commit 79f04fdc92bb3f88ecf79496e53ed7784ffb9c2d Author: lib Date: Thu Jun 22 01:01:45 2023 -0500 Initial commit diff --git a/CMake/CMakeLists.txt b/CMake/CMakeLists.txt new file mode 100644 index 0000000..69ef8c9 --- /dev/null +++ b/CMake/CMakeLists.txt @@ -0,0 +1,62 @@ +PROJECT(VTK_LOADED_COMMANDS) + +IF(NOT VTK_BUILD_FROM_TRY_COMPILE) + STRING(REGEX REPLACE "[\\/][cC][mM][Aa][Kk][Ee]$" "" REAL_SOURCE "${VTK_LOADED_COMMANDS_SOURCE_DIR}") + MESSAGE(SEND_ERROR "\nThis directory:\n${VTK_LOADED_COMMANDS_SOURCE_DIR}\nshould not be used as a source directory for building VTK. \nYou should exit cmake and remove the file:\n${VTK_LOADED_COMMANDS_BINARY_DIR}/CMakeCache.txt\nThen re-run cmake with the source directory set to:\n${REAL_SOURCE}") +ENDIF(NOT VTK_BUILD_FROM_TRY_COMPILE) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") +INCLUDE_DIRECTORIES(${CMAKE_ROOT}/include ${CMAKE_ROOT}/Source) +ADD_LIBRARY(cmVTK_WRAP_TCL2 MODULE cmVTKWrapTcl2Command.c) +ADD_LIBRARY(cmVTK_WRAP_PYTHON2 MODULE cmVTKWrapPython2Command.c) +ADD_LIBRARY(cmVTK_WRAP_JAVA2 MODULE cmVTKWrapJava2Command.c) +ADD_LIBRARY(cmVTK_GENERATE_JAVA_DEPENDENCIES MODULE cmVTKGenerateJavaDependencies.c) + +# Make sure we build with flags matching the CMake executable. +IF(CMAKE_SYSTEM MATCHES "IRIX64") + # A table of ABI flags. + IF(CMAKE_COMPILER_IS_GNUCXX) + SET(CMAKE_ABI_32 "-mabi=32") + SET(CMAKE_ABI_n32 "-mabi=n32") + SET(CMAKE_ABI_64 "-mabi=64") + ELSE(CMAKE_COMPILER_IS_GNUCXX) + SET(CMAKE_ABI_32 "-o32") + SET(CMAKE_ABI_n32 "-n32") + SET(CMAKE_ABI_64 "-64") + ENDIF(CMAKE_COMPILER_IS_GNUCXX) + + # Check how cmake was built. + IF(CMAKE_FILE_SELF MATCHES "^CMAKE_FILE_SELF$") + EXEC_PROGRAM(file ARGS ${CMAKE_COMMAND} OUTPUT_VARIABLE CMAKE_FILE_SELF) + SET(CMAKE_FILE_SELF "${CMAKE_FILE_SELF}" CACHE INTERNAL + "Output of file command on ${CMAKE_COMMAND}.") + ENDIF(CMAKE_FILE_SELF MATCHES "^CMAKE_FILE_SELF$") + + # Remove any existing flag. + SET(CMAKE_ABI_VARS + CMAKE_C_FLAGS + CMAKE_CXX_FLAGS + CMAKE_EXE_LINKER_FLAGS + CMAKE_SHARED_LINKER_FLAGS + CMAKE_MODULE_LINKER_FLAGS + ) + FOREACH(var ${CMAKE_ABI_VARS}) + FOREACH(regex "-([on]32|64)" "-mabi=[a-z0-9]*") + STRING(REGEX REPLACE "${regex}" "" ${var} "${${var}}") + ENDFOREACH(regex) + ENDFOREACH(var) + + # Add the proper flag. + IF(CMAKE_FILE_SELF MATCHES " 32-bit ") + SET(CMAKE_ABI_FLAG "${CMAKE_ABI_32}") + ENDIF(CMAKE_FILE_SELF MATCHES " 32-bit ") + IF(CMAKE_FILE_SELF MATCHES " N32 ") + SET(CMAKE_ABI_FLAG "${CMAKE_ABI_n32}") + ENDIF(CMAKE_FILE_SELF MATCHES " N32 ") + IF(CMAKE_FILE_SELF MATCHES " 64-bit ") + SET(CMAKE_ABI_FLAG "${CMAKE_ABI_64}") + ENDIF(CMAKE_FILE_SELF MATCHES " 64-bit ") + + FOREACH(var ${CMAKE_ABI_VARS}) + SET(${var} "${CMAKE_ABI_FLAG} ${${var}}") + ENDFOREACH(var) +ENDIF(CMAKE_SYSTEM MATCHES "IRIX64") diff --git a/CMake/CTestCustom.ctest.in b/CMake/CTestCustom.ctest.in new file mode 100644 index 0000000..32d572e --- /dev/null +++ b/CMake/CTestCustom.ctest.in @@ -0,0 +1,41 @@ +SET(CTEST_CUSTOM_WARNING_MATCH + ${CTEST_CUSTOM_WARNING_MATCH} + "{standard input}:[0-9][0-9]*: Warning: " + ) + +# Removing this because it somehow matches normal build output lines +# on several platforms. Perhaps there is a bug in the custom match +# support. +# +# SET(CTEST_CUSTOM_ERROR_MATCH +# ${CTEST_CUSTOM_ERROR_MATCH} +# "\\", line [0-9]+, in " +# ) + +IF("@CMAKE_SYSTEM@" MATCHES "OSF") + SET(CTEST_CUSTOM_WARNING_EXCEPTION + ${CTEST_CUSTOM_WARNING_EXCEPTION} + "vtkKWApplication" + "vtkKWObject" + ) +ENDIF("@CMAKE_SYSTEM@" MATCHES "OSF") + +SET(CTEST_CUSTOM_WARNING_EXCEPTION + ${CTEST_CUSTOM_WARNING_EXCEPTION} + "Utilities/vtktiff/" + "xtree.[0-9]+. : warning C4702: unreachable code" + "warning LNK4221" + "variable .var_args[2]*. is used before its value is set" + "jobserver unavailable" + "warning: \\(Long double usage is reported only once for each file" + "warning: To disable this warning use" + "ranlib: file: .+ has no symbols" + "could not be inlined" + "ld: warning prebinding disabled because \\((__TEXT|__DATA|__LINKEDIT) segment \\(address = 0x[a-f0-9]+ size = 0x[a-f0-9]+\\) of (.*) overlaps with (__LINKEDIT|__TEXT|__DATA) segment \\(address = 0x[a-f0-9]+ size = 0x[a-f0-9]+\\) of (.*)" + "ld: warning prebinding disabled because dependent library: (.*).dylib is not prebound" + ) + +SET(CTEST_CUSTOM_COVERAGE_EXCLUDE + ${CTEST_CUSTOM_COVERAGE_EXCLUDE} + "vtk.*TCLInit.cxx" + "vtk[^\\.]+Tcl.cxx") diff --git a/CMake/FindEXPAT.cmake b/CMake/FindEXPAT.cmake new file mode 100644 index 0000000..fa6695d --- /dev/null +++ b/CMake/FindEXPAT.cmake @@ -0,0 +1,27 @@ +# +# Find the native EXPAT includes and library +# +# This module defines +# EXPAT_INCLUDE_DIR, where to find expat.h, etc. +# EXPAT_LIBRARIES, the libraries to link against to use EXPAT. +# EXPAT_FOUND, If false, do not try to use EXPAT. + +# also defined, but not for general use are +# EXPAT_LIBRARY, where to find the EXPAT library. + +FIND_PATH(EXPAT_INCLUDE_DIR expat.h + /usr/local/include + /usr/include +) + +FIND_LIBRARY(EXPAT_LIBRARY expat + /usr/lib + /usr/local/lib +) + +IF(EXPAT_INCLUDE_DIR) + IF(EXPAT_LIBRARY) + SET( EXPAT_FOUND "YES" ) + SET( EXPAT_LIBRARIES ${EXPAT_LIBRARY} ) + ENDIF(EXPAT_LIBRARY) +ENDIF(EXPAT_INCLUDE_DIR) diff --git a/CMake/FindFREETYPE.cmake b/CMake/FindFREETYPE.cmake new file mode 100644 index 0000000..c660103 --- /dev/null +++ b/CMake/FindFREETYPE.cmake @@ -0,0 +1,37 @@ +# +# Find the native FREETYPE includes and library +# + +# This module defines +# FREETYPE_INCLUDE_DIR, where to find ft2build.h, ftheader.h, ... +# FREETYPE_LIBRARIES, the libraries to link against to use FREETYPE. +# FREETYPE_FOUND, If false, do not try to use FREETYPE. + +# also defined, but not for general use are +# FREETYPE_LIBRARY, where to find the FREETYPE library. + +FIND_PATH(FREETYPE_INCLUDE_DIR_FT2BUILD ft2build.h + /usr/include/ + /usr/local/include/ +) + +FIND_PATH(FREETYPE_INCLUDE_DIR_FTHEADER freetype/config/ftheader.h + /usr/include/freetype2 + /usr/local/include/freetype2 +) + +FIND_LIBRARY(FREETYPE_LIBRARY freetype + /usr/lib + /usr/local/lib +) + +IF (FREETYPE_LIBRARY) + IF (FREETYPE_INCLUDE_DIR_FTHEADER AND FREETYPE_INCLUDE_DIR_FT2BUILD) + SET( FREETYPE_FOUND "YES" ) + SET( FREETYPE_INCLUDE_DIR + ${FREETYPE_INCLUDE_DIR_FT2BUILD} + ${FREETYPE_INCLUDE_DIR_FTHEADER} ) + SET( FREETYPE_LIBRARIES ${FREETYPE_LIBRARY} ) + ENDIF (FREETYPE_INCLUDE_DIR_FTHEADER AND FREETYPE_INCLUDE_DIR_FT2BUILD) +ENDIF (FREETYPE_LIBRARY) + diff --git a/CMake/FindMPEG2.cmake b/CMake/FindMPEG2.cmake new file mode 100644 index 0000000..71c7e23 --- /dev/null +++ b/CMake/FindMPEG2.cmake @@ -0,0 +1,38 @@ +# +# Find the MPEG2 includes and library +# +# This module (forces the user to) provide: +# vtkMPEG2Encode_INCLUDE_PATH, for use with INCLUDE_DIRECTORIES commands +# vtkMPEG2Encode_LIBRARIES, for use with TARGET_LINK_LIBRARIES commands +# +# If VTK_USE_MPEG2_ENCODER is ON, it is an error to end up with empty values +# for vtkMPEG2Encode_INCLUDE_PATH or vtkMPEG2Encode_LIBRARIES. +# The only way to fix this error, if it occurs, is to provide non-empty +# values or to turn OFF VTK_USE_MPEG2_ENCODER. +# +# Cache NOTFOUND initial values. The user will have to provide them unless +# they were provided in the initial cache. + + +# vtkMPEG2Encode_INCLUDE_PATH should be "/path/to/source;/path/to/binary" +# where source contains "mpeg2enc.h" and binary contains "mpeg2encDllConfig.h" +# +SET(vtkMPEG2Encode_INCLUDE_PATH "vtkMPEG2Encode_INCLUDE_PATH-NOTFOUND" CACHE STRING "Semi-colon delimited list of paths to vtkmpeg2encode header files") + + +# vtkMPEG2Encode_LIBRARIES should be "/path/to/binary/vtkMPEG2Encode.lib" +# +SET(vtkMPEG2Encode_LIBRARIES "vtkMPEG2Encode_LIBRARIES-NOTFOUND" CACHE STRING "Semi-colon delimited list of vtkMPEG2Encode library full path names") + + +# Error if values are empty: +# +IF(VTK_USE_MPEG2_ENCODER) + IF(NOT vtkMPEG2Encode_INCLUDE_PATH) + MESSAGE(SEND_ERROR "Could not determine value for vtkMPEG2Encode_INCLUDE_PATH. Provide value or turn off VTK_USE_MPEG2_ENCODER. Value should be a semi-colon delimited list of paths to vtkmpeg2encode header files.") + ENDIF(NOT vtkMPEG2Encode_INCLUDE_PATH) + + IF(NOT vtkMPEG2Encode_LIBRARIES) + MESSAGE(SEND_ERROR "Could not determine value for vtkMPEG2Encode_LIBRARIES. Provide value or turn off VTK_USE_MPEG2_ENCODER. Value should be a semi-colon delimited list of vtkMPEG2Encode library full path names.") + ENDIF(NOT vtkMPEG2Encode_LIBRARIES) +ENDIF(VTK_USE_MPEG2_ENCODER) diff --git a/CMake/FindMangledMesa.cmake b/CMake/FindMangledMesa.cmake new file mode 100644 index 0000000..df67c2c --- /dev/null +++ b/CMake/FindMangledMesa.cmake @@ -0,0 +1,23 @@ +# Try to find mangled Mesa libraries and include dir. +# Once done this will define +# +# MANGLED_MESA_INCLUDE_DIR +# MANGLED_MESA_LIBRARY +# MANGLED_OSMESA_INCLUDE_DIR +# MANGLED_OSMESA_LIBRARY + +IF (NOT MANGLED_MESA_INCLUDE_DIR) + FIND_PATH(MANGLED_MESA_INCLUDE_DIR GL/gl_mangle.h ) +ENDIF (NOT MANGLED_MESA_INCLUDE_DIR) + +IF (NOT MANGLED_MESA_LIBRARY) + FIND_LIBRARY(MANGLED_MESA_LIBRARY MesaGL) +ENDIF (NOT MANGLED_MESA_LIBRARY) + +IF (NOT MANGLED_OSMESA_INCLUDE_DIR) + FIND_PATH(MANGLED_OSMESA_INCLUDE_DIR GL/osmesa.h) +ENDIF (NOT MANGLED_OSMESA_INCLUDE_DIR) + +IF (NOT MANGLED_OSMESA_LIBRARY) + FIND_LIBRARY(MANGLED_OSMESA_LIBRARY OSMesa) +ENDIF (NOT MANGLED_OSMESA_LIBRARY) diff --git a/CMake/FindOSMesa.cmake b/CMake/FindOSMesa.cmake new file mode 100644 index 0000000..edb8fdd --- /dev/null +++ b/CMake/FindOSMesa.cmake @@ -0,0 +1,29 @@ +# Try to find Mesa off-screen library and include dir. +# Once done this will define +# +# OSMESA_INCLUDE_DIR - where the GL/osmesa.h can be found +# OSMESA_LIBRARY - Link this to use OSMesa + + +IF (NOT OSMESA_INCLUDE_DIR) + FIND_PATH(OSMESA_INCLUDE_DIR GL/osmesa.h + /usr/include + /usr/local/include + /usr/openwin/share/include + /opt/graphics/OpenGL/include + /usr/X11R6/include + ) +ENDIF (NOT OSMESA_INCLUDE_DIR) + +# This may be left blank if OSMesa symbols are included +# in the main Mesa library +IF (NOT OSMESA_LIBRARY) + FIND_LIBRARY(OSMESA_LIBRARY OSMesa + /usr/lib + /usr/local/lib + /opt/graphics/OpenGL/lib + /usr/openwin/lib + /usr/X11R6/lib + ) +ENDIF (NOT OSMESA_LIBRARY) + diff --git a/CMake/FindVLI.cmake b/CMake/FindVLI.cmake new file mode 100644 index 0000000..25f5a03 --- /dev/null +++ b/CMake/FindVLI.cmake @@ -0,0 +1,53 @@ +# Try to find VLI libraries for VolumePro. +# Once done this will define +# +# VLI_LIBRARY_FOR_VG500 +# VLI_LIBRARY_FOR_VP1000 +# VLI_INCLUDE_PATH_FOR_VG500 +# VLI_INCLUDE_PATH_FOR_VP1000 + +FIND_LIBRARY(VLI_LIBRARY_FOR_VG500 + NAMES vli + PATHS + /usr/lib + /usr/local/lib + /opt/vli/lib + "C:/Program Files/VolumePro/lib" + ) + +FIND_LIBRARY(VLI_LIBRARY_FOR_VP1000 + NAMES vli3 + PATHS + /usr/lib + /usr/local/lib + /opt/vli/lib + "C:/Program Files/VolumePro1000/lib" + ) + +IF (VLI_LIBRARY_FOR_VG500) + IF (WIN32) + FIND_PATH(VLI_INCLUDE_PATH_FOR_VG500 VolumePro/inc/vli.h + "C:/Program Files" + ) + ELSE (WIN32) + FIND_PATH(VLI_INCLUDE_PATH_FOR_VG500 vli/include/vli.h + /usr + /usr/local + /opt + ) + ENDIF (WIN32) +ENDIF (VLI_LIBRARY_FOR_VG500) + +IF (VLI_LIBRARY_FOR_VP1000) + IF (WIN32) + FIND_PATH(VLI_INCLUDE_PATH_FOR_VP1000 VolumePro1000/inc/vli.h + "C:/Program Files" + ) + ELSE (WIN32) + FIND_PATH(VLI_INCLUDE_PATH_FOR_VP1000 vli3/include/vli.h + /usr + /usr/local + /opt/vli/include + ) + ENDIF (WIN32) +ENDIF (VLI_LIBRARY_FOR_VP1000) diff --git a/CMake/InstallDisabled.cmake b/CMake/InstallDisabled.cmake new file mode 100644 index 0000000..7a13561 --- /dev/null +++ b/CMake/InstallDisabled.cmake @@ -0,0 +1,3 @@ +MESSAGE(FATAL_ERROR + "ERROR: VTK installation is disabled because VTK_USE_RPATH is ON. It is not safe to install binaries that have a runtime path pointing to the build tree. In order to install safely you need to delete the libraries from your build tree, set VTK_USE_RPATH to OFF, and rebuild. See comments in VTK/CMake/vtkSelectSharedLibraries.cmake for more information." +) diff --git a/CMake/KitCommonBlock.cmake b/CMake/KitCommonBlock.cmake new file mode 100644 index 0000000..abbec5e --- /dev/null +++ b/CMake/KitCommonBlock.cmake @@ -0,0 +1,116 @@ +# Setup vtkInstantiator registration for this library's classes. +VTK_MAKE_INSTANTIATOR3(vtk${KIT}Instantiator KitInstantiator_SRCS + "${Kit_SRCS}" + VTK_${UKIT}_EXPORT + ${VTK_BINARY_DIR} "") + +ADD_LIBRARY(vtk${KIT} ${Kit_SRCS} ${Kit_EXTRA_SRCS} ${KitInstantiator_SRCS}) +SET(KIT_LIBRARY_TARGETS ${KIT_LIBRARY_TARGETS} vtk${KIT}) + +# Allow the user to customize their build with some local options +# +SET(LOCALUSERMACRODEFINED 0) +INCLUDE (${VTK_BINARY_DIR}/${KIT}/LocalUserOptions.cmake OPTIONAL) +INCLUDE (${VTK_SOURCE_DIR}/${KIT}/LocalUserOptions.cmake OPTIONAL) + +# if we are wrapping into Tcl then add the library and extra +# source files +# +IF (VTK_WRAP_TCL) + VTK_WRAP_TCL3(vtk${KIT}TCL KitTCL_SRCS + "${Kit_SRCS}" + "${Kit_TCL_EXTRA_CMDS}") + ADD_LIBRARY(vtk${KIT}TCL ${KitTCL_SRCS} ${Kit_TCL_EXTRA_SRCS}) + SET(KIT_LIBRARY_TARGETS ${KIT_LIBRARY_TARGETS} vtk${KIT}TCL) + TARGET_LINK_LIBRARIES (vtk${KIT}TCL vtk${KIT} ${KIT_TCL_LIBS}) + IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtk${KIT}TCL) + ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) + IF(KIT_TCL_DEPS) + ADD_DEPENDENCIES(vtk${KIT}TCL ${KIT_TCL_DEPS}) + ENDIF(KIT_TCL_DEPS) +ENDIF (VTK_WRAP_TCL) + +# if we are wrapping into Python then add the library and extra +# source files +# +IF (VTK_WRAP_PYTHON) + # Create custom commands to generate the python wrappers for this kit. + VTK_WRAP_PYTHON3(vtk${KIT}Python KitPython_SRCS "${Kit_SRCS}") + + # Create a shared library containing the python wrappers. Executables + # can link to this but it is not directly loaded dynamically as a + # module. + ADD_LIBRARY(vtk${KIT}PythonD ${KitPython_SRCS} ${Kit_PYTHON_EXTRA_SRCS}) + TARGET_LINK_LIBRARIES(vtk${KIT}PythonD vtk${KIT} ${KIT_PYTHON_LIBS}) + IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtk${KIT}PythonD) + ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) + SET(KIT_LIBRARY_TARGETS ${KIT_LIBRARY_TARGETS} vtk${KIT}PythonD) + + # On some UNIX platforms the python library is static and therefore + # should not be linked into the shared library. Instead the symbols + # are exported from the python executable so that they can be used by + # shared libraries that are linked or loaded. On Windows and OSX we + # want to link to the python libray to resolve its symbols + # immediately. + IF(WIN32 OR APPLE) + TARGET_LINK_LIBRARIES (vtk${KIT}PythonD ${VTK_PYTHON_LIBRARIES}) + ENDIF(WIN32 OR APPLE) + + # Add dependencies that may have been generated by VTK_WRAP_PYTHON3 to + # the python wrapper library. This is needed for the + # pre-custom-command hack in Visual Studio 6. + IF(KIT_PYTHON_DEPS) + ADD_DEPENDENCIES(vtk${KIT}PythonD ${KIT_PYTHON_DEPS}) + ENDIF(KIT_PYTHON_DEPS) + + # Create a python module that can be loaded dynamically. It links to + # the shared library containing the wrappers for this kit. + ADD_LIBRARY(vtk${KIT}Python MODULE vtk${KIT}PythonInit.cxx) + TARGET_LINK_LIBRARIES(vtk${KIT}Python vtk${KIT}PythonD) +ENDIF (VTK_WRAP_PYTHON) + +# if we are wrapping into Java then add the library and extra +# source files +# +IF (VTK_WRAP_JAVA) + VTK_WRAP_JAVA3(vtk${KIT}Java KitJava_SRCS "${Kit_SRCS}") + ADD_LIBRARY(vtk${KIT}Java SHARED ${KitJava_SRCS} ${Kit_JAVA_EXTRA_SRCS}) + SET(KIT_LIBRARY_TARGETS ${KIT_LIBRARY_TARGETS} vtk${KIT}Java) + TARGET_LINK_LIBRARIES(vtk${KIT}Java vtk${KIT} ${KIT_JAVA_LIBS}) + IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtk${KIT}Java) + ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) + IF(KIT_JAVA_DEPS) + ADD_DEPENDENCIES(vtk${KIT}Java ${KIT_JAVA_DEPS}) + ENDIF(KIT_JAVA_DEPS) +ENDIF (VTK_WRAP_JAVA) + +TARGET_LINK_LIBRARIES(vtk${KIT} ${KIT_LIBS}) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtk${KIT}) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h ${Kit_SRCS}) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +VTK_EXPORT_KIT("${KIT}" "${UKIT}" "${Kit_SRCS}") + +# If the user defined a custom macro, execute it now and pass in all the srcs +# +IF(LOCALUSERMACRODEFINED) + LocalUserOptionsMacro( "${Kit_SRCS}" "${Kit_EXTRA_SRCS}" + "${KitTCL_SRCS}" "${Kit_TCL_EXTRA_SRCS}" + "${KitJava_SRCS}" "${Kit_JAVA_EXTRA_SRCS}" + "${KitPython_SRCS}" "${Kit_PYTHON_EXTRA_SRCS}") +ENDIF(LOCALUSERMACRODEFINED) + + +# Apply user-defined properties to the library targets. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(${KIT_LIBRARY_TARGETS} PROPERTIES + ${VTK_LIBRARY_PROPERTIES} + ) +ENDIF(VTK_LIBRARY_PROPERTIES) diff --git a/CMake/TestNO_ICC_IDYNAMIC_NEEDED.cmake b/CMake/TestNO_ICC_IDYNAMIC_NEEDED.cmake new file mode 100644 index 0000000..3b4ce4f --- /dev/null +++ b/CMake/TestNO_ICC_IDYNAMIC_NEEDED.cmake @@ -0,0 +1,31 @@ +# +# Check if the system is big endian or little endian +# +# VARIABLE - variable to store the result to +# + +MACRO(TESTNO_ICC_IDYNAMIC_NEEDED VARIABLE LOCAL_TEST_DIR) + IF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$") + TRY_RUN(${VARIABLE} HAVE_${VARIABLE} + ${CMAKE_BINARY_DIR} + ${LOCAL_TEST_DIR}/TestNO_ICC_IDYNAMIC_NEEDED.cxx + OUTPUT_VARIABLE OUTPUT) + MESSAGE(STATUS "Check if using the Intel icc compiler, and if -i_dynamic is needed... COMPILE_RESULT...${HAVE_${VARIABLE}} RUN_RESULT...${VARIABLE}\n") + IF(HAVE_${VARIABLE}) #Test compiled, either working intel w/o -i_dynamic, or another compiler + IF(${VARIABLE}) #Intel icc compiler, -i_dynamic not needed + FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "-i_dynamic not needed, (Not Intel icc, or this version of Intel icc does not conflict with OS glibc.") + MESSAGE(STATUS "-i_dynamic not needed, (Not Intel icc, or this version of Intel icc does not conflict with OS glibc.") + ELSE(${VARIABLE}) #The compiler is not Intel icc + FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "The compiler ERROR--This should never happen") + MESSAGE(STATUS "The compiler ERROR--This should never happen") + ENDIF(${VARIABLE}) + ELSE(HAVE_${VARIABLE}) #Test did not compile, either badly broken compiler, or intel -i_dynamic needed + FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "\tThe -i_dynamic compiler flag is needed for the Intel icc compiler on this platform.\n") + MESSAGE("The -i_dynamic compiler flag is needed for the Intel icc compiler on this platform.") + ENDIF(HAVE_${VARIABLE}) + FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log "TestNO_ICC_IDYNAMIC_NEEDED produced following output:\n${OUTPUT}\n\n") + ENDIF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$") +ENDMACRO(TESTNO_ICC_IDYNAMIC_NEEDED) diff --git a/CMake/TestNO_ICC_IDYNAMIC_NEEDED.cxx b/CMake/TestNO_ICC_IDYNAMIC_NEEDED.cxx new file mode 100644 index 0000000..ddfa6d2 --- /dev/null +++ b/CMake/TestNO_ICC_IDYNAMIC_NEEDED.cxx @@ -0,0 +1,9 @@ +#ifdef __INTEL_COMPILER + //If -i_dynamic is required (i.e. icc v7.1 on Redhat 9 or similar glibc version), + //this simple program will fail to compile. + #include + int main(int argc, char * argv[]) { return 1; } +#else //__INTEL_COMPILER + // If not the INTEL compiler, just fall though to simplest program + int main(int argc, char * argv[]) { return 1; } +#endif //__INTEL_COMPILER diff --git a/CMake/VTKValgrindSuppressions.supp b/CMake/VTKValgrindSuppressions.supp new file mode 100644 index 0000000..f264006 --- /dev/null +++ b/CMake/VTKValgrindSuppressions.supp @@ -0,0 +1,949 @@ +{ + + Memcheck:Addr1 + fun:strcmp + fun:_dl_map_object_internal +} +{ + + Memcheck:Cond + fun:_dl_relocate_object_internal + obj:/lib/libc-2.3.3.so + fun:_dl_catch_error_internal +} +{ + + Memcheck:Cond + fun:_dl_relocate_object_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open +} +{ + + Memcheck:Cond + fun:__stpcpy + obj:/lib/libc-2.3.3.so + fun:__sysconf +} +{ + + core:PThread + fun:pthread_error + fun:pthread_attr_setscope + fun:_ZN16vtkMultiThreader19SingleMethodExecuteEv +} +{ + + Memcheck:Cond + fun:__stpcpy + obj:/lib/libc-2.3.3.so + fun:setlocale + fun:TclpSetInitialEncodings +} +{ + + Memcheck:Cond + fun:__stpcpy + fun:setlocale + fun:TclpSetInitialEncodings +} +{ + + Memcheck:Cond + fun:__stpcpy + obj:/lib/libc-2.3.3.so + fun:__pthread_once +} +{ + + Memcheck:Cond + fun:__stpcpy + obj:/lib/libc-2.3.3.so + fun:__nss_hosts_lookup + fun:gethostbyname_r + fun:gethostbyname + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_X11TransConnect + fun:_X11TransConnectDisplay + fun:XOpenDisplay + fun:TkpOpenDisplay +} +{ + + Memcheck:Leak + fun:malloc + fun:_XlcDefaultMapModifiers + fun:XSetLocaleModifiers + obj:/usr/lib/libtk8.4.so +} +{ + + Memcheck:Leak + fun:malloc + fun:_XrmDefaultInitParseInfo + fun:_XrmInitParseInfo + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:XrmGetFileDatabase + fun:_XInitKeysymDB + fun:XStringToKeysym + fun:TkStringToKeysym +} +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/X11/locale/lib/common/ximcp.so.2 + fun:_XimOpenIM + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:XOpenIM + obj:/usr/lib/libtk8.4.so +} +{ + + Memcheck:Leak + fun:malloc + fun:_XlcResolveLocaleName + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Leak + fun:malloc + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Leak + fun:realloc + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Leak + fun:malloc + fun:_XlcCreateLocaleDataBase + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Leak + fun:malloc + fun:XauFileName + fun:XauGetBestAuthByAddr + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_X11TransConnectDisplay + fun:XOpenDisplay + fun:TkpOpenDisplay +} +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XrmInternalStringToQuark + fun:XrmStringToQuark + fun:_XlcGetCharSet + fun:_XlcAddCT + fun:_XlcInitCTInfo + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC +} +{ + + Memcheck:Leak + fun:malloc + fun:_XlcAddCT + fun:_XlcInitCTInfo + obj:/usr/X11R6/lib/libX11.so.6.2 + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Leak + fun:malloc + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers + obj:/usr/lib/libtk8.4.so +} +{ + + Memcheck:Leak + fun:malloc + fun:__strdup + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Addr4 + obj:/lib/libc-2.3.3.so + obj:/lib/libc-2.3.3.so + obj:/lib/libc-2.3.3.so + obj:/lib/libc-2.3.3.so + obj:/lib/libc-2.3.3.so + fun:__libc_freeres + fun:vgPlain___libc_freeres_wrapper + fun:exit + fun:Tcl_Exit +} +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:calloc + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:malloc + fun:_dl_map_object_deps_internal + obj:/lib/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcCreateLC + fun:_XlcDefaultLoader + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:malloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object_internal + obj:/lib/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:malloc + fun:_dl_map_object_internal + obj:/lib/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:calloc + fun:_dl_check_map_versions_internal + obj:/lib/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} + +{ + + Memcheck:Leak + fun:calloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object_internal + obj:/lib/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers +} +{ + + Memcheck:Overlap + fun:memcpy + obj:/usr/X11R6/lib/libXt.so.6.0 + fun:_XtGetResources + obj:/usr/X11R6/lib/libXt.so.6.0 + fun:_XtAppCreateShell + fun:XtVaAppCreateShell +} +{ + + Memcheck:Cond + fun:strlen + obj:/lib/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XrmInitParseInfo + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:XrmGetStringDatabase + obj:/usr/X11R6/lib/libXt.so.6.0 + obj:/usr/X11R6/lib/libXt.so.6.0 + fun:_XtDisplayInitialize + fun:XtDisplayInitialize + fun:_ZN29vtkXRenderWindowTclInteractor10InitializeEv +} + +{ + + Memcheck:Leak + fun:calloc + fun:XShmCreateImage + fun:alloc_shm_back_buffer + fun:xmesa_alloc_back_buffer + fun:xmesa_resize_buffers + fun:_mesa_ResizeBuffersMESA + fun:_mesa_set_viewport + fun:_mesa_Viewport + fun:glViewport +} + +{ + + Memcheck:Leak + fun:calloc + fun:XCreateImage + fun:initialize_visual_and_buffer + fun:XMesaCreateWindowBuffer2 + fun:Fake_glXMakeContextCurrent + fun:Fake_glXMakeCurrent + fun:glXMakeCurrent +} + +{ + + Memcheck:Leak + fun:malloc + fun:_dl_map_object_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers + fun:OpenIM + fun:TkpOpenDisplay + fun:GetScreen + fun:CreateTopLevelWindow + fun:TkCreateMainWindow + fun:CreateFrame + fun:TkCreateFrame + fun:Initialize + fun:Tk_Init +} + +{ + + Memcheck:Leak + fun:malloc + fun:_dl_map_object_deps_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XNoticeCreateBitmap + fun:XCreatePixmap + fun:XCreateBitmapFromData + fun:GetBitmap + fun:Tk_GetBitmap + fun:TkButtonWorldChanged + fun:ConfigureButton + fun:ButtonCreate + fun:Tk_ButtonObjCmd + fun:TclEvalObjvInternal + fun:TclExecuteByteCode + fun:TclCompEvalObj + fun:TclObjInterpProc + fun:TclEvalObjvInternal + fun:TclExecuteByteCode + fun:TclCompEvalObj + fun:Tcl_EvalObjEx + fun:NamespaceEvalCmd + fun:Tcl_NamespaceObjCmd + fun:TclEvalObjvInternal + fun:Tcl_EvalEx + fun:Tcl_Eval + fun:Tcl_GlobalEval +} + +{ + + Memcheck:Leak + fun:malloc + fun:_dl_map_object_deps_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers + fun:OpenIM + fun:TkpOpenDisplay + fun:GetScreen + fun:CreateTopLevelWindow + fun:TkCreateMainWindow + fun:CreateFrame + fun:TkCreateFrame + fun:Initialize + fun:Tk_Init +} + +{ + + Memcheck:Leak + fun:malloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers + fun:OpenIM + fun:TkpOpenDisplay + fun:GetScreen + fun:CreateTopLevelWindow + fun:TkCreateMainWindow + fun:CreateFrame + fun:TkCreateFrame + fun:Initialize + fun:Tk_Init +} + +{ + + Memcheck:Leak + fun:malloc + fun:strdup + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers + fun:OpenIM + fun:TkpOpenDisplay + fun:GetScreen + fun:CreateTopLevelWindow + fun:TkCreateMainWindow + fun:CreateFrame + fun:TkCreateFrame + fun:Initialize + fun:Tk_Init +} + +{ + + Memcheck:Leak + fun:calloc + fun:_dl_check_map_versions_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers + fun:OpenIM + fun:TkpOpenDisplay + fun:GetScreen + fun:CreateTopLevelWindow + fun:TkCreateMainWindow + fun:CreateFrame + fun:TkCreateFrame + fun:Initialize + fun:Tk_Init +} + +{ + + Memcheck:Leak + fun:malloc + fun:XCreateGC + fun:initialize_visual_and_buffer + fun:XMesaCreateWindowBuffer2 + fun:Fake_glXMakeContextCurrent + fun:Fake_glXMakeCurrent + fun:glXMakeCurrent +} + +{ + + Memcheck:Leak + fun:malloc + fun:XGetVisualInfo + fun:get_visual + fun:choose_x_visual + fun:choose_visual + fun:Fake_glXChooseVisual + fun:glXChooseVisual +} + +{ + + Memcheck:Leak + fun:malloc + fun:_mesa_malloc + fun:_mesa_new_buffer_object + fun:_mesa_init_buffer_objects + fun:init_attrib_groups + fun:_mesa_initialize_context + fun:XMesaCreateContext + fun:Fake_glXCreateContext + fun:glXCreateContext +} + +{ + + Memcheck:Cond + fun:strchr +} + +{ + + Memcheck:Leak + fun:calloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XlcDynamicLoad + fun:_XOpenLC + fun:_XlcCurrentLC + fun:XSetLocaleModifiers + fun:OpenIM + fun:TkpOpenDisplay + fun:GetScreen + fun:CreateTopLevelWindow + fun:TkCreateMainWindow + fun:CreateFrame + fun:TkCreateFrame + fun:Initialize + fun:Tk_Init +} + +{ + + Memcheck:Leak + fun:calloc + fun:_mesa_calloc + fun:_mesa_alloc_program + fun:alloc_shared_state + fun:_mesa_initialize_context + fun:XMesaCreateContext + fun:Fake_glXCreateContext + fun:glXCreateContext +} + +{ + + Memcheck:Leak + fun:malloc + fun:_mesa_malloc + fun:alloc_vertex_store + fun:_tnl_NewList + fun:_mesa_NewList + fun:glNewList +} + +{ + + Memcheck:Leak + fun:malloc + fun:_mesa_malloc + fun:XMesaCreateVisual + fun:save_glx_visual + fun:choose_visual + fun:Fake_glXChooseVisual + fun:glXChooseVisual +} + +{ + + Memcheck:Leak + fun:calloc + fun:_mesa_calloc + fun:XMesaCreateVisual + fun:save_glx_visual + fun:choose_visual + fun:Fake_glXChooseVisual + fun:glXChooseVisual +} + +{ + + Memcheck:Leak + fun:calloc + fun:_mesa_calloc + fun:_mesa_NewHashTable + fun:_mesa_init_occlude + fun:init_attrib_groups + fun:_mesa_initialize_context + fun:XMesaCreateContext + fun:Fake_glXCreateContext + fun:glXCreateContext +} + +{ + + Memcheck:Leak + fun:calloc + fun:_mesa_calloc + fun:Fake_glXCreateContext + fun:glXCreateContext +} + +{ + + Memcheck:Leak + fun:malloc + fun:_mesa_malloc + fun:_mesa_strdup + fun:_mesa_init_program + fun:init_attrib_groups + fun:_mesa_initialize_context + fun:XMesaCreateContext + fun:Fake_glXCreateContext + fun:glXCreateContext +} + +{ + + Memcheck:Leak + fun:calloc + fun:_mesa_calloc + fun:_mesa_NewHashTable + fun:_mesa_init_depth + fun:init_attrib_groups + fun:_mesa_initialize_context + fun:XMesaCreateContext + fun:Fake_glXCreateContext + fun:glXCreateContext +} + +{ + + Memcheck:Leak + fun:calloc + fun:_mesa_calloc + fun:_mesa_new_texture_object + fun:alloc_shared_state + fun:_mesa_initialize_context + fun:XMesaCreateContext + fun:Fake_glXCreateContext + fun:glXCreateContext +} + +{ + + Memcheck:Param + write(buf) + fun:write + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_X11TransWrite + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XReply + fun:XSync +} + +{ + + Memcheck:Cond + fun:_playback_copy_to_current + fun:_tnl_playback_vertex_list + fun:execute_list + fun:_mesa_CallList + fun:glCallList +} + +{ + + Memcheck:Addr4 + obj:/lib/tls/libc-2.3.3.so + obj:/lib/tls/libc-2.3.3.so + obj:/lib/tls/libc-2.3.3.so + obj:/lib/tls/libc-2.3.3.so + obj:/lib/tls/libc-2.3.3.so + fun:__libc_freeres +} + +{ + + Memcheck:Leak + fun:malloc + fun:get_dispatch + fun:glXChooseVisual +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libXcursor.so.1.0 + fun:XcursorTryShapeCursor + fun:_XTryShapeCursor + fun:XCreateGlyphCursor + fun:TkGetCursorByName +} + +{ + + Memcheck:Leak + fun:calloc + obj:/lib/libdl-2.3.3.so + fun:dlsym + fun:fcntl + fun:TclpOpenFileChannel +} + +{ + + Memcheck:Leak + fun:malloc + fun:open_path + fun:_dl_map_object_internal + obj:/lib/tls/libc-2.3.3.so + fun:_dl_catch_error_internal + fun:_dl_open + obj:/lib/libdl-2.3.3.so + fun:_dl_catch_error_internal + obj:/lib/libdl-2.3.3.so + fun:dlopen + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:_XNoticeCreateBitmap + fun:XCreatePixmap + fun:XCreateBitmapFromData + obj:/usr/lib/libtk8.4.so +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:XQueryFont + obj:/usr/X11R6/lib/libXcursor.so.1.0 + fun:XcursorTryShapeCursor + fun:_XTryShapeCursor + fun:XCreateGlyphCursor + fun:TkGetCursorByName +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:XQueryFont + obj:/usr/X11R6/lib/libXcursor.so.1.0 + fun:XcursorTryShapeCursor + fun:_XTryShapeCursor + fun:XCreateGlyphCursor + fun:TkGetCursorByName +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/X11R6/lib/libX11.so.6.2 + fun:XQueryFont + obj:/usr/X11R6/lib/libXcursor.so.1.0 + fun:XcursorTryShapeCursor + fun:_XTryShapeCursor + fun:XCreateGlyphCursor + fun:TkGetCursorByName +} + +{ + + Memcheck:Leak + fun:malloc + fun:_mesa_malloc + fun:alloc_vertex_store + fun:_save_compile_vertex_list + fun:_save_wrap_buffers + fun:_save_wrap_filled_vertex + fun:save_attrib_0_3 + fun:_save_Vertex3fv + fun:glVertex3fv +} diff --git a/CMake/cmVTKGenerateJavaDependencies.c b/CMake/cmVTKGenerateJavaDependencies.c new file mode 100644 index 0000000..37d6379 --- /dev/null +++ b/CMake/cmVTKGenerateJavaDependencies.c @@ -0,0 +1,195 @@ +/* this is a CMake loadable command to wrap vtk objects into Java */ + +#include "cmCPluginAPI.h" +#include +#include +#include + +#define SINGLE_FILE_BUILD + +/* do almost everything in the initial pass */ +static int InitialPass(void *inf, void *mf, int argc, char *argv[]) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + int i; + int newArgc; + int msize; + int estimated; + char **newArgv; + int numClasses = 0; + char **classes = 0; + char **dependencies = 0; + int numDep = 0; + int numWrapped = 0; + const char *cdir = info->CAPI->GetCurrentDirectory(mf); + const char *def = 0; + char *newName; + char *target = 0; + const char *javac = info->CAPI->GetDefinition(mf,"JAVA_COMPILE"); + const char *jar = info->CAPI->GetDefinition(mf,"JAVA_ARCHIVE"); + void *cfile = 0; + char *args[5]; + char *jargs[5]; + int depends = 0; + char **sargs = 0; + int sargsCnt = 0; + char **srcList = 0; + int srcCnt = 0; + char* javaPath = 0; + const char *libpath = info->CAPI->GetDefinition(mf,"LIBRARY_OUTPUT_PATH"); + const char *vtkpath = info->CAPI->GetDefinition(mf,"VTK_BINARY_DIR"); + const char *userjavapath = info->CAPI->GetDefinition(mf,"USER_JAVA_CLASSPATH"); + const char *startTempFile; + const char *endTempFile; + + FILE* outfile = 0; + const char* filename = 0; + + if(argc < 2 ) + { + info->CAPI->SetError(info, "called with incorrect number of arguments"); + return 0; + } + + /* Now check and see if the value has been stored in the cache */ + /* already, if so use that value and don't look for the program */ + if(!info->CAPI->IsOn(mf,"VTK_WRAP_JAVA")) + { + info->CAPI->FreeArguments(newArgc, newArgv); + return 1; + } + + info->CAPI->ExpandSourceListArguments(mf, argc, (const char**)argv, + &newArgc, &newArgv, 2); + + /* keep the library name */ + target = strdup(newArgv[0]); + + if (userjavapath) + { + javaPath = (char *)malloc(strlen(vtkpath) + 20 + strlen(userjavapath)); + sprintf(javaPath, "%s;%s/java", userjavapath, vtkpath); + } + else + { + javaPath = (char *)malloc(strlen(vtkpath) + 20); + sprintf(javaPath, "%s/java", vtkpath); + } + + args[0] = strdup("-classpath"); + args[1] = strdup(javaPath); + + classes = (char**) malloc( newArgc * sizeof(char*)); + numClasses = 0; + + filename = (char*) malloc( strlen(vtkpath) + strlen("/java/vtk/") + strlen(target) + 100 ); + sprintf(filename, "%s/java/vtk/vtk%sDriver.java", vtkpath, target); + outfile = fopen(filename, "w"); + if ( !outfile ) + { + char buffer[1024]; + sprintf(buffer, "cannot generate output file: %s", filename); + info->CAPI->SetError(info, buffer); + return 0; + } + + fprintf(outfile, + "// Do not edit\n" + "// This file is generated by cmVTKGenerateJavaDependencies.c in VTK\n" + "package vtk;\n" + "import vtk.*;\n" + "\n" + "public class vtk%sDriver\n" + "{\n" + " public static void Initialize(String[] args)\n" + " {\n" + " Object dummy;\n", target); + + /* get the classes for this lib */ + for(i = 1; i < newArgc; ++i) + { + const char *srcName = newArgv[i]; + char *className = 0; + char *srcNameWe; + char *srcPath; + + srcNameWe = info->CAPI->GetFilenameWithoutExtension(srcName); + srcPath = info->CAPI->GetFilenamePath(srcName); + + className = (char *)malloc(strlen(srcPath) + strlen(srcNameWe) + 20); + sprintf(className,"%s/%s.class",srcPath,srcNameWe); + fprintf(outfile, + " dummy = new %s();\n", srcNameWe); + + + args[2] = (char*) malloc(strlen(srcName) + strlen(target) + 20); + /* On Unix we can just call javac ... *.java */ + sprintf(args[2], "%s/vtk%sDriver.java", srcPath, target); + info->CAPI->AddCustomCommand(mf, srcName, javac, 3, (const char**)args, + 0, 0, 1, (const char**)&className, target); + + free(args[2]); + info->CAPI->Free(srcNameWe); + info->CAPI->Free(srcPath); + classes[numClasses++] = strdup(className); + free(className); + } + free(args[0]); + free(args[1]); + + info->CAPI->AddCustomCommand(mf, target, "", 0, 0, + numClasses, (const char**)classes, 0, 0, target); + + for (i = 0; i < numClasses; i ++ ) + { + free(classes[i]); + } + free(classes); + + free(javaPath); + + free(target); + + fprintf(outfile, + " }\n" + " }\n"); + fclose(outfile); + + info->CAPI->FreeArguments(newArgc, newArgv); + return 1; +} + + +static void FinalPass(void *inf, void *mf) +{ +} + +static void Destructor(void *inf) +{ +} + +static const char* GetTerseDocumentation() +{ + return "Create Java Archive."; +} + +static const char* GetFullDocumentation() +{ + return + "VTK_WRAP_JAVA(target SourceLists ...)"; +} + +void CM_PLUGIN_EXPORT VTK_GENERATE_JAVA_DEPENDENCIESInit(cmLoadedCommandInfo *info) +{ + info->InitialPass = InitialPass; + info->FinalPass = FinalPass; + info->Destructor = Destructor; + info->GetTerseDocumentation = GetTerseDocumentation; + info->GetFullDocumentation = GetFullDocumentation; + info->m_Inherited = 0; + info->Name = "VTK_GENERATE_JAVA_DEPENDENCIES"; +} + + + + diff --git a/CMake/cmVTKMakeInstantiator2Command.c b/CMake/cmVTKMakeInstantiator2Command.c new file mode 100644 index 0000000..4ee9622 --- /dev/null +++ b/CMake/cmVTKMakeInstantiator2Command.c @@ -0,0 +1,355 @@ +/* this is a CMake loadable command to wrap vtk objects into Java */ + +#include "cmCPluginAPI.h" +#include +#include +#include + +static void GenerateHeaderFile(cmLoadedCommandInfo *info, + const char *fullPath, const char *hdrName, + const char *macroName, + int numIncludes, const char **includes) +{ + char *tempOutputFile; + FILE *fout; + int i; + + tempOutputFile = (char *)malloc(strlen(fullPath) + 5); + sprintf(tempOutputFile,"%s.tmp",fullPath); + fout = fopen(tempOutputFile,"w"); + if (!fout) + { + return; + } + + fprintf(fout, + "#ifndef __%s_h\n" + "#define __%s_h\n" + "\n" + "#include \"vtkInstantiator.h\"\n", hdrName, hdrName); + + for(i=0; i < numIncludes;++i) + { + fprintf(fout,"#include \"%s\"\n", includes[i]); + } + + /* Write the instantiator class definition. */ + fprintf(fout, + "\n" + "class %s %s\n" + "{\n" + "public:\n" + " %s();\n" + " ~%s();\n" + "private:\n" + " static void ClassInitialize();\n" + " static void ClassFinalize();\n" + " static unsigned int Count;\n" + "};\n" + "\n", macroName, hdrName, hdrName, hdrName); + + /* Write the initialization instance to make sure the creation */ + /* functions get registered when this generated header is included. */ + fprintf(fout, + "static %s %sInitializer;\n" + "\n" + "#endif\n",hdrName, hdrName); + + fclose(fout); + + /* copy the file if different */ + info->CAPI->CopyFileIfDifferent(tempOutputFile, fullPath); + info->CAPI->RemoveFile(tempOutputFile); + free(tempOutputFile); +} + +static void GenerateImplementationFile(cmLoadedCommandInfo *info, + const char *fullPath, + const char *hdrName, + int numClasses, const char **classes) +{ + char *tempOutputFile; + FILE *fout; + int i; + + tempOutputFile = (char *)malloc(strlen(fullPath) + 5); + sprintf(tempOutputFile,"%s.tmp",fullPath); + fout = fopen(tempOutputFile,"w"); + if (!fout) + { + return; + } + + /* Include the instantiator class header. */ + fprintf(fout, + "#include \"%s.h\"\n" + "\n", hdrName); + + /* Write the extern declarations for all the creation functions. */ + for(i=0; i < numClasses; ++i) + { + if (classes[i]) + { + fprintf(fout, + "extern vtkObject* vtkInstantiator%sNew();\n", + classes[i]); + } + } + + /* Write the ClassInitialize method to register all the creation functions.*/ + fprintf(fout, + "\n" + "void %s::ClassInitialize()\n" + "{\n", hdrName); + + for(i=0; i < numClasses; ++i) + { + if (classes[i]) + { + fprintf(fout, + " vtkInstantiator::RegisterInstantiator(\"%s\", vtkInstantiator%sNew);\n", classes[i], classes[i]); + } + } + + /* Write the ClassFinalize method to unregister all the creation functions.*/ + fprintf(fout, + "}\n" + "\n" + "void %s::ClassFinalize()\n" + "{\n", hdrName); + + for(i=0; i < numClasses; ++i) + { + if (classes[i]) + { + fprintf(fout, + " vtkInstantiator::UnRegisterInstantiator(\"%s\", vtkInstantiator%sNew);\n",classes[i],classes[i]); + } + } + + /* Write the constructor and destructor of the initializer class to */ + /* call the ClassInitialize and ClassFinalize methods at the right */ + /* time. */ + fprintf(fout, + "}\n" + "\n" + "%s::%s()\n" + "{\n" + " if(++%s::Count == 1)\n" + " { %s::ClassInitialize(); }\n" + "}\n", hdrName, hdrName, hdrName, hdrName); + fprintf(fout, + "\n" + "%s::~%s()\n" + "{\n" + " if(--%s::Count == 0)\n" + " { %s::ClassFinalize(); }\n" + "}\n" + "\n" + "// Number of translation units that include this class's header.\n" + "// Purposely not initialized. Default is static initialization to 0.\n" + "unsigned int %s::Count;\n", + hdrName, hdrName, hdrName, hdrName, hdrName); + fclose(fout); + + /* copy the file if different */ + info->CAPI->CopyFileIfDifferent(tempOutputFile, fullPath); + info->CAPI->RemoveFile(tempOutputFile); + free(tempOutputFile); +} + +/* do almost everything in the initial pass */ +static int InitialPass(void *inf, void *mf, int argc, char *argv[]) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + int i; + int newArgc; + char **newArgv; + const char *filePath = info->CAPI->GetCurrentOutputDirectory(mf); + const char *headerPath = filePath; + int includesMode = 0; + const char *ExportMacro = 0; + int numClasses = 0; + char **classes = 0; + int numIncludes = 0; + char **includes = 0; + char *fullName; + void *cfile; + + /* make sure we have the correct number of arguments */ + if(argc < 3 ) + { + return 0; + } + + /* expand any source lists */ + info->CAPI->ExpandSourceListArguments(mf, argc, argv, + &newArgc, &newArgv, 2); + + /* make sure we allocate enough memory */ + classes = (char **)malloc(sizeof(char *)*newArgc); + includes = (char **)malloc(sizeof(char *)*newArgc); + + /* Find the path of the files to be generated. */ + for(i=2; i < newArgc; ++i) + { + if(strcmp(newArgv[i],"HEADER_LOCATION") == 0) + { + includesMode = 0; + if(++i < newArgc) + { + headerPath = newArgv[i]; + } + else + { + info->CAPI->SetError(info,"HEADER_LOCATION option used without value."); + return 0; + } + } + else if (strcmp(newArgv[i],"EXPORT_MACRO") == 0) + { + includesMode = 0; + if (++i < newArgc) + { + ExportMacro = newArgv[i]; + } + else + { + info->CAPI->SetError(info, "EXPORT_MACRO option used without value."); + return 0; + } + } + else if (strcmp(newArgv[i],"INCLUDES") == 0) + { + includesMode = 1; + } + /* If not an option, it must be another input source list name or */ + /* an include file. */ + else + { + if(!includesMode) + { + classes[numClasses] = newArgv[i]; + numClasses++; + } + else + { + includes[numIncludes] = newArgv[i]; + numIncludes++; + } + } + } + + if(!ExportMacro) + { + info->CAPI->SetError(info, "No EXPORT_MACRO option given."); + return 0; + } + + for (i = 0; i < numClasses; ++i) + { + const char *srcName = info->CAPI->GetFilenameWithoutExtension(classes[i]); + void *sf = info->CAPI->GetSource(mf,classes[i]); + + /* Wrap-excluded and abstract classes do not have a New() method. */ + /* vtkIndent and vtkTimeStamp are special cases and are not */ + /* vtkObject subclasses. */ + if( + (sf && + (info->CAPI->SourceFileGetPropertyAsBool(sf,"WRAP_EXCLUDE") || + info->CAPI->SourceFileGetPropertyAsBool(sf,"ABSTRACT"))) || + !strcmp(srcName,"vtkIndent") || + !strcmp(srcName,"vtkTimeStamp")) + { + /* remove this class from the list */ + classes[i] = 0; + } + else + { + classes[i] = info->CAPI->GetFilenameWithoutExtension(classes[i]); + } + info->CAPI->Free((char*)srcName); + } + + /* Generate the header */ + fullName = malloc(strlen(newArgv[0]) + strlen(headerPath) + 10); + sprintf(fullName,"%s/%s.h",headerPath,newArgv[0]); + GenerateHeaderFile(info, fullName, newArgv[0], ExportMacro, + numIncludes, includes); + free(fullName); + + /* Generate the implementation */ + fullName = malloc(strlen(newArgv[0]) + strlen(filePath) + 10); + sprintf(fullName,"%s.cxx",newArgv[0]); + info->CAPI->AddDefinition(mf, newArgv[1], fullName); + sprintf(fullName,"%s/%s.cxx",filePath,newArgv[0]); + GenerateImplementationFile(info, fullName, newArgv[0], numClasses, classes); + free(fullName); + + /* free the classes */ + for (i = 0; i < numClasses; ++i) + { + if (classes[i]) + { + info->CAPI->Free(classes[i]); + } + } + + /* Add the generated source file into the source list. */ + cfile = info->CAPI->CreateSourceFile(); + info->CAPI->SourceFileSetProperty(cfile,"WRAP_EXCLUDE","1"); + info->CAPI->SourceFileSetProperty(cfile,"ABSTRACT","0"); + info->CAPI->SourceFileSetName2(cfile, newArgv[0], + info->CAPI->GetCurrentOutputDirectory(mf), + "cxx",0); + info->CAPI->AddSource(mf,cfile); + info->CAPI->DestroySourceFile(cfile); + info->CAPI->FreeArguments(newArgc, newArgv); + free(classes); + free(includes); + return 1; +} + +static const char* GetTerseDocumentation() +{ + return "Register classes for creation by vtkInstantiator"; +} + +static const char* GetFullDocumentation() +{ + return + "VTK_MAKE_INSTANTIATOR(className outSourceList\n" + " src-list1 [src-list2 ..]\n" + " EXPORT_MACRO exportMacro\n" + " [HEADER_LOCATION dir]\n" + " [INCLUDES [file1 file2 ..]])\n" + "Generates a new class with the given name and adds its files to the\n" + "given outSourceList. It registers the classes from the other given\n" + "source lists with vtkInstantiator when it is loaded. The output\n" + "source list should be added to the library with the classes it\n" + "registers.\n" + "The EXPORT_MACRO argument must be given and followed by the export\n" + "macro to use when generating the class (ex. VTK_COMMON_EXPORT).\n" + "The HEADER_LOCATION option must be followed by a path. It specifies\n" + "the directory in which to place the generated class's header file.\n" + "The generated class implementation files always go in the build\n" + "directory corresponding to the CMakeLists.txt file containing\n" + "the command. This is the default location for the header.\n" + "The INCLUDES option can be followed by a list of zero or more files.\n" + "These files will be #included by the generated instantiator header,\n" + "and can be used to gain access to the specified exportMacro in the\n" + " C++ code."; +} + +void CM_PLUGIN_EXPORT VTK_MAKE_INSTANTIATOR2Init(cmLoadedCommandInfo *info) +{ + info->InitialPass = InitialPass; + info->m_Inherited = 0; + info->GetTerseDocumentation = GetTerseDocumentation; + info->GetFullDocumentation = GetFullDocumentation; + info->Name = "VTK_MAKE_INSTANTIATOR2"; +} + + + + diff --git a/CMake/cmVTKWrapJava2Command.c b/CMake/cmVTKWrapJava2Command.c new file mode 100644 index 0000000..e655381 --- /dev/null +++ b/CMake/cmVTKWrapJava2Command.c @@ -0,0 +1,272 @@ +/* this is a CMake loadable command to wrap vtk objects into Java */ + +#include "cmCPluginAPI.h" +#include +#include +#include + +typedef struct +{ + char *LibraryName; + int NumberWrapped; + void **SourceFiles; +} cmVTKWrapJavaData; + +/* do almost everything in the initial pass */ +static int InitialPass(void *inf, void *mf, int argc, char *argv[]) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + int i; + int newArgc; + char **newArgv; + int numWrapped = 0; + cmVTKWrapJavaData *cdata = + (cmVTKWrapJavaData *)malloc(sizeof(cmVTKWrapJavaData)); + const char *cdir = info->CAPI->GetCurrentDirectory(mf); + const char *def = 0; + int sourceListSize = 0; + char *sourceListValue = 0; + char *newName; + void *cfile = 0; + + const char* resultDirectory = "${VTK_JAVA_HOME}"; + const char* res = info->CAPI->GetCurrentOutputDirectory(mf); + char* depFileName; + FILE* fp; + + if(argc < 3 ) + { + info->CAPI->SetError(info, "called with incorrect number of arguments"); + return 0; + } + + info->CAPI->ExpandSourceListArguments(mf, argc, (const char**)argv, + &newArgc, (char***)&newArgv, 2); + + /* Now check and see if the value has been stored in the cache */ + /* already, if so use that value and don't look for the program */ + if(!info->CAPI->IsOn(mf,"VTK_WRAP_JAVA")) + { + info->CAPI->FreeArguments(newArgc, newArgv); + return 1; + } + + /* keep the library name */ + cdata->LibraryName = strdup(newArgv[0]); + cdata->SourceFiles = (void **)malloc(sizeof(void *)*newArgc); + + /* was the list already populated */ + def = info->CAPI->GetDefinition(mf, newArgv[1]); + + /* Calculate size of source list. */ + /* Start with list of source files. */ + sourceListSize = info->CAPI->GetTotalArgumentSize(newArgc,newArgv); + /* Add enough to extend the name of each class. */ + sourceListSize += newArgc*strlen("Java.cxx"); + /* Add enough to include the def. */ + sourceListSize += def?strlen(def):0; + + /* Allocate and initialize the source list. */ + sourceListValue = (char *)malloc(sourceListSize); + sourceListValue[0] = 0; + if (def) + { + sprintf(sourceListValue,"%s",def); + } + + /* Prepare java dependency file */ + depFileName = (char*)malloc(strlen(res) + 40); + sprintf(depFileName, "%s/JavaDependencies.cmake", res); + fp = fopen(depFileName, "w"); + fprintf(fp, "# This file is automatically generated by CMake VTK_WRAP_JAVA\n\n" + "SET(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES}\n"); + + /* get the classes for this lib */ + for(i = 2; i < newArgc; ++i) + { + void *curr = info->CAPI->GetSource(mf,newArgv[i]); + + /* if we should wrap the class */ + if (!curr || + !info->CAPI->SourceFileGetPropertyAsBool(curr,"WRAP_EXCLUDE")) + { + void *file = info->CAPI->CreateSourceFile(); + char *srcName; + char *hname=0; + srcName = info->CAPI->GetFilenameWithoutExtension(newArgv[i]); + if (curr) + { + int abst = info->CAPI->SourceFileGetPropertyAsBool(curr,"ABSTRACT"); + info->CAPI->SourceFileSetProperty(file,"ABSTRACT", + (abst ? "1" : "0")); + } + newName = (char *)malloc(strlen(srcName)+5); + sprintf(newName,"%sJava",srcName); + info->CAPI->SourceFileSetName2(file, newName, + info->CAPI->GetCurrentOutputDirectory(mf), + "cxx",0); + hname = (char *)malloc(strlen(cdir) + strlen(srcName) + 4); + sprintf(hname,"%s/%s.h",cdir,srcName); + /* add starting depends */ + info->CAPI->SourceFileAddDepend(file,hname); + info->CAPI->AddSource(mf,file); + free(hname); + cdata->SourceFiles[numWrapped] = file; + numWrapped++; + strcat(sourceListValue,";"); + strcat(sourceListValue,newName); + strcat(sourceListValue,".cxx"); + + /* Write file to java dependency file */ + fprintf(fp, " %s/%s.java\n", resultDirectory, srcName); + free(newName); + info->CAPI->Free(srcName); + } + } + + /* Finalize java dependency file */ + fprintf(fp, ")\n"); + fclose(fp); + + cdata->NumberWrapped = numWrapped; + info->CAPI->SetClientData(info,cdata); + + info->CAPI->AddDefinition(mf, newArgv[1], sourceListValue); + info->CAPI->FreeArguments(newArgc, newArgv); + free(sourceListValue); + return 1; +} + + +static void FinalPass(void *inf, void *mf) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + /* get our client data from initial pass */ + cmVTKWrapJavaData *cdata = + (cmVTKWrapJavaData *)info->CAPI->GetClientData(info); + + /* first we add the rules for all the .h to Java.cxx files */ + const char *wjava = "${VTK_WRAP_JAVA_EXE}"; + const char *pjava = "${VTK_PARSE_JAVA_EXE}"; + const char *hints = info->CAPI->GetDefinition(mf,"VTK_WRAP_HINTS"); + const char *args[4]; + const char *depends[2]; + const char *depends2[2]; + char **alldeps = 0; + char* util=0; + int i; + int numDepends, numArgs; + const char *cdir = info->CAPI->GetCurrentDirectory(mf); + const char *resultDirectory = "${VTK_JAVA_HOME}"; + + /* If the first pass terminated early, we have nothing to do. */ + if(!cdata) + { + return; + } + + /* wrap all the .h files */ + depends[0] = wjava; + depends2[0] = pjava; + numDepends = 1; + if (hints) + { + depends[1] = hints; + depends2[1] = hints; + numDepends++; + } + alldeps = (char**)malloc(sizeof(const char*)*cdata->NumberWrapped); + for(i = 0; i < cdata->NumberWrapped; i++) + { + char *res; + const char *srcName = info->CAPI->SourceFileGetSourceName(cdata->SourceFiles[i]); + char *hname = (char *)malloc(strlen(cdir) + strlen(srcName) + 4); + sprintf(hname,"%s/%s",cdir,srcName); + hname[strlen(hname)-4]= '\0'; + strcat(hname,".h"); + args[0] = hname; + numArgs = 1; + if (hints) + { + args[1] = hints; + numArgs++; + } + args[numArgs] = + (info->CAPI->SourceFileGetPropertyAsBool(cdata->SourceFiles[i],"ABSTRACT") ?"0" :"1"); + numArgs++; + res = (char *)malloc(strlen(info->CAPI->GetCurrentOutputDirectory(mf)) + + strlen(srcName) + 6); + sprintf(res,"%s/%s.cxx",info->CAPI->GetCurrentOutputDirectory(mf),srcName); + args[numArgs] = res; + numArgs++; + info->CAPI->AddCustomCommand(mf, args[0], + wjava, numArgs, (const char**)args, numDepends, (const char**)depends, + 1, (const char**)&res, cdata->LibraryName); + free(res); + + res = (char *)malloc(strlen(resultDirectory) + + strlen(srcName) + 3); + sprintf(res,"%s/%s",resultDirectory,srcName); + sprintf(res+strlen(res)-4, ".java"); + args[numArgs-1] = res; + info->CAPI->AddCustomCommand(mf, args[0], + pjava, numArgs, args, numDepends, depends2, + 1, (const char**)&res, cdata->LibraryName); + alldeps[i] = res; + free(hname); + } + + util = malloc(strlen(cdata->LibraryName) + 12); + sprintf(util, "%sJavaClasses", cdata->LibraryName); + info->CAPI->AddUtilityCommand(mf, util, "", "", 1, + cdata->NumberWrapped, + (const char**)alldeps, + 0, 0); + for(i = 0; i < cdata->NumberWrapped; i++) + { + free(alldeps[i]); + } + free(alldeps); + free(util); +} + +static void Destructor(void *inf) +{ + int i; + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + /* get our client data from initial pass */ + cmVTKWrapJavaData *cdata = + (cmVTKWrapJavaData *)info->CAPI->GetClientData(info); + if (cdata) + { + for (i = 0; i < cdata->NumberWrapped; ++i) + { + info->CAPI->DestroySourceFile(cdata->SourceFiles[i]); + } + free(cdata->SourceFiles); + free(cdata->LibraryName); + free(cdata); + } +} + +static const char* GetTerseDocumentation() +{ + return "Create Java Wrappers."; +} + +static const char* GetFullDocumentation() +{ + return + "VTK_WRAP_JAVA(resultingLibraryName SourceListName SourceLists ...)"; +} + +void CM_PLUGIN_EXPORT VTK_WRAP_JAVA2Init(cmLoadedCommandInfo *info) +{ + info->InitialPass = InitialPass; + info->FinalPass = FinalPass; + info->Destructor = Destructor; + info->GetTerseDocumentation = GetTerseDocumentation; + info->GetFullDocumentation = GetFullDocumentation; + info->m_Inherited = 0; + info->Name = "VTK_WRAP_JAVA2"; +} diff --git a/CMake/cmVTKWrapPython2Command.c b/CMake/cmVTKWrapPython2Command.c new file mode 100644 index 0000000..b7ddfff --- /dev/null +++ b/CMake/cmVTKWrapPython2Command.c @@ -0,0 +1,350 @@ +/* this is a CMake loadable command to wrap vtk objects into Python */ + +#include "cmCPluginAPI.h" +#include +#include +#include + +typedef struct +{ + char *LibraryName; + int NumberWrapped; + void **SourceFiles; + char **HeaderFiles; +} cmVTKWrapPythonData; + +/* this roputine creates the init file */ +static void CreateInitFile(cmLoadedCommandInfo *info, + void *mf, const char *kitName, + int numClasses, const char **classes) +{ + /* we have to make sure that the name is the correct case */ + int i; + char *tempOutputFile; + char *outFileName = + (char *)malloc(strlen(info->CAPI->GetCurrentOutputDirectory(mf)) + + strlen(kitName) + 10); + FILE *fout; + + sprintf(outFileName,"%s/%sInit.cxx", + info->CAPI->GetCurrentOutputDirectory(mf), kitName); + + tempOutputFile = (char *)malloc(strlen(outFileName) + 5); + sprintf(tempOutputFile,"%s.tmp",outFileName); + fout = fopen(tempOutputFile,"w"); + if (!fout) + { + return; + } + + fprintf(fout,"// Generated by cmVTKWrapPythonCommand2 in VTK/CMake\n\n"); + fprintf(fout,"#include \"vtkPython.h\"\n\n"); + fprintf(fout,"#include \"vtkSystemIncludes.h\"\n"); + fprintf(fout,"#include \n"); + fprintf(fout,"// Handle compiler warning messages, etc.\n" + "#if defined( _MSC_VER ) && !defined(VTK_DISPLAY_WIN32_WARNINGS)\n" + "#pragma warning ( disable : 4706 )\n" + "#endif // Windows Warnings \n\n"); + + for (i = 0; i < numClasses; i++) + { +#ifdef _WIN32 + fprintf(fout,"extern \"C\" {__declspec( dllexport) PyObject *PyVTKClass_%sNew(char *); }\n",classes[i]); +#else + fprintf(fout,"extern \"C\" {PyObject *PyVTKClass_%sNew(char *); }\n",classes[i]); +#endif + } + + fprintf(fout,"\nstatic PyMethodDef Py%s_ClassMethods[] = {\n", + kitName); + fprintf(fout,"{NULL, NULL, 0, NULL}};\n\n"); + +#ifdef _WIN32 + fprintf(fout,"extern \"C\" {__declspec( dllexport) void init%s();}\n\n",kitName); + fprintf(fout,"void init%s()\n{\n",kitName); +#else + fprintf(fout,"extern \"C\" {void initlib%s();}\n\n",kitName); + fprintf(fout,"void initlib%s()\n{\n",kitName); +#endif + + + /* module init function */ + fprintf(fout," PyObject *m, *d, *c;\n\n"); +#ifdef _WIN32 + fprintf(fout," static const char modulename[] = \"%s\";\n",kitName); +#else + fprintf(fout," static const char modulename[] = \"lib%s\";\n",kitName); +#endif + fprintf(fout," m = Py_InitModule((char*)modulename, Py%s_ClassMethods);\n", + kitName); + + fprintf(fout," d = PyModule_GetDict(m);\n"); + fprintf(fout," if (!d) Py_FatalError((char*)\"can't get dictionary for module %s!\");\n\n", + kitName); + + for (i = 0; i < numClasses; i++) + { + fprintf(fout," if ((c = PyVTKClass_%sNew((char*)modulename)))\n", + classes[i]); + fprintf(fout," if (-1 == PyDict_SetItemString(d, (char*)\"%s\", c))\n", + classes[i]); + fprintf(fout," Py_FatalError((char*)\"can't add class %s to dictionary!\");\n\n", + classes[i]); + } + fprintf(fout,"}\n\n"); + fclose(fout); + + /* copy the file if different */ + info->CAPI->CopyFileIfDifferent(tempOutputFile, outFileName); + info->CAPI->RemoveFile(tempOutputFile); +} + +/* do almost everything in the initial pass */ +static int InitialPass(void *inf, void *mf, int argc, char *argv[]) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + int i; + int newArgc; + char **newArgv; + int numClasses = 0; + char **classes = 0; + int numWrapped = 0; + cmVTKWrapPythonData *cdata = + (cmVTKWrapPythonData *)malloc(sizeof(cmVTKWrapPythonData)); + const char *cdir = info->CAPI->GetCurrentDirectory(mf); + const char *def = 0; + int sourceListSize = 0; + char *sourceListValue = 0; + char *newName; + void *cfile = 0; + + if(argc < 3 ) + { + info->CAPI->SetError(info, "called with incorrect number of arguments"); + return 0; + } + + info->CAPI->ExpandSourceListArguments(mf, argc, argv, + &newArgc, &newArgv, 2); + + /* Now check and see if the value has been stored in the cache */ + /* already, if so use that value and don't look for the program */ + if(!info->CAPI->IsOn(mf,"VTK_WRAP_PYTHON")) + { + info->CAPI->FreeArguments(newArgc, newArgv); + return 1; + } + + /* keep the library name */ + classes = (char **)malloc(sizeof(char *)*newArgc); + cdata->LibraryName = strdup(newArgv[0]); + cdata->SourceFiles = (void **)malloc(sizeof(void *)*newArgc); + cdata->HeaderFiles = (char **)malloc(sizeof(char *)*newArgc); + + /* was the list already populated */ + def = info->CAPI->GetDefinition(mf, newArgv[1]); + + /* Calculate size of source list. */ + /* Start with list of source files. */ + sourceListSize = info->CAPI->GetTotalArgumentSize(newArgc,newArgv); + /* Add enough to extend the name of each class. */ + sourceListSize += newArgc*strlen("Python.cxx"); + /* Add enough to include the def and init file. */ + sourceListSize += def?strlen(def):0; + sourceListSize += strlen(";Init.cxx"); + + /* Allocate and initialize the source list. */ + sourceListValue = (char *)malloc(sourceListSize); + if (def) + { + sprintf(sourceListValue,"%s;%sInit.cxx",def,newArgv[0]); + } + else + { + /* Don't include the Init.cxx file in the library on OSX */ + /* It is linked into a MODULE separate from the rest of the dylib */ +#if defined(__APPLE__) + sprintf(sourceListValue,""); +#else + sprintf(sourceListValue,"%sInit.cxx",newArgv[0]); +#endif + } + + /* get the classes for this lib */ + for(i = 2; i < newArgc; ++i) + { + void *curr = info->CAPI->GetSource(mf,newArgv[i]); + + /* if we should wrap the class */ + if (!curr || + !info->CAPI->SourceFileGetPropertyAsBool(curr,"WRAP_EXCLUDE")) + { + void *file = info->CAPI->CreateSourceFile(); + char *srcName; + char *hname; + char *pathName; + srcName = info->CAPI->GetFilenameWithoutExtension(newArgv[i]); + pathName = info->CAPI->GetFilenamePath(newArgv[i]); + if (curr) + { + int abst = info->CAPI->SourceFileGetPropertyAsBool(curr,"ABSTRACT"); + info->CAPI->SourceFileSetProperty(file,"ABSTRACT", + (abst ? "1" : "0")); + } + classes[numClasses] = strdup(srcName); + numClasses++; + newName = (char *)malloc(strlen(srcName)+7); + sprintf(newName,"%sPython",srcName); + info->CAPI->SourceFileSetName2(file, newName, + info->CAPI->GetCurrentOutputDirectory(mf), + "cxx",0); + + if (strlen(pathName) > 1) + { + hname = (char *)malloc(strlen(pathName) + strlen(srcName) + 4); + sprintf(hname,"%s/%s.h",pathName,srcName); + } + else + { + hname = (char *)malloc(strlen(cdir) + strlen(srcName) + 4); + sprintf(hname,"%s/%s.h",cdir,srcName); + } + /* add starting depends */ + info->CAPI->SourceFileAddDepend(file,hname); + info->CAPI->AddSource(mf,file); + cdata->SourceFiles[numWrapped] = file; + cdata->HeaderFiles[numWrapped] = hname; + numWrapped++; + if(sourceListValue[0]) + { + /* This is not the first value, add a separator. */ + strcat(sourceListValue,";"); + } + strcat(sourceListValue,newName); + strcat(sourceListValue,".cxx"); + free(newName); + info->CAPI->Free(srcName); + info->CAPI->Free(pathName); + } + } + + /* add the init file */ + cfile = info->CAPI->CreateSourceFile(); + info->CAPI->SourceFileSetProperty(cfile,"ABSTRACT","0"); + newName = (char *)malloc(strlen(newArgv[0]) + 5); + sprintf(newName,"%sInit",newArgv[0]); + CreateInitFile(info,mf,newArgv[0],numClasses,classes); + info->CAPI->SourceFileSetName2(cfile, newName, + info->CAPI->GetCurrentOutputDirectory(mf), + "cxx",0); + free(newName); + info->CAPI->AddSource(mf,cfile); + + cdata->NumberWrapped = numWrapped; + info->CAPI->SetClientData(info,cdata); + + info->CAPI->AddDefinition(mf, newArgv[1], sourceListValue); + info->CAPI->FreeArguments(newArgc, newArgv); + free(sourceListValue); + return 1; +} + + +static void FinalPass(void *inf, void *mf) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + /* get our client data from initial pass */ + cmVTKWrapPythonData *cdata = + (cmVTKWrapPythonData *)info->CAPI->GetClientData(info); + + /* first we add the rules for all the .h to Python.cxx files */ + const char *wpython = "${VTK_WRAP_PYTHON_EXE}"; + const char *hints = info->CAPI->GetDefinition(mf,"VTK_WRAP_HINTS"); + const char *args[4]; + const char *depends[2]; + int i; + int numDepends, numArgs; + const char *cdir = info->CAPI->GetCurrentDirectory(mf); + + /* If the first pass terminated early, we have nothing to do. */ + if(!cdata) + { + return; + } + + /* wrap all the .h files */ + depends[0] = wpython; + numDepends = 1; + if (hints) + { + depends[1] = hints; + numDepends++; + } + for(i = 0; i < cdata->NumberWrapped; i++) + { + char *res; + const char *srcName = info->CAPI->SourceFileGetSourceName(cdata->SourceFiles[i]); + args[0] = cdata->HeaderFiles[i]; + numArgs = 1; + if (hints) + { + args[1] = hints; + numArgs++; + } + args[numArgs] = + (info->CAPI->SourceFileGetPropertyAsBool(cdata->SourceFiles[i],"ABSTRACT") ?"0" :"1"); + numArgs++; + res = (char *)malloc(strlen(info->CAPI->GetCurrentOutputDirectory(mf)) + + strlen(srcName) + 6); + sprintf(res,"%s/%s.cxx",info->CAPI->GetCurrentOutputDirectory(mf),srcName); + args[numArgs] = res; + numArgs++; + info->CAPI->AddCustomCommand(mf, args[0], + wpython, numArgs, args, numDepends, depends, + 1, &res, cdata->LibraryName); + free(res); + } +} + +static void Destructor(void *inf) +{ + int i; + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + /* get our client data from initial pass */ + cmVTKWrapPythonData *cdata = + (cmVTKWrapPythonData *)info->CAPI->GetClientData(info); + if (cdata) + { + for (i = 0; i < cdata->NumberWrapped; ++i) + { + info->CAPI->DestroySourceFile(cdata->SourceFiles[i]); + free(cdata->HeaderFiles[i]); + } + free(cdata->SourceFiles); + free(cdata->HeaderFiles); + free(cdata->LibraryName); + free(cdata); + } +} + +static const char* GetTerseDocumentation() +{ + return "Create Python Wrappers."; +} + +static const char* GetFullDocumentation() +{ + return + "VTK_WRAP_PYTHON(resultingLibraryName SourceListName SourceLists ...)"; +} + +void CM_PLUGIN_EXPORT VTK_WRAP_PYTHON2Init(cmLoadedCommandInfo *info) +{ + info->InitialPass = InitialPass; + info->FinalPass = FinalPass; + info->Destructor = Destructor; + info->m_Inherited = 0; + info->GetTerseDocumentation = GetTerseDocumentation; + info->GetFullDocumentation = GetFullDocumentation; + info->Name = "VTK_WRAP_PYTHON2"; +} diff --git a/CMake/cmVTKWrapTcl2Command.c b/CMake/cmVTKWrapTcl2Command.c new file mode 100644 index 0000000..b8ab68d --- /dev/null +++ b/CMake/cmVTKWrapTcl2Command.c @@ -0,0 +1,478 @@ +/* this is a CMake loadable command to wrap vtk objects into Tcl */ + +#include "cmCPluginAPI.h" +#include +#include +#include + +typedef struct +{ + char *LibraryName; + int NumberWrapped; + void **SourceFiles; + char **HeaderFiles; +} cmVTKWrapTclData; + +/* this roputine creates the init file */ +static void CreateInitFile(cmLoadedCommandInfo *info, + void *mf, const char *libName, + int numConcrete, const char **concrete, + int numCommands, const char **commands) +{ + /* we have to make sure that the name is the correct case */ + char *kitName = info->CAPI->Capitalized(libName); + int i; + char *tempOutputFile; + char *outFileName = + (char *)malloc(strlen(info->CAPI->GetCurrentOutputDirectory(mf)) + + strlen(libName) + 10); + char **capcommands = (char **)malloc(numCommands*sizeof(char *)); + FILE *fout; + + sprintf(outFileName,"%s/%sInit.cxx", + info->CAPI->GetCurrentOutputDirectory(mf), libName); + + tempOutputFile = (char *)malloc(strlen(outFileName) + 5); + sprintf(tempOutputFile,"%s.tmp",outFileName); + fout = fopen(tempOutputFile,"w"); + if (!fout) + { + return; + } + + /* capitalized commands just once */ + for (i = 0; i < numCommands; i++) + { + capcommands[i] = info->CAPI->Capitalized(commands[i]); + } + + fprintf(fout,"#include \"vtkTclUtil.h\"\n"); + fprintf(fout,"#include \"vtkVersion.h\"\n"); + fprintf(fout,"#define VTK_TCL_TO_STRING(x) VTK_TCL_TO_STRING0(x)\n"); + fprintf(fout,"#define VTK_TCL_TO_STRING0(x) #x\n"); + + fprintf(fout, + "extern \"C\"\n" + "{\n" + "#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4) && (TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE)\n" + " typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,int, CONST84 char *[]);\n" + "#else\n" + " typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,int, char *[]);\n" + "#endif\n" + "}\n" + "\n"); + + for (i = 0; i < numConcrete; i++) + { + fprintf(fout,"int %sCommand(ClientData cd, Tcl_Interp *interp,\n int argc, char *argv[]);\n",concrete[i]); + fprintf(fout,"ClientData %sNewCommand();\n",concrete[i]); + } + + if (!strcmp(kitName,"Vtkcommontcl")) + { + fprintf(fout,"int vtkCreateCommand(ClientData cd, Tcl_Interp *interp,\n" + " int argc, char *argv[]);\n"); + fprintf(fout,"\nTcl_HashTable vtkInstanceLookup;\n"); + fprintf(fout,"Tcl_HashTable vtkPointerLookup;\n"); + fprintf(fout,"Tcl_HashTable vtkCommandLookup;\n"); + } + else + { + fprintf(fout,"\nextern Tcl_HashTable vtkInstanceLookup;\n"); + fprintf(fout,"extern Tcl_HashTable vtkPointerLookup;\n"); + fprintf(fout,"extern Tcl_HashTable vtkCommandLookup;\n"); + } + fprintf(fout,"extern void vtkTclDeleteObjectFromHash(void *);\n"); + fprintf(fout,"extern void vtkTclListInstances(Tcl_Interp *interp, ClientData arg);\n"); + + for (i = 0; i < numCommands; i++) + { + fprintf(fout, + "\nextern \"C\" {int VTK_EXPORT %s_Init(Tcl_Interp *interp);}\n", + capcommands[i]); + } + + fprintf(fout, + "\n\nextern \"C\" {int VTK_EXPORT %s_SafeInit(Tcl_Interp *interp);}\n", + kitName); + fprintf(fout, + "\nextern \"C\" {int VTK_EXPORT %s_Init(Tcl_Interp *interp);}\n", + kitName); + + /* create an extern ref to the generic delete function */ + fprintf(fout,"\nextern void vtkTclGenericDeleteObject(ClientData cd);\n"); + + if (!strcmp(kitName,"Vtkcommontcl")) + { + fprintf(fout, + "extern \"C\"\n{\nvoid vtkCommonDeleteAssocData(ClientData cd)\n"); + fprintf(fout," {\n"); + fprintf(fout," vtkTclInterpStruct *tis = static_cast(cd);\n"); + fprintf(fout," delete tis;\n }\n}\n"); + } + + /* the main declaration */ + fprintf(fout, + "\n\nint VTK_EXPORT %s_SafeInit(Tcl_Interp *interp)\n{\n",kitName); + fprintf(fout," return %s_Init(interp);\n}\n",kitName); + + fprintf(fout,"\n\nint VTK_EXPORT %s_Init(Tcl_Interp *interp)\n{\n", + kitName); + if (!strcmp(kitName,"Vtkcommontcl")) + { + fprintf(fout, + " vtkTclInterpStruct *info = new vtkTclInterpStruct;\n"); + fprintf(fout, + " info->Number = 0; info->InDelete = 0; info->DebugOn = 0; info->DeleteExistingObjectOnNew = 0;\n"); + fprintf(fout,"\n"); + fprintf(fout,"\n"); + fprintf(fout, + " Tcl_InitHashTable(&info->InstanceLookup, TCL_STRING_KEYS);\n"); + fprintf(fout, + " Tcl_InitHashTable(&info->PointerLookup, TCL_STRING_KEYS);\n"); + fprintf(fout, + " Tcl_InitHashTable(&info->CommandLookup, TCL_STRING_KEYS);\n"); + fprintf(fout, + " Tcl_SetAssocData(interp,(char *) \"vtk\",NULL,(ClientData *)info);\n"); + fprintf(fout, + " Tcl_CreateExitHandler(vtkCommonDeleteAssocData,(ClientData *)info);\n"); + + /* create special vtkCommand command */ + fprintf(fout," Tcl_CreateCommand(interp,(char *) \"vtkCommand\",\n" + " reinterpret_cast(vtkCreateCommand),\n" + " (ClientData *)NULL, NULL);\n\n"); + } + + for (i = 0; i < numCommands; i++) + { + fprintf(fout," %s_Init(interp);\n", capcommands[i]); + } + fprintf(fout,"\n"); + + for (i = 0; i < numConcrete; i++) + { + fprintf(fout," vtkTclCreateNew(interp,(char *) \"%s\", %sNewCommand,\n", + concrete[i], concrete[i]); + fprintf(fout," %sCommand);\n",concrete[i]); + } + + fprintf(fout," char pkgName[]=\"%s\";\n", libName); + fprintf(fout," char pkgVers[]=VTK_TCL_TO_STRING(VTK_MAJOR_VERSION)" + " \".\" " + "VTK_TCL_TO_STRING(VTK_MINOR_VERSION);\n"); + fprintf(fout," Tcl_PkgProvide(interp, pkgName, pkgVers);\n"); + fprintf(fout," return TCL_OK;\n}\n"); + fclose(fout); + + /* copy the file if different */ + info->CAPI->CopyFileIfDifferent(tempOutputFile, outFileName); + info->CAPI->RemoveFile(tempOutputFile); + for ( i = 0; i < numCommands; i++ ) + { + info->CAPI->Free(capcommands[i]); + } + free(capcommands); + free(tempOutputFile); + info->CAPI->Free(kitName); + free(outFileName); +} + +/* do almost everything in the initial pass */ +static int InitialPass(void *inf, void *mf, int argc, char *argv[]) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + int i; + int newArgc; + char **newArgv; + int doing_sources = 1; + char **sources = 0; + char **commands = 0; + int numSources = 0; + int numCommands = 0; + int numConcrete = 0; + char **concrete = 0; + int numWrapped = 0; + cmVTKWrapTclData *cdata = + (cmVTKWrapTclData *)malloc(sizeof(cmVTKWrapTclData)); + + if(argc < 3 ) + { + info->CAPI->SetError(info, "called with incorrect number of arguments"); + return 0; + } + + if (!strcmp(argv[1],"SOURCES")) + { + info->CAPI->ExpandSourceListArguments(mf, argc, argv, &newArgc, + &newArgv, 3); + } + else + { + info->CAPI->ExpandSourceListArguments(mf, argc, argv, + &newArgc, &newArgv, 2); + } + + /* Now check and see if the value has been stored in the cache */ + /* already, if so use that value and don't look for the program */ + if(!info->CAPI->IsOn(mf,"VTK_WRAP_TCL")) + { + info->CAPI->FreeArguments(newArgc, newArgv); + return 1; + } + + /* extract the sources and commands parameters */ + sources = (char **)malloc(sizeof(char *)*newArgc); + commands = (char **)malloc(sizeof(char *)*newArgc); + concrete = (char **)malloc(sizeof(char *)*newArgc); + cdata->SourceFiles = (void **)malloc(sizeof(void *)*newArgc); + cdata->HeaderFiles = (char **)malloc(sizeof(char *)*newArgc); + + for(i = 1; i < newArgc; ++i) + { + if(!strcmp(newArgv[i],"SOURCES")) + { + doing_sources = 1; + } + else if (!strcmp(newArgv[i],"COMMANDS")) + { + doing_sources = 0; + } + else + { + if(doing_sources) + { + sources[numSources] = newArgv[i]; + numSources++; + } + else + { + commands[numCommands] = newArgv[i]; + numCommands++; + } + } + } + + /* get the list of classes for this library */ + if (numSources) + { + /* what is the current source dir */ + const char *cdir = info->CAPI->GetCurrentDirectory(mf); + int sourceListSize = 0; + char *sourceListValue = 0; + void *cfile = 0; + char *newName; + + /* was the list already populated */ + const char *def = info->CAPI->GetDefinition(mf, sources[0]); + + /* Calculate size of source list. */ + /* Start with list of source files. */ + sourceListSize = info->CAPI->GetTotalArgumentSize(newArgc,newArgv); + /* Add enough to extend the name of each class. */ + sourceListSize += numSources*strlen("Tcl.cxx"); + /* Add enough to include the def and init file. */ + sourceListSize += def?strlen(def):0; + sourceListSize += strlen(";Init.cxx"); + + /* Allocate and initialize the source list. */ + sourceListValue = (char *)malloc(sourceListSize); + if (def) + { + sprintf(sourceListValue,"%s;%sInit.cxx",def,argv[0]); + } + else + { + sprintf(sourceListValue,"%sInit.cxx",argv[0]); + } + + for(i = 1; i < numSources; ++i) + { + void *curr = info->CAPI->GetSource(mf,sources[i]); + + /* if we should wrap the class */ + if (!curr || + !info->CAPI->SourceFileGetPropertyAsBool(curr,"WRAP_EXCLUDE")) + { + void *file = info->CAPI->CreateSourceFile(); + char *srcName; + char *hname; + char *pathName; + srcName = info->CAPI->GetFilenameWithoutExtension(sources[i]); + pathName = info->CAPI->GetFilenamePath(sources[i]); + if (curr) + { + int abst = info->CAPI->SourceFileGetPropertyAsBool(curr,"ABSTRACT"); + info->CAPI->SourceFileSetProperty(file,"ABSTRACT", + (abst ? "1" : "0")); + if (!abst) + { + concrete[numConcrete] = strdup(srcName); + numConcrete++; + } + } + else + { + concrete[numConcrete] = strdup(srcName); + numConcrete++; + } + newName = (char *)malloc(strlen(srcName)+4); + sprintf(newName,"%sTcl",srcName); + info->CAPI->SourceFileSetName2(file, newName, + info->CAPI->GetCurrentOutputDirectory(mf), + "cxx",0); + + if (strlen(pathName) > 1) + { + hname = (char *)malloc(strlen(pathName) + strlen(srcName) + 4); + sprintf(hname,"%s/%s.h",pathName,srcName); + } + else + { + hname = (char *)malloc(strlen(cdir) + strlen(srcName) + 4); + sprintf(hname,"%s/%s.h",cdir,srcName); + } + /* add starting depends */ + info->CAPI->SourceFileAddDepend(file,hname); + info->CAPI->AddSource(mf,file); + cdata->SourceFiles[numWrapped] = file; + cdata->HeaderFiles[numWrapped] = hname; + numWrapped++; + strcat(sourceListValue,";"); + strcat(sourceListValue,newName); + strcat(sourceListValue,".cxx"); + free(newName); + info->CAPI->Free(srcName); + info->CAPI->Free(pathName); + } + } + /* add the init file */ + cfile = info->CAPI->CreateSourceFile(); + info->CAPI->SourceFileSetProperty(cfile,"ABSTRACT","0"); + newName = (char *)malloc(strlen(argv[0]) + 5); + sprintf(newName,"%sInit",argv[0]); + CreateInitFile(info,mf,argv[0],numConcrete,concrete,numCommands,commands); + info->CAPI->SourceFileSetName2(cfile, newName, + info->CAPI->GetCurrentOutputDirectory(mf), + "cxx",0); + free(newName); + info->CAPI->AddSource(mf,cfile); + info->CAPI->DestroySourceFile(cfile); + info->CAPI->AddDefinition(mf, sources[0], sourceListValue); + free(sourceListValue); + } + + /* store key data in the CLientData for the final pass */ + cdata->NumberWrapped = numWrapped; + cdata->LibraryName = strdup(argv[0]); + info->CAPI->SetClientData(info,cdata); + + free(sources); + free(commands); + info->CAPI->FreeArguments(newArgc, newArgv); + for (i = 0; i < numConcrete; ++i) + { + free(concrete[i]); + } + free(concrete); + return 1; +} + + +static void FinalPass(void *inf, void *mf) +{ + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + /* get our client data from initial pass */ + cmVTKWrapTclData *cdata = + (cmVTKWrapTclData *)info->CAPI->GetClientData(info); + + /* first we add the rules for all the .h to Tcl.cxx files */ + const char *wtcl = "${VTK_WRAP_TCL_EXE}"; + const char *hints = info->CAPI->GetDefinition(mf,"VTK_WRAP_HINTS"); + const char *args[4]; + const char *depends[2]; + int i; + int numDepends, numArgs; + const char *cdir = info->CAPI->GetCurrentDirectory(mf); + + /* If the first pass terminated early, we have nothing to do. */ + if(!cdata) + { + return; + } + + /* wrap all the .h files */ + depends[0] = wtcl; + numDepends = 1; + if (hints) + { + depends[1] = hints; + numDepends++; + } + for(i = 0; i < cdata->NumberWrapped; i++) + { + char *res; + const char *srcName = info->CAPI->SourceFileGetSourceName(cdata->SourceFiles[i]); + args[0] = cdata->HeaderFiles[i]; + numArgs = 1; + if (hints) + { + args[1] = hints; + numArgs++; + } + args[numArgs] = + (info->CAPI->SourceFileGetPropertyAsBool(cdata->SourceFiles[i],"ABSTRACT") ?"0" :"1"); + numArgs++; + res = (char *)malloc(strlen(info->CAPI->GetCurrentOutputDirectory(mf)) + + strlen(srcName) + 6); + sprintf(res,"%s/%s.cxx",info->CAPI->GetCurrentOutputDirectory(mf),srcName); + args[numArgs] = res; + numArgs++; + info->CAPI->AddCustomCommand(mf, args[0], + wtcl, numArgs, args, numDepends, depends, + 1, &res, cdata->LibraryName); + free(res); + } +} + +static void Destructor(void *inf) +{ + int i; + cmLoadedCommandInfo *info = (cmLoadedCommandInfo *)inf; + /* get our client data from initial pass */ + cmVTKWrapTclData *cdata = + (cmVTKWrapTclData *)info->CAPI->GetClientData(info); + if (cdata) + { + for (i = 0; i < cdata->NumberWrapped; ++i) + { + info->CAPI->DestroySourceFile(cdata->SourceFiles[i]); + free(cdata->HeaderFiles[i]); + } + free(cdata->SourceFiles); + free(cdata->HeaderFiles); + free(cdata->LibraryName); + free(cdata); + } +} + +static const char* GetTerseDocumentation() +{ + return "Create Tcl Wrappers for VTK classes."; +} + +static const char* GetFullDocumentation() +{ + return + "VTK_WRAP_TCL(resultingLibraryName [SOURCES] SourceListName SourceLists ... [COMMANDS CommandName1 CommandName2 ...])"; +} + +void CM_PLUGIN_EXPORT VTK_WRAP_TCL2Init(cmLoadedCommandInfo *info) +{ + info->InitialPass = InitialPass; + info->FinalPass = FinalPass; + info->Destructor = Destructor; + info->m_Inherited = 0; + info->GetTerseDocumentation = GetTerseDocumentation; + info->GetFullDocumentation = GetFullDocumentation; + info->Name = "VTK_WRAP_TCL2"; +} diff --git a/CMake/vtkCompileCMakeExtensions.cmake b/CMake/vtkCompileCMakeExtensions.cmake new file mode 100644 index 0000000..50a83f6 --- /dev/null +++ b/CMake/vtkCompileCMakeExtensions.cmake @@ -0,0 +1,36 @@ +#----------------------------------------------------------------------------- +# Macro to compile VTK's CMake extension commands. +# The arguments are the source and build tree locations for the loaded +# commands project, and the variable in which success/failure should +# be stored. +MACRO(VTK_COMPILE_CMAKE_EXTENSIONS source_dir build_dir result_var) + # do we need the extensions + SET (VTK_NEED_LOADED_COMMANDS 0) + IF (VTK_WRAP_TCL OR VTK_WRAP_PYTHON) + SET (VTK_NEED_LOADED_COMMANDS 1) + ENDIF (VTK_WRAP_TCL OR VTK_WRAP_PYTHON) + IF (VTK_WRAP_JAVA) + SET (VTK_NEED_LOADED_COMMANDS 1) + ENDIF (VTK_WRAP_JAVA) + + # if we need them + IF (VTK_NEED_LOADED_COMMANDS) + # if they are not already loaded + IF(COMMAND VTK_WRAP_TCL2) + ELSE(COMMAND VTK_WRAP_TCL2) + MESSAGE(STATUS "Compiling VTK CMake commands") + TRY_COMPILE("${result_var}" "${build_dir}" "${source_dir}" + VTK_LOADED_COMMANDS + CMAKE_FLAGS -DVTK_BUILD_FROM_TRY_COMPILE:BOOL=TRUE + OUTPUT_VARIABLE VTK_COMPILE_CMAKE_EXTENSIONS_OUTPUT) + IF("${result_var}") + MESSAGE(STATUS "Compiling VTK CMake commands - done") + ELSE("${result_var}") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Building of VTK extensions failed with the following output:\n" + "${VTK_COMPILE_CMAKE_EXTENSIONS_OUTPUT}\n" APPEND) + MESSAGE(FATAL_ERROR "Compiling VTK CMake commands - failed") + ENDIF("${result_var}") + ENDIF(COMMAND VTK_WRAP_TCL2) + ENDIF (VTK_NEED_LOADED_COMMANDS) +ENDMACRO(VTK_COMPILE_CMAKE_EXTENSIONS) diff --git a/CMake/vtkDependentOption.cmake b/CMake/vtkDependentOption.cmake new file mode 100644 index 0000000..fc68708 --- /dev/null +++ b/CMake/vtkDependentOption.cmake @@ -0,0 +1,33 @@ +# Macro to provide an option only if a set of other variables are ON. +# Example invocation: +# +# VTK_DEPENDENT_OPTION(USE_FOO "Use Foo" ON "USE_BAR;USE_ZOT" OFF) +# +# If both USE_BAR and USE_ZOT are true, this provides an option called +# USE_FOO that defaults to ON. Otherwise, it sets USE_FOO to OFF. If +# the status of USE_BAR or USE_ZOT ever changes, any value for the +# USE_FOO option is saved so that when the option is re-enabled it +# retains its old value. +# +MACRO(VTK_DEPENDENT_OPTION option doc default depends force) + IF(${option}_ISSET MATCHES "^${option}_ISSET$") + SET(${option}_AVAILABLE 1) + FOREACH(d ${depends}) + IF(NOT ${d}) + SET(${option}_AVAILABLE 0) + ENDIF(NOT ${d}) + ENDFOREACH(d) + IF(${option}_AVAILABLE) + OPTION(${option} "${doc}" "${default}") + SET(${option} "${${option}}" CACHE BOOL "${doc}" FORCE) + ELSE(${option}_AVAILABLE) + IF(${option} MATCHES "^${option}$") + ELSE(${option} MATCHES "^${option}$") + SET(${option} "${${option}}" CACHE INTERNAL "${doc}") + ENDIF(${option} MATCHES "^${option}$") + SET(${option} ${force}) + ENDIF(${option}_AVAILABLE) + ELSE(${option}_ISSET MATCHES "^${option}_ISSET$") + SET(${option} "${${option}_ISSET}") + ENDIF(${option}_ISSET MATCHES "^${option}_ISSET$") +ENDMACRO(VTK_DEPENDENT_OPTION) diff --git a/CMake/vtkExportKit.cmake b/CMake/vtkExportKit.cmake new file mode 100644 index 0000000..2bd4ca5 --- /dev/null +++ b/CMake/vtkExportKit.cmake @@ -0,0 +1,34 @@ +#----------------------------------------------------------------------------- +MACRO(VTK_EXPORT_KIT kit ukit sources) + SET(KIT_CLASS_LIST) + SET(KIT_ABSTRACT_LIST) + SET(KIT_EXCLUDE_LIST) + FOREACH(src ${sources}) + STRING(REGEX REPLACE "\\.cxx$" "" CLASS "${src}") + SET(KIT_CLASS_LIST "${KIT_CLASS_LIST}\n \"${CLASS}\"") + GET_SOURCE_FILE_PROPERTY(IS_ABSTRACT ${src} ABSTRACT) + IF(IS_ABSTRACT MATCHES "^1$") + SET(KIT_ABSTRACT_LIST "${KIT_ABSTRACT_LIST}\n \"${CLASS}\"") + ENDIF(IS_ABSTRACT MATCHES "^1$") + GET_SOURCE_FILE_PROPERTY(IS_EXCLUDE ${src} WRAP_EXCLUDE) + IF(IS_EXCLUDE MATCHES "^1$") + SET(KIT_EXCLUDE_LIST "${KIT_EXCLUDE_LIST}\n \"${CLASS}\"") + ENDIF(IS_EXCLUDE MATCHES "^1$") + ENDFOREACH(src) + SET(VTK_EXPORT_KIT ${kit}) + SET(VTK_EXPORT_UKIT ${ukit}) + SET(VTK_EXPORT_KIT_DOLLAR "$") + SET(VTK_EXPORT_HEADER_DIR ${VTK_EXPORT_KIT_DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_INCLUDE_DIR}) + CONFIGURE_FILE(${VTK_SOURCE_DIR}/CMake/vtkKit.cmake.in + ${VTK_BINARY_DIR}/Utilities/InstallOnly/vtk${kit}Kit.cmake + @ONLY IMMEDIATE) + SET(VTK_EXPORT_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + CONFIGURE_FILE(${VTK_SOURCE_DIR}/CMake/vtkKit.cmake.in + ${VTK_BINARY_DIR}/Utilities/vtk${kit}Kit.cmake + @ONLY IMMEDIATE) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR} FILES + ${VTK_BINARY_DIR}/Utilities/InstallOnly/vtk${kit}Kit.cmake + ) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDMACRO(VTK_EXPORT_KIT) diff --git a/CMake/vtkKit.cmake.in b/CMake/vtkKit.cmake.in new file mode 100644 index 0000000..d1515c6 --- /dev/null +++ b/CMake/vtkKit.cmake.in @@ -0,0 +1,22 @@ +# Directory containing class headers. +SET(VTK_@VTK_EXPORT_UKIT@_HEADER_DIR "@VTK_EXPORT_HEADER_DIR@") + +# Classes in vtk@VTK_EXPORT_KIT@. +SET(VTK_@VTK_EXPORT_UKIT@_CLASSES@KIT_CLASS_LIST@) + +# Abstract classes in vtk@VTK_EXPORT_KIT@. +SET(VTK_@VTK_EXPORT_UKIT@_CLASSES_ABSTRACT@KIT_ABSTRACT_LIST@) + +# Wrap-exclude classes in vtk@VTK_EXPORT_KIT@. +SET(VTK_@VTK_EXPORT_UKIT@_CLASSES_WRAP_EXCLUDE@KIT_EXCLUDE_LIST@) + +# Set convenient variables to test each class. +FOREACH(class ${VTK_@VTK_EXPORT_UKIT@_CLASSES}) + SET(VTK_CLASS_EXISTS_${class} 1) +ENDFOREACH(class) +FOREACH(class ${VTK_@VTK_EXPORT_UKIT@_CLASSES_ABSTRACT}) + SET(VTK_CLASS_ABSTRACT_${class} 1) +ENDFOREACH(class) +FOREACH(class ${VTK_@VTK_EXPORT_UKIT@_CLASSES_WRAP_EXCLUDE}) + SET(VTK_CLASS_WRAP_EXCLUDE_${class} 1) +ENDFOREACH(class) diff --git a/CMake/vtkLoadCMakeExtensions.cmake b/CMake/vtkLoadCMakeExtensions.cmake new file mode 100644 index 0000000..a82c641 --- /dev/null +++ b/CMake/vtkLoadCMakeExtensions.cmake @@ -0,0 +1,33 @@ +#----------------------------------------------------------------------------- +# Macro to load VTK's CMake extension commands. The argument should +# be the directory containing the command modules. +MACRO(VTK_LOAD_SINGLE_CMAKE_EXTENSION name dir) + IF(COMMAND ${name}) + ELSE(COMMAND ${name}) + LOAD_COMMAND(${name} ${dir} ${dir}/Debug) + ENDIF(COMMAND ${name}) + IF(COMMAND ${name}) + ELSE(COMMAND ${name}) + MESSAGE(FATAL_ERROR "Loading VTK command ${name} - failed") + ENDIF(COMMAND ${name}) +ENDMACRO(VTK_LOAD_SINGLE_CMAKE_EXTENSION) + +MACRO(VTK_LOAD_CMAKE_EXTENSIONS ext_dir) + # do we need the extensions + SET (VTK_NEED_LOADED_COMMANDS 0) + IF (VTK_WRAP_TCL OR VTK_WRAP_PYTHON) + SET (VTK_NEED_LOADED_COMMANDS 1) + ENDIF (VTK_WRAP_TCL OR VTK_WRAP_PYTHON) + IF (VTK_WRAP_JAVA) + SET (VTK_NEED_LOADED_COMMANDS 1) + ENDIF (VTK_WRAP_JAVA) + + IF (VTK_NEED_LOADED_COMMANDS) + MESSAGE(STATUS "Loading VTK CMake commands") + VTK_LOAD_SINGLE_CMAKE_EXTENSION(VTK_WRAP_TCL2 ${ext_dir}) + VTK_LOAD_SINGLE_CMAKE_EXTENSION(VTK_WRAP_PYTHON2 ${ext_dir}) + VTK_LOAD_SINGLE_CMAKE_EXTENSION(VTK_WRAP_JAVA2 ${ext_dir}) + VTK_LOAD_SINGLE_CMAKE_EXTENSION(VTK_GENERATE_JAVA_DEPENDENCIES ${ext_dir}) + MESSAGE(STATUS "Loading VTK CMake commands - done") + ENDIF (VTK_NEED_LOADED_COMMANDS) +ENDMACRO(VTK_LOAD_CMAKE_EXTENSIONS) diff --git a/CMake/vtkMakeInstantiator.cmake b/CMake/vtkMakeInstantiator.cmake new file mode 100644 index 0000000..05584f8 --- /dev/null +++ b/CMake/vtkMakeInstantiator.cmake @@ -0,0 +1,115 @@ +# +# a cmake implementation of the Wrap Tcl command +# + +# VTK_MAKE_INSTANTIATOR(className +# outSourceList +# src-list1 +# EXPORT_MACRO +# HEADER_LOCATION +# INCLUDES) +# +# Generates a new class with the given name and adds its files to the +# given outSourceList. It registers the classes from the other given +# source lists with vtkInstantiator when it is loaded. The output +# source list should be added to the library with the classes it +# registers. +# The EXPORT_MACRO argument must be given and followed by the export +# macro to use when generating the class (ex. VTK_COMMON_EXPORT). +# The HEADER_LOCATION option must be followed by a path. It specifies +# the directory in which to place the generated class's header file. +# The generated class implementation files always go in the build +# directory corresponding to the CMakeLists.txt file containing +# the command. This is the default location for the header. +# The INCLUDES option can be followed by a list of zero or more files. +# These files will be #included by the generated instantiator header, +# and can be used to gain access to the specified exportMacro in the +# C++ code. + +MACRO(VTK_MAKE_INSTANTIATOR3 className outSourceList SOURCES EXPORT_MACRO HEADER_LOCATION INCLUDES) + + # Initialize local variables + SET(HEADER_CONTENTS) + SET(CXX_CONTENTS) + SET(CXX_CONTENTS2) + SET(CXX_CONTENTS3) + + # make the arguments available to the configured files + SET (VTK_MAKE_INSTANTIATOR_CLASS_NAME ${className}) + SET (VTK_MAKE_INSTANTIATOR_EXPORT_MACRO ${EXPORT_MACRO}) + + # For each include + FOREACH(FILE ${INCLUDES}) + # generate the header + SET (HEADER_CONTENTS + "${HEADER_CONTENTS}#include \"${FILE}\"\n") + ENDFOREACH(FILE) + + # For each class + FOREACH(FILE ${SOURCES}) + + # should we wrap the file? + SET (WRAP_THIS_CLASS 1) + GET_SOURCE_FILE_PROPERTY(TMP_WRAP_EXCLUDE ${FILE} WRAP_EXCLUDE) + GET_SOURCE_FILE_PROPERTY(TMP_ABSTRACT ${FILE} ABSTRACT) + + # if it is abstract or wrap exclude then don't wrap it + IF (TMP_WRAP_EXCLUDE OR TMP_ABSTRACT) + SET (WRAP_THIS_CLASS 0) + ENDIF (TMP_WRAP_EXCLUDE OR TMP_ABSTRACT) + + # don't wrap vtkIndent or vtkTimeStamp + IF (${FILE} MATCHES "vtkIndent") + SET (WRAP_THIS_CLASS 0) + ENDIF (${FILE} MATCHES "vtkIndent") + IF (${FILE} MATCHES "vtkTimeStamp") + SET (WRAP_THIS_CLASS 0) + ENDIF (${FILE} MATCHES "vtkTimeStamp") + + # finally if we should wrap it, then ... + IF (WRAP_THIS_CLASS) + + # what is the filename without the extension + GET_FILENAME_COMPONENT(TMP_FILENAME ${FILE} NAME_WE) + + # generate the implementation + SET (CXX_CONTENTS + "${CXX_CONTENTS}extern vtkObject* vtkInstantiator${TMP_FILENAME}New();\n") + + SET (CXX_CONTENTS2 + "${CXX_CONTENTS2} vtkInstantiator::RegisterInstantiator(\"${TMP_FILENAME}\", vtkInstantiator${TMP_FILENAME}New);\n") + + SET (CXX_CONTENTS3 + "${CXX_CONTENTS3} vtkInstantiator::UnRegisterInstantiator(\"${TMP_FILENAME}\", vtkInstantiator${TMP_FILENAME}New);\n") + + ENDIF (WRAP_THIS_CLASS) + ENDFOREACH(FILE) + + # add the source file to the source list + SET(${outSourceList} ${${outSourceList}} + ${CMAKE_CURRENT_BINARY_DIR}/${className}.cxx) + + SET_SOURCE_FILES_PROPERTIES( + ${CMAKE_CURRENT_BINARY_DIR}/${className}.cxx + PROPERTIES GENERATED 1 WRAP_EXCLUDE 1 ABSTRACT 0 + ) + + + IF (NOT VTK_CMAKE_DIR) + SET(VTK_CMAKE_DIR ${VTK_SOURCE_DIR}/CMake) + ENDIF (NOT VTK_CMAKE_DIR) + + CONFIGURE_FILE( + ${VTK_CMAKE_DIR}/vtkMakeInstantiator.h.in + ${HEADER_LOCATION}/${className}.h + COPY_ONLY + IMMEDIATE + ) + CONFIGURE_FILE( + ${VTK_CMAKE_DIR}/vtkMakeInstantiator.cxx.in + ${CMAKE_CURRENT_BINARY_DIR}/${className}.cxx + COPY_ONLY + IMMEDIATE + ) + +ENDMACRO(VTK_MAKE_INSTANTIATOR3) diff --git a/CMake/vtkMakeInstantiator.cxx.in b/CMake/vtkMakeInstantiator.cxx.in new file mode 100644 index 0000000..c89dcd4 --- /dev/null +++ b/CMake/vtkMakeInstantiator.cxx.in @@ -0,0 +1,38 @@ +#include "@VTK_MAKE_INSTANTIATOR_CLASS_NAME@.h" + +@CXX_CONTENTS@ + + +void @VTK_MAKE_INSTANTIATOR_CLASS_NAME@::ClassInitialize() +{ + +@CXX_CONTENTS2@ + +} + +void @VTK_MAKE_INSTANTIATOR_CLASS_NAME@::ClassFinalize() +{ + +@CXX_CONTENTS3@ + +} + +@VTK_MAKE_INSTANTIATOR_CLASS_NAME@::@VTK_MAKE_INSTANTIATOR_CLASS_NAME@() +{ + if(++@VTK_MAKE_INSTANTIATOR_CLASS_NAME@::Count == 1) + { + @VTK_MAKE_INSTANTIATOR_CLASS_NAME@::ClassInitialize(); + } +} + +@VTK_MAKE_INSTANTIATOR_CLASS_NAME@::~@VTK_MAKE_INSTANTIATOR_CLASS_NAME@() +{ + if(--@VTK_MAKE_INSTANTIATOR_CLASS_NAME@::Count == 0) + { + @VTK_MAKE_INSTANTIATOR_CLASS_NAME@::ClassFinalize(); + } +} + +// Number of translation units that include this class's header. +// Purposely not initialized. Default is static initialization to 0. +unsigned int @VTK_MAKE_INSTANTIATOR_CLASS_NAME@::Count; diff --git a/CMake/vtkMakeInstantiator.h.in b/CMake/vtkMakeInstantiator.h.in new file mode 100644 index 0000000..415a072 --- /dev/null +++ b/CMake/vtkMakeInstantiator.h.in @@ -0,0 +1,21 @@ +#ifndef __@VTK_MAKE_INSTANTIATOR_CLASS_NAME@_h +#define __@VTK_MAKE_INSTANTIATOR_CLASS_NAME@_h + +#include "vtkInstantiator.h" + +@HEADER_CONTENTS@ + +class @VTK_MAKE_INSTANTIATOR_EXPORT_MACRO@ @VTK_MAKE_INSTANTIATOR_CLASS_NAME@ +{ + public: + @VTK_MAKE_INSTANTIATOR_CLASS_NAME@(); + ~@VTK_MAKE_INSTANTIATOR_CLASS_NAME@(); + private: + static void ClassInitialize(); + static void ClassFinalize(); + static unsigned int Count; +}; + +static @VTK_MAKE_INSTANTIATOR_CLASS_NAME@ @VTK_MAKE_INSTANTIATOR_CLASS_NAME@Initializer; + +#endif diff --git a/CMake/vtkSelectSharedLibraries.cmake b/CMake/vtkSelectSharedLibraries.cmake new file mode 100644 index 0000000..a0c3db4 --- /dev/null +++ b/CMake/vtkSelectSharedLibraries.cmake @@ -0,0 +1,67 @@ +IF(NOT VTK_SHARED_LIBRARIES_SELECTED) + SET(VTK_SHARED_LIBRARIES_SELECTED 1) + + # We need the VTK_DEPENDENT_OPTION macro. + INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkDependentOption.cmake) + + # Choose static or shared libraries. + OPTION(BUILD_SHARED_LIBS "Build VTK with shared libraries." OFF) + SET(VTK_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) + + # On platforms that support rpath users may want to use them to make + # running VTK from the build tree easy. It is not safe to install + # programs built with an rpath pointing at the build tree, so we must + # disable install support when using the rpath feature. + IF(NOT WIN32) + # Choose whether to use the rpath feature. Parent projects may + # set VTK_FORCE_RPATH to force the value on or off without providing + # the option. + IF(VTK_FORCE_RPATH) + SET(VTK_USE_RPATH ${VTK_FORCE_RPATH}) + ELSE(VTK_FORCE_RPATH) + IF("VTK_USE_RPATH_DEFAULT" MATCHES "^VTK_USE_RPATH_DEFAULT$") + # Choosing a default value for this option is tricky. Dashboard + # scripts need to have this ON or set the LD_LIBRARY_PATH, which at + # the time of this writing none does. Therefore the default must be + # ON. However, users that download a VTK release to build and install + # it will not know to turn this OFF and will be confused when they get + # an empty installation. One solution to this dilema is to note that + # users that do not know what they are doing will generally use a + # release. Dashboards use the latest development version. Users that + # checkout from the CVS head will usually run from the build tree or + # at least understand this option. Therefore a simple decision + # criterion is whether VTK_MINOR_VERSION is odd or even. + IF(VTK_MINOR_VERSION MATCHES "[02468]$") + # This is a release version. Default to not use rpath. + SET(VTK_USE_RPATH_DEFAULT OFF) + ELSE(VTK_MINOR_VERSION MATCHES "[02468]$") + # This is a development version. Default to use rpath. + SET(VTK_USE_RPATH_DEFAULT ON) + ENDIF(VTK_MINOR_VERSION MATCHES "[02468]$") + ENDIF("VTK_USE_RPATH_DEFAULT" MATCHES "^VTK_USE_RPATH_DEFAULT$") + VTK_DEPENDENT_OPTION(VTK_USE_RPATH "Build shared libraries with rpath. This makes it easy to run executables from the build tree when using shared libraries, but removes install support." + ${VTK_USE_RPATH_DEFAULT} + "BUILD_SHARED_LIBS" OFF) + ENDIF(VTK_FORCE_RPATH) + + # Configure VTK according to the rpath setting. + IF(VTK_USE_RPATH) + # We will use rpath support. Tell CMake not to skip it. + SET(CMAKE_SKIP_RPATH 0 CACHE INTERNAL "Whether to build with rpath." FORCE) + + # If someone is trying to install do not do an entire build with + # the wrong rpath feature setting just to report failed + # installation. + SET(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 1) + + # Add a dummy target and attach an install rule that will always fail + # and produce a message explaining why installation is disabled. + ADD_CUSTOM_TARGET(vtk_install_disabled) + SET_TARGET_PROPERTIES(vtk_install_disabled PROPERTIES + PRE_INSTALL_SCRIPT ${VTK_SOURCE_DIR}/CMake/InstallDisabled.cmake) + ELSE(VTK_USE_RPATH) + # We will not use rpath support. Tell CMake to skip it. + SET(CMAKE_SKIP_RPATH 1 CACHE INTERNAL "Whether to build with rpath." FORCE) + ENDIF(VTK_USE_RPATH) + ENDIF(NOT WIN32) +ENDIF(NOT VTK_SHARED_LIBRARIES_SELECTED) diff --git a/CMake/vtkSelectStreamsLibrary.cmake b/CMake/vtkSelectStreamsLibrary.cmake new file mode 100644 index 0000000..43e2eb5 --- /dev/null +++ b/CMake/vtkSelectStreamsLibrary.cmake @@ -0,0 +1,62 @@ +# Include CHECK_INCLUDE_FILE_CXX macro used by this macro. +INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFileCXX.cmake) + +#----------------------------------------------------------------------------- +# Macro to select whether to use old streams or ANSI streams. +# Argument is the variable to set with the result (VTK_USE_ANSI_STDLIB). +MACRO(VTK_SELECT_STREAMS_LIBRARY var VTK_SOURCE_DIR) + IF("${var}" MATCHES "^${var}$") + CHECK_INCLUDE_FILE_CXX("iosfwd" VTK_HAVE_ANSI_STREAMS) + CHECK_INCLUDE_FILE_CXX("iostream.h" VTK_HAVE_OLD_STREAMS) + IF(VTK_HAVE_OLD_STREAMS) + # Some compilers have iostream.h but not strstream.h + # or strstrea.h. Treat these as not having old streams. + CHECK_INCLUDE_FILE_CXX("strstrea.h" VTK_HAVE_OLD_STRSTREA_H) + CHECK_INCLUDE_FILE_CXX("strstream.h" VTK_HAVE_OLD_STRSTREAM_H) + IF(NOT VTK_HAVE_OLD_STRSTREAM_H) + IF(NOT VTK_HAVE_OLD_STRSTREA_H) + SET(VTK_HAVE_OLD_STREAMS 0) + ENDIF(NOT VTK_HAVE_OLD_STRSTREA_H) + ENDIF(NOT VTK_HAVE_OLD_STRSTREAM_H) + ENDIF(VTK_HAVE_OLD_STREAMS) + + IF(VTK_HAVE_ANSI_STREAMS AND VTK_HAVE_OLD_STREAMS) + # Have both old and new streams. Provide the option. + # Default to OFF for MSVC 6 and ON for all others. + SET(${var}_DEFAULT ON) + IF(NOT CMAKE_COMPILER_IS_GNUCXX) + IF("VTK_COMPILER_IS_VC6" MATCHES "^VTK_COMPILER_IS_VC6$") + MESSAGE(STATUS "Checking if compiler is VC6") + TRY_COMPILE(VTK_COMPILER_IS_VC6 + ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestCompilerIsVC6.cxx + OUTPUT_VARIABLE OUTPUT) + IF(VTK_COMPILER_IS_VC6) + MESSAGE(STATUS "Checking if compiler is VC6 -- yes") + SET(VTK_COMPILER_IS_VC6 1 CACHE INTERNAL "Compiler is MSVC 6") + ELSE(VTK_COMPILER_IS_VC6) + MESSAGE(STATUS "Checking if compiler is VC6 -- no") + SET(VTK_COMPILER_IS_VC6 0 CACHE INTERNAL "Compiler is MSVC 6") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining if the compiler is MSVC 6 " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_COMPILER_IS_VC6) + ENDIF("VTK_COMPILER_IS_VC6" MATCHES "^VTK_COMPILER_IS_VC6$") + IF(VTK_COMPILER_IS_VC6) + SET(${var}_DEFAULT OFF) + ENDIF(VTK_COMPILER_IS_VC6) + ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX) + OPTION(${var} "Use the ANSI standard iostream library." ${${var}_DEFAULT}) + MARK_AS_ADVANCED(${var}) + ELSE(VTK_HAVE_ANSI_STREAMS AND VTK_HAVE_OLD_STREAMS) + IF(VTK_HAVE_ANSI_STREAMS) + # Have only new streams. Use them. + SET(${var} ON) + ELSE(VTK_HAVE_ANSI_STREAMS) + # Have only old streams. Use them. + SET(${var} OFF) + ENDIF(VTK_HAVE_ANSI_STREAMS) + ENDIF(VTK_HAVE_ANSI_STREAMS AND VTK_HAVE_OLD_STREAMS) + ENDIF("${var}" MATCHES "^${var}$") +ENDMACRO(VTK_SELECT_STREAMS_LIBRARY var) diff --git a/CMake/vtkTclTkMacros.cmake b/CMake/vtkTclTkMacros.cmake new file mode 100644 index 0000000..fb8d99c --- /dev/null +++ b/CMake/vtkTclTkMacros.cmake @@ -0,0 +1,259 @@ +# ---------------------------------------------------------------------------- +# VTK_GET_TCL_TK_VERSION +# Return the major/minor version of the Tcl/Tk library used by VTK. +# +# in: tcl_tk_major_version: name of the var the major version is written to +# tcl_tk_minor_version: name of the var the minor version is written to +# +# ex: VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") +# SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + +MACRO (VTK_GET_TCL_TK_VERSION tcl_tk_major_version tcl_tk_minor_version) + + # Try to find the current Tcl/Tk version by matching TK_INTERNAL_PATH + # or TCL_LIBRARY against some version numbers + + SET (${tcl_tk_major_version} "") + SET (${tcl_tk_minor_version} "") + IF (TK_INTERNAL_PATH) + SET (try_tk_internal_path ${TK_INTERNAL_PATH}) + ELSE (TK_INTERNAL_PATH) + SET (try_tk_internal_path ${VTK_TK_INTERNAL_DIR}) + ENDIF (TK_INTERNAL_PATH) + FOREACH (tcl_tk_minor_version_try "2" "3" "4") + IF ("${try_tk_internal_path}" MATCHES "tk8\\.?${tcl_tk_minor_version_try}") + SET (${tcl_tk_major_version} "8") + SET (${tcl_tk_minor_version} ${tcl_tk_minor_version_try}) + ENDIF ("${try_tk_internal_path}" MATCHES "tk8\\.?${tcl_tk_minor_version_try}") + IF ("${TCL_LIBRARY}" MATCHES "tcl8\\.?${tcl_tk_minor_version_try}") + SET (${tcl_tk_major_version} "8") + SET (${tcl_tk_minor_version} ${tcl_tk_minor_version_try}) + ENDIF ("${TCL_LIBRARY}" MATCHES "tcl8\\.?${tcl_tk_minor_version_try}") + IF ("${TCL_INCLUDE_PATH}" MATCHES "tcl8\\.?${tcl_tk_minor_version_try}") + SET (${tcl_tk_major_version} "8") + SET (${tcl_tk_minor_version} ${tcl_tk_minor_version_try}) + ENDIF ("${TCL_INCLUDE_PATH}" MATCHES "tcl8\\.?${tcl_tk_minor_version_try}") + # Mac + IF ("${TCL_INCLUDE_PATH}" MATCHES "Tcl.*8\\.${tcl_tk_minor_version_try}") + SET (${tcl_tk_major_version} "8") + SET (${tcl_tk_minor_version} ${tcl_tk_minor_version_try}) + ENDIF ("${TCL_INCLUDE_PATH}" MATCHES "Tcl.*8\\.${tcl_tk_minor_version_try}") + ENDFOREACH (tcl_tk_minor_version_try) + + FOREACH(dir ${TCL_INCLUDE_PATH}) + IF(EXISTS "${dir}/tcl.h") + FILE(READ "${TCL_INCLUDE_PATH}/tcl.h" tcl_include_file) + STRING(REGEX REPLACE + ".*#define TCL_VERSION[ \t]*\"([0-9][0-9]*\\.[0-9][0-9]*)\".*" "\\1" + tcl_include_file "${tcl_include_file}") + IF(${tcl_include_file} MATCHES "^[0-9]*\\.[0-9]*$") + STRING(REGEX REPLACE "^([0-9]*)\\.([0-9]*)$" "\\1" "${tcl_tk_major_version}" + "${tcl_include_file}") + STRING(REGEX REPLACE "^([0-9]*)\\.([0-9]*)$" "\\2" "${tcl_tk_minor_version}" + "${tcl_include_file}") + ENDIF(${tcl_include_file} MATCHES "^[0-9]*\\.[0-9]*$") + ENDIF(EXISTS "${dir}/tcl.h") + ENDFOREACH(dir) + +ENDMACRO (VTK_GET_TCL_TK_VERSION) + +# ---------------------------------------------------------------------------- +# VTK_GET_TCL_SUPPORT_FILES, VTK_GET_TK_SUPPORT_FILES +# Get a list of Tcl/Tk support files for a given Tcl/Tk repository. +# Tcl/Tk support files are additional files that are mandatory for Tcl/Tk +# to work properly. Linking against Tcl/Tk shared/static library is just +# not enough, Tcl/Tk needs to access those files at run-time. +# A typical Tcl/Tk installation will store support files in sub-directories +# inside the Tcl/Tk lib directory, organized by version number. +# Example: +# c:/tcl/lib/tcl8.4 +# c:/tcl/lib/tcl8.3 +# c:/tcl/lib/tk8.4 +# c:/tcl/lib/tk8.3 +# A typical source repository is organized differently: +# c:/tcl8.4.5/library +# c:/tk8.4.5/library +# Given the path to the Tcl support lib dir, VTK_GET_TCL_SUPPORT_FILES will +# return the corresponding list of support files. +# Given the path to the Tk support lib dir, VTK_GET_TK_SUPPORT_FILES will +# return the corresponding list of support files. +# +# in: support_lib_dir: path to the Tcl (or Tk) support lib dir +# list: name of the var the list is written to + +MACRO (VTK_GET_TCL_SUPPORT_FILES tcl_support_lib_dir list) + + # Tcl support files (*.tcl + encoding + tclIndex, etc.) + + FILE (GLOB TCL_SUPPORT_FILES_TCL "${tcl_support_lib_dir}/*.tcl") + FILE (GLOB TCL_SUPPORT_FILES_ENC "${tcl_support_lib_dir}/encoding/*.enc") + SET (${list} + "${tcl_support_lib_dir}/tclIndex" + ${TCL_SUPPORT_FILES_TCL} + ${TCL_SUPPORT_FILES_ENC}) + +ENDMACRO (VTK_GET_TCL_SUPPORT_FILES) + +MACRO (VTK_GET_TK_SUPPORT_FILES tk_support_lib_dir list) + + # Tk support files (*.tcl + tclIndex, etc.) + + FILE (GLOB TK_SUPPORT_FILES_TCL "${tk_support_lib_dir}/*.tcl") + SET (${list} + "${tk_support_lib_dir}/tclIndex" + ${TK_SUPPORT_FILES_TCL}) + +ENDMACRO (VTK_GET_TK_SUPPORT_FILES) + +# ---------------------------------------------------------------------------- +# VTK_COPY_TCL_TK_SUPPORT_FILES +# Copy (or install) Tcl/Tk support files to a specific location. +# See VTK_GET_TCL_SUPPORT_FILES for more info about support files. +# Given the paths to the Tcl and Tk support lib dirs, this macro will +# copy (or install) the appropriate support files to destination dirs, +# recreating the subdirs. +# This macro takes an optional last parameter, if set to INSTALL the +# files will be scheduled for installation (using CMake's INSTALL_FILES) +# instead of copied. +# +# in: tcl_support_lib_dir: path to the Tcl support lib dir +# tcl_support_lib_dest: destination dir for the Tcl support lib files +# tk_support_lib_dir: path to the Tk support lib dir +# tk_support_lib_dest: destination dir for the Tk support lib files +# INSTALL: optional parameter (install files instead of copy) +# +# ex: VTK_COPY_TCL_TK_SUPPORT_FILES ( +# "c:/tcl/lib/tcl8.4" "d:/vtk-bin/TclTk/lib/tcl8.4" +# "c:/tcl/lib/tk8.4" "d:/vtk-bin/TclTk/lib/tk8.4") +# this will copy support files from: +# c:/tcl/lib/tcl8.4 +# c:/tcl/lib/tk8.4 +# to: +# d:/vtk-bin/TclTk/lib/tcl8.4 +# d:/vtk-bin/TclTk/lib/tk8.4 + +MACRO (VTK_COPY_TCL_TK_SUPPORT_FILES tcl_support_lib_dir tcl_support_lib_dest tk_support_lib_dir tk_support_lib_dest) + + # Get the support files and copy them to dest dir + # Check if EXISTS to work around CONFIGURE_FILE bug (if file does not + # exist, it would create the subdirs anyway) + + VTK_GET_TCL_SUPPORT_FILES(${tcl_support_lib_dir} "TCL_SUPPORT_FILES") + FOREACH (file ${TCL_SUPPORT_FILES}) + IF (EXISTS ${file}) + STRING (REGEX REPLACE "${tcl_support_lib_dir}/" "" filebase ${file}) + IF ("${ARGV4}" STREQUAL "INSTALL") + GET_FILENAME_COMPONENT(dir ${filebase} PATH) + INSTALL_FILES ("${tcl_support_lib_dest}/${dir}" FILES ${file}) + ELSE ("${ARGV4}" STREQUAL "INSTALL") + CONFIGURE_FILE (${file} "${tcl_support_lib_dest}/${filebase}" COPYONLY) + ENDIF ("${ARGV4}" STREQUAL "INSTALL") + ENDIF (EXISTS ${file}) + ENDFOREACH (file) + + VTK_GET_TK_SUPPORT_FILES(${tk_support_lib_dir} "TK_SUPPORT_FILES") + FOREACH (file ${TK_SUPPORT_FILES}) + IF (EXISTS ${file}) + STRING (REGEX REPLACE "${tk_support_lib_dir}/" "" filebase ${file}) + IF ("${ARGV4}" STREQUAL "INSTALL") + GET_FILENAME_COMPONENT(dir ${filebase} PATH) + INSTALL_FILES ("${tk_support_lib_dest}/${dir}" FILES ${file}) + ELSE ("${ARGV4}" STREQUAL "INSTALL") + CONFIGURE_FILE (${file} "${tk_support_lib_dest}/${filebase}" COPYONLY) + ENDIF ("${ARGV4}" STREQUAL "INSTALL") + ENDIF (EXISTS ${file}) + ENDFOREACH (file) + +ENDMACRO (VTK_COPY_TCL_TK_SUPPORT_FILES) + +# ---------------------------------------------------------------------------- +# VTK_COPY_TCL_TK_SUPPORT_FILES_TO_DIR +# Front-end to VTK_COPY_TCL_TK_SUPPORT_FILES, this macro will +# copy (or install) the appropriate Tcl/Tk support files to a directory. +# The Tcl/Tk version is retrieved automatically and used to create +# the subdirectories (see example below) +# This macro takes an optional last parameter, if set to INSTALL the +# files will be scheduled for installation (using CMake's INSTALL_FILES) +# instead of copied. +# +# in: tcl_support_lib_dir: path to the Tcl support lib dir +# tk_support_lib_dir: path to the Tk support lib dir +# target_dir: target directory +# INSTALL: optional parameter (install files instead of copy) +# +# ex: VTK_COPY_TCL_TK_SUPPORT_FILES_TO_DIR ( +# "c:/tcl/lib/tcl8.4" "c:/tcl/lib/tk8.4" "d:/vtk-bin/lib") +# if this project is configured to use TclTk 8.4, this will copy support +# files from: +# c:/tcl/lib/tcl8.4 +# c:/tcl/lib/tk8.4 +# to: +# d:/vtk-bin/lib/tcl8.4 +# d:/vtk-bin/lib/tk8.4 + +MACRO (VTK_COPY_TCL_TK_SUPPORT_FILES_TO_DIR tcl_support_lib_dir tk_support_lib_dir target_dir) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + IF (TCL_TK_MAJOR_VERSION AND TCL_TK_MINOR_VERSION) + SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + VTK_COPY_TCL_TK_SUPPORT_FILES ( + "${tcl_support_lib_dir}" + "${target_dir}/tcl${TCL_TK_VERSION}" + "${tk_support_lib_dir}" + "${target_dir}/tk${TCL_TK_VERSION}" + "${ARGV3}" + ) + ENDIF (TCL_TK_MAJOR_VERSION AND TCL_TK_MINOR_VERSION) + +ENDMACRO (VTK_COPY_TCL_TK_SUPPORT_FILES_TO_DIR) + +# ---------------------------------------------------------------------------- +# VTK_COPY_TCL_TK_SUPPORT_FILES_TO_BUILD_DIR +# Front-end to VTK_COPY_TCL_TK_SUPPORT_FILES_TO_DIR, this macro will copy the +# appropriate Tcl/Tk support files to a project build directory. +# The support files will be copied simultaneously to all configuration +# sub-directories (Release, RelInfo, Debug, etc.) if needed. +# The Tcl/Tk version is retrieved automatically and used to create +# the subdirectories (see example below) +# +# in: tcl_support_lib_dir: path to the Tcl support lib dir +# tk_support_lib_dir: path to the Tk support lib dir +# build_dir: project build dir +# dir: relative subdir inside the build dir, into which the +# support files will be copied. +# +# ex: VTK_COPY_TCL_TK_SUPPORT_FILES_TO_BUILD_DIR ( +# "c:/tcl/lib/tcl8.4" "c:/tcl/lib/tk8.4" "d:/vtk-bin" "TclTk/lib") +# if this project is configured to use TclTk 8.4, this will copy support +# files from: +# c:/tcl/lib/tcl8.4 +# c:/tcl/lib/tk8.4 +# to: +# d:/vtk-bin/TclTk/lib/tcl8.4 +# d:/vtk-bin/TclTk/lib/tk8.4 +# or (if configuration types are supported by the generator): +# d:/vtk-bin/Release/TclTk/lib/tcl8.4 +# d:/vtk-bin/Release/TclTk/lib/tk8.4 +# d:/vtk-bin/Debug/TclTk/lib/tcl8.4 +# d:/vtk-bin/Debug/TclTk/lib/tk8.4 +# etc. + +MACRO (VTK_COPY_TCL_TK_SUPPORT_FILES_TO_BUILD_DIR tcl_support_lib_dir tk_support_lib_dir build_dir dir) + + # For each configuration type (Debug, RelInfo, Release, etc.) + # Copy the TclTk support files to the corresponding sub-directory inside + # the build dir + + IF (CMAKE_CONFIGURATION_TYPES) + SET (CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) + ELSE (CMAKE_CONFIGURATION_TYPES) + SET (CONFIG_TYPES .) + ENDIF (CMAKE_CONFIGURATION_TYPES) + FOREACH (config ${CONFIG_TYPES}) + VTK_COPY_TCL_TK_SUPPORT_FILES_TO_DIR ( + "${tcl_support_lib_dir}" + "${tk_support_lib_dir}" + "${build_dir}/${config}/${dir}" + ) + ENDFOREACH (config) + +ENDMACRO (VTK_COPY_TCL_TK_SUPPORT_FILES_TO_BUILD_DIR) diff --git a/CMake/vtkTestBoolType.cxx b/CMake/vtkTestBoolType.cxx new file mode 100644 index 0000000..bfc1e5e --- /dev/null +++ b/CMake/vtkTestBoolType.cxx @@ -0,0 +1,9 @@ +// Minimal test for existence of "bool" type. +void TestBool(bool) {} + +int main() +{ + TestBool(false); + TestBool(true); + return 0; +} diff --git a/CMake/vtkTestCharSignedness.cxx b/CMake/vtkTestCharSignedness.cxx new file mode 100644 index 0000000..a25633c --- /dev/null +++ b/CMake/vtkTestCharSignedness.cxx @@ -0,0 +1,6 @@ +/* Return 1 for char signed and 0 for char unsigned. */ +int main() +{ + unsigned char uc = 255; + return (*reinterpret_cast(&uc) < 0)?1:0; +} diff --git a/CMake/vtkTestCompareTypes.cxx b/CMake/vtkTestCompareTypes.cxx new file mode 100644 index 0000000..bb06c89 --- /dev/null +++ b/CMake/vtkTestCompareTypes.cxx @@ -0,0 +1,28 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestCompareTypes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#define TYPE_LONG_LONG long long + +typedef VTK_TEST_COMPARE_TYPE_1 Type1; +typedef VTK_TEST_COMPARE_TYPE_2 Type2; + +void function(Type1**) {} + +int main() +{ + Type2** p = 0; + function(p); + return 0; +} diff --git a/CMake/vtkTestCompilerIsVC6.cxx b/CMake/vtkTestCompilerIsVC6.cxx new file mode 100644 index 0000000..a75b573 --- /dev/null +++ b/CMake/vtkTestCompilerIsVC6.cxx @@ -0,0 +1,7 @@ +/* Compile if this is MSVC 6. */ +#if defined(_MSC_VER) && (_MSC_VER == 1200) +int main() +{ + return 0; +} +#endif diff --git a/CMake/vtkTestConvertTypes.cxx b/CMake/vtkTestConvertTypes.cxx new file mode 100644 index 0000000..81887be --- /dev/null +++ b/CMake/vtkTestConvertTypes.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestConvertTypes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#define TYPE_UNSIGNED___INT64 unsigned __int64 + +typedef VTK_TEST_CONVERT_TYPE_TO TypeTo; +typedef VTK_TEST_CONVERT_TYPE_FROM TypeFrom; + +void function(TypeTo& l, TypeFrom const& r) +{ + l = static_cast(r); +} + +int main() +{ + TypeTo tTo = TypeTo(); + TypeFrom tFrom = TypeFrom(); + function(tTo, tFrom); + return 0; +} diff --git a/CMake/vtkTestExplicitInstantiation.cmake b/CMake/vtkTestExplicitInstantiation.cmake new file mode 100644 index 0000000..ae0bbea --- /dev/null +++ b/CMake/vtkTestExplicitInstantiation.cmake @@ -0,0 +1,56 @@ +# Test whether the compiler supports explicit template instantiation. +# This actually creates a class template instantiation in one source +# file and tries to use it from another. This approach checks that +# both the instantiation syntax and symbol linkage is handled +# properly. +IF("VTK_EXPLICIT_TEMPLATES" MATCHES "^VTK_EXPLICIT_TEMPLATES") + MESSAGE(STATUS "Checking support for C++ explicit template instantiation") + + MAKE_DIRECTORY(${VTK_BINARY_DIR}/CMakeTmp/TestExplicitInstantiation) + STRING(ASCII 35 POUND) + WRITE_FILE( + ${VTK_BINARY_DIR}/CMakeTmp/TestExplicitInstantiation/CMakeLists.txt + "PROJECT(EXPLICIT)\n" + "ADD_LIBRARY(A A.cxx)\n" + "ADD_EXECUTABLE(B B.cxx)\n" + "TARGET_LINK_LIBRARIES(B A)\n" + ) + WRITE_FILE( + ${VTK_BINARY_DIR}/CMakeTmp/TestExplicitInstantiation/A.h + "${POUND}ifndef A_h\n" + "${POUND}define A_h\n" + "template class A { public: static T Method(); };\n" + "${POUND}endif\n" + ) + WRITE_FILE( + ${VTK_BINARY_DIR}/CMakeTmp/TestExplicitInstantiation/A.cxx + "${POUND}include \"A.h\"\n" + "template T A::Method() { return 0; }\n" + "template class A;" + ) + WRITE_FILE( + ${VTK_BINARY_DIR}/CMakeTmp/TestExplicitInstantiation/B.cxx + "${POUND}include \"A.h\"\n" + "int main() { return A::Method(); }\n" + ) + TRY_COMPILE(VTK_EXPLICIT_TEMPLATES + ${VTK_BINARY_DIR}/CMakeTmp/TestExplicitInstantiation/Build + ${VTK_BINARY_DIR}/CMakeTmp/TestExplicitInstantiation + EXPLICIT OUTPUT_VARIABLE OUTPUT + ) + IF(VTK_EXPLICIT_TEMPLATES) + MESSAGE(STATUS "Checking support for C++ explicit template instantiation -- yes") + SET(VTK_EXPLICIT_TEMPLATES 1 CACHE INTERNAL "Support for C++ explict templates") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining if the C++ compiler supports explict template instantiation " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_EXPLICIT_TEMPLATES) + MESSAGE(STATUS "Checking support for C++ explicit template instantiation -- no") + SET(VTK_EXPLICIT_TEMPLATES 0 CACHE INTERNAL "Support for C++ explict templates") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining if the C++ compiler supports explict template instantiation " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_EXPLICIT_TEMPLATES) +ENDIF("VTK_EXPLICIT_TEMPLATES" MATCHES "^VTK_EXPLICIT_TEMPLATES") diff --git a/CMake/vtkTestFullSpecialization.cxx b/CMake/vtkTestFullSpecialization.cxx new file mode 100644 index 0000000..862683b --- /dev/null +++ b/CMake/vtkTestFullSpecialization.cxx @@ -0,0 +1,6 @@ +template struct A {}; +template <> struct A +{ + static int f() { return 0; } +}; +int main() { return A::f(); } diff --git a/CMake/vtkTestMPI_LONG_LONG.cxx b/CMake/vtkTestMPI_LONG_LONG.cxx new file mode 100644 index 0000000..2e832eb --- /dev/null +++ b/CMake/vtkTestMPI_LONG_LONG.cxx @@ -0,0 +1,13 @@ +// Minimal test for existence of MPI_LONG_LONG + +#include "mpi.h" +MPI_Datatype vtkMPICommunicatorGetMPIType() +{ + return MPI_LONG_LONG; +} + +int main() +{ + vtkMPICommunicatorGetMPIType(); + return 0; +} diff --git a/CMake/vtkTestSGIstdarg.cxx b/CMake/vtkTestSGIstdarg.cxx new file mode 100644 index 0000000..92f90b1 --- /dev/null +++ b/CMake/vtkTestSGIstdarg.cxx @@ -0,0 +1,6 @@ +#if defined(_COMPILER_VERSION) && _COMPILER_VERSION == 742 +# include +#endif +#include +void f(const char*, va_list); +int main() { return 0; } diff --git a/CMake/vtkTestSocklenT.cxx b/CMake/vtkTestSocklenT.cxx new file mode 100644 index 0000000..f3ee7ed --- /dev/null +++ b/CMake/vtkTestSocklenT.cxx @@ -0,0 +1,14 @@ +#include +#include +#if !defined(_WIN32) || defined(__CYGWIN__) +# include +# include +#endif + +int main() +{ + /* Test whether getsockname takes socklen_t. */ + if(getsockname(0, 0, (socklen_t*)0)) return 0; + if(sizeof (socklen_t)) return 0; + return 0; +} diff --git a/CMake/vtkTestStreamEOF.cxx.in b/CMake/vtkTestStreamEOF.cxx.in new file mode 100644 index 0000000..7393870 --- /dev/null +++ b/CMake/vtkTestStreamEOF.cxx.in @@ -0,0 +1,139 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestStreamEOF.cxx.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// Many C++ streams libraries have buggy conditions when reading +// reaches the end of a file. When an ifstream attempts to read past +// the end of the file, the "eof" and "fail" bits are set. Clearing +// the fail bit should be enough to allow seekg() to work and tellg() +// to report the file position. Some stream libraries have bugs in +// this case. This source file tests the severity of the eof +// conditions for a compiler. +// +// Severity levels are reported in terms of the extent of the +// work-around required: +// +// 0 - No bug exists. +// 1 - User must clear eof bit. +// 2 - User must clear eof bit and re-seek to end. +// 3 - User must clear eof bit and call _M_seek_return on the filebuf. +// 126 - Could not open sample input file. +// 127 - Unknown severity level. +// +// Severity level 3 is only known to exist for -LANG:std streams on +// the SGI MIPSpro 7.30 - 7.3.1.1 compiler versions. The cause of the +// bug is a code pattern like this: +// +// _M_in_error_mode = true; +// while(!_M_in_error_mode) { _M_in_error_mode = false; } +// +// It requires directly calling a non-public member function in the +// filebuf instance on the stream to escape the bad state. +// Unfortunately there is no way to detect the patch level of the +// compiler from the preprocessor, so we need to actually try the +// call. + +#if defined(__sgi) && !defined(__GNUC__) && defined(_COMPILER_VERSION) +# if _COMPILER_VERSION == 730 +# define VTK_SGI_730 +# endif +#endif + +#if defined(_MSC_VER) +# pragma warning (push, 1) +#endif + +// Include the streams library. Hack access to SGI stream +// implementation for MIPSpro 7.3 compiler. +#cmakedefine VTK_USE_ANSI_STDLIB +#if defined(VTK_USE_ANSI_STDLIB) +# if defined(VTK_SGI_730) +# define protected public +# define private public +# endif +# include + using std::ifstream; + using std::ios; +# if defined(VTK_SGI_730) +# undef protected +# undef private +# endif +#else +# include +#endif + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +int main() +{ + const char* fname = "@VTK_TEST_STREAM_EOF_CXX@"; + + // Open the file. +#if defined(_WIN32) + ifstream fin(fname, ios::binary | ios::in); +#else + ifstream fin(fname, ios::in); +#endif + + // Make sure we opened the file. + if(!fin) + { + return 126; + } + + // Go to eof in a way that exposes the bug everywhere. + char c = 0; + fin.seekg(-1, ios::end); + while(fin.get(c)); + + // Clear the fail bit so tellg() is supposed to return something + // other than -1. + fin.clear(fin.rdstate() & ~ios::failbit); + if(fin.tellg() >= 0) + { + // Nothing is wrong with eof for this streams library. + return 0; + } + + // Some streams return -1 from tellg() if eof is set. + fin.clear(fin.rdstate() & ~ios::failbit & ~ios::eofbit); + if(fin.tellg() >= 0) + { + return 1; + } + + // Some streams still return -1 from tellg. Try seeking to get it + // out of this strange state. + fin.clear(fin.rdstate() & ~ios::failbit & ~ios::eofbit); + fin.seekg(0, ios::end); + if(fin.tellg() >= 0) + { + return 2; + } + + // Only SGI 7.30 to 7.3.1.1 is known to get this far. Try to escape + // the bad state. +#if defined(VTK_USE_ANSI_STDLIB) && defined(VTK_SGI_730) + fin.clear(fin.rdstate() & ~ios::failbit & ~ios::eofbit); + fin.rdbuf()->_M_seek_return(0, 0); + if(fin.tellg() >= 0) + { + return 3; + } +#endif + + return 127; +} diff --git a/CMake/vtkTestStreamLongLong.cxx.in b/CMake/vtkTestStreamLongLong.cxx.in new file mode 100644 index 0000000..2a877df --- /dev/null +++ b/CMake/vtkTestStreamLongLong.cxx.in @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestStreamLongLong.cxx.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#if defined(_MSC_VER) +# pragma warning (push, 1) +#endif + +// Include the streams library. +#cmakedefine VTK_USE_ANSI_STDLIB +#if defined(VTK_USE_ANSI_STDLIB) +# include +using std::ostream; +using std::istream; +using std::cout; +using std::cin; +#else +# include +#endif + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#if defined(VTK_TEST_OSTREAM_LONG_LONG) +int test_ostream(ostream& os, long long x) +{ + return (os << x)? 1:0; +} +#endif + +#if defined(VTK_TEST_ISTREAM_LONG_LONG) +int test_istream(istream& is, long long& x) +{ + return (is >> x)? 1:0; +} +#endif + +int main() +{ +#if defined(VTK_TEST_OSTREAM_LONG_LONG) + long long x = 0; + return test_ostream(cout, x); +#endif +#if defined(VTK_TEST_ISTREAM_LONG_LONG) + long long x; + return test_istream(cin, x); +#endif +} + diff --git a/CMake/vtkTestvfw32.cxx b/CMake/vtkTestvfw32.cxx new file mode 100644 index 0000000..c231535 --- /dev/null +++ b/CMake/vtkTestvfw32.cxx @@ -0,0 +1,9 @@ +#include "windows.h" +#include "vfw.h" + +int main() +{ + AVIFileInit(); + AVIFileExit(); + return 0; +} diff --git a/CMake/vtkTestvfw32Capture.cxx b/CMake/vtkTestvfw32Capture.cxx new file mode 100644 index 0000000..f094bd9 --- /dev/null +++ b/CMake/vtkTestvfw32Capture.cxx @@ -0,0 +1,46 @@ +#include "windows.h" +#include "vfw.h" + +// Can vtkWin32VideoSource.cxx be compiled? +// Test by using some of the structs in a class and +// calling some of the functions Win32VideoSource +// uses... + +class vtkWin32VideoSourceInternal +{ +public: + vtkWin32VideoSourceInternal() {} + HWND CapWnd; + HWND ParentWnd; + CAPSTATUS CapStatus; + CAPDRIVERCAPS CapDriverCaps; + CAPTUREPARMS CaptureParms; + LPBITMAPINFO BitMapPtr; +}; + +int main() +{ + vtkWin32VideoSourceInternal internal; + + internal.CapWnd = capCreateCaptureWindow( + "Capture", WS_CHILD|WS_VISIBLE, 0, 0, 100, 100, NULL, 1); + +// capDriverConnect +// capDriverGetCaps +// capCaptureGetSetup +// capCaptureSetSetup + + capSetUserData(internal.CapWnd, &internal); + +// capSetCallbackOnCapControl +// capSetCallbackOnFrame +// capSetCallbackOnVideoStream +// capSetCallbackOnStatus +// capSetCallbackOnError + + (void) capOverlay(internal.CapWnd, TRUE); + + (void) capGetUserData(internal.CapWnd); + + return 0; +} diff --git a/CMake/vtkThirdParty.cmake b/CMake/vtkThirdParty.cmake new file mode 100644 index 0000000..d354ef7 --- /dev/null +++ b/CMake/vtkThirdParty.cmake @@ -0,0 +1,53 @@ +#----------------------------------------------------------------------------- +MACRO(VTK_THIRD_PARTY_OPTION upper lower) + OPTION(VTK_USE_SYSTEM_${upper} "Use the system's ${lower} library." OFF) + MARK_AS_ADVANCED(VTK_USE_SYSTEM_${upper}) + IF(VTK_USE_SYSTEM_${upper}) + IF(EXISTS ${CMAKE_ROOT}/Modules/Find${upper}.cmake) + INCLUDE(${CMAKE_ROOT}/Modules/Find${upper}.cmake) + ELSE(EXISTS ${CMAKE_ROOT}/Modules/Find${upper}.cmake) + INCLUDE(${VTK_SOURCE_DIR}/CMake/Find${upper}.cmake) + ENDIF(EXISTS ${CMAKE_ROOT}/Modules/Find${upper}.cmake) + MARK_AS_ADVANCED(${upper}_INCLUDE_DIR ${upper}_LIBRARY) + IF(${upper}_FOUND) + SET(VTK_${upper}_LIBRARIES ${${upper}_LIBRARIES}) + IF("${upper}" MATCHES "^PNG$") + SET(PNG_INCLUDE_DIR ${PNG_PNG_INCLUDE_DIR}) + MARK_AS_ADVANCED(PNG_PNG_INCLUDE_DIR) + ENDIF("${upper}" MATCHES "^PNG$") + ELSE(${upper}_FOUND) + MESSAGE(SEND_ERROR "VTK_USE_SYSTEM_${upper} is ON, but ${upper}_LIBRARY is NOTFOUND.") + ENDIF(${upper}_FOUND) + ELSE(VTK_USE_SYSTEM_${upper}) + SET(VTK_${upper}_LIBRARIES vtk${lower}) + ENDIF(VTK_USE_SYSTEM_${upper}) +ENDMACRO(VTK_THIRD_PARTY_OPTION) + +#----------------------------------------------------------------------------- +MACRO(VTK_THIRD_PARTY_INCLUDE upper lower) + IF(VTK_USE_SYSTEM_${upper}) + IF(${upper}_INCLUDE_DIR) + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} ${${upper}_INCLUDE_DIR}) + ENDIF(${upper}_INCLUDE_DIR) + ELSE(VTK_USE_SYSTEM_${upper}) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_BINARY_DIR}/Utilities/${lower} + ${VTK_SOURCE_DIR}/Utilities/${lower} + ) + ENDIF(VTK_USE_SYSTEM_${upper}) +ENDMACRO(VTK_THIRD_PARTY_INCLUDE) + +MACRO(VTK_THIRD_PARTY_INCLUDE2 upper) + IF(VTK_USE_SYSTEM_${upper}) + IF(${upper}_INCLUDE_DIR) + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} ${${upper}_INCLUDE_DIR}) + ENDIF(${upper}_INCLUDE_DIR) + ENDIF(VTK_USE_SYSTEM_${upper}) +ENDMACRO(VTK_THIRD_PARTY_INCLUDE2) + +#----------------------------------------------------------------------------- +MACRO(VTK_THIRD_PARTY_SUBDIR upper lower) + IF(NOT VTK_USE_SYSTEM_${upper}) + SUBDIRS(${lower}) + ENDIF(NOT VTK_USE_SYSTEM_${upper}) +ENDMACRO(VTK_THIRD_PARTY_SUBDIR) diff --git a/CMake/vtkWrapJava.cmake b/CMake/vtkWrapJava.cmake new file mode 100644 index 0000000..df76e39 --- /dev/null +++ b/CMake/vtkWrapJava.cmake @@ -0,0 +1,129 @@ +# +# a cmake implementation of the Wrap Java command +# + +MACRO(VTK_WRAP_JAVA3 TARGET SRC_LIST_NAME SOURCES) + IF(NOT VTK_PARSE_JAVA_EXE) + MESSAGE(SEND_ERROR "VTK_PARSE_JAVA_EXE not specified when calling VTK_WRAP_JAVA3") + ENDIF(NOT VTK_PARSE_JAVA_EXE) + IF(NOT VTK_WRAP_JAVA_EXE) + MESSAGE(SEND_ERROR "VTK_WRAP_JAVA_EXE not specified when calling VTK_WRAP_JAVA3") + ENDIF(NOT VTK_WRAP_JAVA_EXE) + # for new cmake use the new custom commands + IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + + # Initialize the custom target counter. + IF(VTK_WRAP_JAVA_NEED_CUSTOM_TARGETS) + SET(VTK_WRAP_JAVA_CUSTOM_COUNT "") + SET(VTK_WRAP_JAVA_CUSTOM_NAME ${TARGET}) + SET(VTK_WRAP_JAVA_CUSTOM_LIST) + ENDIF(VTK_WRAP_JAVA_NEED_CUSTOM_TARGETS) + + SET(VTK_JAVA_DEPENDENCIES) + SET(VTK_JAVA_DEPENDENCIES_FILE) + # For each class + FOREACH(FILE ${SOURCES}) + # should we wrap the file? + GET_SOURCE_FILE_PROPERTY(TMP_WRAP_EXCLUDE ${FILE} WRAP_EXCLUDE) + + # if we should wrap it + IF (NOT TMP_WRAP_EXCLUDE) + + # what is the filename without the extension + GET_FILENAME_COMPONENT(TMP_FILENAME ${FILE} NAME_WE) + + # the input file might be full path so handle that + GET_FILENAME_COMPONENT(TMP_FILEPATH ${FILE} PATH) + + # compute the input filename + IF (TMP_FILEPATH) + SET(TMP_INPUT ${TMP_FILEPATH}/${TMP_FILENAME}.h) + ELSE (TMP_FILEPATH) + SET(TMP_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${TMP_FILENAME}.h) + ENDIF (TMP_FILEPATH) + + # is it abstract? + GET_SOURCE_FILE_PROPERTY(TMP_ABSTRACT ${FILE} ABSTRACT) + IF (TMP_ABSTRACT) + SET(TMP_CONCRETE 0) + ELSE (TMP_ABSTRACT) + SET(TMP_CONCRETE 1) + ENDIF (TMP_ABSTRACT) + + # new source file is nameJava.cxx, add to resulting list + SET(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} + ${TMP_FILENAME}Java.cxx) + + # add custom command to output + ADD_CUSTOM_COMMAND( + OUTPUT ${VTK_JAVA_HOME}/${TMP_FILENAME}.java + DEPENDS ${VTK_PARSE_JAVA_EXE} ${VTK_WRAP_HINTS} ${TMP_INPUT} + COMMAND ${VTK_PARSE_JAVA_EXE} + ARGS ${TMP_INPUT} ${VTK_WRAP_HINTS} ${TMP_CONCRETE} + ${VTK_JAVA_HOME}/${TMP_FILENAME}.java + COMMENT "Java Wrappings" + ) + + # add custom command to output + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Java.cxx + DEPENDS ${VTK_WRAP_JAVA_EXE} ${VTK_WRAP_HINTS} ${TMP_INPUT} + COMMAND ${VTK_WRAP_JAVA_EXE} + ARGS ${TMP_INPUT} ${VTK_WRAP_HINTS} ${TMP_CONCRETE} + ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Java.cxx + COMMENT "Java Wrappings" + ) + + SET(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES} "${VTK_JAVA_HOME}/${TMP_FILENAME}.java") + SET(VTK_JAVA_DEPENDENCIES_FILE + "${VTK_JAVA_DEPENDENCIES_FILE}\n \"${VTK_JAVA_HOME}/${TMP_FILENAME}.java\"") + + # Add this output to a custom target if needed. + IF(VTK_WRAP_JAVA_NEED_CUSTOM_TARGETS) + SET(VTK_WRAP_JAVA_CUSTOM_LIST ${VTK_WRAP_JAVA_CUSTOM_LIST} + ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Java.cxx + ) + SET(VTK_WRAP_JAVA_CUSTOM_COUNT ${VTK_WRAP_JAVA_CUSTOM_COUNT}x) + IF(VTK_WRAP_JAVA_CUSTOM_COUNT MATCHES "^${VTK_WRAP_JAVA_CUSTOM_LIMIT}$") + SET(VTK_WRAP_JAVA_CUSTOM_NAME ${VTK_WRAP_JAVA_CUSTOM_NAME}Hack) + ADD_CUSTOM_TARGET(${VTK_WRAP_JAVA_CUSTOM_NAME} DEPENDS ${VTK_WRAP_JAVA_CUSTOM_LIST}) + SET(KIT_JAVA_DEPS ${VTK_WRAP_JAVA_CUSTOM_NAME}) + SET(VTK_WRAP_JAVA_CUSTOM_LIST) + SET(VTK_WRAP_JAVA_CUSTOM_COUNT) + ENDIF(VTK_WRAP_JAVA_CUSTOM_COUNT MATCHES "^${VTK_WRAP_JAVA_CUSTOM_LIMIT}$") + ENDIF(VTK_WRAP_JAVA_NEED_CUSTOM_TARGETS) + ENDIF (NOT TMP_WRAP_EXCLUDE) + ENDFOREACH(FILE) + + ADD_CUSTOM_TARGET("${TARGET}JavaClasses" ALL DEPENDS ${VTK_JAVA_DEPENDENCIES}) + SET(dir ${CMAKE_CURRENT_SOURCE_DIR}) + IF(VTK_WRAP_JAVA3_INIT_DIR) + SET(dir ${VTK_WRAP_JAVA3_INIT_DIR}) + ENDIF(VTK_WRAP_JAVA3_INIT_DIR) + CONFIGURE_FILE("${dir}/JavaDependencies.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/JavaDependencies.cmake" IMMEDIATE @ONLY) + + ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + #otherwise use old loaded command + VTK_WRAP_JAVA2(${TARGET} + SOURCES ${SRC_LIST} ${SOURCES} + ) + ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) +ENDMACRO(VTK_WRAP_JAVA3) + +# VS 6 does not like needing to run a huge number of custom commands +# when building a single target. Generate some extra custom targets +# that run the custom commands before the main target is built. This +# is a hack to work-around the limitation. The test to enable it is +# done here since it does not need to be done for every macro +# invocation. +IF(CMAKE_GENERATOR MATCHES "^Visual Studio 6$") + SET(VTK_WRAP_JAVA_NEED_CUSTOM_TARGETS 1) + SET(VTK_WRAP_JAVA_CUSTOM_LIMIT x) + # Limit the number of custom commands in each target + # to 2^7. + FOREACH(t 1 2 3 4 5 6 7) + SET(VTK_WRAP_JAVA_CUSTOM_LIMIT + ${VTK_WRAP_JAVA_CUSTOM_LIMIT}${VTK_WRAP_JAVA_CUSTOM_LIMIT}) + ENDFOREACH(t) +ENDIF(CMAKE_GENERATOR MATCHES "^Visual Studio 6$") diff --git a/CMake/vtkWrapPython.cmake b/CMake/vtkWrapPython.cmake new file mode 100644 index 0000000..aa2efa5 --- /dev/null +++ b/CMake/vtkWrapPython.cmake @@ -0,0 +1,142 @@ +# +# a cmake implementation of the Wrap Python command +# + +MACRO(VTK_WRAP_PYTHON3 TARGET SRC_LIST_NAME SOURCES) + IF(NOT VTK_WRAP_PYTHON_INIT_EXE) + MESSAGE(SEND_ERROR "VTK_WRAP_PYTHON_INIT_EXE not specified when calling VTK_WRAP_PYTHON3") + ENDIF(NOT VTK_WRAP_PYTHON_INIT_EXE) + IF(NOT VTK_WRAP_PYTHON_EXE) + MESSAGE(SEND_ERROR "VTK_WRAP_PYTHON_EXE not specified when calling VTK_WRAP_PYTHON3") + ENDIF(NOT VTK_WRAP_PYTHON_EXE) + # for new cmake use the new custom commands + IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + + # Initialize the custom target counter. + IF(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS) + SET(VTK_WRAP_PYTHON_CUSTOM_COUNT "") + SET(VTK_WRAP_PYTHON_CUSTOM_NAME ${TARGET}) + SET(VTK_WRAP_PYTHON_CUSTOM_LIST) + ENDIF(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS) + + # start writing the input file for the init file + SET(VTK_WRAPPER_INIT_DATA "${TARGET}") + + # For each class + FOREACH(FILE ${SOURCES}) + # should we wrap the file? + GET_SOURCE_FILE_PROPERTY(TMP_WRAP_EXCLUDE ${FILE} WRAP_EXCLUDE) + + # if we should wrap it + IF (NOT TMP_WRAP_EXCLUDE) + + # what is the filename without the extension + GET_FILENAME_COMPONENT(TMP_FILENAME ${FILE} NAME_WE) + + # the input file might be full path so handle that + GET_FILENAME_COMPONENT(TMP_FILEPATH ${FILE} PATH) + + # compute the input filename + IF (TMP_FILEPATH) + SET(TMP_INPUT ${TMP_FILEPATH}/${TMP_FILENAME}.h) + ELSE (TMP_FILEPATH) + SET(TMP_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${TMP_FILENAME}.h) + ENDIF (TMP_FILEPATH) + + # is it abstract? + GET_SOURCE_FILE_PROPERTY(TMP_ABSTRACT ${FILE} ABSTRACT) + IF (TMP_ABSTRACT) + SET(TMP_CONCRETE 0) + ELSE (TMP_ABSTRACT) + SET(TMP_CONCRETE 1) + ENDIF (TMP_ABSTRACT) + + # add the info to the init file + SET(VTK_WRAPPER_INIT_DATA + "${VTK_WRAPPER_INIT_DATA}\n${TMP_FILENAME}") + + # new source file is namePython.cxx, add to resulting list + SET(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} + ${TMP_FILENAME}Python.cxx) + + # add custom command to output + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Python.cxx + DEPENDS ${VTK_WRAP_PYTHON_EXE} ${VTK_WRAP_HINTS} ${TMP_INPUT} + COMMAND ${VTK_WRAP_PYTHON_EXE} + ARGS ${TMP_INPUT} ${VTK_WRAP_HINTS} ${TMP_CONCRETE} + ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Python.cxx + COMMENT "Python Wrappings" + ) + + # Add this output to a custom target if needed. + IF(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS) + SET(VTK_WRAP_PYTHON_CUSTOM_LIST ${VTK_WRAP_PYTHON_CUSTOM_LIST} + ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Python.cxx) + SET(VTK_WRAP_PYTHON_CUSTOM_COUNT ${VTK_WRAP_PYTHON_CUSTOM_COUNT}x) + IF(VTK_WRAP_PYTHON_CUSTOM_COUNT MATCHES "^${VTK_WRAP_PYTHON_CUSTOM_LIMIT}$") + SET(VTK_WRAP_PYTHON_CUSTOM_NAME ${VTK_WRAP_PYTHON_CUSTOM_NAME}Hack) + ADD_CUSTOM_TARGET(${VTK_WRAP_PYTHON_CUSTOM_NAME} DEPENDS ${VTK_WRAP_PYTHON_CUSTOM_LIST}) + SET(KIT_PYTHON_DEPS ${VTK_WRAP_PYTHON_CUSTOM_NAME}) + SET(VTK_WRAP_PYTHON_CUSTOM_LIST) + SET(VTK_WRAP_PYTHON_CUSTOM_COUNT) + ENDIF(VTK_WRAP_PYTHON_CUSTOM_COUNT MATCHES "^${VTK_WRAP_PYTHON_CUSTOM_LIMIT}$") + ENDIF(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS) + ENDIF (NOT TMP_WRAP_EXCLUDE) + ENDFOREACH(FILE) + + # finish the data file for the init file + SET(dir ${CMAKE_CURRENT_SOURCE_DIR}) + IF(VTK_WRAP_PYTHON3_INIT_DIR) + SET(dir ${VTK_WRAP_PYTHON3_INIT_DIR}) + ELSE(VTK_WRAP_PYTHON3_INIT_DIR) + IF(VTK_INSTALL_PREFIX) + SET(dir "${VTK_CMAKE_DIR}") + ELSE(VTK_INSTALL_PREFIX) + SET(dir "${VTK_SOURCE_DIR}/Wrapping") + ENDIF(VTK_INSTALL_PREFIX) + ENDIF(VTK_WRAP_PYTHON3_INIT_DIR) + CONFIGURE_FILE( + ${dir}/vtkWrapperInit.data.in + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data + COPY_ONLY + IMMEDIATE + ) + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx + DEPENDS ${VTK_WRAP_PYTHON_INIT_EXE} + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data + COMMAND ${VTK_WRAP_PYTHON_INIT_EXE} + ARGS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx + COMMENT "Python Wrapping Init" + ) + + # Create the Init File + SET(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} ${TARGET}Init.cxx) + + ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + #otherwise use old loaded command + VTK_WRAP_PYTHON2(${TARGET} + SOURCES ${SRC_LIST} ${SOURCES} + ) + ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) +ENDMACRO(VTK_WRAP_PYTHON3) + +# VS 6 does not like needing to run a huge number of custom commands +# when building a single target. Generate some extra custom targets +# that run the custom commands before the main target is built. This +# is a hack to work-around the limitation. The test to enable it is +# done here since it does not need to be done for every macro +# invocation. +IF(CMAKE_GENERATOR MATCHES "^Visual Studio 6$") + SET(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS 1) + SET(VTK_WRAP_PYTHON_CUSTOM_LIMIT x) + # Limit the number of custom commands in each target + # to 2^7. + FOREACH(t 1 2 3 4 5 6 7) + SET(VTK_WRAP_PYTHON_CUSTOM_LIMIT + ${VTK_WRAP_PYTHON_CUSTOM_LIMIT}${VTK_WRAP_PYTHON_CUSTOM_LIMIT}) + ENDFOREACH(t) +ENDIF(CMAKE_GENERATOR MATCHES "^Visual Studio 6$") diff --git a/CMake/vtkWrapTcl.cmake b/CMake/vtkWrapTcl.cmake new file mode 100644 index 0000000..5bcc742 --- /dev/null +++ b/CMake/vtkWrapTcl.cmake @@ -0,0 +1,157 @@ +# +# a cmake implementation of the Wrap Tcl command +# it takes an optional VERSION parameter that will be output +# to the .data file as VERSION ${VERSION}. +# vtkWrapTclInit will then recognize the VERSION keyword, extract the version +# and make sure the corresponding Tcl package is 'provided' with that version. +# + +MACRO(VTK_WRAP_TCL3 TARGET SRC_LIST_NAME SOURCES COMMANDS) + IF(NOT VTK_WRAP_TCL_INIT_EXE) + MESSAGE(SEND_ERROR "VTK_WRAP_TCL_INIT_EXE not specified when calling VTK_WRAP_TCL3") + ENDIF(NOT VTK_WRAP_TCL_INIT_EXE) + IF(NOT VTK_WRAP_TCL_EXE) + MESSAGE(SEND_ERROR "VTK_WRAP_TCL_EXE not specified when calling VTK_WRAP_TCL3") + ENDIF(NOT VTK_WRAP_TCL_EXE) + # for new cmake use the new custom commands + IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + + # Initialize the custom target counter. + IF(VTK_WRAP_TCL_NEED_CUSTOM_TARGETS) + SET(VTK_WRAP_TCL_CUSTOM_COUNT "") + SET(VTK_WRAP_TCL_CUSTOM_NAME ${TARGET}) + SET(VTK_WRAP_TCL_CUSTOM_LIST) + ENDIF(VTK_WRAP_TCL_NEED_CUSTOM_TARGETS) + + # start writing the input file for the init file + SET(VTK_WRAPPER_INIT_DATA "${TARGET}") + IF (${ARGC} GREATER 4) + SET(VTK_WRAPPER_INIT_DATA + "${VTK_WRAPPER_INIT_DATA}\nVERSION ${ARGV4}") + ENDIF (${ARGC} GREATER 4) + + # For each class + FOREACH(FILE ${SOURCES}) + # should we wrap the file? + GET_SOURCE_FILE_PROPERTY(TMP_WRAP_EXCLUDE ${FILE} WRAP_EXCLUDE) + + # if we should wrap it + IF (NOT TMP_WRAP_EXCLUDE) + + # what is the filename without the extension + GET_FILENAME_COMPONENT(TMP_FILENAME ${FILE} NAME_WE) + + # the input file might be full path so handle that + GET_FILENAME_COMPONENT(TMP_FILEPATH ${FILE} PATH) + + # compute the input filename + IF (TMP_FILEPATH) + SET(TMP_INPUT ${TMP_FILEPATH}/${TMP_FILENAME}.h) + ELSE (TMP_FILEPATH) + SET(TMP_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${TMP_FILENAME}.h) + ENDIF (TMP_FILEPATH) + + # is it abstract? + GET_SOURCE_FILE_PROPERTY(TMP_ABSTRACT ${FILE} ABSTRACT) + IF (TMP_ABSTRACT) + SET(TMP_CONCRETE 0) + ELSE (TMP_ABSTRACT) + SET(TMP_CONCRETE 1) + # add the info to the init file + SET(VTK_WRAPPER_INIT_DATA + "${VTK_WRAPPER_INIT_DATA}\n${TMP_FILENAME}") + ENDIF (TMP_ABSTRACT) + + # new source file is nameTcl.cxx, add to resulting list + SET(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} + ${TMP_FILENAME}Tcl.cxx) + + # add custom command to output + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Tcl.cxx + DEPENDS ${VTK_WRAP_TCL_EXE} ${VTK_WRAP_HINTS} + MAIN_DEPENDENCY "${TMP_INPUT}" + COMMAND ${VTK_WRAP_TCL_EXE} + ARGS ${TMP_INPUT} ${VTK_WRAP_HINTS} ${TMP_CONCRETE} + ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Tcl.cxx + COMMENT + "Tcl Wrappings" + ) + + # Add this output to a custom target if needed. + IF(VTK_WRAP_TCL_NEED_CUSTOM_TARGETS) + SET(VTK_WRAP_TCL_CUSTOM_LIST ${VTK_WRAP_TCL_CUSTOM_LIST} + ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Tcl.cxx) + SET(VTK_WRAP_TCL_CUSTOM_COUNT ${VTK_WRAP_TCL_CUSTOM_COUNT}x) + IF(VTK_WRAP_TCL_CUSTOM_COUNT MATCHES "^${VTK_WRAP_TCL_CUSTOM_LIMIT}$") + SET(VTK_WRAP_TCL_CUSTOM_NAME ${VTK_WRAP_TCL_CUSTOM_NAME}Hack) + ADD_CUSTOM_TARGET(${VTK_WRAP_TCL_CUSTOM_NAME} DEPENDS ${VTK_WRAP_TCL_CUSTOM_LIST}) + SET(KIT_TCL_DEPS ${VTK_WRAP_TCL_CUSTOM_NAME}) + SET(VTK_WRAP_TCL_CUSTOM_LIST) + SET(VTK_WRAP_TCL_CUSTOM_COUNT) + ENDIF(VTK_WRAP_TCL_CUSTOM_COUNT MATCHES "^${VTK_WRAP_TCL_CUSTOM_LIMIT}$") + ENDIF(VTK_WRAP_TCL_NEED_CUSTOM_TARGETS) + ENDIF (NOT TMP_WRAP_EXCLUDE) + ENDFOREACH(FILE) + + # finish the data file for the init file + FOREACH(CMD ${COMMANDS}) + SET(VTK_WRAPPER_INIT_DATA + "${VTK_WRAPPER_INIT_DATA}\nCOMMAND ${CMD}") + ENDFOREACH(CMD ${COMMANDS}) + + SET(dir ${CMAKE_CURRENT_SOURCE_DIR}) + IF(VTK_WRAP_TCL3_INIT_DIR) + SET(dir ${VTK_WRAP_TCL3_INIT_DIR}) + ELSE(VTK_WRAP_TCL3_INIT_DIR) + IF(VTK_INSTALL_PREFIX) + SET(dir "${VTK_CMAKE_DIR}") + ELSE(VTK_INSTALL_PREFIX) + SET(dir "${VTK_SOURCE_DIR}/Wrapping") + ENDIF(VTK_INSTALL_PREFIX) + ENDIF(VTK_WRAP_TCL3_INIT_DIR) + CONFIGURE_FILE( + ${dir}/vtkWrapperInit.data.in + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data + COPY_ONLY + IMMEDIATE + ) + + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx + DEPENDS ${VTK_WRAP_TCL_INIT_EXE} + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data + COMMAND ${VTK_WRAP_TCL_INIT_EXE} + ARGS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data + ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx + COMMENT "Tcl Wrapping Init" + ) + + # Create the Init File + SET(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} ${TARGET}Init.cxx) + + ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + #otherwise use old loaded command + VTK_WRAP_TCL2(${TARGET} + SOURCES ${SRC_LIST} ${SOURCES} + COMMANDS ${COMMANDS} + ) + ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) +ENDMACRO(VTK_WRAP_TCL3) + +# VS 6 does not like needing to run a huge number of custom commands +# when building a single target. Generate some extra custom targets +# that run the custom commands before the main target is built. This +# is a hack to work-around the limitation. The test to enable it is +# done here since it does not need to be done for every macro +# invocation. +IF(CMAKE_GENERATOR MATCHES "^Visual Studio 6$") + SET(VTK_WRAP_TCL_NEED_CUSTOM_TARGETS 1) + SET(VTK_WRAP_TCL_CUSTOM_LIMIT x) + # Limit the number of custom commands in each target + # to 2^7. + FOREACH(t 1 2 3 4 5 6 7) + SET(VTK_WRAP_TCL_CUSTOM_LIMIT + ${VTK_WRAP_TCL_CUSTOM_LIMIT}${VTK_WRAP_TCL_CUSTOM_LIMIT}) + ENDFOREACH(t) +ENDIF(CMAKE_GENERATOR MATCHES "^Visual Studio 6$") diff --git a/CMakeFiles/cmake.check_cache b/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c455985 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,1531 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.0) +PROJECT(VTK) + +# Don't build anything unless the version of CMake is high enough. +# The matching ELSE/ENDIF should be the last lines in the file. +IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.9) + + + + + +# Tell the CMake makefile generator to not have rules depend on +# themselves. This causes extra rebuilds when the include path +# changes from turning a kit on or off. +SET(CMAKE_SKIP_RULE_DEPENDENCY 1) + +#----------------------------------------------------------------------------- +# VTK version number. An even minor number corresponds to releases. +SET(VTK_MAJOR_VERSION 5) +SET(VTK_MINOR_VERSION 0) +SET(VTK_BUILD_VERSION 3) +SET(VTK_VERSION + "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}.${VTK_BUILD_VERSION}") + +# Append the library version information to the library target +# properties. A parent project may set its own properties and/or may +# block this. +IF(NOT VTK_NO_LIBRARY_VERSION) + SET(VTK_LIBRARY_PROPERTIES ${VTK_LIBRARY_PROPERTIES} + VERSION "${VTK_VERSION}" + SOVERSION "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" + ) +ENDIF(NOT VTK_NO_LIBRARY_VERSION) + +#----------------------------------------------------------------------------- +# Load some macros. +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkDependentOption.cmake) +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkThirdParty.cmake) +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkExportKit.cmake) +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkMakeInstantiator.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CMakeExportBuildSettings.cmake) + +#----------------------------------------------------------------------------- +# Choose static or shared libraries. +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkSelectSharedLibraries.cmake) + +# Disable the install targets if using the rpath feature. +IF(NOT WIN32) + IF(VTK_USE_RPATH) + SET(VTK_INSTALL_NO_RUNTIME 1) + SET(VTK_INSTALL_NO_DEVELOPMENT 1) + SET(VTK_INSTALL_NO_DOCUMENTATION 1) + ENDIF(VTK_USE_RPATH) +ENDIF(NOT WIN32) + +#----------------------------------------------------------------------------- +# Output directories. +IF(NOT LIBRARY_OUTPUT_PATH) + SET(LIBRARY_OUTPUT_PATH ${VTK_BINARY_DIR}/bin CACHE INTERNAL "Single output directory for building all libraries.") +ENDIF(NOT LIBRARY_OUTPUT_PATH) +IF(NOT EXECUTABLE_OUTPUT_PATH) + SET(EXECUTABLE_OUTPUT_PATH ${VTK_BINARY_DIR}/bin CACHE INTERNAL "Single output directory for building all executables.") +ENDIF(NOT EXECUTABLE_OUTPUT_PATH) +SET(VTK_LIBRARY_DIR ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}) +SET(VTK_EXECUTABLE_DIR ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}) +SET(CXX_TEST_PATH ${EXECUTABLE_OUTPUT_PATH}) + +#----------------------------------------------------------------------------- +# Configure install locations. This allows parent projects to modify +# the install location. Optionally allow the project to specify a +# single VTK_INSTALL_ROOT which basically adds to its install prefix +# for VTK only. + +# The location in which to install VTK executables. +IF(NOT VTK_INSTALL_BIN_DIR) + SET(VTK_INSTALL_BIN_DIR ${VTK_INSTALL_ROOT}/bin) +ENDIF(NOT VTK_INSTALL_BIN_DIR) + +# The location in which to install VTK header files. +IF(NOT VTK_INSTALL_INCLUDE_DIR) + SET(VTK_INSTALL_INCLUDE_DIR + ${VTK_INSTALL_ROOT}/include/vtk-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} + ) +ENDIF(NOT VTK_INSTALL_INCLUDE_DIR) + +# The location in which to install VTK libraries. +IF(NOT VTK_INSTALL_LIB_DIR) + SET(VTK_INSTALL_LIB_DIR ${VTK_INSTALL_ROOT}/lib) +ENDIF(NOT VTK_INSTALL_LIB_DIR) + +# The location in which to install CMake scripts for packaging VTK. +IF(NOT VTK_INSTALL_PACKAGE_DIR) + SET(VTK_INSTALL_PACKAGE_DIR + ${VTK_INSTALL_LIB_DIR}/vtk-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} + ) +ENDIF(NOT VTK_INSTALL_PACKAGE_DIR) + +# The location in which to install VTK doxygen documentation helper +# files. +IF(NOT VTK_INSTALL_DOXYGEN_DIR) + SET(VTK_INSTALL_DOXYGEN_DIR ${VTK_INSTALL_PACKAGE_DIR}/doxygen) +ENDIF(NOT VTK_INSTALL_DOXYGEN_DIR) + +# Compute the proper location for installing the Tcl package. This +# must be a fixed relative path below the library install location and +# is therefore not settable by parent projects. +SET(VTK_INSTALL_TCL_DIR + ${VTK_INSTALL_LIB_DIR}/vtk-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION} + ) + +IF(NOT VTK_INSTALL_JAVA_DIR) + SET(VTK_INSTALL_JAVA_DIR ${VTK_INSTALL_PACKAGE_DIR}/java) +ENDIF(NOT VTK_INSTALL_JAVA_DIR) + +# Choose a default CMAKE_INSTALL_PREFIX on Windows. CMake 2.2 and +# above already choose a good default, so force a change only if the +# current value looks like the CMake 2.0 default. +IF(NOT UNIX) + IF(CMAKE_INSTALL_PREFIX MATCHES "/usr/local") + IF("$ENV{ProgramFiles}" MATCHES "^$") + IF("$ENV{SystemDrive}" MATCHES "^$") + SET(VTK_GENERIC_PROGRAM_FILES "C:/Program Files") + ELSE("$ENV{SystemDrive}" MATCHES "^$") + SET(VTK_GENERIC_PROGRAM_FILES "$ENV{SystemDrive}/Program Files") + ENDIF("$ENV{SystemDrive}" MATCHES "^$") + ELSE("$ENV{ProgramFiles}" MATCHES "^$") + SET(VTK_GENERIC_PROGRAM_FILES "$ENV{ProgramFiles}") + ENDIF("$ENV{ProgramFiles}" MATCHES "^$") + SET(CMAKE_INSTALL_PREFIX + "${VTK_GENERIC_PROGRAM_FILES}/${PROJECT_NAME}" + CACHE PATH "Install path prefix, prepended onto install directories." + FORCE) + SET(VTK_GENERIC_SYSTEM_DRIVE) + ENDIF(CMAKE_INSTALL_PREFIX MATCHES "/usr/local") + MARK_AS_ADVANCED(CLEAR CMAKE_INSTALL_PREFIX) +ENDIF(NOT UNIX) + +# There are three basic components to the VTK installation: runtime, +# development, and documentation. Install rules for each component +# are surrounded by blockers. Parent projects or users can specify +# VTK_INSTALL_NO_RUNTIME, VTK_INSTALL_NO_DEVELOPMENT, or +# VTK_INSTALL_NO_DOCUMENTATION to avoid installation of the +# corresponding component. + +# Shared libraries are considered both runtime and development and +# static libraries are considered development only. In order to +# switch library installation on and off correctly we make the +# decision here. +SET(VTK_INSTALL_NO_LIBRARIES) +IF(BUILD_SHARED_LIBS) + IF(VTK_INSTALL_NO_RUNTIME AND VTK_INSTALL_NO_DEVELOPMENT) + SET(VTK_INSTALL_NO_LIBRARIES 1) + ENDIF(VTK_INSTALL_NO_RUNTIME AND VTK_INSTALL_NO_DEVELOPMENT) +ELSE(BUILD_SHARED_LIBS) + IF(VTK_INSTALL_NO_DEVELOPMENT) + SET(VTK_INSTALL_NO_LIBRARIES 1) + ENDIF(VTK_INSTALL_NO_DEVELOPMENT) +ENDIF(BUILD_SHARED_LIBS) + +#----------------------------------------------------------------------------- +# Save the compiler settings so another project can import them. +CMAKE_EXPORT_BUILD_SETTINGS(${VTK_BINARY_DIR}/VTKBuildSettings.cmake) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR} .cmake VTKBuildSettings) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +#----------------------------------------------------------------------------- +# Provide compatibility options. +OPTION(VTK_LEGACY_REMOVE "Remove all legacy code completely." OFF) +OPTION(VTK_LEGACY_SILENT "Silence all legacy code messages." OFF) +MARK_AS_ADVANCED(VTK_LEGACY_REMOVE VTK_LEGACY_SILENT) + +#----------------------------------------------------------------------------- +# Determine the set of VTK kits that should be built. +OPTION(VTK_USE_RENDERING "Build the vtkRendering kit. Needed for displaying data or using widgets." OFF) +VTK_DEPENDENT_OPTION(VTK_USE_PARALLEL "Build the vtkParallel kit." OFF + "VTK_USE_RENDERING" OFF) + +# Determine GUI Support. +VTK_DEPENDENT_OPTION(VTK_USE_GUISUPPORT "Build VTK with GUI Support" OFF + "VTK_USE_RENDERING" OFF) +MARK_AS_ADVANCED(VTK_USE_GUISUPPORT) + +# Remove old options from an existing cache. +IF("VTK_USE_HYBRID" MATCHES "^VTK_USE_HYBRID$") +ELSE("VTK_USE_HYBRID" MATCHES "^VTK_USE_HYBRID$") + SET(VTK_USE_HYBRID "" CACHE INTERNAL "Hiding old option") +ENDIF("VTK_USE_HYBRID" MATCHES "^VTK_USE_HYBRID$") +IF("VTK_USE_PATENTED" MATCHES "^VTK_USE_PATENTED$") +ELSE("VTK_USE_PATENTED" MATCHES "^VTK_USE_PATENTED$") + SET(VTK_USE_PATENTED "" CACHE INTERNAL "Hiding old option") +ENDIF("VTK_USE_PATENTED" MATCHES "^VTK_USE_PATENTED$") +IF("VTK_USE_VOLUMERENDERING" MATCHES "^VTK_USE_VOLUMERENDERING$") +ELSE("VTK_USE_VOLUMERENDERING" MATCHES "^VTK_USE_VOLUMERENDERING$") + SET(VTK_USE_VOLUMERENDERING "" CACHE INTERNAL "Hiding old option") +ENDIF("VTK_USE_VOLUMERENDERING" MATCHES "^VTK_USE_VOLUMERENDERING$") + +SET(VTK_KITS COMMON FILTERING IO GENERIC_FILTERING) # Removed IMAGING, GRAPHICS +IF(VTK_USE_RENDERING) + SET(VTK_KITS ${VTK_KITS} RENDERING) + SET(VTK_KITS ${VTK_KITS} VOLUMERENDERING) + SET(VTK_KITS ${VTK_KITS} HYBRID) + SET(VTK_KITS ${VTK_KITS} WIDGETS) +ENDIF(VTK_USE_RENDERING) +IF(VTK_USE_PARALLEL) + SET(VTK_KITS ${VTK_KITS} PARALLEL) +ENDIF(VTK_USE_PARALLEL) + +# from GUISupport +IF(VTK_USE_QVTK) + SET(VTK_KITS ${VTK_KITS} QVTK) +ENDIF(VTK_USE_QVTK) +IF(VTK_USE_MFC) + SET(VTK_KITS ${VTK_KITS} MFC) +ENDIF(VTK_USE_MFC) + + +#----------------------------------------------------------------------------- +# Determine GUI. +FIND_PACKAGE(X11) +SET(VTK_USE_X_OPTIONAL 0) +SET(VTK_USE_X_FORCE 0) +IF(X11_FOUND) + IF(CYGWIN) + SET(VTK_USE_X_OPTIONAL 1) + ENDIF(CYGWIN) + IF(APPLE) + SET(VTK_USE_X_OPTIONAL 1) + ELSE(APPLE) + SET(VTK_USE_X_FORCE ${VTK_USE_RENDERING}) + ENDIF(APPLE) +ENDIF(X11_FOUND) + +VTK_DEPENDENT_OPTION(VTK_USE_CARBON "Build classes using Carbon API." ON + "APPLE;VTK_USE_RENDERING" OFF) +VTK_DEPENDENT_OPTION(VTK_USE_COCOA "Build classes using Cocoa API." OFF + "APPLE;VTK_USE_RENDERING" OFF) +VTK_DEPENDENT_OPTION(VTK_USE_X + "Build classes for the X11 window system." OFF + "X11_FOUND;VTK_USE_RENDERING;VTK_USE_X_OPTIONAL" + "${VTK_USE_X_FORCE}") + +IF(VTK_USE_CARBON AND VTK_USE_COCOA) + MESSAGE(SEND_ERROR "Only one of VTK_USE_CARBON and VTK_USE_COCOA may be ON.") + SET(VTK_USE_CARBON 0) + SET(VTK_USE_COCOA 0) +ENDIF(VTK_USE_CARBON AND VTK_USE_COCOA) + +#----------------------------------------------------------------------------- +# VTK requires special compiler flags on some platforms. +SET(VTK_REQUIRED_C_FLAGS) +SET(VTK_REQUIRED_CXX_FLAGS) + +# make sure Crun is linked in with the native compiler, it is +# not used by default for shared libraries and is required for +# things like java to work. +IF(CMAKE_SYSTEM MATCHES "SunOS.*") + IF(NOT CMAKE_COMPILER_IS_GNUCXX) + FIND_LIBRARY(VTK_SUNCC_CRUN_LIBRARY Crun /opt/SUNWspro/lib) + IF(VTK_SUNCC_CRUN_LIBRARY) + LINK_LIBRARIES(${VTK_SUNCC_CRUN_LIBRARY}) + ENDIF(VTK_SUNCC_CRUN_LIBRARY) + FIND_LIBRARY(VTK_SUNCC_CSTD_LIBRARY Cstd /opt/SUNWspro/lib) + IF(VTK_SUNCC_CSTD_LIBRARY) + LINK_LIBRARIES(${VTK_SUNCC_CSTD_LIBRARY}) + ENDIF(VTK_SUNCC_CSTD_LIBRARY) + ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX) +ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*") + +IF(CMAKE_COMPILER_IS_GNUCXX) + # A GCC compiler. Quiet warning about strstream deprecation. + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS} -Wno-deprecated") + IF(WIN32) + # The platform is gcc on cygwin. + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS} -mwin32") + SET(VTK_REQUIRED_C_FLAGS "${VTK_REQUIRED_C_FLAGS} -mwin32") + ENDIF(WIN32) + IF(MINGW) + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS} -mthreads") + SET(VTK_REQUIRED_C_FLAGS "${VTK_REQUIRED_C_FLAGS} -mthreads") + SET(VTK_REQUIRED_EXE_LINKER_FLAGS "${VTK_REQUIRED_EXE_LINKER_FLAGS} -mthreads -Wl,--export-all-symbols") + SET(VTK_REQUIRED_SHARED_LINKER_FLAGS "${VTK_REQUIRED_SHARED_LINKER_FLAGS} -mthreads -Wl,--export-all-symbols") + SET(VTK_REQUIRED_MODULE_LINKER_FLAGS "${VTK_REQUIRED_MODULE_LINKER_FLAGS} -mthreads -Wl,--export-all-symbols") + LINK_LIBRARIES(-lgdi32) + ENDIF(MINGW) + IF(CMAKE_SYSTEM MATCHES "SunOS.*") + # Disable warnings that occur in X11 headers. + IF(DART_ROOT AND BUILD_TESTING) + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS} -Wno-unknown-pragmas") + SET(VTK_REQUIRED_C_FLAGS "${VTK_REQUIRED_C_FLAGS} -Wno-unknown-pragmas") + ENDIF(DART_ROOT AND BUILD_TESTING) + ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*") +ELSE(CMAKE_COMPILER_IS_GNUCXX) + IF(CMAKE_ANSI_CFLAGS) + SET(VTK_REQUIRED_C_FLAGS "${VTK_REQUIRED_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") + ENDIF(CMAKE_ANSI_CFLAGS) + IF(CMAKE_SYSTEM MATCHES "OSF1-V.*") + SET(VTK_REQUIRED_CXX_FLAGS + "${VTK_REQUIRED_CXX_FLAGS} -timplicit_local -no_implicit_include") + ENDIF(CMAKE_SYSTEM MATCHES "OSF1-V.*") + IF(CMAKE_SYSTEM MATCHES "IRIX.*") + SET(VTK_REQUIRED_CXX_FLAGS + "${VTK_REQUIRED_CXX_FLAGS} -Wl,-woff84 -woff 15 -woff 84 -woff 3439 -woff 1424 -woff 3201") + SET(VTK_REQUIRED_C_FLAGS "${VTK_REQUIRED_C_FLAGS} -woff 3439") + ENDIF(CMAKE_SYSTEM MATCHES "IRIX.*") + #silence duplicate symbol warnings on AIX + IF(CMAKE_SYSTEM MATCHES "AIX.*") + SET(VTK_REQUIRED_EXE_LINKER_FLAGS "${VTK_REQUIRED_EXE_LINKER_FLAGS} -bhalt:5") + SET(VTK_REQUIRED_SHARED_LINKER_FLAGS "${VTK_REQUIRED_SHARED_LINKER_FLAGS} -bhalt:5") + SET(VTK_REQUIRED_MODULE_LINKER_FLAGS "${VTK_REQUIRED_MODULE_LINKER_FLAGS} -bhalt:5") + ENDIF(CMAKE_SYSTEM MATCHES "AIX.*") +ENDIF(CMAKE_COMPILER_IS_GNUCXX) + +IF(APPLE) + SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS} -Wl,-flat_namespace,-U,_environ") + SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -Wl,-flat_namespace,-U,_environ") + IF(CMAKE_COMPILER_IS_GNUCXX) + SET(VTK_REQUIRED_C_FLAGS "${VTK_REQUIRED_C_FLAGS} -no-cpp-precomp") + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS} -no-cpp-precomp") + IF(VTK_USE_CARBON) + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS} -fpascal-strings") + ENDIF(VTK_USE_CARBON) + ENDIF(CMAKE_COMPILER_IS_GNUCXX) +ENDIF(APPLE) + +IF(UNIX) + IF(NOT CMAKE_COMPILER_IS_GNUCXX) + INCLUDE(${VTK_SOURCE_DIR}/CMake/TestNO_ICC_IDYNAMIC_NEEDED.cmake) + TESTNO_ICC_IDYNAMIC_NEEDED(NO_ICC_IDYNAMIC_NEEDED ${VTK_SOURCE_DIR}/CMake) + IF(NO_ICC_IDYNAMIC_NEEDED) + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS}") + ELSE(NO_ICC_IDYNAMIC_NEEDED) + SET(VTK_REQUIRED_CXX_FLAGS "${VTK_REQUIRED_CXX_FLAGS} -i_dynamic") + ENDIF(NO_ICC_IDYNAMIC_NEEDED) + ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX) +ENDIF(UNIX) + +IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake|VCExpress)") + # Use the highest warning level for visual studio. + SET(CMAKE_CXX_WARNING_LEVEL 4) + IF(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + ELSE(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + ENDIF(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + # Disable deprecation warnings for standard C and STL functions in VS2005 + # and later + IF(CMAKE_COMPILER_2005) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) + ADD_DEFINITIONS(-D_SCL_SECURE_NO_DEPRECATE) + ENDIF(CMAKE_COMPILER_2005) +ENDIF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake|VCExpress)") + +# Tell VTK source files they are being built inside VTK. +ADD_DEFINITIONS(-DVTK_IN_VTK) + +#----------------------------------------------------------------------------- +# Add compiler flags VTK needs to work on this platform. This must be +# done after the call to CMAKE_EXPORT_BUILD_SETTINGS, but before any +# try-compiles are done. +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${VTK_REQUIRED_C_FLAGS}") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VTK_REQUIRED_CXX_FLAGS} -w -Wno-narrowing -std=c++03") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${VTK_REQUIRED_EXE_LINKER_FLAGS} -w") +SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${VTK_REQUIRED_SHARED_LINKER_FLAGS} -w") +SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${VTK_REQUIRED_MODULE_LINKER_FLAGS} -w") + +# The Borland implib tool is used by CMake to generate the .lib export +# file from a .dll. CMake 2.0 and earlier did not add the "-c" option +# to specify that the exported symbols should be case sensitive. Add +# the flag now if it is not there. +IF(BORLAND) + STRING(REGEX REPLACE "implib -w" "implib -c -w" + CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY}") +ENDIF(BORLAND) + +#----------------------------------------------------------------------------- +# Platform configuration tests. +INCLUDE(${CMAKE_ROOT}/Modules/CMakeBackwardCompatibilityC.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/TestForANSIStreamHeaders.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/TestForSTDNamespace.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckTypeSize.cmake) + +# Simulate old CMakeBackwardCompatibilityCXX test. +# In CMake 2.4 and up this could be just +# INCLUDE(${CMAKE_ROOT}/Modules/TestForSSTREAM.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckIncludeFileCXX.cmake) +CHECK_INCLUDE_FILE_CXX("sstream" CMAKE_HAS_ANSI_STRING_STREAM) +IF(NOT CMAKE_HAS_ANSI_STRING_STREAM) + SET(CMAKE_NO_ANSI_STRING_STREAM 1 CACHE INTERNAL + "Does the compiler support sstream or stringstream.") +ENDIF(NOT CMAKE_HAS_ANSI_STRING_STREAM) + +SET(VTK_SIZEOF_CHAR ${CMAKE_SIZEOF_CHAR}) +SET(VTK_SIZEOF_DOUBLE ${CMAKE_SIZEOF_DOUBLE}) +SET(VTK_SIZEOF_FLOAT ${CMAKE_SIZEOF_FLOAT}) +SET(VTK_SIZEOF_INT ${CMAKE_SIZEOF_INT}) +SET(VTK_SIZEOF_LONG ${CMAKE_SIZEOF_LONG}) +SET(VTK_SIZEOF_SHORT ${CMAKE_SIZEOF_SHORT}) +CHECK_TYPE_SIZE("long long" VTK_SIZEOF_LONG_LONG) +CHECK_TYPE_SIZE("__int64" VTK_SIZEOF___INT64) + +IF(VTK_SIZEOF___INT64) + IF("VTK_TYPE_SAME_LONG_AND___INT64" MATCHES "^VTK_TYPE_SAME_LONG_AND___INT64$") + MESSAGE(STATUS "Checking whether long and __int64 are the same type") + TRY_COMPILE(VTK_TYPE_SAME_LONG_AND___INT64 + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestCompareTypes.cxx + COMPILE_DEFINITIONS + -DVTK_TEST_COMPARE_TYPE_1=long + -DVTK_TEST_COMPARE_TYPE_2=__int64 + OUTPUT_VARIABLE OUTPUT) + IF(VTK_TYPE_SAME_LONG_AND___INT64) + MESSAGE(STATUS "Checking whether long and __int64 are the same type -- yes") + SET(VTK_TYPE_SAME_LONG_AND___INT64 1 CACHE INTERNAL "Whether long and __int64 are the same type") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining whether long and __int64 are the same type " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_TYPE_SAME_LONG_AND___INT64) + MESSAGE(STATUS "Checking whether long and __int64 are the same type -- no") + SET(VTK_TYPE_SAME_LONG_AND___INT64 0 CACHE INTERNAL "Whether long and __int64 are the same type") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining whether long and __int64 are the same type " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_TYPE_SAME_LONG_AND___INT64) + ENDIF("VTK_TYPE_SAME_LONG_AND___INT64" MATCHES "^VTK_TYPE_SAME_LONG_AND___INT64$") + IF(VTK_SIZEOF_LONG_LONG) + IF("VTK_TYPE_SAME_LONG_LONG_AND___INT64" MATCHES "^VTK_TYPE_SAME_LONG_LONG_AND___INT64$") + MESSAGE(STATUS "Checking whether long long and __int64 are the same type") + TRY_COMPILE(VTK_TYPE_SAME_LONG_LONG_AND___INT64 + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestCompareTypes.cxx + COMPILE_DEFINITIONS + -DVTK_TEST_COMPARE_TYPE_1=TYPE_LONG_LONG + -DVTK_TEST_COMPARE_TYPE_2=__int64 + OUTPUT_VARIABLE OUTPUT) + IF(VTK_TYPE_SAME_LONG_LONG_AND___INT64) + MESSAGE(STATUS "Checking whether long long and __int64 are the same type -- yes") + SET(VTK_TYPE_SAME_LONG_LONG_AND___INT64 1 CACHE INTERNAL "Whether long long and __int64 are the same type") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining whether long long and __int64 are the same type " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_TYPE_SAME_LONG_LONG_AND___INT64) + MESSAGE(STATUS "Checking whether long long and __int64 are the same type -- no") + SET(VTK_TYPE_SAME_LONG_LONG_AND___INT64 0 CACHE INTERNAL "Whether long long and __int64 are the same type") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining whether long long and __int64 are the same type " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_TYPE_SAME_LONG_LONG_AND___INT64) + ENDIF("VTK_TYPE_SAME_LONG_LONG_AND___INT64" MATCHES "^VTK_TYPE_SAME_LONG_LONG_AND___INT64$") + ENDIF(VTK_SIZEOF_LONG_LONG) + IF(NOT VTK_TYPE_SAME_LONG_AND___INT64) + IF(NOT VTK_TYPE_SAME_LONG_LONG_AND___INT64) + # VS 6 cannot convert unsigned __int64 to double unless the + # "Visual C++ Processor Pack" is installed. + IF("VTK_TYPE_CONVERT_UI64_TO_DOUBLE" MATCHES "^VTK_TYPE_CONVERT_UI64_TO_DOUBLE$") + MESSAGE(STATUS "Checking whether unsigned __int64 can convert to double") + TRY_COMPILE(VTK_TYPE_CONVERT_UI64_TO_DOUBLE + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestConvertTypes.cxx + COMPILE_DEFINITIONS + -DVTK_TEST_CONVERT_TYPE_FROM=TYPE_UNSIGNED___INT64 + -DVTK_TEST_CONVERT_TYPE_TO=double + OUTPUT_VARIABLE OUTPUT) + IF(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + MESSAGE(STATUS "Checking whether unsigned __int64 can convert to double -- yes") + SET(VTK_TYPE_CONVERT_UI64_TO_DOUBLE 1 CACHE INTERNAL "Whether unsigned __int64 can convert to double") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining whether unsigned __int64 can convert to double " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + MESSAGE(STATUS "Checking whether unsigned __int64 can convert to double -- no") + SET(VTK_TYPE_CONVERT_UI64_TO_DOUBLE 0 CACHE INTERNAL "Whether unsigned __int64 can convert to double") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining whether unsigned __int64 can convert to double " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + ENDIF("VTK_TYPE_CONVERT_UI64_TO_DOUBLE" MATCHES "^VTK_TYPE_CONVERT_UI64_TO_DOUBLE$") + ENDIF(NOT VTK_TYPE_SAME_LONG_LONG_AND___INT64) + ENDIF(NOT VTK_TYPE_SAME_LONG_AND___INT64) +ENDIF(VTK_SIZEOF___INT64) + +# Enable the "long long" type if it is available. It is standard in +# C99 and C++03 but not in earlier standards. +SET(VTK_TYPE_USE_LONG_LONG) +IF(VTK_SIZEOF_LONG_LONG) + SET(VTK_TYPE_USE_LONG_LONG 1) +ENDIF(VTK_SIZEOF_LONG_LONG) + +# Enable the "__int64" type if it is available and unique. It is not +# standard. +SET(VTK_TYPE_USE___INT64) +IF(VTK_SIZEOF___INT64) + IF(NOT VTK_TYPE_SAME_LONG_AND___INT64) + IF(NOT VTK_TYPE_SAME_LONG_LONG_AND___INT64) + SET(VTK_TYPE_USE___INT64 1) + ENDIF(NOT VTK_TYPE_SAME_LONG_LONG_AND___INT64) + ENDIF(NOT VTK_TYPE_SAME_LONG_AND___INT64) +ENDIF(VTK_SIZEOF___INT64) + +IF("VTK_COMPILER_HAS_BOOL" MATCHES "^VTK_COMPILER_HAS_BOOL$") + MESSAGE(STATUS "Checking support for C++ type bool") + TRY_COMPILE(VTK_COMPILER_HAS_BOOL + ${VTK_BINARY_DIR}/CMakeTmp/Bool + ${VTK_SOURCE_DIR}/CMake/vtkTestBoolType.cxx + OUTPUT_VARIABLE OUTPUT) + IF(VTK_COMPILER_HAS_BOOL) + MESSAGE(STATUS "Checking support for C++ type bool -- yes") + SET(VTK_COMPILER_HAS_BOOL 1 CACHE INTERNAL "Support for C++ type bool") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining if the C++ compiler supports type bool " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_COMPILER_HAS_BOOL) + MESSAGE(STATUS "Checking support for C++ type bool -- no") + SET(VTK_COMPILER_HAS_BOOL 0 CACHE INTERNAL "Support for C++ type bool") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining if the C++ compiler supports type bool " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_COMPILER_HAS_BOOL) +ENDIF("VTK_COMPILER_HAS_BOOL" MATCHES "^VTK_COMPILER_HAS_BOOL$") + +IF("VTK_COMPILER_HAS_FULL_SPECIALIZATION" MATCHES "^VTK_COMPILER_HAS_FULL_SPECIALIZATION$") + MESSAGE(STATUS "Checking support for full template specialization syntax") + TRY_COMPILE(VTK_COMPILER_HAS_FULL_SPECIALIZATION + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestFullSpecialization.cxx + OUTPUT_VARIABLE OUTPUT) + IF(VTK_COMPILER_HAS_FULL_SPECIALIZATION) + MESSAGE(STATUS "Checking support for full template specialization syntax -- yes") + SET(VTK_COMPILER_HAS_FULL_SPECIALIZATION 1 CACHE INTERNAL "Support for full template specialization syntax") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining if the C++ compiler supports full template specialization syntax " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_COMPILER_HAS_FULL_SPECIALIZATION) + MESSAGE(STATUS "Checking support for full template specialization syntax -- no") + SET(VTK_COMPILER_HAS_FULL_SPECIALIZATION 0 CACHE INTERNAL "Support for full template specialization syntax") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining if the C++ compiler supports full template specialization syntax " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_COMPILER_HAS_FULL_SPECIALIZATION) +ENDIF("VTK_COMPILER_HAS_FULL_SPECIALIZATION" MATCHES "^VTK_COMPILER_HAS_FULL_SPECIALIZATION$") + +IF("VTK_TYPE_CHAR_IS_SIGNED" MATCHES "^VTK_TYPE_CHAR_IS_SIGNED$") + MESSAGE(STATUS "Checking signedness of char") + TRY_RUN(VTK_TYPE_CHAR_IS_SIGNED VTK_TYPE_CHAR_IS_SIGNED_COMPILED + ${VTK_BINARY_DIR}/CMakeTmp/Char + ${VTK_SOURCE_DIR}/CMake/vtkTestCharSignedness.cxx) + IF(VTK_TYPE_CHAR_IS_SIGNED_COMPILED) + IF(VTK_TYPE_CHAR_IS_SIGNED) + MESSAGE(STATUS "Checking signedness of char -- signed") + SET(VTK_TYPE_CHAR_IS_SIGNED 1 CACHE INTERNAL "Whether char is signed.") + ELSE(VTK_TYPE_CHAR_IS_SIGNED) + MESSAGE(STATUS "Checking signedness of char -- unsigned") + SET(VTK_TYPE_CHAR_IS_SIGNED 0 CACHE INTERNAL "Whether char is signed.") + ENDIF(VTK_TYPE_CHAR_IS_SIGNED) + ELSE(VTK_TYPE_CHAR_IS_SIGNED_COMPILED) + MESSAGE(STATUS "Checking signedness of char -- failed") + ENDIF(VTK_TYPE_CHAR_IS_SIGNED_COMPILED) +ENDIF("VTK_TYPE_CHAR_IS_SIGNED" MATCHES "^VTK_TYPE_CHAR_IS_SIGNED$") + +INCLUDE(Parallel/VTKParallelCMakeTests.cmake) + +# Check for explicit template instantiation support by compiler. +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkTestExplicitInstantiation.cmake) + +# Setup clean configuration of vtkConfigure.h and vtkToolkits.h. +MACRO(VTK_PREPARE_CMAKEDEFINE not invar outvar) + IF(${not} ${invar}) + SET(${outvar} 1) + ELSE(${not} ${invar}) + SET(${outvar}) + ENDIF(${not} ${invar}) +ENDMACRO(VTK_PREPARE_CMAKEDEFINE) +VTK_PREPARE_CMAKEDEFINE("" CMAKE_WORDS_BIGENDIAN VTK_WORDS_BIGENDIAN) +VTK_PREPARE_CMAKEDEFINE("" CMAKE_USE_PTHREADS VTK_USE_PTHREADS) +VTK_PREPARE_CMAKEDEFINE("" CMAKE_USE_SPROC VTK_USE_SPROC) +VTK_PREPARE_CMAKEDEFINE("" CMAKE_HP_PTHREADS VTK_HP_PTHREADS) +VTK_PREPARE_CMAKEDEFINE("" CMAKE_USE_WIN32_THREADS VTK_USE_WIN32_THREADS) +VTK_PREPARE_CMAKEDEFINE("" CMAKE_NO_ANSI_STRING_STREAM VTK_NO_ANSI_STRING_STREAM) +VTK_PREPARE_CMAKEDEFINE("" CMAKE_NO_STD_NAMESPACE VTK_NO_STD_NAMESPACE) +VTK_PREPARE_CMAKEDEFINE(NOT CMAKE_ANSI_FOR_SCOPE VTK_NO_FOR_SCOPE) +VTK_PREPARE_CMAKEDEFINE(NOT VTK_EXPLICIT_TEMPLATES + VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION) +VTK_PREPARE_CMAKEDEFINE(NOT VTK_COMPILER_HAS_FULL_SPECIALIZATION + VTK_NO_FULL_TEMPLATE_SPECIALIZATION) + +#----------------------------------------------------------------------------- +# Include file dependency tracking regular expression. +SET(VTK_REGEX "vtk[^.]*\\.([^t]|t[^x]|tx[^x]|cxx|hxx)") +IF(VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION) + # Track all .txx file dependencies. + SET(VTK_REGEX_TXX "vtk[^.]*\\.txx") +ELSE(VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION) + # Track all .txx file dependencies except *Implicit.txx files. + SET(VTK_REGEX_TXX "vtk[^.]*([^t]|[^i]t|[^c]it|[^i]cit|[^l]icit|[^p]licit|[^m]plicit|[^I]mplicit)\\.txx") +ENDIF(VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION) +INCLUDE_REGULAR_EXPRESSION("^((lex|png|j|z|t|D).*|${VTK_REGEX}|${VTK_REGEX_TXX})$") + +#----------------------------------------------------------------------------- +# Determine the set of language wrappers that should be built. +OPTION(VTK_WRAP_TCL "Wrap VTK classes into the TCL language." OFF) +OPTION(VTK_WRAP_PYTHON "Wrap VTK classes into the Python language." OFF) +OPTION(VTK_WRAP_JAVA "Wrap VTK classes into the Java language." OFF) + +# Python requires shared libraries. +IF(VTK_WRAP_PYTHON) + IF(NOT BUILD_SHARED_LIBS) + MESSAGE(SEND_ERROR "VTK_WRAP_PYTHON requires BUILD_SHARED_LIBS to be ON.") + SET(VTK_WRAP_PYTHON 0) + ENDIF(NOT BUILD_SHARED_LIBS) +ENDIF(VTK_WRAP_PYTHON) + +# Java requires shared libraries on Windows. +IF(VTK_WRAP_JAVA) + IF(WIN32) + IF(NOT BUILD_SHARED_LIBS) + MESSAGE(SEND_ERROR "VTK_WRAP_JAVA requires BUILD_SHARED_LIBS to be ON.") + SET(VTK_WRAP_JAVA 0) + ENDIF(NOT BUILD_SHARED_LIBS) + ENDIF(WIN32) +ENDIF(VTK_WRAP_JAVA) + +SET(VTK_LANGUAGES "") +IF(VTK_WRAP_TCL) + SET(VTK_LANGUAGES ${VTK_LANGUAGES} TCL) +ENDIF(VTK_WRAP_TCL) +IF(VTK_WRAP_PYTHON) + SET(VTK_LANGUAGES ${VTK_LANGUAGES} PYTHON) +ENDIF(VTK_WRAP_PYTHON) +IF(VTK_WRAP_JAVA) + SET(VTK_LANGUAGES ${VTK_LANGUAGES} JAVA) +ENDIF(VTK_WRAP_JAVA) + +#----------------------------------------------------------------------------- +# Load the VTK CMake extension modules. This must be done after the +# wrapping language selection. + +# Import the VTK_COMPILE_CMAKE_EXTENSIONS and VTK_LOAD_CMAKE_EXTENSIONS macros +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkCompileCMakeExtensions.cmake) +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkLoadCMakeExtensions.cmake) + +# Compile the extensions into the build tree and load them. +VTK_COMPILE_CMAKE_EXTENSIONS(${VTK_SOURCE_DIR}/CMake ${VTK_BINARY_DIR}/CMake + VTK_CMAKE_EXTENSIONS_COMPILED) +IF(VTK_CMAKE_EXTENSIONS_COMPILED) + VTK_LOAD_CMAKE_EXTENSIONS(${VTK_BINARY_DIR}/CMake) +ENDIF(VTK_CMAKE_EXTENSIONS_COMPILED) + +#----------------------------------------------------------------------------- +# Configure Dart testing support. +INCLUDE(${CMAKE_ROOT}/Modules/Dart.cmake) +MARK_AS_ADVANCED(BUILD_TESTING DART_ROOT TCL_TCLSH) +IF(BUILD_TESTING) + ENABLE_TESTING() + CONFIGURE_FILE(${VTK_SOURCE_DIR}/CMake/CTestCustom.ctest.in + ${VTK_BINARY_DIR}/CMake/CTestCustom.ctest @ONLY) + FILE(WRITE ${VTK_BINARY_DIR}/CTestCustom.cmake + "INCLUDE(\"${VTK_BINARY_DIR}/CMake/CTestCustom.ctest\")\n") + OPTION(VTK_USE_DISPLAY "Turn this option off and tests will not popup windows" ON) + MARK_AS_ADVANCED(VTK_USE_DISPLAY) +ENDIF(BUILD_TESTING) + +SET(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") +SET(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } + catch(vtkstd::exception& e) + { + fprintf(stderr, \"Test driver caught exception: [%s]\\n\", e.what()); + result = -1; + }") + +#----------------------------------------------------------------------------- +# Select a streams library. + +INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkSelectStreamsLibrary.cmake) +VTK_SELECT_STREAMS_LIBRARY(VTK_USE_ANSI_STDLIB ${VTK_SOURCE_DIR}) + +# Check the severity of EOF bugs in the streams library. +SET(VTK_TEST_STREAM_EOF_CXX ${VTK_SOURCE_DIR}/CMake/vtkTestStreamEOF.cxx.in) +CONFIGURE_FILE(${VTK_SOURCE_DIR}/CMake/vtkTestStreamEOF.cxx.in + ${VTK_BINARY_DIR}/CMake/vtkTestStreamEOF.cxx @ONLY IMMEDIATE) +IF(VTK_USE_ANSI_STDLIB) + IF("VTK_ANSI_STREAM_EOF_RESULT" MATCHES "^VTK_ANSI_STREAM_EOF_RESULT$") + MESSAGE(STATUS "Checking ANSI streams end-of-file bug level") + TRY_RUN(VTK_ANSI_STREAM_EOF_RESULT VTK_ANSI_STREAM_EOF_COMPILED + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_BINARY_DIR}/CMake/vtkTestStreamEOF.cxx) + IF(VTK_ANSI_STREAM_EOF_COMPILED) + MESSAGE(STATUS "Checking ANSI streams end-of-file bug level - ${VTK_ANSI_STREAM_EOF_RESULT}") + ELSE(VTK_ANSI_STREAM_EOF_COMPILED) + SET(VTK_ANSI_STREAM_EOF_RESULT 0) + MESSAGE(STATUS "Checking ANSI streams end-of-file bug level - failed to compile test") + ENDIF(VTK_ANSI_STREAM_EOF_COMPILED) + ENDIF("VTK_ANSI_STREAM_EOF_RESULT" MATCHES "^VTK_ANSI_STREAM_EOF_RESULT$") + SET(VTK_STREAM_EOF_SEVERITY ${VTK_ANSI_STREAM_EOF_RESULT}) +ELSE(VTK_USE_ANSI_STDLIB) + IF("VTK_OLD_STREAM_EOF_RESULT" MATCHES "^VTK_OLD_STREAM_EOF_RESULT$") + MESSAGE(STATUS "Checking old streams end-of-file bug level") + TRY_RUN(VTK_OLD_STREAM_EOF_RESULT VTK_OLD_STREAM_EOF_COMPILED + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_BINARY_DIR}/CMake/vtkTestStreamEOF.cxx) + IF(VTK_OLD_STREAM_EOF_COMPILED) + MESSAGE(STATUS "Checking old streams end-of-file bug level - ${VTK_OLD_STREAM_EOF_RESULT}") + ELSE(VTK_OLD_STREAM_EOF_COMPILED) + SET(VTK_OLD_STREAM_EOF_RESULT 0) + MESSAGE(STATUS "Checking old streams end-of-file bug level - failed to compile test") + ENDIF(VTK_OLD_STREAM_EOF_COMPILED) + ENDIF("VTK_OLD_STREAM_EOF_RESULT" MATCHES "^VTK_OLD_STREAM_EOF_RESULT$") + SET(VTK_STREAM_EOF_SEVERITY ${VTK_OLD_STREAM_EOF_RESULT}) +ENDIF(VTK_USE_ANSI_STDLIB) + +IF(VTK_SIZEOF_LONG_LONG) + CONFIGURE_FILE(${VTK_SOURCE_DIR}/CMake/vtkTestStreamLongLong.cxx.in + ${VTK_BINARY_DIR}/CMake/vtkTestStreamLongLong.cxx @ONLY IMMEDIATE) + IF("VTK_OSTREAM_SUPPORTS_LONG_LONG" MATCHES "^VTK_OSTREAM_SUPPORTS_LONG_LONG$") + MESSAGE(STATUS "Checking if ostream supports long long") + TRY_COMPILE(VTK_OSTREAM_SUPPORTS_LONG_LONG + ${VTK_BINARY_DIR} + ${VTK_BINARY_DIR}/CMake/vtkTestStreamLongLong.cxx + COMPILE_DEFINITIONS -DVTK_TEST_OSTREAM_LONG_LONG + OUTPUT_VARIABLE OUTPUT) + IF(VTK_OSTREAM_SUPPORTS_LONG_LONG) + MESSAGE(STATUS "Checking if ostream supports long long -- yes") + SET(VTK_OSTREAM_SUPPORTS_LONG_LONG 1 CACHE INTERNAL "Whether ostream supports long long") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining if ostream supports long long " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_OSTREAM_SUPPORTS_LONG_LONG) + MESSAGE(STATUS "Checking if ostream supports long long -- no") + SET(VTK_OSTREAM_SUPPORTS_LONG_LONG 0 CACHE INTERNAL "Whether ostream supports long long") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining if ostream supports long long " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_OSTREAM_SUPPORTS_LONG_LONG) + ENDIF("VTK_OSTREAM_SUPPORTS_LONG_LONG" MATCHES "^VTK_OSTREAM_SUPPORTS_LONG_LONG$") + IF("VTK_ISTREAM_SUPPORTS_LONG_LONG" MATCHES "^VTK_ISTREAM_SUPPORTS_LONG_LONG$") + MESSAGE(STATUS "Checking if istream supports long long") + TRY_COMPILE(VTK_ISTREAM_SUPPORTS_LONG_LONG + ${VTK_BINARY_DIR} + ${VTK_BINARY_DIR}/CMake/vtkTestStreamLongLong.cxx + COMPILE_DEFINITIONS -DVTK_TEST_ISTREAM_LONG_LONG + OUTPUT_VARIABLE OUTPUT) + IF(VTK_ISTREAM_SUPPORTS_LONG_LONG) + MESSAGE(STATUS "Checking if istream supports long long -- yes") + SET(VTK_ISTREAM_SUPPORTS_LONG_LONG 1 CACHE INTERNAL "Whether istream supports long long") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining if istream supports long long " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_ISTREAM_SUPPORTS_LONG_LONG) + MESSAGE(STATUS "Checking if istream supports long long -- no") + SET(VTK_ISTREAM_SUPPORTS_LONG_LONG 0 CACHE INTERNAL "Whether istream supports long long") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining if istream supports long long " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_ISTREAM_SUPPORTS_LONG_LONG) + ENDIF("VTK_ISTREAM_SUPPORTS_LONG_LONG" MATCHES "^VTK_ISTREAM_SUPPORTS_LONG_LONG$") +ENDIF(VTK_SIZEOF_LONG_LONG) + +IF(VTK_USE_RENDERING AND WIN32) + # Check for vfw32 support + IF("VTK_USE_VIDEO_FOR_WINDOWS" MATCHES "^VTK_USE_VIDEO_FOR_WINDOWS$") + MESSAGE(STATUS "Checking if vfw32 is available") + TRY_COMPILE(VTK_USE_VIDEO_FOR_WINDOWS_DEFAULT + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestvfw32.cxx + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=vfw32" + OUTPUT_VARIABLE OUTPUT) + IF(VTK_USE_VIDEO_FOR_WINDOWS_DEFAULT) + MESSAGE(STATUS "Checking if vfw32 is available -- yes") + OPTION(VTK_USE_VIDEO_FOR_WINDOWS "Enable using Video for Windows (vfw32) for video input and output." ON) + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Checking if vfw32 is available " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_USE_VIDEO_FOR_WINDOWS_DEFAULT) + MESSAGE(STATUS "Checking if vfw32 is available -- no") + OPTION(VTK_USE_VIDEO_FOR_WINDOWS "Enable using Video for Windows (vfw32) for video input and output." OFF) + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Checking if vfw32 is available " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_USE_VIDEO_FOR_WINDOWS_DEFAULT) + MARK_AS_ADVANCED(VTK_USE_VIDEO_FOR_WINDOWS) + ENDIF("VTK_USE_VIDEO_FOR_WINDOWS" MATCHES "^VTK_USE_VIDEO_FOR_WINDOWS$") + + # Check if vfw32 supports the video capture functions + IF(VTK_USE_VIDEO_FOR_WINDOWS) + IF("VTK_VFW_SUPPORTS_CAPTURE" MATCHES "^VTK_VFW_SUPPORTS_CAPTURE$") + MESSAGE(STATUS "Checking if vfw32 supports video capture") + TRY_COMPILE(VTK_VFW_SUPPORTS_CAPTURE + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestvfw32Capture.cxx + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=vfw32" + OUTPUT_VARIABLE OUTPUT) + IF(VTK_VFW_SUPPORTS_CAPTURE) + MESSAGE(STATUS "Checking if vfw32 supports video capture -- yes") + SET(VTK_VFW_SUPPORTS_CAPTURE 1 CACHE INTERNAL "Enable using Video for Windows (vfw32) for video capture.") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Checking if vfw32 supports video capture " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_VFW_SUPPORTS_CAPTURE) + MESSAGE(STATUS "Checking if vfw32 supports video capture -- no") + SET(VTK_VFW_SUPPORTS_CAPTURE 0 CACHE INTERNAL "Enable using Video for Windows (vfw32) for video capture.") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Checking if vfw32 supports video capture " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_VFW_SUPPORTS_CAPTURE) + ENDIF("VTK_VFW_SUPPORTS_CAPTURE" MATCHES "^VTK_VFW_SUPPORTS_CAPTURE$") + ELSE(VTK_USE_VIDEO_FOR_WINDOWS) + SET(VTK_VFW_SUPPORTS_CAPTURE 0) + ENDIF(VTK_USE_VIDEO_FOR_WINDOWS) +ENDIF(VTK_USE_RENDERING AND WIN32) + +#----------------------------------------------------------------------------- +# Configure KWSys to be named "vtksys". +SET(KWSYS_NAMESPACE vtksys) +SET(KWSYS_USE_Process 1) +SET(KWSYS_USE_SystemTools 1) +SET(KWSYS_USE_RegularExpression 1) +SET(KWSYS_USE_CommandLineArguments 1) +SET(KWSYS_USE_Base64 1) +SET(KWSYS_USE_Glob 1) +SET(KWSYS_HEADER_ROOT ${VTK_BINARY_DIR}/Utilities) +SET(KWSYS_PROPERTIES_CXX ${VTK_LIBRARY_PROPERTIES}) +IF(NOT VTK_USE_ANSI_STDLIB) + SET(KWSYS_IOS_FORCE_OLD 1) +ENDIF(NOT VTK_USE_ANSI_STDLIB) +IF(NOT VTK_INSTALL_NO_LIBRARIES) + SET(KWSYS_LIBRARY_INSTALL_DIR ${VTK_INSTALL_LIB_DIR}) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + SET(KWSYS_HEADER_INSTALL_DIR ${VTK_INSTALL_INCLUDE_DIR}) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +#----------------------------------------------------------------------------- +# Dispatch the build into the proper subdirectories. + + +SET(VTK_HAS_EXODUS) +IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.8) + SET(VTK_HAS_EXODUS 1) +ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.8) + MESSAGE(STATUS "CMake older than 2.0 detected. NetCDF will be disabled") +ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.8) + +# Utility libraries and executables. +SUBDIRS(Wrapping Utilities) + +# Build the subdirector for each kit. + +SUBDIRS( + Common + Filtering +# Imaging +# Graphics + GenericFiltering + IO) +IF(VTK_USE_RENDERING) + SUBDIRS(Rendering) + SUBDIRS(VolumeRendering) + SUBDIRS(Hybrid) + SUBDIRS(Widgets) +ENDIF(VTK_USE_RENDERING) +IF(VTK_USE_PARALLEL) + SUBDIRS(Parallel) +ENDIF(VTK_USE_PARALLEL) +IF(VTK_USE_GUISUPPORT) + SUBDIRS(GUISupport) +ENDIF(VTK_USE_GUISUPPORT) + +# Wrapping. +IF(VTK_WRAP_TCL) + SUBDIRS(Wrapping/Tcl) +ENDIF(VTK_WRAP_TCL) +IF(VTK_WRAP_PYTHON) + SUBDIRS(Wrapping/Python) +ENDIF(VTK_WRAP_PYTHON) +IF(VTK_WRAP_JAVA) + SUBDIRS(Wrapping/Java) +ENDIF(VTK_WRAP_JAVA) + +# Testing. +IF(BUILD_TESTING) + MAKE_DIRECTORY(${VTK_BINARY_DIR}/Testing/Temporary) + # Build scripts to convert tcl tests to python + SUBDIRS(Utilities/vtkTclTest2Py) + SUBDIRS(Common/Testing Filtering/Testing Graphics/Testing GenericFiltering/Testing Imaging/Testing + IO/Testing) + IF(VTK_USE_RENDERING) + SUBDIRS(Rendering/Testing) + SUBDIRS(VolumeRendering/Testing) + SUBDIRS(Hybrid/Testing) + SUBDIRS(Widgets/Testing) + ENDIF(VTK_USE_RENDERING) + IF(VTK_USE_PARALLEL) + SUBDIRS(Parallel/Testing) + ENDIF(VTK_USE_PARALLEL) +ENDIF(BUILD_TESTING) + + +# Include the examples if they are enabled. Note that the in-tree +# build adds tests and a custom target to build the examples project +# in a separate build tree. The examples are not directly included in +# the VTK build. Doing so will not work because they are designed to +# be built out-of-tree. +IF(BUILD_EXAMPLES) + SET(VTK_CMAKE_VERSION_FOR_EXAMPLES) + # The examples tree now requires CMake 2.0.4 or higher. + IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.9) + IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" MATCHES "^2.0$") + # Have version 2.0. Check for the Modules/CMakeTestForFreeVC.cxx + # file which was added in 2.0.4 (this is a nasty hack). + IF(EXISTS ${CMAKE_ROOT}/Modules/CMakeTestForFreeVC.cxx) + SET(VTK_CMAKE_VERSION_FOR_EXAMPLES 1) + ENDIF(EXISTS ${CMAKE_ROOT}/Modules/CMakeTestForFreeVC.cxx) + ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" MATCHES "^2.0$") + # Have version 2.1 or higher. + SET(VTK_CMAKE_VERSION_FOR_EXAMPLES 1) + ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" MATCHES "^2.0$") + ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.9) + IF(VTK_CMAKE_VERSION_FOR_EXAMPLES) + SUBDIRS(Examples) + ELSE(VTK_CMAKE_VERSION_FOR_EXAMPLES) + MESSAGE( + "Warning: The BUILD_EXAMPLES option now requires CMake 2.0.4 or higher " + "and is being ignored.") + ENDIF(VTK_CMAKE_VERSION_FOR_EXAMPLES) +ENDIF(BUILD_EXAMPLES) + +#----------------------------------------------------------------------------- +# Provide a few configuration options. +OPTION(BUILD_EXAMPLES "Build VTK examples." OFF) +OPTION(VTK_USE_64BIT_IDS "Build VTK with 64 bit ids" OFF) +OPTION(VTK_DEBUG_LEAKS "Build leak checking support into VTK." OFF) +MARK_AS_ADVANCED(VTK_DEBUG_LEAKS VTK_USE_64BIT_IDS) + +VTK_DEPENDENT_OPTION(VTK_USE_MANGLED_MESA "Use mangled Mesa with OpenGL." OFF + "VTK_USE_RENDERING" OFF) +VTK_DEPENDENT_OPTION(VTK_OPENGL_HAS_OSMESA + "The opengl library being used supports off screen Mesa calls." OFF + "VTK_USE_RENDERING;UNIX" OFF) +SET(VTK_CAN_DO_OFF_SCREEN) +IF(VTK_USE_MANGLED_MESA OR VTK_OPENGL_HAS_OSMESA) + SET(VTK_CAN_DO_OFF_SCREEN 1) +ENDIF(VTK_USE_MANGLED_MESA OR VTK_OPENGL_HAS_OSMESA) +VTK_DEPENDENT_OPTION(VTK_USE_OFFSCREEN + "The opengl library being used supports off screen Mesa calls." OFF + "VTK_CAN_DO_OFF_SCREEN" OFF) +VTK_DEPENDENT_OPTION(VTK_USE_MPI + "Use Message Passing Interface (MPI) library for parallel support." OFF + "VTK_USE_PARALLEL" OFF) +VTK_DEPENDENT_OPTION(VTK_USE_MATROX_IMAGING + "Use Matrox Imaging Library for video input." OFF + "VTK_USE_RENDERING;WIN32" OFF) +VTK_DEPENDENT_OPTION(VTK_USE_GL2PS "Build VTK with gl2ps support." OFF + "VTK_USE_RENDERING" ON) + +SET(VTK_CAN_USE_TK) +IF(VTK_WRAP_PYTHON OR VTK_WRAP_TCL) + IF(NOT VTK_USE_COCOA) + IF(NOT VTK_DISABLE_TK_INIT) + SET(VTK_CAN_USE_TK 1) + ENDIF(NOT VTK_DISABLE_TK_INIT) + ENDIF(NOT VTK_USE_COCOA) +ENDIF(VTK_WRAP_PYTHON OR VTK_WRAP_TCL) +VTK_DEPENDENT_OPTION(VTK_USE_TK "Build VTK with Tk support" ON + "VTK_CAN_USE_TK" OFF) + +MARK_AS_ADVANCED(VTK_OPENGL_HAS_OSMESA + VTK_USE_OFFSCREEN + VTK_USE_TK + VTK_USE_GL2PS + VTK_USE_MANGLED_MESA + VTK_USE_MATROX_IMAGING + VTK_USE_MPI) + +#----------------------------------------------------------------------------- +# Provide options to use system versions of third-party libraries. +VTK_THIRD_PARTY_OPTION(ZLIB zlib) +VTK_THIRD_PARTY_OPTION(JPEG jpeg) +VTK_THIRD_PARTY_OPTION(PNG png) +VTK_THIRD_PARTY_OPTION(TIFF tiff) +VTK_THIRD_PARTY_OPTION(EXPAT expat) +VTK_THIRD_PARTY_OPTION(FREETYPE freetype) + +#----------------------------------------------------------------------------- +# Configure OpenGL support. +IF(VTK_USE_RENDERING) + # At the moment CMake's FindOpenGL considers OpenGL should be found + # in the framework version on OSX. This is a reasonable assumption for + # few people are going to use X. The module warns that if X is to be + # used, one has to set the libs and include dir manually, which is + # exactly what we are going to do below. + IF(APPLE AND VTK_USE_X) + FIND_PATH(OPENGL_INCLUDE_DIR GL/gl.h + /usr/X11R6/include) + FIND_PATH(OPENGL_xmesa_INCLUDE_DIR GL/xmesa.h + /usr/X11R6/include) + FIND_LIBRARY(OPENGL_gl_LIBRARY NAMES GL MesaGL + PATHS /usr/lib /usr/local/lib /usr/X11R6/lib) + FIND_LIBRARY(OPENGL_glu_LIBRARY NAMES GLU MesaGLU + PATHS ${OPENGL_gl_LIBRARY} /usr/lib /usr/local/lib /usr/X11R6/lib) + ENDIF(APPLE AND VTK_USE_X) + INCLUDE(${CMAKE_ROOT}/Modules/FindOpenGL.cmake) +ENDIF(VTK_USE_RENDERING) + +VTK_PREPARE_CMAKEDEFINE("" OPENGL_LIBRARY VTK_USE_OPENGL_LIBRARY) + +#----------------------------------------------------------------------------- +# Configure Mangled MESA support. +IF(VTK_USE_MANGLED_MESA) + INCLUDE(${VTK_SOURCE_DIR}/CMake/FindMangledMesa.cmake) + + MARK_AS_ADVANCED(MANGLED_MESA_INCLUDE_DIR MANGLED_MESA_LIBRARY + MANGLED_OSMESA_INCLUDE_DIR MANGLED_OSMESA_LIBRARY) + + IF(MANGLED_MESA_INCLUDE_DIR) + USE_MANGLED_MESA(${MANGLED_MESA_INCLUDE_DIR}/GL + ${VTK_BINARY_DIR}/MangleMesaInclude) + ENDIF(MANGLED_MESA_INCLUDE_DIR) +ENDIF(VTK_USE_MANGLED_MESA) + +#----------------------------------------------------------------------------- +# Configure Off-Screen MESA support. +IF(VTK_OPENGL_HAS_OSMESA) + INCLUDE(${VTK_SOURCE_DIR}/CMake/FindOSMesa.cmake) + MARK_AS_ADVANCED(OSMESA_INCLUDE_DIR OSMESA_LIBRARY) +ENDIF(VTK_OPENGL_HAS_OSMESA) + +# Off-Screen MESA cannot be used with Mangled MESA. +IF(VTK_OPENGL_HAS_OSMESA AND VTK_USE_MANGLED_MESA) + MESSAGE(SEND_ERROR + "Off-Screen MESA cannot be used with Mangled MESA. Turn off either " + "VTK_OPENGL_HAS_OSMESA or VTK_USE_MANGLED_MESA.") +ENDIF(VTK_OPENGL_HAS_OSMESA AND VTK_USE_MANGLED_MESA) + +#----------------------------------------------------------------------------- +# Configure Matrox Imaging support. +IF(VTK_USE_MATROX_IMAGING) + FIND_LIBRARY(MIL_LIBRARY MIL + "C:/Program Files/Matrox Imaging/mil/library/winnt/msc/dll" + "C:/Program Files/Matrox Imaging/mil/library/windows/msc/dll" + ) + FIND_PATH(MIL_INCLUDE_PATH mil.h + "C:/Program Files/Matrox Imaging/mil/include" + ) +ENDIF(VTK_USE_MATROX_IMAGING) + +#----------------------------------------------------------------------------- +# Configure MPI testing support. +# FLAGS used and set for MPI testing +# VTK_MPIRUN_EXE - full path to mpirun command +# VTK_MPI_NUMPROC_FLAG - flag that is used to tell this mpirun how many procs to start +# VTK_MPI_PREFLAGS - flags used directly before process to be run by mpirun +# VTK_MPI_POSTFLAGS - flags used after all other flags by mpirun +# So, tests will be run something like this: +# ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} 2 ${VTK_MPI_PREFLAGS} executable ${VTK_MPI_POSTFLAGS} +# +IF(VTK_USE_MPI AND BUILD_TESTING) + FIND_PROGRAM(VTK_MPIRUN_EXE NAMES mpirun lamexec PATHS "C:/Program Files/MPICH/mpd/bin") + SET(VTK_MPI_NUMPROC_FLAG "-np" CACHE STRING "Flag used by mpi to specify the number of processes, the next option will be the number of processes. (see ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt for more info.)") + SET(VTK_MPI_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by VTK_MPIRUN_EXE. (see ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt for more info.)") + SET(VTK_MPI_POSTFLAGS "" CACHE STRING "These flags will come after all flags given to MPIRun.(see ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt for more info.)") + SET(VTK_MPI_MAX_NUMPROCS "2" CACHE STRING "Maximum number of processors available to run parallel applications. (see ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt for more info.)") + MARK_AS_ADVANCED( + VTK_MPI_NUMPROC_FLAG VTK_MPIRUN_EXE VTK_MPI_PREFLAGS VTK_MPI_POSTFLAGS VTK_MPI_MAX_NUMPROCS) + SEPARATE_ARGUMENTS(VTK_MPI_PREFLAGS) + SEPARATE_ARGUMENTS(VTK_MPI_POSTFLAGS) +ENDIF(VTK_USE_MPI AND BUILD_TESTING) + +#----------------------------------------------------------------------------- +# Create STL header wrappers to block warnings in the STL headers. +FOREACH(header algorithm deque iterator list map numeric queue set stack string + utility vector exception stdexcept) + SET(VTK_STL_HEADER "${header}") + CONFIGURE_FILE(${VTK_SOURCE_DIR}/Utilities/vtkstd.h.in + ${VTK_BINARY_DIR}/vtkstd/${header} @ONLY IMMEDIATE) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtkstd + FILES ${VTK_BINARY_DIR}/vtkstd/${header}) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDFOREACH(header) + +#----------------------------------------------------------------------------- +# VTK utility script locations. +SET(VTK_DOXYGEN_HOME ${VTK_SOURCE_DIR}/Utilities/Doxygen) +SET(VTK_HEADER_TESTING_PY ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py) +SET(VTK_FIND_STRING_TCL ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl) +SET(VTK_PRINT_SELF_CHECK_TCL ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl) +SET(VTK_RT_IMAGE_TEST_TCL ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl) +IF(VTK_USE_PARALLEL) + SET(VTK_PRT_IMAGE_TEST_TCL ${VTK_SOURCE_DIR}/Common/Testing/Tcl/prtImageTest.tcl) +ENDIF(VTK_USE_PARALLEL) + +#----------------------------------------------------------------------------- +# Configure Tcl wrapping support. + +MACRO (VTK_INCLUDE_TCL_TK_MODULES) + INCLUDE(${CMAKE_ROOT}/Modules/FindTCL.cmake) + SET(VTK_TCL_LIBRARIES ${TCL_LIBRARY}) + IF(UNIX) + # The tcl library needs the math library on unix. + SET(VTK_TCL_LIBRARIES ${VTK_TCL_LIBRARIES} m) + ENDIF(UNIX) + IF(VTK_USE_TK) + SET(VTK_TK_LIBRARIES ${TK_LIBRARY} ${VTK_TCL_LIBRARIES}) + ENDIF(VTK_USE_TK) + INCLUDE(${VTK_SOURCE_DIR}/CMake/vtkTclTkMacros.cmake) + # Hide useless settings provided by FindTCL. + FOREACH(entry + TCL_LIBRARY_DEBUG + TK_LIBRARY_DEBUG + TCL_STUB_LIBRARY + TCL_STUB_LIBRARY_DEBUG + TK_STUB_LIBRARY + TK_STUB_LIBRARY_DEBUG + TK_WISH) + SET(${entry} "${${entry}}" CACHE INTERNAL "This value is not used by VTK.") + ENDFOREACH(entry) +ENDMACRO (VTK_INCLUDE_TCL_TK_MODULES) + +IF(VTK_WRAP_TCL) + SET(VTK_WRAP_TCL3_INIT_DIR "${VTK_SOURCE_DIR}/Wrapping") + INCLUDE("${VTK_SOURCE_DIR}/CMake/vtkWrapTcl.cmake") + + VTK_INCLUDE_TCL_TK_MODULES() + + # Wrapping executables. + UTILITY_SOURCE(VTK_WRAP_TCL_EXE vtkWrapTcl Wrapping vtkWrapTcl.c) + UTILITY_SOURCE(VTK_WRAP_TCL_INIT_EXE vtkWrapTclInit + Wrapping vtkWrapTclInit.c) + FIND_FILE(VTK_WRAP_HINTS hints ${VTK_SOURCE_DIR}/Wrapping) + MARK_AS_ADVANCED(VTK_WRAP_TCL_EXE VTK_WRAP_TCL_INIT_EXE VTK_WRAP_HINTS) + + # VTK tcl executables. + SET(VTK_EXECUTABLE ${EXECUTABLE_OUTPUT_PATH}/vtk) + IF(VTK_USE_PARALLEL AND VTK_USE_MPI) + SET(PVTK_EXECUTABLE ${EXECUTABLE_OUTPUT_PATH}/pvtk) + ENDIF(VTK_USE_PARALLEL AND VTK_USE_MPI) + + # Tcl package location. + SET(VTK_TCL_HOME ${VTK_BINARY_DIR}/Wrapping/Tcl) + + OPTION(VTK_TCL_TK_STATIC "Build with static Tcl/Tk support. TCL_LIBRARY and TK_LIBRARY must point to the corresponding Tcl/Tk static libraries (example, tcl84sx.lib, tk84sx.lib)." OFF) + MARK_AS_ADVANCED(VTK_TCL_TK_STATIC) + +ENDIF(VTK_WRAP_TCL) + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR}/CMake FILES + ${VTK_SOURCE_DIR}/CMake/vtkTclTkMacros.cmake + ${VTK_SOURCE_DIR}/CMake/vtkWrapTcl.cmake + ${VTK_SOURCE_DIR}/CMake/vtkWrapJava.cmake + ${VTK_SOURCE_DIR}/CMake/vtkWrapPython.cmake + ${VTK_SOURCE_DIR}/Wrapping/vtkWrapperInit.data.in + ) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +#----------------------------------------------------------------------------- +# Configure Python wrapping support. +IF(VTK_WRAP_PYTHON) + SET(VTK_WRAP_PYTHON3_INIT_DIR "${VTK_SOURCE_DIR}/Wrapping") + INCLUDE("${VTK_SOURCE_DIR}/CMake/vtkWrapPython.cmake") + INCLUDE(${CMAKE_ROOT}/Modules/FindPythonLibs.cmake) + + # Wrapping executables. + UTILITY_SOURCE(VTK_WRAP_PYTHON_EXE vtkWrapPython Wrapping vtkWrapPython.c) + UTILITY_SOURCE(VTK_WRAP_PYTHON_INIT_EXE vtkWrapPythonInit + Wrapping vtkWrapPythonInit.c) + FIND_FILE(VTK_WRAP_HINTS hints ${VTK_SOURCE_DIR}/Wrapping) + MARK_AS_ADVANCED(VTK_WRAP_PYTHON_EXE VTK_WRAP_PYTHON_INIT_EXE VTK_WRAP_HINTS) + + # VTK tcl executables. + SET(VTK_PYTHON_EXE ${EXECUTABLE_OUTPUT_PATH}/vtkpython) + IF(VTK_USE_PARALLEL AND VTK_USE_MPI) + SET(PVTK_PYTHON_EXE ${EXECUTABLE_OUTPUT_PATH}/pvtkpython) + ENDIF(VTK_USE_PARALLEL AND VTK_USE_MPI) + + # Use separate debug/optimized libraries if they are different. + IF(PYTHON_DEBUG_LIBRARY) + STRING(COMPARE EQUAL "${PYTHON_DEBUG_LIBRARY}" "${PYTHON_LIBRARY}" + VTK_PYTHON_LIBRARIES_MATCH) + IF(VTK_PYTHON_LIBRARIES_MATCH) + SET(VTK_PYTHON_LIBRARIES ${PYTHON_LIBRARY}) + ELSE(VTK_PYTHON_LIBRARIES_MATCH) + SET(VTK_PYTHON_LIBRARIES + optimized ${PYTHON_LIBRARY} + debug ${PYTHON_DEBUG_LIBRARY}) + ENDIF(VTK_PYTHON_LIBRARIES_MATCH) + SET(VTK_WINDOWS_PYTHON_DEBUGGABLE 0) + IF(WIN32) + IF(PYTHON_DEBUG_LIBRARY MATCHES "_d") + SET(VTK_WINDOWS_PYTHON_DEBUGGABLE 1) + ENDIF(PYTHON_DEBUG_LIBRARY MATCHES "_d") + ENDIF(WIN32) + ELSE(PYTHON_DEBUG_LIBRARY) + SET(VTK_PYTHON_LIBRARIES ${PYTHON_LIBRARY}) + ENDIF(PYTHON_DEBUG_LIBRARY) + + # Some python installations on UNIX need to link to extra libraries + # such as zlib (-lz). It is hard to automatically detect the needed + # libraries so instead just give the user an easy way to specify + # the libraries. This should be needed only rarely. It should + # also be moved to the CMake FindPython.cmake module at some point. + IF(UNIX) + IF(DEFINED PYTHON_EXTRA_LIBS) + ELSE(DEFINED PYTHON_EXTRA_LIBS) + SET(PYTHON_EXTRA_LIBS "" CACHE STRING + "Extra libraries to link when linking to python (such as \"z\" for zlib). Separate multiple libraries with semicolons.") + MARK_AS_ADVANCED(PYTHON_EXTRA_LIBS) + ENDIF(DEFINED PYTHON_EXTRA_LIBS) + ENDIF(UNIX) + + # Include any extra libraries for python. + SET(VTK_PYTHON_LIBRARIES ${VTK_PYTHON_LIBRARIES} ${PYTHON_EXTRA_LIBS}) +ENDIF(VTK_WRAP_PYTHON) + +#----------------------------------------------------------------------------- +# Configure Java wrapping support. +IF(VTK_WRAP_JAVA) + SET(VTK_WRAP_JAVA3_INIT_DIR "${VTK_SOURCE_DIR}/Wrapping") + INCLUDE("${VTK_SOURCE_DIR}/CMake/vtkWrapJava.cmake") + INCLUDE(${CMAKE_ROOT}/Modules/FindJava.cmake) + INCLUDE(${CMAKE_ROOT}/Modules/FindJNI.cmake) + + # Wrapping executables. + UTILITY_SOURCE(VTK_WRAP_JAVA_EXE vtkWrapJava Wrapping vtkWrapJava.c) + UTILITY_SOURCE(VTK_PARSE_JAVA_EXE vtkParseJava Wrapping vtkParseJava.c) + FIND_FILE(VTK_WRAP_HINTS hints ${VTK_SOURCE_DIR}/Wrapping) + MARK_AS_ADVANCED(VTK_WRAP_JAVA_EXE VTK_PARSE_JAVA_EXE VTK_WRAP_HINTS) + + # Java package location. + SET(VTK_JAVA_JAR ${LIBRARY_OUTPUT_PATH}/vtk.jar) + SET(VTK_JAVA_HOME ${VTK_BINARY_DIR}/java/vtk) + MAKE_DIRECTORY(${VTK_JAVA_HOME}) +ENDIF(VTK_WRAP_JAVA) + +VTK_PREPARE_CMAKEDEFINE("" JAVA_AWT_INCLUDE_PATH VTK_USE_JAWT) + +#----------------------------------------------------------------------------- +# Configure the Tk library for vtkRendering. +IF(VTK_WRAP_TCL OR VTK_WRAP_PYTHON) + IF(VTK_USE_RENDERING OR VTK_WRAP_TCL) + SET(VTK_INCLUDE_NEED_TCL 1) + ENDIF(VTK_USE_RENDERING OR VTK_WRAP_TCL) + IF(VTK_USE_RENDERING) + IF(VTK_USE_TK) + SET(VTK_INCLUDE_NEED_TK 1) + ENDIF(VTK_USE_TK) + ENDIF(VTK_USE_RENDERING) +ENDIF(VTK_WRAP_TCL OR VTK_WRAP_PYTHON) + +IF(VTK_USE_TK) + INCLUDE(${VTK_SOURCE_DIR}/Wrapping/Tcl/vtkDetermineTkResources.cmake) +ENDIF(VTK_USE_TK) + +IF(VTK_INCLUDE_NEED_TK) + # Need Tk headers and libraries for python TK widgets + IF(NOT VTK_WRAP_TCL) + VTK_INCLUDE_TCL_TK_MODULES() + ENDIF(NOT VTK_WRAP_TCL) + + # Need Tk sources on windows + IF(WIN32) + FIND_PATH(TK_XLIB_PATH + X11/Xlib.h ${TK_INCLUDE_PATH} + ${TK_INCLUDE_PATH}/../xlib) + MARK_AS_ADVANCED(TK_XLIB_PATH) + ENDIF(WIN32) +ENDIF(VTK_INCLUDE_NEED_TK) + +# Need Tk internal headers for Tk initialization. + +SET(VTK_RENDERING_NEED_TK_INTERNAL ${VTK_INCLUDE_NEED_TK}) + +IF(VTK_INCLUDE_NEED_TK) + # Need Tk Internal headers to include tk.h on Cocoa + IF(VTK_USE_RENDERING AND VTK_USE_COCOA) + SET(VTK_RENDERING_NEED_TK_INTERNAL 1) + ENDIF(VTK_USE_RENDERING AND VTK_USE_COCOA) +ENDIF(VTK_INCLUDE_NEED_TK) + +IF (VTK_RENDERING_NEED_TK_INTERNAL AND TK_LIBRARY) + SET (try_file "tkInt.h") + IF (CYGWIN OR WIN32) + SET (try_file "tkWinPort.h") + ENDIF (CYGWIN OR WIN32) + IF (APPLE) + SET (try_file "tkMacOSXPort.h") + ENDIF (APPLE) + IF (try_file) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + SET (TCL_TK_VERSIOND "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + FIND_PATH( + TK_INTERNAL_PATH + ${try_file} + "${VTK_SOURCE_DIR}/Utilities/TclTk/internals/tk${TCL_TK_VERSIOND}" + DOC "The path to the Tk internal headers (${try_file}).") + MARK_AS_ADVANCED(TK_INTERNAL_PATH) + ENDIF (try_file) +ENDIF(VTK_RENDERING_NEED_TK_INTERNAL AND TK_LIBRARY) + +#----------------------------------------------------------------------------- +# Configure the python executable for use by testing. + +# Python executable is used by some tests whether VTK_WRAP_PYTHON is +# on or not. do not add a VTK_WRAP_PYTHON to this if. +SET(VTK_NEED_PYTHON_EXECUTABLE 0) +IF(BUILD_TESTING) + SET(VTK_NEED_PYTHON_EXECUTABLE 1) +ENDIF(BUILD_TESTING) + +# If VTK_WRAP_PYTHON is on, then we need python executable to compile +# scripts. +IF(VTK_WRAP_PYTHON) + SET(VTK_NEED_PYTHON_EXECUTABLE 1) +ENDIF(VTK_WRAP_PYTHON) + +IF(VTK_NEED_PYTHON_EXECUTABLE) + FIND_PROGRAM(PYTHON_EXECUTABLE + NAMES python2.4 python2.3 python2.2 python2.1 python2.0 python1.6 python1.5 python + PATHS + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.2\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.1\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.0\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.6\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\1.5\\InstallPath] +) + MARK_AS_ADVANCED(PYTHON_EXECUTABLE) +ENDIF(VTK_NEED_PYTHON_EXECUTABLE) + +#----------------------------------------------------------------------------- +# Configure the default VTK_DATA_ROOT for the location of VTKData. +FIND_PATH(VTK_DATA_ROOT VTKData.readme + ${VTK_SOURCE_DIR}/../VTKData + ${VTK_SOURCE_DIR}/../../VTKData + $ENV{VTK_DATA_ROOT}) + +#----------------------------------------------------------------------------- +# MPEG2 +# +# Portions of the mpeg2 library are patented. VTK does not enable linking to +# this library by default so VTK can remain "patent free". Users who wish to +# link in mpeg2 functionality must build that library separately and then +# turn on VTK_USE_MPEG2_ENCODER when configuring VTK. After turning on +# VTK_USE_MPEG2_ENCODER, you must also set the CMake variables +# vtkMPEG2Encode_INCLUDE_PATH and vtkMPEG2Encode_LIBRARIES. +# +# To use the patented mpeg2 library, first build it, then set the following +# CMake variables during the VTK configure step: +# VTK_USE_MPEG2_ENCODER = ON +# vtkMPEG2Encode_INCLUDE_PATH = /path/to/vtkmpeg2encode;/path/to/vtkmpeg2encode-bin +# vtkMPEG2Encode_LIBRARIES = /path/to/vtkmpeg2encode-bin/vtkMPEG2Encode.lib +# +# Or using -D args on the cmake/ccmake command line: +# -DVTK_USE_MPEG2_ENCODER:BOOL=ON +# "-DvtkMPEG2Encode_INCLUDE_PATH:PATH=/path/to/vtkmpeg2encode;/path/to/vtkmpeg2encode-bin" +# "-DvtkMPEG2Encode_LIBRARIES:STRING=/path/to/vtkmpeg2encode-bin/vtkMPEG2Encode.lib" +# +# You are solely responsible for any legal issues associated with using +# patented code in your software. +# +OPTION (VTK_USE_MPEG2_ENCODER + "Enable use of the patented mpeg2 library. You are solely responsible for any legal issues associated with using patented code in your software." + OFF) +IF (VTK_USE_MPEG2_ENCODER) + INCLUDE(${VTK_SOURCE_DIR}/CMake/FindMPEG2.cmake OPTIONAL) +ENDIF (VTK_USE_MPEG2_ENCODER) + +#----------------------------------------------------------------------------- +# Configure files with settings for use by the build. +CONFIGURE_FILE(${VTK_SOURCE_DIR}/vtkConfigure.h.in + ${VTK_BINARY_DIR}/vtkConfigure.h @ONLY IMMEDIATE) + +CONFIGURE_FILE(${VTK_SOURCE_DIR}/UseVTK.cmake.in + ${VTK_BINARY_DIR}/UseVTK.cmake COPYONLY IMMEDIATE) + +CONFIGURE_FILE(${VTK_SOURCE_DIR}/vtkToolkits.h.in + ${VTK_BINARY_DIR}/vtkToolkits.h @ONLY) + +#----------------------------------------------------------------------------- +# The entire VTK tree should use the same include path. + +# Create the list of include directories needed for VTK header files. +INCLUDE(${VTK_SOURCE_DIR}/vtkIncludeDirectories.cmake) + +# This should be the only INCLUDE_DIRECTORIES command in the entire +# tree, except for the CMake, Utilities, and Examples directories. We +# need to do this in one place to make sure the order is correct. +INCLUDE_DIRECTORIES( + ${VTK_INCLUDE_DIRS_BUILD_TREE} + ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_INCLUDE_DIRS_BUILD_TREE_CXX} + ${VTK_INCLUDE_DIRS_SYSTEM} +) + +#----------------------------------------------------------------------------- +# Help other projects use VTK. + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + # Install the instantiator headers. + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtkCommonInstantiator + vtkFilteringInstantiator vtkIOInstantiator + vtkGenericFilteringInstantiator) + IF(VTK_USE_RENDERING) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtkRenderingInstantiator) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtkVolumeRenderingInstantiator) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtkHybridInstantiator) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtkWidgetsInstantiator) + ENDIF(VTK_USE_RENDERING) + IF(VTK_USE_PARALLEL) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtkParallelInstantiator) + ENDIF(VTK_USE_PARALLEL) + + # Install cmake extensions so user projects can load them. + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR}/CMake FILES + ${VTK_SOURCE_DIR}/CMake/vtkLoadCMakeExtensions.cmake + ${VTK_SOURCE_DIR}/CMake/vtkMakeInstantiator.cmake + ${VTK_SOURCE_DIR}/CMake/vtkMakeInstantiator.h.in + ${VTK_SOURCE_DIR}/CMake/vtkMakeInstantiator.cxx.in) + IF (VTK_NEED_LOADED_COMMANDS) + FOREACH(cmd VTK_WRAP_TCL2 VTK_WRAP_PYTHON2 VTK_WRAP_JAVA2 + VTK_GENERATE_JAVA_DEPENDENCIES) + IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.0) + # CMake 2.2 and above will set CMAKE_LOADED_COMMAND_ + # to the full path to the actual module that was loaded. Use + # this variable to find the module to install. + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR}/CMake FILES ${CMAKE_LOADED_COMMAND_${cmd}}) + ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.0) + # CMake 2.0 will not tell us what module was loaded. Construct the + # name of the module for this platform. If using a generator with + # multiple configurations the loaded commands are always built Debug. + IF(CMAKE_CONFIGURATION_TYPES) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR}/CMake FILES + "${VTK_BINARY_DIR}/CMake/Debug/${CMAKE_SHARED_MODULE_PREFIX}cm${cmd}${CMAKE_SHARED_MODULE_SUFFIX}") + ELSE(CMAKE_CONFIGURATION_TYPES) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR}/CMake FILES + "${VTK_BINARY_DIR}/CMake/${CMAKE_SHARED_MODULE_PREFIX}cm${cmd}${CMAKE_SHARED_MODULE_SUFFIX}") + ENDIF(CMAKE_CONFIGURATION_TYPES) + ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.0) + ENDFOREACH(cmd) + ENDIF (VTK_NEED_LOADED_COMMANDS) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +# Save library dependencies. +EXPORT_LIBRARY_DEPENDENCIES(${VTK_BINARY_DIR}/VTKLibraryDepends.cmake) + +# Install some files. +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtkConfigure vtkToolkits) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR} .cmake UseVTK VTKLibraryDepends) + IF(VTK_WRAP_HINTS) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR} FILES ${VTK_WRAP_HINTS}) + ENDIF(VTK_WRAP_HINTS) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +#----------------------------------------------------------------------------- +# Build a CPack installer if CPack is available and this is a build of just +# VTK (as opposed to a build of VTK included in some other project...) + +IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") +IF("${VTK_BINARY_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") + +# For now, only build the CPack installer if vtk(.exe) will be available for +# installation: +# +IF(VTK_WRAP_TCL) + SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "VTK - The Visualization Toolkit") + SET(CPACK_PACKAGE_VENDOR "Kitware, Inc.") + SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt") + SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt") + SET(CPACK_PACKAGE_VERSION_MAJOR "${VTK_MAJOR_VERSION}") + SET(CPACK_PACKAGE_VERSION_MINOR "${VTK_MINOR_VERSION}") + SET(CPACK_PACKAGE_VERSION_PATCH "${VTK_BUILD_VERSION}") + SET(CPACK_PACKAGE_INSTALL_DIRECTORY "VTK ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}") + SET(CPACK_SOURCE_PACKAGE_FILE_NAME "vtk-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") + SET(CPACK_PACKAGE_EXECUTABLES + "vtk" "VTK" + ) + + IF(WIN32) + STRING(REGEX REPLACE "/" "\\\\\\\\" CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/Release/VTKInstall.bmp") + + SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\vtk.exe") + SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY}") + SET(CPACK_NSIS_HELP_LINK "http://www.vtk.org") + SET(CPACK_NSIS_URL_INFO_ABOUT "http://www.kitware.com") + SET(CPACK_NSIS_CONTACT "kitware@kitware.com") + ENDIF(WIN32) + + INCLUDE(CPack) +ENDIF(VTK_WRAP_TCL) + +ENDIF("${VTK_BINARY_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") +ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") + +#----------------------------------------------------------------------------- +# Allow local additions to this file without CVS conflicts. +INCLUDE(${VTK_BINARY_DIR}/LocalUserOptions.cmake OPTIONAL) +INCLUDE(${VTK_SOURCE_DIR}/LocalUserOptions.cmake OPTIONAL) + +#----------------------------------------------------------------------------- +# The commands in this directory are intended to be executed as +# the end of the whole configuration process, as a "last step". +# This directory is typically the last SUBDIRS in the main CMakeLists.txt. +SUBDIRS(Utilities/LastConfigureStep) + +# If the version of CMake was too old, complain and build nothing. +# These should be the last lines in this file. +ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.9) + MESSAGE(SEND_ERROR + "This version of CMake is too old to build VTK. " + "Please upgrade to CMake 2.0.") +ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.9) diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt new file mode 100644 index 0000000..fa61346 --- /dev/null +++ b/Common/CMakeLists.txt @@ -0,0 +1,346 @@ +SET(KIT Common) +SET(UKIT COMMON) +SET(KIT_TCL_LIBS ${VTK_TCL_LIBRARIES}) +SET(KIT_PYTHON_LIBS) +SET(KIT_JAVA_LIBS) +SET(KIT_LIBS vtksys) + +IF(WIN32) + IF (NOT VTK_USE_X) + SET(VTK_OWP_ENCODED_C vtkWin32OutputWindowProcessEncoded.c) + SET_SOURCE_FILES_PROPERTIES(${VTK_OWP_ENCODED_C} PROPERTIES WRAP_EXCLUDE 1) + ENDIF (NOT VTK_USE_X) +ENDIF(WIN32) + +IF (APPLE) + SET(KIT_LIBS ${KIT_LIBS} "-framework AppKit") +ENDIF (APPLE) +IF (UNIX) + SET(KIT_LIBS ${KIT_LIBS} ${CMAKE_THREAD_LIBS} ${CMAKE_DL_LIBS} -lm) +ENDIF (UNIX) + +SET( Kit_SRCS +vtkAbstractArray.cxx +vtkAbstractTransform.cxx +vtkAmoebaMinimizer.cxx +vtkAnimationCue.cxx +vtkAnimationScene.cxx +vtkAssemblyNode.cxx +vtkAssemblyPath.cxx +vtkAssemblyPaths.cxx +vtkBitArray.cxx +vtkBox.cxx +vtkByteSwap.cxx +vtkCallbackCommand.cxx +vtkCharArray.cxx +vtkCollection.cxx +vtkCollectionIterator.cxx +vtkCommand.cxx +vtkContourValues.cxx +vtkCriticalSection.cxx +vtkCylindricalTransform.cxx +vtkDataArray.cxx +vtkDataArrayCollection.cxx +vtkDataArrayCollectionIterator.cxx +vtkDataArraySelection.cxx +vtkDebugLeaks.cxx +vtkDebugLeaksManager.cxx +vtkDirectory.cxx +vtkDoubleArray.cxx +vtkDynamicLoader.cxx +vtkEdgeTable.cxx +vtkErrorCode.cxx +vtkEventForwarderCommand.cxx +vtkExtentSplitter.cxx +vtkExtentTranslator.cxx +vtkFastNumericConversion.cxx +vtkFileOutputWindow.cxx +vtkFloatArray.cxx +vtkFunctionParser.cxx +vtkFunctionSet.cxx +vtkGarbageCollector.cxx +vtkGarbageCollectorManager.cxx +vtkGeneralTransform.cxx +vtkHeap.cxx +vtkHomogeneousTransform.cxx +vtkIOStream.cxx +vtkIdList.cxx +vtkIdListCollection.cxx +vtkIdTypeArray.cxx +vtkIdentityTransform.cxx +vtkImplicitFunction.cxx +vtkImplicitFunctionCollection.cxx +vtkIndent.cxx +vtkInitialValueProblemSolver.cxx +vtkInstantiator.cxx +vtkIntArray.cxx +vtkLargeInteger.cxx +vtkLinearTransform.cxx +vtkLogLookupTable.cxx +vtkLongArray.cxx +vtkLookupTable.cxx +vtkMath.cxx +vtkMatrix4x4.cxx +vtkMatrixToHomogeneousTransform.cxx +vtkMatrixToLinearTransform.cxx +vtkMultiPartExtentTranslator.cxx +vtkMultiThreader.cxx +vtkMutexLock.cxx +vtkOStrStreamWrapper.cxx +vtkOStreamWrapper.cxx +vtkObject.cxx +vtkObjectBase.cxx +vtkObjectFactory.cxx +vtkObjectFactoryCollection.cxx +vtkOldStyleCallbackCommand.cxx +vtkOutputWindow.cxx +vtkOverrideInformation.cxx +vtkOverrideInformationCollection.cxx +vtkParametricBoy.cxx +vtkParametricConicSpiral.cxx +vtkParametricCrossCap.cxx +vtkParametricDini.cxx +vtkParametricEllipsoid.cxx +vtkParametricEnneper.cxx +vtkParametricFigure8Klein.cxx +vtkParametricFunction.cxx +vtkParametricKlein.cxx +vtkParametricMobius.cxx +vtkParametricRandomHills.cxx +vtkParametricRoman.cxx +vtkParametricSuperEllipsoid.cxx +vtkParametricSuperToroid.cxx +vtkParametricTorus.cxx +vtkPerspectiveTransform.cxx +vtkPlane.cxx +vtkPlaneCollection.cxx +vtkPlanes.cxx +vtkPoints.cxx +vtkPriorityQueue.cxx +vtkProp.cxx +vtkPropCollection.cxx +vtkProperty2D.cxx +vtkQuadric.cxx +vtkReferenceCount.cxx +vtkRungeKutta2.cxx +vtkRungeKutta4.cxx +vtkRungeKutta45.cxx +vtkScalarsToColors.cxx +vtkShortArray.cxx +vtkSignedCharArray.cxx +vtkSmartPointerBase.cxx +vtkSphericalTransform.cxx +vtkStdString.cxx +vtkStringArray.cxx +vtkStructuredData.cxx +vtkStructuredVisibilityConstraint.cxx +vtkTableExtentTranslator.cxx +vtkTensor.cxx +vtkThreadMessager.cxx +vtkTimeStamp.cxx +vtkTimerLog.cxx +vtkTransform.cxx +vtkTransformCollection.cxx +vtkUnsignedCharArray.cxx +vtkUnsignedIntArray.cxx +vtkUnsignedLongArray.cxx +vtkUnsignedShortArray.cxx +vtkVersion.cxx +vtkVoidArray.cxx +vtkWarpTransform.cxx +vtkWindow.cxx +vtkWindowLevelLookupTable.cxx +vtkXMLFileOutputWindow.cxx +) + +IF(VTK_TYPE_USE_LONG_LONG) + SET(Kit_SRCS ${Kit_SRCS} + vtkLongLongArray.cxx + vtkUnsignedLongLongArray.cxx + ) +ENDIF(VTK_TYPE_USE_LONG_LONG) +IF(VTK_TYPE_USE___INT64) + SET(Kit_SRCS ${Kit_SRCS} vtk__Int64Array.cxx) + IF(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + SET(Kit_SRCS ${Kit_SRCS} vtkUnsigned__Int64Array.cxx) + ENDIF(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) +ENDIF(VTK_TYPE_USE___INT64) + +# Configure data arrays for platform-independent fixed-size types. +# Match the type selection here to that in vtkType.h. +IF(VTK_TYPE_CHAR_IS_SIGNED) + SET(VTK_TYPE_NATIVE_Int8 Char) +ELSE(VTK_TYPE_CHAR_IS_SIGNED) + SET(VTK_TYPE_NATIVE_Int8 SignedChar) +ENDIF(VTK_TYPE_CHAR_IS_SIGNED) +SET(VTK_TYPE_NATIVE_Int16 UnsignedShort) +SET(VTK_TYPE_NATIVE_Int32 UnsignedInt) +SET(VTK_TYPE_NATIVE_UInt8 UnsignedChar) +SET(VTK_TYPE_NATIVE_UInt16 UnsignedShort) +SET(VTK_TYPE_NATIVE_UInt32 UnsignedInt) +IF(VTK_SIZEOF_LONG MATCHES "^8$") + SET(VTK_TYPE_NATIVE_Int64 Long) + SET(VTK_TYPE_NATIVE_UInt64 UnsignedLong) +ELSE(VTK_SIZEOF_LONG MATCHES "^8$") + IF(VTK_SIZEOF_LONG_LONG MATCHES "^8$") + SET(VTK_TYPE_NATIVE_Int64 LongLong) + SET(VTK_TYPE_NATIVE_UInt64 UnsignedLongLong) + ELSE(VTK_SIZEOF_LONG_LONG MATCHES "^8$") + IF(VTK_SIZEOF___INT64 MATCHES "^8$") + SET(VTK_TYPE_NATIVE_Int64 __Int64) + IF(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + SET(VTK_TYPE_NATIVE_UInt64 Unsigned__Int64) + ENDIF(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + ENDIF(VTK_SIZEOF___INT64 MATCHES "^8$") + ENDIF(VTK_SIZEOF_LONG_LONG MATCHES "^8$") +ENDIF(VTK_SIZEOF_LONG MATCHES "^8$") +SET(VTK_TYPE_NATIVE_Float32 Float) +SET(VTK_TYPE_NATIVE_Float64 Double) +FOREACH(t Int8 Int16 Int32 Int64 UInt8 UInt16 UInt32 UInt64 Float32 Float64) + SET(VTK_TYPE_NAME ${t}) + SET(VTK_TYPE_NATIVE ${VTK_TYPE_NATIVE_${t}}) + IF(VTK_TYPE_NATIVE) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/vtkTypedArray.h.in + ${CMAKE_CURRENT_BINARY_DIR}/vtkType${t}Array.h + @ONLY IMMEDIATE) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/vtkTypedArray.cxx.in + ${CMAKE_CURRENT_BINARY_DIR}/vtkType${t}Array.cxx + @ONLY IMMEDIATE) + SET(Kit_SRCS ${Kit_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/vtkType${t}Array.cxx) + ENDIF(VTK_TYPE_NATIVE) +ENDFOREACH(t) + +SET_SOURCE_FILES_PROPERTIES( +# vtkObjectBase is marked ABSTRACT so that instantiators are happy. +vtkAbstractArray +vtkAbstractTransform +vtkCallbackCommand +vtkCommand +vtkDataArray +vtkEventForwarderCommand +vtkFunctionSet +vtkHomogeneousTransform +vtkImplicitFunction +vtkInitialValueProblemSolver +vtkLinearTransform +vtkObjectBase +vtkObjectFactory +vtkOldStyleCallbackCommand +vtkOverrideInformation +vtkOverrideInformationCollection +vtkParametricFunction +vtkProp +vtkScalarsToColors +vtkStructuredData +vtkWarpTransform +vtkWindow +ABSTRACT +) + +SET_SOURCE_FILES_PROPERTIES( + vtkCallbackCommand.cxx + vtkCommand.cxx + vtkDebugLeaksManager.cxx + vtkErrorCode.cxx + vtkEventForwarderCommand.cxx + vtkGarbageCollectorManager.cxx + vtkIOStream.cxx + vtkIndent.cxx + vtkLargeInteger.cxx + vtkOStrStreamWrapper.cxx + vtkOStreamWrapper.cxx + vtkOldStyleCallbackCommand.cxx + vtkSmartPointerBase.cxx + vtkStdString.cxx + vtkTimeStamp.cxx + + WRAP_EXCLUDE +) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS vtkTclUtil.cxx) +SET(Kit_PYTHON_EXTRA_SRCS vtkPythonUtil.cxx) +SET(Kit_JAVA_EXTRA_SRCS vtkJavaUtil.cxx) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +IF (WIN32) + IF (NOT VTK_USE_X) + SET(Kit_SRCS ${Kit_SRCS} vtkWin32OutputWindow.cxx + vtkWin32ProcessOutputWindow.cxx) + SET(Kit_EXTRA_SRCS ${Kit_EXTRA_SRCS} vtkWin32OutputWindowProcessEncoded.c) + SET_SOURCE_FILES_PROPERTIES(vtkWin32OutputWindowProcessEncoded.c + PROPERTIES WRAP_EXCLUDE 1) + ENDIF (NOT VTK_USE_X) +ENDIF (WIN32) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtkDataArrayTemplate + vtkIOStream + vtkIOStreamFwd + vtkSetGet + vtkSmartPointer + vtkSystemIncludes + vtkType + vtkTypeTraits + vtkWin32Header + vtkWindows + ) + + IF(VTK_WRAP_TCL) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtkTcl + vtkTclUtil + vtkTk + ) + ENDIF(VTK_WRAP_TCL) + IF(VTK_WRAP_PYTHON) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtkPythonUtil + ) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} FILES + vtkPython.h + ) + IF (TK_LIBRARY) + IF(NOT VTK_USE_COCOA) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtkTcl + vtkTk + ) + ENDIF(NOT VTK_USE_COCOA) + ENDIF (TK_LIBRARY) + ENDIF(VTK_WRAP_PYTHON) + IF(VTK_WRAP_JAVA) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtkJavaUtil + ) + ENDIF(VTK_WRAP_JAVA) + + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .txx + vtkDataArrayTemplate + vtkDataArrayTemplateImplicit + ) + + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR}/testing FILES + ${VTK_SOURCE_DIR}/${KIT}/Testing/HeaderTesting.py + ${VTK_SOURCE_DIR}/${KIT}/Testing/WindowsMangleList.py + ${VTK_SOURCE_DIR}/${KIT}/Testing/Tcl/FindString.tcl + ${VTK_SOURCE_DIR}/${KIT}/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/${KIT}/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/${KIT}/Testing/Tcl/TestSetGet.tcl + ) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} FILES + ${VTK_SOURCE_DIR}/${KIT}/Testing/Cxx/vtkTestUtilities.h) + IF(VTK_USE_PARALLEL) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR}/testing FILES + ${VTK_SOURCE_DIR}/${KIT}/Testing/Tcl/prtImageTest.tcl) + ENDIF(VTK_USE_PARALLEL) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Common/Testing/CMakeLists.txt b/Common/Testing/CMakeLists.txt new file mode 100644 index 0000000..a097053 --- /dev/null +++ b/Common/Testing/CMakeLists.txt @@ -0,0 +1,143 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Common ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Common" + VTK_COMMON_EXPORT + vtkAbstractIterator.h + vtkAbstractList.h + vtkAbstractMap.h + vtkArrayMap.h + vtkArrayMapIterator.h + vtkAssemblyPaths.h + vtkByteSwap.h + vtkCallbackCommand.h + vtkCommand.h + vtkContainer.h + vtkDataArrayCollection.h + vtkDataArrayTemplate.h + vtkDebugLeaks.h + vtkDebugLeaksManager.h + vtkDynamicLoader.h + vtkEventForwarderCommand.h + vtkErrorCode.h + vtkGarbageCollector.h + vtkGarbageCollectorManager.h + vtkHashMap.h + vtkHashMapIterator.h + vtkIdListCollection.h + vtkImplicitFunctionCollection.h + vtkIOStream.h + vtkIOStreamFwd.h + vtkIndent.h + vtkJavaAwt.h + vtkJavaUtil.h + vtkLargeInteger.h + vtkLinkedList.h + vtkLinkedListIterator.h + vtkMultiPartExtentTranslator.h + vtkOStrStreamWrapper.h + vtkOStreamWrapper.h + vtkObject.h + vtkObjectBase.h + vtkObjectFactoryCollection.h + vtkOldStyleCallbackCommand.h + vtkOverrideInformationCollection.h + vtkPlaneCollection.h + vtkProcessStatistics.h + vtkPropCollection.h + vtkPython.h + vtkPythonUtil.h + vtkRayCastStructures.h + vtkRungeKutta2.h + vtkSetGet.h + vtkSmartPointer.h + vtkSmartPointerBase.h + vtkStdString.h + vtkStructuredData.h + vtkSystemIncludes.h + vtkTclUtil.h + vtkTemplateAliasMacro.h + vtkTimeStamp.h + vtkTransformCollection.h + vtkType.h + vtkTypeTraits.h + vtkVector.h + vtkVectorIterator.h + vtkWin32Header.h + vtkWinCE.h + vtkWindows.h + vtkTcl.h + vtkTk.h + vtkVersion.h + vtkXMLFileOutputWindow.h + ) +ENDIF(PYTHON_EXECUTABLE) + +#----------------------------------------------------------------------------- +# Configure the VTK install test. It is enabled only if the install +# prefix is set to an InstallTest/Root directory under the top of the build +# tree. Note that the install prefix used for the install test must +# not be a 1-level deep subdirectory under the top of the build tree. +# If it were such then a few executables may be confused into thinking +# they are running from the build tree instead of the install tree. +IF(WIN32 OR APPLE) + STRING(TOLOWER "${CMAKE_INSTALL_PREFIX}" VTK_TEST_INSTALL_LEFT) + STRING(TOLOWER "${VTK_BINARY_DIR}/InstallTest/Root" VTK_TEST_INSTALL_RIGHT) +ELSE(WIN32 OR APPLE) + SET(VTK_TEST_INSTALL_LEFT "${CMAKE_INSTALL_PREFIX}") + SET(VTK_TEST_INSTALL_RIGHT "${VTK_BINARY_DIR}/InstallTest/Root") +ENDIF(WIN32 OR APPLE) +STRING(COMPARE EQUAL "${VTK_TEST_INSTALL_LEFT}" "${VTK_TEST_INSTALL_RIGHT}" + VTK_TEST_INSTALL) + +# No install when using rpaths. +IF(VTK_USE_RPATH) + SET(VTK_TEST_INSTALL 0) +ENDIF(VTK_USE_RPATH) + +# We cannot safely implement the install test when there are multiple +# configuration types unless tests are run by CTest 2.2 or higher. +# See VTK/Examples/CMakeLists.txt where it adds the Example-vtkLocal +# test for an explanation. +IF(CMAKE_CONFIGURATION_TYPES) + IF(NOT VTK_TEST_WITH_CTEST) + SET(VTK_TEST_INSTALL 0) + ENDIF(NOT VTK_TEST_WITH_CTEST) +ENDIF(CMAKE_CONFIGURATION_TYPES) + +IF(VTK_TEST_INSTALL) + IF(CMAKE_CONFIGURATION_TYPES) + # There are multiple configurations. Make sure the tested + # configuration is the one that is installed. + SET(DOLLAR "$") + SET(VTK_INSTALL_TEST_CONFIG_TYPE -C "${DOLLAR}{CTEST_CONFIGURATION_TYPE}") + ELSE(CMAKE_CONFIGURATION_TYPES) + # There is only one configuration. It will be installed. + SET(VTK_INSTALL_TEST_CONFIG_TYPE) + ENDIF(CMAKE_CONFIGURATION_TYPES) + + # Add a test to install VTK through the build system install target. + ADD_TEST(Install + ${CMAKE_CTEST_COMMAND} + ${VTK_INSTALL_TEST_CONFIG_TYPE} + --build-and-test ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} + --build-generator ${CMAKE_GENERATOR} + --build-project VTK + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-noclean + --build-target install) +ENDIF(VTK_TEST_INSTALL) + +# Suppress memory checking of some tests +CONFIGURE_FILE(${VTK_SOURCE_DIR}/Common/Testing/CTestCustom.ctest.in + ${VTK_BINARY_DIR}/Common/Testing/CTestCustom.ctest @ONLY) diff --git a/Common/Testing/CTestCustom.ctest.in b/Common/Testing/CTestCustom.ctest.in new file mode 100644 index 0000000..1c03872 --- /dev/null +++ b/Common/Testing/CTestCustom.ctest.in @@ -0,0 +1,41 @@ +SET(CTEST_CUSTOM_MEMCHECK_IGNORE + ${CTEST_CUSTOM_MEMCHECK_IGNORE} + HeaderTesting-Common + HeaderTesting-GenericFiltering + HeaderTesting-Filtering + HeaderTesting-Graphics + HeaderTesting-Hybrid + HeaderTesting-IO + HeaderTesting-Imaging + HeaderTesting-Parallel + HeaderTesting-Rendering + PrintSelf-Common + PrintSelf-GenericFiltering + PrintSelf-Filtering + PrintSelf-Graphics + PrintSelf-Hybrid + PrintSelf-IO + PrintSelf-Imaging + PrintSelf-Parallel + PrintSelf-Rendering + SystemInformation + TestSetObjectMacro-Common + TestSetObjectMacro-GenericFiltering + TestSetObjectMacro-Filtering + TestSetObjectMacro-Graphics + TestSetObjectMacro-Hybrid + TestSetObjectMacro-IO + TestSetObjectMacro-Imaging + TestSetObjectMacro-Parallel + TestSetObjectMacro-Rendering + Install + Example-vtkMy + ) + +SET(CTEST_CUSTOM_MEMCHECK_IGNORE + ${CTEST_CUSTOM_MEMCHECK_IGNORE} + largeImageOffset-image + largeImageParallel-image + Sockets-image + ) + diff --git a/Common/Testing/Cxx/CMakeLists.txt b/Common/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..92400de --- /dev/null +++ b/Common/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,60 @@ +SET(KIT Common) +CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx + ObjectFactory.cxx + otherArrays.cxx + otherEmptyCell.cxx + otherRectilinearGrid.cxx + otherCellBoundaries.cxx + otherCellPosition.cxx + otherStructuredGrid.cxx + otherTimerLog.cxx + otherLookupTable.cxx + otherByteSwap.cxx + otherCellArray.cxx + otherStringArray.cxx + otherCellTypes.cxx + otherFieldData.cxx + quadraticEvaluation.cxx + TestAmoebaMinimizer.cxx + TestGarbageCollector.cxx + TestImageIterator.cxx + TestDirectory.cxx + TestSmartPointer.cxx + SystemInformation.cxx + EXTRA_INCLUDE vtkTestDriver.h +) + +ADD_EXECUTABLE(${KIT}CxxTests ${Tests}) +TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkCommon vtkFiltering) + +SET (TestsToRun ${Tests}) +REMOVE (TestsToRun ${KIT}CxxTests.cxx) + +# Configure a header needed by SystemInformation. +CONFIGURE_FILE("${VTK_SOURCE_DIR}/Common/Testing/Cxx/SystemInformation.h.in" + "${VTK_BINARY_DIR}/Common/Testing/Cxx/SystemInformation.h" + @ONLY IMMEDIATE) + +# +# Add all the executables +FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) +ENDFOREACH (test) + +# +# Add the TestCxxFeatures test by itself so that if it doesn't compile +# we don't loose all the tests for common +# +ADD_EXECUTABLE(TestCxxFeatures TestCxxFeatures.cxx) +TARGET_LINK_LIBRARIES(TestCxxFeatures vtkCommon) +ADD_TEST(TestCxxFeatures ${CXX_TEST_PATH}/TestCxxFeatures) + +# +# Add the TestInstantiator test by itself because it is designed to +# test pulling in all class's symbols. We don't want the other tests +# to draw in symbols. +# +ADD_EXECUTABLE(TestInstantiator TestInstantiator.cxx) +TARGET_LINK_LIBRARIES(TestInstantiator vtkCommon) +ADD_TEST(TestInstantiator ${CXX_TEST_PATH}/TestInstantiator) diff --git a/Common/Testing/Cxx/ObjectFactory.cxx b/Common/Testing/Cxx/ObjectFactory.cxx new file mode 100644 index 0000000..bfa57af --- /dev/null +++ b/Common/Testing/Cxx/ObjectFactory.cxx @@ -0,0 +1,194 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ObjectFactory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkDebugLeaks.h" +#include "vtkObjectFactory.h" +#include "vtkObjectFactoryCollection.h" +#include "vtkOutputWindow.h" +#include "vtkOverrideInformation.h" +#include "vtkOverrideInformationCollection.h" +#include "vtkVersion.h" +#include "vtkVertex.h" + +int failed = 0; + +class vtkTestVertex : public vtkVertex +{ +public: + // Methods from vtkObject + ~vtkTestVertex() + { + } + + vtkTypeRevisionMacro(vtkTestVertex,vtkVertex); + static vtkTestVertex* New() { return new vtkTestVertex; } + vtkTestVertex() { } +private: + vtkTestVertex(const vtkTestVertex&); + void operator=(const vtkTestVertex&); +}; + +vtkCxxRevisionMacro(vtkTestVertex, "$Revision: 1.23 $"); + +class vtkTestVertex2 : public vtkVertex +{ +public: + ~vtkTestVertex2() + { + } + + // Methods from vtkObject + vtkTypeRevisionMacro(vtkTestVertex2,vtkVertex); + static vtkTestVertex2* New() { return new vtkTestVertex2; } + vtkTestVertex2() { } +private: + vtkTestVertex2(const vtkTestVertex2&); + void operator=(const vtkTestVertex2&); +}; + +vtkCxxRevisionMacro(vtkTestVertex2, "$Revision: 1.23 $"); + +VTK_CREATE_CREATE_FUNCTION(vtkTestVertex); +VTK_CREATE_CREATE_FUNCTION(vtkTestVertex2); + +class VTK_EXPORT TestFactory : public vtkObjectFactory +{ +public: + TestFactory(); + static TestFactory* New() { return new TestFactory;} + virtual const char* GetVTKSourceVersion() { return VTK_SOURCE_VERSION; } + const char* GetDescription() { return "A fine Test Factory"; } + +protected: + TestFactory(const TestFactory&); + void operator=(const TestFactory&); +}; + + + + + + +TestFactory::TestFactory() +{ + this->RegisterOverride("vtkVertex", + "vtkTestVertex", + "test vertex factory override", + 1, + vtkObjectFactoryCreatevtkTestVertex); + this->RegisterOverride("vtkVertex", "vtkTestVertex2", + "test vertex factory override 2", + 0, + vtkObjectFactoryCreatevtkTestVertex2); +} + +void TestNewVertex(vtkVertex* v, const char* expectedClassName) +{ + if(strcmp(v->GetClassName(), expectedClassName) != 0) + { + failed = 1; + cout << "Test Failed" << endl; + } +} + + +int ObjectFactory(int, char *[]) +{ + vtkOutputWindow::GetInstance()->PromptUserOff(); + vtkGenericWarningMacro("Test Generic Warning"); + TestFactory* factory = TestFactory::New(); + vtkObjectFactory::RegisterFactory(factory); + factory->Delete(); + vtkVertex* v = vtkVertex::New(); + TestNewVertex(v, "vtkTestVertex"); + v->Delete(); + + // disable all vtkVertex creation with the + factory->Disable("vtkVertex"); + v = vtkVertex::New(); + TestNewVertex(v, "vtkVertex"); + + factory->SetEnableFlag(1, "vtkVertex", "vtkTestVertex2"); + v->Delete(); + v = vtkVertex::New(); + TestNewVertex(v, "vtkTestVertex2"); + + factory->SetEnableFlag(0, "vtkVertex", "vtkTestVertex2"); + factory->SetEnableFlag(1, "vtkVertex", "vtkTestVertex"); + v->Delete(); + v = vtkVertex::New(); + TestNewVertex(v, "vtkTestVertex"); + v->Delete(); + vtkOverrideInformationCollection* oic = + vtkOverrideInformationCollection::New(); + vtkObjectFactory::GetOverrideInformation("vtkVertex", oic); + vtkOverrideInformation* oi; + if(oic->GetNumberOfItems() != 2) + { + cout << "Incorrect number of overrides for vtkVertex, expected 2, got: " + << oic->GetNumberOfItems() << "\n"; + failed = 1; + if(oic->GetNumberOfItems() < 2) + { + return 1; + } + } + vtkCollectionSimpleIterator oicit; + oic->InitTraversal(oicit); + oi = oic->GetNextOverrideInformation(oicit); + oi->GetObjectFactory(); + + if(strcmp(oi->GetClassOverrideName(), "vtkVertex")) + { + cout << "failed: GetClassOverrideName should be vtkVertex, is: " + << oi->GetClassOverrideName() << "\n"; + failed = 1; + } + if(strcmp(oi->GetClassOverrideWithName(), "vtkTestVertex")) + { + cout << "failed: GetClassOverrideWithName should be vtkTestVertex, is: " + << oi->GetClassOverrideWithName() << "\n"; + failed = 1; + } + if(strcmp(oi->GetDescription(), "test vertex factory override")) + { + cout << "failed: GetClassOverrideWithName should be test vertex factory override, is: " + << oi->GetDescription() << "\n"; + failed = 1; + } + + oi = oic->GetNextOverrideInformation(oicit); + if(strcmp(oi->GetClassOverrideName(), "vtkVertex")) + { + cout << "failed: GetClassOverrideName should be vtkVertex, is: " + << oi->GetClassOverrideName() << "\n"; + failed = 1; + } + if(strcmp(oi->GetClassOverrideWithName(), "vtkTestVertex2")) + { + cout << "failed: GetClassOverrideWithName should be vtkTestVertex2, is: " + << oi->GetClassOverrideWithName() << "\n"; + failed = 1; + } + if(strcmp(oi->GetDescription(), "test vertex factory override 2")) + { + cout << "failed: GetClassOverrideWithName should be test vertex factory override 2, is: " + << oi->GetDescription() << "\n"; + failed = 1; + } + oic->Delete(); + vtkObjectFactory::UnRegisterAllFactories(); + return failed; +} diff --git a/Common/Testing/Cxx/SystemInformation.cxx b/Common/Testing/Cxx/SystemInformation.cxx new file mode 100644 index 0000000..88bdfaf --- /dev/null +++ b/Common/Testing/Cxx/SystemInformation.cxx @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SystemInformation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME Test to print system information useful for remote debugging. +// .SECTION Description +// Remote dashboard debugging often requires access to the +// CMakeCache.txt file. This test will display the file. + +#include "vtkDebugLeaks.h" +#include +#include + +void vtkSystemInformationPrintFile(const char* name, ostream& os) +{ + os << "================================================================\n"; + struct stat fs; + if(stat(name, &fs) != 0) + { + os << "The file \"" << name << "\" does not exist.\n"; + return; + } + +#ifdef _WIN32 + ifstream fin(name, ios::in | ios::binary); +#else + ifstream fin(name, ios::in); +#endif + + if(fin) + { + os << "Contents of \"" << name << "\":\n"; + os << "----------------------------------------------------------------\n"; + const int bufferSize = 4096; + char buffer[bufferSize]; + // This copy loop is very sensitive on certain platforms with + // slightly broken stream libraries (like HPUX). Normally, it is + // incorrect to not check the error condition on the fin.read() + // before using the data, but the fin.gcount() will be zero if an + // error occurred. Therefore, the loop should be safe everywhere. + while(fin) + { + fin.read(buffer, bufferSize); + if(fin.gcount()) + { + os.write(buffer, fin.gcount()); + } + } + os.flush(); + } + else + { + os << "Error opening \"" << name << "\" for reading.\n"; + } +} + +int SystemInformation(int,char *[]) +{ + const char* files[] = + { + CMAKE_BINARY_DIR "/CMakeCache.txt", + VTK_BINARY_DIR "/vtkConfigure.h", + VTK_BINARY_DIR "/vtkToolkits.h", + CMAKE_BINARY_DIR "/CMakeFiles/CMakeError.log", + VTK_BINARY_DIR "/CMake/CMakeCache.txt", + VTK_BINARY_DIR "/VTKBuildSettings.cmake", + VTK_BINARY_DIR "/VTKLibraryDepends.cmake", + VTK_BINARY_DIR "/VTKConfig.cmake", + 0 + }; + + const char** f; + for(f = files; *f; ++f) + { + vtkSystemInformationPrintFile(*f, cout); + } + +#if defined(__sgi) && !defined(__GNUC__) && defined(_COMPILER_VERSION) + cout << "SGI compiler version: " << int(_COMPILER_VERSION) << endl; +#endif + + return 0; +} diff --git a/Common/Testing/Cxx/SystemInformation.h.in b/Common/Testing/Cxx/SystemInformation.h.in new file mode 100644 index 0000000..f79ab3c --- /dev/null +++ b/Common/Testing/Cxx/SystemInformation.h.in @@ -0,0 +1,7 @@ +#ifndef __vtk_SystemInformation_h +#define __vtk_SystemInformation_h + +#define VTK_BINARY_DIR "@VTK_BINARY_DIR@" +#define CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@" + +#endif diff --git a/Common/Testing/Cxx/TestAmoebaMinimizer.cxx b/Common/Testing/Cxx/TestAmoebaMinimizer.cxx new file mode 100644 index 0000000..4556cf5 --- /dev/null +++ b/Common/Testing/Cxx/TestAmoebaMinimizer.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestAmoebaMinimizer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkAmoebaMinimizer.h" +#include + +// the function to be minimized +static void vtkFunctionToMinimize(void *arg) +{ + vtkAmoebaMinimizer *minimizer = (vtkAmoebaMinimizer *)arg; + + double x = minimizer->GetParameterValue("x"); + double y = minimizer->GetParameterValue("y"); + double z = minimizer->GetParameterValue("z"); + + double r = (x-5)*(x-5) + (y+2)*(y+2) + (z)*(z); + + minimizer->SetFunctionValue(r); +} + +int TestAmoebaMinimizer(int argc, char*[]) +{ + vtkAmoebaMinimizer *minimizer = vtkAmoebaMinimizer::New(); + + minimizer->SetFunction(&vtkFunctionToMinimize, minimizer); + minimizer->SetParameterValue("x",0.0); + minimizer->SetParameterScale("x",2.0); + minimizer->SetParameterValue("y",0.0); + minimizer->SetParameterScale("y",2.0); + minimizer->SetParameterValue("z",0.0); + minimizer->SetParameterScale("z",2.0); + + minimizer->Minimize(); + + double x = minimizer->GetParameterValue("x"); + double y = minimizer->GetParameterValue("y"); + double z = minimizer->GetParameterValue("z"); + + double r = minimizer->GetFunctionValue(); + + int iterations = minimizer->GetIterations(); + + int maxiterations = minimizer->GetMaxIterations(); + + int noconvergence = minimizer->Iterate(); + + minimizer->Delete(); + + // check parameters to make sure that they converged to the + // correct values + if (argc > 10 || + fabs(x - 5.0) > 1e-4 || + fabs(y + 2.0) > 1e-4 || + fabs(z - 0.0) > 1e-4 || + r > 1e-4 || + iterations >= maxiterations || + noconvergence) + { + return 1; + } + + return 0; +} diff --git a/Common/Testing/Cxx/TestCxxFeatures.cxx b/Common/Testing/Cxx/TestCxxFeatures.cxx new file mode 100644 index 0000000..44882cb --- /dev/null +++ b/Common/Testing/Cxx/TestCxxFeatures.cxx @@ -0,0 +1,664 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestCxxFeatures.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME TestCxxFeatures +// .SECTION Description +// Provides a reference for the set of C++ features that can be used +// by VTK. + +#include "vtkConfigure.h" + +//---------------------------------------------------------------------------- + +/* Check for known compilers. */ + +#if defined(_MSC_VER) +# define VTK_CXX_MSVC +#endif + +#if defined(__sgi) && !defined(__GNUC__) +# define VTK_CXX_SGI +# if !defined(_COMPILER_VERSION) +# define VTK_CXX_SGI_6 +# endif +#endif + +#if defined(__HP_aCC) +# define VTK_CXX_ACC +#endif + +#if defined(__SUNPRO_CC) +# define VTK_CXX_SUNPRO +#endif + +#if defined(__GNUC__) && (__GNUC__ < 3) +# if (__GNUC__ < 3) +# define VTK_CXX_GCC_2 +# elif (__GNUC__ == 3) +# define VTK_CXX_GCC_3 +# endif +#endif + +//---------------------------------------------------------------------------- + +/* Check for known compiler limitations. */ + +// Check for IRIX64-6.5-CC-o32 (old SGI compiler). +#if defined(VTK_CXX_SGI_6) +# define VTK_TYPENAME /* empty */ +# define VTK_CLASS_TEMPLATE_SPECIALIZATION /* empty */ +#endif + +// Check for MSVC. +#if defined(VTK_CXX_MSVC) && (_MSC_VER < 1310) +# define VTK_TYPENAME /* empty */ +#endif + +// Assume standard behavior if symbol is not already defined. +#if !defined(VTK_TYPENAME) +# define VTK_TYPENAME typename +#endif + +// Assume standard behavior if symbol is not already defined. +#if !defined(VTK_CLASS_TEMPLATE_SPECIALIZATION) +# define VTK_CLASS_TEMPLATE_SPECIALIZATION template <> +#endif + +//---------------------------------------------------------------------------- + +#include "vtkSystemIncludes.h" + +//---------------------------------------------------------------------------- + +/* Test inclusion of sstream header. */ +//#if !(defined(VTK_CXX_GCC_2) || defined(VTK_CXX_ACC) || defined(VTK_CXX_SGI_6)) +#if defined(VTK_CXX_GCC_3) +# include +#endif + +//---------------------------------------------------------------------------- + +/* Test inclusion of typeinfo header. */ + +#include + +//---------------------------------------------------------------------------- + +/* Test use of namespaces. */ + +#if !defined(VTK_CXX_SGI_6) +// Fails on kulu.crd IRIX64-6.5-CC-o32 (old SGI compiler). +namespace NamespaceTest {} +namespace {} +void NamespaceTestFunc() {} +namespace NamespaceTest +{ + using ::NamespaceTestFunc; +} +using namespace NamespaceTest; +#endif + +//---------------------------------------------------------------------------- + +/* Test nested classes defined outside. */ + +class NestedTestOuter +{ +public: + NestedTestOuter(); + ~NestedTestOuter(); +private: + class NestedTestInner; + NestedTestInner* Inner; +}; + +class NestedTestOuter::NestedTestInner +{ +public: + NestedTestInner() {} + ~NestedTestInner() {} +}; + +NestedTestOuter::NestedTestOuter() +{ + this->Inner = new NestedTestInner; +} + +NestedTestOuter::~NestedTestOuter() +{ + delete this->Inner; +} + +//---------------------------------------------------------------------------- + +/* Test inclusion of some stl headers. */ +#ifdef _MSC_VER +#pragma warning (push, 2) +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#if !defined(VTK_CXX_SGI_6) +// Fails on kulu.crd IRIX64-6.5-CC-o32 (old SGI compiler). +void UsingStdVector() +{ + using vtkstd::vector; + vector(); +} +#endif + +//---------------------------------------------------------------------------- + +/* Test full template specialization of functions. */ +template +int FullySpecializedFunction(T*) +{ + return 0; +} + +#if !defined(VTK_CXX_SGI) +// Fails on kulu.crd IRIX64-6.5-CC-o32 (old SGI compiler). +// Fails on manifold.crd IRIX64-6.5-CC-n32 (new SGI compiler). +template <> +int FullySpecializedFunction(int*) +{ + return 1; +} +#else +// Let overload resolution pick this one instead. +int FullySpecializedFunction(int*) +{ + return 1; +} +#endif + +int TestFullySpecializedFunction() +{ + int result = 1; + int should_be_0 = FullySpecializedFunction(static_cast(0)); + if(should_be_0 != 0) + { + cerr << "FullySpecializedFunction() returned " + << should_be_0 << ", not 0.\n"; + result = 0; + } + int should_be_1 = FullySpecializedFunction(static_cast(0)); + if(should_be_1 != 1) + { + cerr << "FullySpecializedFunction(int*) returned " + << should_be_1 << ", not 1.\n"; + result = 0; + } + return result; +} + +//---------------------------------------------------------------------------- + +/* Test member template of non-template. */ + +class NonTemplate +{ + void* Pointer; +public: + template void Set(T* t) { this->Pointer = t; } + template void Get(T*& t) { t = static_cast(this->Pointer); } +}; + +int TestNonTemplateMemberTemplate() +{ + int x = 123; + int* px = 0; + NonTemplate nt; + nt.Set(&x); + nt.Get(px); + return (*px == 123); +} + +//---------------------------------------------------------------------------- + +/* Test member template of template. */ + +template +class OuterTemplate +{ + T* Pointer; +public: + template void Set(U* u) { this->Pointer = u; } + template void Get(U*& u) { u = static_cast(this->Pointer); } +}; + +int TestTemplateMemberTemplate() +{ + int x = 123; + int* px = 0; + OuterTemplate nt; + nt.Set(&x); + nt.Get(px); + return (*px == 123); +} + +//---------------------------------------------------------------------------- + +/* Test use of standard "bool" type and values. */ + +#if !defined(VTK_CXX_SGI_6) +bool GetFalse() +{ + return false; +} + +bool GetTrue() +{ + return true; +} + +int TestBool() +{ + int result = 1; + bool should_be_false = GetFalse(); + bool should_be_true = GetTrue(); + if(should_be_false) + { + cerr << "GetFalse() returned " << should_be_false << ", not false.\n"; + result = 0; + } + if(!should_be_true) + { + cerr << "GetTrue() returned " << should_be_true << ", not true.\n"; + result = 0; + } + return result; +} +#endif +//---------------------------------------------------------------------------- + +/* Test full template specialization of classes. */ + +template +struct FullySpecializedClass +{ + static int Method() { return 0; } + typedef T Type; +}; + +VTK_CLASS_TEMPLATE_SPECIALIZATION +struct FullySpecializedClass +{ + static int Method() { return 1; } + typedef int Type; +}; + +template +int TestFullySpecializedClassTrait(T*) +{ + typedef VTK_TYPENAME FullySpecializedClass::Type Type; + if(static_cast(3.1) == 3.1) + { + return 0; + } + return 1; +} + +int TestFullySpecializedClass() +{ + int result = 1; + int should_be_0 = FullySpecializedClass::Method(); + if(should_be_0 != 0) + { + cerr << "FullySpecializedClass::Method() returned " + << should_be_0 << ", not 0.\n"; + result = 0; + } + int should_be_1 = FullySpecializedClass::Method(); + if(should_be_1 != 1) + { + cerr << "FullySpecializedClass::Method() returned " + << should_be_1 << ", not 1.\n"; + result = 0; + } + if(!TestFullySpecializedClassTrait(static_cast(0))) + { + cerr << "Trait lookup of float didn't produce int."; + result = 0; + } + return result; +} + +//---------------------------------------------------------------------------- + +/* Test if(int x = f()) style scoping. */ + +int TestIfScopeHelper(int i) +{ + int result = 1; + if(int x = i) + { + if(x != i) + { + cerr << "TestIfScope: x != " << i << "\n"; + result = 0; + } + } + else + { + if(x != i) + { + cerr << "TestIfScope: x != " << i << "\n"; + result = 0; + } + } + int x = result; + return x; +} + +int TestIfScope() +{ + int result = 1; + if(!TestIfScopeHelper(1)) + { + result = 0; + } + if(!TestIfScopeHelper(0)) + { + result = 0; + } + return result; +} + +//---------------------------------------------------------------------------- + +/* Test non-type template parameter. */ + +template +struct NonTypeTemplate +{ + static int GetValue() { return I; } +}; + +int TestNonTypeTemplate() +{ + int result = 1; + if(NonTypeTemplate<0>::GetValue() != 0) + { + cerr << "NonTypeTemplate<0>::GetValue() != 0\n"; + result = 0; + } + if(NonTypeTemplate<1>::GetValue() != 1) + { + cerr << "NonTypeTemplate<1>::GetValue() != 1\n"; + result = 0; + } + if(NonTypeTemplate<2>::GetValue() != 2) + { + cerr << "NonTypeTemplate<2>::GetValue() != 2\n"; + result = 0; + } + return result; +} + +//---------------------------------------------------------------------------- + +/* Test mixed type and non-type template arguments in a non-trival way. */ + +#if !(defined(VTK_CXX_MSVC) && (_MSC_VER < 1300)) && !defined(__BORLANDC__) +// Visual Studio 6 and Borland do not support this fancy array template. +template +int TestMixedTypeTemplateFunction(T (*)[N]) +{ + return N; +} +int TestMixedTypeTemplate() +{ + int x2[2]; + float x3[3]; + int result = 1; + if(TestMixedTypeTemplateFunction(&x2) != 2) + { + cerr << "TestMixedTypeTemplateFunction(&x2) != 2\n"; + result = 0; + } + if(TestMixedTypeTemplateFunction(&x3) != 3) + { + cerr << "TestMixedTypeTemplateFunction(&x3) != 3\n"; + result = 0; + } + return result; +} +#endif + +//---------------------------------------------------------------------------- + +int TestBinaryWriting() +{ + int result = 1; + // ios::binary does not exist on SGI and OSF cxx (DEC) + // it failed to compile on these machines: + // ct02_oc.crd IRIX64-6.5-CC-64 + // manifold IRIX64-6.5-CC-n32 + // kulu.crd IRIX64-6.5-CC-o32 + // a62.iue.tuwien.ac.at OSF1-V5.1-cxx +#if defined(VTK_CXX_SGI) || defined( __DECCXX_VER) + ofstream fout_with_warning_C4701("TestCxxFeatures_TestBinaryWriting", ios::out ); +#else + ofstream fout_with_warning_C4701("TestCxxFeatures_TestBinaryWriting", ios::out | ios::binary); +#endif + if(!fout_with_warning_C4701) + { + cerr << "Error opening TestCxxFeatures_TestBinaryWriting for binary writing.\n"; + result = 0; + } + return result; +} + +//---------------------------------------------------------------------------- + +class SafeBoolIdiomClass +{ +private: + struct SafeBoolDummy { void Dummy() {} }; + typedef void (SafeBoolDummy::* SafeBool)(); +public: + SafeBoolIdiomClass(int x): Value(x) {} + operator SafeBool() + { + return this->Value? &SafeBoolDummy::Dummy : 0; + } + SafeBool operator !() + { + return this->Value? 0 : &SafeBoolDummy::Dummy; + } +protected: + int Value; +}; + +int TestSafeBoolIdiom() +{ + int result = 1; + SafeBoolIdiomClass cTrue(1); + SafeBoolIdiomClass cFalse(0); + if(cTrue) {} + else + { + cerr << "if(cTrue) evaluates to false.\n"; + result = 0; + } + if(!cTrue) + { + cerr << "if(!cTrue) evaluates to true.\n"; + result = 0; + } + if(cFalse) + { + cerr << "if(cFalse) evaluates to true.\n"; + result = 0; + } + if(!cFalse) {} + else + { + cerr << "if(!cFalse) evaluates to false.\n"; + result = 0; + } + return result; +} + +//---------------------------------------------------------------------------- + +/* Test use of exceptions. */ + +#if defined(_MSC_VER) +# pragma warning (push) +# pragma warning (disable: 4702) /* Unreachable code. */ +#endif + +class TestExceptionUnwind +{ + int* pvalue; +public: + TestExceptionUnwind(int* p): pvalue(p) {} + ~TestExceptionUnwind() { *pvalue = 1; } + void Use() {} +}; + +class ExceptionClass {}; + +void TestThrowException(int* p) +{ + TestExceptionUnwind unwind(p); + unwind.Use(); + throw ExceptionClass(); +} + +int TestException() +{ + int value = 0; + try + { + TestThrowException(&value); + } + catch(ExceptionClass&) + { + if(value) + { + return 1; + } + else + { + cerr << "TestExceptionUnwind object not destroyed!" << endl; + return 0; + } + } + catch(...) + { + cerr << "ExceptionClass not caught!" << endl; + return 0; + } + cerr << "No exception caught!" << endl; + return 0; +} + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +//---------------------------------------------------------------------------- + +/* Test void return type syntax. */ + +void TestVoidReturnInner() {} +void TestVoidReturnOuter() +{ + // Visual Studio 6 and MIPSpro 7.3 do not support void returns. +#if !(defined(_MSC_VER) && (_MSC_VER < 1300) || defined(_COMPILER_VERSION) && (_COMPILER_VERSION < 740)) + return TestVoidReturnInner(); +#endif +} + +// MIPSpro warns about type qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 // type qualifier on return is meaningless +#endif +// Intel C++ warns about type qualifiers on return types. +#if defined(__INTEL_COMPILER) +# pragma warning (push) +# pragma warning (disable:858) // type qualifier on return is meaningless +#endif + +void const TestVoidConstReturn() {} + +#if defined(__INTEL_COMPILER) +# pragma warning (pop) +#endif + +#if defined(_COMPILER_VERSION) +# pragma reset woff 3303 // type qualifier on return is meaningless +#endif + + +//------------------------------------------------------------------- +// See if the following code works on all platforms +#if defined(_MSC_VER) && defined(_DEBUG) +/* MSVC debug hook to prevent dialogs when running from DART. */ +# include +static int TestDriverDebugReport(int type, char* message, int* retVal) +{ + (void)type; (void)retVal; + fprintf(stderr, message); + exit(1); +} +#endif + +//---------------------------------------------------------------------------- + +#define DO_TEST(x) \ + if(x()) { cout << "Passed: " #x "\n"; } \ + else { cout << "Failed: " #x "\n"; result = 1; } + +int main() +{ + int result = 0; + DO_TEST(TestFullySpecializedFunction); + DO_TEST(TestNonTemplateMemberTemplate); + DO_TEST(TestTemplateMemberTemplate); +#if !defined(VTK_CXX_SGI_6) + DO_TEST(TestBool); +#endif + DO_TEST(TestFullySpecializedClass); + DO_TEST(TestIfScope); + DO_TEST(TestNonTypeTemplate); +#if !(defined(VTK_CXX_MSVC) && (_MSC_VER < 1300)) && !defined(__BORLANDC__) + DO_TEST(TestMixedTypeTemplate); +#endif + DO_TEST(TestBinaryWriting); + DO_TEST(TestSafeBoolIdiom); +#ifndef VTK_CXX_GCC_2 // avoid strange exception problem on debian gcc 2.95 + DO_TEST(TestException); +#endif +#if defined(_MSC_VER) && defined(_DEBUG) + // just call the code to shut up a linker warning + int retVal = 0; + if (result) + { + // really shouldn't be calle dunless somehting else failed + // just want to make the compiler think it might get called + // all this will be yanked once I see the results of this test + TestDriverDebugReport(0, "a temp test", &retVal); + } +#endif + return result; +} diff --git a/Common/Testing/Cxx/TestDirectory.cxx b/Common/Testing/Cxx/TestDirectory.cxx new file mode 100644 index 0000000..86a8aaa --- /dev/null +++ b/Common/Testing/Cxx/TestDirectory.cxx @@ -0,0 +1,40 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestDirectory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the Directory class + +#include "vtkDirectory.h" +#include "vtkDebugLeaks.h" + +int TestDirectory(int,char *[]) +{ + vtkDirectory *myDir = vtkDirectory::New(); + vtkDirectory *testDir = vtkDirectory::New(); + myDir->Open ("."); + char buf[1024]; + myDir->GetCurrentWorkingDirectory(buf, 1024); + cout << "Working Directory: " << buf << endl; + // Get each file name in the directory + for (int i = 0; i < myDir->GetNumberOfFiles(); i++) + { + cout << (testDir->Open(myDir->GetFile(i)) == 0 ? "file: " : "dir: ") << myDir->GetFile(i) << endl; + } + + myDir->Delete(); + testDir->Delete(); + return 0; +} diff --git a/Common/Testing/Cxx/TestGarbageCollector.cxx b/Common/Testing/Cxx/TestGarbageCollector.cxx new file mode 100644 index 0000000..7ff9732 --- /dev/null +++ b/Common/Testing/Cxx/TestGarbageCollector.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGarbageCollector.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkCallbackCommand.h" +#include "vtkDebugLeaks.h" +#include "vtkGarbageCollector.h" +#include "vtkObject.h" +#include "vtkSmartPointer.h" + +// A class that simulates a reference loop and participates in garbage +// collection. +class vtkTestReferenceLoop: public vtkObject +{ +public: + static vtkTestReferenceLoop* New() { return new vtkTestReferenceLoop; } + vtkTypeMacro(vtkTestReferenceLoop, vtkObject); + + void Register(vtkObjectBase* o) { this->RegisterInternal(o, 1); } + void UnRegister(vtkObjectBase* o) { this->UnRegisterInternal(o, 1); } + +protected: + vtkTestReferenceLoop() + { + this->Other = new vtkTestReferenceLoop(this); +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkTestReferenceLoop"); +#endif + } + vtkTestReferenceLoop(vtkTestReferenceLoop* other) + { + this->Other = other; + this->Other->Register(this); +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkTestReferenceLoop"); +#endif + } + ~vtkTestReferenceLoop() + { + if(this->Other) + { + this->Other->UnRegister(this); + this->Other = 0; + } + } + + void ReportReferences(vtkGarbageCollector* collector) + { + vtkGarbageCollectorReport(collector, this->Other, "Other"); + } + + vtkTestReferenceLoop* Other; + +private: + vtkTestReferenceLoop(const vtkTestReferenceLoop&); // Not implemented. + void operator=(const vtkTestReferenceLoop&); // Not implemented. +}; + +// A callback that reports when it is called. +static int called = 0; +void MyDeleteCallback(vtkObject*, unsigned long, void*, void*) +{ + called = 1; +} + +// Main test function. +int TestGarbageCollector(int,char *[]) +{ + // Create a callback that reports when it is called. + vtkSmartPointer cc = + vtkSmartPointer::New(); + cc->SetCallback(MyDeleteCallback); + + // Create an object and delete it immediately. It should be + // immediately collected. + vtkTestReferenceLoop* obj = vtkTestReferenceLoop::New(); + obj->AddObserver(vtkCommand::DeleteEvent, cc); + called = 0; + obj->Delete(); + if(!called) + { + cerr << "Object not immediately collected." << endl; + return 1; + } + + // Create an object, enable deferred collection, and delete it. It + // should not be collected yet. + obj = vtkTestReferenceLoop::New(); + obj->AddObserver(vtkCommand::DeleteEvent, cc); + vtkGarbageCollector::DeferredCollectionPush(); + called = 0; + obj->Delete(); + if(called) + { + cerr << "Object collection not deferred." << endl; + return 1; + } + + // Disable deferred collection. The object should be deleted now. + vtkGarbageCollector::DeferredCollectionPop(); + if(!called) + { + cerr << "Deferred collection did not collect object." << endl; + return 1; + } + + return 0; +} diff --git a/Common/Testing/Cxx/TestImageIterator.cxx b/Common/Testing/Cxx/TestImageIterator.cxx new file mode 100644 index 0000000..07e5e9e --- /dev/null +++ b/Common/Testing/Cxx/TestImageIterator.cxx @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestImageIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME Test of image iterators +// .SECTION Description +// this program tests the image iterators +// At this point it only creates an object of every supported type. + +#include "vtkDebugLeaks.h" +#include "vtkImageIterator.h" +#include "vtkImageProgressIterator.h" +#include "vtkImageData.h" + +template +inline int DoTest(T*) +{ + int ext[6] = { 0, 0, 0, 0, 0, 0 }; + vtkImageData *id = vtkImageData::New(); + id->SetExtent(ext); + vtkImageIterator *it = new vtkImageIterator(id,ext); + vtkImageProgressIterator *ipt + = new vtkImageProgressIterator(id,ext,0,0); + delete it; + delete ipt; + id->Delete(); + return 0; +} + + +int TestImageIterator(int,char *[]) +{ + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + DoTest( static_cast( 0 ) ); + + return 0; +} diff --git a/Common/Testing/Cxx/TestInstantiator.cxx b/Common/Testing/Cxx/TestInstantiator.cxx new file mode 100644 index 0000000..107b3ed --- /dev/null +++ b/Common/Testing/Cxx/TestInstantiator.cxx @@ -0,0 +1,45 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestInstantiator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME Test of vtkCommonInstantiator +// .SECTION Description +// Make sure common registers its classes with vtkInstantiator. + +#include "vtkCommonInstantiator.h" + +int main() +{ + int result = 0; + vtkObject* object = vtkInstantiator::CreateInstance("vtkDoubleArray"); + if(object) + { + if(object->IsA("vtkDoubleArray")) + { + cout << "Successfully created an instance of vtkDoubleArray." << endl; + } + else + { + cerr << "Created an instance of " << object->GetClassName() + << "instead of vtkDoubleArray." << endl; + result = 1; + } + object->Delete(); + } + else + { + cerr << "Failed to create an instance of vtkDoubleArray." << endl; + result = 1; + } + return result; +} diff --git a/Common/Testing/Cxx/TestSmartPointer.cxx b/Common/Testing/Cxx/TestSmartPointer.cxx new file mode 100644 index 0000000..a5cd507 --- /dev/null +++ b/Common/Testing/Cxx/TestSmartPointer.cxx @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestSmartPointer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME Test of vtkSmartPointer. +// .SECTION Description +// Tests instantiations of the vtkSmartPointer class template. + +#include "vtkDebugLeaks.h" +#include "vtkFloatArray.h" +#include "vtkIntArray.h" +#include "vtkSmartPointer.h" + +int TestSmartPointer(int,char *[]) +{ + vtkIntArray* ia = vtkIntArray::New(); + + // Coverage: + vtkSmartPointer da1; + vtkSmartPointer da2(ia); + vtkSmartPointer da3(da1); + da1 = ia; + da2 = da1; + da2 == da3; + da2 != da3; + da2 < da3; + da2 <= da3; + da2 > da3; + da2 >= da3; + ia == da3; + ia != da3; + ia < da3; + ia <= da3; + ia > da3; + ia >= da3; + da2 == ia; + da2 != ia; + da2 < ia; + da2 <= ia; + da2 > ia; + da2 >= ia; + da1 == 0; + da1 != 0; + da1 < 0; + da1 <= 0; + da1 > 0; + da1 >= 0; + (*da1).SetNumberOfComponents(1); + if(da2) + { + da2->SetNumberOfComponents(1); + } + if(!da2) + { + cerr << "da2 is NULL!" << "\n"; + return 1; + } + cout << "IntArray: " << da2 << "\n"; + da1 = vtkSmartPointer::NewInstance(ia); + da1.TakeReference(vtkIntArray::New()); + vtkSmartPointer da4 = + vtkSmartPointer::Take(vtkIntArray::New()); + ia->Delete(); + + return 0; +} diff --git a/Common/Testing/Cxx/otherArrays.cxx b/Common/Testing/Cxx/otherArrays.cxx new file mode 100644 index 0000000..2dbd0b0 --- /dev/null +++ b/Common/Testing/Cxx/otherArrays.cxx @@ -0,0 +1,673 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherArrays.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkDebugLeaks.h" +#include "vtkCharArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkIntArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkLongArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkShortArray.h" +#include "vtkUnsignedShortArray.h" +#include "vtkFloatArray.h" +#include "vtkDoubleArray.h" +#include "vtkIdTypeArray.h" + +#define SIZE 1000 + +template +int doArrayTest (ostream& strm, T *ptr, A *array, V value, int size) +{ + float tuple1[SIZE/100]; + double tuple3[SIZE/100]; + double *tuple2; + int i; + int errors = 0; + + strm << "\tResize(0)..."; + ptr->Resize(0); + strm << "OK" << endl; + + strm << "\tResize(10)..."; + ptr->Resize(10); + strm << "OK" << endl; + + strm << "\tResize(5)..."; + ptr->Resize(5); + strm << "OK" << endl; + + strm << "\tResize(size)..."; + ptr->Resize(size); + strm << "OK" << endl; + + strm << "\tSetNumberOfTuples..."; + ptr->SetNumberOfTuples (100); + if (ptr->GetNumberOfTuples() == 100) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + strm << "\tSetNumberOfComponents..."; + ptr->SetNumberOfComponents (10); + if (ptr->GetNumberOfComponents() == 10) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetVoidArray..."; + ptr->SetVoidArray(array, size, 1); + strm << "OK" << endl; + + strm << "CreateDefaultLookupTable" << endl; + ptr->CreateDefaultLookupTable(); + strm << *ptr; + + strm << "\tGetTuple(i)..."; + tuple2 = ptr->GetTuple (2); + int passed = 1; + if (tuple2) + { + for (i = 0; i < 10; i++) + { + strm << *(tuple2 + i) << " "; + if (*(tuple2 + i) != (20 + i)) + { + passed = 0; + break; + } + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tGetTuple(i, double *tuple)..."; + ptr->GetTuple (4, tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + tuple1[i] = static_cast(tuple3[i]); + strm << tuple3[i] << " "; + if (tuple3[i] != (40 + i)) + { + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tvtkDataArray::GetTuple(i, double *tuple)..."; + ((vtkDataArray*)ptr)->GetTuple (4, tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << tuple3[i] << " "; + if (tuple3[i] != (40 + i)) + { + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetValue(i, value)..."; + ptr->SetValue (99, value); + if (ptr->GetValue (99) == value) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertValue(i, value)..."; + ptr->InsertValue (500, value); + if (ptr->GetValue (500) == value) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextValue(value)..."; + if (ptr->GetValue (ptr->InsertNextValue (static_cast(22.0))) == 22.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertComponent(i, j, 5.0)..."; + ptr->InsertComponent (500, 9, 5.0); + if (ptr->GetComponent (500, 9) == 5.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetTuple(i, float *tuple)..."; + ptr->SetTuple (99, tuple1); + for (i=0; i < 10; i++) tuple3[i] = 0; + ptr->GetTuple (99, tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << tuple3[i] << " "; + if (tuple3[i] != (40 + i)) + { + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetTuple(i, double *tuple)..."; + ptr->SetTuple (99, tuple3); + for (i=0; i < 10; i++) tuple3[i] = 0; + ptr->GetTuple (99, tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << tuple3[i] << " "; + if (tuple3[i] != (40 + i)) + { + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertTuple(i, float *tuple)..."; + ptr->InsertTuple (100, tuple1); + for (i=0; i < 10; i++) tuple3[i] = 0; + ptr->GetTuple (100, tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << tuple3[i] << " "; + if (tuple3[i] != (40 + i)) + { + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertTuple(i, double *tuple)..."; + ptr->InsertTuple (100, tuple3); + for (i=0; i < 10; i++) tuple3[i] = 0; + ptr->GetTuple (100, tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << tuple3[i] << " "; + if (tuple3[i] != (40 + i)) + { + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextTuple(float *tuple)..."; + for (i=0; i < 10; i++) tuple1[i] = 30 + i; + ptr->GetTuple (ptr->InsertNextTuple (tuple1), tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << tuple3[i] << " "; + if (tuple3[i] != (30 + i)) + { + strm << "Expected " << 30 + 1 << " "; + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextTuple(double *tuple)..."; + for (i=0; i < 10; i++) tuple3[i] = 40 + i; + ptr->GetTuple (ptr->InsertNextTuple (tuple3), tuple3); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << tuple3[i] << " "; + if (tuple3[i] != (40 + i)) + { + strm << "Expected " << 40 + 1; + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tvtkDataArray::GetData..."; + vtkDoubleArray *farray = vtkDoubleArray::New(); + farray->SetNumberOfComponents(1); + ptr->vtkDataArray::GetData (0, 59, 1, 1, farray); + passed = 1; + for (i = 0; i < 10; i++) + { + strm << farray->GetTuple(i)[0] << " "; + if (farray->GetTuple(i)[0] != (1 + i*10)) + { + passed = 0; + break; + } + } + if (passed) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + + strm << "\tSetTuple1..."; + ptr->SetNumberOfComponents(1); + ptr->SetNumberOfTuples(100); + ptr->SetTuple1(50,10.0); + if (ptr->GetTuple1(50) == 10.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetTuple2..."; + ptr->SetNumberOfComponents(2); + ptr->SetNumberOfTuples(100); + ptr->SetTuple2(50,10.0,20.0); + if (ptr->GetTuple2(50)[0] == 10.0 && + ptr->GetTuple2(50)[1] == 20.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetTuple3..."; + ptr->SetNumberOfComponents(3); + ptr->SetNumberOfTuples(100); + ptr->SetTuple3(50,10.0,20.0,30.0); + if (ptr->GetTuple3(50)[0] == 10.0 && + ptr->GetTuple3(50)[1] == 20.0 && + ptr->GetTuple3(50)[2] == 30.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetTuple4..."; + ptr->SetNumberOfComponents(4); + ptr->SetNumberOfTuples(100); + ptr->SetTuple4(50,10.0,20.0,30.0,40.0); + if (ptr->GetTuple4(50)[0] == 10.0 && + ptr->GetTuple4(50)[1] == 20.0 && + ptr->GetTuple4(50)[2] == 30.0 && + ptr->GetTuple4(50)[3] == 40.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tSetTuple9..."; + ptr->SetNumberOfComponents(9); + ptr->SetNumberOfTuples(100); + ptr->SetTuple9(50,10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0); + if (ptr->GetTuple9(50)[0] == 10.0 && + ptr->GetTuple9(50)[1] == 20.0 && + ptr->GetTuple9(50)[2] == 30.0 && + ptr->GetTuple9(50)[3] == 40.0 && + ptr->GetTuple9(50)[4] == 50.0 && + ptr->GetTuple9(50)[5] == 60.0 && + ptr->GetTuple9(50)[6] == 70.0 && + ptr->GetTuple9(50)[7] == 80.0 && + ptr->GetTuple9(50)[8] == 90.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertTuple1..."; + ptr->SetNumberOfComponents(1); + ptr->SetNumberOfTuples(100); + ptr->InsertTuple1(502,10.0); + if (ptr->GetTuple1(502) == 10.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertTuple2..."; + ptr->SetNumberOfComponents(2); + ptr->SetNumberOfTuples(100); + ptr->InsertTuple2(502,10.0,20.0); + if (ptr->GetTuple2(502)[0] == 10.0 && + ptr->GetTuple2(502)[1] == 20.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertTuple3..."; + ptr->SetNumberOfComponents(3); + ptr->SetNumberOfTuples(100); + ptr->InsertTuple3(502,10.0,20.0,30.0); + if (ptr->GetTuple3(502)[0] == 10.0 && + ptr->GetTuple3(502)[1] == 20.0 && + ptr->GetTuple3(502)[2] == 30.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertTuple4..."; + ptr->SetNumberOfComponents(4); + ptr->SetNumberOfTuples(100); + ptr->InsertTuple4(502,10.0,20.0,30.0,40.0); + if (ptr->GetTuple4(502)[0] == 10.0 && + ptr->GetTuple4(502)[1] == 20.0 && + ptr->GetTuple4(502)[2] == 30.0 && + ptr->GetTuple4(502)[3] == 40.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertTuple9..."; + ptr->SetNumberOfComponents(9); + ptr->SetNumberOfTuples(100); + ptr->InsertTuple9(502,10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0); + if (ptr->GetTuple9(502)[0] == 10.0 && + ptr->GetTuple9(502)[1] == 20.0 && + ptr->GetTuple9(502)[2] == 30.0 && + ptr->GetTuple9(502)[3] == 40.0 && + ptr->GetTuple9(502)[4] == 50.0 && + ptr->GetTuple9(502)[5] == 60.0 && + ptr->GetTuple9(502)[6] == 70.0 && + ptr->GetTuple9(502)[7] == 80.0 && + ptr->GetTuple9(502)[8] == 90.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextTuple1..."; + ptr->SetNumberOfComponents(1); + ptr->SetNumberOfTuples(100); + ptr->InsertNextTuple1(10.0); + if (ptr->GetTuple1(100) == 10.0) strm << "OK" << endl; + else + { + errors++; + strm << " FAILED" << endl; + } + strm << "\tInsertNextTuple2..."; + ptr->SetNumberOfComponents(2); + ptr->SetNumberOfTuples(100); + ptr->InsertNextTuple2(10.0,20.0); + if (ptr->GetTuple2(100)[0] == 10.0 && + ptr->GetTuple2(100)[1] == 20.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextTuple3..."; + ptr->SetNumberOfComponents(3); + ptr->SetNumberOfTuples(100); + ptr->InsertNextTuple3(10.0,20.0,30.0); + if (ptr->GetTuple3(100)[0] == 10.0 && + ptr->GetTuple3(100)[1] == 20.0 && + ptr->GetTuple3(100)[2] == 30.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextTuple4..."; + ptr->SetNumberOfComponents(4); + ptr->SetNumberOfTuples(100); + ptr->InsertNextTuple4(10.0,20.0,30.0,40.0); + if (ptr->GetTuple4(100)[0] == 10.0 && + ptr->GetTuple4(100)[1] == 20.0 && + ptr->GetTuple4(100)[2] == 30.0 && + ptr->GetTuple4(100)[3] == 40.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextTuple9..."; + ptr->SetNumberOfComponents(9); + ptr->SetNumberOfTuples(100); + ptr->InsertNextTuple9(10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0); + if (ptr->GetTuple9(100)[0] == 10.0 && + ptr->GetTuple9(100)[1] == 20.0 && + ptr->GetTuple9(100)[2] == 30.0 && + ptr->GetTuple9(100)[3] == 40.0 && + ptr->GetTuple9(100)[4] == 50.0 && + ptr->GetTuple9(100)[5] == 60.0 && + ptr->GetTuple9(100)[6] == 70.0 && + ptr->GetTuple9(100)[7] == 80.0 && + ptr->GetTuple9(100)[8] == 90.0) strm << "OK" << endl; + else + { + errors++; + strm << "FAILED" << endl; + } + + + farray->Delete(); + + + strm << "PrintSelf..." << endl; + strm << *ptr; + + return errors; +} + +int otherArraysTest(ostream& strm) +{ + int errors = 0; + { + strm << "Test CharArray" << endl; + vtkCharArray *ptr = vtkCharArray::New(); + char *array = new char[SIZE]; + char value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test UnsignedCharArray" << endl; + vtkUnsignedCharArray *ptr = vtkUnsignedCharArray::New(); + unsigned char *array = new unsigned char[SIZE]; + unsigned char value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test IntArray" << endl; + vtkIntArray *ptr = vtkIntArray::New(); + int *array = new int[SIZE]; + int value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test UnsignedIntArray" << endl; + vtkUnsignedIntArray *ptr = vtkUnsignedIntArray::New(); + unsigned int *array = new unsigned int[SIZE]; + unsigned int value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test LongArray" << endl; + vtkLongArray *ptr = vtkLongArray::New(); + long *array = new long[SIZE]; + long value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test UnsignedLongArray" << endl; + vtkUnsignedLongArray *ptr = vtkUnsignedLongArray::New(); + unsigned long *array = new unsigned long[SIZE]; + unsigned long value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test ShortArray" << endl; + vtkShortArray *ptr = vtkShortArray::New(); + short *array = new short[SIZE]; + short value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test UnsignedShortArray" << endl; + vtkUnsignedShortArray *ptr = vtkUnsignedShortArray::New(); + unsigned short *array = new unsigned short[SIZE]; + unsigned short value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test FloatArray" << endl; + vtkFloatArray *ptr = vtkFloatArray::New(); + float *array = new float[SIZE]; + float value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test DoubleArray" << endl; + vtkDoubleArray *ptr = vtkDoubleArray::New(); + double *array = new double[SIZE]; + double value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + + { + strm << "Test IdTypeArray" << endl; + vtkIdTypeArray *ptr = vtkIdTypeArray::New(); + vtkIdType *array = new vtkIdType[SIZE]; + vtkIdType value = static_cast(1); + for (int i = 0; i < SIZE; i++) *(array + i ) = i; + errors += doArrayTest (strm, ptr, array, value, SIZE); + ptr->Delete(); + delete []array; + } + return errors; +} + +int otherArrays(int, char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; +// return otherArraysTest(vtkmsg_with_warning_C4701); + return otherArraysTest(cerr); + +} diff --git a/Common/Testing/Cxx/otherByteSwap.cxx b/Common/Testing/Cxx/otherByteSwap.cxx new file mode 100644 index 0000000..25f3eed --- /dev/null +++ b/Common/Testing/Cxx/otherByteSwap.cxx @@ -0,0 +1,159 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherByteSwap.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the byte swapper + +#include "vtkByteSwap.h" +#include "vtkDebugLeaks.h" + +int TestByteSwap(ostream& strm) +{ + // actual test + strm << "Test vtkByteSwap Start" << endl; + + char check[1024]; + short sword[2]; + char cword[1024]; + unsigned short usword[2]; + + memcpy ((char *) sword, "abcd", 2); + vtkByteSwap::Swap2BE(sword); + memcpy ((char *) check, sword, 2); + strm << "Swap2BE(short \"ab\") -> " << (char) check[0] << (char) check[1] << endl; + + memcpy ((char *) usword, "abcd", 2); + vtkByteSwap::Swap2BE(usword); + memcpy ((char *) check, usword, 2); + strm << "Swap2BE(unsigned short \"ab\") -> " << (char) check[0] << (char) check[1] << endl; + + memcpy ((char *) cword, "abcd", 4); + vtkByteSwap::Swap4BE(cword); + memcpy ((char *) check, cword, 4); + strm << "Swap4BE(char *\"abcd\") -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap8BE(cword); + memcpy ((char *) check, cword, 8); + strm << "Swap8BE(char *\"abcdefgh\") -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap2BERange(cword,8); + memcpy ((char *) check, cword, 8); + strm << "Swap2BERange(char *\"abcdefgh\",8) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap4BERange(cword,8); + memcpy ((char *) check, cword, 8); + strm << "Swap4BERange(char *\"abcdefgh\",8) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap8BERange(cword,8); + memcpy ((char *) check, cword, 8); + strm << "Swap8BERange(char *\"abcdefgh\",8) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefghijklmnop", 16); + strm << "SwapWrite2BERange(char *\"abcdefghijklmnop\",8,stdout) -> "; + vtkByteSwap::SwapWrite2BERange(cword,8,stdout); + strm << endl; + + memcpy ((char *) cword, "abcdefghijklmnop", 16); + strm << "SwapWrite4BERange(char *\"abcdefghijklmnop\",4,stdout) -> "; + vtkByteSwap::SwapWrite4BERange(cword,4,stdout); + strm << endl; + + memcpy ((char *) cword, "abcdefghijklmnop", 16); + strm << "SwapWrite8BERange(char *\"abcdefghijklmnop\",2,stdout) -> "; + vtkByteSwap::SwapWrite8BERange(cword,2,stdout); + strm << endl; + + memcpy ((char *) cword, "abcdefghijklmnop", 16); + strm << "SwapWrite2BERange(char *\"abcdefghijklmnop\",8,&strm) -> "; + vtkByteSwap::SwapWrite2BERange(cword,8,&strm); + strm << endl; + + memcpy ((char *) cword, "abcdefghijklmnop", 16); + strm << "SwapWrite4BERange(char *\"abcdefghijklmnop\",4,&strm) -> "; + vtkByteSwap::SwapWrite4BERange(cword,4,&strm); + strm << endl; + + memcpy ((char *) cword, "abcdefghijklmnop", 16); + strm << "SwapWrite8BERange(char *\"abcdefghijklmnop\",2,&strm) -> "; + vtkByteSwap::SwapWrite8BERange(cword,2,&strm); + strm << endl; + + memcpy ((char *) sword, "abcd", 2); + vtkByteSwap::Swap2LE(sword); + memcpy ((char *) check, sword, 2); + strm << "Swap2LE(short \"ab\") -> " << (char) check[0] << (char) check[1] << endl; + + memcpy ((char *) usword, "abcd", 2); + vtkByteSwap::Swap2LE(usword); + memcpy ((char *) check, usword, 2); + strm << "Swap2LE(unsigned short \"ab\") -> " << (char) check[0] << (char) check[1] << endl; + + memcpy ((char *) cword, "abcd", 4); + vtkByteSwap::Swap4LE(cword); + memcpy ((char *) check, cword, 4); + strm << "Swap4LE(char *\"abcd\") -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap8LE(cword); + memcpy ((char *) check, cword, 8); + strm << "Swap8LE(char *\"abcdefgh\") -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap2LERange(cword,8); + memcpy ((char *) check, cword, 8); + strm << "Swap2LERange(char *\"abcdefgh\",8) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap4LERange(cword,8); + memcpy ((char *) check, cword, 8); + strm << "Swap4LERange(char *\"abcdefgh\",8) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::Swap8LERange(cword,8); + memcpy ((char *) check, cword, 8); + strm << "Swap8LERange(char *\"abcdefgh\",8) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::SwapVoidRange(cword,4,2); + memcpy ((char *) check, cword, 8); + strm << "SwapVoidRange(char *\"abcdefgh\",4,2) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::SwapVoidRange(cword,2,4); + memcpy ((char *) check, cword, 8); + strm << "SwapVoidRange(char *\"abcdefgh\",2,4) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + memcpy ((char *) cword, "abcdefgh", 8); + vtkByteSwap::SwapVoidRange(cword,1,8); + memcpy ((char *) check, cword, 8); + strm << "SwapVoidRange(char *\"abcdefgh\",1,8) -> " << (char) check[0] << (char) check[1] << (char) check[2] << (char) check[3] << (char) check[4] << (char) check[5] << (char) check[6] << (char) check[7] << endl; + + strm << "Test vtkByteSwap End" << endl; + return 0; +} + + +int otherByteSwap(int,char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return TestByteSwap(vtkmsg_with_warning_C4701); +} diff --git a/Common/Testing/Cxx/otherCellArray.cxx b/Common/Testing/Cxx/otherCellArray.cxx new file mode 100644 index 0000000..b827092 --- /dev/null +++ b/Common/Testing/Cxx/otherCellArray.cxx @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherCellArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the CellArray + +#include "vtkDebugLeaks.h" + +#include "vtkCellArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" +#include "vtkQuad.h" + +int TestCellArray(ostream& strm) +{ + // actual test + strm << "Test CellArray Start" << endl; + vtkCellArray *ca = vtkCellArray::New(); + + ca->Initialize(); + strm << "ca->GetNumberOfCells() = " << ca->GetNumberOfCells() << endl; + strm << "ca->GetSize() = " << ca->GetSize() << endl; + strm << "ca->GetNumberOfConnectivityEntries() = " << ca->GetNumberOfConnectivityEntries() << endl; + strm << "ca->EstimateSize (1000, 3) = " << ca->EstimateSize(1000,3) << endl; + + vtkIdType npts = 3; + vtkIdType pts[3] = {0, 1, 2}; + vtkQuad *cell = vtkQuad::New(); + vtkIdList *ids = vtkIdList::New(); + vtkIdType *ptrIds = ids->WritePointer(0,3); + memcpy (ptrIds, pts, 3 * sizeof (vtkIdType)); + + strm << "ca->InsertNextCell (npts, pts) = " << ca->InsertNextCell (npts, pts) << endl; + strm << "ca->InsertNextCell (cell) = " << ca->InsertNextCell (cell) << endl; + strm << "ca->InsertNextCell (ids) = " << ca->InsertNextCell (ids) << endl; + strm << "ca->InsertNextCell (4) = " << ca->InsertNextCell (4) << endl; + ca->InsertCellPoint (3); + ca->InsertCellPoint (4); + ca->InsertCellPoint (5); + + ca->InsertCellPoint (6); + ca->InsertCellPoint (7); + ca->InsertCellPoint (8); + ca->UpdateCellCount (3); + + strm << "ca->GetNumberOfCells() = " << ca->GetNumberOfCells() << endl; + strm << "ca->GetSize() = " << ca->GetSize() << endl; + strm << "ca->GetNumberOfConnectivityEntries() = " << ca->GetNumberOfConnectivityEntries() << endl; + + vtkIdTypeArray *cells = vtkIdTypeArray::New(); + cells->SetNumberOfTuples(12); + vtkIdType idT[12] = {3, 0, 1, 2, 3, 1, 2, 3, 3, 3, 4, 5}; + cells->SetVoidArray(idT,12,1); + ca->Allocate(10000); + ca->SetCells (3, cells); + strm << "ca->GetNumberOfCells() = " << ca->GetNumberOfCells() << endl; + strm << "ca->GetSize() = " << ca->GetSize() << endl; + strm << "ca->GetNumberOfConnectivityEntries() = " << ca->GetNumberOfConnectivityEntries() << endl; + + ca->Delete(); + cell->Delete(); + ids->Delete(); + cells->Delete(); + strm << "Test CellArray Complete" << endl; + + return 0; +} + +int otherCellArray(int,char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return TestCellArray(vtkmsg_with_warning_C4701); +} diff --git a/Common/Testing/Cxx/otherCellBoundaries.cxx b/Common/Testing/Cxx/otherCellBoundaries.cxx new file mode 100644 index 0000000..26c75c0 --- /dev/null +++ b/Common/Testing/Cxx/otherCellBoundaries.cxx @@ -0,0 +1,499 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherCellBoundaries.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the CellBoundary method for each cell type + +#include "vtkDebugLeaks.h" +#include "vtkHexahedron.h" +#include "vtkIdList.h" +#include "vtkLine.h" +#include "vtkPixel.h" +#include "vtkPoints.h" +#include "vtkPolyLine.h" +#include "vtkPolyVertex.h" +#include "vtkPolygon.h" +#include "vtkQuad.h" +#include "vtkTetra.h" +#include "vtkTriangle.h" +#include "vtkTriangleStrip.h" +#include "vtkVertex.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" +#include "vtkPentagonalPrism.h" +#include "vtkHexagonalPrism.h" + + +int TestOCB(ostream& strm) +{ + // actual test + vtkIdList *ids = vtkIdList::New(); + int i, j, k; + strm << "Test vtkCell::CellBoundary Start" << endl; + + //Vertex + vtkVertex *vertex = vtkVertex::New(); + double vertexCoords[1][1]; + + vertex->GetPointIds()->SetId(0,0); + + vertexCoords[0][0] = 0.0; + + for (j = 0; j < 1; j++) + { + vertex->CellBoundary (0, vertexCoords[j], ids); + strm << "vtkVertex \t(" << vertexCoords[j][0] << ") \t= "; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Poly Vertex + vtkPolyVertex *polyVertex = vtkPolyVertex::New(); + double polyVertexCoords[1][1]; + + polyVertex->GetPointIds()->SetNumberOfIds(2); + polyVertex->GetPointIds()->SetId(0,0); + polyVertex->GetPointIds()->SetId(1,1); + + polyVertexCoords[0][0] = 0.0; + + for (k = 0; k < polyVertex->GetPointIds()->GetNumberOfIds(); k++) + { + for (j = 0; j < 1; j++) + { + polyVertex->CellBoundary (k, polyVertexCoords[j], ids); + strm << "vtkPolyVertex \t(" << polyVertexCoords[j][0] << ") \t= "; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + } + + //Line + vtkLine *line = vtkLine::New(); + double lineCoords[2][1]; + + line->GetPointIds()->SetId(0,0); + line->GetPointIds()->SetId(1,1); + + lineCoords[0][0] = .25; + lineCoords[1][0] = .75; + + for (j = 0; j < 2; j++) + { + line->CellBoundary (0, lineCoords[j], ids); + strm << "vtkLine \t(" << lineCoords[j][0] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Poly Line + vtkPolyLine *polyLine = vtkPolyLine::New(); + double polyLineCoords[3][1]; + + polyLine->GetPointIds()->SetNumberOfIds(3); + polyLine->GetPointIds()->SetId(0,0); + polyLine->GetPointIds()->SetId(1,1); + polyLine->GetPointIds()->SetId(2,2); + + polyLineCoords[0][0] = .25; + polyLineCoords[1][0] = .75; + + for (k = 0; k < polyLine->GetPointIds()->GetNumberOfIds() - 1; k++) + { + for (j = 0; j < 2; j++) + { + polyLine->CellBoundary (k, polyLineCoords[j], ids); + strm << "vtkPolyLine \t(" << polyLineCoords[j][0] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + } + + //Triangle + vtkTriangle *triangle = vtkTriangle::New(); + double triangleCoords[3][2]; + + triangle->GetPointIds()->SetId(0,0); + triangle->GetPointIds()->SetId(1,1); + triangle->GetPointIds()->SetId(2,2); + + triangleCoords[0][0] = .5; triangleCoords[0][1] = 0.1; + triangleCoords[1][0] = .9; triangleCoords[1][1] = 0.9; + triangleCoords[2][0] = .1; triangleCoords[2][1] = 0.5; + + for (j = 0; j < 3; j++) + { + triangle->CellBoundary (0, triangleCoords[j], ids); + strm << "vtkTriangle \t(" << triangleCoords[j][0] << ", " << triangleCoords[j][1] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Triangle Strip + vtkTriangleStrip *triangleStrip = vtkTriangleStrip::New(); + double triangleStripCoords[3][2]; + + triangleStrip->GetPointIds()->SetNumberOfIds(4); + triangleStrip->GetPointIds()->SetId(0,0); + triangleStrip->GetPointIds()->SetId(1,1); + triangleStrip->GetPointIds()->SetId(2,2); + triangleStrip->GetPointIds()->SetId(3,3); + + triangleStripCoords[0][0] = .5; triangleStripCoords[0][1] = 0.1; + triangleStripCoords[1][0] = .9; triangleStripCoords[1][1] = 0.9; + triangleStripCoords[2][0] = .1; triangleStripCoords[2][1] = 0.5; + + for (k = 0; k < triangleStrip->GetPointIds()->GetNumberOfIds() - 2; k++) + { + for (j = 0; j < 3; j++) + { + triangleStrip->CellBoundary (k, triangleStripCoords[j], ids); + strm << "vtkTriangleStrip \t(" << triangleStripCoords[j][0] << ", " << triangleStripCoords[j][1] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + } + + //Quad + vtkQuad *quad = vtkQuad::New(); + double quadCoords[4][2]; + + quad->GetPointIds()->SetId(0,0); + quad->GetPointIds()->SetId(1,1); + quad->GetPointIds()->SetId(2,2); + quad->GetPointIds()->SetId(3,3); + + quadCoords[0][0] = .5; quadCoords[0][1] = 0.1; + quadCoords[1][0] = .9; quadCoords[1][1] = 0.5; + quadCoords[2][0] = .5; quadCoords[2][1] = 0.9; + quadCoords[3][0] = .1; quadCoords[3][1] = 0.5; + + for (j = 0; j < 4; j++) + { + quad->CellBoundary (0, quadCoords[j], ids); + strm << "vtkQuad \t(" << quadCoords[j][0] << ", " << quadCoords[j][1] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Pixel + vtkPixel *pixel = vtkPixel::New(); + double pixelCoords[4][2]; + + pixel->GetPointIds()->SetId(0,0); + pixel->GetPointIds()->SetId(1,1); + pixel->GetPointIds()->SetId(2,2); + pixel->GetPointIds()->SetId(3,3); + + pixelCoords[0][0] = .5; pixelCoords[0][1] = 0.1; + pixelCoords[1][0] = .9; pixelCoords[1][1] = 0.5; + pixelCoords[2][0] = .5; pixelCoords[2][1] = 0.9; + pixelCoords[3][0] = .1; pixelCoords[3][1] = 0.5; + + for (j = 0; j < 4; j++) + { + pixel->CellBoundary (0, pixelCoords[j], ids); + strm << "vtkPixel \t(" << pixelCoords[j][0] << ", " << pixelCoords[j][1] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Polygon + vtkPolygon *polygon = vtkPolygon::New(); + double polygonCoords[4][2]; + + polygon->GetPointIds()->SetNumberOfIds(4); + polygon->GetPointIds()->SetId(0,0); + polygon->GetPointIds()->SetId(1,1); + polygon->GetPointIds()->SetId(2,2); + polygon->GetPointIds()->SetId(3,3); + + polygon->GetPoints()->SetNumberOfPoints(4); + polygon->GetPoints()->SetPoint(0, 0.0, 0.0, 0.0); + polygon->GetPoints()->SetPoint(1, 1.0, 0.0, 0.0); + polygon->GetPoints()->SetPoint(2, 1.0, 1.0, 0.0); + polygon->GetPoints()->SetPoint(3, 0.0, 1.0, 0.0); + + polygonCoords[0][0] = .5; polygonCoords[0][1] = 0.1; + polygonCoords[1][0] = .9; polygonCoords[1][1] = 0.5; + polygonCoords[2][0] = .5; polygonCoords[2][1] = 0.9; + polygonCoords[3][0] = .1; polygonCoords[3][1] = 0.5; + + for (j = 0; j < 4; j++) + { + polygon->CellBoundary (0, polygonCoords[j], ids); + strm << "vtkPolygon \t(" << polygonCoords[j][0] << ", " << polygonCoords[j][1] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Tetra + vtkTetra *tetra = vtkTetra::New(); + double tetraCoords[4][3]; + + tetra->GetPointIds()->SetNumberOfIds(4); + tetra->GetPointIds()->SetId(0,0); + tetra->GetPointIds()->SetId(1,1); + tetra->GetPointIds()->SetId(2,2); + tetra->GetPointIds()->SetId(3,3); + + tetraCoords[0][0] = .1; tetraCoords[0][1] = 0.2; tetraCoords[0][2] = 0.2; + tetraCoords[1][0] = .2; tetraCoords[1][1] = 0.1; tetraCoords[1][2] = 0.2; + tetraCoords[2][0] = .2; tetraCoords[2][1] = 0.2; tetraCoords[2][2] = 0.1; + tetraCoords[3][0] = .3; tetraCoords[3][1] = 0.3; tetraCoords[3][2] = 0.3; + + for (j = 0; j < 4; j++) + { + tetra->CellBoundary (0, tetraCoords[j], ids); + strm << "vtkTetra \t(" << tetraCoords[j][0] << ", " << tetraCoords[j][1] << ", " << tetraCoords[j][2] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Voxel + vtkVoxel *voxel = vtkVoxel::New(); + double voxelCoords[6][3]; + + voxel->GetPointIds()->SetNumberOfIds(8); + voxel->GetPointIds()->SetId(0,0); + voxel->GetPointIds()->SetId(1,1); + voxel->GetPointIds()->SetId(2,2); + voxel->GetPointIds()->SetId(3,3); + voxel->GetPointIds()->SetId(4,4); + voxel->GetPointIds()->SetId(5,5); + voxel->GetPointIds()->SetId(6,6); + voxel->GetPointIds()->SetId(7,7); + + voxelCoords[0][0] = .5; voxelCoords[0][1] = 0.5; voxelCoords[0][2] = 0.1; + voxelCoords[1][0] = .9; voxelCoords[1][1] = 0.9; voxelCoords[1][2] = 0.5; + voxelCoords[2][0] = .5; voxelCoords[2][1] = 0.1; voxelCoords[2][2] = 0.5; + voxelCoords[3][0] = .5; voxelCoords[3][1] = 0.5; voxelCoords[3][2] = 0.9; + voxelCoords[4][0] = .1; voxelCoords[4][1] = 0.5; voxelCoords[4][2] = 0.5; + voxelCoords[5][0] = .5; voxelCoords[5][1] = 0.9; voxelCoords[5][2] = 0.5; + + for (j = 0; j < 6; j++) + { + voxel->CellBoundary (0, voxelCoords[j], ids); + strm << "vtkVoxel \t(" << voxelCoords[j][0] << ", " << voxelCoords[j][1] << ", " << voxelCoords[j][2] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Wedge + vtkWedge *wedge = vtkWedge::New(); + double wedgeCoords[6][3]; + + wedge->GetPointIds()->SetNumberOfIds(6); + wedge->GetPointIds()->SetId(0,0); + wedge->GetPointIds()->SetId(1,1); + wedge->GetPointIds()->SetId(2,2); + wedge->GetPointIds()->SetId(3,3); + wedge->GetPointIds()->SetId(4,4); + wedge->GetPointIds()->SetId(5,5); + + wedgeCoords[0][0] = .5; wedgeCoords[0][1] = 0.5; wedgeCoords[0][2] = 0.1; + wedgeCoords[1][0] = .9; wedgeCoords[1][1] = 0.9; wedgeCoords[1][2] = 0.5; + wedgeCoords[2][0] = .5; wedgeCoords[2][1] = 0.1; wedgeCoords[2][2] = 0.5; + wedgeCoords[3][0] = .5; wedgeCoords[3][1] = 0.5; wedgeCoords[3][2] = 0.9; + wedgeCoords[4][0] = .1; wedgeCoords[4][1] = 0.5; wedgeCoords[4][2] = 0.5; + wedgeCoords[5][0] = .5; wedgeCoords[5][1] = 0.9; wedgeCoords[5][2] = 0.5; + + for (j = 0; j < 6; j++) + { + wedge->CellBoundary (0, wedgeCoords[j], ids); + strm << "vtkWedge \t(" << wedgeCoords[j][0] << ", " << wedgeCoords[j][1] << ", " << wedgeCoords[j][2] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Hexahedron + vtkHexahedron *hexahedron = vtkHexahedron::New(); + double hexahedronCoords[8][3]; + + hexahedron->GetPointIds()->SetNumberOfIds(8); + hexahedron->GetPointIds()->SetId(0,0); + hexahedron->GetPointIds()->SetId(1,1); + hexahedron->GetPointIds()->SetId(2,2); + hexahedron->GetPointIds()->SetId(3,3); + hexahedron->GetPointIds()->SetId(4,4); + hexahedron->GetPointIds()->SetId(5,5); + hexahedron->GetPointIds()->SetId(6,6); + hexahedron->GetPointIds()->SetId(7,7); + + hexahedronCoords[0][0] = .5; hexahedronCoords[0][1] = 0.5; hexahedronCoords[0][2] = 0.1; + hexahedronCoords[1][0] = .9; hexahedronCoords[1][1] = 0.9; hexahedronCoords[1][2] = 0.5; + hexahedronCoords[2][0] = .5; hexahedronCoords[2][1] = 0.1; hexahedronCoords[2][2] = 0.5; + hexahedronCoords[3][0] = .5; hexahedronCoords[3][1] = 0.5; hexahedronCoords[3][2] = 0.1; + hexahedronCoords[4][0] = .5; hexahedronCoords[4][1] = 0.5; hexahedronCoords[4][2] = 0.9; + hexahedronCoords[5][0] = .9; hexahedronCoords[5][1] = 0.9; hexahedronCoords[5][2] = 0.7; + hexahedronCoords[6][0] = .5; hexahedronCoords[6][1] = 0.1; hexahedronCoords[6][2] = 0.7; + hexahedronCoords[7][0] = .5; hexahedronCoords[7][1] = 0.5; hexahedronCoords[7][2] = 0.9; + + for (j = 0; j < 8; j++) + { + hexahedron->CellBoundary (0, hexahedronCoords[j], ids); + strm << "vtkHexahedron \t(" << hexahedronCoords[j][0] << ", " << hexahedronCoords[j][1] << ", " << hexahedronCoords[j][2] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Pentagonal Prism + vtkPentagonalPrism *penta = vtkPentagonalPrism::New(); + double pentaCoords[10][3]; + + penta->GetPointIds()->SetNumberOfIds(10); + penta->GetPointIds()->SetId(0,0); + penta->GetPointIds()->SetId(1,1); + penta->GetPointIds()->SetId(2,2); + penta->GetPointIds()->SetId(3,3); + penta->GetPointIds()->SetId(4,4); + penta->GetPointIds()->SetId(5,5); + penta->GetPointIds()->SetId(6,6); + penta->GetPointIds()->SetId(7,7); + penta->GetPointIds()->SetId(8,8); + penta->GetPointIds()->SetId(9,9); + + pentaCoords[0][0] = 0.25; pentaCoords[0][1] = 0.0; pentaCoords[0][2] = 0.0; + pentaCoords[1][0] = 0.75; pentaCoords[1][1] = 0.0; pentaCoords[1][2] = 0.0; + pentaCoords[2][0] = 1.0 ; pentaCoords[2][1] = 0.5; pentaCoords[2][2] = 0.0; + pentaCoords[3][0] = 0.5 ; pentaCoords[3][1] = 1.0; pentaCoords[3][2] = 0.0; + pentaCoords[4][0] = 0.0 ; pentaCoords[4][1] = 0.5; pentaCoords[4][2] = 0.0; + pentaCoords[5][0] = 0.25; pentaCoords[5][1] = 0.0; pentaCoords[5][2] = 1.0; + pentaCoords[6][0] = 0.75; pentaCoords[6][1] = 0.0; pentaCoords[6][2] = 1.0; + pentaCoords[7][0] = 1.0 ; pentaCoords[7][1] = 0.5; pentaCoords[7][2] = 1.0; + pentaCoords[8][0] = 0.5 ; pentaCoords[8][1] = 1.0; pentaCoords[8][2] = 1.0; + pentaCoords[9][0] = 0.0 ; pentaCoords[9][1] = 0.5; pentaCoords[9][2] = 1.0; + + for (j = 0; j < 10; j++) + { + penta->CellBoundary (0, pentaCoords[j], ids); + strm << "vtkPentagonalPrism \t(" << pentaCoords[j][0] << ", " << pentaCoords[j][1] << ", " << pentaCoords[j][2] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + //Hexagonal Prism + vtkHexagonalPrism *hexa = vtkHexagonalPrism::New(); + double hexaCoords[12][3]; + + hexa->GetPointIds()->SetNumberOfIds(12); + hexa->GetPointIds()->SetId(0,0); + hexa->GetPointIds()->SetId(1,1); + hexa->GetPointIds()->SetId(2,2); + hexa->GetPointIds()->SetId(3,3); + hexa->GetPointIds()->SetId(4,4); + hexa->GetPointIds()->SetId(5,5); + hexa->GetPointIds()->SetId(6,6); + hexa->GetPointIds()->SetId(7,7); + hexa->GetPointIds()->SetId(8,8); + hexa->GetPointIds()->SetId(9,9); + hexa->GetPointIds()->SetId(10,12); + hexa->GetPointIds()->SetId(11,11); + + hexaCoords[0][0] = 0.5 ; hexaCoords[0][1] = 0.0; hexaCoords[0][2] = 0.3; + hexaCoords[1][0] = 0.93 ; hexaCoords[1][1] = 0.25; hexaCoords[1][2] = 0.3; + hexaCoords[2][0] = 0.93 ; hexaCoords[2][1] = 0.75; hexaCoords[2][2] = 0.3; + hexaCoords[3][0] = 0.716 ; hexaCoords[3][1] = 0.875; hexaCoords[3][2] = 0.4; + hexaCoords[4][0] = 0.55 ; hexaCoords[4][1] = 0.95; hexaCoords[4][2] = 0.3; + hexaCoords[5][0] = 0.067 ; hexaCoords[5][1] = 0.6; hexaCoords[5][2] = 0.1; + hexaCoords[6][0] = 0.05 ; hexaCoords[6][1] = 0.4; hexaCoords[6][2] = 0.7; + hexaCoords[7][0] = 0.5 ; hexaCoords[7][1] = 0.6; hexaCoords[7][2] = 0.7; + hexaCoords[8][0] = 0.93 ; hexaCoords[8][1] = 0.4; hexaCoords[8][2] = 0.7; + hexaCoords[9][0] = 0.93 ; hexaCoords[9][1] = 0.9; hexaCoords[9][2] = 0.7; + hexaCoords[10][0] = 0.06 ; hexaCoords[10][1] = 0.7; hexaCoords[10][2] = 0.7; + hexaCoords[11][0] = 0.07 ; hexaCoords[11][1] = 0.3; hexaCoords[11][2] = 0.7; + + for (j = 0; j < 12; j++) + { + hexa->CellBoundary (0, hexaCoords[j], ids); + strm << "vtkHexagonalPrism \t(" << hexaCoords[j][0] << ", " << hexaCoords[j][1] << ", " << hexaCoords[j][2] << ") = \t"; + for (i = 0; i < ids->GetNumberOfIds(); i++) + { + strm << ids->GetId(i) << ", "; + } + strm << endl; + } + + ids->Delete(); + vertex->Delete(); + polyVertex->Delete(); + line->Delete(); + polyLine->Delete(); + triangle->Delete(); + triangleStrip->Delete(); + quad->Delete(); + pixel->Delete(); + polygon->Delete(); + tetra->Delete(); + voxel->Delete(); + wedge->Delete(); + hexahedron->Delete(); + penta->Delete(); + hexa->Delete(); + + strm << "Test vtkCell::CellBoundary Complete" << endl; + + return 0; +} + + +int otherCellBoundaries(int, char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return TestOCB(vtkmsg_with_warning_C4701); +} diff --git a/Common/Testing/Cxx/otherCellPosition.cxx b/Common/Testing/Cxx/otherCellPosition.cxx new file mode 100644 index 0000000..da3341a --- /dev/null +++ b/Common/Testing/Cxx/otherCellPosition.cxx @@ -0,0 +1,583 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherCellPosition.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the Cell Position and Location Boundary methods for each cell type + +#include "vtkDebugLeaks.h" +#include "vtkHexahedron.h" +#include "vtkIdList.h" +#include "vtkLine.h" +#include "vtkPixel.h" +#include "vtkPoints.h" +#include "vtkPolyLine.h" +#include "vtkPolyVertex.h" +#include "vtkPolygon.h" +#include "vtkQuad.h" +#include "vtkTetra.h" +#include "vtkTriangle.h" +#include "vtkTriangleStrip.h" +#include "vtkVertex.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" +#include "vtkPentagonalPrism.h" +#include "vtkHexagonalPrism.h" + +int TestOCP(ostream& strm) +{ + // actual test + vtkIdList *ids = vtkIdList::New(); + int j; + int n; + double dist2; + int subId; + + strm << "Test vtkCell::EvaluatePosition Start" << endl; + + //Vertex + vtkVertex *vertex = vtkVertex::New(); + double vertexCoords[3], vertexWeights[2]; + double vertexPoint[2][3] = {{10.0, 20.0, 30.0}, {0, 0, 0}}; + double vertexClosest[3]; + + vertex->GetPointIds()->SetId(0,0); + vertex->GetPoints()->SetPoint (0, 10.0, 20.0, 30.0); + + n = sizeof(vertexPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + vertex->EvaluatePosition (&vertexPoint[j][0], &vertexClosest[0], subId, &vertexCoords[0], dist2, &vertexWeights[0]); + strm << "vtkVertex (" << vertexPoint[j][0] << ", " << vertexPoint[j][1] << ", " << vertexPoint[j][2] << ")" << endl; + strm << "\tclosest: " << vertexClosest[0] << ", " << vertexClosest[1] << ", " << vertexClosest[2] << endl; + strm << "\tcoords: " << vertexCoords[0] << endl; + strm << "\tweights: " << vertexWeights[0] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + strm << endl; + } + + //Poly Vertex + vtkPolyVertex *polyVertex = vtkPolyVertex::New(); + double polyVertexCoords[1], polyVertexWeights[2]; + double polyVertexPoint[3][3] = {{10.0, 20.0, 30.0}, {30.0, 20.0, 10.0}, {0, 0, 0}}; + double polyVertexClosest[3]; + + polyVertex->GetPointIds()->SetNumberOfIds(2); + polyVertex->GetPointIds()->SetId(0,0); + polyVertex->GetPointIds()->SetId(1,1); + + polyVertex->GetPoints()->SetNumberOfPoints(2); + polyVertex->GetPoints()->SetPoint (0, 10.0, 20.0, 30.0); + polyVertex->GetPoints()->SetPoint (1, 30.0, 20.0, 10.0); + + n = sizeof(polyVertexPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + polyVertex->EvaluatePosition (&polyVertexPoint[j][0], &polyVertexClosest[0], subId, &polyVertexCoords[0], dist2, &polyVertexWeights[0]); + strm << "vtkPolyVertex (" << polyVertexPoint[j][0] << ", " << polyVertexPoint[j][1] << ", " << polyVertexPoint[j][2] << ")" << endl; + strm << "\tclosest: " << polyVertexClosest[0] << ", " << polyVertexClosest[1] << ", " << polyVertexClosest[2] << endl; + strm << "\tcoords: " << polyVertexCoords[0] << endl; + strm << "\tweights: " << polyVertexWeights[0] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + strm << endl; + } + + //Line + vtkLine *line = vtkLine::New(); + double lineCoords[3], lineWeights[2]; + double linePoint[3][3] = {{10.0, 20.0, 30.0}, {30.0, 20.0, 10.0}, {0, 0, 0}}; + double lineClosest[3]; + + line->GetPointIds()->SetId(0,0); + line->GetPointIds()->SetId(1,1); + line->GetPoints()->SetPoint (0, 10.0, 20.0, 30.0); + line->GetPoints()->SetPoint (1, 30.0, 20.0, 10.0); + + n = sizeof(linePoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + line->EvaluatePosition (&linePoint[j][0], &lineClosest[0], subId, &lineCoords[0], dist2, &lineWeights[0]); + strm << "vtkLine (" << linePoint[j][0] << ", " << linePoint[j][1] << ", " << linePoint[j][2] << ")" << endl; + strm << "\tclosest: " << lineClosest[0] << ", " << lineClosest[1] << ", " << lineClosest[2] << endl; + strm << "\tcoords: " << lineCoords[0] << endl; + strm << "\tweights: " << lineWeights[0] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + strm << endl; + } + + //Poly Line + vtkPolyLine *polyLine = vtkPolyLine::New(); + double polyLineCoords[3], polyLineWeights[3]; + double polyLinePoint[4][3] = {{10.0, 20.0, 30.0}, {10.0, 30.0, 30.0}, {10.0, 30.0, 40.0}, {0, 0, 0}}; + double polyLineClosest[3]; + + polyLine->GetPointIds()->SetNumberOfIds(3); + polyLine->GetPointIds()->SetId(0,0); + polyLine->GetPointIds()->SetId(1,1); + polyLine->GetPointIds()->SetId(2,2); + + polyLine->GetPoints()->SetNumberOfPoints(3); + polyLine->GetPoints()->SetPoint (0, 10.0, 20.0, 30.0); + polyLine->GetPoints()->SetPoint (1, 10.0, 30.0, 30.0); + polyLine->GetPoints()->SetPoint (2, 10.0, 30.0, 40.0); + + n = sizeof(polyLinePoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + polyLine->EvaluatePosition (&polyLinePoint[j][0], &polyLineClosest[0], subId, &polyLineCoords[0], dist2, &polyLineWeights[0]); + strm << "vtkPolyLine (" << polyLinePoint[j][0] << ", " << polyLinePoint[j][1] << ", " << polyLinePoint[j][2] << ")" << endl; + strm << "\tclosest: " << polyLineClosest[0] << ", " << polyLineClosest[1] << ", " << polyLineClosest[2] << endl; + strm << "\tcoords: " << polyLineCoords[0] << endl; + strm << "\tweights: " << polyLineWeights[0] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + strm << endl; + } + + //Triangle + vtkTriangle *triangle = vtkTriangle::New(); + double triangleCoords[3], triangleWeights[3], trianglePosition[3]; + double trianglePoint[4][3] = {{10.0, 10.0, 10.0}, {12.0, 10.0, 10.0}, {11.0, 12.0, 12.0}, {11, 11, 11}}; + double triangleClosest[3]; + + triangle->GetPointIds()->SetId(0,0); + triangle->GetPointIds()->SetId(1,1); + triangle->GetPointIds()->SetId(2,2); + + triangle->GetPoints()->SetPoint (0, 10.0, 10.0, 10.0); + triangle->GetPoints()->SetPoint (1, 12.0, 10.0, 10.0); + triangle->GetPoints()->SetPoint (2, 11.0, 12.0, 12.0); + + n = sizeof(trianglePoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + triangle->EvaluatePosition (&trianglePoint[j][0], &triangleClosest[0], subId, &triangleCoords[0], dist2, &triangleWeights[0]); + strm << "vtkTriangle (" << trianglePoint[j][0] << ", " << trianglePoint[j][1] << ", " << trianglePoint[j][2] << ")" << endl; + strm << "\tclosest: " << triangleClosest[0] << ", " << triangleClosest[1] << ", " << triangleClosest[2] << endl; + strm << "\tcoords: " << triangleCoords[0] << ", " << triangleCoords[1] << ", " << triangleCoords[2] << endl; + strm << "\tweights: " << triangleWeights[0] << ", " << triangleWeights[1] << ", " << triangleWeights[2] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + triangle->EvaluateLocation (subId, triangleCoords, trianglePosition, triangleWeights); + strm << "\tposition: " << trianglePosition[0] << ", " << trianglePosition[1] << ", " << trianglePosition[2] << endl; + strm << endl; + } + + //Triangle Strip + vtkTriangleStrip *triangleStrip = vtkTriangleStrip::New(); + double triangleStripCoords[3], triangleStripWeights[4], triangleStripPosition[3]; + double triangleStripPoint[5][3] = {{10.0, 10.0, 10.0}, {12.0, 10.0, 10.0}, {11.0, 12.0, 10.0}, {13, 10, 10}, {11, 11, 10}}; + double triangleStripClosest[3]; + + triangleStrip->GetPointIds()->SetNumberOfIds(4); + triangleStrip->GetPointIds()->SetId(0,0); + triangleStrip->GetPointIds()->SetId(1,1); + triangleStrip->GetPointIds()->SetId(2,2); + triangleStrip->GetPointIds()->SetId(3,3); + + triangleStrip->GetPoints()->SetNumberOfPoints(4); + triangleStrip->GetPoints()->SetPoint (0, 10.0, 10.0, 10.0); + triangleStrip->GetPoints()->SetPoint (1, 12.0, 10.0, 10.0); + triangleStrip->GetPoints()->SetPoint (2, 11.0, 12.0, 10.0); + triangleStrip->GetPoints()->SetPoint (3, 13.0, 10.0, 10.0); + + n = sizeof(triangleStripPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + triangleStrip->EvaluatePosition (&triangleStripPoint[j][0], &triangleStripClosest[0], subId, &triangleStripCoords[0], dist2, &triangleStripWeights[0]); + strm << "vtkTriangleStrip (" << triangleStripPoint[j][0] << ", " << triangleStripPoint[j][1] << ", " << triangleStripPoint[j][2] << ")" << endl; + strm << "\tclosest: " << triangleStripClosest[0] << ", " << triangleStripClosest[1] << ", " << triangleStripClosest[2] << endl; + strm << "\tcoords: " << triangleStripCoords[0] << ", " << triangleStripCoords[1] << ", " << triangleStripCoords[2] << endl; + strm << "\tweights: " << triangleStripWeights[0] << ", " << triangleStripWeights[1] << ", " << triangleStripWeights[2] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + triangleStrip->EvaluateLocation (subId, triangleStripCoords, triangleStripPosition, triangleStripWeights); + strm << "\tposition: " << triangleStripPosition[0] << ", " << triangleStripPosition[1] << ", " << triangleStripPosition[2] << endl; + strm << endl; + } + + //Quad + vtkQuad *quad = vtkQuad::New(); + double quadCoords[2], quadWeights[4], quadPosition[3]; + double quadPoint[5][3] = {{10.0, 10.0, 10.0}, {12.0, 10.0, 10.0}, {12.0, 12.0, 10.0}, {10, 12, 10}, {11, 11, 10.1}}; + double quadClosest[3]; + + quad->GetPointIds()->SetId(0,0); + quad->GetPointIds()->SetId(1,1); + quad->GetPointIds()->SetId(2,2); + quad->GetPointIds()->SetId(3,3); + + quad->GetPoints()->SetPoint (0, 10.0, 10.0, 10.0); + quad->GetPoints()->SetPoint (1, 12.0, 10.0, 10.0); + quad->GetPoints()->SetPoint (2, 12.0, 12.0, 10.0); + quad->GetPoints()->SetPoint (3, 10.0, 12.0, 10.0); + + n = sizeof(quadPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + quad->EvaluatePosition (&quadPoint[j][0], &quadClosest[0], subId, &quadCoords[0], dist2, &quadWeights[0]); + strm << "vtkQuad (" << quadPoint[j][0] << ", " << quadPoint[j][1] << ", " << quadPoint[j][2] << ")" << endl; + strm << "\tclosest: " << quadClosest[0] << ", " << quadClosest[1] << ", " << quadClosest[2] << endl; + strm << "\tcoords: " << quadCoords[0] << ", " << quadCoords[1] << endl; + strm << "\tweights: " << quadWeights[0] << ", " << quadWeights[1] << ", " << quadWeights[2] << ", " << quadWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + quad->EvaluateLocation (subId, quadCoords, quadPosition, quadWeights); + strm << "\tposition: " << quadPosition[0] << ", " << quadPosition[1] << ", " << quadPosition[2] << endl; + strm << endl; + } + + //Pixel + vtkPixel *pixel = vtkPixel::New(); + double pixelCoords[3], pixelWeights[4], pixelPosition[3]; + double pixelPoint[5][3] = {{10.0, 10.0, 10.0}, {12.0, 10.0, 10.0}, {12.0, 12.0, 10.0}, {10, 12, 10}, {11, 11, 10.1}}; + double pixelClosest[3]; + + pixel->GetPointIds()->SetId(0,0); + pixel->GetPointIds()->SetId(1,1); + pixel->GetPointIds()->SetId(2,3); + pixel->GetPointIds()->SetId(3,2); + + pixel->GetPoints()->SetPoint (0, 10.0, 10.0, 10.0); + pixel->GetPoints()->SetPoint (1, 12.0, 10.0, 10.0); + pixel->GetPoints()->SetPoint (3, 12.0, 12.0, 10.0); + pixel->GetPoints()->SetPoint (2, 10.0, 12.0, 10.0); + + n = sizeof(pixelPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + pixel->EvaluatePosition (&pixelPoint[j][0], &pixelClosest[0], subId, &pixelCoords[0], dist2, &pixelWeights[0]); + strm << "vtkPixel (" << pixelPoint[j][0] << ", " << pixelPoint[j][1] << ", " << pixelPoint[j][2] << ")" << endl; + strm << "\tclosest: " << pixelClosest[0] << ", " << pixelClosest[1] << ", " << pixelClosest[2] << endl; + strm << "\tcoords: " << pixelCoords[0] << ", " << pixelCoords[1] << endl; + strm << "\tweights: " << pixelWeights[0] << ", " << pixelWeights[1] << ", " << pixelWeights[2] << ", " << pixelWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + pixel->EvaluateLocation (subId, pixelCoords, pixelPosition, pixelWeights); + strm << "\tposition: " << pixelPosition[0] << ", " << pixelPosition[1] << ", " << pixelPosition[2] << endl; + strm << endl; + } + + //Polygon + vtkPolygon *polygon = vtkPolygon::New(); + double polygonCoords[2], polygonWeights[4], polygonPosition[3]; + double polygonPoint[5][3] = {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0, 1, 0}, {.5, .5, 0}}; + double polygonClosest[3]; + + polygon->GetPointIds()->SetNumberOfIds(4); + polygon->GetPointIds()->SetId(0,0); + polygon->GetPointIds()->SetId(1,1); + polygon->GetPointIds()->SetId(2,2); + polygon->GetPointIds()->SetId(3,3); + + polygon->GetPoints()->SetNumberOfPoints(4); + polygon->GetPoints()->SetPoint(0, 0.0, 0.0, 0.0); + polygon->GetPoints()->SetPoint(1, 1.0, 0.0, 0.0); + polygon->GetPoints()->SetPoint(2, 1.0, 1.0, 0.0); + polygon->GetPoints()->SetPoint(3, 0.0, 1.0, 0.0); + + n = sizeof(polygonPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + polygon->EvaluatePosition (&polygonPoint[j][0], &polygonClosest[0], subId, &polygonCoords[0], dist2, &polygonWeights[0]); + strm << "vtkPolygon (" << polygonPoint[j][0] << ", " << polygonPoint[j][1] << ", " << polygonPoint[j][2] << ")" << endl; + strm << "\tclosest: " << polygonClosest[0] << ", " << polygonClosest[1] << ", " << polygonClosest[2] << endl; + strm << "\tcoords: " << polygonCoords[0] << ", " << polygonCoords[1] << endl; + strm << "\tweights: " << polygonWeights[0] << ", " << polygonWeights[1] << ", " << polygonWeights[2] << ", " << polygonWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + polygon->EvaluateLocation (subId, polygonCoords, polygonPosition, polygonWeights); + strm << "\tposition: " << polygonPosition[0] << ", " << polygonPosition[1] << ", " << polygonPosition[2] << endl; + strm << endl; + } + + //Tetra + vtkTetra *tetra = vtkTetra::New(); + double tetraCoords[3], tetraWeights[4], tetraPosition[3]; + double tetraPoint[5][3] = {{10, 10, 10}, {12, 10, 10}, {11, 12, 10}, {11, 11, 12}, {11, 11, 11}}; + double tetraClosest[3]; + + tetra->GetPointIds()->SetNumberOfIds(4); + tetra->GetPointIds()->SetId(0,0); + tetra->GetPointIds()->SetId(1,1); + tetra->GetPointIds()->SetId(2,2); + tetra->GetPointIds()->SetId(3,3); + tetra->GetPoints()->SetPoint(0, 10.0, 10.0, 10.0); + tetra->GetPoints()->SetPoint(1, 12.0, 10.0, 10.0); + tetra->GetPoints()->SetPoint(2, 11.0, 12.0, 10.0); + tetra->GetPoints()->SetPoint(3, 11.0, 11.0, 12.0); + + n = sizeof(tetraPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + tetra->EvaluatePosition (&tetraPoint[j][0], &tetraClosest[0], subId, &tetraCoords[0], dist2, &tetraWeights[0]); + strm << "vtkTetra (" << tetraPoint[j][0] << ", " << tetraPoint[j][1] << ", " << tetraPoint[j][2] << ")" << endl; + strm << "\tclosest: " << tetraClosest[0] << ", " << tetraClosest[1] << ", " << tetraClosest[2] << endl; + strm << "\tcoords: " << tetraCoords[0] << ", " << tetraCoords[1] << ", " << tetraCoords[2] << endl; + strm << "\tweights: " << tetraWeights[0] << ", " << tetraWeights[1] << ", " << tetraWeights[2] << ", " << tetraWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + tetra->EvaluateLocation (subId, tetraCoords, tetraPosition, tetraWeights); + strm << "\tposition: " << tetraPosition[0] << ", " << tetraPosition[1] << ", " << tetraPosition[2] << endl; + strm << endl; + } + + //Voxel + vtkVoxel *voxel = vtkVoxel::New(); + double voxelCoords[3], voxelWeights[8], voxelPosition[3]; + double voxelPoint[9][3] = {{10, 10, 10}, {12, 10, 10}, {12, 12, 10}, {10, 12, 10}, + {10, 10, 12}, {12, 10, 12}, {12, 12, 12}, {10, 12, 12}, + {11, 11, 11}}; + double voxelClosest[3]; + + voxel->GetPointIds()->SetNumberOfIds(8); + voxel->GetPointIds()->SetId(0,0); + voxel->GetPointIds()->SetId(1,1); + voxel->GetPointIds()->SetId(2,3); + voxel->GetPointIds()->SetId(3,2); + voxel->GetPointIds()->SetId(4,4); + voxel->GetPointIds()->SetId(5,5); + voxel->GetPointIds()->SetId(6,7); + voxel->GetPointIds()->SetId(7,6); + + voxel->GetPoints()->SetPoint(0, 10, 10, 10); + voxel->GetPoints()->SetPoint(1, 12, 10, 10); + voxel->GetPoints()->SetPoint(3, 12, 12, 10); + voxel->GetPoints()->SetPoint(2, 10, 12, 10); + voxel->GetPoints()->SetPoint(4, 10, 10, 12); + voxel->GetPoints()->SetPoint(5, 12, 10, 12); + voxel->GetPoints()->SetPoint(7, 12, 12, 12); + voxel->GetPoints()->SetPoint(6, 10, 12, 12); + + n = sizeof(voxelPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + voxel->EvaluatePosition (&voxelPoint[j][0], &voxelClosest[0], subId, &voxelCoords[0], dist2, &voxelWeights[0]); + strm << "vtkVoxel (" << voxelPoint[j][0] << ", " << voxelPoint[j][1] << ", " << voxelPoint[j][2] << ")" << endl; + strm << "\tclosest: " << voxelClosest[0] << ", " << voxelClosest[1] << ", " << voxelClosest[2] << endl; + strm << "\tcoords: " << voxelCoords[0] << ", " << voxelCoords[1] << ", " << voxelCoords[2] << endl; + strm << "\tweights: " << voxelWeights[0] << ", " << voxelWeights[1] << ", " << voxelWeights[2] << ", " << voxelWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + voxel->EvaluateLocation (subId, voxelCoords, voxelPosition, voxelWeights); + strm << "\tposition: " << voxelPosition[0] << ", " << voxelPosition[1] << ", " << voxelPosition[2] << endl; + strm << endl; + } + + //Wedge + vtkWedge *wedge = vtkWedge::New(); + double wedgeCoords[3], wedgeWeights[8], wedgePosition[3]; + double wedgePoint[9][3] = {{10, 10, 10}, {12, 10, 10}, {11, 12, 10}, {10, 10, 12}, + {12, 10, 12}, {11, 12, 12}, {11, 11, 11}}; + double wedgeClosest[3]; + + wedge->GetPointIds()->SetNumberOfIds(6); + wedge->GetPointIds()->SetId(0,0); + wedge->GetPointIds()->SetId(1,1); + wedge->GetPointIds()->SetId(2,2); + wedge->GetPointIds()->SetId(3,3); + wedge->GetPointIds()->SetId(4,4); + wedge->GetPointIds()->SetId(5,5); + + wedge->GetPoints()->SetPoint(0, 10, 10, 10); + wedge->GetPoints()->SetPoint(1, 12, 10, 10); + wedge->GetPoints()->SetPoint(2, 11, 12, 10); + wedge->GetPoints()->SetPoint(3, 10, 10, 12); + wedge->GetPoints()->SetPoint(4, 12, 10, 12); + wedge->GetPoints()->SetPoint(5, 11, 12, 12); + + n = sizeof(wedgePoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + wedge->EvaluatePosition (&wedgePoint[j][0], &wedgeClosest[0], subId, &wedgeCoords[0], dist2, &wedgeWeights[0]); + strm << "vtkWedge (" << wedgePoint[j][0] << ", " << wedgePoint[j][1] << ", " << wedgePoint[j][2] << ")" << endl; + strm << "\tclosest: " << wedgeClosest[0] << ", " << wedgeClosest[1] << ", " << wedgeClosest[2] << endl; + strm << "\tcoords: " << wedgeCoords[0] << ", " << wedgeCoords[1] << ", " << wedgeCoords[2] << endl; + strm << "\tweights: " << wedgeWeights[0] << ", " << wedgeWeights[1] << ", " << wedgeWeights[2] << ", " << wedgeWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + wedge->EvaluateLocation (subId, wedgeCoords, wedgePosition, wedgeWeights); + strm << "\tposition: " << wedgePosition[0] << ", " << wedgePosition[1] << ", " << wedgePosition[2] << endl; + strm << endl; + } + + //Hexahedron + vtkHexahedron *hexahedron = vtkHexahedron::New(); + double hexahedronCoords[3], hexahedronWeights[8], hexahedronPosition[3]; + double hexahedronPoint[9][3] = {{10, 10, 10}, {12, 10, 10}, {12, 12, 10}, {10, 12, 10}, + {10, 10, 12}, {12, 10, 12}, {12, 12, 12}, {10, 12, 12}, + {11, 11, 11}}; + double hexahedronClosest[3]; + + hexahedron->GetPointIds()->SetNumberOfIds(8); + hexahedron->GetPointIds()->SetId(0,0); + hexahedron->GetPointIds()->SetId(1,1); + hexahedron->GetPointIds()->SetId(2,2); + hexahedron->GetPointIds()->SetId(3,3); + hexahedron->GetPointIds()->SetId(4,4); + hexahedron->GetPointIds()->SetId(5,5); + hexahedron->GetPointIds()->SetId(6,6); + hexahedron->GetPointIds()->SetId(7,7); + + hexahedron->GetPoints()->SetPoint(0, 10, 10, 10); + hexahedron->GetPoints()->SetPoint(1, 12, 10, 10); + hexahedron->GetPoints()->SetPoint(2, 12, 12, 10); + hexahedron->GetPoints()->SetPoint(3, 10, 12, 10); + hexahedron->GetPoints()->SetPoint(4, 10, 10, 12); + hexahedron->GetPoints()->SetPoint(5, 12, 10, 12); + hexahedron->GetPoints()->SetPoint(6, 12, 12, 12); + hexahedron->GetPoints()->SetPoint(7, 10, 12, 12); + + n = sizeof(hexahedronPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + hexahedron->EvaluatePosition (&hexahedronPoint[j][0], &hexahedronClosest[0], subId, &hexahedronCoords[0], dist2, &hexahedronWeights[0]); + strm << "vtkHexahedron (" << hexahedronPoint[j][0] << ", " << hexahedronPoint[j][1] << ", " << hexahedronPoint[j][2] << ")" << endl; + strm << "\tclosest: " << hexahedronClosest[0] << ", " << hexahedronClosest[1] << ", " << hexahedronClosest[2] << endl; + strm << "\tcoords: " << hexahedronCoords[0] << ", " << hexahedronCoords[1] << ", " << hexahedronCoords[2] << endl; + strm << "\tweights: " << hexahedronWeights[0] << ", " << hexahedronWeights[1] << ", " << hexahedronWeights[2] << ", " << hexahedronWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + hexahedron->EvaluateLocation (subId, hexahedronCoords, hexahedronPosition, hexahedronWeights); + strm << "\tposition: " << hexahedronPosition[0] << ", " << hexahedronPosition[1] << ", " << hexahedronPosition[2] << endl; + strm << endl; + } + + //Pentagonal Prism + vtkPentagonalPrism *penta = vtkPentagonalPrism::New(); + double pentaCoords[3], pentaWeights[10], pentaPosition[3]; + double pentaPoint[11][3] = {{11, 10, 10}, {13, 10, 10}, {14, 12, 10}, {12, 14, 10}, + {10, 12, 10}, {11, 10, 14}, {13, 10, 14}, {14, 12, 14}, + {12, 14, 14}, {10, 12, 14}, {12, 12, 12}}; + double pentaClosest[3]; + + penta->GetPointIds()->SetNumberOfIds(10); + penta->GetPointIds()->SetId(0,0); + penta->GetPointIds()->SetId(1,1); + penta->GetPointIds()->SetId(2,2); + penta->GetPointIds()->SetId(3,3); + penta->GetPointIds()->SetId(4,4); + penta->GetPointIds()->SetId(5,5); + penta->GetPointIds()->SetId(6,6); + penta->GetPointIds()->SetId(7,7); + penta->GetPointIds()->SetId(8,8); + penta->GetPointIds()->SetId(9,9); + + penta->GetPoints()->SetPoint(0, 11, 10, 10); + penta->GetPoints()->SetPoint(1, 13, 10, 10); + penta->GetPoints()->SetPoint(2, 14, 12, 10); + penta->GetPoints()->SetPoint(3, 12, 14, 10); + penta->GetPoints()->SetPoint(4, 10, 12, 10); + penta->GetPoints()->SetPoint(5, 11, 10, 14); + penta->GetPoints()->SetPoint(6, 13, 10, 14); + penta->GetPoints()->SetPoint(7, 14, 12, 14); + penta->GetPoints()->SetPoint(8, 12, 14, 14); + penta->GetPoints()->SetPoint(9, 10, 12, 14); + + n = sizeof(pentaPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + penta->EvaluatePosition (&pentaPoint[j][0], &pentaClosest[0], subId, &pentaCoords[0], dist2, &pentaWeights[0]); + strm << "vtkPentagonalPrism (" << pentaPoint[j][0] << ", " << pentaPoint[j][1] << ", " << pentaPoint[j][2] << ")" << endl; + strm << "\tclosest: " << pentaClosest[0] << ", " << pentaClosest[1] << ", " << pentaClosest[2] << endl; + strm << "\tcoords: " << pentaCoords[0] << ", " << pentaCoords[1] << ", " << pentaCoords[2] << endl; + strm << "\tweights: " << pentaWeights[0] << ", " << pentaWeights[1] << ", " << pentaWeights[2] << ", " << pentaWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + penta->EvaluateLocation (subId, pentaCoords, pentaPosition, pentaWeights); + strm << "\tposition: " << pentaPosition[0] << ", " << pentaPosition[1] << ", " << pentaPosition[2] << endl; + strm << endl; + } + + //Hexagonal Prism + vtkHexagonalPrism *hexa = vtkHexagonalPrism::New(); + double hexaCoords[3], hexaWeights[12], hexaPosition[3]; + double hexaPoint[13][3] = {{11, 10, 10}, {13, 10, 10}, {14, 12, 10}, {13, 14, 10}, + {11, 14, 10}, {10, 12, 10}, {11, 10, 14}, {13, 10, 14}, + {14, 12, 14}, {13, 14, 14}, {11, 14, 14}, {10, 12, 14}, + {12, 12, 12}}; + double hexaClosest[3]; + + hexa->GetPointIds()->SetNumberOfIds(12); + hexa->GetPointIds()->SetId(0,0); + hexa->GetPointIds()->SetId(1,1); + hexa->GetPointIds()->SetId(2,2); + hexa->GetPointIds()->SetId(3,3); + hexa->GetPointIds()->SetId(4,4); + hexa->GetPointIds()->SetId(5,5); + hexa->GetPointIds()->SetId(6,6); + hexa->GetPointIds()->SetId(7,7); + hexa->GetPointIds()->SetId(8,8); + hexa->GetPointIds()->SetId(9,9); + hexa->GetPointIds()->SetId(10,10); + hexa->GetPointIds()->SetId(11,11); + + hexa->GetPoints()->SetPoint(0, 11, 10, 10); + hexa->GetPoints()->SetPoint(1, 13, 10, 10); + hexa->GetPoints()->SetPoint(2, 14, 12, 10); + hexa->GetPoints()->SetPoint(3, 13, 14, 10); + hexa->GetPoints()->SetPoint(4, 11, 14, 10); + hexa->GetPoints()->SetPoint(5, 10, 12, 10); + hexa->GetPoints()->SetPoint(6, 11, 10, 14); + hexa->GetPoints()->SetPoint(7, 13, 10, 14); + hexa->GetPoints()->SetPoint(8, 14, 12, 14); + hexa->GetPoints()->SetPoint(9, 13, 14, 14); + hexa->GetPoints()->SetPoint(10, 11, 14, 14); + hexa->GetPoints()->SetPoint(11, 10, 12, 14); + + n = sizeof(hexaPoint) / (3 * sizeof(double)); + for (j = 0; j < n; j++) + { + hexa->EvaluatePosition (&hexaPoint[j][0], &hexaClosest[0], subId, &hexaCoords[0], dist2, &hexaWeights[0]); + strm << "vtkHexagonalPrism (" << hexaPoint[j][0] << ", " << hexaPoint[j][1] << ", " << hexaPoint[j][2] << ")" << endl; + strm << "\tclosest: " << hexaClosest[0] << ", " << hexaClosest[1] << ", " << hexaClosest[2] << endl; + strm << "\tcoords: " << hexaCoords[0] << ", " << hexaCoords[1] << ", " << hexaCoords[2] << endl; + strm << "\tweights: " << hexaWeights[0] << ", " << hexaWeights[1] << ", " << hexaWeights[2] << ", " << hexaWeights[3] << endl; + strm << "\tsubid: " << subId << endl; + strm << "\tdist2: " << dist2 << endl; + hexa->EvaluateLocation (subId, hexaCoords, hexaPosition, hexaWeights); + strm << "\tposition: " << hexaPosition[0] << ", " << hexaPosition[1] << ", " << hexaPosition[2] << endl; + strm << endl; + } + + ids->Delete(); + vertex->Delete(); + polyVertex->Delete(); + line->Delete(); + polyLine->Delete(); + triangle->Delete(); + triangleStrip->Delete(); + quad->Delete(); + pixel->Delete(); + polygon->Delete(); + tetra->Delete(); + voxel->Delete(); + wedge->Delete(); + hexahedron->Delete(); + penta->Delete(); + hexa->Delete(); + + strm << "Test vtkCell::CellPosition Complete" << endl; + return 0; +} + +int otherCellPosition(int, char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return TestOCP(vtkmsg_with_warning_C4701); +} diff --git a/Common/Testing/Cxx/otherCellTypes.cxx b/Common/Testing/Cxx/otherCellTypes.cxx new file mode 100644 index 0000000..2dc8bf8 --- /dev/null +++ b/Common/Testing/Cxx/otherCellTypes.cxx @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherCellTypes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the CellTypes + +#include "vtkDebugLeaks.h" + +#include "vtkCellTypes.h" +#include "vtkCellType.h" + +void TestOCT() +{ + // actual test + vtkCellTypes *ct = vtkCellTypes::New(); + ct->Allocate(); + + ct->InsertCell(0, VTK_QUAD, 0); + ct->InsertNextCell(VTK_PIXEL, 1); + + vtkUnsignedCharArray *cellTypes = vtkUnsignedCharArray::New(); + vtkIntArray *cellLocations = vtkIntArray::New(); + + cellLocations->InsertNextValue (0); + cellTypes->InsertNextValue(VTK_QUAD); + + cellLocations->InsertNextValue (1); + cellTypes->InsertNextValue(VTK_PIXEL); + + cellLocations->InsertNextValue (2); + cellTypes->InsertNextValue(VTK_TETRA); + + ct->SetCellTypes (3, cellTypes, cellLocations); + + ct->GetCellLocation (1); + ct->DeleteCell(1); + + ct->GetNumberOfTypes(); + + ct->IsType(VTK_QUAD); + ct->IsType(VTK_WEDGE); + + ct->InsertNextType(VTK_WEDGE); + ct->IsType(VTK_WEDGE); + + ct->GetCellType(2); + + ct->GetActualMemorySize(); + + vtkCellTypes *ct1 = vtkCellTypes::New(); + ct1->DeepCopy(ct); + + ct->Reset(); + ct->Squeeze(); + + ct1->Delete(); + ct->Delete(); + cellLocations->Delete(); + cellTypes->Delete(); +} + +int otherCellTypes(int, char *[]) +{ + TestOCT(); + + return 0; +} diff --git a/Common/Testing/Cxx/otherEmptyCell.cxx b/Common/Testing/Cxx/otherEmptyCell.cxx new file mode 100644 index 0000000..9dcedcf --- /dev/null +++ b/Common/Testing/Cxx/otherEmptyCell.cxx @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherEmptyCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkEmptyCell.h" +#include "vtkIdList.h" +#include "vtkPoints.h" +#include "vtkFloatArray.h" +#include "vtkPointLocator.h" +#include "vtkCellArray.h" +#include "vtkPointData.h" +#include "vtkCellData.h" + +#include "vtkDebugLeaks.h" + +void TestOEC(ostream& strm) +{ + vtkEmptyCell *cell = vtkEmptyCell::New(); + vtkCell *cell2 = cell->NewInstance(); + cell2->DeepCopy(cell); + vtkIdList *ids = vtkIdList::New(); + vtkPoints *pts = vtkPoints::New(); + double v = 0.0; + vtkFloatArray *cellScalars = vtkFloatArray::New(); + vtkPointLocator *locator = vtkPointLocator::New(); + vtkCellArray *verts = vtkCellArray::New(); + vtkCellArray *lines = vtkCellArray::New(); + vtkCellArray *polys = vtkCellArray::New(); + vtkPointData *inPd = vtkPointData::New(); + vtkPointData *outPd = vtkPointData::New(); + vtkCellData *inCd = vtkCellData::New(); + vtkCellData *outCd = vtkCellData::New(); + int cellId = 0; + int inOut = 0; + double t, tol = 0.0; + double x[3]; + double c[3]; + double p[3]; + double d; + double w[3]; + int s; + + strm << "Testing EmptyCell" << endl; + strm << "Cell Type is: " << cell2->GetCellType() << endl; + strm << "Cell Dimension is: " << cell2->GetCellDimension() << endl; + strm << "Cell NumberOfEdges is: " << cell2->GetNumberOfEdges() << endl; + strm << "Cell NumberOfFaces is: " << cell2->GetNumberOfFaces() << endl; + strm << "Cell GetEdge(0) is: " << cell2->GetEdge(0) << endl; + strm << "Cell GetFace(0) is: " << cell2->GetFace(0) << endl; + strm << "Cell CellBoundary(0,p,ids) is: " << cell2->CellBoundary(0,p,ids) << endl; + strm << "Cell EvaluatePosition(x, c, s, p, d, w)" << endl; + cell2->EvaluatePosition(x,c,s,p,d,w); + strm << "Cell EvaluateLocation(s, p, x, w)" << endl; + cell2->EvaluateLocation(s,p,x,w); + strm << "Cell Contour" << endl; + cell2->Contour(v,cellScalars,locator,verts,lines,polys,inPd,outPd,inCd,cellId,outCd); + strm << "Cell Clip" << endl; + cell2->Clip(v,cellScalars,locator,verts,inPd,outPd,inCd,cellId,outCd,inOut); + strm << "Cell IntersectWithLine" << endl; + cell2->IntersectWithLine(x,x,tol,t,x,p,s); + strm << "Cell Triangulate" << endl; + cell2->Triangulate(s,ids,pts); + strm << "Cell Derivatives" << endl; + cell2->Derivatives(s,p,x,inOut,w); + + // clean up + cell->Delete(); + cell2->Delete(); + ids->Delete(); + pts->Delete(); + cellScalars->Delete(); + locator->Delete(); + verts->Delete(); + lines->Delete(); + polys->Delete(); + inPd->Delete(); + outPd->Delete(); + inCd->Delete(); + outCd->Delete(); + strm << "Testing EmptyCell Complete" << endl; +} + +int otherEmptyCell(int , char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + TestOEC(vtkmsg_with_warning_C4701); + + return 0; +} diff --git a/Common/Testing/Cxx/otherFieldData.cxx b/Common/Testing/Cxx/otherFieldData.cxx new file mode 100644 index 0000000..a6660b0 --- /dev/null +++ b/Common/Testing/Cxx/otherFieldData.cxx @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherFieldData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkDebugLeaks.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" + +int otherFieldData(int,char *[]) +{ + int i; + vtkFieldData* fd = vtkFieldData::New(); + + vtkFloatArray* fa; + + char name[128]; + for(i=0; i<5; i++) + { + sprintf(name, "Array%d", i); + fa = vtkFloatArray::New(); + fa->SetName(name); + // the tuples must be set before being read to avoid a UMR + // this must have been a UMR in the past that was suppressed + fa->Allocate(20); + fa->SetTuple1(0,0.0); + fa->SetTuple1(2,0.0); + fd->AddArray(fa); + fa->Delete(); + } + + // Coverage + vtkFieldData::Iterator it(fd); + vtkFieldData::Iterator it2(it); + + it = it; + it2 = it; + + fd->Allocate(20); + fd->CopyFieldOff("Array0"); + fd->CopyFieldOff("Array1"); + + vtkFieldData* fd2 = fd->NewInstance(); + fd2->CopyStructure(fd); + fd2->ShallowCopy(fd); + fd2->DeepCopy(fd); + + vtkIdList* ptIds = vtkIdList::New(); + ptIds->InsertNextId(0); + ptIds->InsertNextId(2); + + fd->GetField(ptIds, fd2); + ptIds->Delete(); + + int arrayComp; + int a = fd->GetArrayContainingComponent(1, arrayComp); + if (a != 1) + { + return 1; + } + + double tuple[10]; + // initialize tuple before using it to set something + for (i = 0; i < 10; i++) + { + tuple[i] = i; + } + fd->GetTuple(2); + fd->SetTuple(2, tuple); + fd->InsertTuple(2, tuple); + fd->InsertNextTuple(tuple); + fd->SetComponent(0,0, 1.0); + fd->InsertComponent(0,0, 1.0); + + fd2->Reset(); + + fd->Delete(); + fd2->Delete(); + + return 0; + +} diff --git a/Common/Testing/Cxx/otherLookupTable.cxx b/Common/Testing/Cxx/otherLookupTable.cxx new file mode 100644 index 0000000..a4d9995 --- /dev/null +++ b/Common/Testing/Cxx/otherLookupTable.cxx @@ -0,0 +1,177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherLookupTable.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the LookupTable + +#include "vtkLookupTable.h" +#include "vtkLogLookupTable.h" +#include "vtkDebugLeaks.h" + +void TestOLT(vtkLookupTable *lut1) +{ + // actual test + + lut1->SetRange(1,1024); + + lut1->Allocate (1024); + lut1->SetRampToLinear(); + lut1->Build(); + + double rgb[4]; + lut1->GetColor(0, rgb); + + lut1->GetOpacity(0); + + lut1->GetTableValue(10,rgb); + lut1->GetTableValue(10); + + unsigned char output[4*1024]; + + int bitA = 1; + lut1->MapScalarsThroughTable2((void *) &bitA, output, VTK_BIT, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) &bitA, output, VTK_CHAR, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) &bitA, output, VTK_CHAR, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) &bitA, output, VTK_CHAR, + 2, 1, VTK_LUMINANCE); + + + char charA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) charA, output, VTK_CHAR, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) charA, output, VTK_CHAR, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) charA, output, VTK_CHAR, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) charA, output, VTK_CHAR, + 2, 1, VTK_LUMINANCE); + + unsigned char ucharA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) ucharA, output, VTK_UNSIGNED_CHAR, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) ucharA, output, VTK_UNSIGNED_CHAR, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) ucharA, output, VTK_UNSIGNED_CHAR, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) ucharA, output, VTK_UNSIGNED_CHAR, + 2, 1, VTK_LUMINANCE); + + int intA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) intA, output, VTK_INT, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) intA, output, VTK_INT, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) intA, output, VTK_INT, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) intA, output, VTK_INT, + 2, 1, VTK_LUMINANCE); + + unsigned int uintA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) uintA, output, VTK_UNSIGNED_INT, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) uintA, output, VTK_UNSIGNED_INT, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) uintA, output, VTK_UNSIGNED_INT, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) uintA, output, VTK_UNSIGNED_INT, + 2, 1, VTK_LUMINANCE); + + long longA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) longA, output, VTK_LONG, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) longA, output, VTK_LONG, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) longA, output, VTK_LONG, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) longA, output, VTK_LONG, + 2, 1, VTK_LUMINANCE); + + unsigned long ulongA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) ulongA, output, VTK_UNSIGNED_LONG, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) ulongA, output, VTK_UNSIGNED_LONG, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) ulongA, output, VTK_UNSIGNED_LONG, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) ulongA, output, VTK_UNSIGNED_LONG, 2, 1, VTK_LUMINANCE); + + short shortA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) shortA, output, VTK_SHORT, + 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) shortA, output, VTK_SHORT, + 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) shortA, output, VTK_SHORT, + 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) shortA, output, VTK_SHORT, + 2, 1, VTK_LUMINANCE); + + unsigned short ushortA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) ushortA, output, + VTK_UNSIGNED_SHORT, 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) ushortA, output, + VTK_UNSIGNED_SHORT, 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) ushortA, output, + VTK_UNSIGNED_SHORT, 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) ushortA, output, + VTK_UNSIGNED_SHORT, 2, 1, VTK_LUMINANCE); + + float floatA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) floatA, output, + VTK_FLOAT, 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) floatA, output, + VTK_FLOAT, 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) floatA, output, + VTK_FLOAT, 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) floatA, output, + VTK_FLOAT, 2, 1, VTK_LUMINANCE); + + double doubleA[2] = {1, 10}; + lut1->MapScalarsThroughTable2((void *) doubleA, output, + VTK_DOUBLE, 2, 1, VTK_RGBA); + lut1->MapScalarsThroughTable2((void *) doubleA, output, + VTK_DOUBLE, 2, 1, VTK_RGB); + lut1->MapScalarsThroughTable2((void *) doubleA, output, + VTK_DOUBLE, 2, 1, VTK_LUMINANCE_ALPHA); + lut1->MapScalarsThroughTable2((void *) doubleA, output, + VTK_DOUBLE, 2, 1, VTK_LUMINANCE); + + +} + + +int otherLookupTable(int,char *[]) +{ + vtkLookupTable *lut1 = vtkLookupTable::New(); + lut1->SetAlpha(1.0); + lut1->SetScaleToLinear(); + TestOLT(lut1); + lut1->SetAlpha(.5); + TestOLT(lut1); + lut1->Delete(); + + vtkLogLookupTable *lut2 = vtkLogLookupTable::New(); + lut2->SetAlpha(1.0); + lut2->SetScaleToLog10(); + TestOLT(lut2); + lut2->SetAlpha(.5); + TestOLT(lut2); + lut2->Delete(); + + return 0; +} diff --git a/Common/Testing/Cxx/otherRectilinearGrid.cxx b/Common/Testing/Cxx/otherRectilinearGrid.cxx new file mode 100644 index 0000000..792da3c --- /dev/null +++ b/Common/Testing/Cxx/otherRectilinearGrid.cxx @@ -0,0 +1,602 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherRectilinearGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests vtkRectilinearGrid + +#include "vtkCell.h" +#include "vtkDebugLeaks.h" +#include "vtkDoubleArray.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkLongArray.h" +#include "vtkPointData.h" +#include "vtkRectilinearGrid.h" +#include "vtkShortArray.h" + +int TestORG(ostream& strm) +{ + int i, j, k; + // actual test + strm << "Testing vtkRectilinearGrid" << endl; + vtkRectilinearGrid *rg0D = vtkRectilinearGrid::New(); + vtkRectilinearGrid *rg1Dx = vtkRectilinearGrid::New(); + vtkRectilinearGrid *rg1Dy = vtkRectilinearGrid::New(); + vtkRectilinearGrid *rg1Dz = vtkRectilinearGrid::New(); + vtkRectilinearGrid *rg2Dxy = vtkRectilinearGrid::New(); + vtkRectilinearGrid *rg2Dxz = vtkRectilinearGrid::New(); + vtkRectilinearGrid *rg2Dyz = vtkRectilinearGrid::New(); + vtkRectilinearGrid *rg3D = vtkRectilinearGrid::New(); + + vtkDoubleArray *xdata = vtkDoubleArray::New(); + vtkDoubleArray *ydata = vtkDoubleArray::New(); + vtkDoubleArray *zdata = vtkDoubleArray::New(); + + for (i = 0; i < 20; i++) + { + xdata->InsertNextValue((double) i); + ydata->InsertNextValue((double) i); + zdata->InsertNextValue((double) i); + } + + rg3D->SetDimensions(20,20,20); + rg3D->SetXCoordinates(xdata); + rg3D->SetYCoordinates(ydata); + rg3D->SetZCoordinates(zdata); + + rg2Dxy->SetDimensions(20,20,1); + rg2Dxy->SetXCoordinates(xdata); + rg2Dxy->SetYCoordinates(ydata); + + rg2Dxz->SetDimensions(20,1,20); + rg2Dxz->SetXCoordinates(xdata); + rg2Dxz->SetZCoordinates(zdata); + + rg2Dyz->SetDimensions(1,20,20); + rg2Dyz->SetYCoordinates(ydata); + rg2Dyz->SetZCoordinates(zdata); + + rg1Dx->SetDimensions(20,1,1); + rg1Dx->SetXCoordinates(xdata); + + rg1Dy->SetDimensions(1,20,1); + rg1Dy->SetYCoordinates(ydata); + strm << *rg1Dy; + + rg1Dz->SetDimensions(1,1,20); + rg1Dz->SetZCoordinates(zdata); + + rg0D->SetDimensions(1,1,1); + + vtkShortArray *shortScalars3D = vtkShortArray::New(); + shortScalars3D->SetNumberOfComponents(3); + shortScalars3D->SetNumberOfTuples(20*20*20); + + int l = 0; + for (k = 0; k < 20; k++) + { + for (j = 0; j < 20; j++) + { + for (i = 0; i < 20; i++) + { + shortScalars3D->InsertComponent(l,0,i); + shortScalars3D->InsertComponent(l,0,j); + shortScalars3D->InsertComponent(l,0,k); + l++; + } + } + } + + vtkShortArray *shortScalars2D = vtkShortArray::New(); + shortScalars2D->SetNumberOfComponents(2); + shortScalars2D->SetNumberOfTuples(20*20); + + l = 0; + for (j = 0; j < 20; j++) + { + for (i = 0; i < 20; i++) + { + shortScalars2D->InsertComponent(l,0,i); + shortScalars2D->InsertComponent(l,0,j); + l++; + } + } + + vtkShortArray *shortScalars1D = vtkShortArray::New(); + shortScalars1D->SetNumberOfComponents(1); + shortScalars1D->SetNumberOfTuples(20); + + l = 0; + for (i = 0; i < 20; i++) + { + shortScalars1D->InsertComponent(l,0,i); + l++; + } + + vtkShortArray *shortScalars0D = vtkShortArray::New(); + shortScalars0D->SetNumberOfComponents(1); + shortScalars0D->SetNumberOfTuples(1); + + l = 0; + shortScalars0D->InsertComponent(l,0,0); + + rg3D->GetPointData()->SetScalars(shortScalars3D); + rg2Dxy->GetPointData()->SetScalars(shortScalars2D); + rg2Dxz->GetPointData()->SetScalars(shortScalars2D); + rg2Dyz->GetPointData()->SetScalars(shortScalars2D); + rg1Dx->GetPointData()->SetScalars(shortScalars1D); + rg1Dy->GetPointData()->SetScalars(shortScalars1D); + rg1Dz->GetPointData()->SetScalars(shortScalars1D); + rg0D->GetPointData()->SetScalars(shortScalars0D); + + strm << "rg3D:" << *rg3D; + + // Test shallow copy + vtkRectilinearGrid *scrg3D = vtkRectilinearGrid::New(); + scrg3D->ShallowCopy(rg3D); + strm << "ShallowCopy(rg3D):" << *scrg3D; + + // Test deep copy + vtkRectilinearGrid *dcrg3D = vtkRectilinearGrid::New(); + dcrg3D->DeepCopy(rg3D); + strm << "DeepCopy(rg3D):" << *dcrg3D; + + // Test GetCell + vtkIdList *ids = vtkIdList::New(); + int cellId; + int ii; + + i = 10; j = 15; k = 7; + cellId = k * (19 * 19) + j * 19 + i; + vtkCell *cell3D = rg3D->GetCell(cellId); + strm << "cell3D: " << *cell3D ; + rg3D->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; j = 15; + cellId = j * 19 + i; + vtkCell *cell2D = rg2Dxy->GetCell(cellId); + strm << "cell2D: " << *cell2D ; + rg2Dxy->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + + i = 10; j = 15; + cellId = j * 19 + i; + cell2D = rg2Dxz->GetCell(j * 19 + i); + strm << "cell2D: " << *cell2D ; + rg2Dxz->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; j = 15; + cellId = j * 19 + i; + cell2D = rg2Dyz->GetCell(j * 19 + i); + strm << "cell2D: " << *cell2D ; + rg2Dyz->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; + cellId = i; + vtkCell *cell1D = rg1Dx->GetCell(i); + strm << "cell1D: " << *cell1D; + rg1Dx->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; + cellId = i; + cell1D = rg1Dy->GetCell(i); + strm << "cell1D: " << *cell1D; + rg1Dy->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; + cellId = i; + cell1D = rg1Dz->GetCell(i); + strm << "cell1D: " << *cell1D; + rg1Dz->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + cellId = 0; + vtkCell *cell0D = rg0D->GetCell(0); + strm << "cell0D: " << *cell0D; + rg0D->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + // Test Thread Safe GetCell + vtkGenericCell *gcell3D = vtkGenericCell::New(); + vtkGenericCell *gcell2D = vtkGenericCell::New(); + vtkGenericCell *gcell1D = vtkGenericCell::New(); + vtkGenericCell *gcell0D = vtkGenericCell::New(); + i = 10; j = 15; k = 7; + rg3D->GetCell(k * (19 * 19) + j * 19 + i, gcell3D); + strm << "gcell3D: " << *gcell3D ; + + i = 10; j = 15; + rg2Dxy->GetCell(j * 19 + i,gcell2D); + strm << "gcell2D: " << *gcell2D ; + + i = 10; j = 15; + rg2Dxz->GetCell(j * 19 + i,gcell2D); + strm << "gcell2D: " << *gcell2D ; + + i = 10; j = 15; + rg2Dxz->GetCell(j * 19 + i,gcell2D); + strm << "gcell2D: " << *gcell2D ; + + i = 10; j = 15; + rg2Dyz->GetCell(j * 19 + i,gcell2D); + strm << "gcell2D: " << *gcell2D ; + + i = 10; + rg1Dx->GetCell(i,gcell1D); + strm << "gcell1D: " << *gcell1D; + + i = 10; + rg1Dy->GetCell(i,gcell1D); + strm << "gcell1D: " << *gcell1D; + + i = 10; + rg1Dz->GetCell(i,gcell1D); + strm << "gcell1D: " << *gcell1D; + + i = 10; + rg0D->GetCell(0,gcell0D); + strm << "gcell0D: " << *gcell0D; + + // Test GetCellBounds + + double bounds[6]; + rg3D->GetCellBounds(k * (19 * 19) + j * 19 + i, bounds); + strm << "GetCellBounds(rg3D): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + rg2Dxy->GetCellBounds(j * 19 + i, bounds); + strm << "GetCellBounds(rg2Dxy): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + rg2Dxz->GetCellBounds(j * 19 + i, bounds); + strm << "GetCellBounds(rg2Dxz): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + rg2Dyz->GetCellBounds(j * 19 + i, bounds); + strm << "GetCellBounds(rg2Dyz): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + rg1Dx->GetCellBounds(i, bounds); + strm << "GetCellBounds(rg1x): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + rg1Dy->GetCellBounds(i, bounds); + strm << "GetCellBounds(rg1Dy): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + rg1Dz->GetCellBounds(i, bounds); + strm << "GetCellBounds(rg1Dz): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + rg0D->GetCellBounds(i, bounds); + strm << "GetCellBounds(rg0D): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + // Test GetPoint + + double point[6]; + rg3D->GetPoint(k * (20 * 20) + j * 20 + i, point); + strm << "GetPoint(rg3D): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + rg2Dxy->GetPoint(j * 20 + i, point); + strm << "GetPoint(rg2Dxy): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + rg2Dxz->GetPoint(j * 20 + i, point); + strm << "GetPoint(rg2Dxz): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + rg2Dyz->GetPoint(j * 20 + i, point); + strm << "GetPoint(rg2Dyz): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + rg1Dx->GetPoint(i, point); + strm << "GetPoint(rg1x): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + rg1Dy->GetPoint(i, point); + strm << "GetPoint(rg1Dy): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + rg1Dz->GetPoint(i, point); + strm << "GetPoint(rg1Dz): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + rg0D->GetPoint(0, point); + strm << "GetPoint(rg0D): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + // Test FindPoint + + double point3D[3] = {10, 12, 14}; + + rg3D->GetPoint(rg3D->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 10; point3D[1] = 12; point3D[2] = 0; + rg2Dxy->GetPoint(rg2Dxy->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 10; point3D[1] = 0; point3D[2] = 14; + rg2Dxz->GetPoint(rg2Dxz->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 0; point3D[1] = 12; point3D[2] = 14; + rg2Dyz->GetPoint(rg2Dyz->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 10; point3D[1] = 0; point3D[2] = 0; + rg1Dx->GetPoint(rg1Dx->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 0; point3D[1] = 12; point3D[2] = 0; + rg1Dy->GetPoint(rg1Dy->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 0; point3D[1] = 0; point3D[2] = 14; + rg1Dz->GetPoint(rg1Dz->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + // Test FindAndGetCell + + double pcoords[3], weights[8]; + int subId; + vtkCell *dummyCell = NULL; + + point3D[0] = 10.5; + point3D[1] = 12.1; + point3D[2] = 14.7; + + strm << "FindAndGetCell(rg3D): " << *rg3D->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << ", " << pcoords[2] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " + << weights[2] << ", " << weights[3] << ", " + << weights[4] << ", " << weights[5] << ", " + << weights[6] << ", " << weights[7] << endl; + + point3D[0] = 10.5; point3D[1] = 12.1; point3D[2] = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + dummyCell = 0; + vtkCell *found = rg2Dxy->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(rg2Dxy) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(rg2Dxy): " << *found; + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " << weights[2] << ", " << weights[3] << endl; + + point3D[0] = 10.5; point3D[1] = 0.0; point3D[2] = 14.7; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + weights[0] = weights[1] = weights[2] = weights[3] = 0.0; + dummyCell = 0; + found = rg2Dxz->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(rg2Dxz) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(rg2Dxz): " << *found; + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " << weights[2] << ", " << weights[3] << endl; + + point3D[0] = 0.0; point3D[1] = 12.1; point3D[2] = 14.7; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + weights[0] = weights[1] = weights[2] = weights[3] = 0.0; + dummyCell = 0; + found = rg2Dyz->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(rg2Dyz) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(rg2Dyz): " << *found; + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " << weights[2] << ", " << weights[3] << endl; + + point3D[0] = 10.5; point3D[1] = 0.0; point3D[2] = 0.0; + dummyCell = 0; + found = rg1Dx->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(rg1Dx) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(rg1Dx): " << *found; + strm << "pcoords: " + << pcoords[0] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << endl; + + + point3D[0] = 0.0; point3D[1] = 12.1; point3D[2] = 0.0; + dummyCell = 0; + found = rg1Dy->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(rg1Dy) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(rg1Dy): " << *found; + strm << "pcoords: " + << pcoords[0] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << endl; + + + point3D[0] = 0.0; point3D[1] = 0.0; point3D[2] = 14.7; + dummyCell = 0; + found = rg1Dz->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(rg1Dz) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(rg1Dz): " << *found; + strm << "pcoords: " + << pcoords[0] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << endl; + + + // Test GetCellType + + strm << "GetCellType(rg3D): " << rg3D->GetCellType(0) << endl; + strm << "GetCellType(rg2Dxy): " << rg2Dxy->GetCellType(0) << endl; + strm << "GetCellType(rg2Dxz): " << rg2Dxz->GetCellType(0) << endl; + strm << "GetCellType(rg2Dyz): " << rg2Dyz->GetCellType(0) << endl; + strm << "GetCellType(rg1Dx): " << rg1Dx->GetCellType(0) << endl; + strm << "GetCellType(rg1Dy): " << rg1Dy->GetCellType(0) << endl; + strm << "GetCellType(rg1Dz): " << rg1Dz->GetCellType(0) << endl; + strm << "GetCellType(rg0D): " << rg0D->GetCellType(0) << endl; + + // Test GetActualMemorySize + + strm << "GetActualMemorySize(rg3D): " << rg3D->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(rg2Dxy): " << rg2Dxy->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(rg2Dxz): " << rg2Dxz->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(rg2Dyz): " << rg2Dyz->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(rg1Dx): " << rg1Dx->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(rg1Dy): " << rg1Dy->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(rg1Dz): " << rg1Dz->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(rg0D): " << rg0D->GetActualMemorySize() << endl; + + // Cleanup + rg0D->Delete(); + rg1Dx->Delete(); + rg1Dy->Delete(); + rg1Dz->Delete(); + rg2Dxy->Delete(); + rg2Dxz->Delete(); + rg2Dyz->Delete(); + rg3D->Delete(); + xdata->Delete(); + ydata->Delete(); + zdata->Delete(); + shortScalars3D->Delete(); + shortScalars2D->Delete(); + shortScalars1D->Delete(); + shortScalars0D->Delete(); + scrg3D->Delete(); + dcrg3D->Delete(); + ids->Delete(); + gcell3D->Delete(); + gcell2D->Delete(); + gcell1D->Delete(); + gcell0D->Delete(); + + strm << "Testing completed" << endl; + return 0; +} + +int otherRectilinearGrid(int,char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return TestORG(vtkmsg_with_warning_C4701); +} diff --git a/Common/Testing/Cxx/otherStringArray.cxx b/Common/Testing/Cxx/otherStringArray.cxx new file mode 100644 index 0000000..c7fd794 --- /dev/null +++ b/Common/Testing/Cxx/otherStringArray.cxx @@ -0,0 +1,266 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherStringArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkDebugLeaks.h" +#include "vtkCharArray.h" +#include "vtkIdTypeArray.h" +#include "vtkStringArray.h" +#include "vtkIdList.h" + +#define SIZE 1000 + +int doStringArrayTest(ostream& strm, int size) +{ + int errors = 0; + + vtkStringArray *ptr = vtkStringArray::New(); + vtkStdString *strings = new vtkStdString[SIZE]; + for (int i = 0; i < SIZE; ++i) + { + char buf[1024]; + sprintf(buf, "string entry %d", i); + strings[i] = vtkStdString(buf); + } + + strm << "\tResize(0)..."; + ptr->Resize(0); + strm << "OK" << endl; + + strm << "\tResize(10)..."; + ptr->Resize(10); + strm << "OK" << endl; + + strm << "\tResize(5)..."; + ptr->Resize(5); + strm << "OK" << endl; + + strm << "\tResize(size)..."; + ptr->Resize(size); + strm << "OK" << endl; + + strm << "\tSetNumberOfValues..."; + ptr->SetNumberOfValues(100); + if (ptr->GetNumberOfValues() == 100) strm << "OK" << endl; + else + { + ++errors; + strm << "FAILED" << endl; + } + + strm << "\tSetVoidArray..."; + ptr->SetVoidArray(strings, size, 1); + strm << "OK" << endl; + + strm << "\tGetValue..."; + vtkStdString value = ptr->GetValue(123); + if (value == "string entry 123") + { + strm << "OK" << endl; + } + else + { + ++errors; + strm << "FAILED. Expected 'string entry 123', got '" + << value << "'" << endl; +#ifdef DUMP_VALUES + for (int i = 0; i < ptr->GetNumberOfValues(); ++i) + { + strm << "\t\tValue " << i << ": " << ptr->GetValue(i) << endl; + } +#endif + } + + strm << "\tSetValue..."; + ptr->SetValue(124, "jabberwocky"); + if (ptr->GetValue(124) == "jabberwocky") + { + strm << "OK" << endl; + } + else + { + ++errors; + strm << "FAILED" << endl; + } + + strm << "\tInsertValue..."; + ptr->InsertValue(500, "There and Back Again"); + if (ptr->GetValue(500) == "There and Back Again") + { + strm << "OK" << endl; + } + else + { + ++errors; + strm << "FAILED" << endl; + } + + strm << "\tInsertNextValue..."; + if (ptr->GetValue(ptr->InsertNextValue("3.141592653589")) == + "3.141592653589") + { + strm << "OK" << endl; + } + else + { + ++errors; + strm << "FAILED" << endl; + } + + strm << "\tvtkAbstractArray::GetValues(vtkIdList)..."; + vtkIdList *indices = vtkIdList::New(); + indices->InsertNextId(10); + indices->InsertNextId(20); + indices->InsertNextId(314); + + vtkStringArray *newValues = vtkStringArray::New(); + newValues->SetNumberOfValues(3); + ptr->GetValues(indices, newValues); + + if (newValues->GetValue(0) == "string entry 10" && + newValues->GetValue(1) == "string entry 20" && + newValues->GetValue(2) == "string entry 314") + { + strm << "OK" << endl; + } + else + { + ++errors; + strm << "FAILED. Results:" << endl; + strm << "\tExpected: 'string entry 10'\tActual: '" + << newValues->GetValue(0) << "'" << endl; + strm << "\tExpected: 'string entry 20'\tActual: '" + << newValues->GetValue(1) << "'" << endl; + strm << "\tExpected: 'string entry 314'\tActual: '" + << newValues->GetValue(2) << "'" << endl; + } + + newValues->Reset(); + + strm << "\tvtkAbstractArray::GetValues(vtkIdType, vtkIdType)..."; + newValues->SetNumberOfValues(3); + ptr->GetValues(30, 32, newValues); + if (newValues->GetValue(0) == "string entry 30" && + newValues->GetValue(1) == "string entry 31" && + newValues->GetValue(2) == "string entry 32") + { + strm << "OK" << endl; + } + else + { + ++errors; + strm << "FAILED" << endl; + } + + strm << "\tvtkAbstractArray::CopyValue..."; + ptr->CopyValue(150, 2, newValues); + if (ptr->GetValue(150) == "string entry 32") + { + strm << "OK" << endl; + } + else + { + ++errors; + strm << "FAILED" << endl; + } + + newValues->Delete(); + indices->Delete(); + + strm << "PrintSelf..." << endl; + strm << *ptr; + + ptr->Delete(); + delete [] strings; + + strm << "\tvtkAbstractArray::ConvertToContiguous..."; + vtkStringArray *srcArray = vtkStringArray::New(); + vtkStringArray *destArray = vtkStringArray::New(); + + srcArray->InsertNextValue("First"); + srcArray->InsertNextValue("Second"); + srcArray->InsertNextValue("Third"); + + vtkDataArray *data; + vtkIdTypeArray *offsets; + srcArray->ConvertToContiguous(&data, &offsets); + + char combinedString[] = "FirstSecondThird"; + vtkCharArray *charData = vtkCharArray::SafeDownCast(data); + if (charData == NULL) + { + ++errors; + strm << "FAILED: couldn't downcast data array" << endl; + } + else + { + for (int i = 0; i < static_cast(strlen(combinedString)); ++i) + { + if (charData->GetValue(i) != combinedString[i]) + { + strm << "FAILED: array element " << i << " is wrong. Expected " + << combinedString[i] << ", got " + << charData->GetValue(i) << endl; + ++errors; + } + } + + + destArray->ConvertFromContiguous(data, offsets); + + if (destArray->GetNumberOfValues() != srcArray->GetNumberOfValues()) + { + ++errors; + strm << "FAILED: reconstructed lengths don't match" << endl; + } + else + { + for (int i = 0; i < srcArray->GetNumberOfValues(); ++i) + { + if (destArray->GetValue(i) != srcArray->GetValue(i)) + { + strm << "FAILED: element " << i << " doesn't match" << endl; + ++errors; + } + } + } + } + + + srcArray->Delete(); + destArray->Delete(); + data->Delete(); + offsets->Delete(); + + return errors; +} + +int otherStringArrayTest(ostream& strm) +{ + int errors = 0; + { + strm << "Test StringArray" << endl; + errors += doStringArrayTest(strm, SIZE); + } + + return errors; +} + +int otherStringArray(int, char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; +// return otherArraysTest(vtkmsg_with_warning_C4701); + return otherStringArrayTest(cerr); + +} diff --git a/Common/Testing/Cxx/otherStructuredGrid.cxx b/Common/Testing/Cxx/otherStructuredGrid.cxx new file mode 100644 index 0000000..4b6bda6 --- /dev/null +++ b/Common/Testing/Cxx/otherStructuredGrid.cxx @@ -0,0 +1,634 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherStructuredGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests vtkStructuredGrid + +#include "vtkCell.h" +#include "vtkDebugLeaks.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkLongArray.h" +#include "vtkPointData.h" +#include "vtkShortArray.h" +#include "vtkStructuredGrid.h" + +int TestOSG(ostream& strm) +{ + int i, j, k; + // actual test + strm << "Testing vtkStructuredGrid" << endl; + vtkStructuredGrid *sg0D = vtkStructuredGrid::New(); + vtkStructuredGrid *sg1Dx = vtkStructuredGrid::New(); + vtkStructuredGrid *sg1Dy = vtkStructuredGrid::New(); + vtkStructuredGrid *sg1Dz = vtkStructuredGrid::New(); + vtkStructuredGrid *sg2Dxy = vtkStructuredGrid::New(); + vtkStructuredGrid *sg2Dxz = vtkStructuredGrid::New(); + vtkStructuredGrid *sg2Dyz = vtkStructuredGrid::New(); + vtkStructuredGrid *sg3D = vtkStructuredGrid::New(); + + vtkPoints *xyzpoints = vtkPoints::New(); + for (k = 0; k < 20; k++) + { + for (j = 0; j < 20; j++) + { + for (i = 0; i < 20; i++) + { + xyzpoints->InsertNextPoint((double) i, (double) j, (double) k); + } + } + } + sg3D->SetDimensions(20,20,20); + sg3D->SetPoints(xyzpoints); xyzpoints->Delete(); + + vtkPoints *xypoints = vtkPoints::New(); + for (j = 0; j < 20; j++) + { + for (i = 0; i < 20; i++) + { + xypoints->InsertNextPoint((double) i, (double) j, 0.0); + } + } + sg2Dxy->SetDimensions(20,20,1); + sg2Dxy->SetPoints(xypoints); xypoints->Delete(); + + vtkPoints *xzpoints = vtkPoints::New(); + for (k = 0; k < 20; k++) + { + for (i = 0; i < 20; i++) + { + xzpoints->InsertNextPoint((double) i, 0.0, (double) k); + } + } + sg2Dxz->SetDimensions(20,1,20); + sg2Dxz->SetPoints(xzpoints); xzpoints->Delete(); + + vtkPoints *yzpoints = vtkPoints::New(); + for (k = 0; k < 20; k++) + { + for (j = 0; j < 20; j++) + { + yzpoints->InsertNextPoint(0.0, (double) j, (double) k); + } + } + sg2Dyz->SetDimensions(1,20,20); + sg2Dyz->SetPoints(yzpoints); yzpoints->Delete(); + + vtkPoints *xpoints = vtkPoints::New(); + for (i = 0; i < 20; i++) + { + xpoints->InsertNextPoint((double) i, 0.0, 0.0); + } + sg1Dx->SetDimensions(20,1,1); + sg1Dx->SetPoints(xpoints); xpoints->Delete(); + + vtkPoints *ypoints = vtkPoints::New(); + for (j = 0; j < 20; j++) + { + ypoints->InsertNextPoint(0.0, (double) j, 0.0); + } + sg1Dy->SetDimensions(1,20,1); + sg1Dy->SetPoints(ypoints); ypoints->Delete(); + strm << *sg1Dy; + + vtkPoints *zpoints = vtkPoints::New(); + for (k = 0; k < 20; k++) + { + zpoints->InsertNextPoint(0.0, 0.0, (double) k); + } + sg1Dz->SetDimensions(1,1,20); + sg1Dz->SetPoints(zpoints); zpoints->Delete(); + + vtkPoints *onepoints = vtkPoints::New(); + for (k = 0; k < 1; k++) + { + onepoints->InsertNextPoint(0.0, 0.0, 0.0); + } + sg0D->SetDimensions(1,1,1); + sg0D->SetPoints(onepoints); onepoints->Delete(); + + vtkShortArray *shortScalars3D = vtkShortArray::New(); + shortScalars3D->SetNumberOfComponents(3); + shortScalars3D->SetNumberOfTuples(20*20*20); + + int l = 0; + for (k = 0; k < 20; k++) + { + for (j = 0; j < 20; j++) + { + for (i = 0; i < 20; i++) + { + shortScalars3D->InsertComponent(l,0,i); + shortScalars3D->InsertComponent(l,0,j); + shortScalars3D->InsertComponent(l,0,k); + l++; + } + } + } + + vtkShortArray *shortScalars2D = vtkShortArray::New(); + shortScalars2D->SetNumberOfComponents(2); + shortScalars2D->SetNumberOfTuples(20*20); + + l = 0; + for (j = 0; j < 20; j++) + { + for (i = 0; i < 20; i++) + { + shortScalars2D->InsertComponent(l,0,i); + shortScalars2D->InsertComponent(l,0,j); + l++; + } + } + + vtkShortArray *shortScalars1D = vtkShortArray::New(); + shortScalars1D->SetNumberOfComponents(1); + shortScalars1D->SetNumberOfTuples(20); + + l = 0; + for (i = 0; i < 20; i++) + { + shortScalars1D->InsertComponent(l,0,i); + l++; + } + + vtkShortArray *shortScalars0D = vtkShortArray::New(); + shortScalars0D->SetNumberOfComponents(1); + shortScalars0D->SetNumberOfTuples(1); + + l = 0; + shortScalars0D->InsertComponent(l,0,0); + + sg3D->GetPointData()->SetScalars(shortScalars3D); + sg2Dxy->GetPointData()->SetScalars(shortScalars2D); + sg2Dxz->GetPointData()->SetScalars(shortScalars2D); + sg2Dyz->GetPointData()->SetScalars(shortScalars2D); + sg1Dx->GetPointData()->SetScalars(shortScalars1D); + sg1Dy->GetPointData()->SetScalars(shortScalars1D); + sg1Dz->GetPointData()->SetScalars(shortScalars1D); + sg0D->GetPointData()->SetScalars(shortScalars3D); + + strm << "sg3D:" << *sg3D; + + // Test shallow copy + vtkStructuredGrid *scsg3D = vtkStructuredGrid::New(); + scsg3D->ShallowCopy(sg3D); + strm << "ShallowCopy(sg3D):" << *scsg3D; + + // Test deep copy + vtkStructuredGrid *dcsg3D = vtkStructuredGrid::New(); + dcsg3D->DeepCopy(sg3D); + strm << "DeepCopy(sg3D):" << *dcsg3D; + + // Test GetCell + vtkIdList *ids = vtkIdList::New(); + int cellId; + int ii; + + i = 10; j = 15; k = 7; + cellId = k * (19 * 19) + j * 19 + i; + vtkCell *cell3D = sg3D->GetCell(cellId); + strm << "cell3D: " << *cell3D ; + sg3D->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; j = 15; + cellId = j * 19 + i; + vtkCell *cell2D = sg2Dxy->GetCell(cellId); + strm << "cell2D: " << *cell2D ; + sg2Dxy->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + + i = 10; j = 15; + cellId = j * 19 + i; + cell2D = sg2Dxz->GetCell(j * 19 + i); + strm << "cell2D: " << *cell2D ; + sg2Dxz->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; j = 15; + cellId = j * 19 + i; + cell2D = sg2Dyz->GetCell(j * 19 + i); + strm << "cell2D: " << *cell2D ; + sg2Dyz->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; + cellId = i; + vtkCell *cell1D = sg1Dx->GetCell(i); + strm << "cell1D: " << *cell1D; + sg1Dx->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; + cellId = i; + cell1D = sg1Dy->GetCell(i); + strm << "cell1D: " << *cell1D; + sg1Dy->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + i = 10; + cellId = i; + cell1D = sg1Dz->GetCell(i); + strm << "cell1D: " << *cell1D; + sg1Dz->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + cellId = 0; + vtkCell *cell0D = sg0D->GetCell(0); + strm << "cell0D: " << *cell0D; + sg0D->GetCellPoints (cellId, ids); + strm << "Ids for cell " << cellId << " are "; + for (ii = 0; ii < ids->GetNumberOfIds(); ii++) + { + strm << ids->GetId(ii) << " "; + } + strm << endl << endl; + + // Test Thread Safe GetCell + vtkGenericCell *gcell3D = vtkGenericCell::New(); + vtkGenericCell *gcell2D = vtkGenericCell::New(); + vtkGenericCell *gcell1D = vtkGenericCell::New(); + vtkGenericCell *gcell0D = vtkGenericCell::New(); + i = 10; j = 15; k = 7; + sg3D->GetCell(k * (19 * 19) + j * 19 + i, gcell3D); + strm << "gcell3D: " << *gcell3D ; + + i = 10; j = 15; + sg2Dxy->GetCell(j * 19 + i,gcell2D); + strm << "gcell2D: " << *gcell2D ; + + i = 10; j = 15; + sg2Dxz->GetCell(j * 19 + i,gcell2D); + strm << "gcell2D: " << *gcell2D ; + + i = 10; j = 15; + sg2Dyz->GetCell(j * 19 + i,gcell2D); + strm << "gcell2D: " << *gcell2D ; + + i = 10; + sg1Dx->GetCell(i,gcell1D); + strm << "gcell1D: " << *gcell1D; + + i = 10; + sg1Dy->GetCell(i,gcell1D); + strm << "gcell1D: " << *gcell1D; + + i = 10; + sg1Dz->GetCell(i,gcell1D); + strm << "gcell1D: " << *gcell1D; + + i = 10; + sg0D->GetCell(0,gcell0D); + strm << "gcell0D: " << *gcell0D; + + // Test GetCellBounds + + double bounds[6]; + sg3D->GetCellBounds(k * (19 * 19) + j * 19 + i, bounds); + strm << "GetCellBounds(sg3D): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + sg2Dxy->GetCellBounds(j * 19 + i, bounds); + strm << "GetCellBounds(sg2Dxy): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + sg2Dxz->GetCellBounds(j * 19 + i, bounds); + strm << "GetCellBounds(sg2Dxz): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + sg2Dyz->GetCellBounds(j * 19 + i, bounds); + strm << "GetCellBounds(sg2Dyz): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + sg1Dx->GetCellBounds(i, bounds); + strm << "GetCellBounds(sg1x): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + sg1Dy->GetCellBounds(i, bounds); + strm << "GetCellBounds(sg1Dy): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + sg1Dz->GetCellBounds(i, bounds); + strm << "GetCellBounds(sg1Dz): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + sg0D->GetCellBounds(i, bounds); + strm << "GetCellBounds(sg0D): " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5] << endl; + + // Test GetPoint + + double point[6]; + sg3D->GetPoint(k * (20 * 20) + j * 20 + i, point); + strm << "GetPoint(sg3D): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + sg2Dxy->GetPoint(j * 20 + i, point); + strm << "GetPoint(sg2Dxy): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + sg2Dxz->GetPoint(j * 20 + i, point); + strm << "GetPoint(sg2Dxz): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + sg2Dyz->GetPoint(j * 20 + i, point); + strm << "GetPoint(sg2Dyz): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + sg1Dx->GetPoint(i, point); + strm << "GetPoint(sg1x): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + sg1Dy->GetPoint(i, point); + strm << "GetPoint(sg1Dy): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + sg1Dz->GetPoint(i, point); + strm << "GetPoint(sg1Dz): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + sg0D->GetPoint(0, point); + strm << "GetPoint(sg0D): " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + // Test FindPoint + + double point3D[3] = {10, 12, 14}; + + sg3D->GetPoint(sg3D->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 10; point3D[1] = 12; point3D[2] = 0; + sg2Dxy->GetPoint(sg2Dxy->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 10; point3D[1] = 0; point3D[2] = 14; + sg2Dxz->GetPoint(sg2Dxz->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 0; point3D[1] = 12; point3D[2] = 14; + sg2Dyz->GetPoint(sg2Dyz->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 10; point3D[1] = 0; point3D[2] = 0; + sg1Dx->GetPoint(sg1Dx->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 0; point3D[1] = 12; point3D[2] = 0; + sg1Dy->GetPoint(sg1Dy->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + point3D[0] = 0; point3D[1] = 0; point3D[2] = 14; + sg1Dz->GetPoint(sg1Dz->FindPoint(point3D), point); + strm << "FindPoint(" + << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ") = " + << point[0] << ", " << point[1] << ", " << point[2] << endl; + + // Test FindAndGetCell + + double pcoords[3], weights[8]; + int subId; + vtkCell *dummyCell = 0; + + point3D[0] = 10.5; + point3D[1] = 12.1; + point3D[2] = 14.7; + + strm << "FindAndGetCell(sg3D): " << *sg3D->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << ", " << pcoords[2] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " + << weights[2] << ", " << weights[3] << ", " + << weights[4] << ", " << weights[5] << ", " + << weights[6] << ", " << weights[7] << endl; + + point3D[0] = 10.5; point3D[1] = 12.1; point3D[2] = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + dummyCell = 0; + vtkCell *found = sg2Dxy->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(sg2Dxy) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(sg2Dxy): " << *found; + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " << weights[2] << ", " << weights[3] << endl; + + point3D[0] = 10.5; point3D[1] = 0.0; point3D[2] = 14.7; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + weights[0] = weights[1] = weights[2] = weights[3] = 0.0; + dummyCell = 0; + found = sg2Dxz->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(sg2Dxz) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(sg2Dxz): " << *found; + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " << weights[2] << ", " << weights[3] << endl; + + point3D[0] = 0.0; point3D[1] = 12.1; point3D[2] = 14.7; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + weights[0] = weights[1] = weights[2] = weights[3] = 0.0; + dummyCell = 0; + found = sg2Dyz->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(sg2Dyz) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(sg2Dyz): " << *found; + strm << "pcoords: " + << pcoords[0] << ", " << pcoords[1] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << ", " << weights[2] << ", " << weights[3] << endl; + + point3D[0] = 10.5; point3D[1] = 0.0; point3D[2] = 0.0; + dummyCell = 0; + found = sg1Dx->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(sg1Dx) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(sg1Dx): " << *found; + strm << "pcoords: " + << pcoords[0] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << endl; + + + point3D[0] = 0.0; point3D[1] = 12.1; point3D[2] = 0.0; + dummyCell = 0; + found = sg1Dy->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(sg1Dy) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(sg1Dy): " << *found; + strm << "pcoords: " + << pcoords[0] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << endl; + + + point3D[0] = 0.0; point3D[1] = 0.0; point3D[2] = 14.7; + dummyCell = 0; + found = sg1Dz->FindAndGetCell(point3D, dummyCell, 0, 0, subId, pcoords, weights); + if (found == NULL) + { + strm << "FindAndGetCell(sg1Dz) not found!" << endl; + return 1; + } + + strm << "FindAndGetCell(sg1Dz): " << *found; + strm << "pcoords: " + << pcoords[0] << endl; + strm << "weights: " + << weights[0] << ", " << weights[1] << endl; + + + // Test GetCellType + + strm << "GetCellType(sg3D): " << sg3D->GetCellType(0) << endl; + strm << "GetCellType(sg2Dxy): " << sg2Dxy->GetCellType(0) << endl; + strm << "GetCellType(sg2Dxz): " << sg2Dxz->GetCellType(0) << endl; + strm << "GetCellType(sg2Dyz): " << sg2Dyz->GetCellType(0) << endl; + strm << "GetCellType(sg1Dx): " << sg1Dx->GetCellType(0) << endl; + strm << "GetCellType(sg1Dy): " << sg1Dy->GetCellType(0) << endl; + strm << "GetCellType(sg1Dz): " << sg1Dz->GetCellType(0) << endl; + strm << "GetCellType(sg0D): " << sg0D->GetCellType(0) << endl; + + // Test GetActualMemorySize + + strm << "GetActualMemorySize(sg3D): " << sg3D->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(sg2Dxy): " << sg2Dxy->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(sg2Dxz): " << sg2Dxz->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(sg2Dyz): " << sg2Dyz->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(sg1Dx): " << sg1Dx->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(sg1Dy): " << sg1Dy->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(sg1Dz): " << sg1Dz->GetActualMemorySize() << endl; + strm << "GetActualMemorySize(sg0D): " << sg0D->GetActualMemorySize() << endl; + + sg0D->Delete(); + sg1Dx->Delete(); + sg1Dy->Delete(); + sg1Dz->Delete(); + sg2Dxy->Delete(); + sg2Dxz->Delete(); + sg2Dyz->Delete(); + sg3D->Delete(); + shortScalars3D->Delete(); + shortScalars2D->Delete(); + shortScalars1D->Delete(); + shortScalars0D->Delete(); + scsg3D->Delete(); + dcsg3D->Delete(); + ids->Delete(); + gcell3D->Delete(); + gcell2D->Delete(); + gcell1D->Delete(); + gcell0D->Delete(); + + strm << "Testing completed" << endl; + return 0; +} + +int otherStructuredGrid(int,char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return TestOSG(vtkmsg_with_warning_C4701); +} diff --git a/Common/Testing/Cxx/otherTimerLog.cxx b/Common/Testing/Cxx/otherTimerLog.cxx new file mode 100644 index 0000000..3a77173 --- /dev/null +++ b/Common/Testing/Cxx/otherTimerLog.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherTimerLog.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the TimerLog + +#include "vtkTimerLog.h" +#include "vtkDebugLeaks.h" + +// this is needed for the unlink call +#if defined(__CYGWIN__) +#include +#elif defined(_WIN32) +# include +#endif + +#include "vtkWindows.h" // for Sleep + +void otherTimerLogTest(ostream& strm) +{ + // actual test + float a = 1.0; + int i, j; + strm << "Test vtkTimerLog Start" << endl; + vtkTimerLog *timer1 = vtkTimerLog::New(); + + timer1->SetMaxEntries (3); + timer1->StartTimer(); + for (j = 0; j < 4; j++) + { + timer1->FormatAndMarkEvent("%s%d", "start", j); + for (i = 0; i < 10000000; i++) + { + a *= a; + } +#ifndef WIN32 + sleep (1); +#else + Sleep(1000); +#endif + timer1->FormatAndMarkEvent("%s%d", "end", j); + } + timer1->StopTimer(); + strm << *timer1; + strm << "GetElapsedTime: " << timer1->GetElapsedTime() << endl; + strm << "GetCPUTime: " << timer1->GetCPUTime() << endl; + timer1->DumpLog( "timing" ); + timer1->ResetLog (); + timer1->CleanupLog(); + unlink("timing"); + timer1->Delete(); + strm << "Test vtkTimerLog End" << endl; +} + + +int otherTimerLog(int,char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + otherTimerLogTest(vtkmsg_with_warning_C4701); + + return 0; +} diff --git a/Common/Testing/Cxx/quadraticEvaluation.cxx b/Common/Testing/Cxx/quadraticEvaluation.cxx new file mode 100644 index 0000000..71628f7 --- /dev/null +++ b/Common/Testing/Cxx/quadraticEvaluation.cxx @@ -0,0 +1,400 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: quadraticEvaluation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME +// .SECTION Description +// This program tests quadratic cell EvaluatePosition() and EvaluateLocation() +// methods. + +#include "vtkDebugLeaks.h" + +#include "vtkIdList.h" +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticTriangle.h" +#include "vtkQuadraticQuad.h" +#include "vtkQuadraticHexahedron.h" +#include "vtkQuadraticTetra.h" +#include "vtkQuadraticWedge.h" +#include "vtkQuadraticPyramid.h" + +void ComputeDataValues(vtkPoints *pts, double *edgeValues) +{ + double x[3]; + int numPts = pts->GetNumberOfPoints(); + for (int i=0; iGetPoint(i,x); + double dem = (1.0 + x[0]); + if(fabs(dem) < 1.e-08) + { + edgeValues[i] = 0; + } + else + { + edgeValues[i] = 1.0 / dem; //simple linear function for now + } + } +} + +int TestQE(ostream& strm) +{ + // actual test + double dist2; + int subId; + + //----------------------------------------------------------- + strm << "Test instantiation New() and NewInstance() Start" << endl; + vtkQuadraticEdge *edge = vtkQuadraticEdge::New(); + vtkQuadraticEdge *edge2 = edge->NewInstance(); + + vtkQuadraticTriangle *tri = vtkQuadraticTriangle::New(); + vtkQuadraticTriangle *tri2 = tri->NewInstance(); + + vtkQuadraticQuad *quad = vtkQuadraticQuad::New(); + vtkQuadraticQuad *quad2 = quad->NewInstance(); + + vtkQuadraticTetra *tetra = vtkQuadraticTetra::New(); + vtkQuadraticTetra *tetra2 = tetra->NewInstance(); + + vtkQuadraticHexahedron *hex = vtkQuadraticHexahedron::New(); + vtkQuadraticHexahedron *hex2 = hex->NewInstance(); + + vtkQuadraticWedge *wedge = vtkQuadraticWedge::New(); + vtkQuadraticWedge *wedge2 = wedge->NewInstance(); + + vtkQuadraticPyramid *pyra = vtkQuadraticPyramid::New(); + vtkQuadraticHexahedron *pyra2 = hex->NewInstance(); + + edge2->Delete(); + tri2->Delete(); + quad2->Delete(); + tetra2->Delete(); + hex2->Delete(); + wedge2->Delete(); + pyra2->Delete(); + + strm << "Test instantiation New() and NewInstance() End" << endl; + + + //------------------------------------------------------------- + strm << "Test vtkCell::EvaluatePosition Start" << endl; + + // vtkQuadraticEdge + double edgePCoords[3], edgeWeights[3], edgePosition[3]; + double edgePoint[1][3] = {{0.25, 0.125, 0.0}}; + double edgeClosest[3]; + + edge->GetPointIds()->SetId(0,0); + edge->GetPointIds()->SetId(1,1); + edge->GetPointIds()->SetId(2,2); + + edge->GetPoints()->SetPoint(0, 0, 0, 0); + edge->GetPoints()->SetPoint(1, 1, 0, .5); + edge->GetPoints()->SetPoint(2, 0.5, 0.25, .2); + + edge->EvaluatePosition(edgePoint[0], edgeClosest, subId, edgePCoords, + dist2, edgeWeights); + + // vtkQuadraticTriangle + double triPCoords[3], triWeights[6], triPosition[3]; + double triPoint[1][3] = {{0.5, 0.266667, 0.0}}; + double triClosest[3]; + + tri->GetPointIds()->SetId(0,0); + tri->GetPointIds()->SetId(1,1); + tri->GetPointIds()->SetId(2,2); + tri->GetPointIds()->SetId(3,3); + tri->GetPointIds()->SetId(4,4); + tri->GetPointIds()->SetId(5,5); + + tri->GetPoints()->SetPoint(0, 0, 0, 0); + tri->GetPoints()->SetPoint(1, 1, 0, 0); + tri->GetPoints()->SetPoint(2, 0.5, 0.8, 0); + tri->GetPoints()->SetPoint(3, 0.5, 0.0, 0); + tri->GetPoints()->SetPoint(4, 0.75, 0.4, 0); + tri->GetPoints()->SetPoint(5, 0.25, 0.4, 0); + + tri->EvaluatePosition(triPoint[0], triClosest, subId, triPCoords, + dist2, triWeights); + + + // vtkQuadraticQuad + double quadPCoords[3], quadWeights[8], quadPosition[3]; + double quadPoint[1][3] = {{0.25, 0.33, 0.0}}; + double quadClosest[3]; + + quad->GetPointIds()->SetId(0,0); + quad->GetPointIds()->SetId(1,1); + quad->GetPointIds()->SetId(2,2); + quad->GetPointIds()->SetId(3,3); + quad->GetPointIds()->SetId(4,4); + quad->GetPointIds()->SetId(5,5); + quad->GetPointIds()->SetId(6,6); + quad->GetPointIds()->SetId(7,7); + + quad->GetPoints()->SetPoint(0, 0.0, 0.0, 0.0); + quad->GetPoints()->SetPoint(1, 1.0, 0.0, 0.0); + quad->GetPoints()->SetPoint(2, 1.0, 1.0, 0.0); + quad->GetPoints()->SetPoint(3, 0.0, 1.0, 0.0); + quad->GetPoints()->SetPoint(4, 0.5, 0.0, 0.0); + quad->GetPoints()->SetPoint(5, 1.0, 0.5, 0.0); + quad->GetPoints()->SetPoint(6, 0.5, 1.0, 0.0); + quad->GetPoints()->SetPoint(7, 0.0, 0.5, 0.0); + + quad->EvaluatePosition(quadPoint[0], quadClosest, subId, quadPCoords, + dist2, quadWeights); + + // vtkQuadraticTetra + double tetraPCoords[3], tetraWeights[10], tetraPosition[3]; + double tetraPoint[1][3] = {{0.5, 0.266667, 0.333333}}; + double tetraClosest[3]; + + tetra->GetPointIds()->SetId(0,0); + tetra->GetPointIds()->SetId(1,1); + tetra->GetPointIds()->SetId(2,2); + tetra->GetPointIds()->SetId(3,3); + tetra->GetPointIds()->SetId(4,4); + tetra->GetPointIds()->SetId(5,5); + tetra->GetPointIds()->SetId(6,6); + tetra->GetPointIds()->SetId(7,7); + tetra->GetPointIds()->SetId(8,8); + tetra->GetPointIds()->SetId(9,9); + + tetra->GetPoints()->SetPoint(0, 0.0, 0.0, 0.0); + tetra->GetPoints()->SetPoint(1, 1.0, 0.0, 0.0); + tetra->GetPoints()->SetPoint(2, 0.5, 0.8, 0.0); + tetra->GetPoints()->SetPoint(3, 0.5, 0.4, 1.0); + tetra->GetPoints()->SetPoint(4, 0.5, 0.0, 0.0); + tetra->GetPoints()->SetPoint(5, 0.75, 0.4, 0.0); + tetra->GetPoints()->SetPoint(6, 0.25, 0.4, 0.0); + tetra->GetPoints()->SetPoint(7, 0.25, 0.2, 0.5); + tetra->GetPoints()->SetPoint(8, 0.75, 0.2, 0.5); + tetra->GetPoints()->SetPoint(9, 0.50, 0.6, 0.5); + + tetra->EvaluatePosition(tetraPoint[0], tetraClosest, subId, tetraPCoords, + dist2, tetraWeights); + + + // vtkQuadraticHexahedron + double hexPCoords[3], hexWeights[20], hexPosition[3]; + double hexPoint[1][3] = {{0.25, 0.33333, 0.666667}}; + double hexClosest[3]; + + hex->GetPointIds()->SetId(0,0); + hex->GetPointIds()->SetId(1,1); + hex->GetPointIds()->SetId(2,2); + hex->GetPointIds()->SetId(3,3); + hex->GetPointIds()->SetId(4,4); + hex->GetPointIds()->SetId(5,5); + hex->GetPointIds()->SetId(6,6); + hex->GetPointIds()->SetId(7,7); + hex->GetPointIds()->SetId(8,8); + hex->GetPointIds()->SetId(9,9); + hex->GetPointIds()->SetId(10,10); + hex->GetPointIds()->SetId(11,11); + hex->GetPointIds()->SetId(12,12); + hex->GetPointIds()->SetId(13,13); + hex->GetPointIds()->SetId(14,14); + hex->GetPointIds()->SetId(15,15); + hex->GetPointIds()->SetId(16,16); + hex->GetPointIds()->SetId(17,17); + hex->GetPointIds()->SetId(18,18); + hex->GetPointIds()->SetId(19,19); + + hex->GetPoints()->SetPoint( 0, 0, 0, 0 ); + hex->GetPoints()->SetPoint( 1, 1, 0, 0 ); + hex->GetPoints()->SetPoint( 2, 1, 1, 0 ); + hex->GetPoints()->SetPoint( 3, 0, 1, 0 ); + hex->GetPoints()->SetPoint( 4, 0, 0, 1 ); + hex->GetPoints()->SetPoint( 5, 1, 0, 1 ); + hex->GetPoints()->SetPoint( 6, 1, 1, 1 ); + hex->GetPoints()->SetPoint( 7, 0, 1, 1 ); + hex->GetPoints()->SetPoint( 8, 0.5, 0, 0); + hex->GetPoints()->SetPoint( 9, 1, 0.5, 0); + hex->GetPoints()->SetPoint(10, 0.5, 1, 0); + hex->GetPoints()->SetPoint(11, 0, 0.5, 0); + hex->GetPoints()->SetPoint(12, 0.5, 0, 1); + hex->GetPoints()->SetPoint(13, 1, 0.5, 1); + hex->GetPoints()->SetPoint(14, 0.5, 1, 1); + hex->GetPoints()->SetPoint(15, 0, 0.5, 1); + hex->GetPoints()->SetPoint(16, 0, 0, 0.5); + hex->GetPoints()->SetPoint(17, 1, 0, 0.5); + hex->GetPoints()->SetPoint(18, 1, 1, 0.5); + hex->GetPoints()->SetPoint(19, 0, 1, 0.5); + + hex->EvaluatePosition(hexPoint[0], hexClosest, subId, hexPCoords, + dist2, hexWeights); + + // vtkQuadraticWedge + double wedgePCoords[3], wedgeWeights[20], wedgePosition[3]; + double wedgePoint[1][3] = {{0.25, 0.33333, 0.666667}}; + double wedgeClosest[3]; + + wedge->GetPointIds()->SetId(0,0); + wedge->GetPointIds()->SetId(1,1); + wedge->GetPointIds()->SetId(2,2); + wedge->GetPointIds()->SetId(3,3); + wedge->GetPointIds()->SetId(4,4); + wedge->GetPointIds()->SetId(5,5); + wedge->GetPointIds()->SetId(6,6); + wedge->GetPointIds()->SetId(7,7); + wedge->GetPointIds()->SetId(8,8); + wedge->GetPointIds()->SetId(9,9); + wedge->GetPointIds()->SetId(10,10); + wedge->GetPointIds()->SetId(11,11); + wedge->GetPointIds()->SetId(12,12); + wedge->GetPointIds()->SetId(13,13); + wedge->GetPointIds()->SetId(14,14); + + wedge->GetPoints()->SetPoint( 0, 0, 0, 0 ); + wedge->GetPoints()->SetPoint( 1, 1, 0, 0 ); + wedge->GetPoints()->SetPoint( 2, 0, 1, 0 ); + wedge->GetPoints()->SetPoint( 3, 0, 0, 1 ); + wedge->GetPoints()->SetPoint( 4, 1, 0, 1 ); + wedge->GetPoints()->SetPoint( 5, 0, 1, 1 ); + wedge->GetPoints()->SetPoint( 6, 0.5, 0, 0 ); + wedge->GetPoints()->SetPoint( 7, 0.5, 0.5, 0 ); + wedge->GetPoints()->SetPoint( 8, 0, 0.5, 0); + wedge->GetPoints()->SetPoint( 9, 0.5, 0, 1); + wedge->GetPoints()->SetPoint(10, 0.5, 0.5, 1); + wedge->GetPoints()->SetPoint(11, 0, 0.5, 1); + wedge->GetPoints()->SetPoint(12, 0, 0, 0.5); + wedge->GetPoints()->SetPoint(13, 1, 0, 0.5); + wedge->GetPoints()->SetPoint(14, 0, 1, 0.5); + + wedge->EvaluatePosition(wedgePoint[0], wedgeClosest, subId, wedgePCoords, + dist2, wedgeWeights); + + // vtkQuadraticPyramid + double pyraPCoords[3], pyraWeights[20], pyraPosition[3]; + double pyraPoint[1][3] = {{0.25, 0.33333, 0.666667}}; + double pyraClosest[3]; + + pyra->GetPointIds()->SetId(0,0); + pyra->GetPointIds()->SetId(1,1); + pyra->GetPointIds()->SetId(2,2); + pyra->GetPointIds()->SetId(3,3); + pyra->GetPointIds()->SetId(4,4); + pyra->GetPointIds()->SetId(5,5); + pyra->GetPointIds()->SetId(6,6); + pyra->GetPointIds()->SetId(7,7); + pyra->GetPointIds()->SetId(8,8); + pyra->GetPointIds()->SetId(9,9); + pyra->GetPointIds()->SetId(10,10); + pyra->GetPointIds()->SetId(11,11); + pyra->GetPointIds()->SetId(12,12); + + pyra->GetPoints()->SetPoint( 0, 0, 0, 0 ); + pyra->GetPoints()->SetPoint( 1, 1, 0, 0 ); + pyra->GetPoints()->SetPoint( 2, 1, 1, 0 ); + pyra->GetPoints()->SetPoint( 3, 0, 1, 0 ); + pyra->GetPoints()->SetPoint( 4, 0, 0, 1 ); + pyra->GetPoints()->SetPoint( 5, 0.5, 0, 0 ); + pyra->GetPoints()->SetPoint( 6, 1, 0.5, 0 ); + pyra->GetPoints()->SetPoint( 7, 0.5, 1, 0 ); + pyra->GetPoints()->SetPoint( 8, 0, 0.5, 0 ); + pyra->GetPoints()->SetPoint( 9, 0, 0, 0.5 ); + pyra->GetPoints()->SetPoint(10, 0.5, 0, 0.5 ); + pyra->GetPoints()->SetPoint(11, 0.5, 0.5, 0.5 ); + pyra->GetPoints()->SetPoint(12, 0, 0.5, 0.5 ); + + pyra->EvaluatePosition(pyraPoint[0], pyraClosest, subId, pyraPCoords, + dist2, pyraWeights); + + strm << "Test vtkCell::EvaluatePosition End" << endl; + + //------------------------------------------------------------- + strm << "Test vtkCell::EvaluateLocation Start" << endl; + // vtkQuadraticEdge + edge->EvaluateLocation(subId, edgePCoords, edgePosition, edgeWeights); + + // vtkQuadraticTriangle + tri->EvaluateLocation(subId, triPCoords, triPosition, triWeights); + + // vtkQuadraticQuad + quad->EvaluateLocation(subId, quadPCoords, quadPosition, quadWeights); + + // vtkQuadraticTetra + tetra->EvaluateLocation(subId, tetraPCoords, tetraPosition, tetraWeights); + + // vtkQuadraticHexahedron + hexPCoords[0] = 0.25; + hexPCoords[1] = 0.33; + hexPCoords[2] = 0.75; + hex->EvaluateLocation(subId, hexPCoords, hexPosition, hexWeights); + + // vtkQuadraticWedge + wedge->EvaluateLocation(subId, wedgePCoords, wedgePosition, wedgeWeights); + + // vtkQuadraticPyramid + pyra->EvaluateLocation(subId, pyraPCoords, pyraPosition, pyraWeights); + + strm << "Test vtkCell::EvaluateLocation End" << endl; + + //------------------------------------------------------------- + strm << "Test vtkCell::CellDerivs Start" << endl; + + // vtkQuadraticEdge - temporarily commented out +// double edgeValues[3], edgeDerivs[3]; +// ComputeDataValues(edge->Points,edgeValues); +// edge->Derivatives(subId, edgePCoords, edgeValues, 1, edgeDerivs); + + // vtkQuadraticTriangle + double triValues[6], triDerivs[3]; + ComputeDataValues(tri->Points,triValues); + tri->Derivatives(subId, triPCoords, triValues, 1, triDerivs); + + // vtkQuadraticQuad + double quadValues[8], quadDerivs[3]; + ComputeDataValues(quad->Points,quadValues); + quad->Derivatives(subId, quadPCoords, quadValues, 1, quadDerivs); + + // vtkQuadraticTetra + double tetraValues[10], tetraDerivs[3]; + ComputeDataValues(tetra->Points,tetraValues); + tetra->Derivatives(subId, tetraPCoords, tetraValues, 1, tetraDerivs); + + // vtkQuadraticHexahedron + double hexValues[20], hexDerivs[3]; + ComputeDataValues(hex->Points,hexValues); + hex->Derivatives(subId, hexPCoords, hexValues, 1, hexDerivs); + + // vtkQuadraticWedge + double wedgeValues[15], wedgeDerivs[3]; + ComputeDataValues(wedge->Points,wedgeValues); + wedge->Derivatives(subId, wedgePCoords, wedgeValues, 1, wedgeDerivs); + + // vtkQuadraticPyramid + double pyraValues[13], pyraDerivs[3]; + ComputeDataValues(pyra->Points,pyraValues); + pyra->Derivatives(subId, pyraPCoords, pyraValues, 1, pyraDerivs); + + strm << "Test vtkCell::CellDerivs End" << endl; + + edge->Delete(); + tri->Delete(); + quad->Delete(); + tetra->Delete(); + hex->Delete(); + wedge->Delete(); + pyra->Delete(); + + return 0; +} + +int quadraticEvaluation(int,char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return TestQE(vtkmsg_with_warning_C4701); +} diff --git a/Common/Testing/Cxx/vtkTestDriver.h b/Common/Testing/Cxx/vtkTestDriver.h new file mode 100644 index 0000000..f596e59 --- /dev/null +++ b/Common/Testing/Cxx/vtkTestDriver.h @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestDriver.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This header is included by all the C++ test drivers in VTK. +#ifndef _vtkTestDriver_h +#define _vtkTestDriver_h + +// MSVC 6.0 warns about unused inline functions from and +// . Unfortunately this pragma has to be in effect at the +// end of the translation unit so we cannot push/pop it around the +// include. +#if defined(_MSC_VER) && (_MSC_VER < 1300) +# pragma warning (disable: 4514) /* unreferenced inline function */ + +// Temporary suppression of this warning from CMake generated TestDriver +// code until it can be fixed in the generator... +# pragma warning (disable: 4701) /* local variable 'x' may be used + without having been initialized */ + +#endif + +#include // for vtkstd::exception + +#endif diff --git a/Common/Testing/Cxx/vtkTestUtilities.h b/Common/Testing/Cxx/vtkTestUtilities.h new file mode 100644 index 0000000..354d9a2 --- /dev/null +++ b/Common/Testing/Cxx/vtkTestUtilities.h @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestUtilities.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTestUtilities - Utility functions used for regression testing. +// .SECTION Description +// vtkTestUtilities provides methods to perform common testing operations. +// These include getting a command line argument or an environment variable, +// or a default value. Particularly, there are specialized methods to get the +// root directory for VTK Data, expanding a filename with this root directory. + +#ifndef __vtkTestUtilities_h +#define __vtkTestUtilities_h + +#include "vtkSystemIncludes.h" + +struct vtkTestUtilities +{ + // Description: + // Function necessary for accessing the root directory for VTK data. Try the + // -D command line argument or VTK_DATA_ROOT or a default value. The returned + // string has to be deleted (with delete[]) by the user. + static inline char* GetDataRoot(int argc, char* argv[]); + + // Description: + // Given a file name, this function returns a new string which is (in theory) + // the full path. This path is constructed by prepending the file name with a + // command line argument (-D path) or VTK_DATA_ROOT env. variable. If slash + // is true, appends a slash to the resulting string. The returned string has + // to be deleted (with delete[]) by the user. + static inline char* ExpandDataFileName(int argc, char* argv[], + const char* fname, + int slash = 0); + // Description: + // Function returning either a command line argument, an environment variable + // or a default value. The returned string has to be deleted (with delete[]) + // by the user. + static inline char* GetArgOrEnvOrDefault(const char* arg, + int argc, char* argv[], + const char* env, + const char* def); + + // Description: + // Given a file name, this function returns a new string which is (in theory) + // the full path. This path is constructed by prepending the file name with a + // command line argument, an environment variable or a default value. If + // slash is true, appends a slash to the resulting string. The returned + // string has to be deleted (with delete[]) by the user. + static inline char* ExpandFileNameWithArgOrEnvOrDefault(const char* arg, + int argc, char* argv[], + const char* env, + const char* def, + const char* fname, + int slash = 0); +}; + +inline +char* vtkTestUtilities::GetDataRoot(int argc, char* argv[]) +{ + return vtkTestUtilities::GetArgOrEnvOrDefault( + "-D", argc, argv, + "VTK_DATA_ROOT", + "../../../../VTKData"); +} + +inline +char* vtkTestUtilities::ExpandDataFileName(int argc, char* argv[], + const char* fname, + int slash) +{ + return vtkTestUtilities::ExpandFileNameWithArgOrEnvOrDefault( + "-D", argc, argv, + "VTK_DATA_ROOT", + "../../../../VTKData", + fname, + slash); +} + +inline +char* vtkTestUtilities::GetArgOrEnvOrDefault(const char* arg, + int argc, char* argv[], + const char* env, + const char *def) +{ + int index = -1; + + for (int i = 0; i < argc; i++) + { + if (strcmp(arg, argv[i]) == 0 && i < argc - 1) + { + index = i + 1; + } + } + + char* value; + + if (index != -1) + { + value = new char[strlen(argv[index]) + 1]; + strcpy(value, argv[index]); + } + else + { + char *foundenv = getenv(env); + if (foundenv) + { + value = new char[strlen(foundenv) + 1]; + strcpy(value, foundenv); + } + else + { + value = new char[strlen(def) + 1]; + strcpy(value, def); + } + } + + return value; +} + +inline +char* vtkTestUtilities::ExpandFileNameWithArgOrEnvOrDefault(const char* arg, + int argc, + char* argv[], + const char* env, + const char *def, + const char* fname, + int slash) +{ + char* fullName; + + char* value = vtkTestUtilities::GetArgOrEnvOrDefault(arg, argc, argv, + env, + def); + if (value) + { + fullName = new char[strlen(value) + strlen(fname) + 2 + (slash ? 1 : 0)]; + fullName[0] = 0; + strcat(fullName, value); + int len = static_cast(strlen(fullName)); + fullName[len] = '/'; + fullName[len+1] = 0; + strcat(fullName, fname); + } + else + { + fullName = new char[strlen(fname) + 1 + (slash ? 1 : 0)]; + strcpy(fullName, fname); + } + + if (slash) + { + strcat(fullName, "/"); + } + + delete[] value; + + return fullName; +} + +#endif // __vtkTestUtilities_h diff --git a/Common/Testing/Cxx/vtkTestingColors.h b/Common/Testing/Cxx/vtkTestingColors.h new file mode 100644 index 0000000..74c2238 --- /dev/null +++ b/Common/Testing/Cxx/vtkTestingColors.h @@ -0,0 +1,218 @@ +#ifndef __vtkTestingColors_h +#define __vtkTestingColors_h + +// Standard colors used by many vtk scripts + +static float vtk_antique_white[3] = { 0.9804, 0.9216, 0.8431 }; +static float vtk_azure[3] = { 0.9412, 1.0000, 1.0000 }; +static float vtk_bisque[3] = { 1.0000, 0.8941, 0.7686 }; +static float vtk_blanched_almond[3] = { 1.0000, 0.9216, 0.8039 }; +static float vtk_cornsilk[3] = { 1.0000, 0.9725, 0.8627 }; +static float vtk_eggshell[3] = { 0.9900, 0.9000, 0.7900 }; +static float vtk_floral_white[3] = { 1.0000, 0.9804, 0.9412 }; +static float vtk_gainsboro[3] = { 0.8627, 0.8627, 0.8627 }; +static float vtk_ghost_white[3] = { 0.9725, 0.9725, 1.0000 }; +static float vtk_honeydew[3] = { 0.9412, 1.0000, 0.9412 }; +static float vtk_ivory[3] = { 1.0000, 1.0000, 0.9412 }; +static float vtk_lavender[3] = { 0.9020, 0.9020, 0.9804 }; +static float vtk_lavender_blush[3] = { 1.0000, 0.9412, 0.9608 }; +static float vtk_lemon_chiffon[3] = { 1.0000, 0.9804, 0.8039 }; +static float vtk_linen[3] = { 0.9804, 0.9412, 0.9020 }; +static float vtk_mint_cream[3] = { 0.9608, 1.0000, 0.9804 }; +static float vtk_misty_rose[3] = { 1.0000, 0.8941, 0.8824 }; +static float vtk_moccasin[3] = { 1.0000, 0.8941, 0.7098 }; +static float vtk_navajo_white[3] = { 1.0000, 0.8706, 0.6784 }; +static float vtk_old_lace[3] = { 0.9922, 0.9608, 0.9020 }; +static float vtk_papaya_whip[3] = { 1.0000, 0.9373, 0.8353 }; +static float vtk_peach_puff[3] = { 1.0000, 0.8549, 0.7255 }; +static float vtk_seashell[3] = { 1.0000, 0.9608, 0.9333 }; +static float vtk_snow[3] = { 1.0000, 0.9804, 0.9804 }; +static float vtk_thistle[3] = { 0.8471, 0.7490, 0.8471 }; +static float vtk_titanium_white[3] = { 0.9900, 1.0000, 0.9400 }; +static float vtk_wheat[3] = { 0.9608, 0.8706, 0.7020 }; +static float vtk_white[3] = { 1.0000, 1.0000, 1.0000 }; +static float vtk_white_smoke[3] = { 0.9608, 0.9608, 0.9608 }; +static float vtk_zinc_white[3] = { 0.9900, 0.9700, 1.0000 }; + +// Greys +static float vtk_cold_grey[3] = { 0.5000, 0.5400, 0.5300 }; +static float vtk_dim_grey[3] = { 0.4118, 0.4118, 0.4118 }; +static float vtk_grey[3] = { 0.7529, 0.7529, 0.7529 }; +static float vtk_light_grey[3] = { 0.8275, 0.8275, 0.8275 }; +static float vtk_slate_grey[3] = { 0.4392, 0.5020, 0.5647 }; +static float vtk_slate_grey_dark[3] = { 0.1843, 0.3098, 0.3098 }; +static float vtk_slate_grey_light[3] = { 0.4667, 0.5333, 0.6000 }; +static float vtk_warm_grey[3] = { 0.5000, 0.5000, 0.4100 }; + +// Blacks +static float vtk_black[3] = { 0.0000, 0.0000, 0.0000 }; +static float vtk_ivory_black[3] = { 0.1600, 0.1400, 0.1300 }; +static float vtk_lamp_black[3] = { 0.1800, 0.2800, 0.2300 }; + +// Reds +static float vtk_alizarin_crimson[3] = { 0.8900, 0.1500, 0.2100 }; +static float vtk_brick[3] = { 0.6100, 0.4000, 0.1200 }; +static float vtk_cadmium_red_deep[3] = { 0.8900, 0.0900, 0.0500 }; +static float vtk_coral[3] = { 1.0000, 0.4980, 0.3137 }; +static float vtk_coral_light[3] = { 0.9412, 0.5020, 0.5020 }; +static float vtk_deep_pink[3] = { 1.0000, 0.0784, 0.5765 }; +static float vtk_english_red[3] = { 0.8300, 0.2400, 0.1000 }; +static float vtk_firebrick[3] = { 0.6980, 0.1333, 0.1333 }; +static float vtk_geranium_lake[3] = { 0.8900, 0.0700, 0.1900 }; +static float vtk_hot_pink[3] = { 1.0000, 0.4118, 0.7059 }; +static float vtk_indian_red[3] = { 0.6900, 0.0900, 0.1200 }; +static float vtk_light_salmon[3] = { 1.0000, 0.6275, 0.4784 }; +static float vtk_madder_lake_deep[3] = { 0.8900, 0.1800, 0.1900 }; +static float vtk_maroon[3] = { 0.6902, 0.1882, 0.3765 }; +static float vtk_pink[3] = { 1.0000, 0.7529, 0.7961 }; +static float vtk_pink_light[3] = { 1.0000, 0.7137, 0.7569 }; +static float vtk_raspberry[3] = { 0.5300, 0.1500, 0.3400 }; +static float vtk_red[3] = { 1.0000, 0.0000, 0.0000 }; +static float vtk_rose_madder[3] = { 0.8900, 0.2100, 0.2200 }; +static float vtk_salmon[3] = { 0.9804, 0.5020, 0.4471 }; +static float vtk_tomato[3] = { 1.0000, 0.3882, 0.2784 }; +static float vtk_venetian_red[3] = { 0.8300, 0.1000, 0.1200 }; + +// Browns +static float vtk_beige[3] = { 0.6400, 0.5800, 0.5000 }; +static float vtk_brown[3] = { 0.5000, 0.1647, 0.1647 }; +static float vtk_brown_madder[3] = { 0.8600, 0.1600, 0.1600 }; +static float vtk_brown_ochre[3] = { 0.5300, 0.2600, 0.1200 }; +static float vtk_burlywood[3] = { 0.8706, 0.7216, 0.5294 }; +static float vtk_burnt_sienna[3] = { 0.5400, 0.2100, 0.0600 }; +static float vtk_burnt_umber[3] = { 0.5400, 0.2000, 0.1400 }; +static float vtk_chocolate[3] = { 0.8235, 0.4118, 0.1176 }; +static float vtk_deep_ochre[3] = { 0.4500, 0.2400, 0.1000 }; +static float vtk_flesh[3] = { 1.0000, 0.4900, 0.2500 }; +static float vtk_flesh_ochre[3] = { 1.0000, 0.3400, 0.1300 }; +static float vtk_gold_ochre[3] = { 0.7800, 0.4700, 0.1500 }; +static float vtk_greenish_umber[3] = { 1.0000, 0.2400, 0.0500 }; +static float vtk_khaki[3] = { 0.9412, 0.9020, 0.5490 }; +static float vtk_khaki_dark[3] = { 0.7412, 0.7176, 0.4196 }; +static float vtk_light_beige[3] = { 0.9608, 0.9608, 0.8627 }; +static float vtk_peru[3] = { 0.8039, 0.5216, 0.2471 }; +static float vtk_rosy_brown[3] = { 0.7373, 0.5608, 0.5608 }; +static float vtk_raw_sienna[3] = { 0.7800, 0.3800, 0.0800 }; +static float vtk_raw_umber[3] = { 0.4500, 0.2900, 0.0700 }; +static float vtk_sepia[3] = { 0.3700, 0.1500, 0.0700 }; +static float vtk_sienna[3] = { 0.6275, 0.3216, 0.1765 }; +static float vtk_saddle_brown[3] = { 0.5451, 0.2706, 0.0745 }; +static float vtk_sandy_brown[3] = { 0.9569, 0.6431, 0.3765 }; +static float vtk_tan[3] = { 0.8235, 0.7059, 0.5490 }; +static float vtk_van_dyke_brown[3] = { 0.3700, 0.1500, 0.0200 }; + +// Oranges +static float vtk_cadmium_orange[3] = { 1.0000, 0.3800, 0.0100 }; +static float vtk_cadmium_red_light[3] = { 1.0000, 0.0100, 0.0500 }; +static float vtk_carrot[3] = { 0.9300, 0.5700, 0.1300 }; +static float vtk_dark_orange[3] = { 1.0000, 0.5490, 0.0000 }; +static float vtk_mars_orange[3] = { 0.5900, 0.2700, 0.0800 }; +static float vtk_mars_yellow[3] = { 0.8900, 0.4400, 0.1000 }; +static float vtk_orange[3] = { 1.0000, 0.5000, 0.0000 }; +static float vtk_orange_red[3] = { 1.0000, 0.2706, 0.0000 }; +static float vtk_yellow_ochre[3] = { 0.8900, 0.5100, 0.0900 }; + +// Yellows +static float vtk_aureoline_yellow[3] = { 1.0000, 0.6600, 0.1400 }; +static float vtk_banana[3] = { 0.8900, 0.8100, 0.3400 }; +static float vtk_cadmium_lemon[3] = { 1.0000, 0.8900, 0.0100 }; +static float vtk_cadmium_yellow[3] = { 1.0000, 0.6000, 0.0700 }; +static float vtk_cadmium_yellow_light[3] = { 1.0000, 0.6900, 0.0600 }; +static float vtk_gold[3] = { 1.0000, 0.8431, 0.0000 }; +static float vtk_goldenrod[3] = { 0.8549, 0.6471, 0.1255 }; +static float vtk_goldenrod_dark[3] = { 0.7216, 0.5255, 0.0431 }; +static float vtk_goldenrod_light[3] = { 0.9804, 0.9804, 0.8235 }; +static float vtk_goldenrod_pale[3] = { 0.9333, 0.9098, 0.6667 }; +static float vtk_light_goldenrod[3] = { 0.9333, 0.8667, 0.5098 }; +static float vtk_melon[3] = { 0.8900, 0.6600, 0.4100 }; +static float vtk_naples_yellow_deep[3] = { 1.0000, 0.6600, 0.0700 }; +static float vtk_yellow[3] = { 1.0000, 1.0000, 0.0000 }; +static float vtk_yellow_light[3] = { 1.0000, 1.0000, 0.8784 }; + +// Greens +static float vtk_chartreuse[3] = { 0.4980, 1.0000, 0.0000 }; +static float vtk_chrome_oxide_green[3] = { 0.4000, 0.5000, 0.0800 }; +static float vtk_cinnabar_green[3] = { 0.3800, 0.7000, 0.1600 }; +static float vtk_cobalt_green[3] = { 0.2400, 0.5700, 0.2500 }; +static float vtk_emerald_green[3] = { 0.0000, 0.7900, 0.3400 }; +static float vtk_forest_green[3] = { 0.1333, 0.5451, 0.1333 }; +static float vtk_green[3] = { 0.0000, 1.0000, 0.0000 }; +static float vtk_green_dark[3] = { 0.0000, 0.3922, 0.0000 }; +static float vtk_green_pale[3] = { 0.5961, 0.9843, 0.5961 }; +static float vtk_green_yellow[3] = { 0.6784, 1.0000, 0.1843 }; +static float vtk_lawn_green[3] = { 0.4863, 0.9882, 0.0000 }; +static float vtk_lime_green[3] = { 0.1961, 0.8039, 0.1961 }; +static float vtk_mint[3] = { 0.7400, 0.9900, 0.7900 }; +static float vtk_olive[3] = { 0.2300, 0.3700, 0.1700 }; +static float vtk_olive_drab[3] = { 0.4196, 0.5569, 0.1373 }; +static float vtk_olive_green_dark[3] = { 0.3333, 0.4196, 0.1843 }; +static float vtk_permanent_green[3] = { 0.0400, 0.7900, 0.1700 }; +static float vtk_sap_green[3] = { 0.1900, 0.5000, 0.0800 }; +static float vtk_sea_green[3] = { 0.1804, 0.5451, 0.3412 }; +static float vtk_sea_green_dark[3] = { 0.5608, 0.7373, 0.5608 }; +static float vtk_sea_green_medium[3] = { 0.2353, 0.7020, 0.4431 }; +static float vtk_sea_green_light[3] = { 0.1255, 0.6980, 0.6667 }; +static float vtk_spring_green[3] = { 0.0000, 1.0000, 0.4980 }; +static float vtk_spring_green_medium[3] = { 0.0000, 0.9804, 0.6039 }; +static float vtk_terre_verte[3] = { 0.2200, 0.3700, 0.0600 }; +static float vtk_viridian_light[3] = { 0.4300, 1.0000, 0.4400 }; +static float vtk_yellow_green[3] = { 0.6039, 0.8039, 0.1961 }; + +// Cyans +static float vtk_aquamarine[3] = { 0.4980, 1.0000, 0.8314 }; +static float vtk_aquamarine_medium[3] = { 0.4000, 0.8039, 0.6667 }; +static float vtk_cyan[3] = { 0.0000, 1.0000, 1.0000 }; +static float vtk_cyan_white[3] = { 0.8784, 1.0000, 1.0000 }; +static float vtk_turquoise[3] = { 0.2510, 0.8784, 0.8157 }; +static float vtk_turquoise_dark[3] = { 0.0000, 0.8078, 0.8196 }; +static float vtk_turquoise_medium[3] = { 0.2824, 0.8196, 0.8000 }; +static float vtk_turquoise_pale[3] = { 0.6863, 0.9333, 0.9333 }; + +// Blues +static float vtk_alice_blue[3] = { 0.9412, 0.9725, 1.0000 }; +static float vtk_blue[3] = { 0.0000, 0.0000, 1.0000 }; +static float vtk_blue_light[3] = { 0.6784, 0.8471, 0.9020 }; +static float vtk_blue_medium[3] = { 0.0000, 0.0000, 0.8039 }; +static float vtk_cadet[3] = { 0.3725, 0.6196, 0.6275 }; +static float vtk_cobalt[3] = { 0.2400, 0.3500, 0.6700 }; +static float vtk_cornflower[3] = { 0.3922, 0.5843, 0.9294 }; +static float vtk_cerulean[3] = { 0.0200, 0.7200, 0.8000 }; +static float vtk_dodger_blue[3] = { 0.1176, 0.5647, 1.0000 }; +static float vtk_indigo[3] = { 0.0300, 0.1800, 0.3300 }; +static float vtk_manganese_blue[3] = { 0.0100, 0.6600, 0.6200 }; +static float vtk_midnight_blue[3] = { 0.0980, 0.0980, 0.4392 }; +static float vtk_navy[3] = { 0.0000, 0.0000, 0.5020 }; +static float vtk_peacock[3] = { 0.2000, 0.6300, 0.7900 }; +static float vtk_powder_blue[3] = { 0.6902, 0.8784, 0.9020 }; +static float vtk_royal_blue[3] = { 0.2549, 0.4118, 0.8824 }; +static float vtk_slate_blue[3] = { 0.4157, 0.3529, 0.8039 }; +static float vtk_slate_blue_dark[3] = { 0.2824, 0.2392, 0.5451 }; +static float vtk_slate_blue_light[3] = { 0.5176, 0.4392, 1.0000 }; +static float vtk_slate_blue_medium[3] = { 0.4824, 0.4078, 0.9333 }; +static float vtk_sky_blue[3] = { 0.5294, 0.8078, 0.9216 }; +static float vtk_sky_blue_deep[3] = { 0.0000, 0.7490, 1.0000 }; +static float vtk_sky_blue_light[3] = { 0.5294, 0.8078, 0.9804 }; +static float vtk_steel_blue[3] = { 0.2745, 0.5098, 0.7059 }; +static float vtk_steel_blue_light[3] = { 0.6902, 0.7686, 0.8706 }; +static float vtk_turquoise_blue[3] = { 0.0000, 0.7800, 0.5500 }; +static float vtk_ultramarine[3] = { 0.0700, 0.0400, 0.5600 }; + +// Magentas +static float vtk_blue_violet[3] = { 0.5412, 0.1686, 0.8863 }; +static float vtk_cobalt_violet_deep[3] = { 0.5700, 0.1300, 0.6200 }; +static float vtk_magenta[3] = { 1.0000, 0.0000, 1.0000 }; +static float vtk_orchid[3] = { 0.8549, 0.4392, 0.8392 }; +static float vtk_orchid_dark[3] = { 0.6000, 0.1961, 0.8000 }; +static float vtk_orchid_medium[3] = { 0.7294, 0.3333, 0.8275 }; +static float vtk_permanent_red_violet[3] = { 0.8600, 0.1500, 0.2700 }; +static float vtk_plum[3] = { 0.8667, 0.6275, 0.8667 }; +static float vtk_purple[3] = { 0.6275, 0.1255, 0.9412 }; +static float vtk_purple_medium[3] = { 0.5765, 0.4392, 0.8588 }; +static float vtk_ultramarine_violet[3] = { 0.3600, 0.1400, 0.4300 }; +static float vtk_violet[3] = { 0.5600, 0.3700, 0.6000 }; +static float vtk_violet_dark[3] = { 0.5804, 0.0000, 0.8275 }; +static float vtk_violet_red[3] = { 0.8157, 0.1255, 0.5647 }; +static float vtk_violet_red_medium[3] = { 0.7804, 0.0824, 0.5216 }; +static float vtk_violet_red_pale[3] = { 0.8588, 0.4392, 0.5765 }; + +#endif // __vtkTestingColors_h diff --git a/Common/Testing/HeaderTesting.py b/Common/Testing/HeaderTesting.py new file mode 100644 index 0000000..570cdde --- /dev/null +++ b/Common/Testing/HeaderTesting.py @@ -0,0 +1,453 @@ +#!/usr/bin/env python + +## /*========================================================================= + +## Program: Visualization Toolkit +## Module: $RCSfile: HeaderTesting.py,v $ + +## Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +## All rights reserved. +## See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +## This software is distributed WITHOUT ANY WARRANTY; without even +## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the above copyright notice for more information. + +## =========================================================================*/ +## .NAME HeaderTesting - a VTK style and validity checking utility +## .SECTION Description +## HeaderTesting is a script which checks the list of header files for +## validity based on VTK coding standard. It checks for proper super +## classes, number and style of include files, type macro, private +## copy constructor and assignment operator, broken constructors, and +## exsistence of PrintSelf method. This script should be run as a part +## of the dashboard checking of the Visualization Toolkit and related +## projects. + +## .SECTION See Also +## http://www.vtk.org http://public.kitware.com/Dart/HTML/Index.shtml +## http://www.vtk.org/contribute.php#coding-standards + +import sys +import re +import os +import stat +import string + +# Get the path to the directory containing this script. +if __name__ == '__main__': + selfpath = os.path.abspath(sys.path[0] or os.curdir) +else: + selfpath = os.path.abspath(os.path.dirname(__file__)) + +# Load the list of names mangled by windows.h. +execfile(os.path.join(selfpath, 'WindowsMangleList.py')) + +## If tested from dart, make sure to fix all the output strings +test_from_dart = 0 +if os.environ.has_key("DART_TEST_FROM_DART"): + test_from_dart = 1 + +## For backward compatibility +def StringEndsWith(str1, str2): + l1 = len(str1) + l2 = len(str2) + if l1 < l2: + return 0 + return (str1[(l1-l2):] == str2) + +## +class TestVTKFiles: + def __init__(self): + self.FileName = "" + self.ErrorValue = 0; + self.Errors = {} + self.WarningValue = 0; + self.Warnings = {} + self.FileLines = [] + self.Export = "" + self.UnnecessaryIncludes = [ + "stdio.h", + "stdlib.h", + "string.h", + "iostream", + "iostream.h", + "strstream", + "strstream.h", + "fstream", + "fstream.h", + "windows.h" + ] + pass + def SetExport(self, export): + self.Export = export + def Print(self, text=""): + rtext = text + if test_from_dart: + rtext = string.replace(rtext, "<", "<") + rtext = string.replace(rtext, ">", ">") + print rtext + def Error(self, error): + self.ErrorValue = 1 + self.Errors[error] = 1 + pass + def Warning(self, warning): + self.WarningValue = 1 + self.Warnings[warning] = 1 + pass + def PrintErrors(self): + if self.ErrorValue: + self.Print( ) + self.Print( "There were errors:" ) + for a in self.Errors.keys(): + self.Print( "* %s" % a ) + def PrintWarnings(self): + if self.WarningValue: + self.Print( ) + self.Print( "There were warnings:" ) + for a in self.Warnings.keys(): + self.Print( "* %s" % a ) + + def TestFile(self, filename): + self.FileName = filename + self.FileLines = [] + self.ClassName = "" + self.ParentName = "" + try: + file = open(filename) + self.FileLines = file.readlines() + file.close() + except: + self.Print( "Problem reading file: %s" % filename ) + sys.exit(1) + pass + + def CheckIncludes(self): + count = 0 + lines = [] + nplines = [] + unlines = [] + includere = "^\s*#\s*include\s*[\"<]([^>\"]+)" + ignincludere = ".*\/\/.*" + regx = re.compile(includere) + regx1 = re.compile(ignincludere) + cc = 0 + includeparent = 0 + for a in self.FileLines: + line = string.strip(a) + rm = regx.match(line) + if rm and not regx1.match(line): + lines.append(" %4d: %s" % (cc, line)) + file = rm.group(1) + if file == (self.ParentName + ".h"): + includeparent = 1 + if not StringEndsWith(file, ".h"): + nplines.append(" %4d: %s" % (cc, line)) + if file in self.UnnecessaryIncludes: + unlines.append(" %4d: %s" % (cc, line)) + cc = cc + 1 + if len(lines) > 1: + self.Print() + self.Print( "File: %s has %d includes: " % + ( self.FileName, len(lines)) ) + for a in lines: + self.Print( a ) + self.Error("Multiple includes") + if len(nplines) > 0: + self.Print( ) + self.Print( "File: %s has non-portable include(s): " % self.FileName ) + for a in nplines: + self.Print( a ) + self.Error("Non-portable includes") + if len(unlines) > 0: + self.Print( ) + self.Print( "File: %s has unnecessary include(s): " % self.FileName ) + for a in unlines: + self.Print( a ) + self.Error("Unnecessary includes") + if not includeparent and self.ParentName: + self.Print() + self.Print( "File: %s does not include parent \"%s.h\"" % + ( self.FileName, self.ParentName ) ) + self.Error("Does not include parent") + pass + + def CheckParent(self): + classre = "^class\s*(.*_EXPORT|\s*) (vtk[A-Z0-9_][^ :\n]*)\s*:\s*public\s*(vtk[^ \n\{]*)" + cname = "" + pname = "" + classlines = [] + regx = re.compile(classre) + cc = 0 + lastline = "" + for a in self.FileLines: + line = string.strip(a) + rm = regx.match(line) + if not rm and not cname: + rm = regx.match(lastline + line) + if rm: + export = rm.group(1) + export = string.strip(export) + cname = rm.group(2) + pname = rm.group(3) + classlines.append(" %4d: %s" % (cc, line)) + if not export: + self.Print("File: %s defines 1 class with no export macro:" % self.FileName) + self.Print(" %4d: %s" % (cc, line)) + self.Error("No export macro") + elif self.Export and self.Export != export: + self.Print("File: %s defines 1 class with wrong export macro:" % self.FileName) + self.Print(" %4d: %s" % (cc, line)) + self.Print(" The export macro should be: %s" % (self.Export)) + self.Error("Wrong export macro") + cc = cc + 1 + lastline = a + if len(classlines) > 1: + self.Print() + self.Print( "File: %s defines %d classes: " % + (self.FileName, len(classlines)) ) + for a in classlines: + self.Print( a ) + self.Error("Multiple classes defined") + if len(classlines) < 1: + self.Print() + self.Print( "File: %s does not define any classes" % self.FileName ) + self.Error("No class defined") + return + #self.Print( "Classname: %s ParentName: %s" % (cname, pname) + self.ClassName = cname + self.ParentName = pname + pass + def CheckTypeMacro(self): + count = 0 + lines = [] + oldlines = [] + typere = "^\s*vtkType(Revision)*Macro\s*\(\s*(vtk[^ ,]+)\s*,\s*(vtk[^ \)]+)\s*\)\s*;" + typesplitre = "^\s*vtkType(Revision)*Macro\s*\(" + + regx = re.compile(typere) + regxs = re.compile(typesplitre) + cc = 0 + found = 0 + for a in range(len(self.FileLines)): + line = string.strip(self.FileLines[a]) + rm = regx.match(line) + if rm: + found = 1 + if rm.group(1) != "Revision": + oldlines.append(" %4d: %s" % (cc, line)) + cname = rm.group(2) + pname = rm.group(3) + if cname != self.ClassName or pname != self.ParentName: + lines.append(" %4d: %s" % (cc, line)) + else: + # Maybe it is in two lines + rm = regxs.match(line) + if rm: + nline = line + " " + string.strip(self.FileLines[a+1]) + line = string.strip(nline) + rm = regx.match(line) + if rm: + found = 1 + if rm.group(1) != "Revision": + oldlines.append(" %4d: %s" % (cc, line)) + cname = rm.group(2) + pname = rm.group(3) + if cname != self.ClassName or pname != self.ParentName: + lines.append(" %4d: %s" % (cc, line)) + cc = cc + 1 + if len(lines) > 0: + self.Print( "File: %s has broken type macro(s):" % self.FileName ) + for a in lines: + self.Print( a ) + self.Print( "Should be:\n vtkTypeRevisionMacro(%s, %s)" % + (self.ClassName, self.ParentName) ) + self.Error("Broken type macro") + if len(oldlines) > 0: + self.Print( "File: %s has old type macro(s):" % self.FileName ) + for a in oldlines: + self.Print( a ) + self.Print( "Should be:\n vtkTypeRevisionMacro(%s, %s);" % + (self.ClassName, self.ParentName)) + self.Error("Old style type macro") + if not found: + self.Print( "File: %s does not have type macro" % self.FileName ) + self.Print( "Should be:\n vtkTypeRevisionMacro(%s, %s);" % + (self.ClassName, self.ParentName)) + self.Error("No type macro") + pass + def CheckForCopyAndAssignment(self): + if not self.ClassName: + return + count = 0 + lines = [] + oldlines = [] + copyoperator = "^\s*%s\s*\(\s*const\s*%s\s*&\s*\)\s*;\s*\/\/\s*Not\s*[iI]mplemented(\.)*" % ( self.ClassName, self.ClassName) + asgnoperator = "^\s*void\s*operator\s*=\s*\(\s*const\s*%s\s*&\s*\)\s*;\s*\/\/\s*Not\s*[iI]mplemented(\.)*" % self.ClassName + #self.Print( copyoperator + regx1 = re.compile(copyoperator) + regx2 = re.compile(asgnoperator) + foundcopy = 0 + foundasgn = 0 + for a in self.FileLines: + line = string.strip(a) + if regx1.match(line): + foundcopy = foundcopy + 1 + if regx2.match(line): + foundasgn = foundasgn + 1 + lastline = "" + if foundcopy < 1: + for a in self.FileLines: + line = string.strip(a) + if regx1.match(lastline + line): + foundcopy = foundcopy + 1 + lastline = a + lastline = "" + if foundasgn < 1: + for a in self.FileLines: + line = string.strip(a) + if regx2.match(lastline + line): + foundasgn = foundasgn + 1 + lastline = a + + if foundcopy < 1: + self.Print( "File: %s does not define copy constructor" % + self.FileName ) + self.Print( "Should be:\n%s(const %s&); // Not implemented" % + (self.ClassName, self.ClassName) ) + self.Error("No private copy constructor") + if foundcopy > 1: + self.Print( "File: %s defines multiple copy constructors" % + self.FileName ) + self.Error("Multiple copy constructor") + if foundasgn < 1: + self.Print( "File: %s does not define assignment operator" % + self.FileName ) + self.Print( "Should be:\nvoid operator=(const %s&); // Not implemented" + % self.ClassName ) + self.Error("No private assignment operator") + if foundcopy > 1: + self.Print( "File: %s defines multiple assignment operators" % + self.FileName ) + self.Error("Multiple assignment operators") + pass + def CheckWeirdConstructors(self): + count = 0 + lines = [] + oldlines = [] + constructor = "^\s*%s\s*\(([^ )]*)\)" % self.ClassName + copyoperator = "^\s*%s\s*\(\s*const\s*%s\s*&\s*\)\s*;\s*\/\/\s*Not\s*implemented(\.)*" % ( self.ClassName, self.ClassName) + regx1 = re.compile(constructor) + regx2 = re.compile(copyoperator) + cc = 0 + for a in self.FileLines: + line = string.strip(a) + rm = regx1.match(line) + if rm: + arg = string.strip(rm.group(1)) + if arg and not regx2.match(line): + lines.append(" %4d: %s" % (cc, line)) + cc = cc + 1 + if len(lines) > 0: + self.Print( "File: %s has weird constructor(s):" % self.FileName ) + for a in lines: + self.Print( a ) + self.Print( "There should be only:\n %s();" % self.ClassName ) + self.Error("Weird constructor") + pass + + def CheckPrintSelf(self): + if not self.ClassName: + return + typere = "^\s*void\s*PrintSelf\s*\(\s*ostream\s*&\s*os*\s*,\s*vtkIndent\s*indent\s*\)" + newtypere = "^\s*virtual\s*void\s*PrintSelf\s*\(\s*ostream\s*&\s*os*\s*,\s*vtkIndent\s*indent\s*\)" + regx1 = re.compile(typere) + regx2 = re.compile(newtypere) + found = 0 + oldstyle = 0 + for a in self.FileLines: + line = string.strip(a) + rm1 = regx1.match(line) + rm2 = regx2.match(line) + if rm1 or rm2: + found = 1 + if rm1: + oldstyle = 1 + if not found: + self.Print( "File: %s does not define PrintSelf method:" % + self.FileName ) + self.Warning("No PrintSelf method") + pass + + def CheckWindowsMangling(self): + lines = [] + regx1 = WindowsMangleRegEx + regx2 = re.compile("^.*VTK_LEGACY.*$") + # This version will leave out comment lines but we probably do + # not want to refer to mangled (hopefully deprecated) methods + # in comments. + # regx2 = re.compile("^(\s*//|\s*\*|.*VTK_LEGACY).*$") + cc = 1 + for a in self.FileLines: + line = string.strip(a) + rm = regx1.match(line) + if rm: + arg = string.strip(rm.group(1)) + if arg and not regx2.match(line): + lines.append(" %4d: %s" % (cc, line)) + cc = cc + 1 + if len(lines) > 0: + self.Print( "File: %s has windows.h mangling violations:" % self.FileName ) + for a in lines: + self.Print(a) + self.Error("Windows Mangling Violation") + pass + +## +test = TestVTKFiles() + +## Check command line arguments +if len(sys.argv) < 2: + print "Testing directory not specified..." + print "Usage: %s [ exception(s) ]" % sys.argv[0] + sys.exit(1) + +dirname = sys.argv[1] +exceptions = sys.argv[2:] +if len(sys.argv) > 2: + export = sys.argv[2] + if export[:3] == "VTK" and export[len(export)-len("EXPORT"):] == "EXPORT": + print "Use export macro: %s" % export + exceptions = sys.argv[3:] + test.SetExport(export) + +## Traverse through the list of files +for a in os.listdir(dirname): + ## Skip non-header files + if not StringEndsWith(a, ".h"): + continue + ## Skip exceptions + if a in exceptions: + continue + pathname = '%s/%s' % (dirname, a) + if pathname in exceptions: + continue + mode = os.stat(pathname)[stat.ST_MODE] + ## Skip directories + if stat.S_ISDIR(mode): + continue + elif stat.S_ISREG(mode): + ## Do all the tests + test.TestFile(pathname) + test.CheckParent() + test.CheckIncludes() + test.CheckTypeMacro() + test.CheckForCopyAndAssignment() + test.CheckWeirdConstructors() + test.CheckPrintSelf() + test.CheckWindowsMangling() + +## Summarize errors +test.PrintWarnings() +test.PrintErrors() +sys.exit(test.ErrorValue) diff --git a/Common/Testing/Install/CMakeLists.txt b/Common/Testing/Install/CMakeLists.txt new file mode 100644 index 0000000..9991c1e --- /dev/null +++ b/Common/Testing/Install/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT(VIT) + +INCLUDE(${CMAKE_ROOT}/Modules/FindVTK.cmake) +IF(VTK_FOUND) + INCLUDE("${VTK_USE_FILE}") + ADD_EXECUTABLE(vit vit.cxx) + TARGET_LINK_LIBRARIES(vit vtkGraphics) +ELSE(VTK_FOUND) + MESSAGE(SEND_ERROR "VTK not found!") +ENDIF(VTK_FOUND) diff --git a/Common/Testing/Install/test.sh.in b/Common/Testing/Install/test.sh.in new file mode 100644 index 0000000..09d7b94 --- /dev/null +++ b/Common/Testing/Install/test.sh.in @@ -0,0 +1,88 @@ +#!/bin/sh + +CMAKE_COMMAND="@CMAKE_COMMAND@" +VTK_SOURCE_DIR="@VTK_SOURCE_DIR@" +VTK_BINARY_DIR="@VTK_BINARY_DIR@" +CMAKE_INSTALL_PREFIX="@CMAKE_INSTALL_PREFIX@" +CMAKE_MAKE_PROGRAM="@CMAKE_MAKE_PROGRAM@" +VTK_INSTALL_LIB_DIR="@VTK_INSTALL_LIB_DIR@" + +SOURCE_DIR="${VTK_SOURCE_DIR}/Common/Testing/Install" +BINARY_DIR="${VTK_BINARY_DIR}/Common/Testing/Install" + +trap cleanup 1 2 3 6 + +cleanup() +{ + ( + cd "${VTK_BINARY_DIR}" + if [ -d "bin-InstallTestTemp" ]; then + mv "bin-InstallTestTemp" "bin" + fi + ) + exit 1 +} + +install() +{ + echo "Erasing ${CMAKE_INSTALL_PREFIX}" && + ([ ! -d "${CMAKE_INSTALL_PREFIX}" ] || rm -rf "${CMAKE_INSTALL_PREFIX}") && + mkdir -p "${CMAKE_INSTALL_PREFIX}" && + echo "Running make install" && + ( + cd "${VTK_BINARY_DIR}" && + "${CMAKE_MAKE_PROGRAM}" install + ) +} + +setup() +{ + echo "Entering ${BINARY_DIR}" && + cd "${BINARY_DIR}" +} + +write_cache() +{ + install || return 1 + setup || return 1 + echo "Writing CMakeCache.txt" + ( + cat > CMakeCache.txt <Delete(); + vtkDoubleArray::New()->Delete(); + return 0; +} diff --git a/Common/Testing/Python/CMakeLists.txt b/Common/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..02b7313 --- /dev/null +++ b/Common/Testing/Python/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Add tests, with the data +# +IF (VTK_PYTHON_EXE) + FOREACH ( tfile + PythonSmoke + TestWeakref + ) + ADD_TEST(${tfile}Python-image ${VTK_PYTHON_EXE} + ${VTK_SOURCE_DIR}/Common/Testing/Python/${tfile}.py) + ENDFOREACH( tfile ) +ENDIF (VTK_PYTHON_EXE) diff --git a/Common/Testing/Python/PythonSmoke.py b/Common/Testing/Python/PythonSmoke.py new file mode 100644 index 0000000..ed840d8 --- /dev/null +++ b/Common/Testing/Python/PythonSmoke.py @@ -0,0 +1,47 @@ +import sys + +try: + import vtk + +except: + print "Cannot import vtk" + sys.exit(1) +try: + print dir(vtk) +except: + print "Cannot print dir(vtk)" + sys.exit(1) + +try: + try: + try: + o = vtk.vtkLineWidget() + print "Using Hybrid" + except: + o = vtk.vtkActor() + print "Using Rendering" + except: + o = vtk.vtkObject() + print "Using Common" +except: + print "Cannot create vtkObject" + sys.exit(1) + +try: + print o + print "Reference count: %d" % o.GetReferenceCount() + print "Class name: %s" % o.GetClassName() +except: + print "Cannot print object" + sys.exit(1) + +try: + b = vtk.vtkObject() + d = b.SafeDownCast(o) + print b, d +except: + print "Cannot downcast" + sys.exit(1) + +sys.exit(0) + diff --git a/Common/Testing/Python/TestWeakref.py b/Common/Testing/Python/TestWeakref.py new file mode 100644 index 0000000..3a3b965 --- /dev/null +++ b/Common/Testing/Python/TestWeakref.py @@ -0,0 +1,42 @@ +"""Test if VTK-Python objects support weak referencing. + +Run this test like so: + $ vtkpython TestWeakref.py +or + $ python TestWeakref.py + +Created on July, 8 2005 +Prabhu Ramachandran + +""" + +import sys +import vtk +from vtk.test import Testing +try: + import weakref +except ImportError: + print "No weakref in this version of Python. Time to upgrade?" + print "Python version:", sys.version + sys.exit(0) + + +class TestWeakref(Testing.vtkTest): + def testWeakref(self): + o = vtk.vtkObject() + ref = weakref.ref(o) + self.assertEqual(ref().GetClassName(), 'vtkObject') + del o + self.assertEqual(ref(), None) + + def testProxy(self): + o = vtk.vtkObject() + proxy = weakref.proxy(o) + self.assertEqual(proxy.GetClassName(), 'vtkObject') + del o + self.assertRaises(weakref.ReferenceError, getattr, + proxy, 'GetClassName') + + +if __name__ == "__main__": + Testing.main([(TestWeakref, 'test')]) diff --git a/Common/Testing/Tcl/CMakeLists.txt b/Common/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..13679c2 --- /dev/null +++ b/Common/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,26 @@ +ADD_TEST(otherInterp ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/otherInterp.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) +ADD_TEST(otherPrint ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/otherPrint.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) +ADD_TEST(TestEmptyInput ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/TestEmptyInput.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) +ADD_TEST(TestSetGet ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/TestSetGet.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) +ADD_TEST(TestArrays ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/TestArrays.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) +ADD_TEST(TestAmoebaMinimizer ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/TestAmoebaMinimizer.tcl) +ADD_TEST(PrintSelf-Common ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Common) +ADD_TEST(TestSetObjectMacro-Common ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Common/vtk\\\\*.h" + "vtkSetObjectMacro" + ${VTK_SOURCE_DIR}/Common/vtkSetGet.h + ) diff --git a/Common/Testing/Tcl/FindString.tcl b/Common/Testing/Tcl/FindString.tcl new file mode 100644 index 0000000..a60feb9 --- /dev/null +++ b/Common/Testing/Tcl/FindString.tcl @@ -0,0 +1,87 @@ +#!/usr/bin/tclsh + +# This script will find all files that include certain regular expression. +# If the files are not in the list provided, the script will return error. + +set ProgName [ lindex [ split $argv0 "/" ] end ] + +if { $argc < 2 } { + puts "Usage: $ProgName \[ ... \]" + puts "\texpr1 - file list expression (vtk*.h)" + puts "\texpr2 - search string expression (vtkSet.*Macro)" + puts "\tfile - files that should be ignore" + + puts "" + puts "You provided:" + foreach { a } $argv { + puts "$a" + } + + exit 1 +} + +# Parse command line arguments +set FileExpression [ lindex $argv 0 ] +set SearchMessage [ lindex $argv 1 ] +set IgnoreFileListIn [ lrange $argv 2 end ] +set IgnoreFileList {} +foreach { file } $IgnoreFileListIn { + set IgnoreFileList "$IgnoreFileList [ glob $file ]" +} +#puts "Searching for $SearchMessage in $FileExpression" +#puts "Ignore list: $IgnoreFileList" + +# Find regular expression in the string +proc FindString { InFile SearchString } { + if [ catch { open $InFile r } inchan ] { + puts stderr "Cannot open $InFile" + return 0 + } + set res 0 + set lcount 1 + while { ! [eof $inchan] } { + gets $inchan line + if [ regexp $SearchString $line matches ] { + puts "$InFile: Found $SearchString on line $lcount" + puts "$line" + set res 1 + } + set lcount [ expr $lcount + 1 ] + } + close $inchan + return $res +} + +# Get all files that match expression +set files "" +if [ catch { [ set files [ glob $FileExpression ] ] } result ] { + regsub {\\\*} $FileExpression "*" FileExpression + if [ catch { [ set files [ glob $FileExpression ] ] } nresult ] { + #puts "Cannot expand the expression: \"$FileExpression\"" + #puts "Error: $nresult" + #exit 1 + } +} + +if { [ llength $files ] < 1 } { + puts "Cannot find any files that match your file expression" + exit 0 +} + +set count 0 +foreach { a } $files { + regsub -all {\\} $a {/} b + if { [ lsearch $IgnoreFileList $b ] >= 0 } { + puts "Ignoring: $b" + } else { + set count [ expr $count + [ FindString $a $SearchMessage ] ] + } +} + +if { $count > 0 } { + puts "" + puts "Found \"$SearchMessage\" $count times" + exit 1 +} + +exit 0 diff --git a/Common/Testing/Tcl/PrintSelfCheck.tcl b/Common/Testing/Tcl/PrintSelfCheck.tcl new file mode 100644 index 0000000..3a57ea8 --- /dev/null +++ b/Common/Testing/Tcl/PrintSelfCheck.tcl @@ -0,0 +1,720 @@ +# +# Verify that each class's PrintSelf prints all ivars that have +# a set/get. +# +# +# Verbose Levels: +# +# 0: No extra printing +# 1: Print basic extra information +# 2: Print lots of details +# +set verbose 0 + +set class_name "" + +set class_count 0 +set class_print_count 0 +set printself_miss_count 0 +set super_miss_count 0 +set ivar_count 0 +set ivar_miss_count 0 + +set total_class_count 0 +set total_class_print_count 0 +set total_ivar_count 0 +set total_printself_miss_count 0 +set total_super_miss_count 0 +set total_ivar_miss_count 0 + +# Fileid for the PrintSelfDetails.html file +set pd_id 0 + +# +# class_list contains the following for each class evaluated: +# +# .p True if printself declared +# .s. True if superclass used in printself +# .i. True if ivar used in printself + +set class_list(null) 1 + +proc list_contains { string } { + + global class_list + + set ivar_found 0 + + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + + set element [array nextelement class_list $searchid] + + if { $element == $string } { + + set ivar_found 1 + } + } + + array donesearch class_list $searchid + + return $ivar_found +} + +proc get_ivar { string } { + + global verbose + + set ivar_string "-1" + +#puts "Getting ivar from macro: $string" + + # Search for the first occurrence of an open parenthesis + set first [string first "(" $string]; + + if { $first > -1 } { + + set begintrim [string range $string [expr $first + 1] end]; + set begintrim [string trim $begintrim]; + + # Find the end of the ivar + set last [string wordend $begintrim 0] + + if { $last > -1 } { + + set ivar_string [string range $begintrim 0 [expr $last - 1] ]; + + set ivar_string [string trim $ivar_string]; + + if { $verbose >= 2 } { + puts " Macro: $ivar_string" + } + } + } + + return [string trim $ivar_string] +} + +proc check_header_file { filename } { + + global class_name + global class_count + global ivar_count + global class_list + global verbose + + if { $verbose >= 2 } { + puts "Processing file: $filename" + } + + set data "" + set class_name "" + + set printself_found 0 + set class_found 0 + + if { [file readable $filename] } { + set fileid [open $filename "r"] + + set protected_not_found 1 + + # + # Read each line in the file + # + while { [gets $fileid data] >= 0 && $protected_not_found } { + # Search for the printSelf string + if { [string match "*PrintSelf*(*" $data] == 1 } { + + set printself_found 1 + + set class_list($class_name.p) 1 + } + + if { [string match "*protected:*" $data] == 1 } { + set protected_not_found 0 + } + + # Search for the class string + # Extract the class name from the string + if { [string match "*class VTK_*EXPORT*" $data] == 1 } { + set class_found 1 + + set class_ivar_count 0 + + set first [string first "vtk" $data]; + + if { $first > -1 } { + + set end [expr [string first ":" $data] - 1]; + + set newstring [string range $data $first $end ] + + set last [string wordend $newstring 0]; + + if { $last > -1 } { + set class_name [string trim [string range $newstring 0 $last] ]; + } + + } + set class_list($class_name.p) 0 + + if { $verbose >= 2 } { + puts " Class Name: $class_name" + } + + if { [string compare $class_name ""] == 0 } { + puts "Problem with class definition in file $filename" + } + + set first [string first "public" $data] + + if { $first > -1 } { + set first [expr $first + 7]; + set end [ string length $data] + + set string [string range $data $first $end ] + + set first [string first "vtk" $string] + set end [string wordend $string $first] + + set super_class [string range $string $first $end ] + set super_class [string trim $super_class] + + set class_list($class_name.s.$super_class) 0 + set class_list($class_name.s.Superclass) 0 + } + } + + if { $class_found == 1 } { + + # Search for Set and Get macros + set set_macro_found [string match "*vtkSet*Macro*(*" $data] + set get_macro_found [string match "*vtkGet*Macro*(*" $data] + + if { $set_macro_found || $get_macro_found } { + + # Get the ivar from the Macro declaration + set ivar [get_ivar $data]; + + if { [string compare $ivar "-1"] != 0 } { + + if { [list_contains "$class_name.i.$ivar"] == 0 } { + + incr ivar_count + incr class_ivar_count + + set class_list($class_name.i.$ivar) 0 + } + } + } + } + } + + # If a class was found within the file then increment the class count + if { $class_found } { + incr class_count + } + + close $fileid + + } + +} + +proc check_printself { filename } { + + global verbose + + global class_list + global class_name + + if { $verbose >= 2 } { + puts " Checking PrintSelf in file: $filename" + } + + if { [file readable $filename] } { + + set fileid [open $filename "r"] + + set search_state 0 + + set curly_open 0 + set curly_close 0 + + set line_count 0 + + # + # Read each line in the file + # + while { [gets $fileid data] >= 0 && $search_state != 3 } { + + incr line_count + + # Search for the PrintSelf string + if { $search_state == 0 && [string match "*PrintSelf*(*" $data] == 1 } { + + set search_state 1 + + set first [string first ")" $data] + + set data [string range $data [expr $first + 1] end] + + } + + # Find the first open curly bracket + if { $search_state == 1 } { + + while { [string length $data] > 0 && $curly_open == 0 } { + + # Check for an open curly bracket + set curly_found [string first "\{" $data] + + if { $curly_found > -1 } { + + set data [string range $data [expr $curly_found + 1] end ] + set curly_open 1 + set search_state 2 + + } else { + set data "" + } + } + } + + # Count curly brackets in PrintSelf() method and find ivars + if { $search_state == 2 } { + + set start 0 + set end [string length $data] + + #puts "Line: $data" + + if { [string match "*this->Superclass::PrintSelf(*)*" $data] == 1 } { + if { [list_contains "$class_name.s.Superclass"] == 1 } { + set class_list($class_name.s.Superclass) 1 + } + } elseif { [string match "*::PrintSelf(*)*" $data] == 1 } { + set start [string first "vtk" $data] + set end [string wordend $data $start] + + set super_class [string range $data $start [expr $end -1]] + set super_class [string trim $super_class] + + if { [list_contains "$class_name.s.$super_class"] == 1 } { + set class_list($class_name.s.$super_class) 1 + } elseif { $verbose >= 2 } { + puts "\tSuperclass Issue:\tCan't find $class_name.s.$super_class" + } + } + + while { $start < $end && $curly_open > $curly_close } { + + set word_end [string wordend $data $start] + + set token [string range $data $start [expr $word_end -1] ] + + set token [string trim $token] + + set start $word_end + + if { $verbose >= 2 } { + puts "\tNew Token: $token" + } + + # Check for open and close curly braces + if { [string compare "\{" $token] == 0 } { + incr curly_open + } elseif { [string compare "\}" $token] == 0 } { + incr curly_close + } elseif { [string compare "this" $token] == 0 } { + set start [expr $start + 2] + set token_end [expr [string wordend $data $start ] - 1] + + # Check if this is an array. If so, remove bracket + #if { [string first "\[" $data] > -1 } { + # set token_end [expr $token_end - 1]; + #} + + set ivar [string range $data $start $token_end] + + # Check if this is a Get procedure. If so, remove open parenthesis + #if { [string first "(" $ivar] > -1 } { + # set token_end [expr $token_end - 1]; + # set ivar [string range $data $start $token_end] + #} + + if { [string first "Get" $ivar] > -1 } { + set start [expr $start + 3]; + + # Check if this is a Get*AsString() method + if { [string first "AsString" $ivar] > -1 } { + set token_end [expr $token_end - 8]; + } + + set ivar [string range $data $start $token_end] + } + + set ivar [string trim $ivar] + + if { [list_contains "$class_name.i.$ivar"] == 1 } { + set class_list($class_name.i.$ivar) 1 + } elseif { $verbose } { + puts "\tIvar Issue:\t\tCan't find $class_name.i.$ivar" + } + } + + } + + if { $curly_open == $curly_close } { + set search_state 3 + } + } + } + + close $fileid + } +} + +proc read_directory { dirname } { + + global class_name + global argv + + set total_defects 0 + + set files [glob -nocomplain "$dirname/vtk*.h"] + if { $files != "" } { + foreach headername $files { + + set class_name "" + + # Check that a PrintSelf() is defined + check_header_file $headername + + # Check that the PrintSelf() method accesses the appropriate ivars + if { $class_name != "" && [list_contains "$class_name.p"] == 1 } { + set length [string length $headername] + set filename [string range $headername 0 [expr $length - 3] ] + if {[file exists "$filename.mm"] == 1} { + check_printself "$filename.mm" + } else { + check_printself "$filename.cxx" + } + } + + } + } +} + +proc class_has_ivars { class } { + + global verbose + global class_list + + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + + set element [array nextelement class_list $searchid] + + if { [string match "$class.i.*" $element] == 1 } { + array donesearch class_list $searchid + return 1 + } + } + + array donesearch class_list $searchid + + return 0 +} + +proc check_for_defects { print } { + + global pd_id + + global verbose + global class_list + global class_print_count + global ivar_miss_count + global printself_miss_count + global super_miss_count + + # + # PRINTSELF CHECK + # + + # Loop through list and count printself defects, if any + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + set element [array nextelement class_list $searchid] + # Extract strings that represent PrintSelfs + if { [string match "*.p" $element] == 1 } { + set end [expr [string wordend $element 0] - 1] + set curr_class [string range $element 0 $end] + + if { [class_has_ivars $curr_class] == 1 } { + + incr class_print_count + + if { $class_list($element) != 1 } { + + incr printself_miss_count + } + } + } + } + + array donesearch class_list $searchid + + # Loop through list and print printself defects + if { $printself_miss_count > 0 && $print } { + puts $pd_id " PrintSelf DEFECTS: " + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + + set element [array nextelement class_list $searchid] + # Extract strings that represent PrintSelfs + if { [string match "*.p" $element] == 1 } { + set end [expr [string wordend $element 0] - 1] + set curr_class [string range $element 0 $end] + + if { [class_has_ivars $curr_class] == 1 } { + if { $class_list($element) != 1 } { + puts $pd_id " $curr_class does not have a PrintSelf method" + } + } + } + } + + array donesearch class_list $searchid + } + + # + # SUPERCLASS CHECK + # + + # Loop through list and count superclass defects, if any + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + + set element [array nextelement class_list $searchid] + # Extract strings that represent superclasses + if { [string match "*.s.*" $element] == 1 } { + set end [expr [string wordend $element 0] - 1] + set curr_class [string range $element 0 $end] + + if { $class_list($curr_class.s.Superclass) != 1 && + [class_has_ivars $curr_class] == 1 && + $class_list($element) != 1 } { + set start [expr $end + 4] + set end [expr [string wordend $element $start] - 1] + set parent [string range $element $start $end] + if { $parent == "Superclass" } continue; + + incr super_miss_count + } + } + } + + array donesearch class_list $searchid + + # Loop through list and print superclass defects + if { $super_miss_count > 0 && $print } { + puts $pd_id " Superclass DEFECTS: " + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + + set element [array nextelement class_list $searchid] + # Extract strings that represent superclasses + if { [string match "*.s.*" $element] == 1 } { + set end [expr [string wordend $element 0] - 1] + set curr_class [string range $element 0 $end] + + if { $class_list($curr_class.s.Superclass) != 1 && + [class_has_ivars $curr_class] == 1 && + $class_list($element) != 1 } { + + set start [expr $end + 4] + set end [expr [string wordend $element $start] - 1] + set parent [string range $element $start $end] + if { $parent == "Superclass" } continue; + puts $pd_id " $curr_class did not print superclass $parent" + } + } + } + + array donesearch class_list $searchid + } + + # + # IVAR CHECK + # + + # Loop through list and count ivar defects, if any + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + + set element [array nextelement class_list $searchid] + + # Extract strings that represent ivars + if { [string match "*.i.*" $element] == 1 } { + if { $class_list($element) != 1 } { + incr ivar_miss_count + + } + } + } + + array donesearch class_list $searchid + + # Loop through list and print ivar defects + if { $ivar_miss_count > 0 && $print } { + puts $pd_id " Ivar DEFECTS: " + set searchid [array startsearch class_list] + + while { [array anymore class_list $searchid] } { + + set element [array nextelement class_list $searchid] + + # Extract strings that represent ivars + if { [string match "*.i.*" $element] == 1 } { + if { $class_list($element) != 1 } { + set end [expr [string wordend $element 0] - 1] + set curr_class [string range $element 0 $end] + + set start [expr $end + 4] + set end [expr [string wordend $element $start] - 1] + set ivar [string range $element $start $end] + + puts $pd_id " $curr_class does not print ivar: $ivar" + } + } + } + + array donesearch class_list $searchid + } + +} + +proc print_toolkit_results { toolkit } { + + global pd_id + + global class_count + global class_print_count + global printself_miss_count + global ivar_count + global ivar_miss_count + global super_miss_count + + check_for_defects 1 + + set tk [string range $toolkit 0 14 ] + +} + +proc print_totals {} { + global total_defects + global total_class_count + global total_class_print_count + global total_printself_miss_count + global total_ivar_count + global total_ivar_miss_count + global total_super_miss_count + + set total_defects [expr $total_printself_miss_count + $total_super_miss_count + $total_ivar_miss_count] + +} + +proc open_files { } { + + global pd_id + + set pd_id stdout + +} + +proc close_files { } { + + global pd_id + + close $pd_id + + set pd_id 0 +} + +proc clear_results { } { + + global class_count + global class_print_count + global printself_miss_count + global ivar_count + global ivar_miss_count + global super_miss_count + global class_list + + unset class_list + set class_list(null) 1 + + set class_count 0 + set class_print_count 0 + set ivar_count 0 + set printself_miss_count 0 + set ivar_miss_count 0 + set super_miss_count 0 +} + +proc measure_vtk {kit} { + + global pd_id + + global verbose + + global class_list + global class_count + global class_print_count + global printself_miss_count + global ivar_count + global ivar_miss_count + global super_miss_count + + global total_class_count + global total_class_print_count + global total_printself_miss_count + global total_ivar_count + global total_ivar_miss_count + global total_super_miss_count + + open_files + + clear_results + + read_directory "$kit" + + print_toolkit_results $kit + + set total_class_count [expr $total_class_count + $class_count] + set total_class_print_count [expr $total_class_print_count + $class_print_count] + set total_printself_miss_count [expr $total_printself_miss_count + $printself_miss_count]; + set total_ivar_count [expr $total_ivar_count + $ivar_count]; + set total_ivar_miss_count [expr $total_ivar_miss_count + $ivar_miss_count]; + set total_super_miss_count [expr $total_super_miss_count + $super_miss_count]; + + print_totals + close_files + + if { $verbose } { + parray class_list + } + +} +measure_vtk [lindex $argv 0] + +exit $total_defects + diff --git a/Common/Testing/Tcl/TestAmoebaMinimizer.tcl b/Common/Testing/Tcl/TestAmoebaMinimizer.tcl new file mode 100644 index 0000000..1369da3 --- /dev/null +++ b/Common/Testing/Tcl/TestAmoebaMinimizer.tcl @@ -0,0 +1,57 @@ +for {set i 0} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + set auto_path "$auto_path [lindex $argv [expr $i +1]]" + } +} + +package require vtk + +vtkAmoebaMinimizer m + +proc func {} { + set x [m GetParameterValue "x"] + set y [m GetParameterValue "y"] + set z [m GetParameterValue "z"] + + set r [expr ($x-5.0)*($x-5.0) + ($y+2.0)*($y+2.0) + ($z)*($z)] + + m SetFunctionValue $r +} + +m SetFunction func +m SetParameterValue "x" 0.0 +m SetParameterScale "x" 2.0 +m SetParameterValue "y" 0.0 +m SetParameterScale "y" 2.0 +m SetParameterValue "z" 0.0 +m SetParameterScale "z" 2.0 +m Minimize + +puts "should find x=5, y=-2, z=0" + +puts -nonewline "should be 0 if the simplex converged -> " +puts [m Iterate] + +puts -nonewline "x = " +puts [m GetParameterValue "x"] +puts -nonewline "y = " +puts [m GetParameterValue "y"] +puts -nonewline "z = " +puts [m GetParameterValue "z"] + +puts -nonewline "function value = " +puts [m GetFunctionValue] + +puts -nonewline "evaluations = " +puts [m GetFunctionEvaluations] + +puts -nonewline "iterations = " +puts [m GetIterations] + +puts "To improve coverage and catch errors, do a PrintSelf with parameters set:" + +puts [m Print] + +m Delete + +exit \ No newline at end of file diff --git a/Common/Testing/Tcl/TestArrays.tcl b/Common/Testing/Tcl/TestArrays.tcl new file mode 100644 index 0000000..fa2e92d --- /dev/null +++ b/Common/Testing/Tcl/TestArrays.tcl @@ -0,0 +1,62 @@ +for {set i 0} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + set auto_path "$auto_path [lindex $argv [expr $i +1]]" + } +} + +package require vtk + +foreach array "Bit Char Double Float Int Long Short UnsignedChar UnsignedInt UnsignedLong UnsignedShort" { + puts "$array array" + vtk${array}Array a${array}Array + a${array}Array Allocate 1 1 + a${array}Array SetNumberOfComponents 3 + a${array}Array SetNumberOfTuples 4 + + # InsertComponent + set k 0 + for {set i 0} {$i < [a${array}Array GetNumberOfTuples]} {incr i} { + for {set j 0} {$j < [a${array}Array GetNumberOfComponents]} {incr j} { + a${array}Array InsertComponent $i $j 1 + incr k + } + } + # SetComponent + set k 0 + for {set i 0} {$i < [a${array}Array GetNumberOfTuples]} {incr i} { + for {set j 0} {$j < [a${array}Array GetNumberOfComponents]} {incr j} { + a${array}Array SetComponent $i $j 1 + incr k + } + } + + # DeepCopy + vtk${array}Array b${array}Array + b${array}Array Allocate 1000 100 + # force a resize + b${array}Array InsertComponent 2001 0 1 + b${array}Array DeepCopy a${array}Array + + # NewInstance + set m${array} [b${array}Array NewInstance] + eval [set m${array}] UnRegister b${array}Array + + # confirm the deep copy + for {set i 0} {$i < [a${array}Array GetNumberOfTuples]} {incr i} { + for {set j 0} {$j < [a${array}Array GetNumberOfComponents]} {incr j} { + if { [a${array}Array GetComponent $i $j] != [b${array}Array GetComponent $i $j] } { + puts "${array}: bad component $i $j" + } + incr k + } + } + b${array}Array InsertComponent 2001 0 1 + b${array}Array Resize 3000 + + a${array}Array Squeeze + a${array}Array Initialize + + a${array}Array Delete + b${array}Array Delete +} +exit diff --git a/Common/Testing/Tcl/TestEmptyInput.tcl b/Common/Testing/Tcl/TestEmptyInput.tcl new file mode 100644 index 0000000..d942d29 --- /dev/null +++ b/Common/Testing/Tcl/TestEmptyInput.tcl @@ -0,0 +1,88 @@ +for {set i 0} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + set auto_path "$auto_path [lindex $argv [expr $i +1]]" + } +} + +package require vtk +vtkObject a +a GlobalWarningDisplayOff +a Delete + + +vtkPolyData emptyPD +vtkImageData emptyID +vtkStructuredGrid emptySG +vtkUnstructuredGrid emptyUG +vtkRectilinearGrid emptyRG + +proc TestOne {cname} { + + $cname b + + if {[b IsA "vtkAlgorithm"]} { + catch {b Update} + if {[catch {b SetInput emptyPD}] == 0} { + catch {b Update} + } + if {[catch {b SetInput emptyID}] == 0} { + catch {b Update} + } + if {[catch {b SetInput emptySG}] == 0} { + catch {b Update} + } + if {[catch {b SetInput emptyUG}] == 0} { + catch {b Update} + } + if {[catch {b SetInput emptyRG}] == 0} { + catch {b Update} + } + } + + b Delete +} + +set classExceptions { + vtkCommand + vtkIndent + vtkTimeStamp + vtkTkImageViewerWidget + vtkTkImageWindowWidget + vtkTkRenderWidget + vtkImageDataToTkPhoto + vtkJPEGReader + vtkWin32VideoSource + vtkDistributedDataFilter +} + +proc rtTestEmptyInputTest { fileid } { + global classExceptions + # for every class + set all [lsort [info command vtk*]] + foreach a $all { + if {[lsearch $classExceptions $a] == -1} { + # test some set get methods + puts -nonewline "Testing -- $a - " + flush stdout + TestOne $a + puts "done" + } + } + puts "All Passed" +} + + + + + +rtTestEmptyInputTest stdout + +emptyPD Delete +emptyID Delete +emptySG Delete +emptyUG Delete +emptyRG Delete + +exit + + diff --git a/Common/Testing/Tcl/TestSetGet.tcl b/Common/Testing/Tcl/TestSetGet.tcl new file mode 100644 index 0000000..5d44ad6 --- /dev/null +++ b/Common/Testing/Tcl/TestSetGet.tcl @@ -0,0 +1,95 @@ +for {set i 0} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + set auto_path "$auto_path [lindex $argv [expr $i +1]]" + } +} + +package require vtk +vtkObject a +a GlobalWarningDisplayOff +a Delete + +set exceptions { +vtkLODProp3D-GetPickLODID +vtkObject-GetSuperClassName +vtkPropAssembly-GetBounds +vtkRenderWindow-GetEventPending +vtkXOpenGLRenderWindow-GetEventPending +vtkXMesaRenderWindow-GetEventPending +vtkMPICommunicator-GetWorldCommunicator +} + +proc TestOne {cname} { + global exceptions + $cname b + puts "Testing Class $cname" + set methods [b ListMethods] + # look for a Get Set pair + set len [llength $methods] + for {set i 0} {$i < $len} {incr i} { + if {[regsub {^Get([A-za-z0-9]*)} [lindex $methods $i] {\1} name]} { + if {($i == $len - 1) || ($i < $len - 1 && [lindex $methods [expr $i + 1]] != "with")} { + if {[lsearch $exceptions "$cname-[lindex $methods $i]"] == -1} { + # invoke the GetMethod + puts " Invoking Get$name" + set tmp [b Get$name] + # find matching set method + for {set j 0} {$j < $len} {incr j} { + if {[regexp "^Set$name" [lindex $methods $j]]} { + if {$j < $len - 3 && [lindex $methods [expr $j + 2]] == "1"} { + puts " Invoking Set$name" + catch {b Set$name $tmp} + } + if {$j < $len - 3 && [lindex $methods [expr $j + 2]] > 1} { + puts " Invoking Set$name" + catch {eval b Set$name $tmp} + } + } + } + } + } + } + } + # Test the PrintRevisions method. + b PrintRevisions + b Delete +} + +set classExceptions { + vtkCommand + vtkFileOutputWindow + vtkIndent + vtkOutputWindow + vtkParallelFactory + vtkPlanes + vtkProjectedPolyDataRayBounder + vtkRayCaster + vtkTimeStamp + vtkTkImageViewerWidget + vtkTkImageWindowWidget + vtkTkRenderWidget + vtkImageDataToTkPhoto + vtkViewRays + vtkWin32OutputWindow + vtkWin32ProcessOutputWindow + vtkXMLFileOutputWindow +} + +proc rtSetGetTest { fileid } { + global classExceptions + # for every class + set all [lsort [info command vtk*]] + foreach a $all { + if {[lsearch $classExceptions $a] == -1} { + # test some set get methods + #puts "Testing -- $a" + TestOne $a + } + } +} + +# All tests should end with the following... + +rtSetGetTest stdout + +exit diff --git a/Common/Testing/Tcl/otherInterp.tcl b/Common/Testing/Tcl/otherInterp.tcl new file mode 100644 index 0000000..a18dc98 --- /dev/null +++ b/Common/Testing/Tcl/otherInterp.tcl @@ -0,0 +1,51 @@ +for {set i 0} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + set auto_path "$auto_path [lindex $argv [expr $i +1]]" + } +} +package require vtk + +proc rtOtherTest { fileid } { +#actual test + puts $fileid "vtkTclUtil test started" + + vtkCommand DebugOn + vtkTriangle a + vtkQuad b + puts $fileid "a ListInstances: [a ListInstances]" + puts $fileid "vtkTriangle ListInstances: [vtkTriangle ListInstances]" + puts $fileid "vtkCommand ListMethods" + puts $fileid "[vtkCommand ListMethods]" + puts $fileid "vtkCommand ListAllInstances" + puts $fileid "[vtkCommand ListAllInstances]" + puts $fileid "Some error handling..." + + puts $fileid "vtkWedge" + set rc [catch {puts $fileid "[vtkWedge]"} status] + puts $fileid "tcl return code: $rc : $status" + + puts $fileid "vtkWedge 1a" + set rc [catch {puts $fileid "[vtkWedge 1a]"} status] + puts $fileid "tcl return code: $rc : $status" + + puts $fileid "vtkTransform t; vtkTransform t" + set rc [catch {puts $fileid "[vtkTransform t; vtkTransform t]"} status] + puts $fileid "tcl return code: $rc : $status" + + puts $fileid "vtkTransform image;" + set rc [catch {puts $fileid "[vtkTransform image]"} status] + puts $fileid "tcl return code: $rc : $status" + + puts $fileid "vtkTclUtil test ended" +} + +# All tests should end with the following... + +if {![info exists rtOutId]} { + rtOtherTest stdout + vtkCommand DebugOff + vtkCommand DeleteAllObjects + exit +} + +wm withdraw . diff --git a/Common/Testing/Tcl/otherPrint.tcl b/Common/Testing/Tcl/otherPrint.tcl new file mode 100644 index 0000000..f145a69 --- /dev/null +++ b/Common/Testing/Tcl/otherPrint.tcl @@ -0,0 +1,56 @@ +for {set i 0} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + set auto_path "$auto_path [lindex $argv [expr $i +1]]" + } +} + +package require vtk + +vtkObject a +a GlobalWarningDisplayOff +a Delete + +proc rtOtherTest { fileid } { +#actual test + set all [lsort [info command vtk*]] + foreach a $all { + if {$a == "vtkIndent"} { + continue + } + if {$a == "vtkOutputPort"} { + continue + } + if {$a == "vtkTimeStamp"} { + continue + } + if {$a == "vtkOutputWindow"} { + continue + } + catch { + $a b + b Print + if {[b IsA $a] == 0} {puts stderr "$a failed IsA test!!!"} + if {[b IsA "vtkObject"] == 0} {puts stdout "$a is not a sub-class of vtkObject"} + b GetClassName + b Delete + } + catch { + $a b + $a c + set d [b SafeDownCast c] + b Delete + c Delete + } + catch { + b Delete + c Delete + } + } +} + +# All tests should end with the following... + +rtOtherTest stdout + +exit + diff --git a/Common/Testing/Tcl/prtImageTest.tcl b/Common/Testing/Tcl/prtImageTest.tcl new file mode 100644 index 0000000..f4d2fd4 --- /dev/null +++ b/Common/Testing/Tcl/prtImageTest.tcl @@ -0,0 +1,130 @@ + +# setup some common things for testing +vtkObject rtTempObject; +rtTempObject GlobalWarningDisplayOff; +vtkMath rtExMath +rtExMath RandomSeed 6 + +# create the testing class to do the work +vtkTesting rtTester +for {set i 1} {$i < [expr $argc - 1]} {incr i} { + rtTester AddArgument "[lindex $argv $i]" +} +set VTK_DATA_ROOT [rtTester GetDataRoot] + +for {set i 1} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + foreach dir [split [lindex $argv [expr $i +1]] ":"] { + lappend auto_path $dir + } + } +} + +vtkMPIController mpc +set gc [mpc GetGlobalController] +mpc Delete + +vtkCompositeRenderManager compManager + +if { $gc != "" } { + set myProcId [$gc GetLocalProcessId] + set numProcs [$gc GetNumberOfProcesses] + + compManager SetController $gc +} else { + set myProcId 0 + set numProcs 1 +} + + +proc ExitMaster { code } { + global numProcs + for { set i 1 } { $i < $numProcs } { incr i } { + # Send break to all the nodes + #puts "Send break to: $i" + catch [ [ compManager GetController ] TriggerRMI $i 239954 ] + } + + vtkCommand DeleteAllObjects + catch {destroy .top} + catch {destroy .geo} + + exit $code +} + +# load in the script +set file [lindex $argv 0] + +if { $myProcId != 0 } { + #puts "Start reading script on satellite node" + source $file + + compManager InitializeRMIs + #puts "Process RMIs" + [ compManager GetController ] ProcessRMIs + + #puts "**********************************" + #puts "Done on the slave node" + #puts "**********************************" + + + vtkCommand DeleteAllObjects + catch {destroy .top} + catch {destroy .geo} + exit 0 +} + +# set the default threshold, the Tcl script may change this +set threshold -1 + +if {[info commands wm] != ""} { + wm withdraw . +} else { + # There is no Tk. Help the tests run without it. + proc wm args { + puts "wm not implemented" + } + # The vtkinteraction package requires Tk but since Tk is not + # available it will never be used anyway. Just pretend it is + # already loaded so that tests that load it will not try to load Tk. + package provide vtkinteraction 5.0 +} + +# Run the test. +source $file +if {[info commands iren] == "iren"} {renWin Render} +# run the event loop quickly to map any tkwidget windows +update + +# current directory +if {[rtTester IsValidImageSpecified] != 0} { + # look for a renderWindow ImageWindow or ImageViewer + # first check for some common names + if {[info commands renWin] == "renWin"} { + rtTester SetRenderWindow renWin + if {$threshold == -1} { + set threshold 10 + } + } else { + if {$threshold == -1} { + set threshold 5 + } + if {[info commands viewer] == "viewer"} { + rtTester SetRenderWindow [viewer GetRenderWindow] + viewer Render + } else { + if {[info commands imgWin] == "imgWin"} { + rtTester SetRenderWindow imgWin + imgWin Render + } else { + if {[info exists viewer]} { + rtTester SetRenderWindow [$viewer GetRenderWindow] + } + } + } + } + set rtResult [rtTester RegressionTest $threshold] +} + +if {$rtResult == 0} {ExitMaster 1} +ExitMaster 0 diff --git a/Common/Testing/Tcl/rtImageTest.tcl b/Common/Testing/Tcl/rtImageTest.tcl new file mode 100644 index 0000000..6ddb97d --- /dev/null +++ b/Common/Testing/Tcl/rtImageTest.tcl @@ -0,0 +1,87 @@ + +# setup some common things for testing +vtkObject rtTempObject; + +# This really should be removed but used to hang dashboards. +# I'm commenting it out for now to see what happens. +#rtTempObject GlobalWarningDisplayOff; + +vtkMath rtExMath +rtExMath RandomSeed 6 + +# create the testing class to do the work +vtkTesting rtTester +for {set i 1} {$i < [expr $argc - 1]} {incr i} { + rtTester AddArgument "[lindex $argv $i]" +} +set VTK_DATA_ROOT [rtTester GetDataRoot] + +for {set i 1} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + foreach dir [split [lindex $argv [expr $i +1]] ":"] { + lappend auto_path $dir + } + } +} + +# load in the script +set file [lindex $argv 0] + +# set the default threshold, the Tcl script may change this +set threshold -1 + +if {[info commands wm] != ""} { + wm withdraw . +} else { + # There is no Tk. Help the tests run without it. + proc wm args { + puts "wm not implemented" + } + # The vtkinteraction package requires Tk but since Tk is not + # available it will never be used anyway. Just pretend it is + # already loaded so that tests that load it will not try to load Tk. + package provide vtkinteraction 5.0 +} + +# Run the test. +source $file +if {[info commands iren] == "iren"} {renWin Render} +# run the event loop quickly to map any tkwidget windows +update + +# current directory +if {[rtTester IsValidImageSpecified] != 0} { + # look for a renderWindow ImageWindow or ImageViewer + # first check for some common names + if {[info commands renWin] == "renWin"} { + rtTester SetRenderWindow renWin + if {$threshold == -1} { + set threshold 10 + } + } else { + if {$threshold == -1} { + set threshold 5 + } + if {[info commands viewer] == "viewer"} { + rtTester SetRenderWindow [viewer GetRenderWindow] + viewer Render + } else { + if {[info commands imgWin] == "imgWin"} { + rtTester SetRenderWindow imgWin + imgWin Render + } else { + if {[info exists viewer]} { + rtTester SetRenderWindow [$viewer GetRenderWindow] + } + } + } + } + set rtResult [rtTester RegressionTest $threshold] +} + +vtkCommand DeleteAllObjects +catch {destroy .top} +catch {destroy .geo} + +if {$rtResult == 0} {exit 1} +exit 0 diff --git a/Common/Testing/WindowsMangleList.py b/Common/Testing/WindowsMangleList.py new file mode 100644 index 0000000..8026301 --- /dev/null +++ b/Common/Testing/WindowsMangleList.py @@ -0,0 +1,1086 @@ +#!/usr/bin/env python + +## /*========================================================================= + +## Program: Visualization Toolkit +## Module: $RCSfile: WindowsMangleList.py,v $ + +## Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +## All rights reserved. +## See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +## This software is distributed WITHOUT ANY WARRANTY; without even +## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the above copyright notice for more information. + +## =========================================================================*/ +## .NAME WindowsMangleList - List of method names mangled by windows.h. +## .SECTION Description +## WindowsMangleList is a script imported by HeaderTesting to get a regular +## expression matching method names that will be mangled by windows.h. +## See VTK/Utilities/Upgrading/README.WindowsMangling.txt for details +## on the windows.h mangling problems. + +import re + +# NOTE: The lists below are up-to-date for windows.h versions up to +# Visual Studio .NET 2003. Additional names may be added by future +# versions of windows.h. +# +# The set of macros defined by windows.h was obtained with the command +# +# gccxml --gccxml-compiler msvc71 -E win.cxx -dM +# +# where "win.cxx" contains the line "#include ". Some +# filtering for names of the VTK naming convention was then applied. + +# Names defined as macros by windows.h. +WindowsMangleNames = [ +'AbnormalTermination', +'AbortSystemShutdown', +'AccessCheckAndAuditAlarm', +'AddAtom', +'AddFontResource', +'AddForm', +'AddJob', +'AddMonitor', +'AddPort', +'AddPrintProcessor', +'AddPrintProvidor', +'AddPrinter', +'AddPrinterConnection', +'AddPrinterDriver', +'AddPrinterDriverEx', +'AdvancedDocumentProperties', +'AnsiLower', +'AnsiLowerBuff', +'AnsiNext', +'AnsiPrev', +'AnsiToOem', +'AnsiToOemBuff', +'AnsiUpper', +'AnsiUpperBuff', +'AppendMenu', +'BackupEventLog', +'BeginUpdateResource', +'BuildCommDCB', +'BuildCommDCBAndTimeouts', +'CallMsgFilter', +'CallNamedPipe', +'CallWindowProc', +'CdChangerClassGuid', +'CdRomClassGuid', +'CertAddEncodedCertificateToSystemStore', +'CertGetNameString', +'CertNameToStr', +'CertOpenSystemStore', +'CertRDNValueToStr', +'CertStrToName', +'ChangeDisplaySettings', +'ChangeDisplaySettingsEx', +'ChangeMenu', +'ChangeServiceConfig', +'ChangeServiceConfig2', +'CharLower', +'CharLowerBuff', +'CharNext', +'CharPrev', +'CharToOem', +'CharToOemBuff', +'CharUpper', +'CharUpperBuff', +'ChooseColor', +'ChooseFont', +'ClearEventLog', +'CommConfigDialog', +'CommDlg_OpenSave_GetFilePath', +'CommDlg_OpenSave_GetFilePathA', +'CommDlg_OpenSave_GetFilePathW', +'CommDlg_OpenSave_GetFolderIDList', +'CommDlg_OpenSave_GetFolderPath', +'CommDlg_OpenSave_GetFolderPathA', +'CommDlg_OpenSave_GetFolderPathW', +'CommDlg_OpenSave_GetSpec', +'CommDlg_OpenSave_GetSpecA', +'CommDlg_OpenSave_GetSpecW', +'CommDlg_OpenSave_HideControl', +'CommDlg_OpenSave_SetControlText', +'CommDlg_OpenSave_SetDefExt', +'CompareString', +'ConfigurePort', +'CopyAcceleratorTable', +'CopyCursor', +'CopyEnhMetaFile', +'CopyFile', +'CopyMemory', +'CopyMetaFile', +'CreateAcceleratorTable', +'CreateColorSpace', +'CreateDC', +'CreateDesktop', +'CreateDialog', +'CreateDialogA', +'CreateDialogIndirect', +'CreateDialogIndirectA', +'CreateDialogIndirectParam', +'CreateDialogIndirectW', +'CreateDialogParam', +'CreateDialogW', +'CreateDirectory', +'CreateDirectoryEx', +'CreateEnhMetaFile', +'CreateEvent', +'CreateFile', +'CreateFileMapping', +'CreateFont', +'CreateFontIndirect', +'CreateIC', +'CreateMDIWindow', +'CreateMailslot', +'CreateMetaFile', +'CreateMutex', +'CreateNamedPipe', +'CreateProcess', +'CreateProcessAsUser', +'CreatePropertySheetPage', +'CreateScalableFontResource', +'CreateSemaphore', +'CreateService', +'CreateWindow', +'CreateWindowA', +'CreateWindowEx', +'CreateWindowStation', +'CreateWindowW', +'CryptAcquireContext', +'CryptBinaryToString', +'CryptEnumProviderTypes', +'CryptEnumProviders', +'CryptGetDefaultProvider', +'CryptRetrieveObjectByUrl', +'CryptSetProvider', +'CryptSetProviderEx', +'CryptSignHash', +'CryptStringToBinary', +'CryptVerifySignature', +'DceErrorInqText', +'DdeCreateStringHandle', +'DdeInitialize', +'DdeQueryString', +'DecryptFile', +'DefDlgProc', +'DefFrameProc', +'DefHookProc', +'DefMDIChildProc', +'DefWindowProc', +'DefineDosDevice', +'DefineHandleTable', +'DeleteFile', +'DeleteForm', +'DeleteMonitor', +'DeletePort', +'DeletePrintProcessor', +'DeletePrintProvidor', +'DeletePrinterConnection', +'DeletePrinterData', +'DeletePrinterDataEx', +'DeletePrinterDriver', +'DeletePrinterDriverEx', +'DeletePrinterKey', +'DeviceCapabilities', +'DialogBox', +'DialogBoxA', +'DialogBoxIndirect', +'DialogBoxIndirectA', +'DialogBoxIndirectParam', +'DialogBoxIndirectW', +'DialogBoxParam', +'DialogBoxW', +'DiskClassGuid', +'DispatchMessage', +'DlgDirList', +'DlgDirListComboBox', +'DlgDirSelectComboBoxEx', +'DlgDirSelectEx', +'DoEnvironmentSubst', +'DocumentProperties', +'DragQueryFile', +'DrawState', +'DrawText', +'DrawTextEx', +'EncryptFile', +'EndUpdateResource', +'EnumCalendarInfo', +'EnumCalendarInfoEx', +'EnumDateFormats', +'EnumDateFormatsEx', +'EnumDependentServices', +'EnumDesktops', +'EnumDisplayDevices', +'EnumDisplaySettings', +'EnumDisplaySettingsEx', +'EnumFontFamilies', +'EnumFontFamiliesEx', +'EnumFonts', +'EnumForms', +'EnumICMProfiles', +'EnumJobs', +'EnumLanguageGroupLocales', +'EnumMonitors', +'EnumPorts', +'EnumPrintProcessorDatatypes', +'EnumPrintProcessors', +'EnumPrinterData', +'EnumPrinterDataEx', +'EnumPrinterDrivers', +'EnumPrinterKey', +'EnumPrinters', +'EnumProps', +'EnumPropsEx', +'EnumResourceLanguages', +'EnumResourceNames', +'EnumResourceTypes', +'EnumServicesStatus', +'EnumServicesStatusEx', +'EnumSystemCodePages', +'EnumSystemLanguageGroups', +'EnumSystemLocales', +'EnumTaskWindows', +'EnumTimeFormats', +'EnumUILanguages', +'EnumWindowStations', +'ExitWindows', +'ExpandEnvironmentStrings', +'ExtTextOut', +'ExtractAssociatedIcon', +'ExtractAssociatedIconEx', +'ExtractIcon', +'ExtractIconEx', +'FatalAppExit', +'FileEncryptionStatus', +'FillConsoleOutputCharacter', +'FillMemory', +'FindAtom', +'FindExecutable', +'FindFirstChangeNotification', +'FindFirstFile', +'FindNextFile', +'FindResource', +'FindResourceEx', +'FindText', +'FindWindow', +'FindWindowEx', +'FloppyClassGuid', +'FoldString', +'FormatMessage', +'FreeEnvironmentStrings', +'FreeModule', +'FreeProcInstance', +'GetAltTabInfo', +'GetAtomName', +'GetBValue', +'GetBinaryType', +'GetCPInfoEx', +'GetCValue', +'GetCalendarInfo', +'GetCharABCWidths', +'GetCharABCWidthsFloat', +'GetCharWidth', +'GetCharWidth32', +'GetCharWidthFloat', +'GetCharacterPlacement', +'GetClassInfo', +'GetClassInfoEx', +'GetClassLong', +'GetClassLongPtr', +'GetClassLongPtrA', +'GetClassLongPtrW', +#'GetClassName', # Leave out GetClassName for now. +'GetClipboardFormatName', +'GetCommandLine', +'GetCompressedFileSize', +'GetComputerName', +'GetConsoleTitle', +'GetCurrencyFormat', +'GetCurrentDirectory', +'GetCurrentTime', +'GetDateFormat', +'GetDefaultCommConfig', +'GetDefaultPrinter', +'GetDiskFreeSpace', +'GetDiskFreeSpaceEx', +'GetDlgItemText', +'GetDriveType', +'GetEnhMetaFile', +'GetEnhMetaFileDescription', +'GetEnvironmentStringsA', +'GetEnvironmentVariable', +'GetExceptionCode', +'GetExceptionInformation', +'GetExpandedName', +'GetFileAttributes', +'GetFileAttributesEx', +'GetFileSecurity', +'GetFileTitle', +'GetFileVersionInfo', +'GetFileVersionInfoSize', +'GetFirmwareEnvironmentVariable', +'GetForm', +'GetFreeSpace', +'GetFullPathName', +'GetGValue', +'GetGeoInfo', +'GetGlyphOutline', +'GetICMProfile', +'GetJob', +'GetKValue', +'GetKerningPairs', +'GetKeyNameText', +'GetKeyboardLayoutName', +'GetLocaleInfo', +'GetLogColorSpace', +'GetLogicalDriveStrings', +'GetLongPathName', +'GetMValue', +'GetMenuItemInfo', +'GetMenuString', +'GetMessage', +'GetMetaFile', +'GetModuleFileName', +'GetModuleHandle', +'GetMonitorInfo', +'GetNamedPipeHandleState', +'GetNextWindow', +'GetNumberFormat', +'GetObject', +'GetOpenCardName', +'GetOpenFileName', +'GetOutlineTextMetrics', +'GetPrintProcessorDirectory', +'GetPrinter', +'GetPrinterData', +'GetPrinterDataEx', +'GetPrinterDriver', +'GetPrinterDriverDirectory', +'GetPrivateProfileInt', +'GetPrivateProfileSection', +'GetPrivateProfileSectionNames', +'GetPrivateProfileString', +'GetPrivateProfileStruct', +'GetProfileInt', +'GetProfileSection', +'GetProfileString', +'GetProp', +'GetRValue', +'GetSaveFileName', +'GetScode', +'GetServiceDisplayName', +'GetServiceKeyName', +'GetShortPathName', +'GetStartupInfo', +'GetStringTypeEx', +'GetSysModalWindow', +'GetSystemDirectory', +'GetSystemWindowsDirectory', +'GetTabbedTextExtent', +'GetTempFileName', +'GetTempPath', +'GetTextExtentExPoint', +'GetTextExtentPoint', +'GetTextExtentPoint32', +'GetTextFace', +'GetTextMetrics', +'GetTimeFormat', +'GetUrlPolicyPermissions', +'GetUserName', +'GetUserObjectInformation', +'GetVersionEx', +'GetVolumeInformation', +'GetWindowLong', +'GetWindowLongPtr', +'GetWindowLongPtrA', +'GetWindowLongPtrW', +'GetWindowModuleFileName', +'GetWindowTask', +'GetWindowText', +'GetWindowTextLength', +'GetWindowsDirectory', +'GetYValue', +'GlobalAddAtom', +'GlobalDiscard', +'GlobalFindAtom', +'GlobalGetAtomName', +'GlobalLRUNewest', +'GlobalLRUOldest', +'GrayString', +'HandleToLong', +'HandleToULong', +'HandleToUlong', +'HasOverlappedIoCompleted', +'ImmConfigureIME', +'ImmEnumRegisterWord', +'ImmEscape', +'ImmGetCandidateList', +'ImmGetCandidateListCount', +'ImmGetCompositionFont', +'ImmGetCompositionString', +'ImmGetConversionList', +'ImmGetDescription', +'ImmGetGuideLine', +'ImmGetIMEFileName', +'ImmGetImeMenuItems', +'ImmGetRegisterWordStyle', +'ImmInstallIME', +'ImmIsUIMessage', +'ImmRegisterWord', +'ImmSetCompositionFont', +'ImmSetCompositionString', +'ImmUnregisterWord', +'InitiateSystemShutdown', +'InitiateSystemShutdownEx', +'InsertMenu', +'InsertMenuItem', +'Int32x32To64', +'IntToPtr', +'InterlockedCompareExchangePointer', +'InterlockedExchangePointer', +'IsBadStringPtr', +'IsCharAlpha', +'IsCharAlphaNumeric', +'IsCharLower', +'IsCharUpper', +'IsContainerPartition', +'IsDialogMessage', +'IsEqualCLSID', +'IsEqualFMTID', +'IsEqualIID', +'IsFTPartition', +'IsHashValCompatible', +'IsLFNDrive', +'IsLoggingEnabled', +'IsRecognizedPartition', +'IsReparseTagMicrosoft', +'IsReparseTagNameSurrogate', +'IsValidDevmode', +'LimitEmsPages', +'LoadBitmap', +'LoadCursor', +'LoadCursorFromFile', +'LoadIcon', +'LoadImage', +'LoadKeyboardLayout', +'LoadLibrary', +'LoadLibraryEx', +'LoadMenu', +'LoadMenuIndirect', +'LoadString', +'LocalDiscard', +'LockSegment', +'LogonUser', +'LogonUserEx', +'LongToHandle', +'LongToPtr', +'LookupAccountName', +'LookupAccountSid', +'LookupPrivilegeDisplayName', +'LookupPrivilegeName', +'LookupPrivilegeValue', +'MakeProcInstance', +'MapVirtualKey', +'MapVirtualKeyEx', +'MaxNumberOfEEInfoParams', +'MediumChangerClassGuid', +'MessageBox', +'MessageBoxEx', +'MessageBoxIndirect', +'ModifyMenu', +'MoveFile', +'MoveFileEx', +'MoveMemory', +'MultinetGetConnectionPerformance', +'NdrFcLong', +'NdrFcShort', +'NdrFieldOffset', +'NdrFieldPad', +'NdrMarshCCtxtHdl', +'NdrMarshConfStringHdr', +'NdrMarshSCtxtHdl', +'NdrUnMarshCCtxtHdl', +'NdrUnMarshConfStringHdr', +'NdrUnMarshSCtxtHdl', +'ObjectCloseAuditAlarm', +'ObjectDeleteAuditAlarm', +'ObjectOpenAuditAlarm', +'ObjectPrivilegeAuditAlarm', +'OemToAnsi', +'OemToAnsiBuff', +'OemToChar', +'OemToCharBuff', +'OpenBackupEventLog', +'OpenDesktop', +'OpenEncryptedFileRaw', +'OpenEvent', +'OpenEventLog', +'OpenFileMapping', +'OpenMutex', +'OpenPrinter', +'OpenSCManager', +'OpenSemaphore', +'OpenService', +'OpenWindowStation', +'OutputDebugStr', +'OutputDebugString', +'PageSetupDlg', +'PartitionClassGuid', +'PeekConsoleInput', +'PeekMessage', +'PlaySound', +'PolyTextOut', +'PostAppMessage', +'PostAppMessageA', +'PostAppMessageW', +'PostMessage', +'PostThreadMessage', +'PrintDlg', +'PrintDlgEx', +'PrinterMessageBox', +'PrivateExtractIcons', +'PrivilegedServiceAuditAlarm', +'PropSheet_AddPage', +'PropSheet_Apply', +'PropSheet_CancelToClose', +'PropSheet_Changed', +'PropSheet_GetCurrentPageHwnd', +'PropSheet_GetResult', +'PropSheet_GetTabControl', +'PropSheet_HwndToIndex', +'PropSheet_IdToIndex', +'PropSheet_IndexToHwnd', +'PropSheet_IndexToId', +'PropSheet_IndexToPage', +'PropSheet_InsertPage', +'PropSheet_IsDialogMessage', +'PropSheet_PageToIndex', +'PropSheet_PressButton', +'PropSheet_QuerySiblings', +'PropSheet_RebootSystem', +'PropSheet_RecalcPageSizes', +'PropSheet_RemovePage', +'PropSheet_RestartWindows', +'PropSheet_SetCurSel', +'PropSheet_SetCurSelByID', +'PropSheet_SetFinishText', +'PropSheet_SetHeaderSubTitle', +'PropSheet_SetHeaderTitle', +'PropSheet_SetTitle', +'PropSheet_SetWizButtons', +'PropSheet_UnChanged', +'PropagateResult', +'PropertySheet', +'PtrToInt', +'PtrToLong', +'PtrToShort', +'PtrToUint', +'PtrToUlong', +'PtrToUshort', +'QueryDosDevice', +'QueryServiceConfig', +'QueryServiceConfig2', +'QueryServiceLockStatus', +'ReadConsole', +'ReadConsoleInput', +'ReadConsoleOutput', +'ReadConsoleOutputCharacter', +'ReadEventLog', +'RealGetWindowClass', +'RegConnectRegistry', +'RegCreateKey', +'RegCreateKeyEx', +'RegDeleteKey', +'RegDeleteValue', +'RegEnumKey', +'RegEnumKeyEx', +'RegEnumValue', +'RegLoadKey', +'RegOpenKey', +'RegOpenKeyEx', +'RegQueryInfoKey', +'RegQueryMultipleValues', +'RegQueryValue', +'RegQueryValueEx', +'RegReplaceKey', +'RegRestoreKey', +'RegSaveKey', +'RegSaveKeyEx', +'RegSetValue', +'RegSetValueEx', +'RegUnLoadKey', +'RegisterClass', +'RegisterClassEx', +'RegisterClipboardFormat', +'RegisterDeviceNotification', +'RegisterEventSource', +'RegisterServiceCtrlHandler', +'RegisterServiceCtrlHandlerEx', +'RegisterWindowMessage', +'RemoveDirectory', +'RemoveFontResource', +'RemoveProp', +'ReplaceText', +'ReportEvent', +'ResetDC', +'ResetPrinter', +'ResultFromScode', +'RpcAbnormalTermination', +'RpcAsyncGetCallHandle', +'RpcBindingFromStringBinding', +'RpcBindingInqAuthClient', +'RpcBindingInqAuthClientEx', +'RpcBindingInqAuthInfo', +'RpcBindingInqAuthInfoEx', +'RpcBindingSetAuthInfo', +'RpcBindingSetAuthInfoEx', +'RpcBindingToStringBinding', +'RpcEndExcept', +'RpcEndFinally', +'RpcEpRegister', +'RpcEpRegisterNoReplace', +'RpcExcept', +'RpcExceptionCode', +'RpcFinally', +'RpcMgmtEpEltInqNext', +'RpcMgmtInqServerPrincName', +'RpcNetworkInqProtseqs', +'RpcNetworkIsProtseqValid', +'RpcNsBindingExport', +'RpcNsBindingExportPnP', +'RpcNsBindingImportBegin', +'RpcNsBindingInqEntryName', +'RpcNsBindingLookupBegin', +'RpcNsBindingUnexport', +'RpcNsBindingUnexportPnP', +'RpcNsEntryExpandName', +'RpcNsEntryObjectInqBegin', +'RpcNsGroupDelete', +'RpcNsGroupMbrAdd', +'RpcNsGroupMbrInqBegin', +'RpcNsGroupMbrInqNext', +'RpcNsGroupMbrRemove', +'RpcNsMgmtBindingUnexport', +'RpcNsMgmtEntryCreate', +'RpcNsMgmtEntryDelete', +'RpcNsMgmtEntryInqIfIds', +'RpcNsProfileDelete', +'RpcNsProfileEltAdd', +'RpcNsProfileEltInqBegin', +'RpcNsProfileEltInqNext', +'RpcNsProfileEltRemove', +'RpcProtseqVectorFree', +'RpcServerInqCallAttributes', +'RpcServerInqDefaultPrincName', +'RpcServerRegisterAuthInfo', +'RpcServerUseProtseq', +'RpcServerUseProtseqEp', +'RpcServerUseProtseqEpEx', +'RpcServerUseProtseqEx', +'RpcServerUseProtseqIf', +'RpcServerUseProtseqIfEx', +'RpcStringBindingCompose', +'RpcStringBindingParse', +'RpcStringFree', +'RpcTryExcept', +'RpcTryFinally', +'RtlCopyMemory', +'RtlEqualMemory', +'RtlFillMemory', +'RtlMoveMemory', +'RtlZeroMemory', +'ScrollConsoleScreenBuffer', +'SearchPath', +'SecureZeroMemory', +'SendDlgItemMessage', +'SendMessage', +'SendMessageCallback', +'SendMessageTimeout', +'SendNotifyMessage', +'SetCalendarInfo', +'SetClassLong', +'SetClassLongPtr', +'SetClassLongPtrA', +'SetClassLongPtrW', +'SetComputerName', +'SetConsoleTitle', +'SetCurrentDirectory', +'SetCurrentTime', # Not actually mangled but matches GetCurrentTime +'SetDefaultCommConfig', +'SetDefaultPrinter', +'SetDlgItemText', +'SetEnvironmentStrings', +'SetEnvironmentVariable', +'SetFileAttributes', +'SetFileSecurity', +'SetFileShortName', +'SetFirmwareEnvironmentVariable', +'SetForm', +'SetICMProfile', +'SetJob', +'SetLocaleInfo', +'SetMenuItemInfo', +'SetPort', +'SetPrinter', +'SetPrinterData', +'SetPrinterDataEx', +'SetProp', +'SetSwapAreaSize', +'SetSysModalWindow', +'SetUrlPolicyPermissions', +'SetUserObjectInformation', +'SetVolumeLabel', +'SetWindowLong', +'SetWindowLongPtr', +'SetWindowLongPtrA', +'SetWindowLongPtrW', +'SetWindowText', +'SetWindowsHook', +'SetWindowsHookEx', +'ShellAbout', +'ShellExecute', +'ShellExecuteEx', +'ShellMessageBox', +'Shell_NotifyIcon', +'StartDoc', +'StartDocPrinter', +'StartService', +'StartServiceCtrlDispatcher', +'StoragePortClassGuid', +'SystemParametersInfo', +'TabbedTextOut', +'TapeClassGuid', +'TextOut', +'TranslateAccelerator', +'UintToPtr', +'UlongToHandle', +'UlongToPtr', +'UnlockResource', +'UnlockSegment', +'UnregisterClass', +'UpdateICMRegKey', +'UpdateResource', +'UuidFromString', +'UuidToString', +'VarBoolFromInt', +'VarBoolFromUint', +'VarBstrFromInt', +'VarBstrFromUint', +'VarCyFromInt', +'VarCyFromUint', +'VarDateFromInt', +'VarDateFromUint', +'VarDecFromInt', +'VarDecFromUint', +'VarI1FromInt', +'VarI1FromUint', +'VarI2FromInt', +'VarI2FromUint', +'VarI4FromI4', +'VarI4FromInt', +'VarI4FromUint', +'VarI8FromI8', +'VarI8FromInt', +'VarI8FromUint', +'VarIntFromBool', +'VarIntFromCy', +'VarIntFromDate', +'VarIntFromDec', +'VarIntFromDisp', +'VarIntFromI1', +'VarIntFromI2', +'VarIntFromI4', +'VarIntFromI8', +'VarIntFromR4', +'VarIntFromR8', +'VarIntFromStr', +'VarIntFromUI1', +'VarIntFromUI2', +'VarIntFromUI4', +'VarIntFromUI8', +'VarIntFromUint', +'VarR4FromInt', +'VarR4FromUint', +'VarR8FromInt', +'VarR8FromUint', +'VarUI1FromInt', +'VarUI1FromUint', +'VarUI2FromInt', +'VarUI2FromUint', +'VarUI4FromInt', +'VarUI4FromUI4', +'VarUI4FromUint', +'VarUI8FromUI8', +'VarUintFromBool', +'VarUintFromCy', +'VarUintFromDate', +'VarUintFromDec', +'VarUintFromDisp', +'VarUintFromI1', +'VarUintFromI2', +'VarUintFromI4', +'VarUintFromI8', +'VarUintFromInt', +'VarUintFromR4', +'VarUintFromR8', +'VarUintFromStr', +'VarUintFromUI1', +'VarUintFromUI2', +'VarUintFromUI4', +'VarUintFromUI8', +'VerFindFile', +'VerInstallFile', +'VerLanguageName', +'VerQueryValue', +'VerifyVersionInfo', +'VkKeyScan', +'VkKeyScanEx', +'VolumeClassGuid', +'WaitNamedPipe', +'WinExecError', +'WinHelp', +'WriteConsole', +'WriteConsoleInput', +'WriteConsoleOutput', +'WriteConsoleOutputCharacter', +'WriteOnceDiskClassGuid', +'WritePrivateProfileSection', +'WritePrivateProfileString', +'WritePrivateProfileStruct', +'WriteProfileSection', +'WriteProfileString', +'XcvData', +'Yield' +] + +# Names for which Get is a macro defined by windows.h. +WindowsMangleGets = [ +'AltTabInfo', +'AtomName', +'BValue', +'BinaryType', +'CPInfoEx', +'CValue', +'CalendarInfo', +'CharABCWidths', +'CharABCWidthsFloat', +'CharWidth', +'CharWidth32', +'CharWidthFloat', +'CharacterPlacement', +'ClassInfo', +'ClassInfoEx', +'ClassLong', +'ClassLongPtr', +'ClassLongPtrA', +'ClassLongPtrW', +'ClassName', # GetClassName is left out but not for GetMacro case. +'ClipboardFormatName', +'CommandLine', +'CompressedFileSize', +'ComputerName', +'ConsoleTitle', +'CurrencyFormat', +'CurrentDirectory', +'CurrentTime', +'DateFormat', +'DefaultCommConfig', +'DefaultPrinter', +'DiskFreeSpace', +'DiskFreeSpaceEx', +'DlgItemText', +'DriveType', +'EnhMetaFile', +'EnhMetaFileDescription', +'EnvironmentStringsA', +'EnvironmentVariable', +'ExceptionCode', +'ExceptionInformation', +'ExpandedName', +'FileAttributes', +'FileAttributesEx', +'FileSecurity', +'FileTitle', +'FileVersionInfo', +'FileVersionInfoSize', +'FirmwareEnvironmentVariable', +'Form', +'FreeSpace', +'FullPathName', +'GValue', +'GeoInfo', +'GlyphOutline', +'ICMProfile', +'Job', +'KValue', +'KerningPairs', +'KeyNameText', +'KeyboardLayoutName', +'LocaleInfo', +'LogColorSpace', +'LogicalDriveStrings', +'LongPathName', +'MValue', +'MenuItemInfo', +'MenuString', +'Message', +'MetaFile', +'ModuleFileName', +'ModuleHandle', +'MonitorInfo', +'NamedPipeHandleState', +'NextWindow', +'NumberFormat', +'Object', +'OpenCardName', +'OpenFileName', +'OutlineTextMetrics', +'PrintProcessorDirectory', +'Printer', +'PrinterData', +'PrinterDataEx', +'PrinterDriver', +'PrinterDriverDirectory', +'PrivateProfileInt', +'PrivateProfileSection', +'PrivateProfileSectionNames', +'PrivateProfileString', +'PrivateProfileStruct', +'ProfileInt', +'ProfileSection', +'ProfileString', +'Prop', +'RValue', +'SaveFileName', +'Scode', +'ServiceDisplayName', +'ServiceKeyName', +'ShortPathName', +'StartupInfo', +'StringTypeEx', +'SysModalWindow', +'SystemDirectory', +'SystemWindowsDirectory', +'TabbedTextExtent', +'TempFileName', +'TempPath', +'TextExtentExPoint', +'TextExtentPoint', +'TextExtentPoint32', +'TextFace', +'TextMetrics', +'TimeFormat', +'UrlPolicyPermissions', +'UserName', +'UserObjectInformation', +'VersionEx', +'VolumeInformation', +'WindowLong', +'WindowLongPtr', +'WindowLongPtrA', +'WindowLongPtrW', +'WindowModuleFileName', +'WindowTask', +'WindowText', +'WindowTextLength', +'WindowsDirectory', +'YValue' +] + +# Names for which Set is a macro defined by windows.h. +WindowsMangleSets = [ +'CalendarInfo', +'ClassLong', +'ClassLongPtr', +'ClassLongPtrA', +'ClassLongPtrW', +'ComputerName', +'ConsoleTitle', +'CurrentDirectory', +'CurrentTime', # Not actually mangled but matches GetCurrentTime +'DefaultCommConfig', +'DefaultPrinter', +'DlgItemText', +'EnvironmentStrings', +'EnvironmentVariable', +'FileAttributes', +'FileSecurity', +'FileShortName', +'FirmwareEnvironmentVariable', +'Form', +'ICMProfile', +'Job', +'LocaleInfo', +'MenuItemInfo', +'Port', +'Printer', +'PrinterData', +'PrinterDataEx', +'Prop', +'SwapAreaSize', +'SysModalWindow', +'UrlPolicyPermissions', +'UserObjectInformation', +'VolumeLabel', +'WindowLong', +'WindowLongPtr', +'WindowLongPtrA', +'WindowLongPtrW', +'WindowText', +'WindowsHook', +'WindowsHookEx' +] + +#----------------------------------------------------------------------------- +# Construct a regular expression matching lines declaring methods with +# these names. + +# Beginning of line. +WindowsMangle = '^.*(' + +#----------------------------------------- +# Check explicit method names. +WindowsMangle = WindowsMangle + '[^A-Za-z0-9_](' +sep = '' +for name in WindowsMangleNames: + WindowsMangle = WindowsMangle+sep+name + sep = '|' +WindowsMangle = WindowsMangle+')\s*\(' +#----------------------------------------- + +WindowsMangle = WindowsMangle+'|' + +#----------------------------------------- +# Check names generated by GetMacro calls. +WindowsMangle = WindowsMangle+'vtkGet.*Macro\s*\(\s*(' +sep = '' +for g in WindowsMangleGets: + WindowsMangle = WindowsMangle+sep+g + sep = '|' +WindowsMangle = WindowsMangle+')\s*,' + +#----------------------------------------- +WindowsMangle = WindowsMangle+'|' +#----------------------------------------- + +#----------------------------------------- +# Check names generated by SetMacro calls. +WindowsMangle = WindowsMangle+'vtkSet.*Macro\s*\(\s*(' +sep = '' +for s in WindowsMangleSets: + WindowsMangle = WindowsMangle+sep+s + sep = '|' +WindowsMangle = WindowsMangle+')\s*,' + +#----------------------------------------- +# End of line. +WindowsMangle = WindowsMangle+').*$' + +#----------------------------------------------------------------------------- +# Compile the regular expression. +WindowsMangleRegEx = re.compile(WindowsMangle) diff --git a/Common/vtkAbstractArray.cxx b/Common/vtkAbstractArray.cxx new file mode 100644 index 0000000..07dc6dc --- /dev/null +++ b/Common/vtkAbstractArray.cxx @@ -0,0 +1,206 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAbstractArray.h" +#include "vtkIdList.h" +#include "vtkMath.h" + +#include "vtkDataArray.h" +#include "vtkBitArray.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIntArray.h" +#include "vtkIdTypeArray.h" +#include "vtkLongArray.h" +#include "vtkShortArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +vtkCxxRevisionMacro(vtkAbstractArray, "$Revision: 1.5 $"); + +// Construct object with sane defaults. + +vtkAbstractArray::vtkAbstractArray(vtkIdType vtkNotUsed(numComp)) +{ + this->Size = 0; + this->MaxId = -1; + + this->Name = NULL; + this->DataType = -1; +} + +vtkAbstractArray::~vtkAbstractArray() +{ + if (this->Name != NULL) + { + delete [] this->Name; + } + this->Name = NULL; +} + +void vtkAbstractArray::SetName(const char* name) +{ + if (this->Name != NULL) + { + delete[] this->Name; + } + + this->Name = NULL; + if (name) + { + int size = static_cast(strlen(name)); + this->Name = new char[size+1]; + strcpy(this->Name, name); + } +} + +const char* vtkAbstractArray::GetName() +{ + return this->Name; +} + + +void vtkAbstractArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + const char* name = this->GetName(); + if (name) + { + os << indent << "Name: " << name << "\n"; + } + else + { + os << indent << "Name: (none)\n"; + } + os << indent << "Data type: " << this->GetDataTypeAsString(); + os << indent << "Size: " << this->Size << "\n"; + os << indent << "MaxId: " << this->MaxId << "\n"; +} + +unsigned long vtkAbstractArray::GetDataTypeSize(int type) +{ + switch (type) + { + case VTK_BIT: + return 1; + break; + + case VTK_CHAR: + return sizeof(char); + break; + + case VTK_UNSIGNED_CHAR: + return sizeof(unsigned char); + break; + + case VTK_SHORT: + return sizeof(short); + break; + + case VTK_UNSIGNED_SHORT: + return sizeof(unsigned short); + break; + + case VTK_INT: + return sizeof(int); + break; + + case VTK_UNSIGNED_INT: + return sizeof(unsigned int); + break; + + case VTK_LONG: + return sizeof(long); + break; + + case VTK_UNSIGNED_LONG: + return sizeof(unsigned long); + break; + + case VTK_FLOAT: + return sizeof(float); + break; + + case VTK_DOUBLE: + return sizeof(double); + break; + + case VTK_ID_TYPE: + return sizeof(vtkIdType); + break; + + case VTK_STRING: + return 0; + break; + + default: + vtkGenericWarningMacro(<<"Unsupported data type!"); + } + + return 1; +} + +// ---------------------------------------------------------------------- + +#if 0 +vtkAbstractArray* vtkAbstractArray::CreateArray(int dataType) +{ + switch (dataType) + { + case VTK_BIT: + return vtkBitArray::New(); + + case VTK_CHAR: + return vtkCharArray::New(); + + case VTK_UNSIGNED_CHAR: + return vtkUnsignedCharArray::New(); + + case VTK_SHORT: + return vtkShortArray::New(); + + case VTK_UNSIGNED_SHORT: + return vtkUnsignedShortArray::New(); + + case VTK_INT: + return vtkIntArray::New(); + + case VTK_UNSIGNED_INT: + return vtkUnsignedIntArray::New(); + + case VTK_LONG: + return vtkLongArray::New(); + + case VTK_UNSIGNED_LONG: + return vtkUnsignedLongArray::New(); + + case VTK_FLOAT: + return vtkFloatArray::New(); + + case VTK_DOUBLE: + return vtkDoubleArray::New(); + + case VTK_ID_TYPE: + return vtkIdTypeArray::New(); + + default: + vtkGenericWarningMacro(<<"Unsupported data type! Setting to VTK_DOUBLE"); + return vtkDoubleArray::New(); + } +} +#endif diff --git a/Common/vtkAbstractArray.h b/Common/vtkAbstractArray.h new file mode 100644 index 0000000..5ce1035 --- /dev/null +++ b/Common/vtkAbstractArray.h @@ -0,0 +1,247 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// .NAME vtkAbstractArray - Abstract superclass for all arrays +// +// .SECTION Description +// +// vtkAbstractArray is an abstract superclass for data array objects. +// This class defines an API that all subclasses must support. The +// data type must be assignable and copy-constructible, but no other +// assumptions about its type are made. Most of the subclasses of +// this array deal with numeric data either as scalars or tuples of +// scalars. A program can use the IsNumeric() method to check whether +// an instance of vtkAbstractArray contains numbers. It is also +// possible to test for this by attempting to SafeDownCast an array to +// an instance of vtkDataArray, although this assumes that all numeric +// arrays will always be descended from vtkDataArray. +// +//

+// +// Every array has a character-string name. The naming of the array +// occurs automatically when it is instantiated, but you are free to +// change this name using the SetName() method. (The array name is +// used for data manipulation.) +// +// .SECTION See Also +// vtkDataArray vtkStringArray vtkCellArray + +#ifndef __vtkAbstractArray_h +#define __vtkAbstractArray_h + +#include "vtkObject.h" + +class vtkIdList; +class vtkIdTypeArray; +class vtkDataArray; + +#define VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES 11 + +class VTK_COMMON_EXPORT vtkAbstractArray : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkAbstractArray,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate memory for this array. Delete old storage only if necessary. + // Note that ext is no longer used. + virtual int Allocate(vtkIdType sz, vtkIdType ext=1000) = 0; + + // Description: + // Release storage and reset array to initial state. + virtual void Initialize() = 0; + + // Description: + // Return the underlying data type. An integer indicating data type is + // returned as specified in vtkSetGet.h. + virtual int GetDataType() = 0; + + // Description: + // Return the size of the underlying data type. For a bit, 0 is + // returned. XXX FIXME How will this method behave for + // variably-sized objects? + virtual int GetDataTypeSize() = 0; + static unsigned long GetDataTypeSize(int type); + + // Description: + // Given a list of indices, return an array of values. The caller + // must ensure that enough room has been allocated within the output + // array to hold the data and that the data types match well enough + // to allow any necessary conversions. + virtual void GetValues(vtkIdList *indices, vtkAbstractArray *output) = 0; + + // Description: + // Get the values for the range of indices specified (i.e., p1->p2 + // inclusive). You must insure that the output array has been + // previously allocated with enough space to hold the data and that + // the type of the output array is compatible with the type of this + // array. + virtual void GetValues(vtkIdType p1, vtkIdType p2, vtkAbstractArray *output) = 0; + + // Description: + // Return the number of components in a single element of the array. + // For vtkDataArray and its subclasses, this is the number of + // components in a tuple. Arrays with variable-length elements + // (such as vtkStringArray and vtkCellArray) should return 0. + virtual int GetNumberOfElementComponents() = 0; + + // Description: + // Return the size, in bytes, of the lowest-level element of an + // array. For vtkDataArray and subclasses this is the size of the + // data type. For vtkStringArray, this is + // sizeof(vtkStdString::value_type), which winds up being + // sizeof(char). + virtual int GetElementComponentSize() = 0; + + // Description: + // Return a void pointer. For image pipeline interface and other + // special pointer manipulation. + virtual void *GetVoidPointer(vtkIdType id) = 0; + + // Description: + // Deep copy of data. Implementation left to subclasses, which + // should support as many type conversions as possible given the + // data type. + virtual void DeepCopy(vtkAbstractArray *da) = 0; + + // Description: + // Copy an element from one array into an element on this array. + virtual void CopyValue(int toIndex, int fromIndex, + vtkAbstractArray *sourceArray) = 0; + + // Description: + // Free any unnecessary memory. + // Description: + // Resize object to just fit data requirement. Reclaims extra memory. + virtual void Squeeze() = 0; + + // Description: + // Resize the array while conserving the data. + virtual int Resize(vtkIdType numTuples) = 0; + + // Description: + // Reset to an empty state, without freeing any memory. + void Reset() + {this->MaxId = -1;} + + // Description: + // Return the size of the data. + vtkIdType GetSize() + {return this->Size;} + + // Description: + // What is the maximum id currently in the array. + vtkIdType GetMaxId() + {return this->MaxId;} + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the supplied array. + virtual void SetVoidArray(void *vtkNotUsed(array), + vtkIdType vtkNotUsed(size), + int vtkNotUsed(save)) {}; + + // Description: + // Return the memory in kilobytes consumed by this data array. Used to + // support streaming and reading/writing data. The value returned is + // guaranteed to be greater than or equal to the memory required to + // actually represent the data represented by this object. The + // information returned is valid only after the pipeline has + // been updated. + virtual unsigned long GetActualMemorySize() = 0; + + // Description: + // Set/get array's name + void SetName(const char* name); + const char* GetName(); + + // Description: + // Get the name of a data type as a string. + // XXX FIXME Find this macro and move it into vtkTypeNames.h or + // something. + virtual const char *GetDataTypeAsString( void ) + { return vtkImageScalarTypeNameMacro( this->GetDataType() ); } + + + // This function will only make sense once vtkDataArray is + // re-parented to be a subclass of vtkAbstractArray. It is + // commented out for now. + + // Description: + // Creates an array for dataType where dataType is one of + // VTK_BIT, VTK_CHAR, VTK_UNSIGNED_CHAR, VTK_SHORT, + // VTK_UNSIGNED_SHORT, VTK_INT, VTK_UNSIGNED_INT, VTK_LONG, + // VTK_UNSIGNED_LONG, VTK_DOUBLE, VTK_DOUBLE, VTK_ID_TYPE, + // VTK_STRING, VTK_CELL. + // Note that the data array returned has be deleted by the + // user. + +// static vtkAbstractArray* CreateArray(int dataType); + + // Description: + // This method is here to make backward compatibility easier. It + // must return true if and only if an array contains numeric data. + virtual bool IsNumeric() = 0; + + // Description: + // Flatten an arbitrary array into two separate numeric arrays. The + // first contains all the data in the source array; the second, the + // index of the end of each element. This function is meant to + // assist reading and writing arrays with variable-length elements + // such as vtkStringArray and vtkCellArray. The arrays will be + // created within the method body: the caller is responsible for + // deleting them when no longer needed. + // + //

+ // + // For example, a string array with the elements "This" "Is" "A" + // "Test" would be converted into the following two arrays: + // + // Data: (unsigned char array) ThisIsATest + // Offsets: 3 5 6 10 + // + // vtkDataArray also implements this method, although in practice + // you shouldn't need it. It ignores the offsets array and takes + // its tuple-size information from the data array. + virtual void ConvertToContiguous(vtkDataArray **Data, vtkIdTypeArray **Offsets) = 0; + + // Description: + // This is the inverse of ConvertToContiguous(), above. + virtual void ConvertFromContiguous(vtkDataArray *Data, vtkIdTypeArray *Offsets) = 0; + +protected: + // Construct object with default tuple dimension (number of components) of 1. + vtkAbstractArray(vtkIdType numComp=1); + ~vtkAbstractArray(); + + vtkIdType Size; // allocated size of data + vtkIdType MaxId; // maximum index inserted thus far + + char* Name; + + int DataType; // uses constants in vtkSystemIncludes.h + + +private: + vtkAbstractArray(const vtkAbstractArray&); // Not implemented. + void operator=(const vtkAbstractArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkAbstractTransform.cxx b/Common/vtkAbstractTransform.cxx new file mode 100644 index 0000000..b0009e1 --- /dev/null +++ b/Common/vtkAbstractTransform.cxx @@ -0,0 +1,1131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAbstractTransform.h" + +#include "vtkCriticalSection.h" +#include "vtkDataArray.h" +#include "vtkDebugLeaks.h" +#include "vtkHomogeneousTransform.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkAbstractTransform, "$Revision: 1.26 $"); + +//---------------------------------------------------------------------------- +vtkAbstractTransform::vtkAbstractTransform() +{ + this->MyInverse = NULL; + this->DependsOnInverse = 0; + this->InUnRegister = 0; + this->UpdateMutex = vtkSimpleCriticalSection::New(); + this->InverseMutex = vtkSimpleCriticalSection::New(); +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform::~vtkAbstractTransform() +{ + if (this->MyInverse) + { + this->MyInverse->Delete(); + } + if (this->UpdateMutex) + { + this->UpdateMutex->Delete(); + } + if (this->InverseMutex) + { + this->InverseMutex->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkAbstractTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Inverse: (" << this->MyInverse << ")\n"; +} + +//---------------------------------------------------------------------------- +void vtkAbstractTransform::TransformNormalAtPoint(const double point[3], + const double in[3], + double out[3]) +{ + this->Update(); + + double matrix[3][3]; + double coord[3]; + + this->InternalTransformDerivative(point,coord,matrix); + vtkMath::Transpose3x3(matrix,matrix); + vtkMath::LinearSolve3x3(matrix,in,out); + vtkMath::Normalize(out); +} + +void vtkAbstractTransform::TransformNormalAtPoint(const float point[3], + const float in[3], + float out[3]) +{ + double coord[3]; + double normal[3]; + + coord[0] = point[0]; + coord[1] = point[1]; + coord[2] = point[2]; + + normal[0] = in[0]; + normal[1] = in[1]; + normal[2] = in[2]; + + this->TransformNormalAtPoint(coord,normal,normal); + + out[0] = normal[0]; + out[1] = normal[1]; + out[2] = normal[2]; +} + +//---------------------------------------------------------------------------- +void vtkAbstractTransform::TransformVectorAtPoint(const double point[3], + const double in[3], + double out[3]) +{ + this->Update(); + + double matrix[3][3]; + double coord[3]; + + this->InternalTransformDerivative(point,coord,matrix); + vtkMath::Multiply3x3(matrix,in,out); +} + +void vtkAbstractTransform::TransformVectorAtPoint(const float point[3], + const float in[3], + float out[3]) +{ + double coord[3]; + double vector[3]; + + coord[0] = point[0]; + coord[1] = point[1]; + coord[2] = point[2]; + + vector[0] = in[0]; + vector[1] = in[1]; + vector[2] = in[2]; + + this->TransformVectorAtPoint(coord,vector,vector); + + out[0] = vector[0]; + out[1] = vector[1]; + out[2] = vector[2]; +} + +//---------------------------------------------------------------------------- +// Transform a series of points. +void vtkAbstractTransform::TransformPoints(vtkPoints *in, vtkPoints *out) +{ + this->Update(); + + double point[3]; + vtkIdType i; + vtkIdType n = in->GetNumberOfPoints(); + + for (i = 0; i < n; i++) + { + in->GetPoint(i,point); + this->InternalTransformPoint(point,point); + out->InsertNextPoint(point); + } +} + +//---------------------------------------------------------------------------- +// Transform the normals and vectors using the derivative of the +// transformation. Either inNms or inVrs can be set to NULL. +// Normals are multiplied by the inverse transpose of the transform +// derivative, while vectors are simply multiplied by the derivative. +// Note that the derivative of the inverse transform is simply the +// inverse of the derivative of the forward transform. + +void vtkAbstractTransform::TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs) +{ + this->Update(); + + double matrix[3][3]; + double coord[3]; + + vtkIdType i; + vtkIdType n = inPts->GetNumberOfPoints(); + + for (i = 0; i < n; i++) + { + inPts->GetPoint(i,coord); + this->InternalTransformDerivative(coord,coord,matrix); + outPts->InsertNextPoint(coord); + + if (inVrs) + { + inVrs->GetTuple(i,coord); + vtkMath::Multiply3x3(matrix,coord,coord); + outVrs->InsertNextTuple(coord); + } + + if (inNms) + { + inNms->GetTuple(i,coord); + vtkMath::Transpose3x3(matrix,matrix); + vtkMath::LinearSolve3x3(matrix,coord,coord); + vtkMath::Normalize(coord); + outNms->InsertNextTuple(coord); + } + } +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkAbstractTransform::GetInverse() +{ + this->InverseMutex->Lock(); + if (this->MyInverse == NULL) + { + // we create a circular reference here, it is dealt with in UnRegister + this->MyInverse = this->MakeTransform(); + this->MyInverse->SetInverse(this); + } + this->InverseMutex->Unlock(); + return this->MyInverse; +} + +//---------------------------------------------------------------------------- +void vtkAbstractTransform::SetInverse(vtkAbstractTransform *transform) +{ + if (this->MyInverse == transform) + { + return; + } + + // check type first + if (!transform->IsA(this->GetClassName())) + { + vtkErrorMacro("SetInverse: requires a " << this->GetClassName() << ", a " + << transform->GetClassName() << " is not compatible."); + return; + } + + if (transform->CircuitCheck(this)) + { + vtkErrorMacro("SetInverse: this would create a circular reference."); + return; + } + + if (this->MyInverse) + { + this->MyInverse->Delete(); + } + + transform->Register(this); + this->MyInverse = transform; + + // we are now a special 'inverse transform' + this->DependsOnInverse = (transform != 0); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAbstractTransform::DeepCopy(vtkAbstractTransform *transform) +{ + // check whether we're trying to copy a transform to itself + if (transform == this) + { + return; + } + + // check to see if the transform is the same type as this one + if (!transform->IsA(this->GetClassName())) + { + vtkErrorMacro("DeepCopy: can't copy a " << transform->GetClassName() + << " into a " << this->GetClassName() << "."); + return; + } + + if (transform->CircuitCheck(this)) + { + vtkErrorMacro("DeepCopy: this would create a circular reference."); + return; + } + + // call InternalDeepCopy for subtype + this->InternalDeepCopy(transform); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAbstractTransform::Update() +{ + // locking is require to ensure that the class is thread-safe + this->UpdateMutex->Lock(); + + // check to see if we are a special 'inverse' transform + if (this->DependsOnInverse && + this->MyInverse->GetMTime() >= this->UpdateTime.GetMTime()) + { + vtkDebugMacro("Updating transformation from its inverse"); + this->InternalDeepCopy(this->MyInverse); + this->Inverse(); + vtkDebugMacro("Calling InternalUpdate on the transformation"); + this->InternalUpdate(); + } + // otherwise just check our MTime against our last update + else if (this->GetMTime() >= this->UpdateTime.GetMTime()) + { + // do internal update for subclass + vtkDebugMacro("Calling InternalUpdate on the transformation"); + this->InternalUpdate(); + } + + this->UpdateTime.Modified(); + this->UpdateMutex->Unlock(); +} + +//---------------------------------------------------------------------------- +int vtkAbstractTransform::CircuitCheck(vtkAbstractTransform *transform) +{ + return (transform == this || (this->DependsOnInverse && + this->MyInverse->CircuitCheck(transform))); +} + +//---------------------------------------------------------------------------- +// Need to check inverse's MTime if we are an inverse transform +unsigned long vtkAbstractTransform::GetMTime() +{ + unsigned long mtime = this->vtkObject::GetMTime(); + if (this->DependsOnInverse) + { + unsigned long inverseMTime = this->MyInverse->GetMTime(); + if (inverseMTime > mtime) + { + return inverseMTime; + } + } + + return mtime; +} + +//---------------------------------------------------------------------------- +// We need to handle the circular reference between a transform and its +// inverse. +void vtkAbstractTransform::UnRegister(vtkObjectBase *o) +{ + if (this->InUnRegister) + { // we don't want to go into infinite recursion... + vtkDebugMacro(<<"UnRegister: circular reference eliminated"); + this->ReferenceCount--; + return; + } + + // check to see if the only reason our reference count is not 1 + // is the circular reference from MyInverse + if (this->MyInverse && this->ReferenceCount == 2 && + this->MyInverse->ReferenceCount == 1) + { // break the cycle + vtkDebugMacro(<<"UnRegister: eliminating circular reference"); + this->InUnRegister = 1; + this->MyInverse->UnRegister(this); + this->MyInverse = NULL; + this->InUnRegister = 0; + } + + this->vtkObject::UnRegister(o); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// All of the following methods are for vtkTransformConcatenation +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// A very, very minimal transformation +class vtkSimpleTransform : public vtkHomogeneousTransform +{ +public: + vtkTypeRevisionMacro(vtkSimpleTransform,vtkHomogeneousTransform); + static vtkSimpleTransform *New() { +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkSimpleTransform"); +#endif + return new vtkSimpleTransform; }; + vtkAbstractTransform *MakeTransform() { return vtkSimpleTransform::New(); }; + void Inverse() { this->Matrix->Invert(); this->Modified(); }; +protected: + vtkSimpleTransform() {}; + vtkSimpleTransform(const vtkSimpleTransform&); + void operator=(const vtkSimpleTransform&); +}; + +vtkCxxRevisionMacro(vtkSimpleTransform, "$Revision: 1.26 $"); + +//---------------------------------------------------------------------------- +vtkTransformConcatenation::vtkTransformConcatenation() +{ + this->PreMatrix = NULL; + this->PostMatrix = NULL; + this->PreMatrixTransform = NULL; + this->PostMatrixTransform = NULL; + + this->PreMultiplyFlag = 1; + this->InverseFlag = 0; + + this->NumberOfTransforms = 0; + this->NumberOfPreTransforms = 0; + this->MaxNumberOfTransforms = 0; + + // The transform list is the list of the transforms to be concatenated. + this->TransformList = NULL; +} + +//---------------------------------------------------------------------------- +vtkTransformConcatenation::~vtkTransformConcatenation() +{ + if (this->NumberOfTransforms > 0) + { + for (int i = 0; i < this->NumberOfTransforms; i++) + { + vtkTransformPair *tuple = &this->TransformList[i]; + if (tuple->ForwardTransform) + { + tuple->ForwardTransform->Delete(); + } + if (tuple->InverseTransform) + { + tuple->InverseTransform->Delete(); + } + } + } + if (this->TransformList) + { + delete [] this->TransformList; + } +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::Concatenate(vtkAbstractTransform *trans) +{ + // in case either PreMatrix or PostMatrix is going to be pushed + // into the concatenation from their position at the end + if (this->PreMultiplyFlag && this->PreMatrix) + { + this->PreMatrix = NULL; + this->PreMatrixTransform = NULL; + } + else if (!this->PreMultiplyFlag && this->PostMatrix) + { + this->PostMatrix = NULL; + this->PostMatrixTransform = NULL; + } + + vtkTransformPair *transList = this->TransformList; + int n = this->NumberOfTransforms; + this->NumberOfTransforms++; + + // check to see if we need to allocate more space + if (this->NumberOfTransforms > this->MaxNumberOfTransforms) + { + int nMax = this->MaxNumberOfTransforms + 5; + transList = new vtkTransformPair[nMax]; + for (int i = 0; i < n; i++) + { + transList[i].ForwardTransform = this->TransformList[i].ForwardTransform; + transList[i].InverseTransform = this->TransformList[i].InverseTransform; + } + if (this->TransformList) + { + delete [] this->TransformList; + } + this->TransformList = transList; + this->MaxNumberOfTransforms = nMax; + } + + // add the transform either the beginning or end of the list, + // according to flags + if (this->PreMultiplyFlag ^ this->InverseFlag) + { + for (int i = n; i > 0; i--) + { + transList[i].ForwardTransform = transList[i-1].ForwardTransform; + transList[i].InverseTransform = transList[i-1].InverseTransform; + } + n = 0; + this->NumberOfPreTransforms++; + } + + trans->Register(NULL); + + if (this->InverseFlag) + { + transList[n].ForwardTransform = NULL; + transList[n].InverseTransform = trans; + } + else + { + transList[n].ForwardTransform = trans; + transList[n].InverseTransform = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::Concatenate(const double elements[16]) +{ + // concatenate the matrix with either the Pre- or PostMatrix + if (this->PreMultiplyFlag) + { + if (this->PreMatrix == NULL) + { + // add the matrix to the concatenation + vtkSimpleTransform *mtrans = vtkSimpleTransform::New(); + this->Concatenate(mtrans); + mtrans->Delete(); + this->PreMatrixTransform = mtrans; + this->PreMatrix = mtrans->GetMatrix(); + } + vtkMatrix4x4::Multiply4x4(*this->PreMatrix->Element, elements, + *this->PreMatrix->Element); + this->PreMatrix->Modified(); + this->PreMatrixTransform->Modified(); + } + else + { + if (this->PostMatrix == NULL) + { + // add the matrix to the concatenation + vtkSimpleTransform *mtrans = vtkSimpleTransform::New(); + this->Concatenate(mtrans); + mtrans->Delete(); + this->PostMatrixTransform = mtrans; + this->PostMatrix = mtrans->GetMatrix(); + } + vtkMatrix4x4::Multiply4x4(elements, *this->PostMatrix->Element, + *this->PostMatrix->Element); + this->PostMatrix->Modified(); + this->PostMatrixTransform->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::Translate(double x, double y, double z) +{ + if (x == 0.0 && y == 0.0 && z == 0.0) + { + return; + } + + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + matrix[0][3] = x; + matrix[1][3] = y; + matrix[2][3] = z; + + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::Rotate(double angle, + double x, double y, double z) +{ + if (angle == 0.0 || (x == 0.0 && y == 0.0 && z == 0.0)) + { + return; + } + + // convert to radians + angle = angle*vtkMath::DoubleDegreesToRadians(); + + // make a normalized quaternion + double w = cos(0.5*angle); + double f = sin(0.5*angle)/sqrt(x*x+y*y+z*z); + x *= f; + y *= f; + z *= f; + + // convert the quaternion to a matrix + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + double ww = w*w; + double wx = w*x; + double wy = w*y; + double wz = w*z; + + double xx = x*x; + double yy = y*y; + double zz = z*z; + + double xy = x*y; + double xz = x*z; + double yz = y*z; + + double s = ww - xx - yy - zz; + + matrix[0][0] = xx*2 + s; + matrix[1][0] = (xy + wz)*2; + matrix[2][0] = (xz - wy)*2; + + matrix[0][1] = (xy - wz)*2; + matrix[1][1] = yy*2 + s; + matrix[2][1] = (yz + wx)*2; + + matrix[0][2] = (xz + wy)*2; + matrix[1][2] = (yz - wx)*2; + matrix[2][2] = zz*2 + s; + + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::Scale(double x, double y, double z) +{ + if (x == 1.0 && y == 1.0 && z == 1.0) + { + return; + } + + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + matrix[0][0] = x; + matrix[1][1] = y; + matrix[2][2] = z; + + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::Inverse() +{ + // invert the matrices + if (this->PreMatrix) + { + this->PreMatrix->Invert(); + this->PreMatrixTransform->Modified(); + int i = (this->InverseFlag ? this->NumberOfTransforms-1 : 0); + this->TransformList[i].SwapForwardInverse(); + } + + if (this->PostMatrix) + { + this->PostMatrix->Invert(); + this->PostMatrixTransform->Modified(); + int i = (this->InverseFlag ? 0 : this->NumberOfTransforms-1); + this->TransformList[i].SwapForwardInverse(); + } + + // swap the pre- and post-matrices + vtkMatrix4x4 *tmp = this->PreMatrix; + vtkAbstractTransform *tmp2 = this->PreMatrixTransform; + this->PreMatrix = this->PostMatrix; + this->PreMatrixTransform = this->PostMatrixTransform; + this->PostMatrix = tmp; + this->PostMatrixTransform = tmp2; + + // what used to be pre-transforms are now post-transforms + this->NumberOfPreTransforms = + this->NumberOfTransforms - this->NumberOfPreTransforms; + + this->InverseFlag = !this->InverseFlag; +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::Identity() +{ + // forget the Pre- and PostMatrix + this->PreMatrix = NULL; + this->PostMatrix = NULL; + this->PreMatrixTransform = NULL; + this->PostMatrixTransform = NULL; + + // delete all the transforms + if (this->NumberOfTransforms > 0) + { + for (int i = 0; i < this->NumberOfTransforms; i++) + { + vtkTransformPair *tuple = &this->TransformList[i]; + if (tuple->ForwardTransform) + { + tuple->ForwardTransform->Delete(); + } + if (tuple->InverseTransform) + { + tuple->InverseTransform->Delete(); + } + } + } + this->NumberOfTransforms = 0; + this->NumberOfPreTransforms = 0; +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkTransformConcatenation::GetTransform(int i) +{ + // we walk through the list in reverse order if InverseFlag is set + if (this->InverseFlag) + { + int j = this->NumberOfTransforms-i-1; + vtkTransformPair *tuple = &this->TransformList[j]; + // if inverse is NULL, then get it from the forward transform + if (tuple->InverseTransform == NULL) + { + tuple->InverseTransform = tuple->ForwardTransform->GetInverse(); + tuple->InverseTransform->Register(NULL); + } + return tuple->InverseTransform; + } + else + { + vtkTransformPair *tuple = &this->TransformList[i]; + // if transform is NULL, then get it from its inverse + if (tuple->ForwardTransform == NULL) + { + tuple->ForwardTransform = tuple->InverseTransform->GetInverse(); + tuple->ForwardTransform->Register(NULL); + } + return tuple->ForwardTransform; + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkTransformConcatenation::GetMaxMTime() +{ + unsigned long result = 0; + unsigned long mtime; + + for (int i = 0; i < this->NumberOfTransforms; i++) + { + vtkTransformPair *tuple = &this->TransformList[i]; + if (tuple->ForwardTransform) + { + mtime = tuple->ForwardTransform->GetMTime(); + } + else + { + mtime = tuple->InverseTransform->GetMTime(); + } + + if (mtime > result) + { + result = mtime; + } + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::DeepCopy(vtkTransformConcatenation *concat) +{ + // allocate a larger list if necessary + if (this->MaxNumberOfTransforms < concat->NumberOfTransforms) + { + int newMax = concat->NumberOfTransforms; + vtkTransformPair *newList = new vtkTransformPair[newMax]; + // copy items onto new list + int i = 0; + for (; i < this->NumberOfTransforms; i++) + { + newList[i].ForwardTransform = this->TransformList[i].ForwardTransform; + newList[i].InverseTransform = this->TransformList[i].InverseTransform; + } + for (; i < concat->NumberOfTransforms; i++) + { + newList[i].ForwardTransform = NULL; + newList[i].InverseTransform = NULL; + } + if (this->TransformList) + { + delete [] this->TransformList; + } + this->MaxNumberOfTransforms = newMax; + this->TransformList = newList; + } + + // save the PreMatrix and PostMatrix in case they can be re-used + vtkSimpleTransform *oldPreMatrixTransform = NULL; + vtkSimpleTransform *oldPostMatrixTransform = NULL; + + if (this->PreMatrix) + { + vtkTransformPair *tuple; + if (this->InverseFlag) + { + tuple = &this->TransformList[this->NumberOfTransforms-1]; + tuple->SwapForwardInverse(); + } + else + { + tuple = &this->TransformList[0]; + } + tuple->ForwardTransform = NULL; + if (tuple->InverseTransform) + { + tuple->InverseTransform->Delete(); + tuple->InverseTransform = NULL; + } + oldPreMatrixTransform = (vtkSimpleTransform *)this->PreMatrixTransform; + this->PreMatrixTransform = NULL; + this->PreMatrix = NULL; + } + + if (this->PostMatrix) + { + vtkTransformPair *tuple; + if (this->InverseFlag) + { + tuple = &this->TransformList[0]; + tuple->SwapForwardInverse(); + } + else + { + tuple = &this->TransformList[this->NumberOfTransforms-1]; + } + tuple->ForwardTransform = NULL; + if (tuple->InverseTransform) + { + tuple->InverseTransform->Delete(); + tuple->InverseTransform = NULL; + } + oldPostMatrixTransform = (vtkSimpleTransform *)this->PostMatrixTransform; + this->PostMatrixTransform = NULL; + this->PostMatrix = NULL; + } + + // the PreMatrix and PostMatrix transforms must be DeepCopied, + // not copied by reference, so adjust the copy loop accordingly + int i = 0; + int n = concat->NumberOfTransforms; + if (concat->PreMatrix) + { + if (concat->InverseFlag) { n--; } else { i++; } + } + if (concat->PostMatrix) + { + if (concat->InverseFlag) { i++; } else { n--; } + } + + // copy the transforms by reference + for (; i < n; i++) + { + vtkTransformPair *pair = &this->TransformList[i]; + vtkTransformPair *pair2 = &concat->TransformList[i]; + + if (pair->ForwardTransform != pair2->ForwardTransform) + { + if (pair->ForwardTransform && i < this->NumberOfTransforms) + { + pair->ForwardTransform->Delete(); + } + pair->ForwardTransform = pair2->ForwardTransform; + if (pair->ForwardTransform) + { + pair->ForwardTransform->Register(NULL); + } + } + if (pair->InverseTransform != pair2->InverseTransform) + { + if (pair->InverseTransform && i < this->NumberOfTransforms) + { + pair->InverseTransform->Delete(); + } + pair->InverseTransform = pair2->InverseTransform; + if (pair->InverseTransform) + { + pair->InverseTransform->Register(NULL); + } + } + } + + // delete surplus items from the list + for (i = concat->NumberOfTransforms; i < this->NumberOfTransforms; i++) + { + if (this->TransformList[i].ForwardTransform) + { + this->TransformList[i].ForwardTransform->Delete(); + } + if (this->TransformList[i].InverseTransform) + { + this->TransformList[i].InverseTransform->Delete(); + } + } + + // make a DeepCopy of the PreMatrix transform + if (concat->PreMatrix) + { + i = (concat->InverseFlag ? concat->NumberOfTransforms-1 : 0); + vtkTransformPair *pair = &this->TransformList[i]; + vtkSimpleTransform *mtrans; + + if (concat->InverseFlag == this->InverseFlag) + { + mtrans = (oldPreMatrixTransform ? oldPreMatrixTransform : + vtkSimpleTransform::New()); + oldPreMatrixTransform = NULL; + } + else + { + mtrans = (oldPostMatrixTransform ? oldPostMatrixTransform : + vtkSimpleTransform::New()); + oldPostMatrixTransform = NULL; + } + + this->PreMatrix = mtrans->GetMatrix(); + this->PreMatrix->DeepCopy(concat->PreMatrix); + this->PreMatrixTransform = mtrans; + this->PreMatrixTransform->Modified(); + + if (pair->ForwardTransform) + { + pair->ForwardTransform->Delete(); + pair->ForwardTransform = NULL; + } + if (pair->InverseTransform) + { + pair->InverseTransform->Delete(); + pair->InverseTransform = NULL; + } + + if (concat->InverseFlag) + { + pair->ForwardTransform = NULL; + pair->InverseTransform = this->PreMatrixTransform; + } + else + { + pair->ForwardTransform = this->PreMatrixTransform; + pair->InverseTransform = NULL; + } + } + + // make a DeepCopy of the PostMatrix transform + if (concat->PostMatrix) + { + i = (concat->InverseFlag ? 0 : concat->NumberOfTransforms-1); + vtkTransformPair *pair = &this->TransformList[i]; + vtkSimpleTransform *mtrans; + + if (concat->InverseFlag == this->InverseFlag) + { + mtrans = (oldPostMatrixTransform ? oldPostMatrixTransform : + vtkSimpleTransform::New()); + oldPostMatrixTransform = NULL; + } + else + { + mtrans = (oldPreMatrixTransform ? oldPreMatrixTransform : + vtkSimpleTransform::New()); + oldPreMatrixTransform = NULL; + } + + this->PostMatrix = mtrans->GetMatrix(); + this->PostMatrix->DeepCopy(concat->PostMatrix); + this->PostMatrixTransform = mtrans; + this->PostMatrixTransform->Modified(); + + if (pair->ForwardTransform) + { + pair->ForwardTransform->Delete(); + pair->ForwardTransform = NULL; + } + if (pair->InverseTransform) + { + pair->InverseTransform->Delete(); + pair->InverseTransform = NULL; + } + if (concat->InverseFlag) + { + pair->ForwardTransform = NULL; + pair->InverseTransform = this->PostMatrixTransform; + } + else + { + pair->ForwardTransform = this->PostMatrixTransform; + pair->InverseTransform = NULL; + } + } + + // delete the old PreMatrix and PostMatrix transforms if not re-used + if (oldPreMatrixTransform) + { + oldPreMatrixTransform->Delete(); + } + if (oldPostMatrixTransform) + { + oldPostMatrixTransform->Delete(); + } + + // copy misc. ivars + this->InverseFlag = concat->InverseFlag; + this->PreMultiplyFlag = concat->PreMultiplyFlag; + + this->NumberOfTransforms = concat->NumberOfTransforms; + this->NumberOfPreTransforms = concat->NumberOfPreTransforms; +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenation::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "InverseFlag: " << this->InverseFlag << "\n"; + os << indent << (this->PreMultiplyFlag ? "PreMultiply\n" : "PostMultiply\n"); + os << indent << "NumberOfPreTransforms: " << + this->GetNumberOfPreTransforms() << "\n"; + os << indent << "NumberOfPostTransforms: " << + this->GetNumberOfPostTransforms() << "\n"; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// All of the following methods are for vtkTransformConcatenationStack +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +vtkTransformConcatenationStack::vtkTransformConcatenationStack() +{ + this->StackSize = 0; + this->StackBottom = NULL; + this->Stack = NULL; +} + +//---------------------------------------------------------------------------- +vtkTransformConcatenationStack::~vtkTransformConcatenationStack() +{ + int n = this->Stack-this->StackBottom; + for (int i = 0; i < n; i++) + { + this->StackBottom[i]->Delete(); + } + + if (this->StackBottom) + { + delete [] this->StackBottom; + } +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenationStack::Pop(vtkTransformConcatenation **concat) +{ + // if we're at the bottom of the stack, don't pop + if (this->Stack == this->StackBottom) + { + return; + } + + // get the previous PreMultiplyFlag + int preMultiplyFlag = (*concat)->GetPreMultiplyFlag(); + + // delete the previous item + (*concat)->Delete(); + + // pop new item off the stack + *concat = *--this->Stack; + + // re-set the PreMultiplyFlag + (*concat)->SetPreMultiplyFlag(preMultiplyFlag); +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenationStack::Push(vtkTransformConcatenation **concat) +{ + // check stack size and grow if necessary + if ((this->Stack - this->StackBottom) == this->StackSize) + { + int newStackSize = this->StackSize + 10; + vtkTransformConcatenation **newStackBottom = + new vtkTransformConcatenation *[newStackSize]; + for (int i = 0; i < this->StackSize; i++) + { + newStackBottom[i] = this->StackBottom[i]; + } + if (this->StackBottom) + { + delete [] this->StackBottom; + } + this->StackBottom = newStackBottom; + this->Stack = this->StackBottom+this->StackSize; + this->StackSize = newStackSize; + } + + // add item to the stack + *this->Stack++ = *concat; + + // make a copy of that item the current item + *concat = vtkTransformConcatenation::New(); + (*concat)->DeepCopy(*(this->Stack-1)); +} + +//---------------------------------------------------------------------------- +void vtkTransformConcatenationStack::DeepCopy( + vtkTransformConcatenationStack *stack) +{ + int n = stack->Stack - stack->StackBottom; + int m = this->Stack - this->StackBottom; + + // check to see if we have to grow the stack + if (n > this->StackSize) + { + int newStackSize = n + n%10; + vtkTransformConcatenation **newStackBottom = + new vtkTransformConcatenation *[newStackSize]; + for (int j = 0; j < m; j++) + { + newStackBottom[j] = this->StackBottom[j]; + } + if (this->StackBottom) + { + delete [] this->StackBottom; + } + this->StackBottom = newStackBottom; + this->Stack = this->StackBottom+this->StackSize; + this->StackSize = newStackSize; + } + + // delete surplus items + for (int l = n; l < m; l++) + { + (*--this->Stack)->Delete(); + } + + // allocate new items + for (int i = m; i < n; i++) + { + *this->Stack++ = vtkTransformConcatenation::New(); + } + + // deep copy the items + for (int k = 0; k < n; k++) + { + this->StackBottom[k]->DeepCopy(stack->StackBottom[k]); + } +} + +#ifndef VTK_LEGACY_REMOVE +void vtkAbstractTransform::Identity() +{ + vtkWarningMacro("vtkAbstractTransform::Identity() is deprecated"); +} +#endif diff --git a/Common/vtkAbstractTransform.h b/Common/vtkAbstractTransform.h new file mode 100644 index 0000000..0d6b1a3 --- /dev/null +++ b/Common/vtkAbstractTransform.h @@ -0,0 +1,417 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAbstractTransform - superclass for all geometric transformations +// .SECTION Description +// vtkAbstractTransform is the superclass for all VTK geometric +// transformations. The VTK transform hierarchy is split into two +// major branches: warp transformations and homogeneous (including linear) +// transformations. The latter can be represented in terms of a 4x4 +// transformation matrix, the former cannot. +//

Transformations can be pipelined through two mechanisms: +//

1) GetInverse() returns the pipelined +// inverse of a transformation i.e. if you modify the original transform, +// any transform previously returned by the GetInverse() method will +// automatically update itself according to the change. +//

2) You can do pipelined concatenation of transformations through +// the vtkGeneralTransform class, the vtkPerspectiveTransform class, +// or the vtkTransform class. +// .SECTION see also +// vtkGeneralTransform vtkWarpTransform vtkHomogeneousTransform +// vtkLinearTransform vtkIdentityTransform +// vtkTransformPolyDataFilter vtkTransformFilter vtkImageReslice +// vtkImplicitFunction + + +#ifndef __vtkAbstractTransform_h +#define __vtkAbstractTransform_h + +#include "vtkObject.h" + +class vtkDataArray; +class vtkMatrix4x4; +class vtkPoints; +class vtkSimpleCriticalSection; + +class VTK_COMMON_EXPORT vtkAbstractTransform : public vtkObject +{ +public: + + vtkTypeRevisionMacro(vtkAbstractTransform,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Apply the transformation to a coordinate. You can use the same + // array to store both the input and output point. + void TransformPoint(const float in[3], float out[3]) { + this->Update(); this->InternalTransformPoint(in,out); }; + + // Description: + // Apply the transformation to a double-precision coordinate. + // You can use the same array to store both the input and output point. + void TransformPoint(const double in[3], double out[3]) { + this->Update(); this->InternalTransformPoint(in,out); }; + + // Description: + // Apply the transformation to a double-precision coordinate. + // Use this if you are programming in Python, tcl or Java. + double *TransformPoint(double x, double y, double z) { + return this->TransformDoublePoint(x,y,z); } + double *TransformPoint(const double point[3]) { + return this->TransformPoint(point[0],point[1],point[2]); }; + + // Description: + // Apply the transformation to an (x,y,z) coordinate. + // Use this if you are programming in Python, tcl or Java. + float *TransformFloatPoint(float x, float y, float z) { + this->InternalFloatPoint[0] = x; + this->InternalFloatPoint[1] = y; + this->InternalFloatPoint[2] = z; + this->TransformPoint(this->InternalFloatPoint,this->InternalFloatPoint); + return this->InternalFloatPoint; }; + float *TransformFloatPoint(const float point[3]) { + return this->TransformFloatPoint(point[0],point[1],point[2]); }; + + // Description: + // Apply the transformation to a double-precision (x,y,z) coordinate. + // Use this if you are programming in Python, tcl or Java. + double *TransformDoublePoint(double x, double y, double z) { + this->InternalDoublePoint[0] = x; + this->InternalDoublePoint[1] = y; + this->InternalDoublePoint[2] = z; + this->TransformPoint(this->InternalDoublePoint,this->InternalDoublePoint); + return this->InternalDoublePoint; }; + double *TransformDoublePoint(const double point[3]) { + return this->TransformDoublePoint(point[0],point[1],point[2]); }; + + // Description: + // Apply the transformation to a normal at the specified vertex. If the + // transformation is a vtkLinearTransform, you can use TransformNormal() + // instead. + void TransformNormalAtPoint(const float point[3], const float in[3], + float out[3]); + void TransformNormalAtPoint(const double point[3], const double in[3], + double out[3]); + + double *TransformNormalAtPoint(const double point[3], + const double normal[3]) { + this->TransformNormalAtPoint(point,normal,this->InternalDoublePoint); + return this->InternalDoublePoint; }; + + // Description: + // Apply the transformation to a double-precision normal at the specified + // vertex. If the transformation is a vtkLinearTransform, you can use + // TransformDoubleNormal() instead. + double *TransformDoubleNormalAtPoint(const double point[3], + const double normal[3]) { + this->TransformNormalAtPoint(point,normal,this->InternalDoublePoint); + return this->InternalDoublePoint; }; + + // Description: + // Apply the transformation to a single-precision normal at the specified + // vertex. If the transformation is a vtkLinearTransform, you can use + // TransformFloatNormal() instead. + float *TransformFloatNormalAtPoint(const float point[3], + const float normal[3]) { + this->TransformNormalAtPoint(point,normal,this->InternalFloatPoint); + return this->InternalFloatPoint; }; + + // Description: + // Apply the transformation to a vector at the specified vertex. If the + // transformation is a vtkLinearTransform, you can use TransformVector() + // instead. + void TransformVectorAtPoint(const float point[3], const float in[3], + float out[3]); + void TransformVectorAtPoint(const double point[3], const double in[3], + double out[3]); + + double *TransformVectorAtPoint(const double point[3], + const double vector[3]) { + this->TransformVectorAtPoint(point,vector,this->InternalDoublePoint); + return this->InternalDoublePoint; }; + + // Description: + // Apply the transformation to a double-precision vector at the specified + // vertex. If the transformation is a vtkLinearTransform, you can use + // TransformDoubleVector() instead. + double *TransformDoubleVectorAtPoint(const double point[3], + const double vector[3]) { + this->TransformVectorAtPoint(point,vector,this->InternalDoublePoint); + return this->InternalDoublePoint; }; + + // Description: + // Apply the transformation to a single-precision vector at the specified + // vertex. If the transformation is a vtkLinearTransform, you can use + // TransformFloatVector() instead. + float *TransformFloatVectorAtPoint(const float point[3], + const float vector[3]) { + this->TransformVectorAtPoint(point,vector,this->InternalFloatPoint); + return this->InternalFloatPoint; }; + + // Description: + // Apply the transformation to a series of points, and append the + // results to outPts. + virtual void TransformPoints(vtkPoints *inPts, vtkPoints *outPts); + + // Description: + // Apply the transformation to a combination of points, normals + // and vectors. + virtual void TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs); + + // Description: + // Get the inverse of this transform. If you modify this transform, + // the returned inverse transform will automatically update. If you + // want the inverse of a vtkTransform, you might want to use + // GetLinearInverse() instead which will type cast the result from + // vtkAbstractTransform to vtkLinearTransform. + vtkAbstractTransform *GetInverse(); + + // Description: + // Set a transformation that this transform will be the inverse of. + // This transform will automatically update to agree with the + // inverse transform that you set. + void SetInverse(vtkAbstractTransform *transform); + + // Description: + // Invert the transformation. + virtual void Inverse() = 0; + + // Description: + // Copy this transform from another of the same type. + void DeepCopy(vtkAbstractTransform *); + + // Description: + // Update the transform to account for any changes which + // have been made. You do not have to call this method + // yourself, it is called automatically whenever the + // transform needs an update. + void Update(); + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + virtual void InternalTransformPoint(const float in[3], float out[3]) = 0; + virtual void InternalTransformPoint(const double in[3], double out[3]) = 0; + + // Description: + // This will transform a point and, at the same time, calculate a + // 3x3 Jacobian matrix that provides the partial derivatives of the + // transformation at that point. This method does not call Update. + // Meant for use only within other VTK classes. + virtual void InternalTransformDerivative(const float in[3], float out[3], + float derivative[3][3]) = 0; + virtual void InternalTransformDerivative(const double in[3], double out[3], + double derivative[3][3]) = 0; + + // Description: + // Make another transform of the same type. + virtual vtkAbstractTransform *MakeTransform() = 0; + + // Description: + // Check for self-reference. Will return true if concatenating + // with the specified transform, setting it to be our inverse, + // or setting it to be our input will create a circular reference. + // CircuitCheck is automatically called by SetInput(), SetInverse(), + // and Concatenate(vtkXTransform *). Avoid using this function, + // it is experimental. + virtual int CircuitCheck(vtkAbstractTransform *transform); + + // Description: + // Override GetMTime necessary because of inverse transforms. + unsigned long GetMTime(); + + // Description: + // Needs a special UnRegister() implementation to avoid + // circular references. + virtual void UnRegister(vtkObjectBase *O); + + // Description: + // @deprecated This method is deprecated in the base class. It is + // still valid to use it on many of the specialized classes. + VTK_LEGACY(void Identity()); + +protected: + vtkAbstractTransform(); + ~vtkAbstractTransform(); + + // Description: + // Perform any subclass-specific Update. + virtual void InternalUpdate() {}; + + // Description: + // Perform any subclass-specific DeepCopy. + virtual void InternalDeepCopy(vtkAbstractTransform *) {}; + + float InternalFloatPoint[3]; + double InternalDoublePoint[3]; + +private: + +//BTX + // We need to record the time of the last update, and we also need + // to do mutex locking so updates don't collide. These are private + // because Update() is not virtual. + // If DependsOnInverse is set, then this transform object will + // check its inverse on every update, and update itself accordingly + // if necessary. +//ETX + vtkTimeStamp UpdateTime; + vtkSimpleCriticalSection *UpdateMutex; + vtkSimpleCriticalSection *InverseMutex; + int DependsOnInverse; + +//BTX + // MyInverse is a transform which is the inverse of this one. +//ETX + vtkAbstractTransform *MyInverse; + + int InUnRegister; + +private: + vtkAbstractTransform(const vtkAbstractTransform&); // Not implemented. + void operator=(const vtkAbstractTransform&); // Not implemented. +}; + +//BTX +//------------------------------------------------------------------------- +// A simple data structure to hold both a transform and its inverse. +// One of ForwardTransform or InverseTransform might be NULL, +// and must be acquired by calling GetInverse() on the other. +class vtkTransformPair +{ +public: + vtkAbstractTransform *ForwardTransform; + vtkAbstractTransform *InverseTransform; + + void SwapForwardInverse() { + vtkAbstractTransform *tmp = this->ForwardTransform; + this->ForwardTransform = this->InverseTransform; + this->InverseTransform = tmp; }; +}; + +// A helper class (not derived from vtkObject) to store a series of +// transformations in a pipelined concatenation. +class VTK_COMMON_EXPORT vtkTransformConcatenation +{ +public: + static vtkTransformConcatenation *New() { + return new vtkTransformConcatenation(); }; + void Delete() { delete this; }; + + // add a transform to the list according to Pre/PostMultiply semantics + void Concatenate(vtkAbstractTransform *transform); + + // concatenate with a matrix according to Pre/PostMultiply semantics + void Concatenate(const double elements[16]); + + // set the PreMultiply flag + void SetPreMultiplyFlag(int flag) { this->PreMultiplyFlag = flag; }; + int GetPreMultiplyFlag() { return this->PreMultiplyFlag; }; + + // the three basic linear transformations + void Translate(double x, double y, double z); + void Rotate(double angle, double x, double y, double z); + void Scale(double x, double y, double z); + + // invert the concatenation + void Inverse(); + + // get the inverse flag + int GetInverseFlag() { return this->InverseFlag; }; + + // identity simply clears the transform list + void Identity(); + + // copy the list + void DeepCopy(vtkTransformConcatenation *transform); + + // the number of stored transforms + int GetNumberOfTransforms() { return this->NumberOfTransforms; }; + + // the number of transforms that were pre-concatenated (note that + // whenever Iverse() is called, the pre-concatenated and + // post-concatenated transforms are switched) + int GetNumberOfPreTransforms() { return this->NumberOfPreTransforms; }; + + // the number of transforms that were post-concatenated. + int GetNumberOfPostTransforms() { + return this->NumberOfTransforms-this->NumberOfPreTransforms; }; + + // get one of the transforms + vtkAbstractTransform *GetTransform(int i); + + // get maximum MTime of all transforms + unsigned long GetMaxMTime(); + + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkTransformConcatenation(); + ~vtkTransformConcatenation(); + + int InverseFlag; + int PreMultiplyFlag; + + vtkMatrix4x4 *PreMatrix; + vtkMatrix4x4 *PostMatrix; + vtkAbstractTransform *PreMatrixTransform; + vtkAbstractTransform *PostMatrixTransform; + + int NumberOfTransforms; + int NumberOfPreTransforms; + int MaxNumberOfTransforms; + vtkTransformPair *TransformList; +}; + +// A helper class (not derived from vtkObject) to store a stack of +// concatenations. +class VTK_COMMON_EXPORT vtkTransformConcatenationStack +{ +public: + static vtkTransformConcatenationStack *New() { + return new vtkTransformConcatenationStack(); }; + void Delete() { delete this; }; + + // pop will pop delete 'concat', then pop the + // top item on the stack onto 'concat'. + void Pop(vtkTransformConcatenation **concat); + + // push will move 'concat' onto the stack, and + // make 'concat' a copy of its previous self + void Push(vtkTransformConcatenation **concat); + + void DeepCopy(vtkTransformConcatenationStack *stack); + +protected: + vtkTransformConcatenationStack(); + ~vtkTransformConcatenationStack(); + + int StackSize; + vtkTransformConcatenation **Stack; + vtkTransformConcatenation **StackBottom; +}; + +//ETX + +#endif + + + + + diff --git a/Common/vtkAmoebaMinimizer.cxx b/Common/vtkAmoebaMinimizer.cxx new file mode 100644 index 0000000..5b4c873 --- /dev/null +++ b/Common/vtkAmoebaMinimizer.cxx @@ -0,0 +1,754 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAmoebaMinimizer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAmoebaMinimizer.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkAmoebaMinimizer, "$Revision: 1.4.14.1 $"); +vtkStandardNewMacro(vtkAmoebaMinimizer); + +//---------------------------------------------------------------------------- +vtkAmoebaMinimizer::vtkAmoebaMinimizer() +{ + this->Function = NULL; + this->FunctionArg = NULL; + this->FunctionArgDelete = NULL; + + this->NumberOfParameters = 0; + this->ParameterNames = NULL; + this->ParameterValues = NULL; + this->ParameterScales = NULL; + + this->FunctionValue = 0.0; + + this->Tolerance = 1e-4; + this->MaxIterations = 1000; + this->Iterations = 0; + this->FunctionEvaluations = 0; + + // specific to the amoeba + this->AmoebaVertices = NULL; + this->AmoebaValues = NULL; + this->AmoebaSum = NULL; + this->AmoebaNStepsNoImprovement = 0; +} + +//---------------------------------------------------------------------------- +vtkAmoebaMinimizer::~vtkAmoebaMinimizer() +{ + this->TerminateAmoeba(); + + if ((this->FunctionArg) && (this->FunctionArgDelete)) + { + (*this->FunctionArgDelete)(this->FunctionArg); + } + this->FunctionArg = NULL; + this->FunctionArgDelete = NULL; + this->Function = NULL; + + if (this->ParameterNames) + { + for (int i = 0; i < this->NumberOfParameters; i++) + { + if (this->ParameterNames[i]) + { + delete [] this->ParameterNames[i]; + } + } + delete [] this->ParameterNames; + this->ParameterNames = NULL; + } + if (this->ParameterValues) + { + delete [] this->ParameterValues; + this->ParameterValues = NULL; + } + if (this->ParameterScales) + { + delete [] this->ParameterScales; + this->ParameterScales = NULL; + } + + this->NumberOfParameters = 0; +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "NumberOfParameters: " << this->GetNumberOfParameters() << "\n"; + if (this->NumberOfParameters > 0) + { + int i; + + os << indent << "ParameterValues: \n"; + for (i = 0; i < this->NumberOfParameters; i++) + { + const char *name = this->GetParameterName(i); + os << indent << " "; + if (name) + { + os << name << ": "; + } + else + { + os << i << ": "; + } + os << this->GetParameterValue(i) << "\n"; + } + + os << indent << "ParameterScales: \n"; + for (i = 0; i < this->NumberOfParameters; i++) + { + const char *name = this->GetParameterName(i); + os << indent << " "; + if (name) + { + os << name << ": "; + } + else + { + os << i << ": "; + } + os << this->GetParameterScale(i) << "\n"; + } + } + + os << indent << "FunctionValue: " << this->GetFunctionValue() << "\n"; + os << indent << "FunctionEvaluations: " << this->GetFunctionEvaluations() + << "\n"; + os << indent << "Iterations: " << this->GetIterations() << "\n"; + os << indent << "MaxIterations: " << this->GetMaxIterations() << "\n"; + os << indent << "Tolerance: " << this->GetTolerance() << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::SetFunction(void (*f)(void *), void *arg) +{ + if ( f != this->Function || arg != this->FunctionArg ) + { + // delete the current arg if there is one and a delete meth + if ((this->FunctionArg) && (this->FunctionArgDelete)) + { + (*this->FunctionArgDelete)(this->FunctionArg); + } + this->Function = f; + this->FunctionArg = arg; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::SetFunctionArgDelete(void (*f)(void *)) +{ + if ( f != this->FunctionArgDelete) + { + this->FunctionArgDelete = f; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +double vtkAmoebaMinimizer::GetParameterValue(const char *name) +{ + for (int i = 0; i < this->NumberOfParameters; i++) + { + if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0) + { + return this->ParameterValues[i]; + } + } + vtkErrorMacro("GetParameterValue: no parameter named " << name); + return 0.0; +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::SetParameterValue(const char *name, double val) +{ + int i; + + for (i = 0; i < this->NumberOfParameters; i++) + { + if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0) + { + break; + } + } + + this->SetParameterValue(i, val); + + if (!this->ParameterNames[i]) + { + char *cp = new char[strlen(name)+8]; + strcpy(cp,name); + this->ParameterNames[i] = cp; + } +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::SetParameterValue(int i, double val) +{ + if (i < this->NumberOfParameters) + { + if (this->ParameterValues[i] != val) + { + this->ParameterValues[i] = val; + this->Iterations = 0; // reset to start + this->FunctionEvaluations = 0; + this->Modified(); + } + return; + } + + int n = this->NumberOfParameters + 1; + + char **newParameterNames = new char *[n]; + double *newParameterValues = new double[n]; + double *newParameterScales = new double[n]; + + for (int j = 0; j < this->NumberOfParameters; j++) + { + newParameterNames[j] = this->ParameterNames[j]; + this->ParameterNames[j] = NULL; // or else it will be deleted in Initialize + newParameterValues[j] = this->ParameterValues[j]; + newParameterScales[j] = this->ParameterScales[j]; + } + + newParameterNames[n-1] = 0; + newParameterValues[n-1] = val; + newParameterScales[n-1] = 1.0; + + this->Initialize(); + + this->NumberOfParameters = n; + this->ParameterNames = newParameterNames; + this->ParameterValues = newParameterValues; + this->ParameterScales = newParameterScales; + + this->Iterations = 0; // reset to start + this->FunctionEvaluations = 0; +} + +//---------------------------------------------------------------------------- +double vtkAmoebaMinimizer::GetParameterScale(const char *name) +{ + for (int i = 0; i < this->NumberOfParameters; i++) + { + if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0) + { + return this->ParameterScales[i]; + } + } + vtkErrorMacro("GetParameterScale: no parameter named " << name); + return 1.0; +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::SetParameterScale(const char *name, double scale) +{ + for (int i = 0; i < this->NumberOfParameters; i++) + { + if (this->ParameterNames[i] && strcmp(name,this->ParameterNames[i]) == 0) + { + this->SetParameterScale(i, scale); + return; + } + } + vtkErrorMacro("SetParameterScale: no parameter named " << name); +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::SetParameterScale(int i, double scale) +{ + if (i < 0 || i > this->NumberOfParameters) + { + vtkErrorMacro("SetParameterScale: parameter number out of range: " << i); + return; + } + + if (this->ParameterScales[i] != scale) + { + this->ParameterScales[i] = scale; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// reset the number of parameters to zero +void vtkAmoebaMinimizer::Initialize() +{ + if (this->ParameterNames) + { + for (int i = 0; i < this->NumberOfParameters; i++) + { + if (this->ParameterNames[i]) + { + delete [] this->ParameterNames[i]; + } + } + delete [] this->ParameterNames; + this->ParameterNames = 0; + } + if (this->ParameterValues) + { + delete [] this->ParameterValues; + this->ParameterValues = 0; + } + if (this->ParameterScales) + { + delete [] this->ParameterScales; + this->ParameterScales = 0; + } + + this->NumberOfParameters = 0; + this->Iterations = 0; + this->FunctionEvaluations = 0; + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::EvaluateFunction() +{ + if (this->Function) + { + this->Function(this->FunctionArg); + } + this->FunctionEvaluations++; +} + +//---------------------------------------------------------------------------- +int vtkAmoebaMinimizer::Iterate() +{ + if (this->Iterations == 0) + { + if (!this->Function) + { + vtkErrorMacro("Iterate: Function is NULL"); + return 0; + } + this->InitializeAmoeba(); + } + + int improved = this->PerformAmoeba(); + this->GetAmoebaParameterValues(); + this->Iterations++; + + return improved; +} + +//---------------------------------------------------------------------------- +void vtkAmoebaMinimizer::Minimize() +{ + if (this->Iterations == 0) + { + if (!this->Function) + { + vtkErrorMacro("Minimize: Function is NULL"); + return; + } + this->InitializeAmoeba(); + } + + for (; this->Iterations < this->MaxIterations; this->Iterations++) + { + int improved = this->PerformAmoeba(); + if (!improved) + { + break; + } + } + + this->GetAmoebaParameterValues(); +} + +/* ---------------------------------------------------------------------------- +@COPYRIGHT : + Copyright 1993,1994,1995 David MacDonald, + McConnell Brain Imaging Centre, + Montreal Neurological Institute, McGill University. + 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. The author and McGill University + make no representations about the suitability of this + software for any purpose. It is provided "as is" without + express or implied warranty. +---------------------------------------------------------------------------- */ + +/* ------------------------------------------------ + This code has been modified from the original. Several macros + have been expanded, functions have been renamed to match VTK + conventions, and the formatting has been changed. +*/ + +#define VTK_AMOEBA_FLIP_RATIO 1.0 +#define VTK_AMOEBA_CONTRACT_RATIO 0.5 +#define VTK_AMOEBA_STRETCH_RATIO 2.0 + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : vtkAmoebaNumericallyClose +@INPUT : n1 + n2 + threshold_ratio +@OUTPUT : +@RETURNS : true if the numbers are within the threshold ratio +@DESCRIPTION: Decides if two numbers are close to each other. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : 1993 David MacDonald +@MODIFIED : 2002 David Gobbi +---------------------------------------------------------------------------- */ + +#define VTK_AMOEBA_SMALLEST 1.0e-20 + +static int vtkAmoebaNumericallyClose(double n1, + double n2, + double threshold_ratio ) +{ + double avg, diff, abs_n1, abs_n2; + + diff = n1 - n2; + if( diff < 0.0 ) + { + diff = -diff; + } + + abs_n1 = (n1 < 0.0 ? -n1 : n1); + abs_n2 = (n2 < 0.0 ? -n2 : n2); + + if( abs_n1 < VTK_AMOEBA_SMALLEST || abs_n2 < VTK_AMOEBA_SMALLEST ) + { + return( abs_n1 < threshold_ratio && abs_n2 < threshold_ratio ); + } + + avg = (n1 + n2) / 2.0; + + if( avg == 0.0 ) + { + return( diff <= threshold_ratio ); + } + + if( avg < 0.0 ) + { + avg = -avg; + } + + return( (diff / avg) <= threshold_ratio ); +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : InitializeAmoeba +@INPUT : +@OUTPUT : +@RETURNS : +@DESCRIPTION: Initializes the amoeba structure to minimize the function. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : 1993 David MacDonald +@MODIFIED : 2002 David Gobbi +---------------------------------------------------------------------------- */ + +void vtkAmoebaMinimizer::InitializeAmoeba() +{ + int i, j; + + this->TerminateAmoeba(); + + int n_parameters = this->NumberOfParameters; + this->AmoebaNStepsNoImprovement = 0; + this->AmoebaVertices = new double *[n_parameters+1]; + this->AmoebaVertices[0] = new double[n_parameters*(n_parameters+1)]; + + for( i = 1 ; i < n_parameters+1 ; i++) + { + this->AmoebaVertices[i] = this->AmoebaVertices[i-1] + n_parameters; + } + + this->AmoebaValues = new double[n_parameters+1]; + + this->AmoebaSum = new double[n_parameters]; + + for (j = 0; j < n_parameters; j++) + { + this->AmoebaSum[j] = 0.0; + } + + for( i = 0 ; i < n_parameters+1 ; i++ ) + { + for( j = 0; j < n_parameters ; j++ ) + { + this->AmoebaVertices[i][j] = this->ParameterValues[j]; + if( i > 0 && j == i - 1 ) + { + this->AmoebaVertices[i][j] = + this->ParameterValues[j] + this->ParameterScales[j]; + } + this->AmoebaSum[j] += this->ParameterValues[j]; + } + } + for( i = 0 ; i < n_parameters+1 ; i++ ) + { + for( j = 0; j < n_parameters; j++ ) + { + this->ParameterValues[j] = this->AmoebaVertices[i][j]; + } + this->EvaluateFunction(); + this->AmoebaValues[i] = this->FunctionValue; + } + + for ( j = 0 ; j < n_parameters ; j++ ) + { + this->ParameterValues[j] = this->AmoebaVertices[0][j]; + } +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : GetAmoebaParameterValues +@INPUT : +@OUTPUT : +@RETURNS : +@DESCRIPTION: Passes back the current position of the amoeba (best value), + and returns the function value at that point. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : 1993 David MacDonald +@MODIFIED : 2002 David Gobbi +---------------------------------------------------------------------------- */ + +void vtkAmoebaMinimizer::GetAmoebaParameterValues() +{ + int i, j, low; + + low = 0; + for( i = 1 ; i < this->NumberOfParameters+1 ; i++ ) + { + if( this->AmoebaValues[i] < this->AmoebaValues[low] ) + { + low = i; + } + } + + for( j = 0 ; j < this->NumberOfParameters ; j++ ) + { + this->ParameterValues[j] = this->AmoebaVertices[low][j]; + } + + this->FunctionValue = this->AmoebaValues[low]; +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : TerminateAmoeba +@INPUT : +@OUTPUT : +@RETURNS : +@DESCRIPTION: Frees the amoeba. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : 1993 David MacDonald +@MODIFIED : 2002 David Gobbi +---------------------------------------------------------------------------- */ + +void vtkAmoebaMinimizer::TerminateAmoeba() +{ + if (this->AmoebaVertices) + { + delete [] this->AmoebaVertices[0]; + delete [] this->AmoebaVertices; + this->AmoebaVertices = NULL; + } + if (this->AmoebaValues) + { + delete [] this->AmoebaValues; + this->AmoebaValues = NULL; + } + if (this->AmoebaSum) + { + delete [] this->AmoebaSum; + this->AmoebaSum = NULL; + } +} + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : TryAmoeba +@INPUT : sum + high + fac +@OUTPUT : +@RETURNS : value +@DESCRIPTION: Does a modification to the high vertex of the amoeba and + returns the value of the new point. If the new point is + better (smaller value), it replaces the high vertex of the + amoeba. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : 1993 David MacDonald +@MODIFIED : 2002 David Gobbi +---------------------------------------------------------------------------- */ + +double vtkAmoebaMinimizer::TryAmoeba(double sum[], + int high, + double fac ) +{ + int j; + double y_try, fac1, fac2; + double *parameters; + + parameters = this->ParameterValues; + + fac1 = (1.0 - fac) / this->NumberOfParameters; + fac2 = fac - fac1; + + for( j = 0 ; j < this->NumberOfParameters ; j++ ) + { + parameters[j] = (sum[j] * fac1 + this->AmoebaVertices[high][j] * fac2); + } + + this->EvaluateFunction(); + y_try = this->FunctionValue; + + if( y_try < this->AmoebaValues[high] ) + { + this->AmoebaValues[high] = y_try; + for( j = 0 ; j < this->NumberOfParameters ; j++ ) + { + sum[j] += parameters[j] - this->AmoebaVertices[high][j]; + this->AmoebaVertices[high][j] = parameters[j]; + } + } + + return( y_try ); +} + +#define N_STEPS_NO_IMPROVEMENT 20 + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : PerformAmoeba +@INPUT : +@OUTPUT : + +@RETURNS : true if numerically significant improvement +@DESCRIPTION: Performs one iteration of an amoeba, returning true if a + numerically significant improvement has been found recently. + Even if it returns 0, you can keep calling this function, + since it may be contracting with no improvement, but will + eventually shrink small enough to get an improvment. +@METHOD : +@GLOBALS : +@CALLS : +@CREATED : 1993 David MacDonald +@MODIFIED : 2002 David Gobbi +---------------------------------------------------------------------------- */ + +int vtkAmoebaMinimizer::PerformAmoeba() +{ + int i, j, low, high, next_high; + double y_try, y_save; + int improvement_found; + + improvement_found = 1; + + if( this->AmoebaValues[0] > this->AmoebaValues[1] ) + { + high = 0; + next_high = 1; + } + else + { + high = 1; + next_high = 0; + } + + low = next_high; + + for( i = 2 ; i < this->NumberOfParameters+1 ; i++ ) + { + if( this->AmoebaValues[i] < this->AmoebaValues[low] ) + { + low = i; + } + else if( this->AmoebaValues[i] > this->AmoebaValues[high] ) + { + next_high = high; + high = i; + } + else if( this->AmoebaValues[i] > this->AmoebaValues[next_high] ) + { + next_high = i; + } + } + + if( vtkAmoebaNumericallyClose( this->AmoebaValues[low], + this->AmoebaValues[high], + this->Tolerance ) ) + { + ++this->AmoebaNStepsNoImprovement; + if( this->AmoebaNStepsNoImprovement >= N_STEPS_NO_IMPROVEMENT ) + { + improvement_found = 0; + } + } + else + { + this->AmoebaNStepsNoImprovement = 0; + } + + y_try = this->TryAmoeba( this->AmoebaSum, high, -VTK_AMOEBA_FLIP_RATIO ); + + if( y_try <= this->AmoebaValues[low] ) + { + y_try = TryAmoeba( this->AmoebaSum, high, VTK_AMOEBA_STRETCH_RATIO ); + } + else if( y_try >= this->AmoebaValues[next_high] ) + { + y_save = this->AmoebaValues[high]; + y_try = TryAmoeba( this->AmoebaSum, high, VTK_AMOEBA_CONTRACT_RATIO ); + + if( y_try >= y_save ) + { + for( i = 0 ; i < this->NumberOfParameters+1 ; i++) + { + if( i != low ) + { + for( j = 0 ; j < this->NumberOfParameters ; j++ ) + { + this->ParameterValues[j] = (this->AmoebaVertices[i][j] + + this->AmoebaVertices[low][j]) / 2.0; + this->AmoebaVertices[i][j] = this->ParameterValues[j]; + } + + this->EvaluateFunction(); + this->AmoebaValues[i] = this->FunctionValue; + } + } + + for( j = 0 ; j < this->NumberOfParameters ; j++ ) + { + this->AmoebaSum[j] = 0.0; + for( i = 0 ; i < this->NumberOfParameters+1 ; i++ ) + { + this->AmoebaSum[j] += this->AmoebaVertices[i][j]; + } + } + } + } + + return( improvement_found ); +} + diff --git a/Common/vtkAmoebaMinimizer.h b/Common/vtkAmoebaMinimizer.h new file mode 100644 index 0000000..b20542f --- /dev/null +++ b/Common/vtkAmoebaMinimizer.h @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAmoebaMinimizer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAmoebaMinimizer - nonlinear optimization with a simplex +// .SECTION Description +// vtkAmoebaMinimizer will modify a set of parameters in order to find +// the minimum of a specified function. The method used is commonly +// known as the amoeba method, it constructs an n-dimensional simplex +// in parameter space (i.e. a tetrahedron if the number or parameters +// is 3) and moves the vertices around parameter space until a local +// minimum is found. The amoeba method is robust, reasonably efficient, +// but is not guaranteed to find the global minimum if several local +// minima exist. + +#ifndef __vtkAmoebaMinimizer_h +#define __vtkAmoebaMinimizer_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkAmoebaMinimizer : public vtkObject +{ +public: + static vtkAmoebaMinimizer *New(); + vtkTypeRevisionMacro(vtkAmoebaMinimizer,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the function to be minimized. When this function + // is called, it must get the parameter values by calling + // GetParameterValue() for each parameter, and then must + // call SetFunctionValue() to tell the minimizer what the result + // of the function evaluation was. The number of function + // evaluations used for the minimization can be retrieved + // using GetFunctionEvaluations(). + void SetFunction(void (*f)(void *), void *arg); + + // Description: + // Set a function to call when a void* argument is being discarded. + void SetFunctionArgDelete(void (*f)(void *)); + + // Description: + // Set the initial value for the specified parameter. Calling + // this function for any parameter will reset the Iterations + // and the FunctionEvaluations counts to zero. You must also + // use SetParameterScale() to specify the step size by which the + // parameter will be modified during the minimization. It is + // preferable to specify parameters by name, rather than by + // number. + void SetParameterValue(const char *name, double value); + void SetParameterValue(int i, double value); + + // Description: + // Set the scale to use when modifying a parameter, i.e. the + // initial amount by which the parameter will be modified + // during the search for the minimum. It is preferable to + // identify scalars by name rather than by number. + void SetParameterScale(const char *name, double scale); + double GetParameterScale(const char *name); + void SetParameterScale(int i, double scale); + double GetParameterScale(int i) { return this->ParameterScales[i]; }; + + // Description: + // Get the value of a parameter at the current stage of the minimization. + // Call this method within the function that you are minimizing in order + // to get the current parameter values. It is preferable to specify + // parameters by name rather than by index. + double GetParameterValue(const char *name); + double GetParameterValue(int i) { return this->ParameterValues[i]; }; + + // Description: + // For completeness, an unchecked method to get the name for particular + // parameter (the result will be NULL if no name was set). + const char *GetParameterName(int i) { return this->ParameterNames[i]; }; + + // Description: + // Get the number of parameters that have been set. + int GetNumberOfParameters() { return this->NumberOfParameters; }; + + // Description: + // Initialize the minimizer. This will reset the number of parameters to + // zero so that the minimizer can be reused. + void Initialize(); + + // Description: + // Iterate until the minimum is found to within the specified tolerance, + // or until the MaxIterations has been reached. + virtual void Minimize(); + + // Description: + // Perform one iteration of minimization. Returns zero if the tolerance + // stopping criterion has been met. + virtual int Iterate(); + + // Description: + // Get the function value resulting from the minimization. + vtkSetMacro(FunctionValue,double); + double GetFunctionValue() { return this->FunctionValue; }; + + // Description: + // Specify the fractional tolerance to aim for during the minimization. + vtkSetMacro(Tolerance,double); + vtkGetMacro(Tolerance,double); + + // Description: + // Specify the maximum number of iterations to try before giving up. + vtkSetMacro(MaxIterations,int); + vtkGetMacro(MaxIterations,int); + + // Description: + // Return the number of interations that have been performed. This + // is not necessarily the same as the number of function evaluations. + vtkGetMacro(Iterations,int); + + // Description: + // Return the number of times that the function has been evaluated. + vtkGetMacro(FunctionEvaluations,int); + + // Description: + // Evaluate the function. This is usually called internally by the + // minimization code, but it is provided here as a public method. + void EvaluateFunction(); + +protected: + vtkAmoebaMinimizer(); + ~vtkAmoebaMinimizer(); + +//BTX + void (*Function)(void *); + void (*FunctionArgDelete)(void *); + void *FunctionArg; +//ETX + + int NumberOfParameters; + char **ParameterNames; + double *ParameterValues; + double *ParameterScales; + double FunctionValue; + + double Tolerance; + int MaxIterations; + int Iterations; + int FunctionEvaluations; + +private: +// specific to amoeba simplex minimization +//BTX + double **AmoebaVertices; + double *AmoebaValues; + double *AmoebaSum; + int AmoebaNStepsNoImprovement; + + void InitializeAmoeba(); + void GetAmoebaParameterValues(); + void TerminateAmoeba(); + double TryAmoeba(double sum[], int high, double fac); + int PerformAmoeba(); +//ETX + + vtkAmoebaMinimizer(const vtkAmoebaMinimizer&); // Not implemented. + void operator=(const vtkAmoebaMinimizer&); // Not implemented. +}; + +#endif diff --git a/Common/vtkAnimationCue.cxx b/Common/vtkAnimationCue.cxx new file mode 100644 index 0000000..83d54f9 --- /dev/null +++ b/Common/vtkAnimationCue.cxx @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAnimationCue.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkAnimationCue.h" +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + +vtkCxxRevisionMacro(vtkAnimationCue, "$Revision: 1.3.6.1 $"); +vtkStandardNewMacro(vtkAnimationCue); + +//---------------------------------------------------------------------------- +vtkAnimationCue::vtkAnimationCue() +{ + this->StartTime = this->EndTime = 0.0; + this->CueState = vtkAnimationCue::UNINITIALIZED; + this->TimeMode = TIMEMODE_RELATIVE; +} + +//---------------------------------------------------------------------------- +vtkAnimationCue::~vtkAnimationCue() +{ +} + +//---------------------------------------------------------------------------- +void vtkAnimationCue::StartCueInternal() +{ + vtkAnimationCue::AnimationCueInfo info; + info.StartTime = this->StartTime; + info.EndTime = this->EndTime; + info.AnimationTime = 0.0; + info.DeltaTime = 0.0; + this->InvokeEvent(vtkCommand::StartAnimationCueEvent, &info); +} + +//---------------------------------------------------------------------------- +void vtkAnimationCue::EndCueInternal() +{ + vtkAnimationCue::AnimationCueInfo info; + info.StartTime = this->StartTime; + info.EndTime = this->EndTime; + info.AnimationTime = this->EndTime; + info.DeltaTime = 0.0; + this->InvokeEvent(vtkCommand::EndAnimationCueEvent, &info); +} + +//---------------------------------------------------------------------------- +void vtkAnimationCue::TickInternal(double currenttime, double deltatime) +{ + vtkAnimationCue::AnimationCueInfo info; + info.StartTime = this->StartTime; + info.EndTime = this->EndTime; + info.DeltaTime = deltatime; + info.AnimationTime = currenttime; + + this->InvokeEvent(vtkCommand::AnimationCueTickEvent, &info); +} + + +//---------------------------------------------------------------------------- +void vtkAnimationCue::Tick(double currenttime, double deltatime) +{ + // Check to see if we have crossed the Cue start. + if (currenttime >= this->StartTime && + this->CueState == vtkAnimationCue::UNINITIALIZED) + { + this->CueState = vtkAnimationCue::ACTIVE; + this->StartCueInternal(); + } + + // Note that Tick event is sent for both start time and + // end time. + if (this->CueState == vtkAnimationCue::ACTIVE) + { + if (currenttime <= this->EndTime) + { + this->TickInternal(currenttime, deltatime); + } + if (currenttime >= this->EndTime) + { + this->EndCueInternal(); + this->CueState = vtkAnimationCue::INACTIVE; + } + } +} + +//---------------------------------------------------------------------------- +void vtkAnimationCue::SetTimeMode(int mode) +{ + this->TimeMode = mode; +} + +//---------------------------------------------------------------------------- +void vtkAnimationCue::Initialize() +{ + this->CueState = vtkAnimationCue::UNINITIALIZED; +} + +//---------------------------------------------------------------------------- +void vtkAnimationCue::Finalize() +{ + if (this->CueState == vtkAnimationCue::ACTIVE) + { + this->EndCueInternal(); + } + this->CueState = vtkAnimationCue::INACTIVE; +} + +//---------------------------------------------------------------------------- +void vtkAnimationCue::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "StartTime: " << this->StartTime << endl; + os << indent << "EndTime: " << this->EndTime << endl; + os << indent << "CueState: " << this->CueState << endl; + os << indent << "TimeMode: " << this->TimeMode << endl; +} diff --git a/Common/vtkAnimationCue.h b/Common/vtkAnimationCue.h new file mode 100644 index 0000000..b395eb9 --- /dev/null +++ b/Common/vtkAnimationCue.h @@ -0,0 +1,167 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAnimationCue.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAnimationCue - a seqin an animation. +// .SECTION Description +// vtkAnimationCue and vtkAnimationScene provide the framework to support +// animations in VTK. vtkAnimationCue represents an entity that changes/ +// animates with time, while vtkAnimationScene represents scene or setup +// for the animation, which consists on individual cues or other scenes. +// +// A cue has three states: UNINITIALIZED, ACTIVE and INACTIVE. +// UNINITIALIZED represents an point in time before the start time of the cue. +// The cue is in ACTIVE state at a point in time between start time and end time +// for the cue. While, beyond the end time, it is in INACTIVE state. +// When the cue enters the ACTIVE state, StartAnimationCueEvent is fired. This +// event may be handled to initialize the entity to be animated. +// When the cue leaves the ACTIVE state, EndAnimationCueEvent is fired, which +// can be handled to cleanup after having run the animation. +// For every request to render during the ACTIVE state, AnimationCueTickEvent is +// fired, which must be handled to perform the actual animation. +// .SECTION See Also +// vtkAnimationScene + +#ifndef __vtkAnimationCue_h +#define __vtkAnimationCue_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkAnimationCue: public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkAnimationCue,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkAnimationCue* New(); + + //BTX + // Structure passed on every event invocation. + // Depending upon the cue time mode, these times are either + // normalized [0,1] or relative to the scene that contains the cue. + class AnimationCueInfo + { + public: + double StartTime; + double EndTime; + double AnimationTime;// valid only on AnimationCueTickEvent + double DeltaTime; // valid only on AnimationCueTickEvent + }; + //ETX + + // Description: + // Get/Set the time mode. In Normalized mode, the start and end + // times of the cue are normalized [0,1] with respect to the start and + // end times of the container scene. In Relative mode the start and end + // time of the cue are specified in offset seconds relative to the + // start time of the container scene. + virtual void SetTimeMode(int mode); + vtkGetMacro(TimeMode, int); + void SetTimeModeToRelative() + { this->SetTimeMode(TIMEMODE_RELATIVE); } + void SetTimeModeToNormalized() + { this->SetTimeMode(TIMEMODE_NORMALIZED); } + + // Description: + // Get/Set the Start time for this cue. + // When the current time is >= StartTime, the Cue is in + // ACTIVE state. if Current time i < StartTime, the Cue is in + // UNINITIALIZED state. Whenever the cue enters the ACTIVE state from + // an INACTIVE state, it triggers the StartEvent. + // The Start time is in seconds relative to the start of the + // container Scene (when in Relative time mode) or is normalized + // over the span of the container Scene (when in Normalized time mode). + vtkSetMacro(StartTime, double); + vtkGetMacro(StartTime, double); + + // Description: + // Get/Set the End time for this cue. + // When the current time is > EndTime, the Cue is in + // INACTIVE state. Whenever the cue leaves an ACTIVE state to enter + // INACTIVE state, the EndEvent is triggered. + // The End time is in seconds relative to the start of the + // container Scene (when in Relative time mode) or is normalized + // over the span of the container Scene (when in Normalized time mode). + vtkSetMacro(EndTime, double); + vtkGetMacro(EndTime, double); + + // Description: + // Indicates a tick or point in time in the animation. + // Triggers a Tick event if currenttime >= StartTime and + // currenttime <= EndTime. + // Whenever the state of the cue changes, + // either StartEvent or EndEvent is triggerred depending upon + // whether the cue entered Active state or quit active state respectively. + // The current time is relative to the start of the container Scene + // (when in Relative time mode) or is normalized + // over the span of the container Scene (when in Normalized time mode). + // deltatime is the time since last call to Tick. deltatime also can be in seconds + // relative to the start of the container Scene or normalized depending upon the + // cue's Time mode. + // For the first call to Tick + // after a call to Initialize(), the deltatime is 0; + virtual void Tick(double currenttime, double deltatime); + + // Description: + // Called when the playing of the scene begins. + // This will set the Cue to UNINITIALIZED state. + virtual void Initialize(); + + // Description: + // Called when the scene reaches the end. + // If the cue state is ACTIVE when this method is called, this will + // trigger a EndAnimationCueEvent. + virtual void Finalize(); + +//BTX + enum TimeCodes + { + TIMEMODE_NORMALIZED=0, + TIMEMODE_RELATIVE=1 + }; +//ETX +protected: + vtkAnimationCue(); + ~vtkAnimationCue(); +//BTX + enum { + UNINITIALIZED=0, + INACTIVE, + ACTIVE + }; +//ETX + double StartTime; + double EndTime; + int TimeMode; + + // Description: + // Current state of the Cue. + int CueState; + + // Description: + // These are the internal methods that actually trigger they + // corresponding events. Subclasses can override these to + // do extra processing at start/end or on tick. + virtual void StartCueInternal(); + virtual void TickInternal(double currenttime, double deltatime); + virtual void EndCueInternal(); + +private: + vtkAnimationCue(const vtkAnimationCue&); // Not implemented. + void operator=(const vtkAnimationCue&); // Not implemented. +}; + +#endif + + + diff --git a/Common/vtkAnimationScene.cxx b/Common/vtkAnimationScene.cxx new file mode 100644 index 0000000..937fef5 --- /dev/null +++ b/Common/vtkAnimationScene.cxx @@ -0,0 +1,279 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAnimationScene.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkAnimationScene.h" +#include "vtkObjectFactory.h" +#include "vtkCollection.h" +#include "vtkCollectionIterator.h" +#include "vtkTimerLog.h" + +vtkCxxRevisionMacro(vtkAnimationScene, "$Revision: 1.7.4.1 $"); +vtkStandardNewMacro(vtkAnimationScene); + +//---------------------------------------------------------------------------- +vtkAnimationScene::vtkAnimationScene() +{ + this->PlayMode = PLAYMODE_SEQUENCE; + this->FrameRate = 10.0; + this->Loop = 0; + this->InPlay = 0; + this->StopPlay = 0; + this->AnimationTime = 0.0; + + this->AnimationCues = vtkCollection::New(); + this->AnimationCuesIterator = this->AnimationCues->NewIterator(); + this->AnimationTimer = vtkTimerLog::New(); +} + +//---------------------------------------------------------------------------- +vtkAnimationScene::~vtkAnimationScene() +{ + if (this->InPlay) + { + this->Stop(); + } + this->AnimationCues->Delete(); + this->AnimationCuesIterator->Delete(); + this->AnimationTimer->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::AddCue(vtkAnimationCue* cue) +{ + if (this->AnimationCues->IsItemPresent(cue)) + { + vtkErrorMacro("Animation cue already present in the scene"); + return; + } + if (this->TimeMode == vtkAnimationCue::TIMEMODE_NORMALIZED && + cue->GetTimeMode() != vtkAnimationCue::TIMEMODE_NORMALIZED) + { + vtkErrorMacro("A cue with relative time mode cannot be added to a scene " + "with normalized time mode."); + return; + } + this->AnimationCues->AddItem(cue); +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::RemoveCue(vtkAnimationCue* cue) +{ + this->AnimationCues->RemoveItem(cue); +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::SetTimeMode(int mode) +{ + if (mode == vtkAnimationCue::TIMEMODE_NORMALIZED) + { + // If noralized time mode is being set on the scene, + // ensure that none of the contained cues need relative times. + vtkCollectionIterator *it = this->AnimationCuesIterator; + for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem()) + { + vtkAnimationCue* cue = + vtkAnimationCue::SafeDownCast(it->GetCurrentObject()); + if (cue && cue->GetTimeMode() != vtkAnimationCue::TIMEMODE_NORMALIZED) + { + vtkErrorMacro("Scene contains a cue in relative mode. It must be removed " + "or chaged to normalized mode before changing the scene time mode"); + return; + } + } + } + this->Superclass::SetTimeMode(mode); +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::InitializeChildren() +{ + // run thr all the cues and init them. + vtkCollectionIterator *it = this->AnimationCuesIterator; + for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem()) + { + vtkAnimationCue* cue = + vtkAnimationCue::SafeDownCast(it->GetCurrentObject()); + if (cue) + { + cue->Initialize(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::FinalizeChildren() +{ + vtkCollectionIterator *it = this->AnimationCuesIterator; + for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem()) + { + vtkAnimationCue* cue = + vtkAnimationCue::SafeDownCast(it->GetCurrentObject()); + if (cue) + { + cue->Finalize(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::Play() +{ + if (this->InPlay) + { + return; + } + + if (this->TimeMode == vtkAnimationCue::TIMEMODE_NORMALIZED) + { + vtkErrorMacro("Cannot play a scene with normalized time mode"); + return; + } + if (this->EndTime <= this->StartTime) + { + vtkErrorMacro("Scene start and end times are not suitable for playing"); + return; + } + + this->InPlay = 1; + this->StopPlay = 0; + this->FrameRate = (!this->FrameRate)? 1.0 : this->FrameRate; + // the actual play loop, check for StopPlay flag. + double deltatime = 0.0; + double currenttime = this->AnimationTime; + double span = this->EndTime - this->StartTime; + + // adjust currenttime to a valid time. + currenttime = (currenttime < this->StartTime || currenttime >= this->EndTime)? + this->StartTime : currenttime; + double STime = currenttime; + double clocktime = currenttime; + double oldclocktime = clocktime; + double time_adjustment = 0; + this->AnimationTimer->StartTimer(); + do + { + this->Initialize(); // Set the Scene in unintialized mode. + do + { + currenttime = clocktime - time_adjustment; + this->Tick(currenttime, deltatime); + oldclocktime = clocktime; + if (this->PlayMode == PLAYMODE_REALTIME) + { + this->AnimationTimer->StopTimer(); + clocktime = this->AnimationTimer->GetElapsedTime() + + STime; + } + else if (this->PlayMode == PLAYMODE_SEQUENCE) + { + clocktime += 1.0 / this->FrameRate; + } + else + { + vtkErrorMacro("Invalid Play Mode"); + this->StopPlay = 1; + break; + } + deltatime = clocktime - oldclocktime; + deltatime = (deltatime < 0)? -1*deltatime : deltatime; + } + while (!this->StopPlay && this->CueState != vtkAnimationCue::INACTIVE); + time_adjustment += span; + } + while (this->Loop && !this->StopPlay); + this->StopPlay = 0; + this->InPlay = 0; +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::Stop() +{ + if (!this->InPlay) + { + return; + } + this->StopPlay = 1; +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::TickInternal(double currenttime, double deltatime) +{ + this->AnimationTime = currenttime; + + vtkCollectionIterator* iter = this->AnimationCuesIterator; + for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem()) + { + vtkAnimationCue* cue = vtkAnimationCue::SafeDownCast( + iter->GetCurrentObject()); + if (cue) + { + switch(cue->GetTimeMode()) + { + case vtkAnimationCue::TIMEMODE_RELATIVE: + cue->Tick(currenttime - this->StartTime, deltatime); + break; + case vtkAnimationCue::TIMEMODE_NORMALIZED: + cue->Tick( (currenttime - this->StartTime) / (this->EndTime - this->StartTime), + deltatime / (this->EndTime - this->StartTime)); + break; + default: + vtkErrorMacro("Invalid cue time mode"); + } + } + } + this->Superclass::TickInternal(currenttime, deltatime); +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::StartCueInternal() +{ + this->Superclass::StartCueInternal(); + this->InitializeChildren(); +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::EndCueInternal() +{ + this->FinalizeChildren(); + this->Superclass::EndCueInternal(); +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::SetAnimationTime(double currenttime) +{ + if (this->InPlay) + { + vtkErrorMacro("SetAnimationTime cannot be called while playing"); + return; + } + this->Initialize(); + this->Tick(currenttime,0.0); + if (this->CueState == vtkAnimationCue::INACTIVE) + { + this->Finalize(); + } +} + +//---------------------------------------------------------------------------- +void vtkAnimationScene::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "PlayMode: " << this->PlayMode << endl; + os << indent << "FrameRate: " << this->FrameRate << endl; + os << indent << "Loop: " << this->Loop << endl; + os << indent << "InPlay: " << this->InPlay << endl; + os << indent << "StopPlay: " << this->StopPlay << endl; + os << indent << "AnimationTime: " << this->AnimationTime << endl; +} diff --git a/Common/vtkAnimationScene.h b/Common/vtkAnimationScene.h new file mode 100644 index 0000000..fbe4895 --- /dev/null +++ b/Common/vtkAnimationScene.h @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAnimationScene.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAnimationScene - the animation scene manager. +// .SECTION Description +// vtkAnimationCue and vtkAnimationScene provide the framework to support +// animations in VTK. vtkAnimationCue represents an entity that changes/ +// animates with time, while vtkAnimationScene represents scene or setup +// for the animation, which consists on individual cues or other scenes. +// +// A scene can be played in real time mode, or as a seqence of frames +// 1/frame rate apart in time. +// .SECTION See Also +// vtkAnimationCue + +#ifndef __vtkAnimationScene_h +#define __vtkAnimationScene_h + +#include "vtkAnimationCue.h" + +class vtkAnimationCue; +class vtkCollection; +class vtkCollectionIterator; +class vtkTimerLog; + +class VTK_COMMON_EXPORT vtkAnimationScene: public vtkAnimationCue +{ +public: + vtkTypeRevisionMacro(vtkAnimationScene, vtkAnimationCue); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkAnimationScene* New(); + + // Description: + // Get/Set the PlayMode for running/playing the animation scene. + // In the Sequence mode, all the frames are generated one after the other. + // The time reported to each Tick of the constituent cues (during Play) is + // incremented by 1/frame rate, irrespective of the current time. + // In the RealTime mode, time indicates the instance in time. + vtkSetMacro(PlayMode, int); + void SetModeToSequence() { this->SetPlayMode(PLAYMODE_SEQUENCE); } + void SetModeToRealTime() { this->SetPlayMode(PLAYMODE_REALTIME); } + vtkGetMacro(PlayMode, int); + + // Description: + // Get/Set the frame rate (in frames per second). + // This parameter affects only in the Sequence mode. The time interval + // indicated to each cue on every tick is progressed by 1/frame-rate seconds. + vtkSetMacro(FrameRate, double); + vtkGetMacro(FrameRate, double); + + // Description: + // Add/Remove an AnimationCue to/from the Scene. + // It's an error to add a cue twice to the Scene. + void AddCue(vtkAnimationCue* cue); + void RemoveCue(vtkAnimationCue* cue); + + // Description: + // Starts playing the animation scene. + void Play(); + + // Description: + // Stops the animation scene that is running. + void Stop(); + + // Description: + // Enable/Disable animation loop. + vtkSetMacro(Loop, int); + vtkGetMacro(Loop, int); + + // Description: + // Makes the state of the scene same as the given time. + void SetAnimationTime(double time); + + // Description: + // Overridden to allow change to Normalized mode only + // if none of the constituent cues is in Relative time mode. + virtual void SetTimeMode(int mode); + + // Description: + // Returns if the animation is being played. + int IsInPlay() { return this->InPlay; } + +//BTX + enum PlayModes + { + PLAYMODE_SEQUENCE=0, + PLAYMODE_REALTIME=1 + }; +//ETX + +protected: + vtkAnimationScene(); + ~vtkAnimationScene(); + + // Description: + // Called on every valid tick. + // Calls ticks on all the contained cues. + virtual void TickInternal(double currenttime, double deltatime); + virtual void StartCueInternal(); + virtual void EndCueInternal(); + + void InitializeChildren(); + void FinalizeChildren(); + + int PlayMode; + double FrameRate; + int Loop; + int InPlay; + int StopPlay; + double AnimationTime; + + vtkCollection* AnimationCues; + vtkCollectionIterator* AnimationCuesIterator; + vtkTimerLog* AnimationTimer; + +private: + vtkAnimationScene(const vtkAnimationScene&); // Not implemented. + void operator=(const vtkAnimationScene&); // Not implemented. +}; + +#endif + diff --git a/Common/vtkAssemblyNode.cxx b/Common/vtkAssemblyNode.cxx new file mode 100644 index 0000000..8e5ccd4 --- /dev/null +++ b/Common/vtkAssemblyNode.cxx @@ -0,0 +1,156 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssemblyNode.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAssemblyNode.h" +#include "vtkProp.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkAssemblyNode, "$Revision: 1.9.12.1 $"); +vtkStandardNewMacro(vtkAssemblyNode); + +vtkAssemblyNode::vtkAssemblyNode() +{ + this->ViewProp = NULL; + this->Matrix = NULL; +} + +vtkAssemblyNode::~vtkAssemblyNode() +{ + if ( this->Matrix ) + { + this->Matrix->Delete(); + } +} + +//---------------------------------------------------------------------------- +// Don't do reference counting +void vtkAssemblyNode::SetViewProp(vtkProp *prop) +{ + this->ViewProp = prop; +} + + +void vtkAssemblyNode::SetMatrix(vtkMatrix4x4 *matrix) +{ + // delete previous + if ( this->Matrix != NULL ) + { + this->Matrix->Delete(); + this->Matrix = NULL; + } + // return if NULL matrix specified + if ( matrix == NULL ) + { + return; + } + + // else create a copy of the matrix + vtkMatrix4x4 *newMatrix = vtkMatrix4x4::New(); + newMatrix->DeepCopy(matrix); + this->Matrix = newMatrix; +} + +unsigned long vtkAssemblyNode::GetMTime() +{ + unsigned long propMTime=0; + unsigned long matrixMTime=0; + + if ( this->ViewProp != NULL ) + { + propMTime = this->ViewProp->GetMTime(); + } + if ( this->Matrix != NULL ) + { + matrixMTime = this->Matrix->GetMTime(); + } + + return (propMTime > matrixMTime ? propMTime : matrixMTime); +} + +void vtkAssemblyNode::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->ViewProp ) + { + os << indent << "ViewProp: " << this->ViewProp << "\n"; + } + else + { + os << indent << "ViewProp: (none)\n"; + } + + if ( this->Matrix ) + { + os << indent << "Matrix: " << this->Matrix << "\n"; + } + else + { + os << indent << "Matrix: (none)\n"; + } +} + +//---------------------------------------------------------------------------- + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (disable:858) +#endif + +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SetProp +# undef GetProp +void const vtkAssemblyNode::SetPropA(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::SetProp, "VTK 5.0", + vtkAssemblyNode::SetViewProp); + this->SetViewProp(prop); +} +void const vtkAssemblyNode::SetPropW(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::SetProp, "VTK 5.0", + vtkAssemblyNode::SetViewProp); + this->SetViewProp(prop); +} +vtkProp* const vtkAssemblyNode::GetPropA() +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::GetProp, "VTK 5.0", + vtkAssemblyNode::GetViewProp); + return this->GetViewProp(); +} +vtkProp* const vtkAssemblyNode::GetPropW() +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::GetProp, "VTK 5.0", + vtkAssemblyNode::GetViewProp); + return this->GetViewProp(); +} +# endif +void const vtkAssemblyNode::SetProp(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::SetProp, "VTK 5.0", + vtkAssemblyNode::SetViewProp); + this->SetViewProp(prop); +} +vtkProp* const vtkAssemblyNode::GetProp() +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::GetProp, "VTK 5.0", + vtkAssemblyNode::GetViewProp); + return this->GetViewProp(); +} +#endif diff --git a/Common/vtkAssemblyNode.h b/Common/vtkAssemblyNode.h new file mode 100644 index 0000000..8207b57 --- /dev/null +++ b/Common/vtkAssemblyNode.h @@ -0,0 +1,137 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssemblyNode.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAssemblyNode - represent a node in an assembly +// .SECTION Description +// vtkAssemblyNode represents a node in an assembly. It is used by +// vtkAssemblyPath to create hierarchical assemblies of props. The +// props can be either 2D or 3D. +// +// An assembly node refers to a vtkProp, and possibly a vtkMatrix4x4. +// Nodes are used by vtkAssemblyPath to build fully evaluated path +// (matrices are concatenated through the path) that is used by picking +// and other operations involving assemblies. + +// .SECTION Caveats +// The assembly node is guaranteed to contain a reference to an instance +// of vtkMatrix4x4 if the prop referred to by the node is of type +// vtkProp3D (or subclass). The matrix is evaluated through the assembly +// path, so the assembly node's matrix is a function of its location in +// the vtkAssemblyPath. +// +// vtkAssemblyNode does not reference count its association with vtkProp. +// Therefore, do not create an assembly node, associate a prop with it, +// delete the prop, and then try to dereference the prop. The program +// will break! (Reason: vtkAssemblyPath (which uses vtkAssemblyNode) +// create self-referencing loops that destroy reference counting.) + +// .SECTION see also +// vtkAssemblyPath vtkProp vtkPicker vtkMatrix4x4 + +#ifndef __vtkAssemblyNode_h +#define __vtkAssemblyNode_h + +#include "vtkObject.h" + +class vtkProp; +class vtkMatrix4x4; + +class VTK_COMMON_EXPORT vtkAssemblyNode : public vtkObject +{ +public: + // Description: + // Create an assembly node. + static vtkAssemblyNode *New(); + + vtkTypeRevisionMacro(vtkAssemblyNode,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the prop that this assembly node refers to. + virtual void SetViewProp(vtkProp* prop); + vtkGetObjectMacro(ViewProp, vtkProp); + + // Description: + // Specify a transformation matrix associated with the prop. + // Note: if the prop is not a type of vtkProp3D, then the + // transformation matrix is ignored (and expected to be NULL). + // Also, internal to this object the matrix is copied because + // the matrix is used for computation by vtkAssemblyPath. + void SetMatrix(vtkMatrix4x4 *matrix); + vtkGetObjectMacro(Matrix, vtkMatrix4x4); + + // Description: + // Override the standard GetMTime() to check for the modified times + // of the prop and matrix. + virtual unsigned long GetMTime(); + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (push) +# pragma warning (disable:858) +#endif + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define SetPropA SetProp +# define SetPropW SetProp +# define GetPropA GetProp +# define GetPropW GetProp +#endif + + // Description: + // @deprecated Replaced by vtkAssemblyNode::SetViewProp() as of VTK 5.0. + VTK_LEGACY(virtual void const SetProp(vtkProp* prop)); + + // Description: + // @deprecated Replaced by vtkAssemblyNode::GetViewProp() as of VTK 5.0. + VTK_LEGACY(virtual vtkProp* const GetProp()); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SetPropW +# undef SetPropA +# undef GetPropW +# undef GetPropA + //BTX + VTK_LEGACY(virtual void const SetPropA(vtkProp* prop)); + VTK_LEGACY(virtual void const SetPropW(vtkProp* prop)); + VTK_LEGACY(virtual vtkProp* const GetPropA()); + VTK_LEGACY(virtual vtkProp* const GetPropW()); + //ETX +#endif + +// Reset disabled warning about qualifiers on return types. +#if defined(__INTEL_COMPILER) +# pragma warning (pop) +#endif +#if defined(_COMPILER_VERSION) +# pragma reset woff 3303 +#endif + +protected: + vtkAssemblyNode(); + ~vtkAssemblyNode(); + +private: + vtkProp *ViewProp; //reference to vtkProp + vtkMatrix4x4 *Matrix; //associated matrix + +private: + void operator=(const vtkAssemblyNode&); // Not implemented. + vtkAssemblyNode(const vtkAssemblyNode&); // Not implemented. +}; + +#endif diff --git a/Common/vtkAssemblyPath.cxx b/Common/vtkAssemblyPath.cxx new file mode 100644 index 0000000..8301c48 --- /dev/null +++ b/Common/vtkAssemblyPath.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssemblyPath.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAssemblyPath.h" + +#include "vtkAssemblyNode.h" +#include "vtkTransform.h" +#include "vtkObjectFactory.h" +#include "vtkProp.h" + +vtkCxxRevisionMacro(vtkAssemblyPath, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkAssemblyPath); + +vtkAssemblyPath::vtkAssemblyPath() +{ + this->Transform = vtkTransform::New(); + this->Transform->PreMultiply(); + this->TransformedProp = NULL; +} + +vtkAssemblyPath::~vtkAssemblyPath() +{ + this->Transform->Delete(); + if ( this->TransformedProp != NULL ) + { + this->TransformedProp->Delete(); + } +} + +void vtkAssemblyPath::AddNode(vtkProp *p, vtkMatrix4x4 *m) +{ + vtkAssemblyNode *n = vtkAssemblyNode::New(); + n->SetViewProp(p); + n->SetMatrix(m); //really a copy because we're gonna compute with it + this->AddNode(n); + n->Delete(); //ok reference counted +} + +void vtkAssemblyPath::AddNode(vtkAssemblyNode *n) +{ + // First add the node to the list + this->vtkCollection::AddItem((vtkObject *)n); + + // Grab the matrix, if any, and concatenate it + this->Transform->Push(); //keep in synch with list of nodes + vtkMatrix4x4 *matrix; + if ( (matrix = n->GetMatrix()) != NULL ) + { + this->Transform->Concatenate(matrix); + this->Transform->GetMatrix(matrix); //replace previous matrix + } +} + +vtkAssemblyNode *vtkAssemblyPath::GetNextNode() +{ + return (vtkAssemblyNode *)(this->GetNextItemAsObject()); +} + +vtkAssemblyNode *vtkAssemblyPath::GetFirstNode() +{ + if ( this->Top == NULL ) + { + return NULL; + } + else + { + return (vtkAssemblyNode *)(this->Top->Item); + } +} + +vtkAssemblyNode *vtkAssemblyPath::GetLastNode() +{ + if ( this->Bottom == NULL ) + { + return NULL; + } + else + { + return (vtkAssemblyNode *)(this->Bottom->Item); + } +} + +void vtkAssemblyPath::DeleteLastNode() +{ + vtkAssemblyNode *node = this->GetLastNode(); + this->vtkCollection::RemoveItem(node); + + this->Transform->Pop(); +} + +void vtkAssemblyPath::ShallowCopy(vtkAssemblyPath *path) +{ + vtkAssemblyNode *node; + + this->RemoveAllItems(); + for ( path->InitTraversal(); (node = path->GetNextNode()); ) + { + this->vtkCollection::AddItem((vtkObject *)node); + } +} + +unsigned long vtkAssemblyPath::GetMTime() +{ + unsigned long mtime=this->vtkCollection::GetMTime(); + unsigned long nodeMTime; + vtkAssemblyNode *node; + + for ( this->InitTraversal(); (node = this->GetNextNode()); ) + { + nodeMTime = node->GetMTime(); + if ( nodeMTime > mtime ) + { + mtime = nodeMTime; + } + } + return mtime; +} + +void vtkAssemblyPath::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + + diff --git a/Common/vtkAssemblyPath.h b/Common/vtkAssemblyPath.h new file mode 100644 index 0000000..12d9337 --- /dev/null +++ b/Common/vtkAssemblyPath.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssemblyPath.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAssemblyPath - a list of nodes that form an assembly path +// .SECTION Description +// vtkAssemblyPath represents an ordered list of assembly nodes that +// represent a fully evaluated assembly path. This class is used primarily +// for picking. Note that the use of this class is to add one or more +// assembly nodes to form the path. (An assembly node consists of an instance +// of vtkProp and vtkMatrix4x4, the matrix may be NULL.) As each node is +// added, the matrices are concatenated to create a final, evaluated matrix. + +// .SECTION See Also +// vtkAssemblyNode vtkAssembly vtkActor vtkMatrix4x4 vtkProp vtkAbstractPicker + +#ifndef __vtkAssemblyPath_h +#define __vtkAssemblyPath_h + +#include "vtkCollection.h" +#include "vtkAssemblyNode.h" // used for inlines + +class vtkMatrix4x4; +class vtkTransform; +class vtkProp; + +class VTK_COMMON_EXPORT vtkAssemblyPath : public vtkCollection +{ +public: + vtkTypeRevisionMacro(vtkAssemblyPath,vtkCollection); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate empty path with identify matrix. + static vtkAssemblyPath *New(); + + // Description: + // Convenience method adds a prop and matrix together, + // creating an assembly node transparently. The matrix + // pointer m may be NULL. Note: that matrix is the one, + // if any, associated with the prop. + void AddNode(vtkProp *p, vtkMatrix4x4 *m); + + // Description: + // Get the next assembly node in the list. The node returned + // contains a pointer to a prop and a 4x4 matrix. The matrix + // is evaluated based on the preceding assembly hierarchy + // (i.e., the matrix is not necessarily as the same as the + // one that was added with AddNode() because of the + // concatenation of matrices in the assembly hierarchy). + vtkAssemblyNode *GetNextNode(); + + // Description: + // Get the first assembly node in the list. See the comments for + // GetNextNode() regarding the contents of the returned node. (Note: This + // node corresponds to the vtkProp associated with the vtkRenderer. + vtkAssemblyNode *GetFirstNode(); + + // Description: + // Get the last assembly node in the list. See the comments + // for GetNextNode() regarding the contents of the returned node. + vtkAssemblyNode *GetLastNode(); + + // Description: + // Delete the last assembly node in the list. This is like + // a stack pop. + void DeleteLastNode(); + + // Description: + // Perform a shallow copy (reference counted) on the + // incoming path. + void ShallowCopy(vtkAssemblyPath *path); + + // Description: + // Override the standard GetMTime() to check for the modified times + // of the nodes in this path. + virtual unsigned long GetMTime(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkAssemblyNode *GetNextNode(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkAssemblyPath(); + ~vtkAssemblyPath(); + + void AddNode(vtkAssemblyNode *n); //Internal method adds assembly node + vtkTransform *Transform; //Used to perform matrix concatentation + vtkProp *TransformedProp; //A transformed prop used to do the rendering + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkAssemblyPath(const vtkAssemblyPath&); // Not implemented. + void operator=(const vtkAssemblyPath&); // Not implemented. +}; + +#endif diff --git a/Common/vtkAssemblyPaths.cxx b/Common/vtkAssemblyPaths.cxx new file mode 100644 index 0000000..8c13b13 --- /dev/null +++ b/Common/vtkAssemblyPaths.cxx @@ -0,0 +1,41 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssemblyPaths.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAssemblyPaths.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkAssemblyPaths, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkAssemblyPaths); + +unsigned long vtkAssemblyPaths::GetMTime() +{ + unsigned long mtime=this->vtkCollection::GetMTime(); + unsigned long pathMTime; + vtkAssemblyPath *path; + + for ( this->InitTraversal(); (path = this->GetNextItem()); ) + { + pathMTime = path->GetMTime(); + if ( pathMTime > mtime ) + { + mtime = pathMTime; + } + } + return mtime; +} + + + + + diff --git a/Common/vtkAssemblyPaths.h b/Common/vtkAssemblyPaths.h new file mode 100644 index 0000000..7c4af37 --- /dev/null +++ b/Common/vtkAssemblyPaths.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssemblyPaths.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAssemblyPaths - a list of lists of props representing an assembly hierarchy +// .SECTION Description +// vtkAssemblyPaths represents an assembly hierarchy as a list of +// vtkAssemblyPath. Each path represents the complete path from the +// top level assembly (if any) down to the leaf prop. + +// .SECTION see also +// vtkAssemblyPath vtkAssemblyNode vtkPicker vtkAssembly vtkProp + +#ifndef __vtkAssemblyPaths_h +#define __vtkAssemblyPaths_h + +#include "vtkCollection.h" + +#include "vtkAssemblyPath.h" // Needed for inline methods + +class vtkProp; + +class VTK_COMMON_EXPORT vtkAssemblyPaths : public vtkCollection +{ +public: + static vtkAssemblyPaths *New(); + vtkTypeRevisionMacro(vtkAssemblyPaths,vtkCollection); + + // Description: + // Add a path to the list. + void AddItem(vtkAssemblyPath *p); + + // Description: + // Remove a path from the list. + void RemoveItem(vtkAssemblyPath *p); + + // Description: + // Determine whether a particular path is present. Returns its position + // in the list. + int IsItemPresent(vtkAssemblyPath *p); + + // Description: + // Get the next path in the list. + vtkAssemblyPath *GetNextItem(); + + // Description: + // Override the standard GetMTime() to check for the modified times + // of the paths. + virtual unsigned long GetMTime(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkAssemblyPath *GetNextPath(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkAssemblyPaths() {}; + ~vtkAssemblyPaths() {}; + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + void RemoveItem(vtkObject *o) { this->vtkCollection::RemoveItem(o); }; + void RemoveItem(int i) { this->vtkCollection::RemoveItem(i); }; + int IsItemPresent(vtkObject *o) + { return this->vtkCollection::IsItemPresent(o);}; +private: + vtkAssemblyPaths(const vtkAssemblyPaths&); // Not implemented. + void operator=(const vtkAssemblyPaths&); // Not implemented. +}; + +inline void vtkAssemblyPaths::AddItem(vtkAssemblyPath *p) +{ + this->vtkCollection::AddItem((vtkObject *)p); +} + +inline void vtkAssemblyPaths::RemoveItem(vtkAssemblyPath *p) +{ + this->vtkCollection::RemoveItem((vtkObject *)p); +} + +inline int vtkAssemblyPaths::IsItemPresent(vtkAssemblyPath *p) +{ + return this->vtkCollection::IsItemPresent((vtkObject *)p); +} + +inline vtkAssemblyPath *vtkAssemblyPaths::GetNextItem() +{ + return (vtkAssemblyPath *)(this->GetNextItemAsObject()); +} + +#endif diff --git a/Common/vtkBitArray.cxx b/Common/vtkBitArray.cxx new file mode 100644 index 0000000..47bc18f --- /dev/null +++ b/Common/vtkBitArray.cxx @@ -0,0 +1,396 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBitArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBitArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkBitArray, "$Revision: 1.59.4.1 $"); +vtkStandardNewMacro(vtkBitArray); + +// Instantiate object. +vtkBitArray::vtkBitArray(vtkIdType numComp) +{ + this->NumberOfComponents = (numComp < 1 ? 1 : numComp); + this->Array = NULL; + this->TupleSize = 3; + this->Tuple = new double[this->TupleSize]; //used for conversion + this->SaveUserArray = 0; +} + +vtkBitArray::~vtkBitArray() +{ + if ((this->Array) && (!this->SaveUserArray)) + { + delete [] this->Array; + } + delete [] this->Tuple; +} + +unsigned char *vtkBitArray::WritePointer(vtkIdType id, vtkIdType number) +{ + vtkIdType newSize=id+number; + if ( newSize > this->Size ) + { + this->ResizeAndExtend(newSize); + } + if ( (--newSize) > this->MaxId ) + { + this->MaxId = newSize; + } + return this->Array + id/8; +} + +// This method lets the user specify data to be held by the array. The +// array argument is a pointer to the data. size is the size of +// the array supplied by the user. Set save to 1 to keep the class +// from deleting the array when it cleans up or reallocates memory. +// The class uses the actual array provided; it does not copy the data +// from the suppled array. +void vtkBitArray::SetArray(unsigned char* array, vtkIdType size, int save) +{ + + if ((this->Array) && (!this->SaveUserArray)) + { + vtkDebugMacro (<< "Deleting the array..."); + delete [] this->Array; + } + else + { + vtkDebugMacro (<<"Warning, array not deleted, but will point to new array."); + } + + vtkDebugMacro(<<"Setting array to: " << array); + + this->Array = array; + this->Size = size; + this->MaxId = size-1; + this->SaveUserArray = save; +} + +// Get the data at a particular index. +int vtkBitArray::GetValue(vtkIdType id) +{ + if (this->Array[id/8]&(0x80 >> (id%8))) + { + return 1; + } + return 0; +} + +// Allocate memory for this array. Delete old storage only if necessary. +int vtkBitArray::Allocate(vtkIdType sz, vtkIdType vtkNotUsed(ext)) +{ + if ( sz > this->Size ) + { + if (( this->Array != NULL ) && (!this->SaveUserArray)) + { + delete [] this->Array; + } + this->Size = ( sz > 0 ? sz : 1); + if ( (this->Array = new unsigned char[(this->Size+7)/8]) == NULL ) + { + return 0; + } + this->SaveUserArray = 0; + } + + this->MaxId = -1; + + return 1; +} + +// Release storage and reset array to initial state. +void vtkBitArray::Initialize() +{ + if (( this->Array != NULL ) && (!this->SaveUserArray)) + { + delete [] this->Array; + } + this->Array = NULL; + this->Size = 0; + this->MaxId = -1; + this->SaveUserArray = 0; +} + +// Deep copy of another bit array. +void vtkBitArray::DeepCopy(vtkDataArray *ia) +{ + // Do nothing on a NULL input. + if (ia == NULL) + { + return; + } + + if (ia->GetDataType() != VTK_BIT) + { + vtkIdType numTuples = ia->GetNumberOfTuples(); + this->NumberOfComponents = ia->GetNumberOfComponents(); + this->SetNumberOfTuples(numTuples); + + for (vtkIdType i = 0; i < numTuples; i++) + { + this->SetTuple(i, ia->GetTuple(i)); + } + return; + } + + if ( this != ia ) + { + if ((this->Array) && (!this->SaveUserArray)) + { + delete [] this->Array; + } + + this->NumberOfComponents = ia->GetNumberOfComponents(); + this->MaxId = ia->GetMaxId(); + this->Size = ia->GetSize(); + this->SaveUserArray = 0; + + this->Array = new unsigned char[(this->Size+7)/8]; + memcpy(this->Array, (unsigned char*)ia->GetVoidPointer(0), + ((this->Size+7)/8)*sizeof(unsigned char)); + } +} + +void vtkBitArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->Array) + { + os << indent << "Array: " << this->Array << "\n"; + } + else + { + os << indent << "Array: (null)\n"; + } +} + +// +// Private function does "reallocate". Sz is the number of "bits", and we +// can allocate only 8-bit bytes. +unsigned char *vtkBitArray::ResizeAndExtend(vtkIdType sz) +{ + unsigned char *newArray; + vtkIdType newSize; + + if ( sz > this->Size ) + { + newSize = this->Size + sz; + } + else if (sz == this->Size) + { + return this->Array; + } + else + { + newSize = sz; + } + + if (newSize <= 0) + { + this->Initialize(); + return 0; + } + + if ( (newArray = new unsigned char[(newSize+7)/8]) == NULL ) + { + vtkErrorMacro(<< "Cannot allocate memory\n"); + return 0; + } + + if (this->Array) + { + int usedSize = (sz < this->Size) ? sz : this->Size; + + memcpy(newArray, this->Array, + ((usedSize+7)/8)*sizeof(unsigned char)); + if (!this->SaveUserArray) + { + delete[] this->Array; + } + } + + if (newSize < this->Size) + { + this->MaxId = newSize-1; + } + this->Size = newSize; + this->Array = newArray; + this->SaveUserArray = 0; + + return this->Array; +} + +int vtkBitArray::Resize(vtkIdType sz) +{ + unsigned char *newArray; + vtkIdType newSize = sz*this->NumberOfComponents; + + if (newSize == this->Size) + { + return 1; + } + + if (newSize <= 0) + { + this->Initialize(); + return 1; + } + + if ( (newArray = new unsigned char[(newSize+7)/8]) == NULL ) + { + vtkErrorMacro(<< "Cannot allocate memory\n"); + return 0; + } + + if (this->Array) + { + int usedSize = (newSize < this->Size) ? newSize : this->Size; + + memcpy(newArray, this->Array, + ((usedSize+7)/8)*sizeof(unsigned char)); + if (!this->SaveUserArray) + { + delete[] this->Array; + } + } + + if (newSize < this->Size) + { + this->MaxId = newSize-1; + } + this->Size = newSize; + this->Array = newArray; + this->SaveUserArray = 0; + + return 1; +} + +// Set the number of n-tuples in the array. +void vtkBitArray::SetNumberOfTuples(vtkIdType number) +{ + this->SetNumberOfValues(number*this->NumberOfComponents); +} + +// Get a pointer to a tuple at the ith location. This is a dangerous method +// (it is not thread safe since a pointer is returned). +double *vtkBitArray::GetTuple(vtkIdType i) +{ + if ( this->TupleSize < this->NumberOfComponents ) + { + this->TupleSize = this->NumberOfComponents; + delete [] this->Tuple; + this->Tuple = new double[this->TupleSize]; + } + + int loc = this->NumberOfComponents*i; + for (int j=0; jNumberOfComponents; j++) + { + this->Tuple[j] = (double)this->GetValue(loc+j); + } + + return this->Tuple; +} + +// Copy the tuple value into a user-provided array. +void vtkBitArray::GetTuple(vtkIdType i, double * tuple) +{ + vtkIdType loc = this->NumberOfComponents*i; + + for (int j=0; jNumberOfComponents; j++) + { + tuple[j] = (double)this->GetValue(loc+j); + } +} + +// Set the tuple value at the ith location in the array. +void vtkBitArray::SetTuple(vtkIdType i, const float * tuple) +{ + vtkIdType loc = i * this->NumberOfComponents; + + for (int j=0; jNumberOfComponents; j++) + { + this->SetValue(loc+j,(int)tuple[j]); + } +} + +void vtkBitArray::SetTuple(vtkIdType i, const double * tuple) +{ + vtkIdType loc = i * this->NumberOfComponents; + + for (int j=0; jNumberOfComponents; j++) + { + this->SetValue(loc+j,(int)tuple[j]); + } +} + +// Insert (memory allocation performed) the tuple into the ith location +// in the array. +void vtkBitArray::InsertTuple(vtkIdType i, const float * tuple) +{ + vtkIdType loc = this->NumberOfComponents*i; + + for (int j=0; jNumberOfComponents; j++) + { + this->InsertValue(loc+j,(int)tuple[j]); + } +} + +void vtkBitArray::InsertTuple(vtkIdType i, const double * tuple) +{ + vtkIdType loc = this->NumberOfComponents*i; + + for (int j=0; jNumberOfComponents; j++) + { + this->InsertValue(loc+j,(int)tuple[j]); + } +} + +// Insert (memory allocation performed) the tuple onto the end of the array. +vtkIdType vtkBitArray::InsertNextTuple(const float * tuple) +{ + for (int i=0; iNumberOfComponents; i++) + { + this->InsertNextValue((int)tuple[i]); + } + + return this->MaxId / this->NumberOfComponents; +} + +vtkIdType vtkBitArray::InsertNextTuple(const double * tuple) +{ + for (int i=0; iNumberOfComponents; i++) + { + this->InsertNextValue((int)tuple[i]); + } + + return this->MaxId / this->NumberOfComponents; +} + + +void vtkBitArray::InsertComponent(vtkIdType i, int j, double c) +{ + this->InsertValue(i*this->NumberOfComponents + j, + static_cast(c)); +} + +// Set the data component at the ith tuple and jth component location. +// Note that iSetValue(i*this->NumberOfComponents + j, static_cast(c)); +} diff --git a/Common/vtkBitArray.h b/Common/vtkBitArray.h new file mode 100644 index 0000000..a1d3b96 --- /dev/null +++ b/Common/vtkBitArray.h @@ -0,0 +1,216 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBitArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBitArray - dynamic, self-adjusting array of bits +// .SECTION Description +// vtkBitArray is an array of bits (0/1 data value). The array is packed +// so that each byte stores eight bits. vtkBitArray provides methods +// for insertion and retrieval of bits, and will automatically resize +// itself to hold new data. + +#ifndef __vtkBitArray_h +#define __vtkBitArray_h + +#include "vtkDataArray.h" + +class VTK_COMMON_EXPORT vtkBitArray : public vtkDataArray +{ +public: + static vtkBitArray *New(); + vtkTypeRevisionMacro(vtkBitArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate memory for this array. Delete old storage only if necessary. + // Note that ext is no longer used. + int Allocate(vtkIdType sz, vtkIdType ext=1000); + + // Description: + // Release storage and reset array to initial state. + void Initialize(); + + // satisfy vtkDataArray API + int GetDataType() {return VTK_BIT;}; + int GetDataTypeSize() { return 0; } + + // Description: + // Set the number of n-tuples in the array. + void SetNumberOfTuples(vtkIdType number); + + // Description: + // Get a pointer to a tuple at the ith location. This is a dangerous method + // (it is not thread safe since a pointer is returned). + double *GetTuple(vtkIdType i); + + // Description: + // Copy the tuple value into a user-provided array. + void GetTuple(vtkIdType i, double * tuple); + + // Description: + // Set the tuple value at the ith location in the array. + void SetTuple(vtkIdType i, const float * tuple); + void SetTuple(vtkIdType i, const double * tuple); + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTuple(vtkIdType i, const float * tuple); + void InsertTuple(vtkIdType i, const double * tuple); + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTuple(const float * tuple); + vtkIdType InsertNextTuple(const double * tuple); + + // Description: + // Set the data component at the ith tuple and jth component location. + // Note that i is less then NumberOfTuples and j is less then + // NumberOfComponents. Make sure enough memory has been allocated (use + // SetNumberOfTuples() and SetNumberOfComponents()). + void SetComponent(vtkIdType i, int j, double c); + + // Description: + // Free any unneeded memory. + void Squeeze(); + + // Description: + // Resize the array while conserving the data. + virtual int Resize(vtkIdType numTuples); + + // Description: + // Get the data at a particular index. + int GetValue(vtkIdType id); + + // Description: + // Fast method based setting of values without memory checks. First + // use SetNumberOfValues then use SetValue to actually set them. + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number); + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, int value); + + // Description: + // Insets values and checks to make sure there is enough memory + void InsertValue(vtkIdType id, int i); + vtkIdType InsertNextValue(int i); + + // Description: + // Insert the data component at ith tuple and jth component location. + // Note that memory allocation is performed as necessary to hold the data. + virtual void InsertComponent(vtkIdType i, int j, double c); + + // Description: + // Direct manipulation of the underlying data. + unsigned char *GetPointer(vtkIdType id) {return this->Array + id/8;} + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + unsigned char *WritePointer(vtkIdType id, vtkIdType number); + void* WriteVoidPointer(vtkIdType id, vtkIdType number) + { return this->WritePointer(id, number); } + void *GetVoidPointer(vtkIdType id) + {return (void *)this->GetPointer(id);}; + + // Description: + // Deep copy of another bit array. + void DeepCopy(vtkDataArray *da); + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(unsigned char* array, vtkIdType size, int save); + void SetVoidArray(void *array, vtkIdType size, int save) + {this->SetArray((unsigned char *)array, size, save);}; + + +protected: + vtkBitArray(vtkIdType numComp=1); + ~vtkBitArray(); + + unsigned char *Array; // pointer to data + unsigned char *ResizeAndExtend(vtkIdType sz); + // function to resize data + + int TupleSize; //used for data conversion + double *Tuple; + + int SaveUserArray; + +private: + // hide superclass' DeepCopy() from the user and the compiler + void DeepCopy(vtkDataArray &da) {this->vtkDataArray::DeepCopy(&da);} + +private: + vtkBitArray(const vtkBitArray&); // Not implemented. + void operator=(const vtkBitArray&); // Not implemented. +}; + +inline void vtkBitArray::SetNumberOfValues(vtkIdType number) +{ + this->Allocate(number); + this->MaxId = number - 1; +} + +inline void vtkBitArray::SetValue(vtkIdType id, int value) +{ + if (value) + { + this->Array[id/8] |= (0x80 >> id%8); + } + else + { + this->Array[id/8] &= (~(0x80 >> id%8)); + } +} + +inline void vtkBitArray::InsertValue(vtkIdType id, int i) +{ + if ( id >= this->Size ) + { + this->ResizeAndExtend(id+1); + } + if (i) + { + this->Array[id/8] |= (0x80 >> id%8); + } + else + { + this->Array[id/8] &= (~(0x80 >> id%8)); + } + if ( id > this->MaxId ) + { + this->MaxId = id; + } +} + +inline vtkIdType vtkBitArray::InsertNextValue(int i) +{ + this->InsertValue (++this->MaxId,i); return this->MaxId; +} + +inline void vtkBitArray::Squeeze() {this->ResizeAndExtend (this->MaxId+1);} + +#endif + diff --git a/Common/vtkBox.cxx b/Common/vtkBox.cxx new file mode 100644 index 0000000..6f235e6 --- /dev/null +++ b/Common/vtkBox.cxx @@ -0,0 +1,363 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBox.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBox.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkBox, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkBox); + +// Construct the box centered at the origin and each side length 1.0. +vtkBox::vtkBox() +{ + this->XMin[0] = -0.5; + this->XMin[1] = -0.5; + this->XMin[2] = -0.5; + + this->XMax[0] = 0.5; + this->XMax[1] = 0.5; + this->XMax[2] = 0.5; +} + +// Set the bounds in various ways +void vtkBox::SetBounds(double xMin, double xMax, + double yMin, double yMax, + double zMin, double zMax) +{ + if ( this->XMin[0] != xMin || this->XMax[0] != xMax || + this->XMin[1] != yMin || this->XMax[1] != yMax || + this->XMin[2] != zMin || this->XMax[2] != yMax ) + { + this->XMin[0] = xMin; + this->XMax[0] = xMax; + this->XMin[1] = yMin; + this->XMax[1] = yMax; + this->XMin[2] = zMin; + this->XMax[2] = zMax; + for (int i=0; i<3; i++) + { + if ( this->XMax[i] < this->XMin[i] ) + { + this->XMax[i] = this->XMin[i]; + } + } + this->Modified(); + } +} + +void vtkBox::SetBounds(double bounds[6]) +{ + this->SetBounds(bounds[0],bounds[1], bounds[2],bounds[3], + bounds[4],bounds[5]); +} + +void vtkBox::GetBounds(double &xMin, double &xMax, + double &yMin, double &yMax, + double &zMin, double &zMax) +{ + xMin = this->XMin[0]; + yMin = this->XMin[1]; + zMin = this->XMin[2]; + xMax = this->XMax[0]; + yMax = this->XMax[1]; + zMax = this->XMax[2]; +} + +void vtkBox::GetBounds(double bounds[6]) +{ + for (int i=0; i<3; i++) + { + bounds[2*i] = this->XMin[i]; + bounds[2*i+1] = this->XMax[i]; + } +} + +// Evaluate box equation. This differs from the similar vtkPlanes +// (with six planes) because of the "rounded" nature of the corners. +double vtkBox::EvaluateFunction(double x[3]) +{ + double diff, dist, minDistance=(-VTK_DOUBLE_MAX), t, distance=0.0; + int inside=1; + for (int i=0; i<3; i++) + { + diff = this->XMax[i] - this->XMin[i]; + if ( diff != 0.0 ) + { + t = (x[i]-this->XMin[i]) / (this->XMax[i]-this->XMin[i]); + if ( t < 0.0 ) + { + inside = 0; + dist = this->XMin[i] - x[i]; + } + else if ( t > 1.0 ) + { + inside = 0; + dist = x[i] - this->XMax[i]; + } + else + {//want negative distance, we are inside + if ( t <= 0.5 ) + { + dist = this->XMin[i] - x[i]; + } + else + { + dist = x[i] - this->XMax[i]; + } + if ( dist > minDistance ) //remember, it's negative + { + minDistance = dist; + } + }//if inside + } + else + { + dist = fabs(x[i]-this->XMin[i]); + if ( x[i] != this->XMin[i] ) + { + inside = 0; + } + } + if ( dist > 0.0 ) + { + distance += dist*dist; + } + }//for all coordinate directions + + distance = sqrt(distance); + if ( inside ) + { + return minDistance; + } + else + { + return distance; + } +} + +// Evaluate box gradient. +void vtkBox::EvaluateGradient(double x[3], double n[3]) +{ + int i, loc[3], minAxis=0; + double dist, minDist=VTK_DOUBLE_MAX, center[3]; + double inDir[3], outDir[3]; + + // Compute the location of the point with respect to the box. + // Ultimately the point will lie in one of 27 separate regions around + // or within the box. The gradient vector is computed differently in + // each of the regions. + inDir[0] = inDir[1] = inDir[2] = 0.0; + outDir[0] = outDir[1] = outDir[2] = 0.0; + for (i=0; i<3; i++) + { + center[i] = (this->XMin[i] + this->XMax[i])/2.0; + if ( x[i] < this->XMin[i] ) + { + loc[i] = 0; + outDir[i] = -1.0; + } + else if ( x[i] > this->XMax[i] ) + { + loc[i] = 2; + outDir[i] = 1.0; + } + else + { + loc[i] = 1; + if ( x[i] <= center[i] ) + { + dist = x[i] - this->XMin[i]; + inDir[i] = -1.0; + } + else + { + dist = this->XMax[i] - x[i]; + inDir[i] = 1.0; + } + if ( dist < minDist ) //remember, it's negative + { + minDist = dist; + minAxis = i; + } + }//if inside + }//for all coordinate directions + + int indx = loc[0] + 3*loc[1] + 9*loc[2]; + + switch (indx) + { + // verts - gradient points away from center point + case 0: case 2: case 6: case 8: case 18: case 20: case 24: case 26: + for (i=0; i<3; i++) + { + n[i] = x[i] - center[i]; + } + vtkMath::Normalize(n); + break; + + // edges - gradient points out from axis of cube + case 1: case 3: case 5: case 7: + case 9: case 11: case 15: case 17: + case 19: case 21: case 23: case 25: + for (i=0; i<3; i++) + { + if ( outDir[i] != 0.0 ) + { + n[i] = x[i] - center[i]; + } + else + { + n[i] = 0.0; + } + } + vtkMath::Normalize(n); + break; + + // faces - gradient points perpendicular to face + case 4: case 10: case 12: case 14: case 16: case 22: + for (i=0; i<3; i++) + { + n[i] = outDir[i]; + } + break; + + // interior - gradient is perpendicular to closest face + case 13: + n[0] = n[1] = n[2] = 0.0; + n[minAxis] = inDir[minAxis]; + break; + } +} + +#define VTK_RIGHT 0 +#define VTK_LEFT 1 +#define VTK_MIDDLE 2 + +// Bounding box intersection modified from Graphics Gems Vol I. The method +// returns a non-zero value if the bounding box is hit. Origin[3] starts +// the ray, dir[3] is the vector components of the ray in the x-y-z +// directions, coord[3] is the location of hit, and t is the parametric +// coordinate along line. (Notes: the intersection ray dir[3] is NOT +// normalized. Valid intersections will only occur between 0<=t<=1.) +char vtkBox::IntersectBox (double bounds[6], double origin[3], double dir[3], + double coord[3], double& t) +{ + char inside=1; + char quadrant[3]; + int i, whichPlane=0; + double maxT[3], candidatePlane[3]; + + // First find closest planes + // + for (i=0; i<3; i++) + { + if ( origin[i] < bounds[2*i] ) + { + quadrant[i] = VTK_LEFT; + candidatePlane[i] = bounds[2*i]; + inside = 0; + } + else if ( origin[i] > bounds[2*i+1] ) + { + quadrant[i] = VTK_RIGHT; + candidatePlane[i] = bounds[2*i+1]; + inside = 0; + } + else + { + quadrant[i] = VTK_MIDDLE; + } + } + + // Check whether origin of ray is inside bbox + // + if (inside) + { + coord[0] = origin[0]; + coord[1] = origin[1]; + coord[2] = origin[2]; + t = 0; + return 1; + } + + // Calculate parametric distances to plane + // + for (i=0; i<3; i++) + { + if ( quadrant[i] != VTK_MIDDLE && dir[i] != 0.0 ) + { + maxT[i] = (candidatePlane[i]-origin[i]) / dir[i]; + } + else + { + maxT[i] = -1.0; + } + } + + // Find the largest parametric value of intersection + // + for (i=0; i<3; i++) + { + if ( maxT[whichPlane] < maxT[i] ) + { + whichPlane = i; + } + } + + // Check for valid intersection along line + // + if ( maxT[whichPlane] > 1.0 || maxT[whichPlane] < 0.0 ) + { + return 0; + } + else + { + t = maxT[whichPlane]; + } + + // Intersection point along line is okay. Check bbox. + // + for (i=0; i<3; i++) + { + if (whichPlane != i) + { + coord[i] = origin[i] + maxT[whichPlane]*dir[i]; + if ( coord[i] < bounds[2*i] || coord[i] > bounds[2*i+1] ) + { + return 0; + } + } + else + { + coord[i] = candidatePlane[i]; + } + } + + return 1; +} +#undef VTK_RIGHT +#undef VTK_LEFT +#undef VTK_MIDDLE + + +void vtkBox::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "XMin: (" << this->XMin[0] << ", " + << this->XMin[1] << ", " << this->XMin[2] << ")\n"; + os << indent << "XMax: (" << this->XMax[0] << ", " + << this->XMax[1] << ", " << this->XMax[2] << ")\n"; +} diff --git a/Common/vtkBox.h b/Common/vtkBox.h new file mode 100644 index 0000000..8a6dbab --- /dev/null +++ b/Common/vtkBox.h @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBox.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBox - implicit function for a bounding box +// .SECTION Description +// vtkBox computes the implicit function and/or gradient for a axis-aligned +// bounding box. (The superclasses transform can be used to modify this +// orientation.) Each side of the box is orthogonal to all other sides +// meeting along shared edges and all faces are orthogonal to the x-y-z +// coordinate axes. (If you wish to orient this box differently, recall that +// the superclass vtkImplicitFunction supports a transformation matrix.) +// vtkCube is a concrete implementation of vtkImplicitFunction. +// +// .SECTION See Also +// vtkCubeSource vtkImplicitFunction + +#ifndef __vtkBox_h +#define __vtkBox_h + +#include "vtkImplicitFunction.h" + +class VTK_COMMON_EXPORT vtkBox : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkBox,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct box with center at (0,0,0) and each side of length 1.0. + static vtkBox *New(); + + // Description + // Evaluate box defined by the two points (pMin,pMax). + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } + + // Description + // Evaluate the gradient of the box. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Set / get the bounding box using various methods. + vtkSetVector3Macro(XMin,double); + vtkGetVector3Macro(XMin,double); + vtkSetVector3Macro(XMax,double); + vtkGetVector3Macro(XMax,double); + void SetBounds(double xMin, double xMax, + double yMin, double yMax, + double zMin, double zMax); + void SetBounds(double bounds[6]); + void GetBounds(double &xMin, double &xMax, + double &yMin, double &yMax, + double &zMin, double &zMax); + void GetBounds(double bounds[6]); + + // Description: + // Bounding box intersection modified from Graphics Gems Vol I. The method + // returns a non-zero value if the bounding box is hit. Origin[3] starts + // the ray, dir[3] is the vector components of the ray in the x-y-z + // directions, coord[3] is the location of hit, and t is the parametric + // coordinate along line. (Notes: the intersection ray dir[3] is NOT + // normalized. Valid intersections will only occur between 0<=t<=1.) + static char IntersectBox(double bounds[6], double origin[3], double dir[3], + double coord[3], double& t); + +protected: + vtkBox(); + ~vtkBox() {} + + double XMin[3]; + double XMax[3]; + +private: + vtkBox(const vtkBox&); // Not implemented. + void operator=(const vtkBox&); // Not implemented. +}; + +#endif + + diff --git a/Common/vtkByteSwap.cxx b/Common/vtkByteSwap.cxx new file mode 100644 index 0000000..beb1e44 --- /dev/null +++ b/Common/vtkByteSwap.cxx @@ -0,0 +1,319 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkByteSwap.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkByteSwap.h" +#include +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkByteSwap, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkByteSwap); + +//---------------------------------------------------------------------------- +vtkByteSwap::vtkByteSwap() +{ +} + +//---------------------------------------------------------------------------- +vtkByteSwap::~vtkByteSwap() +{ +} + +//---------------------------------------------------------------------------- +// Define swap functions for each type size. +template struct vtkByteSwapper; +VTK_TEMPLATE_SPECIALIZE struct vtkByteSwapper<1> +{ + static inline void Swap(void*) {} +}; +VTK_TEMPLATE_SPECIALIZE struct vtkByteSwapper<2> +{ + static inline void Swap(void* p) + { + char one_byte; + char* data = static_cast(p); + one_byte = data[0]; data[0] = data[1]; data[1] = one_byte; + } +}; +VTK_TEMPLATE_SPECIALIZE struct vtkByteSwapper<4> +{ + static inline void Swap(void* p) + { + char one_byte; + char* data = static_cast(p); + one_byte = data[0]; data[0] = data[3]; data[3] = one_byte; + one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; + } +}; +VTK_TEMPLATE_SPECIALIZE struct vtkByteSwapper<8> +{ + static inline void Swap(void* p) + { + char one_byte; + char* data = static_cast(p); + one_byte = data[0]; data[0] = data[7]; data[7] = one_byte; + one_byte = data[1]; data[1] = data[6]; data[6] = one_byte; + one_byte = data[2]; data[2] = data[5]; data[5] = one_byte; + one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; + } +}; + +//---------------------------------------------------------------------------- +// Define range swap functions. +template inline void vtkByteSwapRange(T* first, vtkIdType num) +{ + // Swap one value at a time. + T* last = first + num; + for(T* p=first; p != last; ++p) + { + vtkByteSwapper::Swap(p); + } +} +inline void vtkByteSwapRangeWrite(const char* first, vtkIdType num, + FILE* f, int) +{ + // No need to swap segments of 1 byte. + fwrite(first, sizeof(char), num, f); +} +inline void vtkByteSwapRangeWrite(const signed char* first, vtkIdType num, + FILE* f, int) +{ + // No need to swap segments of 1 byte. + fwrite(first, sizeof(signed char), num, f); +} +inline void vtkByteSwapRangeWrite(const unsigned char* first, vtkIdType num, + FILE* f, int) +{ + // No need to swap segments of 1 byte. + fwrite(first, sizeof(unsigned char), num, f); +} +template +inline void vtkByteSwapRangeWrite(const T* first, vtkIdType num, FILE* f, long) +{ + // Swap and write one value at a time. We do not need to do this in + // blocks because the file stream is already buffered. + const T* last = first + num; + for(const T* p=first; p != last; ++p) + { + T temp = *p; + vtkByteSwapper::Swap(&temp); + fwrite(&temp, sizeof(temp), 1, f); + } +} +inline void vtkByteSwapRangeWrite(const char* first, vtkIdType num, + ostream* os, int) +{ + // No need to swap segments of 1 byte. + os->write((char*)first, num*sizeof(char)); +} +inline void vtkByteSwapRangeWrite(const signed char* first, vtkIdType num, + ostream* os, int) +{ + // No need to swap segments of 1 byte. + os->write((char*)first, num*sizeof(signed char)); +} +inline void vtkByteSwapRangeWrite(const unsigned char* first, vtkIdType num, + ostream* os, int) +{ + // No need to swap segments of 1 byte. + os->write((char*)first, num*sizeof(unsigned char)); +} +template +inline void vtkByteSwapRangeWrite(const T* first, vtkIdType num, + ostream* os, long) +{ + // Swap and write one value at a time. We do not need to do this in + // blocks because the file stream is already buffered. + const T* last = first + num; + for(const T* p=first; p != last; ++p) + { + T temp = *p; + vtkByteSwapper::Swap(&temp); + os->write((char*)&temp, sizeof(temp)); + } +} + +//---------------------------------------------------------------------------- +// Define swap functions for each endian-ness. +#if defined(VTK_WORDS_BIGENDIAN) +template inline void vtkByteSwapBE(T*) {} +template inline void vtkByteSwapBERange(T*, vtkIdType) {} +template +inline void vtkByteSwapBERangeWrite(const T* p, vtkIdType num, FILE* f) +{ + fwrite(p, sizeof(T), num, f); +} +template +inline void vtkByteSwapBERangeWrite(const T* p, vtkIdType num, ostream* os) +{ + os->write((char*)p, sizeof(T)*num); +} +template inline void vtkByteSwapLE(T* p) +{ + vtkByteSwapper::Swap(p); +} +template inline void vtkByteSwapLERange(T* p, vtkIdType num) +{ + vtkByteSwapRange(p, num); +} +template +inline void vtkByteSwapLERangeWrite(const T* p, vtkIdType num, FILE* f) +{ + vtkByteSwapRangeWrite(p, num, f, 1); +} +template +inline void vtkByteSwapLERangeWrite(const T* p, vtkIdType num, ostream* os) +{ + vtkByteSwapRangeWrite(p, num, os, 1); +} +#else +template inline void vtkByteSwapBE(T* p) +{ + vtkByteSwapper::Swap(p); +} +template inline void vtkByteSwapBERange(T* p, vtkIdType num) +{ + vtkByteSwapRange(p, num); +} +template +inline void vtkByteSwapBERangeWrite(const T* p, vtkIdType num, FILE* f) +{ + vtkByteSwapRangeWrite(p, num, f, 1); +} +template +inline void vtkByteSwapBERangeWrite(const T* p, vtkIdType num, ostream* os) +{ + vtkByteSwapRangeWrite(p, num, os, 1); +} +template inline void vtkByteSwapLE(T*) {} +template inline void vtkByteSwapLERange(T*, vtkIdType) {} +template +inline void vtkByteSwapLERangeWrite(const T* p, vtkIdType num, FILE* f) +{ + fwrite(p, sizeof(T), num, f); +} +template +inline void vtkByteSwapLERangeWrite(const T* p, vtkIdType num, ostream* os) +{ + os->write((char*)p, sizeof(T)*num); +} +#endif + +//---------------------------------------------------------------------------- +#define VTK_BYTE_SWAP_IMPL(T) \ + void vtkByteSwap::SwapLE(T* p) { vtkByteSwapLE(p); } \ + void vtkByteSwap::SwapBE(T* p) { vtkByteSwapBE(p); } \ + void vtkByteSwap::SwapLERange(T* p, vtkIdType num) \ + { vtkByteSwapLERange(p, num); } \ + void vtkByteSwap::SwapBERange(T* p, vtkIdType num) \ + { vtkByteSwapBERange(p, num); } \ + void vtkByteSwap::SwapLERangeWrite(const T* p, vtkIdType num, FILE* file) \ + { vtkByteSwapLERangeWrite(p, num, file); } \ + void vtkByteSwap::SwapBERangeWrite(const T* p, vtkIdType num, FILE* file) \ + { vtkByteSwapBERangeWrite(p, num, file); } \ + void vtkByteSwap::SwapLERangeWrite(const T* p, vtkIdType num, ostream* os) \ + { vtkByteSwapLERangeWrite(p, num, os); } \ + void vtkByteSwap::SwapBERangeWrite(const T* p, vtkIdType num, ostream* os) \ + { vtkByteSwapBERangeWrite(p, num, os); } +VTK_BYTE_SWAP_IMPL(float) +VTK_BYTE_SWAP_IMPL(double) +VTK_BYTE_SWAP_IMPL(char) +VTK_BYTE_SWAP_IMPL(short) +VTK_BYTE_SWAP_IMPL(int) +VTK_BYTE_SWAP_IMPL(long) +VTK_BYTE_SWAP_IMPL(signed char) +VTK_BYTE_SWAP_IMPL(unsigned char) +VTK_BYTE_SWAP_IMPL(unsigned short) +VTK_BYTE_SWAP_IMPL(unsigned int) +VTK_BYTE_SWAP_IMPL(unsigned long) +#if defined(VTK_IMPL_USE_LONG_LONG) +VTK_BYTE_SWAP_IMPL(long long) +VTK_BYTE_SWAP_IMPL(unsigned long long) +#endif +#if defined(VTK_IMPL_USE___INT64) +VTK_BYTE_SWAP_IMPL(__int64) +VTK_BYTE_SWAP_IMPL(unsigned __int64) +#endif +#undef VTK_BYTE_SWAP_IMPL + +#if VTK_SIZEOF_SHORT == 2 +typedef short vtkByteSwapType2; +#else +# error "..." +#endif + +#if VTK_SIZEOF_INT == 4 +typedef int vtkByteSwapType4; +#else +# error "..." +#endif + +#if VTK_SIZEOF_DOUBLE == 8 +typedef double vtkByteSwapType8; +#else +# error "..." +#endif + +//---------------------------------------------------------------------------- +#define VTK_BYTE_SWAP_SIZE(S) \ + void vtkByteSwap::Swap##S##LE(void* p) \ + { vtkByteSwap::SwapLE(static_cast(p)); } \ + void vtkByteSwap::Swap##S##BE(void* p) \ + { vtkByteSwap::SwapBE(static_cast(p)); } \ + void vtkByteSwap::Swap##S##LERange(void* p, int n) \ + { vtkByteSwap::SwapLERange(static_cast(p), n); } \ + void vtkByteSwap::Swap##S##BERange(void* p, int n) \ + { vtkByteSwap::SwapBERange(static_cast(p), n); } \ + void vtkByteSwap::SwapWrite##S##LERange(const void* p, int n, FILE* f) \ + { vtkByteSwap::SwapLERangeWrite(static_cast(p), \ + n, f); } \ + void vtkByteSwap::SwapWrite##S##BERange(const void* p, int n, FILE* f) \ + { vtkByteSwap::SwapBERangeWrite(static_cast(p), \ + n, f); } \ + void vtkByteSwap::SwapWrite##S##LERange(const void* p, int n, ostream* os) \ + { vtkByteSwap::SwapLERangeWrite(static_cast(p), \ + n, os); } \ + void vtkByteSwap::SwapWrite##S##BERange(const void* p, int n, ostream* os) \ + { vtkByteSwap::SwapBERangeWrite(static_cast(p), \ + n, os); } +VTK_BYTE_SWAP_SIZE(2) +VTK_BYTE_SWAP_SIZE(4) +VTK_BYTE_SWAP_SIZE(8) +#undef VTK_BYTE_SWAP_SIZE + +//---------------------------------------------------------------------------- +// Swaps the bytes of a buffer. Uses an arbitrary word size, but +// assumes the word size is divisible by two. +void vtkByteSwap::SwapVoidRange(void *buffer, int numWords, int wordSize) +{ + unsigned char temp, *out, *buf; + int idx1, idx2, inc, half; + + half = wordSize / 2; + inc = wordSize - 1; + buf = (unsigned char *)(buffer); + + for (idx1 = 0; idx1 < numWords; ++idx1) + { + out = buf + inc; + for (idx2 = 0; idx2 < half; ++idx2) + { + temp = *out; + *out = *buf; + *buf = temp; + ++buf; + --out; + } + buf += half; + } +} diff --git a/Common/vtkByteSwap.h b/Common/vtkByteSwap.h new file mode 100644 index 0000000..cba1cd3 --- /dev/null +++ b/Common/vtkByteSwap.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkByteSwap.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkByteSwap - perform machine dependent byte swapping +// .SECTION Description +// vtkByteSwap is used by other classes to perform machine dependent byte +// swapping. Byte swapping is often used when reading or writing binary +// files. +#ifndef __vtkByteSwap_h +#define __vtkByteSwap_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkByteSwap : public vtkObject +{ +public: + static vtkByteSwap *New(); + vtkTypeRevisionMacro(vtkByteSwap,vtkObject); + + //BTX + // Description: + // Type-safe swap signatures to swap for storage in either Little + // Endian or Big Endian format. Swapping is performed according to + // the true size of the type given. +#define VTK_BYTE_SWAP_DECL(T) \ + static void SwapLE(T* p); \ + static void SwapBE(T* p); \ + static void SwapLERange(T* p, vtkIdType num); \ + static void SwapBERange(T* p, vtkIdType num); \ + static void SwapLERangeWrite(const T* p, vtkIdType num, FILE* file); \ + static void SwapBERangeWrite(const T* p, vtkIdType num, FILE* file); \ + static void SwapLERangeWrite(const T* p, vtkIdType num, ostream* os); \ + static void SwapBERangeWrite(const T* p, vtkIdType num, ostream* os) + VTK_BYTE_SWAP_DECL(float); + VTK_BYTE_SWAP_DECL(double); + VTK_BYTE_SWAP_DECL(char); + VTK_BYTE_SWAP_DECL(short); + VTK_BYTE_SWAP_DECL(int); + VTK_BYTE_SWAP_DECL(long); + VTK_BYTE_SWAP_DECL(signed char); + VTK_BYTE_SWAP_DECL(unsigned char); + VTK_BYTE_SWAP_DECL(unsigned short); + VTK_BYTE_SWAP_DECL(unsigned int); + VTK_BYTE_SWAP_DECL(unsigned long); +#if defined(VTK_DECL_USE_LONG_LONG) + VTK_BYTE_SWAP_DECL(long long); + VTK_BYTE_SWAP_DECL(unsigned long long); +#endif +#if defined(VTK_DECL_USE___INT64) + VTK_BYTE_SWAP_DECL(__int64); + VTK_BYTE_SWAP_DECL(unsigned __int64); +#endif +#undef VTK_BYTE_SWAP_DECL + //ETX + + // Description: + // Swap 2, 4, or 8 bytes for storage as Little Endian. + static void Swap2LE(void* p); + static void Swap4LE(void* p); + static void Swap8LE(void* p); + + // Description: + // Swap a block of 2-, 4-, or 8-byte segments for storage as Little Endian. + static void Swap2LERange(void* p, int num); + static void Swap4LERange(void* p, int num); + static void Swap8LERange(void* p, int num); + + // Description: + // Swap a block of 2-, 4-, or 8-byte segments for storage as Little Endian. + // The results are written directly to a file to avoid temporary storage. + static void SwapWrite2LERange(const void* p, int num, FILE* f); + static void SwapWrite4LERange(const void* p, int num, FILE* f); + static void SwapWrite8LERange(const void* p, int num, FILE* f); + static void SwapWrite2LERange(const void* p, int num, ostream* os); + static void SwapWrite4LERange(const void* p, int num, ostream* os); + static void SwapWrite8LERange(const void* p, int num, ostream* os); + + // Description: + // Swap 2, 4, or 8 bytes for storage as Big Endian. + static void Swap2BE(void* p); + static void Swap4BE(void* p); + static void Swap8BE(void* p); + + // Description: + // Swap a block of 2-, 4-, or 8-byte segments for storage as Big Endian. + static void Swap2BERange(void* p, int num); + static void Swap4BERange(void* p, int num); + static void Swap8BERange(void* p, int num); + + // Description: + // Swap a block of 2-, 4-, or 8-byte segments for storage as Big Endian. + // The results are written directly to a file to avoid temporary storage. + static void SwapWrite2BERange(const void* p, int num, FILE* f); + static void SwapWrite4BERange(const void* p, int num, FILE* f); + static void SwapWrite8BERange(const void* p, int num, FILE* f); + static void SwapWrite2BERange(const void* p, int num, ostream* os); + static void SwapWrite4BERange(const void* p, int num, ostream* os); + static void SwapWrite8BERange(const void* p, int num, ostream* os); + + // Description: + // Swaps the bytes of a buffer. Uses an arbitrary word size, but + // assumes the word size is divisible by two. + static void SwapVoidRange(void *buffer, int numWords, int wordSize); + +protected: + vtkByteSwap(); + ~vtkByteSwap(); + +private: + vtkByteSwap(const vtkByteSwap&); // Not implemented. + void operator=(const vtkByteSwap&); // Not implemented. +}; + +#endif diff --git a/Common/vtkCallbackCommand.cxx b/Common/vtkCallbackCommand.cxx new file mode 100644 index 0000000..da8c7a1 --- /dev/null +++ b/Common/vtkCallbackCommand.cxx @@ -0,0 +1,49 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCallbackCommand.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include "vtkCallbackCommand.h" + +//---------------------------------------------------------------- +vtkCallbackCommand::vtkCallbackCommand() +{ + this->ClientData = NULL; + this->Callback = NULL; + this->ClientDataDeleteCallback = NULL; + this->AbortFlagOnExecute = 0; +} + +vtkCallbackCommand::~vtkCallbackCommand() +{ + if (this->ClientDataDeleteCallback) + { + this->ClientDataDeleteCallback(this->ClientData); + } +} + +void vtkCallbackCommand::Execute(vtkObject *caller, unsigned long event, + void *callData) +{ + if (this->Callback) + { + this->Callback(caller, event, this->ClientData, callData); + if (this->AbortFlagOnExecute) + { + this->AbortFlagOn(); + } + } +} + diff --git a/Common/vtkCallbackCommand.h b/Common/vtkCallbackCommand.h new file mode 100644 index 0000000..518613c --- /dev/null +++ b/Common/vtkCallbackCommand.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCallbackCommand.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCallbackCommand - supports function callbacks +// .SECTION Description +// Use vtkCallbackCommand for generic function callbacks. That is, this class +// can be used when you wish to execute a function (of the signature +// described below) using the Command/Observer design pattern in VTK. +// The callback function should have the form +//

+// void func(vtkObject*, unsigned long eid, void* clientdata, void *calldata)
+// 
+// where the parameter vtkObject* is the object invoking the event; eid is +// the event id (see vtkCommand.h); clientdata is special data that should +// is associated with this instance of vtkCallbackCommand; and calldata is +// data that the vtkObject::InvokeEvent() may send with the callback. For +// example, the invocation of the ProgressEvent sends along the progress +// value as calldata. +// + +// .SECTION See Also +// vtkCommand vtkOldStyleCallbackCommand + +#ifndef __vtkCallbackCommand_h +#define __vtkCallbackCommand_h + +#include "vtkCommand.h" + +class VTK_COMMON_EXPORT vtkCallbackCommand : public vtkCommand +{ +public: + static vtkCallbackCommand *New() + {return new vtkCallbackCommand;}; + + // Description: + // Satisfy the superclass API for callbacks. Recall that the caller is + // the instance invoking the event; eid is the event id (see + // vtkCommand.h); and calldata is information sent when the callback + // was invoked (e.g., progress value in the vtkCommand::ProgressEvent). + virtual void Execute(vtkObject *caller, unsigned long eid, void *callData); + + // Description: + // Methods to set and get client and callback information, and the callback + // function. + virtual void SetClientData(void *cd) + { this->ClientData = cd; } + virtual void* GetClientData() + { return this->ClientData; } + virtual void SetCallback(void (*f)(vtkObject *caller, unsigned long eid, + void *clientdata, void *calldata)) + { this->Callback = f; } + virtual void SetClientDataDeleteCallback(void (*f)(void *)) + { this->ClientDataDeleteCallback = f; } + + // Description: + // Set/Get the abort flag on execute. If this is set to true the AbortFlag + // will be set to On automatically when the Execute method is triggered *and* + // a callback is set. + void SetAbortFlagOnExecute(int f) + { this->AbortFlagOnExecute = f; } + int GetAbortFlagOnExecute() + { return this->AbortFlagOnExecute; } + void AbortFlagOnExecuteOn() + { this->SetAbortFlagOnExecute(1); } + void AbortFlagOnExecuteOff() + { this->SetAbortFlagOnExecute(0); } + + void (*Callback)(vtkObject *, unsigned long, void *, void *); + void (*ClientDataDeleteCallback)(void *); + +protected: + + int AbortFlagOnExecute; + void *ClientData; + + vtkCallbackCommand(); + ~vtkCallbackCommand(); +}; + + + +#endif /* __vtkCallbackCommand_h */ + diff --git a/Common/vtkCharArray.cxx b/Common/vtkCharArray.cxx new file mode 100644 index 0000000..16483d9 --- /dev/null +++ b/Common/vtkCharArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCharArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(char); + +#define __vtkCharArray_cxx +#include "vtkCharArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkCharArray, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkCharArray); + +//---------------------------------------------------------------------------- +vtkCharArray::vtkCharArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkCharArray::~vtkCharArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkCharArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkCharArray.h b/Common/vtkCharArray.h new file mode 100644 index 0000000..51b53bb --- /dev/null +++ b/Common/vtkCharArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCharArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCharArray - dynamic, self-adjusting array of char +// .SECTION Description +// vtkCharArray is an array of values of type char. It provides +// methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkCharArray_h +#define __vtkCharArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkCharArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE char +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkCharArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkCharArray* New(); + vtkTypeRevisionMacro(vtkCharArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_CHAR; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, char* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const char* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const char* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const char* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + char GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, char value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, char f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(char f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + char* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + char* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(char* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkCharArray(vtkIdType numComp=1); + ~vtkCharArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkCharArray(const vtkCharArray&); // Not implemented. + void operator=(const vtkCharArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkCollection.cxx b/Common/vtkCollection.cxx new file mode 100644 index 0000000..8ca0dc6 --- /dev/null +++ b/Common/vtkCollection.cxx @@ -0,0 +1,323 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCollection.h" + +#include "vtkCollectionIterator.h" +#include "vtkGarbageCollector.h" +#include "vtkObjectFactory.h" + +#include +#include + +vtkCxxRevisionMacro(vtkCollection, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkCollection); + +// Construct with empty list. +vtkCollection::vtkCollection() +{ + this->NumberOfItems = 0; + this->Top = NULL; + this->Bottom = NULL; + this->Current = NULL; +} + +// Desctructor for the vtkCollection class. This removes all +// objects from the collection. +vtkCollection::~vtkCollection() +{ + vtkCollectionElement *elem; + + while (this->NumberOfItems ) + { + elem = this->Top; + this->Top = elem->Next; + this->Current = elem->Next; + this->NumberOfItems--; + this->DeleteElement(elem); + } +} + +// protected function to delete an element. Internal use only. +void vtkCollection::DeleteElement(vtkCollectionElement *e) +{ + if (e->Item != NULL) + { + e->Item->UnRegister(this); + } + delete e; +} + +// Add an object to the list. Does not prevent duplicate entries. +void vtkCollection::AddItem(vtkObject *a) +{ + vtkCollectionElement *elem; + + elem = new vtkCollectionElement; + + if (!this->Top) + { + this->Top = elem; + } + else + { + this->Bottom->Next = elem; + } + this->Bottom = elem; + + a->Register(this); + elem->Item = a; + elem->Next = NULL; + + this->Modified(); + + this->NumberOfItems++; +} + +// Remove an object from the list. Removes the first object found, not +// all occurrences. If no object found, list is unaffected. See warning +// in description of RemoveItem(int). +void vtkCollection::RemoveItem(vtkObject *a) +{ + int i; + vtkCollectionElement *elem; + + if (!this->Top) + { + return; + } + + elem = this->Top; + for (i = 0; i < this->NumberOfItems; i++) + { + if (elem->Item == a) + { + this->RemoveItem(i); + this->Modified(); + return; + } + else + { + elem = elem->Next; + } + } +} + +// Remove all objects from the list. +void vtkCollection::RemoveAllItems() +{ + vtkCollectionElement *elem; + + while (this->NumberOfItems ) + { + elem = this->Top; + this->Top = elem->Next; + this->Current = elem->Next; + this->NumberOfItems--; + this->DeleteElement(elem); + } + + this->Modified(); +} + +// Search for an object and return location in list. If location == 0, +// object was not found. +int vtkCollection::IsItemPresent(vtkObject *a) +{ + int i; + vtkCollectionElement *elem; + + if (!this->Top) + { + return 0; + } + + elem = this->Top; + for (i = 0; i < this->NumberOfItems; i++) + { + if (elem->Item == a) + { + return i + 1; + } + else + { + elem = elem->Next; + } + } + + return 0; +} + + +// Return the number of objects in the list. +int vtkCollection::GetNumberOfItems() +{ + return this->NumberOfItems; +} + + +void vtkCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Items: " << this->NumberOfItems << "\n"; +} + + +// Get the i'th item in the collection. NULL is returned if i is out +// of range +vtkObject *vtkCollection::GetItemAsObject(int i) +{ + vtkCollectionElement *elem=this->Top; + + if (i < 0) + { + return NULL; + } + + if (i == this->NumberOfItems - 1) + { + // optimize for the special case where we're looking for the last elem + elem = this->Bottom; + } + else + { + while (elem != NULL && i > 0) + { + elem = elem->Next; + i--; + } + } + if ( elem != NULL ) + { + return elem->Item; + } + else + { + return NULL; + } +} + + +// Replace the i'th item in the collection with a +void vtkCollection::ReplaceItem(int i, vtkObject *a) +{ + vtkCollectionElement *elem; + + if( i < 0 || i >= this->NumberOfItems ) + { + return; + } + + elem = this->Top; + if (i == this->NumberOfItems - 1) + { + elem = this->Bottom; + } + else + { + for (int j = 0; j < i; j++, elem = elem->Next ) + {} + } + + // Take care of reference counting + if (elem->Item != NULL) + { + elem->Item->UnRegister(this); + } + a->Register(this); + + // j == i + elem->Item = a; + + this->Modified(); +} + + +// Remove the i'th item in the list. +// Be careful if using this function during traversal of the list using +// GetNextItemAsObject (or GetNextItem in derived class). The list WILL +// be shortened if a valid index is given! If this->Current is equal to the +// element being removed, have it point to then next element in the list. +void vtkCollection::RemoveItem(int i) +{ + vtkCollectionElement *elem,*prev; + + if( i < 0 || i >= this->NumberOfItems ) + { + return; + } + + this->Modified(); + + elem = this->Top; + prev = NULL; + for (int j = 0; j < i; j++) + { + prev = elem; + elem = elem->Next; + } + + // j == i + if (prev) + { + prev->Next = elem->Next; + } + else + { + this->Top = elem->Next; + } + + if (!elem->Next) + { + this->Bottom = prev; + } + + if ( this->Current == elem ) + { + this->Current = elem->Next; + } + + this->NumberOfItems--; + this->DeleteElement(elem); +} + +vtkCollectionIterator* vtkCollection::NewIterator() +{ + vtkCollectionIterator* it = vtkCollectionIterator::New(); + it->SetCollection(this); + return it; +} + +//---------------------------------------------------------------------------- +void vtkCollection::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkCollection::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkCollection::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + for(vtkCollectionElement* elem = this->Top; elem; elem = elem->Next) + { + vtkGarbageCollectorReport(collector, elem->Item, "Element"); + } +} diff --git a/Common/vtkCollection.h b/Common/vtkCollection.h new file mode 100644 index 0000000..86768c0 --- /dev/null +++ b/Common/vtkCollection.h @@ -0,0 +1,186 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCollection - create and manipulate unsorted lists of objects +// .SECTION Description +// vtkCollection is a general object for creating and manipulating lists +// of objects. The lists are unsorted and allow duplicate entries. +// vtkCollection also serves as a base class for lists of specific types +// of objects. + +// .SECTION See Also +// vtkActorCollection vtkAssemblyPaths vtkDataSetCollection +// vtkImplicitFunctionCollection vtkLightCollection vtkPolyDataCollection +// vtkRenderWindowCollection vtkRendererCollection +// vtkStructuredPointsCollection vtkTransformCollection vtkVolumeCollection + +#ifndef __vtkCollection_h +#define __vtkCollection_h + +#include "vtkObject.h" + +//BTX - begin tcl exclude +class vtkCollectionElement //;prevents pick-up by man page generator +{ + public: + vtkCollectionElement():Item(NULL),Next(NULL) {}; + vtkObject *Item; + vtkCollectionElement *Next; +}; +typedef void * vtkCollectionSimpleIterator; +//ETX end tcl exclude + +class vtkCollectionIterator; + +class VTK_COMMON_EXPORT vtkCollection : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCollection,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with empty list. + static vtkCollection *New(); + + // Description: + // Add an object to the list. Does not prevent duplicate entries. + void AddItem(vtkObject *); + + // Description: + // Replace the i'th item in the collection with a + void ReplaceItem(int i, vtkObject *); + + // Description: + // Remove the i'th item in the list. + // Be careful if using this function during traversal of the list using + // GetNextItemAsObject (or GetNextItem in derived class). The list WILL + // be shortened if a valid index is given! If this->Current is equal to the + // element being removed, have it point to then next element in the list. + void RemoveItem(int i); + + // Description: + // Remove an object from the list. Removes the first object found, not + // all occurrences. If no object found, list is unaffected. See warning + // in description of RemoveItem(int). + void RemoveItem(vtkObject *); + + // Description: + // Remove all objects from the list. + void RemoveAllItems(); + + // Description: + // Search for an object and return location in list. If location == 0, + // object was not found. + int IsItemPresent(vtkObject *); + + // Description: + // Return the number of objects in the list. + int GetNumberOfItems(); + + // Description: + // Initialize the traversal of the collection. This means the data pointer + // is set at the beginning of the list. + void InitTraversal() { this->Current = this->Top;}; + + //BTX + // Description: + // A reentrant safe way to iterate through a collection. + // Just pass the same cookie value around each time + void InitTraversal(vtkCollectionSimpleIterator &cookie) { + cookie = static_cast(this->Top);}; + //ETX + + // Description: + // Get the next item in the collection. NULL is returned if the collection + // is exhausted. + vtkObject *GetNextItemAsObject(); + + // Description: + // Get the i'th item in the collection. NULL is returned if i is out + // of range + vtkObject *GetItemAsObject(int i); + + //BTX + // Description: + // A reentrant safe way to get the next object as a collection. Just pass the + // same cookie back and forth. + vtkObject *GetNextItemAsObject(vtkCollectionSimpleIterator &cookie); + //ETX + + // Description: + // Get an iterator to traverse the objects in this collection. + vtkCollectionIterator* NewIterator(); + + // Description: + // Participate in garbage collection. + virtual void Register(vtkObjectBase* o); + virtual void UnRegister(vtkObjectBase* o); +protected: + vtkCollection(); + ~vtkCollection(); + + virtual void DeleteElement(vtkCollectionElement *); + int NumberOfItems; + vtkCollectionElement *Top; + vtkCollectionElement *Bottom; + vtkCollectionElement *Current; + + //BTX + friend class vtkCollectionIterator; + //ETX + + // See vtkGarbageCollector.h: + virtual void ReportReferences(vtkGarbageCollector* collector); +private: + vtkCollection(const vtkCollection&); // Not implemented + void operator=(const vtkCollection&); // Not implemented +}; + + +inline vtkObject *vtkCollection::GetNextItemAsObject() +{ + vtkCollectionElement *elem=this->Current; + + if ( elem != NULL ) + { + this->Current = elem->Next; + return elem->Item; + } + else + { + return NULL; + } +} + +inline vtkObject *vtkCollection::GetNextItemAsObject(void *&cookie) +{ + vtkCollectionElement *elem=static_cast(cookie); + + if ( elem != NULL ) + { + cookie = static_cast(elem->Next); + return elem->Item; + } + else + { + return NULL; + } +} + +#endif + + + + + diff --git a/Common/vtkCollectionIterator.cxx b/Common/vtkCollectionIterator.cxx new file mode 100644 index 0000000..437601a --- /dev/null +++ b/Common/vtkCollectionIterator.cxx @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCollectionIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCollectionIterator.h" +#include "vtkObjectFactory.h" +#include "vtkCollection.h" + +vtkCxxRevisionMacro(vtkCollectionIterator, "$Revision: 1.4.12.1 $"); +vtkStandardNewMacro(vtkCollectionIterator); + +//---------------------------------------------------------------------------- +vtkCollectionIterator::vtkCollectionIterator() +{ + this->Element = 0; + this->Collection = 0; +} + +//---------------------------------------------------------------------------- +vtkCollectionIterator::~vtkCollectionIterator() +{ + this->SetCollection(0); +} + +//---------------------------------------------------------------------------- +void vtkCollectionIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if(this->Collection) + { + os << indent << "Collection: " << this->Collection << "\n"; + } + else + { + os << indent << "Collection: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkCollectionIterator::SetCollection(vtkCollection* collection) +{ + vtkSetObjectBodyMacro(Collection, vtkCollection, collection); + this->GoToFirstItem(); +} + +//---------------------------------------------------------------------------- +void vtkCollectionIterator::GoToFirstItem() +{ + if(this->Collection) + { + this->Element = this->Collection->Top; + } + else + { + this->Element = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkCollectionIterator::GoToNextItem() +{ + if(this->Element) + { + this->Element = this->Element->Next; + } +} + +//---------------------------------------------------------------------------- +int vtkCollectionIterator::IsDoneWithTraversal() +{ + return (this->Element? 0:1); +} + +//---------------------------------------------------------------------------- +vtkObject* vtkCollectionIterator::GetCurrentObject() +{ + if(this->Element) + { + return this->Element->Item; + } + return 0; +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetObject +vtkObject* vtkCollectionIterator::GetObjectA() +{ + VTK_LEGACY_REPLACED_BODY(vtkCollectionIterator::GetObject, "VTK 5.0", + vtkCollectionIterator::GetCurrentObject); + return this->GetCurrentObject(); +} +vtkObject* vtkCollectionIterator::GetObjectW() +{ + VTK_LEGACY_REPLACED_BODY(vtkCollectionIterator::GetObject, "VTK 5.0", + vtkCollectionIterator::GetCurrentObject); + return this->GetCurrentObject(); +} +# endif +vtkObject* vtkCollectionIterator::GetObject() +{ + VTK_LEGACY_REPLACED_BODY(vtkCollectionIterator::GetObject, "VTK 5.0", + vtkCollectionIterator::GetCurrentObject); + return this->GetCurrentObject(); +} +#endif diff --git a/Common/vtkCollectionIterator.h b/Common/vtkCollectionIterator.h new file mode 100644 index 0000000..bea67df --- /dev/null +++ b/Common/vtkCollectionIterator.h @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCollectionIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCollectionIterator - iterator through a vtkCollection. +// .SECTION Description +// vtkCollectionIterator provides an alternative way to traverse +// through the objects in a vtkCollection. Unlike the collection's +// built in interface, this allows multiple iterators to +// simultaneously traverse the collection. If items are removed from +// the collection, only the iterators currently pointing to those +// items are invalidated. Other iterators will still continue to +// function normally. + +#ifndef __vtkCollectionIterator_h +#define __vtkCollectionIterator_h + +#include "vtkObject.h" + +class vtkCollection; +class vtkCollectionElement; + +class VTK_COMMON_EXPORT vtkCollectionIterator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCollectionIterator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkCollectionIterator* New(); + + // Description: + // Set/Get the collection over which to iterate. + virtual void SetCollection(vtkCollection*); + vtkGetObjectMacro(Collection, vtkCollection); + + // Description: + // Position the iterator at the first item in the collection. + void InitTraversal() { this->GoToFirstItem(); } + + // Description: + // Position the iterator at the first item in the collection. + void GoToFirstItem(); + + // Description: + // Move the iterator to the next item in the collection. + void GoToNextItem(); + + // Description: + // Test whether the iterator is currently positioned at a valid item. + // Returns 1 for yes, 0 for no. + int IsDoneWithTraversal(); + + // Description: + // Get the item at the current iterator position. Valid only when + // IsDoneWithTraversal() returns 1. + vtkObject* GetCurrentObject(); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define GetObjectA GetObject +# define GetObjectW GetObject +#endif + + // Description: + // @deprecated Replaced by vtkCollectionIterator::GetCurrentObject() as + // of VTK 5.0. + VTK_LEGACY(vtkObject* GetObject()); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetObjectW +# undef GetObjectA + //BTX + VTK_LEGACY(vtkObject* GetObjectA()); + VTK_LEGACY(vtkObject* GetObjectW()); + //ETX +#endif + +protected: + vtkCollectionIterator(); + ~vtkCollectionIterator(); + + // The collection over which we are iterating. + vtkCollection* Collection; + + // The current iterator position. + vtkCollectionElement* Element; + + vtkObject* GetObjectInternal(); +private: + vtkCollectionIterator(const vtkCollectionIterator&); // Not implemented + void operator=(const vtkCollectionIterator&); // Not implemented +}; + +#endif diff --git a/Common/vtkCommand.cxx b/Common/vtkCommand.cxx new file mode 100644 index 0000000..3bd3ff3 --- /dev/null +++ b/Common/vtkCommand.cxx @@ -0,0 +1,158 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCommand.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkCommand.h" +#include "vtkDebugLeaks.h" + +// this list should only contain the initial, contiguous +// set of events and should not include UserEvent +static const char *vtkCommandEventStrings[] = { + "NoEvent", + "AnyEvent", + "DeleteEvent", + "StartEvent", + "EndEvent", + "RenderEvent", + "ProgressEvent", + "PickEvent", + "StartPickEvent", + "EndPickEvent", + "AbortCheckEvent", + "ExitEvent", + "LeftButtonPressEvent", + "LeftButtonReleaseEvent", + "MiddleButtonPressEvent", + "MiddleButtonReleaseEvent", + "RightButtonPressEvent", + "RightButtonReleaseEvent", + "EnterEvent", + "LeaveEvent", + "KeyPressEvent", + "KeyReleaseEvent", + "CharEvent", + "ExposeEvent", + "ConfigureEvent", + "TimerEvent", + "MouseMoveEvent", + "MouseWheelForwardEvent", + "MouseWheelBackwardEvent", + "ResetCameraEvent", + "ResetCameraClippingRangeEvent", + "ModifiedEvent", + "WindowLevelEvent", + "StartWindowLevelEvent", + "EndWindowLevelEvent", + "ResetWindowLevelEvent", + "SetOutputEvent", + "ErrorEvent", + "WarningEvent", + "StartInteractionEvent", + "InteractionEvent", + "EndInteractionEvent", + "EnableEvent", + "DisableEvent", + "CreateTimerEvent", + "DestroyTimerEvent", + "PlacePointEvent", + "PlaceWidgetEvent", + "CursorChangedEvent", + "ExecuteInformationEvent", + "RenderWindowMessageEvent", + "WrongTagEvent", + "StartAnimationCueEvent", + "AnimationCueTickEvent", + "EndAnimationCueEvent", + "VolumeMapperRenderProgressEvent", + "VolumeMapperComputeGradientsEndEvent", + "VolumeMapperComputeGradientsProgressEvent", + "VolumeMapperComputeGradientsStartEvent", + "WidgetModifiedEvent", + "WidgetValueChangedEvent", + "WidgetActivateEvent", + NULL +}; + +//---------------------------------------------------------------- +vtkCommand::vtkCommand():AbortFlag(0) +{ +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkCommand or subclass"); +#endif +} + + +//---------------------------------------------------------------- +void vtkCommand::UnRegister() +{ + int refcount = this->GetReferenceCount()-1; + this->SetReferenceCount(refcount); + if (refcount <= 0) + { +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass("vtkCommand or subclass"); +#endif + delete this; + } +} + +const char *vtkCommand::GetStringFromEventId(unsigned long event) +{ + static unsigned long numevents = 0; + + // find length of table + if (!numevents) + { + while (vtkCommandEventStrings[numevents] != NULL) + { + numevents++; + } + } + + if (event < numevents) + { + return vtkCommandEventStrings[event]; + } + else if (event == vtkCommand::UserEvent) + { + return "UserEvent"; + } + else + { + return "NoEvent"; + } +} + +unsigned long vtkCommand::GetEventIdFromString(const char *event) +{ + unsigned long i; + + for (i = 0; vtkCommandEventStrings[i] != NULL; i++) + { + if (!strcmp(vtkCommandEventStrings[i],event)) + { + return i; + } + } + if (!strcmp("UserEvent",event)) + { + return vtkCommand::UserEvent; + } + return vtkCommand::NoEvent; +} + + + + + diff --git a/Common/vtkCommand.h b/Common/vtkCommand.h new file mode 100644 index 0000000..f8eca39 --- /dev/null +++ b/Common/vtkCommand.h @@ -0,0 +1,181 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCommand.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCommand - superclass for callback/observer methods +// .SECTION Description +// vtkCommand is an implementation of the observer/command design +// pattern. In this design pattern, any instance of vtkObject can be +// "observed" for any events it might invoke. For example, +// vtkRenderer invokes a StartEvent as it begins to render and a +// EndEvent when it finishes rendering. Filters (subclasses of +// vtkProcessObject) invoke StartEvent, ProgressEvent, and EndEvent as +// the filter processes data. Observers of events are added with the +// AddObserver() method found in vtkObject. AddObserver(), besides +// requiring an event id or name, also takes an instance of vtkCommand +// (or a subclasses). Note that vtkCommand is meant to be subclassed, +// so that you can package the information necessary to support your +// callback. +// +// Event processing can be organized in priority lists, so it is +// possible to truncate the processing of a particular event by +// setting the AbortFlag variable. The priority is set using the +// AddObserver() method. By default the priority is 0, events of the +// same priority are processed in last-in-first-processed order. The +// ordering/aborting of events is important for things like 3D +// widgets, which handle an event if the widget is selected (and then +// aborting further processing of that event). Otherwise. the event +// is passed along for further processing. + +// .SECTION See Also +// vtkObject vtkCallbackCommand vtkOldStyleCallbackCommand +// vtkInteractorObserver vtk3DWidget + +#ifndef __vtkCommand_h +#define __vtkCommand_h + +#include "vtkObjectBase.h" + +class vtkObject; + +// The superclass that all commands should be subclasses of +class VTK_COMMON_EXPORT vtkCommand : public vtkObjectBase +{ +public: + // Description: + // Decrease the reference count (release by another object). This has + // the same effect as invoking Delete() (i.e., it reduces the reference + // count by 1). + void UnRegister(); + virtual void UnRegister(vtkObjectBase *) + { this->UnRegister(); } + + // Description: + // All derived classes of vtkCommand must implement this + // method. This is the method that actually does the work of the + // callback. The caller argument is the object invoking the event, + // the eventId parameter is the id of the event, and callData + // parameter is data that can be passed into the execute + // method. (Note: vtkObject::InvokeEvent() takes two parameters: the + // event id (or name) and call data. Typically call data is NULL, + // but the user can package data and pass it this + // way. Alternatively, a derived class of vtkCommand can be used to + // pass data.) + virtual void Execute(vtkObject *caller, unsigned long eventId, + void *callData) = 0; + + // Description: + // Convenience methods for translating between event names and event + // ids. + static const char *GetStringFromEventId(unsigned long event); + static unsigned long GetEventIdFromString(const char *event); + + // Description: + // Set/Get the abort flag. If this is set to true no further + // commands are executed. + void SetAbortFlag(int f) + { this->AbortFlag = f; } + int GetAbortFlag() + { return this->AbortFlag; } + void AbortFlagOn() + { this->SetAbortFlag(1); } + void AbortFlagOff() + { this->SetAbortFlag(0); } + +//BTX + // Description: + // All the currently defined events are listed here. Developers can + // use -- vtkCommand::UserEvent + int to specify their own event + // ids. If this list is adjusted, be sure to adjust + // vtkCommandEventStrings in vtkCommand.cxx to match. + enum EventIds { + NoEvent = 0, + AnyEvent, + DeleteEvent, + StartEvent, + EndEvent, + RenderEvent, + ProgressEvent, + PickEvent, + StartPickEvent, + EndPickEvent, + AbortCheckEvent, + ExitEvent, + LeftButtonPressEvent, + LeftButtonReleaseEvent, + MiddleButtonPressEvent, + MiddleButtonReleaseEvent, + RightButtonPressEvent, + RightButtonReleaseEvent, + EnterEvent, + LeaveEvent, + KeyPressEvent, + KeyReleaseEvent, + CharEvent, + ExposeEvent, + ConfigureEvent, + TimerEvent, + MouseMoveEvent, + MouseWheelForwardEvent, + MouseWheelBackwardEvent, + ResetCameraEvent, + ResetCameraClippingRangeEvent, + ModifiedEvent, + WindowLevelEvent, + StartWindowLevelEvent, + EndWindowLevelEvent, + ResetWindowLevelEvent, + SetOutputEvent, + ErrorEvent, + WarningEvent, + StartInteractionEvent, //mainly used by vtkInteractorObservers + InteractionEvent, + EndInteractionEvent, + EnableEvent, + DisableEvent, + CreateTimerEvent, + DestroyTimerEvent, + PlacePointEvent, + PlaceWidgetEvent, + CursorChangedEvent, + ExecuteInformationEvent, + RenderWindowMessageEvent, + WrongTagEvent, + StartAnimationCueEvent, // used by vtkAnimationCue + AnimationCueTickEvent, + EndAnimationCueEvent, + VolumeMapperRenderProgressEvent, + VolumeMapperComputeGradientsEndEvent, + VolumeMapperComputeGradientsProgressEvent, + VolumeMapperComputeGradientsStartEvent, + WidgetModifiedEvent, + WidgetValueChangedEvent, + WidgetActivateEvent, + UserEvent = 1000 + }; +//ETX + +protected: + int AbortFlag; + vtkCommand(); + virtual ~vtkCommand() {} + + friend class vtkSubjectHelper; +//BTX + vtkCommand(const vtkCommand& c) : vtkObjectBase(c) {} + void operator=(const vtkCommand&) {} +//ETX +}; + +#endif /* __vtkCommand_h */ + diff --git a/Common/vtkContourValues.cxx b/Common/vtkContourValues.cxx new file mode 100644 index 0000000..6a55d4d --- /dev/null +++ b/Common/vtkContourValues.cxx @@ -0,0 +1,175 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkContourValues.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkContourValues.h" +#include "vtkDoubleArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkContourValues, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkContourValues); + +// Construct object with a single contour value at 0.0. +vtkContourValues::vtkContourValues() +{ + this->Contours = vtkDoubleArray::New(); + this->Contours->Allocate(64); + this->Contours->InsertValue(0,0.0); +} + +vtkContourValues::~vtkContourValues() +{ + this->Contours->Delete(); +} + +// Set the ith contour value. +void vtkContourValues::SetValue(int i, double value) +{ + int numContours=this->Contours->GetMaxId()+1; + i = (i < 0 ? 0 : i); + + if ( i >= numContours || value != this->Contours->GetValue(i) ) + { + this->Modified(); + this->Contours->InsertValue(i,value); + } +} + +// Get the ith contour value. The return value will be clamped if the +// index i is out of range. +double vtkContourValues::GetValue(int i) +{ + i = (i < 0 ? 0 : i); + i = (i > this->Contours->GetMaxId() ? this->Contours->GetMaxId() : i); + return this->Contours->GetValue(i); +} + +// Return a pointer to a list of contour values. The contents of the +// list will be garbage if the number of contours <= 0. +double *vtkContourValues::GetValues() +{ + return this->Contours->GetPointer(0); +} + +// Fill a supplied list with contour values. Make sure you've +// allocated memory of size GetNumberOfContours(). +void vtkContourValues::GetValues(double *contourValues) +{ + int i, numContours=this->Contours->GetMaxId()+1; + + for ( i=0; i < numContours; i++ ) + { + contourValues[i] = this->Contours->GetValue(i); + } +} + +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +void vtkContourValues::SetNumberOfContours(const int number) +{ + int currentNumber = this->Contours->GetMaxId()+1; + int n = ( number < 0 ? 0 : number); + int i; + double *oldValues = NULL; + + if ( n != currentNumber ) + { + this->Modified(); + + // Keep a copy of the old values + if ( currentNumber > 0 ) + { + oldValues = new double[currentNumber]; + for ( i = 0; i < currentNumber; i++ ) + { + oldValues[i] = this->Contours->GetValue(i); + } + } + + this->Contours->SetNumberOfValues(n); + + // Copy them back in since the array may have been re-allocated + if ( currentNumber > 0 ) + { + int limit = (currentNumber < n)?(currentNumber):(n); + for ( i = 0; i < limit; i++ ) + { + this->Contours->SetValue( i, oldValues[i] ); + } + delete [] oldValues; + } + + } + // Set the new contour values to 0.0 + if (n > currentNumber) + { + for ( i = currentNumber; i < n; i++ ) + { + this->Contours->SetValue (i, 0.0); + } + } +} + +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +void vtkContourValues::GenerateValues(int numContours, double rangeStart, + double rangeEnd) +{ + double range[2]; + + range[0] = rangeStart; + range[1] = rangeEnd; + this->GenerateValues(numContours,range); +} + +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +void vtkContourValues::GenerateValues(int numContours, double range[2]) +{ + double val, incr; + int i; + + this->SetNumberOfContours(numContours); + if (numContours == 1) + { + incr = 0; + } + else + { + incr = (range[1] - range[0]) / (numContours-1); + } + for (i=0, val=range[0]; i < numContours; i++, val+=incr) + { + this->SetValue(i,val); + } +} + +// Return the number of contours in the +int vtkContourValues::GetNumberOfContours() +{ + return this->Contours->GetMaxId()+1; +} + +void vtkContourValues::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + int i, numContours=this->Contours->GetMaxId() + 1; + + os << indent << "Contour Values: \n"; + for ( i=0; i < numContours; i++) + { + os << indent << " Value " << i << ": " << this->Contours->GetValue(i) << "\n"; + } +} diff --git a/Common/vtkContourValues.h b/Common/vtkContourValues.h new file mode 100644 index 0000000..9c44cbe --- /dev/null +++ b/Common/vtkContourValues.h @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkContourValues.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkContourValues - helper object to manage setting and generating contour values +// .SECTION Description +// vtkContourValues is a general class to manage the creation, generation, +// and retrieval of contour values. This class serves as a helper class for +// contouring classes, or those classes operating on lists of contour values. + +// .SECTION See Also +// vtkContourFilter + +#ifndef __vtkContourValues_h +#define __vtkContourValues_h + +#include "vtkObject.h" + +class vtkDoubleArray; + +class VTK_COMMON_EXPORT vtkContourValues : public vtkObject +{ +public: + // Description: + // Construct object with a single contour value at 0.0. + static vtkContourValues *New(); + + vtkTypeRevisionMacro(vtkContourValues,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the ith contour value. + void SetValue(int i, double value); + + // Description: + // Get the ith contour value. The return value will be clamped if the + // index i is out of range. + double GetValue(int i); + + // Description: + // Return a pointer to a list of contour values. The contents of the + // list will be garbage if the number of contours <= 0. + double *GetValues(); + + // Description: + // Fill a supplied list with contour values. Make sure you've + // allocated memory of size GetNumberOfContours(). + void GetValues(double *contourValues); + + // Description: + // Set the number of contours to place into the list. You only really + // need to use this method to reduce list size. The method SetValue() + // will automatically increase list size as needed. + void SetNumberOfContours(const int number); + + // Description: + // Return the number of contours in the + int GetNumberOfContours(); + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double range[2]); + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + +protected: + vtkContourValues(); + ~vtkContourValues(); + + vtkDoubleArray *Contours; + +private: + vtkContourValues(const vtkContourValues&); // Not implemented. + void operator=(const vtkContourValues&); // Not implemented. +}; + +#endif diff --git a/Common/vtkCriticalSection.cxx b/Common/vtkCriticalSection.cxx new file mode 100644 index 0000000..1a55dad --- /dev/null +++ b/Common/vtkCriticalSection.cxx @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCriticalSection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCriticalSection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCriticalSection, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkCriticalSection); + +// New for the SimpleCriticalSection +vtkSimpleCriticalSection *vtkSimpleCriticalSection::New() +{ + return new vtkSimpleCriticalSection; +} + +void vtkSimpleCriticalSection::Init() +{ +#ifdef VTK_USE_SPROC + init_lock( &this->CritSec ); +#endif + +#ifdef VTK_USE_WIN32_THREADS + //this->MutexLock = CreateMutex( NULL, FALSE, NULL ); + InitializeCriticalSection(&this->CritSec); +#endif + +#ifdef VTK_USE_PTHREADS +#ifdef VTK_HP_PTHREADS + pthread_mutex_init(&(this->CritSec), pthread_mutexattr_default); +#else + pthread_mutex_init(&(this->CritSec), NULL); +#endif +#endif +} + + +// Destruct the vtkMutexVariable +vtkSimpleCriticalSection::~vtkSimpleCriticalSection() +{ +#ifdef VTK_USE_WIN32_THREADS + //CloseHandle(this->MutexLock); + DeleteCriticalSection(&this->CritSec); +#endif + +#ifdef VTK_USE_PTHREADS + pthread_mutex_destroy( &this->CritSec); +#endif +} + +// Lock the vtkCriticalSection +void vtkSimpleCriticalSection::Lock() +{ +#ifdef VTK_USE_SPROC + spin_lock( &this->CritSec ); +#endif + +#ifdef VTK_USE_WIN32_THREADS + //WaitForSingleObject( this->MutexLock, INFINITE ); + EnterCriticalSection(&this->CritSec); +#endif + +#ifdef VTK_USE_PTHREADS + pthread_mutex_lock( &this->CritSec); +#endif +} + +// Unlock the vtkCriticalSection +void vtkSimpleCriticalSection::Unlock() +{ +#ifdef VTK_USE_SPROC + release_lock( &this->CritSec ); +#endif + +#ifdef VTK_USE_WIN32_THREADS + //ReleaseMutex( this->MutexLock ); + LeaveCriticalSection(&this->CritSec); +#endif + +#ifdef VTK_USE_PTHREADS + pthread_mutex_unlock( &this->CritSec); +#endif +} + +void vtkCriticalSection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + diff --git a/Common/vtkCriticalSection.h b/Common/vtkCriticalSection.h new file mode 100644 index 0000000..87de926 --- /dev/null +++ b/Common/vtkCriticalSection.h @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCriticalSection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCriticalSection - critical section locking class +// .SECTION Description +// vtkCriticalSection allows the locking of variables which are accessed +// through different threads. This header file also defines +// vtkSimpleCriticalSection which is not a subclass of vtkObject. +// The API is identical to that of vtkMutexLock, and the behavior is +// identical as well, except on Windows 9x/NT platforms. The only difference +// on these platforms is that vtkMutexLock is more flexible, in that +// it works across processes as well as across threads, but also costs +// more, in that it evokes a 600-cycle x86 ring transition. The +// vtkCriticalSection provides a higher-performance equivalent (on +// Windows) but won't work across processes. Since it is unclear how, +// in vtk, an object at the vtk level can be shared across processes +// in the first place, one should use vtkCriticalSection unless one has +// a very good reason to use vtkMutexLock. If higher-performance equivalents +// for non-Windows platforms (Irix, SunOS, etc) are discovered, they +// should replace the implementations in this class + +#ifndef __vtkCriticalSection_h +#define __vtkCriticalSection_h + +#include "vtkObject.h" + +//BTX + +#ifdef VTK_USE_SPROC +#include // Needed for sproc implementation of mutex +typedef abilock_t vtkCritSecType; +#endif + +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) +#include // Needed for pthreads implementation of mutex +typedef pthread_mutex_t vtkCritSecType; +#endif + +#ifdef VTK_USE_WIN32_THREADS +# include "vtkWindows.h" // Needed for win32 implementation of mutex +typedef CRITICAL_SECTION vtkCritSecType; +#endif + +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS +#ifndef VTK_USE_WIN32_THREADS +typedef int vtkCritSecType; +#endif +#endif +#endif + +// Critical Section object that is not a vtkObject. +class VTK_COMMON_EXPORT vtkSimpleCriticalSection +{ +public: + vtkSimpleCriticalSection() + { + this->Init(); + } + + vtkSimpleCriticalSection(int isLocked) + { + this->Init(); + if(isLocked) + { + this->Lock(); + } + } + + void Init(); + + virtual ~vtkSimpleCriticalSection(); + + static vtkSimpleCriticalSection *New(); + + void Delete() {delete this;} + + // Description: + // Lock the vtkCriticalSection + void Lock( void ); + + // Description: + // Unlock the vtkCriticalSection + void Unlock( void ); + +protected: + vtkCritSecType CritSec; +}; + +//ETX + +class VTK_COMMON_EXPORT vtkCriticalSection : public vtkObject +{ +public: + static vtkCriticalSection *New(); + + vtkTypeRevisionMacro(vtkCriticalSection,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Lock the vtkCriticalSection + void Lock( void ); + + // Description: + // Unlock the vtkCriticalSection + void Unlock( void ); + +protected: + vtkSimpleCriticalSection SimpleCriticalSection; + vtkCriticalSection() {}; +private: + vtkCriticalSection(const vtkCriticalSection&); // Not implemented. + void operator=(const vtkCriticalSection&); // Not implemented. +}; + + +inline void vtkCriticalSection::Lock( void ) +{ + this->SimpleCriticalSection.Lock(); +} + +inline void vtkCriticalSection::Unlock( void ) +{ + this->SimpleCriticalSection.Unlock(); +} + +#endif diff --git a/Common/vtkCylindricalTransform.cxx b/Common/vtkCylindricalTransform.cxx new file mode 100644 index 0000000..e4285ca --- /dev/null +++ b/Common/vtkCylindricalTransform.cxx @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCylindricalTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCylindricalTransform.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include +#include + +vtkCxxRevisionMacro(vtkCylindricalTransform, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkCylindricalTransform); + +//---------------------------------------------------------------------------- +vtkCylindricalTransform::vtkCylindricalTransform() +{ +} + +vtkCylindricalTransform::~vtkCylindricalTransform() +{ +} + +void vtkCylindricalTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkWarpTransform::PrintSelf(os,indent); +} + +void vtkCylindricalTransform::InternalDeepCopy(vtkAbstractTransform *transform) +{ + vtkCylindricalTransform *cylindricalTransform = + (vtkCylindricalTransform *)transform; + + // copy these even though they aren't used + this->SetInverseTolerance(cylindricalTransform->InverseTolerance); + this->SetInverseIterations(cylindricalTransform->InverseIterations); + + // copy the inverse flag, which is used + if (this->InverseFlag != cylindricalTransform->InverseFlag) + { + this->InverseFlag = cylindricalTransform->InverseFlag; + this->Modified(); + } +} + +vtkAbstractTransform *vtkCylindricalTransform::MakeTransform() +{ + return vtkCylindricalTransform::New(); +} + +template +void vtkCylindricalToRectangular(const T inPoint[3], T outPoint[3], + T derivative[3][3]) +{ + T r = inPoint[0]; + T sintheta = sin(inPoint[1]); + T costheta = cos(inPoint[1]); + T z = inPoint[2]; + + outPoint[0] = r*costheta; + outPoint[1] = r*sintheta; + outPoint[2] = z; + + if (derivative) + { + derivative[0][0] = costheta; + derivative[0][1] = -r*sintheta; + derivative[0][2] = 0; + + derivative[1][0] = sintheta; + derivative[1][1] = r*costheta; + derivative[1][2] = 0; + + derivative[2][0] = 0; + derivative[2][1] = 0; + derivative[2][2] = 1; + } +} + +template +void vtkRectangularToCylindrical(const T inPoint[3], T outPoint[3]) +{ + T x = inPoint[0]; + T y = inPoint[1]; + T z = inPoint[2]; + + T rr = x*x + y*y; + + outPoint[0] = sqrt(rr); + if (rr == 0) + { + outPoint[1] = 0; + } + else + { + // Change range to [0, 2*Pi], otherwise the same as atan2(y, x) + outPoint[1] = vtkMath::Pi() + atan2(-y, -x); + } + outPoint[2] = z; +} + +void vtkCylindricalTransform::ForwardTransformPoint(const float inPoint[3], + float outPoint[3]) +{ + vtkCylindricalToRectangular(inPoint, outPoint, (float (*)[3])0); +} + +void vtkCylindricalTransform::ForwardTransformPoint(const double inPoint[3], + double outPoint[3]) +{ + vtkCylindricalToRectangular(inPoint, outPoint, (double (*)[3])0); +} + +void vtkCylindricalTransform::ForwardTransformDerivative( + const float inPoint[3], + float outPoint[3], + float derivative[3][3]) +{ + vtkCylindricalToRectangular(inPoint, outPoint, derivative); +} + +void vtkCylindricalTransform::ForwardTransformDerivative( + const double inPoint[3], + double outPoint[3], + double derivative[3][3]) +{ + vtkCylindricalToRectangular(inPoint, outPoint, derivative); +} + +void vtkCylindricalTransform::InverseTransformPoint(const float inPoint[3], + float outPoint[3]) +{ + vtkRectangularToCylindrical(inPoint, outPoint); +} + +void vtkCylindricalTransform::InverseTransformPoint(const double inPoint[3], + double outPoint[3]) +{ + vtkRectangularToCylindrical(inPoint, outPoint); +} + +void vtkCylindricalTransform::InverseTransformDerivative( + const float inPoint[3], + float outPoint[3], + float derivative[3][3]) +{ + float tmp[3]; + vtkRectangularToCylindrical(inPoint, outPoint); + vtkCylindricalToRectangular(outPoint, tmp, derivative); +} + +void vtkCylindricalTransform::InverseTransformDerivative( + const double inPoint[3], + double outPoint[3], + double derivative[3][3]) +{ + double tmp[3]; + vtkRectangularToCylindrical(inPoint, outPoint); + vtkCylindricalToRectangular(outPoint, tmp, derivative); +} + diff --git a/Common/vtkCylindricalTransform.h b/Common/vtkCylindricalTransform.h new file mode 100644 index 0000000..72c0658 --- /dev/null +++ b/Common/vtkCylindricalTransform.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCylindricalTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCylindricalTransform - cylindrical to rectangular coords and back +// .SECTION Description +// vtkCylindricalTransform will convert (r,theta,z) coordinates to +// (x,y,z) coordinates and back again. The angles are given in radians. +// By default, it converts cylindrical coordinates to rectangular, but +// GetInverse() returns a transform that will do the opposite. The +// equation that is used is x = r*cos(theta), y = r*sin(theta), z = z. +// .SECTION Caveats +// This transform is not well behaved along the line x=y=0 (i.e. along +// the z-axis) +// .SECTION see also +// vtkSphericalTransform vtkGeneralTransform + +#ifndef __vtkCylindricalTransform_h +#define __vtkCylindricalTransform_h + +#include "vtkWarpTransform.h" + +class VTK_COMMON_EXPORT vtkCylindricalTransform : public vtkWarpTransform +{ +public: + static vtkCylindricalTransform *New(); + vtkTypeRevisionMacro(vtkCylindricalTransform,vtkWarpTransform); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Make another transform of the same type. + vtkAbstractTransform *MakeTransform(); + +protected: + vtkCylindricalTransform(); + ~vtkCylindricalTransform(); + + // Description: + // Copy this transform from another of the same type. + void InternalDeepCopy(vtkAbstractTransform *transform); + + // Description: + // Internal functions for calculating the transformation. + void ForwardTransformPoint(const float in[3], float out[3]); + void ForwardTransformPoint(const double in[3], double out[3]); + + void ForwardTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void ForwardTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + void InverseTransformPoint(const float in[3], float out[3]); + void InverseTransformPoint(const double in[3], double out[3]); + + void InverseTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InverseTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + +private: + vtkCylindricalTransform(const vtkCylindricalTransform&); // Not implemented. + void operator=(const vtkCylindricalTransform&); // Not implemented. +}; + +#endif + diff --git a/Common/vtkDataArray.cxx b/Common/vtkDataArray.cxx new file mode 100644 index 0000000..e35ea83 --- /dev/null +++ b/Common/vtkDataArray.cxx @@ -0,0 +1,1044 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataArray.h" +#include "vtkBitArray.h" +#include "vtkCharArray.h" +#include "vtkCriticalSection.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIntArray.h" +#include "vtkIdTypeArray.h" +#include "vtkIdList.h" +#include "vtkLookupTable.h" +#include "vtkLongArray.h" +#include "vtkMath.h" +#include "vtkShortArray.h" +#include "vtkSignedCharArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#if defined(VTK_TYPE_USE_LONG_LONG) +# include "vtkLongLongArray.h" +# include "vtkUnsignedLongLongArray.h" +#endif + +#if defined(VTK_TYPE_USE___INT64) +# include "vtk__Int64Array.h" +# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) +# include "vtkUnsigned__Int64Array.h" +# endif +#endif + +vtkCxxRevisionMacro(vtkDataArray, "$Revision: 1.69 $"); + +//---------------------------------------------------------------------------- +// Construct object with default tuple dimension (number of components) of 1. +vtkDataArray::vtkDataArray(vtkIdType numComp) +{ + this->Range[0] = 0; + this->Range[1] = 1; + + this->Size = 0; + this->MaxId = -1; + this->LookupTable = NULL; + + this->NumberOfComponents = (numComp < 1 ? 1 : numComp); + this->Name = 0; +} + +//---------------------------------------------------------------------------- +vtkDataArray::~vtkDataArray() +{ + if ( this->LookupTable ) + { + this->LookupTable->Delete(); + } + this->SetName(0); +} + +//---------------------------------------------------------------------------- +template +void vtkDeepCopyArrayOfDifferentType(IT *input, OT *output, + int numTuples, int nComp) +{ + int i, j; + for (i=0; i(input[i*nComp+j]); + } + } +} + +//---------------------------------------------------------------------------- +template +void vtkDeepCopySwitchOnOutput(IT *input, vtkDataArray *da, + int numTuples, int nComp) +{ + void *output = da->GetVoidPointer(0); + + switch (da->GetDataType()) + { + vtkTemplateMacro( + vtkDeepCopyArrayOfDifferentType (input, + (VTK_TT*)output, + numTuples, + nComp) ); + + default: + vtkGenericWarningMacro("Unsupported data type " << da->GetDataType() + <<"!"); + } +} + +//---------------------------------------------------------------------------- +//Normally subclasses will do this when the input and output type of the +//DeepCopy are the same. When they are not the same, then we use the +//templated code below. +void vtkDataArray::DeepCopy(vtkDataArray *da) +{ + // Match the behavior of the old AttributeData + if ( da == NULL ) + { + return; + } + + if ( this != da ) + { + int numTuples = da->GetNumberOfTuples(); + this->NumberOfComponents = da->NumberOfComponents; + this->SetNumberOfTuples(numTuples); + void *input=da->GetVoidPointer(0); + + switch (da->GetDataType()) + { + vtkTemplateMacro( + vtkDeepCopySwitchOnOutput((VTK_TT*)input, + this, + numTuples, + this->NumberOfComponents)); + + case VTK_BIT: + {//bit not supported, using generic double API + for (int i=0; i < numTuples; i++) + { + this->SetTuple(i, da->GetTuple(i)); + } + break; + } + + default: + vtkErrorMacro("Unsupported data type " << da->GetDataType() << "!"); + } + + this->SetLookupTable(0); + if (da->LookupTable) + { + this->LookupTable = da->LookupTable->NewInstance(); + this->LookupTable->DeepCopy(da->LookupTable); + } + } +} + +//---------------------------------------------------------------------------- +// These can be overridden for more efficiency +double vtkDataArray::GetComponent(vtkIdType i, int j) +{ + double *tuple=new double[this->NumberOfComponents], c; + + this->GetTuple(i,tuple); + c = tuple[j]; + delete [] tuple; + + return c; +} + +//---------------------------------------------------------------------------- +void vtkDataArray::SetComponent(vtkIdType i, int j, double c) +{ + double *tuple=new double[this->NumberOfComponents]; + + if ( i < this->GetNumberOfTuples() ) + { + this->GetTuple(i,tuple); + } + else + { + for (int k=0; kNumberOfComponents; k++) + { + tuple[k] = 0.0; + } + } + + tuple[j] = c; + this->SetTuple(i,tuple); + + delete [] tuple; +} + +//---------------------------------------------------------------------------- +void vtkDataArray::InsertComponent(vtkIdType i, int j, double c) +{ + double *tuple=new double[this->NumberOfComponents]; + + if ( i < this->GetNumberOfTuples() ) + { + this->GetTuple(i,tuple); + } + else + { + for (int k=0; kNumberOfComponents; k++) + { + tuple[k] = 0.0; + } + } + + tuple[j] = c; + this->InsertTuple(i,tuple); + + delete [] tuple; +} + +//---------------------------------------------------------------------------- +void vtkDataArray::GetData(vtkIdType tupleMin, vtkIdType tupleMax, int compMin, + int compMax, vtkDoubleArray* data) +{ + int i, j; + int numComp=this->GetNumberOfComponents(); + double *tuple=new double[numComp]; + double *ptr=data->WritePointer(0,(tupleMax-tupleMin+1)*(compMax-compMin+1)); + + for (j=tupleMin; j <= tupleMax; j++) + { + this->GetTuple(j,tuple); + for (i=compMin; i <= compMax; i++) + { + *ptr++ = tuple[i]; + } + } + delete [] tuple; +} + +//---------------------------------------------------------------------------- +void vtkDataArray::CreateDefaultLookupTable() +{ + if ( this->LookupTable ) + { + this->LookupTable->UnRegister(this); + } + this->LookupTable = vtkLookupTable::New(); + // make sure it is built + // otherwise problems with InsertScalar trying to map through + // non built lut + this->LookupTable->Build(); +} + +//---------------------------------------------------------------------------- +void vtkDataArray::SetLookupTable(vtkLookupTable* lut) +{ + if ( this->LookupTable != lut ) + { + if ( this->LookupTable ) + { + this->LookupTable->UnRegister(this); + } + this->LookupTable = lut; + this->LookupTable->Register(this); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +double* vtkDataArray::GetTupleN(vtkIdType i, int n) +{ + int numComp = this->GetNumberOfComponents(); + if (numComp != n) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != " << n); + } + return this->GetTuple(i); +} + +//---------------------------------------------------------------------------- +double vtkDataArray::GetTuple1(vtkIdType i) +{ + int numComp = this->GetNumberOfComponents(); + if (numComp != 1) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 1"); + } + return *(this->GetTuple(i)); +} + +//---------------------------------------------------------------------------- +double* vtkDataArray::GetTuple2(vtkIdType i) +{ + return this->GetTupleN(i, 2); +} +//---------------------------------------------------------------------------- +double* vtkDataArray::GetTuple3(vtkIdType i) +{ + return this->GetTupleN(i, 3); +} +//---------------------------------------------------------------------------- +double* vtkDataArray::GetTuple4(vtkIdType i) +{ + return this->GetTupleN(i, 4); +} +//---------------------------------------------------------------------------- +double* vtkDataArray::GetTuple9(vtkIdType i) +{ + return this->GetTupleN(i, 9); +} + +//---------------------------------------------------------------------------- +void vtkDataArray::SetTuple1(vtkIdType i, double value) +{ + int numComp = this->GetNumberOfComponents(); + if (numComp != 1) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 1"); + } + this->SetTuple(i, &value); +} +//---------------------------------------------------------------------------- +void vtkDataArray::SetTuple2(vtkIdType i, double val0, double val1) +{ + double tuple[2]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 2) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 2"); + } + tuple[0] = val0; + tuple[1] = val1; + this->SetTuple(i, tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::SetTuple3(vtkIdType i, double val0, double val1, + double val2) +{ + double tuple[3]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 3) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 3"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + this->SetTuple(i, tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::SetTuple4(vtkIdType i, double val0, double val1, + double val2, double val3) +{ + double tuple[4]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 4) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 4"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + tuple[3] = val3; + this->SetTuple(i, tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::SetTuple9(vtkIdType i, double val0, double val1, + double val2, double val3, double val4, + double val5, double val6, double val7, double val8) +{ + double tuple[9]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 9) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 9"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + tuple[3] = val3; + tuple[4] = val4; + tuple[5] = val5; + tuple[6] = val6; + tuple[7] = val7; + tuple[8] = val8; + this->SetTuple(i, tuple); +} + +//---------------------------------------------------------------------------- +void vtkDataArray::InsertTuple1(vtkIdType i, double value) +{ + int numComp = this->GetNumberOfComponents(); + if (numComp != 1) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 1"); + } + this->InsertTuple(i, &value); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertTuple2(vtkIdType i, double val0, double val1) +{ + double tuple[2]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 2) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 2"); + } + tuple[0] = val0; + tuple[1] = val1; + this->InsertTuple(i, tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertTuple3(vtkIdType i, double val0, double val1, + double val2) +{ + double tuple[3]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 3) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 3"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + this->InsertTuple(i, tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertTuple4(vtkIdType i, double val0, double val1, + double val2, double val3) +{ + double tuple[4]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 4) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 4"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + tuple[3] = val3; + this->InsertTuple(i, tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertTuple9(vtkIdType i, double val0, double val1, + double val2, double val3, double val4, + double val5, double val6,double val7, double val8) +{ + double tuple[9]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 9) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 9"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + tuple[3] = val3; + tuple[4] = val4; + tuple[5] = val5; + tuple[6] = val6; + tuple[7] = val7; + tuple[8] = val8; + this->InsertTuple(i, tuple); +} + +//---------------------------------------------------------------------------- +void vtkDataArray::InsertNextTuple1(double value) +{ + int numComp = this->GetNumberOfComponents(); + if (numComp != 1) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 1"); + } + this->InsertNextTuple(&value); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertNextTuple2(double val0, double val1) +{ + double tuple[2]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 2) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 2"); + } + tuple[0] = val0; + tuple[1] = val1; + this->InsertNextTuple(tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertNextTuple3(double val0, double val1, + double val2) +{ + double tuple[3]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 3) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 3"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + this->InsertNextTuple(tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertNextTuple4(double val0, double val1, + double val2, double val3) +{ + double tuple[4]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 4) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 4"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + tuple[3] = val3; + this->InsertNextTuple(tuple); +} +//---------------------------------------------------------------------------- +void vtkDataArray::InsertNextTuple9(double val0, double val1, + double val2, double val3, double val4, + double val5, double val6,double val7, + double val8) +{ + double tuple[9]; + int numComp = this->GetNumberOfComponents(); + if (numComp != 9) + { + vtkErrorMacro("The number of components do not match the number requested: " + << numComp << " != 9"); + } + tuple[0] = val0; + tuple[1] = val1; + tuple[2] = val2; + tuple[3] = val3; + tuple[4] = val4; + tuple[5] = val5; + tuple[6] = val6; + tuple[7] = val7; + tuple[8] = val8; + this->InsertNextTuple(tuple); +} + +//---------------------------------------------------------------------------- +template +unsigned long vtkDataArrayGetDataTypeSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +unsigned long vtkDataArray::GetDataTypeSize(int type) +{ + switch (type) + { + vtkTemplateMacro( + return vtkDataArrayGetDataTypeSize(static_cast(0)) + ); + case VTK_BIT: + return 1; + break; + default: + vtkGenericWarningMacro("Unsupported data type " << type << "!"); + } + return 1; +} + +//---------------------------------------------------------------------------- +unsigned long vtkDataArray::GetActualMemorySize() +{ + unsigned long numPrims; + double size = 0.0; + // The allocated array may be larger than the number of primatives used. + //numPrims = this->GetNumberOfTuples() * this->GetNumberOfComponents(); + numPrims = this->GetSize(); + + size = vtkDataArray::GetDataTypeSize(this->GetDataType()); + + return (unsigned long)ceil((size * numPrims)/1000.0); //kilobytes +} + +//---------------------------------------------------------------------------- +vtkDataArray* vtkDataArray::CreateDataArray(int dataType) +{ + switch (dataType) + { + case VTK_BIT: + return vtkBitArray::New(); + + case VTK_CHAR: + return vtkCharArray::New(); + + case VTK_SIGNED_CHAR: + return vtkSignedCharArray::New(); + + case VTK_UNSIGNED_CHAR: + return vtkUnsignedCharArray::New(); + + case VTK_SHORT: + return vtkShortArray::New(); + + case VTK_UNSIGNED_SHORT: + return vtkUnsignedShortArray::New(); + + case VTK_INT: + return vtkIntArray::New(); + + case VTK_UNSIGNED_INT: + return vtkUnsignedIntArray::New(); + + case VTK_LONG: + return vtkLongArray::New(); + + case VTK_UNSIGNED_LONG: + return vtkUnsignedLongArray::New(); + +#if defined(VTK_TYPE_USE_LONG_LONG) + case VTK_LONG_LONG: + return vtkLongLongArray::New(); + + case VTK_UNSIGNED_LONG_LONG: + return vtkUnsignedLongLongArray::New(); +#endif + +#if defined(VTK_TYPE_USE___INT64) + case VTK___INT64: + return vtk__Int64Array::New(); + break; + +# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + case VTK_UNSIGNED___INT64: + return vtkUnsigned__Int64Array::New(); + break; +# endif +#endif + + case VTK_FLOAT: + return vtkFloatArray::New(); + + case VTK_DOUBLE: + return vtkDoubleArray::New(); + + case VTK_ID_TYPE: + return vtkIdTypeArray::New(); + + default: + vtkGenericWarningMacro("Unsupported data type " << dataType + << "! Setting to VTK_DOUBLE"); + return vtkDoubleArray::New(); + } +} + +//---------------------------------------------------------------------------- +template +void vtkCopyTuples(IT* input, OT* output, int nComp, vtkIdList* ptIds ) +{ + int i, j; + int num=ptIds->GetNumberOfIds(); + for (i=0; i(input[ptIds->GetId(i)*nComp+j]); + } + } +} + +//---------------------------------------------------------------------------- +template +void vtkCopyTuples1(IT* input, vtkDataArray* output, vtkIdList* ptIds) +{ + switch (output->GetDataType()) + { + vtkTemplateMacro(vtkCopyTuples(input, + (VTK_TT *)output->GetVoidPointer(0), + output->GetNumberOfComponents(), ptIds) ); + + default: + vtkGenericWarningMacro("Sanity check failed: Unsupported data type " + << output->GetDataType() << "."); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkDataArray::GetTuples(vtkIdList *ptIds, vtkDataArray *da) +{ + + if ((da->GetNumberOfComponents() != this->GetNumberOfComponents())) + { + vtkWarningMacro("Number of components for input and output do not match"); + return; + } + + switch (this->GetDataType()) + { + vtkTemplateMacro(vtkCopyTuples1 ((VTK_TT *)this->GetVoidPointer(0), da, + ptIds )); + // This is not supported by the template macro. + // Switch to using the double interface. + case VTK_BIT: + { + vtkIdType num=ptIds->GetNumberOfIds(); + for (vtkIdType i=0; iSetTuple(i,this->GetTuple(ptIds->GetId(i))); + } + } + break; + default: + vtkErrorMacro("Sanity check failed: Unsupported data type " + << this->GetDataType() << "."); + return; + } +} + +//---------------------------------------------------------------------------- +template +void vtkCopyTuples(IT* input, OT* output, int nComp, + vtkIdType p1, vtkIdType p2) +{ + int i, j; + int num=p2-p1+1; + for (i=0; i(input[(p1+i)*nComp+j]); + } + } +} + +//---------------------------------------------------------------------------- +template +void vtkCopyTuples1(IT* input, vtkDataArray* output, + vtkIdType p1, vtkIdType p2) +{ + switch (output->GetDataType()) + { + vtkTemplateMacro(vtkCopyTuples( input, + (VTK_TT *)output->GetVoidPointer(0), + output->GetNumberOfComponents(), p1, p2) ); + + default: + vtkGenericWarningMacro("Sanity check failed: Unsupported data type " + << output->GetDataType() << "."); + return; + } +} + + +//---------------------------------------------------------------------------- +void vtkDataArray::GetTuples(vtkIdType p1, vtkIdType p2, vtkDataArray *da) +{ + + if ((da->GetNumberOfComponents() != this->GetNumberOfComponents())) + { + vtkWarningMacro("Number of components for input and output do not match"); + return; + } + + switch (this->GetDataType()) + { + vtkTemplateMacro(vtkCopyTuples1( (VTK_TT *)this->GetVoidPointer(0), da, + p1, p2 ) ); + // This is not supported by the template macro. + // Switch to using the double interface. + case VTK_BIT: + { + vtkIdType num=p2-p1+1; + for (vtkIdType i=0; iSetTuple(i,this->GetTuple(p1+i)); + } + } + break; + default: + vtkErrorMacro("Sanity check failed: Unsupported data type " + << this->GetDataType() << "."); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkDataArray::FillComponent(int j, double c) +{ + if (j < 0 || j >= this->GetNumberOfComponents()) + { + vtkErrorMacro(<< "Specified component " << j << " is not in [0, " + << this->GetNumberOfComponents() << ")" ); + return; + } + + vtkIdType i; + + for (i = 0; i < this->GetNumberOfTuples(); i++) + { + this->SetComponent(i, j, c); + } +} + + +//---------------------------------------------------------------------------- +void vtkDataArray::CopyComponent(int j, vtkDataArray *from, + int fromComponent) +{ + if (this->GetNumberOfTuples() != from->GetNumberOfTuples()) + { + vtkErrorMacro(<< "Number of tuples in 'from' (" + << from->GetNumberOfTuples() << ") and 'to' (" + << this->GetNumberOfTuples() << ") do not match."); + return; + } + + if (j < 0 || j >= this->GetNumberOfComponents()) + { + vtkErrorMacro(<< "Specified component " << j << " in 'to' array is not in [0, " + << this->GetNumberOfComponents() << ")" ); + return; + } + + if (fromComponent < 0 || fromComponent >= from->GetNumberOfComponents()) + { + vtkErrorMacro(<< "Specified component " << fromComponent << " in 'from' array is not in [0, " + << from->GetNumberOfComponents() << ")" ); + return; + } + + vtkIdType i; + for (i = 0; i < this->GetNumberOfTuples(); i++) + { + this->SetComponent(i, j, from->GetComponent(i, fromComponent)); + } +} + +//---------------------------------------------------------------------------- +double vtkDataArray::GetMaxNorm() +{ + vtkIdType i; + double norm, maxNorm; + int nComponents = this->GetNumberOfComponents(); + + maxNorm = 0.0; + for (i=0; iGetNumberOfTuples(); i++) + { + norm = vtkMath::Norm(this->GetTuple(i), nComponents); + if ( norm > maxNorm ) + { + maxNorm = norm; + } + } + + return maxNorm; +} + +//---------------------------------------------------------------------------- +void vtkDataArray::ComputeRange(int comp) +{ + double s,t; + vtkIdType numTuples; + + if (comp < 0 && this->NumberOfComponents == 1) + { + comp = 0; + } + + int idx = comp; + idx = (idx<0)?(this->NumberOfComponents):(idx); + + if (idx >= VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES || + (this->GetMTime() > this->ComponentRangeComputeTime[idx]) ) + { + numTuples=this->GetNumberOfTuples(); + this->Range[0] = VTK_DOUBLE_MAX; + this->Range[1] = VTK_DOUBLE_MIN; + + for (vtkIdType i=0; i= 0) + { + s = this->GetComponent(i,comp); + } + else + { // Compute range of vector magnitude. + s = 0.0; + for (int j=0; j < this->NumberOfComponents; ++j) + { + t = this->GetComponent(i,j); + s += t*t; + } + s = sqrt(s); + } + if ( s < this->Range[0] ) + { + this->Range[0] = s; + } + if ( s > this->Range[1] ) + { + this->Range[1] = s; + } + } + if (idx < VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES) + { + this->ComponentRangeComputeTime[idx].Modified(); + this->ComponentRange[idx][0] = this->Range[0]; + this->ComponentRange[idx][1] = this->Range[1]; + } + } + else + { + this->Range[0] = this->ComponentRange[idx][0]; + this->Range[1] = this->ComponentRange[idx][1]; + } +} + +//---------------------------------------------------------------------------- +void vtkDataArray::GetDataTypeRange(double range[2]) +{ + vtkDataArray::GetDataTypeRange(this->GetDataType(), range); +} + +//---------------------------------------------------------------------------- +double vtkDataArray::GetDataTypeMin() +{ + return vtkDataArray::GetDataTypeMin(this->GetDataType()); +} + +//---------------------------------------------------------------------------- +double vtkDataArray::GetDataTypeMax() +{ + return vtkDataArray::GetDataTypeMax(this->GetDataType()); +} + +//---------------------------------------------------------------------------- +void vtkDataArray::GetDataTypeRange(int type, double range[2]) +{ + range[0] = vtkDataArray::GetDataTypeMin(type); + range[1] = vtkDataArray::GetDataTypeMax(type); +} + +//---------------------------------------------------------------------------- +double vtkDataArray::GetDataTypeMin(int type) +{ + switch (type) + { + case VTK_BIT: return (double)VTK_BIT_MIN; + case VTK_SIGNED_CHAR: return (double)VTK_SIGNED_CHAR_MIN; + case VTK_UNSIGNED_CHAR: return (double)VTK_UNSIGNED_CHAR_MIN; + case VTK_CHAR: return (double)VTK_CHAR_MIN; + case VTK_UNSIGNED_SHORT: return (double)VTK_UNSIGNED_SHORT_MIN; + case VTK_SHORT: return (double)VTK_SHORT_MIN; + case VTK_UNSIGNED_INT: return (double)VTK_UNSIGNED_INT_MIN; + case VTK_INT: return (double)VTK_INT_MIN; + case VTK_UNSIGNED_LONG: return (double)VTK_UNSIGNED_LONG_MIN; + case VTK_LONG: return (double)VTK_LONG_MIN; +#if defined(VTK_TYPE_USE_LONG_LONG) + case VTK_UNSIGNED_LONG_LONG: return (double)VTK_UNSIGNED_LONG_LONG_MIN; + case VTK_LONG_LONG: return (double)VTK_LONG_LONG_MIN; +#endif +#if defined(VTK_TYPE_USE___INT64) + case VTK___INT64: return (double)VTK___INT64_MIN; +# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + case VTK_UNSIGNED___INT64: return (double)VTK_UNSIGNED___INT64_MIN; +# endif +#endif + case VTK_FLOAT: return (double)VTK_FLOAT_MIN; + case VTK_DOUBLE: return (double)VTK_DOUBLE_MIN; + default: return 0; + } +} + +//---------------------------------------------------------------------------- +double vtkDataArray::GetDataTypeMax(int type) +{ + switch (type) + { + case VTK_BIT: return (double)VTK_BIT_MAX; + case VTK_SIGNED_CHAR: return (double)VTK_SIGNED_CHAR_MAX; + case VTK_UNSIGNED_CHAR: return (double)VTK_UNSIGNED_CHAR_MAX; + case VTK_CHAR: return (double)VTK_CHAR_MAX; + case VTK_UNSIGNED_SHORT: return (double)VTK_UNSIGNED_SHORT_MAX; + case VTK_SHORT: return (double)VTK_SHORT_MAX; + case VTK_UNSIGNED_INT: return (double)VTK_UNSIGNED_INT_MAX; + case VTK_INT: return (double)VTK_INT_MAX; + case VTK_UNSIGNED_LONG: return (double)VTK_UNSIGNED_LONG_MAX; + case VTK_LONG: return (double)VTK_LONG_MAX; +#if defined(VTK_TYPE_USE_LONG_LONG) + case VTK_UNSIGNED_LONG_LONG: return (double)VTK_UNSIGNED_LONG_LONG_MAX; + case VTK_LONG_LONG: return (double)VTK_LONG_LONG_MAX; +#endif +#if defined(VTK_TYPE_USE___INT64) + case VTK___INT64: return (double)VTK___INT64_MAX; +# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + case VTK_UNSIGNED___INT64: return (double)VTK_UNSIGNED___INT64_MAX; +# endif +#endif + case VTK_FLOAT: return (double)VTK_FLOAT_MAX; + case VTK_DOUBLE: return (double)VTK_DOUBLE_MAX; + default: return 1; + } +} + +//---------------------------------------------------------------------------- +void vtkDataArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + const char* name = this->GetName(); + if (name) + { + os << indent << "Name: " << name << "\n"; + } + else + { + os << indent << "Name: (none)\n"; + } + os << indent << "Number Of Components: " << this->NumberOfComponents << "\n"; + os << indent << "Number Of Tuples: " << this->GetNumberOfTuples() << "\n"; + os << indent << "Size: " << this->Size << "\n"; + os << indent << "MaxId: " << this->MaxId << "\n"; + if ( this->LookupTable ) + { + os << indent << "Lookup Table:\n"; + this->LookupTable->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "LookupTable: (none)\n"; + } +} diff --git a/Common/vtkDataArray.h b/Common/vtkDataArray.h new file mode 100644 index 0000000..45f4b81 --- /dev/null +++ b/Common/vtkDataArray.h @@ -0,0 +1,402 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataArray - abstract superclass for arrays +// .SECTION Description +// vtkDataArray is an abstract superclass for data array objects. This class +// defines an API that all array objects must support. Note that the concrete +// subclasses of this class represent data in native form (char, int, etc.) and +// often have specialized more efficient methods for operating on this data +// (for example, getting pointers to data or getting/inserting data in native +// form). +// +// The logical structure of this class is an array of tuples, where each +// tuple is made up of n-components (also called a component group), and n is +// the number of component values in a tuple(n >= 1). Another view of this +// class is a mxn matrix, where m is the number of tuples, and n is the +// number of components in a tuple. Thus vtkDataArray can be used to +// represent scalars (1-4 components), 3D vectors (3 components), texture +// coordinates (1-3 components), tensors, (9 components) and so on. +// +// Each data array is required to have a character-string name. The +// naming of the array occurs automatically when it is instantiated, but +// you are free to name arrays using the SetName() method. +// (The array name is used for data manipulation.) +// +// .SECTION See Also +// vtkBitArray vtkCharArray vtkUnsignedCharArray vtkShortArray +// vtkUnsignedShortArray vtkIntArray vtkUnsignedIntArray vtkLongArray +// vtkUnsignedLongArray vtkDoubleArray vtkDoubleArray + +#ifndef __vtkDataArray_h +#define __vtkDataArray_h + +#include "vtkObject.h" + +class vtkDoubleArray; +class vtkLookupTable; +class vtkIdList; + +#define VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES 11 + +class VTK_COMMON_EXPORT vtkDataArray : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkDataArray,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate memory for this array. Delete old storage only if necessary. + // Note that ext is no longer used. + virtual int Allocate(vtkIdType sz, vtkIdType ext=1000) = 0; + + // Description: + // Release storage and reset array to initial state. + virtual void Initialize() = 0; + + // Description: + // Return the underlying data type. An integer indicating data type is + // returned as specified in vtkSetGet.h. + virtual int GetDataType() = 0; + + // Description: + // Return the size of the underlying data type. For a bit, 0 is returned. + virtual int GetDataTypeSize() = 0; + static unsigned long GetDataTypeSize(int type); + + // Description: + // Set/Get the dimension (n) of the components. Must be >= 1. Make sure that + // this is set before allocation. + vtkSetClampMacro(NumberOfComponents,int,1,VTK_LARGE_INTEGER); + int GetNumberOfComponents() {return this->NumberOfComponents;}; + + // Description: + // Set the number of tuples (a component group) in the array. Note that + // this may allocate space depending on the number of components. + virtual void SetNumberOfTuples(vtkIdType number) = 0; + + // Description: + // Get the number of tuples (a component group) in the array. + vtkIdType GetNumberOfTuples() + {return (this->MaxId + 1)/this->NumberOfComponents;} + + // Description: + // Get the data tuple at ith location. Return it as a pointer to an array. + // Note: this method is not thread-safe, and the pointer is only valid + // as long as another method invocation to a vtk object is not performed. + virtual double *GetTuple(vtkIdType i) = 0; + + // Description: + // Get the data tuple at ith location by filling in a user-provided array, + // Make sure that your array is large enough to hold the NumberOfComponents + // amount of data being returned. + virtual void GetTuple(vtkIdType i, double * tuple) = 0; + + // Description: + // These methods are included as convenience for the wrappers. + // GetTuple() and SetTuple() which return/take arrays can not be + // used from wrapped languages. These methods can be used instead. + double GetTuple1(vtkIdType i); + double* GetTuple2(vtkIdType i); + double* GetTuple3(vtkIdType i); + double* GetTuple4(vtkIdType i); + double* GetTuple9(vtkIdType i); + + // Description: + // Given a list of point ids, return an array of tuples. + // You must insure that the output array has been previously + // allocated with enough space to hold the data. + void GetTuples(vtkIdList *ptIds, vtkDataArray *output); + + // Description: + // Get the tuples for the range of points ids specified + // (i.e., p1->p2 inclusive). You must insure that the output array has + // been previously allocated with enough space to hold the data. + void GetTuples(vtkIdType p1, vtkIdType p2, vtkDataArray *output); + + // Description: + // Set the data tuple at ith location. Note that range checking or + // memory allocation is not performed; use this method in conjunction + // with SetNumberOfTuples() to allocate space. + virtual void SetTuple(vtkIdType i, const float * tuple) = 0; + virtual void SetTuple(vtkIdType i, const double * tuple) = 0; + + // Description: + // These methods are included as convenience for the wrappers. + // GetTuple() and SetTuple() which return/take arrays can not be + // used from wrapped languages. These methods can be used instead. + void SetTuple1(vtkIdType i, double value); + void SetTuple2(vtkIdType i, double val0, double val1); + void SetTuple3(vtkIdType i, double val0, double val1, double val2); + void SetTuple4(vtkIdType i, double val0, double val1, double val2, + double val3); + void SetTuple9(vtkIdType i, double val0, double val1, double val2, + double val3, double val4, double val5, double val6, + double val7, double val8); + + // Description: + // Insert the data tuple at ith location. Note that memory allocation + // is performed as necessary to hold the data. + virtual void InsertTuple(vtkIdType i, const float * tuple) = 0; + virtual void InsertTuple(vtkIdType i, const double * tuple) = 0; + + // Description: + // These methods are included as convenience for the wrappers. + // InsertTuple() which takes arrays can not be + // used from wrapped languages. These methods can be used instead. + void InsertTuple1(vtkIdType i, double value); + void InsertTuple2(vtkIdType i, double val0, double val1); + void InsertTuple3(vtkIdType i, double val0, double val1, double val2); + void InsertTuple4(vtkIdType i, double val0, double val1, double val2, + double val3); + void InsertTuple9(vtkIdType i, double val0, double val1, double val2, + double val3, double val4, double val5, double val6, + double val7, double val8); + + // Description: + // Insert the data tuple at the end of the array and return the location at + // which the data was inserted. Memory is allocated as necessary to hold + // the data. + virtual vtkIdType InsertNextTuple(const float * tuple) = 0; + virtual vtkIdType InsertNextTuple(const double * tuple) = 0; + + // Description: + // These methods are included as convenience for the wrappers. + // InsertTuple() which takes arrays can not be + // used from wrapped languages. These methods can be used instead. + void InsertNextTuple1(double value); + void InsertNextTuple2(double val0, double val1); + void InsertNextTuple3(double val0, double val1, double val2); + void InsertNextTuple4(double val0, double val1, double val2, + double val3); + void InsertNextTuple9(double val0, double val1, double val2, + double val3, double val4, double val5, double val6, + double val7, double val8); + + // Description: + // Return the data component at the ith tuple and jth component location. + // Note that i is less than NumberOfTuples and j is less than + // NumberOfComponents. + virtual double GetComponent(vtkIdType i, int j); + + // Description: + // Set the data component at the ith tuple and jth component location. + // Note that i is less than NumberOfTuples and j is less than + // NumberOfComponents. Make sure enough memory has been allocated + // (use SetNumberOfTuples() and SetNumberOfComponents()). + virtual void SetComponent(vtkIdType i, int j, double c); + + // Description: + // Insert the data component at ith tuple and jth component location. + // Note that memory allocation is performed as necessary to hold the data. + virtual void InsertComponent(vtkIdType i, int j, double c); + + // Description: + // Get the data as a double array in the range (tupleMin,tupleMax) and + // (compMin, compMax). The resulting double array consists of all data in + // the tuple range specified and only the component range specified. This + // process typically requires casting the data from native form into + // doubleing point values. This method is provided as a convenience for data + // exchange, and is not very fast. + virtual void GetData(vtkIdType tupleMin, vtkIdType tupleMax, int compMin, + int compMax, vtkDoubleArray* data); + + // Description: + // Deep copy of data. Copies data from different data arrays even if + // they are different types (using doubleing-point exchange). + virtual void DeepCopy(vtkDataArray *da); + + // Description: + // Fill a component of a data array with a specified value. This method + // sets the specified component to specified value for all tuples in the + // data array. This methods can be used to initialize or reinitialize a + // single component of a multi-component array. + virtual void FillComponent(int j, double c); + + // Description: + // Copy a component from one data array into a component on this data array. + // This method copies the specified component ("fromComponent") from the + // specified data array ("from") to the specified component ("j") over all + // the tuples in this data array. This method can be used to extract + // a component (column) from one data array and paste that data into + // a component on this data array. + virtual void CopyComponent(int j, vtkDataArray *from, + int fromComponent); + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + virtual void* WriteVoidPointer(vtkIdType id, vtkIdType number) = 0; + + // Description: + // Return a void pointer. For image pipeline interface and other + // special pointer manipulation. + virtual void *GetVoidPointer(vtkIdType id) = 0; + + // Description: + // Free any unnecessary memory. + virtual void Squeeze() = 0; + + // Description: + // Resize the array while conserving the data. Returns 1 if + // resizing succeeded and 0 otherwise. + virtual int Resize(vtkIdType numTuples) = 0; + + // Description: + // Reset to an empty state, without freeing any memory. + void Reset() + {this->MaxId = -1;} + + // Description: + // Return the size of the data. + vtkIdType GetSize() + {return this->Size;} + + // Description: + // What is the maximum id currently in the array. + vtkIdType GetMaxId() + {return this->MaxId;} + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the supplied array. + virtual void SetVoidArray(void *vtkNotUsed(array), + vtkIdType vtkNotUsed(size), + int vtkNotUsed(save)) {}; + + // Description: + // This method copies the array data to the void pointer specified + // by the user. It is up to the user to allocate enough memory for + // the void pointer. + virtual void ExportToVoidPointer(void *vtkNotUsed(out_ptr)) {} + + // Description: + // Return the memory in kilobytes consumed by this data array. Used to + // support streaming and reading/writing data. The value returned is + // guaranteed to be greater than or equal to the memory required to + // actually represent the data represented by this object. The + // information returned is valid only after the pipeline has + // been updated. + unsigned long GetActualMemorySize(); + + // Description: + // Create default lookup table. Generally used to create one when none + // is available. + void CreateDefaultLookupTable(); + + // Description: + // Set/get the lookup table associated with this scalar data, if any. + void SetLookupTable(vtkLookupTable *lut); + vtkGetObjectMacro(LookupTable,vtkLookupTable); + + // Description: + // Set/get array's name + vtkSetStringMacro(Name); + vtkGetStringMacro(Name); + + // Description: + // Return the range of the array values for the given component. + // Range is copied into the array provided. + // If comp is equal to -1, it returns the range of the magnitude + // (if the number of components is equal to 1 it still returns the range of + // component 0). + void GetRange(double range[2], int comp) + { + this->ComputeRange(comp); + memcpy(range, this->Range, 2*sizeof(double)); + } + double* GetRange(int comp) + { + this->ComputeRange(comp); + return this->Range; + } + + virtual void ComputeRange(int comp); + // Description: + // Return the range of the array values for the 0th component. + // Range is copied into the array provided. + double* GetRange() + { + this->ComputeRange(0); + return this->Range; + } + void GetRange(double range[2]) + { + this->GetRange(range,0); + } + + // Description: + // These methods return the Min and Max possible range of the native + // data type. For example if a vtkScalars consists of unsigned char + // data these will return (0,255). + void GetDataTypeRange(double range[2]); + double GetDataTypeMin(); + double GetDataTypeMax(); + static void GetDataTypeRange(int type, double range[2]); + static double GetDataTypeMin(int type); + static double GetDataTypeMax(int type); + + // Description: + // Return the maximum norm for the tuples. + // Note that the max. is computed everytime GetMaxNorm is called. + virtual double GetMaxNorm(); + + // Description: + // Creates an array for dataType where dataType is one of + // VTK_BIT, VTK_CHAR, VTK_SIGNED_CHAR, VTK_UNSIGNED_CHAR, VTK_SHORT, + // VTK_UNSIGNED_SHORT, VTK_INT, VTK_UNSIGNED_INT, VTK_LONG, + // VTK_UNSIGNED_LONG, VTK_DOUBLE, VTK_DOUBLE, VTK_ID_TYPE. + // Note that the data array returned has be deleted by the + // user. + static vtkDataArray* CreateDataArray(int dataType); + +protected: + // Construct object with default tuple dimension (number of components) of 1. + vtkDataArray(vtkIdType numComp=1); + ~vtkDataArray(); + + vtkLookupTable *LookupTable; + + vtkIdType Size; // allocated size of data + vtkIdType MaxId; // maximum index inserted thus far + int NumberOfComponents; // the number of components per tuple + + char* Name; + + double Range[2]; + + // We can have arbitrary number of components, but 11 should + // take care of 99.99% of the cases. Components greater + // than 11 do not get cached. The comment below assume max of 4 comps. + // 5 components since you can compute the range of components + // less than 0 to get a magnitude range. ComponentRange[4] is + // this magnitude range + vtkTimeStamp + ComponentRangeComputeTime[VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES]; + double ComponentRange[VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES][2]; + +private: + double* GetTupleN(vtkIdType i, int n); + +private: + vtkDataArray(const vtkDataArray&); // Not implemented. + void operator=(const vtkDataArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkDataArrayCollection.cxx b/Common/vtkDataArrayCollection.cxx new file mode 100644 index 0000000..05c7d82 --- /dev/null +++ b/Common/vtkDataArrayCollection.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArrayCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataArrayCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDataArrayCollection, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkDataArrayCollection); diff --git a/Common/vtkDataArrayCollection.h b/Common/vtkDataArrayCollection.h new file mode 100644 index 0000000..33b3da1 --- /dev/null +++ b/Common/vtkDataArrayCollection.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArrayCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataArrayCollection - maintain an unordered list of dataarray objects +// .SECTION Description +// vtkDataArrayCollection is an object that creates and manipulates lists of +// datasets. See also vtkCollection and subclasses. + +#ifndef __vtkDataArrayCollection_h +#define __vtkDataArrayCollection_h + +#include "vtkCollection.h" + +#include "vtkDataArray.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkDataArrayCollection : public vtkCollection +{ +public: + static vtkDataArrayCollection *New(); + vtkTypeRevisionMacro(vtkDataArrayCollection,vtkCollection); + + // Description: + // Add a dataarray to the list. + void AddItem(vtkDataArray *ds) { + this->vtkCollection::AddItem((vtkObject *)ds);}; + + // Description: + // Get the next dataarray in the list. + vtkDataArray *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + // Description: + // Get the ith dataarray in the list. + vtkDataArray *GetItem(int i) { + return static_cast(this->GetItemAsObject(i));}; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkDataArray *GetNextDataArray(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkDataArrayCollection() {}; + ~vtkDataArrayCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkDataArrayCollection(const vtkDataArrayCollection&); // Not implemented. + void operator=(const vtkDataArrayCollection&); // Not implemented. +}; + + +#endif diff --git a/Common/vtkDataArrayCollectionIterator.cxx b/Common/vtkDataArrayCollectionIterator.cxx new file mode 100644 index 0000000..9452ec3 --- /dev/null +++ b/Common/vtkDataArrayCollectionIterator.cxx @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArrayCollectionIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataArrayCollectionIterator.h" +#include "vtkObjectFactory.h" +#include "vtkDataArray.h" +#include "vtkDataArrayCollection.h" + +vtkCxxRevisionMacro(vtkDataArrayCollectionIterator, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkDataArrayCollectionIterator); + +//---------------------------------------------------------------------------- +vtkDataArrayCollectionIterator::vtkDataArrayCollectionIterator() +{ +} + +//---------------------------------------------------------------------------- +vtkDataArrayCollectionIterator::~vtkDataArrayCollectionIterator() +{ +} + +//---------------------------------------------------------------------------- +void vtkDataArrayCollectionIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +void vtkDataArrayCollectionIterator::SetCollection(vtkCollection* c) +{ + if(c) + { + this->Superclass::SetCollection(vtkDataArrayCollection::SafeDownCast(c)); + if(!this->Collection) + { + vtkErrorMacro("vtkDataArrayCollectionIterator cannot traverse a " + << c->GetClassName()); + } + } + else + { + this->Superclass::SetCollection(0); + } +} + +//---------------------------------------------------------------------------- +void vtkDataArrayCollectionIterator::SetCollection(vtkDataArrayCollection* c) +{ + this->Superclass::SetCollection(c); +} + +//---------------------------------------------------------------------------- +vtkDataArray* vtkDataArrayCollectionIterator::GetDataArray() +{ + return static_cast(this->GetCurrentObject()); +} diff --git a/Common/vtkDataArrayCollectionIterator.h b/Common/vtkDataArrayCollectionIterator.h new file mode 100644 index 0000000..a520a91 --- /dev/null +++ b/Common/vtkDataArrayCollectionIterator.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArrayCollectionIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataArrayCollectionIterator - iterator through a vtkDataArrayCollection. +// .SECTION Description +// vtkDataArrayCollectionIterator provides an implementation of +// vtkCollectionIterator which allows the items to be retrieved with +// the proper subclass pointer type for vtkDataArrayCollection. + +#ifndef __vtkDataArrayCollectionIterator_h +#define __vtkDataArrayCollectionIterator_h + +#include "vtkCollectionIterator.h" + +class vtkDataArray; +class vtkDataArrayCollection; + +class VTK_COMMON_EXPORT vtkDataArrayCollectionIterator : public vtkCollectionIterator +{ +public: + vtkTypeRevisionMacro(vtkDataArrayCollectionIterator,vtkCollectionIterator); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkDataArrayCollectionIterator* New(); + + // Description: + // Set the collection over which to iterate. + virtual void SetCollection(vtkCollection*); + void SetCollection(vtkDataArrayCollection*); + + // Description: + // Get the item at the current iterator position. Valid only when + // IsDoneWithTraversal() returns 1. + vtkDataArray* GetDataArray(); + +protected: + vtkDataArrayCollectionIterator(); + ~vtkDataArrayCollectionIterator(); + +private: + vtkDataArrayCollectionIterator(const vtkDataArrayCollectionIterator&); // Not implemented + void operator=(const vtkDataArrayCollectionIterator&); // Not implemented +}; + +#endif diff --git a/Common/vtkDataArraySelection.cxx b/Common/vtkDataArraySelection.cxx new file mode 100644 index 0000000..2308cfe --- /dev/null +++ b/Common/vtkDataArraySelection.cxx @@ -0,0 +1,383 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArraySelection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataArraySelection.h" +#include "vtkObjectFactory.h" + +#include +#include + +vtkCxxRevisionMacro(vtkDataArraySelection, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkDataArraySelection); + +class vtkDataArraySelectionInternals +{ +public: + vtkstd::vector ArrayNames; + vtkstd::vector ArraySettings; +}; + +//---------------------------------------------------------------------------- +vtkDataArraySelection::vtkDataArraySelection() +{ + this->Internal = new vtkDataArraySelectionInternals; +} + +//---------------------------------------------------------------------------- +vtkDataArraySelection::~vtkDataArraySelection() +{ + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Number of Arrays: " << this->GetNumberOfArrays() << "\n"; + vtkIndent nindent = indent.GetNextIndent(); + int cc; + for ( cc = 0; cc < this->GetNumberOfArrays(); cc ++ ) + { + os << nindent << "Array: " << this->GetArrayName(cc) << " is: " + << (this->GetArraySetting(cc)?"enabled":"disabled") + << " (" << this->ArrayIsEnabled(this->GetArrayName(cc)) << ")" << endl; + } +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::EnableArray(const char* name) +{ + vtkDebugMacro("Enabling array \"" << name << "\"."); + int index = this->GetArrayIndex(name); + if(index >= 0) + { + if(!this->Internal->ArraySettings[index]) + { + this->Internal->ArraySettings[index] = 1; + this->Modified(); + } + } + else + { + this->Internal->ArrayNames.push_back(name); + this->Internal->ArraySettings.push_back(1); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::DisableArray(const char* name) +{ + vtkDebugMacro("Disabling array \"" << name << "\"."); + int index = this->GetArrayIndex(name); + if(index >= 0) + { + if(this->Internal->ArraySettings[index]) + { + this->Internal->ArraySettings[index] = 0; + this->Modified(); + } + } + else + { + this->Internal->ArrayNames.push_back(name); + this->Internal->ArraySettings.push_back(0); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::ArrayIsEnabled(const char* name) +{ + // Check if there is a specific entry for this array. + int index = this->GetArrayIndex(name); + if(index >= 0) + { + return this->Internal->ArraySettings[index]; + } + + // The array does not have an entry. Assume it is disabled. + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::ArrayExists(const char* name) +{ + // Check if there is a specific entry for this array. + return (this->GetArrayIndex(name) >= 0)? 1:0; +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::EnableAllArrays() +{ + vtkDebugMacro("Enabling all arrays."); + int modified = 0; + for(vtkstd::vector::iterator i = this->Internal->ArraySettings.begin(); + i != this->Internal->ArraySettings.end(); ++i) + { + if(!*i) + { + *i = 1; + modified = 1; + } + } + if(modified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::DisableAllArrays() +{ + vtkDebugMacro("Disabling all arrays."); + int modified = 0; + for(vtkstd::vector::iterator i = this->Internal->ArraySettings.begin(); + i != this->Internal->ArraySettings.end(); ++i) + { + if(*i) + { + *i = 0; + modified = 1; + } + } + if(modified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::GetNumberOfArrays() +{ + return static_cast(this->Internal->ArrayNames.size()); +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::GetNumberOfArraysEnabled() +{ + int numArrays = 0; + for(vtkstd::vector::iterator i = this->Internal->ArraySettings.begin(); + i != this->Internal->ArraySettings.end(); ++i) + { + if(*i) + { + numArrays++; + } + } + return numArrays; +} + +//---------------------------------------------------------------------------- +const char* vtkDataArraySelection::GetArrayName(int index) +{ + if(index >= 0 && index < this->GetNumberOfArrays()) + { + return this->Internal->ArrayNames[index].c_str(); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::GetArrayIndex(const char* name) +{ + for(unsigned int i=0; i < this->Internal->ArrayNames.size(); ++i) + { + if(this->Internal->ArrayNames[i] == name) + { + return i; + } + } + return -1; +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::GetEnabledArrayIndex(const char* name) +{ + int index = 0; + for(unsigned int i=0; i < this->Internal->ArrayNames.size(); ++i) + { + if(this->Internal->ArrayNames[i] == name) + { + return index; + } + else if(this->Internal->ArraySettings[i]) + { + ++index; + } + } + return -1; +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::GetArraySetting(int index) +{ + if(index >= 0 && index < this->GetNumberOfArrays()) + { + return this->Internal->ArraySettings[index]; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::RemoveAllArrays() +{ + vtkDebugMacro("Removing all arrays."); + if(this->GetNumberOfArrays() > 0) + { + this->Internal->ArrayNames.erase(this->Internal->ArrayNames.begin(), + this->Internal->ArrayNames.end()); + this->Internal->ArraySettings.erase(this->Internal->ArraySettings.begin(), + this->Internal->ArraySettings.end()); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkDataArraySelection::AddArray(const char* name) +{ + vtkDebugMacro("Adding array \"" << name << "\"."); + // This function is called only by the filter owning the selection. + // It should not call Modified() because array settings are not + // changed. + if(this->ArrayExists(name)) + { + return 0; + } + this->Internal->ArrayNames.push_back(name); + this->Internal->ArraySettings.push_back(1); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::RemoveArrayByIndex(int index) +{ + if(index >= 0 && index < this->GetNumberOfArrays()) + { + this->Internal->ArrayNames.erase( + this->Internal->ArrayNames.begin()+index + ); + this->Internal->ArraySettings.erase( + this->Internal->ArraySettings.begin()+index + ); + } +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::RemoveArrayByName(const char *name) +{ + this->RemoveArrayByIndex(this->GetArrayIndex(name)); +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::SetArrays(const char* const* names, int numArrays) +{ + this->SetArraysWithDefault(names, numArrays, 1); +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::SetArraysWithDefault(const char* const* names, + int numArrays, + int defaultStatus) +{ + // This function is called only by the filter owning the selection. + // It should not call Modified() because array settings are not + // changed. + + vtkDebugMacro("Settings arrays to given list of " << numArrays + << " arrays."); + + // Create a new map for this set of arrays. + vtkDataArraySelectionInternals* newInternal = + new vtkDataArraySelectionInternals; + + newInternal->ArrayNames.reserve(numArrays); + newInternal->ArraySettings.reserve(numArrays); + + // Fill with settings for all arrays. + int i; + for(i=0;i < numArrays; ++i) + { + // Add this array. + newInternal->ArrayNames.push_back(names[i]); + + // Fill in the setting. Use the old value if available. + // Otherwise, use the given default. + int setting = defaultStatus?1:0; + int index = this->GetArrayIndex(names[i]); + if(index >= 0) + { + setting = this->Internal->ArraySettings[index]; + } + newInternal->ArraySettings.push_back(setting); + } + + // Delete the old map and save the new one. + delete this->Internal; + this->Internal = newInternal; +} + +//---------------------------------------------------------------------------- +void vtkDataArraySelection::CopySelections(vtkDataArraySelection* selections) +{ + if(this == selections) + { + return; + } + + int needUpdate = 0; + int i; + const char* arrayName; + if (this->GetNumberOfArrays() != selections->GetNumberOfArrays()) + { + needUpdate = 1; + } + else + { + for (i = 0; i < this->GetNumberOfArrays(); i++) + { + arrayName = this->GetArrayName(i); + if (!selections->ArrayExists(arrayName)) + { + needUpdate = 1; + break; + } + if (selections->ArrayIsEnabled(arrayName) != + this->ArrayIsEnabled(arrayName)) + { + needUpdate = 1; + break; + } + } + } + + if (!needUpdate) + { + return; + } + + vtkDebugMacro("Copying arrays and settings from " << selections << "."); + + this->RemoveAllArrays(); + + this->Internal->ArrayNames.insert(this->Internal->ArrayNames.begin(), + selections->Internal->ArrayNames.begin(), + selections->Internal->ArrayNames.end()); + this->Internal->ArraySettings.insert( + this->Internal->ArraySettings.begin(), + selections->Internal->ArraySettings.begin(), + selections->Internal->ArraySettings.end() + ); + this->Modified(); +} diff --git a/Common/vtkDataArraySelection.h b/Common/vtkDataArraySelection.h new file mode 100644 index 0000000..f947ddd --- /dev/null +++ b/Common/vtkDataArraySelection.h @@ -0,0 +1,139 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArraySelection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataArraySelection - Store on/off settings for data arrays for a vtkSource. +// .SECTION Description +// vtkDataArraySelection can be used by vtkSource subclasses to store +// on/off settings for whether each vtkDataArray in its input should +// be passed in the source's output. This is primarily intended to +// allow file readers to configure what data arrays are read from the +// file. + +#ifndef __vtkDataArraySelection_h +#define __vtkDataArraySelection_h + +#include "vtkObject.h" + +class vtkDataArraySelectionInternals; + +class VTK_COMMON_EXPORT vtkDataArraySelection : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkDataArraySelection,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkDataArraySelection* New(); + + // Description: + // Enable the array with the given name. Creates a new entry if + // none exists. + void EnableArray(const char* name); + + // Description: + // Disable the array with the given name. Creates a new entry if + // none exists. + void DisableArray(const char* name); + + // Description: + // Return whether the array with the given name is enabled. If + // there is no entry, the array is assumed to be disabled. + int ArrayIsEnabled(const char* name); + + // Description: + // Return whether the array with the given name exists. + int ArrayExists(const char* name); + + // Description: + // Enable all arrays that currently have an entry. + void EnableAllArrays(); + + // Description: + // Disable all arrays that currently have an entry. + void DisableAllArrays(); + + // Description: + // Get the number of arrays that currently have an entry. + int GetNumberOfArrays(); + + // Description: + // Get the number of arrays that are enabled. + int GetNumberOfArraysEnabled(); + + // Description: + // Get the name of the array entry at the given index. + const char* GetArrayName(int index); + + // Description: + // Get an index of the array containing name within the enabled arrays + int GetArrayIndex(const char *name); + + // Description: + // Get the index of an array with the given name among those + // that are enabled. Returns -1 if the array is not enabled. + int GetEnabledArrayIndex(const char* name); + + // Description: + // Get whether the array at the given index is enabled. + int GetArraySetting(int index); + + // Description: + // Remove all array entries. + void RemoveAllArrays(); + + //BTX + // Description: + // Add to the list of arrays that have entries. For arrays that + // already have entries, the settings are untouched. For arrays + // that don't already have an entry, they are assumed to be enabled. + // This method should be called only by the filter owning this + // object. + int AddArray(const char* name); + + // Description: + // Remove an array setting given its index. + void RemoveArrayByIndex(int index); + + // Description: + // Remove an array setting given its name. + void RemoveArrayByName(const char* name); + + // Description: + // Set the list of arrays that have entries. For arrays that + // already have entries, the settings are copied. For arrays that + // don't already have an entry, they are assigned the given default + // status. If no default status is given, it is assumed to be on. + // There will be no more entries than the names given. This method + // should be called only by the filter owning this object. The + // signature with the default must have a different name due to a + // bug in the Borland C++ 5.5 compiler. + void SetArrays(const char* const* names, int numArrays); + void SetArraysWithDefault(const char* const* names, int numArrays, + int defaultStatus); + //ETX + + // Description: + // Copy the selections from the given vtkDataArraySelection instance. + void CopySelections(vtkDataArraySelection* selections); +protected: + vtkDataArraySelection(); + ~vtkDataArraySelection(); + + // Internal implementation details. + vtkDataArraySelectionInternals* Internal; + +private: + vtkDataArraySelection(const vtkDataArraySelection&); // Not implemented. + void operator=(const vtkDataArraySelection&); // Not implemented. +}; + +#endif diff --git a/Common/vtkDataArrayTemplate.h b/Common/vtkDataArrayTemplate.h new file mode 100644 index 0000000..fc16f15 --- /dev/null +++ b/Common/vtkDataArrayTemplate.h @@ -0,0 +1,211 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArrayTemplate.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataArrayTemplate - Implementation template for vtkDataArray. +// .SECTION Description +// There is a vtkDataArray subclass for each native type supported by +// VTK. This template is used to implement all the subclasses in the +// same way while avoiding code duplication. + +#ifndef __vtkDataArrayTemplate_h +#define __vtkDataArrayTemplate_h + +#include "vtkDataArray.h" + +template +class vtkDataArrayTemplate: public vtkDataArray +{ +public: + typedef vtkDataArray Superclass; + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate memory for this array. Delete old storage only if necessary. + // Note that ext is no longer used. + int Allocate(vtkIdType sz, vtkIdType ext=1000); + + // Description: + // Release storage and reset array to initial state. + void Initialize(); + + // Description: + // Return the size of the data type. + int GetDataTypeSize() { return static_cast(sizeof(T)); } + + // Description: + // Set the number of n-tuples in the array. + void SetNumberOfTuples(vtkIdType number); + + // Description: + // Get a pointer to a tuple at the ith location. This is a dangerous method + // (it is not thread safe since a pointer is returned). + double* GetTuple(vtkIdType i); + + // Description: + // Copy the tuple value into a user-provided array. + void GetTuple(vtkIdType i, double* tuple); + void GetTupleValue(vtkIdType i, T* tuple); + + // Description: + // Set the tuple value at the ith location in the array. + void SetTuple(vtkIdType i, const float* tuple); + void SetTuple(vtkIdType i, const double* tuple); + void SetTupleValue(vtkIdType i, const T* tuple); + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTuple(vtkIdType i, const float* tuple); + void InsertTuple(vtkIdType i, const double* tuple); + void InsertTupleValue(vtkIdType i, const T* tuple); + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTuple(const float* tuple); + vtkIdType InsertNextTuple(const double* tuple); + vtkIdType InsertNextTupleValue(const T* tuple); + + // Description: + // Resize object to just fit data requirement. Reclaims extra memory. + void Squeeze() { this->ResizeAndExtend (this->MaxId+1); } + + // Description: + // Resize the array while conserving the data. + virtual int Resize(vtkIdType numTuples); + + // Description: + // Get the data at a particular index. + T GetValue(vtkIdType id) { return this->Array[id]; } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, T value) + { this->Array[id] = value;}; + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number); + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, T f); + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(T f); + + // Description: + // Return the data component at the ith tuple and jth component location. + // Note that i is less then NumberOfTuples and j is less then + // NumberOfComponents. + double GetComponent(vtkIdType i, int j); + + // Description: + // Set the data component at the ith tuple and jth component location. + // Note that i is less then NumberOfTuples and j is less then + // NumberOfComponents. Make sure enough memory has been allocated + // (use SetNumberOfTuples() and SetNumberOfComponents()). + void SetComponent(vtkIdType i, int j, double c); + + // Description: + // Insert the data component at ith tuple and jth component location. + // Note that memory allocation is performed as necessary to hold the data. + virtual void InsertComponent(vtkIdType i, int j, double c); + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + T* WritePointer(vtkIdType id, vtkIdType number); + void* WriteVoidPointer(vtkIdType id, vtkIdType number) + { return this->WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + T* GetPointer(vtkIdType id) { return this->Array + id; } + void* GetVoidPointer(vtkIdType id) { return this->GetPointer(id); } + + // Description: + // Deep copy of another double array. + void DeepCopy(vtkDataArray* da); + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(T* array, vtkIdType size, int save); + void SetVoidArray(void* array, vtkIdType size, int save) + { this->SetArray(static_cast(array), size, save); } + + // Description: + // This method copies the array data to the void pointer specified + // by the user. It is up to the user to allocate enough memory for + // the void pointer. + void ExportToVoidPointer(void *out_ptr); + + // Description: + // Do not call. Use GetRange. + virtual void ComputeRange(int comp); +protected: + vtkDataArrayTemplate(vtkIdType numComp); + ~vtkDataArrayTemplate(); + + T* Array; // pointer to data + T* ResizeAndExtend(vtkIdType sz); // function to resize data + + int TupleSize; //used for data conversion + double* Tuple; + + int SaveUserArray; + + void ComputeScalarRange(int comp); + void ComputeVectorRange(); +private: + vtkDataArrayTemplate(const vtkDataArrayTemplate&); // Not implemented. + void operator=(const vtkDataArrayTemplate&); // Not implemented. +}; + +#if !defined(VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION) +# define VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(T) \ + template class VTK_COMMON_EXPORT vtkDataArrayTemplate< T > +#else +# include "vtkDataArrayTemplateImplicit.txx" +# define VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(T) +#endif + +#endif // !defined(__vtkDataArrayTemplate_h) + +// This portion must be OUTSIDE the include blockers. Each +// vtkDataArray subclass uses this to give its instantiation of this +// template a DLL interface. +#if defined(VTK_DATA_ARRAY_TEMPLATE_TYPE) +# if defined(VTK_BUILD_SHARED_LIBS) && defined(_MSC_VER) +# pragma warning (push) +# pragma warning (disable: 4091) // warning C4091: 'extern ' : + // ignored on left of 'int' when no variable is declared +# pragma warning (disable: 4231) // Compiler-specific extension warning. + // Use an "extern explicit instantiation" to give the class a DLL + // interface. This is a compiler-specific extension. + extern VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(VTK_DATA_ARRAY_TEMPLATE_TYPE); +# pragma warning (pop) +# endif +# undef VTK_DATA_ARRAY_TEMPLATE_TYPE +#endif diff --git a/Common/vtkDataArrayTemplate.txx b/Common/vtkDataArrayTemplate.txx new file mode 100644 index 0000000..99521a4 --- /dev/null +++ b/Common/vtkDataArrayTemplate.txx @@ -0,0 +1,703 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArrayTemplate.txx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkDataArrayTemplate_txx +#define __vtkDataArrayTemplate_txx + +#include "vtkDataArrayTemplate.h" + +#include + +// We do not provide a definition for the copy constructor or +// operator=. Block the warning. +#ifdef _MSC_VER +# pragma warning (disable: 4661) +#endif + +//---------------------------------------------------------------------------- +template +vtkDataArrayTemplate::vtkDataArrayTemplate(vtkIdType numComp): + vtkDataArray(numComp) +{ + this->Array = 0; + this->Tuple = 0; + this->TupleSize = 0; + this->SaveUserArray = 0; +} + +//---------------------------------------------------------------------------- +template +vtkDataArrayTemplate::~vtkDataArrayTemplate() +{ + if ((this->Array) && (!this->SaveUserArray)) + { + free(this->Array); + } + if(this->Tuple) + { + free(this->Tuple); + } +} + +//---------------------------------------------------------------------------- +// This method lets the user specify data to be held by the array. The +// array argument is a pointer to the data. size is the size of +// the array supplied by the user. Set save to 1 to keep the class +// from deleting the array when it cleans up or reallocates memory. +// The class uses the actual array provided; it does not copy the data +// from the suppled array. +template +void vtkDataArrayTemplate::SetArray(T* array, vtkIdType size, int save) +{ + if ((this->Array) && (!this->SaveUserArray)) + { + vtkDebugMacro (<< "Deleting the array..."); + free(this->Array); + } + else + { + vtkDebugMacro (<<"Warning, array not deleted, but will point to new array."); + } + + vtkDebugMacro(<<"Setting array to: " << static_cast(array)); + + this->Array = array; + this->Size = size; + this->MaxId = size-1; + this->SaveUserArray = save; +} + +//---------------------------------------------------------------------------- +// Allocate memory for this array. Delete old storage only if necessary. +template +int vtkDataArrayTemplate::Allocate(vtkIdType sz, vtkIdType) +{ + this->MaxId = -1; + + if(sz > this->Size) + { + if(this->Array && !this->SaveUserArray) + { + free(this->Array); + } + + this->Array = 0; + this->Size = 0; + this->SaveUserArray = 0; + + int newSize = (sz > 0 ? sz : 1); + this->Array = (T*)malloc(newSize * sizeof(T)); + if(!this->Array) + { + vtkErrorMacro("Unable to allocate " << newSize + << " elements of size " << sizeof(T) + << " bytes. "); + return 0; + } + this->Size = newSize; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Release storage and reset array to initial state. +template +void vtkDataArrayTemplate::Initialize() +{ + if(this->Array && !this->SaveUserArray) + { + free(this->Array); + } + this->Array = 0; + this->Size = 0; + this->MaxId = -1; + this->SaveUserArray = 0; +} + +//---------------------------------------------------------------------------- +// Deep copy of another double array. +template +void vtkDataArrayTemplate::DeepCopy(vtkDataArray* fa) +{ + // Do nothing on a NULL input. + if(!fa) + { + return; + } + + // Avoid self-copy. + if(this == fa) + { + return; + } + + // If data type does not match, do copy with conversion. + if(fa->GetDataType() != this->GetDataType()) + { + this->Superclass::DeepCopy(fa); + return; + } + + // Free our previous memory. + if(this->Array && !this->SaveUserArray) + { + free(this->Array); + } + + // Copy the given array into new memory. + this->NumberOfComponents = fa->GetNumberOfComponents(); + this->MaxId = fa->GetMaxId(); + this->Size = fa->GetSize(); + this->SaveUserArray = 0; + this->Array = (T*)malloc(this->Size * sizeof(T)); + if(!this->Array) + { + vtkErrorMacro("Unable to allocate " << this->Size + << " elements of size " << sizeof(T) + << " bytes. "); + this->Size = 0; + this->NumberOfComponents = 0; + this->MaxId = -1; + return; + } + memcpy(this->Array, fa->GetVoidPointer(0), this->Size*sizeof(T)); +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + vtkOStreamWrapper osw(os); + if(this->Array) + { + osw << indent << "Array: " << static_cast(this->Array) << "\n"; + } + else + { + osw << indent << "Array: (null)\n"; + } +} + +//---------------------------------------------------------------------------- +// Protected function does "reallocate" +template +T* vtkDataArrayTemplate::ResizeAndExtend(vtkIdType sz) +{ + T* newArray; + vtkIdType newSize; + + if(sz > this->Size) + { + // Requested size is bigger than current size. Allocate enough + // memory to fit the requested size and be more than double the + // currently allocated memory. + newSize = this->Size + sz; + } + else if (sz == this->Size) + { + // Requested size is equal to current size. Do nothing. + return this->Array; + } + else + { + // Requested size is smaller than current size. Squeeze the + // memory. + newSize = sz; + } + + // Wipe out the array completely if new size is zero. + if(newSize <= 0) + { + this->Initialize(); + return 0; + } + + // Allocate the new array or reallocate the old. + if(this->Array && this->SaveUserArray) + { + // The old array is owned by the user so we cannot try to + // reallocate it. Just allocate new memory that we will own. + newArray = (T*)malloc(newSize*sizeof(T)); + if(!newArray) + { + vtkErrorMacro("Unable to allocate " << newSize + << " elements of size " << sizeof(T) + << " bytes. "); + return 0; + } + + // Copy the data from the old array. + memcpy(newArray, this->Array, + (newSize < this->Size ? newSize : this->Size) * sizeof(T)); + } + else + { + // Try to reallocate with minimal memory usage and possibly avoid + // copying. + newArray = (T*)realloc(this->Array, newSize*sizeof(T)); + if(!newArray) + { + vtkErrorMacro("Unable to allocate " << newSize + << " elements of size " << sizeof(T) + << " bytes. "); + return 0; + } + } + + // Allocation was successful. Save it. + if((newSize-1) < this->MaxId) + { + this->MaxId = newSize-1; + } + this->Size = newSize; + this->Array = newArray; + + // This object has now allocated its memory and owns it. + this->SaveUserArray = 0; + + return this->Array; +} + +//---------------------------------------------------------------------------- +template +int vtkDataArrayTemplate::Resize(vtkIdType sz) +{ + if(this->ResizeAndExtend(sz*this->NumberOfComponents) || sz <= 0) + { + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +// Set the number of n-tuples in the array. +template +void vtkDataArrayTemplate::SetNumberOfTuples(vtkIdType number) +{ + this->SetNumberOfValues(number*this->NumberOfComponents); +} + +//---------------------------------------------------------------------------- +// Get a pointer to a tuple at the ith location. This is a dangerous method +// (it is not thread safe since a pointer is returned). +template +double* vtkDataArrayTemplate::GetTuple(vtkIdType i) +{ + // If the small Tuple array fails to allocate we need something to + // return. This will avoid an immediate crash for arrays that do + // not have too many components. + static double sentryTuple[6] = {0,0,0,0,0,0}; +#if 1 + // Allocate a larger tuple buffer if needed. + if(this->TupleSize < this->NumberOfComponents) + { + this->TupleSize = this->NumberOfComponents; + free(this->Tuple); + this->Tuple = (double*)malloc(this->TupleSize * sizeof(double)); + } + + // Make sure tuple allocation succeeded. + if(!this->Tuple) + { + vtkErrorMacro("Unable to allocate " << this->TupleSize + << " elements of size " << sizeof(double) + << " bytes. "); + return sentryTuple; + } + + // Copy the data into the tuple. + T* t = this->Array + this->NumberOfComponents*i; + for(int j=0; j < this->NumberOfComponents; ++j) + { + this->Tuple[j] = static_cast(t[j]); + } + return this->Tuple; +#else + // Use this version along with purify or valgrind to detect code + // that saves the pointer returned by GetTuple. By always + // allocating a new tuple and freeing the old one code that keeps + // the pointer will do invalid reads or writes. + double* newTuple; + newTuple = (double*)malloc(this->NumberOfComponents * sizeof(double)); + if(!newTuple) + { + vtkErrorMacro("Unable to allocate " << this->NumberOfComponents + << " elements of size " << sizeof(double) + << " bytes. "); + return sentryTuple; + } + + // Copy the data into the new tuple. + T* t = this->Array + this->NumberOfComponents*i; + for(int j=0; j < this->NumberOfComponents; ++j) + { + newTuple[j] = static_cast(t[j]); + } + + // Replace the old tuple with the new one. + free(this->Tuple); + this->Tuple = newTuple; + return this->Tuple; +#endif +} + +//---------------------------------------------------------------------------- +// Copy the tuple value into a user-provided array. +template +void vtkDataArrayTemplate::GetTuple(vtkIdType i, double* tuple) +{ + T* t = this->Array + this->NumberOfComponents*i; + for(int j=0; j < this->NumberOfComponents; ++j) + { + tuple[j] = static_cast(t[j]); + } +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::GetTupleValue(vtkIdType i, T* tuple) +{ + T* t = this->Array + this->NumberOfComponents*i; + for(int j=0; j < this->NumberOfComponents; ++j) + { + tuple[j] = t[j]; + } +} + +//---------------------------------------------------------------------------- +// Set the tuple value at the ith location in the array. +template +void vtkDataArrayTemplate::SetTuple(vtkIdType i, const float* tuple) +{ + vtkIdType loc = i * this->NumberOfComponents; + for(int j=0; j < this->NumberOfComponents; ++j) + { + this->Array[loc+j] = static_cast(tuple[j]); + } +} + +template +void vtkDataArrayTemplate::SetTuple(vtkIdType i, const double* tuple) +{ + vtkIdType loc = i * this->NumberOfComponents; + for(int j=0; j < this->NumberOfComponents; ++j) + { + this->Array[loc+j] = static_cast(tuple[j]); + } +} + +template +void vtkDataArrayTemplate::SetTupleValue(vtkIdType i, const T* tuple) +{ + vtkIdType loc = i * this->NumberOfComponents; + for(int j=0; j < this->NumberOfComponents; ++j) + { + this->Array[loc+j] = tuple[j]; + } +} + +//---------------------------------------------------------------------------- +// Insert (memory allocation performed) the tuple into the ith location +// in the array. +template +void vtkDataArrayTemplate::InsertTuple(vtkIdType i, const float* tuple) +{ + T* t = this->WritePointer(i*this->NumberOfComponents, + this->NumberOfComponents); + + for(int j=0; j < this->NumberOfComponents; ++j) + { + *t++ = static_cast(*tuple++); + } +} + +template +void vtkDataArrayTemplate::InsertTuple(vtkIdType i, const double* tuple) +{ + T* t = this->WritePointer(i*this->NumberOfComponents, + this->NumberOfComponents); + + for(int j=0; j < this->NumberOfComponents; ++j) + { + *t++ = static_cast(*tuple++); + } +} + +template +void vtkDataArrayTemplate::InsertTupleValue(vtkIdType i, const T* tuple) +{ + T* t = this->WritePointer(i*this->NumberOfComponents, + this->NumberOfComponents); + + for(int j=0; j < this->NumberOfComponents; ++j) + { + *t++ = *tuple++; + } +} + +//---------------------------------------------------------------------------- +// Insert (memory allocation performed) the tuple onto the end of the array. +template +vtkIdType vtkDataArrayTemplate::InsertNextTuple(const float* tuple) +{ + T* t = this->WritePointer(this->MaxId + 1, this->NumberOfComponents); + + for(int j=0; j < this->NumberOfComponents; ++j) + { + *t++ = static_cast(*tuple++); + } + + return this->MaxId / this->NumberOfComponents; +} + +template +vtkIdType vtkDataArrayTemplate::InsertNextTuple(const double* tuple) +{ + T* t = this->WritePointer(this->MaxId + 1,this->NumberOfComponents); + + for(int j=0; j < this->NumberOfComponents; ++j) + { + *t++ = static_cast(*tuple++); + } + + return this->MaxId / this->NumberOfComponents; +} + +template +vtkIdType vtkDataArrayTemplate::InsertNextTupleValue(const T* tuple) +{ + T* t = this->WritePointer(this->MaxId + 1,this->NumberOfComponents); + + for(int j=0; j < this->NumberOfComponents; ++j) + { + *t++ = *tuple++; + } + + return this->MaxId / this->NumberOfComponents; +} + +//---------------------------------------------------------------------------- +// Return the data component at the ith tuple and jth component location. +// Note that i +double vtkDataArrayTemplate::GetComponent(vtkIdType i, int j) +{ + return static_cast(this->GetValue(i*this->NumberOfComponents + j)); +} + +//---------------------------------------------------------------------------- +// Set the data component at the ith tuple and jth component location. +// Note that i +void vtkDataArrayTemplate::SetComponent(vtkIdType i, int j, + double c) +{ + this->SetValue(i*this->NumberOfComponents + j, static_cast(c)); +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::InsertComponent(vtkIdType i, int j, + double c) +{ + this->InsertValue(i*this->NumberOfComponents + j, static_cast(c)); +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::SetNumberOfValues(vtkIdType number) +{ + if(this->Allocate(number)) + { + this->MaxId = number - 1; + } +} + +//---------------------------------------------------------------------------- +template +T* vtkDataArrayTemplate::WritePointer(vtkIdType id, + vtkIdType number) +{ + vtkIdType newSize=id+number; + if ( newSize > this->Size ) + { + this->ResizeAndExtend(newSize); + } + if ( (--newSize) > this->MaxId ) + { + this->MaxId = newSize; + } + return this->Array + id; +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::InsertValue(vtkIdType id, T f) +{ + if ( id >= this->Size ) + { + this->ResizeAndExtend(id+1); + } + this->Array[id] = f; + if ( id > this->MaxId ) + { + this->MaxId = id; + } +} + +//---------------------------------------------------------------------------- +template +vtkIdType vtkDataArrayTemplate::InsertNextValue(T f) +{ + this->InsertValue (++this->MaxId,f); + return this->MaxId; +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::ComputeRange(int comp) +{ + // If we got component -1 on a vector array, compute vector magnitude. + if(comp < 0 && this->NumberOfComponents == 1) + { + comp = 0; + } + + // Choose index into component range cache. + int index = (comp<0)? this->NumberOfComponents : comp; + + if(index >= VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES || + (this->GetMTime() > this->ComponentRangeComputeTime[index])) + { + // We need to compute the range. + this->Range[0] = VTK_DOUBLE_MAX; + this->Range[1] = VTK_DOUBLE_MIN; + + if(comp >= 0) + { + this->ComputeScalarRange(comp); + } + else + { + this->ComputeVectorRange(); + } + + // Store the result in the range cache if there is room. + if(index < VTK_MAXIMUM_NUMBER_OF_CACHED_COMPONENT_RANGES) + { + this->ComponentRangeComputeTime[index].Modified(); + this->ComponentRange[index][0] = this->Range[0]; + this->ComponentRange[index][1] = this->Range[1]; + } + } + else + { + // Copy value from range cache entry for this component. + this->Range[0] = this->ComponentRange[index][0]; + this->Range[1] = this->ComponentRange[index][1]; + } +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::ComputeScalarRange(int comp) +{ + // Compute range only if there are data. + T* begin = this->Array+comp; + T* end = this->Array+comp+this->MaxId+1; + if(begin == end) + { + return; + } + + // Compute the range of scalar values. + int numComp = this->NumberOfComponents; + T range[2] = {*begin, *begin}; + for(T* i = begin+numComp; i != end; i += numComp) + { + T s = *i; + if(s < range[0]) + { + range[0] = s; + } + else if(s > range[1]) + { + range[1] = s; + } + } + + // Store the range. + this->Range[0] = range[0]; + this->Range[1] = range[1]; +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::ComputeVectorRange() +{ + // Compute range only if there are data. + T* begin = this->Array; + T* end = this->Array+this->MaxId+1; + if(begin == end) + { + return; + } + + // Compute the range of vector magnitude squared. + int numComp = this->NumberOfComponents; + double range[2] = {VTK_DOUBLE_MAX, VTK_DOUBLE_MIN}; + for(T* i = begin; i != end; i += numComp) + { + double s = 0.0; + for(int j=0; j < numComp; ++j) + { + double t = i[j]; + s += t*t; + } + if(s < range[0]) + { + range[0] = s; + } + // this cannot be an elseif because there may be only one vector in which + // case the range[1] would be left at a bad value + if(s > range[1]) + { + range[1] = s; + } + } + + // Store the range of vector magnitude. + this->Range[0] = sqrt(range[0]); + this->Range[1] = sqrt(range[1]); +} + +//---------------------------------------------------------------------------- +template +void vtkDataArrayTemplate::ExportToVoidPointer(void *out_ptr) +{ + if(out_ptr && this->Array) + { + memcpy(static_cast(out_ptr), this->Array, + (this->MaxId + 1)*sizeof(T)); + } +} + +#endif diff --git a/Common/vtkDataArrayTemplateImplicit.txx b/Common/vtkDataArrayTemplateImplicit.txx new file mode 100644 index 0000000..cfd83a7 --- /dev/null +++ b/Common/vtkDataArrayTemplateImplicit.txx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataArrayTemplateImplicit.txx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This file is used to stop dependency tracking from including a +// dependence on the .txx file from the .h file when implicit +// instantiation is not needed. It just includes the corresponding +// .txx file, so only the name is important. + +#ifndef __vtkDataArrayTemplateImplicit_txx +#define __vtkDataArrayTemplateImplicit_txx + +#include "vtkDataArrayTemplate.txx" + +#endif diff --git a/Common/vtkDebugLeaks.cxx b/Common/vtkDebugLeaks.cxx new file mode 100644 index 0000000..55b63f5 --- /dev/null +++ b/Common/vtkDebugLeaks.cxx @@ -0,0 +1,463 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDebugLeaks.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDebugLeaks.h" + +#include "vtkCriticalSection.h" +#include "vtkObjectFactory.h" +#include "vtkWindows.h" + +#include + +static const char *vtkDebugLeaksIgnoreClasses[] = { + 0 +}; + +//---------------------------------------------------------------------------- +// return 1 if the class should be ignored +int vtkDebugLeaksIgnoreClassesCheck(const char* s) +{ + int i =0; + while(vtkDebugLeaksIgnoreClasses[i]) + { + if(strcmp(s, vtkDebugLeaksIgnoreClasses[i]) == 0) + { + return 1; + } + i++; + } + return 0; +} + +vtkCxxRevisionMacro(vtkDebugLeaks, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkDebugLeaks); + +//---------------------------------------------------------------------------- +// A hash function for converting a string to a long +inline size_t vtkHashString(const char* s) +{ + unsigned long h = 0; + for ( ; *s; ++s) + { + h = 5*h + *s; + } + return size_t(h); +} + +//---------------------------------------------------------------------------- +class vtkDebugLeaksHashNode +{ +public: + vtkDebugLeaksHashNode() + { + this->Count =1; // if it goes in, then there is one of them + this->Key = 0; + this->Next =0; + } + void Print(vtkstd::string& os) + { + if(this->Count) + { + char tmp[256]; + sprintf(tmp,"\" has %i %s still around.\n",this->Count, + (this->Count == 1) ? "instance" : "instances"); + os += "Class \""; + os += this->Key; + os += tmp; + } + } + ~vtkDebugLeaksHashNode() + { + delete [] this->Key; + if(this->Next) + { + delete this->Next; + } + } +public: + vtkDebugLeaksHashNode *Next; + char *Key; + int Count; +}; + +//---------------------------------------------------------------------------- +class vtkDebugLeaksHashTable +{ +public: + vtkDebugLeaksHashTable(); + vtkDebugLeaksHashNode* GetNode(const char* name); + void IncrementCount(const char *name); + unsigned int GetCount(const char *name); + int DecrementCount(const char* name); + void PrintTable(vtkstd::string &os); + int IsEmpty(); + ~vtkDebugLeaksHashTable() + { + for (int i = 0; i < 64; i++) + { + vtkDebugLeaksHashNode *pos = this->Nodes[i]; + if(pos) + { + delete pos; + } + } + } + +private: + vtkDebugLeaksHashNode* Nodes[64]; +}; + +//---------------------------------------------------------------------------- +vtkDebugLeaksHashTable::vtkDebugLeaksHashTable() +{ + int i; + for (i = 0; i < 64; i++) + { + this->Nodes[i] = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkDebugLeaksHashTable::IncrementCount(const char * name) +{ + vtkDebugLeaksHashNode *pos; + vtkDebugLeaksHashNode *newpos; + int loc; + + pos = this->GetNode(name); + if(pos) + { + pos->Count++; + return; + } + + newpos = new vtkDebugLeaksHashNode; + newpos->Key = strcpy(new char[strlen(name)+1], name); + + loc = (((unsigned long)vtkHashString(name)) & 0x03f0) / 16; + + pos = this->Nodes[loc]; + if (!pos) + { + this->Nodes[loc] = newpos; + return; + } + while (pos->Next) + { + pos = pos->Next; + } + pos->Next = newpos; +} + +//---------------------------------------------------------------------------- +vtkDebugLeaksHashNode* vtkDebugLeaksHashTable::GetNode(const char* key) +{ + vtkDebugLeaksHashNode *pos; + int loc = (((unsigned long)vtkHashString(key)) & 0x03f0) / 16; + + pos = this->Nodes[loc]; + + if (!pos) + { + return NULL; + } + while ((pos) && (strcmp(pos->Key, key) != 0) ) + { + pos = pos->Next; + } + return pos; +} + +//---------------------------------------------------------------------------- +unsigned int vtkDebugLeaksHashTable::GetCount(const char* key) +{ + vtkDebugLeaksHashNode *pos; + int loc = (((unsigned long)vtkHashString(key)) & 0x03f0) / 16; + + pos = this->Nodes[loc]; + + if (!pos) + { + return 0; + } + while ((pos)&&(pos->Key != key)) + { + pos = pos->Next; + } + if (pos) + { + return pos->Count; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDebugLeaksHashTable::IsEmpty() +{ + int count = 0; + for(int i =0; i < 64; i++) + { + vtkDebugLeaksHashNode *pos = this->Nodes[i]; + if(pos) + { + if(!vtkDebugLeaksIgnoreClassesCheck(pos->Key)) + { + count += pos->Count; + } + while(pos->Next) + { + pos = pos->Next; + if(!vtkDebugLeaksIgnoreClassesCheck(pos->Key)) + { + count += pos->Count; + } + } + } + } + return !count; +} + +//---------------------------------------------------------------------------- +int vtkDebugLeaksHashTable::DecrementCount(const char *key) +{ + + vtkDebugLeaksHashNode *pos = this->GetNode(key); + if(pos) + { + pos->Count--; + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkDebugLeaksHashTable::PrintTable(vtkstd::string &os) +{ + for(int i =0; i < 64; i++) + { + vtkDebugLeaksHashNode *pos = this->Nodes[i]; + if(pos) + { + if(!vtkDebugLeaksIgnoreClassesCheck(pos->Key)) + { + pos->Print(os); + } + while(pos->Next) + { + pos = pos->Next; + if(!vtkDebugLeaksIgnoreClassesCheck(pos->Key)) + { + pos->Print(os); + } + } + } + } +} + +//---------------------------------------------------------------------------- +#ifdef VTK_DEBUG_LEAKS +void vtkDebugLeaks::ConstructClass(const char* name) +{ + vtkDebugLeaks::CriticalSection->Lock(); + vtkDebugLeaks::MemoryTable->IncrementCount(name); + vtkDebugLeaks::CriticalSection->Unlock(); +} +#else +void vtkDebugLeaks::ConstructClass(const char*) +{ +} +#endif + +//---------------------------------------------------------------------------- +#ifdef VTK_DEBUG_LEAKS +void vtkDebugLeaks::DestructClass(const char* p) +{ + vtkDebugLeaks::CriticalSection->Lock(); + // Due to globals being deleted, this table may already have + // been deleted. + if(vtkDebugLeaks::MemoryTable && + !vtkDebugLeaks::MemoryTable->DecrementCount(p)) + { + vtkDebugLeaks::CriticalSection->Unlock(); + vtkGenericWarningMacro("Deleting unknown object: " << p); + } + else + { + vtkDebugLeaks::CriticalSection->Unlock(); + } +} +#else +void vtkDebugLeaks::DestructClass(const char*) +{ +} +#endif + +//---------------------------------------------------------------------------- +int vtkDebugLeaks::PrintCurrentLeaks() +{ +#ifdef VTK_DEBUG_LEAKS + if(vtkDebugLeaks::MemoryTable->IsEmpty()) + { + return 0; + } + + // we must not use stringstream ior strstream due to problems with + // finalizers in MSVC + vtkstd::string leaks; + vtkDebugLeaks::MemoryTable->PrintTable(leaks); +#ifdef _WIN32 + fprintf(stderr,"%s",leaks.c_str()); + fflush(stderr); + int cancel=0; + if(getenv("DASHBOARD_TEST_FROM_CTEST") || + getenv("DART_TEST_FROM_DART")) + { + // Skip dialogs when running on dashboard. + return 1; + } + vtkstd::string::size_type myPos = 0; + int count = 0; + vtkstd::string msg; + msg = "vtkDebugLeaks has detected LEAKS!\n"; + while(!cancel && myPos != leaks.npos) + { + vtkstd::string::size_type newPos = leaks.find('\n',myPos); + if (newPos != leaks.npos) + { + msg += leaks.substr(myPos,newPos-myPos); + msg += "\n"; + myPos = newPos; + myPos++; + } + else + { + myPos = newPos; + } + count++; + if (count == 10) + { + count = 0; + cancel = vtkDebugLeaks::DisplayMessageBox(msg.c_str()); + msg = ""; + } + } + if (!cancel && count > 0) + { + vtkDebugLeaks::DisplayMessageBox(msg.c_str()); + } +#else + cout << "vtkDebugLeaks has detected LEAKS!\n"; + cout << leaks.c_str() << endl; +#endif +#endif + return 1; +} + +//---------------------------------------------------------------------------- +#ifdef _WIN32 +int vtkDebugLeaks::DisplayMessageBox(const char* msg) +{ +#ifdef UNICODE + wchar_t *wmsg = new wchar_t [mbstowcs(NULL, msg, 32000)+1]; + mbstowcs(wmsg, msg, 32000); + int result = (MessageBox(NULL, wmsg, L"Error", + MB_ICONERROR | MB_OKCANCEL) == IDCANCEL); + delete [] wmsg; +#else + int result = (MessageBox(NULL, msg, "Error", + MB_ICONERROR | MB_OKCANCEL) == IDCANCEL); +#endif + return result; +} +#else +int vtkDebugLeaks::DisplayMessageBox(const char*) +{ + return 0; +} +#endif + +//---------------------------------------------------------------------------- +int vtkDebugLeaks::GetExitError() +{ + return vtkDebugLeaks::ExitError; +} + +//---------------------------------------------------------------------------- +void vtkDebugLeaks::SetExitError(int flag) +{ + vtkDebugLeaks::ExitError = flag; +} + +//---------------------------------------------------------------------------- +void vtkDebugLeaks::ClassInitialize() +{ +#ifdef VTK_DEBUG_LEAKS + // Create the hash table. + vtkDebugLeaks::MemoryTable = new vtkDebugLeaksHashTable; + + // Create the lock for the critical sections. + vtkDebugLeaks::CriticalSection = new vtkSimpleCriticalSection; + + // Default to error when leaks occur while running tests. + vtkDebugLeaks::ExitError = + (getenv("DASHBOARD_TEST_FROM_CTEST") || + getenv("DART_TEST_FROM_DART"))? 1:0; +#else + vtkDebugLeaks::MemoryTable = 0; + vtkDebugLeaks::CriticalSection = 0; + vtkDebugLeaks::ExitError = 0; +#endif +} + +//---------------------------------------------------------------------------- +void vtkDebugLeaks::ClassFinalize() +{ +#ifdef VTK_DEBUG_LEAKS + // Report leaks. + int leaked = vtkDebugLeaks::PrintCurrentLeaks(); + + // Destroy the hash table. + delete vtkDebugLeaks::MemoryTable; + vtkDebugLeaks::MemoryTable = 0; + + // Destroy the lock for the critical sections. + delete vtkDebugLeaks::CriticalSection; + vtkDebugLeaks::CriticalSection = 0; + + // Exit with error if leaks occured and error mode is on. + if(leaked && vtkDebugLeaks::ExitError) + { + exit(1); + } +#endif +} + +#ifndef VTK_LEGACY_REMOVE +void vtkDebugLeaks::PromptUserOn() {} +void vtkDebugLeaks::PromptUserOff() {} +#endif + +//---------------------------------------------------------------------------- + +// Purposely not initialized. ClassInitialize will handle it. +vtkDebugLeaksHashTable* vtkDebugLeaks::MemoryTable; + +// Purposely not initialized. ClassInitialize will handle it. +vtkSimpleCriticalSection* vtkDebugLeaks::CriticalSection; + +// Purposely not initialized. ClassInitialize will handle it. +int vtkDebugLeaks::ExitError; diff --git a/Common/vtkDebugLeaks.h b/Common/vtkDebugLeaks.h new file mode 100644 index 0000000..2bbc8af --- /dev/null +++ b/Common/vtkDebugLeaks.h @@ -0,0 +1,90 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDebugLeaks.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDebugLeaks - identify memory leaks at program termination +// .SECTION Description +// vtkDebugLeaks is used to report memory leaks at the exit of the program. +// It uses the vtkObjectFactory to intercept the construction of all VTK +// objects. It uses the UnRegister method of vtkObject to intercept the +// destruction of all objects. A table of object name to number of instances +// is kept. At the exit of the program if there are still VTK objects around +// it will print them out. To enable this class add the flag +// -DVTK_DEBUG_LEAKS to the compile line, and rebuild vtkObject and +// vtkObjectFactory. + +#ifndef __vtkDebugLeaks_h +#define __vtkDebugLeaks_h + +#include "vtkObject.h" + +#include "vtkToolkits.h" // Needed for VTK_DEBUG_LEAKS macro setting. +#include "vtkDebugLeaksManager.h" // Needed for proper singleton initialization + +class vtkDebugLeaksHashTable; +class vtkSimpleCriticalSection; + +class VTK_COMMON_EXPORT vtkDebugLeaks : public vtkObject +{ +public: + static vtkDebugLeaks *New(); + vtkTypeRevisionMacro(vtkDebugLeaks,vtkObject); + + // Description: + // Call this when creating a class of a given name. + static void ConstructClass(const char* classname); + + // Description: + // Call this when deleting a class of a given name. + static void DestructClass(const char* classname); + + // Description: + // Print all the values in the table. Returns non-zero if there + // were leaks. + static int PrintCurrentLeaks(); + + // Description: + // @deprecated Turn prompt at exit on/off (this setting is deprecated + // and will be ignored). + VTK_LEGACY(static void PromptUserOn()); + VTK_LEGACY(static void PromptUserOff()); + + // Description: + // Get/Set flag for exiting with an error when leaks are present. + // Default is on when testing and off otherwise. + static int GetExitError(); + static void SetExitError(int); + +protected: + vtkDebugLeaks(){}; + virtual ~vtkDebugLeaks(){}; + + static int DisplayMessageBox(const char*); + + static void ClassInitialize(); + static void ClassFinalize(); + + //BTX + friend class vtkDebugLeaksManager; + //ETX + +private: + static vtkDebugLeaksHashTable* MemoryTable; + static vtkSimpleCriticalSection* CriticalSection; + static int ExitError; + + vtkDebugLeaks(const vtkDebugLeaks&); // Not implemented. + void operator=(const vtkDebugLeaks&); // Not implemented. +}; + +#endif // __vtkDebugLeaks_h diff --git a/Common/vtkDebugLeaksManager.cxx b/Common/vtkDebugLeaksManager.cxx new file mode 100644 index 0000000..652e36a --- /dev/null +++ b/Common/vtkDebugLeaksManager.cxx @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDebugLeaksManager.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDebugLeaksManager.h" +#include "vtkDebugLeaks.h" + +// Global optimization performed by MSVC breaks the initialization +// order across translation units enforced by this manager. Disable +// them for this object file. +#if defined(_MSC_VER) +# pragma optimize("g", off) +#endif + +// Must NOT be initialized. Default initialization to zero is +// necessary. +unsigned int vtkDebugLeaksManagerCount; + +vtkDebugLeaksManager::vtkDebugLeaksManager() +{ + if(++vtkDebugLeaksManagerCount == 1) + { + vtkDebugLeaks::ClassInitialize(); + } +} + +vtkDebugLeaksManager::~vtkDebugLeaksManager() +{ + if(--vtkDebugLeaksManagerCount == 0) + { + vtkDebugLeaks::ClassFinalize(); + } +} + +#if defined(_MSC_VER) +# pragma optimize("g", on) +#endif diff --git a/Common/vtkDebugLeaksManager.h b/Common/vtkDebugLeaksManager.h new file mode 100644 index 0000000..cf63bb2 --- /dev/null +++ b/Common/vtkDebugLeaksManager.h @@ -0,0 +1,40 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDebugLeaksManager.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDebugLeaksManager - Manages the vtkDebugLeaks singleton. +// .SECTION Description +// vtkDebugLeaksManager should be included in any translation unit +// that will use vtkDebugLeaks or that implements the singleton +// pattern. It makes sure that the vtkDebugLeaks singleton is created +// before and destroyed after all other singletons in VTK. + +#ifndef __vtkDebugLeaksManager_h +#define __vtkDebugLeaksManager_h + +#include "vtkSystemIncludes.h" + +class VTK_COMMON_EXPORT vtkDebugLeaksManager +{ +public: + vtkDebugLeaksManager(); + ~vtkDebugLeaksManager(); +}; + +// This instance will show up in any translation unit that uses +// vtkDebugLeaks or that has a singleton. It will make sure +// vtkDebugLeaks is initialized before it is used and is the last +// static object destroyed. +static vtkDebugLeaksManager vtkDebugLeaksManagerInstance; + +#endif diff --git a/Common/vtkDirectory.cxx b/Common/vtkDirectory.cxx new file mode 100644 index 0000000..46a28aa --- /dev/null +++ b/Common/vtkDirectory.cxx @@ -0,0 +1,262 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDirectory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDirectory.h" + +#include "vtkDebugLeaks.h" + +#include + +vtkCxxRevisionMacro(vtkDirectory, "$Revision: 1.25.12.1 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkDirectory); + +//---------------------------------------------------------------------------- +vtkDirectory* vtkDirectory::New() +{ +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkDirectory"); +#endif + return new vtkDirectory; +} + +vtkDirectory::vtkDirectory() + : Path(0), Files(0), NumberOfFiles(0) +{ +} + + +void vtkDirectory::CleanUpFilesAndPath() +{ + for(int i =0; i < this->NumberOfFiles; i++) + { + delete [] this->Files[i]; + } + delete [] this->Files; + delete [] this->Path; + this->Files = 0; + this->Path = 0; + this->NumberOfFiles = 0; +} + +vtkDirectory::~vtkDirectory() +{ + this->CleanUpFilesAndPath(); +} + + + +void vtkDirectory::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if(!this->Path) + { + os << indent << "Directory not open\n"; + return; + } + + os << indent << "Directory for: " << this->Path << "\n"; + os << indent << "Contains the following files:\n"; + indent = indent.GetNextIndent(); + for(int i =0; i < this->NumberOfFiles; i++) + { + os << indent << this->Files[i] << "\n"; + } +} + +// First microsoft and borland compilers + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) +#include "vtkWindows.h" +#include +#include +#include +#include +#include +#include +#include +#include + +int vtkDirectory::Open(const char* name) +{ + // clean up from any previous open + this->CleanUpFilesAndPath(); + char* buf=0; + int n = static_cast(strlen(name)); + if (name[n - 1] == '/') + { + buf = new char[n + 1 + 1]; + sprintf(buf, "%s*", name); + } + else + { + buf = new char[n + 2 + 1]; + sprintf(buf, "%s/*", name); + } + struct _finddata_t data; // data of current file + + // First count the number of files in the directory +#if _MSC_VER < 1300 + long srchHandle; +#else + intptr_t srchHandle; +#endif + srchHandle = _findfirst(buf, &data); + if (srchHandle == -1) + { + this->NumberOfFiles = 0; + _findclose(srchHandle); + delete[] buf; + return 0; + } + + this->NumberOfFiles = 1; + + while(_findnext(srchHandle, &data) != -1) + { + this->NumberOfFiles++; + } + this->Files = new char*[this->NumberOfFiles]; + // close the handle + _findclose(srchHandle); + // Now put them into the file array + srchHandle = _findfirst(buf, &data); + delete [] buf; + + if (srchHandle == -1) + { + this->NumberOfFiles = 0; + _findclose(srchHandle); + return 0; + } + + // Loop through names + int i = 0; + do + { + this->Files[i] = strcpy(new char[strlen(data.name)+1], data.name); + i++; + } + while (_findnext(srchHandle, &data) != -1); + this->Path = strcpy(new char[strlen(name)+1], name); + return _findclose(srchHandle) != -1; +} + +const char* vtkDirectory::GetCurrentWorkingDirectory(char* buf, + unsigned int len) +{ + return _getcwd(buf, len); +} + +#else + +// Now the POSIX style directory access + +#include +#include +#include + +int vtkDirectory::Open(const char* name) +{ + // clean up from any previous open + this->CleanUpFilesAndPath(); + + DIR* dir = opendir(name); + if (!dir) + { + return 0; + } + this->NumberOfFiles = 0; + dirent* d =0; + + for (d = readdir(dir); d; d = readdir(dir)) + { + this->NumberOfFiles++; + } + this->Files = new char*[this->NumberOfFiles]; + closedir(dir); + + dir = opendir(name); + if (!dir) + { + return 0; + } + int i = 0; + for (d = readdir(dir); d; d = readdir(dir)) + { + this->Files[i] = strcpy(new char[strlen(d->d_name)+1], d->d_name); + i++; + } + this->Path = strcpy(new char[strlen(name)+1], name); + closedir(dir); + return 1; +} + +const char* vtkDirectory::GetCurrentWorkingDirectory(char* buf, + unsigned int len) +{ + return getcwd(buf, len); +} + +#endif + +//---------------------------------------------------------------------------- +int vtkDirectory::MakeDirectory(const char* dir) +{ +#if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) \ + || defined(__MINGW32__)) + return _mkdir(dir) == 0; +#else + return mkdir(dir, 00777) == 0; +#endif +} + + +const char* vtkDirectory::GetFile(int index) +{ + if(index >= this->NumberOfFiles || index < 0) + { + vtkErrorMacro( << "Bad index for GetFile on vtkDirectory\n"); + return 0; + } + + return this->Files[index]; +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef CreateDirectory +int vtkDirectory::CreateDirectoryA(const char* dir) +{ + VTK_LEGACY_REPLACED_BODY(vtkDirectory::CreateDirectory, "VTK 5.0", + vtkDirectory::MakeDirectory); + return vtkDirectory::MakeDirectory(dir); +} +int vtkDirectory::CreateDirectoryW(const char* dir) +{ + VTK_LEGACY_REPLACED_BODY(vtkDirectory::CreateDirectory, "VTK 5.0", + vtkDirectory::MakeDirectory); + return vtkDirectory::MakeDirectory(dir); +} +# endif +int vtkDirectory::CreateDirectory(const char* dir) +{ + VTK_LEGACY_REPLACED_BODY(vtkDirectory::CreateDirectory, "VTK 5.0", + vtkDirectory::MakeDirectory); + return vtkDirectory::MakeDirectory(dir); +} +#endif diff --git a/Common/vtkDirectory.h b/Common/vtkDirectory.h new file mode 100644 index 0000000..96daa0a --- /dev/null +++ b/Common/vtkDirectory.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDirectory.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDirectory - OS independent class for access to system directories +// .SECTION Description +// vtkDirectory provides a portable way of finding the names of the files +// in a system directory. + +// .SECTION Caveats +// vtkDirectory works with windows and unix only. + + + +#ifndef __vtkDirectory_h +#define __vtkDirectory_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkDirectory : public vtkObject +{ +public: + // Description: + // Return the class name as a string. + vtkTypeRevisionMacro(vtkDirectory,vtkObject); + + // Description: + // Create a new vtkDirectory object. + static vtkDirectory *New(); + + // Description: + // Print directory to stream. + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Open the specified directory and load the names of the files + // in that directory. 0 is returned if the directory can not be + // opened, 1 if it is opened. + int Open(const char* dir); + + // Description: + // Return the number of files in the current directory. + int GetNumberOfFiles() { return this->NumberOfFiles; } + + // Description: + // Return the file at the given index, the indexing is 0 based + const char* GetFile(int index); + + // Description: + // Get the current working directory. + static const char* GetCurrentWorkingDirectory(char* buf, unsigned int len); + + // Description: + // Create directory. Needs rework to do all the testing and to work + // on all platforms. + static int MakeDirectory(const char* dir); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define CreateDirectoryA CreateDirectory +# define CreateDirectoryW CreateDirectory +#endif + + // Description: + // @deprecated Replaced by vtkDirectory::MakeDirectory() as of VTK 5.0. + VTK_LEGACY(static int CreateDirectory(const char* dir)); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef CreateDirectoryW +# undef CreateDirectoryA + //BTX + VTK_LEGACY(static int CreateDirectoryA(const char* dir)); + VTK_LEGACY(static int CreateDirectoryW(const char* dir)); + //ETX +#endif + +protected: + // delete the Files and Path ivars and set + // NumberOfFiles to 0 + void CleanUpFilesAndPath(); + vtkDirectory(); + ~vtkDirectory() ; +private: + char* Path; // Path to Open'ed directory + char** Files; // Array of Files + int NumberOfFiles; // Number if files in open directory + + static int CreateDirectoryInternal(const char* dir); +private: + vtkDirectory(const vtkDirectory&); // Not implemented. + void operator=(const vtkDirectory&); // Not implemented. +}; + +#endif diff --git a/Common/vtkDoubleArray.cxx b/Common/vtkDoubleArray.cxx new file mode 100644 index 0000000..99c6691 --- /dev/null +++ b/Common/vtkDoubleArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDoubleArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(double); + +#define __vtkDoubleArray_cxx +#include "vtkDoubleArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkDoubleArray, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkDoubleArray); + +//---------------------------------------------------------------------------- +vtkDoubleArray::vtkDoubleArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkDoubleArray::~vtkDoubleArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkDoubleArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkDoubleArray.h b/Common/vtkDoubleArray.h new file mode 100644 index 0000000..bc9d06e --- /dev/null +++ b/Common/vtkDoubleArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDoubleArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDoubleArray - dynamic, self-adjusting array of double +// .SECTION Description +// vtkDoubleArray is an array of values of type double. It provides +// methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkDoubleArray_h +#define __vtkDoubleArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkDoubleArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE double +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkDoubleArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkDoubleArray* New(); + vtkTypeRevisionMacro(vtkDoubleArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_DOUBLE; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, double* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const double* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const double* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const double* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + double GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, double value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, double f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(double f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + double* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + double* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(double* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkDoubleArray(vtkIdType numComp=1); + ~vtkDoubleArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkDoubleArray(const vtkDoubleArray&); // Not implemented. + void operator=(const vtkDoubleArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkDynamicLoader.cxx b/Common/vtkDynamicLoader.cxx new file mode 100644 index 0000000..f60327f --- /dev/null +++ b/Common/vtkDynamicLoader.cxx @@ -0,0 +1,273 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDynamicLoader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDynamicLoader.h" + +#include "vtkDebugLeaks.h" + +// This file is actually 3 different implementations. +// 1. HP machines which uses shl_load +// 2. Apple OSX which uses NSLinkModule +// 3. Windows which uses LoadLibrary +// 4. Most unix systems which use dlopen (default ) +// Each part of the ifdef contains a complete implementation for +// the static methods of vtkDynamicLoader. + +vtkCxxRevisionMacro(vtkDynamicLoader, "$Revision: 1.21 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkDynamicLoader); + +//---------------------------------------------------------------------------- +vtkDynamicLoader* vtkDynamicLoader::New() +{ +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkDynamicLoader"); +#endif + return new vtkDynamicLoader; +} + + +// --------------------------------------------------------------- +// 1. Implementation for HPUX machines +#ifdef __hpux +#define VTKDYNAMICLOADER_DEFINED 1 +#include + +vtkLibHandle vtkDynamicLoader::OpenLibrary(const char* libname ) +{ + return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L); +} + +int vtkDynamicLoader::CloseLibrary(vtkLibHandle lib) +{ + return 0; +} + +void* vtkDynamicLoader::GetSymbolAddress(vtkLibHandle lib, const char* sym) +{ + void* addr; + int status; + + status = shl_findsym (&lib, sym, TYPE_PROCEDURE, &addr); + return (status < 0) ? (void*)0 : addr; +} + +const char* vtkDynamicLoader::LibPrefix() +{ + return "lib"; +} + +const char* vtkDynamicLoader::LibExtension() +{ + return ".sl"; +} + +const char* vtkDynamicLoader::LastError() +{ + return 0; +} +#endif + + + +// --------------------------------------------------------------- +// 2. Implementation for Darwin (including OSX) Machines + +#ifdef __APPLE__ +#define VTKDYNAMICLOADER_DEFINED + +// Visual Age Compiler for Mac OSX does not understand this extension. +#if defined(__IBMCPP__) && !defined(__private_extern__) +# define __private_extern__ +#endif + +#include + +vtkLibHandle vtkDynamicLoader::OpenLibrary(const char* libname ) +{ + NSObjectFileImageReturnCode rc; + NSObjectFileImage image; + + rc = NSCreateObjectFileImageFromFile(libname, &image); + return NSLinkModule(image, libname, TRUE); +} + +int vtkDynamicLoader::CloseLibrary(vtkLibHandle) +{ + return 0; +} + +void* vtkDynamicLoader::GetSymbolAddress(vtkLibHandle, const char* sym) +{ + void *result = 0; + // global 'C' symbols names are preceded with an underscore '_' + char *_sym = new char[ strlen(sym) + 2 ]; + strcpy( _sym + 1, sym ); + _sym[0] = '_'; + if( NSIsSymbolNameDefined(_sym) ) + { + cout << _sym << " is defined!" << endl; + NSSymbol symbol = NSLookupAndBindSymbol(_sym); + if(symbol) + { + result = NSAddressOfSymbol(symbol); + } + } + else + { + cout << _sym << " is not defined!" << endl; + } + + delete[] _sym; + return result; +} + +const char* vtkDynamicLoader::LibPrefix() +{ + return "lib"; +} + +const char* vtkDynamicLoader::LibExtension() +{ + return ".so"; +} + +const char* vtkDynamicLoader::LastError() +{ + return 0; +} + +#endif + + + + +// --------------------------------------------------------------- +// 3. Implementation for Windows win32 code +#ifdef _WIN32 +# include "vtkWindows.h" +#define VTKDYNAMICLOADER_DEFINED 1 + +vtkLibHandle vtkDynamicLoader::OpenLibrary(const char* libname ) +{ +#ifdef UNICODE + wchar_t *libn = new wchar_t [mbstowcs(NULL, libname, 32000)+1]; + mbstowcs(libn, libname, 32000); + vtkLibHandle ret = LoadLibrary(libn); + delete [] libn; + return ret; +#else + return LoadLibrary(libname); +#endif +} + +int vtkDynamicLoader::CloseLibrary(vtkLibHandle lib) +{ + return (int)FreeLibrary(static_cast(lib)); +} + +void* vtkDynamicLoader::GetSymbolAddress(vtkLibHandle lib, const char* sym) +{ +#if defined (UNICODE) && !defined(_MSC_VER) + wchar_t *wsym = new wchar_t [mbstowcs(NULL, sym, 32000)+1]; + mbstowcs(wsym, sym, 32000); + // Force GetProcAddress to return void* with a c style cast + // This is because you can not cast a function to a void* without + // an error on gcc 3.2 and ANSI C++, + void *ret = (void*)GetProcAddress(lib, wsym); + delete [] wsym; + return ret; +#else + return (void*)GetProcAddress(static_cast(lib), sym); +#endif +} + +const char* vtkDynamicLoader::LibPrefix() +{ + return ""; +} + +const char* vtkDynamicLoader::LibExtension() +{ + return ".dll"; +} + +const char* vtkDynamicLoader::LastError() +{ + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + + // Free the buffer. + static char* str = 0; + delete [] str; + if (lpMsgBuf) + { + str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf); + LocalFree( lpMsgBuf ); + } + return str; +} + +#endif + +// --------------------------------------------------------------- +// 4. Implementation for default UNIX machines. +// if nothing has been defined then use this +#ifndef VTKDYNAMICLOADER_DEFINED +#define VTKDYNAMICLOADER_DEFINED +// Setup for most unix machines +#include + +vtkLibHandle vtkDynamicLoader::OpenLibrary(const char* libname ) +{ + return dlopen(libname, RTLD_LAZY); +} + +int vtkDynamicLoader::CloseLibrary(vtkLibHandle lib) +{ + // dlclose returns 0 on success, and non-zero on error. + return !((int)dlclose(lib)); +} + +void* vtkDynamicLoader::GetSymbolAddress(vtkLibHandle lib, const char* sym) +{ + return dlsym(lib, sym); +} + +const char* vtkDynamicLoader::LibPrefix() +{ + return "lib"; +} + +const char* vtkDynamicLoader::LibExtension() +{ + return ".so"; +} + +const char* vtkDynamicLoader::LastError() +{ + return dlerror(); +} +#endif diff --git a/Common/vtkDynamicLoader.h b/Common/vtkDynamicLoader.h new file mode 100644 index 0000000..62eb145 --- /dev/null +++ b/Common/vtkDynamicLoader.h @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDynamicLoader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDynamicLoader - class interface to system dynamic libraries +// .SECTION Description +// vtkDynamicLoader provides a portable interface to loading dynamic +// libraries into a process. + + +#ifndef __vtkDynamicLoader_h +#define __vtkDynamicLoader_h +#include "vtkObject.h" + +//BTX +// Ugly stuff for library handles +// They are different on several different OS's +#if defined(__hpux) +# include // Needed for special dynamic loading on hp + typedef shl_t vtkLibHandle; +#elif defined(_WIN32) + typedef void* vtkLibHandle; +#else + typedef void* vtkLibHandle; +#endif +//ETX + + + +class VTK_COMMON_EXPORT vtkDynamicLoader : public vtkObject +{ +public: + static vtkDynamicLoader* New(); + vtkTypeRevisionMacro(vtkDynamicLoader,vtkObject); + + //BTX + // Description: + // Load a dynamic library into the current process. + // The returned vtkLibHandle can be used to access the symbols in the + // library. + static vtkLibHandle OpenLibrary(const char*); + + // Description: + // Attempt to detach a dynamic library from the + // process. A value of true is returned if it is successful. + static int CloseLibrary(vtkLibHandle); + //ETX + + // Description: + // Find the address of the symbol in the given library + static void* GetSymbolAddress(vtkLibHandle, const char*); + + // Description: + // Return the library prefix for the given architecture + static const char* LibPrefix(); + + // Description: + // Return the library extension for the given architecture + static const char* LibExtension(); + + // Description: + // Return the last error produced from a calls made on this class. + static const char* LastError(); + +protected: + vtkDynamicLoader() {}; + ~vtkDynamicLoader() {}; + + +private: + vtkDynamicLoader(const vtkDynamicLoader&); // Not implemented. + void operator=(const vtkDynamicLoader&); // Not implemented. +}; + +#endif diff --git a/Common/vtkEdgeTable.cxx b/Common/vtkEdgeTable.cxx new file mode 100644 index 0000000..81c7ae4 --- /dev/null +++ b/Common/vtkEdgeTable.cxx @@ -0,0 +1,593 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEdgeTable.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEdgeTable.h" +#include "vtkPoints.h" +#include "vtkIdList.h" +#include "vtkVoidArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkEdgeTable, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkEdgeTable); + +// Instantiate object based on maximum point id. +vtkEdgeTable::vtkEdgeTable() +{ + this->Table = NULL; + this->Attributes = NULL; + this->PointerAttributes = NULL; + this->Points = NULL; + + this->TableMaxId = -1; + this->TableSize = 0; + + this->Position[0] = 0; + this->Position[1] = -1; + this->NumberOfEdges = 0; +} + +// Free memory and return to instantiated state. +void vtkEdgeTable::Initialize() +{ + vtkIdType i; + + if ( this->Table ) + { + for (i=0; i < this->TableSize; i++) + { + if ( this->Table[i] ) + { + this->Table[i]->Delete(); + } + } + delete [] this->Table; + this->Table = NULL; + this->TableMaxId = -1; + + if ( this->StoreAttributes == 1 ) + { + for (i=0; i < this->TableSize; i++) + { + if ( this->Attributes[i] ) + { + this->Attributes[i]->Delete(); + } + } + delete [] this->Attributes; + this->Attributes = NULL; + } + else if ( this->StoreAttributes == 2 ) + { + for (i=0; i < this->TableSize; i++) + { + if ( this->PointerAttributes[i] ) + { + this->PointerAttributes[i]->Delete(); + } + } + delete [] this->PointerAttributes; + this->PointerAttributes = NULL; + } + }//if table defined + + if ( this->Points ) + { + this->Points->Delete(); + this->Points = NULL; + } + + this->TableSize = 0; + this->NumberOfEdges = 0; +} + +// Free memory and return to instantiated state. +void vtkEdgeTable::Reset() +{ + vtkIdType i; + + if ( this->Table ) + { + for (i=0; i < this->TableSize; i++) + { + if ( this->Table[i] ) + { + this->Table[i]->Reset(); + } + } + + if ( this->StoreAttributes == 1 && this->Attributes ) + { + for (i=0; i < this->TableSize; i++) + { + if ( this->Attributes[i] ) + { + this->Attributes[i]->Reset(); + } + } + } + else if ( this->StoreAttributes == 2 && this->PointerAttributes ) + { + for (i=0; i < this->TableSize; i++) + { + if ( this->PointerAttributes[i] ) + { + this->PointerAttributes[i]->Reset(); + } + } + } + }//if table defined + + this->TableMaxId = -1; + + if ( this->Points ) + { + this->Points->Reset(); + } + + this->NumberOfEdges = 0; +} + +vtkEdgeTable::~vtkEdgeTable() +{ + this->Initialize(); +} + +int vtkEdgeTable::InitEdgeInsertion(vtkIdType numPoints, int storeAttributes) +{ + vtkIdType i; + + numPoints = (numPoints < 1 ? 1 : numPoints); + + // Discard old memory if not enough has been previously allocated + this->StoreAttributes = storeAttributes; + this->TableMaxId = -1; + + if ( numPoints > this->TableSize ) + { + this->Initialize(); + this->Table = new vtkIdList *[numPoints]; + for (i=0; i < numPoints; i++) + { + this->Table[i] = NULL; + } + + if (this->StoreAttributes == 1) + { + this->Attributes = new vtkIdList *[numPoints]; + for (i=0; i < numPoints; i++) + { + this->Attributes[i] = NULL; + } + } + else if (this->StoreAttributes == 2) + { + this->PointerAttributes = new vtkVoidArray *[numPoints]; + for (i=0; i < numPoints; i++) + { + this->PointerAttributes[i] = NULL; + } + } + this->TableSize = numPoints; + } + + // Otherwise, reuse the old memory + else + { + this->Reset(); + } + + this->Position[0] = 0; + this->Position[1] = -1; + + this->NumberOfEdges = 0; + + return 1; +} + +// Return non-negative if edge (p1,p2) is an edge; otherwise -1. +vtkIdType vtkEdgeTable::IsEdge(vtkIdType p1, vtkIdType p2) +{ + vtkIdType index, search; + + if ( p1 < p2 ) + { + index = p1; + search = p2; + } + else + { + index = p2; + search = p1; + } + + if ( this->Table[index] == NULL ) + { + return (-1); + } + else + { + vtkIdType loc; + if ( (loc=this->Table[index]->IsId(search)) == (-1) ) + { + return (-1); + } + else + { + if ( this->StoreAttributes == 1 ) + { + return this->Attributes[index]->GetId(loc); + } + else + { + return 1; + } + } + } +} + +// Return non-negative if edge (p1,p2) is an edge; otherwise -1. +void vtkEdgeTable::IsEdge(vtkIdType p1, vtkIdType p2, void* &ptr) +{ + vtkIdType index, search; + + if ( p1 < p2 ) + { + index = p1; + search = p2; + } + else + { + index = p2; + search = p1; + } + + if ( this->Table[index] == NULL ) + { + ptr = NULL; + } + else + { + vtkIdType loc; + if ( (loc=this->Table[index]->IsId(search)) == (-1) ) + { + ptr = NULL; + } + else + { + if ( this->StoreAttributes == 2 ) + { + ptr = this->PointerAttributes[index]->GetVoidPointer(loc); + } + else + { + ptr = NULL; + } + } + } +} + +// Insert the edge (p1,p2) into the table. It is the user's responsibility to +// check if the edge has already been inserted. +vtkIdType vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2) +{ + vtkIdType index, search; + + if ( p1 < p2 ) + { + index = p1; + search = p2; + } + else + { + index = p2; + search = p1; + } + + if ( index >= this->TableSize ) + { + this->Resize(index+1); + } + + if ( index > this->TableMaxId ) + { + this->TableMaxId = index; + } + + if ( this->Table[index] == NULL ) + { + this->Table[index] = vtkIdList::New(); + this->Table[index]->Allocate(6,12); + if ( this->StoreAttributes == 1 ) + { + if ( this->Attributes[index] ) + { + this->Attributes[index]->Delete(); + } + this->Attributes[index] = vtkIdList::New(); + this->Attributes[index]->Allocate(6,12); + } + } + + this->Table[index]->InsertNextId(search); + if ( this->StoreAttributes == 1 ) + { + this->Attributes[index]->InsertNextId(this->NumberOfEdges); + } + this->NumberOfEdges++; + + return (this->NumberOfEdges - 1); +} + +void vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2, + vtkIdType attributeId) +{ + vtkIdType index, search; + + if ( p1 < p2 ) + { + index = p1; + search = p2; + } + else + { + index = p2; + search = p1; + } + + if ( index >= this->TableSize ) + { + this->Resize(index+1); + } + + if ( index > this->TableMaxId ) + { + this->TableMaxId = index; + } + + if ( this->Table[index] == NULL ) + { + this->Table[index] = vtkIdList::New(); + this->Table[index]->Allocate(6,12); + if ( this->StoreAttributes == 1 ) + { + this->Attributes[index] = vtkIdList::New(); + this->Attributes[index]->Allocate(6,12); + } + } + + this->NumberOfEdges++; + this->Table[index]->InsertNextId(search); + if ( this->StoreAttributes ) + { + this->Attributes[index]->InsertNextId(attributeId); + } +} + +void vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2, void* ptr) +{ + vtkIdType index, search; + + if ( p1 < p2 ) + { + index = p1; + search = p2; + } + else + { + index = p2; + search = p1; + } + + if ( index >= this->TableSize ) + { + this->Resize(index+1); + } + + if ( index > this->TableMaxId ) + { + this->TableMaxId = index; + } + + if ( this->Table[index] == NULL ) + { + this->Table[index] = vtkIdList::New(); + this->Table[index]->Allocate(6,12); + if ( this->StoreAttributes == 2 ) + { + this->PointerAttributes[index] = vtkVoidArray::New(); + this->PointerAttributes[index]->Allocate(6,12); + } + } + + this->NumberOfEdges++; + this->Table[index]->InsertNextId(search); + if ( this->StoreAttributes == 2 ) + { + this->PointerAttributes[index]->InsertNextVoidPointer(ptr); + } +} + + +// Intialize traversal of edges in table. +void vtkEdgeTable::InitTraversal() +{ + this->Position[0] = 0; + this->Position[1] = -1; +} + +// Traverse list of edges in table. Return the edge as (p1,p2), where p1 and +// p2 are point id's. Method return value is <0 if the list is exhausted; +// otherwise a valid id >=0. The value of p1 is guaranteed to be <= p2. The +// return value is an id that can be used for accessing attributes. +vtkIdType vtkEdgeTable::GetNextEdge(vtkIdType &p1, vtkIdType &p2) +{ + for ( ; this->Position[0] <= this->TableMaxId; + this->Position[0]++, this->Position[1]=(-1) ) + { + if ( this->Table[this->Position[0]] != NULL && + ++this->Position[1] < this->Table[this->Position[0]]->GetNumberOfIds() ) + { + p1 = this->Position[0]; + p2 = this->Table[this->Position[0]]->GetId(this->Position[1]); + if ( this->StoreAttributes == 1 ) + { + return this->Attributes[this->Position[0]]->GetId(this->Position[1]); + } + else + { + return (-1); + } + } + } + + return (-1); +} + +// Traverse list of edges in table. Return the edge as (p1,p2), where p1 and +// p2 are point id's. The value of p1 is guaranteed to be <= p2. The +// return value is either 1 for success or 0 if the list is exhausted. +int vtkEdgeTable::GetNextEdge(vtkIdType &p1, vtkIdType &p2, void* &ptr) +{ + for ( ; this->Position[0] <= this->TableMaxId; + this->Position[0]++, this->Position[1]=(-1) ) + { + if ( this->Table[this->Position[0]] != NULL && + ++this->Position[1] < this->Table[this->Position[0]]->GetNumberOfIds() ) + { + p1 = this->Position[0]; + p2 = this->Table[this->Position[0]]->GetId(this->Position[1]); + if ( this->StoreAttributes == 2 ) + { + this->IsEdge(p1, p2, ptr); + } + else + { + ptr = NULL; + } + return 1; + } + } + return 0; +} + +vtkIdList **vtkEdgeTable::Resize(vtkIdType sz) +{ + vtkIdList **newTableArray; + vtkIdList **newAttributeArray; + vtkVoidArray **newPointerAttributeArray; + vtkIdType newSize, i; + vtkIdType extend=this->TableSize/2 + 1; + + if (sz >= this->TableSize) + { + newSize = this->TableSize + + extend*(((sz-this->TableSize)/extend)+1); + } + else + { + newSize = sz; + } + + sz = (sz < this->TableSize ? sz : this->TableSize); + newTableArray = new vtkIdList *[newSize]; + memcpy(newTableArray, this->Table, sz * sizeof(vtkIdList *)); + for (i=sz; i < newSize; i++) + { + newTableArray[i] = NULL; + } + this->TableSize = newSize; + delete [] this->Table; + this->Table = newTableArray; + + if ( this->StoreAttributes == 1 ) + { + newAttributeArray = new vtkIdList *[newSize]; + memcpy(newAttributeArray, this->Attributes, sz * sizeof(vtkIdList *)); + for (i=sz; i < newSize; i++) + { + newAttributeArray[i] = NULL; + } + if ( this->Attributes ) + { + delete [] this->Attributes; + } + this->Attributes = newAttributeArray; + } + else if ( this->StoreAttributes == 2 ) + { + newPointerAttributeArray = new vtkVoidArray *[newSize]; + memcpy(newPointerAttributeArray, this->Attributes, sz * sizeof(vtkVoidArray *)); + for (i=sz; i < newSize; i++) + { + newPointerAttributeArray[i] = NULL; + } + if ( this->PointerAttributes ) + { + delete [] this->PointerAttributes; + } + this->PointerAttributes = newPointerAttributeArray; + } + + return this->Table; +} + +int vtkEdgeTable::InitPointInsertion(vtkPoints *newPts, vtkIdType estSize) +{ + // Initialize + if ( this->Table ) + { + this->Initialize(); + } + if ( newPts == NULL ) + { + vtkErrorMacro(<<"Must define points for point insertion"); + return 0; + } + if (this->Points != NULL) + { + this->Points->Delete(); + } + // Set up the edge insertion + this->InitEdgeInsertion(estSize,1); + + this->Points = newPts; + this->Points->Register(this); + + return 1; +} + +int vtkEdgeTable::InsertUniquePoint(vtkIdType p1, vtkIdType p2, double x[3], + vtkIdType &ptId) +{ + int loc = this->IsEdge(p1,p2); + + if ( loc != -1 ) + { + ptId = loc; + return 0; + } + else + { + ptId = this->InsertEdge(p1,p2); + this->Points->InsertPoint(ptId,x); + return 1; + } +} + +void vtkEdgeTable::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfEdges: " << this->GetNumberOfEdges() << "\n"; +} diff --git a/Common/vtkEdgeTable.h b/Common/vtkEdgeTable.h new file mode 100644 index 0000000..86d6dfc --- /dev/null +++ b/Common/vtkEdgeTable.h @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEdgeTable.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEdgeTable - keep track of edges (edge is pair of integer id's) +// .SECTION Description +// vtkEdgeTable is a general object for keeping track of lists of edges. An +// edge is defined by the pair of point id's (p1,p2). Methods are available +// to insert edges, check if edges exist, and traverse the list of edges. +// Also, it's possible to associate attribute information with each edge. +// The attribute information may take the form of vtkIdType id's, void* +// pointers, or points. To store attributes, make sure that +// InitEdgeInsertion() is invoked with the storeAttributes flag set properly. +// If points are inserted, use the methods InitPointInsertion() and +// InsertUniquePoint(). + +#ifndef __vtkEdgeTable_h +#define __vtkEdgeTable_h + +#include "vtkObject.h" + +class vtkIdList; +class vtkPoints; +class vtkVoidArray; + +class VTK_COMMON_EXPORT vtkEdgeTable : public vtkObject +{ +public: + // Description: + // Instantiate object assuming that 1000 edges are to be inserted. + static vtkEdgeTable *New(); + + vtkTypeRevisionMacro(vtkEdgeTable,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Free memory and return to the initially instantiated state. + void Initialize(); + + // Description: + // Initialize the edge insertion process. Provide an estimate of the number + // of points in a dataset (the maximum range value of p1 or p2). The + // storeAttributes variable controls whether attributes are to be stored + // with the edge, and what type of attributes. If storeAttributes==1, then + // attributes of vtkIdType can be stored. If storeAttributes==2, then + // attributes of type void* can be stored. In either case, additional + // memory will be required by the data structure to store attribute data + // per each edge. This method is used in conjunction with one of the three + // InsertEdge() methods described below (don't mix the InsertEdge() + // methods---make sure that the one used is consistent with the + // storeAttributes flag set in InitEdgeInsertion()). + int InitEdgeInsertion(vtkIdType numPoints, int storeAttributes=0); + + // Description: + // Insert the edge (p1,p2) into the table. It is the user's + // responsibility to check if the edge has already been inserted + // (use IsEdge()). If the storeAttributes flag in InitEdgeInsertion() + // has been set, then the method returns a unique integer id (i.e., + // the edge id) that can be used to set and get edge + // attributes. Otherwise, the method will return 1. Do not mix this + // method with the InsertEdge() method that follows. + vtkIdType InsertEdge(vtkIdType p1, vtkIdType p2); + + // Description: + // Insert the edge (p1,p2) into the table with the attribute id + // specified (make sure the attributeId >= 0). Note that the + // attributeId is ignored if the storeAttributes variable was set to + // 0 in the InitEdgeInsertion() method. It is the user's + // responsibility to check if the edge has already been inserted + // (use IsEdge()). Do not mix this method with the other two + // InsertEdge() methods. + void InsertEdge(vtkIdType p1, vtkIdType p2, vtkIdType attributeId); + + // Description: + // Insert the edge (p1,p2) into the table with the attribute id + // specified (make sure the attributeId >= 0). Note that the + // attributeId is ignored if the storeAttributes variable was set to + // 0 in the InitEdgeInsertion() method. It is the user's + // responsibility to check if the edge has already been inserted + // (use IsEdge()). Do not mix this method with the other two + // InsertEdge() methods. + void InsertEdge(vtkIdType p1, vtkIdType p2, void* ptr); + + // Description: + // Return an integer id for the edge, or an attribute id of the edge + // (p1,p2) if the edge has been previously defined (it depends upon + // which version of InsertEdge() is being used); otherwise -1. The + // unique integer id can be used to set and retrieve attributes to + // the edge. + vtkIdType IsEdge(vtkIdType p1, vtkIdType p2); + + // Description: + // Similar to above, but returns a void* pointer is InitEdgeInsertion() + // has been called with storeAttributes==2. A NULL pointer value + // is returned if the edge does not exist. + void IsEdge(vtkIdType p1, vtkIdType p2, void* &ptr); + + // Description: + // Initialize the point insertion process. The newPts is an object + // representing point coordinates into which incremental insertion methods + // place their data. The points are associated with the edge. + int InitPointInsertion(vtkPoints *newPts, vtkIdType estSize); + + // Description: + // Insert a unique point on the specified edge. Invoke this method only + // after InitPointInsertion() has been called. Return 0 if point was + // already in the list, otherwise return 1. + int InsertUniquePoint(vtkIdType p1, vtkIdType p2, double x[3], + vtkIdType &ptId); + + // Description: + // Return the number of edges that have been inserted thus far. + vtkGetMacro(NumberOfEdges, vtkIdType); + + // Description: + // Intialize traversal of edges in table. + void InitTraversal(); + + // Description: + // Traverse list of edges in table. Return the edge as (p1,p2), where p1 + // and p2 are point id's. Method return value is <0 if list is exhausted; + // non-zero otherwise. The value of p1 is guaranteed to be <= p2. + vtkIdType GetNextEdge(vtkIdType &p1, vtkIdType &p2); + + // Description: + // Similar to above, but fills a void* pointer if InitEdgeInsertion() + // has been called with storeAttributes==2. A NULL pointer value + // is filled otherwise. Returns 0 if list is exhausted. + int GetNextEdge(vtkIdType &p1, vtkIdType &p2, void* &ptr); + + // Description: + // Reset the object and prepare for reinsertion of edges. Does not delete + // memory like the Initialize() method. + void Reset(); + +protected: + vtkEdgeTable(); + ~vtkEdgeTable(); + + vtkIdList **Table; + vtkIdType TableMaxId; //maximum point id inserted + vtkIdType TableSize; //allocated size of table + int Position[2]; + int Extend; + vtkIdType NumberOfEdges; + vtkPoints *Points; //support point insertion + + int StoreAttributes; //==0:no attributes stored;==1:vtkIdType;==2:void* + vtkIdList **Attributes; //used to store IdTypes attributes + vtkVoidArray **PointerAttributes; //used to store void* pointers + + vtkIdList **Resize(vtkIdType size); + +private: + vtkEdgeTable(const vtkEdgeTable&); // Not implemented. + void operator=(const vtkEdgeTable&); // Not implemented. +}; + +#endif + diff --git a/Common/vtkErrorCode.cxx b/Common/vtkErrorCode.cxx new file mode 100644 index 0000000..f75fb62 --- /dev/null +++ b/Common/vtkErrorCode.cxx @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkErrorCode.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkErrorCode.h" + +#include +#include +#include + +// this list should only contain the initial, contiguous +// set of error codes and should not include UserError +static const char *vtkErrorCodeErrorStrings[] = { + "NoError", + "FileNotFoundError", + "CannotOpenFileError", + "UnrecognizedFileTypeError", + "PrematureEndOfFileError", + "FileFormatError", + "NoFileNameError", + "OutOfDiskSpaceError", + "UnknownError", + "UserError", + NULL +}; + +const char *vtkErrorCode::GetStringFromErrorCode(unsigned long error) +{ + static unsigned long numerrors = 0; + if(error < FirstVTKErrorCode) + { + return strerror(static_cast(error)); + } + else + { + error -= FirstVTKErrorCode; + } + + // find length of table + if (!numerrors) + { + while (vtkErrorCodeErrorStrings[numerrors] != NULL) + { + numerrors++; + } + } + if (error < numerrors) + { + return vtkErrorCodeErrorStrings[error]; + } + else if (error == vtkErrorCode::UserError) + { + return "UserError"; + } + else + { + return "NoError"; + } +} + +unsigned long vtkErrorCode::GetErrorCodeFromString(const char *error) +{ + unsigned long i; + + for (i = 0; vtkErrorCodeErrorStrings[i] != NULL; i++) + { + if (!strcmp(vtkErrorCodeErrorStrings[i],error)) + { + return i; + } + } + if (!strcmp("UserError",error)) + { + return vtkErrorCode::UserError; + } + return vtkErrorCode::NoError; +} + + +unsigned long vtkErrorCode::GetLastSystemError() +{ + return static_cast(errno); +} + + + diff --git a/Common/vtkErrorCode.h b/Common/vtkErrorCode.h new file mode 100644 index 0000000..30a1f8c --- /dev/null +++ b/Common/vtkErrorCode.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkErrorCode.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkErrorCode - superclass for error codes +// .SECTION Description +// vtkErrorCode is an mechanism for (currently) reader object to +// return errors during reading file. + +#ifndef __vtkErrorCode_h +#define __vtkErrorCode_h +#include "vtkSystemIncludes.h" + +// The superclass that all commands should be subclasses of +class VTK_COMMON_EXPORT vtkErrorCode +{ +public: + static const char *GetStringFromErrorCode(unsigned long event); + static unsigned long GetErrorCodeFromString(const char *event); + static unsigned long GetLastSystemError(); +//BTX + // all the currently defined error codes + // developers can use -- vtkErrorCode::UserError + int to + // specify their own errors. + // if this list is adjusted, be sure to adjust vtkErrorCodeErrorStrings + // in vtkErrorCode.cxx to match. + enum ErrorIds { + NoError = 0, + FirstVTKErrorCode = 20000, + FileNotFoundError, + CannotOpenFileError, + UnrecognizedFileTypeError, + PrematureEndOfFileError, + FileFormatError, + NoFileNameError, + OutOfDiskSpaceError, + UnknownError, + UserError = 40000 + }; +//ETX +}; + +#endif /* __vtkErrorCode_h */ + diff --git a/Common/vtkEventForwarderCommand.cxx b/Common/vtkEventForwarderCommand.cxx new file mode 100644 index 0000000..0818541 --- /dev/null +++ b/Common/vtkEventForwarderCommand.cxx @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEventForwarderCommand.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkEventForwarderCommand.h" +#include "vtkObject.h" + +//---------------------------------------------------------------- +vtkEventForwarderCommand::vtkEventForwarderCommand() +{ + this->Target = NULL; +} + +//---------------------------------------------------------------- +void vtkEventForwarderCommand::Execute(vtkObject *, + unsigned long event, + void *call_data) +{ + if (this->Target) + { + this->Target->InvokeEvent(event, call_data); + } +} + diff --git a/Common/vtkEventForwarderCommand.h b/Common/vtkEventForwarderCommand.h new file mode 100644 index 0000000..0590d90 --- /dev/null +++ b/Common/vtkEventForwarderCommand.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEventForwarderCommand.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEventForwarderCommand - a simple event forwarder command +// .SECTION Description +// Use vtkEventForwarderCommand to forward an event to a new object. +// This command will intercept the event, and use InvokeEvent +// on a 'target' as if that object was the one that invoked the event instead +// of the object this commmand was attached to using AddObserver. +// +// .SECTION See Also +// vtkCommand + +#ifndef __vtkEventForwarderCommand_h +#define __vtkEventForwarderCommand_h + +#include "vtkCommand.h" + +class VTK_COMMON_EXPORT vtkEventForwarderCommand : public vtkCommand +{ +public: + static vtkEventForwarderCommand *New() + {return new vtkEventForwarderCommand;}; + + // Description: + // Satisfy the superclass API for callbacks. Recall that the caller is + // the instance invoking the event; eid is the event id (see + // vtkCommand.h); and calldata is information sent when the callback + // was invoked (e.g., progress value in the vtkCommand::ProgressEvent). + void Execute(vtkObject *caller, unsigned long eid, void *callData); + + // Description: + // Methods to set and get client and callback information, and the callback + // function. + virtual void SetTarget(vtkObject *obj) + { this->Target = obj; } + virtual void* GetTarget() + { return this->Target; } + +protected: + + vtkObject *Target; + + vtkEventForwarderCommand(); + ~vtkEventForwarderCommand() {}; +}; + +#endif /* __vtkEventForwarderCommand_h */ + diff --git a/Common/vtkExtentSplitter.cxx b/Common/vtkExtentSplitter.cxx new file mode 100644 index 0000000..28e9c02 --- /dev/null +++ b/Common/vtkExtentSplitter.cxx @@ -0,0 +1,479 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtentSplitter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtentSplitter.h" + +#include "vtkObjectFactory.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkExtentSplitter, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkExtentSplitter); + +//---------------------------------------------------------------------------- +struct vtkExtentSplitterExtent +{ + int extent[6]; +}; + +struct vtkExtentSplitterSource +{ + int extent[6]; + int priority; +}; + +struct vtkExtentSplitterSubExtent +{ + int extent[6]; + int source; +}; + +class vtkExtentSplitterInternals +{ +public: + typedef vtkstd::queue QueueType; + typedef vtkstd::map SourcesType; + typedef vtkstd::vector SubExtentsType; + SourcesType Sources; + QueueType Queue; + SubExtentsType SubExtents; +}; + +//---------------------------------------------------------------------------- +vtkExtentSplitter::vtkExtentSplitter() +{ + this->Internal = new vtkExtentSplitterInternals; + this->PointMode = 0; +} + +//---------------------------------------------------------------------------- +vtkExtentSplitter::~vtkExtentSplitter() +{ + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + vtkIndent nextIndent = indent.GetNextIndent(); + os << indent << "PointMode: " << this->PointMode << "\n"; + if(this->Internal->Sources.empty()) + { + os << indent << "Extent Sources: (none)\n"; + } + else + { + os << indent << "Extent Sources: (format = \"id priority: extent\")\n"; + for(vtkExtentSplitterInternals::SourcesType::const_iterator src = + this->Internal->Sources.begin(); + src != this->Internal->Sources.end(); ++src) + { + const int* extent = src->second.extent; + os << nextIndent << src->first + << " " << src->second.priority << ": " + << extent[0] << " " << extent[1] << " " + << extent[2] << " " << extent[3] << " " + << extent[4] << " " << extent[5] << "\n"; + } + } + os << indent << "Number of Extents in Queue: " << + (int)this->Internal->Queue.size() << "\n"; + if(this->Internal->SubExtents.empty()) + { + os << indent << "SubExtents: (none)\n"; + } + else + { + os << indent << "SubExtents: (format = \"id: extent\")\n"; + for(vtkExtentSplitterInternals::SubExtentsType::const_iterator i = + this->Internal->SubExtents.begin(); + i != this->Internal->SubExtents.end(); ++i) + { + const int* extent = i->extent; + os << nextIndent << i->source << ": " + << extent[0] << " " << extent[1] << " " + << extent[2] << " " << extent[3] << " " + << extent[4] << " " << extent[5] << "\n"; + } + } +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::AddExtentSource(int id, int priority, int x0, int x1, + int y0, int y1, int z0, int z1) +{ + // Add the source. + vtkExtentSplitterSource& source = this->Internal->Sources[id]; + source.extent[0] = x0; + source.extent[1] = x1; + source.extent[2] = y0; + source.extent[3] = y1; + source.extent[4] = z0; + source.extent[5] = z1; + source.priority = priority; + + // Previously calculated sub-extents are now invalid. + this->Internal->SubExtents.clear(); +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::AddExtentSource(int id, int priority, int* extent) +{ + this->AddExtentSource(id, priority, extent[0], extent[1], extent[2], + extent[3], extent[4], extent[5]); +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::RemoveExtentSource(int id) +{ + // Remove the source. + this->Internal->Sources.erase(id); + + // Previously calculated sub-extents are now invalid. + this->Internal->SubExtents.clear(); +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::RemoveAllExtentSources() +{ + // Clear the set of sources. + this->Internal->Sources.clear(); + + // Previously calculated sub-extents are now invalid. + this->Internal->SubExtents.clear(); +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::AddExtent(int x0, int x1, int y0, int y1, + int z0, int z1) +{ + // Queue the extent. + vtkExtentSplitterExtent e; + e.extent[0] = x0; + e.extent[1] = x1; + e.extent[2] = y0; + e.extent[3] = y1; + e.extent[4] = z0; + e.extent[5] = z1; + this->Internal->Queue.push(e); + + // Previously calculated sub-extents are now invalid. + this->Internal->SubExtents.clear(); +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::AddExtent(int* extent) +{ + this->AddExtent(extent[0], extent[1], extent[2], + extent[3], extent[4], extent[5]); +} + +//---------------------------------------------------------------------------- +int vtkExtentSplitter::GetNumberOfSubExtents() +{ + return static_cast(this->Internal->SubExtents.size()); +} + +//---------------------------------------------------------------------------- +int* vtkExtentSplitter::GetSubExtent(int index) +{ + if(index < 0 || index >= this->GetNumberOfSubExtents()) + { + static int dummy[6] = {0, -1, 0, -1, 0, -1}; + vtkErrorMacro("SubExtent index " << index << " is out of range [0," + << this->GetNumberOfSubExtents()-1 << "]"); + return dummy; + } + return this->Internal->SubExtents[index].extent; +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::GetSubExtent(int index, int* extent) +{ + if(index < 0 || index >= this->GetNumberOfSubExtents()) + { + vtkErrorMacro("SubExtent index " << index << " is out of range [0," + << this->GetNumberOfSubExtents()-1 << "]"); + extent[0] = 0; + extent[1] = -1; + extent[2] = 0; + extent[3] = -1; + extent[4] = 0; + extent[5] = -1; + } + else + { + int i; + int* e = this->Internal->SubExtents[index].extent; + for(i=0; i < 6; ++i) + { + extent[i] = e[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkExtentSplitter::GetSubExtentSource(int index) +{ + if(index < 0 || index >= this->GetNumberOfSubExtents()) + { + vtkErrorMacro("SubExtent index " << index << " is out of range [0," + << this->GetNumberOfSubExtents()-1 << "]"); + return -1; + } + return this->Internal->SubExtents[index].source; +} + +//---------------------------------------------------------------------------- +int vtkExtentSplitter::ComputeSubExtents() +{ + // Assume success. + int result = 1; + + vtkExtentSplitterInternals::SubExtentsType subExtents; + int bestPriority; + int dimensionality = 0; + + while(!this->Internal->Queue.empty()) + { + // Pop the next extent off the queue. + vtkExtentSplitterExtent e = this->Internal->Queue.front(); + this->Internal->Queue.pop(); + + // In non-PointMode, intersections must have the same topological + // dimension as the original extent. This will prevent + // high-priority source extents from repeatedly producing + // single-point-wide intersections. + if(!this->PointMode) + { + dimensionality = (((e.extent[1]-e.extent[0] > 0)?1:0)+ + ((e.extent[3]-e.extent[2] > 0)?1:0)+ + ((e.extent[5]-e.extent[4] > 0)?1:0)); + } + + // Intersect the extent with each extent source. + subExtents.clear(); + bestPriority = -1; + vtkExtentSplitterSubExtent se; + for(vtkExtentSplitterInternals::SourcesType::const_iterator src = + this->Internal->Sources.begin(); + src != this->Internal->Sources.end(); ++src) + { + se.source = src->first; + if(this->IntersectExtents(e.extent, src->second.extent, se.extent) && + (this->PointMode || + (dimensionality == (((se.extent[1]-se.extent[0] > 0)?1:0)+ + ((se.extent[3]-se.extent[2] > 0)?1:0)+ + ((se.extent[5]-se.extent[4] > 0)?1:0))))) + { + // Non-zero intersection volume. Add the extent as a + // candidate for best extent. + if(src->second.priority > bestPriority) + { + // New highest priority. Clear previous intersections with + // lower priority. + subExtents.clear(); + subExtents.push_back(se); + bestPriority = src->second.priority; + } + else if(src->second.priority == bestPriority) + { + // Matching priority. Add this intersection to the list. + subExtents.push_back(se); + } + } + } + + // Check whether any extent sources intersected the extent. + if(subExtents.empty()) + { + // No extent source intersected the extent. Add the extent as + // an error. + int i; + result = 0; + se.source = -1; + for(i=0; i < 6; ++i) + { + se.extent[i] = e.extent[i]; + } + this->Internal->SubExtents.push_back(se); + } + else + { + // Choose the extent intersection with the largest volume. + int bestVolume = 0; + int bestIndex = 0; + int i; + for(i=0; i < static_cast(subExtents.size()); ++i) + { + int* extent = subExtents[i].extent; + int volume = ((extent[1]-extent[0]+1)* + (extent[3]-extent[2]+1)* + (extent[5]-extent[4]+1)); + if(volume > bestVolume) + { + bestVolume = volume; + bestIndex = i; + } + } + + // Add this extent source with its sub-extent. + se.source = subExtents[bestIndex].source; + for(i=0; i < 6; ++i) + { + se.extent[i] = subExtents[bestIndex].extent[i]; + } + this->Internal->SubExtents.push_back(se); + + // Subtract the sub-extent from the extent and split the rest of + // the volume into more sub-extents. + this->SplitExtent(e.extent, se.extent); + } + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkExtentSplitter::SplitExtent(int* extent, int* subextent) +{ + // Subtract the volume described by subextent from that described by + // extent. Split the remaining region into rectangular solids and + // queue them as additional extents. We may assume that subextent + // is completely contained by extent. + vtkExtentSplitterExtent e; + + // In PointMode, there are no cell data, so we can skip over cells. + int pointMode = this->PointMode?1:0; + + // Split with xy-planes. + if(extent[4] < subextent[4]) + { + e.extent[0] = extent[0]; + e.extent[1] = extent[1]; + e.extent[2] = extent[2]; + e.extent[3] = extent[3]; + e.extent[4] = extent[4]; + e.extent[5] = subextent[4]-pointMode; + this->Internal->Queue.push(e); + + extent[4] = subextent[4]; + } + if(extent[5] > subextent[5]) + { + e.extent[0] = extent[0]; + e.extent[1] = extent[1]; + e.extent[2] = extent[2]; + e.extent[3] = extent[3]; + e.extent[4] = subextent[5]+pointMode; + e.extent[5] = extent[5]; + this->Internal->Queue.push(e); + + extent[5] = subextent[5]; + } + + // Split with xz-planes. + if(extent[2] < subextent[2]) + { + e.extent[0] = extent[0]; + e.extent[1] = extent[1]; + e.extent[2] = extent[2]; + e.extent[3] = subextent[2]-pointMode; + e.extent[4] = extent[4]; + e.extent[5] = extent[5]; + this->Internal->Queue.push(e); + + extent[2] = subextent[2]; + } + if(extent[3] > subextent[3]) + { + e.extent[0] = extent[0]; + e.extent[1] = extent[1]; + e.extent[2] = subextent[3]+pointMode; + e.extent[3] = extent[3]; + e.extent[4] = extent[4]; + e.extent[5] = extent[5]; + this->Internal->Queue.push(e); + + extent[3] = subextent[3]; + } + + // Split with yz-planes. + if(extent[0] < subextent[0]) + { + e.extent[0] = extent[0]; + e.extent[1] = subextent[0]-pointMode; + e.extent[2] = extent[2]; + e.extent[3] = extent[3]; + e.extent[4] = extent[4]; + e.extent[5] = extent[5]; + this->Internal->Queue.push(e); + + extent[0] = subextent[0]; + } + if(extent[1] > subextent[1]) + { + e.extent[0] = subextent[1]+pointMode; + e.extent[1] = extent[1]; + e.extent[2] = extent[2]; + e.extent[3] = extent[3]; + e.extent[4] = extent[4]; + e.extent[5] = extent[5]; + this->Internal->Queue.push(e); + + // Leave this line out because the value will not be used: + //extent[1] = subextent[1]; + } + + // At this point, we should have extent[i] == subextent[i] for 0 <= i < 6. + // No more volume remains. +} + +//---------------------------------------------------------------------------- +int vtkExtentSplitter::IntersectExtents(const int* extent1, const int* extent2, + int* result) +{ + if((extent1[0] > extent2[1]) || (extent1[2] > extent2[3]) || + (extent1[4] > extent2[5]) || (extent1[1] < extent2[0]) || + (extent1[3] < extent2[2]) || (extent1[5] < extent2[4])) + { + // No intersection of extents. + return 0; + } + + // Get the intersection of the extents. + result[0] = this->Max(extent1[0], extent2[0]); + result[1] = this->Min(extent1[1], extent2[1]); + result[2] = this->Max(extent1[2], extent2[2]); + result[3] = this->Min(extent1[3], extent2[3]); + result[4] = this->Max(extent1[4], extent2[4]); + result[5] = this->Min(extent1[5], extent2[5]); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkExtentSplitter::Min(int a, int b) +{ + return (a < b)? a : b; +} + +//---------------------------------------------------------------------------- +int vtkExtentSplitter::Max(int a, int b) +{ + return (a > b)? a : b; +} diff --git a/Common/vtkExtentSplitter.h b/Common/vtkExtentSplitter.h new file mode 100644 index 0000000..8003965 --- /dev/null +++ b/Common/vtkExtentSplitter.h @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtentSplitter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtentSplitter - Split an extent across other extents. +// .SECTION Description +// vtkExtentSplitter splits each input extent into non-overlapping +// sub-extents that are completely contained within other "source +// extents". A source extent corresponds to some resource providing +// an extent. Each source extent has an integer identifier, integer +// priority, and an extent. The input extents are split into +// sub-extents according to priority, availability, and amount of +// overlap of the source extents. This can be used by parallel data +// readers to read as few piece files as possible. + +#ifndef __vtkExtentSplitter_h +#define __vtkExtentSplitter_h + +#include "vtkObject.h" + +class vtkExtentSplitterInternals; + +class VTK_COMMON_EXPORT vtkExtentSplitter : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkExtentSplitter,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkExtentSplitter *New(); + + // Description: + // Add/Remove a source providing the given extent. Sources with + // higher priority numbers are favored. Source id numbers and + // priorities must be non-negative. + void AddExtentSource(int id, int priority, int x0, int x1, + int y0, int y1, int z0, int z1); + void AddExtentSource(int id, int priority, int* extent); + void RemoveExtentSource(int id); + void RemoveAllExtentSources(); + + // Description: + // Add an extent to the queue of extents to be split among the + // available sources. + void AddExtent(int x0, int x1, int y0, int y1, int z0, int z1); + void AddExtent(int* extent); + + // Description: + // Split the extents currently in the queue among the available + // sources. The queue is empty when this returns. Returns 1 if all + // extents could be read. Returns 0 if any portion of any extent + // was not available through any source. + int ComputeSubExtents(); + + // Description: + // Get the number of sub-extents into which the original set of + // extents have been split across the available sources. Valid + // after a call to ComputeSubExtents. + int GetNumberOfSubExtents(); + + // Description: + // Get the sub-extent associated with the given index. Use + // GetSubExtentSource to get the id of the source from which this + // sub-extent should be read. Valid after a call to + // ComputeSubExtents. + int* GetSubExtent(int index); + void GetSubExtent(int index, int* extent); + + // Description: + // Get the id of the source from which the sub-extent associated + // with the given index should be read. Returns -1 if no source + // provides the sub-extent. + int GetSubExtentSource(int index); + + // Description: + // Get/Set whether "point mode" is on. In point mode, sub-extents + // are generated to ensure every point in the update request is + // read, but not necessarily every cell. This can be used when + // point data are stored in a planar slice per piece with no cell + // data. The default is OFF. + vtkGetMacro(PointMode, int); + vtkSetMacro(PointMode, int); + vtkBooleanMacro(PointMode, int); + +protected: + vtkExtentSplitter(); + ~vtkExtentSplitter(); + + // Internal utility methods. + void SplitExtent(int* extent, int* subextent); + int IntersectExtents(const int* extent1, const int* extent2, int* result); + int Min(int a, int b); + int Max(int a, int b); + + // Internal implementation data. + vtkExtentSplitterInternals* Internal; + + // On if reading only all points (but not always all cells) is + // necessary. Used for reading volumes of planar slices storing + // only point data. + int PointMode; + +private: + vtkExtentSplitter(const vtkExtentSplitter&); // Not implemented. + void operator=(const vtkExtentSplitter&); // Not implemented. +}; + +#endif diff --git a/Common/vtkExtentTranslator.cxx b/Common/vtkExtentTranslator.cxx new file mode 100644 index 0000000..29a27d8 --- /dev/null +++ b/Common/vtkExtentTranslator.cxx @@ -0,0 +1,361 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtentTranslator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtentTranslator.h" +#include "vtkObjectFactory.h" +#include "vtkLargeInteger.h" + +vtkCxxRevisionMacro(vtkExtentTranslator, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkExtentTranslator); + +//---------------------------------------------------------------------------- +vtkExtentTranslator::vtkExtentTranslator() +{ + this->Piece = 0; + this->NumberOfPieces = 0; + + this->GhostLevel = 0; + + this->Extent[0] = this->Extent[2] = this->Extent[4] = 0; + this->Extent[1] = this->Extent[3] = this->Extent[5] = -1; + this->WholeExtent[0] = this->WholeExtent[2] = this->WholeExtent[4] = 0; + this->WholeExtent[1] = this->WholeExtent[3] = this->WholeExtent[5] = -1; + + // Set a default split mode to be slabs + this->SplitMode = vtkExtentTranslator::BLOCK_MODE; +} + +//---------------------------------------------------------------------------- +vtkExtentTranslator::~vtkExtentTranslator() +{ +} + +//---------------------------------------------------------------------------- +int vtkExtentTranslator::PieceToExtent() +{ + return + this->PieceToExtentThreadSafe(this->Piece, this->NumberOfPieces, + this->GhostLevel, this->WholeExtent, + this->Extent, this->SplitMode, 0); +} + +//---------------------------------------------------------------------------- +int vtkExtentTranslator::PieceToExtentByPoints() +{ + return + this->PieceToExtentThreadSafe(this->Piece, this->NumberOfPieces, + this->GhostLevel, this->WholeExtent, + this->Extent, this->SplitMode, 1); +} + +int vtkExtentTranslator::PieceToExtentThreadSafe(int piece, int numPieces, + int ghostLevel, + int *wholeExtent, + int *resultExtent, + int splitMode, + int byPoints) +{ + memcpy(resultExtent, wholeExtent, sizeof(int)*6); + int ret; + if (byPoints) + { + ret = this->SplitExtentByPoints(piece, numPieces, resultExtent, splitMode); + } + else + { + ret = this->SplitExtent(piece, numPieces, resultExtent, splitMode); + } + + if (ret == 0) + { + // Nothing in this piece. + resultExtent[0] = resultExtent[2] = resultExtent[4] = 0; + resultExtent[1] = resultExtent[3] = resultExtent[5] = -1; + return 0; + } + if (ghostLevel > 0) + { + resultExtent[0] -= ghostLevel; + resultExtent[1] += ghostLevel; + resultExtent[2] -= ghostLevel; + resultExtent[3] += ghostLevel; + resultExtent[4] -= ghostLevel; + resultExtent[5] += ghostLevel; + + if (resultExtent[0] < wholeExtent[0]) + { + resultExtent[0] = wholeExtent[0]; + } + if (resultExtent[1] > wholeExtent[1]) + { + resultExtent[1] = wholeExtent[1]; + } + if (resultExtent[2] < wholeExtent[2]) + { + resultExtent[2] = wholeExtent[2]; + } + if (resultExtent[3] > wholeExtent[3]) + { + resultExtent[3] = wholeExtent[3]; + } + if (resultExtent[4] < wholeExtent[4]) + { + resultExtent[4] = wholeExtent[4]; + } + if (resultExtent[5] > wholeExtent[5]) + { + resultExtent[5] = wholeExtent[5]; + } + } + + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkExtentTranslator::SplitExtent(int piece, int numPieces, int *ext, + int splitMode) +{ + int numPiecesInFirstHalf; + unsigned long size[3]; + int splitAxis; + vtkLargeInteger mid; + + if (piece >= numPieces || piece < 0) + { + return 0; + } + + // keep splitting until we have only one piece. + // piece and numPieces will always be relative to the current ext. + while (numPieces > 1) + { + // Get the dimensions for each axis. + size[0] = ext[1]-ext[0]; + size[1] = ext[3]-ext[2]; + size[2] = ext[5]-ext[4]; + // choose what axis to split on based on the SplitMode + // if the user has requested x, y, or z slabs then try to + // honor that request. If that axis is already split as + // far as it can go, then drop to block mode. + if (splitMode < 3 && size[splitMode] > 1) + { + splitAxis = splitMode; + } + // otherwise use block mode + else + { + // choose the biggest axis + if (size[2] >= size[1] && size[2] >= size[0] && size[2]/2 >= 1) + { + splitAxis = 2; + } + else if (size[1] >= size[0] && size[1]/2 >= 1) + { + splitAxis = 1; + } + else if (size[0]/2 >= 1) + { + splitAxis = 0; + } + else + { + // signal no more splits possible + splitAxis = -1; + } + } + + if (splitAxis == -1) + { + // can not split any more. + if (piece == 0) + { + // just return the remaining piece + numPieces = 1; + } + else + { + // the rest must be empty + return 0; + } + } + else + { + // split the chosen axis into two pieces. + numPiecesInFirstHalf = (numPieces / 2); + mid = size[splitAxis]; + mid = (mid * numPiecesInFirstHalf) / numPieces + ext[splitAxis*2]; + if (piece < numPiecesInFirstHalf) + { + // piece is in the first half + // set extent to the first half of the previous value. + ext[splitAxis*2+1] = mid.CastToInt(); + // piece must adjust. + numPieces = numPiecesInFirstHalf; + } + else + { + // piece is in the second half. + // set the extent to be the second half. (two halves share points) + ext[splitAxis*2] = mid.CastToInt(); + // piece must adjust + numPieces = numPieces - numPiecesInFirstHalf; + piece -= numPiecesInFirstHalf; + } + } + } // end of while + + return 1; +} + + + +//---------------------------------------------------------------------------- +int vtkExtentTranslator::SplitExtentByPoints(int piece, int numPieces, + int *ext, int splitMode) +{ + int numPiecesInFirstHalf; + int size[3], splitAxis; + vtkLargeInteger mid; + + // keep splitting until we have only one piece. + // piece and numPieces will always be relative to the current ext. + while (numPieces > 1) + { + // Get the dimensions for each axis. + size[0] = ext[1]-ext[0] + 1; + size[1] = ext[3]-ext[2] + 1; + size[2] = ext[5]-ext[4] + 1; + // choose what axis to split on based on the SplitMode + // if the user has requested x, y, or z slabs then try to + // honor that request. If that axis is already split as + // far as it can go, then drop to block mode. + if (splitMode < 3 && size[splitMode] > 1) + { + splitAxis = splitMode; + } + // otherwise use block mode + else + { + if (size[2] >= size[1] && size[2] >= size[0] && size[2]/2 >= 1) + { + splitAxis = 2; + } + else if (size[1] >= size[0] && size[1]/2 >= 1) + { + splitAxis = 1; + } + else if (size[0]/2 >= 1) + { + splitAxis = 0; + } + else + { + // signal no more splits possible + splitAxis = -1; + } + } + + if (splitAxis == -1) + { + // can not split any more. + if (piece == 0) + { + // just return the remaining piece + numPieces = 1; + } + else + { + // the rest must be empty + return 0; + } + } + else + { + // split the chosen axis into two pieces. + numPiecesInFirstHalf = (numPieces / 2); + mid = size[splitAxis]; + mid = (mid * numPiecesInFirstHalf) / numPieces + ext[splitAxis*2]; + if (piece < numPiecesInFirstHalf) + { + // piece is in the first half + // set extent to the first half of the previous value. + ext[splitAxis*2+1] = mid.CastToInt() - 1; + // piece must adjust. + numPieces = numPiecesInFirstHalf; + } + else + { + // piece is in the second half. + // set the extent to be the second half. + ext[splitAxis*2] = mid.CastToInt(); + // piece must adjust + numPieces = numPieces - numPiecesInFirstHalf; + piece -= numPiecesInFirstHalf; + } + } + } // end of while + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkExtentTranslator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Piece: " << this->Piece << endl; + os << indent << "NumberOfPieces: " << this->NumberOfPieces << endl; + + os << indent << "GhostLevel: " << this->GhostLevel << endl; + + os << indent << "Extent: " << this->Extent[0] << ", " + << this->Extent[1] << ", " << this->Extent[2] << ", " + << this->Extent[3] << ", " << this->Extent[4] << ", " + << this->Extent[5] << endl; + + os << indent << "WholeExtent: " << this->WholeExtent[0] << ", " + << this->WholeExtent[1] << ", " << this->WholeExtent[2] << ", " + << this->WholeExtent[3] << ", " << this->WholeExtent[4] << ", " + << this->WholeExtent[5] << endl; + + os << indent << "SplitMode: "; + if (this->SplitMode == vtkExtentTranslator::BLOCK_MODE) + { + os << "Block\n"; + } + else if (this->SplitMode == vtkExtentTranslator::X_SLAB_MODE) + { + os << "X Slab\n"; + } + else if (this->SplitMode == vtkExtentTranslator::Y_SLAB_MODE) + { + os << "Y Slab\n"; + } + else if (this->SplitMode == vtkExtentTranslator::Z_SLAB_MODE) + { + os << "Z Slab\n"; + } + else + { + os << "Unknown\n"; + } +} + + + + + + + diff --git a/Common/vtkExtentTranslator.h b/Common/vtkExtentTranslator.h new file mode 100644 index 0000000..c51b5e0 --- /dev/null +++ b/Common/vtkExtentTranslator.h @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtentTranslator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtentTranslator - Generates a structured extent from unstructured. + +// .SECTION Description +// vtkExtentTranslator generates a structured extent from an unstructured +// extent. It uses a recursive scheme that splits the largest axis. A hard +// coded extent can be used for a starting point. + +// .SECTION Caveats +// This object is still under development. + +#ifndef __vtkExtentTranslator_h +#define __vtkExtentTranslator_h + +#include "vtkObject.h" + + +class VTK_COMMON_EXPORT vtkExtentTranslator : public vtkObject +{ +public: + static vtkExtentTranslator *New(); + + vtkTypeRevisionMacro(vtkExtentTranslator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the Piece/NumPieces. Set the WholeExtent and then call PieceToExtent. + // The result can be obtained from the Extent ivar. + vtkSetVector6Macro(WholeExtent, int); + vtkGetVector6Macro(WholeExtent, int); + vtkSetVector6Macro(Extent, int); + vtkGetVector6Macro(Extent, int); + vtkSetMacro(Piece,int); + vtkGetMacro(Piece,int); + vtkSetMacro(NumberOfPieces,int); + vtkGetMacro(NumberOfPieces,int); + vtkSetMacro(GhostLevel, int); + vtkGetMacro(GhostLevel, int); + + // Description: + // These are the main methods that should be called. These methods + // are responsible for converting a piece to an extent. The signatures + // without arguments are only thread safe when each thread accesses a + // different instance. The signatures with arguements are fully thread + // safe. + virtual int PieceToExtent(); + virtual int PieceToExtentByPoints(); + virtual int PieceToExtentThreadSafe(int piece, int numPieces, + int ghostLevel, int *wholeExtent, + int *resultExtent, int splitMode, + int byPoints); + + + + // Description: + // How should the streamer break up extents. Block mode + // tries to break an extent up into cube blocks. It always chooses + // the largest axis to split. + // Slab mode first breaks up the Z axis. If it gets to one slice, + // then it starts breaking up other axes. + void SetSplitModeToBlock() + {this->SplitMode = vtkExtentTranslator::BLOCK_MODE;} + void SetSplitModeToXSlab() + {this->SplitMode = vtkExtentTranslator::X_SLAB_MODE;} + void SetSplitModeToYSlab() + {this->SplitMode = vtkExtentTranslator::Y_SLAB_MODE;} + void SetSplitModeToZSlab() + {this->SplitMode = vtkExtentTranslator::Z_SLAB_MODE;} + vtkGetMacro(SplitMode,int); + +protected: + vtkExtentTranslator(); + ~vtkExtentTranslator(); + + // Description: + // Returns 0 if no data exist for a piece. + // The whole extent Should be passed in as the extent. + // It is modified to return the result. + int SplitExtent(int piece, int numPieces, int *extent, int splitMode); + int SplitExtentByPoints(int piece, int numPieces, int *extent, + int splitMode); + + int Piece; + int NumberOfPieces; + int GhostLevel; + int Extent[6]; + int WholeExtent[6]; + int SplitMode; + +//BTX + // Don't change the numbers here - they are used in the code + // to indicate array indices. + enum Modes { + X_SLAB_MODE=0, + Y_SLAB_MODE=1, + Z_SLAB_MODE=2, + BLOCK_MODE= 3 + }; +//ETX + +private: + vtkExtentTranslator(const vtkExtentTranslator&); // Not implemented. + void operator=(const vtkExtentTranslator&); // Not implemented. +}; + +#endif + diff --git a/Common/vtkFastNumericConversion.cxx b/Common/vtkFastNumericConversion.cxx new file mode 100644 index 0000000..7aa86b9 --- /dev/null +++ b/Common/vtkFastNumericConversion.cxx @@ -0,0 +1,211 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFastNumericConversion.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFastNumericConversion - Enables fast conversion of floating point to fixed point +// .SECTION Description +// vtkFastNumericConversion uses a portable (assuming IEEE format) method for converting single and +// double precision floating point values to a fixed point representation. This allows fast +// integer flooring on platforms, such as Intel X86, in which CPU floating point flooring +// algorithms are very slow. It is based on the techniques described in Chris Hecker's article, +// "Let's Get to the (Floating) Point", in Game Developer Magazine, Feb/Mar 1996, and the +// techniques described in Michael Herf's website, http://www.stereopsis.com/FPU.html. +// The Hecker article can be found at http://www.d6.com/users/checker/pdfs/gdmfp.pdf. +// Unfortunately, each of these techniques is incomplete, and doesn't floor properly, +// in a way that depends on how many bits are reserved for fixed point fractional use, due to +// failing to properly account for the default round-towards-even rounding mode of the X86. Thus, +// my implementation incorporates some rounding correction that undoes the rounding that the +// FPU performs during denormalization of the floating point value. Note that +// the rounding affect I'm talking about here is not the effect on the fistp instruction, +// but rather the effect that occurs during the denormalization of a value that occurs when +// adding it to a much larger value. The bits must be shifted to the right, and when a "1" bit +// falls off the edge, the rounding mode determines what happens next, in order +// to avoid completely "losing" the 1-bit. Furthermore, my implementation works on Linux, where the +// default precision mode is 64-bit extended precision. + +// This class is contributed to VTK by Chris Volpe of Applied Research Associates, Inc. +// (My employer requires me to say that -- CRV) + + +#include "vtkFastNumericConversion.h" +#include "vtkObjectFactory.h" +#include "vtkTimerLog.h" + +vtkCxxRevisionMacro(vtkFastNumericConversion, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkFastNumericConversion); + +int vtkFastNumericConversion::TestQuickFloor(double val) + { + return vtkFastNumericConversion::QuickFloor(val); + } + +int vtkFastNumericConversion::TestSafeFloor(double val) + { + return vtkFastNumericConversion::SafeFloor(val); + } + +int vtkFastNumericConversion::TestRound(double val) + { + return vtkFastNumericConversion::Round(val); + } + +int vtkFastNumericConversion::TestConvertFixedPointIntPart(double val) + { + int frac; + return this->ConvertFixedPoint(val, frac); + } + +int vtkFastNumericConversion::TestConvertFixedPointFracPart(double val) + { + int frac; + this->ConvertFixedPoint(val, frac); + return frac; + } + +void vtkFastNumericConversion::InternalRebuild() + { + int i; + this->fixRound=.5; + for (i=this->internalReservedFracBits; i; i--) + { + this->fixRound *= .5; + } + this->fracMask = (1<internalReservedFracBits)-1; + this->fpDenormalizer = (((unsigned long)1) << (52-30-this->internalReservedFracBits)) * + this->two30() * this->BorrowBit(); + this->epTempDenormalizer = this->fpDenormalizer * (((unsigned long)1) << (63-52)); + } + + +void vtkFastNumericConversion::PrintSelf(ostream &os, vtkIndent indent) + { + os << indent << "ReservedFracBits: " << this->internalReservedFracBits << endl; + os << indent << "Bare time from last PerformanceTest() call: " << this->bare_time << endl; + os << indent << "Cast time from last PerformanceTest() call: " << this->cast_time << endl; + os << indent << "ConvertFixedPoint time from last PerformanceTest() call: " << this->convert_time << endl; + os << indent << "QuickFloor time from last PerformanceTest() call: " << this->quickfloor_time << endl; + os << indent << "SafeFloor time from last PerformanceTest() call: " << this->safefloor_time << endl; + os << indent << "Round time from last PerformanceTest() call: " << this->round_time << endl; + if (this->bare_time != 0.0) + { + // Don't do this if we haven't run the tests yet. + os << indent << "Speedup ratio from cast to quickfloor is: " << + (this->cast_time-this->bare_time)/(this->quickfloor_time-this->bare_time) << endl; + os << indent << "Speedup ratio from cast to safefloor is: " << + (this->cast_time-this->bare_time)/(this->safefloor_time-this->bare_time) << endl; + os << indent << "Speedup ratio from cast to round is: " << + (this->cast_time-this->bare_time)/(this->round_time-this->bare_time) << endl; + } + } + + +void vtkFastNumericConversion::PerformanceTests(void) + { + const int inner_count = 10000; + const int outer_count = 10000; + double *dval = new double[inner_count]; + int *ival = new int[inner_count]; + int *frac = new int[inner_count]; + + + int i,o; + vtkTimerLog *timer = vtkTimerLog::New(); + + for (i=0; iStartTimer(); + for (o=0; oStopTimer(); + this->bare_time = timer->GetElapsedTime(); + + + // Compute cast time + timer->StartTimer(); + for (o=0; oStopTimer(); + this->cast_time = timer->GetElapsedTime(); + + + // Compute convert time + timer->StartTimer(); + for (o=0; oConvertFixedPoint(dval[i], frac[i]); + } + } + timer->StopTimer(); + this->convert_time = timer->GetElapsedTime(); + + // Compute quickfloor time + timer->StartTimer(); + for (o=0; oStopTimer(); + this->quickfloor_time = timer->GetElapsedTime(); + + // Compute safefloor time + timer->StartTimer(); + for (o=0; oStopTimer(); + this->safefloor_time = timer->GetElapsedTime(); + + // Compute round time + timer->StartTimer(); + for (o=0; oStopTimer(); + this->round_time = timer->GetElapsedTime(); + + + + delete [] dval; + delete [] ival; + delete [] frac; + + timer->Delete(); + } diff --git a/Common/vtkFastNumericConversion.h b/Common/vtkFastNumericConversion.h new file mode 100644 index 0000000..bc21789 --- /dev/null +++ b/Common/vtkFastNumericConversion.h @@ -0,0 +1,461 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFastNumericConversion.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFastNumericConversion - Enables fast conversion of floating point to fixed point +// .SECTION Description +// vtkFastNumericConversion uses a portable (assuming IEEE format) method for +// converting single and double precision floating point values to a fixed +// point representation. This allows fast integer floor operations on +// platforms, such as Intel X86, in which CPU floating point conversion +// algorithms are very slow. It is based on the techniques described in Chris +// Hecker's article, "Let's Get to the (Floating) Point", in Game Developer +// Magazine, Feb/Mar 1996, and the techniques described in Michael Herf's +// website, http://www.stereopsis.com/FPU.html. The Hecker article can be +// found at http://www.d6.com/users/checker/pdfs/gdmfp.pdf. Unfortunately, +// each of these techniques is incomplete, and doesn't convert properly, in a +// way that depends on how many bits are reserved for fixed point fractional +// use, due to failing to properly account for the default round-towards-even +// rounding mode of the X86. Thus, my implementation incorporates some +// rounding correction that undoes the rounding that the FPU performs during +// denormalization of the floating point value. Note that the rounding affect +// I'm talking about here is not the effect on the fistp instruction, but +// rather the effect that occurs during the denormalization of a value that +// occurs when adding it to a much larger value. The bits must be shifted to +// the right, and when a "1" bit falls off the edge, the rounding mode +// determines what happens next, in order to avoid completely "losing" the +// 1-bit. Furthermore, my implementation works on Linux, where the default +// precision mode is 64-bit extended precision. + +// This class is contributed to VTK by Chris Volpe of Applied Research +// Associates, Inc. (My employer requires me to say that -- CRV) + +// This code assumes that the FPU is in round-to-nearest mode. It assumes, on +// Linux, that the default extended precision mode is in effect, and it +// assumes, on Windows, that the default double precision mode is in effect. + +#ifndef __vtkFastNumericConversion_h +#define __vtkFastNumericConversion_h + +#include "vtkObject.h" + +// Use the bit-representation trick only on X86, and only when producing +// optimized code +#if defined(NDEBUG) && (defined i386 || defined _M_IX86) +#define VTK_USE_TRICK +#endif + +// Linux puts the FPU in extended precision. Windows and FreeBSD keep it in +// double precision. If other operating systems for i386 (Solaris?) behave +// like Linux, add them below. Special care needs to be taken when dealing +// with extended precision mode because even though we are eventually writing +// out to a double-precision variable to capture the fixed-point or integer +// results, the extra bits maintained in the internal computations disrupt +// the bit-playing that we're doing here. +#if defined(__linux__) +#define VTK_EXT_PREC +#endif + +//#define VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS +#ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS +#define VTK_EXT_PREC +#endif + + +class VTK_COMMON_EXPORT vtkFastNumericConversion : public vtkObject +{ +public: + static vtkFastNumericConversion *New(); + vtkTypeRevisionMacro(vtkFastNumericConversion, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Wrappable method for script-testing of correct cross-platform + // functionality + int TestQuickFloor(double val); + + // Description: + // Wrappable method for script-testing of correct cross-platform + // functionality + int TestSafeFloor(double val); + + // Description: + // Wrappable method for script-testing of correct cross-platform + // functionality + int TestRound(double val); + + // Description: + // Wrappable method for script-testing of correct cross-platform + // functionality + int TestConvertFixedPointIntPart(double val); + + // Description: + // Wrappable method for script-testing of correct cross-platform + // functionality + int TestConvertFixedPointFracPart(double val); + +protected: + //BTX + // Description: + // Internal use: multiply the denormalizer value by 1.5 to ensure that it + // has a "1" bit, other than the implicit initial "1" bit, from which to + // borrow when adding (flooring) a negative number, so that we don't borrow + // from the implicit "1" bit, which would cause partial re-normalization, + // resulting in a shift of our integer bits. + static inline double BorrowBit() { return 1.5;}; + + // Description: + // Represent 2^30 as a double precision float. Use as a stepping + // stone for computing 2^52 as a double, since we can't represent 2^52 as an + // int before converting to double. + static inline double two30() { return (double)(((unsigned long)1) << 30); }; + + // Description: + // Represent 2^52 as a double precision float. This value is + // significant because doubles have 52 bits of precision in the mantissa + static inline double two52() + { return (((unsigned long)1) << (52-30)) * two30(); }; + + // Description: + // Represent 2^51 as a double precision float. This value is significant + // because doubles have 52 (explicit) bits of precision in the mantissa, + // but we're going to pretend we only have 51 to play with when using safe + // floor, since the default round-to-even on an X86 mucks with the LSB + // during the denormalizing shift. + static inline double two51() + { return (((unsigned long)1) << (51-30)) * two30(); }; + + // Description: + // Represent 2^63 as a double precision float. We need this value to shift + // unwanted fractional bits off the end of an extended precision value + static inline double two63() + { return (((unsigned long)1) << (63-60)) * two30() * two30();}; + + // Description: + // Represent 2^62 as a double precision float. We need this value to shift + // unwanted fractional bits off the end of an extended precision value. Use + // when we're doing a SafeFloor. + static inline double two62() + { return (((unsigned long)1) << (62-60)) * two30() * two30();}; + + // Define number of bits of precision for various data types. + // Note: INT_BITS is really 31, (rather than 32, since one of the bits is + // just used for the two's-complement sign), but we say 30 because we don't + // need to be able to handle 31-bit magnitudes correctly. I say that + // because this is used for the QuickFloor code, and the SafeFloor code + // retains an extra bit of fixed point precision which it shifts-out at the + // end, thus reducing the magnitude of integers that it can handle. That's + // an inherent limitation of using SafeFloor to prevent round-ups under any + // circumstances, and there's no need to make QuickFloor handle a wider + // range of numbers than SafeFloor. +#define INT_BITS 30 +#define EXT_BITS 64 +#define DBL_BITS 53 + + // Description: + // Small amount to use as a rounding tie-breaker to prevent + // round-to-nearest-and-even mode from flooring-down odd numbered + // integers. But number to nudge by depends on number of bits mantissa in + // our floating point representation minus number of mantissa bits in the + // range of signed ints we need to handle. In order to ensure that + // flooring-down doesn't happen even for very large odd-integer values, the + // number of bits used to represent the tie-breaker (i.e. to the right of + // the binary-point), plus the number of bits needed to represent the + // integer (to the left of the binary point), can not exceeds the number of + // bits in the current precision mode. Thus, in selecting the tie-breaker + // value, we select the largest number of bits to the right of the binary + // point as possible while still maintining that inequality. Thus, extended + // precision mode allows a larger number of bits to the right of the binary + // point. This, in turn, implies a smaller value of the tie-breaker. And a + // smaller tie-breaker will impose a tighter window on the range of values + // that are erroneously rounded-up by a floor operation. Under double + // precision, a QuickFloor of 0.9999998 (six 9's and an 8) correctly yields + // 0. A value must be very close to 1.0, in fact, at least as close as + // 0.9999999 (seven 9's)in order for the tie-breaker to bump it up to 1. + // Under extended precision, an even smaller tie-breaker can be used. In + // this mode, a QuickFloor of 0.9999999999 (ten 9's) correctly yields 0. A + // QuickFloor of 0.99999999999 (eleven 9's) gets rounded up to 1. Since + // these spurious round-ups occur only when the given value is virtually + // indistinguishable from the next higher integer, the results should be + // acceptable in most situations where performance is of the essence. + // Make this public so that clients can account for the RoundingTieBreaker + // if necessary +public: +#ifdef VTK_EXT_PREC + // Compute (0.5 ^ (EXT_BITS-INT_BITS)) as a compile-time constant + static inline double RoundingTieBreaker() {return 1.0 / (two30() * (((unsigned long)1) << (EXT_BITS - INT_BITS - 30))); }; +#else + // Compute (0.5 ^ (DBL_BITS-INT_BITS)) as a compile-time constant + static inline double RoundingTieBreaker() { return 1.0 / (((unsigned long)1) << (DBL_BITS - INT_BITS)); }; +#endif + +protected: + // Description: + // This is the magic floating point value which when added to any other + // floating point value, causes the rounded integer portion of that + // floating point value to appear in the least significant bits of the + // mantissa, which is what we want. + static inline double QuickFloorDenormalizer() + {return two52() * BorrowBit(); }; + + // Description: + // This is the magic floating point value which when added to any other + // floating point value, causes the rounded integer portion of that + // floating point value to appear in the NEXT TO least significant bits of + // the mantissa, which is what we want. This allows the CPU rounding mode + // to muck with the LSB which we can then discard in SafeFloor + static inline double SafeFloorDenormalizer() + { return two51() * BorrowBit(); }; + + // Description: + // This value is added to and then subtracted from an extended precision + // value in order to clear the fractional bits so that they do not + // adversely affect the final double-precision result. + static inline double QuickExtPrecTempDenormalizer() + {return two63() * BorrowBit(); }; + + // Description: + // Just like QuickExtPrecTempDenormalizer(), but preserves one extra bit of + // fixed point precision to guard against the CPU mucking with the LSB + static inline double SafeExtPrecTempDenormalizer() + {return two62() * BorrowBit(); }; + + static inline double QuickRoundAdjust() {return 0.5;}; + static inline double SafeRoundAdjust() {return 0.25;}; + static inline int SafeFinalShift() {return 1;}; + + +#ifdef VTK_WORDS_BIGENDIAN + enum {exponent_pos = 0, mantissa_pos = 1}; +#else + enum {exponent_pos = 1, mantissa_pos = 0}; +#endif + //ETX + +public: + + // Description: + // Set the number of bits reserved for fractional precision that are + // maintained as part of the flooring process. This number affects the + // flooring arithmetic. It may be useful if the factional part is to be + // used to index into a lookup table of some sort. However, if you are only + // interested in knowing the fractional remainder after flooring, there + // doesn't appear to be any advantage to using these bits, either in terms + // of a lookup table, or by directly multiplying by some unit fraction, + // over simply subtracting the floored value from the original value. Note + // that since only 32 bits are used for the entire fixed point + // representation, increasing the number of reserved fractional bits + // reduces the range of integer values that can be floored to. + void SetReservedFracBits(int bits) + { + // Add one to the requested number of fractional bits, to make + // the conversion safe with respect to rounding mode. This is the + // same as the difference between QuickFloor and SafeFloor. + bits++; + unsigned long mtime = this->GetMTime(); + this->SetinternalReservedFracBits(bits); + if (mtime != this->GetMTime()) + { + this->InternalRebuild(); + } + }; + + // Description: + // Conduct timing tests so that the usefulness of this class can be + // ascertained on whatever platform it is being used. Output can be + // retrieved via Print method. + void PerformanceTests(void); + + //BTX + // Description: + // Perform a quick flooring of the double-precision floating point + // value. The result is sometimes incorrect, but in a way that makes it + // acceptable for most uses. The naive way to implement floor(), given that + // the x86 FPU does round() by default, is to define floor(x) as + // round(x-.5). This would work fine except for the fact that the x86 FPU + // breaks rounding ties by selecting the even number. Thus, floor(4.0) = + // round(3.5) = 4, but floor(3.0) = round(2.5) = 2. As a result, + // subtracting .5 gives the wrong answer for odd integers. So, let's + // subtract just a TEENSY bit less than .5, to swing the odd-integer + // results up to their corect value. How teensy? Well, if it's too teensy, + // it will be insignificant compared to 0.5, and will become equivalent to + // 0.5. And if it's not teensy enough, we'll overshoot, causing results + // like floor(N-epsilon)==N, for some epsilon. Furthermore, the "too + // teensy" problem is exacerbated when trying to floor larger numbers, due + // to limitations of the representation's dynamic range. See the definition + // of RoundingTieBreaker() for details. + inline static int QuickFloor(const double &val) + { +#ifdef VTK_USE_TRICK + union { int i[2]; double d; } u; +#ifdef VTK_EXT_PREC + u.d = (((val - (QuickRoundAdjust() - RoundingTieBreaker())) + // Push off those extended precision bits + + QuickExtPrecTempDenormalizer()) + // Pull back the wanted bits into double range + - QuickExtPrecTempDenormalizer()) + + QuickFloorDenormalizer(); +#else // ! VTK_EXT_PREC + u.d = (val - (QuickRoundAdjust() - RoundingTieBreaker())) + + QuickFloorDenormalizer(); +#endif // VTK_EXT_PREC + return u.i[mantissa_pos]; +#else // ! VTK_USE_TRICK + return (int) val; +#endif // VTK_USE_TRICK + } + + // Description: + // Perform a SAFE flooring. Similar to QuickFloor, but modified to return + // the correct result always. Use this when it absolutely positively needs + // to be the correct answer all the time, and considering 0.9999999 as + // being equal to 1.0 is simply not acceptable. It works similarly to + // QuickFloor, but it retains one extra bit of fixed point precision in the + // conversion process, so that the problem with QuickFloor affects only an + // unneeded bit, and then it ditches that bit from the resulting integer + // with a right-shift. In other words, it rounds to the nearest one-half, + // choosing the EVEN one-half (i.e. the integer) as a tie-breaker, and then + // shifting off that half-integer bit. As a result of maintaining one extra + // bit of fixed point precision in the intermediate calculation, the range + // of integers supported is reduced by one bit. Plus, it takes a little + // longer to execute, due to the final bit shift. + inline static int SafeFloor(const double &val) + { +#ifdef VTK_USE_TRICK + union { int i[2]; double d; } u; +#ifdef VTK_EXT_PREC + u.d = (((val - SafeRoundAdjust()) + + SafeExtPrecTempDenormalizer()) + - SafeExtPrecTempDenormalizer()) + + SafeFloorDenormalizer(); +#else // ! VTK_EXT_PREC + u.d = (val - SafeRoundAdjust()) + + SafeFloorDenormalizer(); +#endif // VTK_EXT_PREC + return u.i[mantissa_pos] >> SafeFinalShift(); +#else // ! VTK_USE_TRICK + return (int) val; +#endif // VTK_USE_TRICK + } + + // Description: + // Round to nearest int. This is pretty sweet in the default + // round-to-nearest FPU mode, since it is generally immaterial how ties are + // broken when rounding. I.e., either "2" or "3" are acceptable results for + // "Round(2.5)", but only one of them (the one naively not chosen without + // jumping through the hoops in QuickFloor and SafeFloor) is the acceptable + // result for the analogous "Floor(3)". Therefore, we don't need to worry + // at all about adding a teensy but not too teensy tie breaker, or shifting + // off a half-integer bit. This makes it exceptionally fast. + inline static int Round(const double &val) + { +#ifdef VTK_USE_TRICK + union { int i[2]; double d; } u; +#ifdef VTK_EXT_PREC + u.d = ((val + + QuickExtPrecTempDenormalizer()) + - QuickExtPrecTempDenormalizer()) + + QuickFloorDenormalizer(); +#else // ! VTK_EXT_PREC + u.d = val + + QuickFloorDenormalizer(); +#endif // VTK_EXT_PREC + return u.i[mantissa_pos]; +#else // ! VTK_USE_TRICK + if (val>=0) + { + return (int) (val + 0.5); + } + else + { + return (int) (val - 0.5); + } +#endif // VTK_USE_TRICK + } + + // Description: + // Convert the value to a fixed point representation, returning the + // integer portion as function value, and returning the fractional + // part in the second parameter. + inline int ConvertFixedPoint(const double &val, int &fracPart) + { + union { int i[2]; double d; } u; +#ifdef VTK_EXT_PREC + u.d = (((val - fixRound) + + this->epTempDenormalizer) + - this->epTempDenormalizer) + + this->fpDenormalizer; +#else // ! VTK_EXT_PREC + u.d = (val - fixRound) + + this->fpDenormalizer; +#endif // VTK_EXT_PREC + fracPart = (u.i[mantissa_pos] & fracMask) >> 1; + return u.i[mantissa_pos] >> this->internalReservedFracBits; + } + //ETX + + +protected: + //BTX + vtkFastNumericConversion() + { +#ifdef VTK_TEST_HACK_TO_EMULATE_LINUX_UNDER_WINDOWS + _controlfp( _PC_64, MCW_PC ); +#endif + + this->fixRound = 0; + this->internalReservedFracBits = 0; + this->fracMask = 0; + this->fpDenormalizer = 0; + this->bare_time = 0; + this->cast_time = 0; + this->convert_time = 0; + this->quickfloor_time = 0; + this->safefloor_time = 0; + this->round_time = 0; + this->InternalRebuild(); + }; + ~vtkFastNumericConversion() {}; + void InternalRebuild(void); + +private: + vtkSetMacro(internalReservedFracBits, int); + vtkGetMacro(internalReservedFracBits, int); + int internalReservedFracBits; + int fracMask; + + // Used when doing fixed point conversions with a certain number of bits + // remaining for the fractional part, as opposed to the pure integer + // flooring + double fpDenormalizer; + + // Used when doing fixed point conversions in extended precision mode + double epTempDenormalizer; + + // Adjustment for rounding based on the number of bits reserved for + // fractional representation + double fixRound; + + double bare_time; + double cast_time; + double convert_time; + double quickfloor_time; + double safefloor_time; + double round_time; + //ETX + + vtkFastNumericConversion(const vtkFastNumericConversion&); // Not implemented + void operator=(const vtkFastNumericConversion&); // Not implemented +}; + +#endif diff --git a/Common/vtkFileOutputWindow.cxx b/Common/vtkFileOutputWindow.cxx new file mode 100644 index 0000000..414e453 --- /dev/null +++ b/Common/vtkFileOutputWindow.cxx @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFileOutputWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFileOutputWindow.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkFileOutputWindow, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkFileOutputWindow); + +vtkFileOutputWindow::vtkFileOutputWindow() +{ + this->OStream = NULL; + this->FileName = NULL; + this->Append = 0; + this->Flush = 0; +} + +vtkFileOutputWindow::~vtkFileOutputWindow() +{ + if (this->FileName) + { + delete[] this->FileName; + } + if (this->OStream) + { + delete this->OStream; + } +} + +void vtkFileOutputWindow::Initialize() +{ + if (!this->OStream) + { + if (!this->FileName) + { + char* fileName = (char *) "vtkMessageLog.log"; + this->FileName = new char[strlen(fileName)+1]; + strcpy(this->FileName, fileName); + } + if (this->Append) + { + this->OStream = new ofstream(this->FileName, ios::app); + } + else + { + this->OStream = new ofstream(this->FileName); + } + } +} + +void vtkFileOutputWindow::DisplayText(const char* text) +{ + if(!text) + { + return; + } + + if (!this->OStream) + { + this->Initialize(); + } + *this->OStream << text << endl; + + if (this->Flush) + { + this->OStream->flush(); + } +} + +void vtkFileOutputWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "OStream: " << this->OStream << endl; + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "Append: " << (this->Append ? "On" : "Off") << endl; + os << indent << "Flush: " << (this->Flush ? "On" : "Off") << endl; +} diff --git a/Common/vtkFileOutputWindow.h b/Common/vtkFileOutputWindow.h new file mode 100644 index 0000000..bb31396 --- /dev/null +++ b/Common/vtkFileOutputWindow.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFileOutputWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFileOutputWindow - File Specific output window class +// .SECTION Description +// Writes debug/warning/error output to a log file instead of the console. +// To use this class, instantiate it and then call SetInstance(this). +// + +#ifndef __vtkFileOutputWindow_h +#define __vtkFileOutputWindow_h + +#include "vtkOutputWindow.h" + + +class VTK_COMMON_EXPORT vtkFileOutputWindow : public vtkOutputWindow +{ +public: + vtkTypeRevisionMacro(vtkFileOutputWindow, vtkOutputWindow); + + static vtkFileOutputWindow* New(); + + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: Put the text into the log file + // New lines are converted to carriage return new lines. + virtual void DisplayText(const char*); + + // Description: Sets the name for the log file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: Turns on buffer flushing for the output + // to the log file. + vtkSetMacro(Flush, int); + vtkGetMacro(Flush, int); + vtkBooleanMacro(Flush, int); + + // Description: Setting append will cause the log file to be + // opened in append mode. Otherwise, if the log file exists, + // it will be overwritten each time the vtkFileOutputWindow + // is created. + vtkSetMacro(Append, int); + vtkGetMacro(Append, int); + vtkBooleanMacro(Append, int); + + protected: + vtkFileOutputWindow(); + virtual ~vtkFileOutputWindow(); + void Initialize(); + char* FileName; + ofstream* OStream; + int Flush; + int Append; +private: + vtkFileOutputWindow(const vtkFileOutputWindow&); // Not implemented. + void operator=(const vtkFileOutputWindow&); // Not implemented. +}; + + + +#endif diff --git a/Common/vtkFloatArray.cxx b/Common/vtkFloatArray.cxx new file mode 100644 index 0000000..dd57dac --- /dev/null +++ b/Common/vtkFloatArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFloatArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(float); + +#define __vtkFloatArray_cxx +#include "vtkFloatArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkFloatArray, "$Revision: 1.58 $"); +vtkStandardNewMacro(vtkFloatArray); + +//---------------------------------------------------------------------------- +vtkFloatArray::vtkFloatArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkFloatArray::~vtkFloatArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkFloatArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkFloatArray.h b/Common/vtkFloatArray.h new file mode 100644 index 0000000..be8cab1 --- /dev/null +++ b/Common/vtkFloatArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFloatArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFloatArray - dynamic, self-adjusting array of float +// .SECTION Description +// vtkFloatArray is an array of values of type float. It provides +// methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkFloatArray_h +#define __vtkFloatArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkFloatArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE float +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkFloatArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkFloatArray* New(); + vtkTypeRevisionMacro(vtkFloatArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_FLOAT; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, float* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const float* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const float* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const float* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + float GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, float value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, float f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(float f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + float* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + float* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(float* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkFloatArray(vtkIdType numComp=1); + ~vtkFloatArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkFloatArray(const vtkFloatArray&); // Not implemented. + void operator=(const vtkFloatArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkFunctionParser.cxx b/Common/vtkFunctionParser.cxx new file mode 100644 index 0000000..82955cb --- /dev/null +++ b/Common/vtkFunctionParser.cxx @@ -0,0 +1,1995 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFunctionParser.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFunctionParser.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkFunctionParser, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkFunctionParser); + +static double vtkParserVectorErrorResult[3] = { VTK_PARSER_ERROR_RESULT, + VTK_PARSER_ERROR_RESULT, + VTK_PARSER_ERROR_RESULT }; + +vtkFunctionParser::vtkFunctionParser() +{ + this->NumberOfScalarVariables = 0; + this->NumberOfVectorVariables = 0; + this->ScalarVariableNames = NULL; + this->VectorVariableNames = NULL; + this->ScalarVariableValues = NULL; + this->VectorVariableValues = NULL; + this->Function = NULL; + this->ByteCode = NULL; + this->ByteCodeSize = 0; + this->Immediates = NULL; + this->ImmediatesSize = 0; + this->Stack = NULL; + this->StackSize = 0; + this->StackPointer = 0; + + this->EvaluateMTime.Modified(); + this->VariableMTime.Modified(); + this->ParseMTime.Modified(); + this->FunctionMTime.Modified(); + + this->ReplaceInvalidValues = 0; + this->ReplacementValue = 0.0; +} + +vtkFunctionParser::~vtkFunctionParser() +{ + int i; + + if (this->ScalarVariableNames) + { + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + delete [] this->ScalarVariableNames[i]; + this->ScalarVariableNames[i] = NULL; + } + delete [] this->ScalarVariableNames; + this->ScalarVariableNames = NULL; + } + + if (this->VectorVariableNames) + { + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + delete [] this->VectorVariableNames[i]; + this->VectorVariableNames[i] = NULL; + } + delete [] this->VectorVariableNames; + this->VectorVariableNames = NULL; + } + + if (this->ScalarVariableValues) + { + delete [] this->ScalarVariableValues; + this->ScalarVariableValues = NULL; + } + + if (this->VectorVariableValues) + { + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + delete [] this->VectorVariableValues[i]; + this->VectorVariableValues[i] = NULL; + } + delete [] this->VectorVariableValues; + this->VectorVariableValues = NULL; + } + + if (this->Function) + { + delete [] this->Function; + this->Function = NULL; + } + + if (this->ByteCode) + { + delete [] this->ByteCode; + this->ByteCode = NULL; + } + + if (this->Immediates) + { + delete [] this->Immediates; + this->Immediates = NULL; + } + + if (this->Stack) + { + delete [] this->Stack; + this->Stack = NULL; + } +} + +void vtkFunctionParser::SetFunction(const char *function) +{ + if (this->Function && function && strcmp(this->Function,function) == 0) + { + return; + } + + if (this->Function) + { + delete [] this->Function; + } + + if (function) + { + this->Function = new char[strlen(function)+1]; + strcpy(this->Function,function); + } + else + { + this->Function = NULL; + } + + this->FunctionMTime.Modified(); + this->Modified(); +} + +int vtkFunctionParser::Parse() +{ + int result; + int i; + + if (this->Function == NULL) + { + vtkErrorMacro("Parse: no function has been set"); + return 0; + } + + this->RemoveSpaces(); + + result = this->CheckSyntax(); + if (!result) + { + return 0; + } + + result = this->BuildInternalFunctionStructure(); + if (!result) + { + vtkErrorMacro("Parse: Error creating internal structure for parse string"); + return 0; + } + + // need to make sure that the ambiguous operators are correct + // - scalar/vector + + // - scalar/vector - + // - scalar/vector unary minus + // - * (2 scalars) or scalar multiple (scalar, vector) + result = this->DisambiguateOperators(); + if (!result) + { + vtkErrorMacro("Parse: Error deciding between ambiguous operators"); + return 0; + } + + // need to recalculate stack size based on number of vector variables + // in byte code + for (i = 0; i < this->ByteCodeSize; i++) + { + if ((this->ByteCode[i] >= VTK_PARSER_BEGIN_VARIABLES + + this->NumberOfScalarVariables) || + (this->ByteCode[i] == VTK_PARSER_IHAT) || + (this->ByteCode[i] == VTK_PARSER_JHAT) || + (this->ByteCode[i] == VTK_PARSER_KHAT)) + { + this->StackSize += 2; + } + } + + if (this->StackSize) + { + this->Stack = new double[this->StackSize]; + if (!this->Stack) + { + vtkErrorMacro("Parse: Out of memory"); + return 0; + } + } + + this->ParseMTime.Modified(); + return 1; +} + +int vtkFunctionParser::DisambiguateOperators() +{ + unsigned char* tempStack = new unsigned char[this->ByteCodeSize]; + int i; + int tempStackPtr = -1; + + // using 0 for scalars and 1 for vectors + for (i = 0; i < this->ByteCodeSize; i++) + { + switch (this->ByteCode[i]) + { + case VTK_PARSER_IMMEDIATE: + tempStackPtr++; + tempStack[tempStackPtr] = 0; + break; + case VTK_PARSER_UNARY_MINUS: + if (tempStack[tempStackPtr] != 0) + { + this->ByteCode[i] = VTK_PARSER_VECTOR_UNARY_MINUS; + } + break; + case VTK_PARSER_ADD: + if (tempStack[tempStackPtr] != 0 && tempStack[tempStackPtr-1] != 0) + { + this->ByteCode[i] = VTK_PARSER_VECTOR_ADD; + } + else if ((tempStack[tempStackPtr] == 0 && + tempStack[tempStackPtr-1] != 0) || + (tempStack[tempStackPtr] != 0 && + tempStack[tempStackPtr-1] == 0)) + { + vtkErrorMacro("addition expects either 2 vectors or 2 scalars"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_SUBTRACT: + if (tempStack[tempStackPtr] != 0 && tempStack[tempStackPtr-1] != 0) + { + this->ByteCode[i] = VTK_PARSER_VECTOR_SUBTRACT; + } + else if ((tempStack[tempStackPtr] == 0 && + tempStack[tempStackPtr-1] != 0) || + (tempStack[tempStackPtr] != 0 && + tempStack[tempStackPtr-1] == 0)) + { + vtkErrorMacro("addition expects either 2 vectors or 2 scalars"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_MULTIPLY: + if (tempStack[tempStackPtr-1] == 0 && tempStack[tempStackPtr] == 1) + { + this->ByteCode[i] = VTK_PARSER_SCALAR_TIMES_VECTOR; + tempStack[tempStackPtr-1] = 1; + } + else if (tempStack[tempStackPtr-1] == 1 && + tempStack[tempStackPtr] == 0) + { + this->ByteCode[i] = VTK_PARSER_VECTOR_TIMES_SCALAR; + tempStack[tempStackPtr-1] = 1; + } + else if (tempStack[tempStackPtr] == 1) + { + vtkErrorMacro("expecting either 2 scalars or a scalar and" + << " a vector"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_DIVIDE: + if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1) + { + vtkErrorMacro("can't divide vectors"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_POWER: + if (tempStack[tempStackPtr] == 1) + { + vtkErrorMacro("can't raise a vector to a power"); + return 0; + } + case VTK_PARSER_ABSOLUTE_VALUE: + case VTK_PARSER_EXPONENT: + case VTK_PARSER_CEILING: + case VTK_PARSER_FLOOR: + case VTK_PARSER_LOGARITHM: + case VTK_PARSER_LOGARITHME: + case VTK_PARSER_LOGARITHM10: + case VTK_PARSER_SQUARE_ROOT: + case VTK_PARSER_SINE: + case VTK_PARSER_COSINE: + case VTK_PARSER_TANGENT: + case VTK_PARSER_ARCSINE: + case VTK_PARSER_ARCCOSINE: + case VTK_PARSER_ARCTANGENT: + case VTK_PARSER_HYPERBOLIC_SINE: + case VTK_PARSER_HYPERBOLIC_COSINE: + case VTK_PARSER_HYPERBOLIC_TANGENT: + case VTK_PARSER_SIGN: + if (tempStack[tempStackPtr] == 1) + { + vtkErrorMacro("expecting a scalar, but got a vector"); + return 0; + } + break; + case VTK_PARSER_MIN: + if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1) + { + vtkErrorMacro("can't apply min to vectors"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_MAX: + if (tempStack[tempStackPtr] == 1 || tempStack[tempStackPtr-1] == 1) + { + vtkErrorMacro("can't apply max to vectors"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_VECTOR_UNARY_MINUS: + if (tempStack[tempStackPtr] == 0) + { + this->ByteCode[i] = VTK_PARSER_UNARY_MINUS; + } + break; + case VTK_PARSER_DOT_PRODUCT: + if (tempStack[tempStackPtr] == 0 || tempStack[tempStackPtr-1] == 0) + { + vtkErrorMacro("dot product does not operate on scalars"); + return 0; + } + tempStack[tempStackPtr-1] = 0; + tempStackPtr--; + break; + case VTK_PARSER_VECTOR_ADD: + if (tempStack[tempStackPtr] != 1 && tempStack[tempStackPtr-1] != 1) + { + this->ByteCode[i] = VTK_PARSER_ADD; + } + else if ((tempStack[tempStackPtr] == 0 && + tempStack[tempStackPtr-1] != 0) || + (tempStack[tempStackPtr] != 0 && + tempStack[tempStackPtr-1] == 0)) + { + vtkErrorMacro("addition expects either 2 vectors or 2 scalars"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_VECTOR_SUBTRACT: + if (tempStack[tempStackPtr] != 1 && tempStack[tempStackPtr-1] != 1) + { + this->ByteCode[i] = VTK_PARSER_SUBTRACT; + } + else if ((tempStack[tempStackPtr] == 0 && + tempStack[tempStackPtr-1] != 0) || + (tempStack[tempStackPtr] != 0 && + tempStack[tempStackPtr-1] == 0)) + { + vtkErrorMacro("subtraction expects either 2 vectors or 2 scalars"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_SCALAR_TIMES_VECTOR: + if (tempStack[tempStackPtr] == 0 && tempStack[tempStackPtr-1] == 0) + { + this->ByteCode[i] = VTK_PARSER_MULTIPLY; + } + else if (tempStack[tempStackPtr-1] == 1 && + tempStack[tempStackPtr] == 0) + { + this->ByteCode[i] = VTK_PARSER_VECTOR_TIMES_SCALAR; + } + else + { + vtkErrorMacro("expecting a scalar followed by a vector"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_VECTOR_TIMES_SCALAR: + if (tempStack[tempStackPtr] == 0 && tempStack[tempStackPtr-1] == 0) + { + this->ByteCode[i] = VTK_PARSER_MULTIPLY; + } + else if (tempStack[tempStackPtr-1] == 0 && + tempStack[tempStackPtr] == 1) + { + this->ByteCode[i] = VTK_PARSER_SCALAR_TIMES_VECTOR; + } + else + { + vtkErrorMacro("expecting a vector followed by a scalar"); + return 0; + } + tempStackPtr--; + break; + case VTK_PARSER_MAGNITUDE: + if (tempStack[tempStackPtr] == 0) + { + vtkErrorMacro("magnitude expects a vector, but got a scalar"); + return 0; + } + tempStack[tempStackPtr] = 0; + break; + case VTK_PARSER_NORMALIZE: + if (tempStack[tempStackPtr] == 0) + { + vtkErrorMacro("normalize expects a vector, but got a scalar"); + return 0; + } + break; + case VTK_PARSER_IHAT: + case VTK_PARSER_JHAT: + case VTK_PARSER_KHAT: + tempStackPtr++; + tempStack[tempStackPtr] = 1; + break; + default: + if ((this->ByteCode[i] - VTK_PARSER_BEGIN_VARIABLES) < + this->NumberOfScalarVariables) + { + tempStackPtr++; + tempStack[tempStackPtr] = 0; + } + else + { + tempStackPtr++; + tempStack[tempStackPtr] = 1; + } + } + } + + delete [] tempStack; + return 1; +} + +void vtkFunctionParser::Evaluate() +{ + int numBytesProcessed; + int numImmediatesProcessed = 0; + int stackPosition = -1; + double magnitude; + + this->StackPointer = -1; + + if (this->FunctionMTime.GetMTime() > this->ParseMTime.GetMTime()) + { + if (this->Parse() == 0) + { + return; + } + } + + for (numBytesProcessed = 0; numBytesProcessed < this->ByteCodeSize; + numBytesProcessed++) + { + switch (this->ByteCode[numBytesProcessed]) + { + case VTK_PARSER_IMMEDIATE: + this->Stack[++stackPosition] = + this->Immediates[numImmediatesProcessed++]; + break; + case VTK_PARSER_UNARY_MINUS: + this->Stack[stackPosition] =- this->Stack[stackPosition]; + break; + case VTK_PARSER_ADD: + this->Stack[stackPosition-1] += this->Stack[stackPosition]; + stackPosition--; + break; + case VTK_PARSER_SUBTRACT: + this->Stack[stackPosition-1] -= this->Stack[stackPosition]; + stackPosition--; + break; + case VTK_PARSER_MULTIPLY: + this->Stack[stackPosition-1] *= this->Stack[stackPosition]; + stackPosition--; + break; + case VTK_PARSER_DIVIDE: + if (this->Stack[stackPosition]==0) + { + if (this->ReplaceInvalidValues) + { + this->Stack[stackPosition-1] = this->ReplacementValue; + stackPosition--; + } + else + { + vtkErrorMacro("Trying to divide by zero"); + return; + } + } + else + { + this->Stack[stackPosition-1] /= this->Stack[stackPosition]; + stackPosition--; + } + break; + case VTK_PARSER_POWER: + this->Stack[stackPosition-1] = pow(this->Stack[stackPosition-1], + this->Stack[stackPosition]); + stackPosition--; + break; + case VTK_PARSER_ABSOLUTE_VALUE: + this->Stack[stackPosition] = fabs(this->Stack[stackPosition]); + break; + case VTK_PARSER_EXPONENT: + this->Stack[stackPosition] = exp(this->Stack[stackPosition]); + break; + case VTK_PARSER_CEILING: + this->Stack[stackPosition] = ceil(this->Stack[stackPosition]); + break; + case VTK_PARSER_FLOOR: + this->Stack[stackPosition] = floor(this->Stack[stackPosition]); + break; + case VTK_PARSER_LOGARITHM: + if (this->Stack[stackPosition]<=0) + { + if (this->ReplaceInvalidValues) + { + this->Stack[stackPosition] = this->ReplacementValue; + } + else + { + vtkErrorMacro("Trying to take a logarithm of a negative value"); + return; + } + } + else + { + this->Stack[stackPosition] = log(this->Stack[stackPosition]); + } + break; + case VTK_PARSER_LOGARITHME: + if (this->Stack[stackPosition]<=0) + { + if (this->ReplaceInvalidValues) + { + this->Stack[stackPosition] = this->ReplacementValue; + } + else + { + vtkErrorMacro("Trying to take a logarithm of a negative value"); + return; + } + } + else + { + this->Stack[stackPosition] = log(this->Stack[stackPosition]); + } + break; + case VTK_PARSER_LOGARITHM10: + if (this->Stack[stackPosition]<=0) + { + if (this->ReplaceInvalidValues) + { + this->Stack[stackPosition] = this->ReplacementValue; + } + else + { + vtkErrorMacro("Trying to take a logarithm of a negative value"); + return; + } + } + else + { + this->Stack[stackPosition] = + log(this->Stack[stackPosition])/log((double)10); + } + break; + case VTK_PARSER_SQUARE_ROOT: + if (this->Stack[stackPosition] < 0) + { + if (this->ReplaceInvalidValues) + { + this->Stack[stackPosition] = this->ReplacementValue; + } + else + { + vtkErrorMacro("Trying to take a square root of a negative value"); + return; + } + } + else + { + this->Stack[stackPosition] = sqrt(this->Stack[stackPosition]); + } + break; + case VTK_PARSER_SINE: + this->Stack[stackPosition] = sin(this->Stack[stackPosition]); + break; + case VTK_PARSER_COSINE: + this->Stack[stackPosition] = cos(this->Stack[stackPosition]); + break; + case VTK_PARSER_TANGENT: + this->Stack[stackPosition] = tan(this->Stack[stackPosition]); + break; + case VTK_PARSER_ARCSINE: + if (this->Stack[stackPosition] < -1 || this->Stack[stackPosition] > 1) + { + if (this->ReplaceInvalidValues) + { + this->Stack[stackPosition] = this->ReplacementValue; + } + else + { + vtkErrorMacro("Trying to take asin of a value < -1 or > 1"); + return; + } + } + else + { + this->Stack[stackPosition] = asin(this->Stack[stackPosition]); + } + break; + case VTK_PARSER_ARCCOSINE: + if(this->Stack[stackPosition]<-1 || this->Stack[stackPosition]>1) + { + if (this->ReplaceInvalidValues) + { + this->Stack[stackPosition] = this->ReplacementValue; + } + else + { + vtkErrorMacro("Trying to take acos of a value < -1 or > 1"); + return; + } + } + else + { + this->Stack[stackPosition] = acos(this->Stack[stackPosition]); + } + break; + case VTK_PARSER_ARCTANGENT: + this->Stack[stackPosition] = atan(this->Stack[stackPosition]); + break; + case VTK_PARSER_HYPERBOLIC_SINE: + this->Stack[stackPosition] = sinh(this->Stack[stackPosition]); + break; + case VTK_PARSER_HYPERBOLIC_COSINE: + this->Stack[stackPosition] = cosh(this->Stack[stackPosition]); + break; + case VTK_PARSER_HYPERBOLIC_TANGENT: + this->Stack[stackPosition] = tanh(this->Stack[stackPosition]); + break; + case VTK_PARSER_MIN: + if (this->Stack[stackPosition] < this->Stack[stackPosition-1]) + { + this->Stack[stackPosition-1] = this->Stack[stackPosition]; + } + stackPosition--; + break; + case VTK_PARSER_MAX: + if (this->Stack[stackPosition] > this->Stack[stackPosition-1]) + { + this->Stack[stackPosition-1] = this->Stack[stackPosition]; + } + stackPosition--; + break; + case VTK_PARSER_SIGN: + if (this->Stack[stackPosition] < 0) + { + this->Stack[stackPosition] = -1; + } + else if (this->Stack[stackPosition] == 0) + { + this->Stack[stackPosition] = 0; + } + else + { + this->Stack[stackPosition] = 1; + } + break; + case VTK_PARSER_VECTOR_UNARY_MINUS: + this->Stack[stackPosition] = -this->Stack[stackPosition]; + this->Stack[stackPosition-1] = -this->Stack[stackPosition-1]; + this->Stack[stackPosition-2] = -this->Stack[stackPosition-2]; + break; + case VTK_PARSER_DOT_PRODUCT: + this->Stack[stackPosition-3] *= this->Stack[stackPosition]; + this->Stack[stackPosition-4] *= this->Stack[stackPosition-1]; + this->Stack[stackPosition-5] *= this->Stack[stackPosition-2]; + this->Stack[stackPosition-5] = this->Stack[stackPosition-5] + + this->Stack[stackPosition-4] + this->Stack[stackPosition-3]; + stackPosition -= 5; + break; + case VTK_PARSER_VECTOR_ADD: + this->Stack[stackPosition-3] += this->Stack[stackPosition]; + this->Stack[stackPosition-4] += this->Stack[stackPosition-1]; + this->Stack[stackPosition-5] += this->Stack[stackPosition-2]; + stackPosition -= 3; + break; + case VTK_PARSER_VECTOR_SUBTRACT: + this->Stack[stackPosition-3] -= this->Stack[stackPosition]; + this->Stack[stackPosition-4] -= this->Stack[stackPosition-1]; + this->Stack[stackPosition-5] -= this->Stack[stackPosition-2]; + stackPosition -= 3; + break; + case VTK_PARSER_SCALAR_TIMES_VECTOR: + this->Stack[stackPosition] *= this->Stack[stackPosition-3]; + this->Stack[stackPosition-1] *= this->Stack[stackPosition-3]; + this->Stack[stackPosition-2] *= this->Stack[stackPosition-3]; + this->Stack[stackPosition-3] = this->Stack[stackPosition-2]; + this->Stack[stackPosition-2] = this->Stack[stackPosition-1]; + this->Stack[stackPosition-1] = this->Stack[stackPosition]; + stackPosition--; + break; + case VTK_PARSER_VECTOR_TIMES_SCALAR: + this->Stack[stackPosition-3] *= this->Stack[stackPosition]; + this->Stack[stackPosition-2] *= this->Stack[stackPosition]; + this->Stack[stackPosition-1] *= this->Stack[stackPosition]; + stackPosition--; + break; + case VTK_PARSER_MAGNITUDE: + this->Stack[stackPosition-2] = + sqrt(pow(this->Stack[stackPosition], 2) + + pow(this->Stack[stackPosition-1], 2) + + pow(this->Stack[stackPosition-2], 2)); + stackPosition -= 2; + break; + case VTK_PARSER_NORMALIZE: + magnitude = sqrt(pow(this->Stack[stackPosition], 2) + + pow(this->Stack[stackPosition-1], 2) + + pow(this->Stack[stackPosition-2], 2)); + if (magnitude != 0) + { + this->Stack[stackPosition] /= magnitude; + this->Stack[stackPosition-1] /= magnitude; + this->Stack[stackPosition-2] /= magnitude; + } + break; + case VTK_PARSER_IHAT: + this->Stack[++stackPosition] = 1; + this->Stack[++stackPosition] = 0; + this->Stack[++stackPosition] = 0; + break; + case VTK_PARSER_JHAT: + this->Stack[++stackPosition] = 0; + this->Stack[++stackPosition] = 1; + this->Stack[++stackPosition] = 0; + break; + case VTK_PARSER_KHAT: + this->Stack[++stackPosition] = 0; + this->Stack[++stackPosition] = 0; + this->Stack[++stackPosition] = 1; + break; + default: + if ((this->ByteCode[numBytesProcessed] - + VTK_PARSER_BEGIN_VARIABLES) < this->NumberOfScalarVariables) + { + this->Stack[++stackPosition] = + this->ScalarVariableValues[this->ByteCode[numBytesProcessed] - + VTK_PARSER_BEGIN_VARIABLES]; + } + else + { + int vectorNum = this->ByteCode[numBytesProcessed] - + VTK_PARSER_BEGIN_VARIABLES - this->NumberOfScalarVariables; + this->Stack[++stackPosition] = + this->VectorVariableValues[vectorNum][0]; + this->Stack[++stackPosition] = + this->VectorVariableValues[vectorNum][1]; + this->Stack[++stackPosition] = + this->VectorVariableValues[vectorNum][2]; + } + } + } + this->StackPointer = stackPosition; + + this->EvaluateMTime.Modified(); +} + +int vtkFunctionParser::IsScalarResult() +{ + if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() || + this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime()) + { + this->Evaluate(); + } + return (this->StackPointer == 0); +} + +double vtkFunctionParser::GetScalarResult() +{ + if (!(this->IsScalarResult())) + { + vtkErrorMacro("GetScalarResult: no valid scalar result"); + return VTK_PARSER_ERROR_RESULT; + } + return this->Stack[0]; +} + +int vtkFunctionParser::IsVectorResult() +{ + if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() || + this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime()) + { + this->Evaluate(); + } + return (this->StackPointer == 2); +} + +double *vtkFunctionParser::GetVectorResult() +{ + if (!(this->IsVectorResult())) + { + vtkErrorMacro("GetVectorResult: no valid vector result"); + return vtkParserVectorErrorResult; + } + return this->Stack; +} + +char* vtkFunctionParser::GetScalarVariableName(int i) +{ + if (i >= 0 && i < this->NumberOfScalarVariables) + { + return this->ScalarVariableNames[i]; + } + return NULL; +} + +char* vtkFunctionParser::GetVectorVariableName(int i) +{ + if (i >= 0 && i < this->NumberOfVectorVariables) + { + return this->VectorVariableNames[i]; + } + return NULL; +} + +int vtkFunctionParser::IsVariableName(int currentIndex) +{ + int i; + + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + if (strncmp(this->ScalarVariableNames[i], &this->Function[currentIndex], + strlen(this->ScalarVariableNames[i])) == 0) + { + return 1; + } + } + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + if (strncmp(this->VectorVariableNames[i], &this->Function[currentIndex], + strlen(this->VectorVariableNames[i])) == 0) + { + return 1; + } + } + + return 0; +} + +int vtkFunctionParser::IsElementaryOperator(int op) +{ + return strchr("+-.*/^", op) != NULL; +} + +void vtkFunctionParser::SetScalarVariableValue(const char* inVariableName, + double value) +{ + int i; + double *tempValues; + char** tempNames; + char* variableName = this->RemoveSpacesFrom(inVariableName); + + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + if (strcmp(variableName, this->ScalarVariableNames[i]) == 0) + { + if (this->ScalarVariableValues[i] != value) + { + this->ScalarVariableValues[i] = value; + this->VariableMTime.Modified(); + this->Modified(); + } + delete [] variableName; + return; + } + } + + tempValues = new double [this->NumberOfScalarVariables]; + tempNames = new char *[this->NumberOfScalarVariables]; + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + tempValues[i] = this->ScalarVariableValues[i]; + tempNames[i] = new char [strlen(this->ScalarVariableNames[i]) + 1]; + strcpy(tempNames[i], this->ScalarVariableNames[i]); + delete [] this->ScalarVariableNames[i]; + this->ScalarVariableNames[i] = NULL; + } + + if (this->ScalarVariableValues) + { + delete [] this->ScalarVariableValues; + this->ScalarVariableValues = NULL; + } + if (this->ScalarVariableNames) + { + delete [] this->ScalarVariableNames; + this->ScalarVariableNames = NULL; + } + + this->ScalarVariableValues = new double [this->NumberOfScalarVariables + 1]; + this->ScalarVariableNames = new char *[this->NumberOfScalarVariables + 1]; + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + this->ScalarVariableValues[i] = tempValues[i]; + this->ScalarVariableNames[i] = new char [strlen(tempNames[i]) + 1]; + strcpy(this->ScalarVariableNames[i], tempNames[i]); + delete [] tempNames[i]; + tempNames[i] = NULL; + } + delete [] tempValues; + delete [] tempNames; + + this->ScalarVariableValues[i] = value; + this->ScalarVariableNames[i] = new char [strlen(variableName) + 1]; + strcpy(this->ScalarVariableNames[i], variableName); + this->NumberOfScalarVariables++; + + this->VariableMTime.Modified(); + this->Modified(); + delete [] variableName; +} + +void vtkFunctionParser::SetScalarVariableValue(int i, double value) +{ + if (i < 0 || i >= this->NumberOfScalarVariables) + { + return; + } + + if (this->ScalarVariableValues[i] != value) + { + this->ScalarVariableValues[i] = value; + this->VariableMTime.Modified(); + } + this->Modified(); +} + +double vtkFunctionParser::GetScalarVariableValue(const char* inVariableName) +{ + int i; + char* variableName = this->RemoveSpacesFrom(inVariableName); + + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + if (strcmp(variableName, this->ScalarVariableNames[i]) == 0) + { + delete [] variableName; + return this->ScalarVariableValues[i]; + } + } + vtkErrorMacro("GetScalarVariableValue: scalar variable " << variableName + << " does not exist"); + delete [] variableName; + return VTK_PARSER_ERROR_RESULT; +} + +double vtkFunctionParser::GetScalarVariableValue(int i) +{ + if (i < 0 || i >= this->NumberOfScalarVariables) + { + vtkErrorMacro("GetScalarVariableValue: scalar variable " << i + << " does not exist"); + return VTK_PARSER_ERROR_RESULT; + } + + return this->ScalarVariableValues[i]; +} + +void vtkFunctionParser::SetVectorVariableValue(const char* inVariableName, + double xValue, double yValue, + double zValue) +{ + int i; + double **tempValues; + char** tempNames; + char* variableName = this->RemoveSpacesFrom(inVariableName); + + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + if (strcmp(variableName, this->VectorVariableNames[i]) == 0) + { + if (this->VectorVariableValues[i][0] != xValue || + this->VectorVariableValues[i][1] != yValue || + this->VectorVariableValues[i][2] != zValue) + { + this->VectorVariableValues[i][0] = xValue; + this->VectorVariableValues[i][1] = yValue; + this->VectorVariableValues[i][2] = zValue; + this->VariableMTime.Modified(); + this->Modified(); + } + delete [] variableName; + return; + } + } + + tempValues = new double *[this->NumberOfVectorVariables]; + tempNames = new char *[this->NumberOfVectorVariables]; + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + tempValues[i] = new double[3]; + tempValues[i][0] = this->VectorVariableValues[i][0]; + tempValues[i][1] = this->VectorVariableValues[i][1]; + tempValues[i][2] = this->VectorVariableValues[i][2]; + tempNames[i] = new char [strlen(this->VectorVariableNames[i]) + 1]; + strcpy(tempNames[i], this->VectorVariableNames[i]); + delete [] this->VectorVariableNames[i]; + this->VectorVariableNames[i] = NULL; + delete [] this->VectorVariableValues[i]; + this->VectorVariableValues[i] = NULL; + } + + if (this->VectorVariableValues) + { + delete [] this->VectorVariableValues; + this->VectorVariableValues = NULL; + } + if (this->VectorVariableNames) + { + delete [] this->VectorVariableNames; + this->VectorVariableNames = NULL; + } + + this->VectorVariableValues = new double *[this->NumberOfVectorVariables + 1]; + this->VectorVariableNames = new char *[this->NumberOfVectorVariables + 1]; + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + this->VectorVariableValues[i] = new double[3]; + this->VectorVariableValues[i][0] = tempValues[i][0]; + this->VectorVariableValues[i][1] = tempValues[i][1]; + this->VectorVariableValues[i][2] = tempValues[i][2]; + this->VectorVariableNames[i] = new char [strlen(tempNames[i]) + 1]; + strcpy(this->VectorVariableNames[i], tempNames[i]); + delete [] tempNames[i]; + tempNames[i] = NULL; + delete [] tempValues[i]; + tempValues[i] = NULL; + } + delete [] tempValues; + delete [] tempNames; + + this->VectorVariableValues[i] = new double[3]; + this->VectorVariableValues[i][0] = xValue; + this->VectorVariableValues[i][1] = yValue; + this->VectorVariableValues[i][2] = zValue; + this->VectorVariableNames[i] = new char [strlen(variableName) + 1]; + strcpy(this->VectorVariableNames[i], variableName); + this->NumberOfVectorVariables++; + + this->VariableMTime.Modified(); + this->Modified(); + delete [] variableName; +} + +void vtkFunctionParser::SetVectorVariableValue(int i, double xValue, + double yValue, double zValue) +{ + if (i < 0 || i >= this->NumberOfVectorVariables) + { + return; + } + if (this->VectorVariableValues[i][0] != xValue || + this->VectorVariableValues[i][1] != yValue || + this->VectorVariableValues[i][2] != zValue) + { + this->VectorVariableValues[i][0] = xValue; + this->VectorVariableValues[i][1] = yValue; + this->VectorVariableValues[i][2] = zValue; + this->VariableMTime.Modified(); + this->Modified(); + } +} + +double* vtkFunctionParser::GetVectorVariableValue(const char* inVariableName) +{ + int i; + char* variableName = this->RemoveSpacesFrom(inVariableName); + + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + if (strcmp(variableName, this->VectorVariableNames[i]) == 0) + { + delete [] variableName; + return this->VectorVariableValues[i]; + } + } + vtkErrorMacro("GetVectorVariableValue: vector variable " << variableName + << " does not exist"); + delete [] variableName; + return vtkParserVectorErrorResult; +} + +double* vtkFunctionParser::GetVectorVariableValue(int i) +{ + if (i < 0 || i >= this->NumberOfVectorVariables) + { + vtkErrorMacro("GetVectorVariableValue: vector variable " << i + << " does not exist"); + return vtkParserVectorErrorResult; + } + return this->VectorVariableValues[i]; +} + +char* vtkFunctionParser::RemoveSpacesFrom(const char* variableName) +{ + int len = static_cast(strlen(variableName)); + int i; + char* resultString = new char[len+1]; + char* out = resultString; + for(i=0; i < len; ++i) + { + if(variableName[i] != ' ') + { + *out++ = variableName[i]; + } + } + *out = '\0'; + return resultString; +} + +void vtkFunctionParser::RemoveSpaces() +{ + char *tempString; + int i, length; + + this->FunctionLength = 0; + length = static_cast(strlen(this->Function)); + + tempString = new char[length+1]; + for (i = 0; i < length; i++) + { + if (!isspace(this->Function[i])) + { + tempString[this->FunctionLength] = this->Function[i]; + this->FunctionLength++; + } + } + + delete [] this->Function; + this->Function = new char[this->FunctionLength+1]; + strncpy(this->Function, tempString, this->FunctionLength); + this->Function[this->FunctionLength] = '\0'; + delete [] tempString; +} + +int vtkFunctionParser::OperatorWithinVariable(int idx) +{ + int i; + char *tmpString; + int start, end; + + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + if (strchr(this->ScalarVariableNames[i], this->Function[idx]) != 0) + { + tmpString = strstr(this->Function, this->ScalarVariableNames[i]); + if (tmpString) + { + start = (int)(tmpString - this->Function); + end = start + strlen(this->ScalarVariableNames[i]); + if (start <= idx && end >= idx) + { + return 1; + } + } + } + } + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + if (strchr(this->VectorVariableNames[i], this->Function[idx]) != 0) + { + tmpString = strstr(this->Function, this->VectorVariableNames[i]); + if (tmpString) + { + start = (int)(tmpString - this->Function); + end = start + strlen(this->VectorVariableNames[i]); + if (start <= idx && end >= idx) + { + return 1; + } + } + } + } + + return 0; +} + +int vtkFunctionParser::CheckSyntax() +{ + int index = 0, parenthesisCount = 0, currentChar; + char* ptr; + int functionNumber, constantNumber; + int *expectCommaOnParenthesisCount = new int[this->FunctionLength]; + int i; + + for (i = 0; i < this->FunctionLength; i++) + { + expectCommaOnParenthesisCount[i] = 0; + } + + while (1) + { + currentChar = this->Function[index]; + + // Check for valid operand (must appear) + + // Check for leading - + if (currentChar == '-') + { + currentChar = this->Function[++index]; + if(index == this->FunctionLength) + { + vtkErrorMacro("Syntax error: unary minus with no operand;" + << " see position " << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + } + + // Check for math function + if ((functionNumber = this->GetMathFunctionNumber(index))) + { + if ((functionNumber == VTK_PARSER_MIN) || + (functionNumber == VTK_PARSER_MAX)) + { + expectCommaOnParenthesisCount[parenthesisCount+1] = 1; + } + index += this->GetMathFunctionStringLength(functionNumber); + currentChar = this->Function[index]; + if ( currentChar != '(' ) + { + vtkErrorMacro("Syntax error: input to math function not in " + << "parentheses; see position " << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + } + + // Check for opening parenthesis + if( currentChar == '(' ) + { + parenthesisCount++; + index++; + continue; + } + + // Check for number + if(isdigit(currentChar) || + (currentChar == '.' && isdigit(this->Function[index+1]))) + { + strtod(&this->Function[index], &ptr); + index += int(ptr-&this->Function[index]); + currentChar = this->Function[index]; + } + // Check for named constant + else if ((constantNumber = this->GetMathConstantNumber(index))) + { + index += this->GetMathConstantStringLength(constantNumber); + currentChar = this->Function[index]; + } + else + { // Check for variable + if (!this->IsVariableName(index)) + { + vtkErrorMacro("Syntax error: expecting a variable name; " + << "see position " << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + index += this->GetVariableNameLength(this->GetOperandNumber(index) - + VTK_PARSER_BEGIN_VARIABLES); + currentChar = this->Function[index]; + } + + // Check for possible second number from min or max function + if (expectCommaOnParenthesisCount[parenthesisCount]) + { + // Check for comma + if (currentChar == ',') + { + expectCommaOnParenthesisCount[parenthesisCount] = 2; + index++; + continue; + } + } + + // Check for closing parenthesis + while ( currentChar == ')' ) + { + if (expectCommaOnParenthesisCount[parenthesisCount] == 1) + { + // We can't be closing this function if + // expectCommaOnParenthesisCount[..] is still 1; either it was always + // 0 or it should have been incremented to 2. + vtkErrorMacro("Syntax Error: two parameters separated by commas " + << "expected; see position " << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + parenthesisCount--; + if(parenthesisCount < 0) + { + vtkErrorMacro("Syntax Error: mismatched parenthesis; see position " + << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + if( this->Function[index - 1] == '(' ) + { + vtkErrorMacro("Syntax Error: empty parentheses; see position " + << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + currentChar = this->Function[++index]; + } + + // If we get here, we have a legal operand and now a legal operator or + // end of string must follow. + + // Check for EOS + // The only way to end the checking loop without error. + if (index == this->FunctionLength) + { + break; + } + // Check for operator + if(!this->IsElementaryOperator(currentChar)) + { + vtkErrorMacro("Syntax error: operator expected; see position " + << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + + // If we get here, we have an operand and an operator; the next loop will + // check for another operand (must appear) + index++; + } // while + + // Check that all opened parentheses are also closed + if(parenthesisCount > 0) + { + vtkErrorMacro("Syntax Error: missing closing parenthesis; see position " + << index); + delete [] expectCommaOnParenthesisCount; + return 0; + } + + + // The string is ok + delete [] expectCommaOnParenthesisCount; + return 1; +} + +int vtkFunctionParser::BuildInternalFunctionStructure() +{ + if (this->ByteCode) + { + delete [] this->ByteCode; + this->ByteCode = NULL; + } + if (this->Immediates) + { + delete [] this->Immediates; + this->Immediates = NULL; + } + if (this->Stack) + { + delete [] this->Stack; + this->Stack = NULL; + } + + this->ByteCodeSize = this->ImmediatesSize = this->StackSize = 0; + this->StackPointer = 0; + this->BuildInternalSubstringStructure(0, this->FunctionLength - 1); + + return 1; +} + +void vtkFunctionParser::BuildInternalSubstringStructure(int beginIndex, + int endIndex) +{ + int mathFunctionNum, beginIndex2; + int opNum, parenthesisCount, i; + static const char* const elementaryMathOps = "+-.*/^"; + + if (this->IsSubstringCompletelyEnclosed(beginIndex, endIndex)) + { + this->BuildInternalSubstringStructure(beginIndex+1, endIndex-1); + return; + } + + if (this->Function[beginIndex] == '-') + { + if (this->IsSubstringCompletelyEnclosed(beginIndex+1, endIndex)) + { + this->BuildInternalSubstringStructure(beginIndex+2, endIndex-1); + this->AddInternalByte(VTK_PARSER_UNARY_MINUS); + return; + } + if (this->GetMathFunctionNumber(beginIndex+1) > 0 && + this->FindEndOfMathFunction(beginIndex+1) == endIndex) + { + this->BuildInternalSubstringStructure(beginIndex+1, endIndex); + this->AddInternalByte(VTK_PARSER_UNARY_MINUS); + return; + } + if (this->GetMathConstantNumber(beginIndex+1) > 0 && + this->FindEndOfMathConstant(beginIndex+1) == endIndex) + { + this->BuildInternalSubstringStructure(beginIndex+1, endIndex); + this->AddInternalByte(VTK_PARSER_UNARY_MINUS); + return; + } + } + + if (isalpha(this->Function[beginIndex])) + { + mathFunctionNum = this->GetMathFunctionNumber(beginIndex); + if (mathFunctionNum > 0) + { + beginIndex2 = beginIndex; + while (this->Function[beginIndex2] != '(') + { + beginIndex2++; + } + if (this->IsSubstringCompletelyEnclosed(beginIndex2, endIndex)) + { + if ((mathFunctionNum == VTK_PARSER_MIN) || + (mathFunctionNum == VTK_PARSER_MAX)) + { + parenthesisCount = 0; + for (i = endIndex-1; i > beginIndex2; i--) + { + if (this->Function[i] == ')') + { + parenthesisCount++; + } + else if (this->Function[i] == '(') + { + parenthesisCount--; + } + if (parenthesisCount == 0 && this->Function[i] == ',') + { + this->BuildInternalSubstringStructure(beginIndex2+1, i-1); + this->BuildInternalSubstringStructure(i+1, endIndex-1); + this->AddInternalByte(mathFunctionNum); + this->StackPointer--; + return; + } + } + } + + this->BuildInternalSubstringStructure(beginIndex2+1, endIndex-1); + this->AddInternalByte(mathFunctionNum); + return; + } + } + } + + for (opNum = 0; opNum < 6; opNum++) + { + parenthesisCount = 0; + for (i = endIndex; i > beginIndex; i--) + { + if (this->Function[i] == ')') + { + parenthesisCount++; + } + else if (this->Function[i] == '(') + { + parenthesisCount--; + } + if (parenthesisCount == 0 && + this->Function[i] == elementaryMathOps[opNum] && + !(this->Function[i] == '-' && + (this->IsElementaryOperator(this->Function[i-1]) || + this->Function[i-1] == '(' || + (this->Function[i-1] == 'e' && i > 1 && + isdigit(this->Function[i-2])))) && + !(this->Function[i] == '.' && + (i+1 < this->FunctionLength) && + (isdigit(this->Function[i+1]))) && + !this->OperatorWithinVariable(i)) + { + this->BuildInternalSubstringStructure(beginIndex, i-1); + this->BuildInternalSubstringStructure(i+1, endIndex); + this->AddInternalByte( + this->GetElementaryOperatorNumber(elementaryMathOps[opNum])); + this->StackPointer--; + return; + } + } + } + + beginIndex2 = beginIndex; + if (this->Function[beginIndex] == '-') + { + beginIndex2++; + } + + this->AddInternalByte(this->GetOperandNumber(beginIndex2)); + this->StackPointer++; + + if (this->StackPointer > this->StackSize) + { + this->StackSize++; + } + if (beginIndex2 > beginIndex) + { + this->AddInternalByte(VTK_PARSER_UNARY_MINUS); + } +} + +void vtkFunctionParser::AddInternalByte(unsigned char newByte) +{ + int i; + unsigned char *tempByteCode = new unsigned char[this->ByteCodeSize]; + + for (i = 0; i < this->ByteCodeSize; i++) + { // Copy current byte code to a temporary array + tempByteCode[i] = this->ByteCode[i]; + } + if (this->ByteCode) + { + delete [] this->ByteCode; + } + + // Allocate space for new byte. + this->ByteCode = new unsigned char[this->ByteCodeSize + 1]; + + // Copy contents of temporary array back to ByteCode. + for (i = 0; i < this->ByteCodeSize; i++) + { + this->ByteCode[i] = tempByteCode[i]; + } + + this->ByteCode[this->ByteCodeSize] = newByte; + this->ByteCodeSize++; + delete [] tempByteCode; +} + +int vtkFunctionParser::IsSubstringCompletelyEnclosed(int beginIndex, + int endIndex) +{ + int i, parenthesisCount; + + if ( this->Function[beginIndex] == '(' && this->Function[endIndex]== ')' ) + { + parenthesisCount = 1; + for (i = beginIndex + 1; i < endIndex; i++) + { + if (this->Function[i] == '(' ) + { + parenthesisCount++; + } + else if(this->Function[i] == ')' ) + { + parenthesisCount--; + } + if (parenthesisCount == 0) + { + break; + } + } + if (i == endIndex) + { + return 1; + } + } + return 0; +} + +int vtkFunctionParser::GetMathFunctionNumber(int currentIndex) +{ + if (strncmp(&this->Function[currentIndex], "abs", 3) == 0) + { + return VTK_PARSER_ABSOLUTE_VALUE; + } + if (strncmp(&this->Function[currentIndex], "exp", 3) == 0) + { + return VTK_PARSER_EXPONENT; + } + if (strncmp(&this->Function[currentIndex], "ceil", 4) == 0) + { + return VTK_PARSER_CEILING; + } + if (strncmp(&this->Function[currentIndex], "floor", 5) == 0) + { + return VTK_PARSER_FLOOR; + } + if (strncmp(&this->Function[currentIndex], "ln", 2) == 0) + { + return VTK_PARSER_LOGARITHME; + } + if (strncmp(&this->Function[currentIndex], "log10", 5) == 0) + { + return VTK_PARSER_LOGARITHM10; + } + if (strncmp(&this->Function[currentIndex], "log", 3) == 0) + { + vtkErrorMacro("The use of log function is being deprecated. " + "Please use log10 or ln instead"); + return VTK_PARSER_LOGARITHM; + } + if (strncmp(&this->Function[currentIndex], "sqrt", 4) == 0) + { + return VTK_PARSER_SQUARE_ROOT; + } + if (strncmp(&this->Function[currentIndex], "sin", 3) == 0) + { + if (strncmp(&this->Function[currentIndex], "sinh", 4) == 0) + { + return VTK_PARSER_HYPERBOLIC_SINE; + } + return VTK_PARSER_SINE; + } + if (strncmp(&this->Function[currentIndex], "cos", 3) == 0) + { + if (strncmp(&this->Function[currentIndex], "cosh", 4) == 0) + { + return VTK_PARSER_HYPERBOLIC_COSINE; + } + return VTK_PARSER_COSINE; + } + if (strncmp(&this->Function[currentIndex], "tan", 3) == 0) + { + if (strncmp(&this->Function[currentIndex], "tanh", 4) == 0) + { + return VTK_PARSER_HYPERBOLIC_TANGENT; + } + return VTK_PARSER_TANGENT; + } + if (strncmp(&this->Function[currentIndex], "asin", 4) == 0) + { + return VTK_PARSER_ARCSINE; + } + if (strncmp(&this->Function[currentIndex], "acos", 4) == 0) + { + return VTK_PARSER_ARCCOSINE; + } + if (strncmp(&this->Function[currentIndex], "atan", 4) == 0) + { + return VTK_PARSER_ARCTANGENT; + } + if (strncmp(&this->Function[currentIndex], "min", 3) == 0) + { + return VTK_PARSER_MIN; + } + if (strncmp(&this->Function[currentIndex], "max", 3) == 0) + { + return VTK_PARSER_MAX; + } + if (strncmp(&this->Function[currentIndex], "sign", 4) == 0) + { + return VTK_PARSER_SIGN; + } + if (strncmp(&this->Function[currentIndex], "mag", 3) == 0) + { + return VTK_PARSER_MAGNITUDE; + } + if (strncmp(&this->Function[currentIndex], "norm", 4) == 0) + { + return VTK_PARSER_NORMALIZE; + } + + return 0; +} + +int vtkFunctionParser::GetMathFunctionStringLength(int mathFunctionNumber) +{ + switch (mathFunctionNumber) + { + case VTK_PARSER_LOGARITHME: + return 2; + case VTK_PARSER_ABSOLUTE_VALUE: + case VTK_PARSER_EXPONENT: + case VTK_PARSER_LOGARITHM: + case VTK_PARSER_SINE: + case VTK_PARSER_COSINE: + case VTK_PARSER_TANGENT: + case VTK_PARSER_MAGNITUDE: + return 3; + case VTK_PARSER_CEILING: + case VTK_PARSER_SQUARE_ROOT: + case VTK_PARSER_ARCSINE: + case VTK_PARSER_ARCCOSINE: + case VTK_PARSER_ARCTANGENT: + case VTK_PARSER_HYPERBOLIC_SINE: + case VTK_PARSER_HYPERBOLIC_COSINE: + case VTK_PARSER_HYPERBOLIC_TANGENT: + case VTK_PARSER_NORMALIZE: + return 4; + case VTK_PARSER_FLOOR: + case VTK_PARSER_LOGARITHM10: + return 5; + default: + vtkWarningMacro("Unknown math function"); + return 0; + } +} + +int vtkFunctionParser::GetMathConstantNumber(int currentIndex) +{ + if (strncmp(&this->Function[currentIndex], "iHat", 4) == 0) + { + return VTK_PARSER_IHAT; + } + if (strncmp(&this->Function[currentIndex], "jHat", 4) == 0) + { + return VTK_PARSER_JHAT; + } + if (strncmp(&this->Function[currentIndex], "kHat", 4) == 0) + { + return VTK_PARSER_KHAT; + } + + return 0; +} + +int vtkFunctionParser::GetMathConstantStringLength(int mathConstantNumber) +{ + switch (mathConstantNumber) + { + case VTK_PARSER_IHAT: + case VTK_PARSER_JHAT: + case VTK_PARSER_KHAT: + return 4; + default: + vtkWarningMacro("Unknown math constant"); + return 0; + } +} + +int vtkFunctionParser::GetVariableNameLength(int variableNumber) +{ + if (variableNumber < this->NumberOfScalarVariables) + { + return static_cast(strlen(this->ScalarVariableNames[variableNumber])); + } + else + { + return static_cast(strlen( + this->VectorVariableNames[variableNumber - + this->NumberOfScalarVariables])); + } +} + +int vtkFunctionParser::FindEndOfMathFunction(int beginIndex) +{ + int i = beginIndex, parenthesisCount; + + while (this->Function[i] != '(' ) + { + i++; + } + + for (parenthesisCount = 1; parenthesisCount > 0; ++i) + { + parenthesisCount += (this->Function[i] == '(' ? 1 : + (this->Function[i] == ')' ? -1 : 0)); + } + return i - 1; +} + +int vtkFunctionParser::FindEndOfMathConstant(int beginIndex) +{ + if(int constantNumber = this->GetMathConstantNumber(beginIndex)) + { + return beginIndex+this->GetMathConstantStringLength(constantNumber); + } + return beginIndex; +} + +int vtkFunctionParser::GetElementaryOperatorNumber(char op) +{ + static const char* const operators = "+-*/^"; + int i; + + for(i = 0; i < 5; i++) + { + if (operators[i] == op) + { + return VTK_PARSER_ADD + i; + } + } + if (op == '.') + { + return VTK_PARSER_DOT_PRODUCT; + } + + return 0; +} + +int vtkFunctionParser::GetOperandNumber(int currentIndex) +{ + int i, variableIndex = -1; + + if (isdigit(this->Function[currentIndex]) || + this->Function[currentIndex] == '.') // Number + { + double *tempImmediates = new double[this->ImmediatesSize]; + for (i = 0; i < this->ImmediatesSize; i++) + { // Copy current immediates to a temporary array + tempImmediates[i] = this->Immediates[i]; + } + if (this->Immediates) + { + delete [] this->Immediates; + } + + // Allocate space for new immediate value. + this->Immediates = new double[this->ImmediatesSize + 1]; + + // Copy contents of temporary array back to Immediates. + for (i = 0; i < this->ImmediatesSize; i++) + { + this->Immediates[i] = tempImmediates[i]; + } + + this->Immediates[this->ImmediatesSize] = + atof(&this->Function[currentIndex]); + this->ImmediatesSize++; + delete [] tempImmediates; + return VTK_PARSER_IMMEDIATE; + } + + if (!strncmp(&this->Function[currentIndex], "iHat", 4)) + { + return VTK_PARSER_IHAT; + } + if (!strncmp(&this->Function[currentIndex], "jHat", 4)) + { + return VTK_PARSER_JHAT; + } + if (!strncmp(&this->Function[currentIndex], "kHat", 4)) + { + return VTK_PARSER_KHAT; + } + + for (i = 0; i < this->NumberOfScalarVariables; i++) + { // Variable + if (strncmp(&this->Function[currentIndex], this->ScalarVariableNames[i], + strlen(this->ScalarVariableNames[i])) == 0) + { + if (variableIndex == -1 || + (strlen(this->ScalarVariableNames[i]) > + strlen(this->ScalarVariableNames[variableIndex]))) + { + variableIndex = i; + } + } + } + if (variableIndex >= 0) + { + return VTK_PARSER_BEGIN_VARIABLES + variableIndex; + } + + for (i = 0; i < this->NumberOfVectorVariables; i++) + { // Variable + if (strncmp(&this->Function[currentIndex], this->VectorVariableNames[i], + strlen(this->VectorVariableNames[i])) == 0) + { + if (variableIndex == -1 || + (strlen(this->VectorVariableNames[i]) > + strlen(this->VectorVariableNames[variableIndex]))) + { + variableIndex = i; + } + } + } + if (variableIndex >= 0) + { + return VTK_PARSER_BEGIN_VARIABLES + variableIndex + this->NumberOfScalarVariables; + } + + return 0; +} + +void vtkFunctionParser::RemoveAllVariables() +{ + int i; + + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + delete [] this->ScalarVariableNames[i]; + this->ScalarVariableNames[i] = NULL; + } + if (this->NumberOfScalarVariables > 0) + { + delete [] this->ScalarVariableNames; + this->ScalarVariableNames = NULL; + delete [] this->ScalarVariableValues; + this->ScalarVariableValues = NULL; + } + this->NumberOfScalarVariables = 0; + + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + delete [] this->VectorVariableNames[i]; + this->VectorVariableNames[i] = NULL; + } + if (this->NumberOfVectorVariables > 0) + { + delete [] this->VectorVariableNames; + this->VectorVariableNames = NULL; + delete [] this->VectorVariableValues; + this->VectorVariableValues = NULL; + } + this->NumberOfVectorVariables = 0; +} + +void vtkFunctionParser::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int i; + + os << indent << "Function: " + << (this->Function ? this->Function : "(none)") << endl; + + os << indent << "NumberOfScalarVariables: " + << this->NumberOfScalarVariables << endl; + + for (i = 0; i < this->NumberOfScalarVariables; i++) + { + os << indent << " " << this->GetScalarVariableName(i) << ": " + << this->GetScalarVariableValue(i) << endl; + } + + os << indent << "NumberOfVectorVariables: " + << this->NumberOfVectorVariables << endl; + + for (i = 0; i < this->NumberOfVectorVariables; i++) + { + os << indent << " " << this->GetVectorVariableName(i) << ": (" + << this->GetVectorVariableValue(i)[0] << ", " + << this->GetVectorVariableValue(i)[1] << ", " + << this->GetVectorVariableValue(i)[2] << ")" << endl; + } + + if (this->EvaluateMTime.GetMTime() > this->FunctionMTime.GetMTime() && + this->EvaluateMTime.GetMTime() > this->VariableMTime.GetMTime() && + this->StackPointer == 0 || this->StackPointer == 2) + { + if (this->StackPointer == 0) + { + os << indent << "ScalarResult: " << this->GetScalarResult() << endl; + os << indent << "VectorResult: " << "(none)" << endl; + } + else if (this->StackPointer == 2) + { + os << indent << "ScalarResult: " << "(none)" << endl; + os << indent << "VectorResult: " << "(" + << this->GetVectorResult()[0] << ", " + << this->GetVectorResult()[1] << ", " + << this->GetVectorResult()[2] << ")" << endl; + } + } + else + { + os << indent << "ScalarResult: " << "(none)" << endl; + os << indent << "VectorResult: " << "(none)" << endl; + } + + os << indent << "Replace Invalid Values: " + << (this->ReplaceInvalidValues ? "On" : "Off") << endl; + os << indent << "Replacement Value: " << this->ReplacementValue << endl; +} + diff --git a/Common/vtkFunctionParser.h b/Common/vtkFunctionParser.h new file mode 100644 index 0000000..9606a86 --- /dev/null +++ b/Common/vtkFunctionParser.h @@ -0,0 +1,245 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFunctionParser.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFunctionParser - Parse and evaluate a mathematical expression +// .SECTION Description +// vtkFunctionParser is a class that takes in a mathematical expression as +// a char string, parses it, and evaluates it at the specified values of +// the variables in the input string. +// .SECTION Thanks +// Thomas Dunne (thomas.dunne@iwr.uni-heidelberg.de) for adding code for +// two-parameter-parsing and a few functions (sign, min, max). + +#ifndef __vtkFunctionParser_h +#define __vtkFunctionParser_h + +#include "vtkObject.h" + +#define VTK_PARSER_IMMEDIATE 1 +#define VTK_PARSER_UNARY_MINUS 2 + +// supported math functions +#define VTK_PARSER_ADD 3 +#define VTK_PARSER_SUBTRACT 4 +#define VTK_PARSER_MULTIPLY 5 +#define VTK_PARSER_DIVIDE 6 +#define VTK_PARSER_POWER 7 +#define VTK_PARSER_ABSOLUTE_VALUE 8 +#define VTK_PARSER_EXPONENT 9 +#define VTK_PARSER_CEILING 10 +#define VTK_PARSER_FLOOR 11 +#define VTK_PARSER_LOGARITHM 12 +#define VTK_PARSER_LOGARITHME 13 +#define VTK_PARSER_LOGARITHM10 14 +#define VTK_PARSER_SQUARE_ROOT 15 +#define VTK_PARSER_SINE 16 +#define VTK_PARSER_COSINE 17 +#define VTK_PARSER_TANGENT 18 +#define VTK_PARSER_ARCSINE 19 +#define VTK_PARSER_ARCCOSINE 20 +#define VTK_PARSER_ARCTANGENT 21 +#define VTK_PARSER_HYPERBOLIC_SINE 22 +#define VTK_PARSER_HYPERBOLIC_COSINE 23 +#define VTK_PARSER_HYPERBOLIC_TANGENT 24 +#define VTK_PARSER_MIN 25 +#define VTK_PARSER_MAX 26 +#define VTK_PARSER_SIGN 27 + +// functions involving vectors +#define VTK_PARSER_VECTOR_UNARY_MINUS 28 +#define VTK_PARSER_DOT_PRODUCT 29 +#define VTK_PARSER_VECTOR_ADD 30 +#define VTK_PARSER_VECTOR_SUBTRACT 31 +#define VTK_PARSER_SCALAR_TIMES_VECTOR 32 +#define VTK_PARSER_VECTOR_TIMES_SCALAR 33 +#define VTK_PARSER_MAGNITUDE 34 +#define VTK_PARSER_NORMALIZE 35 + +// constants involving vectors +#define VTK_PARSER_IHAT 36 +#define VTK_PARSER_JHAT 37 +#define VTK_PARSER_KHAT 38 + +// codes for scalar variables come before those for vectors +#define VTK_PARSER_BEGIN_VARIABLES 39 + +// the value that is retuned as a result if there is an error +#define VTK_PARSER_ERROR_RESULT VTK_LARGE_FLOAT + +class VTK_COMMON_EXPORT vtkFunctionParser : public vtkObject +{ +public: + static vtkFunctionParser *New(); + vtkTypeRevisionMacro(vtkFunctionParser, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Decription: + // Set/Get input string to evaluate. + void SetFunction(const char *function); + vtkGetStringMacro(Function); + + // Description: + // Check whether the result is a scalar result. If it isn't, then + // either the result is a vector or an error has occurred. + int IsScalarResult(); + + // Description: + // Check whether the result is a vector result. If it isn't, then + // either the result is scalar or an error has occurred. + int IsVectorResult(); + + // Description: + // Get a scalar result from evaluating the input function. + double GetScalarResult(); + + // Description: + // Get a vector result from evaluating the input function. + double* GetVectorResult(); + void GetVectorResult(double result[3]) { + double *r = this->GetVectorResult(); + result[0] = r[0]; result[1] = r[1]; result[2] = r[2]; }; + + // Description: + // Set the value of a scalar variable. If a variable with this name + // exists, then its value will be set to the new value. If there is not + // already a variable with this name, variableName will be added to the + // list of variables, and its value will be set to the new value. + void SetScalarVariableValue(const char* variableName, double value); + void SetScalarVariableValue(int i, double value); + + // Description: + // Get the value of a scalar variable. + double GetScalarVariableValue(const char* variableName); + double GetScalarVariableValue(int i); + + // Description: + // Set the value of a vector variable. If a variable with this name + // exists, then its value will be set to the new value. If there is not + // already a variable with this name, variableName will be added to the + // list of variables, and its value will be set to the new value. + void SetVectorVariableValue(const char* variableName, double xValue, + double yValue, double zValue); + void SetVectorVariableValue(const char* variableName, + const double values[3]) { + this->SetVectorVariableValue(variableName,values[0],values[1],values[2]);}; + void SetVectorVariableValue(int i, double xValue, double yValue, + double zValue); + void SetVectorVariableValue(int i, const double values[3]) { + this->SetVectorVariableValue(i,values[0],values[1],values[2]);}; + + // Description: + // Get the value of a vector variable. + double* GetVectorVariableValue(const char* variableName); + void GetVectorVariableValue(const char* variableName, double value[3]) { + double *r = this->GetVectorVariableValue(variableName); + value[0] = r[0]; value[1] = r[1]; value[2] = r[2]; }; + double* GetVectorVariableValue(int i); + void GetVectorVariableValue(int i, double value[3]) { + double *r = this->GetVectorVariableValue(i); + value[0] = r[0]; value[1] = r[1]; value[2] = r[2]; }; + + // Description: + // Get the number of scalar variables. + vtkGetMacro(NumberOfScalarVariables,int); + + // Description: + // Get the number of vector variables. + vtkGetMacro(NumberOfVectorVariables,int); + + // Description: + // Get the ith scalar variable name. + char* GetScalarVariableName(int i); + + // Description: + // Get the ith vector variable name. + char* GetVectorVariableName(int i); + + // Description: + // Remove all the current variables. + void RemoveAllVariables(); + + // Description: + // When ReplaceInvalidValues is on, all invalid values (such as + // sqrt(-2), note that function parser does not handle complex + // numbers) will be replaced by ReplacementValue. Otherwise an + // error will be reported + vtkSetMacro(ReplaceInvalidValues,int); + vtkGetMacro(ReplaceInvalidValues,int); + vtkBooleanMacro(ReplaceInvalidValues,int); + vtkSetMacro(ReplacementValue,double); + vtkGetMacro(ReplacementValue,double); + +protected: + vtkFunctionParser(); + ~vtkFunctionParser(); + + int Parse(); + void Evaluate(); + + int CheckSyntax(); + void RemoveSpaces(); + char* RemoveSpacesFrom(const char* variableName); + int OperatorWithinVariable(int idx); + + int BuildInternalFunctionStructure(); + void BuildInternalSubstringStructure(int beginIndex, int endIndex); + void AddInternalByte(unsigned char newByte); + + int IsSubstringCompletelyEnclosed(int beginIndex, int endIndex); + int FindEndOfMathFunction(int beginIndex); + int FindEndOfMathConstant(int beginIndex); + + int IsVariableName(int currentIndex); + int IsElementaryOperator(int op); + + int GetMathFunctionNumber(int currentIndex); + int GetMathFunctionStringLength(int mathFunctionNumber); + int GetMathConstantNumber(int currentIndex); + int GetMathConstantStringLength(int mathConstantNumber); + int GetElementaryOperatorNumber(char op); + int GetOperandNumber(int currentIndex); + int GetVariableNameLength(int variableNumber); + + int DisambiguateOperators(); + + char* Function; + int FunctionLength; + int NumberOfScalarVariables; + int NumberOfVectorVariables; + char** ScalarVariableNames; + char** VectorVariableNames; + double* ScalarVariableValues; + double** VectorVariableValues; + unsigned char *ByteCode; + int ByteCodeSize; + double *Immediates; + int ImmediatesSize; + double *Stack; + int StackSize; + int StackPointer; + + vtkTimeStamp FunctionMTime; + vtkTimeStamp ParseMTime; + vtkTimeStamp VariableMTime; + vtkTimeStamp EvaluateMTime; + + int ReplaceInvalidValues; + double ReplacementValue; + +private: + vtkFunctionParser(const vtkFunctionParser&); // Not implemented. + void operator=(const vtkFunctionParser&); // Not implemented. +}; + +#endif diff --git a/Common/vtkFunctionSet.cxx b/Common/vtkFunctionSet.cxx new file mode 100644 index 0000000..71d33b5 --- /dev/null +++ b/Common/vtkFunctionSet.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFunctionSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFunctionSet.h" + +vtkCxxRevisionMacro(vtkFunctionSet, "$Revision: 1.5 $"); + +vtkFunctionSet::vtkFunctionSet() +{ + this->NumFuncs = 0; + this->NumIndepVars = 0; +} + +void vtkFunctionSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Number of functions: " << this->NumFuncs + << "\n"; + os << indent << "Number of independant variables: " << this->NumIndepVars + << "\n"; +} diff --git a/Common/vtkFunctionSet.h b/Common/vtkFunctionSet.h new file mode 100644 index 0000000..0994694 --- /dev/null +++ b/Common/vtkFunctionSet.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFunctionSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFunctionSet - Abstract inteface for sets of functions +// .SECTION Description +// vtkFunctionSet specifies an abstract interface for set of functions +// of the form F_i = F_i(x_j) where F (with i=1..m) are the functions +// and x (with j=1..n) are the independent variables. +// The only supported operation is the function evaluation at x_j. + +// .SECTION See Also +// vtkImplicitDataSet vtkInterpolatedVelocityField +// vtkInitialValueProblemSolver + +#ifndef __vtkFunctionSet_h +#define __vtkFunctionSet_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkFunctionSet : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkFunctionSet,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Evaluate functions at x_j. + // x and f have to point to valid double arrays of appropriate + // sizes obtained with GetNumberOfFunctions() and + // GetNumberOfIndependentVariables. + virtual int FunctionValues(double* x, double* f) = 0; + + // Description: + // Return the number of functions. Note that this is constant for + // a given type of set of functions and can not be changed at + // run time. + virtual int GetNumberOfFunctions() { + return this->NumFuncs; } + + // Description: + // Return the number of independent variables. Note that this is + // constant for a given type of set of functions and can not be changed + // at run time. + virtual int GetNumberOfIndependentVariables() { + return this->NumIndepVars; } + +protected: + vtkFunctionSet(); + ~vtkFunctionSet() {}; + + int NumFuncs; + int NumIndepVars; + +private: + vtkFunctionSet(const vtkFunctionSet&); // Not implemented. + void operator=(const vtkFunctionSet&); // Not implemented. +}; + +#endif + + + + + diff --git a/Common/vtkGarbageCollector.cxx b/Common/vtkGarbageCollector.cxx new file mode 100644 index 0000000..5b656f9 --- /dev/null +++ b/Common/vtkGarbageCollector.cxx @@ -0,0 +1,1078 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGarbageCollector.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGarbageCollector.h" + +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkSmartPointerBase.h" + +#include +#include +#include + +// Leave the hashing version off for now. +#define VTK_GARBAGE_COLLECTOR_HASH 0 + +#if VTK_GARBAGE_COLLECTOR_HASH +# include +# include +#else +# include +# include +#endif + +#include + +vtkCxxRevisionMacro(vtkGarbageCollector, "$Revision: 1.28.4.2 $"); +vtkStandardNewMacro(vtkGarbageCollector); + +#if VTK_GARBAGE_COLLECTOR_HASH +struct vtkGarbageCollectorHash +{ + size_t operator()(void* p) const { return reinterpret_cast(p); } +}; +#endif + +class vtkGarbageCollectorSingleton; + +//---------------------------------------------------------------------------- +// The garbage collector singleton. In order to support delayed +// collection vtkObjectBase::UnRegister passes references to the +// singleton instead of decrementing the reference count. At some +// point collection occurs and accounts for these references. This +// MUST be default initialized to zero by the compiler and is +// therefore not initialized here. The ClassInitialize and +// ClassFinalize methods handle this instance. +static vtkGarbageCollectorSingleton* vtkGarbageCollectorSingletonInstance; + +//---------------------------------------------------------------------------- +// Global debug setting. This flag specifies whether a collector +// should print debugging output. This must be default initialized to +// zero by the compiler and is therefore not initialized here. The +// ClassInitialize and ClassFinalize methods handle it. +static int vtkGarbageCollectorGlobalDebugFlag; + +//---------------------------------------------------------------------------- +// The thread identifier of the main thread. Delayed garbage +// collection is supported only for objects in the main thread. This +// is initialized when the program loads. All garbage collection +// calls test whether they are called from this thread. If not, no +// references are accepted by the singleton. This must be default +// initialized to zero by the compiler and is therefore not +// initialized here. The ClassInitialize and ClassFinalize methods +// handle it. +static vtkMultiThreaderIDType vtkGarbageCollectorMainThread; + +//---------------------------------------------------------------------------- +vtkGarbageCollector::vtkGarbageCollector() +{ +} + +//---------------------------------------------------------------------------- +vtkGarbageCollector::~vtkGarbageCollector() +{ + this->SetReferenceCount(0); +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::SetGlobalDebugFlag(int flag) +{ + vtkGarbageCollectorGlobalDebugFlag = flag; +} + +//---------------------------------------------------------------------------- +int vtkGarbageCollector::GetGlobalDebugFlag() +{ + return vtkGarbageCollectorGlobalDebugFlag; +} + +//---------------------------------------------------------------------------- +// Friendship interface listing non-public methods the garbage +// collector can call on vtkObjectBase. +class vtkGarbageCollectorToObjectBaseFriendship +{ +public: + static void ReportReferences(vtkGarbageCollector* self, vtkObjectBase* obj) + { + obj->ReportReferences(self); + } + static void RegisterBase(vtkObjectBase* obj) + { + // Call vtkObjectBase::RegisterInternal directly to make sure the + // object does not try to report the call back to the garbage + // collector and no debugging output is shown. + obj->vtkObjectBase::RegisterInternal(0, 0); + } + static void UnRegisterBase(vtkObjectBase* obj) + { + // Call vtkObjectBase::UnRegisterInternal directly to make sure + // the object does not try to report the call back to the garbage + // collector and no debugging output is shown. + obj->vtkObjectBase::UnRegisterInternal(0, 0); + } + static void Register(vtkObjectBase* obj, vtkObjectBase* from) + { + // Call RegisterInternal directly to make sure the object does not + // try to report the call back to the garbage collector. + obj->RegisterInternal(from, 0); + } + static void UnRegister(vtkObjectBase* obj, vtkObjectBase* from) + { + // Call UnRegisterInternal directly to make sure the object does + // not try to report the call back to the garbage collector. + obj->UnRegisterInternal(from, 0); + } +}; + +//---------------------------------------------------------------------------- +// Function to test whether caller is the main thread. +static int vtkGarbageCollectorIsMainThread() +{ + return + vtkMultiThreader::ThreadsEqual(vtkGarbageCollectorMainThread, + vtkMultiThreader::GetCurrentThreadID()); +} + +//---------------------------------------------------------------------------- +// Singleton to hold discarded references. +class vtkGarbageCollectorSingleton +{ +public: + vtkGarbageCollectorSingleton(); + ~vtkGarbageCollectorSingleton(); + + // Internal implementation of vtkGarbageCollector::GiveReference. + int GiveReference(vtkObjectBase* obj); + + // Internal implementation of vtkGarbageCollector::TakeReference. + int TakeReference(vtkObjectBase* obj); + + // Called by GiveReference to decide whether to accept a reference. + int CheckAccept(); + + // Push/Pop deferred collection. + void DeferredCollectionPush(); + void DeferredCollectionPop(); + + // Map from object to number of stored references. +#if VTK_GARBAGE_COLLECTOR_HASH + typedef vtksys::hash_map + ReferencesType; +#else + typedef vtkstd::map ReferencesType; +#endif + ReferencesType References; + + // The number of references stored in the map. + int TotalNumberOfReferences; + + // The number of times DeferredCollectionPush has been called not + // matched by a DeferredCollectionPop. + int DeferredCollectionCount; +}; + +//---------------------------------------------------------------------------- +// Internal implementation subclass. +class vtkGarbageCollectorImpl: public vtkGarbageCollector +{ +public: + vtkTypeMacro(vtkGarbageCollectorImpl, vtkGarbageCollector); + + vtkGarbageCollectorImpl(); + ~vtkGarbageCollectorImpl(); + + // Description: + // Prevent normal vtkObject reference counting behavior. + virtual void Register(vtkObjectBase*); + + // Description: + // Prevent normal vtkObject reference counting behavior. + virtual void UnRegister(vtkObjectBase*); + + // Perform a collection check. + void CollectInternal(vtkObjectBase* root); + + +// Sun's compiler is broken and does not allow access to protected members from +// nested class +// protected: + //-------------------------------------------------------------------------- + // Internal data structure types. + +#if VTK_GARBAGE_COLLECTOR_HASH + typedef vtksys::hash_map + ReferencesType; +#else + typedef vtkstd::map ReferencesType; +#endif + struct ComponentType; + + struct Entry; + struct EntryEdge + { + Entry* Reference; + void* Pointer; + EntryEdge(Entry* r, void* p): Reference(r), Pointer(p) {} + }; + + // Store garbage collection entries keyed by object. + struct Entry + { + Entry(vtkObjectBase* obj): Object(obj), Root(0), Component(0), + VisitOrder(0), Count(0), GarbageCount(0), + References() {} + ~Entry() { assert(this->GarbageCount == 0); } + + // The object corresponding to this entry. + vtkObjectBase* Object; + + // The candidate root for the component containing this object. + Entry* Root; + + // The component to which the object is assigned, if any. + ComponentType* Component; + + // Mark the order in which object's are visited by Tarjan's algorithm. + int VisitOrder; + + // The number of references from outside the component not + // counting the garbage collector references. + int Count; + + // The number of references held by the garbage collector. + int GarbageCount; + + // The list of references reported by this entry's object. + typedef vtkstd::vector ReferencesType; + ReferencesType References; + }; + + // Compare entries by object pointer for quick lookup. +#if VTK_GARBAGE_COLLECTOR_HASH + struct EntryCompare + { + vtkstd_bool operator()(Entry* l, Entry* r) const + { return l->Object == r->Object; } + }; + struct EntryHash + { + size_t operator()(Entry* e) const + { return e?reinterpret_cast(e->Object):0; } + }; +#else + struct EntryCompare + { + vtkstd::less Compare; + vtkstd_bool operator()(Entry* l, Entry* r) const + { return Compare(l->Object, r->Object); } + }; +#endif + + // Represent a strongly connected component of the reference graph. + typedef vtkstd::vector ComponentBase; + struct ComponentType: public ComponentBase + { + typedef ComponentBase::iterator iterator; + ComponentType(): NetCount(0), Identifier(0) {} + ~ComponentType() + { for(iterator i = begin(); i != end(); ++i) { (*i)->Component = 0; } } + + // The net reference count of the component. + int NetCount; + + // The component identifier. + int Identifier; + }; + + //-------------------------------------------------------------------------- + // Internal data objects. + + // The set of objects that have been visited. +#if VTK_GARBAGE_COLLECTOR_HASH + typedef vtksys::hash_set VisitedType; +#else + typedef vtkstd::set VisitedType; +#endif + VisitedType Visited; + + // Count the number of components found to give each an identifier + // for use in debugging messages. + int NumberOfComponents; + + // The set of components found that have not yet leaked. +#if VTK_GARBAGE_COLLECTOR_HASH + typedef vtksys::hash_set + ComponentsType; +#else + typedef vtkstd::set ComponentsType; +#endif + ComponentsType ReferencedComponents; + + // Queue leaked components for deletion. + vtkstd::queue LeakedComponents; + + // The stack of objects forming the connected components. This is + // used in the implementation of Tarjan's algorithm. + vtkstd::stack Stack; + + // The object whose references are currently being traced by + // Tarjan's algorithm. Used during the ReportReferences callback. + Entry* Current; + + // Count for visit order of Tarjan's algorithm. + int VisitCount; + + // The singleton instance from which to take references when passing + // references to the entries. + vtkGarbageCollectorSingleton* Singleton; + + //-------------------------------------------------------------------------- + // Internal implementation methods. + + // Walk the reference graph using Tarjan's algorithm to identify + // strongly connected components. + void FindComponents(vtkObjectBase* root); + + // Get the entry for the given object. This may visit the object. + Entry* MaybeVisit(vtkObjectBase*); + + // Node visitor for Tarjan's algorithm. + Entry* VisitTarjan(vtkObjectBase*); + + // Callback from objects to report references. + void Report(vtkObjectBase* obj, void* ptr); + virtual void Report(vtkObjectBase* obj, void* ptr, const char* desc); + + // Collect the objects of the given leaked component. + void CollectComponent(ComponentType* c); + + // Print the given component as a debugging message. + void PrintComponent(ComponentType* c); + + // Subtract references the component holds to itself. + void SubtractInternalReferences(ComponentType* c); + + // Subtract references the component holds to other components. + void SubtractExternalReferences(ComponentType* c); + + // Subtract one reference from the given entry. If the entry's + // component is left with no references, it is queued as a leaked + // component. + void SubtractReference(Entry* e); + + // Transfer references from the garbage collector to the entry for + // its object. + void PassReferencesToEntry(Entry* e); + + // Flush all collector references to the object in an entry. + void FlushEntryReferences(Entry* e); + +private: + vtkGarbageCollectorImpl(const vtkGarbageCollectorImpl&); // Not implemented. + void operator=(const vtkGarbageCollectorImpl&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +vtkGarbageCollectorImpl::vtkGarbageCollectorImpl() +{ + // Set debugging state. + this->SetDebug(vtkGarbageCollectorGlobalDebugFlag); + + // Take references from the singleton only in the main thread. + if(vtkGarbageCollectorIsMainThread()) + { + this->Singleton = vtkGarbageCollectorSingletonInstance; + } + else + { + this->Singleton = 0; + } + + // Initialize reference graph walk implementation. + this->VisitCount = 0; + this->Current = 0; + this->NumberOfComponents = 0; +} + +//---------------------------------------------------------------------------- +vtkGarbageCollectorImpl::~vtkGarbageCollectorImpl() +{ + // The collector implementation should have left these empty. + assert(this->Current == 0); + assert(this->Stack.empty()); + assert(this->LeakedComponents.empty()); + + // Clear component list. + for(ComponentsType::iterator c = this->ReferencedComponents.begin(); + c != this->ReferencedComponents.end(); ++c) + { + delete *c; + } + this->ReferencedComponents.clear(); + + // Clear visited list. + for(VisitedType::iterator v = this->Visited.begin(); + v != this->Visited.end();) + { + // Increment the iterator before deleting because the hash table + // compare function dereferences the pointer. + delete *v++; + } + this->Visited.clear(); + + // Disable debugging to avoid destruction message. + this->SetDebug(0); +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::Register(vtkObjectBase*) +{ +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::UnRegister(vtkObjectBase*) +{ +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::CollectInternal(vtkObjectBase* root) +{ + // Identify strong components. + this->FindComponents(root); + + // Delete all the leaked components. + while(!this->LeakedComponents.empty()) + { + // Get the next leaked component. + ComponentType* c = this->LeakedComponents.front(); + this->LeakedComponents.pop(); + + // Subtract this component's references to other components. This + // may cause others to be queued. + this->SubtractExternalReferences(c); + + // Collect the members of this component. + this->CollectComponent(c); + + // We are done with this component. + delete c; + } + + // Print remaining referenced components for debugging. + for(ComponentsType::iterator i = this->ReferencedComponents.begin(); + i != this->ReferencedComponents.end(); ++i) + { + this->PrintComponent(*i); + } + + // Flush remaining references owned by entries in referenced + // components. + for(ComponentsType::iterator c = this->ReferencedComponents.begin(); + c != this->ReferencedComponents.end(); ++c) + { + for(ComponentType::iterator j = (*c)->begin(); j != (*c)->end(); ++j) + { + this->FlushEntryReferences(*j); + } + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::FindComponents(vtkObjectBase* root) +{ + // Walk the references from the given object, if any. + if(root) + { + this->MaybeVisit(root); + } +} + +//---------------------------------------------------------------------------- +vtkGarbageCollectorImpl::Entry* +vtkGarbageCollectorImpl::MaybeVisit(vtkObjectBase* obj) +{ + // Check for an existing entry. + assert(obj != 0); + Entry e(obj); + VisitedType::iterator i = this->Visited.find(&e); + if(i == this->Visited.end()) + { + // Visit the object to create the entry. + return this->VisitTarjan(obj); + } + // else Return the existing entry. + return *i; +} + +//---------------------------------------------------------------------------- +vtkGarbageCollectorImpl::Entry* +vtkGarbageCollectorImpl::VisitTarjan(vtkObjectBase* obj) +{ + // Create an entry for the object. + Entry* v = new Entry(obj); + this->Visited.insert(v); + + // Initialize the entry and push it onto the stack of graph nodes. + v->Root = v; + v->Component = 0; + v->VisitOrder = ++this->VisitCount; + this->PassReferencesToEntry(v); + this->Stack.push(v); + + vtkDebugMacro("Requesting references from " + << v->Object->GetClassName() << "(" + << v->Object << ") with reference count " + << (v->Object->GetReferenceCount()-v->GarbageCount)); + + // Process the references from this node. + Entry* saveCurrent = this->Current; + this->Current = v; + vtkGarbageCollectorToObjectBaseFriendship::ReportReferences(this, v->Object); + this->Current = saveCurrent; + + // Check if we have found a component. + if(v->Root == v) + { + // Found a new component. + ComponentType* c = new ComponentType; + c->Identifier = ++this->NumberOfComponents; + Entry* w; + do + { + // Get the next member of the component. + w = this->Stack.top(); + this->Stack.pop(); + + // Assign the member to the component. + w->Component = c; + w->Root = v; + c->push_back(w); + + // Include this member's reference count in the component total. + c->NetCount += w->Count; + } while(w != v); + + // Save the component. + this->ReferencedComponents.insert(c); + + // Print the component for debugging. + this->PrintComponent(c); + + // Remove internal references from the component. + this->SubtractInternalReferences(c); + } + + return v; +} + +//---------------------------------------------------------------------------- +#ifdef VTK_LEAN_AND_MEAN +void vtkGarbageCollectorImpl::Report(vtkObjectBase* obj, void* ptr, + const char*) +{ + // All calls should be given the pointer. + assert(ptr != 0); + + // Forward call to the internal implementation. + if(obj) + { + this->Report(obj, ptr); + } +} +#else +void vtkGarbageCollectorImpl::Report(vtkObjectBase* obj, void* ptr, + const char* desc) +{ + // All calls should be given the pointer. + assert(ptr != 0); + + if(obj) + { + // Report debugging information if requested. + if(this->Debug && vtkObject::GetGlobalWarningDisplay()) + { + vtkObjectBase* current = this->Current->Object; + ostrstream msg; + msg << "Report: " + << current->GetClassName() << "(" << current << ") " + << (desc?desc:"") + << " -> " << obj->GetClassName() << "(" << obj << ")"; + msg << ends; + vtkDebugMacro(<< msg.str()); + msg.rdbuf()->freeze(0); + } + + // Forward call to the internal implementation. + this->Report(obj, ptr); + } +} +#endif + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::Report(vtkObjectBase* obj, void* ptr) +{ + // Get the source and destination of this reference. + Entry* v = this->Current; + Entry* w = this->MaybeVisit(obj); + + // If the destination has not yet been assigned to a component, + // check if it is a better potential root for the current object. + if(!w->Component) + { + if(w->Root->VisitOrder < v->Root->VisitOrder) + { + v->Root = w->Root; + } + } + + // Save this reference. + v->References.push_back(EntryEdge(w, ptr)); +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::CollectComponent(ComponentType* c) +{ + ComponentType::iterator e; + + // Print out the component for debugging. + this->PrintComponent(c); + + // Get an extra reference to all objects in the component so that + // they are not deleted until all references are removed. + for(e = c->begin(); e != c->end(); ++e) + { + vtkGarbageCollectorToObjectBaseFriendship::Register((*e)->Object, this); + } + + // Disconnect the reference graph. + for(e = c->begin(); e != c->end(); ++e) + { + // Loop over all references made by this entry's object. + Entry* entry = *e; + for(unsigned int i = 0; i < entry->References.size(); ++i) + { + // Get a pointer to the object referenced. + vtkObjectBase* obj = entry->References[i].Reference->Object; + + // Get a pointer to the pointer holding the reference. + void** ptr = static_cast(entry->References[i].Pointer); + + // Set the pointer holding the reference to NULL. The + // destructor of the object that reported this reference must + // deal with this. + *ptr = 0; + + // Remove the reference to the object referenced without + // recursively collecting. We already know about the object. + vtkGarbageCollectorToObjectBaseFriendship::UnRegister(obj, + entry->Object); + } + } + + // Remove the Entries' references to objects. + for(e = c->begin(); e != c->end(); ++e) + { + this->FlushEntryReferences(*e); + } + + // Only our extra reference to each object remains. Delete the + // objects. + for(e = c->begin(); e != c->end(); ++e) + { + assert((*e)->Object->GetReferenceCount() == 1); + vtkGarbageCollectorToObjectBaseFriendship::UnRegister((*e)->Object, this); + } +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEAN_AND_MEAN +void vtkGarbageCollectorImpl::PrintComponent(ComponentType* c) +{ + if(this->Debug && vtkObject::GetGlobalWarningDisplay()) + { + ostrstream msg; + msg << "Identified strongly connected component " + << c->Identifier << " with net reference count " + << c->NetCount << ":"; + for(ComponentType::iterator i = c->begin(); i != c->end(); ++i) + { + vtkObjectBase* obj = (*i)->Object; + int count = (*i)->Count; + msg << "\n " << obj->GetClassName() << "(" << obj << ")" + << " with " << count << " external " + << ((count == 1)? "reference" : "references"); + } + msg << ends; + vtkDebugMacro(<< msg.str()); + msg.rdbuf()->freeze(0); + } +} +#else +void vtkGarbageCollectorImpl::PrintComponent(ComponentType*) +{ +} +#endif + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::SubtractInternalReferences(ComponentType* c) +{ + // Loop over all members of the component. + for(ComponentType::iterator i = c->begin(); i != c->end(); ++i) + { + Entry* v = *i; + + // Loop over all references from this member. + for(Entry::ReferencesType::iterator r = v->References.begin(); + r != v->References.end(); ++r) + { + Entry* w = r->Reference; + + // If this reference points inside the component, subtract it. + if(v->Component == w->Component) + { + this->SubtractReference(w); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::SubtractExternalReferences(ComponentType* c) +{ + // Loop over all members of the component. + for(ComponentType::iterator i = c->begin(); i != c->end(); ++i) + { + Entry* v = *i; + + // Loop over all references from this member. + for(Entry::ReferencesType::iterator r = v->References.begin(); + r != v->References.end(); ++r) + { + Entry* w = r->Reference; + + // If this reference points outside the component, subtract it. + if(v->Component != w->Component) + { + this->SubtractReference(w); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::SubtractReference(Entry* e) +{ + // The component should not be leaked before we get here. + assert(e->Component != 0); + assert(e->Component->NetCount > 0); + + vtkDebugMacro("Subtracting reference to object " + << e->Object->GetClassName() << "(" << e->Object << ")" + << " in component " << e->Component->Identifier << "."); + + // Decrement the entry's reference count. + --e->Count; + + // If the component's net count is now zero, move it to the queue of + // leaked component. + if(--e->Component->NetCount == 0) + { + this->ReferencedComponents.erase(e->Component); + this->LeakedComponents.push(e->Component); + vtkDebugMacro("Component " << e->Component->Identifier << " is leaked."); + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::PassReferencesToEntry(Entry* e) +{ + // Get the number of references the collector holds. + e->GarbageCount = 0; + if(this->Singleton) + { + ReferencesType::iterator i = this->Singleton->References.find(e->Object); + if(i != this->Singleton->References.end()) + { + // Pass these references from the singleton to the entry. + e->GarbageCount = i->second; + this->Singleton->References.erase(i); + this->Singleton->TotalNumberOfReferences -= e->GarbageCount; + } + } + + // Make sure the entry has at least one reference to the object. + // This ensures the object in components of size 1 is not deleted + // until we delete the component. + if(e->GarbageCount == 0) + { + vtkGarbageCollectorToObjectBaseFriendship::RegisterBase(e->Object); + ++e->GarbageCount; + } + + // Subtract the garbage count from the object's reference count. + e->Count = e->Object->GetReferenceCount() - e->GarbageCount; +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorImpl::FlushEntryReferences(Entry* e) +{ + while(e->GarbageCount > 0) + { + vtkGarbageCollectorToObjectBaseFriendship::UnRegisterBase(e->Object); + --e->GarbageCount; + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::ClassInitialize() +{ + // Set default debugging state. + vtkGarbageCollectorGlobalDebugFlag = 0; + + // Record the id of the main thread. + vtkGarbageCollectorMainThread = vtkMultiThreader::GetCurrentThreadID(); + + // Allocate the singleton used for delayed collection in the main + // thread. + vtkGarbageCollectorSingletonInstance = new vtkGarbageCollectorSingleton; +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::ClassFinalize() +{ + // We are done with the singleton. Delete it and reset the pointer. + // Other singletons may still cause garbage collection of VTK + // objects, they just will not have the option of deferred + // collection. In order to get it they need only to include + // vtkGarbageCollectorManager.h so that this singleton stays around + // longer. + delete vtkGarbageCollectorSingletonInstance; + vtkGarbageCollectorSingletonInstance = 0; +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::Report(vtkObjectBase*, void*, const char*) +{ + vtkErrorMacro("vtkGarbageCollector::Report should be overridden."); +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::Collect() +{ + // This must be called only from the main thread. + assert(vtkGarbageCollectorIsMainThread()); + + // Keep collecting until no deferred checks exist. + while(vtkGarbageCollectorSingletonInstance && + vtkGarbageCollectorSingletonInstance->TotalNumberOfReferences > 0) + { + // Collect starting from one deferred object at a time. Each + // check will remove at least the starting object and possibly + // other objects from the singleton's references. + vtkObjectBase* root = + vtkGarbageCollectorSingletonInstance->References.begin()->first; + vtkGarbageCollector::Collect(root); + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::Collect(vtkObjectBase* root) +{ + // Create a collector instance. + vtkGarbageCollectorImpl collector; + + vtkDebugWithObjectMacro((&collector), "Starting collection check."); + + // Collect leaked objects. + collector.CollectInternal(root); + + vtkDebugWithObjectMacro((&collector), "Finished collection check."); +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::DeferredCollectionPush() +{ + // This must be called only from the main thread. + assert(vtkGarbageCollectorIsMainThread()); + + // Forward the call to the singleton. + if(vtkGarbageCollectorSingletonInstance) + { + vtkGarbageCollectorSingletonInstance->DeferredCollectionPush(); + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollector::DeferredCollectionPop() +{ + // This must be called only from the main thread. + assert(vtkGarbageCollectorIsMainThread()); + + // Forward the call to the singleton. + if(vtkGarbageCollectorSingletonInstance) + { + vtkGarbageCollectorSingletonInstance->DeferredCollectionPop(); + } +} + +//---------------------------------------------------------------------------- +int vtkGarbageCollector::GiveReference(vtkObjectBase* obj) +{ + // We must have an object. + assert(obj != 0); + + // See if the singleton will accept a reference. + if(vtkGarbageCollectorIsMainThread() && + vtkGarbageCollectorSingletonInstance) + { + return vtkGarbageCollectorSingletonInstance->GiveReference(obj); + } + + // Could not accept the reference. + return 0; +} + +//---------------------------------------------------------------------------- +int vtkGarbageCollector::TakeReference(vtkObjectBase* obj) +{ + // We must have an object. + assert(obj != 0); + + // See if the singleton has a reference. + if(vtkGarbageCollectorIsMainThread() && + vtkGarbageCollectorSingletonInstance) + { + return vtkGarbageCollectorSingletonInstance->TakeReference(obj); + } + + // No reference is available. + return 0; +} + +//---------------------------------------------------------------------------- +vtkGarbageCollectorSingleton::vtkGarbageCollectorSingleton() +{ + this->TotalNumberOfReferences = 0; + this->DeferredCollectionCount = 0; +} + +//---------------------------------------------------------------------------- +vtkGarbageCollectorSingleton::~vtkGarbageCollectorSingleton() +{ + // There should be no deferred collections left. + assert(this->TotalNumberOfReferences == 0); +} + +//---------------------------------------------------------------------------- +int vtkGarbageCollectorSingleton::GiveReference(vtkObjectBase* obj) +{ + // Check if we can store a reference to the object in the map. + if(this->CheckAccept()) + { + // Create a reference to the object. + ReferencesType::iterator i = this->References.find(obj); + if(i == this->References.end()) + { + // This is a new object. Create a map entry for it. + this->References.insert(ReferencesType::value_type(obj, 1)); + } + else + { + ++i->second; + } + ++this->TotalNumberOfReferences; + return 1; + } + + // We did not accept the reference. + return 0; +} + +//---------------------------------------------------------------------------- +int vtkGarbageCollectorSingleton::TakeReference(vtkObjectBase* obj) +{ + // If we have a reference to the object hand it back to the caller. + ReferencesType::iterator i = this->References.find(obj); + if(i != this->References.end()) + { + // Remove our reference to the object. + --this->TotalNumberOfReferences; + if(--i->second == 0) + { + // If we have no more references to the object, remove its map + // entry. + this->References.erase(i); + } + return 1; + } + + // We do not have a reference to the object. + return 0; +} + +//---------------------------------------------------------------------------- +int vtkGarbageCollectorSingleton::CheckAccept() +{ + // Accept the reference only if deferred collection is enabled. It + // is tempting to put a check against TotalNumberOfReferences here + // to collect every so many deferred calls, but this will NOT work. + // Some objects call UnRegister on other objects during + // construction. We do not want to perform deferred collection + // while an object is under construction because the reference walk + // might call ReportReferences on a partially constructed object! + return this->DeferredCollectionCount > 0; +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorSingleton::DeferredCollectionPush() +{ + if(++this->DeferredCollectionCount <= 0) + { + // Deferred collection is disabled. Collect immediately. + vtkGarbageCollector::Collect(); + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorSingleton::DeferredCollectionPop() +{ + if(--this->DeferredCollectionCount <= 0) + { + // Deferred collection is disabled. Collect immediately. + vtkGarbageCollector::Collect(); + } +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorReportInternal(vtkGarbageCollector* collector, + vtkObjectBase* obj, void* ptr, + const char* desc) +{ + collector->Report(obj, ptr, desc); +} + +//---------------------------------------------------------------------------- +void vtkGarbageCollectorReport(vtkGarbageCollector* collector, + vtkSmartPointerBase& ptr, + const char* desc) +{ + ptr.Report(collector, desc); +} diff --git a/Common/vtkGarbageCollector.h b/Common/vtkGarbageCollector.h new file mode 100644 index 0000000..d954a64 --- /dev/null +++ b/Common/vtkGarbageCollector.h @@ -0,0 +1,203 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGarbageCollector.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGarbageCollector - Detect and break reference loops +// .SECTION Description +// vtkGarbageCollector is used by VTK classes that may be involved in +// reference counting loops (such as Algorithm <-> Executive). It +// detects strongly connected components of the reference graph that +// have been leaked deletes them. The garbage collector uses the +// ReportReferences method to search the reference graph and construct +// a net reference count for each connected component. If the net +// reference count is zero the entire set of objects is deleted. +// Deleting each component may leak other components, which are then +// collected recursively. +// +// To enable garbage collection for a class, add these members: +// +// \code +// +// public: +// virtual void Register(vtkObjectBase* o) +// { +// this->RegisterInternal(o, 1); +// } +// virtual void UnRegister(vtkObjectBase* o) +// { +// this->UnRegisterInternal(o, 1); +// } +// +// protected: +// +// virtual void ReportReferences(vtkGarbageCollector* collector) +// { +// // Report references held by this object that may be in a loop. +// this->Superclass::ReportReferences(collector); +// vtkGarbageCollectorReport(collector, this->OtherObject, "Other Object"); +// } +// \endcode +// +// The implementations should be in the .cxx file in practice. +// It is important that the reference be reported using the real +// pointer or smart pointer instance that holds the reference. When +// collecting the garbage collector will actually set this pointer to +// NULL. The destructor of the class should be written to deal with +// this. It is also expected that an invariant is maintained for any +// reference that is reported. The variable holding the reference +// must always either be NULL or refer to a fully constructed valid +// object. Therefore code like "this->Object->UnRegister(this)" must +// be avoided if "this->Object" is a reported reference because it +// is possible that the object is deleted before UnRegister returns +// but then "this->Object" will be left as a dangling pointer. Instead +// use code like +// +// vtkObjectBase* obj = this->Object; +// this->Object = 0; +// obj->UnRegister(this); +// +// so that the reported reference maintains the invariant. +// +// If subclassing from a class that already supports garbage +// collection, one need only provide the ReportReferences method. + +#ifndef __vtkGarbageCollector_h +#define __vtkGarbageCollector_h + +#include "vtkObject.h" +#include "vtkGarbageCollectorManager.h" // Needed for singleton initialization. + +// This function is a friend of the collector so that it can call the +// internal report method. +void VTK_COMMON_EXPORT +vtkGarbageCollectorReportInternal(vtkGarbageCollector*, + vtkObjectBase*, void*, + const char*); + +// This allows vtkObjectBase to get at the methods it needs. +class vtkObjectBaseToGarbageCollectorFriendship; + +class VTK_COMMON_EXPORT vtkGarbageCollector : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkGarbageCollector,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkGarbageCollector* New(); + + // Description: + // Collect immediately using any objects whose collection was + // previously deferred as a root for the reference graph walk. + // Strongly connected components in the reference graph are + // identified. Those with a net reference count of zero are + // deleted. When a component is deleted it may remove references to + // other components that are not part of the same reference loop but + // are held by objects in the original component. These removed + // references are handled as any other and their corresponding + // checks may be deferred. This method keeps collecting until no + // deferred collection checks remain. + static void Collect(); + + // Description: + // Collect immediately using the given object as the root for a + // reference graph walk. Strongly connected components in the + // reference graph are identified. Those with a net reference count + // of zero are deleted. When a component is deleted it may remove + // references to other components that are not part of the same + // reference loop but are held by objects in the original component. + // These removed references are handled as any other and their + // corresponding checks may be deferred. This method does continue + // collecting in this case. + static void Collect(vtkObjectBase* root); + + // Description: + // Push/Pop whether to do deferred collection. Whenever the total + // number of pushes exceeds the total number of pops collection will + // be deferred. Code can call the Collect method directly to force + // collection. + static void DeferredCollectionPush(); + static void DeferredCollectionPop(); + + // Description: + // Set/Get global garbage collection debugging flag. When set to 1, + // all garbage collection checks will produce debugging information. + static void SetGlobalDebugFlag(int flag); + static int GetGlobalDebugFlag(); + +protected: + vtkGarbageCollector(); + ~vtkGarbageCollector(); + +private: + + // Description: + // Called by UnRegister method of an object that supports garbage + // collection. The UnRegister may not actually decrement the + // reference count, but instead hands the reference to the garbage + // collector. If a reference can be given, this method accepts it + // from the caller by returning 1. If the reference cannot be + // accepted then it returns 0. This may be the case when delayed + // garbage collection is disabled, or when the collector has decided + // it is time to do a check. + static int GiveReference(vtkObjectBase* obj); + + // Description: + // Called by Register method of an object that supports garbage + // collection. The Register may not actually increment the + // reference count if it can take a reference previously handed to + // the garbage collector. If a reference can be taken, this method + // hands it back to the caller by returning 1. If no reference is + // available, returns 0. + static int TakeReference(vtkObjectBase* obj); + + // Singleton management functions. + static void ClassInitialize(); + static void ClassFinalize(); + + //BTX + friend class vtkGarbageCollectorManager; + friend class vtkObjectBaseToGarbageCollectorFriendship; + //ETX + + // Internal report callback and friend function that calls it. + virtual void Report(vtkObjectBase* obj, void* ptr, const char* desc); + friend void VTK_COMMON_EXPORT + vtkGarbageCollectorReportInternal(vtkGarbageCollector*, + vtkObjectBase*, void*, + const char*); + +private: + vtkGarbageCollector(const vtkGarbageCollector&); // Not implemented. + void operator=(const vtkGarbageCollector&); // Not implemented. +}; + +//BTX +class vtkSmartPointerBase; + +// Description: +// Function to report a reference held by a smart pointer to a collector. +void VTK_COMMON_EXPORT +vtkGarbageCollectorReport(vtkGarbageCollector* collector, + vtkSmartPointerBase& ptr, + const char* desc); + +// Description: +// Function to report a reference held by a raw pointer to a collector. +template +void vtkGarbageCollectorReport(vtkGarbageCollector* collector, T*& ptr, + const char* desc) +{ + vtkGarbageCollectorReportInternal(collector, ptr, &ptr, desc); +} +//ETX + +#endif diff --git a/Common/vtkGarbageCollectorManager.cxx b/Common/vtkGarbageCollectorManager.cxx new file mode 100644 index 0000000..c000014 --- /dev/null +++ b/Common/vtkGarbageCollectorManager.cxx @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGarbageCollectorManager.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGarbageCollectorManager.h" + +#include "vtkGarbageCollector.h" + +// Must NOT be initialized. Default initialization to zero is +// necessary. +unsigned int vtkGarbageCollectorManagerCount; + +vtkGarbageCollectorManager::vtkGarbageCollectorManager() +{ + if(++vtkGarbageCollectorManagerCount == 1) + { + vtkGarbageCollector::ClassInitialize(); + } +} + +vtkGarbageCollectorManager::~vtkGarbageCollectorManager() +{ + if(--vtkGarbageCollectorManagerCount == 0) + { + vtkGarbageCollector::ClassFinalize(); + } +} diff --git a/Common/vtkGarbageCollectorManager.h b/Common/vtkGarbageCollectorManager.h new file mode 100644 index 0000000..ff63b7f --- /dev/null +++ b/Common/vtkGarbageCollectorManager.h @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGarbageCollectorManager.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGarbageCollectorManager - Manages the vtkGarbageCollector singleton. +// .SECTION Description +// vtkGarbageCollectorManager should be included in any translation unit +// that will use vtkGarbageCollector or that implements the singleton +// pattern. It makes sure that the vtkGarbageCollector singleton is created +// before and destroyed after it is used. + +#ifndef __vtkGarbageCollectorManager_h +#define __vtkGarbageCollectorManager_h + +#include "vtkSystemIncludes.h" + +#include "vtkDebugLeaksManager.h" // DebugLeaks is around longer than + // the garbage collector. + +class VTK_COMMON_EXPORT vtkGarbageCollectorManager +{ +public: + vtkGarbageCollectorManager(); + ~vtkGarbageCollectorManager(); +}; + +// This instance will show up in any translation unit that uses +// vtkGarbageCollector or that has a singleton. It will make sure +// vtkGarbageCollector is initialized before it is used finalized when +// it is done being used. +static vtkGarbageCollectorManager vtkGarbageCollectorManagerInstance; + +#endif diff --git a/Common/vtkGeneralTransform.cxx b/Common/vtkGeneralTransform.cxx new file mode 100644 index 0000000..591ce0d --- /dev/null +++ b/Common/vtkGeneralTransform.cxx @@ -0,0 +1,328 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGeneralTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGeneralTransform.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkGeneralTransform, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkGeneralTransform); + +//---------------------------------------------------------------------------- +vtkGeneralTransform::vtkGeneralTransform() +{ + this->Input = NULL; + + // most of the functionality is provided by the concatenation + this->Concatenation = vtkTransformConcatenation::New(); + + // the stack will be allocated the first time Push is called + this->Stack = NULL; +} + +//---------------------------------------------------------------------------- +vtkGeneralTransform::~vtkGeneralTransform() +{ + this->SetInput(NULL); + + if (this->Concatenation) + { + this->Concatenation->Delete(); + } + if (this->Stack) + { + this->Stack->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Input: (" << this->Input << ")\n"; + os << indent << "InverseFlag: " << this->GetInverseFlag() << "\n"; + os << indent << "NumberOfConcatenatedTransforms: " << + this->GetNumberOfConcatenatedTransforms() << "\n"; + if (this->GetNumberOfConcatenatedTransforms() != 0) + { + int n = this->GetNumberOfConcatenatedTransforms(); + for (int i = 0; i < n; i++) + { + vtkAbstractTransform *t = this->GetConcatenatedTransform(i); + os << indent << " " << i << ": " << t->GetClassName() << " at " << + t << "\n"; + } + } +} + +//------------------------------------------------------------------------ +// Pass the point through each transform in turn +template +void vtkConcatenationTransformPoint(vtkAbstractTransform *input, + vtkTransformConcatenation *concat, + T2 point[3], T3 output[3]) +{ + output[0] = point[0]; + output[1] = point[1]; + output[2] = point[2]; + + int i = 0; + int nTransforms = concat->GetNumberOfTransforms(); + int nPreTransforms = concat->GetNumberOfPreTransforms(); + + // push point through the PreTransforms + for (; i < nPreTransforms; i++) + { + concat->GetTransform(i)->InternalTransformPoint(output,output); + } + + // push point though the Input, if present + if (input) + { + if (concat->GetInverseFlag()) + { + input = input->GetInverse(); + } + input->InternalTransformPoint(output,output); + } + + // push point through PostTransforms + for (; i < nTransforms; i++) + { + concat->GetTransform(i)->InternalTransformPoint(output,output); + } +} + +//---------------------------------------------------------------------------- +// Pass the point through each transform in turn, +// concatenate the derivatives. +template +void vtkConcatenationTransformDerivative( + vtkAbstractTransform *input, + vtkTransformConcatenation *concat, + T2 point[3], T3 output[3], + T4 derivative[3][3]) +{ + T4 matrix[3][3]; + + output[0] = point[0]; + output[1] = point[1]; + output[2] = point[2]; + + vtkMath::Identity3x3(derivative); + + int i = 0; + int nTransforms = concat->GetNumberOfTransforms(); + int nPreTransforms = concat->GetNumberOfPreTransforms(); + + // push point through the PreTransforms + for (; i < nPreTransforms; i++) + { + concat->GetTransform(i)->InternalTransformDerivative(output,output,matrix); + vtkMath::Multiply3x3(matrix,derivative,derivative); + } + + // push point though the Input, if present + if (input) + { + if (concat->GetInverseFlag()) + { + input = input->GetInverse(); + } + input->InternalTransformDerivative(output,output,matrix); + vtkMath::Multiply3x3(matrix,derivative,derivative); + } + + // push point through PostTransforms + for (; i < nTransforms; i++) + { + concat->GetTransform(i)->InternalTransformDerivative(output,output,matrix); + vtkMath::Multiply3x3(matrix,derivative,derivative); + } +} + +//------------------------------------------------------------------------ +void vtkGeneralTransform::InternalTransformPoint(const float input[3], + float output[3]) +{ + vtkConcatenationTransformPoint(this->Input,this->Concatenation,input,output); +} + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::InternalTransformPoint(const double input[3], + double output[3]) +{ + vtkConcatenationTransformPoint(this->Input,this->Concatenation,input,output); +} + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::InternalTransformDerivative(const float input[3], + float output[3], + float derivative[3][3]) +{ + vtkConcatenationTransformDerivative(this->Input,this->Concatenation, + input,output,derivative); +} + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::InternalTransformDerivative(const double input[3], + double output[3], + double derivative[3][3]) +{ + vtkConcatenationTransformDerivative(this->Input,this->Concatenation, + input,output,derivative); +} + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::InternalDeepCopy(vtkAbstractTransform *gtrans) +{ + vtkGeneralTransform *transform = + (vtkGeneralTransform *)gtrans; + + // copy the input + this->SetInput(transform->Input); + + // copy the concatenation + this->Concatenation->DeepCopy(transform->Concatenation); + + // copy the stack + if (transform->Stack) + { + if (this->Stack == NULL) + { + this->Stack = vtkTransformConcatenationStack::New(); + } + this->Stack->DeepCopy(transform->Stack); + } + else + { + if (this->Stack) + { + this->Stack->Delete(); + this->Stack = NULL; + } + } +} + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::InternalUpdate() +{ + // update the input + if (this->Input) + { + if (this->Concatenation->GetInverseFlag()) + { + this->Input->GetInverse()->Update(); + } + else + { + this->Input->Update(); + } + } + + // update the concatenation + int nTransforms = this->Concatenation->GetNumberOfTransforms(); + for (int i = 0; i < nTransforms; i++) + { + this->Concatenation->GetTransform(i)->Update(); + } +} + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::Concatenate(vtkAbstractTransform *transform) +{ + if (transform->CircuitCheck(this)) + { + vtkErrorMacro("Concatenate: this would create a circular reference."); + return; + } + this->Concatenation->Concatenate(transform); + this->Modified(); +}; + +//---------------------------------------------------------------------------- +void vtkGeneralTransform::SetInput(vtkAbstractTransform *input) +{ + if (this->Input == input) + { + return; + } + if (input && input->CircuitCheck(this)) + { + vtkErrorMacro("SetInput: this would create a circular reference."); + return; + } + if (this->Input) + { + this->Input->Delete(); + } + this->Input = input; + if (this->Input) + { + this->Input->Register(this); + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +int vtkGeneralTransform::CircuitCheck(vtkAbstractTransform *transform) +{ + if (this->vtkAbstractTransform::CircuitCheck(transform) || + this->Input && this->Input->CircuitCheck(transform)) + { + return 1; + } + + int n = this->Concatenation->GetNumberOfTransforms(); + for (int i = 0; i < n; i++) + { + if (this->Concatenation->GetTransform(i)->CircuitCheck(transform)) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkGeneralTransform::MakeTransform() +{ + return vtkGeneralTransform::New(); +} + +//---------------------------------------------------------------------------- +unsigned long vtkGeneralTransform::GetMTime() +{ + unsigned long mtime = this->vtkAbstractTransform::GetMTime(); + unsigned long mtime2; + + if (this->Input) + { + mtime2 = this->Input->GetMTime(); + if (mtime2 > mtime) + { + mtime = mtime2; + } + } + mtime2 = this->Concatenation->GetMaxMTime(); + if (mtime2 > mtime) + { + return mtime2; + } + return mtime; +} + + + diff --git a/Common/vtkGeneralTransform.h b/Common/vtkGeneralTransform.h new file mode 100644 index 0000000..6e6cc51 --- /dev/null +++ b/Common/vtkGeneralTransform.h @@ -0,0 +1,237 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGeneralTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGeneralTransform - allows operations on any transforms +// .SECTION Description +// vtkGeneralTransform is like vtkTransform and vtkPerspectiveTransform, +// but it will work with any vtkAbstractTransform as input. It is +// not as efficient as the other two, however, because arbitrary +// transformations cannot be concatenated by matrix multiplication. +// Transform concatenation is simulated by passing each input point +// through each transform in turn. +// .SECTION see also +// vtkTransform vtkPerspectiveTransform + +#ifndef __vtkGeneralTransform_h +#define __vtkGeneralTransform_h + +#include "vtkAbstractTransform.h" + +#include "vtkMatrix4x4.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkGeneralTransform : public vtkAbstractTransform +{ +public: + static vtkGeneralTransform *New(); + + vtkTypeRevisionMacro(vtkGeneralTransform,vtkAbstractTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set this transformation to the identity transformation. If + // the transform has an Input, then the transformation will be + // reset so that it is the same as the Input. + void Identity() { this->Concatenation->Identity(); this->Modified(); }; + + // Description: + // Invert the transformation. This will also set a flag so that + // the transformation will use the inverse of its Input, if an Input + // has been set. + void Inverse() { this->Concatenation->Inverse(); this->Modified(); }; + + // Description: + // Create a translation matrix and concatenate it with the current + // transformation according to PreMultiply or PostMultiply semantics. + void Translate(double x, double y, double z) { + this->Concatenation->Translate(x,y,z); }; + void Translate(const double x[3]) { this->Translate(x[0], x[1], x[2]); }; + void Translate(const float x[3]) { this->Translate(x[0], x[1], x[2]); }; + + // Description: + // Create a rotation matrix and concatenate it with the current + // transformation according to PreMultiply or PostMultiply semantics. + // The angle is in degrees, and (x,y,z) specifies the axis that the + // rotation will be performed around. + void RotateWXYZ(double angle, double x, double y, double z) { + this->Concatenation->Rotate(angle,x,y,z); }; + void RotateWXYZ(double angle, const double axis[3]) { + this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); }; + void RotateWXYZ(double angle, const float axis[3]) { + this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); }; + + // Description: + // Create a rotation matrix about the X, Y, or Z axis and concatenate + // it with the current transformation according to PreMultiply or + // PostMultiply semantics. The angle is expressed in degrees. + void RotateX(double angle) { this->RotateWXYZ(angle, 1, 0, 0); }; + void RotateY(double angle) { this->RotateWXYZ(angle, 0, 1, 0); }; + void RotateZ(double angle) { this->RotateWXYZ(angle, 0, 0, 1); }; + + // Description: + // Create a scale matrix (i.e. set the diagonal elements to x, y, z) + // and concatenate it with the current transformation according to + // PreMultiply or PostMultiply semantics. + void Scale(double x, double y, double z) { + this->Concatenation->Scale(x,y,z); }; + void Scale(const double s[3]) { this->Scale(s[0], s[1], s[2]); }; + void Scale(const float s[3]) { this->Scale(s[0], s[1], s[2]); }; + + // Description: + // Concatenates the matrix with the current transformation according + // to PreMultiply or PostMultiply semantics. + void Concatenate(vtkMatrix4x4 *matrix) { + this->Concatenate(*matrix->Element); }; + void Concatenate(const double elements[16]) { + this->Concatenation->Concatenate(elements); }; + + // Description: + // Concatenate the specified transform with the current transformation + // according to PreMultiply or PostMultiply semantics. + // The concatenation is pipelined, meaning that if any of the + // transformations are changed, even after Concatenate() is called, + // those changes will be reflected when you call TransformPoint(). + void Concatenate(vtkAbstractTransform *transform); + + // Description: + // Sets the internal state of the transform to PreMultiply. All subsequent + // operations will occur before those already represented in the + // current transformation. In homogeneous matrix notation, M = M*A where + // M is the current transformation matrix and A is the applied matrix. + // The default is PreMultiply. + void PreMultiply() { + if (this->Concatenation->GetPreMultiplyFlag()) { return; } + this->Concatenation->SetPreMultiplyFlag(1); this->Modified(); }; + + // Description: + // Sets the internal state of the transform to PostMultiply. All subsequent + // operations will occur after those already represented in the + // current transformation. In homogeneous matrix notation, M = A*M where + // M is the current transformation matrix and A is the applied matrix. + // The default is PreMultiply. + void PostMultiply() { + if (!this->Concatenation->GetPreMultiplyFlag()) { return; } + this->Concatenation->SetPreMultiplyFlag(0); this->Modified(); }; + + // Description: + // Get the total number of transformations that are linked into this + // one via Concatenate() operations or via SetInput(). + int GetNumberOfConcatenatedTransforms() { + return this->Concatenation->GetNumberOfTransforms() + + (this->Input == NULL ? 0 : 1); }; + + // Description + // Get one of the concatenated transformations as a vtkAbstractTransform. + // These transformations are applied, in series, every time the + // transformation of a coordinate occurs. This method is provided + // to make it possible to decompose a transformation into its + // constituents, for example to save a transformation to a file. + vtkAbstractTransform *GetConcatenatedTransform(int i) { + if (this->Input == NULL) { + return this->Concatenation->GetTransform(i); } + else if (i < this->Concatenation->GetNumberOfPreTransforms()) { + return this->Concatenation->GetTransform(i); } + else if (i > this->Concatenation->GetNumberOfPreTransforms()) { + return this->Concatenation->GetTransform(i-1); } + else if (this->GetInverseFlag()) { + return this->Input->GetInverse(); } + else { + return this->Input; } }; + + // Description: + // Set the input for this transformation. This will be used as the + // base transformation if it is set. This method allows you to build + // a transform pipeline: if the input is modified, then this transformation + // will automatically update accordingly. Note that the InverseFlag, + // controlled via Inverse(), determines whether this transformation + // will use the Input or the inverse of the Input. + void SetInput(vtkAbstractTransform *input); + vtkAbstractTransform *GetInput() { return this->Input; }; + + // Description: + // Get the inverse flag of the transformation. This controls + // whether it is the Input or the inverse of the Input that + // is used as the base transformation. The InverseFlag is + // flipped every time Inverse() is called. The InverseFlag + // is off when a transform is first created. + int GetInverseFlag() { + return this->Concatenation->GetInverseFlag(); }; + + // Description: + // Pushes the current transformation onto the transformation stack. + void Push() { if (this->Stack == NULL) { + this->Stack = vtkTransformConcatenationStack::New(); } + this->Stack->Push(&this->Concatenation); + this->Modified(); }; + + // Description: + // Deletes the transformation on the top of the stack and sets the top + // to the next transformation on the stack. + void Pop() { if (this->Stack == NULL) { return; } + this->Stack->Pop(&this->Concatenation); + this->Modified(); }; + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + void InternalTransformPoint(const float in[3], float out[3]); + void InternalTransformPoint(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation as well as its derivative + // without calling Update. Meant for use only within other VTK + // classes. + void InternalTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InternalTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + // Description: + // Check for self-reference. Will return true if concatenating + // with the specified transform, setting it to be our inverse, + // or setting it to be our input will create a circular reference. + // CircuitCheck is automatically called by SetInput(), SetInverse(), + // and Concatenate(vtkXTransform *). Avoid using this function, + // it is experimental. + int CircuitCheck(vtkAbstractTransform *transform); + + // Description: + // Make another transform of the same type. + vtkAbstractTransform *MakeTransform(); + + // Description: + // Override GetMTime to account for input and concatenation. + unsigned long GetMTime(); + +protected: + vtkGeneralTransform(); + ~vtkGeneralTransform(); + + void InternalDeepCopy(vtkAbstractTransform *t); + void InternalUpdate(); + + vtkAbstractTransform *Input; + vtkTransformConcatenation *Concatenation; + vtkTransformConcatenationStack *Stack; +private: + vtkGeneralTransform(const vtkGeneralTransform&); // Not implemented. + void operator=(const vtkGeneralTransform&); // Not implemented. +}; + + +#endif + + + + + diff --git a/Common/vtkHeap.cxx b/Common/vtkHeap.cxx new file mode 100644 index 0000000..3203012 --- /dev/null +++ b/Common/vtkHeap.cxx @@ -0,0 +1,184 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHeap.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHeap.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkHeap, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkHeap); + +struct vtkTestAlignLong +{ + char pad; + long x; +}; + +static int vtkGetLongAlignment() +{ + struct vtkTestAlignLong s1; + char * p1; + char * p2; + + p1 = (char *) &s1; // Get address of struct + p2 = (char *) &s1.x; // Get address of long within struct + + return (p2 - p1); // Get member offset/alignment +} + +class VTK_COMMON_EXPORT vtkHeapBlock +{ +public: + char* Data; + vtkHeapBlock* Next; + size_t Size; //Variable size guards against block size changing from SetBlockSize() + //or large requests greater than the standard block size. + + vtkHeapBlock(size_t size):Next(0),Size(size) + {this->Data = new char [size];} + ~vtkHeapBlock() + {delete [] this->Data;} +}; + +vtkHeap::vtkHeap() +{ + this->BlockSize = 256000; + this->NumberOfBlocks = 0; + this->NumberOfAllocations = 0; + this->Alignment = vtkGetLongAlignment(); + this->First = 0; + this->Last = 0; + this->Current = 0; + this->Position = 0; +} + +vtkHeap::~vtkHeap() +{ + this->CleanAll(); +} + +void vtkHeap::SetBlockSize(size_t _arg) +{ + vtkDebugMacro( + << this->GetClassName() << " (" << this << "): setting BlockSize to " + << (int)_arg); + if (this->BlockSize != _arg) + { + this->BlockSize = _arg; + this->Modified(); + } +} + +void* vtkHeap::AllocateMemory(size_t n) +{ + if ( n%this->Alignment ) //4-byte word alignement + { + n += this->Alignment - (n%this->Alignment); + } + + size_t blockSize = (n > this->BlockSize ? n : this->BlockSize ); + this->NumberOfAllocations++; + + if ( ! this->Current || + (this->Position + n) >= this->Current->Size ) + { + this->Add(blockSize); + } + + char *ptr = this->Current->Data + this->Position; + this->Position += n; + + return ptr; +} + +// If a Reset() was invoked, then we reuse memory (i.e., the list of blocks) +// or allocate it as necessary. Otherwise a block is allocated and placed into +// the list of blocks. +void vtkHeap::Add(size_t blockSize) +{ + this->Position = 0; //reset to the beginning of the block + + if ( this->Current && this->Current != this->Last && + this->Current->Next->Size >= blockSize ) //reuse + { + this->Current = this->Current->Next; + } + + else //allocate a new block + { + this->NumberOfBlocks++; + vtkHeapBlock* block = new vtkHeapBlock(blockSize); + + if (!this->Last) + { + this->First = block; + this->Current = block; + this->Last = block; + return; + } + + this->Last->Next = block; + this->Last = block; + this->Current = block; + } +} + +void vtkHeap::CleanAll() +{ + this->Current = this->First; + if (!this->Current) { return; } + while (this->DeleteAndNext()); + this->First = this->Current = this->Last = 0; + this->Position = 0; +} + +vtkHeapBlock* vtkHeap::DeleteAndNext() +{ + if (this->Current) + { + vtkHeapBlock* tmp = this->Current; + this->Current = this->Current->Next; + delete tmp; + return this->Current; + } + else + { + return 0; + } +} + +void vtkHeap::Reset() +{ + this->Current = this->First; + this->Position = 0; +} + +char* vtkHeap::StringDup(const char* str) +{ + char *newStr = static_cast(this->AllocateMemory(strlen(str)+1)); + strcpy(newStr,str); + return newStr; +} + +void vtkHeap::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Block Size: " << (int)this->BlockSize << "\n"; + os << indent << "Number of Blocks: " << this->NumberOfBlocks << "\n"; + os << indent << "Number of Allocations: " << this->NumberOfAllocations << "\n"; + os << indent << "Current bytes allocated: " + << ((this->NumberOfBlocks-1)*(int)this->BlockSize + + (int)this->Position) << "\n"; +} + diff --git a/Common/vtkHeap.h b/Common/vtkHeap.h new file mode 100644 index 0000000..1462589 --- /dev/null +++ b/Common/vtkHeap.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHeap.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHeap - replacement for malloc/free and new/delete +// .SECTION Description +// This class is a replacement for malloc/free and new/delete for software +// that has inherent memory leak or performance problems. For example, +// external software such as the PLY library (vtkPLY) and VRML importer +// (vtkVRMLImporter) are often written with lots of malloc() calls but +// without the corresponding free() invocations. The class +// vtkOrderedTriangulator may create and delete millions of new/delete calls. +// This class allows the overloading of the C++ new operator (or other memory +// allocation requests) by using the method AllocateMemory(). Memory is +// deleted with an invocation of CleanAll() (which deletes ALL memory; any +// given memory allocation cannot be deleted). Note: a block size can be used +// to control the size of each memory allocation. Requests for memory are +// fulfilled from the block until the block runs out, then a new block is +// created. +// +// .SECTION Caveats +// Do not use this class as a general replacement for system memory +// allocation. This class should be used only as a last resort if memory +// leaks cannot be tracked down and eliminated by conventional means. Also, +// deleting memory from vtkHeap is not supported. Only the deletion of +// the entire heap is. (A Reset() method allows you to reuse previously +// allocated memory.) + +// .SECTION See Also +// vtkVRMLImporter vtkPLY vtkOrderedTriangulator + +#ifndef __vtkHeap_h +#define __vtkHeap_h + +#include "vtkObject.h" + +class vtkHeapBlock; //forward declaration + +class VTK_COMMON_EXPORT vtkHeap : public vtkObject +{ +public: + static vtkHeap *New(); + vtkTypeRevisionMacro(vtkHeap,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate the memory requested. + void* AllocateMemory(size_t n); + + // Description: + // Set/Get the size at which blocks are allocated. If a memory + // request is bigger than the block size, then that size + // will be allocated. + virtual void SetBlockSize(size_t); + virtual size_t GetBlockSize() { return this->BlockSize;}; + + // Description: + // Get the number of allocations thus far. + vtkGetMacro(NumberOfBlocks,int); + vtkGetMacro(NumberOfAllocations,int); + + // Description: + // This methods resets the current allocation location + // back to the beginning of the heap. This allows + // reuse of previously allocated memory which may be + // beneficial to performance in many cases. + void Reset(); + + // Description: + // Convenience method performs string duplication. + char* StringDup(const char* str); + +protected: + vtkHeap(); + ~vtkHeap(); + + void Add(size_t blockSize); + void CleanAll(); + vtkHeapBlock* DeleteAndNext(); + + size_t BlockSize; + int NumberOfAllocations; + int NumberOfBlocks; + int Alignment; + + // Manage the blocks + vtkHeapBlock* First; + vtkHeapBlock* Last; + vtkHeapBlock* Current; + // Manage the memory in the block + size_t Position; //the position in the Current block + +private: + vtkHeap(const vtkHeap&); // Not implemented. + void operator=(const vtkHeap&); // Not implemented. +}; + +#endif diff --git a/Common/vtkHomogeneousTransform.cxx b/Common/vtkHomogeneousTransform.cxx new file mode 100644 index 0000000..e8f92ce --- /dev/null +++ b/Common/vtkHomogeneousTransform.cxx @@ -0,0 +1,224 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHomogeneousTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHomogeneousTransform.h" + +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkHomogeneousTransform, "$Revision: 1.10 $"); + +//---------------------------------------------------------------------------- +vtkHomogeneousTransform::vtkHomogeneousTransform() +{ + this->Matrix = vtkMatrix4x4::New(); +} + +//---------------------------------------------------------------------------- +vtkHomogeneousTransform::~vtkHomogeneousTransform() +{ + if (this->Matrix) + { + this->Matrix->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkHomogeneousTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Matrix: (" << this->Matrix << ")\n"; + if (this->Matrix) + { + this->Matrix->PrintSelf(os, indent.GetNextIndent()); + } +} + +//------------------------------------------------------------------------ +template +inline double vtkHomogeneousTransformPoint(T1 M[4][4], + T2 in[3], T3 out[3]) +{ + double x = M[0][0]*in[0] + M[0][1]*in[1] + M[0][2]*in[2] + M[0][3]; + double y = M[1][0]*in[0] + M[1][1]*in[1] + M[1][2]*in[2] + M[1][3]; + double z = M[2][0]*in[0] + M[2][1]*in[1] + M[2][2]*in[2] + M[2][3]; + double w = M[3][0]*in[0] + M[3][1]*in[1] + M[3][2]*in[2] + M[3][3]; + + double f = 1.0/w; + out[0] = x*f; + out[1] = y*f; + out[2] = z*f; + + return f; +} + +//------------------------------------------------------------------------ +// computes a coordinate transformation and also returns the Jacobian matrix +template +inline void vtkHomogeneousTransformDerivative(T1 M[4][4], + T2 in[3], T3 out[3], + T4 derivative[3][3]) +{ + double f = vtkHomogeneousTransformPoint(M,in,out); + + for (int i = 0; i < 3; i++) + { + derivative[0][i] = (M[0][i] - M[3][i]*out[0])*f; + derivative[1][i] = (M[1][i] - M[3][i]*out[1])*f; + derivative[2][i] = (M[2][i] - M[3][i]*out[2])*f; + } +} + +//------------------------------------------------------------------------ +void vtkHomogeneousTransform::InternalTransformPoint(const float in[3], + float out[3]) +{ + vtkHomogeneousTransformPoint(this->Matrix->Element,in,out); +} + +//------------------------------------------------------------------------ +void vtkHomogeneousTransform::InternalTransformPoint(const double in[3], + double out[3]) +{ + vtkHomogeneousTransformPoint(this->Matrix->Element,in,out); +} + +//---------------------------------------------------------------------------- +void vtkHomogeneousTransform::InternalTransformDerivative(const float in[3], + float out[3], + float derivative[3][3]) +{ + vtkHomogeneousTransformDerivative(this->Matrix->Element,in,out,derivative); +} + +//---------------------------------------------------------------------------- +void vtkHomogeneousTransform::InternalTransformDerivative(const double in[3], + double out[3], + double derivative[3][3]) +{ + vtkHomogeneousTransformDerivative(this->Matrix->Element,in,out,derivative); +} + +//---------------------------------------------------------------------------- +void vtkHomogeneousTransform::TransformPoints(vtkPoints *inPts, + vtkPoints *outPts) +{ + int n = inPts->GetNumberOfPoints(); + double (*M)[4] = this->Matrix->Element; + double point[3]; + + this->Update(); + + for (int i = 0; i < n; i++) + { + inPts->GetPoint(i,point); + + vtkHomogeneousTransformPoint(M,point,point); + + outPts->InsertNextPoint(point); + } +} + +//---------------------------------------------------------------------------- +// Transform the normals and vectors using the derivative of the +// transformation. Either inNms or inVrs can be set to NULL. +// Normals are multiplied by the inverse transpose of the transform +// derivative, while vectors are simply multiplied by the derivative. +// Note that the derivative of the inverse transform is simply the +// inverse of the derivative of the forward transform. +void vtkHomogeneousTransform::TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs) +{ + int n = inPts->GetNumberOfPoints(); + double (*M)[4] = this->Matrix->Element; + double L[4][4]; + double inPnt[3],outPnt[3],inNrm[3],outNrm[3],inVec[3],outVec[3]; + double w; + + this->Update(); + + if (inNms) + { // need inverse of the matrix to calculate normals + vtkMatrix4x4::DeepCopy(*L,this->Matrix); + vtkMatrix4x4::Invert(*L,*L); + vtkMatrix4x4::Transpose(*L,*L); + } + + for (int i = 0; i < n; i++) + { + inPts->GetPoint(i,inPnt); + + // do the coordinate transformation, get 1/w + double f = vtkHomogeneousTransformPoint(M,inPnt,outPnt); + outPts->InsertNextPoint(outPnt); + + if (inVrs) + { + inVrs->GetTuple(i,inVec); + + // do the linear homogeneous transformation + outVec[0] = M[0][0]*inVec[0] + M[0][1]*inVec[1] + M[0][2]*inVec[2]; + outVec[1] = M[1][0]*inVec[0] + M[1][1]*inVec[1] + M[1][2]*inVec[2]; + outVec[2] = M[2][0]*inVec[0] + M[2][1]*inVec[1] + M[2][2]*inVec[2]; + w = M[3][0]*inVec[0] + M[3][1]*inVec[1] + M[3][2]*inVec[2]; + + // apply homogeneous correction: note that the f we are using + // is the one we calculated in the point transformation + outVec[0] = (outVec[0]-w*outPnt[0])*f; + outVec[1] = (outVec[1]-w*outPnt[1])*f; + outVec[2] = (outVec[2]-w*outPnt[2])*f; + + outVrs->InsertNextTuple(outVec); + } + + if (inNms) + { + inNms->GetTuple(i,inNrm); + + // calculate the w component of the normal + w = -(inNrm[0]*inPnt[0] + inNrm[1]*inPnt[1] + inNrm[2]*inPnt[2]); + + // perform the transformation in homogeneous coordinates + outNrm[0] = L[0][0]*inNrm[0]+L[0][1]*inNrm[1]+L[0][2]*inNrm[2]+L[0][3]*w; + outNrm[1] = L[1][0]*inNrm[0]+L[1][1]*inNrm[1]+L[1][2]*inNrm[2]+L[1][3]*w; + outNrm[2] = L[2][0]*inNrm[0]+L[2][1]*inNrm[1]+L[2][2]*inNrm[2]+L[2][3]*w; + + // re-normalize + vtkMath::Normalize(outNrm); + outNms->InsertNextTuple(outNrm); + } + } +} + +//---------------------------------------------------------------------------- +// update and copy out the current matrix +void vtkHomogeneousTransform::GetMatrix(vtkMatrix4x4 *m) +{ + this->Update(); + m->DeepCopy(this->Matrix); +} + +//---------------------------------------------------------------------------- +void vtkHomogeneousTransform::InternalDeepCopy(vtkAbstractTransform *transform) +{ + vtkHomogeneousTransform *t = (vtkHomogeneousTransform *)transform; + + this->Matrix->DeepCopy(t->Matrix); +} + diff --git a/Common/vtkHomogeneousTransform.h b/Common/vtkHomogeneousTransform.h new file mode 100644 index 0000000..11daba2 --- /dev/null +++ b/Common/vtkHomogeneousTransform.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHomogeneousTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHomogeneousTransform - superclass for homogeneous transformations +// .SECTION Description +// vtkHomogeneousTransform provides a generic interface for homogeneous +// transformations, i.e. transformations which can be represented by +// multiplying a 4x4 matrix with a homogeneous coordinate. +// .SECTION see also +// vtkPerspectiveTransform vtkLinearTransform vtkIdentityTransform + + +#ifndef __vtkHomogeneousTransform_h +#define __vtkHomogeneousTransform_h + +#include "vtkAbstractTransform.h" + +class vtkMatrix4x4; + +class VTK_COMMON_EXPORT vtkHomogeneousTransform : public vtkAbstractTransform +{ +public: + + vtkTypeRevisionMacro(vtkHomogeneousTransform,vtkAbstractTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Apply the transformation to a series of points, and append the + // results to outPts. + void TransformPoints(vtkPoints *inPts, vtkPoints *outPts); + + // Description: + // Apply the transformation to a combination of points, normals + // and vectors. + virtual void TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs); + + // Description: + // Get a copy of the internal transformation matrix. The + // transform is Updated first, to guarantee that the matrix + // is valid. + void GetMatrix(vtkMatrix4x4 *m); + + // Description: + // Get a pointer to an internal vtkMatrix4x4 that represents + // the transformation. An Update() is called on the transform + // to ensure that the matrix is up-to-date when you get it. + // You should not store the matrix pointer anywhere because it + // might become stale. + vtkMatrix4x4 *GetMatrix() { this->Update(); return this->Matrix; }; + + // Description: + // Just like GetInverse(), but includes typecast to vtkHomogeneousTransform. + vtkHomogeneousTransform *GetHomogeneousInverse() { + return (vtkHomogeneousTransform *)this->GetInverse(); }; + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + void InternalTransformPoint(const float in[3], float out[3]); + void InternalTransformPoint(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation as well as its derivative + // without calling Update. Meant for use only within other VTK + // classes. + void InternalTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InternalTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + +protected: + vtkHomogeneousTransform(); + ~vtkHomogeneousTransform(); + + void InternalDeepCopy(vtkAbstractTransform *transform); + + vtkMatrix4x4 *Matrix; + +private: + vtkHomogeneousTransform(const vtkHomogeneousTransform&); // Not implemented. + void operator=(const vtkHomogeneousTransform&); // Not implemented. +}; + +#endif + + + + + diff --git a/Common/vtkIOStream.cxx b/Common/vtkIOStream.cxx new file mode 100644 index 0000000..824aa72 --- /dev/null +++ b/Common/vtkIOStream.cxx @@ -0,0 +1,268 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIOStream.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkConfigure.h" + +#if defined(VTK_IOSTREAM_NEED_OPERATORS_LL) +# ifdef _MSC_VER +# pragma warning (push, 1) +# endif +# if defined(VTK_USE_ANSI_STDLIB) +# include + using std::istream; + using std::ostream; + using std::ios_base; +# else +# include // memchr +# include // sscanf, sprintf +# if defined(__HP_aCC) +# define protected public +# include // Hack access to some private stream methods. +# undef protected +# else +# include +# endif +# endif +# ifdef _MSC_VER +# pragma warning (pop) +# endif +#endif + +// Include function declarations. +#include "vtkIOStream.h" + +#if defined(VTK_IOSTREAM_NEED_OPERATORS_LL) + +# if !defined(VTK_USE_ANSI_STDLIB) +# define ios_base ios +# endif + +# if defined(_MAX_INT_DIG) +# define VTK_TYPE_INT64_MAX_DIG _MAX_INT_DIG +# else +# define VTK_TYPE_INT64_MAX_DIG 32 +# endif + +static int vtkIOStreamScanStream(istream& is, char* buffer) +{ + // Prepare to write to buffer. + char* out = buffer; + char* end = buffer + VTK_TYPE_INT64_MAX_DIG - 1; + + // Look for leading sign. + if(is.peek() == '+') { *out++ = '+'; is.ignore(); } + else if(is.peek() == '-') { *out++ = '-'; is.ignore(); } + + // Determine the base. If not specified in the stream, try to + // detect it from the input. A leading 0x means hex, and a leading + // 0 alone means octal. + int base = 0; + int flags = is.flags() & ios_base::basefield; + if(flags == ios_base::oct) { base = 8; } + else if(flags == ios_base::dec) { base = 10; } + else if(flags == ios_base::hex) { base = 16; } + bool foundDigit = false; + bool foundNonZero = false; + if(is.peek() == '0') + { + foundDigit = true; + is.ignore(); + if((is.peek() == 'x' || is.peek() == 'X') && (base == 0 || base == 16)) + { + base = 16; + foundDigit = false; + is.ignore(); + } + else if (base == 0) + { + base = 8; + } + } + + // Determine the range of digits allowed for this number. + const char* digits = "0123456789abcdefABCDEF"; + int maxDigitIndex = 10; + if(base == 8) + { + maxDigitIndex = 8; + } + else if(base == 16) + { + maxDigitIndex = 10+6+6; + } + + // Scan until an invalid digit is found. + for(;is.peek() != EOF; is.ignore()) + { + if(memchr(digits, *out = (char)is.peek(), maxDigitIndex) != 0) + { + if((foundNonZero || *out != '0') && out < end) + { + ++out; + foundNonZero = true; + } + foundDigit = true; + } + else + { + break; + } + } + + // Correct the buffer contents for degenerate cases. + if(foundDigit && !foundNonZero) + { + *out++ = '0'; + } + else if (!foundDigit) + { + out = buffer; + } + + // Terminate the string in the buffer. + *out = '\0'; + + return base; +} + +// Scan an input stream for a vtkIOStreamSLL or vtkIOStreamULL value. +template +istream& vtkIOStreamScanTemplate(istream& is, T& value, char type) +{ + int state = ios_base::goodbit; + + // Skip leading whitespace. +# if defined(VTK_USE_ANSI_STDLIB) + istream::sentry okay(is); +# else + is.eatwhite(); + istream& okay = is; +# endif + + if(okay) + { +# if defined(VTK_USE_ANSI_STDLIB) + try { +# endif + // Copy the string to a buffer and construct the format string. + char buffer[VTK_TYPE_INT64_MAX_DIG]; +# if defined(_MSC_VER) + char format[] = "%I64_"; + const int typeIndex = 4; +# else + char format[] = "%ll_"; + const int typeIndex = 3; +# endif + switch(vtkIOStreamScanStream(is, buffer)) + { + case 8: format[typeIndex] = 'o'; break; + case 0: // Default to decimal if not told otherwise. + case 10: format[typeIndex] = type; break; + case 16: format[typeIndex] = 'x'; break; + }; + + // Use sscanf to parse the number from the buffer. + T result; + int success = (sscanf(buffer, format, &result) == 1)?1:0; + + // Set flags for resulting state. + if(is.peek() == EOF) { state |= ios_base::eofbit; } + if(!success) { state |= ios_base::failbit; } + else { value = result; } +# if defined(VTK_USE_ANSI_STDLIB) + } catch(...) { state |= ios_base::badbit; } +# endif + } + +# if defined(VTK_USE_ANSI_STDLIB) + is.setstate(ios_base::iostate(state)); +# else + is.clear(state); +# endif + return is; +} + +// Print a vtkIOStreamSLL or vtkIOStreamULL value to an output stream. +template +ostream& vtkIOStreamPrintTemplate(ostream& os, T value, char type) +{ +# if defined(VTK_USE_ANSI_STDLIB) + ostream::sentry okay(os); +# else + ostream& okay = os; +# endif + if(okay) + { +# if defined(VTK_USE_ANSI_STDLIB) + try { +# endif + // Construct the format string. + char format[8]; + char* f = format; + *f++ = '%'; + if(os.flags() & ios_base::showpos) { *f++ = '+'; } + if(os.flags() & ios_base::showbase) { *f++ = '#'; } +# if defined(_MSC_VER) + *f++ = 'I'; *f++ = '6'; *f++ = '4'; +# else + *f++ = 'l'; *f++ = 'l'; +# endif + long bflags = os.flags() & ios_base::basefield; + if(bflags == ios_base::oct) { *f++ = 'o'; } + else if(bflags != ios_base::hex) { *f++ = type; } + else if(os.flags() & ios_base::uppercase) { *f++ = 'X'; } + else { *f++ = 'x'; } + *f = '\0'; + + // Use sprintf to print to a buffer and then write the + // buffer to the stream. + char buffer[2*VTK_TYPE_INT64_MAX_DIG]; + sprintf(buffer, format, value); + os << buffer; +# if defined(VTK_USE_ANSI_STDLIB) + } catch(...) { os.clear(os.rdstate() | ios_base::badbit); } +# endif + } + return os; +} + +# if !defined(VTK_ISTREAM_SUPPORTS_LONG_LONG) +// Implement input stream operator for vtkIOStreamSLL. +istream& vtkIOStreamScan(istream& is, vtkIOStreamSLL& value) +{ + return vtkIOStreamScanTemplate(is, value, 'd'); +} + +// Implement input stream operator for vtkIOStreamULL. +istream& vtkIOStreamScan(istream& is, vtkIOStreamULL& value) +{ + return vtkIOStreamScanTemplate(is, value, 'u'); +} +#endif + +# if !defined(VTK_OSTREAM_SUPPORTS_LONG_LONG) +// Implement output stream operator for vtkIOStreamSLL. +ostream& vtkIOStreamPrint(ostream& os, vtkIOStreamSLL value) +{ + return vtkIOStreamPrintTemplate(os, value, 'd'); +} + +// Implement output stream operator for vtkIOStreamULL. +ostream& vtkIOStreamPrint(ostream& os, vtkIOStreamULL value) +{ + return vtkIOStreamPrintTemplate(os, value, 'u'); +} +# endif + +#endif diff --git a/Common/vtkIOStream.h b/Common/vtkIOStream.h new file mode 100644 index 0000000..6d9dc94 --- /dev/null +++ b/Common/vtkIOStream.h @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIOStream.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIOStream - Include C++ iostreams as used by VTK. +// .SECTION Description +// VTK supports both ANSI and old-style streams. This header includes +// the proper streams according to VTK_USE_ANSI_STDLIB. + +#ifndef __vtkIOStream_h +#define __vtkIOStream_h + +#include "vtkConfigure.h" + +#define __VTK_SYSTEM_INCLUDES__INSIDE +#include "vtkWin32Header.h" // For export macros. +#undef __VTK_SYSTEM_INCLUDES__INSIDE + +#ifdef VTK_USE_ANSI_STDLIB + +#ifdef _MSC_VER +#pragma warning (push, 3) +#endif + +# include // Include real ansi istream and ostream. +# include // Include real ansi strstreams. +# include // Include real ansi ifstream and ofstream. +# include // Include real ansi io manipulators. + +// Need these in global namespace so the same code will work with ansi +// and old-style streams. +using std::dec; +using std::hex; +using std::setw; +using std::setfill; +using std::setprecision; +using std::cerr; +using std::cout; +using std::cin; +using std::ios; +using std::endl; +using std::ends; +using std::ostream; +using std::istream; +using std::ostrstream; +using std::istrstream; +using std::strstream; +using std::ofstream; +using std::ifstream; +using std::fstream; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#else + +// Include old-style streams. +# ifdef _WIN32_WCE +# include "vtkWinCE.h" // Include mini-streams for Windows CE. +# else +# include // Include old-style istream and ostream. +# include +# if defined(_MSC_VER) +# include // Include old-style strstream from MSVC. +# else +# include // Include old-style strstream. +# endif +# include // Include old-style ifstream and ofstream. +# endif +#endif + +#if defined(VTK_IOSTREAM_NEED_OPERATORS_LL) + +# if !defined(VTK_ISTREAM_SUPPORTS_LONG_LONG) +VTK_COMMON_EXPORT istream& vtkIOStreamScan(istream&, vtkIOStreamSLL&); +# if !defined(VTK_DO_NOT_DEFINE_ISTREAM_SLL) +inline istream& operator >> (istream& is, vtkIOStreamSLL& value) +{ + return vtkIOStreamScan(is, value); +} +# endif + +VTK_COMMON_EXPORT istream& vtkIOStreamScan(istream&, vtkIOStreamULL&); +# if !defined(VTK_DO_NOT_DEFINE_ISTREAM_ULL) +inline istream& operator >> (istream& is, vtkIOStreamULL& value) +{ + return vtkIOStreamScan(is, value); +} +# endif +# endif + +# if !defined(VTK_OSTREAM_SUPPORTS_LONG_LONG) +VTK_COMMON_EXPORT ostream& vtkIOStreamPrint(ostream&, vtkIOStreamSLL); +# if !defined(VTK_DO_NOT_DEFINE_OSTREAM_SLL) +inline ostream& operator << (ostream& os, vtkIOStreamSLL value) +{ + return vtkIOStreamPrint(os, value); +} +# endif + +VTK_COMMON_EXPORT ostream& vtkIOStreamPrint(ostream&, vtkIOStreamULL); +# if !defined(VTK_DO_NOT_DEFINE_OSTREAM_ULL) +inline ostream& operator << (ostream& os, vtkIOStreamULL value) +{ + return vtkIOStreamPrint(os, value); +} +# endif +# endif + +#endif + +#endif // __vtkIOStream_h diff --git a/Common/vtkIOStreamFwd.h b/Common/vtkIOStreamFwd.h new file mode 100644 index 0000000..94ed1b3 --- /dev/null +++ b/Common/vtkIOStreamFwd.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIOStreamFwd.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIOStreamFwd - Forward-declare C++ iostreams as used by VTK. +// .SECTION Description +// VTK supports both ANSI and old-style streams. This header +// forward-declares the proper streams according to +// VTK_USE_ANSI_STDLIB. + +#ifndef __vtkIOStreamFwd_h +#define __vtkIOStreamFwd_h + +#include "vtkConfigure.h" + +#ifdef VTK_USE_ANSI_STDLIB + +#ifdef _MSC_VER +#pragma warning (push, 3) +#endif + +// Forward-declare ansi streams. +# include +using std::ios; +using std::streambuf; +using std::istream; +using std::ostream; +using std::iostream; +using std::filebuf; +using std::ifstream; +using std::ofstream; +using std::fstream; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#else +# ifdef __BORLANDC__ +# include +# else + +// Forward-declare non-ansi streams. +class ios; +class streambuf; +class istream; +class ostream; +class iostream; +class filebuf; +class ifstream; +class ofstream; +class fstream; +# endif + +#endif + + +#endif // __vtkIOStreamFwd_h diff --git a/Common/vtkIdList.cxx b/Common/vtkIdList.cxx new file mode 100644 index 0000000..7793dc6 --- /dev/null +++ b/Common/vtkIdList.cxx @@ -0,0 +1,240 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdList.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIdList.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkIdList, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkIdList); + +vtkIdList::vtkIdList() +{ + this->NumberOfIds = 0; + this->Size = 0; + this->Ids = NULL; +} + +vtkIdList::~vtkIdList() +{ + if ( this->Ids != NULL ) + { + delete [] this->Ids; + } +} + +void vtkIdList::Initialize() +{ + if ( this->Ids != NULL ) + { + delete [] this->Ids; + this->Ids = NULL; + } + this->NumberOfIds = 0; + this->Size = 0; +} + +int vtkIdList::Allocate(const int sz, const int vtkNotUsed(strategy)) +{ + if ( sz > this->Size) + { + this->Initialize(); + this->Size = ( sz > 0 ? sz : 1); + if ( (this->Ids = new vtkIdType[this->Size]) == NULL ) + { + return 0; + } + } + this->NumberOfIds = 0; + return 1; +} + +void vtkIdList::SetNumberOfIds(const vtkIdType number) +{ + this->Allocate(number,0); + this->NumberOfIds = number; +} + +void vtkIdList::InsertId(const vtkIdType i, const vtkIdType id) +{ + if ( i >= this->Size ) + { + this->Resize(i+1); + } + this->Ids[i] = id; + if ( i >= this->NumberOfIds ) + { + this->NumberOfIds = i + 1; + } +} + +vtkIdType vtkIdList::InsertUniqueId(const vtkIdType id) +{ + for (vtkIdType i=0; i < this->NumberOfIds; i++) + { + if ( id == this->Ids[i] ) + { + return i; + } + } + + return this->InsertNextId(id); +} + +vtkIdType *vtkIdList::WritePointer(const vtkIdType i, const vtkIdType number) +{ + vtkIdType newSize=i+number; + if ( newSize > this->Size ) + { + this->Resize(newSize); + } + if ( newSize > this->NumberOfIds ) + { + this->NumberOfIds = newSize; + } + return this->Ids + i; +} + +void vtkIdList::DeleteId(vtkIdType id) +{ + vtkIdType i=0; + + // while loop is necessary to delete all occurences of id + while ( i < this->NumberOfIds ) + { + for ( ; i < this->NumberOfIds; i++) + { + if ( this->Ids[i] == id ) + { + break; + } + } + + // if found; replace current id with last + if ( i < this->NumberOfIds ) + { + this->SetId(i,this->Ids[this->NumberOfIds-1]); + this->NumberOfIds--; + } + } +} + +void vtkIdList::DeepCopy(vtkIdList *ids) +{ + this->Initialize(); + this->NumberOfIds = ids->NumberOfIds; + this->Size = ids->Size; + this->Ids = new vtkIdType [ids->Size]; + for (vtkIdType i=0; i < ids->NumberOfIds; i++) + { + this->Ids[i] = ids->Ids[i]; + } +} + +vtkIdType *vtkIdList::Resize(const vtkIdType sz) +{ + vtkIdType *newIds; + vtkIdType newSize; + + if ( sz > this->Size ) + { + newSize = this->Size + sz; + } + else if (sz == this->Size) + { + return this->Ids; + } + else + { + newSize = sz; + } + + if (newSize <= 0) + { + this->Initialize(); + return 0; + } + + if ( (newIds = new vtkIdType[newSize]) == NULL ) + { + vtkErrorMacro(<< "Cannot allocate memory\n"); + return 0; + } + + if (this->Ids) + { + memcpy(newIds, this->Ids, + (sz < this->Size ? sz : this->Size) * sizeof(vtkIdType)); + delete [] this->Ids; + } + + this->Size = newSize; + this->Ids = newIds; + return this->Ids; +} + +#define VTK_TMP_ARRAY_SIZE 500 +// Intersect this list with another vtkIdList. Updates current list according +// to result of intersection operation. +void vtkIdList::IntersectWith(vtkIdList& otherIds) +{ + // Fast method due to Dr. Andreas Mueller of ISE Integrated Systems + // Engineering (CH). + vtkIdType thisNumIds = this->GetNumberOfIds(); + + if (thisNumIds <= VTK_TMP_ARRAY_SIZE) + {//Use fast method if we can fit in temporary storage + int thisIds[VTK_TMP_ARRAY_SIZE]; + vtkIdType i, id; + + for (i=0; i < thisNumIds; i++) + { + thisIds[i] = this->GetId(i); + } + for (this->Reset(), i=0; i < thisNumIds; i++) + { + id = thisIds[i]; + if ( otherIds.IsId(id) != (-1) ) + { + this->InsertNextId(id); + } + } + } + else + {//use slower method for extreme cases + vtkIdType *thisIds = new vtkIdType [thisNumIds]; + vtkIdType i, id; + + for (i=0; i < thisNumIds; i++) + { + *(thisIds + i) = this->GetId(i); + } + for (this->Reset(), i=0; i < thisNumIds; i++) + { + id = *(thisIds + i); + if ( otherIds.IsId(id) != (-1) ) + { + this->InsertNextId(id); + } + } + delete [] thisIds; + } +} +#undef VTK_TMP_ARRAY_SIZE + +void vtkIdList::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of Ids: " << this->NumberOfIds << "\n"; +} diff --git a/Common/vtkIdList.h b/Common/vtkIdList.h new file mode 100644 index 0000000..2c1dcc5 --- /dev/null +++ b/Common/vtkIdList.h @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdList.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIdList - list of point or cell ids +// .SECTION Description +// vtkIdList is used to represent and pass data id's between +// objects. vtkIdList may represent any type of integer id, but +// usually represents point and cell ids. + +#ifndef __vtkIdList_h +#define __vtkIdList_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkIdList : public vtkObject +{ +public: + static vtkIdList *New(); + + void Initialize(); + int Allocate(const int sz, const int strategy=0); + vtkTypeRevisionMacro(vtkIdList,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the number of id's in the list. + vtkIdType GetNumberOfIds() {return this->NumberOfIds;}; + + // Description: + // Return the id at location i. + vtkIdType GetId(const int i) {return this->Ids[i];}; + + // Description: + // Specify the number of ids for this object to hold. Does an + // allocation as well as setting the number of ids. + void SetNumberOfIds(const vtkIdType number); + + // Description: + // Set the id at location i. Doesn't do range checking so it's a bit + // faster than InsertId. Make sure you use SetNumberOfIds() to allocate + // memory prior to using SetId(). + void SetId(const vtkIdType i, const vtkIdType id) {this->Ids[i] = id;}; + + // Description: + // Set the id at location i. Does range checking and allocates memory + // as necessary. + void InsertId(const vtkIdType i, const vtkIdType id); + + // Description: + // Add the id specified to the end of the list. Range checking is performed. + vtkIdType InsertNextId(const vtkIdType id); + + // Description: + // If id is not already in list, insert it and return location in + // list. Otherwise return just location in list. + vtkIdType InsertUniqueId(const vtkIdType id); + + // Description: + // Get a pointer to a particular data index. + vtkIdType *GetPointer(const vtkIdType i) {return this->Ids + i;}; + + // Description: + // Get a pointer to a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + vtkIdType *WritePointer(const vtkIdType i, const vtkIdType number); + + // Description: + // Reset to an empty state. + void Reset() {this->NumberOfIds = 0;}; + + // Description: + // Free any unused memory. + void Squeeze() {this->Resize(this->NumberOfIds);}; + + // Description: + // Copy an id list by explicitly copying the internal array. + void DeepCopy(vtkIdList *ids); + + // Description: + // Delete specified id from list. Will remove all occurrences of id in list. + void DeleteId(vtkIdType id); + + // Description: + // Return -1 if id specified is not contained in the list; otherwise return + // the position in the list. + vtkIdType IsId(vtkIdType id); + + // Description: + // Intersect this list with another vtkIdList. Updates current list according + // to result of intersection operation. + void IntersectWith(vtkIdList& otherIds); + +protected: + vtkIdList(); + ~vtkIdList(); + + vtkIdType NumberOfIds; + vtkIdType Size; + vtkIdType *Ids; + + vtkIdType *Resize(const vtkIdType sz); +private: + vtkIdList(const vtkIdList&); // Not implemented. + void operator=(const vtkIdList&); // Not implemented. +}; + +// In-lined for performance +inline vtkIdType vtkIdList::InsertNextId(const vtkIdType id) +{ + if ( this->NumberOfIds >= this->Size ) + { + this->Resize(this->NumberOfIds+1); + } + this->Ids[this->NumberOfIds++] = id; + return this->NumberOfIds-1; +} + +inline vtkIdType vtkIdList::IsId(vtkIdType id) +{ + vtkIdType *ptr, i; + for (ptr=this->Ids, i=0; iNumberOfIds; i++, ptr++) + { + if ( id == *ptr ) + { + return i; + } + } + return (-1); +} + +#endif diff --git a/Common/vtkIdListCollection.cxx b/Common/vtkIdListCollection.cxx new file mode 100644 index 0000000..6a61426 --- /dev/null +++ b/Common/vtkIdListCollection.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdListCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIdListCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkIdListCollection, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkIdListCollection); diff --git a/Common/vtkIdListCollection.h b/Common/vtkIdListCollection.h new file mode 100644 index 0000000..2025e47 --- /dev/null +++ b/Common/vtkIdListCollection.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdListCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIdListCollection - maintain an unordered list of dataarray objects +// .SECTION Description +// vtkIdListCollection is an object that creates and manipulates lists of +// datasets. See also vtkCollection and subclasses. + +#ifndef __vtkIdListCollection_h +#define __vtkIdListCollection_h + +#include "vtkCollection.h" + +#include "vtkIdList.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkIdListCollection : public vtkCollection +{ +public: + static vtkIdListCollection *New(); + vtkTypeRevisionMacro(vtkIdListCollection,vtkCollection); + + // Description: + // Add a dataset to the list. + void AddItem(vtkIdList *ds) { + this->vtkCollection::AddItem((vtkObject *)ds);}; + + // Description: + // Get the next dataset in the list. + vtkIdList *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + // Description: + // Get the ith dataset in the list. + vtkIdList *GetItem(int i) { + return static_cast(this->GetItemAsObject(i));}; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkIdList *GetNextIdList(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkIdListCollection() {}; + ~vtkIdListCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkIdListCollection(const vtkIdListCollection&); // Not implemented. + void operator=(const vtkIdListCollection&); // Not implemented. +}; + + +#endif diff --git a/Common/vtkIdTypeArray.cxx b/Common/vtkIdTypeArray.cxx new file mode 100644 index 0000000..77e229f --- /dev/null +++ b/Common/vtkIdTypeArray.cxx @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdTypeArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// We never need to instantiate vtkDataArrayTemplate or +// vtkArrayIteratorTemplate because they are instantiated +// by the corresponding array for its native type. Therefore this +// code should not be uncommented and is here for reference: +// #include "vtkDataArrayTemplate.txx" +// VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(vtkIdType); +// #include "vtkArrayIteratorTemplate.txx" +// VTK_ARRAY_ITERATOR_TEMPLATE_INSTANTIATE(vtkIdType); + +#define __vtkIdTypeArray_cxx +#include "vtkIdTypeArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkIdTypeArray, "$Revision: 1.11.6.1 $"); +vtkStandardNewMacro(vtkIdTypeArray); + +//---------------------------------------------------------------------------- +vtkIdTypeArray::vtkIdTypeArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkIdTypeArray::~vtkIdTypeArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkIdTypeArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkIdTypeArray.h b/Common/vtkIdTypeArray.h new file mode 100644 index 0000000..a520ae1 --- /dev/null +++ b/Common/vtkIdTypeArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdTypeArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIdTypeArray - dynamic, self-adjusting array of vtkIdType +// .SECTION Description +// vtkIdTypeArray is an array of values of type vtkIdType. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkIdTypeArray_h +#define __vtkIdTypeArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !(defined(__vtkIdTypeArray_cxx) && defined(VTK_USE_64BIT_IDS)) && (defined(VTK_USE_64BIT_IDS) || !defined(__vtkIntArray_h)) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE vtkIdType +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkIdTypeArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkIdTypeArray* New(); + vtkTypeRevisionMacro(vtkIdTypeArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_ID_TYPE; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, vtkIdType* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const vtkIdType* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const vtkIdType* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const vtkIdType* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + vtkIdType GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, vtkIdType value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, vtkIdType f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(vtkIdType f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + vtkIdType* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + vtkIdType* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(vtkIdType* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkIdTypeArray(vtkIdType numComp=1); + ~vtkIdTypeArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkIdTypeArray(const vtkIdTypeArray&); // Not implemented. + void operator=(const vtkIdTypeArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkIdentityTransform.cxx b/Common/vtkIdentityTransform.cxx new file mode 100644 index 0000000..de2f196 --- /dev/null +++ b/Common/vtkIdentityTransform.cxx @@ -0,0 +1,202 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdentityTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIdentityTransform.h" + +#include "vtkDataArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkIdentityTransform, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkIdentityTransform); + +//---------------------------------------------------------------------------- +vtkIdentityTransform::vtkIdentityTransform() +{ +} + +//---------------------------------------------------------------------------- +vtkIdentityTransform::~vtkIdentityTransform() +{ +} + +//---------------------------------------------------------------------------- +void vtkIdentityTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//------------------------------------------------------------------------ +void vtkIdentityTransform::InternalDeepCopy(vtkAbstractTransform *) +{ + // nothin' to do +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkIdentityTransform::MakeTransform() +{ + return vtkIdentityTransform::New(); +} + +//------------------------------------------------------------------------ +template +void vtkIdentityTransformPoint(T2 in[3], T3 out[3]) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +//------------------------------------------------------------------------ +template +void vtkIdentityTransformDerivative(T2 in[3], T3 out[3], + T4 derivative[3][3]) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + + vtkMath::Identity3x3(derivative); +} + +//------------------------------------------------------------------------ +void vtkIdentityTransform::InternalTransformPoint(const float in[3], + float out[3]) +{ + vtkIdentityTransformPoint(in,out); +} + +//------------------------------------------------------------------------ +void vtkIdentityTransform::InternalTransformPoint(const double in[3], + double out[3]) +{ + vtkIdentityTransformPoint(in,out); +} + +//------------------------------------------------------------------------ +void vtkIdentityTransform::InternalTransformNormal(const float in[3], + float out[3]) +{ + vtkIdentityTransformPoint(in,out); + vtkMath::Normalize(out); +} + +//------------------------------------------------------------------------ +void vtkIdentityTransform::InternalTransformNormal(const double in[3], + double out[3]) +{ + vtkIdentityTransformPoint(in,out); + vtkMath::Normalize(out); +} + +//------------------------------------------------------------------------ +void vtkIdentityTransform::InternalTransformVector(const float in[3], + float out[3]) +{ + vtkIdentityTransformPoint(in,out); +} + +//------------------------------------------------------------------------ +void vtkIdentityTransform::InternalTransformVector(const double in[3], + double out[3]) +{ + vtkIdentityTransformPoint(in,out); +} + +//---------------------------------------------------------------------------- +void vtkIdentityTransform::InternalTransformDerivative(const float in[3], + float out[3], + float derivative[3][3]) +{ + vtkIdentityTransformDerivative(in,out,derivative); +} + +//---------------------------------------------------------------------------- +void vtkIdentityTransform::InternalTransformDerivative(const double in[3], + double out[3], + double derivative[3][3]) +{ + vtkIdentityTransformDerivative(in,out,derivative); +} + +//---------------------------------------------------------------------------- +// Transform the normals and vectors using the derivative of the +// transformation. Either inNms or inVrs can be set to NULL. +// Normals are multiplied by the inverse transpose of the transform +// derivative, while vectors are simply multiplied by the derivative. +// Note that the derivative of the inverse transform is simply the +// inverse of the derivative of the forward transform. +void vtkIdentityTransform::TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs) +{ + this->TransformPoints(inPts,outPts); + if (inNms) + { + this->TransformNormals(inNms,outNms); + } + if (inVrs) + { + this->TransformVectors(inVrs,outVrs); + } +} + +//---------------------------------------------------------------------------- +void vtkIdentityTransform::TransformPoints(vtkPoints *inPts, + vtkPoints *outPts) +{ + int n = inPts->GetNumberOfPoints(); + double point[3]; + + for (int i = 0; i < n; i++) + { + inPts->GetPoint(i,point); + outPts->InsertNextPoint(point); + } +} + +//---------------------------------------------------------------------------- +void vtkIdentityTransform::TransformNormals(vtkDataArray *inNms, + vtkDataArray *outNms) +{ + int n = inNms->GetNumberOfTuples(); + double normal[3]; + + for (int i = 0; i < n; i++) + { + inNms->GetTuple(i,normal); + outNms->InsertNextTuple(normal); + } +} + +//---------------------------------------------------------------------------- +void vtkIdentityTransform::TransformVectors(vtkDataArray *inNms, + vtkDataArray *outNms) +{ + int n = inNms->GetNumberOfTuples(); + double vect[3]; + + for (int i = 0; i < n; i++) + { + inNms->GetTuple(i,vect); + outNms->InsertNextTuple(vect); + } +} + + + diff --git a/Common/vtkIdentityTransform.h b/Common/vtkIdentityTransform.h new file mode 100644 index 0000000..b38a13a --- /dev/null +++ b/Common/vtkIdentityTransform.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdentityTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIdentityTransform - a transform that doesn't do anything +// .SECTION Description +// vtkIdentityTransform is a transformation which will simply pass coordinate +// data unchanged. All other transform types can also do this, however, +// the vtkIdentityTransform does so with much greater efficiency. +// .SECTION see also +// vtkLinearTransform + + +#ifndef __vtkIdentityTransform_h +#define __vtkIdentityTransform_h + +#include "vtkLinearTransform.h" + +class VTK_COMMON_EXPORT vtkIdentityTransform : public vtkLinearTransform +{ +public: + static vtkIdentityTransform *New(); + + vtkTypeRevisionMacro(vtkIdentityTransform,vtkLinearTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Apply the transformation to a series of points, and append the + // results to outPts. + void TransformPoints(vtkPoints *inPts, vtkPoints *outPts); + + // Description: + // Apply the transformation to a series of normals, and append the + // results to outNms. + void TransformNormals(vtkDataArray *inNms, vtkDataArray *outNms); + + // Description: + // Apply the transformation to a series of vectors, and append the + // results to outVrs. + void TransformVectors(vtkDataArray *inVrs, vtkDataArray *outVrs); + + // Description: + // Apply the transformation to a combination of points, normals + // and vectors. + void TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs); + + // Invert the transformation. This doesn't do anything to the + // identity transformation. + void Inverse() {}; + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + void InternalTransformPoint(const float in[3], float out[3]); + void InternalTransformPoint(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + void InternalTransformNormal(const float in[3], float out[3]); + void InternalTransformNormal(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + void InternalTransformVector(const float in[3], float out[3]); + void InternalTransformVector(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation as well as its derivative + // without calling Update. Meant for use only within other VTK + // classes. + void InternalTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InternalTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + // Description: + // Make a transform of the same type. This will actually + // return the same transform. + vtkAbstractTransform *MakeTransform(); + +protected: + vtkIdentityTransform(); + ~vtkIdentityTransform(); + + void InternalDeepCopy(vtkAbstractTransform *t); + +private: + vtkIdentityTransform(const vtkIdentityTransform&); // Not implemented. + void operator=(const vtkIdentityTransform&); // Not implemented. +}; + +#endif + + + + + diff --git a/Common/vtkImplicitFunction.cxx b/Common/vtkImplicitFunction.cxx new file mode 100644 index 0000000..90edd80 --- /dev/null +++ b/Common/vtkImplicitFunction.cxx @@ -0,0 +1,154 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitFunction.h" + +#include "vtkMath.h" +#include "vtkAbstractTransform.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkImplicitFunction, "$Revision: 1.37 $"); +vtkCxxSetObjectMacro(vtkImplicitFunction,Transform,vtkAbstractTransform); + +vtkImplicitFunction::vtkImplicitFunction() +{ + this->Transform = NULL; +} + +vtkImplicitFunction::~vtkImplicitFunction() +{ + //static_cast needed since otherwise the + //call to SetTransform becomes ambiguous + this->SetTransform(static_cast(NULL)); +} + +// Evaluate function at position x-y-z and return value. Point x[3] is +// transformed through transform (if provided). +double vtkImplicitFunction::FunctionValue(const double x[3]) +{ + if ( ! this->Transform ) + { + return this->EvaluateFunction((double *)x); + } + else //pass point through transform + { + double pt[3]; + this->Transform->TransformPoint(x,pt); + return this->EvaluateFunction(pt); + } + + /* Return negative if determinant of Jacobian matrix is negative, + i.e. if the transformation has a flip. This is more 'correct' + than the above behaviour, because it turns the implicit surface + inside-out in the same way that polygonal surfaces are turned + inside-out by a flip. It takes up too many valuable CPU cycles + to check the determinant on every function evaluation, though. + { + double pt[3]; + double A[3][3]; + this->Transform->Update(); + this->Transform->InternalTransformDerivative(x,pt,A); + double val = this->EvaluateFunction((double *)pt); + + if (vtkMath::Determinant3x3(A) < 0) + { + return -val; + } + else + { + return +val; + } + } + */ +} + +// Evaluate function gradient at position x-y-z and pass back vector. Point +// x[3] is transformed through transform (if provided). +void vtkImplicitFunction::FunctionGradient(const double x[3], double g[3]) +{ + if ( ! this->Transform ) + { + this->EvaluateGradient((double *)x,g); + } + else //pass point through transform + { + double pt[3]; + double A[3][3]; + this->Transform->Update(); + this->Transform->InternalTransformDerivative(x,pt,A); + this->EvaluateGradient((double *)pt,g); + + // The gradient must be transformed using the same math as is + // use for a normal to a surface: it must be multiplied by the + // inverse of the transposed inverse of the Jacobian matrix of + // the transform, which is just the transpose of the Jacobian. + vtkMath::Transpose3x3(A,A); + vtkMath::Multiply3x3(A,g,g); + + /* If the determinant of the Jacobian matrix is negative, + then the gradient points in the opposite direction. This + behaviour is actually incorrect, but is necessary to + balance the incorrect behaviour of FunctionValue. Otherwise, + if you feed certain VTK filters a transform with a flip + the gradient will point in the wrong direction and they + will never converge to a result */ + + if (vtkMath::Determinant3x3(A) < 0) + { + g[0] = -g[0]; + g[1] = -g[1]; + g[2] = -g[2]; + } + } +} + +// Overload standard modified time function. If Transform is modified, +// then this object is modified as well. +unsigned long vtkImplicitFunction::GetMTime() +{ + unsigned long mTime=this->vtkObject::GetMTime(); + unsigned long TransformMTime; + + if ( this->Transform != NULL ) + { + TransformMTime = this->Transform->GetMTime(); + mTime = ( TransformMTime > mTime ? TransformMTime : mTime ); + } + + return mTime; +} + +void vtkImplicitFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Transform ) + { + os << indent << "Transform:\n"; + this->Transform->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Transform: (None)\n"; + } +} + +void vtkImplicitFunction::SetTransform(double elements[16]) +{ + vtkTransform* transform = vtkTransform::New(); + transform->SetMatrix(elements); + this->SetTransform(transform); + transform->Delete(); +} + diff --git a/Common/vtkImplicitFunction.h b/Common/vtkImplicitFunction.h new file mode 100644 index 0000000..3444ae3 --- /dev/null +++ b/Common/vtkImplicitFunction.h @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitFunction - abstract interface for implicit functions +// .SECTION Description +// vtkImplicitFunction specifies an abstract interface for implicit +// functions. Implicit functions are real valued functions defined in 3D +// space, w = F(x,y,z). Two primitive operations are required: the ability to +// evaluate the function, and the function gradient at a given point. The +// implicit function divides space into three regions: on the surface +// (F(x,y,z)=w), outside of the surface (F(x,y,z)>c), and inside the +// surface (F(x,y,z)FunctionValue(xyz); }; + + // Description: + // Evaluate function gradient at position x-y-z and pass back vector. Point + // x[3] is transformed through transform (if provided). + void FunctionGradient(const double x[3], double g[3]); + double *FunctionGradient(const double x[3]) { + this->FunctionGradient(x,this->ReturnValue); + return this->ReturnValue; }; + double *FunctionGradient(double x, double y, double z) { + double xyz[3] = {x, y, z}; return this->FunctionGradient(xyz); }; + + // Description: + // Set/Get a transformation to apply to input points before + // executing the implicit function. + virtual void SetTransform(vtkAbstractTransform*); + virtual void SetTransform(double elements[16]); + vtkGetObjectMacro(Transform,vtkAbstractTransform); + + // Description: + // Evaluate function at position x-y-z and return value. You should + // generally not call this method directly, you should use + // FunctionValue() instead. This method must be implemented by + // any derived class. + virtual double EvaluateFunction(double x[3]) = 0; + double EvaluateFunction(double x, double y, double z) { + double xyz[3] = {x, y, z}; return this->EvaluateFunction(xyz); }; + + // Description: + // Evaluate function gradient at position x-y-z and pass back vector. + // You should generally not call this method directly, you should use + // FunctionGradient() instead. This method must be implemented by + // any derived class. + virtual void EvaluateGradient(double x[3], double g[3]) = 0; + +protected: + vtkImplicitFunction(); + ~vtkImplicitFunction(); + + vtkAbstractTransform *Transform; + double ReturnValue[3]; +private: + vtkImplicitFunction(const vtkImplicitFunction&); // Not implemented. + void operator=(const vtkImplicitFunction&); // Not implemented. +}; + +#endif diff --git a/Common/vtkImplicitFunctionCollection.cxx b/Common/vtkImplicitFunctionCollection.cxx new file mode 100644 index 0000000..bc3c68f --- /dev/null +++ b/Common/vtkImplicitFunctionCollection.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitFunctionCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitFunctionCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImplicitFunctionCollection, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkImplicitFunctionCollection); diff --git a/Common/vtkImplicitFunctionCollection.h b/Common/vtkImplicitFunctionCollection.h new file mode 100644 index 0000000..7c74e1a --- /dev/null +++ b/Common/vtkImplicitFunctionCollection.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitFunctionCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitFunctionCollection - maintain a list of implicit functions +// .SECTION Description +// vtkImplicitFunctionCollection is an object that creates and manipulates +// lists of objects of type vtkImplicitFunction. +// .SECTION See Also +// vtkCollection vtkPlaneCollection + +#ifndef __vtkImplicitFunctionCollection_h +#define __vtkImplicitFunctionCollection_h + +#include "vtkCollection.h" + +#include "vtkImplicitFunction.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkImplicitFunctionCollection : public vtkCollection +{ +public: + vtkTypeRevisionMacro(vtkImplicitFunctionCollection,vtkCollection); + static vtkImplicitFunctionCollection *New(); + + // Description: + // Add an implicit function to the list. + void AddItem(vtkImplicitFunction *); + + // Description: + // Get the next implicit function in the list. + vtkImplicitFunction *GetNextItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkImplicitFunction *GetNextImplicitFunction( + vtkCollectionSimpleIterator &cookie) + { + return static_cast( + this->GetNextItemAsObject(cookie)); + }; + //ETX + +protected: + vtkImplicitFunctionCollection() {}; + ~vtkImplicitFunctionCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkImplicitFunctionCollection(const vtkImplicitFunctionCollection&); // Not implemented. + void operator=(const vtkImplicitFunctionCollection&); // Not implemented. +}; + +inline void vtkImplicitFunctionCollection::AddItem(vtkImplicitFunction *f) +{ + this->vtkCollection::AddItem((vtkObject *)f); +} + +inline vtkImplicitFunction *vtkImplicitFunctionCollection::GetNextItem() +{ + return static_cast(this->GetNextItemAsObject()); +} + +#endif diff --git a/Common/vtkIndent.cxx b/Common/vtkIndent.cxx new file mode 100644 index 0000000..7c6a17e --- /dev/null +++ b/Common/vtkIndent.cxx @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIndent.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIndent.h" +#include "vtkObjectFactory.h" + +//------------------------------------------------------------------------------ +vtkIndent* vtkIndent::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkObjectFactory::CreateInstance("vtkIndent"); + if(ret) + { + return reinterpret_cast(ret); + } + // If the factory was unable to create the object, then create it here. + return new vtkIndent; +} + + +#define VTK_STD_INDENT 2 +#define VTK_NUMBER_OF_BLANKS 40 + +static const char blanks[VTK_NUMBER_OF_BLANKS+1]=" "; + +// Determine the next indentation level. Keep indenting by two until the +// max of forty. +vtkIndent vtkIndent::GetNextIndent() +{ + int indent = this->Indent + VTK_STD_INDENT; + if ( indent > VTK_NUMBER_OF_BLANKS ) + { + indent = VTK_NUMBER_OF_BLANKS; + } + return indent; +} + +// Print out the indentation. Basically output a bunch of spaces. +ostream& operator<<(ostream& os, const vtkIndent& ind) +{ + os << blanks + (VTK_NUMBER_OF_BLANKS-ind.Indent) ; + return os; +} + diff --git a/Common/vtkIndent.h b/Common/vtkIndent.h new file mode 100644 index 0000000..6f992e1 --- /dev/null +++ b/Common/vtkIndent.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIndent.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkIndent - a simple class to control print indentation +// .SECTION Description +// vtkIndent is used to control indentation during the chaining print +// process. This way nested objects can correctly indent themselves. + +#ifndef __vtkIndent_h +#define __vtkIndent_h + +#include "vtkSystemIncludes.h" + +class vtkIndent; +VTK_COMMON_EXPORT ostream& operator<<(ostream& os, const vtkIndent& o); + +class VTK_COMMON_EXPORT vtkIndent +{ +public: + void Delete() {delete this;}; + vtkIndent(int ind=0) {this->Indent=ind;}; + static vtkIndent *New(); + + // Description: + // Determine the next indentation level. Keep indenting by two until the + // max of forty. + vtkIndent GetNextIndent(); + + //BTX + // Description: + // Print out the indentation. Basically output a bunch of spaces. + friend VTK_COMMON_EXPORT ostream& operator<<(ostream& os, const vtkIndent& o); + //ETX + +protected: + int Indent; + +}; + +#endif diff --git a/Common/vtkInitialValueProblemSolver.cxx b/Common/vtkInitialValueProblemSolver.cxx new file mode 100644 index 0000000..e39866d --- /dev/null +++ b/Common/vtkInitialValueProblemSolver.cxx @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInitialValueProblemSolver.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInitialValueProblemSolver.h" + +#include "vtkFunctionSet.h" + +vtkCxxRevisionMacro(vtkInitialValueProblemSolver, "$Revision: 1.10 $"); + +vtkInitialValueProblemSolver::vtkInitialValueProblemSolver() +{ + this->FunctionSet = 0; + this->Vals = 0; + this->Derivs = 0; + this->Initialized = 0; + this->Adaptive = 0; +} + +vtkInitialValueProblemSolver::~vtkInitialValueProblemSolver() +{ + this->SetFunctionSet(0); + delete[] this->Vals; + this->Vals = 0; + delete[] this->Derivs; + this->Derivs = 0; + this->Initialized = 0; +} + +void vtkInitialValueProblemSolver::SetFunctionSet(vtkFunctionSet* fset) +{ + if (this->FunctionSet != fset) + { + if (this->FunctionSet != 0) { this->FunctionSet->UnRegister(this); } + if (fset != 0 && (fset->GetNumberOfFunctions() != + fset->GetNumberOfIndependentVariables() - 1)) + { + vtkErrorMacro("Invalid function set!"); + this->FunctionSet = 0; + return; + } + this->FunctionSet = fset; + if (this->FunctionSet != 0) { this->FunctionSet->Register(this); } + this->Modified(); + } + this->Initialize(); +} + +void vtkInitialValueProblemSolver::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Function set : " << this->FunctionSet << endl; + os << indent << "Function values : " << this->Vals << endl; + os << indent << "Function derivatives: " << this->Derivs << endl; + os << indent << "Initialized: "; + if (this->Initialized) + { + os << "yes." << endl; + } + else + { + os << "no." << endl; + } +} + +void vtkInitialValueProblemSolver::Initialize() +{ + if (!FunctionSet || this->Initialized) + { + return; + } + this->Vals = + new double[this->FunctionSet->GetNumberOfIndependentVariables()]; + this->Derivs = + new double[this->FunctionSet->GetNumberOfFunctions()]; + this->Initialized = 1; +} diff --git a/Common/vtkInitialValueProblemSolver.h b/Common/vtkInitialValueProblemSolver.h new file mode 100644 index 0000000..3264a56 --- /dev/null +++ b/Common/vtkInitialValueProblemSolver.h @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInitialValueProblemSolver.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInitialValueProblemSolver - Integrate a set of ordinary +// differential equations (initial value problem) in time. + +// .SECTION Description +// Given a vtkFunctionSet which returns dF_i(x_j, t)/dt given x_j and +// t, vtkInitialValueProblemSolver computes the value of F_i at t+deltat. + +// .SECTION Warning +// vtkInitialValueProblemSolver and it's subclasses are not thread-safe. +// You should create a new integrator for each thread. + +// .SECTION See Also +// vtkRungeKutta2 vtkRungeKutta4 + +#ifndef __vtkInitialValueProblemSolver_h +#define __vtkInitialValueProblemSolver_h + +#include "vtkObject.h" + +class vtkFunctionSet; + +class VTK_COMMON_EXPORT vtkInitialValueProblemSolver : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkInitialValueProblemSolver,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Given initial values, xprev , initial time, t and a requested time + // interval, delT calculate values of x at t+delTActual (xnext). + // For certain concrete sub-classes delTActual != delT. This occurs + // when the solver supports adaptive stepsize control. If this + // is the case, the solver tries to change to stepsize such that + // the (estimated) error of the integration is less than maxError. + // The solver will not set the stepsize smaller than minStep or + // larger than maxStep. + // Also note that delT is an in/out argument. Adaptive solvers + // will modify delT to reflect the best (estimated) size for the next + // integration step. + // An estimated value for the error is returned (by reference) in error. + // Note that only some concrete sub-classes support this. Otherwise, + // the error is set to 0. + // This method returns an error code representing the nature of + // the failure: + // OutOfDomain = 1, + // NotInitialized = 2, + // UnexpectedValue = 3 + virtual int ComputeNextStep(double* xprev, double* xnext, double t, + double& delT, double maxError, + double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, double maxError, + double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, dxprev, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error) + { + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error) = 0; + + // Description: + // Set / get the dataset used for the implicit function evaluation. + virtual void SetFunctionSet(vtkFunctionSet* functionset); + vtkGetObjectMacro(FunctionSet,vtkFunctionSet); + + // Description: + // Returns 1 if the solver uses adaptive stepsize control, + // 0 otherwise + virtual int IsAdaptive() { return this->Adaptive; } + +//BTX + enum ErrorCodes + { + OUT_OF_DOMAIN = 1, + NOT_INITIALIZED = 2, + UNEXPECTED_VALUE = 3 + }; +//ETX + +protected: + vtkInitialValueProblemSolver(); + ~vtkInitialValueProblemSolver(); + + virtual void Initialize(); + + vtkFunctionSet* FunctionSet; + + double* Vals; + double* Derivs; + int Initialized; + int Adaptive; + +private: + vtkInitialValueProblemSolver(const vtkInitialValueProblemSolver&); // Not implemented. + void operator=(const vtkInitialValueProblemSolver&); // Not implemented. +}; + +#endif + + + + diff --git a/Common/vtkInstantiator.cxx b/Common/vtkInstantiator.cxx new file mode 100644 index 0000000..8d0cff6 --- /dev/null +++ b/Common/vtkInstantiator.cxx @@ -0,0 +1,314 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInstantiator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInstantiator.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkInstantiator, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkInstantiator); + +// Node in hash table. +class vtkInstantiatorHashNode +{ +public: + typedef vtkInstantiator::CreateFunction CreateFunction; + + vtkInstantiatorHashNode() { this->ClassName = 0; this->Function = 0; } + + void SetClassName(const char* className) { this->ClassName = className; } + const char* GetClassName() { return this->ClassName; } + + void SetFunction(CreateFunction function) { this->Function = function; } + CreateFunction GetFunction() { return this->Function; } + +private: + const char* ClassName; + CreateFunction Function; +}; + +// Hash table used by vtkInstantiator. Must not be a vtkObject. +class vtkInstantiatorHashTable +{ +public: + vtkInstantiatorHashTable(); + ~vtkInstantiatorHashTable(); + + void PrintSelf(ostream& os, vtkIndent indent); + + typedef vtkInstantiator::CreateFunction CreateFunction; + void Insert(const char* className, CreateFunction function); + void Erase(const char* className, CreateFunction function); + CreateFunction Find(const char* className); + +protected: + unsigned long Hash(const char* s); + void ExtendBucket(unsigned long bucket); + const char* AddClassName(const char* className); + + vtkInstantiatorHashNode** Buckets; + unsigned int* BucketCounts; + unsigned int* BucketSizes; + unsigned long NumberOfBuckets; + char** ClassNames; + unsigned long NumberOfClassNames; + unsigned long ClassNamesSize; + +private: + vtkInstantiatorHashTable(const vtkInstantiatorHashTable&); // Not implemented. + void operator=(const vtkInstantiatorHashTable&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +vtkInstantiatorHashTable::vtkInstantiatorHashTable() +{ + this->NumberOfBuckets = 101; + this->Buckets = new vtkInstantiatorHashNode*[this->NumberOfBuckets]; + this->BucketCounts = new unsigned int[this->NumberOfBuckets]; + this->BucketSizes = new unsigned int[this->NumberOfBuckets]; + + unsigned int i; + for(i=0;i < this->NumberOfBuckets;++i) + { + this->BucketCounts[i] = 0; + this->BucketSizes[i] = 16; + this->Buckets[i] = new vtkInstantiatorHashNode[this->BucketSizes[i]]; + } + + this->NumberOfClassNames = 0; + this->ClassNamesSize = 256; + this->ClassNames = new char*[this->ClassNamesSize]; +} + +//---------------------------------------------------------------------------- +vtkInstantiatorHashTable::~vtkInstantiatorHashTable() +{ + unsigned long i; + for(i=0; i < this->NumberOfBuckets;++i) + { + delete [] this->Buckets[i]; + } + delete [] this->BucketSizes; + delete [] this->BucketCounts; + delete [] this->Buckets; + + for(i=0;i < this->NumberOfClassNames;++i) + { + delete [] this->ClassNames[i]; + } + delete [] this->ClassNames; +} + +//---------------------------------------------------------------------------- +void vtkInstantiatorHashTable::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "NumberOfBuckets: " << this->NumberOfBuckets << "\n"; + unsigned int i; + float avgBucketSize = 0; + unsigned int maxBucketSize = 0; + unsigned int minBucketSize = this->NumberOfClassNames; + for(i=0;i < this->NumberOfBuckets;++i) + { + avgBucketSize += this->BucketCounts[i]; + if(this->BucketCounts[i] > maxBucketSize) + { maxBucketSize = this->BucketCounts[i]; } + if(this->BucketCounts[i] < minBucketSize) + { minBucketSize = this->BucketCounts[i]; } + } + avgBucketSize /= float(this->NumberOfBuckets); + os << indent << "Average Bucket Size: " << avgBucketSize << "\n"; + os << indent << "Minimum Bucket Size: " << minBucketSize << "\n"; + os << indent << "Maximum Bucket Size: " << maxBucketSize << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkInstantiatorHashTable::Insert(const char* className, + CreateFunction function) +{ + unsigned long bucket = this->Hash(className); + + if(this->BucketCounts[bucket] == this->BucketSizes[bucket]) + { this->ExtendBucket(bucket); } + + // Do not check if the class is already registered. It is possible + // that more than one create function will be registered for the + // same class, and even that the same function is registered more + // than once. Each register should have a corresponding unregister. + // As long as any register has not had its corresponding unregister, + // we want to allow the class to be created. + unsigned int pos = this->BucketCounts[bucket]++; + this->Buckets[bucket][pos].SetClassName(this->AddClassName(className)); + this->Buckets[bucket][pos].SetFunction(function); +} + +//---------------------------------------------------------------------------- +void vtkInstantiatorHashTable::Erase(const char* className, + CreateFunction function) +{ + unsigned long bucket = this->Hash(className); + + // Find the exact registration function we have been given, and + // remove it only once. If more than one funcion has been + // registered for this class, or the same function more than once, + // each register should have its corresponding unregister. + unsigned int i; + for(i=0; i < this->BucketCounts[bucket];++i) + { + if(((this->Buckets[bucket][i].GetFunction() == function) + && (strcmp(this->Buckets[bucket][i].GetClassName(), className) == 0))) + { + unsigned int j; + --this->BucketCounts[bucket]; + for(j=i;j < this->BucketCounts[bucket];++j) + { + this->Buckets[bucket][j] = this->Buckets[bucket][j+1]; + } + return; + } + } +} + +//---------------------------------------------------------------------------- +vtkInstantiatorHashTable::CreateFunction +vtkInstantiatorHashTable::Find(const char* className) +{ + unsigned long bucket = this->Hash(className); + + unsigned int i; + for(i=0; i < this->BucketCounts[bucket];++i) + { + if(strcmp(this->Buckets[bucket][i].GetClassName(), className) == 0) + { return this->Buckets[bucket][i].GetFunction(); } + } + return 0; +} + +//---------------------------------------------------------------------------- +unsigned long vtkInstantiatorHashTable::Hash(const char* s) +{ + unsigned long h = 0; + for(;*s;++s) { h = 5*h + *s; } + return h % this->NumberOfBuckets; +} + +//---------------------------------------------------------------------------- +void vtkInstantiatorHashTable::ExtendBucket(unsigned long bucket) +{ + unsigned int newSize = this->BucketSizes[bucket] * 2; + + vtkInstantiatorHashNode* newBucket = + new vtkInstantiatorHashNode[newSize]; + + unsigned int i; + for(i=0; i < this->BucketCounts[bucket];++i) + { newBucket[i] = this->Buckets[bucket][i]; } + + delete [] this->Buckets[bucket]; + this->Buckets[bucket] = newBucket; + this->BucketSizes[bucket] = newSize; +} + +//---------------------------------------------------------------------------- +const char* vtkInstantiatorHashTable::AddClassName(const char* className) +{ + if(this->NumberOfClassNames == this->ClassNamesSize) + { + unsigned long newSize = this->ClassNamesSize * 2; + char** newNames = new char*[newSize]; + + unsigned long i; + for(i=0;i < this->NumberOfClassNames;++i) + { newNames[i] = this->ClassNames[i]; } + + delete [] this->ClassNames; + this->ClassNames = newNames; + this->ClassNamesSize = newSize; + } + + char* newName = new char[strlen(className)+1]; + strcpy(newName, className); + this->ClassNames[this->NumberOfClassNames++] = newName; + + return newName; +} + +//---------------------------------------------------------------------------- +// Implementation of actual vtkInstantiator class. +//---------------------------------------------------------------------------- +vtkInstantiator::vtkInstantiator() +{ +} + +//---------------------------------------------------------------------------- +vtkInstantiator::~vtkInstantiator() +{ +} + +//---------------------------------------------------------------------------- +void vtkInstantiator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + vtkInstantiator::CreatorTable->PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkObject* vtkInstantiator::CreateInstance(const char* className) +{ + CreateFunction function = vtkInstantiator::CreatorTable->Find(className); + if(function) { return function(); } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkInstantiator::RegisterInstantiator(const char* className, + CreateFunction createFunction) +{ + vtkInstantiator::CreatorTable->Insert(className, createFunction); +} + +//---------------------------------------------------------------------------- +void vtkInstantiator::UnRegisterInstantiator(const char* className, + CreateFunction createFunction) +{ + vtkInstantiator::CreatorTable->Erase(className, createFunction); +} + +//---------------------------------------------------------------------------- +void vtkInstantiator::ClassInitialize() +{ + vtkInstantiator::CreatorTable = new vtkInstantiatorHashTable; +} + +//---------------------------------------------------------------------------- +void vtkInstantiator::ClassFinalize() +{ + delete vtkInstantiator::CreatorTable; +} + +//---------------------------------------------------------------------------- +vtkInstantiatorInitialize::vtkInstantiatorInitialize() +{ + if(++vtkInstantiatorInitialize::Count == 1) + { vtkInstantiator::ClassInitialize(); } +} + +//---------------------------------------------------------------------------- +vtkInstantiatorInitialize::~vtkInstantiatorInitialize() +{ + if(--vtkInstantiatorInitialize::Count == 0) + { vtkInstantiator::ClassFinalize(); } +} + +//---------------------------------------------------------------------------- +unsigned int vtkInstantiatorInitialize::Count; +vtkInstantiatorHashTable* vtkInstantiator::CreatorTable; diff --git a/Common/vtkInstantiator.h b/Common/vtkInstantiator.h new file mode 100644 index 0000000..518b42c --- /dev/null +++ b/Common/vtkInstantiator.h @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInstantiator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInstantiator - create an instance of any VTK class from its name. +// .SECTION Description +// vtkInstantiator provides an interface to create an instance of any +// VTK class from its name. Instances are created through registered +// pointers to functions returning the objects. New classes can also be +// registered with the creator. VTK libraries automatically register +// their classes with the creator when they are loaded. Instances are +// created using the static New() method, so the normal vtkObjectFactory +// mechanism is still invoked. +// +// When using this class from language wrappers (Tcl, Python, or Java), +// the vtkInstantiator should be able to create any class from any kit +// that has been loaded. +// +// In C++ code, one should include the header for each kit from which +// one wishes to create instances through vtkInstantiator. This is +// necessary to ensure proper linking when building static libraries. +// Be careful, though, because including each kit's header means every +// class from that kit will be linked into your executable whether or +// not the class is used. The headers are: +// +// vtkCommon - vtkCommonInstantiator.h +// vtkFiltering - vtkFilteringInstantiator.h +// vtkIO - vtkIOInstantiator.h +// vtkImaging - vtkImagingInstantiator.h +// vtkGraphics - vtkGraphicsInstantiator.h +// vtkRendering - vtkRenderingInstantiator.h +// vtkVolumeRendering - vtkVolumeRenderingInstantiator.h +// vtkHybrid - vtkHybridInstantiator.h +// vtkParallel - vtkParallelInstantiator.h +// +// The VTK_MAKE_INSTANTIATOR() command in CMake is used to automatically +// generate the creator registration for each VTK library. It can also +// be used to create registration code for VTK-style user libraries +// that are linked to vtkCommon. After using this command to register +// classes from a new library, the generated header must be included. +// + +#ifndef __vtkInstantiator_h +#define __vtkInstantiator_h + +#include "vtkObject.h" + +// The vtkDebugLeaks singleton must be initialized before and +// destroyed after the vtkInstantiator singleton. +#include "vtkDebugLeaksManager.h" // Needed for proper singleton initialization + +class vtkInstantiatorInitialize; +class vtkInstantiatorHashTable; + +class VTK_COMMON_EXPORT vtkInstantiator : public vtkObject +{ +public: + static vtkInstantiator* New(); + vtkTypeRevisionMacro(vtkInstantiator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create an instance of the class whose name is given. If creation + // fails, a NULL pointer is returned. + static vtkObject* CreateInstance(const char* className); + + //BTX + typedef vtkObject* (*CreateFunction)(); + + // Description: + // Register a function to create instances of the class whose name + // is given. This allows more than one create function to be + // registered for the same class. The first one registered is used + // until it is unregistered. + static void RegisterInstantiator(const char* className, + CreateFunction createFunction); + + // Description: + // Unregister the instance creation of the class whose name is + // given. This will unregister the function given, but any other + // function registered for the same class will be left untouched. + static void UnRegisterInstantiator(const char* className, + CreateFunction createFunction); + //ETX + +protected: + vtkInstantiator(); + ~vtkInstantiator(); + + // Internal storage for registered creation functions. + static vtkInstantiatorHashTable* CreatorTable; + + static void ClassInitialize(); + static void ClassFinalize(); + + //BTX + friend class vtkInstantiatorInitialize; + //ETX + +private: + vtkInstantiator(const vtkInstantiator&); // Not implemented. + void operator=(const vtkInstantiator&); // Not implemented. +}; + +//BTX +// Utility class to make sure vtkInstantiator is initialized before it +// is used. +class VTK_COMMON_EXPORT vtkInstantiatorInitialize +{ +public: + vtkInstantiatorInitialize(); + ~vtkInstantiatorInitialize(); +private: + static unsigned int Count; +}; + +// This instance will show up in any translation unit that uses +// vtkInstantiator. It will make sure vtkInstantiator is initialized +// before it is used. +static vtkInstantiatorInitialize vtkInstantiatorInitializer; +//ETX + +#endif diff --git a/Common/vtkIntArray.cxx b/Common/vtkIntArray.cxx new file mode 100644 index 0000000..4ff9175 --- /dev/null +++ b/Common/vtkIntArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIntArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(int); + +#define __vtkIntArray_cxx +#include "vtkIntArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkIntArray, "$Revision: 1.67 $"); +vtkStandardNewMacro(vtkIntArray); + +//---------------------------------------------------------------------------- +vtkIntArray::vtkIntArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkIntArray::~vtkIntArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkIntArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkIntArray.h b/Common/vtkIntArray.h new file mode 100644 index 0000000..37b3841 --- /dev/null +++ b/Common/vtkIntArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIntArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIntArray - dynamic, self-adjusting array of int +// .SECTION Description +// vtkIntArray is an array of values of type int. It provides +// methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkIntArray_h +#define __vtkIntArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkIntArray_cxx) && (defined(VTK_USE_64BIT_IDS) || !defined(__vtkIdTypeArray_h)) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE int +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkIntArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkIntArray* New(); + vtkTypeRevisionMacro(vtkIntArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_INT; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, int* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const int* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const int* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const int* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + int GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, int value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, int f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(int f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + int* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + int* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(int* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkIntArray(vtkIdType numComp=1); + ~vtkIntArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkIntArray(const vtkIntArray&); // Not implemented. + void operator=(const vtkIntArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkJavaAwt.h b/Common/vtkJavaAwt.h new file mode 100644 index 0000000..fb5acc0 --- /dev/null +++ b/Common/vtkJavaAwt.h @@ -0,0 +1,252 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJavaAwt.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// for use with JAWT +#include "jawt_md.h" + +#define VTK_JAVA_DEBUG + + +#if defined(_WIN32) || defined(WIN32) +#define WIN32_JAWT_LOCK_HACK +#endif + +#if defined(WIN32_JAWT_LOCK_HACK) +#define WJLH_MAX_COUNT (32) +#define WJLH_HASH_FUNC(E,C,H) {\ + jclass cls = E->GetObjectClass(C);\ + jmethodID mid = E->GetMethodID(cls, "hashCode", "()I");\ + H = E->CallIntMethod(C, mid); } +# include "vtkWindows.h" +int WJLH_init_check = 0; +# include +vtkstd::map WJLH_lock_map; +#endif + +extern "C" JNIEXPORT jint JNICALL +Java_vtk_vtkPanel_RenderCreate(JNIEnv *env, jobject canvas, jobject id0) +{ +#if defined(WIN32_JAWT_LOCK_HACK) + int hash; + WJLH_HASH_FUNC(env, canvas, hash); + WJLH_lock_map[hash] = 0; +#endif + + JAWT awt; + JAWT_DrawingSurface* ds; + JAWT_DrawingSurfaceInfo* dsi; + jint lock; + + // get the render window pointer + vtkRenderWindow *temp0; + temp0 = (vtkRenderWindow *)(vtkJavaGetPointerFromObject(env,id0,(char *) "vtkRenderWindow")); + + /* Get the AWT */ + awt.version = JAWT_VERSION_1_3; + if (JAWT_GetAWT(env, &awt) == JNI_FALSE) + { +#ifndef VTK_JAVA_DEBUG + printf("AWT Not found\n"); +#endif + return 1; + } + + /* Get the drawing surface */ + ds = awt.GetDrawingSurface(env, canvas); + if (ds == NULL) + { +#ifndef VTK_JAVA_DEBUG + printf("NULL drawing surface\n"); +#endif + return 1; + } + + /* Lock the drawing surface */ + lock = ds->Lock(ds); + if((lock & JAWT_LOCK_ERROR) != 0) + { +#ifndef VTK_JAVA_DEBUG + printf("Error locking surface\n"); +#endif + awt.FreeDrawingSurface(ds); + return 1; + } + + /* Get the drawing surface info */ + dsi = ds->GetDrawingSurfaceInfo(ds); + if (dsi == NULL) + { + printf("Error getting surface info\n"); + ds->Unlock(ds); + awt.FreeDrawingSurface(ds); + return 1; + } + +// Here is the win32 drawing code +#if defined(_WIN32) || defined(WIN32) + JAWT_Win32DrawingSurfaceInfo* dsi_win; + dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo; + temp0->SetWindowId((void *)dsi_win->hwnd); + temp0->SetDisplayId((void *)dsi_win->hdc); + // also set parent id to avoid border sizes being added + temp0->SetParentId((void *)dsi_win->hdc); +// use mac code +#elif defined(__APPLE__) + JAWT_MacOSXDrawingSurfaceInfo* dsi_mac; + dsi_mac = (JAWT_MacOSXDrawingSurfaceInfo*)dsi->platformInfo; + temp0->SetDisplayId(dsi_mac->cocoaViewRef); +// otherwise use X11 code +#else + JAWT_X11DrawingSurfaceInfo* dsi_x11; + dsi_x11 = (JAWT_X11DrawingSurfaceInfo*)dsi->platformInfo; + temp0->SetDisplayId((void *)dsi_x11->display); + temp0->SetWindowId((void *)dsi_x11->drawable); + temp0->SetParentId((void *)dsi_x11->display); +#endif + + /* Free the drawing surface info */ + ds->FreeDrawingSurfaceInfo(dsi); + + /* Unlock the drawing surface */ + ds->Unlock(ds); + + /* Free the drawing surface */ + awt.FreeDrawingSurface(ds); + +#if defined(WIN32_JAWT_LOCK_HACK) +if (WJLH_init_check == 0) +{ + WJLH_init_check = 1; +} + WJLH_lock_map[hash] = 1; +#endif + return 0; + +} + + +// Lock must be called prior to render or anything which might +// cause vtkRenderWindow to make an XLib call or to call Render(). +// The Lock() and UnLock() functions are necessary for drawing in +// JAWT, but they also provide a form of mutex locking so that multiple +// java threads are prevented from accessing X at the same time. The only +// requirement JAWT has is that all operations on a JAWT_DrawingSurface +// MUST be performed from the same thread as the call to GetDrawingSurface. +extern "C" JNIEXPORT jint JNICALL +Java_vtk_vtkPanel_Lock(JNIEnv *env, + jobject canvas) +{ + JAWT awt; + JAWT_DrawingSurface* ds; + jint lock; + + /* Get the AWT */ + awt.version = JAWT_VERSION_1_3; + if (JAWT_GetAWT(env, &awt) == JNI_FALSE) + { +#ifndef VTK_JAVA_DEBUG + printf("AWT Not found\n"); +#endif + return 1; + } + + /* Get the drawing surface */ + ds = awt.GetDrawingSurface(env, canvas); + if (ds == NULL) + { +#ifndef VTK_JAVA_DEBUG + printf("NULL drawing surface\n"); +#endif + return 1; + } + +#if defined(WIN32_JAWT_LOCK_HACK) + int hash; + WJLH_HASH_FUNC(env, canvas, hash); + if (WJLH_init_check && WJLH_lock_map[hash] > WJLH_MAX_COUNT) + { + env->MonitorEnter(canvas); + } + else + { +#endif + /* Lock the drawing surface */ + lock = ds->Lock(ds); + if((lock & JAWT_LOCK_ERROR) != 0) + { +#ifndef VTK_JAVA_DEBUG + printf("Error locking surface\n"); +#endif + awt.FreeDrawingSurface(ds); + return 1; + } +#if defined(WIN32_JAWT_LOCK_HACK) + } +#endif + + return 0; + +} + +// UnLock() must be called after a Lock() and execution of a +// function which might change the drawing surface. See Lock(). +extern "C" JNIEXPORT jint JNICALL +Java_vtk_vtkPanel_UnLock(JNIEnv *env, + jobject canvas) +{ + JAWT awt; + JAWT_DrawingSurface* ds; + + /* Get the AWT */ + awt.version = JAWT_VERSION_1_3; + if (JAWT_GetAWT(env, &awt) == JNI_FALSE) + { +#ifndef VTK_JAVA_DEBUG + printf("AWT Not found\n"); +#endif + return 1; + } + + /* Get the drawing surface */ + ds = awt.GetDrawingSurface(env, canvas); + if (ds == NULL) + { +#ifndef VTK_JAVA_DEBUG + printf("NULL drawing surface\n"); +#endif + return 1; + } + +#if defined(WIN32_JAWT_LOCK_HACK) + int hash; + WJLH_HASH_FUNC(env, canvas, hash); + if (WJLH_init_check && WJLH_lock_map[hash] > WJLH_MAX_COUNT) + { + env->MonitorExit(canvas); + } + else + { + if (WJLH_init_check) WJLH_lock_map[hash]++; +#endif + /* Unlock the drawing surface */ + ds->Unlock(ds); +#if defined(WIN32_JAWT_LOCK_HACK) + } +#endif + + /* Free the drawing surface */ + awt.FreeDrawingSurface(ds); + + return 0; +} diff --git a/Common/vtkJavaUtil.cxx b/Common/vtkJavaUtil.cxx new file mode 100644 index 0000000..8eac2aa --- /dev/null +++ b/Common/vtkJavaUtil.cxx @@ -0,0 +1,959 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJavaUtil.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// include stdmutex for borland +#ifdef __BORLANDC__ +#include +#endif + +#ifdef _INTEGRAL_MAX_BITS +#undef _INTEGRAL_MAX_BITS +#endif +#define _INTEGRAL_MAX_BITS 64 + +#include "vtkObject.h" +#include "vtkDebugLeaks.h" +#include "vtkWindows.h" + +#ifdef _WIN32 +HANDLE vtkGlobalMutex = NULL; +#define VTK_GET_MUTEX() WaitForSingleObject(vtkGlobalMutex,INFINITE) +#define VTK_RELEASE_MUTEX() ReleaseMutex(vtkGlobalMutex) +#include +#else + +#ifdef VTK_USE_SPROC +// for SGI's +#include +abilock_t vtkGlobalMutex; +static void vtk_get_mutex() { + static int inited = 0; + if (!inited) { + if (init_lock(&vtkGlobalMutex) < 0) + perror("initializing mutex"); + inited = 1; + } + spin_lock(&vtkGlobalMutex); +} +static void vtk_release_mutex() { + if (release_lock(&vtkGlobalMutex) < 0) + perror("releasing mutex"); +} +#define VTK_GET_MUTEX() vtk_get_mutex() +#define VTK_RELEASE_MUTEX() vtk_release_mutex() +#elif defined(__FreeBSD__) || defined(__linux__) || defined(sgi) || defined(__APPLE_CC__) +#include +pthread_mutex_t vtkGlobalMutex; +static void vtk_get_mutex() { + static int inited = 0; + if (!inited) + { + inited = 1; + pthread_mutex_init ( &vtkGlobalMutex, NULL ); + } + pthread_mutex_lock(&vtkGlobalMutex); +} +// #define VTK_GET_MUTEX() pthread_mutex_lock(&vtkGlobalMutex) +#define VTK_GET_MUTEX() vtk_get_mutex() +#define VTK_RELEASE_MUTEX() pthread_mutex_unlock(&vtkGlobalMutex) +#else +// for solaris +#include +#include +mutex_t vtkGlobalMutex; +#define VTK_GET_MUTEX() mutex_lock(&vtkGlobalMutex) +#define VTK_RELEASE_MUTEX() mutex_unlock(&vtkGlobalMutex) +#endif + +#endif + +#include "vtkJavaUtil.h" + +int vtkJavaIdCount = 1; + +//#define VTKJAVADEBUG + +class vtkHashNode +{ +public: + vtkHashNode *next; + void *key; + void *value; +}; + + +class vtkHashTable +{ +public: + vtkHashTable(); + vtkHashNode *(nodes[64]); + void AddHashEntry(void *key,void *value); + void *GetHashTableValue(void *key); + void *GetHashTableValue(int key); + void *InternalGetHashTableValue(int loc, void *key); + void DeleteHashEntry(void *key); +}; + +vtkHashTable::vtkHashTable() +{ + int i; + for (i = 0; i < 64; i++) + { + this->nodes[i] = NULL; + } +} + +vtkHashTable *vtkInstanceLookup = NULL; +vtkHashTable *vtkPointerLookup = NULL; +vtkHashTable *vtkTypecastLookup = NULL; + +void vtkHashTable::AddHashEntry(void *key,void *value) +{ + vtkHashNode *pos; + vtkHashNode *newpos; + int loc; + + newpos = new vtkHashNode; + newpos->key = key; + newpos->value = value; + newpos->next = NULL; + + loc = (unsigned long)((size_t)key & 0x03f0) / 16; + + pos = this->nodes[loc]; + if (!pos) + { + this->nodes[loc] = newpos; + return; + } + while (pos->next) + { + pos = pos->next; + } + pos->next = newpos; +} + +void *vtkHashTable::GetHashTableValue(int key) +{ + int loc = (unsigned long)(key & 0x03f0) / 16; + return this->InternalGetHashTableValue(loc, (void *)(size_t)key); +} + +void *vtkHashTable::GetHashTableValue(void *key) +{ + int loc = (unsigned long)((size_t)key & 0x03f0) / 16; + return this->InternalGetHashTableValue(loc, key); +} + +void *vtkHashTable::InternalGetHashTableValue(int loc, void *key) +{ + vtkHashNode *pos; + pos = this->nodes[loc]; + + if (!pos) + { + return NULL; + } + while ((pos)&&(pos->key != key)) + { + pos = pos->next; + } + if (pos) + { + return pos->value; + } + return NULL; +} + +void vtkHashTable::DeleteHashEntry(void *key) +{ + vtkHashNode *pos; + vtkHashNode *prev = NULL; + int loc = (unsigned long)((size_t)key & 0x03f0) / 16; + + pos = this->nodes[loc]; + + while ((pos)&&(pos->key != key)) + { + prev = pos; + pos = pos->next; + } + if (pos) + { + // we found this object + if (prev) + { + prev->next = pos->next; + } + else + { + this->nodes[loc] = pos->next; + } + delete pos; + } +} + +JNIEXPORT int vtkJavaGetId(JNIEnv *env,jobject obj) +{ + jfieldID id; + int result; + + id = env->GetFieldID(env->GetObjectClass(obj),"vtkId","I"); + + result = (int)env->GetIntField(obj,id); + return result; +} + +JNIEXPORT void vtkJavaSetId(JNIEnv *env,jobject obj, int newVal) +{ + jfieldID id; + jint jNewVal = (jint)newVal; + + id = env->GetFieldID(env->GetObjectClass(obj),"vtkId","I"); + + env->SetIntField(obj,id,jNewVal); +} + +JNIEXPORT void vtkJavaRegisterCastFunction(JNIEnv *vtkNotUsed(env), + jobject vtkNotUsed(obj), + int id, void *tcFunc) +{ + VTK_GET_MUTEX(); +#ifdef VTKJAVADEBUG + if (id == 0) { + vtkGenericWarningMacro("RegisterCastFunction: Try to add a CastFuction to a unregistered function"); + } +#endif + vtkTypecastLookup->AddHashEntry((void *)(size_t)id,tcFunc); + VTK_RELEASE_MUTEX(); +} + +// add an object to the hash table +JNIEXPORT int vtkJavaRegisterNewObject(JNIEnv *env, jobject obj, void *ptr) +{ + if (!vtkInstanceLookup) // first call ? + { + vtkInstanceLookup = new vtkHashTable(); + vtkPointerLookup = new vtkHashTable(); + vtkTypecastLookup = new vtkHashTable(); + + // Java does not guarantee object destruction. Do not produce an + // error when leaks are detected. + vtkDebugLeaks::SetExitError(0); + +#ifdef _WIN32 + vtkGlobalMutex = CreateMutex(NULL, FALSE, NULL); +#endif + } + +VTK_GET_MUTEX(); + +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("RegisterNewObject: Adding an object to hash ptr = " << ptr); +#endif + // lets make sure it isn't already there + int id = 0; + id = vtkJavaGetId(env,obj); + if (id) + { +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("RegisterNewObject: Attempt to add an object to the hash when one already exists!!!"); +#endif + VTK_RELEASE_MUTEX(); + return id; + } + + // get a unique id for this object + // just use vtkJavaIdCount and then increment + // to handle loop around make sure the id isn't currently in use + while (vtkInstanceLookup->GetHashTableValue(vtkJavaIdCount)) + { + vtkJavaIdCount++; + if (vtkJavaIdCount > 268435456) vtkJavaIdCount = 1; + } + id = vtkJavaIdCount; + vtkInstanceLookup->AddHashEntry((void *)(size_t)vtkJavaIdCount,ptr); + +#ifdef JNI_VERSION_1_2 + vtkPointerLookup->AddHashEntry(ptr,(void *)env->NewWeakGlobalRef(obj)); +#else + vtkPointerLookup->AddHashEntry(ptr,(void *)env->NewGlobalRef(obj)); +#endif + vtkJavaSetId(env,obj,vtkJavaIdCount); + +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("RegisterNewObject: Added object to hash id= " << vtkJavaIdCount << " " << ptr); +#endif + vtkJavaIdCount++; + VTK_RELEASE_MUTEX(); + return id; +} + +// delete an object from the hash +// doesn't need a mutex because it is only called from within +// the above func which does have a mutex +JNIEXPORT void vtkJavaDeleteObjectFromHash(JNIEnv *env, int id) +{ + void *ptr; + void *vptr; + + ptr = vtkInstanceLookup->GetHashTableValue(id); + if (!ptr) + { +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("DeleteObjectFromHash: Attempt to delete an object that doesn't exist!"); +#endif + return; + } + vtkInstanceLookup->DeleteHashEntry((void *)(size_t)id); + vtkTypecastLookup->DeleteHashEntry((void *)(size_t)id); + vptr = vtkPointerLookup->GetHashTableValue(ptr); +#ifdef JNI_VERSION_1_2 + env->DeleteWeakGlobalRef((jweak)vptr); +#else + env->DeleteGlobalRef((jobject)vptr); +#endif + vtkPointerLookup->DeleteHashEntry(ptr); +} + +// should we delete this object +JNIEXPORT void vtkJavaDeleteObject(JNIEnv *env,jobject obj) +{ + int id = vtkJavaGetId(env,obj); + + VTK_GET_MUTEX(); + +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("DeleteObject: Deleting id = " << id); +#endif + vtkJavaDeleteObjectFromHash(env, id); + VTK_RELEASE_MUTEX(); +} + + + +JNIEXPORT jobject vtkJavaGetObjectFromPointer(void *ptr) +{ + jobject obj; + +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("GetObjectFromPointer: Checking into pointer " << ptr); +#endif + obj = (jobject)vtkPointerLookup->GetHashTableValue((jobject *)ptr); +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("GetObjectFromPointer: Checking into pointer " << ptr << " obj = " << obj); +#endif + return obj; +} + +JNIEXPORT void *vtkJavaGetPointerFromObject(JNIEnv *env, jobject obj, char *result_type) +{ + void *ptr; + void *(*command)(void *,char *); + int id; + + if (!obj) + { + return NULL; + } + + id = vtkJavaGetId(env,obj); + VTK_GET_MUTEX(); + ptr = vtkInstanceLookup->GetHashTableValue(id); + command = (void *(*)(void *,char *))vtkTypecastLookup->GetHashTableValue(id); + VTK_RELEASE_MUTEX(); + +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("GetPointerFromObject: Checking into id " << id << " ptr = " << ptr); +#endif + + if (!ptr) + { + return NULL; + } + + void* res= command(ptr,result_type); + if (res) + { +#ifdef VTKJAVADEBUG + vtkGenericWarningMacro("GetPointerFromObject: Got id= " << id << " ptr= " << ptr << " " << result_type); +#endif + return res; + } + else + { + vtkGenericWarningMacro("GetPointerFromObject: vtk bad argument, type conversion failed."); + return NULL; + } +} + +JNIEXPORT jobject vtkJavaCreateNewJavaStubForObject(JNIEnv *env, vtkObject* obj) +{ + char fullname[512]; + const char* classname= obj->GetClassName(); + fullname[0]= 'v'; + fullname[1]= 't'; + fullname[2]= 'k'; + fullname[3]= '/'; + strcpy(&fullname[4], classname); + obj->Register(obj); + return vtkJavaCreateNewJavaStub(env, fullname, (void*)obj); +} + +JNIEXPORT jobject vtkJavaCreateNewJavaStub(JNIEnv *env, const char* fullclassname, void* obj) +{ + jclass cl= env->FindClass(fullclassname); + if (!cl) { return NULL; } + + jobject stub= env->NewObject(cl, env->GetMethodID(cl, "","(I)V"), (int)0 ); + vtkJavaRegisterNewObject(env, stub, obj); + env->CallVoidMethod(stub, env->GetMethodID(cl, "VTKCastInit", "()V")); + return stub; +} + + +JNIEXPORT jarray vtkJavaMakeJArrayOfDoubleFromDouble(JNIEnv *env, double *ptr, int size) +{ + jdoubleArray ret; + int i; + jdouble *array; + + ret = env->NewDoubleArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetDoubleArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseDoubleArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfDoubleFromFloat(JNIEnv *env, float *ptr, int size) +{ + jdoubleArray ret; + int i; + jdouble *array; + + ret = env->NewDoubleArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetDoubleArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseDoubleArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromInt(JNIEnv *env, int *ptr, int size) +{ + jintArray ret; + int i; + jint *array; + + ret = env->NewIntArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetIntArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseIntArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromIdType(JNIEnv *env, vtkIdType *ptr, int size) +{ + jintArray ret; + int i; + jint *array; + + ret = env->NewIntArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetIntArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = (int)ptr[i]; + } + + env->ReleaseIntArrayElements(ret,array,0); + return ret; +} + +#if defined(VTK_TYPE_USE_LONG_LONG) +JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromLongLong(JNIEnv *env, long long *ptr, int size) +{ + jintArray ret; + int i; + jint *array; + + ret = env->NewIntArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetIntArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = (int)ptr[i]; + } + + env->ReleaseIntArrayElements(ret,array,0); + return ret; +} +#endif + +#if defined(VTK_TYPE_USE___INT64) +JNIEXPORT jarray vtkJavaMakeJArrayOfIntFrom__Int64(JNIEnv *env, __int64 *ptr, int size) +{ + jintArray ret; + int i; + jint *array; + + ret = env->NewIntArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetIntArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = (int)ptr[i]; + } + + env->ReleaseIntArrayElements(ret,array,0); + return ret; +} +#endif + +JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromSignedChar(JNIEnv *env, signed char *ptr, int size) +{ + jintArray ret; + int i; + jint *array; + + ret = env->NewIntArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetIntArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = (int)ptr[i]; + } + + env->ReleaseIntArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfFloatFromFloat(JNIEnv *env, float *ptr, int size) +{ + jfloatArray ret; + int i; + jfloat *array; + + ret = env->NewFloatArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetFloatArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseFloatArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfShortFromShort(JNIEnv *env, short *ptr, int size) +{ + jshortArray ret; + int i; + jshort *array; + + ret = env->NewShortArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetShortArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseShortArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfByteFromUnsignedChar(JNIEnv *env, unsigned char *ptr, int size) +{ + jbyteArray ret; + int i; + jbyte *array; + + ret = env->NewByteArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetByteArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseByteArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfLongFromLong(JNIEnv *env, long *ptr, int size) +{ + cout.flush(); + jlongArray ret; + int i; + jlong *array; + + ret = env->NewLongArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetLongArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseLongArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedLongFromUnsignedLong(JNIEnv *env,unsigned long *ptr,int size) +{ + cout.flush(); + jlongArray ret; + int i; + jlong *array; + + ret = env->NewLongArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetLongArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseLongArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedShortFromUnsignedShort(JNIEnv *env,unsigned short *ptr,int size) +{ + cout.flush(); + jshortArray ret; + int i; + jshort *array; + + ret = env->NewShortArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetShortArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseShortArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedCharFromUnsignedChar(JNIEnv *env,unsigned char *ptr,int size) +{ + cout.flush(); + jbyteArray ret; + int i; + jbyte *array; + + ret = env->NewByteArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetByteArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseByteArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedIntFromUnsignedInt(JNIEnv *env,unsigned int *ptr,int size) +{ + cout.flush(); + jintArray ret; + int i; + jint *array; + + ret = env->NewIntArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetIntArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseIntArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT jarray vtkJavaMakeJArrayOfCharFromChar(JNIEnv *env, char *ptr, int size) +{ + cout.flush(); + jcharArray ret; + int i; + jchar *array; + + ret = env->NewCharArray(size); + if (ret == 0) + { + // should throw an exception here + return 0; + } + + array = env->GetCharArrayElements(ret,NULL); + + // copy the data + for (i = 0; i < size; i++) + { + array[i] = ptr[i]; + } + + env->ReleaseCharArrayElements(ret,array,0); + return ret; +} + +JNIEXPORT char *vtkJavaUTFToChar(JNIEnv *env, jstring in) +{ + char *result; + const char *inBytes; + int length, i; + int resultLength = 1; + + length = env->GetStringUTFLength(in); + inBytes = env->GetStringUTFChars(in,NULL); + + for (i = 0; i < length; i++) + { + if ((inBytes[i] & 0x80) == 0) resultLength++; + } + result = new char [resultLength]; + + resultLength = 0; // the 0 versus 1 up above is on purpose + for (i = 0; i < length; i++) + { + if ((inBytes[i] & 0x80) == 0) + { + result[resultLength] = inBytes[i]; + resultLength++; + } + } + result[resultLength] = '\0'; + env->ReleaseStringUTFChars(in,inBytes); + return result; +} + +JNIEXPORT jstring vtkJavaMakeJavaString(JNIEnv *env, const char *in) +{ + if (!in) { + return env->NewStringUTF(""); + } else { + return env->NewStringUTF(in); + } +} + +//**jcp this is the callback inteface stub for Java. no user parms are passed +//since the callback must be a method of a class. We make the rash assumption +//that the pointer will anchor any required other elements for the +//called functions. - edited by km +JNIEXPORT void vtkJavaVoidFunc(void* f) +{ + vtkJavaVoidFuncArg *iprm = (vtkJavaVoidFuncArg *)f; + // make sure we have a valid method ID + if (iprm->mid) + { + JNIEnv *e; + // it should already be atached +#ifdef JNI_VERSION_1_2 + iprm->vm->AttachCurrentThread((void **)(&e),NULL); +#else + iprm->vm->AttachCurrentThread((JNIEnv_**)(&e),NULL); +#endif + e->CallVoidMethod(iprm->uobj,iprm->mid,NULL); + } +} + +JNIEXPORT void vtkJavaVoidFuncArgDelete(void* arg) +{ + vtkJavaVoidFuncArg *arg2; + + arg2 = (vtkJavaVoidFuncArg *)arg; + + JNIEnv *e; + // it should already be atached +#ifdef JNI_VERSION_1_2 + arg2->vm->AttachCurrentThread((void **)(&e),NULL); +#else + arg2->vm->AttachCurrentThread((JNIEnv_**)(&e),NULL); +#endif + // free the structure + e->DeleteGlobalRef(arg2->uobj); + delete arg2; +} + +jobject vtkJavaExportedGetObjectFromPointer(void *ptr) +{ + return vtkJavaGetObjectFromPointer(ptr); +} + +void* vtkJavaExportedGetPointerFromObject(JNIEnv *env,jobject obj, + char *result_type) +{ + return vtkJavaGetPointerFromObject(env, obj, result_type); +} + +vtkJavaCommand::vtkJavaCommand() +{ + this->vm = NULL; +} + +vtkJavaCommand::~vtkJavaCommand() +{ + JNIEnv *e; + // it should already be atached +#ifdef JNI_VERSION_1_2 + this->vm->AttachCurrentThread((void **)(&e),NULL); +#else + this->vm->AttachCurrentThread((JNIEnv_**)(&e),NULL); +#endif + // free the structure + e->DeleteGlobalRef(this->uobj); +} + +void vtkJavaCommand::Execute(vtkObject *, unsigned long, void *) +{ + // make sure we have a valid method ID + if (this->mid) + { + JNIEnv *e; + // it should already be atached +#ifdef JNI_VERSION_1_2 + this->vm->AttachCurrentThread((void **)(&e),NULL); +#else + this->vm->AttachCurrentThread((JNIEnv_**)(&e),NULL); +#endif + e->CallVoidMethod(this->uobj,this->mid,NULL); + } +} + diff --git a/Common/vtkJavaUtil.h b/Common/vtkJavaUtil.h new file mode 100644 index 0000000..21520e5 --- /dev/null +++ b/Common/vtkJavaUtil.h @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJavaUtil.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __vtkJavaUtil_h +#define __vtkJavaUtil_h + +#include "vtkSystemIncludes.h" +#include +#include "vtkCommand.h" + + +extern JNIEXPORT int vtkJavaGetId(JNIEnv *env,jobject obj); + +extern JNIEXPORT int vtkJavaRegisterNewObject(JNIEnv *env, jobject obj, void *ptr); +extern JNIEXPORT void vtkJavaRegisterCastFunction(JNIEnv *env, jobject obj, int id, void *tcFunc); + +extern JNIEXPORT void *vtkJavaGetPointerFromObject(JNIEnv *env,jobject obj, + char *result_type); +extern JNIEXPORT void vtkJavaDeleteObject(JNIEnv *env, jobject obj); +extern JNIEXPORT jobject vtkJavaGetObjectFromPointer(void *ptr); +extern JNIEXPORT char *vtkJavaUTFToChar(JNIEnv *env, jstring in); +extern JNIEXPORT jstring vtkJavaMakeJavaString(JNIEnv *env, const char *in); + +extern JNIEXPORT jarray vtkJavaMakeJArrayOfFloatFromFloat(JNIEnv *env, + float *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfDoubleFromFloat(JNIEnv *env, + float *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfDoubleFromDouble(JNIEnv *env, + double *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfShortFromShort(JNIEnv *env, short *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromInt(JNIEnv *env, int *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromIdType(JNIEnv *env, vtkIdType *arr, int size); +#if defined(VTK_TYPE_USE_LONG_LONG) +extern JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromLongLong(JNIEnv *env, long long *arr, int size); +#endif +#if defined(VTK_TYPE_USE___INT64) +extern JNIEXPORT jarray vtkJavaMakeJArrayOfIntFrom__Int64(JNIEnv *env, __int64 *arr, int size); +#endif +extern JNIEXPORT jarray vtkJavaMakeJArrayOfIntFromSignedChar(JNIEnv *env, signed char *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfLongFromLong(JNIEnv *env, long *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfByteFromUnsignedChar(JNIEnv *env, unsigned char *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfByteFromChar(JNIEnv *env, char *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfCharFromChar(JNIEnv *env, char *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedCharFromUnsignedChar(JNIEnv *env, unsigned char *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedIntFromUnsignedInt(JNIEnv *env, unsigned int *arr, int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedShortFromUnsignedShort(JNIEnv *env,unsigned short *ptr,int size); +extern JNIEXPORT jarray vtkJavaMakeJArrayOfUnsignedLongFromUnsignedLong(JNIEnv *env, unsigned long *arr, int size); + +extern JNIEXPORT jobject vtkJavaCreateNewJavaStubForObject(JNIEnv *env, vtkObject* obj); +extern JNIEXPORT jobject vtkJavaCreateNewJavaStub(JNIEnv *env, + const char* fullclassname, void* obj); + + +// this is the void pointer parameter passed to the vtk callback routines on +// behalf of the Java interface for callbacks. +struct vtkJavaVoidFuncArg +{ + JavaVM *vm; + jobject uobj; + jmethodID mid; +} ; + +extern JNIEXPORT void vtkJavaVoidFunc(void *); +extern JNIEXPORT void vtkJavaVoidFuncArgDelete(void *); + +class vtkJavaCommand : public vtkCommand +{ +public: + static vtkJavaCommand *New() { return new vtkJavaCommand; }; + + void SetGlobalRef(jobject obj) { this->uobj = obj; }; + void SetMethodID(jmethodID id) { this->mid = id; }; + void AssignJavaVM(JNIEnv *env) { env->GetJavaVM(&(this->vm)); }; + + void Execute(vtkObject *, unsigned long, void *); + + JavaVM *vm; + jobject uobj; + jmethodID mid; +protected: + vtkJavaCommand(); + ~vtkJavaCommand(); +}; + +#endif diff --git a/Common/vtkLargeInteger.cxx b/Common/vtkLargeInteger.cxx new file mode 100644 index 0000000..89abf5a --- /dev/null +++ b/Common/vtkLargeInteger.cxx @@ -0,0 +1,923 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLargeInteger.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// code taken from +// Arbitrarily large numbers +// +// Author Matthew Caryl +// Created 13.3.97 + +#include "vtkLargeInteger.h" + +const unsigned int BIT_INCREMENT = 32; + +int maximum(int a, int b) +{ + return a > b ? a : b; +} + +int minimum(int a, int b) +{ + return a < b ? a : b; +} + +long vtkpow(long a, long b) +{ + long a1 = a; + long b1 = b; + long c = 1; + + while (b1 >= 1) + { + while ( ( b & 1 ) == 0) + { + b1 = b1 / 2; + a1 = a1 * a1; + } + b1 = b1 - 1; + c = c * a1; + } + return c; +} + +void vtkLargeInteger::Contract() +{ + while (this->Number[this->Sig] == 0 && this->Sig > 0) + { + this->Sig--; + } +} + + +vtkLargeInteger::vtkLargeInteger(void) +{ + this->Number = new char[BIT_INCREMENT]; + this->Number[0] = 0; + this->Negative = 0; + this->Max = BIT_INCREMENT - 1; + this->Sig = 0; +} + +#if defined(VTK_TYPE_USE_LONG_LONG) +vtkLargeInteger::vtkLargeInteger(long long n) +{ + this->Negative = n < 0 ? 1 : 0; + n = n < 0 ? -n : n; // strip of sign + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} + +vtkLargeInteger::vtkLargeInteger(unsigned long long n) +{ + this->Negative = 0; + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} +#endif + +#if defined(VTK_TYPE_USE___INT64) +vtkLargeInteger::vtkLargeInteger(__int64 n) +{ + this->Negative = n < 0 ? 1 : 0; + n = n < 0 ? -n : n; // strip of sign + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} + +vtkLargeInteger::vtkLargeInteger(unsigned __int64 n) +{ + this->Negative = 0; + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} +#endif + +vtkLargeInteger::vtkLargeInteger(long n) +{ + this->Negative = n < 0 ? 1 : 0; + n = n < 0 ? -n : n; // strip of sign + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} + +vtkLargeInteger::vtkLargeInteger(unsigned long n) +{ + this->Negative = 0; + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} + +vtkLargeInteger::vtkLargeInteger(unsigned int n) +{ + this->Negative = 0; + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} + +vtkLargeInteger::vtkLargeInteger(int n) +{ + this->Negative = n < 0 ? 1 : 0; + n = n < 0 ? -n : n; // strip of sign + this->Number = new char[BIT_INCREMENT]; + for (unsigned int i = 0; i < BIT_INCREMENT; i++) + { + this->Number[i] = n & 1; + n >>= 1; + } + this->Max = BIT_INCREMENT - 1; + this->Sig = BIT_INCREMENT - 1; + this->Contract(); // remove leading 0s +} + +vtkLargeInteger::vtkLargeInteger(const vtkLargeInteger& n) +{ + this->Number = new char[n.Max + 1]; + this->Negative = n.Negative; + this->Max = n.Max; + this->Sig = n.Sig; + for (int i = this->Sig; i >= 0; i--) + { + this->Number[i] = n.Number[i]; + } +} + +vtkLargeInteger::~vtkLargeInteger(void) +{ + delete []this->Number; +} + +char vtkLargeInteger::CastToChar(void) const +{ + return this->CastToLong(); +} + +short vtkLargeInteger::CastToShort(void) const +{ + return this->CastToLong(); +} + +int vtkLargeInteger::CastToInt(void) const +{ + return this->CastToLong(); +} + +long vtkLargeInteger::CastToLong(void) const +{ + long n = 0; + + for (int i = this->Sig; i >= 0; i--) + { + n <<= 1; + n |= this->Number[i]; + } + if (this->Negative) + { + return -n; + } + + return n; +} + +// convert to an unsigned long, return max if bigger than unsigned long +unsigned long vtkLargeInteger::CastToUnsignedLong(void) const +{ + unsigned long n = 0; + + if (this->Sig >= (8*sizeof(unsigned long))) + { + for (int i = (8*sizeof(unsigned long)); i > 0; i--) + { + n <<= 1; + n |= 1; + } + } + else + { + for (int i = this->Sig; i >= 0; i--) + { + n <<= 1; + n |= this->Number[i]; + } + } + + return n; +} + +int vtkLargeInteger::IsEven(void) const +{ + return this->Number[0] == 0; +} + +int vtkLargeInteger::IsOdd(void) const +{ + return this->Number[0] == 1; +} + +int vtkLargeInteger::GetLength(void) const +{ + return this->Sig + 1; +} + +int vtkLargeInteger::GetBit(unsigned int p) const +{ + if (p <= this->Sig) // check if within current size + { + return this->Number[p]; + } + + return 0; +} + +int vtkLargeInteger::IsZero(void) const +{ + return (this->Sig == 0 && this->Number[0] == 0); +} + +int vtkLargeInteger::GetSign(void) const +{ + return this->Negative; +} + +void vtkLargeInteger::Truncate(unsigned int n) +{ + if (n < 1) // either set to zero + { + this->Sig = 0; + this->Number[0] = 0; + this->Negative = 0; + } + else if (this->Sig > n - 1) // or chop down + { + this->Sig = n - 1; + this->Contract(); // may have revealed leading zeros + } +} + +void vtkLargeInteger::Complement(void) +{ + if (!this->IsZero()) // can't have negative zeros + { + this->Negative = !this->Negative; + } +} + +int vtkLargeInteger::operator==(const vtkLargeInteger& n) const +{ + if (this->Sig != n.Sig) // check size + { + return 0; + } + + if (this->Negative != n.Negative) // check sign + { + return 0; + } + + for (int i = this->Sig; i >= 0; i--) + { + if (this->Number[i] != n.Number[i]) // check bits + { + return 0; + } + } + + return 1; +} + +int vtkLargeInteger::operator!=(const vtkLargeInteger& n) const +{ + return !(*this == n); +} + +int vtkLargeInteger::IsSmaller(const vtkLargeInteger& n) const +{ + if (this->Sig < n.Sig) // check size + { + return 1; + } + if (this->Sig > n.Sig) // check size + { + return 0; + } + + for (int i = this->Sig; i >= 0; i--) + { + if (this->Number[i] < n.Number[i]) // check bits + { + return 1; + } + if (this->Number[i] > n.Number[i]) + { + return 0; + } + } + + return 0; +} + +int vtkLargeInteger::IsGreater(const vtkLargeInteger& n) const +{ + if (this->Sig > n.Sig) // check size + { + return 1; + } + if (this->Sig < n.Sig) // check sign + { + return 0; + } + + for (int i = this->Sig; i >= 0; i--) + { + if (this->Number[i] > n.Number[i]) // check bits + { + return 1; + } + if (this->Number[i] < n.Number[i]) + { + return 0; + } + } + + return 0; +} + +int vtkLargeInteger::operator<(const vtkLargeInteger& n) const +{ + if (this->Negative & !n.Negative) // try to make judgement using signs + return 1; + else if (!this->Negative & n.Negative) + return 0; + else if (this->Negative) + return !this->IsSmaller(n); + else + return this->IsSmaller(n); +} + +int vtkLargeInteger::operator<=(const vtkLargeInteger& n) const +{ + return *this < n || *this == n; +} + +int vtkLargeInteger::operator>(const vtkLargeInteger& n) const +{ + return !(*this <= n); +} + +int vtkLargeInteger::operator>=(const vtkLargeInteger& n) const +{ + return !(*this < n); +} + +void vtkLargeInteger::Expand(unsigned int n) +{ + if (n < this->Sig) // don't need to expand + { + return; + } + if (this->Max < n) // need to make a larger array + { + char* new_number = new char[n + 1]; + for (int i = this->Sig; i >= 0; i--) + { + new_number[i] = this->Number[i]; + } + delete []this->Number; + this->Number = new_number; + this->Max = n; + } + // zero top of array + for (unsigned int i = this->Sig + 1; i <= this->Max; i++) + { + this->Number[i] = 0; + } + this->Sig = n; +} + +vtkLargeInteger& vtkLargeInteger::operator=(const vtkLargeInteger& n) +{ + if (this == &n) // same object + { + return *this; + } + this->Expand(n.Sig); // make equal sizes + this->Sig = n.Sig; // might have been larger + for (int i = this->Sig; i >= 0; i--) + { + this->Number[i] = n.Number[i]; + } + this->Negative = n.Negative; + return *this; +} + +void vtkLargeInteger::Plus(const vtkLargeInteger& n) +{ + int m = maximum(this->Sig + 1, n.Sig + 1); + this->Expand(m); // allow for overflow + unsigned int i = 0; + int carry = 0; + for (; i <= n.Sig; i++) // add overlap + { + carry += this->Number[i] + n.Number[i]; + this->Number[i] = carry & 1; + carry /= 2; + } + for (; carry != 0; i++) // continue with carry + { + carry += this->Number[i]; + this->Number[i] = carry & 1; + carry /= 2; + } + this->Contract(); +} + +void vtkLargeInteger::Minus(const vtkLargeInteger& n) +{ + int m = maximum(this->Sig, n.Sig); + this->Expand(m); + unsigned int i = 0; + int carry = 0; + for (; i <= n.Sig; i++) // subtract overflow + { + carry += this->Number[i] - n.Number[i]; + this->Number[i] = (carry + 2) & 1; + carry = carry < 0 ? -1 : 0; + } + for (; carry != 0; i++) // continue with carry + { + carry += this->Number[i]; + this->Number[i] = (carry + 2) & 1; + carry = carry < 0 ? -1 : 0; + } + this->Contract(); +} + +vtkLargeInteger& vtkLargeInteger::operator+=(const vtkLargeInteger& n) +{ + if ((this->Negative ^ n.Negative) == 0) // cope with negatives + { + this->Plus(n); + } + else + { + if (this->IsSmaller(n)) + { + vtkLargeInteger m(*this); + *this = n; + this->Minus(m); + } + else + { + this->Minus(n); + } + if (this->IsZero()) + { + this->Negative = 0; + } + } + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator-=(const vtkLargeInteger& n) +{ + if ((this->Negative ^ n.Negative) == 1) // cope with negatives + { + this->Plus(n); + } + else + { + if (this->IsSmaller(n)) + { + vtkLargeInteger m(*this); + *this = n; + this->Minus(m); + this->Complement(); + } + else + { + this->Minus(n); + } + if (this->IsZero()) + { + this->Negative = 0; + } + } + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator<<=(int n) +{ + int i; + + if (n < 0) // avoid negatives + { + *this >>= -n; + return *this; + } + this->Expand(this->Sig + n); + + // first shift + for (i = this->Sig; i >= n; i--) + { + this->Number[i] = this->Number[i - n]; + } + for (i = n - 1; i >= 0; i--) // then fill with 0s + { + this->Number[i] = 0; + } + this->Contract(); + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator>>=(int n) +{ + if (n < 0) // avoid negatives + { + *this <<= -n; + return *this; + } + + // first shift the data + unsigned int i; + if (this->Sig >= (unsigned long)n) + { + for (i = 0; i <= (this->Sig - n); i++) + { + this->Number[i] = this->Number[i + n]; + } + } + + // then clear the other values to be safe + int start = (this->Sig - n + 1); + if (start < 0) + { + start = 0; + } + for (i = start; i <= this->Sig; i++) + { + this->Number[i] = 0; + } + + start = start - 1; + if (start < 0) + { + start = 0; + } + this->Sig = start; + if (this->IsZero()) + { + this->Negative = 0; + } + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator++(void) +{ + return (*this += 1); +} + +vtkLargeInteger& vtkLargeInteger::operator--(void) +{ + return (*this -= 1); +} + +vtkLargeInteger vtkLargeInteger::operator++(int) +{ + vtkLargeInteger c = *this; + *this += 1; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator--(int) +{ + vtkLargeInteger c = *this; + *this -= 1; + return c; +} + +vtkLargeInteger& vtkLargeInteger::operator*=(const vtkLargeInteger& n) +{ + vtkLargeInteger c; + int m2 = this->Sig + n.Sig + 1; + this->Expand(m2); + if (n.IsSmaller(*this)) // loop through the smaller number + { + for (unsigned int i = 0; i <= n.Sig; i++) + { + if (n.Number[i] == 1) + { + c.Plus(*this); // add on multiples of two + } + *this <<= 1; + } + } + else + { + vtkLargeInteger m = n; + for (unsigned int i = 0; i <= this->Sig; i++) + { + if (this->Number[i] == 1) + { + c.Plus(m); // add on multiples of two + } + m <<= 1; + } + } + if (c.IsZero()) // check negatives + { + c.Negative = 0; + } + else + { + c.Negative = this->Negative ^ n.Negative; + } + + *this = c; + this->Contract(); + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator/=(const vtkLargeInteger& n) +{ + if (n.IsZero()) // no divide by zero + { + vtkGenericWarningMacro("Divide by zero!"); + return *this; + } + + vtkLargeInteger c; + vtkLargeInteger m = n; + m <<= maximum(this->Sig - n.Sig, 0); // vtkpower of two multiple of n + vtkLargeInteger i = 1; + i = i << (this->Sig - n.Sig); + for (; i > 0; i = i >> 1) + { + if (!m.IsGreater(*this)) + { + this->Minus(m); // subtract of large chunk at time + c += i; + } + m >>= 1; // shrink chunk down + } + if (c.IsZero()) // check negatives + { + c.Negative = 0; + } + else + { + c.Negative = this->Negative ^ n.Negative; + } + *this = c; + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator%=(const vtkLargeInteger& n) +{ + if (n.IsZero()) // no divide by zero + { + vtkGenericWarningMacro("Divide by zero!"); + return *this; + } + + vtkLargeInteger m = n; + m <<= maximum(this->Sig - n.Sig, 0); // power of two multiple of n + for (int i = this->Sig - n.Sig; i >= 0; i--) + { + if (!m.IsGreater(*this)) + { + this->Minus(m); // subtract of large chunk at time + } + m >>= 1; // shrink chunk down + } + if (this->IsZero()) + { + this->Negative = 0; + } + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator&=(const vtkLargeInteger& n) +{ + int m = maximum(this->Sig, n.Sig); + this->Expand(m); // match sizes + for (int i = minimum(this->Sig, n.Sig); i >= 0; i--) + { + this->Number[i] &= n.Number[i]; + } + this->Contract(); + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator|=(const vtkLargeInteger& n) +{ + int m = maximum(this->Sig, n.Sig); + this->Expand(m); // match sizes + for (int i = minimum(this->Sig, n.Sig); i >= 0; i--) + { + this->Number[i] |= n.Number[i]; + } + this->Contract(); + return *this; +} + +vtkLargeInteger& vtkLargeInteger::operator^=(const vtkLargeInteger& n) +{ + int m = maximum(this->Sig, n.Sig); + this->Expand(m); // match sizes + for (int i = minimum(this->Sig, n.Sig); i >= 0; i--) + { + this->Number[i] ^= n.Number[i]; + } + this->Contract(); + return *this; +} + +vtkLargeInteger vtkLargeInteger::operator+(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c += n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator-(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c -= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator*(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c *= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator/(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c /= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator%(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c %= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator&(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c &= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator|(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c |= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator^(const vtkLargeInteger& n) const +{ + vtkLargeInteger c = *this; + c ^= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator<<(int n) const +{ + vtkLargeInteger c = *this; + c <<= n; + return c; +} + +vtkLargeInteger vtkLargeInteger::operator>>(int n) const +{ + vtkLargeInteger c = *this; + c >>= n; + return c; +} + +ostream& operator<<(ostream& s, const vtkLargeInteger& n) +{ + if (n.Negative) + { + s << '-'; + } + for (int i = n.Sig; i >= 0; i--) + { + s << char(n.Number[i] + '0'); + } + return s; +} + +istream& operator>>(istream& s, vtkLargeInteger& n) +{ + char c=0; + while (s.get(c)) // strip any leading spaces + if (c != ' ' && c != '\n' && c != '\r') + { + s.putback(c); + break; + } + n = 0; + while (s.get(c)) // check for this->Negative + { + if (c != '-' && c != '+') + { + s.putback(c); + break; + } + if (c == '-') + n.Negative = !n.Negative; + } + while (s.get(c)) // build digits in reverse + { + if (c != '0' && c != '1') + { + s.putback(c); + break; + } + if (n.Sig > n.Max) { + n.Expand(n.Sig + BIT_INCREMENT); + n.Sig -= BIT_INCREMENT; + } + n.Number[n.Sig++] = c - '0'; + } + if (n.Sig > 0) // put digits right way round + { + n.Sig--; + for (unsigned int j = n.Sig; j > n.Sig / 2; j--) + { + c = n.Number[j]; + n.Number[j] = n.Number[n.Sig - j]; + n.Number[n.Sig - j] = c; + } + n.Contract(); + } + return s; +} diff --git a/Common/vtkLargeInteger.h b/Common/vtkLargeInteger.h new file mode 100644 index 0000000..1241f62 --- /dev/null +++ b/Common/vtkLargeInteger.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLargeInteger.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLargeInteger - class for arbitrarily large ints + +#ifndef __vtkLargeInteger_h +#define __vtkLargeInteger_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkLargeInteger +{ +public: + vtkLargeInteger(void); + vtkLargeInteger(long n); + vtkLargeInteger(unsigned long n); + vtkLargeInteger(int n); + vtkLargeInteger(unsigned int n); + vtkLargeInteger(const vtkLargeInteger& n); +#if defined(VTK_TYPE_USE_LONG_LONG) + vtkLargeInteger(long long n); + vtkLargeInteger(unsigned long long n); +#endif +#if defined(VTK_TYPE_USE___INT64) + vtkLargeInteger(__int64 n); + vtkLargeInteger(unsigned __int64 n); +#endif + + ~vtkLargeInteger(void); + + char CastToChar(void) const; + short CastToShort(void) const; + int CastToInt(void) const; + long CastToLong(void) const; + unsigned long CastToUnsignedLong(void) const; + + int IsEven(void) const; + int IsOdd(void) const; + int GetLength(void) const; // in bits + int GetBit(unsigned int p) const; // p'th bit (from zero) + int IsZero() const; // is zero + int GetSign(void) const; // is negative + + void Truncate(unsigned int n); // reduce to lower n bits + void Complement(void); // * -1 + + int operator==(const vtkLargeInteger& n) const; + int operator!=(const vtkLargeInteger& n) const; + int operator<(const vtkLargeInteger& n) const; + int operator<=(const vtkLargeInteger& n) const; + int operator>(const vtkLargeInteger& n) const; + int operator>=(const vtkLargeInteger& n) const; + + vtkLargeInteger& operator=(const vtkLargeInteger& n); + vtkLargeInteger& operator+=(const vtkLargeInteger& n); + vtkLargeInteger& operator-=(const vtkLargeInteger& n); + vtkLargeInteger& operator<<=(int n); + vtkLargeInteger& operator>>=(int n); + vtkLargeInteger& operator++(void); + vtkLargeInteger& operator--(void); + vtkLargeInteger operator++(int); + vtkLargeInteger operator--(int); + vtkLargeInteger& operator*=(const vtkLargeInteger& n); + vtkLargeInteger& operator/=(const vtkLargeInteger& n); + vtkLargeInteger& operator%=(const vtkLargeInteger& n); + // no change of sign for following operators + vtkLargeInteger& operator&=(const vtkLargeInteger& n); + vtkLargeInteger& operator|=(const vtkLargeInteger& n); + vtkLargeInteger& operator^=(const vtkLargeInteger& n); + + vtkLargeInteger operator+(const vtkLargeInteger& n) const; + vtkLargeInteger operator-(const vtkLargeInteger& n) const; + vtkLargeInteger operator*(const vtkLargeInteger& n) const; + vtkLargeInteger operator/(const vtkLargeInteger& n) const; + vtkLargeInteger operator%(const vtkLargeInteger& n) const; + // no change of sign for following operators + vtkLargeInteger operator&(const vtkLargeInteger& n) const; + vtkLargeInteger operator|(const vtkLargeInteger& n) const; + vtkLargeInteger operator^(const vtkLargeInteger& n) const; + vtkLargeInteger operator<<(int n) const; + vtkLargeInteger operator>>(int n) const; + + friend ostream& operator<<(ostream& s, const vtkLargeInteger& n); + friend istream& operator>>(istream& s, vtkLargeInteger& n); + +private: + char* Number; + int Negative; + unsigned int Sig; + unsigned int Max; + + // unsigned operators + int IsSmaller(const vtkLargeInteger& n) const; // unsigned + int IsGreater(const vtkLargeInteger& n) const; // unsigned + void Expand(unsigned int n); // ensure n'th bit exits + void Contract(); // remove leading 0s + void Plus(const vtkLargeInteger& n); // unsigned + void Minus(const vtkLargeInteger& n); // unsigned +}; + +#endif + + diff --git a/Common/vtkLinearTransform.cxx b/Common/vtkLinearTransform.cxx new file mode 100644 index 0000000..d1a7f1d --- /dev/null +++ b/Common/vtkLinearTransform.cxx @@ -0,0 +1,240 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinearTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLinearTransform.h" + +#include "vtkDataArray.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkLinearTransform, "$Revision: 1.34 $"); + +//------------------------------------------------------------------------ +void vtkLinearTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//------------------------------------------------------------------------ +template +inline void vtkLinearTransformPoint(T1 matrix[4][4], + T2 in[3], T3 out[3]) +{ + T3 x = matrix[0][0]*in[0]+matrix[0][1]*in[1]+matrix[0][2]*in[2]+matrix[0][3]; + T3 y = matrix[1][0]*in[0]+matrix[1][1]*in[1]+matrix[1][2]*in[2]+matrix[1][3]; + T3 z = matrix[2][0]*in[0]+matrix[2][1]*in[1]+matrix[2][2]*in[2]+matrix[2][3]; + + out[0] = x; + out[1] = y; + out[2] = z; +} + +//------------------------------------------------------------------------ +template +inline void vtkLinearTransformDerivative(T1 matrix[4][4], + T2 in[3], T3 out[3], + T4 derivative[3][3]) +{ + vtkLinearTransformPoint(matrix,in,out); + + for (int i = 0; i < 3; i++) + { + derivative[0][i] = matrix[0][i]; + derivative[1][i] = matrix[1][i]; + derivative[2][i] = matrix[2][i]; + } +} + +//------------------------------------------------------------------------ +template +inline void vtkLinearTransformVector(T1 matrix[4][4], + T2 in[3], T3 out[3]) +{ + T3 x = matrix[0][0]*in[0] + matrix[0][1]*in[1] + matrix[0][2]*in[2]; + T3 y = matrix[1][0]*in[0] + matrix[1][1]*in[1] + matrix[1][2]*in[2]; + T3 z = matrix[2][0]*in[0] + matrix[2][1]*in[1] + matrix[2][2]*in[2]; + + out[0] = x; + out[1] = y; + out[2] = z; +} + +//------------------------------------------------------------------------ +template +inline void vtkLinearTransformNormal(T1 mat[4][4], + T2 in[3], T3 out[3]) +{ + // to transform the normal, multiply by the transposed inverse matrix + T1 matrix[4][4]; + memcpy(*matrix,*mat,16*sizeof(T1)); + vtkMatrix4x4::Invert(*matrix,*matrix); + vtkMatrix4x4::Transpose(*matrix,*matrix); + + vtkLinearTransformVector(matrix,in,out); + + vtkMath::Normalize(out); +} + +//------------------------------------------------------------------------ +void vtkLinearTransform::InternalTransformPoint(const float in[3], + float out[3]) +{ + vtkLinearTransformPoint(this->Matrix->Element,in,out); +} + +//------------------------------------------------------------------------ +void vtkLinearTransform::InternalTransformPoint(const double in[3], + double out[3]) +{ + vtkLinearTransformPoint(this->Matrix->Element,in,out); +} + +//------------------------------------------------------------------------ +void vtkLinearTransform::InternalTransformNormal(const float in[3], + float out[3]) +{ + vtkLinearTransformNormal(this->Matrix->Element,in,out); +} + +//------------------------------------------------------------------------ +void vtkLinearTransform::InternalTransformNormal(const double in[3], + double out[3]) +{ + vtkLinearTransformNormal(this->Matrix->Element,in,out); +} + +//------------------------------------------------------------------------ +void vtkLinearTransform::InternalTransformVector(const float in[3], + float out[3]) +{ + vtkLinearTransformVector(this->Matrix->Element,in,out); +} + +//------------------------------------------------------------------------ +void vtkLinearTransform::InternalTransformVector(const double in[3], + double out[3]) +{ + vtkLinearTransformVector(this->Matrix->Element,in,out); +} + +//---------------------------------------------------------------------------- +void vtkLinearTransform::InternalTransformDerivative(const float in[3], + float out[3], + float derivative[3][3]) +{ + vtkLinearTransformDerivative(this->Matrix->Element,in,out,derivative); +} + +//---------------------------------------------------------------------------- +void vtkLinearTransform::InternalTransformDerivative(const double in[3], + double out[3], + double derivative[3][3]) +{ + vtkLinearTransformDerivative(this->Matrix->Element,in,out,derivative); +} + +//---------------------------------------------------------------------------- +// Transform the normals and vectors using the derivative of the +// transformation. Either inNms or inVrs can be set to NULL. +// Normals are multiplied by the inverse transpose of the transform +// derivative, while vectors are simply multiplied by the derivative. +// Note that the derivative of the inverse transform is simply the +// inverse of the derivative of the forward transform. +void vtkLinearTransform::TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs) +{ + this->TransformPoints(inPts,outPts); + if (inNms) + { + this->TransformNormals(inNms,outNms); + } + if (inVrs) + { + this->TransformVectors(inVrs,outVrs); + } +} + +//---------------------------------------------------------------------------- +void vtkLinearTransform::TransformPoints(vtkPoints *inPts, + vtkPoints *outPts) +{ + int n = inPts->GetNumberOfPoints(); + double (*matrix)[4] = this->Matrix->Element; + double point[3]; + + this->Update(); + + for (int i = 0; i < n; i++) + { + inPts->GetPoint(i,point); + + vtkLinearTransformPoint(matrix,point,point); + + outPts->InsertNextPoint(point); + } +} + +//---------------------------------------------------------------------------- +void vtkLinearTransform::TransformNormals(vtkDataArray *inNms, + vtkDataArray *outNms) +{ + int n = inNms->GetNumberOfTuples(); + double norm[3]; + double matrix[4][4]; + + this->Update(); + + // to transform the normal, multiply by the transposed inverse matrix + vtkMatrix4x4::DeepCopy(*matrix,this->Matrix); + vtkMatrix4x4::Invert(*matrix,*matrix); + vtkMatrix4x4::Transpose(*matrix,*matrix); + + for (int i = 0; i < n; i++) + { + inNms->GetTuple(i,norm); + + // use TransformVector because matrix is already transposed & inverted + vtkLinearTransformVector(matrix,norm,norm); + vtkMath::Normalize(norm); + + outNms->InsertNextTuple(norm); + } +} + +//---------------------------------------------------------------------------- +void vtkLinearTransform::TransformVectors(vtkDataArray *inNms, + vtkDataArray *outNms) +{ + vtkIdType n = inNms->GetNumberOfTuples(); + double vec[3]; + + this->Update(); + + double (*matrix)[4] = this->Matrix->Element; + + for (vtkIdType i = 0; i < n; i++) + { + inNms->GetTuple(i,vec); + + vtkLinearTransformVector(matrix,vec,vec); + + outNms->InsertNextTuple(vec); + } +} + diff --git a/Common/vtkLinearTransform.h b/Common/vtkLinearTransform.h new file mode 100644 index 0000000..035e57f --- /dev/null +++ b/Common/vtkLinearTransform.h @@ -0,0 +1,194 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinearTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLinearTransform - abstract superclass for linear transformations +// .SECTION Description +// vtkLinearTransform provides a generic interface for linear +// (affine or 12 degree-of-freedom) geometric transformations. +// .SECTION see also +// vtkTransform vtkIdentityTransform + + +#ifndef __vtkLinearTransform_h +#define __vtkLinearTransform_h + +#include "vtkHomogeneousTransform.h" + +class VTK_COMMON_EXPORT vtkLinearTransform : public vtkHomogeneousTransform +{ +public: + + vtkTypeRevisionMacro(vtkLinearTransform,vtkHomogeneousTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Apply the transformation to a normal. + // You can use the same array to store both the input and output. + void TransformNormal(const float in[3], float out[3]) { + this->Update(); this->InternalTransformNormal(in,out); }; + + // Description: + // Apply the transformation to a double-precision normal. + // You can use the same array to store both the input and output. + void TransformNormal(const double in[3], double out[3]) { + this->Update(); this->InternalTransformNormal(in,out); }; + + // Description: + // Synonymous with TransformDoubleNormal(x,y,z). + // Use this if you are programming in python, tcl or Java. + double *TransformNormal(double x, double y, double z) { + return this->TransformDoubleNormal(x,y,z); } + double *TransformNormal(const double normal[3]) { + return this->TransformDoubleNormal(normal[0],normal[1],normal[2]); }; + + // Description: + // Apply the transformation to an (x,y,z) normal. + // Use this if you are programming in python, tcl or Java. + float *TransformFloatNormal(float x, float y, float z) { + this->InternalFloatPoint[0] = x; + this->InternalFloatPoint[1] = y; + this->InternalFloatPoint[2] = z; + this->TransformNormal(this->InternalFloatPoint,this->InternalFloatPoint); + return this->InternalFloatPoint; }; + float *TransformFloatNormal(const float normal[3]) { + return this->TransformFloatNormal(normal[0],normal[1],normal[2]); }; + + // Description: + // Apply the transformation to a double-precision (x,y,z) normal. + // Use this if you are programming in python, tcl or Java. + double *TransformDoubleNormal(double x, double y, double z) { + this->InternalDoublePoint[0] = x; + this->InternalDoublePoint[1] = y; + this->InternalDoublePoint[2] = z; + this->TransformNormal(this->InternalDoublePoint,this->InternalDoublePoint); + return this->InternalDoublePoint; }; + double *TransformDoubleNormal(const double normal[3]) { + return this->TransformDoubleNormal(normal[0],normal[1],normal[2]); }; + + // Description: + // Synonymous with TransformDoubleVector(x,y,z). + // Use this if you are programming in python, tcl or Java. + double *TransformVector(double x, double y, double z) { + return this->TransformDoubleVector(x,y,z); } + double *TransformVector(const double normal[3]) { + return this->TransformDoubleVector(normal[0],normal[1],normal[2]); }; + + // Description: + // Apply the transformation to a vector. + // You can use the same array to store both the input and output. + void TransformVector(const float in[3], float out[3]) { + this->Update(); this->InternalTransformVector(in,out); }; + + // Description: + // Apply the transformation to a double-precision vector. + // You can use the same array to store both the input and output. + void TransformVector(const double in[3], double out[3]) { + this->Update(); this->InternalTransformVector(in,out); }; + + // Description: + // Apply the transformation to an (x,y,z) vector. + // Use this if you are programming in python, tcl or Java. + float *TransformFloatVector(float x, float y, float z) { + this->InternalFloatPoint[0] = x; + this->InternalFloatPoint[1] = y; + this->InternalFloatPoint[2] = z; + this->TransformVector(this->InternalFloatPoint,this->InternalFloatPoint); + return this->InternalFloatPoint; }; + float *TransformFloatVector(const float vec[3]) { + return this->TransformFloatVector(vec[0],vec[1],vec[2]); }; + + // Description: + // Apply the transformation to a double-precision (x,y,z) vector. + // Use this if you are programming in python, tcl or Java. + double *TransformDoubleVector(double x, double y, double z) { + this->InternalDoublePoint[0] = x; + this->InternalDoublePoint[1] = y; + this->InternalDoublePoint[2] = z; + this->TransformVector(this->InternalDoublePoint,this->InternalDoublePoint); + return this->InternalDoublePoint; }; + double *TransformDoubleVector(const double vec[3]) { + return this->TransformDoubleVector(vec[0],vec[1],vec[2]); }; + + // Description: + // Apply the transformation to a series of points, and append the + // results to outPts. + void TransformPoints(vtkPoints *inPts, vtkPoints *outPts); + + // Description: + // Apply the transformation to a series of normals, and append the + // results to outNms. + virtual void TransformNormals(vtkDataArray *inNms, vtkDataArray *outNms); + + // Description: + // Apply the transformation to a series of vectors, and append the + // results to outVrs. + virtual void TransformVectors(vtkDataArray *inVrs, vtkDataArray *outVrs); + + // Description: + // Apply the transformation to a combination of points, normals + // and vectors. + void TransformPointsNormalsVectors(vtkPoints *inPts, + vtkPoints *outPts, + vtkDataArray *inNms, + vtkDataArray *outNms, + vtkDataArray *inVrs, + vtkDataArray *outVrs); + + // Description: + // Just like GetInverse, but it includes a typecast to + // vtkLinearTransform. + vtkLinearTransform *GetLinearInverse() { + return (vtkLinearTransform *)this->GetInverse(); }; + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + void InternalTransformPoint(const float in[3], float out[3]); + void InternalTransformPoint(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + virtual void InternalTransformNormal(const float in[3], float out[3]); + virtual void InternalTransformNormal(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + virtual void InternalTransformVector(const float in[3], float out[3]); + virtual void InternalTransformVector(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation as well as its derivative + // without calling Update. Meant for use only within other VTK + // classes. + void InternalTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InternalTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + +protected: + vtkLinearTransform() {}; + ~vtkLinearTransform() {}; +private: + vtkLinearTransform(const vtkLinearTransform&); // Not implemented. + void operator=(const vtkLinearTransform&); // Not implemented. +}; + +#endif + + + + + diff --git a/Common/vtkLogLookupTable.cxx b/Common/vtkLogLookupTable.cxx new file mode 100644 index 0000000..ec395b8 --- /dev/null +++ b/Common/vtkLogLookupTable.cxx @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLogLookupTable.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLogLookupTable.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkLogLookupTable, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkLogLookupTable); + +// Construct with (minimum,maximum) range 1 to 10 (based on +// logarithmic values). +vtkLogLookupTable::vtkLogLookupTable(int sze, int ext) + : vtkLookupTable(sze,ext) +{ + this->Scale = VTK_SCALE_LOG10; + + this->TableRange[0] = 1; + this->TableRange[1] = 10; +} + +void vtkLogLookupTable::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Common/vtkLogLookupTable.h b/Common/vtkLogLookupTable.h new file mode 100644 index 0000000..e8b0ec2 --- /dev/null +++ b/Common/vtkLogLookupTable.h @@ -0,0 +1,44 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLogLookupTable.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLogLookupTable - map scalars into colors using log (base 10) scale +// .SECTION Description +// This class is an empty shell. Use vtkLookupTable with SetScaleToLog10() +// instead. +// +// .SECTION See Also +// vtkLookupTable + +#ifndef __vtkLogLookupTable_h +#define __vtkLogLookupTable_h + +#include "vtkLookupTable.h" + +class VTK_COMMON_EXPORT vtkLogLookupTable : public vtkLookupTable +{ +public: + static vtkLogLookupTable *New(); + + vtkTypeRevisionMacro(vtkLogLookupTable,vtkLookupTable); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkLogLookupTable(int sze=256, int ext=256); + ~vtkLogLookupTable() {}; +private: + vtkLogLookupTable(const vtkLogLookupTable&); // Not implemented. + void operator=(const vtkLogLookupTable&); // Not implemented. +}; + +#endif diff --git a/Common/vtkLongArray.cxx b/Common/vtkLongArray.cxx new file mode 100644 index 0000000..6c35260 --- /dev/null +++ b/Common/vtkLongArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLongArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(long); + +#define __vtkLongArray_cxx +#include "vtkLongArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkLongArray, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkLongArray); + +//---------------------------------------------------------------------------- +vtkLongArray::vtkLongArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkLongArray::~vtkLongArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkLongArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkLongArray.h b/Common/vtkLongArray.h new file mode 100644 index 0000000..3502f36 --- /dev/null +++ b/Common/vtkLongArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLongArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLongArray - dynamic, self-adjusting array of long +// .SECTION Description +// vtkLongArray is an array of values of type long. It provides +// methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkLongArray_h +#define __vtkLongArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkLongArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE long +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkLongArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkLongArray* New(); + vtkTypeRevisionMacro(vtkLongArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_LONG; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, long* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const long* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const long* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const long* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + long GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, long value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, long f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(long f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + long* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + long* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(long* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkLongArray(vtkIdType numComp=1); + ~vtkLongArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkLongArray(const vtkLongArray&); // Not implemented. + void operator=(const vtkLongArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkLongLongArray.cxx b/Common/vtkLongLongArray.cxx new file mode 100644 index 0000000..dfd6269 --- /dev/null +++ b/Common/vtkLongLongArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLongLongArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(long long); + +#define __vtkLongLongArray_cxx +#include "vtkLongLongArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkLongLongArray, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkLongLongArray); + +//---------------------------------------------------------------------------- +vtkLongLongArray::vtkLongLongArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkLongLongArray::~vtkLongLongArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkLongLongArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkLongLongArray.h b/Common/vtkLongLongArray.h new file mode 100644 index 0000000..f7242c8 --- /dev/null +++ b/Common/vtkLongLongArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLongLongArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLongLongArray - dynamic, self-adjusting array of long long +// .SECTION Description +// vtkLongLongArray is an array of values of type long long. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkLongLongArray_h +#define __vtkLongLongArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkLongLongArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE long long +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkLongLongArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkLongLongArray* New(); + vtkTypeRevisionMacro(vtkLongLongArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_LONG_LONG; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, long long* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const long long* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const long long* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const long long* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + long long GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, long long value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, long long f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(long long f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + long long* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + long long* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(long long* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkLongLongArray(vtkIdType numComp=1); + ~vtkLongLongArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkLongLongArray(const vtkLongLongArray&); // Not implemented. + void operator=(const vtkLongLongArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkLookupTable.cxx b/Common/vtkLookupTable.cxx new file mode 100644 index 0000000..23e9040 --- /dev/null +++ b/Common/vtkLookupTable.cxx @@ -0,0 +1,942 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLookupTable.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLookupTable.h" +#include "vtkBitArray.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkLookupTable, "$Revision: 1.103.4.1 $"); +vtkStandardNewMacro(vtkLookupTable); + +// Construct with range=(0,1); and hsv ranges set up for rainbow color table +// (from red to blue). +vtkLookupTable::vtkLookupTable(int sze, int ext) +{ + this->NumberOfColors = sze; + this->Table = vtkUnsignedCharArray::New(); + this->Table->Register(this); + this->Table->Delete(); + this->Table->SetNumberOfComponents(4); + this->Table->Allocate(4*sze,4*ext); + + this->HueRange[0] = 0.0; + this->HueRange[1] = 0.66667; + + this->SaturationRange[0] = 1.0; + this->SaturationRange[1] = 1.0; + + this->ValueRange[0] = 1.0; + this->ValueRange[1] = 1.0; + + this->AlphaRange[0] = 1.0; + this->AlphaRange[1] = 1.0; + this->Alpha = 1.0; + + this->TableRange[0] = 0.0; + this->TableRange[1] = 1.0; + + this->Ramp = VTK_RAMP_SCURVE; + this->Scale = VTK_SCALE_LINEAR; +} + +//---------------------------------------------------------------------------- +vtkLookupTable::~vtkLookupTable() +{ + this->Table->UnRegister(this); + this->Table = NULL; +} + +//---------------------------------------------------------------------------- +// Scalar values greater than maximum range value are clamped to maximum +// range value. +void vtkLookupTable::SetTableRange(double r[2]) +{ + this->SetTableRange(r[0],r[1]); +} + +//---------------------------------------------------------------------------- +// Set the minimum/maximum scalar values for scalar mapping. Scalar values +// less than minimum range value are clamped to minimum range value. +// Scalar values greater than maximum range value are clamped to maximum +// range value. +void vtkLookupTable::SetTableRange(double rmin, double rmax) +{ + if (this->Scale == VTK_SCALE_LOG10 && + ((rmin > 0 && rmax < 0) || (rmin < 0 && rmax > 0))) + { + vtkErrorMacro("Bad table range for log scale: ["<TableRange[0] == rmin && this->TableRange[1] == rmax) + { + return; + } + + this->TableRange[0] = rmin; + this->TableRange[1] = rmax; + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Have to be careful about the range if scale is logarithmic +void vtkLookupTable::SetScale(int scale) +{ + if (this->Scale == scale) + { + return; + } + this->Scale = scale; + this->Modified(); + + double rmin = this->TableRange[0]; + double rmax = this->TableRange[1]; + + if (this->Scale == VTK_SCALE_LOG10 && + ((rmin > 0 && rmax < 0) || (rmin < 0 && rmax > 0))) + { + this->TableRange[0] = 1.0; + this->TableRange[1] = 10.0; + vtkErrorMacro("Bad table range for log scale: ["<NumberOfColors = sz; + int a = this->Table->Allocate(4*this->NumberOfColors,4*ext); + this->Modified(); + return a; +} + +//---------------------------------------------------------------------------- +// Force the lookup table to rebuild +void vtkLookupTable::ForceBuild() +{ + int i; + double hue, sat, val, hinc, sinc, vinc, ainc; + double rgba[4], alpha; + unsigned char *c_rgba; + + int maxIndex = this->NumberOfColors - 1; + + if( maxIndex ) + { + hinc = (this->HueRange[1] - this->HueRange[0])/maxIndex; + sinc = (this->SaturationRange[1] - this->SaturationRange[0])/maxIndex; + vinc = (this->ValueRange[1] - this->ValueRange[0])/maxIndex; + ainc = (this->AlphaRange[1] - this->AlphaRange[0])/maxIndex; + } + else + { + hinc = sinc = vinc = ainc = 0.0; + } + + for (i = 0; i <= maxIndex; i++) + { + hue = this->HueRange[0] + i*hinc; + sat = this->SaturationRange[0] + i*sinc; + val = this->ValueRange[0] + i*vinc; + alpha = this->AlphaRange[0] + i*ainc; + + vtkMath::HSVToRGB(hue, sat, val, &rgba[0], &rgba[1], &rgba[2]); + rgba[3] = alpha; + + c_rgba = this->Table->WritePointer(4*i,4); + + switch(this->Ramp) + { + case VTK_RAMP_SCURVE: + { + c_rgba[0] = static_cast + (127.5*(1.0+cos((1.0-static_cast(rgba[0]))*3.141593))); + c_rgba[1] = static_cast + (127.5*(1.0+cos((1.0-static_cast(rgba[1]))*3.141593))); + c_rgba[2] = static_cast + (127.5*(1.0+cos((1.0-static_cast(rgba[2]))*3.141593))); + c_rgba[3] = static_cast (alpha*255.0); + /* same code, but with rounding + c_rgba[0] = static_cast + (127.5f*(1.0f + (double)cos(double((1.0f-rgba[0])*3.141593f)))+0.5f); + c_rgba[1] = static_cast + (127.5f*(1.0f + (double)cos(double((1.0f-rgba[1])*3.141593f)))+0.5f); + c_rgba[2] = static_cast + (127.5f*(1.0f + (double)cos(double((1.0f-rgba[2])*3.141593f)))+0.5f); + c_rgba[3] = static_cast(rgba[3]*255.0f + 0.5f); + */ + } + break; + case VTK_RAMP_LINEAR: + { + c_rgba[0] = static_cast((rgba[0])*255.0f + 0.5f); + c_rgba[1] = static_cast((rgba[1])*255.0f + 0.5f); + c_rgba[2] = static_cast((rgba[2])*255.0f + 0.5f); + c_rgba[3] = static_cast(rgba[3]*255.0f + 0.5f); + } + break; + case VTK_RAMP_SQRT: + { + c_rgba[0] = static_cast((sqrt(rgba[0]))*255.0f + 0.5f); + c_rgba[1] = static_cast((sqrt(rgba[1]))*255.0f + 0.5f); + c_rgba[2] = static_cast((sqrt(rgba[2]))*255.0f + 0.5f); + c_rgba[3] = static_cast((sqrt(rgba[3]))*255.0f + 0.5f); + } + break; + } + } + this->BuildTime.Modified(); +} + +//---------------------------------------------------------------------------- +// Generate lookup table from hue, saturation, value, alpha min/max values. +// Table is built from linear ramp of each value. +void vtkLookupTable::Build() +{ + if (this->Table->GetNumberOfTuples() < 1 || + (this->GetMTime() > this->BuildTime && + this->InsertTime <= this->BuildTime)) + { + this->ForceBuild(); + } +} + +//---------------------------------------------------------------------------- +// get the color for a scalar value +void vtkLookupTable::GetColor(double v, double rgb[3]) +{ + unsigned char *rgb8 = this->MapValue(v); + + rgb[0] = rgb8[0]/255.0; + rgb[1] = rgb8[1]/255.0; + rgb[2] = rgb8[2]/255.0; +} + +//---------------------------------------------------------------------------- +// get the opacity (alpha) for a scalar value +double vtkLookupTable::GetOpacity(double v) +{ + unsigned char *rgb8 = this->MapValue(v); + + return rgb8[3]/255.0; +} + +//---------------------------------------------------------------------------- +// There is a little more to this than simply taking the log10 of the +// two range values: we do conversion of negative ranges to positive +// ranges, and conversion of zero to a 'very small number' +void vtkLookupTableLogRange(double range[2], double logRange[2]) +{ + double rmin = range[0]; + double rmax = range[1]; + + if (rmin == 0) + { + rmin = 1.0e-6*(rmax - rmin); + if (rmax < 0) + { + rmin = -rmin; + } + } + if (rmax == 0) + { + rmax = 1.0e-6*(rmin - rmax); + if (rmin < 0) + { + rmax = -rmax; + } + } + if (rmin < 0 && rmax < 0) + { + logRange[0] = log10(-(double)rmin); + logRange[1] = log10(-(double)rmax); + } + else if (rmin > 0 && rmax > 0) + { + logRange[0] = log10((double)rmin); + logRange[1] = log10((double)rmax); + } +} + +//---------------------------------------------------------------------------- +// Apply log to value, with appropriate constraints. +inline double vtkApplyLogScale(double v, double range[2], + double logRange[2]) +{ + // is the range set for negative numbers? + if (range[0] < 0) + { + if (v < 0) + { + v = log10(-static_cast(v)); + } + else if (range[0] > range[1]) + { + v = logRange[0]; + } + else + { + v = logRange[1]; + } + } + else + { + if (v > 0) + { + v = log10(static_cast(v)); + } + else if (range[0] < range[1]) + { + v = logRange[0]; + } + else + { + v = logRange[1]; + } + } + return v; +} + +//---------------------------------------------------------------------------- +// Apply shift/scale to the scalar value v and do table lookup. +inline unsigned char *vtkLinearLookup(double v, + unsigned char *table, + double maxIndex, + double shift, double scale) +{ + double findx = (v + shift)*scale; + if (findx < 0) + { + findx = 0; + } + if (findx > maxIndex) + { + findx = maxIndex; + } + return &table[4*static_cast(findx)]; + /* round + return &table[4*(int)(findx + 0.5f)]; + */ +} + +//---------------------------------------------------------------------------- +// Given a scalar value v, return an index into the lookup table +vtkIdType vtkLookupTable::GetIndex(double v) +{ + double maxIndex = this->NumberOfColors - 1; + double shift, scale; + + if (this->Scale == VTK_SCALE_LOG10) + { // handle logarithmic scale + double logRange[2]; + vtkLookupTableLogRange(this->TableRange, logRange); + shift = -logRange[0]; + if (logRange[1] <= logRange[0]) + { + scale = VTK_DOUBLE_MAX; + } + else + { + /* while this looks like the wrong scale, it is the correct scale + * taking into account the truncation to int that happens below. */ + scale = (maxIndex + 1)/(logRange[1] - logRange[0]); + } + v = vtkApplyLogScale(v, this->TableRange, logRange); + } + else + { // plain old linear + shift = -this->TableRange[0]; + if (this->TableRange[1] <= this->TableRange[0]) + { + scale = VTK_DOUBLE_MAX; + } + else + { + /* while this looks like the wrong scale, it is the correct scale + * taking into account the truncation to int that happens below. */ + scale = (maxIndex + 1)/(this->TableRange[1] - this->TableRange[0]); + } + } + + // map to an index + double findx = (v + shift)*scale; + if (findx < 0) + { + findx = 0; + } + if (findx > maxIndex) + { + findx = maxIndex; + } + return static_cast(findx); +} + +//---------------------------------------------------------------------------- +// Given a table, set the internal table and set the number of colors. +void vtkLookupTable::SetTable(vtkUnsignedCharArray *table) +{ + if (table != this->Table && table != NULL) + { + // Check for incorrect arrays. + if (table->GetNumberOfComponents() != this->Table->GetNumberOfComponents()) + { + vtkErrorMacro(<<"Number of components in given table (" + << table->GetNumberOfComponents() + << ") is incorrect, it should have " + << this->Table->GetNumberOfComponents() + << "." ); + return; + } + this->Table->UnRegister(this); + this->Table = table; + this->Table->Register(this); + this->NumberOfColors = this->Table->GetNumberOfTuples(); + // If InsertTime is not modified the array will be rebuilt. So we + // use the same approach that the SetTableValue function does. + this->InsertTime.Modified(); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Given a scalar value v, return an rgba color value from lookup table. +unsigned char *vtkLookupTable::MapValue(double v) +{ + int idx = this->GetIndex(v); + return (this->Table->GetPointer(0) + 4*idx); +} + +//---------------------------------------------------------------------------- +// accelerate the mapping by copying the data in 32-bit chunks instead +// of 8-bit chunks +template +void vtkLookupTableMapData(vtkLookupTable *self, T *input, + unsigned char *output, int length, + int inIncr, int outFormat) +{ + int i = length; + double *range = self->GetTableRange(); + double maxIndex = self->GetNumberOfColors() - 1; + double shift, scale; + unsigned char *table = self->GetPointer(0); + unsigned char *cptr; + double alpha; + + if ( (alpha=self->GetAlpha()) >= 1.0 ) //no blending required + { + if (self->GetScale() == VTK_SCALE_LOG10) + { + double val; + double logRange[2]; + vtkLookupTableLogRange(range, logRange); + shift = -logRange[0]; + if (logRange[1] <= logRange[0]) + { + scale = VTK_DOUBLE_MAX; + } + else + { + /* while this looks like the wrong scale, it is the correct scale + * taking into account the truncation to int that happens below. */ + scale = (maxIndex + 1)/(logRange[1] - logRange[0]); + } + if (outFormat == VTK_RGBA) + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_RGB) + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_LUMINANCE_ALPHA) + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + *output++ = cptr[3]; + input += inIncr; + } + } + else // outFormat == VTK_LUMINANCE + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + input += inIncr; + } + } + }//if log scale + + else //not log scale + { + shift = -range[0]; + if (range[1] <= range[0]) + { + scale = VTK_DOUBLE_MAX; + } + else + { + /* while this looks like the wrong scale, it is the correct scale + * taking into account the truncation to int that happens below. */ + scale = (maxIndex + 1)/(range[1] - range[0]); + } + + if (outFormat == VTK_RGBA) + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_RGB) + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_LUMINANCE_ALPHA) + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + *output++ = cptr[3]; + input += inIncr; + } + } + else // outFormat == VTK_LUMINANCE + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + input += inIncr; + } + } + }//if not log lookup + }//if blending not needed + + else //blend with the specified alpha + { + if (self->GetScale() == VTK_SCALE_LOG10) + { + double val; + double logRange[2]; + vtkLookupTableLogRange(range, logRange); + shift = -logRange[0]; + if (logRange[1] <= logRange[0]) + { + scale = VTK_DOUBLE_MAX; + } + else + { + /* while this looks like the wrong scale, it is the correct scale + * taking into account the truncation to int that happens below. */ + scale = (maxIndex + 1)/(logRange[1] - logRange[0]); + } + if (outFormat == VTK_RGBA) + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = static_cast((*cptr)*alpha); cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_RGB) + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_LUMINANCE_ALPHA) + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + *output++ = static_cast(alpha*cptr[3]); + input += inIncr; + } + } + else // outFormat == VTK_LUMINANCE + { + while (--i >= 0) + { + val = vtkApplyLogScale(*input, range, logRange); + cptr = vtkLinearLookup(val, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + input += inIncr; + } + } + }//log scale with blending + + else //no log scale with blending + { + shift = -range[0]; + if (range[1] <= range[0]) + { + scale = VTK_DOUBLE_MAX; + } + else + { + /* while this looks like the wrong scale, it is the correct scale + * taking into account the truncation to int that happens below. */ + scale = (maxIndex + 1)/(range[1] - range[0]); + } + + if (outFormat == VTK_RGBA) + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = static_cast((*cptr)*alpha); cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_RGB) + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = *cptr++; + *output++ = *cptr++; + *output++ = *cptr++; + input += inIncr; + } + } + else if (outFormat == VTK_LUMINANCE_ALPHA) + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + *output++ = static_cast(cptr[3]*alpha); + input += inIncr; + } + } + else // outFormat == VTK_LUMINANCE + { + while (--i >= 0) + { + cptr = vtkLinearLookup(*input, table, maxIndex, shift, scale); + *output++ = static_cast(cptr[0]*0.30 + cptr[1]*0.59 + + cptr[2]*0.11 + 0.5); + input += inIncr; + } + } + }//no log scale + }//alpha blending +} + +//---------------------------------------------------------------------------- +// Although this is a relatively expensive calculation, +// it is only done on the first render. Colors are cached +// for subsequent renders. +template +void vtkLookupTableMapMag(vtkLookupTable *self, T *input, + unsigned char *output, int length, + int inIncr, int outFormat) +{ + double tmp, sum; + double *mag; + int i, j; + + mag = new double[length]; + for (i = 0; i < length; ++i) + { + sum = 0; + for (j = 0; j < inIncr; ++j) + { + tmp = (double)(*input); + sum += (tmp * tmp); + ++input; + } + mag[i] = sqrt(sum); + } + + vtkLookupTableMapData(self, mag, output, length, 1, outFormat); + + delete [] mag; +} + + +//---------------------------------------------------------------------------- +void vtkLookupTable::MapScalarsThroughTable2(void *input, + unsigned char *output, + int inputDataType, + int numberOfValues, + int inputIncrement, + int outputFormat) +{ + if (this->UseMagnitude && inputIncrement > 1) + { + switch (inputDataType) + { + vtkTemplateMacro( + vtkLookupTableMapMag(this,static_cast(input),output, + numberOfValues,inputIncrement,outputFormat); + return + ); + case VTK_BIT: + vtkErrorMacro("Cannot comput magnitude of bit array."); + break; + default: + vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType"); + } + } + + switch (inputDataType) + { + case VTK_BIT: + { + vtkIdType i, id; + vtkBitArray *bitArray = vtkBitArray::New(); + bitArray->SetVoidArray(input,numberOfValues,1); + vtkUnsignedCharArray *newInput = vtkUnsignedCharArray::New(); + newInput->SetNumberOfValues(numberOfValues); + for (id=i=0; iSetValue(i, bitArray->GetValue(id)); + } + vtkLookupTableMapData(this, + static_cast(newInput->GetPointer(0)), + output,numberOfValues, + inputIncrement,outputFormat); + newInput->Delete(); + bitArray->Delete(); + } + break; + + vtkTemplateMacro( + vtkLookupTableMapData(this,static_cast(input),output, + numberOfValues,inputIncrement,outputFormat) + ); + default: + vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +// Specify the number of values (i.e., colors) in the lookup +// table. This method simply allocates memory and prepares the table +// for use with SetTableValue(). It differs from Build() method in +// that the allocated memory is not initialized according to HSVA ramps. +void vtkLookupTable::SetNumberOfTableValues(vtkIdType number) +{ + if (this->NumberOfColors == number) + { + return; + } + this->Modified(); + this->NumberOfColors = number; + this->Table->SetNumberOfTuples(number); +} + +//---------------------------------------------------------------------------- +// Directly load color into lookup table. Use [0,1] double values for color +// component specification. Make sure that you've either used the +// Build() method or used SetNumberOfTableValues() prior to using this method. +void vtkLookupTable::SetTableValue(vtkIdType indx, double rgba[4]) +{ + // Check the index to make sure it is valid + if (indx < 0) + { + vtkErrorMacro("Can't set the table value for negative index " << indx); + return; + } + if (indx >= this->NumberOfColors) + { + vtkErrorMacro("Index " << indx << + " is greater than the number of colors " << + this->NumberOfColors); + return; + } + + unsigned char *_rgba = this->Table->WritePointer(4*indx,4); + + _rgba[0] = static_cast(rgba[0]*255.0f + 0.5f); + _rgba[1] = static_cast(rgba[1]*255.0f + 0.5f); + _rgba[2] = static_cast(rgba[2]*255.0f + 0.5f); + _rgba[3] = static_cast(rgba[3]*255.0f + 0.5f); + + this->InsertTime.Modified(); + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Directly load color into lookup table. Use [0,1] double values for color +// component specification. +void vtkLookupTable::SetTableValue(vtkIdType indx, double r, double g, double b, + double a) +{ + double rgba[4]; + rgba[0] = r; rgba[1] = g; rgba[2] = b; rgba[3] = a; + this->SetTableValue(indx,rgba); +} + +//---------------------------------------------------------------------------- +// Return a rgba color value for the given index into the lookup Table. Color +// components are expressed as [0,1] double values. +void vtkLookupTable::GetTableValue(vtkIdType indx, double rgba[4]) +{ + unsigned char *_rgba; + + indx = (indx < 0 ? 0 : (indx >= this->NumberOfColors ? + this->NumberOfColors-1 : indx)); + + _rgba = this->Table->GetPointer(indx*4); + + rgba[0] = _rgba[0]/255.0; + rgba[1] = _rgba[1]/255.0; + rgba[2] = _rgba[2]/255.0; + rgba[3] = _rgba[3]/255.0; +} + +// Return a rgba color value for the given index into the lookup table. Color +// components are expressed as [0,1] double values. +double *vtkLookupTable::GetTableValue(vtkIdType indx) +{ + this->GetTableValue(indx, this->RGBA); + return this->RGBA; +} + +//---------------------------------------------------------------------------- +void vtkLookupTable::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "TableRange: (" << this->TableRange[0] << ", " + << this->TableRange[1] << ")\n"; + os << indent << "Scale: " + << (this->Scale == VTK_SCALE_LOG10 ? "Log10\n" : "Linear\n"); + os << indent << "HueRange: (" << this->HueRange[0] << ", " + << this->HueRange[1] << ")\n"; + os << indent << "SaturationRange: (" << this->SaturationRange[0] << ", " + << this->SaturationRange[1] << ")\n"; + os << indent << "ValueRange: (" << this->ValueRange[0] << ", " + << this->ValueRange[1] << ")\n"; + os << indent << "AlphaRange: (" << this->AlphaRange[0] << ", " + << this->AlphaRange[1] << ")\n"; + os << indent << "NumberOfTableValues: " + << this->GetNumberOfTableValues() << "\n"; + os << indent << "NumberOfColors: " << this->NumberOfColors << "\n"; + os << indent << "Ramp: " + << (this->Ramp == VTK_RAMP_SCURVE ? "SCurve\n" : "Linear\n"); + os << indent << "InsertTime: " <InsertTime.GetMTime() << "\n"; + os << indent << "BuildTime: " <BuildTime.GetMTime() << "\n"; + os << indent << "Table: "; + if( this->Table ) + { + this->Table->PrintSelf(os << "\n", indent.GetNextIndent()); + } + else + { + // Should not happen + os << "(none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkLookupTable::DeepCopy(vtkLookupTable *lut) +{ + if (!lut) + { + return; + } + this->Alpha = lut->Alpha; + this->UseMagnitude = lut->UseMagnitude; + this->VectorMode = lut->VectorMode; + this->VectorComponent = lut->VectorComponent; + this->Scale = lut->Scale; + this->TableRange[0] = lut->TableRange[0]; + this->TableRange[1] = lut->TableRange[1]; + this->HueRange[0] = lut->HueRange[0]; + this->HueRange[1] = lut->HueRange[1]; + this->SaturationRange[0] = lut->SaturationRange[0]; + this->SaturationRange[1] = lut->SaturationRange[1]; + this->ValueRange[0] = lut->ValueRange[0]; + this->ValueRange[1] = lut->ValueRange[1]; + this->AlphaRange[0] = lut->AlphaRange[0]; + this->AlphaRange[1] = lut->AlphaRange[1]; + this->NumberOfColors = lut->NumberOfColors; + this->Ramp = lut->Ramp; + this->InsertTime = lut->InsertTime; + this->BuildTime = lut->BuildTime; + this->Table->DeepCopy(lut->Table); +} + diff --git a/Common/vtkLookupTable.h b/Common/vtkLookupTable.h new file mode 100644 index 0000000..4092305 --- /dev/null +++ b/Common/vtkLookupTable.h @@ -0,0 +1,249 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLookupTable.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLookupTable - map scalar values into colors via a lookup table +// .SECTION Description +// vtkLookupTable is an object that is used by mapper objects to map scalar +// values into rgba (red-green-blue-alpha transparency) color specification, +// or rgba into scalar values. The color table can be created by direct +// insertion of color values, or by specifying hue, saturation, value, and +// alpha range and generating a table. +// +// .SECTION Caveats +// You need to explicitely call Build() when constructing the LUT by hand. +// +// .SECTION See Also +// vtkLogLookupTable vtkWindowLevelLookupTable + +#ifndef __vtkLookupTable_h +#define __vtkLookupTable_h + +#include "vtkScalarsToColors.h" + +#include "vtkUnsignedCharArray.h" // Needed for inline method + +#define VTK_RAMP_LINEAR 0 +#define VTK_RAMP_SCURVE 1 +#define VTK_RAMP_SQRT 2 +#define VTK_SCALE_LINEAR 0 +#define VTK_SCALE_LOG10 1 + +class VTK_COMMON_EXPORT vtkLookupTable : public vtkScalarsToColors +{ +public: + // Description: + // Construct with range=[0,1]; and hsv ranges set up for rainbow color table + // (from red to blue). + static vtkLookupTable *New(); + + vtkTypeRevisionMacro(vtkLookupTable,vtkScalarsToColors); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate a color table of specified size. + int Allocate(int sz=256, int ext=256); + + // Description: + // Generate lookup table from hue, saturation, value, alpha min/max values. + // Table is built from linear ramp of each value. + virtual void Build(); + + // Description: + // Force the lookup table to regenerate from hue, saturation, value, + // and alpha min/max values. Table is built from a linear ramp of + // each value. ForceBuild() is useful if a lookup table has been + // defined manually (using SetTableValue) and then an application + // decides to rebuild the lookup table using the implicit process. + virtual void ForceBuild(); + + // Description: + // Set the shape of the table ramp to either linear or S-curve. + // The default is S-curve, which tails off gradually at either end. + // The equation used for the S-curve is y = (sin((x - 1/2)*pi) + 1)/2, + // while the equation for the linear ramp is simply y = x. For an + // S-curve greyscale ramp, you should set NumberOfTableValues to 402 + // (which is 256*pi/2) to provide room for the tails of the ramp. + // The equation for the SQRT is y = sqrt(x). + vtkSetMacro(Ramp,int); + void SetRampToLinear() { this->SetRamp(VTK_RAMP_LINEAR); }; + void SetRampToSCurve() { this->SetRamp(VTK_RAMP_SCURVE); }; + void SetRampToSQRT() { this->SetRamp(VTK_RAMP_SQRT); }; + vtkGetMacro(Ramp,int); + + // Description: + // Set the type of scale to use, linear or logarithmic. The default + // is linear. If the scale is logarithmic, then the TableRange must not + // cross the value zero. + void SetScale(int scale); + void SetScaleToLinear() { this->SetScale(VTK_SCALE_LINEAR); }; + void SetScaleToLog10() { this->SetScale(VTK_SCALE_LOG10); }; + vtkGetMacro(Scale,int); + + // Description: + // Set/Get the minimum/maximum scalar values for scalar mapping. Scalar + // values less than minimum range value are clamped to minimum range value. + // Scalar values greater than maximum range value are clamped to maximum + // range value. + void SetTableRange(double r[2]); + virtual void SetTableRange(double min, double max); + vtkGetVectorMacro(TableRange,double,2); + + // Description: + // Set the range in hue (using automatic generation). Hue ranges + // between [0,1]. + vtkSetVector2Macro(HueRange,double); + vtkGetVector2Macro(HueRange,double); + + // Description: + // Set the range in saturation (using automatic generation). Saturation + // ranges between [0,1]. + vtkSetVector2Macro(SaturationRange,double); + vtkGetVector2Macro(SaturationRange,double); + + // Description: + // Set the range in value (using automatic generation). Value ranges + // between [0,1]. + vtkSetVector2Macro(ValueRange,double); + vtkGetVector2Macro(ValueRange,double); + + // Description: + // Set the range in alpha (using automatic generation). Alpha ranges from + // [0,1]. + vtkSetVector2Macro(AlphaRange,double); + vtkGetVector2Macro(AlphaRange,double); + + // Description: + // Map one value through the lookup table. + unsigned char *MapValue(double v); + + // Description: + // Map one value through the lookup table and return the color as + // an RGB array of doubles between 0 and 1. + void GetColor(double x, double rgb[3]); + + // Description: + // Map one value through the lookup table and return the alpha value + // (the opacity) as a double between 0 and 1. + double GetOpacity(double v); + + // Description: + // Return the table index associated with a particular value. + virtual vtkIdType GetIndex(double v); + + // Description: + // Specify the number of values (i.e., colors) in the lookup + // table. + void SetNumberOfTableValues(vtkIdType number); + vtkIdType GetNumberOfTableValues() { return this->NumberOfColors; }; + + // Description: + // Directly load color into lookup table. Use [0,1] double values for color + // component specification. Make sure that you've either used the + // Build() method or used SetNumberOfTableValues() prior to using this + // method. + void SetTableValue(vtkIdType indx, double rgba[4]); + + // Description: + // Directly load color into lookup table. Use [0,1] double values for color + // component specification. + void SetTableValue(vtkIdType indx, double r, double g, double b, double a=1.0); + + // Description: + // Return a rgba color value for the given index into the lookup table. Color + // components are expressed as [0,1] double values. + double *GetTableValue(vtkIdType id); + + // Description: + // Return a rgba color value for the given index into the lookup table. Color + // components are expressed as [0,1] double values. + void GetTableValue(vtkIdType id, double rgba[4]); + + // Description: + // Get pointer to color table data. Format is array of unsigned char + // r-g-b-a-r-g-b-a... + unsigned char *GetPointer(const vtkIdType id) { + return this->Table->GetPointer(4*id); }; + + // Description: + // Get pointer to data. Useful for direct writes into object. MaxId is bumped + // by number (and memory allocated if necessary). Id is the location you + // wish to write into; number is the number of rgba values to write. + unsigned char *WritePointer(const vtkIdType id, const int number); + + // Description: + // Sets/Gets the range of scalars which will be mapped. This is a duplicate + // of Get/SetTableRange. + double *GetRange() { return this->GetTableRange(); }; + void SetRange(double min, double max) { this->SetTableRange(min, max); }; + void SetRange(double rng[2]) { this->SetRange(rng[0], rng[1]); }; + + // Description: + // Set the number of colors in the lookup table. Use + // SetNumberOfTableValues() instead, it can be used both before and + // after the table has been built whereas SetNumberOfColors() has no + // effect after the table has been built. + vtkSetClampMacro(NumberOfColors,vtkIdType,2,VTK_LARGE_ID); + vtkGetMacro(NumberOfColors,vtkIdType); + + // Description: + // Set/Get the internal table array that is used to map the scalars + // to colors. The table array is an unsigned char array with 4 + // components representing RGBA. + void SetTable(vtkUnsignedCharArray *); + vtkGetObjectMacro(Table,vtkUnsignedCharArray); + + // Description: + // map a set of scalars through the lookup table + void MapScalarsThroughTable2(void *input, unsigned char *output, + int inputDataType, int numberOfValues, + int inputIncrement, int outputIncrement); + + // Description: + // Copy the contents from another LookupTable + void DeepCopy(vtkLookupTable *lut); + +protected: + vtkLookupTable(int sze=256, int ext=256); + ~vtkLookupTable(); + + vtkIdType NumberOfColors; + vtkUnsignedCharArray *Table; + double TableRange[2]; + double HueRange[2]; + double SaturationRange[2]; + double ValueRange[2]; + double AlphaRange[2]; + int Scale; + int Ramp; + vtkTimeStamp InsertTime; + vtkTimeStamp BuildTime; + double RGBA[4]; //used during conversion process + +private: + vtkLookupTable(const vtkLookupTable&); // Not implemented. + void operator=(const vtkLookupTable&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline unsigned char *vtkLookupTable::WritePointer(const vtkIdType id, + const int number) +{ + this->InsertTime.Modified(); + return this->Table->WritePointer(4*id,4*number); +} + +#endif + + + diff --git a/Common/vtkMath.cxx b/Common/vtkMath.cxx new file mode 100644 index 0000000..0f06890 --- /dev/null +++ b/Common/vtkMath.cxx @@ -0,0 +1,2793 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMath.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkDataArray.h" + +vtkCxxRevisionMacro(vtkMath, "$Revision: 1.97.4.1 $"); +vtkStandardNewMacro(vtkMath); + +long vtkMath::Seed = 1177; // One authors home address + +// +// some constants we need +// +#define VTK_K_A 16807 +#define VTK_K_M 2147483647 /* Mersenne prime 2^31 -1 */ +#define VTK_K_Q 127773 /* VTK_K_M div VTK_K_A */ +#define VTK_K_R 2836 /* VTK_K_M mod VTK_K_A */ +// +// Some useful macros and functions +// +#define VTK_SIGN(x) (( (x) < 0 )?( -1 ):( 1 )) +// avoid dll boundary problems + +//---------------------------------------------------------------------------- +// Generate random numbers between 0.0 and 1.0. +// This is used to provide portability across different systems. +double vtkMath::Random() +{ + long hi, lo; + + // Based on code in "Random Number Generators: Good Ones are Hard to Find," + // by Stephen K. Park and Keith W. Miller in Communications of the ACM, + // 31, 10 (Oct. 1988) pp. 1192-1201. + // Borrowed from: Fuat C. Baran, Columbia University, 1988. + hi = vtkMath::Seed / VTK_K_Q; + lo = vtkMath::Seed % VTK_K_Q; + if ((vtkMath::Seed = VTK_K_A * lo - VTK_K_R * hi) <= 0) + { + Seed += VTK_K_M; + } + return ((double) vtkMath::Seed / VTK_K_M); +} + +//---------------------------------------------------------------------------- +// Initialize seed value. NOTE: Random() has the bad property that +// the first random number returned after RandomSeed() is called +// is proportional to the seed value! To help solve this, call +// RandomSeed() a few times inside seed. This doesn't ruin the +// repeatability of Random(). +// +void vtkMath::RandomSeed(long s) +{ + vtkMath::Seed = s; + + vtkMath::Random(); + vtkMath::Random(); + vtkMath::Random(); +} + +//---------------------------------------------------------------------------- +// Find unit vectors which is perpendicular to this on and to +// each other. +void vtkMath::Perpendiculars(const double x[3], double y[3], double z[3], + double theta) +{ + int dx,dy,dz; + double x2 = x[0]*x[0]; + double y2 = x[1]*x[1]; + double z2 = x[2]*x[2]; + double r = sqrt(x2 + y2 + z2); + + // transpose the vector to avoid divide-by-zero error + if (x2 > y2 && x2 > z2) + { + dx = 0; dy = 1; dz = 2; + } + else if (y2 > z2) + { + dx = 1; dy = 2; dz = 0; + } + else + { + dx = 2; dy = 0; dz = 1; + } + + double a = x[dx]/r; + double b = x[dy]/r; + double c = x[dz]/r; + + double tmp = sqrt(a*a+c*c); + + if (theta != 0) + { + double sintheta = sin(theta); + double costheta = cos(theta); + + if (y) + { + y[dx] = (c*costheta - a*b*sintheta)/tmp; + y[dy] = sintheta*tmp; + y[dz] = (-a*costheta - b*c*sintheta)/tmp; + } + + if (z) + { + z[dx] = (-c*sintheta - a*b*costheta)/tmp; + z[dy] = costheta*tmp; + z[dz] = (a*sintheta - b*c*costheta)/tmp; + } + } + else + { + if (y) + { + y[dx] = c/tmp; + y[dy] = 0; + y[dz] = -a/tmp; + } + + if (z) + { + z[dx] = -a*b/tmp; + z[dy] = tmp; + z[dz] = -b*c/tmp; + } + } +} + +//---------------------------------------------------------------------------- +// Find unit vectors which are perpendicular to this one and to +// each other. +void vtkMath::Perpendiculars(const float x[3], float y[3], float z[3], + double theta) +{ + int dx,dy,dz; + double x2 = x[0]*x[0]; + double y2 = x[1]*x[1]; + double z2 = x[2]*x[2]; + double r = sqrt(x2 + y2 + z2); + + // transpose the vector to avoid divide-by-zero error + if (x2 > y2 && x2 > z2) + { + dx = 0; dy = 1; dz = 2; + } + else if (y2 > z2) + { + dx = 1; dy = 2; dz = 0; + } + else + { + dx = 2; dy = 0; dz = 1; + } + + double a = x[dx]/r; + double b = x[dy]/r; + double c = x[dz]/r; + + double tmp = sqrt(a*a+c*c); + + if (theta != 0) + { + double sintheta = sin(theta); + double costheta = cos(theta); + + if (y) + { + y[dx] = (c*costheta - a*b*sintheta)/tmp; + y[dy] = sintheta*tmp; + y[dz] = (-a*costheta - b*c*sintheta)/tmp; + } + + if (z) + { + z[dx] = (-c*sintheta - a*b*costheta)/tmp; + z[dy] = costheta*tmp; + z[dz] = (a*sintheta - b*c*costheta)/tmp; + } + } + else + { + if (y) + { + y[dx] = c/tmp; + y[dy] = 0; + y[dz] = -a/tmp; + } + + if (z) + { + z[dx] = -a*b/tmp; + z[dy] = tmp; + z[dz] = -b*c/tmp; + } + } +} + +#define VTK_SMALL_NUMBER 1.0e-12 + +//---------------------------------------------------------------------------- +// Solve linear equations Ax = b using Crout's method. Input is square matrix A +// and load vector x. Solution x is written over load vector. The dimension of +// the matrix is specified in size. If error is found, method returns a 0. +int vtkMath::SolveLinearSystem(double **A, double *x, int size) +{ + // if we solving something simple, just solve it + // + if (size == 2) + { + double det, y[2]; + + det = vtkMath::Determinant2x2(A[0][0], A[0][1], A[1][0], A[1][1]); + + if (det == 0.0) + { + // Unable to solve linear system + return 0; + } + + y[0] = (A[1][1]*x[0] - A[0][1]*x[1]) / det; + y[1] = (-A[1][0]*x[0] + A[0][0]*x[1]) / det; + + x[0] = y[0]; + x[1] = y[1]; + return 1; + } + else if (size == 1) + { + if (A[0][0] == 0.0) + { + // Unable to solve linear system + return 0; + } + + x[0] /= A[0][0]; + return 1; + } + + // + // System of equations is not trivial, use Crout's method + // + + // Check on allocation of working vectors + // + int *index, scratch[10]; + index = ( size < 10 ? scratch : new int[size] ); + + // + // Factor and solve matrix + // + if ( vtkMath::LUFactorLinearSystem(A, index, size) == 0 ) + { + return 0; + } + vtkMath::LUSolveLinearSystem(A,index,x,size); + + if (size >= 10 ) delete [] index; + return 1; +} + +//---------------------------------------------------------------------------- +// Invert input square matrix A into matrix AI. Note that A is modified during +// the inversion. The size variable is the dimension of the matrix. Returns 0 +// if inverse not computed. +int vtkMath::InvertMatrix(double **A, double **AI, int size) +{ + int *index=NULL, iScratch[10]; + double *column=NULL, dScratch[10]; + + // Check on allocation of working vectors + // + if ( size <= 10 ) + { + index = iScratch; + column = dScratch; + } + else + { + index = new int[size]; + column = new double[size]; + } + + int retVal = vtkMath::InvertMatrix(A, AI, size, index, column); + + if ( size > 10 ) + { + delete [] index; + delete [] column; + } + + return retVal; +} + +//---------------------------------------------------------------------------- +// Factor linear equations Ax = b using LU decompostion A = LU where L is +// lower triangular matrix and U is upper triangular matrix. Input is +// square matrix A, integer array of pivot indices index[0->n-1], and size +// of square matrix n. Output factorization LU is in matrix A. If error is +// found, method returns 0. +int vtkMath::LUFactorLinearSystem(double **A, int *index, int size) +{ + double scratch[10]; + double *scale = (size<10 ? scratch : new double[size]); + + int i, j, k; + int maxI = 0; + double largest, temp1, temp2, sum; + + // + // Loop over rows to get implicit scaling information + // + for ( i = 0; i < size; i++ ) + { + for ( largest = 0.0, j = 0; j < size; j++ ) + { + if ( (temp2 = fabs(A[i][j])) > largest ) + { + largest = temp2; + } + } + + if ( largest == 0.0 ) + { + vtkGenericWarningMacro(<<"Unable to factor linear system"); + return 0; + } + scale[i] = 1.0 / largest; + } + // + // Loop over all columns using Crout's method + // + for ( j = 0; j < size; j++ ) + { + for (i = 0; i < j; i++) + { + sum = A[i][j]; + for ( k = 0; k < i; k++ ) + { + sum -= A[i][k] * A[k][j]; + } + A[i][j] = sum; + } + // + // Begin search for largest pivot element + // + for ( largest = 0.0, i = j; i < size; i++ ) + { + sum = A[i][j]; + for ( k = 0; k < j; k++ ) + { + sum -= A[i][k] * A[k][j]; + } + A[i][j] = sum; + + if ( (temp1 = scale[i]*fabs(sum)) >= largest ) + { + largest = temp1; + maxI = i; + } + } + // + // Check for row interchange + // + if ( j != maxI ) + { + for ( k = 0; k < size; k++ ) + { + temp1 = A[maxI][k]; + A[maxI][k] = A[j][k]; + A[j][k] = temp1; + } + scale[maxI] = scale[j]; + } + // + // Divide by pivot element and perform elimination + // + index[j] = maxI; + + if ( fabs(A[j][j]) <= VTK_SMALL_NUMBER ) + { + vtkGenericWarningMacro(<<"Unable to factor linear system"); + return 0; + } + + if ( j != (size-1) ) + { + temp1 = 1.0 / A[j][j]; + for ( i = j + 1; i < size; i++ ) + { + A[i][j] *= temp1; + } + } + } + + if (size >= 10 ) delete [] scale; + + return 1; +} + +//---------------------------------------------------------------------------- +// Solve linear equations Ax = b using LU decompostion A = LU where L is +// lower triangular matrix and U is upper triangular matrix. Input is +// factored matrix A=LU, integer array of pivot indices index[0->n-1], +// load vector x[0->n-1], and size of square matrix n. Note that A=LU and +// index[] are generated from method LUFactorLinearSystem). Also, solution +// vector is written directly over input load vector. +void vtkMath::LUSolveLinearSystem(double **A, int *index, + double *x, int size) +{ + int i, j, ii, idx; + double sum; +// +// Proceed with forward and backsubstitution for L and U +// matrices. First, forward substitution. +// + for ( ii = -1, i = 0; i < size; i++ ) + { + idx = index[i]; + sum = x[idx]; + x[idx] = x[i]; + + if ( ii >= 0 ) + { + for ( j = ii; j <= (i-1); j++ ) + { + sum -= A[i][j]*x[j]; + } + } + else if (sum) + { + ii = i; + } + + x[i] = sum; + } +// +// Now, back substitution +// + for ( i = size-1; i >= 0; i-- ) + { + sum = x[i]; + for ( j = i + 1; j < size; j++ ) + { + sum -= A[i][j]*x[j]; + } + x[i] = sum / A[i][i]; + } +} + +#undef VTK_SMALL_NUMBER + +#define VTK_ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);\ + a[k][l]=h+s*(g-h*tau) + +#define VTK_MAX_ROTATIONS 20 + +//#undef VTK_MAX_ROTATIONS + +//#define VTK_MAX_ROTATIONS 50 + +// Jacobi iteration for the solution of eigenvectors/eigenvalues of a nxn +// real symmetric matrix. Square nxn matrix a; size of matrix in n; +// output eigenvalues in w; and output eigenvectors in v. Resulting +// eigenvalues/vectors are sorted in decreasing order; eigenvectors are +// normalized. +template +int vtkJacobiN(T **a, int n, T *w, T **v) +{ + int i, j, k, iq, ip, numPos; + T tresh, theta, tau, t, sm, s, h, g, c, tmp; + T bspace[4], zspace[4]; + T *b = bspace; + T *z = zspace; + + // only allocate memory if the matrix is large + if (n > 4) + { + b = new T[n]; + z = new T[n]; + } + + // initialize + for (ip=0; ip 3 && (fabs(w[ip])+g) == fabs(w[ip]) + && (fabs(w[iq])+g) == fabs(w[iq])) + { + a[ip][iq] = 0.0; + } + else if (fabs(a[ip][iq]) > tresh) + { + h = w[iq] - w[ip]; + if ( (fabs(h)+g) == fabs(h)) + { + t = (a[ip][iq]) / h; + } + else + { + theta = 0.5*h / (a[ip][iq]); + t = 1.0 / (fabs(theta)+sqrt(1.0+theta*theta)); + if (theta < 0.0) + { + t = -t; + } + } + c = 1.0 / sqrt(1+t*t); + s = t*c; + tau = s/(1.0+c); + h = t*a[ip][iq]; + z[ip] -= h; + z[iq] += h; + w[ip] -= h; + w[iq] += h; + a[ip][iq]=0.0; + + // ip already shifted left by 1 unit + for (j = 0;j <= ip-1;j++) + { + VTK_ROTATE(a,j,ip,j,iq); + } + // ip and iq already shifted left by 1 unit + for (j = ip+1;j <= iq-1;j++) + { + VTK_ROTATE(a,ip,j,j,iq); + } + // iq already shifted left by 1 unit + for (j=iq+1; j= VTK_MAX_ROTATIONS ) + { + vtkGenericWarningMacro( + "vtkMath::Jacobi: Error extracting eigenfunctions"); + return 0; + } + + // sort eigenfunctions these changes do not affect accuracy + for (j=0; j= tmp) // why exchage if same? + { + k = i; + tmp = w[k]; + } + } + if (k != j) + { + w[k] = w[j]; + w[j] = tmp; + for (i=0; i> 1) + (n & 1); + for (j=0; j= 0.0 ) + { + numPos++; + } + } +// if ( numPos < ceil(double(n)/double(2.0)) ) + if ( numPos < ceil_half_n) + { + for(i=0; i 4) + { + delete [] b; + delete [] z; + } + return 1; +} + +#undef VTK_ROTATE +#undef VTK_MAX_ROTATIONS + +//---------------------------------------------------------------------------- +int vtkMath::JacobiN(float **a, int n, float *w, float **v) +{ + return vtkJacobiN(a,n,w,v); +} + +//---------------------------------------------------------------------------- +int vtkMath::JacobiN(double **a, int n, double *w, double **v) +{ + return vtkJacobiN(a,n,w,v); +} + + +//---------------------------------------------------------------------------- +// Jacobi iteration for the solution of eigenvectors/eigenvalues of a 3x3 +// real symmetric matrix. Square 3x3 matrix a; output eigenvalues in w; +// and output eigenvectors in v. Resulting eigenvalues/vectors are sorted +// in decreasing order; eigenvectors are normalized. +int vtkMath::Jacobi(float **a, float *w, float **v) +{ + return vtkMath::JacobiN(a, 3, w, v); +} + +//---------------------------------------------------------------------------- +int vtkMath::Jacobi(double **a, double *w, double **v) +{ + return vtkMath::JacobiN(a, 3, w, v); +} + +//---------------------------------------------------------------------------- +// Estimate the condition number of a LU factored matrix. Used to judge the +// accuracy of the solution. The matrix A must have been previously factored +// using the method LUFactorLinearSystem. The condition number is the ratio +// of the infinity matrix norm (i.e., maximum value of matrix component) +// divided by the minimum diagonal value. (This works for triangular matrices +// only: see Conte and de Boor, Elementary Numerical Analysis.) +double vtkMath::EstimateMatrixCondition(double **A, int size) +{ + int i; + int j = 0; + double min=VTK_LARGE_FLOAT, max=(-VTK_LARGE_FLOAT); + + // find the maximum value + for (i=0; i < size; i++) + { + for (j=i; j < size; j++) + { + if ( fabs(A[i][j]) > max ) + { + max = fabs(A[i][j]); + } + } + } + + // find the minimum diagonal value + for (i=0; i < size; i++) + { + if ( fabs(A[i][i]) < min ) + { + min = fabs(A[i][i]); + } + } + + if ( min == 0.0 ) + { + return VTK_LARGE_FLOAT; + } + else + { + return (max/min); + } +} + +//---------------------------------------------------------------------------- +// Solves a cubic equation c0*t^3 + c1*t^2 + c2*t + c3 = 0 when +// c0, c1, c2, and c3 are REAL. +// Solution is motivated by Numerical Recipes In C 2nd Ed. +// Return array contains number of (real) roots (counting multiple roots as one) +// followed by roots themselves. The value in roots[4] is a integer giving +// further information about the roots (see return codes for int SolveCubic()). +double* vtkMath::SolveCubic( double c0, double c1, double c2, double c3 ) +{ + static double roots[5]; + roots[1] = 0.0; + roots[2] = 0.0; + roots[3] = 0.0; + int num_roots; + + roots[4] = vtkMath::SolveCubic(c0, c1, c2, c3, + &roots[1], &roots[2], &roots[3], &num_roots ); + roots[0] = num_roots; + return roots; +} + +//---------------------------------------------------------------------------- +// Solves a cubic equation when c0, c1, c2, And c3 Are REAL. Solution +// is motivated by Numerical Recipes In C 2nd Ed. Roots and number of +// real roots are stored in user provided variables r1, r2, r3, and +// num_roots. Note that the function can return the following integer +// values describing the roots: (0)-no solution; (-1)-infinite number +// of solutions; (1)-one distinct real root of multiplicity 3 (stored +// in r1); (2)-two distinct real roots, one of multiplicity 2 (stored +// in r1 & r2); (3)-three distinct real roots; (-2)-quadratic equation +// with complex conjugate solution (real part of root returned in r1, +// imaginary in r2); (-3)-one real root and a complex conjugate pair +// (real root in r1 and real part of pair in r2 and imaginary in r3). +int vtkMath::SolveCubic( double c0, double c1, double c2, double c3, + double *r1, double *r2, double *r3, int *num_roots ) +{ + double Q, R; + double R_squared; /* R*R */ + double Q_cubed; /* Q*Q*Q */ + double theta; + double A, B; + + // Cubic equation: c0*t^3 + c1*t^2 + c2*t + c3 = 0 + // + // r1, r2, r3 are roots and num_roots is the number + // of real roots + + // Make Sure This Is A Bonafide Cubic Equation + if( c0 != 0.0 ) + { + //Put Coefficients In Right Form + c1 = c1/c0; + c2 = c2/c0; + c3 = c3/c0; + + Q = ((c1*c1) - 3*c2)/9.0; + + R = (2.0*(c1*c1*c1) - 9.0*(c1*c2) + 27.0*c3)/54.0; + + R_squared = R*R; + Q_cubed = Q*Q*Q; + + if( R_squared <= Q_cubed ) + { + if( Q_cubed == 0.0 ) + { + *r1 = -c1/3.0; + *r2 = *r1; + *r3 = *r1; + *num_roots = 1; + return 1; + } + else + { + theta = acos( R / (sqrt(Q_cubed) ) ); + + *r1 = -2.0*sqrt(Q)*cos( theta/3.0 ) - c1/3.0; + *r2 = -2.0*sqrt(Q)*cos( (theta + 2.0*3.141592653589)/3.0) - c1/3.0; + *r3 = -2.0*sqrt(Q)*cos( (theta - 2.0*3.141592653589)/3.0) - c1/3.0; + + *num_roots = 3; + + // Reduce Number Of Roots To Two + if( *r1 == *r2 ) + { + *num_roots = 2; + *r2 = *r3; + } + else if( *r1 == *r3 ) + { + *num_roots = 2; + } + + if( (*r2 == *r3) && (*num_roots == 3) ) + { + *num_roots = 2; + } + + // Reduce Number Of Roots To One + if( (*r1 == *r2) ) + { + *num_roots = 1; + } + } + return *num_roots; + } + else //single real and complex conjugate pair + { + A = -VTK_SIGN(R) * pow(fabs(R) + sqrt(R_squared - Q_cubed), 1.0/3); + + if( A == 0.0 ) + { + B = 0.0; + } + else + { + B = Q/A; + } + + *r1 = (A + B) - c1/3.0; + *r2 = -0.5*(A + B) - c1/3.0; + *r3 = sqrt(3.0)/2.0*(A - B); + + *num_roots = 1; + return (-3); + } + } //if cubic equation + + else // Quadratic Equation: c1*t + c2*t + c3 = 0 + { + // Okay this was not a cubic - lets try quadratic + return vtkMath::SolveQuadratic( c1, c2, c3, r1, r2, num_roots ); + } +} + +//---------------------------------------------------------------------------- +// Solves a quadratic equation c1*t^2 + c2*t + c3 = 0 when c1, c2, and +// c3 are REAL. Solution is motivated by Numerical Recipes In C 2nd +// Ed. Return array contains number of (real) roots (counting +// multiple roots as one) followed by roots themselves. Note that +// roots[3] contains a return code further describing solution - see +// documentation for SolveCubic() for meaining of return codes. +double* vtkMath::SolveQuadratic( double c1, double c2, double c3) +{ + static double roots[4]; + roots[0] = 0.0; + roots[1] = 0.0; + roots[2] = 0.0; + int num_roots; + + roots[3] = vtkMath::SolveQuadratic( c1, c2, c3, &roots[1], &roots[2], + &num_roots ); + roots[0] = num_roots; + return roots; +} + +//---------------------------------------------------------------------------- +// Solves A Quadratic Equation c1*t^2 + c2*t + c3 = 0 when +// c1, c2, and c3 are REAL. +// Solution is motivated by Numerical Recipes In C 2nd Ed. +// Roots and number of roots are stored in user provided variables +// r1, r2, num_roots +int vtkMath::SolveQuadratic( double c1, double c2, double c3, + double *r1, double *r2, int *num_roots ) +{ + double Q; + double determinant; + + // Quadratic equation: c1*t^2 + c2*t + c3 = 0 + + // Make sure this is a quadratic equation + if( c1 != 0.0 ) + { + determinant = c2*c2 - 4*c1*c3; + + if( determinant >= 0.0 ) + { + Q = -0.5 * (c2 + VTK_SIGN(c2)*sqrt(determinant)); + + *r1 = Q / c1; + + if( Q == 0.0 ) + { + *r2 = 0.0; + } + else + { + *r2 = c3 / Q; + } + + *num_roots = 2; + + // Reduce Number Of Roots To One + if( *r1 == *r2 ) + { + *num_roots = 1; + } + return *num_roots; + } + else // Equation Does Not Have Real Roots + { + *num_roots = 0; + return (-2); + } + } + + else // Linear Equation: c2*t + c3 = 0 + { + // Okay this was not quadratic - lets try linear + return vtkMath::SolveLinear( c2, c3, r1, num_roots ); + } +} + +//---------------------------------------------------------------------------- +// Solves a linear equation c2*t + c3 = 0 when c2 and c3 are REAL. +// Solution is motivated by Numerical Recipes In C 2nd Ed. +// Return array contains number of roots followed by roots themselves. +double* vtkMath::SolveLinear( double c2, double c3) +{ + static double roots[3]; + int num_roots; + roots[1] = 0.0; + roots[2] = vtkMath::SolveLinear( c2, c3, &roots[1], &num_roots ); + roots[0] = num_roots; + return roots; +} + +//---------------------------------------------------------------------------- +// Solves a linear equation c2*t + c3 = 0 when c2 and c3 are REAL. +// Solution is motivated by Numerical Recipes In C 2nd Ed. +// Root and number of (real) roots are stored in user provided variables +// r2 and num_roots. +int vtkMath::SolveLinear( double c2, double c3, double *r1, int *num_roots ) +{ + // Linear equation: c2*t + c3 = 0 + // Now this had better be linear + if( c2 != 0.0 ) + { + *r1 = -c3 / c2; + *num_roots = 1; + return *num_roots; + } + else + { + *num_roots = 0; + if ( c3 == 0.0 ) + { + return (-1); + } + } + + return *num_roots; +} + +//---------------------------------------------------------------------------- +// Solves for the least squares best fit matrix for the homogeneous equation X'M' = 0'. +// Uses the method described on pages 40-41 of Computer Vision by +// Forsyth and Ponce, which is that the solution is the eigenvector +// associated with the minimum eigenvalue of T(X)X, where T(X) is the +// transpose of X. +// The inputs and output are transposed matrices. +// Dimensions: X' is numberOfSamples by xOrder, +// M' dimension is xOrder by 1. +// M' should be pre-allocated. All matrices are row major. The resultant +// matrix M' should be pre-multiplied to X' to get 0', or transposed and +// then post multiplied to X to get 0 +int vtkMath::SolveHomogeneousLeastSquares(int numberOfSamples, double **xt, int xOrder, + double **mt) + { + // check dimensional consistency + if (numberOfSamples < xOrder) + { + vtkGenericWarningMacro("Insufficient number of samples. Underdetermined."); + return 0; + } + + int i, j, k; + + // set up intermediate variables + // Allocate matrix to hold X times transpose of X + double **XXt = new double *[xOrder]; // size x by x + // Allocate the array of eigenvalues and eigenvectors + double *eigenvals = new double [xOrder]; + double **eigenvecs = new double *[xOrder]; + + + // Clear the upper triangular region (and btw, allocate the eigenvecs as well) + for (i = 0; i < xOrder; i++) + { + eigenvecs[i] = new double[xOrder]; + XXt[i] = new double[xOrder]; + for (j = 0; j < xOrder; j++) + { + XXt[i][j] = 0.0; + } + } + + // Calculate XXt upper half only, due to symmetry + for (k = 0; k < numberOfSamples; k++) + { + for (i = 0; i < xOrder; i++) + { + for (j = i; j < xOrder; j++) + { + XXt[i][j] += xt[k][i] * xt[k][j]; + } + } + } + + // now fill in the lower half of the XXt matrix + for (i = 0; i < xOrder; i++) + { + for (j = 0; j < i; j++) + { + XXt[i][j] = XXt[j][i]; + } + } + + // Compute the eigenvectors and eigenvalues + vtkMath::JacobiN(XXt, xOrder, eigenvals, eigenvecs); + + // Smallest eigenval is at the end of the list (xOrder-1), and solution is + // corresponding eigenvec. + for (i=0; i VTK_SMALL_NUMBER) + { + allHomogeneous = 0; + homogenFlags[j] = 0; + } + } + } + + // If we've got one system, and it's homogeneous, do it and bail out quickly. + if (allHomogeneous && yOrder == 1) + { + vtkGenericWarningMacro("Detected homogeneous system (Y=0), calling SolveHomogeneousLeastSquares()"); + return vtkMath::SolveHomogeneousLeastSquares(numberOfSamples, xt, xOrder, mt); + } + + + // Ok, we've got more than one system of equations. + // Figure out if we need to calculate the homogeneous equation solution for + // any of them. + if (allHomogeneous) + { + someHomogeneous = 1; + } + else + { + for (j=0; jn-1], and size +// of square matrix n. Output factorization LU is in matrix A. If error is +// found, method returns 0. +//------------------------------------------------------------------ +// For thread safe, temporary memory array tmpSize of length size +// must be passed in. +int vtkMath::LUFactorLinearSystem(double **A, int *index, int size, + double *tmpSize) +{ + int i, j, k; + int maxI = 0; + double largest, temp1, temp2, sum; + + // + // Loop over rows to get implicit scaling information + // + for ( i = 0; i < size; i++ ) + { + for ( largest = 0.0, j = 0; j < size; j++ ) + { + if ( (temp2 = fabs(A[i][j])) > largest ) + { + largest = temp2; + } + } + + if ( largest == 0.0 ) + { + vtkGenericWarningMacro(<<"Unable to factor linear system"); + return 0; + } + tmpSize[i] = 1.0 / largest; + } + // + // Loop over all columns using Crout's method + // + for ( j = 0; j < size; j++ ) + { + for (i = 0; i < j; i++) + { + sum = A[i][j]; + for ( k = 0; k < i; k++ ) + { + sum -= A[i][k] * A[k][j]; + } + A[i][j] = sum; + } + // + // Begin search for largest pivot element + // + for ( largest = 0.0, i = j; i < size; i++ ) + { + sum = A[i][j]; + for ( k = 0; k < j; k++ ) + { + sum -= A[i][k] * A[k][j]; + } + A[i][j] = sum; + + if ( (temp1 = tmpSize[i]*fabs(sum)) >= largest ) + { + largest = temp1; + maxI = i; + } + } + // + // Check for row interchange + // + if ( j != maxI ) + { + for ( k = 0; k < size; k++ ) + { + temp1 = A[maxI][k]; + A[maxI][k] = A[j][k]; + A[j][k] = temp1; + } + tmpSize[maxI] = tmpSize[j]; + } + // + // Divide by pivot element and perform elimination + // + index[j] = maxI; + + if ( fabs(A[j][j]) <= VTK_SMALL_NUMBER ) + { + vtkGenericWarningMacro(<<"Unable to factor linear system"); + return 0; + } + + if ( j != (size-1) ) + { + temp1 = 1.0 / A[j][j]; + for ( i = j + 1; i < size; i++ ) + { + A[i][j] *= temp1; + } + } + } + + return 1; +} + +#undef VTK_SMALL_NUMBER + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// All of the following methods are for dealing with 3x3 matrices +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// helper function, swap two 3-vectors +template +inline void vtkSwapVectors3(T v1[3], T v2[3]) +{ + for (int i = 0; i < 3; i++) + { + T tmp = v1[i]; + v1[i] = v2[i]; + v2[i] = tmp; + } +} + +//---------------------------------------------------------------------------- +// Unrolled LU factorization of a 3x3 matrix with pivoting. +// This decomposition is non-standard in that the diagonal +// elements are inverted, to convert a division to a multiplication +// in the backsubstitution. +template +inline void vtkLUFactor3x3(T A[3][3], int index[3]) +{ + int i,maxI; + T tmp,largest; + T scale[3]; + + // Loop over rows to get implicit scaling information + + for ( i = 0; i < 3; i++ ) + { + largest = fabs(A[i][0]); + if ((tmp = fabs(A[i][1])) > largest) + { + largest = tmp; + } + if ((tmp = fabs(A[i][2])) > largest) + { + largest = tmp; + } + scale[i] = T(1.0)/largest; + } + + // Loop over all columns using Crout's method + + // first column + largest = scale[0]*fabs(A[0][0]); + maxI = 0; + if ((tmp = scale[1]*fabs(A[1][0])) >= largest) + { + largest = tmp; + maxI = 1; + } + if ((tmp = scale[2]*fabs(A[2][0])) >= largest) + { + maxI = 2; + } + if (maxI != 0) + { + vtkSwapVectors3(A[maxI],A[0]); + scale[maxI] = scale[0]; + } + index[0] = maxI; + + A[0][0] = T(1.0)/A[0][0]; + A[1][0] *= A[0][0]; + A[2][0] *= A[0][0]; + + // second column + A[1][1] -= A[1][0]*A[0][1]; + A[2][1] -= A[2][0]*A[0][1]; + largest = scale[1]*fabs(A[1][1]); + maxI = 1; + if ((tmp = scale[2]*fabs(A[2][1])) >= largest) + { + maxI = 2; + vtkSwapVectors3(A[2],A[1]); + scale[2] = scale[1]; + } + index[1] = maxI; + A[1][1] = T(1.0)/A[1][1]; + A[2][1] *= A[1][1]; + + // third column + A[1][2] -= A[1][0]*A[0][2]; + A[2][2] -= A[2][0]*A[0][2] + A[2][1]*A[1][2]; + largest = scale[2]*fabs(A[2][2]); + index[2] = 2; + A[2][2] = T(1.0)/A[2][2]; +} + +//---------------------------------------------------------------------------- +void vtkMath::LUFactor3x3(float A[3][3], int index[3]) +{ + vtkLUFactor3x3(A,index); +} + +//---------------------------------------------------------------------------- +void vtkMath::LUFactor3x3(double A[3][3], int index[3]) +{ + vtkLUFactor3x3(A,index); +} + +//---------------------------------------------------------------------------- +// Backsubsitution with an LU-decomposed matrix. This is the standard +// LU decomposition, except that the diagonals elements have been inverted. +template +inline void vtkLUSolve3x3(const T1 A[3][3], const int index[3], T2 x[3]) +{ + T2 sum; + + // forward substitution + + sum = x[index[0]]; + x[index[0]] = x[0]; + x[0] = sum; + + sum = x[index[1]]; + x[index[1]] = x[1]; + x[1] = sum - A[1][0]*x[0]; + + sum = x[index[2]]; + x[index[2]] = x[2]; + x[2] = sum - A[2][0]*x[0] - A[2][1]*x[1]; + + // back substitution + + x[2] = x[2]*A[2][2]; + x[1] = (x[1] - A[1][2]*x[2])*A[1][1]; + x[0] = (x[0] - A[0][1]*x[1] - A[0][2]*x[2])*A[0][0]; +} + +//---------------------------------------------------------------------------- +void vtkMath::LUSolve3x3(const float A[3][3], + const int index[3], float x[3]) +{ + vtkLUSolve3x3(A,index,x); +} + +//---------------------------------------------------------------------------- +void vtkMath::LUSolve3x3(const double A[3][3], + const int index[3], double x[3]) +{ + vtkLUSolve3x3(A,index,x); +} + +//---------------------------------------------------------------------------- +// this method solves Ay = x for y +template +inline void vtkLinearSolve3x3(const T1 A[3][3], const T2 x[3], T3 y[3]) +{ + int index[3]; + T3 B[3][3]; + for (int i = 0; i < 3; i++) + { + B[i][0] = A[i][0]; + B[i][1] = A[i][1]; + B[i][2] = A[i][2]; + y[i] = x[i]; + } + + vtkMath::LUFactor3x3(B,index); + vtkMath::LUSolve3x3(B,index,y); +} + +//---------------------------------------------------------------------------- +void vtkMath::LinearSolve3x3(const float A[3][3], + const float x[3], float y[3]) +{ + vtkLinearSolve3x3(A,x,y); +} + +//---------------------------------------------------------------------------- +void vtkMath::LinearSolve3x3(const double A[3][3], + const double x[3], double y[3]) +{ + vtkLinearSolve3x3(A,x,y); +} + +//---------------------------------------------------------------------------- +template +inline void vtkMultiply3x3(const T1 A[3][3], const T2 v[3], T3 u[3]) +{ + T3 x = A[0][0]*v[0] + A[0][1]*v[1] + A[0][2]*v[2]; + T3 y = A[1][0]*v[0] + A[1][1]*v[1] + A[1][2]*v[2]; + T3 z = A[2][0]*v[0] + A[2][1]*v[1] + A[2][2]*v[2]; + + u[0] = x; + u[1] = y; + u[2] = z; +} + +//---------------------------------------------------------------------------- +void vtkMath::Multiply3x3(const float A[3][3], const float v[3], float u[3]) +{ + vtkMultiply3x3(A,v,u); +} + +//---------------------------------------------------------------------------- +void vtkMath::Multiply3x3(const double A[3][3], const double v[3], double u[3]) +{ + vtkMultiply3x3(A,v,u); +} + +//---------------------------------------------------------------------------- +template +inline void vtkMultiplyMatrix3x3(const T A[3][3], const T2 B[3][3], + T3 C[3][3]) +{ + T3 D[3][3]; + + for (int i = 0; i < 3; i++) + { + D[0][i] = A[0][0]*B[0][i] + A[0][1]*B[1][i] + A[0][2]*B[2][i]; + D[1][i] = A[1][0]*B[0][i] + A[1][1]*B[1][i] + A[1][2]*B[2][i]; + D[2][i] = A[2][0]*B[0][i] + A[2][1]*B[1][i] + A[2][2]*B[2][i]; + } + + for (int j = 0; j < 3; j++) + { + C[j][0] = D[j][0]; + C[j][1] = D[j][1]; + C[j][2] = D[j][2]; + } +} + +//---------------------------------------------------------------------------- +void vtkMath::Multiply3x3(const float A[3][3], + const float B[3][3], float C[3][3]) +{ + vtkMultiplyMatrix3x3(A,B,C); +} + +//---------------------------------------------------------------------------- +void vtkMath::Multiply3x3(const double A[3][3], + const double B[3][3], double C[3][3]) +{ + vtkMultiplyMatrix3x3(A,B,C); +} + +//---------------------------------------------------------------------------- +template +inline void vtkTranspose3x3(const T1 A[3][3], T2 AT[3][3]) +{ + T2 tmp; + tmp = A[1][0]; + AT[1][0] = A[0][1]; + AT[0][1] = tmp; + tmp = A[2][0]; + AT[2][0] = A[0][2]; + AT[0][2] = tmp; + tmp = A[2][1]; + AT[2][1] = A[1][2]; + AT[1][2] = tmp; + + AT[0][0] = A[0][0]; + AT[1][1] = A[1][1]; + AT[2][2] = A[2][2]; +} + +//---------------------------------------------------------------------------- +void vtkMath::Transpose3x3(const float A[3][3], float AT[3][3]) +{ + vtkTranspose3x3(A,AT); +} + +//---------------------------------------------------------------------------- +void vtkMath::Transpose3x3(const double A[3][3], double AT[3][3]) +{ + vtkTranspose3x3(A,AT); +} + +//---------------------------------------------------------------------------- +template +inline void vtkInvert3x3(const T1 A[3][3], T2 AI[3][3]) +{ + int index[3]; + T2 tmp[3][3]; + + for (int k = 0; k < 3; k++) + { + AI[k][0] = A[k][0]; + AI[k][1] = A[k][1]; + AI[k][2] = A[k][2]; + } + // invert one column at a time + vtkMath::LUFactor3x3(AI,index); + for (int i = 0; i < 3; i++) + { + T2 *x = tmp[i]; + x[0] = x[1] = x[2] = 0.0; + x[i] = 1.0; + vtkMath::LUSolve3x3(AI,index,x); + } + for (int j = 0; j < 3; j++) + { + T2 *x = tmp[j]; + AI[0][j] = x[0]; + AI[1][j] = x[1]; + AI[2][j] = x[2]; + } +} + +//---------------------------------------------------------------------------- +void vtkMath::Invert3x3(const float A[3][3], float AI[3][3]) +{ + vtkInvert3x3(A,AI); +} + +//---------------------------------------------------------------------------- +void vtkMath::Invert3x3(const double A[3][3], double AI[3][3]) +{ + vtkInvert3x3(A,AI); +} + +//---------------------------------------------------------------------------- +template + inline void vtkIdentity3x3(T A[3][3]) +{ + for (int i = 0; i < 3; i++) + { + A[i][0] = A[i][1] = A[i][2] = T(0.0); + A[i][i] = 1.0; + } +} + +//---------------------------------------------------------------------------- +void vtkMath::Identity3x3(float A[3][3]) +{ + vtkIdentity3x3(A); +} + +//---------------------------------------------------------------------------- +void vtkMath::Identity3x3(double A[3][3]) +{ + vtkIdentity3x3(A); +} + +//---------------------------------------------------------------------------- +template + inline void vtkQuaternionToMatrix3x3(T1 quat[4], T2 A[3][3]) +{ + T2 ww = quat[0]*quat[0]; + T2 wx = quat[0]*quat[1]; + T2 wy = quat[0]*quat[2]; + T2 wz = quat[0]*quat[3]; + + T2 xx = quat[1]*quat[1]; + T2 yy = quat[2]*quat[2]; + T2 zz = quat[3]*quat[3]; + + T2 xy = quat[1]*quat[2]; + T2 xz = quat[1]*quat[3]; + T2 yz = quat[2]*quat[3]; + + T2 rr = xx + yy + zz; + // normalization factor, just in case quaternion was not normalized + T2 f = T2(1)/T2(sqrt(ww + rr)); + T2 s = (ww - rr)*f; + f *= 2; + + A[0][0] = xx*f + s; + A[1][0] = (xy + wz)*f; + A[2][0] = (xz - wy)*f; + + A[0][1] = (xy - wz)*f; + A[1][1] = yy*f + s; + A[2][1] = (yz + wx)*f; + + A[0][2] = (xz + wy)*f; + A[1][2] = (yz - wx)*f; + A[2][2] = zz*f + s; +} + +//---------------------------------------------------------------------------- +void vtkMath::QuaternionToMatrix3x3(const float quat[4], float A[3][3]) +{ + vtkQuaternionToMatrix3x3(quat,A); +} + +//---------------------------------------------------------------------------- +void vtkMath::QuaternionToMatrix3x3(const double quat[4], double A[3][3]) +{ + vtkQuaternionToMatrix3x3(quat,A); +} + +//---------------------------------------------------------------------------- +// The solution is based on +// Berthold K. P. Horn (1987), +// "Closed-form solution of absolute orientation using unit quaternions," +// Journal of the Optical Society of America A, 4:629-642 +template +inline void vtkMatrix3x3ToQuaternion(const T1 A[3][3], T2 quat[4]) +{ + T2 N[4][4]; + + // on-diagonal elements + N[0][0] = A[0][0]+A[1][1]+A[2][2]; + N[1][1] = A[0][0]-A[1][1]-A[2][2]; + N[2][2] = -A[0][0]+A[1][1]-A[2][2]; + N[3][3] = -A[0][0]-A[1][1]+A[2][2]; + + // off-diagonal elements + N[0][1] = N[1][0] = A[2][1]-A[1][2]; + N[0][2] = N[2][0] = A[0][2]-A[2][0]; + N[0][3] = N[3][0] = A[1][0]-A[0][1]; + + N[1][2] = N[2][1] = A[1][0]+A[0][1]; + N[1][3] = N[3][1] = A[0][2]+A[2][0]; + N[2][3] = N[3][2] = A[2][1]+A[1][2]; + + T2 eigenvectors[4][4],eigenvalues[4]; + + // convert into format that JacobiN can use, + // then use Jacobi to find eigenvalues and eigenvectors + T2 *NTemp[4],*eigenvectorsTemp[4]; + for (int i = 0; i < 4; i++) + { + NTemp[i] = N[i]; + eigenvectorsTemp[i] = eigenvectors[i]; + } + vtkMath::JacobiN(NTemp,4,eigenvalues,eigenvectorsTemp); + + // the first eigenvector is the one we want + quat[0] = eigenvectors[0][0]; + quat[1] = eigenvectors[1][0]; + quat[2] = eigenvectors[2][0]; + quat[3] = eigenvectors[3][0]; +} + +//---------------------------------------------------------------------------- +void vtkMath::Matrix3x3ToQuaternion(const float A[3][3], float quat[4]) +{ + vtkMatrix3x3ToQuaternion(A,quat); +} + +//---------------------------------------------------------------------------- +void vtkMath::Matrix3x3ToQuaternion(const double A[3][3], double quat[4]) +{ + vtkMatrix3x3ToQuaternion(A,quat); +} + +//---------------------------------------------------------------------------- +// The orthogonalization is done via quaternions in order to avoid +// having to use a singular value decomposition algorithm. +template +inline void vtkOrthogonalize3x3(const T1 A[3][3], T2 B[3][3]) +{ + int i; + + // copy the matrix + for (i = 0; i < 3; i++) + { + B[0][i] = A[0][i]; + B[1][i] = A[1][i]; + B[2][i] = A[2][i]; + } + + // Pivot the matrix to improve accuracy + T2 scale[3]; + int index[3]; + T2 tmp, largest; + + // Loop over rows to get implicit scaling information + for (i = 0; i < 3; i++) + { + largest = fabs(B[i][0]); + if ((tmp = fabs(B[i][1])) > largest) + { + largest = tmp; + } + if ((tmp = fabs(B[i][2])) > largest) + { + largest = tmp; + } + scale[i] = 1.0; + if (largest != 0) + { + scale[i] = T2(1.0)/largest; + } + } + + // first column + index[0] = 0; + largest = scale[0]*fabs(B[0][0]); + if ((tmp = scale[1]*fabs(B[1][0])) >= largest) + { + largest = tmp; + index[0] = 1; + } + if ((tmp = scale[2]*fabs(B[2][0])) >= largest) + { + index[0] = 2; + } + if (index[0] != 0) + { + vtkSwapVectors3(B[index[0]],B[0]); + scale[index[0]] = scale[0]; + } + + // second column + index[1] = 1; + largest = scale[1]*fabs(B[1][1]); + if ((tmp = scale[2]*fabs(B[2][1])) >= largest) + { + index[1] = 2; + vtkSwapVectors3(B[2],B[1]); + } + + // third column + index[2] = 2; + + // A quaternian can only describe a pure rotation, not + // a rotation with a flip, therefore the flip must be + // removed before the matrix is converted to a quaternion. + T2 d = vtkDeterminant3x3(B); + if (d < 0) + { + for (i = 0; i < 3; i++) + { + B[0][i] = -B[0][i]; + B[1][i] = -B[1][i]; + B[2][i] = -B[2][i]; + } + } + + // Do orthogonalization using a quaternion intermediate + // (this, essentially, does the orthogonalization via + // diagonalization of an appropriately constructed symmetric + // 4x4 matrix rather than by doing SVD of the 3x3 matrix) + T2 quat[4]; + vtkMath::Matrix3x3ToQuaternion(B,quat); + vtkMath::QuaternionToMatrix3x3(quat,B); + + // Put the flip back into the orthogonalized matrix. + if (d < 0) + { + for (i = 0; i < 3; i++) + { + B[0][i] = -B[0][i]; + B[1][i] = -B[1][i]; + B[2][i] = -B[2][i]; + } + } + + // Undo the pivoting + if (index[1] != 1) + { + vtkSwapVectors3(B[index[1]],B[1]); + } + if (index[0] != 0) + { + vtkSwapVectors3(B[index[0]],B[0]); + } +} + +//---------------------------------------------------------------------------- +void vtkMath::Orthogonalize3x3(const float A[3][3], float B[3][3]) +{ + vtkOrthogonalize3x3(A,B); +} + +//---------------------------------------------------------------------------- +void vtkMath::Orthogonalize3x3(const double A[3][3], double B[3][3]) +{ + vtkOrthogonalize3x3(A,B); +} + +//---------------------------------------------------------------------------- +float vtkMath::Norm(const float* x, int n) +{ + double sum=0; + for (int i=0; i +inline void vtkDiagonalize3x3(const T1 A[3][3], T2 w[3], T2 V[3][3]) +{ + int i,j,k,maxI; + T2 tmp, maxVal; + + // do the matrix[3][3] to **matrix conversion for Jacobi + T2 C[3][3]; + T2 *ATemp[3],*VTemp[3]; + for (i = 0; i < 3; i++) + { + C[i][0] = A[i][0]; + C[i][1] = A[i][1]; + C[i][2] = A[i][2]; + ATemp[i] = C[i]; + VTemp[i] = V[i]; + } + + // diagonalize using Jacobi + vtkMath::JacobiN(ATemp,3,w,VTemp); + + // if all the eigenvalues are the same, return identity matrix + if (w[0] == w[1] && w[0] == w[2]) + { + vtkMath::Identity3x3(V); + return; + } + + // transpose temporarily, it makes it easier to sort the eigenvectors + vtkMath::Transpose3x3(V,V); + + // if two eigenvalues are the same, re-orthogonalize to optimally line + // up the eigenvectors with the x, y, and z axes + for (i = 0; i < 3; i++) + { + if (w[(i+1)%3] == w[(i+2)%3]) // two eigenvalues are the same + { + // find maximum element of the independant eigenvector + maxVal = fabs(V[i][0]); + maxI = 0; + for (j = 1; j < 3; j++) + { + if (maxVal < (tmp = fabs(V[i][j]))) + { + maxVal = tmp; + maxI = j; + } + } + // swap the eigenvector into its proper position + if (maxI != i) + { + tmp = w[maxI]; + w[maxI] = w[i]; + w[i] = tmp; + vtkSwapVectors3(V[i],V[maxI]); + } + // maximum element of eigenvector should be positive + if (V[maxI][maxI] < 0) + { + V[maxI][0] = -V[maxI][0]; + V[maxI][1] = -V[maxI][1]; + V[maxI][2] = -V[maxI][2]; + } + + // re-orthogonalize the other two eigenvectors + j = (maxI+1)%3; + k = (maxI+2)%3; + + V[j][0] = 0.0; + V[j][1] = 0.0; + V[j][2] = 0.0; + V[j][j] = 1.0; + vtkMath::Cross(V[maxI],V[j],V[k]); + vtkMath::Normalize(V[k]); + vtkMath::Cross(V[k],V[maxI],V[j]); + + // transpose vectors back to columns + vtkMath::Transpose3x3(V,V); + return; + } + } + + // the three eigenvalues are different, just sort the eigenvectors + // to align them with the x, y, and z axes + + // find the vector with the largest x element, make that vector + // the first vector + maxVal = fabs(V[0][0]); + maxI = 0; + for (i = 1; i < 3; i++) + { + if (maxVal < (tmp = fabs(V[i][0]))) + { + maxVal = tmp; + maxI = i; + } + } + // swap eigenvalue and eigenvector + if (maxI != 0) + { + tmp = w[maxI]; + w[maxI] = w[0]; + w[0] = tmp; + vtkSwapVectors3(V[maxI],V[0]); + } + // do the same for the y element + if (fabs(V[1][1]) < fabs(V[2][1])) + { + tmp = w[2]; + w[2] = w[1]; + w[1] = tmp; + vtkSwapVectors3(V[2],V[1]); + } + + // ensure that the sign of the eigenvectors is correct + for (i = 0; i < 2; i++) + { + if (V[i][i] < 0) + { + V[i][0] = -V[i][0]; + V[i][1] = -V[i][1]; + V[i][2] = -V[i][2]; + } + } + // set sign of final eigenvector to ensure that determinant is positive + if (vtkMath::Determinant3x3(V) < 0) + { + V[2][0] = -V[2][0]; + V[2][1] = -V[2][1]; + V[2][2] = -V[2][2]; + } + + // transpose the eigenvectors back again + vtkMath::Transpose3x3(V,V); +} + +//---------------------------------------------------------------------------- +void vtkMath::Diagonalize3x3(const float A[3][3], float w[3], float V[3][3]) +{ + vtkDiagonalize3x3(A,w,V); +} + +//---------------------------------------------------------------------------- +void vtkMath::Diagonalize3x3(const double A[3][3],double w[3],double V[3][3]) +{ + vtkDiagonalize3x3(A,w,V); +} + +//---------------------------------------------------------------------------- +// Perform singular value decomposition on the matrix A: +// A = U * W * VT +// where U and VT are orthogonal W is diagonal (the diagonal elements +// are returned in vector w). +// The matrices U and VT will both have positive determinants. +// The scale factors w are ordered according to how well the +// corresponding eigenvectors (in VT) match the x, y and z axes +// respectively. +// +// The singular value decomposition is used to decompose a linear +// transformation into a rotation, followed by a scale, followed +// by a second rotation. The scale factors w will be negative if +// the determinant of matrix A is negative. +// +// Contributed by David Gobbi (dgobbi@irus.rri.on.ca) +template +inline void vtkSingularValueDecomposition3x3(const T1 A[3][3], + T2 U[3][3], T2 w[3], + T2 VT[3][3]) +{ + int i; + T2 B[3][3]; + + // copy so that A can be used for U or VT without risk + for (i = 0; i < 3; i++) + { + B[0][i] = A[0][i]; + B[1][i] = A[1][i]; + B[2][i] = A[2][i]; + } + + // temporarily flip if determinant is negative + T2 d = vtkMath::Determinant3x3(B); + if (d < 0) + { + for (i = 0; i < 3; i++) + { + B[0][i] = -B[0][i]; + B[1][i] = -B[1][i]; + B[2][i] = -B[2][i]; + } + } + + // orthogonalize, diagonalize, etc. + vtkMath::Orthogonalize3x3(B, U); + vtkMath::Transpose3x3(B, B); + vtkMath::Multiply3x3(B, U, VT); + vtkMath::Diagonalize3x3(VT, w, VT); + vtkMath::Multiply3x3(U, VT, U); + vtkMath::Transpose3x3(VT, VT); + + // re-create the flip + if (d < 0) + { + w[0] = -w[0]; + w[1] = -w[1]; + w[2] = -w[2]; + } + + /* paranoia check: recombine to ensure that the SVD is correct + vtkMath::Transpose3x3(B, B); + + if (d < 0) + { + for (i = 0; i < 3; i++) + { + B[0][i] = -B[0][i]; + B[1][i] = -B[1][i]; + B[2][i] = -B[2][i]; + } + } + + int j; + T2 maxerr = 0; + T2 tmp; + T2 M[3][3]; + T2 W[3][3]; + vtkMath::Identity3x3(W); + W[0][0] = w[0]; W[1][1] = w[1]; W[2][2] = w[2]; + vtkMath::Identity3x3(M); + vtkMath::Multiply3x3(M, U, M); + vtkMath::Multiply3x3(M, W, M); + vtkMath::Multiply3x3(M, VT, M); + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if ((tmp = fabs(B[i][j] - M[i][j])) > maxerr) + { + maxerr = tmp; + } + } + } + + vtkGenericWarningMacro("SingularValueDecomposition max error = " << maxerr); + */ +} + +//---------------------------------------------------------------------------- +void vtkMath::SingularValueDecomposition3x3(const float A[3][3], + float U[3][3], float w[3], + float VT[3][3]) +{ + vtkSingularValueDecomposition3x3(A,U,w,VT); +} + +//---------------------------------------------------------------------------- +void vtkMath::SingularValueDecomposition3x3(const double A[3][3], + double U[3][3], double w[3], + double VT[3][3]) +{ + vtkSingularValueDecomposition3x3(A,U,w,VT); +} + +//---------------------------------------------------------------------------- +void vtkMath::RGBToHSV(float r, float g, float b, + float *h, float *s, float *v) +{ + double dh,ds,dv; + vtkMath::RGBToHSV(r,g,b,&dh,&ds,&dv); + *h = static_cast(dh); + *s = static_cast(ds); + *v = static_cast(dv); +} + +//---------------------------------------------------------------------------- +double* vtkMath::RGBToHSV(double rgb[3]) +{ + return vtkMath::RGBToHSV(rgb[0], rgb[1], rgb[2]); +} + +//---------------------------------------------------------------------------- +double* vtkMath::RGBToHSV(double r, double g, double b) +{ + static double hsv[3]; + vtkMath::RGBToHSV(r, g, b, hsv, hsv + 1, hsv + 2); + return hsv; +} + +//---------------------------------------------------------------------------- +void vtkMath::RGBToHSV(double r, double g, double b, + double *h, double *s, double *v) +{ + double onethird = 1.0 / 3.0; + double onesixth = 1.0 / 6.0; + double twothird = 2.0 / 3.0; + + double cmax, cmin; + + cmax = r; + cmin = r; + if (g > cmax) + { + cmax = g; + } + else if (g < cmin) + { + cmin = g; + } + if (b > cmax) + { + cmax = b; + } + else if (b < cmin) + { + cmin = b; + } + *v = cmax; + + if (*v > 0.0) + { + *s = (cmax - cmin) / cmax; + } + else + { + *s = 0.0; + } + if (*s > 0) + { + if (r == cmax) + { + *h = onesixth * (g - b) / (cmax - cmin); + } + else if (g == cmax) + { + *h = onethird + onesixth * (b - r) / (cmax - cmin); + } + else + { + *h = twothird + onesixth * (r - g) / (cmax - cmin); + } + if (*h < 0.0) + { + *h += 1.0; + } + } + else + { + *h = 0.0; + } +} + +//---------------------------------------------------------------------------- +void vtkMath::HSVToRGB(float h, float s, float v, + float *r, float *g, float *b) +{ + double dr,dg,db; + vtkMath::HSVToRGB(h,s,v,&dr,&dg,&db); + *r = static_cast(dr); + *g = static_cast(dg); + *b = static_cast(db); +} + +//---------------------------------------------------------------------------- +double* vtkMath::HSVToRGB(double hsv[3]) +{ + return vtkMath::HSVToRGB(hsv[0], hsv[1], hsv[2]); +} + +//---------------------------------------------------------------------------- +double* vtkMath::HSVToRGB(double h, double s, double v) +{ + static double rgb[3]; + vtkMath::HSVToRGB(h, s, v, rgb, rgb + 1, rgb + 2); + return rgb; +} + +//---------------------------------------------------------------------------- +void vtkMath::HSVToRGB(double h, double s, double v, + double *r, double *g, double *b) +{ + double onethird = 1.0 / 3.0; + double onesixth = 1.0 / 6.0; + double twothird = 2.0 / 3.0; + double fivesixth = 5.0 / 6.0; + + // compute RGB from HSV + if (h > onesixth && h <= onethird) // green/red + { + *g = 1.0; + *r = (onethird - h) / onesixth; + *b = 0.0; + } + else if (h > onethird && h <= 0.5) // green/blue + { + *g = 1.0; + *b = (h - onethird) / onesixth; + *r = 0.0; + } + else if (h > 0.5 && h <= twothird) // blue/green + { + *b = 1.0; + *g = (twothird - h) / onesixth; + *r = 0.0; + } + else if (h > twothird && h <= fivesixth) // blue/red + { + *b = 1.0; + *r = (h - twothird) / onesixth; + *g = 0.0; + } + else if (h > fivesixth && h <= 1.0) // red/blue + { + *r = 1.0; + *b = (1.0 - h) / onesixth; + *g = 0.0; + } + else // red/green + { + *r = 1.0; + *g = h / onesixth; + *b = 0.0; + } + + // add Saturation to the equation. + *r = (s * *r + (1.0 - s)); + *g = (s * *g + (1.0 - s)); + *b = (s * *b + (1.0 - s)); + + *r *= v; + *g *= v; + *b *= v; +} + +//---------------------------------------------------------------------------- +void vtkMath::LabToXYZ(double lab[3], double xyz[3]) +{ + //LAB to XYZ + double var_Y = ( lab[0] + 16 ) / 116; + double var_X = lab[1] / 500 + var_Y; + double var_Z = var_Y - lab[2] / 200; + + if ( pow(var_Y,3) > 0.008856 ) var_Y = pow(var_Y,3); + else var_Y = ( var_Y - 16 / 116 ) / 7.787; + + if ( pow(var_X,3) > 0.008856 ) var_X = pow(var_X,3); + else var_X = ( var_X - 16 / 116 ) / 7.787; + + if ( pow(var_Z,3) > 0.008856 ) var_Z = pow(var_Z,3); + else var_Z = ( var_Z - 16 / 116 ) / 7.787; + double ref_X = 95.047; + double ref_Y = 100.000; + double ref_Z = 108.883; + xyz[0] = ref_X * var_X; //ref_X = 95.047 Observer= 2 Illuminant= D65 + xyz[1] = ref_Y * var_Y; //ref_Y = 100.000 + xyz[2] = ref_Z * var_Z; //ref_Z = 108.883 +} + + +//---------------------------------------------------------------------------- +void vtkMath::XYZToRGB(double xyz[3], double rgb[3]) +{ + + //double ref_X = 95.047; //Observer = 2° Illuminant = D65 + //double ref_Y = 100.000; + //double ref_Z = 108.883; + + double var_X = xyz[0] / 100; //X = From 0 to ref_X + double var_Y = xyz[1] / 100; //Y = From 0 to ref_Y + double var_Z = xyz[2] / 100; //Z = From 0 to ref_Y + + double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986; + double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415; + double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570; + + if ( var_R > 0.0031308 ) var_R = 1.055 * ( pow(var_R, ( 1 / 2.4 )) ) - 0.055; + else var_R = 12.92 * var_R; + if ( var_G > 0.0031308 ) var_G = 1.055 * ( pow(var_G ,( 1 / 2.4 )) ) - 0.055; + else var_G = 12.92 * var_G; + if ( var_B > 0.0031308 ) var_B = 1.055 * ( pow(var_B, ( 1 / 2.4 )) ) - 0.055; + else var_B = 12.92 * var_B; + + rgb[0] = var_R; + rgb[1] = var_G; + rgb[2] = var_B; + + //clip colors. ideally we would do something different for colors + //out of gamut, but not really sure what to do atm. + if (rgb[0]<0) rgb[0]=0; + if (rgb[1]<0) rgb[1]=0; + if (rgb[2]<0) rgb[2]=0; + if (rgb[0]>1) rgb[0]=1; + if (rgb[1]>1) rgb[1]=1; + if (rgb[2]>1) rgb[2]=1; + +} +//---------------------------------------------------------------------------- +void vtkMath::ClampValues(double *values, + int nb_values, + const double range[2]) +{ + if (!values || nb_values <= 0 || !range) + { + return; + } + + const double *values_end = values + nb_values; + while (values < values_end) + { + if (*values < range[0]) + { + *values = range[0]; + } + else if (*values > range[1]) + { + *values = range[1]; + } + values++; + } +} + +//---------------------------------------------------------------------------- +void vtkMath::ClampValues(const double *values, + int nb_values, + const double range[2], + double *clamped_values) +{ + if (!values || nb_values <= 0 || !range || !clamped_values) + { + return; + } + + const double *values_end = values + nb_values; + while (values < values_end) + { + if (*values < range[0]) + { + *clamped_values = range[0]; + } + else if (*values > range[1]) + { + *clamped_values = range[1]; + } + else + { + *clamped_values = *values; + } + values++; + clamped_values++; + } +} + +//---------------------------------------------------------------------------- +int vtkMath::GetScalarTypeFittingRange( + double range_min, double range_max, double scale, double shift) +{ + class TypeRange + { + public: + int Type; + double Min; + double Max; + }; + + TypeRange FloatTypes[] = + { + { VTK_FLOAT, VTK_FLOAT_MIN, VTK_FLOAT_MAX }, + { VTK_DOUBLE, VTK_DOUBLE_MIN, VTK_DOUBLE_MAX } + }; + + TypeRange IntTypes[] = + { + { VTK_BIT, VTK_BIT_MIN, VTK_BIT_MAX }, + { VTK_CHAR, VTK_CHAR_MIN, VTK_CHAR_MAX }, + { VTK_SIGNED_CHAR, VTK_SIGNED_CHAR_MIN, VTK_SIGNED_CHAR_MAX }, + { VTK_UNSIGNED_CHAR, VTK_UNSIGNED_CHAR_MIN, VTK_UNSIGNED_CHAR_MAX }, + { VTK_SHORT, VTK_SHORT_MIN, VTK_SHORT_MAX }, + { VTK_UNSIGNED_SHORT, VTK_UNSIGNED_SHORT_MIN, VTK_UNSIGNED_SHORT_MAX }, + { VTK_INT, VTK_INT_MIN, VTK_INT_MAX }, + { VTK_UNSIGNED_INT, VTK_UNSIGNED_INT_MIN, VTK_UNSIGNED_INT_MAX }, + { VTK_LONG, VTK_LONG_MIN, VTK_LONG_MAX }, + { VTK_UNSIGNED_LONG, VTK_UNSIGNED_LONG_MIN, VTK_UNSIGNED_LONG_MAX } +#if defined(VTK_TYPE_USE_LONG_LONG) + , + { VTK_LONG_LONG, VTK_LONG_LONG_MIN, VTK_LONG_LONG_MAX }, + { VTK_UNSIGNED_LONG_LONG, + VTK_UNSIGNED_LONG_LONG_MIN, VTK_UNSIGNED_LONG_LONG_MAX } +#endif +#if defined(VTK_TYPE_USE___INT64) + , + { VTK___INT64, VTK___INT64_MIN, VTK___INT64_MAX } +# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + , + { VTK_UNSIGNED___INT64, + VTK_UNSIGNED___INT64_MIN, VTK_UNSIGNED___INT64_MAX } +# endif +#endif + }; + + // If the range, scale or shift are decimal number, just browse + // the decimal types + + double intpart; + + int range_min_is_int = (modf(range_min, &intpart) == 0.0); + int range_max_is_int = (modf(range_max, &intpart) == 0.0); + int scale_is_int = (modf(scale, &intpart) == 0.0); + int shift_is_int = (modf(shift, &intpart) == 0.0); + + range_min = range_min * scale + shift; + range_max = range_max * scale + shift; + + if (range_min_is_int && range_max_is_int && scale_is_int && shift_is_int) + { + for (unsigned int i = 0; i < sizeof(IntTypes) / sizeof(TypeRange); i++) + { + if (IntTypes[i].Min <= range_min && range_max <= IntTypes[i].Max) + { + return IntTypes[i].Type; + } + } + } + + for (unsigned int i = 0; i < sizeof(FloatTypes) / sizeof(TypeRange); i++) + { + if (FloatTypes[i].Min <= range_min && range_max <= FloatTypes[i].Max) + { + return FloatTypes[i].Type; + } + } + + return -1; +} + +//---------------------------------------------------------------------------- +int vtkMath::GetAdjustedScalarRange( + vtkDataArray *array, int comp, double range[2]) +{ + if (!array || comp < 0 || comp >= array->GetNumberOfComponents()) + { + return 0; + } + + array->GetRange(range, comp); + + switch (array->GetDataType()) + { + case VTK_UNSIGNED_CHAR: + range[0] = (double)array->GetDataTypeMin(); + range[1] = (double)array->GetDataTypeMax(); + break; + + case VTK_UNSIGNED_SHORT: + range[0] = (double)array->GetDataTypeMin(); + if (range[1] <= 4095.0) + { + if (range[1] > VTK_UNSIGNED_CHAR_MAX) + { + range[1] = 4095.0; + } + } + else + { + range[1] = (double)array->GetDataTypeMax(); + } + break; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkMath::ExtentIsWithinOtherExtent(int extent1[6], int extent2[6]) +{ + if (!extent1 || !extent2) + { + return 0; + } + + int i; + for (i = 0; i < 6; i += 2) + { + if (extent1[i] < extent2[i] || extent1[i] > extent2[i + 1] || + extent1[i + 1] < extent2[i] || extent1[i + 1] > extent2[i + 1]) + { + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- + +int vtkMath::BoundsIsWithinOtherBounds(double bounds1[6], double bounds2[6], double delta[3]) +{ + if(!bounds1 || !bounds2) + { + return 0; + } + for(int i=0;i<6;i+=2) + { + + if(bounds1[i]+delta[i/2] < bounds2[i] || bounds1[i]-delta[i/2] > bounds2[i+1] || + bounds1[i+1]+delta[i/2] < bounds2[i] || bounds1[i+1]-delta[i/2] > bounds2[i+1]) + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkMath::PointIsWithinBounds(double point[3], double bounds[6], double delta[3]) +{ + if(!point || !bounds || !delta) + { + return 0; + } + for(int i=0;i<3;i++) + if(point[i]+delta[i] < bounds[2*i] || point[i]-delta[i] > bounds[2*i+1]) + return 0; + return 1; + +} + +//---------------------------------------------------------------------------- +void vtkMath::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Seed: " << this->Seed << "\n"; +} + diff --git a/Common/vtkMath.h b/Common/vtkMath.h new file mode 100644 index 0000000..b56cbd0 --- /dev/null +++ b/Common/vtkMath.h @@ -0,0 +1,773 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMath.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMath - performs common math operations +// .SECTION Description +// vtkMath is provides methods to perform common math operations. These +// include providing constants such as Pi; conversion from degrees to +// radians; vector operations such as dot and cross products and vector +// norm; matrix determinant for 2x2 and 3x3 matrices; and random +// number generation. + +#ifndef __vtkMath_h +#define __vtkMath_h + +#include "vtkObject.h" + +class vtkDataArray; + +class VTK_COMMON_EXPORT vtkMath : public vtkObject +{ +public: + static vtkMath *New(); + vtkTypeRevisionMacro(vtkMath,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Useful constants. + static float Pi() {return 3.14159265358979f;}; + static float DegreesToRadians() {return 0.017453292f;}; + static float RadiansToDegrees() {return 57.2957795131f;}; + + // Description: + // Useful constants. (double-precision version) + static double DoubleDegreesToRadians() {return 0.017453292519943295;}; + static double DoublePi() {return 3.1415926535897932384626;}; + static double DoubleRadiansToDegrees() {return 57.29577951308232;}; + + // Description: + // Rounds a float to the nearest integer. + static int Round(float f) { + return static_cast(f + (f >= 0 ? 0.5 : -0.5)); } + static int Round(double f) { + return static_cast(f + (f >= 0 ? 0.5 : -0.5)); } + + static int Floor(double x); + + // Description: + // Dot product of two 3-vectors (float version). + static float Dot(const float x[3], const float y[3]) { + return (x[0]*y[0] + x[1]*y[1] + x[2]*y[2]);}; + + // Description: + // Dot product of two 3-vectors (double-precision version). + static double Dot(const double x[3], const double y[3]) { + return (x[0]*y[0] + x[1]*y[1] + x[2]*y[2]);}; + + // Description: + // Cross product of two 3-vectors. Result vector in z[3]. + static void Cross(const float x[3], const float y[3], float z[3]); + + // Description: + // Cross product of two 3-vectors. Result vector in z[3]. (double-precision + // version) + static void Cross(const double x[3], const double y[3], double z[3]); + + // Description: + // Compute the norm of n-vector. + static float Norm(const float* x, int n); + static double Norm(const double* x, int n); + + // Description: + // Compute the norm of 3-vector. + static float Norm(const float x[3]) { + return static_cast (sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]));}; + + // Description: + // Compute the norm of 3-vector (double-precision version). + static double Norm(const double x[3]) { + return sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);}; + + // Description: + // Normalize (in place) a 3-vector. Returns norm of vector. + static float Normalize(float x[3]); + + // Description: + // Normalize (in place) a 3-vector. Returns norm of vector + // (double-precision version). + static double Normalize(double x[3]); + + // Description: + // Given a unit vector x, find two unit vectors y and z such that + // x cross y = z (i.e. the vectors are perpendicular to each other). + // There is an infinite number of such vectors, specify an angle theta + // to choose one set. If you want only one perpendicular vector, + // specify NULL for z. + static void Perpendiculars(const double x[3], double y[3], double z[3], + double theta); + static void Perpendiculars(const float x[3], float y[3], float z[3], + double theta); + + // Description: + // Compute distance squared between two points. + static float Distance2BetweenPoints(const float x[3], const float y[3]); + + // Description: + // Compute distance squared between two points (double precision version). + static double Distance2BetweenPoints(const double x[3], const double y[3]); + + // Description: + // Dot product of two 2-vectors. The third (z) component is ignored. + static float Dot2D(const float x[3], const float y[3]) { + return (x[0]*y[0] + x[1]*y[1]);}; + + // Description: + // Dot product of two 2-vectors. The third (z) component is + // ignored (double-precision version). + static double Dot2D(const double x[3], const double y[3]) { + return (x[0]*y[0] + x[1]*y[1]);}; + + // Description: + // Compute the norm of a 2-vector. Ignores z-component. + static float Norm2D(const float x[3]) { + return static_cast (sqrt(x[0]*x[0] + x[1]*x[1]));}; + + // Description: + // Compute the norm of a 2-vector. Ignores z-component + // (double-precision version). + static double Norm2D(const double x[3]) { + return sqrt(x[0]*x[0] + x[1]*x[1]);}; + + // Description: + // Normalize (in place) a 2-vector. Returns norm of vector. Ignores + // z-component. + static float Normalize2D(float x[3]); + + // Description: + // Normalize (in place) a 2-vector. Returns norm of vector. Ignores + // z-component (double-precision version). + static double Normalize2D(double x[3]); + + // Description: + // Compute determinant of 2x2 matrix. Two columns of matrix are input. + static float Determinant2x2(const float c1[2], const float c2[2]) { + return (c1[0]*c2[1] - c2[0]*c1[1]);}; + + // Description: + // Calculate the determinant of a 2x2 matrix: | a b | | c d | + static double Determinant2x2(double a, double b, double c, double d) { + return (a * d - b * c);}; + static double Determinant2x2(const double c1[2], const double c2[2]) { + return (c1[0]*c2[1] - c2[0]*c1[1]);}; + + // Description: + // LU Factorization of a 3x3 matrix. The diagonal elements are the + // multiplicative inverse of those in the standard LU factorization. + static void LUFactor3x3(float A[3][3], int index[3]); + static void LUFactor3x3(double A[3][3], int index[3]); + + // Description: + // LU back substitution for a 3x3 matrix. The diagonal elements are the + // multiplicative inverse of those in the standard LU factorization. + static void LUSolve3x3(const float A[3][3], const int index[3], + float x[3]); + static void LUSolve3x3(const double A[3][3], const int index[3], + double x[3]); + + // Description: + // Solve Ay = x for y and place the result in y. The matrix A is + // destroyed in the process. + static void LinearSolve3x3(const float A[3][3], const float x[3], + float y[3]); + static void LinearSolve3x3(const double A[3][3], const double x[3], + double y[3]); + + // Description: + // Multiply a vector by a 3x3 matrix. The result is placed in out. + static void Multiply3x3(const float A[3][3], const float in[3], + float out[3]); + static void Multiply3x3(const double A[3][3], const double in[3], + double out[3]); + + // Description: + // Multiply one 3x3 matrix by another according to C = AB. + static void Multiply3x3(const float A[3][3], const float B[3][3], + float C[3][3]); + static void Multiply3x3(const double A[3][3], const double B[3][3], + double C[3][3]); + + // Description: + // Transpose a 3x3 matrix. + static void Transpose3x3(const float A[3][3], float AT[3][3]); + static void Transpose3x3(const double A[3][3], double AT[3][3]); + + // Description: + // Invert a 3x3 matrix. + static void Invert3x3(const float A[3][3], float AI[3][3]); + static void Invert3x3(const double A[3][3], double AI[3][3]); + + // Description: + // Set A to the identity matrix. + static void Identity3x3(float A[3][3]); + static void Identity3x3(double A[3][3]); + + // Description: + // Return the determinant of a 3x3 matrix. + static double Determinant3x3(float A[3][3]); + static double Determinant3x3(double A[3][3]); + + // Description: + // Compute determinant of 3x3 matrix. Three columns of matrix are input. + static float Determinant3x3(const float c1[3], + const float c2[3], + const float c3[3]); + + // Description: + // Compute determinant of 3x3 matrix. Three columns of matrix are input. + static double Determinant3x3(const double c1[3], + const double c2[3], + const double c3[3]); + + // Description: + // Calculate the determinant of a 3x3 matrix in the form: + // | a1, b1, c1 | + // | a2, b2, c2 | + // | a3, b3, c3 | + static double Determinant3x3(double a1, double a2, double a3, + double b1, double b2, double b3, + double c1, double c2, double c3); + + // Description: + // Convert a quaternion to a 3x3 rotation matrix. The quaternion + // does not have to be normalized beforehand. + static void QuaternionToMatrix3x3(const float quat[4], float A[3][3]); + static void QuaternionToMatrix3x3(const double quat[4], double A[3][3]); + + // Description: + // Convert a 3x3 matrix into a quaternion. This will provide the + // best possible answer even if the matrix is not a pure rotation matrix. + // The method used is that of B.K.P. Horn. + static void Matrix3x3ToQuaternion(const float A[3][3], float quat[4]); + static void Matrix3x3ToQuaternion(const double A[3][3], double quat[4]); + + // Description: + // Orthogonalize a 3x3 matrix and put the result in B. If matrix A + // has a negative determinant, then B will be a rotation plus a flip + // i.e. it will have a determinant of -1. + static void Orthogonalize3x3(const float A[3][3], float B[3][3]); + static void Orthogonalize3x3(const double A[3][3], double B[3][3]); + + // Description: + // Diagonalize a symmetric 3x3 matrix and return the eigenvalues in + // w and the eigenvectors in the columns of V. The matrix V will + // have a positive determinant, and the three eigenvectors will be + // aligned as closely as possible with the x, y, and z axes. + static void Diagonalize3x3(const float A[3][3], float w[3], float V[3][3]); + static void Diagonalize3x3(const double A[3][3],double w[3],double V[3][3]); + + // Description: + // Perform singular value decomposition on a 3x3 matrix. This is not + // done using a conventional SVD algorithm, instead it is done using + // Orthogonalize3x3 and Diagonalize3x3. Both output matrices U and VT + // will have positive determinants, and the w values will be arranged + // such that the three rows of VT are aligned as closely as possible + // with the x, y, and z axes respectively. If the determinant of A is + // negative, then the three w values will be negative. + static void SingularValueDecomposition3x3(const float A[3][3], + float U[3][3], float w[3], + float VT[3][3]); + static void SingularValueDecomposition3x3(const double A[3][3], + double U[3][3], double w[3], + double VT[3][3]); + + // Description: + // Solve linear equations Ax = b using Crout's method. Input is square + // matrix A and load vector x. Solution x is written over load vector. The + // dimension of the matrix is specified in size. If error is found, method + // returns a 0. + static int SolveLinearSystem(double **A, double *x, int size); + + // Description: + // Invert input square matrix A into matrix AI. + // Note that A is modified during + // the inversion. The size variable is the dimension of the matrix. Returns 0 + // if inverse not computed. + static int InvertMatrix(double **A, double **AI, int size); + + // Description: + // Thread safe version of InvertMatrix method. + // Working memory arrays tmp1SIze and tmp2Size + // of length size must be passed in. + static int InvertMatrix(double **A, double **AI, int size, + int *tmp1Size, double *tmp2Size); + + // Description: + // Factor linear equations Ax = b using LU decomposition A = LU where L is + // lower triangular matrix and U is upper triangular matrix. Input is + // square matrix A, integer array of pivot indices index[0->n-1], and size + // of square matrix n. Output factorization LU is in matrix A. If error is + // found, method returns 0. + static int LUFactorLinearSystem(double **A, int *index, int size); + + // Description: + // Thread safe version of LUFactorLinearSystem method. + // Working memory array tmpSize of length size + // must be passed in. + static int LUFactorLinearSystem(double **A, int *index, int size, + double *tmpSize); + + // Description: + // Solve linear equations Ax = b using LU decomposition A = LU where L is + // lower triangular matrix and U is upper triangular matrix. Input is + // factored matrix A=LU, integer array of pivot indices index[0->n-1], + // load vector x[0->n-1], and size of square matrix n. Note that A=LU and + // index[] are generated from method LUFactorLinearSystem). Also, solution + // vector is written directly over input load vector. + static void LUSolveLinearSystem(double **A, int *index, + double *x, int size); + + // Description: + // Estimate the condition number of a LU factored matrix. Used to judge the + // accuracy of the solution. The matrix A must have been previously factored + // using the method LUFactorLinearSystem. The condition number is the ratio + // of the infinity matrix norm (i.e., maximum value of matrix component) + // divided by the minimum diagonal value. (This works for triangular matrices + // only: see Conte and de Boor, Elementary Numerical Analysis.) + static double EstimateMatrixCondition(double **A, int size); + + // Description: + // Initialize seed value. NOTE: Random() has the bad property that + // the first random number returned after RandomSeed() is called + // is proportional to the seed value! To help solve this, call + // RandomSeed() a few times inside seed. This doesn't ruin the + // repeatability of Random(). + static void RandomSeed(long s); + + // Description: + // Generate random numbers between 0.0 and 1.0. + // This is used to provide portability across different systems. + static double Random(); + + // Description: + // Generate random number between (min,max). + static double Random(double min, double max); + + // Description: + // Jacobi iteration for the solution of eigenvectors/eigenvalues of a 3x3 + // real symmetric matrix. Square 3x3 matrix a; output eigenvalues in w; + // and output eigenvectors in v. Resulting eigenvalues/vectors are sorted + // in decreasing order; eigenvectors are normalized. + static int Jacobi(float **a, float *w, float **v); + static int Jacobi(double **a, double *w, double **v); + + // Description: + // JacobiN iteration for the solution of eigenvectors/eigenvalues of a nxn + // real symmetric matrix. Square nxn matrix a; size of matrix in n; output + // eigenvalues in w; and output eigenvectors in v. Resulting + // eigenvalues/vectors are sorted in decreasing order; eigenvectors are + // normalized. w and v need to be allocated previously + static int JacobiN(float **a, int n, float *w, float **v); + static int JacobiN(double **a, int n, double *w, double **v); + + // Description: + // Solves a cubic equation c0*t^3 + c1*t^2 + c2*t + c3 = 0 when c0, c1, c2, + // and c3 are REAL. Solution is motivated by Numerical Recipes In C 2nd + // Ed. Return array contains number of (real) roots (counting multiple + // roots as one) followed by roots themselves. The value in roots[4] is a + // integer giving further information about the roots (see return codes for + // int SolveCubic()). + static double* SolveCubic(double c0, double c1, double c2, double c3); + + // Description: + // Solves a quadratic equation c1*t^2 + c2*t + c3 = 0 when c1, c2, and c3 + // are REAL. Solution is motivated by Numerical Recipes In C 2nd Ed. + // Return array contains number of (real) roots (counting multiple roots as + // one) followed by roots themselves. Note that roots[3] contains a return + // code further describing solution - see documentation for SolveCubic() + // for meaning of return codes. + static double* SolveQuadratic(double c0, double c1, double c2); + + // Description: + // Solves a linear equation c2*t + c3 = 0 when c2 and c3 are REAL. + // Solution is motivated by Numerical Recipes In C 2nd Ed. + // Return array contains number of roots followed by roots themselves. + static double* SolveLinear(double c0, double c1); + + // Description: + // Solves a cubic equation when c0, c1, c2, And c3 Are REAL. Solution + // is motivated by Numerical Recipes In C 2nd Ed. Roots and number of + // real roots are stored in user provided variables r1, r2, r3, and + // num_roots. Note that the function can return the following integer + // values describing the roots: (0)-no solution; (-1)-infinite number + // of solutions; (1)-one distinct real root of multiplicity 3 (stored + // in r1); (2)-two distinct real roots, one of multiplicity 2 (stored + // in r1 & r2); (3)-three distinct real roots; (-2)-quadratic equation + // with complex conjugate solution (real part of root returned in r1, + // imaginary in r2); (-3)-one real root and a complex conjugate pair + // (real root in r1 and real part of pair in r2 and imaginary in r3). + static int SolveCubic(double c0, double c1, double c2, double c3, + double *r1, double *r2, double *r3, int *num_roots); + + // Description: + // Solves A Quadratic Equation c1*t^2 + c2*t + c3 = 0 when + // c1, c2, and c3 are REAL. + // Solution is motivated by Numerical Recipes In C 2nd Ed. + // Roots and number of roots are stored in user provided variables + // r1, r2, num_roots + static int SolveQuadratic(double c0, double c1, double c2, + double *r1, double *r2, int *num_roots); + + // Description: + // Solves a linear equation c2*t + c3 = 0 when c2 and c3 are REAL. + // Solution is motivated by Numerical Recipes In C 2nd Ed. + // Root and number of (real) roots are stored in user provided variables + // r2 and num_roots. + static int SolveLinear(double c0, double c1, double *r1, int *num_roots); + + // Description: + // Solves for the least squares best fit matrix for the homogeneous equation X'M' = 0'. + // Uses the method described on pages 40-41 of Computer Vision by + // Forsyth and Ponce, which is that the solution is the eigenvector + // associated with the minimum eigenvalue of T(X)X, where T(X) is the + // transpose of X. + // The inputs and output are transposed matrices. + // Dimensions: X' is numberOfSamples by xOrder, + // M' dimension is xOrder by yOrder. + // M' should be pre-allocated. All matrices are row major. The resultant + // matrix M' should be pre-multiplied to X' to get 0', or transposed and + // then post multiplied to X to get 0 + static int SolveHomogeneousLeastSquares(int numberOfSamples, double **xt, int xOrder, + double **mt); + + + // Description: + // Solves for the least squares best fit matrix for the equation X'M' = Y'. + // Uses pseudoinverse to get the ordinary least squares. + // The inputs and output are transposed matrices. + // Dimensions: X' is numberOfSamples by xOrder, + // Y' is numberOfSamples by yOrder, + // M' dimension is xOrder by yOrder. + // M' should be pre-allocated. All matrices are row major. The resultant + // matrix M' should be pre-multiplied to X' to get Y', or transposed and + // then post multiplied to X to get Y + // By default, this method checks for the homogeneous condition where Y==0, and + // if so, invokes SolveHomogeneousLeastSquares. For better performance when + // the system is known not to be homogeneous, invoke with checkHomogeneous=0. + static int SolveLeastSquares(int numberOfSamples, double **xt, int xOrder, + double **yt, int yOrder, double **mt, int checkHomogeneous=1); + + // Description: + // Convert color in RGB format (Red, Green, Blue) to HSV format + // (Hue, Saturation, Value). The input color is not modified. + static void RGBToHSV(float rgb[3], float hsv[3]) + { RGBToHSV(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); } + static void RGBToHSV(float r, float g, float b, float *h, float *s, float *v); + static double* RGBToHSV(double rgb[3]); + static double* RGBToHSV(double r, double g, double b); + static void RGBToHSV(double rgb[3], double hsv[3]) + { RGBToHSV(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2); } + static void RGBToHSV(double r, double g, double b, double *h, double *s, double *v); + + // Description: + // Convert color in HSV format (Hue, Saturation, Value) to RGB + // format (Red, Green, Blue). The input color is not modified. + static void HSVToRGB(float hsv[3], float rgb[3]) + { HSVToRGB(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); } + static void HSVToRGB(float h, float s, float v, float *r, float *g, float *b); + static double* HSVToRGB(double hsv[3]); + static double* HSVToRGB(double h, double s, double v); + static void HSVToRGB(double hsv[3], double rgb[3]) + { HSVToRGB(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); } + static void HSVToRGB(double h, double s, double v, double *r, double *g, double *b); + + // Description: + // Convert color from Lab to XYZ system, and vice-versa + static void LabToXYZ(double lab[3], double xyz[3]); + static void XYZToRGB(double xyz[3], double rgb[3]); + + // Description: + // Set the bounds to an uninitialized state + static void UninitializeBounds(double bounds[6]){ + bounds[0] = 1.0; + bounds[1] = -1.0; + bounds[2] = 1.0; + bounds[3] = -1.0; + bounds[4] = 1.0; + bounds[5] = -1.0; + } + + // Description: + // Are the bounds initialized? + static int AreBoundsInitialized(double bounds[6]){ + if (bounds[1]-bounds[0]<0.0) + { + return 0; + } + return 1; + } + + // Description: + // Clamp some values against a range + // The method without 'clamped_values' will perform in-place clamping. + static void ClampValue(double *value, const double range[2]); + static void ClampValue(double value, const double range[2], double *clamped_value); + static void ClampValues( + double *values, int nb_values, const double range[2]); + static void ClampValues( + const double *values, int nb_values, const double range[2], double *clamped_values); + + // Description: + // Return the scalar type that is most likely to have enough precision + // to store a given range of data once it has been scaled and shifted + // (i.e. [range_min * scale + shift, range_max * scale + shift]. + // If any one of the parameters is not an integer number (decimal part != 0), + // the search will default to float types only (float or double) + // Return -1 on error or no scalar type found. + static int GetScalarTypeFittingRange( + double range_min, double range_max, + double scale = 1.0, double shift = 0.0); + + // Description: + // Get a vtkDataArray's scalar range for a given component. + // If the vtkDataArray's data type is unsigned char (VTK_UNSIGNED_CHAR) + // the range is adjusted to the whole data type range [0, 255.0]. + // Same goes for unsigned short (VTK_UNSIGNED_SHORT) but the upper bound + // is also adjusted down to 4095.0 if was between ]255, 4095.0]. + // Return 1 on success, 0 otherwise. + static int GetAdjustedScalarRange( + vtkDataArray *array, int comp, double range[2]); + + // Description: + // Return true if first 3D extent is within second 3D extent + // Extent is x-min, x-max, y-min, y-max, z-min, z-max + static int ExtentIsWithinOtherExtent(int extent1[6], int extent2[6]); + + // Description: + // Return true if first 3D bounds is within the second 3D bounds + // Bounds is x-min, x-max, y-min, y-max, z-min, z-max + // Delta is the error margin along each axis (usually a small number) + static int BoundsIsWithinOtherBounds(double bounds1[6], double bounds2[6], double delta[3]); + + // Description: + // Return true if point is within the given 3D bounds + // Bounds is x-min, x-max, y-min, y-max, z-min, z-max + // Delta is the error margin along each axis (usually a small number) + static int PointIsWithinBounds(double point[3], double bounds[6], double delta[3]); + + +protected: + vtkMath() {}; + ~vtkMath() {}; + + static long Seed; +private: + vtkMath(const vtkMath&); // Not implemented. + void operator=(const vtkMath&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkMath::Floor(double x) +{ +#if defined i386 || defined _M_IX86 + union { int i[2]; double d; } u; + // use 52-bit precision of IEEE double to round (x - 0.25) to + // the nearest multiple of 0.5, according to prevailing rounding + // mode which is IEEE round-to-nearest,even + u.d = (x - 0.25) + 3377699720527872.0; // (2**51)*1.5 + // extract mantissa, use shift to divide by 2 and hence get rid + // of the bit that gets messed up because the FPU uses + // round-to-nearest,even mode instead of round-to-nearest,+infinity + return u.i[0] >> 1; +#else + return (int)floor(x); +#endif +} + +//---------------------------------------------------------------------------- +inline float vtkMath::Normalize(float x[3]) +{ + float den; + if ( (den = vtkMath::Norm(x)) != 0.0 ) + { + for (int i=0; i < 3; i++) + { + x[i] /= den; + } + } + return den; +} + +//---------------------------------------------------------------------------- +inline double vtkMath::Normalize(double x[3]) +{ + double den; + if ( (den = vtkMath::Norm(x)) != 0.0 ) + { + for (int i=0; i < 3; i++) + { + x[i] /= den; + } + } + return den; +} + +//---------------------------------------------------------------------------- +inline float vtkMath::Normalize2D(float x[3]) +{ + float den; + if ( (den = vtkMath::Norm2D(x)) != 0.0 ) + { + for (int i=0; i < 2; i++) + { + x[i] /= den; + } + } + return den; +} + +//---------------------------------------------------------------------------- +inline double vtkMath::Normalize2D(double x[3]) +{ + double den; + if ( (den = vtkMath::Norm2D(x)) != 0.0 ) + { + for (int i=0; i < 2; i++) + { + x[i] /= den; + } + } + return den; +} + +//---------------------------------------------------------------------------- +inline float vtkMath::Determinant3x3(const float c1[3], + const float c2[3], + const float c3[3]) +{ + return c1[0]*c2[1]*c3[2] + c2[0]*c3[1]*c1[2] + c3[0]*c1[1]*c2[2] - + c1[0]*c3[1]*c2[2] - c2[0]*c1[1]*c3[2] - c3[0]*c2[1]*c1[2]; +} + +//---------------------------------------------------------------------------- +inline double vtkMath::Determinant3x3(const double c1[3], + const double c2[3], + const double c3[3]) +{ + return c1[0]*c2[1]*c3[2] + c2[0]*c3[1]*c1[2] + c3[0]*c1[1]*c2[2] - + c1[0]*c3[1]*c2[2] - c2[0]*c1[1]*c3[2] - c3[0]*c2[1]*c1[2]; +} + +//---------------------------------------------------------------------------- +inline double vtkMath::Determinant3x3(double a1, double a2, double a3, + double b1, double b2, double b3, + double c1, double c2, double c3) +{ + return ( a1 * vtkMath::Determinant2x2( b2, b3, c2, c3 ) + - b1 * vtkMath::Determinant2x2( a2, a3, c2, c3 ) + + c1 * vtkMath::Determinant2x2( a2, a3, b2, b3 ) ); +} + +//---------------------------------------------------------------------------- +inline float vtkMath::Distance2BetweenPoints(const float x[3], + const float y[3]) +{ + return ((x[0]-y[0])*(x[0]-y[0]) + (x[1]-y[1])*(x[1]-y[1]) + + (x[2]-y[2])*(x[2]-y[2])); +} + +//---------------------------------------------------------------------------- +inline double vtkMath::Distance2BetweenPoints(const double x[3], + const double y[3]) +{ + return ((x[0]-y[0])*(x[0]-y[0]) + (x[1]-y[1])*(x[1]-y[1]) + + (x[2]-y[2])*(x[2]-y[2])); +} + +//---------------------------------------------------------------------------- +inline double vtkMath::Random(double min, double max) +{ + return (min + vtkMath::Random()*(max-min)); +} + +//---------------------------------------------------------------------------- +// Cross product of two 3-vectors. Result vector in z[3]. +inline void vtkMath::Cross(const float x[3], const float y[3], float z[3]) +{ + float Zx = x[1]*y[2] - x[2]*y[1]; + float Zy = x[2]*y[0] - x[0]*y[2]; + float Zz = x[0]*y[1] - x[1]*y[0]; + z[0] = Zx; z[1] = Zy; z[2] = Zz; +} + +//---------------------------------------------------------------------------- +// Cross product of two 3-vectors. Result vector in z[3]. +inline void vtkMath::Cross(const double x[3], const double y[3], double z[3]) +{ + double Zx = x[1]*y[2] - x[2]*y[1]; + double Zy = x[2]*y[0] - x[0]*y[2]; + double Zz = x[0]*y[1] - x[1]*y[0]; + z[0] = Zx; z[1] = Zy; z[2] = Zz; +} + +//BTX +//---------------------------------------------------------------------------- +template +inline double vtkDeterminant3x3(T A[3][3]) +{ + return A[0][0]*A[1][1]*A[2][2] + A[1][0]*A[2][1]*A[0][2] + + A[2][0]*A[0][1]*A[1][2] - A[0][0]*A[2][1]*A[1][2] - + A[1][0]*A[0][1]*A[2][2] - A[2][0]*A[1][1]*A[0][2]; +} +//ETX + +//---------------------------------------------------------------------------- +inline double vtkMath::Determinant3x3(float A[3][3]) +{ + return vtkDeterminant3x3(A); +} + +//---------------------------------------------------------------------------- +inline double vtkMath::Determinant3x3(double A[3][3]) +{ + return vtkDeterminant3x3(A); +} + +//---------------------------------------------------------------------------- +inline void vtkMath::ClampValue(double *value, const double range[2]) +{ + if (value && range) + { + if (*value < range[0]) + { + *value = range[0]; + } + else if (*value > range[1]) + { + *value = range[1]; + } + } +} + +//---------------------------------------------------------------------------- +inline void vtkMath::ClampValue( + double value, const double range[2], double *clamped_value) +{ + if (range && clamped_value) + { + if (value < range[0]) + { + *clamped_value = range[0]; + } + else if (value > range[1]) + { + *clamped_value = range[1]; + } + else + { + *clamped_value = value; + } + } +} + +#endif diff --git a/Common/vtkMatrix4x4.cxx b/Common/vtkMatrix4x4.cxx new file mode 100644 index 0000000..1fb6c85 --- /dev/null +++ b/Common/vtkMatrix4x4.cxx @@ -0,0 +1,332 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMatrix4x4.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMatrix4x4.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +#include +#include + +vtkCxxRevisionMacro(vtkMatrix4x4, "$Revision: 1.62 $"); +vtkStandardNewMacro(vtkMatrix4x4); + +// Useful for viewing a double[16] as a double[4][4] +typedef double (*SqMatPtr)[4]; + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::Zero(double Elements[16]) +{ + SqMatPtr elem = (SqMatPtr)Elements; + int i,j; + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + elem[i][j] = 0.0; + } + } +} + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::Identity(double Elements[16]) +{ + Elements[0] = Elements[5] = Elements[10] = Elements[15] = 1.0; + Elements[1] = Elements[2] = Elements[3] = Elements[4] = + Elements[6] = Elements[7] = Elements[8] = Elements[9] = + Elements[11] = Elements[12] = Elements[13] = Elements[14] = 0.0; +} + +//---------------------------------------------------------------------------- +template +void vtkMatrixMultiplyPoint(T1 elem[16], T2 in[4], T3 out[4]) +{ + T3 v1 = in[0]; + T3 v2 = in[1]; + T3 v3 = in[2]; + T3 v4 = in[3]; + + out[0] = v1*elem[0] + v2*elem[1] + v3*elem[2] + v4*elem[3]; + out[1] = v1*elem[4] + v2*elem[5] + v3*elem[6] + v4*elem[7]; + out[2] = v1*elem[8] + v2*elem[9] + v3*elem[10] + v4*elem[11]; + out[3] = v1*elem[12] + v2*elem[13] + v3*elem[14] + v4*elem[15]; +} + +//---------------------------------------------------------------------------- +// Multiply this matrix by a point (in homogeneous coordinates). +// and return the result in result. The in[4] and result[4] +// arrays must both be allocated but they can be the same array. +void vtkMatrix4x4::MultiplyPoint(const double Elements[16], + const float in[4], float result[4]) +{ + vtkMatrixMultiplyPoint(Elements,in,result); +} + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::MultiplyPoint(const double Elements[16], + const double in[4], double result[4]) +{ + vtkMatrixMultiplyPoint(Elements,in,result); +} + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::PointMultiply(const double Elements[16], + const float in[4], float result[4]) +{ + double newElements[16]; + vtkMatrix4x4::Transpose(Elements,newElements); + vtkMatrix4x4::MultiplyPoint(newElements,in,result); +} + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::PointMultiply(const double Elements[16], + const double in[4], double result[4]) +{ + double newElements[16]; + vtkMatrix4x4::Transpose(Elements,newElements); + vtkMatrix4x4::MultiplyPoint(newElements,in,result); +} + +//---------------------------------------------------------------------------- +// Multiplies matrices a and b and stores the result in c. +void vtkMatrix4x4::Multiply4x4(const double a[16], const double b[16], + double c[16]) +{ + SqMatPtr aMat = (SqMatPtr) a; + SqMatPtr bMat = (SqMatPtr) b; + SqMatPtr cMat = (SqMatPtr) c; + int i, k; + double Accum[4][4]; + + for (i = 0; i < 4; i++) + { + for (k = 0; k < 4; k++) + { + Accum[i][k] = aMat[i][0] * bMat[0][k] + + aMat[i][1] * bMat[1][k] + + aMat[i][2] * bMat[2][k] + + aMat[i][3] * bMat[3][k]; + } + } + + // Copy to final dest + for (i = 0; i < 4; i++) + { + cMat[i][0] = Accum[i][0]; + cMat[i][1] = Accum[i][1]; + cMat[i][2] = Accum[i][2]; + cMat[i][3] = Accum[i][3]; + } + +} + +//---------------------------------------------------------------------------- +// Matrix Inversion (adapted from Richard Carling in "Graphics Gems," +// Academic Press, 1990). +void vtkMatrix4x4::Invert(const double inElements[16], + double outElements[16]) +{ + SqMatPtr outElem = (SqMatPtr)outElements; + + // inverse( original_matrix, inverse_matrix ) + // calculate the inverse of a 4x4 matrix + // + // -1 + // A = ___1__ adjoint A + // det A + // + + int i, j; + double det; + + // calculate the 4x4 determinent + // if the determinent is zero, + // then the inverse matrix is not unique. + + det = vtkMatrix4x4::Determinant(inElements); + if ( det == 0.0 ) + { + return; + } + + // calculate the adjoint matrix + vtkMatrix4x4::Adjoint(inElements, outElements ); + + // scale the adjoint matrix to get the inverse + for (i=0; i<4; i++) + { + for(j=0; j<4; j++) + { + outElem[i][j] = outElem[i][j] / det; + } + } +} + +//---------------------------------------------------------------------------- +double vtkMatrix4x4::Determinant(const double Elements[16]) +{ + SqMatPtr elem = (SqMatPtr)Elements; + + double a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4; + + // assign to individual variable names to aid selecting + // correct elements + + a1 = elem[0][0]; b1 = elem[0][1]; + c1 = elem[0][2]; d1 = elem[0][3]; + + a2 = elem[1][0]; b2 = elem[1][1]; + c2 = elem[1][2]; d2 = elem[1][3]; + + a3 = elem[2][0]; b3 = elem[2][1]; + c3 = elem[2][2]; d3 = elem[2][3]; + + a4 = elem[3][0]; b4 = elem[3][1]; + c4 = elem[3][2]; d4 = elem[3][3]; + + return a1 * vtkMath::Determinant3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4) + - b1 * vtkMath::Determinant3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4) + + c1 * vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4) + - d1 * vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4); +} + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::Adjoint(const double inElements[16], double outElements[16]) +{ + SqMatPtr inElem = (SqMatPtr) inElements; + SqMatPtr outElem = (SqMatPtr) outElements; + + // + // adjoint( original_matrix, inverse_matrix ) + // + // calculate the adjoint of a 4x4 matrix + // + // Let a denote the minor determinant of matrix A obtained by + // ij + // + // deleting the ith row and jth column from A. + // + // i+j + // Let b = (-1) a + // ij ji + // + // The matrix B = (b ) is the adjoint of A + // ij + // + double a1, a2, a3, a4, b1, b2, b3, b4; + double c1, c2, c3, c4, d1, d2, d3, d4; + + // assign to individual variable names to aid + // selecting correct values + + a1 = inElem[0][0]; b1 = inElem[0][1]; + c1 = inElem[0][2]; d1 = inElem[0][3]; + + a2 = inElem[1][0]; b2 = inElem[1][1]; + c2 = inElem[1][2]; d2 = inElem[1][3]; + + a3 = inElem[2][0]; b3 = inElem[2][1]; + c3 = inElem[2][2]; d3 = inElem[2][3]; + + a4 = inElem[3][0]; b4 = inElem[3][1]; + c4 = inElem[3][2]; d4 = inElem[3][3]; + + + // row column labeling reversed since we transpose rows & columns + + outElem[0][0] = + vtkMath::Determinant3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4); + outElem[1][0] = + - vtkMath::Determinant3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4); + outElem[2][0] = + vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4); + outElem[3][0] = + - vtkMath::Determinant3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4); + + outElem[0][1] = + - vtkMath::Determinant3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4); + outElem[1][1] = + vtkMath::Determinant3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4); + outElem[2][1] = + - vtkMath::Determinant3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4); + outElem[3][1] = + vtkMath::Determinant3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4); + + outElem[0][2] = + vtkMath::Determinant3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4); + outElem[1][2] = + - vtkMath::Determinant3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4); + outElem[2][2] = + vtkMath::Determinant3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4); + outElem[3][2] = + - vtkMath::Determinant3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4); + + outElem[0][3] = + - vtkMath::Determinant3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3); + outElem[1][3] = + vtkMath::Determinant3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3); + outElem[2][3] = + - vtkMath::Determinant3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3); + outElem[3][3] = + vtkMath::Determinant3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3); +} + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::DeepCopy(double Elements[16], const double newElements[16]) +{ + for (int i = 0; i < 16; i++) + { + Elements[i] = newElements[i]; + } +} + +//---------------------------------------------------------------------------- +// Transpose the matrix and put it into out. +void vtkMatrix4x4::Transpose(const double inElements[16], + double outElements[16]) +{ + SqMatPtr inElem = (SqMatPtr)inElements; + SqMatPtr outElem = (SqMatPtr)outElements; + int i, j; + double temp; + + for (i=0; i<4; i++) + { + for(j=i; j<4; j++) + { + temp = inElem[i][j]; + outElem[i][j] = inElem[j][i]; + outElem[j][i] = temp; + } + } +} + +//---------------------------------------------------------------------------- +void vtkMatrix4x4::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + int i, j; + + os << indent << "Elements:\n"; + for (i = 0; i < 4; i++) + { + os << indent << indent; + for (j = 0; j < 4; j++) + { + os << this->Element[i][j] << " "; + } + os << "\n"; + } +} diff --git a/Common/vtkMatrix4x4.h b/Common/vtkMatrix4x4.h new file mode 100644 index 0000000..0246575 --- /dev/null +++ b/Common/vtkMatrix4x4.h @@ -0,0 +1,204 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMatrix4x4.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMatrix4x4 - represent and manipulate 4x4 transformation matrices +// .SECTION Description +// vtkMatrix4x4 is a class to represent and manipulate 4x4 matrices. +// Specifically, it is designed to work on 4x4 transformation matrices +// found in 3D rendering using homogeneous coordinates [x y z w]. + +// .SECTION See Also +// vtkTransform + +#ifndef __vtkMatrix4x4_h +#define __vtkMatrix4x4_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkMatrix4x4 : public vtkObject +{ + // Some of the methods in here have a corresponding static (class) + // method taking a pointer to 16 doubles that constitutes a user + // supplied matrix. This allows C++ clients to allocate double arrays + // on the stack and manipulate them using vtkMatrix4x4 methods. + // This is an alternative to allowing vtkMatrix4x4 instances to be + // created on the stack (which is frowned upon) or doing lots of + // temporary heap allocation within vtkTransform and vtkActor methods, + // which is inefficient. + +public: + double Element[4][4]; + + // Description: + // Construct a 4x4 identity matrix. + static vtkMatrix4x4 *New(); + + vtkTypeRevisionMacro(vtkMatrix4x4,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the elements of the matrix to the same values as the elements + // of the source Matrix. + void DeepCopy(vtkMatrix4x4 *source) + {vtkMatrix4x4::DeepCopy(*this->Element,source); this->Modified(); } +//BTX + static void DeepCopy(double Elements[16], vtkMatrix4x4 *source) + {vtkMatrix4x4::DeepCopy(Elements,*source->Element); } + static void DeepCopy(double Elements[16], const double newElements[16]); +//ETX + + // Description: + // Non-static member function. Assigns *from* elements array + void DeepCopy(const double Elements[16]) + { this->DeepCopy(*this->Element,Elements); this->Modified(); } + + // Description: + // Set all of the elements to zero. + void Zero() + { vtkMatrix4x4::Zero(*this->Element); this->Modified(); } +//BTX + static void Zero(double Elements[16]); +//ETX + + // Description: + // Set equal to Identity matrix + void Identity() + { vtkMatrix4x4::Identity(*this->Element); this->Modified();} +//BTX + static void Identity(double Elements[16]); +//ETX + + // Description: + // Matrix Inversion (adapted from Richard Carling in "Graphics Gems," + // Academic Press, 1990). + static void Invert(vtkMatrix4x4 *in, vtkMatrix4x4 *out) + {vtkMatrix4x4::Invert(*in->Element,*out->Element); out->Modified(); } + void Invert() + { vtkMatrix4x4::Invert(this,this); } +//BTX + static void Invert(const double inElements[16], double outElements[16]); +//ETX + + + // Description: + // Transpose the matrix and put it into out. + static void Transpose(vtkMatrix4x4 *in, vtkMatrix4x4 *out) + {vtkMatrix4x4::Transpose(*in->Element,*out->Element); out->Modified(); } + void Transpose() + { vtkMatrix4x4::Transpose(this,this); } +//BTX + static void Transpose(const double inElements[16], double outElements[16]); +//ETX + + // Description: + // Multiply a homogeneous coordinate by this matrix, i.e. out = A*in. + // The in[4] and out[4] can be the same array. + void MultiplyPoint(const float in[4], float out[4]) + {vtkMatrix4x4::MultiplyPoint(*this->Element,in,out); } + void MultiplyPoint(const double in[4], double out[4]) + {vtkMatrix4x4::MultiplyPoint(*this->Element,in,out); } + +//BTX + static void MultiplyPoint(const double Elements[16], + const float in[4], float out[4]); + static void MultiplyPoint(const double Elements[16], + const double in[4], double out[4]); +//ETX + + // Description: + // For use in Java, Python or Tcl. The default MultiplyPoint() uses + // a single-precision point. + float *MultiplyPoint(const float in[4]) + {return this->MultiplyFloatPoint(in); } + float *MultiplyFloatPoint(const float in[4]) + {this->MultiplyPoint(in,this->FloatPoint); return this->FloatPoint; } + double *MultiplyDoublePoint(const double in[4]) + {this->MultiplyPoint(in,this->DoublePoint); return this->DoublePoint; } + + // Description: + // Multiplies matrices a and b and stores the result in c. + static void Multiply4x4(vtkMatrix4x4 *a, vtkMatrix4x4 *b, vtkMatrix4x4 *c) { + vtkMatrix4x4::Multiply4x4(*a->Element,*b->Element,*c->Element); }; +//BTX + static void Multiply4x4(const double a[16], const double b[16], + double c[16]); +//ETX + + // Description: + // Compute adjoint of the matrix and put it into out. + void Adjoint(vtkMatrix4x4 *in, vtkMatrix4x4 *out) + {vtkMatrix4x4::Adjoint(*in->Element,*out->Element);} +//BTX + static void Adjoint(const double inElements[16], double outElements[16]); +//ETX + + // Description: + // Compute the determinant of the matrix and return it. + double Determinant() {return vtkMatrix4x4::Determinant(*this->Element);} +//BTX + static double Determinant(const double Elements[16]); +//ETX + + // Description: + // Sets the element i,j in the matrix. + void SetElement(int i, int j, double value); + + // Description: + // Returns the element i,j from the matrix. + double GetElement(int i, int j) const + {return this->Element[i][j];} + +//BTX + double *operator[](const unsigned int i) + {return &(this->Element[i][0]);} + const double *operator[](unsigned int i) const + { return &(this->Element[i][0]); } + void Adjoint(vtkMatrix4x4 &in,vtkMatrix4x4 &out) + {this->Adjoint(&in,&out);} + double Determinant(vtkMatrix4x4 &in) + {return this->Determinant(&in);} + double Determinant(vtkMatrix4x4 *in) + {return vtkMatrix4x4::Determinant(*in->Element);} + void Invert(vtkMatrix4x4 &in,vtkMatrix4x4 &out) + {this->Invert(&in,&out);} + void Transpose(vtkMatrix4x4 &in,vtkMatrix4x4 &out) + {this->Transpose(&in,&out);} + static void PointMultiply(const double Elements[16], + const float in[4], float out[4]); + static void PointMultiply(const double Elements[16], + const double in[4], double out[4]); +//ETX + +protected: + vtkMatrix4x4() { vtkMatrix4x4::Identity(*this->Element); }; + ~vtkMatrix4x4() {}; + + float FloatPoint[4]; + double DoublePoint[4]; +private: + vtkMatrix4x4(const vtkMatrix4x4&); // Not implemented + void operator= (const vtkMatrix4x4&); // Not implemented +}; + +inline void vtkMatrix4x4::SetElement(int i, int j, double value) +{ + if (this->Element[i][j] != value) + { + this->Element[i][j] = value; + this->Modified(); + } +} + +#endif + diff --git a/Common/vtkMatrixToHomogeneousTransform.cxx b/Common/vtkMatrixToHomogeneousTransform.cxx new file mode 100644 index 0000000..9813ad9 --- /dev/null +++ b/Common/vtkMatrixToHomogeneousTransform.cxx @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMatrixToHomogeneousTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMatrixToHomogeneousTransform.h" + +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkMatrixToHomogeneousTransform, "$Revision: 1.9.4.1 $"); +vtkStandardNewMacro(vtkMatrixToHomogeneousTransform); +vtkCxxSetObjectMacro(vtkMatrixToHomogeneousTransform,Input,vtkMatrix4x4); + +//---------------------------------------------------------------------------- +vtkMatrixToHomogeneousTransform::vtkMatrixToHomogeneousTransform() +{ + this->Input = NULL; + this->InverseFlag = 0; +} + +//---------------------------------------------------------------------------- +vtkMatrixToHomogeneousTransform::~vtkMatrixToHomogeneousTransform() +{ + this->SetInput(NULL); +} + +//---------------------------------------------------------------------------- +void vtkMatrixToHomogeneousTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Update(); + + this->Superclass::PrintSelf(os, indent); + os << indent << "Input: " << this->Input << "\n"; + os << indent << "InverseFlag: " << this->InverseFlag << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkMatrixToHomogeneousTransform::Inverse() +{ + this->InverseFlag = !this->InverseFlag; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkMatrixToHomogeneousTransform::InternalUpdate() +{ + if (this->Input) + { + this->Matrix->DeepCopy(this->Input); + if (this->InverseFlag) + { + this->Matrix->Invert(); + } + } + else + { + this->Matrix->Identity(); + } +} + +//---------------------------------------------------------------------------- +void vtkMatrixToHomogeneousTransform::InternalDeepCopy( + vtkAbstractTransform *gtrans) +{ + vtkMatrixToHomogeneousTransform *transform = + (vtkMatrixToHomogeneousTransform *)gtrans; + + this->SetInput(transform->Input); + + if (this->InverseFlag != transform->InverseFlag) + { + this->Inverse(); + } +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkMatrixToHomogeneousTransform::MakeTransform() +{ + return vtkMatrixToHomogeneousTransform::New(); +} + +//---------------------------------------------------------------------------- +// Get the MTime +unsigned long vtkMatrixToHomogeneousTransform::GetMTime() +{ + unsigned long mtime = this->vtkHomogeneousTransform::GetMTime(); + + if (this->Input) + { + unsigned long matrixMTime = this->Input->GetMTime(); + if (matrixMTime > mtime) + { + return matrixMTime; + } + } + return mtime; +} + +#ifndef VTK_LEGACY_REMOVE +void vtkMatrixToHomogeneousTransform::SetMatrix(vtkMatrix4x4 *matrix) +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::SetMatrix, "VTK 5.0", + vtkAssemblyNode::SetInput); + this->SetInput(matrix); +} +#endif diff --git a/Common/vtkMatrixToHomogeneousTransform.h b/Common/vtkMatrixToHomogeneousTransform.h new file mode 100644 index 0000000..5f23719 --- /dev/null +++ b/Common/vtkMatrixToHomogeneousTransform.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMatrixToHomogeneousTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkMatrixToHomogeneousTransform - convert a matrix to a transform +// .SECTION Description +// This is a very simple class which allows a vtkMatrix4x4 to be used in +// place of a vtkHomogeneousTransform or vtkAbstractTransform. For example, +// if you use it as a proxy between a matrix and vtkTransformPolyDataFilter +// then any modifications to the matrix will automatically be reflected in +// the output of the filter. +// .SECTION See Also +// vtkPerspectiveTransform vtkMatrix4x4 vtkMatrixToLinearTransform + +#ifndef __vtkMatrixToHomogeneousTransform_h +#define __vtkMatrixToHomogeneousTransform_h + +#include "vtkHomogeneousTransform.h" + +class vtkMatrix4x4; + +class VTK_COMMON_EXPORT vtkMatrixToHomogeneousTransform : public vtkHomogeneousTransform +{ + public: + static vtkMatrixToHomogeneousTransform *New(); + vtkTypeRevisionMacro(vtkMatrixToHomogeneousTransform,vtkHomogeneousTransform); + void PrintSelf (ostream& os, vtkIndent indent); + + // Set the input matrix. Any modifications to the matrix will be + // reflected in the transformation. + virtual void SetInput(vtkMatrix4x4*); + vtkGetObjectMacro(Input,vtkMatrix4x4); + + // Description: + // The input matrix is left as-is, but the transformation matrix + // is inverted. + void Inverse(); + + // Description: + // Get the MTime: this is the bit of magic that makes everything work. + unsigned long GetMTime(); + + // Description: + // Make a new transform of the same type. + vtkAbstractTransform *MakeTransform(); + + // Description: + // @deprecated This method is deprecated. + VTK_LEGACY(void SetMatrix(vtkMatrix4x4 *matrix)); + +protected: + vtkMatrixToHomogeneousTransform(); + ~vtkMatrixToHomogeneousTransform(); + + void InternalUpdate(); + void InternalDeepCopy(vtkAbstractTransform *transform); + + int InverseFlag; + vtkMatrix4x4 *Input; +private: + vtkMatrixToHomogeneousTransform(const vtkMatrixToHomogeneousTransform&); // Not implemented. + void operator=(const vtkMatrixToHomogeneousTransform&); // Not implemented. +}; + +#endif diff --git a/Common/vtkMatrixToLinearTransform.cxx b/Common/vtkMatrixToLinearTransform.cxx new file mode 100644 index 0000000..06f3aeb --- /dev/null +++ b/Common/vtkMatrixToLinearTransform.cxx @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMatrixToLinearTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMatrixToLinearTransform.h" + +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkMatrixToLinearTransform, "$Revision: 1.14.4.1 $"); +vtkStandardNewMacro(vtkMatrixToLinearTransform); +vtkCxxSetObjectMacro(vtkMatrixToLinearTransform,Input,vtkMatrix4x4); + +//---------------------------------------------------------------------------- +vtkMatrixToLinearTransform::vtkMatrixToLinearTransform() +{ + this->Input = NULL; + this->InverseFlag = 0; +} + +//---------------------------------------------------------------------------- +vtkMatrixToLinearTransform::~vtkMatrixToLinearTransform() +{ + this->SetInput(NULL); +} + +//---------------------------------------------------------------------------- +void vtkMatrixToLinearTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Update(); + + this->Superclass::PrintSelf(os, indent); + os << indent << "Input: " << this->Input << "\n"; + os << indent << "InverseFlag: " << this->InverseFlag << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkMatrixToLinearTransform::Inverse() +{ + this->InverseFlag = !this->InverseFlag; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkMatrixToLinearTransform::InternalUpdate() +{ + if (this->Input) + { + this->Matrix->DeepCopy(this->Input); + if (this->InverseFlag) + { + this->Matrix->Invert(); + } + } + else + { + this->Matrix->Identity(); + } +} + +//---------------------------------------------------------------------------- +void vtkMatrixToLinearTransform::InternalDeepCopy(vtkAbstractTransform *gtrans) +{ + vtkMatrixToLinearTransform *transform = + (vtkMatrixToLinearTransform *)gtrans; + + this->SetInput(transform->Input); + + if (this->InverseFlag != transform->InverseFlag) + { + this->Inverse(); + } +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkMatrixToLinearTransform::MakeTransform() +{ + return vtkMatrixToLinearTransform::New(); +} + +//---------------------------------------------------------------------------- +// Get the MTime +unsigned long vtkMatrixToLinearTransform::GetMTime() +{ + unsigned long mtime = this->vtkLinearTransform::GetMTime(); + + if (this->Input) + { + unsigned long matrixMTime = this->Input->GetMTime(); + if (matrixMTime > mtime) + { + return matrixMTime; + } + } + return mtime; +} + +#ifndef VTK_LEGACY_REMOVE +void vtkMatrixToLinearTransform::SetMatrix(vtkMatrix4x4 *matrix) +{ + VTK_LEGACY_REPLACED_BODY(vtkAssemblyNode::SetMatrix, "VTK 5.0", + vtkAssemblyNode::SetInput); + this->SetInput(matrix); +} +#endif diff --git a/Common/vtkMatrixToLinearTransform.h b/Common/vtkMatrixToLinearTransform.h new file mode 100644 index 0000000..4e1a258 --- /dev/null +++ b/Common/vtkMatrixToLinearTransform.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMatrixToLinearTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkMatrixToLinearTransform - convert a matrix to a transform +// .SECTION Description +// This is a very simple class which allows a vtkMatrix4x4 to be used in +// place of a vtkLinearTransform or vtkAbstractTransform. For example, +// if you use it as a proxy between a matrix and vtkTransformPolyDataFilter +// then any modifications to the matrix will automatically be reflected in +// the output of the filter. +// .SECTION See Also +// vtkTransform vtkMatrix4x4 vtkMatrixToHomogeneousTransform + +#ifndef __vtkMatrixToLinearTransform_h +#define __vtkMatrixToLinearTransform_h + +#include "vtkLinearTransform.h" + +class vtkMatrix4x4; + +class VTK_COMMON_EXPORT vtkMatrixToLinearTransform : public vtkLinearTransform +{ + public: + static vtkMatrixToLinearTransform *New(); + vtkTypeRevisionMacro(vtkMatrixToLinearTransform,vtkLinearTransform); + void PrintSelf (ostream& os, vtkIndent indent); + + // Description: + // Set the input matrix. Any modifications to the matrix will be + // reflected in the transformation. + virtual void SetInput(vtkMatrix4x4*); + vtkGetObjectMacro(Input,vtkMatrix4x4); + + // Description: + // The input matrix is left as-is, but the transformation matrix + // is inverted. + void Inverse(); + + // Description: + // Get the MTime: this is the bit of magic that makes everything work. + unsigned long GetMTime(); + + // Description: + // Make a new transform of the same type. + vtkAbstractTransform *MakeTransform(); + + // Description: + // @deprecated This method is deprecated. + VTK_LEGACY(void SetMatrix(vtkMatrix4x4 *matrix)); + +protected: + vtkMatrixToLinearTransform(); + ~vtkMatrixToLinearTransform(); + + void InternalUpdate(); + void InternalDeepCopy(vtkAbstractTransform *transform); + + int InverseFlag; + vtkMatrix4x4 *Input; +private: + vtkMatrixToLinearTransform(const vtkMatrixToLinearTransform&); // Not implemented. + void operator=(const vtkMatrixToLinearTransform&); // Not implemented. +}; + +#endif diff --git a/Common/vtkMultiPartExtentTranslator.cxx b/Common/vtkMultiPartExtentTranslator.cxx new file mode 100644 index 0000000..a8106da --- /dev/null +++ b/Common/vtkMultiPartExtentTranslator.cxx @@ -0,0 +1,41 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiPartExtentTranslator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMultiPartExtentTranslator.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkMultiPartExtentTranslator, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkMultiPartExtentTranslator); + +//---------------------------------------------------------------------------- +vtkMultiPartExtentTranslator::vtkMultiPartExtentTranslator() +{ +} + +//---------------------------------------------------------------------------- +vtkMultiPartExtentTranslator::~vtkMultiPartExtentTranslator() +{ +} + +//---------------------------------------------------------------------------- +int vtkMultiPartExtentTranslator::PieceToExtentThreadSafe(int , int , int , + int *wholeExtent, + int *resultExtent, + int , int ) +{ + memcpy(resultExtent, wholeExtent, sizeof(int)*6); + return 1; +} + + diff --git a/Common/vtkMultiPartExtentTranslator.h b/Common/vtkMultiPartExtentTranslator.h new file mode 100644 index 0000000..4403288 --- /dev/null +++ b/Common/vtkMultiPartExtentTranslator.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiPartExtentTranslator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMultiPartExtentTranslator - Returns the whole extent for any piece. +// .SECTION Description +// This is used when a parallel data set is composed of multple structured +// pieces. + +#ifndef __vtkMultiPartExtentTranslator_h +#define __vtkMultiPartExtentTranslator_h + +#include "vtkExtentTranslator.h" + + +class VTK_COMMON_EXPORT vtkMultiPartExtentTranslator : public vtkExtentTranslator +{ +public: + static vtkMultiPartExtentTranslator *New(); + + vtkTypeRevisionMacro(vtkMultiPartExtentTranslator,vtkExtentTranslator); + + // Description: + // These are the main methods that should be called. These methods + // are responsible for converting a piece to an extent. The signatures + // without arguments are only thread safe when each thread accesses a + // different instance. The signatures with arguements are fully thread + // safe. + virtual int PieceToExtentThreadSafe(int piece, int numPieces, + int ghostLevel, int *wholeExtent, + int *resultExtent, int splitMode, + int byPoints); + +protected: + vtkMultiPartExtentTranslator(); + ~vtkMultiPartExtentTranslator(); + +private: + vtkMultiPartExtentTranslator(const vtkMultiPartExtentTranslator&); // Not implemented. + void operator=(const vtkMultiPartExtentTranslator&); // Not implemented. +}; + +#endif + diff --git a/Common/vtkMultiThreader.cxx b/Common/vtkMultiThreader.cxx new file mode 100644 index 0000000..58ad067 --- /dev/null +++ b/Common/vtkMultiThreader.cxx @@ -0,0 +1,779 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiThreader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMultiThreader.h" + +#include "vtkMutexLock.h" +#include "vtkObjectFactory.h" +#include "vtkWindows.h" + +vtkCxxRevisionMacro(vtkMultiThreader, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkMultiThreader); + +// These are the includes necessary for multithreaded rendering on an SGI +// using the sproc() call +#ifdef VTK_USE_SPROC +#include +#include +#include +#include +#endif + +// Need to define "vtkExternCThreadFunctionType" to avoid warning on some +// platforms about passing function pointer to an argument expecting an +// extern "C" function. Placing the typedef of the function pointer type +// inside an extern "C" block solves this problem. +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) +#include +extern "C" { typedef void *(*vtkExternCThreadFunctionType)(void *); } +#else +typedef vtkThreadFunctionType vtkExternCThreadFunctionType; +#endif + +#ifdef __APPLE__ +#include +#endif + +// Initialize static member that controls global maximum number of threads +static int vtkMultiThreaderGlobalMaximumNumberOfThreads = 0; + +void vtkMultiThreader::SetGlobalMaximumNumberOfThreads(int val) +{ + if (val == vtkMultiThreaderGlobalMaximumNumberOfThreads) + { + return; + } + vtkMultiThreaderGlobalMaximumNumberOfThreads = val; +} + +int vtkMultiThreader::GetGlobalMaximumNumberOfThreads() +{ + return vtkMultiThreaderGlobalMaximumNumberOfThreads; +} + +// 0 => Not initialized. +static int vtkMultiThreaderGlobalDefaultNumberOfThreads = 0; + +void vtkMultiThreader::SetGlobalDefaultNumberOfThreads(int val) +{ + if (val == vtkMultiThreaderGlobalDefaultNumberOfThreads) + { + return; + } + vtkMultiThreaderGlobalDefaultNumberOfThreads = val; +} + +int vtkMultiThreader::GetGlobalDefaultNumberOfThreads() +{ + if (vtkMultiThreaderGlobalDefaultNumberOfThreads == 0) + { + int num = 1; // default is 1 +#ifdef VTK_USE_SPROC + // Default the number of threads to be the number of available + // processors if we are using sproc() + num = prctl( PR_MAXPPROCS ); +#endif + +#ifdef VTK_USE_PTHREADS + // Default the number of threads to be the number of available + // processors if we are using pthreads() +#ifdef _SC_NPROCESSORS_ONLN + num = sysconf( _SC_NPROCESSORS_ONLN ); +#elif defined(_SC_NPROC_ONLN) + num = sysconf( _SC_NPROC_ONLN ); +#endif +#if defined(__SVR4) && defined(sun) && defined(PTHREAD_MUTEX_NORMAL) + pthread_setconcurrency(num); +#endif +#endif + +#ifdef __APPLE__ + // MPProcessors returns the physical number of processors present + // MPProcessorsScheduled returns number of active processors + num = MPProcessors(); +#endif + +#ifdef _WIN32 + { + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + num = sysInfo.dwNumberOfProcessors; + } +#endif + +#ifndef VTK_USE_WIN32_THREADS +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS + // If we are not multithreading, the number of threads should + // always be 1 + num = 1; +#endif +#endif +#endif + + // Lets limit the number of threads to VTK_MAX_THREADS + if (num > VTK_MAX_THREADS) + { + num = VTK_MAX_THREADS; + } + + vtkMultiThreaderGlobalDefaultNumberOfThreads = num; + } + + + return vtkMultiThreaderGlobalDefaultNumberOfThreads; +} + +// Constructor. Default all the methods to NULL. Since the +// ThreadInfoArray is static, the ThreadIDs can be initialized here +// and will not change. +vtkMultiThreader::vtkMultiThreader() +{ + int i; + + for ( i = 0; i < VTK_MAX_THREADS; i++ ) + { + this->ThreadInfoArray[i].ThreadID = i; + this->ThreadInfoArray[i].ActiveFlag = NULL; + this->ThreadInfoArray[i].ActiveFlagLock = NULL; + this->MultipleMethod[i] = NULL; + this->SpawnedThreadActiveFlag[i] = 0; + this->SpawnedThreadActiveFlagLock[i] = NULL; + this->SpawnedThreadInfoArray[i].ThreadID = i; + } + + this->SingleMethod = NULL; + this->NumberOfThreads = + vtkMultiThreader::GetGlobalDefaultNumberOfThreads(); + +} + +// Destructor. Nothing allocated so nothing needs to be done here. +vtkMultiThreader::~vtkMultiThreader() +{ +} + +//---------------------------------------------------------------------------- +int vtkMultiThreader::GetNumberOfThreads() +{ + int num = this->NumberOfThreads; + if(vtkMultiThreaderGlobalMaximumNumberOfThreads > 0 && + num > vtkMultiThreaderGlobalMaximumNumberOfThreads) + { + num = vtkMultiThreaderGlobalMaximumNumberOfThreads; + } + return num; +} + +// Set the user defined method that will be run on NumberOfThreads threads +// when SingleMethodExecute is called. +void vtkMultiThreader::SetSingleMethod( vtkThreadFunctionType f, + void *data ) +{ + this->SingleMethod = f; + this->SingleData = data; +} + +// Set one of the user defined methods that will be run on NumberOfThreads +// threads when MultipleMethodExecute is called. This method should be +// called with index = 0, 1, .., NumberOfThreads-1 to set up all the +// required user defined methods +void vtkMultiThreader::SetMultipleMethod( int index, + vtkThreadFunctionType f, void *data ) +{ + // You can only set the method for 0 through NumberOfThreads-1 + if ( index >= this->NumberOfThreads ) + { + vtkErrorMacro( << "Can't set method " << index << + " with a thread count of " << this->NumberOfThreads ); + } + else + { + this->MultipleMethod[index] = f; + this->MultipleData[index] = data; + } +} + +// Execute the method set as the SingleMethod on NumberOfThreads threads. +void vtkMultiThreader::SingleMethodExecute() +{ + int thread_loop = 0; + +#ifdef VTK_USE_WIN32_THREADS + DWORD threadId; + HANDLE process_id[VTK_MAX_THREADS]; +#endif + +#ifdef VTK_USE_SPROC + siginfo_t info_ptr; + int process_id[VTK_MAX_THREADS]; +#endif + +#ifdef VTK_USE_PTHREADS + pthread_t process_id[VTK_MAX_THREADS]; +#endif + + if ( !this->SingleMethod ) + { + vtkErrorMacro( << "No single method set!" ); + return; + } + + // obey the global maximum number of threads limit + if (vtkMultiThreaderGlobalMaximumNumberOfThreads && + this->NumberOfThreads > vtkMultiThreaderGlobalMaximumNumberOfThreads) + { + this->NumberOfThreads = vtkMultiThreaderGlobalMaximumNumberOfThreads; + } + + + // We are using sproc (on SGIs), pthreads(on Suns), or a single thread + // (the default) + +#ifdef VTK_USE_WIN32_THREADS + // Using CreateThread on a PC + // + // We want to use CreateThread to start this->NumberOfThreads - 1 + // additional threads which will be used to call this->SingleMethod(). + // The parent thread will also call this routine. When it is done, + // it will wait for all the children to finish. + // + // First, start up the this->NumberOfThreads-1 processes. Keep track + // of their process ids for use later in the waitid call + for (thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + this->ThreadInfoArray[thread_loop].UserData = this->SingleData; + this->ThreadInfoArray[thread_loop].NumberOfThreads = this->NumberOfThreads; + process_id[thread_loop] = + CreateThread(NULL, 0, this->SingleMethod, + ((void *)(&this->ThreadInfoArray[thread_loop])), 0, &threadId); + if (process_id[thread_loop] == NULL) + { + vtkErrorMacro("Error in thread creation !!!"); + } + } + + // Now, the parent thread calls this->SingleMethod() itself + this->ThreadInfoArray[0].UserData = this->SingleData; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + this->SingleMethod((void *)(&this->ThreadInfoArray[0])); + + // The parent thread has finished this->SingleMethod() - so now it + // waits for each of the other processes to exit + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + WaitForSingleObject(process_id[thread_loop], INFINITE); + } + + // close the threads + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + CloseHandle(process_id[thread_loop]); + } +#endif + +#ifdef VTK_USE_SPROC + // Using sproc() on an SGI + // + // We want to use sproc to start this->NumberOfThreads - 1 additional + // threads which will be used to call this->SingleMethod(). The + // parent thread will also call this routine. When it is done, + // it will wait for all the children to finish. + // + // First, start up the this->NumberOfThreads-1 processes. Keep track + // of their process ids for use later in the waitid call + + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + this->ThreadInfoArray[thread_loop].UserData = this->SingleData; + this->ThreadInfoArray[thread_loop].NumberOfThreads = this->NumberOfThreads; + process_id[thread_loop] = + sproc( this->SingleMethod, PR_SADDR, + ( (void *)(&this->ThreadInfoArray[thread_loop]) ) ); + if ( process_id[thread_loop] == -1) + { + vtkErrorMacro("sproc call failed. Code: " << errno << endl); + } + } + + // Now, the parent thread calls this->SingleMethod() itself + this->ThreadInfoArray[0].UserData = this->SingleData; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + this->SingleMethod((void *)(&this->ThreadInfoArray[0]) ); + + // The parent thread has finished this->SingleMethod() - so now it + // waits for each of the other processes to exit + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + waitid( P_PID, (id_t) process_id[thread_loop], &info_ptr, WEXITED ); + } +#endif + +#ifdef VTK_USE_PTHREADS + // Using POSIX threads + // + // We want to use pthread_create to start this->NumberOfThreads-1 additional + // threads which will be used to call this->SingleMethod(). The + // parent thread will also call this routine. When it is done, + // it will wait for all the children to finish. + // + // First, start up the this->NumberOfThreads-1 processes. Keep track + // of their process ids for use later in the pthread_join call + + pthread_attr_t attr; + +#ifdef VTK_HP_PTHREADS + pthread_attr_create( &attr ); +#else + pthread_attr_init(&attr); +#if !defined(__CYGWIN__) + pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); +#endif +#endif + + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + this->ThreadInfoArray[thread_loop].UserData = this->SingleData; + this->ThreadInfoArray[thread_loop].NumberOfThreads = this->NumberOfThreads; + +#ifdef VTK_HP_PTHREADS + pthread_create( &(process_id[thread_loop]), + attr, this->SingleMethod, + ( (void *)(&this->ThreadInfoArray[thread_loop]) ) ); +#else + int threadError; + threadError = + pthread_create( &(process_id[thread_loop]), &attr, + reinterpret_cast( + this->SingleMethod), + ( (void *)(&this->ThreadInfoArray[thread_loop]) ) ); + if (threadError != 0) + { + vtkErrorMacro(<< "Unable to create a thread. pthread_create() returned " + << threadError); + } +#endif + } + + // Now, the parent thread calls this->SingleMethod() itself + this->ThreadInfoArray[0].UserData = this->SingleData; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + this->SingleMethod((void *)(&this->ThreadInfoArray[0]) ); + + // The parent thread has finished this->SingleMethod() - so now it + // waits for each of the other processes to exit + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + pthread_join( process_id[thread_loop], NULL ); + } +#endif + +#ifndef VTK_USE_WIN32_THREADS +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS + // There is no multi threading, so there is only one thread. + this->ThreadInfoArray[0].UserData = this->SingleData; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + this->SingleMethod( (void *)(&this->ThreadInfoArray[0]) ); +#endif +#endif +#endif +} + +void vtkMultiThreader::MultipleMethodExecute() +{ + int thread_loop; + +#ifdef VTK_USE_WIN32_THREADS + DWORD threadId; + HANDLE process_id[VTK_MAX_THREADS]; +#endif + +#ifdef VTK_USE_SPROC + siginfo_t info_ptr; + int process_id[VTK_MAX_THREADS]; +#endif + +#ifdef VTK_USE_PTHREADS + pthread_t process_id[VTK_MAX_THREADS]; +#endif + + + // obey the global maximum number of threads limit + if (vtkMultiThreaderGlobalMaximumNumberOfThreads && + this->NumberOfThreads > vtkMultiThreaderGlobalMaximumNumberOfThreads) + { + this->NumberOfThreads = vtkMultiThreaderGlobalMaximumNumberOfThreads; + } + + for ( thread_loop = 0; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + if ( this->MultipleMethod[thread_loop] == (vtkThreadFunctionType)NULL) + { + vtkErrorMacro( << "No multiple method set for: " << thread_loop ); + return; + } + } + + // We are using sproc (on SGIs), pthreads(on Suns), CreateThread + // on a PC or a single thread (the default) + +#ifdef VTK_USE_WIN32_THREADS + // Using CreateThread on a PC + // + // We want to use CreateThread to start this->NumberOfThreads - 1 + // additional threads which will be used to call the NumberOfThreads-1 + // methods defined in this->MultipleMethods[](). The parent thread + // will call this->MultipleMethods[NumberOfThreads-1](). When it is done, + // it will wait for all the children to finish. + // + // First, start up the this->NumberOfThreads-1 processes. Keep track + // of their process ids for use later in the waitid call + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + this->ThreadInfoArray[thread_loop].UserData = + this->MultipleData[thread_loop]; + this->ThreadInfoArray[thread_loop].NumberOfThreads = this->NumberOfThreads; + process_id[thread_loop] = + CreateThread(NULL, 0, this->MultipleMethod[thread_loop], + ((void *)(&this->ThreadInfoArray[thread_loop])), 0, &threadId); + if (process_id[thread_loop] == NULL) + { + vtkErrorMacro("Error in thread creation !!!"); + } + } + + // Now, the parent thread calls the last method itself + this->ThreadInfoArray[0].UserData = this->MultipleData[0]; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + (this->MultipleMethod[0])((void *)(&this->ThreadInfoArray[0]) ); + + // The parent thread has finished its method - so now it + // waits for each of the other processes (created with sproc) to + // exit + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + WaitForSingleObject(process_id[thread_loop], INFINITE); + } + + // close the threads + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + CloseHandle(process_id[thread_loop]); + } +#endif + +#ifdef VTK_USE_SPROC + // Using sproc() on an SGI + // + // We want to use sproc to start this->NumberOfThreads - 1 additional + // threads which will be used to call the NumberOfThreads-1 methods + // defined in this->MultipleMethods[](). The parent thread + // will call this->MultipleMethods[NumberOfThreads-1](). When it is done, + // it will wait for all the children to finish. + // + // First, start up the this->NumberOfThreads-1 processes. Keep track + // of their process ids for use later in the waitid call + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + this->ThreadInfoArray[thread_loop].UserData = + this->MultipleData[thread_loop]; + this->ThreadInfoArray[thread_loop].NumberOfThreads = this->NumberOfThreads; + process_id[thread_loop] = + sproc( this->MultipleMethod[thread_loop], PR_SADDR, + ( (void *)(&this->ThreadInfoArray[thread_loop]) ) ); + } + + // Now, the parent thread calls the last method itself + this->ThreadInfoArray[0].UserData = this->MultipleData[0]; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + (this->MultipleMethod[0])((void *)(&this->ThreadInfoArray[0]) ); + + // The parent thread has finished its method - so now it + // waits for each of the other processes (created with sproc) to + // exit + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + waitid( P_PID, (id_t) process_id[thread_loop], &info_ptr, WEXITED ); + } +#endif + +#ifdef VTK_USE_PTHREADS + // Using POSIX threads + // + // We want to use pthread_create to start this->NumberOfThreads - 1 + // additional + // threads which will be used to call the NumberOfThreads-1 methods + // defined in this->MultipleMethods[](). The parent thread + // will call this->MultipleMethods[NumberOfThreads-1](). When it is done, + // it will wait for all the children to finish. + // + // First, start up the this->NumberOfThreads-1 processes. Keep track + // of their process ids for use later in the pthread_join call + + pthread_attr_t attr; + +#ifdef VTK_HP_PTHREADS + pthread_attr_create( &attr ); +#else + pthread_attr_init(&attr); +#ifndef __CYGWIN__ + pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); +#endif +#endif + + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + this->ThreadInfoArray[thread_loop].UserData = + this->MultipleData[thread_loop]; + this->ThreadInfoArray[thread_loop].NumberOfThreads = this->NumberOfThreads; +#ifdef VTK_HP_PTHREADS + pthread_create( &(process_id[thread_loop]), + attr, this->MultipleMethod[thread_loop], + ( (void *)(&this->ThreadInfoArray[thread_loop]) ) ); +#else + pthread_create( &(process_id[thread_loop]), + &attr, + reinterpret_cast( + this->MultipleMethod[thread_loop]), + ( (void *)(&this->ThreadInfoArray[thread_loop]) ) ); +#endif + } + + // Now, the parent thread calls the last method itself + this->ThreadInfoArray[0].UserData = this->MultipleData[0]; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + (this->MultipleMethod[0])((void *)(&this->ThreadInfoArray[0]) ); + + // The parent thread has finished its method - so now it + // waits for each of the other processes to exit + for ( thread_loop = 1; thread_loop < this->NumberOfThreads; thread_loop++ ) + { + pthread_join( process_id[thread_loop], NULL ); + } +#endif + +#ifndef VTK_USE_WIN32_THREADS +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS + // There is no multi threading, so there is only one thread. + this->ThreadInfoArray[0].UserData = this->MultipleData[0]; + this->ThreadInfoArray[0].NumberOfThreads = this->NumberOfThreads; + (this->MultipleMethod[0])( (void *)(&this->ThreadInfoArray[0]) ); +#endif +#endif +#endif +} + +int vtkMultiThreader::SpawnThread( vtkThreadFunctionType f, void *userdata ) +{ + int id; + +#ifdef VTK_USE_WIN32_THREADS + DWORD threadId; +#endif + + for ( id = 0; id < VTK_MAX_THREADS; id++ ) + { + if ( this->SpawnedThreadActiveFlagLock[id] == NULL ) + { + this->SpawnedThreadActiveFlagLock[id] = vtkMutexLock::New(); + } + this->SpawnedThreadActiveFlagLock[id]->Lock(); + if (this->SpawnedThreadActiveFlag[id] == 0) + { + // We've got a useable thread id, so grab it + this->SpawnedThreadActiveFlag[id] = 1; + this->SpawnedThreadActiveFlagLock[id]->Unlock(); + break; + } + this->SpawnedThreadActiveFlagLock[id]->Unlock(); + } + + if ( id >= VTK_MAX_THREADS ) + { + vtkErrorMacro( << "You have too many active threads!" ); + return -1; + } + + this->SpawnedThreadInfoArray[id].UserData = userdata; + this->SpawnedThreadInfoArray[id].NumberOfThreads = 1; + this->SpawnedThreadInfoArray[id].ActiveFlag = + &this->SpawnedThreadActiveFlag[id]; + this->SpawnedThreadInfoArray[id].ActiveFlagLock = + this->SpawnedThreadActiveFlagLock[id]; + + // We are using sproc (on SGIs), pthreads(on Suns or HPs), + // CreateThread (on win32), or generating an error + +#ifdef VTK_USE_WIN32_THREADS + // Using CreateThread on a PC + // + this->SpawnedThreadProcessID[id] = + CreateThread(NULL, 0, f, + ((void *)(&this->SpawnedThreadInfoArray[id])), 0, &threadId); + if (this->SpawnedThreadProcessID[id] == NULL) + { + vtkErrorMacro("Error in thread creation !!!"); + } +#endif + +#ifdef VTK_USE_SPROC + // Using sproc() on an SGI + // + this->SpawnedThreadProcessID[id] = + sproc( f, PR_SADDR, ( (void *)(&this->SpawnedThreadInfoArray[id]) ) ); + +#endif + +#ifdef VTK_USE_PTHREADS + // Using POSIX threads + // + pthread_attr_t attr; + +#ifdef VTK_HP_PTHREADS + pthread_attr_create( &attr ); +#else + pthread_attr_init(&attr); +#ifndef __CYGWIN__ + pthread_attr_setscope(&attr, PTHREAD_SCOPE_PROCESS); +#endif +#endif + +#ifdef VTK_HP_PTHREADS + pthread_create( &(this->SpawnedThreadProcessID[id]), + attr, f, + ( (void *)(&this->SpawnedThreadInfoArray[id]) ) ); +#else + pthread_create( &(this->SpawnedThreadProcessID[id]), + &attr, + reinterpret_cast(f), + ( (void *)(&this->SpawnedThreadInfoArray[id]) ) ); +#endif + +#endif + +#ifndef VTK_USE_WIN32_THREADS +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS + // There is no multi threading, so there is only one thread. + // This won't work - so give an error message. + vtkErrorMacro( << "Cannot spawn thread in a single threaded environment!" ); + this->SpawnedThreadActiveFlagLock[id]->Delete(); + id = -1; +#endif +#endif +#endif + + return id; +} + +void vtkMultiThreader::TerminateThread( int threadID ) +{ + + if ( !this->SpawnedThreadActiveFlag[threadID] ) + { + return; + } + + this->SpawnedThreadActiveFlagLock[threadID]->Lock(); + this->SpawnedThreadActiveFlag[threadID] = 0; + this->SpawnedThreadActiveFlagLock[threadID]->Unlock(); + +#ifdef VTK_USE_WIN32_THREADS + WaitForSingleObject(this->SpawnedThreadProcessID[threadID], INFINITE); + CloseHandle(this->SpawnedThreadProcessID[threadID]); +#endif + +#ifdef VTK_USE_SPROC + siginfo_t info_ptr; + + waitid( P_PID, (id_t) this->SpawnedThreadProcessID[threadID], + &info_ptr, WEXITED ); +#endif + +#ifdef VTK_USE_PTHREADS + pthread_join( this->SpawnedThreadProcessID[threadID], NULL ); +#endif + +#ifndef VTK_USE_WIN32_THREADS +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS + // There is no multi threading, so there is only one thread. + // This won't work - so give an error message. + vtkErrorMacro(<< "Cannot terminate thread in single threaded environment!"); +#endif +#endif +#endif + + this->SpawnedThreadActiveFlagLock[threadID]->Delete(); + this->SpawnedThreadActiveFlagLock[threadID] = NULL; + +} + +//---------------------------------------------------------------------------- +vtkMultiThreaderIDType vtkMultiThreader::GetCurrentThreadID() +{ +#if defined(VTK_USE_PTHREADS) + return pthread_self(); +#elif defined(VTK_USE_WIN32_THREADS) + return GetCurrentThreadId(); +#elif defined(VTK_USE_SPROC) + return getpid(); +#else + // No threading implementation. Assume all callers are in the same + // thread. + return 0; +#endif +} + +//---------------------------------------------------------------------------- +int vtkMultiThreader::ThreadsEqual(vtkMultiThreaderIDType t1, + vtkMultiThreaderIDType t2) +{ +#if defined(VTK_USE_PTHREADS) + return pthread_equal(t1, t2) != 0; +#elif defined(VTK_USE_WIN32_THREADS) + return t1 == t2; +#elif defined(VTK_USE_SPROC) + return t1 == t2; +#else + // No threading implementation. Assume all callers are in the same + // thread. + return 1; +#endif +} + +// Print method for the multithreader +void vtkMultiThreader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Thread Count: " << this->NumberOfThreads << "\n"; + os << indent << "Global Maximum Number Of Threads: " << + vtkMultiThreaderGlobalMaximumNumberOfThreads << endl; + os << "Thread system used: " << +#ifdef VTK_USE_PTHREADS + "PTHREADS" +#elif defined VTK_USE_SPROC + "SPROC" +#elif defined VTK_USE_WIN32_THREADS + "WIN32 Threads" +#elif defined VTK_HP_PTHREADS + "HP PThreads" +#else + "NO THREADS SUPPORT" +#endif + << endl; +} diff --git a/Common/vtkMultiThreader.h b/Common/vtkMultiThreader.h new file mode 100644 index 0000000..7a6c74b --- /dev/null +++ b/Common/vtkMultiThreader.h @@ -0,0 +1,228 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiThreader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMultiThreader - A class for performing multithreaded execution +// .SECTION Description +// vtkMultithreader is a class that provides support for multithreaded +// execution using sproc() on an SGI, or pthread_create on any platform +// supporting POSIX threads. This class can be used to execute a single +// method on multiple threads, or to specify a method per thread. + +#ifndef __vtkMultiThreader_h +#define __vtkMultiThreader_h + +#include "vtkObject.h" + +#ifdef VTK_USE_SPROC +#include // Needed for unix implementation of sproc +#include // Needed for unix implementation of sproc +#endif + +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) +#include // Needed for PTHREAD implementation of mutex +#include // Needed for unix implementation of pthreads +#include // Needed for unix implementation of pthreads +#endif + +// If VTK_USE_SPROC is defined, then sproc() will be used to create +// multiple threads on an SGI. If VTK_USE_PTHREADS is defined, then +// pthread_create() will be used to create multiple threads (on +// a sun, for example) + +// Defined in vtkSystemIncludes.h: +// VTK_MAX_THREADS + +// If VTK_USE_PTHREADS is defined, then the multithreaded +// function is of type void *, and returns NULL +// Otherwise the type is void which is correct for WIN32 +// and SPROC +//BTX +#ifdef VTK_USE_SPROC +typedef int vtkThreadProcessIDType; +typedef int vtkMultiThreaderIDType; +#endif + +// Defined in vtkSystemIncludes.h: +// VTK_THREAD_RETURN_VALUE +// VTK_THREAD_RETURN_TYPE + +#ifdef VTK_USE_PTHREADS +typedef void *(*vtkThreadFunctionType)(void *); +typedef pthread_t vtkThreadProcessIDType; +// #define VTK_THREAD_RETURN_VALUE NULL +// #define VTK_THREAD_RETURN_TYPE void * +typedef pthread_t vtkMultiThreaderIDType; +#endif + +#ifdef VTK_USE_WIN32_THREADS +typedef vtkWindowsLPTHREAD_START_ROUTINE vtkThreadFunctionType; +typedef vtkWindowsHANDLE vtkThreadProcessIDType; +// #define VTK_THREAD_RETURN_VALUE 0 +// #define VTK_THREAD_RETURN_TYPE DWORD __stdcall +typedef vtkWindowsDWORD vtkMultiThreaderIDType; +#endif + +#if !defined(VTK_USE_PTHREADS) && !defined(VTK_USE_WIN32_THREADS) +typedef void (*vtkThreadFunctionType)(void *); +typedef int vtkThreadProcessIDType; +// #define VTK_THREAD_RETURN_VALUE +// #define VTK_THREAD_RETURN_TYPE void +typedef int vtkMultiThreaderIDType; +#endif +//ETX + +class vtkMutexLock; + +class VTK_COMMON_EXPORT vtkMultiThreader : public vtkObject +{ +public: + static vtkMultiThreader *New(); + + vtkTypeRevisionMacro(vtkMultiThreader,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is the structure that is passed to the thread that is + // created from the SingleMethodExecute, MultipleMethodExecute or + // the SpawnThread method. It is passed in as a void *, and it is + // up to the method to cast correctly and extract the information. + // The ThreadID is a number between 0 and NumberOfThreads-1 that indicates + // the id of this thread. The NumberOfThreads is this->NumberOfThreads for + // threads created from SingleMethodExecute or MultipleMethodExecute, + // and it is 1 for threads created from SpawnThread. + // The UserData is the (void *)arg passed into the SetSingleMethod, + // SetMultipleMethod, or SpawnThread method. + + //BTX +#define ThreadInfoStruct vtkMultiThreader::ThreadInfo + class ThreadInfo + { + public: + int ThreadID; + int NumberOfThreads; + int *ActiveFlag; + vtkMutexLock *ActiveFlagLock; + void *UserData; + }; + //ETX + + // Description: + // Get/Set the number of threads to create. It will be clamped to the range + // 1 - VTK_MAX_THREADS, so the caller of this method should check that the + // requested number of threads was accepted. + vtkSetClampMacro( NumberOfThreads, int, 1, VTK_MAX_THREADS ); + virtual int GetNumberOfThreads(); + + // Description: + // Set/Get the maximum number of threads to use when multithreading. + // This limits and overrides any other settings for multithreading. + // A value of zero indicates no limit. + static void SetGlobalMaximumNumberOfThreads(int val); + static int GetGlobalMaximumNumberOfThreads(); + + // Description: + // Set/Get the value which is used to initialize the NumberOfThreads + // in the constructor. Initially this default is set to the number of + // processors or VTK_MAX_THREADS (which ever is less). + static void SetGlobalDefaultNumberOfThreads(int val); + static int GetGlobalDefaultNumberOfThreads(); + + // These methods are excluded from Tcl wrapping 1) because the + // wrapper gives up on them and 2) because they really shouldn't be + // called from a script anyway. + //BTX + + // Description: + // Execute the SingleMethod (as define by SetSingleMethod) using + // this->NumberOfThreads threads. + void SingleMethodExecute(); + + // Description: + // Execute the MultipleMethods (as define by calling SetMultipleMethod + // for each of the required this->NumberOfThreads methods) using + // this->NumberOfThreads threads. + void MultipleMethodExecute(); + + // Description: + // Set the SingleMethod to f() and the UserData field of the + // ThreadInfo that is passed to it will be data. + // This method (and all the methods passed to SetMultipleMethod) + // must be of type vtkThreadFunctionType and must take a single argument of + // type void *. + void SetSingleMethod(vtkThreadFunctionType, void *data ); + + // Description: + // Set the MultipleMethod at the given index to f() and the UserData + // field of the ThreadInfo that is passed to it will be data. + void SetMultipleMethod( int index, vtkThreadFunctionType, void *data ); + + // Description: + // Create a new thread for the given function. Return a thread id + // which is a number between 0 and VTK_MAX_THREADS - 1. This id should + // be used to kill the thread at a later time. + int SpawnThread( vtkThreadFunctionType, void *data ); + + // Description: + // Terminate the thread that was created with a SpawnThreadExecute() + void TerminateThread( int thread_id ); + + // Description: + // Get the thread identifier of the calling thread. + static vtkMultiThreaderIDType GetCurrentThreadID(); + + // Description: + // Check whether two thread identifiers refer to the same thread. + static int ThreadsEqual(vtkMultiThreaderIDType t1, + vtkMultiThreaderIDType t2); + +protected: + vtkMultiThreader(); + ~vtkMultiThreader(); + + // The number of threads to use + int NumberOfThreads; + + // An array of thread info containing a thread id + // (0, 1, 2, .. VTK_MAX_THREADS-1), the thread count, and a pointer + // to void so that user data can be passed to each thread + ThreadInfo ThreadInfoArray[VTK_MAX_THREADS]; + + // The methods + vtkThreadFunctionType SingleMethod; + vtkThreadFunctionType MultipleMethod[VTK_MAX_THREADS]; + + // Storage of MutexFunctions and ints used to control spawned + // threads and the spawned thread ids + int SpawnedThreadActiveFlag[VTK_MAX_THREADS]; + vtkMutexLock *SpawnedThreadActiveFlagLock[VTK_MAX_THREADS]; + vtkThreadProcessIDType SpawnedThreadProcessID[VTK_MAX_THREADS]; + ThreadInfo SpawnedThreadInfoArray[VTK_MAX_THREADS]; + +//ETX + + // Internal storage of the data + void *SingleData; + void *MultipleData[VTK_MAX_THREADS]; + +private: + vtkMultiThreader(const vtkMultiThreader&); // Not implemented. + void operator=(const vtkMultiThreader&); // Not implemented. +}; + +#endif + + + + + diff --git a/Common/vtkMutexLock.cxx b/Common/vtkMutexLock.cxx new file mode 100644 index 0000000..f66b45a --- /dev/null +++ b/Common/vtkMutexLock.cxx @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMutexLock.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMutexLock.h" +#include "vtkObjectFactory.h" + +#ifdef VTK_USE_WIN32_THREADS +# include "vtkWindows.h" +#endif + +vtkCxxRevisionMacro(vtkMutexLock, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkMutexLock); + +// New for the SimpleMutex +vtkSimpleMutexLock *vtkSimpleMutexLock::New() +{ + return new vtkSimpleMutexLock; +} + +// Construct a new vtkMutexLock +vtkSimpleMutexLock::vtkSimpleMutexLock() +{ +#ifdef VTK_USE_SPROC + init_lock( &this->MutexLock ); +#endif + +#ifdef VTK_USE_WIN32_THREADS + this->MutexLock = CreateMutex( NULL, FALSE, NULL ); +#endif + +#ifdef VTK_USE_PTHREADS +#ifdef VTK_HP_PTHREADS + pthread_mutex_init(&(this->MutexLock), pthread_mutexattr_default); +#else + pthread_mutex_init(&(this->MutexLock), NULL); +#endif +#endif + +} + +// Destruct the vtkMutexVariable +vtkSimpleMutexLock::~vtkSimpleMutexLock() +{ +#ifdef VTK_USE_WIN32_THREADS + CloseHandle(this->MutexLock); +#endif + +#ifdef VTK_USE_PTHREADS + pthread_mutex_destroy( &this->MutexLock); +#endif +} + +// Lock the vtkMutexLock +void vtkSimpleMutexLock::Lock() +{ +#ifdef VTK_USE_SPROC + spin_lock( &this->MutexLock ); +#endif + +#ifdef VTK_USE_WIN32_THREADS + WaitForSingleObject( this->MutexLock, INFINITE ); +#endif + +#ifdef VTK_USE_PTHREADS + pthread_mutex_lock( &this->MutexLock); +#endif +} + +// Unlock the vtkMutexLock +void vtkSimpleMutexLock::Unlock() +{ +#ifdef VTK_USE_SPROC + release_lock( &this->MutexLock ); +#endif + +#ifdef VTK_USE_WIN32_THREADS + ReleaseMutex( this->MutexLock ); +#endif + +#ifdef VTK_USE_PTHREADS + pthread_mutex_unlock( &this->MutexLock); +#endif +} + +void vtkMutexLock::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + diff --git a/Common/vtkMutexLock.h b/Common/vtkMutexLock.h new file mode 100644 index 0000000..259845c --- /dev/null +++ b/Common/vtkMutexLock.h @@ -0,0 +1,112 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMutexLock.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMutexLock - mutual exclusion locking class +// .SECTION Description +// vtkMutexLock allows the locking of variables which are accessed +// through different threads. This header file also defines +// vtkSimpleMutexLock which is not a subclass of vtkObject. + +#ifndef __vtkMutexVariable_h +#define __vtkMutexVariable_h + + +#include "vtkObject.h" + +//BTX + +#ifdef VTK_USE_SPROC +#include // Needed for SPROC implementation of mutex +typedef abilock_t vtkMutexType; +#endif + +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) +#include // Needed for PTHREAD implementation of mutex +typedef pthread_mutex_t vtkMutexType; +#endif + +#ifdef VTK_USE_WIN32_THREADS +typedef vtkWindowsHANDLE vtkMutexType; +#endif + +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS +#ifndef VTK_USE_WIN32_THREADS +typedef int vtkMutexType; +#endif +#endif +#endif + +// Mutex lock that is not a vtkObject. +class VTK_COMMON_EXPORT vtkSimpleMutexLock +{ +public: + // left public purposely + vtkSimpleMutexLock(); + virtual ~vtkSimpleMutexLock(); + + static vtkSimpleMutexLock *New(); + + void Delete() {delete this;} + + // Description: + // Lock the vtkMutexLock + void Lock( void ); + + // Description: + // Unlock the vtkMutexLock + void Unlock( void ); + +protected: + vtkMutexType MutexLock; +}; + +//ETX + +class VTK_COMMON_EXPORT vtkMutexLock : public vtkObject +{ +public: + static vtkMutexLock *New(); + + vtkTypeRevisionMacro(vtkMutexLock,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Lock the vtkMutexLock + void Lock( void ); + + // Description: + // Unlock the vtkMutexLock + void Unlock( void ); + +protected: + vtkSimpleMutexLock SimpleMutexLock; + vtkMutexLock() {}; +private: + vtkMutexLock(const vtkMutexLock&); // Not implemented. + void operator=(const vtkMutexLock&); // Not implemented. +}; + + +inline void vtkMutexLock::Lock( void ) +{ + this->SimpleMutexLock.Lock(); +} + +inline void vtkMutexLock::Unlock( void ) +{ + this->SimpleMutexLock.Unlock(); +} + +#endif diff --git a/Common/vtkOStrStreamWrapper.cxx b/Common/vtkOStrStreamWrapper.cxx new file mode 100644 index 0000000..8ea057a --- /dev/null +++ b/Common/vtkOStrStreamWrapper.cxx @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOStrStreamWrapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSystemIncludes.h" // Cannot include vtkOStrStreamWrapper.h directly. + +// Need strcpy. +#include + +// Use ANSI ostrstream or ostringstream. +#ifdef VTK_USE_ANSI_STDLIB +# ifndef VTK_NO_ANSI_STRING_STREAM +# include +using std::ostringstream; +# else +# include +using std::ostrstream; +using std::ends; +# endif + +// Use old-style strstream. +#else +# ifdef _WIN32_WCE +# include "vtkWinCE.h" +# else +# if defined(_MSC_VER) +# include +# else +# include +# endif +# endif // Win CE +#endif + +//---------------------------------------------------------------------------- +#if defined(VTK_USE_ANSI_STDLIB) && !defined(VTK_NO_ANSI_STRING_STREAM) +vtkOStrStreamWrapper::vtkOStrStreamWrapper(): + vtkOStreamWrapper(*(new ostringstream)) +{ + this->Result = 0; + this->Frozen = 0; +} +#else +vtkOStrStreamWrapper::vtkOStrStreamWrapper(): + vtkOStreamWrapper(*(new ostrstream)) +{ + this->Result = 0; + this->Frozen = 0; +} +#endif + +//---------------------------------------------------------------------------- +vtkOStrStreamWrapper::~vtkOStrStreamWrapper() +{ + if(this->Result && !this->Frozen) + { + delete [] this->Result; + } + delete &this->ostr; +} + +//---------------------------------------------------------------------------- +#if defined(VTK_USE_ANSI_STDLIB) && !defined(VTK_NO_ANSI_STRING_STREAM) +char* vtkOStrStreamWrapper::str() +{ + if(!this->Result) + { + std::string s = static_cast(&this->ostr)->str(); + this->Result = new char[s.length()+1]; + strcpy(this->Result, s.c_str()); + this->freeze(); + } + return this->Result; +} +#else +char* vtkOStrStreamWrapper::str() +{ + if(!this->Result) + { + this->ostr << ends; + this->Result = static_cast(&this->ostr)->str(); + this->freeze(); + } + return this->Result; +} +#endif + +//---------------------------------------------------------------------------- +vtkOStrStreamWrapper* vtkOStrStreamWrapper::rdbuf() +{ + return this; +} + +//---------------------------------------------------------------------------- +void vtkOStrStreamWrapper::freeze() +{ + this->freeze(1); +} + +//---------------------------------------------------------------------------- +void vtkOStrStreamWrapper::freeze(int f) +{ + this->Frozen = f; +} diff --git a/Common/vtkOStrStreamWrapper.h b/Common/vtkOStrStreamWrapper.h new file mode 100644 index 0000000..9685977 --- /dev/null +++ b/Common/vtkOStrStreamWrapper.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOStrStreamWrapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOStrStreamWrapper - Wrapper for ostrstream. Internal VTK use only. +// .SECTION Description +// Provides a wrapper around the C++ ostrstream class so that VTK +// source files need not include the full C++ streams library. This +// is intended to prevent cluttering of the translation unit and speed +// up compilation. Experimentation has revealed between 10% and 60% +// less time for compilation depending on the platform. This wrapper +// is used by the macros in vtkSetGet.h. + +#ifndef __vtkOStrStreamWrapper_h +#define __vtkOStrStreamWrapper_h + +#ifndef __VTK_SYSTEM_INCLUDES__INSIDE +Do_not_include_vtkOStrStreamWrapper_directly__vtkSystemIncludes_includes_it; +#endif + +class VTK_COMMON_EXPORT vtkOStrStreamWrapper: public vtkOStreamWrapper +{ +public: + // Description: + // Constructor. + vtkOStrStreamWrapper(); + + // Description: + // Destructor frees all used memory. + ~vtkOStrStreamWrapper(); + + // Description: + // Get the string that has been written. This call transfers + // ownership of the returned memory to the caller. Call + // rdbuf()->freeze(0) to return ownership to the vtkOStrStreamWrapper. + char* str(); + + // Description: + // Returns a pointer to this class. This is a hack so that the old + // ostrstream's s.rdbuf()->freeze(0) can work. + vtkOStrStreamWrapper* rdbuf(); + + // Description: + // Set whether the memory is frozen. The vtkOStrStreamWrapper will free + // the memory returned by str() only if it is not frozen. + void freeze(); + void freeze(int); +protected: + // The pointer returned by str(). + char* Result; + + // Whether the caller of str() owns the memory. + int Frozen; +private: + vtkOStrStreamWrapper(const vtkOStrStreamWrapper& r); // Not Implemented. + vtkOStrStreamWrapper& operator=(const vtkOStrStreamWrapper&); // Not Implemented. +}; + +#endif diff --git a/Common/vtkOStreamWrapper.cxx b/Common/vtkOStreamWrapper.cxx new file mode 100644 index 0000000..871a3b0 --- /dev/null +++ b/Common/vtkOStreamWrapper.cxx @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOStreamWrapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSystemIncludes.h" // Cannot include vtkOStreamWrapper.h directly. + +#include "vtkIOStream.h" +#include "vtkIndent.h" +#include "vtkLargeInteger.h" +#include "vtkObjectBase.h" +#include "vtkSmartPointerBase.h" + +#define VTKOSTREAM_OPERATOR(type) \ + vtkOStreamWrapper& vtkOStreamWrapper::operator << (type a) \ + { this->ostr << a; return *this; } + +#define VTKOSTREAM_OPERATOR_FUNC(arg) \ + vtkOStreamWrapper& vtkOStreamWrapper::operator << (arg) \ + { this->ostr << a; return *this; } + +//---------------------------------------------------------------------------- +vtkOStreamWrapper::vtkOStreamWrapper(ostream& os): ostr(os) +{ +} + +//---------------------------------------------------------------------------- +vtkOStreamWrapper::vtkOStreamWrapper(vtkOStreamWrapper& r): ostr(r.ostr) +{ +} + +//---------------------------------------------------------------------------- +vtkOStreamWrapper::~vtkOStreamWrapper() +{ +} + +//---------------------------------------------------------------------------- +vtkOStreamWrapper& vtkOStreamWrapper::operator << (const EndlType&) +{ + this->ostr << endl; + return *this; +} + +//---------------------------------------------------------------------------- +VTKOSTREAM_OPERATOR(const vtkIndent&); +VTKOSTREAM_OPERATOR(vtkObjectBase&); +VTKOSTREAM_OPERATOR(const vtkLargeInteger&); +VTKOSTREAM_OPERATOR(const vtkSmartPointerBase&); +VTKOSTREAM_OPERATOR(ostream&); +VTKOSTREAM_OPERATOR(const char*); +VTKOSTREAM_OPERATOR(void*); +VTKOSTREAM_OPERATOR(char); +VTKOSTREAM_OPERATOR(short); +VTKOSTREAM_OPERATOR(int); +VTKOSTREAM_OPERATOR(long); +VTKOSTREAM_OPERATOR(unsigned char); +VTKOSTREAM_OPERATOR(unsigned short); +VTKOSTREAM_OPERATOR(unsigned int); +VTKOSTREAM_OPERATOR(unsigned long); +VTKOSTREAM_OPERATOR(float); +VTKOSTREAM_OPERATOR(double); +#ifdef VTK_COMPILER_HAS_BOOL +VTKOSTREAM_OPERATOR(bool); +#endif +#if defined(VTK_TYPE_USE_LONG_LONG) +VTKOSTREAM_OPERATOR(long long); +VTKOSTREAM_OPERATOR(unsigned long long); +#endif +#if defined(VTK_TYPE_USE___INT64) +VTKOSTREAM_OPERATOR(__int64); +VTKOSTREAM_OPERATOR(unsigned __int64); +#endif +VTKOSTREAM_OPERATOR_FUNC(void (*a)(void*)); +VTKOSTREAM_OPERATOR_FUNC(void* (*a)(void*)); +VTKOSTREAM_OPERATOR_FUNC(int (*a)(void*)); +VTKOSTREAM_OPERATOR_FUNC(int* (*a)(void*)); +VTKOSTREAM_OPERATOR_FUNC(float* (*a)(void*)); +VTKOSTREAM_OPERATOR_FUNC(const char* (*a)(void*)); +VTKOSTREAM_OPERATOR_FUNC(void (*a)(void*, int*)); + +//---------------------------------------------------------------------------- +#if defined(__IBMCPP__) +vtkOStreamWrapper& vtkOStreamWrapper::WriteInternal(const char* a) +{ + this->ostr << a; + return *this; +} +vtkOStreamWrapper& vtkOStreamWrapper::WriteInternal(void* a) +{ + this->ostr << a; + return *this; +} +#endif + +//---------------------------------------------------------------------------- +vtkOStreamWrapper& vtkOStreamWrapper::write(const char* str, + unsigned long size) +{ + this->ostr.write(str, size); + return *this; +} + +//---------------------------------------------------------------------------- +ostream& vtkOStreamWrapper::GetOStream() +{ + return this->ostr; +} + +//---------------------------------------------------------------------------- +vtkOStreamWrapper::operator ostream&() +{ + return this->ostr; +} + +//---------------------------------------------------------------------------- +vtkOStreamWrapper::operator int() +{ + return this->ostr? 1:0; +} + +//---------------------------------------------------------------------------- +void vtkOStreamWrapper::flush() +{ + this->ostr.flush(); +} diff --git a/Common/vtkOStreamWrapper.h b/Common/vtkOStreamWrapper.h new file mode 100644 index 0000000..cb9081b --- /dev/null +++ b/Common/vtkOStreamWrapper.h @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOStreamWrapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOStreamWrapper - Wrapper for C++ ostream. Internal VTK use only. +// .SECTION Description +// Provides a wrapper around the C++ ostream so that VTK source files +// need not include the full C++ streams library. This is intended to +// prevent cluttering of the translation unit and speed up +// compilation. Experimentation has revealed between 10% and 60% less +// time for compilation depending on the platform. This wrapper is +// used by the macros in vtkSetGet.h. + +#ifndef __vtkOStreamWrapper_h +#define __vtkOStreamWrapper_h + +#ifndef __VTK_SYSTEM_INCLUDES__INSIDE +Do_not_include_vtkOStreamWrapper_directly__vtkSystemIncludes_includes_it; +#endif + +class vtkIndent; +class vtkObjectBase; +class vtkLargeInteger; +class vtkSmartPointerBase; + +class VTK_COMMON_EXPORT vtkOStreamWrapper +{ +public: + // Description: + // Construct class to reference a real ostream. All methods and + // operators will be forwarded. + vtkOStreamWrapper(ostream& os); + vtkOStreamWrapper(vtkOStreamWrapper& r); + + // Description: + virtual ~vtkOStreamWrapper(); + + // Description: + // Type for a fake endl. + struct EndlType {}; + + // Description: + // Forward this output operator to the real ostream. + vtkOStreamWrapper& operator << (const EndlType&); + vtkOStreamWrapper& operator << (const vtkIndent&); + vtkOStreamWrapper& operator << (vtkObjectBase&); + vtkOStreamWrapper& operator << (const vtkLargeInteger&); + vtkOStreamWrapper& operator << (const vtkSmartPointerBase&); + vtkOStreamWrapper& operator << (ostream&); + vtkOStreamWrapper& operator << (const char*); + vtkOStreamWrapper& operator << (void*); + vtkOStreamWrapper& operator << (char); + vtkOStreamWrapper& operator << (short); + vtkOStreamWrapper& operator << (int); + vtkOStreamWrapper& operator << (long); + vtkOStreamWrapper& operator << (unsigned char); + vtkOStreamWrapper& operator << (unsigned short); + vtkOStreamWrapper& operator << (unsigned int); + vtkOStreamWrapper& operator << (unsigned long); + vtkOStreamWrapper& operator << (float); + vtkOStreamWrapper& operator << (double); +#if defined(VTK_TYPE_USE_LONG_LONG) + vtkOStreamWrapper& operator << (long long); + vtkOStreamWrapper& operator << (unsigned long long); +#endif +#if defined(VTK_TYPE_USE___INT64) + vtkOStreamWrapper& operator << (__int64); + vtkOStreamWrapper& operator << (unsigned __int64); +#endif + + // Need to switch on bool type because this wrapper is supposed to + // be as transparent as possible to user code. This example should + // not be used to justify using bool elsewhere in VTK. +#ifdef VTK_COMPILER_HAS_BOOL + vtkOStreamWrapper& operator << (bool); +#endif + + // Work-around for IBM Visual Age bug in overload resolution. +#if defined(__IBMCPP__) + vtkOStreamWrapper& WriteInternal(const char*); + vtkOStreamWrapper& WriteInternal(void*); + template + vtkOStreamWrapper& operator << (T* p) + { + return this->WriteInternal(p); + } +#endif + + vtkOStreamWrapper& operator << (void (*)(void*)); + vtkOStreamWrapper& operator << (void* (*)(void*)); + vtkOStreamWrapper& operator << (int (*)(void*)); + vtkOStreamWrapper& operator << (int* (*)(void*)); + vtkOStreamWrapper& operator << (float* (*)(void*)); + vtkOStreamWrapper& operator << (const char* (*)(void*)); + vtkOStreamWrapper& operator << (void (*)(void*, int*)); + + // Description: + // Forward the write method to the real stream. + vtkOStreamWrapper& write(const char*, unsigned long); + + // Description: + // Get a reference to the real ostream. + ostream& GetOStream(); + + // Description: + // Allow conversion to the real ostream type. This allows an + // instance of vtkOStreamWrapper to look like ostream when passing to a + // function argument. + operator ostream&(); + + // Description: + // Forward conversion to bool to the real ostream. + operator int(); + + // Description: + // Forward the flush method to the real ostream. + void flush(); + + // Description: + // Implementation detail to allow macros to provide an endl that may + // or may not be used. + static void UseEndl(const EndlType&) {} +protected: + // Reference to the real ostream. + ostream& ostr; +private: + vtkOStreamWrapper& operator=(const vtkOStreamWrapper& r); // Not Implemented. +}; + +#endif diff --git a/Common/vtkObject.cxx b/Common/vtkObject.cxx new file mode 100644 index 0000000..57f5571 --- /dev/null +++ b/Common/vtkObject.cxx @@ -0,0 +1,664 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObject.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkObject.h" + +#include "vtkCommand.h" +#include "vtkDebugLeaks.h" +#include "vtkGarbageCollector.h" +#include "vtkTimeStamp.h" + +vtkCxxRevisionMacro(vtkObject, "$Revision: 1.93 $"); + +// Initialize static member that controls warning display +static int vtkObjectGlobalWarningDisplay = 1; + + +// avoid dll boundary problems +#ifdef _WIN32 +void* vtkObject::operator new(size_t nSize) +{ + void* p=malloc(nSize); + return p; +} + +void vtkObject::operator delete( void *p ) +{ + free(p); +} +#endif + +void vtkObject::SetGlobalWarningDisplay(int val) +{ + vtkObjectGlobalWarningDisplay = val; +} + +int vtkObject::GetGlobalWarningDisplay() +{ + return vtkObjectGlobalWarningDisplay; +} + +//----------------------------------Command/Observer stuff------------------- +// +class vtkObserver +{ + public: + vtkObserver():Command(0),Event(0),Tag(0),Next(0),Priority(0.0), Visited(0) {} + ~vtkObserver(); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkCommand *Command; + unsigned long Event; + unsigned long Tag; + vtkObserver *Next; + float Priority; + int Visited; +}; + +void vtkObserver::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "vtkObserver (" << this << ")\n"; + indent = indent.GetNextIndent(); + os << indent << "Event: " << this->Event << "\n"; + os << indent << "EventName: " << vtkCommand::GetStringFromEventId(this->Event) << "\n"; + os << indent << "Command: " << this->Command << "\n"; + os << indent << "Priority: " << this->Priority << "\n"; + os << indent << "Tag: " << this->Tag << "\n"; +} + +class vtkSubjectHelper +{ +public: + vtkSubjectHelper():ListModified(0),Start(0),Count(1) {} + ~vtkSubjectHelper(); + + unsigned long AddObserver(unsigned long event, vtkCommand *cmd, float p); + void RemoveObserver(unsigned long tag); + void RemoveObservers(unsigned long event); + void RemoveObservers(unsigned long event, vtkCommand *cmd); + int InvokeEvent(unsigned long event, void *callData, vtkObject *self); + vtkCommand *GetCommand(unsigned long tag); + unsigned long GetTag(vtkCommand*); + int HasObserver(unsigned long event); + int HasObserver(unsigned long event, vtkCommand *cmd); + void PrintSelf(ostream& os, vtkIndent indent); + + int ListModified; + +protected: + vtkObserver *Start; + unsigned long Count; +}; + +// ------------------------------------vtkObject---------------------- + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkObject); + +vtkObject *vtkObject::New() +{ +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkObject"); +#endif + return new vtkObject; +} + + +// Create an object with Debug turned off and modified time initialized +// to zero. +vtkObject::vtkObject() +{ + this->Debug = 0; + this->SubjectHelper = NULL; + this->Modified(); // Insures modified time > than any other time + // initial reference count = 1 and reference counting on. +} + +vtkObject::~vtkObject() +{ + vtkDebugMacro(<< "Destructing!"); + + // warn user if reference counting is on and the object is being referenced + // by another object + if ( this->ReferenceCount > 0) + { + vtkErrorMacro(<< "Trying to delete object with non-zero reference count."); + } + delete this->SubjectHelper; + this->SubjectHelper = NULL; +} + +// Return the modification for this object. +unsigned long int vtkObject::GetMTime() +{ + return this->MTime.GetMTime(); +} + +// Chaining method to print an object's instance variables, as well as +// its superclasses. +void vtkObject::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "Debug: " << (this->Debug ? "On\n" : "Off\n"); + os << indent << "Modified Time: " << this->GetMTime() << "\n"; + this->Superclass::PrintSelf(os, indent); + os << indent << "Registered Events: "; + if ( this->SubjectHelper ) + { + os << endl; + this->SubjectHelper->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << "(none)\n"; + } +} + +// Turn debugging output on. +void vtkObject::DebugOn() +{ + this->Debug = 1; +} + +// Turn debugging output off. +void vtkObject::DebugOff() +{ + this->Debug = 0; +} + +// Get the value of the debug flag. +unsigned char vtkObject::GetDebug() +{ + return this->Debug; +} + +// Set the value of the debug flag. A non-zero value turns debugging on. +void vtkObject::SetDebug(unsigned char debugFlag) +{ + this->Debug = debugFlag; +} + + +// This method is called when vtkErrorMacro executes. It allows +// the debugger to break on error. +void vtkObject::BreakOnError() +{ +} + +//----------------------------------Command/Observer stuff------------------- +// + +vtkObserver::~vtkObserver() +{ + this->Command->UnRegister(0); +} + +vtkSubjectHelper::~vtkSubjectHelper() +{ + vtkObserver *elem = this->Start; + vtkObserver *next; + while (elem) + { + next = elem->Next; + delete elem; + elem = next; + } + this->Start = NULL; +} + + +unsigned long vtkSubjectHelper:: +AddObserver(unsigned long event, vtkCommand *cmd, float p) +{ + vtkObserver *elem; + + // initialize the new observer element + elem = new vtkObserver; + elem->Priority = p; + elem->Next = NULL; + elem->Event = event; + elem->Command = cmd; + cmd->Register(0); + elem->Tag = this->Count; + this->Count++; + + // now insert into the list + // if no other elements in the list then this is Start + if (!this->Start) + { + this->Start = elem; + } + else + { + // insert high priority first + vtkObserver* prev = 0; + vtkObserver* pos = this->Start; + while(pos->Priority >= elem->Priority && pos->Next) + { + prev = pos; + pos = pos->Next; + } + // pos is Start and elem should not be start + if(pos->Priority > elem->Priority) + { + pos->Next = elem; + } + else + { + if(prev) + { + prev->Next = elem; + } + elem->Next = pos; + // check to see if the new element is the start + if(pos == this->Start) + { + this->Start = elem; + } + } + } + return elem->Tag; +} + +void vtkSubjectHelper::RemoveObserver(unsigned long tag) +{ + vtkObserver *elem; + vtkObserver *prev; + vtkObserver *next; + + elem = this->Start; + prev = NULL; + while (elem) + { + if (elem->Tag == tag) + { + if (prev) + { + prev->Next = elem->Next; + next = prev->Next; + } + else + { + this->Start = elem->Next; + next = this->Start; + } + delete elem; + elem = next; + } + else + { + prev = elem; + elem = elem->Next; + } + } + + this->ListModified = 1; +} + +void vtkSubjectHelper::RemoveObservers(unsigned long event) +{ + vtkObserver *elem; + vtkObserver *prev; + vtkObserver *next; + + elem = this->Start; + prev = NULL; + while (elem) + { + if (elem->Event == event) + { + if (prev) + { + prev->Next = elem->Next; + next = prev->Next; + } + else + { + this->Start = elem->Next; + next = this->Start; + } + delete elem; + elem = next; + } + else + { + prev = elem; + elem = elem->Next; + } + } + + this->ListModified = 1; +} + +void vtkSubjectHelper::RemoveObservers(unsigned long event, vtkCommand *cmd) +{ + vtkObserver *elem; + vtkObserver *prev; + vtkObserver *next; + + elem = this->Start; + prev = NULL; + while (elem) + { + if (elem->Event == event && elem->Command == cmd) + { + if (prev) + { + prev->Next = elem->Next; + next = prev->Next; + } + else + { + this->Start = elem->Next; + next = this->Start; + } + delete elem; + elem = next; + } + else + { + prev = elem; + elem = elem->Next; + } + } + + this->ListModified = 1; +} + +int vtkSubjectHelper::HasObserver(unsigned long event) +{ + vtkObserver *elem = this->Start; + while (elem) + { + if (elem->Event == event || elem->Event == vtkCommand::AnyEvent) + { + return 1; + } + elem = elem->Next; + } + return 0; +} + +int vtkSubjectHelper::HasObserver(unsigned long event, vtkCommand *cmd) +{ + vtkObserver *elem = this->Start; + while (elem) + { + if ((elem->Event == event || elem->Event == vtkCommand::AnyEvent) && + elem->Command == cmd) + { + return 1; + } + elem = elem->Next; + } + return 0; +} + +int vtkSubjectHelper::InvokeEvent(unsigned long event, void *callData, + vtkObject *self) +{ + this->ListModified = 0; + + vtkObserver *elem = this->Start; + while (elem) + { + elem->Visited = 0; + elem=elem->Next; + } + + elem = this->Start; + vtkObserver *next; + while (elem) + { + // store the next pointer because elem could disappear due to Command + next = elem->Next; + if (!elem->Visited && + elem->Event == event || elem->Event == vtkCommand::AnyEvent) + { + elem->Visited = 1; + vtkCommand* command = elem->Command; + command->Register(command); + command->SetAbortFlag(0); + elem->Command->Execute(self,event,callData); + // if the command set the abort flag, then stop firing events + // and return + if(command->GetAbortFlag()) + { + command->UnRegister(); + return 1; + } + command->UnRegister(); + } + if (this->ListModified) + { + elem = this->Start; + this->ListModified = 0; + } + else + { + elem = next; + } + } + return 0; +} + +unsigned long vtkSubjectHelper::GetTag(vtkCommand* cmd) +{ + vtkObserver *elem = this->Start; + while (elem) + { + if (elem->Command == cmd) + { + return elem->Tag; + } + elem = elem->Next; + } + return 0; +} + +vtkCommand *vtkSubjectHelper::GetCommand(unsigned long tag) +{ + vtkObserver *elem = this->Start; + while (elem) + { + if (elem->Tag == tag) + { + return elem->Command; + } + elem = elem->Next; + } + return NULL; +} + +void vtkSubjectHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "Registered Observers:\n"; + indent = indent.GetNextIndent(); + vtkObserver *elem = this->Start; + if ( !elem ) + { + os << indent << "(none)\n"; + return; + } + + for ( ; elem; elem=elem->Next ) + { + elem->PrintSelf(os, indent); + } +} + +//--------------------------------vtkObject observer----------------------- +unsigned long vtkObject::AddObserver(unsigned long event, vtkCommand *cmd, float p) +{ + if (!this->SubjectHelper) + { + this->SubjectHelper = new vtkSubjectHelper; + } + return this->SubjectHelper->AddObserver(event,cmd, p); +} + +unsigned long vtkObject::AddObserver(const char *event,vtkCommand *cmd, float p) +{ + return this->AddObserver(vtkCommand::GetEventIdFromString(event), cmd, p); +} + +vtkCommand *vtkObject::GetCommand(unsigned long tag) +{ + if (this->SubjectHelper) + { + return this->SubjectHelper->GetCommand(tag); + } + return NULL; +} + +void vtkObject::RemoveObserver(unsigned long tag) +{ + if (this->SubjectHelper) + { + this->SubjectHelper->RemoveObserver(tag); + } +} + +void vtkObject::RemoveObserver(vtkCommand* c) +{ + if (this->SubjectHelper) + { + unsigned long tag = this->SubjectHelper->GetTag(c); + while(tag) + { + this->SubjectHelper->RemoveObserver(tag); + tag = this->SubjectHelper->GetTag(c); + } + } +} + +void vtkObject::RemoveObservers(unsigned long event) +{ + if (this->SubjectHelper) + { + this->SubjectHelper->RemoveObservers(event); + } +} + +void vtkObject::RemoveObservers(const char *event) +{ + this->RemoveObservers(vtkCommand::GetEventIdFromString(event)); +} + +void vtkObject::RemoveObservers(unsigned long event, vtkCommand *cmd) +{ + if (this->SubjectHelper) + { + this->SubjectHelper->RemoveObservers(event, cmd); + } +} + +void vtkObject::RemoveObservers(const char *event, vtkCommand *cmd) +{ + this->RemoveObservers(vtkCommand::GetEventIdFromString(event), cmd); +} + +int vtkObject::InvokeEvent(unsigned long event, void *callData) +{ + if (this->SubjectHelper) + { + return this->SubjectHelper->InvokeEvent(event,callData, this); + } + return 0; +} + +int vtkObject::InvokeEvent(const char *event, void *callData) +{ + return this->InvokeEvent(vtkCommand::GetEventIdFromString(event), callData); +} + +int vtkObject::HasObserver(unsigned long event) +{ + if (this->SubjectHelper) + { + return this->SubjectHelper->HasObserver(event); + } + return 0; +} + +int vtkObject::HasObserver(const char *event) +{ + return this->HasObserver(vtkCommand::GetEventIdFromString(event)); +} + +int vtkObject::HasObserver(unsigned long event, vtkCommand *cmd) +{ + if (this->SubjectHelper) + { + return this->SubjectHelper->HasObserver(event, cmd); + } + return 0; +} + +int vtkObject::HasObserver(const char *event, vtkCommand *cmd) +{ + return this->HasObserver(vtkCommand::GetEventIdFromString(event), cmd); +} + +void vtkObject::Modified() +{ + this->MTime.Modified(); + this->InvokeEvent(vtkCommand::ModifiedEvent,NULL); +} + +//---------------------------------------------------------------------------- +void vtkObject::RegisterInternal(vtkObjectBase* o, int check) +{ + // Print debugging messages. + if(o) + { + vtkDebugMacro(<< "Registered by " << o->GetClassName() << " (" << o + << "), ReferenceCount = " << this->ReferenceCount+1); + } + else + { + vtkDebugMacro(<< "Registered by NULL, ReferenceCount = " + << this->ReferenceCount+1); + } + + // Increment the reference count. + this->Superclass::RegisterInternal(o, check); +} + +//---------------------------------------------------------------------------- +void vtkObject::UnRegisterInternal(vtkObjectBase* o, int check) +{ + // Print debugging messages. + if(o) + { + vtkDebugMacro(<< "UnRegistered by " + << o->GetClassName() << " (" << o << "), ReferenceCount = " + << (this->ReferenceCount-1)); + } + else + { + vtkDebugMacro(<< "UnRegistered by NULL, ReferenceCount = " + << (this->ReferenceCount-1)); + } + + if(this->ReferenceCount == 1) + { + // The reference count is 1, so the object is about to be deleted. + // Invoke the delete event. + this->InvokeEvent(vtkCommand::DeleteEvent, 0); + } + + // Decrement the reference count. + this->Superclass::UnRegisterInternal(o, check); +} diff --git a/Common/vtkObject.h b/Common/vtkObject.h new file mode 100644 index 0000000..f9119fe --- /dev/null +++ b/Common/vtkObject.h @@ -0,0 +1,181 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObject.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkObject - abstract base class for most VTK objects +// .SECTION Description +// vtkObject is the base class for most objects in the visualization +// toolkit. vtkObject provides methods for tracking modification time, +// debugging, printing, and event callbacks. Most objects created +// within the VTK framework should be a subclass of vtkObject or one +// of its children. The few exceptions tend to be very small helper +// classes that usually never get instantiated or situations where +// multiple inheritance gets in the way. vtkObject also performs +// reference counting: objects that are reference counted exist as +// long as another object uses them. Once the last reference to a +// reference counted object is removed, the object will spontaneously +// destruct. + +// .SECTION Caveats +// Note: in VTK objects should always be created with the New() method +// and deleted with the Delete() method. VTK objects cannot be +// allocated off the stack (i.e., automatic objects) because the +// constructor is a protected method. + +// .SECTION See also +// vtkCommand vtkTimeStamp + +#ifndef __vtkObject_h +#define __vtkObject_h + +#include "vtkObjectBase.h" +#include "vtkSetGet.h" +#include "vtkTimeStamp.h" + +class vtkSubjectHelper; +class vtkCommand; + +class VTK_COMMON_EXPORT vtkObject : public vtkObjectBase +{ +public: + vtkTypeRevisionMacro(vtkObject,vtkObjectBase); + + // Description: + // Create an object with Debug turned off, modified time initialized + // to zero, and reference counting on. + static vtkObject *New(); + +#ifdef _WIN32 + // avoid dll boundary problems + void* operator new( size_t tSize ); + void operator delete( void* p ); +#endif + + // Description: + // Turn debugging output on. + virtual void DebugOn(); + + // Description: + // Turn debugging output off. + virtual void DebugOff(); + + // Description: + // Get the value of the debug flag. + unsigned char GetDebug(); + + // Description: + // Set the value of the debug flag. A non-zero value turns debugging on. + void SetDebug(unsigned char debugFlag); + + // Description: + // This method is called when vtkErrorMacro executes. It allows + // the debugger to break on error. + static void BreakOnError(); + + // Description: + // Update the modification time for this object. Many filters rely on + // the modification time to determine if they need to recompute their + // data. The modification time is a unique monotonically increasing + // unsigned long integer. + virtual void Modified(); + + // Description: + // Return this object's modified time. + virtual unsigned long GetMTime(); + + // Description: + // Methods invoked by print to print information about the object + // including superclasses. Typically not called by the user (use + // Print() instead) but used in the hierarchical print process to + // combine the output of several classes. + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is a global flag that controls whether any debug, warning + // or error messages are displayed. + static void SetGlobalWarningDisplay(int val); + static void GlobalWarningDisplayOn(){vtkObject::SetGlobalWarningDisplay(1);}; + static void GlobalWarningDisplayOff() + {vtkObject::SetGlobalWarningDisplay(0);}; + static int GetGlobalWarningDisplay(); + + // Description: + // Allow people to add/remove/invoke observers (callbacks) to any VTK + // object. This is an implementation of the subject/observer design + // pattern. An observer is added by specifying an event to respond to + // and a vtkCommand to execute. It returns an unsigned long tag which + // can be used later to remove the event or retrieve the command. + // When events are invoked, the observers are called in the order they + // were added. If a priority value is specified, then the higher + // priority commands are called first. A command may set an abort + // flag to stop processing of the event. (See vtkCommand.h for more + // information.) + //BTX + unsigned long AddObserver(unsigned long event, vtkCommand *, + float priority=0.0); + unsigned long AddObserver(const char *event, vtkCommand *, + float priority=0.0); + vtkCommand *GetCommand(unsigned long tag); + void RemoveObserver(vtkCommand*); + void RemoveObservers(unsigned long event, vtkCommand *); + void RemoveObservers(const char *event, vtkCommand *); + int HasObserver(unsigned long event, vtkCommand *); + int HasObserver(const char *event, vtkCommand *); + //ETX + void RemoveObserver(unsigned long tag); + void RemoveObservers(unsigned long event); + void RemoveObservers(const char *event); + int HasObserver(unsigned long event); + int HasObserver(const char *event); + + // Description: + // Allow people to add/remove/invoke observers (callbacks) to any + // VTK object. This is an implementation of the subject/observer + // design pattern. An observer is added by specifying an event to + // respond to and a vtkCommand to execute. It returns an unsigned + // long tag which can be used later to remove the event or retrieve + // the command. When events are invoked, the observers are called + // in the order they were added. If a priority value is specified, + // then the higher priority commands are called first. A command may + // set an abort flag to stop processing of the event. (See + // vtkCommand.h for more information.) + + // This method invokes an event and return whether the event was + // aborted or not. If the event was aborted, the return value is 1, + // otherwise it is 0. + //BTX + int InvokeEvent(unsigned long event, void *callData); + int InvokeEvent(const char *event, void *callData); + //ETX + int InvokeEvent(unsigned long event) { return this->InvokeEvent(event, NULL); }; + int InvokeEvent(const char *event) { return this->InvokeEvent(event, NULL); }; + +protected: + vtkObject(); + virtual ~vtkObject(); + + // See vtkObjectBase.h. + virtual void RegisterInternal(vtkObjectBase*, int check); + virtual void UnRegisterInternal(vtkObjectBase*, int check); + + unsigned char Debug; // Enable debug messages + vtkTimeStamp MTime; // Keep track of modification time + vtkSubjectHelper *SubjectHelper; + +private: + vtkObject(const vtkObject&); // Not implemented. + void operator=(const vtkObject&); // Not implemented. +}; + +#endif + diff --git a/Common/vtkObjectBase.cxx b/Common/vtkObjectBase.cxx new file mode 100644 index 0000000..23667dd --- /dev/null +++ b/Common/vtkObjectBase.cxx @@ -0,0 +1,275 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObjectBase.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkObjectBase.h" +#include "vtkDebugLeaks.h" +#include "vtkGarbageCollector.h" + +#define vtkBaseDebugMacro(x) + +class vtkObjectBaseToGarbageCollectorFriendship +{ +public: + static int GiveReference(vtkObjectBase* obj) + { + return vtkGarbageCollector::GiveReference(obj); + } + static int TakeReference(vtkObjectBase* obj) + { + return vtkGarbageCollector::TakeReference(obj); + } +}; + +// avoid dll boundary problems +#ifdef _WIN32 +void* vtkObjectBase::operator new(size_t nSize) +{ + void* p=malloc(nSize); + return p; +} + +void vtkObjectBase::operator delete( void *p ) +{ + free(p); +} +#endif + +// ------------------------------------vtkObjectBase---------------------- +// This operator allows all subclasses of vtkObjectBase to be printed via <<. +// It in turn invokes the Print method, which in turn will invoke the +// PrintSelf method that all objects should define, if they have anything +// interesting to print out. +ostream& operator<<(ostream& os, vtkObjectBase& o) +{ + o.Print(os); + return os; +} + +// Create an object with Debug turned off and modified time initialized +// to zero. +vtkObjectBase::vtkObjectBase() +{ + this->ReferenceCount = 1; + // initial reference count = 1 and reference counting on. +} + +vtkObjectBase::~vtkObjectBase() +{ + // warn user if reference counting is on and the object is being referenced + // by another object + if ( this->ReferenceCount > 0) + { + vtkGenericWarningMacro(<< "Trying to delete object with non-zero reference count."); + } +} + +//---------------------------------------------------------------------------- +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetClassName +// Define possible mangled names. +const char* vtkObjectBase::GetClassNameA() const +{ + return this->GetClassNameInternal(); +} +const char* vtkObjectBase::GetClassNameW() const +{ + return this->GetClassNameInternal(); +} +#endif +const char* vtkObjectBase::GetClassName() const +{ + return this->GetClassNameInternal(); +} + +int vtkObjectBase::IsTypeOf(const char *name) +{ + if ( !strcmp("vtkObjectBase",name) ) + { + return 1; + } + return 0; +} + +int vtkObjectBase::IsA(const char *type) +{ + return this->vtkObjectBase::IsTypeOf(type); +} + +// Delete a vtk object. This method should always be used to delete an object +// when the new operator was used to create it. Using the C++ delete method +// will not work with reference counting. +void vtkObjectBase::Delete() +{ + this->UnRegister((vtkObjectBase *)NULL); +} + +void vtkObjectBase::FastDelete() +{ + // Remove the reference without doing a collection check even if + // this object normally participates in garbage collection. + this->UnRegisterInternal(0, 0); +} + +void vtkObjectBase::Print(ostream& os) +{ + vtkIndent indent; + + this->PrintHeader(os,0); + this->PrintSelf(os, indent.GetNextIndent()); + this->PrintTrailer(os,0); +} + +void vtkObjectBase::PrintHeader(ostream& os, vtkIndent indent) +{ + os << indent << this->GetClassName() << " (" << this << ")\n"; +} + +// Chaining method to print an object's instance variables, as well as +// its superclasses. +void vtkObjectBase::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "Reference Count: " << this->ReferenceCount << "\n"; +} + +void vtkObjectBase::PrintTrailer(ostream& os, vtkIndent indent) +{ + os << indent << "\n"; +} + +// Description: +// Sets the reference count (use with care) +void vtkObjectBase::SetReferenceCount(int ref) +{ + this->ReferenceCount = ref; + vtkBaseDebugMacro(<< "Reference Count set to " << this->ReferenceCount); +} + +//---------------------------------------------------------------------------- +void vtkObjectBase::Register(vtkObjectBase* o) +{ + // Do not participate in garbage collection by default. + this->RegisterInternal(o, 0); +} + +//---------------------------------------------------------------------------- +void vtkObjectBase::UnRegister(vtkObjectBase* o) +{ + // Do not participate in garbage collection by default. + this->UnRegisterInternal(o, 0); +} + +void vtkObjectBase::CollectRevisions(ostream& os) +{ + os << "vtkObjectBase $Revision: 1.14.6.1 $\n"; +} + +void vtkObjectBase::PrintRevisions(ostream& os) +{ + ostrstream revisions; + this->CollectRevisions(revisions); + revisions << ends; + const char* c = revisions.str(); + while(*c) + { + const char* beginClass = 0; + const char* endClass = 0; + const char* beginRevision = 0; + const char* endRevision = 0; + for(;*c && *c != '\n'; ++c) + { + if(!beginClass && *c != ' ') + { + beginClass = c; + } + else if(beginClass && !endClass && *c == ' ') + { + endClass = c; + } + else if(endClass && !beginRevision && (*c >= '0' && *c <= '9')) + { + beginRevision = c; + } + else if(beginRevision && !endRevision && *c == ' ') + { + endRevision = c; + } + } + if (beginRevision && !endRevision) + { + endRevision = c - 1; + } + if(beginClass && endClass && beginRevision && endRevision) + { + os.write(beginClass, endClass-beginClass); + os << " "; + os.write(beginRevision, endRevision-beginRevision); + os << "\n"; + } + if(*c == '\n') + { + ++c; + } + } + revisions.rdbuf()->freeze(0); +} + +//---------------------------------------------------------------------------- +void vtkObjectBase::RegisterInternal(vtkObjectBase*, int check) +{ + // If a reference is available from the garbage collector, use it. + // Otherwise create a new reference by incrementing the reference + // count. + if(!(check && + vtkObjectBaseToGarbageCollectorFriendship::TakeReference(this))) + { + ++this->ReferenceCount; + } +} + +//---------------------------------------------------------------------------- +void vtkObjectBase::UnRegisterInternal(vtkObjectBase*, int check) +{ + // If the garbage collector accepts a reference, do not decrement + // the count. + if(check && this->ReferenceCount > 1 && + vtkObjectBaseToGarbageCollectorFriendship::GiveReference(this)) + { + return; + } + + // Decrement the reference count. + if(--this->ReferenceCount <= 0) + { + // Count has gone to zero. Delete the object. +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass(this->GetClassName()); +#endif + delete this; + } + else if(check) + { + // The garbage collector did not accept the reference, but the + // object still exists and is participating in garbage collection. + // This means either that delayed garbage collection is disabled + // or the collector has decided it is time to do a check. + vtkGarbageCollector::Collect(this); + } +} + +//---------------------------------------------------------------------------- +void vtkObjectBase::ReportReferences(vtkGarbageCollector*) +{ + // vtkObjectBase has no references to report. +} diff --git a/Common/vtkObjectBase.h b/Common/vtkObjectBase.h new file mode 100644 index 0000000..311cdc7 --- /dev/null +++ b/Common/vtkObjectBase.h @@ -0,0 +1,185 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObjectBase.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkObjectBase - abstract base class for most VTK objects +// .SECTION Description +// vtkObjectBase is the base class for all reference counted classes +// in the VTK. These classes include vtkCommand classes, vtkContainer +// classes, and vtkObject classes. +// +// vtkObjectBase performs reference counting: objects that are +// reference counted exist as long as another object uses them. Once +// the last reference to a reference counted object is removed, the +// object will spontaneously destruct. +// +// Constructor and destructor of the subclasses of vtkObjectBase +// should be protected, so that only New() and UnRegister() actually +// call them. Debug leaks can be used to see if there are any objects +// left with nonzero reference count. +// +// .SECTION Caveats +// Note: Objects of subclasses of vtkObjectBase should always be +// created with the New() method and deleted with the Delete() +// method. They cannot be allocated off the stack (i.e., automatic +// objects) because the constructor is a protected method. +// +// .SECTION See also +// vtkObject vtkCommand vtkContainer + +#ifndef __vtkObjectBase_h +#define __vtkObjectBase_h + +#include "vtkIndent.h" +#include "vtkSystemIncludes.h" + +class vtkGarbageCollector; +class vtkGarbageCollectorToObjectBaseFriendship; + +class VTK_COMMON_EXPORT vtkObjectBase +{ + virtual const char* GetClassNameInternal() const { return "vtkObjectBase"; } +public: + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE + // Avoid windows name mangling. +# define GetClassNameA GetClassName +# define GetClassNameW GetClassName +#endif + + // Description: + // Return the class name as a string. This method is defined + // in all subclasses of vtkObjectBase with the vtkTypeRevisionMacro found + // in vtkSetGet.h. + const char* GetClassName() const; + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetClassNameW +# undef GetClassNameA + //BTX + // Define possible mangled names. + const char* GetClassNameA() const; + const char* GetClassNameW() const; + //ETX +#endif + + // Description: + // Return 1 if this class type is the same type of (or a subclass of) + // the named class. Returns 0 otherwise. This method works in + // combination with vtkTypeRevisionMacro found in vtkSetGet.h. + static int IsTypeOf(const char *name); + + // Description: + // Return 1 if this class is the same type of (or a subclass of) + // the named class. Returns 0 otherwise. This method works in + // combination with vtkTypeRevisionMacro found in vtkSetGet.h. + virtual int IsA(const char *name); + + // Description: + // Delete a VTK object. This method should always be used to delete + // an object when the New() method was used to create it. Using the + // C++ delete method will not work with reference counting. + virtual void Delete(); + + // Description: + // Delete a reference to this object. This version will not invoke + // garbage collection and can potentially leak the object if it is + // part of a reference loop. Use this method only when it is known + // that the object has another reference and would not be collected + // if a full garbage collection check were done. + virtual void FastDelete(); + + // Description: + // Create an object with Debug turned off, modified time initialized + // to zero, and reference counting on. + static vtkObjectBase *New() + {return new vtkObjectBase;} + +#ifdef _WIN32 + // avoid dll boundary problems + void* operator new( size_t tSize ); + void operator delete( void* p ); +#endif + + // Description: + // Print an object to an ostream. This is the method to call + // when you wish to see print the internal state of an object. + void Print(ostream& os); + + // Description: + // Methods invoked by print to print information about the object + // including superclasses. Typically not called by the user (use + // Print() instead) but used in the hierarchical print process to + // combine the output of several classes. + virtual void PrintSelf(ostream& os, vtkIndent indent); + virtual void PrintHeader(ostream& os, vtkIndent indent); + virtual void PrintTrailer(ostream& os, vtkIndent indent); + + // Description: + // Increase the reference count (mark as used by another object). + virtual void Register(vtkObjectBase* o); + + // Description: + // Decrease the reference count (release by another object). This + // has the same effect as invoking Delete() (i.e., it reduces the + // reference count by 1). + virtual void UnRegister(vtkObjectBase* o); + + // Description: + // Return the current reference count of this object. + int GetReferenceCount() + {return this->ReferenceCount;} + + // Description: + // Sets the reference count. (This is very dangerous, use with care.) + void SetReferenceCount(int); + + // Description: + // Prints a list of the class .cxx file CVS revisions for all + // classes in the object's inheritance chain. The format of the + // list is "vtkObjectBase 1.4\n" with one class per line. The list + // always starts with the least-derived class (vtkObjectBase), and + // ends with the most-derived class. This is useful for programs + // wishing to do serialization of VTK objects. + void PrintRevisions(ostream& os); + +protected: + vtkObjectBase(); + virtual ~vtkObjectBase(); + + virtual void CollectRevisions(ostream& os); + + int ReferenceCount; // Number of uses of this object by other objects + + // Internal Register/UnRegister implementation that accounts for + // possible garbage collection participation. The second argument + // indicates whether to participate in garbage collection. + virtual void RegisterInternal(vtkObjectBase*, int check); + virtual void UnRegisterInternal(vtkObjectBase*, int check); + + // See vtkGarbageCollector.h: + virtual void ReportReferences(vtkGarbageCollector*); +private: + //BTX + friend VTK_COMMON_EXPORT ostream& operator<<(ostream& os, vtkObjectBase& o); + friend class vtkGarbageCollectorToObjectBaseFriendship; + //ETX +protected: +//BTX + vtkObjectBase(const vtkObjectBase&) {} + void operator=(const vtkObjectBase&) {} +//ETX +}; + +#endif + diff --git a/Common/vtkObjectFactory.cxx b/Common/vtkObjectFactory.cxx new file mode 100644 index 0000000..1dbc184 --- /dev/null +++ b/Common/vtkObjectFactory.cxx @@ -0,0 +1,726 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObjectFactory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkObjectFactory.h" + +#include "vtkDebugLeaks.h" +#include "vtkDirectory.h" +#include "vtkDynamicLoader.h" +#include "vtkObjectFactoryCollection.h" +#include "vtkOverrideInformation.h" +#include "vtkOverrideInformationCollection.h" +#include "vtkVersion.h" + +#include + +vtkCxxRevisionMacro(vtkObjectFactory, "$Revision: 1.43 $"); + +vtkObjectFactoryCollection* vtkObjectFactory::RegisteredFactories = 0; + + +class vtkCleanUpObjectFactory +{ +public: + inline void Use() + { + } + ~vtkCleanUpObjectFactory() + { + vtkObjectFactory::UnRegisterAllFactories(); + } +}; + +static vtkCleanUpObjectFactory vtkCleanUpObjectFactoryGlobal; + +// Create an instance of a named vtk object using the loaded +// factories + +vtkObject* vtkObjectFactory::CreateInstance(const char* vtkclassname) +{ + if(!vtkObjectFactory::RegisteredFactories) + { + vtkObjectFactory::Init(); + } + + vtkObjectFactory* factory; + vtkCollectionSimpleIterator osit; + for(vtkObjectFactory::RegisteredFactories->InitTraversal(osit); + (factory = vtkObjectFactory::RegisteredFactories-> + GetNextObjectFactory(osit));) + { + vtkObject* newobject = factory->CreateObject(vtkclassname); + if(newobject) + { + return newobject; + } + } + // if the factory does not create the object, then + // the object will be created with the name passed in, + // so register the construction +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass(vtkclassname); +#endif + + return 0; +} + + + + +// A one time initialization method. +void vtkObjectFactory::Init() +{ + vtkCleanUpObjectFactoryGlobal.Use(); + // Don't do anything if we are already initialized + if(vtkObjectFactory::RegisteredFactories) + { + return; + } + + vtkObjectFactory::RegisteredFactories = vtkObjectFactoryCollection::New(); + vtkObjectFactory::RegisterDefaults(); + vtkObjectFactory::LoadDynamicFactories(); +} + + +// Register any factories that are always present in VTK like +// the OpenGL factory, currently this is not done. + +void vtkObjectFactory::RegisterDefaults() +{ +} + + +// Load all libraries in VTK_AUTOLOAD_PATH + +void vtkObjectFactory::LoadDynamicFactories() +{ + // follow PATH convensions +#ifdef _WIN32 + char PathSeparator = ';'; +#else + char PathSeparator = ':'; +#endif + + char* LoadPath = 0; + +#ifndef _WIN32_WCE + LoadPath = getenv("VTK_AUTOLOAD_PATH"); +#endif + if(LoadPath == 0 || strlen(LoadPath) == 0) + { + return; + } + char* CurrentPath = new char[strlen(LoadPath)+1]; + char* SeparatorPosition = LoadPath; // initialize to env variable + while(SeparatorPosition) + { + size_t PathLength =0; + // find PathSeparator in LoadPath + SeparatorPosition = strchr(LoadPath, PathSeparator); + // if not found then use the whole string + if(SeparatorPosition == 0) + { + PathLength = strlen(LoadPath); + } + else + { + PathLength = SeparatorPosition - LoadPath; + } + // copy the path out of LoadPath into CurrentPath + strncpy(CurrentPath, LoadPath, PathLength); + // add a null terminator + CurrentPath[PathLength] = 0; + // Get ready for the next path + LoadPath = SeparatorPosition+1; + // Load the libraries in the current path + vtkObjectFactory::LoadLibrariesInPath(CurrentPath); + } + // clean up memory + delete [] CurrentPath; +} + +// A file scope helper function to concat path and file into +// a full path +static char* CreateFullPath(const char* path, const char* file) +{ + int lenpath = static_cast(strlen(path)); + char* ret = new char[lenpath + strlen(file)+2]; +#ifdef _WIN32 + const char sep = '\\'; +#else + const char sep = '/'; +#endif + // make sure the end of path is a separator + strcpy(ret, path); + if(ret[lenpath-1] != sep) + { + ret[lenpath] = sep; + ret[lenpath+1] = 0; + } + strcat(ret, file); + return ret; +} + +// A file scope typedef to make the cast code to the load +// function cleaner to read. +typedef vtkObjectFactory* (* VTK_LOAD_FUNCTION)(); +typedef const char* (* VTK_VERSION_FUNCTION)(); +typedef const char* (* VTK_COMPILER_FUNCTION)(); + + +// A file scoped function to determine if a file has +// the shared library extension in its name, this converts name to lower +// case before the compare, vtkDynamicLoader always uses +// lower case for LibExtension values. + +inline int vtkNameIsSharedLibrary(const char* name) +{ + int len = static_cast(strlen(name)); + char* copy = new char[len+1]; + + for(int i = 0; i < len; i++) + { + copy[i] = tolower(name[i]); + } + copy[len] = 0; + char* ret = strstr(copy, vtkDynamicLoader::LibExtension()); + delete [] copy; + return (ret != NULL); +} + +void vtkObjectFactory::LoadLibrariesInPath(const char* path) +{ + vtkDirectory* dir = vtkDirectory::New(); + if(!dir->Open(path)) + { + dir->Delete(); + return; + } + + // Attempt to load each file in the directory as a shared library + for(int i = 0; i < dir->GetNumberOfFiles(); i++) + { + const char* file = dir->GetFile(i); + // try to make sure the file has at least the extension + // for a shared library in it. + if(vtkNameIsSharedLibrary(file)) + { + char* fullpath = CreateFullPath(path, file); + vtkLibHandle lib = vtkDynamicLoader::OpenLibrary(fullpath); + if(lib) + { + // Look for the symbol vtkLoad, vtkGetFactoryCompilerUsed, + // and vtkGetFactoryVersion in the library + VTK_LOAD_FUNCTION loadfunction + = (VTK_LOAD_FUNCTION) + vtkDynamicLoader::GetSymbolAddress(lib, + "vtkLoad"); + VTK_COMPILER_FUNCTION compilerFunction + = (VTK_COMPILER_FUNCTION) + vtkDynamicLoader::GetSymbolAddress(lib, + "vtkGetFactoryCompilerUsed"); + VTK_VERSION_FUNCTION versionFunction + = (VTK_VERSION_FUNCTION) + vtkDynamicLoader::GetSymbolAddress(lib, + "vtkGetFactoryVersion"); + // if the symbol is found call it to create the factory + // from the library + if(loadfunction && compilerFunction && versionFunction) + { + const char* compiler = (*compilerFunction)(); + const char* version = (*versionFunction)(); + if(strcmp(compiler, VTK_CXX_COMPILER) || + strcmp(version, vtkVersion::GetVTKSourceVersion())) + { + vtkGenericWarningMacro( + << "Incompatible factory rejected:" + << "\nRunning VTK compiled with: " << VTK_CXX_COMPILER + << "\nFactory compiled with: " << compiler + << "\nRunning VTK version: " << vtkVersion::GetVTKSourceVersion() + << "\nFactory version: " << version + << "\nPath to rejected factory: " << fullpath << "\n"); + } + else + { + vtkObjectFactory* newfactory = (*loadfunction)(); + newfactory->LibraryVTKVersion = + strcpy(new char[strlen(version)+1], version); + newfactory->LibraryCompilerUsed = + strcpy(new char[strlen(compiler)+1], compiler); + // initialize class members if load worked + newfactory->LibraryHandle = (void*)lib; + newfactory->LibraryPath = + strcpy(new char[strlen(fullpath)+1], fullpath); + vtkObjectFactory::RegisterFactory(newfactory); + newfactory->Delete(); + } + } + // if only the loadfunction is found, then warn + else if (loadfunction) + { + vtkGenericWarningMacro("Old Style Factory not loaded. Shared object has vtkLoad, but is missing vtkGetFactoryCompilerUsed and vtkGetFactoryVersion. Recompile factory: " << fullpath << ", and use VTK_FACTORY_INTERFACE_IMPLEMENT macro."); + } + } + delete [] fullpath; + } + } + dir->Delete(); +} + + +// Recheck the VTK_AUTOLOAD_PATH for new libraries + +void vtkObjectFactory::ReHash() +{ + vtkObjectFactory::UnRegisterAllFactories(); + vtkObjectFactory::Init(); +} + +// initialize class members +vtkObjectFactory::vtkObjectFactory() +{ + this->LibraryHandle = 0; + this->LibraryPath = 0; + this->OverrideArray = 0; + this->OverrideClassNames = 0; + this->SizeOverrideArray = 0; + this->OverrideArrayLength = 0; + this->LibraryVTKVersion = 0; + this->LibraryCompilerUsed = 0; +} + + +// Unload the library and free the path string +vtkObjectFactory::~vtkObjectFactory() +{ + delete [] this->LibraryVTKVersion; + delete [] this->LibraryCompilerUsed; + delete [] this->LibraryPath; + this->LibraryPath = 0; + + for(int i =0; i < this->OverrideArrayLength; i++) + { + delete [] this->OverrideClassNames[i]; + delete [] this->OverrideArray[i].Description; + delete [] this->OverrideArray[i].OverrideWithName; + } + delete [] this->OverrideArray; + delete [] this->OverrideClassNames; + this->OverrideArray = NULL; + this->OverrideClassNames = NULL; +} + +// Add a factory to the registered list +void vtkObjectFactory::RegisterFactory(vtkObjectFactory* factory) +{ + if(factory->LibraryHandle == 0) + { + const char* nonDynamicName = "Non-Dynamicly loaded factory"; + factory->LibraryPath = strcpy(new char[strlen(nonDynamicName)+1], + nonDynamicName); + factory->LibraryCompilerUsed = + strcpy(new char[strlen(VTK_CXX_COMPILER)+1], VTK_CXX_COMPILER); + factory->LibraryVTKVersion = + strcpy(new char[strlen(vtkVersion::GetVTKSourceVersion())+1], + vtkVersion::GetVTKSourceVersion()); + } + else + { + if(strcmp(factory->LibraryCompilerUsed, + VTK_CXX_COMPILER) != 0) + { + vtkGenericWarningMacro(<< "Possible incompatible factory load:" + << "\nRunning vtk compiled with :\n" << VTK_CXX_COMPILER + << "\nLoaded Factory compiled with:\n" << factory->LibraryCompilerUsed + << "\nRejecting factory:\n" << factory->LibraryPath << "\n"); + return; + } + if(strcmp(factory->LibraryVTKVersion, + vtkVersion::GetVTKSourceVersion()) != 0) + { + vtkGenericWarningMacro(<< "Possible incompatible factory load:" + << "\nRunning vtk version :\n" << vtkVersion::GetVTKSourceVersion() + << "\nLoaded Factory version:\n" << factory->LibraryVTKVersion + << "\nRejecting factory:\n" << factory->LibraryPath << "\n"); + return; + } + if(strcmp(factory->GetVTKSourceVersion(), + vtkVersion::GetVTKSourceVersion()) != 0) + { + vtkGenericWarningMacro(<< "Possible incompatible factory load:" + << "\nRunning vtk version :\n" << vtkVersion::GetVTKSourceVersion() + << "\nLoaded Factory version:\n" << factory->GetVTKSourceVersion() + << "\nRejecting factory:\n" << factory->LibraryPath << "\n"); + return; + } + } + + vtkObjectFactory::Init(); + vtkObjectFactory::RegisteredFactories->AddItem(factory); +} + +// print ivars to stream +void vtkObjectFactory::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent + << "Factory DLL path: " << this->LibraryPath << "\n"; + os << indent << "Library version: " << this->LibraryVTKVersion << "\n"; + os << indent << "Compiler used: " << this->LibraryCompilerUsed << "\n"; + os << indent << "Factory description: " << this->GetDescription() << endl; + int num = this->GetNumberOfOverrides(); + os << indent << "Factory overides " << num << " classes:" << endl; + indent = indent.GetNextIndent(); + for(int i =0; i < num; i++) + { + os << indent << "Class : " << this->GetClassOverrideName(i) << endl; + os << indent << "Overriden with: " << this->GetClassOverrideWithName(i) + << endl; + os << indent << "Enable flag: " << this->GetEnableFlag(i) << endl; + os << endl; + } +} + +// Remove a factory from the list of registered factories. +void vtkObjectFactory::UnRegisterFactory(vtkObjectFactory* factory) +{ + void* lib = factory->LibraryHandle; + vtkObjectFactory::RegisteredFactories->RemoveItem(factory); + if(lib) + { + vtkDynamicLoader::CloseLibrary((vtkLibHandle)lib); + } +} + +// unregister all factories and delete the RegisteredFactories list +void vtkObjectFactory::UnRegisterAllFactories() +{ + // do not do anything if this is null + if( ! vtkObjectFactory::RegisteredFactories ) + { + return; + } + int num = vtkObjectFactory::RegisteredFactories->GetNumberOfItems(); + // collect up all the library handles so they can be closed + // AFTER the factory has been deleted. + void** libs = new void*[num+1]; + vtkObjectFactory* factory; + vtkCollectionSimpleIterator osit; + vtkObjectFactory::RegisteredFactories->InitTraversal(osit); + int index = 0; + while((factory = + vtkObjectFactory::RegisteredFactories->GetNextObjectFactory(osit))) + { + libs[index++] = factory->LibraryHandle; + } + // delete the factory list and its factories + vtkObjectFactory::RegisteredFactories->Delete(); + vtkObjectFactory::RegisteredFactories = 0; + // now close the libraries + for(int i = 0; i < num; i++) + { + void* lib = libs[i]; + if(lib) + { + vtkDynamicLoader::CloseLibrary(reinterpret_cast(lib)); + } + } + delete [] libs; +} + + +// Register an override function with a factory. +void vtkObjectFactory::RegisterOverride(const char* classOverride, + const char* subclass, + const char* description, + int enableFlag, + CreateFunction createFunction) +{ + this->GrowOverrideArray(); + int nextIndex = this->OverrideArrayLength; + this->OverrideArrayLength++; + char* override = strcpy(new char[strlen(classOverride)+1], classOverride); + char* desc = strcpy(new char[strlen(description)+1], description); + char* ocn = strcpy(new char[strlen(subclass)+1], + subclass); + this->OverrideClassNames[nextIndex] = override; + this->OverrideArray[nextIndex].Description = desc; + this->OverrideArray[nextIndex].OverrideWithName = ocn; + this->OverrideArray[nextIndex].EnabledFlag = enableFlag; + this->OverrideArray[nextIndex].CreateCallback = createFunction; +} + +// Create an instance of an object +vtkObject* vtkObjectFactory::CreateObject(const char* vtkclassname) +{ + for(int i=0; i < this->OverrideArrayLength; i++) + { + if(this->OverrideArray[i].EnabledFlag && + strcmp(this->OverrideClassNames[i], vtkclassname) == 0) + { + return (*this->OverrideArray[i].CreateCallback)(); + } + } + return 0; +} + +// grow the array if the length is greater than the size. +void vtkObjectFactory::GrowOverrideArray() +{ + if(this->OverrideArrayLength+1 > this->SizeOverrideArray) + { + int newLength = this->OverrideArrayLength + 50; + OverrideInformation* newArray = new OverrideInformation[newLength]; + char** newNameArray = new char*[newLength]; + for(int i =0; i < this->OverrideArrayLength; i++) + { + newNameArray[i] = this->OverrideClassNames[i]; + newArray[i] = this->OverrideArray[i]; + } + delete [] this->OverrideClassNames; + this->OverrideClassNames = newNameArray; + delete [] this->OverrideArray; + this->OverrideArray = newArray; + } +} + +int vtkObjectFactory::GetNumberOfOverrides() +{ + return this->OverrideArrayLength; +} + +const char* vtkObjectFactory::GetClassOverrideName(int index) +{ + return this->OverrideClassNames[index]; +} + +const char* vtkObjectFactory::GetClassOverrideWithName(int index) +{ + return this->OverrideArray[index].OverrideWithName; +} + +int vtkObjectFactory::GetEnableFlag(int index) +{ + return this->OverrideArray[index].EnabledFlag; +} + +const char* vtkObjectFactory::GetOverrideDescription(int index) +{ + return this->OverrideArray[index].Description; +} + +// Set the enable flag for a class / subclassName pair +void vtkObjectFactory::SetEnableFlag(int flag, + const char* className, + const char* subclassName) +{ + for(int i =0; i < this->OverrideArrayLength; i++) + { + if(strcmp(this->OverrideClassNames[i], className) == 0) + { + // if subclassName is null, then set on className match + if(!subclassName) + { + this->OverrideArray[i].EnabledFlag = flag; + } + else + { + if(strcmp(this->OverrideArray[i].OverrideWithName, subclassName) == 0) + { + this->OverrideArray[i].EnabledFlag = flag; + } + } + } + } +} + +// Get the enable flag for a className/subclassName pair +int vtkObjectFactory::GetEnableFlag(const char* className, + const char* subclassName) +{ + for(int i =0; i < this->OverrideArrayLength; i++) + { + if(strcmp(this->OverrideClassNames[i], className) == 0) + { + if(strcmp(this->OverrideArray[i].OverrideWithName, subclassName) == 0) + { + return this->OverrideArray[i].EnabledFlag; + } + } + } + return 0; +} + +// Set the EnabledFlag to 0 for a given classname +void vtkObjectFactory::Disable(const char* className) +{ + for(int i =0; i < this->OverrideArrayLength; i++) + { + if(strcmp(this->OverrideClassNames[i], className) == 0) + { + this->OverrideArray[i].EnabledFlag = 0; + } + } +} + +// 1,0 is the class overriden by className +int vtkObjectFactory::HasOverride(const char* className) +{ + for(int i =0; i < this->OverrideArrayLength; i++) + { + if(strcmp(this->OverrideClassNames[i], className) == 0) + { + return 1; + } + } + return 0; +} + +// 1,0 is the class overriden by className/subclassName pair +int vtkObjectFactory::HasOverride(const char* className, + const char* subclassName) +{ + for(int i =0; i < this->OverrideArrayLength; i++) + { + if(strcmp(this->OverrideClassNames[i], className) == 0) + { + if(strcmp(this->OverrideArray[i].OverrideWithName, subclassName) == 0) + { + return 1; + } + } + } + return 0; +} + + +vtkObjectFactoryCollection* vtkObjectFactory::GetRegisteredFactories() +{ + if(!vtkObjectFactory::RegisteredFactories) + { + vtkObjectFactory::Init(); + } + + return vtkObjectFactory::RegisteredFactories; +} + + +// 1,0 is the className overriden by any registered factories +int vtkObjectFactory::HasOverrideAny(const char* className) +{ + vtkObjectFactory* factory; + vtkCollectionSimpleIterator osit; + for(vtkObjectFactory::RegisteredFactories->InitTraversal(osit); + (factory = + vtkObjectFactory::RegisteredFactories->GetNextObjectFactory(osit));) + { + if(factory->HasOverride(className)) + { + return 1; + } + } + return 0; +} + +// collect up information about current registered factories +void vtkObjectFactory::GetOverrideInformation(const char* name, + vtkOverrideInformationCollection* + ret) +{ + // create the collection to return + vtkOverrideInformation* overInfo; // info object pointer + vtkObjectFactory* factory; // factory pointer for traversal + vtkCollectionSimpleIterator osit; + vtkObjectFactory::RegisteredFactories->InitTraversal(osit); + for(;(factory = + vtkObjectFactory::RegisteredFactories->GetNextObjectFactory(osit));) + { + for(int i =0; i < factory->OverrideArrayLength; i++) + { + if( strcmp(name, factory->OverrideClassNames[i]) == 0) + { + // Create a new override info class + overInfo = vtkOverrideInformation::New(); + // Set the class name + overInfo->SetClassOverrideName(factory->OverrideClassNames[i]); + // Set the override class name + overInfo->SetClassOverrideWithName( + factory->OverrideArray[i].OverrideWithName); + // Set the Description for the override + overInfo->SetDescription(factory->OverrideArray[i].Description); + // Set the factory for the override + overInfo->SetObjectFactory(factory); + // add the item to the collection + ret->AddItem(overInfo); + overInfo->Delete(); + } + } + } +} + +// set enable flag for all registered factories for the given className +void vtkObjectFactory::SetAllEnableFlags(int flag, + const char* className) +{ + vtkObjectFactory* factory; + vtkCollectionSimpleIterator osit; + for(vtkObjectFactory::RegisteredFactories->InitTraversal(osit); + (factory = + vtkObjectFactory::RegisteredFactories->GetNextObjectFactory(osit));) + { + factory->SetEnableFlag(flag, className, 0); + } + +} + +// set enable flag for the first factory that that +// has an override for className/subclassName pair +void vtkObjectFactory::SetAllEnableFlags(int flag, + const char* className, + const char* subclassName) +{ + vtkObjectFactory* factory; + vtkCollectionSimpleIterator osit; + for(vtkObjectFactory::RegisteredFactories->InitTraversal(osit); + (factory = + vtkObjectFactory::RegisteredFactories->GetNextObjectFactory(osit));) + { + factory->SetEnableFlag(flag, className, subclassName); + } +} + + + + + +void vtkObjectFactory::CreateAllInstance(const char* vtkclassname, + vtkCollection* retList) +{ + vtkObjectFactory* f; + vtkObjectFactoryCollection* collection + = vtkObjectFactory::GetRegisteredFactories(); + vtkCollectionSimpleIterator osit; + for(collection->InitTraversal(osit); + (f = collection->GetNextObjectFactory(osit)); ) + { + vtkObject* o = f->CreateObject(vtkclassname); + if(o) + { + retList->AddItem(o); + o->Delete(); + } + } +} + diff --git a/Common/vtkObjectFactory.h b/Common/vtkObjectFactory.h new file mode 100644 index 0000000..c3d7b05 --- /dev/null +++ b/Common/vtkObjectFactory.h @@ -0,0 +1,287 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObjectFactory.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkObjectFactory - abstract base class for vtkObjectFactories +// .SECTION Description +// vtkObjectFactory is used to create vtk objects. The base class +// vtkObjectFactory contains a static method CreateInstance which is used +// to create vtk objects from the list of registered vtkObjectFactory +// sub-classes. The first time CreateInstance is called, all dll's or shared +// libraries in the environment variable VTK_AUTOLOAD_PATH are loaded into +// the current process. The C functions vtkLoad, vtkGetFactoryCompilerUsed, +// and vtkGetFactoryVersion are called on each dll. To implement these +// functions in a shared library or dll, use the macro: +// VTK_FACTORY_INTERFACE_IMPLEMENT. +// VTK_AUTOLOAD_PATH is an environment variable +// containing a colon separated (semi-colon on win32) list of paths. +// +// The vtkObjectFactory can be use to override the creation of any object +// in VTK with a sub-class of that object. The factories can be registered +// either at run time with the VTK_AUTOLOAD_PATH, or at compile time +// with the vtkObjectFactory::RegisterFactory method. +// + + + +#ifndef __vtkObjectFactory_h +#define __vtkObjectFactory_h + + + + +#include "vtkObject.h" + +class vtkObjectFactoryCollection; +class vtkOverrideInformationCollection; +class vtkCollection; + +class VTK_COMMON_EXPORT vtkObjectFactory : public vtkObject +{ +public: + // Class Methods used to interface with the registered factories + + // Description: + // Create and return an instance of the named vtk object. + // Each loaded vtkObjectFactory will be asked in the order + // the factory was in the VTK_AUTOLOAD_PATH. After the + // first factory returns the object no other factories are asked. + static vtkObject* CreateInstance(const char* vtkclassname); + + // Description: + // Create all possible instances of the named vtk object. + // Each registered vtkObjectFactory will be asked, and the + // result will be stored in the user allocated vtkCollection + // passed in to the function. + static void CreateAllInstance(const char* vtkclassname, + vtkCollection* retList); + // Description: + // Re-check the VTK_AUTOLOAD_PATH for new factory libraries. + // This calls UnRegisterAll before re-loading + static void ReHash(); + // Description: + // Register a factory so it can be used to create vtk objects + static void RegisterFactory(vtkObjectFactory* ); + // Description: + // Remove a factory from the list of registered factories + static void UnRegisterFactory(vtkObjectFactory*); + // Description: + // Unregister all factories + static void UnRegisterAllFactories(); + + // Description: + // Return the list of all registered factories. This is NOT a copy, + // do not remove items from this list! + static vtkObjectFactoryCollection* GetRegisteredFactories(); + + // Description: + // return 1 if one of the registered factories + // overrides the given class name + static int HasOverrideAny(const char* className); + + // Description: + // Fill the given collection with all the overrides for + // the class with the given name. + static void GetOverrideInformation(const char* name, + vtkOverrideInformationCollection*); + + // Description: + // Set the enable flag for a given named class for all registered + // factories. + static void SetAllEnableFlags(int flag, + const char* className); + // Description: + // Set the enable flag for a given named class subclass pair + // for all registered factories. + static void SetAllEnableFlags(int flag, + const char* className, + const char* subclassName); + + // Instance methods to be used on individual instances of vtkObjectFactory + + // Methods from vtkObject + vtkTypeRevisionMacro(vtkObjectFactory,vtkObject); + // Description: + // Print ObjectFactory to stream. + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // All sub-classes of vtkObjectFactory should must return the version of + // VTK they were built with. This should be implemented with the macro + // VTK_SOURCE_VERSION and NOT a call to vtkVersion::GetVTKSourceVersion. + // As the version needs to be compiled into the file as a string constant. + // This is critical to determine possible incompatible dynamic factory loads. + virtual const char* GetVTKSourceVersion() = 0; + + // Description: + // Return a descriptive string describing the factory. + virtual const char* GetDescription() = 0; + + // Description: + // Return number of overrides this factory can create. + virtual int GetNumberOfOverrides(); + + // Description: + // Return the name of a class override at the given index. + virtual const char* GetClassOverrideName(int index); + + // Description: + // Return the name of the class that will override the class + // at the given index + virtual const char* GetClassOverrideWithName(int index); + + // Description: + // Return the enable flag for the class at the given index. + virtual int GetEnableFlag(int index); + + // Description: + // Return the description for a the class override at the given + // index. + virtual const char* GetOverrideDescription(int index); + + // Description: + // Set and Get the Enable flag for the specific override of className. + // if subclassName is null, then it is ignored. + virtual void SetEnableFlag(int flag, + const char* className, + const char* subclassName); + virtual int GetEnableFlag(const char* className, + const char* subclassName); + + // Description: + // Return 1 if this factory overrides the given class name, 0 otherwise. + virtual int HasOverride(const char* className); + // Description: + // Return 1 if this factory overrides the given class name, 0 otherwise. + virtual int HasOverride(const char* className, const char* subclassName); + + // Description: + // Set all enable flags for the given class to 0. This will + // mean that the factory will stop producing class with the given + // name. + virtual void Disable(const char* className); + + // Description: + // This returns the path to a dynamically loaded factory. + vtkGetStringMacro(LibraryPath); + + //BTX + typedef vtkObject* (*CreateFunction)(); + //ETX +protected: + //BTX + + // Description: + // Register object creation information with the factory. + void RegisterOverride(const char* classOverride, + const char* overrideClassName, + const char* description, + int enableFlag, + CreateFunction createFunction); + + //ETX + + + // Description: + // This method is provided by sub-classes of vtkObjectFactory. + // It should create the named vtk object or return 0 if that object + // is not supported by the factory implementation. + virtual vtkObject* CreateObject(const char* vtkclassname ); + + vtkObjectFactory(); + ~vtkObjectFactory(); + //BTX + struct OverrideInformation + { + char* Description; + char* OverrideWithName; + int EnabledFlag; + CreateFunction CreateCallback; + }; + //ETX + OverrideInformation* OverrideArray; + char** OverrideClassNames; + int SizeOverrideArray; + int OverrideArrayLength; + +private: + void GrowOverrideArray(); + + // Description: + // Initialize the static members of vtkObjectFactory. RegisterDefaults + // is called here. + static void Init(); + // Description: + // Register default factories which are not loaded at run time. + static void RegisterDefaults(); + // Description: + // Load dynamic factories from the VTK_AUTOLOAD_PATH + static void LoadDynamicFactories(); + // Description: + // Load all dynamic libraries in the given path + static void LoadLibrariesInPath( const char*); + + // list of registered factories + static vtkObjectFactoryCollection* RegisteredFactories; + + // member variables for a factory set by the base class + // at load or register time + void* LibraryHandle; + char* LibraryVTKVersion; + char* LibraryCompilerUsed; + char* LibraryPath; +private: + vtkObjectFactory(const vtkObjectFactory&); // Not implemented. + void operator=(const vtkObjectFactory&); // Not implemented. +}; + +// Macro to create an object creation function. +// The name of the function will by vtkObjectFactoryCreateclassname +// where classname is the name of the class being created +#define VTK_CREATE_CREATE_FUNCTION(classname) \ +static vtkObject* vtkObjectFactoryCreate##classname() \ +{ return classname::New(); } + +#endif + + +#ifdef _WIN32 +#define VTK_FACTORY_INTERFACE_EXPORT __declspec( dllexport ) +#else +#define VTK_FACTORY_INTERFACE_EXPORT +#endif + +// Macro to create the interface "C" functions used in +// a dll or shared library that contains a VTK object factory. +// Put this function in the .cxx file of your object factory, +// and pass in the name of the factory sub-class that you want +// the dll to create. +#define VTK_FACTORY_INTERFACE_IMPLEMENT(factoryName) \ +extern "C" \ +VTK_FACTORY_INTERFACE_EXPORT \ +const char* vtkGetFactoryCompilerUsed() \ +{ \ + return VTK_CXX_COMPILER; \ +} \ +extern "C" \ +VTK_FACTORY_INTERFACE_EXPORT \ +const char* vtkGetFactoryVersion() \ +{ \ + return VTK_SOURCE_VERSION; \ +} \ +extern "C" \ +VTK_FACTORY_INTERFACE_EXPORT \ +vtkObjectFactory* vtkLoad() \ +{ \ + return factoryName ::New(); \ +} diff --git a/Common/vtkObjectFactoryCollection.cxx b/Common/vtkObjectFactoryCollection.cxx new file mode 100644 index 0000000..48e0e87 --- /dev/null +++ b/Common/vtkObjectFactoryCollection.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObjectFactoryCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkObjectFactoryCollection.h" + +#include "vtkDebugLeaks.h" + +vtkCxxRevisionMacro(vtkObjectFactoryCollection, "$Revision: 1.5 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkObjectFactoryCollection); + +vtkObjectFactoryCollection* vtkObjectFactoryCollection::New() +{ +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkObjectFactoryCollection"); +#endif + return new vtkObjectFactoryCollection; +} + diff --git a/Common/vtkObjectFactoryCollection.h b/Common/vtkObjectFactoryCollection.h new file mode 100644 index 0000000..97f3dd0 --- /dev/null +++ b/Common/vtkObjectFactoryCollection.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkObjectFactoryCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkObjectFactoryCollection - maintain a list of object factories +// .SECTION Description +// vtkObjectFactoryCollection is an object that creates and manipulates lists +// of object of type vtkObjectFactory. + +// .SECTION see also +// vtkCollection vtkObjectFactory + +#ifndef __vtkObjectFactoryCollection_h +#define __vtkObjectFactoryCollection_h + +#include "vtkCollection.h" + +#include "vtkObjectFactory.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkObjectFactoryCollection : public vtkCollection +{ +public: + vtkTypeRevisionMacro(vtkObjectFactoryCollection,vtkCollection); + static vtkObjectFactoryCollection *New(); + + // Description: + // Add an ObjectFactory from the list. + void AddItem(vtkObjectFactory *t) { this->vtkCollection::AddItem((vtkObject *)t); } + + // Description: + // Get the next ObjectFactory in the list. Return NULL when the end of the + // list is reached. + vtkObjectFactory *GetNextItem() + { return static_cast(this->GetNextItemAsObject());} + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkObjectFactory *GetNextObjectFactory(vtkCollectionSimpleIterator &cookie) { + return static_cast( + this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkObjectFactoryCollection() {}; + ~vtkObjectFactoryCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkObjectFactoryCollection(const vtkObjectFactoryCollection&); // Not implemented. + void operator=(const vtkObjectFactoryCollection&); // Not implemented. +}; + + +#endif diff --git a/Common/vtkOldStyleCallbackCommand.cxx b/Common/vtkOldStyleCallbackCommand.cxx new file mode 100644 index 0000000..730e74d --- /dev/null +++ b/Common/vtkOldStyleCallbackCommand.cxx @@ -0,0 +1,45 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOldStyleCallbackCommand.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOldStyleCallbackCommand.h" + +#include "vtkSetGet.h" +#include "vtkObject.h" + +#include +#include + +//---------------------------------------------------------------- +vtkOldStyleCallbackCommand::vtkOldStyleCallbackCommand() +{ + this->ClientData = NULL; + this->Callback = NULL; + this->ClientDataDeleteCallback = NULL; +} + +vtkOldStyleCallbackCommand::~vtkOldStyleCallbackCommand() +{ + if (this->ClientDataDeleteCallback) + { + this->ClientDataDeleteCallback(this->ClientData); + } +} + +void vtkOldStyleCallbackCommand::Execute(vtkObject *,unsigned long, void *) +{ + if (this->Callback) + { + this->Callback(this->ClientData); + } +} diff --git a/Common/vtkOldStyleCallbackCommand.h b/Common/vtkOldStyleCallbackCommand.h new file mode 100644 index 0000000..0569ed7 --- /dev/null +++ b/Common/vtkOldStyleCallbackCommand.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOldStyleCallbackCommand.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOldStyleCallbackCommand - supports legacy function callbacks for VTK +// .SECTION Description +// vtkOldStyleCallbackCommand is a callback that supports the legacy callback +// methods found in VTK. For example, the legacy method +// vtkProcessObject::SetStartMethod() is actually invoked using the +// command/observer design pattern of VTK, and the vtkOldStyleCallbackCommand +// is used to provide the legacy functionality. The callback function should +// have the form void func(void *clientdata), where clientdata is special data +// that should is associated with this instance of vtkCallbackCommand. +// +// .SECTION Caveats +// This is legacy glue. Please do not use; it will be eventually eliminated. + +// .SECTION See Also +// vtkCommand vtkCallbackCommand + +#ifndef __vtkOldStyleCallbackCommand_h +#define __vtkOldStyleCallbackCommand_h + +#include "vtkCommand.h" + +// the old style void fund(void *) callbacks +class VTK_COMMON_EXPORT vtkOldStyleCallbackCommand : public vtkCommand +{ +public: + static vtkOldStyleCallbackCommand *New() + {return new vtkOldStyleCallbackCommand;}; + + // Description: + // Satisfy the superclass API for callbacks. + void Execute(vtkObject *invoker, unsigned long eid, void *calldata); + + // Description: + // Methods to set and get client and callback information. + void SetClientData(void *cd) + {this->ClientData = cd;}; + void SetCallback(void (*f)(void *clientdata)) + {this->Callback = f;}; + void SetClientDataDeleteCallback(void (*f)(void *)) + {this->ClientDataDeleteCallback = f;}; + + void *ClientData; + void (*Callback)(void *); + void (*ClientDataDeleteCallback)(void *); + +protected: + vtkOldStyleCallbackCommand(); + ~vtkOldStyleCallbackCommand(); +}; + + +#endif /* __vtkOldStyleCallbackCommand_h */ + diff --git a/Common/vtkOutputWindow.cxx b/Common/vtkOutputWindow.cxx new file mode 100644 index 0000000..bef0f7d --- /dev/null +++ b/Common/vtkOutputWindow.cxx @@ -0,0 +1,187 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutputWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOutputWindow.h" +#include "vtkToolkits.h" +#if defined( _WIN32 ) && !defined( VTK_USE_X ) && defined( VTK_USE_DISPLAY ) +#include "vtkWin32OutputWindow.h" +#endif +#include "vtkObjectFactory.h" +#include "vtkDebugLeaks.h" + +vtkCxxRevisionMacro(vtkOutputWindow, "$Revision: 1.38 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkOutputWindow); + +//---------------------------------------------------------------------------- + +vtkOutputWindow* vtkOutputWindow::Instance = 0; +vtkOutputWindowCleanup vtkOutputWindow::Cleanup; + +void vtkOutputWindowDisplayText(const char* message) +{ + vtkOutputWindow::GetInstance()->DisplayText(message); +} + +void vtkOutputWindowDisplayErrorText(const char* message) +{ + vtkOutputWindow::GetInstance()->DisplayErrorText(message); +} + +void vtkOutputWindowDisplayWarningText(const char* message) +{ + vtkOutputWindow::GetInstance()->DisplayWarningText(message); +} + +void vtkOutputWindowDisplayGenericWarningText(const char* message) +{ + vtkOutputWindow::GetInstance()->DisplayGenericWarningText(message); +} + +void vtkOutputWindowDisplayDebugText(const char* message) +{ + vtkOutputWindow::GetInstance()->DisplayDebugText(message); +} + +vtkOutputWindowCleanup::vtkOutputWindowCleanup() +{ +} + +vtkOutputWindowCleanup::~vtkOutputWindowCleanup() +{ + // Destroy any remaining output window. + vtkOutputWindow::SetInstance(0); +} + +vtkOutputWindow::vtkOutputWindow() +{ + this->PromptUser = 0; +} + +vtkOutputWindow::~vtkOutputWindow() +{ +} + +void vtkOutputWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "vtkOutputWindow Single instance = " + << (void*)vtkOutputWindow::Instance << endl; + os << indent << "Prompt User: " + << (this->PromptUser ? "On\n" : "Off\n"); +} + + +// default implementation outputs to cerr only +void vtkOutputWindow::DisplayText(const char* txt) +{ + cerr << txt; + if (this->PromptUser) + { + char c = 'n'; + cerr << "\nDo you want to suppress any further messages (y,n,q)?." + << endl; + cin >> c; + if (c == 'y') + { + vtkObject::GlobalWarningDisplayOff(); + } + if(c == 'q') + { + this->PromptUser = 0; + } + } +} + +void vtkOutputWindow::DisplayErrorText(const char* txt) +{ + this->DisplayText(txt); +} + +void vtkOutputWindow::DisplayWarningText(const char* txt) +{ + this->DisplayText(txt); +} + +void vtkOutputWindow::DisplayGenericWarningText(const char* txt) +{ + this->DisplayText(txt); +} + +void vtkOutputWindow::DisplayDebugText(const char* txt) +{ + this->DisplayText(txt); +} + +// Up the reference count so it behaves like New +vtkOutputWindow* vtkOutputWindow::New() +{ + vtkOutputWindow* ret = vtkOutputWindow::GetInstance(); + ret->Register(NULL); + return ret; +} + + +// Return the single instance of the vtkOutputWindow +vtkOutputWindow* vtkOutputWindow::GetInstance() +{ + if(!vtkOutputWindow::Instance) + { + // Try the factory first + vtkOutputWindow::Instance = (vtkOutputWindow*) + vtkObjectFactory::CreateInstance("vtkOutputWindow"); + // if the factory did not provide one, then create it here + if(!vtkOutputWindow::Instance) + { + // if the factory failed to create the object, + // then destroy it now, as vtkDebugLeaks::ConstructClass was called + // with "vtkOutputWindow", and not the real name of the class +#if defined( _WIN32 ) && !defined( VTK_USE_X ) && defined( VTK_USE_DISPLAY ) +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass("vtkOutputWindow"); +#endif + vtkOutputWindow::Instance = vtkWin32OutputWindow::New(); +#else + vtkOutputWindow::Instance = new vtkOutputWindow; +#endif + } + } + // return the instance + return vtkOutputWindow::Instance; +} + +void vtkOutputWindow::SetInstance(vtkOutputWindow* instance) +{ + if (vtkOutputWindow::Instance==instance) + { + return; + } + // preferably this will be NULL + if (vtkOutputWindow::Instance) + { + vtkOutputWindow::Instance->Delete();; + } + vtkOutputWindow::Instance = instance; + if (!instance) + { + return; + } + // user will call ->Delete() after setting instance + instance->Register(NULL); +} + + diff --git a/Common/vtkOutputWindow.h b/Common/vtkOutputWindow.h new file mode 100644 index 0000000..26c41f0 --- /dev/null +++ b/Common/vtkOutputWindow.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutputWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOutputWindow - base class for writing debug output to a console +// .SECTION Description +// This class is used to encapsulate all text output, so that it will work +// with operating systems that have a stdout and stderr, and ones that +// do not. (i.e windows does not). Sub-classes can be provided which can +// redirect the output to a window. + +#ifndef __vtkOutputWindow_h +#define __vtkOutputWindow_h + +#include "vtkObject.h" + +//BTX + +class VTK_COMMON_EXPORT vtkOutputWindow; + +class VTK_COMMON_EXPORT vtkOutputWindowCleanup +{ +public: + vtkOutputWindowCleanup(); + ~vtkOutputWindowCleanup(); +}; +//ETX + +class VTK_COMMON_EXPORT vtkOutputWindow : public vtkObject +{ +public: +// Methods from vtkObject + vtkTypeRevisionMacro(vtkOutputWindow,vtkObject); + // Description: + // Print ObjectFactor to stream. + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is a singleton pattern New. There will only be ONE + // reference to a vtkOutputWindow object per process. Clients that + // call this must call Delete on the object so that the reference + // counting will work. The single instance will be unreferenced when + // the program exits. + static vtkOutputWindow* New(); + // Description: + // Return the singleton instance with no reference counting. + static vtkOutputWindow* GetInstance(); + // Description: + // Supply a user defined output window. Call ->Delete() on the supplied + // instance after setting it. + static void SetInstance(vtkOutputWindow *instance); + // Description: + // Display the text. Four virtual methods exist, depending on the type of + // message to display. This allows redirection or reformatting of the + // messages. The default implementation uses DisplayText for all. + virtual void DisplayText(const char*); + virtual void DisplayErrorText(const char*); + virtual void DisplayWarningText(const char*); + virtual void DisplayGenericWarningText(const char*); + + virtual void DisplayDebugText(const char*); + // Description: + // If PromptUser is set to true then each time a line of text + // is displayed, the user is asked if they want to keep getting + // messages. + vtkBooleanMacro(PromptUser,int); + vtkSetMacro(PromptUser, int); +//BTX + // use this as a way of memory management when the + // program exits the SmartPointer will be deleted which + // will delete the Instance singleton + static vtkOutputWindowCleanup Cleanup; +//ETX +protected: + vtkOutputWindow(); + virtual ~vtkOutputWindow(); + int PromptUser; +private: + static vtkOutputWindow* Instance; +private: + vtkOutputWindow(const vtkOutputWindow&); // Not implemented. + void operator=(const vtkOutputWindow&); // Not implemented. +}; + +#endif diff --git a/Common/vtkOverrideInformation.cxx b/Common/vtkOverrideInformation.cxx new file mode 100644 index 0000000..bf81f5a --- /dev/null +++ b/Common/vtkOverrideInformation.cxx @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOverrideInformation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOverrideInformation.h" + +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkOverrideInformation, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkOverrideInformation); +vtkCxxSetObjectMacro(vtkOverrideInformation,ObjectFactory,vtkObjectFactory); + +vtkOverrideInformation::vtkOverrideInformation() +{ + this->ClassOverrideName = 0; + this->ClassOverrideWithName = 0; + this->Description = 0; + this->ObjectFactory = 0; +} + +vtkOverrideInformation::~vtkOverrideInformation() +{ + delete [] this->ClassOverrideName; + delete [] this->ClassOverrideWithName; + delete [] this->Description; + if(this->ObjectFactory) + { + this->ObjectFactory->Delete(); + } +} + + +void vtkOverrideInformation::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent + << "Override: " << this->ClassOverrideName + << "\nWith: " << this->ClassOverrideWithName + << "\nDescription: " << this->Description; + os << indent << "From Factory:\n"; + if(this->ObjectFactory) + { + this->ObjectFactory->PrintSelf(os, indent.GetNextIndent()); + } + else + { + vtkIndent n = indent.GetNextIndent(); + os << n << "(NULL)\n"; + } +} + + diff --git a/Common/vtkOverrideInformation.h b/Common/vtkOverrideInformation.h new file mode 100644 index 0000000..e1c990a --- /dev/null +++ b/Common/vtkOverrideInformation.h @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOverrideInformation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOverrideInformation - Factory object override information +// .SECTION Description +// vtkOverrideInformation is used to represent the information about +// a class which is overriden in a vtkObjectFactory. +// + +#ifndef __vtkOverrideInformation_h +#define __vtkOverrideInformation_h + +#include "vtkObject.h" + +class vtkObjectFactory; + +class VTK_COMMON_EXPORT vtkOverrideInformation : public vtkObject +{ +public: + static vtkOverrideInformation* New(); + vtkTypeRevisionMacro(vtkOverrideInformation,vtkObject); + // Description: + // Print ObjectFactor to stream. + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Returns the name of the class being overriden. For example, + // if you had a factory that provided an override for + // vtkVertex, then this funciton would return "vtkVertex" + const char* GetClassOverrideName() + { + return this->ClassOverrideName; + } + + // Description: + // Returns the name of the class that will override the class. + // For example, if you had a factory that provided an override for + // vtkVertex called vtkMyVertex, then this would return "vtkMyVertex" + const char* GetClassOverrideWithName() + { + return this->ClassOverrideWithName; + } + + // Description: + // Return a human readable or GUI displayable description of this + // override. + const char* GetDescription() + { + return this->Description; + } + + // Description: + // Return the specific object factory that this override occurs in. + vtkObjectFactory* GetObjectFactory() + { + return this->ObjectFactory; + } + // Description: + // Set the class override name + vtkSetStringMacro(ClassOverrideName); + // Set the class override with name + vtkSetStringMacro(ClassOverrideWithName); + // Set the description + vtkSetStringMacro(Description); +protected: + virtual void SetObjectFactory(vtkObjectFactory*); + +private: + vtkOverrideInformation(); + ~vtkOverrideInformation(); + // allow the object factory to set the values in this + // class, but only the object factory +//BTX + friend class vtkObjectFactory; +//ETX + + char* ClassOverrideName; + char* ClassOverrideWithName; + char* Description; + vtkObjectFactory* ObjectFactory; +private: + vtkOverrideInformation(const vtkOverrideInformation&); // Not implemented. + void operator=(const vtkOverrideInformation&); // Not implemented. +}; + +#endif diff --git a/Common/vtkOverrideInformationCollection.cxx b/Common/vtkOverrideInformationCollection.cxx new file mode 100644 index 0000000..4c5157a --- /dev/null +++ b/Common/vtkOverrideInformationCollection.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOverrideInformationCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOverrideInformationCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkOverrideInformationCollection, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkOverrideInformationCollection); diff --git a/Common/vtkOverrideInformationCollection.h b/Common/vtkOverrideInformationCollection.h new file mode 100644 index 0000000..641503c --- /dev/null +++ b/Common/vtkOverrideInformationCollection.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOverrideInformationCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOverrideInformationCollection - maintain a list of override information objects +// .SECTION Description +// vtkOverrideInformationCollection is an object that creates and manipulates +// lists of objects of type vtkOverrideInformation. +// .SECTION See Also +// vtkCollection + +#ifndef __vtkOverrideInformationCollection_h +#define __vtkOverrideInformationCollection_h + +#include "vtkCollection.h" + +#include "vtkOverrideInformation.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkOverrideInformationCollection : public vtkCollection +{ +public: + vtkTypeRevisionMacro(vtkOverrideInformationCollection,vtkCollection); + static vtkOverrideInformationCollection *New(); + + // Description: + // Add a OverrideInformation to the list. + void AddItem(vtkOverrideInformation *); + + // Description: + // Get the next OverrideInformation in the list. + vtkOverrideInformation *GetNextItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkOverrideInformation *GetNextOverrideInformation( + vtkCollectionSimpleIterator &cookie) { + return static_cast( + this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkOverrideInformationCollection() {}; + ~vtkOverrideInformationCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkOverrideInformationCollection(const vtkOverrideInformationCollection&); // Not implemented. + void operator=(const vtkOverrideInformationCollection&); // Not implemented. +}; + +inline void vtkOverrideInformationCollection::AddItem(vtkOverrideInformation *f) +{ + this->vtkCollection::AddItem((vtkObject *)f); +} + +inline vtkOverrideInformation *vtkOverrideInformationCollection::GetNextItem() +{ + return static_cast(this->GetNextItemAsObject()); +} + +#endif diff --git a/Common/vtkParametricBoy.cxx b/Common/vtkParametricBoy.cxx new file mode 100644 index 0000000..a4dbe9f --- /dev/null +++ b/Common/vtkParametricBoy.cxx @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricBoy.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricBoy.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricBoy, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkParametricBoy); + +//---------------------------------------------------------------------------- +vtkParametricBoy::vtkParametricBoy() +{ + // Preset triangulation parameters + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = vtkMath::Pi(); + this->MaximumV = vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 1; + this->TwistU = 1; + this->TwistV = 1; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; + + this->ZScale = 0.125; +} + +//---------------------------------------------------------------------------- +vtkParametricBoy::~vtkParametricBoy() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricBoy::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double cu = cos(u); + double su = sin(u); + double sv = sin(v); + + double X = cos(u)*sin(v); + double Y = sin(u)*sin(v); + double Z = cos(v); + + double X2 = X * X; + double X3 = X2 * X; + double X4 = X3 * X; + double Y2 = Y * Y; + double Y3 = Y2 * Y; + double Y4 = Y3 * Y; + double Z2 = Z * Z; + double Z3 = Z2 * Z; + double Z4 = Z3 * Z; + + // The point + Pt[0] = 1.0/2.0*(2*X2-Y2-Z2+2.0*Y*Z*(Y2-Z2)+ + Z*X*(X2-Z2)+X*Y*(Y2-X2)); + Pt[1] = sqrt(3.0)/2.0*(Y2-Z2+(Z*X*(Z2-X2)+ + X*Y*(Y2-X2))); + Pt[2] = this->ZScale*(X+Y+Z)*((X+Y+Z)*(X+Y+Z)*(X+Y+Z)+ + 4.0*(Y-X)*(Z-Y)*(X-Z)); + + //The derivatives are: + Du[0] = -1.0/2.0*X4-Z3*X+3.0*Y2*X2-3.0/2.0*Z*X2*Y+3.0*Z*X*Y2- + 3.0*Y*X-1.0/2.0*Y4+1.0/2.0*Z3*Y; + Dv[0] = (3.0/2.0*Z2*X2+2*Z*X-1.0/2.0*Z4)*cu+ + (-2.0*Z*X3+2*Z*X*Y2+3*Z2*Y2-Z*Y-Z4)*su+ + (-1.0/2.0*X3+3.0/2.0*Z2*X-Y3+3.0*Z2*Y+Z)*sv; + Du[1] = -1.0/2.0*sqrt(3.0)*X4+3.0*sqrt(3.0)*Y2*X2+ + 3.0/2.0*sqrt(3.0)*Z*X2*Y+sqrt(3.0)*Y*X- + 1.0/2.0*sqrt(3.0)*Y4-1.0/2.0*sqrt(3.0)*Z3*Y; + Dv[1] = (-3.0/2.0*sqrt(3.0)*Z2*X2+1.0/2.0*sqrt(3.0)*Z4)*cu+ + (-2.0*sqrt(3.0)*Z*X3+2.0*sqrt(3.0)*Z*Y2*X+sqrt(3.0)*Z*Y)*su+ + (1.0/2.0*sqrt(3.0)*X3-3.0/2.0*sqrt(3.0)*Z2*X+sqrt(3.0)*Z)*sv; + Du[2] = X4+3/2*Z*X3+3/2*Z2*X2+X3*Y-3*X2*Y2+ + 3*Z*X2*Y-Y3*X-3/2*Z*Y3-3/2*Z2*Y2-Z3*Y; + Dv[2] = (1/2*Z*X3+3/2*Z3*X+Z4)*cu+(4*Z*X3+3*Z*X2*Y+ + 9/2*Z2*X2+9/2*Z2*X*Y+3*Z3*X+1/2*Z*Y3+3*Z2*Y2+ + 3/2*Z3*Y)*su+(-3/2*X2*Y-3/2*Z*X2-3/2*X*Y2- + 3*Z*X*Y-3*Z2*X-Y3-3/2*Z*Y2-1/2*Z3)*sv; +} + +//---------------------------------------------------------------------------- +double vtkParametricBoy::EvaluateScalar(double *, double *, double *) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricBoy::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ZScale: " << this->ZScale << "\n"; + +} diff --git a/Common/vtkParametricBoy.h b/Common/vtkParametricBoy.h new file mode 100644 index 0000000..959d408 --- /dev/null +++ b/Common/vtkParametricBoy.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricBoy.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricBoy - Generate Boy's surface. +// .SECTION Description +// vtkParametricBoy generates Boy's surface. +// This is a Model of the projective plane without singularities. +// It was found by Werner Boy on assignment from David Hilbert. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for +// creating and contributing the class. +// +#ifndef __vtkParametricBoy_h +#define __vtkParametricBoy_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricBoy : public vtkParametricFunction +{ +public: + + vtkTypeRevisionMacro(vtkParametricBoy,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct Boy's surface with the following parameters: + // MinimumU = 0, MaximumU = Pi, + // MinimumV = 0, MaximumV = Pi, + // JoinU = 1, JoinV = 1, + // TwistU = 1, TwistV = 1; + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + // ZScale = 0.125. + static vtkParametricBoy *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Set/Get the scale factor for the z-coordinate. + // Default = 1/8, giving a nice shape. + vtkSetMacro(ZScale,double); + vtkGetMacro(ZScale,double); + + // Description: + // Boy's surface. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricBoy(); + ~vtkParametricBoy(); + + // Variables + double ZScale; + +private: + vtkParametricBoy(const vtkParametricBoy&); // Not implemented. + void operator=(const vtkParametricBoy&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricConicSpiral.cxx b/Common/vtkParametricConicSpiral.cxx new file mode 100644 index 0000000..cbea03c --- /dev/null +++ b/Common/vtkParametricConicSpiral.cxx @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricConicSpiral.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricConicSpiral.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricConicSpiral, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkParametricConicSpiral); + +//---------------------------------------------------------------------------- +vtkParametricConicSpiral::vtkParametricConicSpiral() +{ + // Preset triangulation parameters + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = 2.0*vtkMath::Pi(); + this->MaximumV = 2.0*vtkMath::Pi(); + + this->JoinU = 0; + this->JoinV = 0; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; + + // Conic Spiral + this->A = 0.2; + this->B = 1; + this->C = 0.1; + this->N = 2; +} + +//---------------------------------------------------------------------------- +vtkParametricConicSpiral::~vtkParametricConicSpiral() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricConicSpiral::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double inv2pi = 1.0/(2.0*vtkMath::Pi()); + + double cnv = cos(this->N*v); + double snv = sin(this->N*v); + double cu = cos(u); + double su = sin(u); + + // The point + Pt[0] = this->A*(1-v*inv2pi)*cnv*(1+cu)+this->C*cnv; + Pt[1] = this->A*(1-v*inv2pi)*snv*(1+cu)+this->C*snv; + Pt[2] = this->B*v*inv2pi+this->A*(1-v*inv2pi)*su; + + //The derivatives are: + Du[0] = -this->A*(1-v*inv2pi)*cnv*su; + Dv[0] = -this->A*inv2pi*cnv*(1+cu)-this->A*(1-v*inv2pi)*snv*this->N*(1+cu)-this->C*snv*N; + Du[1] = -this->A*(1-v*inv2pi)*snv*su; + Dv[1] = -this->A*inv2pi*snv*(1+cu)+this->A*(1-v*inv2pi)*cnv*this->N*(1+cu)+C*cnv*this->N; + Du[2] = this->A*(1-v*inv2pi)*cu; + Dv[2] = this->B*inv2pi-this->A*inv2pi*su; +} + +//---------------------------------------------------------------------------- +double vtkParametricConicSpiral::EvaluateScalar(double *, double *, double *) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricConicSpiral::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "A: " << this->A << "\n"; + os << indent << "B: " << this->B << "\n"; + os << indent << "C: " << this->C << "\n"; + os << indent << "N: " << this->N << "\n"; +} diff --git a/Common/vtkParametricConicSpiral.h b/Common/vtkParametricConicSpiral.h new file mode 100644 index 0000000..4866712 --- /dev/null +++ b/Common/vtkParametricConicSpiral.h @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricConicSpiral.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricConicSpiral - Generate conic spiral surfaces that resemble sea-shells. +// .SECTION Description +// vtkParametricConicSpiral generates conic spiral surfaces. These can resemble sea shells, or +// may look like a torus "eating" its own tail. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +#ifndef __vtkParametricConicSpiral_h +#define __vtkParametricConicSpiral_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricConicSpiral : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricConicSpiral,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a conic spiral surface with the following parameters: + // MinimumU = 0, MaximumU = 2Pi, + // MinimumV = 0, MaximumV = 2Pi, + // JoinU = 0, JoinV = 0, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + // A = 0.2, B = 1.0, C = 0.1, N = 2. + static vtkParametricConicSpiral *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Set/Get the scale factor. + // Default = 0.2 + vtkSetMacro(A,double); + vtkGetMacro(A,double); + + // Description: + // Set/Get the A function coefficient (see equation below). + // Default = 1. + vtkSetMacro(B,double); + vtkGetMacro(B,double); + + // Description: + // Set/Get the B function coefficient (see equation below). + // Default = 0.1. + vtkSetMacro(C,double); + vtkGetMacro(C,double); + + // Description: + // Set/Get the C function coefficient (see equation below). + // Default = 2. + vtkSetMacro(N,double); + vtkGetMacro(N,double); + + // Description: + // A conic spiral surface. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricConicSpiral(); + ~vtkParametricConicSpiral(); + + // Variables + double A; + double B; + double C; + double N; + +private: + vtkParametricConicSpiral(const vtkParametricConicSpiral&); // Not implemented. + void operator=(const vtkParametricConicSpiral&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricCrossCap.cxx b/Common/vtkParametricCrossCap.cxx new file mode 100644 index 0000000..1f43305 --- /dev/null +++ b/Common/vtkParametricCrossCap.cxx @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricCrossCap.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricCrossCap.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricCrossCap, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkParametricCrossCap); + +//---------------------------------------------------------------------------- +vtkParametricCrossCap::vtkParametricCrossCap() +{ + // Preset triangulation parameters + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = vtkMath::Pi(); + this->MaximumV = vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 1; + this->TwistU = 1; + this->TwistV = 1; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; +} + +//---------------------------------------------------------------------------- +vtkParametricCrossCap::~vtkParametricCrossCap() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricCrossCap::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double cu = cos(u); + double su = sin(u); + double cv = cos(v); + double c2v = cos(2 * v); + double sv = sin(v); + double s2v = sin(2 * v); + + // The point + Pt[0] = cu * s2v; + Pt[1] = su * s2v; + Pt[2] = cv * cv - cu * cu * sv * sv; + + //The derivatives are: + Du[0] = -Pt[1]; + Du[1] = Pt[0]; + Du[2] = 2 * cu * su * sv * sv; + Dv[0] = 2 * cu * c2v; + Dv[1] = 2 * su * c2v; + Dv[2] = -2 * cv * sv * (1 + cu * cu); +} + +//---------------------------------------------------------------------------- +double vtkParametricCrossCap::EvaluateScalar(double *, double *, double *) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricCrossCap::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Common/vtkParametricCrossCap.h b/Common/vtkParametricCrossCap.h new file mode 100644 index 0000000..e531d57 --- /dev/null +++ b/Common/vtkParametricCrossCap.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricCrossCap.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricCrossCap - Generate a cross-cap. +// .SECTION Description +// vtkParametricCrossCap generates a cross-cap which is a +// non-orientable self-intersecting single-sided surface. +// This is one possible image of a projective plane in three-space. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for +// creating and contributing the class. +// +#ifndef __vtkParametricCrossCap_h +#define __vtkParametricCrossCap_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricCrossCap : public vtkParametricFunction +{ +public: + + vtkTypeRevisionMacro(vtkParametricCrossCap,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a cross-cap with the following parameters: + // MinimumU = 0, MaximumU = Pi, + // MinimumV = 0, MaximumV = Pi, + // JoinU = 1, JoinV = 1, + // TwistU = 1, TwistV = 1; + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1 + static vtkParametricCrossCap *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // A cross-cap. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricCrossCap(); + ~vtkParametricCrossCap(); + +private: + vtkParametricCrossCap(const vtkParametricCrossCap&); // Not implemented. + void operator=(const vtkParametricCrossCap&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricDini.cxx b/Common/vtkParametricDini.cxx new file mode 100644 index 0000000..6fb44cf --- /dev/null +++ b/Common/vtkParametricDini.cxx @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricDini.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricDini.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricDini, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkParametricDini); + +//---------------------------------------------------------------------------- +vtkParametricDini::vtkParametricDini() +{ + // Preset triangulation parameters + this->MinimumU = 0; + this->MinimumV = 0.001; + this->MaximumU = 4*vtkMath::Pi(); + this->MaximumV = 2.0; + + this->JoinU = 0; + this->JoinV = 0; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; + + this->A = 1.0; + this->B = 0.2; +} + +//---------------------------------------------------------------------------- +vtkParametricDini::~vtkParametricDini() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricDini::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double cu = cos(u); + double cv = cos(v); + double su = sin(u); + double sv = sin(v); + + // The point + Pt[0] = this->A*cu*sv; + Pt[1] = this->A*su*sv; + Pt[2] = this->A*(cos(v)+log(tan((v/2))))+this->B*u; + + //The derivatives are: + Du[0] = -Pt[1]; + Dv[0] = this->A*cu*cv; + Du[1] = Pt[0]; + Dv[1] = this->A*su*cv; + Du[2] = this->B; + double tv2 = tan(0.5*v); + if ( tv2 != 0 ) + Dv[2] = this->A*(-sv+(0.5+0.5*tv2*tv2)/tv2); + else + Dv[2] = this->A*(-sv+(0.5+0.5*tv2*tv2)/0.0001); // Avoid division by zero. +} + +//---------------------------------------------------------------------------- +double vtkParametricDini::EvaluateScalar(double *, double *, double *) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricDini::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "A: " << this->A << "\n"; + os << indent << "B: " << this->B << "\n"; + +} diff --git a/Common/vtkParametricDini.h b/Common/vtkParametricDini.h new file mode 100644 index 0000000..6cb1642 --- /dev/null +++ b/Common/vtkParametricDini.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricDini.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricDini - Generate Dini's surface. +// .SECTION Description +// vtkParametricDini generates Dini's surface. +// Dini's surface is a surface that posesses constant negative +// Gaussian curvature +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for +// creating and contributing the class. +// +#ifndef __vtkParametricDini_h +#define __vtkParametricDini_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricDini : public vtkParametricFunction +{ +public: + + vtkTypeRevisionMacro(vtkParametricDini,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct Dini's surface with the following parameters: + // MinimumU = 0, MaximumU = 4*Pi, + // MinimumV = 0.001, MaximumV = 2, + // JoinU = 0, JoinV = 0, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1 + // A = 1, B = 0.2 + static vtkParametricDini *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Set/Get the scale factor. + // Default = 1. + vtkSetMacro(A,double); + vtkGetMacro(A,double); + + // Description: + // Set/Get the scale factor. + // Default = 0.2 + vtkSetMacro(B,double); + vtkGetMacro(B,double); + + // Description: + // Dini's surface. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricDini(); + ~vtkParametricDini(); + + // Variables + double A; + double B; + +private: + vtkParametricDini(const vtkParametricDini&); // Not implemented. + void operator=(const vtkParametricDini&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricEllipsoid.cxx b/Common/vtkParametricEllipsoid.cxx new file mode 100644 index 0000000..3656a9c --- /dev/null +++ b/Common/vtkParametricEllipsoid.cxx @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricEllipsoid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricEllipsoid.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include + +vtkCxxRevisionMacro(vtkParametricEllipsoid, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkParametricEllipsoid); + +//---------------------------------------------------------------------------- +vtkParametricEllipsoid::vtkParametricEllipsoid() : + XRadius(1) + , YRadius(1) + , ZRadius(1) +{ + // Preset triangulation parameters + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = 2.0 * vtkMath::Pi(); + this->MaximumV = vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 0; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; +} + +//---------------------------------------------------------------------------- +vtkParametricEllipsoid::~vtkParametricEllipsoid() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricEllipsoid::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + for ( int i = 0; i < 3; ++i) + { + Pt[i] = Du[i] = Dv[i] = 0; + } + + double cu = cos(u); + double su = sin(u); + double cv = cos(v); + double sv = sin(v); + + // The point + Pt[0] = this->XRadius*sv*cu; + Pt[1] = this->YRadius*sv*su; + Pt[2] = this->ZRadius*cv; + + //The derivatives are: + Du[0] = -this->XRadius*sv*su; + Du[1] = this->YRadius*sv*cu; + Du[2] = 0; + Dv[0] = this->XRadius*cv*cu; + Dv[1] = this->YRadius*cv*su; + Dv[2] = -this->ZRadius*sv; + +} + +//---------------------------------------------------------------------------- +double vtkParametricEllipsoid::EvaluateScalar(double*, double*, double*) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricEllipsoid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "X scale factor: " << this->XRadius << "\n"; + os << indent << "Y scale factor: " << this->YRadius << "\n"; + os << indent << "Z scale factor: " << this->ZRadius << "\n"; +} + diff --git a/Common/vtkParametricEllipsoid.h b/Common/vtkParametricEllipsoid.h new file mode 100644 index 0000000..40f71d5 --- /dev/null +++ b/Common/vtkParametricEllipsoid.h @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricEllipsoid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricEllipsoid - Generate an ellipsoid. +// .SECTION Description +// vtkParametricEllipsoid generates an ellipsoid. +// If all the radii are the same, we have a sphere. +// An oblate spheroid occurs if RadiusX = RadiusY > RadiusZ. +// Here the Z-axis forms the symmetry axis. To a first +// approximation, this is the shape of the earth. +// A prolate spheroid occurs if RadiusX = RadiusY < RadiusZ. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +#ifndef __vtkParametricEllipsoid_h +#define __vtkParametricEllipsoid_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricEllipsoid : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricEllipsoid,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct an ellipsoid with the following parameters: + // MinimumU = 0, MaximumU = 2*Pi, + // MinimumV = 0, MaximumV = Pi, + // JoinU = 1, JoinV = 0, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + // XRadius = 1, YRadius = 1, + // ZRadius = 1, a sphere in this case. + static vtkParametricEllipsoid *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Set/Get the scaling factor for the x-axis. Default = 1. + vtkSetMacro(XRadius,double); + vtkGetMacro(XRadius,double); + + // Description: + // Set/Get the scaling factor for the y-axis. Default = 1. + vtkSetMacro(YRadius,double); + vtkGetMacro(YRadius,double); + + // Description: + // Set/Get the scaling factor for the z-axis. Default = 1. + vtkSetMacro(ZRadius,double); + vtkGetMacro(ZRadius,double); + + // Description: + // An ellipsoid. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricEllipsoid(); + ~vtkParametricEllipsoid(); + + // Variables + double XRadius; + double YRadius; + double ZRadius; + double N1; + double N2; + +private: + vtkParametricEllipsoid(const vtkParametricEllipsoid&); // Not implemented. + void operator=(const vtkParametricEllipsoid&); // Not implemented. + +}; + +#endif diff --git a/Common/vtkParametricEnneper.cxx b/Common/vtkParametricEnneper.cxx new file mode 100644 index 0000000..3e57e23 --- /dev/null +++ b/Common/vtkParametricEnneper.cxx @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricEnneper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricEnneper.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricEnneper, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkParametricEnneper); + +//---------------------------------------------------------------------------- +vtkParametricEnneper::vtkParametricEnneper() +{ + // Preset triangulation parameters + this->MinimumU = -2.0; + this->MinimumV = -2.0; + this->MaximumU = 2.0; + this->MaximumV = 2.0; + + this->JoinU = 0; + this->JoinV = 0; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; + +} + +//---------------------------------------------------------------------------- +vtkParametricEnneper::~vtkParametricEnneper() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricEnneper::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + // The point + Pt[0] = u-u*u*u/3+u*v*v; + Pt[1] = v-v*v*v/3+u*u*v; + Pt[2] = u*u-v*v; + + //The derivatives are: + Du[0] = 1-u*u+v*v; + Dv[0] = 2*u*v; + Du[1] = 2*u*v; + Dv[1] = 1-v*v+u*u; + Du[2] = 2*u; + Dv[2] = -2*v; +} + +//---------------------------------------------------------------------------- +double vtkParametricEnneper::EvaluateScalar(double *, double *, double *) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricEnneper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Common/vtkParametricEnneper.h b/Common/vtkParametricEnneper.h new file mode 100644 index 0000000..083e4b4 --- /dev/null +++ b/Common/vtkParametricEnneper.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricEnneper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricEnneper - Generate Enneper's surface. +// .SECTION Description +// vtkParametricEnneper generates Enneper's surface. +// Enneper's surface is a a self-intersecting minimal surface +// posessing constant negative Gaussian curvature +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for +// creating and contributing the class. +// +#ifndef __vtkParametricEnneper_h +#define __vtkParametricEnneper_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricEnneper : public vtkParametricFunction +{ +public: + + vtkTypeRevisionMacro(vtkParametricEnneper,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct Enneper's surface with the following parameters: + // MinimumU = -2, MaximumU = 2, + // MinimumV = -2, MaximumV = 2, + // JoinU = 0, JoinV = 0, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1 + static vtkParametricEnneper *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Enneper's surface. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uv are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricEnneper(); + ~vtkParametricEnneper(); + +private: + vtkParametricEnneper(const vtkParametricEnneper&); // Not implemented. + void operator=(const vtkParametricEnneper&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricFigure8Klein.cxx b/Common/vtkParametricFigure8Klein.cxx new file mode 100644 index 0000000..59cf8b0 --- /dev/null +++ b/Common/vtkParametricFigure8Klein.cxx @@ -0,0 +1,90 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricFigure8Klein.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricFigure8Klein.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricFigure8Klein, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkParametricFigure8Klein); + +//---------------------------------------------------------------------------- +vtkParametricFigure8Klein::vtkParametricFigure8Klein() +{ + // Preset triangulation parameters + this->MinimumU = -vtkMath::Pi(); + this->MinimumV = -vtkMath::Pi(); + this->MaximumU = vtkMath::Pi(); + this->MaximumV = vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 1; + this->TwistU = 1; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; + this->Radius = 1; +} + +//---------------------------------------------------------------------------- +vtkParametricFigure8Klein::~vtkParametricFigure8Klein() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricFigure8Klein::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double cu = cos(u); + double cu2 = cos(u / 2); + double su = sin(u); + double su2 = sin(u / 2); + double cv = cos(v); + double c2v = cos(2 * v); + double s2v = sin(2 * v); + double sv = sin(v); + double t = this->Radius + sv * cu2 - s2v * su2 / 2; + + // The point + Pt[0] = cu * t; + Pt[1] = su * t; + Pt[2] = su2 * sv + cu2 * s2v / 2; + + //The derivatives are: + Du[0] = -Pt[1] - cu * ( 2 * sv * su2 + s2v * cu2 ) / 4; + Du[1] = Pt[0] - su * ( 2 * sv * su2 + s2v * cu2 ) / 4; + Du[2] = cu2 * sv / 2 - su2 * s2v / 4; + Dv[0] = cu * ( cv * cu2 - c2v * su2); + Dv[1] = su * ( cv * cu2 - c2v * su2); + Dv[2] = su2 * cv / 2 + cu2 * c2v; +} + +//---------------------------------------------------------------------------- +double vtkParametricFigure8Klein::EvaluateScalar(double*, double*, double*) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricFigure8Klein::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Radius: " << this->Radius << "\n"; +} + diff --git a/Common/vtkParametricFigure8Klein.h b/Common/vtkParametricFigure8Klein.h new file mode 100644 index 0000000..7b8b8bc --- /dev/null +++ b/Common/vtkParametricFigure8Klein.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricFigure8Klein.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricFigure8Klein - Generate a figure-8 Klein bottle. +// .SECTION Description +// vtkParametricFigure8Klein generates a figure-8 Klein bottle. A Klein bottle +// is a closed surface with no interior and only one surface. It is +// unrealisable in 3 dimensions without intersecting surfaces. It can be +// realised in 4 dimensions by considering the map \f$F:R^2 \rightarrow R^4\f$ given by: +// +// - \f$f(u,v) = ((r*cos(v)+a)*cos(u),(r*cos(v)+a)*sin(u),r*sin(v)*cos(u/2),r*sin(v)*sin(u/2))\f$ +// +// This representation of the immersion in \f$R^3\f$ is formed by taking two Mobius +// strips and joining them along their boundaries, this is the so called +// "Figure-8 Klein Bottle" +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +#ifndef __vtkParametricFigure8Klein_h +#define __vtkParametricFigure8Klein_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricFigure8Klein : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricFigure8Klein,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a figure-8 Klein Bottle with the following parameters: + // MinimumU = -Pi, MaximumU = Pi, + // MinimumV = -Pi, MaximumV = Pi, + // JoinU = 1, JoinV = 1, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + // Radius = 1 + static vtkParametricFigure8Klein *New(); + + // Description: + // Set/Get the radius of the bottle. + vtkSetMacro(Radius,double); + vtkGetMacro(Radius,double); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // A Figure-8 Klein bottle. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricFigure8Klein(); + ~vtkParametricFigure8Klein(); + + // Variables + double Radius; + +private: + vtkParametricFigure8Klein(const vtkParametricFigure8Klein&); // Not implemented. + void operator=(const vtkParametricFigure8Klein&); // Not implemented. + +}; + +#endif diff --git a/Common/vtkParametricFunction.cxx b/Common/vtkParametricFunction.cxx new file mode 100644 index 0000000..b0152e4 --- /dev/null +++ b/Common/vtkParametricFunction.cxx @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricFunction.h" + +vtkCxxRevisionMacro(vtkParametricFunction, "$Revision: 1.2 $"); + +//---------------------------------------------------------------------------- +vtkParametricFunction::vtkParametricFunction() : + MinimumU(0.0) + , MaximumU(1.0) + , MinimumV(0.0) + , MaximumV(1.0) + , MinimumW(0.0) + , MaximumW(1.0) + , JoinU(0) + , JoinV(0) + , JoinW(0) + , TwistU(0) + , TwistV(0) + , TwistW(0) + , ClockwiseOrdering(1) + , DerivativesAvailable(1) +{ +} + + +//---------------------------------------------------------------------------- +vtkParametricFunction::~vtkParametricFunction() +{ +} + + +//---------------------------------------------------------------------------- +void vtkParametricFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Minimum U: " << this->MinimumU << "\n"; + os << indent << "Maximum U: " << this->MaximumU << "\n"; + + os << indent << "Minimum V: " << this->MinimumV << "\n"; + os << indent << "Maximum V: " << this->MaximumV << "\n"; + + os << indent << "Minimum W: " << this->MinimumW << "\n"; + os << indent << "Maximum W: " << this->MaximumW << "\n"; + + os << indent << "JoinU: " << this->JoinU << "\n"; + os << indent << "JoinV: " << this->JoinV << "\n"; + os << indent << "JoinW: " << this->JoinV << "\n"; + + os << indent << "TwistU: " << this->TwistU << "\n"; + os << indent << "TwistV: " << this->TwistV << "\n"; + os << indent << "TwistW: " << this->TwistV << "\n"; + + os << indent << "ClockwiseOrdering: " << this->ClockwiseOrdering << "\n"; + os << indent << "Derivatives Available: " << this->DerivativesAvailable << "\n"; +} diff --git a/Common/vtkParametricFunction.h b/Common/vtkParametricFunction.h new file mode 100644 index 0000000..905af5c --- /dev/null +++ b/Common/vtkParametricFunction.h @@ -0,0 +1,203 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricFunction - abstract interface for parametric functions +// .SECTION Description +// vtkParametricFunction is an abstract interface for functions +// defined by parametric mapping i.e. f(u,v,w)->(x,y,z) where +// u_min <= u < u_max, v_min <= v < v_max, w_min <= w < w_max. (For +// notational convenience, we will write f(u)->x and assume that +// u means (u,v,w) and x means (x,y,z).) +// +// The interface contains the pure virtual function, Evaluate(), that +// generates a point and the derivatives at that point which are then used to +// construct the surface. A second pure virtual function, EvaluateScalar(), +// can be used to generate a scalar for the surface. Finally, the +// GetDimension() virtual function is used to differentiate 1D, 2D, and 3D +// parametric functions. Since this abstract class defines a pure virtual +// API, its subclasses must implement the pure virtual functions +// GetDimension(), Evaluate() and EvaluateScalar(). +// +// This class has also methods for defining a range of parametric values (u,v,w). +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +// .SECTION See Also +// vtkParametricFunctionSource - tessellates a parametric function +// +// Implementations of derived classes implementing non-orentable surfaces: +// vtkParametricBoy vtkParametricCrossCap vtkParametricFigure8Klein +// vtkParametricKlein vtkParametricMobius vtkParametricRoman +// +// Implementations of derived classes implementing orientable surfaces: +// vtkParametricConicSpiral vtkParametricDini vtkParametricEllipsoid +// vtkParametricEnneper vtkParametricRandomHills vtkParametricSuperEllipsoid +// vtkParametricSuperToroid vtkParametricTorus +// +#ifndef __vtkParametricFunction_h +#define __vtkParametricFunction_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkParametricFunction : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkParametricFunction, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Return the dimension of parametric space. Depending on the dimension, + // then the (u,v,w) parameters and associated information (e.g., derivates) + // have meaning. For example, if the dimension of the function is one, then + // u[0] and Duvw[0...2] have meaning. + // This is a pure virtual function that must be instantiated in + // a derived class. + virtual int GetDimension() = 0; + + // Description: + // Performs the mapping \$f(uvw)->(Pt,Duvw)\$f. + // This is a pure virtual function that must be instantiated in + // a derived class. + // + // uvw are the parameters, with u corresponding to uvw[0], + // v to uvw[1] and w to uvw[2] respectively. Pt is the returned Cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Note that the first three values in Duvw are Du, the next three are Dv, + // and the final three are Dw. Du Dv Dw are the partial derivatives of the + // function at the point Pt with respect to u, v and w respectively. + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]) = 0; + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // This is a pure virtual function that must be instantiated in + // a derived class. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v, and w. + // Pt, Duvw are obtained from Evaluate(). + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]) = 0; + + // Description: + // Set/Get the minimum u-value. + vtkSetMacro(MinimumU,double); + vtkGetMacro(MinimumU,double); + + // Description: + // Set/Get the maximum u-value. + vtkSetMacro(MaximumU,double); + vtkGetMacro(MaximumU,double); + + // Description: + // Set/Get the minimum v-value. + vtkSetMacro(MinimumV,double); + vtkGetMacro(MinimumV,double); + + // Description: + // Set/Get the maximum v-value. + vtkSetMacro(MaximumV,double); + vtkGetMacro(MaximumV,double); + + // Description: + // Set/Get the minimum w-value. + vtkSetMacro(MinimumW,double); + vtkGetMacro(MinimumW,double); + + // Description: + // Set/Get the maximum w-value. + vtkSetMacro(MaximumW,double); + vtkGetMacro(MaximumW,double); + + // Description: + // Set/Get the flag which joins the first triangle strip to the last one. + vtkSetMacro(JoinU,int); + vtkGetMacro(JoinU,int); + vtkBooleanMacro(JoinU,int); + + // Description: + // Set/Get the flag which joins the the ends of the triangle strips. + vtkSetMacro(JoinV,int); + vtkGetMacro(JoinV,int); + vtkBooleanMacro(JoinV,int); + + // Description: + // Set/Get the flag which joins the first triangle strip to + // the last one with a twist. + // JoinU must also be set if this is set. Used when building + // some non-orientable surfaces. + vtkSetMacro(TwistU,int); + vtkGetMacro(TwistU,int); + vtkBooleanMacro(TwistU,int); + + // Description: + // Set/Get the flag which joins the ends of the + // triangle strips with a twist. + // JoinV must also be set if this is set. Used when building + // some non-orientable surfaces. + vtkSetMacro(TwistV,int); + vtkGetMacro(TwistV,int); + vtkBooleanMacro(TwistV,int); + + // Description: + // Set/Get the flag which determines the ordering of the the + // vertices forming the triangle strips. The ordering of the + // points being inserted into the triangle strip is important + // because it determines the direction of the normals for the + // lighting. If set, the ordering is clockwise, otherwise the + // ordering is anti-clockwise. Default is true (i.e. clockwise + // ordering). + vtkSetMacro(ClockwiseOrdering,int); + vtkGetMacro(ClockwiseOrdering,int); + vtkBooleanMacro(ClockwiseOrdering,int); + + // Description: + // Set/Get the flag which determines whether derivatives are available + // from the parametric function (i.e., whether the Evaluate() method + // returns valid derivatives). + vtkSetMacro(DerivativesAvailable,int); + vtkGetMacro(DerivativesAvailable,int); + vtkBooleanMacro(DerivativesAvailable,int); + +protected: + vtkParametricFunction(); + virtual ~vtkParametricFunction(); + + // Variables + double MinimumU; + double MaximumU; + double MinimumV; + double MaximumV; + double MinimumW; + double MaximumW; + + int JoinU; + int JoinV; + int JoinW; + + int TwistU; + int TwistV; + int TwistW; + + int ClockwiseOrdering; + + int DerivativesAvailable; + +private: + vtkParametricFunction(const vtkParametricFunction&); // Not implemented. + void operator=(const vtkParametricFunction&); // Not implemented. + +}; + +#endif diff --git a/Common/vtkParametricKlein.cxx b/Common/vtkParametricKlein.cxx new file mode 100644 index 0000000..260d7ef --- /dev/null +++ b/Common/vtkParametricKlein.cxx @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricKlein.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricKlein.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricKlein, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkParametricKlein); + +//---------------------------------------------------------------------------- +vtkParametricKlein::vtkParametricKlein() +{ + // Preset triangulation parameters + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = vtkMath::Pi(); + this->MaximumV = 2.0 * vtkMath::Pi(); + + this->JoinU = 0; + this->JoinV = 1; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; +} + +//---------------------------------------------------------------------------- +vtkParametricKlein::~vtkParametricKlein() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricKlein::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double cu = cos(u); + double su = sin(u); + double cv = cos(v); + double sv = sin(v); + + double subX = 3*cv+5*su*cv*cu-30*su-60*su*pow(cu,6) + +90*su*pow(cu,4); + double subY = 80*cv*pow(cu,7)*su+48*cv*pow(cu,6) + -80*cv*pow(cu,5)*su + -48*cv*pow(cu,4)-5*cv*pow(cu,3)*su-3*cv*pow(cu,2)+ + 5*su*cv*cu+3*cv-60*su; + double subZ = 3+5*su*cu; + + // The point + Pt[0] = -2.0/15.0*cu*subX; + Pt[1] = -1.0/15.0*su*subY; + Pt[2] = 2.0/15.0*sv*subZ; + + // The derivatives + Du[0] = 2.0/15.0*su*subX -2.0/15.0*cu*(5.0*cv*pow(cu,2) + -5.0*pow(su,2)*cv-30.0*cu-60.0*pow(cu,7) + +360.0*pow(su,2)*pow(cu,5) + +90.0*pow(cu,5)-360.0*pow(su,2)*pow(cu,3)); + Dv[0] = -2.0/15.0*cu*(-3.0*sv-5.0*su*sv*cu); + Du[1] = -1.0/15.0*cu*subY-1.0/15.0*su*( + -560.0*cv*pow(cu,6)*pow(su,2) + +80.0*cv*pow(cu,8)-288*cv*pow(cu,5)*su+ + 400*cv*pow(cu,4)*pow(su,2) + -80.0*cv*pow(cu,6)+192*cv*pow(cu,3)*su + +15.0*pow(su,2)*cv*pow(cu,2) + -5.0*cv*pow(cu,4)+6.0*su*cv*cu+5.0*cv*pow(cu,2) + -5.0*pow(su,2)*cv-60.0*cu); + Dv[1] = -1.0/15.0*su*(-80.0*sv*pow(cu,7)*su-48.0*sv*pow(cu,6) + +80.0*sv*pow(cu,5)*su+48.0*sv*pow(cu,4)+5.0*sv*pow(cu,3)*su + +3.0*sv*pow(cu,2)-5.0*su*sv*cu-3.0*sv); + Du[2] = 2.0/15.0*sv*(5.0*pow(cu,2)-5.0*pow(su,2)); + Dv[2] = 2.0/15.0*cv*subZ; +} + +//---------------------------------------------------------------------------- +double vtkParametricKlein::EvaluateScalar(double*, double*, double*) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricKlein::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Common/vtkParametricKlein.h b/Common/vtkParametricKlein.h new file mode 100644 index 0000000..5da2f77 --- /dev/null +++ b/Common/vtkParametricKlein.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricKlein.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricKlein - Generates a "classical" representation of a Klein bottle. +// .SECTION Description +// vtkParametricKlein generates a "classical" representation of a Klein +// bottle. A Klein bottle is a closed surface with no interior and only one +// surface. It is unrealisable in 3 dimensions without intersecting +// surfaces. It can be +// realised in 4 dimensions by considering the map \f$F:R^2 \rightarrow R^4\f$ given by: +// +// - \f$f(u,v) = ((r*cos(v)+a)*cos(u),(r*cos(v)+a)*sin(u),r*sin(v)*cos(u/2),r*sin(v)*sin(u/2))\f$ +// +// The classical representation of the immersion in \f$R^3\f$ is returned by this function. +// +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +#ifndef __vtkParametricKlein_h +#define __vtkParametricKlein_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricKlein : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricKlein,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a Klein Bottle with the following parameters: + // MinimumU = 0, MaximumU = 2*Pi, + // MinimumV = -Pi, MaximumV = Pi, + // JoinU = 0, JoinV = 1, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + static vtkParametricKlein *New(); //! Initialise the parameters for the Klein bottle + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // A Klein bottle. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricKlein(); + ~vtkParametricKlein(); + +private: + vtkParametricKlein(const vtkParametricKlein&); // Not implemented. + void operator=(const vtkParametricKlein&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricMobius.cxx b/Common/vtkParametricMobius.cxx new file mode 100644 index 0000000..3096385 --- /dev/null +++ b/Common/vtkParametricMobius.cxx @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricMobius.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricMobius.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricMobius, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkParametricMobius); + +//---------------------------------------------------------------------------- +vtkParametricMobius::vtkParametricMobius() +{ + this->MinimumU = 0; + this->MinimumV = -1; + this->MaximumU = 2 * vtkMath::Pi(); + this->MaximumV = 1; + + this->JoinU = 1; + this->JoinV = 0; + this->TwistU = 1; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; + + this->Radius = 1; +} + +//---------------------------------------------------------------------------- +vtkParametricMobius::~vtkParametricMobius() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricMobius::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw+3; + + double cu = cos(u); + double cu2 = cos( u / 2 ); + double su = sin(u); + double su2 = sin( u / 2 ); + double t = this->Radius - v * su2; + + // The point + Pt[0] = t * su; + Pt[1] = t * cu; + Pt[2] = v * cu2; + + //The derivatives are: + Du[0] = -v*cu2*su/2+Pt[1]; + Du[1] = -v*cu2*cu/2-Pt[0]; + Du[2] = -v*su2/2; + Dv[0] = -su2*su; + Dv[1] = -su2*cu; + Dv[2] = cu2; +} + +//---------------------------------------------------------------------------- +double vtkParametricMobius::EvaluateScalar(double *, double*, double *) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricMobius::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Radius: " << this->Radius << "\n"; +} diff --git a/Common/vtkParametricMobius.h b/Common/vtkParametricMobius.h new file mode 100644 index 0000000..4a95df8 --- /dev/null +++ b/Common/vtkParametricMobius.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricMobius.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricMobius - Generate a Mobius strip. +// .SECTION Description +// vtkParametricMobius generates a Mobius strip. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +#ifndef __vtkParametricMobius_h +#define __vtkParametricMobius_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricMobius : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricMobius,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a Mobius strip with the following parameters: + // MinimumU = 0, MaximumU = 2*Pi, + // MinimumV = -1, MaximumV = 1, + // JoinU = 1, JoinV = 0, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + // Radius = 1. + static vtkParametricMobius *New(); + + // Description: + // Set/Get the radius of the Mobius strip. + vtkSetMacro(Radius,double); + vtkGetMacro(Radius,double); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // The Mobius strip. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Du, Dv are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricMobius(); + ~vtkParametricMobius(); + + // Variables + double Radius; + +private: + vtkParametricMobius(const vtkParametricMobius&); // Not implemented. + void operator=(const vtkParametricMobius&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricRandomHills.cxx b/Common/vtkParametricRandomHills.cxx new file mode 100644 index 0000000..496bbff --- /dev/null +++ b/Common/vtkParametricRandomHills.cxx @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricRandomHills.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricRandomHills.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include "vtkDoubleArray.h" + +#include + +vtkCxxRevisionMacro(vtkParametricRandomHills, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkParametricRandomHills); + +//---------------------------------------------------------------------------- +vtkParametricRandomHills::vtkParametricRandomHills() : + NumberOfHills(30) + , HillXVariance(2.5) + , HillYVariance(2.5) + , HillAmplitude(2) + , RandomSeed(1) + , XVarianceScaleFactor(1.0/3.0) + , YVarianceScaleFactor(1.0/3.0) + , AmplitudeScaleFactor(1.0/3.0) + , AllowRandomGeneration(1) +{ + // Preset triangulation parameters + this->MinimumU = -10; + this->MinimumV = -10; + this->MaximumU = 10; + this->MaximumV = 10; + + this->JoinU = 0; + this->JoinV = 0; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 0; + + this->hillData = vtkDoubleArray::New(); + + GenerateTheHills(); +} + +//---------------------------------------------------------------------------- +vtkParametricRandomHills::~vtkParametricRandomHills() +{ + this->hillData->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkParametricRandomHills::InitSeed ( int randomSeed ) +{ + if ( randomSeed < 0 ) + { + randomSeed = (int)time( NULL ); + } + srand( (unsigned int) randomSeed ); +} + +//---------------------------------------------------------------------------- +double vtkParametricRandomHills::Rand ( void ) +{ + return double(rand())/double(RAND_MAX); +} + +//---------------------------------------------------------------------------- +void vtkParametricRandomHills::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + // Zero out the point and derivatives. + for ( int i = 0; i < 3; ++i ) + Pt[i] = Du[i] = Dv[i] = 0; + + // The point + // The height of the surface is made up from + // the contributions from all the Hills. + Pt[0] = u; + Pt[1] = this->MaximumV - v; // Texturing is oriented OK if we do this. + double hillTuple[5]; // 0: mX, 1: mY, 2: VarX, 3: VarY, 4: Amplitude + for ( int j = 0; j < NumberOfHills; ++j ) + { + this->hillData->GetTuple(j,hillTuple); + double x = (u - hillTuple[0])/hillTuple[2]; + double y = (v - hillTuple[1])/hillTuple[3]; + Pt[2] += hillTuple[4] * exp( -(x*x+y*y) / 2.0 ); + } +} + +//---------------------------------------------------------------------------- +double vtkParametricRandomHills::EvaluateScalar(double* vtkNotUsed(uv[3]), + double* vtkNotUsed(Pt[3]), + double* vtkNotUsed(Duv[9])) +{ + return 0; +} + +void vtkParametricRandomHills::GenerateTheHills( void ) +{ + this->hillData->Initialize(); + this->hillData->SetNumberOfComponents(5); + this->hillData->SetNumberOfTuples(NumberOfHills); + + double hillTuple[5]; // 0: mX, 1: mY, 2: VarX, 3: VarY, 4: Amplitude + // Generate the centers of the Hills, standard deviations and amplitudes. + if ( AllowRandomGeneration != 0 ) + { + InitSeed(this->RandomSeed); + for ( int i = 0; i < this->NumberOfHills; ++ i ) + { + hillTuple[0] = MinimumU + Rand() * (MaximumU - MinimumU); + hillTuple[1] = MinimumV + Rand() * (MaximumV - MinimumV); + hillTuple[2] = this->HillXVariance * Rand() + this->HillXVariance * this->XVarianceScaleFactor; + hillTuple[3] = this->HillYVariance * Rand() + this->HillYVariance * this->YVarianceScaleFactor; + hillTuple[4] = this->HillAmplitude * Rand() + this->HillAmplitude * this->AmplitudeScaleFactor; + this->hillData->SetTuple(i,hillTuple); + } + } + else + { + // Here the generation is nonrandom. + // We put hills in a regular grid over the whole surface. + double randVal = 0.1; + double gridMax = sqrt((double)this->NumberOfHills); + int counter = 0; + + double midU = (MaximumU - MinimumU)/2.0; + double shiftU = midU / gridMax; + double midV = (MaximumV - MinimumV)/2.0; + double shiftV = midV / gridMax; + + hillTuple[2] = this->HillXVariance * randVal + this->HillXVariance * this->XVarianceScaleFactor; + hillTuple[3] = this->HillYVariance * randVal + this->HillYVariance * this->YVarianceScaleFactor; + hillTuple[4] = this->HillAmplitude * randVal * 2.0 + this->HillAmplitude * this->AmplitudeScaleFactor; + + for ( int i = 0; i < (int)gridMax; ++i ) + { + hillTuple[0] = MinimumU + shiftU + (i / gridMax) * (MaximumU - MinimumU); + for ( int j = 0; j < (int)gridMax; ++j ) + { + hillTuple[1] = MinimumV + shiftV + (j / gridMax) * (MaximumV - MinimumV); + this->hillData->SetTuple(counter,hillTuple); + ++counter; + } + } + // If the number of hills is not a perfect square, set the amplitude contribution + // from the rest of the hills to zero. + hillTuple[4] = 0; + for ( int k = counter; k < this->NumberOfHills; ++ k ) + { + hillTuple[0] = MinimumU + midU; + hillTuple[1] = MinimumV + midV; + this->hillData->SetTuple(k,hillTuple); + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkParametricRandomHills::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Hills: " << this->NumberOfHills << "\n"; + os << indent << "Hill variance x-direction: " << this->HillXVariance << "\n"; + os << indent << "Hill variance x-direction scaling factor: " << this->XVarianceScaleFactor << "\n"; + os << indent << "Hill variance y-direction: " << this->HillYVariance << "\n"; + os << indent << "Hill variance y-direction scaling factor: " << this->YVarianceScaleFactor << "\n"; + os << indent << "Hill amplitude (height): " << this->HillAmplitude << "\n"; + os << indent << "Amplitude scaling factor: " << this->AmplitudeScaleFactor << "\n"; + os << indent << "Random number generator seed: " << this->RandomSeed << "\n"; + os << indent << "Allow random generation: " << this->AllowRandomGeneration << "\n"; +} diff --git a/Common/vtkParametricRandomHills.h b/Common/vtkParametricRandomHills.h new file mode 100644 index 0000000..5d84b9c --- /dev/null +++ b/Common/vtkParametricRandomHills.h @@ -0,0 +1,192 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricRandomHills.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricRandomHills - Generate a surface covered with randomly placed hills. +// .SECTION Description +// vtkParametricRandomHills generates a surface covered with randomly placed hills. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for +// creating and contributing the class. +// +#ifndef __vtkParametricRandomHills_h +#define __vtkParametricRandomHills_h + +#include "vtkParametricFunction.h" + +class vtkDoubleArray; + +class VTK_COMMON_EXPORT vtkParametricRandomHills : public vtkParametricFunction +{ + +public: + vtkTypeRevisionMacro(vtkParametricRandomHills,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Construct a surface of random hills with the following parameters: + // MinimumU = -10, MaximumU = 10, + // MinimumV = -10, MaximumV = 10, + // JoinU = 0, JoinV = 0, + // TwistU = 0, TwistV = 0; + // ClockwiseOrdering = 1, + // DerivativesAvailable = 0, + // Number of hills = 30, + // Variance of the hills 2.5 in both x- and y- directions, + // Scaling factor for the variances 1/3 in both x- and y- directions, + // Amplitude of each hill = 1, + // Scaling factor for the amplitude = 1/3, + // RandomSeed = 1, + // AllowRandomGeneration = 1. + static vtkParametricRandomHills *New(); + + // Description: + // Set/Get the number of hills. + // Default is 30. + vtkSetMacro(NumberOfHills,int); + vtkGetMacro(NumberOfHills,int); + + // Description: + // Set/Get the hill variance in the x-direction. + // Default is 2.5. + vtkSetMacro(HillXVariance,double); + vtkGetMacro(HillXVariance,double); + + // Description: + // Set/Get the hill variance in the y-direction. + // Default is 2.5. + vtkSetMacro(HillYVariance,double); + vtkGetMacro(HillYVariance,double); + + // Description: + // Set/Get the hill amplitude (height). + // Default is 2. + vtkSetMacro(HillAmplitude,double); + vtkGetMacro(HillAmplitude,double); + + // Description: + // Set/Get the Seed for the random number generator, + // a value of 1 will initialize the random number generator, + // a negative value will initialize it with the system time. + // Default is 1. + vtkSetMacro(RandomSeed,int); + vtkGetMacro(RandomSeed,int); + + // Description: + // Set/Get the random generation flag. + // A value of 0 will disable the generation of random hills on the surface. + // This allows a reproducible shape to be generated. + // Any other value means that the generation of the hills will be done + // randomly. + // Default is 1. + vtkSetMacro(AllowRandomGeneration,int); + vtkGetMacro(AllowRandomGeneration,int); + vtkBooleanMacro(AllowRandomGeneration,int); + + // Description: + // Set/Get the scaling factor for the variance in the x-direction. + // Default is 1/3. + vtkSetMacro(XVarianceScaleFactor,double); + vtkGetMacro(XVarianceScaleFactor,double); + + // Description: + // Set/Get the scaling factor for the variance in the y-direction. + // Default is 1/3. + vtkSetMacro(YVarianceScaleFactor,double); + vtkGetMacro(YVarianceScaleFactor,double); + + // Description: + // Set/Get the scaling factor for the amplitude. + // Default is 1/3. + vtkSetMacro(AmplitudeScaleFactor,double); + vtkGetMacro(AmplitudeScaleFactor,double); + + // Description: + // Generate the centers of the hills, their standard deviations and + // their amplitudes. This function creates a series of vectors representing + // the u, v coordinates of each hill, its variance in the u, v directions and + // the amplitude. + // + // NOTE: This function must be called whenever any of the parameters are changed. + void GenerateTheHills( void ); + + // Description: + // Construct a terrain consisting of randomly placed hills on a surface. + // + // It is assumed that the function GenerateTheHills() has been executed + // to build the vectors of coordinates required to generate the point Pt. + // Pt represents the sum of all the amplitudes over the space. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the Cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricRandomHills(); + ~vtkParametricRandomHills(); + + // Variables + int NumberOfHills; + double HillXVariance; + double HillYVariance; + double HillAmplitude; + int RandomSeed; + double XVarianceScaleFactor; + double YVarianceScaleFactor; + double AmplitudeScaleFactor; + int AllowRandomGeneration; + +private: + vtkParametricRandomHills(const vtkParametricRandomHills&); // Not implemented. + void operator=(const vtkParametricRandomHills&); // Not implemented. + + // Description: + // Initialise the random number generator. + void InitSeed ( int RandomSeed ); + + // Description: + // Return a random number between 0 and 1. + double Rand ( void ); + + // Description: + // Center (x,y), variances (x,y) and amplitudes of the hills. + vtkDoubleArray * hillData; +}; + +#endif diff --git a/Common/vtkParametricRoman.cxx b/Common/vtkParametricRoman.cxx new file mode 100644 index 0000000..9b7b8cd --- /dev/null +++ b/Common/vtkParametricRoman.cxx @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricRoman.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricRoman.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricRoman, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkParametricRoman); + +//---------------------------------------------------------------------------- +vtkParametricRoman::vtkParametricRoman(): + Radius(1) +{ + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = vtkMath::Pi(); + this->MaximumV = vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 1; + this->TwistU = 1; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; +} + +//---------------------------------------------------------------------------- +vtkParametricRoman::~vtkParametricRoman() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricRoman::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double cu = cos(u); + double c2u = cos(2.0*u); + double su = sin(u); + double s2u = sin(2.0*u); + double cv = cos(v); + double cv2 = cv*cv; + double c2v = cos(2.0*v); + double s2v = sin(2.0*v); + double sv = sin(v); + double a2 = this->Radius*this->Radius; + + // The point + Pt[0] = a2*cv2*s2u/2.0; + Pt[1] = a2*su*s2v/2.0; + Pt[2] = a2*cu*s2v/2.0; + + //The derivatives are: + Du[0] = a2*cv2*c2u; + Du[1] = a2*cu*s2v/2.0; + Du[2] = -a2*su*s2v/2.0; + Dv[0] = -a2*cv*s2u*sv; + Dv[1] = a2*su*c2v; + Dv[2] = a2*cu*c2v; +} + +//---------------------------------------------------------------------------- +double vtkParametricRoman::EvaluateScalar(double* vtkNotUsed(uv[3]), + double* vtkNotUsed(Pt[3]), + double* vtkNotUsed(Duv[9])) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricRoman::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Radius: " << this->Radius << "\n"; + +} diff --git a/Common/vtkParametricRoman.h b/Common/vtkParametricRoman.h new file mode 100644 index 0000000..b46eb45 --- /dev/null +++ b/Common/vtkParametricRoman.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricRoman.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricRoman - Generate Steiner's Roman Surface. +// .SECTION Description +// vtkParametricRoman generates Steiner's Roman Surface. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for +// creating and contributing the class. +// +#ifndef __vtkParametricRoman_h +#define __vtkParametricRoman_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricRoman : public vtkParametricFunction +{ + +public: + vtkTypeRevisionMacro(vtkParametricRoman,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Construct Steiner's Roman Surface with the following parameters: + // MinimumU = 0, MaximumU = Pi, + // MinimumV = 0, MaximumV = Pi, + // JoinU = 1, JoinV = 1, + // TwistU = 1, TwistV = 0; + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + // Radius = 1 + static vtkParametricRoman *New(); + + // Description: + // Set/Get the radius. + vtkSetMacro(Radius,double); + vtkGetMacro(Radius,double); + + // Description: + // Steiner's Roman Surface + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the Cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + + +protected: + vtkParametricRoman(); + ~vtkParametricRoman(); + + // Variables + double Radius; + +private: + vtkParametricRoman(const vtkParametricRoman&); // Not implemented. + void operator=(const vtkParametricRoman&); // Not implemented. +}; + +#endif diff --git a/Common/vtkParametricSuperEllipsoid.cxx b/Common/vtkParametricSuperEllipsoid.cxx new file mode 100644 index 0000000..1fa7bfc --- /dev/null +++ b/Common/vtkParametricSuperEllipsoid.cxx @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricSuperEllipsoid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricSuperEllipsoid.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include + +vtkCxxRevisionMacro(vtkParametricSuperEllipsoid, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkParametricSuperEllipsoid); + +//---------------------------------------------------------------------------- +vtkParametricSuperEllipsoid::vtkParametricSuperEllipsoid() : + XRadius(1) + , YRadius(1) + , ZRadius(1) + , N1(1) + , N2(1) +{ + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumV = vtkMath::Pi(); + this->MaximumU = 2.0*vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 0; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 0; +} + +//---------------------------------------------------------------------------- +vtkParametricSuperEllipsoid::~vtkParametricSuperEllipsoid() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricSuperEllipsoid::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + for ( int i = 0; i < 3; ++i) + { + Pt[i] = Du[i] = Dv[i] = 0; + } + + double cu = cos(u); + double su = sin(u); + double cv = cos(v); + double sv = sin(v); + + double tmp = this->Power(sv,N1); + + // The point + Pt[0] = this->XRadius * tmp * this->Power(cu,this->N2); + Pt[1] = this->YRadius * tmp * this->Power(su,this->N2); + Pt[2] = this->ZRadius * this->Power(cv,this->N1); +} + +//---------------------------------------------------------------------------- +double vtkParametricSuperEllipsoid::EvaluateScalar(double*, double*, double*) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricSuperEllipsoid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "X scale factor: " << this->XRadius << "\n"; + os << indent << "Y scale factor: " << this->YRadius << "\n"; + os << indent << "Z scale factor: " << this->ZRadius << "\n"; + os << indent << "Squareness in the z-axis: " << this->N1 << "\n"; + os << indent << "Squareness in the x-y plane: " << this->N2 << "\n"; +} + +//---------------------------------------------------------------------------- +double vtkParametricSuperEllipsoid::Power ( double x, double n ) +{ + if ( x == 0 ) + { + return 0; + } + else if ( x < 0 ) + { + return -pow(-x,n); + } + else + { + return pow(x,n); + } +} diff --git a/Common/vtkParametricSuperEllipsoid.h b/Common/vtkParametricSuperEllipsoid.h new file mode 100644 index 0000000..b0152ed --- /dev/null +++ b/Common/vtkParametricSuperEllipsoid.h @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricSuperEllipsoid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricSuperEllipsoid - Generate a superellipsoid. +// .SECTION Description +// vtkParametricSuperEllipsoid generates a superellipsoid. A superellipsoid +// is a versatile primitive that is controlled by two parameters n1 and +// n2. As special cases it can represent a sphere, square box, and closed +// cylindrical can. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// Also see: http://astronomy.swin.edu.au/~pbourke/surfaces/ +// +// .SECTION Caveats +// Care needs to be taken specifying the bounds correctly. You may need to +// carefully adjust MinimumU, MinimumV, MaximumU, MaximumV. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +#ifndef __vtkParametricSuperEllipsoid_h +#define __vtkParametricSuperEllipsoid_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricSuperEllipsoid : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricSuperEllipsoid,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a superellipsoid with the following parameters: + // MinimumU = 0, MaximumU = 2*Pi, + // MinimumV = 0, MaximumV = Pi, + // JoinU = 1, JoinV = 0, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 0, + // N1 = 1, N2 = 1, XRadius = 1, YRadius = 1, + // ZRadius = 1, a sphere in this case. + static vtkParametricSuperEllipsoid *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Set/Get the scaling factor for the x-axis. Default = 1. + vtkSetMacro(XRadius,double); + vtkGetMacro(XRadius,double); + + // Description: + // Set/Get the scaling factor for the y-axis. Default = 1. + vtkSetMacro(YRadius,double); + vtkGetMacro(YRadius,double); + + // Description: + // Set/Get the scaling factor for the z-axis. Default = 1. + vtkSetMacro(ZRadius,double); + vtkGetMacro(ZRadius,double); + + // Description: + // Set/Get the "squareness" parameter in the z axis. Default = 1. + vtkSetMacro(N1,double); + vtkGetMacro(N1,double); + + // Description: + // Set/Get the "squareness" parameter in the x-y plane. Default = 1. + vtkSetMacro(N2,double); + vtkGetMacro(N2,double); + + // Description: + // A superellipsoid. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricSuperEllipsoid(); + ~vtkParametricSuperEllipsoid(); + + // Variables + double XRadius; + double YRadius; + double ZRadius; + double N1; + double N2; + +private: + vtkParametricSuperEllipsoid(const vtkParametricSuperEllipsoid&); // Not implemented. + void operator=(const vtkParametricSuperEllipsoid&); // Not implemented. + + // Description: + // Calculate sign(x)*(abs(x)^n). + double Power ( double x, double n ); + +}; + +#endif diff --git a/Common/vtkParametricSuperToroid.cxx b/Common/vtkParametricSuperToroid.cxx new file mode 100644 index 0000000..9ca157b --- /dev/null +++ b/Common/vtkParametricSuperToroid.cxx @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricSuperToroid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricSuperToroid.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include + +vtkCxxRevisionMacro(vtkParametricSuperToroid, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkParametricSuperToroid); + +//---------------------------------------------------------------------------- +vtkParametricSuperToroid::vtkParametricSuperToroid() : + RingRadius(1) + , CrossSectionRadius(0.5) + , XRadius(1) + , YRadius(1) + , ZRadius(1) + , N1(1) + , N2(1) +{ + // Preset triangulation parameters + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = 2.0 * vtkMath::Pi(); + this->MaximumV = 2.0 * vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 1; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 0; +} + +//---------------------------------------------------------------------------- +vtkParametricSuperToroid::~vtkParametricSuperToroid() +{ +} + + +//---------------------------------------------------------------------------- +void vtkParametricSuperToroid::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + for ( int i = 0; i < 3; ++i) + { + Pt[i] = Du[i] = Dv[i] = 0; + } + + double cu = cos(u); + double su = sin(u); + double cv = cos(v); + double sv = sin(v); + + double tmp = this->RingRadius + this->CrossSectionRadius * this->Power(cv,this->N2); + + // The point + Pt[0] = this->XRadius * tmp * this->Power(cu,this->N1); + Pt[1] = this->YRadius * tmp * this->Power(su,this->N1); + Pt[2] = this->ZRadius * this->CrossSectionRadius * this->Power(sv,this->N2); +} + +//---------------------------------------------------------------------------- +double vtkParametricSuperToroid::EvaluateScalar(double*, double*, double*) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricSuperToroid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Ring radius: " << this->RingRadius << "\n"; + os << indent << "Cross-sectional radius: " << this->CrossSectionRadius << "\n"; + os << indent << "Squareness in the z-axis: " << this->N1 << "\n"; + os << indent << "Squareness in the x-y plane: " << this->N2 << "\n"; + os << indent << "X scale factor: " << this->XRadius << "\n"; + os << indent << "Y scale factor: " << this->YRadius << "\n"; + os << indent << "Z scale factor: " << this->ZRadius << "\n"; + +} + +//---------------------------------------------------------------------------- +double vtkParametricSuperToroid::Power ( double x, double n ) +{ + if ( x == 0 ) + { + return 0; + } + if ( x < 0 ) + { + return -pow(-x,n); + } + else + { + return pow(x,n); + } +} diff --git a/Common/vtkParametricSuperToroid.h b/Common/vtkParametricSuperToroid.h new file mode 100644 index 0000000..624857e --- /dev/null +++ b/Common/vtkParametricSuperToroid.h @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricSuperToroid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricSuperToroid - Generate a supertoroid. +// .SECTION Description +// vtkParametricSuperToroid generates a supertoroid. Essentially a +// supertoroid is a torus with the sine and cosine terms raised to a power. +// A supertoroid is a versatile primitive that is controlled by four +// parameters r0, r1, n1 and n2. r0, r1 determine the type of torus whilst +// the value of n1 determines the shape of the torus ring and n2 determines +// the shape of the cross section of the ring. It is the different values of +// these powers which give rise to a family of 3D shapes that are all +// basically toroidal in shape. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// Also see: http://astronomy.swin.edu.au/~pbourke/surfaces/. +// +// .SECTION Caveats +// Care needs to be taken specifying the bounds correctly. You may need to +// carefully adjust MinimumU, MinimumV, MaximumU, MaximumV. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +#ifndef __vtkParametricSuperToroid_h +#define __vtkParametricSuperToroid_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricSuperToroid : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricSuperToroid,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a supertoroid with the following parameters: + // MinimumU = 0, MaximumU = 2*Pi, + // MinimumV = 0, MaximumV = 2*Pi, + // JoinU = 1, JoinV = 1, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 0, + // RingRadius = 1, CrossSectionRadius = 0.5, + // N1 = 1, N2 = 1, XRadius = 1, + // YRadius = 1, ZRadius = 1, a torus in this case. + static vtkParametricSuperToroid *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // Set/Get the radius from the center to the middle of the ring of the + // supertoroid. Default = 1. + vtkSetMacro(RingRadius,double); + vtkGetMacro(RingRadius,double); + + // Description: + // Set/Get the radius of the cross section of ring of the supertoroid. + // Default = 0.5. + vtkSetMacro(CrossSectionRadius,double); + vtkGetMacro(CrossSectionRadius,double); + + // Description: + // Set/Get the scaling factor for the x-axis. Default = 1. + vtkSetMacro(XRadius,double); + vtkGetMacro(XRadius,double); + + // Description: + // Set/Get the scaling factor for the y-axis. Default = 1. + vtkSetMacro(YRadius,double); + vtkGetMacro(YRadius,double); + + // Description: + // Set/Get the scaling factor for the z-axis. Default = 1. + vtkSetMacro(ZRadius,double); + vtkGetMacro(ZRadius,double); + + // Description: + // Set/Get the shape of the torus ring. Default = 1. + vtkSetMacro(N1,double); + vtkGetMacro(N1,double); + + // Description: + // Set/Get the shape of the cross section of the ring. Default = 1. + vtkSetMacro(N2,double); + vtkGetMacro(N2,double); + + // Description: + // A supertoroid. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricSuperToroid(); + ~vtkParametricSuperToroid(); + + // Variables + double RingRadius; + double CrossSectionRadius; + double XRadius; + double YRadius; + double ZRadius; + double N1; + double N2; + +private: + vtkParametricSuperToroid(const vtkParametricSuperToroid&); // Not implemented. + void operator=(const vtkParametricSuperToroid&); // Not implemented. + + // Description: + // Calculate sign(x)*(abs(x)^n). + double Power ( double x, double n ); + +}; + +#endif + diff --git a/Common/vtkParametricTorus.cxx b/Common/vtkParametricTorus.cxx new file mode 100644 index 0000000..aec8481 --- /dev/null +++ b/Common/vtkParametricTorus.cxx @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricTorus.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricTorus.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricTorus, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkParametricTorus); + +//---------------------------------------------------------------------------- +vtkParametricTorus::vtkParametricTorus() : + RingRadius(1.0), CrossSectionRadius(0.5) +{ + this->MinimumU = 0; + this->MinimumV = 0; + this->MaximumU = 2 * vtkMath::Pi(); + this->MaximumV = 2 * vtkMath::Pi(); + + this->JoinU = 1; + this->JoinV = 1; + this->TwistU = 0; + this->TwistV = 0; + this->ClockwiseOrdering = 1; + this->DerivativesAvailable = 1; +} + +//---------------------------------------------------------------------------- +vtkParametricTorus::~vtkParametricTorus() +{ +} + +//---------------------------------------------------------------------------- +void vtkParametricTorus::Evaluate(double uvw[3], double Pt[3], double Duvw[9]) +{ + double u = uvw[0]; + double v = uvw[1]; + double *Du = Duvw; + double *Dv = Duvw + 3; + + double cu = cos(u); + double su = sin(u); + double cv = cos(v); + double sv = sin(v); + double t = this->RingRadius + this->CrossSectionRadius * cv; + + // The point + Pt[0] = t * cu; + Pt[1] = t * su; + Pt[2] = this->CrossSectionRadius * sv; + + //The derivatives are: + Du[0] = -t * su; + Du[1] = t * cu; + Du[2] = 0; + Dv[0] = -this->CrossSectionRadius * sv * cu; + Dv[1] = -this->CrossSectionRadius * sv * su; + Dv[2] = this->CrossSectionRadius * cv; +} + +//---------------------------------------------------------------------------- +double vtkParametricTorus::EvaluateScalar(double* vtkNotUsed(uv[3]), + double* vtkNotUsed(Pt[3]), + double* vtkNotUsed(Duv[9])) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkParametricTorus::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Ring Radius: " << this->RingRadius << "\n"; + os << indent << "Cross-Sectional Radius: " << this->CrossSectionRadius << "\n"; +} diff --git a/Common/vtkParametricTorus.h b/Common/vtkParametricTorus.h new file mode 100644 index 0000000..1c7b929 --- /dev/null +++ b/Common/vtkParametricTorus.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricTorus.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricTorus - Generate a torus. +// .SECTION Description +// vtkParametricTorus generates a torus. +// +// For further information about this surface, please consult the +// technical description "Parametric surfaces" in http://www.vtk.org/documents.php +// in the "VTK Technical Documents" section in the VTk.org web pages. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for +// creating and contributing the class. +// +#ifndef __vtkParametricTorus_h +#define __vtkParametricTorus_h + +#include "vtkParametricFunction.h" + +class VTK_COMMON_EXPORT vtkParametricTorus : public vtkParametricFunction +{ + +public: + vtkTypeRevisionMacro(vtkParametricTorus,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a torus with the following parameters: + // MinimumU = 0, MaximumU = 2*Pi, + // MinimumV = 0, MaximumV = 2*Pi, + // JoinU = 1, JoinV = 1, + // TwistU = 0, TwistV = 0, + // ClockwiseOrdering = 1, + // DerivativesAvailable = 1, + // RingRadius = 1, CrossSectionRadius = 0.5. + static vtkParametricTorus *New(); + + // Description: + // Set/Get the radius from the center to the middle of the ring of the + // torus. The default value is 1.0. + vtkSetMacro(RingRadius,double); + vtkGetMacro(RingRadius,double); + + // Description: + // Set/Get the radius of the cross section of ring of the torus. The default value + // is 0.5. + vtkSetMacro(CrossSectionRadius,double); + vtkGetMacro(CrossSectionRadius,double); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 2;} + + // Description: + // A torus. + // + // This function performs the mapping \f$f(u,v) \rightarrow (x,y,x)\f$, returning it + // as Pt. It also returns the partial derivatives Du and Dv. + // \f$Pt = (x, y, z), Du = (dx/du, dy/du, dz/du), Dv = (dx/dv, dy/dv, dz/dv)\f$ . + // Then the normal is \f$N = Du X Dv\f$ . + virtual void Evaluate(double uvw[3], double Pt[3], double Duvw[9]); + + // Description: + // Calculate a user defined scalar using one or all of uvw, Pt, Duvw. + // + // uvw are the parameters with Pt being the the Cartesian point, + // Duvw are the derivatives of this point with respect to u, v and w. + // Pt, Duvw are obtained from Evaluate(). + // + // This function is only called if the ScalarMode has the value + // vtkParametricFunctionSource::SCALAR_FUNCTION_DEFINED + // + // If the user does not need to calculate a scalar, then the + // instantiated function should return zero. + // + virtual double EvaluateScalar(double uvw[3], double Pt[3], double Duvw[9]); + +protected: + vtkParametricTorus(); + ~vtkParametricTorus(); + + // Variables + double RingRadius; + double CrossSectionRadius; + +private: + vtkParametricTorus(const vtkParametricTorus&); // Not implemented. + void operator=(const vtkParametricTorus&); // Not implemented. +}; + +#endif diff --git a/Common/vtkPerspectiveTransform.cxx b/Common/vtkPerspectiveTransform.cxx new file mode 100644 index 0000000..208de78 --- /dev/null +++ b/Common/vtkPerspectiveTransform.cxx @@ -0,0 +1,479 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPerspectiveTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPerspectiveTransform.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkPerspectiveTransform, "$Revision: 1.29 $"); +vtkStandardNewMacro(vtkPerspectiveTransform); + +//---------------------------------------------------------------------------- +vtkPerspectiveTransform::vtkPerspectiveTransform() +{ + this->Input = NULL; + + // most of the functionality is provided by the concatenation + this->Concatenation = vtkTransformConcatenation::New(); + + // the stack will be allocated the first time Push is called + this->Stack = NULL; +} + +//---------------------------------------------------------------------------- +vtkPerspectiveTransform::~vtkPerspectiveTransform() +{ + this->SetInput(NULL); + + if (this->Concatenation) + { + this->Concatenation->Delete(); + } + if (this->Stack) + { + this->Stack->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkPerspectiveTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Update(); + + this->Superclass::PrintSelf(os, indent); + os << indent << "Input: (" << this->Input << ")\n"; + os << indent << "InverseFlag: " << this->GetInverseFlag() << "\n"; + os << indent << "NumberOfConcatenatedTransforms: " << + this->GetNumberOfConcatenatedTransforms() << "\n"; + if (this->GetNumberOfConcatenatedTransforms() != 0) + { + int n = this->GetNumberOfConcatenatedTransforms(); + for (int i = 0; i < n; i++) + { + vtkHomogeneousTransform *t = this->GetConcatenatedTransform(i); + os << indent << " " << i << ": " << t->GetClassName() << " at " << + t << "\n"; + } + } +} + +//---------------------------------------------------------------------------- +void vtkPerspectiveTransform::Concatenate(vtkHomogeneousTransform *transform) +{ + if (transform->CircuitCheck(this)) + { + vtkErrorMacro("Concatenate: this would create a circular reference."); + return; + } + this->Concatenation->Concatenate(transform); + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkPerspectiveTransform::SetInput(vtkHomogeneousTransform *input) +{ + if (this->Input == input) + { + return; + } + if (input && input->CircuitCheck(this)) + { + vtkErrorMacro("SetInput: this would create a circular reference."); + return; + } + if (this->Input) + { + this->Input->Delete(); + } + this->Input = input; + if (this->Input) + { + this->Input->Register(this); + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +int vtkPerspectiveTransform::CircuitCheck(vtkAbstractTransform *transform) +{ + if (this->vtkHomogeneousTransform::CircuitCheck(transform) || + this->Input && this->Input->CircuitCheck(transform)) + { + return 1; + } + + int n = this->Concatenation->GetNumberOfTransforms(); + for (int i = 0; i < n; i++) + { + if (this->Concatenation->GetTransform(i)->CircuitCheck(transform)) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkPerspectiveTransform::MakeTransform() +{ + return vtkPerspectiveTransform::New(); +} + +//---------------------------------------------------------------------------- +unsigned long vtkPerspectiveTransform::GetMTime() +{ + unsigned long mtime = this->vtkHomogeneousTransform::GetMTime(); + unsigned long mtime2; + + if (this->Input) + { + mtime2 = this->Input->GetMTime(); + if (mtime2 > mtime) + { + mtime = mtime2; + } + } + mtime2 = this->Concatenation->GetMaxMTime(); + if (mtime2 > mtime) + { + return mtime2; + } + return mtime; +} + +//---------------------------------------------------------------------------- +void vtkPerspectiveTransform::InternalDeepCopy(vtkAbstractTransform *gtrans) +{ + vtkPerspectiveTransform *transform = (vtkPerspectiveTransform *)gtrans; + + // copy the input + this->SetInput(transform->Input); + + // copy the concatenation + this->Concatenation->DeepCopy(transform->Concatenation); + + // copy the stack + if (transform->Stack) + { + if (this->Stack == NULL) + { + this->Stack = vtkTransformConcatenationStack::New(); + } + this->Stack->DeepCopy(transform->Stack); + } + else + { + if (this->Stack) + { + this->Stack->Delete(); + this->Stack = NULL; + } + } + + // defer to superclass + this->vtkHomogeneousTransform::InternalDeepCopy(transform); +} + +//---------------------------------------------------------------------------- +void vtkPerspectiveTransform::InternalUpdate() +{ + // copy matrix from input + if (this->Input) + { + this->Matrix->DeepCopy(this->Input->GetMatrix()); + // if inverse flag is set, invert the matrix + if (this->Concatenation->GetInverseFlag()) + { + this->Matrix->Invert(); + } + } + else + // no input, start with identity + { + this->Matrix->Identity(); + } + + int i; + int nTransforms = this->Concatenation->GetNumberOfTransforms(); + int nPreTransforms = this->Concatenation->GetNumberOfPreTransforms(); + + // concatenate PreTransforms + for (i = nPreTransforms-1; i >= 0; i--) + { + vtkHomogeneousTransform *transform = + (vtkHomogeneousTransform *)this->Concatenation->GetTransform(i); + vtkMatrix4x4::Multiply4x4(this->Matrix,transform->GetMatrix(), + this->Matrix); + } + + // concatenate PostTransforms + for (i = nPreTransforms; i < nTransforms; i++) + { + vtkHomogeneousTransform *transform = + (vtkHomogeneousTransform *)this->Concatenation->GetTransform(i); + vtkMatrix4x4::Multiply4x4(transform->GetMatrix(),this->Matrix, + this->Matrix); + } +} + +//---------------------------------------------------------------------------- +// Utility for adjusting the window range to a new one. Usually the +// previous range was ([-1,+1],[-1,+1]) as per Ortho and Frustum, and you +// are mapping to the display coordinate range ([0,width-1],[0,height-1]). +void vtkPerspectiveTransform::AdjustViewport(double oldXMin, double oldXMax, + double oldYMin, double oldYMax, + double newXMin, double newXMax, + double newYMin, double newYMax) +{ + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + matrix[0][0] = (newXMax - newXMin)/(oldXMax - oldXMin); + matrix[1][1] = (newYMax - newYMin)/(oldYMax - oldYMin); + + matrix[0][3] = (newXMin*oldXMax - newXMax*oldXMin)/(oldXMax - oldXMin); + matrix[1][3] = (newYMin*oldYMax - newYMax*oldYMin)/(oldYMax - oldYMin); + + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +// Utility for adjusting the min/max range of the Z buffer. Usually +// the oldZMin, oldZMax are [-1,+1] as per Ortho and Frustum, and +// you are mapping the Z buffer to a new range. +void vtkPerspectiveTransform::AdjustZBuffer(double oldZMin, double oldZMax, + double newZMin, double newZMax) +{ + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + matrix[2][2] = (newZMax - newZMin)/(oldZMax - oldZMin); + matrix[2][3] = (newZMin*oldZMax - newZMax*oldZMin)/(oldZMax - oldZMin); + + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +// The orthographic perspective maps [xmin,xmax], [ymin,ymax], [-znear,-zfar] +// to [-1,+1], [-1,+1], [-1,+1]. +// From the OpenGL Programmer's guide, 2nd Ed. +void vtkPerspectiveTransform::Ortho(double xmin, double xmax, + double ymin, double ymax, + double znear, double zfar) +{ + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + matrix[0][0] = 2/(xmax - xmin); + matrix[1][1] = 2/(ymax - ymin); + matrix[2][2] = -2/(zfar - znear); + + matrix[0][3] = -(xmin + xmax)/(xmax - xmin); + matrix[1][3] = -(ymin + ymax)/(ymax - ymin); + matrix[2][3] = -(znear + zfar)/(zfar - znear); + + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +// The frustrum perspective maps a frustum with the front plane at -znear +// which has extent [xmin,xmax],[ymin,ymax] and a back plane at -zfar +// to [-1,+1], [-1,+1], [-1,+1]. +// From the OpenGL Programmer's guide, 2nd Ed. +void vtkPerspectiveTransform::Frustum(double xmin, double xmax, + double ymin, double ymax, + double znear, double zfar) +{ + double matrix[4][4]; + + matrix[0][0] = 2*znear/(xmax - xmin); + matrix[1][0] = 0; + matrix[2][0] = 0; + matrix[3][0] = 0; + + matrix[0][1] = 0; + matrix[1][1] = 2*znear/(ymax - ymin); + matrix[2][1] = 0; + matrix[3][1] = 0; + + matrix[0][2] = (xmin + xmax)/(xmax - xmin); + matrix[1][2] = (ymin + ymax)/(ymax - ymin); + matrix[2][2] = -(znear + zfar)/(zfar - znear); + matrix[3][2] = -1; + + matrix[0][3] = 0; + matrix[1][3] = 0; + matrix[2][3] = -2*znear*zfar/(zfar - znear); + matrix[3][3] = 0; + + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +// For convenience, an easy way to set up a symmetrical frustum. +void vtkPerspectiveTransform::Perspective(double angle, double aspect, + double znear, double zfar) +{ + double ymax = tan(angle*vtkMath::DoubleDegreesToRadians()/2)*znear; + double ymin = -ymax; + + double xmax = ymax*aspect; + double xmin = -xmax; + + this->Frustum(xmin, xmax, ymin, ymax, znear, zfar); +} + +//---------------------------------------------------------------------------- +// The Shear method can be used after Perspective to create correct +// perspective views for use with head-tracked stereo on a flat, fixed +// (i.e. not head-mounted) viewing screen. +// +// You must measure the eye position relative to the center of the +// RenderWindow (or the center of the screen, if the window is +// full-screen). The following applies: +x is 'right', +y is 'up', +// and zplane is the distance from screen to the eye. +// +// Here is some info on how to set this up properly: +// +// - Decide on a real-world-coords to virtual-world-coords conversion +// factor that is appropriate for the scene you are viewing. +// - The screen is the focal plane, the near clipping plane lies in +// front of the screen and far clipping plane lies behind. +// Measure the (x,y,z) displacent from the center of the screen to +// your eye. Scale these by the factor you chose. +// - After you have scaled x, y, and z call Shear(x/z,y/z,z). +// +// We're not done yet! +// +// - When you set up the view using SetupCamera(), the camera should +// be placed the same distance from the screen as your eye, but so +// that it looks at the screen straight-on. I.e. it must lie along +// the ray perpendicular to the screen which passes through the center +// of screen (i.e. the center of the screen, in world coords, corresponds +// to the focal point). Whatever 'z' you used in Shear(), the +// camera->focalpoint distance should be the same. If you are +// wondering why you don't set the camera position to be the eye +// position, don't worry -- the combination of SetupCamera() and +// an Oblique() shear about the focal plane does precisely that. +// +// - When you set up the view frustum using Perspective(), +// set the angle to 2*atan(0.5*height/z) where 'height' is +// the height of your screen multiplied by the real-to-virtual +// scale factor. Don't forget to convert the angle to degrees. +// - Though it is not absolutely necessary, you might want to +// keep your near and far clipping planes at constant distances +// from the focal point. By default, they are set up relative +// to the camera position. +// +// The order in which you apply the transformations, in +// PreMultiply mode, is: +// 1) Perspective(), 2) Shear(), 3) SetupCamera() +// +// Take the above advice with a grain of salt... I've never actually +// tried any of this except for with pencil & paper. Looks good on +// paper, though! +void vtkPerspectiveTransform::Shear(double dxdz, double dydz, double zplane) +{ + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + // everything is negative because the position->focalpoint vector + // is in the -z direction, hence z distances along that vector + // are negative. + + // shear according to the eye position relative to the screen + matrix[0][2] = -dxdz; + matrix[1][2] = -dydz; + + // shift so that view rays converge in the focal plane + matrix[0][3] = -zplane*dxdz; + matrix[1][3] = -zplane*dydz; + + // concatenate with the current matrix + this->Concatenate(*matrix); +} + +//---------------------------------------------------------------------------- +// For convenience -- this is sufficient for most people's stereo needs. +// Set the angle to negative for left eye, positive for right eye. +void vtkPerspectiveTransform::Stereo(double angle, double focaldistance) +{ + double dxdz = tan(angle*vtkMath::DoubleDegreesToRadians()); + + this->Shear(dxdz, 0.0, focaldistance); +} + +//---------------------------------------------------------------------------- +void vtkPerspectiveTransform::SetupCamera(const double position[3], + const double focalPoint[3], + const double viewUp[3]) +{ + double matrix[4][4]; + vtkMatrix4x4::Identity(*matrix); + + // the view directions correspond to the rows of the rotation matrix, + // so we'll make the connection explicit + double *viewSideways = matrix[0]; + double *orthoViewUp = matrix[1]; + double *viewPlaneNormal = matrix[2]; + + // set the view plane normal from the view vector + viewPlaneNormal[0] = position[0] - focalPoint[0]; + viewPlaneNormal[1] = position[1] - focalPoint[1]; + viewPlaneNormal[2] = position[2] - focalPoint[2]; + vtkMath::Normalize(viewPlaneNormal); + + // orthogonalize viewUp and compute viewSideways + vtkMath::Cross(viewUp,viewPlaneNormal,viewSideways); + vtkMath::Normalize(viewSideways); + vtkMath::Cross(viewPlaneNormal,viewSideways,orthoViewUp); + + // translate by the vector from the position to the origin + double delta[4]; + delta[0] = -position[0]; + delta[1] = -position[1]; + delta[2] = -position[2]; + delta[3] = 0.0; // yes, this should be zero, not one + + vtkMatrix4x4::MultiplyPoint(*matrix,delta,delta); + + matrix[0][3] = delta[0]; + matrix[1][3] = delta[1]; + matrix[2][3] = delta[2]; + + // apply the transformation + this->Concatenate(*matrix); +} + +void vtkPerspectiveTransform::SetupCamera(double p0, double p1, double p2, + double fp0, double fp1, double fp2, + double vup0, double vup1, double vup2) +{ + double p[3], fp[3], vup[3]; + p[0] = p0; + p[1] = p1; + p[2] = p2; + fp[0] = fp0; + fp[1] = fp1; + fp[2] = fp2; + vup[0] = vup0; + vup[1] = vup1; + vup[2] = vup2; + + this->SetupCamera(p, fp, vup); +} + diff --git a/Common/vtkPerspectiveTransform.h b/Common/vtkPerspectiveTransform.h new file mode 100644 index 0000000..9a088ad --- /dev/null +++ b/Common/vtkPerspectiveTransform.h @@ -0,0 +1,321 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPerspectiveTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkPerspectiveTransform - describes a 4x4 matrix transformation +// .SECTION Description +// A vtkPerspectiveTransform can be used to describe the full range of +// homogeneous transformations. It was designed in particular +// to describe a camera-view of a scene. +//

The order in which you set up the display coordinates (via +// AdjustZBuffer() and AdjustViewport()), the projection (via Perspective(), +// Frustum(), or Ortho()) and the camera view (via SetupCamera()) are +// important. If the transform is in PreMultiply mode, which is the +// default, set the Viewport and ZBuffer first, then the projection, and +// finally the camera view. Once the view is set up, the Translate +// and Rotate methods can be used to move the camera around in world +// coordinates. If the Oblique() or Stereo() methods are used, they +// should be called just before SetupCamera(). +//

In PostMultiply mode, you must perform all transformations +// in the opposite order. This is necessary, for example, if you +// already have a perspective transformation set up but must adjust +// the viewport. Another example is if you have a view transformation, +// and wish to perform translations and rotations in the camera's +// coordinate system rather than in world coordinates. +//

The SetInput and Concatenate methods can be used to create +// a transformation pipeline with vtkPerspectiveTransform. See vtkTransform +// for more information on the transformation pipeline. +// .SECTION See Also +// vtkGeneralTransform vtkTransform vtkMatrix4x4 vtkCamera + +#ifndef __vtkPerspectiveTransform_h +#define __vtkPerspectiveTransform_h + +#include "vtkHomogeneousTransform.h" + +#include "vtkMatrix4x4.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkPerspectiveTransform : public vtkHomogeneousTransform +{ + public: + static vtkPerspectiveTransform *New(); + vtkTypeRevisionMacro(vtkPerspectiveTransform,vtkHomogeneousTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set this transformation to the identity transformation. If + // the transform has an Input, then the transformation will be + // reset so that it is the same as the Input. + void Identity() { this->Concatenation->Identity(); this->Modified(); }; + + // Description: + // Invert the transformation. This will also set a flag so that + // the transformation will use the inverse of its Input, if an Input + // has been set. + void Inverse() { this->Concatenation->Inverse(); this->Modified(); }; + + // Description: + // Perform an adjustment to the viewport coordinates. By default Ortho, + // Frustum, and Perspective provide a window of ([-1,+1],[-1,+1]). + // In PreMultiply mode, you call this method before calling Ortho, Frustum, + // or Perspective. In PostMultiply mode you can call it after. Note + // that if you must apply both AdjustZBuffer and AdjustViewport, it + // makes no difference which order you apply them in. + void AdjustViewport(double oldXMin, double oldXMax, + double oldYMin, double oldYMax, + double newXMin, double newXMax, + double newYMin, double newYMax); + + // Description: + // Perform an adjustment to the Z-Buffer range that the near and far + // clipping planes map to. By default Ortho, Frustum, and Perspective + // map the near clipping plane to -1 and the far clipping plane to +1. + // In PreMultiply mode, you call this method before calling Ortho, Frustum, + // or Perspective. In PostMultiply mode you can call it after. + void AdjustZBuffer(double oldNearZ, double oldFarZ, + double newNearZ, double newFarZ); + + // Description: + // Create an orthogonal projection matrix and concatenate it by the + // current transformation. The matrix maps [xmin,xmax], [ymin,ymax], + // [-znear,-zfar] to [-1,+1], [-1,+1], [+1,-1]. + void Ortho(double xmin, double xmax, double ymin, double ymax, + double znear, double zfar); + + // Description: + // Create an perspective projection matrix and concatenate it by the + // current transformation. The matrix maps a frustum with a back + // plane at -zfar and a front plane at -znear with extent + // [xmin,xmax],[ymin,ymax] to [-1,+1], [-1,+1], [+1,-1]. + void Frustum(double xmin, double xmax, double ymin, double ymax, + double znear, double zfar); + + // Description: + // Create a perspective projection matrix by specifying the view angle + // (this angle is in the y direction), the aspect ratio, and the near + // and far clipping range. The projection matrix is concatenated + // with the current transformation. This method works via Frustum. + void Perspective(double angle, double aspect, double znear, double zfar); + + // Description: + // Create a shear transformation about a plane at distance z from + // the camera. The values dxdz (i.e. dx/dz) and dydz specify the + // amount of shear in the x and y directions. The 'zplane' specifies + // the distance from the camera to the plane at which the shear + // causes zero displacement. Generally you want this plane to be the + // focal plane. + // This transformation can be used in combination with Ortho to create + // an oblique projection. It can also be used in combination with + // Perspective to provide correct stereo views when the eye is at + // arbitrary but known positions relative to the center of a flat + // viewing screen. + void Shear(double dxdz, double dydz, double zplane); + + // Description: + // Create a stereo shear matrix and concatenate it with the + // current transformation. This can be applied in conjunction with either a + // perspective transformation (via Frustum or Projection) or an + // orthographic projection. You must specify the distance from + // the camera plane to the focal plane, and the angle between + // the distance vector and the eye. The angle should be negative + // for the left eye, and positive for the right. This method + // works via Oblique. + void Stereo(double angle, double focaldistance); + + // Description: + // Set a view transformation matrix for the camera (this matrix does + // not contain any perspective) and concatenate it with the current + // transformation. + void SetupCamera(const double position[3], const double focalpoint[3], + const double viewup[3]); + + void SetupCamera(double p0, double p1, double p2, + double fp0, double fp1, double fp2, + double vup0, double vup1, double vup2); + + // Description: + // Create a translation matrix and concatenate it with the current + // transformation according to PreMultiply or PostMultiply semantics. + void Translate(double x, double y, double z) { + this->Concatenation->Translate(x,y,z); }; + void Translate(const double x[3]) { this->Translate(x[0], x[1], x[2]); }; + void Translate(const float x[3]) { this->Translate(x[0], x[1], x[2]); }; + + // Description: + // Create a rotation matrix and concatenate it with the current + // transformation according to PreMultiply or PostMultiply semantics. + // The angle is in degrees, and (x,y,z) specifies the axis that the + // rotation will be performed around. + void RotateWXYZ(double angle, double x, double y, double z) { + this->Concatenation->Rotate(angle,x,y,z); }; + void RotateWXYZ(double angle, const double axis[3]) { + this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); }; + void RotateWXYZ(double angle, const float axis[3]) { + this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); }; + + // Description: + // Create a rotation matrix about the X, Y, or Z axis and concatenate + // it with the current transformation according to PreMultiply or + // PostMultiply semantics. The angle is expressed in degrees. + void RotateX(double angle) { this->RotateWXYZ(angle, 1, 0, 0); }; + void RotateY(double angle) { this->RotateWXYZ(angle, 0, 1, 0); }; + void RotateZ(double angle) { this->RotateWXYZ(angle, 0, 0, 1); }; + + // Description: + // Create a scale matrix (i.e. set the diagonal elements to x, y, z) + // and concatenate it with the current transformation according to + // PreMultiply or PostMultiply semantics. + void Scale(double x, double y, double z) { + this->Concatenation->Scale(x,y,z); }; + void Scale(const double s[3]) { this->Scale(s[0], s[1], s[2]); }; + void Scale(const float s[3]) { this->Scale(s[0], s[1], s[2]); }; + + // Description: + // Set the current matrix directly. This actually calls Identity(), + // followed by Concatenate(matrix). + void SetMatrix(vtkMatrix4x4 *matrix) { + this->SetMatrix(*matrix->Element); }; + void SetMatrix(const double elements[16]) { + this->Identity(); this->Concatenate(elements); }; + + // Description: + // Concatenates the matrix with the current transformation according + // to PreMultiply or PostMultiply semantics. + void Concatenate(vtkMatrix4x4 *matrix) { + this->Concatenate(*matrix->Element); }; + void Concatenate(const double elements[16]) { + this->Concatenation->Concatenate(elements); }; + + // Description: + // Concatenate the specified transform with the current transformation + // according to PreMultiply or PostMultiply semantics. + // The concatenation is pipelined, meaning that if any of the + // transformations are changed, even after Concatenate() is called, + // those changes will be reflected when you call TransformPoint(). + void Concatenate(vtkHomogeneousTransform *transform); + + // Description: + // Sets the internal state of the transform to PreMultiply. All subsequent + // operations will occur before those already represented in the + // current transformation. In homogeneous matrix notation, M = M*A where + // M is the current transformation matrix and A is the applied matrix. + // The default is PreMultiply. + void PreMultiply() { + if (this->Concatenation->GetPreMultiplyFlag()) { return; } + this->Concatenation->SetPreMultiplyFlag(1); this->Modified(); }; + + // Description: + // Sets the internal state of the transform to PostMultiply. All subsequent + // operations will occur after those already represented in the + // current transformation. In homogeneous matrix notation, M = A*M where + // M is the current transformation matrix and A is the applied matrix. + // The default is PreMultiply. + void PostMultiply() { + if (!this->Concatenation->GetPreMultiplyFlag()) { return; } + this->Concatenation->SetPreMultiplyFlag(0); this->Modified(); }; + + // Description: + // Get the total number of transformations that are linked into this + // one via Concatenate() operations or via SetInput(). + int GetNumberOfConcatenatedTransforms() { + return this->Concatenation->GetNumberOfTransforms() + + (this->Input == NULL ? 0 : 1); }; + + // Description + // Get one of the concatenated transformations as a vtkAbstractTransform. + // These transformations are applied, in series, every time the + // transformation of a coordinate occurs. This method is provided + // to make it possible to decompose a transformation into its + // constituents, for example to save a transformation to a file. + vtkHomogeneousTransform *GetConcatenatedTransform(int i) { + if (this->Input == NULL) { + return (vtkHomogeneousTransform *)this->Concatenation->GetTransform(i); } + else if (i < this->Concatenation->GetNumberOfPreTransforms()) { + return (vtkHomogeneousTransform *)this->Concatenation->GetTransform(i); } + else if (i > this->Concatenation->GetNumberOfPreTransforms()) { + return (vtkHomogeneousTransform*)this->Concatenation->GetTransform(i-1);} + else if (this->GetInverseFlag()) { + return (vtkHomogeneousTransform *)this->Input->GetInverse(); } + else { + return (vtkHomogeneousTransform *)this->Input; } }; + + // Description: + // Set the input for this transformation. This will be used as the + // base transformation if it is set. This method allows you to build + // a transform pipeline: if the input is modified, then this transformation + // will automatically update accordingly. Note that the InverseFlag, + // controlled via Inverse(), determines whether this transformation + // will use the Input or the inverse of the Input. + void SetInput(vtkHomogeneousTransform *input); + vtkHomogeneousTransform *GetInput() { return this->Input; }; + + // Description: + // Get the inverse flag of the transformation. This controls + // whether it is the Input or the inverse of the Input that + // is used as the base transformation. The InverseFlag is + // flipped every time Inverse() is called. The InverseFlag + // is off when a transform is first created. + int GetInverseFlag() { + return this->Concatenation->GetInverseFlag(); }; + + // Description: + // Pushes the current transformation onto the transformation stack. + void Push() { if (this->Stack == NULL) { + this->Stack = vtkTransformConcatenationStack::New(); } + this->Stack->Push(&this->Concatenation); + this->Modified(); }; + + // Description: + // Deletes the transformation on the top of the stack and sets the top + // to the next transformation on the stack. + void Pop() { if (this->Stack == NULL) { return; } + this->Stack->Pop(&this->Concatenation); + this->Modified(); }; + + // Description: + // Make a new transform of the same type -- you are responsible for + // deleting the transform when you are done with it. + vtkAbstractTransform *MakeTransform(); + + // Description: + // Check for self-reference. Will return true if concatenating + // with the specified transform, setting it to be our inverse, + // or setting it to be our input will create a circular reference. + // CircuitCheck is automatically called by SetInput(), SetInverse(), + // and Concatenate(vtkXTransform *). Avoid using this function, + // it is experimental. + int CircuitCheck(vtkAbstractTransform *transform); + + // Description: + // Override GetMTime to account for input and concatenation. + unsigned long GetMTime(); + +protected: + vtkPerspectiveTransform(); + ~vtkPerspectiveTransform(); + + void InternalDeepCopy(vtkAbstractTransform *t); + void InternalUpdate(); + + vtkHomogeneousTransform *Input; + vtkTransformConcatenation *Concatenation; + vtkTransformConcatenationStack *Stack; + +private: + vtkPerspectiveTransform(const vtkPerspectiveTransform&); // Not implemented + void operator=(const vtkPerspectiveTransform&); // Not implemented +}; + + +#endif diff --git a/Common/vtkPlane.cxx b/Common/vtkPlane.cxx new file mode 100644 index 0000000..195c6cd --- /dev/null +++ b/Common/vtkPlane.cxx @@ -0,0 +1,190 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlane.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPlane.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPlane, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkPlane); + +// Construct plane passing through origin and normal to z-axis. +vtkPlane::vtkPlane() +{ + this->Normal[0] = 0.0; + this->Normal[1] = 0.0; + this->Normal[2] = 1.0; + + this->Origin[0] = 0.0; + this->Origin[1] = 0.0; + this->Origin[2] = 0.0; +} + +void vtkPlane::ProjectPoint(double x[3], double origin[3], + double normal[3], double xproj[3]) +{ + double t, xo[3]; + + xo[0] = x[0] - origin[0]; + xo[1] = x[1] - origin[1]; + xo[2] = x[2] - origin[2]; + + t = vtkMath::Dot(normal,xo); + + xproj[0] = x[0] - t * normal[0]; + xproj[1] = x[1] - t * normal[1]; + xproj[2] = x[2] - t * normal[2]; +} + +void vtkPlane::Push(double distance) +{ + int i; + + if ( distance == 0.0 ) + { + return; + } + for (i=0; i < 3; i++ ) + { + this->Origin[i] += distance * this->Normal[i]; + } + this->Modified(); +} + +// Project a point x onto plane defined by origin and normal. The +// projected point is returned in xproj. NOTE : normal NOT required to +// have magnitude 1. +void vtkPlane::GeneralizedProjectPoint(double x[3], double origin[3], + double normal[3], double xproj[3]) +{ + double t, xo[3], n2; + + xo[0] = x[0] - origin[0]; + xo[1] = x[1] - origin[1]; + xo[2] = x[2] - origin[2]; + + t = vtkMath::Dot(normal,xo); + n2 = vtkMath::Dot(normal, normal); + + if (n2 != 0) + { + xproj[0] = x[0] - t * normal[0]/n2; + xproj[1] = x[1] - t * normal[1]/n2; + xproj[2] = x[2] - t * normal[2]/n2; + } + else + { + xproj[0] = x[0]; + xproj[1] = x[1]; + xproj[2] = x[2]; + } +} + + +// Evaluate plane equation for point x[3]. +double vtkPlane::EvaluateFunction(double x[3]) +{ + return ( this->Normal[0]*(x[0]-this->Origin[0]) + + this->Normal[1]*(x[1]-this->Origin[1]) + + this->Normal[2]*(x[2]-this->Origin[2]) ); +} + +// Evaluate function gradient at point x[3]. +void vtkPlane::EvaluateGradient(double vtkNotUsed(x)[3], double n[3]) +{ + for (int i=0; i<3; i++) + { + n[i] = this->Normal[i]; + } +} + +#define VTK_PLANE_TOL 1.0e-06 + +// Given a line defined by the two points p1,p2; and a plane defined by the +// normal n and point p0, compute an intersection. The parametric +// coordinate along the line is returned in t, and the coordinates of +// intersection are returned in x. A zero is returned if the plane and line +// do not intersect between (0<=t<=1). If the plane and line are parallel, +// zero is returned and t is set to VTK_LARGE_DOUBLE. +int vtkPlane::IntersectWithLine(double p1[3], double p2[3], double n[3], + double p0[3], double& t, double x[3]) +{ + double num, den, p21[3]; + double fabsden, fabstolerance; + + // Compute line vector + // + p21[0] = p2[0] - p1[0]; + p21[1] = p2[1] - p1[1]; + p21[2] = p2[2] - p1[2]; + + // Compute denominator. If ~0, line and plane are parallel. + // + num = vtkMath::Dot(n,p0) - ( n[0]*p1[0] + n[1]*p1[1] + n[2]*p1[2] ) ; + den = n[0]*p21[0] + n[1]*p21[1] + n[2]*p21[2]; + // + // If denominator with respect to numerator is "zero", then the line and + // plane are considered parallel. + // + + // trying to avoid an expensive call to fabs() + if (den < 0.0) + { + fabsden = -den; + } + else + { + fabsden = den; + } + if (num < 0.0) + { + fabstolerance = -num*VTK_PLANE_TOL; + } + else + { + fabstolerance = num*VTK_PLANE_TOL; + } + if ( fabsden <= fabstolerance ) + { + t = VTK_DOUBLE_MAX; + return 0; + } + + // valid intersection + t = num / den; + + x[0] = p1[0] + t*p21[0]; + x[1] = p1[1] + t*p21[1]; + x[2] = p1[2] + t*p21[2]; + + if ( t >= 0.0 && t <= 1.0 ) + { + return 1; + } + else + { + return 0; + } +} + +void vtkPlane::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Normal: (" << this->Normal[0] << ", " + << this->Normal[1] << ", " << this->Normal[2] << ")\n"; + + os << indent << "Origin: (" << this->Origin[0] << ", " + << this->Origin[1] << ", " << this->Origin[2] << ")\n"; +} diff --git a/Common/vtkPlane.h b/Common/vtkPlane.h new file mode 100644 index 0000000..f2180d2 --- /dev/null +++ b/Common/vtkPlane.h @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlane.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPlane - perform various plane computations +// .SECTION Description +// vtkPlane provides methods for various plane computations. These include +// projecting points onto a plane, evaluating the plane equation, and +// returning plane normal. vtkPlane is a concrete implementation of the +// abstract class vtkImplicitFunction. + +#ifndef __vtkPlane_h +#define __vtkPlane_h + +#include "vtkImplicitFunction.h" + +class VTK_COMMON_EXPORT vtkPlane : public vtkImplicitFunction +{ +public: + // Description + // Construct plane passing through origin and normal to z-axis. + static vtkPlane *New(); + + vtkTypeRevisionMacro(vtkPlane,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Evaluate plane equation for point x[3]. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate function gradient at point x[3]. + void EvaluateGradient(double x[3], double g[3]); + + // Description: + // Set/get plane normal. Plane is defined by point and normal. + vtkSetVector3Macro(Normal,double); + vtkGetVectorMacro(Normal,double,3); + + // Description: + // Set/get point through which plane passes. Plane is defined by point + // and normal. + vtkSetVector3Macro(Origin,double); + vtkGetVectorMacro(Origin,double,3); + + // Description: + // Translate the plane in the direction of the normal by the + // distance specified. Negative values move the plane in the + // opposite direction. + void Push(double distance); + + // Description + // Project a point x onto plane defined by origin and normal. The + // projected point is returned in xproj. NOTE : normal assumed to + // have magnitude 1. + static void ProjectPoint(double x[3], double origin[3], double normal[3], + double xproj[3]); + + // Description + // Project a point x onto plane defined by origin and normal. The + // projected point is returned in xproj. NOTE : normal does NOT have to + // have magnitude 1. + static void GeneralizedProjectPoint(double x[3], double origin[3], + double normal[3], double xproj[3]); + + // Description: + // Quick evaluation of plane equation n(x-origin)=0. + static double Evaluate(double normal[3], double origin[3], double x[3]); + + // Description: + // Return the distance of a point x to a plane defined by n(x-p0) = 0. The + // normal n[3] must be magnitude=1. + static double DistanceToPlane(double x[3], double n[3], double p0[3]); + + // Description: + // Given a line defined by the two points p1,p2; and a plane defined by the + // normal n and point p0, compute an intersection. The parametric + // coordinate along the line is returned in t, and the coordinates of + // intersection are returned in x. A zero is returned if the plane and line + // do not intersect between (0<=t<=1). If the plane and line are parallel, + // zero is returned and t is set to VTK_LARGE_DOUBLE. + static int IntersectWithLine(double p1[3], double p2[3], double n[3], + double p0[3], double& t, double x[3]); + + +protected: + vtkPlane(); + ~vtkPlane() {}; + + double Normal[3]; + double Origin[3]; + +private: + vtkPlane(const vtkPlane&); // Not implemented. + void operator=(const vtkPlane&); // Not implemented. +}; + +inline double vtkPlane::Evaluate(double normal[3], + double origin[3], double x[3]) +{ + return normal[0]*(x[0]-origin[0]) + normal[1]*(x[1]-origin[1]) + + normal[2]*(x[2]-origin[2]); +} + +inline double vtkPlane::DistanceToPlane(double x[3], double n[3], double p0[3]) +{ +#define vtkPlaneAbs(x) ((x)<0?-(x):(x)) + return (vtkPlaneAbs(n[0]*(x[0]-p0[0]) + n[1]*(x[1]-p0[1]) + + n[2]*(x[2]-p0[2]))); +} + +#endif + + diff --git a/Common/vtkPlaneCollection.cxx b/Common/vtkPlaneCollection.cxx new file mode 100644 index 0000000..b7d1800 --- /dev/null +++ b/Common/vtkPlaneCollection.cxx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlaneCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPlaneCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPlaneCollection, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkPlaneCollection); + +vtkPlane *vtkPlaneCollection::GetNextPlane( + vtkCollectionSimpleIterator &cookie) +{ + return static_cast(this->GetNextItemAsObject(cookie)); +} diff --git a/Common/vtkPlaneCollection.h b/Common/vtkPlaneCollection.h new file mode 100644 index 0000000..f18a507 --- /dev/null +++ b/Common/vtkPlaneCollection.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlaneCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPlaneCollection - maintain a list of planes +// .SECTION Description +// vtkPlaneCollection is an object that creates and manipulates +// lists of objects of type vtkPlane. +// .SECTION See Also +// vtkCollection + +#ifndef __vtkPlaneCollection_h +#define __vtkPlaneCollection_h + +#include "vtkCollection.h" + +#include "vtkPlane.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkPlaneCollection : public vtkCollection +{ +public: + vtkTypeRevisionMacro(vtkPlaneCollection,vtkCollection); + static vtkPlaneCollection *New(); + + // Description: + // Add a plane to the list. + void AddItem(vtkPlane *); + + // Description: + // Get the next plane in the list. + vtkPlane *GetNextItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkPlane *GetNextPlane(vtkCollectionSimpleIterator &cookie); + //ETX + +protected: + vtkPlaneCollection() {}; + ~vtkPlaneCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkPlaneCollection(const vtkPlaneCollection&); // Not implemented. + void operator=(const vtkPlaneCollection&); // Not implemented. +}; + +inline void vtkPlaneCollection::AddItem(vtkPlane *f) +{ + this->vtkCollection::AddItem((vtkObject *)f); +} + +inline vtkPlane *vtkPlaneCollection::GetNextItem() +{ + return static_cast(this->GetNextItemAsObject()); +} + +#endif diff --git a/Common/vtkPlanes.cxx b/Common/vtkPlanes.cxx new file mode 100644 index 0000000..f6f9764 --- /dev/null +++ b/Common/vtkPlanes.cxx @@ -0,0 +1,369 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlanes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPlanes.h" + +#include "vtkDoubleArray.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPoints.h" + +#include + +vtkCxxRevisionMacro(vtkPlanes, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkPlanes); +vtkCxxSetObjectMacro(vtkPlanes,Points,vtkPoints); + +vtkPlanes::vtkPlanes() +{ + int i; + + this->Points = NULL; + this->Normals = NULL; + this->Plane = vtkPlane::New(); + + for (i=0; i<24; i++) + { + this->Planes[i] = 0.0; + } + for (i=0; i<6; i++) + { + this->Bounds[i] = 0.0; + } +} + +vtkPlanes::~vtkPlanes() +{ + if ( this->Points ) + { + this->Points->UnRegister(this); + } + if ( this->Normals ) + { + this->Normals->UnRegister(this); + } + this->Plane->Delete(); +} + +void vtkPlanes::SetNormals(vtkDataArray* normals) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this + << "): setting Normals to " << normals ); + + if (normals && normals->GetNumberOfComponents() != 3) + { + vtkWarningMacro("This array does not have 3 components. Ignoring normals."); + return; + } + + if (this->Normals != normals) + { + if (this->Normals != NULL) { this->Normals->UnRegister(this); } + this->Normals = normals; + if (this->Normals != NULL) { this->Normals->Register(this); } + this->Modified(); + } +} + +// Evaluate plane equations. Return smallest absolute value. +double vtkPlanes::EvaluateFunction(double x[3]) +{ + int numPlanes, i; + double val, maxVal; + double normal[3], point[3]; + + if ( !this->Points || ! this->Normals ) + { + vtkErrorMacro(<<"Please define points and/or normals!"); + return VTK_DOUBLE_MAX; + } + + if ( (numPlanes=this->Points->GetNumberOfPoints()) != this->Normals->GetNumberOfTuples() ) + { + vtkErrorMacro(<<"Number of normals/points inconsistent!"); + return VTK_DOUBLE_MAX; + } + + for (maxVal=-VTK_DOUBLE_MAX, i=0; i < numPlanes; i++) + { + this->Normals->GetTuple(i,normal); + this->Points->GetPoint(i,point); + val = this->Plane->Evaluate(normal, point, x); + if (val > maxVal ) + { + maxVal = val; + } + } + + return maxVal; +} + +// Evaluate planes gradient. +void vtkPlanes::EvaluateGradient(double x[3], double n[3]) +{ + int numPlanes, i; + double val, maxVal; + double nTemp[3]; + double pTemp[3]; + + if ( !this->Points || ! this->Normals ) + { + vtkErrorMacro(<<"Please define points and/or normals!"); + return; + } + + if ( (numPlanes=this->Points->GetNumberOfPoints()) != + this->Normals->GetNumberOfTuples() ) + { + vtkErrorMacro(<<"Number of normals/points inconsistent!"); + return; + } + + for (maxVal=-VTK_DOUBLE_MAX, i=0; i < numPlanes; i++) + { + this->Normals->GetTuple(i, nTemp); + this->Points->GetPoint(i, pTemp); + val = this->Plane->Evaluate(nTemp, pTemp, x); + if ( val > maxVal ) + { + maxVal = val; + n[0] = nTemp[0]; + n[1] = nTemp[1]; + n[2] = nTemp[2]; + } + } +} + +void vtkPlanes::SetFrustumPlanes(double planes[24]) +{ + int i; + double *plane, n[3], x[3]; + + for (i=0; i<24; i++) + { + if ( this->Planes[i] != planes[i] ) + { + break; + } + } + if ( i >= 24 ) + { + return; //same as before don't modify + } + + // okay, need to allocate stuff + this->Modified(); + vtkPoints *pts = vtkPoints::New(); + vtkDoubleArray *normals = vtkDoubleArray::New(); + + pts->SetNumberOfPoints(6); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(6); + this->SetPoints(pts); + this->SetNormals(normals); + + for (i=0; i<6; i++) + { + plane = planes + 4*i; + n[0] = -plane[0]; + n[1] = -plane[1]; + n[2] = -plane[2]; + x[0] = x[1] = x[2] = 0.0; + if ( n[0] != 0.0 ) + { + x[0] = plane[3] / n[0]; + } + else if ( n[1] != 0.0 ) + { + x[1] = plane[3] / n[1]; + } + else + { + x[2] = plane[3] / n[2]; + } + pts->SetPoint(i,x); + normals->SetTuple(i,n); + } + + pts->Delete(); //ok reference counting + normals->Delete(); +} + +void vtkPlanes::SetBounds(double bounds[6]) +{ + int i; + double n[3], x[3]; + + for (i=0; i<6; i++) + { + if ( this->Bounds[i] != bounds[i] ) + { + break; + } + } + if ( i >= 6 ) + { + return; //same as before don't modify + } + + // okay, need to allocate stuff + this->Modified(); + vtkPoints *pts = vtkPoints::New(); + vtkDoubleArray *normals = vtkDoubleArray::New(); + + pts->SetNumberOfPoints(6); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(6); + this->SetPoints(pts); + this->SetNormals(normals); + + // Define the six planes + // The x planes + n[0] = -1.0; + n[1] = 0.0; + n[2] = 0.0; + x[0] = this->Bounds[0] = bounds[0]; + x[1] = 0.0; + x[2] = 0.0; + pts->SetPoint(0,x); + normals->SetTuple(0,n); + + n[0] = 1.0; + x[0] = this->Bounds[1] = bounds[1]; + pts->SetPoint(1,x); + normals->SetTuple(1,n); + + // The y planes + n[0] = 0.0; + n[1] = -1.0; + n[2] = 0.0; + x[0] = 0.0; + x[1] = this->Bounds[2] = bounds[2]; + x[2] = 0.0; + pts->SetPoint(2,x); + normals->SetTuple(2,n); + + n[1] = 1.0; + x[1] = this->Bounds[3] = bounds[3]; + pts->SetPoint(3,x); + normals->SetTuple(3,n); + + // The z planes + n[0] = 0.0; + n[1] = 0.0; + n[2] = -1.0; + x[0] = 0.0; + x[1] = 0.0; + x[2] = this->Bounds[4] = bounds[4]; + pts->SetPoint(4,x); + normals->SetTuple(4,n); + + n[2] = 1.0; + x[2] = this->Bounds[5] = bounds[5]; + pts->SetPoint(5,x); + normals->SetTuple(5,n); + + pts->Delete(); //ok reference counting + normals->Delete(); +} + +void vtkPlanes::SetBounds(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) +{ + double bounds[6]; + bounds[0] = xmin; + bounds[1] = xmax; + bounds[2] = ymin; + bounds[3] = ymax; + bounds[4] = zmin; + bounds[5] = zmax; + + this->SetBounds(bounds); +} + +int vtkPlanes::GetNumberOfPlanes() +{ + if ( this->Points && this->Normals ) + { + int npts = this->Points->GetNumberOfPoints(); + int nnormals = this->Normals->GetNumberOfTuples(); + return ( npts <= nnormals ? npts : nnormals ); + } + else + { + return 0; + } +} + +vtkPlane *vtkPlanes::GetPlane(int i) +{ + double normal[3]; + double point[3]; + + if ( i >= 0 && i < this->GetNumberOfPlanes() ) + { + this->Normals->GetTuple(i,normal); + this->Points->GetPoint(i,point); + this->Plane->SetNormal(normal); + this->Plane->SetOrigin(point); + return this->Plane; + } + else + { + return NULL; + } +} + +void vtkPlanes::GetPlane(int i, vtkPlane *plane) +{ + double normal[3]; + double point[3]; + + if ( i >= 0 && i < this->GetNumberOfPlanes() ) + { + this->Normals->GetTuple(i,normal); + this->Points->GetPoint(i,point); + plane->SetNormal(normal); + plane->SetOrigin(point); + } + else + { + plane = NULL; + } +} + +void vtkPlanes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int numPlanes; + + if ( this->Points && (numPlanes=this->Points->GetNumberOfPoints()) > 0 ) + { + os << indent << "Number of Planes: " << numPlanes << "\n"; + } + else + { + os << indent << "No Planes Defined.\n"; + } + + if ( this->Normals ) + { + os << indent << "Normals: " << this->Normals << "\n"; + } + else + { + os << indent << "Normals: (none)\n"; + } +} diff --git a/Common/vtkPlanes.h b/Common/vtkPlanes.h new file mode 100644 index 0000000..7c79cc1 --- /dev/null +++ b/Common/vtkPlanes.h @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlanes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPlanes - implicit function for convex set of planes +// .SECTION Description +// vtkPlanes computes the implicit function and function gradient for a set +// of planes. The planes must define a convex space. +// +// The function value is the closest first order distance of a point to the +// convex region defined by the planes. The function gradient is the plane +// normal at the function value. Note that the normals must point outside of +// the convex region. Thus, a negative function value means that a point is +// inside the convex region. +// +// There are several methods to define the set of planes. The most general is +// to supply an instance of vtkPoints and an instance of vtkDataArray. (The +// points define a point on the plane, and the normals corresponding plane +// normals.) Two other specialized ways are to 1) supply six planes defining +// the view frustrum of a camera, and 2) provide a bounding box. + +// .SECTION See Also +// vtkCamera + +#ifndef __vtkPlanes_h +#define __vtkPlanes_h + +#include "vtkImplicitFunction.h" + +class vtkPlane; +class vtkPoints; +class vtkDataArray; + +class VTK_COMMON_EXPORT vtkPlanes : public vtkImplicitFunction +{ +public: + static vtkPlanes *New(); + vtkTypeRevisionMacro(vtkPlanes,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Evaluate plane equations. Return smallest absolute value. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate planes gradient. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Specify a list of points defining points through which the planes pass. + virtual void SetPoints(vtkPoints*); + vtkGetObjectMacro(Points,vtkPoints); + + // Description: + // Specify a list of normal vectors for the planes. There is a one-to-one + // correspondence between plane points and plane normals. + void SetNormals(vtkDataArray* normals); + vtkGetObjectMacro(Normals,vtkDataArray); + + // Description: + // An alternative method to specify six planes defined by the camera view + // frustrum. See vtkCamera::GetFrustumPlanes() documentation. + void SetFrustumPlanes(double planes[24]); + + // Description: + // An alternative method to specify six planes defined by a bounding box. + // The bounding box is a six-vector defined as (xmin,xmax,ymin,ymax,zmin,zmax). + // It defines six planes orthogonal to the x-y-z coordinate axes. + void SetBounds(double bounds[6]); + void SetBounds(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax); + + // Description: + // Return the number of planes in the set of planes. + int GetNumberOfPlanes(); + + // Description: + // Create and return a pointer to a vtkPlane object at the ith + // position. Asking for a plane outside the allowable range returns NULL. + // This method always returns the same object. + // Use GetPlane(int i, vtkPlane *plane) instead + vtkPlane *GetPlane(int i); + void GetPlane(int i, vtkPlane *plane); + +protected: + vtkPlanes(); + ~vtkPlanes(); + + vtkPoints *Points; + vtkDataArray *Normals; + vtkPlane *Plane; + +private: + double Planes[24]; + double Bounds[6]; + +private: + vtkPlanes(const vtkPlanes&); // Not implemented. + void operator=(const vtkPlanes&); // Not implemented. +}; + +#endif + + diff --git a/Common/vtkPoints.cxx b/Common/vtkPoints.cxx new file mode 100644 index 0000000..b45935d --- /dev/null +++ b/Common/vtkPoints.cxx @@ -0,0 +1,240 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPoints.h" + +#include "vtkBitArray.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkObjectFactory.h" +#include "vtkShortArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +vtkCxxRevisionMacro(vtkPoints, "$Revision: 1.52 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkPoints); + +//---------------------------------------------------------------------------- +vtkPoints* vtkPoints::New(int dataType) +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkObjectFactory::CreateInstance("vtkPoints"); + if(ret) + { + return (vtkPoints*)ret; + } + // If the factory was unable to create the object, then create it here. + return new vtkPoints(dataType); +} + +vtkPoints* vtkPoints::New() +{ + return vtkPoints::New(VTK_FLOAT); +} + +// Construct object with an initial data array of type float. +vtkPoints::vtkPoints(int dataType) +{ + this->Data = vtkFloatArray::New(); + this->Data->Register(this); + this->Data->Delete(); + this->SetDataType(dataType); + + this->Data->SetNumberOfComponents(3); + + this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = 0.0; + this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = 1.0; +} + +vtkPoints::~vtkPoints() +{ + this->Data->UnRegister(this); +} + +// Given a list of pt ids, return an array of points. +void vtkPoints::GetPoints(vtkIdList *ptIds, vtkPoints *fp) +{ + vtkIdType num = ptIds->GetNumberOfIds(); + + for (vtkIdType i=0; i < num; i++) + { + fp->InsertPoint(i, this->GetPoint(ptIds->GetId(i))); + } +} + +// Determine (xmin,xmax, ymin,ymax, zmin,zmax) bounds of points. +void vtkPoints::ComputeBounds() +{ + vtkIdType i; + int j; + double *x; + + if ( this->GetMTime() > this->ComputeTime ) + { + this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX; + this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX; + for (i=0; iGetNumberOfPoints(); i++) + { + x = this->GetPoint(i); + for (j=0; j<3; j++) + { + if ( x[j] < this->Bounds[2*j] ) + { + this->Bounds[2*j] = x[j]; + } + if ( x[j] > this->Bounds[2*j+1] ) + { + this->Bounds[2*j+1] = x[j]; + } + } + } + + this->ComputeTime.Modified(); + } +} + +// Return the bounds of the points. +double *vtkPoints::GetBounds() +{ + this->ComputeBounds(); + return this->Bounds; +} + +// Return the bounds of the points. +void vtkPoints::GetBounds(double bounds[6]) +{ + this->ComputeBounds(); + for (int i=0; i<6; i++) + { + bounds[i] = this->Bounds[i]; + } +} + +int vtkPoints::Allocate(const vtkIdType sz, const vtkIdType ext) +{ + int numComp=this->Data->GetNumberOfComponents(); + return this->Data->Allocate(sz*numComp,ext*numComp); +} + +void vtkPoints::Initialize() +{ + this->Data->Initialize(); +} + +int vtkPoints::GetDataType() +{ + return this->Data->GetDataType(); +} + +// Specify the underlying data type of the object. +void vtkPoints::SetDataType(int dataType) +{ + if ( dataType == this->Data->GetDataType() ) + { + return; + } + + this->Modified(); + + this->Data->Delete(); + this->Data = vtkDataArray::CreateDataArray(dataType); + this->Data->SetNumberOfComponents(3); +} + +// Set the data for this object. The tuple dimension must be consistent with +// the object. +void vtkPoints::SetData(vtkDataArray *data) +{ + if ( data != this->Data && data != NULL ) + { + if (data->GetNumberOfComponents() != this->Data->GetNumberOfComponents() ) + { + vtkErrorMacro(<<"Number of components is different...can't set data"); + return; + } + this->Data->UnRegister(this); + this->Data = data; + this->Data->Register(this); + this->Modified(); + } +} + +// Deep copy of data. Checks consistency to make sure this operation +// makes sense. +void vtkPoints::DeepCopy(vtkPoints *da) +{ + if (da == NULL) + { + return; + } + if ( da->Data != this->Data && da->Data != NULL ) + { + if (da->Data->GetNumberOfComponents() != this->Data->GetNumberOfComponents() ) + { + vtkErrorMacro(<<"Number of components is different...can't copy"); + return; + } + this->Data->DeepCopy(da->Data); + this->Modified(); + } +} + +// Shallow copy of data (i.e. via reference counting). Checks +// consistency to make sure this operation makes sense. +void vtkPoints::ShallowCopy(vtkPoints *da) +{ + this->SetData(da->GetData()); +} + +unsigned long vtkPoints::GetActualMemorySize() +{ + return this->Data->GetActualMemorySize(); +} + +void vtkPoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + double *bounds; + + os << indent << "Data: " << this->Data << "\n"; + if ( this->Data ) + { + if ( this->Data->GetName() ) + { + os << indent << "Data Array Name: " << this->Data->GetName() << "\n"; + } + else + { + os << indent << "Data Array Name: (none)\n"; + } + } + + os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n"; + bounds = this->GetBounds(); + os << indent << "Bounds: \n"; + os << indent << " Xmin,Xmax: (" << bounds[0] << ", " << bounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << bounds[2] << ", " << bounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << bounds[4] << ", " << bounds[5] << ")\n"; +} diff --git a/Common/vtkPoints.h b/Common/vtkPoints.h new file mode 100644 index 0000000..137602a --- /dev/null +++ b/Common/vtkPoints.h @@ -0,0 +1,217 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPoints - represent and manipulate 3D points +// .SECTION Description +// vtkPoints represents 3D points. The data model for vtkPoints is an +// array of vx-vy-vz triplets accessible by (point or cell) id. + +#ifndef __vtkPoints_h +#define __vtkPoints_h + +#include "vtkObject.h" + +#include "vtkDataArray.h" // Needed for inline methods + +class vtkIdList; +class vtkPoints; + +class VTK_COMMON_EXPORT vtkPoints : public vtkObject +{ +public: +//BTX + static vtkPoints *New(int dataType); +//ETX + static vtkPoints *New(); + + vtkTypeRevisionMacro(vtkPoints,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate initial memory size. + virtual int Allocate(const vtkIdType sz, const vtkIdType ext=1000); + + // Description: + // Return object to instantiated state. + virtual void Initialize(); + + // Description: + // Set/Get the underlying data array. This function must be implemented + // in a concrete subclass to check for consistency. (The tuple size must + // match the type of data. For example, 3-tuple data array can be assigned to + // a vector, normal, or points object, but not a tensor object, which has a + // tuple dimension of 9. Scalars, on the other hand, can have tuple dimension + // from 1-4, depending on the type of scalar.) + virtual void SetData(vtkDataArray *); + vtkDataArray *GetData() {return this->Data;}; + + // Description: + // Return the underlying data type. An integer indicating data type is + // returned as specified in vtkSetGet.h. + virtual int GetDataType(); + + // Description: + // Specify the underlying data type of the object. + virtual void SetDataType(int dataType); + void SetDataTypeToBit() {this->SetDataType(VTK_BIT);}; + void SetDataTypeToChar() {this->SetDataType(VTK_CHAR);}; + void SetDataTypeToUnsignedChar() {this->SetDataType(VTK_UNSIGNED_CHAR);}; + void SetDataTypeToShort() {this->SetDataType(VTK_SHORT);}; + void SetDataTypeToUnsignedShort() {this->SetDataType(VTK_UNSIGNED_SHORT);}; + void SetDataTypeToInt() {this->SetDataType(VTK_INT);}; + void SetDataTypeToUnsignedInt() {this->SetDataType(VTK_UNSIGNED_INT);}; + void SetDataTypeToLong() {this->SetDataType(VTK_LONG);}; + void SetDataTypeToUnsignedLong() {this->SetDataType(VTK_UNSIGNED_LONG);}; + void SetDataTypeToFloat() {this->SetDataType(VTK_FLOAT);}; + void SetDataTypeToDouble() {this->SetDataType(VTK_DOUBLE);}; + + // Description: + // Return a void pointer. For image pipeline interface and other + // special pointer manipulation. + void *GetVoidPointer(const int id) {return this->Data->GetVoidPointer(id);}; + + // Description: + // Reclaim any extra memory. + virtual void Squeeze() {this->Data->Squeeze();}; + + // Description: + // Make object look empty but do not delete memory. + virtual void Reset() {this->Data->Reset();}; + + // Description: + // Different ways to copy data. Shallow copy does reference count (i.e., + // assigns pointers and updates reference count); deep copy runs through + // entire data array assigning values. + virtual void DeepCopy(vtkPoints *ad); + virtual void ShallowCopy(vtkPoints *ad); + + // Description: + // Return the memory in kilobytes consumed by this attribute data. + // Used to support streaming and reading/writing data. The value + // returned is guaranteed to be greater than or equal to the + // memory required to actually represent the data represented + // by this object. The information returned is valid only after + // the pipeline has been updated. + unsigned long GetActualMemorySize(); + + // Description: + // Return number of points in array. + vtkIdType GetNumberOfPoints() { return this->Data->GetNumberOfTuples();}; + + // Description: + // Return a pointer to a double point x[3] for a specific id. + double *GetPoint(vtkIdType id) { return this->Data->GetTuple(id);}; + + // Description: + // Copy point components into user provided array v[3] for specified + // id. + void GetPoint(vtkIdType id, double x[3]) { this->Data->GetTuple(id,x);}; + + // Description: + // Insert point into object. No range checking performed (fast!). + // Make sure you use SetNumberOfPoints() to allocate memory prior + // to using SetPoint(). + void SetPoint(vtkIdType id, const float x[3]) { this->Data->SetTuple(id,x);}; + void SetPoint(vtkIdType id, const double x[3]) { this->Data->SetTuple(id,x);}; + void SetPoint(vtkIdType id, double x, double y, double z); + + // Description: + // Insert point into object. Range checking performed and memory + // allocated as necessary. + void InsertPoint(vtkIdType id, const float x[3]) + { this->Data->InsertTuple(id,x);}; + void InsertPoint(vtkIdType id, const double x[3]) + {this->Data->InsertTuple(id,x);}; + void InsertPoint(vtkIdType id, double x, double y, double z); + + // Description: + // Insert point into next available slot. Returns id of slot. + vtkIdType InsertNextPoint(const float x[3]) { + return this->Data->InsertNextTuple(x);}; + vtkIdType InsertNextPoint(const double x[3]) { + return this->Data->InsertNextTuple(x);}; + vtkIdType InsertNextPoint(double x, double y, double z); + + // Description: + // Specify the number of points for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetPoint() method for fast insertion. + void SetNumberOfPoints(vtkIdType number); + + // Description: + // Given a list of pt ids, return an array of points. + void GetPoints(vtkIdList *ptId, vtkPoints *fp); + + // Description: + // Determine (xmin,xmax, ymin,ymax, zmin,zmax) bounds of points. + virtual void ComputeBounds(); + + // Description: + // Return the bounds of the points. + double *GetBounds(); + + // Description: + // Return the bounds of the points. + void GetBounds(double bounds[6]); + +protected: + vtkPoints(int dataType=VTK_FLOAT); + ~vtkPoints(); + + double Bounds[6]; + vtkTimeStamp ComputeTime; // Time at which bounds computed + vtkDataArray *Data; // Array which represents data + +private: + vtkPoints(const vtkPoints&); // Not implemented. + void operator=(const vtkPoints&); // Not implemented. +}; + +inline void vtkPoints::SetNumberOfPoints(vtkIdType number) +{ + this->Data->SetNumberOfComponents(3); + this->Data->SetNumberOfTuples(number); +} + +inline void vtkPoints::SetPoint(vtkIdType id, double x, double y, double z) +{ + double p[3]; + p[0] = x; + p[1] = y; + p[2] = z; + this->Data->SetTuple(id,p); +} + +inline void vtkPoints::InsertPoint(vtkIdType id, double x, double y, double z) +{ + double p[3]; + + p[0] = x; + p[1] = y; + p[2] = z; + this->Data->InsertTuple(id,p); +} + +inline vtkIdType vtkPoints::InsertNextPoint(double x, double y, double z) +{ + double p[3]; + + p[0] = x; + p[1] = y; + p[2] = z; + return this->Data->InsertNextTuple(p); +} + +#endif + diff --git a/Common/vtkPriorityQueue.cxx b/Common/vtkPriorityQueue.cxx new file mode 100644 index 0000000..ede8c8e --- /dev/null +++ b/Common/vtkPriorityQueue.cxx @@ -0,0 +1,232 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPriorityQueue.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPriorityQueue.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPriorityQueue, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkPriorityQueue); + +// Instantiate priority queue with default size and extension size of 1000. +vtkPriorityQueue::vtkPriorityQueue() +{ + this->Size = 0; + this->Extend = 1000; + this->Array = NULL; + this->MaxId = -1; + this->ItemLocation = vtkIdTypeArray::New(); +} + +// Allocate priority queue with specified size and amount to extend +// queue (if reallocation required). +void vtkPriorityQueue::Allocate(const vtkIdType sz, const vtkIdType ext) +{ + this->ItemLocation->Allocate(sz,ext); + for (vtkIdType i=0; i < sz; i++) + { + this->ItemLocation->SetValue(i,-1); + } + + this->Size = ( sz > 0 ? sz : 1); + if ( this->Array != NULL ) + { + delete [] this->Array; + } + this->Array = new vtkPriorityQueue::Item[sz]; + this->Extend = ( ext > 0 ? ext : 1); + this->MaxId = -1; +} + +// Destructor for the vtkPriorityQueue class +vtkPriorityQueue::~vtkPriorityQueue() +{ + this->ItemLocation->Delete(); + if ( this->Array ) + { + delete [] this->Array; + } +} + +// Insert id with priority specified. +void vtkPriorityQueue::Insert(double priority, vtkIdType id) +{ + vtkIdType i, idx; + vtkPriorityQueue::Item temp; + + // check and make sure item hasn't been inserted before + if ( id <= this->ItemLocation->GetMaxId() && + this->ItemLocation->GetValue(id) != -1 ) + { + return; + } + + // start by placing new entry at bottom of tree + if ( ++this->MaxId >= this->Size ) + { + this->Resize(this->MaxId + 1); + } + this->Array[this->MaxId].priority = priority; + this->Array[this->MaxId].id = id; + if ( id >= this->ItemLocation->GetSize() ) //might have to resize and initialize + { + vtkIdType oldSize = this->ItemLocation->GetSize(); + this->ItemLocation->InsertValue(id,this->MaxId); + for (i=oldSize; i < this->ItemLocation->GetSize(); i++) + { + this->ItemLocation->SetValue(i, -1); + } + this->ItemLocation->SetValue(id,this->MaxId); + } + + this->ItemLocation->InsertValue(id,this->MaxId); + + // now begin percolating towards top of tree + for ( i=this->MaxId; + i > 0 && this->Array[i].priority < this->Array[(idx=(i-1)/2)].priority; + i=idx) + { + temp = this->Array[i]; + + this->ItemLocation->SetValue(temp.id,idx); + this->Array[i] = this->Array[idx]; + + this->ItemLocation->SetValue(this->Array[idx].id,i); + this->Array[idx] = temp; + } +} + +// Simplified call for easier wrapping for Tcl. +vtkIdType vtkPriorityQueue::Pop(vtkIdType location) +{ + double priority; + return this->Pop(location, priority); +} + +// Removes item at specified location from tree; then reorders and +// balances tree. The location == 0 is the root of the tree. +vtkIdType vtkPriorityQueue::Pop(vtkIdType location, double &priority) +{ + vtkIdType id, i, j, idx; + vtkPriorityQueue::Item temp; + + if ( this->MaxId < 0 ) + { + return -1; + } + + id = this->Array[location].id; + priority = this->Array[location].priority; + + // move the last item to the location specified and push into the tree + this->Array[location].id = this->Array[this->MaxId].id; + this->Array[location].priority = this->Array[this->MaxId].priority; + + this->ItemLocation->SetValue(this->Array[location].id,location); + this->ItemLocation->SetValue(id,-1); + + if ( --this->MaxId <= 0 ) + { + return id; + } + + // percolate into the tree + for ( j=0, i=location; i <= (this->MaxId-1)/2; i=j ) + { + idx = 2*i + 1; + + if ( this->Array[idx].priority < this->Array[idx+1].priority || + idx == this->MaxId ) + { + j = idx; + } + else + { + j = idx + 1; + } + + if ( this->Array[i].priority > this->Array[j].priority ) + { + temp = this->Array[i]; + + this->ItemLocation->SetValue(temp.id,j); + this->Array[i] = this->Array[j]; + + this->ItemLocation->SetValue(this->Array[j].id,i); + this->Array[j] = temp; + } + else + { + break; + } + } + + return id; +} + +// Protected method reallocates queue. +vtkPriorityQueue::Item *vtkPriorityQueue::Resize(const vtkIdType sz) +{ + vtkPriorityQueue::Item *newArray; + vtkIdType newSize; + + if (sz >= this->Size) + { + newSize = this->Size + sz; + } + else + { + newSize = sz; + } + + if (newSize <= 0) + { + newSize = 1; + } + + newArray = new vtkPriorityQueue::Item[newSize]; + + if (this->Array) + { + memcpy(newArray, this->Array, + (sz < this->Size ? sz : this->Size) * sizeof(vtkPriorityQueue::Item)); + delete [] this->Array; + } + + this->Size = newSize; + this->Array = newArray; + + return this->Array; +} + +// Reset all of the entries in the queue so they don not have a priority +void vtkPriorityQueue::Reset() +{ + this->MaxId = -1; + + for (int i=0; i <= this->ItemLocation->GetMaxId(); i++) + { + this->ItemLocation->SetValue(i,-1); + } + this->ItemLocation->Reset(); +} + +void vtkPriorityQueue::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Entries: " << this->MaxId + 1 << "\n"; + os << indent << "Size: " << this->Size << "\n"; + os << indent << "Extend size: " << this->Extend << "\n"; +} + diff --git a/Common/vtkPriorityQueue.h b/Common/vtkPriorityQueue.h new file mode 100644 index 0000000..ab853ae --- /dev/null +++ b/Common/vtkPriorityQueue.h @@ -0,0 +1,181 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPriorityQueue.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPriorityQueue - an list of ids arranged in priority order +// .SECTION Description +// vtkPriorityQueue is a general object for creating and manipulating lists +// of object ids (e.g., point or cell ids). Object ids are sorted according +// to a user-specified priority, where entries at the top of the queue have +// the smallest values. +// +// This implementation provides a feature beyond the usual ability to insert +// and retrieve (or pop) values from the queue. It is also possible to +// pop any item in the queue given its id number. This allows you to delete +// entries in the queue which can useful for reinserting an item into the +// queue. +// +// .SECTION Caveats +// This implementation is a variation of the priority queue described in +// "Data Structures & Algorithms" by Aho, Hopcroft, Ullman. It creates +// a balanced, partially ordered binary tree implemented as an ordered +// array. This avoids the overhead associated with parent/child pointers, +// and frequent memory allocation and deallocation. + +#ifndef __vtkPriorityQueue_h +#define __vtkPriorityQueue_h + +#include "vtkObject.h" + +#include "vtkIdTypeArray.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkPriorityQueue : public vtkObject +{ +public: + //BTX + class Item + { + public: + double priority; + vtkIdType id; + }; + //ETX + + // Description: + // Instantiate priority queue with default size and extension size of 1000. + static vtkPriorityQueue *New(); + + vtkTypeRevisionMacro(vtkPriorityQueue,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate initial space for priority queue. + void Allocate(const vtkIdType sz, const vtkIdType ext=1000); + + // Description: + // Insert id with priority specified. The id is generally an + // index like a point id or cell id. + void Insert(double priority, vtkIdType id); + + // Description: + // Removes item at specified location from tree; then reorders and + // balances tree. The location == 0 is the root of the tree. If queue + // is exhausted, then a value < 0 is returned. (Note: the location + // is not the same as deleting an id; id is mapped to location.) +//BTX + vtkIdType Pop(vtkIdType location, double &priority); +//ETX + + // Description: + // Same as above but simplified for easier wrapping into interpreted + // languages. + vtkIdType Pop(vtkIdType location=0); + + // Description: + // Peek into the queue without actually removing anything. Returns the + // id and the priority. +//BTX + vtkIdType Peek(vtkIdType location, double &priority); +//ETX + + // Description: + // Peek into the queue without actually removing anything. Returns the + // id. + vtkIdType Peek(vtkIdType location=0); + + // Description: + // Delete entry in queue with specified id. Returns priority value + // associated with that id; or VTK_DOUBLE_MAX if not in queue. + double DeleteId(vtkIdType id); + + // Description: + // Get the priority of an entry in the queue with specified id. Returns + // priority value of that id or VTK_DOUBLE_MAX if not in queue. + double GetPriority(vtkIdType id); + + // Description: + // Return the number of items in this queue. + vtkIdType GetNumberOfItems() {return this->MaxId+1;}; + + // Description: + // Empty the queue but without releasing memory. This avoids the + // overhead of memory allocation/deletion. + void Reset(); + +protected: + vtkPriorityQueue(); + ~vtkPriorityQueue(); + + Item *Resize(const vtkIdType sz); + + vtkIdTypeArray *ItemLocation; + Item *Array; + vtkIdType Size; + vtkIdType MaxId; + vtkIdType Extend; +private: + vtkPriorityQueue(const vtkPriorityQueue&); // Not implemented. + void operator=(const vtkPriorityQueue&); // Not implemented. +}; + +inline double vtkPriorityQueue::DeleteId(vtkIdType id) +{ + double priority=VTK_DOUBLE_MAX; + int loc; + + if ( id <= this->ItemLocation->GetMaxId() && + (loc=this->ItemLocation->GetValue(id)) != -1 ) + { + this->Pop(loc,priority); + } + return priority; +} + +inline double vtkPriorityQueue::GetPriority(vtkIdType id) +{ + int loc; + + if ( id <= this->ItemLocation->GetMaxId() && + (loc=this->ItemLocation->GetValue(id)) != -1 ) + { + return this->Array[loc].priority; + } + return VTK_DOUBLE_MAX; +} + +inline vtkIdType vtkPriorityQueue::Peek(vtkIdType location, double &priority) +{ + if ( this->MaxId < 0 ) + { + return -1; + } + else + { + priority = this->Array[location].priority; + return this->Array[location].id; + } +} + +inline vtkIdType vtkPriorityQueue::Peek(vtkIdType location) +{ + if ( this->MaxId < 0 ) + { + return -1; + } + else + { + return this->Array[location].id; + } +} + +#endif diff --git a/Common/vtkProcessStatistics.cxx b/Common/vtkProcessStatistics.cxx new file mode 100644 index 0000000..28cf1e7 --- /dev/null +++ b/Common/vtkProcessStatistics.cxx @@ -0,0 +1,148 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcessStatistics.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProcessStatistics.h" + +vtkCxxRevisionMacro(vtkProcessStatistics, "$Revision: 1.13 $"); + +#ifndef _WIN32 +#include +#include +#include +#include +#include "vtkObjectFactory.h" + +vtkStandardNewMacro(vtkProcessStatistics); + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ +#endif _WIN32 + +// Construct the ProcessStatistics with eight points. +vtkProcessStatistics::vtkProcessStatistics() +{ +} + + +int vtkProcessStatistics::GetProcessSizeInBytes() +{ + +#ifndef _WIN32 + prpsinfo psinfo; + int fd; + char pname[1024]; + int pagesize; + pid_t pid; + + // Get out process id + pid = getpid(); + + // Get the size of a page in bytes + pagesize = getpagesize(); + + // Open the /proc/ file and query the + // process info + sprintf( pname, "/proc/%d", pid ); + fd = open( pname, O_RDONLY ); + if (fd != -1) + { + psinfo.pr_size = 0; + ioctl( fd, PIOCPSINFO, &psinfo ); + close( fd ); + } + else + { + vtkErrorMacro(<< "Cannot get size of " << pname); + return 0; + } + + // The size in bytes is the page size of the process times + // the size of a page in bytes + return psinfo.pr_size * pagesize; +#endif + +#ifdef _WIN32 + return 0; +#endif + +} + +double vtkProcessStatistics::GetProcessCPUTimeInMilliseconds() +{ + +#ifndef _WIN32 + prpsinfo psinfo; + int fd; + char pname[1024]; + pid_t pid; + + // Get out process id + pid = getpid(); + + // Open the /proc/ file and query the + // process info + sprintf( pname, "/proc/%d", pid ); + fd = open( pname, O_RDONLY ); + ioctl( fd, PIOCPSINFO, &psinfo ); + close( fd ); + + return + (double) psinfo.pr_time.tv_sec * 1000.0 + + (double) psinfo.pr_time.tv_nsec / 1000000.0; +#endif + +#ifdef _WIN32 + return 0.0; +#endif + +} + diff --git a/Common/vtkProcessStatistics.h b/Common/vtkProcessStatistics.h new file mode 100644 index 0000000..f588239 --- /dev/null +++ b/Common/vtkProcessStatistics.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcessStatistics.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProcessStatistics - get statistics such as cpu and memory usage +// .SECTION Description + +#ifndef __vtkProcessStatistics_h +#define __vtkProcessStatistics_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkProcessStatistics : public vtkObject +{ +public: + // Description: + // Construct the ProcessStatistics with eight points. + static vtkProcessStatistics *New(); + + vtkTypeRevisionMacro(vtkProcessStatistics,vtkObject); + + int GetProcessSizeInBytes(); + double GetProcessCPUTimeInMilliseconds(); + +protected: + vtkProcessStatistics(); + ~vtkProcessStatistics() {}; + + +private: + vtkProcessStatistics(const vtkProcessStatistics&); // Not implemented. + void operator=(const vtkProcessStatistics&); // Not implemented. +}; + +#endif + + diff --git a/Common/vtkProp.cxx b/Common/vtkProp.cxx new file mode 100644 index 0000000..a61b8eb --- /dev/null +++ b/Common/vtkProp.cxx @@ -0,0 +1,186 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProp.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProp.h" +#include "vtkObjectFactory.h" +#include "vtkAssemblyPaths.h" +#include "vtkCommand.h" + +vtkCxxRevisionMacro(vtkProp, "$Revision: 1.25 $"); + +// Creates an Prop with the following defaults: visibility on. +vtkProp::vtkProp() +{ + this->Visibility = 1; // ON + + this->Pickable = 1; + this->Dragable = 1; + + this->AllocatedRenderTime = 10.0; + this->EstimatedRenderTime = 0.0; + this->RenderTimeMultiplier = 1.0; + + this->Paths = NULL; + + this->NumberOfConsumers = 0; + this->Consumers = 0; +} + +vtkProp::~vtkProp() +{ + if ( this->Paths ) + { + this->Paths->Delete(); + } + if (this->Consumers) + { + delete [] this->Consumers; + } +} + +// This method is invoked if the prop is picked. +void vtkProp::Pick() +{ + this->InvokeEvent(vtkCommand::PickEvent,NULL); +} + +// Shallow copy of vtkProp. +void vtkProp::ShallowCopy(vtkProp *prop) +{ + this->Visibility = prop->GetVisibility(); + this->Pickable = prop->GetPickable(); + this->Dragable = prop->GetDragable(); +} + +void vtkProp::InitPathTraversal() +{ + if ( this->Paths == NULL ) + { + this->Paths = vtkAssemblyPaths::New(); + vtkAssemblyPath *path = vtkAssemblyPath::New(); + path->AddNode(this,NULL); + this->BuildPaths(this->Paths,path); + path->Delete(); + } + this->Paths->InitTraversal(); +} + +vtkAssemblyPath *vtkProp::GetNextPath() +{ + if ( ! this->Paths) + { + return NULL; + } + return this->Paths->GetNextItem(); +} + +// This method is used in conjunction with the assembly object to build a copy +// of the assembly hierarchy. This hierarchy can then be traversed for +// rendering, picking or other operations. +void vtkProp::BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path) +{ + // This is a leaf node in the assembly hierarchy so we + // copy the path in preparation to assingning it to paths. + vtkAssemblyPath *childPath = vtkAssemblyPath::New(); + childPath->ShallowCopy(path); + + // We can add this path to the list of paths + paths->AddItem(childPath); + childPath->Delete(); //okay, reference counting +} + +void vtkProp::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Dragable: " << (this->Dragable ? "On\n" : "Off\n"); + os << indent << "Pickable: " << (this->Pickable ? "On\n" : "Off\n"); + + os << indent << "AllocatedRenderTime: " + << this->AllocatedRenderTime << endl; + os << indent << "EstimatedRenderTime: " + << this->EstimatedRenderTime << endl; + os << indent << "NumberOfConsumers: " << this->NumberOfConsumers << endl; + os << indent << "RenderTimeMultiplier: " + << this->RenderTimeMultiplier << endl; + os << indent << "Visibility: " << (this->Visibility ? "On\n" : "Off\n"); +} + + +void vtkProp::AddConsumer(vtkObject *c) +{ + // make sure it isn't already there + if (this->IsConsumer(c)) + { + return; + } + // add it to the list, reallocate memory + vtkObject **tmp = this->Consumers; + this->NumberOfConsumers++; + this->Consumers = new vtkObject* [this->NumberOfConsumers]; + for (int i = 0; i < (this->NumberOfConsumers-1); i++) + { + this->Consumers[i] = tmp[i]; + } + this->Consumers[this->NumberOfConsumers-1] = c; + // free old memory + delete [] tmp; +} + +void vtkProp::RemoveConsumer(vtkObject *c) +{ + // make sure it is already there + if (!this->IsConsumer(c)) + { + return; + } + // remove it from the list, reallocate memory + vtkObject **tmp = this->Consumers; + this->NumberOfConsumers--; + this->Consumers = new vtkObject* [this->NumberOfConsumers]; + int cnt = 0; + int i; + for (i = 0; i <= this->NumberOfConsumers; i++) + { + if (tmp[i] != c) + { + this->Consumers[cnt] = tmp[i]; + cnt++; + } + } + // free old memory + delete [] tmp; +} + +int vtkProp::IsConsumer(vtkObject *c) +{ + int i; + for (i = 0; i < this->NumberOfConsumers; i++) + { + if (this->Consumers[i] == c) + { + return 1; + } + } + return 0; +} + +vtkObject *vtkProp::GetConsumer(int i) +{ + if (i >= this->NumberOfConsumers) + { + return 0; + } + return this->Consumers[i]; +} diff --git a/Common/vtkProp.h b/Common/vtkProp.h new file mode 100644 index 0000000..620084e --- /dev/null +++ b/Common/vtkProp.h @@ -0,0 +1,269 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProp.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProp - abstract superclass for all actors, volumes and annotations +// .SECTION Description +// vtkProp is an abstract superclass for any objects that can exist in a +// rendered scene (either 2D or 3D). Instances of vtkProp may respond to +// various render methods (e.g., RenderOpaqueGeometry()). vtkProp also +// defines the API for picking, LOD manipulation, and common instance +// variables that control visibility, picking, and dragging. +// .SECTION See Also +// vtkActor2D vtkActor vtkVolume vtkProp3D + +#ifndef __vtkProp_h +#define __vtkProp_h + +#include "vtkObject.h" + +class vtkAssemblyPath; +class vtkAssemblyPaths; +class vtkMatrix4x4; +class vtkPropCollection; +class vtkViewport; +class vtkWindow; + +class VTK_COMMON_EXPORT vtkProp : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkProp,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. These methods + // are used in that process. + virtual void GetActors(vtkPropCollection *) {} + virtual void GetActors2D(vtkPropCollection *) {} + virtual void GetVolumes(vtkPropCollection *) {} + + // Description: + // Set/Get visibility of this vtkProp. + vtkSetMacro(Visibility, int); + vtkGetMacro(Visibility, int); + vtkBooleanMacro(Visibility, int); + + // Description: + // Set/Get the pickable instance variable. This determines if the vtkProp + // can be picked (typically using the mouse). Also see dragable. + vtkSetMacro(Pickable,int); + vtkGetMacro(Pickable,int); + vtkBooleanMacro(Pickable,int); + + // Description: + // Method fires PickEvent if the prop is picked. + virtual void Pick(); + + // Description: + // Set/Get the value of the dragable instance variable. This determines if + // an Prop, once picked, can be dragged (translated) through space. + // This is typically done through an interactive mouse interface. + // This does not affect methods such as SetPosition, which will continue + // to work. It is just intended to prevent some vtkProp'ss from being + // dragged from within a user interface. + vtkSetMacro(Dragable,int); + vtkGetMacro(Dragable,int); + vtkBooleanMacro(Dragable,int); + + // Description: + // Return the mtime of anything that would cause the rendered image to + // appear differently. Usually this involves checking the mtime of the + // prop plus anything else it depends on such as properties, textures + // etc. + virtual unsigned long GetRedrawMTime() {return this->GetMTime();} + + // Description: + // Get the bounds for this Prop as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). + // in world coordinates. NULL means that the bounds are not defined. + virtual double *GetBounds() {return NULL;} + + // Description: + // Shallow copy of this vtkProp. + virtual void ShallowCopy(vtkProp *prop); + + // Description: + // vtkProp and its subclasses can be picked by subclasses of + // vtkAbstractPicker (e.g., vtkPropPicker). The following methods interface + // with the picking classes and return "pick paths". A pick path is a + // hierarchical, ordered list of props that form an assembly. Most often, + // when a vtkProp is picked, its path consists of a single node (i.e., the + // prop). However, classes like vtkAssembly and vtkPropAssembly can return + // more than one path, each path being several layers deep. (See + // vtkAssemblyPath for more information.) To use these methods - first + // invoke InitPathTraversal() followed by repeated calls to GetNextPath(). + // GetNextPath() returns a NULL pointer when the list is exhausted. + virtual void InitPathTraversal(); + virtual vtkAssemblyPath *GetNextPath(); + virtual int GetNumberOfPaths() {return 1;} + + // Description: + // These methods are used by subclasses to place a matrix (if any) in the + // prop prior to rendering. Generally used only for picking. See vtkProp3D + // for more information. + virtual void PokeMatrix(vtkMatrix4x4 *vtkNotUsed(matrix)) {} + virtual vtkMatrix4x4 *GetMatrix() {return NULL;} + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THESE METHODS OUTSIDE OF THE RENDERING PROCESS + // All concrete subclasses must be able to render themselves. + // There are three key render methods in vtk and they correspond + // to three different points in the rendering cycle. Any given + // prop may implement one or more of these methods. + // The first method is intended for rendering all opaque geometry. The + // second method is intended for rendering all translucent geometry. Most + // volume rendering mappers draw their results during this second method. + // The last method is to render any 2D annotation or overlays. + // Each of these methods return an integer value indicating + // whether or not this render method was applied to this data. + virtual int RenderOpaqueGeometry( vtkViewport *) { return 0; } + virtual int RenderTranslucentGeometry( vtkViewport *) { return 0; } + virtual int RenderOverlay( vtkViewport *) { return 0; } + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *) {} + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THESE METHODS OUTSIDE OF THE RENDERING PROCESS + // The EstimatedRenderTime may be used to select between different props, + // for example in LODProp it is used to select the level-of-detail. + // The value is returned in seconds. For simple geometry the accuracy may + // not be great due to buffering. For ray casting, which is already + // multi-resolution, the current resolution of the image is factored into + // the time. We need the viewport for viewing parameters that affect timing. + // The no-arguments version simply returns the value of the variable with + // no estimation. + virtual double GetEstimatedRenderTime( vtkViewport * ) + { return this->EstimatedRenderTime; } + virtual double GetEstimatedRenderTime(){ return this->EstimatedRenderTime; } + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THESE METHODS OUTSIDE OF THE RENDERING PROCESS + // This method is used by, for example, the vtkLODProp3D in order to + // initialize the estimated render time at start-up to some user defined + // value. + virtual void SetEstimatedRenderTime(double t) + {this->EstimatedRenderTime = t; this->SavedEstimatedRenderTime = t;} + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THESE METHODS OUTSIDE OF THE RENDERING PROCESS + // When the EstimatedRenderTime is first set to 0.0 (in the + // SetAllocatedRenderTime method) the old value is saved. This + // method is used to restore that old value should the render be + // aborted. + virtual void RestoreEstimatedRenderTime() + { this->EstimatedRenderTime = this->SavedEstimatedRenderTime; } + + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // This method is intended to allow the renderer to add to the + // EstimatedRenderTime in props that require information that + // the renderer has in order to do this. For example, props + // that are rendered with a ray casting method do not know + // themselves how long it took for them to render. We don't want to + // cause a this->Modified() when we set this value since it is not + // really a modification to the object. (For example, we don't want + // to rebuild matrices at every render because the estimated render time + // is changing) + virtual void AddEstimatedRenderTime(double t, vtkViewport *vtkNotUsed(vp)) + {this->EstimatedRenderTime+=t;} + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // The renderer may use the allocated rendering time to determine + // how to render this actor. Therefore it might need the information + // provided in the viewport. + // A side effect of this method is to reset the EstimatedRenderTime to + // 0.0. This way, each of the ways that this prop may be rendered can + // be timed and added together into this value. + virtual void SetAllocatedRenderTime(double t, vtkViewport *vtkNotUsed(v)) + { + this->AllocatedRenderTime = t; + this->SavedEstimatedRenderTime = this->EstimatedRenderTime; + this->EstimatedRenderTime = 0.0; + } + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + vtkGetMacro(AllocatedRenderTime, double); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Get/Set the multiplier for the render time. This is used + // for culling and is a number between 0 and 1. It is used + // to create the allocated render time value. + void SetRenderTimeMultiplier( double t ) { this->RenderTimeMultiplier = t; } + vtkGetMacro(RenderTimeMultiplier, double); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Used to construct assembly paths and perform part traversal. + virtual void BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path); + + // Description: + // Get the number of consumers + vtkGetMacro(NumberOfConsumers,int); + + // Description: + // Add or remove or get or check a consumer, + void AddConsumer(vtkObject *c); + void RemoveConsumer(vtkObject *c); + vtkObject *GetConsumer(int i); + int IsConsumer(vtkObject *c); + +//ETX + +protected: + vtkProp(); + ~vtkProp(); + + int Visibility; + int Pickable; + int Dragable; + + double AllocatedRenderTime; + double EstimatedRenderTime; + double SavedEstimatedRenderTime; + double RenderTimeMultiplier; + + // how many consumers does this object have + int NumberOfConsumers; + vtkObject **Consumers; + + // support multi-part props and access to paths of prop + // stuff that follows is used to build the assembly hierarchy + vtkAssemblyPaths *Paths; + +private: + vtkProp(const vtkProp&); // Not implemented. + void operator=(const vtkProp&); // Not implemented. +}; + +#endif + + diff --git a/Common/vtkPropCollection.cxx b/Common/vtkPropCollection.cxx new file mode 100644 index 0000000..49fff64 --- /dev/null +++ b/Common/vtkPropCollection.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPropCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPropCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPropCollection, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkPropCollection); + +int vtkPropCollection::GetNumberOfPaths() +{ + int numPaths=0; + vtkProp *aProp; + + vtkCollectionSimpleIterator pit; + for ( this->InitTraversal(pit); (aProp=this->GetNextProp(pit)); ) + { + numPaths += aProp->GetNumberOfPaths(); + } + return numPaths; +} diff --git a/Common/vtkPropCollection.h b/Common/vtkPropCollection.h new file mode 100644 index 0000000..2ba9689 --- /dev/null +++ b/Common/vtkPropCollection.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPropCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPropCollection - a list of Props +// .SECTION Description +// vtkPropCollection represents and provides methods to manipulate a list of +// Props (i.e., vtkProp and subclasses). The list is unsorted and duplicate +// entries are not prevented. + +// .SECTION see also +// vtkProp vtkCollection + +#ifndef __vtkPropC_h +#define __vtkPropC_h + +#include "vtkCollection.h" + +#include "vtkProp.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkPropCollection : public vtkCollection +{ + public: + static vtkPropCollection *New(); + vtkTypeRevisionMacro(vtkPropCollection,vtkCollection); + + // Description: + // Add an Prop to the list. + void AddItem(vtkProp *a); + + // Description: + // Get the next Prop in the list. + vtkProp *GetNextProp(); + + // Description: + // Get the last Prop in the list. + vtkProp *GetLastProp(); + + // Description: + // Get the number of paths contained in this list. (Recall that a + // vtkProp can consist of multiple parts.) Used in picking and other + // activities to get the parts of composite entities like vtkAssembly + // or vtkPropAssembly. + int GetNumberOfPaths(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkProp *GetNextProp(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkPropCollection() {}; + ~vtkPropCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkPropCollection(const vtkPropCollection&); // Not implemented. + void operator=(const vtkPropCollection&); // Not implemented. +}; + +inline void vtkPropCollection::AddItem(vtkProp *a) +{ + this->vtkCollection::AddItem((vtkObject *)a); +} + +inline vtkProp *vtkPropCollection::GetNextProp() +{ + return static_cast(this->GetNextItemAsObject()); +} + +inline vtkProp *vtkPropCollection::GetLastProp() +{ + if ( this->Bottom == NULL ) + { + return NULL; + } + else + { + return static_cast(this->Bottom->Item); + } +} + +#endif + + + + + diff --git a/Common/vtkProperty2D.cxx b/Common/vtkProperty2D.cxx new file mode 100644 index 0000000..fc6f77c --- /dev/null +++ b/Common/vtkProperty2D.cxx @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProperty2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProperty2D.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkProperty2D, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkProperty2D); + +// Creates a vtkProperty2D with the following default values: +// Opacity 1, Color (1,0,0), CompositingOperator VTK_SRC +vtkProperty2D::vtkProperty2D() +{ + this->Opacity = 1.0; + this->PointSize = 1.0; + this->LineWidth = 1.0; + this->LineStipplePattern = 0xFFFF; + this->LineStippleRepeatFactor = 1; + this->Color[0] = 1.0; + this->Color[1] = 1.0; + this->Color[2] = 1.0; + this->DisplayLocation = VTK_FOREGROUND_LOCATION; +} + +vtkProperty2D::~vtkProperty2D() +{ +} + +// Assign one property to another. +void vtkProperty2D::DeepCopy(vtkProperty2D *p) +{ + if ( p != NULL ) + { + this->SetColor(p->GetColor()); + this->SetOpacity(p->GetOpacity()); + this->SetPointSize(p->GetPointSize()); + this->SetLineWidth(p->GetLineWidth()); + this->SetLineStipplePattern(p->GetLineStipplePattern()); + this->SetLineStippleRepeatFactor(p->GetLineStippleRepeatFactor()); + this->SetDisplayLocation(p->GetDisplayLocation()); + } +} + +void vtkProperty2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Opacity: " << this->Opacity << "\n"; + os << indent << "Color: (" << this->Color[0] << ", " + << this->Color[1] << ", " + << this->Color[2] << ")\n"; + os << indent << "Point size: " << this->PointSize << "\n"; + os << indent << "Line width: " << this->LineWidth << "\n"; + os << indent << "Line stipple pattern: " << this->LineStipplePattern << "\n"; + os << indent << "Line stipple repeat factor: " << this->LineStippleRepeatFactor << "\n"; + switch ( this->DisplayLocation ) + { + case VTK_FOREGROUND_LOCATION: + os << indent << "Display location: foreground\n"; + break; + case VTK_BACKGROUND_LOCATION: + os << indent << "Display location: background\n"; + break; + default: + os << indent << "Display location: invalid\n"; + break; + } + +} + + + + diff --git a/Common/vtkProperty2D.h b/Common/vtkProperty2D.h new file mode 100644 index 0000000..59644d2 --- /dev/null +++ b/Common/vtkProperty2D.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProperty2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProperty2D - represent surface properties of a 2D image +// .SECTION Description +// vtkProperty2D contains properties used to render two dimensional images +// and annotations. + +// .SECTION See Also +// vtkActor2D + +#ifndef __vtkProperty2D_h +#define __vtkProperty2D_h + +#include "vtkObject.h" + +class vtkViewport; + +#define VTK_BACKGROUND_LOCATION 0 +#define VTK_FOREGROUND_LOCATION 1 + +class VTK_COMMON_EXPORT vtkProperty2D : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkProperty2D,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates a vtkProperty2D with the following default values: + // Opacity 1, Color (1,1,1) + static vtkProperty2D *New(); + + // Description: + // Assign one property to another. + void DeepCopy(vtkProperty2D *p); + + // Description: + // Set/Get the RGB color of this property. + vtkSetVector3Macro(Color, double); + vtkGetVectorMacro(Color, double, 3); + + // Description: + // Set/Get the Opacity of this property. + vtkGetMacro(Opacity, double); + vtkSetMacro(Opacity, double); + + // Description: + // Set/Get the diameter of a Point. The size is expressed in screen units. + // This is only implemented for OpenGL. The default is 1.0. + vtkSetClampMacro(PointSize,float,0,VTK_LARGE_FLOAT); + vtkGetMacro(PointSize,float); + + // Description: + // Set/Get the width of a Line. The width is expressed in screen units. + // This is only implemented for OpenGL. The default is 1.0. + vtkSetClampMacro(LineWidth,float,0,VTK_LARGE_FLOAT); + vtkGetMacro(LineWidth,float); + + // Description: + // Set/Get the stippling pattern of a Line, as a 16-bit binary pattern + // (1 = pixel on, 0 = pixel off). + // This is only implemented for OpenGL. The default is 0xFFFF. + vtkSetMacro(LineStipplePattern,int); + vtkGetMacro(LineStipplePattern,int); + + // Description: + // Set/Get the stippling repeat factor of a Line, which specifies how + // many times each bit in the pattern is to be repeated. + // This is only implemented for OpenGL. The default is 1. + vtkSetClampMacro(LineStippleRepeatFactor,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(LineStippleRepeatFactor,int); + + // Description: + // The DisplayLocation is either background or foreground. + // If it is background, then this 2D actor will be drawn + // behind all 3D props or foreground 2D actors. If it is + // background, then this 2D actor will be drawn in front of + // all 3D props and background 2D actors. Within 2D actors + // of the same DisplayLocation type, order is determined by + // the order in which the 2D actors were added to the viewport. + vtkSetClampMacro( DisplayLocation, int, + VTK_BACKGROUND_LOCATION, VTK_FOREGROUND_LOCATION ); + vtkGetMacro( DisplayLocation, int ); + void SetDisplayLocationToBackground() + {this->DisplayLocation = VTK_BACKGROUND_LOCATION;}; + void SetDisplayLocationToForeground() + {this->DisplayLocation = VTK_FOREGROUND_LOCATION;}; + + + // Description: + // Have the device specific subclass render this property. + virtual void Render (vtkViewport* vtkNotUsed(viewport)) {} + +protected: + vtkProperty2D(); + ~vtkProperty2D(); + + double Color[3]; + double Opacity; + float PointSize; + float LineWidth; + int LineStipplePattern; + int LineStippleRepeatFactor; + int DisplayLocation; +private: + vtkProperty2D(const vtkProperty2D&); // Not implemented. + void operator=(const vtkProperty2D&); // Not implemented. +}; + + +#endif + + + diff --git a/Common/vtkPython.h b/Common/vtkPython.h new file mode 100644 index 0000000..f9afe3b --- /dev/null +++ b/Common/vtkPython.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPython.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkPython_h +#define __vtkPython_h + +#undef _POSIX_THREADS + +#include "vtkToolkits.h" + +/* + Use the real python debugging library if it is provided. + Otherwise use the "documented" trick involving checking for _DEBUG + and undefined that symbol while we include Python headers. + Update: this method does not fool Microsoft Visual C++ 8 anymore; two + of its header files (crtdefs.h and use_ansi.h) check if _DEBUG was set + or not, and set flags accordingly (_CRT_MANIFEST_RETAIL, + _CRT_MANIFEST_DEBUG, _CRT_MANIFEST_INCONSISTENT). The next time the + check is performed in the same compilation unit, and the flags are found, + and error is triggered. Let's prevent that by setting _CRT_NOFORCE_MANIFEST. +*/ +#if defined(VTK_WINDOWS_PYTHON_DEBUGGABLE) +# include +#else +# ifdef _DEBUG +# undef _DEBUG +# if defined(_MSC_VER) && _MSC_VER >= 1400 +# define _CRT_NOFORCE_MANIFEST 1 +# endif +# include +# define _DEBUG +# else +# include +# endif +#endif + +#endif diff --git a/Common/vtkPythonUtil.cxx b/Common/vtkPythonUtil.cxx new file mode 100644 index 0000000..2232d58 --- /dev/null +++ b/Common/vtkPythonUtil.cxx @@ -0,0 +1,2006 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPythonUtil.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// This include allows VTK to build on some platforms with broken Python +// header files. +#include "vtkPythonUtil.h" + +#include "vtkSystemIncludes.h" + +#include "vtkObject.h" +#include "vtkObjectFactory.h" +#include "vtkSmartPointerBase.h" +#include "vtkTimeStamp.h" +#include "vtkWindows.h" + +#include +#include + +#if defined ( _MSC_VER ) +# define vtkConvertPtrToLong(x) ((long)(PtrToUlong(x))) +#else +# define vtkConvertPtrToLong(x) ((long)(x)) +#endif + +// The following macro is used to supress missing initializer +// warnings. Python documentation says these should not be necessary. +// We define it as a macro in case the length needs to change across +// python versions. +#if PY_VERSION_HEX >= 0x02030000 +#define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED \ + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0, +#elif PY_VERSION_HEX >= 0x02020000 +#define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED \ + 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, +#else +#define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED +#endif + +//#define VTKPYTHONDEBUG + +//-------------------------------------------------------------------- +// There are two hash tables associated with the Python wrappers + +class vtkPythonUtil +{ +public: + vtkPythonUtil(); + ~vtkPythonUtil(); + + vtkstd::map *ObjectHash; + vtkstd::map *ClassHash; +}; + +//-------------------------------------------------------------------- +vtkPythonUtil *vtkPythonHash = NULL; + +//-------------------------------------------------------------------- +vtkPythonUtil::vtkPythonUtil() +{ + this->ObjectHash = new vtkstd::map; + this->ClassHash = new vtkstd::map;; +} + +//-------------------------------------------------------------------- +vtkPythonUtil::~vtkPythonUtil() +{ + delete this->ObjectHash; + delete this->ClassHash; +} + +//-------------------------------------------------------------------- +extern "C" void vtkPythonHashDelete() +{ + delete vtkPythonHash; + vtkPythonHash = 0; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKObject_PyString(PyVTKObject *self) +{ + PyObject *func = PyObject_GetAttrString((PyObject *)self, (char*)"__str__"); + + if (func) + { + PyObject *res = PyEval_CallObject(func, (PyObject *)NULL); + Py_DECREF(func); + return res; + } + PyErr_Clear(); + + ostrstream vtkmsg_with_warning_C4701; + self->vtk_ptr->Print(vtkmsg_with_warning_C4701); + vtkmsg_with_warning_C4701.put('\0'); + PyObject *res = PyString_FromString(vtkmsg_with_warning_C4701.str()); + vtkmsg_with_warning_C4701.rdbuf()->freeze(0); + return res; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKObject_PyRepr(PyVTKObject *self) +{ + PyObject *func = PyObject_GetAttrString((PyObject *)self, (char*)"__repr__"); + + if (func) + { + PyObject *res = PyEval_CallObject(func, (PyObject *)NULL); + Py_DECREF(func); + return res; + } + PyErr_Clear(); + + char buf[255]; + sprintf(buf,"<%s.%s %s at %p>", + PyString_AsString(self->vtk_class->vtk_module), + PyString_AsString(self->vtk_class->vtk_name), + self->ob_type->tp_name,self); + + return PyString_FromString(buf); +} + +//-------------------------------------------------------------------- +int PyVTKObject_PySetAttr(PyVTKObject *self, PyObject *attr, + PyObject *value) +{ + char *name = PyString_AsString(attr); + + if (name[0] == '_' && name[1] == '_') + { + if (strcmp(name, "__dict__") == 0) + { + PyErr_SetString(PyExc_RuntimeError, + "__dict__ is a read-only attribute"); + return -1; + } + if (strcmp(name, "__class__") == 0) + { + PyErr_SetString(PyExc_RuntimeError, + "__class__ is a read-only attribute"); + return -1; + } + } + + if (value) + { + PyObject *func = self->vtk_class->vtk_setattr; + if (func) + { + PyObject *args = Py_BuildValue((char*)"(OOO)", self, attr, value); + PyObject *res = PyEval_CallObject(func, args); + Py_DECREF(args); + if (res) + { + Py_DECREF(res); + return 0; + } + return -1; + } + return PyDict_SetItem(self->vtk_dict, attr, value); + } + else + { + PyObject *func = self->vtk_class->vtk_delattr; + if (func) + { + PyObject *args = Py_BuildValue((char*)"(OO)", self, attr); + PyObject *res = PyEval_CallObject(func, args); + Py_DECREF(args); + if (res) + { + Py_DECREF(res); + return 0; + } + return -1; + } + int rv = PyDict_DelItem(self->vtk_dict, attr); + if (rv < 0) + { + PyErr_SetString(PyExc_AttributeError, + "delete non-existing class attribute"); + } + return rv; + } +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKObject_PyGetAttr(PyVTKObject *self, PyObject *attr) +{ + char *name = PyString_AsString(attr); + PyVTKClass *pyclass = self->vtk_class; + PyObject *bases; + PyObject *value; + + if ((value = PyDict_GetItem(self->vtk_dict, attr))) + { + Py_INCREF(value); + return value; + } + + if (name[0] == '_') + { + if (strcmp(name,"__class__") == 0) + { + Py_INCREF(self->vtk_class); + return (PyObject *)self->vtk_class; + } + + if (strcmp(name,"__this__") == 0) + { + char buf[256]; + sprintf(buf,"p_%s", self->vtk_ptr->GetClassName()); + return PyString_FromString(vtkPythonManglePointer(self->vtk_ptr,buf)); + } + + if (strcmp(name,"__doc__") == 0) + { + Py_INCREF(pyclass->vtk_doc); + return pyclass->vtk_doc; + } + + if (strcmp(name,"__dict__") == 0) + { + Py_INCREF(self->vtk_dict); + return self->vtk_dict; + } + + /* __methods__ is no longer applicable, methods are in __dict__ + if (strcmp(name,"__methods__") == 0) + { + PyMethodDef *meth = pyclass->vtk_methods; + PyObject *lst; + int i, n, m; + + n = 0; + if ((lst = PyList_New(0)) == NULL) + { + return NULL; + } + + bases = NULL; + while (pyclass != NULL) + { + m = 0; + for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++) + { + for (i = 0; i < n; i++) + { + if (strcmp(PyString_AsString(PyList_GetItem(lst,i)), + meth->ml_name) == 0) + { + break; + } + } + if (i == n && + PyDict_GetItemString(self->vtk_dict, meth->ml_name) == 0) + { + if (PyList_Append(lst,PyString_FromString(meth->ml_name)) == -1) + { + Py_DECREF(lst); + return NULL; + } + m++; + } + } + n += m; + bases = pyclass->vtk_bases; + pyclass = NULL; + if (PyTuple_Size(bases)) + { + pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0); + } + } + PyList_Sort(lst); + return lst; + } + + if (strcmp(name,"__members__") == 0) + { + PyObject *lst; + if ((lst = PyList_New(6)) != NULL) + { + PyList_SetItem(lst,0,PyString_FromString("__class__")); + PyList_SetItem(lst,1,PyString_FromString("__dict__")); + PyList_SetItem(lst,2,PyString_FromString("__doc__")); + PyList_SetItem(lst,3,PyString_FromString("__members__")); + PyList_SetItem(lst,4,PyString_FromString("__methods__")); + PyList_SetItem(lst,5,PyString_FromString("__this__")); + } + return lst; + } + */ + } + + while (pyclass != NULL) + { + PyMethodDef *meth; + + if (pyclass->vtk_dict == NULL) + { + pyclass->vtk_dict = PyDict_New(); + + for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++) + { + PyDict_SetItemString(pyclass->vtk_dict,meth->ml_name, + PyCFunction_New(meth, (PyObject *)pyclass)); + } + } + + value = PyDict_GetItem(pyclass->vtk_dict, attr); + + if (value) + { + if (PyCFunction_Check(value)) + { + return PyCFunction_New(((PyCFunctionObject *)value)->m_ml, + (PyObject *)self); + } + else if (PyCallable_Check(value)) + { + return PyMethod_New(value, (PyObject *)self, + (PyObject *)self->vtk_class); + } + Py_INCREF(value); + return value; + } + + bases = ((PyVTKClass *)pyclass)->vtk_bases; + pyclass = NULL; + if (PyTuple_Size(bases)) + { + pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0); + } + } + + // try the __getattr__ attribute if set + pyclass = self->vtk_class; + if (pyclass->vtk_getattr) + { + PyObject *args = Py_BuildValue((char*)"(OO)", self, attr); + PyObject *res = PyEval_CallObject(pyclass->vtk_getattr, args); + Py_DECREF(args); + return res; + } + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +//-------------------------------------------------------------------- +class vtkPythonDeleteCommand : public vtkCommand +{ +public: + static vtkPythonDeleteCommand *New(PyVTKObject *obj) { + return new vtkPythonDeleteCommand(obj); }; + + void Execute(vtkObject *caller, unsigned long, void *); + +private: + vtkPythonDeleteCommand(PyVTKObject *obj) : Self(obj) {}; + + PyVTKObject *Self; +}; + +void vtkPythonDeleteCommand::Execute(vtkObject *caller, + unsigned long vtkNotUsed(id), + void *vtkNotUsed(data)) +{ + if (this->Self->vtk_ptr != caller) + { + vtkGenericWarningMacro("Python vs. VTK mismatch for " << caller); + return; + } + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_STATE state = PyGILState_Ensure(); +#endif + + vtkPythonDeleteObjectFromHash((PyObject *)this->Self); + Py_DECREF((PyObject *)this->Self->vtk_class); + Py_DECREF(this->Self->vtk_dict); +#if (PY_MAJOR_VERSION >= 2) + PyObject_Del(this->Self); +#else + PyMem_DEL(this->Self); +#endif + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_Release(state); +#endif +} + +//-------------------------------------------------------------------- +static void PyVTKObject_PyDelete(PyVTKObject *self) +{ +#if PY_VERSION_HEX >= 0x02010000 + if (self->vtk_weakreflist != NULL) + { + PyObject_ClearWeakRefs((PyObject *) self); + } +#endif + self->vtk_ptr->Delete(); + // the rest of the delection is handled when the VTK-level object + // is destroyed + vtkPythonDeleteObjectFromHash((PyObject *)self); + Py_DECREF((PyObject *)self->vtk_class); + Py_DECREF(self->vtk_dict); +#if (PY_MAJOR_VERSION >= 2) + PyObject_Del(self); +#else + PyMem_DEL(self); +#endif +} + +//-------------------------------------------------------------------- +static PyTypeObject PyVTKObjectType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + (char*)"vtkobject", // tp_name + sizeof(PyVTKObject), // tp_basicsize + 0, // tp_itemsize + (destructor)PyVTKObject_PyDelete, // tp_dealloc + (printfunc)0, // tp_print + (getattrfunc)0, // tp_getattr + (setattrfunc)0, // tp_setattr + (cmpfunc)0, // tp_compare + (reprfunc)PyVTKObject_PyRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + (hashfunc)0, // tp_hash + (ternaryfunc)0, // tp_call + (reprfunc)PyVTKObject_PyString, // tp_string + (getattrofunc)PyVTKObject_PyGetAttr, // tp_getattro + (setattrofunc)PyVTKObject_PySetAttr, // tp_setattro + 0, // tp_as_buffer +#if PY_VERSION_HEX >= 0x02010000 + Py_TPFLAGS_HAVE_WEAKREFS, // tp_flags +#else + 0, // tp_flags +#endif + (char*)"A VTK object. Special attributes are: __class__ (the class that this object belongs to), __dict__ (user-controlled attributes), __doc__ (the docstring for the class), __methods__ (a list of all methods for this object), and __this__ (a string that contains the hexidecimal address of the underlying VTK object)", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare +#if PY_VERSION_HEX >= 0x02010000 + offsetof(PyVTKObject, vtk_weakreflist),// tp_weaklistoffset +#else + 0, // tp_weaklistoffset +#endif + VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED +}; + +int PyVTKObject_Check(PyObject *obj) +{ + return (obj->ob_type == &PyVTKObjectType); +} + +PyObject *PyVTKObject_New(PyObject *pyvtkclass, vtkObjectBase *ptr) +{ + PyVTKClass *vtkclass = (PyVTKClass *)pyvtkclass; + + if (ptr) + { + ptr->Register(NULL); + } + else if (vtkclass->vtk_new != NULL) + { + ptr = vtkclass->vtk_new(); + } + else + { + PyErr_SetString(PyExc_TypeError, + (char*)"this is an abstract class and cannot be instantiated"); + return 0; + } +#if (PY_MAJOR_VERSION >= 2) + PyVTKObject *self = PyObject_New(PyVTKObject, &PyVTKObjectType); +#else + PyVTKObject *self = PyObject_NEW(PyVTKObject, &PyVTKObjectType); +#endif + self->vtk_ptr = ptr; + PyObject *cls = NULL; + vtkstd::map::iterator i = + vtkPythonHash->ClassHash->find(ptr->GetClassName()); + if(i != vtkPythonHash->ClassHash->end()) + { + cls = i->second; + } + self->vtk_class = (PyVTKClass *)cls; + + // If the class was not in the dictionary (i.e. if there is no 'python' + // level class to support the VTK level class) we fall back to this. + if (self->vtk_class == NULL || vtkclass->vtk_methods == NULL) + { + self->vtk_class = vtkclass; + } + + Py_INCREF(self->vtk_class); + + self->vtk_dict = PyDict_New(); + +#if PY_VERSION_HEX >= 0x02010000 + self->vtk_weakreflist = NULL; +#endif + + vtkPythonAddObjectToHash((PyObject *)self, ptr); + /* I'll reinstate this later + ptr->AddObserver(vtkCommand::DeleteEvent, + vtkPythonDeleteCommand::New(self)); + */ + return (PyObject *)self; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClass_PyString(PyVTKClass *self) +{ + char buf[255]; + sprintf(buf,"%s.%s", + PyString_AsString(self->vtk_module), + PyString_AsString(self->vtk_name)); + + return PyString_FromString(buf); +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClass_PyRepr(PyVTKClass *self) +{ + char buf[255]; + sprintf(buf,"<%s %s.%s at %p>",self->ob_type->tp_name, + PyString_AsString(self->vtk_module), + PyString_AsString(self->vtk_name), + self); + + return PyString_FromString(buf); +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClass_PyCall(PyVTKClass *self, PyObject *arg, + PyObject *kw) +{ + static PyObject *initstr = 0; + + if (((PyVTKClass *)self)->vtk_dict) + { + if (initstr == 0) + { + initstr = PyString_FromString("__init__"); + } + + PyObject *initfunc; + initfunc = PyDict_GetItem(self->vtk_dict, initstr); + + if (initfunc) + { + PyObject *obj = PyVTKObject_New((PyObject *)self,NULL); + PyObject *cinitfunc = PyVTKObject_PyGetAttr((PyVTKObject *)obj, initstr); + PyObject *res = PyEval_CallObjectWithKeywords(cinitfunc, arg, kw); + if (res == NULL) + { + Py_DECREF(obj); + obj = NULL; + } + else if (res != Py_None) + { + PyErr_SetString(PyExc_TypeError, "__init__() should return None"); + Py_DECREF(obj); + obj = NULL; + } + Py_DECREF(cinitfunc); + return obj; + } + } + + if (kw != NULL) + { + PyErr_SetString(PyExc_TypeError, + "this function takes no keyword arguments"); + return NULL; + } + if (PyArg_ParseTuple(arg,(char*)"")) + { + return PyVTKObject_New((PyObject *)self, NULL); + } + PyErr_Clear(); + if (PyArg_ParseTuple(arg,(char*)"O", &arg)) + { + return vtkPythonGetObjectFromObject(arg, + PyString_AsString(self->vtk_name)); + } + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, + "function requires 0 or 1 arguments"); + + return NULL; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClass_PyGetAttr(PyVTKClass *self, PyObject *attr) +{ + char *name = PyString_AsString(attr); + PyVTKClass *pyclass = self; + PyObject *bases; + + while (pyclass != NULL) + { + PyMethodDef *meth; + PyObject *value; + + if (pyclass->vtk_dict == NULL) + { + pyclass->vtk_dict = PyDict_New(); + + for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++) + { + PyDict_SetItemString(pyclass->vtk_dict,meth->ml_name, + PyCFunction_New(meth, (PyObject *)pyclass)); + } + } + + value = PyDict_GetItem(pyclass->vtk_dict, attr); + + if (value) + { + Py_INCREF(value); + return value; + } + + bases = pyclass->vtk_bases; + pyclass = NULL; + if (PyTuple_Size(bases)) + { + pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0); + } + } + + if (name[0] == '_') + { + pyclass = (PyVTKClass *)self; + + if (strcmp(name,"__bases__") == 0) + { + Py_INCREF(pyclass->vtk_bases); + return pyclass->vtk_bases; + } + + if (strcmp(name,"__name__") == 0) + { + Py_INCREF(pyclass->vtk_name); + return pyclass->vtk_name; + } + + if (strcmp(name,"__module__") == 0) + { + Py_INCREF(pyclass->vtk_module); + return pyclass->vtk_module; + } + + if (strcmp(name,"__dict__") == 0 && pyclass->vtk_dict) + { + Py_INCREF(pyclass->vtk_dict); + return pyclass->vtk_dict; + } + + if (strcmp(name,"__doc__") == 0) + { + Py_INCREF(pyclass->vtk_doc); + return pyclass->vtk_doc; + } + + /* methods are stored in __dict__, so this is irrelevant + if (strcmp(name,"__methods__") == 0) + { + PyMethodDef *meth = pyclass->vtk_methods; + PyObject *lst; + int i, n; + + for (n = 0; meth && meth[n].ml_name; n++); + + if ((lst = PyList_New(0)) != NULL) + { + meth = pyclass->vtk_methods; + for (i = 0; i < n; i++) + { + if (pyclass->vtk_dict == NULL || + PyDict_GetItemString(pyclass->vtk_dict, meth[i].ml_name) == 0) + { + PyList_Append(lst, PyString_FromString(meth[i].ml_name)); + } + } + PyList_Sort(lst); + } + return lst; + } + + if (strcmp(name,"__members__") == 0) + { + int n = 6; + int i = 0; + PyObject *lst; + + if (pyclass->vtk_dict) + { + n++; + } + + if ((lst = PyList_New(n)) != NULL) + { + PyList_SetItem(lst,i++,PyString_FromString("__bases__")); + if (pyclass->vtk_dict) + { + PyList_SetItem(lst,i++,PyString_FromString("__dict__")); + } + PyList_SetItem(lst,i++,PyString_FromString("__doc__")); + PyList_SetItem(lst,i++,PyString_FromString("__members__")); + PyList_SetItem(lst,i++,PyString_FromString("__methods__")); + PyList_SetItem(lst,i++,PyString_FromString("__module__")); + PyList_SetItem(lst,i++,PyString_FromString("__name__")); + } + return lst; + } + */ + } + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +//-------------------------------------------------------------------- +static void PyVTKClass_PyDelete(PyVTKClass *self) +{ + Py_XDECREF(self->vtk_bases); + Py_XDECREF(self->vtk_dict); + Py_XDECREF(self->vtk_name); + + Py_XDECREF(self->vtk_getattr); + Py_XDECREF(self->vtk_setattr); + Py_XDECREF(self->vtk_delattr); + + Py_XDECREF(self->vtk_module); + Py_XDECREF(self->vtk_doc); + +#if (PY_MAJOR_VERSION >= 2) + PyObject_Del(self); +#else + PyMem_DEL(self); +#endif +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClassMetaType_GetAttr(PyTypeObject *t, char *name) +{ + if (strcmp(name, "__name__") == 0) + { + return PyString_FromString(t->tp_name); + } + if (strcmp(name, "__doc__") == 0) + { + const char *doc = t->tp_doc; + if (doc != NULL) + { + return PyString_FromString(doc); + } + Py_INCREF(Py_None); + return Py_None; + } + if (strcmp(name, "__members__") == 0) + { + return Py_BuildValue((char*)"[ss]", "__doc__", "__name__"); + } + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClassMetaType_Repr(PyTypeObject *v) +{ + char buf[100]; + sprintf(buf, "", v->tp_name); + return PyString_FromString(buf); +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClass_NewSubclass(PyObject *self, PyObject *args, + PyObject *kw); + +//-------------------------------------------------------------------- +PyTypeObject PyVTKClassMetaType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* Number of items for varobject */ + (char*)"vtkclass type", /* Name of this type */ + sizeof(PyTypeObject), /* Basic object size */ + 0, /* Item size for varobject */ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + (getattrfunc)PyVTKClassMetaType_GetAttr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + (reprfunc)PyVTKClassMetaType_Repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)PyVTKClass_NewSubclass, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_xxx1*/ + 0, /*tp_xxx2*/ + 0, /*tp_xxx3*/ + 0, /*tp_xxx4*/ + (char*)"Define the behavior of a particular type of object.", + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED +}; + +//-------------------------------------------------------------------- +static PyTypeObject PyVTKClassType = { + PyObject_HEAD_INIT(&PyVTKClassMetaType) + 0, + (char*)"vtkclass", // tp_name + sizeof(PyVTKClass), // tp_basicsize + 0, // tp_itemsize + (destructor)PyVTKClass_PyDelete, // tp_dealloc + (printfunc)0, // tp_print + (getattrfunc)0, // tp_getattr + (setattrfunc)0, // tp_setattr + (cmpfunc)0, // tp_compare + (reprfunc)PyVTKClass_PyRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + (hashfunc)0, // tp_hash + (ternaryfunc)PyVTKClass_PyCall, // tp_call + (reprfunc)PyVTKClass_PyString, // tp_string + (getattrofunc)PyVTKClass_PyGetAttr, // tp_getattro + (setattrofunc)0, // tp_setattro + 0, // tp_as_buffer + 0, // tp_flags + (char*)"A generator for VTK objects. Special attributes are: __bases__ (a tuple of base classes), __dict__ (user-defined methods and attributes), __doc__ (the docstring for the class), __name__ (the name of class), __methods__ (methods for this class, not including inherited methods or user-defined methods), and __module__ (module that the class is defined in).", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED +}; + +int PyVTKClass_Check(PyObject *obj) +{ + return (obj->ob_type == &PyVTKClassType); +} + +//-------------------------------------------------------------------- +// Concatenate an array of strings into a single string. The resulting +// string is allocated via new. The array of strings must be null-terminated, +// e.g. static char *strings[] = {"string1", "string2", NULL}; +static PyObject *vtkBuildDocString(char *docstring[]) +{ + PyObject *result; + char *data; + int i, j, n; + int *m; + int total = 0; + + for (n = 0; docstring[n] != NULL; n++); + + m = new int[n]; + + for (i = 0; i < n; i++) + { + m[i] = static_cast(strlen(docstring[i])); + total += m[i]; + } + + result = PyString_FromStringAndSize(docstring[0], m[0]); + + if (n > 1) + { + _PyString_Resize(&result, total); + } + + data = PyString_AsString(result); + + j = m[0]; + for (i = 1; i < n; i++) + { + strcpy(&data[j], docstring[i]); + j += m[i]; + } + + delete [] m; + + return result; +} + +PyObject *PyVTKClass_New(vtknewfunc constructor, + PyMethodDef *methods, + char *classname, char *modulename, char *docstring[], + PyObject *base) +{ + static PyObject *modulestr[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static int nmodulestr = 10; + PyObject *moduleobj = 0; + PyObject *self = NULL; + int i; + + if (vtkPythonHash) + { + vtkstd::map::iterator it = + vtkPythonHash->ClassHash->find(classname); + if(it != vtkPythonHash->ClassHash->end()) + { + self = it->second; + } + } + if (self) + { + Py_INCREF(self); + } + else + { +#if (PY_MAJOR_VERSION >= 2) + PyVTKClass *class_self = PyObject_New(PyVTKClass, &PyVTKClassType); +#else + PyVTKClass *class_self = PyObject_NEW(PyVTKClass, &PyVTKClassType); +#endif + self = (PyObject *)class_self; + + if (base) + { + class_self->vtk_bases = PyTuple_New(1); + PyTuple_SET_ITEM(class_self->vtk_bases, 0, base); + } + else + { + class_self->vtk_bases = PyTuple_New(0); + } + class_self->vtk_dict = NULL; + class_self->vtk_name = PyString_FromString(classname); + + class_self->vtk_getattr = NULL; + class_self->vtk_setattr = NULL; + class_self->vtk_delattr = NULL; + + class_self->vtk_methods = methods; + class_self->vtk_new = constructor; + class_self->vtk_doc = vtkBuildDocString(docstring); + + // intern the module string + for (i = 0; i < nmodulestr; i++) + { + if (modulestr[i] == 0) + { + modulestr[i] = PyString_InternFromString(modulename); + moduleobj = modulestr[i]; + Py_INCREF(moduleobj); + break; + } + else if (strcmp(modulename,PyString_AsString(modulestr[i])) == 0) + { + moduleobj = modulestr[i]; + Py_INCREF(moduleobj); + break; + } + } + if (i == nmodulestr) + { + moduleobj = PyString_FromString(modulename); + } + + class_self->vtk_module = moduleobj; + + vtkPythonAddClassToHash(self,classname); + } + + return (PyObject *)self; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKClass_NewSubclass(PyObject *, PyObject *args, + PyObject *kw) +{ + static const char *kwlist[] = {"name", "bases", "dict", NULL}; + + PyVTKClass *newclass; + char *classname; + PyObject *globals; + PyObject *bases; + PyVTKClass *base; + PyObject *attributes; + + if ((PyArg_ParseTupleAndKeywords(args, kw, (char*)"sOO", (char**)kwlist, + &classname, &bases, &attributes))) + { + if (!PyTuple_Check(bases) || PyTuple_Size(bases) != 1) + { + PyErr_SetString(PyExc_ValueError, + "multiple inheritence is not allowed with VTK classes"); + return NULL; + } + + base = (PyVTKClass *)PyTuple_GetItem(bases,0); + if (base == 0) + { + PyErr_SetString(PyExc_ValueError,"bases must be a tuple"); + return NULL; + } + + if (!PyVTKClass_Check((PyObject *)base)) + { + PyErr_SetString(PyExc_ValueError,"base class is not a VTK class"); + return NULL; + } + + if (!PyDict_Check(attributes)) + { + PyErr_SetString(PyExc_ValueError,"namespace not provided"); + return NULL; + } + + if (PyDict_GetItemString(attributes, (char*)"__del__")) + { + PyErr_SetString(PyExc_ValueError, "__del__ attribute is not supported"); + return NULL; + } + +#if (PY_MAJOR_VERSION >= 2) + newclass = PyObject_New(PyVTKClass, &PyVTKClassType); +#else + newclass = PyObject_NEW(PyVTKClass, &PyVTKClassType); +#endif + + Py_INCREF(bases); + Py_INCREF(attributes); + + newclass->vtk_bases = bases; + newclass->vtk_dict = attributes; + newclass->vtk_name = PyString_FromString(classname); + + newclass->vtk_getattr = PyDict_GetItemString(attributes, (char*)"__getattr__"); + if (newclass->vtk_getattr == 0) + { + newclass->vtk_getattr = base->vtk_getattr; + } + Py_XINCREF(newclass->vtk_getattr); + newclass->vtk_setattr = PyDict_GetItemString(attributes, (char*)"__setattr__"); + if (newclass->vtk_setattr == 0) + { + newclass->vtk_setattr = base->vtk_setattr; + } + Py_XINCREF(newclass->vtk_setattr); + newclass->vtk_delattr = PyDict_GetItemString(attributes, (char*)"__delattr__"); + if (newclass->vtk_delattr == 0) + { + newclass->vtk_delattr = base->vtk_delattr; + } + Py_XINCREF(newclass->vtk_delattr); + + newclass->vtk_methods = NULL; + newclass->vtk_new = base->vtk_new; + newclass->vtk_module = NULL; + newclass->vtk_doc = NULL; + + globals = PyEval_GetGlobals(); + if (globals != NULL) + { + PyObject *modname = PyDict_GetItemString(globals, (char*)"__name__"); + if (modname != NULL) + { + Py_INCREF(modname); + newclass->vtk_module = modname; + } + } + if (newclass->vtk_module == NULL) + { + newclass->vtk_module = PyString_FromString("__main__"); + } + + newclass->vtk_doc = PyDict_GetItemString(attributes, (char*)"__doc__"); + if (newclass->vtk_doc) + { + Py_INCREF(newclass->vtk_doc); + PyDict_DelItemString(attributes, (char*)"__doc__"); + } + else + { + newclass->vtk_doc = PyString_FromString(""); + } + + return (PyObject *)newclass; + } + return NULL; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKSpecialObject_PyString(PyVTKSpecialObject *self) +{ + Py_INCREF(self->vtk_name); + return self->vtk_name; +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKSpecialObject_PyRepr(PyVTKSpecialObject *self) +{ + char buf[255]; + sprintf(buf,"<%s %s at %p>", self->ob_type->tp_name, + PyString_AsString(self->vtk_name), self); + return PyString_FromString(buf); +} + +//-------------------------------------------------------------------- +static PyObject *PyVTKSpecialObject_PyGetAttr(PyVTKSpecialObject *self, + PyObject *attr) +{ + char *name = PyString_AsString(attr); + PyMethodDef *meth; + + if (name[0] == '_') + { + if (strcmp(name,"__name__") == 0) + { + Py_INCREF(self->vtk_name); + return self->vtk_name; + } + if (strcmp(name,"__doc__") == 0) + { + Py_INCREF(self->vtk_doc); + return self->vtk_doc; + } + if (strcmp(name,"__methods__") == 0) + { + meth = self->vtk_methods; + PyObject *lst; + int i, n; + + for (n = 0; meth && meth[n].ml_name; n++); + + if ((lst = PyList_New(n)) != NULL) + { + meth = self->vtk_methods; + for (i = 0; i < n; i++) + { + PyList_SetItem(lst, i, PyString_FromString(meth[i].ml_name)); + } + PyList_Sort(lst); + } + return lst; + } + + if (strcmp(name,"__members__") == 0) + { + PyObject *lst; + if ((lst = PyList_New(4)) != NULL) + { + PyList_SetItem(lst,0,PyString_FromString("__doc__")); + PyList_SetItem(lst,1,PyString_FromString("__members__")); + PyList_SetItem(lst,2,PyString_FromString("__methods__")); + PyList_SetItem(lst,3,PyString_FromString("__name__")); + } + return lst; + } + } + + for (meth = self->vtk_methods; meth && meth->ml_name; meth++) + { + if (name[0] == meth->ml_name[0] && strcmp(name+1, meth->ml_name+1) == 0) + { + return PyCFunction_New(meth, (PyObject *)self); + } + } + + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +} + +//-------------------------------------------------------------------- +static void PyVTKSpecialObject_PyDelete(PyVTKSpecialObject *self) +{ + self->vtk_ptr = NULL; + Py_XDECREF(self->vtk_name); + Py_XDECREF(self->vtk_doc); +#if (PY_MAJOR_VERSION >= 2) + PyObject_Del(self); +#else + PyMem_DEL(self); +#endif +} + +//-------------------------------------------------------------------- +static PyTypeObject PyVTKSpecialObjectType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + (char*)"vtkspecialobject", // tp_name + sizeof(PyVTKSpecialObject), // tp_basicsize + 0, // tp_itemsize + (destructor)PyVTKSpecialObject_PyDelete, // tp_dealloc + (printfunc)0, // tp_print + (getattrfunc)0, // tp_getattr + (setattrfunc)0, // tp_setattr + (cmpfunc)0, // tp_compare + (reprfunc)PyVTKSpecialObject_PyRepr, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + (hashfunc)0, // tp_hash + (ternaryfunc)0, // tp_call + (reprfunc)PyVTKSpecialObject_PyString, // tp_string + (getattrofunc)PyVTKSpecialObject_PyGetAttr, // tp_getattro + (setattrofunc)0, // tp_setattro + 0, // tp_as_buffer + 0, // tp_flags + (char*)"vtkspecialobject - a vtk object not derived from vtkObjectBase.", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED +}; + +int PyVTKSpecialObject_Check(PyObject *obj) +{ + return (obj->ob_type == &PyVTKSpecialObjectType); +} + +PyObject *PyVTKSpecialObject_New(void *ptr, PyMethodDef *methods, + char *classname, char *docstring[]) +{ +#if (PY_MAJOR_VERSION >= 2) + PyVTKSpecialObject *self = PyObject_New(PyVTKSpecialObject, + &PyVTKSpecialObjectType); +#else + PyVTKSpecialObject *self = PyObject_NEW(PyVTKSpecialObject, + &PyVTKSpecialObjectType); +#endif + self->vtk_ptr = ptr; + self->vtk_methods = methods; + self->vtk_name = PyString_FromString(classname); + self->vtk_doc = vtkBuildDocString(docstring); + + return (PyObject *)self; +} + +//-------------------------------------------------------------------- +vtkObjectBase *PyArg_VTKParseTuple(PyObject *pself, PyObject *args, + char *format, ...) +{ + PyVTKObject *self = (PyVTKObject *)pself; + vtkObjectBase *obj = NULL; + va_list va; + va_start(va, format); + + /* check if this was called as an unbound method */ + if (self->ob_type == &PyVTKClassType) + { + int n = PyTuple_Size(args); + PyVTKClass *vtkclass = (PyVTKClass *)self; + + if (n == 0 || (self = (PyVTKObject *)PyTuple_GetItem(args, 0)) == NULL || + self->ob_type != &PyVTKObjectType || + !self->vtk_ptr->IsA(PyString_AsString(vtkclass->vtk_name))) + { + char buf[256]; + sprintf(buf,"unbound method requires a %s as the first argument", + PyString_AsString(vtkclass->vtk_name)); + PyErr_SetString(PyExc_ValueError,buf); + return NULL; + } + // re-slice the args to remove 'self' + args = PyTuple_GetSlice(args,1,n); + if (PyArg_VaParse(args,format,va)) + { + obj = self->vtk_ptr; + } + Py_DECREF(args); + } + /* it was called as a bound method */ + else + { + if (PyArg_VaParse(args,format,va)) + { + obj = self->vtk_ptr; + } + } + return obj; +} + +//-------------------------------------------------------------------- +void vtkPythonAddClassToHash(PyObject *vtkclass, const char *classname) +{ + if (vtkPythonHash == NULL) + { + vtkPythonHash = new vtkPythonUtil(); + Py_AtExit(vtkPythonHashDelete); + } + +#ifdef VTKPYTHONDEBUG + // vtkGenericWarningMacro("Adding an type " << type << " to hash ptr"); +#endif + + // lets make sure it isn't already there + vtkstd::map::iterator i = + vtkPythonHash->ClassHash->find(classname); + if(i != vtkPythonHash->ClassHash->end()) + { +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Attempt to add type to the hash when already there!!!"); +#endif + return; + } + + (*vtkPythonHash->ClassHash)[classname] = vtkclass; + +#ifdef VTKPYTHONDEBUG + // vtkGenericWarningMacro("Added type to hash type = " << typeObject); +#endif +} + +//-------------------------------------------------------------------- +void vtkPythonAddObjectToHash(PyObject *obj, vtkObjectBase *ptr) +{ + if (vtkPythonHash == NULL) + { + vtkPythonHash = new vtkPythonUtil(); + Py_AtExit(vtkPythonHashDelete); + } + +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Adding an object to hash ptr = " << ptr); +#endif + + ((PyVTKObject *)obj)->vtk_ptr = ptr; + (*vtkPythonHash->ObjectHash)[ptr] = obj; + +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Added object to hash obj= " << obj << " " + << ptr); +#endif +} + +//-------------------------------------------------------------------- +void vtkPythonDeleteObjectFromHash(PyObject *obj) +{ + vtkObjectBase *ptr = ((PyVTKObject *)obj)->vtk_ptr; + +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Deleting an object from hash obj = " << obj << " " + << obj->vtk_ptr); +#endif + + vtkPythonHash->ObjectHash->erase(ptr); +} + +//-------------------------------------------------------------------- +static PyObject *vtkFindNearestBase(vtkObjectBase *ptr); + +PyObject *vtkPythonGetObjectFromPointer(vtkObjectBase *ptr) +{ + PyObject *obj = NULL; + +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Checking into pointer " << ptr); +#endif + + if (ptr) + { + vtkstd::map::iterator i = + vtkPythonHash->ObjectHash->find(ptr); + if(i != vtkPythonHash->ObjectHash->end()) + { + obj = i->second; + } + if (obj) + { + Py_INCREF(obj); + } + } + else + { + Py_INCREF(Py_None); + obj = Py_None; + } +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Checking into pointer " << ptr << " obj = " << obj); +#endif + + if (obj == NULL) + { + PyObject *vtkclass = NULL; + vtkstd::map::iterator i = + vtkPythonHash->ClassHash->find(ptr->GetClassName()); + if(i != vtkPythonHash->ClassHash->end()) + { + vtkclass = i->second; + } + + // if the class was not in the hash, then find the nearest base class + // that is and associate ptr->GetClassName() with that base class + if (vtkclass == NULL) + { + vtkclass = vtkFindNearestBase(ptr); + vtkPythonAddClassToHash(vtkclass, ptr->GetClassName()); + } + + obj = PyVTKObject_New(vtkclass, ptr); + } + + return obj; +} + +// this is a helper function to find the nearest base class for an +// object whose class is not in the ClassDict +static PyObject *vtkFindNearestBase(vtkObjectBase *ptr) +{ + PyObject *nearestbase = NULL; + int maxdepth = 0; + int depth; + + for(vtkstd::map::iterator classes = + vtkPythonHash->ClassHash->begin(); + classes != vtkPythonHash->ClassHash->end(); ++classes) + { + PyObject *pyclass = classes->second; + + if (ptr->IsA(PyString_AsString(((PyVTKClass *)pyclass)->vtk_name))) + { + PyObject *cls = pyclass; + PyObject *bases = ((PyVTKClass *)pyclass)->vtk_bases; + // count the heirarchy depth for this class + for (depth = 0; PyTuple_Size(bases) != 0; depth++) + { + cls = PyTuple_GetItem(bases,0); + bases = ((PyVTKClass *)cls)->vtk_bases; + } + // we want the class that is furthest from vtkObjectBase + if (depth > maxdepth) + { + maxdepth = depth; + nearestbase = pyclass; + } + } + } + + return nearestbase; +} + +//-------------------------------------------------------------------- +vtkObjectBase *vtkPythonGetPointerFromObject(PyObject *obj, + const char *result_type) +{ + vtkObjectBase *ptr; + + // convert Py_None to NULL every time + if (obj == Py_None) + { + return NULL; + } + + // check to ensure it is a vtk object + if (obj->ob_type != &PyVTKObjectType) + { + obj = PyObject_GetAttrString(obj,(char*)"__vtk__"); + if (obj) + { + PyObject *arglist = Py_BuildValue((char*)"()"); + PyObject *result = PyEval_CallObject(obj, arglist); + Py_DECREF(arglist); + Py_DECREF(obj); + if (result == NULL) + { + return NULL; + } + if (result->ob_type != &PyVTKObjectType) + { + PyErr_SetString(PyExc_ValueError,"__vtk__() doesn't return a VTK object"); + Py_DECREF(result); + return NULL; + } + else + { + ptr = ((PyVTKObject *)result)->vtk_ptr; + Py_DECREF(result); + } + } + else + { +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Object " << obj << " is not a VTK object!!"); +#endif + PyErr_SetString(PyExc_ValueError,"method requires a VTK object"); + return NULL; + } + } + else + { + ptr = ((PyVTKObject *)obj)->vtk_ptr; + } + +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Checking into obj " << obj << " ptr = " << ptr); +#endif + + if (ptr->IsA(result_type)) + { +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("Got obj= " << obj << " ptr= " << ptr << " " << result_type); +#endif + return ptr; + } + else + { + char error_string[256]; +#ifdef VTKPYTHONDEBUG + vtkGenericWarningMacro("vtk bad argument, type conversion failed."); +#endif + sprintf(error_string,"method requires a %s, a %s was provided.", + result_type,((vtkObjectBase *)ptr)->GetClassName()); + PyErr_SetString(PyExc_ValueError,error_string); + return NULL; + } +} + +PyObject *vtkPythonGetObjectFromObject(PyObject *arg, const char *type) +{ + if (PyString_Check(arg)) + { + char *ptrText = PyString_AsString(arg); + + vtkObjectBase *ptr; + char typeCheck[256]; // typeCheck is currently not used + int i = sscanf(ptrText,"_%lx_%s",(long *)&ptr,typeCheck); + + if (i <= 0) + { + i = sscanf(ptrText,"Addr=0x%lx",(long *)&ptr); + } + if (i <= 0) + { + i = sscanf(ptrText,"%lx",(long *)&ptr); + } + if (i <= 0) + { + PyErr_SetString(PyExc_ValueError,"could not extract hexidecimal address from argument string"); + return NULL; + } + + if (!ptr->IsA(type)) + { + char error_string[256]; + sprintf(error_string,"method requires a %s address, a %s address was provided.", + type,((vtkObjectBase *)ptr)->GetClassName()); + PyErr_SetString(PyExc_TypeError,error_string); + return NULL; + } + + return vtkPythonGetObjectFromPointer(ptr); + } + + PyErr_SetString(PyExc_TypeError,"method requires a string argument"); + return NULL; +} + +//-------------------------------------------------------------------- +// mangle a void pointer into a SWIG-style string +char *vtkPythonManglePointer(void *ptr, const char *type) +{ + static char ptrText[128]; + sprintf(ptrText,"_%*.*lx_%s",2*(int)sizeof(void *),2*(int)sizeof(void *), + vtkConvertPtrToLong(ptr),type); + return ptrText; +} + +//-------------------------------------------------------------------- +// unmangle a void pointer from a SWIG-style string +void *vtkPythonUnmanglePointer(char *ptrText, int *len, const char *type) +{ + int i; + void *ptr; + char typeCheck[128]; + if (*len < 128) + { + i = sscanf(ptrText,"_%lx_%s",(long *)&ptr,typeCheck); + if (strcmp(type,typeCheck) == 0) + { // sucessfully unmangle + *len = 0; + return ptr; + } + else if (i == 2) + { // mangled pointer of wrong type + *len = -1; + return NULL; + } + } + // couldn't unmangle: return string as void pointer if it didn't look + // like a SWIG mangled pointer + return (void *)ptrText; +} + +//-------------------------------------------------------------------- +// These functions check an array that was sent to a method to see if +// any of the values were changed by the method. +// If a value was changed, then the corresponding value in the python +// list is modified. + +template +static inline +int vtkPythonCheckFloatArray(PyObject *args, int i, T *a, int n) +{ + int changed = 0; + + PyObject *seq = PyTuple_GET_ITEM(args, i); + for (i = 0; i < n; i++) + { + PyObject *oldobj = PySequence_GetItem(seq, i); + T oldval = (T)PyFloat_AsDouble(oldobj); + Py_DECREF(oldobj); + changed |= (a[i] != oldval); + } + + if (changed) + { + for (i = 0; i < n; i++) + { + PyObject *newobj = PyFloat_FromDouble(a[i]); + int rval = PySequence_SetItem(seq, i, newobj); + Py_DECREF(newobj); + if (rval == -1) + { + return -1; + } + } + } + + return 0; +} + +template +static inline +int vtkPythonCheckIntArray(PyObject *args, int i, T *a, int n) +{ + int changed = 0; + + PyObject *seq = PyTuple_GET_ITEM(args, i); + for (i = 0; i < n; i++) + { + PyObject *oldobj = PySequence_GetItem(seq, i); + T oldval = (T)PyInt_AsLong(oldobj); + Py_DECREF(oldobj); + changed |= (a[i] != oldval); + } + + if (changed) + { + for (i = 0; i < n; i++) + { + PyObject *newobj = PyInt_FromLong(a[i]); + int rval = PySequence_SetItem(seq, i, newobj); + Py_DECREF(newobj); + if (rval == -1) + { + return -1; + } + } + } + + return 0; +} + +#if defined(VTK_TYPE_USE_LONG_LONG) || defined(VTK_TYPE_USE___INT64) +template +static inline +int vtkPythonCheckLongArray(PyObject *args, int i, T *a, int n) +{ + int changed = 0; + + PyObject *seq = PyTuple_GET_ITEM(args, i); + for (i = 0; i < n; i++) + { + PyObject *oldobj = PySequence_GetItem(seq, i); + T oldval; + if (PyLong_Check(oldobj)) + { +#ifdef PY_LONG_LONG + oldval = PyLong_AsLongLong(oldobj); +#else + oldval = PyLong_AsLong(oldobj); +#endif + } + else + { + oldval = PyInt_AsLong(oldobj); + } + Py_DECREF(oldobj); + changed |= (a[i] != oldval); + } + + if (changed) + { + for (i = 0; i < n; i++) + { +#if defined(VTK_TYPE_USE_LONG_LONG) +# if defined(PY_LONG_LONG) && (VTK_SIZEOF_LONG != VTK_SIZEOF_LONG_LONG) + PyObject *newobj = PyLong_FromLongLong(a[i]); +# else + PyObject *newobj = PyInt_FromLong((long)a[i]); +# endif +#else +# if defined(PY_LONG_LONG) && (VTK_SIZEOF_LONG != VTK_SIZEOF___INT64) + PyObject *newobj = PyLong_FromLongLong(a[i]); +# else + PyObject *newobj = PyInt_FromLong((long)a[i]); +# endif +#endif + int rval = PySequence_SetItem(seq, i, newobj); + Py_DECREF(newobj); + if (rval == -1) + { + return -1; + } + } + } + + return 0; +} +#endif + +int vtkPythonCheckArray(PyObject *args, int i, char *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, signed char *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, unsigned char *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, short *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, unsigned short *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, int *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, unsigned int *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, long *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, unsigned long *a, int n) +{ + return vtkPythonCheckIntArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, float *a, int n) +{ + return vtkPythonCheckFloatArray(args, i, a, n); +} + +int vtkPythonCheckArray(PyObject *args, int i, double *a, int n) +{ + return vtkPythonCheckFloatArray(args, i, a, n); +} + +#if defined(VTK_TYPE_USE_LONG_LONG) +int vtkPythonCheckArray(PyObject *args, int i, long long *a, int n) +{ + return vtkPythonCheckLongArray(args, i, a, n); +} +int vtkPythonCheckArray(PyObject *args, int i, unsigned long long *a, int n) +{ + return vtkPythonCheckLongArray(args, i, a, n); +} +#endif + +#if defined(VTK_TYPE_USE___INT64) +int vtkPythonCheckArray(PyObject *args, int i, __int64 *a, int n) +{ + return vtkPythonCheckLongArray(args, i, a, n); +} +int vtkPythonCheckArray(PyObject *args, int i, unsigned __int64 *a, int n) +{ + return vtkPythonCheckLongArray(args, i, a, n); +} +#endif + +//-------------------------------------------------------------------- +void vtkPythonVoidFunc(void *arg) +{ + PyObject *arglist, *result; + PyObject *func = (PyObject *)arg; + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_STATE state = PyGILState_Ensure(); +#endif + + arglist = Py_BuildValue((char*)"()"); + + result = PyEval_CallObject(func, arglist); + Py_DECREF(arglist); + + if (result) + { + Py_XDECREF(result); + } + else + { + if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) + { + cerr << "Caught a Ctrl-C within python, exiting program.\n"; + Py_Exit(1); + } + PyErr_Print(); + } + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_Release(state); +#endif +} + +//-------------------------------------------------------------------- +void vtkPythonVoidFuncArgDelete(void *arg) +{ + PyObject *func = (PyObject *)arg; + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_STATE state = PyGILState_Ensure(); +#endif + + if (func) + { + Py_DECREF(func); + } + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_Release(state); +#endif +} + +//-------------------------------------------------------------------- +vtkPythonCommand::vtkPythonCommand() +{ + this->obj = NULL; +} + +vtkPythonCommand::~vtkPythonCommand() +{ + if (this->obj) + { + Py_DECREF(this->obj); + } + this->obj = NULL; +} + +void vtkPythonCommand::SetObject(PyObject *o) +{ + this->obj = o; +} + +void vtkPythonCommand::Execute(vtkObject *ptr, unsigned long eventtype, + void *CallData) +{ + PyObject *arglist, *result, *obj2; + const char *eventname; + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_STATE state = PyGILState_Ensure(); +#endif + + if (ptr && ptr->GetReferenceCount() > 0) + { + obj2 = vtkPythonGetObjectFromPointer(ptr); + } + else + { + Py_INCREF(Py_None); + obj2 = Py_None; + } + + eventname = this->GetStringFromEventId(eventtype); + + // extension by Charl P. Botha so that CallData is available from Python: + // * CallData used to be ignored completely: this is not entirely desirable, + // e.g. with catching ErrorEvent + // * I have extended this code so that CallData can be caught whilst not + // affecting any existing VTK Python code + // * make sure your observer python function has a CallDataType string + // attribute that describes how CallData should be passed through, e.g.: + // def handler(theObject, eventType, message): + // print "Error: %s" % (message) + // # we know that ErrorEvent passes a null-terminated string + // handler.CallDataType = "string0" + // someObject.AddObserver('ErrorEvent', handler) + // * At the moment, only string0 is supported as that is what ErrorEvent + // generates. + // + char CallDataTypeLiteral[] = "CallDataType"; // Need char*, not const char*. + PyObject *CallDataTypeObj = PyObject_GetAttrString(this->obj, + CallDataTypeLiteral); + char *CallDataTypeString = NULL; + if (CallDataTypeObj) + { + CallDataTypeString = PyString_AsString(CallDataTypeObj); + if (CallDataTypeString) + { + if (strcmp(CallDataTypeString, "string0") == 0) + { + // this means the user wants the CallData cast as a string + PyObject* CallDataAsString = PyString_FromString((char*)CallData); + if (CallDataAsString) + { + arglist = Py_BuildValue((char*)"(NsN)", obj2, eventname, CallDataAsString); + } + else + { + PyErr_Clear(); + // we couldn't create a string, so we pass in None + Py_INCREF(Py_None); + arglist = Py_BuildValue((char*)"(NsN)", obj2, eventname, Py_None); + } + } + else + { + // we don't handle this, so we pass in a None as the third parameter + Py_INCREF(Py_None); + arglist = Py_BuildValue((char*)"(NsN)", obj2, eventname, Py_None); + } + } + else + { + // the handler object has a CallDataType attribute, but it's not a + // string -- then we do traditional arguments + arglist = Py_BuildValue((char*)"(Ns)",obj2,eventname); + } + + // we have to do this + Py_DECREF(CallDataTypeObj); + } + else + { + // this means there was no CallDataType attribute, so we do the + // traditional obj(object, eventname) call + PyErr_Clear(); + arglist = Py_BuildValue((char*)"(Ns)",obj2,eventname); + } + + result = PyEval_CallObject(this->obj, arglist); + Py_DECREF(arglist); + + if (result) + { + Py_DECREF(result); + } + else + { + if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) + { + cerr << "Caught a Ctrl-C within python, exiting program.\n"; + Py_Exit(1); + } + PyErr_Print(); + } + +#if (PY_MAJOR_VERSION > 2) || \ +((PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION >= 3)) + PyGILState_Release(state); +#endif +} +//-------------------------------------------------------------------- + + + diff --git a/Common/vtkPythonUtil.h b/Common/vtkPythonUtil.h new file mode 100644 index 0000000..5f7194f --- /dev/null +++ b/Common/vtkPythonUtil.h @@ -0,0 +1,192 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPythonUtil.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkPythonUtil_h +#define __vtkPythonUtil_h + +#include "vtkPython.h" +#include "vtkCommand.h" + +#if defined(WIN32) +# if defined(vtkCommonPythonD_EXPORTS) +# define VTK_PYTHON_EXPORT __declspec(dllexport) +# else +# define VTK_PYTHON_EXPORT __declspec(dllimport) +# endif +#else +# define VTK_PYTHON_EXPORT +#endif + +// This is the VTK/Python 'class,' it contains the method list and a pointer +// to the superclass +typedef vtkObjectBase *(*vtknewfunc)(); + +typedef struct { + PyObject_HEAD + // the first six are common to PyClassObject + PyObject *vtk_bases; + PyObject *vtk_dict; + PyObject *vtk_name; + PyObject *vtk_getattr; + PyObject *vtk_setattr; + PyObject *vtk_delattr; + // these are unique to the PyVTKClass + PyObject *vtk_module; + PyObject *vtk_doc; + PyMethodDef *vtk_methods; + vtknewfunc vtk_new; +} PyVTKClass; + +// This is the VTK/Python 'object,' it contains the python object header +// plus a pointer to the associated vtkObjectBase and PyVTKClass. +typedef struct { + PyObject_HEAD + // the first two are common with the PyInstanceObject + PyVTKClass *vtk_class; + PyObject *vtk_dict; + // the rest are unique to the PyVTKObject + vtkObjectBase *vtk_ptr; +#if PY_VERSION_HEX >= 0x02010000 + PyObject *vtk_weakreflist; +#endif +} PyVTKObject; + +// This for objects not derived from vtkObjectBase +typedef struct { + PyObject_HEAD + void *vtk_ptr; + PyMethodDef *vtk_methods; + PyObject *vtk_name; + PyObject *vtk_doc; +} PyVTKSpecialObject; + +// Standard methods for all vtk/python objects +extern "C" +{ +VTK_PYTHON_EXPORT int PyVTKObject_Check(PyObject *obj); +VTK_PYTHON_EXPORT int PyVTKClass_Check(PyObject *obj); +VTK_PYTHON_EXPORT int PyVTKSpecialObjectCheck(PyObject *obj); +VTK_PYTHON_EXPORT +PyObject *PyVTKObject_New(PyObject *vtkclass, vtkObjectBase *ptr); +VTK_PYTHON_EXPORT +PyObject *PyVTKClass_New(vtknewfunc constructor, PyMethodDef *methods, + char *classname, char *modulename, char *docstring[], + PyObject *base); +VTK_PYTHON_EXPORT +PyObject *PyVTKSpecialObject_New(void *ptr, PyMethodDef *methods, + char *classname, char *docstring[]); + +// this is a special version of ParseTuple that handles both bound +// and unbound method calls for VTK objects +VTK_PYTHON_EXPORT +vtkObjectBase *PyArg_VTKParseTuple(PyObject *self, PyObject *args, + char *format, ...); +} + +// Add a PyVTKClass to the type lookup table, this allows us to later +// create object given only the class name. +extern VTK_PYTHON_EXPORT +void vtkPythonAddClassToHash(PyObject *obj, const char *type); + +// Extract the vtkObjectBase from a PyVTKObject. If the PyObject is not a +// PyVTKObject, or is not a PyVTKObject of the specified type, the python +// error indicator will be set. +// Special behaviour: Py_None is converted to NULL without no error. +extern VTK_PYTHON_EXPORT +vtkObjectBase *vtkPythonGetPointerFromObject(PyObject *obj, const char *type); + +// Convert a vtkObjectBase to a PyVTKObject. This will first check to see if +// the PyVTKObject already exists, and create a new PyVTKObject if necessary. +// This function also passes ownership of the reference to the PyObject. +// Special behaviour: NULL is converted to Py_None. +extern VTK_PYTHON_EXPORT +PyObject *vtkPythonGetObjectFromPointer(vtkObjectBase *ptr); + +// Try to convert some PyObject into a PyVTKObject, currently conversion +// is supported for SWIG-style mangled pointer strings. +extern VTK_PYTHON_EXPORT +PyObject *vtkPythonGetObjectFromObject(PyObject *arg, const char *type); + +// Add and delete PyVTKObject/vtkObjectBase pairs from the wrapper hash table, +// these methods do not change the reference counts of either the vtkObjectBase +// or the PyVTKObject. +extern VTK_PYTHON_EXPORT +void vtkPythonAddObjectToHash(PyObject *obj, vtkObjectBase *anInstance); +extern VTK_PYTHON_EXPORT +void vtkPythonDeleteObjectFromHash(PyObject *obj); + +// Utility functions for creating/usinge SWIG-style mangled pointer strings. +extern VTK_PYTHON_EXPORT +char *vtkPythonManglePointer(void *ptr, const char *type); +extern VTK_PYTHON_EXPORT +void *vtkPythonUnmanglePointer(char *ptrText, int *len, const char *type); + +// check array arguments sent through the wrappers to see if the underlying +// C++ method changed the values, and attempt to modify the original python +// sequence (list or tuple) if so. +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, char *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, signed char *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, unsigned char *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, short *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, unsigned short *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, int *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, unsigned int *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, long *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, unsigned long *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, float *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, double *a, int n); +#if defined(VTK_TYPE_USE_LONG_LONG) +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, long long *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, unsigned long long *a, int n); +#endif +#if defined(VTK_TYPE_USE___INT64) +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, __int64 *a, int n); +extern VTK_PYTHON_EXPORT +int vtkPythonCheckArray(PyObject *args, int i, unsigned __int64 *a, int n); +#endif + +// For use by SetXXMethod() , SetXXMethodArgDelete() +extern VTK_PYTHON_EXPORT void vtkPythonVoidFunc(void *); +extern VTK_PYTHON_EXPORT void vtkPythonVoidFuncArgDelete(void *); + +// To allow Python to use the vtkCommand features +class vtkPythonCommand : public vtkCommand +{ +public: + static vtkPythonCommand *New() { return new vtkPythonCommand; }; + + void SetObject(PyObject *o); + void Execute(vtkObject *ptr, unsigned long eventtype, void *CallData); + + PyObject *obj; +protected: + vtkPythonCommand(); + ~vtkPythonCommand(); +}; + +#endif diff --git a/Common/vtkQuadric.cxx b/Common/vtkQuadric.cxx new file mode 100644 index 0000000..a38164d --- /dev/null +++ b/Common/vtkQuadric.cxx @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadric.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkQuadric, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkQuadric); + +// Construct quadric with all coefficients = 1. +vtkQuadric::vtkQuadric() +{ + this->Coefficients[0] = 1.0; + this->Coefficients[1] = 1.0; + this->Coefficients[2] = 1.0; + this->Coefficients[3] = 1.0; + this->Coefficients[4] = 1.0; + this->Coefficients[5] = 1.0; + this->Coefficients[6] = 1.0; + this->Coefficients[7] = 1.0; + this->Coefficients[8] = 1.0; + this->Coefficients[9] = 1.0; +} + +// Set the 10 coefficients of the quadric equation. +void vtkQuadric::SetCoefficients(double a[10]) +{ + int i; + double *c=this->Coefficients; + + for (i=0; i < 10; i++ ) + { + if ( a[i] != c[i] ) + { + break; + } + } + + if ( i < 10 ) + { + this->Modified(); + for (i=0; i < 10; i++ ) + { + c[i] = a[i]; + } + } +} + +// Evaluate quadric equation. +double vtkQuadric::EvaluateFunction(double x[3]) +{ + double *a = this->Coefficients; + return ( a[0]*x[0]*x[0] + a[1]*x[1]*x[1] + a[2]*x[2]*x[2] + + a[3]*x[0]*x[1] + a[4]*x[1]*x[2] + a[5]*x[0]*x[2] + + a[6]*x[0] + a[7]*x[1] + a[8]*x[2] + a[9] ); +} + +// Evaluate the gradient to the quadric equation. +void vtkQuadric::EvaluateGradient(double x[3], double n[3]) +{ + double *a=this->Coefficients; + + n[0] = 2.0*a[0]*x[0] + a[3]*x[1] + a[5]*x[2] + a[6]; + n[1] = 2.0*a[1]*x[1] + a[3]*x[0] + a[4]*x[2] + a[7]; + n[2] = 2.0*a[2]*x[2] + a[4]*x[1] + a[5]*x[0] + a[8]; +} + + +// Set the 10 coefficients of the quadric equation. +void vtkQuadric::SetCoefficients(double a0,double a1,double a2,double a3, double a4, + double a5,double a6,double a7,double a8, double a9) +{ + double a[10]; + + a[0] = a0; a[1] = a1; a[2] = a2; a[3] = a3; a[4] = a4; + a[5] = a5; a[6] = a6; a[7] = a7; a[8] = a8; a[9] = a9; + + vtkQuadric::SetCoefficients(a); +} +void vtkQuadric::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Coefficients: " + << "\n\ta0: " << this->Coefficients[0] + << "\n\ta1: " << this->Coefficients[1] + << "\n\ta2: " << this->Coefficients[2] + << "\n\ta3: " << this->Coefficients[3] + << "\n\ta4: " << this->Coefficients[4] + << "\n\ta5: " << this->Coefficients[5] + << "\n\ta6: " << this->Coefficients[6] + << "\n\ta7: " << this->Coefficients[7] + << "\n\ta8: " << this->Coefficients[8] + << "\n\ta9: " << this->Coefficients[9] << "\n"; +} diff --git a/Common/vtkQuadric.h b/Common/vtkQuadric.h new file mode 100644 index 0000000..b5d670d --- /dev/null +++ b/Common/vtkQuadric.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadric.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadric - evaluate implicit quadric function +// .SECTION Description +// vtkQuadric evaluates the quadric function F(x,y,z) = a0*x^2 + a1*y^2 + +// a2*z^2 + a3*x*y + a4*y*z + a5*x*z + a6*x + a7*y + a8*z + a9. vtkQuadric is +// a concrete implementation of vtkImplicitFunction. + +#ifndef __vtkQuadric_h +#define __vtkQuadric_h + +#include "vtkImplicitFunction.h" + +class VTK_COMMON_EXPORT vtkQuadric : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkQuadric,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct quadric with all coefficients = 1. + static vtkQuadric *New(); + + // Description + // Evaluate quadric equation. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate the gradient to the quadric equation. + void EvaluateGradient(double x[3], double g[3]); + + // Description + // Set / get the 10 coefficients of the quadric equation. + void SetCoefficients(double a[10]); + void SetCoefficients(double a0, double a1, double a2, double a3, double a4, + double a5, double a6, double a7, double a8, double a9); + vtkGetVectorMacro(Coefficients,double,10); + +protected: + vtkQuadric(); + ~vtkQuadric() {}; + + double Coefficients[10]; + +private: + vtkQuadric(const vtkQuadric&); // Not implemented. + void operator=(const vtkQuadric&); // Not implemented. +}; + +#endif + + diff --git a/Common/vtkRayCastStructures.h b/Common/vtkRayCastStructures.h new file mode 100644 index 0000000..95836f7 --- /dev/null +++ b/Common/vtkRayCastStructures.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRayCastStructures.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkRayCastStructures - the structure definitions for ray casting + +// .SECTION Description +// These are the structures required for ray casting. + +// .SECTION See Also +// vtkRayCaster + +#ifndef __vtkRayCastStructures_h +#define __vtkRayCastStructures_h + +typedef struct +{ + // These are the input values that define the ray. Depending on + // whether we are casting a WorldRay or a ViewRay, these are in + // world coordinates or view coordinates. + float Origin[3]; + float Direction[3]; + + // The pixel location for the ray that is being cast can be + // important, for example if hardware ray bounding is being used + // and the location in the depth buffer must be matched to this + // ray. + int Pixel[2]; + + // The world coordinate location of the camera is important for the + // ray caster to be able to return a Z value for the intersection + float CameraPosition[3]; + + // This input value defines the size of the image + int ImageSize[2]; + + // These are input values for clipping but may be changed + // along the way + float NearClip; + float FarClip; + + // These are the return values - RGBA and Z + float Color[4]; + float Depth; + + + // Some additional space that may be useful for the + // specific implementation of the ray caster. This structure + // is a convenient place to put it, since there is one + // per thread so that writing to these locations is safe + + // Ray information transformed into local coordinates + float TransformedStart[4]; + float TransformedEnd[4]; + float TransformedDirection[4]; + float TransformedIncrement[3]; + + // The number of steps we want to take if this is + // a ray caster that takes steps + int NumberOfStepsToTake; + + // The number of steps we actually take if this is + // a ray caster that takes steps + int NumberOfStepsTaken; + +} vtkRayCastRayInfo; + +#endif diff --git a/Common/vtkReferenceCount.cxx b/Common/vtkReferenceCount.cxx new file mode 100644 index 0000000..6083d10 --- /dev/null +++ b/Common/vtkReferenceCount.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkReferenceCount.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkReferenceCount.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkReferenceCount, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkReferenceCount); + +vtkReferenceCount::vtkReferenceCount() +{ +} + +vtkReferenceCount::~vtkReferenceCount() +{ +} + +void vtkReferenceCount::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Common/vtkReferenceCount.h b/Common/vtkReferenceCount.h new file mode 100644 index 0000000..6cae5c1 --- /dev/null +++ b/Common/vtkReferenceCount.h @@ -0,0 +1,45 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkReferenceCount.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkReferenceCount - Obsolete / empty subclass of object. +// .SECTION Description +// vtkReferenceCount functionality has now been moved into vtkObject +// .SECTION See Also +// vtkObject + +#ifndef __vtkReferenceCount_h +#define __vtkReferenceCount_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkReferenceCount : public vtkObject +{ +public: + static vtkReferenceCount *New(); + + vtkTypeRevisionMacro(vtkReferenceCount,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkReferenceCount(); + ~vtkReferenceCount(); + +private: + vtkReferenceCount(const vtkReferenceCount&); // Not implemented. + void operator=(const vtkReferenceCount&); // Not implemented. +}; + + +#endif + diff --git a/Common/vtkRungeKutta2.cxx b/Common/vtkRungeKutta2.cxx new file mode 100644 index 0000000..32f4ac1 --- /dev/null +++ b/Common/vtkRungeKutta2.cxx @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRungeKutta2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRungeKutta2.h" + +#include "vtkFunctionSet.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkRungeKutta2, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkRungeKutta2); + +vtkRungeKutta2::vtkRungeKutta2() +{ +} + +vtkRungeKutta2::~vtkRungeKutta2() +{ +} + +// Calculate next time step +int vtkRungeKutta2::ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, double& delTActual, + double, double, double, double& error) +{ + int i, numDerivs, numVals; + + delTActual = delT; + error = 0.0; + + if (!this->FunctionSet) + { + vtkErrorMacro("No derivative functions are provided!"); + return NOT_INITIALIZED; + } + + if (!this->Initialized) + { + vtkErrorMacro("Integrator not initialized!"); + return NOT_INITIALIZED; + } + + numDerivs = this->FunctionSet->GetNumberOfFunctions(); + numVals = numDerivs + 1; + for(i=0; iVals[i] = xprev[i]; + } + this->Vals[numVals-1] = t; + + // Obtain the derivatives dx_i at x_i + if (dxprev) + { + for(i=0; iDerivs[i] = dxprev[i]; + } + } + else if ( !this->FunctionSet->FunctionValues(this->Vals, this->Derivs) ) + { + memcpy(xnext, this->Vals, (numVals-1)*sizeof(double)); + return OUT_OF_DOMAIN; + } + + // Half-step + for(i=0; iVals[i] = xprev[i] + delT/2.0*this->Derivs[i]; + } + this->Vals[numVals-1] = t + delT/2.0; + + // Obtain the derivatives at x_i + dt/2 * dx_i + if (!this->FunctionSet->FunctionValues(this->Vals, this->Derivs)) + { + memcpy(xnext, this->Vals, (numVals-1)*sizeof(double)); + return OUT_OF_DOMAIN; + } + + // Calculate x_i using improved values of derivatives + for(i=0; iDerivs[i]; + } + + return 0; +} + + + + + + diff --git a/Common/vtkRungeKutta2.h b/Common/vtkRungeKutta2.h new file mode 100644 index 0000000..f8bd4e8 --- /dev/null +++ b/Common/vtkRungeKutta2.h @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRungeKutta2.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRungeKutta2 - Integrate an initial value problem using 2nd +// order Runge-Kutta method. + +// .SECTION Description +// This is a concrete sub-class of vtkInitialValueProblemSolver. +// It uses a 2nd order Runge-Kutta method to obtain the values of +// a set of functions at the next time step. + +// .SECTION See Also +// vtkInitialValueProblemSolver vtkRungeKutta4 vtkRungeKutta45 vtkFunctionSet + +#ifndef __vtkRungeKutta2_h +#define __vtkRungeKutta2_h + +#include "vtkInitialValueProblemSolver.h" + +class VTK_COMMON_EXPORT vtkRungeKutta2 : public vtkInitialValueProblemSolver +{ +public: + vtkTypeRevisionMacro(vtkRungeKutta2,vtkInitialValueProblemSolver); + + // Description: + // Construct a vtkRungeKutta2 with no initial FunctionSet. + static vtkRungeKutta2 *New(); + + // Description: + // Given initial values, xprev , initial time, t and a requested time + // interval, delT calculate values of x at t+delT (xnext). + // delTActual is always equal to delT. + // Since this class can not provide an estimate for the error error + // is set to 0. + // maxStep, minStep and maxError are unused. + // This method returns an error code representing the nature of + // the failure: + // OutOfDomain = 1, + // NotInitialized = 2, + // UnexpectedValue = 3 + virtual int ComputeNextStep(double* xprev, double* xnext, double t, + double& delT, double maxError, double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, + double maxError, double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, dxprev, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error) + { + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error); + +protected: + vtkRungeKutta2(); + ~vtkRungeKutta2(); +private: + vtkRungeKutta2(const vtkRungeKutta2&); // Not implemented. + void operator=(const vtkRungeKutta2&); // Not implemented. +}; + +#endif + + + + + + + + diff --git a/Common/vtkRungeKutta4.cxx b/Common/vtkRungeKutta4.cxx new file mode 100644 index 0000000..7d37434 --- /dev/null +++ b/Common/vtkRungeKutta4.cxx @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRungeKutta4.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRungeKutta4.h" + +#include "vtkFunctionSet.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkRungeKutta4, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkRungeKutta4); + +vtkRungeKutta4::vtkRungeKutta4() +{ + for(int i=0; i<3; i++) + { + this->NextDerivs[i] = 0; + } +} + +vtkRungeKutta4::~vtkRungeKutta4() +{ + for(int i=0; i<3; i++) + { + delete[] this->NextDerivs[i]; + this->NextDerivs[i] = 0; + } +} + + +void vtkRungeKutta4::Initialize() +{ + this->vtkInitialValueProblemSolver::Initialize(); + if (!this->Initialized) + { + return; + } + // Allocate memory for temporary derivatives array + for(int i=0; i<3; i++) + { + this->NextDerivs[i] = + new double[this->FunctionSet->GetNumberOfFunctions()]; + } +} + +// For a detailed description of Runge-Kutta methods, +// see, for example, Numerical Recipes in (C/Fortran/Pascal) by +// Press et al. (Cambridge University Press) or +// Applied Numerical Analysis by C. F. Gerald and P. O. Wheatley +// (Addison Wesley) +int vtkRungeKutta4::ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, double& delTActual, + double, double, double, double& error) +{ + + int i, numDerivs, numVals; + + delTActual = delT; + error = 0; + + if (!this->FunctionSet) + { + vtkErrorMacro("No derivative functions are provided!"); + return NOT_INITIALIZED; + } + + if (!this->Initialized) + { + vtkErrorMacro("Integrator not initialized!"); + return NOT_INITIALIZED; + } + + numDerivs = this->FunctionSet->GetNumberOfFunctions(); + numVals = numDerivs + 1; + for(i=0; iVals[i] = xprev[i]; + } + this->Vals[numVals-1] = t; + + // 4th order + // 1 + if (dxprev) + { + for(i=0; iDerivs[i] = dxprev[i]; + } + } + else if ( !this->FunctionSet->FunctionValues(this->Vals, this->Derivs) ) + { + return OUT_OF_DOMAIN; + } + + for(i=0; iVals[i] = xprev[i] + delT/2.0*this->Derivs[i]; + } + this->Vals[numVals-1] = t + delT/2.0; + + // 2 + if (!this->FunctionSet->FunctionValues(this->Vals, this->NextDerivs[0])) + { + return OUT_OF_DOMAIN; + } + + for(i=0; iVals[i] = xprev[i] + delT/2.0*this->NextDerivs[0][i]; + } + this->Vals[numVals-1] = t + delT/2.0; + + // 3 + if (!this->FunctionSet->FunctionValues(this->Vals, this->NextDerivs[1])) + { + return OUT_OF_DOMAIN; + } + + for(i=0; iVals[i] = xprev[i] + delT*this->NextDerivs[1][i]; + } + this->Vals[numVals-1] = t + delT; + + // 4 + if (!this->FunctionSet->FunctionValues(this->Vals, this->NextDerivs[2])) + { + return OUT_OF_DOMAIN; + } + + for(i=0; iDerivs[i]/6.0 + + this->NextDerivs[0][i]/3.0 + + this->NextDerivs[1][i]/3.0 + + this->NextDerivs[2][i]/6.0); + } + + return 0; +} + +void vtkRungeKutta4::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Runge-Kutta 4 function derivatives: " + << this->NextDerivs[0] << " " << this->NextDerivs[1] << " " + << this->NextDerivs[2] << endl; +} + + + + + + diff --git a/Common/vtkRungeKutta4.h b/Common/vtkRungeKutta4.h new file mode 100644 index 0000000..dbeb037 --- /dev/null +++ b/Common/vtkRungeKutta4.h @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRungeKutta4.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRungeKutta4 - Integrate an initial value problem using 4th +// order Runge-Kutta method. + +// .SECTION Description +// This is a concrete sub-class of vtkInitialValueProblemSolver. +// It uses a 4th order Runge-Kutta method to obtain the values of +// a set of functions at the next time step. + +// .SECTION See Also +// vtkInitialValueProblemSolver vtkRungeKutta45 vtkRungeKutta2 vtkFunctionSet + +#ifndef __vtkRungeKutta4_h +#define __vtkRungeKutta4_h + +#include "vtkInitialValueProblemSolver.h" + +class VTK_COMMON_EXPORT vtkRungeKutta4 : public vtkInitialValueProblemSolver +{ +public: + vtkTypeRevisionMacro(vtkRungeKutta4,vtkInitialValueProblemSolver); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a vtkRungeKutta4 with no initial FunctionSet. + static vtkRungeKutta4 *New(); + + + // Description: + // Given initial values, xprev , initial time, t and a requested time + // interval, delT calculate values of x at t+delT (xnext). + // delTActual is always equal to delT. + // Since this class can not provide an estimate for the error error + // is set to 0. + // maxStep, minStep and maxError are unused. + // This method returns an error code representing the nature of + // the failure: + // OutOfDomain = 1, + // NotInitialized = 2, + // UnexpectedValue = 3 + virtual int ComputeNextStep(double* xprev, double* xnext, double t, + double& delT, double maxError, double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, + double maxError, double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, dxprev, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error) + { + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error); + +protected: + vtkRungeKutta4(); + ~vtkRungeKutta4(); + + virtual void Initialize(); + + double* NextDerivs[3]; +private: + vtkRungeKutta4(const vtkRungeKutta4&); // Not implemented. + void operator=(const vtkRungeKutta4&); // Not implemented. +}; + +#endif + + + + + + + + diff --git a/Common/vtkRungeKutta45.cxx b/Common/vtkRungeKutta45.cxx new file mode 100644 index 0000000..7cfd1e5 --- /dev/null +++ b/Common/vtkRungeKutta45.cxx @@ -0,0 +1,326 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRungeKutta45.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRungeKutta45.h" + +#include "vtkObjectFactory.h" +#include "vtkFunctionSet.h" + +vtkCxxRevisionMacro(vtkRungeKutta45, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkRungeKutta45); + +//---------------------------------------------------------------------------- +// Cash-Karp parameters +double vtkRungeKutta45::A[5] = { 1.0L/5.0, 3.0L/10.0, 3.0L/5.0, 1.0, + 7.0L/8.0 }; +double vtkRungeKutta45::B[5][5] = { { 1.0L/5.0, 0, 0, 0, 0 }, + { 3.0L/40.0, 9.0L/40.0, 0, 0, 0 }, + { 3.0L/10.0, -9.0L/10.0, 6.0L/5.0, 0, 0 }, + { -11.0L/54.0, + 5.0L/2.0, + -70.0L/27.0, + 35.0L/27.0, + 0 }, + { 1631.0L/55296.0, + 175.0/512.0, + 575.0/13824.0, + 44275.0/110592.0, + 253.0L/4096.0 } }; +double vtkRungeKutta45::C[6] = {37.0L/378.0, + 0, + 250.0L/621.0, + 125.0L/594.0, + 0, + 512.0L/1771.0 }; +double vtkRungeKutta45::DC[6] = { 37.0L/378.0 - 2825.0L/27648.0, + 0, + 250.0L/621.0 - 18575.0L/48384.0, + 125.0L/594.0 - 13525.0L/55296, + -277.0L/14336.0, + 512.0L/1771.0 - 1.0L/4.0}; + +//---------------------------------------------------------------------------- +vtkRungeKutta45::vtkRungeKutta45() +{ + for(int i=0; i<6; i++) + { + this->NextDerivs[i] = 0; + } + this->Adaptive = 1; +} + +//---------------------------------------------------------------------------- +vtkRungeKutta45::~vtkRungeKutta45() +{ + for(int i=0; i<6; i++) + { + delete[] this->NextDerivs[i]; + this->NextDerivs[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkRungeKutta45::Initialize() +{ + this->vtkInitialValueProblemSolver::Initialize(); + if (!this->Initialized) + { + return; + } + // Allocate memory for temporary derivatives array + for(int i=0; i<6; i++) + { + this->NextDerivs[i] = + new double[this->FunctionSet->GetNumberOfFunctions()]; + } +} + +//---------------------------------------------------------------------------- +int vtkRungeKutta45::ComputeNextStep(double* xprev, double* dxprev, + double* xnext, double t, double& delT, + double& delTActual, + double minStep, double maxStep, + double maxError, double& estErr ) +{ + estErr = VTK_DOUBLE_MAX; + + // Step size should always be positive. We'll check anyway. + if (minStep < 0) + { + minStep = -minStep; + } + if (maxStep < 0) + { + maxStep = -maxStep; + } + + delTActual = delT; + + // No step size control if minStep == maxStep == delT + double absDT = fabs(delT); + if ( ((minStep == absDT) && (maxStep == absDT)) || + (maxError <= 0.0) ) + { + return this->ComputeAStep(xprev, dxprev, xnext, t, delT, estErr); + } + else if ( minStep > maxStep ) + { + return UNEXPECTED_VALUE; + } + + double errRatio, tmp, tmp2; + int retVal, shouldBreak = 0; + + // Reduce the step size until estimated error <= maximum allowed error + while ( estErr > maxError ) + { + if ((retVal = + this->ComputeAStep(xprev, dxprev, xnext, t, delT, estErr))) + { + delTActual = delT; + return retVal; + } + // If the step just taken was either min, we are done, + // break + absDT = fabs(delT); + if ( absDT == minStep ) + { + break; + } + + errRatio = (double)estErr / (double)maxError; + // Empirical formulae for calculating next step size + // 0.9 is a safety factor to prevent infinite loops (see reference) + if ( errRatio == 0.0 ) // avoid pow errors + { + tmp = minStep; // arbitrarily set to minStep + } + else if ( errRatio > 1 ) + { + tmp = 0.9*delT*pow(errRatio, -0.25); + } + else + { + tmp = 0.9*delT*pow(errRatio, -0.2); + } + tmp2 = fabs(tmp); + + // Re-adjust step size if it exceeds the bounds + // If this happens, calculate once with the extrama step + // size and break (flagged by setting shouldBreak, see below) + if (tmp2 > maxStep ) + { + delT = maxStep * delT/fabs(delT); + shouldBreak = 1; + } + else if (tmp2 < minStep) + { + delT = minStep * delT/fabs(delT); + shouldBreak = 1; + } + else + { + delT = tmp; + } + + tmp2 = t + delT; + if ( tmp2 == t ) + { + vtkWarningMacro("Step size underflow. You must choose a larger " + "tolerance or set the minimum step size to a larger " + "value."); + return UNEXPECTED_VALUE; + } + + // If the new step size is equal to min or max, + // calculate once with the extrama step size and break + // (flagged by setting shouldBreak, see above) + if (shouldBreak) + { + if ( (retVal = + this->ComputeAStep(xprev, dxprev, xnext, t, delT, estErr)) ) + { + delTActual = delT; + return retVal; + } + break; + } + } + + delTActual = delT; + return 0; +} + +//---------------------------------------------------------------------------- +// Calculate next time step +int vtkRungeKutta45::ComputeAStep(double* xprev, double* dxprev, + double* xnext, double t, double& delT, + double& error) +{ + int i, j, k, numDerivs, numVals; + + + if (!this->FunctionSet) + { + vtkErrorMacro("No derivative functions are provided!"); + return NOT_INITIALIZED ; + } + + if (!this->Initialized) + { + vtkErrorMacro("Integrator not initialized!"); + return NOT_INITIALIZED; + } + + + numDerivs = this->FunctionSet->GetNumberOfFunctions(); + numVals = numDerivs + 1; + for(i=0; iVals[i] = xprev[i]; + } + this->Vals[numVals-1] = t; + + // Obtain the derivatives dx_i at x_i + if (dxprev) + { + for(i=0; iNextDerivs[0][i] = dxprev[i]; + } + } + else if ( !this->FunctionSet->FunctionValues(this->Vals, + this->NextDerivs[0]) ) + { + for(i=0; iVals[i]; + } + return OUT_OF_DOMAIN; + } + + double sum; + for (i=1; i<6; i++) + { + // Step i + // Calculate k_i (NextDerivs) for each step + for(j=0; jNextDerivs[k][j]; + } + this->Vals[j] = xprev[j] + delT*sum; + } + this->Vals[numVals-1] = t + delT*A[i-1]; + + if ( !this->FunctionSet->FunctionValues(this->Vals, + this->NextDerivs[i]) ) + { + for(i=0; iVals[i]; + } + return OUT_OF_DOMAIN; + } + } + + + // Calculate xnext + for(i=0; iNextDerivs[j][i]; + } + xnext[i] = xprev[i] + delT*sum; + } + + // Calculate norm of error vector + double err=0; + for(i=0; iNextDerivs[j][i]; + } + err += delT*sum*delT*sum; + } + error = sqrt(err); + + int numZero = 0; + for(i=0; iSuperclass::PrintSelf(os,indent); +} + diff --git a/Common/vtkRungeKutta45.h b/Common/vtkRungeKutta45.h new file mode 100644 index 0000000..1c53c1f --- /dev/null +++ b/Common/vtkRungeKutta45.h @@ -0,0 +1,130 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRungeKutta45.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRungeKutta45 - Integrate an initial value problem using 5th +// order Runge-Kutta method with adaptive stepsize control. + +// .SECTION Description +// This is a concrete sub-class of vtkInitialValueProblemSolver. +// It uses a 5th order Runge-Kutta method with stepsize control to obtain +// the values of a set of functions at the next time step. The stepsize +// is adjusted by calculating an estimated error using an embedded 4th +// order Runge-Kutta formula: +// Press, W. H. et al., 1992, Numerical Recipes in Fortran, Second +// Edition, Cambridge University Press +// Cash, J.R. and Karp, A.H. 1990, ACM Transactions on Mathematical +// Software, vol 16, pp 201-222 + +// .SECTION See Also +// vtkInitialValueProblemSolver vtkRungeKutta4 vtkRungeKutta2 vtkFunctionSet + +#ifndef __vtkRungeKutta45_h +#define __vtkRungeKutta45_h + +#include "vtkInitialValueProblemSolver.h" + +class VTK_COMMON_EXPORT vtkRungeKutta45 : public vtkInitialValueProblemSolver +{ +public: + vtkTypeRevisionMacro(vtkRungeKutta45,vtkInitialValueProblemSolver); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a vtkRungeKutta45 with no initial FunctionSet. + static vtkRungeKutta45 *New(); + + // Description: + // Given initial values, xprev , initial time, t and a requested time + // interval, delT calculate values of x at t+delTActual (xnext). + // Possibly delTActual != delT. This may occur + // because this solver supports adaptive stepsize control. It tries + // to change to stepsize such that + // the (estimated) error of the integration is less than maxError. + // The solver will not set the stepsize smaller than minStep or + // larger than maxStep (note that maxStep and minStep should both + // be positive, whereas delT can be negative). + // Also note that delT is an in/out argument. vtkRungeKutta45 + // will modify delT to reflect the best (estimated) size for the next + // integration step. + // An estimated value for the error is returned (by reference) in error. + // This is the norm of the error vector if there are more than + // one function to be integrated. + // This method returns an error code representing the nature of + // the failure: + // OutOfDomain = 1, + // NotInitialized = 2, + // UnexpectedValue = 3 + virtual int ComputeNextStep(double* xprev, double* xnext, double t, + double& delT, double maxError, double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, + double maxError, double& error) + { + double minStep = delT; + double maxStep = delT; + double delTActual; + return this->ComputeNextStep(xprev, dxprev, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error) + { + return this->ComputeNextStep(xprev, 0, xnext, t, delT, delTActual, + minStep, maxStep, maxError, error); + } + virtual int ComputeNextStep(double* xprev, double* dxprev, double* xnext, + double t, double& delT, double& delTActual, + double minStep, double maxStep, + double maxError, double& error); + +protected: + vtkRungeKutta45(); + ~vtkRungeKutta45(); + + virtual void Initialize(); + + // Cash-Karp parameters + static double A[5]; + static double B[5][5]; + static double C[6]; + static double DC[6]; + + double* NextDerivs[6]; + + int ComputeAStep(double* xprev, double* dxprev, double* xnext, double t, + double& delT, double& error); + +private: + vtkRungeKutta45(const vtkRungeKutta45&); // Not implemented. + void operator=(const vtkRungeKutta45&); // Not implemented. +}; + +#endif + + + + + + + + diff --git a/Common/vtkScalarsToColors.cxx b/Common/vtkScalarsToColors.cxx new file mode 100644 index 0000000..545990e --- /dev/null +++ b/Common/vtkScalarsToColors.cxx @@ -0,0 +1,283 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarsToColors.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkScalarsToColors.h" + +#include "vtkUnsignedCharArray.h" + +#include + +vtkCxxRevisionMacro(vtkScalarsToColors, "$Revision: 1.25 $"); + +//---------------------------------------------------------------------------- +vtkScalarsToColors::vtkScalarsToColors() +{ + this->Alpha = 1.0; + this->VectorComponent = 0; + this->VectorMode = vtkScalarsToColors::COMPONENT; + this->UseMagnitude = 0; +} + +//---------------------------------------------------------------------------- +void vtkScalarsToColors::SetVectorModeToComponent() +{ + this->SetVectorMode(vtkScalarsToColors::COMPONENT); +} + +//---------------------------------------------------------------------------- +void vtkScalarsToColors::SetVectorModeToMagnitude() +{ + this->SetVectorMode(vtkScalarsToColors::MAGNITUDE); +} + +//---------------------------------------------------------------------------- +// do not use SetMacro() because we do not want the table to rebuild. +void vtkScalarsToColors::SetAlpha(double alpha) +{ + this->Alpha = (alpha < 0.0 ? 0.0 : (alpha > 1.0 ? 1.0 : alpha)); +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray *vtkScalarsToColors::MapScalars(vtkDataArray *scalars, + int colorMode, int comp) +{ + vtkUnsignedCharArray *newColors; + vtkUnsignedCharArray *colors; + + // map scalars through lookup table only if needed + if ( colorMode == VTK_COLOR_MODE_DEFAULT && + (colors=vtkUnsignedCharArray::SafeDownCast(scalars)) != NULL ) + { + newColors = this-> + ConvertUnsignedCharToRGBA(colors, colors->GetNumberOfComponents(), + scalars->GetNumberOfTuples()); + } + else + { + newColors = vtkUnsignedCharArray::New(); + newColors->SetNumberOfComponents(4); + newColors->SetNumberOfTuples(scalars->GetNumberOfTuples()); + + // If mapper did not specify a component, use our mode. + this->UseMagnitude = 0; + if (comp < 0 && this->VectorMode == vtkScalarsToColors::COMPONENT) + { + comp = this->VectorComponent; + } + if (comp < 0 && this->VectorMode == vtkScalarsToColors::MAGNITUDE) + { + comp = 0; + this->UseMagnitude = 1; + } + + // Just some error checking. + if (comp < 0) + { + comp = 0; + } + if (comp >= scalars->GetNumberOfComponents()) + { + comp = scalars->GetNumberOfComponents()-1; + } + // Fill in the colors. + this->MapScalarsThroughTable2(scalars->GetVoidPointer(comp), + newColors->GetPointer(0), + scalars->GetDataType(), + scalars->GetNumberOfTuples(), + scalars->GetNumberOfComponents(), + VTK_RGBA); + }//need to map + + // Here is a bit of a hack. + // It is much faster to render RGB instead of RGBA when possible. + // I do not want to create a 3 component color array because + // it would be another condition. Give the mapper a hint that + // the colors have no alpha by setting the name. + // When the mapper can handle 3 component color array, + // I will change this logic to use NumberOfComponents as + // an indicator of opacity. + unsigned char* alphaPtr = newColors->GetPointer(0) + 3; + vtkIdType idx, num; + int opaque = 1; + num = newColors->GetNumberOfTuples(); + for (idx = 0; idx < num; ++idx) + { + if (*alphaPtr < 255) + { + opaque = 0; + } + alphaPtr += 4; + } + if (opaque) + { + newColors->SetName("Opaque Colors"); + } + + return newColors; +} + +//---------------------------------------------------------------------------- +// Map a set of scalar values through the table +void vtkScalarsToColors::MapScalarsThroughTable(vtkDataArray *scalars, + unsigned char *output, + int outputFormat) +{ + switch (outputFormat) + { + case VTK_RGBA: + case VTK_RGB: + case VTK_LUMINANCE_ALPHA: + case VTK_LUMINANCE: + break; + default: + vtkErrorMacro(<< "MapScalarsThroughTable: unrecognized color format"); + break; + } + + this->MapScalarsThroughTable2(scalars->GetVoidPointer(0), + output, + scalars->GetDataType(), + scalars->GetNumberOfTuples(), + scalars->GetNumberOfComponents(), + outputFormat); +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray *vtkScalarsToColors::ConvertUnsignedCharToRGBA( + vtkUnsignedCharArray *colors, int numComp, int numTuples) +{ + if ( numComp == 4 && this->Alpha >= 1.0 ) + { + colors->Register(this); + return colors; + } + + unsigned char *cptr = colors->GetPointer(0); + vtkUnsignedCharArray *newColors = vtkUnsignedCharArray::New(); + newColors->SetNumberOfComponents(4); + newColors->SetNumberOfTuples(numTuples); + unsigned char *nptr = newColors->GetPointer(0); + int i; + + if ( this->Alpha >= 1.0 ) + { + switch (numComp) + { + case 1: + for (i=0; i(this->Alpha*255); + for (i=0; i((*cptr)*this->Alpha); cptr++; + } + break; + + case 3: + alpha = static_cast(this->Alpha*255); + for (i=0; i((*cptr)*this->Alpha); cptr++; + } + break; + + default: + vtkErrorMacro(<<"Cannot convert colors"); + return NULL; + } + } + + return newColors; +} + +//---------------------------------------------------------------------------- +void vtkScalarsToColors::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Alpha: " << this->Alpha << endl; + if (this->VectorMode == vtkScalarsToColors::MAGNITUDE) + { + os << indent << "VectorMode: Magnitude\n"; + } + else + { + os << indent << "VectorMode: Component\n"; + os << indent << "VectorComponent: " << this->VectorComponent << endl; + } +} diff --git a/Common/vtkScalarsToColors.h b/Common/vtkScalarsToColors.h new file mode 100644 index 0000000..b00732a --- /dev/null +++ b/Common/vtkScalarsToColors.h @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarsToColors.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkScalarsToColors - map scalar values into colors +// .SECTION Description +// vtkScalarsToColors is a general purpose superclass for objects that +// convert scalars to colors. This include vtkLookupTable classes and +// color transfer functions. +// +// The scalars to color mapping can be augmented with an additional +// uniform alpha blend. This is used, for example, to blend a vtkActor's +// opacity with the lookup table values. +// +// .SECTION See Also +// vtkLookupTable vtkColorTransferFunction + +#ifndef __vtkScalarsToColors_h +#define __vtkScalarsToColors_h + +#include "vtkObject.h" + +class vtkDataArray; +class vtkUnsignedCharArray; + +class VTK_COMMON_EXPORT vtkScalarsToColors : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkScalarsToColors,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Perform any processing required (if any) before processing + // scalars. + virtual void Build() {}; + + // Description: + // Sets/Gets the range of scalars which will be mapped. + virtual double *GetRange() = 0; + virtual void SetRange(double min, double max) = 0; + void SetRange(double rng[2]) + {this->SetRange(rng[0],rng[1]);} + + // Description: + // Map one value through the lookup table and return a color defined + // as a RGBA unsigned char tuple (4 bytes). + virtual unsigned char *MapValue(double v) = 0; + + // Description: + // Map one value through the lookup table and return the color as + // an RGB array of doubles between 0 and 1. + virtual void GetColor(double v, double rgb[3]) = 0; + + // Description: + // Map one value through the lookup table and return the color as + // an RGB array of doubles between 0 and 1. + double *GetColor(double v) + {this->GetColor(v,this->RGB); return this->RGB;} + + // Description: + // Map one value through the lookup table and return the alpha value + // (the opacity) as a double between 0 and 1. + virtual double GetOpacity(double vtkNotUsed(v)) + {return 1.0;} + + // Description: + // Map one value through the lookup table and return the luminance + // 0.3*red + 0.59*green + 0.11*blue as a double between 0 and 1. + // Returns the luminance value for the specified scalar value. + double GetLuminance(double x) + {double rgb[3]; this->GetColor(x,rgb); + return static_cast(rgb[0]*0.30 + rgb[1]*0.59 + rgb[2]*0.11);} + + // Description: + // Specify an additional opacity (alpha) value to blend with. Values + // != 1 modify the resulting color consistent with the requested + // form of the output. This is typically used by an actor in order to + // blend its opacity. + void SetAlpha(double alpha); + vtkGetMacro(Alpha,double); + + // Description: + // An internal method maps a data array into a 4-component, unsigned char + // RGBA array. The color mode determines the behavior of mapping. If + // VTK_COLOR_MODE_DEFAULT is set, then unsigned char data arrays are + // treated as colors (and converted to RGBA if necessary); otherwise, + // the data is mapped through this instance of ScalarsToColors. The offset + // is used for data arrays with more than one component; it indicates + // which component to use to do the blending. + // When the component argument is -1, then the this object uses its + // own selected technique to change a vector into a scalar to map. + vtkUnsignedCharArray *MapScalars(vtkDataArray *scalars, int colorMode, + int component); + + // Description: + // Change mode that maps vectors by magnitude vs. component. + vtkSetMacro(VectorMode, int); + vtkGetMacro(VectorMode, int); + void SetVectorModeToMagnitude(); + void SetVectorModeToComponent(); + +//BTX + enum VectorModes { + MAGNITUDE=0, + COMPONENT=1 + }; +//ETX + + + // Description: + // If the mapper does not select which component of a vector + // to map to colors, you can specify it here. + vtkSetMacro(VectorComponent, int); + vtkGetMacro(VectorComponent, int); + + // Description: + // Map a set of scalars through the lookup table in a single operation. + // The output format can be set to VTK_RGBA (4 components), + // VTK_RGB (3 components), VTK_LUMINANCE (1 component, greyscale), + // or VTK_LUMINANCE_ALPHA (2 components) + // If not supplied, the output format defaults to RGBA. + void MapScalarsThroughTable(vtkDataArray *scalars, + unsigned char *output, + int outputFormat); + void MapScalarsThroughTable(vtkDataArray *scalars, + unsigned char *output) + {this->MapScalarsThroughTable(scalars,output,VTK_RGBA);} + + + // Description: + // An internal method typically not used in applications. + virtual void MapScalarsThroughTable2(void *input, unsigned char *output, + int inputDataType, int numberOfValues, + int inputIncrement, + int outputFormat) = 0; + + // Description: + // An internal method used to convert a color array to RGBA. The + // method instantiates a vtkUnsignedCharArray and returns it. The user is + // responsible for managing the memory. + virtual vtkUnsignedCharArray *ConvertUnsignedCharToRGBA( + vtkUnsignedCharArray *colors, int numComp, int numTuples); + +protected: + vtkScalarsToColors(); + ~vtkScalarsToColors() {} + + double Alpha; + + // How to map arrays with multiple components. + int VectorMode; + // Internal flag used to togle between vector and component mode. + // We need this flag because the mapper can override our mode, and + // I do not want to change the interface to the map scalars methods. + int UseMagnitude; + int VectorComponent; + +private: + double RGB[3]; + + vtkScalarsToColors(const vtkScalarsToColors&); // Not implemented. + void operator=(const vtkScalarsToColors&); // Not implemented. +}; + +#endif + + + diff --git a/Common/vtkSetGet.h b/Common/vtkSetGet.h new file mode 100644 index 0000000..8b9bce6 --- /dev/null +++ b/Common/vtkSetGet.h @@ -0,0 +1,771 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSetGet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME SetGet Macros - standard macros for setting/getting instance variables +// .SECTION Description +// The SetGet macros are used to interface to instance variables +// in a standard fashion. This includes properly treating modified time +// and printing out debug information. +// +// Macros are available for built-in types; for character strings; +// vector arrays of built-in types size 2,3,4; for setting objects; and +// debug, warning, and error printout information. + +#ifndef __vtkSetGet_h +#define __vtkSetGet_h + +#include "vtkSystemIncludes.h" +#include + +// A macro to get the name of a type +#define vtkImageScalarTypeNameMacro(type) \ +(((type) == VTK_VOID) ? "void" : \ +(((type) == VTK_BIT) ? "bit" : \ +(((type) == VTK_CHAR) ? "char" : \ +(((type) == VTK_SIGNED_CHAR) ? "signed char" : \ +(((type) == VTK_UNSIGNED_CHAR) ? "unsigned char" : \ +(((type) == VTK_SHORT) ? "short" : \ +(((type) == VTK_UNSIGNED_SHORT) ? "unsigned short" : \ +(((type) == VTK_INT) ? "int" : \ +(((type) == VTK_UNSIGNED_INT) ? "unsigned int" : \ +(((type) == VTK_LONG) ? "long" : \ +(((type) == VTK_UNSIGNED_LONG) ? "unsigned long" : \ +(((type) == VTK_LONG_LONG) ? "long long" : \ +(((type) == VTK_UNSIGNED_LONG_LONG) ? "unsigned long long" : \ +(((type) == VTK___INT64) ? "__int64" : \ +(((type) == VTK_UNSIGNED___INT64) ? "unsigned __int64" : \ +(((type) == VTK_FLOAT) ? "float" : \ +(((type) == VTK_DOUBLE) ? "double" : \ +(((type) == VTK_ID_TYPE) ? "idtype" : \ +"Undefined")))))))))))))))))) + +// +// Set built-in type. Creates member Set"name"() (e.g., SetVisibility()); +// +#define vtkSetMacro(name,type) \ +virtual void Set##name (type _arg) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " #name " to " << _arg); \ + if (this->name != _arg) \ + { \ + this->name = _arg; \ + this->Modified(); \ + } \ + } + +// +// Get built-in type. Creates member Get"name"() (e.g., GetVisibility()); +// +#define vtkGetMacro(name,type) \ +virtual type Get##name () { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " of " << this->name ); \ + return this->name; \ + } + + +// +// Set character string. Creates member Set"name"() +// (e.g., SetFilename(char *)); +// +#define vtkSetStringMacro(name) \ +virtual void Set##name (const char* _arg) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " << #name " to " << (_arg?_arg:"(null)") ); \ + if ( this->name == NULL && _arg == NULL) { return;} \ + if ( this->name && _arg && (!strcmp(this->name,_arg))) { return;} \ + if (this->name) { delete [] this->name; } \ + if (_arg) \ + { \ + size_t n = strlen(_arg) + 1; \ + char *cp1 = new char[n]; \ + const char *cp2 = (_arg); \ + this->name = cp1; \ + do { *cp1++ = *cp2++; } while ( --n ); \ + } \ + else \ + { \ + this->name = NULL; \ + } \ + this->Modified(); \ + } + +// +// Get character string. Creates member Get"name"() +// (e.g., char *GetFilename()); +// +#define vtkGetStringMacro(name) \ +virtual char* Get##name () { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " of " << (this->name?this->name:"(null)")); \ + return this->name; \ + } + +// +// Set built-in type where value is constrained between min/max limits. +// Create member Set"name"() (eg., SetRadius()). #defines are +// convenience for clamping open-ended values. +// The Get"name"MinValue() and Get"name"MaxValue() members return the +// min and max limits. +// +#define vtkSetClampMacro(name,type,min,max) \ +virtual void Set##name (type _arg) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " << #name " to " << _arg ); \ + if (this->name != (_argmax?max:_arg))) \ + { \ + this->name = (_argmax?max:_arg)); \ + this->Modified(); \ + } \ + } \ +virtual type Get##name##MinValue () \ + { \ + return min; \ + } \ +virtual type Get##name##MaxValue () \ + { \ + return max; \ + } + +// +// This macro defines a body of set object macro. It can be used either in +// the header file vtkSetObjectMacro or in the implementation one +// vtkSetObjectMacro. It sets the pointer to object; uses vtkObject +// reference counting methodology. Creates method +// Set"name"() (e.g., SetPoints()). +// +#define vtkSetObjectBodyMacro(name,type,args) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this \ + << "): setting " << #name " to " << args ); \ + if (this->name != args) \ + { \ + type* tempSGMacroVar = this->name; \ + this->name = args; \ + if (this->name != NULL) { this->name->Register(this); } \ + if (tempSGMacroVar != NULL) \ + { \ + tempSGMacroVar->UnRegister(this); \ + } \ + this->Modified(); \ + } \ + } + +// +// Set pointer to object; uses vtkObject reference counting methodology. +// Creates method Set"name"() (e.g., SetPoints()). This macro should +// be used in the header file. +// +#define vtkSetObjectMacro(name,type) \ +virtual void Set##name (type* _arg) \ + { \ + vtkSetObjectBodyMacro(name,type,_arg); \ + } + +// +// Set pointer to object; uses vtkObject reference counting methodology. +// Creates method Set"name"() (e.g., SetPoints()). This macro should +// be used in the implementation file. You will also have to write +// prototype in the header file. The prototype should look like this: +// virtual void Set"name"("type" *); +// +// Please use vtkCxxSetObjectMacro not vtkSetObjectImplementationMacro. +// The first one is just for people who already used it. +#define vtkSetObjectImplementationMacro(class,name,type) \ + vtkCxxSetObjectMacro(class,name,type) + +#define vtkCxxSetObjectMacro(class,name,type) \ +void class::Set##name (type* _arg) \ + { \ + vtkSetObjectBodyMacro(name,type,_arg); \ + } + +// +// Get pointer to object. Creates member Get"name" (e.g., GetPoints()). +// This macro should be used in the header file. +// +#define vtkGetObjectMacro(name,type) \ +virtual type *Get##name () \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this \ + << "): returning " #name " address " << this->name ); \ + return this->name; \ + } + +// +// Create members "name"On() and "name"Off() (e.g., DebugOn() DebugOff()). +// Set method must be defined to use this macro. +// +#define vtkBooleanMacro(name,type) \ +virtual void name##On () { this->Set##name((type)1);}; \ +virtual void name##Off () { this->Set##name((type)0);} + +// +// Following set macros for vectors define two members for each macro. The first +// allows setting of individual components (e.g, SetColor(float,float,float)), +// the second allows setting from an array (e.g., SetColor(float* rgb[3])). +// The macros vary in the size of the vector they deal with. +// +#define vtkSetVector2Macro(name,type) \ +virtual void Set##name (type _arg1, type _arg2) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " << #name " to (" << _arg1 << "," << _arg2 << ")"); \ + if ((this->name[0] != _arg1)||(this->name[1] != _arg2)) \ + { \ + this->name[0] = _arg1; \ + this->name[1] = _arg2; \ + this->Modified(); \ + } \ + }; \ +void Set##name (type _arg[2]) \ + { \ + this->Set##name (_arg[0], _arg[1]); \ + } + +#define vtkGetVector2Macro(name,type) \ +virtual type *Get##name () \ +{ \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " pointer " << this->name); \ + return this->name; \ +} \ +virtual void Get##name (type &_arg1, type &_arg2) \ + { \ + _arg1 = this->name[0]; \ + _arg2 = this->name[1]; \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " = (" << _arg1 << "," << _arg2 << ")"); \ + }; \ +virtual void Get##name (type _arg[2]) \ + { \ + this->Get##name (_arg[0], _arg[1]);\ + } + +#define vtkSetVector3Macro(name,type) \ +virtual void Set##name (type _arg1, type _arg2, type _arg3) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " << #name " to (" << _arg1 << "," << _arg2 << "," << _arg3 << ")"); \ + if ((this->name[0] != _arg1)||(this->name[1] != _arg2)||(this->name[2] != _arg3)) \ + { \ + this->name[0] = _arg1; \ + this->name[1] = _arg2; \ + this->name[2] = _arg3; \ + this->Modified(); \ + } \ + }; \ +virtual void Set##name (type _arg[3]) \ + { \ + this->Set##name (_arg[0], _arg[1], _arg[2]);\ + } + +#define vtkGetVector3Macro(name,type) \ +virtual type *Get##name () \ +{ \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " pointer " << this->name); \ + return this->name; \ +} \ +virtual void Get##name (type &_arg1, type &_arg2, type &_arg3) \ + { \ + _arg1 = this->name[0]; \ + _arg2 = this->name[1]; \ + _arg3 = this->name[2]; \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " = (" << _arg1 << "," << _arg2 << "," << _arg3 << ")"); \ + }; \ +virtual void Get##name (type _arg[3]) \ + { \ + this->Get##name (_arg[0], _arg[1], _arg[2]);\ + } + +#define vtkSetVector4Macro(name,type) \ +virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " << #name " to (" << _arg1 << "," << _arg2 << "," << _arg3 << "," << _arg4 << ")"); \ + if ((this->name[0] != _arg1)||(this->name[1] != _arg2)||(this->name[2] != _arg3)||(this->name[3] != _arg4)) \ + { \ + this->name[0] = _arg1; \ + this->name[1] = _arg2; \ + this->name[2] = _arg3; \ + this->name[3] = _arg4; \ + this->Modified(); \ + } \ + }; \ +virtual void Set##name (type _arg[4]) \ + { \ + this->Set##name (_arg[0], _arg[1], _arg[2], _arg[3]);\ + } + + +#define vtkGetVector4Macro(name,type) \ +virtual type *Get##name () \ +{ \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " pointer " << this->name); \ + return this->name; \ +} \ +virtual void Get##name (type &_arg1, type &_arg2, type &_arg3, type &_arg4) \ + { \ + _arg1 = this->name[0]; \ + _arg2 = this->name[1]; \ + _arg3 = this->name[2]; \ + _arg4 = this->name[3]; \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " = (" << _arg1 << "," << _arg2 << "," << _arg3 << "," << _arg4 << ")"); \ + }; \ +virtual void Get##name (type _arg[4]) \ + { \ + this->Get##name (_arg[0], _arg[1], _arg[2], _arg[3]);\ + } + +#define vtkSetVector6Macro(name,type) \ +virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4, type _arg5, type _arg6) \ + { \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " << #name " to (" << _arg1 << "," << _arg2 << "," << _arg3 << "," << _arg4 << "," << _arg5 << "," << _arg6 << ")"); \ + if ((this->name[0] != _arg1)||(this->name[1] != _arg2)||(this->name[2] != _arg3)||(this->name[3] != _arg4)||(this->name[4] != _arg5)||(this->name[5] != _arg6)) \ + { \ + this->name[0] = _arg1; \ + this->name[1] = _arg2; \ + this->name[2] = _arg3; \ + this->name[3] = _arg4; \ + this->name[4] = _arg5; \ + this->name[5] = _arg6; \ + this->Modified(); \ + } \ + }; \ +virtual void Set##name (type _arg[6]) \ + { \ + this->Set##name (_arg[0], _arg[1], _arg[2], _arg[3], _arg[4], _arg[5]);\ + } + +#define vtkGetVector6Macro(name,type) \ +virtual type *Get##name () \ +{ \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " pointer " << this->name); \ + return this->name; \ +} \ +virtual void Get##name (type &_arg1, type &_arg2, type &_arg3, type &_arg4, type &_arg5, type &_arg6) \ + { \ + _arg1 = this->name[0]; \ + _arg2 = this->name[1]; \ + _arg3 = this->name[2]; \ + _arg4 = this->name[3]; \ + _arg5 = this->name[4]; \ + _arg6 = this->name[5]; \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " = (" << _arg1 << "," << _arg2 << "," << _arg3 << "," << _arg4 << "," << _arg5 <<"," << _arg6 << ")"); \ + }; \ +virtual void Get##name (type _arg[6]) \ + { \ + this->Get##name (_arg[0], _arg[1], _arg[2], _arg[3], _arg[4], _arg[5]);\ + } + +// +// General set vector macro creates a single method that copies specified +// number of values into object. +// Examples: void SetColor(c,3) +// +#define vtkSetVectorMacro(name,type,count) \ +virtual void Set##name(type data[]) \ +{ \ + int i; \ + for (i=0; iname[i] ) { break; }} \ + if ( i < count ) \ + { \ + for (i=0; iname[i] = data[i]; }\ + this->Modified(); \ + } \ +} + +// +// Get vector macro defines two methods. One returns pointer to type +// (i.e., array of type). This is for efficiency. The second copies data +// into user provided array. This is more object-oriented. +// Examples: float *GetColor() and void GetColor(float c[count]). +// +#define vtkGetVectorMacro(name,type,count) \ +virtual type *Get##name () \ +{ \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " pointer " << this->name); \ + return this->name; \ +} \ +virtual void Get##name (type data[count]) \ +{ \ + for (int i=0; iname[i]; }\ +} + +// Use a global function which actually calls: +// vtkOutputWindow::GetInstance()->DisplayText(); +// This is to avoid vtkObject #include of vtkOutputWindow +// while vtkOutputWindow #includes vtkObject + +extern VTK_COMMON_EXPORT void vtkOutputWindowDisplayText(const char*); +extern VTK_COMMON_EXPORT void vtkOutputWindowDisplayErrorText(const char*); +extern VTK_COMMON_EXPORT void vtkOutputWindowDisplayWarningText(const char*); +extern VTK_COMMON_EXPORT void vtkOutputWindowDisplayGenericWarningText(const char*); +extern VTK_COMMON_EXPORT void vtkOutputWindowDisplayDebugText(const char*); + +// +// This macro is used for any output that may not be in an instance method +// vtkGenericWarningMacro(<< "this is debug info" << this->SomeVariable); +// +#define vtkGenericWarningMacro(x) \ +{ if (vtkObject::GetGlobalWarningDisplay()) { \ + vtkOStreamWrapper::EndlType endl; \ + vtkOStreamWrapper::UseEndl(endl); \ + vtkOStrStreamWrapper vtkmsg; \ + vtkmsg << "Generic Warning: In " __FILE__ ", line " << __LINE__ << "\n" x \ + << "\n\n"; \ + vtkOutputWindowDisplayGenericWarningText(vtkmsg.str());\ + vtkmsg.rdbuf()->freeze(0);}} + +// +// This macro is used for debug statements in instance methods +// vtkDebugMacro(<< "this is debug info" << this->SomeVariable); +// +#define vtkDebugMacro(x) \ + vtkDebugWithObjectMacro(this,x) + +// +// This macro is used to print out warning messages. +// vtkWarningMacro(<< "Warning message" << variable); +// +#define vtkWarningMacro(x) \ + vtkWarningWithObjectMacro(this,x) + +// +// This macro is used to print out errors +// vtkErrorMacro(<< "Error message" << variable); +// +#define vtkErrorMacro(x) \ + vtkErrorWithObjectMacro(this,x) + +// +// This macro is used to print out errors +// vtkErrorWithObjectMacro(self, << "Error message" << variable); +// +#define vtkErrorWithObjectMacro(self, x) \ + { \ + if (vtkObject::GetGlobalWarningDisplay()) \ + { \ + vtkOStreamWrapper::EndlType endl; \ + vtkOStreamWrapper::UseEndl(endl); \ + vtkOStrStreamWrapper vtkmsg; \ + vtkmsg << "ERROR: In " __FILE__ ", line " << __LINE__ \ + << "\n" << self->GetClassName() << " (" << self \ + << "): " x << "\n\n"; \ + if ( self->HasObserver("ErrorEvent") ) \ + { \ + self->InvokeEvent("ErrorEvent", vtkmsg.str()); \ + } \ + else \ + { \ + vtkOutputWindowDisplayErrorText(vtkmsg.str()); \ + } \ + vtkmsg.rdbuf()->freeze(0); vtkObject::BreakOnError(); \ + } \ + } + +// +// This macro is used to print out warnings +// vtkWarningWithObjectMacro(self, "Warning message" << variable); +// +#define vtkWarningWithObjectMacro(self, x) \ + { \ + if (vtkObject::GetGlobalWarningDisplay()) \ + { \ + vtkOStreamWrapper::EndlType endl; \ + vtkOStreamWrapper::UseEndl(endl); \ + vtkOStrStreamWrapper vtkmsg; \ + vtkmsg << "Warning: In " __FILE__ ", line " << __LINE__ \ + << "\n" << self->GetClassName() << " (" << self \ + << "): " x << "\n\n"; \ + if ( self->HasObserver("WarningEvent") ) \ + { \ + self->InvokeEvent("WarningEvent", vtkmsg.str()); \ + } \ + else \ + { \ + vtkOutputWindowDisplayWarningText(vtkmsg.str()); \ + } \ + vtkmsg.rdbuf()->freeze(0); \ + } \ + } + +#ifdef VTK_LEAN_AND_MEAN +# define vtkDebugWithObjectMacro(self, x) +#else +# define vtkDebugWithObjectMacro(self, x) \ + { \ + if (self->GetDebug() && vtkObject::GetGlobalWarningDisplay()) \ + { \ + vtkOStreamWrapper::EndlType endl; \ + vtkOStreamWrapper::UseEndl(endl); \ + vtkOStrStreamWrapper vtkmsg; \ + vtkmsg << "Debug: In " __FILE__ ", line " << __LINE__ << "\n" \ + << self->GetClassName() << " (" << self << "): " x << "\n\n"; \ + vtkOutputWindowDisplayDebugText(vtkmsg.str()); \ + vtkmsg.rdbuf()->freeze(0); \ + } \ + } +#endif + +// +// This macro is used to quiet compiler warnings about unused parameters +// to methods. Only use it when the parameter really shouldn't be used. +// Don't use it as a way to shut up the compiler while you take your +// sweet time getting around to implementing the method. +// +#define vtkNotUsed(x) + +#define vtkWorldCoordinateMacro(name) \ +virtual vtkCoordinate *Get##name##Coordinate () \ +{ \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " #name "Coordinate address " << this->name##Coordinate ); \ + return this->name##Coordinate; \ +} \ +virtual void Set##name(double x[3]) {this->Set##name(x[0],x[1],x[2]);}; \ +virtual void Set##name(double x, double y, double z) \ +{ \ + this->name##Coordinate->SetValue(x,y,z); \ +} \ +virtual double *Get##name() \ +{ \ + return this->name##Coordinate->GetValue(); \ +} + +#define vtkViewportCoordinateMacro(name) \ +virtual vtkCoordinate *Get##name##Coordinate () \ +{ \ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " #name "Coordinate address " << this->name##Coordinate ); \ + return this->name##Coordinate; \ +} \ +virtual void Set##name(double x[2]) {this->Set##name(x[0],x[1]);}; \ +virtual void Set##name(double x, double y) \ +{ \ + this->name##Coordinate->SetValue(x,y); \ +} \ +virtual double *Get##name() \ +{ \ + return this->name##Coordinate->GetValue(); \ +} + +// Macro used to determine whether a class is the same class or +// a subclass of the named class. +// +#define vtkTypeMacro(thisClass,superclass) \ + typedef superclass Superclass; \ + private: \ + virtual const char* GetClassNameInternal() const { return #thisClass; } \ + public: \ + static int IsTypeOf(const char *type) \ + { \ + if ( !strcmp(#thisClass,type) ) \ + { \ + return 1; \ + } \ + return superclass::IsTypeOf(type); \ + } \ + virtual int IsA(const char *type) \ + { \ + return this->thisClass::IsTypeOf(type); \ + } \ + static thisClass* SafeDownCast(vtkObjectBase *o) \ + { \ + if ( o && o->IsA(#thisClass) ) \ + { \ + return static_cast(o); \ + } \ + return NULL;\ + } \ + protected: \ + virtual vtkObjectBase *NewInstanceInternal() const \ + { \ + return thisClass::New(); \ + } \ + public: \ + thisClass *NewInstance() const \ + { \ + return thisClass::SafeDownCast(this->NewInstanceInternal()); \ + } + +// Version of vtkTypeMacro that adds the CollectRevisions method. +#define vtkTypeRevisionMacro(thisClass,superclass) \ + protected: \ + void CollectRevisions(ostream& os); \ + public: \ + vtkTypeMacro(thisClass,superclass) + +// Macro to implement the standard CollectRevisions method. +#define vtkCxxRevisionMacro(thisClass, revision) \ + void thisClass::CollectRevisions(ostream& sos) \ + { \ + vtkOStreamWrapper os(sos); \ + this->Superclass::CollectRevisions(os); \ + os << #thisClass " " revision "\n"; \ + } + +// Macro to implement the standard form of the New() method. +#define vtkStandardNewMacro(thisClass) \ + thisClass* thisClass::New() \ + { \ + vtkObject* ret = vtkObjectFactory::CreateInstance(#thisClass); \ + if(ret) \ + { \ + return static_cast(ret); \ + } \ + return new thisClass; \ + } \ + vtkInstantiatorNewMacro(thisClass) + +// Macro to implement the instantiator's wrapper around the New() +// method. Use this macro if and only if vtkStandardNewMacro is not +// used by the class. +#define vtkInstantiatorNewMacro(thisClass) \ + extern vtkObject* vtkInstantiator##thisClass##New(); \ + vtkObject* vtkInstantiator##thisClass##New() \ + { \ + return thisClass::New(); \ + } + +// The vtkTemplateMacro is used to centralize the set of types +// supported by Execute methods. It also avoids duplication of long +// switch statement case lists. +// +// This version of the macro allows the template to take any number of +// arguments. Example usage: +// switch(array->GetDataType()) +// { +// vtkTemplateMacro(myFunc(static_cast(data), arg2)); +// } +#define vtkTemplateMacroCase(typeN, type, call) \ + case typeN: { typedef type VTK_TT; call; }; break +#define vtkTemplateMacro(call) \ + vtkTemplateMacroCase(VTK_DOUBLE, double, call); \ + vtkTemplateMacroCase(VTK_FLOAT, float, call); \ + vtkTemplateMacroCase_ll(VTK_LONG_LONG, long long, call) \ + vtkTemplateMacroCase_ll(VTK_UNSIGNED_LONG_LONG, unsigned long long, call) \ + vtkTemplateMacroCase_si64(VTK___INT64, __int64, call) \ + vtkTemplateMacroCase_ui64(VTK_UNSIGNED___INT64, unsigned __int64, call) \ + vtkTemplateMacroCase(VTK_ID_TYPE, vtkIdType, call); \ + vtkTemplateMacroCase(VTK_LONG, long, call); \ + vtkTemplateMacroCase(VTK_UNSIGNED_LONG, unsigned long, call); \ + vtkTemplateMacroCase(VTK_INT, int, call); \ + vtkTemplateMacroCase(VTK_UNSIGNED_INT, unsigned int, call); \ + vtkTemplateMacroCase(VTK_SHORT, short, call); \ + vtkTemplateMacroCase(VTK_UNSIGNED_SHORT, unsigned short, call); \ + vtkTemplateMacroCase(VTK_CHAR, char, call); \ + vtkTemplateMacroCase(VTK_SIGNED_CHAR, signed char, call); \ + vtkTemplateMacroCase(VTK_UNSIGNED_CHAR, unsigned char, call) + +// Add "long long" to the template macro if it is enabled. +#if defined(VTK_TYPE_USE_LONG_LONG) +# define vtkTemplateMacroCase_ll(typeN, type, call) \ + vtkTemplateMacroCase(typeN, type, call); +#else +# define vtkTemplateMacroCase_ll(typeN, type, call) +#endif + +// Add "__int64" to the template macro if it is enabled. +#if defined(VTK_TYPE_USE___INT64) +# define vtkTemplateMacroCase_si64(typeN, type, call) \ + vtkTemplateMacroCase(typeN, type, call); +#else +# define vtkTemplateMacroCase_si64(typeN, type, call) +#endif + +// Add "unsigned __int64" to the template macro if it is enabled and +// can be converted to double. +#if defined(VTK_TYPE_USE___INT64) && defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) +# define vtkTemplateMacroCase_ui64(typeN, type, call) \ + vtkTemplateMacroCase(typeN, type, call); +#else +# define vtkTemplateMacroCase_ui64(typeN, type, call) +#endif + +// Legacy versions of vtkTemplateMacro: +#if !defined(VTK_LEGACY_REMOVE) +# define vtkTemplateMacro3(func, a1, a2, a3) \ + vtkTemplateMacro(func (a1, a2, a3)) +# define vtkTemplateMacro4(func, a1, a2, a3, a4) \ + vtkTemplateMacro(func (a1, a2, a3, a4)) +# define vtkTemplateMacro5(func, a1, a2, a3, a4, a5) \ + vtkTemplateMacro(func (a1, a2, a3, a4, a5)) +# define vtkTemplateMacro6(func, a1, a2, a3, a4, a5, a6) \ + vtkTemplateMacro(func (a1, a2, a3, a4, a5, a6)) +# define vtkTemplateMacro7(func, a1, a2, a3, a4, a5, a6, a7) \ + vtkTemplateMacro(func (a1, a2, a3, a4, a5, a6, a7)) +# define vtkTemplateMacro8(func, a1, a2, a3, a4, a5, a6, a7, a8) \ + vtkTemplateMacro(func (a1, a2, a3, a4, a5, a6, a7, a8)) +# define vtkTemplateMacro9(func, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + vtkTemplateMacro(func (a1, a2, a3, a4, a5, a6, a7, a8, a9)) +# define vtkTemplateMacro10(func,a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + vtkTemplateMacro(func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)) +// These are legacy macros, do not add anymore. Use vtkTemplateMacro instead +#endif + +// Old-style legacy code marker macro. +#if !defined(VTK_LEGACY_REMOVE) && !defined(VTK_LEAN_AND_MEAN) +#define VTK_LEGACY_METHOD(oldMethod,versionStringMadeLegacy) \ + vtkErrorMacro(<< #oldMethod \ + << " was obsoleted for version " << #versionStringMadeLegacy \ + << " and will be removed in a future version"); +#else +#define VTK_LEGACY_METHOD(oldMethod,versionStringMadeLegacy) +#endif + +//---------------------------------------------------------------------------- +// Setup legacy code policy. + +// Define VTK_LEGACY macro to mark legacy methods where they are +// declared in their class. Example usage: +// +// // @deprecated Replaced by MyOtherMethod() as of VTK 5.0. +// VTK_LEGACY(void MyMethod()); +#if defined(VTK_LEGACY_REMOVE) + // Remove legacy methods completely. Put a bogus declaration in + // place to avoid stray semicolons because this is an error for some + // compilers. Using a class forward declaration allows any number + // of repeats in any context without generating unique names. +# define VTK_LEGACY(method) class vtkLegacyMethodRemoved +#elif defined(VTK_LEGACY_SILENT) || defined(VTK_WRAPPING_CXX) + // Provide legacy methods with no warnings. +# define VTK_LEGACY(method) method +#else + // Setup compile-time warnings for uses of deprecated methods if + // possible on this compiler. +# if defined(__GNUC__) && !defined(__INTEL_COMPILER) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define VTK_LEGACY(method) method __attribute__((deprecated)) +# elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define VTK_LEGACY(method) __declspec(deprecated) method +# else +# define VTK_LEGACY(method) method +# endif +#endif + +// Macros to create runtime deprecation warning messages in function +// bodies. Example usage: +// +// void vtkMyClass::MyOldMethod() +// { +// VTK_LEGACY_BODY(vtkMyClass::MyOldMethod, "VTK 5.0"); +// } +// +// void vtkMyClass::MyMethod() +// { +// VTK_LEGACY_REPLACED_BODY(vtkMyClass::MyMethod, "VTK 5.0", +// vtkMyClass::MyOtherMethod); +// } +#if defined(VTK_LEGACY_REMOVE) || defined(VTK_LEGACY_SILENT) +# define VTK_LEGACY_BODY(method, version) +# define VTK_LEGACY_REPLACED_BODY(method, version, replace) +#else +# define VTK_LEGACY_BODY(method, version) \ + vtkGenericWarningMacro(#method " was deprecated for " version " and will be removed in a future version.") +# define VTK_LEGACY_REPLACED_BODY(method, version, replace) \ + vtkGenericWarningMacro(#method " was deprecated for " version " and will be removed in a future version. Use " #replace " instead.") +#endif + +#endif diff --git a/Common/vtkShortArray.cxx b/Common/vtkShortArray.cxx new file mode 100644 index 0000000..5e7a182 --- /dev/null +++ b/Common/vtkShortArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShortArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(short); + +#define __vtkShortArray_cxx +#include "vtkShortArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkShortArray, "$Revision: 1.54 $"); +vtkStandardNewMacro(vtkShortArray); + +//---------------------------------------------------------------------------- +vtkShortArray::vtkShortArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkShortArray::~vtkShortArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkShortArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkShortArray.h b/Common/vtkShortArray.h new file mode 100644 index 0000000..b00e6a5 --- /dev/null +++ b/Common/vtkShortArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShortArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkShortArray - dynamic, self-adjusting array of short +// .SECTION Description +// vtkShortArray is an array of values of type short. It provides +// methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkShortArray_h +#define __vtkShortArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkShortArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE short +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkShortArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkShortArray* New(); + vtkTypeRevisionMacro(vtkShortArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_SHORT; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, short* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const short* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const short* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const short* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + short GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, short value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, short f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(short f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + short* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + short* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(short* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkShortArray(vtkIdType numComp=1); + ~vtkShortArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkShortArray(const vtkShortArray&); // Not implemented. + void operator=(const vtkShortArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkSignedCharArray.cxx b/Common/vtkSignedCharArray.cxx new file mode 100644 index 0000000..1be8edb --- /dev/null +++ b/Common/vtkSignedCharArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSignedCharArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(signed char); + +#define __vtkSignedCharArray_cxx +#include "vtkSignedCharArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkSignedCharArray, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkSignedCharArray); + +//---------------------------------------------------------------------------- +vtkSignedCharArray::vtkSignedCharArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkSignedCharArray::~vtkSignedCharArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkSignedCharArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkSignedCharArray.h b/Common/vtkSignedCharArray.h new file mode 100644 index 0000000..4d1b22e --- /dev/null +++ b/Common/vtkSignedCharArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSignedCharArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSignedCharArray - dynamic, self-adjusting array of signed char +// .SECTION Description +// vtkSignedCharArray is an array of values of type signed char. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkSignedCharArray_h +#define __vtkSignedCharArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkSignedCharArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE signed char +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkSignedCharArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkSignedCharArray* New(); + vtkTypeRevisionMacro(vtkSignedCharArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_SIGNED_CHAR; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, signed char* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const signed char* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const signed char* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const signed char* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + signed char GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, signed char value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, signed char f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(signed char f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + signed char* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + signed char* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(signed char* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkSignedCharArray(vtkIdType numComp=1); + ~vtkSignedCharArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkSignedCharArray(const vtkSignedCharArray&); // Not implemented. + void operator=(const vtkSignedCharArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkSmartPointer.h b/Common/vtkSmartPointer.h new file mode 100644 index 0000000..6241c2c --- /dev/null +++ b/Common/vtkSmartPointer.h @@ -0,0 +1,203 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSmartPointer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSmartPointer - Hold a reference to a vtkObjectBase instance. +// .SECTION Description +// vtkSmartPointer is a class template that provides automatic casting +// for objects held by the vtkSmartPointerBase superclass. + +#ifndef __vtkSmartPointer_h +#define __vtkSmartPointer_h + +#include "vtkSmartPointerBase.h" + +template +class vtkSmartPointer: public vtkSmartPointerBase +{ +public: + // Description: + // Initialize smart pointer to NULL. + vtkSmartPointer() {} + + // Description: + // Initialize smart pointer to given object. + vtkSmartPointer(T* r): vtkSmartPointerBase(r) {} + + // Description: + // Initialize smart pointer with a new reference to the same object + // referenced by given smart pointer. + vtkSmartPointer(const vtkSmartPointerBase& r): vtkSmartPointerBase(r) {} + + // Description: + // Assign object to reference. This removes any reference to an old + // object. + vtkSmartPointer& operator=(T* r) + { + this->vtkSmartPointerBase::operator=(r); + return *this; + } + + // Description: + // Assign object to reference. This removes any reference to an old + // object. + vtkSmartPointer& operator=(const vtkSmartPointerBase& r) + { + this->vtkSmartPointerBase::operator=(r); + return *this; + } + + // Description: + // Get the contained pointer. + T* GetPointer() const + { + return static_cast(this->Object); + } + + // Description: + // Get the contained pointer. + operator T* () const + { + return static_cast(this->Object); + } + + // Description: + // Dereference the pointer and return a reference to the contained + // object. + T& operator*() const + { + return *static_cast(this->Object); + } + + // Description: + // Provides normal pointer target member access using operator ->. + T* operator->() const + { + return static_cast(this->Object); + } + + // Description: + // Transfer ownership of one reference to the given VTK object to + // this smart pointer. This does not increment the reference count + // of the object, but will decrement it later. The caller is + // effectively passing ownership of one reference to the smart + // pointer. This is useful for code like: + // + // vtkSmartPointer foo; + // foo.TakeReference(bar->NewFoo()); + // + // The input argument may not be another smart pointer. + void TakeReference(T* t) + { + *this = vtkSmartPointer(t, NoReference()); + } + + // Description: + // Create an instance of a VTK object. + static vtkSmartPointer New() + { + return vtkSmartPointer(T::New(), NoReference()); + } + + // Description: + // Create a new instance of the given VTK object. + static vtkSmartPointer NewInstance(T* t) + { + return vtkSmartPointer(t->NewInstance(), NoReference()); + } + + // Description: + // Transfer ownership of one reference to the given VTK object to a + // new smart pointer. The returned smart pointer does not increment + // the reference count of the object on construction but will + // decrement it on destruction. The caller is effectively passing + // ownership of one reference to the smart pointer. This is useful + // for code like: + // + // vtkSmartPointer foo = + // vtkSmartPointer::Take(bar->NewFoo()); + // + // The input argument may not be another smart pointer. + static vtkSmartPointer Take(T* t) + { + return vtkSmartPointer(t, NoReference()); + } + + // Work-around for HP overload resolution bug. Since + // NullPointerOnly is a private type the only pointer value that can + // be passed by user code is a null pointer. This operator will be + // chosen by the compiler when comparing against null explicitly and + // avoid the bogus ambiguous overload error. +#if defined(__HP_aCC) +# define VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(op) \ + vtkstd_bool operator op (NullPointerOnly*) const \ + { \ + return ::operator op (*this, 0); \ + } +private: + class NullPointerOnly {}; +public: + VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(==) + VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(!=) + VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(<) + VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(<=) + VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(>) + VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND(>=) +# undef VTK_SMART_POINTER_DEFINE_OPERATOR_WORKAROUND +#endif +protected: + vtkSmartPointer(T* r, const NoReference& n): vtkSmartPointerBase(r, n) {} +private: + // These are purposely not implemented to prevent callers from + // trying to take references from other smart pointers. + void TakeReference(const vtkSmartPointerBase&); // Not implemented. + static void Take(const vtkSmartPointerBase&); // Not implemented. +}; + +#define VTK_SMART_POINTER_DEFINE_OPERATOR(op) \ + template \ + inline vtkstd_bool \ + operator op (const vtkSmartPointer& l, const vtkSmartPointer& r) \ + { \ + return (l.GetPointer() op r.GetPointer()); \ + } \ + template \ + inline vtkstd_bool operator op (T* l, const vtkSmartPointer& r) \ + { \ + return (l op r.GetPointer()); \ + } \ + template \ + inline vtkstd_bool operator op (const vtkSmartPointer& l, T* r) \ + { \ + return (l.GetPointer() op r); \ + } +// Description: +// Compare smart pointer values. +VTK_SMART_POINTER_DEFINE_OPERATOR(==) +VTK_SMART_POINTER_DEFINE_OPERATOR(!=) +VTK_SMART_POINTER_DEFINE_OPERATOR(<) +VTK_SMART_POINTER_DEFINE_OPERATOR(<=) +VTK_SMART_POINTER_DEFINE_OPERATOR(>) +VTK_SMART_POINTER_DEFINE_OPERATOR(>=) + +#undef VTK_SMART_POINTER_DEFINE_OPERATOR + +// Description: +// Streaming operator to print smart pointer like regular pointers. +template +inline ostream& operator << (ostream& os, const vtkSmartPointer& p) +{ + return os << static_cast(p); +} + +#endif diff --git a/Common/vtkSmartPointerBase.cxx b/Common/vtkSmartPointerBase.cxx new file mode 100644 index 0000000..1e39cf8 --- /dev/null +++ b/Common/vtkSmartPointerBase.cxx @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSmartPointerBase.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSmartPointerBase.h" + +#include "vtkGarbageCollector.h" + +//---------------------------------------------------------------------------- +vtkSmartPointerBase::vtkSmartPointerBase(): + Object(0) +{ + // Add a reference to the object. + this->Register(); +} + +//---------------------------------------------------------------------------- +vtkSmartPointerBase::vtkSmartPointerBase(vtkObjectBase* r): + Object(r) +{ + // Add a reference to the object. + this->Register(); +} + +//---------------------------------------------------------------------------- +vtkSmartPointerBase::vtkSmartPointerBase(vtkObjectBase* r, const NoReference&): + Object(r) +{ + // Do not add a reference to the object because we received the + // NoReference argument. +} + +//---------------------------------------------------------------------------- +vtkSmartPointerBase::vtkSmartPointerBase(const vtkSmartPointerBase& r): + Object(r.Object) +{ + // Add a reference to the object. + this->Register(); +} + +//---------------------------------------------------------------------------- +vtkSmartPointerBase::~vtkSmartPointerBase() +{ + // The main pointer must be set to NULL before calling UnRegister, + // so use a local variable to save the pointer. This is because the + // garbage collection reference graph traversal may make it back to + // this smart pointer, and we do not want to include this reference. + vtkObjectBase* object = this->Object; + if(object) + { + this->Object = 0; + object->UnRegister(0); + } +} + +//---------------------------------------------------------------------------- +vtkSmartPointerBase& +vtkSmartPointerBase::operator=(vtkObjectBase* r) +{ + // This is an exception-safe assignment idiom that also gives the + // correct order of register/unregister calls to all objects + // involved. A temporary is constructed that references the new + // object. Then the main pointer and temporary are swapped and the + // temporary's destructor unreferences the old object. + vtkSmartPointerBase(r).Swap(*this); + return *this; +} + +//---------------------------------------------------------------------------- +vtkSmartPointerBase& +vtkSmartPointerBase::operator=(const vtkSmartPointerBase& r) +{ + // This is an exception-safe assignment idiom that also gives the + // correct order of register/unregister calls to all objects + // involved. A temporary is constructed that references the new + // object. Then the main pointer and temporary are swapped and the + // temporary's destructor unreferences the old object. + vtkSmartPointerBase(r).Swap(*this); + return *this; +} + +//---------------------------------------------------------------------------- +void vtkSmartPointerBase::Report(vtkGarbageCollector* collector, + const char* desc) +{ + vtkGarbageCollectorReport(collector, this->Object, desc); +} + +//---------------------------------------------------------------------------- +void vtkSmartPointerBase::Swap(vtkSmartPointerBase& r) +{ + // Just swap the pointers. This is used internally by the + // assignment operator. + vtkObjectBase* temp = r.Object; + r.Object = this->Object; + this->Object = temp; +} + +//---------------------------------------------------------------------------- +void vtkSmartPointerBase::Register() +{ + // Add a reference only if the object is not NULL. + if(this->Object) + { + this->Object->Register(0); + } +} + +//---------------------------------------------------------------------------- +ostream& operator << (ostream& os, const vtkSmartPointerBase& p) +{ + // Just print the pointer value into the stream. + return os << static_cast(p.GetPointer()); +} diff --git a/Common/vtkSmartPointerBase.h b/Common/vtkSmartPointerBase.h new file mode 100644 index 0000000..a98a07b --- /dev/null +++ b/Common/vtkSmartPointerBase.h @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSmartPointerBase.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSmartPointerBase - Non-templated superclass for vtkSmartPointer. +// .SECTION Description +// vtkSmartPointerBase holds a pointer to a vtkObjectBase or subclass +// instance and performs one Register/UnRegister pair. This is useful +// for storing VTK objects in STL containers. This class is not +// intended to be used directly. Instead, use the vtkSmartPointer +// class template to automatically perform proper cast operations. + +#ifndef __vtkSmartPointerBase_h +#define __vtkSmartPointerBase_h + +#include "vtkObjectBase.h" + +class VTK_COMMON_EXPORT vtkSmartPointerBase +{ +public: + // Description: + // Initialize smart pointer to NULL. + vtkSmartPointerBase(); + + // Description: + // Initialize smart pointer to given object. + vtkSmartPointerBase(vtkObjectBase* r); + + // Description: + // Initialize smart pointer with a new reference to the same object + // referenced by given smart pointer. + vtkSmartPointerBase(const vtkSmartPointerBase& r); + + // Description: + // Destroy smart pointer and remove the reference to its object. + ~vtkSmartPointerBase(); + + // Description: + // Assign object to reference. This removes any reference to an old + // object. + vtkSmartPointerBase& operator=(vtkObjectBase* r); + vtkSmartPointerBase& operator=(const vtkSmartPointerBase& r); + + // Description: + // Get the contained pointer. + vtkObjectBase* GetPointer() const + { + // Inline implementation so smart pointer comparisons can be fully + // inlined. + return this->Object; + } + + // Description: + // Report the reference held by the smart pointer to a collector. + void Report(vtkGarbageCollector* collector, const char* desc); + +protected: + + // Initialize smart pointer to given object, but do not increment + // reference count. The destructor will still decrement the count. + // This effectively makes it an auto-ptr. + class NoReference {}; + vtkSmartPointerBase(vtkObjectBase* r, const NoReference&); + + // Pointer to the actual object. + vtkObjectBase* Object; + +private: + // Internal utility methods. + void Swap(vtkSmartPointerBase& r); + void Register(); +}; + +//---------------------------------------------------------------------------- +// Need to use vtkstd_bool type because std: :less requires bool return +// type from operators. This example should not be used to justify +// using bool elsewhere in VTK. + +#define VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(op) \ + inline vtkstd_bool \ + operator op (const vtkSmartPointerBase& l, const vtkSmartPointerBase& r) \ + { \ + return (static_cast(l.GetPointer()) op \ + static_cast(r.GetPointer())); \ + } \ + inline vtkstd_bool \ + operator op (vtkObjectBase* l, const vtkSmartPointerBase& r) \ + { \ + return (static_cast(l) op static_cast(r.GetPointer())); \ + } \ + inline vtkstd_bool \ + operator op (const vtkSmartPointerBase& l, vtkObjectBase* r) \ + { \ + return (static_cast(l.GetPointer()) op static_cast(r)); \ + } +// Description: +// Compare smart pointer values. +VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(==) +VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(!=) +VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(<) +VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(<=) +VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(>) +VTK_SMART_POINTER_BASE_DEFINE_OPERATOR(>=) + +#undef VTK_SMART_POINTER_BASE_DEFINE_OPERATOR + +// Description: +// Streaming operator to print smart pointer like regular pointers. +VTK_COMMON_EXPORT ostream& operator << (ostream& os, + const vtkSmartPointerBase& p); + +#endif diff --git a/Common/vtkSphericalTransform.cxx b/Common/vtkSphericalTransform.cxx new file mode 100644 index 0000000..8d9427b --- /dev/null +++ b/Common/vtkSphericalTransform.cxx @@ -0,0 +1,175 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphericalTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSphericalTransform.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include +#include + +vtkCxxRevisionMacro(vtkSphericalTransform, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkSphericalTransform); + +//---------------------------------------------------------------------------- +vtkSphericalTransform::vtkSphericalTransform() +{ +} + +vtkSphericalTransform::~vtkSphericalTransform() +{ +} + +void vtkSphericalTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkWarpTransform::PrintSelf(os,indent); +} + +void vtkSphericalTransform::InternalDeepCopy(vtkAbstractTransform *transform) +{ + vtkSphericalTransform *sphericalTransform = + (vtkSphericalTransform *)transform; + + // copy these even though they aren't used + this->SetInverseTolerance(sphericalTransform->InverseTolerance); + this->SetInverseIterations(sphericalTransform->InverseIterations); + + // copy the inverse flag, which is used + if (this->InverseFlag != sphericalTransform->InverseFlag) + { + this->InverseFlag = sphericalTransform->InverseFlag; + this->Modified(); + } +} + +vtkAbstractTransform *vtkSphericalTransform::MakeTransform() +{ + return vtkSphericalTransform::New(); +} + +template +void vtkSphericalToRectangular(const T inPoint[3], T outPoint[3], + T derivative[3][3]) +{ + T r = inPoint[0]; + T sinphi = sin(inPoint[1]); + T cosphi = cos(inPoint[1]); + T sintheta = sin(inPoint[2]); + T costheta = cos(inPoint[2]); + + outPoint[0] = r*sinphi*costheta; + outPoint[1] = r*sinphi*sintheta; + outPoint[2] = r*cosphi; + + if (derivative) + { + derivative[0][0] = sinphi*costheta; + derivative[0][1] = r*cosphi*costheta; + derivative[0][2] = -r*sinphi*sintheta; + + derivative[1][0] = sinphi*sintheta; + derivative[1][1] = r*cosphi*sintheta; + derivative[1][2] = r*sinphi*costheta; + + derivative[2][0] = cosphi; + derivative[2][1] = -r*sinphi; + derivative[2][2] = 0; + } +} + +template +void vtkRectangularToSpherical(const T inPoint[3], T outPoint[3]) +{ + T x = inPoint[0]; + T y = inPoint[1]; + T z = inPoint[2]; + + T RR = x*x + y*y; + T r = sqrt(RR + z*z); + + outPoint[0] = r; + if (r == 0) + { + outPoint[1] = 0; + } + else + { + outPoint[1] = acos(z/r); + } + if (RR == 0) + { + outPoint[2] = 0; + } + else + { + // Change range to [0, 2*Pi], otherwise the same as atan2(y, x) + outPoint[2] = vtkMath::Pi() + atan2(-y, -x); + } +} + +void vtkSphericalTransform::ForwardTransformPoint(const float inPoint[3], + float outPoint[3]) +{ + vtkSphericalToRectangular(inPoint, outPoint, (float (*)[3])0); +} + +void vtkSphericalTransform::ForwardTransformPoint(const double inPoint[3], + double outPoint[3]) +{ + vtkSphericalToRectangular(inPoint, outPoint, (double (*)[3])0); +} + +void vtkSphericalTransform::ForwardTransformDerivative(const float inPoint[3], + float outPoint[3], + float derivative[3][3]) +{ + vtkSphericalToRectangular(inPoint, outPoint, derivative); +} + +void vtkSphericalTransform::ForwardTransformDerivative(const double inPoint[3], + double outPoint[3], + double derivative[3][3]) +{ + vtkSphericalToRectangular(inPoint, outPoint, derivative); +} + +void vtkSphericalTransform::InverseTransformPoint(const float inPoint[3], + float outPoint[3]) +{ + vtkRectangularToSpherical(inPoint, outPoint); +} + +void vtkSphericalTransform::InverseTransformPoint(const double inPoint[3], + double outPoint[3]) +{ + vtkRectangularToSpherical(inPoint, outPoint); +} + +void vtkSphericalTransform::InverseTransformDerivative(const float inPoint[3], + float outPoint[3], + float derivative[3][3]) +{ + float tmp[3]; + vtkRectangularToSpherical(inPoint, outPoint); + vtkSphericalToRectangular(outPoint, tmp, derivative); +} + +void vtkSphericalTransform::InverseTransformDerivative(const double inPoint[3], + double outPoint[3], + double derivative[3][3]) +{ + double tmp[3]; + vtkRectangularToSpherical(inPoint, outPoint); + vtkSphericalToRectangular(outPoint, tmp, derivative); +} + diff --git a/Common/vtkSphericalTransform.h b/Common/vtkSphericalTransform.h new file mode 100644 index 0000000..2523b42 --- /dev/null +++ b/Common/vtkSphericalTransform.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphericalTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSphericalTransform - spherical to rectangular coords and back +// .SECTION Description +// vtkSphericalTransform will convert (r,phi,theta) coordinates to +// (x,y,z) coordinates and back again. The angles are given in radians. +// By default, it converts cylindrical coordinates to rectangular, but +// GetInverse() returns a transform that will do the opposite. The equation +// that is used is x = r*sin(phi)*cos(theta), y = r*sin(phi)*sin(theta), +// z = r*cos(phi). +// .SECTION Caveats +// This transform is not well behaved along the line x=y=0 (i.e. along +// the z-axis) +// .SECTION see also +// vtkCylindricalTransform vtkGeneralTransform + +#ifndef __vtkSphericalTransform_h +#define __vtkSphericalTransform_h + +#include "vtkWarpTransform.h" + +class VTK_COMMON_EXPORT vtkSphericalTransform : public vtkWarpTransform +{ +public: + static vtkSphericalTransform *New(); + vtkTypeRevisionMacro(vtkSphericalTransform,vtkWarpTransform); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Make another transform of the same type. + vtkAbstractTransform *MakeTransform(); + +protected: + vtkSphericalTransform(); + ~vtkSphericalTransform(); + + // Description: + // Copy this transform from another of the same type. + void InternalDeepCopy(vtkAbstractTransform *transform); + + // Description: + // Internal functions for calculating the transformation. + void ForwardTransformPoint(const float in[3], float out[3]); + void ForwardTransformPoint(const double in[3], double out[3]); + + void ForwardTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void ForwardTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + void InverseTransformPoint(const float in[3], float out[3]); + void InverseTransformPoint(const double in[3], double out[3]); + + void InverseTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InverseTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + +private: + vtkSphericalTransform(const vtkSphericalTransform&); // Not implemented. + void operator=(const vtkSphericalTransform&); // Not implemented. +}; + +#endif + diff --git a/Common/vtkStdString.cxx b/Common/vtkStdString.cxx new file mode 100644 index 0000000..1e3413d --- /dev/null +++ b/Common/vtkStdString.cxx @@ -0,0 +1,21 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStdString.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStdString.h" + +//---------------------------------------------------------------------------- +ostream& operator<<(ostream& os, const vtkStdString& s) +{ + return os << s.c_str(); +} diff --git a/Common/vtkStdString.h b/Common/vtkStdString.h new file mode 100644 index 0000000..4308b27 --- /dev/null +++ b/Common/vtkStdString.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStdString.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStdString - Wrapper around vtkstd::string to keep symbols short. +// .SECTION Description +// vtkStdString derives from vtkstd::string to provide shorter symbol +// names than basic_string<...> in namespace std given by the standard +// STL string. + +#ifndef __vtkStdString_h +#define __vtkStdString_h + +#include "vtkSystemIncludes.h" // For VTK_COMMON_EXPORT. +#include // For the superclass. + +class vtkStdString; +VTK_COMMON_EXPORT ostream& operator<<(ostream&, const vtkStdString&); + +class vtkStdString : public vtkstd::string +{ +public: + typedef vtkstd::string StdString; + typedef StdString::value_type value_type; + typedef StdString::pointer pointer; + typedef StdString::reference reference; + typedef StdString::const_reference const_reference; + typedef StdString::size_type size_type; + typedef StdString::difference_type difference_type; + typedef StdString::iterator iterator; + typedef StdString::const_iterator const_iterator; + typedef StdString::reverse_iterator reverse_iterator; + typedef StdString::const_reverse_iterator const_reverse_iterator; + + vtkStdString(): StdString() {} + vtkStdString(const value_type* s): StdString(s) {} + vtkStdString(const value_type* s, size_type n): StdString(s, n) {} + vtkStdString(const StdString& s, size_type pos=0, size_type n=npos): + StdString(s, pos, n) {} + + operator const char *() { return this->c_str(); }; + +}; + +#endif diff --git a/Common/vtkStringArray.cxx b/Common/vtkStringArray.cxx new file mode 100644 index 0000000..5845c21 --- /dev/null +++ b/Common/vtkStringArray.cxx @@ -0,0 +1,557 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStringArray.cxx,v $ + Language: C++ + Date: $Date: 2006/01/09 21:48:01 $ + Version: $Revision: 1.4.6.2 $ + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + + + +// We do not provide a definition for the copy constructor or +// operator=. Block the warning. +#ifdef _MSC_VER +# pragma warning (disable: 4661) +#endif + +#include + +#include "vtkStringArray.h" +#include "vtkStdString.h" + +#include "vtkCharArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" + +vtkCxxRevisionMacro(vtkStringArray, "$Revision: 1.4.6.2 $"); +vtkStandardNewMacro(vtkStringArray); + +//---------------------------------------------------------------------------- + +vtkStringArray::vtkStringArray(vtkIdType numComp) : + vtkAbstractArray( numComp ) +{ + this->Array = NULL; + this->SaveUserArray = 0; +} + +//---------------------------------------------------------------------------- + +vtkStringArray::~vtkStringArray() +{ + if ((this->Array) && (!this->SaveUserArray)) + { + delete [] this->Array; + } +} + +//---------------------------------------------------------------------------- +// This method lets the user specify data to be held by the array. The +// array argument is a pointer to the data. size is the size of +// the array supplied by the user. Set save to 1 to keep the class +// from deleting the array when it cleans up or reallocates memory. +// The class uses the actual array provided; it does not copy the data +// from the suppled array. + +void vtkStringArray::SetArray(vtkStdString *array, vtkIdType size, int save) +{ + if ((this->Array) && (!this->SaveUserArray)) + { + vtkDebugMacro (<< "Deleting the array..."); + delete [] this->Array; + } + else + { + vtkDebugMacro (<<"Warning, array not deleted, but will point to new array."); + } + + vtkDebugMacro(<<"Setting array to: " << array); + + this->Array = array; + this->Size = size; + this->MaxId = size-1; + this->SaveUserArray = save; +} + +//---------------------------------------------------------------------------- +// Allocate memory for this array. Delete old storage only if necessary. + +int vtkStringArray::Allocate(vtkIdType sz, vtkIdType) +{ + if(sz > this->Size) + { + if(this->Array && !this->SaveUserArray) + { + delete [] this->Array; + } + + this->Size = ( sz > 0 ? sz : 1); + this->Array = new vtkStdString[this->Size]; + if(!this->Array) + { + return 0; + } + this->SaveUserArray = 0; + } + + this->MaxId = -1; + + return 1; +} + +//---------------------------------------------------------------------------- +// Release storage and reset array to initial state. + +void vtkStringArray::Initialize() +{ + if(this->Array && !this->SaveUserArray) + { + delete [] this->Array; + } + this->Array = 0; + this->Size = 0; + this->MaxId = -1; + this->SaveUserArray = 0; +} + +//---------------------------------------------------------------------------- +// Deep copy of another string array. + +void vtkStringArray::DeepCopy(vtkAbstractArray* aa) +{ + // Do nothing on a NULL input. + if(!aa) + { + return; + } + + // Avoid self-copy. + if(this == aa) + { + return; + } + + // If data type does not match, we can't copy. + if(aa->GetDataType() != this->GetDataType()) + { + vtkErrorMacro(<< "Incompatible types: tried to copy an array of type " + << aa->GetDataTypeAsString() + << " into a string array "); + return; + } + + vtkStringArray *fa = vtkStringArray::SafeDownCast( aa ); + if ( fa == NULL ) + { + vtkErrorMacro(<< "Shouldn't Happen: Couldn't downcast array into a vtkStringArray." ); + return; + } + + // Free our previous memory. + if(this->Array && !this->SaveUserArray) + { + delete [] this->Array; + } + + // Copy the given array into new memory. + this->MaxId = fa->GetMaxId(); + this->Size = fa->GetSize(); + this->SaveUserArray = 0; + this->Array = new vtkStdString[this->Size]; + + for (int i = 0; i < this->Size; ++i) + { + this->Array[i] = fa->Array[i]; + } +} + +//---------------------------------------------------------------------------- + +void vtkStringArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if(this->Array) + { + os << indent << "Array: " << this->Array << "\n"; + } + else + { + os << indent << "Array: (null)\n"; + } +} + +//---------------------------------------------------------------------------- +// Protected function does "reallocate" + +vtkStdString * vtkStringArray::ResizeAndExtend(vtkIdType sz) +{ + vtkStdString * newArray; + vtkIdType newSize; + + if(sz > this->Size) + { + // Requested size is bigger than current size. Allocate enough + // memory to fit the requested size and be more than double the + // currently allocated memory. + newSize = this->Size + sz; + } + else if (sz == this->Size) + { + // Requested size is equal to current size. Do nothing. + return this->Array; + } + else + { + // Requested size is smaller than current size. Squeeze the + // memory. + newSize = sz; + } + + if(newSize <= 0) + { + this->Initialize(); + return 0; + } + + newArray = new vtkStdString[newSize]; + if(!newArray) + { + vtkErrorMacro("Cannot allocate memory\n"); + return 0; + } + + if(this->Array) + { + // can't use memcpy here + int numCopy = (newSize < this->Size ? newSize : this->Size); + for (int i = 0; i < numCopy; ++i) + { + newArray[i] = this->Array[i]; + } + if(!this->SaveUserArray) + { + delete [] this->Array; + } + } + + if(newSize < this->Size) + { + this->MaxId = newSize-1; + } + this->Size = newSize; + this->Array = newArray; + this->SaveUserArray = 0; + + return this->Array; +} + +//---------------------------------------------------------------------------- + +int vtkStringArray::Resize(vtkIdType sz) +{ + vtkStdString * newArray; + vtkIdType newSize = sz; + + if(newSize == this->Size) + { + return 1; + } + + if(newSize <= 0) + { + this->Initialize(); + return 1; + } + + newArray = new vtkStdString[newSize]; + if(!newArray) + { + vtkErrorMacro(<< "Cannot allocate memory\n"); + return 0; + } + + if(this->Array) + { + int numCopy = (newSize < this->Size ? newSize : this->Size); + + for (int i = 0; i < numCopy; ++i) + { + newArray[i] = this->Array[i]; + } + + if(!this->SaveUserArray) + { + delete[] this->Array; + } + } + + if(newSize < this->Size) + { + this->MaxId = newSize-1; + } + this->Size = newSize; + this->Array = newArray; + this->SaveUserArray = 0; + return 1; +} + + +//---------------------------------------------------------------------------- + +void vtkStringArray::SetNumberOfValues(vtkIdType number) +{ + this->Allocate(number); + this->MaxId = number - 1; +} + +//---------------------------------------------------------------------------- + +vtkStdString * vtkStringArray::WritePointer(vtkIdType id, + vtkIdType number) +{ + vtkIdType newSize=id+number; + if ( newSize > this->Size ) + { + this->ResizeAndExtend(newSize); + } + if ( (--newSize) > this->MaxId ) + { + this->MaxId = newSize; + } + return this->Array + id; +} + +//---------------------------------------------------------------------------- + +void vtkStringArray::InsertValue(vtkIdType id, vtkStdString f) +{ + if ( id >= this->Size ) + { + this->ResizeAndExtend(id+1); + } + this->Array[id] = f; + if ( id > this->MaxId ) + { + this->MaxId = id; + } +} + +//---------------------------------------------------------------------------- + +vtkIdType vtkStringArray::InsertNextValue(vtkStdString f) +{ + this->InsertValue (++this->MaxId,f); + return this->MaxId; +} + +// ---------------------------------------------------------------------- + +int +vtkStringArray::GetDataTypeSize( void ) +{ return static_cast(sizeof(vtkStdString)); } + + +// ---------------------------------------------------------------------- + +unsigned long +vtkStringArray::GetActualMemorySize( void ) +{ + unsigned long totalSize = 0; + unsigned long numPrims = this->GetSize(); + + for (unsigned long i = 0; i < numPrims; ++i) + { + totalSize += sizeof( vtkStdString ); + totalSize += this->Array[i].size() * sizeof( vtkStdString::value_type ); + } + + return (unsigned long) ceil( totalSize / 1000.0 ); // kilobytes +} + +// ---------------------------------------------------------------------- + +vtkStdString & +vtkStringArray::GetValue( vtkIdType id ) +{ + return this->Array[id]; +} + +// ---------------------------------------------------------------------- + +void +vtkStringArray::GetValues(vtkIdList *indices, vtkAbstractArray *aa) +{ + if (aa == NULL) + { + vtkErrorMacro(<<"GetValues: Output array is null!"); + return; + } + + vtkStringArray *output = vtkStringArray::SafeDownCast(aa); + + if (output == NULL) + { + vtkErrorMacro(<< "Can't copy values from a string array into an array " + << "of type " << aa->GetDataTypeAsString()); + return; + } + + for (vtkIdType i = 0; i < indices->GetNumberOfIds(); ++i) + { + vtkIdType index = indices->GetId(i); + output->SetValue(i, this->GetValue(index)); + } +} + +// ---------------------------------------------------------------------- + +void +vtkStringArray::GetValues(vtkIdType startIndex, + vtkIdType endIndex, + vtkAbstractArray *aa) +{ + if (aa == NULL) + { + vtkErrorMacro(<<"GetValues: Output array is null!"); + return; + } + + vtkStringArray *output = vtkStringArray::SafeDownCast(aa); + + if (output == NULL) + { + vtkErrorMacro(<< "Can't copy values from a string array into an array " + << "of type " << aa->GetDataTypeAsString()); + return; + } + + for (vtkIdType i = 0; i < (endIndex - startIndex) + 1; ++i) + { + vtkIdType index = startIndex + i; + output->SetValue(i, this->GetValue(index)); + } +} + + +// ---------------------------------------------------------------------- + +void +vtkStringArray::CopyValue(int toIndex, int fromIndex, + vtkAbstractArray *source) +{ + if (source == NULL) + { + vtkErrorMacro(<<"CopyValue: Input array is null!"); + return; + } + + vtkStringArray *realSource = vtkStringArray::SafeDownCast(source); + + if (realSource == NULL) + { + vtkErrorMacro(<< "Can't copy values from an array of type " + << source->GetDataTypeAsString() + << " into a string array!"); + return; + } + + this->SetValue(toIndex, realSource->GetValue(fromIndex)); +} + +// ---------------------------------------------------------------------- + +void +vtkStringArray::ConvertToContiguous(vtkDataArray **Data, + vtkIdTypeArray **Offsets) +{ + vtkCharArray *data = vtkCharArray::New(); + vtkIdTypeArray *offsets = vtkIdTypeArray::New(); + int currentPosition = 0; + + for (vtkIdType i = 0; i < this->GetNumberOfValues(); ++i) + { + vtkStdString thisString = this->Array[i]; + for (vtkStdString::size_type j = 0; j < this->Array[i].length(); ++j) + { + data->InsertNextValue(thisString[j]); + ++currentPosition; + } + offsets->InsertNextValue(currentPosition); + } + + *Data = data; + *Offsets = offsets; +} + +// ---------------------------------------------------------------------- + +// This will work with any sort of data array, but if you call it with +// anything other than a char array you might get strange results. +// You have been warned... + +void +vtkStringArray::ConvertFromContiguous(vtkDataArray *Data, + vtkIdTypeArray *Offsets) +{ + this->Reset(); + + vtkIdType currentStringStart = 0; + + for (vtkIdType i = 0; i < Offsets->GetNumberOfTuples(); ++i) + { + // YOU ARE HERE + vtkStdString newString; + vtkIdType stringEnd = Offsets->GetValue(i); + + for (vtkIdType here = currentStringStart; + here < stringEnd; + ++here) + { + newString += static_cast(Data->GetTuple1(here)); + } + this->InsertNextValue(newString); + currentStringStart = stringEnd; + } +} + + + +// ---------------------------------------------------------------------- + +// +// +// Below here are interface methods to allow values to be inserted as +// const char * instead of vtkStdString. Yes, they're trivial. The +// wrapper code needs them. +// +// + + +void +vtkStringArray::SetValue( vtkIdType id, const char *value ) +{ + this->SetValue( id, vtkStdString(value) ); +} + +void +vtkStringArray::InsertValue( vtkIdType id, const char *value ) +{ + this->InsertValue( id, vtkStdString( value ) ); +} + +vtkIdType +vtkStringArray::InsertNextValue( const char *value ) +{ + return this->InsertNextValue( vtkStdString( value ) ); +} + +// ---------------------------------------------------------------------- diff --git a/Common/vtkStringArray.h b/Common/vtkStringArray.h new file mode 100644 index 0000000..7c913ca --- /dev/null +++ b/Common/vtkStringArray.h @@ -0,0 +1,215 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStringArray.h,v $ + Language: C++ + Date: $Date: 2005/11/08 16:08:45 $ + Version: $Revision: 1.3.6.1 $ + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +// .NAME vtkStringArray - Subclass of vtkAbstractArray that holds vtkStdStrings +// +// .SECTION Description +// Points and cells may sometimes have associated data that are stored +// as strings, e.g. many information visualization projects. This +// class provides a reasonably clean way to store and access those. +// +// +// .SECTION Caveats +// +// Wrapping support for the Set/Get/Insert methods is a little +// strange. The Tcl/Python/Java wrappers treat vtkStdString as const +// char * right now instead of dealing with native strings. This is +// why there are two versions of every Set method: one (which you +// should use in C++ code) taking a vtkStdString argument and one +// (used by the wrapper) taking a const char * argument. +// +// If you'd like to look into modifying the wrappers to handle this +// properly, go right ahead... +// +// .SECTION Thanks +// Andy Wilson (atwilso@sandia.gov) wrote this class. + +#ifndef __vtkStringArray_h +#define __vtkStringArray_h + +#include "vtkAbstractArray.h" +#include "vtkStdString.h" // needed for vtkStdString definition + +class VTK_COMMON_EXPORT vtkStringArray : public vtkAbstractArray +{ +public: + static vtkStringArray* New(); + vtkTypeRevisionMacro(vtkStringArray,vtkAbstractArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // + // + // Functions required by vtkAbstractArray + // + // + + // Description: + // Get the data type. + int GetDataType() + { return VTK_STRING; } + + bool IsNumeric() { return false; } + + // Description: + // Release storage and reset array to initial state. + void Initialize(); + + // Description: + // Return the size of the data type. WARNING: This may not mean + // what you expect with strings. It will return + // sizeof(vtkstd::string) and not take into account the data + // included in any particular string. + int GetDataTypeSize(); + + // Description: + // Free any unnecessary memory. + // Resize object to just fit data requirement. Reclaims extra memory. + void Squeeze() { this->ResizeAndExtend (this->MaxId+1); } + + // Description: + // Resize the array while conserving the data. + int Resize(vtkIdType numTuples); + + // Description: + // Given a list of indices, return an array of values. You must + // insure that the output array has been previously allocated with + // enough space to hold the data and that the types match + // sufficiently to allow conversion (if necessary). + void GetValues(vtkIdList *ptIds, vtkAbstractArray *output); + + // Description: + // Get the values for the range of indices specified (i.e., + // p1->p2 inclusive). You must insure that the output array has been + // previously allocated with enough space to hold the data and that + // the type of the output array is compatible with the type of this + // array. + void GetValues(vtkIdType p1, vtkIdType p2, vtkAbstractArray *output); + + // Description: + // Copy a value from a given source array into this array. + void CopyValue(int toIndex, int fromIndex, vtkAbstractArray *sourceArray); + + // Description: + // Allocate memory for this array. Delete old storage only if necessary. + // Note that ext is no longer used. + int Allocate( vtkIdType sz, vtkIdType ext=1000 ); + + // Description: + // Get the data at a particular index. + vtkStdString &GetValue(vtkIdType id); + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. +//BTX + void SetValue(vtkIdType id, vtkStdString value) + { this->Array[id] = value; } +//ETX + void SetValue(vtkIdType id, const char *value); + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number); + + int GetNumberOfValues() { return this->MaxId + 1; } + + int GetNumberOfElementComponents() { return 0; } + int GetElementComponentSize() { return static_cast(sizeof(vtkStdString::value_type)); } + + // Description: + // Insert data at a specified position in the array. +//BTX + void InsertValue(vtkIdType id, vtkStdString f); +//ETX + void InsertValue(vtkIdType id, const char *val); + + // Description: + // Insert data at the end of the array. Return its location in the array. +//BTX + vtkIdType InsertNextValue(vtkStdString f); +//ETX + vtkIdType InsertNextValue(const char *f); + +//BTX + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + vtkStdString* WritePointer(vtkIdType id, vtkIdType number); +//ETX + +//BTX + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + vtkStdString* GetPointer(vtkIdType id) { return this->Array + id; } + void* GetVoidPointer(vtkIdType id) { return this->GetPointer(id); } +//BTX + + // Description: + // Deep copy of another string array. Will complain and change nothing + // if the array passed in is not a vtkStringArray. + void DeepCopy( vtkAbstractArray* aa ); + + +//BTX + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(vtkStdString* array, vtkIdType size, int save); + void SetVoidArray(void* array, vtkIdType size, int save) + { this->SetArray(static_cast(array), size, save); } +//ETX + + // Description: + // Return the memory in kilobytes consumed by this data array. Used to + // support streaming and reading/writing data. The value returned is + // guaranteed to be greater than or equal to the memory required to + // actually represent the data represented by this object. The + // information returned is valid only after the pipeline has + // been updated. + // + // This function takes into account the size of the contents of the + // strings as well as the string containers themselves. + unsigned long GetActualMemorySize(); + + void ConvertToContiguous(vtkDataArray **Data, vtkIdTypeArray **Offsets); + void ConvertFromContiguous(vtkDataArray *Data, vtkIdTypeArray *Offsets); + +protected: + vtkStringArray(vtkIdType numComp=1); + ~vtkStringArray(); + + vtkStdString* Array; // pointer to data + vtkStdString* ResizeAndExtend(vtkIdType sz); // function to resize data + + int SaveUserArray; + +private: + vtkStringArray(const vtkStringArray&); // Not implemented. + void operator=(const vtkStringArray&); // Not implemented. +}; + + + +#endif diff --git a/Common/vtkStructuredData.cxx b/Common/vtkStructuredData.cxx new file mode 100644 index 0000000..cf45cd3 --- /dev/null +++ b/Common/vtkStructuredData.cxx @@ -0,0 +1,446 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredData.h" + +#include "vtkIdList.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkStructuredData, "$Revision: 1.60 $"); + +// Return the topological dimension of the data (e.g., 0, 1, 2, or 3D). +int vtkStructuredData::GetDataDimension(int dataDescription) +{ + switch (dataDescription) + { + case VTK_EMPTY: return 0; // Should I put -1? + + case VTK_SINGLE_POINT: return 0; + + case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: return 1; + + case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: return 2; + + case VTK_XYZ_GRID: return 3; + + default: + return -1; + } +} + +// Specify the dimensions of a regular, rectangular dataset. The input is +// the new dimensions (inDim) and the current dimensions (dim). The function +// returns the dimension of the dataset (0-3D). If the dimensions are +// improperly specified a -1 is returned. If the dimensions are unchanged, a +// value of 100 is returned. +int vtkStructuredData::SetDimensions(int inDim[3], int dim[3]) +{ + int dataDim, i; + int dataDescription=VTK_UNCHANGED; + + + + if ( inDim[0] != dim[0] || inDim[1] != dim[1] || inDim[2] != dim[2] ) + { + for (dataDim=0, i=0; i<3 ; i++) + { + dim[i] = inDim[i]; + if (inDim[i] > 1) + { + dataDim++; + } + } + + if ( inDim[0]<1 || inDim[1]<1 || inDim[2]<1 ) + { + return VTK_EMPTY; + } + + if ( dataDim == 3 ) + { + dataDescription = VTK_XYZ_GRID; + } + else if ( dataDim == 2) + { + if ( inDim[0] == 1 ) + { + dataDescription = VTK_YZ_PLANE; + } + else if ( inDim[1] == 1 ) + { + dataDescription = VTK_XZ_PLANE; + } + else + { + dataDescription = VTK_XY_PLANE; + } + } + else if ( dataDim == 1 ) + { + if ( inDim[0] != 1 ) + { + dataDescription = VTK_X_LINE; + } + else if ( inDim[1] != 1 ) + { + dataDescription = VTK_Y_LINE; + } + else + { + dataDescription = VTK_Z_LINE; + } + } + else + { + dataDescription = VTK_SINGLE_POINT; + } + } + + return dataDescription; +} + +// Specify the extent of a regular, rectangular dataset. The input is +// the new extent (inExt) and the current extent (ext). The function +// returns the dimension of the dataset (0-3D). If the extents are +// improperly specified a -1 is returned. If the dimensions are unchanged, a +// value of 100 is returned. +int vtkStructuredData::SetExtent(int inExt[6], int ext[6]) +{ + int dataDim, i; + int dataDescription; + + if ( inExt[0] == ext[0] && inExt[1] == ext[1] && + inExt[2] == ext[2] && inExt[3] == ext[3] && + inExt[4] == ext[4] && inExt[5] == ext[5]) + { + return VTK_UNCHANGED; + } + + dataDim = 0; + for (i=0; i<3 ; ++i) + { + ext[i*2] = inExt[i*2]; + ext[i*2+1] = inExt[i*2+1]; + if (inExt[i*2] < inExt[i*2+1]) + { + dataDim++; + } + } + + if ( inExt[0]>inExt[1] || inExt[2]>inExt[3] || inExt[4]>inExt[5] ) + { + return VTK_EMPTY; + } + + if ( dataDim == 3 ) + { + dataDescription = VTK_XYZ_GRID; + } + else if ( dataDim == 2) + { + if ( inExt[0] == inExt[1] ) + { + dataDescription = VTK_YZ_PLANE; + } + else if ( inExt[2] == inExt[3] ) + { + dataDescription = VTK_XZ_PLANE; + } + else + { + dataDescription = VTK_XY_PLANE; + } + } + else if ( dataDim == 1 ) + { + if ( inExt[0] < inExt[1] ) + { + dataDescription = VTK_X_LINE; + } + else if ( inExt[2] < inExt[3] ) + { + dataDescription = VTK_Y_LINE; + } + else + { + dataDescription = VTK_Z_LINE; + } + } + else + { + dataDescription = VTK_SINGLE_POINT; + } + + return dataDescription; +} + +// Get the points defining a cell. (See vtkDataSet for more info.) +void vtkStructuredData::GetCellPoints(vtkIdType cellId, vtkIdList *ptIds, + int dataDescription, int dim[3]) +{ + int loc[3]; + vtkIdType idx, npts; + int iMin, iMax, jMin, jMax, kMin, kMax; + int d01 = dim[0]*dim[1]; + + ptIds->Reset(); + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + switch (dataDescription) + { + case VTK_EMPTY: + return; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + break; + + case VTK_XY_PLANE: + iMin = cellId % (dim[0]-1); + iMax = iMin + 1; + jMin = cellId / (dim[0]-1); + jMax = jMin + 1; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (dim[1]-1); + jMax = jMin + 1; + kMin = cellId / (dim[1]-1); + kMax = kMin + 1; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (dim[0]-1); + iMax = iMin + 1; + kMin = cellId / (dim[0]-1); + kMax = kMin + 1; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (dim[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (dim[0] - 1)) % (dim[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((dim[0] - 1) * (dim[1] - 1)); + kMax = kMin + 1; + break; + } + + // Extract point ids + for (npts=0,loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + idx = loc[0] + loc[1]*dim[0] + loc[2]*d01; + ptIds->InsertId(npts++,idx); + } + } + } +} + +// Get the cells using a point. (See vtkDataSet for more info.) +void vtkStructuredData::GetPointCells(vtkIdType ptId, vtkIdList *cellIds, + int dim[3]) +{ + int cellDim[3]; + int ptLoc[3], cellLoc[3]; + int i, j; + vtkIdType cellId; + static int offset[8][3] = {{-1,0,0}, {-1,-1,0}, {-1,-1,-1}, {-1,0,-1}, + {0,0,0}, {0,-1,0}, {0,-1,-1}, {0,0,-1}}; + + for (i=0; i<3; i++) + { + cellDim[i] = dim[i] - 1; + if (cellDim[i] == 0) + { + cellDim[i] = 1; + } + } + + // Get the location of the point + // + ptLoc[0] = ptId % dim[0]; + ptLoc[1] = (ptId / dim[0]) % dim[1]; + ptLoc[2] = ptId / (dim[0]*dim[1]); + + // From the point location, compute the cell locations. There are at + // most eight possible. + // + cellIds->Reset(); + + for (j=0; j<8; j++) + { + for (i=0; i<3; i++) + { + cellLoc[i] = ptLoc[i] + offset[j][i]; + if ( cellLoc[i] < 0 || cellLoc[i] >= cellDim[i] ) + { + break; + } + } + if ( i >= 3 ) //add cell + { + cellId = cellLoc[0] + cellLoc[1]*cellDim[0] + + cellLoc[2]*cellDim[0]*cellDim[1]; + cellIds->InsertNextId(cellId); + } + } + + return; +} + +void vtkStructuredData::GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds, int dim[3]) +{ + int j, seedLoc[3], ptLoc[3], cellLoc[3], cellDim[3]; + int offset[8][3]; + vtkIdType numPts=ptIds->GetNumberOfIds(), id, i; + + cellIds->Reset(); + + // Start by finding the "space" of the points in i-j-k space. + // The points define a point, line, or plane in topological space, + // which results in degrees of freedom in three, two or one direction. + // The numbers of DOF determines which neighbors to select. + + // Start by finding a seed point + id = ptIds->GetId(0); + seedLoc[0] = id % dim[0]; + seedLoc[1] = (id / dim[0]) % dim[1]; + seedLoc[2] = id / (dim[0]*dim[1]); + + // This defines the space around the seed + offset[0][0] = -1; offset[0][1] = -1; offset[0][2] = -1; + offset[1][0] = 0; offset[1][1] = -1; offset[1][2] = -1; + offset[2][0] = -1; offset[2][1] = 0; offset[2][2] = -1; + offset[3][0] = 0; offset[3][1] = 0; offset[3][2] = -1; + offset[4][0] = -1; offset[4][1] = -1; offset[4][2] = 0; + offset[5][0] = 0; offset[5][1] = -1; offset[5][2] = 0; + offset[6][0] = -1; offset[6][1] = 0; offset[6][2] = 0; + offset[7][0] = 0; offset[7][1] = 0; offset[7][2] = 0; + + // For the rest of the points, trim the seed region + // This is essentially an intersection of edge neighbors. + for (i=1; iGetId(i); + ptLoc[0] = id % dim[0]; + ptLoc[1] = (id / dim[0]) % dim[1]; + ptLoc[2] = id / (dim[0]*dim[1]); + + if ( (ptLoc[0]-1) == seedLoc[0] ) + { + offset[0][0] = -10; + offset[2][0] = -10; + offset[4][0] = -10; + offset[6][0] = -10; + } + else if ( (ptLoc[0]+1) == seedLoc[0] ) + { + offset[1][0] = -10; + offset[3][0] = -10; + offset[5][0] = -10; + offset[7][0] = -10; + } + else if ( (ptLoc[1]-1) == seedLoc[1] ) + { + offset[0][1] = -10; + offset[1][1] = -10; + offset[4][1] = -10; + offset[5][1] = -10; + } + else if ( (ptLoc[1]+1) == seedLoc[1] ) + { + offset[2][1] = -10; + offset[3][1] = -10; + offset[6][1] = -10; + offset[7][1] = -10; + } + else if ( (ptLoc[2]-1) == seedLoc[2] ) + { + offset[0][2] = -10; + offset[1][2] = -10; + offset[2][2] = -10; + offset[3][2] = -10; + } + else if ( (ptLoc[2]+1) == seedLoc[2] ) + { + offset[4][2] = -10; + offset[5][2] = -10; + offset[6][2] = -10; + offset[7][2] = -10; + } + } + + // Load the non-trimmed cells + cellDim[0] = dim[0] - 1; + cellDim[1] = dim[1] - 1; + cellDim[2] = dim[2] - 1; + + for(i=0; i<3; i++) + { + if ( cellDim[i] < 1 ) + { + cellDim[i] = 1; + } + } + + for (j=0; j<8; j++) + { + for (i=0; i<3; i++) + { + if ( offset[j][i] != -10 ) + { + cellLoc[i] = seedLoc[i] + offset[j][i]; + if ( cellLoc[i] < 0 || cellLoc[i] >= cellDim[i] ) + { + break; + } + } + else + { + break; + } + } + if ( i >= 3 ) //add cell + { + id = cellLoc[0] + cellLoc[1]*cellDim[0] + + cellLoc[2]*cellDim[0]*cellDim[1]; + if (id != cellId ) + { + cellIds->InsertNextId(id); + } + } + } +} + + diff --git a/Common/vtkStructuredData.h b/Common/vtkStructuredData.h new file mode 100644 index 0000000..851881f --- /dev/null +++ b/Common/vtkStructuredData.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredData - abstract class for topologically regular data +// .SECTION Description +// vtkStructuredData is an abstract class that specifies an interface for +// topologically regular data. Regular data is data that can be accessed +// in rectangular fashion using an i-j-k index. A finite difference grid, +// a volume, or a pixmap are all considered regular. + +#ifndef __vtkStructuredData_h +#define __vtkStructuredData_h + +#include "vtkObject.h" + +class vtkIdList; + +#define VTK_UNCHANGED 0 +#define VTK_SINGLE_POINT 1 +#define VTK_X_LINE 2 +#define VTK_Y_LINE 3 +#define VTK_Z_LINE 4 +#define VTK_XY_PLANE 5 +#define VTK_YZ_PLANE 6 +#define VTK_XZ_PLANE 7 +#define VTK_XYZ_GRID 8 +#define VTK_EMPTY 9 + +class VTK_COMMON_EXPORT vtkStructuredData : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkStructuredData,vtkObject); + + // Description: + // Specify the dimensions of a regular, rectangular dataset. The input is + // the new dimensions (inDim) and the current dimensions (dim). The function + // returns the dimension of the dataset (0-3D). If the dimensions are + // improperly specified a -1 is returned. If the dimensions are unchanged, a + // value of 100 is returned. + static int SetDimensions(int inDim[3], int dim[3]); + static int SetExtent(int inExt[6], int ext[6]); + + // Description: + // Return the topological dimension of the data (e.g., 0, 1, 2, or 3D). + static int GetDataDimension(int dataDescription); + + // Description: + // Get the points defining a cell. (See vtkDataSet for more info.) + static void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds, + int dataDescription, int dim[3]); + + // Description: + // Get the cells using a point. (See vtkDataSet for more info.) + static void GetPointCells(vtkIdType ptId, vtkIdList *cellIds, int dim[3]); + + // Description: + // Get the cells using the points ptIds, exclusive of the cell cellId. + // (See vtkDataSet for more info.) + static void GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds, int dim[3]); + + // Description: + // Given a location in structured coordinates (i-j-k), and the dimensions + // of the structured dataset, return the point id. + static vtkIdType ComputePointId(int dim[3], int ijk[3]) { + return (ijk[2]*dim[1] + ijk[1])*dim[0] + ijk[0];} + + // Description: + // Given a location in structured coordinates (i-j-k), and the dimensions + // of the structured dataset, return the cell id. + static vtkIdType ComputeCellId(int dim[3], int ijk[3]) { + return (ijk[2]*(dim[1]-1) + ijk[1])*(dim[0]-1) + ijk[0];} + +protected: + vtkStructuredData() {}; + ~vtkStructuredData() {}; + +private: + vtkStructuredData(const vtkStructuredData&); // Not implemented. + void operator=(const vtkStructuredData&); // Not implemented. +}; + + +#endif + diff --git a/Common/vtkStructuredVisibilityConstraint.cxx b/Common/vtkStructuredVisibilityConstraint.cxx new file mode 100644 index 0000000..c712db6 --- /dev/null +++ b/Common/vtkStructuredVisibilityConstraint.cxx @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredVisibilityConstraint.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredVisibilityConstraint.h" + +#include "vtkObjectFactory.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkStructuredVisibilityConstraint, + "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkStructuredVisibilityConstraint); + +vtkCxxSetObjectMacro(vtkStructuredVisibilityConstraint, + VisibilityById, + vtkUnsignedCharArray); + +//---------------------------------------------------------------------------- +vtkStructuredVisibilityConstraint::vtkStructuredVisibilityConstraint() +{ + this->VisibilityById = 0; + for (int i=0; i<3; i++) + { + this->Dimensions[i] = 0; + } + this->NumberOfIds = 0; + this->Initialized = 0; +} + +//---------------------------------------------------------------------------- +vtkStructuredVisibilityConstraint::~vtkStructuredVisibilityConstraint() +{ + if (this->VisibilityById) + { + this->VisibilityById->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkStructuredVisibilityConstraint::DeepCopy( + vtkStructuredVisibilityConstraint* src) +{ + memcpy(this->Dimensions, src->Dimensions, 3*sizeof(int)); + this->NumberOfIds = + this->Dimensions[0]*this->Dimensions[1]*this->Dimensions[2]; + if(src->VisibilityById) + { + if (!this->VisibilityById) + { + this->VisibilityById = vtkUnsignedCharArray::New(); + } + this->VisibilityById->DeepCopy(src->VisibilityById); + } + this->Initialized = src->Initialized; +} + +//---------------------------------------------------------------------------- +void vtkStructuredVisibilityConstraint::ShallowCopy( + vtkStructuredVisibilityConstraint* src) +{ + memcpy(this->Dimensions, src->Dimensions, 3*sizeof(int)); + this->NumberOfIds = + this->Dimensions[0]*this->Dimensions[1]*this->Dimensions[2]; + this->SetVisibilityById(src->VisibilityById); + this->Initialized = src->Initialized; +} + +//---------------------------------------------------------------------------- +void vtkStructuredVisibilityConstraint::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "VisibilityById: "; + if (this->VisibilityById) + { + os << endl; + this->VisibilityById->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << "(none)" << endl; + } + os << indent << "Dimensions: " + << this->Dimensions[0] << " " + << this->Dimensions[1] << " " + << this->Dimensions[2] + << endl; +} + diff --git a/Common/vtkStructuredVisibilityConstraint.h b/Common/vtkStructuredVisibilityConstraint.h new file mode 100644 index 0000000..4aafc75 --- /dev/null +++ b/Common/vtkStructuredVisibilityConstraint.h @@ -0,0 +1,157 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredVisibilityConstraint.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredVisibilityConstraint - helper object to manage the +// visibility of points and cells +// .SECTION Description +// vtkStructuredVisibilityConstraint is a general class to manage +// a list of points/cell marked as invalid or invisible. Currently, +// it does this by maintaining an unsigned char array associated +// with points/cells. To conserve memory, this array is allocated +// only when it is needed (when Blank() is called the first time). +// Make sure to call Initialize() with the right dimensions before +// calling any methods that set/get visibility. + +#ifndef __vtkStructuredVisibilityConstraint_h +#define __vtkStructuredVisibilityConstraint_h + +#include "vtkObject.h" + +#include "vtkUnsignedCharArray.h" // Needed for inline methods. + +class VTK_COMMON_EXPORT vtkStructuredVisibilityConstraint : public vtkObject +{ +public: + static vtkStructuredVisibilityConstraint *New(); + + vtkTypeRevisionMacro(vtkStructuredVisibilityConstraint,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Returns 1 is the point/cell is visible, 0 otherwise. + unsigned char IsVisible(vtkIdType id); + + // Description: + // Sets the visibility flag of the given point/cell off. + // The first time blank is called, a new visibility array + // is created if it doesn't exist. + void Blank(vtkIdType id); + + // Description: + // Sets the visibility flag of the given point/cell on. + void UnBlank(vtkIdType id); + + // Description: + // Get the dimensions used to initialize the object. + vtkGetVectorMacro(Dimensions,int,3); + + // Description: + // Set the dimensions and set the Initialized flag to 1. Once + // an object is initialized, it's dimensions can not be + // changed anymore. + void Initialize(int dims[3]); + + // Description: + // Set/Get the array used to store the visibility flags. + void SetVisibilityById(vtkUnsignedCharArray* vis); + vtkGetObjectMacro(VisibilityById, vtkUnsignedCharArray); + + // Description: + // Copies the dimensions, the visibility array pointer + // and the initialized flag. + void ShallowCopy(vtkStructuredVisibilityConstraint* src); + + // Description: + // Copies the dimensions, the visibility array + // and the initialized flag. + void DeepCopy(vtkStructuredVisibilityConstraint* src); + + // Description: + // Returns 0 if there is no visibility array (all cells/points + // are visibile), 0 otherwise. + unsigned char IsConstrained() + { + return this->VisibilityById ? 1 : 0; + } + +protected: + vtkStructuredVisibilityConstraint(); + ~vtkStructuredVisibilityConstraint(); + + vtkUnsignedCharArray* VisibilityById; + int Dimensions[3]; + vtkIdType NumberOfIds; + unsigned char Initialized; + +private: + vtkStructuredVisibilityConstraint(const vtkStructuredVisibilityConstraint&); // Not implemented. + void operator=(const vtkStructuredVisibilityConstraint&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +// These methods are inline for efficiency. + +//---------------------------------------------------------------------------- +inline unsigned char vtkStructuredVisibilityConstraint::IsVisible( + vtkIdType id) +{ + vtkUnsignedCharArray* vis = this->VisibilityById; + return vis ? vis->GetValue(id) : 1; +} + +//---------------------------------------------------------------------------- +inline void vtkStructuredVisibilityConstraint::Blank(vtkIdType id) +{ + vtkUnsignedCharArray* vis = this->VisibilityById; + if (!vis) + { + this->VisibilityById = vtkUnsignedCharArray::New(); + vis = this->VisibilityById; + this->VisibilityById->Allocate(this->NumberOfIds); + for (int i=0; iNumberOfIds; ++i) + { + this->VisibilityById->SetValue(i, 1); + } + } + vis->SetValue(id, 0); +} + +//---------------------------------------------------------------------------- +inline void vtkStructuredVisibilityConstraint::UnBlank(vtkIdType id) +{ + vtkUnsignedCharArray* vis = this->VisibilityById; + if (!vis) + { + return; + } + vis->SetValue(id, 1); +} + +//---------------------------------------------------------------------------- +inline void vtkStructuredVisibilityConstraint::Initialize(int dims[3]) +{ + if (this->Initialized) + { + return; + } + for (int i=0; i<3; i++) + { + this->Dimensions[i] = dims[i]; + } + this->NumberOfIds = dims[0]*dims[1]*dims[2]; + this->Initialized = 1; +} + + +#endif diff --git a/Common/vtkSystemIncludes.h b/Common/vtkSystemIncludes.h new file mode 100644 index 0000000..93475d1 --- /dev/null +++ b/Common/vtkSystemIncludes.h @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSystemIncludes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSystemIncludes - transition VTK to ANSI C++, centralize +// inclusion of system files +// .SECTION Description +// The vtkSystemIncludes centralizes the inclusion of system include +// files. (This is particularly important as VTK moves towards ANSI +// C++.) For example, this include file enables user's to build VTK +// with STL (i.e., use std: :ostream and other standard ANSI C++ +// functionality). A configured flag in vtkConfigure.h +// (VTK_USE_ANSI_STDLIB) must be set to enable ANSI C++ compliance. + +#ifndef __vtkSystemIncludes_h +#define __vtkSystemIncludes_h + +/* first include the local configuration for this machine */ +#define __VTK_SYSTEM_INCLUDES__INSIDE +#include "vtkWin32Header.h" +#undef __VTK_SYSTEM_INCLUDES__INSIDE + +// The language wrapper files do not need the real streams. They +// define VTK_STREAMS_FWD_ONLY so that the streams are only +// forward-declared. This significantly improves compile time on some +// platforms. +#if defined(VTK_STREAMS_FWD_ONLY) +# include "vtkIOStreamFwd.h" // Forward-declare the C++ streams. +#else +# include "vtkIOStream.h" // Include the real C++ streams. +#endif + +// Setup the basic types to be used by VTK. +#include "vtkType.h" + +// this should be removed at some point +#define VTK_USE_EXECUTIVES + +#define __VTK_SYSTEM_INCLUDES__INSIDE +#include "vtkOStreamWrapper.h" // Include the ostream wrapper. +#include "vtkOStrStreamWrapper.h" // Include the ostrstream wrapper. +#undef __VTK_SYSTEM_INCLUDES__INSIDE + +// Include generic stuff. +#include +#include +#include + +// Borland C++ defines several of the stdlib.h and string.h symbols in +// sub-headers search.h and mem.h. These sub-headers have using +// declarations to pull functions from the std namespace to the global +// namespace, but they are defined only if the header was not included +// through the C++-style cstdlib or cstring header. These outer +// headers are included by the streams library in C++-style and +// include blockers are put in place that prevent including the +// C-style versions from ever including the sub-headers. Therefore we +// have to include the sub-headers here to get the using declarations. +#if defined(__BORLANDC__) +# include /* mem... functions from string.h */ +# include /* search functions from stdlib.h */ +#endif + +// These types define error codes for vtk functions +#define VTK_OK 1 +#define VTK_ERROR 2 + +// These types define different text properties +#define VTK_ARIAL 0 +#define VTK_COURIER 1 +#define VTK_TIMES 2 + +#define VTK_TEXT_LEFT 0 +#define VTK_TEXT_CENTERED 1 +#define VTK_TEXT_RIGHT 2 + +#define VTK_TEXT_BOTTOM 0 +#define VTK_TEXT_TOP 2 + +#define VTK_TEXT_GLOBAL_ANTIALIASING_SOME 0 +#define VTK_TEXT_GLOBAL_ANTIALIASING_NONE 1 +#define VTK_TEXT_GLOBAL_ANTIALIASING_ALL 2 + +#define VTK_LUMINANCE 1 +#define VTK_LUMINANCE_ALPHA 2 +#define VTK_RGB 3 +#define VTK_RGBA 4 + +#define VTK_COLOR_MODE_DEFAULT 0 +#define VTK_COLOR_MODE_MAP_SCALARS 1 + +// Constants for InterpolationType +#define VTK_NEAREST_INTERPOLATION 0 +#define VTK_LINEAR_INTERPOLATION 1 + +// For volume rendering +#define VTK_MAX_VRCOMP 4 + +// For multithreading + +// The maximum number of threads allowed +#ifdef VTK_USE_SPROC +#define VTK_MAX_THREADS 32 +#endif + +#ifdef VTK_USE_PTHREADS +#define VTK_MAX_THREADS 32 +#endif + +#ifdef VTK_USE_WIN32_THREADS +#define VTK_MAX_THREADS 8 +#endif + +#ifndef VTK_USE_WIN32_THREADS +#ifndef VTK_USE_SPROC +#ifndef VTK_USE_PTHREADS +#define VTK_MAX_THREADS 1 +#endif +#endif +#endif + +// If VTK_USE_PTHREADS is defined, then the multithreaded +// function is of type void *, and returns NULL +// Otherwise the type is void which is correct for WIN32 +// and SPROC +#ifdef VTK_USE_PTHREADS +#define VTK_THREAD_RETURN_VALUE NULL +#define VTK_THREAD_RETURN_TYPE void * +#endif + +#ifdef VTK_USE_WIN32_THREADS +#define VTK_THREAD_RETURN_VALUE 0 +#define VTK_THREAD_RETURN_TYPE vtkWindowsDWORD __stdcall +#endif + +#if !defined(VTK_USE_PTHREADS) && !defined(VTK_USE_WIN32_THREADS) +#define VTK_THREAD_RETURN_VALUE +#define VTK_THREAD_RETURN_TYPE void +#endif + +// For encoding + +#define VTK_ENCODING_NONE 0 // to specify that no encoding should occur +#define VTK_ENCODING_US_ASCII 1 +#define VTK_ENCODING_UNICODE 2 +#define VTK_ENCODING_UTF_8 3 +#define VTK_ENCODING_ISO_8859_1 4 +#define VTK_ENCODING_ISO_8859_2 5 +#define VTK_ENCODING_ISO_8859_3 6 +#define VTK_ENCODING_ISO_8859_4 7 +#define VTK_ENCODING_ISO_8859_5 8 +#define VTK_ENCODING_ISO_8859_6 9 +#define VTK_ENCODING_ISO_8859_7 10 +#define VTK_ENCODING_ISO_8859_8 11 +#define VTK_ENCODING_ISO_8859_9 12 +#define VTK_ENCODING_ISO_8859_10 13 +#define VTK_ENCODING_ISO_8859_11 14 +#define VTK_ENCODING_ISO_8859_12 15 +#define VTK_ENCODING_ISO_8859_13 16 +#define VTK_ENCODING_ISO_8859_14 17 +#define VTK_ENCODING_ISO_8859_15 18 +#define VTK_ENCODING_ISO_8859_16 19 +#define VTK_ENCODING_UNKNOWN 20 // leave this one at the end + +#endif diff --git a/Common/vtkTableExtentTranslator.cxx b/Common/vtkTableExtentTranslator.cxx new file mode 100644 index 0000000..2082338 --- /dev/null +++ b/Common/vtkTableExtentTranslator.cxx @@ -0,0 +1,321 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTableExtentTranslator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTableExtentTranslator.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkTableExtentTranslator, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkTableExtentTranslator); + +//---------------------------------------------------------------------------- +vtkTableExtentTranslator::vtkTableExtentTranslator() +{ + this->ExtentTable = 0; + this->MaximumGhostLevel = 0; + this->PieceAvailable = 0; + this->NumberOfPiecesInTable = 0; +} + +//---------------------------------------------------------------------------- +vtkTableExtentTranslator::~vtkTableExtentTranslator() +{ + this->SetNumberOfPiecesInTable(0); +} + +//---------------------------------------------------------------------------- +void vtkTableExtentTranslator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if(this->ExtentTable) + { + vtkIndent nextIndent = indent.GetNextIndent(); + int* extent = this->ExtentTable; + int i; + + os << indent << "ExtentTable: 0: " + << extent[0] << " " << extent[1] << " " + << extent[2] << " " << extent[3] << " " + << extent[4] << " " << extent[5] << "\n"; + for(i=1;i < this->NumberOfPiecesInTable;++i) + { + extent += 6; + os << nextIndent << " " << i << ": " + << extent[0] << " " << extent[1] << " " + << extent[2] << " " << extent[3] << " " + << extent[4] << " " << extent[5] << "\n"; + } + } + else + { + os << indent << "ExtentTable: (none)\n"; + } + os << indent << "MaximumGhostLevel: " << this->MaximumGhostLevel << "\n"; + os << indent << "NumberOfPiecesInTable: " + << this->NumberOfPiecesInTable << "\n"; + if(this->PieceAvailable) + { + vtkIndent nextIndent = indent.GetNextIndent(); + int* available = this->PieceAvailable; + int i; + + os << indent << "PieceAvailable: 0: " << *available << "\n"; + for(i=1;i < this->NumberOfPiecesInTable;++i) + { + ++available; + os << nextIndent << " " << i << ": " + << *available << "\n"; + } + } + else + { + os << indent << "PieceAvailable: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkTableExtentTranslator::SetNumberOfPieces(int pieces) +{ + // Allocate a table for this number of pieces. + if(this->NumberOfPiecesInTable == 0) + { + this->SetNumberOfPiecesInTable(pieces); + } + this->Superclass::SetNumberOfPieces(pieces); +} + +//---------------------------------------------------------------------------- +void vtkTableExtentTranslator::SetNumberOfPiecesInTable(int pieces) +{ + // Make sure we are really changing the number of pieces. + if(this->NumberOfPiecesInTable == pieces) + { + return; + } + + // The default number of pieces returned is the real number of + // pieces. + this->Superclass::SetNumberOfPieces(pieces); + this->NumberOfPiecesInTable = pieces; + + // Clean out any old extent table. + if(this->ExtentTable) + { + delete [] this->ExtentTable; + this->ExtentTable = 0; + } + if(this->PieceAvailable) + { + delete [] this->PieceAvailable; + this->PieceAvailable = 0; + } + + // Create and initialize a new extent table if there are any pieces. + // Assume all pieces are available. + if(this->NumberOfPiecesInTable > 0) + { + this->ExtentTable = new int[this->NumberOfPiecesInTable*6]; + this->PieceAvailable = new int[this->NumberOfPiecesInTable]; + int i; + for(i=0;i < this->NumberOfPiecesInTable;++i) + { + int* extent = this->ExtentTable + i*6; + extent[0] = extent[2] = extent[4] = 0; + extent[1] = extent[3] = extent[5] = -1; + this->PieceAvailable[i] = 1; + } + } +} + +//---------------------------------------------------------------------------- +void vtkTableExtentTranslator::SetExtentForPiece(int piece, int* extent) +{ + if((!this->ExtentTable) || (piece < 0) || + (piece >= this->NumberOfPiecesInTable)) + { + vtkErrorMacro("Piece " << piece << " does not exist. " + "NumberOfPiecesInTable is " << this->NumberOfPiecesInTable); + return; + } + memcpy(this->ExtentTable+piece*6, extent, sizeof(int)*6); +} + +//---------------------------------------------------------------------------- +void vtkTableExtentTranslator::GetExtentForPiece(int piece, int* extent) +{ + if((!this->ExtentTable) || (piece < 0) || + (piece >= this->NumberOfPiecesInTable)) + { + vtkErrorMacro("Piece " << piece << " does not exist. " + "NumberOfPiecesInTable is " << this->NumberOfPiecesInTable); + extent[0] = extent[2] = extent[4] = 0; + extent[1] = extent[3] = extent[5] = -1; + return; + } + memcpy(extent, this->ExtentTable+piece*6, sizeof(int)*6); +} + +//---------------------------------------------------------------------------- +int* vtkTableExtentTranslator::GetExtentForPiece(int piece) +{ + static int emptyExtent[6] = {0,-1,0,-1,0,-1}; + if((!this->ExtentTable) || (piece < 0) || + (piece >= this->NumberOfPiecesInTable)) + { + vtkErrorMacro("Piece " << piece << " does not exist. " + "NumberOfPiecesInTable is " << this->NumberOfPiecesInTable); + return emptyExtent; + } + return this->ExtentTable+piece*6; +} + +//---------------------------------------------------------------------------- +void vtkTableExtentTranslator::SetPieceAvailable(int piece, int available) +{ + if((!this->ExtentTable) || (piece < 0) || + (piece >= this->NumberOfPiecesInTable)) + { + vtkErrorMacro("Piece " << piece << " does not exist. " + "NumberOfPiecesInTable is " << this->NumberOfPiecesInTable); + return; + } + this->PieceAvailable[piece] = available?1:0; +} + +//---------------------------------------------------------------------------- +int vtkTableExtentTranslator::GetPieceAvailable(int piece) +{ + if((!this->ExtentTable) || (piece < 0) || + (piece >= this->NumberOfPiecesInTable)) + { + vtkErrorMacro("Piece " << piece << " does not exist. " + "NumberOfPiecesInTable is " << this->NumberOfPiecesInTable); + return 0; + } + return this->PieceAvailable[piece]; +} + +//---------------------------------------------------------------------------- +int vtkTableExtentTranslator::PieceToExtentByPoints() +{ + vtkErrorMacro("PieceToExtentByPoints not supported."); + return 0; +} + +//---------------------------------------------------------------------------- +int +vtkTableExtentTranslator::PieceToExtentThreadSafe(int piece, int numPieces, + int ghostLevel, + int *wholeExtent, + int *resultExtent, + int vtkNotUsed(splitMode), + int byPoints) +{ + if (byPoints) + { + vtkErrorMacro("PieceToExtentByPoints not supported."); + return 0; + } + + if((!this->ExtentTable) || (piece < 0) || + (piece >= numPieces)) + { + vtkErrorMacro("Piece " << piece << " does not exist."); + return 0; + } + + if(ghostLevel > this->MaximumGhostLevel) + { + vtkWarningMacro("Ghost level " << ghostLevel + << " is larger than MaximumGhostLevel " + << this->MaximumGhostLevel << ". Using the maximum."); + ghostLevel = this->MaximumGhostLevel; + } + + if(numPieces == 1) + { + // The number of pieces requested is one. Return the whole extent. + memcpy(resultExtent, wholeExtent, sizeof(int)*6); + } + else if(piece < this->NumberOfPiecesInTable) + { + // Return the extent from the table entry. + memcpy(resultExtent, this->ExtentTable+piece*6, sizeof(int)*6); + } + else + { + // The requested piece is beyond the table. Return an empty extent. + resultExtent[0] = 0; + resultExtent[1] = -1; + resultExtent[2] = 0; + resultExtent[3] = -1; + resultExtent[4] = 0; + resultExtent[5] = -1; + } + + if(((resultExtent[1] - resultExtent[0] + 1)* + (resultExtent[3] - resultExtent[2] + 1)* + (resultExtent[5] - resultExtent[4] + 1)) == 0) + { + return 0; + } + + if(ghostLevel > 0) + { + resultExtent[0] -= this->GhostLevel; + resultExtent[1] += this->GhostLevel; + resultExtent[2] -= this->GhostLevel; + resultExtent[3] += this->GhostLevel; + resultExtent[4] -= this->GhostLevel; + resultExtent[5] += this->GhostLevel; + + if (resultExtent[0] < wholeExtent[0]) + { + resultExtent[0] = wholeExtent[0]; + } + if (resultExtent[1] > wholeExtent[1]) + { + resultExtent[1] = wholeExtent[1]; + } + if (resultExtent[2] < wholeExtent[2]) + { + resultExtent[2] = wholeExtent[2]; + } + if (resultExtent[3] > wholeExtent[3]) + { + resultExtent[3] = wholeExtent[3]; + } + if (resultExtent[4] < wholeExtent[4]) + { + resultExtent[4] = wholeExtent[4]; + } + if (resultExtent[5] > wholeExtent[5]) + { + resultExtent[5] = wholeExtent[5]; + } + } + + return 1; + +} + +//---------------------------------------------------------------------------- +int vtkTableExtentTranslator::PieceToExtent() +{ + return this->PieceToExtentThreadSafe(this->Piece, this->NumberOfPieces, + this->GhostLevel, + this->WholeExtent, + this->Extent, + this->SplitMode, + 0); +} diff --git a/Common/vtkTableExtentTranslator.h b/Common/vtkTableExtentTranslator.h new file mode 100644 index 0000000..b484a34 --- /dev/null +++ b/Common/vtkTableExtentTranslator.h @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTableExtentTranslator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTableExtentTranslator - Extent translation through lookup table. +// .SECTION Description +// vtkTableExtentTranslator provides a vtkExtentTranslator that is +// programmed with a specific extent corresponding to each piece +// number. Readers can provide this to an application to allow the +// pipeline to execute using the same piece breakdown that is provided +// in the input file. + +#ifndef __vtkTableExtentTranslator_h +#define __vtkTableExtentTranslator_h + +#include "vtkExtentTranslator.h" + +class VTK_COMMON_EXPORT vtkTableExtentTranslator : public vtkExtentTranslator +{ +public: + vtkTypeRevisionMacro(vtkTableExtentTranslator,vtkExtentTranslator); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkTableExtentTranslator* New(); + + // Description: + + // Set the number of pieces into which the whole extent will be + // split. If this is 1 then the whole extent will be returned. If + // this is more than the number of pieces in the table then the + // extra pieces will be empty data. If this is more than one but + // less than the number of pieces in the table then only this many + // pieces will be returned (FIXME). + void SetNumberOfPieces(int pieces); + + // Description: + // Set the real number of pieces in the extent table. + void SetNumberOfPiecesInTable(int pieces); + vtkGetMacro(NumberOfPiecesInTable, int); + + // Description: + // Called to translate the current piece into an extent. This is + // not thread safe. + int PieceToExtent(); + + // Description: + // Not supported by this subclass of vtkExtentTranslator. + int PieceToExtentByPoints(); + + // Description: + // Not supported by this subclass of vtkExtentTranslator. + int PieceToExtentThreadSafe(int piece, int numPieces, + int ghostLevel, int *wholeExtent, + int *resultExtent, int splitMode, + int byPoints); + + // Description: + // Set the extent to be used for a piece. This sets the extent table + // entry for the piece. + virtual void SetExtentForPiece(int piece, int* extent); + + // Description: + // Get the extent table entry for the given piece. This is only for + // code that is setting up the table. Extent translation should + // always be done through the PieceToExtent method. + virtual void GetExtentForPiece(int piece, int* extent); + virtual int* GetExtentForPiece(int piece); + + // Description: + // Set the maximum ghost level that can be requested. This can be + // used by a reader to make sure an extent request does not go + // outside the boundaries of the piece's file. + vtkSetMacro(MaximumGhostLevel, int); + vtkGetMacro(MaximumGhostLevel, int); + + // Description: + // Get/Set whether the given piece is available. Requesting a piece + // that is not available will produce errors in the pipeline. + virtual void SetPieceAvailable(int piece, int available); + virtual int GetPieceAvailable(int piece); + +protected: + vtkTableExtentTranslator(); + ~vtkTableExtentTranslator(); + + // Store the extent table in a single array. Every 6 values form an extent. + int* ExtentTable; + int NumberOfPiecesInTable; + int MaximumGhostLevel; + + // Store a flag for the availability of each piece. + int* PieceAvailable; + +private: + vtkTableExtentTranslator(const vtkTableExtentTranslator&); // Not implemented. + void operator=(const vtkTableExtentTranslator&); // Not implemented. +}; + +#endif diff --git a/Common/vtkTcl.h b/Common/vtkTcl.h new file mode 100644 index 0000000..d95045a --- /dev/null +++ b/Common/vtkTcl.h @@ -0,0 +1,28 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTcl.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkTcl_h +#define __vtkTcl_h + +#include "vtkConfigure.h" + +#ifdef VTK_TCL_TK_STATIC +# ifndef STATIC_BUILD +# define STATIC_BUILD +# endif +#endif + +#include + +#endif diff --git a/Common/vtkTclUtil.cxx b/Common/vtkTclUtil.cxx new file mode 100644 index 0000000..528722f --- /dev/null +++ b/Common/vtkTclUtil.cxx @@ -0,0 +1,833 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTclUtil.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkObject.h" +#include "vtkTclUtil.h" +#include "vtkSetGet.h" +#include "vtkCallbackCommand.h" + +#include +#include + +extern "C" +{ +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,int, CONST84 char *[]); +#else + typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,int, char *[]); +#endif +} + +vtkTclInterpStruct *vtkGetInterpStruct(Tcl_Interp *interp) +{ + vtkTclInterpStruct *is = (vtkTclInterpStruct *)Tcl_GetAssocData(interp,(char *) "vtk",NULL); + if (!is) + { + vtkGenericWarningMacro("unable to find interp struct"); + } + return is; +} + +VTKTCL_EXPORT int vtkTclInDelete(Tcl_Interp *interp) +{ + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + if (is) + { + return is->InDelete; + } + return 0; +} + + +// just another way into DeleteCommand +VTKTCL_EXPORT void vtkTclDeleteObjectFromHash(vtkObject *obj, + unsigned long vtkNotUsed(eventId), + void *cd, void *) +{ + vtkTclCommandArgStruct *as = (vtkTclCommandArgStruct *)cd; + char temps[80]; + Tcl_HashEntry *entry; + char *temp; + vtkTclInterpStruct *is = vtkGetInterpStruct(as->Interp); + + // lookup the objects name + sprintf(temps,"%p",obj); + entry = Tcl_FindHashEntry(&is->PointerLookup,temps); + if (entry) + { + temp = (char *)(Tcl_GetHashValue(entry)); + if (temp) + { + Tcl_DeleteCommand(as->Interp,temp); + } + } +} + +// we do no error checking in this. We assume that if we were called +// then tcl must have been able to find the command function and object. +VTKTCL_EXPORT void vtkTclGenericDeleteObject(ClientData cd) +{ + char temps[80]; + Tcl_HashEntry *entry; + int (*command)(ClientData, Tcl_Interp *,int, char *[]); + char *args[2]; + char *temp; + vtkObject *tobject; + int error; + vtkTclCommandArgStruct *as = (vtkTclCommandArgStruct *)cd; + Tcl_Interp *interp = as->Interp; + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + + /* set up the args */ + args[1] = (char *) "Delete"; + + // lookup the objects name + sprintf(temps,"%p",as->Pointer); + entry = Tcl_FindHashEntry(&is->PointerLookup,temps); + if (!entry) + { + return; + } + + temp = (char *)(Tcl_GetHashValue(entry)); + args[0] = temp; + + // first we clear the delete callback since we will + // always remove this object from the hash regardless + // of if it has really been freed. + tobject = (vtkObject *)vtkTclGetPointerFromObject(temp,"vtkObject", + interp, error); + tobject->RemoveObserver(as->Tag); + as->Tag = 0; + + // get the command function and invoke the delete operation + entry = Tcl_FindHashEntry(&is->CommandLookup,temp); + command = (int (*)(ClientData,Tcl_Interp *,int,char *[])) + Tcl_GetHashValue(entry); + + // do we need to delete the c++ obj + if (strncmp(temp,"vtkTemp",7)) + { + is->InDelete = 1; + command(cd,interp,2,args); + is->InDelete = 0; + } + + // the actual C++ object may not be freed yet. So we + // force it to be free from the hash table. + Tcl_DeleteHashEntry(entry); + entry = Tcl_FindHashEntry(&is->PointerLookup,temps); + Tcl_DeleteHashEntry(entry); + entry = Tcl_FindHashEntry(&is->InstanceLookup,temp); + Tcl_DeleteHashEntry(entry); + delete as; + + if (is->DebugOn) + { + vtkGenericWarningMacro("vtkTcl Attempting to free object named " << temp); + } + if (temp) + { + free(temp); + } +} + +int vtkCreateCommand(ClientData vtkNotUsed(cd), Tcl_Interp *interp, int argc, char *argv[]) +{ + Tcl_HashEntry *entry; + Tcl_HashSearch search; + char * tmp; + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + + if (argc < 2) + { + return TCL_OK; + } + + if (!strcmp(argv[1],"DeleteAllObjects")) + { + for (entry = Tcl_FirstHashEntry(&is->PointerLookup,&search); + entry != NULL; + entry = Tcl_FirstHashEntry(&is->PointerLookup,&search)) + { + tmp = strdup((char *)Tcl_GetHashValue(entry)); + if (tmp) + { + Tcl_DeleteCommand(interp,tmp); + } + if (tmp) + { + free(tmp); + } + } + return TCL_OK; + } + if (!strcmp(argv[1],"ListAllInstances")) + { + for (entry = Tcl_FirstHashEntry(&is->InstanceLookup,&search); + entry != NULL; entry = Tcl_NextHashEntry(&search)) + { + Tcl_AppendResult(interp, + (char *)Tcl_GetHashKey(&is->InstanceLookup,entry),NULL); + Tcl_AppendResult(interp,"\n",NULL); + } + return TCL_OK; + } + if (!strcmp(argv[1],"DebugOn")) + { + is->DebugOn = 1; + return TCL_OK; + } + if (!strcmp(argv[1],"DebugOff")) + { + is->DebugOn = 0; + return TCL_OK; + } + if (!strcmp(argv[1],"DeleteExistingObjectOnNewOn")) + { + is->DeleteExistingObjectOnNew = 1; + return TCL_OK; + } + if (!strcmp(argv[1],"DeleteExistingObjectOnNewOff")) + { + is->DeleteExistingObjectOnNew = 0; + return TCL_OK; + } + if (!strcmp("ListMethods",argv[1])) + { + Tcl_AppendResult(interp,"Methods for vtkCommand:\n",NULL); + Tcl_AppendResult(interp," DebugOn\n",NULL); + Tcl_AppendResult(interp," DebugOff\n",NULL); + Tcl_AppendResult(interp," DeleteAllObjects\n",NULL); + Tcl_AppendResult(interp," ListAllInstances\n",NULL); + Tcl_AppendResult(interp," DeleteExistingObjectOnNewOn\n",NULL); + Tcl_AppendResult(interp," DeleteExistingObjectOnNewOff\n",NULL); + return TCL_OK; + } + + Tcl_AppendResult(interp,"invalid method for vtkCommand\n",NULL); + return TCL_ERROR; +} + +VTKTCL_EXPORT void +vtkTclUpdateCommand(Tcl_Interp *interp, char *name, vtkObject *temp) +{ + Tcl_CmdProc *command = NULL; + + // check to see if we can find the command function based on class name + Tcl_CmdInfo cinf; + char *tstr = strdup(temp->GetClassName()); + if (Tcl_GetCommandInfo(interp,tstr,&cinf)) + { + if (cinf.clientData) + { + vtkTclCommandStruct *cs = (vtkTclCommandStruct *)cinf.clientData; + command = (Tcl_CmdProc *)cs->CommandFunction; + } + } + if (tstr) + { + free(tstr); + } + + // if not found then just return + if (!command) + { + return; + } + + // is the current command the same + Tcl_CmdInfo cinfo; + Tcl_GetCommandInfo(interp, name, &cinfo); + cinfo.proc = command; + Tcl_SetCommandInfo(interp, name, &cinfo); + + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + Tcl_HashEntry *entry = Tcl_FindHashEntry(&is->CommandLookup,name); + Tcl_SetHashValue(entry,(ClientData)command); +} + + +VTKTCL_EXPORT void +vtkTclGetObjectFromPointer(Tcl_Interp *interp, void *temp1, + const char *targetType) +{ + int (*command)(ClientData, Tcl_Interp *,int, char *[]) = 0; + int is_new; + vtkObject *temp = (vtkObject *)temp1; + char temps[80]; + char name[80]; + Tcl_HashEntry *entry; + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + + /* if it is NULL then return empty string */ + if (!temp) + { + Tcl_ResetResult(interp); + return; + } + + /* return a pointer to a vtk Object */ + if (is->DebugOn) + { + vtkGenericWarningMacro("Looking up name for vtk pointer: " << temp); + } + + /* first we must look up the pointer to see if it already exists */ + sprintf(temps,"%p",temp); + if ((entry = Tcl_FindHashEntry(&is->PointerLookup,temps))) + { + if (is->DebugOn) + { + vtkGenericWarningMacro("Found name: " + << (char *)(Tcl_GetHashValue(entry)) + << " for vtk pointer: " << temp); + } + + /* while we are at it store the name since it is required anyhow */ + Tcl_SetResult(interp, (char *)(Tcl_GetHashValue(entry)), TCL_VOLATILE); + return; + } + + /* we must create a new name if it isn't NULL */ + sprintf(name,"vtkTemp%i",is->Number); + is->Number++; + + if (is->DebugOn) + { + vtkGenericWarningMacro("Created name: " << name + << " for vtk pointer: " << temp); + } + + // check to see if we can find the command function based on class name + Tcl_CmdInfo cinf; + char *tstr = strdup(temp->GetClassName()); + if (Tcl_GetCommandInfo(interp,tstr,&cinf)) + { + if (cinf.clientData) + { + vtkTclCommandStruct *cs = (vtkTclCommandStruct *)cinf.clientData; + command = cs->CommandFunction; + } + } + // if the class command wasn;t found try the target return type command + if (!command && targetType) + { + if (tstr) + { + free(tstr); + } + tstr = strdup(targetType); + if (Tcl_GetCommandInfo(interp,tstr,&cinf)) + { + if (cinf.clientData) + { + vtkTclCommandStruct *cs = (vtkTclCommandStruct *)cinf.clientData; + command = cs->CommandFunction; + } + } + } + // if we still do not havbe a match then try vtkObject + if (!command) + { + if (tstr) + { + free(tstr); + } + tstr = strdup("vtkObject"); + if (Tcl_GetCommandInfo(interp,tstr,&cinf)) + { + if (cinf.clientData) + { + vtkTclCommandStruct *cs = (vtkTclCommandStruct *)cinf.clientData; + command = cs->CommandFunction; + } + } + } + if (tstr) + { + free(tstr); + } + + entry = Tcl_CreateHashEntry(&is->InstanceLookup,name,&is_new); + Tcl_SetHashValue(entry,(ClientData)(temp)); + entry = Tcl_CreateHashEntry(&is->PointerLookup,temps,&is_new); + Tcl_SetHashValue(entry,(ClientData)(strdup(name))); + vtkTclCommandArgStruct *as = new vtkTclCommandArgStruct; + as->Pointer = (void *)temp; + as->Interp = interp; + Tcl_CreateCommand(interp,name, + reinterpret_cast(command), + (ClientData)(as), + (Tcl_CmdDeleteProc *)vtkTclGenericDeleteObject); + entry = Tcl_CreateHashEntry(&is->CommandLookup,name,&is_new); + Tcl_SetHashValue(entry,(ClientData)command); + + // setup the delete callback + vtkCallbackCommand *cbc = vtkCallbackCommand::New(); + cbc->SetCallback(vtkTclDeleteObjectFromHash); + cbc->SetClientData((void *)as); + as->Tag = temp->AddObserver(vtkCommand::DeleteEvent, cbc); + cbc->Delete(); + + Tcl_SetResult(interp, (char *)name, TCL_VOLATILE); +} + +VTKTCL_EXPORT void *vtkTclGetPointerFromObject(const char *name, + const char *result_type, + Tcl_Interp *interp, + int &error) +{ + Tcl_HashEntry *entry; + ClientData temp; + int (*command)(ClientData, Tcl_Interp *,int, char *[]); + char *args[3]; + char temps[256]; + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + + /* check for empty string, empty string is the same as passing NULL */ + if (name[0] == '\0') + { + return NULL; + } + + // object names cannot start with a number + if ((name[0] >= '0')&&(name[0] <= '9')) + { + error = 1; + return NULL; + } + + if ((entry = Tcl_FindHashEntry(&is->InstanceLookup,name))) + { + temp = (ClientData)Tcl_GetHashValue(entry); + } + else + { + sprintf(temps,"vtk bad argument, could not find object named %s\n", name); + Tcl_AppendResult(interp,temps,NULL); + error = 1; + return NULL; + } + + /* now handle the typecasting, get the command proc */ + if ((entry = Tcl_FindHashEntry(&is->CommandLookup,name))) + { + command = (int (*)(ClientData,Tcl_Interp *,int,char *[]))Tcl_GetHashValue(entry); + } + else + { + sprintf(temps,"vtk bad argument, could not find command process for %s.\n", name); + Tcl_AppendResult(interp,temps,NULL); + error = 1; + return NULL; + } + + /* set up the args */ + args[0] = (char *) "DoTypecasting"; + args[1] = strdup(result_type); + args[2] = NULL; + vtkTclCommandArgStruct foo; + foo.Pointer = temp; + foo.Interp = interp; + if (command((ClientData)&foo,(Tcl_Interp *)NULL,3,args) == TCL_OK) + { + free (args[1]); + return (void *)(args[2]); + } + else + { + Tcl_Interp *i; + i = Tcl_CreateInterp(); + // provide more diagnostic info + args[0] = (char *) "Dummy"; + free (args[1]); + args[1] = (char *) "GetClassName"; + args[2] = NULL; + command((ClientData)&foo,i,2,args); + + sprintf(temps,"vtk bad argument, type conversion failed for object %s.\nCould not type convert %s which is of type %s, to type %s.\n", name, name, i->result, result_type); + Tcl_AppendResult(interp,temps,NULL); + error = 1; + Tcl_DeleteInterp(i); + return NULL; + } + +} + +VTKTCL_EXPORT void vtkTclVoidFunc(void *arg) +{ + int res; + + vtkTclVoidFuncArg *arg2; + + arg2 = (vtkTclVoidFuncArg *)arg; + +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 2 + res = Tcl_GlobalEval(arg2->interp, arg2->command); +#else + res = Tcl_EvalEx(arg2->interp, arg2->command, -1, TCL_EVAL_GLOBAL); +#endif + + if (res == TCL_ERROR) + { + if (Tcl_GetVar(arg2->interp,(char *) "errorInfo",0)) + { + vtkGenericWarningMacro("Error returned from vtk/tcl callback:\n" << + arg2->command << endl << + Tcl_GetVar(arg2->interp,(char *) "errorInfo",0) << + " at line number " << arg2->interp->errorLine); + } + else + { + vtkGenericWarningMacro("Error returned from vtk/tcl callback:\n" << + arg2->command << endl << + " at line number " << arg2->interp->errorLine); + } + } +} + +VTKTCL_EXPORT void vtkTclVoidFuncArgDelete(void *arg) +{ + vtkTclVoidFuncArg *arg2; + + arg2 = (vtkTclVoidFuncArg *)arg; + + // free the string and then structure + delete [] arg2->command; + delete arg2; +} + +VTKTCL_EXPORT void vtkTclListInstances(Tcl_Interp *interp, ClientData arg) +{ + Tcl_HashSearch srch; + Tcl_HashEntry *entry; + int first = 1; + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + + // iteratively search hash table for command function + entry = Tcl_FirstHashEntry(&is->CommandLookup, &srch); + if (!entry) + { + Tcl_ResetResult(interp); + return; + } + while (entry) + { + if (Tcl_GetHashValue(entry) == arg) + { + if (first) + { + first = 0; + Tcl_AppendResult(interp,Tcl_GetHashKey(&is->CommandLookup,entry),NULL); + } + else + { + Tcl_AppendResult(interp, " ", Tcl_GetHashKey(&is->CommandLookup,entry), + NULL); + } + } + entry = Tcl_NextHashEntry(&srch); + } +} + + +int vtkTclNewInstanceCommand(ClientData cd, Tcl_Interp *interp, + int argc, char *argv[]) +{ + int (*command)(ClientData, Tcl_Interp *,int, char *[]); + Tcl_HashEntry *entry; + int is_new; + char temps[80]; + char name[80]; + vtkTclCommandStruct *cs = (vtkTclCommandStruct *)cd; + Tcl_CmdInfo cinf; + vtkTclInterpStruct *is = vtkGetInterpStruct(interp); + + if (argc != 2) + { + Tcl_SetResult(interp, (char *) "vtk object creation requires one argument, a name, or the special New keyword to instantiate a new name.", TCL_VOLATILE); + return TCL_ERROR; + } + + if ((argv[1][0] >= '0')&&(argv[1][0] <= '9')) + { + Tcl_SetResult(interp, argv[1], TCL_VOLATILE); + Tcl_AppendResult(interp, ": vtk object cannot start with a numeric.", NULL); + return TCL_ERROR; + } + + if (Tcl_FindHashEntry(&is->InstanceLookup,argv[1])) + { + if (is->DeleteExistingObjectOnNew) + { + Tcl_DeleteCommand(interp, argv[1]); + } + else + { + Tcl_SetResult(interp, argv[1], TCL_VOLATILE); + Tcl_AppendResult(interp, + ": a vtk object with that name already exists.", + NULL); + return TCL_ERROR; + } + } + + // Make sure we are not clobbering a built in command + if (Tcl_GetCommandInfo(interp,argv[1],&cinf)) + { + Tcl_SetResult(interp, argv[1], TCL_VOLATILE); + Tcl_AppendResult(interp, + ": a tcl/tk command with that name already exists.", + NULL); + return TCL_ERROR; + } + + ClientData temp; + if (!strcmp("ListInstances",argv[1])) + { + vtkTclListInstances(interp,(ClientData) cs->CommandFunction); + return TCL_OK; + } + + if (!strcmp("New",argv[1])) + { + sprintf(name,"vtkObj%i",is->Number); + is->Number++; + argv[1] = name; + } + + temp = cs->NewCommand(); + + entry = Tcl_CreateHashEntry(&is->InstanceLookup,argv[1],&is_new); + Tcl_SetHashValue(entry,temp); + sprintf(temps,"%p",(void *)temp); + entry = Tcl_CreateHashEntry(&is->PointerLookup,temps,&is_new); + Tcl_SetHashValue(entry,(ClientData)(strdup(argv[1]))); + + // check to see if we can find the command function based on class name + char *tstr = strdup(((vtkObject *)temp)->GetClassName()); + if (Tcl_GetCommandInfo(interp,tstr,&cinf)) + { + if (cinf.clientData) + { + vtkTclCommandStruct *cs2 = (vtkTclCommandStruct *)cinf.clientData; + command = cs2->CommandFunction; + } + else + { + command = cs->CommandFunction; + } + } + else + { + command = cs->CommandFunction; + } + if (tstr) + { + free(tstr); + } + + vtkTclCommandArgStruct *as = new vtkTclCommandArgStruct; + as->Pointer = (void *)temp; + as->Interp = interp; + Tcl_CreateCommand(interp,argv[1], + reinterpret_cast(command), + (ClientData)as, + (Tcl_CmdDeleteProc *)vtkTclGenericDeleteObject); + entry = Tcl_CreateHashEntry(&is->CommandLookup,argv[1],&is_new); + Tcl_SetHashValue(entry,(ClientData)(cs->CommandFunction)); + + // setup the delete callback + vtkCallbackCommand *cbc = vtkCallbackCommand::New(); + cbc->SetCallback(vtkTclDeleteObjectFromHash); + cbc->SetClientData((void *)as); + as->Tag = ((vtkObject *)temp)->AddObserver(vtkCommand::DeleteEvent, cbc); + cbc->Delete(); + + Tcl_SetResult(interp, argv[1], TCL_VOLATILE); + return TCL_OK; +} + +void vtkTclDeleteCommandStruct(ClientData cd) +{ + vtkTclCommandStruct *cs = (vtkTclCommandStruct *)cd; + delete cs; +} + +void vtkTclCreateNew(Tcl_Interp *interp, const char *cname, + ClientData (*NewCommand)(), + int (*CommandFunction)(ClientData cd, + Tcl_Interp *interp, + int argc, char *argv[])) +{ + vtkTclCommandStruct *cs = new vtkTclCommandStruct; + cs->NewCommand = NewCommand; + cs->CommandFunction = CommandFunction; + Tcl_CreateCommand(interp,(char *) cname, + reinterpret_cast( + vtkTclNewInstanceCommand), + (ClientData *)cs, + (Tcl_CmdDeleteProc *)vtkTclDeleteCommandStruct); +} + + +vtkTclCommand::vtkTclCommand() +{ + this->Interp = NULL; + this->StringCommand = NULL; +} + +vtkTclCommand::~vtkTclCommand() +{ + if(this->StringCommand) { delete [] this->StringCommand; } +} + +void vtkTclCommand::SetStringCommand(const char *arg) +{ + if(this->StringCommand) { delete [] this->StringCommand; } + this->StringCommand = new char[strlen(arg)+1]; + strcpy(this->StringCommand, arg); +} + +void vtkTclCommand::Execute(vtkObject *, unsigned long, void *) +{ + int res; +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 2 + res = Tcl_GlobalEval(this->Interp, this->StringCommand); +#else + res = Tcl_EvalEx(this->Interp, this->StringCommand, -1, TCL_EVAL_GLOBAL); +#endif + + if (res == TCL_ERROR) + { + if (Tcl_GetVar(this->Interp,(char *) "errorInfo",0)) + { + vtkGenericWarningMacro("Error returned from vtk/tcl callback:\n" << + this->StringCommand << endl << + Tcl_GetVar(this->Interp,(char *) "errorInfo",0) << + " at line number " << this->Interp->errorLine); + } + else + { + vtkGenericWarningMacro("Error returned from vtk/tcl callback:\n" << + this->StringCommand << endl << + " at line number " << + this->Interp->errorLine); + } + } + else if (res == -1) + { + this->AbortFlagOn(); + } +} + +void vtkTclApplicationInitExecutable(int vtkNotUsed(argc), + const char* const argv[]) +{ + vtkstd::string av0 = vtksys::SystemTools::CollapseFullPath(argv[0]); + Tcl_FindExecutable(av0.c_str()); +} + +// We need two internal Tcl functions. They usually are declared in +// tclIntDecls.h, but UNIX builds do not have access to VTK's +// tkInternals include path. Since the signature has not changed for +// years (at least since 8.2), let's just prototype them. +EXTERN Tcl_Obj* TclGetLibraryPath _ANSI_ARGS_((void)); +EXTERN void TclSetLibraryPath _ANSI_ARGS_((Tcl_Obj * pathPtr)); + +void vtkTclApplicationInitTclTk(Tcl_Interp* interp, + const char* const relative_dirs[]) +{ + /* + Tcl/Tk requires support files to work (set of tcl files). + When an app is linked against Tcl/Tk shared libraries, the path to + the libraries is used by Tcl/Tk to search for its support files. + For example, on Windows, if bin/tcl84.dll is the shared lib, support + files will be searched in bin/../lib/tcl8.4, which is where they are + usually installed. + If an app is linked against Tcl/Tk *static* libraries, there is no + way for Tcl/Tk to find its support files. In that case, it will + use the TCL_LIBRARY and TK_LIBRARY environment variable (those should + point to the support files dir, ex: c:/tcl/lib/tcl8.4, c:/tk/lib/tcl8.4). + + The above code will also make Tcl/Tk search inside VTK's build/install + directory, more precisely inside a TclTk/lib sub dir. + ex: [path to vtk.exe]/TclTk/lib/tcl8.4, [path to vtk.exe]/TclTk/lib/tk8.4 + Support files are copied to that location when + VTK_TCL_TK_COPY_SUPPORT_LIBRARY is ON. + */ + + int has_tcllibpath_env = getenv("TCL_LIBRARY") ? 1 : 0; + int has_tklibpath_env = getenv("TK_LIBRARY") ? 1 : 0; + vtkstd::string selfdir; + if(!has_tcllibpath_env || !has_tklibpath_env) + { + const char* nameofexec = Tcl_GetNameOfExecutable(); + if(nameofexec && vtksys::SystemTools::FileExists(nameofexec)) + { + vtkstd::string name = nameofexec; + vtksys::SystemTools::ConvertToUnixSlashes(name); + selfdir = vtksys::SystemTools::GetFilenamePath(name); + } + } + if(selfdir.length() > 0) + { + if(!has_tcllibpath_env) + { + vtkstd::string tdir; + for(const char* const* p = relative_dirs; *p; ++p) + { + tdir = selfdir; + tdir += "/"; + tdir += *p; + tdir += "/tcl" TCL_VERSION; + tdir = vtksys::SystemTools::CollapseFullPath(tdir.c_str()); + if(vtksys::SystemTools::FileExists(tdir.c_str()) && + vtksys::SystemTools::FileIsDirectory(tdir.c_str())) + { + // Set the tcl_library Tcl variable. + char tcl_library[1024]; + strcpy(tcl_library, tdir.c_str()); + Tcl_SetVar(interp, "tcl_library", tcl_library, + TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG); + break; + } + } + } + if(!has_tklibpath_env) + { + vtkstd::string tdir; + for(const char* const* p = relative_dirs; *p; ++p) + { + tdir = selfdir; + tdir += "/"; + tdir += *p; + tdir += "/tk" TCL_VERSION; + tdir = vtksys::SystemTools::CollapseFullPath(tdir.c_str()); + if(vtksys::SystemTools::FileExists(tdir.c_str()) && + vtksys::SystemTools::FileIsDirectory(tdir.c_str())) + { + // Set the tk_library Tcl variable. + char tk_library[1024]; + strcpy(tk_library, tdir.c_str()); + Tcl_SetVar(interp, "tk_library", tk_library, + TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG); + break; + } + } + } + } +} diff --git a/Common/vtkTclUtil.h b/Common/vtkTclUtil.h new file mode 100644 index 0000000..4b4c656 --- /dev/null +++ b/Common/vtkTclUtil.h @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTclUtil.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __vtkTclInclude_h +#define __vtkTclInclude_h + +#include "vtkObject.h" +#include "vtkCommand.h" +#include "vtkTcl.h" + +#ifdef WIN32 +#define VTKTCL_EXPORT __declspec( dllexport ) +#else +#define VTKTCL_EXPORT +#endif + +extern VTKTCL_EXPORT void vtkTclUpdateCommand(Tcl_Interp *interp, + char *name, + vtkObject *obj); + +extern VTKTCL_EXPORT void vtkTclDeleteObjectFromHash(vtkObject *, + unsigned long eventId, + void *, void *); +extern VTKTCL_EXPORT void vtkTclGenericDeleteObject(ClientData cd); + +extern VTKTCL_EXPORT void +vtkTclGetObjectFromPointer(Tcl_Interp *interp, void *temp, + const char *targetType); + +extern VTKTCL_EXPORT void * +vtkTclGetPointerFromObject(const char *name, const char *result_type, + Tcl_Interp *interp, int &error); + +extern VTKTCL_EXPORT void vtkTclVoidFunc(void *); +extern VTKTCL_EXPORT void vtkTclVoidFuncArgDelete(void *); +extern VTKTCL_EXPORT void vtkTclListInstances(Tcl_Interp *interp, + ClientData arg); +extern VTKTCL_EXPORT int vtkTclInDelete(Tcl_Interp *interp); + +extern VTKTCL_EXPORT int vtkTclNewInstanceCommand(ClientData cd, + Tcl_Interp *interp, + int argc, char *argv[]); +extern VTKTCL_EXPORT void vtkTclDeleteCommandStruct(ClientData cd); +extern VTKTCL_EXPORT +void vtkTclCreateNew(Tcl_Interp *interp, const char *cname, + ClientData (*NewCommand)(), + int (*CommandFunction)(ClientData cd, + Tcl_Interp *interp, + int argc, char *argv[])); + +class vtkTclCommand : public vtkCommand +{ +public: + static vtkTclCommand *New() { return new vtkTclCommand; }; + + void SetStringCommand(const char *arg); + void SetInterp(Tcl_Interp *interp) { this->Interp = interp; }; + + void Execute(vtkObject *, unsigned long, void *); + + char *StringCommand; + Tcl_Interp *Interp; +protected: + vtkTclCommand(); + ~vtkTclCommand(); +}; + +typedef struct _vtkTclVoidFuncArg +{ + Tcl_Interp *interp; + char *command; +} vtkTclVoidFuncArg; + +struct vtkTclCommandArgStruct +{ + void *Pointer; + Tcl_Interp *Interp; + unsigned long Tag; +}; + +struct vtkTclCommandStruct +{ + ClientData (*NewCommand)(); + int (*CommandFunction)(ClientData cd, Tcl_Interp *interp, + int argc, char *argv[]); +}; + +struct vtkTclInterpStruct +{ + Tcl_HashTable InstanceLookup; + Tcl_HashTable PointerLookup; + Tcl_HashTable CommandLookup; + + int Number; + int DebugOn; + int InDelete; + int DeleteExistingObjectOnNew; +}; + +extern VTKTCL_EXPORT +void vtkTclApplicationInitExecutable(int argc, const char* const argv[]); +extern VTKTCL_EXPORT +void vtkTclApplicationInitTclTk(Tcl_Interp* interp, + const char* const relative_dirs[]); + +#endif + diff --git a/Common/vtkTemplateAliasMacro.h b/Common/vtkTemplateAliasMacro.h new file mode 100644 index 0000000..f27ba8f --- /dev/null +++ b/Common/vtkTemplateAliasMacro.h @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTemplateAliasMacro.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTemplateAliasMacro - Dispatch a scalar processing template. +// .SECTION Description +// vtkTemplateAliasMacro is used in a switch statement to +// automatically generate duplicate code for all enabled scalar types. +// The code can be written to use VTK_TT to refer to the type, and +// each case generated will define VTK_TT appropriately. The +// difference between this and the standard vtkTemplateMacro is that +// this version will set VTK_TT to an "alias" for each type. The +// alias may be the same type or may be a different type that is the +// same size/signedness. This is sufficient when only the numerical +// value associated with instances of the type is needed, and it +// avoids unnecessary template instantiations. +// +// Example usage: +// +// void* p = dataArray->GetVoidPointer(0); +// switch(dataArray->GetDataType()) +// { +// vtkTemplateAliasMacro(vtkMyTemplateFunction(static_cast(p))); +// } + +#ifndef __vtkTemplateAliasMacro_h +#define __vtkTemplateAliasMacro_h + +#include "vtkTypeTraits.h" + +// Allow individual switching of support for each scalar size/signedness. +// These could be made advanced user options to be configured by CMake. +#define VTK_USE_INT8 1 +#define VTK_USE_UINT8 1 +#define VTK_USE_INT16 1 +#define VTK_USE_UINT16 1 +#define VTK_USE_INT32 1 +#define VTK_USE_UINT32 1 +#define VTK_USE_INT64 1 +#define VTK_USE_UINT64 1 +#define VTK_USE_FLOAT32 1 +#define VTK_USE_FLOAT64 1 + +// Force UINT64 off if we cannot implement support for it. +#if defined(VTK_TYPE_USE___INT64) && !defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) +# undef VTK_USE_UINT64 +# define VTK_USE_UINT64 0 +#endif + +//-------------------------------------------------------------------------- + +// Define helper macros to switch types on and off. +#define vtkTemplateAliasMacroCase(typeN, call) \ + vtkTemplateAliasMacroCase0(typeN, call, VTK_TYPE_SIZED_##typeN) +#define vtkTemplateAliasMacroCase0(typeN, call, sized) \ + vtkTemplateAliasMacroCase1(typeN, call, sized) +#define vtkTemplateAliasMacroCase1(typeN, call, sized) \ + vtkTemplateAliasMacroCase2(typeN, call, VTK_USE_##sized) +#define vtkTemplateAliasMacroCase2(typeN, call, value) \ + vtkTemplateAliasMacroCase3(typeN, call, value) +#define vtkTemplateAliasMacroCase3(typeN, call, value) \ + vtkTemplateAliasMacroCase_##value(typeN, call) +#define vtkTemplateAliasMacroCase_0(typeN, call) \ + case VTK_##typeN: \ + { \ + vtkGenericWarningMacro("Support for VTK_" #typeN " not compiled."); \ + }; break +#define vtkTemplateAliasMacroCase_1(typeN, call) \ + case VTK_##typeN: \ + { \ + typedef vtkTypeTraits::SizedType VTK_TT; call; \ + }; break + +// Add "long long" to the template macro if it is enabled. +#if defined(VTK_TYPE_USE_LONG_LONG) +# define vtkTemplateAliasMacroCase_ll(typeN, call) \ + vtkTemplateAliasMacroCase(typeN, call); +#else +# define vtkTemplateAliasMacroCase_ll(typeN, call) +#endif + +// Add "__int64" to the template macro if it is enabled. +#if defined(VTK_TYPE_USE___INT64) +# define vtkTemplateAliasMacroCase_i64(typeN, call) \ + vtkTemplateAliasMacroCase(typeN, call); +#else +# define vtkTemplateAliasMacroCase_i64(typeN, call) +#endif + +// Define a macro to dispatch calls to a template instantiated over +// the aliased scalar types. +#define vtkTemplateAliasMacro(call) \ + vtkTemplateAliasMacroCase(DOUBLE, call); \ + vtkTemplateAliasMacroCase(FLOAT, call); \ + vtkTemplateAliasMacroCase_ll(LONG_LONG, call) \ + vtkTemplateAliasMacroCase_ll(UNSIGNED_LONG_LONG, call) \ + vtkTemplateAliasMacroCase_i64(__INT64, call) \ + vtkTemplateAliasMacroCase_i64(UNSIGNED___INT64, call) \ + vtkTemplateAliasMacroCase(ID_TYPE, call); \ + vtkTemplateAliasMacroCase(LONG, call); \ + vtkTemplateAliasMacroCase(UNSIGNED_LONG, call); \ + vtkTemplateAliasMacroCase(INT, call); \ + vtkTemplateAliasMacroCase(UNSIGNED_INT, call); \ + vtkTemplateAliasMacroCase(SHORT, call); \ + vtkTemplateAliasMacroCase(UNSIGNED_SHORT, call); \ + vtkTemplateAliasMacroCase(CHAR, call); \ + vtkTemplateAliasMacroCase(SIGNED_CHAR, call); \ + vtkTemplateAliasMacroCase(UNSIGNED_CHAR, call) + +#endif diff --git a/Common/vtkTensor.cxx b/Common/vtkTensor.cxx new file mode 100644 index 0000000..105edc5 --- /dev/null +++ b/Common/vtkTensor.cxx @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTensor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTensor.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkTensor, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkTensor); + +// Construct tensor initially pointing to internal storage. +vtkTensor::vtkTensor() +{ + this->T = this->Storage; + for (int j=0; j<3; j++) + { + for (int i=0; i<3; i++) + { + this->T[i+j*3] = 0.0; + } + } +} + +//---------------------------------------------------------------------------- +void vtkTensor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + for (int j=0; j<3; j++) + { + os << indent; + for (int i=0; i<3; i++) + { + os << this->Storage[i+j*3] << " "; + } + os << "\n"; + } +} diff --git a/Common/vtkTensor.h b/Common/vtkTensor.h new file mode 100644 index 0000000..fa24278 --- /dev/null +++ b/Common/vtkTensor.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTensor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTensor - supporting class to enable assignment and referencing of tensors +// .SECTION Description +// vtkTensor is a floating point representation of an nxn tensor. vtkTensor +// provides methods for assignment and reference of tensor components. It +// does it in such a way as to minimize data copying. +// +// .SECTION Caveats +// vtkTensor performs its operations using pointer reference. You are +// responsible for supplying data storage (if necessary) if local copies +// of data are being made. + +#ifndef __vtkTensor_h +#define __vtkTensor_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkTensor : public vtkObject +{ +public: + static vtkTensor *New(); + vtkTypeRevisionMacro(vtkTensor,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initialize tensor components to 0.0. + void Initialize(); + + // Description: + // Get the tensor component (i,j). + double GetComponent(int i, int j) {return this->T[i+3*j];}; + + // Description: + // Set the value of the tensor component (i,j). + void SetComponent(int i, int j, double v) {if (i > 2 || j > 2) {vtkErrorMacro("trying to set tensor component i or j > 2: i = " << i << ", j = " << j); return;}; this->T[i+3*j] = v;}; + + // Description: + // Add to the value of the tensor component at location (i,j). + void AddComponent(int i, int j, double v) { if (i > 2 || j > 2) {vtkErrorMacro("trying to add tensor component i or j > 2: i = " << i << ", j = " << j); return;}; this->T[i+3*j] += v;}; + + // Description: + // Return column vector from tensor. (Assumes 2D matrix form and 0-offset.) + double *GetColumn(int j) { if (j > 2) {vtkErrorMacro("trying to get tensor column j > 2: j = " << j); return NULL;}; return this->T + 3*j;}; + + // Description: + // Deep copy of one tensor to another tensor. + void DeepCopy(vtkTensor *t); + + // Description: + // Provide double * type conversion. + operator double*() {return this->T;}; + + // Description: + // Data member left public for efficiency. + double *T; + +protected: + vtkTensor(); + ~vtkTensor() {}; + + double Storage[9]; +private: + vtkTensor(const vtkTensor&); // Not implemented. + void operator=(const vtkTensor&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline void vtkTensor::Initialize() +{ + for (int j=0; j<3; j++) + { + for (int i=0; i<3; i++) + { + this->T[i+j*3] = 0.0; + } + } +} + +//---------------------------------------------------------------------------- +inline void vtkTensor::DeepCopy(vtkTensor *t) +{ + for (int j=0; j < 3; j++) + { + for (int i=0; i < 3; i++) + { + this->T[i+3*j] = t->T[i+3*j]; + } + } +} + +#endif diff --git a/Common/vtkThreadMessager.cxx b/Common/vtkThreadMessager.cxx new file mode 100644 index 0000000..23a5a63 --- /dev/null +++ b/Common/vtkThreadMessager.cxx @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThreadMessager.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkThreadMessager.h" + +#include "vtkObjectFactory.h" + +#ifdef VTK_USE_WIN32_THREADS +# include "vtkWindows.h" +#endif + +vtkCxxRevisionMacro(vtkThreadMessager, "$Revision: 1.3.12.1 $"); +vtkStandardNewMacro(vtkThreadMessager); + +vtkThreadMessager::vtkThreadMessager() +{ +#ifdef VTK_USE_WIN32_THREADS + this->WSignal = CreateEvent(0, FALSE, FALSE, 0); +#elif defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) + pthread_cond_init(&this->PSignal, 0); + pthread_mutex_init(&this->Mutex, 0); + pthread_mutex_lock(&this->Mutex); +#endif +} + +vtkThreadMessager::~vtkThreadMessager() +{ +#ifdef VTK_USE_WIN32_THREADS + CloseHandle(this->WSignal); +#elif defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) + pthread_mutex_unlock(&this->Mutex); + pthread_mutex_destroy(&this->Mutex); + pthread_cond_destroy(&this->PSignal); +#endif +} + +void vtkThreadMessager::WaitForMessage() +{ +#ifdef VTK_USE_WIN32_THREADS + WaitForSingleObject( this->WSignal, INFINITE ); +#elif defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) + pthread_cond_wait(&this->PSignal, &this->Mutex); +#endif +} + +//---------------------------------------------------------------------------- +void vtkThreadMessager::SendWakeMessage() +{ +#ifdef VTK_USE_WIN32_THREADS + SetEvent( this->WSignal ); +#elif defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) + pthread_cond_broadcast(&this->PSignal); +#endif +} + +void vtkThreadMessager::EnableWaitForReceiver() +{ +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) + pthread_mutex_lock(&this->Mutex); +#endif +} + +void vtkThreadMessager::WaitForReceiver() +{ +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) + pthread_mutex_lock(&this->Mutex); +#endif +} + +void vtkThreadMessager::DisableWaitForReceiver() +{ +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) + pthread_mutex_unlock(&this->Mutex); +#endif +} + +void vtkThreadMessager::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SendMessage +void vtkThreadMessager::SendMessageA() +{ + VTK_LEGACY_REPLACED_BODY(vtkThreadMessager::SendMessage, "VTK 5.0", + vtkThreadMessager::SendWakeMessage); + this->SendWakeMessage(); +} +void vtkThreadMessager::SendMessageW() +{ + VTK_LEGACY_REPLACED_BODY(vtkThreadMessager::SendMessage, "VTK 5.0", + vtkThreadMessager::SendWakeMessage); + this->SendWakeMessage(); +} +# endif +void vtkThreadMessager::SendMessage() +{ + VTK_LEGACY_REPLACED_BODY(vtkThreadMessager::SendMessage, "VTK 5.0", + vtkThreadMessager::SendWakeMessage); + this->SendWakeMessage(); +} +#endif diff --git a/Common/vtkThreadMessager.h b/Common/vtkThreadMessager.h new file mode 100644 index 0000000..27dd25c --- /dev/null +++ b/Common/vtkThreadMessager.h @@ -0,0 +1,107 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThreadMessager.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkThreadMessager - A class for performing inter-thread messaging +// .SECTION Description +// vtkMultithreader is a class that provides support for messaging between +// threads multithreaded using pthreads or Windows messaging. + +#ifndef __vtkThreadMessager_h +#define __vtkThreadMessager_h + +#include "vtkObject.h" + +#if defined(VTK_USE_PTHREADS) || defined(VTK_HP_PTHREADS) +#include // Needed for pthread types +#endif + +class VTK_COMMON_EXPORT vtkThreadMessager : public vtkObject +{ +public: + static vtkThreadMessager *New(); + + vtkTypeRevisionMacro(vtkThreadMessager,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Wait (block, non-busy) until another thread sends a + // message. + void WaitForMessage(); + + // Description: + // Send a message to all threads who are waiting via + // WaitForMessage(). + void SendWakeMessage(); + + // Description: + // pthreads only. If the wait is enabled, the thread who + // is to call WaitForMessage() will block until a receiver + // thread is ready to receive. + void EnableWaitForReceiver(); + + // Description: + // pthreads only. If the wait is enabled, the thread who + // is to call WaitForMessage() will block until a receiver + // thread is ready to receive. + void DisableWaitForReceiver(); + + // Description: + // pthreads only. + // If wait is enable, this will block until one thread is ready + // to receive a message. + void WaitForReceiver(); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define SendMessageA SendMessage +# define SendMessageW SendMessage +#endif + + // Description: + // @deprecated Replaced by vtkThreadMessager::SendWakeMessage() as of + // VTK 5.0. + VTK_LEGACY(void SendMessage()); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SendMessageW +# undef SendMessageA + //BTX + VTK_LEGACY(void SendMessageA()); + VTK_LEGACY(void SendMessageW()); + //ETX +#endif + +protected: + vtkThreadMessager(); + ~vtkThreadMessager(); + +#ifdef VTK_USE_PTHREADS + pthread_mutex_t Mutex; + pthread_cond_t PSignal; +#endif + +#ifdef VTK_USE_WIN32_THREADS + vtkWindowsHANDLE WSignal; +#endif + +private: + vtkThreadMessager(const vtkThreadMessager&); // Not implemented. + void operator=(const vtkThreadMessager&); // Not implemented. +}; + +#endif + + + + + diff --git a/Common/vtkTimeStamp.cxx b/Common/vtkTimeStamp.cxx new file mode 100644 index 0000000..01feb17 --- /dev/null +++ b/Common/vtkTimeStamp.cxx @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTimeStamp.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// Initialize static member +// +#include "vtkTimeStamp.h" + +#include "vtkCriticalSection.h" +#include "vtkObjectFactory.h" +#include "vtkWindows.h" + +//------------------------------------------------------------------------- +vtkTimeStamp* vtkTimeStamp::New() +{ + // If the factory was unable to create the object, then create it here. + return new vtkTimeStamp; +} + +//------------------------------------------------------------------------- +void vtkTimeStamp::Modified() +{ +#if defined(WIN32) || defined(_WIN32) + static LONG vtkTimeStampTime = 0; + + this->ModifiedTime = (unsigned long)InterlockedIncrement(&vtkTimeStampTime); +#else + static unsigned long vtkTimeStampTime = 0; + static vtkSimpleCriticalSection TimeStampCritSec; + + TimeStampCritSec.Lock(); + this->ModifiedTime = ++vtkTimeStampTime; + TimeStampCritSec.Unlock(); +#endif +} + + + + + + + + + diff --git a/Common/vtkTimeStamp.h b/Common/vtkTimeStamp.h new file mode 100644 index 0000000..2f8f4e2 --- /dev/null +++ b/Common/vtkTimeStamp.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTimeStamp.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTimeStamp - record modification and/or execution time +// .SECTION Description +// vtkTimeStamp records a unique time when the method Modified() is +// executed. This time is guaranteed to be monotonically increasing. +// Classes use this object to record modified and/or execution time. +// There is built in support for the binary < and > comparison +// operators between two vtkTimeStamp objects. + +#ifndef __vtkTimeStamp_h +#define __vtkTimeStamp_h + +#include "vtkSystemIncludes.h" + +class VTK_COMMON_EXPORT vtkTimeStamp +{ +public: + vtkTimeStamp() {this->ModifiedTime = 0;}; + static vtkTimeStamp *New(); + void Delete() {delete this;}; + + // Description: + // Set this objects time to the current time. The current time is + // just a monotonically increasing unsigned long integer. It is + // possible for this number to wrap around back to zero. + // This should only happen for processes that have been running + // for a very long time, while constantly changing objects + // within the program. When this does occur, the typical consequence + // should be that some filters will update themselves when really + // they don't need to. + void Modified(); + + // Description: + // Return this object's Modified time. + unsigned long int GetMTime() {return this->ModifiedTime;}; + + // Description: + // Support comparisons of time stamp objects directly. + int operator>(vtkTimeStamp& ts) { + return (this->ModifiedTime > ts.ModifiedTime);}; + int operator<(vtkTimeStamp& ts) { + return (this->ModifiedTime < ts.ModifiedTime);}; + + // Description: + // Allow for typecasting to unsigned long. + operator unsigned long() {return this->ModifiedTime;}; + +private: + unsigned long ModifiedTime; +}; + +#endif diff --git a/Common/vtkTimerLog.cxx b/Common/vtkTimerLog.cxx new file mode 100644 index 0000000..5928e88 --- /dev/null +++ b/Common/vtkTimerLog.cxx @@ -0,0 +1,676 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTimerLog.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTimerLog - Maintains timing table for performance analysis +// .SECTION Description +// vtkTimerLog contains walltime and cputime measurements associated +// with a given event. These results can be later analyzed when +// "dumping out" the table. +// +// In addition, vtkTimerLog allows the user to simply get the current +// time, and to start/stop a simple timer separate from the timing +// table logging. + +#include "vtkTimerLog.h" + +#include // Needed for ... + +#ifndef _WIN32 +#include // for CLK_TCK +#include +#include +#endif + +#ifndef _WIN32_WCE +#include +#include +#endif +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkTimerLog, "$Revision: 1.42.12.1 $"); +vtkStandardNewMacro(vtkTimerLog); + +// Create a singleton to cleanup the table. No other singletons +// should be using the timer log, so it is safe to do this without the +// full ClassInitialize/ClassFinalize idiom. +class vtkTimerLogCleanup +{ +public: + ~vtkTimerLogCleanup() + { + vtkTimerLog::CleanupLog(); + } +}; +static vtkTimerLogCleanup vtkTimerLogCleanupInstance; + +// initialze the class variables +int vtkTimerLog::Logging = 1; +int vtkTimerLog::Indent = 0; +int vtkTimerLog::MaxEntries = 100; +int vtkTimerLog::NextEntry = 0; +int vtkTimerLog::WrapFlag = 0; +vtkTimerLogEntry *vtkTimerLog::TimerLog = NULL; + +#ifdef CLK_TCK +int vtkTimerLog::TicksPerSecond = CLK_TCK; +#else +int vtkTimerLog::TicksPerSecond = 60; +#endif + +#ifndef CLOCKS_PER_SEC +#define CLOCKS_PER_SEC (vtkTimerLog::TicksPerSecond) +#endif + + +#ifdef _WIN32 +#ifndef _WIN32_WCE +timeb vtkTimerLog::FirstWallTime; +timeb vtkTimerLog::CurrentWallTime; +#else +FILETIME vtkTimerLog::FirstWallTime; +FILETIME vtkTimerLog::CurrentWallTime; +#endif +#else +timeval vtkTimerLog::FirstWallTime; +timeval vtkTimerLog::CurrentWallTime; +tms vtkTimerLog::FirstCpuTicks; +tms vtkTimerLog::CurrentCpuTicks; +#endif + +//---------------------------------------------------------------------------- +// Allocate timing table with MaxEntries elements. +void vtkTimerLog::AllocateLog() +{ + if (vtkTimerLog::TimerLog != NULL) + { + delete [] vtkTimerLog::TimerLog; + } + vtkTimerLog::TimerLog = new vtkTimerLogEntry[vtkTimerLog::MaxEntries]; +} + +//---------------------------------------------------------------------------- +// Remove timer log. +void vtkTimerLog::CleanupLog() +{ + if ( !vtkTimerLog::TimerLog ) + { + return; + } + delete [] vtkTimerLog::TimerLog; + vtkTimerLog::TimerLog = 0; +} + +//---------------------------------------------------------------------------- +// Clear the timing table. walltime and cputime will also be set +// to zero when the first new event is recorded. +void vtkTimerLog::ResetLog() +{ + vtkTimerLog::WrapFlag = 0; + vtkTimerLog::NextEntry = 0; + // may want to free TimerLog to force realloc so + // that user can resize the table by changing MaxEntries. +} + + +//---------------------------------------------------------------------------- +// Record a timing event. The event is represented by a formatted +// string. +void vtkTimerLog::FormatAndMarkEvent(const char *format, ...) +{ + if (! vtkTimerLog::Logging) + { + return; + } + + static char event[4096]; + va_list var_args; + va_start(var_args, format); + vsprintf(event, format, var_args); + va_end(var_args); + + vtkTimerLog::MarkEvent(event); +} + + +//---------------------------------------------------------------------------- +// Record a timing event and capture walltime and cputicks. +void vtkTimerLog::MarkEvent(const char *event) +{ + if (! vtkTimerLog::Logging) + { + return; + } + + int strsize; + double time_diff; + int ticks_diff; + + strsize = (strlen(event)) > VTK_LOG_EVENT_LENGTH - 1 + ? VTK_LOG_EVENT_LENGTH-1 : static_cast(strlen(event)); + + // If this the first event we're recording, allocate the + // internal timing table and initialize WallTime and CpuTicks + // for this first event to zero. + if (vtkTimerLog::NextEntry == 0 && ! vtkTimerLog::WrapFlag) + { + if (vtkTimerLog::TimerLog == NULL) + { + vtkTimerLog::AllocateLog(); + } + +#ifdef _WIN32 +#ifdef _WIN32_WCE + SYSTEMTIME st; + GetLocalTime(&st); + SystemTimeToFileTime(&st, &(vtkTimerLog::FirstWallTime)); +#else + ::ftime( &(vtkTimerLog::FirstWallTime) ); +#endif +#else + gettimeofday( &(vtkTimerLog::FirstWallTime), NULL ); + times(&FirstCpuTicks); +#endif + + vtkTimerLog::TimerLog[0].Indent = vtkTimerLog::Indent; + vtkTimerLog::TimerLog[0].WallTime = 0.0; + vtkTimerLog::TimerLog[0].CpuTicks = 0; + strncpy(vtkTimerLog::TimerLog[0].Event, event, strsize); + vtkTimerLog::TimerLog[0].Event[strsize] = '\0'; + vtkTimerLog::NextEntry = 1; + return; + } + +#ifdef _WIN32 +#ifdef _WIN32_WCE + SYSTEMTIME st; + GetLocalTime(&st); + SystemTimeToFileTime(&st, &(vtkTimerLog::CurrentWallTime)); + time_diff = (vtkTimerLog::CurrentWallTime.dwHighDateTime - + vtkTimerLog::FirstWallTime.dwHighDateTime); + time_diff = time_diff * 429.4967296; + time_diff = time_diff + ((vtkTimerLog::CurrentWallTime.dwLowDateTime - + vtkTimerLog::FirstWallTime.dwLowDateTime) / 10000000.0); +#else + static double scale = 1.0/1000.0; + ::ftime( &(vtkTimerLog::CurrentWallTime) ); + time_diff = + vtkTimerLog::CurrentWallTime.time - vtkTimerLog::FirstWallTime.time; + time_diff += + (vtkTimerLog::CurrentWallTime.millitm + - vtkTimerLog::FirstWallTime.millitm) * scale; +#endif + ticks_diff = 0; +#else + static double scale = 1.0/1000000.0; + gettimeofday( &(vtkTimerLog::CurrentWallTime), NULL ); + time_diff = vtkTimerLog::CurrentWallTime.tv_sec + - vtkTimerLog::FirstWallTime.tv_sec; + time_diff += + (vtkTimerLog::CurrentWallTime.tv_usec + - vtkTimerLog::FirstWallTime.tv_usec) * scale; + + times(&CurrentCpuTicks); + ticks_diff = (CurrentCpuTicks.tms_utime + CurrentCpuTicks.tms_stime) - + (FirstCpuTicks.tms_utime + FirstCpuTicks.tms_stime); +#endif + + vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].Indent = vtkTimerLog::Indent; + vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].WallTime = (double)time_diff; + vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].CpuTicks = ticks_diff; + strncpy(vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].Event, event, strsize); + vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].Event[strsize] = '\0'; + + vtkTimerLog::NextEntry++; + if (vtkTimerLog::NextEntry == vtkTimerLog::MaxEntries) + { + vtkTimerLog::NextEntry = 0; + vtkTimerLog::WrapFlag = 1; + } +} + + +//---------------------------------------------------------------------------- +// Record a timing event and capture walltime and cputicks. +// Increments indent after mark. +void vtkTimerLog::MarkStartEvent(const char *event) +{ + if (! vtkTimerLog::Logging) + { // Maybe we should still change the Indent ... + return; + } + + vtkTimerLog::MarkEvent(event); + ++vtkTimerLog::Indent; +} + +//---------------------------------------------------------------------------- +// Record a timing event and capture walltime and cputicks. +// Decrements indent after mark. +void vtkTimerLog::MarkEndEvent(const char *event) +{ + if (! vtkTimerLog::Logging) + { // Maybe we should still change the Indent ... + return; + } + + vtkTimerLog::MarkEvent(event); + --vtkTimerLog::Indent; +} + +//---------------------------------------------------------------------------- +// Record a timing event and capture walltime and cputicks. +int vtkTimerLog::GetNumberOfEvents() +{ + if (vtkTimerLog::WrapFlag) + { + return vtkTimerLog::MaxEntries; + } + else + { + return vtkTimerLog::NextEntry; + } +} + + +//---------------------------------------------------------------------------- +vtkTimerLogEntry *vtkTimerLog::GetEvent(int idx) +{ + int num = vtkTimerLog::GetNumberOfEvents(); + int start = 0; + if (vtkTimerLog::WrapFlag) + { + start = vtkTimerLog::NextEntry; + } + + if (idx < 0 || idx >= num) + { + cerr << "Bad entry index."; + return NULL; + } + idx = (idx + start) % vtkTimerLog::MaxEntries; + + return vtkTimerLog::TimerLog + idx; +} + + +//---------------------------------------------------------------------------- +int vtkTimerLog::GetEventIndent(int idx) +{ + vtkTimerLogEntry *tmp = vtkTimerLog::GetEvent(idx); + + if (tmp) + { + return tmp->Indent; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +double vtkTimerLog::GetEventWallTime(int idx) +{ + vtkTimerLogEntry *tmp = vtkTimerLog::GetEvent(idx); + + if (tmp) + { + return tmp->WallTime; + } + else + { + return 0.0; + } +} + +//---------------------------------------------------------------------------- +const char* vtkTimerLog::GetEventString(int idx) +{ + vtkTimerLogEntry *tmp = vtkTimerLog::GetEvent(idx); + + if (tmp) + { + return tmp->Event; + } + else + { + return NULL; + } +} + + +//---------------------------------------------------------------------------- +// Write the timing table out to a file. Calculate some helpful +// statistics (deltas and percentages) in the process. +void vtkTimerLog::DumpLogWithIndents(ostream *os, double threshold) +{ +#ifndef _WIN32_WCE + int num; + int i1, i2, j; + int indent1; + int nextIndent; + double dtime; + + num = vtkTimerLog::GetNumberOfEvents(); + + for (i1=0; i1 < num; i1++) + { + indent1 = vtkTimerLog::GetEventIndent(i1); + + // Search for an end event. + i2 = i1 + 1; + while (i2 < num && vtkTimerLog::GetEventIndent(i2) > indent1) + { // This was a start event. + ++i2; + } + // If the next indent is smaller, then the event should be an end event. + if (i2 == num) + { + nextIndent = vtkTimerLog::Indent; + } + else + { + nextIndent = vtkTimerLog::GetEventIndent(i2); + } + + // Backup one to get the end event. + --i2; + + // Simple events and end events will have dtime of 0. + dtime = vtkTimerLog::GetEventWallTime(i2) - vtkTimerLog::GetEventWallTime(i1); + if (nextIndent == indent1) + { // not an end event + if (dtime >= threshold || i2 == i1) + { // start event past threshold or singleton event. + // Print the indent. + j = indent1; + while (j-- > 0) + { + *os << " "; + } + *os << vtkTimerLog::GetEventString(i1); + if (i2 > i1) + { // Start event. + *os << ", " << dtime << " seconds\n"; + } + else + { // Singlton event. + *os << endl; + } + } + } + } + +#endif +} + +//---------------------------------------------------------------------------- +// Write the timing table out to a file. Calculate some helpful +// statistics (deltas and percentages) in the process. +void vtkTimerLog::DumpLog(const char *filename) +{ +#ifndef _WIN32_WCE + ofstream os_with_warning_C4701(filename); + int i; + + if ( vtkTimerLog::WrapFlag ) + { + vtkTimerLog::DumpEntry(os_with_warning_C4701, 0, + vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].WallTime, 0, + vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].CpuTicks, 0, + vtkTimerLog::TimerLog[vtkTimerLog::NextEntry].Event); + for (i=vtkTimerLog::NextEntry+1; iSuperclass::PrintSelf(os, indent); + + int i; + + os << indent << "MaxEntries: " << vtkTimerLog::MaxEntries << "\n"; + os << indent << "NextEntry: " << vtkTimerLog::NextEntry << "\n"; + os << indent << "WrapFlag: " << vtkTimerLog::WrapFlag << "\n"; + os << indent << "TicksPerSecond: " << vtkTimerLog::TicksPerSecond << "\n"; + os << "\n"; + + os << indent << "Entry \tWall Time\tCpuTicks\tEvent\n"; + os << indent << "----------------------------------------------\n"; + + if ( vtkTimerLog::WrapFlag ) + { + for (i=vtkTimerLog::NextEntry; iStartTime << "\n"; + os << indent << "WrapFlag: " << vtkTimerLog::WrapFlag << "\n"; +} + + +// Methods to support simple timer functionality, separate from +// timer table logging. + +//---------------------------------------------------------------------------- +// Returns the elapsed number of seconds since January 1, 1970. This +// is also called Universal Coordinated Time. +double vtkTimerLog::GetUniversalTime() +{ + double currentTimeInSeconds; + +#ifdef _WIN32 +#ifdef _WIN32_WCE + FILETIME CurrentTime; + SYSTEMTIME st; + GetLocalTime(&st); + SystemTimeToFileTime(&st, &CurrentTime); + currentTimeInSeconds = CurrentTime.dwHighDateTime; + currentTimeInSeconds *= 429.4967296; + currentTimeInSeconds = currentTimeInSeconds + + CurrentTime.dwLowDateTime / 10000000.0; +#else + timeb CurrentTime; + static double scale = 1.0/1000.0; + ::ftime( &CurrentTime ); + currentTimeInSeconds = CurrentTime.time + scale * CurrentTime.millitm; +#endif +#else + timeval CurrentTime; + static double scale = 1.0/1000000.0; + gettimeofday( &CurrentTime, NULL ); + currentTimeInSeconds = CurrentTime.tv_sec + scale * CurrentTime.tv_usec; +#endif + + return (currentTimeInSeconds); +} + +double vtkTimerLog::GetCPUTime() +{ + double currentCPUTime = 1.0; +#ifndef _WIN32_WCE + currentCPUTime = (double)clock() / (double)CLOCKS_PER_SEC; +#endif + return currentCPUTime; +} + +//---------------------------------------------------------------------------- +// Set the StartTime to the current time. Used with GetElapsedTime(). +void vtkTimerLog::StartTimer() +{ + this->StartTime = vtkTimerLog::GetUniversalTime(); +} + +//---------------------------------------------------------------------------- +// Sets EndTime to the current time. Used with GetElapsedTime(). +void vtkTimerLog::StopTimer() +{ + this->EndTime = vtkTimerLog::GetUniversalTime(); +} + +//---------------------------------------------------------------------------- +// Returns the difference between StartTime and EndTime as +// a floating point value indicating the elapsed time in seconds. +double vtkTimerLog::GetElapsedTime() +{ + return (this->EndTime - this->StartTime); +} + +//---------------------------------------------------------------------------- +void vtkTimerLog::DumpEntry(ostream& os, int index, double ttime, + double deltatime, + int tick, int deltatick, const char *event) +{ + os << index << " " + << ttime << " " + << deltatime << " " + << (double)tick/vtkTimerLog::TicksPerSecond << " " + << (double)deltatick/vtkTimerLog::TicksPerSecond << " "; + if (deltatime == 0.0) + { + os << "0.0 "; + } + else + { + os << 100.0*deltatick/vtkTimerLog::TicksPerSecond/deltatime << " "; + } + os << event << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkTimerLog::SetMaxEntries(int a) +{ + int num, i, offset; + vtkTimerLogEntry *newLog, *tmp; + + if (vtkTimerLog::MaxEntries == a) + { + return; + } + + newLog = new vtkTimerLogEntry[a]; + if (vtkTimerLog::TimerLog == NULL) + { + vtkTimerLog::MaxEntries = a; + vtkTimerLog::TimerLog = newLog; + return; + } + + // Copy the old log to the new. + num = vtkTimerLog::GetNumberOfEvents(); + offset = 0; + if (a < num) + { + offset = num - a; + num = a; + } + + for (i = 0; i < num; ++i) + { + tmp = vtkTimerLog::GetEvent(i+offset); + newLog[i] = *tmp; + } + + delete [] vtkTimerLog::TimerLog; + vtkTimerLog::MaxEntries = a; + vtkTimerLog::TimerLog = newLog; + vtkTimerLog::WrapFlag = 0; + vtkTimerLog::NextEntry = num; +} + + +//---------------------------------------------------------------------------- +int vtkTimerLog::GetMaxEntries() +{ + return vtkTimerLog::MaxEntries; +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetCurrentTime +double vtkTimerLog::GetTickCount() +{ + VTK_LEGACY_REPLACED_BODY(vtkTimerLog::GetCurrentTime, "VTK 5.0", + vtkTimerLog::GetUniversalTime); + return vtkTimerLog::GetUniversalTime(); +} +# endif +double vtkTimerLog::GetCurrentTime() +{ + VTK_LEGACY_REPLACED_BODY(vtkTimerLog::GetCurrentTime, "VTK 5.0", + vtkTimerLog::GetUniversalTime); + return vtkTimerLog::GetUniversalTime(); +} +#endif diff --git a/Common/vtkTimerLog.h b/Common/vtkTimerLog.h new file mode 100644 index 0000000..13d246e --- /dev/null +++ b/Common/vtkTimerLog.h @@ -0,0 +1,233 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTimerLog.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTimerLog - Timer support and logging +// .SECTION Description +// vtkTimerLog contains walltime and cputime measurements associated +// with a given event. These results can be later analyzed when +// "dumping out" the table. +// +// In addition, vtkTimerLog allows the user to simply get the current +// time, and to start/stop a simple timer separate from the timing +// table logging. + +#ifndef __vtkTimerLog_h +#define __vtkTimerLog_h + +#include "vtkObject.h" + +#ifdef _WIN32 +#ifndef _WIN32_WCE +#include // Needed for Win32 implementation of timer +#include // Needed for Win32 implementation of timer +#endif +#else +#include // Needed for unix implementation of timer +#include // Needed for unix implementation of timer +#include // Needed for unix implementation of timer +#include // Needed for unix implementation of timer +#endif + +// var args +#ifndef _WIN32 +#include // Needed for unix implementation of timer +#endif + +// select stuff here is for sleep method +#ifndef NO_FD_SET +# define SELECT_MASK fd_set +#else +# ifndef _AIX + typedef long fd_mask; +# endif +# if defined(_IBMR2) +# define SELECT_MASK void +# else +# define SELECT_MASK int +# endif +#endif + + +#define VTK_LOG_EVENT_LENGTH 40 + +//BTX +typedef struct +{ + double WallTime; + int CpuTicks; + char Event[VTK_LOG_EVENT_LENGTH]; + unsigned char Indent; +} vtkTimerLogEntry; +//ETX + +class VTK_COMMON_EXPORT vtkTimerLog : public vtkObject +{ +public: + static vtkTimerLog *New(); + + vtkTypeRevisionMacro(vtkTimerLog,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This flag will turn loging of events off or on. + // By default, logging is on. + static void SetLogging(int v) {vtkTimerLog::Logging = v;} + static int GetLogging() {return vtkTimerLog::Logging;} + static void LoggingOn() {vtkTimerLog::SetLogging(1);} + static void LoggingOff() {vtkTimerLog::SetLogging(0);} + + // Description: + // Set/Get the maximum number of entries allowed in the timer log + static void SetMaxEntries(int a); + static int GetMaxEntries(); + +//BTX + // Description: + // Record a timing event. The event is represented by a formatted + // string. + static void FormatAndMarkEvent(const char *EventString, ...); +//ETX + + // Description: + // Write the timing table out to a file. Calculate some helpful + // statistics (deltas and percentages) in the process. + static void DumpLog(const char *filename); + + // Description: + // I want to time events, so I am creating this interface to + // mark events that have a start and an end. These events can be, + // nested. The standard Dumplog ignores the indents. + static void MarkStartEvent(const char *EventString); + static void MarkEndEvent(const char *EventString); +//BTX + static void DumpLogWithIndents(ostream *os, double threshold); +//ETX + + // Description: + // Programatic access to events. Indexed from 0 to num-1. + static int GetNumberOfEvents(); + static int GetEventIndent(int i); + static double GetEventWallTime(int i); + static const char* GetEventString(int i); + + // Description: + // Record a timing event and capture wall time and cpu ticks. + static void MarkEvent(const char *EventString); + + // Description: + // Clear the timing table. walltime and cputime will also be set + // to zero when the first new event is recorded. + static void ResetLog(); + + // Description: + // Allocate timing table with MaxEntries elements. + static void AllocateLog(); + + // Description: + // Remove timer log. + static void CleanupLog(); + + // Description: + // Returns the elapsed number of seconds since January 1, 1970. This + // is also called Universal Coordinated Time. + static double GetUniversalTime(); + + // Description: + // Returns the CPU time for this process + // On Win32 platforms this actually returns wall time. + static double GetCPUTime(); + + // Description: + // Set the StartTime to the current time. Used with GetElapsedTime(). + void StartTimer(); + + // Description: + // Sets EndTime to the current time. Used with GetElapsedTime(). + void StopTimer(); + + // Description: + // Returns the difference between StartTime and EndTime as + // a doubleing point value indicating the elapsed time in seconds. + double GetElapsedTime(); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define GetTickCount GetCurrentTime +#endif + + // Description: + // @deprecated Replaced by vtkTimerLog::GetUniversalTime() as of VTK 5.0. + VTK_LEGACY(static double GetCurrentTime()); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetTickCount + //BTX + VTK_LEGACY(static double GetTickCount()); + //ETX +#endif + +protected: + vtkTimerLog() {this->StartTime=0; this->EndTime = 0;}; //insure constructor/destructor protected + virtual ~vtkTimerLog() { }; + + static vtkTimerLogEntry* GetEvent(int i); + + static int Logging; + static int Indent; + static int MaxEntries; + static int NextEntry; + static int WrapFlag; + static int TicksPerSecond; + static vtkTimerLogEntry *TimerLog; + +#ifdef _WIN32 +#ifndef _WIN32_WCE + static timeb FirstWallTime; + static timeb CurrentWallTime; +#else + static FILETIME FirstWallTime; + static FILETIME CurrentWallTime; +#endif +#else + static timeval FirstWallTime; + static timeval CurrentWallTime; + static tms FirstCpuTicks; + static tms CurrentCpuTicks; +#endif + + // instance variables to support simple timing functionality, + // separate from timer table logging. + double StartTime; + double EndTime; + + //BTX + static void DumpEntry(ostream& os, int index, double time, double deltatime, + int tick, int deltatick, const char *event); + //ETX + +private: + vtkTimerLog(const vtkTimerLog&); // Not implemented. + void operator=(const vtkTimerLog&); // Not implemented. +}; + + +// +// Set built-in type. Creates member Set"name"() (e.g., SetVisibility()); +// +#define vtkTimerLogMacro(string) \ + { \ + vtkTimerLog::FormatAndMarkEvent("Mark: In %s, line %d, class %s: %s", \ + __FILE__, __LINE__, this->GetClassName(), string); \ + } + +#endif diff --git a/Common/vtkTk.h b/Common/vtkTk.h new file mode 100644 index 0000000..fe77d09 --- /dev/null +++ b/Common/vtkTk.h @@ -0,0 +1,28 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTk.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkTk_h +#define __vtkTk_h + +#include "vtkConfigure.h" + +#ifdef VTK_TCL_TK_STATIC +# ifndef STATIC_BUILD +# define STATIC_BUILD +# endif +#endif + +#include + +#endif diff --git a/Common/vtkTransform.cxx b/Common/vtkTransform.cxx new file mode 100644 index 0000000..4cabffb --- /dev/null +++ b/Common/vtkTransform.cxx @@ -0,0 +1,539 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransform.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkTransform, "$Revision: 1.106 $"); +vtkStandardNewMacro(vtkTransform); + +//---------------------------------------------------------------------------- +vtkTransform::vtkTransform() +{ + this->Input = NULL; + + // most of the functionality is provided by the concatenation + this->Concatenation = vtkTransformConcatenation::New(); + + // the stack will be allocated the first time Push is called + this->Stack = NULL; + + // initialize the legacy 'Point' info + this->Point[0] = this->Point[1] = this->Point[2] = this->Point[3] = 0.0; + this->DoublePoint[0] = + this->DoublePoint[1] = this->DoublePoint[2] = this->DoublePoint[3] = 0.0; + + // save the original matrix MTime as part of a hack to support legacy code + this->MatrixUpdateMTime = this->Matrix->GetMTime(); +} + +//---------------------------------------------------------------------------- +vtkTransform::~vtkTransform() +{ + this->SetInput(NULL); + + if (this->Concatenation) + { + this->Concatenation->Delete(); + } + if (this->Stack) + { + this->Stack->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Update(); + + this->Superclass::PrintSelf(os, indent); + os << indent << "Input: (" << this->Input << ")\n"; + os << indent << "InverseFlag: " << this->GetInverseFlag() << "\n"; + os << indent << "NumberOfConcatenatedTransforms: " << + this->GetNumberOfConcatenatedTransforms() << "\n"; + if (this->GetNumberOfConcatenatedTransforms() != 0) + { + int n = this->GetNumberOfConcatenatedTransforms(); + for (int i = 0; i < n; i++) + { + vtkLinearTransform *t = this->GetConcatenatedTransform(i); + os << indent << " " << i << ": " << t->GetClassName() << " at " << + t << "\n"; + } + } + + os << indent << "DoublePoint: " << "( " << + this->DoublePoint[0] << ", " << this->DoublePoint[1] << ", " << + this->DoublePoint[2] << ", " << this->DoublePoint[3] << ")\n"; + + os << indent << "Point: " << "( " << + this->Point[0] << ", " << this->Point[1] << ", " << + this->Point[2] << ", " << this->Point[3] << ")\n"; +} + +//---------------------------------------------------------------------------- +void vtkTransform::Identity() +{ + this->Concatenation->Identity(); + this->Modified(); + + // support for the legacy hack in InternalUpdate + if (this->Matrix->GetMTime() > this->MatrixUpdateMTime) + { + this->Matrix->Identity(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransform::Inverse() +{ + this->Concatenation->Inverse(); + this->Modified(); + + // for the legacy hack in InternalUpdate + if (this->Matrix->GetMTime() > this->MatrixUpdateMTime) + { + this->Matrix->Invert(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransform::InternalDeepCopy(vtkAbstractTransform *gtrans) +{ + vtkTransform *transform = (vtkTransform *)gtrans; + + // copy the input + this->SetInput(transform->Input); + + // copy the concatenation + this->Concatenation->DeepCopy(transform->Concatenation); + + // copy the stack + if (transform->Stack) + { + if (this->Stack == NULL) + { + this->Stack = vtkTransformConcatenationStack::New(); + } + this->Stack->DeepCopy(transform->Stack); + } + else + { + if (this->Stack) + { + this->Stack->Delete(); + this->Stack = NULL; + } + } + + // legacy stuff: copy Point and DoublePoint + for (int j = 0; j < 3; j++) + { + this->Point[j] = transform->Point[j]; + this->DoublePoint[j] = transform->DoublePoint[j]; + } + + // to support the legacy hack in InternalUpdate + this->Matrix->DeepCopy(transform->Matrix); + this->MatrixUpdateMTime = this->Matrix->GetMTime(); +#ifndef VTK_LEGACY_REMOVE + if (transform->Matrix->GetMTime() > transform->MatrixUpdateMTime) + { // this copies the legacy hack flag to the transform + vtkWarningMacro(<<"InternalDeepCopy: Legacy Hack deprecated in VTK 4.2. May be removed in a future version."); + this->MatrixUpdateMTime--; + } +#endif +} + +//---------------------------------------------------------------------------- +void vtkTransform::InternalUpdate() +{ + int i; + int nTransforms = this->Concatenation->GetNumberOfTransforms(); + int nPreTransforms = this->Concatenation->GetNumberOfPreTransforms(); + + // check to see whether someone has been fooling around with our matrix + int doTheLegacyHack = 0; + if (this->Matrix->GetMTime() > this->MatrixUpdateMTime) + { + vtkDebugMacro(<<"InternalUpdate: this->Matrix was modified by something other than 'this'"); + + // check to see if we have any inputs or concatenated transforms + int isPipelined = (this->Input != 0); + for (i = 0; i < nTransforms && !isPipelined; i++) + { // the vtkSimpleTransform is just a matrix placeholder, + // it is not a real transform + isPipelined = + !this->Concatenation->GetTransform(i)->IsA("vtkSimpleTransform"); + } + // do the legacy hack only if we have no input transforms + doTheLegacyHack = !isPipelined; + } + + // copy matrix from input + if (this->Input) + { + this->Matrix->DeepCopy(this->Input->GetMatrix()); + // if inverse flag is set, invert the matrix + if (this->Concatenation->GetInverseFlag()) + { + this->Matrix->Invert(); + } + } + else if (doTheLegacyHack) + { + vtkWarningMacro("InternalUpdate: doing hack to support legacy code. " + "This is deprecated in VTK 4.2. May be removed in a " + "future version."); + // this heuristic works perfectly if GetMatrix() or GetMatrixPointer() + // was called immediately prior to the matrix modifications + // (fortunately, this is almost always the case) + if (this->Matrix->GetMTime() > this->Concatenation->GetMaxMTime()) + { // don't apply operations that occurred after matrix modification + nPreTransforms = nTransforms = 0; + } + } + else + { // otherwise, we start with the identity transform as our base + this->Matrix->Identity(); + } + + // concatenate PreTransforms + for (i = nPreTransforms-1; i >= 0; i--) + { + vtkHomogeneousTransform *transform = + (vtkHomogeneousTransform *)this->Concatenation->GetTransform(i); + vtkMatrix4x4::Multiply4x4(this->Matrix,transform->GetMatrix(), + this->Matrix); + } + + // concatenate PostTransforms + for (i = nPreTransforms; i < nTransforms; i++) + { + vtkHomogeneousTransform *transform = + (vtkHomogeneousTransform *)this->Concatenation->GetTransform(i); + vtkMatrix4x4::Multiply4x4(transform->GetMatrix(),this->Matrix, + this->Matrix); + } + + if (doTheLegacyHack) + { // the transform operations have been incorporated into the matrix, + // so delete them + this->Concatenation->Identity(); + } + else + { // having this in the 'else' forces the legacy flag to be sticky + this->MatrixUpdateMTime = this->Matrix->GetMTime(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransform::Concatenate(vtkLinearTransform *transform) +{ + if (transform->CircuitCheck(this)) + { + vtkErrorMacro("Concatenate: this would create a circular reference."); + return; + } + this->Concatenation->Concatenate(transform); + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkTransform::SetInput(vtkLinearTransform *input) +{ + if (this->Input == input) + { + return; + } + if (input && input->CircuitCheck(this)) + { + vtkErrorMacro("SetInput: this would create a circular reference."); + return; + } + if (this->Input) + { + this->Input->Delete(); + } + this->Input = input; + if (this->Input) + { + this->Input->Register(this); + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +int vtkTransform::CircuitCheck(vtkAbstractTransform *transform) +{ + if (this->vtkLinearTransform::CircuitCheck(transform) || + this->Input && this->Input->CircuitCheck(transform)) + { + return 1; + } + + int n = this->Concatenation->GetNumberOfTransforms(); + for (int i = 0; i < n; i++) + { + if (this->Concatenation->GetTransform(i)->CircuitCheck(transform)) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkTransform::MakeTransform() +{ + return vtkTransform::New(); +} + +//---------------------------------------------------------------------------- +unsigned long vtkTransform::GetMTime() +{ + unsigned long mtime = this->vtkLinearTransform::GetMTime(); + unsigned long mtime2; + + // checking the matrix MTime is part of the legacy hack in InternalUpdate + if ((mtime2 = this->Matrix->GetMTime()) > this->MatrixUpdateMTime) + { + if (mtime2 > mtime) + { + mtime = mtime2; + } + } + + if (this->Input) + { + mtime2 = this->Input->GetMTime(); + if (mtime2 > mtime) + { + mtime = mtime2; + } + } + mtime2 = this->Concatenation->GetMaxMTime(); + if (mtime2 > mtime) + { + return mtime2; + } + return mtime; +} + +//---------------------------------------------------------------------------- +// Get the x, y, z orientation angles from the transformation matrix as an +// array of three floating point values. +void vtkTransform::GetOrientation(double orientation[3], + vtkMatrix4x4 *amatrix) +{ +#define VTK_AXIS_EPSILON 0.001 + int i; + + // convenient access to matrix + double (*matrix)[4] = amatrix->Element; + double ortho[3][3]; + + for (i = 0; i < 3; i++) + { + ortho[0][i] = matrix[0][i]; + ortho[1][i] = matrix[1][i]; + ortho[2][i] = matrix[2][i]; + } + if (vtkMath::Determinant3x3(ortho) < 0) + { + ortho[0][2] = -ortho[0][2]; + ortho[1][2] = -ortho[1][2]; + ortho[2][2] = -ortho[2][2]; + } + + vtkMath::Orthogonalize3x3(ortho, ortho); + + // first rotate about y axis + double x2 = ortho[2][0]; + double y2 = ortho[2][1]; + double z2 = ortho[2][2]; + + double x3 = ortho[1][0]; + double y3 = ortho[1][1]; + double z3 = ortho[1][2]; + + double d1 = sqrt(x2*x2 + z2*z2); + + double cosTheta, sinTheta; + if (d1 < VTK_AXIS_EPSILON) + { + cosTheta = 1.0; + sinTheta = 0.0; + } + else + { + cosTheta = z2/d1; + sinTheta = x2/d1; + } + + double theta = atan2(sinTheta, cosTheta); + orientation[1] = -theta/vtkMath::DoubleDegreesToRadians(); + + // now rotate about x axis + double d = sqrt(x2*x2 + y2*y2 + z2*z2); + + double sinPhi, cosPhi; + if (d < VTK_AXIS_EPSILON) + { + sinPhi = 0.0; + cosPhi = 1.0; + } + else if (d1 < VTK_AXIS_EPSILON) + { + sinPhi = y2/d; + cosPhi = z2/d; + } + else + { + sinPhi = y2/d; + cosPhi = (x2*x2 + z2*z2)/(d1*d); + } + + double phi = atan2(sinPhi, cosPhi); + orientation[0] = phi/vtkMath::DoubleDegreesToRadians(); + + // finally, rotate about z + double x3p = x3*cosTheta - z3*sinTheta; + double y3p = - sinPhi*sinTheta*x3 + cosPhi*y3 - sinPhi*cosTheta*z3; + double d2 = sqrt(x3p*x3p + y3p*y3p); + + double cosAlpha, sinAlpha; + if (d2 < VTK_AXIS_EPSILON) + { + cosAlpha = 1.0; + sinAlpha = 0.0; + } + else + { + cosAlpha = y3p/d2; + sinAlpha = x3p/d2; + } + + double alpha = atan2(sinAlpha, cosAlpha); + orientation[2] = alpha/vtkMath::DoubleDegreesToRadians(); +} + +//---------------------------------------------------------------------------- +// Get the x, y, z orientation angles from the transformation matrix as an +// array of three floating point values. +void vtkTransform::GetOrientation(double orientation[3]) +{ + this->Update(); + this->GetOrientation(orientation, this->Matrix); +} + +//---------------------------------------------------------------------------- +// vtkTransform::GetOrientationWXYZ +void vtkTransform::GetOrientationWXYZ(double wxyz[4]) +{ + int i; + + this->Update(); + // convenient access to matrix + double (*matrix)[4] = this->Matrix->Element; + double ortho[3][3]; + + for (i = 0; i < 3; i++) + { + ortho[0][i] = matrix[0][i]; + ortho[1][i] = matrix[1][i]; + ortho[2][i] = matrix[2][i]; + } + if (vtkMath::Determinant3x3(ortho) < 0) + { + ortho[0][i] = -ortho[0][i]; + ortho[1][i] = -ortho[1][i]; + ortho[2][i] = -ortho[2][i]; + } + + vtkMath::Matrix3x3ToQuaternion(ortho, wxyz); + + // calc the return value wxyz + double mag = sqrt(wxyz[1]*wxyz[1] + wxyz[2]*wxyz[2] + wxyz[3]*wxyz[3]); + + if (mag) + { + wxyz[0] = 2.0*acos(wxyz[0])/vtkMath::DoubleDegreesToRadians(); + wxyz[1] /= mag; + wxyz[2] /= mag; + wxyz[3] /= mag; + } + else + { + wxyz[0] = 0.0; + wxyz[1] = 0.0; + wxyz[2] = 0.0; + wxyz[3] = 1.0; + } +} + + +//---------------------------------------------------------------------------- +// Return the position from the current transformation matrix as an array +// of three floating point numbers. This is simply returning the translation +// component of the 4x4 matrix. +void vtkTransform::GetPosition(double position[3]) +{ + this->Update(); + + position[0] = this->Matrix->Element[0][3]; + position[1] = this->Matrix->Element[1][3]; + position[2] = this->Matrix->Element[2][3]; +} + +//---------------------------------------------------------------------------- +// Return the x, y, z scale factors of the current transformation matrix as +// an array of three float numbers. +void vtkTransform::GetScale(double scale[3]) +{ + this->Update(); + + // convenient access to matrix + double (*matrix)[4] = this->Matrix->Element; + double U[3][3], VT[3][3]; + + for (int i = 0; i < 3; i++) + { + U[0][i] = matrix[0][i]; + U[1][i] = matrix[1][i]; + U[2][i] = matrix[2][i]; + } + + vtkMath::SingularValueDecomposition3x3(U, U, scale, VT); +} + +//---------------------------------------------------------------------------- +// Return the inverse of the current transformation matrix. +void vtkTransform::GetInverse(vtkMatrix4x4 *inverse) +{ + vtkMatrix4x4::Invert(this->GetMatrix(),inverse); +} + +//---------------------------------------------------------------------------- +// Obtain the transpose of the current transformation matrix. +void vtkTransform::GetTranspose(vtkMatrix4x4 *transpose) +{ + vtkMatrix4x4::Transpose(this->GetMatrix(),transpose); +} + diff --git a/Common/vtkTransform.h b/Common/vtkTransform.h new file mode 100644 index 0000000..72c6756 --- /dev/null +++ b/Common/vtkTransform.h @@ -0,0 +1,331 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkTransform - describes linear transformations via a 4x4 matrix +// .SECTION Description +// A vtkTransform can be used to describe the full range of linear (also +// known as affine) coordinate transformations in three dimensions, +// which are internally represented as a 4x4 homogeneous transformation +// matrix. When you create a new vtkTransform, it is always initialized +// to the identity transformation. +//

The SetInput() method allows you to set another transform, +// instead of the identity transform, to be the base transformation. +// There is a pipeline mechanism to ensure that when the input is +// modified, the current transformation will be updated accordingly. +// This pipeline mechanism is also supported by the Concatenate() method. +//

Most of the methods for manipulating this transformation, +// e.g. Translate, Rotate, and Concatenate, can operate in either +// PreMultiply (the default) or PostMultiply mode. In PreMultiply +// mode, the translation, concatenation, etc. will occur before any +// transformations which are represented by the current matrix. In +// PostMultiply mode, the additional transformation will occur after +// any transformations represented by the current matrix. +//

This class performs all of its operations in a right handed +// coordinate system with right handed rotations. Some other graphics +// libraries use left handed coordinate systems and rotations. +// .SECTION See Also +// vtkPerspectiveTransform vtkGeneralTransform vtkMatrix4x4 +// vtkTransformCollection vtkTransformFilter vtkTransformPolyDataFilter +// vtkImageReslice + +#ifndef __vtkTransform_h +#define __vtkTransform_h + +#include "vtkLinearTransform.h" + +#include "vtkMatrix4x4.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkTransform : public vtkLinearTransform +{ + public: + static vtkTransform *New(); + vtkTypeRevisionMacro(vtkTransform,vtkLinearTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the transformation to the identity transformation. If + // the transform has an Input, then the transformation will be + // reset so that it is the same as the Input. + void Identity(); + + // Description: + // Invert the transformation. This will also set a flag so that + // the transformation will use the inverse of its Input, if an Input + // has been set. + void Inverse(); + + // Description: + // Create a translation matrix and concatenate it with the current + // transformation according to PreMultiply or PostMultiply semantics. + void Translate(double x, double y, double z) { + this->Concatenation->Translate(x,y,z); }; + void Translate(const double x[3]) { this->Translate(x[0], x[1], x[2]); }; + void Translate(const float x[3]) { this->Translate(x[0], x[1], x[2]); }; + + // Description: + // Create a rotation matrix and concatenate it with the current + // transformation according to PreMultiply or PostMultiply semantics. + // The angle is in degrees, and (x,y,z) specifies the axis that the + // rotation will be performed around. + void RotateWXYZ(double angle, double x, double y, double z) { + this->Concatenation->Rotate(angle,x,y,z); }; + void RotateWXYZ(double angle, const double axis[3]) { + this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); }; + void RotateWXYZ(double angle, const float axis[3]) { + this->RotateWXYZ(angle, axis[0], axis[1], axis[2]); }; + + // Description: + // Create a rotation matrix about the X, Y, or Z axis and concatenate + // it with the current transformation according to PreMultiply or + // PostMultiply semantics. The angle is expressed in degrees. + void RotateX(double angle) { this->RotateWXYZ(angle, 1, 0, 0); }; + void RotateY(double angle) { this->RotateWXYZ(angle, 0, 1, 0); }; + void RotateZ(double angle) { this->RotateWXYZ(angle, 0, 0, 1); }; + + // Description: + // Create a scale matrix (i.e. set the diagonal elements to x, y, z) + // and concatenate it with the current transformation according to + // PreMultiply or PostMultiply semantics. + void Scale(double x, double y, double z) { + this->Concatenation->Scale(x,y,z); }; + void Scale(const double s[3]) { this->Scale(s[0], s[1], s[2]); }; + void Scale(const float s[3]) { this->Scale(s[0], s[1], s[2]); }; + + // Description: + // Set the current matrix directly. This actually calls Identity(), + // followed by Concatenate(matrix). + void SetMatrix(vtkMatrix4x4 *matrix) { + this->SetMatrix(*matrix->Element); }; + void SetMatrix(const double elements[16]) { + this->Identity(); this->Concatenate(elements); }; + + // Description: + // Concatenates the matrix with the current transformation according + // to PreMultiply or PostMultiply semantics. + void Concatenate(vtkMatrix4x4 *matrix) { + this->Concatenate(*matrix->Element); }; + void Concatenate(const double elements[16]) { + this->Concatenation->Concatenate(elements); }; + + // Description: + // Concatenate the specified transform with the current transformation + // according to PreMultiply or PostMultiply semantics. + // The concatenation is pipelined, meaning that if any of the + // transformations are changed, even after Concatenate() is called, + // those changes will be reflected when you call TransformPoint(). + void Concatenate(vtkLinearTransform *transform); + + // Description: + // Sets the internal state of the transform to PreMultiply. All subsequent + // operations will occur before those already represented in the + // current transformation. In homogeneous matrix notation, M = M*A where + // M is the current transformation matrix and A is the applied matrix. + // The default is PreMultiply. + void PreMultiply() { + if (this->Concatenation->GetPreMultiplyFlag()) { return; } + this->Concatenation->SetPreMultiplyFlag(1); this->Modified(); }; + + // Description: + // Sets the internal state of the transform to PostMultiply. All subsequent + // operations will occur after those already represented in the + // current transformation. In homogeneous matrix notation, M = A*M where + // M is the current transformation matrix and A is the applied matrix. + // The default is PreMultiply. + void PostMultiply() { + if (!this->Concatenation->GetPreMultiplyFlag()) { return; } + this->Concatenation->SetPreMultiplyFlag(0); this->Modified(); }; + + // Description: + // Get the total number of transformations that are linked into this + // one via Concatenate() operations or via SetInput(). + int GetNumberOfConcatenatedTransforms() { + return this->Concatenation->GetNumberOfTransforms() + + (this->Input == NULL ? 0 : 1); }; + + // Description + // Get one of the concatenated transformations as a vtkAbstractTransform. + // These transformations are applied, in series, every time the + // transformation of a coordinate occurs. This method is provided + // to make it possible to decompose a transformation into its + // constituents, for example to save a transformation to a file. + vtkLinearTransform *GetConcatenatedTransform(int i) { + if (this->Input == NULL) { + return (vtkLinearTransform *)this->Concatenation->GetTransform(i); } + else if (i < this->Concatenation->GetNumberOfPreTransforms()) { + return (vtkLinearTransform *)this->Concatenation->GetTransform(i); } + else if (i > this->Concatenation->GetNumberOfPreTransforms()) { + return (vtkLinearTransform *)this->Concatenation->GetTransform(i-1); } + else if (this->GetInverseFlag()) { + return (vtkLinearTransform *)this->Input->GetInverse(); } + else { + return (vtkLinearTransform *)this->Input; } }; + + // Description: + // Get the x, y, z orientation angles from the transformation matrix as an + // array of three floating point values. + void GetOrientation(double orient[3]); + void GetOrientation(float orient[3]) { + double temp[3]; this->GetOrientation(temp); + orient[0] = static_cast(temp[0]); + orient[1] = static_cast(temp[1]); + orient[2] = static_cast(temp[2]); }; + double *GetOrientation() { + this->GetOrientation(this->ReturnValue); return this->ReturnValue; }; + + // Description: + // Convenience function to get the x, y, z orientation angles from + // a transformation matrix as an array of three floating point values. + static void GetOrientation(double orient[3], vtkMatrix4x4 *matrix); + + // Description: + // Return the wxyz angle+axis representing the current orientation. + // The angle is in degrees and the axis is a unit vector. + void GetOrientationWXYZ(double wxyz[4]); + void GetOrientationWXYZ(float wxyz[3]) { + double temp[4]; this->GetOrientationWXYZ(temp); + wxyz[0]=static_cast(temp[0]); + wxyz[1]=static_cast(temp[1]); + wxyz[2]=static_cast(temp[2]); + wxyz[3]=static_cast(temp[3]);}; + double *GetOrientationWXYZ() { + this->GetOrientationWXYZ(this->ReturnValue); return this->ReturnValue; }; + + // Description: + // Return the position from the current transformation matrix as an array + // of three floating point numbers. This is simply returning the translation + // component of the 4x4 matrix. + void GetPosition(double pos[3]); + void GetPosition(float pos[3]) { + double temp[3]; this->GetPosition(temp); + pos[0] = static_cast(temp[0]); + pos[1] = static_cast(temp[1]); + pos[2] = static_cast(temp[2]); }; + double *GetPosition() { + this->GetPosition(this->ReturnValue); return this->ReturnValue; }; + + // Description: + // Return the scale factors of the current transformation matrix as + // an array of three float numbers. These scale factors are not necessarily + // about the x, y, and z axes unless unless the scale transformation was + // applied before any rotations. + void GetScale(double scale[3]); + void GetScale(float scale[3]) { + double temp[3]; this->GetScale(temp); + scale[0] = static_cast(temp[0]); + scale[1] = static_cast(temp[1]); + scale[2] = static_cast(temp[2]); }; + double *GetScale() { + this->GetScale(this->ReturnValue); return this->ReturnValue; }; + + // Description: + // Return a matrix which is the inverse of the current transformation + // matrix. + void GetInverse(vtkMatrix4x4 *inverse); + + // Description: + // Return a matrix which is the transpose of the current transformation + // matrix. This is equivalent to the inverse if and only if the + // transformation is a pure rotation with no translation or scale. + void GetTranspose(vtkMatrix4x4 *transpose); + + // Description: + // Set the input for this transformation. This will be used as the + // base transformation if it is set. This method allows you to build + // a transform pipeline: if the input is modified, then this transformation + // will automatically update accordingly. Note that the InverseFlag, + // controlled via Inverse(), determines whether this transformation + // will use the Input or the inverse of the Input. + void SetInput(vtkLinearTransform *input); + vtkLinearTransform *GetInput() { return this->Input; }; + + // Description: + // Get the inverse flag of the transformation. This controls + // whether it is the Input or the inverse of the Input that + // is used as the base transformation. The InverseFlag is + // flipped every time Inverse() is called. The InverseFlag + // is off when a transform is first created. + int GetInverseFlag() { + return this->Concatenation->GetInverseFlag(); }; + + // Description: + // Pushes the current transformation onto the transformation stack. + void Push() { if (this->Stack == NULL) { + this->Stack = vtkTransformConcatenationStack::New(); } + this->Stack->Push(&this->Concatenation); + this->Modified(); }; + + // Description: + // Deletes the transformation on the top of the stack and sets the top + // to the next transformation on the stack. + void Pop() { if (this->Stack == NULL) { return; } + this->Stack->Pop(&this->Concatenation); + this->Modified(); }; + + // Description: + // Check for self-reference. Will return true if concatenating + // with the specified transform, setting it to be our inverse, + // or setting it to be our input will create a circular reference. + // CircuitCheck is automatically called by SetInput(), SetInverse(), + // and Concatenate(vtkXTransform *). Avoid using this function, + // it is experimental. + int CircuitCheck(vtkAbstractTransform *transform); + + // Return an inverse transform which will always update itself + // to match this transform. + vtkAbstractTransform *GetInverse() { + return vtkLinearTransform::GetInverse(); } + + // Description: + // Make a new transform of the same type. + vtkAbstractTransform *MakeTransform(); + + // Description: + // Override GetMTime to account for input and concatenation. + unsigned long GetMTime(); + + // Description: + // Use this method only if you wish to compute the transformation in + // homogeneous (x,y,z,w) coordinates, otherwise use TransformPoint(). + // This method calls this->GetMatrix()->MultiplyPoint(). + void MultiplyPoint(const float in[4], float out[4]) { + this->GetMatrix()->MultiplyPoint(in,out);}; + void MultiplyPoint(const double in[4], double out[4]) { + this->GetMatrix()->MultiplyPoint(in,out);}; + +protected: + vtkTransform (); + ~vtkTransform (); + + void InternalDeepCopy(vtkAbstractTransform *t); + + void InternalUpdate(); + + vtkLinearTransform *Input; + vtkTransformConcatenation *Concatenation; + vtkTransformConcatenationStack *Stack; + + // this allows us to check whether people have been fooling + // around with our matrix + unsigned long MatrixUpdateMTime; + + float Point[4]; + double DoublePoint[4]; + double ReturnValue[4]; +private: + vtkTransform (const vtkTransform&); // Not implemented + void operator=(const vtkTransform&); // Not implemented +}; + +#endif diff --git a/Common/vtkTransformCollection.cxx b/Common/vtkTransformCollection.cxx new file mode 100644 index 0000000..6dfea94 --- /dev/null +++ b/Common/vtkTransformCollection.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransformCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkTransformCollection, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkTransformCollection); diff --git a/Common/vtkTransformCollection.h b/Common/vtkTransformCollection.h new file mode 100644 index 0000000..eba2a1b --- /dev/null +++ b/Common/vtkTransformCollection.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransformCollection - maintain a list of transforms + +// .SECTION Description +// vtkTransformCollection is an object that creates and manipulates lists of +// objects of type vtkTransform. + +// .SECTION see also +// vtkCollection vtkTransform + +#ifndef __vtkTransformCollection_h +#define __vtkTransformCollection_h + +#include "vtkCollection.h" + +#include "vtkTransform.h" // Needed for inline methods + +class VTK_COMMON_EXPORT vtkTransformCollection : public vtkCollection +{ +public: + vtkTypeRevisionMacro(vtkTransformCollection,vtkCollection); + static vtkTransformCollection *New(); + + // Description: + // Add a Transform to the list. + void AddItem(vtkTransform *); + + // Description: + // Get the next Transform in the list. Return NULL when the end of the + // list is reached. + vtkTransform *GetNextItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkTransform *GetNextTransform(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkTransformCollection() {}; + ~vtkTransformCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkTransformCollection(const vtkTransformCollection&); // Not implemented. + void operator=(const vtkTransformCollection&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline void vtkTransformCollection::AddItem(vtkTransform *t) +{ + this->vtkCollection::AddItem((vtkObject *)t); +} + +//---------------------------------------------------------------------------- +inline vtkTransform *vtkTransformCollection::GetNextItem() +{ + return static_cast(this->GetNextItemAsObject()); +} + +#endif diff --git a/Common/vtkType.h b/Common/vtkType.h new file mode 100644 index 0000000..8707d6f --- /dev/null +++ b/Common/vtkType.h @@ -0,0 +1,245 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkType.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkType_h +#define __vtkType_h + +#include "vtkConfigure.h" + +/*--------------------------------------------------------------------------*/ +/* Define a unique integer identifier for each native scalar type. */ + +/* These types are returned by GetDataType to indicate pixel type. */ +#define VTK_VOID 0 +#define VTK_BIT 1 +#define VTK_CHAR 2 +#define VTK_SIGNED_CHAR 15 +#define VTK_UNSIGNED_CHAR 3 +#define VTK_SHORT 4 +#define VTK_UNSIGNED_SHORT 5 +#define VTK_INT 6 +#define VTK_UNSIGNED_INT 7 +#define VTK_LONG 8 +#define VTK_UNSIGNED_LONG 9 +#define VTK_FLOAT 10 +#define VTK_DOUBLE 11 +#define VTK_ID_TYPE 12 + +/* These types are not currently supported by GetDataType, but are for + completeness. */ +#define VTK_STRING 13 +#define VTK_OPAQUE 14 + +/* These types are enabled if VTK_TYPE_USE_LONG_LONG is defined. */ +#define VTK_LONG_LONG 16 +#define VTK_UNSIGNED_LONG_LONG 17 + +/* This type is enabled if VTK_TYPE_USE___INT64 is defined. */ +#define VTK___INT64 18 + +/* This type is enabled if VTK_TYPE_USE___INT64 and + VTK_TYPE_CONVERT_UI64_TO_DOUBLE are both defined. */ +#define VTK_UNSIGNED___INT64 19 + +/*--------------------------------------------------------------------------*/ +/* Define a unique integer identifier for each vtkDataObject type. */ +#define VTK_POLY_DATA 0 +#define VTK_STRUCTURED_POINTS 1 +#define VTK_STRUCTURED_GRID 2 +#define VTK_RECTILINEAR_GRID 3 +#define VTK_UNSTRUCTURED_GRID 4 +#define VTK_PIECEWISE_FUNCTION 5 +#define VTK_IMAGE_DATA 6 +#define VTK_DATA_OBJECT 7 +#define VTK_DATA_SET 8 +#define VTK_POINT_SET 9 +#define VTK_UNIFORM_GRID 10 +#define VTK_COMPOSITE_DATA_SET 11 +#define VTK_HIERARCHICAL_DATA_SET 12 +#define VTK_HIERARCHICAL_BOX_DATA_SET 13 +#define VTK_GENERIC_DATA_SET 14 + +/*--------------------------------------------------------------------------*/ +/* Define a casting macro for use by the constants below. */ +#if defined(__cplusplus) +# define VTK_TYPE_CAST(T, V) static_cast< T >(V) +#else +# define VTK_TYPE_CAST(T, V) ((T)(V)) +#endif + +/*--------------------------------------------------------------------------*/ +/* Define min/max constants for each type. */ +#define VTK_BIT_MIN 0 +#define VTK_BIT_MAX 1 +#if VTK_TYPE_CHAR_IS_SIGNED +# define VTK_CHAR_MIN VTK_TYPE_CAST(char, 0x80) +# define VTK_CHAR_MAX VTK_TYPE_CAST(char, 0x7f) +#else +# define VTK_CHAR_MIN VTK_TYPE_CAST(char, 0u) +# define VTK_CHAR_MAX VTK_TYPE_CAST(char, 0xffu) +#endif +#define VTK_SIGNED_CHAR_MIN VTK_TYPE_CAST(signed char, 0x80) +#define VTK_SIGNED_CHAR_MAX VTK_TYPE_CAST(signed char, 0x7f) +#define VTK_UNSIGNED_CHAR_MIN VTK_TYPE_CAST(unsigned char, 0u) +#define VTK_UNSIGNED_CHAR_MAX VTK_TYPE_CAST(unsigned char, 0xffu) +#define VTK_SHORT_MIN VTK_TYPE_CAST(short, 0x8000) +#define VTK_SHORT_MAX VTK_TYPE_CAST(short, 0x7fff) +#define VTK_UNSIGNED_SHORT_MIN VTK_TYPE_CAST(unsigned short, 0u) +#define VTK_UNSIGNED_SHORT_MAX VTK_TYPE_CAST(unsigned short, 0xffffu) +#define VTK_INT_MIN VTK_TYPE_CAST(int, ~(~0u >> 1)) +#define VTK_INT_MAX VTK_TYPE_CAST(int, ~0u >> 1) +#define VTK_UNSIGNED_INT_MIN VTK_TYPE_CAST(unsigned int, 0) +#define VTK_UNSIGNED_INT_MAX VTK_TYPE_CAST(unsigned int, ~0u) +#define VTK_LONG_MIN VTK_TYPE_CAST(long, ~(~0ul >> 1)) +#define VTK_LONG_MAX VTK_TYPE_CAST(long, ~0ul >> 1) +#define VTK_UNSIGNED_LONG_MIN VTK_TYPE_CAST(unsigned long, 0ul) +#define VTK_UNSIGNED_LONG_MAX VTK_TYPE_CAST(unsigned long, ~0ul) +#define VTK_FLOAT_MIN VTK_TYPE_CAST(float, -1.0e+38f) +#define VTK_FLOAT_MAX VTK_TYPE_CAST(float, 1.0e+38f) +#define VTK_DOUBLE_MIN VTK_TYPE_CAST(double, -1.0e+299) +#define VTK_DOUBLE_MAX VTK_TYPE_CAST(double, 1.0e+299) +#if defined(VTK_SIZEOF_LONG_LONG) +# define VTK_LONG_LONG_MIN VTK_TYPE_CAST(long long, ~(~0ull >> 1)) +# define VTK_LONG_LONG_MAX VTK_TYPE_CAST(long long, ~0ull >> 1) +# define VTK_UNSIGNED_LONG_LONG_MIN VTK_TYPE_CAST(unsigned long long, 0ull) +# define VTK_UNSIGNED_LONG_LONG_MAX VTK_TYPE_CAST(unsigned long long, ~0ull) +#endif +#if defined(VTK_SIZEOF___INT64) +# define VTK___INT64_MIN VTK_TYPE_CAST(__int64, ~(~0ui64 >> 1)) +# define VTK___INT64_MAX VTK_TYPE_CAST(__int64, ~0ui64 >> 1) +# define VTK_UNSIGNED___INT64_MIN VTK_TYPE_CAST(unsigned __int64, 0ui64) +# define VTK_UNSIGNED___INT64_MAX VTK_TYPE_CAST(unsigned __int64, ~0ui64) +#endif + +/* Define compatibility names for these constants. */ +#define VTK_LARGE_INTEGER VTK_INT_MAX +#define VTK_LARGE_FLOAT VTK_FLOAT_MAX + +/*--------------------------------------------------------------------------*/ +/* Define named types and constants corresponding to specific integer + and floating-point sizes and signedness. */ + +/* Select an 8-bit integer type. */ +#if VTK_SIZEOF_CHAR == 1 +typedef unsigned char vtkTypeUInt8; +typedef signed char vtkTypeInt8; +# define VTK_TYPE_UINT8 VTK_UNSIGNED_CHAR +# if VTK_TYPE_CHAR_IS_SIGNED +# define VTK_TYPE_INT8 VTK_CHAR +# else +# define VTK_TYPE_INT8 VTK_SIGNED_CHAR +# endif +#else +# error "No native data type can represent an 8-bit integer." +#endif + +/* Select a 16-bit integer type. */ +#if VTK_SIZEOF_SHORT == 2 +typedef unsigned short vtkTypeUInt16; +typedef signed short vtkTypeInt16; +# define VTK_TYPE_UINT16 VTK_UNSIGNED_SHORT +# define VTK_TYPE_INT16 VTK_SHORT +#elif VTK_SIZEOF_INT == 2 +typedef unsigned int vtkTypeUInt16; +typedef signed int vtkTypeInt16; +# define VTK_TYPE_UINT16 VTK_UNSIGNED_INT +# define VTK_TYPE_INT16 VTK_INT +#else +# error "No native data type can represent a 16-bit integer." +#endif + +/* Select a 32-bit integer type. */ +#if VTK_SIZEOF_INT == 4 +typedef unsigned int vtkTypeUInt32; +typedef signed int vtkTypeInt32; +# define VTK_TYPE_UINT32 VTK_UNSIGNED_INT +# define VTK_TYPE_INT32 VTK_INT +#elif VTK_SIZEOF_LONG == 4 +typedef unsigned long vtkTypeUInt32; +typedef signed long vtkTypeInt32; +# define VTK_TYPE_UINT32 VTK_UNSIGNED_LONG +# define VTK_TYPE_INT32 VTK_LONG +#else +# error "No native data type can represent a 32-bit integer." +#endif + +/* Select a 64-bit integer type. */ +#if VTK_SIZEOF_LONG == 8 +typedef unsigned long vtkTypeUInt64; +typedef signed long vtkTypeInt64; +# define VTK_TYPE_UINT64 VTK_UNSIGNED_LONG +# define VTK_TYPE_INT64 VTK_LONG +#elif defined(VTK_TYPE_USE_LONG_LONG) && VTK_SIZEOF_LONG_LONG == 8 +typedef unsigned long long vtkTypeUInt64; +typedef signed long long vtkTypeInt64; +# define VTK_TYPE_UINT64 VTK_UNSIGNED_LONG_LONG +# define VTK_TYPE_INT64 VTK_LONG_LONG +#elif defined(VTK_TYPE_USE___INT64) && VTK_SIZEOF___INT64 == 8 +typedef unsigned __int64 vtkTypeUInt64; +typedef signed __int64 vtkTypeInt64; +# define VTK_TYPE_UINT64 VTK_UNSIGNED___INT64 +# define VTK_TYPE_INT64 VTK___INT64 +#else +# error "No native data type can represent a 64-bit integer." +#endif + +/* Select a 32-bit floating point type. */ +#if VTK_SIZEOF_FLOAT == 4 +typedef float vtkTypeFloat32; +# define VTK_TYPE_FLOAT32 VTK_FLOAT +#else +# error "No native data type can represent a 32-bit floating point value." +#endif + +/* Select a 64-bit floating point type. */ +#if VTK_SIZEOF_DOUBLE == 8 +typedef double vtkTypeFloat64; +# define VTK_TYPE_FLOAT64 VTK_DOUBLE +#else +# error "No native data type can represent a 64-bit floating point value." +#endif + +/*--------------------------------------------------------------------------*/ +/* Choose an implementation for vtkIdType. */ +#define VTK_HAS_ID_TYPE +#ifdef VTK_USE_64BIT_IDS +# if defined(VTK_SIZEOF_LONG) && VTK_SIZEOF_LONG == 8 && 0 +typedef long vtkIdType; +# define VTK_SIZEOF_ID_TYPE VTK_SIZEOF_LONG +# define VTK_LARGE_ID VTK_LONG_MAX +# elif defined(VTK_TYPE_USE_LONG_LONG) && VTK_SIZEOF_LONG_LONG == 8 +typedef long long vtkIdType; +# define VTK_SIZEOF_ID_TYPE VTK_SIZEOF_LONG_LONG +# define VTK_LARGE_ID VTK_LONG_LONG_MAX +# elif defined(VTK_TYPE_USE___INT64) && VTK_SIZEOF___INT64 == 8 +typedef __int64 vtkIdType; +# define VTK_SIZEOF_ID_TYPE VTK_SIZEOF___INT64 +# define VTK_LARGE_ID VTK___INT64_MAX +# else +# error "VTK_USE_64BIT_IDS is ON but no 64-bit integer type is available." +# endif +#else +typedef int vtkIdType; +# define VTK_SIZEOF_ID_TYPE VTK_SIZEOF_INT +# define VTK_LARGE_ID VTK_INT_MAX +#endif + +/*--------------------------------------------------------------------------*/ +/* Define the type of floating point interface used for old and new + versions of VTK. VTK 4.2 and older use float and VTK 4.4 and newer + use double for most of the API calls. */ +#define vtkFloatingPointType vtkFloatingPointType +typedef double vtkFloatingPointType; + +#endif diff --git a/Common/vtkTypeTraits.h b/Common/vtkTypeTraits.h new file mode 100644 index 0000000..633afb7 --- /dev/null +++ b/Common/vtkTypeTraits.h @@ -0,0 +1,156 @@ +/*========================================================================= + + Program: ParaView + Module: $RCSfile: vtkTypeTraits.h,v $ + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTypeTraits - Template defining traits of native types used by VTK. +// .SECTION Description +// vtkTypeTraits provides information about VTK's supported scalar types +// that is useful for templates. +#ifndef __vtkTypeTraits_h +#define __vtkTypeTraits_h + +#include "vtkSystemIncludes.h" + +// Forward-declare template. There is no primary template. +template struct vtkTypeTraits; + +// Define a macro to simplify trait definitions. +#define VTK_TYPE_TRAITS(type, macro, isSigned, name, print, format) \ + VTK_TEMPLATE_SPECIALIZE struct vtkTypeTraits< type > \ + { \ + /* The type itself. */ \ + typedef type ValueType; \ + \ + /* The smallest possible value represented by the type. */ \ + static type Min() { return VTK_##macro##_MIN; } \ + \ + /* The largest possible value represented by the type. */ \ + static type Max() { return VTK_##macro##_MAX; } \ + \ + /* Whether the type is signed. */ \ + static int IsSigned() { return isSigned; } \ + \ + /* An "alias" type that is the same size and signedness. */ \ + typedef vtkType##name SizedType; \ + \ + /* A name for the type indicating its size and signedness. */ \ + static const char* SizedName() { return #name; } \ + \ + /* A type to use for printing or parsing values in strings. */ \ + typedef print PrintType; \ + \ + /* A format for parsing values from strings. Use with PrintType. */ \ + static const char* ParseFormat() { return format; } \ + } + +// Define traits for floating-point types. +#define VTK_TYPE_NAME_FLOAT float +#define VTK_TYPE_NAME_DOUBLE double +#define VTK_TYPE_SIZED_FLOAT FLOAT32 +#define VTK_TYPE_SIZED_DOUBLE FLOAT64 +VTK_TYPE_TRAITS(float, FLOAT, 1, Float32, float, "%f"); +VTK_TYPE_TRAITS(double, DOUBLE, 1, Float64, double, "%lf"); + +// Define traits for char types. +// Note the print type is short because not all platforms support formating integers with char. +#define VTK_TYPE_NAME_CHAR char +#if VTK_TYPE_CHAR_IS_SIGNED +# define VTK_TYPE_SIZED_CHAR INT8 +VTK_TYPE_TRAITS(char, CHAR, 1, Int8, short, "%hd"); +#else +# define VTK_TYPE_SIZED_CHAR UINT8 +VTK_TYPE_TRAITS(char, CHAR, 0, UInt8, unsigned short, "%hu"); +#endif +#define VTK_TYPE_NAME_SIGNED_CHAR signed char +#define VTK_TYPE_NAME_UNSIGNED_CHAR unsigned char +#define VTK_TYPE_SIZED_SIGNED_CHAR INT8 +#define VTK_TYPE_SIZED_UNSIGNED_CHAR UINT8 +VTK_TYPE_TRAITS(signed char, SIGNED_CHAR, 1, Int8, short, "%hd"); +VTK_TYPE_TRAITS(unsigned char, UNSIGNED_CHAR, 0, UInt8, unsigned short, "%hu"); + +// Define traits for short types. +#define VTK_TYPE_NAME_SHORT short +#define VTK_TYPE_NAME_UNSIGNED_SHORT unsigned short +#define VTK_TYPE_SIZED_SHORT INT16 +#define VTK_TYPE_SIZED_UNSIGNED_SHORT UINT16 +VTK_TYPE_TRAITS(short, SHORT, 1, Int16, short, "%hd"); +VTK_TYPE_TRAITS(unsigned short, UNSIGNED_SHORT, 0, UInt16, unsigned short, + "%hu"); + +// Define traits for int types. +#define VTK_TYPE_NAME_INT int +#define VTK_TYPE_NAME_UNSIGNED_INT unsigned int +#define VTK_TYPE_SIZED_INT INT32 +#define VTK_TYPE_SIZED_UNSIGNED_INT UINT32 +VTK_TYPE_TRAITS(int, INT, 1, Int32, int, "%d"); +VTK_TYPE_TRAITS(unsigned int, UNSIGNED_INT, 0, UInt32, unsigned int, "%u"); + +// Define traits for long types. +#define VTK_TYPE_NAME_LONG long +#define VTK_TYPE_NAME_UNSIGNED_LONG unsigned long +#if VTK_SIZEOF_LONG == 4 +# define VTK_TYPE_SIZED_LONG INT32 +# define VTK_TYPE_SIZED_UNSIGNED_LONG UINT32 +VTK_TYPE_TRAITS(long, LONG, 1, Int32, long, "%ld"); +VTK_TYPE_TRAITS(unsigned long, UNSIGNED_LONG, 0, UInt32, unsigned long, "%lu"); +#elif VTK_SIZEOF_LONG == 8 +# define VTK_TYPE_SIZED_LONG INT64 +# define VTK_TYPE_SIZED_UNSIGNED_LONG UINT64 +VTK_TYPE_TRAITS(long, LONG, 1, Int64, long, "%ld"); +VTK_TYPE_TRAITS(unsigned long, UNSIGNED_LONG, 0, UInt64, unsigned long, "%lu"); +#else +# error "Type long is not 4 or 8 bytes in size." +#endif + +// Define traits for long long types if they are enabled. +#if defined(VTK_TYPE_USE_LONG_LONG) +# define VTK_TYPE_NAME_LONG_LONG long long +# define VTK_TYPE_NAME_UNSIGNED_LONG_LONG unsigned long long +# if VTK_SIZEOF_LONG_LONG == 8 +# define VTK_TYPE_SIZED_LONG_LONG INT64 +# define VTK_TYPE_SIZED_UNSIGNED_LONG_LONG UINT64 +VTK_TYPE_TRAITS(long long, LONG_LONG, 1, Int64, long long, "%lld"); +VTK_TYPE_TRAITS(unsigned long long, UNSIGNED_LONG_LONG, 0, UInt64, + unsigned long long, "%llu"); +# else +# error "Type long long is not 8 bytes in size." +# endif +#endif + +// Define traits for __int64 types if they are enabled. +#if defined(VTK_TYPE_USE___INT64) +# define VTK_TYPE_NAME___INT64 __int64 +# define VTK_TYPE_NAME_UNSIGNED___INT64 unsigned __int64 +# if VTK_SIZEOF___INT64 == 8 +# define VTK_TYPE_SIZED___INT64 INT64 +# define VTK_TYPE_SIZED_UNSIGNED___INT64 UINT64 +VTK_TYPE_TRAITS(__int64, __INT64, 1, Int64, __int64, "%I64d"); +VTK_TYPE_TRAITS(unsigned __int64, UNSIGNED___INT64, 0, UInt64, + unsigned __int64, "%I64u"); +# else +# error "Type __int64 is not 8 bytes in size." +# endif +#endif + +// Define traits for vtkIdType. The template specialization is +// already defined for the corresponding native type. +#define VTK_TYPE_NAME_ID_TYPE vtkIdType +#if defined(VTK_USE_64BIT_IDS) +# define VTK_TYPE_SIZED_ID_TYPE INT64 +#else +# define VTK_TYPE_SIZED_ID_TYPE INT32 +#endif + +#undef VTK_TYPE_TRAITS + +#endif diff --git a/Common/vtkTypedArray.cxx.in b/Common/vtkTypedArray.cxx.in new file mode 100644 index 0000000..6a40dd4 --- /dev/null +++ b/Common/vtkTypedArray.cxx.in @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTypedArray.cxx.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkType@VTK_TYPE_NAME@Array.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkType@VTK_TYPE_NAME@Array, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkType@VTK_TYPE_NAME@Array); + +//---------------------------------------------------------------------------- +vtkType@VTK_TYPE_NAME@Array::vtkType@VTK_TYPE_NAME@Array(vtkIdType numComp): Superclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkType@VTK_TYPE_NAME@Array::~vtkType@VTK_TYPE_NAME@Array() +{ +} + +//---------------------------------------------------------------------------- +void vtkType@VTK_TYPE_NAME@Array::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Common/vtkTypedArray.h.in b/Common/vtkTypedArray.h.in new file mode 100644 index 0000000..55a9b5d --- /dev/null +++ b/Common/vtkTypedArray.h.in @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTypedArray.h.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkType@VTK_TYPE_NAME@Array - dynamic, self-adjusting array of vtkType@VTK_TYPE_NAME@ +// .SECTION Description +// vtkType@VTK_TYPE_NAME@Array is an array of values of type vtkType@VTK_TYPE_NAME@. It +// provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkType@VTK_TYPE_NAME@Array_h +#define __vtkType@VTK_TYPE_NAME@Array_h + +#include "vtk@VTK_TYPE_NATIVE@Array.h" + +class VTK_COMMON_EXPORT vtkType@VTK_TYPE_NAME@Array : public vtk@VTK_TYPE_NATIVE@Array +{ +public: + static vtkType@VTK_TYPE_NAME@Array* New(); + vtkTypeRevisionMacro(vtkType@VTK_TYPE_NAME@Array,vtk@VTK_TYPE_NATIVE@Array); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkType@VTK_TYPE_NAME@Array(vtkIdType numComp=1); + ~vtkType@VTK_TYPE_NAME@Array(); + +private: + vtkType@VTK_TYPE_NAME@Array(const vtkType@VTK_TYPE_NAME@Array&); // Not implemented. + void operator=(const vtkType@VTK_TYPE_NAME@Array&); // Not implemented. +}; + +#endif diff --git a/Common/vtkUnsignedCharArray.cxx b/Common/vtkUnsignedCharArray.cxx new file mode 100644 index 0000000..88b4997 --- /dev/null +++ b/Common/vtkUnsignedCharArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedCharArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(unsigned char); + +#define __vtkUnsignedCharArray_cxx +#include "vtkUnsignedCharArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkUnsignedCharArray, "$Revision: 1.59 $"); +vtkStandardNewMacro(vtkUnsignedCharArray); + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray::vtkUnsignedCharArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray::~vtkUnsignedCharArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkUnsignedCharArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkUnsignedCharArray.h b/Common/vtkUnsignedCharArray.h new file mode 100644 index 0000000..d8cec9b --- /dev/null +++ b/Common/vtkUnsignedCharArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedCharArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnsignedCharArray - dynamic, self-adjusting array of unsigned char +// .SECTION Description +// vtkUnsignedCharArray is an array of values of type unsigned char. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkUnsignedCharArray_h +#define __vtkUnsignedCharArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkUnsignedCharArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE unsigned char +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkUnsignedCharArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkUnsignedCharArray* New(); + vtkTypeRevisionMacro(vtkUnsignedCharArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_UNSIGNED_CHAR; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, unsigned char* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const unsigned char* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const unsigned char* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const unsigned char* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + unsigned char GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, unsigned char value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, unsigned char f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(unsigned char f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + unsigned char* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + unsigned char* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(unsigned char* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkUnsignedCharArray(vtkIdType numComp=1); + ~vtkUnsignedCharArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkUnsignedCharArray(const vtkUnsignedCharArray&); // Not implemented. + void operator=(const vtkUnsignedCharArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkUnsignedIntArray.cxx b/Common/vtkUnsignedIntArray.cxx new file mode 100644 index 0000000..b1ffd30 --- /dev/null +++ b/Common/vtkUnsignedIntArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedIntArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(unsigned int); + +#define __vtkUnsignedIntArray_cxx +#include "vtkUnsignedIntArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkUnsignedIntArray, "$Revision: 1.35 $"); +vtkStandardNewMacro(vtkUnsignedIntArray); + +//---------------------------------------------------------------------------- +vtkUnsignedIntArray::vtkUnsignedIntArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkUnsignedIntArray::~vtkUnsignedIntArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkUnsignedIntArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkUnsignedIntArray.h b/Common/vtkUnsignedIntArray.h new file mode 100644 index 0000000..ab92d69 --- /dev/null +++ b/Common/vtkUnsignedIntArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedIntArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnsignedIntArray - dynamic, self-adjusting array of unsigned int +// .SECTION Description +// vtkUnsignedIntArray is an array of values of type unsigned int. It +// provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkUnsignedIntArray_h +#define __vtkUnsignedIntArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkUnsignedIntArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE unsigned int +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkUnsignedIntArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkUnsignedIntArray* New(); + vtkTypeRevisionMacro(vtkUnsignedIntArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_UNSIGNED_INT; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, unsigned int* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const unsigned int* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const unsigned int* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const unsigned int* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + unsigned int GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, unsigned int value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, unsigned int f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(unsigned int f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + unsigned int* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + unsigned int* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(unsigned int* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkUnsignedIntArray(vtkIdType numComp=1); + ~vtkUnsignedIntArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkUnsignedIntArray(const vtkUnsignedIntArray&); // Not implemented. + void operator=(const vtkUnsignedIntArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkUnsignedLongArray.cxx b/Common/vtkUnsignedLongArray.cxx new file mode 100644 index 0000000..fbf4a3f --- /dev/null +++ b/Common/vtkUnsignedLongArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedLongArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(unsigned long); + +#define __vtkUnsignedLongArray_cxx +#include "vtkUnsignedLongArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkUnsignedLongArray, "$Revision: 1.35 $"); +vtkStandardNewMacro(vtkUnsignedLongArray); + +//---------------------------------------------------------------------------- +vtkUnsignedLongArray::vtkUnsignedLongArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkUnsignedLongArray::~vtkUnsignedLongArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkUnsignedLongArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkUnsignedLongArray.h b/Common/vtkUnsignedLongArray.h new file mode 100644 index 0000000..06d64c2 --- /dev/null +++ b/Common/vtkUnsignedLongArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedLongArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnsignedLongArray - dynamic, self-adjusting array of unsigned long +// .SECTION Description +// vtkUnsignedLongArray is an array of values of type unsigned long. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkUnsignedLongArray_h +#define __vtkUnsignedLongArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkUnsignedLongArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE unsigned long +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkUnsignedLongArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkUnsignedLongArray* New(); + vtkTypeRevisionMacro(vtkUnsignedLongArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_UNSIGNED_LONG; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, unsigned long* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const unsigned long* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const unsigned long* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const unsigned long* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + unsigned long GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, unsigned long value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, unsigned long f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(unsigned long f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + unsigned long* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + unsigned long* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(unsigned long* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkUnsignedLongArray(vtkIdType numComp=1); + ~vtkUnsignedLongArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkUnsignedLongArray(const vtkUnsignedLongArray&); // Not implemented. + void operator=(const vtkUnsignedLongArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkUnsignedLongLongArray.cxx b/Common/vtkUnsignedLongLongArray.cxx new file mode 100644 index 0000000..049db93 --- /dev/null +++ b/Common/vtkUnsignedLongLongArray.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedLongLongArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(unsigned long long); + +#define __vtkUnsignedLongLongArray_cxx +#include "vtkUnsignedLongLongArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkUnsignedLongLongArray, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkUnsignedLongLongArray); + +//---------------------------------------------------------------------------- +vtkUnsignedLongLongArray::vtkUnsignedLongLongArray(vtkIdType numComp): + RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkUnsignedLongLongArray::~vtkUnsignedLongLongArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkUnsignedLongLongArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkUnsignedLongLongArray.h b/Common/vtkUnsignedLongLongArray.h new file mode 100644 index 0000000..5602cd2 --- /dev/null +++ b/Common/vtkUnsignedLongLongArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedLongLongArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnsignedLongLongArray - dynamic, self-adjusting array of unsigned long long +// .SECTION Description +// vtkUnsignedLongLongArray is an array of values of type unsigned long long. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkUnsignedLongLongArray_h +#define __vtkUnsignedLongLongArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkUnsignedLongLongArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE unsigned long long +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkUnsignedLongLongArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkUnsignedLongLongArray* New(); + vtkTypeRevisionMacro(vtkUnsignedLongLongArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_UNSIGNED_LONG_LONG; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, unsigned long long* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const unsigned long long* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const unsigned long long* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const unsigned long long* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + unsigned long long GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, unsigned long long value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, unsigned long long f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(unsigned long long f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + unsigned long long* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + unsigned long long* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(unsigned long long* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkUnsignedLongLongArray(vtkIdType numComp=1); + ~vtkUnsignedLongLongArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkUnsignedLongLongArray(const vtkUnsignedLongLongArray&); // Not implemented. + void operator=(const vtkUnsignedLongLongArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkUnsignedShortArray.cxx b/Common/vtkUnsignedShortArray.cxx new file mode 100644 index 0000000..1e5fd5a --- /dev/null +++ b/Common/vtkUnsignedShortArray.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedShortArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(unsigned short); + +#define __vtkUnsignedShortArray_cxx +#include "vtkUnsignedShortArray.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkUnsignedShortArray, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkUnsignedShortArray); + +//---------------------------------------------------------------------------- +vtkUnsignedShortArray::vtkUnsignedShortArray(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkUnsignedShortArray::~vtkUnsignedShortArray() +{ +} + +//---------------------------------------------------------------------------- +void vtkUnsignedShortArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkUnsignedShortArray.h b/Common/vtkUnsignedShortArray.h new file mode 100644 index 0000000..929f218 --- /dev/null +++ b/Common/vtkUnsignedShortArray.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsignedShortArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnsignedShortArray - dynamic, self-adjusting array of unsigned short +// .SECTION Description +// vtkUnsignedShortArray is an array of values of type unsigned short. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkUnsignedShortArray_h +#define __vtkUnsignedShortArray_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkUnsignedShortArray_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE unsigned short +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkUnsignedShortArray : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkUnsignedShortArray* New(); + vtkTypeRevisionMacro(vtkUnsignedShortArray,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_UNSIGNED_SHORT; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, unsigned short* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const unsigned short* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const unsigned short* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const unsigned short* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + unsigned short GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, unsigned short value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, unsigned short f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(unsigned short f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + unsigned short* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + unsigned short* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(unsigned short* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkUnsignedShortArray(vtkIdType numComp=1); + ~vtkUnsignedShortArray(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkUnsignedShortArray(const vtkUnsignedShortArray&); // Not implemented. + void operator=(const vtkUnsignedShortArray&); // Not implemented. +}; + +#endif diff --git a/Common/vtkUnsigned__Int64Array.cxx b/Common/vtkUnsigned__Int64Array.cxx new file mode 100644 index 0000000..682b690 --- /dev/null +++ b/Common/vtkUnsigned__Int64Array.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsigned__Int64Array.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(unsigned __int64); + +#define __vtkUnsigned__Int64Array_cxx +#include "vtkUnsigned__Int64Array.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkUnsigned__Int64Array, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkUnsigned__Int64Array); + +//---------------------------------------------------------------------------- +vtkUnsigned__Int64Array::vtkUnsigned__Int64Array(vtkIdType numComp): + RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtkUnsigned__Int64Array::~vtkUnsigned__Int64Array() +{ +} + +//---------------------------------------------------------------------------- +void vtkUnsigned__Int64Array::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtkUnsigned__Int64Array.h b/Common/vtkUnsigned__Int64Array.h new file mode 100644 index 0000000..138dae0 --- /dev/null +++ b/Common/vtkUnsigned__Int64Array.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnsigned__Int64Array.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnsigned__Int64Array - dynamic, self-adjusting array of unsigned __int64 +// .SECTION Description +// vtkUnsigned__Int64Array is an array of values of type unsigned __int64. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtkUnsigned__Int64Array_h +#define __vtkUnsigned__Int64Array_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtkUnsigned__Int64Array_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE unsigned __int64 +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate +class VTK_COMMON_EXPORT vtkUnsigned__Int64Array : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtkUnsigned__Int64Array* New(); + vtkTypeRevisionMacro(vtkUnsigned__Int64Array,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK_UNSIGNED___INT64; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, unsigned __int64* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const unsigned __int64* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const unsigned __int64* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const unsigned __int64* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + unsigned __int64 GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, unsigned __int64 value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, unsigned __int64 f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(unsigned __int64 f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + unsigned __int64* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + unsigned __int64* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(unsigned __int64* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtkUnsigned__Int64Array(vtkIdType numComp=1); + ~vtkUnsigned__Int64Array(); + +private: + //BTX + typedef vtkDataArrayTemplate RealSuperclass; + //ETX + vtkUnsigned__Int64Array(const vtkUnsigned__Int64Array&); // Not implemented. + void operator=(const vtkUnsigned__Int64Array&); // Not implemented. +}; + +#endif diff --git a/Common/vtkVersion.cxx b/Common/vtkVersion.cxx new file mode 100644 index 0000000..98449be --- /dev/null +++ b/Common/vtkVersion.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVersion.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVersion.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkVersion, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkVersion); diff --git a/Common/vtkVersion.h b/Common/vtkVersion.h new file mode 100644 index 0000000..7f351c5 --- /dev/null +++ b/Common/vtkVersion.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVersion.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVersion - Versioning class for vtk +// .SECTION Description +// Holds methods for defining/determining the current vtk version +// (major, minor, build). + +// .SECTION Caveats +// This file will change frequently to update the VTKSourceVersion which +// timestamps a particular source release. + + +#ifndef __vtkVersion_h +#define __vtkVersion_h + + +#include "vtkObject.h" + +#define VTK_SOURCE_VERSION "vtk version " VTK_VERSION ", vtk source $Revision: 1.2196 $, $Date: 2005/09/01 09:01:29 $ (GMT)" + + +class VTK_COMMON_EXPORT vtkVersion : public vtkObject +{ +public: + static vtkVersion *New(); + vtkTypeRevisionMacro(vtkVersion,vtkObject); + + // Description: + // Return the version of vtk this object is a part of. + // A variety of methods are included. GetVTKSourceVersion returns a string + // with an identifier which timestamps a particular source tree. + static const char *GetVTKVersion() { return VTK_VERSION; } + static int GetVTKMajorVersion() { return VTK_MAJOR_VERSION; } + static int GetVTKMinorVersion() { return VTK_MINOR_VERSION; } + static int GetVTKBuildVersion() { return VTK_BUILD_VERSION; } + static const char *GetVTKSourceVersion() { return VTK_SOURCE_VERSION; } + +protected: + vtkVersion() {}; //insure constructor/destructor protected + ~vtkVersion() {}; +private: + vtkVersion(const vtkVersion&); // Not implemented. + void operator=(const vtkVersion&); // Not implemented. +}; + +#endif diff --git a/Common/vtkVoidArray.cxx b/Common/vtkVoidArray.cxx new file mode 100644 index 0000000..43d681f --- /dev/null +++ b/Common/vtkVoidArray.cxx @@ -0,0 +1,181 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoidArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVoidArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkVoidArray, "$Revision: 1.44 $"); +vtkStandardNewMacro(vtkVoidArray); + +typedef void *voidPtr; + +// Instantiate object. +vtkVoidArray::vtkVoidArray() + : NumberOfPointers(0),Size(0),Array(NULL) +{ +} + +vtkVoidArray::~vtkVoidArray() +{ + if (this->Array) + { + delete [] this->Array; + } +} + +// Allocate memory for this array. Delete old storage only if necessary. +int vtkVoidArray::Allocate(vtkIdType sz, vtkIdType vtkNotUsed(ext)) +{ + if ( sz > this->Size || this->Array != NULL ) + { + delete [] this->Array; + + this->Size = ( sz > 0 ? sz : 1); + if ( (this->Array = new voidPtr[this->Size]) == NULL ) + { + return 0; + } + } + + this->NumberOfPointers = 0; + + return 1; +} + +// Release storage and reset array to initial state. +void vtkVoidArray::Initialize() +{ + if ( this->Array != NULL ) + { + delete [] this->Array; + this->Array = NULL; + } + this->Size = 0; + this->NumberOfPointers = 0; +} + +// Deep copy of another void array. +void vtkVoidArray::DeepCopy(vtkVoidArray *va) +{ + // Do nothing on a NULL input. + if (va == NULL) + { + return; + } + + if ( this != va ) + { + delete [] this->Array; + + this->NumberOfPointers = va->NumberOfPointers; + this->Size = va->Size; + + this->Array = new voidPtr[this->Size]; + memcpy(this->Array, va->GetVoidPointer(0), this->Size*sizeof(void *)); + } +} + +void** vtkVoidArray::WritePointer(vtkIdType id, + vtkIdType number) +{ + vtkIdType newSize=id+number; + if ( newSize > this->Size ) + { + this->ResizeAndExtend(newSize); + } + if ( newSize > this->NumberOfPointers ) + { + this->NumberOfPointers = newSize; + } + return this->Array + id; +} + +void vtkVoidArray::InsertVoidPointer(vtkIdType id, void* p) +{ + if ( id >= this->Size ) + { + this->ResizeAndExtend(id+1); + } + this->Array[id] = p; + if ( id >= this->NumberOfPointers ) + { + this->NumberOfPointers = id+1; + } +} + +vtkIdType vtkVoidArray::InsertNextVoidPointer(void* p) +{ + this->InsertVoidPointer(this->NumberOfPointers,p); + return this->NumberOfPointers-1; +} + +// Protected function does "reallocate" +// +void** vtkVoidArray::ResizeAndExtend(vtkIdType sz) +{ + void** newArray; + vtkIdType newSize; + + if ( sz > this->Size ) + { + newSize = this->Size + sz; + } + else if (sz == this->Size) + { + return this->Array; + } + else + { + newSize = sz; + } + + if (newSize <= 0) + { + this->Initialize(); + return 0; + } + + if ( (newArray = new voidPtr[newSize]) == NULL ) + { + vtkErrorMacro(<< "Cannot allocate memory\n"); + return 0; + } + + memcpy(newArray, this->Array, + (sz < this->Size ? sz : this->Size) * sizeof(voidPtr)); + + if (newSize < this->Size) + { + this->NumberOfPointers = newSize; + } + this->Size = newSize; + delete [] this->Array; + this->Array = newArray; + + return this->Array; +} + +void vtkVoidArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->Array) + { + os << indent << "Array: " << this->Array << "\n"; + } + else + { + os << indent << "Array: (null)\n"; + } +} diff --git a/Common/vtkVoidArray.h b/Common/vtkVoidArray.h new file mode 100644 index 0000000..775c1ef --- /dev/null +++ b/Common/vtkVoidArray.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoidArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVoidArray - dynamic, self-adjusting array of void* pointers +// .SECTION Description +// vtkVoidArray is an array of pointers to void. It provides methods +// for insertion and retrieval of these pointers values, and will +// automatically resize itself to hold new data. + +#ifndef __vtkVoidArray_h +#define __vtkVoidArray_h + +#include "vtkObject.h" + +class VTK_COMMON_EXPORT vtkVoidArray : public vtkObject +{ +public: + // Description: + // Initialize with empty array. + static vtkVoidArray *New(); + + vtkTypeRevisionMacro(vtkVoidArray,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate memory for this array. Delete old storage only if necessary. + // Note that the parameter ext is no longer used. + int Allocate(vtkIdType sz, vtkIdType ext=1000); + + // Description: + // Release storage and reset array to initial state. + void Initialize(); + + // Description: + // Return the type of data. + int GetDataType() {return VTK_VOID;} + + // Description: + // Return the size of the data contained in the array. + int GetDataTypeSize() { return sizeof(void*); } + + // Description: + // Set the number of void* pointers held in the array. + void SetNumberOfPointers(vtkIdType number) + {this->Allocate(number); this->NumberOfPointers = number;} + + // Description: + // Get the number of void* pointers held in the array. + vtkIdType GetNumberOfPointers() + {return this->NumberOfPointers;} + + // Description: + // Get the void* pointer at the ith location. + void* GetVoidPointer(vtkIdType id) + {return this->Array[id];} + + // Description: + // Set the void* pointer value at the ith location in the array. + void SetVoidPointer(vtkIdType id, void* ptr) + {this->Array[id] = ptr;} + + // Description: + // Insert (memory allocation performed) the void* into the ith location + // in the array. + void InsertVoidPointer(vtkIdType i, void* ptr); + + // Description: + // Insert (memory allocation performed) the void* pointer at the + // end of the array. + vtkIdType InsertNextVoidPointer(void* tuple); + + // Description: + // Reuse already allocated data; make the container look like it is + // empty. + void Reset() + {this->NumberOfPointers = 0;} + + // Description: + // Resize the array to just fit the inserted memory. Reclaims extra memory. + void Squeeze() + {this->ResizeAndExtend (this->NumberOfPointers);} + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + void** GetPointer(vtkIdType id) {return this->Array + id;} + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set NumberOfPointers according to + // the number of data values requested. + void** WritePointer(vtkIdType id, vtkIdType number); + + // Description: + // Deep copy of another void array. + void DeepCopy(vtkVoidArray *va); + +protected: + vtkVoidArray(); + ~vtkVoidArray(); + + vtkIdType NumberOfPointers; + vtkIdType Size; + void** Array; // pointer to data + + void** ResizeAndExtend(vtkIdType sz); // function to resize data + +private: + vtkVoidArray(const vtkVoidArray&); // Not implemented. + void operator=(const vtkVoidArray&); // Not implemented. +}; + + +#endif diff --git a/Common/vtkWarpTransform.cxx b/Common/vtkWarpTransform.cxx new file mode 100644 index 0000000..bc74708 --- /dev/null +++ b/Common/vtkWarpTransform.cxx @@ -0,0 +1,293 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWarpTransform.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkWarpTransform, "$Revision: 1.11 $"); + +//---------------------------------------------------------------------------- +void vtkWarpTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "InverseFlag: " << this->InverseFlag << "\n"; + os << indent << "InverseTolerance: " << this->InverseTolerance << "\n"; + os << indent << "InverseIterations: " << this->InverseIterations << "\n"; +} + +//---------------------------------------------------------------------------- +vtkWarpTransform::vtkWarpTransform() +{ + this->InverseFlag = 0; + this->InverseTolerance = 0.001; + this->InverseIterations = 500; +} + +//---------------------------------------------------------------------------- +vtkWarpTransform::~vtkWarpTransform() +{ +} + +//------------------------------------------------------------------------ +// Check the InverseFlag, and perform a forward or reverse transform +// as appropriate. +template +void vtkWarpTransformPoint(vtkWarpTransform *self, int inverse, + const T input[3], T output[3]) +{ + if (inverse) + { + self->TemplateTransformInverse(input,output); + } + else + { + self->TemplateTransformPoint(input,output); + } +} + +void vtkWarpTransform::InternalTransformPoint(const float input[3], + float output[3]) +{ + vtkWarpTransformPoint(this,this->InverseFlag,input,output); +} + +void vtkWarpTransform::InternalTransformPoint(const double input[3], + double output[3]) +{ + vtkWarpTransformPoint(this,this->InverseFlag,input,output); +} + +//------------------------------------------------------------------------ +// Check the InverseFlag, and set the output point and derivative as +// appropriate. +template +void vtkWarpTransformDerivative(vtkWarpTransform *self, + int inverse, + const T input[3], T output[3], + T derivative[3][3]) +{ + if (inverse) + { + self->TemplateTransformInverse(input,output,derivative); + vtkMath::Invert3x3(derivative,derivative); + } + else + { + self->TemplateTransformPoint(input,output,derivative); + } +} + +void vtkWarpTransform::InternalTransformDerivative(const float input[3], + float output[3], + float derivative[3][3]) +{ + vtkWarpTransformDerivative(this,this->InverseFlag,input,output,derivative); +} + +void vtkWarpTransform::InternalTransformDerivative(const double input[3], + double output[3], + double derivative[3][3]) +{ + vtkWarpTransformDerivative(this,this->InverseFlag,input,output,derivative); +} + +//---------------------------------------------------------------------------- +// We use Newton's method to iteratively invert the transformation. +// This is actally quite robust as long as the Jacobian matrix is never +// singular. +template +void vtkWarpInverseTransformPoint(vtkWarpTransform *self, + const T point[3], + T output[3], + T derivative[3][3]) +{ + T inverse[3], lastInverse[3]; + T deltaP[3], deltaI[3]; + + double functionValue = 0; + double functionDerivative = 0; + double lastFunctionValue = VTK_DOUBLE_MAX; + + double errorSquared = 0; + double toleranceSquared = self->GetInverseTolerance(); + toleranceSquared *= toleranceSquared; + + T f = 1.0; + T a; + + // first guess at inverse point: invert the displacement + self->TemplateTransformPoint(point,inverse); + + inverse[0] -= 2*(inverse[0]-point[0]); + inverse[1] -= 2*(inverse[1]-point[1]); + inverse[2] -= 2*(inverse[2]-point[2]); + + lastInverse[0] = inverse[0]; + lastInverse[1] = inverse[1]; + lastInverse[2] = inverse[2]; + + // do a maximum 500 iterations, usually less than 10 are required + int n = self->GetInverseIterations(); + int i; + + for (i = 0; i < n; i++) + { + // put the inverse point back through the transform + self->TemplateTransformPoint(inverse,deltaP,derivative); + + // how far off are we? + deltaP[0] -= point[0]; + deltaP[1] -= point[1]; + deltaP[2] -= point[2]; + + // get the current function value + functionValue = (deltaP[0]*deltaP[0] + + deltaP[1]*deltaP[1] + + deltaP[2]*deltaP[2]); + + // if the function value is decreasing, do next Newton step + // (the check on f is to ensure that we don't do too many + // reduction steps between the Newton steps) + if (functionValue < lastFunctionValue || f < 0.05) + { + // here is the critical step in Newton's method + vtkMath::LinearSolve3x3(derivative,deltaP,deltaI); + + // get the error value in the output coord space + errorSquared = (deltaI[0]*deltaI[0] + + deltaI[1]*deltaI[1] + + deltaI[2]*deltaI[2]); + + // break if less than tolerance in both coordinate systems + if (errorSquared < toleranceSquared && + functionValue < toleranceSquared) + { + break; + } + + // save the last inverse point + lastInverse[0] = inverse[0]; + lastInverse[1] = inverse[1]; + lastInverse[2] = inverse[2]; + + // save the function value at that point + lastFunctionValue = functionValue; + + // derivative of functionValue at last inverse point + functionDerivative = (deltaP[0]*derivative[0][0]*deltaI[0] + + deltaP[1]*derivative[1][1]*deltaI[1] + + deltaP[2]*derivative[2][2]*deltaI[2])*2; + + // calculate new inverse point + inverse[0] -= deltaI[0]; + inverse[1] -= deltaI[1]; + inverse[2] -= deltaI[2]; + + // reset f to 1.0 + f = 1.0; + + continue; + } + + // the error is increasing, so take a partial step + // (see Numerical Recipes 9.7 for rationale, this code + // is a simplification of the algorithm provided there) + + // quadratic approximation to find best fractional distance + a = -functionDerivative/(2*(functionValue - + lastFunctionValue - + functionDerivative)); + + // clamp to range [0.1,0.5] + f *= (a < 0.1 ? 0.1 : (a > 0.5 ? 0.5 : a)); + + // re-calculate inverse using fractional distance + inverse[0] = lastInverse[0] - f*deltaI[0]; + inverse[1] = lastInverse[1] - f*deltaI[1]; + inverse[2] = lastInverse[2] - f*deltaI[2]; + } + + if (self->GetDebug()) + { + vtkGenericWarningMacro(<<"Debug: In " __FILE__ ", line "<< __LINE__ <<"\n" + << self->GetClassName() << " (" << self + <<") Inverse Iterations: " << (i+1)); + } + + if (i >= n) + { + // didn't converge: back up to last good result + inverse[0] = lastInverse[0]; + inverse[1] = lastInverse[1]; + inverse[2] = lastInverse[2]; + + // print warning: Newton's method didn't converge + vtkGenericWarningMacro(<< + "Warning: In " __FILE__ ", line " << __LINE__ << "\n" << + self->GetClassName() << " (" << self << ") " << + "InverseTransformPoint: no convergence (" << + point[0] << ", " << point[1] << ", " << point[2] << + ") error = " << sqrt(errorSquared) << " after " << + i << " iterations."); + } + + output[0] = inverse[0]; + output[1] = inverse[1]; + output[2] = inverse[2]; +} + +void vtkWarpTransform::InverseTransformPoint(const float point[3], + float output[3]) +{ + float derivative[3][3]; + vtkWarpInverseTransformPoint(this, point, output, derivative); +} + +void vtkWarpTransform::InverseTransformPoint(const double point[3], + double output[3]) +{ + double derivative[3][3]; + vtkWarpInverseTransformPoint(this, point, output, derivative); +} + +//---------------------------------------------------------------------------- +void vtkWarpTransform::InverseTransformDerivative(const float point[3], + float output[3], + float derivative[3][3]) +{ + vtkWarpInverseTransformPoint(this, point, output, derivative); +} + +void vtkWarpTransform::InverseTransformDerivative(const double point[3], + double output[3], + double derivative[3][3]) +{ + vtkWarpInverseTransformPoint(this, point, output, derivative); +} + +//---------------------------------------------------------------------------- +// To invert the transformation, just set the InverseFlag. +void vtkWarpTransform::Inverse() +{ + this->InverseFlag = !this->InverseFlag; + this->Modified(); +} + + + + + + + diff --git a/Common/vtkWarpTransform.h b/Common/vtkWarpTransform.h new file mode 100644 index 0000000..1e2a64c --- /dev/null +++ b/Common/vtkWarpTransform.h @@ -0,0 +1,150 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWarpTransform - superclass for nonlinear geometric transformations +// .SECTION Description +// vtkWarpTransform provides a generic interface for nonlinear +// warp transformations. +// .SECTION see also +// vtkThinPlateSplineTransform vtkGridTransform vtkGeneralTransform + + +#ifndef __vtkWarpTransform_h +#define __vtkWarpTransform_h + +#include "vtkAbstractTransform.h" + +class VTK_COMMON_EXPORT vtkWarpTransform : public vtkAbstractTransform +{ +public: + + vtkTypeRevisionMacro(vtkWarpTransform,vtkAbstractTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Invert the transformation. Warp transformations are usually + // inverted using an iterative technique such as Newton's method. + // The inverse transform is usually around five or six times as + // computationally expensive as the forward transform. + void Inverse(); + + // Description: + // Get the inverse flag of the transformation. This flag is + // set to zero when the transformation is first created, and + // is flipped each time Inverse() is called. + vtkGetMacro(InverseFlag,int); + + // Description: + // Set the tolerance for inverse transformation. + // The default is 0.001. + vtkSetMacro(InverseTolerance,double); + vtkGetMacro(InverseTolerance,double); + + // Description: + // Set the maximum number of iterations for the inverse + // transformation. The default is 500, but usually only + // 2 to 5 iterations are used. The inversion method + // is fairly robust, and it should converge for nearly all smooth + // transformations that do not fold back on themselves. + vtkSetMacro(InverseIterations,int); + vtkGetMacro(InverseIterations,int); + + // Description: + // This will calculate the transformation without calling Update. + // Meant for use only within other VTK classes. + void InternalTransformPoint(const float in[3], float out[3]); + void InternalTransformPoint(const double in[3], double out[3]); + + // Description: + // This will calculate the transformation, as well as its derivative + // without calling Update. Meant for use only within other VTK + // classes. + void InternalTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InternalTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + // Description: + // Do not use these methods. They exists only as a work-around for + // internal templated functions (I really didn't want to make the + // Forward/Inverse methods public, is there a decent work around + // for this sort of thing?) + void TemplateTransformPoint(const float in[3], float out[3]) { + this->ForwardTransformPoint(in,out); }; + void TemplateTransformPoint(const double in[3], double out[3]) { + this->ForwardTransformPoint(in,out); }; + void TemplateTransformPoint(const float in[3], float out[3], + float derivative[3][3]) { + this->ForwardTransformDerivative(in,out,derivative); }; + void TemplateTransformPoint(const double in[3], double out[3], + double derivative[3][3]) { + this->ForwardTransformDerivative(in,out,derivative); }; + void TemplateTransformInverse(const float in[3], float out[3]) { + this->InverseTransformPoint(in,out); }; + void TemplateTransformInverse(const double in[3], double out[3]) { + this->InverseTransformPoint(in,out); }; + void TemplateTransformInverse(const float in[3], float out[3], + float derivative[3][3]) { + this->InverseTransformDerivative(in,out,derivative); }; + void TemplateTransformInverse(const double in[3], double out[3], + double derivative[3][3]) { + this->InverseTransformDerivative(in,out,derivative); }; + +protected: + vtkWarpTransform(); + ~vtkWarpTransform(); + + // Description: + // If the InverseFlag is set to 0, then a call to InternalTransformPoint + // results in a call to ForwardTransformPoint. + virtual void ForwardTransformPoint(const float in[3], float out[3]) = 0; + virtual void ForwardTransformPoint(const double in[3], double out[3]) = 0; + + // Description: + // Calculate the forward transform as well as the derivative. + virtual void ForwardTransformDerivative(const float in[3], float out[3], + float derivative[3][3]) = 0; + virtual void ForwardTransformDerivative(const double in[3], double out[3], + double derivative[3][3]) = 0; + + // Description: + // If the InverseFlag is set to 1, then a call to InternalTransformPoint + // results in a call to InverseTransformPoint. The inverse transformation + // is calculated from using Newton's method. + virtual void InverseTransformPoint(const float in[3], float out[3]); + virtual void InverseTransformPoint(const double in[3], double out[3]); + + // Description: + // Calculate the inverse transform as well as the derivative of the + // forward transform (that's correct: the derivative of the + // forward transform, not of the inverse transform) + virtual void InverseTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + virtual void InverseTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + int InverseFlag; + int InverseIterations; + double InverseTolerance; +private: + vtkWarpTransform(const vtkWarpTransform&); // Not implemented. + void operator=(const vtkWarpTransform&); // Not implemented. +}; + +#endif + + + + + diff --git a/Common/vtkWin32Header.h b/Common/vtkWin32Header.h new file mode 100644 index 0000000..a409f64 --- /dev/null +++ b/Common/vtkWin32Header.h @@ -0,0 +1,192 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32Header.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWin32Header - manage Windows system differences +// .SECTION Description +// The vtkWin32Header captures some system differences between Unix and +// Windows operating systems. + +#ifndef __vtkWIN32Header_h +#define __vtkWIN32Header_h + +#ifndef __VTK_SYSTEM_INCLUDES__INSIDE +Do_not_include_vtkWin32Header_directly__vtkSystemIncludes_includes_it; +#endif + +#include "vtkConfigure.h" + +// +// Windows specific stuff------------------------------------------ +#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) + +// define strict header for windows +#ifndef STRICT +#define STRICT +#endif + +#ifdef VTK_USE_ANSI_STDLIB +#ifndef NOMINMAX +#define NOMINMAX +#endif +#endif + +#endif + +// Never include the windows header here when building VTK itself. +#if defined(VTK_IN_VTK) +# undef VTK_INCLUDE_WINDOWS_H +#endif + +#if defined(_WIN32) + // Include the windows header here only if requested by user code. +# if defined(VTK_INCLUDE_WINDOWS_H) +# include + // Define types from the windows header file. + typedef DWORD vtkWindowsDWORD; + typedef PVOID vtkWindowsPVOID; + typedef LPVOID vtkWindowsLPVOID; + typedef HANDLE vtkWindowsHANDLE; + typedef LPTHREAD_START_ROUTINE vtkWindowsLPTHREAD_START_ROUTINE; +# else + // Define types from the windows header file. + typedef unsigned long vtkWindowsDWORD; + typedef void* vtkWindowsPVOID; + typedef vtkWindowsPVOID vtkWindowsLPVOID; + typedef vtkWindowsPVOID vtkWindowsHANDLE; + typedef vtkWindowsDWORD (__stdcall *vtkWindowsLPTHREAD_START_ROUTINE)(vtkWindowsLPVOID); +# endif + // Enable workaround for windows header name mangling. + // See VTK/Utilities/Upgrading/README.WindowsMangling.txt for details. +# define VTK_WORKAROUND_WINDOWS_MANGLE +#endif + +#if defined(_MSC_VER) + // Enable MSVC compiler warning messages that are useful but off by default. +# pragma warning ( default : 4263 ) /* no override, call convention differs */ + // Disable MSVC compiler warning messages that often occur in valid code. +# if !defined(VTK_DISPLAY_WIN32_WARNINGS) +# pragma warning ( disable : 4097 ) /* typedef is synonym for class */ +# pragma warning ( disable : 4127 ) /* conditional expression is constant */ +# pragma warning ( disable : 4244 ) /* possible loss in conversion */ +# pragma warning ( disable : 4251 ) /* missing DLL-interface */ +# pragma warning ( disable : 4305 ) /* truncation from type1 to type2 */ +# pragma warning ( disable : 4309 ) /* truncation of constant value */ +# pragma warning ( disable : 4514 ) /* unreferenced inline function */ +# pragma warning ( disable : 4706 ) /* assignment in conditional expression */ +# pragma warning ( disable : 4710 ) /* function not inlined */ +# pragma warning ( disable : 4786 ) /* identifier truncated in debug info */ +# endif +#endif + +// MSVC 6.0 in release mode will warn about code it produces with its +// optimizer. Disable the warnings specifically for this +// configuration. Real warnings will be revealed by a debug build or +// by other compilers. +#if defined(_MSC_VER) && (_MSC_VER < 1300) && defined(NDEBUG) +# pragma warning ( disable : 4701 ) /* Variable may be used uninitialized. */ +# pragma warning ( disable : 4702 ) /* Unreachable code. */ +#endif + +#if defined(WIN32) && defined(VTK_BUILD_SHARED_LIBS) + #define VTK_EXPORT __declspec( dllexport ) + + #if defined(vtkCommon_EXPORTS) + #define VTK_COMMON_EXPORT __declspec( dllexport ) + #else + #define VTK_COMMON_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkFiltering_EXPORTS) + #define VTK_FILTERING_EXPORT __declspec( dllexport ) + #else + #define VTK_FILTERING_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkImaging_EXPORTS) + #define VTK_IMAGING_EXPORT __declspec( dllexport ) + #else + #define VTK_IMAGING_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkGenericFiltering_EXPORTS) + #define VTK_GENERIC_FILTERING_EXPORT __declspec( dllexport ) + #else + #define VTK_GENERIC_FILTERING_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkGraphics_EXPORTS) + #define VTK_GRAPHICS_EXPORT __declspec( dllexport ) + #else + #define VTK_GRAPHICS_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkIO_EXPORTS) + #define VTK_IO_EXPORT __declspec( dllexport ) + #else + #define VTK_IO_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkRendering_EXPORTS) + #define VTK_RENDERING_EXPORT __declspec( dllexport ) + #else + #define VTK_RENDERING_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkVolumeRendering_EXPORTS) + #define VTK_VOLUMERENDERING_EXPORT __declspec( dllexport ) + #else + #define VTK_VOLUMERENDERING_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkHybrid_EXPORTS) + #define VTK_HYBRID_EXPORT __declspec( dllexport ) + #else + #define VTK_HYBRID_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkWidgets_EXPORTS) + #define VTK_WIDGETS_EXPORT __declspec( dllexport ) + #else + #define VTK_WIDGETS_EXPORT __declspec( dllimport ) + #endif + + #if defined(vtkParallel_EXPORTS) + #define VTK_PARALLEL_EXPORT __declspec( dllexport ) + #else + #define VTK_PARALLEL_EXPORT __declspec( dllimport ) + #endif + +#else + #define VTK_COMMON_EXPORT + #define VTK_FILTERING_EXPORT + #define VTK_GENERIC_FILTERING_EXPORT + #define VTK_GRAPHICS_EXPORT + #define VTK_IMAGING_EXPORT + #define VTK_IO_EXPORT + #define VTK_RENDERING_EXPORT + #define VTK_VOLUMERENDERING_EXPORT + #define VTK_HYBRID_EXPORT + #define VTK_WIDGETS_EXPORT + #define VTK_PARALLEL_EXPORT + #define VTK_EXPORT +#endif + +// this is exclusively for the tcl Init functions +#if defined(WIN32) + #define VTK_TK_EXPORT __declspec( dllexport ) +#else + #define VTK_TK_EXPORT +#endif + +#endif diff --git a/Common/vtkWin32OutputWindow.cxx b/Common/vtkWin32OutputWindow.cxx new file mode 100644 index 0000000..a89dd59 --- /dev/null +++ b/Common/vtkWin32OutputWindow.cxx @@ -0,0 +1,302 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32OutputWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWin32OutputWindow.h" + +#include "vtkObjectFactory.h" +#include "vtkWindows.h" + +vtkCxxRevisionMacro(vtkWin32OutputWindow, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkWin32OutputWindow); + +HWND vtkWin32OutputWindowOutputWindow = 0; + +LRESULT APIENTRY vtkWin32OutputWindowWndProc(HWND hWnd, UINT message, + WPARAM wParam, + LPARAM lParam) +{ + switch (message) + { + case WM_SIZE: + { + int w = LOWORD(lParam); // width of client area + int h = HIWORD(lParam); // height of client area + + MoveWindow(vtkWin32OutputWindowOutputWindow, + 0, 0, w, h, true); + } + break; + case WM_DESTROY: + vtkWin32OutputWindowOutputWindow = NULL; + vtkObject::GlobalWarningDisplayOff(); + break; + case WM_CREATE: + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +// Display text in the window, and translate the \n to \r\n. + +void vtkWin32OutputWindow::DisplayText(const char* someText) +{ + if(!someText) + { + return; + } + if(this->PromptUser) + { + this->PromptText(someText); + return; + } + + // Create a buffer big enough to hold the entire text + char* buffer = new char[strlen(someText)+1]; + // Start at the begining + const char* NewLinePos = someText; + while(NewLinePos) + { + int len = 0; + // Find the next new line in text + NewLinePos = strchr(someText, '\n'); + // if no new line is found then just add the text + if(NewLinePos == 0) + { + vtkWin32OutputWindow::AddText(someText); + } + // if a new line is found copy it to the buffer + // and add the buffer with a control new line + else + { + len = NewLinePos - someText; + strncpy(buffer, someText, len); + buffer[len] = 0; + someText = NewLinePos+1; + vtkWin32OutputWindow::AddText(buffer); + vtkWin32OutputWindow::AddText("\r\n"); + } + } + delete [] buffer; +} + + +// Add some text to the EDIT control. + +void vtkWin32OutputWindow::AddText(const char* someText) +{ + if(!Initialize() || (strlen(someText) == 0)) + { + return; + } + +#ifdef UNICODE + // move to the end of the text area + SendMessageW( vtkWin32OutputWindowOutputWindow, EM_SETSEL, + (WPARAM)-1, (LPARAM)-1 ); + wchar_t *wmsg = new wchar_t [mbstowcs(NULL, someText, 32000)+1]; + mbstowcs(wmsg, someText, 32000); + // Append the text to the control + SendMessageW( vtkWin32OutputWindowOutputWindow, EM_REPLACESEL, + 0, (LPARAM)wmsg ); + delete [] wmsg; +#else + // move to the end of the text area + SendMessageA( vtkWin32OutputWindowOutputWindow, EM_SETSEL, + (WPARAM)-1, (LPARAM)-1 ); + // Append the text to the control + SendMessageA( vtkWin32OutputWindowOutputWindow, EM_REPLACESEL, + 0, (LPARAM)someText ); +#endif +} + + +// initialize the output window with an EDIT control and +// a container window. + +int vtkWin32OutputWindow::Initialize() +{ + // check to see if it is already initialized + if(vtkWin32OutputWindowOutputWindow) + { + return 1; + } + // Initialized the output window + + WNDCLASS wndClass; + // has the class been registered ? +#ifdef UNICODE + if (!GetClassInfo(GetModuleHandle(NULL),L"vtkOutputWindow",&wndClass)) +#else + if (!GetClassInfo(GetModuleHandle(NULL),"vtkOutputWindow",&wndClass)) +#endif + { + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = vtkWin32OutputWindowWndProc; + wndClass.cbClsExtra = 0; + wndClass.hInstance = GetModuleHandle(NULL); +#ifndef _WIN32_WCE + wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); +#endif + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndClass.lpszMenuName = NULL; +#ifdef UNICODE + wndClass.lpszClassName = L"vtkOutputWindow"; +#else + wndClass.lpszClassName = "vtkOutputWindow"; +#endif + // vtk doesn't use these extra 4 bytes, but app writers + // may want them, so we provide them. + wndClass.cbWndExtra = 4; + RegisterClass(&wndClass); + } + + // create parent container window +#ifdef _WIN32_WCE + HWND win = CreateWindow( + L"vtkOutputWindow", L"vtkOutputWindow", + WS_OVERLAPPED | WS_CLIPCHILDREN, + 0, 0, 512, 512, + NULL, NULL, GetModuleHandle(NULL), NULL); +#elif UNICODE + HWND win = CreateWindow( + L"vtkOutputWindow", L"vtkOutputWindow", + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, + 0, 0, 512, 512, + NULL, NULL, GetModuleHandle(NULL), NULL); +#else + HWND win = CreateWindow( + "vtkOutputWindow", "vtkOutputWindow", + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, + 0, 0, 512, 512, + NULL, NULL, GetModuleHandle(NULL), NULL); +#endif + + // Now create child window with text display box + CREATESTRUCT lpParam; + lpParam.hInstance = GetModuleHandle(NULL); + lpParam.hMenu = NULL; + lpParam.hwndParent = win; + lpParam.cx = 512; + lpParam.cy = 512; + lpParam.x = 0; + lpParam.y = 0; +#if defined(_WIN32_WCE) || defined(UNICODE) + lpParam.lpszName = L"Output Control"; + lpParam.lpszClass = L"EDIT"; // use the RICHEDIT control widget +#else + lpParam.lpszName = "Output Control"; + lpParam.lpszClass = "EDIT"; // use the RICHEDIT control widget +#endif + +#ifdef _WIN32_WCE + lpParam.style = ES_MULTILINE | ES_READONLY | WS_CHILD + | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE + | WS_VSCROLL | WS_HSCROLL; +#else + lpParam.style = ES_MULTILINE | ES_READONLY | WS_CHILD + | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE | WS_MAXIMIZE + | WS_VSCROLL | WS_HSCROLL; +#endif + + lpParam.dwExStyle = 0; + // Create the EDIT window as a child of win +#if defined(_WIN32_WCE) || defined(UNICODE) + vtkWin32OutputWindowOutputWindow = CreateWindow( + lpParam.lpszClass, // pointer to registered class name + L"", // pointer to window name + lpParam.style, // window style + lpParam.x, // horizontal position of window + lpParam.y, // vertical position of window + lpParam.cx, // window width + lpParam.cy, // window height + lpParam.hwndParent, // handle to parent or owner window + NULL, // handle to menu or child-window identifier + lpParam.hInstance, // handle to application instance + &lpParam // pointer to window-creation data + ); +#else + vtkWin32OutputWindowOutputWindow = CreateWindow( + lpParam.lpszClass, // pointer to registered class name + "", // pointer to window name + lpParam.style, // window style + lpParam.x, // horizontal position of window + lpParam.y, // vertical position of window + lpParam.cx, // window width + lpParam.cy, // window height + lpParam.hwndParent, // handle to parent or owner window + NULL, // handle to menu or child-window identifier + lpParam.hInstance, // handle to application instance + &lpParam // pointer to window-creation data + ); +#endif + + const int maxsize = 5242880; + +#ifdef UNICODE + SendMessageW(vtkWin32OutputWindowOutputWindow, + EM_LIMITTEXT, maxsize, 0L); +#else + SendMessageA(vtkWin32OutputWindowOutputWindow, + EM_LIMITTEXT, maxsize, 0L); +#endif + + + // show the top level container window + ShowWindow(win, SW_SHOW); + return 1; +} + + +void vtkWin32OutputWindow::PromptText(const char* someText) +{ + char *vtkmsg = new char [strlen(someText) + 100]; + sprintf(vtkmsg,"%s\nPress Cancel to suppress any further messages.", + someText); +#ifdef UNICODE + wchar_t *wmsg = new wchar_t [mbstowcs(NULL, vtkmsg, 32000)+1]; + mbstowcs(wmsg, vtkmsg, 32000); + if (MessageBox(NULL, wmsg, L"Error", + MB_ICONERROR | MB_OKCANCEL) == IDCANCEL) + { + vtkObject::GlobalWarningDisplayOff(); + } + delete [] wmsg; +#else + if (MessageBox(NULL, vtkmsg, "Error", + MB_ICONERROR | MB_OKCANCEL) == IDCANCEL) + { + vtkObject::GlobalWarningDisplayOff(); + } +#endif + delete [] vtkmsg; +} + +void vtkWin32OutputWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (vtkWin32OutputWindowOutputWindow) + { + os << indent << "OutputWindow: " + << vtkWin32OutputWindowOutputWindow << "\n"; + } + else + { + os << indent << "OutputWindow: (null)\n"; + } + + +} + diff --git a/Common/vtkWin32OutputWindow.h b/Common/vtkWin32OutputWindow.h new file mode 100644 index 0000000..d77c799 --- /dev/null +++ b/Common/vtkWin32OutputWindow.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32OutputWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWin32OutputWindow - Win32 Specific output window class +// .SECTION Description +// This class is used for error and debug message output on the windows +// platform. It creates a read only EDIT control to display the +// output. This class should not be used directly. It should +// only be used through the interface of vtkOutputWindow. This class +// only handles one output window per process. If the window is destroyed, +// the vtkObject::GlobalWarningDisplayOff() function is called. The +// window is created the next time text is written to the window. + +#ifndef __vtkWin32OutputWindow_h +#define __vtkWin32OutputWindow_h + +#include "vtkOutputWindow.h" + + +class VTK_COMMON_EXPORT vtkWin32OutputWindow : public vtkOutputWindow +{ +public: +// Methods from vtkObject + vtkTypeRevisionMacro(vtkWin32OutputWindow,vtkOutputWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a vtkWin32OutputWindow. + static vtkWin32OutputWindow* New(); + // Description: Put the text into the display window. + // New lines are converted to carriage return new lines. + virtual void DisplayText(const char*); +protected: + vtkWin32OutputWindow() {}; + virtual ~vtkWin32OutputWindow() {}; + + void PromptText(const char* text); + static void AddText(const char*); + static int Initialize(); +private: + vtkWin32OutputWindow(const vtkWin32OutputWindow&); // Not implemented. + void operator=(const vtkWin32OutputWindow&); // Not implemented. +}; + + + +#endif diff --git a/Common/vtkWin32OutputWindowProcessEncoded.c b/Common/vtkWin32OutputWindowProcessEncoded.c new file mode 100644 index 0000000..5db6117 --- /dev/null +++ b/Common/vtkWin32OutputWindowProcessEncoded.c @@ -0,0 +1,3208 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32OutputWindowProcessEncoded.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + +DO NOT EDIT + +This file is generated by running CMake on +VTK/Utilities/OutputWindowProcess as a separate project using a Visual +Studio generator. The program built in that project works only when +compiled by the Visual Studio compiler because it depends on being +able to manipulate the stack frame of another process. See +VTK/Utilities/OutputWindowProcess/README.txt for more information. + +This file contains an encoded executable that can be written to disk using + + int vtkEncodedArrayWin32OutputWindowProcessWrite(const char* fname); + +It returns 1 for success and 0 for failure. The executable is +self-deleting and therefore can be run only once. It is used by +vtkWin32ProcessOutputWindow. + +*/ + +#include + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_0[1024] = { +0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, +0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xD0, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, +0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, +0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, +0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, 0x65, +0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, +0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, +0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x38, +0x75, 0xB0, 0xF7, 0x59, 0x1B, 0xE3, 0xF7, 0x59, 0x1B, 0xE3, +0xF7, 0x59, 0x1B, 0xE3, 0x98, 0x46, 0x11, 0xE3, 0xFC, 0x59, +0x1B, 0xE3, 0x74, 0x45, 0x15, 0xE3, 0xF6, 0x59, 0x1B, 0xE3, +0x98, 0x46, 0x1F, 0xE3, 0xF5, 0x59, 0x1B, 0xE3, 0xF7, 0x59, +0x1A, 0xE3, 0xC4, 0x59, 0x1B, 0xE3, 0x95, 0x46, 0x08, 0xE3, +0xF0, 0x59, 0x1B, 0xE3, 0xF1, 0x7A, 0x11, 0xE3, 0xF6, 0x59, +0x1B, 0xE3, 0x52, 0x69, 0x63, 0x68, 0xF7, 0x59, 0x1B, 0xE3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, +0x00, 0x00, 0x4C, 0x01, 0x05, 0x00, 0x41, 0xA2, 0x24, 0x41, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, +0x0E, 0x01, 0x0B, 0x01, 0x06, 0x00, 0x00, 0x20, 0x00, 0x00, +0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x17, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x00, 0x00, 0x00, 0x80, 0x96, 0x98, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, +0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x04, 0x52, 0x00, 0x00, 0xA0, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, +0x74, 0x00, 0x00, 0x00, 0x16, 0x1A, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x2E, 0x72, 0x64, 0x61, +0x74, 0x61, 0x00, 0x00, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x2E, 0x64, 0x61, 0x74, +0x61, 0x00, 0x00, 0x00, 0xA4, 0x05, 0x00, 0x00, 0x00, 0x40, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x2E, 0x69, 0x64, 0x61, +0x74, 0x61, 0x00, 0x00, 0x65, 0x08, 0x00, 0x00, 0x00, 0x50, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x2E, 0x72, 0x65, 0x6C, +0x6F, 0x63, 0x00, 0x00, 0xCC, 0x01, 0x00, 0x00, 0x00, 0x60, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_1[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_2[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_3[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_4[1024] = { +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xE9, 0x16, 0x00, 0x00, 0x00, +0xE9, 0x91, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0x83, 0xEC, 0x1C, 0x8D, 0x44, 0x24, 0x00, 0x53, +0x56, 0x8B, 0x35, 0x64, 0x53, 0x40, 0x00, 0x57, 0x6A, 0x00, +0x6A, 0x00, 0x6A, 0x00, 0x50, 0xFF, 0xD6, 0x85, 0xC0, 0x74, +0x30, 0x8B, 0x3D, 0x68, 0x53, 0x40, 0x00, 0x8B, 0x1D, 0x5C, +0x53, 0x40, 0x00, 0x83, 0xF8, 0xFF, 0x74, 0x1F, 0x8D, 0x4C, +0x24, 0x0C, 0x51, 0xFF, 0xD7, 0x8D, 0x54, 0x24, 0x0C, 0x52, +0xFF, 0xD3, 0x6A, 0x00, 0x6A, 0x00, 0x8D, 0x44, 0x24, 0x14, +0x6A, 0x00, 0x50, 0xFF, 0xD6, 0x85, 0xC0, 0x75, 0xDC, 0x5F, +0x5E, 0x5B, 0x83, 0xC4, 0x1C, 0xC3, 0x90, 0x90, 0x90, 0x90, +0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0x51, 0x56, 0x57, 0xE8, 0x38, 0x03, 0x00, 0x00, 0xE8, 0x03, +0x01, 0x00, 0x00, 0x8B, 0x35, 0x38, 0x52, 0x40, 0x00, 0x6A, +0x00, 0x6A, 0x00, 0xFF, 0xD6, 0x50, 0xA1, 0x18, 0x44, 0x40, +0x00, 0x6A, 0x00, 0x6A, 0x00, 0x68, 0x00, 0x02, 0x00, 0x00, +0x68, 0x00, 0x02, 0x00, 0x00, 0x8B, 0x3D, 0x58, 0x53, 0x40, +0x00, 0x6A, 0x00, 0x6A, 0x00, 0x50, 0xA1, 0x10, 0x44, 0x40, +0x00, 0x50, 0x50, 0x6A, 0x00, 0xFF, 0xD7, 0x6A, 0x00, 0x6A, +0x00, 0xA3, 0x64, 0x45, 0x40, 0x00, 0xFF, 0xD6, 0x8B, 0x0D, +0x64, 0x45, 0x40, 0x00, 0x8B, 0x15, 0x1C, 0x44, 0x40, 0x00, +0x50, 0xA1, 0x14, 0x44, 0x40, 0x00, 0x6A, 0x00, 0x51, 0x68, +0x00, 0x02, 0x00, 0x00, 0x68, 0x00, 0x02, 0x00, 0x00, 0x6A, +0x00, 0x6A, 0x00, 0x52, 0x68, 0x70, 0x45, 0x40, 0x00, 0x50, +0x6A, 0x00, 0xFF, 0xD7, 0x8B, 0x0D, 0x64, 0x45, 0x40, 0x00, +0x6A, 0x05, 0x51, 0xA3, 0x68, 0x45, 0x40, 0x00, 0xFF, 0x15, +0x6C, 0x53, 0x40, 0x00, 0x8B, 0x15, 0x64, 0x45, 0x40, 0x00, +0x52, 0xFF, 0x15, 0x60, 0x53, 0x40, 0x00, 0x8D, 0x44, 0x24, +0x08, 0x50, 0x6A, 0x00, 0x6A, 0x00, 0x68, 0x00, 0x13, 0x40, +0x00, 0x68, 0x00, 0x04, 0x00, 0x00, 0x6A, 0x00, 0xFF, 0x15, +0x34, 0x52, 0x40, 0x00, 0xE8, 0xA8, 0xFE, 0xFF, 0xFF, 0x5F, +0x33, 0xC0, 0x5E, 0x59, 0xC2, 0x10, 0x00, 0x90, 0x90, 0x90, +0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0x8B, 0x0D, 0x10, 0x44, 0x40, 0x00, 0x83, 0xEC, +0x28, 0x8D, 0x44, 0x24, 0x00, 0x56, 0x8B, 0x35, 0x38, 0x52, +0x40, 0x00, 0x50, 0x51, 0x6A, 0x00, 0xFF, 0xD6, 0x50, 0xFF, +0x15, 0x48, 0x53, 0x40, 0x00, 0x85, 0xC0, 0x75, 0x6E, 0x50, +0xC7, 0x44, 0x24, 0x08, 0x03, 0x00, 0x00, 0x00, 0xC7, 0x44, +0x24, 0x0C, 0x80, 0x12, 0x40, 0x00, 0x89, 0x44, 0x24, 0x10, +0xFF, 0xD6, 0x68, 0x00, 0x7F, 0x00, 0x00, 0x6A, 0x00, 0x89, +0x44, 0x24, 0x1C, 0xFF, 0x15, 0x4C, 0x53, 0x40, 0x00, 0x68, +0x00, 0x7F, 0x00, 0x00, 0x6A, 0x00, 0x89, 0x44, 0x24, 0x20, +0xFF, 0x15, 0x50, 0x53, 0x40, 0x00, 0x6A, 0x04, 0x89, 0x44, +0x24, 0x20, 0xFF, 0x15, 0x04, 0x52, 0x40, 0x00, 0x8B, 0x15, +0x10, 0x44, 0x40, 0x00, 0x89, 0x44, 0x24, 0x20, 0x8D, 0x44, +0x24, 0x04, 0xC7, 0x44, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, +0x50, 0x89, 0x54, 0x24, 0x2C, 0xC7, 0x44, 0x24, 0x14, 0x00, +0x00, 0x00, 0x00, 0xFF, 0x15, 0x54, 0x53, 0x40, 0x00, 0x5E, +0x83, 0xC4, 0x28, 0xC3, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, +0x90, 0x90, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0x56, 0x8B, 0x74, 0x24, 0x14, 0x57, 0x8B, 0x7C, 0x24, 0x10, +0x8B, 0xC7, 0x83, 0xE8, 0x02, 0x74, 0x29, 0x83, 0xE8, 0x03, +0x75, 0x2C, 0x8B, 0x15, 0x68, 0x45, 0x40, 0x00, 0x8B, 0xC6, +0x8B, 0xCE, 0x6A, 0x01, 0xC1, 0xE8, 0x10, 0x81, 0xE1, 0xFF, +0xFF, 0x00, 0x00, 0x50, 0x51, 0x6A, 0x00, 0x6A, 0x00, 0x52, +0xFF, 0x15, 0x3C, 0x53, 0x40, 0x00, 0xEB, 0x08, 0x6A, 0x00, +0xFF, 0x15, 0x40, 0x53, 0x40, 0x00, 0x8B, 0x44, 0x24, 0x14, +0x8B, 0x4C, 0x24, 0x0C, 0x56, 0x50, 0x57, 0x51, 0xFF, 0x15, +0x44, 0x53, 0x40, 0x00, 0x5F, 0x5E, 0xC2, 0x10, 0x00, 0x90, +0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x81, 0xEC, +0x04, 0x04, 0x00, 0x00, 0x55, 0x57, 0x8B, 0x3D, 0x40, 0x52, +0x40, 0x00, 0x8D, 0x44, 0x24, 0x08, 0x6A, 0x00, 0x50, 0x8D, +0x4C, 0x24, 0x14, 0x68, 0x00, 0x04, 0x00, 0x00, 0x51, 0x6A, +0xF6, 0xC7, 0x44, 0x24, 0x1C, 0x00, 0x00, 0x00, 0x00, 0xFF, +0xD7, 0x8B, 0x2D, 0x3C, 0x52, 0x40, 0x00, 0x50, 0xFF, 0xD5, +0x85, 0xC0, 0x74, 0x65, 0x56, 0x8B, 0x35, 0x38, 0x53, 0x40, +0x00, 0x8B, 0x54, 0x24, 0x0C, 0xA1, 0x68, 0x45, 0x40, 0x00, +0x6A, 0xFF, 0x6A, 0xFF, 0x68, 0xB1, 0x00, 0x00, 0x00, 0x50, +0xC6, 0x44, 0x14, 0x20, 0x00, 0xFF, 0xD6, 0x8B, 0x15, 0x68, +0x45, 0x40, 0x00, 0x8D, 0x4C, 0x24, 0x10, 0x51, 0x6A, 0x00, +0x68, 0xC2, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xD6, 0x8D, 0x44, +0x24, 0x0C, 0x6A, 0x00, 0x50, 0x8D, 0x4C, 0x24, 0x18, 0x68, +0x00, 0x04, 0x00, 0x00, 0x51, 0x6A, 0xF6, 0xFF, 0xD7, 0x50, +0xFF, 0xD5, 0x85, 0xC0, 0x75, 0xB5, 0x8B, 0x84, 0x24, 0x14, +0x04, 0x00, 0x00, 0x5E, 0x5F, 0x5D, 0x81, 0xC4, 0x04, 0x04, +0x00, 0x00, 0xC2, 0x04, 0x00, 0x8B, 0x84, 0x24, 0x10, 0x04, +0x00, 0x00, 0x5F, 0x5D, 0x81, 0xC4, 0x04, 0x04, 0x00, 0x00, +0xC2, 0x04, 0x00, 0x90, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0x81, 0xEC, 0x48, 0x06, 0x00, 0x00, 0x57, 0xB9, +0x11, 0x00, 0x00, 0x00, 0x33, 0xC0, 0x8D, 0x7C, 0x24, 0x18, +0xF3, 0xAB, 0x8D, 0x44, 0x24, 0x04, 0x8D, 0x4C, 0x24, 0x18, +0x50, 0x51, 0x6A, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_5[1024] = { +0x6A, 0x00, 0x6A, 0x44, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, +0x68, 0x48, 0x44, 0x40, 0x00, 0x6A, 0x00, 0xC7, 0x44, 0x24, +0x40, 0x44, 0x00, 0x00, 0x00, 0xFF, 0x15, 0x80, 0x52, 0x40, +0x00, 0x85, 0xC0, 0x0F, 0x84, 0x5A, 0x01, 0x00, 0x00, 0x8B, +0x15, 0x7C, 0x52, 0x40, 0x00, 0x8B, 0x0D, 0x78, 0x52, 0x40, +0x00, 0xA1, 0x74, 0x52, 0x40, 0x00, 0x53, 0x8B, 0x1D, 0x70, +0x52, 0x40, 0x00, 0x89, 0x94, 0x24, 0x68, 0x02, 0x00, 0x00, +0x8B, 0x15, 0x6C, 0x52, 0x40, 0x00, 0x56, 0x8B, 0x35, 0x68, +0x52, 0x40, 0x00, 0x89, 0x8C, 0x24, 0x78, 0x02, 0x00, 0x00, +0x6A, 0x00, 0x89, 0x94, 0x24, 0x80, 0x02, 0x00, 0x00, 0x8B, +0x54, 0x24, 0x10, 0x6A, 0x00, 0x8D, 0x8C, 0x24, 0x70, 0x02, +0x00, 0x00, 0x89, 0x84, 0x24, 0x7C, 0x02, 0x00, 0x00, 0xA1, +0x64, 0x52, 0x40, 0x00, 0x6A, 0x00, 0x51, 0x52, 0x89, 0x9C, +0x24, 0x84, 0x02, 0x00, 0x00, 0x89, 0x84, 0x24, 0x94, 0x02, +0x00, 0x00, 0xFF, 0xD6, 0x50, 0xFF, 0xD6, 0x50, 0xFF, 0x15, +0x60, 0x52, 0x40, 0x00, 0x8D, 0x84, 0x24, 0x84, 0x02, 0x00, +0x00, 0x68, 0x04, 0x01, 0x00, 0x00, 0x50, 0x6A, 0x00, 0xFF, +0x15, 0x5C, 0x52, 0x40, 0x00, 0x8B, 0x54, 0x24, 0x10, 0xB9, +0x80, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x16, 0x40, 0x00, 0x8D, +0x7C, 0x24, 0x68, 0xF3, 0xA5, 0x8D, 0x8C, 0x24, 0x88, 0x03, +0x00, 0x00, 0xC7, 0x84, 0x24, 0x88, 0x03, 0x00, 0x00, 0x03, +0x00, 0x01, 0x00, 0x51, 0x52, 0xFF, 0x15, 0x58, 0x52, 0x40, +0x00, 0x8B, 0x84, 0x24, 0x4C, 0x04, 0x00, 0x00, 0x8D, 0xB0, +0xDC, 0xFC, 0xFF, 0xFF, 0x8D, 0x44, 0x24, 0x1C, 0x83, 0xE6, +0xE0, 0x50, 0x6A, 0x40, 0x68, 0x24, 0x03, 0x00, 0x00, 0x8D, +0x4E, 0xFC, 0x8D, 0x56, 0x04, 0x89, 0x8C, 0x24, 0x58, 0x04, +0x00, 0x00, 0x8B, 0x4C, 0x24, 0x18, 0x56, 0x51, 0x89, 0x74, +0x24, 0x78, 0x89, 0x94, 0x24, 0x54, 0x04, 0x00, 0x00, 0xFF, +0x15, 0x54, 0x52, 0x40, 0x00, 0x8B, 0x44, 0x24, 0x0C, 0x6A, +0x00, 0x8D, 0x54, 0x24, 0x68, 0x68, 0x24, 0x03, 0x00, 0x00, +0x52, 0x56, 0x50, 0xFF, 0x15, 0x50, 0x52, 0x40, 0x00, 0x8B, +0x4C, 0x24, 0x0C, 0x68, 0x24, 0x03, 0x00, 0x00, 0x56, 0x51, +0xFF, 0x15, 0x4C, 0x52, 0x40, 0x00, 0x8B, 0x44, 0x24, 0x10, +0x8D, 0x94, 0x24, 0x88, 0x03, 0x00, 0x00, 0x52, 0x50, 0xFF, +0x15, 0x48, 0x52, 0x40, 0x00, 0x8B, 0x4C, 0x24, 0x10, 0x51, +0xFF, 0x15, 0x44, 0x52, 0x40, 0x00, 0x8B, 0x54, 0x24, 0x10, +0x52, 0xFF, 0xD3, 0x8B, 0x44, 0x24, 0x0C, 0x50, 0xFF, 0xD3, +0x5E, 0x5B, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x5F, 0x81, 0xC4, +0x48, 0x06, 0x00, 0x00, 0xC3, 0x33, 0xC0, 0x5F, 0x81, 0xC4, +0x48, 0x06, 0x00, 0x00, 0xC3, 0x90, 0x90, 0x90, 0x90, 0x90, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0x56, 0x8B, 0x74, 0x24, 0x08, 0x57, 0x6A, 0xFF, +0x8B, 0x86, 0x04, 0x02, 0x00, 0x00, 0x50, 0xFF, 0x96, 0x08, +0x02, 0x00, 0x00, 0x8B, 0x8E, 0x04, 0x02, 0x00, 0x00, 0x51, +0xFF, 0x96, 0x0C, 0x02, 0x00, 0x00, 0x8D, 0xBE, 0x20, 0x02, +0x00, 0x00, 0x57, 0xFF, 0x96, 0x10, 0x02, 0x00, 0x00, 0x85, +0xC0, 0x75, 0x16, 0x68, 0xE8, 0x03, 0x00, 0x00, 0xFF, 0x96, +0x14, 0x02, 0x00, 0x00, 0x57, 0xFF, 0x96, 0x10, 0x02, 0x00, +0x00, 0x85, 0xC0, 0x74, 0xEA, 0x6A, 0x00, 0xFF, 0x96, 0x18, +0x02, 0x00, 0x00, 0x5F, 0x5E, 0xC3, 0x90, 0x90, 0x90, 0x90, +0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xFF, 0x25, 0x04, 0x52, 0x40, 0x00, 0xFF, 0x25, +0x34, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x38, 0x52, 0x40, 0x00, +0xFF, 0x25, 0x3C, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x40, 0x52, +0x40, 0x00, 0xFF, 0x25, 0x44, 0x52, 0x40, 0x00, 0xFF, 0x25, +0x48, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x4C, 0x52, 0x40, 0x00, +0xFF, 0x25, 0x50, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x54, 0x52, +0x40, 0x00, 0xFF, 0x25, 0x58, 0x52, 0x40, 0x00, 0xFF, 0x25, +0x5C, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x60, 0x52, 0x40, 0x00, +0xFF, 0x25, 0x64, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x68, 0x52, +0x40, 0x00, 0xFF, 0x25, 0x6C, 0x52, 0x40, 0x00, 0xFF, 0x25, +0x70, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x74, 0x52, 0x40, 0x00, +0xFF, 0x25, 0x78, 0x52, 0x40, 0x00, 0xFF, 0x25, 0x7C, 0x52, +0x40, 0x00, 0xFF, 0x25, 0x80, 0x52, 0x40, 0x00, 0xFF, 0x25, +0x5C, 0x53, 0x40, 0x00, 0xFF, 0x25, 0x68, 0x53, 0x40, 0x00, +0xFF, 0x25, 0x64, 0x53, 0x40, 0x00, 0xFF, 0x25, 0x60, 0x53, +0x40, 0x00, 0xFF, 0x25, 0x6C, 0x53, 0x40, 0x00, 0xFF, 0x25, +0x58, 0x53, 0x40, 0x00, 0xFF, 0x25, 0x54, 0x53, 0x40, 0x00, +0xFF, 0x25, 0x50, 0x53, 0x40, 0x00, 0xFF, 0x25, 0x4C, 0x53, +0x40, 0x00, 0xFF, 0x25, 0x48, 0x53, 0x40, 0x00, 0xFF, 0x25, +0x44, 0x53, 0x40, 0x00, 0xFF, 0x25, 0x40, 0x53, 0x40, 0x00, +0xFF, 0x25, 0x3C, 0x53, 0x40, 0x00, 0xFF, 0x25, 0x38, 0x53, +0x40, 0x00, 0x55, 0x8B, 0xEC, 0x6A, 0xFF, 0x68, 0x00, 0x30, +0x40, 0x00, 0x68, 0x40, 0x19, 0x40, 0x00, 0x64, 0xA1, 0x00, +0x00, 0x00, 0x00, 0x50, 0x64, 0x89, 0x25, 0x00, 0x00, 0x00, +0x00, 0x83, 0xEC, 0x68, 0x53, 0x56, 0x57, 0x89, 0x65, 0xE8, +0x33, 0xDB, 0x89, 0x5D, 0xFC, 0x6A, 0x02, 0xFF, 0x15, 0xD8, +0x52, 0x40, 0x00, 0x59, 0x83, 0x0D, 0x84, 0x45, 0x40, 0x00, +0xFF, 0x83, 0x0D, 0x94, 0x45, 0x40, 0x00, 0xFF, 0xFF, 0x15, +0xDC, 0x52, 0x40, 0x00, 0x8B, 0x0D, 0x80, 0x45, 0x40, 0x00, +0x89, 0x08, 0xFF, 0x15, 0xE0, 0x52, 0x40, 0x00, 0x8B, 0x0D, +0x7C, 0x45, 0x40, 0x00, 0x89, 0x08, 0xA1, 0xE4, 0x52, 0x40, +0x00, 0x8B, 0x00, 0xA3, 0x98, 0x45, 0x40, 0x00, 0xE8, 0x28, +0x01, 0x00, 0x00, 0x39, 0x1D, 0x58, 0x44, 0x40, 0x00, 0x75, +0x0C, 0x68, 0xDE, 0x18, 0x40, 0x00, 0xFF, 0x15, 0xE8, 0x52, +0x40, 0x00, 0x59, 0xE8, 0xF4, 0x00, 0x00, 0x00, 0x68, 0x0C, +0x43, 0x40, 0x00, 0x68, 0x08, 0x42, 0x40, 0x00, 0xE8, 0xDF, +0x00, 0x00, 0x00, 0xA1, 0x78, 0x45, 0x40, 0x00, 0x89, 0x45, +0x94, 0x8D, 0x45, 0x94, 0x50, 0xFF, 0x35, 0x74, 0x45, 0x40, +0x00, 0x8D, 0x45, 0x9C, 0x50, 0x8D, 0x45, 0x90, 0x50, 0x8D, +0x45, 0xA0, 0x50, 0xFF}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_6[1024] = { +0x15, 0xF0, 0x52, 0x40, 0x00, 0x68, 0x04, 0x41, 0x40, 0x00, +0x68, 0x00, 0x40, 0x40, 0x00, 0xE8, 0xAC, 0x00, 0x00, 0x00, +0x83, 0xC4, 0x24, 0xA1, 0xF4, 0x52, 0x40, 0x00, 0x8B, 0x30, +0x89, 0x75, 0x8C, 0x80, 0x3E, 0x22, 0x75, 0x3A, 0x46, 0x89, +0x75, 0x8C, 0x8A, 0x06, 0x3A, 0xC3, 0x74, 0x04, 0x3C, 0x22, +0x75, 0xF2, 0x80, 0x3E, 0x22, 0x75, 0x04, 0x46, 0x89, 0x75, +0x8C, 0x8A, 0x06, 0x3A, 0xC3, 0x74, 0x04, 0x3C, 0x20, 0x76, +0xF2, 0x89, 0x5D, 0xD0, 0x8D, 0x45, 0xA4, 0x50, 0xFF, 0x15, +0x84, 0x52, 0x40, 0x00, 0xF6, 0x45, 0xD0, 0x01, 0x74, 0x11, +0x0F, 0xB7, 0x45, 0xD4, 0xEB, 0x0E, 0x80, 0x3E, 0x20, 0x76, +0xD8, 0x46, 0x89, 0x75, 0x8C, 0xEB, 0xF5, 0x6A, 0x0A, 0x58, +0x50, 0x56, 0x53, 0x53, 0xFF, 0x15, 0x38, 0x52, 0x40, 0x00, +0x50, 0xE8, 0x8C, 0xF7, 0xFF, 0xFF, 0x89, 0x45, 0x98, 0x50, +0xFF, 0x15, 0xF8, 0x52, 0x40, 0x00, 0x8B, 0x45, 0xEC, 0x8B, +0x08, 0x8B, 0x09, 0x89, 0x4D, 0x88, 0x50, 0x51, 0xE8, 0x15, +0x00, 0x00, 0x00, 0x59, 0x59, 0xC3, 0x8B, 0x65, 0xE8, 0xFF, +0x75, 0x88, 0xFF, 0x15, 0xFC, 0x52, 0x40, 0x00, 0xFF, 0x25, +0xFC, 0x52, 0x40, 0x00, 0xFF, 0x25, 0xC4, 0x52, 0x40, 0x00, +0xFF, 0x25, 0xF8, 0x52, 0x40, 0x00, 0xFF, 0x25, 0xF0, 0x52, +0x40, 0x00, 0xFF, 0x25, 0xEC, 0x52, 0x40, 0x00, 0x68, 0x00, +0x00, 0x03, 0x00, 0x68, 0x00, 0x00, 0x01, 0x00, 0xE8, 0x71, +0x00, 0x00, 0x00, 0x59, 0x59, 0xC3, 0xFF, 0x25, 0xE8, 0x52, +0x40, 0x00, 0x33, 0xC0, 0xC3, 0xC3, 0xFF, 0x25, 0xE0, 0x52, +0x40, 0x00, 0xFF, 0x25, 0xDC, 0x52, 0x40, 0x00, 0x83, 0x3D, +0x94, 0x45, 0x40, 0x00, 0xFF, 0x75, 0x0C, 0xFF, 0x74, 0x24, +0x04, 0xFF, 0x15, 0xC8, 0x52, 0x40, 0x00, 0x59, 0xC3, 0x68, +0x84, 0x45, 0x40, 0x00, 0x68, 0x94, 0x45, 0x40, 0x00, 0xFF, +0x74, 0x24, 0x0C, 0xE8, 0x36, 0x00, 0x00, 0x00, 0x83, 0xC4, +0x0C, 0xC3, 0xFF, 0x74, 0x24, 0x04, 0xE8, 0xCB, 0xFF, 0xFF, +0xFF, 0xF7, 0xD8, 0x1B, 0xC0, 0x59, 0xF7, 0xD8, 0x48, 0xC3, +0xFF, 0x25, 0xD8, 0x52, 0x40, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xFF, 0x25, 0xD4, 0x52, 0x40, 0x00, 0xFF, 0x25, 0xD0, 0x52, +0x40, 0x00, 0xFF, 0x25, 0xCC, 0x52, 0x40, 0x00, 0xFF, 0x25, +0x84, 0x52, 0x40, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_7[1024] = { +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_8[1024] = { +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_9[1024] = { +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_10[1024] = { +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, +0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_11[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_12[1024] = { +0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x18, 0x40, 0x00, 0x9C, 0x18, +0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_13[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_14[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_15[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_16[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_17[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x44, 0x40, 0x00, +0x24, 0x44, 0x40, 0x00, 0x00, 0x00, 0xCF, 0x02, 0xC4, 0x08, +0x30, 0x51, 0x00, 0x00, 0x00, 0x00, 0x45, 0x44, 0x49, 0x54, +0x00, 0x00, 0x00, 0x00, 0x76, 0x74, 0x6B, 0x4F, 0x75, 0x74, +0x70, 0x75, 0x74, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x50, +0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x65, 0x78, 0x70, 0x6C, 0x6F, 0x72, 0x65, 0x72, +0x2E, 0x65, 0x78, 0x65, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_18[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_19[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_20[1024] = { +0x64, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xB6, 0x53, 0x00, 0x00, 0x04, 0x52, 0x00, 0x00, +0x94, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x20, 0x55, 0x00, 0x00, 0x34, 0x52, 0x00, 0x00, +0x98, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x12, 0x56, 0x00, 0x00, 0x38, 0x53, 0x00, 0x00, +0x24, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xCA, 0x56, 0x00, 0x00, 0xC4, 0x52, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xA4, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x53, +0x00, 0x00, 0xD0, 0x53, 0x00, 0x00, 0xE4, 0x53, 0x00, 0x00, +0xF0, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x10, 0x54, +0x00, 0x00, 0x24, 0x54, 0x00, 0x00, 0x3C, 0x54, 0x00, 0x00, +0x52, 0x54, 0x00, 0x00, 0x66, 0x54, 0x00, 0x00, 0x7A, 0x54, +0x00, 0x00, 0x90, 0x54, 0x00, 0x00, 0xA2, 0x54, 0x00, 0x00, +0xB2, 0x54, 0x00, 0x00, 0xC6, 0x54, 0x00, 0x00, 0xD4, 0x54, +0x00, 0x00, 0xE2, 0x54, 0x00, 0x00, 0xF0, 0x54, 0x00, 0x00, +0xF8, 0x54, 0x00, 0x00, 0x0E, 0x55, 0x00, 0x00, 0xFC, 0x56, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x26, 0x56, 0x00, 0x00, 0xF2, 0x56, 0x00, 0x00, +0xE4, 0x56, 0x00, 0x00, 0xD6, 0x56, 0x00, 0x00, 0xB6, 0x56, +0x00, 0x00, 0xA4, 0x56, 0x00, 0x00, 0x96, 0x56, 0x00, 0x00, +0x86, 0x56, 0x00, 0x00, 0x76, 0x56, 0x00, 0x00, 0x62, 0x56, +0x00, 0x00, 0x56, 0x56, 0x00, 0x00, 0x46, 0x56, 0x00, 0x00, +0x3C, 0x56, 0x00, 0x00, 0x34, 0x56, 0x00, 0x00, 0x1E, 0x56, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x56, +0x00, 0x00, 0xF4, 0x55, 0x00, 0x00, 0xE2, 0x55, 0x00, 0x00, +0xD0, 0x55, 0x00, 0x00, 0xC0, 0x55, 0x00, 0x00, 0xB4, 0x55, +0x00, 0x00, 0xA6, 0x55, 0x00, 0x00, 0x94, 0x55, 0x00, 0x00, +0x82, 0x55, 0x00, 0x00, 0x2E, 0x55, 0x00, 0x00, 0x64, 0x55, +0x00, 0x00, 0x56, 0x55, 0x00, 0x00, 0x42, 0x55, 0x00, 0x00, +0x74, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x53, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xC0, 0x53, 0x00, 0x00, 0xD0, 0x53, +0x00, 0x00, 0xE4, 0x53, 0x00, 0x00, 0xF0, 0x53, 0x00, 0x00, +0x00, 0x54, 0x00, 0x00, 0x10, 0x54, 0x00, 0x00, 0x24, 0x54, +0x00, 0x00, 0x3C, 0x54, 0x00, 0x00, 0x52, 0x54, 0x00, 0x00, +0x66, 0x54, 0x00, 0x00, 0x7A, 0x54, 0x00, 0x00, 0x90, 0x54, +0x00, 0x00, 0xA2, 0x54, 0x00, 0x00, 0xB2, 0x54, 0x00, 0x00, +0xC6, 0x54, 0x00, 0x00, 0xD4, 0x54, 0x00, 0x00, 0xE2, 0x54, +0x00, 0x00, 0xF0, 0x54, 0x00, 0x00, 0xF8, 0x54, 0x00, 0x00, +0x0E, 0x55, 0x00, 0x00, 0xFC, 0x56, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x56, +0x00, 0x00, 0xF2, 0x56, 0x00, 0x00, 0xE4, 0x56, 0x00, 0x00, +0xD6, 0x56, 0x00, 0x00, 0xB6, 0x56, 0x00, 0x00, 0xA4, 0x56, +0x00, 0x00, 0x96, 0x56, 0x00, 0x00, 0x86, 0x56, 0x00, 0x00, +0x76, 0x56, 0x00, 0x00, 0x62, 0x56, 0x00, 0x00, 0x56, 0x56, +0x00, 0x00, 0x46, 0x56, 0x00, 0x00, 0x3C, 0x56, 0x00, 0x00, +0x34, 0x56, 0x00, 0x00, 0x1E, 0x56, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x02, 0x56, 0x00, 0x00, 0xF4, 0x55, +0x00, 0x00, 0xE2, 0x55, 0x00, 0x00, 0xD0, 0x55, 0x00, 0x00, +0xC0, 0x55, 0x00, 0x00, 0xB4, 0x55, 0x00, 0x00, 0xA6, 0x55, +0x00, 0x00, 0x94, 0x55, 0x00, 0x00, 0x82, 0x55, 0x00, 0x00, +0x2E, 0x55, 0x00, 0x00, 0x64, 0x55, 0x00, 0x00, 0x56, 0x55, +0x00, 0x00, 0x42, 0x55, 0x00, 0x00, 0x74, 0x55, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x5F, 0x01, 0x47, 0x65, 0x74, 0x53, 0x74, 0x6F, +0x63, 0x6B, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, 0x00, +0x47, 0x44, 0x49, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, +0x4A, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x68, +0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x26, 0x01, 0x47, 0x65, +0x74, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x48, 0x61, 0x6E, +0x64, 0x6C, 0x65, 0x41, 0x00, 0x00, 0x18, 0x02, 0x52, 0x65, +0x61, 0x64, 0x46, 0x69, 0x6C, 0x65, 0x00, 0x00, 0x52, 0x01, +0x47, 0x65, 0x74, 0x53, 0x74, 0x64, 0x48, 0x61, 0x6E, 0x64, +0x6C, 0x65, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_21[1024] = { +0x2C, 0x02, 0x52, 0x65, 0x73, 0x75, 0x6D, 0x65, 0x54, 0x68, +0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x83, 0x02, 0x53, 0x65, +0x74, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x43, 0x6F, 0x6E, +0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0xAB, 0x00, 0x46, 0x6C, +0x75, 0x73, 0x68, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x63, +0x74, 0x69, 0x6F, 0x6E, 0x43, 0x61, 0x63, 0x68, 0x65, 0x00, +0xE9, 0x02, 0x57, 0x72, 0x69, 0x74, 0x65, 0x50, 0x72, 0x6F, +0x63, 0x65, 0x73, 0x73, 0x4D, 0x65, 0x6D, 0x6F, 0x72, 0x79, +0x00, 0x00, 0xC4, 0x02, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, +0x6C, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x45, 0x78, +0x00, 0x00, 0x67, 0x01, 0x47, 0x65, 0x74, 0x54, 0x68, 0x72, +0x65, 0x61, 0x64, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, 0x74, +0x00, 0x00, 0x24, 0x01, 0x47, 0x65, 0x74, 0x4D, 0x6F, 0x64, +0x75, 0x6C, 0x65, 0x46, 0x69, 0x6C, 0x65, 0x4E, 0x61, 0x6D, +0x65, 0x41, 0x00, 0x00, 0x63, 0x00, 0x44, 0x75, 0x70, 0x6C, +0x69, 0x63, 0x61, 0x74, 0x65, 0x48, 0x61, 0x6E, 0x64, 0x6C, +0x65, 0x00, 0x1A, 0x01, 0x47, 0x65, 0x74, 0x4C, 0x61, 0x73, +0x74, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x00, 0xF7, 0x00, +0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, +0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x00, 0x7D, 0x00, +0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, +0x73, 0x00, 0x1B, 0x00, 0x43, 0x6C, 0x6F, 0x73, 0x65, 0x48, +0x61, 0x6E, 0x64, 0x6C, 0x65, 0x00, 0x57, 0x00, 0x44, 0x65, +0x6C, 0x65, 0x74, 0x65, 0x46, 0x69, 0x6C, 0x65, 0x41, 0x00, +0x96, 0x02, 0x53, 0x6C, 0x65, 0x65, 0x70, 0x00, 0xCE, 0x02, +0x57, 0x61, 0x69, 0x74, 0x46, 0x6F, 0x72, 0x53, 0x69, 0x6E, +0x67, 0x6C, 0x65, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, +0x44, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, +0x6F, 0x63, 0x65, 0x73, 0x73, 0x41, 0x00, 0x00, 0x4B, 0x45, +0x52, 0x4E, 0x45, 0x4C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, +0x00, 0x00, 0x95, 0x00, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, +0x63, 0x68, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, +0x00, 0x00, 0x82, 0x02, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x6C, +0x61, 0x74, 0x65, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, +0x00, 0x00, 0x2A, 0x01, 0x47, 0x65, 0x74, 0x4D, 0x65, 0x73, +0x73, 0x61, 0x67, 0x65, 0x41, 0x00, 0x91, 0x02, 0x55, 0x70, +0x64, 0x61, 0x74, 0x65, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, +0x00, 0x00, 0x6A, 0x02, 0x53, 0x68, 0x6F, 0x77, 0x57, 0x69, +0x6E, 0x64, 0x6F, 0x77, 0x00, 0x00, 0x59, 0x00, 0x43, 0x72, +0x65, 0x61, 0x74, 0x65, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, +0x45, 0x78, 0x41, 0x00, 0xF2, 0x01, 0x52, 0x65, 0x67, 0x69, +0x73, 0x74, 0x65, 0x72, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x41, +0x00, 0x00, 0x9A, 0x01, 0x4C, 0x6F, 0x61, 0x64, 0x43, 0x75, +0x72, 0x73, 0x6F, 0x72, 0x41, 0x00, 0x9E, 0x01, 0x4C, 0x6F, +0x61, 0x64, 0x49, 0x63, 0x6F, 0x6E, 0x41, 0x00, 0xE7, 0x00, +0x47, 0x65, 0x74, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x49, 0x6E, +0x66, 0x6F, 0x41, 0x00, 0x84, 0x00, 0x44, 0x65, 0x66, 0x57, +0x69, 0x6E, 0x64, 0x6F, 0x77, 0x50, 0x72, 0x6F, 0x63, 0x41, +0x00, 0x00, 0xE0, 0x01, 0x50, 0x6F, 0x73, 0x74, 0x51, 0x75, +0x69, 0x74, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x00, +0xC9, 0x01, 0x4D, 0x6F, 0x76, 0x65, 0x57, 0x69, 0x6E, 0x64, +0x6F, 0x77, 0x00, 0x00, 0x14, 0x02, 0x53, 0x65, 0x6E, 0x64, +0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x00, 0x00, +0x55, 0x53, 0x45, 0x52, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, +0x00, 0x00, 0xD3, 0x00, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x00, +0x48, 0x00, 0x5F, 0x58, 0x63, 0x70, 0x74, 0x46, 0x69, 0x6C, +0x74, 0x65, 0x72, 0x00, 0x49, 0x02, 0x65, 0x78, 0x69, 0x74, +0x00, 0x00, 0x8F, 0x00, 0x5F, 0x61, 0x63, 0x6D, 0x64, 0x6C, +0x6E, 0x00, 0x58, 0x00, 0x5F, 0x5F, 0x67, 0x65, 0x74, 0x6D, +0x61, 0x69, 0x6E, 0x61, 0x72, 0x67, 0x73, 0x00, 0x0F, 0x01, +0x5F, 0x69, 0x6E, 0x69, 0x74, 0x74, 0x65, 0x72, 0x6D, 0x00, +0x83, 0x00, 0x5F, 0x5F, 0x73, 0x65, 0x74, 0x75, 0x73, 0x65, +0x72, 0x6D, 0x61, 0x74, 0x68, 0x65, 0x72, 0x72, 0x00, 0x00, +0x9D, 0x00, 0x5F, 0x61, 0x64, 0x6A, 0x75, 0x73, 0x74, 0x5F, +0x66, 0x64, 0x69, 0x76, 0x00, 0x00, 0x6A, 0x00, 0x5F, 0x5F, +0x70, 0x5F, 0x5F, 0x63, 0x6F, 0x6D, 0x6D, 0x6F, 0x64, 0x65, +0x00, 0x00, 0x6F, 0x00, 0x5F, 0x5F, 0x70, 0x5F, 0x5F, 0x66, +0x6D, 0x6F, 0x64, 0x65, 0x00, 0x00, 0x81, 0x00, 0x5F, 0x5F, +0x73, 0x65, 0x74, 0x5F, 0x61, 0x70, 0x70, 0x5F, 0x74, 0x79, +0x70, 0x65, 0x00, 0x00, 0xCA, 0x00, 0x5F, 0x65, 0x78, 0x63, +0x65, 0x70, 0x74, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, +0x72, 0x33, 0x00, 0x00, 0x4D, 0x53, 0x56, 0x43, 0x52, 0x54, +0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x00, 0xB7, 0x00, 0x5F, 0x63, +0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x66, 0x70, 0x00, 0x00, +0x55, 0x00, 0x5F, 0x5F, 0x64, 0x6C, 0x6C, 0x6F, 0x6E, 0x65, +0x78, 0x69, 0x74, 0x00, 0x86, 0x01, 0x5F, 0x6F, 0x6E, 0x65, +0x78, 0x69, 0x74, 0x00, 0x50, 0x01, 0x47, 0x65, 0x74, 0x53, +0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x49, 0x6E, 0x66, 0x6F, +0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_22[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_23[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_24[1024] = { +0x00, 0x10, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x2B, 0x30, +0x3F, 0x30, 0x45, 0x30, 0xAF, 0x30, 0xBB, 0x30, 0xCF, 0x30, +0xD9, 0x30, 0xE8, 0x30, 0xF0, 0x30, 0xF6, 0x30, 0xFC, 0x30, +0x13, 0x31, 0x1E, 0x31, 0x26, 0x31, 0x2C, 0x31, 0x32, 0x31, +0x39, 0x31, 0x47, 0x31, 0x54, 0x31, 0xB2, 0x31, 0xC0, 0x31, +0xCD, 0x31, 0xE2, 0x31, 0xF9, 0x31, 0x0A, 0x32, 0x16, 0x32, +0x1C, 0x32, 0x3F, 0x32, 0x98, 0x32, 0xB4, 0x32, 0xBE, 0x32, +0xD0, 0x32, 0x0A, 0x33, 0x2D, 0x33, 0x3B, 0x33, 0x44, 0x33, +0x5B, 0x33, 0x0B, 0x34, 0x1B, 0x34, 0x29, 0x34, 0x2F, 0x34, +0x34, 0x34, 0x3B, 0x34, 0x48, 0x34, 0x4F, 0x34, 0x78, 0x34, +0x96, 0x34, 0xAB, 0x34, 0xB9, 0x34, 0xD9, 0x34, 0x19, 0x35, +0x31, 0x35, 0x42, 0x35, 0x55, 0x35, 0x60, 0x35, 0x7A, 0x36, +0x80, 0x36, 0x86, 0x36, 0x8C, 0x36, 0x92, 0x36, 0x98, 0x36, +0x9E, 0x36, 0xA4, 0x36, 0xAA, 0x36, 0xB0, 0x36, 0xB6, 0x36, +0xBC, 0x36, 0xC2, 0x36, 0xC8, 0x36, 0xCE, 0x36, 0xD4, 0x36, +0xDA, 0x36, 0xE0, 0x36, 0xE6, 0x36, 0xEC, 0x36, 0xF2, 0x36, +0xF8, 0x36, 0xFE, 0x36, 0x04, 0x37, 0x0A, 0x37, 0x10, 0x37, +0x16, 0x37, 0x1C, 0x37, 0x22, 0x37, 0x28, 0x37, 0x2E, 0x37, +0x34, 0x37, 0x3A, 0x37, 0x40, 0x37, 0x46, 0x37, 0x50, 0x37, +0x55, 0x37, 0x79, 0x37, 0x80, 0x37, 0x87, 0x37, 0x8E, 0x37, +0x94, 0x37, 0x9C, 0x37, 0xA2, 0x37, 0xA9, 0x37, 0xB0, 0x37, +0xBB, 0x37, 0xC2, 0x37, 0xC8, 0x37, 0xD3, 0x37, 0xD8, 0x37, +0xE2, 0x37, 0xEF, 0x37, 0x01, 0x38, 0x06, 0x38, 0x0B, 0x38, +0x18, 0x38, 0x50, 0x38, 0x74, 0x38, 0x84, 0x38, 0xA4, 0x38, +0xAA, 0x38, 0xB0, 0x38, 0xB6, 0x38, 0xBC, 0x38, 0xC2, 0x38, +0xDA, 0x38, 0xE4, 0x38, 0xEA, 0x38, 0xF0, 0x38, 0xFD, 0x38, +0x04, 0x39, 0x09, 0x39, 0x2E, 0x39, 0x42, 0x39, 0x48, 0x39, +0x4E, 0x39, 0x54, 0x39, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, +0x0C, 0x00, 0x00, 0x00, 0x04, 0x30, 0x08, 0x30, 0x00, 0x40, +0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x10, 0x34, 0x14, 0x34, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_25[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_26[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +static unsigned char vtkEncodedArrayWin32OutputWindowProcess_27[1024] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00}; + +extern int vtkEncodedArrayWin32OutputWindowProcessWrite(const char* fname) +{ + FILE* ofp = fopen(fname, "wb"); + if(!ofp) { return 0; } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_0, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_0), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_0)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_1, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_1), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_1)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_2, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_2), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_2)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_3, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_3), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_3)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_4, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_4), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_4)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_5, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_5), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_5)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_6, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_6), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_6)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_7, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_7), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_7)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_8, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_8), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_8)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_9, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_9), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_9)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_10, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_10), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_10)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_11, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_11), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_11)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_12, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_12), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_12)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_13, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_13), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_13)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_14, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_14), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_14)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_15, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_15), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_15)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_16, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_16), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_16)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_17, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_17), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_17)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_18, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_18), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_18)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_19, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_19), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_19)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_20, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_20), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_20)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_21, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_21), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_21)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_22, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_22), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_22)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_23, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_23), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_23)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_24, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_24), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_24)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_25, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_25), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_25)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_26, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_26), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_26)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + if(fwrite(vtkEncodedArrayWin32OutputWindowProcess_27, 1, + sizeof(vtkEncodedArrayWin32OutputWindowProcess_27), ofp) != + sizeof(vtkEncodedArrayWin32OutputWindowProcess_27)) + { + fclose(ofp); + _unlink(fname); + return 0; + } + fclose(ofp); + return 1; +} diff --git a/Common/vtkWin32ProcessOutputWindow.cxx b/Common/vtkWin32ProcessOutputWindow.cxx new file mode 100644 index 0000000..a3454f0 --- /dev/null +++ b/Common/vtkWin32ProcessOutputWindow.cxx @@ -0,0 +1,171 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32ProcessOutputWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWin32ProcessOutputWindow.h" + +#include "vtkObjectFactory.h" +#include "vtkWindows.h" + +#include + +#ifndef _MAX_FNAME +# define _MAX_FNAME 4096 +#endif +#ifndef _MAX_PATH +# define _MAX_PATH 4096 +#endif + +vtkCxxRevisionMacro(vtkWin32ProcessOutputWindow, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkWin32ProcessOutputWindow); + +extern "C" int vtkEncodedArrayWin32OutputWindowProcessWrite(const char* fname); + +//---------------------------------------------------------------------------- +vtkWin32ProcessOutputWindow::vtkWin32ProcessOutputWindow() +{ + this->OutputPipe = 0; + this->Broken = 0; + this->Count = 0; +} + +//---------------------------------------------------------------------------- +vtkWin32ProcessOutputWindow::~vtkWin32ProcessOutputWindow() +{ + if(this->OutputPipe) + { + CloseHandle(this->OutputPipe); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32ProcessOutputWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkWin32ProcessOutputWindow::DisplayText(const char* text) +{ + // Display the text if the pipe has not been broken. + if(!this->Broken && text) + { + const char* begin = text; + while(const char* end = strchr(begin, '\n')) + { + this->Write(begin, end-begin); + this->Write("\r\n", 2); + begin = end+1; + } + this->Write(begin, strlen(begin)); + } +} + +//---------------------------------------------------------------------------- +int vtkWin32ProcessOutputWindow::Initialize() +{ + // Write the executable as a temporary file. It will delete itself. + char exeName[_MAX_FNAME+1] = ""; + char tempDir[_MAX_PATH+1] = ""; + + // We will try putting the executable in the system temp directory. + // Note that the returned path already has a trailing slash. + DWORD length = GetTempPath(_MAX_PATH+1, tempDir); + if(length <= 0 || length > _MAX_PATH) + { + return 0; + } + + // Construct the executable name from the process id, pointer to + // this output window instance, and a count. This should be unique. + sprintf(exeName, "vtkWin32OWP_%u_%p_%u.exe", + GetCurrentProcessId(), this, this->Count++); + + // Allocate a buffer to hold the executable path. + size_t tdlen = strlen(tempDir); + char* exeFullPath = (char*)malloc(tdlen + strlen(exeName) + 2); + if(!exeFullPath) + { + return 0; + } + + // Construct the full path to the executable. + sprintf(exeFullPath, "%s%s", tempDir, exeName); + + // Try to write the executable to disk. + if(!vtkEncodedArrayWin32OutputWindowProcessWrite(exeFullPath)) + { + free(exeFullPath); + return 0; + } + + // Create a process and a pipe connected to its stdin. + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.dwFlags |= STARTF_USESHOWWINDOW; + si.dwFlags |= STARTF_USESTDHANDLES; + si.wShowWindow = SW_SHOWDEFAULT; + + // Create a pipe with an inherited read end. + if(!CreatePipe(&si.hStdInput, &this->OutputPipe, 0, 0) || + !DuplicateHandle(GetCurrentProcess(), si.hStdInput, + GetCurrentProcess(), &si.hStdInput, + 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) + { + DeleteFile(exeFullPath); + free(exeFullPath); + return 0; + } + + // Create the child process. + if(!CreateProcess(0, exeFullPath, 0, 0, TRUE, + NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi)) + { + DeleteFile(exeFullPath); + free(exeFullPath); + CloseHandle(si.hStdInput); + return 0; + } + + // We only need to keep the pipe write end. Close all other handles. + CloseHandle(si.hStdInput); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + free(exeFullPath); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkWin32ProcessOutputWindow::Write(const char* data, int length) +{ + if(data && length) + { + // Initialize the output pipe the first time. + if(this->Broken || !this->OutputPipe && !this->Initialize()) + { + this->Broken = 1; + return; + } + + // Write the data to the pipe. If it breaks, close the pipe. + DWORD nWritten; + if(!WriteFile(this->OutputPipe, data, length, &nWritten, 0)) + { + this->Broken = 1; + CloseHandle(this->OutputPipe); + this->OutputPipe = 0; + } + } +} diff --git a/Common/vtkWin32ProcessOutputWindow.h b/Common/vtkWin32ProcessOutputWindow.h new file mode 100644 index 0000000..fc390b5 --- /dev/null +++ b/Common/vtkWin32ProcessOutputWindow.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32ProcessOutputWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWin32ProcessOutputWindow - Win32-specific output window class +// .SECTION Description +// vtkWin32ProcessOutputWindow executes a process and sends messages +// to its standard input pipe. This is useful to have a separate +// process display VTK errors so that if a VTK application crashes, +// the error messages are still available. + +#ifndef __vtkWin32ProcessOutputWindow_h +#define __vtkWin32ProcessOutputWindow_h + +#include "vtkOutputWindow.h" + +class VTK_COMMON_EXPORT vtkWin32ProcessOutputWindow : public vtkOutputWindow +{ +public: + vtkTypeRevisionMacro(vtkWin32ProcessOutputWindow,vtkOutputWindow); + static vtkWin32ProcessOutputWindow* New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Send text to the output window process. + virtual void DisplayText(const char*); + +protected: + vtkWin32ProcessOutputWindow(); + ~vtkWin32ProcessOutputWindow(); + + int Initialize(); + void Write(const char* data, int length); + + // The write end of the pipe to the child process. + vtkWindowsHANDLE OutputPipe; + + // Whether the pipe has been broken. + int Broken; + + // Count the number of times a new child has been initialized. + unsigned int Count; +private: + vtkWin32ProcessOutputWindow(const vtkWin32ProcessOutputWindow&); // Not implemented. + void operator=(const vtkWin32ProcessOutputWindow&); // Not implemented. +}; + +#endif diff --git a/Common/vtkWinCE.cxx b/Common/vtkWinCE.cxx new file mode 100644 index 0000000..259a5f1 --- /dev/null +++ b/Common/vtkWinCE.cxx @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWinCE.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include "vtkWinCE.h" + +char *endl = "\n"; // declare endl here +ostream cout; // declare cout here +ostream cerr; // declare cerr here +istream cin; // declare cin here + + +ostream & ostream::operator <<(const char *str) +{ + printf("%s",str); return *this; +} + +ostream & ostream::operator <<(int x) // integers +{ + printf("%d",x); + return *this; +} + +ostream & ostream::operator <<(void *x) // integers +{ + printf("%p",x); + return *this; +} + +ostream & ostream::operator <<(unsigned int x) // integers +{ + printf("%u",x); + return *this; +} + + +ostream & ostream::operator <<(long l) // long integers +{ + printf( "%ld",l); + return *this; +} + +ostream & ostream::operator <<(unsigned long l) // long integers +{ + printf( "%lu",l); + return *this; +} + +ostream & ostream::operator << (char ch) // characters +{ + printf("%c",ch); + return *this; +} + + +ostream & ostream::operator <<(float fl ) // floats +{ + printf("%f",fl); + return *this; +} + + +ostream & ostream::operator << (double dbl) // double floats +{ + printf("%lf",dbl); + return *this; +} + +////////////////////////// istream members //////////////////////////////// + +istream & istream::operator >>(char *str) // strings +{ + gets(str); + return *this; +} + +istream & istream::operator >>(int &x) // integers +{ + scanf("%d",&x); + return *this; +} + +istream & istream::operator >> (char &ch) // characters +{ + scanf("%c",&ch); + return *this; +} + +istream & istream::operator >>(float &fl ) // floats +{ + scanf("%f",&fl); + return *this; +} + +istream & istream::operator >> (double &dbl ) // doubles +{ + scanf("%lf",&dbl); + return *this; +} + + diff --git a/Common/vtkWinCE.h b/Common/vtkWinCE.h new file mode 100644 index 0000000..4c7a331 --- /dev/null +++ b/Common/vtkWinCE.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWinCE.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWinCE - support for C++ functionality missing in WinCE +// .SECTION Description +// This is a half baked implementaiton of some of the key features +// missing from WindowsCE. Half of this is implemented and half is +// missing. + +#ifndef vtkWinCE_h + +#define vtkWinCE_h +#define VTK_LEAN_AND_MEAN + +struct ostream // Output stream +{ + ostream & operator <<(const char *str); // strings + ostream & operator <<(void *str); // pointers + ostream & operator <<(short x) ; // integers + ostream & operator <<(unsigned short x) ; // integers + ostream & operator <<(int x) ; // integers + ostream & operator <<(unsigned int x) ; // integers + ostream &operator <<(long l) ; // long integers + ostream &operator <<(unsigned long l) ; // long integers + ostream & operator << (char ch) ; // characters + ostream & operator <<(float fl ) ; // floats + ostream & operator << (double dbl); // double floats + + write(void *data, size_t size); + void flush() {}; +}; + +struct ofstream // Output stream +{ + ofstream & operator <<(const char *str); // strings + ofstream & operator <<(void *str); // pointers + ofstream & operator <<(short x) ; // integers + ofstream & operator <<(unsigned short x) ; // integers + ofstream & operator <<(int x) ; // integers + ofstream &operator <<(long l) ; // long integers + ofstream &operator <<(unsigned long l) ; // long integers + ofstream & operator << (char ch) ; // characters + ofstream & operator <<(float fl ) ; // floats + ofstream & operator << (double dbl); // double floats + + write(void *data, size_t size); +}; + +struct ostrhelp +{ + freeze(int i); +}; + +struct ostrstream // Output stream +{ + ostrstream & operator <<(char *str); // strings + ostrstream & operator <<(void *str); // pointers + ostrstream & operator <<(int x) ; // integers + ostrstream &operator <<(long l) ; // long integers + ostrstream & operator << (char ch) ; // characters + ostrstream & operator <<(float fl ) ; // floats + ostrstream & operator << (double dbl); // double floats + + char *str(); + ostrhelp *rdbuf(); +}; + + +struct istream +{ + int get(char &c) { c = (char)getchar(); return c;} + int putback(char &c) { return ungetc(c,stdin);} + istream & operator >>(char *str); // strings + istream & operator >>(int &x) ; // integers + istream & operator >> (char &ch) ; // characters + istream & operator >> (float &fl ) ; // floats + istream & operator >> (double &dbl ); // doubles +}; + + + +extern char *endl; +extern ostream cout; +extern ostream cerr; +extern istream cin; + +#endif vtkWinCE_h diff --git a/Common/vtkWindow.cxx b/Common/vtkWindow.cxx new file mode 100644 index 0000000..e3a5d78 --- /dev/null +++ b/Common/vtkWindow.cxx @@ -0,0 +1,150 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWindow.h" + +#include "vtkToolkits.h" + +vtkCxxRevisionMacro(vtkWindow, "$Revision: 1.27 $"); + +// Construct an instance of vtkRenderWindow with its screen size +// set to 300x300, borders turned on, positioned at (0,0), double +// buffering turned on. +vtkWindow::vtkWindow() +{ +#ifdef VTK_USE_OFFSCREEN + this->OffScreenRendering = 1; +#else + this->OffScreenRendering = 0; +#endif + this->Size[0] = this->Size[1] = 0; + this->Position[0] = this->Position[1] = 0; + this->Mapped = 0; + this->WindowName = new char[strlen("Visualization Toolkit")+1]; + strcpy( this->WindowName, "Visualization Toolkit" ); + this->Erase = 1; + this->DoubleBuffer = 0; + this->DPI = 120; + this->TileViewport[0] = 0; + this->TileViewport[1] = 0; + this->TileViewport[2] = 1.0; + this->TileViewport[3] = 1.0; + this->TileSize[0] = 0; + this->TileSize[1] = 0; + this->TileScale[0] = 1; + this->TileScale[1] = 1; +} + +// Destructor for the vtkWindow object. +vtkWindow::~vtkWindow() +{ + if( this->WindowName ) + { + delete [] this->WindowName; + this->WindowName = NULL; + } +} + +void vtkWindow::SetWindowName( const char * _arg ) +{ + vtkDebugMacro("Debug: In " __FILE__ << ", line " << __LINE__ << "\n" + << this->GetClassName() << " (" << this << "): setting " + << this->WindowName << " to " << _arg << "\n\n"); + + if ( this->WindowName && _arg && (!strcmp(this->WindowName,_arg))) + { + return; + } + if (this->WindowName) + { + delete [] this->WindowName; + } + this->WindowName = new char[strlen(_arg) + 1]; + strcpy(this->WindowName, _arg); + this->Modified(); +} + +int *vtkWindow::GetSize() +{ + this->TileSize[0] = this->Size[0]*this->TileScale[0]; + this->TileSize[1] = this->Size[1]*this->TileScale[1]; + + return this->TileSize; +} + +void vtkWindow::SetSize(int a[2]) +{ + this->SetSize(a[0],a[1]); +} + +void vtkWindow::SetSize(int x, int y) +{ + if ((this->Size[0] != x)||(this->Size[1] != y)) + { + this->Modified(); + this->Size[0] = x; + this->Size[1] = y; + } +} + +int *vtkWindow::GetPosition() +{ + return this->Position; +} + +void vtkWindow::SetPosition(int a[2]) +{ + this->SetPosition(a[0],a[1]); +} +void vtkWindow::SetPosition(int x, int y) +{ + if ((this->Position[0] != x)||(this->Position[1] != y)) + { + this->Modified(); + this->Position[0] = x; + this->Position[1] = y; + } +} + +void vtkWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Erase: " << (this->Erase ? "On\n" : "Off\n"); + if ( this->WindowName ) + { + os << indent << "Window Name: " << this->WindowName << "\n"; + } + else + { + os << indent << "Window Name: (none)\n"; + } + + // Can only print out the ivars because the window may not have been + // created yet. + // temp = this->GetPosition(); + os << indent << "Position: (" << this->Position[0] << ", " << this->Position[1] << ")\n"; + // temp = this->GetSize(); + os << indent << "Size: (" << this->Size[0] << ", " << this->Size[1] << ")\n"; + os << indent << "Mapped: " << this->Mapped << "\n"; + os << indent << "OffScreenRendering: " << this->OffScreenRendering << "\n"; + os << indent << "Double Buffered: " << this->DoubleBuffer << "\n"; + os << indent << "DPI: " << this->DPI << "\n"; + os << indent << "TileScale: (" << this->TileScale[0] << ", " + << this->TileScale[1] << ")\n"; + os << indent << "TileViewport: (" << this->TileViewport[0] << ", " + << this->TileViewport[1] << ", " << this->TileViewport[2] << ", " + << this->TileViewport[3] << ")\n"; +} + diff --git a/Common/vtkWindow.h b/Common/vtkWindow.h new file mode 100644 index 0000000..b054821 --- /dev/null +++ b/Common/vtkWindow.h @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWindow - window superclass for vtkRenderWindow +// .SECTION Description +// vtkWindow is an abstract object to specify the behavior of a +// rendering window. It contains vtkViewports. + +// .SECTION see also +// vtkRenderWindow vtkViewport + +#ifndef __vtkWindow_h +#define __vtkWindow_h + +#include "vtkObject.h" + +class vtkUnsignedCharArray; + +class VTK_COMMON_EXPORT vtkWindow : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkWindow,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // These are window system independent methods that are used + // to help interface vtkWindow to native windowing systems. + virtual void SetDisplayId(void *) = 0; + virtual void SetWindowId(void *) = 0; + virtual void SetParentId(void *) = 0; + virtual void *GetGenericDisplayId() = 0; + virtual void *GetGenericWindowId() = 0; + virtual void *GetGenericParentId() = 0; + virtual void *GetGenericContext() = 0; + virtual void *GetGenericDrawable() = 0; + virtual void SetWindowInfo(char *) = 0; + virtual void SetParentInfo(char *) = 0; + + // Description: + // Set/Get the position in screen coordinates of the rendering window. + virtual int *GetPosition(); + virtual void SetPosition(int,int); + virtual void SetPosition(int a[2]); + + // Description: + // Set/Get the size of the window in screen coordinates. + virtual int *GetSize(); + virtual void SetSize(int,int); + virtual void SetSize(int a[2]); + + // Description: + // Get the size of the screen in pixels + virtual int *GetScreenSize() = 0; + + // Description: + // Keep track of whether the rendering window has been mapped to screen. + vtkSetMacro(Mapped,int); + vtkGetMacro(Mapped,int); + vtkBooleanMacro(Mapped,int); + + // Description: + // Turn on/off erasing the screen between images. This allows multiple + // exposure sequences if turned on. You will need to turn double + // buffering off or make use of the SwapBuffers methods to prevent + // you from swapping buffers between exposures. + vtkSetMacro(Erase,int); + vtkGetMacro(Erase,int); + vtkBooleanMacro(Erase,int); + + // Description: + // Keep track of whether double buffering is on or off + vtkSetMacro(DoubleBuffer,int); + vtkGetMacro(DoubleBuffer,int); + vtkBooleanMacro(DoubleBuffer,int); + + // Description: + // Get name of rendering window + vtkGetStringMacro(WindowName); + virtual void SetWindowName(const char *); + + // Description: + // Ask each viewport owned by this Window to render its image and + // synchronize this process. + virtual void Render() = 0; + + // Description: + // Get the pixel data of an image, transmitted as RGBRGBRGB. The + // front argument indicates if the front buffer should be used or the back + // buffer. It is the caller's responsibility to delete the resulting + // array. It is very important to realize that the memory in this array + // is organized from the bottom of the window to the top. The origin + // of the screen is in the lower left corner. The y axis increases as + // you go up the screen. So the storage of pixels is from left to right + // and from bottom to top. + virtual unsigned char *GetPixelData(int, int, int, int, int) = 0; + virtual int GetPixelData(int ,int ,int ,int , int, + vtkUnsignedCharArray*) = 0; + + // Description: + // Return a best estimate to the dots per inch of the display + // device being rendered (or printed). + vtkGetMacro(DPI,int); + vtkSetClampMacro(DPI,int,1,3000); + + // Description: + // Create a window in memory instead of on the screen. This may not be + // supported for every type of window and on some windows you may need to + // invoke this prior to the first render. + vtkSetMacro(OffScreenRendering,int); + vtkGetMacro(OffScreenRendering,int); + vtkBooleanMacro(OffScreenRendering,int); + + // Description: + // Make the window current. May be overridden in subclasses to do + // for example a glXMakeCurrent or a wglMakeCurrent. + virtual void MakeCurrent() {}; + + // Description: + // These methods are used by vtkWindowToImageFilter to tell a VTK window + // to simulate a larger window by tiling. For 3D geometry these methods + // have no impact. It is just in handling annotation that this information + // must be available to the mappers and the coordinate calculations. + vtkSetVector2Macro(TileScale,int); + vtkGetVector2Macro(TileScale,int); + void SetTileScale(int s) {this->SetTileScale(s,s);} + vtkSetVector4Macro(TileViewport,double); + vtkGetVector4Macro(TileViewport,double); + +protected: + int OffScreenRendering; + vtkWindow(); + ~vtkWindow(); + + char *WindowName; + int Size[2]; + int Position[2]; + int Mapped; + int Erase; + int DoubleBuffer; + int DPI; + + double TileViewport[4]; + int TileSize[2]; + int TileScale[2]; + +private: + vtkWindow(const vtkWindow&); // Not implemented. + void operator=(const vtkWindow&); // Not implemented. +}; + +#endif + + diff --git a/Common/vtkWindowLevelLookupTable.cxx b/Common/vtkWindowLevelLookupTable.cxx new file mode 100644 index 0000000..b43ab16 --- /dev/null +++ b/Common/vtkWindowLevelLookupTable.cxx @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindowLevelLookupTable.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWindowLevelLookupTable.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkWindowLevelLookupTable, "$Revision: 1.24.4.1 $"); +vtkStandardNewMacro(vtkWindowLevelLookupTable); + +//---------------------------------------------------------------------------- +vtkWindowLevelLookupTable::vtkWindowLevelLookupTable(int sze, int ext) + : vtkLookupTable(sze, ext) +{ + this->Level = (this->TableRange[0] + this->TableRange[1])/2; + this->Window = (this->TableRange[1] - this->TableRange[0]); + + this->InverseVideo = 0; + + this->MinimumTableValue[0] = 0.0; + this->MinimumTableValue[1] = 0.0; + this->MinimumTableValue[2] = 0.0; + this->MinimumTableValue[3] = 1.0; + + this->MaximumTableValue[0] = 1.0; + this->MaximumTableValue[1] = 1.0; + this->MaximumTableValue[2] = 1.0; + this->MaximumTableValue[3] = 1.0; +} + +//---------------------------------------------------------------------------- +// Table is built as a linear ramp between MinimumTableValue and +// MaximumTableValue. +void vtkWindowLevelLookupTable::Build() +{ + if (this->Table->GetNumberOfTuples() < 1 || + (this->GetMTime() > this->BuildTime && + this->InsertTime < this->BuildTime)) + { + int i, j; + unsigned char *rgba; + double start[4], incr[4]; + + for (j = 0; j < 4; j++) + { + start[j] = this->MinimumTableValue[j]*255; + incr[j] = ((this->MaximumTableValue[j]-this->MinimumTableValue[j]) / + (this->NumberOfColors - 1) * 255); + } + + if (this->InverseVideo) + { + for (i = 0; i < this->NumberOfColors; i++) + { + rgba = this->Table->WritePointer(4*i,4); + for (j = 0; j < 4; j++) + { + rgba[j] = (unsigned char) \ + (start[j] + (this->NumberOfColors - i - 1)*incr[j] + 0.5); + } + } + } + else + { + for (i = 0; i < this->NumberOfColors; i++) + { + rgba = this->Table->WritePointer(4*i,4); + for (j = 0; j < 4; j++) + { + rgba[j] = (unsigned char)(start[j] + i*incr[j] + 0.5); + } + } + } + } + this->BuildTime.Modified(); +} + +//---------------------------------------------------------------------------- +// Reverse the color table (don't rebuild in case someone has +// been adjusting the table values by hand) +// This is a little ugly ... it might be best to remove +// SetInverseVideo altogether and just use a negative Window. +void vtkWindowLevelLookupTable::SetInverseVideo(int iv) +{ + if (this->InverseVideo == iv) + { + return; + } + + this->InverseVideo = iv; + + if (this->Table->GetNumberOfTuples() < 1) + { + return; + } + + unsigned char *rgba, *rgba2; + unsigned char tmp[4]; + int i; + int n = this->NumberOfColors-1; + + for (i = 0; i < this->NumberOfColors/2; i++) + { + rgba = this->Table->WritePointer(4*i,4); + rgba2 = this->Table->WritePointer(4*(n-i),4); + tmp[0]=rgba[0]; tmp[1]=rgba[1]; tmp[2]=rgba[2]; tmp[3]=rgba[3]; + rgba[0]=rgba2[0]; rgba[1]=rgba2[1]; rgba[2]=rgba2[2]; rgba[3]=rgba2[3]; + rgba2[0]=tmp[0]; rgba2[1]=tmp[1]; rgba2[2]=tmp[2]; rgba2[3]=tmp[3]; + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkWindowLevelLookupTable::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Window: " << this->Window << "\n"; + os << indent << "Level: " << this->Level << "\n"; + os << indent << "InverseVideo: " + << (this->InverseVideo ? "On\n" : "Off\n"); + os << indent << "MinimumTableValue : (" + << this->MinimumTableValue[0] << ", " + << this->MinimumTableValue[1] << ", " + << this->MinimumTableValue[2] << ", " + << this->MinimumTableValue[3] << ")\n"; + os << indent << "MaximumTableValue : (" + << this->MaximumTableValue[0] << ", " + << this->MaximumTableValue[1] << ", " + << this->MaximumTableValue[2] << ", " + << this->MaximumTableValue[3] << ")\n"; +} + + +//---------------------------------------------------------------------------- +// Deprecated methods: + +#ifndef VTK_LEGACY_REMOVE +void vtkWindowLevelLookupTable::SetMinimumColor(int r, int g, int b, int a) +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::SetMinimumColor, "VTK 5.0", + vtkWindowLevelLookupTable::SetMinimumTableValue); + this->SetMinimumTableValue(r*255.0,g*255.0,b*255.0,a*255.0); +} + +void vtkWindowLevelLookupTable::SetMinimumColor(const unsigned char rgba[4]) +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::SetMinimumColor, "VTK 5.0", + vtkWindowLevelLookupTable::SetMinimumTableValue); + this->SetMinimumTableValue(rgba[0]*255,rgba[1]*255,rgba[2]*255,rgba[3]*255); +} + +void vtkWindowLevelLookupTable::GetMinimumColor(unsigned char rgba[4]) +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::GetMinimumColor, "VTK 5.0", + vtkWindowLevelLookupTable::GetMinimumTableValue); + rgba[0] = int(this->MinimumTableValue[0]*255); + rgba[1] = int(this->MinimumTableValue[1]*255); + rgba[2] = int(this->MinimumTableValue[2]*255); + rgba[3] = int(this->MinimumTableValue[3]*255); +} + +unsigned char *vtkWindowLevelLookupTable::GetMinimumColor() +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::GetMinimumColor, "VTK 5.0", + vtkWindowLevelLookupTable::GetMinimumTableValue); + static unsigned char minimumcolor[4]; + minimumcolor[0] = int(this->MinimumTableValue[0]*255); + minimumcolor[1] = int(this->MinimumTableValue[1]*255); + minimumcolor[2] = int(this->MinimumTableValue[2]*255); + minimumcolor[3] = int(this->MinimumTableValue[3]*255); + return minimumcolor; +} + +void vtkWindowLevelLookupTable::SetMaximumColor(int r, int g, int b, int a) +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::SetMaximumColor, "VTK 5.0", + vtkWindowLevelLookupTable::SetMaximumTableValue); + this->SetMaximumTableValue(r*255.0,g*255.0,b*255.0,a*255.0); +} + +void vtkWindowLevelLookupTable::SetMaximumColor(const unsigned char rgba[4]) +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::SetMaximumColor, "VTK 5.0", + vtkWindowLevelLookupTable::SetMaximumTableValue); + this->SetMaximumTableValue(rgba[0]*255,rgba[1]*255,rgba[2]*255,rgba[3]*255); +} + +void vtkWindowLevelLookupTable::GetMaximumColor(unsigned char rgba[4]) +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::GetMaximumColor, "VTK 5.0", + vtkWindowLevelLookupTable::GetMaximumTableValue); + rgba[0] = int(this->MaximumTableValue[0]*255); + rgba[1] = int(this->MaximumTableValue[1]*255); + rgba[2] = int(this->MaximumTableValue[2]*255); + rgba[3] = int(this->MaximumTableValue[3]*255); +} + +unsigned char *vtkWindowLevelLookupTable::GetMaximumColor() +{ + VTK_LEGACY_REPLACED_BODY(vtkWindowLevelLookupTable::GetMaximumColor, "VTK 5.0", + vtkWindowLevelLookupTable::GetMaximumTableValue); + static unsigned char maximumcolor[4]; + maximumcolor[0] = int(this->MaximumTableValue[0]*255); + maximumcolor[1] = int(this->MaximumTableValue[1]*255); + maximumcolor[2] = int(this->MaximumTableValue[2]*255); + maximumcolor[3] = int(this->MaximumTableValue[3]*255); + return maximumcolor; +} + +#endif diff --git a/Common/vtkWindowLevelLookupTable.h b/Common/vtkWindowLevelLookupTable.h new file mode 100644 index 0000000..46d229f --- /dev/null +++ b/Common/vtkWindowLevelLookupTable.h @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindowLevelLookupTable.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWindowLevelLookupTable - map scalar values into colors or colors to scalars; generate color table +// .SECTION Description +// vtkWindowLevelLookupTable is an object that is used by mapper objects +// to map scalar values into rgba (red-green-blue-alpha transparency) +// color specification, or rgba into scalar values. The color table can +// be created by direct insertion of color values, or by specifying a +// window and level. Window / Level is used in medical imaging to specify +// a linear greyscale ramp. The Level is the center of the ramp. The +// Window is the width of the ramp. + +// .SECTION Caveats +// vtkWindowLevelLookupTable is a reference counted object. Therefore, you +// should always use operator "new" to construct new objects. This procedure +// will avoid memory problems (see text). + +// .SECTION See Also +// vtkLogLookupTable + +#ifndef __vtkWindowLevelLookupTable_h +#define __vtkWindowLevelLookupTable_h + +#include "vtkLookupTable.h" + +class VTK_COMMON_EXPORT vtkWindowLevelLookupTable : public vtkLookupTable +{ +public: + static vtkWindowLevelLookupTable *New(); + vtkTypeRevisionMacro(vtkWindowLevelLookupTable,vtkLookupTable); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Generate lookup table as a linear ramp between MinimumTableValue + // and MaximumTableValue. + void Build(); + + // Description: + // Set the window for the lookup table. The window is the difference + // between TableRange[0] and TableRange[1]. + void SetWindow(double window) { + if (window < 1e-5) { window = 1e-5; } + this->Window = window; + this->SetTableRange(this->Level - this->Window/2.0, + this->Level + this->Window/2.0); }; + vtkGetMacro(Window,double); + + // Description: + // Set the Level for the lookup table. The level is the average of + // TableRange[0] and TableRange[1]. + void SetLevel(double level) { + this->Level = level; + this->SetTableRange(this->Level - this->Window/2.0, + this->Level + this->Window/2.0); }; + vtkGetMacro(Level,double); + + // Description: + // Set inverse video on or off. You can achieve the same effect by + // switching the MinimumTableValue and the MaximumTableValue. + void SetInverseVideo(int iv); + vtkGetMacro(InverseVideo,int); + vtkBooleanMacro(InverseVideo,int); + + // Description: + // Set the minimum table value. All lookup table entries below the + // start of the ramp will be set to this color. After you change + // this value, you must re-build the lookup table. + vtkSetVector4Macro(MinimumTableValue,double); + vtkGetVector4Macro(MinimumTableValue,double); + + // Description: + // Set the maximum table value. All lookup table entries above the + // end of the ramp will be set to this color. After you change + // this value, you must re-build the lookup table. + vtkSetVector4Macro(MaximumTableValue,double); + vtkGetVector4Macro(MaximumTableValue,double); + + // Description: + // @deprecated For backwards compatibility: specify the color using + // integers in the range [0,255]. + VTK_LEGACY(void SetMinimumColor(int r, int g, int b, int a)); + VTK_LEGACY(void SetMinimumColor(const unsigned char rgba[4])); + VTK_LEGACY(void GetMinimumColor(unsigned char rgba[4])); + VTK_LEGACY(unsigned char *GetMinimumColor()); + + // Description: + // @deprecated For backwards compatibility: specify the color using + // integers in the range [0,255]. + VTK_LEGACY(void SetMaximumColor(int r, int g, int b, int a)); + VTK_LEGACY(void SetMaximumColor(const unsigned char rgba[4])); + VTK_LEGACY(void GetMaximumColor(unsigned char rgba[4])); + VTK_LEGACY(unsigned char *GetMaximumColor()); + +protected: + vtkWindowLevelLookupTable(int sze=256, int ext=256); + ~vtkWindowLevelLookupTable() {}; + + double Window; + double Level; + int InverseVideo; + double MaximumTableValue[4]; + double MinimumTableValue[4]; +private: + vtkWindowLevelLookupTable(const vtkWindowLevelLookupTable&); // Not implemented. + void operator=(const vtkWindowLevelLookupTable&); // Not implemented. +}; + +#endif + + diff --git a/Common/vtkWindows.h b/Common/vtkWindows.h new file mode 100644 index 0000000..85d257a --- /dev/null +++ b/Common/vtkWindows.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindows.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkWindows_h +#define __vtkWindows_h + +/* This header is useless when not on windows or when the windows + header has already been included at the top of VTK. Block the + whole thing on this condition. */ +#if defined(_WIN32) && !defined(VTK_INCLUDE_WINDOWS_H) + +/* +Define some macros to shorten the windows header. Record which ones +we defined here so that we can undefine them later. + +See this page for details: +http://msdn.microsoft.com/library/en-us/vccore/html/_core_faster_builds_and_smaller_header_files.asp +*/ +#if !defined(VTK_WINDOWS_FULL) +# if !defined(VC_EXTRALEAN) +# define VC_EXTRALEAN +# define VTK_WINDOWS_VC_EXTRALEAN +# endif +# if !defined(WIN32_LEAN_AND_MEAN) +# define WIN32_LEAN_AND_MEAN +# define VTK_WINDOWS_WIN32_LEAN_AND_MEAN +# endif +# if !defined(NOSERVICE) +# define NOSERVICE +# define VTK_WINDOWS_NOSERVICE +# endif +# if !defined(NOMCX) +# define NOMCX +# define VTK_WINDOWS_NOMCX +# endif +# if !defined(NOIME) +# define NOIME +# define VTK_WINDOWS_NOIME +# endif +# if !defined(NONLS) +# define NONLS +# define VTK_WINDOWS_NONLS +# endif +#endif + +/* Include the real windows header. */ +#include + +/* Undefine any macros we defined to shorten the windows header. + Leave the VTK_WINDOWS_* versions defined so that user code can tell + what parts of the windows header were included. */ +#if !defined(VTK_WINDOWS_FULL) +# if defined(VTK_WINDOWS_VC_EXTRALEAN) +# undef VC_EXTRALEAN +# endif +# if defined(VTK_WINDOWS_WIN32_LEAN_AND_MEAN) +# undef WIN32_LEAN_AND_MEAN +# endif +# if defined(VTK_WINDOWS_NOSERVICE) +# undef NOSERVICE +# endif +# if defined(VTK_WINDOWS_NOMCX) +# undef NOMCX +# endif +# if defined(VTK_WINDOWS_NOIME) +# undef NOIME +# endif +# if defined(VTK_WINDOWS_NONLS) +# undef NONLS +# endif +#endif + +#endif /* defined(_WIN32) && !defined(VTK_INCLUDE_WINDOWS_H) */ + +#endif diff --git a/Common/vtkXMLFileOutputWindow.cxx b/Common/vtkXMLFileOutputWindow.cxx new file mode 100644 index 0000000..23fcb6b --- /dev/null +++ b/Common/vtkXMLFileOutputWindow.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLFileOutputWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLFileOutputWindow.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkXMLFileOutputWindow, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkXMLFileOutputWindow); + +void vtkXMLFileOutputWindow::Initialize() +{ + if (!this->OStream) + { + if (!this->FileName) + { + char* fileName = (char *) "vtkMessageLog.xml"; + this->FileName = new char[strlen(fileName)+1]; + strcpy(this->FileName, fileName); + } + if (this->Append) + { + this->OStream = new ofstream(this->FileName, ios::app); + } + else + { + this->OStream = new ofstream(this->FileName); + this->DisplayTag(""); + } + } +} + +void vtkXMLFileOutputWindow::DisplayTag(const char* text) +{ + if(!text) + { + return; + } + + if (!this->OStream) + { + this->Initialize(); + } + *this->OStream << text << endl; + + if (this->Flush) + { + this->OStream->flush(); + } +} + +// Description: +// Process text to replace XML special characters with escape sequences +void vtkXMLFileOutputWindow:: DisplayXML(const char* tag, const char* text) +{ + char *xmlText; + + if(!text) + { + return; + } + + // allocate enough room for the worst case + xmlText = new char[strlen(text) * 6 + 1]; + + const char *s = text; + char *x = xmlText; + *x = '\0'; + + // replace all special characters + while (*s) + { + switch (*s) + { + case '&': + strcat(x, "&"); x += 5; + break; + case '"': + strcat(x, """); x += 6; + break; + case '\'': + strcat(x, "'"); x += 6; + break; + case '<': + strcat(x, "<"); x += 4; + break; + case '>': + strcat(x, ">"); x += 4; + break; + default: + *x = *s; x++; + *x = '\0'; // explicitly terminate the new string + } + s++; + } + + if (!this->OStream) + { + this->Initialize(); + } + *this->OStream << "<" << tag << ">" << xmlText << "" << endl; + + if (this->Flush) + { + this->OStream->flush(); + } + delete []xmlText; +} + +void vtkXMLFileOutputWindow::DisplayText(const char* text) +{ + this->DisplayXML("Text", text); +} + +void vtkXMLFileOutputWindow::DisplayErrorText(const char* text) +{ + this->DisplayXML("Error", text); +} + +void vtkXMLFileOutputWindow::DisplayWarningText(const char* text) +{ + this->DisplayXML("Warning", text); +} + +void vtkXMLFileOutputWindow::DisplayGenericWarningText(const char* text) +{ + this->DisplayXML("GenericWarning", text); +} + +void vtkXMLFileOutputWindow::DisplayDebugText(const char* text) +{ + this->DisplayXML("Debug", text); +} diff --git a/Common/vtkXMLFileOutputWindow.h b/Common/vtkXMLFileOutputWindow.h new file mode 100644 index 0000000..c204b4b --- /dev/null +++ b/Common/vtkXMLFileOutputWindow.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLFileOutputWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLFileOutputWindow - XML File Specific output window class +// .SECTION Description +// Writes debug/warning/error output to an XML file. Uses prefined XML +// tags for each text display method. The text is processed to replace +// XML markup characters. +// +// DisplayText - +// +// DisplayErrorText - +// +// DisplayWarningText - +// +// DisplayGenericWarningText - +// +// DisplayDebugText - +// +// The method DisplayTag outputs the text unprocessed. To use this +// class, instantiate it and then call SetInstance(this). + + +#ifndef __vtkXMLFileOutputWindow_h +#define __vtkXMLFileOutputWindow_h + +#include "vtkFileOutputWindow.h" + + +class VTK_COMMON_EXPORT vtkXMLFileOutputWindow : public vtkFileOutputWindow +{ +public: + vtkTypeRevisionMacro(vtkXMLFileOutputWindow, vtkFileOutputWindow); + + static vtkXMLFileOutputWindow* New(); + + // Description: + // Put the text into the log file. The text is processed to + // replace &, <, > with &, <, and >. + // Each display method outputs a different XML tag. + virtual void DisplayText(const char*); + virtual void DisplayErrorText(const char*); + virtual void DisplayWarningText(const char*); + virtual void DisplayGenericWarningText(const char*); + virtual void DisplayDebugText(const char*); + + // Description: + // Put the text into the log file without processing it. + virtual void DisplayTag(const char*); + + protected: + vtkXMLFileOutputWindow() {}; + virtual ~vtkXMLFileOutputWindow() {}; + + void Initialize(); + virtual void DisplayXML(const char*, const char*); + +private: + vtkXMLFileOutputWindow(const vtkXMLFileOutputWindow&); // Not implemented. + void operator=(const vtkXMLFileOutputWindow&); // Not implemented. +}; + + + +#endif diff --git a/Common/vtk__Int64Array.cxx b/Common/vtk__Int64Array.cxx new file mode 100644 index 0000000..496b028 --- /dev/null +++ b/Common/vtk__Int64Array.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk__Int64Array.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Instantiate superclass first to give the template a DLL interface. +#include "vtkDataArrayTemplate.txx" +VTK_DATA_ARRAY_TEMPLATE_INSTANTIATE(__int64); + +#define __vtk__Int64Array_cxx +#include "vtk__Int64Array.h" + +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtk__Int64Array, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtk__Int64Array); + +//---------------------------------------------------------------------------- +vtk__Int64Array::vtk__Int64Array(vtkIdType numComp): RealSuperclass(numComp) +{ +} + +//---------------------------------------------------------------------------- +vtk__Int64Array::~vtk__Int64Array() +{ +} + +//---------------------------------------------------------------------------- +void vtk__Int64Array::PrintSelf(ostream& os, vtkIndent indent) +{ + this->RealSuperclass::PrintSelf(os,indent); +} diff --git a/Common/vtk__Int64Array.h b/Common/vtk__Int64Array.h new file mode 100644 index 0000000..fe12f65 --- /dev/null +++ b/Common/vtk__Int64Array.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk__Int64Array.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtk__Int64Array - dynamic, self-adjusting array of __int64 +// .SECTION Description +// vtk__Int64Array is an array of values of type __int64. +// It provides methods for insertion and retrieval of values and will +// automatically resize itself to hold new data. + +#ifndef __vtk__Int64Array_h +#define __vtk__Int64Array_h + +// Tell the template header how to give our superclass a DLL interface. +#if !defined(__vtk__Int64Array_cxx) +# define VTK_DATA_ARRAY_TEMPLATE_TYPE __int64 +#endif + +#include "vtkDataArray.h" +#include "vtkDataArrayTemplate.h" // Real Superclass + +// Fake the superclass for the wrappers. +#define vtkDataArray vtkDataArrayTemplate<__int64> +class VTK_COMMON_EXPORT vtk__Int64Array : public vtkDataArray +#undef vtkDataArray +{ +public: + static vtk__Int64Array* New(); + vtkTypeRevisionMacro(vtk__Int64Array,vtkDataArray); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the data type. + int GetDataType() + { return VTK___INT64; } + + // Description: + // Copy the tuple value into a user-provided array. + void GetTupleValue(vtkIdType i, __int64* tuple) + { this->RealSuperclass::GetTupleValue(i, tuple); } + + // Description: + // Set the tuple value at the ith location in the array. + void SetTupleValue(vtkIdType i, const __int64* tuple) + { this->RealSuperclass::SetTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple into the ith location + // in the array. + void InsertTupleValue(vtkIdType i, const __int64* tuple) + { this->RealSuperclass::InsertTupleValue(i, tuple); } + + // Description: + // Insert (memory allocation performed) the tuple onto the end of the array. + vtkIdType InsertNextTupleValue(const __int64* tuple) + { return this->RealSuperclass::InsertNextTupleValue(tuple); } + + // Description: + // Get the data at a particular index. + __int64 GetValue(vtkIdType id) + { return this->RealSuperclass::GetValue(id); } + + // Description: + // Set the data at a particular index. Does not do range checking. Make sure + // you use the method SetNumberOfValues() before inserting data. + void SetValue(vtkIdType id, __int64 value) + { this->RealSuperclass::SetValue(id, value); } + + // Description: + // Specify the number of values for this object to hold. Does an + // allocation as well as setting the MaxId ivar. Used in conjunction with + // SetValue() method for fast insertion. + void SetNumberOfValues(vtkIdType number) + { this->RealSuperclass::SetNumberOfValues(number); } + + // Description: + // Insert data at a specified position in the array. + void InsertValue(vtkIdType id, __int64 f) + { this->RealSuperclass::InsertValue(id, f); } + + // Description: + // Insert data at the end of the array. Return its location in the array. + vtkIdType InsertNextValue(__int64 f) + { return this->RealSuperclass::InsertNextValue(f); } + + // Description: + // Get the address of a particular data index. Make sure data is allocated + // for the number of items requested. Set MaxId according to the number of + // data values requested. + __int64* WritePointer(vtkIdType id, vtkIdType number) + { return this->RealSuperclass::WritePointer(id, number); } + + // Description: + // Get the address of a particular data index. Performs no checks + // to verify that the memory has been allocated etc. + __int64* GetPointer(vtkIdType id) + { return this->RealSuperclass::GetPointer(id); } + + // Description: + // This method lets the user specify data to be held by the array. The + // array argument is a pointer to the data. size is the size of + // the array supplied by the user. Set save to 1 to keep the class + // from deleting the array when it cleans up or reallocates memory. + // The class uses the actual array provided; it does not copy the data + // from the suppled array. + void SetArray(__int64* array, vtkIdType size, int save) + { this->RealSuperclass::SetArray(array, size, save); } + +protected: + vtk__Int64Array(vtkIdType numComp=1); + ~vtk__Int64Array(); + +private: + //BTX + typedef vtkDataArrayTemplate<__int64> RealSuperclass; + //ETX + vtk__Int64Array(const vtk__Int64Array&); // Not implemented. + void operator=(const vtk__Int64Array&); // Not implemented. +}; + +#endif diff --git a/Copyright.txt b/Copyright.txt new file mode 100644 index 0000000..395c742 --- /dev/null +++ b/Copyright.txt @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Copyright.txt,v $ + +Copyright (c) 1993-2006 Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names + of any contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + * Modified source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================*/ diff --git a/DEPENDENCIES b/DEPENDENCIES new file mode 100644 index 0000000..e69de29 diff --git a/DartConfig.cmake b/DartConfig.cmake new file mode 100644 index 0000000..9d4af8d --- /dev/null +++ b/DartConfig.cmake @@ -0,0 +1,53 @@ +# Dashboard is opened for submissions for a 24 hour period starting at +# the specified NIGHLY_START_TIME. Time is specified in 24 hour format. +SET (NIGHTLY_START_TIME "23:00:00 EDT") + +# Dart server to submit results (used by client) +IF(NOT DROP_METHOD) + SET(DROP_METHOD http) +ENDIF(NOT DROP_METHOD) +IF(DROP_METHOD MATCHES http) + SET (DROP_SITE "public.kitware.com") + SET (DROP_LOCATION "/cgi-bin/HTTPUploadDartFile.cgi") +ELSE(DROP_METHOD MATCHES http) + SET (DROP_SITE "public.kitware.com") + SET (DROP_LOCATION "/incoming") + SET (DROP_SITE_USER "ftpuser") + SET (DROP_SITE_PASSWORD "public") +ENDIF(DROP_METHOD MATCHES http) + +SET (TRIGGER_SITE + "http://${DROP_SITE}/cgi-bin/Submit-vtk-TestingResults.pl") + +# Project Home Page +SET (PROJECT_URL "http://www.vtk.org") + +# Dart server configuration +SET (ROLLUP_URL "http://${DROP_SITE}/cgi-bin/vtk-rollup-dashboard.sh") +SET (CVS_WEB_URL "http://${DROP_SITE}/cgi-bin/viewcvs.cgi/") +SET (CVS_WEB_CVSROOT "VTK") +SET (USE_DOXYGEN "On") +SET (DOXYGEN_URL "http://www.vtk.org/doc/nightly/html/" ) +SET (GNATS_WEB_URL "${PROJECT_URL}/Bug/query.php?projects=1&status%5B%5D=1&status%5B%5D=2&status%5B%5D=3&status%5B%5D=4&status%5B%5D=6&op=doquery") +SET (USE_GNATS "On") + +# copy over the testing logo +CONFIGURE_FILE(${VTK_SOURCE_DIR}/TestingLogo.gif ${VTK_BINARY_DIR}/Testing/HTML/TestingResults/Icons/Logo.gif COPYONLY) + +# Continuous email delivery variables +SET (CONTINUOUS_FROM "lorensen@crd.ge.com") +SET (SMTP_MAILHOST "public.kitware.com") +SET (CONTINUOUS_MONITOR_LIST "lorensen@crd.ge.com millerjv@crd.ge.com ken.martin@kitware.com") +SET (CONTINUOUS_BASE_URL "${PROJECT_URL}/Testing") + +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_TEST_FAILURES ON) +SET (DELIVER_BROKEN_BUILD_EMAIL "Continuous Nightly") +SET (EMAIL_FROM "vtk-dashboard@public.kitware.com") +SET (DARTBOARD_BASE_URL "${PROJECT_URL}/Testing") + +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_CONFIGURE_FAILURES 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_BUILD_ERRORS 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_BUILD_WARNINGS 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_TEST_NOT_RUNS 1) +SET (DELIVER_BROKEN_BUILD_EMAIL_WITH_TEST_FAILURES 1) + diff --git a/Examples/AMR/Cxx/CMakeLists.txt b/Examples/AMR/Cxx/CMakeLists.txt new file mode 100644 index 0000000..b910207 --- /dev/null +++ b/Examples/AMR/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (AMR) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(HierarchicalBoxPipeline HierarchicalBoxPipeline.cxx vtkTestHierarchicalDataReader.cxx) +TARGET_LINK_LIBRARIES(HierarchicalBoxPipeline vtkRendering vtkIO) diff --git a/Examples/AMR/Cxx/HierarchicalBoxPipeline.cxx b/Examples/AMR/Cxx/HierarchicalBoxPipeline.cxx new file mode 100644 index 0000000..fbe7dca --- /dev/null +++ b/Examples/AMR/Cxx/HierarchicalBoxPipeline.cxx @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: HierarchicalBoxPipeline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how hierarchical box (uniform rectilinear) +// AMR datasets can be processed using the new vtkHierarchicalBoxDataSet class. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +#include "vtkCamera.h" +#include "vtkCellDataToPointData.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkContourFilter.h" +#include "vtkDebugLeaks.h" +#include "vtkHierarchicalDataExtractLevel.h" +#include "vtkHierarchicalDataSetGeometryFilter.h" +#include "vtkOutlineCornerFilter.h" +#include "vtkHierarchicalPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkShrinkPolyData.h" +#include "vtkTestHierarchicalDataReader.h" +#include "vtkTestUtilities.h" + +int main(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *ren = vtkRenderer::New(); + vtkCamera* cam = ren->GetActiveCamera(); + cam->SetPosition(-5.1828, 5.89733, 8.97969); + cam->SetFocalPoint(14.6491, -2.08677, -8.92362); + cam->SetViewUp(0.210794, 0.95813, -0.193784); + + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + char* cfname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/chombo3d/chombo3d"); + + vtkTestHierarchicalDataReader* reader = vtkTestHierarchicalDataReader::New(); + reader->SetFileName(cfname); + delete[] cfname; + + // geometry filter + vtkHierarchicalDataSetGeometryFilter* geom = + vtkHierarchicalDataSetGeometryFilter::New(); + geom->SetInputConnection(0, reader->GetOutputPort(0)); + + vtkShrinkPolyData* shrink = vtkShrinkPolyData::New(); + shrink->SetShrinkFactor(0.5); + shrink->SetInputConnection(0, geom->GetOutputPort(0)); + + // Rendering objects + vtkHierarchicalPolyDataMapper* shMapper = vtkHierarchicalPolyDataMapper::New(); + shMapper->SetInputConnection(0, shrink->GetOutputPort(0)); + vtkActor* shActor = vtkActor::New(); + shActor->SetMapper(shMapper); + shActor->GetProperty()->SetColor(0, 0, 1); + ren->AddActor(shActor); + + // corner outline + vtkOutlineCornerFilter* ocf = vtkOutlineCornerFilter::New(); + ocf->SetInputConnection(0, reader->GetOutputPort(0)); + + // Rendering objects + // This one is actually just a vtkPolyData so it doesn't need a hierarchical + // mapper, but we use this one to test hierarchical mapper with polydata input + vtkHierarchicalPolyDataMapper* ocMapper = vtkHierarchicalPolyDataMapper::New(); + ocMapper->SetInputConnection(0, ocf->GetOutputPort(0)); + vtkActor* ocActor = vtkActor::New(); + ocActor->SetMapper(ocMapper); + ocActor->GetProperty()->SetColor(1, 0, 0); + ren->AddActor(ocActor); + + // cell 2 point and contour + vtkHierarchicalDataExtractLevel* el = vtkHierarchicalDataExtractLevel::New(); + el->SetInputConnection(0, reader->GetOutputPort(0)); + el->SetLevelRange(2,2); + + vtkCellDataToPointData* c2p = vtkCellDataToPointData::New(); + c2p->SetInputConnection(0, el->GetOutputPort(0)); + + vtkContourFilter* contour = vtkContourFilter::New(); + contour->SetInputConnection(0, c2p->GetOutputPort(0)); + contour->SetValue(0, -0.013); + contour->SetInputArrayToProcess( + 0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,"phi"); + + // Rendering objects + vtkHierarchicalPolyDataMapper* contMapper = + vtkHierarchicalPolyDataMapper::New(); + contMapper->SetInputConnection(0, contour->GetOutputPort(0)); + vtkActor* contActor = vtkActor::New(); + contActor->SetMapper(contMapper); + contActor->GetProperty()->SetColor(1, 0, 0); + ren->AddActor(contActor); + + ren->SetBackground(1,1,1); + renWin->SetSize(300,300); + ren->ResetCamera(); + iren->Start(); + + ocf->Delete(); + ocMapper->Delete(); + ocActor->Delete(); + c2p->Delete(); + contour->Delete(); + contMapper->Delete(); + contActor->Delete(); + el->Delete(); + geom->Delete(); + shMapper->Delete(); + shActor->Delete(); + ren->Delete(); + renWin->Delete(); + iren->Delete(); + reader->Delete(); + shrink->Delete(); + + return 0; +} diff --git a/Examples/AMR/Cxx/vtkTestHierarchicalDataReader.cxx b/Examples/AMR/Cxx/vtkTestHierarchicalDataReader.cxx new file mode 100644 index 0000000..e9c1253 --- /dev/null +++ b/Examples/AMR/Cxx/vtkTestHierarchicalDataReader.cxx @@ -0,0 +1,360 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkTestHierarchicalDataReader.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTestHierarchicalDataReader.h" + +#include "vtkAMRBox.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkExecutive.h" +#include "vtkHierarchicalBoxDataSet.h" +#include "vtkHierarchicalDataInformation.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationDoubleVectorKey.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkUniformGrid.h" +#include "vtkXMLImageDataReader.h" + +vtkCxxRevisionMacro(vtkTestHierarchicalDataReader, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkTestHierarchicalDataReader); + +vtkTestHierarchicalDataReader::vtkTestHierarchicalDataReader() +{ + this->FileName = 0; + + this->SetNumberOfInputPorts(0); +} + +vtkTestHierarchicalDataReader::~vtkTestHierarchicalDataReader() +{ + this->SetFileName(0); +} + +// Provide information about the dataset: +// * Number of levels +// * Number of boxes / level +// * AMRBox (extent) of each box +int vtkTestHierarchicalDataReader::RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if (!this->Superclass::RequestInformation(request, inputVector, outputVector)) + { + return 0; + } + + const int numLevels = 3; + int numBlocks[numLevels] = { 1, 1, 14 }; + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::New(); + compInfo->SetNumberOfLevels(numLevels); + int i; + for (i=0; iSetNumberOfDataSets(i, numBlocks[i]); + } + + vtkInformation* info = outputVector->GetInformationObject(0); + info->Set( + vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION(), compInfo); + + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1); + + vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New(); + + for (i=0; i<16; i++) + { + // Here we load the 16 separate files (each containing + // an image dataset -uniform rectilinear grid-) + char* fstr = this->GetBlockFileName(i); + reader->SetFileName(fstr); + + reader->UpdateInformation(); + + delete[] fstr; + + // Each sub-dataset in a vtkHierarchicalBoxDataSet has an associated + // vtkAMRBox. This is similar to extent but is stored externally + // since it is possible to have sub-dataset nodes with NULL + // vtkUniformGrid pointers. + vtkAMRBox box; + + // This is a hack (do not do this at home). Normally, the + // region (box) information should be available in the file. + // In this case, since there is no such information available, + // we obtain it by looking at each image data's extent. + // -- begin hack + int extent[6]; + double spacing[3]; + double origin[3]; + + vtkInformation* outInfo = reader->GetExecutive()->GetOutputInformation(0); + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + outInfo->Get(vtkDataObject::SPACING(), spacing); + outInfo->Get(vtkDataObject::ORIGIN(), origin); + + int j; + for (j=0; j<3; j++) + { + int num = static_cast(floor(origin[j]/spacing[j] + 0.5)); + box.LoCorner[j] = num + extent[2*j]; + box.HiCorner[j] = num + extent[2*j+1] - 1; + } + + int level; + int dsindex; + + this->GetBlockIdx(i, level, dsindex); + + vtkInformation* subInfo = compInfo->GetInformation(level, dsindex); + subInfo->Set(vtkHierarchicalBoxDataSet::BOX(), + box.LoCorner[0], box.LoCorner[1], box.LoCorner[2], + box.HiCorner[0], box.HiCorner[1], box.HiCorner[2]); + } + + reader->Delete(); + compInfo->Delete(); + + return 1; +} + +int vtkTestHierarchicalDataReader::SetUpdateBlocks( + vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + + if (!info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) || + !info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())) + { + vtkErrorMacro("Expected information not found. " + "Cannot provide update extent."); + return 0; + } + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::SafeDownCast( + info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + + if (!compInfo) + { + vtkErrorMacro("Expected information not found. " + "Cannot provide update extent."); + return 0; + } + + vtkHierarchicalDataInformation* updateInfo = + vtkHierarchicalDataInformation::New(); + info->Set( + vtkCompositeDataPipeline::UPDATE_BLOCKS(), updateInfo); + updateInfo->SetNumberOfLevels(compInfo->GetNumberOfLevels()); + + unsigned int updatePiece = static_cast( + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + unsigned int updateNumPieces = static_cast( + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + + unsigned int numLevels = updateInfo->GetNumberOfLevels(); + for (unsigned int j=0; jSetNumberOfDataSets(j, compInfo->GetNumberOfDataSets(j)); + unsigned int numBlocks = updateInfo->GetNumberOfDataSets(j); + unsigned int numBlocksPerPiece = 1; + if (updateNumPieces < numBlocks) + { + numBlocksPerPiece = numBlocks / updateNumPieces; + } + unsigned int minBlock = numBlocksPerPiece*updatePiece; + unsigned int maxBlock = numBlocksPerPiece*(updatePiece+1); + if (updatePiece == updateNumPieces - 1) + { + maxBlock = numBlocks; + } + for (unsigned int i=minBlock; iGetInformation(j, i); + blockInfo->Set(vtkCompositeDataPipeline::MARKED_FOR_UPDATE(), 1); + } + } + updateInfo->Delete(); + return 1; +} + +int vtkTestHierarchicalDataReader::RequestData( + vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector) +{ + int i; + + if (!this->FileName) + { + return 0; + } + + vtkInformation* info = outputVector->GetInformationObject(0); + + vtkDataObject* doOutput = + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkHierarchicalBoxDataSet* hb = + vtkHierarchicalBoxDataSet::SafeDownCast(doOutput); + if (!hb) + { + return 0; + } + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::SafeDownCast( + info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + + hb->SetHierarchicalDataInformation(compInfo); + + // Since there is no AMR reader avaible yet, we will load a + // collection of VTK files and create our own vtkHierarchicalBoxDataSet. + // To create the files, I loaded a Chombo file with an experimental + // Chombo reader and wrote the datasets separately. + vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New(); + + for (i=0; i<16; i++) + { + // Here we load the 16 separate files (each containing + // an image dataset -uniform rectilinear grid-) + char* fstr = this->GetBlockFileName(i); + reader->SetFileName(fstr); + + // We have to update since we are working without a VTK pipeline. + // This will read the file and the output of the reader will be + // a valid image data. + reader->Update(); + delete[] fstr; + + // We now create a vtkUniformGrid. This is essentially a simple + // vtkImageData (not a sub-class though) with blanking. Since + // VTK readers do not know vtkUniformGrid, we simply create our + // own by copying from the image data. + vtkUniformGrid* ug = vtkUniformGrid::New(); + ug->ShallowCopy(reader->GetOutput()); + + int level; + int dsindex; + + this->GetBlockIdx(i, level, dsindex); + + // Given the level, index and box, add the sub-dataset to + // hierarchical dataset. + hb->SetDataSet(level, dsindex, ug); + + ug->Delete(); + } + reader->Delete(); + + // I hard-coded the refinement ratios. These should normally + // be available in the file. + hb->SetRefinementRatio(0, 2); + hb->SetRefinementRatio(1, 2); + + // This call generates visibility (blanking) arrays that mask + // regions of lower level datasets that overlap with regions + // of higher level datasets (it is assumed that, when available, + // higher level information should always be used instead of + // lower level information) + hb->GenerateVisibilityArrays(); + + return 1; +} + +void vtkTestHierarchicalDataReader::GetBlockIdx( + int blockId, int& level, int& dsindex) +{ + // Similarly, the level of each sub-dataset is normally + // available in the file. Since this is not the case, I + // hard-coded this into the example program. + // Level 0 = { 0 }, Level 1 = { 1 }, + // Level 2 = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } + if (blockId == 0) + { + level = 0; + dsindex = 0; + } + else if (blockId == 1) + { + level = 1; + dsindex = 0; + } + else + { + level = 2; + dsindex = blockId-2; + } +} + +char* vtkTestHierarchicalDataReader::GetBlockFileName(int blockId) +{ + size_t len = strlen(this->FileName); + size_t pos; + + // Search from the tail end of the filename until we + // find a '.' indicating an extension, or we find a + // path separator or the beginning of the string. + for (pos=len-1; pos!=0; --pos) + { + if (this->FileName[pos] == '.') + { + break; + } + + if (1==pos || this->FileName[pos] == '/') + { + // No extension on this->FileName; use the whole + // thing as the base name + pos= len; + break; + } + } + + char* fname = new char[pos+1]; + strncpy(fname, this->FileName, pos); + fname[pos] = '\0'; + + // Here we load the 16 separate files (each containing + // an image dataset -uniform rectilinear grid-) + char* fstr = new char [strlen(fname) + + strlen(".vti") + 10]; + sprintf(fstr,"%s_%i.vti",fname, blockId); + delete[] fname; + + return fstr; +} + +int vtkTestHierarchicalDataReader::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject"); + info->Set(vtkCompositeDataPipeline::COMPOSITE_DATA_TYPE_NAME(), + "vtkHierarchicalBoxDataSet"); + return 1; +} + +void vtkTestHierarchicalDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " << + (this->FileName ? this->FileName : "(none)") << "\n"; +} + diff --git a/Examples/AMR/Cxx/vtkTestHierarchicalDataReader.h b/Examples/AMR/Cxx/vtkTestHierarchicalDataReader.h new file mode 100644 index 0000000..2c1c466 --- /dev/null +++ b/Examples/AMR/Cxx/vtkTestHierarchicalDataReader.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestHierarchicalDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTestHierarchicalDataReader - reader used in testing +// .SECTION Description +// This reader uses the xml reader and puts together one AMR dataset +// using hard-coded values. + +#ifndef __vtkTestHierarchicalDataReader_h +#define __vtkTestHierarchicalDataReader_h + +#include "vtkHierarchicalDataSetAlgorithm.h" + +class vtkTestHierarchicalDataReader : public vtkHierarchicalDataSetAlgorithm +{ +public: + static vtkTestHierarchicalDataReader *New(); + vtkTypeRevisionMacro(vtkTestHierarchicalDataReader,vtkHierarchicalDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the file prefix. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkTestHierarchicalDataReader(); + ~vtkTestHierarchicalDataReader(); + + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int SetUpdateBlocks(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + char* GetBlockFileName(int blockId); + void GetBlockIdx(int blockId, int& level, int& dsindex); + + char* FileName; + + virtual int FillOutputPortInformation(int port, vtkInformation* info); + +private: + vtkTestHierarchicalDataReader(const vtkTestHierarchicalDataReader&); // Not implemented. + void operator=(const vtkTestHierarchicalDataReader&); // Not implemented. +}; + +#endif + + diff --git a/Examples/Annotation/Python/DispAllFonts.py b/Examples/Annotation/Python/DispAllFonts.py new file mode 100644 index 0000000..5d4e294 --- /dev/null +++ b/Examples/Annotation/Python/DispAllFonts.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python + +# This example displays all possible combinations of font families and +# styles. This example also shows how to create a simple Tkinter +# based GUI for VTK-Python. + +import vtk +import Tkinter +from vtk.tk.vtkTkRenderWindowInteractor import \ + vtkTkRenderWindowInteractor +import string + +# We set the font size constraints, default text and colors +current_font_size = 16 +min_font_size = 3 +max_font_size = 50 + +default_text = "ABCDEFGHIJKLMnopqrstuvwxyz(0123456789, !@#%()-=_+.:,./<>?" + +# set default_text "The quick red fox" + +text_color = [246/255.0, 255/255.0, 11/255.0] +bg_color = [56/255.0, 56/255.0, 154/255.0] + +# We create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. +# Do not set the size of the window here. +renWin = vtk.vtkRenderWindow() +ren = vtk.vtkRenderer() +ren.SetBackground(bg_color) +renWin.AddRenderer(ren) + +# We create text actors for each font family and several combinations +# of bold, italic and shadowed style. +text_actors = [] +for family in ("Arial", "Courier", "Times"): + for (bold, italic, shadow) in ((0, 0, 0), (0, 0, 1), (1, 0, 0), + (0, 1, 0), (1, 1, 0)): + mapper = vtk.vtkTextMapper() + attribs = [] + if bold: + attribs.append("b") + if italic: + attribs.append("i") + if shadow: + attribs.append("s") + + face_name = family + if len(attribs): + face_name = face_name + "(" + \ + string.join(attribs, ",") + ")" + + mapper.SetInput(face_name + ": " + default_text) + tprop = mapper.GetTextProperty() + eval("tprop.SetFontFamilyTo%s()"%family) + tprop.SetColor(text_color) + tprop.SetBold(bold) + tprop.SetItalic(italic) + tprop.SetShadow(shadow) + + actor = vtk.vtkActor2D() + actor.SetMapper(mapper) + text_actors.append(actor) + ren.AddActor(actor) + + +# Now setup the Tkinter GUI. + +# Create the root window. +root = Tkinter.Tk() + +# vtkTkRenderWindowInteractor is a Tk widget that we can render into. +# It has a GetRenderWindow method that returns a vtkRenderWindow. +# This can then be used to create a vtkRenderer and etc. We can also +# specify a vtkRenderWindow to be used when creating the widget by +# using the rw keyword argument, which is what we do here by using +# renWin. It also takes width and height options that can be used to +# specify the widget size, hence the render window size. +vtkw = vtkTkRenderWindowInteractor(root, rw=renWin, width=800) + + +# Once the VTK widget has been created it can be inserted into a whole +# Tk GUI as well as any other standard Tk widgets. + +# This function is called by the slider-widget handler whenever the +# slider value changes (either through user interaction or +# programmatically). It receives the slider value as parameter. We +# update the corresponding VTK objects by calling the SetFontSize +# method using this parameter and we render the scene to update the +# pipeline. +def set_font_size(sz): + global text_actors, renWin + size = int(sz) + i = 0 + for actor in text_actors: + i += 1 + actor.GetMapper().GetTextProperty().SetFontSize(size) + actor.SetDisplayPosition(10, i*(size+5)) + + renWin.SetSize(800, 20+i*(size+5)) + renWin.Render() + +# We create a size slider controlling the font size. The orientation +# of this widget is horizontal (orient option). We label it using the +# label option. Finally, we bind the scale to Python code by assigning +# the command option to the name of a Python function. Whenever the +# slider value changes this function will be called, enabling us to +# propagate this GUI setting to the corresponding VTK object. +size_slider = Tkinter.Scale(root, from_=min_font_size, + to=max_font_size, res=1, + orient='horizontal', label="Font size:", + command=set_font_size) +size_slider.set(current_font_size) + +# Finally we pack the VTK widget and the sliders on top of each other +# (side='top') inside the main root widget. +vtkw.Initialize() +size_slider.pack(side="top", fill="both") +vtkw.pack(side="top", fill='both', expand=1) + + +# Define a quit method that exits cleanly. +def quit(obj=root): + obj.quit() + +# We handle the WM_DELETE_WINDOW protocal request. This request is +# triggered when the widget is closed using the standard window +# manager icons or buttons. In this case the quit function will be +# called and it will free up any objects we created then exit the +# application. +root.protocol("WM_DELETE_WINDOW", quit) + +renWin.Render() +vtkw.Start() + +# start the Tkinter event loop. +root.mainloop() diff --git a/Examples/Annotation/Python/TestText.py b/Examples/Annotation/Python/TestText.py new file mode 100644 index 0000000..289fa76 --- /dev/null +++ b/Examples/Annotation/Python/TestText.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +# This example demonstrates the use of 2D text. + +import vtk + +# Create a sphere source, mapper, and actor +sphere = vtk.vtkSphereSource() + +sphereMapper = vtk.vtkPolyDataMapper() +sphereMapper.SetInputConnection(sphere.GetOutputPort()) +sphereMapper.GlobalImmediateModeRenderingOn() +sphereActor = vtk.vtkLODActor() +sphereActor.SetMapper(sphereMapper) + +# Create a scaled text actor. +# Set the text, font, justification, and properties (bold, italics, +# etc.). +textActor = vtk.vtkTextActor() +textActor.ScaledTextOn() +textActor.SetDisplayPosition(90, 50) +textActor.SetInput("This is a sphere") + +# Set coordinates to match the old vtkScaledTextActor default value +textActor.GetPosition2Coordinate().SetCoordinateSystemToNormalizedViewport() +textActor.GetPosition2Coordinate().SetValue(0.6, 0.1) + +tprop = textActor.GetTextProperty() +tprop.SetFontSize(18) +tprop.SetFontFamilyToArial() +tprop.SetJustificationToCentered() +tprop.BoldOn() +tprop.ItalicOn() +tprop.ShadowOn() +tprop.SetColor(0, 0, 1) + +# Create the Renderer, RenderWindow, RenderWindowInteractor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer; set the background and size; zoom +# in; and render. +ren.AddActor2D(textActor) +ren.AddActor(sphereActor) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(250, 125) +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.5) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Annotation/Python/TestTextOldWay.py b/Examples/Annotation/Python/TestTextOldWay.py new file mode 100644 index 0000000..3ffc519 --- /dev/null +++ b/Examples/Annotation/Python/TestTextOldWay.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +# This example demonstrates the use of 2D text the old way by using a +# vtkTextMapper and a vtkScaledTextActor. + +import vtk + +# Create a sphere source, mapper, and actor +sphere = vtk.vtkSphereSource() + +sphereMapper = vtk.vtkPolyDataMapper() +sphereMapper.SetInputConnection(sphere.GetOutputPort()) +sphereMapper.GlobalImmediateModeRenderingOn() +sphereActor = vtk.vtkLODActor() +sphereActor.SetMapper(sphereMapper) + +# Create a text mapper. +textMapper = vtk.vtkTextMapper() +textMapper.SetInput("This is a sphere") + +# Set the text, font, justification, and text properties (bold, +# italics, etc.). +tprop = textMapper.GetTextProperty() +tprop.SetFontSize(18) +tprop.SetFontFamilyToArial() +tprop.SetJustificationToCentered() +tprop.BoldOn() +tprop.ItalicOn() +tprop.ShadowOn() +tprop.SetColor(0, 0, 1) + +# Create a scaled text actor. Set the position of the text. +textActor = vtk.vtkScaledTextActor() +textActor.SetMapper(textMapper) +textActor.SetDisplayPosition(90, 50) + +# Create the Renderer, RenderWindow, RenderWindowInteractor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer; set the background and size; zoom +# in; and render. +ren.AddActor2D(textActor) +ren.AddActor(sphereActor) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(250, 125) +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.5) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Annotation/Python/annotatePick.py b/Examples/Annotation/Python/annotatePick.py new file mode 100644 index 0000000..233765e --- /dev/null +++ b/Examples/Annotation/Python/annotatePick.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +# This example demonstrates cell picking using vtkCellPicker. It +# displays the results of picking using a vtkTextMapper. + +import vtk + +# create a sphere source, mapper, and actor +sphere = vtk.vtkSphereSource() +sphereMapper = vtk.vtkPolyDataMapper() +sphereMapper.SetInputConnection(sphere.GetOutputPort()) +sphereMapper.GlobalImmediateModeRenderingOn() +sphereActor = vtk.vtkLODActor() +sphereActor.SetMapper(sphereMapper) + +# create the spikes by glyphing the sphere with a cone. Create the +# mapper and actor for the glyphs. +cone = vtk.vtkConeSource() +glyph = vtk.vtkGlyph3D() +glyph.SetInputConnection(sphere.GetOutputPort()) +glyph.SetSource(cone.GetOutput()) +glyph.SetVectorModeToUseNormal() +glyph.SetScaleModeToScaleByVector() +glyph.SetScaleFactor(0.25) +spikeMapper = vtk.vtkPolyDataMapper() +spikeMapper.SetInputConnection(glyph.GetOutputPort()) +spikeActor = vtk.vtkLODActor() +spikeActor.SetMapper(spikeMapper) + +# Create a text mapper and actor to display the results of picking. +textMapper = vtk.vtkTextMapper() +tprop = textMapper.GetTextProperty() +tprop.SetFontFamilyToArial() +tprop.SetFontSize(10) +tprop.BoldOn() +tprop.ShadowOn() +tprop.SetColor(1, 0, 0) +textActor = vtk.vtkActor2D() +textActor.VisibilityOff() +textActor.SetMapper(textMapper) + +# Create a cell picker. +picker = vtk.vtkCellPicker() + +# Create a Python function to create the text for the text mapper used +# to display the results of picking. +def annotatePick(object, event): + global picker, textActor, textMapper + if picker.GetCellId() < 0: + textActor.VisibilityOff() + else: + selPt = picker.GetSelectionPoint() + pickPos = picker.GetPickPosition() + textMapper.SetInput("(%.6f, %.6f, %.6f)"%pickPos) + textActor.SetPosition(selPt[:2]) + textActor.VisibilityOn() + +# Now at the end of the pick event call the above function. +picker.AddObserver("EndPickEvent", annotatePick) + +# Create the Renderer, RenderWindow, etc. and set the Picker. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) +iren.SetPicker(picker) + +# Add the actors to the renderer, set the background and size +ren.AddActor2D(textActor) +ren.AddActor(sphereActor) +ren.AddActor(spikeActor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 300) + +# Get the camera and zoom in closer to the image. +ren.ResetCamera() +cam1 = ren.GetActiveCamera() +cam1.Zoom(1.4) + +iren.Initialize() +# Initially pick the cell at this location. +picker.Pick(85, 126, 0, ren) +renWin.Render() +iren.Start() diff --git a/Examples/Annotation/Python/cubeAxes.py b/Examples/Annotation/Python/cubeAxes.py new file mode 100644 index 0000000..cffe5ca --- /dev/null +++ b/Examples/Annotation/Python/cubeAxes.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkCubeAxesActor2D to indicate +# the position in space that the camera is currently viewing. The +# vtkCubeAxesActor2D draws axes on the bounding box of the data set +# and labels the axes with x-y-z coordinates. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create a vtkBYUReader and read in a data set. +fohe = vtk.vtkBYUReader() +fohe.SetGeometryFileName(VTK_DATA_ROOT + "/Data/teapot.g") + +# Create a vtkPolyDataNormals filter to calculate the normals of the +# data set. +normals = vtk.vtkPolyDataNormals() +normals.SetInputConnection(fohe.GetOutputPort()) +# Set up the associated mapper and actor. +foheMapper = vtk.vtkPolyDataMapper() +foheMapper.SetInputConnection(normals.GetOutputPort()) +foheActor = vtk.vtkLODActor() +foheActor.SetMapper(foheMapper) + +# Create a vtkOutlineFilter to draw the bounding box of the data set. +# Also create the associated mapper and actor. +outline = vtk.vtkOutlineFilter() +outline.SetInputConnection(normals.GetOutputPort()) +mapOutline = vtk.vtkPolyDataMapper() +mapOutline.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(mapOutline) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Create a vtkCamera, and set the camera parameters. +camera = vtk.vtkCamera() +camera.SetClippingRange(1.60187, 20.0842) +camera.SetFocalPoint(0.21406, 1.5, 0) +camera.SetPosition(8.3761, 4.94858, 4.12505) +camera.SetViewUp(0.180325, 0.549245, -0.815974) + +# Create a vtkLight, and set the light parameters. +light = vtk.vtkLight() +light.SetFocalPoint(0.21406, 1.5, 0) +light.SetPosition(8.3761, 4.94858, 4.12505) + +# Create the Renderers. Assign them the appropriate viewport +# coordinates, active camera, and light. +ren = vtk.vtkRenderer() +ren.SetViewport(0, 0, 0.5, 1.0) +ren.SetActiveCamera(camera) +ren.AddLight(light) +ren2 = vtk.vtkRenderer() +ren2.SetViewport(0.5, 0, 1.0, 1.0) +ren2.SetActiveCamera(camera) +ren2.AddLight(light) + +# Create the RenderWindow and RenderWindowInteractor. +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.AddRenderer(ren2) +renWin.SetWindowName("VTK - Cube Axes") +renWin.SetSize(600, 300) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, and set the background. +ren.AddViewProp(foheActor) +ren.AddViewProp(outlineActor) +ren2.AddViewProp(foheActor) +ren2.AddViewProp(outlineActor) + +ren.SetBackground(0.1, 0.2, 0.4) +ren2.SetBackground(0.1, 0.2, 0.4) + +# Create a text property for both cube axes +tprop = vtk.vtkTextProperty() +tprop.SetColor(1, 1, 1) +tprop.ShadowOn() + +# Create a vtkCubeAxesActor2D. Use the outer edges of the bounding box to +# draw the axes. Add the actor to the renderer. +axes = vtk.vtkCubeAxesActor2D() +axes.SetInput(normals.GetOutput()) +axes.SetCamera(ren.GetActiveCamera()) +axes.SetLabelFormat("%6.4g") +axes.SetFlyModeToOuterEdges() +axes.SetFontFactor(0.8) +axes.SetAxisTitleTextProperty(tprop) +axes.SetAxisLabelTextProperty(tprop) +ren.AddViewProp(axes) + +# Create a vtkCubeAxesActor2D. Use the closest vertex to the camera to +# determine where to draw the axes. Add the actor to the renderer. +axes2 = vtk.vtkCubeAxesActor2D() +axes2.SetViewProp(foheActor) +axes2.SetCamera(ren2.GetActiveCamera()) +axes2.SetLabelFormat("%6.4g") +axes2.SetFlyModeToClosestTriad() +axes2.SetFontFactor(0.8) +axes2.ScalingOff() +axes2.SetAxisTitleTextProperty(tprop) +axes2.SetAxisLabelTextProperty(tprop) +ren2.AddViewProp(axes2) + +# Set up a check for aborting rendering. +def CheckAbort(obj, event): + # obj will be the object generating the event. In this case it + # is renWin. + if obj.GetEventPending() != 0: + obj.SetAbortRender(1) + +renWin.AddObserver("AbortCheckEvent", CheckAbort) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Annotation/Python/labeledMesh.py b/Examples/Annotation/Python/labeledMesh.py new file mode 100644 index 0000000..3389472 --- /dev/null +++ b/Examples/Annotation/Python/labeledMesh.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkLabeledDataMapper. This +# class is used for displaying numerical data from an underlying data +# set. In the case of this example, the underlying data are the point +# and cell ids. + +import vtk + +# Create a selection window. We will display the point and cell ids +# that lie within this window. +xmin = 200 +xLength = 100 +xmax = xmin + xLength +ymin = 200 +yLength = 100 +ymax = ymin + yLength + +pts = vtk.vtkPoints() +pts.InsertPoint(0, xmin, ymin, 0) +pts.InsertPoint(1, xmax, ymin, 0) +pts.InsertPoint(2, xmax, ymax, 0) +pts.InsertPoint(3, xmin, ymax, 0) +rect = vtk.vtkCellArray() +rect.InsertNextCell(5) +rect.InsertCellPoint(0) +rect.InsertCellPoint(1) +rect.InsertCellPoint(2) +rect.InsertCellPoint(3) +rect.InsertCellPoint(0) +selectRect = vtk.vtkPolyData() +selectRect.SetPoints(pts) +selectRect.SetLines(rect) +rectMapper = vtk.vtkPolyDataMapper2D() +rectMapper.SetInput(selectRect) +rectActor = vtk.vtkActor2D() +rectActor.SetMapper(rectMapper) + +# Create a sphere and its associated mapper and actor. +sphere = vtk.vtkSphereSource() +sphereMapper = vtk.vtkPolyDataMapper() +sphereMapper.SetInputConnection(sphere.GetOutputPort()) +sphereMapper.GlobalImmediateModeRenderingOn() +sphereActor = vtk.vtkActor() +sphereActor.SetMapper(sphereMapper) + +# Generate data arrays containing point and cell ids +ids = vtk.vtkIdFilter() +ids.SetInputConnection(sphere.GetOutputPort()) +ids.PointIdsOn() +ids.CellIdsOn() +ids.FieldDataOn() + +# Create the renderer here because vtkSelectVisiblePoints needs it. +ren = vtk.vtkRenderer() + +# Create labels for points +visPts = vtk.vtkSelectVisiblePoints() +visPts.SetInputConnection(ids.GetOutputPort()) +visPts.SetRenderer(ren) +visPts.SelectionWindowOn() +visPts.SetSelection(xmin, xmin + xLength, ymin, ymin + yLength) + +# Create the mapper to display the point ids. Specify the format to +# use for the labels. Also create the associated actor. +ldm = vtk.vtkLabeledDataMapper() +ldm.SetInputConnection(visPts.GetOutputPort()) +ldm.SetLabelFormat("%g") +ldm.SetLabelModeToLabelFieldData() +pointLabels = vtk.vtkActor2D() +pointLabels.SetMapper(ldm) + +# Create labels for cells +cc = vtk.vtkCellCenters() +cc.SetInputConnection(ids.GetOutputPort()) +visCells = vtk.vtkSelectVisiblePoints() +visCells.SetInputConnection(cc.GetOutputPort()) +visCells.SetRenderer(ren) +visCells.SelectionWindowOn() +visCells.SetSelection(xmin, xmin + xLength, ymin, ymin + yLength) + +# Create the mapper to display the cell ids. Specify the format to +# use for the labels. Also create the associated actor. +cellMapper = vtk.vtkLabeledDataMapper() +cellMapper.SetInputConnection(visCells.GetOutputPort()) +cellMapper.SetLabelFormat("%g") +cellMapper.SetLabelModeToLabelFieldData() +cellMapper.GetLabelTextProperty().SetColor(0, 1, 0) +cellLabels = vtk.vtkActor2D() +cellLabels.SetMapper(cellMapper) + +# Create the RenderWindow and RenderWindowInteractor +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer; set the background and size; +# render +ren.AddActor(sphereActor) +ren.AddActor2D(rectActor) +ren.AddActor2D(pointLabels) +ren.AddActor2D(cellLabels) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(500, 500) + +# Create a function to move the selection window across the data set. +def MoveWindow(): + for y in range(100, 300, 25): + for x in range(100, 300, 25): + PlaceWindow(x, y) + + +# Create a function to draw the selection window at each location it +# is moved to. +def PlaceWindow(xmin, ymin): + global xLength, yLength, visPts, visCells, pts, renWin + + xmax = xmin + xLength + ymax = ymin + yLength + + visPts.SetSelection(xmin, xmax, ymin, ymax) + visCells.SetSelection(xmin, xmax, ymin, ymax) + + pts.InsertPoint(0, xmin, ymin, 0) + pts.InsertPoint(1, xmax, ymin, 0) + pts.InsertPoint(2, xmax, ymax, 0) + pts.InsertPoint(3, xmin, ymax, 0) + # Call Modified because InsertPoints does not modify vtkPoints + # (for performance reasons) + pts.Modified() + renWin.Render() + + +# Initialize the interactor. +iren.Initialize() +renWin.Render() + +# Move the selection window across the data set. +MoveWindow() + +# Put the selection window in the center of the render window. +# This works because the xmin = ymin = 200, xLength = yLength = 100, and +# the render window size is 500 x 500. +PlaceWindow(xmin, ymin) + +# Now start normal interaction. +iren.Start() diff --git a/Examples/Annotation/Python/multiLineText.py b/Examples/Annotation/Python/multiLineText.py new file mode 100644 index 0000000..7b72f76 --- /dev/null +++ b/Examples/Annotation/Python/multiLineText.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python + +# This example demonstrates the use of multiline 2D text using +# vtkTextMappers. It shows several justifications as well as +# single-line and multiple-line text inputs. + +import vtk + +font_size = 14 + +# Create the text mappers and the associated Actor2Ds. + +# The font and text properties (except justification) are the same for +# each single line mapper. Let's create a common text property object +singleLineTextProp = vtk.vtkTextProperty() +singleLineTextProp.SetFontSize(font_size) +singleLineTextProp.SetFontFamilyToArial() +singleLineTextProp.BoldOff() +singleLineTextProp.ItalicOff() +singleLineTextProp.ShadowOff() + +# The font and text properties (except justification) are the same for +# each multi line mapper. Let's create a common text property object +multiLineTextProp = vtk.vtkTextProperty() +multiLineTextProp.ShallowCopy(singleLineTextProp) +multiLineTextProp.BoldOn() +multiLineTextProp.ItalicOn() +multiLineTextProp.ShadowOn() +multiLineTextProp.SetLineSpacing(0.8) + +# The text is on a single line and bottom-justified. +singleLineTextB = vtk.vtkTextMapper() +singleLineTextB.SetInput("Single line (bottom)") +tprop = singleLineTextB.GetTextProperty() +tprop.ShallowCopy(singleLineTextProp) +tprop.SetVerticalJustificationToBottom() +tprop.SetColor(1, 0, 0) +singleLineTextActorB = vtk.vtkActor2D() +singleLineTextActorB.SetMapper(singleLineTextB) +singleLineTextActorB.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() +singleLineTextActorB.GetPositionCoordinate().SetValue(0.05, 0.85) + +# The text is on a single line and center-justified (vertical +# justification). +singleLineTextC = vtk.vtkTextMapper() +singleLineTextC.SetInput("Single line (centered)") +tprop = singleLineTextC.GetTextProperty() +tprop.ShallowCopy(singleLineTextProp) +tprop.SetVerticalJustificationToCentered() +tprop.SetColor(0, 1, 0) +singleLineTextActorC = vtk.vtkActor2D() +singleLineTextActorC.SetMapper(singleLineTextC) +singleLineTextActorC.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() +singleLineTextActorC.GetPositionCoordinate().SetValue(0.05, 0.75) + +# The text is on a single line and top-justified. +singleLineTextT = vtk.vtkTextMapper() +singleLineTextT.SetInput("Single line (top)") +tprop = singleLineTextT.GetTextProperty() +tprop.ShallowCopy(singleLineTextProp) +tprop.SetVerticalJustificationToTop() +tprop.SetColor(0, 0, 1) +singleLineTextActorT = vtk.vtkActor2D() +singleLineTextActorT.SetMapper(singleLineTextT) +singleLineTextActorT.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() +singleLineTextActorT.GetPositionCoordinate().SetValue(0.05, 0.65) + +# The text is on multiple lines and left- and top-justified. +textMapperL = vtk.vtkTextMapper() +textMapperL.SetInput("This is\nmulti-line\ntext output\n(left-top)") +tprop = textMapperL.GetTextProperty() +tprop.ShallowCopy(multiLineTextProp) +tprop.SetJustificationToLeft() +tprop.SetVerticalJustificationToTop() +tprop.SetColor(1, 0, 0) +textActorL = vtk.vtkActor2D() +textActorL.SetMapper(textMapperL) +textActorL.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() +textActorL.GetPositionCoordinate().SetValue(0.05, 0.5) + +# The text is on multiple lines and center-justified (both horizontal and +# vertical). +textMapperC = vtk.vtkTextMapper() +textMapperC.SetInput("This is\nmulti-line\ntext output\n(centered)") +tprop = textMapperC.GetTextProperty() +tprop.ShallowCopy(multiLineTextProp) +tprop.SetJustificationToCentered() +tprop.SetVerticalJustificationToCentered() +tprop.SetColor(0, 1, 0) +textActorC = vtk.vtkActor2D() +textActorC.SetMapper(textMapperC) +textActorC.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() +textActorC.GetPositionCoordinate().SetValue(0.5, 0.5) + +# The text is on multiple lines and right- and bottom-justified. +textMapperR = vtk.vtkTextMapper() +textMapperR.SetInput("This is\nmulti-line\ntext output\n(right-bottom)") +tprop = textMapperR.GetTextProperty() +tprop.ShallowCopy(multiLineTextProp) +tprop.SetJustificationToRight() +tprop.SetVerticalJustificationToBottom() +tprop.SetColor(0, 0, 1) +textActorR = vtk.vtkActor2D() +textActorR.SetMapper(textMapperR) +textActorR.GetPositionCoordinate().SetCoordinateSystemToNormalizedDisplay() +textActorR.GetPositionCoordinate().SetValue(0.95, 0.5) + +# Draw the grid to demonstrate the placement of the text. + +# Set up the necessary points. +Pts = vtk.vtkPoints() +Pts.InsertNextPoint(0.05, 0.0, 0.0) +Pts.InsertNextPoint(0.05, 1.0, 0.0) +Pts.InsertNextPoint(0.5, 0.0, 0.0) +Pts.InsertNextPoint(0.5, 1.0, 0.0) +Pts.InsertNextPoint(0.95, 0.0, 0.0) +Pts.InsertNextPoint(0.95, 1.0, 0.0) +Pts.InsertNextPoint(0.0, 0.5, 0.0) +Pts.InsertNextPoint(1.0, 0.5, 0.0) +Pts.InsertNextPoint(0.00, 0.85, 0.0) +Pts.InsertNextPoint(0.50, 0.85, 0.0) +Pts.InsertNextPoint(0.00, 0.75, 0.0) +Pts.InsertNextPoint(0.50, 0.75, 0.0) +Pts.InsertNextPoint(0.00, 0.65, 0.0) +Pts.InsertNextPoint(0.50, 0.65, 0.0) +# Set up the lines that use these points. +Lines = vtk.vtkCellArray() +Lines.InsertNextCell(2) +Lines.InsertCellPoint(0) +Lines.InsertCellPoint(1) +Lines.InsertNextCell(2) +Lines.InsertCellPoint(2) +Lines.InsertCellPoint(3) +Lines.InsertNextCell(2) +Lines.InsertCellPoint(4) +Lines.InsertCellPoint(5) +Lines.InsertNextCell(2) +Lines.InsertCellPoint(6) +Lines.InsertCellPoint(7) +Lines.InsertNextCell(2) +Lines.InsertCellPoint(8) +Lines.InsertCellPoint(9) +Lines.InsertNextCell(2) +Lines.InsertCellPoint(10) +Lines.InsertCellPoint(11) +Lines.InsertNextCell(2) +Lines.InsertCellPoint(12) +Lines.InsertCellPoint(13) +# Create a grid that uses these points and lines. +Grid = vtk.vtkPolyData() +Grid.SetPoints(Pts) +Grid.SetLines(Lines) +# Set up the coordinate system. +normCoords = vtk.vtkCoordinate() +normCoords.SetCoordinateSystemToNormalizedViewport() + +# Set up the mapper and actor (2D) for the grid. +mapper = vtk.vtkPolyDataMapper2D() +mapper.SetInput(Grid) +mapper.SetTransformCoordinate(normCoords) +gridActor = vtk.vtkActor2D() +gridActor.SetMapper(mapper) +gridActor.GetProperty().SetColor(0.1, 0.1, 0.1) + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer; set the background and size; zoom in +# closer to the image; render +ren.AddActor2D(textActorL) +ren.AddActor2D(textActorC) +ren.AddActor2D(textActorR) +ren.AddActor2D(singleLineTextActorB) +ren.AddActor2D(singleLineTextActorC) +ren.AddActor2D(singleLineTextActorT) +ren.AddActor2D(gridActor) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(500, 300) +ren.GetActiveCamera().Zoom(1.5) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Annotation/Python/textOrigin.py b/Examples/Annotation/Python/textOrigin.py new file mode 100644 index 0000000..54355dd --- /dev/null +++ b/Examples/Annotation/Python/textOrigin.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkVectorText and vtkFollower. +# vtkVectorText is used to create 3D annotation. vtkFollower is used to +# position the 3D text and to ensure that the text always faces the +# renderer's active camera (i.e., the text is always readable). + +import vtk + +# Create the axes and the associated mapper and actor. +axes = vtk.vtkAxes() +axes.SetOrigin(0, 0, 0) +axesMapper = vtk.vtkPolyDataMapper() +axesMapper.SetInputConnection(axes.GetOutputPort()) +axesActor = vtk.vtkActor() +axesActor.SetMapper(axesMapper) + +# Create the 3D text and the associated mapper and follower (a type of +# actor). Position the text so it is displayed over the origin of the +# axes. +atext = vtk.vtkVectorText() +atext.SetText("Origin") +textMapper = vtk.vtkPolyDataMapper() +textMapper.SetInputConnection(atext.GetOutputPort()) +textActor = vtk.vtkFollower() +textActor.SetMapper(textMapper) +textActor.SetScale(0.2, 0.2, 0.2) +textActor.AddPosition(0, -0.1, 0) + +# Create the Renderer, RenderWindow, and RenderWindowInteractor. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer. +ren.AddActor(axesActor) +ren.AddActor(textActor) + +# Zoom in closer. +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.6) + +# Reset the clipping range of the camera; set the camera of the +# follower; render. +ren.ResetCameraClippingRange() +textActor.SetCamera(ren.GetActiveCamera()) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Annotation/Python/xyPlot.py b/Examples/Annotation/Python/xyPlot.py new file mode 100644 index 0000000..938dccc --- /dev/null +++ b/Examples/Annotation/Python/xyPlot.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkXYPlotActor to display three +# probe lines using three different techniques. In this example, we +# are loading data using the vtkPLOT3DReader. We are using the +# vtkProbeFilter to extract the underlying point data along three +# probe lines. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create a PLOT3D reader and load the data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# Create three the line source to use for the probe lines. +line = vtk.vtkLineSource() +line.SetResolution(30) + +# Move the line into place and create the probe filter. For +# vtkProbeFilter, the probe line is the input, and the underlying data +# set is the source. +transL1 = vtk.vtkTransform() +transL1.Translate(3.7, 0.0, 28.37) +transL1.Scale(5, 5, 5) +transL1.RotateY(90) +tf = vtk.vtkTransformPolyDataFilter() +tf.SetInputConnection(line.GetOutputPort()) +tf.SetTransform(transL1) +probe = vtk.vtkProbeFilter() +probe.SetInputConnection(tf.GetOutputPort()) +probe.SetSource(pl3d.GetOutput()) + +# Move the line again and create another probe filter. +transL2 = vtk.vtkTransform() +transL2.Translate(9.2, 0.0, 31.20) +transL2.Scale(5, 5, 5) +transL2.RotateY(90) +tf2 = vtk.vtkTransformPolyDataFilter() +tf2.SetInputConnection(line.GetOutputPort()) +tf2.SetTransform(transL2) +probe2 = vtk.vtkProbeFilter() +probe2.SetInputConnection(tf2.GetOutputPort()) +probe2.SetSource(pl3d.GetOutput()) + +# Move the line again and create a third probe filter. +transL3 = vtk.vtkTransform() +transL3.Translate(13.27, 0.0, 33.40) +transL3.Scale(4.5, 4.5, 4.5) +transL3.RotateY(90) +tf3 = vtk.vtkTransformPolyDataFilter() +tf3.SetInputConnection(line.GetOutputPort()) +tf3.SetTransform(transL3) +probe3 = vtk.vtkProbeFilter() +probe3.SetInputConnection(tf3.GetOutputPort()) +probe3.SetSource(pl3d.GetOutput()) + +# Create a vtkAppendPolyData to merge the output of the three probe +# filters into one data set. +appendF = vtk.vtkAppendPolyData() +appendF.AddInput(probe.GetPolyDataOutput()) +appendF.AddInput(probe2.GetPolyDataOutput()) +appendF.AddInput(probe3.GetPolyDataOutput()) + +# Create a tube filter to represent the lines as tubes. Set up the +# associated mapper and actor. +tuber = vtk.vtkTubeFilter() +tuber.SetInputConnection(appendF.GetOutputPort()) +tuber.SetRadius(0.1) +lineMapper = vtk.vtkPolyDataMapper() +lineMapper.SetInputConnection(tuber.GetOutputPort()) +lineActor = vtk.vtkActor() +lineActor.SetMapper(lineMapper) + +# Create an xy-plot using the output of the 3 probe filters as input. +# The x-values we are plotting are arc length. +xyplot = vtk.vtkXYPlotActor() +xyplot.AddInput(probe.GetOutput()) +xyplot.AddInput(probe2.GetOutput()) +xyplot.AddInput(probe3.GetOutput()) +xyplot.GetPositionCoordinate().SetValue(0.0, 0.67, 0) +xyplot.GetPosition2Coordinate().SetValue(1.0, 0.33, 0) #relative to Position +xyplot.SetXValuesToArcLength() +xyplot.SetNumberOfXLabels(6) +xyplot.SetTitle("Pressure vs. Arc Length (Zoomed View)") +xyplot.SetXTitle("") +xyplot.SetYTitle("P") +xyplot.SetXRange(.1, .35) +xyplot.SetYRange(.2, .4) +xyplot.GetProperty().SetColor(0, 0, 0) +xyplot.GetProperty().SetLineWidth(2) +# Set text prop color (same color for backward compat with test) +# Assign same object to all text props +tprop = xyplot.GetTitleTextProperty() +tprop.SetColor(xyplot.GetProperty().GetColor()) +xyplot.SetAxisTitleTextProperty(tprop) +xyplot.SetAxisLabelTextProperty(tprop) + +# Create an xy-plot using the output of the 3 probe filters as input. +# The x-values we are plotting are normalized arc length. +xyplot2 = vtk.vtkXYPlotActor() +xyplot2.AddInput(probe.GetOutput()) +xyplot2.AddInput(probe2.GetOutput()) +xyplot2.AddInput(probe3.GetOutput()) +xyplot2.GetPositionCoordinate().SetValue(0.00, 0.33, 0) +xyplot2.GetPosition2Coordinate().SetValue(1.0, 0.33, 0) #relative to Position +xyplot2.SetXValuesToNormalizedArcLength() +xyplot2.SetNumberOfXLabels(6) +xyplot2.SetTitle("Pressure vs. Normalized Arc Length") +xyplot2.SetXTitle("") +xyplot2.SetYTitle("P") +xyplot2.PlotPointsOn() +xyplot2.PlotLinesOff() +xyplot2.GetProperty().SetColor(1, 0, 0) +xyplot2.GetProperty().SetPointSize(2) +# Set text prop color (same color for backward compat with test) +# Assign same object to all text props +tprop = xyplot2.GetTitleTextProperty() +tprop.SetColor(xyplot2.GetProperty().GetColor()) +xyplot2.SetAxisTitleTextProperty(tprop) +xyplot2.SetAxisLabelTextProperty(tprop) + +# Create an xy-plot using the output of the 3 probe filters as input. +# The x-values we are plotting are the underlying point data values. +xyplot3 = vtk.vtkXYPlotActor() +xyplot3.AddInput(probe.GetOutput()) +xyplot3.AddInput(probe2.GetOutput()) +xyplot3.AddInput(probe3.GetOutput()) +xyplot3.GetPositionCoordinate().SetValue(0.0, 0.0, 0) +xyplot3.GetPosition2Coordinate().SetValue(1.0, 0.33, 0) #relative to Position +xyplot3.SetXValuesToIndex() +xyplot3.SetNumberOfXLabels(6) +xyplot3.SetTitle("Pressure vs. Point Id") +xyplot3.SetXTitle("Probe Length") +xyplot3.SetYTitle("P") +xyplot3.PlotPointsOn() +xyplot3.GetProperty().SetColor(0, 0, 1) +xyplot3.GetProperty().SetPointSize(3) +# Set text prop color (same color for backward compat with test) +# Assign same object to all text props +tprop = xyplot3.GetTitleTextProperty() +tprop.SetColor(xyplot3.GetProperty().GetColor()) +xyplot3.SetAxisTitleTextProperty(tprop) +xyplot3.SetAxisLabelTextProperty(tprop) + +# Draw an outline of the PLOT3D data set. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Create the Renderers, RenderWindow, and RenderWindowInteractor. +ren = vtk.vtkRenderer() +ren2 = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.AddRenderer(ren2) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Set the background, viewport (necessary because we want to have the +# renderers draw to different parts of the render window) of the first +# renderer. Add the outline and line actors to the renderer. +ren.SetBackground(0.6784, 0.8471, 0.9020) +ren.SetViewport(0, 0, .5, 1) +ren.AddActor(outlineActor) +ren.AddActor(lineActor) + +# Set the background and viewport of the second renderer. Add the +# xy-plot actors to the renderer. Set the size of the render window. +ren2.SetBackground(1, 1, 1) +ren2.SetViewport(0.5, 0.0, 1.0, 1.0) +ren2.AddActor2D(xyplot) +ren2.AddActor2D(xyplot2) +ren2.AddActor2D(xyplot3) +renWin.SetSize(500, 250) + +# Set up the camera parameters. +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 100) +cam1.SetFocalPoint(8.88908, 0.595038, 29.3342) +cam1.SetPosition(-12.3332, 31.7479, 41.2387) +cam1.SetViewUp(0.060772, -0.319905, 0.945498) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Annotation/Tcl/DispAllFonts.tcl b/Examples/Annotation/Tcl/DispAllFonts.tcl new file mode 100644 index 0000000..547bc51 --- /dev/null +++ b/Examples/Annotation/Tcl/DispAllFonts.tcl @@ -0,0 +1,164 @@ +# +# This example displays all possible combinations of font families and styles. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# +# We set the font size constraints, default text and colors +# +set current_font_size 16 +set min_font_size 3 +set max_font_size 50 + +set default_text "ABCDEFGHIJKLMnopqrstuvwxyz 0123456789 !@#$%()-=_+[]{};:,./<>?" +# set default_text "The quick red fox" + +set text_color [list [expr 246 / 255.0] [expr 255 / 255.0] [expr 11 / 255.0]] +set bg_color [list [expr 56 / 255.0] [expr 56 / 255.0] [expr 154 / 255.0]] + +# +# We create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. +# Do not set the size of the window here. +# +vtkRenderWindow renWin + +vtkRenderer ren1 + eval ren1 SetBackground $bg_color + renWin AddRenderer ren1 + +# +# We create text actors for each font family and several combinations of bold, +# italic and shadowed style. +# +set text_actors {} +foreach family { + Arial + Courier + Times +} { + foreach {bold italic shadow} { + 0 0 0 + 0 0 1 + 1 0 0 + 0 1 0 + 1 1 0 + } { + set mapper [vtkTextMapper mapper_${family}_${bold}_${italic}_${shadow}] + set attribs {} + if {$bold} { + lappend attribs "b" + } + if {$italic} { + lappend attribs "i" + } + if {$shadow} { + lappend attribs "s" + } + set face_name "$family" + if {[llength $attribs]} { + set face_name "$face_name ([join $attribs ,])" + } + $mapper SetInput "$face_name: $default_text" + set tprop [$mapper GetTextProperty] + eval $tprop SetFontFamilyTo$family + eval $tprop SetColor $text_color + $tprop SetBold $bold + $tprop SetItalic $italic + $tprop SetShadow $shadow + + set actor [vtkActor2D actor_${family}_${bold}_${italic}_${shadow}] + $actor SetMapper $mapper + lappend text_actors $actor + ren1 AddActor $actor + } +} + +# +# vtkTkRenderWidget is a Tk widget that we can render into. It has a +# GetRenderWindow method that returns a vtkRenderWindow. This can then +# be used to create a vtkRenderer and etc. We can also specify a +# vtkRenderWindow to be used when creating the widget by using the -rw +# option, which is what we do here by using renWin. It also takes +# -width and -height options that can be used to specify the widget +# size, hence the render window size. +# +set vtkw [vtkTkRenderWidget .ren \ + -width 800 \ + -rw renWin] + +# +# Setup Tk bindings and VTK observers for that widget. +# +::vtk::bind_tk_render_widget $vtkw + +# +# Once the VTK widget has been created it can be inserted into a whole Tk GUI +# as well as any other standard Tk widgets. +# +# We create a size slider controlling the font size. +# The orientation of this widget is horizontal (-orient option). We label +# it using the -label option. Finally, we bind the scale to Tcl code +# by assigning the -command option to the name of a Tcl +# procedure. Whenever the slider value changes this procedure will be +# called, enabling us to propagate this GUI setting to the +# corresponding VTK object. +# +set size_slider [scale .size \ + -from $min_font_size -to $max_font_size -res 1 \ + -orient horizontal \ + -label "Font size:" \ + -command set_font_size] + +# +# The procedure is called by the slider-widget handler whenever the +# slider value changes (either through user interaction or +# programmatically). It receives the slider value as parameter. We +# update the corresponding VTK objects by calling the +# SetFontSize method using this parameter and we render the scene to +# update the pipeline. +# +proc set_font_size {size} { + global text_actors + set i 0 + foreach actor $text_actors { + incr i + [[$actor GetMapper] GetTextProperty] SetFontSize $size + $actor SetDisplayPosition 10 [expr $i * ($size + 5)] + } + + renWin SetSize 800 [expr 20 + $i * ($size + 5)] + renWin Render +} + +$size_slider set $current_font_size + +# +# Finally we pack the VTK widget and the sliders on top of each other +# (-side top) inside the main root widget. +# +pack $size_slider -side top -fill both +pack $vtkw -side top -fill both -expand yes + +# +# We set the window manager (wm command) so that it registers a +# command to handle the WM_DELETE_WINDOW protocal request. This +# request is triggered when the widget is closed using the standard +# window manager icons or buttons. In this case the exit callback +# will be called and it will free up any objects we created then exit +# the application. +# +wm protocol . WM_DELETE_WINDOW ::vtk::cb_exit + +# +# You only need this line if you run this script from a Tcl shell +# (tclsh) instead of a Tk shell (wish) +# +tkwait window . + diff --git a/Examples/Annotation/Tcl/TestText.tcl b/Examples/Annotation/Tcl/TestText.tcl new file mode 100644 index 0000000..9a11445 --- /dev/null +++ b/Examples/Annotation/Tcl/TestText.tcl @@ -0,0 +1,63 @@ +# This example demonstrates the use of 2D text. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create a sphere source, mapper, and actor +vtkSphereSource sphere + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +# Create a scaled text actor. +# Set the text, font, justification, and properties (bold, italics, etc.). +vtkTextActor textActor + textActor ScaledTextOn + textActor SetDisplayPosition 90 50 + textActor SetInput "This is a sphere" + + # Set coordinates to match the old vtkScaledTextActor default value + [textActor GetPosition2Coordinate] SetCoordinateSystemToNormalizedViewport + [textActor GetPosition2Coordinate] SetValue 0.6 0.1 + +set tprop [textActor GetTextProperty] + $tprop SetFontSize 18 + $tprop SetFontFamilyToArial + $tprop SetJustificationToCentered + $tprop BoldOn + $tprop ItalicOn + $tprop ShadowOn + $tprop SetColor 0 0 1 + +# Create the Renderer, RenderWindow, RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer; set the background and size; zoom in; +# and render. +# +ren1 AddActor2D textActor +ren1 AddActor sphereActor + +ren1 SetBackground 1 1 1 +renWin SetSize 250 125 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +# Set the user method (bound to key 'u') +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the tk window +wm withdraw . diff --git a/Examples/Annotation/Tcl/TestTextOldWay.tcl b/Examples/Annotation/Tcl/TestTextOldWay.tcl new file mode 100644 index 0000000..1364ce0 --- /dev/null +++ b/Examples/Annotation/Tcl/TestTextOldWay.tcl @@ -0,0 +1,64 @@ +# This example demonstrates the use of 2D text. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create a sphere source, mapper, and actor +vtkSphereSource sphere + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +# Create a text mapper. +vtkTextMapper textMapper + textMapper SetInput "This is a sphere" + +# Set the text, font, justification, and text +# properties (bold, italics, etc.). + +set tprop [textMapper GetTextProperty] + $tprop SetFontSize 18 + $tprop SetFontFamilyToArial + $tprop SetJustificationToCentered + $tprop BoldOn + $tprop ItalicOn + $tprop ShadowOn + $tprop SetColor 0 0 1 + +# Create a scaled text actor. Set the position of the text. +vtkScaledTextActor textActor + textActor SetMapper textMapper + textActor SetDisplayPosition 90 50 + +# Create the Renderer, RenderWindow, RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer; set the background and size; zoom in; +# and render. +# +ren1 AddActor2D textActor +ren1 AddActor sphereActor + +ren1 SetBackground 1 1 1 +renWin SetSize 250 125 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +# Set the user method (bound to key 'u') +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the tk window +wm withdraw . diff --git a/Examples/Annotation/Tcl/annotatePick.tcl b/Examples/Annotation/Tcl/annotatePick.tcl new file mode 100644 index 0000000..f68fb93 --- /dev/null +++ b/Examples/Annotation/Tcl/annotatePick.tcl @@ -0,0 +1,104 @@ +# This example demonstrates cell picking using vtkCellPicker. It displays +# the results of picking using a vtkTextMapper. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# create a sphere source, mapper, and actor +# +vtkSphereSource sphere + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +# create the spikes by glyphing the sphere with a cone. Create the mapper +# and actor for the glyphs. +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] +vtkLODActor spikeActor + spikeActor SetMapper spikeMapper + +# Create a cell picker. +vtkCellPicker picker + picker AddObserver EndPickEvent annotatePick + +# Create a text mapper and actor to display the results of picking. +vtkTextMapper textMapper +set tprop [textMapper GetTextProperty] + $tprop SetFontFamilyToArial + $tprop SetFontSize 10 + $tprop BoldOn + $tprop ShadowOn + $tprop SetColor 1 0 0 +vtkActor2D textActor + textActor VisibilityOff + textActor SetMapper textMapper + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetPicker picker + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor2D textActor +ren1 AddActor sphereActor +ren1 AddActor spikeActor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 + +# Get the camera and zoom in closer to the image. +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 + +# Set the user method (bound to key 'u') +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# Withdraw the default tk window +wm withdraw . + +# Create a Tcl procedure to create the text for the text mapper used to +# display the results of picking. +proc annotatePick {} { + if { [picker GetCellId] < 0 } { + textActor VisibilityOff + + } else { + set selPt [picker GetSelectionPoint] + set x [lindex $selPt 0] + set y [lindex $selPt 1] + set pickPos [picker GetPickPosition] + set xp [lindex $pickPos 0] + set yp [lindex $pickPos 1] + set zp [lindex $pickPos 2] + + textMapper SetInput "($xp, $yp, $zp)" + textActor SetPosition $x $y + textActor VisibilityOn + } + + renWin Render +} + +# Pick the cell at this location. +picker Pick 85 126 0 ren1 diff --git a/Examples/Annotation/Tcl/cubeAxes.tcl b/Examples/Annotation/Tcl/cubeAxes.tcl new file mode 100644 index 0000000..d421571 --- /dev/null +++ b/Examples/Annotation/Tcl/cubeAxes.tcl @@ -0,0 +1,127 @@ +# This example demonstrates the use of vtkCubeAxesActor2D to indicate the +# position in space that the camera is currently viewing. +# The vtkCubeAxesActor2D draws axes on the bounding box of the data set and +# labels the axes with x-y-z coordinates. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create a vtkBYUReader and read in a data set. +# +vtkBYUReader fohe + fohe SetGeometryFileName "$VTK_DATA_ROOT/Data/teapot.g" +# Create a vtkPolyDataNormals filter to calculate the normals of the data set. +vtkPolyDataNormals normals + normals SetInputConnection [fohe GetOutputPort] +# Set up the associated mapper and actor. +vtkPolyDataMapper foheMapper + foheMapper SetInputConnection [normals GetOutputPort] +vtkLODActor foheActor + foheActor SetMapper foheMapper + +# Create a vtkOutlineFilter to draw the bounding box of the data set. Also +# create the associated mapper and actor. +vtkOutlineFilter outline + outline SetInputConnection [normals GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Create a vtkCamera, and set the camera parameters. +vtkCamera camera + camera SetClippingRange 1.60187 20.0842 + camera SetFocalPoint 0.21406 1.5 0 + camera SetPosition 8.3761 4.94858 4.12505 + camera SetViewUp 0.180325 0.549245 -0.815974 + +# Create a vtkLight, and set the light parameters. +vtkLight light + light SetFocalPoint 0.21406 1.5 0 + light SetPosition 8.3761 4.94858 4.12505 + +# Create the Renderers. Assign them the appropriate viewport coordinates, +# active camera, and light. +vtkRenderer ren1 + ren1 SetViewport 0 0 0.5 1.0 + ren1 SetActiveCamera camera + ren1 AddLight light +vtkRenderer ren2 + ren2 SetViewport 0.5 0 1.0 1.0 + ren2 SetActiveCamera camera + ren2 AddLight light + +# Create the RenderWindow and RenderWindowInteractor. +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin SetWindowName "VTK - Cube Axes" + renWin SetSize 600 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, and set the background. +# +ren1 AddViewProp foheActor +ren1 AddViewProp outlineActor +ren2 AddViewProp foheActor +ren2 AddViewProp outlineActor + +ren1 SetBackground 0.1 0.2 0.4 +ren2 SetBackground 0.1 0.2 0.4 + +# Create a text property for both cube axes +# +vtkTextProperty tprop + tprop SetColor 1 1 1 + tprop ShadowOn + +# Create a vtkCubeAxesActor2D. Use the outer edges of the bounding box to +# draw the axes. Add the actor to the renderer. +vtkCubeAxesActor2D axes + axes SetInput [normals GetOutput] + axes SetCamera [ren1 GetActiveCamera] + axes SetLabelFormat "%6.4g" + axes SetFlyModeToOuterEdges + axes SetFontFactor 0.8 + axes SetAxisTitleTextProperty tprop + axes SetAxisLabelTextProperty tprop +ren1 AddViewProp axes + +# Create a vtkCubeAxesActor2D. Use the closest vertex to the camera to +# determine where to draw the axes. Add the actor to the renderer. +vtkCubeAxesActor2D axes2 + axes2 SetViewProp foheActor + axes2 SetCamera [ren2 GetActiveCamera] + axes2 SetLabelFormat "%6.4g" + axes2 SetFlyModeToClosestTriad + axes2 SetFontFactor 0.8 + axes2 ScalingOff + axes2 SetAxisTitleTextProperty tprop + axes2 SetAxisLabelTextProperty tprop +ren2 AddViewProp axes2 + +# Render +renWin Render + +# Set the user method (bound to key 'u') +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# Set up a check for aborting rendering. +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +# Withdraw the default tk window. +wm withdraw . + + diff --git a/Examples/Annotation/Tcl/labeledMesh.tcl b/Examples/Annotation/Tcl/labeledMesh.tcl new file mode 100644 index 0000000..c2512b2 --- /dev/null +++ b/Examples/Annotation/Tcl/labeledMesh.tcl @@ -0,0 +1,157 @@ +# This example demonstrates the use of vtkLabeledDataMapper. This class +# is used for displaying numerical data from an underlying data set. In +# the case of this example, the underlying data are the point and cell +# ids. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create a selection window. We will display the point and cell ids that +# lie within this window. +set xmin 200 +set xLength 100 +set xmax [expr $xmin + $xLength] +set ymin 200 +set yLength 100 +set ymax [expr $ymin + $yLength] + +vtkPoints pts + pts InsertPoint 0 $xmin $ymin 0 + pts InsertPoint 1 $xmax $ymin 0 + pts InsertPoint 2 $xmax $ymax 0 + pts InsertPoint 3 $xmin $ymax 0 +vtkCellArray rect + rect InsertNextCell 5 + rect InsertCellPoint 0 + rect InsertCellPoint 1 + rect InsertCellPoint 2 + rect InsertCellPoint 3 + rect InsertCellPoint 0 +vtkPolyData selectRect + selectRect SetPoints pts + selectRect SetLines rect +vtkPolyDataMapper2D rectMapper + rectMapper SetInput selectRect +vtkActor2D rectActor + rectActor SetMapper rectMapper + +# Create a sphere and its associated mapper and actor. +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Generate data arrays containing point and cell ids +vtkIdFilter ids + ids SetInputConnection [sphere GetOutputPort] + ids PointIdsOn + ids CellIdsOn + ids FieldDataOn + +# Create the renderer here because vtkSelectVisiblePoints needs it. +vtkRenderer ren1 + +# Create labels for points +vtkSelectVisiblePoints visPts + visPts SetInputConnection [ids GetOutputPort] + visPts SetRenderer ren1 + visPts SelectionWindowOn + visPts SetSelection $xmin [expr $xmin + $xLength] \ + $ymin [expr $ymin + $yLength] + +# Create the mapper to display the point ids. Specify the +# format to use for the labels. Also create the associated actor. +vtkLabeledDataMapper ldm + ldm SetInputConnection [visPts GetOutputPort] + ldm SetLabelFormat "%g" + ldm SetLabelModeToLabelFieldData +vtkActor2D pointLabels + pointLabels SetMapper ldm + +# Create labels for cells +vtkCellCenters cc + cc SetInputConnection [ids GetOutputPort] +vtkSelectVisiblePoints visCells + visCells SetInputConnection [cc GetOutputPort] + visCells SetRenderer ren1 + visCells SelectionWindowOn + visCells SetSelection $xmin [expr $xmin + $xLength] \ + $ymin [expr $ymin + $yLength] +# Create the mapper to display the cell ids. Specify the +# format to use for the labels. Also create the associated actor. +vtkLabeledDataMapper cellMapper + cellMapper SetInputConnection [visCells GetOutputPort] + cellMapper SetLabelFormat "%g" + cellMapper SetLabelModeToLabelFieldData + [cellMapper GetLabelTextProperty] SetColor 0 1 0 +vtkActor2D cellLabels + cellLabels SetMapper cellMapper + +# Create the RenderWindow and RenderWindowInteractor +# +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer; set the background and size; +# render +ren1 AddActor sphereActor +ren1 AddActor2D rectActor +ren1 AddActor2D pointLabels +ren1 AddActor2D cellLabels + +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +renWin Render + +# Set the user method (bound to key 'u') +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the default tk window. +wm withdraw . + +# Create a tcl procedure to move the selection window across the data set. +proc MoveWindow {} { + for {set y 100} {$y < 300} {incr y 25} { + for {set x 100} {$x < 300} {incr x 25} { + PlaceWindow $x $y + } + } +} + +# Create a tcl procedure to draw the selection window at each location it +# is moved to. +proc PlaceWindow {xmin ymin} { + global xLength yLength + + set xmax [expr $xmin + $xLength] + set ymax [expr $ymin + $yLength] + + visPts SetSelection $xmin $xmax $ymin $ymax + visCells SetSelection $xmin $xmax $ymin $ymax + + pts InsertPoint 0 $xmin $ymin 0 + pts InsertPoint 1 $xmax $ymin 0 + pts InsertPoint 2 $xmax $ymax 0 + pts InsertPoint 3 $xmin $ymax 0 + # Call Modified because InsertPoints does not modify vtkPoints + # (for performance reasons). + pts Modified; + + renWin Render +} + +# Move the selection window across the data set. +MoveWindow +# Put the selection window in the center of the render window. +# This works because the xmin = ymin = 200, xLength = yLength = 100, and +# the render window size is 500 x 500. +PlaceWindow $xmin $ymin diff --git a/Examples/Annotation/Tcl/multiLineText.tcl b/Examples/Annotation/Tcl/multiLineText.tcl new file mode 100644 index 0000000..d4f236e --- /dev/null +++ b/Examples/Annotation/Tcl/multiLineText.tcl @@ -0,0 +1,204 @@ +# This example demonstrates the use of multiline 2D text using +# vtkTextMappers. It shows several justifications as well as single-line +# and multiple-line text inputs. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +set font_size 14 + +# Create the text mappers and the associated Actor2Ds. + +# The font and text properties (except justification) are the same for each +# single line mapper. Let's create a common text property object + +vtkTextProperty singleLineTextProp + singleLineTextProp SetFontSize $font_size + singleLineTextProp SetFontFamilyToArial + singleLineTextProp BoldOff + singleLineTextProp ItalicOff + singleLineTextProp ShadowOff + +# The font and text properties (except justification) are the same for each +# multi line mapper. Let's create a common text property object + +vtkTextProperty multiLineTextProp + multiLineTextProp ShallowCopy singleLineTextProp + multiLineTextProp BoldOn + multiLineTextProp ItalicOn + multiLineTextProp ShadowOn + multiLineTextProp SetLineSpacing 0.8 + +# The text is on a single line and bottom-justified. +vtkTextMapper singleLineTextB + singleLineTextB SetInput "Single line (bottom)" + set tprop [singleLineTextB GetTextProperty] + $tprop ShallowCopy singleLineTextProp + $tprop SetVerticalJustificationToBottom + $tprop SetColor 1 0 0 +vtkActor2D singleLineTextActorB + singleLineTextActorB SetMapper singleLineTextB + [singleLineTextActorB GetPositionCoordinate] \ + SetCoordinateSystemToNormalizedDisplay + [singleLineTextActorB GetPositionCoordinate] SetValue 0.05 0.85 + +# The text is on a single line and center-justified (vertical justification). +vtkTextMapper singleLineTextC + singleLineTextC SetInput "Single line (centered)" + set tprop [singleLineTextC GetTextProperty] + $tprop ShallowCopy singleLineTextProp + $tprop SetVerticalJustificationToCentered + $tprop SetColor 0 1 0 +vtkActor2D singleLineTextActorC + singleLineTextActorC SetMapper singleLineTextC + [singleLineTextActorC GetPositionCoordinate] \ + SetCoordinateSystemToNormalizedDisplay + [singleLineTextActorC GetPositionCoordinate] SetValue 0.05 0.75 + +# The text is on a single line and top-justified. +vtkTextMapper singleLineTextT + singleLineTextT SetInput "Single line (top)" + set tprop [singleLineTextT GetTextProperty] + $tprop ShallowCopy singleLineTextProp + $tprop SetVerticalJustificationToTop + $tprop SetColor 0 0 1 +vtkActor2D singleLineTextActorT + singleLineTextActorT SetMapper singleLineTextT + [singleLineTextActorT GetPositionCoordinate] \ + SetCoordinateSystemToNormalizedDisplay + [singleLineTextActorT GetPositionCoordinate] SetValue 0.05 0.65 + +# The text is on multiple lines and left- and top-justified. +vtkTextMapper textMapperL + textMapperL SetInput "This is\nmulti-line\ntext output\n(left-top)" + set tprop [textMapperL GetTextProperty] + $tprop ShallowCopy multiLineTextProp + $tprop SetJustificationToLeft + $tprop SetVerticalJustificationToTop + $tprop SetColor 1 0 0 +vtkActor2D textActorL + textActorL SetMapper textMapperL + [textActorL GetPositionCoordinate] SetCoordinateSystemToNormalizedDisplay + [textActorL GetPositionCoordinate] SetValue 0.05 0.5 + +# The text is on multiple lines and center-justified (both horizontal and +# vertical). +vtkTextMapper textMapperC + textMapperC SetInput "This is\nmulti-line\ntext output\n(centered)" + set tprop [textMapperC GetTextProperty] + $tprop ShallowCopy multiLineTextProp + $tprop SetJustificationToCentered + $tprop SetVerticalJustificationToCentered + $tprop SetColor 0 1 0 +vtkActor2D textActorC + textActorC SetMapper textMapperC + [textActorC GetPositionCoordinate] SetCoordinateSystemToNormalizedDisplay + [textActorC GetPositionCoordinate] SetValue 0.5 0.5 + +# The text is on multiple lines and right- and bottom-justified. +vtkTextMapper textMapperR + textMapperR SetInput "This is\nmulti-line\ntext output\n(right-bottom)" + set tprop [textMapperR GetTextProperty] + $tprop ShallowCopy multiLineTextProp + $tprop SetJustificationToRight + $tprop SetVerticalJustificationToBottom + $tprop SetColor 0 0 1 +vtkActor2D textActorR + textActorR SetMapper textMapperR + [textActorR GetPositionCoordinate] SetCoordinateSystemToNormalizedDisplay + [textActorR GetPositionCoordinate] SetValue 0.95 0.5 + +# Draw the grid to demonstrate the placement of the text. + +# Set up the necessary points. +vtkPoints Pts + Pts InsertNextPoint 0.05 0.0 0.0 + Pts InsertNextPoint 0.05 1.0 0.0 + Pts InsertNextPoint 0.5 0.0 0.0 + Pts InsertNextPoint 0.5 1.0 0.0 + Pts InsertNextPoint 0.95 0.0 0.0 + Pts InsertNextPoint 0.95 1.0 0.0 + Pts InsertNextPoint 0.0 0.5 0.0 + Pts InsertNextPoint 1.0 0.5 0.0 + Pts InsertNextPoint 0.00 0.85 0.0 + Pts InsertNextPoint 0.50 0.85 0.0 + Pts InsertNextPoint 0.00 0.75 0.0 + Pts InsertNextPoint 0.50 0.75 0.0 + Pts InsertNextPoint 0.00 0.65 0.0 + Pts InsertNextPoint 0.50 0.65 0.0 +# Set up the lines that use these points. +vtkCellArray Lines + Lines InsertNextCell 2 + Lines InsertCellPoint 0 + Lines InsertCellPoint 1 + Lines InsertNextCell 2 + Lines InsertCellPoint 2 + Lines InsertCellPoint 3 + Lines InsertNextCell 2 + Lines InsertCellPoint 4 + Lines InsertCellPoint 5 + Lines InsertNextCell 2 + Lines InsertCellPoint 6 + Lines InsertCellPoint 7 + Lines InsertNextCell 2 + Lines InsertCellPoint 8 + Lines InsertCellPoint 9 + Lines InsertNextCell 2 + Lines InsertCellPoint 10 + Lines InsertCellPoint 11 + Lines InsertNextCell 2 + Lines InsertCellPoint 12 + Lines InsertCellPoint 13 +# Create a grid that uses these points and lines. +vtkPolyData Grid + Grid SetPoints Pts + Grid SetLines Lines +# Set up the coordinate system. +vtkCoordinate normCoords + normCoords SetCoordinateSystemToNormalizedViewport + +# Set up the mapper and actor (2D) for the grid. +vtkPolyDataMapper2D mapper + mapper SetInput Grid + mapper SetTransformCoordinate normCoords +vtkActor2D gridActor + gridActor SetMapper mapper + [gridActor GetProperty] SetColor 0.1 0.1 0.1 + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer; set the background and size; zoom in +# closer to the image; render +# +ren1 AddActor2D textActorL +ren1 AddActor2D textActorC +ren1 AddActor2D textActorR +ren1 AddActor2D singleLineTextActorB +ren1 AddActor2D singleLineTextActorC +ren1 AddActor2D singleLineTextActorT +ren1 AddActor2D gridActor + +ren1 SetBackground 1 1 1 +renWin SetSize 500 300 +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +# Set the user method (bound to key 'u') +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the default tk window. +wm withdraw . + + + diff --git a/Examples/Annotation/Tcl/textOrigin.tcl b/Examples/Annotation/Tcl/textOrigin.tcl new file mode 100644 index 0000000..255b66b --- /dev/null +++ b/Examples/Annotation/Tcl/textOrigin.tcl @@ -0,0 +1,58 @@ +# This example demonstrates the use of vtkVectorText and vtkFollower. +# vtkVectorText is used to create 3D annotation. vtkFollower is used to +# position the 3D text and to ensure that the text always faces the +# renderer's active camera (i.e., the text is always readable). + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create the axes and the associated mapper and actor. +vtkAxes axes + axes SetOrigin 0 0 0 +vtkPolyDataMapper axesMapper + axesMapper SetInputConnection [axes GetOutputPort] +vtkActor axesActor + axesActor SetMapper axesMapper + +# Create the 3D text and the associated mapper and follower (a type of +# actor). Position the text so it is displayed over the origin of the axes. +vtkVectorText atext + atext SetText "Origin" +vtkPolyDataMapper textMapper + textMapper SetInputConnection [atext GetOutputPort] +vtkFollower textActor + textActor SetMapper textMapper + textActor SetScale 0.2 0.2 0.2 + textActor AddPosition 0 -0.1 0 + +# Create the Renderer, RenderWindow, and RenderWindowInteractor. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer. +ren1 AddActor axesActor +ren1 AddActor textActor + +# Zoom in closer. +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.6 + +# Reset the clipping range of the camera; set the camera of the follower; +# render. +ren1 ResetCameraClippingRange +textActor SetCamera [ren1 GetActiveCamera] +renWin Render + +# Set the user method (bound to key 'u') +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the default tk window. +wm withdraw . diff --git a/Examples/Annotation/Tcl/xyPlot.tcl b/Examples/Annotation/Tcl/xyPlot.tcl new file mode 100644 index 0000000..db9c710 --- /dev/null +++ b/Examples/Annotation/Tcl/xyPlot.tcl @@ -0,0 +1,201 @@ +# This example demonstrates the use of vtkXYPlotActor to display three +# probe lines using three different techniques. In this example, we are +# loading data using the vtkPLOT3DReader. We are using the vtkProbeFilter +# to extract the underlying point data along three probe lines. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl. +# +package require vtk +package require vtkinteraction + +# Create a PLOT3D reader and load the data. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# Create three the line source to use for the probe lines. +vtkLineSource line + line SetResolution 30 + +# Move the line into place and create the probe filter. For vtkProbeFilter, +# the probe line is the input, and the underlying data set is the source. +vtkTransform transL1 + transL1 Translate 3.7 0.0 28.37 + transL1 Scale 5 5 5 + transL1 RotateY 90 +vtkTransformPolyDataFilter tf + tf SetInputConnection [line GetOutputPort] + tf SetTransform transL1 +vtkProbeFilter probe + probe SetInputConnection [tf GetOutputPort] + probe SetSource [pl3d GetOutput] + +# Move the line again and create another probe filter. +vtkTransform transL2 + transL2 Translate 9.2 0.0 31.20 + transL2 Scale 5 5 5 + transL2 RotateY 90 +vtkTransformPolyDataFilter tf2 + tf2 SetInputConnection [line GetOutputPort] + tf2 SetTransform transL2 +vtkProbeFilter probe2 + probe2 SetInputConnection [tf2 GetOutputPort] + probe2 SetSource [pl3d GetOutput] + +# Move the line again and create a third probe filter. +vtkTransform transL3 + transL3 Translate 13.27 0.0 33.40 + transL3 Scale 4.5 4.5 4.5 + transL3 RotateY 90 +vtkTransformPolyDataFilter tf3 + tf3 SetInputConnection [line GetOutputPort] + tf3 SetTransform transL3 +vtkProbeFilter probe3 + probe3 SetInputConnection [tf3 GetOutputPort] + probe3 SetSource [pl3d GetOutput] + +# Create a vtkAppendPolyData to merge the output of the three probe filters +# into one data set. +vtkAppendPolyData appendF + appendF AddInput [probe GetPolyDataOutput] + appendF AddInput [probe2 GetPolyDataOutput] + appendF AddInput [probe3 GetPolyDataOutput] + +# Create a tube filter to represent the lines as tubes. Set up the associated +# mapper and actor. +vtkTubeFilter tuber + tuber SetInputConnection [appendF GetOutputPort] + tuber SetRadius 0.1 +vtkPolyDataMapper lineMapper + lineMapper SetInputConnection [tuber GetOutputPort] +vtkActor lineActor + lineActor SetMapper lineMapper + +# Create an xy-plot using the output of the 3 probe filters as input. +# The x-values we are plotting are arc length. +vtkXYPlotActor xyplot + xyplot AddInput [probe GetOutput] + xyplot AddInput [probe2 GetOutput] + xyplot AddInput [probe3 GetOutput] + [xyplot GetPositionCoordinate] SetValue 0.0 0.67 0 + [xyplot GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot SetXValuesToArcLength + xyplot SetNumberOfXLabels 6 + xyplot SetTitle "Pressure vs. Arc Length (Zoomed View)" + xyplot SetXTitle "" + xyplot SetYTitle "P" + xyplot SetXRange .1 .35 + xyplot SetYRange .2 .4 + [xyplot GetProperty] SetColor 0 0 0 + [xyplot GetProperty] SetLineWidth 2 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot GetTitleTextProperty] + eval $tprop SetColor [[xyplot GetProperty] GetColor] + xyplot SetAxisTitleTextProperty $tprop + xyplot SetAxisLabelTextProperty $tprop + +# Create an xy-plot using the output of the 3 probe filters as input. +# The x-values we are plotting are normalized arc length. +vtkXYPlotActor xyplot2 + xyplot2 AddInput [probe GetOutput] + xyplot2 AddInput [probe2 GetOutput] + xyplot2 AddInput [probe3 GetOutput] + [xyplot2 GetPositionCoordinate] SetValue 0.00 0.33 0 + [xyplot2 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot2 SetXValuesToNormalizedArcLength + xyplot2 SetNumberOfXLabels 6 + xyplot2 SetTitle "Pressure vs. Normalized Arc Length" + xyplot2 SetXTitle "" + xyplot2 SetYTitle "P" + xyplot2 PlotPointsOn + xyplot2 PlotLinesOff + [xyplot2 GetProperty] SetColor 1 0 0 + [xyplot2 GetProperty] SetPointSize 2 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot2 GetTitleTextProperty] + eval $tprop SetColor [[xyplot2 GetProperty] GetColor] + xyplot2 SetAxisTitleTextProperty $tprop + xyplot2 SetAxisLabelTextProperty $tprop + +# Create an xy-plot using the output of the 3 probe filters as input. +# The x-values we are plotting are the underlying point data values. +vtkXYPlotActor xyplot3 + xyplot3 AddInput [probe GetOutput] + xyplot3 AddInput [probe2 GetOutput] + xyplot3 AddInput [probe3 GetOutput] + [xyplot3 GetPositionCoordinate] SetValue 0.0 0.0 0 + [xyplot3 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot3 SetXValuesToIndex + xyplot3 SetNumberOfXLabels 6 + xyplot3 SetTitle "Pressure vs. Point Id" + xyplot3 SetXTitle "Probe Length" + xyplot3 SetYTitle "P" + xyplot3 PlotPointsOn + [xyplot3 GetProperty] SetColor 0 0 1 + [xyplot3 GetProperty] SetPointSize 3 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot3 GetTitleTextProperty] + eval $tprop SetColor [[xyplot3 GetProperty] GetColor] + xyplot3 SetAxisTitleTextProperty $tprop + xyplot3 SetAxisLabelTextProperty $tprop + +# Draw an outline of the PLOT3D data set. +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Create the Renderers, RenderWindow, and RenderWindowInteractor. +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Set the background, viewport (necessary because we want to have the +# renderers draw to different parts of the render window) of the first +# renderer. Add the outline and line actors to the renderer. +ren1 SetBackground 0.6784 0.8471 0.9020 +ren1 SetViewport 0 0 .5 1 +ren1 AddActor outlineActor +ren1 AddActor lineActor + +# Set the background and viewport of the second renderer. Add the xy-plot +# actors to the renderer. Set the size of the render window. +ren2 SetBackground 1 1 1 +ren2 SetViewport 0.5 0.0 1.0 1.0 +ren2 AddActor2D xyplot +ren2 AddActor2D xyplot2 +ren2 AddActor2D xyplot3 +renWin SetSize 500 250 + +# Set up the camera parameters. +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.95297 100 + $cam1 SetFocalPoint 8.88908 0.595038 29.3342 + $cam1 SetPosition -12.3332 31.7479 41.2387 + $cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize + +# Set the user method (bound to key 'u') +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the default tk window. +wm withdraw . + diff --git a/Examples/Build/vtkLocal/CMakeLists.txt b/Examples/Build/vtkLocal/CMakeLists.txt new file mode 100644 index 0000000..eed6d9d --- /dev/null +++ b/Examples/Build/vtkLocal/CMakeLists.txt @@ -0,0 +1,150 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.0) + +# Set the project/library name here. Classes should be declared as +# "class vtkLocal_EXPORT vtkFoo", where vtkLocal is the name of the +# project set here. +PROJECT(vtkLocal) + +# Set your list of sources here. Do not change the name of the +# vtkLocal_SRCS variable. +SET(vtkLocal_SRCS + vtkLocalExample.cxx +) + +# List the kits from VTK that are needed by this project. +SET(vtkLocal_LIBS + vtkCommon +) + +#----------------------------------------------------------------------------- +# Most users should not need to change anything below this line. + +# Need to include class headers and the configuration header. +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}) + +# Setup output paths. +SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin CACHE PATH + "Single output directory for building all libraries.") +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin CACHE PATH + "Single output directory for building all executables.") +MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) + +# Find and load VTK settings. +FIND_PACKAGE(VTK REQUIRED) +INCLUDE(${VTK_USE_FILE}) + +# Give user option of building shared or static libraries. Default to +# the choice made for VTK. +OPTION(BUILD_SHARED_LIBS "Build with shared libraries." + ${VTK_BUILD_SHARED_LIBS}) + +# Set VTKLOCAL_BUILD_SHARED_LIBS to 1 or 0 for use in creating the +# configuration header. +IF(BUILD_SHARED_LIBS) + SET(VTKLOCAL_BUILD_SHARED_LIBS_CONFIG 1) +ELSE(BUILD_SHARED_LIBS) + SET(VTKLOCAL_BUILD_SHARED_LIBS_CONFIG 0) +ENDIF(BUILD_SHARED_LIBS) + +IF(VTK_FOUND) + # If this is a build tree, provide an option for putting this + # project's executables and libraries in with VTK's. + IF (EXISTS ${VTK_DIR}/bin) + OPTION(USE_VTK_OUTPUT_PATHS + "Use VTK's output directory for this project's executables and libraries." + OFF) + MARK_AS_ADVANCED (USE_VTK_OUTPUT_PATHS) + IF (USE_VTK_OUTPUT_PATHS) + SET (LIBRARY_OUTPUT_PATH ${VTK_DIR}/bin) + SET (EXECUTABLE_OUTPUT_PATH ${VTK_DIR}/bin) + ENDIF (USE_VTK_OUTPUT_PATHS) + ENDIF (EXISTS ${VTK_DIR}/bin) + + # Create the header to configure the classes. + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/vtkLocalConfigure.h.in + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Configure.h + @ONLY IMMEDIATE) + + # Use wrapping hints for this project. + SET(VTK_WRAP_HINTS "${PROJECT_SOURCE_DIR}/hints") + + # Create the instantiator for these classes. + SET(VTK_USE_INSTANTIATOR_NEW 1) + VTK_MAKE_INSTANTIATOR3("${PROJECT_NAME}Instantiator" + vtkLocalInstantiator_SRCS + "${vtkLocal_SRCS}" + "VTK_${PROJECT_NAME}_EXPORT" + ${PROJECT_BINARY_DIR} + "${PROJECT_NAME}Configure.h") + + # Create the library. + ADD_LIBRARY(${PROJECT_NAME} ${vtkLocal_SRCS} ${vtkLocalInstantiator_SRCS}) + TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${vtkLocal_LIBS}) + + # Create Tcl wrappers if VTK is wrapped in Tcl. + IF(VTK_WRAP_TCL) + INCLUDE(${VTK_CMAKE_DIR}/vtkWrapTcl.cmake) + SET(VTK_WRAP_TCL3_INIT_DIR "${PROJECT_SOURCE_DIR}") + VTK_WRAP_TCL3(${PROJECT_NAME}TCL vtkLocalTCL_SRCS "${vtkLocal_SRCS}" "") + ADD_LIBRARY(${PROJECT_NAME}TCL ${vtkLocalTCL_SRCS}) + TARGET_LINK_LIBRARIES(${PROJECT_NAME}TCL ${PROJECT_NAME}) + FOREACH(c ${vtkLocal_LIBS}) + TARGET_LINK_LIBRARIES(${PROJECT_NAME}TCL ${c}TCL) + ENDFOREACH(c) + + # Create the list of kits that are required. + SET(VTKLOCAL_KITS "") + FOREACH(c ${vtkLocal_LIBS}) + SET(VTKLOCAL_KITS "${VTKLOCAL_KITS} ${c}") + ENDFOREACH(c) + FOREACH(c ${vtkLocal_SRCS}) + GET_FILENAME_COMPONENT(VTKLOCAL_LAST_CLASS ${c} NAME_WE) + ENDFOREACH(c) + + IF(CMAKE_CONFIGURATION_TYPES) + FOREACH(config ${CMAKE_CONFIGURATION_TYPES}) + SET(VTKLOCAL_TCL_LIBRARY_DIR "${LIBRARY_OUTPUT_PATH}/${config}") + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/pkgIndex.tcl.in + ${PROJECT_BINARY_DIR}/${config}/pkgIndex.tcl + @ONLY IMMEDIATE) + ENDFOREACH(config) + ELSE(CMAKE_CONFIGURATION_TYPES) + SET(VTKLOCAL_TCL_LIBRARY_DIR "${LIBRARY_OUTPUT_PATH}") + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/pkgIndex.tcl.in + ${PROJECT_BINARY_DIR}/pkgIndex.tcl + @ONLY IMMEDIATE) + ENDIF(CMAKE_CONFIGURATION_TYPES) + + ENDIF(VTK_WRAP_TCL) + + # Create Python wrappers if VTK is wrapped in Python. + IF(VTK_WRAP_PYTHON) + INCLUDE(${VTK_CMAKE_DIR}/vtkWrapPython.cmake) + SET(VTK_WRAP_PYTHON3_INIT_DIR "${PROJECT_SOURCE_DIR}") + VTK_WRAP_PYTHON3(${PROJECT_NAME}Python vtkLocalPYTHON_SRCS "${vtkLocal_SRCS}") + ADD_LIBRARY(${PROJECT_NAME}PythonD ${vtkLocalPYTHON_SRCS}) + ADD_LIBRARY(${PROJECT_NAME}Python MODULE ${PROJECT_NAME}PythonInit.cxx) + TARGET_LINK_LIBRARIES(${PROJECT_NAME}PythonD ${PROJECT_NAME}) + FOREACH(c ${vtkLocal_LIBS}) + TARGET_LINK_LIBRARIES(${PROJECT_NAME}PythonD ${c}PythonD) + ENDFOREACH(c) + TARGET_LINK_LIBRARIES(${PROJECT_NAME}Python ${PROJECT_NAME}PythonD) + ENDIF(VTK_WRAP_PYTHON) + + # Create Java wrappers if VTK is wrapped in Java. + IF(VTK_WRAP_JAVA) + INCLUDE(${VTK_CMAKE_DIR}/vtkWrapJava.cmake) + SET(VTK_WRAP_JAVA3_INIT_DIR "${PROJECT_SOURCE_DIR}") + SET(VTK_JAVA_HOME ${PROJECT_BINARY_DIR}/java/${PROJECT_NAME}) + MAKE_DIRECTORY(${VTK_JAVA_HOME}) + VTK_WRAP_JAVA3(${PROJECT_NAME}Java vtkLocalJAVA_SRCS "${vtkLocal_SRCS}") + ADD_LIBRARY(${PROJECT_NAME}Java ${vtkLocalJAVA_SRCS}) + TARGET_LINK_LIBRARIES(${PROJECT_NAME}Java ${PROJECT_NAME}) + FOREACH(c ${vtkLocal_LIBS}) + TARGET_LINK_LIBRARIES(${PROJECT_NAME}Java ${c}Java) + ENDFOREACH(c) + ENDIF(VTK_WRAP_JAVA) + + SUBDIRS(Testing) +ENDIF(VTK_FOUND) diff --git a/Examples/Build/vtkLocal/JavaDependencies.cmake.in b/Examples/Build/vtkLocal/JavaDependencies.cmake.in new file mode 100644 index 0000000..016235e --- /dev/null +++ b/Examples/Build/vtkLocal/JavaDependencies.cmake.in @@ -0,0 +1,5 @@ +# This file is automatically generated by CMake VTK_WRAP_JAVA +SET(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES} +@VTK_JAVA_DEPENDENCIES_FILE@ +) + diff --git a/Examples/Build/vtkLocal/README b/Examples/Build/vtkLocal/README new file mode 100644 index 0000000..5418608 --- /dev/null +++ b/Examples/Build/vtkLocal/README @@ -0,0 +1,47 @@ +Introduction: +------------- + +This directory provides a starting point to create a local project +that adds classes to VTK. It is intended to enable users to put a few +of their own classes into a new local kit. The classes are +automatically wrapped into the same languages into which your VTK +build is wrapped. + +What you should do: +------------------- + +- Copy this vtkLocal directory to a different out-of-source place, and + remove all CVS subdirs to avoid any accidental commit to the main + VTK CVS. + +- Edit the CMakeLists.txt file and add your classes to the vtkLocal_SRCS + list. Also add any VTK kits used by your classes to the vtkLocal_LIBS + list. You can also change the project name, but "vtkLocal" is fine + for most users unless you wish to distribute the library. + Your classes should #include "vtkLocalConfigure.h", or + "Configure.h" if you changed the project name. They + should also be declared as "class VTK_vtkLocal_EXPORT vtkMyClass" + or "class VTK__EXPORT vtkMyClass" if you changed the project + name. + +- Run CMake as usual. Use your copy of the vtkLocal directory as the + source dir, and choose whatever build directory you prefer. + If it is not found automatically, set VTK_DIR in the CMake GUI + to point to the VTK build tree, or to the install tree in PREFIX/lib/vtk. + +- Build your project. + +- If you want to use your classes from another C++ project and are + building with shared libraries on windows, add the path to your + build-dir/bin directory to your PATH environment variable so the + DLL can be found (with the Debug, Release, etc. directory name for + Visual Studio builds). + +- If you want to use your classes from Tcl, add your project build tree + to the TCLLIBPATH (with the Debug, Release, etc. directory name for + Visual Studio builds). You may load your classes by using + "package require vtkLocalTCL" or "package require TCL" + if you changed the project name. Windows users should use forward + slashes (/) instead of the usual backward slashes (\), and should + surround the path by quotes (") if it contains any space. Remember + that TCLLIBPATH is a space-separated list. diff --git a/Examples/Build/vtkLocal/Testing/CMakeLists.txt b/Examples/Build/vtkLocal/Testing/CMakeLists.txt new file mode 100644 index 0000000..f749b8b --- /dev/null +++ b/Examples/Build/vtkLocal/Testing/CMakeLists.txt @@ -0,0 +1 @@ +SUBDIRS(Cxx) \ No newline at end of file diff --git a/Examples/Build/vtkLocal/Testing/Cxx/CMakeLists.txt b/Examples/Build/vtkLocal/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..b630f78 --- /dev/null +++ b/Examples/Build/vtkLocal/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,2 @@ +ADD_EXECUTABLE(vtkLocalTest vtkLocalTest.cxx) +TARGET_LINK_LIBRARIES(vtkLocalTest vtkLocal) \ No newline at end of file diff --git a/Examples/Build/vtkLocal/Testing/Cxx/vtkLocalTest.cxx b/Examples/Build/vtkLocal/Testing/Cxx/vtkLocalTest.cxx new file mode 100644 index 0000000..59e3b45 --- /dev/null +++ b/Examples/Build/vtkLocal/Testing/Cxx/vtkLocalTest.cxx @@ -0,0 +1,9 @@ +#include "vtkLocalExample.h" + +int main() +{ + vtkLocalExample* l = vtkLocalExample::New(); + l->Print(cout); + l->Delete(); + return 0; +} diff --git a/Examples/Build/vtkLocal/hints b/Examples/Build/vtkLocal/hints new file mode 100644 index 0000000..e69de29 diff --git a/Examples/Build/vtkLocal/pkgIndex.tcl.in b/Examples/Build/vtkLocal/pkgIndex.tcl.in new file mode 100644 index 0000000..4e2d7c0 --- /dev/null +++ b/Examples/Build/vtkLocal/pkgIndex.tcl.in @@ -0,0 +1,12 @@ +package ifneeded {@PROJECT_NAME@TCL} {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} { + if {@VTKLOCAL_BUILD_SHARED_LIBS_CONFIG@} { + package require -exact vtkinit {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} + foreach kit {@VTKLOCAL_KITS@} { + package require -exact "${kit}TCL" {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} + } + ::vtk::init::load_library_package {@PROJECT_NAME@TCL} {@VTKLOCAL_TCL_LIBRARY_DIR@} + } else { + error {Error loading @PROJECT_NAME@TCL. @PROJECT_NAME@ must be built\ + with shared libraries for loading as a Tcl package.} + } +} diff --git a/Examples/Build/vtkLocal/vtkLocalConfigure.h.in b/Examples/Build/vtkLocal/vtkLocalConfigure.h.in new file mode 100644 index 0000000..5bb6544 --- /dev/null +++ b/Examples/Build/vtkLocal/vtkLocalConfigure.h.in @@ -0,0 +1,33 @@ +/*========================================================================= +This source has no copyright. It is intended to be copied by users +wishing to create their own VTK classes locally. +=========================================================================*/ +#ifndef __@PROJECT_NAME@Configure_h +#define __@PROJECT_NAME@Configure_h + +// Define @PROJECT_NAME@_SHARED if the library was built shared. +#if @VTKLOCAL_BUILD_SHARED_LIBS_CONFIG@ +# define @PROJECT_NAME@_SHARED +#endif + +// Disable warning caused from static VTK and shared @PROJECT_NAME@. +#if defined(_MSC_VER) && defined(@PROJECT_NAME@_SHARED) +# pragma warning (disable: 4275) /* non-DLL-interface base class used */ +#endif + +// Setup export/import macro for DLL. The symbol +// "@PROJECT_NAME@_EXPORTS" is defined by CMake when building source +// files for a shared library named "@PROJECT_NAME@". For these +// sources we should export if building a shared library. For other +// sources we should import if using a shared library. +#if defined(_WIN32) && defined(@PROJECT_NAME@_SHARED) +# if defined(@PROJECT_NAME@_EXPORTS) +# define VTK_@PROJECT_NAME@_EXPORT __declspec(dllexport) +# else +# define VTK_@PROJECT_NAME@_EXPORT __declspec(dllimport) +# endif +#else +# define VTK_@PROJECT_NAME@_EXPORT +#endif + +#endif // __@PROJECT_NAME@Configure_h diff --git a/Examples/Build/vtkLocal/vtkLocalExample.cxx b/Examples/Build/vtkLocal/vtkLocalExample.cxx new file mode 100644 index 0000000..6457a37 --- /dev/null +++ b/Examples/Build/vtkLocal/vtkLocalExample.cxx @@ -0,0 +1,26 @@ +/*========================================================================= +This source has no copyright. It is intended to be copied by users +wishing to create their own VTK classes locally. +=========================================================================*/ +#include "vtkLocalExample.h" + +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkLocalExample, "$Revision: 1.1.34.1 $"); +vtkStandardNewMacro(vtkLocalExample); + +//---------------------------------------------------------------------------- +vtkLocalExample::vtkLocalExample() +{ +} + +//---------------------------------------------------------------------------- +vtkLocalExample::~vtkLocalExample() +{ +} + +//---------------------------------------------------------------------------- +void vtkLocalExample::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Examples/Build/vtkLocal/vtkLocalExample.h b/Examples/Build/vtkLocal/vtkLocalExample.h new file mode 100644 index 0000000..73e8fe8 --- /dev/null +++ b/Examples/Build/vtkLocal/vtkLocalExample.h @@ -0,0 +1,32 @@ +/*========================================================================= +This source has no copyright. It is intended to be copied by users +wishing to create their own VTK classes locally. +=========================================================================*/ +// .NAME vtkLocalExample - Example class using VTK. +// .SECTION Description +// vtkLocalExample is a simple class that uses VTK. This class can be +// copied and modified to produce your own classes. + +#ifndef __vtkLocalExample_h +#define __vtkLocalExample_h + +#include "vtkLocalConfigure.h" // Include configuration header. +#include "vtkObject.h" + +class VTK_vtkLocal_EXPORT vtkLocalExample : public vtkObject +{ +public: + static vtkLocalExample* New(); + vtkTypeRevisionMacro(vtkLocalExample, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkLocalExample(); + ~vtkLocalExample(); + +private: + vtkLocalExample(const vtkLocalExample&); // Not implemented. + void operator=(const vtkLocalExample&); // Not implemented. +}; + +#endif diff --git a/Examples/Build/vtkLocal/vtkWrapperInit.data.in b/Examples/Build/vtkLocal/vtkWrapperInit.data.in new file mode 100644 index 0000000..3d10232 --- /dev/null +++ b/Examples/Build/vtkLocal/vtkWrapperInit.data.in @@ -0,0 +1 @@ +@VTK_WRAPPER_INIT_DATA@ diff --git a/Examples/Build/vtkMy/CMakeLists.txt b/Examples/Build/vtkMy/CMakeLists.txt new file mode 100644 index 0000000..70823e6 --- /dev/null +++ b/Examples/Build/vtkMy/CMakeLists.txt @@ -0,0 +1,57 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.0) + +# +# Set the project name. +# + +PROJECT (VTKMY) + +# +# Load CMake commands that you probably should not modify. +# + +INCLUDE (${VTKMY_SOURCE_DIR}/CMakeOptions.cmake) + +# +# Here is where you can list the sub-directories holding your local +# classes. Sorting classes by 'package' type like VTK does (Common, +# Rendering, Filtering, Imaging, IO, etc.) is a good thing and prevents +# numerous dependencies problems. +# + +SUBDIRS ( + Common + Imaging + Unsorted + Utilities +) + +# +# You can put your include path(s) here +# + +INCLUDE_DIRECTORIES(${VTKMY_SOURCE_DIR}/Common) +INCLUDE_DIRECTORIES (${VTKMY_SOURCE_DIR}/Imaging) +INCLUDE_DIRECTORIES (${VTKMY_SOURCE_DIR}/Unsorted) + +# +# Build examples too ? +# + +OPTION(BUILD_EXAMPLES "Build examples." ON) +IF (BUILD_EXAMPLES) + SUBDIRS(Examples) +ENDIF (BUILD_EXAMPLES) + +# +# Common configuration settings +# +# Do not worry about this one. +# + +CONFIGURE_FILE( + ${VTKMY_SOURCE_DIR}/vtkmyConfigure.h.in + ${VTKMY_BINARY_DIR}/vtkmyConfigure.h +) + +INCLUDE_DIRECTORIES(${VTKMY_BINARY_DIR}) diff --git a/Examples/Build/vtkMy/CMakeOptions.cmake b/Examples/Build/vtkMy/CMakeOptions.cmake new file mode 100644 index 0000000..c7bd7fd --- /dev/null +++ b/Examples/Build/vtkMy/CMakeOptions.cmake @@ -0,0 +1,148 @@ +# +# Configure output paths for libraries and executables. +# +SET(LIBRARY_OUTPUT_PATH ${VTKMY_BINARY_DIR}/bin CACHE PATH + "Single output directory for building all libraries.") +SET(EXECUTABLE_OUTPUT_PATH ${VTKMY_BINARY_DIR}/bin CACHE PATH + "Single output directory for building all executables.") +MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) + +# +# Try to find VTK and include its settings (otherwise complain) +# +FIND_PACKAGE(VTK REQUIRED) +INCLUDE(${VTK_USE_FILE}) + +# +# Build shared libs ? +# +# Defaults to the same VTK setting. +# + +# Standard CMake option for building libraries shared or static by default. +OPTION(BUILD_SHARED_LIBS + "Build with shared libraries." + ${VTK_BUILD_SHARED_LIBS}) +# Copy the CMake option to a setting with VTKMY_ prefix for use in +# our project. This name is used in vtkmyConfigure.h.in. +SET(VTKMY_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) + +# If this is a build tree, provide an option for putting +# this project's executables and libraries in with VTK's. +IF (EXISTS ${VTK_DIR}/bin) + OPTION(USE_VTK_OUTPUT_PATHS + "Use VTK's output directory for this project's executables and libraries." + OFF) + MARK_AS_ADVANCED (USE_VTK_OUTPUT_PATHS) + IF (USE_VTK_OUTPUT_PATHS) + SET (LIBRARY_OUTPUT_PATH ${VTK_DIR}/bin) + SET (EXECUTABLE_OUTPUT_PATH ${VTK_DIR}/bin) + ENDIF (USE_VTK_OUTPUT_PATHS) +ENDIF (EXISTS ${VTK_DIR}/bin) + + +# +# Wrap Tcl, Java, Python +# +# Rational: even if your VTK was wrapped, it does not mean that you want to +# wrap your own local classes. +# Default value is OFF as the VTK cache might have set them to ON but +# the wrappers might not be present (or yet not found). +# + +# +# Tcl +# + +IF (VTK_WRAP_TCL) + + OPTION(VTKMY_WRAP_TCL + "Wrap classes into the TCL interpreted language." + ON) + + IF(VTKMY_WRAP_TCL) + SET(VTK_WRAP_TCL3_INIT_DIR "${VTKMY_SOURCE_DIR}/Wrapping") + INCLUDE(${VTK_CMAKE_DIR}/vtkWrapTcl.cmake) + ENDIF(VTKMY_WRAP_TCL) + +ELSE (VTK_WRAP_TCL) + + IF (VTKMY_WRAP_TCL) + MESSAGE("Warning. VTKMY_WRAP_TCL is ON but the VTK version you have " + "chosen has not support for Tcl (VTK_WRAP_TCL is OFF). " + "Please set VTKMY_WRAP_TCL to OFF.") + SET (VTKMY_WRAP_TCL OFF) + ENDIF (VTKMY_WRAP_TCL) + +ENDIF (VTK_WRAP_TCL) + +# +# Python +# + +IF (VTK_WRAP_PYTHON) + + OPTION(VTKMY_WRAP_PYTHON + "Wrap classes into the Python interpreted language." + ON) + + IF (VTKMY_WRAP_PYTHON) + SET(VTK_WRAP_PYTHON3_INIT_DIR "${VTKMY_SOURCE_DIR}/Wrapping") + INCLUDE(${VTK_CMAKE_DIR}/vtkWrapPython.cmake) + IF (WIN32) + IF (NOT BUILD_SHARED_LIBS) + MESSAGE(FATAL_ERROR "Python support requires BUILD_SHARED_LIBS to be ON.") + SET (VTKMY_CAN_BUILD 0) + ENDIF (NOT BUILD_SHARED_LIBS) + ENDIF (WIN32) + ENDIF (VTKMY_WRAP_PYTHON) + +ELSE (VTK_WRAP_PYTHON) + + IF (VTKMY_WRAP_PYTHON) + MESSAGE("Warning. VTKMY_WRAP_PYTHON is ON but the VTK version you have " + "chosen has not support for Python (VTK_WRAP_PYTHON is OFF). " + "Please set VTKMY_WRAP_PYTHON to OFF.") + SET (VTKMY_WRAP_PYTHON OFF) + ENDIF (VTKMY_WRAP_PYTHON) + +ENDIF (VTK_WRAP_PYTHON) + +# +# Java +# + +IF (VTK_WRAP_JAVA) + + OPTION(VTKMY_WRAP_JAVA + "Wrap classes into the Java interpreted language." + ON) + + IF (VTKMY_WRAP_JAVA) + SET(VTK_WRAP_JAVA3_INIT_DIR "${VTKMY_SOURCE_DIR}/Wrapping") + INCLUDE(${VTK_CMAKE_DIR}/vtkWrapJava.cmake) + IF (WIN32) + IF (NOT BUILD_SHARED_LIBS) + MESSAGE(FATAL_ERROR "Java support requires BUILD_SHARED_LIBS to be ON.") + SET (VTKMY_CAN_BUILD 0) + ENDIF (NOT BUILD_SHARED_LIBS) + ENDIF (WIN32) + + # Tell the java wrappers where to go. + SET(VTK_JAVA_HOME ${VTKMY_BINARY_DIR}/java/vtkmy) + MAKE_DIRECTORY(${VTK_JAVA_HOME}) + ENDIF (VTKMY_WRAP_JAVA) + +ELSE (VTK_WRAP_JAVA) + + IF (VTKMY_WRAP_JAVA) + MESSAGE("Warning. VTKMY_WRAP_JAVA is ON but the VTK version you have " + "chosen has not support for Java (VTK_WRAP_JAVA is OFF). " + "Please set VTKMY_WRAP_JAVA to OFF.") + SET (VTKMY_WRAP_JAVA OFF) + ENDIF (VTKMY_WRAP_JAVA) + +ENDIF (VTK_WRAP_JAVA) + +# Setup our local hints file in case wrappers need them. +SET(VTK_WRAP_HINTS ${VTKMY_SOURCE_DIR}/Wrapping/hints) diff --git a/Examples/Build/vtkMy/Common/CMakeLists.txt b/Examples/Build/vtkMy/Common/CMakeLists.txt new file mode 100644 index 0000000..9024a91 --- /dev/null +++ b/Examples/Build/vtkMy/Common/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# Source files +# +# Here is where you can add the name of your local common classes. +# + +SET (Common_SRCS + vtkBar.cxx +) + +# -------------------------------------------------------------------------- +# You probably do not need to modify anything below this line + +# Create the vtkmyCommon C++ library. +ADD_LIBRARY (vtkmyCommon ${Common_SRCS}) +TARGET_LINK_LIBRARIES (vtkmyCommon vtkCommon) + +# Create the vtkmyCommon Tcl library. +IF (VTK_WRAP_TCL AND VTKMY_WRAP_TCL) + VTK_WRAP_TCL3 (vtkmyCommonTCL CommonTCL_SRCS "${Common_SRCS}" "") + ADD_LIBRARY (vtkmyCommonTCL ${CommonTCL_SRCS}) + TARGET_LINK_LIBRARIES (vtkmyCommonTCL vtkmyCommon vtkCommonTCL) +ENDIF (VTK_WRAP_TCL AND VTKMY_WRAP_TCL) + +# Create the vtkmyCommon Python library. +IF (VTK_WRAP_PYTHON AND VTKMY_WRAP_PYTHON) + VTK_WRAP_PYTHON3 (vtkmyCommonPython CommonPython_SRCS "${Common_SRCS}") + ADD_LIBRARY (vtkmyCommonPythonD ${CommonPython_SRCS}) + ADD_LIBRARY (vtkmyCommonPython MODULE vtkmyCommonPythonInit.cxx) + TARGET_LINK_LIBRARIES(vtkmyCommonPythonD vtkmyCommon vtkCommon vtkCommonPythonD) + TARGET_LINK_LIBRARIES(vtkmyCommonPython vtkmyCommonPythonD) +ENDIF (VTK_WRAP_PYTHON AND VTKMY_WRAP_PYTHON) + +# Create the vtkmyCommon Java library. +IF (VTK_WRAP_JAVA AND VTKMY_WRAP_JAVA) + VTK_WRAP_JAVA3 (vtkmyCommonJava CommonJava_SRCS "${Common_SRCS}") + ADD_LIBRARY (vtkmyCommonJava SHARED ${CommonJava_SRCS}) + TARGET_LINK_LIBRARIES (vtkmyCommonJava vtkmyCommon vtkCommonJava) +ENDIF (VTK_WRAP_JAVA AND VTKMY_WRAP_JAVA) diff --git a/Examples/Build/vtkMy/Common/vtkBar.cxx b/Examples/Build/vtkMy/Common/vtkBar.cxx new file mode 100644 index 0000000..04d69a8 --- /dev/null +++ b/Examples/Build/vtkMy/Common/vtkBar.cxx @@ -0,0 +1,21 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBar.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBar.h" +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkBar, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkBar); diff --git a/Examples/Build/vtkMy/Common/vtkBar.h b/Examples/Build/vtkMy/Common/vtkBar.h new file mode 100644 index 0000000..271e607 --- /dev/null +++ b/Examples/Build/vtkMy/Common/vtkBar.h @@ -0,0 +1,39 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBar.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBar - Bar class for vtk +// .SECTION Description +// None. + +#ifndef __vtkBar_h +#define __vtkBar_h + +#include "vtkObject.h" +#include "vtkmyCommonWin32Header.h" + +class VTK_MY_COMMON_EXPORT vtkBar : public vtkObject +{ +public: + static vtkBar *New(); + vtkTypeRevisionMacro(vtkBar,vtkObject); + +protected: + vtkBar() {}; + ~vtkBar() {}; +private: + vtkBar(const vtkBar&); // Not implemented. + void operator=(const vtkBar&); // Not implemented. +}; + +#endif diff --git a/Examples/Build/vtkMy/Common/vtkmyCommonWin32Header.h b/Examples/Build/vtkMy/Common/vtkmyCommonWin32Header.h new file mode 100644 index 0000000..a5d1fd6 --- /dev/null +++ b/Examples/Build/vtkMy/Common/vtkmyCommonWin32Header.h @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkmyCommonWin32Header.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkmyCommonWin32Header - manage Windows system differences +// .SECTION Description +// The vtkmyCommonWin32Header captures some system differences between Unix +// and Windows operating systems. + +#ifndef __vtkmyCommonWin32Header_h +#define __vtkmyCommonWin32Header_h + +#include + +#if defined(WIN32) && !defined(VTKMY_STATIC) +#if defined(vtkmyCommon_EXPORTS) +#define VTK_MY_COMMON_EXPORT __declspec( dllexport ) +#else +#define VTK_MY_COMMON_EXPORT __declspec( dllimport ) +#endif +#else +#define VTK_MY_COMMON_EXPORT +#endif + +#endif diff --git a/Examples/Build/vtkMy/Examples/CMakeLists.txt b/Examples/Build/vtkMy/Examples/CMakeLists.txt new file mode 100644 index 0000000..d971ab2 --- /dev/null +++ b/Examples/Build/vtkMy/Examples/CMakeLists.txt @@ -0,0 +1 @@ +SUBDIRS(Cxx) diff --git a/Examples/Build/vtkMy/Examples/Cxx/CMakeLists.txt b/Examples/Build/vtkMy/Examples/Cxx/CMakeLists.txt new file mode 100644 index 0000000..ca46d07 --- /dev/null +++ b/Examples/Build/vtkMy/Examples/Cxx/CMakeLists.txt @@ -0,0 +1,7 @@ +SUBDIRS( + Ex1 +) + +IF(VTK_USE_RENDERING) + SUBDIRS(Ex2) +ENDIF(VTK_USE_RENDERING) diff --git a/Examples/Build/vtkMy/Examples/Cxx/Ex1/CMakeLists.txt b/Examples/Build/vtkMy/Examples/Cxx/Ex1/CMakeLists.txt new file mode 100644 index 0000000..e99606d --- /dev/null +++ b/Examples/Build/vtkMy/Examples/Cxx/Ex1/CMakeLists.txt @@ -0,0 +1,6 @@ +# +# Add the executable +# + +ADD_EXECUTABLE(vtkmyEx1 vtkmyEx1.cxx) +TARGET_LINK_LIBRARIES(vtkmyEx1 vtkmyUnsorted) diff --git a/Examples/Build/vtkMy/Examples/Cxx/Ex1/vtkmyEx1.cxx b/Examples/Build/vtkMy/Examples/Cxx/Ex1/vtkmyEx1.cxx new file mode 100644 index 0000000..3774d7d --- /dev/null +++ b/Examples/Build/vtkMy/Examples/Cxx/Ex1/vtkmyEx1.cxx @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkmyEx1.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example creates a couple of class instances and print them to +// the standard output. No rendering window is created. +// + +// +// First include the required header files for the vtk classes we are using +// +#include "vtkBar.h" +#include "vtkBar2.h" +#include "vtkImageFoo.h" + +int main() +{ + + // + // Next we create an instance of vtkBar + // + cout << "Create vtkBar object and print it." << endl; + + vtkBar *bar = vtkBar::New(); + bar->Print(cout); + + // + // Then we create an instance of vtkBar2 + // + cout << "Create vtkBar2 object and print it." << endl; + + vtkBar2 *bar2 = vtkBar2::New(); + bar2->Print(cout); + + // + // And we create an instance of vtkImageFoo + // + cout << "Create vtkImageFoo object and print it." << endl; + + vtkImageFoo *imagefoo = vtkImageFoo::New(); + imagefoo->Print(cout); + + cout << "Looks good ?" << endl; + + // + // Free up any objects we created + // + bar->Delete(); + bar2->Delete(); + imagefoo->Delete(); + + return 0; +} diff --git a/Examples/Build/vtkMy/Examples/Cxx/Ex2/CMakeLists.txt b/Examples/Build/vtkMy/Examples/Cxx/Ex2/CMakeLists.txt new file mode 100644 index 0000000..6b08d23 --- /dev/null +++ b/Examples/Build/vtkMy/Examples/Cxx/Ex2/CMakeLists.txt @@ -0,0 +1,6 @@ +# +# Add the executable +# + +ADD_EXECUTABLE(vtkmyEx2 vtkmyEx2.cxx) +TARGET_LINK_LIBRARIES(vtkmyEx2 vtkmyUnsorted) diff --git a/Examples/Build/vtkMy/Examples/Cxx/Ex2/vtkmyEx2.cxx b/Examples/Build/vtkMy/Examples/Cxx/Ex2/vtkmyEx2.cxx new file mode 100644 index 0000000..105fa34 --- /dev/null +++ b/Examples/Build/vtkMy/Examples/Cxx/Ex2/vtkmyEx2.cxx @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkmyEx2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example creates a polygonal model of a cone, and then rendered it to +// the screen. It willrotate the cone 360 degrees and then exit. The basic +// setup of source -> mapper -> actor -> renderer -> renderwindow is +// typical of most VTK programs. +// + +// +// First include the required header files for the vtk classes we are using +// +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" + +int main() +{ + // + // Next we create an instance of vtkConeSource and set some of its + // properties + // + vtkConeSource *cone = vtkConeSource::New(); + cone->SetHeight(3.0); + cone->SetRadius(1.0); + cone->SetResolution(10); + + // + // We create an instance of vtkPolyDataMapper to map the polygonal data + // into graphics primitives. We connect the output of the cone souece + // to the input of this mapper + // + vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New(); + coneMapper->SetInputConnection(cone->GetOutputPort()); + + // + // Create an actor to represent the cone. The actor coordinates rendering of + // the graphics primitives for a mapper. We set this actor's mapper to be + // coneMapper which we created above. + // + vtkActor *coneActor = vtkActor::New(); + coneActor->SetMapper(coneMapper); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the background + // color here + // + vtkRenderer *ren1= vtkRenderer::New(); + ren1->AddActor(coneActor); + ren1->SetBackground(0.1, 0.2, 0.4); + + // + // Finally we create the render window which will show up on the screen + // We put our renderer into the render window using AddRenderer. We also + // set the size to be 300 pixels by 300 + // + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + renWin->SetSize(300, 300); + + // + // Now we loop over 360 degreeees and render the cone each time + // + int i; + for (i = 0; i < 360; ++i) + { + // Render the image and rotate the active camera by one degree + renWin->Render(); + ren1->GetActiveCamera()->Azimuth(1); + } + + // + // Free up any objects we created + // + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); + ren1->Delete(); + renWin->Delete(); + + return 0; +} diff --git a/Examples/Build/vtkMy/Examples/Tcl/vtkmyEx1.Tcl b/Examples/Build/vtkMy/Examples/Tcl/vtkmyEx1.Tcl new file mode 100644 index 0000000..11a761d --- /dev/null +++ b/Examples/Build/vtkMy/Examples/Tcl/vtkmyEx1.Tcl @@ -0,0 +1,54 @@ +# +# This example creates a couple of class instances and print them to +# the standard output. No rendering window is created. +# + +# +# Do not forget to add the path to the Wrapping/Tcl directory to your +# TCLLIBPATH environment variable. Use forward slash / instead of \ +# and quote (") path containing spaces. +# Also check that the path to your DLL (i.e. your build dir) is also +# in your PATH environment variable. +# + +# +# First we include the Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtkmy + +# +# Next we create an instance of vtkBar +# +puts "Create vtkBar object and print it." + +vtkBar bar +puts [bar Print] + +# +# Then we create an instance of vtkBar2 +# +puts "Create vtkBar2 object and print it." + +vtkBar2 bar2 +puts [bar2 Print] + +# +# And we create an instance of vtkImageFoo +# +puts "Create vtkImageFoo object and print it." + +vtkImageFoo imagefoo +puts [imagefoo Print] + +puts "Looks good ?" + +# +# Free up any objects we created +# +vtkCommand DeleteAllObjects + +# +# Exit the application +# +exit diff --git a/Examples/Build/vtkMy/Examples/Tcl/vtkmyEx2.tcl b/Examples/Build/vtkMy/Examples/Tcl/vtkmyEx2.tcl new file mode 100644 index 0000000..001567c --- /dev/null +++ b/Examples/Build/vtkMy/Examples/Tcl/vtkmyEx2.tcl @@ -0,0 +1,85 @@ +# +# This example creates a polygonal model of a cone, and then rendered it to +# the screen. It willrotate the cone 360 degrees and then exit. The basic +# setup of source -> mapper -> actor -> renderer -> renderwindow is +# typical of most VTK programs. +# + +# +# Do not forget to add the path to the Wrapping/Tcl directory to your +# TCLLIBPATH environment variable. Use forward slash / instead of \ +# and quote (") path containing spaces. +# Also check that the path to your DLL (i.e. your build dir) is also +# in your PATH environment variable. +# + +# +# First we include the Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtkmy + +# +# Next we create an instance of vtkConeSource and set some of its +# properties +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +# +# We create an instance of vtkPolyDataMapper to map the polygonal data +# into graphics primitives. We connect the output of the cone souece +# to the input of this mapper +# +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] + +# +# Create an actor to represent the cone. The actor coordinates rendering of +# the graphics primitives for a mapper. We set this actor's mapper to be +# coneMapper which we created above. +# +vtkActor coneActor +coneActor SetMapper coneMapper + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here +# +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300 +# +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +# +# Now we loop over 360 degreeees and render the cone each time +# +for {set i 0} {$i < 360} {incr i} { + # Render the image and rotate the active camera by one degree + renWin Render + [ren1 GetActiveCamera] Azimuth 1 +} + +# +# Free up any objects we created +# +vtkCommand DeleteAllObjects + +# +# Exit the application +# +exit + + + diff --git a/Examples/Build/vtkMy/Imaging/CMakeLists.txt b/Examples/Build/vtkMy/Imaging/CMakeLists.txt new file mode 100644 index 0000000..1db72df --- /dev/null +++ b/Examples/Build/vtkMy/Imaging/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# Source files +# +# Here is where you can add the name of your local imaging classes. +# + +SET (Imaging_SRCS + vtkImageFoo.cxx +) + +# -------------------------------------------------------------------------- +# You probably do not need to modify anything below this line + +# Create the vtkmyImaging C++ library +ADD_LIBRARY (vtkmyImaging ${Imaging_SRCS}) +TARGET_LINK_LIBRARIES(vtkmyImaging vtkmyCommon vtkImaging) + +# Create the vtkmyImaging Tcl library +IF (VTK_WRAP_TCL AND VTKMY_WRAP_TCL) + VTK_WRAP_TCL3 (vtkmyImagingTCL ImagingTCL_SRCS "${Imaging_SRCS}" "") + ADD_LIBRARY (vtkmyImagingTCL ${ImagingTCL_SRCS}) + TARGET_LINK_LIBRARIES (vtkmyImagingTCL vtkmyCommonTCL vtkmyImaging vtkImagingTCL) +ENDIF (VTK_WRAP_TCL AND VTKMY_WRAP_TCL) + +# Create the vtkmyImaging Python library. +IF (VTK_WRAP_PYTHON AND VTKMY_WRAP_PYTHON) + VTK_WRAP_PYTHON3 (vtkmyImagingPython ImagingPython_SRCS "${Imaging_SRCS}") + ADD_LIBRARY (vtkmyImagingPythonD ${ImagingPython_SRCS}) + ADD_LIBRARY (vtkmyImagingPython MODULE vtkmyImagingPythonInit.cxx) + TARGET_LINK_LIBRARIES(vtkmyImagingPythonD vtkmyImaging vtkmyCommonPythonD vtkImaging vtkImagingPythonD) + TARGET_LINK_LIBRARIES(vtkmyImagingPython vtkmyImagingPythonD) +ENDIF (VTK_WRAP_PYTHON AND VTKMY_WRAP_PYTHON) + +# Create the vtkmyImaging Java library. +IF (VTK_WRAP_JAVA AND VTKMY_WRAP_JAVA) + VTK_WRAP_JAVA3 (vtkmyImagingJava ImagingJava_SRCS "${Imaging_SRCS}") + ADD_LIBRARY (vtkmyImagingJava SHARED ${ImagingJava_SRCS}) + TARGET_LINK_LIBRARIES (vtkmyImagingJava vtkmyCommonJava vtkmyImaging vtkImagingJava) +ENDIF (VTK_WRAP_JAVA AND VTKMY_WRAP_JAVA) diff --git a/Examples/Build/vtkMy/Imaging/vtkImageFoo.cxx b/Examples/Build/vtkMy/Imaging/vtkImageFoo.cxx new file mode 100644 index 0000000..6c4c78f --- /dev/null +++ b/Examples/Build/vtkMy/Imaging/vtkImageFoo.cxx @@ -0,0 +1,180 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFoo.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageFoo.h" + +#include "vtkBar.h" +#include "vtkImageData.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkImageFoo, "$Revision: 1.10.2.1 $"); +vtkStandardNewMacro(vtkImageFoo); + +//---------------------------------------------------------------------------- +vtkImageFoo::vtkImageFoo() +{ + this->Foo = 0.0; + this->OutputScalarType = -1; + this->Bar = vtkBar::New(); +} + +//---------------------------------------------------------------------------- +vtkImageFoo::~vtkImageFoo() +{ + if (this->Bar) + { + this->Bar->Delete(); + this->Bar = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageFoo::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Foo: " << this->Foo << "\n"; + os << indent << "Output Scalar Type: " << this->OutputScalarType << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkImageFoo::RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + // Set the scalar type we will produce in the output information for + // the first output port. + if(this->OutputScalarType != -1) + { + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo( + outInfo, this->OutputScalarType, -1); + } + return 1; +} + +//---------------------------------------------------------------------------- +// This function template implements the filter for any combination of +// input and output data type. +template +void vtkImageFooExecute(vtkImageFoo* self, + vtkImageData* inData, IT* inPtr, + vtkImageData* outData, OT* outPtr, + int outExt[6], int id) +{ + float foo = self->GetFoo(); + + int idxR, idxY, idxZ; + int maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int rowLength; + + unsigned long count = 0; + unsigned long target; + + // find the region to loop over + + rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents(); + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // Loop through ouput pixels + + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + for (idxR = 0; idxR < rowLength; idxR++) + { + // Pixel operation. Add foo. Dumber would be impossible. + *outPtr = (OT)((float)(*inPtr) + foo); + outPtr++; + inPtr++; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + +//---------------------------------------------------------------------------- +// This function template is instantiated for each input data type and +// forwards the call to the above function template for each output +// data type. +template +void vtkImageFooExecute1(vtkImageFoo* self, + vtkImageData* inData, T* inPtr, + vtkImageData* outData, + int outExt[6], int id) +{ + void *outPtr = outData->GetScalarPointerForExtent(outExt); + int outType = outData->GetScalarType(); + switch (outType) + { + vtkTemplateMacro( + vtkImageFooExecute(self, + inData, inPtr, + outData, static_cast(outPtr), + outExt, id) + ); + default: + vtkErrorWithObjectMacro(self, "Unknown output scalar type " << outType); + return; + } +} + +//---------------------------------------------------------------------------- +// This method is passed an input and output data, and executes the +// filter algorithm to fill the output from the input. It just +// executes a switch statement to call the correct function for the +// datas data types. +void vtkImageFoo::ThreadedRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*, + vtkImageData*** inData, + vtkImageData** outData, + int outExt[6], int id) +{ + void* inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); + int inType = inData[0][0]->GetScalarType(); + switch (inType) + { + vtkTemplateMacro( + vtkImageFooExecute1(this, inData[0][0], static_cast(inPtr), + outData[0], outExt, id) + ); + default: + vtkErrorMacro("Unknown input scalar type " << inType); + return; + } +} diff --git a/Examples/Build/vtkMy/Imaging/vtkImageFoo.h b/Examples/Build/vtkMy/Imaging/vtkImageFoo.h new file mode 100644 index 0000000..a338479 --- /dev/null +++ b/Examples/Build/vtkMy/Imaging/vtkImageFoo.h @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFoo.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageFoo - foo and scale an input image +// .SECTION Description +// With vtkImageFoo Pixels are foo'ed. + +#ifndef __vtkImageFoo_h +#define __vtkImageFoo_h + +#include "vtkThreadedImageAlgorithm.h" +#include "vtkmyImagingWin32Header.h" + +class vtkBar; + +class VTK_MY_IMAGING_EXPORT vtkImageFoo : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageFoo *New(); + vtkTypeRevisionMacro(vtkImageFoo,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the foo value. + vtkSetMacro(Foo,float); + vtkGetMacro(Foo,float); + + // Description: + // Set the desired output scalar type. + vtkSetMacro(OutputScalarType, int); + vtkGetMacro(OutputScalarType, int); + void SetOutputScalarTypeToDouble() + {this->SetOutputScalarType(VTK_DOUBLE);} + void SetOutputScalarTypeToFloat() + {this->SetOutputScalarType(VTK_FLOAT);} + void SetOutputScalarTypeToLong() + {this->SetOutputScalarType(VTK_LONG);} + void SetOutputScalarTypeToUnsignedLong() + {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; + void SetOutputScalarTypeToInt() + {this->SetOutputScalarType(VTK_INT);} + void SetOutputScalarTypeToUnsignedInt() + {this->SetOutputScalarType(VTK_UNSIGNED_INT);} + void SetOutputScalarTypeToShort() + {this->SetOutputScalarType(VTK_SHORT);} + void SetOutputScalarTypeToUnsignedShort() + {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);} + void SetOutputScalarTypeToChar() + {this->SetOutputScalarType(VTK_CHAR);} + void SetOutputScalarTypeToSignedChar() + {this->SetOutputScalarType(VTK_SIGNED_CHAR);} + void SetOutputScalarTypeToUnsignedChar() + {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);} + +protected: + vtkImageFoo(); + ~vtkImageFoo(); + + float Foo; + int OutputScalarType; + vtkBar* Bar; + + virtual int RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector); + void ThreadedRequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData*** inData, vtkImageData** outData, + int outExt[6], int id); +private: + vtkImageFoo(const vtkImageFoo&); // Not implemented. + void operator=(const vtkImageFoo&); // Not implemented. +}; + +#endif diff --git a/Examples/Build/vtkMy/Imaging/vtkmyImagingWin32Header.h b/Examples/Build/vtkMy/Imaging/vtkmyImagingWin32Header.h new file mode 100644 index 0000000..888778a --- /dev/null +++ b/Examples/Build/vtkMy/Imaging/vtkmyImagingWin32Header.h @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkmyImagingWin32Header.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkmyImagingWin32Header - manage Windows system differences +// .SECTION Description +// The vtkmyImagingWin32Header captures some system differences between Unix +// and Windows operating systems. + +#ifndef __vtkmyImagingWin32Header_h +#define __vtkmyImagingWin32Header_h + +#include + +#if defined(WIN32) && !defined(VTKMY_STATIC) +#if defined(vtkmyImaging_EXPORTS) +#define VTK_MY_IMAGING_EXPORT __declspec( dllexport ) +#else +#define VTK_MY_IMAGING_EXPORT __declspec( dllimport ) +#endif +#else +#define VTK_MY_IMAGING_EXPORT +#endif + +#endif diff --git a/Examples/Build/vtkMy/README b/Examples/Build/vtkMy/README new file mode 100644 index 0000000..8d1665c --- /dev/null +++ b/Examples/Build/vtkMy/README @@ -0,0 +1,75 @@ +Introduction: +------------- + +This directory demonstrates how to organize a local source repository +where local VTK classes can be compiled and wrapped into +C++/Tcl/Java/Python libraries without interferring with the main VTK +source dir. + +It might be good thing to sort local classes into different 'package' +directories like VTK does (Common, Rendering, Filtering, Imaging, IO, +etc.). It prevents numerous dependencies problems and provides a +better overview of the class hierarchy. + + - this example enforces this 'package' organization by referring to a + vtkBar class into the Common/ directory and a vtkImageFoo class into + the Imaging/ directory (the later uses an instance of vtkBar to + "work", thus demonstrating how CMake resolves dependencies between + both directories). + +Nevertheless, if you do not care about this ordering, you might just +put your classes into the Unsorted/ directory, like the vtkBar2 class +for example. By default, members of the Unsorted package will depend +on all other packages and will be linked against all VTK packages too. + +What you should do: +------------------- + +- Copy this vtkMy directory to a different out-of-source place, and + remove all CVS subdirs to avoid any accidental commit to the main VTK + CVS. + +- Fill the subdirs with your own classes. Remove the dummy classes if + needed. For each CMakeList.txt in the package dirs, add or remove the + class(es) pertaining to this directory (SET command). Depending on + the directory, your class must #include "vtkmy*Win32Header.h" + (see dummy classes for example) and use the corresponding VTK_MY_*_EXPORT + macro after the 'class' keyword to ensure proper DLL build. + +- Run CMake as usual. Use your vtkMy local dir as source dir, and + choose whatever build directory. Your VTK build- or install- directory + should be found automatically. + +- Build your project. + +- Add the path to your build-dir bin/ directory to your PATH + environment variable (as well as LD_LIBRARY_PATH for Unix users), so + these C++ and Tcl DLL can be found (if any). + +- Add the path to your vtkMy/Wrapping/Tcl directory to your TCLLIBPATH + environment variable. TCLLIBPATH is a space separated set of paths to + Tcl libraries. Windows users should use forward slashes (/) instead of + the usual backward slashes (\), and should surround the path by quotes + (") if it contains any space. + +Distribute or exchange your modules: +------------------------------------ + +Ideally, if you plan to exchange or distribute your modules then you +should rename the vtkmy lib prefix to something more personal or +unique. You might use your initials for example. In a nutshell, if you +were to choose vtksb, then you should take care of the following: + + - Search for the vtkmy string and replace it with vtksb in all files. + - In the same way, replace VTKMY by VTKSB. + - Rename all vtkmy* files *and* directories to vtksb* (this should + only concern files like vtkmy*Win32Header.h for example). + - In all *Win32Header.h files and VTK headers, change + VTK_MY_*_EXPORT to VTK_SB_*_EXPORT. Sorry for the inconvenience, but + the wrappers expect this symbol to start with VTK_, thus + VTKMY_*_EXPORT could not be used. + +Any prefix should work, but make sure that your class names start with +'vtk', otherwise the wrappers will fail (hence the vtksb or vtkmy +prefix, not sbvtk or myvtk). A safe bet is to use something starting +'vtk' in a consistent way. diff --git a/Examples/Build/vtkMy/Unsorted/CMakeLists.txt b/Examples/Build/vtkMy/Unsorted/CMakeLists.txt new file mode 100644 index 0000000..dff23e5 --- /dev/null +++ b/Examples/Build/vtkMy/Unsorted/CMakeLists.txt @@ -0,0 +1,50 @@ +# +# Source files +# +# Here is where you can add the name of your local unsorted classes. +# + +SET (Unsorted_SRCS + vtkBar2.cxx +) + +# -------------------------------------------------------------------------- +# You probably do not need to modify anything below this line + +# Create the vtkmyUnsorted C++ library. +ADD_LIBRARY (vtkmyUnsorted ${Unsorted_SRCS}) +TARGET_LINK_LIBRARIES(vtkmyUnsorted vtkmyImaging vtkGraphics vtkIO) + +IF (VTK_USE_PARALLEL) + TARGET_LINK_LIBRARIES (vtkmyUnsorted vtkParallel) +ENDIF (VTK_USE_PARALLEL) + +IF (VTK_USE_RENDERING) + TARGET_LINK_LIBRARIES (vtkmyUnsorted vtkRendering) + TARGET_LINK_LIBRARIES (vtkmyUnsorted vtkVolumeRendering) + TARGET_LINK_LIBRARIES (vtkmyUnsorted vtkHybrid) + TARGET_LINK_LIBRARIES (vtkmyUnsorted vtkWidgets) +ENDIF (VTK_USE_RENDERING) + +# Create the vtkmyUnsorted Tcl library. +IF (VTK_WRAP_TCL AND VTKMY_WRAP_TCL) + VTK_WRAP_TCL3 (vtkmyUnsortedTCL UnsortedTCL_SRCS "${Unsorted_SRCS}" "") + ADD_LIBRARY (vtkmyUnsortedTCL ${UnsortedTCL_SRCS}) + TARGET_LINK_LIBRARIES (vtkmyUnsortedTCL vtkmyCommonTCL vtkmyUnsorted) +ENDIF (VTK_WRAP_TCL AND VTKMY_WRAP_TCL) + +# Create the vtkmyUnsorted Python library. +IF (VTK_WRAP_PYTHON AND VTKMY_WRAP_PYTHON) + VTK_WRAP_PYTHON3 (vtkmyUnsortedPython UnsortedPython_SRCS "${Unsorted_SRCS}") + ADD_LIBRARY (vtkmyUnsortedPythonD ${UnsortedPython_SRCS}) + ADD_LIBRARY (vtkmyUnsortedPython MODULE vtkmyUnsortedPythonInit.cxx) + TARGET_LINK_LIBRARIES(vtkmyUnsortedPythonD vtkmyUnsorted vtkmyCommonPythonD) + TARGET_LINK_LIBRARIES(vtkmyUnsortedPython vtkmyUnsortedPythonD) +ENDIF (VTK_WRAP_PYTHON AND VTKMY_WRAP_PYTHON) + +# Create the vtkmyUnsorted Java library. +IF (VTK_WRAP_JAVA AND VTKMY_WRAP_JAVA) + VTK_WRAP_JAVA3 (vtkmyUnsortedJava UnsortedJava_SRCS "${Unsorted_SRCS}") + ADD_LIBRARY (vtkmyUnsortedJava SHARED ${UnsortedJava_SRCS}) + TARGET_LINK_LIBRARIES(vtkmyUnsortedJava vtkmyCommonJava vtkmyUnsorted) +ENDIF (VTK_WRAP_JAVA AND VTKMY_WRAP_JAVA) diff --git a/Examples/Build/vtkMy/Unsorted/vtkBar2.cxx b/Examples/Build/vtkMy/Unsorted/vtkBar2.cxx new file mode 100644 index 0000000..89ab9a9 --- /dev/null +++ b/Examples/Build/vtkMy/Unsorted/vtkBar2.cxx @@ -0,0 +1,21 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBar2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBar2.h" +#include "vtkObjectFactory.h" + +//---------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkBar2, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkBar2); diff --git a/Examples/Build/vtkMy/Unsorted/vtkBar2.h b/Examples/Build/vtkMy/Unsorted/vtkBar2.h new file mode 100644 index 0000000..eb3f674 --- /dev/null +++ b/Examples/Build/vtkMy/Unsorted/vtkBar2.h @@ -0,0 +1,39 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBar2.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBar2 - Bar2 class for vtk +// .SECTION Description +// None. + +#ifndef __vtkBar2_h +#define __vtkBar2_h + +#include "vtkObject.h" +#include "vtkmyUnsortedWin32Header.h" + +class VTK_MY_UNSORTED_EXPORT vtkBar2 : public vtkObject +{ +public: + static vtkBar2 *New(); + vtkTypeRevisionMacro(vtkBar2,vtkObject); + +protected: + vtkBar2() {}; + ~vtkBar2() {}; +private: + vtkBar2(const vtkBar2&); // Not implemented. + void operator=(const vtkBar2&); // Not implemented. +}; + +#endif diff --git a/Examples/Build/vtkMy/Unsorted/vtkmyUnsortedWin32Header.h b/Examples/Build/vtkMy/Unsorted/vtkmyUnsortedWin32Header.h new file mode 100644 index 0000000..27367ca --- /dev/null +++ b/Examples/Build/vtkMy/Unsorted/vtkmyUnsortedWin32Header.h @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkmyUnsortedWin32Header.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkmyUnsortedWin32Header - manage Windows system differences +// .SECTION Description +// The vtkmyUnsortedWin32Header captures some system differences between Unix +// and Windows operating systems. + +#ifndef __vtkmyUnsortedWin32Header_h +#define __vtkmyUnsortedWin32Header_h + +#include + +#if defined(WIN32) && !defined(VTKMY_STATIC) +#if defined(vtkmyUnsorted_EXPORTS) +#define VTK_MY_UNSORTED_EXPORT __declspec( dllexport ) +#else +#define VTK_MY_UNSORTED_EXPORT __declspec( dllimport ) +#endif +#else +#define VTK_MY_UNSORTED_EXPORT +#endif + +#endif diff --git a/Examples/Build/vtkMy/Utilities/CMakeLists.txt b/Examples/Build/vtkMy/Utilities/CMakeLists.txt new file mode 100644 index 0000000..bce5c54 --- /dev/null +++ b/Examples/Build/vtkMy/Utilities/CMakeLists.txt @@ -0,0 +1 @@ +SUBDIRS(Doxygen) diff --git a/Examples/Build/vtkMy/Utilities/Doxygen/CMakeLists.txt b/Examples/Build/vtkMy/Utilities/Doxygen/CMakeLists.txt new file mode 100644 index 0000000..bafa60b --- /dev/null +++ b/Examples/Build/vtkMy/Utilities/Doxygen/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# Build the documentation +# + +INCLUDE (${CMAKE_ROOT}/Modules/Documentation.cmake OPTIONAL) + +IF (BUILD_DOCUMENTATION) + OPTION (DOCUMENTATION_DOWNLOAD_VTK_TAGFILE + "Download the VTK tag file." ON) + MARK_AS_ADVANCED ( + DOCUMENTATION_DOWNLOAD_VTK_TAGFILE + ) + + # + # Configure the script and the doxyfile, then add target + # + IF(NOT DOT_PATH) + GET_FILENAME_COMPONENT(DOT_PATH ${DOT} PATH) + ENDIF(NOT DOT_PATH) + + CONFIGURE_FILE( + ${VTKMY_SOURCE_DIR}/Utilities/Doxygen/doxyfile.in + ${VTKMY_BINARY_DIR}/Utilities/Doxygen/doxyfile) + + CONFIGURE_FILE( + ${VTKMY_SOURCE_DIR}/Utilities/Doxygen/doc_makeall.sh.in + ${VTKMY_BINARY_DIR}/Utilities/Doxygen/doc_makeall.sh) + + ADD_CUSTOM_TARGET(vtkMyDoxygenDoc + ${BASH} + ${VTKMY_BINARY_DIR}/Utilities/Doxygen/doc_makeall.sh) + +ENDIF (BUILD_DOCUMENTATION) diff --git a/Examples/Build/vtkMy/Utilities/Doxygen/doc_makeall.sh.in b/Examples/Build/vtkMy/Utilities/Doxygen/doc_makeall.sh.in new file mode 100644 index 0000000..45207fb --- /dev/null +++ b/Examples/Build/vtkMy/Utilities/Doxygen/doc_makeall.sh.in @@ -0,0 +1,291 @@ +# ------------------------------------------------------------------------- +# Doxygen documentation batch +# modified by S. Barre (Time-stamp: <2003-01-16 14:04:41 barre> +# ------------------------------------------------------------------------- + +# Path to several tools (_PROG to avoid the typical GZIP env var pb) +# Example: +# DOXYGEN_PROG=@DOXYGEN@ (INCLUDE(FindDoxygen.cmake)) +# GZIP_PROG=@GZIP@ (INCLUDE(FindCygwin.cmake)) +# HHC_PROG=@HTML_HELP_COMPILER@ (INCLUDE(FindHTMLHelp.cmake)) +# MV_PROG=@MV@ (INCLUDE(FindCygwin.cmake)) +# PERL_PROG=@PERL@ (INCLUDE(FindPerl.cmake)) +# RM_PROG=@RM@ (INCLUDE(FindCygwin.cmake)) +# TAR_PROG=@TAR@ (INCLUDE(FindCygwin.cmake)) +# WGET_PROG=@WGET@ (INCLUDE(FindWget.cmake)) +# +export DOXYGEN_PROG="@DOXYGEN@" # Doxygen +export GZIP_PROG="@GZIP@" # gzip (Unix-like 'gzip compressor') +export GNUPLOT_PROG="@GNUPLOT@" # gnuplot (data plotting program) +export HHC_PROG="@HTML_HELP_COMPILER@" # HTML Help Compiler +export MV_PROG="@MV@" # mv (Unix-like 'move/rename files') +export PERL_PROG="@PERL@" # Perl +export RM_PROG="@RM@" # rm (Unix-like 'remove files') +export TAR_PROG="@TAR@" # tar (Unix-like 'archiver') +export WGET_PROG="@WGET@" # wget (remote file retrieval) + +# PROJECT_NAME: +# Documentation/project name. Used in some of the resulting file names and +# xrefs to uniquify two or more projects linked together through their +# Doxygen's tag files. Mandatory for each documentation set. +# Note: might be the same as the doxyfile's PROJECT_NAME +# Example: +# PROJECT_NAME=VTK +# +export PROJECT_NAME=vtkMy + +# PATH_TO_VTK_DOX_SCRIPTS: +# Path to the directory holding the Perl scripts used to produce the VTK doc +# in Doxygen format. You need the VTK source files or a local copy of +# these scripts. +# Example: +# PATH_TO_VTK_DOX_SCRIPTS=@VTK_SOURCE_DIR@/Utilities/Doxygen +# +export PATH_TO_VTK_DOX_SCRIPTS="@VTK_SOURCE_DIR@/Utilities/Doxygen" + +# SOURCE_DIR: +# Source directory. The top directory of the source files. +# Example: +# SOURCE_DIR=@VTKMY_SOURCE_DIR@ +# +export SOURCE_DIR="@VTKMY_SOURCE_DIR@" + +# REL_PATH_TO_TOP: +# Relative path from the top directory of the source files to the directory +# (or top directory) holding the files to document. Useful if several parts +# of the same source directory should be documented separately. +# Example: +# REL_PATH_TO_TOP=. +# REL_PATH_TO_TOP=framework/src +# +export REL_PATH_TO_TOP=. + +# INTERMEDIATE_DOX_DIR: +# Directory where the intermediate Doxygen files should be stored (mainly +# these headers files converted from the VTK format to the Doxygen format). +# This directory is erased at the end of this script, unless you comment +# the corresponding line. +# DOXTEMP might be used to simplify the syntax. +# Example: +# DOXTEMP=DOXTEMP=@VTKMY_BINARY_DIR@/Utilities/Doxygen +# INTERMEDIATE_DOX_DIR=$DOXTEMP/dox +# +export DOXTEMP="@VTKMY_BINARY_DIR@/Utilities/Doxygen" +export INTERMEDIATE_DOX_DIR="$DOXTEMP/dox" + +# CVSWEB_CHECKOUT, CVSWEB_CHECKOUT_SUFFIX: +# URL to the CVSWeb of the project, in checkout mode (i.e. appending a file +# name to this URL will retrieve the contents of the file). In the same way +# CVSWEB_CHECKOUT_SUFFIX is appended to the result. +# Example: +# CVSWEB_CHECKOUT=http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/VTK +# CVSWEB_CHECKOUT_SUFFIX=?cvsroot=CMake +# +export CVSWEB_CHECKOUT="http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/VTK/" +export CVSWEB_CHECKOUT_SUFFIX="?cvsroot=VTK" + +# DATA_ROOT: +# Data directory. The root directory of the data files. +# Example: +# DATA_ROOT=@VTK_DATA_ROOT@ +# +#export DATA_ROOT="@VTK_DATA_ROOT@" + +# DOXYFILE: +# Path to the Doxygen configuration file (i.e. doxyfile). +# Example: +# DOXYFILE=$DOXTEMP/doxyfile +# +export DOXYFILE="$DOXTEMP/doxyfile" + +# OUTPUT_DIRECTORY ALLOW_ERASE_OUTPUT_DIRECTORY: +# Path to the Doxygen output directory (where the resulting doc is stored). +# Note: should be the same as your doxyfile's OUTPUT_DIRECTORY +# If ON, allows the output directory to be erased when some advanced output +# file have been produced (HTML Help, or TAR archive for example). +# Example: +# OUTPUT_DIRECTORY=$DOXTEMP/doc +# ALLOW_ERASE_OUTPUT_DIRECTORY=ON +# +export OUTPUT_DIRECTORY="$DOXTEMP/doc" +export ALLOW_ERASE_OUTPUT_DIRECTORY=ON + +# COMPILE_HTML_HELP RESULTING_HTML_HELP_FILE: +# Compile the CHM (Compressed HTML) HTML Help file, name of the resulting +# file. If set to ON and name is non-empty these options will actually +# trigger the HTML-Help compiler to create the CHM. The resulting +# file (usually index.chm) will be renamed to this name. +# Note: if ON, the whole $OUTPUT_DIRECTORY will be erased at the end of +# this script, since this file is considered to be one of the +# advanced final output, unless ALLOW_ERASE_OUTPUT_DIRECTORY is OFF +# Note: your doxyfile should be configured to enable HTML Help creation +# (using GENERATE_HTML = YES, GENERATE_HTMLHELP = YES) +# Example: +# COMPILE_HTML_HELP=ON +# COMPILE_HTML_HELP=@DOCUMENTATION_HTML_HELP@ +# RESULTING_HTML_HELP_FILE=$DOXTEMP/vtk4.chm +# +export COMPILE_HTML_HELP=@DOCUMENTATION_HTML_HELP@ +export RESULTING_HTML_HELP_FILE="$DOXTEMP/$PROJECT_NAME.chm" + +# CREATE_HTML_TARZ_ARCHIVE RESULTING_HTML_TARZ_ARCHIVE_FILE: +# Create a compressed (gzip) tar archive of the html directory (located +# under the OUTPUT_DIRECTORY), and name of the resulting archive file. +# Note: your doxyfile should be configured to enable HTML creation +# (using GENERATE_HTML = YES) +# Example: +# CREATE_HTML_TARZ_ARCHIVE=ON +# CREATE_HTML_TARZ_ARCHIVE=@DOCUMENTATION_HTML_TARZ@ +# RESULTING_HTML_TARZ_ARCHIVE_FILE=$DOXTEMP/vtk4-html.tar.gz +# +export CREATE_HTML_TARZ_ARCHIVE=@DOCUMENTATION_HTML_TARZ@ +export RESULTING_HTML_TARZ_ARCHIVE_FILE="$DOXTEMP/$PROJECT_NAME-html.tar.gz" + +# DOWNLOAD_VTK_TAGFILE VTK_TAGFILE VTK_TAGFILE_REMOTE_DIR VTK_TAGFILE_DEST_DIR: +# Download the VTK tag file, name, remote location and destination dir of this +# tag file. If set to ON, the tag file is retrieved from its remote location +# using wget and stored in the destination dir. +# The tag file is expected to be compressed using gzip, but DO NOT include +# the .gz extension in VTK_TAGFILE. +# Note: your doxyfile must be tailored to make use-of or create this tag file. +# (using TAGFILES = vtk4-nightly.tag=http://www.vtk.org/doc/nightly/html +# or GENERATE_TAGFILE = "@FOO_BINARY_DIR@/Utilities/Doxygen/vtk4.tag") +# Example: +# DOWNLOAD_VTK_TAGFILE=OFF +# VTK_TAGFILE=vtk4-nightly.tag +# VTK_TAGFILE_REMOTE_DIR=http://www.vtk.org/doc/nightly/html +# VTK_TAGFILE_DEST_DIR=$DOXTEMP +# +export DOWNLOAD_VTK_TAGFILE=@DOCUMENTATION_DOWNLOAD_VTK_TAGFILE@ +export VTK_TAGFILE=vtkNightlyDoc.tag +export VTK_TAGFILE_REMOTE_DIR="http://www.vtk.org/files/nightly" +export VTK_TAGFILE_DEST_DIR="$DOXTEMP" + +# ---------------------------------------------------------------------------- +# Convert the VTKMY headers to the Doxygen format. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + $PERL_PROG "$PATH_TO_VTK_DOX_SCRIPTS/doc_header2doxygen.pl" \ + --to "$INTERMEDIATE_DOX_DIR" \ + --relativeto "$SOURCE_DIR/$REL_PATH_TO_TOP" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Common" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Imaging" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Unsorted" +fi + +# ---------------------------------------------------------------------------- +# Build the full-text index. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + $PERL_PROG "$PATH_TO_VTK_DOX_SCRIPTS/doc_index.pl" \ + --project "$PROJECT_NAME" \ + --stop "$PATH_TO_VTK_DOX_SCRIPTS/doc_index.stop" \ + --store "doc_""$PROJECT_NAME""_index.dox" \ + --to "$INTERMEDIATE_DOX_DIR" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Common" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Imaging" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Unsorted" +fi + +# ---------------------------------------------------------------------------- +# Retrieve the (gziped) VTK 4 tag file and decompress it + +if test "x$DOWNLOAD_VTK_TAGFILE" == "xON" ; then + if test "x$VTK_TAGFILE" != "x" ; then + if test "x$WGET_PROG" != "xNOTFOUND" ; then + $WGET_PROG -nd -nH \ + "$VTK_TAGFILE_REMOTE_DIR/$VTK_TAGFILE.gz" \ + -O "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE.gz" + if test "x$GZIP_PROG" != "xNOTFOUND" ; then + $GZIP_PROG -d "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE.gz" + fi + fi + fi +fi + +# ---------------------------------------------------------------------------- +# Create the Doxygen doc. + +if test "x$DOXYGEN_PROG" != "xNOTFOUND" ; then + + if test "x$RM_PROG" != "xNOTFOUND" ; then + $RM_PROG -fr "$OUTPUT_DIRECTORY" + fi + + $DOXYGEN_PROG "$DOXYFILE" +fi + +# ---------------------------------------------------------------------------- +# Clean the HTML pages to remove the path to the intermediate Doxygen dir. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + $PERL_PROG "$PATH_TO_VTK_DOX_SCRIPTS/doc_rmpath.pl" \ + --to "$INTERMEDIATE_DOX_DIR" \ + --html "$OUTPUT_DIRECTORY/html" +fi + +# ---------------------------------------------------------------------------- +# clean the HTML pages to remove layout pbs +# +#if test "x$PERL_PROG" != "xNOTFOUND" ; then +# $PERL_PROG $PATH_TO_VTK_DOX_SCRIPTS/doc_cleanhtml.pl \ +# --html "$OUTPUT_DIRECTORY/html" +#fi + +# ---------------------------------------------------------------------------- +# Create the CHM HTML HELP doc. + +if test "x$COMPILE_HTML_HELP" == "xON" ; then + if test "x$RESULTING_HTML_HELP_FILE" != "x" ; then + cd "$OUTPUT_DIRECTORY/html" + if test "x$HHC_PROG" != "xNOTFOUND" ; then + $HHC_PROG index.hhp + if test "x$MV_PROG" != "xNOTFOUND" ; then + $MV_PROG -f index.chm "$RESULTING_HTML_HELP_FILE" + fi + fi + fi +fi + +# ---------------------------------------------------------------------------- +# Create the compressed tar archive. + +if test "x$CREATE_HTML_TARZ_ARCHIVE" == "xON" ; then + if test "x$RESULTING_HTML_TARZ_ARCHIVE_FILE" != "x" ; then + cd "$OUTPUT_DIRECTORY" + if test "x$TAR_PROG" != "xNOTFOUND" ; then + if test "x$RM_PROG" != "xNOTFOUND" ; then + $RM_PROG -f html.tar + fi + $TAR_PROG -cf html.tar html + if test "x$GZIP_PROG" != "xNOTFOUND" ; then + if test "x$RM_PROG" != "xNOTFOUND" ; then + $RM_PROG -f html.tar.gz + fi + $GZIP_PROG html.tar + $MV_PROG -f html.tar.gz "$RESULTING_HTML_TARZ_ARCHIVE_FILE" + fi + fi + fi +fi + +# ---------------------------------------------------------------------------- +# Clean-up. + +if test "x$RM_PROG" != "xNOTFOUND" ; then + $RM_PROG -fr "$INTERMEDIATE_DOX_DIR" + + if test "x$DOWNLOAD_VTK_TAGFILE" == "xON" ; then + if test "x$VTK_TAGFILE" != "x" ; then + $RM_PROG -f "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE" + fi + fi + + if test "x$COMPILE_HTML_HELP" == "xON" ; then + if test "x$RESULTING_HTML_HELP_FILE" != "x" ; then + if test "x$ALLOW_ERASE_OUTPUT_DIRECTORY" == "xON" ; then + $RM_PROG -fr "$OUTPUT_DIRECTORY" + fi + fi + fi +fi diff --git a/Examples/Build/vtkMy/Utilities/Doxygen/doxyfile.in b/Examples/Build/vtkMy/Utilities/Doxygen/doxyfile.in new file mode 100644 index 0000000..1608e75 --- /dev/null +++ b/Examples/Build/vtkMy/Utilities/Doxygen/doxyfile.in @@ -0,0 +1,149 @@ +# ------------------------------------------------------------------------- +# doxyfile for vtkMy +# modified by S. Barre (Time-stamp: <2002-02-13 18:24:35 barre> +# ------------------------------------------------------------------------- + +PROJECT_NAME = vtkMy + +FULL_PATH_NAMES = YES +WARN_IF_UNDOCUMENTED = NO + +GENERATE_TREEVIEW = NO +GENERATE_TODOLIST = YES +GENERATE_BUGLIST = YES +GENERATE_HTML = YES +GENERATE_HTMLHELP = YES +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +GENERATE_TAGFILE = "@VTKMY_BINARY_DIR@/Utilities/Doxygen/vtkMy.tag" + +HAVE_DOT = YES +#HAVE_DOT = NO +DOT_PATH = "@DOT_PATH@" +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CLASS_DIAGRAMS = YES +GENERATE_LEGEND = YES +GRAPHICAL_HIERARCHY = YES + +ALLEXTERNALS = NO + +IMAGE_PATH = "@VTKMY_SOURCE_DIR@/Utilities/Doxygen" + +OUTPUT_DIRECTORY = "@VTKMY_BINARY_DIR@/Utilities/Doxygen/doc" + +INPUT = \ + "@VTKMY_BINARY_DIR@/Utilities/Doxygen/dox/Common" \ + "@VTKMY_BINARY_DIR@/Utilities/Doxygen/dox/Imaging" \ + "@VTKMY_BINARY_DIR@/Utilities/Doxygen/dox/Unsorted" \ + "@VTKMY_BINARY_DIR@/Utilities/Doxygen/dox/doc_vtkMy_index.dox" + +EXCLUDE_PATTERNS = +EXCLUDE = + +TAGFILES = "@VTKMY_BINARY_DIR@/Utilities/Doxygen/vtkNightlyDoc.tag=http://www.vtk.org/doc/nightly/html" + +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = YES +ALWAYS_DETAILED_SEC = NO +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +CASE_SENSE_NAMES = YES +VERBATIM_HEADERS = NO +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +SORT_MEMBER_DOCS = NO +DISTRIBUTE_GROUP_DOC = YES +TAB_SIZE = 3 +DETAILS_AT_TOP = YES + +FILE_PATTERNS = *.h +RECURSIVE = NO + +HTML_ALIGN_MEMBERS = YES +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 3 +IGNORE_PREFIX = vtkMy vtk + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +EXPAND_ONLY_PREDEF = YES +PREDEFINED = "vtkSetMacro(name,type)= \ + virtual void Set##name (type);" \ + "vtkGetMacro(name,type)= \ + virtual type Get##name ();" \ + "vtkSetStringMacro(name)= \ + virtual void Set##name (const char*);" \ + "vtkGetStringMacro(name)= \ + virtual char* Get##name ();" \ + "vtkSetClampMacro(name,type,min,max)= \ + virtual void Set##name (type);" \ + "vtkSetObjectMacro(name,type)= \ + virtual void Set##name (type*);" \ + "vtkGetObjectMacro(name,type)= \ + virtual type *Get##name ();" \ + "vtkBooleanMacro(name,type)= \ + virtual void name##On (); \ + virtual void name##Off ();" \ + "vtkSetVector2Macro(name,type)= \ + virtual void Set##name (type, type); \ + void Set##name (type [2]);" \ + "vtkGetVector2Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &); \ + virtual void Get##name (type [2]);" \ + "vtkSetVector3Macro(name,type)= \ + virtual void Set##name (type, type, type); \ + virtual void Set##name (type [3]);" \ + "vtkGetVector3Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &, type &); \ + virtual void Get##name (type [3]);" \ + "vtkSetVector4Macro(name,type)= \ + virtual void Set##name (type, type, type, type); \ + virtual void Set##name (type [4]);" \ + "vtkGetVector4Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &, type &, type &); \ + virtual void Get##name (type [4]);" \ + "vtkSetVector6Macro(name,type)= \ + virtual void Set##name (type, type, type, type, \ + type, type); \ + virtual void Set##name (type [6]);" \ + "vtkGetVector6Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &, type &, \ + type &, type &, type &); \ + virtual void Get##name (type [6]);" \ + "vtkSetVectorMacro(name,type,count)= \ + virtual void Set##name(type data[]);" \ + "vtkGetVectorMacro(name,type,count)= \ + virtual type *Get##name (); \ + virtual void Get##name(type data[##count]);" \ + "vtkWorldCoordinateMacro(name)= \ + virtual vtkCoordinate *Get##name##Coordinate (); \ + virtual void Set##name(float x[3]); \ + virtual void Set##name(float x, float y, float z); \ + virtual float *Get##name();" \ + "vtkViewportCoordinateMacro(name)= \ + virtual vtkCoordinate *Get##name##Coordinate (); \ + virtual void Set##name(float x[2]); \ + virtual void Set##name(float x, float y); \ + virtual float *Get##name();" \ + "vtkTypeMacro(thisClass,superclass)= \ + virtual const char *GetClassName(); \ + static int IsTypeOf(const char *type); \ + virtual int IsA(const char *type); \ + static thisClass* SafeDownCast(vtkObject *o);" + + diff --git a/Examples/Build/vtkMy/Wrapping/JavaDependencies.cmake.in b/Examples/Build/vtkMy/Wrapping/JavaDependencies.cmake.in new file mode 100644 index 0000000..016235e --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/JavaDependencies.cmake.in @@ -0,0 +1,5 @@ +# This file is automatically generated by CMake VTK_WRAP_JAVA +SET(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES} +@VTK_JAVA_DEPENDENCIES_FILE@ +) + diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/MakePackages.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/MakePackages.tcl new file mode 100644 index 0000000..ba9c0e4 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/MakePackages.tcl @@ -0,0 +1,12 @@ +#!/usr/bin/env tclsh + +# Execute this script each time you add a new directory or file. + +# Packages + +pkg_mkIndex -direct -verbose vtkmy +pkg_mkIndex -direct -verbose vtkmycommon +pkg_mkIndex -direct -verbose vtkmyimaging +pkg_mkIndex -direct -verbose vtkmyunsorted + +exit \ No newline at end of file diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmy/pkgIndex.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmy/pkgIndex.tcl new file mode 100644 index 0000000..452c3ce --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmy/pkgIndex.tcl @@ -0,0 +1,11 @@ +# Tcl package index file, version 1.1 +# This file is generated by the "pkg_mkIndex -direct" command +# and sourced either when an application starts up or +# by a "package unknown" script. It invokes the +# "package ifneeded" command to set up package-related +# information so that packages will be loaded automatically +# in response to "package require" commands. When this +# script is sourced, the variable $dir must contain the +# full path name of this file's directory. + +package ifneeded vtkmy 4.0 [list source [file join $dir vtkmy.tcl]] diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmy/vtkmy.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmy/vtkmy.tcl new file mode 100644 index 0000000..54469c5 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmy/vtkmy.tcl @@ -0,0 +1,6 @@ +package require vtkmycommon +package require vtkmyimaging +package require vtkmyunsorted + +package provide vtkmy 4.0 + diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmycommon/pkgIndex.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmycommon/pkgIndex.tcl new file mode 100644 index 0000000..7cceb86 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmycommon/pkgIndex.tcl @@ -0,0 +1,11 @@ +# Tcl package index file, version 1.1 +# This file is generated by the "pkg_mkIndex -direct" command +# and sourced either when an application starts up or +# by a "package unknown" script. It invokes the +# "package ifneeded" command to set up package-related +# information so that packages will be loaded automatically +# in response to "package require" commands. When this +# script is sourced, the variable $dir must contain the +# full path name of this file's directory. + +package ifneeded vtkmycommon 4.0 [list source [file join $dir vtkmycommon.tcl]] diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmycommon/vtkmycommon.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmycommon/vtkmycommon.tcl new file mode 100644 index 0000000..2d0c149 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmycommon/vtkmycommon.tcl @@ -0,0 +1,11 @@ +package require vtkcommon + +# +# Here you should pick the name of one your common local classes +# instead of vtkBar. +# + +if {[info commands vtkBar] != "" || + [::vtk::load_component vtkmyCommonTCL] == ""} { + package provide vtkmycommon 4.0 +} diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyimaging/pkgIndex.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyimaging/pkgIndex.tcl new file mode 100644 index 0000000..a9ba258 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyimaging/pkgIndex.tcl @@ -0,0 +1,11 @@ +# Tcl package index file, version 1.1 +# This file is generated by the "pkg_mkIndex -direct" command +# and sourced either when an application starts up or +# by a "package unknown" script. It invokes the +# "package ifneeded" command to set up package-related +# information so that packages will be loaded automatically +# in response to "package require" commands. When this +# script is sourced, the variable $dir must contain the +# full path name of this file's directory. + +package ifneeded vtkmyimaging 4.0 [list source [file join $dir vtkmyimaging.tcl]] diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyimaging/vtkmyimaging.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyimaging/vtkmyimaging.tcl new file mode 100644 index 0000000..f8d5825 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyimaging/vtkmyimaging.tcl @@ -0,0 +1,12 @@ +package require vtkmycommon +package require vtkimaging + +# +# Here you should pick the name of one your imaging local classes +# instead of vtkImageFoo. +# + +if {[info commands vtkImageFoo] != "" || + [::vtk::load_component vtkmyImagingTCL] == ""} { + package provide vtkmyimaging 4.0 +} diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyunsorted/pkgIndex.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyunsorted/pkgIndex.tcl new file mode 100644 index 0000000..fa49c7f --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyunsorted/pkgIndex.tcl @@ -0,0 +1,11 @@ +# Tcl package index file, version 1.1 +# This file is generated by the "pkg_mkIndex -direct" command +# and sourced either when an application starts up or +# by a "package unknown" script. It invokes the +# "package ifneeded" command to set up package-related +# information so that packages will be loaded automatically +# in response to "package require" commands. When this +# script is sourced, the variable $dir must contain the +# full path name of this file's directory. + +package ifneeded vtkmyunsorted 4.0 [list source [file join $dir vtkmyunsorted.tcl]] diff --git a/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyunsorted/vtkmyunsorted.tcl b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyunsorted/vtkmyunsorted.tcl new file mode 100644 index 0000000..25f0ac6 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/Tcl/vtkmyunsorted/vtkmyunsorted.tcl @@ -0,0 +1,12 @@ +package require vtkmyimaging +package require vtk + +# +# Here you should pick the name of one your imaging local classes +# instead of vtkBar2. +# + +if {[info commands vtkBar2] != "" || + [::vtk::load_component vtkmyUnsortedTCL] == ""} { + package provide vtkmyunsorted 4.0 +} diff --git a/Examples/Build/vtkMy/Wrapping/hints b/Examples/Build/vtkMy/Wrapping/hints new file mode 100644 index 0000000..e69de29 diff --git a/Examples/Build/vtkMy/Wrapping/vtkWrapperInit.data.in b/Examples/Build/vtkMy/Wrapping/vtkWrapperInit.data.in new file mode 100644 index 0000000..3d10232 --- /dev/null +++ b/Examples/Build/vtkMy/Wrapping/vtkWrapperInit.data.in @@ -0,0 +1 @@ +@VTK_WRAPPER_INIT_DATA@ diff --git a/Examples/Build/vtkMy/vtkmyConfigure.h.in b/Examples/Build/vtkMy/vtkmyConfigure.h.in new file mode 100644 index 0000000..03ac390 --- /dev/null +++ b/Examples/Build/vtkMy/vtkmyConfigure.h.in @@ -0,0 +1,13 @@ +/* + * Here is where system computed values get stored. + * These values should only change when the target compile platform changes. + */ + +#cmakedefine VTKMY_BUILD_SHARED_LIBS +#ifndef VTKMY_BUILD_SHARED_LIBS +#define VTKMY_STATIC +#endif + +#if defined(_MSC_VER) && !defined(VTKMY_STATIC) +#pragma warning ( disable : 4275 ) +#endif diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt new file mode 100644 index 0000000..2099d4a --- /dev/null +++ b/Examples/CMakeLists.txt @@ -0,0 +1,176 @@ +# VTK examples now require CMake 2.0 or higher. +CMAKE_MINIMUM_REQUIRED(VERSION 2.0) +IF(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 1.9) +ELSE(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 1.9) + MESSAGE(FATAL_ERROR "VTKExamples requires CMake 2.0 or higher.") +ENDIF(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 1.9) + +# Choose behavior based on whether we are building inside the VTK tree. +IF(VTK_BINARY_DIR) + # We are building in the VTK tree. Add tests for some examples. + # Test the build system examples. + IF(BUILD_TESTING) + # If multiple configuration types are available we must add the test + # in a way that will use the configuration given for testing. When + # CTest 2.1 and higher is used to drive the tests it evaluates the + # ADD_TEST commands stored in the test files using standard cmake + # language evaluation. The variable CTEST_CONFIGURATION_TYPE expands + # to the configuration specified for testing (Debug, Release, etc.). + # This variable must be stored in the test string and evaluated at + # testing time, so the dollar must be stored in a way that will not be + # evaluated immediately. In CMake 2.1 and higher this can be done + # with an escaped dollar but we must support older CMake versions + # syntactically. Since we do not know what tool will be used to drive + # the tests (Dart, CTest <= 2.0, CTest > 2.0, etc.) we have to have a + # special cache option "VTK_TEST_WITH_CTEST" to enable this feature. + # Dashboard maintainers will have to set this option to properly run + # these tests. + + # Default to single-configuration behavior. + SET(VTK_EXAMPLE_TEST_CONFIG_TYPE) + SET(VTK_EXAMPLE_TEST_RUN_DIR "${EXECUTABLE_OUTPUT_PATH}") + + # Enable multi-configuration behavior if support is available. + IF(CMAKE_CONFIGURATION_TYPES AND VTK_TEST_WITH_CTEST) + SET(DOLLAR "$") + IF(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.0) + SET(VTK_EXAMPLE_TEST_CONFIG_TYPE -C "${DOLLAR}{CTEST_CONFIGURATION_TYPE}") + SET(VTK_EXAMPLE_TEST_RUN_DIR "${EXECUTABLE_OUTPUT_PATH}/${DOLLAR}{CTEST_CONFIGURATION_TYPE}") + ENDIF(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.0) + ENDIF(CMAKE_CONFIGURATION_TYPES AND VTK_TEST_WITH_CTEST) + + # Add a test to build the vtkLocal example. + ADD_TEST(Example-vtkLocal ${CMAKE_CTEST_COMMAND} + ${VTK_EXAMPLE_TEST_CONFIG_TYPE} + --build-and-test + ${VTK_SOURCE_DIR}/Examples/Build/vtkLocal + ${VTK_BINARY_DIR}/Examples/Build/vtkLocal + --build-two-config + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-project VTKLOCAL + --build-run-dir ${VTK_EXAMPLE_TEST_RUN_DIR} + --build-options -DVTK_DIR:PATH=${VTK_BINARY_DIR} + --test-command "${VTK_BINARY_DIR}/Examples/Build/vtkLocal/bin/vtkLocalTest" + ) + + # Add a test to build the vtkMy example. + ADD_TEST(Example-vtkMy ${CMAKE_CTEST_COMMAND} + ${VTK_EXAMPLE_TEST_CONFIG_TYPE} + --build-and-test + ${VTK_SOURCE_DIR}/Examples/Build/vtkMy + ${VTK_BINARY_DIR}/Examples/Build/vtkMy + --build-two-config + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-project VTKMY + --build-run-dir ${VTK_EXAMPLE_TEST_RUN_DIR} + --build-options -DVTK_DIR:PATH=${VTK_BINARY_DIR} + --test-command "${VTK_BINARY_DIR}/Examples/Build/vtkMy/bin/vtkmyEx1" + ) + ENDIF(BUILD_TESTING) + + # Build the examples as a separate project using a custom target. + # Make sure it uses the same build configuration as VTK. + IF(CMAKE_CONFIGURATION_TYPES) + SET(VTKExamples_CONFIG_TYPE -C "${CMAKE_CFG_INTDIR}") + ELSE(CMAKE_CONFIGURATION_TYPES) + SET(VTKExamples_CONFIG_TYPE) + ENDIF(CMAKE_CONFIGURATION_TYPES) + ADD_CUSTOM_COMMAND( + OUTPUT ${VTK_BINARY_DIR}/VTKExamples + COMMAND ${CMAKE_CTEST_COMMAND} + ARGS ${VTKExamples_CONFIG_TYPE} + --build-and-test + ${VTK_SOURCE_DIR}/Examples + ${VTK_BINARY_DIR}/Examples/All + --build-noclean + --build-two-config + --build-project VTKExamples + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} + --build-options -DVTK_DIR:PATH=${VTK_BINARY_DIR} + -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} + -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} + -DCMAKE_C_FLAGS_DEBUG:STRING=${CMAKE_C_FLAGS_DEBUG} + -DCMAKE_C_FLAGS_RELEASE:STRING=${CMAKE_C_FLAGS_RELEASE} + -DCMAKE_C_FLAGS_MINSIZEREL:STRING=${CMAKE_C_FLAGS_MINSIZEREL} + -DCMAKE_C_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_C_FLAGS_RELWITHDEBINFO} + -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} + -DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} + -DCMAKE_CXX_FLAGS_DEBUG:STRING=${CMAKE_CXX_FLAGS_DEBUG} + -DCMAKE_CXX_FLAGS_RELEASE:STRING=${CMAKE_CXX_FLAGS_RELEASE} + -DCMAKE_CXX_FLAGS_MINSIZEREL:STRING=${CMAKE_CXX_FLAGS_MINSIZEREL} + -DCMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} + -DEXECUTABLE_OUTPUT_PATH:PATH=${EXECUTABLE_OUTPUT_PATH} + -DLIBRARY_OUTPUT_PATH:PATH=${LIBRARY_OUTPUT_PATH} + ) + ADD_CUSTOM_TARGET(VTKExamplesTarget ALL DEPENDS ${VTK_BINARY_DIR}/VTKExamples) + + # Make sure the target builds after the rest of VTK. + ADD_DEPENDENCIES(VTKExamplesTarget + vtkCommon + vtkFiltering + vtkImaging + vtkGraphics + vtkGenericFiltering + vtkIO + ) + IF(VTK_USE_RENDERING) + ADD_DEPENDENCIES(VTKExamplesTarget vtkRendering) + ADD_DEPENDENCIES(VTKExamplesTarget vtkVolumeRendering) + ADD_DEPENDENCIES(VTKExamplesTarget vtkHybrid) + ADD_DEPENDENCIES(VTKExamplesTarget vtkWidgets) + ENDIF(VTK_USE_RENDERING) + IF(VTK_USE_PARALLEL) + ADD_DEPENDENCIES(VTKExamplesTarget vtkParallel) + ENDIF(VTK_USE_PARALLEL) + IF(VTK_USE_QVTK) + ADD_DEPENDENCIES(VTKExamplesTarget QVTK) + ENDIF(VTK_USE_QVTK) + IF(VTK_USE_MFC) + ADD_DEPENDENCIES(VTKExamplesTarget vtkMFC) + ENDIF(VTK_USE_MFC) + +ELSE(VTK_BINARY_DIR) + # We are building outside the VTK tree. Build the examples directly. + PROJECT(VTKExamples) + + # Find and load the VTK configuration. + FIND_PACKAGE(VTK) + IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") + ENDIF(NOT VTK_DIR) + INCLUDE(${VTK_USE_FILE}) + + # Most examples require rendering support. + IF(VTK_USE_RENDERING) + SUBDIRS( + AMR/Cxx + MultiBlock/Cxx + GUI/Motif + DataManipulation/Cxx + Medical/Cxx + Modelling/Cxx + Rendering/Cxx + Tutorial/Step1/Cxx + Tutorial/Step2/Cxx + Tutorial/Step3/Cxx + Tutorial/Step4/Cxx + Tutorial/Step5/Cxx + Tutorial/Step6/Cxx + ) + + IF(VTK_USE_PARALLEL) + SUBDIRS(ParallelProcessing) + ENDIF(VTK_USE_PARALLEL) + + IF(VTK_USE_QVTK) + SUBDIRS(GUI/Qt) + ENDIF(VTK_USE_QVTK) + + IF(VTK_USE_MFC) + SUBDIRS(GUI/Win32/vtkMFC) + ENDIF(VTK_USE_MFC) + ENDIF(VTK_USE_RENDERING) +ENDIF(VTK_BINARY_DIR) diff --git a/Examples/DataManipulation/Cxx/Arrays.cxx b/Examples/DataManipulation/Cxx/Arrays.cxx new file mode 100644 index 0000000..af70ff8 --- /dev/null +++ b/Examples/DataManipulation/Cxx/Arrays.cxx @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Arrays.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrate the use of VTK data arrays as attribute +// data as well as field data. It creates geometry (vtkPolyData) as +// well as attribute data explicitly. + +// first include the required header files for the vtk classes we are using +#include "vtkActor.h" +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIntArray.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" + +int main() +{ + int i; + + // Create a float array which represents the points. + vtkFloatArray* pcoords = vtkFloatArray::New(); + + // Note that by default, an array has 1 component. + // We have to change it to 3 for points + pcoords->SetNumberOfComponents(3); + // We ask pcoords to allocate room for at least 4 tuples + // and set the number of tuples to 4. + pcoords->SetNumberOfTuples(4); + // Assign each tuple. There are 5 specialized versions of SetTuple: + // SetTuple1 SetTuple2 SetTuple3 SetTuple4 SetTuple9 + // These take 1, 2, 3, 4 and 9 components respectively. + float pts[4][3] = { {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, + {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0} }; + for (i=0; i<4; i++) + { + pcoords->SetTuple(i, pts[i]); + } + + // Create vtkPoints and assign pcoords as the internal data array. + vtkPoints* points = vtkPoints::New(); + points->SetData(pcoords); + + // Create the cells. In this case, a triangle strip with 2 triangles + // (which can be represented by 4 points) + vtkCellArray* strips = vtkCellArray::New(); + strips->InsertNextCell(4); + strips->InsertCellPoint(0); + strips->InsertCellPoint(1); + strips->InsertCellPoint(2); + strips->InsertCellPoint(3); + + // Create an integer array with 4 tuples. Note that when using + // InsertNextValue (or InsertNextTuple1 which is equivalent in + // this situation), the array will expand automatically + vtkIntArray* temperature = vtkIntArray::New(); + temperature->SetName("Temperature"); + temperature->InsertNextValue(10); + temperature->InsertNextValue(20); + temperature->InsertNextValue(30); + temperature->InsertNextValue(40); + + // Create a double array. + vtkDoubleArray* vorticity = vtkDoubleArray::New(); + vorticity->SetName("Vorticity"); + vorticity->InsertNextValue(2.7); + vorticity->InsertNextValue(4.1); + vorticity->InsertNextValue(5.3); + vorticity->InsertNextValue(3.4); + + // Create the dataset. In this case, we create a vtkPolyData + vtkPolyData* polydata = vtkPolyData::New(); + // Assign points and cells + polydata->SetPoints(points); + polydata->SetStrips(strips); + // Assign scalars + polydata->GetPointData()->SetScalars(temperature); + // Add the vorticity array. In this example, this field + // is not used. + polydata->GetPointData()->AddArray(vorticity); + + // Create the mapper and set the appropriate scalar range + // (default is (0,1) + vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); + mapper->SetInput(polydata); + mapper->SetScalarRange(0, 40); + + // Create an actor. + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + + // Create the rendering objects. + vtkRenderer* ren = vtkRenderer::New(); + ren->AddActor(actor); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + iren->Initialize(); + iren->Start(); + + pcoords->Delete(); + points->Delete(); + strips->Delete(); + temperature->Delete(); + vorticity->Delete(); + polydata->Delete(); + mapper->Delete(); + actor->Delete(); + ren->Delete(); + renWin->Delete(); + iren->Delete(); + return 0; +} + + diff --git a/Examples/DataManipulation/Cxx/CMakeLists.txt b/Examples/DataManipulation/Cxx/CMakeLists.txt new file mode 100644 index 0000000..7f4f41f --- /dev/null +++ b/Examples/DataManipulation/Cxx/CMakeLists.txt @@ -0,0 +1,17 @@ +PROJECT (DataManipulation) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Arrays Arrays.cxx) +ADD_EXECUTABLE(Cube Cube.cxx) +ADD_EXECUTABLE(SGrid SGrid.cxx) +ADD_EXECUTABLE(RGrid RGrid.cxx) + +TARGET_LINK_LIBRARIES(Arrays vtkRendering) +TARGET_LINK_LIBRARIES(Cube vtkRendering) +TARGET_LINK_LIBRARIES(SGrid vtkRendering) +TARGET_LINK_LIBRARIES(RGrid vtkRendering) diff --git a/Examples/DataManipulation/Cxx/Cube.cxx b/Examples/DataManipulation/Cxx/Cube.cxx new file mode 100644 index 0000000..f6d6f07 --- /dev/null +++ b/Examples/DataManipulation/Cxx/Cube.cxx @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cube.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example shows how to manually create vtkPolyData. + +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" + +int main() +{ + int i; + static float x[8][3]={{0,0,0}, {1,0,0}, {1,1,0}, {0,1,0}, + {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1}}; + static vtkIdType pts[6][4]={{0,1,2,3}, {4,5,6,7}, {0,1,5,4}, + {1,2,6,5}, {2,3,7,6}, {3,0,4,7}}; + + // We'll create the building blocks of polydata including data attributes. + vtkPolyData *cube = vtkPolyData::New(); + vtkPoints *points = vtkPoints::New(); + vtkCellArray *polys = vtkCellArray::New(); + vtkFloatArray *scalars = vtkFloatArray::New(); + + // Load the point, cell, and data attributes. + for (i=0; i<8; i++) points->InsertPoint(i,x[i]); + for (i=0; i<6; i++) polys->InsertNextCell(4,pts[i]); + for (i=0; i<8; i++) scalars->InsertTuple1(i,i); + + // We now assign the pieces to the vtkPolyData. + cube->SetPoints(points); + points->Delete(); + cube->SetPolys(polys); + polys->Delete(); + cube->GetPointData()->SetScalars(scalars); + scalars->Delete(); + + // Now we'll look at it. + vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); + cubeMapper->SetInput(cube); + cubeMapper->SetScalarRange(0,7); + vtkActor *cubeActor = vtkActor::New(); + cubeActor->SetMapper(cubeMapper); + + // The usual rendering stuff. + vtkCamera *camera = vtkCamera::New(); + camera->SetPosition(1,1,1); + camera->SetFocalPoint(0,0,0); + + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + renderer->AddActor(cubeActor); + renderer->SetActiveCamera(camera); + renderer->ResetCamera(); + renderer->SetBackground(1,1,1); + + renWin->SetSize(300,300); + + // interact with data + renWin->Render(); + iren->Start(); + + // Clean up + + cube->Delete(); + cubeMapper->Delete(); + cubeActor->Delete(); + camera->Delete(); + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + + return 0; +} diff --git a/Examples/DataManipulation/Cxx/RGrid.cxx b/Examples/DataManipulation/Cxx/RGrid.cxx new file mode 100644 index 0000000..60deb4b --- /dev/null +++ b/Examples/DataManipulation/Cxx/RGrid.cxx @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: RGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example shows how to create a rectilinear grid. +// + +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkFloatArray.h" +#include "vtkRectilinearGrid.h" +#include "vtkRectilinearGridGeometryFilter.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkProperty.h" +#include "vtkCamera.h" + +int main() +{ + int i; + static float x[47]={ + -1.22396, -1.17188, -1.11979, -1.06771, -1.01562, -0.963542, + -0.911458, -0.859375, -0.807292, -0.755208, -0.703125, -0.651042, + -0.598958, -0.546875, -0.494792, -0.442708, -0.390625, -0.338542, + -0.286458, -0.234375, -0.182292, -0.130209, -0.078125, -0.026042, + 0.0260415, 0.078125, 0.130208, 0.182291, 0.234375, 0.286458, + 0.338542, 0.390625, 0.442708, 0.494792, 0.546875, 0.598958, + 0.651042, 0.703125, 0.755208, 0.807292, 0.859375, 0.911458, + 0.963542, 1.01562, 1.06771, 1.11979, 1.17188}; + static float y[33]={-1.25, -1.17188, -1.09375, -1.01562, -0.9375, -0.859375, + -0.78125, -0.703125, -0.625, -0.546875, -0.46875, -0.390625, + -0.3125, -0.234375, -0.15625, -0.078125, 0, 0.078125, + 0.15625, 0.234375, 0.3125, 0.390625, 0.46875, 0.546875, + 0.625, 0.703125, 0.78125, 0.859375, 0.9375, 1.01562, + 1.09375, 1.17188, 1.25}; + static float z[44]={0, 0.1, 0.2, 0.3, 0.4, 0.5, + 0.6, 0.7, 0.75, 0.8, 0.9, 1, + 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, + 1.7, 1.75, 1.8, 1.9, 2, 2.1, + 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, + 2.75, 2.8, 2.9, 3, 3.1, 3.2, + 3.3, 3.4, 3.5, 3.6, 3.7, 3.75, + 3.8, 3.9}; + + // Create a rectilinear grid by defining three arrays specifying the + // coordinates in the x-y-z directions. + vtkFloatArray *xCoords = vtkFloatArray::New(); + for (i=0; i<47; i++) xCoords->InsertNextValue(x[i]); + + vtkFloatArray *yCoords = vtkFloatArray::New(); + for (i=0; i<33; i++) yCoords->InsertNextValue(y[i]); + + vtkFloatArray *zCoords = vtkFloatArray::New(); + for (i=0; i<44; i++) zCoords->InsertNextValue(z[i]); + + // The coordinates are assigned to the rectilinear grid. Make sure that + // the number of values in each of the XCoordinates, YCoordinates, + // and ZCoordinates is equal to what is defined in SetDimensions(). + // + vtkRectilinearGrid *rgrid = vtkRectilinearGrid::New(); + rgrid->SetDimensions(47,33,44); + rgrid->SetXCoordinates(xCoords); + rgrid->SetYCoordinates(yCoords); + rgrid->SetZCoordinates(zCoords); + + // Extract a plane from the grid to see what we've got. + vtkRectilinearGridGeometryFilter *plane = vtkRectilinearGridGeometryFilter::New(); + plane->SetInput(rgrid); + plane->SetExtent(0,46, 16,16, 0,43); + + vtkPolyDataMapper *rgridMapper = vtkPolyDataMapper::New(); + rgridMapper->SetInputConnection(plane->GetOutputPort()); + + vtkActor *wireActor = vtkActor::New(); + wireActor->SetMapper(rgridMapper); + wireActor->GetProperty()->SetRepresentationToWireframe(); + wireActor->GetProperty()->SetColor(0,0,0); + + // Create the usual rendering stuff. + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + renderer->AddActor(wireActor); + renderer->SetBackground(1,1,1); + renderer->ResetCamera(); + renderer->GetActiveCamera()->Elevation(60.0); + renderer->GetActiveCamera()->Azimuth(30.0); + renderer->GetActiveCamera()->Zoom(1.0); + + renWin->SetSize(300,300); + + // interact with data + renWin->Render(); + iren->Start(); + + // Clean up + plane->Delete(); + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + xCoords->Delete(); + yCoords->Delete(); + zCoords->Delete(); + rgrid->Delete(); + rgridMapper->Delete(); + wireActor->Delete(); + + return 0; +} diff --git a/Examples/DataManipulation/Cxx/SGrid.cxx b/Examples/DataManipulation/Cxx/SGrid.cxx new file mode 100644 index 0000000..d9bc6f2 --- /dev/null +++ b/Examples/DataManipulation/Cxx/SGrid.cxx @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example shows how to manually create a structured grid. +// The basic idea is to instantiate vtkStructuredGrid, set its dimensions, +// and then assign points defining the grid coordinate. The number of +// points must equal the number of points implicit in the dimensions +// (i.e., dimX*dimY*dimZ). Also, data attributes (either point or cell) +// can be added to the dataset. +// +// +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkFloatArray.h" +#include "vtkHedgeHog.h" +#include "vtkMath.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkStructuredGrid.h" + +int main() +{ + int i, j, k, kOffset, jOffset, offset; + float x[3], v[3], rMin=0.5, rMax=1.0, deltaRad, deltaZ; + float radius, theta; + static int dims[3]={13,11,11}; + + // Create the structured grid. + vtkStructuredGrid *sgrid = vtkStructuredGrid::New(); + sgrid->SetDimensions(dims); + + // We also create the points and vectors. The points + // form a hemi-cylinder of data. + vtkFloatArray *vectors = vtkFloatArray::New(); + vectors->SetNumberOfComponents(3); + vectors->SetNumberOfTuples(dims[0]*dims[1]*dims[2]); + vtkPoints *points = vtkPoints::New(); + points->Allocate(dims[0]*dims[1]*dims[2]); + + deltaZ = 2.0 / (dims[2]-1); + deltaRad = (rMax-rMin) / (dims[1]-1); + v[2]=0.0; + for ( k=0; kInsertPoint(offset,x); + vectors->InsertTuple(offset,v); + } + } + } + sgrid->SetPoints(points); + points->Delete(); + sgrid->GetPointData()->SetVectors(vectors); + vectors->Delete(); + + // We create a simple pipeline to display the data. + vtkHedgeHog *hedgehog = vtkHedgeHog::New(); + hedgehog->SetInput(sgrid); + hedgehog->SetScaleFactor(0.1); + + vtkPolyDataMapper *sgridMapper = vtkPolyDataMapper::New(); + sgridMapper->SetInputConnection(hedgehog->GetOutputPort()); + vtkActor *sgridActor = vtkActor::New(); + sgridActor->SetMapper(sgridMapper); + sgridActor->GetProperty()->SetColor(0,0,0); + + // Create the usual rendering stuff + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + renderer->AddActor(sgridActor); + renderer->SetBackground(1,1,1); + renderer->ResetCamera(); + renderer->GetActiveCamera()->Elevation(60.0); + renderer->GetActiveCamera()->Azimuth(30.0); + renderer->GetActiveCamera()->Zoom(1.25); + renWin->SetSize(300,300); + + // interact with data + renWin->Render(); + iren->Start(); + + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + sgrid->Delete(); + hedgehog->Delete(); + sgridMapper->Delete(); + sgridActor->Delete(); + + return 0; +} diff --git a/Examples/DataManipulation/Python/Arrays.py b/Examples/DataManipulation/Python/Arrays.py new file mode 100644 index 0000000..68cde31 --- /dev/null +++ b/Examples/DataManipulation/Python/Arrays.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +# This example demonstrates the use of VTK data arrays as attribute +# data as well as field data. It creates geometry (vtkPolyData) as +# well as attribute data explicitly. + +import vtk + +# Create a float array which represents the points. +pcoords = vtk.vtkFloatArray() +# Note that by default, an array has 1 component. +# We have to change it to 3 for points +pcoords.SetNumberOfComponents(3) +# We ask pcoords to allocate room for at least 4 tuples +# and set the number of tuples to 4. +pcoords.SetNumberOfTuples(4) +# Assign each tuple. There are 5 specialized versions of SetTuple: +# SetTuple1 SetTuple2 SetTuple3 SetTuple4 SetTuple9 +# These take 1, 2, 3, 4 and 9 components respectively. +pcoords.SetTuple3(0, 0.0, 0.0, 0.0) +pcoords.SetTuple3(1, 0.0, 1.0, 0.0) +pcoords.SetTuple3(2, 1.0, 0.0, 0.0) +pcoords.SetTuple3(3, 1.0, 1.0, 0.0) + +# Create vtkPoints and assign pcoords as the internal data array. +points = vtk.vtkPoints() +points.SetData(pcoords) + +# Create the cells. In this case, a triangle strip with 2 triangles +# (which can be represented by 4 points) +strips = vtk.vtkCellArray() +strips.InsertNextCell(4) +strips.InsertCellPoint(0) +strips.InsertCellPoint(1) +strips.InsertCellPoint(2) +strips.InsertCellPoint(3) + +# Create an integer array with 4 tuples. Note that when using +# InsertNextValue (or InsertNextTuple1 which is equivalent in +# this situation), the array will expand automatically +temperature = vtk.vtkIntArray() +temperature.SetName("Temperature") +temperature.InsertNextValue(10) +temperature.InsertNextValue(20) +temperature.InsertNextValue(30) +temperature.InsertNextValue(40) + +# Create a double array. +vorticity = vtk.vtkDoubleArray() +vorticity.SetName("Vorticity") +vorticity.InsertNextValue(2.7) +vorticity.InsertNextValue(4.1) +vorticity.InsertNextValue(5.3) +vorticity.InsertNextValue(3.4) + +# Create the dataset. In this case, we create a vtkPolyData +polydata = vtk.vtkPolyData() +# Assign points and cells +polydata.SetPoints(points) +polydata.SetStrips(strips) +# Assign scalars +polydata.GetPointData().SetScalars(temperature) +# Add the vorticity array. In this example, this field +# is not used. +polydata.GetPointData().AddArray(vorticity) + +# Create the mapper and set the appropriate scalar range +# (default is (0,1) +mapper = vtk.vtkPolyDataMapper() +mapper.SetInput(polydata) +mapper.SetScalarRange(0, 40) + +# Create an actor. +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +# Create the rendering objects. +ren = vtk.vtkRenderer() +ren.AddActor(actor) + +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/DataManipulation/Python/BuildUGrid.py b/Examples/DataManipulation/Python/BuildUGrid.py new file mode 100644 index 0000000..f7584e1 --- /dev/null +++ b/Examples/DataManipulation/Python/BuildUGrid.py @@ -0,0 +1,386 @@ +#!/usr/bin/env python + +# This example shows how to manually construct unstructured grids +# using Python. Unstructured grids require explicit point and cell +# representations, so every point and cell must be created, and then +# added to the vtkUnstructuredGrid instance. + +import vtk + +# Create several unstructured grids each containing a cell of a +# different type. +voxelPoints = vtk.vtkPoints() +voxelPoints.SetNumberOfPoints(8) +voxelPoints.InsertPoint(0, 0, 0, 0) +voxelPoints.InsertPoint(1, 1, 0, 0) +voxelPoints.InsertPoint(2, 0, 1, 0) +voxelPoints.InsertPoint(3, 1, 1, 0) +voxelPoints.InsertPoint(4, 0, 0, 1) +voxelPoints.InsertPoint(5, 1, 0, 1) +voxelPoints.InsertPoint(6, 0, 1, 1) +voxelPoints.InsertPoint(7, 1, 1, 1) +aVoxel = vtk.vtkVoxel() +aVoxel.GetPointIds().SetId(0, 0) +aVoxel.GetPointIds().SetId(1, 1) +aVoxel.GetPointIds().SetId(2, 2) +aVoxel.GetPointIds().SetId(3, 3) +aVoxel.GetPointIds().SetId(4, 4) +aVoxel.GetPointIds().SetId(5, 5) +aVoxel.GetPointIds().SetId(6, 6) +aVoxel.GetPointIds().SetId(7, 7) +aVoxelGrid = vtk.vtkUnstructuredGrid() +aVoxelGrid.Allocate(1, 1) +aVoxelGrid.InsertNextCell(aVoxel.GetCellType(), aVoxel.GetPointIds()) +aVoxelGrid.SetPoints(voxelPoints) +aVoxelMapper = vtk.vtkDataSetMapper() +aVoxelMapper.SetInput(aVoxelGrid) +aVoxelActor = vtk.vtkActor() +aVoxelActor.SetMapper(aVoxelMapper) +aVoxelActor.GetProperty().SetDiffuseColor(1, 0, 0) + +hexahedronPoints = vtk.vtkPoints() +hexahedronPoints.SetNumberOfPoints(8) +hexahedronPoints.InsertPoint(0, 0, 0, 0) +hexahedronPoints.InsertPoint(1, 1, 0, 0) +hexahedronPoints.InsertPoint(2, 1, 1, 0) +hexahedronPoints.InsertPoint(3, 0, 1, 0) +hexahedronPoints.InsertPoint(4, 0, 0, 1) +hexahedronPoints.InsertPoint(5, 1, 0, 1) +hexahedronPoints.InsertPoint(6, 1, 1, 1) +hexahedronPoints.InsertPoint(7, 0, 1, 1) +aHexahedron = vtk.vtkHexahedron() +aHexahedron.GetPointIds().SetId(0, 0) +aHexahedron.GetPointIds().SetId(1, 1) +aHexahedron.GetPointIds().SetId(2, 2) +aHexahedron.GetPointIds().SetId(3, 3) +aHexahedron.GetPointIds().SetId(4, 4) +aHexahedron.GetPointIds().SetId(5, 5) +aHexahedron.GetPointIds().SetId(6, 6) +aHexahedron.GetPointIds().SetId(7, 7) +aHexahedronGrid = vtk.vtkUnstructuredGrid() +aHexahedronGrid.Allocate(1, 1) +aHexahedronGrid.InsertNextCell(aHexahedron.GetCellType(), + aHexahedron.GetPointIds()) +aHexahedronGrid.SetPoints(hexahedronPoints) +aHexahedronMapper = vtk.vtkDataSetMapper() +aHexahedronMapper.SetInput(aHexahedronGrid) +aHexahedronActor = vtk.vtkActor() +aHexahedronActor.SetMapper(aHexahedronMapper) +aHexahedronActor.AddPosition(2, 0, 0) +aHexahedronActor.GetProperty().SetDiffuseColor(1, 1, 0) + +tetraPoints = vtk.vtkPoints() +tetraPoints.SetNumberOfPoints(4) +tetraPoints.InsertPoint(0, 0, 0, 0) +tetraPoints.InsertPoint(1, 1, 0, 0) +tetraPoints.InsertPoint(2, .5, 1, 0) +tetraPoints.InsertPoint(3, .5, .5, 1) +aTetra = vtk.vtkTetra() +aTetra.GetPointIds().SetId(0, 0) +aTetra.GetPointIds().SetId(1, 1) +aTetra.GetPointIds().SetId(2, 2) +aTetra.GetPointIds().SetId(3, 3) +aTetraGrid = vtk.vtkUnstructuredGrid() +aTetraGrid.Allocate(1, 1) +aTetraGrid.InsertNextCell(aTetra.GetCellType(), aTetra.GetPointIds()) +aTetraGrid.SetPoints(tetraPoints) +aTetraMapper = vtk.vtkDataSetMapper() +aTetraMapper.SetInput(aTetraGrid) +aTetraActor = vtk.vtkActor() +aTetraActor.SetMapper(aTetraMapper) +aTetraActor.AddPosition(4, 0, 0) +aTetraActor.GetProperty().SetDiffuseColor(0, 1, 0) + +wedgePoints = vtk.vtkPoints() +wedgePoints.SetNumberOfPoints(6) +wedgePoints.InsertPoint(0, 0, 1, 0) +wedgePoints.InsertPoint(1, 0, 0, 0) +wedgePoints.InsertPoint(2, 0, .5, .5) +wedgePoints.InsertPoint(3, 1, 1, 0) +wedgePoints.InsertPoint(4, 1, 0, 0) +wedgePoints.InsertPoint(5, 1, .5, .5) +aWedge = vtk.vtkWedge() +aWedge.GetPointIds().SetId(0, 0) +aWedge.GetPointIds().SetId(1, 1) +aWedge.GetPointIds().SetId(2, 2) +aWedge.GetPointIds().SetId(3, 3) +aWedge.GetPointIds().SetId(4, 4) +aWedge.GetPointIds().SetId(5, 5) +aWedgeGrid = vtk.vtkUnstructuredGrid() +aWedgeGrid.Allocate(1, 1) +aWedgeGrid.InsertNextCell(aWedge.GetCellType(), aWedge.GetPointIds()) +aWedgeGrid.SetPoints(wedgePoints) +aWedgeMapper = vtk.vtkDataSetMapper() +aWedgeMapper.SetInput(aWedgeGrid) +aWedgeActor = vtk.vtkActor() +aWedgeActor.SetMapper(aWedgeMapper) +aWedgeActor.AddPosition(6, 0, 0) +aWedgeActor.GetProperty().SetDiffuseColor(0, 1, 1) + +pyramidPoints = vtk.vtkPoints() +pyramidPoints.SetNumberOfPoints(5) +pyramidPoints.InsertPoint(0, 0, 0, 0) +pyramidPoints.InsertPoint(1, 1, 0, 0) +pyramidPoints.InsertPoint(2, 1, 1, 0) +pyramidPoints.InsertPoint(3, 0, 1, 0) +pyramidPoints.InsertPoint(4, .5, .5, 1) +aPyramid = vtk.vtkPyramid() +aPyramid.GetPointIds().SetId(0, 0) +aPyramid.GetPointIds().SetId(1, 1) +aPyramid.GetPointIds().SetId(2, 2) +aPyramid.GetPointIds().SetId(3, 3) +aPyramid.GetPointIds().SetId(4, 4) +aPyramidGrid = vtk.vtkUnstructuredGrid() +aPyramidGrid.Allocate(1, 1) +aPyramidGrid.InsertNextCell(aPyramid.GetCellType(), aPyramid.GetPointIds()) +aPyramidGrid.SetPoints(pyramidPoints) +aPyramidMapper = vtk.vtkDataSetMapper() +aPyramidMapper.SetInput(aPyramidGrid) +aPyramidActor = vtk.vtkActor() +aPyramidActor.SetMapper(aPyramidMapper) +aPyramidActor.AddPosition(8, 0, 0) +aPyramidActor.GetProperty().SetDiffuseColor(1, 0, 1) + +pixelPoints = vtk.vtkPoints() +pixelPoints.SetNumberOfPoints(4) +pixelPoints.InsertPoint(0, 0, 0, 0) +pixelPoints.InsertPoint(1, 1, 0, 0) +pixelPoints.InsertPoint(2, 0, 1, 0) +pixelPoints.InsertPoint(3, 1, 1, 0) +aPixel = vtk.vtkPixel() +aPixel.GetPointIds().SetId(0, 0) +aPixel.GetPointIds().SetId(1, 1) +aPixel.GetPointIds().SetId(2, 2) +aPixel.GetPointIds().SetId(3, 3) +aPixelGrid = vtk.vtkUnstructuredGrid() +aPixelGrid.Allocate(1, 1) +aPixelGrid.InsertNextCell(aPixel.GetCellType(), aPixel.GetPointIds()) +aPixelGrid.SetPoints(pixelPoints) +aPixelMapper = vtk.vtkDataSetMapper() +aPixelMapper.SetInput(aPixelGrid) +aPixelActor = vtk.vtkActor() +aPixelActor.SetMapper(aPixelMapper) +aPixelActor.AddPosition(0, 0, 2) +aPixelActor.GetProperty().SetDiffuseColor(0, 1, 1) + +quadPoints = vtk.vtkPoints() +quadPoints.SetNumberOfPoints(4) +quadPoints.InsertPoint(0, 0, 0, 0) +quadPoints.InsertPoint(1, 1, 0, 0) +quadPoints.InsertPoint(2, 1, 1, 0) +quadPoints.InsertPoint(3, 0, 1, 0) +aQuad = vtk.vtkQuad() +aQuad.GetPointIds().SetId(0, 0) +aQuad.GetPointIds().SetId(1, 1) +aQuad.GetPointIds().SetId(2, 2) +aQuad.GetPointIds().SetId(3, 3) +aQuadGrid = vtk.vtkUnstructuredGrid() +aQuadGrid.Allocate(1, 1) +aQuadGrid.InsertNextCell(aQuad.GetCellType(), aQuad.GetPointIds()) +aQuadGrid.SetPoints(quadPoints) +aQuadMapper = vtk.vtkDataSetMapper() +aQuadMapper.SetInput(aQuadGrid) +aQuadActor = vtk.vtkActor() +aQuadActor.SetMapper(aQuadMapper) +aQuadActor.AddPosition(2, 0, 2) +aQuadActor.GetProperty().SetDiffuseColor(1, 0, 1) + +trianglePoints = vtk.vtkPoints() +trianglePoints.SetNumberOfPoints(3) +trianglePoints.InsertPoint(0, 0, 0, 0) +trianglePoints.InsertPoint(1, 1, 0, 0) +trianglePoints.InsertPoint(2, .5, .5, 0) +triangleTCoords = vtk.vtkFloatArray() +triangleTCoords.SetNumberOfComponents(3) +triangleTCoords.SetNumberOfTuples(3) +triangleTCoords.InsertTuple3(0, 1, 1, 1) +triangleTCoords.InsertTuple3(1, 2, 2, 2) +triangleTCoords.InsertTuple3(2, 3, 3, 3) +aTriangle = vtk.vtkTriangle() +aTriangle.GetPointIds().SetId(0, 0) +aTriangle.GetPointIds().SetId(1, 1) +aTriangle.GetPointIds().SetId(2, 2) +aTriangleGrid = vtk.vtkUnstructuredGrid() +aTriangleGrid.Allocate(1, 1) +aTriangleGrid.InsertNextCell(aTriangle.GetCellType(), + aTriangle.GetPointIds()) +aTriangleGrid.SetPoints(trianglePoints) +aTriangleGrid.GetPointData().SetTCoords(triangleTCoords) +aTriangleMapper = vtk.vtkDataSetMapper() +aTriangleMapper.SetInput(aTriangleGrid) +aTriangleActor = vtk.vtkActor() +aTriangleActor.SetMapper(aTriangleMapper) +aTriangleActor.AddPosition(4, 0, 2) +aTriangleActor.GetProperty().SetDiffuseColor(.3, 1, .5) + +polygonPoints = vtk.vtkPoints() +polygonPoints.SetNumberOfPoints(4) +polygonPoints.InsertPoint(0, 0, 0, 0) +polygonPoints.InsertPoint(1, 1, 0, 0) +polygonPoints.InsertPoint(2, 1, 1, 0) +polygonPoints.InsertPoint(3, 0, 1, 0) +aPolygon = vtk.vtkPolygon() +aPolygon.GetPointIds().SetNumberOfIds(4) +aPolygon.GetPointIds().SetId(0, 0) +aPolygon.GetPointIds().SetId(1, 1) +aPolygon.GetPointIds().SetId(2, 2) +aPolygon.GetPointIds().SetId(3, 3) +aPolygonGrid = vtk.vtkUnstructuredGrid() +aPolygonGrid.Allocate(1, 1) +aPolygonGrid.InsertNextCell(aPolygon.GetCellType(), aPolygon.GetPointIds()) +aPolygonGrid.SetPoints(polygonPoints) +aPolygonMapper = vtk.vtkDataSetMapper() +aPolygonMapper.SetInput(aPolygonGrid) +aPolygonActor = vtk.vtkActor() +aPolygonActor.SetMapper(aPolygonMapper) +aPolygonActor.AddPosition(6, 0, 2) +aPolygonActor.GetProperty().SetDiffuseColor(1, .4, .5) + +triangleStripPoints = vtk.vtkPoints() +triangleStripPoints.SetNumberOfPoints(5) +triangleStripPoints.InsertPoint(0, 0, 1, 0) +triangleStripPoints.InsertPoint(1, 0, 0, 0) +triangleStripPoints.InsertPoint(2, 1, 1, 0) +triangleStripPoints.InsertPoint(3, 1, 0, 0) +triangleStripPoints.InsertPoint(4, 2, 1, 0) +triangleStripTCoords = vtk.vtkFloatArray() +triangleStripTCoords.SetNumberOfComponents(3) +triangleStripTCoords.SetNumberOfTuples(3) +triangleStripTCoords.InsertTuple3(0, 1, 1, 1) +triangleStripTCoords.InsertTuple3(1, 2, 2, 2) +triangleStripTCoords.InsertTuple3(2, 3, 3, 3) +triangleStripTCoords.InsertTuple3(3, 4, 4, 4) +triangleStripTCoords.InsertTuple3(4, 5, 5, 5) +aTriangleStrip = vtk.vtkTriangleStrip() +aTriangleStrip.GetPointIds().SetNumberOfIds(5) +aTriangleStrip.GetPointIds().SetId(0, 0) +aTriangleStrip.GetPointIds().SetId(1, 1) +aTriangleStrip.GetPointIds().SetId(2, 2) +aTriangleStrip.GetPointIds().SetId(3, 3) +aTriangleStrip.GetPointIds().SetId(4, 4) +aTriangleStripGrid = vtk.vtkUnstructuredGrid() +aTriangleStripGrid.Allocate(1, 1) +aTriangleStripGrid.InsertNextCell(aTriangleStrip.GetCellType(), + aTriangleStrip.GetPointIds()) +aTriangleStripGrid.SetPoints(triangleStripPoints) +aTriangleStripGrid.GetPointData().SetTCoords(triangleStripTCoords) +aTriangleStripMapper = vtk.vtkDataSetMapper() +aTriangleStripMapper.SetInput(aTriangleStripGrid) +aTriangleStripActor = vtk.vtkActor() +aTriangleStripActor.SetMapper(aTriangleStripMapper) +aTriangleStripActor.AddPosition(8, 0, 2) +aTriangleStripActor.GetProperty().SetDiffuseColor(.3, .7, 1) + +linePoints = vtk.vtkPoints() +linePoints.SetNumberOfPoints(2) +linePoints.InsertPoint(0, 0, 0, 0) +linePoints.InsertPoint(1, 1, 1, 0) +aLine = vtk.vtkLine() +aLine.GetPointIds().SetId(0, 0) +aLine.GetPointIds().SetId(1, 1) +aLineGrid = vtk.vtkUnstructuredGrid() +aLineGrid.Allocate(1, 1) +aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds()) +aLineGrid.SetPoints(linePoints) +aLineMapper = vtk.vtkDataSetMapper() +aLineMapper.SetInput(aLineGrid) +aLineActor = vtk.vtkActor() +aLineActor.SetMapper(aLineMapper) +aLineActor.AddPosition(0, 0, 4) +aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1) + +polyLinePoints = vtk.vtkPoints() +polyLinePoints.SetNumberOfPoints(3) +polyLinePoints.InsertPoint(0, 0, 0, 0) +polyLinePoints.InsertPoint(1, 1, 1, 0) +polyLinePoints.InsertPoint(2, 1, 0, 0) +aPolyLine = vtk.vtkPolyLine() +aPolyLine.GetPointIds().SetNumberOfIds(3) +aPolyLine.GetPointIds().SetId(0, 0) +aPolyLine.GetPointIds().SetId(1, 1) +aPolyLine.GetPointIds().SetId(2, 2) +aPolyLineGrid = vtk.vtkUnstructuredGrid() +aPolyLineGrid.Allocate(1, 1) +aPolyLineGrid.InsertNextCell(aPolyLine.GetCellType(), + aPolyLine.GetPointIds()) +aPolyLineGrid.SetPoints(polyLinePoints) +aPolyLineMapper = vtk.vtkDataSetMapper() +aPolyLineMapper.SetInput(aPolyLineGrid) +aPolyLineActor = vtk.vtkActor() +aPolyLineActor.SetMapper(aPolyLineMapper) +aPolyLineActor.AddPosition(2, 0, 4) +aPolyLineActor.GetProperty().SetDiffuseColor(1, 1, 1) + +vertexPoints = vtk.vtkPoints() +vertexPoints.SetNumberOfPoints(1) +vertexPoints.InsertPoint(0, 0, 0, 0) +aVertex = vtk.vtkVertex() +aVertex.GetPointIds().SetId(0, 0) +aVertexGrid = vtk.vtkUnstructuredGrid() +aVertexGrid.Allocate(1, 1) +aVertexGrid.InsertNextCell(aVertex.GetCellType(), aVertex.GetPointIds()) +aVertexGrid.SetPoints(vertexPoints) +aVertexMapper = vtk.vtkDataSetMapper() +aVertexMapper.SetInput(aVertexGrid) +aVertexActor = vtk.vtkActor() +aVertexActor.SetMapper(aVertexMapper) +aVertexActor.AddPosition(0, 0, 6) +aVertexActor.GetProperty().SetDiffuseColor(1, 1, 1) + +polyVertexPoints = vtk.vtkPoints() +polyVertexPoints.SetNumberOfPoints(3) +polyVertexPoints.InsertPoint(0, 0, 0, 0) +polyVertexPoints.InsertPoint(1, 1, 0, 0) +polyVertexPoints.InsertPoint(2, 1, 1, 0) +aPolyVertex = vtk.vtkPolyVertex() +aPolyVertex.GetPointIds().SetNumberOfIds(3) +aPolyVertex.GetPointIds().SetId(0, 0) +aPolyVertex.GetPointIds().SetId(1, 1) +aPolyVertex.GetPointIds().SetId(2, 2) +aPolyVertexGrid = vtk.vtkUnstructuredGrid() +aPolyVertexGrid.Allocate(1, 1) +aPolyVertexGrid.InsertNextCell(aPolyVertex.GetCellType(), + aPolyVertex.GetPointIds()) +aPolyVertexGrid.SetPoints(polyVertexPoints) +aPolyVertexMapper = vtk.vtkDataSetMapper() +aPolyVertexMapper.SetInput(aPolyVertexGrid) +aPolyVertexActor = vtk.vtkActor() +aPolyVertexActor.SetMapper(aPolyVertexMapper) +aPolyVertexActor.AddPosition(2, 0, 6) +aPolyVertexActor.GetProperty().SetDiffuseColor(1, 1, 1) + +# Create the usual rendering stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.SetSize(300, 150) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +ren.SetBackground(.1, .2, .4) + +ren.AddActor(aVoxelActor) +ren.AddActor(aHexahedronActor) +ren.AddActor(aTetraActor) +ren.AddActor(aWedgeActor) +ren.AddActor(aPyramidActor) +ren.AddActor(aPixelActor) +ren.AddActor(aQuadActor) +ren.AddActor(aTriangleActor) +ren.AddActor(aPolygonActor) +ren.AddActor(aTriangleStripActor) +ren.AddActor(aLineActor) +ren.AddActor(aPolyLineActor) +ren.AddActor(aVertexActor) +ren.AddActor(aPolyVertexActor) + +ren.ResetCamera() +ren.GetActiveCamera().Azimuth(30) +ren.GetActiveCamera().Elevation(20) +ren.GetActiveCamera().Dolly(2.8) +ren.ResetCameraClippingRange() + +# Render the scene and start interaction. +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/DataManipulation/Python/CreateStrip.py b/Examples/DataManipulation/Python/CreateStrip.py new file mode 100644 index 0000000..bea887b --- /dev/null +++ b/Examples/DataManipulation/Python/CreateStrip.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +# This script shows how to manually create a vtkPolyData with a +# triangle strip. + +import vtk + +# First we'll create some points. +points = vtk.vtkPoints() +points.InsertPoint(0, 0.0, 0.0, 0.0) +points.InsertPoint(1, 0.0, 1.0, 0.0) +points.InsertPoint(2, 1.0, 0.0, 0.0) +points.InsertPoint(3, 1.0, 1.0, 0.0) +points.InsertPoint(4, 2.0, 0.0, 0.0) +points.InsertPoint(5, 2.0, 1.0, 0.0) +points.InsertPoint(6, 3.0, 0.0, 0.0) +points.InsertPoint(7, 3.0, 1.0, 0.0) + +# The cell array can be thought of as a connectivity list. Here we +# specify the number of points followed by that number of point +# ids. This can be repeated as many times as there are primitives in +# the list. +strips = vtk.vtkCellArray() +strips.InsertNextCell(8) # number of points +strips.InsertCellPoint(0) +strips.InsertCellPoint(1) +strips.InsertCellPoint(2) +strips.InsertCellPoint(3) +strips.InsertCellPoint(4) +strips.InsertCellPoint(5) +strips.InsertCellPoint(6) +strips.InsertCellPoint(7) +profile = vtk.vtkPolyData() +profile.SetPoints(points) +profile.SetStrips(strips) + +map = vtk.vtkPolyDataMapper() +map.SetInput(profile) + +strip = vtk.vtkActor() +strip.SetMapper(map) +strip.GetProperty().SetColor(0.3800, 0.7000, 0.1600) + +# Create the usual rendering stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(strip) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(250, 250) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/DataManipulation/Python/FinancialField.py b/Examples/DataManipulation/Python/FinancialField.py new file mode 100644 index 0000000..ef513bd --- /dev/null +++ b/Examples/DataManipulation/Python/FinancialField.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python + +# This example demonstrates the use of fields and use of +# vtkProgrammableDataObjectSource. It creates fields the hard way (as +# compared to reading a vtk field file), but shows you how to +# interface to your own raw data. + +import os +import re +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +xAxis = "INTEREST_RATE" +yAxis = "MONTHLY_PAYMENT" +zAxis = "MONTHLY_INCOME" +scalar = "TIME_LATE" + +def getNumberFromLine(line): + patn = re.compile('[-+]{0,1}[\d.]+e?[-+\d]*', re.M) + val = patn.findall(line) + ret = [] + for i in val: + ret.append(float(i)) + return ret + +# Parse an ASCII file and manually create a field. Then construct a +# dataset from the field. +dos = vtk.vtkProgrammableDataObjectSource() + +# First define the function that will parse the data. +def parseFile(): + global VTK_DATA_ROOT, dos + + # Use Python to read an ASCII file + file = open(os.path.join(VTK_DATA_ROOT, "Data/financial.txt"), "r") + + line = file.readline() + numPts = int(getNumberFromLine(line)[0]) + + numLines = (numPts - 1)/8 + # Get the data object's field data and allocate + # room for 4, fields + fieldData = dos.GetOutput().GetFieldData() + fieldData.AllocateArrays(4) + + # read TIME_LATE - dependent variable + # search the file until an array called TIME_LATE is found + while file.readline()[:9] != "TIME_LATE": + pass + + # Create the corresponding float array + timeLate = vtk.vtkFloatArray() + timeLate.SetName("TIME_LATE") + # Read the values + for i in range(0, numLines): + val = getNumberFromLine(file.readline()) + for j in range(0, 8): + timeLate.InsertNextValue(val[j]) + # Add the array + fieldData.AddArray(timeLate) + + # MONTHLY_PAYMENT - independent variable + while file.readline()[:15] != "MONTHLY_PAYMENT": + pass + + monthlyPayment = vtk.vtkFloatArray() + monthlyPayment.SetName("MONTHLY_PAYMENT") + for i in range(0, numLines): + val = getNumberFromLine(file.readline()) + for j in range(0, 8): + monthlyPayment.InsertNextValue(val[j]) + + fieldData.AddArray(monthlyPayment) + + # UNPAID_PRINCIPLE - skip + while file.readline()[:16] != "UNPAID_PRINCIPLE": + pass + for i in range(0, numLines): + file.readline() + + # LOAN_AMOUNT - skip + while file.readline()[:11] != "LOAN_AMOUNT": + pass + for i in range(0, numLines): + file.readline() + + + # INTEREST_RATE - independent variable + while file.readline()[:13] != "INTEREST_RATE": + pass + + interestRate = vtk.vtkFloatArray() + interestRate.SetName("INTEREST_RATE") + for i in range(0, numLines): + val = getNumberFromLine(file.readline()) + for j in range(0, 8): + interestRate.InsertNextValue(val[j]) + + fieldData.AddArray(interestRate) + + # MONTHLY_INCOME - independent variable + while file.readline()[:14] != "MONTHLY_INCOME": + pass + + monthlyIncome = vtk.vtkFloatArray() + monthlyIncome.SetName("MONTHLY_INCOME") + for i in range(0, numLines): + val = getNumberFromLine(file.readline()) + for j in range(0, 8): + monthlyIncome.InsertNextValue(val[j]) + + fieldData.AddArray(monthlyIncome) + +# Arrange to call the parsing function when the programmable data +# source is executed. +dos.SetExecuteMethod(parseFile) + +# Create the dataset. + +# DataObjectToDataSetFilter can create geometry using fields from +# DataObject's FieldData +do2ds = vtk.vtkDataObjectToDataSetFilter() +do2ds.SetInputConnection(dos.GetOutputPort()) +# We are generating polygonal data +do2ds.SetDataSetTypeToPolyData() +do2ds.DefaultNormalizeOn() +# All we need is points. Assign them. +do2ds.SetPointComponent(0, xAxis, 0) +do2ds.SetPointComponent(1, yAxis, 0) +do2ds.SetPointComponent(2, zAxis, 0) + +# RearrangeFields is used to move fields between DataObject's +# FieldData, PointData and CellData. +rf = vtk.vtkRearrangeFields() +rf.SetInputConnection(do2ds.GetOutputPort()) +# Add an operation to "move TIME_LATE from DataObject's FieldData to +# PointData" +rf.AddOperation("MOVE", scalar, "DATA_OBJECT", "POINT_DATA") +# Force the filter to execute. This is need to force the pipeline +# to execute so that we can find the range of the array TIME_LATE +rf.Update() +# Set max to the second (GetRange returns [min,max]) of the "range of the +# array called scalar in the PointData of the output of rf" +max = rf.GetOutput().GetPointData().GetArray(scalar).GetRange()[1] + + +# Use an ArrayCalculator to normalize TIME_LATE +calc = vtk.vtkArrayCalculator() +calc.SetInputConnection(rf.GetOutputPort()) +# Working on point data +calc.SetAttributeModeToUsePointData() +# Map scalar to s. When setting function, we can use s to +# represent the array scalar (TIME_LATE) +calc.AddScalarVariable("s", scalar, 0) +# Divide scalar by max (applies division to all components of the array) +calc.SetFunction("s / %f"%max) +# The output array will be called resArray +calc.SetResultArrayName("resArray") + +# Use AssignAttribute to make resArray the active scalar field +aa = vtk.vtkAssignAttribute() +aa.SetInputConnection(calc.GetOutputPort()) +aa.Assign("resArray", "SCALARS", "POINT_DATA") +aa.Update() + +# construct pipeline for original population +# GaussianSplatter -> Contour -> Mapper -> Actor +popSplatter = vtk.vtkGaussianSplatter() +popSplatter.SetInputConnection(aa.GetOutputPort()) +popSplatter.SetSampleDimensions(50, 50, 50) +popSplatter.SetRadius(0.05) +popSplatter.ScalarWarpingOff() + +popSurface = vtk.vtkContourFilter() +popSurface.SetInputConnection(popSplatter.GetOutputPort()) +popSurface.SetValue(0, 0.01) + +popMapper = vtk.vtkPolyDataMapper() +popMapper.SetInputConnection(popSurface.GetOutputPort()) +popMapper.ScalarVisibilityOff() + +popActor = vtk.vtkActor() +popActor.SetMapper(popMapper) +popActor.GetProperty().SetOpacity(0.3) +popActor.GetProperty().SetColor(.9, .9, .9) + +# This is for decoration only. +def CreateAxes(): + global xAxis, yAxis, zAxis, popSplatter + + # Create axes. + popSplatter.Update() + bounds = popSplatter.GetOutput().GetBounds() + axes = vtk.vtkAxes() + axes.SetOrigin(bounds[0], bounds[2], bounds[4]) + axes.SetScaleFactor(popSplatter.GetOutput().GetLength()/5.0) + + axesTubes = vtk.vtkTubeFilter() + axesTubes.SetInputConnection(axes.GetOutputPort()) + axesTubes.SetRadius(axes.GetScaleFactor()/25.0) + axesTubes.SetNumberOfSides(6) + + axesMapper = vtk.vtkPolyDataMapper() + axesMapper.SetInputConnection(axesTubes.GetOutputPort()) + + axesActor = vtk.vtkActor() + axesActor.SetMapper(axesMapper) + + # Label the axes. + XText = vtk.vtkVectorText() + XText.SetText(xAxis) + + XTextMapper = vtk.vtkPolyDataMapper() + XTextMapper.SetInputConnection(XText.GetOutputPort()) + + XActor = vtk.vtkFollower() + XActor.SetMapper(XTextMapper) + XActor.SetScale(0.02, .02, .02) + XActor.SetPosition(0.35, -0.05, -0.05) + XActor.GetProperty().SetColor(0, 0, 0) + + YText = vtk.vtkVectorText() + YText.SetText(yAxis) + + YTextMapper = vtk.vtkPolyDataMapper() + YTextMapper.SetInputConnection(YText.GetOutputPort()) + + YActor = vtk.vtkFollower() + YActor.SetMapper(YTextMapper) + YActor.SetScale(0.02, .02, .02) + YActor.SetPosition(-0.05, 0.35, -0.05) + YActor.GetProperty().SetColor(0, 0, 0) + + ZText = vtk.vtkVectorText() + ZText.SetText(zAxis) + + ZTextMapper = vtk.vtkPolyDataMapper() + ZTextMapper.SetInputConnection(ZText.GetOutputPort()) + + ZActor = vtk.vtkFollower() + ZActor.SetMapper(ZTextMapper) + ZActor.SetScale(0.02, .02, .02) + ZActor.SetPosition(-0.05, -0.05, 0.35) + ZActor.GetProperty().SetColor(0, 0, 0) + return axesActor, XActor, YActor, ZActor + +axesActor, XActor, YActor, ZActor = CreateAxes() + +# Create the render window, renderer, interactor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.SetWindowName("vtk - Field Data") +renWin.SetSize(500, 500) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(axesActor) +ren.AddActor(XActor) +ren.AddActor(YActor) +ren.AddActor(ZActor) +ren.AddActor(popActor) +ren.SetBackground(1, 1, 1) + +# Set the default camera position +camera = vtk.vtkCamera() +camera.SetClippingRange(.274, 13.72) +camera.SetFocalPoint(0.433816, 0.333131, 0.449) +camera.SetPosition(-1.96987, 1.15145, 1.49053) +camera.SetViewUp(0.378927, 0.911821, 0.158107) +ren.SetActiveCamera(camera) +# Assign the camera to the followers. +XActor.SetCamera(camera) +YActor.SetCamera(camera) +ZActor.SetCamera(camera) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/DataManipulation/Python/marching.py b/Examples/DataManipulation/Python/marching.py new file mode 100644 index 0000000..e3c2c64 --- /dev/null +++ b/Examples/DataManipulation/Python/marching.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python + +# This example demonstrates the use of the vtkTransformPolyDataFilter +# to reposition a 3D text string. + +import vtk +from vtk.util.colors import * + +# Define a Single Cube +Scalars = vtk.vtkFloatArray() +Scalars.InsertNextValue(1.0) +Scalars.InsertNextValue(0.0) +Scalars.InsertNextValue(0.0) +Scalars.InsertNextValue(1.0) +Scalars.InsertNextValue(0.0) +Scalars.InsertNextValue(0.0) +Scalars.InsertNextValue(0.0) +Scalars.InsertNextValue(0.0) + +Points = vtk.vtkPoints() +Points.InsertNextPoint(0, 0, 0) +Points.InsertNextPoint(1, 0, 0) +Points.InsertNextPoint(1, 1, 0) +Points.InsertNextPoint(0, 1, 0) +Points.InsertNextPoint(0, 0, 1) +Points.InsertNextPoint(1, 0, 1) +Points.InsertNextPoint(1, 1, 1) +Points.InsertNextPoint(0, 1, 1) + +Ids = vtk.vtkIdList() +Ids.InsertNextId(0) +Ids.InsertNextId(1) +Ids.InsertNextId(2) +Ids.InsertNextId(3) +Ids.InsertNextId(4) +Ids.InsertNextId(5) +Ids.InsertNextId(6) +Ids.InsertNextId(7) + +Grid = vtk.vtkUnstructuredGrid() +Grid.Allocate(10, 10) +Grid.InsertNextCell(12, Ids) +Grid.SetPoints(Points) +Grid.GetPointData().SetScalars(Scalars) + +# Find the triangles that lie along the 0.5 contour in this cube. +Marching = vtk.vtkContourFilter() +Marching.SetInput(Grid) +Marching.SetValue(0, 0.5) +Marching.Update() + +# Extract the edges of the triangles just found. +triangleEdges = vtk.vtkExtractEdges() +triangleEdges.SetInputConnection(Marching.GetOutputPort()) +# Draw the edges as tubes instead of lines. Also create the associated +# mapper and actor to display the tubes. +triangleEdgeTubes = vtk.vtkTubeFilter() +triangleEdgeTubes.SetInputConnection(triangleEdges.GetOutputPort()) +triangleEdgeTubes.SetRadius(.005) +triangleEdgeTubes.SetNumberOfSides(6) +triangleEdgeTubes.UseDefaultNormalOn() +triangleEdgeTubes.SetDefaultNormal(.577, .577, .577) +triangleEdgeMapper = vtk.vtkPolyDataMapper() +triangleEdgeMapper.SetInputConnection(triangleEdgeTubes.GetOutputPort()) +triangleEdgeMapper.ScalarVisibilityOff() +triangleEdgeActor = vtk.vtkActor() +triangleEdgeActor.SetMapper(triangleEdgeMapper) +triangleEdgeActor.GetProperty().SetDiffuseColor(lamp_black) +triangleEdgeActor.GetProperty().SetSpecular(.4) +triangleEdgeActor.GetProperty().SetSpecularPower(10) + +# Shrink the triangles we found earlier. Create the associated mapper +# and actor. Set the opacity of the shrunken triangles. +aShrinker = vtk.vtkShrinkPolyData() +aShrinker.SetShrinkFactor(1) +aShrinker.SetInputConnection(Marching.GetOutputPort()) +aMapper = vtk.vtkPolyDataMapper() +aMapper.ScalarVisibilityOff() +aMapper.SetInputConnection(aShrinker.GetOutputPort()) +Triangles = vtk.vtkActor() +Triangles.SetMapper(aMapper) +Triangles.GetProperty().SetDiffuseColor(banana) +Triangles.GetProperty().SetOpacity(.6) + +# Draw a cube the same size and at the same position as the one +# created previously. Extract the edges because we only want to see +# the outline of the cube. Pass the edges through a vtkTubeFilter so +# they are displayed as tubes rather than lines. +CubeModel = vtk.vtkCubeSource() +CubeModel.SetCenter(.5, .5, .5) +Edges = vtk.vtkExtractEdges() +Edges.SetInputConnection(CubeModel.GetOutputPort()) +Tubes = vtk.vtkTubeFilter() +Tubes.SetInputConnection(Edges.GetOutputPort()) +Tubes.SetRadius(.01) +Tubes.SetNumberOfSides(6) +Tubes.UseDefaultNormalOn() +Tubes.SetDefaultNormal(.577, .577, .577) +# Create the mapper and actor to display the cube edges. +TubeMapper = vtk.vtkPolyDataMapper() +TubeMapper.SetInputConnection(Tubes.GetOutputPort()) +CubeEdges = vtk.vtkActor() +CubeEdges.SetMapper(TubeMapper) +CubeEdges.GetProperty().SetDiffuseColor(khaki) +CubeEdges.GetProperty().SetSpecular(.4) +CubeEdges.GetProperty().SetSpecularPower(10) + +# Create a sphere to use as a glyph source for vtkGlyph3D. +Sphere = vtk.vtkSphereSource() +Sphere.SetRadius(0.04) +Sphere.SetPhiResolution(20) +Sphere.SetThetaResolution(20) +# Remove the part of the cube with data values below 0.5. +ThresholdIn = vtk.vtkThresholdPoints() +ThresholdIn.SetInput(Grid) +ThresholdIn.ThresholdByUpper(.5) +# Display spheres at the vertices remaining in the cube data set after +# it was passed through vtkThresholdPoints. +Vertices = vtk.vtkGlyph3D() +Vertices.SetInputConnection(ThresholdIn.GetOutputPort()) +Vertices.SetSource(Sphere.GetOutput()) +# Create a mapper and actor to display the glyphs. +SphereMapper = vtk.vtkPolyDataMapper() +SphereMapper.SetInputConnection(Vertices.GetOutputPort()) +SphereMapper.ScalarVisibilityOff() +CubeVertices = vtk.vtkActor() +CubeVertices.SetMapper(SphereMapper) +CubeVertices.GetProperty().SetDiffuseColor(tomato) +CubeVertices.GetProperty().SetDiffuseColor(tomato) + +# Define the text for the label +caseLabel = vtk.vtkVectorText() +caseLabel.SetText("Case 1") + +# Set up a transform to move the label to a new position. +aLabelTransform = vtk.vtkTransform() +aLabelTransform.Identity() +aLabelTransform.Translate(-0.2, 0, 1.25) +aLabelTransform.Scale(.05, .05, .05) + +# Move the label to a new position. +labelTransform = vtk.vtkTransformPolyDataFilter() +labelTransform.SetTransform(aLabelTransform) +labelTransform.SetInputConnection(caseLabel.GetOutputPort()) + +# Create a mapper and actor to display the text. +labelMapper = vtk.vtkPolyDataMapper() +labelMapper.SetInputConnection(labelTransform.GetOutputPort()) + +labelActor = vtk.vtkActor() +labelActor.SetMapper(labelMapper) + +# Define the base that the cube sits on. Create its associated mapper +# and actor. Set the position of the actor. +baseModel = vtk.vtkCubeSource() +baseModel.SetXLength(1.5) +baseModel.SetYLength(.01) +baseModel.SetZLength(1.5) +baseMapper = vtk.vtkPolyDataMapper() +baseMapper.SetInputConnection(baseModel.GetOutputPort()) +base = vtk.vtkActor() +base.SetMapper(baseMapper) +base.SetPosition(.5, -0.09, .5) + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.SetSize(640, 480) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer +ren.AddActor(triangleEdgeActor) +ren.AddActor(base) +ren.AddActor(labelActor) +ren.AddActor(CubeEdges) +ren.AddActor(CubeVertices) +ren.AddActor(Triangles) + +# Set the background color. +ren.SetBackground(slate_grey) + +# This sets up the right values for case12 of the marching cubes +# algorithm (routine translated from vtktesting/mccases.tcl). +def case12(scalars, caselabel, IN, OUT): + scalars.InsertValue(0, OUT) + scalars.InsertValue(1, IN) + scalars.InsertValue(2, OUT) + scalars.InsertValue(3, IN) + scalars.InsertValue(4, IN) + scalars.InsertValue(5, IN) + scalars.InsertValue(6, OUT) + scalars.InsertValue(7, OUT) + if IN == 1: + caselabel.SetText("Case 12 - 00111010") + else: + caselabel.SetText("Case 12 - 11000101") + +# Set the scalar values for this case of marching cubes. +case12(Scalars, caseLabel, 0, 1) + +# Force the grid to update. +Grid.Modified() + +# Position the camera. +ren.ResetCamera() +ren.GetActiveCamera().Dolly(1.2) +ren.GetActiveCamera().Azimuth(30) +ren.GetActiveCamera().Elevation(20) +ren.ResetCameraClippingRange() + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/DataManipulation/Python/pointToCellData.py b/Examples/DataManipulation/Python/pointToCellData.py new file mode 100644 index 0000000..bab4523 --- /dev/null +++ b/Examples/DataManipulation/Python/pointToCellData.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python + +# This example demonstrates the conversion of point data to cell data. +# The conversion is necessary because we want to threshold data based +# on cell scalar values. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read some data with point data attributes. The data is from a +# plastic blow molding process (e.g., to make plastic bottles) and +# consists of two logical components: a mold and a parison. The +# parison is the hot plastic that is being molded, and the mold is +# clamped around the parison to form its shape. +reader = vtk.vtkUnstructuredGridReader() +reader.SetFileName(VTK_DATA_ROOT + "/Data/blow.vtk") +reader.SetScalarsName("thickness9") +reader.SetVectorsName("displacement9") + +# Convert the point data to cell data. The point data is passed +# through the filter so it can be warped. The vtkThresholdFilter then +# thresholds based on cell scalar values and extracts a portion of the +# parison whose cell scalar values lie between 0.25 and 0.75. +p2c = vtk.vtkPointDataToCellData() +p2c.SetInputConnection(reader.GetOutputPort()) +p2c.PassPointDataOn() +warp = vtk.vtkWarpVector() +warp.SetInput(p2c.GetUnstructuredGridOutput()) +thresh = vtk.vtkThreshold() +thresh.SetInputConnection(warp.GetOutputPort()) +thresh.ThresholdBetween(0.25, 0.75) +thresh.SetInputArrayToProcess(1, 0, 0, 0, "thickness9") +#thresh.SetAttributeModeToUseCellData() + +# This is used to extract the mold from the parison. +connect = vtk.vtkConnectivityFilter() +connect.SetInputConnection(thresh.GetOutputPort()) +connect.SetExtractionModeToSpecifiedRegions() +connect.AddSpecifiedRegion(0) +connect.AddSpecifiedRegion(1) +moldMapper = vtk.vtkDataSetMapper() +moldMapper.SetInputConnection(reader.GetOutputPort()) +moldMapper.ScalarVisibilityOff() +moldActor = vtk.vtkActor() +moldActor.SetMapper(moldMapper) +moldActor.GetProperty().SetColor(.2, .2, .2) +moldActor.GetProperty().SetRepresentationToWireframe() + +# The threshold filter has been used to extract the parison. +connect2 = vtk.vtkConnectivityFilter() +connect2.SetInputConnection(thresh.GetOutputPort()) +parison = vtk.vtkGeometryFilter() +parison.SetInputConnection(connect2.GetOutputPort()) +normals2 = vtk.vtkPolyDataNormals() +normals2.SetInputConnection(parison.GetOutputPort()) +normals2.SetFeatureAngle(60) +lut = vtk.vtkLookupTable() +lut.SetHueRange(0.0, 0.66667) +parisonMapper = vtk.vtkPolyDataMapper() +parisonMapper.SetInputConnection(normals2.GetOutputPort()) +parisonMapper.SetLookupTable(lut) +parisonMapper.SetScalarRange(0.12, 1.0) +parisonActor = vtk.vtkActor() +parisonActor.SetMapper(parisonMapper) + +# We generate some contour lines on the parison. +cf = vtk.vtkContourFilter() +cf.SetInputConnection(connect2.GetOutputPort()) +cf.SetValue(0, .5) +contourMapper = vtk.vtkPolyDataMapper() +contourMapper.SetInputConnection(cf.GetOutputPort()) +contours = vtk.vtkActor() +contours.SetMapper(contourMapper) + +# Create graphics stuff +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(moldActor) +ren.AddActor(parisonActor) +ren.AddActor(contours) + +ren.ResetCamera() +ren.GetActiveCamera().Azimuth(60) +ren.GetActiveCamera().Roll(-90) +ren.GetActiveCamera().Dolly(2) +ren.ResetCameraClippingRange() + +ren.SetBackground(1, 1, 1) +renWin.SetSize(750, 400) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/DataManipulation/Tcl/Arrays.tcl b/Examples/DataManipulation/Tcl/Arrays.tcl new file mode 100644 index 0000000..6948903 --- /dev/null +++ b/Examples/DataManipulation/Tcl/Arrays.tcl @@ -0,0 +1,88 @@ +# This example demonstrate the use of VTK data arrays as attribute +# data as well as field data. It creates geometry (vtkPolyData) as +# well as attribute data explicitly. + +package require vtk +package require vtkinteraction + +# Create a float array which represents the points. +vtkFloatArray pcoords +# Note that by default, an array has 1 component. +# We have to change it to 3 for points +pcoords SetNumberOfComponents 3 +# We ask pcoords to allocate room for at least 4 tuples +# and set the number of tuples to 4. +pcoords SetNumberOfTuples 4 +# Assign each tuple. There are 5 specialized versions of SetTuple: +# SetTuple1 SetTuple2 SetTuple3 SetTuple4 SetTuple9 +# These take 1, 2, 3, 4 and 9 components respectively. +pcoords SetTuple3 0 0.0 0.0 0.0 +pcoords SetTuple3 1 0.0 1.0 0.0 +pcoords SetTuple3 2 1.0 0.0 0.0 +pcoords SetTuple3 3 1.0 1.0 0.0 + +# Create vtkPoints and assign pcoords as the internal data array. +vtkPoints points +points SetData pcoords + +# Create the cells. In this case, a triangle strip with 2 triangles +# (which can be represented by 4 points) +vtkCellArray strips +strips InsertNextCell 4 +strips InsertCellPoint 0 +strips InsertCellPoint 1 +strips InsertCellPoint 2 +strips InsertCellPoint 3 + +# Create an integer array with 4 tuples. Note that when using +# InsertNextValue (or InsertNextTuple1 which is equivalent in +# this situation), the array will expand automatically +vtkIntArray temperature +temperature SetName "Temperature" +temperature InsertNextValue 10 +temperature InsertNextValue 20 +temperature InsertNextValue 30 +temperature InsertNextValue 40 + +# Create a double array. +vtkDoubleArray vorticity +vorticity SetName "Vorticity" +vorticity InsertNextValue 2.7 +vorticity InsertNextValue 4.1 +vorticity InsertNextValue 5.3 +vorticity InsertNextValue 3.4 + +# Create the dataset. In this case, we create a vtkPolyData +vtkPolyData polydata +# Assign points and cells +polydata SetPoints points +polydata SetStrips strips +# Assign scalars +[polydata GetPointData] SetScalars temperature +# Add the vorticity array. In this example, this field +# is not used. +[polydata GetPointData] AddArray vorticity + +# Create the mapper and set the appropriate scalar range +# (default is (0,1) +vtkPolyDataMapper mapper +mapper SetInput polydata +mapper SetScalarRange 0 40 + +# Create an actor. +vtkActor actor +actor SetMapper mapper + +# Create the rendering objects. +vtkRenderer ren +ren AddActor actor + +vtkRenderWindow renWin +renWin AddRenderer ren + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . \ No newline at end of file diff --git a/Examples/DataManipulation/Tcl/BuildUGrid.tcl b/Examples/DataManipulation/Tcl/BuildUGrid.tcl new file mode 100644 index 0000000..742aaea --- /dev/null +++ b/Examples/DataManipulation/Tcl/BuildUGrid.tcl @@ -0,0 +1,383 @@ +# This example shows how to manually construct unstructured grids using +# Tcl. Unstructured grids require explicit point and cell representations, +# so every point and cell must be created, and then added to the +# vtkUnstructuredGrid instance. +# + +package require vtk +package require vtkinteraction + +# Create several unstructured grids each containing a cell of a different type. +vtkPoints voxelPoints + voxelPoints SetNumberOfPoints 8 + voxelPoints InsertPoint 0 0 0 0 + voxelPoints InsertPoint 1 1 0 0 + voxelPoints InsertPoint 2 0 1 0 + voxelPoints InsertPoint 3 1 1 0 + voxelPoints InsertPoint 4 0 0 1 + voxelPoints InsertPoint 5 1 0 1 + voxelPoints InsertPoint 6 0 1 1 + voxelPoints InsertPoint 7 1 1 1 +vtkVoxel aVoxel + [aVoxel GetPointIds] SetId 0 0 + [aVoxel GetPointIds] SetId 1 1 + [aVoxel GetPointIds] SetId 2 2 + [aVoxel GetPointIds] SetId 3 3 + [aVoxel GetPointIds] SetId 4 4 + [aVoxel GetPointIds] SetId 5 5 + [aVoxel GetPointIds] SetId 6 6 + [aVoxel GetPointIds] SetId 7 7 +vtkUnstructuredGrid aVoxelGrid + aVoxelGrid Allocate 1 1 + aVoxelGrid InsertNextCell [aVoxel GetCellType] [aVoxel GetPointIds] + aVoxelGrid SetPoints voxelPoints +vtkDataSetMapper aVoxelMapper + aVoxelMapper SetInput aVoxelGrid +vtkActor aVoxelActor + aVoxelActor SetMapper aVoxelMapper + [aVoxelActor GetProperty] SetDiffuseColor 1 0 0 + +vtkPoints hexahedronPoints + hexahedronPoints SetNumberOfPoints 8 + hexahedronPoints InsertPoint 0 0 0 0 + hexahedronPoints InsertPoint 1 1 0 0 + hexahedronPoints InsertPoint 2 1 1 0 + hexahedronPoints InsertPoint 3 0 1 0 + hexahedronPoints InsertPoint 4 0 0 1 + hexahedronPoints InsertPoint 5 1 0 1 + hexahedronPoints InsertPoint 6 1 1 1 + hexahedronPoints InsertPoint 7 0 1 1 +vtkHexahedron aHexahedron + [aHexahedron GetPointIds] SetId 0 0 + [aHexahedron GetPointIds] SetId 1 1 + [aHexahedron GetPointIds] SetId 2 2 + [aHexahedron GetPointIds] SetId 3 3 + [aHexahedron GetPointIds] SetId 4 4 + [aHexahedron GetPointIds] SetId 5 5 + [aHexahedron GetPointIds] SetId 6 6 + [aHexahedron GetPointIds] SetId 7 7 +vtkUnstructuredGrid aHexahedronGrid + aHexahedronGrid Allocate 1 1 + aHexahedronGrid InsertNextCell [aHexahedron GetCellType] [aHexahedron GetPointIds] + aHexahedronGrid SetPoints hexahedronPoints +vtkDataSetMapper aHexahedronMapper + aHexahedronMapper SetInput aHexahedronGrid +vtkActor aHexahedronActor + aHexahedronActor SetMapper aHexahedronMapper + aHexahedronActor AddPosition 2 0 0 + [aHexahedronActor GetProperty] SetDiffuseColor 1 1 0 + +vtkPoints tetraPoints + tetraPoints SetNumberOfPoints 4 + tetraPoints InsertPoint 0 0 0 0 + tetraPoints InsertPoint 1 1 0 0 + tetraPoints InsertPoint 2 .5 1 0 + tetraPoints InsertPoint 3 .5 .5 1 +vtkTetra aTetra + [aTetra GetPointIds] SetId 0 0 + [aTetra GetPointIds] SetId 1 1 + [aTetra GetPointIds] SetId 2 2 + [aTetra GetPointIds] SetId 3 3 +vtkUnstructuredGrid aTetraGrid + aTetraGrid Allocate 1 1 + aTetraGrid InsertNextCell [aTetra GetCellType] [aTetra GetPointIds] + aTetraGrid SetPoints tetraPoints +vtkDataSetMapper aTetraMapper + aTetraMapper SetInput aTetraGrid +vtkActor aTetraActor + aTetraActor SetMapper aTetraMapper + aTetraActor AddPosition 4 0 0 + [aTetraActor GetProperty] SetDiffuseColor 0 1 0 + +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 6 + wedgePoints InsertPoint 0 0 1 0 + wedgePoints InsertPoint 1 0 0 0 + wedgePoints InsertPoint 2 0 .5 .5 + wedgePoints InsertPoint 3 1 1 0 + wedgePoints InsertPoint 4 1 0 0 + wedgePoints InsertPoint 5 1 .5 .5 +vtkWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeGrid +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + aWedgeActor AddPosition 6 0 0 + [aWedgeActor GetProperty] SetDiffuseColor 0 1 1 + +vtkPoints pyramidPoints + pyramidPoints SetNumberOfPoints 5 + pyramidPoints InsertPoint 0 0 0 0 + pyramidPoints InsertPoint 1 1 0 0 + pyramidPoints InsertPoint 2 1 1 0 + pyramidPoints InsertPoint 3 0 1 0 + pyramidPoints InsertPoint 4 .5 .5 1 +vtkPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyramidPoints +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + aPyramidActor AddPosition 8 0 0 + [aPyramidActor GetProperty] SetDiffuseColor 1 0 1 + +vtkPoints pixelPoints + pixelPoints SetNumberOfPoints 4 + pixelPoints InsertPoint 0 0 0 0 + pixelPoints InsertPoint 1 1 0 0 + pixelPoints InsertPoint 2 0 1 0 + pixelPoints InsertPoint 3 1 1 0 +vtkPixel aPixel + [aPixel GetPointIds] SetId 0 0 + [aPixel GetPointIds] SetId 1 1 + [aPixel GetPointIds] SetId 2 2 + [aPixel GetPointIds] SetId 3 3 +vtkUnstructuredGrid aPixelGrid + aPixelGrid Allocate 1 1 + aPixelGrid InsertNextCell [aPixel GetCellType] [aPixel GetPointIds] + aPixelGrid SetPoints pixelPoints +vtkDataSetMapper aPixelMapper + aPixelMapper SetInput aPixelGrid +vtkActor aPixelActor + aPixelActor SetMapper aPixelMapper + aPixelActor AddPosition 0 0 2 + [aPixelActor GetProperty] SetDiffuseColor 0 1 1 + +vtkPoints quadPoints + quadPoints SetNumberOfPoints 4 + quadPoints InsertPoint 0 0 0 0 + quadPoints InsertPoint 1 1 0 0 + quadPoints InsertPoint 2 1 1 0 + quadPoints InsertPoint 3 0 1 0 +vtkQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + aQuadActor AddPosition 2 0 2 + [aQuadActor GetProperty] SetDiffuseColor 1 0 1 + +vtkPoints trianglePoints + trianglePoints SetNumberOfPoints 3 + trianglePoints InsertPoint 0 0 0 0 + trianglePoints InsertPoint 1 1 0 0 + trianglePoints InsertPoint 2 .5 .5 0 +vtkFloatArray triangleTCoords + triangleTCoords SetNumberOfComponents 3 + triangleTCoords SetNumberOfTuples 3 + triangleTCoords InsertTuple3 0 1 1 1 + triangleTCoords InsertTuple3 1 2 2 2 + triangleTCoords InsertTuple3 2 3 3 3 +vtkTriangle aTriangle + [aTriangle GetPointIds] SetId 0 0 + [aTriangle GetPointIds] SetId 1 1 + [aTriangle GetPointIds] SetId 2 2 +vtkUnstructuredGrid aTriangleGrid + aTriangleGrid Allocate 1 1 + aTriangleGrid InsertNextCell [aTriangle GetCellType] [aTriangle GetPointIds] + aTriangleGrid SetPoints trianglePoints + [aTriangleGrid GetPointData] SetTCoords triangleTCoords +vtkDataSetMapper aTriangleMapper + aTriangleMapper SetInput aTriangleGrid +vtkActor aTriangleActor + aTriangleActor SetMapper aTriangleMapper + aTriangleActor AddPosition 4 0 2 + [aTriangleActor GetProperty] SetDiffuseColor .3 1 .5 + +vtkPoints polygonPoints + polygonPoints SetNumberOfPoints 4 + polygonPoints InsertPoint 0 0 0 0 + polygonPoints InsertPoint 1 1 0 0 + polygonPoints InsertPoint 2 1 1 0 + polygonPoints InsertPoint 3 0 1 0 +vtkPolygon aPolygon + [aPolygon GetPointIds] SetNumberOfIds 4 + [aPolygon GetPointIds] SetId 0 0 + [aPolygon GetPointIds] SetId 1 1 + [aPolygon GetPointIds] SetId 2 2 + [aPolygon GetPointIds] SetId 3 3 +vtkUnstructuredGrid aPolygonGrid + aPolygonGrid Allocate 1 1 + aPolygonGrid InsertNextCell [aPolygon GetCellType] [aPolygon GetPointIds] + aPolygonGrid SetPoints polygonPoints +vtkDataSetMapper aPolygonMapper + aPolygonMapper SetInput aPolygonGrid +vtkActor aPolygonActor + aPolygonActor SetMapper aPolygonMapper + aPolygonActor AddPosition 6 0 2 + [aPolygonActor GetProperty] SetDiffuseColor 1 .4 .5 + +vtkPoints triangleStripPoints + triangleStripPoints SetNumberOfPoints 5 + triangleStripPoints InsertPoint 0 0 1 0 + triangleStripPoints InsertPoint 1 0 0 0 + triangleStripPoints InsertPoint 2 1 1 0 + triangleStripPoints InsertPoint 3 1 0 0 + triangleStripPoints InsertPoint 4 2 1 0 +vtkFloatArray triangleStripTCoords + triangleStripTCoords SetNumberOfComponents 3 + triangleStripTCoords SetNumberOfTuples 3 + triangleStripTCoords InsertTuple3 0 1 1 1 + triangleStripTCoords InsertTuple3 1 2 2 2 + triangleStripTCoords InsertTuple3 2 3 3 3 + triangleStripTCoords InsertTuple3 3 4 4 4 + triangleStripTCoords InsertTuple3 4 5 5 5 +vtkTriangleStrip aTriangleStrip + [aTriangleStrip GetPointIds] SetNumberOfIds 5 + [aTriangleStrip GetPointIds] SetId 0 0 + [aTriangleStrip GetPointIds] SetId 1 1 + [aTriangleStrip GetPointIds] SetId 2 2 + [aTriangleStrip GetPointIds] SetId 3 3 + [aTriangleStrip GetPointIds] SetId 4 4 +vtkUnstructuredGrid aTriangleStripGrid + aTriangleStripGrid Allocate 1 1 + aTriangleStripGrid InsertNextCell [aTriangleStrip GetCellType] [aTriangleStrip GetPointIds] + aTriangleStripGrid SetPoints triangleStripPoints + [aTriangleStripGrid GetPointData] SetTCoords triangleStripTCoords +vtkDataSetMapper aTriangleStripMapper + aTriangleStripMapper SetInput aTriangleStripGrid +vtkActor aTriangleStripActor + aTriangleStripActor SetMapper aTriangleStripMapper + aTriangleStripActor AddPosition 8 0 2 + [aTriangleStripActor GetProperty] SetDiffuseColor .3 .7 1 + +vtkPoints linePoints + linePoints SetNumberOfPoints 2 + linePoints InsertPoint 0 0 0 0 + linePoints InsertPoint 1 1 1 0 +vtkLine aLine + [aLine GetPointIds] SetId 0 0 + [aLine GetPointIds] SetId 1 1 +vtkUnstructuredGrid aLineGrid + aLineGrid Allocate 1 1 + aLineGrid InsertNextCell [aLine GetCellType] [aLine GetPointIds] + aLineGrid SetPoints linePoints +vtkDataSetMapper aLineMapper + aLineMapper SetInput aLineGrid +vtkActor aLineActor + aLineActor SetMapper aLineMapper + aLineActor AddPosition 0 0 4 + [aLineActor GetProperty] SetDiffuseColor .2 1 1 + +vtkPoints polyLinePoints + polyLinePoints SetNumberOfPoints 3 + polyLinePoints InsertPoint 0 0 0 0 + polyLinePoints InsertPoint 1 1 1 0 + polyLinePoints InsertPoint 2 1 0 0 +vtkPolyLine aPolyLine + [aPolyLine GetPointIds] SetNumberOfIds 3 + [aPolyLine GetPointIds] SetId 0 0 + [aPolyLine GetPointIds] SetId 1 1 + [aPolyLine GetPointIds] SetId 2 2 +vtkUnstructuredGrid aPolyLineGrid + aPolyLineGrid Allocate 1 1 + aPolyLineGrid InsertNextCell [aPolyLine GetCellType] [aPolyLine GetPointIds] + aPolyLineGrid SetPoints polyLinePoints +vtkDataSetMapper aPolyLineMapper + aPolyLineMapper SetInput aPolyLineGrid +vtkActor aPolyLineActor + aPolyLineActor SetMapper aPolyLineMapper + aPolyLineActor AddPosition 2 0 4 + [aPolyLineActor GetProperty] SetDiffuseColor 1 1 1 + +vtkPoints vertexPoints + vertexPoints SetNumberOfPoints 1 + vertexPoints InsertPoint 0 0 0 0 +vtkVertex aVertex + [aVertex GetPointIds] SetId 0 0 +vtkUnstructuredGrid aVertexGrid + aVertexGrid Allocate 1 1 + aVertexGrid InsertNextCell [aVertex GetCellType] [aVertex GetPointIds] + aVertexGrid SetPoints vertexPoints +vtkDataSetMapper aVertexMapper + aVertexMapper SetInput aVertexGrid +vtkActor aVertexActor + aVertexActor SetMapper aVertexMapper + aVertexActor AddPosition 0 0 6 + [aVertexActor GetProperty] SetDiffuseColor 1 1 1 + +vtkPoints polyVertexPoints + polyVertexPoints SetNumberOfPoints 3 + polyVertexPoints InsertPoint 0 0 0 0 + polyVertexPoints InsertPoint 1 1 0 0 + polyVertexPoints InsertPoint 2 1 1 0 +vtkPolyVertex aPolyVertex + [aPolyVertex GetPointIds] SetNumberOfIds 3 + [aPolyVertex GetPointIds] SetId 0 0 + [aPolyVertex GetPointIds] SetId 1 1 + [aPolyVertex GetPointIds] SetId 2 2 +vtkUnstructuredGrid aPolyVertexGrid + aPolyVertexGrid Allocate 1 1 + aPolyVertexGrid InsertNextCell [aPolyVertex GetCellType] [aPolyVertex GetPointIds] + aPolyVertexGrid SetPoints polyVertexPoints +vtkDataSetMapper aPolyVertexMapper + aPolyVertexMapper SetInput aPolyVertexGrid +vtkActor aPolyVertexActor + aPolyVertexActor SetMapper aPolyVertexMapper + aPolyVertexActor AddPosition 2 0 6 + [aPolyVertexActor GetProperty] SetDiffuseColor 1 1 1 + +# Create the usual rendering stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 300 150 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground .1 .2 .4 + +ren1 AddActor aVoxelActor +ren1 AddActor aHexahedronActor +ren1 AddActor aTetraActor +ren1 AddActor aWedgeActor +ren1 AddActor aPyramidActor +ren1 AddActor aPixelActor +ren1 AddActor aQuadActor +ren1 AddActor aTriangleActor +ren1 AddActor aPolygonActor +ren1 AddActor aTriangleStripActor +ren1 AddActor aLineActor +ren1 AddActor aPolyLineActor +ren1 AddActor aVertexActor +ren1 AddActor aPolyVertexActor + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Dolly 2.8 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . diff --git a/Examples/DataManipulation/Tcl/CreateStrip.tcl b/Examples/DataManipulation/Tcl/CreateStrip.tcl new file mode 100644 index 0000000..101a49f --- /dev/null +++ b/Examples/DataManipulation/Tcl/CreateStrip.tcl @@ -0,0 +1,68 @@ +# This script shows how to manually create a vtkPolyData with a +# triangle strip. + +package require vtk +package require vtkinteraction + +# First we'll create some points. +# +vtkPoints points + points InsertPoint 0 0.0 0.0 0.0 + points InsertPoint 1 0.0 1.0 0.0 + points InsertPoint 2 1.0 0.0 0.0 + points InsertPoint 3 1.0 1.0 0.0 + points InsertPoint 4 2.0 0.0 0.0 + points InsertPoint 5 2.0 1.0 0.0 + points InsertPoint 6 3.0 0.0 0.0 + points InsertPoint 7 3.0 1.0 0.0 + +# The cell array can be thought of as a connectivity list. +# Here we specify the number of points followed by that number of +# point ids. This can be repeated as many times as there are +# primitives in the list. +# +vtkCellArray strips + strips InsertNextCell 8;#number of points + strips InsertCellPoint 0 + strips InsertCellPoint 1 + strips InsertCellPoint 2 + strips InsertCellPoint 3 + strips InsertCellPoint 4 + strips InsertCellPoint 5 + strips InsertCellPoint 6 + strips InsertCellPoint 7 +vtkPolyData profile + profile SetPoints points + profile SetStrips strips + +vtkPolyDataMapper map + map SetInput profile + +vtkActor strip + strip SetMapper map + [strip GetProperty] SetColor 0.3800 0.7000 0.1600 + +# Create the usual rendering stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor strip + +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/DataManipulation/Tcl/FinancialField.tcl b/Examples/DataManipulation/Tcl/FinancialField.tcl new file mode 100644 index 0000000..d02c9c8 --- /dev/null +++ b/Examples/DataManipulation/Tcl/FinancialField.tcl @@ -0,0 +1,263 @@ +# This example demonstrates the use of fields and use of +# vtkProgrammableDataObjectSource. It creates fields the hard way +# (as compared to reading a vtk field file), but shows you how to +# interface to your own raw data. + +package require vtk +package require vtkinteraction + +set xAxis INTEREST_RATE +set yAxis MONTHLY_PAYMENT +set zAxis MONTHLY_INCOME +set scalar TIME_LATE + +# Parse an ascii file and manually create a field. Then construct a +# dataset from the field. +vtkProgrammableDataObjectSource dos +dos SetExecuteMethod parseFile + +proc parseFile {} { + global VTK_DATA_ROOT + + # Use Tcl to read an ascii file + set file [open "$VTK_DATA_ROOT/Data/financial.txt" r] + set line [gets $file] + scan $line "%*s %d" numPts + set numLines [expr (($numPts - 1) / 8) + 1 ] + + # Get the data object's field data and allocate + # room for 4 fields + set fieldData [[dos GetOutput] GetFieldData] + $fieldData AllocateArrays 4 + + # read TIME_LATE - dependent variable + # search the file until an array called TIME_LATE is found + while { [gets $file arrayName] == 0 } {} + # Create the corresponding float array + vtkFloatArray timeLate + timeLate SetName TIME_LATE + # Read the values + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {timeLate InsertNextValue $v($j)} + } + # Add the array + $fieldData AddArray timeLate + + # MONTHLY_PAYMENT - independent variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray monthlyPayment + monthlyPayment SetName MONTHLY_PAYMENT + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {monthlyPayment InsertNextValue $v($j)} + } + $fieldData AddArray monthlyPayment + + # UNPAID_PRINCIPLE - skip + while { [gets $file arrayName] == 0 } {} + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + } + + # LOAN_AMOUNT - skip + while { [gets $file arrayName] == 0 } {} + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + } + + # INTEREST_RATE - independnet variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray interestRate + interestRate SetName INTEREST_RATE + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {interestRate InsertNextValue $v($j)} + } + $fieldData AddArray interestRate + + # MONTHLY_INCOME - independent variable + while { [gets $file arrayName] == 0 } {} + vtkIntArray monthlyIncome + monthlyIncome SetName MONTHLY_INCOME + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%d %d %d %d %d %d %d %d" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {monthlyIncome InsertNextValue $v($j)} + } + $fieldData AddArray monthlyIncome + +} + +# Create the dataset. +# DataObjectToDataSetFilter can create geometry using +# fields from DataObject's FieldData +vtkDataObjectToDataSetFilter do2ds +do2ds SetInputConnection [dos GetOutputPort] +# We are generating polygonal data +do2ds SetDataSetTypeToPolyData +do2ds DefaultNormalizeOn +# All we need is points. Assign them. +do2ds SetPointComponent 0 $xAxis 0 +do2ds SetPointComponent 1 $yAxis 0 +do2ds SetPointComponent 2 $zAxis 0 + +# RearrangeFields is used to move fields between DataObject's +# FieldData, PointData and CellData. +vtkRearrangeFields rf +rf SetInputConnection [do2ds GetOutputPort] +# Add an operation to "move TIME_LATE from DataObject's FieldData to +# PointData" +rf AddOperation MOVE $scalar DATA_OBJECT POINT_DATA +# Force the filter to execute. This is need to force the pipeline +# to execute so that we can find the range of the array TIME_LATE +rf Update +# Set max to the second (GetRange return [min,max]) of the "range of the +# array called $scalar in the PointData of the output of rf" +set max [lindex [[[[rf GetOutput] GetPointData] GetArray $scalar] GetRange 0] 1] + +# Use an ArrayCalculator to normalize TIME_LATE +vtkArrayCalculator calc +calc SetInputConnection [rf GetOutputPort] +# Working on point data +calc SetAttributeModeToUsePointData +# Map $scalar to s. When setting function, we can use s to +# represent the array $scalar (TIME_LATE) +calc AddScalarVariable s $scalar 0 +# Divide $scalar by $max (applies division to all components of the array) +calc SetFunction "s / $max" +# The output array will be called resArray +calc SetResultArrayName resArray + +# Use AssignAttribute to make resArray the active scalar field +vtkAssignAttribute aa +aa SetInputConnection [calc GetOutputPort] +aa Assign resArray SCALARS POINT_DATA +aa Update + +# construct pipeline for original population +# GaussianSplatter -> Contour -> Mapper -> Actor +vtkGaussianSplatter popSplatter +popSplatter SetInputConnection [aa GetOutputPort] +popSplatter SetSampleDimensions 50 50 50 +popSplatter SetRadius 0.05 +popSplatter ScalarWarpingOff + +vtkContourFilter popSurface +popSurface SetInputConnection [popSplatter GetOutputPort] +popSurface SetValue 0 0.01 + +vtkPolyDataMapper popMapper +popMapper SetInputConnection [popSurface GetOutputPort] +popMapper ScalarVisibilityOff + +vtkActor popActor +popActor SetMapper popMapper +[popActor GetProperty] SetOpacity 0.3 +[popActor GetProperty] SetColor .9 .9 .9 + +# This is for decoration only. +proc CreateAxes {} { + global xAxis yAxis zAxis + # Create axes. + popSplatter Update + set bounds [[popSplatter GetOutput] GetBounds] + vtkAxes axes + axes SetOrigin [lindex $bounds 0] [lindex $bounds 2] [lindex $bounds 4] + axes SetScaleFactor [expr [[popSplatter GetOutput] GetLength]/5.0] + + vtkTubeFilter axesTubes + axesTubes SetInputConnection [axes GetOutputPort] + axesTubes SetRadius [expr [axes GetScaleFactor]/25.0] + axesTubes SetNumberOfSides 6 + + vtkPolyDataMapper axesMapper + axesMapper SetInputConnection [axesTubes GetOutputPort] + + vtkActor axesActor + axesActor SetMapper axesMapper + + # Label the axes. + vtkVectorText XText + XText SetText $xAxis + + vtkPolyDataMapper XTextMapper + XTextMapper SetInputConnection [XText GetOutputPort] + + vtkFollower XActor + XActor SetMapper XTextMapper + XActor SetScale 0.02 .02 .02 + XActor SetPosition 0.35 -0.05 -0.05 + [XActor GetProperty] SetColor 0 0 0 + + vtkVectorText YText + YText SetText $yAxis + + vtkPolyDataMapper YTextMapper + YTextMapper SetInputConnection [YText GetOutputPort] + + vtkFollower YActor + YActor SetMapper YTextMapper + YActor SetScale 0.02 .02 .02 + YActor SetPosition -0.05 0.35 -0.05 + [YActor GetProperty] SetColor 0 0 0 + + vtkVectorText ZText + ZText SetText $zAxis + + vtkPolyDataMapper ZTextMapper + ZTextMapper SetInputConnection [ZText GetOutputPort] + + vtkFollower ZActor + ZActor SetMapper ZTextMapper + ZActor SetScale 0.02 .02 .02 + ZActor SetPosition -0.05 -0.05 0.35 + [ZActor GetProperty] SetColor 0 0 0 +} +CreateAxes + +# Create the render window, renderer, interactor +vtkRenderer ren1 +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetWindowName "vtk - Field Data" +renWin SetSize 500 500 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor axesActor +ren1 AddActor XActor +ren1 AddActor YActor +ren1 AddActor ZActor +ren1 AddActor popActor; +ren1 SetBackground 1 1 1 + +# Set the default camera position +vtkCamera camera +camera SetClippingRange .274 13.72 +camera SetFocalPoint 0.433816 0.333131 0.449 +camera SetPosition -1.96987 1.15145 1.49053 +camera SetViewUp 0.378927 0.911821 0.158107 +ren1 SetActiveCamera camera +# Assign the camera to the followers. +XActor SetCamera camera +YActor SetCamera camera +ZActor SetCamera camera + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Examples/DataManipulation/Tcl/marching.tcl b/Examples/DataManipulation/Tcl/marching.tcl new file mode 100644 index 0000000..3ce5515 --- /dev/null +++ b/Examples/DataManipulation/Tcl/marching.tcl @@ -0,0 +1,208 @@ +# This example demonstrates the use of the vtkTransformPolyDataFilter +# to reposition a 3D text string. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction +package require vtktesting + +#define a Single Cube +vtkFloatArray Scalars + Scalars InsertNextValue 1.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 1.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + +vtkPoints Points + Points InsertNextPoint 0 0 0 + Points InsertNextPoint 1 0 0 + Points InsertNextPoint 1 1 0 + Points InsertNextPoint 0 1 0 + Points InsertNextPoint 0 0 1 + Points InsertNextPoint 1 0 1 + Points InsertNextPoint 1 1 1 + Points InsertNextPoint 0 1 1 + +vtkIdList Ids + Ids InsertNextId 0 + Ids InsertNextId 1 + Ids InsertNextId 2 + Ids InsertNextId 3 + Ids InsertNextId 4 + Ids InsertNextId 5 + Ids InsertNextId 6 + Ids InsertNextId 7 + +vtkUnstructuredGrid Grid + Grid Allocate 10 10 + Grid InsertNextCell 12 Ids + Grid SetPoints Points + [Grid GetPointData] SetScalars Scalars + +# Find the triangles that lie along the 0.5 contour in this cube. +vtkContourFilter Marching + Marching SetInput Grid + Marching SetValue 0 0.5 + Marching Update + +# Extract the edges of the triangles just found. +vtkExtractEdges triangleEdges + triangleEdges SetInputConnection [Marching GetOutputPort] +# Draw the edges as tubes instead of lines. Also create the associated +# mapper and actor to display the tubes. +vtkTubeFilter triangleEdgeTubes + triangleEdgeTubes SetInputConnection [triangleEdges GetOutputPort] + triangleEdgeTubes SetRadius .005 + triangleEdgeTubes SetNumberOfSides 6 + triangleEdgeTubes UseDefaultNormalOn + triangleEdgeTubes SetDefaultNormal .577 .577 .577 +vtkPolyDataMapper triangleEdgeMapper + triangleEdgeMapper SetInputConnection [triangleEdgeTubes GetOutputPort] + triangleEdgeMapper ScalarVisibilityOff +vtkActor triangleEdgeActor + triangleEdgeActor SetMapper triangleEdgeMapper + eval [triangleEdgeActor GetProperty] SetDiffuseColor $lamp_black + [triangleEdgeActor GetProperty] SetSpecular .4 + [triangleEdgeActor GetProperty] SetSpecularPower 10 + +# Shrink the triangles we found earlier. Create the associated mapper +# and actor. Set the opacity of the shrunken triangles. +vtkShrinkPolyData aShrinker + aShrinker SetShrinkFactor 1 + aShrinker SetInputConnection [Marching GetOutputPort] +vtkPolyDataMapper aMapper + aMapper ScalarVisibilityOff + aMapper SetInputConnection [aShrinker GetOutputPort] +vtkActor Triangles + Triangles SetMapper aMapper + eval [Triangles GetProperty] SetDiffuseColor $banana +[Triangles GetProperty] SetOpacity .6 + +# Draw a cube the same size and at the same position as the one created +# previously. Extract the edges because we only want to see the outline +# of the cube. Pass the edges through a vtkTubeFilter so they are displayed +# as tubes rather than lines. +vtkCubeSource CubeModel + CubeModel SetCenter .5 .5 .5 +vtkExtractEdges Edges + Edges SetInputConnection [CubeModel GetOutputPort] +vtkTubeFilter Tubes + Tubes SetInputConnection [Edges GetOutputPort] + Tubes SetRadius .01 + Tubes SetNumberOfSides 6 + Tubes UseDefaultNormalOn + Tubes SetDefaultNormal .577 .577 .577 +# Create the mapper and actor to display the cube edges. +vtkPolyDataMapper TubeMapper + TubeMapper SetInputConnection [Tubes GetOutputPort] +vtkActor CubeEdges + CubeEdges SetMapper TubeMapper + eval [CubeEdges GetProperty] SetDiffuseColor $khaki + [CubeEdges GetProperty] SetSpecular .4 + [CubeEdges GetProperty] SetSpecularPower 10 + +# Create a sphere to use as a glyph source for vtkGlyph3D. +vtkSphereSource Sphere + Sphere SetRadius 0.04 + Sphere SetPhiResolution 20 + Sphere SetThetaResolution 20 +# Remove the part of the cube with data values below 0.5. +vtkThresholdPoints ThresholdIn + ThresholdIn SetInput Grid + ThresholdIn ThresholdByUpper .5 +# Display spheres at the vertices remaining in the cube data set after +# it was passed through vtkThresholdPoints. +vtkGlyph3D Vertices + Vertices SetInputConnection [ThresholdIn GetOutputPort] + Vertices SetSource [Sphere GetOutput] +# Create a mapper and actor to display the glyphs. +vtkPolyDataMapper SphereMapper + SphereMapper SetInputConnection [Vertices GetOutputPort] + SphereMapper ScalarVisibilityOff +vtkActor CubeVertices + CubeVertices SetMapper SphereMapper + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + +# Define the text for the label +vtkVectorText caseLabel + caseLabel SetText "Case 1" + +# Set up a transform to move the label to a new position. +vtkTransform aLabelTransform + aLabelTransform Identity + aLabelTransform Translate -.2 0 1.25 + aLabelTransform Scale .05 .05 .05 + +# Move the label to a new position. +vtkTransformPolyDataFilter labelTransform + labelTransform SetTransform aLabelTransform + labelTransform SetInputConnection [caseLabel GetOutputPort] + +# Create a mapper and actor to display the text. +vtkPolyDataMapper labelMapper + labelMapper SetInputConnection [labelTransform GetOutputPort]; + +vtkActor labelActor + labelActor SetMapper labelMapper + +# Define the base that the cube sits on. Create its associated mapper +# and actor. Set the position of the actor. +vtkCubeSource baseModel + baseModel SetXLength 1.5 + baseModel SetYLength .01 + baseModel SetZLength 1.5 +vtkPolyDataMapper baseMapper + baseMapper SetInputConnection [baseModel GetOutputPort] +vtkActor base + base SetMapper baseMapper + base SetPosition .5 -.09 .5 + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 640 480 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer +ren1 AddActor triangleEdgeActor +ren1 AddActor base +ren1 AddActor labelActor +ren1 AddActor CubeEdges +ren1 AddActor CubeVertices +ren1 AddActor Triangles + +# Set the background color. +eval ren1 SetBackground $slate_grey + +# Set the scalar values for this case of marching cubes. +case12 Scalars 0 1 +# Force the grid to update. +Grid Modified + +# Position the camera. +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +ren1 ResetCameraClippingRange + +# Render +renWin Render + +# Set the user method (bound to key 'u') +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# Withdraw the default tk window. +wm withdraw . diff --git a/Examples/DataManipulation/Tcl/pointToCellData.tcl b/Examples/DataManipulation/Tcl/pointToCellData.tcl new file mode 100644 index 0000000..7f137ec --- /dev/null +++ b/Examples/DataManipulation/Tcl/pointToCellData.tcl @@ -0,0 +1,98 @@ +# This example demonstrates the conversion of point data to cell data. +# The conversion is necessary because we want to threshold data based +# on cell scalar values. + +package require vtk +package require vtkinteraction + +# Read some data with point data attributes. The data is from a plastic +# blow molding process (e.g., to make plastic bottles) and consists of two +# logical components: a mold and a parison. The parison is the +# hot plastic that is being molded, and the mold is clamped around the +# parison to form its shape. +vtkUnstructuredGridReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/blow.vtk" + reader SetScalarsName "thickness9" + reader SetVectorsName "displacement9" + +# Convert the point data to cell data. The point data is passed through the +# filter so it can be warped. The vtkThresholdFilter then thresholds based +# on cell scalar values and extracts a portion of the parison whose cell +# scalar values lie between 0.25 and 0.75. +vtkPointDataToCellData p2c + p2c SetInputConnection [reader GetOutputPort] + p2c PassPointDataOn +vtkWarpVector warp + warp SetInputConnection [p2c GetOutputPort] +vtkThreshold thresh + thresh SetInputConnection [warp GetOutputPort] + thresh ThresholdBetween 0.25 0.75 + thresh SetInputArrayToProcess 1 0 0 0 "thickness9" +# thresh SetAttributeModeToUseCellData + +# This is used to extract the mold from the parison. +vtkConnectivityFilter connect + connect SetInputConnection [thresh GetOutputPort] + connect SetExtractionModeToSpecifiedRegions + connect AddSpecifiedRegion 0 + connect AddSpecifiedRegion 1 +vtkDataSetMapper moldMapper + moldMapper SetInputConnection [reader GetOutputPort] + moldMapper ScalarVisibilityOff +vtkActor moldActor + moldActor SetMapper moldMapper + [moldActor GetProperty] SetColor .2 .2 .2 + [moldActor GetProperty] SetRepresentationToWireframe + +# The threshold filter has been used to extract the parison. +vtkConnectivityFilter connect2 + connect2 SetInputConnection [thresh GetOutputPort] +vtkGeometryFilter parison + parison SetInputConnection [connect2 GetOutputPort] +vtkPolyDataNormals normals2 + normals2 SetInputConnection [parison GetOutputPort] + normals2 SetFeatureAngle 60 +vtkLookupTable lut + lut SetHueRange 0.0 0.66667 +vtkPolyDataMapper parisonMapper + parisonMapper SetInputConnection [normals2 GetOutputPort] + parisonMapper SetLookupTable lut + parisonMapper SetScalarRange 0.12 1.0 +vtkActor parisonActor + parisonActor SetMapper parisonMapper + +# We generate some contour lines on the parison. +vtkContourFilter cf + cf SetInputConnection [connect2 GetOutputPort] + cf SetValue 0 .5 +vtkPolyDataMapper contourMapper + contourMapper SetInputConnection [cf GetOutputPort] +vtkActor contours + contours SetMapper contourMapper + +# Create graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor moldActor +ren1 AddActor parisonActor +ren1 AddActor contours + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 60 +[ren1 GetActiveCamera] Roll -90 +[ren1 GetActiveCamera] Dolly 2 +ren1 ResetCameraClippingRange + +ren1 SetBackground 1 1 1 +renWin SetSize 750 400 + +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Examples/GUI/Motif/CMakeLists.txt b/Examples/GUI/Motif/CMakeLists.txt new file mode 100644 index 0000000..67e40df --- /dev/null +++ b/Examples/GUI/Motif/CMakeLists.txt @@ -0,0 +1,33 @@ +IF (UNIX) + PROJECT (MotifExamples) + + INCLUDE(${CMAKE_ROOT}/Modules/CheckIncludeFileCXX.cmake) + CHECK_INCLUDE_FILE_CXX("Xm/PushB.h" HAVE_XM_PUSHB_H) + + IF (HAVE_XM_PUSHB_H) + # WARNING: The Motif library HAS to be placed BEFORE the Xt library + # brought in by VTK (see Motif FAQ item 335) + + LINK_LIBRARIES(-lXm) + + FIND_PACKAGE(VTK) + IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") + ENDIF(NOT VTK_DIR) + INCLUDE(${VTK_USE_FILE}) + + LINK_LIBRARIES( + vtkRendering + vtkGraphics + vtkImaging + vtkIO + vtkFiltering + vtkCommon + ) + + ADD_EXECUTABLE(Example1 Example1.cxx) + ADD_EXECUTABLE(Example2 Example2.cxx) + ELSE (HAVE_XM_PUSHB_H) + MESSAGE(STATUS "Could not find required Motif header Xm/PushB.h. Not building Motif examples.") + ENDIF (HAVE_XM_PUSHB_H) +ENDIF (UNIX) diff --git a/Examples/GUI/Motif/Example1.cxx b/Examples/GUI/Motif/Example1.cxx new file mode 100644 index 0000000..7f71a6d --- /dev/null +++ b/Examples/GUI/Motif/Example1.cxx @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Example1.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// include OS specific include file to mix in X code + +#include "vtkActor.h" +#include "vtkConeSource.h" +#include "vtkGlyph3D.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkXRenderWindowInteractor.h" + +#include + +void quit_cb(Widget,XtPointer,XtPointer); + +main (int argc, char *argv[]) +{ + // X window stuff + XtAppContext app; + Widget toplevel, button; + Display *display; + + // VTK stuff + vtkRenderWindow *renWin; + vtkRenderer *ren1; + vtkActor *sphereActor1, *spikeActor1; + vtkSphereSource *sphere; + vtkConeSource *cone; + vtkGlyph3D *glyph; + vtkPolyDataMapper *sphereMapper, *spikeMapper; + vtkXRenderWindowInteractor *iren; + + renWin = vtkRenderWindow::New(); + ren1 = vtkRenderer::New(); + renWin->AddRenderer(ren1); + + sphere = vtkSphereSource::New(); + sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + sphereActor1 = vtkActor::New(); + sphereActor1->SetMapper(sphereMapper); + cone = vtkConeSource::New(); + glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(sphere->GetOutputPort()); + glyph->SetSourceConnection(cone->GetOutputPort()); + glyph->SetVectorModeToUseNormal(); + glyph->SetScaleModeToScaleByVector(); + glyph->SetScaleFactor(0.25); + spikeMapper = vtkPolyDataMapper::New(); + spikeMapper->SetInputConnection(glyph->GetOutputPort()); + spikeActor1 = vtkActor::New(); + spikeActor1->SetMapper(spikeMapper); + ren1->AddActor(sphereActor1); + ren1->AddActor(spikeActor1); + ren1->SetBackground(0.4,0.1,0.2); + + // do the xwindow ui stuff + XtSetLanguageProc(NULL,NULL,NULL); + toplevel = XtVaAppInitialize(&app,"Sample",NULL,0, + &argc,argv,NULL, NULL); + + // get the display connection and give it to the renderer + display = XtDisplay(toplevel); + renWin->SetDisplayId(display); + + // We use an X specific interactor + // since we have decided to make this an X program + iren = vtkXRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + iren->Initialize(app); + + button = XtVaCreateManagedWidget("Exit", + xmPushButtonWidgetClass, + toplevel, + XmNwidth, 50, + XmNheight, 50, NULL); + + XtRealizeWidget(toplevel); + XtAddCallback(button,XmNactivateCallback,quit_cb,NULL); + XtAppMainLoop(app); +} + +// simple quit callback +void quit_cb(Widget w,XtPointer client_data, XtPointer call_data) +{ + exit(0); +} diff --git a/Examples/GUI/Motif/Example2.cxx b/Examples/GUI/Motif/Example2.cxx new file mode 100644 index 0000000..dc78e06 --- /dev/null +++ b/Examples/GUI/Motif/Example2.cxx @@ -0,0 +1,132 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Example2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// include OS specific include file to mix in X code + +#include "vtkActor.h" +#include "vtkConeSource.h" +#include "vtkGlyph3D.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkXOpenGLRenderWindow.h" +#include "vtkXRenderWindowInteractor.h" + +#include +#include + +void quit_cb(Widget,XtPointer,XtPointer); + +main (int argc, char *argv[]) +{ + // X window stuff + XtAppContext app; + Widget toplevel, form, toplevel2, vtkpw; + Widget button; + int depth; + Visual *vis; + Display *display; + Colormap col; + + // VTK stuff + vtkXOpenGLRenderWindow *renWin; + vtkRenderer *ren1; + vtkActor *sphereActor1, *spikeActor1; + vtkSphereSource *sphere; + vtkConeSource *cone; + vtkGlyph3D *glyph; + vtkPolyDataMapper *sphereMapper, *spikeMapper; + vtkXRenderWindowInteractor *iren; + + renWin = vtkXOpenGLRenderWindow::New(); + ren1 = vtkRenderer::New(); + renWin->AddRenderer(ren1); + + sphere = vtkSphereSource::New(); + sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + sphereActor1 = vtkActor::New(); + sphereActor1->SetMapper(sphereMapper); + cone = vtkConeSource::New(); + glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(sphere->GetOutputPort()); + glyph->SetSourceConnection(cone->GetOutputPort()); + glyph->SetVectorModeToUseNormal(); + glyph->SetScaleModeToScaleByVector(); + glyph->SetScaleFactor(0.25); + spikeMapper = vtkPolyDataMapper::New(); + spikeMapper->SetInputConnection(glyph->GetOutputPort()); + spikeActor1 = vtkActor::New(); + spikeActor1->SetMapper(spikeMapper); + ren1->AddActor(sphereActor1); + ren1->AddActor(spikeActor1); + ren1->SetBackground(0.4,0.1,0.2); + + // do the xwindow ui stuff + XtSetLanguageProc(NULL,NULL,NULL); + toplevel = XtVaAppInitialize(&app,"Sample",NULL,0, + &argc,argv,NULL,NULL); + + // get the display connection and give it to the renderer + display = XtDisplay(toplevel); + renWin->SetDisplayId(display); + depth = renWin->GetDesiredDepth(); + vis = renWin->GetDesiredVisual(); + col = renWin->GetDesiredColormap(); + + toplevel2 = XtVaCreateWidget("top2", + topLevelShellWidgetClass, toplevel, + XmNdepth, depth, + XmNvisual, vis, + XmNcolormap, col, + NULL); + + form = XtVaCreateWidget("form",xmFormWidgetClass, toplevel2, NULL); + vtkpw = XtVaCreateManagedWidget("vtkpw", + xmPrimitiveWidgetClass, form, + XmNwidth, 300, XmNheight, 300, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_FORM, + NULL); + button = XtVaCreateManagedWidget("Exit", + xmPushButtonWidgetClass, form, + XmNheight, 40, + XmNbottomAttachment, XmATTACH_FORM, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, vtkpw, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + NULL); + + XtAddCallback(button,XmNactivateCallback,quit_cb,NULL); + XtManageChild(form); + XtRealizeWidget(toplevel2); + XtMapWidget(toplevel2); + + // We use an X specific interactor + // since we have decided to make this an X program + iren = vtkXRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + iren->SetWidget(vtkpw); + iren->Initialize(app); + XtAppMainLoop(app); +} + +// quit when the Exit button is clicked +void quit_cb(Widget w,XtPointer client_data, XtPointer call_data) +{ + exit(0); +} diff --git a/Examples/GUI/Python/BoxWidget.py b/Examples/GUI/Python/BoxWidget.py new file mode 100644 index 0000000..734231e --- /dev/null +++ b/Examples/GUI/Python/BoxWidget.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +# Demonstrate how to use the vtkBoxWidget 3D widget. This script uses +# a 3D box widget to define a "clipping box" to clip some simple +# geometry (a mace). Make sure that you hit the "i" key to activate +# the widget. + +import vtk + +# Create a mace out of filters. +sphere = vtk.vtkSphereSource() +cone = vtk.vtkConeSource() +glyph = vtk.vtkGlyph3D() +glyph.SetInputConnection(sphere.GetOutputPort()) +glyph.SetSource(cone.GetOutput()) +glyph.SetVectorModeToUseNormal() +glyph.SetScaleModeToScaleByVector() +glyph.SetScaleFactor(0.25) + +# The sphere and spikes are appended into a single polydata. This just +# makes things simpler to manage. +apd = vtk.vtkAppendPolyData() +apd.AddInput(glyph.GetOutput()) +apd.AddInput(sphere.GetOutput()) +maceMapper = vtk.vtkPolyDataMapper() +maceMapper.SetInputConnection(apd.GetOutputPort()) +maceActor = vtk.vtkLODActor() +maceActor.SetMapper(maceMapper) +maceActor.VisibilityOn() + +# This portion of the code clips the mace with the vtkPlanes implicit +# function. The clipped region is colored green. +planes = vtk.vtkPlanes() +clipper = vtk.vtkClipPolyData() +clipper.SetInputConnection(apd.GetOutputPort()) +clipper.SetClipFunction(planes) +clipper.InsideOutOn() +selectMapper = vtk.vtkPolyDataMapper() +selectMapper.SetInputConnection(clipper.GetOutputPort()) +selectActor = vtk.vtkLODActor() +selectActor.SetMapper(selectMapper) +selectActor.GetProperty().SetColor(0, 1, 0) +selectActor.VisibilityOff() +selectActor.SetScale(1.01, 1.01, 1.01) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# The SetInteractor method is how 3D widgets are associated with the +# render window interactor. Internally, SetInteractor sets up a bunch +# of callbacks using the Command/Observer mechanism (AddObserver()). +boxWidget = vtk.vtkBoxWidget() +boxWidget.SetInteractor(iren) +boxWidget.SetPlaceFactor(1.25) + +ren.AddActor(maceActor) +ren.AddActor(selectActor) + +# Add the actors to the renderer, set the background and size +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(300, 300) + +# This callback funciton does the actual work: updates the vtkPlanes +# implicit function. This in turn causes the pipeline to update. +def SelectPolygons(object, event): + # object will be the boxWidget + global selectActor, planes + object.GetPlanes(planes) + selectActor.VisibilityOn() + +# Place the interactor initially. The input to a 3D widget is used to +# initially position and scale the widget. The "EndInteractionEvent" is +# observed which invokes the SelectPolygons callback. +boxWidget.SetInput(glyph.GetOutput()) +boxWidget.PlaceWidget() +boxWidget.AddObserver("EndInteractionEvent", SelectPolygons) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/CustomInteraction.py b/Examples/GUI/Python/CustomInteraction.py new file mode 100644 index 0000000..88925f6 --- /dev/null +++ b/Examples/GUI/Python/CustomInteraction.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python + +# This example creates a polygonal model of a cone, and then renders +# it to the screen. It also defines an interaction style by creating a +# set of Command/Observers. (Note: it is far more efficient to create +# new styles by subclassing vtkInteractorStyle. This is just an +# illustrative example.) If you really want trackball behavior, look +# at the vtkInteractorStyleTrackballCamera class. + +import vtk +import sys + +# We create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a +# visualization pipeline (it is a source process object); it produces +# data (output type is vtkPolyData) which other filters may process. +cone = vtk.vtkConeSource() +cone.SetHeight(3.0) +cone.SetRadius(1.0) +cone.SetResolution(10) + +# In this example we terminate the pipeline with a mapper process +# object. (Intermediate filters such as vtkShrinkPolyData could be +# inserted in between the source and the mapper.) We create an +# instance of vtkPolyDataMapper to map the polygonal data into +# graphics primitives. We connect the output of the cone souece to the +# input of this mapper. +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) + +# Create an actor to represent the cone. The actor orchestrates +# rendering of the mapper's graphics primitives. An actor also refers +# to properties via a vtkProperty instance, and includes an internal +# transformation matrix. We set this actor's mapper to be coneMapper +# which we created above. +coneActor = vtk.vtkActor() +coneActor.SetMapper(coneMapper) + +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is +# responsible for drawing the actors it has. We also set the +# background color here. +ren = vtk.vtkRenderer() +ren.AddActor(coneActor) +ren.SetBackground(0.1, 0.2, 0.4) + +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We +# also set the size to be 300 pixels by 300. +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.SetSize(300, 300) + +# Define custom interaction. +iren = vtk.vtkRenderWindowInteractor() +iren.SetInteractorStyle(None) +iren.SetRenderWindow(renWin) + +# Add the observers to watch for particular events. These invoke +# Python functions. +Rotating = 0 +Panning = 0 +Zooming = 0 + +# Handle the mouse button events. +def ButtonEvent(obj, event): + global Rotating, Panning, Zooming + if event == "LeftButtonPressEvent": + Rotating = 1 + elif event == "LeftButtonReleaseEvent": + Rotating = 0 + elif event == "MiddleButtonPressEvent": + Panning = 1 + elif event == "MiddleButtonReleaseEvent": + Panning = 0 + elif event == "RightButtonPressEvent": + Zooming = 1 + elif event == "RightButtonReleaseEvent": + Zooming = 0 + +# General high-level logic +def MouseMove(obj, event): + global Rotating, Panning, Zooming + global iren, renWin, ren + lastXYpos = iren.GetLastEventPosition() + lastX = lastXYpos[0] + lastY = lastXYpos[1] + + xypos = iren.GetEventPosition() + x = xypos[0] + y = xypos[1] + + center = renWin.GetSize() + centerX = center[0]/2.0 + centerY = center[1]/2.0 + + if Rotating: + Rotate(ren, ren.GetActiveCamera(), x, y, lastX, lastY, + centerX, centerY) + elif Panning: + Pan(ren, ren.GetActiveCamera(), x, y, lastX, lastY, centerX, + centerY) + elif Zooming: + Dolly(ren, ren.GetActiveCamera(), x, y, lastX, lastY, + centerX, centerY) + + +def Keypress(obj, event): + key = obj.GetKeySym() + if key == "e": + obj.InvokeEvent("DeleteAllObjects") + sys.exit() + elif key == "w": + Wireframe() + elif key =="s": + Surface() + + +# Routines that translate the events into camera motions. + +# This one is associated with the left mouse button. It translates x +# and y relative motions into camera azimuth and elevation commands. +def Rotate(renderer, camera, x, y, lastX, lastY, centerX, centerY): + camera.Azimuth(lastX-x) + camera.Elevation(lastY-y) + camera.OrthogonalizeViewUp() + renWin.Render() + + +# Pan translates x-y motion into translation of the focal point and +# position. +def Pan(renderer, camera, x, y, lastX, lastY, centerX, centerY): + FPoint = camera.GetFocalPoint() + FPoint0 = FPoint[0] + FPoint1 = FPoint[1] + FPoint2 = FPoint[2] + + PPoint = camera.GetPosition() + PPoint0 = PPoint[0] + PPoint1 = PPoint[1] + PPoint2 = PPoint[2] + + renderer.SetWorldPoint(FPoint0, FPoint1, FPoint2, 1.0) + renderer.WorldToDisplay() + DPoint = renderer.GetDisplayPoint() + focalDepth = DPoint[2] + + APoint0 = centerX+(x-lastX) + APoint1 = centerY+(y-lastY) + + renderer.SetDisplayPoint(APoint0, APoint1, focalDepth) + renderer.DisplayToWorld() + RPoint = renderer.GetWorldPoint() + RPoint0 = RPoint[0] + RPoint1 = RPoint[1] + RPoint2 = RPoint[2] + RPoint3 = RPoint[3] + + if RPoint3 != 0.0: + RPoint0 = RPoint0/RPoint3 + RPoint1 = RPoint1/RPoint3 + RPoint2 = RPoint2/RPoint3 + + camera.SetFocalPoint( (FPoint0-RPoint0)/2.0 + FPoint0, + (FPoint1-RPoint1)/2.0 + FPoint1, + (FPoint2-RPoint2)/2.0 + FPoint2) + camera.SetPosition( (FPoint0-RPoint0)/2.0 + PPoint0, + (FPoint1-RPoint1)/2.0 + PPoint1, + (FPoint2-RPoint2)/2.0 + PPoint2) + renWin.Render() + + +# Dolly converts y-motion into a camera dolly commands. +def Dolly(renderer, camera, x, y, lastX, lastY, centerX, centerY): + dollyFactor = pow(1.02,(0.5*(y-lastY))) + if camera.GetParallelProjection(): + parallelScale = camera.GetParallelScale()*dollyFactor + camera.SetParallelScale(parallelScale) + else: + camera.Dolly(dollyFactor) + renderer.ResetCameraClippingRange() + + renWin.Render() + +# Wireframe sets the representation of all actors to wireframe. +def Wireframe(): + actors = ren.GetActors() + actors.InitTraversal() + actor = actors.GetNextItem() + while actor: + actor.GetProperty().SetRepresentationToWireframe() + actor = actors.GetNextItem() + + renWin.Render() + +# Surface sets the representation of all actors to surface. +def Surface(): + actors = ren.GetActors() + actors.InitTraversal() + actor = actors.GetNextItem() + while actor: + actor.GetProperty().SetRepresentationToSurface() + actor = actors.GetNextItem() + renWin.Render() + + +iren.AddObserver("LeftButtonPressEvent", ButtonEvent) +iren.AddObserver("LeftButtonReleaseEvent", ButtonEvent) +iren.AddObserver("MiddleButtonPressEvent", ButtonEvent) +iren.AddObserver("MiddleButtonReleaseEvent", ButtonEvent) +iren.AddObserver("RightButtonPressEvent", ButtonEvent) +iren.AddObserver("RightButtonReleaseEvent", ButtonEvent) +iren.AddObserver("MouseMoveEvent", MouseMove) +iren.AddObserver("KeyPressEvent", Keypress) + + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/ImagePlaneWidget.py b/Examples/GUI/Python/ImagePlaneWidget.py new file mode 100644 index 0000000..d5591c4 --- /dev/null +++ b/Examples/GUI/Python/ImagePlaneWidget.py @@ -0,0 +1,335 @@ +#!/usr/bin/env python + +# This code is a direct translation of the Tcl code in +# ImagePlaneWidget.tcl. It could easily be written using a nice class +# to do the job but the present code should definitely make for an +# illustrative example. + +# This example demonstrates how to use the vtkImagePlaneWidget +# to probe a 3D image dataset with three orthogonal planes. +# Buttons are provided to: +# a) capture the render window display to a tiff file +# b) x,y,z buttons reset the widget to orthonormal +# positioning, set the horizontal slider to move the +# associated widget along its normal, and set the +# camera to face the widget +# c) right clicking on x,y,z buttons pops up a menu to set +# the associated widget's reslice interpolation mode + +import vtk +import Tkinter +from vtk.tk.vtkTkRenderWindowInteractor import \ + vtkTkRenderWindowInteractor +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Start by loading some data. +v16 = vtk.vtkVolume16Reader() +v16.SetDataDimensions(64, 64) +v16.SetDataByteOrderToLittleEndian() +v16.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter") +v16.SetImageRange(1, 93) +v16.SetDataSpacing(3.2, 3.2, 1.5) +v16.Update() + +xMin, xMax, yMin, yMax, zMin, zMax = v16.GetOutput().GetWholeExtent() + +spacing = v16.GetOutput().GetSpacing() +sx, sy, sz = spacing + +origin = v16.GetOutput().GetOrigin() +ox, oy, oz = origin + +# An outline is shown for context. +outline = vtk.vtkOutlineFilter() +outline.SetInputConnection(v16.GetOutputPort()) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) + +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# The shared picker enables us to use 3 planes at one time +# and gets the picking order right +picker = vtk.vtkCellPicker() +picker.SetTolerance(0.005) + +# The 3 image plane widgets are used to probe the dataset. +planeWidgetX = vtk.vtkImagePlaneWidget() +planeWidgetX.DisplayTextOn() +planeWidgetX.SetInput(v16.GetOutput()) +planeWidgetX.SetPlaneOrientationToXAxes() +planeWidgetX.SetSliceIndex(32) +planeWidgetX.SetPicker(picker) +planeWidgetX.SetKeyPressActivationValue("x") +prop1 = planeWidgetX.GetPlaneProperty() +prop1.SetColor(1, 0, 0) + +planeWidgetY = vtk.vtkImagePlaneWidget() +planeWidgetY.DisplayTextOn() +planeWidgetY.SetInput(v16.GetOutput()) +planeWidgetY.SetPlaneOrientationToYAxes() +planeWidgetY.SetSliceIndex(32) +planeWidgetY.SetPicker(picker) +planeWidgetY.SetKeyPressActivationValue("y") +prop2 = planeWidgetY.GetPlaneProperty() +prop2.SetColor(1, 1, 0) +planeWidgetY.SetLookupTable(planeWidgetX.GetLookupTable()) + +# for the z-slice, turn off texture interpolation: +# interpolation is now nearest neighbour, to demonstrate +# cross-hair cursor snapping to pixel centers +planeWidgetZ = vtk.vtkImagePlaneWidget() +planeWidgetZ.DisplayTextOn() +planeWidgetZ.SetInput(v16.GetOutput()) +planeWidgetZ.SetPlaneOrientationToZAxes() +planeWidgetZ.SetSliceIndex(46) +planeWidgetZ.SetPicker(picker) +planeWidgetZ.SetKeyPressActivationValue("z") +prop3 = planeWidgetZ.GetPlaneProperty() +prop3.SetColor(0, 0, 1) +planeWidgetZ.SetLookupTable(planeWidgetX.GetLookupTable()) + +# Create the RenderWindow and Renderer +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) + +# Add the outline actor to the renderer, set the background color and size +ren.AddActor(outlineActor) +renWin.SetSize(600, 600) +ren.SetBackground(0.1, 0.1, 0.2) + +current_widget = planeWidgetZ +mode_widget = planeWidgetZ + +# Create the GUI +# We first create the supporting functions (callbacks) for the GUI +# +# Align the camera so that it faces the desired widget +def AlignCamera(): + #global ox, oy, oz, sx, sy, sz, xMax, xMin, yMax, yMin, zMax, \ + # zMin, slice_number + #global current_widget + cx = ox+(0.5*(xMax-xMin))*sx + cy = oy+(0.5*(yMax-yMin))*sy + cz = oy+(0.5*(zMax-zMin))*sz + vx, vy, vz = 0, 0, 0 + nx, ny, nz = 0, 0, 0 + iaxis = current_widget.GetPlaneOrientation() + if iaxis == 0: + vz = -1 + nx = ox + xMax*sx + cx = ox + slice_number*sx + elif iaxis == 1: + vz = -1 + ny = oy+yMax*sy + cy = oy+slice_number*sy + else: + vy = 1 + nz = oz+zMax*sz + cz = oz+slice_number*sz + + px = cx+nx*2 + py = cy+ny*2 + pz = cz+nz*3 + + camera = ren.GetActiveCamera() + camera.SetViewUp(vx, vy, vz) + camera.SetFocalPoint(cx, cy, cz) + camera.SetPosition(px, py, pz) + camera.OrthogonalizeViewUp() + ren.ResetCameraClippingRange() + renWin.Render() + +# Capture the display and place in a tiff +def CaptureImage(): + w2i = vtk.vtkWindowToImageFilter() + writer = vtk.vtkTIFFWriter() + w2i.SetInput(renWin) + w2i.Update() + writer.SetInputConnection(w2i.GetOutputPort()) + writer.SetFileName("image.tif") + renWin.Render() + writer.Write() + + +# Align the widget back into orthonormal position, +# set the slider to reflect the widget's position, +# call AlignCamera to set the camera facing the widget +def AlignXaxis(): + global xMax, xMin, current_widget, slice_number + po = planeWidgetX.GetPlaneOrientation() + if po == 3: + planeWidgetX.SetPlaneOrientationToXAxes() + slice_number = (xMax-xMin)/2 + planeWidgetX.SetSliceIndex(slice_number) + else: + slice_number = planeWidgetX.GetSliceIndex() + + current_widget = planeWidgetX + + slice.config(from_=xMin, to=xMax) + slice.set(slice_number) + AlignCamera() + + +def AlignYaxis(): + global yMin, yMax, current_widget, slice_number + po = planeWidgetY.GetPlaneOrientation() + if po == 3: + planeWidgetY.SetPlaneOrientationToYAxes() + slice_number = (yMax-yMin)/2 + planeWidgetY.SetSliceIndex(slice_number) + else: + slice_number = planeWidgetY.GetSliceIndex() + + current_widget = planeWidgetY + + slice.config(from_=yMin, to=yMax) + slice.set(slice_number) + AlignCamera() + +def AlignZaxis(): + global yMin, yMax, current_widget, slice_number + po = planeWidgetZ.GetPlaneOrientation() + if po == 3: + planeWidgetZ.SetPlaneOrientationToZAxes() + slice_number = (zMax-zMin)/2 + planeWidgetZ.SetSliceIndex(slice_number) + else: + slice_number = planeWidgetZ.GetSliceIndex() + + current_widget = planeWidgetZ + + slice.config(from_=zMin, to=zMax) + slice.set(slice_number) + AlignCamera() + + +# Set the widget's reslice interpolation mode +# to the corresponding popup menu choice +def SetInterpolation(): + global mode_widget, mode + if mode.get() == 0: + mode_widget.TextureInterpolateOff() + else: + mode_widget.TextureInterpolateOn() + + mode_widget.SetResliceInterpolate(mode.get()) + renWin.Render() + +# Share the popup menu among buttons, keeping track of associated +# widget's interpolation mode +def buttonEvent(event, arg=None): + global mode, mode_widget, popm + if arg == 0: + mode_widget = planeWidgetX + elif arg == 1: + mode_widget = planeWidgetY + elif arg == 2: + mode_widget = planeWidgetZ + else: + return + mode.set(mode_widget.GetResliceInterpolate()) + popm.entryconfigure(arg, variable=mode) + popm.post(event.x + event.x_root, event.y + event.y_root) + +def SetSlice(sl): + global current_widget + current_widget.SetSliceIndex(int(sl)) + ren.ResetCameraClippingRange() + renWin.Render() + + +### +# Now actually create the GUI +root = Tkinter.Tk() +root.withdraw() +top = Tkinter.Toplevel(root) + +# Define a quit method that exits cleanly. +def quit(obj=root): + obj.quit() + +# Popup menu +popm = Tkinter.Menu(top, tearoff=0) +mode = Tkinter.IntVar() +mode.set(1) +popm.add_radiobutton(label="nearest", variable=mode, value=0, + command=SetInterpolation) +popm.add_radiobutton(label="linear", variable=mode, value=1, + command=SetInterpolation) +popm.add_radiobutton(label="cubic", variable=mode, value=2, + command=SetInterpolation) + +display_frame = Tkinter.Frame(top) +display_frame.pack(side="top", anchor="n", fill="both", expand="false") + +# Buttons +ctrl_buttons = Tkinter.Frame(top) +ctrl_buttons.pack(side="top", anchor="n", fill="both", expand="false") + +quit_button = Tkinter.Button(ctrl_buttons, text="Quit", command=quit) +capture_button = Tkinter.Button(ctrl_buttons, text="Tif", + command=CaptureImage) + +x_button = Tkinter.Button(ctrl_buttons, text="x", command=AlignXaxis) +y_button = Tkinter.Button(ctrl_buttons, text="y", command=AlignYaxis) +z_button = Tkinter.Button(ctrl_buttons, text="z", command=AlignZaxis) +x_button.bind("", lambda e: buttonEvent(e, 0)) +y_button.bind("", lambda e: buttonEvent(e, 1)) +z_button.bind("", lambda e: buttonEvent(e, 2)) + +for i in (quit_button, capture_button, x_button, y_button, z_button): + i.pack(side="left", expand="true", fill="both") + + +# Create the render widget +renderer_frame = Tkinter.Frame(display_frame) +renderer_frame.pack(padx=3, pady=3,side="left", anchor="n", + fill="both", expand="false") + +render_widget = vtkTkRenderWindowInteractor(renderer_frame, + rw=renWin, width=600, + height=600) +for i in (render_widget, display_frame): + i.pack(side="top", anchor="n",fill="both", expand="false") + +# Add a slice scale to browse the current slice stack +slice_number = Tkinter.IntVar() +slice_number.set(current_widget.GetSliceIndex()) +slice = Tkinter.Scale(top, from_=zMin, to=zMax, orient="horizontal", + command=SetSlice,variable=slice_number, + label="Slice") +slice.pack(fill="x", expand="false") + +# Done with the GUI. +### + +# Set the interactor for the widgets +iact = render_widget.GetRenderWindow().GetInteractor() +planeWidgetX.SetInteractor(iact) +planeWidgetX.On() +planeWidgetY.SetInteractor(iact) +planeWidgetY.On() +planeWidgetZ.SetInteractor(iact) +planeWidgetZ.On() + +# Create an initial interesting view +cam1 = ren.GetActiveCamera() +cam1.Elevation(110) +cam1.SetViewUp(0, 0, -1) +cam1.Azimuth(45) +ren.ResetCameraClippingRange() + +# Render it +render_widget.Render() + +iact.Initialize() +renWin.Render() +iact.Start() + +# Start Tkinter event loop +root.mainloop() diff --git a/Examples/GUI/Python/ImageTracerWidget.py b/Examples/GUI/Python/ImageTracerWidget.py new file mode 100644 index 0000000..eb3fb1f --- /dev/null +++ b/Examples/GUI/Python/ImageTracerWidget.py @@ -0,0 +1,293 @@ +#!/usr/bin/env python + +# initial translation from the tcl by VTK/Utilities/tcl2py.py +# further cleanup and fixes to the translation by Charl P. Botha + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# This example demonstrates how to use the vtkImageTracerWidget +# to trace on a slice of a 3D image dataset on one of its orthogonal planes. +# The button actions and key modifiers are as follows for controlling the +# widget: +# 1) left button click over the image, hold and drag draws a free hand line. +# 2) left button click and release erases the widget line, if it exists, and +# repositions the handle. +# 3) middle button click starts a snap line. The snap line can be +# terminated by clicking the middle button while depressing the ctrl key. +# 4) when tracing or snap drawing a line, if the last cursor position is +# within specified tolerance to the first handle, the widget line will form +# a closed loop with only one handle. +# 5) right button clicking and holding on any handle that is part of a snap +# line allows handle dragging. Any existing line segments are updated +# accordingly. +# 6) ctrl key + right button down on any handle will erase it. Any existing +# snap line segments are updated accordingly. If the line was formed by +# continous tracing, the line is deleted leaving one handle. +# 7) shift key + right button down on any snap line segment will insert a +# handle at the cursor position. The snap line segment is split accordingly. +# +# + +def AdjustSpline(evt, obj): + itw.GetPath(poly) + npts = itw.GetNumberOfHandles() + + if npts < 2: + imageActor2.SetInputConnection(extract.GetOutputPort()) + return + + closed = itw.GetIsClosed() + + if closed: + isw.ClosedOn() + else: + isw.ClosedOff() + imageActor2.SetInputConnection(extract.GetOutputPort()) + + isw.SetNumberOfHandles(npts) + + for i in range(0, npts): + pt = poly.GetPoints().GetPoint(i) + isw.SetHandlePosition(i, pt[0], pt[1], pt[2]) + + if closed: + isw.GetPolyData(spoly) + imageActor2.SetInputConnection(stencil.GetOutputPort()) + stencil.Update() + +def AdjustTracer(evt, obj): + npts = isw.GetNumberOfHandles() + points.SetNumberOfPoints(npts) + + for i in range(0, npts): + pt = isw.GetHandlePosition(i) + points.SetPoint(i, pt[0], pt[1], pt[2]) + + closed = isw.GetClosed() + + if closed: + isw.GetPolyData(spoly) + imageActor2.SetInputConnection(stencil.GetOutputPort()) + stencil.Update() + + itw.InitializeHandles(points) + + +# Start by loading some data. +v16 = vtk.vtkVolume16Reader() +v16.SetDataDimensions(64, 64) +v16.SetDataByteOrderToLittleEndian() +v16.SetImageRange(1, 93) +v16.SetDataSpacing(3.2, 3.2, 1.5) +v16.SetFilePrefix("%s/Data/headsq/quarter" % (VTK_DATA_ROOT,)) +v16.Update() +# + +srange = v16.GetOutput().GetScalarRange() +min = srange[0] +max = srange[1] + +diff = max-min +slope = 255.0/diff +inter = -slope*min +shift = inter/slope + +shifter = vtk.vtkImageShiftScale() +shifter.SetShift(shift) +shifter.SetScale(slope) +shifter.SetOutputScalarTypeToUnsignedChar() +shifter.SetInputConnection(v16.GetOutputPort()) +shifter.ReleaseDataFlagOff() +shifter.Update() + +# Display a y-z plane. +# +imageActor = vtk.vtkImageActor() +imageActor.SetInput(shifter.GetOutput()) +imageActor.VisibilityOn() +imageActor.SetDisplayExtent(31, 31, 0, 63, 0, 92) +imageActor.InterpolateOff() +# + +spc = shifter.GetOutput().GetSpacing() +orig = shifter.GetOutput().GetOrigin() +x0 = orig[0] +xspc = spc[0] +pos = x0+xspc*31.0 + +# An alternative would be to formulate position in this case by: +# set bounds [imageActor GetBounds] +# set pos [lindex $bounds 0] +# +# + +ren = vtk.vtkRenderer() +ren.SetBackground(0.4, 0.4, 0.5) +ren2 = vtk.vtkRenderer() +ren2.SetBackground(0.5, 0.4, 0.4) +# + +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.AddRenderer(ren2) +renWin.SetSize(600, 300) +# + +ren.SetViewport(0, 0, 0.5, 1) +ren2.SetViewport(0.5, 0, 1, 1) +# + +interactor = vtk.vtkInteractorStyleImage() +# + +iren = vtk.vtkRenderWindowInteractor() +iren.SetInteractorStyle(interactor) +iren.SetRenderWindow(renWin) +# + +extract = vtk.vtkExtractVOI() +extract.SetVOI(31, 31, 0, 63, 0, 92) +extract.SetSampleRate(1, 1, 1) +extract.SetInputConnection(shifter.GetOutputPort()) +extract.ReleaseDataFlagOff() +# + +imageActor2 = vtk.vtkImageActor() +imageActor2.SetInput(extract.GetOutput()) +imageActor2.VisibilityOn() +imageActor2.SetDisplayExtent(31, 31, 0, 63, 0, 92) +imageActor2.InterpolateOff() +# + +# Set up the image tracer widget +# +itw = vtk.vtkImageTracerWidget() +# +# Set the tolerance for capturing last handle when near first handle +# to form closed paths. +# +itw.SetCaptureRadius(1.5) +itw.GetGlyphSource().SetColor(1, 0, 0) +# +# Set the size of the glyph handle +# +itw.GetGlyphSource().SetScale(3.0) +# +# Set the initial rotation of the glyph if desired. The default glyph +# set internally by the widget is a '+' so rotating 45 deg. gives a 'x' +# +itw.GetGlyphSource().SetRotationAngle(45.0) +itw.GetGlyphSource().Modified() +itw.ProjectToPlaneOn() +itw.SetProjectionNormalToXAxes() +itw.SetProjectionPosition(pos) +itw.SetViewProp(imageActor) +itw.SetInput(shifter.GetOutput()) +itw.SetInteractor(iren) +itw.PlaceWidget() + +# +# When the underlying vtkDataSet is a vtkImageData, the widget can be +# forced to snap to either nearest pixel points, or pixel centers. Here +# it is turned off. +# +itw.SnapToImageOff() + +# +# Automatically form closed paths. +# +#itw AutoCloseOn +itw.AutoCloseOn() +# + +# Set up a vtkSplineWidget in the second renderer and have +# its handles set by the tracer widget. +# +isw = vtk.vtkSplineWidget() +isw.SetCurrentRenderer(ren2) +isw.SetDefaultRenderer(ren2) +isw.SetInput(extract.GetOutput()) +isw.SetInteractor(iren) +bnds = imageActor2.GetBounds() +isw.PlaceWidget(bnds[0], bnds[1], bnds[2], bnds[3], bnds[4], bnds[5]) +isw.ProjectToPlaneOn() +isw.SetProjectionNormalToXAxes() +isw.SetProjectionPosition(pos) +# + +# Have the widgets control each others handle positions. +# +itw.AddObserver('EndInteractionEvent',AdjustSpline) +isw.AddObserver('EndInteractionEvent',AdjustTracer) +# + +itw.On() +isw.On() +# + +poly = vtk.vtkPolyData() +points = vtk.vtkPoints() +spoly = vtk.vtkPolyData() +# + +# Set up a pipleline to demonstrate extraction of a 2D +# region of interest. Defining a closed clockwise path using the +# tracer widget will extract all pixels within the loop. A counter +# clockwise path provides the dual region of interest. +# +extrude = vtk.vtkLinearExtrusionFilter() +extrude.SetInput(spoly) +extrude.SetScaleFactor(1) +extrude.SetExtrusionTypeToNormalExtrusion() +extrude.SetVector(1, 0, 0) +# + +dataToStencil = vtk.vtkPolyDataToImageStencil() +dataToStencil.SetInputConnection(extrude.GetOutputPort()) +# + +stencil = vtk.vtkImageStencil() +stencil.SetInputConnection(extract.GetOutputPort()) +stencil.SetStencil(dataToStencil.GetOutput()) +stencil.ReverseStencilOff() +stencil.SetBackgroundValue(128) +# + +# Add all the actors. +# +ren.AddViewProp(imageActor) +ren2.AddViewProp(imageActor2) +# + +# Render the image. +# +renWin.Render() +# + +ren.GetActiveCamera().SetViewUp(0, 1, 0) +ren.GetActiveCamera().Azimuth(270) +ren.GetActiveCamera().Roll(270) +ren.GetActiveCamera().Dolly(1.7) +ren.ResetCameraClippingRange() +# + +ren2.GetActiveCamera().SetViewUp(0, 1, 0) +ren2.GetActiveCamera().Azimuth(270) +ren2.GetActiveCamera().Roll(270) +ren2.GetActiveCamera().Dolly(1.7) +ren2.ResetCameraClippingRange() +# + +# if we don't do this, the widgets disappear behind the imageActor. +vtk.vtkMapper.SetResolveCoincidentTopologyToPolygonOffset() +vtk.vtkMapper.SetResolveCoincidentTopologyPolygonOffsetParameters(10,10) + + +renWin.Render() +# + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/ImplicitPlaneWidget.py b/Examples/GUI/Python/ImplicitPlaneWidget.py new file mode 100644 index 0000000..50691db --- /dev/null +++ b/Examples/GUI/Python/ImplicitPlaneWidget.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python + +# This example demonstrates how to use the vtkPlaneWidget to probe a +# dataset and then generate contours on the probed data. + +import vtk + +# Create a mace out of filters. +sphere = vtk.vtkSphereSource() +cone = vtk.vtkConeSource() +glyph = vtk.vtkGlyph3D() +glyph.SetInputConnection(sphere.GetOutputPort()) +glyph.SetSource(cone.GetOutput()) +glyph.SetVectorModeToUseNormal() +glyph.SetScaleModeToScaleByVector() +glyph.SetScaleFactor(0.25) + +# The sphere and spikes are appended into a single polydata. +# This just makes things simpler to manage. +apd = vtk.vtkAppendPolyData() +apd.AddInput(glyph.GetOutput()) +apd.AddInput(sphere.GetOutput()) + +maceMapper = vtk.vtkPolyDataMapper() +maceMapper.SetInputConnection(apd.GetOutputPort()) + +maceActor = vtk.vtkLODActor() +maceActor.SetMapper(maceMapper) +maceActor.VisibilityOn() + +# This portion of the code clips the mace with the vtkPlanes +# implicit function. The clipped region is colored green. +plane = vtk.vtkPlane() +clipper = vtk.vtkClipPolyData() +clipper.SetInputConnection(apd.GetOutputPort()) +clipper.SetClipFunction(plane) +clipper.InsideOutOn() + +selectMapper = vtk.vtkPolyDataMapper() +selectMapper.SetInputConnection(clipper.GetOutputPort()) + +selectActor = vtk.vtkLODActor() +selectActor.SetMapper(selectMapper) +selectActor.GetProperty().SetColor(0, 1, 0) +selectActor.VisibilityOff() +selectActor.SetScale(1.01, 1.01, 1.01) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# The callback function +def myCallback(obj, event): + global plane, selectActor + obj.GetPlane(plane) + selectActor.VisibilityOn() + +# Associate the line widget with the interactor +planeWidget = vtk.vtkImplicitPlaneWidget() +planeWidget.SetInteractor(iren) +planeWidget.SetPlaceFactor(1.25) +planeWidget.SetInput(glyph.GetOutput()) +planeWidget.PlaceWidget() +planeWidget.AddObserver("InteractionEvent", myCallback) + +ren.AddActor(maceActor) +ren.AddActor(selectActor) + +# Add the actors to the renderer, set the background and size +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 300) +ren.SetBackground(0.1, 0.2, 0.4) + +# Start interaction. +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/OrthogonalPlanesWithTkPhoto.py b/Examples/GUI/Python/OrthogonalPlanesWithTkPhoto.py new file mode 100644 index 0000000..2a4b45e --- /dev/null +++ b/Examples/GUI/Python/OrthogonalPlanesWithTkPhoto.py @@ -0,0 +1,143 @@ +import vtk +from vtk import * +import Tkinter +from Tkinter import * +import sys, os +import vtk.tk +import vtk.tk.vtkLoadPythonTkWidgets +import vtk.tk.vtkTkImageViewerWidget +from vtk.tk.vtkTkPhotoImage import * +from vtk.util.misc import * + + +class SampleViewer: + def __init__ ( self ): + self.Tk = Tk = Tkinter.Tk(); + Tk.title ( 'Python Version of vtkImageDataToTkPhoto' ); + + # Image pipeline + reader = vtkVolume16Reader () + reader.SetDataDimensions ( 64, 64 ) + reader.SetDataByteOrderToLittleEndian ( ) + reader.SetFilePrefix ( vtkGetDataRoot() + '/Data/headsq/quarter' ) + reader.SetImageRange ( 1, 93 ) + reader.SetDataSpacing ( 3.2, 3.2, 1.5 ) + reader.Update () + + self.cast = cast = vtkImageCast() + cast.SetInputConnection( reader.GetOutputPort() ) + cast.SetOutputScalarType ( reader.GetOutput().GetScalarType() ) + cast.ClampOverflowOn() + + # Make the image a little bigger + self.resample = resample = vtkImageResample () + resample.SetInputConnection( cast.GetOutputPort() ) + resample.SetAxisMagnificationFactor ( 0, 2 ) + resample.SetAxisMagnificationFactor ( 1, 2 ) + resample.SetAxisMagnificationFactor ( 2, 1 ) + + l,h = reader.GetOutput().GetScalarRange() + + # Create the three orthogonal views + + tphoto = self.tphoto = self.tphoto = vtkTkPhotoImage (); + cphoto = self.cphoto = vtkTkPhotoImage (); + sphoto = self.sphoto = vtkTkPhotoImage (); + reader.Update() + d = reader.GetOutput().GetDimensions() + self.Position = [ int(d[0]/2.0), int(d[0]/2.0), int(d[0]/2.0) ] + + # Create a popup menu + v = IntVar() + self.popup = popup = Menu ( Tk, tearoff=0 ) + popup.add_radiobutton ( label='unsigned char', command=self.CastToUnsignedChar, variable=v, value=-1 ) + popup.add_radiobutton ( label='unsigned short', command=self.CastToUnsignedShort, variable=v, value=0 ) + popup.add_radiobutton ( label='unsigned int', command=self.CastToFloat, variable=v, value=1 ) + popup.add_radiobutton ( label='float', command=self.CastToFloat, variable=v, value=2 ) + + v.set ( 0 ) + + w = self.TransverseLabelWidget = Label ( Tk, image = tphoto ) + w.grid ( row = 0, column = 0 ) + w.bind ( "", lambda e, i=tphoto, o='transverse', s=self: s.Motion ( e, i, o ) ) + w.bind ( "", self.DoPopup ) + w = Label ( Tk, image = cphoto ) + w.grid ( row = 1, column = 0 ) + w.bind ( "", lambda e, i=cphoto, o='coronal', s=self: s.Motion ( e, i, o ) ) + w.bind ( "", self.DoPopup ) + w = Label ( Tk, image = sphoto ) + w.grid ( row = 0, column = 1 ) + w.bind ( "", lambda e, i=sphoto, o='sagittal', s=self: s.Motion ( e, i, o ) ) + w.bind ( "", self.DoPopup ) + w = self.WindowWidget = Scale ( Tk, label='Window', orient='horizontal', from_=1, to=(h-l)/2, command = self.SetWindowLevel ) + w = self.LevelWidget = Scale ( Tk, label='Level', orient='horizontal', from_=l, to=h, command=self.SetWindowLevel ) + self.WindowWidget.grid ( row=2, columnspan=2, sticky='ew' ) + self.LevelWidget.grid ( row=3, columnspan=2, sticky='ew' ); + self.WindowWidget.set ( 1370 ); + self.LevelWidget.set ( 1268 ); + + w = self.LabelWidget = Label ( Tk, bd=2, relief='raised' ) + w.grid ( row=4, columnspan=2, sticky='ew' ) + w.configure ( text = "Use the right mouse button to change data type" ) + + + def DoPopup ( self, event ): + self.popup.post ( event.x_root, event.y_root ) + + def CastToUnsignedChar ( self ): + self.cast.SetOutputScalarTypeToUnsignedChar() + self.SetImages() + def CastToUnsignedShort ( self ): + self.cast.SetOutputScalarTypeToUnsignedShort() + self.SetImages() + def CastToUnsignedInt ( self ): + self.cast.SetOutputScalarTypeToUnsignedInt() + self.SetImages() + def CastToFloat ( self ): + self.cast.SetOutputScalarTypeToFloat() + self.SetImages() + + + def Motion ( self, event, image, orientation ): + w = image.width(); + h = image.height() + if orientation == 'transverse': + self.Position[0] = event.x + self.Position[1] = h - event.y - 1 + if orientation == 'coronal': + self.Position[0] = event.x; + self.Position[2] = event.y + if orientation == 'sagittal': + self.Position[1] = w - event.x - 1 + self.Position[2] = event.y + self.LabelWidget.configure ( text = "Position: %d, %d, %d" % tuple ( self.Position ) ) + self.SetImages() + + def SetWindowLevel ( self, event ): + self.SetImages() + + def SetImages ( self ): + Window = self.WindowWidget.get() + Level = self.LevelWidget.get() + image = self.resample.GetOutput() + self.tphoto.PutImageSlice ( image, + self.Position[2], + 'transverse', + Window, + Level ) + self.sphoto.PutImageSlice ( image, + self.Position[0], + 'sagittal', + Window, + Level ) + self.cphoto.PutImageSlice ( image, + self.Position[1], + 'coronal', + Window, + Level ) + + + +if __name__ == '__main__': + S = SampleViewer() + S.Tk.mainloop() diff --git a/Examples/GUI/Python/ProbeWithPointWidget.py b/Examples/GUI/Python/ProbeWithPointWidget.py new file mode 100644 index 0000000..3c2134c --- /dev/null +++ b/Examples/GUI/Python/ProbeWithPointWidget.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +# This example demonstrates how to use the vtkPointWidget to probe a +# dataset and then color the probed point (represented as a cone) as +# per the probed value and orient it as per the vector. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Start by loading some data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# The plane widget is used probe the dataset. +pointWidget = vtk.vtkPointWidget() +pointWidget.SetInput(pl3d.GetOutput()) +pointWidget.AllOff() +pointWidget.PlaceWidget() +point = vtk.vtkPolyData() +pointWidget.GetPolyData(point) + +probe = vtk.vtkProbeFilter() +probe.SetInput(point) +probe.SetSource(pl3d.GetOutput()) + +# create glyph +cone = vtk.vtkConeSource() +cone.SetResolution(16) +glyph = vtk.vtkGlyph3D() +glyph.SetInputConnection(probe.GetOutputPort()) +glyph.SetSource(cone.GetOutput()) +glyph.SetVectorModeToUseVector() +glyph.SetScaleModeToDataScalingOff() +glyph.SetScaleFactor(pl3d.GetOutput().GetLength()*0.1) +glyphMapper = vtk.vtkPolyDataMapper() +glyphMapper.SetInputConnection(glyph.GetOutputPort()) +glyphActor = vtk.vtkActor() +glyphActor.SetMapper(glyphMapper) +glyphActor.VisibilityOff() + +# An outline is shown for context. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Actually set the color and orientation of the probe. +def BeginInteraction(obj, event): + global point, glyphActor + obj.GetPolyData(point) + glyphActor.VisibilityOn() + +def ProbeData(obj, event): + obj.GetPolyData(point) + +# Associate the line widget with the interactor +pointWidget.SetInteractor(iren) +pointWidget.AddObserver("EnableEvent", BeginInteraction) +pointWidget.AddObserver("StartInteractionEvent", BeginInteraction) +pointWidget.AddObserver("InteractionEvent", ProbeData) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(glyphActor) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 300) +ren.SetBackground(0.1, 0.2, 0.4) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(9.71821, 0.458166, 29.3999) +cam1.SetPosition(2.7439, -37.3196, 38.7167) +cam1.SetViewUp(-0.16123, 0.264271, 0.950876) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/ProbingWithPlaneWidget.py b/Examples/GUI/Python/ProbingWithPlaneWidget.py new file mode 100644 index 0000000..829fa87 --- /dev/null +++ b/Examples/GUI/Python/ProbingWithPlaneWidget.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +# This example demonstrates how to use the vtkPlaneWidget to probe +# a dataset and then generate contours on the probed data. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Start by loading some data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# The plane widget is used probe the dataset. +planeWidget = vtk.vtkPlaneWidget() +planeWidget.SetInput(pl3d.GetOutput()) +planeWidget.NormalToXAxisOn() +planeWidget.SetResolution(20) +planeWidget.SetRepresentationToOutline() +planeWidget.PlaceWidget() +plane = vtk.vtkPolyData() +planeWidget.GetPolyData(plane) + +probe = vtk.vtkProbeFilter() +probe.SetInput(plane) +probe.SetSource(pl3d.GetOutput()) + +contourMapper = vtk.vtkPolyDataMapper() +contourMapper.SetInputConnection(probe.GetOutputPort()) +contourMapper.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +contourActor = vtk.vtkActor() +contourActor.SetMapper(contourMapper) +contourActor.VisibilityOff() + +# An outline is shown for context. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Actually generate contour lines. +def BeginInteraction(obj, event): + global plane, contourActor + obj.GetPolyData(plane) + contourActor.VisibilityOn() + +def ProbeData(obj, event): + global plane + obj.GetPolyData(plane) + + +# Associate the widget with the interactor +planeWidget.SetInteractor(iren) +# Handle the events. +planeWidget.AddObserver("EnableEvent", BeginInteraction) +planeWidget.AddObserver("StartInteractionEvent", BeginInteraction) +planeWidget.AddObserver("InteractionEvent", ProbeData) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(contourActor) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 300) +ren.SetBackground(0.1, 0.2, 0.4) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(9.71821, 0.458166, 29.3999) +cam1.SetPosition(2.7439, -37.3196, 38.7167) +cam1.SetViewUp(-0.16123, 0.264271, 0.950876) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/SphereWidget.py b/Examples/GUI/Python/SphereWidget.py new file mode 100644 index 0000000..2936e7b --- /dev/null +++ b/Examples/GUI/Python/SphereWidget.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +# This example demonstrates how to use the vtkSphereWidget to control +# the position of a light. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Start by loading some data. +dem = vtk.vtkDEMReader() +dem.SetFileName(VTK_DATA_ROOT + "/Data/SainteHelens.dem") +dem.Update() + +Scale = 2 +lut = vtk.vtkLookupTable() +lut.SetHueRange(0.6, 0) +lut.SetSaturationRange(1.0, 0) +lut.SetValueRange(0.5, 1.0) + +lo = Scale*dem.GetElevationBounds()[0] +hi = Scale*dem.GetElevationBounds()[1] + +shrink = vtk.vtkImageShrink3D() +shrink.SetShrinkFactors(4, 4, 1) +shrink.SetInputConnection(dem.GetOutputPort()) +shrink.AveragingOn() + +geom = vtk.vtkImageDataGeometryFilter() +geom.SetInputConnection(shrink.GetOutputPort()) +geom.ReleaseDataFlagOn() + +warp = vtk.vtkWarpScalar() +warp.SetInputConnection(geom.GetOutputPort()) +warp.SetNormal(0, 0, 1) +warp.UseNormalOn() +warp.SetScaleFactor(Scale) +warp.ReleaseDataFlagOn() + +elevation = vtk.vtkElevationFilter() +elevation.SetInputConnection(warp.GetOutputPort()) +elevation.SetLowPoint(0, 0, lo) +elevation.SetHighPoint(0, 0, hi) +elevation.SetScalarRange(lo, hi) +elevation.ReleaseDataFlagOn() + +normals = vtk.vtkPolyDataNormals() +normals.SetInput(elevation.GetPolyDataOutput()) +normals.SetFeatureAngle(60) +normals.ConsistencyOff() +normals.SplittingOff() +normals.ReleaseDataFlagOn() + +demMapper = vtk.vtkPolyDataMapper() +demMapper.SetInputConnection(normals.GetOutputPort()) +demMapper.SetScalarRange(lo, hi) +demMapper.SetLookupTable(lut) +demMapper.ImmediateModeRenderingOn() + +demActor = vtk.vtkLODActor() +demActor.SetMapper(demMapper) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) +iren.LightFollowCameraOff() +iren.SetInteractorStyle(None) + +# Associate the line widget with the interactor +sphereWidget = vtk.vtkSphereWidget() +sphereWidget.SetInteractor(iren) +sphereWidget.SetProp3D(demActor) +sphereWidget.SetPlaceFactor(4) +sphereWidget.PlaceWidget() +sphereWidget.TranslationOff() +sphereWidget.ScaleOff() +sphereWidget.HandleVisibilityOn() + +# Uncomment the next line if you want to see the widget active when +# the script starts +#sphereWidget.EnabledOn() + +# Actually probe the data +def MoveLight(obj, event): + global light + light.SetPosition(obj.GetHandlePosition()) + +sphereWidget.AddObserver("InteractionEvent", MoveLight) + +# Add the actors to the renderer, set the background and size +ren.AddActor(demActor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 300) +ren.SetBackground(0.1, 0.2, 0.4) + +cam1 = ren.GetActiveCamera() +cam1.SetViewUp(0, 0, 1) +cam1.SetFocalPoint(dem.GetOutput().GetCenter()) +cam1.SetPosition(1, 0, 0) +ren.ResetCamera() +cam1.Elevation(25) +cam1.Azimuth(125) +cam1.Zoom(1.25) + +light = vtk.vtkLight() +light.SetFocalPoint(dem.GetOutput().GetCenter()) +ren.AddLight(light) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/StreamlinesWithLineWidget.py b/Examples/GUI/Python/StreamlinesWithLineWidget.py new file mode 100644 index 0000000..f5a522e --- /dev/null +++ b/Examples/GUI/Python/StreamlinesWithLineWidget.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python + +# This example demonstrates how to use the vtkLineWidget to seed and +# manipulate streamlines. Two line widgets are created. One is invoked +# by pressing 'i', the other by pressing 'L' (capital). Both can exist +# together. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Start by loading some data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# The line widget is used seed the streamlines. +lineWidget = vtk.vtkLineWidget() +seeds = vtk.vtkPolyData() +lineWidget.SetInput(pl3d.GetOutput()) +lineWidget.SetAlignToYAxis() +lineWidget.PlaceWidget() +lineWidget.GetPolyData(seeds) +lineWidget.ClampToBoundsOn() + +rk4 = vtk.vtkRungeKutta4() +streamer = vtk.vtkStreamLine() +streamer.SetInputConnection(pl3d.GetOutputPort()) +streamer.SetSource(seeds) +streamer.SetMaximumPropagationTime(100) +streamer.SetIntegrationStepLength(.2) +streamer.SetStepLength(.001) +streamer.SetNumberOfThreads(1) +streamer.SetIntegrationDirectionToForward() +streamer.VorticityOn() +streamer.SetIntegrator(rk4) +rf = vtk.vtkRibbonFilter() +rf.SetInputConnection(streamer.GetOutputPort()) +rf.SetWidth(0.1) +rf.SetWidthFactor(5) +streamMapper = vtk.vtkPolyDataMapper() +streamMapper.SetInputConnection(rf.GetOutputPort()) +streamMapper.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +streamline = vtk.vtkActor() +streamline.SetMapper(streamMapper) +streamline.VisibilityOff() + +# The second line widget is used seed more streamlines. +lineWidget2 = vtk.vtkLineWidget() +seeds2 = vtk.vtkPolyData() +lineWidget2.SetInput(pl3d.GetOutput()) +lineWidget2.PlaceWidget() +lineWidget2.GetPolyData(seeds2) +lineWidget2.SetKeyPressActivationValue('L') + +streamer2 = vtk.vtkStreamLine() +streamer2.SetInputConnection(pl3d.GetOutputPort()) +streamer2.SetSource(seeds2) +streamer2.SetMaximumPropagationTime(100) +streamer2.SetIntegrationStepLength(.2) +streamer2.SetStepLength(.001) +streamer2.SetNumberOfThreads(1) +streamer2.SetIntegrationDirectionToForward() +streamer2.VorticityOn() +streamer2.SetIntegrator(rk4) +rf2 = vtk.vtkRibbonFilter() +rf2.SetInputConnection(streamer2.GetOutputPort()) +rf2.SetWidth(0.1) +rf2.SetWidthFactor(5) +streamMapper2 = vtk.vtkPolyDataMapper() +streamMapper2.SetInputConnection(rf2.GetOutputPort()) +streamMapper2.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +streamline2 = vtk.vtkActor() +streamline2.SetMapper(streamMapper2) +streamline2.VisibilityOff() + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Callback functions that actually generate streamlines. +def BeginInteraction(obj, event): + global streamline + streamline.VisibilityOn() + +def GenerateStreamlines(obj, event): + global seeds, renWin + obj.GetPolyData(seeds) + renWin.Render() + +def BeginInteraction2(obj, event): + global streamline2 + streamline2.VisibilityOn() + +def GenerateStreamlines2(obj, event): + global seeds2, renWin + obj.GetPolyData(seeds2) + renWin.Render() + +# Associate the line widget with the interactor and setup callbacks. +lineWidget.SetInteractor(iren) +lineWidget.AddObserver("StartInteractionEvent", BeginInteraction) +lineWidget.AddObserver("InteractionEvent", GenerateStreamlines) + +lineWidget2.SetInteractor(iren) +lineWidget2.AddObserver("StartInteractionEvent", BeginInteraction2) +lineWidget2.AddObserver("EndInteractionEvent", GenerateStreamlines2) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(streamline) +ren.AddActor(streamline2) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 300) +ren.SetBackground(0.1, 0.2, 0.4) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(9.71821, 0.458166, 29.3999) +cam1.SetPosition(2.7439, -37.3196, 38.7167) +cam1.SetViewUp(-0.16123, 0.264271, 0.950876) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/TransformWithBoxWidget.py b/Examples/GUI/Python/TransformWithBoxWidget.py new file mode 100644 index 0000000..a04f332 --- /dev/null +++ b/Examples/GUI/Python/TransformWithBoxWidget.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +# Demonstrate how to use the vtkBoxWidget to translate, scale, and +# rotate actors. The basic idea is that the box widget controls an +# actor's transform. A callback which modifies the transform is +# invoked as the box widget is manipulated. + +import vtk + +# Start by creating some simple geometry; in this case a mace. +sphere = vtk.vtkSphereSource() +cone = vtk.vtkConeSource() +glyph = vtk.vtkGlyph3D() +glyph.SetInputConnection(sphere.GetOutputPort()) +glyph.SetSource(cone.GetOutput()) +glyph.SetVectorModeToUseNormal() +glyph.SetScaleModeToScaleByVector() +glyph.SetScaleFactor(0.25) +appendData = vtk.vtkAppendPolyData() +appendData.AddInput(glyph.GetOutput()) +appendData.AddInput(sphere.GetOutput()) +maceMapper = vtk.vtkPolyDataMapper() +maceMapper.SetInputConnection(appendData.GetOutputPort()) +maceActor = vtk.vtkLODActor() +maceActor.SetMapper(maceMapper) +maceActor.VisibilityOn() + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# The box widget observes the events invoked by the render window +# interactor. These events come from user interaction in the render +# window. +boxWidget = vtk.vtkBoxWidget() +boxWidget.SetInteractor(iren) +boxWidget.SetPlaceFactor(1.25) + +# Add the actors to the renderer, set the background and window size. +ren.AddActor(maceActor) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(300, 300) + +# As the box widget is interacted with, it produces a transformation +# matrix that is set on the actor. +t = vtk.vtkTransform() +def TransformActor(obj, event): + global t, maceActor + obj.GetTransform(t) + maceActor.SetUserTransform(t) + +# Place the interactor initially. The actor is used to place and scale +# the interactor. An observer is added to the box widget to watch for +# interaction events. This event is captured and used to set the +# transformation matrix of the actor. +boxWidget.SetProp3D(maceActor) +boxWidget.PlaceWidget() +boxWidget.AddObserver("InteractionEvent", TransformActor) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Python/VolumeRenderWithBoxWidget.py b/Examples/GUI/Python/VolumeRenderWithBoxWidget.py new file mode 100644 index 0000000..7b8e549 --- /dev/null +++ b/Examples/GUI/Python/VolumeRenderWithBoxWidget.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python + +# Demonstrate how to use the vtkBoxWidget to control volume rendering +# within the interior of the widget. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Load a volume, use the widget to control what's volume +# rendered. Basically the idea is that the vtkBoxWidget provides a box +# which clips the volume rendering. +v16 = vtk.vtkVolume16Reader() +v16.SetDataDimensions(64, 64) +v16.GetOutput().SetOrigin(0.0, 0.0, 0.0) +v16.SetDataByteOrderToLittleEndian() +v16.SetFilePrefix(VTK_DATA_ROOT+ "/Data/headsq/quarter") +v16.SetImageRange(1, 93) +v16.SetDataSpacing(3.2, 3.2, 1.5) + +tfun = vtk.vtkPiecewiseFunction() +tfun.AddPoint(70.0, 0.0) +tfun.AddPoint(599.0, 0) +tfun.AddPoint(600.0, 0) +tfun.AddPoint(1195.0, 0) +tfun.AddPoint(1200, .2) +tfun.AddPoint(1300, .3) +tfun.AddPoint(2000, .3) +tfun.AddPoint(4095.0, 1.0) + +ctfun = vtk.vtkColorTransferFunction() +ctfun.AddRGBPoint(0.0, 0.5, 0.0, 0.0) +ctfun.AddRGBPoint(600.0, 1.0, 0.5, 0.5) +ctfun.AddRGBPoint(1280.0, 0.9, 0.2, 0.3) +ctfun.AddRGBPoint(1960.0, 0.81, 0.27, 0.1) +ctfun.AddRGBPoint(4095.0, 0.5, 0.5, 0.5) + +compositeFunction = vtk.vtkVolumeRayCastCompositeFunction() + +volumeMapper = vtk.vtkVolumeRayCastMapper() +volumeMapper.SetInputConnection(v16.GetOutputPort()) +volumeMapper.SetVolumeRayCastFunction(compositeFunction) + +volumeProperty = vtk.vtkVolumeProperty() +volumeProperty.SetColor(ctfun) +volumeProperty.SetScalarOpacity(tfun) +volumeProperty.SetInterpolationTypeToLinear() +volumeProperty.ShadeOn() + +newvol = vtk.vtkVolume() +newvol.SetMapper(volumeMapper) +newvol.SetProperty(volumeProperty) + +outline = vtk.vtkOutlineFilter() +outline.SetInputConnection(v16.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# The SetInteractor method is how 3D widgets are associated with the +# render window interactor. Internally, SetInteractor sets up a bunch +# of callbacks using the Command/Observer mechanism (AddObserver()). +boxWidget = vtk.vtkBoxWidget() +boxWidget.SetInteractor(iren) +boxWidget.SetPlaceFactor(1.0) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddVolume(newvol) + +ren.SetBackground(0, 0, 0) +renWin.SetSize(300, 300) + +# When interaction starts, the requested frame rate is increased. +def StartInteraction(obj, event): + global renWin + renWin.SetDesiredUpdateRate(10) + +# When interaction ends, the requested frame rate is decreased to +# normal levels. This causes a full resolution render to occur. +def EndInteraction(obj, event): + global renWin + renWin.SetDesiredUpdateRate(0.001) + +# The implicit function vtkPlanes is used in conjunction with the +# volume ray cast mapper to limit which portion of the volume is +# volume rendered. +planes = vtk.vtkPlanes() +def ClipVolumeRender(obj, event): + global planes, volumeMapper + obj.GetPlanes(planes) + volumeMapper.SetClippingPlanes(planes) + + +# Place the interactor initially. The output of the reader is used to +# place the box widget. +boxWidget.SetInput(v16.GetOutput()) +boxWidget.PlaceWidget() +boxWidget.InsideOutOn() +boxWidget.AddObserver("StartInteractionEvent", StartInteraction) +boxWidget.AddObserver("InteractionEvent", ClipVolumeRender) +boxWidget.AddObserver("EndInteractionEvent", EndInteraction) + +outlineProperty = boxWidget.GetOutlineProperty() +outlineProperty.SetRepresentationToWireframe() +outlineProperty.SetAmbient(1.0) +outlineProperty.SetAmbientColor(1, 1, 1) +outlineProperty.SetLineWidth(3) + +selectedOutlineProperty = boxWidget.GetSelectedOutlineProperty() +selectedOutlineProperty.SetRepresentationToWireframe() +selectedOutlineProperty.SetAmbient(1.0) +selectedOutlineProperty.SetAmbientColor(1, 0, 0) +selectedOutlineProperty.SetLineWidth(3) + + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/GUI/Qt/CMakeLists.txt b/Examples/GUI/Qt/CMakeLists.txt new file mode 100644 index 0000000..c799e3e --- /dev/null +++ b/Examples/GUI/Qt/CMakeLists.txt @@ -0,0 +1,4 @@ + + +SUBDIRS(ImageViewer SimpleView Events) + diff --git a/Examples/GUI/Qt/Events/CMakeLists.txt b/Examples/GUI/Qt/Events/CMakeLists.txt new file mode 100644 index 0000000..fed3e6a --- /dev/null +++ b/Examples/GUI/Qt/Events/CMakeLists.txt @@ -0,0 +1,87 @@ +PROJECT(QtEvents) + +FIND_PACKAGE(VTK) +IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") +ENDIF(NOT VTK_DIR) +INCLUDE(${VTK_USE_FILE}) + +# use what QVTK built with +SET(QT_QMAKE_EXECUTABLE ${VTK_QT_QMAKE_EXECUTABLE} CACHE FILEPATH "") +SET(QT_MOC_EXECUTABLE ${VTK_QT_MOC_EXECUTABLE} CACHE FILEPATH "") +SET(QT_UIC_EXECUTABLE ${VTK_QT_UIC_EXECUTABLE} CACHE FILEPATH "") +SET(DESIRED_QT_VERSION ${VTK_DESIRED_QT_VERSION} CACHE FILEPATH "") +FIND_PACKAGE(Qt) +IF(QT_USE_FILE) + SET(QT_USE_QT3SUPPORT TRUE) + INCLUDE(${QT_USE_FILE}) +ELSE(QT_USE_FILE) + SET(QT_LIBRARIES ${QT_QT_LIBRARY}) +ENDIF(QT_USE_FILE) + +SET (SRCS + main.cxx +) + +# Use the include path and library for Qt that is used by VTK. +INCLUDE_DIRECTORIES( + ${QT_INCLUDE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +IF(DESIRED_QT_VERSION MATCHES 4) + + # instead of a complete port to Qt4, lets try out uic3 and Qt3Support + + STRING(REGEX REPLACE "uic" "uic3" QT_UIC3_EXECUTABLE "${QT_UIC_EXECUTABLE}") + ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/GUI.h + COMMAND ${QT_UIC3_EXECUTABLE} + ARGS -o ${CMAKE_CURRENT_BINARY_DIR}/GUI.h + ${CMAKE_CURRENT_SOURCE_DIR}/GUI.ui + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/GUI.ui + ) + ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/GUI.cxx + COMMAND ${QT_UIC3_EXECUTABLE} + ARGS -impl ${CMAKE_CURRENT_BINARY_DIR}/GUI.h + -o ${CMAKE_CURRENT_BINARY_DIR}/GUI.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/GUI.ui + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/GUI.ui + ${CMAKE_CURRENT_BINARY_DIR}/GUI.h + ) + GET_DIRECTORY_PROPERTY(moc_includes_tmp INCLUDE_DIRECTORIES) + SET(moc_includes) + FOREACH(it ${moc_includes_tmp}) + SET(moc_includes ${moc_includes} "-I${it}") + ENDFOREACH(it) + + ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/moc_GUI.cxx + COMMAND ${QT_MOC_EXECUTABLE} + ARGS ${moc_includes} -o ${CMAKE_CURRENT_BINARY_DIR}/moc_GUI.cxx + ${CMAKE_CURRENT_BINARY_DIR}/GUI.h + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/GUI.h) + + SET(UI_SRCS GUI.cxx moc_GUI.cxx) +ELSE(DESIRED_QT_VERSION MATCHES 4) + QT_WRAP_UI( qtevents UI_HDRS UI_SRCS GUI.ui ) + # help cmake with Qt depends + SET_SOURCE_FILES_PROPERTIES(main.cxx PROPERTIES + OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/GUI.h) +ENDIF(DESIRED_QT_VERSION MATCHES 4) + + +SET_SOURCE_FILES_PROPERTIES(GUI.cxx PROPERTIES + OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/GUI.ui.h) + +ADD_EXECUTABLE( qtevents MACOSX_BUNDLE ${SRCS} ${UI_SRCS}) + +TARGET_LINK_LIBRARIES( qtevents + QVTK + ${QT_LIBRARIES} + vtkRendering + vtkGraphics + vtkIO + vtkCommon +) + + diff --git a/Examples/GUI/Qt/Events/GUI.ui b/Examples/GUI/Qt/Events/GUI.ui new file mode 100644 index 0000000..2daea16 --- /dev/null +++ b/Examples/GUI/Qt/Events/GUI.ui @@ -0,0 +1,189 @@ + +Form1 + + + Form1 + + + + 0 + 0 + 502 + 456 + + + + Form1 + + + + unnamed + + + + buttonGroup1 + + + 0 + + + + + + + unnamed + + + + layout1 + + + + unnamed + + + + radio1 + + + NoFocus + + + Mouse In Window 1 + + + + + radio2 + + + NoFocus + + + Mouse In Window 2 + + + + + + + + + layout2 + + + + unnamed + + + + qVTK1 + + + + + qVTK2 + + + + + + + coord + + + textLabel1 + + + AlignCenter + + + + + + + MenuBar + + + + + + + + + + QVTKWidget +

QVTKWidget.h
+ + -1 + -1 + + 0 + + 7 + 7 + 0 + 0 + + image0 + + + + + + fileExitAction + + + Exit + + + E&xit + + + + + + + + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154789cad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a19017a725d8c60000000049454e44ae426082 + + + + + fileExitAction + activated() + Form1 + close() + + + + vtkRenderer.h + vtkRenderWindow.h + vtkEventQtSlotConnect.h + QVTKWidget.h + GUI.ui.h + + + class vtkRenderer; + class vtkEventQtSlotConnect; + class vtkObject; + class vtkCommand; + + + vtkRenderer* ren1; + vtkRenderer* ren2; + vtkEventQtSlotConnect* connections; + + + fileExit() + updateCoords( vtkObject * obj ) + popup( vtkObject * obj, unsigned long event, void * client_data, vtkCommand * command ) + color1(int color) + color2(int color) + + + init() + destroy() + + diff --git a/Examples/GUI/Qt/Events/GUI.ui.h b/Examples/GUI/Qt/Events/GUI.ui.h new file mode 100644 index 0000000..48de3ad --- /dev/null +++ b/Examples/GUI/Qt/Events/GUI.ui.h @@ -0,0 +1,229 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** Qt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + + +#include "vtkSphereSource.h" +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" + +#if QT_VERSION >= 0x040000 +#include "q3popupmenu.h" +#define QPopupMenu Q3PopupMenu +#endif + +void Form1::init() +{ + // create a window to make it stereo capable and give it to QVTKWidget + vtkRenderWindow* renwin = vtkRenderWindow::New(); + renwin->StereoCapableWindowOn(); + qVTK1->SetRenderWindow(renwin); + renwin->Delete(); + + // add a renderer + ren1 = vtkRenderer::New(); + qVTK1->GetRenderWindow()->AddRenderer(ren1); + + // add a popup menu for the window and connect it to our slot + QPopupMenu* popup1 = new QPopupMenu(qVTK1); + popup1->insertItem("Background White", 1); + popup1->insertItem("Background Black", 2); + popup1->insertItem("Stereo Rendering", 3); + connect(popup1, SIGNAL(activated(int)), this, SLOT(color1(int))); + + // put cone in one window + vtkConeSource* cone = vtkConeSource::New(); + vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); + mapper->SetInput(cone->GetOutput()); + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + ren1->AddViewProp(actor); + actor->Delete(); + mapper->Delete(); + cone->Delete(); + + // create a window to make it stereo capable and give it to QVTKWidget + renwin = vtkRenderWindow::New(); + renwin->StereoCapableWindowOn(); + qVTK2->SetRenderWindow(renwin); + renwin->Delete(); + + // add a renderer + ren2 = vtkRenderer::New(); + qVTK2->GetRenderWindow()->AddRenderer(ren2); + + // add a popup menu for the window and connect it to our slot + QPopupMenu* popup2 = new QPopupMenu(qVTK2); + popup2->insertItem("Background White", 1); + popup2->insertItem("Background Black", 2); + popup2->insertItem("Stereo Rendering", 3); + connect(popup2, SIGNAL(activated(int)), this, SLOT(color2(int))); + + // put sphere in other window + vtkSphereSource* sphere = vtkSphereSource::New(); + mapper = vtkPolyDataMapper::New(); + mapper->SetInput(sphere->GetOutput()); + actor = vtkActor::New(); + actor->SetMapper(mapper); + ren2->AddViewProp(actor); + actor->Delete(); + mapper->Delete(); + sphere->Delete(); + + + connections = vtkEventQtSlotConnect::New(); + + // get right mouse pressed with high priority + connections->Connect(qVTK1->GetRenderWindow()->GetInteractor(), + vtkCommand::RightButtonPressEvent, + this, + SLOT(popup( vtkObject*, unsigned long, void*, vtkCommand*)), + popup1, 1.0); + + // get right mouse pressed with high priority + connections->Connect(qVTK2->GetRenderWindow()->GetInteractor(), + vtkCommand::RightButtonPressEvent, + this, + SLOT(popup( vtkObject*, unsigned long, void*, vtkCommand*)), + popup2, 1.0); + + // connect window enter event to radio button slot + connections->Connect(qVTK1->GetRenderWindow()->GetInteractor(), + vtkCommand::EnterEvent, + radio1, + SLOT(animateClick())); + + // connect window enter event to radio button slot + connections->Connect(qVTK2->GetRenderWindow()->GetInteractor(), + vtkCommand::EnterEvent, + radio2, + SLOT(animateClick())); + + // update coords as we move through the window + connections->Connect(qVTK1->GetRenderWindow()->GetInteractor(), + vtkCommand::MouseMoveEvent, + this, + SLOT(updateCoords(vtkObject*))); + + // update coords as we move through the window + connections->Connect(qVTK2->GetRenderWindow()->GetInteractor(), + vtkCommand::MouseMoveEvent, + this, + SLOT(updateCoords(vtkObject*))); + + connections->PrintSelf(cout, vtkIndent()); + +} + +void Form1::destroy() +{ + ren1->Delete(); + ren2->Delete(); + + connections->Delete(); +} + + + +void Form1::fileExit() +{ +} + + +void Form1::updateCoords( vtkObject * obj) +{ + // get interactor + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj); + // get event position + int event_pos[2]; + iren->GetEventPosition(event_pos); + // update label + QString str; + str.sprintf("x=%d : y=%d", event_pos[0], event_pos[1]); + coord->setText(str); + +} + + +void Form1::popup( vtkObject * obj, unsigned long , void * client_data, vtkCommand* command) +{ + + // A note about context menus in Qt and the QVTKWidget + // You may find it easy to just do context menus on right button up, + // due to the event proxy mechanism in place. + + // That usually works, except in some cases. + // One case is where you capture context menu events that + // child windows don't process. You could end up with a second + // context menu after the first one. + + // See QVTKWidget::ContextMenuEvent enum which was added after the + // writing of this example. + + // get interactor + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj); + // consume event so the interactor style doesn't get it + command->AbortFlagOn(); + // get popup menu + QPopupMenu* popup = static_cast(client_data); + // get event location + int* size = iren->GetSize(); + int* pos = iren->GetEventPosition(); + // remember to flip y + QPoint pt = QPoint(pos[0], size[1]-pos[1]); + // map to global + QPoint global_pt = popup->parentWidget()->mapToGlobal(pt); + // show popup menu at global point + popup->popup(global_pt); +} + + + +void Form1::color1( int color ) +{ + if(color == 1) + ren1->SetBackground(1,1,1); + else if(color == 2) + ren1->SetBackground(0,0,0); + else if(color == 3) + { + ren1->GetRenderWindow()->SetStereoRender(!ren1->GetRenderWindow()->GetStereoRender()); + } +} + + +void Form1::color2( int color ) +{ + if(color == 1) + ren2->SetBackground(1,1,1); + else if(color == 2) + ren2->SetBackground(0,0,0); + else if(color == 3) + { + ren2->GetRenderWindow()->SetStereoRender(!ren2->GetRenderWindow()->GetStereoRender()); + } +} diff --git a/Examples/GUI/Qt/Events/main.cxx b/Examples/GUI/Qt/Events/main.cxx new file mode 100644 index 0000000..57bfdc7 --- /dev/null +++ b/Examples/GUI/Qt/Events/main.cxx @@ -0,0 +1,45 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include "qapplication.h" + +#include "GUI.h" + + +int main(int argc, char** argv) +{ + QApplication app(argc, argv); + + Form1 widget; + app.setMainWidget(&widget); + + widget.show(); + + return app.exec(); + + +} + diff --git a/Examples/GUI/Qt/ImageViewer/CMakeLists.txt b/Examples/GUI/Qt/ImageViewer/CMakeLists.txt new file mode 100644 index 0000000..f2d2ba6 --- /dev/null +++ b/Examples/GUI/Qt/ImageViewer/CMakeLists.txt @@ -0,0 +1,39 @@ +PROJECT(QtImageViewer) + +FIND_PACKAGE(VTK) +IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") +ENDIF(NOT VTK_DIR) +INCLUDE(${VTK_USE_FILE}) + +SET(QT_QMAKE_EXECUTABLE ${VTK_QT_QMAKE_EXECUTABLE} CACHE FILEPATH "") +SET(QT_MOC_EXECUTABLE ${VTK_QT_MOC_EXECUTABLE} CACHE FILEPATH "") +SET(QT_UIC_EXECUTABLE ${VTK_QT_UIC_EXECUTABLE} CACHE FILEPATH "") +SET(DESIRED_QT_VERSION ${VTK_DESIRED_QT_VERSION} CACHE FILEPATH "") +FIND_PACKAGE(Qt) +IF(QT_USE_FILE) + INCLUDE(${QT_USE_FILE}) +ELSE(QT_USE_FILE) + SET(QT_LIBRARIES ${QT_QT_LIBRARY}) +ENDIF(QT_USE_FILE) + +SET (SRCS + main.cxx +) + +# Use the include path and library for Qt that is used by VTK. +INCLUDE_DIRECTORIES( ${QT_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} + ${QT_QTCORE_INCLUDE_DIR}) + +ADD_EXECUTABLE( qtimageviewer MACOSX_BUNDLE ${SRCS}) + +TARGET_LINK_LIBRARIES( qtimageviewer + QVTK + ${QT_LIBRARIES} + vtkRendering + vtkGraphics + vtkIO + vtkCommon +) + + diff --git a/Examples/GUI/Qt/ImageViewer/main.cxx b/Examples/GUI/Qt/ImageViewer/main.cxx new file mode 100644 index 0000000..bf7c8e0 --- /dev/null +++ b/Examples/GUI/Qt/ImageViewer/main.cxx @@ -0,0 +1,74 @@ + + +/*========================================================================= + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include "qapplication.h" + +#include "vtkImageViewer.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkPNGReader.h" +#include "vtkTestUtilities.h" + +#include "QVTKWidget.h" + +int main(int argc, char** argv) +{ + QApplication app(argc, argv); + + QVTKWidget widget; + widget.resize(256,256); + +#if QT_VERSION < 0x040000 + app.setMainWidget(&widget); +#endif + + vtkPNGReader* reader = vtkPNGReader::New(); + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/vtk.png"); + reader->SetFileName(fname); + delete [] fname; + + vtkImageViewer* image_view = vtkImageViewer::New(); + image_view->SetInputConnection(reader->GetOutputPort()); + + widget.SetRenderWindow(image_view->GetRenderWindow()); + image_view->SetupInteractor(widget.GetRenderWindow()->GetInteractor()); + + image_view->SetColorLevel(138.5); + image_view->SetColorWindow(233); + + widget.show(); + + app.exec(); + + + image_view->Delete(); + reader->Delete(); + + return 0; +} + + diff --git a/Examples/GUI/Qt/SimpleView/CMakeLists.txt b/Examples/GUI/Qt/SimpleView/CMakeLists.txt new file mode 100644 index 0000000..75d54ab --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/CMakeLists.txt @@ -0,0 +1,75 @@ +PROJECT(QtSimpleView) + +FIND_PACKAGE(VTK) +IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") +ENDIF(NOT VTK_DIR) +INCLUDE(${VTK_USE_FILE}) + +# use what QVTK built with +SET(QT_MOC_EXECUTABLE ${VTK_QT_MOC_EXECUTABLE} CACHE FILEPATH "") +SET(QT_UIC_EXECUTABLE ${VTK_QT_UIC_EXECUTABLE} CACHE FILEPATH "") +SET(QT_QMAKE_EXECUTABLE ${VTK_QT_QMAKE_EXECUTABLE} CACHE FILEPATH "") +SET(DESIRED_QT_VERSION ${VTK_DESIRED_QT_VERSION} CACHE FILEPATH "") +FIND_PACKAGE(Qt) +IF(QT_USE_FILE) + INCLUDE(${QT_USE_FILE}) +ELSE(QT_USE_FILE) + SET(QT_LIBRARIES ${QT_QT_LIBRARY}) +ENDIF(QT_USE_FILE) + +SET (SimpleViewSrcs + main.cxx +) + +# Use the include path and library for Qt that is used by VTK. +INCLUDE_DIRECTORIES( + ${QT_INCLUDE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) + +IF(DESIRED_QT_VERSION MATCHES 4) + + SET(SimpleViewSrcs ${SimpleViewSrcs} SimpleView4.cxx) + SET(UIS uiSimpleView4.ui) + SET (SimpleViewHeaders SimpleView4.h) + QT4_WRAP_UI(UIHeaders ${UIS}) + QT4_WRAP_CPP(MOCSrcs ${SimpleViewHeaders} ) + ADD_DEFINITIONS(-DQT_GUI_LIBS -DQT_CORE_LIB -DQT3_SUPPORT) + SET_SOURCE_FILES_PROPERTIES(${SimpleViewSrcs} PROPERTIES + OBJECT_DEPENDS "${UIHeaders}") + +ELSE(DESIRED_QT_VERSION MATCHES 4) + + SET(SimpleViewSrcs ${SimpleViewSrcs} SimpleView3.cxx) + SET(UIS uiSimpleView3.ui) + SET (SimpleViewHeaders SimpleView3.h) + QT_WRAP_UI( simpleview UIHeaders UISrcs ${UIS}) + QT_WRAP_CPP( simpleview MOCSrcs ${SimpleViewHeaders} ) + SET_SOURCE_FILES_PROPERTIES(${SimpleViewSrcs} PROPERTIES + OBJECT_DEPENDS "${UIHeaders}") + +ENDIF(DESIRED_QT_VERSION MATCHES 4) + +# It's nice to have the ui in the windows project file...just double click on it +# and designer comes up on that ui file :) +IF (${CMAKE_BUILD_TOOL} MATCHES "msdev") + SET (SimpleViewSrcs ${SimpleViewSrcs} ${UIS}) +ENDIF (${CMAKE_BUILD_TOOL} MATCHES "msdev") +IF (${CMAKE_BUILD_TOOL} MATCHES "devenv") + SET (SimpleViewSrcs ${SimpleViewSrcs} ${UIS}) +ENDIF (${CMAKE_BUILD_TOOL} MATCHES "devenv") + +ADD_EXECUTABLE( qtsimpleview MACOSX_BUNDLE ${SimpleViewSrcs} ${UISrcs} ${MOCSrcs}) + +TARGET_LINK_LIBRARIES( qtsimpleview + QVTK + ${QT_LIBRARIES} + vtkRendering + vtkGraphics + vtkIO + vtkCommon +) + + diff --git a/Examples/GUI/Qt/SimpleView/SimpleView3.cxx b/Examples/GUI/Qt/SimpleView/SimpleView3.cxx new file mode 100644 index 0000000..94a28eb --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/SimpleView3.cxx @@ -0,0 +1,73 @@ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include +#include + +#include "SimpleView3.h" +#include +#include +#include +#include "vtkCylinderSource.h" +#include + + +// Constructor +SimpleView::SimpleView(QWidget* parent) + : uiSimpleView(parent) +{ + // QT/VTK interact + ren = vtkRenderer::New(); + vtkWidget->GetRenderWindow()->AddRenderer(ren); + +}; + +// Action to be taken upon file open +void SimpleView::fileOpen() +{ + // Geometry + source = vtkCylinderSource::New(); + + // Mapper + mapper = vtkPolyDataMapper::New(); + mapper->ImmediateModeRenderingOn(); + mapper->SetInputConnection(source->GetOutputPort()); + + // Actor in scene + actor = vtkActor::New(); + actor->SetMapper(mapper); + + // Add Actor to renderer + ren->AddActor(actor); + + // Reset camera + ren->ResetCamera(); + + ren->GetRenderWindow()->Render(); +} + +void SimpleView::fileExit() { + qApp->exit(); +} + diff --git a/Examples/GUI/Qt/SimpleView/SimpleView3.h b/Examples/GUI/Qt/SimpleView/SimpleView3.h new file mode 100644 index 0000000..45eeb8b --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/SimpleView3.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SimpleView3.h,v $ + Language: C++ + Date: $Date: 2005/08/11 18:46:44 $ + Version: $Revision: 1.2 $ + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + + +#ifndef SIMPLEVIEW_H +#define SIMPLEVIEW_H + +#include "uiSimpleView3.h" + +// Forward class declarations +class vtkCylinderSource; +class vtkPolyDataMapper; +class vtkExodusReader; +class vtkDataSetMapper; +class vtkActor; +class vtkRenderer; + + +class SimpleView : public uiSimpleView +{ + Q_OBJECT + +public: + + // Constructor/Destructor + SimpleView(QWidget* parent = 0); + ~SimpleView() {}; + +public slots: + + virtual void fileOpen(); + virtual void fileExit(); + +protected: + +protected slots: + +private: + vtkCylinderSource* source; + vtkPolyDataMapper* mapper; + vtkActor* actor; + vtkRenderer* ren; + +}; + +#endif // SIMPLEVIEW_H + diff --git a/Examples/GUI/Qt/SimpleView/SimpleView4.cxx b/Examples/GUI/Qt/SimpleView/SimpleView4.cxx new file mode 100644 index 0000000..b26fe62 --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/SimpleView4.cxx @@ -0,0 +1,91 @@ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include +#include +#include "qmenubar.h" + +#include "SimpleView4.h" +#include +#include +#include +#include "vtkCylinderSource.h" +#include + + +// Constructor +SimpleView::SimpleView(QWidget* parent) + : QMainWindow(parent) +{ + setupUi(this); + + QAction* a_fileOpen = new QAction(tr("&Open"), this); + a_fileOpen->setShortcut(tr("Ctrl+N")); + a_fileOpen->setStatusTip(tr("Create a new file")); + connect(a_fileOpen, SIGNAL(triggered()), this, SLOT(fileOpen())); + + QAction* a_fileExit = new QAction(tr("&Exit"), this); + a_fileExit->setShortcut(tr("Ctrl+Q")); + a_fileExit->setStatusTip(tr("Exit")); + connect(a_fileExit, SIGNAL(triggered()), this, SLOT(fileExit())); + + QMenu* file_menu = this->menuBar()->addMenu(tr("&File")); + file_menu->addAction(a_fileOpen); + file_menu->addAction(a_fileExit); + + + // QT/VTK interact + ren = vtkRenderer::New(); + vtkWidget->GetRenderWindow()->AddRenderer(ren); + +}; + +// Action to be taken upon file open +void SimpleView::fileOpen() +{ + // Geometry + source = vtkCylinderSource::New(); + + // Mapper + mapper = vtkPolyDataMapper::New(); + mapper->ImmediateModeRenderingOn(); + mapper->SetInputConnection(source->GetOutputPort()); + + // Actor in scene + actor = vtkActor::New(); + actor->SetMapper(mapper); + + // Add Actor to renderer + ren->AddActor(actor); + + // Reset camera + ren->ResetCamera(); + + ren->GetRenderWindow()->Render(); +} + +void SimpleView::fileExit() { + qApp->exit(); +} + diff --git a/Examples/GUI/Qt/SimpleView/SimpleView4.h b/Examples/GUI/Qt/SimpleView/SimpleView4.h new file mode 100644 index 0000000..9f7351c --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/SimpleView4.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SimpleView4.h,v $ + Language: C++ + Date: $Date: 2005/08/11 16:47:38 $ + Version: $Revision: 1.1 $ + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + + +#ifndef SIMPLEVIEW_H +#define SIMPLEVIEW_H + +#include "qmainwindow.h" +#include "ui_uiSimpleView4.h" + +// Forward class declarations +class vtkCylinderSource; +class vtkPolyDataMapper; +class vtkExodusReader; +class vtkDataSetMapper; +class vtkActor; +class vtkRenderer; + + +class SimpleView : public QMainWindow, private Ui_MainWindow +{ + Q_OBJECT + +public: + + // Constructor/Destructor + SimpleView(QWidget* parent = 0); + ~SimpleView() {}; + +public slots: + + virtual void fileOpen(); + virtual void fileExit(); + +protected: + +protected slots: + +private: + vtkCylinderSource* source; + vtkPolyDataMapper* mapper; + vtkActor* actor; + vtkRenderer* ren; + +}; + +#endif // SIMPLEVIEW_H + diff --git a/Examples/GUI/Qt/SimpleView/main.cxx b/Examples/GUI/Qt/SimpleView/main.cxx new file mode 100644 index 0000000..3d66ecc --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/main.cxx @@ -0,0 +1,45 @@ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +// QT includes +#include + +#if QT_VERSION >= 0x040000 +#include "SimpleView4.h" +#else +#include "SimpleView3.h" +#endif + +int main( int argc, char** argv ) +{ + // QT Stuff + QApplication app( argc, argv ); + + SimpleView mainwindow; + app.setMainWidget(&mainwindow); + mainwindow.show(); + + return app.exec(); +} + diff --git a/Examples/GUI/Qt/SimpleView/uiSimpleView3.ui b/Examples/GUI/Qt/SimpleView/uiSimpleView3.ui new file mode 100644 index 0000000..effc40a --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/uiSimpleView3.ui @@ -0,0 +1,342 @@ + +uiSimpleView + + + uiSimpleView + + + + 0 + 0 + 600 + 480 + + + + SimpleView + + + image0 + + + + unnamed + + + + layout2 + + + + unnamed + + + + groupBox1 + + + groupBox1 + + + + + groupBox1_2 + + + groupBox1 + + + + + + + layout3 + + + + unnamed + + + + vtkWidget + + + + + layout1 + + + + unnamed + + + + active + + + Function... + + + + + progressBar1 + + + + + + + + + + + MenuBar + + + + + + + + + + + + + + + + + + + + + + + + fileNewAction + + + image1 + + + New + + + &New + + + Ctrl+N + + + + + fileOpenAction + + + image2 + + + Open + + + &Open... + + + Ctrl+O + + + + + fileSaveAction + + + image3 + + + Save + + + &Save + + + Ctrl+S + + + + + fileSaveAsAction + + + Save As + + + Save &As... + + + + + + + + filePrintAction + + + image4 + + + Print + + + &Print... + + + Ctrl+P + + + + + fileExitAction + + + Exit + + + E&xit + + + + + + + + helpContentsAction + + + Contents + + + &Contents... + + + + + + + + helpIndexAction + + + Index + + + &Index... + + + + + + + + helpAboutAction + + + About + + + &About + + + + + + + + + 789c3596c96e1dcb0d86f77e0ac1dc5d04bcddd533822c34cfd2d16059529005bbfbb4ac79b68620ef1eeae76f1c0bd627d6e14c56fdfdd7c2e96c77e1afbfbf3dbfd8cbe5b030fcb2a785bfc6d7dbdb8f7fffe75ffffdf63d650bfe2fef9a85f4fd1fdfbef7b6302c48d64e5936817b72910d5f6c1db89b0f79012ec9f33cc779254f7906f932d8e6556ee09c5ce71d789bdce60db82277790dfe41b6bc0227729f97e02d703fce13ecdb03794ab02fb3e07996231ebb271779c4d392cbbc0767e061ec52d83f265b82fd5ec87d827d59220f09f9903bf0381629f4ef90cb04fda2e42a211f724bae13f2a119b9492df81c3c1f5c21ec0f640f00dfff23f702811783c72c215e3920a73442df3e781a9a22f427725b44fe97c85d81f87546b602f1eb01792810af1664fa27a8579e793ac25e4e2e0ae4435ec96511f9b8205705f2a187e4ba403e6422d35f0bce7b4f28ce9f91bd80e023f25446ffdd050f5911f940fdf2d4d765f4df21b92d23fe75725746fddfc85646ff9d90fb32eaff9bec01418efce485b7e71cf28e9c4ae4433ec94519fd31239725f2a17be4aa8c7941bdf2d2ac0afbab643f007d3b644f20b8217b83e1fc13d90710f265f254457ee6e0cacb1bf5f9c36515fe1c93ab2afaf5845c57519f337253a13e724feeaae89f88bfeeba1a2c15d91580f7c95e709c5f22fb8200ef92a71afe6a196c5915f3bc016ebc5d239fd7e4b28e79be245775f86fe4ba0effd7c94d1df3704a6e6bf483dc80db76dec47eb9224f4dccdbafe02eabc39f819cd7a8bf2e93538dfadb33b86bdb06fa7587ec0e402e644f28f896dc3751ef0db22f0830e62fb73635d15f6be4a2897c9c92cb26f2d193ab26e66d915c37b17f56c84d13f316fafa666cc35e224f6dd423fab96fb326e6eb8d9c37d1ff9b64fa67312f83ab8f7ee9c99e10c88dec0500bf93dd639c1fc93eb0b0bf4af6050639f667feb53e231f0fe4a28d7c9c91cb36f64f4daedae88f925cb7d11f2b64fa6b2fe079ed1704ecb764bfb0703eea3f6ffcca847c8d9cb7d10fb8eff2c9d31df1af92bd0120ff49f601027f907d21c1fe0ad91734e498a794557e4142df1679b2e8cfede03aeba23e2fe4bc833f76434e5de4eb885c76d12f23b9ea621fbd927da2711efea6dcc72bf899ec05837ff7646f68f00fb22f349c7f24fb05033e26fb850b7b1764c66798b794caa98ff82e83abcc22be43726e91ef3b72b288ef895c58f4c339d9372ae4b8af5251fa82c7f7dfc9431ffb5dc9fe0080fc81ec0f12c877c9f4cf223fa5aff7d8a78fe4aa8f7cee91bda1c17fe45d1ffb13f3e4eefa0303f29aec0f3070135c667df4db2dd96f44c817c9a98ffbf8845cf4113ffa2bd53e1e317f9b64bf50707e8bec171cf889ec0f009c2fc8f44fa3fe8d5ff7d0af37644f207893ec0507d7646f68e83b22fb40a31e98afd4a6f918f7c16ff234c6fe590ff6e769c4df90f321e2c77e4a9db777e4f39aec1724f49f92fd4101fe20fb8306e731cfc9fc3913f7e32ed91b00f291ec0d0bf91ed91704f88aec0b14e7b1df52fff56001bf92fd4107eec9fea0c5f7afc9fec086fc8a3ccda3ffa33ffb948d11ff9cec0ac0311fc3d7007df1c10bd91716e4426ee6e1df1fb95f78e00db25fc8e089ec0f0a70cce398bb83e00bb2172cecc547454d7b1d74d4b9ff3ff95f2ef497ff5c863c62c367d06bbdd15bbdd37b7dd0477dd267ffdb8b5efacfebd789a8a37f7eeb9bbeeb877eeaa22ee9b2aee8aaaef937d6ddc2869f1df53a7a4eb7fcdcb6eee8aeeee9becef4400ff5488ffd2f3fdcd6954e6e613de6c3edfed4533dd373cdfce7d07fcb3569e1bf955a698d282237f7da6aa767e2c18988492f838cba287399e4427ec9a55cc935f57ec88d1ec9addcc9bd3cc8a33cb9e57b7996175d9257f92d6f5acbbb7cc41d2c9fb2284bb22c2b7a27abb226ebb2219bb225dbb2e37e2ce9bbecca1eeabfaf496672e0d60ee5c87370ec3fa7ae73538e75557ec889fc945341cee44cce65e65e64924b723f0a29dddf1da9745b6af7a1912dbd9698bbce639ae99eac9a9ac889997e5a6f62838d9eef339bcbcfaf3a61c626f775263b7661bfecd22583bcd9955deb8addd8adddb93fef7e760b7a27bbb707ddb3d11ee5c69eecd95edc9fde5eedb79cd99bbddb877dda22f42ef9d9653db2157d942d5b750bcfb62699eb9ddbba6d78165bdbd47be8bdb02ddbb61dddb15ddbb317dbb7997cda811d7a16d7dd8f23aff3bbae22bf333bb61faefbc4def5d17ebaed53bbf22c2cdb999d7bb76c9aea9aece36c6199e5966c471aefb4477db345d7affebd429fad30757f4a438dbdc58f6dd94aabe4d60e3c07a37ee9afad51af8277c09bcc3dfbe7383b9399b5d6f5eaba8fe5423bb9f13af7eef9a98977da9116bdc80c79a8f0e97aebfbde3c23593fe8a167fdd3b3b0e43d3573ab7ee2fbfffef9edff345192e3 + + + 789cedd2b10ac2301405d03d5ff148b62056035241fc04c5511087f425a2432b681d44fc777ba329d6b47fe07d19dee50cc9904cd376b3229d896b6deb13131fed85b4bb95e57db75f3e8434869a93d3548e841c13d3fa5c79ecaad9d52404b540351e83caa833c6a03ad4798e41f5a86c30a816f510126ee94d14d52611fb8e2ad49070a4445ca4447ca4446ca444da07fecac7ffd2956ebe64f81ff4c873215e0583a9b0 + + + 789cad914d0ac2301085f739c5d0d915b11a140ae211149782b898448b2e5a41eb42c4bb9b9fa6a67644045f0299978f37134896c27ab5803413979aeaa3067da033a4bb6b59de36dbf95d245282d953182703910c41c3f254ed6d8da6c69193b5dada7c924b6fc9dac2c85b156c51b83eacfe41d0c89defc4dfa2dd7c37fc44b025a179043c4152a4b055f4365414ad0e8901fd94c1ae5e19441da9211c68e7f44098d3074d86019e70a0210c089958df7ffb31134fa13797a8 + + + 789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523232520022530543251d2e253d856405bffcbc54105b19c856360003103711c4b530b13082709340dc644310047193c1dcc424d314883958015846190b80ca24262a2721012087349964a030ba69c9c9303d403e9132087b68279388ecff4414193440948c32aa71d86470bb80863258a21b9a0eb0a7905a6b2e006d59a436 + + + 789c7d944973db461085effa152cf54d956a932089a55239c896572d96bcc4b253390033186ea2488aa416a7f2dfd3db0cbd44e6d340f8f8def43406209e1c742ecf4f3b074ff6d69b7a33711d37ae6f3a077e3b9f3ffcf5f71fffeced675987fecab293edffb6b77fb1e9b8ced9e2ba65c08c00baf2117e2f5c86d02d99e196b9d7ed963df53f2ab3c47789258fa7c26564688d4bf30f23673de113e6ac1719ae9459e27f4d5c893f17ae126f8d2be3ebc87d9dff4e3904f317ccfd5ef23f28b3c45f26963c7e510ec1fc9570157dd81857967f883c90cd8635f3208b8c0b6596f863e17a500fd597fe8744c35afc1be33aef8bff5ad9b5e637cc7993f7f346fca571637c1fb9d0f99f9543b07ab2df453ff9723d0551a1f3d791cb8170573904f3a5bf725034e66f133be96fa44c1246799e4a573495e461a29cfcbbc8e64f8d9df96564f5519e876a1019668975fda05c593d5c25d67a6f945d6ef3bdb08b3ed491eba1e467c6561fcf229bff4ad9b5c6c7ccf530fa8089bdf8136596703fb1f800c23ee5ff548e3e7a636f3c8ddc68bd8ab91926066596b05c5fe359c285b2cf8de5f7ed7296f050b825d6f74763dc1a0f227bcdbf60f679e29789353f5666093f4facfe857208e63f156e93df8bdc16c223e358ff28b2f939735b240eca2ce1678983f0a57208e6bf150ec96f8d83f127e650b084cf85e5a32fdf9d10b0c6c6e44835c9631dfd9ff235b618925ad1e89779278af5750df7681ea40316d8111eef876a79ad977ae773d8257ec8efead629fdeb3ca4ba9ae6e11fcdbbef6aa72b7934ef695702eddf4e631a13d2f4c73cd599e115f533a639bbc173e6788d0b5cf23a314fe915dee01a37df698bb77887f7f8805ff190e64c342fb59fe2333ca2e373d30b7c89aff035bec1634a9e904ef1417faf78866ff1fc275de03b7c4fa3a1553e50fd8f78a2ef0bfcf43fe973bcc4cff805bb74d6a3de0e31b37c9f561fe090c6583a19612e9d1dd179417db1575237191eeafb172b9cd22a7d409a7bcc8f0c4e68f01900ef44090db8547f4ee9a966456732445083078f779a8756dfdf52f19b1cd59c699254e31c46d0703f30b6fa5239a5d27faabc22b78409de838316bdd51fd1377730a531a12bd363c949aa3d936f1a6821e8fda566aef8fe011d612eba860569495a9196721ebe7d7ed0c30dac491b58d2bd21c116b634bf25ddd2fd9dd9f3f6efef7bff0111915e41 + + + + + fileNewAction + activated() + uiSimpleView + fileNew() + + + fileOpenAction + activated() + uiSimpleView + fileOpen() + + + fileSaveAction + activated() + uiSimpleView + fileSave() + + + fileSaveAsAction + activated() + uiSimpleView + fileSaveAs() + + + filePrintAction + activated() + uiSimpleView + filePrint() + + + fileExitAction + activated() + uiSimpleView + fileExit() + + + helpIndexAction + activated() + uiSimpleView + helpIndex() + + + helpContentsAction + activated() + uiSimpleView + helpContents() + + + helpAboutAction + activated() + uiSimpleView + helpAbout() + + + + QVTKWidget.h + + + fileNew() + fileOpen() + fileSave() + fileSaveAs() + filePrint() + fileExit() + helpIndex() + helpContents() + helpAbout() + + + diff --git a/Examples/GUI/Qt/SimpleView/uiSimpleView4.ui b/Examples/GUI/Qt/SimpleView/uiSimpleView4.ui new file mode 100644 index 0000000..dd23bba --- /dev/null +++ b/Examples/GUI/Qt/SimpleView/uiSimpleView4.ui @@ -0,0 +1,108 @@ + + + + + MainWindow + + + + 0 + 0 + 560 + 398 + + + + MainWindow + + + + + 8 + + + 6 + + + + + 0 + + + 6 + + + + + GroupBox + + + + + + + + 16 + 16 + + + + GroupBox + + + + + + + + + 0 + + + 6 + + + + + + + + 0 + + + 6 + + + + + Function... + + + + + + + 24 + + + + + + + + + + + + + + QVTKWidget + +
QVTKWidget.h
+ 0 + +
+
+ + +
diff --git a/Examples/GUI/Tcl/BoxWidget.tcl b/Examples/GUI/Tcl/BoxWidget.tcl new file mode 100644 index 0000000..ad1f1c2 --- /dev/null +++ b/Examples/GUI/Tcl/BoxWidget.tcl @@ -0,0 +1,89 @@ +package require vtk +package require vtkinteraction + +# Demonstrate how to use the vtkBoxWidget 3D widget, +# This script uses a 3D box widget to define a "clipping box" to clip some +# simple geometry (a mace). Make sure that you hit the "W" key to activate the widget. + +# Create a mace out of filters. +# +vtkSphereSource sphere +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 + +# The sphere and spikes are appended into a single polydata. This just makes things +# simpler to manage. +vtkAppendPolyData apd + apd AddInput [glyph GetOutput] + apd AddInput [sphere GetOutput] +vtkPolyDataMapper maceMapper + maceMapper SetInputConnection [apd GetOutputPort] +vtkLODActor maceActor + maceActor SetMapper maceMapper + maceActor VisibilityOn + +# This portion of the code clips the mace with the vtkPlanes implicit function. +# The clipped region is colored green. +vtkPlanes planes +vtkClipPolyData clipper + clipper SetInputConnection [apd GetOutputPort] + clipper SetClipFunction planes + clipper InsideOutOn +vtkPolyDataMapper selectMapper + selectMapper SetInputConnection [clipper GetOutputPort] +vtkLODActor selectActor + selectActor SetMapper selectMapper + [selectActor GetProperty] SetColor 0 1 0 + selectActor VisibilityOff + selectActor SetScale 1.01 1.01 1.01 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# The SetInteractor method is how 3D widgets are associated with the render +# window interactor. Internally, SetInteractor sets up a bunch of callbacks +# using the Command/Observer mechanism (AddObserver()). +vtkBoxWidget boxWidget + boxWidget SetInteractor iren + boxWidget SetPlaceFactor 1.25 + +ren1 AddActor maceActor +ren1 AddActor selectActor + +# Add the actors to the renderer, set the background and size +# +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# Place the interactor initially. The input to a 3D widget is used to +# initially position and scale the widget. The EndInteractionEvent is +# observed which invokes the SelectPolygons callback. +boxWidget SetInput [glyph GetOutput] +boxWidget PlaceWidget +boxWidget AddObserver EndInteractionEvent SelectPolygons + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# This does the actual work: updates the vtkPlanes implicit function. +# This in turn causes the pipeline to update. +proc SelectPolygons {} { + boxWidget GetPlanes planes + selectActor VisibilityOn +} diff --git a/Examples/GUI/Tcl/CustomInteraction.tcl b/Examples/GUI/Tcl/CustomInteraction.tcl new file mode 100644 index 0000000..c97fdb9 --- /dev/null +++ b/Examples/GUI/Tcl/CustomInteraction.tcl @@ -0,0 +1,238 @@ +# +# This example creates a polygonal model of a cone, and then renders it to +# the screen. It also defines an interaction style by creating a set +# of Command/Observers. (Note: it is far more efficient to create new +# styles by subclassing vtkInteractorStyle. This is just an illustrative +# example.) If you really want trackball behavior, look at the +# vtkInteractorStyleTrackballCamera class. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the VTK commands to Tcl. +# +package require vtk + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +vtkActor coneActor +coneActor SetMapper coneMapper + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300. +# +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +# +# Define custom interaction. +# +vtkRenderWindowInteractor iren +iren SetInteractorStyle "" +iren SetRenderWindow renWin + +# +# Add the observers to watch for particular events. These invoke +# Tcl procedures. +# +set Rotating 0 +set Panning 0 +set Zooming 0 +iren AddObserver LeftButtonPressEvent {global Rotating; set Rotating 1} +iren AddObserver LeftButtonReleaseEvent {global Rotating; set Rotating 0} +iren AddObserver MiddleButtonPressEvent {global Panning; set Panning 1} +iren AddObserver MiddleButtonReleaseEvent {global Panning; set Panning 0} +iren AddObserver RightButtonPressEvent {global Zooming; set Zooming 1} +iren AddObserver RightButtonReleaseEvent {global Zooming; set Zooming 0} +iren AddObserver MouseMoveEvent MouseMove +iren AddObserver KeyPressEvent Keypress + +# General high-level logic +# +proc MouseMove {} { + global Rotating Panning Zooming + + set lastXYpos [iren GetLastEventPosition] + set lastX [lindex $lastXYpos 0] + set lastY [lindex $lastXYpos 1] + + set xypos [iren GetEventPosition] + set x [lindex $xypos 0] + set y [lindex $xypos 1] + + set center [renWin GetSize] + set centerX [expr [lindex $center 0] / 2.0] + set centerY [expr [lindex $center 1] / 2.0] + + if { $Rotating } { + Rotate ren1 [ren1 GetActiveCamera] $x $y $lastX $lastY $centerX $centerY + } elseif { $Panning } { + Pan ren1 [ren1 GetActiveCamera] $x $y $lastX $lastY $centerX $centerY + } elseif { $Zooming } { + Dolly ren1 [ren1 GetActiveCamera] $x $y $lastX $lastY $centerX $centerY + } +} + +proc Keypress {} { + set key [iren GetKeySym] + if { $key == "e" } { + vtkCommand DeleteAllObjects + exit + } elseif { $key == "w" } { + Wireframe + } elseif { $key == "s" } { + Surface + } +} + +# +# Routines that translate the events into camera motions. +# +# This one is associated with the left mouse button. It translates x and y +# relative motions into camera azimuth and elevation commands. +# +proc Rotate {renderer camera x y lastX lastY centerX centerY} { + + $camera Azimuth [expr ($lastX - $x)] + $camera Elevation [expr ($lastY - $y)] + $camera OrthogonalizeViewUp + + renWin Render +} + +# Pan translates x-y motion into translation of the focal point and position. +# +proc Pan {renderer camera x y lastX lastY centerX centerY} { + + set FPoint [$camera GetFocalPoint] + set FPoint0 [lindex $FPoint 0] + set FPoint1 [lindex $FPoint 1] + set FPoint2 [lindex $FPoint 2] + + set PPoint [$camera GetPosition] + set PPoint0 [lindex $PPoint 0] + set PPoint1 [lindex $PPoint 1] + set PPoint2 [lindex $PPoint 2] + + $renderer SetWorldPoint $FPoint0 $FPoint1 $FPoint2 1.0 + $renderer WorldToDisplay + set DPoint [$renderer GetDisplayPoint] + set focalDepth [lindex $DPoint 2] + + set APoint0 [expr $centerX + ($x - $lastX)] + set APoint1 [expr $centerY + ($y - $lastY)] + + $renderer SetDisplayPoint $APoint0 $APoint1 $focalDepth + $renderer DisplayToWorld + set RPoint [$renderer GetWorldPoint] + set RPoint0 [lindex $RPoint 0] + set RPoint1 [lindex $RPoint 1] + set RPoint2 [lindex $RPoint 2] + set RPoint3 [lindex $RPoint 3] + if { $RPoint3 != 0.0 } { + set RPoint0 [expr $RPoint0 / $RPoint3] + set RPoint1 [expr $RPoint1 / $RPoint3] + set RPoint2 [expr $RPoint2 / $RPoint3] + } + + $camera SetFocalPoint \ + [expr ($FPoint0 - $RPoint0)/2.0 + $FPoint0] \ + [expr ($FPoint1 - $RPoint1)/2.0 + $FPoint1] \ + [expr ($FPoint2 - $RPoint2)/2.0 + $FPoint2] + + $camera SetPosition \ + [expr ($FPoint0 - $RPoint0)/2.0 + $PPoint0] \ + [expr ($FPoint1 - $RPoint1)/2.0 + $PPoint1] \ + [expr ($FPoint2 - $RPoint2)/2.0 + $PPoint2] + + renWin Render +} + +# Dolly converts y-motion into a camera dolly commands. + +proc Dolly {renderer camera x y lastX lastY centerX centerY} { + set dollyFactor [expr pow(1.02,(0.5*($y - $lastY)))] + + if {[$camera GetParallelProjection]} { + set parallelScale [expr [$camera GetParallelScale] * $dollyFactor]; + $camera SetParallelScale $parallelScale; + } else { + $camera Dolly $dollyFactor + $renderer ResetCameraClippingRange + } + + renWin Render +} + +# Wireframe sets the representation of all actors to wireframe. +# +proc Wireframe {} { + set actors [ren1 GetActors] + + $actors InitTraversal + set actor [$actors GetNextItem] + while { $actor != "" } { + [$actor GetProperty] SetRepresentationToWireframe + set actor [$actors GetNextItem] + } + + renWin Render +} + +# Surface sets the representation of all actors to surface. +# +proc Surface {} { + set actors [ren1 GetActors] + + $actors InitTraversal + set actor [$actors GetNextItem] + while { $actor != "" } { + [$actor GetProperty] SetRepresentationToSurface + set actor [$actors GetNextItem] + } + + renWin Render +} + +iren Initialize +wm withdraw . + + + diff --git a/Examples/GUI/Tcl/ImagePlaneWidget.tcl b/Examples/GUI/Tcl/ImagePlaneWidget.tcl new file mode 100644 index 0000000..ba18c5e --- /dev/null +++ b/Examples/GUI/Tcl/ImagePlaneWidget.tcl @@ -0,0 +1,373 @@ +package require vtk +package require vtkinteraction + +# This example demonstrates how to use the vtkImagePlaneWidget +# to probe a 3D image dataset with three orthogonal planes. +# Buttons are provided to: +# a) capture the render window display to a tiff file +# b) x,y,z buttons reset the widget to orthonormal +# positioning, set the horizontal slider to move the +# associated widget along its normal, and set the +# camera to face the widget +# c) right clicking on x,y,z buttons pops up a menu to set +# the associated widget's reslice interpolation mode +# + +# Start by loading some data. +# +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + v16 Update + +scan [[v16 GetOutput] GetWholeExtent] "%d %d %d %d %d %d" \ + xMin xMax yMin yMax zMin zMax + +set spacing [[v16 GetOutput] GetSpacing] +set sx [lindex $spacing 0] +set sy [lindex $spacing 1] +set sz [lindex $spacing 2] + +set origin [[v16 GetOutput] GetOrigin] +set ox [lindex $origin 0] +set oy [lindex $origin 1] +set oz [lindex $origin 2] + +# An outline is shown for context. +# +vtkOutlineFilter outline + outline SetInputConnection [v16 GetOutputPort] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# The shared picker enables us to use 3 planes at one time +# and gets the picking order right +# +vtkCellPicker picker + picker SetTolerance 0.005 + +# The 3 image plane widgets are used to probe the dataset. +# +vtkImagePlaneWidget planeWidgetX + planeWidgetX DisplayTextOn + planeWidgetX SetInput [v16 GetOutput] + planeWidgetX SetPlaneOrientationToXAxes + planeWidgetX SetSliceIndex 32 + planeWidgetX SetPicker picker + planeWidgetX SetKeyPressActivationValue "x" + set prop1 [planeWidgetX GetPlaneProperty] + $prop1 SetColor 1 0 0 + +vtkImagePlaneWidget planeWidgetY + planeWidgetY DisplayTextOn + planeWidgetY SetInput [v16 GetOutput] + planeWidgetY SetPlaneOrientationToYAxes + planeWidgetY SetSliceIndex 32 + planeWidgetY SetPicker picker + planeWidgetY SetKeyPressActivationValue "y" + set prop2 [planeWidgetY GetPlaneProperty] + $prop2 SetColor 1 1 0 + planeWidgetY SetLookupTable [planeWidgetX GetLookupTable] + +# for the z-slice, turn off texture interpolation: +# interpolation is now nearest neighbour, to demonstrate +# cross-hair cursor snapping to pixel centers +# +vtkImagePlaneWidget planeWidgetZ + planeWidgetZ DisplayTextOn + planeWidgetZ SetInput [v16 GetOutput] + planeWidgetZ SetPlaneOrientationToZAxes + planeWidgetZ SetSliceIndex 46 + planeWidgetZ SetPicker picker + planeWidgetZ SetKeyPressActivationValue "z" + set prop3 [planeWidgetZ GetPlaneProperty] + $prop3 SetColor 0 0 1 + planeWidgetZ SetLookupTable [planeWidgetX GetLookupTable] + +set current_widget planeWidgetZ +set mode_widget planeWidgetZ + +# Create the RenderWindow and Renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + +# Add the outline actor to the renderer, set the background color and size +# +ren1 AddActor outlineActor +renWin SetSize 600 600 +ren1 SetBackground 0.1 0.1 0.2 + + +# Create the GUI +# +wm withdraw . +toplevel .top +wm title .top "vtkImagePlaneWidget Example" +wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit + +set popm [menu .top.mm -tearoff 0] +set mode 1 +$popm add radiobutton -label "nearest" -variable mode -value 0 \ + -command SetInterpolation +$popm add radiobutton -label "linear" -variable mode -value 1 \ + -command SetInterpolation +$popm add radiobutton -label "cubic" -variable mode -value 2 \ + -command SetInterpolation + +set display_frame [frame .top.f1] + +set ctrl_buttons [frame .top.btns] + +pack $display_frame $ctrl_buttons \ + -side top -anchor n \ + -fill both -expand f + +set quit_button [button $ctrl_buttons.btn1 \ + -text "Quit" \ + -command ::vtk::cb_exit] + +set capture_button [button $ctrl_buttons.btn2 \ + -text "Tif" \ + -command CaptureImage] + +set x_button [button $ctrl_buttons.btn3 \ + -text "x" \ + -command AlignXaxis] + +set y_button [button $ctrl_buttons.btn4 \ + -text "y" \ + -command AlignYaxis] + +set z_button [button $ctrl_buttons.btn5 \ + -text "z" \ + -command AlignZaxis] + +set last_btn -1 +bind $x_button "set last_btn 0; configMenu; $popm post %X %Y" +bind $y_button "set last_btn 1; configMenu; $popm post %X %Y" +bind $z_button "set last_btn 2; configMenu; $popm post %X %Y" + +# Share the popup menu among buttons, keeping +# track of associated widget's interpolation mode +# +proc configMenu { } { + global last_btn popm mode mode_widget + if { $last_btn == 0 } { + set mode_widget planeWidgetX + } elseif { $last_btn == 1 } { + set mode_widget planeWidgetY + } else { + set mode_widget planeWidgetZ + } + set mode [$mode_widget GetResliceInterpolate] + $popm entryconfigure $last_btn -variable mode +} + +pack $quit_button $capture_button $x_button $y_button $z_button \ + -side left \ + -expand t -fill both + +# Create the render widget +# +set renderer_frame [frame $display_frame.rFm] + +pack $renderer_frame \ + -padx 3 -pady 3 \ + -side left -anchor n \ + -fill both -expand f + +set render_widget [vtkTkRenderWidget $renderer_frame.r \ + -width 600 \ + -height 600 \ + -rw renWin] + +pack $render_widget $display_frame \ + -side top -anchor n \ + -fill both -expand f + +# Add a slice scale to browse the current slice stack +# + +set slice_number [$current_widget GetSliceIndex] + +scale .top.slice \ + -from $zMin \ + -to $zMax \ + -orient horizontal \ + -command SetSlice \ + -variable slice_number \ + -label "Slice" + +pack .top.slice \ + -fill x -expand f + +proc SetSlice {slice} { + global current_widget + $current_widget SetSliceIndex $slice + ren1 ResetCameraClippingRange + renWin Render +} + +::vtk::bind_tk_render_widget $render_widget +# Set the interactor for the widgets +# +set iact [[$render_widget GetRenderWindow] GetInteractor] +planeWidgetX SetInteractor $iact +planeWidgetX On +planeWidgetY SetInteractor $iact +planeWidgetY On +planeWidgetZ SetInteractor $iact +planeWidgetZ On + +# Create an initial interesting view +# +set cam1 [ren1 GetActiveCamera] +$cam1 Elevation 110 +$cam1 SetViewUp 0 0 -1 +$cam1 Azimuth 45 +ren1 ResetCameraClippingRange + +# Render it +# +$render_widget Render + +# Supporting procedures +# + +# Align the camera so that it faces the desired widget +# +proc AlignCamera { } { + global ox oy oz sx sy sz xMax xMin yMax yMin zMax zMin slice_number + global current_widget + set cx [expr $ox + (0.5*($xMax - $xMin))*$sx] + set cy [expr $oy + (0.5*($yMax - $yMin))*$sy] + set cz [expr $oy + (0.5*($zMax - $zMin))*$sz] + set vx 0 + set vy 0 + set vz 0 + set nx 0 + set ny 0 + set nz 0 + set iaxis [$current_widget GetPlaneOrientation] + if { $iaxis == 0 } { + set vz -1 + set nx [expr $ox + $xMax*$sx] + set cx [expr $ox + $slice_number*$sx] + } elseif { $iaxis == 1 } { + set vz -1 + set ny [expr $oy + $yMax*$sy] + set cy [expr $oy + $slice_number*$sy] + } else { + set vy 1 + set nz [expr $oz + $zMax*$sz] + set cz [expr $oz + $slice_number*$sz] + } + set px [expr $cx + $nx*2] + set py [expr $cy + $ny*2] + set pz [expr $cz + $nz*3] + + set camera [ ren1 GetActiveCamera ] + $camera SetViewUp $vx $vy $vz + $camera SetFocalPoint $cx $cy $cz + $camera SetPosition $px $py $pz + $camera OrthogonalizeViewUp + ren1 ResetCameraClippingRange + renWin Render +} + +# Capture the display and place in a tiff +# +proc CaptureImage { } { + vtkWindowToImageFilter w2i + vtkTIFFWriter writer + + w2i SetInput renWin + w2i Update + writer SetInputConnection [w2i GetOutputPort] + writer SetFileName image.tif + renWin Render + writer Write + + writer Delete + w2i Delete +} + +# Align the widget back into orthonormal position, +# set the slider to reflect the widget's position, +# call AlignCamera to set the camera facing the widget +# +proc AlignXaxis { } { + global xMax xMin current_widget slice_number + set po [ planeWidgetX GetPlaneOrientation ] + if { $po == 3 } { + planeWidgetX SetPlaneOrientationToXAxes + set slice_number [expr ($xMax - $xMin)/2] + planeWidgetX SetSliceIndex $slice_number + } else { + set slice_number [planeWidgetX GetSliceIndex] + } + set current_widget planeWidgetX + .top.slice config -from $xMin -to $xMax + .top.slice set $slice_number + AlignCamera +} + +proc AlignYaxis { } { + global yMin yMax current_widget slice_number + set po [ planeWidgetY GetPlaneOrientation ] + if { $po == 3 } { + planeWidgetY SetPlaneOrientationToYAxes + set slice_number [expr ($yMax - $yMin)/2] + planeWidgetY SetSliceIndex $slice_number + } else { + set slice_number [planeWidgetY GetSliceIndex] + } + set current_widget planeWidgetY + .top.slice config -from $yMin -to $yMax + .top.slice set $slice_number + AlignCamera +} + +proc AlignZaxis { } { + global zMin zMax current_widget slice_number + set po [ planeWidgetZ GetPlaneOrientation ] + if { $po == 3 } { + planeWidgetZ SetPlaneOrientationToZAxes + set slice_number [expr ($zMax - $zMin)/2] + planeWidgetZ SetSliceIndex $slice_number + } else { + set slice_number [planeWidgetZ GetSliceIndex] + } + set current_widget planeWidgetZ + .top.slice config -from $zMin -to $zMax + .top.slice set $slice_number + AlignCamera +} + +# Set the widget's reslice interpolation mode +# to the corresponding popup menu choice +# +proc SetInterpolation { } { + global mode_widget mode + if { $mode == 0 } { + $mode_widget TextureInterpolateOff + } else { + $mode_widget TextureInterpolateOn + } + $mode_widget SetResliceInterpolate $mode + renWin Render +} + + + + + diff --git a/Examples/GUI/Tcl/ImageTracerWidget.tcl b/Examples/GUI/Tcl/ImageTracerWidget.tcl new file mode 100644 index 0000000..32bb6ca --- /dev/null +++ b/Examples/GUI/Tcl/ImageTracerWidget.tcl @@ -0,0 +1,267 @@ +package require vtk +package require vtkinteraction + +# This example demonstrates how to use the vtkImageTracerWidget +# to trace on a slice of a 3D image dataset on one of its orthogonal planes. +# The button actions and key modifiers are as follows for controlling the +# widget: +# 1) left button click over the image, hold and drag draws a free hand line. +# 2) left button click and release erases the widget line, if it exists, and +# repositions the handle. +# 3) middle button click starts a snap line. The snap line can be +# terminated by clicking the middle button while depressing the ctrl key. +# 4) when tracing or snap drawing a line, if the last cursor position is +# within specified tolerance to the first handle, the widget line will form +# a closed loop with only one handle. +# 5) right button clicking and holding on any handle that is part of a snap +# line allows handle dragging. Any existing line segments are updated +# accordingly. +# 6) ctrl key + right button down on any handle will erase it. Any existing +# snap line segments are updated accordingly. If the line was formed by +# continous tracing, the line is deleted leaving one handle. +# 7) shift key + right button down on any snap line segment will insert a +# handle at the cursor position. The snap line segment is split accordingly. +# + +# Start by loading some data. +# +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 Update + + set range [[v16 GetOutput] GetScalarRange] + set min [lindex $range 0] + set max [lindex $range 1] + set diff [expr $max - $min] + set slope [expr 255.0/$diff] + set inter [expr -$slope*$min] + set shift [expr $inter/$slope] + +vtkImageShiftScale shifter + shifter SetShift $shift + shifter SetScale $slope + shifter SetOutputScalarTypeToUnsignedChar + shifter SetInputConnection [v16 GetOutputPort] + shifter ReleaseDataFlagOff + shifter Update + +# Display a y-z plane. +# +vtkImageActor imageActor + imageActor SetInput [shifter GetOutput] + imageActor VisibilityOn + imageActor SetDisplayExtent 31 31 0 63 0 92 + imageActor InterpolateOff + + set spc [[shifter GetOutput] GetSpacing] + set orig [[shifter GetOutput] GetOrigin] + set x0 [lindex $orig 0] + set xspc [lindex $spc 0] + set pos [expr $x0 + $xspc*31.0] + +# An alternative would be to formulate position in this case by: +# set bounds [imageActor GetBounds] +# set pos [lindex $bounds 0] +# + +vtkRenderer ren1 + ren1 SetBackground 0.4 0.4 0.5 +vtkRenderer ren2 + ren2 SetBackground 0.5 0.4 0.4 + +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin SetSize 600 300 + +ren1 SetViewport 0 0 0.5 1 +ren2 SetViewport 0.5 0 1 1 + +vtkInteractorStyleImage interactor + +vtkRenderWindowInteractor iren + iren SetInteractorStyle interactor + iren SetRenderWindow renWin + +vtkExtractVOI extract + extract SetVOI 31 31 0 63 0 92 + extract SetSampleRate 1 1 1 + extract SetInputConnection [shifter GetOutputPort] + extract ReleaseDataFlagOff + +vtkImageActor imageActor2 + imageActor2 SetInput [extract GetOutput] + imageActor2 VisibilityOn + imageActor2 SetDisplayExtent 31 31 0 63 0 92 + imageActor2 InterpolateOff + +# Set up the image tracer widget +# +vtkImageTracerWidget itw +# +# Set the tolerance for capturing last handle when near first handle +# to form closed paths. +# + itw SetCaptureRadius 1.5 + [itw GetGlyphSource] SetColor 1 0 0 +# +# Set the size of the glyph handle +# + [itw GetGlyphSource] SetScale 3.0 +# +# Set the initial rotation of the glyph if desired. The default glyph +# set internally by the widget is a '+' so rotating 45 deg. gives a 'x' +# + [itw GetGlyphSource] SetRotationAngle 45.0 + [itw GetGlyphSource] Modified + itw ProjectToPlaneOn + itw SetProjectionNormalToXAxes + itw SetProjectionPosition $pos + itw SetViewProp imageActor + itw SetInput [shifter GetOutput] + itw SetInteractor iren + itw PlaceWidget +# +# When the underlying vtkDataSet is a vtkImageData, the widget can be +# forced to snap to either nearest pixel points, or pixel centers. Here +# it is turned off. +# + itw SnapToImageOff +# +# Automatically form closed paths. +# + itw AutoCloseOn + +# Set up a vtkSplineWidget in the second renderer and have +# its handles set by the tracer widget. +# +vtkSplineWidget isw + isw SetCurrentRenderer ren2 + isw SetDefaultRenderer ren2 + isw SetInput [extract GetOutput] + isw SetInteractor iren + set bnds [imageActor2 GetBounds] + isw PlaceWidget [lindex $bnds 0] [lindex $bnds 1] [lindex $bnds 2] [lindex $bnds 3] [lindex $bnds 4] [lindex $bnds 5] + isw ProjectToPlaneOn + isw SetProjectionNormalToXAxes + isw SetProjectionPosition $pos + +# Have the widgets control each others handle positions. +# + itw AddObserver EndInteractionEvent AdjustSpline + isw AddObserver EndInteractionEvent AdjustTracer + + itw On + isw On + +vtkPolyData poly +vtkPoints points +vtkPolyData spoly + +# Set up a pipleline to demonstrate extraction of a 2D +# region of interest. Defining a closed clockwise path using the +# tracer widget will extract all pixels within the loop. A counter +# clockwise path provides the dual region of interest. +# +vtkLinearExtrusionFilter extrude + extrude SetInput spoly + extrude SetScaleFactor 1 + extrude SetExtrusionTypeToNormalExtrusion + extrude SetVector 1 0 0 + +vtkPolyDataToImageStencil dataToStencil +dataToStencil SetInputConnection [extrude GetOutputPort] + +vtkImageStencil stencil +stencil SetInputConnection [extract GetOutputPort] +stencil SetStencil [dataToStencil GetOutput] +stencil ReverseStencilOff +stencil SetBackgroundValue 128 + +# Add all the actors. +# +ren1 AddViewProp imageActor +ren2 AddViewProp imageActor2 + +# Render the image. +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +[ren1 GetActiveCamera] SetViewUp 0 1 0 +[ren1 GetActiveCamera] Azimuth 270 +[ren1 GetActiveCamera] Roll 270 +[ren1 GetActiveCamera] Dolly 1.7 +ren1 ResetCameraClippingRange + +[ren2 GetActiveCamera] SetViewUp 0 1 0 +[ren2 GetActiveCamera] Azimuth 270 +[ren2 GetActiveCamera] Roll 270 +[ren2 GetActiveCamera] Dolly 1.7 +ren2 ResetCameraClippingRange + +renWin Render + +# Prevent the tk window from showing up then start the event loop. +wm withdraw . + +proc AdjustSpline { } { + + set closed [itw IsClosed] + + if { $closed } { + isw ClosedOn + } else { + isw ClosedOff + imageActor2 SetInput [extract GetOutput] + } + + set npts [ itw GetNumberOfHandles ] + if { $npts < 2 } { + return + } + + itw GetPath poly + set pts [poly GetPoints] + + isw InitializeHandles $pts + + if { $closed } { + isw GetPolyData spoly + stencil Update + imageActor2 SetInput [stencil GetOutput] + } +} + +proc AdjustTracer { } { + + set npts [isw GetNumberOfHandles] + + points Reset + + for {set i 0} {$i < $npts} {incr i} { + set pt [isw GetHandlePosition $i] + points InsertNextPoint [lindex $pt 0] [lindex $pt 1] [lindex $pt 2] + } + + set closed [isw IsClosed] + + if { $closed } { + set ac [itw GetAutoClose] + if { $ac } { + set pt [isw GetHandlePosition 0] + points InsertNextPoint [lindex $pt 0] [lindex $pt 1] [lindex $pt 2] + } + isw GetPolyData spoly + stencil Update + imageActor2 SetInput [stencil GetOutput] + } else { + imageActor2 SetInput [extract GetOutput] + } + + itw InitializeHandles points +} diff --git a/Examples/GUI/Tcl/ImplicitPlaneWidget.tcl b/Examples/GUI/Tcl/ImplicitPlaneWidget.tcl new file mode 100644 index 0000000..343323f --- /dev/null +++ b/Examples/GUI/Tcl/ImplicitPlaneWidget.tcl @@ -0,0 +1,85 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# This example demonstrates how to use the vtkPlaneWidget to probe +# a dataset and then generate contours on the probed data. + +# Create a mace out of filters. +# +vtkSphereSource sphere +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSourceConnection [cone GetOutputPort] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 + +# The sphere and spikes are appended into a single polydata. +# This just makes things simpler to manage. +vtkAppendPolyData apd + apd AddInputConnection [glyph GetOutputPort] + apd AddInputConnection [sphere GetOutputPort] + +vtkPolyDataMapper maceMapper +maceMapper SetInputConnection [apd GetOutputPort] + +vtkLODActor maceActor + maceActor SetMapper maceMapper + maceActor VisibilityOn + +# This portion of the code clips the mace with the vtkPlanes +# implicit function. The clipped region is colored green. +vtkPlane plane +vtkClipPolyData clipper + clipper SetInputConnection [apd GetOutputPort] + clipper SetClipFunction plane + clipper InsideOutOn + +vtkPolyDataMapper selectMapper + selectMapper SetInputConnection [clipper GetOutputPort] + +vtkLODActor selectActor + selectActor SetMapper selectMapper + [selectActor GetProperty] SetColor 0 1 0 + selectActor VisibilityOff + selectActor SetScale 1.01 1.01 1.01 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Associate the line widget with the interactor +vtkImplicitPlaneWidget planeWidget + planeWidget SetInteractor iren + planeWidget SetPlaceFactor 1.25 + planeWidget SetInput [glyph GetOutput] + planeWidget PlaceWidget + planeWidget AddObserver InteractionEvent myCallback + +ren1 AddActor maceActor +ren1 AddActor selectActor + +# Add the actors to the renderer, set the background and size +# +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# Prevent the tk window from showing up then start the event loop. +wm withdraw . + +proc myCallback {} { + planeWidget GetPlane plane + selectActor VisibilityOn +} diff --git a/Examples/GUI/Tcl/Mace.tcl b/Examples/GUI/Tcl/Mace.tcl new file mode 100644 index 0000000..4f54882 --- /dev/null +++ b/Examples/GUI/Tcl/Mace.tcl @@ -0,0 +1,144 @@ +# +# This example creates a polygonal model of a mace made of a sphere +# and a set of cones adjusted on its surface using glyphing. +# +# The sphere is rendered to the screen through the usual VTK render window +# and interactions is performed using vtkRenderWindowInteractor. +# The basic setup of source -> mapper -> actor -> renderer -> +# renderwindow is typical of most VTK programs. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# +# Next we create an instance of vtkSphereSource and set some of its +# properties +# +vtkSphereSource sphere + sphere SetThetaResolution 8 + sphere SetPhiResolution 8 + +# +# We create an instance of vtkPolyDataMapper to map the polygonal data +# into graphics primitives. We connect the output of the sphere source +# to the input of this mapper +# +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + +# +# Create an actor to represent the sphere. The actor coordinates rendering of +# the graphics primitives for a mapper. We set this actor's mapper to be +# the mapper which we created above. +# +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# +# Next we create an instance of vtkConeSource that will be used to +# set the glyphs on the sphere's surface +# +vtkConeSource cone + cone SetResolution 6 + +# +# Glyphing is a visualization technique that represents data by using +# symbol or glyphs. In VTK, the vtkGlyph3D class allows you to create +# glyphs that can be scaled, colored and oriented along a +# direction. The glyphs (here, cones) are copied at each point of the +# input dataset (the sphere's vertices). +# +# Create a vtkGlyph3D to dispatch the glyph/cone geometry (SetSource) on the +# sphere dataset (SetInput). Each glyph is oriented through the dataset +# normals (SetVectorModeToUseNormal). The resulting dataset is a set +# of cones lying on a sphere surface. +# +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 + +# +# We create an instance of vtkPolyDataMapper to map the polygonal data +# into graphics primitives. We connect the output of the glyph3d +# to the input of this mapper +# +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] + +# +# Create an actor to represent the glyphs. The actor coordinates rendering of +# the graphics primitives for a mapper. We set this actor's mapper to be +# the mapper which we created above. +# +vtkActor spikeActor + spikeActor SetMapper spikeMapper + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +vtkRenderer renderer + renderer AddActor sphereActor + renderer AddActor spikeActor + renderer SetBackground 1 1 1 + +# +# We create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300 +# +vtkRenderWindow renWin + renWin AddRenderer renderer + renWin SetSize 300 300 + +# +# Finally we create the render window interactor handling user +# interactions. vtkRenderWindowInteractor provides a +# platform-independent interaction mechanism for mouse/key/time +# events. vtkRenderWindowInteractor also provides controls for +# picking, rendering frame rate, and headlights. It is associated +# to a render window. +# +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# +# vtkRenderWindowInteractor provides default key bindings. The 'u' +# key will trigger its "user method", provided that it has been +# defined. Similarly the 'e' or 'q' key will trigger its "exit +# method". The lines below set these methods through the AddObserver +# method with the events "UserEvent" and "ExitEvent". The corresponding +# "user-method" Tcl code will bring up the .vtkInteract widget and +# allow the user to evaluate any Tcl code and get access to all +# previously-created VTK objects. The +# "exit-method" Tcl code will exit (do not try to free up any objects +# we created using 'vtkCommand DeleteAllObjects' because you are right +# inside a VTK object. +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren AddObserver ExitEvent {exit} + +# +# Render the image +# +renWin Render + +# +# Hide the default . widget +# +wm withdraw . + +# +# You only need this line if you run this script from a Tcl shell +# (tclsh) instead of a Tk shell (wish) +# +tkwait window . diff --git a/Examples/GUI/Tcl/MaceTk.tcl b/Examples/GUI/Tcl/MaceTk.tcl new file mode 100644 index 0000000..3366641 --- /dev/null +++ b/Examples/GUI/Tcl/MaceTk.tcl @@ -0,0 +1,251 @@ +# +# This example creates a polygonal model of a mace made of a sphere +# and a set of cones adjusted on its surface using glyphing. +# +# +# The sphere is rendered to the screen through the usual VTK render +# window but is included inside a standard Tk GUI comprising several +# other Tk widgets allowing the user to modify the VTK objects +# properties interactively. Interactions are performed through Tk +# events bindings instead of vtkRenderWindowInteractor. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# +# Next we create an instance of vtkSphereSource and set some of its +# properties +# +set sphere_max_res 60 +set sphere_init_res 8 +vtkSphereSource sphere + sphere SetThetaResolution $sphere_init_res + sphere SetPhiResolution $sphere_init_res + +# +# We create an instance of vtkPolyDataMapper to map the polygonal data +# into graphics primitives. We connect the output of the sphere source +# to the input of this mapper +# +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +# +# Create an actor to represent the sphere. The actor coordinates rendering of +# the graphics primitives for a mapper. We set this actor's mapper to be +# the mapper which we created above. +# +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +# +# Next we create an instance of vtkConeSource that will be used to +# set the glyphs on the sphere's surface +# +vtkConeSource cone + cone SetResolution 6 + +# +# Glyphing is a visualization technique that represents data by using +# symbol or glyphs. In VTK, the vtkGlyph3D class allows you to create +# glyphs that can be scaled, colored and oriented along a +# direction. The glyphs (here, cones) are copied at each point of the +# input dataset (the sphere's vertices). +# +# Create a vtkGlyph3D to dispatch the glyph/cone geometry (SetSource) on the +# sphere dataset (SetInput). Each glyph is oriented through the dataset +# normals (SetVectorModeToUseNormal). The resulting dataset is a set +# of cones lying on a sphere surface. +# +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 + +# +# We create an instance of vtkPolyDataMapper to map the polygonal data +# into graphics primitives. We connect the output of the glyph3d +# to the input of this mapper +# +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] + +# +# Create an actor to represent the glyphs. The actor coordinates rendering of +# the graphics primitives for a mapper. We set this actor's mapper to be +# the mapper which we created above. +# +vtkLODActor spikeActor + spikeActor SetMapper spikeMapper + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +vtkRenderer renderer + renderer AddActor sphereActor + renderer AddActor spikeActor + renderer SetBackground 1 1 1 + +# +# We create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. +# Do not set the size of the window here. +# +vtkRenderWindow renWin + renWin AddRenderer renderer + +# +# vtkTkRenderWidget is a Tk widget that we can render into. It has a +# GetRenderWindow method that returns a vtkRenderWindow. This can then +# be used to create a vtkRenderer and etc. We can also specify a +# vtkRenderWindow to be used when creating the widget by using the -rw +# option, which is what we do here by using renWin. It also takes +# -width and -height options that can be used to specify the widget +# size, hence the render window size: we set the size to be 300 +# pixels by 300. +# +set vtkw [vtkTkRenderWidget .ren \ + -width 300 \ + -height 300 \ + -rw renWin] + +# +# Setup Tk bindings and VTK observers for that widget. +# +::vtk::bind_tk_render_widget $vtkw + +# +# Once the VTK widget has been created it can be inserted into a whole Tk GUI +# as well as any other standard Tk widgets. The code below will create several +# "scale" (sliders) widgets enabling us to control the mace parameters +# interactively. +# + +# +# We first create a .params Tk frame into which we will pack all sliders. +# +frame .params + +# +# Next we create a scale slider controlling the sphere Theta +# resolution. The value of this slider will range from 3 to 20 by +# increment 1 (-from, -to and -res options respectively). The +# orientation of this widget is horizontal (-orient option). We label +# it using the -label option. Finally, we bind the scale to Tcl code +# by assigning the -command option to the name of a Tcl +# procedure. Whenever the slider value changes this procedure will be +# called, enabling us to propagate this GUI setting to the +# corresponding VTK object. +# +set sth [scale .params.sth \ + -from 3 -to $sphere_max_res -res 1 \ + -orient horizontal \ + -label "Sphere Theta Resolution:" \ + -command setSphereThetaResolution] + +# +# The slider widget is initialized using the value obtained from the +# corresponding VTK object (i.e. the sphere theta resolution). +# +$sth set [sphere GetThetaResolution] + +# +# The procedure is called by the slider-widget handler whenever the +# slider value changes (either through user interaction or +# programmatically). It receives the slider value as parameter. We +# update the corresponding VTK object by calling the +# SetThetaResolution using this parameter and we render the scene to +# update the pipeline. +# +proc setSphereThetaResolution {res} { + sphere SetThetaResolution $res + renWin Render +} + +# +# In the exact same way we create a scale slider controlling the sphere Phi +# resolution. +# +set sph [scale .params.sph \ + -from 3 -to $sphere_max_res -res 1 \ + -orient horizontal \ + -label "Sphere Phi Resolution:" \ + -command setSpherePhiResolution] + +$sph set [sphere GetPhiResolution] + +proc setSpherePhiResolution {res} { + sphere SetPhiResolution $res + renWin Render +} + +# +# In the exact same way we create a scale slider controlling the cone +# resolution. +# +set cone_max_res $sphere_max_res +set cre [scale .params.cre \ + -from 3 -to $cone_max_res -res 1 \ + -orient horizontal \ + -label "Cone Source Resolution:" \ + -command setConeSourceResolution] + +$cre set [cone GetResolution] + +proc setConeSourceResolution {res} { + cone SetResolution $res + renWin Render +} + +# +# In the exact same way we create a scale slider controlling the glyph +# scale factor. +# +set gsc [scale .params.gsc \ + -from 0.1 -to 1.5 -res 0.05 \ + -orient horizontal\ + -label "Glyph Scale Factor:" \ + -command setGlyphScaleFactor] +$gsc set [glyph GetScaleFactor] + +proc setGlyphScaleFactor {factor} { + glyph SetScaleFactor $factor + renWin Render +} + +# +# Let's add a quit button that will trigger the exit callback (see below) +# +button .params.quit -text "Quit" -command ::vtk::cb_exit + +# +# Finally we pack all sliders on top of each other (-side top) inside +# the frame and we pack the VTK widget $vtkw and the frame .params +# inside the main root widget. +# +pack $sth $sph $cre $gsc .params.quit -side top -anchor nw -fill both +pack $vtkw .params -side top -fill both -expand yes + +# +# We set the window manager (wm command) so that it registers a +# command to handle the WM_DELETE_WINDOW protocal request. This +# request is triggered when the widget is closed using the standard +# window manager icons or buttons. In this case the exit callback +# will be called and it will free up any objects we created then exit +# the application. +# +wm protocol . WM_DELETE_WINDOW ::vtk::cb_exit + +# +# You only need this line if you run this script from a Tcl shell +# (tclsh) instead of a Tk shell (wish) +# +tkwait window . diff --git a/Examples/GUI/Tcl/OrthogonalPlanesWithTkPhoto.tcl b/Examples/GUI/Tcl/OrthogonalPlanesWithTkPhoto.tcl new file mode 100644 index 0000000..4fe6aaf --- /dev/null +++ b/Examples/GUI/Tcl/OrthogonalPlanesWithTkPhoto.tcl @@ -0,0 +1,120 @@ + +#//////////////////////////////////////////////// +package require vtk +package require vtkinteraction + +# Image pipeline + +vtkVolume16Reader reader + reader SetDataDimensions 64 64 + reader SetDataByteOrderToLittleEndian + reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + reader SetImageRange 1 93 + reader SetDataSpacing 3.2 3.2 1.5 + reader Update + +vtkImageCast cast +cast SetInputConnection [reader GetOutputPort] +cast SetOutputScalarType [[reader GetOutput] GetScalarType] +cast ClampOverflowOn + +# Make the image a little bigger +vtkImageResample resample +resample SetInputConnection [cast GetOutputPort] +resample SetAxisMagnificationFactor 0 2 +resample SetAxisMagnificationFactor 1 2 +resample SetAxisMagnificationFactor 2 1 + +set range [[reader GetOutput] GetScalarRange] +set l [lindex $range 0] +set h [lindex $range 1] + +wm withdraw . +toplevel .c +wm title .c "Tcl Version of vtkImageDataToTkPhoto" +wm protocol .c WM_DELETE_WINDOW ::vtk::cb_exit + +# Create the three orthogonal views +set mode 0 +set m [menu .c.mm -tearoff 0] +$m add radiobutton -label "unsigned char" -value -1 -variable mode -command CastToUnsignedChar +$m add radiobutton -label "unsigned short" -value 0 -variable mode -command CastToUnsignedShort +$m add radiobutton -label "unsigned int" -value 1 -variable mode -command CastToUnsignedInt +$m add radiobutton -label "float" -value 2 -variable mode -command CastToFloat + +set tphoto [image create photo] +set cphoto [image create photo] +set sphoto [image create photo] +grid [label .c.t -image $tphoto] -row 0 -column 0 +bind .c.t "SetPosition transverse %W %x %y" +bind .c.t "$m post %X %Y" +grid [label .c.c -image $cphoto] -row 1 -column 0 +bind .c.c "SetPosition coronal %W %x %y" +bind .c.c "$m post %X %Y" +grid [label .c.s -image $sphoto] -row 0 -column 1 +bind .c.s "SetPosition sagittal %W %x %y" +bind .c.s "$m post %X %Y" + +grid [scale .c.w -label Window -orient horizontal -from 1 -to [expr ($h - $l) / 2] -command SetWindow ] -row 2 -columnspan 2 -sticky ew +grid [scale .c.l -label Level -orient horizontal -from $l -to $h -command SetWindow ] -row 3 -columnspan 2 -sticky ew +grid [label .c.text -textvariable Label -bd 2 -relief raised] -row 4 -columnspan 2 -sticky ew +set Label "Use the right mouse button to change data type" +.c.w set 1370 +.c.l set 1268 +reader Update + +set d [[reader GetOutput] GetDimensions] +set Position(x) [expr int ( [lindex $d 0] / 2.0 ) ] +set Position(y) [expr int ( [lindex $d 1] / 2.0 ) ] +set Position(z) [expr int ( [lindex $d 2] / 2.0 ) ] +# Scale = 255 / window +# Shift = Window / 2 - level + +proc SetPosition { orientation widget x y } { + global Label Position + set i [$widget cget -image] + set w [image width $i] + set h [image height $i] + switch $orientation { + transverse { set Position(x) $x; set Position(y) [expr $h - $y - 1] } + coronal { set Position(x) $x; set Position(z) $y } + sagittal { set Position(y) [expr $w - $x - 1]; set Position(z) $y } + } + set Label "$orientation Position: $Position(x), $Position(y), $Position(z)" + SetImages +} + +proc SetWindow { foo } { + SetImages +} + +proc SetImages {} { + global Position tphoto sphoto cphoto + set Window [.c.w get] + set Level [.c.l get] + vtkImageDataToTkPhoto [resample GetOutput] $tphoto $Position(z) transverse $Window $Level + vtkImageDataToTkPhoto [resample GetOutput] $sphoto $Position(x) sagittal $Window $Level + vtkImageDataToTkPhoto [resample GetOutput] $cphoto $Position(y) coronal $Window $Level +} + +proc CastToUnsignedChar {} { + cast SetOutputScalarTypeToUnsignedChar + SetImages +} +proc CastToUnsignedShort {} { + cast SetOutputScalarTypeToUnsignedShort + SetImages +} +proc CastToUnsignedInt {} { + cast SetOutputScalarTypeToUnsignedInt + SetImages +} +proc CastToFloat {} { + cast SetOutputScalarTypeToFloat + SetImages +} + +# Prime the pump +SetImages +#/////////////////////////////////////////////////// + diff --git a/Examples/GUI/Tcl/ProbeWithPointWidget.tcl b/Examples/GUI/Tcl/ProbeWithPointWidget.tcl new file mode 100644 index 0000000..1587397 --- /dev/null +++ b/Examples/GUI/Tcl/ProbeWithPointWidget.tcl @@ -0,0 +1,102 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# This example demonstrates how to use the vtkPlaneWidget to probe +# a dataset and then generate contours on the probed data. + +# Start by loading some data. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# The plane widget is used probe the dataset. +# +vtkPointWidget pointWidget + pointWidget SetInput [pl3d GetOutput] + pointWidget AllOff + pointWidget PlaceWidget +vtkPolyData point + pointWidget GetPolyData point + +vtkProbeFilter probe + probe SetInput point + probe SetSource [pl3d GetOutput] + +# create glyph +vtkConeSource cone + cone SetResolution 16 +vtkGlyph3D glyph + glyph SetInputConnection [probe GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseVector + glyph SetScaleModeToDataScalingOff + glyph SetScaleFactor [expr [[pl3d GetOutput] GetLength] * 0.1] +vtkPolyDataMapper glyphMapper + glyphMapper SetInputConnection [glyph GetOutputPort] +vtkActor glyphActor + glyphActor SetMapper glyphMapper + glyphActor VisibilityOff + +# An outline is shown for context. +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Associate the line widget with the interactor + +pointWidget SetInteractor iren +pointWidget AddObserver EnableEvent BeginInteraction +pointWidget AddObserver StartInteractionEvent BeginInteraction +pointWidget AddObserver InteractionEvent ProbeData + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor glyphActor + +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# Prevent the tk window from showing up then start the event loop. +wm withdraw . + +# Actually generate contour lines. +proc BeginInteraction {} { + pointWidget GetPolyData point + glyphActor VisibilityOn +} + +proc ProbeData {} { + pointWidget GetPolyData point +} + + + diff --git a/Examples/GUI/Tcl/ProbeWithSplineWidget.tcl b/Examples/GUI/Tcl/ProbeWithSplineWidget.tcl new file mode 100644 index 0000000..425a63c --- /dev/null +++ b/Examples/GUI/Tcl/ProbeWithSplineWidget.tcl @@ -0,0 +1,515 @@ +package require vtk +package require vtkinteraction + +# This example demonstrates how to use the vtkImagePlaneWidget +# and a vtkSplineWidger to do profile probing of a 3D image +# dataset. The use of vtkAnnotatedCubeActor, vtkAxesActor and +# vtkOrientationMarkerWidget is also demostrated. +# +# GUI controls are provided as follows: +# a) x,y,z buttons set the widgets to orthonormal +# positioning, set the horizontal slider to move the +# widgets along their common plane normal, and set the +# camera to face the widgets +# b) right clicking on x,y,z buttons pops up a menu to set +# the widget's reslice interpolation mode +# c) when in axes aligned, orthogonal orientation, the slider +# will move the widget by slice index within the appropriate range +# + +# Start by loading some data. +# +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 Update + +scan [[v16 GetOutput] GetWholeExtent] "%d %d %d %d %d %d" \ + xMin xMax yMin yMax zMin zMax + +set spacing [[v16 GetOutput] GetSpacing] +set sx [lindex $spacing 0] +set sy [lindex $spacing 1] +set sz [lindex $spacing 2] + +set origin [[v16 GetOutput] GetOrigin] +set ox [lindex $origin 0] +set oy [lindex $origin 1] +set oz [lindex $origin 2] + +# Create an outline of the 3D image data bounds. +# +vtkOutlineFilter outline + outline SetInput [ v16 GetOutput ] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInput [ outline GetOutput ] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Set up two renderers in one render window: one for the +# vtkImagePlaneWidget, vtkSplineWidget, and outline, and +# one for the profile plot. +# +vtkRenderer ren1 + ren1 SetBackground 0.4 0.4 0.5 +vtkRenderer ren2 + ren2 SetBackground 0.8 0.8 0.8 + +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin SetSize 800 400 + +ren1 SetViewport 0 0 0.5 1 +ren2 SetViewport 0.5 0 1 1 + +# Create a vtkImagePlaneWidget to slice through the data. +# +vtkImagePlaneWidget ipw + ipw DisplayTextOn + ipw TextureInterpolateOff + ipw UserControlledLookupTableOff + ipw SetInput [ v16 GetOutput ] + ipw SetResliceInterpolateToNearestNeighbour + ipw KeyPressActivationOff + [ ipw GetPlaneProperty ] SetColor 1 0 0 + set xmode [ ipw GetResliceInterpolate ] + set ymode [ ipw GetResliceInterpolate ] + set zmode [ ipw GetResliceInterpolate ] + ipw SetPlaneOrientationToXAxes + ipw SetSliceIndex 32 + ipw AddObserver InteractionEvent UpdateIPW + +# Create a vtkSplineWidget to interactively probe the data. +# +vtkSplineWidget spline + spline SetInput [ v16 GetOutput ] + spline PlaceWidget + spline SetPriority 1.0 + spline KeyPressActivationOff + spline ProjectToPlaneOn + spline SetProjectionNormal 0 + spline SetProjectionPosition 102.4 + spline SetNumberOfHandles 5 + spline SetResolution 500 + spline AddObserver InteractionEvent UpdateSW + +# A vtkPolyData will be continuously updated from the spline +# during interaction. +# +vtkPolyData poly + spline GetPolyData poly + +# The filter to probe the image data. +# +vtkProbeFilter probe + probe SetInput poly + probe SetSource [ v16 GetOutput ] + +# The plot of the profile data. +# +vtkXYPlotActor profile + profile AddInput [ probe GetOutput ] + [ profile GetPositionCoordinate ] SetValue 0.05 0.05 0 + [ profile GetPosition2Coordinate ] SetValue 0.95 0.95 0 + profile SetXValuesToNormalizedArcLength + profile SetNumberOfXLabels 6 + profile SetTitle "Profile Data " + profile SetXTitle "s" + profile SetYTitle "I(s)" + profile SetXRange 0 1 + set range [[v16 GetOutput] GetScalarRange] + profile SetYRange [lindex $range 0] [lindex $range 1] + [ profile GetProperty ] SetColor 0 0 0 + [ profile GetProperty ] SetLineWidth 2 + profile SetLabelFormat "%g" + [ profile GetTitleTextProperty ] SetColor 0.02 0.06 0.62 + [ profile GetTitleTextProperty ] SetFontFamilyToArial + profile SetAxisTitleTextProperty [ profile GetTitleTextProperty ] + profile SetAxisLabelTextProperty [ profile GetTitleTextProperty ] + profile SetTitleTextProperty [ profile GetTitleTextProperty ] + +# Create a composite orientation marker using +# vtkAnnotatedCubeActor and vtkAxesActor. +# +vtkAnnotatedCubeActor cube + cube SetXPlusFaceText "R" + cube SetXMinusFaceText "L" + cube SetYPlusFaceText "A" + cube SetYMinusFaceText "P" + cube SetZPlusFaceText "I" + cube SetZMinusFaceText "S" + cube SetXFaceTextRotation 180 + cube SetYFaceTextRotation 180 + cube SetZFaceTextRotation -90 + cube SetFaceTextScale 0.65 + set property [ cube GetCubeProperty ] + $property SetColor 0.5 1 1 + set property [ cube GetTextEdgesProperty ] + $property SetLineWidth 1 + $property SetDiffuse 0 + $property SetAmbient 1 + $property SetColor 0.18 0.28 0.23 + cube TextEdgesOn + cube CubeOn + cube FaceTextOn + set property [ cube GetXPlusFaceProperty ] + $property SetColor 0 0 1 + $property SetInterpolationToFlat + set property [ cube GetXMinusFaceProperty ] + $property SetColor 0 0 1 + $property SetInterpolationToFlat + set property [ cube GetYPlusFaceProperty ] + $property SetColor 0 1 0 + $property SetInterpolationToFlat + set property [ cube GetYMinusFaceProperty ] + $property SetColor 0 1 0 + $property SetInterpolationToFlat + set property [ cube GetZPlusFaceProperty ] + $property SetColor 1 0 0 + $property SetInterpolationToFlat + set property [ cube GetZMinusFaceProperty ] + $property SetColor 1 0 0 + $property SetInterpolationToFlat + +vtkAxesActor axes + axes SetShaftTypeToCylinder + axes SetXAxisLabelText "x" + axes SetYAxisLabelText "y" + axes SetZAxisLabelText "z" + axes SetTotalLength 1.5 1.5 1.5 + vtkTextProperty tprop + tprop ItalicOn + tprop ShadowOn + tprop SetFontFamilyToTimes + [ axes GetXAxisCaptionActor2D ] SetCaptionTextProperty tprop + vtkTextProperty tprop2 + tprop2 ShallowCopy tprop + [ axes GetYAxisCaptionActor2D ] SetCaptionTextProperty tprop2 + vtkTextProperty tprop3 + tprop3 ShallowCopy tprop + [ axes GetZAxisCaptionActor2D ] SetCaptionTextProperty tprop3 + +# Combine the two actors into one with vtkPropAssembly ... +# + vtkPropAssembly assembly + assembly AddPart axes + assembly AddPart cube + +# Add the composite marker to the widget. The widget +# should be kept in non-interactive mode and the aspect +# ratio of the render window taken into account explicitly, +# since the widget currently does not take this into +# account in a multi-renderer environment. +# + vtkOrientationMarkerWidget marker + marker SetOutlineColor 0.93 0.57 0.13 + marker SetOrientationMarker assembly + marker SetViewport 0.0 0.0 0.15 0.3 + +# Add the actors. +# + ren1 AddActor outlineActor + ren2 AddActor2D profile + +# Prevent the tk window from showing up then start the event loop. + wm withdraw . + +# Build a tcl GUI. +# + +toplevel .top +wm title .top "Probe With vtkSplineWidget Example" +wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit + +set popm [menu .top.mm -tearoff 0] +set interpmode 0 +$popm add radiobutton -label "nearest" -variable interpmode -value 0 \ + -command SetInterpolation +$popm add radiobutton -label "linear" -variable interpmode -value 1 \ + -command SetInterpolation +$popm add radiobutton -label "cubic" -variable interpmode -value 2 \ + -command SetInterpolation + +set display_frame [frame .top.f1] + +set ctrl_buttons [frame .top.btns] + +pack $display_frame $ctrl_buttons \ + -side top -anchor n \ + -fill both -expand f + +set quit_button [button $ctrl_buttons.btn1 \ + -text "Quit" \ + -command ::vtk::cb_exit] + +set x_button [button $ctrl_buttons.btn2 \ + -text "x" \ + -command AlignXaxis] + +set y_button [button $ctrl_buttons.btn3 \ + -text "y" \ + -command AlignYaxis] + +set z_button [button $ctrl_buttons.btn4 \ + -text "z" \ + -command AlignZaxis] + +set last_btn -1 +bind $x_button "set last_btn 0; ConfigMenu; $popm post %X %Y" +bind $y_button "set last_btn 1; ConfigMenu; $popm post %X %Y" +bind $z_button "set last_btn 2; ConfigMenu; $popm post %X %Y" + +# Share the popup menu among buttons, keeping +# track of associated plane's interpolation mode +# +proc ConfigMenu { } { + global last_btn popm interpmode xmode ymode zmode + if { $last_btn == 0 } { + set interpmode $xmode + } elseif { $last_btn == 1 } { + set interpmode $ymode + } else { + set interpmode $zmode + } + $popm entryconfigure $last_btn -variable interpmode +} + +pack $quit_button $x_button $y_button $z_button \ + -side left \ + -expand t -fill both + +# Create the render widget +# +set renderer_frame [frame $display_frame.rFm] + +pack $renderer_frame \ + -padx 3 -pady 3 \ + -side left -anchor n \ + -fill both -expand f + +set render_widget [vtkTkRenderWidget $renderer_frame.r \ + -width 800 \ + -height 400 \ + -rw renWin] + +pack $render_widget $display_frame \ + -side top -anchor n \ + -fill both -expand f + +# Add a slice scale to browse the current slice stack +# + +set slice_number [ipw GetSliceIndex] + +scale .top.slice \ + -from $xMin \ + -to $xMax \ + -orient horizontal \ + -command SetSlice \ + -variable slice_number \ + -label "Slice" + +pack .top.slice \ + -fill x -expand f + +proc SetSlice {slice} { + ipw SetSliceIndex $slice + UpdateIPW + renWin Render +} + +::vtk::bind_tk_render_widget $render_widget +# Set the interactor for the widgets +# +set iact [[$render_widget GetRenderWindow] GetInteractor] +vtkInteractorStyleTrackballCamera style +$iact SetInteractorStyle style + +ipw SetInteractor $iact +ipw On + +spline SetInteractor $iact +spline SetPlaneSource [ ipw GetPolyDataAlgorithm ] +spline SetProjectionNormal 3 +spline On + +marker SetInteractor $iact +marker SetEnabled 1 +marker InteractiveOff + +# Create an initial interesting view +# +set cam1 [ren1 GetActiveCamera] +$cam1 Elevation 110 +$cam1 SetViewUp 0 0 -1 +$cam1 Azimuth 45 +ren1 ResetCamera + +# Render it +# +$render_widget Render + +# Supporting procedures +# + +# Align the camera so that it faces the desired widget +# +proc AlignCamera { } { + global ox oy oz sx sy sz xMax xMin yMax yMin zMax zMin slice_number + set cx [expr $ox + (0.5*($xMax - $xMin))*$sx] + set cy [expr $oy + (0.5*($yMax - $yMin))*$sy] + set cz [expr $oy + (0.5*($zMax - $zMin))*$sz] + set vx 0 + set vy 0 + set vz 0 + set nx 0 + set ny 0 + set nz 0 + set iaxis [ipw GetPlaneOrientation] + if { $iaxis == 0 } { + set vz -1 + set nx [expr $ox + $xMax*$sx] + set cx [expr $ox + $slice_number*$sx] + } elseif { $iaxis == 1 } { + set vz -1 + set ny [expr $oy + $yMax*$sy] + set cy [expr $oy + $slice_number*$sy] + } else { + set vy 1 + set nz [expr $oz + $zMax*$sz] + set cz [expr $oz + $slice_number*$sz] + } + set px [expr $cx + $nx*2] + set py [expr $cy + $ny*2] + set pz [expr $cz + $nz*3] + + set camera [ ren1 GetActiveCamera ] + $camera SetViewUp $vx $vy $vz + $camera SetFocalPoint $cx $cy $cz + $camera SetPosition $px $py $pz + $camera OrthogonalizeViewUp + ren1 ResetCamera + renWin Render +} + +# Align the widget back into orthonormal position, +# set the slider to reflect the widget's position, +# call AlignCamera to set the camera facing the widget +# +proc AlignXaxis { } { + global xMax xMin slice_number interpmode xmode + set ori [ ipw GetPlaneOrientation ] + if { $ori != 0 } { + ipw SetPlaneOrientationToXAxes + set slice_number [expr ($xMax - $xMin)/2] + ipw SetSliceIndex $slice_number + } else { + set slice_number [ipw GetSliceIndex] + } + .top.slice config -from $xMin -to $xMax + .top.slice set $slice_number + UpdateSplinePosition + AlignCamera + set interpmode $xmode + SetInterpolation +} + +proc AlignYaxis { } { + global yMin yMax slice_number interpmode ymode + + set po [ ipw GetPlaneOrientation ] + set ori [ ipw GetPlaneOrientation ] + if { $ori != 1 } { + ipw SetPlaneOrientationToYAxes + set slice_number [expr ($yMax - $yMin)/2] + ipw SetSliceIndex $slice_number + } else { + set slice_number [ipw GetSliceIndex] + } + .top.slice config -from $yMin -to $yMax + .top.slice set $slice_number + UpdateSplinePosition + AlignCamera + set interpmode $ymode + SetInterpolation +} + +proc AlignZaxis { } { + global zMin zMax slice_number interpmode zmode + set ori [ ipw GetPlaneOrientation ] + if { $ori != 2 } { + ipw SetPlaneOrientationToZAxes + set slice_number [expr ($zMax - $zMin)/2] + ipw SetSliceIndex $slice_number + } else { + set slice_number [ipw GetSliceIndex] + } + .top.slice config -from $zMin -to $zMax + .top.slice set $slice_number + UpdateSplinePosition + AlignCamera + set interpmode $zmode + SetInterpolation +} + +proc UpdateSplinePosition { } { + set ori [ ipw GetPlaneOrientation ] + spline ProjectToPlaneOff + spline PlaceWidget + spline ProjectToPlaneOn + spline SetProjectionNormal $ori + spline SetProjectionNormal 3 + UpdateIPW +} + +# Set the vtkImagePlaneWidget's reslice interpolation mode +# to the corresponding popup menu choice and store +# it for subsequent orientation changes. +# +proc SetInterpolation { } { + global interpmode xmode ymode zmode + if { $interpmode == 0 } { + ipw TextureInterpolateOff + } else { + ipw TextureInterpolateOn + } + ipw SetResliceInterpolate $interpmode + set ori [ipw GetPlaneOrientation] + if { $ori == 0 } { + set xmode $interpmode + } elseif { $ori == 1 } { + set ymode $interpmode + } else { + set zmode $interpmode + } + renWin Render +} + +# Procedure to update the placement of the vtkSplineWidget on the +# plane defined by the vtkImagePlaneWidget. +# +proc UpdateIPW { } { + set ori [ ipw GetPlaneOrientation ] + + if { $ori == 3 } { + spline SetProjectionPosition 0 + } else { + set pos [ ipw GetSlicePosition ] + spline SetProjectionPosition $pos + } + + UpdateSW +} + +# Procedure to update the spline geometry fed into the probe filter. +# +proc UpdateSW { } { + spline GetPolyData poly +} + diff --git a/Examples/GUI/Tcl/ProbingWithPlaneWidget.tcl b/Examples/GUI/Tcl/ProbingWithPlaneWidget.tcl new file mode 100644 index 0000000..dc34c6c --- /dev/null +++ b/Examples/GUI/Tcl/ProbingWithPlaneWidget.tcl @@ -0,0 +1,94 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# This example demonstrates how to use the vtkPlaneWidget to probe +# a dataset and then generate contours on the probed data. + +# Start by loading some data. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# The plane widget is used probe the dataset. +# +vtkPlaneWidget planeWidget + planeWidget SetInput [pl3d GetOutput] + planeWidget NormalToXAxisOn + planeWidget SetResolution 20 + planeWidget SetRepresentationToOutline + planeWidget PlaceWidget +vtkPolyData plane + planeWidget GetPolyData plane + +vtkProbeFilter probe + probe SetInput plane + probe SetSource [pl3d GetOutput] + +vtkPolyDataMapper contourMapper + contourMapper SetInputConnection [probe GetOutputPort] + eval contourMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor contourActor + contourActor SetMapper contourMapper + contourActor VisibilityOff + +# An outline is shown for context. +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Associate the line widget with the interactor + +planeWidget SetInteractor iren +planeWidget AddObserver EnableEvent BeginInteraction +planeWidget AddObserver StartInteractionEvent BeginInteraction +planeWidget AddObserver InteractionEvent ProbeData + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor contourActor + +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# Prevent the tk window from showing up then start the event loop. +wm withdraw . + +# Actually generate contour lines. +proc BeginInteraction {} { + planeWidget GetPolyData plane + contourActor VisibilityOn +} + +proc ProbeData {} { + planeWidget GetPolyData plane +} + diff --git a/Examples/GUI/Tcl/ProgressEvent.tcl b/Examples/GUI/Tcl/ProgressEvent.tcl new file mode 100644 index 0000000..064effb --- /dev/null +++ b/Examples/GUI/Tcl/ProgressEvent.tcl @@ -0,0 +1,28 @@ +# Halves the size of the image in the x, y and z dimensions. +package require vtk + +# Image pipeline +vtkImageReader reader + reader SetDataByteOrderToLittleEndian + reader SetDataExtent 0 255 0 255 1 93 + reader SetFilePrefix $VTK_DATA_ROOT/Data/headsq/quarter + reader SetDataMask 0x7fff + +vtkImageShrink3D shrink + shrink SetInputConnection [reader GetOutputPort] + shrink SetShrinkFactors 2 2 2 + shrink AddObserver ProgressEvent { + .text configure -text "Completed [expr [shrink GetProgress]*100.0] percent" + update + } + shrink AddObserver EndEvent { + .text configure -text "Completed Processing" + update + } + +button .run -text "Execute" -command { + shrink Modified + shrink Update +} +label .text -text "Waiting to Process" +pack .run .text diff --git a/Examples/GUI/Tcl/SphereWidget.tcl b/Examples/GUI/Tcl/SphereWidget.tcl new file mode 100644 index 0000000..b4f301f --- /dev/null +++ b/Examples/GUI/Tcl/SphereWidget.tcl @@ -0,0 +1,115 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# This example demonstrates how to use the vtkSphereWidget to control the +# position of a light. + +# Start by loading some data. +# +vtkDEMReader dem + dem SetFileName "$VTK_DATA_ROOT/Data/SainteHelens.dem" + dem Update + +set Scale 2 +vtkLookupTable lut + lut SetHueRange 0.6 0 + lut SetSaturationRange 1.0 0 + lut SetValueRange 0.5 1.0 +set lo [expr $Scale * [lindex [dem GetElevationBounds] 0]] +set hi [expr $Scale * [lindex [dem GetElevationBounds] 1]] + +vtkImageShrink3D shrink + shrink SetShrinkFactors 4 4 1 + shrink SetInputConnection [dem GetOutputPort] + shrink AveragingOn + +vtkImageDataGeometryFilter geom + geom SetInputConnection [shrink GetOutputPort] + geom ReleaseDataFlagOn + +vtkWarpScalar warp + warp SetInputConnection [geom GetOutputPort] + warp SetNormal 0 0 1 + warp UseNormalOn + warp SetScaleFactor $Scale + warp ReleaseDataFlagOn + +vtkElevationFilter elevation + elevation SetInputConnection [warp GetOutputPort] + elevation SetLowPoint 0 0 $lo + elevation SetHighPoint 0 0 $hi + eval elevation SetScalarRange $lo $hi + elevation ReleaseDataFlagOn + +vtkPolyDataNormals normals + normals SetInput [elevation GetPolyDataOutput] + normals SetFeatureAngle 60 + normals ConsistencyOff + normals SplittingOff + normals ReleaseDataFlagOn + +vtkPolyDataMapper demMapper + demMapper SetInputConnection [normals GetOutputPort] + eval demMapper SetScalarRange $lo $hi + demMapper SetLookupTable lut + demMapper ImmediateModeRenderingOn + +vtkLODActor demActor + demActor SetMapper demMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren LightFollowCameraOff + iren SetInteractorStyle "" + +# Associate the line widget with the interactor +vtkSphereWidget sphereWidget +sphereWidget SetInteractor iren +sphereWidget SetProp3D demActor +sphereWidget SetPlaceFactor 4 +sphereWidget PlaceWidget +sphereWidget TranslationOff +sphereWidget ScaleOff +sphereWidget HandleVisibilityOn +sphereWidget AddObserver InteractionEvent MoveLight + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor demActor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetViewUp 0 0 1 +eval $cam1 SetFocalPoint [[dem GetOutput] GetCenter] +$cam1 SetPosition 1 0 0 +ren1 ResetCamera +$cam1 Elevation 25 +$cam1 Azimuth 125 +$cam1 Zoom 1.25 + +vtkLight light +eval light SetFocalPoint [[dem GetOutput] GetCenter] +ren1 AddLight light + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# Prevent the tk window from showing up then start the event loop. +wm withdraw . + +# Actually probe the data + +proc MoveLight {} { + eval light SetPosition [sphereWidget GetHandlePosition] +} + diff --git a/Examples/GUI/Tcl/StreamlinesWithLineWidget.tcl b/Examples/GUI/Tcl/StreamlinesWithLineWidget.tcl new file mode 100644 index 0000000..8fc723d --- /dev/null +++ b/Examples/GUI/Tcl/StreamlinesWithLineWidget.tcl @@ -0,0 +1,145 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# This example demonstrates how to use the vtkLineWidget to seed +# and manipulate streamlines. Two line widgets are created. One is +# invoked by pressing 'W', the other by pressing 'L'. Both can exist +# together. + +# Start by loading some data. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# The line widget is used seed the streamlines. +# +vtkLineWidget lineWidget +vtkPolyData seeds +lineWidget SetInput [pl3d GetOutput] +lineWidget SetAlignToYAxis +lineWidget PlaceWidget +lineWidget GetPolyData seeds +lineWidget ClampToBoundsOn + +vtkRungeKutta4 rk4 +vtkStreamLine streamer + streamer SetInputConnection [pl3d GetOutputPort] + streamer SetSource seeds + streamer SetMaximumPropagationTime 100 + streamer SetIntegrationStepLength .2 + streamer SetStepLength .001 + streamer SetNumberOfThreads 1 + streamer SetIntegrationDirectionToForward + streamer VorticityOn + streamer SetIntegrator rk4 +vtkRibbonFilter rf + rf SetInputConnection [streamer GetOutputPort] + rf SetWidth 0.1 + rf SetWidthFactor 5 +vtkPolyDataMapper streamMapper + streamMapper SetInputConnection [rf GetOutputPort] + eval streamMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor streamline + streamline SetMapper streamMapper + streamline VisibilityOff + +# The second line widget is used seed more streamlines. +# +vtkLineWidget lineWidget2 +vtkPolyData seeds2 +lineWidget2 SetInput [pl3d GetOutput] +lineWidget2 PlaceWidget +lineWidget2 GetPolyData seeds2 +lineWidget2 SetKeyPressActivationValue L + +vtkStreamLine streamer2 + streamer2 SetInputConnection [pl3d GetOutputPort] + streamer2 SetSource seeds2 + streamer2 SetMaximumPropagationTime 100 + streamer2 SetIntegrationStepLength .2 + streamer2 SetStepLength .001 + streamer2 SetNumberOfThreads 1 + streamer2 SetIntegrationDirectionToForward + streamer2 VorticityOn + streamer2 SetIntegrator rk4 +vtkRibbonFilter rf2 + rf2 SetInputConnection [streamer2 GetOutputPort] + rf2 SetWidth 0.1 + rf2 SetWidthFactor 5 +vtkPolyDataMapper streamMapper2 + streamMapper2 SetInputConnection [rf2 GetOutputPort] + eval streamMapper2 SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor streamline2 + streamline2 SetMapper streamMapper2 + streamline2 VisibilityOff + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Associate the line widget with the interactor +lineWidget SetInteractor iren +lineWidget AddObserver StartInteractionEvent BeginInteraction +lineWidget AddObserver InteractionEvent GenerateStreamlines + +lineWidget2 SetInteractor iren +lineWidget2 AddObserver StartInteractionEvent BeginInteraction2 +lineWidget2 AddObserver EndInteractionEvent GenerateStreamlines2 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor streamline +ren1 AddActor streamline2 + +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# Prevent the tk window from showing up then start the event loop. +wm withdraw . + +# Actually generate streamlines. +proc BeginInteraction {} { + streamline VisibilityOn +} + +proc GenerateStreamlines {} { + lineWidget GetPolyData seeds +} + +proc BeginInteraction2 {} { + streamline2 VisibilityOn +} + +proc GenerateStreamlines2 {} { + lineWidget2 GetPolyData seeds2 +} + diff --git a/Examples/GUI/Tcl/TransformWithBoxWidget.tcl b/Examples/GUI/Tcl/TransformWithBoxWidget.tcl new file mode 100644 index 0000000..f96cbe9 --- /dev/null +++ b/Examples/GUI/Tcl/TransformWithBoxWidget.tcl @@ -0,0 +1,68 @@ +package require vtk +package require vtkinteraction + +# Demonstrate how to use the vtkBoxWidget to translate, scale, and rotate actors. +# The basic idea is that the box widget controls an actor's transform. A callback +# which modifies the transform is invoked as the box widget is manipulated. + +# Start by creating some simple geometry; in this case a mace. +vtkSphereSource sphere +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 +vtkAppendPolyData appendData + appendData AddInput [glyph GetOutput] + appendData AddInput [sphere GetOutput] +vtkPolyDataMapper maceMapper + maceMapper SetInputConnection [appendData GetOutputPort] +vtkLODActor maceActor + maceActor SetMapper maceMapper + maceActor VisibilityOn + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# The box widget observes the events invoked by the render window interactor. +# These events come from user interaction in the render window. +vtkBoxWidget boxWidget + boxWidget SetInteractor iren + boxWidget SetPlaceFactor 1.25 + +# Add the actors to the renderer, set the background and window size. +# +ren1 AddActor maceActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# Place the interactor initially. The actor is used to place and scale +# the interactor. An observer is added to the box widget to watch for +# interaction events. This event is captured and used to set the +# transformation matrix of the actor. +boxWidget SetProp3D maceActor +boxWidget PlaceWidget +boxWidget AddObserver InteractionEvent TransformActor + +# Support the "u" keypress user event (pops up a Tcl interpreter). +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# As the box widget is interacted with, it produces a transformation +# matrix that is set on the actor. +vtkTransform t +proc TransformActor {} { + boxWidget GetTransform t + maceActor SetUserTransform t +} diff --git a/Examples/GUI/Tcl/VolumeRenderWithBoxWidget.tcl b/Examples/GUI/Tcl/VolumeRenderWithBoxWidget.tcl new file mode 100644 index 0000000..905a744 --- /dev/null +++ b/Examples/GUI/Tcl/VolumeRenderWithBoxWidget.tcl @@ -0,0 +1,126 @@ +package require vtk +package require vtkinteraction + +# Demonstrate how to use the vtkBoxWidget to control volume rendering within +# the interior of the widget. + +# Load a volume, use the widget to control what's volume rendered. Basically +# the idea is that the vtkBoxWidget provides a box which clips the volume +# rendering. +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + +vtkPiecewiseFunction tfun + tfun AddPoint 70.0 0.0 + tfun AddPoint 599.0 0 + tfun AddPoint 600.0 0 + tfun AddPoint 1195.0 0 + tfun AddPoint 1200 .2 + tfun AddPoint 1300 .3 + tfun AddPoint 2000 .3 + tfun AddPoint 4095.0 1.0 + +vtkColorTransferFunction ctfun + ctfun AddRGBPoint 0.0 0.5 0.0 0.0 + ctfun AddRGBPoint 600.0 1.0 0.5 0.5 + ctfun AddRGBPoint 1280.0 0.9 0.2 0.3 + ctfun AddRGBPoint 1960.0 0.81 0.27 0.1 + ctfun AddRGBPoint 4095.0 0.5 0.5 0.5 + +vtkVolumeRayCastCompositeFunction compositeFunction + +vtkVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [v16 GetOutputPort] + volumeMapper SetVolumeRayCastFunction compositeFunction + +vtkVolumeProperty volumeProperty + volumeProperty SetColor ctfun + volumeProperty SetScalarOpacity tfun + volumeProperty SetInterpolationTypeToLinear + volumeProperty ShadeOn + +vtkVolume newvol + newvol SetMapper volumeMapper + newvol SetProperty volumeProperty + +vtkOutlineFilter outline + outline SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# The SetInteractor method is how 3D widgets are associated with the render +# window interactor. Internally, SetInteractor sets up a bunch of callbacks +# using the Command/Observer mechanism (AddObserver()). +vtkBoxWidget boxWidget + boxWidget SetInteractor iren + boxWidget SetPlaceFactor 1.0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddVolume newvol + +ren1 SetBackground 0 0 0 +renWin SetSize 300 300 + +# Place the interactor initially. The output of the reader is used to place +# the box widget. +boxWidget SetInput [v16 GetOutput] +boxWidget PlaceWidget +boxWidget InsideOutOn +boxWidget AddObserver StartInteractionEvent StartInteraction +boxWidget AddObserver InteractionEvent ClipVolumeRender +boxWidget AddObserver EndInteractionEvent EndInteraction +set outlineProperty [boxWidget GetOutlineProperty] + $outlineProperty SetRepresentationToWireframe + $outlineProperty SetAmbient 1.0 + $outlineProperty SetAmbientColor 1 1 1 + $outlineProperty SetLineWidth 3 +set selectedOutlineProperty [boxWidget GetSelectedOutlineProperty] + $selectedOutlineProperty SetRepresentationToWireframe + $selectedOutlineProperty SetAmbient 1.0 + $selectedOutlineProperty SetAmbientColor 1 0 0 + $selectedOutlineProperty SetLineWidth 3 + +# This adds the "u" keypress event...it pops up a Tcl interpreter. +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# Prevent the tk window from showing up then start the event loop. +wm withdraw . + +# When interaction starts, the requested frame rate is increased. +proc StartInteraction {} { + renWin SetDesiredUpdateRate 10 +} + +# When interaction ends, the requested frame rate is decreased to +# normal levels. This causes a full resolution render to occur. +proc EndInteraction {} { + renWin SetDesiredUpdateRate 0.001 +} + +# The implicit function vtkPlanes is used in conjunction with the +# volume ray cast mapper to limit which portion of the volume is +# volume rendered. +vtkPlanes planes +proc ClipVolumeRender {} { + boxWidget GetPlanes planes + volumeMapper SetClippingPlanes planes +} diff --git a/Examples/GUI/Tcl/spikeColor.tcl b/Examples/GUI/Tcl/spikeColor.tcl new file mode 100644 index 0000000..7567c83 --- /dev/null +++ b/Examples/GUI/Tcl/spikeColor.tcl @@ -0,0 +1,83 @@ +# load the necessary VTK libraries. +package require vtk +package require vtkinteraction +package require vtktesting + +# This example demonstrates how to use Tcl/Tk in a simple GUI to control +# the color of the spikes on the mace. The spikes are a separate actor so +# the actor's property via the SetColor() method is manipulated. + +# Create a sphere source and actor. This forms the head of the mace. +# +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +# Create the spikes using a cone source. The cones are glyphed onto the +# the mace head using the sphere normals. +# +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] +vtkLODActor spikeActor + spikeActor SetMapper spikeMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size. +# +ren1 AddActor sphereActor +ren1 AddActor spikeActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# An observer is added to allow the invocation of the interaction Tk GUI. +# When the 'u' key is pressed (which is translated into the UserEvent) +# then the corresponding Tcl proc is invoked. +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.4 +iren Initialize + +# Create Tk user interface. This is a simple frame with three sliders +# to control the R-G-B components. +# +frame .f +label .f.l -text "Spike Color" +scale .f.r -from 0 -to 100 -background #f00 \ + -orient horizontal -command SetColor +scale .f.g -from 0 -to 100 -background #0f0 \ + -orient horizontal -command SetColor +scale .f.b -from 0 -to 100 -background #00f \ + -orient horizontal -command SetColor + +set color [[spikeActor GetProperty] GetColor] +.f.r set [expr [lindex $color 0] * 100.0] +.f.g set [expr [lindex $color 1] * 100.0] +.f.b set [expr [lindex $color 2] * 100.0] + +pack .f.l .f.r .f.g .f.b -side top +pack .f + +proc SetColor {value} { + [spikeActor GetProperty] SetColor [expr [.f.r get]/100.0] \ + [expr [.f.g get]/100.0] \ [expr [.f.b get]/100.0] + renWin Render +} + diff --git a/Examples/GUI/Tcl/vtkTkRenderWidgetDemo.tcl b/Examples/GUI/Tcl/vtkTkRenderWidgetDemo.tcl new file mode 100644 index 0000000..0e44f4a --- /dev/null +++ b/Examples/GUI/Tcl/vtkTkRenderWidgetDemo.tcl @@ -0,0 +1,36 @@ +package require vtk +package require vtkinteraction + +# This script uses a vtkTkRenderWidget to create a +# Tk widget that is associated with a vtkRenderWindow + +# Create the GUI: a render widget and a quit button +wm withdraw . +toplevel .top +frame .top.f1 +vtkTkRenderWidget .top.f1.r1 -width 400 -height 400 +button .top.btn -text Quit -command exit +pack .top.f1.r1 -side left -padx 3 -pady 3 -fill both -expand t +pack .top.f1 -fill both -expand t +pack .top.btn -fill x + +# Get the render window associated with the widget +set renWin [.top.f1.r1 GetRenderWindow] +vtkRenderer ren1 +$renWin AddRenderer ren1 + +# bind the mouse events +::vtk::bind_tk_render_widget .top.f1.r1 + +# create a Cone source and actor +vtkConeSource cone +vtkPolyDataMapper coneMapper + coneMapper SetInputConnection [cone GetOutputPort] + coneMapper GlobalImmediateModeRenderingOn +vtkLODActor coneActor + coneActor SetMapper coneMapper + +# Add the actor to the renderer and set the background +ren1 AddViewProp coneActor +ren1 SetBackground 0.1 0.2 0.4 +[ren1 GetActiveCamera] Zoom 0.6 diff --git a/Examples/GUI/Win32/SampleMFC/CMakeLists.txt b/Examples/GUI/Win32/SampleMFC/CMakeLists.txt new file mode 100644 index 0000000..80f8f56 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/CMakeLists.txt @@ -0,0 +1,38 @@ +PROJECT (Win32SampleMFC) + +FIND_PACKAGE(VTK) +IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") +ENDIF(NOT VTK_DIR) +INCLUDE(${VTK_USE_FILE}) + +LINK_LIBRARIES( + vtkRendering + vtkGraphics + vtkImaging + vtkIO + vtkFiltering + vtkCommon +) + +SET(SRCS +ChildFrm.cpp +MainFrm.cpp +Sample.cpp +Sample.rc +SampleDoc.cpp +SampleView.cpp +StdAfx.cpp +vtkMFCDocument.cpp +vtkMFCRenderView.cpp +vtkMFCView.cpp +res/Sample.ico +res/Sample.rc2 +res/SampleDoc.ico +) + +# add stuff to use MFC in this executable +ADD_DEFINITIONS(-D_AFXDLL) +SET(CMAKE_MFC_FLAG 6) + +ADD_EXECUTABLE(Win32SampleMFC WIN32 ${SRCS}) diff --git a/Examples/GUI/Win32/SampleMFC/ChildFrm.cpp b/Examples/GUI/Win32/SampleMFC/ChildFrm.cpp new file mode 100644 index 0000000..b8923f9 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/ChildFrm.cpp @@ -0,0 +1,70 @@ +// ChildFrm.cpp : implementation of the CChildFrame class +// + +#include "stdafx.h" +#include "Sample.h" + +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame + +IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) + +BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) + //{{AFX_MSG_MAP(CChildFrame) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame construction/destruction + +CChildFrame::CChildFrame() +{ + // TODO: add member initialization code here + +} + +CChildFrame::~CChildFrame() +{ +} + +BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + if( !CMDIChildWnd::PreCreateWindow(cs) ) + return FALSE; + + return TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame diagnostics + +#ifdef _DEBUG +void CChildFrame::AssertValid() const +{ + CMDIChildWnd::AssertValid(); +} + +void CChildFrame::Dump(CDumpContext& dc) const +{ + CMDIChildWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CChildFrame message handlers diff --git a/Examples/GUI/Win32/SampleMFC/ChildFrm.h b/Examples/GUI/Win32/SampleMFC/ChildFrm.h new file mode 100644 index 0000000..9e54e06 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/ChildFrm.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ChildFrm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// ChildFrm.h : interface of the CChildFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CHILDFRM_H__B7F7B85F_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) +#define AFX_CHILDFRM_H__B7F7B85F_EEC9_11D2_87FE_0060082B79FD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +class CChildFrame : public CMDIChildWnd +{ + DECLARE_DYNCREATE(CChildFrame) +public: + CChildFrame(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChildFrame) + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CChildFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + //{{AFX_MSG(CChildFrame) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHILDFRM_H__B7F7B85F_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/MainFrm.cpp b/Examples/GUI/Win32/SampleMFC/MainFrm.cpp new file mode 100644 index 0000000..7667155 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/MainFrm.cpp @@ -0,0 +1,68 @@ +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "Sample.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here + +} + +CMainFrame::~CMainFrame() +{ +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CMDIFrameWnd::PreCreateWindow(cs) ) + return FALSE; + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CMDIFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CMDIFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + diff --git a/Examples/GUI/Win32/SampleMFC/MainFrm.h b/Examples/GUI/Win32/SampleMFC/MainFrm.h new file mode 100644 index 0000000..e570c52 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/MainFrm.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: MainFrm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// MainFrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAINFRM_H__B7F7B85D_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) +#define AFX_MAINFRM_H__B7F7B85D_EEC9_11D2_87FE_0060082B79FD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CMainFrame : public CMDIFrameWnd +{ + DECLARE_DYNAMIC(CMainFrame) +public: + CMainFrame(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__B7F7B85D_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/Resource.h b/Examples/GUI/Win32/SampleMFC/Resource.h new file mode 100644 index 0000000..d105e46 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/Resource.h @@ -0,0 +1,33 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Resource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by SAMPLE.RC +// +#define IDD_ABOUTBOX 100 +#define IDR_MAINFRAME 128 +#define IDR_SAMPLETYPE 129 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 32771 +#endif +#endif diff --git a/Examples/GUI/Win32/SampleMFC/Sample.cpp b/Examples/GUI/Win32/SampleMFC/Sample.cpp new file mode 100644 index 0000000..1cde5cb --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/Sample.cpp @@ -0,0 +1,168 @@ +// Sample.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "Sample.h" + +#include "MainFrm.h" +#include "ChildFrm.h" +#include "SampleDoc.h" +#include "SampleView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSampleApp + +BEGIN_MESSAGE_MAP(CSampleApp, CWinApp) + //{{AFX_MSG_MAP(CSampleApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) + // Standard print setup command + ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSampleApp construction + +CSampleApp::CSampleApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CSampleApp object + +CSampleApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CSampleApp initialization + +BOOL CSampleApp::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + // Change the registry key under which our settings are stored. + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization. + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CMultiDocTemplate* pDocTemplate; + pDocTemplate = new CMultiDocTemplate( + IDR_SAMPLETYPE, + RUNTIME_CLASS(CSampleDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CSampleView)); + AddDocTemplate(pDocTemplate); + + // create main MDI Frame window + CMainFrame* pMainFrame = new CMainFrame; + if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) + return FALSE; + m_pMainWnd = pMainFrame; + + // Enable drag/drop open + m_pMainWnd->DragAcceptFiles(); + + // Enable DDE Execute open + EnableShellOpen(); + RegisterShellFileTypes(TRUE); + + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + + // The main window has been initialized, so show and update it. + pMainFrame->ShowWindow(m_nCmdShow); + pMainFrame->UpdateWindow(); + + return TRUE; +} + + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CSampleApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CSampleApp message handlers + diff --git a/Examples/GUI/Win32/SampleMFC/Sample.h b/Examples/GUI/Win32/SampleMFC/Sample.h new file mode 100644 index 0000000..42b68b3 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/Sample.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Sample.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Sample.h : main header file for the SAMPLE application +// + +#if !defined(AFX_SAMPLE_H__B7F7B859_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) +#define AFX_SAMPLE_H__B7F7B859_EEC9_11D2_87FE_0060082B79FD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CSampleApp: +// See Sample.cpp for the implementation of this class +// + +class CSampleApp : public CWinApp +{ +public: + CSampleApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSampleApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + //{{AFX_MSG(CSampleApp) + afx_msg void OnAppAbout(); + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SAMPLE_H__B7F7B859_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/Sample.rc b/Examples/GUI/Win32/SampleMFC/Sample.rc new file mode 100644 index 0000000..53d5872 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/Sample.rc @@ -0,0 +1,361 @@ +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// + +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#ifdef APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\Sample.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#include ""afxprint.rc"" // printing/print preview resources\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +IDR_MAINFRAME ICON DISCARDABLE "res\\Sample.ico" +IDR_SAMPLETYPE ICON DISCARDABLE "res\\SampleDoc.ico" +#endif + + + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN + MENUITEM SEPARATOR + MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP + MENUITEM SEPARATOR + MENUITEM "Recent File", ID_FILE_MRU_FILE1,GRAYED + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About Sample...", ID_APP_ABOUT + END +END +IDR_SAMPLETYPE MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN + MENUITEM "&Close", ID_FILE_CLOSE + MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE + MENUITEM "Save &As...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT + MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW + MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP + MENUITEM SEPARATOR + MENUITEM "Recent File", ID_FILE_MRU_FILE1,GRAYED + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT + MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE + END + POPUP "&Window" + BEGIN + MENUITEM "&New Window", ID_WINDOW_NEW + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "&Tile", ID_WINDOW_TILE_HORZ + MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + END + POPUP "&Help" + BEGIN + MENUITEM "&About Sample...", ID_APP_ABOUT + END +END + + + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE +BEGIN + "N", ID_FILE_NEW, VIRTKEY,CONTROL + "O", ID_FILE_OPEN, VIRTKEY,CONTROL + "S", ID_FILE_SAVE, VIRTKEY,CONTROL + "P", ID_FILE_PRINT, VIRTKEY,CONTROL + "Z", ID_EDIT_UNDO, VIRTKEY,CONTROL + "X", ID_EDIT_CUT, VIRTKEY,CONTROL + "C", ID_EDIT_COPY, VIRTKEY,CONTROL + "V", ID_EDIT_PASTE, VIRTKEY,CONTROL + VK_BACK, ID_EDIT_UNDO, VIRTKEY,ALT + VK_DELETE, ID_EDIT_CUT, VIRTKEY,SHIFT + VK_INSERT, ID_EDIT_COPY, VIRTKEY,CONTROL + VK_INSERT, ID_EDIT_PASTE, VIRTKEY,SHIFT + VK_F6, ID_NEXT_PANE, VIRTKEY + VK_F6, ID_PREV_PANE, VIRTKEY,SHIFT +END + + + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 235, 55 +CAPTION "About Sample" +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "Sample Version 1.0",IDC_STATIC,40,10,119,8, + SS_NOPREFIX + LTEXT "Copyright (C) 1999",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP +END + + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "Sample MFC Application\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "Sample\0" + VALUE "LegalCopyright", "Copyright (C) 1999\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename","Sample.EXE\0" + VALUE "ProductName", "Sample Application\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END +END +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + IDR_MAINFRAME "Sample" + IDR_SAMPLETYPE "\nSample\nSample\nvtk Files (*.vtk)\n.vtk\nSample.Document\nSample Document" +END +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + AFX_IDS_APP_TITLE "Sample" + AFX_IDS_IDLEMESSAGE "Ready" +END +STRINGTABLE DISCARDABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_NEW "Create a new document\nNew" + ID_FILE_OPEN "Open an existing document\nOpen" + ID_FILE_CLOSE "Close the active document\nClose" + ID_FILE_SAVE "Save the active document\nSave" + ID_FILE_SAVE_AS "Save the active document with a new name\nSave As" + ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup" + ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup" + ID_FILE_PRINT "Print the active document\nPrint" + ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview" + ID_APP_ABOUT "Display program information, version number and copyright\nAbout" + ID_APP_EXIT "Quit the application; prompts to save documents\nExit" + ID_FILE_MRU_FILE1 "Open this document" + ID_FILE_MRU_FILE2 "Open this document" + ID_FILE_MRU_FILE3 "Open this document" + ID_FILE_MRU_FILE4 "Open this document" + ID_FILE_MRU_FILE5 "Open this document" + ID_FILE_MRU_FILE6 "Open this document" + ID_FILE_MRU_FILE7 "Open this document" + ID_FILE_MRU_FILE8 "Open this document" + ID_FILE_MRU_FILE9 "Open this document" + ID_FILE_MRU_FILE10 "Open this document" + ID_FILE_MRU_FILE11 "Open this document" + ID_FILE_MRU_FILE12 "Open this document" + ID_FILE_MRU_FILE13 "Open this document" + ID_FILE_MRU_FILE14 "Open this document" + ID_FILE_MRU_FILE15 "Open this document" + ID_FILE_MRU_FILE16 "Open this document" + ID_NEXT_PANE "Switch to the next window pane\nNext Pane" + ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" + ID_WINDOW_NEW "Open another window for the active document\nNew Window" + ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons" + ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows" + ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_SPLIT "Split the active window into panes\nSplit" + ID_EDIT_CLEAR "Erase the selection\nErase" + ID_EDIT_CLEAR_ALL "Erase everything\nErase All" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" + ID_EDIT_FIND "Find the specified text\nFind" + ID_EDIT_PASTE "Insert Clipboard contents\nPaste" + ID_EDIT_REPEAT "Repeat the last action\nRepeat" + ID_EDIT_REPLACE "Replace specific text with different text\nReplace" + ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" + ID_EDIT_UNDO "Undo the last action\nUndo" + ID_EDIT_REDO "Redo the previously undone action\nRedo" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" + AFX_IDS_MDICHILD "Activate this window" + AFX_IDS_PREVIEW_CLOSE "Close print preview mode\nCancel Preview" +END + + +#endif + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\\Sample.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#include "afxprint.rc" // printing/print preview resources +#endif + +#endif // not APSTUDIO_INVOKED diff --git a/Examples/GUI/Win32/SampleMFC/SampleDoc.cpp b/Examples/GUI/Win32/SampleMFC/SampleDoc.cpp new file mode 100644 index 0000000..3020c2f --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/SampleDoc.cpp @@ -0,0 +1,118 @@ +// SampleDoc.cpp : implementation of the CSampleDoc class +// + +#include "stdafx.h" +#include "Sample.h" + +#include "SampleDoc.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +#include "vtkTextMapper.h" +#include "vtkActor2D.h" +#include "vtkTextProperty.h" +///////////////////////////////////////////////////////////////////////////// +// CSampleDoc + +IMPLEMENT_DYNCREATE(CSampleDoc, vtkMFCDocument) + +BEGIN_MESSAGE_MAP(CSampleDoc, vtkMFCDocument) + //{{AFX_MSG_MAP(CSampleDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSampleDoc construction/destruction + +CSampleDoc::CSampleDoc() +{ + // TODO: add one-time construction code here + this->Reader = vtkDataSetReader::New(); + this->Mapper = vtkDataSetMapper::New(); + this->Actor = vtkActor::New(); + this->Actor->SetMapper(this->Mapper); + this->Actor->VisibilityOff(); + this->Props->AddItem(this->Actor); + + vtkActor2D *act = vtkActor2D::New(); + vtkTextMapper *txt = vtkTextMapper::New(); + act->SetMapper(txt); + txt->SetInput("Hello World"); + txt->GetTextProperty()->SetFontSize(24); + this->Props->AddItem(act); + txt->Delete(); + act->Delete(); +} + +CSampleDoc::~CSampleDoc() +{ + this->Reader->Delete(); + this->Mapper->Delete(); + this->Actor->Delete(); +} + +BOOL CSampleDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// CSampleDoc serialization + +void CSampleDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CSampleDoc diagnostics + +#ifdef _DEBUG +void CSampleDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CSampleDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CSampleDoc commands + +BOOL CSampleDoc::OnOpenDocument(LPCTSTR lpszPathName) +{ + if (!vtkMFCDocument::OnOpenDocument(lpszPathName)) + { + return FALSE; + } + + // TODO: Add your specialized creation code here + this->Reader->SetFileName(lpszPathName); + this->Mapper->SetInput(this->Reader->GetOutput()); + this->Actor->VisibilityOn(); + + return TRUE; +} diff --git a/Examples/GUI/Win32/SampleMFC/SampleDoc.h b/Examples/GUI/Win32/SampleMFC/SampleDoc.h new file mode 100644 index 0000000..7c82001 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/SampleDoc.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SampleDoc.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// SampleDoc.h : interface of the CSampleDoc class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_SAMPLEDOC_H__B7F7B861_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) +#define AFX_SAMPLEDOC_H__B7F7B861_EEC9_11D2_87FE_0060082B79FD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "vtkMFCDocument.h" +#include "vtkDataSetReader.h" +#include "vtkDataSetMapper.h" + +class CSampleDoc : public vtkMFCDocument +{ +protected: // create from serialization only + CSampleDoc(); + DECLARE_DYNCREATE(CSampleDoc) + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSampleDoc) + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CSampleDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + vtkDataSetReader *Reader; + vtkDataSetMapper *Mapper; + vtkActor *Actor; + +// Generated message map functions +protected: + //{{AFX_MSG(CSampleDoc) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SAMPLEDOC_H__B7F7B861_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/SampleView.cpp b/Examples/GUI/Win32/SampleMFC/SampleView.cpp new file mode 100644 index 0000000..15c4982 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/SampleView.cpp @@ -0,0 +1,85 @@ +// SampleView.cpp : implementation of the CSampleView class +// + +#include "stdafx.h" +#include "Sample.h" + +#include "SampleDoc.h" +#include "SampleView.h" + +#include "vtkRenderer.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSampleView + +IMPLEMENT_DYNCREATE(CSampleView, vtkMFCRenderView) + +BEGIN_MESSAGE_MAP(CSampleView, vtkMFCRenderView) + //{{AFX_MSG_MAP(CSampleView) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSampleView construction/destruction + +CSampleView::CSampleView() +{ + // TODO: add construction code here + +} + +CSampleView::~CSampleView() +{ +} + + +///////////////////////////////////////////////////////////////////////////// +// CSampleView diagnostics + +#ifdef _DEBUG +void CSampleView::AssertValid() const +{ + CView::AssertValid(); +} + +void CSampleView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CSampleDoc* CSampleView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSampleDoc))); + return (CSampleDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CSampleView message handlers + +void CSampleView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) +{ + // TODO: Add your specialized code here and/or call the base class + vtkPropCollection *propc; + vtkProp *prop; + // TODO: Add your specialized code here and/or call the base class + // first remove any old actors + this->Renderer->GetViewProps()->RemoveAllItems(); + propc = this->GetDocument()->GetViewProps(); + propc->InitTraversal(); + while (prop = propc->GetNextProp()) + { + this->Renderer->AddViewProp(prop); + this->Renderer->ResetCamera(); + } + + this->vtkMFCRenderView::OnUpdate(pSender, lHint, pHint); +} diff --git a/Examples/GUI/Win32/SampleMFC/SampleView.h b/Examples/GUI/Win32/SampleMFC/SampleView.h new file mode 100644 index 0000000..78655f7 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/SampleView.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SampleView.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// SampleView.h : interface of the CSampleView class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_SAMPLEVIEW_H__B7F7B863_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) +#define AFX_SAMPLEVIEW_H__B7F7B863_EEC9_11D2_87FE_0060082B79FD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "vtkMFCRenderView.h" + +class CSampleView : public vtkMFCRenderView +{ +protected: // create from serialization only + CSampleView(); + DECLARE_DYNCREATE(CSampleView) + +// Attributes +public: + CSampleDoc* GetDocument(); + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSampleView) + protected: + virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CSampleView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CSampleView) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in SampleView.cpp +inline CSampleDoc* CSampleView::GetDocument() + { return (CSampleDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SAMPLEVIEW_H__B7F7B863_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/StdAfx.cpp b/Examples/GUI/Win32/SampleMFC/StdAfx.cpp new file mode 100644 index 0000000..52fe1ce --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// Sample.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/Examples/GUI/Win32/SampleMFC/StdAfx.h b/Examples/GUI/Win32/SampleMFC/StdAfx.h new file mode 100644 index 0000000..6bc4ed1 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/StdAfx.h @@ -0,0 +1,41 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: StdAfx.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__B7F7B85B_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) +#define AFX_STDAFX_H__B7F7B85B_EEC9_11D2_87FE_0060082B79FD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__B7F7B85B_EEC9_11D2_87FE_0060082B79FD__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/res/Sample.ico b/Examples/GUI/Win32/SampleMFC/res/Sample.ico new file mode 100644 index 0000000..7eef0bc Binary files /dev/null and b/Examples/GUI/Win32/SampleMFC/res/Sample.ico differ diff --git a/Examples/GUI/Win32/SampleMFC/res/Sample.rc2 b/Examples/GUI/Win32/SampleMFC/res/Sample.rc2 new file mode 100644 index 0000000..3d56802 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/res/Sample.rc2 @@ -0,0 +1,13 @@ +// +// SAMPLE.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Examples/GUI/Win32/SampleMFC/res/SampleDoc.ico b/Examples/GUI/Win32/SampleMFC/res/SampleDoc.ico new file mode 100644 index 0000000..2a1f1ae Binary files /dev/null and b/Examples/GUI/Win32/SampleMFC/res/SampleDoc.ico differ diff --git a/Examples/GUI/Win32/SampleMFC/vtkMFCDocument.cpp b/Examples/GUI/Win32/SampleMFC/vtkMFCDocument.cpp new file mode 100644 index 0000000..475b3dd --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/vtkMFCDocument.cpp @@ -0,0 +1,75 @@ +// vtkMFCDocument.cpp : implementation file +// + +#include "stdafx.h" +#include "Sample.h" +#include "vtkMFCDocument.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCDocument + +IMPLEMENT_DYNCREATE(vtkMFCDocument, CDocument) + +vtkMFCDocument::vtkMFCDocument() +{ + this->Props = vtkPropCollection::New(); +} + +BOOL vtkMFCDocument::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + return TRUE; +} + +vtkMFCDocument::~vtkMFCDocument() +{ + if (this->Props) this->Props->Delete(); +} + + +BEGIN_MESSAGE_MAP(vtkMFCDocument, CDocument) + //{{AFX_MSG_MAP(vtkMFCDocument) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCDocument diagnostics + +#ifdef _DEBUG +void vtkMFCDocument::AssertValid() const +{ + CDocument::AssertValid(); +} + +void vtkMFCDocument::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCDocument serialization + +void vtkMFCDocument::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCDocument commands + diff --git a/Examples/GUI/Win32/SampleMFC/vtkMFCDocument.h b/Examples/GUI/Win32/SampleMFC/vtkMFCDocument.h new file mode 100644 index 0000000..1bd450f --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/vtkMFCDocument.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMFCDocument.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#if !defined(AFX_VTKMFCDOCUMENT_H__5D36A982_8081_11D2_985E_00A0CC243C06__INCLUDED_) +#define AFX_VTKMFCDOCUMENT_H__5D36A982_8081_11D2_985E_00A0CC243C06__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// vtkMFCDocument.h : header file +// +#include "vtkActorCollection.h" +#include "vtkVolumeCollection.h" +#include "vtkActor2DCollection.h" + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCDocument document + +class vtkMFCDocument : public CDocument +{ +protected: + vtkMFCDocument(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(vtkMFCDocument) + + vtkPropCollection *Props; + +// Attributes +public: + +// Operations +public: + vtkPropCollection *GetViewProps() {return this->Props;}; + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(vtkMFCDocument) + public: + virtual void Serialize(CArchive& ar); // overridden for document i/o + protected: + virtual BOOL OnNewDocument(); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~vtkMFCDocument(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions +protected: + //{{AFX_MSG(vtkMFCDocument) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VTKMFCDOCUMENT_H__5D36A982_8081_11D2_985E_00A0CC243C06__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/vtkMFCRenderView.cpp b/Examples/GUI/Win32/SampleMFC/vtkMFCRenderView.cpp new file mode 100644 index 0000000..3c1b67d --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/vtkMFCRenderView.cpp @@ -0,0 +1,233 @@ +// vtkMFCRenderView.cpp : implementation file +// + +#include "stdafx.h" +#include "vtkMFCRenderView.h" + +#include "vtkMFCDocument.h" + +#include "vtkRenderer.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +///////////////////////////////////////////////////////////////////////////// +// vtkMFCRenderView + +IMPLEMENT_DYNCREATE(vtkMFCRenderView, vtkMFCView) + +vtkMFCRenderView::vtkMFCRenderView() +{ + this->Renderer = vtkRenderer::New(); + this->RenderWindow = vtkWin32OpenGLRenderWindow::New(); + this->RenderWindow->AddRenderer(this->Renderer); + this->Interactor = vtkWin32RenderWindowInteractor::New(); +} + +vtkMFCRenderView::~vtkMFCRenderView() +{ + if (this->Interactor) + { + this->Interactor->Delete(); + } + if (this->Renderer) + { + this->Renderer->SetRenderWindow(NULL); + } + if (this->RenderWindow) + { + this->RenderWindow->Delete(); + } + if (this->Renderer) + { + this->Renderer->Delete(); + } +} + + +BEGIN_MESSAGE_MAP(vtkMFCRenderView, vtkMFCView) + //{{AFX_MSG_MAP(vtkMFCRenderView) + ON_WM_CREATE() + ON_WM_SIZE() + //}}AFX_MSG_MAP + ON_COMMAND(ID_FILE_PRINT, vtkMFCRenderView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, vtkMFCRenderView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, vtkMFCRenderView::OnFilePrintPreview) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCRenderView drawing + +void vtkMFCRenderView::OnDraw(CDC* pDC) +{ + CDocument* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if (!this->Interactor->GetInitialized()) + { + this->Interactor->SetRenderWindow(this->RenderWindow); + WNDPROC OldProc = (WNDPROC)GetWindowLong(this->m_hWnd,GWL_WNDPROC); + this->Interactor->Initialize(); + SetWindowLong(this->m_hWnd,GWL_WNDPROC,(LONG)OldProc); + } + + // TODO: add draw code for native data here + if (pDC->IsPrinting()) + { + int size[2]; + float scale; + + BeginWaitCursor(); + memcpy(size,this->RenderWindow->GetSize(),sizeof(int)*2); + + int cxDIB = size[0]; // Size of DIB - x + int cyDIB = size[1]; // Size of DIB - y + CRect rcDest; + + // get size of printer page (in pixels) + int cxPage = pDC->GetDeviceCaps(HORZRES); + int cyPage = pDC->GetDeviceCaps(VERTRES); + // get printer pixels per inch + int cxInch = pDC->GetDeviceCaps(LOGPIXELSX); + int cyInch = pDC->GetDeviceCaps(LOGPIXELSY); + scale = cxInch/this->GetPrintDPI(); + + // + // Best Fit case -- create a rectangle which preserves + // the DIB's aspect ratio, and fills the page horizontally. + // + // The formula in the "->bottom" field below calculates the Y + // position of the printed bitmap, based on the size of the + // bitmap, the width of the page, and the relative size of + // a printed pixel (cyInch / cxInch). + // + rcDest.bottom = rcDest.left = 0; + if (((float)cyDIB*(float)cxPage/(float)cxInch) > + ((float)cxDIB*(float)cyPage/(float)cyInch)) + { + rcDest.top = cyPage; + rcDest.right = ((float)(cyPage*cxInch*cxDIB)) / + ((float)(cyInch*cyDIB)); + } + else + { + rcDest.right = cxPage; + rcDest.top = ((float)(cxPage*cyInch*cyDIB)) / + ((float)(cxInch*cxDIB)); + } + + CRect rcDestLP(rcDest); + pDC->DPtoLP(rcDestLP); + int DPI = this->RenderWindow->GetDPI(); + + this->RenderWindow->SetupMemoryRendering(rcDest.right/scale, + rcDest.top/scale, + pDC->m_hAttribDC); + + this->RenderWindow->Render(); + + pDC->SetStretchBltMode(HALFTONE); + + StretchBlt(pDC->GetSafeHdc(),0,0, + rcDest.right, rcDest.top, + this->RenderWindow->GetMemoryDC(), + 0, 0, rcDest.right/scale, rcDest.top/scale, SRCCOPY); + + this->RenderWindow->ResumeScreenRendering(); + + EndWaitCursor(); + } + else + { + this->RenderWindow->Render(); + } + CView::OnDraw(pDC); +} + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCRenderView diagnostics + +#ifdef _DEBUG +void vtkMFCRenderView::AssertValid() const +{ + CView::AssertValid(); +} + +void vtkMFCRenderView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCRenderView message handlers + + +int vtkMFCRenderView::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (vtkMFCView::OnCreate(lpCreateStruct) == -1) + return -1; + + // TODO: Add your specialized creation code here + this->RenderWindow->SetParentId(lpCreateStruct->hwndParent); + + return 0; +} + +void vtkMFCRenderView::OnInitialUpdate() +{ + vtkMFCView::OnInitialUpdate(); + + // TODO: Add your specialized creation code here + + this->RenderWindow->SetWindowId(this->m_hWnd); + this->RenderWindow->WindowInitialize(); +} + +// Define our own event handler here +LRESULT vtkMFCRenderView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + //case WM_PAINT: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSEMOVE: + case WM_MOUSEWHEEL: + case WM_CHAR: + case WM_TIMER: + if (this->Interactor->GetInitialized()) + { + return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam, + this->Interactor); + } + break; + } + return vtkMFCView::WindowProc(message, wParam, lParam); +} + +void vtkMFCRenderView::OnSize(UINT nType, int cx, int cy) +{ + vtkMFCView::OnSize(nType, cx, cy); + + // TODO: Add your message handler code here + if (this->Interactor->GetInitialized()) + { + this->Interactor->SetSize(cx,cy); + } +} + +BOOL vtkMFCRenderView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // TODO: call DoPreparePrinting to invoke the Print dialog box + // default preparation + pInfo->SetMinPage(1); + pInfo->SetMaxPage(1); + return DoPreparePrinting(pInfo); +} diff --git a/Examples/GUI/Win32/SampleMFC/vtkMFCRenderView.h b/Examples/GUI/Win32/SampleMFC/vtkMFCRenderView.h new file mode 100644 index 0000000..9b094e6 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/vtkMFCRenderView.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMFCRenderView.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#if !defined(AFX_VTKMFCRENDERVIEW_H__AEB91BA7_8091_11D2_985E_00A0CC243C06__INCLUDED_) +#define AFX_VTKMFCRENDERVIEW_H__AEB91BA7_8091_11D2_985E_00A0CC243C06__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// vtkMFCRenderView.h : header file +// +#include "vtkMFCView.h" +#include "vtkWin32OpenGLRenderWindow.h" +#include "vtkWin32RenderWindowInteractor.h" + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCRenderView view + +class vtkMFCRenderView : public vtkMFCView +{ +protected: + vtkMFCRenderView(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(vtkMFCRenderView) + + vtkRenderer *Renderer; + vtkWin32OpenGLRenderWindow *RenderWindow; + vtkWin32RenderWindowInteractor *Interactor; + + // Attributes +public: + + // Operations +public: + virtual void OnInitialUpdate(); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + void Render() {this->RenderWindow->Render();}; + vtkWindow *GetVTKWindow() {return this->RenderWindow;}; + virtual void SetupMemoryRendering(int x, int y, HDC prn) { + this->RenderWindow->SetupMemoryRendering(x,y,prn);}; + virtual void ResumeScreenRendering() { + this->RenderWindow->ResumeScreenRendering();}; + virtual unsigned char *GetMemoryData() { + return this->RenderWindow->GetMemoryData();}; + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(vtkMFCRenderView) +protected: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + //}}AFX_VIRTUAL + + // Implementation +protected: + virtual ~vtkMFCRenderView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions +protected: + //{{AFX_MSG(vtkMFCRenderView) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + }; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VTKMFCRENDERVIEW_H__AEB91BA7_8091_11D2_985E_00A0CC243C06__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/vtkMFCView.cpp b/Examples/GUI/Win32/SampleMFC/vtkMFCView.cpp new file mode 100644 index 0000000..774a717 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/vtkMFCView.cpp @@ -0,0 +1,129 @@ +// vtkMFCView.cpp : implementation file +// + +#include "stdafx.h" +#include "vtkMFCView.h" +#include "vtkMFCDocument.h" +#include "resource.h" + +#include "vtkWindowToImageFilter.h" +#include "vtkBMPWriter.h" +#include "vtkTIFFWriter.h" +#include "vtkPNMWriter.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCView + +IMPLEMENT_DYNCREATE(vtkMFCView, CView) + +vtkMFCView::vtkMFCView() +{ + this->PrintDPI = 100; +} + +vtkMFCView::~vtkMFCView() +{ +} + + +BEGIN_MESSAGE_MAP(vtkMFCView, CView) + //{{AFX_MSG_MAP(vtkMFCView) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCView drawing + +void vtkMFCView::OnDraw(CDC* pDC) +{ + CDocument* pDoc = GetDocument(); + // TODO: add draw code here +} + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCView diagnostics + +#ifdef _DEBUG +void vtkMFCView::AssertValid() const +{ + CView::AssertValid(); +} + +void vtkMFCView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCView message handlers + +BOOL vtkMFCView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Add your specialized code here and/or call the base class + // the CREATESTRUCT cs + cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_OWNDC; + return CView::PreCreateWindow(cs); +} + +BOOL vtkMFCView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // TODO: call DoPreparePrinting to invoke the Print dialog box + // default preparation + pInfo->SetMinPage(1); + pInfo->SetMaxPage(1); + return DoPreparePrinting(pInfo); +} + +void vtkMFCView::OnEditCopy() +{ + // TODO: Add your command handler code here + LPBITMAPINFOHEADER lpbi; // pointer to BITMAPINFOHEADER + DWORD dwLen; // size of memory block + HANDLE hDIB = NULL; // handle to DIB, temp handle + vtkWindow *vtkWin = this->GetVTKWindow(); + int *size = vtkWin->GetSize(); + int dataWidth = ((size[0]*3+3)/4)*4; + + if (OpenClipboard()) + { + BeginWaitCursor(); + EmptyClipboard(); + + dwLen = sizeof(BITMAPINFOHEADER) + dataWidth*size[1]; + hDIB = ::GlobalAlloc(GHND, dwLen); + lpbi = (LPBITMAPINFOHEADER) ::GlobalLock(hDIB); + + lpbi->biSize = sizeof(BITMAPINFOHEADER); + lpbi->biWidth = size[0]; + lpbi->biHeight = size[1]; + lpbi->biPlanes = 1; + lpbi->biBitCount = 24; + lpbi->biCompression = BI_RGB; + lpbi->biClrUsed = 0; + lpbi->biClrImportant = 0; + lpbi->biSizeImage = dataWidth*size[1]; + + this->SetupMemoryRendering(size[0],size[1], + this->GetDC()->GetSafeHdc()); + vtkWin->Render(); + + memcpy((LPSTR)lpbi + lpbi->biSize, + this->GetMemoryData(),dataWidth*size[1]); + + SetClipboardData (CF_DIB, hDIB); + ::GlobalUnlock(hDIB); + CloseClipboard(); + this->ResumeScreenRendering(); + EndWaitCursor(); + } +} + diff --git a/Examples/GUI/Win32/SampleMFC/vtkMFCView.h b/Examples/GUI/Win32/SampleMFC/vtkMFCView.h new file mode 100644 index 0000000..2f8f420 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/vtkMFCView.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMFCView.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#if !defined(AFX_VTKMFCVIEW_H__5D36A981_8081_11D2_985E_00A0CC243C06__INCLUDED_) +#define AFX_VTKMFCVIEW_H__5D36A981_8081_11D2_985E_00A0CC243C06__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// vtkMFCView.h : header file +// +#define vtkMFCSetObjectMacro(name,type) \ +void Set##name (type* _arg) \ + { \ + if (this->name != _arg) \ + { \ + if (this->name != NULL) { this->name->UnRegister(NULL); }\ + this->name = _arg; \ + if (this->name != NULL) { this->name->Register(NULL); } \ + } \ + } + +///////////////////////////////////////////////////////////////////////////// +// vtkMFCView view +class vtkMFCDocument; +#include "vtkWindow.h" + +class vtkMFCView : public CView +{ +protected: + vtkMFCView(); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(vtkMFCView) + int PrintDPI; + +// Attributes +public: + +// Operations +public: + void SetPrintDPI(int dpi) {this->PrintDPI = dpi;}; + int GetPrintDPI() {return this->PrintDPI;}; + vtkMFCDocument *GetDocument() {return (vtkMFCDocument *)m_pDocument;}; + virtual vtkWindow *GetVTKWindow() {return NULL;}; + virtual void SetupMemoryRendering(int x, int y, HDC prn) {}; + virtual void ResumeScreenRendering() {}; + virtual unsigned char *GetMemoryData() {return NULL;}; + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(vtkMFCView) +protected: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~vtkMFCView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions +protected: + //{{AFX_MSG(vtkMFCView) + afx_msg void OnEditCopy(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + }; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VTKMFCVIEW_H__5D36A981_8081_11D2_985E_00A0CC243C06__INCLUDED_) diff --git a/Examples/GUI/Win32/SampleMFC/weldedSpheres.vtk b/Examples/GUI/Win32/SampleMFC/weldedSpheres.vtk new file mode 100644 index 0000000..5107019 --- /dev/null +++ b/Examples/GUI/Win32/SampleMFC/weldedSpheres.vtk @@ -0,0 +1,5163 @@ +# vtk DataFile Version 2.0 +vtk output +ASCII +DATASET POLYDATA +POINTS 2312 float +0.263107 0 0.425176 0.33131 0 0.374478 0.389942 0 0.312962 +0.43731 0 0.242405 0.472045 0 0.164845 0.493143 0 0.0825238 +0.499995 0 -0.00218166 0.251418 0.0775521 0.425176 0.316591 0.0976553 0.374478 +0.372618 0.114937 0.312962 0.417881 0.128899 0.242405 0.451073 0.139138 0.164845 +0.471234 0.145356 0.0825238 0.477782 0.147376 -0.00218166 0.217389 0.148213 0.425176 +0.273741 0.186634 0.374478 0.322185 0.219662 0.312962 0.361322 0.246345 0.242405 +0.390021 0.265912 0.164845 0.407454 0.277797 0.0825238 0.413115 0.281657 -0.00218166 +0.164045 0.205705 0.425176 0.206568 0.259029 0.374478 0.243125 0.304869 0.312962 +0.272658 0.341903 0.242405 0.294315 0.369059 0.164845 0.30747 0.385555 0.0825238 +0.311742 0.390912 -0.00218166 0.0961238 0.244919 0.425176 0.121041 0.308408 0.374478 +0.142462 0.362987 0.312962 0.159767 0.40708 0.242405 0.172457 0.439414 0.164845 +0.180165 0.459054 0.0825238 0.182669 0.465432 -0.00218166 0.019662 0.262371 0.425176 +0.0247588 0.330384 0.374478 0.0291404 0.388852 0.312962 0.0326802 0.436087 0.242405 +0.0352759 0.470725 0.164845 0.0368526 0.491764 0.0825238 0.0373646 0.498597 -0.00218166 +-0.0585468 0.25651 0.425176 -0.0737234 0.323003 0.374478 -0.0867703 0.380166 0.312962 +-0.0973106 0.426346 0.242405 -0.10504 0.460209 0.164845 -0.109735 0.480779 0.0825238 +-0.111259 0.487459 -0.00218166 -0.131554 0.227857 0.425176 -0.165655 0.286923 0.374478 +-0.194971 0.3377 0.312962 -0.218655 0.378721 0.242405 -0.236022 0.408803 0.164845 +-0.246571 0.427074 0.0825238 -0.249998 0.433009 -0.00218166 0.129331 0.253826 0.409691 +0.135149 0.265245 0.400476 0.140832 0.276398 0.39086 0.146374 0.287275 0.380853 +0.151769 0.297864 0.370465 0.157013 0.308155 0.359706 0.162099 0.318138 0.348587 +0.167024 0.327803 0.33712 0.171781 0.337139 0.325315 0.176366 0.346138 0.313184 +0.180775 0.354791 0.30074 0.185003 0.363089 0.287995 0.189046 0.371023 0.274962 +0.1929 0.378587 0.261654 0.19656 0.385771 0.248084 0.200024 0.392569 0.234266 +0.203288 0.398975 0.220214 0.206348 0.404981 0.205941 0.209202 0.410582 0.191462 +0.211847 0.415773 0.176791 0.214279 0.420547 0.161944 0.216497 0.4249 0.146934 +0.218499 0.428828 0.131778 0.220282 0.432328 0.116489 0.221844 0.435394 0.101084 +0.223185 0.438025 0.0855781 0.224302 0.440218 0.0699863 0.225195 0.44197 0.0543245 +0.225862 0.443279 0.0386084 0.226304 0.444146 0.0228536 0.226518 0.444568 0.00707595 +0.226507 0.444545 -0.00870878 0.226268 0.444077 -0.0244848 0.225804 0.443164 -0.0402363 +0.225113 0.441809 -0.0559476 0.224197 0.440011 -0.0716029 0.223057 0.437773 -0.0871865 +0.221693 0.435097 -0.102683 0.220108 0.431986 -0.118076 0.218302 0.428442 -0.133352 +0.216278 0.42447 -0.148494 0.214038 0.420072 -0.163487 0.211583 0.415255 -0.178317 +0.208917 0.410022 -0.192969 0.206041 0.404379 -0.207427 0.20296 0.398331 -0.221678 +0.199675 0.391884 -0.235707 0.117895 0.259335 0.409691 0.123199 0.271002 0.400476 +0.128379 0.282397 0.39086 0.133431 0.29351 0.380853 0.13835 0.304329 0.370465 +0.14313 0.314844 0.359706 0.147766 0.325043 0.348587 0.152255 0.334918 0.33712 +0.156592 0.344457 0.325315 0.160772 0.353651 0.313184 0.164791 0.362492 0.30074 +0.168645 0.37097 0.287995 0.17233 0.379076 0.274962 0.175843 0.386804 0.261654 +0.17918 0.394144 0.248084 0.182338 0.40109 0.234266 0.185313 0.407635 0.220214 +0.188103 0.413771 0.205941 0.190704 0.419494 0.191462 0.193115 0.424797 0.176791 +0.195333 0.429675 0.161944 0.197355 0.434123 0.146934 0.199179 0.438136 0.131778 +0.200804 0.441711 0.116489 0.202229 0.444844 0.101084 0.203451 0.447532 0.0855781 +0.204469 0.449773 0.0699863 0.205283 0.451563 0.0543245 0.205891 0.452901 0.0386084 +0.206294 0.453786 0.0228536 0.20649 0.454217 0.00707595 0.206479 0.454193 -0.00870878 +0.206262 0.453715 -0.0244848 0.205838 0.452783 -0.0402363 0.205208 0.451398 -0.0559476 +0.204373 0.449562 -0.0716029 0.203334 0.447275 -0.0871865 0.202091 0.444541 -0.102683 +0.200646 0.441362 -0.118076 0.199 0.437741 -0.133352 0.197155 0.433683 -0.148494 +0.195112 0.42919 -0.163487 0.192875 0.424268 -0.178317 0.190444 0.418921 -0.192969 +0.187823 0.413156 -0.207427 0.185014 0.406976 -0.221678 0.18202 0.40039 -0.235707 +0.106226 0.26433 0.409691 0.111004 0.276221 0.400476 0.115672 0.287836 0.39086 +0.120224 0.299163 0.380853 0.124655 0.31019 0.370465 0.128962 0.320907 0.359706 +0.13314 0.331303 0.348587 0.137185 0.341368 0.33712 0.141092 0.35109 0.325315 +0.144858 0.360462 0.313184 0.148479 0.369473 0.30074 0.151952 0.378114 0.287995 +0.155272 0.386377 0.274962 0.158438 0.394253 0.261654 0.161444 0.401735 0.248084 +0.164289 0.408815 0.234266 0.16697 0.415485 0.220214 0.169484 0.42174 0.205941 +0.171828 0.427573 0.191462 0.174 0.432978 0.176791 0.175998 0.43795 0.161944 +0.17782 0.442483 0.146934 0.179464 0.446574 0.131778 0.180928 0.450218 0.116489 +0.182212 0.453411 0.101084 0.183313 0.456151 0.0855781 0.18423 0.458434 0.0699863 +0.184963 0.460259 0.0543245 0.185512 0.461623 0.0386084 0.185874 0.462525 0.0228536 +0.186051 0.462965 0.00707595 0.186041 0.462941 -0.00870878 0.185845 0.462453 -0.0244848 +0.185463 0.461503 -0.0402363 0.184896 0.460092 -0.0559476 0.184144 0.458219 -0.0716029 +0.183207 0.455889 -0.0871865 0.182087 0.453102 -0.102683 0.180785 0.449862 -0.118076 +0.179302 0.446172 -0.133352 0.17764 0.442035 -0.148494 0.175799 0.437456 -0.163487 +0.173783 0.432439 -0.178317 0.171593 0.426989 -0.192969 0.169232 0.421112 -0.207427 +0.166701 0.414814 -0.221678 0.164003 0.408101 -0.235707 0.0943451 0.268799 0.409691 +0.0985894 0.280892 0.400476 0.102735 0.292703 0.39086 0.106778 0.304221 0.380853 +0.110714 0.315435 0.370465 0.114539 0.326333 0.359706 0.118249 0.336905 0.348587 +0.121842 0.34714 0.33712 0.125312 0.357027 0.325315 0.128657 0.366557 0.313184 +0.131873 0.37572 0.30074 0.134957 0.384508 0.287995 0.137907 0.39291 0.274962 +0.140718 0.40092 0.261654 0.143388 0.408528 0.248084 0.145915 0.415727 0.234266 +0.148296 0.422511 0.220214 0.150528 0.428871 0.205941 0.15261 0.434803 0.191462 +0.154539 0.440299 0.176791 0.156314 0.445355 0.161944 0.157932 0.449965 0.146934 +0.159392 0.454125 0.131778 0.160693 0.457831 0.116489 0.161833 0.461078 0.101084 +0.162811 0.463864 0.0855781 0.163625 0.466186 0.0699863 0.164277 0.468042 0.0543245 +0.164764 0.469429 0.0386084 0.165086 0.470346 0.0228536 0.165242 0.470793 0.00707595 +0.165234 0.470768 -0.00870878 0.16506 0.470273 -0.0244848 0.164721 0.469307 -0.0402363 +0.164217 0.467871 -0.0559476 0.163549 0.465968 -0.0716029 0.162717 0.463598 -0.0871865 +0.161722 0.460764 -0.102683 0.160566 0.457469 -0.118076 0.159249 0.453716 -0.133352 +0.157772 0.449509 -0.148494 0.156138 0.444853 -0.163487 0.154347 0.439751 -0.178317 +0.152402 0.434209 -0.192969 0.150304 0.428233 -0.207427 0.148056 0.421828 -0.221678 +0.14566 0.415002 -0.235707 0.0822773 0.272735 0.409691 0.0859787 0.285005 0.400476 +0.089594 0.296989 0.39086 0.0931197 0.308676 0.380853 0.0965522 0.320054 0.370465 +0.0998881 0.331112 0.359706 0.103124 0.341838 0.348587 0.106257 0.352223 0.33712 +0.109283 0.362255 0.325315 0.1122 0.371925 0.313184 0.115005 0.381222 0.30074 +0.117695 0.390138 0.287995 0.120267 0.398663 0.274962 0.122718 0.40679 0.261654 +0.125047 0.41451 0.248084 0.127251 0.421815 0.234266 0.129327 0.428697 0.220214 +0.131274 0.435151 0.205941 0.13309 0.44117 0.191462 0.134772 0.446746 0.176791 +0.13632 0.451876 0.161944 0.137731 0.456554 0.146934 0.139004 0.460775 0.131778 +0.140138 0.464535 0.116489 0.141132 0.46783 0.101084 0.141985 0.470657 0.0855781 +0.142696 0.473012 0.0699863 0.143264 0.474895 0.0543245 0.143688 0.476302 0.0386084 +0.143969 0.477233 0.0228536 0.144106 0.477687 0.00707595 0.144099 0.477662 -0.00870878 +0.143947 0.477159 -0.0244848 0.143651 0.476179 -0.0402363 0.143212 0.474722 -0.0559476 +0.142629 0.472791 -0.0716029 0.141904 0.470386 -0.0871865 0.141036 0.46751 -0.102683 +0.140028 0.464167 -0.118076 0.138879 0.46036 -0.133352 0.137591 0.456091 -0.148494 +0.136166 0.451366 -0.163487 0.134604 0.44619 -0.178317 0.132908 0.440567 -0.192969 +0.131079 0.434504 -0.207427 0.129118 0.428005 -0.221678 0.127029 0.421078 -0.235707 +0.0700461 0.27613 0.409691 0.0731973 0.288552 0.400476 0.0762751 0.300685 0.39086 +0.0792767 0.312518 0.380853 0.0821989 0.324037 0.370465 0.0850389 0.335233 0.359706 +0.0877938 0.346093 0.348587 0.0904608 0.356607 0.33712 0.0930374 0.366764 0.325315 +0.0955208 0.376553 0.313184 0.0979086 0.385967 0.30074 0.100198 0.394994 0.287995 +0.102388 0.403625 0.274962 0.104475 0.411853 0.261654 0.106458 0.419669 0.248084 +0.108334 0.427065 0.234266 0.110102 0.434033 0.220214 0.111759 0.440567 0.205941 +0.113305 0.44666 0.191462 0.114737 0.452307 0.176791 0.116055 0.4575 0.161944 +0.117256 0.462236 0.146934 0.11834 0.46651 0.131778 0.119306 0.470316 0.116489 +0.120152 0.473652 0.101084 0.120878 0.476514 0.0855781 0.121483 0.4789 0.0699863 +0.121967 0.480806 0.0543245 0.122328 0.482231 0.0386084 0.122567 0.483173 0.0228536 +0.122683 0.483632 0.00707595 0.122677 0.483607 -0.00870878 0.122548 0.483098 -0.0244848 +0.122296 0.482105 -0.0402363 0.121922 0.480631 -0.0559476 0.121426 0.478675 -0.0716029 +0.120808 0.47624 -0.0871865 0.12007 0.473329 -0.102683 0.119211 0.469944 -0.118076 +0.118233 0.466089 -0.133352 0.117137 0.461768 -0.148494 0.115924 0.456984 -0.163487 +0.114594 0.451743 -0.178317 0.11315 0.446051 -0.192969 0.111593 0.439911 -0.207427 +0.109924 0.433332 -0.221678 0.108145 0.426319 -0.235707 0.0576759 0.278976 0.409691 +0.0602705 0.291526 0.400476 0.0628048 0.303784 0.39086 0.0652763 0.315739 0.380853 +0.0676825 0.327377 0.370465 0.0700209 0.338688 0.359706 0.0722893 0.34966 0.348587 +0.0744853 0.360282 0.33712 0.0766068 0.370544 0.325315 0.0786517 0.380435 0.313184 +0.0806178 0.389945 0.30074 0.0825033 0.399065 0.287995 0.0843062 0.407786 0.274962 +0.0860248 0.416098 0.261654 0.0876573 0.423994 0.248084 0.089202 0.431466 0.234266 +0.0906575 0.438507 0.220214 0.0920223 0.445108 0.205941 0.0932951 0.451264 0.191462 +0.0944744 0.456969 0.176791 0.0955592 0.462216 0.161944 0.0965485 0.467001 0.146934 +0.0974411 0.471318 0.131778 0.0982362 0.475164 0.116489 0.0989329 0.478534 0.101084 +0.0995307 0.481426 0.0855781 0.100029 0.483836 0.0699863 0.100427 0.485762 0.0543245 +0.100725 0.487201 0.0386084 0.100922 0.488153 0.0228536 0.101017 0.488617 0.00707595 +0.101012 0.488592 -0.00870878 0.100906 0.488077 -0.0244848 0.100699 0.487075 -0.0402363 +0.100391 0.485585 -0.0559476 0.099982 0.483609 -0.0716029 0.0994735 0.481149 -0.0871865 +0.0988654 0.478208 -0.102683 0.0981584 0.474788 -0.118076 0.0973532 0.470893 -0.133352 +0.0964506 0.466527 -0.148494 0.0954514 0.461695 -0.163487 0.0943568 0.4564 -0.178317 +0.0931677 0.450648 -0.192969 0.0918854 0.444446 -0.207427 0.0905112 0.437799 -0.221678 +0.0890463 0.430713 -0.235707 0.0451912 0.281268 0.409691 0.0472242 0.293921 0.400476 +0.0492099 0.306281 0.39086 0.0511464 0.318333 0.380853 0.0530317 0.330067 0.370465 +0.0548639 0.341471 0.359706 0.0566413 0.352533 0.348587 0.058362 0.363243 0.33712 +0.0600242 0.373589 0.325315 0.0616265 0.383561 0.313184 0.063167 0.393149 0.30074 +0.0646443 0.402344 0.287995 0.066057 0.411136 0.274962 0.0674036 0.419517 0.261654 +0.0686827 0.427478 0.248084 0.069893 0.435012 0.234266 0.0710335 0.44211 0.220214 +0.0721029 0.448766 0.205941 0.0731001 0.454972 0.191462 0.0740242 0.460724 0.176791 +0.0748742 0.466014 0.161944 0.0756492 0.470838 0.146934 0.0763486 0.475191 0.131778 +0.0769716 0.479069 0.116489 0.0775176 0.482467 0.101084 0.077986 0.485382 0.0855781 +0.0783763 0.487812 0.0699863 0.0786883 0.489753 0.0543245 0.0789215 0.491204 0.0386084 +0.0790757 0.492164 0.0228536 0.0791508 0.492632 0.00707595 0.0791467 0.492606 -0.00870878 +0.0790634 0.492088 -0.0244848 0.078901 0.491077 -0.0402363 0.0786597 0.489575 -0.0559476 +0.0783396 0.487583 -0.0716029 0.0779411 0.485103 -0.0871865 0.0774647 0.482137 -0.102683 +0.0769107 0.47869 -0.118076 0.0762798 0.474763 -0.133352 0.0755726 0.470361 -0.148494 +0.0747897 0.465488 -0.163487 0.073932 0.46015 -0.178317 0.0730003 0.454351 -0.192969 +0.0719956 0.448098 -0.207427 0.0709188 0.441396 -0.221678 0.0697711 0.434253 -0.235707 +0.0326167 0.283002 0.409691 0.034084 0.295733 0.400476 0.0355172 0.308169 0.39086 +0.0369149 0.320296 0.380853 0.0382756 0.332102 0.370465 0.039598 0.343576 0.359706 +0.0408808 0.354707 0.348587 0.0421227 0.365482 0.33712 0.0433224 0.375892 0.325315 +0.0444788 0.385925 0.313184 0.0455907 0.395573 0.30074 0.046657 0.404824 0.287995 +0.0476766 0.413671 0.274962 0.0486485 0.422103 0.261654 0.0495717 0.430114 0.248084 +0.0504452 0.437694 0.234266 0.0512684 0.444835 0.220214 0.0520402 0.451532 0.205941 +0.0527599 0.457777 0.191462 0.0534269 0.463564 0.176791 0.0540404 0.468887 0.161944 +0.0545998 0.473741 0.146934 0.0551045 0.47812 0.131778 0.0555542 0.482022 0.116489 +0.0559482 0.485441 0.101084 0.0562863 0.488374 0.0855781 0.0565681 0.490819 0.0699863 +0.0567932 0.492772 0.0543245 0.0569615 0.494233 0.0386084 0.0570728 0.495198 0.0228536 +0.057127 0.495669 0.00707595 0.0571241 0.495643 -0.00870878 0.057064 0.495121 -0.0244848 +0.0569467 0.494104 -0.0402363 0.0567725 0.492593 -0.0559476 0.0565415 0.490589 -0.0716029 +0.0562539 0.488093 -0.0871865 0.0559101 0.48511 -0.102683 0.0555102 0.481641 -0.118076 +0.0550549 0.477689 -0.133352 0.0545444 0.47326 -0.148494 0.0539794 0.468358 -0.163487 +0.0533603 0.462987 -0.178317 0.0526879 0.457152 -0.192969 0.0519627 0.45086 -0.207427 +0.0511856 0.444117 -0.221678 0.0503572 0.43693 -0.235707 0.0199774 0.284174 0.409691 +0.0208762 0.296958 0.400476 0.021754 0.309445 0.39086 0.02261 0.321622 0.380853 +0.0234435 0.333477 0.370465 0.0242534 0.344999 0.359706 0.0250391 0.356176 0.348587 +0.0257998 0.366996 0.33712 0.0265346 0.377448 0.325315 0.0272429 0.387524 0.313184 +0.0279239 0.397211 0.30074 0.028577 0.406501 0.287995 0.0292015 0.415384 0.274962 +0.0297968 0.423852 0.261654 0.0303622 0.431895 0.248084 0.0308973 0.439506 0.234266 +0.0314014 0.446678 0.220214 0.0318742 0.453402 0.205941 0.032315 0.459673 0.191462 +0.0327235 0.465484 0.176791 0.0330993 0.470829 0.161944 0.0334419 0.475703 0.146934 +0.0337511 0.480101 0.131778 0.0340265 0.484018 0.116489 0.0342678 0.487451 0.101084 +0.0344749 0.490397 0.0855781 0.0346475 0.492851 0.0699863 0.0347854 0.494813 0.0543245 +0.0348884 0.496279 0.0386084 0.0349566 0.497249 0.0228536 0.0349898 0.497721 0.00707595 +0.034988 0.497696 -0.00870878 0.0349512 0.497172 -0.0244848 0.0348794 0.496151 -0.0402363 +0.0347727 0.494633 -0.0559476 0.0346312 0.49262 -0.0716029 0.0344551 0.490115 -0.0871865 +0.0342444 0.487119 -0.102683 0.0339996 0.483635 -0.118076 0.0337206 0.479668 -0.133352 +0.033408 0.47522 -0.148494 0.0330619 0.470298 -0.163487 0.0326828 0.464904 -0.178317 +0.0322709 0.459045 -0.192969 0.0318267 0.452727 -0.207427 0.0313507 0.445956 -0.221678 +0.0308434 0.438739 -0.235707 0.00729854 0.284782 0.409691 0.00762688 0.297593 0.400476 +0.00794758 0.310107 0.39086 0.00826033 0.32231 0.380853 0.00856482 0.334191 0.370465 +0.00886073 0.345737 0.359706 0.00914778 0.356937 0.348587 0.00942568 0.367781 0.33712 +0.00969414 0.378256 0.325315 0.0099529 0.388353 0.313184 0.0102017 0.398061 0.30074 +0.0104403 0.40737 0.287995 0.0106685 0.416273 0.274962 0.0108859 0.424758 0.261654 +0.0110925 0.432819 0.248084 0.011288 0.440446 0.234266 0.0114722 0.447633 0.220214 +0.0116449 0.454372 0.205941 0.0118059 0.460656 0.191462 0.0119552 0.466479 0.176791 +0.0120925 0.471836 0.161944 0.0122176 0.47672 0.146934 0.0123306 0.481127 0.131778 +0.0124312 0.485053 0.116489 0.0125194 0.488494 0.101084 0.012595 0.491446 0.0855781 +0.0126581 0.493906 0.0699863 0.0127085 0.495871 0.0543245 0.0127461 0.497341 0.0386084 +0.012771 0.498313 0.0228536 0.0127832 0.498786 0.00707595 0.0127825 0.49876 -0.00870878 +0.012769 0.498235 -0.0244848 0.0127428 0.497212 -0.0402363 0.0127038 0.495691 -0.0559476 +0.0126521 0.493674 -0.0716029 0.0125878 0.491163 -0.0871865 0.0125108 0.488161 -0.102683 +0.0124214 0.48467 -0.118076 0.0123195 0.480694 -0.133352 0.0122053 0.476237 -0.148494 +0.0120788 0.471303 -0.163487 0.0119403 0.465898 -0.178317 0.0117898 0.460027 -0.192969 +0.0116276 0.453696 -0.207427 0.0114537 0.44691 -0.221678 0.0112683 0.439677 -0.235707 +-0.00539485 0.284824 0.409691 -0.00563754 0.297638 0.400476 -0.0058746 0.310153 0.39086 +-0.00610577 0.322358 0.380853 -0.00633084 0.334241 0.370465 -0.00654957 0.345789 0.359706 +-0.00676175 0.356991 0.348587 -0.00696716 0.367835 0.33712 -0.0071656 0.378312 0.325315 +-0.00735687 0.38841 0.313184 -0.00754078 0.39812 0.30074 -0.00771714 0.407431 0.287995 +-0.00788578 0.416335 0.274962 -0.00804653 0.424821 0.261654 -0.00819923 0.432883 0.248084 +-0.00834372 0.440512 0.234266 -0.00847987 0.4477 0.220214 -0.00860753 0.45444 0.205941 +-0.00872657 0.460725 0.191462 -0.00883689 0.466549 0.176791 -0.00893836 0.471906 0.161944 +-0.00903089 0.476791 0.146934 -0.00911438 0.481199 0.131778 -0.00918875 0.485126 0.116489 +-0.00925393 0.488567 0.101084 -0.00930984 0.491519 0.0855781 -0.00935644 0.493979 0.0699863 +-0.00939368 0.495945 0.0543245 -0.00942152 0.497415 0.0386084 -0.00943993 0.498387 0.0228536 +-0.0094489 0.49886 0.00707595 -0.00944841 0.498835 -0.00870878 -0.00943847 0.49831 -0.0244848 +-0.00941908 0.497286 -0.0402363 -0.00939026 0.495765 -0.0559476 -0.00935206 0.493747 -0.0716029 +-0.00930449 0.491236 -0.0871865 -0.00924761 0.488233 -0.102683 -0.00918148 0.484742 -0.118076 +-0.00910616 0.480765 -0.133352 -0.00902173 0.476308 -0.148494 -0.00892827 0.471374 -0.163487 +-0.00882588 0.465968 -0.178317 -0.00871466 0.460096 -0.192969 -0.00859472 0.453763 -0.207427 +-0.00846617 0.446977 -0.221678 -0.00832916 0.439743 -0.235707 -0.0180775 0.284301 0.409691 +-0.0188907 0.297091 0.400476 -0.0196851 0.309583 0.39086 -0.0204597 0.321766 0.380853 +-0.0212139 0.333627 0.370465 -0.0219468 0.345154 0.359706 -0.0226578 0.356335 0.348587 +-0.0233461 0.36716 0.33712 -0.0240111 0.377617 0.325315 -0.024652 0.387697 0.313184 +-0.0252682 0.397389 0.30074 -0.0258592 0.406683 0.287995 -0.0264243 0.41557 0.274962 +-0.026963 0.424041 0.261654 -0.0274746 0.432088 0.248084 -0.0279588 0.439703 0.234266 +-0.028415 0.446878 0.220214 -0.0288428 0.453605 0.205941 -0.0292417 0.459879 0.191462 +-0.0296114 0.465692 0.176791 -0.0299514 0.471039 0.161944 -0.0302614 0.475916 0.146934 +-0.0305412 0.480315 0.131778 -0.0307904 0.484235 0.116489 -0.0310088 0.487669 0.101084 +-0.0311962 0.490616 0.0855781 -0.0313523 0.493072 0.0699863 -0.0314771 0.495034 0.0543245 +-0.0315704 0.496501 0.0386084 -0.0316321 0.497472 0.0228536 -0.0316621 0.497944 0.00707595 +-0.0316605 0.497918 -0.00870878 -0.0316272 0.497394 -0.0244848 -0.0315622 0.496373 -0.0402363 +-0.0314657 0.494854 -0.0559476 -0.0313376 0.492841 -0.0716029 -0.0311782 0.490334 -0.0871865 +-0.0309876 0.487337 -0.102683 -0.030766 0.483852 -0.118076 -0.0305137 0.479882 -0.133352 +-0.0302307 0.475433 -0.148494 -0.0299176 0.470508 -0.163487 -0.0295745 0.465112 -0.178317 +-0.0292018 0.459251 -0.192969 -0.0287999 0.45293 -0.207427 -0.0283691 0.446156 -0.221678 +-0.02791 0.438935 -0.235707 -0.0307243 0.283214 0.409691 -0.0321065 0.295955 0.400476 +-0.0334565 0.308399 0.39086 -0.0347731 0.320535 0.380853 -0.0360549 0.332351 0.370465 +-0.0373006 0.343833 0.359706 -0.0385089 0.354972 0.348587 -0.0396788 0.365755 0.33712 +-0.0408089 0.376173 0.325315 -0.0418982 0.386214 0.313184 -0.0429456 0.395869 0.30074 +-0.04395 0.405127 0.287995 -0.0449104 0.41398 0.274962 -0.0458259 0.422419 0.261654 +-0.0466955 0.430435 0.248084 -0.0475185 0.438021 0.234266 -0.0482938 0.445168 0.220214 +-0.0490208 0.45187 0.205941 -0.0496988 0.458119 0.191462 -0.0503271 0.463911 0.176791 +-0.050905 0.469238 0.161944 -0.0514319 0.474095 0.146934 -0.0519074 0.478478 0.131778 +-0.052331 0.482382 0.116489 -0.0527022 0.485804 0.101084 -0.0530206 0.488739 0.0855781 +-0.053286 0.491186 0.0699863 -0.0534981 0.493141 0.0543245 -0.0536566 0.494602 0.0386084 +-0.0537615 0.495569 0.0228536 -0.0538126 0.496039 0.00707595 -0.0538098 0.496014 -0.00870878 +-0.0537531 0.495492 -0.0244848 -0.0536427 0.494474 -0.0402363 -0.0534786 0.492961 -0.0559476 +-0.053261 0.490956 -0.0716029 -0.0529901 0.488458 -0.0871865 -0.0526662 0.485472 -0.102683 +-0.0522896 0.482001 -0.118076 -0.0518606 0.478047 -0.133352 -0.0513798 0.473614 -0.148494 +-0.0508475 0.468708 -0.163487 -0.0502644 0.463333 -0.178317 -0.049631 0.457494 -0.192969 +-0.0489479 0.451197 -0.207427 -0.0482158 0.444449 -0.221678 -0.0474355 0.437256 -0.235707 +-0.0433101 0.281564 0.409691 -0.0452584 0.294231 0.400476 -0.0471615 0.306603 0.39086 +-0.0490174 0.318668 0.380853 -0.0508242 0.330414 0.370465 -0.0525802 0.34183 0.359706 +-0.0542836 0.352904 0.348587 -0.0559326 0.363625 0.33712 -0.0575257 0.373982 0.325315 +-0.0590612 0.383964 0.313184 -0.0605377 0.393563 0.30074 -0.0619535 0.402767 0.287995 +-0.0633074 0.411569 0.274962 -0.0645979 0.419958 0.261654 -0.0658237 0.427928 0.248084 +-0.0669837 0.435469 0.234266 -0.0680767 0.442575 0.220214 -0.0691016 0.449238 0.205941 +-0.0700573 0.455451 0.191462 -0.0709429 0.461208 0.176791 -0.0717575 0.466504 0.161944 +-0.0725003 0.471333 0.146934 -0.0731706 0.475691 0.131778 -0.0737677 0.479572 0.116489 +-0.0742909 0.482974 0.101084 -0.0747398 0.485892 0.0855781 -0.0751139 0.488324 0.0699863 +-0.0754129 0.490268 0.0543245 -0.0756364 0.491721 0.0386084 -0.0757842 0.492682 0.0228536 +-0.0758561 0.49315 0.00707595 -0.0758522 0.493124 -0.00870878 -0.0757724 0.492605 -0.0244848 +-0.0756167 0.491593 -0.0402363 -0.0753854 0.49009 -0.0559476 -0.0750787 0.488096 -0.0716029 +-0.0746968 0.485613 -0.0871865 -0.0742402 0.482644 -0.102683 -0.0737093 0.479193 -0.118076 +-0.0731046 0.475262 -0.133352 -0.0724268 0.470855 -0.148494 -0.0716766 0.465978 -0.163487 +-0.0708546 0.460634 -0.178317 -0.0699616 0.454829 -0.192969 -0.0689987 0.448569 -0.207427 +-0.0679668 0.44186 -0.221678 -0.0668668 0.434709 -0.235707 -0.0558099 0.279355 0.409691 +-0.0583206 0.291922 0.400476 -0.0607729 0.304197 0.39086 -0.0631644 0.316168 0.380853 +-0.0654927 0.327822 0.370465 -0.0677555 0.339149 0.359706 -0.0699505 0.350136 0.348587 +-0.0720755 0.360772 0.33712 -0.0741283 0.371048 0.325315 -0.076107 0.380952 0.313184 +-0.0780096 0.390475 0.30074 -0.079834 0.399608 0.287995 -0.0815786 0.40834 0.274962 +-0.0832416 0.416664 0.261654 -0.0848213 0.424571 0.248084 -0.086316 0.432053 0.234266 +-0.0877245 0.439103 0.220214 -0.0890451 0.445713 0.205941 -0.0902766 0.451878 0.191462 +-0.0914178 0.45759 0.176791 -0.0924676 0.462844 0.161944 -0.0934248 0.467636 0.146934 +-0.0942885 0.471959 0.131778 -0.0950579 0.47581 0.116489 -0.0957321 0.479185 0.101084 +-0.0963106 0.482081 0.0855781 -0.0967927 0.484494 0.0699863 -0.0971779 0.486422 0.0543245 +-0.0974659 0.487864 0.0386084 -0.0976564 0.488817 0.0228536 -0.0977491 0.489281 0.00707595 +-0.0977441 0.489256 -0.00870878 -0.0976412 0.488741 -0.0244848 -0.0974406 0.487737 -0.0402363 +-0.0971426 0.486245 -0.0559476 -0.0967473 0.484266 -0.0716029 -0.0962552 0.481803 -0.0871865 +-0.0956668 0.478858 -0.102683 -0.0949827 0.475434 -0.118076 -0.0942035 0.471534 -0.133352 +-0.0933301 0.467162 -0.148494 -0.0923633 0.462322 -0.163487 -0.091304 0.45702 -0.178317 +-0.0901534 0.451261 -0.192969 -0.0889126 0.44505 -0.207427 -0.0875828 0.438394 -0.221678 +-0.0861654 0.431299 -0.235707 -0.0681988 0.276592 0.409691 -0.0712669 0.289035 0.400476 +-0.0742636 0.301188 0.39086 -0.077186 0.31304 0.380853 -0.0800311 0.324579 0.370465 +-0.0827962 0.335794 0.359706 -0.0854784 0.346672 0.348587 -0.0880752 0.357203 0.33712 +-0.0905837 0.367377 0.325315 -0.0930016 0.377184 0.313184 -0.0953265 0.386612 0.30074 +-0.097556 0.395654 0.287995 -0.0996879 0.404301 0.274962 -0.10172 0.412542 0.261654 +-0.10365 0.420371 0.248084 -0.105477 0.427779 0.234266 -0.107198 0.434759 0.220214 +-0.108812 0.441304 0.205941 -0.110317 0.447408 0.191462 -0.111711 0.453063 0.176791 +-0.112994 0.458266 0.161944 -0.114164 0.46301 0.146934 -0.115219 0.46729 0.131778 +-0.116159 0.471103 0.116489 -0.116983 0.474445 0.101084 -0.11769 0.477312 0.0855781 +-0.118279 0.479701 0.0699863 -0.11875 0.48161 0.0543245 -0.119102 0.483037 0.0386084 +-0.119335 0.483981 0.0228536 -0.119448 0.484441 0.00707595 -0.119442 0.484416 -0.00870878 +-0.119316 0.483906 -0.0244848 -0.119071 0.482912 -0.0402363 -0.118707 0.481435 -0.0559476 +-0.118224 0.479476 -0.0716029 -0.117622 0.477037 -0.0871865 -0.116903 0.474121 -0.102683 +-0.116067 0.470731 -0.118076 -0.115115 0.466869 -0.133352 -0.114048 0.46254 -0.148494 +-0.112867 0.457749 -0.163487 -0.111572 0.452499 -0.178317 -0.110166 0.446797 -0.192969 +-0.10865 0.440647 -0.207427 -0.107025 0.434057 -0.221678 -0.105293 0.427032 -0.235707 +-0.0804524 0.273279 0.409691 -0.0840717 0.285573 0.400476 -0.0876068 0.297581 0.39086 +-0.0910543 0.309291 0.380853 -0.0944107 0.320692 0.370465 -0.0976726 0.331772 0.359706 +-0.100837 0.34252 0.348587 -0.1039 0.352925 0.33712 -0.106859 0.362977 0.325315 +-0.109712 0.372666 0.313184 -0.112454 0.381982 0.30074 -0.115084 0.390916 0.287995 +-0.117599 0.399458 0.274962 -0.119996 0.407601 0.261654 -0.122274 0.415336 0.248084 +-0.124428 0.422656 0.234266 -0.126459 0.429552 0.220214 -0.128363 0.436019 0.205941 +-0.130138 0.442049 0.191462 -0.131783 0.447637 0.176791 -0.133296 0.452777 0.161944 +-0.134676 0.457464 0.146934 -0.135921 0.461694 0.131778 -0.13703 0.465461 0.116489 +-0.138002 0.468763 0.101084 -0.138836 0.471595 0.0855781 -0.139531 0.473956 0.0699863 +-0.140086 0.475842 0.0543245 -0.140501 0.477252 0.0386084 -0.140776 0.478185 0.0228536 +-0.14091 0.478639 0.00707595 -0.140902 0.478614 -0.00870878 -0.140754 0.478111 -0.0244848 +-0.140465 0.477129 -0.0402363 -0.140035 0.475669 -0.0559476 -0.139466 0.473733 -0.0716029 +-0.138756 0.471324 -0.0871865 -0.137908 0.468443 -0.102683 -0.136922 0.465093 -0.118076 +-0.135799 0.461278 -0.133352 -0.134539 0.457001 -0.148494 -0.133146 0.452267 -0.163487 +-0.131619 0.44708 -0.178317 -0.12996 0.441446 -0.192969 -0.128171 0.43537 -0.207427 +-0.126255 0.428859 -0.221678 -0.124211 0.421918 -0.235707 -0.0925463 0.269424 0.409691 +-0.0967096 0.281544 0.400476 -0.100776 0.293383 0.39086 -0.104742 0.304928 0.380853 +-0.108603 0.316168 0.370465 -0.112355 0.327092 0.359706 -0.115995 0.337688 0.348587 +-0.119519 0.347946 0.33712 -0.122923 0.357857 0.325315 -0.126204 0.367409 0.313184 +-0.129359 0.376593 0.30074 -0.132384 0.385401 0.287995 -0.135277 0.393823 0.274962 +-0.138035 0.401851 0.261654 -0.140654 0.409477 0.248084 -0.143133 0.416693 0.234266 +-0.145468 0.423492 0.220214 -0.147658 0.429868 0.205941 -0.149701 0.435813 0.191462 +-0.151593 0.441322 0.176791 -0.153334 0.44639 0.161944 -0.154921 0.451011 0.146934 +-0.156353 0.455181 0.131778 -0.157629 0.458895 0.116489 -0.158747 0.46215 0.101084 +-0.159706 0.464942 0.0855781 -0.160506 0.46727 0.0699863 -0.161145 0.469129 0.0543245 +-0.161622 0.47052 0.0386084 -0.161938 0.471439 0.0228536 -0.162092 0.471887 0.00707595 +-0.162083 0.471862 -0.00870878 -0.161913 0.471366 -0.0244848 -0.16158 0.470398 -0.0402363 +-0.161086 0.468959 -0.0559476 -0.16043 0.46705 -0.0716029 -0.159614 0.464675 -0.0871865 +-0.158639 0.461834 -0.102683 -0.157504 0.458532 -0.118076 -0.156212 0.45477 -0.133352 +-0.154764 0.450554 -0.148494 -0.153161 0.445886 -0.163487 -0.151404 0.440773 -0.178317 +-0.149496 0.435218 -0.192969 -0.147439 0.429228 -0.207427 -0.145234 0.422809 -0.221678 +-0.142883 0.415966 -0.235707 -0.104456 0.265034 0.409691 -0.109156 0.276957 0.400476 +-0.113745 0.288602 0.39086 -0.118222 0.299959 0.380853 -0.122579 0.311016 0.370465 +-0.126814 0.321762 0.359706 -0.130923 0.332186 0.348587 -0.1349 0.342277 0.33712 +-0.138742 0.352026 0.325315 -0.142446 0.361422 0.313184 -0.146006 0.370457 0.30074 +-0.149421 0.379121 0.287995 -0.152686 0.387406 0.274962 -0.155799 0.395303 0.261654 +-0.158755 0.402805 0.248084 -0.161553 0.409904 0.234266 -0.164189 0.416592 0.220214 +-0.166661 0.422863 0.205941 -0.168966 0.428712 0.191462 -0.171102 0.434131 0.176791 +-0.173067 0.439116 0.161944 -0.174858 0.443662 0.146934 -0.176475 0.447764 0.131778 +-0.177915 0.451417 0.116489 -0.179177 0.454619 0.101084 -0.180259 0.457366 0.0855781 +-0.181162 0.459656 0.0699863 -0.181883 0.461485 0.0543245 -0.182422 0.462853 0.0386084 +-0.182778 0.463757 0.0228536 -0.182952 0.464198 0.00707595 -0.182942 0.464174 -0.00870878 +-0.18275 0.463685 -0.0244848 -0.182375 0.462733 -0.0402363 -0.181817 0.461317 -0.0559476 +-0.181077 0.45944 -0.0716029 -0.180156 0.457103 -0.0871865 -0.179055 0.454309 -0.102683 +-0.177774 0.45106 -0.118076 -0.176316 0.44736 -0.133352 -0.174681 0.443212 -0.148494 +-0.172871 0.438621 -0.163487 -0.170889 0.433591 -0.178317 -0.168735 0.428127 -0.192969 +-0.166413 0.422234 -0.207427 -0.163924 0.415919 -0.221678 -0.161271 0.409188 -0.235707 +-0.116159 0.260117 0.409691 -0.121385 0.271819 0.400476 -0.126489 0.283249 0.39086 +-0.131466 0.294395 0.380853 -0.136312 0.305247 0.370465 -0.141022 0.315793 0.359706 +-0.145591 0.326024 0.348587 -0.150013 0.335928 0.33712 -0.154286 0.345496 0.325315 +-0.158404 0.354718 0.313184 -0.162364 0.363585 0.30074 -0.166162 0.372089 0.287995 +-0.169793 0.38022 0.274962 -0.173254 0.387971 0.261654 -0.176542 0.395333 0.248084 +-0.179653 0.4023 0.234266 -0.182584 0.408864 0.220214 -0.185333 0.415019 0.205941 +-0.187896 0.420759 0.191462 -0.190271 0.426078 0.176791 -0.192456 0.430971 0.161944 +-0.194448 0.435432 0.146934 -0.196246 0.439458 0.131778 -0.197847 0.443044 0.116489 +-0.199251 0.446186 0.101084 -0.200455 0.448882 0.0855781 -0.201458 0.451129 0.0699863 +-0.20226 0.452925 0.0543245 -0.202859 0.454267 0.0386084 -0.203256 0.455155 0.0228536 +-0.203449 0.455587 0.00707595 -0.203438 0.455563 -0.00870878 -0.203224 0.455084 -0.0244848 +-0.202807 0.454149 -0.0402363 -0.202186 0.45276 -0.0559476 -0.201364 0.450918 -0.0716029 +-0.200339 0.448624 -0.0871865 -0.199115 0.445882 -0.102683 -0.197691 0.442693 -0.118076 +-0.196069 0.439062 -0.133352 -0.194251 0.434991 -0.148494 -0.192239 0.430485 -0.163487 +-0.190034 0.425548 -0.178317 -0.18764 0.420185 -0.192969 -0.185057 0.414402 -0.207427 +-0.182289 0.408204 -0.221678 -0.179339 0.401598 -0.235707 -0.127631 0.254685 0.409691 +-0.133373 0.266142 0.400476 -0.138981 0.277333 0.39086 -0.14445 0.288247 0.380853 +-0.149775 0.298872 0.370465 -0.15495 0.309198 0.359706 -0.159969 0.319214 0.348587 +-0.164829 0.328912 0.33712 -0.169524 0.33828 0.325315 -0.174049 0.347309 0.313184 +-0.1784 0.355991 0.30074 -0.182572 0.364317 0.287995 -0.186562 0.372279 0.274962 +-0.190365 0.379867 0.261654 -0.193977 0.387076 0.248084 -0.197396 0.393898 0.234266 +-0.200617 0.400325 0.220214 -0.203637 0.406351 0.205941 -0.206453 0.411972 0.191462 +-0.209063 0.417179 0.176791 -0.211464 0.42197 0.161944 -0.213653 0.426338 0.146934 +-0.215628 0.430279 0.131778 -0.217387 0.43379 0.116489 -0.218929 0.436867 0.101084 +-0.220252 0.439507 0.0855781 -0.221355 0.441707 0.0699863 -0.222236 0.443465 0.0543245 +-0.222894 0.444779 0.0386084 -0.22333 0.445648 0.0228536 -0.223542 0.446072 0.00707595 +-0.22353 0.446049 -0.00870878 -0.223295 0.445579 -0.0244848 -0.222836 0.444664 -0.0402363 +-0.222155 0.443304 -0.0559476 -0.221251 0.4415 -0.0716029 -0.220125 0.439254 -0.0871865 +-0.21878 0.436569 -0.102683 -0.217215 0.433447 -0.118076 -0.215433 0.429891 -0.133352 +-0.213436 0.425906 -0.148494 -0.211225 0.421494 -0.163487 -0.208803 0.41666 -0.178317 +-0.206171 0.411409 -0.192969 -0.203334 0.405747 -0.207427 -0.200293 0.399678 -0.221678 +-0.197051 0.39321 -0.235707 -0.13885 0.248746 0.409691 -0.145096 0.259936 0.400476 +-0.151198 0.270867 0.39086 -0.157147 0.281526 0.380853 -0.16294 0.291903 0.370465 +-0.16857 0.301988 0.359706 -0.174031 0.311771 0.348587 -0.179317 0.321243 0.33712 +-0.184425 0.330392 0.325315 -0.189347 0.339211 0.313184 -0.194081 0.347691 0.30074 +-0.19862 0.355823 0.287995 -0.20296 0.363598 0.274962 -0.207098 0.37101 0.261654 +-0.211028 0.378051 0.248084 -0.214747 0.384713 0.234266 -0.218251 0.390991 0.220214 +-0.221536 0.396877 0.205941 -0.2246 0.402366 0.191462 -0.227439 0.407452 0.176791 +-0.230051 0.412131 0.161944 -0.232432 0.416397 0.146934 -0.234581 0.420247 0.131778 +-0.236495 0.423676 0.116489 -0.238173 0.426681 0.101084 -0.239612 0.429259 0.0855781 +-0.240811 0.431408 0.0699863 -0.24177 0.433125 0.0543245 -0.242486 0.434408 0.0386084 +-0.24296 0.435257 0.0228536 -0.243191 0.435671 0.00707595 -0.243178 0.435648 -0.00870878 +-0.242923 0.43519 -0.0244848 -0.242424 0.434296 -0.0402363 -0.241682 0.432967 -0.0559476 +-0.240699 0.431206 -0.0716029 -0.239474 0.429012 -0.0871865 -0.23801 0.42639 -0.102683 +-0.236308 0.423341 -0.118076 -0.23437 0.419868 -0.133352 -0.232197 0.415975 -0.148494 +-0.229791 0.411666 -0.163487 -0.227156 0.406945 -0.178317 -0.224294 0.401816 -0.192969 +-0.221207 0.396286 -0.207427 -0.217898 0.390359 -0.221678 -0.214372 0.384042 -0.235707 +-0.149793 0.242314 0.409691 -0.156532 0.253215 0.400476 -0.163114 0.263862 0.39086 +-0.169532 0.274246 0.380853 -0.175782 0.284355 0.370465 -0.181855 0.294179 0.359706 +-0.187746 0.303709 0.348587 -0.19345 0.312936 0.33712 -0.198959 0.321849 0.325315 +-0.20427 0.33044 0.313184 -0.209377 0.3387 0.30074 -0.214273 0.346622 0.287995 +-0.218956 0.354196 0.274962 -0.223419 0.361416 0.261654 -0.227659 0.368275 0.248084 +-0.231671 0.374765 0.234266 -0.235451 0.38088 0.220214 -0.238996 0.386614 0.205941 +-0.242301 0.391961 0.191462 -0.245364 0.396916 0.176791 -0.248182 0.401474 0.161944 +-0.250751 0.40563 0.146934 -0.253069 0.40938 0.131778 -0.255134 0.41272 0.116489 +-0.256944 0.415648 0.101084 -0.258496 0.418159 0.0855781 -0.25979 0.420252 0.0699863 +-0.260824 0.421925 0.0543245 -0.261597 0.423175 0.0386084 -0.262108 0.424002 0.0228536 +-0.262357 0.424405 0.00707595 -0.262344 0.424383 -0.00870878 -0.262068 0.423936 -0.0244848 +-0.261529 0.423066 -0.0402363 -0.260729 0.421771 -0.0559476 -0.259668 0.420055 -0.0716029 +-0.258348 0.417919 -0.0871865 -0.256768 0.415364 -0.102683 -0.254932 0.412394 -0.118076 +-0.252841 0.409011 -0.133352 -0.250497 0.405218 -0.148494 -0.247902 0.401021 -0.163487 +-0.245059 0.396422 -0.178317 -0.241971 0.391426 -0.192969 -0.23864 0.386039 -0.207427 +-0.235071 0.380265 -0.221678 -0.231267 0.374111 -0.235707 -0.160439 0.235401 0.409691 +-0.167656 0.245991 0.400476 -0.174706 0.256334 0.39086 -0.181581 0.266421 0.380853 +-0.188274 0.276242 0.370465 -0.194779 0.285786 0.359706 -0.201089 0.295044 0.348587 +-0.207198 0.304007 0.33712 -0.213099 0.312666 0.325315 -0.218787 0.321012 0.313184 +-0.224257 0.329037 0.30074 -0.229502 0.336732 0.287995 -0.234517 0.344091 0.274962 +-0.239297 0.351105 0.261654 -0.243839 0.357768 0.248084 -0.248136 0.364073 0.234266 +-0.252185 0.370013 0.220214 -0.255981 0.375584 0.205941 -0.259521 0.380778 0.191462 +-0.262802 0.385592 0.176791 -0.26582 0.390019 0.161944 -0.268571 0.394057 0.146934 +-0.271054 0.3977 0.131778 -0.273266 0.400945 0.116489 -0.275204 0.403789 0.101084 +-0.276867 0.406229 0.0855781 -0.278253 0.408262 0.0699863 -0.279361 0.409887 0.0543245 +-0.280189 0.411102 0.0386084 -0.280736 0.411905 0.0228536 -0.281003 0.412296 0.00707595 +-0.280988 0.412275 -0.00870878 -0.280693 0.411841 -0.0244848 -0.280116 0.410995 -0.0402363 +-0.279259 0.409738 -0.0559476 -0.278123 0.408071 -0.0716029 -0.276708 0.405995 -0.0871865 +-0.275017 0.403513 -0.102683 -0.27305 0.400628 -0.118076 -0.27081 0.397341 -0.133352 +-0.268299 0.393657 -0.148494 -0.26552 0.389579 -0.163487 -0.262475 0.385112 -0.178317 +-0.259167 0.380258 -0.192969 -0.2556 0.375025 -0.207427 -0.251777 0.369416 -0.221678 +-0.247703 0.363437 -0.235707 -0.170766 0.22802 0.409691 -0.178448 0.238278 0.400476 +-0.185951 0.248297 0.39086 -0.193269 0.258068 0.380853 -0.200393 0.267581 0.370465 +-0.207317 0.276826 0.359706 -0.214033 0.285794 0.348587 -0.220535 0.294476 0.33712 +-0.226816 0.302863 0.325315 -0.23287 0.310947 0.313184 -0.238692 0.31872 0.30074 +-0.244274 0.326174 0.287995 -0.249612 0.333302 0.274962 -0.254701 0.340097 0.261654 +-0.259534 0.34655 0.248084 -0.264108 0.352658 0.234266 -0.268417 0.358412 0.220214 +-0.272458 0.363808 0.205941 -0.276226 0.368839 0.191462 -0.279718 0.373502 0.176791 +-0.28293 0.377791 0.161944 -0.285859 0.381702 0.146934 -0.288502 0.38523 0.131778 +-0.290856 0.388374 0.116489 -0.292919 0.391129 0.101084 -0.294689 0.393492 0.0855781 +-0.296164 0.395462 0.0699863 -0.297343 0.397036 0.0543245 -0.298224 0.398212 0.0386084 +-0.298807 0.39899 0.0228536 -0.29909 0.399369 0.00707595 -0.299075 0.399349 -0.00870878 +-0.29876 0.398928 -0.0244848 -0.298146 0.398109 -0.0402363 -0.297234 0.396891 -0.0559476 +-0.296025 0.395276 -0.0716029 -0.294519 0.393266 -0.0871865 -0.292719 0.390862 -0.102683 +-0.290626 0.388067 -0.118076 -0.288242 0.384883 -0.133352 -0.285569 0.381315 -0.148494 +-0.282611 0.377365 -0.163487 -0.27937 0.373037 -0.178317 -0.275849 0.368336 -0.192969 +-0.272053 0.363266 -0.207427 -0.267984 0.357833 -0.221678 -0.263647 0.352042 -0.235707 +-0.180754 0.220187 0.409691 -0.188885 0.230092 0.400476 -0.196828 0.239767 0.39086 +-0.204573 0.249202 0.380853 -0.212114 0.258388 0.370465 -0.219443 0.267316 0.359706 +-0.226551 0.275975 0.348587 -0.233434 0.284359 0.33712 -0.240082 0.292458 0.325315 +-0.246491 0.300265 0.313184 -0.252653 0.307771 0.30074 -0.258562 0.314969 0.287995 +-0.264212 0.321852 0.274962 -0.269598 0.328413 0.261654 -0.274714 0.334645 0.248084 +-0.279555 0.340542 0.234266 -0.284117 0.346099 0.220214 -0.288394 0.351309 0.205941 +-0.292383 0.356168 0.191462 -0.296079 0.360671 0.176791 -0.299479 0.364812 0.161944 +-0.302579 0.368589 0.146934 -0.305376 0.371996 0.131778 -0.307868 0.375032 0.116489 +-0.310052 0.377692 0.101084 -0.311925 0.379974 0.0855781 -0.313486 0.381876 0.0699863 +-0.314734 0.383396 0.0543245 -0.315667 0.384532 0.0386084 -0.316284 0.385283 0.0228536 +-0.316584 0.385649 0.00707595 -0.316568 0.385629 -0.00870878 -0.316235 0.385224 -0.0244848 +-0.315585 0.384432 -0.0402363 -0.31462 0.383256 -0.0559476 -0.313339 0.381697 -0.0716029 +-0.311746 0.379755 -0.0871865 -0.30984 0.377434 -0.102683 -0.307624 0.374735 -0.118076 +-0.305101 0.371661 -0.133352 -0.302272 0.368215 -0.148494 -0.299141 0.364401 -0.163487 +-0.29571 0.360221 -0.178317 -0.291984 0.355682 -0.192969 -0.287965 0.350787 -0.207427 +-0.283658 0.34554 -0.221678 -0.279067 0.339948 -0.235707 -0.190383 0.211916 0.409691 +-0.198948 0.221449 0.400476 -0.207313 0.230761 0.39086 -0.215471 0.239842 0.380853 +-0.223414 0.248683 0.370465 -0.231133 0.257275 0.359706 -0.23862 0.265609 0.348587 +-0.245869 0.273678 0.33712 -0.252872 0.281473 0.325315 -0.259622 0.288986 0.313184 +-0.266112 0.29621 0.30074 -0.272336 0.303138 0.287995 -0.278287 0.309763 0.274962 +-0.28396 0.316077 0.261654 -0.289349 0.322075 0.248084 -0.294448 0.327751 0.234266 +-0.299252 0.333099 0.220214 -0.303757 0.338114 0.205941 -0.307959 0.34279 0.191462 +-0.311852 0.347123 0.176791 -0.315432 0.351109 0.161944 -0.318698 0.354744 0.146934 +-0.321644 0.358023 0.131778 -0.324269 0.360945 0.116489 -0.326569 0.363505 0.101084 +-0.328542 0.365701 0.0855781 -0.330187 0.367532 0.0699863 -0.331501 0.368995 0.0543245 +-0.332483 0.370088 0.0386084 -0.333133 0.370812 0.0228536 -0.333449 0.371164 0.00707595 +-0.333432 0.371145 -0.00870878 -0.333081 0.370754 -0.0244848 -0.332397 0.369992 -0.0402363 +-0.33138 0.368861 -0.0559476 -0.330032 0.36736 -0.0716029 -0.328353 0.365491 -0.0871865 +-0.326346 0.363257 -0.102683 -0.324012 0.360659 -0.118076 -0.321354 0.357701 -0.133352 +-0.318375 0.354384 -0.148494 -0.315077 0.350713 -0.163487 -0.311463 0.346691 -0.178317 +-0.307538 0.342322 -0.192969 -0.303305 0.33761 -0.207427 -0.298769 0.332561 -0.221678 +-0.293934 0.327179 -0.235707 -0.199634 0.203225 0.409691 -0.208615 0.212367 0.400476 +-0.217387 0.221297 0.39086 -0.225942 0.230005 0.380853 -0.23427 0.238483 0.370465 +-0.242364 0.246723 0.359706 -0.250216 0.254716 0.348587 -0.257817 0.262454 0.33712 +-0.26516 0.269929 0.325315 -0.272238 0.277134 0.313184 -0.279043 0.284062 0.30074 +-0.285569 0.290706 0.287995 -0.29181 0.297058 0.274962 -0.297758 0.303114 0.261654 +-0.303409 0.308866 0.248084 -0.308756 0.314309 0.234266 -0.313794 0.319438 0.220214 +-0.318518 0.324246 0.205941 -0.322923 0.328731 0.191462 -0.327005 0.332887 0.176791 +-0.33076 0.336709 0.161944 -0.334184 0.340195 0.146934 -0.337274 0.34334 0.131778 +-0.340026 0.346141 0.116489 -0.342438 0.348596 0.101084 -0.344507 0.350703 0.0855781 +-0.346231 0.352458 0.0699863 -0.347609 0.353861 0.0543245 -0.348639 0.35491 0.0386084 +-0.349321 0.355603 0.0228536 -0.349652 0.355941 0.00707595 -0.349634 0.355923 -0.00870878 +-0.349266 0.355548 -0.0244848 -0.348549 0.354818 -0.0402363 -0.347483 0.353732 -0.0559476 +-0.346069 0.352293 -0.0716029 -0.344309 0.350501 -0.0871865 -0.342204 0.348359 -0.102683 +-0.339757 0.345867 -0.118076 -0.33697 0.34303 -0.133352 -0.333845 0.33985 -0.148494 +-0.330387 0.336329 -0.163487 -0.326598 0.332472 -0.178317 -0.322482 0.328282 -0.192969 +-0.318044 0.323764 -0.207427 -0.313287 0.318922 -0.221678 -0.308217 0.31376 -0.235707 +-0.208489 0.19413 0.409691 -0.217868 0.202863 0.400476 -0.227029 0.211393 0.39086 +-0.235963 0.219712 0.380853 -0.244661 0.227811 0.370465 -0.253114 0.235682 0.359706 +-0.261314 0.243317 0.348587 -0.269252 0.250708 0.33712 -0.276921 0.257849 0.325315 +-0.284313 0.264732 0.313184 -0.29142 0.271349 0.30074 -0.298236 0.277696 0.287995 +-0.304753 0.283764 0.274962 -0.310966 0.289549 0.261654 -0.316867 0.295043 0.248084 +-0.322451 0.300243 0.234266 -0.327712 0.305142 0.220214 -0.332646 0.309736 0.205941 +-0.337246 0.314019 0.191462 -0.34151 0.317989 0.176791 -0.345431 0.32164 0.161944 +-0.349007 0.32497 0.146934 -0.352234 0.327974 0.131778 -0.355108 0.330651 0.116489 +-0.357627 0.332996 0.101084 -0.359787 0.335008 0.0855781 -0.361588 0.336685 0.0699863 +-0.363028 0.338025 0.0543245 -0.364103 0.339027 0.0386084 -0.364815 0.339689 0.0228536 +-0.365161 0.340012 0.00707595 -0.365143 0.339994 -0.00870878 -0.364758 0.339636 -0.0244848 +-0.364009 0.338939 -0.0402363 -0.362895 0.337902 -0.0559476 -0.361419 0.336527 -0.0716029 +-0.359581 0.334815 -0.0871865 -0.357383 0.332769 -0.102683 -0.354827 0.330389 -0.118076 +-0.351916 0.327679 -0.133352 -0.348653 0.324641 -0.148494 -0.345041 0.321278 -0.163487 +-0.341084 0.317593 -0.178317 -0.336786 0.313591 -0.192969 -0.332151 0.309275 -0.207427 +-0.327183 0.304649 -0.221678 -0.321888 0.299719 -0.235707 -0.21693 0.18465 0.409691 +-0.226689 0.192956 0.400476 -0.236221 0.20107 0.39086 -0.245517 0.208982 0.380853 +-0.254567 0.216686 0.370465 -0.263362 0.224172 0.359706 -0.271894 0.231434 0.348587 +-0.280153 0.238465 0.33712 -0.288133 0.245257 0.325315 -0.295824 0.251804 0.313184 +-0.303219 0.258098 0.30074 -0.31031 0.264135 0.287995 -0.317092 0.269907 0.274962 +-0.323555 0.275409 0.261654 -0.329695 0.280635 0.248084 -0.335506 0.285581 0.234266 +-0.34098 0.29024 0.220214 -0.346113 0.29461 0.205941 -0.3509 0.298684 0.191462 +-0.355336 0.30246 0.176791 -0.359416 0.305933 0.161944 -0.363137 0.3091 0.146934 +-0.366494 0.311958 0.131778 -0.369485 0.314503 0.116489 -0.372105 0.316734 0.101084 +-0.374354 0.318648 0.0855781 -0.376228 0.320243 0.0699863 -0.377725 0.321518 0.0543245 +-0.378845 0.32247 0.0386084 -0.379585 0.323101 0.0228536 -0.379945 0.323408 0.00707595 +-0.379926 0.323391 -0.00870878 -0.379526 0.32305 -0.0244848 -0.378746 0.322387 -0.0402363 +-0.377588 0.321401 -0.0559476 -0.376051 0.320093 -0.0716029 -0.374139 0.318465 -0.0871865 +-0.371852 0.316518 -0.102683 -0.369192 0.314255 -0.118076 -0.366164 0.311677 -0.133352 +-0.362769 0.308787 -0.148494 -0.359011 0.305588 -0.163487 -0.354894 0.302084 -0.178317 +-0.350421 0.298277 -0.192969 -0.345598 0.294171 -0.207427 -0.340429 0.289772 -0.221678 +-0.33492 0.285082 -0.235707 -0.22494 0.174803 0.409691 -0.235059 0.182666 0.400476 +-0.244943 0.190347 0.39086 -0.254582 0.197838 0.380853 -0.263967 0.20513 0.370465 +-0.273087 0.212218 0.359706 -0.281933 0.219093 0.348587 -0.290498 0.225748 0.33712 +-0.298772 0.232178 0.325315 -0.306747 0.238376 0.313184 -0.314415 0.244335 0.30074 +-0.321769 0.250049 0.287995 -0.3288 0.255513 0.274962 -0.335503 0.260722 0.261654 +-0.34187 0.26567 0.248084 -0.347894 0.270351 0.234266 -0.353571 0.274763 0.220214 +-0.358894 0.278899 0.205941 -0.363857 0.282756 0.191462 -0.368457 0.286331 0.176791 +-0.372688 0.289619 0.161944 -0.376546 0.292617 0.146934 -0.380027 0.295322 0.131778 +-0.383128 0.297732 0.116489 -0.385846 0.299844 0.101084 -0.388177 0.301655 0.0855781 +-0.39012 0.303165 0.0699863 -0.391673 0.304372 0.0543245 -0.392834 0.305274 0.0386084 +-0.393601 0.305871 0.0228536 -0.393975 0.306161 0.00707595 -0.393955 0.306145 -0.00870878 +-0.39354 0.305823 -0.0244848 -0.392732 0.305195 -0.0402363 -0.39153 0.304261 -0.0559476 +-0.389937 0.303023 -0.0716029 -0.387954 0.301482 -0.0871865 -0.385582 0.299639 -0.102683 +-0.382825 0.297496 -0.118076 -0.379685 0.295056 -0.133352 -0.376164 0.29232 -0.148494 +-0.372267 0.289292 -0.163487 -0.367998 0.285974 -0.178317 -0.363361 0.28237 -0.192969 +-0.35836 0.278484 -0.207427 -0.353 0.274319 -0.221678 -0.347287 0.269879 -0.235707 +-0.232504 0.164609 0.409691 -0.242963 0.172014 0.400476 -0.25318 0.179247 0.39086 +-0.263143 0.186301 0.380853 -0.272842 0.193168 0.370465 -0.282269 0.199842 0.359706 +-0.291413 0.206316 0.348587 -0.300266 0.212584 0.33712 -0.308818 0.218638 0.325315 +-0.317061 0.224474 0.313184 -0.324987 0.230086 0.30074 -0.332588 0.235467 0.287995 +-0.339856 0.240613 0.274962 -0.346784 0.245518 0.261654 -0.353365 0.250177 0.248084 +-0.359592 0.254586 0.234266 -0.36546 0.25874 0.220214 -0.370961 0.262635 0.205941 +-0.376092 0.266267 0.191462 -0.380846 0.269633 0.176791 -0.385219 0.272729 0.161944 +-0.389207 0.275552 0.146934 -0.392805 0.2781 0.131778 -0.396011 0.280369 0.116489 +-0.39882 0.282358 0.101084 -0.401229 0.284064 0.0855781 -0.403238 0.285486 0.0699863 +-0.404843 0.286622 0.0543245 -0.406042 0.287472 0.0386084 -0.406836 0.288033 0.0228536 +-0.407222 0.288307 0.00707595 -0.407201 0.288292 -0.00870878 -0.406773 0.287989 -0.0244848 +-0.405937 0.287397 -0.0402363 -0.404695 0.286518 -0.0559476 -0.403049 0.285352 -0.0716029 +-0.400999 0.283901 -0.0871865 -0.398547 0.282165 -0.102683 -0.395697 0.280147 -0.118076 +-0.392451 0.277849 -0.133352 -0.388813 0.275273 -0.148494 -0.384785 0.272421 -0.163487 +-0.380372 0.269297 -0.178317 -0.375579 0.265904 -0.192969 -0.370409 0.262244 -0.207427 +-0.36487 0.258322 -0.221678 -0.358965 0.254141 -0.235707 -0.239606 0.154088 0.409691 +-0.250385 0.16102 0.400476 -0.260913 0.167791 0.39086 -0.271181 0.174394 0.380853 +-0.281177 0.180822 0.370465 -0.290891 0.187069 0.359706 -0.300315 0.19313 0.348587 +-0.309438 0.198997 0.33712 -0.318251 0.204664 0.325315 -0.326746 0.210127 0.313184 +-0.334914 0.21538 0.30074 -0.342747 0.220418 0.287995 -0.350237 0.225234 0.274962 +-0.357377 0.229826 0.261654 -0.364159 0.234187 0.248084 -0.370576 0.238314 0.234266 +-0.376623 0.242203 0.220214 -0.382293 0.245849 0.205941 -0.38758 0.249249 0.191462 +-0.39248 0.2524 0.176791 -0.396986 0.255298 0.161944 -0.401096 0.257941 0.146934 +-0.404804 0.260326 0.131778 -0.408107 0.26245 0.116489 -0.411002 0.264311 0.101084 +-0.413485 0.265908 0.0855781 -0.415555 0.267239 0.0699863 -0.417209 0.268303 0.0543245 +-0.418445 0.269098 0.0386084 -0.419263 0.269624 0.0228536 -0.419661 0.26988 0.00707595 +-0.41964 0.269866 -0.00870878 -0.419198 0.269582 -0.0244848 -0.418337 0.269028 -0.0402363 +-0.417057 0.268206 -0.0559476 -0.41536 0.267114 -0.0716029 -0.413248 0.265756 -0.0871865 +-0.410721 0.264131 -0.102683 -0.407784 0.262242 -0.118076 -0.404439 0.260091 -0.133352 +-0.400689 0.257679 -0.148494 -0.396538 0.25501 -0.163487 -0.391991 0.252086 -0.178317 +-0.387051 0.248909 -0.192969 -0.381724 0.245483 -0.207427 -0.376015 0.241812 -0.221678 +-0.369929 0.237898 -0.235707 -0.246232 0.143261 0.409691 -0.257309 0.149706 0.400476 +-0.268129 0.156001 0.39086 -0.27868 0.16214 0.380853 -0.288952 0.168117 0.370465 +-0.298936 0.173925 0.359706 -0.30862 0.17956 0.348587 -0.317995 0.185015 0.33712 +-0.327053 0.190284 0.325315 -0.335782 0.195363 0.313184 -0.344176 0.200247 0.30074 +-0.352226 0.20493 0.287995 -0.359923 0.209409 0.274962 -0.36726 0.213677 0.261654 +-0.374229 0.217732 0.248084 -0.380824 0.221569 0.234266 -0.387038 0.225185 0.220214 +-0.392865 0.228575 0.205941 -0.398299 0.231736 0.191462 -0.403334 0.234666 0.176791 +-0.407965 0.23736 0.161944 -0.412188 0.239817 0.146934 -0.415999 0.242034 0.131778 +-0.419393 0.244009 0.116489 -0.422368 0.24574 0.101084 -0.42492 0.247225 0.0855781 +-0.427047 0.248463 0.0699863 -0.428747 0.249451 0.0543245 -0.430017 0.250191 0.0386084 +-0.430858 0.25068 0.0228536 -0.431267 0.250918 0.00707595 -0.431245 0.250905 -0.00870878 +-0.430791 0.250641 -0.0244848 -0.429906 0.250126 -0.0402363 -0.428591 0.249361 -0.0559476 +-0.426847 0.248346 -0.0716029 -0.424676 0.247083 -0.0871865 -0.42208 0.245572 -0.102683 +-0.419062 0.243816 -0.118076 -0.415624 0.241816 -0.133352 -0.41177 0.239574 -0.148494 +-0.407505 0.237092 -0.163487 -0.402831 0.234373 -0.178317 -0.397755 0.23142 -0.192969 +-0.39228 0.228235 -0.207427 -0.386413 0.224821 -0.221678 -0.38016 0.221183 -0.235707 +-0.252369 0.13215 0.409691 -0.263723 0.138095 0.400476 -0.274812 0.143902 0.39086 +-0.285626 0.149565 0.380853 -0.296155 0.155078 0.370465 -0.306387 0.160436 0.359706 +-0.316312 0.165633 0.348587 -0.325922 0.170665 0.33712 -0.335204 0.175526 0.325315 +-0.344152 0.180211 0.313184 -0.352755 0.184716 0.30074 -0.361005 0.189036 0.287995 +-0.368894 0.193167 0.274962 -0.376414 0.197105 0.261654 -0.383557 0.200845 0.248084 +-0.390317 0.204385 0.234266 -0.396685 0.20772 0.220214 -0.402657 0.210847 0.205941 +-0.408226 0.213763 0.191462 -0.413387 0.216465 0.176791 -0.418134 0.218951 0.161944 +-0.422462 0.221218 0.146934 -0.426368 0.223263 0.131778 -0.429847 0.225084 0.116489 +-0.432896 0.226681 0.101084 -0.435511 0.228051 0.0855781 -0.437691 0.229192 0.0699863 +-0.439433 0.230104 0.0543245 -0.440736 0.230786 0.0386084 -0.441597 0.231237 0.0228536 +-0.442017 0.231457 0.00707595 -0.441994 0.231445 -0.00870878 -0.441528 0.231201 -0.0244848 +-0.440622 0.230727 -0.0402363 -0.439274 0.230021 -0.0559476 -0.437486 0.229085 -0.0716029 +-0.435261 0.22792 -0.0871865 -0.4326 0.226526 -0.102683 -0.429507 0.224906 -0.118076 +-0.425983 0.223061 -0.133352 -0.422034 0.220993 -0.148494 -0.417662 0.218704 -0.163487 +-0.412872 0.216196 -0.178317 -0.407669 0.213471 -0.192969 -0.402058 0.210533 -0.207427 +-0.396045 0.207385 -0.221678 -0.389635 0.204028 -0.235707 -0.258006 0.120777 0.409691 +-0.269612 0.12621 0.400476 -0.280949 0.131517 0.39086 -0.292005 0.136693 0.380853 +-0.302769 0.141731 0.370465 -0.31323 0.146628 0.359706 -0.323377 0.151378 0.348587 +-0.333201 0.155977 0.33712 -0.342691 0.16042 0.325315 -0.351838 0.164702 0.313184 +-0.360634 0.168819 0.30074 -0.369068 0.172767 0.287995 -0.377133 0.176543 0.274962 +-0.384821 0.180141 0.261654 -0.392124 0.18356 0.248084 -0.399034 0.186795 0.234266 +-0.405545 0.189843 0.220214 -0.41165 0.192701 0.205941 -0.417344 0.195366 0.191462 +-0.422619 0.197835 0.176791 -0.427472 0.200107 0.161944 -0.431897 0.202179 0.146934 +-0.43589 0.204048 0.131778 -0.439447 0.205713 0.116489 -0.442564 0.207172 0.101084 +-0.445238 0.208424 0.0855781 -0.447467 0.209467 0.0699863 -0.449248 0.210301 0.0543245 +-0.450579 0.210924 0.0386084 -0.45146 0.211336 0.0228536 -0.451888 0.211537 0.00707595 +-0.451865 0.211526 -0.00870878 -0.451389 0.211303 -0.0244848 -0.450462 0.210869 -0.0402363 +-0.449084 0.210224 -0.0559476 -0.447257 0.209369 -0.0716029 -0.444982 0.208304 -0.0871865 +-0.442262 0.20703 -0.102683 -0.439099 0.20555 -0.118076 -0.435497 0.203864 -0.133352 +-0.431459 0.201974 -0.148494 -0.42699 0.199881 -0.163487 -0.422093 0.197589 -0.178317 +-0.416774 0.195099 -0.192969 -0.411038 0.192414 -0.207427 -0.40489 0.189536 -0.221678 +-0.398337 0.186469 -0.235707 -0.26313 0.109164 0.409691 -0.274967 0.114075 0.400476 +-0.286529 0.118871 0.39086 -0.297805 0.123549 0.380853 -0.308782 0.128103 0.370465 +-0.319451 0.132529 0.359706 -0.329799 0.136823 0.348587 -0.339818 0.140979 0.33712 +-0.349497 0.144994 0.325315 -0.358826 0.148865 0.313184 -0.367796 0.152586 0.30074 +-0.376398 0.156155 0.287995 -0.384623 0.159567 0.274962 -0.392464 0.16282 0.261654 +-0.399911 0.16591 0.248084 -0.406959 0.168834 0.234266 -0.413599 0.171588 0.220214 +-0.419826 0.174172 0.205941 -0.425632 0.17658 0.191462 -0.431013 0.178813 0.176791 +-0.435962 0.180866 0.161944 -0.440475 0.182738 0.146934 -0.444547 0.184428 0.131778 +-0.448175 0.185933 0.116489 -0.451353 0.187251 0.101084 -0.454081 0.188383 0.0855781 +-0.456354 0.189326 0.0699863 -0.45817 0.190079 0.0543245 -0.459528 0.190643 0.0386084 +-0.460426 0.191015 0.0228536 -0.460863 0.191197 0.00707595 -0.460839 0.191187 -0.00870878 +-0.460354 0.190985 -0.0244848 -0.459409 0.190593 -0.0402363 -0.458003 0.19001 -0.0559476 +-0.45614 0.189237 -0.0716029 -0.45382 0.188274 -0.0871865 -0.451045 0.187124 -0.102683 +-0.44782 0.185785 -0.118076 -0.444146 0.184261 -0.133352 -0.440028 0.182553 -0.148494 +-0.43547 0.180662 -0.163487 -0.430476 0.17859 -0.178317 -0.425051 0.176339 -0.192969 +-0.419201 0.173912 -0.207427 -0.412931 0.171311 -0.221678 -0.406249 0.168539 -0.235707 +-0.267732 0.0973337 0.409691 -0.279776 0.101712 0.400476 -0.29154 0.105989 0.39086 +-0.303013 0.11016 0.380853 -0.314182 0.114221 0.370465 -0.325037 0.118167 0.359706 +-0.335567 0.121995 0.348587 -0.345761 0.125701 0.33712 -0.355609 0.129282 0.325315 +-0.365101 0.132732 0.313184 -0.374228 0.13605 0.30074 -0.38298 0.139232 0.287995 +-0.39135 0.142275 0.274962 -0.399327 0.145175 0.261654 -0.406905 0.14793 0.248084 +-0.414076 0.150537 0.234266 -0.420832 0.152994 0.220214 -0.427168 0.155297 0.205941 +-0.433076 0.157445 0.191462 -0.43855 0.159435 0.176791 -0.443586 0.161266 0.161944 +-0.448178 0.162935 0.146934 -0.452321 0.164441 0.131778 -0.456012 0.165783 0.116489 +-0.459247 0.166959 0.101084 -0.462022 0.167968 0.0855781 -0.464335 0.168809 0.0699863 +-0.466183 0.169481 0.0543245 -0.467564 0.169983 0.0386084 -0.468478 0.170315 0.0228536 +-0.468923 0.170477 0.00707595 -0.468899 0.170468 -0.00870878 -0.468405 0.170289 -0.0244848 +-0.467443 0.169939 -0.0402363 -0.466013 0.169419 -0.0559476 -0.464117 0.16873 -0.0716029 +-0.461756 0.167871 -0.0871865 -0.458933 0.166845 -0.102683 -0.455652 0.165652 -0.118076 +-0.451914 0.164293 -0.133352 -0.447724 0.16277 -0.148494 -0.443086 0.161084 -0.163487 +-0.438004 0.159236 -0.178317 -0.432485 0.15723 -0.192969 -0.426532 0.155066 -0.207427 +-0.420153 0.152746 -0.221678 -0.413353 0.150274 -0.235707 -0.271802 0.0853105 0.409691 +-0.284029 0.0891483 0.400476 -0.295972 0.0928969 0.39086 -0.307619 0.0965526 0.380853 +-0.318958 0.100112 0.370465 -0.329978 0.10357 0.359706 -0.340668 0.106926 0.348587 +-0.351017 0.110174 0.33712 -0.361015 0.113312 0.325315 -0.370652 0.116337 0.313184 +-0.379917 0.119245 0.30074 -0.388803 0.122034 0.287995 -0.397299 0.1247 0.274962 +-0.405398 0.127242 0.261654 -0.413091 0.129657 0.248084 -0.420371 0.131942 0.234266 +-0.42723 0.134095 0.220214 -0.433662 0.136114 0.205941 -0.43966 0.137996 0.191462 +-0.445217 0.139741 0.176791 -0.45033 0.141345 0.161944 -0.454991 0.142808 0.146934 +-0.459198 0.144129 0.131778 -0.462945 0.145305 0.116489 -0.466228 0.146335 0.101084 +-0.469046 0.14722 0.0855781 -0.471393 0.147956 0.0699863 -0.47327 0.148545 0.0543245 +-0.474672 0.148986 0.0386084 -0.4756 0.149277 0.0228536 -0.476052 0.149418 0.00707595 +-0.476027 0.149411 -0.00870878 -0.475526 0.149254 -0.0244848 -0.474549 0.148947 -0.0402363 +-0.473097 0.148491 -0.0559476 -0.471172 0.147887 -0.0716029 -0.468776 0.147135 -0.0871865 +-0.46591 0.146235 -0.102683 -0.462579 0.14519 -0.118076 -0.458784 0.143999 -0.133352 +-0.45453 0.142664 -0.148494 -0.449822 0.141186 -0.163487 -0.444663 0.139567 -0.178317 +-0.439059 0.137808 -0.192969 -0.433016 0.135911 -0.207427 -0.42654 0.133878 -0.221678 +-0.419637 0.131712 -0.235707 -0.275332 0.0731179 0.409691 -0.287718 0.0764072 0.400476 +-0.299817 0.0796201 0.39086 -0.311615 0.0827532 0.380853 -0.323101 0.0858036 0.370465 +-0.334265 0.0887682 0.359706 -0.345093 0.0916438 0.348587 -0.355577 0.0944278 0.33712 +-0.365704 0.0971173 0.325315 -0.375466 0.0997097 0.313184 -0.384852 0.102202 0.30074 +-0.393853 0.104593 0.287995 -0.40246 0.106878 0.274962 -0.410664 0.109057 0.261654 +-0.418457 0.111126 0.248084 -0.425831 0.113085 0.234266 -0.432779 0.11493 0.220214 +-0.439295 0.11666 0.205941 -0.44537 0.118274 0.191462 -0.451 0.119769 0.176791 +-0.456179 0.121144 0.161944 -0.460901 0.122398 0.146934 -0.465162 0.12353 0.131778 +-0.468958 0.124538 0.116489 -0.472284 0.125421 0.101084 -0.475138 0.126179 0.0855781 +-0.477517 0.12681 0.0699863 -0.479417 0.127315 0.0543245 -0.480838 0.127692 0.0386084 +-0.481777 0.127942 0.0228536 -0.482235 0.128064 0.00707595 -0.48221 0.128057 -0.00870878 +-0.481703 0.127922 -0.0244848 -0.480713 0.127659 -0.0402363 -0.479243 0.127269 -0.0559476 +-0.477293 0.126751 -0.0716029 -0.474865 0.126106 -0.0871865 -0.471962 0.125335 -0.102683 +-0.468587 0.124439 -0.118076 -0.464743 0.123418 -0.133352 -0.460434 0.122274 -0.148494 +-0.455664 0.121007 -0.163487 -0.450439 0.11962 -0.178317 -0.444762 0.118112 -0.192969 +-0.438641 0.116487 -0.207427 -0.432081 0.114744 -0.221678 -0.425088 0.112887 -0.235707 +-0.278316 0.0607801 0.409691 -0.290836 0.0635144 0.400476 -0.303066 0.0661851 0.39086 +-0.314992 0.0687896 0.380853 -0.326603 0.0713253 0.370465 -0.337887 0.0737896 0.359706 +-0.348833 0.07618 0.348587 -0.35943 0.0784943 0.33712 -0.369668 0.08073 0.325315 +-0.379535 0.0828849 0.313184 -0.389023 0.0849568 0.30074 -0.398121 0.0869438 0.287995 +-0.406821 0.0888437 0.274962 -0.415114 0.0906548 0.261654 -0.422992 0.0923752 0.248084 +-0.430446 0.0940031 0.234266 -0.43747 0.0955369 0.220214 -0.444055 0.0969752 0.205941 +-0.450197 0.0983164 0.191462 -0.455888 0.0995592 0.176791 -0.461123 0.100702 0.161944 +-0.465896 0.101745 0.146934 -0.470204 0.102686 0.131778 -0.47404 0.103523 0.116489 +-0.477403 0.104258 0.101084 -0.480287 0.104888 0.0855781 -0.482691 0.105413 0.0699863 +-0.484613 0.105832 0.0543245 -0.486049 0.106146 0.0386084 -0.486999 0.106353 0.0228536 +-0.487461 0.106454 0.00707595 -0.487436 0.106449 -0.00870878 -0.486923 0.106337 -0.0244848 +-0.485923 0.106118 -0.0402363 -0.484436 0.105794 -0.0559476 -0.482465 0.105363 -0.0716029 +-0.480011 0.104827 -0.0871865 -0.477077 0.104187 -0.102683 -0.473665 0.103442 -0.118076 +-0.46978 0.102593 -0.133352 -0.465424 0.101642 -0.148494 -0.460603 0.100589 -0.163487 +-0.45532 0.0994352 -0.178317 -0.449582 0.0981822 -0.192969 -0.443395 0.0968309 -0.207427 +-0.436763 0.0953826 -0.221678 -0.429695 0.093839 -0.235707 -0.280747 0.0483217 0.409691 +-0.293377 0.0504956 0.400476 -0.305713 0.0526189 0.39086 -0.317744 0.0546895 0.380853 +-0.329456 0.0567054 0.370465 -0.340839 0.0586646 0.359706 -0.351881 0.0605651 0.348587 +-0.36257 0.0624049 0.33712 -0.372897 0.0641824 0.325315 -0.38285 0.0658956 0.313184 +-0.392421 0.0675428 0.30074 -0.401599 0.0691225 0.287995 -0.410375 0.070633 0.274962 +-0.41874 0.0720729 0.261654 -0.426687 0.0734406 0.248084 -0.434206 0.0747348 0.234266 +-0.441291 0.0759543 0.220214 -0.447935 0.0770977 0.205941 -0.45413 0.078164 0.191462 +-0.45987 0.0791521 0.176791 -0.465151 0.080061 0.161944 -0.469966 0.0808898 0.146934 +-0.474311 0.0816376 0.131778 -0.478181 0.0823037 0.116489 -0.481573 0.0828875 0.101084 +-0.484483 0.0833884 0.0855781 -0.486908 0.0838058 0.0699863 -0.488846 0.0841393 0.0543245 +-0.490295 0.0843887 0.0386084 -0.491253 0.0845536 0.0228536 -0.491719 0.0846339 0.00707595 +-0.491694 0.0846295 -0.00870878 -0.491177 0.0845405 -0.0244848 -0.490168 0.0843668 -0.0402363 +-0.488668 0.0841087 -0.0559476 -0.48668 0.0837665 -0.0716029 -0.484204 0.0833404 -0.0871865 +-0.481245 0.082831 -0.102683 -0.477803 0.0822386 -0.118076 -0.473884 0.081564 -0.133352 +-0.46949 0.0808078 -0.148494 -0.464626 0.0799707 -0.163487 -0.459298 0.0790536 -0.178317 +-0.45351 0.0780573 -0.192969 -0.447268 0.076983 -0.207427 -0.440579 0.0758316 -0.221678 +-0.433448 0.0746044 -0.235707 -0.282621 0.0357674 0.409691 -0.295335 0.0373764 0.400476 +-0.307754 0.038948 0.39086 -0.319865 0.0404807 0.380853 -0.331655 0.0419729 0.370465 +-0.343114 0.0434231 0.359706 -0.354229 0.0448298 0.348587 -0.36499 0.0461916 0.33712 +-0.375386 0.0475073 0.325315 -0.385406 0.0487754 0.313184 -0.39504 0.0499947 0.30074 +-0.404279 0.0511639 0.287995 -0.413114 0.052282 0.274962 -0.421535 0.0533478 0.261654 +-0.429535 0.0543601 0.248084 -0.437104 0.0553181 0.234266 -0.444237 0.0562207 0.220214 +-0.450924 0.0570671 0.205941 -0.457161 0.0578564 0.191462 -0.46294 0.0585877 0.176791 +-0.468256 0.0592605 0.161944 -0.473103 0.0598739 0.146934 -0.477477 0.0604275 0.131778 +-0.481373 0.0609206 0.116489 -0.484787 0.0613527 0.101084 -0.487717 0.0617234 0.0855781 +-0.490158 0.0620324 0.0699863 -0.492109 0.0622792 0.0543245 -0.493567 0.0624638 0.0386084 +-0.494532 0.0625859 0.0228536 -0.495002 0.0626453 0.00707595 -0.494976 0.0626421 -0.00870878 +-0.494455 0.0625762 -0.0244848 -0.493439 0.0624476 -0.0402363 -0.49193 0.0622566 -0.0559476 +-0.489928 0.0620033 -0.0716029 -0.487436 0.0616879 -0.0871865 -0.484457 0.0613108 -0.102683 +-0.480992 0.0608724 -0.118076 -0.477046 0.060373 -0.133352 -0.472623 0.0598132 -0.148494 +-0.467727 0.0591936 -0.163487 -0.462363 0.0585148 -0.178317 -0.456537 0.0577774 -0.192969 +-0.450253 0.0569822 -0.207427 -0.443519 0.0561299 -0.221678 -0.436341 0.0552216 -0.235707 +-0.283934 0.023142 0.409691 -0.296707 0.024183 0.400476 -0.309183 0.0251999 0.39086 +-0.32135 0.0261916 0.380853 -0.333196 0.027157 0.370465 -0.344708 0.0280953 0.359706 +-0.355875 0.0290055 0.348587 -0.366685 0.0298866 0.33712 -0.377129 0.0307378 0.325315 +-0.387196 0.0315583 0.313184 -0.396875 0.0323472 0.30074 -0.406157 0.0331037 0.287995 +-0.415033 0.0338271 0.274962 -0.423493 0.0345167 0.261654 -0.43153 0.0351717 0.248084 +-0.439135 0.0357916 0.234266 -0.4463 0.0363756 0.220214 -0.453019 0.0369232 0.205941 +-0.459284 0.0374338 0.191462 -0.46509 0.0379071 0.176791 -0.470431 0.0383423 0.161944 +-0.475301 0.0387392 0.146934 -0.479695 0.0390974 0.131778 -0.483609 0.0394164 0.116489 +-0.487039 0.039696 0.101084 -0.489982 0.0399359 0.0855781 -0.492435 0.0401358 0.0699863 +-0.494395 0.0402955 0.0543245 -0.49586 0.0404149 0.0386084 -0.496829 0.0404939 0.0228536 +-0.497301 0.0405324 0.00707595 -0.497275 0.0405303 -0.00870878 -0.496752 0.0404876 -0.0244848 +-0.495731 0.0404044 -0.0402363 -0.494215 0.0402808 -0.0559476 -0.492204 0.0401169 -0.0716029 +-0.4897 0.0399129 -0.0871865 -0.486707 0.0396689 -0.102683 -0.483226 0.0393852 -0.118076 +-0.479262 0.0390621 -0.133352 -0.474819 0.0387 -0.148494 -0.4699 0.0382991 -0.163487 +-0.464511 0.0378599 -0.178317 -0.458657 0.0373827 -0.192969 -0.452345 0.0368682 -0.207427 +-0.445579 0.0363168 -0.221678 -0.438368 0.0357291 -0.235707 -0.284683 0.0104706 0.409691 +-0.29749 0.0109417 0.400476 -0.309999 0.0114017 0.39086 -0.322198 0.0118504 0.380853 +-0.334075 0.0122872 0.370465 -0.345617 0.0127118 0.359706 -0.356813 0.0131236 0.348587 +-0.367653 0.0135222 0.33712 -0.378124 0.0139074 0.325315 -0.388218 0.0142786 0.313184 +-0.397922 0.0146355 0.30074 -0.407229 0.0149778 0.287995 -0.416128 0.0153051 0.274962 +-0.424611 0.0156171 0.261654 -0.432668 0.0159135 0.248084 -0.440293 0.0161939 0.234266 +-0.447477 0.0164582 0.220214 -0.454214 0.0167059 0.205941 -0.460496 0.016937 0.191462 +-0.466317 0.0171511 0.176791 -0.471672 0.017348 0.161944 -0.476554 0.0175276 0.146934 +-0.48096 0.0176897 0.131778 -0.484885 0.017834 0.116489 -0.488324 0.0179605 0.101084 +-0.491275 0.018069 0.0855781 -0.493734 0.0181595 0.0699863 -0.495699 0.0182318 0.0543245 +-0.497168 0.0182858 0.0386084 -0.49814 0.0183215 0.0228536 -0.498613 0.0183389 0.00707595 +-0.498587 0.018338 -0.00870878 -0.498062 0.0183187 -0.0244848 -0.497039 0.0182811 -0.0402363 +-0.495519 0.0182251 -0.0559476 -0.493502 0.018151 -0.0716029 -0.490992 0.0180587 -0.0871865 +-0.487991 0.0179483 -0.102683 -0.484501 0.0178199 -0.118076 -0.480527 0.0176737 -0.133352 +-0.476071 0.0175099 -0.148494 -0.47114 0.0173285 -0.163487 -0.465737 0.0171297 -0.178317 +-0.459867 0.0169139 -0.192969 -0.453538 0.0166811 -0.207427 -0.446755 0.0164316 -0.221678 +-0.439525 0.0161657 -0.235707 -0.284867 -0.00222152 0.409691 -0.297682 -0.00232145 0.400476 +-0.310199 -0.00241907 0.39086 -0.322406 -0.00251426 0.380853 -0.33429 -0.00260694 0.370465 +-0.34584 -0.00269701 0.359706 -0.357044 -0.00278438 0.348587 -0.36789 -0.00286897 0.33712 +-0.378369 -0.00295068 0.325315 -0.388468 -0.00302945 0.313184 -0.398179 -0.00310518 0.30074 +-0.407492 -0.0031778 0.287995 -0.416397 -0.00324724 0.274962 -0.424885 -0.00331344 0.261654 +-0.432948 -0.00337632 0.248084 -0.440577 -0.00343582 0.234266 -0.447766 -0.00349188 0.220214 +-0.454507 -0.00354445 0.205941 -0.460793 -0.00359347 0.191462 -0.466618 -0.00363889 0.176791 +-0.471976 -0.00368068 0.161944 -0.476862 -0.00371878 0.146934 -0.481271 -0.00375316 0.131778 +-0.485198 -0.00378379 0.116489 -0.488639 -0.00381063 0.101084 -0.491592 -0.00383365 0.0855781 +-0.494053 -0.00385284 0.0699863 -0.496019 -0.00386817 0.0543245 -0.497489 -0.00387964 0.0386084 +-0.498461 -0.00388722 0.0228536 -0.498935 -0.00389091 0.00707595 -0.498909 -0.00389071 -0.00870878 +-0.498384 -0.00388662 -0.0244848 -0.49736 -0.00387863 -0.0402363 -0.495839 -0.00386677 -0.0559476 +-0.493821 -0.00385103 -0.0716029 -0.491309 -0.00383145 -0.0871865 -0.488306 -0.00380803 -0.102683 +-0.484814 -0.00378079 -0.118076 -0.480837 -0.00374978 -0.133352 -0.476379 -0.00371501 -0.148494 +-0.471444 -0.00367653 -0.163487 -0.466037 -0.00363436 -0.178317 -0.460164 -0.00358856 -0.192969 +-0.453831 -0.00353917 -0.207427 -0.447043 -0.00348624 -0.221678 -0.439808 -0.00342982 -0.235707 +-0.284485 -0.0149092 0.409691 -0.297283 -0.01558 0.400476 -0.309784 -0.0162351 0.39086 +-0.321974 -0.016874 0.380853 -0.333842 -0.0174959 0.370465 -0.345377 -0.0181004 0.359706 +-0.356565 -0.0186868 0.348587 -0.367397 -0.0192545 0.33712 -0.377861 -0.0198029 0.325315 +-0.387948 -0.0203315 0.313184 -0.397646 -0.0208397 0.30074 -0.406946 -0.0213271 0.287995 +-0.415839 -0.0217932 0.274962 -0.424315 -0.0222374 0.261654 -0.432368 -0.0226594 0.248084 +-0.439987 -0.0230588 0.234266 -0.447166 -0.023435 0.220214 -0.453898 -0.0237878 0.205941 +-0.460176 -0.0241168 0.191462 -0.465993 -0.0244217 0.176791 -0.471344 -0.0247021 0.161944 +-0.476223 -0.0249578 0.146934 -0.480626 -0.0251885 0.131778 -0.484548 -0.0253941 0.116489 +-0.487985 -0.0255742 0.101084 -0.490933 -0.0257287 0.0855781 -0.493391 -0.0258575 0.0699863 +-0.495354 -0.0259604 0.0543245 -0.496822 -0.0260374 0.0386084 -0.497793 -0.0260883 0.0228536 +-0.498266 -0.026113 0.00707595 -0.49824 -0.0261117 -0.00870878 -0.497716 -0.0260842 -0.0244848 +-0.496694 -0.0260306 -0.0402363 -0.495174 -0.025951 -0.0559476 -0.493159 -0.0258454 -0.0716029 +-0.490651 -0.0257139 -0.0871865 -0.487652 -0.0255568 -0.102683 -0.484164 -0.025374 -0.118076 +-0.480193 -0.0251658 -0.133352 -0.47574 -0.0249325 -0.148494 -0.470812 -0.0246742 -0.163487 +-0.465413 -0.0243913 -0.178317 -0.459548 -0.0240839 -0.192969 -0.453223 -0.0237524 -0.207427 +-0.446444 -0.0233972 -0.221678 -0.439219 -0.0230185 -0.235707 +POLYGONS 4385 17540 +3 0 1 8 +3 0 8 7 +3 1 2 9 +3 1 9 8 +3 2 3 10 +3 2 10 9 +3 3 4 11 +3 3 11 10 +3 4 5 12 +3 4 12 11 +3 5 6 13 +3 5 13 12 +3 7 8 15 +3 7 15 14 +3 8 9 16 +3 8 16 15 +3 9 10 17 +3 9 17 16 +3 10 11 18 +3 10 18 17 +3 11 12 19 +3 11 19 18 +3 12 13 20 +3 12 20 19 +3 14 15 22 +3 14 22 21 +3 15 16 23 +3 15 23 22 +3 16 17 24 +3 16 24 23 +3 17 18 25 +3 17 25 24 +3 18 19 26 +3 18 26 25 +3 19 20 27 +3 19 27 26 +3 59 21 22 +3 152 103 21 +3 63 62 22 +3 61 60 22 +3 68 23 24 +3 67 66 23 +3 74 24 25 +3 72 71 24 +3 79 25 26 +3 77 76 25 +3 85 26 27 +3 83 82 26 +3 198 197 28 +3 386 338 28 +3 154 29 30 +3 344 201 29 +3 208 207 30 +3 254 30 38 +3 213 212 31 +3 307 259 31 +3 219 218 32 +3 360 312 217 +3 224 223 33 +3 318 270 33 +3 482 35 36 +3 668 620 35 +3 484 483 36 +3 578 530 36 +3 490 489 37 +3 583 488 37 +3 495 494 38 +3 38 732 541 +3 500 499 39 +3 594 546 39 +3 506 505 40 +3 647 599 40 +3 809 808 42 +3 997 949 42 +3 813 812 43 +3 907 859 43 +3 819 818 44 +3 960 912 44 +3 824 823 45 +3 918 870 45 +3 830 829 46 +3 1019 971 828 +3 835 834 47 +3 881 47 55 +3 106 59 22 +3 106 22 29 +3 106 29 21 +3 106 21 59 +3 151 150 103 +3 103 28 21 +3 153 29 28 +3 150 28 103 +3 152 151 103 +3 153 152 29 +3 152 21 29 +3 152 150 151 +3 28 152 153 +3 28 150 152 +3 63 22 23 +3 62 30 22 +3 64 63 23 +3 111 30 62 +3 65 64 23 +3 111 65 30 +3 65 23 30 +3 111 64 65 +3 111 62 63 +3 111 63 64 +3 108 60 61 +3 60 29 22 +3 110 109 61 +3 156 109 110 +3 107 29 60 +3 108 107 60 +3 109 108 61 +3 155 29 107 +3 110 61 22 +3 155 107 108 +3 110 22 30 +3 156 155 108 +3 155 30 29 +3 156 108 109 +3 157 156 110 +3 157 30 155 +3 157 110 30 +3 157 155 156 +3 69 68 24 +3 68 31 23 +3 70 69 24 +3 117 31 68 +3 70 24 31 +3 117 70 31 +3 117 68 69 +3 117 69 70 +3 114 66 67 +3 66 30 23 +3 67 23 31 +3 161 114 115 +3 113 30 66 +3 114 113 66 +3 115 114 67 +3 113 160 30 +3 115 67 31 +3 161 160 113 +3 30 163 31 +3 161 113 114 +3 162 161 115 +3 30 160 163 +3 163 162 115 +3 162 160 161 +3 164 163 115 +3 163 160 162 +3 164 115 31 +3 164 31 163 +3 75 74 25 +3 74 32 24 +3 75 25 32 +3 122 75 32 +3 122 32 74 +3 122 74 75 +3 120 72 73 +3 71 31 24 +3 73 72 24 +3 165 31 118 +3 73 24 32 +3 119 71 72 +3 118 31 71 +3 119 118 71 +3 167 119 120 +3 120 119 72 +3 121 120 73 +3 165 118 119 +3 121 73 32 +3 166 165 119 +3 168 32 31 +3 167 166 119 +3 167 120 121 +3 166 31 165 +3 168 167 121 +3 167 31 166 +3 169 168 121 +3 168 31 167 +3 169 121 32 +3 169 32 168 +3 80 79 26 +3 127 33 25 +3 81 80 26 +3 128 127 81 +3 81 26 33 +3 127 80 81 +3 127 25 79 +3 127 79 80 +3 128 81 33 +3 128 33 127 +3 125 77 78 +3 76 32 25 +3 78 77 25 +3 125 124 77 +3 78 25 33 +3 76 77 124 +3 123 32 76 +3 76 124 123 +3 172 124 125 +3 123 170 32 +3 126 125 78 +3 171 170 123 +3 126 78 33 +3 173 33 32 +3 171 123 124 +3 172 171 124 +3 172 125 126 +3 171 32 170 +3 173 172 126 +3 172 32 171 +3 174 173 126 +3 173 32 172 +3 174 126 33 +3 174 33 173 +3 86 85 27 +3 85 34 26 +3 86 27 34 +3 133 86 34 +3 133 34 85 +3 133 85 86 +3 130 82 83 +3 82 33 26 +3 132 83 26 +3 178 130 131 +3 129 33 82 +3 130 129 82 +3 131 130 83 +3 129 176 33 +3 178 177 130 +3 177 176 129 +3 132 26 34 +3 132 131 83 +3 178 34 33 +3 177 129 130 +3 178 131 132 +3 177 33 176 +3 179 178 132 +3 178 33 177 +3 180 179 132 +3 179 34 178 +3 180 132 34 +3 180 34 179 +3 198 28 29 +3 245 197 198 +3 199 198 29 +3 245 244 197 +3 200 199 29 +3 246 245 198 +3 247 200 29 +3 247 246 199 +3 292 244 245 +3 244 28 197 +3 246 198 199 +3 292 291 244 +3 247 199 200 +3 293 292 245 +3 294 247 29 +3 293 246 247 +3 291 36 28 +3 291 28 244 +3 293 245 246 +3 340 339 293 +3 294 293 247 +3 339 292 293 +3 341 294 29 +3 340 293 294 +3 387 36 291 +3 339 291 292 +3 341 340 294 +3 388 387 341 +3 341 29 36 +3 387 340 341 +3 387 291 339 +3 387 339 340 +3 388 341 36 +3 435 388 36 +3 435 36 387 +3 435 387 388 +3 386 385 338 +3 338 35 28 +3 433 432 386 +3 385 35 338 +3 386 28 36 +3 432 35 385 +3 433 36 35 +3 432 385 386 +3 434 433 386 +3 433 35 432 +3 434 386 36 +3 434 36 433 +3 203 202 154 +3 250 202 203 +3 204 203 154 +3 249 29 154 +3 204 154 30 +3 250 249 202 +3 205 204 30 +3 251 250 203 +3 252 205 30 +3 252 251 204 +3 249 37 29 +3 249 154 202 +3 251 203 204 +3 298 250 251 +3 252 204 205 +3 298 297 250 +3 299 252 30 +3 298 251 252 +3 297 37 249 +3 297 249 250 +3 299 298 252 +3 346 345 299 +3 346 299 30 +3 345 298 299 +3 345 37 297 +3 345 297 298 +3 346 30 37 +3 393 346 37 +3 393 37 345 +3 393 345 346 +3 296 248 201 +3 343 342 295 +3 342 36 29 +3 248 29 201 +3 343 295 296 +3 295 29 248 +3 344 296 201 +3 296 295 248 +3 390 342 343 +3 342 29 295 +3 391 390 343 +3 438 391 392 +3 392 344 29 +3 344 343 296 +3 389 36 342 +3 390 389 342 +3 391 343 344 +3 437 36 436 +3 438 437 391 +3 437 389 390 +3 392 29 37 +3 392 391 344 +3 436 36 389 +3 437 436 389 +3 439 37 36 +3 390 391 437 +3 439 438 392 +3 438 36 437 +3 440 439 392 +3 439 36 438 +3 440 392 37 +3 440 37 439 +3 209 208 30 +3 303 255 256 +3 209 30 31 +3 256 208 209 +3 210 209 31 +3 256 255 208 +3 211 210 31 +3 257 256 209 +3 258 211 31 +3 257 210 211 +3 302 30 207 +3 255 207 208 +3 257 209 210 +3 303 302 255 +3 258 257 211 +3 304 303 256 +3 305 258 31 +3 304 257 258 +3 302 38 30 +3 302 207 255 +3 304 256 257 +3 351 350 304 +3 305 304 258 +3 350 303 304 +3 352 305 31 +3 351 304 305 +3 350 38 302 +3 350 302 303 +3 352 351 305 +3 399 398 352 +3 352 31 38 +3 398 351 352 +3 398 38 350 +3 398 350 351 +3 399 352 38 +3 446 399 38 +3 446 38 398 +3 446 398 399 +3 349 301 254 +3 348 37 30 +3 396 395 348 +3 301 30 254 +3 396 348 349 +3 348 30 301 +3 397 349 254 +3 349 348 301 +3 443 396 397 +3 395 37 348 +3 397 396 349 +3 442 37 395 +3 397 254 38 +3 444 38 37 +3 395 443 442 +3 395 396 443 +3 444 443 397 +3 443 37 442 +3 445 444 397 +3 444 37 443 +3 445 397 38 +3 445 38 444 +3 214 213 31 +3 212 39 31 +3 214 31 32 +3 261 213 214 +3 215 214 32 +3 261 260 213 +3 216 215 32 +3 262 261 214 +3 263 216 32 +3 262 215 216 +3 260 39 212 +3 260 212 213 +3 262 214 215 +3 309 261 262 +3 263 262 216 +3 309 308 261 +3 310 263 32 +3 309 262 263 +3 308 39 260 +3 308 260 261 +3 310 309 263 +3 357 356 310 +3 357 310 32 +3 356 309 310 +3 356 39 308 +3 356 308 309 +3 357 32 39 +3 404 357 39 +3 404 39 356 +3 404 356 357 +3 354 353 306 +3 353 38 31 +3 354 306 307 +3 306 31 259 +3 355 307 31 +3 307 306 259 +3 401 353 354 +3 353 31 306 +3 402 401 354 +3 449 448 402 +3 355 31 39 +3 355 354 307 +3 400 38 353 +3 401 400 353 +3 402 354 355 +3 448 38 447 +3 450 402 355 +3 448 400 401 +3 447 38 400 +3 448 447 400 +3 449 39 38 +3 401 402 448 +3 450 449 402 +3 449 38 448 +3 450 355 39 +3 450 39 449 +3 220 219 32 +3 314 266 267 +3 220 32 33 +3 267 219 220 +3 221 220 33 +3 267 266 219 +3 222 221 33 +3 267 220 221 +3 269 222 33 +3 268 221 222 +3 313 32 218 +3 266 218 219 +3 268 267 221 +3 314 313 266 +3 269 268 222 +3 314 267 268 +3 316 269 33 +3 315 268 269 +3 313 40 32 +3 313 218 266 +3 315 314 268 +3 362 361 315 +3 316 315 269 +3 361 314 315 +3 363 316 33 +3 362 315 316 +3 361 40 313 +3 361 313 314 +3 363 362 316 +3 410 409 363 +3 363 33 40 +3 409 362 363 +3 409 40 361 +3 409 361 362 +3 410 363 40 +3 457 410 40 +3 457 40 409 +3 457 409 410 +3 312 264 217 +3 359 358 311 +3 358 39 32 +3 264 32 217 +3 359 311 312 +3 311 32 264 +3 360 217 32 +3 312 311 264 +3 406 358 359 +3 358 32 311 +3 407 406 359 +3 454 407 408 +3 408 360 32 +3 360 359 312 +3 405 39 358 +3 406 405 358 +3 407 359 360 +3 453 39 452 +3 408 407 360 +3 453 405 406 +3 408 32 40 +3 455 40 39 +3 452 39 405 +3 453 452 405 +3 454 453 406 +3 454 406 407 +3 455 454 408 +3 454 39 453 +3 456 455 408 +3 455 39 454 +3 456 408 40 +3 456 40 455 +3 225 224 33 +3 319 414 366 +3 225 33 34 +3 272 224 225 +3 226 225 34 +3 272 271 224 +3 227 226 34 +3 272 225 226 +3 274 227 34 +3 273 226 227 +3 366 223 271 +3 271 223 224 +3 273 272 226 +3 320 319 273 +3 274 273 227 +3 319 272 273 +3 321 274 34 +3 320 273 274 +3 319 366 271 +3 319 271 272 +3 321 320 274 +3 368 367 321 +3 368 321 34 +3 367 320 321 +3 366 41 33 +3 366 33 223 +3 462 415 41 +3 367 319 320 +3 368 34 41 +3 415 368 41 +3 462 41 414 +3 414 41 366 +3 414 367 415 +3 415 367 368 +3 414 415 462 +3 367 414 319 +3 365 364 317 +3 364 40 33 +3 365 317 318 +3 317 33 270 +3 318 33 41 +3 318 317 270 +3 412 364 365 +3 364 33 317 +3 413 365 318 +3 460 412 413 +3 411 40 364 +3 412 411 364 +3 413 412 365 +3 459 40 458 +3 413 318 41 +3 459 411 412 +3 458 40 411 +3 459 458 411 +3 460 41 40 +3 460 459 412 +3 461 460 413 +3 460 40 459 +3 461 413 41 +3 461 41 460 +3 529 482 36 +3 527 35 482 +3 574 526 527 +3 527 526 35 +3 528 527 482 +3 574 573 526 +3 529 528 482 +3 575 574 527 +3 576 529 36 +3 576 575 528 +3 573 43 35 +3 573 35 526 +3 575 527 528 +3 622 574 575 +3 576 528 529 +3 622 621 574 +3 623 576 36 +3 622 575 576 +3 621 43 573 +3 621 573 574 +3 623 622 576 +3 670 669 623 +3 670 623 36 +3 669 622 623 +3 669 43 621 +3 669 621 622 +3 670 36 43 +3 717 670 43 +3 717 43 669 +3 717 669 670 +3 714 667 668 +3 667 42 35 +3 715 714 668 +3 667 35 620 +3 716 668 35 +3 668 667 620 +3 762 715 716 +3 714 42 667 +3 762 761 715 +3 761 42 714 +3 716 35 43 +3 716 715 668 +3 762 43 42 +3 761 714 715 +3 763 762 716 +3 762 42 761 +3 763 716 43 +3 763 43 762 +3 487 484 37 +3 627 579 580 +3 484 36 37 +3 533 532 484 +3 534 533 487 +3 532 531 484 +3 531 36 483 +3 531 483 484 +3 533 484 487 +3 580 532 533 +3 534 487 37 +3 580 579 532 +3 581 534 37 +3 581 580 533 +3 626 36 531 +3 579 531 532 +3 581 533 534 +3 627 626 579 +3 628 581 37 +3 627 580 581 +3 626 44 36 +3 626 531 579 +3 628 627 581 +3 675 674 628 +3 675 628 37 +3 674 627 628 +3 674 44 626 +3 674 626 627 +3 675 37 44 +3 722 675 44 +3 722 44 674 +3 722 674 675 +3 625 624 577 +3 624 43 36 +3 625 577 578 +3 577 36 530 +3 578 36 44 +3 578 577 530 +3 672 624 625 +3 624 36 577 +3 673 625 578 +3 720 719 673 +3 671 43 624 +3 672 671 624 +3 673 672 625 +3 719 672 673 +3 721 673 578 +3 671 672 719 +3 718 43 671 +3 671 719 718 +3 767 720 721 +3 765 766 43 +3 721 720 673 +3 766 765 719 +3 721 578 44 +3 766 719 720 +3 765 43 718 +3 765 718 719 +3 767 44 43 +3 767 766 720 +3 768 767 721 +3 767 43 766 +3 769 768 721 +3 768 44 767 +3 769 721 44 +3 769 44 768 +3 492 490 38 +3 537 489 490 +3 490 37 38 +3 537 536 489 +3 493 492 38 +3 538 537 490 +3 492 493 540 +3 539 538 492 +3 775 45 37 +3 536 37 489 +3 538 490 492 +3 585 537 538 +3 492 540 539 +3 585 584 537 +3 540 493 38 +3 586 585 538 +3 587 540 38 +3 587 586 539 +3 775 37 536 +3 584 536 537 +3 586 538 539 +3 633 585 586 +3 587 539 540 +3 633 632 585 +3 634 587 38 +3 633 586 587 +3 536 584 775 +3 632 584 585 +3 634 633 587 +3 681 680 634 +3 634 38 45 +3 680 633 634 +3 775 728 45 +3 680 632 633 +3 681 634 45 +3 728 681 45 +3 775 680 728 +3 728 680 681 +3 775 584 632 +3 775 632 680 +3 631 583 37 +3 488 44 37 +3 678 677 630 +3 677 44 488 +3 678 630 631 +3 630 488 583 +3 679 631 37 +3 631 630 583 +3 725 724 678 +3 677 488 630 +3 725 678 679 +3 772 725 726 +3 679 37 45 +3 679 678 631 +3 724 44 677 +3 724 677 678 +3 726 725 679 +3 771 44 724 +3 774 726 679 +3 773 45 44 +3 771 724 725 +3 772 771 725 +3 773 772 726 +3 772 44 771 +3 774 773 726 +3 773 44 772 +3 774 679 45 +3 774 45 773 +3 497 496 39 +3 590 542 543 +3 496 495 38 +3 543 495 496 +3 496 38 39 +3 543 542 495 +3 498 497 39 +3 544 543 496 +3 545 498 39 +3 545 544 497 +3 542 38 494 +3 542 494 495 +3 544 496 497 +3 590 589 542 +3 545 497 498 +3 591 590 543 +3 592 545 39 +3 592 591 544 +3 589 46 38 +3 589 38 542 +3 591 543 544 +3 638 590 591 +3 592 544 545 +3 638 637 590 +3 639 592 39 +3 638 591 592 +3 637 46 589 +3 637 589 590 +3 639 638 592 +3 686 685 639 +3 639 39 46 +3 685 638 639 +3 685 46 637 +3 685 637 638 +3 686 639 46 +3 733 686 46 +3 733 46 685 +3 733 685 686 +3 636 588 541 +3 635 45 38 +3 683 682 635 +3 588 38 541 +3 683 635 636 +3 635 38 588 +3 684 636 541 +3 636 635 588 +3 730 682 683 +3 682 45 635 +3 730 683 684 +3 777 730 731 +3 732 684 541 +3 684 683 636 +3 729 45 682 +3 730 729 682 +3 731 730 684 +3 776 45 729 +3 732 731 684 +3 778 46 45 +3 38 46 732 +3 778 777 731 +3 776 729 730 +3 777 776 730 +3 778 731 732 +3 777 45 776 +3 779 778 732 +3 778 45 777 +3 780 779 732 +3 779 46 778 +3 780 732 46 +3 780 46 779 +3 502 39 40 +3 738 47 39 +3 501 500 39 +3 548 500 501 +3 502 501 39 +3 548 547 500 +3 503 502 40 +3 549 548 501 +3 504 503 40 +3 550 549 502 +3 551 504 40 +3 550 503 504 +3 547 39 499 +3 547 499 500 +3 549 501 502 +3 596 548 549 +3 550 502 503 +3 596 595 548 +3 551 550 504 +3 597 596 549 +3 598 551 40 +3 597 550 551 +3 738 786 47 +3 595 547 548 +3 597 549 550 +3 644 643 597 +3 598 597 551 +3 643 596 597 +3 645 598 40 +3 644 597 598 +3 738 595 643 +3 643 595 596 +3 645 644 598 +3 692 691 645 +3 645 40 47 +3 691 644 645 +3 738 643 786 +3 691 643 644 +3 692 645 47 +3 739 692 47 +3 738 39 547 +3 738 547 595 +3 786 739 47 +3 739 691 692 +3 786 643 691 +3 786 691 739 +3 641 640 593 +3 640 46 39 +3 641 593 594 +3 593 39 546 +3 642 594 39 +3 594 593 546 +3 688 640 641 +3 640 39 593 +3 689 688 641 +3 736 688 689 +3 642 39 47 +3 642 641 594 +3 687 46 640 +3 688 687 640 +3 689 641 642 +3 736 735 688 +3 737 689 642 +3 687 688 735 +3 734 46 687 +3 687 735 734 +3 783 736 737 +3 782 46 781 +3 737 736 689 +3 782 734 735 +3 737 642 47 +3 784 47 46 +3 781 46 734 +3 782 781 734 +3 735 736 782 +3 783 782 736 +3 784 783 737 +3 783 46 782 +3 785 784 737 +3 784 46 783 +3 785 737 47 +3 785 47 784 +3 507 40 41 +3 601 553 554 +3 507 506 40 +3 554 506 507 +3 508 507 41 +3 554 553 506 +3 509 508 41 +3 555 554 507 +3 556 509 41 +3 555 508 509 +3 553 40 505 +3 553 505 506 +3 555 507 508 +3 601 600 553 +3 556 555 509 +3 601 554 555 +3 603 556 41 +3 602 555 556 +3 600 48 40 +3 600 40 553 +3 602 601 555 +3 649 648 602 +3 603 602 556 +3 648 601 602 +3 650 603 41 +3 649 602 603 +3 648 48 600 +3 648 600 601 +3 650 649 603 +3 697 696 650 +3 650 41 48 +3 696 649 650 +3 696 48 648 +3 696 648 649 +3 697 650 48 +3 744 697 48 +3 744 48 696 +3 744 696 697 +3 694 693 646 +3 646 47 40 +3 694 646 647 +3 646 40 599 +3 695 647 40 +3 647 646 599 +3 741 693 694 +3 693 47 646 +3 742 741 694 +3 788 741 742 +3 743 695 40 +3 695 694 647 +3 740 47 693 +3 741 740 693 +3 742 694 695 +3 787 47 740 +3 789 788 742 +3 789 48 47 +3 743 40 48 +3 743 742 695 +3 740 788 787 +3 740 741 788 +3 789 742 743 +3 788 47 787 +3 790 789 743 +3 789 47 788 +3 790 743 48 +3 790 48 789 +3 809 42 43 +3 856 808 809 +3 810 809 43 +3 856 855 808 +3 811 810 43 +3 857 856 809 +3 858 811 43 +3 858 857 810 +3 951 903 904 +3 855 42 808 +3 857 809 810 +3 904 856 857 +3 858 810 811 +3 904 903 856 +3 905 858 43 +3 905 904 857 +3 950 42 855 +3 903 855 856 +3 905 857 858 +3 951 950 903 +3 952 905 43 +3 951 904 905 +3 950 50 42 +3 950 855 903 +3 952 951 905 +3 999 998 952 +3 952 43 50 +3 998 951 952 +3 998 50 950 +3 998 950 951 +3 999 952 50 +3 1046 999 50 +3 1046 50 998 +3 1046 998 999 +3 997 996 949 +3 949 49 42 +3 1044 1043 997 +3 996 49 949 +3 1045 997 42 +3 1043 49 996 +3 1091 1044 1045 +3 1043 996 997 +3 1045 1044 997 +3 1090 49 1043 +3 1045 42 50 +3 1091 1090 1044 +3 1091 50 49 +3 1090 1043 1044 +3 1092 1091 1045 +3 1091 49 1090 +3 1093 1092 1045 +3 1092 50 1091 +3 1093 1045 50 +3 1093 50 1092 +3 814 813 43 +3 43 1051 51 +3 814 43 44 +3 861 813 814 +3 815 814 44 +3 861 860 813 +3 816 815 44 +3 862 861 814 +3 817 816 44 +3 863 862 815 +3 817 44 51 +3 863 816 817 +3 43 812 1051 +3 860 812 813 +3 862 814 815 +3 909 861 862 +3 863 815 816 +3 909 908 861 +3 910 863 817 +3 910 909 862 +3 1051 1099 51 +3 908 860 861 +3 910 862 863 +3 957 909 910 +3 957 910 817 +3 957 956 909 +3 1051 908 956 +3 956 908 909 +3 1099 957 817 +3 1051 1004 1099 +3 1004 1051 956 +3 1004 956 957 +3 1051 812 860 +3 1051 860 908 +3 1099 817 51 +3 1099 1004 957 +3 954 953 906 +3 953 50 43 +3 954 906 907 +3 906 43 859 +3 955 907 43 +3 907 906 859 +3 1001 953 954 +3 953 43 906 +3 1001 954 955 +3 1049 1002 1003 +3 1003 955 43 +3 955 954 907 +3 1000 50 953 +3 1001 1000 953 +3 1002 1001 955 +3 1094 50 1047 +3 1049 1048 1002 +3 1001 1048 1047 +3 1003 43 51 +3 1003 1002 955 +3 1047 50 1000 +3 1047 1000 1001 +3 1096 1049 1050 +3 1001 1002 1048 +3 1050 1049 1003 +3 1095 50 1094 +3 1098 1050 1003 +3 1095 1048 1049 +3 1094 1047 1048 +3 1095 1094 1048 +3 1096 51 50 +3 1096 1095 1049 +3 1097 1096 1050 +3 1096 50 1095 +3 1098 1097 1050 +3 1097 51 1096 +3 1098 1003 51 +3 1098 51 1097 +3 820 819 44 +3 914 866 867 +3 820 44 45 +3 867 819 820 +3 821 820 45 +3 867 866 819 +3 822 821 45 +3 868 867 820 +3 869 822 45 +3 869 868 821 +3 913 44 818 +3 866 818 819 +3 868 820 821 +3 914 913 866 +3 869 821 822 +3 915 914 867 +3 916 869 45 +3 916 915 868 +3 913 52 44 +3 913 818 866 +3 915 867 868 +3 962 914 915 +3 916 868 869 +3 962 961 914 +3 963 916 45 +3 962 915 916 +3 961 52 913 +3 961 913 914 +3 963 962 916 +3 1010 1009 963 +3 963 45 52 +3 1009 962 963 +3 1009 52 961 +3 1009 961 962 +3 1010 963 52 +3 1057 1010 52 +3 1057 52 1009 +3 1057 1009 1010 +3 1006 959 960 +3 959 51 44 +3 1007 1006 960 +3 959 44 912 +3 1008 960 44 +3 960 959 912 +3 1054 1053 1007 +3 1006 51 959 +3 1054 1007 1008 +3 1101 1054 1055 +3 1056 1008 44 +3 1008 1007 960 +3 1053 51 1006 +3 1053 1006 1007 +3 1055 1054 1008 +3 1053 1100 51 +3 1056 1055 1008 +3 1053 1054 1100 +3 1056 44 52 +3 1102 1101 1055 +3 1102 52 51 +3 1101 1100 1054 +3 1102 1055 1056 +3 1101 51 1100 +3 1103 1102 1056 +3 1102 51 1101 +3 1104 1103 1056 +3 1103 52 1102 +3 1104 1056 52 +3 1104 52 1103 +3 825 824 45 +3 1062 53 1014 +3 825 45 46 +3 872 824 825 +3 826 825 46 +3 872 871 824 +3 827 826 46 +3 873 872 825 +3 874 827 46 +3 874 873 826 +3 871 45 823 +3 871 823 824 +3 873 825 826 +3 920 872 873 +3 874 826 827 +3 920 919 872 +3 921 874 46 +3 921 920 873 +3 1014 871 919 +3 919 871 872 +3 921 873 874 +3 968 967 921 +3 968 921 46 +3 967 920 921 +3 1062 1015 53 +3 967 919 920 +3 968 46 53 +3 1015 968 53 +3 1014 53 45 +3 1014 45 871 +3 1014 967 1015 +3 1015 967 968 +3 1014 1015 1062 +3 967 1014 919 +3 965 964 917 +3 964 52 45 +3 965 917 918 +3 917 45 870 +3 918 45 53 +3 918 917 870 +3 1012 964 965 +3 964 45 917 +3 1013 965 918 +3 1060 1059 1013 +3 1011 52 964 +3 1012 1011 964 +3 1013 1012 965 +3 1105 52 1058 +3 1061 1013 918 +3 1012 1059 1058 +3 1058 52 1011 +3 1058 1011 1012 +3 1106 1059 1060 +3 1012 1013 1059 +3 1061 1060 1013 +3 1107 53 52 +3 1061 918 53 +3 1107 1106 1060 +3 1105 1058 1059 +3 1106 1105 1059 +3 1107 1060 1061 +3 1106 52 1105 +3 1108 1107 1061 +3 1107 52 1106 +3 1109 1108 1061 +3 1108 53 1107 +3 1109 1061 53 +3 1109 53 1108 +3 831 830 46 +3 877 829 830 +3 831 46 47 +3 877 876 829 +3 832 831 47 +3 878 877 830 +3 833 832 47 +3 879 878 831 +3 880 833 47 +3 880 879 832 +3 876 54 46 +3 876 46 829 +3 878 830 831 +3 925 877 878 +3 879 831 832 +3 925 924 877 +3 880 832 833 +3 926 925 878 +3 927 880 47 +3 926 879 880 +3 876 1115 54 +3 924 876 877 +3 926 878 879 +3 973 972 926 +3 927 926 880 +3 972 925 926 +3 974 927 47 +3 973 926 927 +3 876 924 1115 +3 972 924 925 +3 974 973 927 +3 1021 1020 974 +3 974 47 54 +3 1020 973 974 +3 1115 1068 54 +3 1020 972 973 +3 1021 974 54 +3 1068 1021 54 +3 1115 1020 1068 +3 1068 1020 1021 +3 1115 924 972 +3 1115 972 1020 +3 923 875 828 +3 969 53 46 +3 970 969 922 +3 875 46 828 +3 970 922 923 +3 922 46 875 +3 971 923 828 +3 923 922 875 +3 1017 969 970 +3 969 46 922 +3 1018 1017 970 +3 1065 1064 1018 +3 1019 828 46 +3 971 970 923 +3 1016 53 969 +3 1017 1016 969 +3 1018 970 971 +3 1064 1017 1018 +3 1065 1018 1019 +3 1064 1063 1017 +3 1067 1019 46 +3 1019 1018 971 +3 1063 53 1016 +3 1063 1016 1017 +3 1112 1065 1066 +3 1110 1111 53 +3 1066 1065 1019 +3 1111 1110 1064 +3 1113 1112 1066 +3 1111 1064 1065 +3 1067 46 54 +3 1067 1066 1019 +3 1110 53 1063 +3 1110 1063 1064 +3 1113 54 53 +3 1112 1111 1065 +3 1113 1066 1067 +3 1112 53 1111 +3 1114 1113 1067 +3 1113 53 1112 +3 1114 1067 54 +3 1114 54 1113 +3 836 835 47 +3 978 977 931 +3 836 47 48 +3 883 835 836 +3 837 836 48 +3 883 882 835 +3 838 837 48 +3 884 883 836 +3 885 838 48 +3 884 837 838 +3 882 47 834 +3 882 834 835 +3 884 836 837 +3 931 883 884 +3 885 884 838 +3 931 930 883 +3 932 885 48 +3 931 884 885 +3 977 47 882 +3 930 882 883 +3 932 931 885 +3 977 930 931 +3 979 932 48 +3 978 931 932 +3 977 55 47 +3 977 882 930 +3 979 978 932 +3 1026 1025 979 +3 979 48 55 +3 1025 978 979 +3 1025 55 977 +3 1025 977 978 +3 1026 979 55 +3 1073 1026 55 +3 1073 55 1025 +3 1073 1025 1026 +3 976 928 881 +3 975 54 47 +3 976 975 928 +3 928 47 881 +3 1023 975 976 +3 975 47 928 +3 1024 976 881 +3 1071 1070 1024 +3 1022 54 975 +3 1023 1022 975 +3 1024 1023 976 +3 1069 1116 54 +3 1072 1024 881 +3 1070 1022 1023 +3 1069 54 1022 +3 1070 1069 1022 +3 1117 1070 1071 +3 1023 1024 1070 +3 1072 1071 1024 +3 1069 1070 1116 +3 1072 881 55 +3 1118 1117 1071 +3 1118 55 54 +3 1117 1116 1070 +3 1118 1071 1072 +3 1117 54 1116 +3 1119 1118 1072 +3 1118 54 1117 +3 1120 1119 1072 +3 1119 55 1118 +3 1120 1072 55 +3 1120 55 1119 +3 56 104 28 +3 58 105 28 +3 87 134 34 +3 104 105 28 +3 134 181 34 +3 181 228 34 +3 228 275 34 +3 275 322 34 +3 322 369 34 +3 369 416 41 +3 416 463 41 +3 463 510 41 +3 510 557 41 +3 557 604 41 +3 604 651 41 +3 651 698 48 +3 698 745 48 +3 745 792 48 +3 792 839 48 +3 839 886 48 +3 886 933 48 +3 933 980 48 +3 980 1027 55 +3 1027 1074 55 +3 1074 1121 55 +3 1138 1137 49 +3 1139 1138 50 +3 1140 1139 50 +3 1141 1140 50 +3 1142 1141 50 +3 1143 1142 50 +3 1144 1143 51 +3 1145 1144 51 +3 1146 1145 51 +3 1147 1146 51 +3 1148 1147 51 +3 1149 1148 51 +3 1150 1149 52 +3 1151 1150 52 +3 1152 1151 52 +3 1153 1152 52 +3 1154 1153 52 +3 1155 1154 53 +3 1156 1155 53 +3 1157 1156 53 +3 1158 1157 53 +3 1159 1158 53 +3 1160 1159 53 +3 1161 1160 54 +3 1162 1161 54 +3 1163 1162 54 +3 1164 1163 54 +3 1165 1164 54 +3 1166 1165 55 +3 1167 1166 55 +3 1121 1168 55 +3 1168 1167 55 +3 56 57 104 +3 57 58 105 +3 57 105 104 +3 87 88 135 +3 87 135 134 +3 88 89 136 +3 88 136 135 +3 89 90 137 +3 89 137 136 +3 90 91 138 +3 90 138 137 +3 91 92 139 +3 91 139 138 +3 92 93 140 +3 92 140 139 +3 93 94 141 +3 93 141 140 +3 94 95 142 +3 94 142 141 +3 95 96 143 +3 95 143 142 +3 96 97 144 +3 96 144 143 +3 97 98 145 +3 97 145 144 +3 98 99 146 +3 98 146 145 +3 99 100 147 +3 99 147 146 +3 100 101 148 +3 100 148 147 +3 101 102 149 +3 101 149 148 +3 134 135 182 +3 134 182 181 +3 135 136 183 +3 135 183 182 +3 136 137 184 +3 136 184 183 +3 137 138 185 +3 137 185 184 +3 138 139 186 +3 138 186 185 +3 139 140 187 +3 139 187 186 +3 140 141 188 +3 140 188 187 +3 141 142 189 +3 141 189 188 +3 142 143 190 +3 142 190 189 +3 143 144 191 +3 143 191 190 +3 144 145 192 +3 144 192 191 +3 145 146 193 +3 145 193 192 +3 146 147 194 +3 146 194 193 +3 147 148 195 +3 147 195 194 +3 148 149 196 +3 148 196 195 +3 181 182 229 +3 181 229 228 +3 182 183 230 +3 182 230 229 +3 183 184 231 +3 183 231 230 +3 184 185 232 +3 184 232 231 +3 185 186 233 +3 185 233 232 +3 186 187 234 +3 186 234 233 +3 187 188 235 +3 187 235 234 +3 188 189 236 +3 188 236 235 +3 189 190 237 +3 189 237 236 +3 190 191 238 +3 190 238 237 +3 191 192 239 +3 191 239 238 +3 192 193 240 +3 192 240 239 +3 193 194 241 +3 193 241 240 +3 194 195 242 +3 194 242 241 +3 195 196 243 +3 195 243 242 +3 228 229 276 +3 228 276 275 +3 229 230 277 +3 229 277 276 +3 230 231 278 +3 230 278 277 +3 231 232 279 +3 231 279 278 +3 232 233 280 +3 232 280 279 +3 233 234 281 +3 233 281 280 +3 234 235 282 +3 234 282 281 +3 235 236 283 +3 235 283 282 +3 236 237 284 +3 236 284 283 +3 237 238 285 +3 237 285 284 +3 238 239 286 +3 238 286 285 +3 239 240 287 +3 239 287 286 +3 240 241 288 +3 240 288 287 +3 241 242 289 +3 241 289 288 +3 242 243 290 +3 242 290 289 +3 275 276 323 +3 275 323 322 +3 276 277 324 +3 276 324 323 +3 277 278 325 +3 277 325 324 +3 278 279 326 +3 278 326 325 +3 279 280 327 +3 279 327 326 +3 280 281 328 +3 280 328 327 +3 281 282 329 +3 281 329 328 +3 282 283 330 +3 282 330 329 +3 283 284 331 +3 283 331 330 +3 284 285 332 +3 284 332 331 +3 285 286 333 +3 285 333 332 +3 286 287 334 +3 286 334 333 +3 287 288 335 +3 287 335 334 +3 288 289 336 +3 288 336 335 +3 289 290 337 +3 289 337 336 +3 322 323 370 +3 322 370 369 +3 323 324 371 +3 323 371 370 +3 324 325 372 +3 324 372 371 +3 325 326 373 +3 325 373 372 +3 326 327 374 +3 326 374 373 +3 327 328 375 +3 327 375 374 +3 328 329 376 +3 328 376 375 +3 329 330 377 +3 329 377 376 +3 330 331 378 +3 330 378 377 +3 331 332 379 +3 331 379 378 +3 332 333 380 +3 332 380 379 +3 333 334 381 +3 333 381 380 +3 334 335 382 +3 334 382 381 +3 335 336 383 +3 335 383 382 +3 336 337 384 +3 336 384 383 +3 369 370 417 +3 369 417 416 +3 370 371 418 +3 370 418 417 +3 371 372 419 +3 371 419 418 +3 372 373 420 +3 372 420 419 +3 373 374 421 +3 373 421 420 +3 374 375 422 +3 374 422 421 +3 375 376 423 +3 375 423 422 +3 376 377 424 +3 376 424 423 +3 377 378 425 +3 377 425 424 +3 378 379 426 +3 378 426 425 +3 379 380 427 +3 379 427 426 +3 380 381 428 +3 380 428 427 +3 381 382 429 +3 381 429 428 +3 382 383 430 +3 382 430 429 +3 383 384 431 +3 383 431 430 +3 416 417 464 +3 416 464 463 +3 417 418 465 +3 417 465 464 +3 418 419 466 +3 418 466 465 +3 419 420 467 +3 419 467 466 +3 420 421 468 +3 420 468 467 +3 421 422 469 +3 421 469 468 +3 422 423 470 +3 422 470 469 +3 423 424 471 +3 423 471 470 +3 424 425 472 +3 424 472 471 +3 425 426 473 +3 425 473 472 +3 426 427 474 +3 426 474 473 +3 427 428 475 +3 427 475 474 +3 428 429 476 +3 428 476 475 +3 429 430 477 +3 429 477 476 +3 430 431 478 +3 430 478 477 +3 463 464 511 +3 463 511 510 +3 464 465 512 +3 464 512 511 +3 465 466 513 +3 465 513 512 +3 466 467 514 +3 466 514 513 +3 467 468 515 +3 467 515 514 +3 468 469 516 +3 468 516 515 +3 469 470 517 +3 469 517 516 +3 470 471 518 +3 470 518 517 +3 471 472 519 +3 471 519 518 +3 472 473 520 +3 472 520 519 +3 473 474 521 +3 473 521 520 +3 474 475 522 +3 474 522 521 +3 475 476 523 +3 475 523 522 +3 476 477 524 +3 476 524 523 +3 477 478 525 +3 477 525 524 +3 510 511 558 +3 510 558 557 +3 511 512 559 +3 511 559 558 +3 512 513 560 +3 512 560 559 +3 513 514 561 +3 513 561 560 +3 514 515 562 +3 514 562 561 +3 515 516 563 +3 515 563 562 +3 516 517 564 +3 516 564 563 +3 517 518 565 +3 517 565 564 +3 518 519 566 +3 518 566 565 +3 519 520 567 +3 519 567 566 +3 520 521 568 +3 520 568 567 +3 521 522 569 +3 521 569 568 +3 522 523 570 +3 522 570 569 +3 523 524 571 +3 523 571 570 +3 524 525 572 +3 524 572 571 +3 557 558 605 +3 557 605 604 +3 558 559 606 +3 558 606 605 +3 559 560 607 +3 559 607 606 +3 560 561 608 +3 560 608 607 +3 561 562 609 +3 561 609 608 +3 562 563 610 +3 562 610 609 +3 563 564 611 +3 563 611 610 +3 564 565 612 +3 564 612 611 +3 565 566 613 +3 565 613 612 +3 566 567 614 +3 566 614 613 +3 567 568 615 +3 567 615 614 +3 568 569 616 +3 568 616 615 +3 569 570 617 +3 569 617 616 +3 570 571 618 +3 570 618 617 +3 571 572 619 +3 571 619 618 +3 604 605 652 +3 604 652 651 +3 605 606 653 +3 605 653 652 +3 606 607 654 +3 606 654 653 +3 607 608 655 +3 607 655 654 +3 608 609 656 +3 608 656 655 +3 609 610 657 +3 609 657 656 +3 610 611 658 +3 610 658 657 +3 611 612 659 +3 611 659 658 +3 612 613 660 +3 612 660 659 +3 613 614 661 +3 613 661 660 +3 614 615 662 +3 614 662 661 +3 615 616 663 +3 615 663 662 +3 616 617 664 +3 616 664 663 +3 617 618 665 +3 617 665 664 +3 618 619 666 +3 618 666 665 +3 651 652 699 +3 651 699 698 +3 652 653 700 +3 652 700 699 +3 653 654 701 +3 653 701 700 +3 654 655 702 +3 654 702 701 +3 655 656 703 +3 655 703 702 +3 656 657 704 +3 656 704 703 +3 657 658 705 +3 657 705 704 +3 658 659 706 +3 658 706 705 +3 659 660 707 +3 659 707 706 +3 660 661 708 +3 660 708 707 +3 661 662 709 +3 661 709 708 +3 662 663 710 +3 662 710 709 +3 663 664 711 +3 663 711 710 +3 664 665 712 +3 664 712 711 +3 665 666 713 +3 665 713 712 +3 698 699 746 +3 698 746 745 +3 699 700 747 +3 699 747 746 +3 700 701 748 +3 700 748 747 +3 701 702 749 +3 701 749 748 +3 702 703 750 +3 702 750 749 +3 703 704 751 +3 703 751 750 +3 704 705 752 +3 704 752 751 +3 705 706 753 +3 705 753 752 +3 706 707 754 +3 706 754 753 +3 707 708 755 +3 707 755 754 +3 708 709 756 +3 708 756 755 +3 709 710 757 +3 709 757 756 +3 710 711 758 +3 710 758 757 +3 711 712 759 +3 711 759 758 +3 712 713 760 +3 712 760 759 +3 745 746 793 +3 745 793 792 +3 746 747 794 +3 746 794 793 +3 747 748 795 +3 747 795 794 +3 748 749 796 +3 748 796 795 +3 749 750 797 +3 749 797 796 +3 750 751 798 +3 750 798 797 +3 751 752 799 +3 751 799 798 +3 752 753 800 +3 752 800 799 +3 753 754 801 +3 753 801 800 +3 754 755 802 +3 754 802 801 +3 755 756 803 +3 755 803 802 +3 756 757 804 +3 756 804 803 +3 757 758 805 +3 757 805 804 +3 758 759 806 +3 758 806 805 +3 759 760 807 +3 759 807 806 +3 792 793 840 +3 792 840 839 +3 793 794 841 +3 793 841 840 +3 794 795 842 +3 794 842 841 +3 795 796 843 +3 795 843 842 +3 796 797 844 +3 796 844 843 +3 797 798 845 +3 797 845 844 +3 798 799 846 +3 798 846 845 +3 799 800 847 +3 799 847 846 +3 800 801 848 +3 800 848 847 +3 801 802 849 +3 801 849 848 +3 802 803 850 +3 802 850 849 +3 803 804 851 +3 803 851 850 +3 804 805 852 +3 804 852 851 +3 805 806 853 +3 805 853 852 +3 806 807 854 +3 806 854 853 +3 839 840 887 +3 839 887 886 +3 840 841 888 +3 840 888 887 +3 841 842 889 +3 841 889 888 +3 842 843 890 +3 842 890 889 +3 843 844 891 +3 843 891 890 +3 844 845 892 +3 844 892 891 +3 845 846 893 +3 845 893 892 +3 846 847 894 +3 846 894 893 +3 847 848 895 +3 847 895 894 +3 848 849 896 +3 848 896 895 +3 849 850 897 +3 849 897 896 +3 850 851 898 +3 850 898 897 +3 851 852 899 +3 851 899 898 +3 852 853 900 +3 852 900 899 +3 853 854 901 +3 853 901 900 +3 886 887 934 +3 886 934 933 +3 887 888 935 +3 887 935 934 +3 888 889 936 +3 888 936 935 +3 889 890 937 +3 889 937 936 +3 890 891 938 +3 890 938 937 +3 891 892 939 +3 891 939 938 +3 892 893 940 +3 892 940 939 +3 893 894 941 +3 893 941 940 +3 894 895 942 +3 894 942 941 +3 895 896 943 +3 895 943 942 +3 896 897 944 +3 896 944 943 +3 897 898 945 +3 897 945 944 +3 898 899 946 +3 898 946 945 +3 899 900 947 +3 899 947 946 +3 900 901 948 +3 900 948 947 +3 933 934 981 +3 933 981 980 +3 934 935 982 +3 934 982 981 +3 935 936 983 +3 935 983 982 +3 936 937 984 +3 936 984 983 +3 937 938 985 +3 937 985 984 +3 938 939 986 +3 938 986 985 +3 939 940 987 +3 939 987 986 +3 940 941 988 +3 940 988 987 +3 941 942 989 +3 941 989 988 +3 942 943 990 +3 942 990 989 +3 943 944 991 +3 943 991 990 +3 944 945 992 +3 944 992 991 +3 945 946 993 +3 945 993 992 +3 946 947 994 +3 946 994 993 +3 947 948 995 +3 947 995 994 +3 980 981 1028 +3 980 1028 1027 +3 981 982 1029 +3 981 1029 1028 +3 982 983 1030 +3 982 1030 1029 +3 983 984 1031 +3 983 1031 1030 +3 984 985 1032 +3 984 1032 1031 +3 985 986 1033 +3 985 1033 1032 +3 986 987 1034 +3 986 1034 1033 +3 987 988 1035 +3 987 1035 1034 +3 988 989 1036 +3 988 1036 1035 +3 989 990 1037 +3 989 1037 1036 +3 990 991 1038 +3 990 1038 1037 +3 991 992 1039 +3 991 1039 1038 +3 992 993 1040 +3 992 1040 1039 +3 993 994 1041 +3 993 1041 1040 +3 994 995 1042 +3 994 1042 1041 +3 1027 1028 1075 +3 1027 1075 1074 +3 1028 1029 1076 +3 1028 1076 1075 +3 1029 1030 1077 +3 1029 1077 1076 +3 1030 1031 1078 +3 1030 1078 1077 +3 1031 1032 1079 +3 1031 1079 1078 +3 1032 1033 1080 +3 1032 1080 1079 +3 1033 1034 1081 +3 1033 1081 1080 +3 1034 1035 1082 +3 1034 1082 1081 +3 1035 1036 1083 +3 1035 1083 1082 +3 1036 1037 1084 +3 1036 1084 1083 +3 1037 1038 1085 +3 1037 1085 1084 +3 1038 1039 1086 +3 1038 1086 1085 +3 1039 1040 1087 +3 1039 1087 1086 +3 1040 1041 1088 +3 1040 1088 1087 +3 1041 1042 1089 +3 1041 1089 1088 +3 1074 1075 1122 +3 1074 1122 1121 +3 1075 1076 1123 +3 1075 1123 1122 +3 1076 1077 1124 +3 1076 1124 1123 +3 1077 1078 1125 +3 1077 1125 1124 +3 1078 1079 1126 +3 1078 1126 1125 +3 1079 1080 1127 +3 1079 1127 1126 +3 1080 1081 1128 +3 1080 1128 1127 +3 1081 1082 1129 +3 1081 1129 1128 +3 1082 1083 1130 +3 1082 1130 1129 +3 1083 1084 1131 +3 1083 1131 1130 +3 1084 1085 1132 +3 1084 1132 1131 +3 1085 1086 1133 +3 1085 1133 1132 +3 1086 1087 1134 +3 1086 1134 1133 +3 1087 1088 1135 +3 1087 1135 1134 +3 1088 1089 1136 +3 1088 1136 1135 +3 1121 1122 1169 +3 1121 1169 1168 +3 1122 1123 1170 +3 1122 1170 1169 +3 1123 1124 1171 +3 1123 1171 1170 +3 1124 1125 1172 +3 1124 1172 1171 +3 1125 1126 1173 +3 1125 1173 1172 +3 1126 1127 1174 +3 1126 1174 1173 +3 1127 1128 1175 +3 1127 1175 1174 +3 1128 1129 1176 +3 1128 1176 1175 +3 1129 1130 1177 +3 1129 1177 1176 +3 1130 1131 1178 +3 1130 1178 1177 +3 1131 1132 1179 +3 1131 1179 1178 +3 1132 1133 1180 +3 1132 1180 1179 +3 1133 1134 1181 +3 1133 1181 1180 +3 1134 1135 1182 +3 1134 1182 1181 +3 1135 1136 1183 +3 1135 1183 1182 +3 1137 1138 1185 +3 1137 1185 1184 +3 1138 1139 1186 +3 1138 1186 1185 +3 1139 1140 1187 +3 1139 1187 1186 +3 1140 1141 1188 +3 1140 1188 1187 +3 1141 1142 1189 +3 1141 1189 1188 +3 1142 1143 1190 +3 1142 1190 1189 +3 1143 1144 1191 +3 1143 1191 1190 +3 1144 1145 1192 +3 1144 1192 1191 +3 1145 1146 1193 +3 1145 1193 1192 +3 1146 1147 1194 +3 1146 1194 1193 +3 1147 1148 1195 +3 1147 1195 1194 +3 1148 1149 1196 +3 1148 1196 1195 +3 1149 1150 1197 +3 1149 1197 1196 +3 1150 1151 1198 +3 1150 1198 1197 +3 1151 1152 1199 +3 1151 1199 1198 +3 1152 1153 1200 +3 1152 1200 1199 +3 1153 1154 1201 +3 1153 1201 1200 +3 1154 1155 1202 +3 1154 1202 1201 +3 1155 1156 1203 +3 1155 1203 1202 +3 1156 1157 1204 +3 1156 1204 1203 +3 1157 1158 1205 +3 1157 1205 1204 +3 1158 1159 1206 +3 1158 1206 1205 +3 1159 1160 1207 +3 1159 1207 1206 +3 1160 1161 1208 +3 1160 1208 1207 +3 1161 1162 1209 +3 1161 1209 1208 +3 1162 1163 1210 +3 1162 1210 1209 +3 1163 1164 1211 +3 1163 1211 1210 +3 1164 1165 1212 +3 1164 1212 1211 +3 1165 1166 1213 +3 1165 1213 1212 +3 1166 1167 1214 +3 1166 1214 1213 +3 1167 1168 1215 +3 1167 1215 1214 +3 1168 1169 1216 +3 1168 1216 1215 +3 1169 1170 1217 +3 1169 1217 1216 +3 1170 1171 1218 +3 1170 1218 1217 +3 1171 1172 1219 +3 1171 1219 1218 +3 1172 1173 1220 +3 1172 1220 1219 +3 1173 1174 1221 +3 1173 1221 1220 +3 1174 1175 1222 +3 1174 1222 1221 +3 1175 1176 1223 +3 1175 1223 1222 +3 1176 1177 1224 +3 1176 1224 1223 +3 1177 1178 1225 +3 1177 1225 1224 +3 1178 1179 1226 +3 1178 1226 1225 +3 1179 1180 1227 +3 1179 1227 1226 +3 1180 1181 1228 +3 1180 1228 1227 +3 1181 1182 1229 +3 1181 1229 1228 +3 1182 1183 1230 +3 1182 1230 1229 +3 1184 1185 1232 +3 1184 1232 1231 +3 1185 1186 1233 +3 1185 1233 1232 +3 1186 1187 1234 +3 1186 1234 1233 +3 1187 1188 1235 +3 1187 1235 1234 +3 1188 1189 1236 +3 1188 1236 1235 +3 1189 1190 1237 +3 1189 1237 1236 +3 1190 1191 1238 +3 1190 1238 1237 +3 1191 1192 1239 +3 1191 1239 1238 +3 1192 1193 1240 +3 1192 1240 1239 +3 1193 1194 1241 +3 1193 1241 1240 +3 1194 1195 1242 +3 1194 1242 1241 +3 1195 1196 1243 +3 1195 1243 1242 +3 1196 1197 1244 +3 1196 1244 1243 +3 1197 1198 1245 +3 1197 1245 1244 +3 1198 1199 1246 +3 1198 1246 1245 +3 1199 1200 1247 +3 1199 1247 1246 +3 1200 1201 1248 +3 1200 1248 1247 +3 1201 1202 1249 +3 1201 1249 1248 +3 1202 1203 1250 +3 1202 1250 1249 +3 1203 1204 1251 +3 1203 1251 1250 +3 1204 1205 1252 +3 1204 1252 1251 +3 1205 1206 1253 +3 1205 1253 1252 +3 1206 1207 1254 +3 1206 1254 1253 +3 1207 1208 1255 +3 1207 1255 1254 +3 1208 1209 1256 +3 1208 1256 1255 +3 1209 1210 1257 +3 1209 1257 1256 +3 1210 1211 1258 +3 1210 1258 1257 +3 1211 1212 1259 +3 1211 1259 1258 +3 1212 1213 1260 +3 1212 1260 1259 +3 1213 1214 1261 +3 1213 1261 1260 +3 1214 1215 1262 +3 1214 1262 1261 +3 1215 1216 1263 +3 1215 1263 1262 +3 1216 1217 1264 +3 1216 1264 1263 +3 1217 1218 1265 +3 1217 1265 1264 +3 1218 1219 1266 +3 1218 1266 1265 +3 1219 1220 1267 +3 1219 1267 1266 +3 1220 1221 1268 +3 1220 1268 1267 +3 1221 1222 1269 +3 1221 1269 1268 +3 1222 1223 1270 +3 1222 1270 1269 +3 1223 1224 1271 +3 1223 1271 1270 +3 1224 1225 1272 +3 1224 1272 1271 +3 1225 1226 1273 +3 1225 1273 1272 +3 1226 1227 1274 +3 1226 1274 1273 +3 1227 1228 1275 +3 1227 1275 1274 +3 1228 1229 1276 +3 1228 1276 1275 +3 1229 1230 1277 +3 1229 1277 1276 +3 1231 1232 1279 +3 1231 1279 1278 +3 1232 1233 1280 +3 1232 1280 1279 +3 1233 1234 1281 +3 1233 1281 1280 +3 1234 1235 1282 +3 1234 1282 1281 +3 1235 1236 1283 +3 1235 1283 1282 +3 1236 1237 1284 +3 1236 1284 1283 +3 1237 1238 1285 +3 1237 1285 1284 +3 1238 1239 1286 +3 1238 1286 1285 +3 1239 1240 1287 +3 1239 1287 1286 +3 1240 1241 1288 +3 1240 1288 1287 +3 1241 1242 1289 +3 1241 1289 1288 +3 1242 1243 1290 +3 1242 1290 1289 +3 1243 1244 1291 +3 1243 1291 1290 +3 1244 1245 1292 +3 1244 1292 1291 +3 1245 1246 1293 +3 1245 1293 1292 +3 1246 1247 1294 +3 1246 1294 1293 +3 1247 1248 1295 +3 1247 1295 1294 +3 1248 1249 1296 +3 1248 1296 1295 +3 1249 1250 1297 +3 1249 1297 1296 +3 1250 1251 1298 +3 1250 1298 1297 +3 1251 1252 1299 +3 1251 1299 1298 +3 1252 1253 1300 +3 1252 1300 1299 +3 1253 1254 1301 +3 1253 1301 1300 +3 1254 1255 1302 +3 1254 1302 1301 +3 1255 1256 1303 +3 1255 1303 1302 +3 1256 1257 1304 +3 1256 1304 1303 +3 1257 1258 1305 +3 1257 1305 1304 +3 1258 1259 1306 +3 1258 1306 1305 +3 1259 1260 1307 +3 1259 1307 1306 +3 1260 1261 1308 +3 1260 1308 1307 +3 1261 1262 1309 +3 1261 1309 1308 +3 1262 1263 1310 +3 1262 1310 1309 +3 1263 1264 1311 +3 1263 1311 1310 +3 1264 1265 1312 +3 1264 1312 1311 +3 1265 1266 1313 +3 1265 1313 1312 +3 1266 1267 1314 +3 1266 1314 1313 +3 1267 1268 1315 +3 1267 1315 1314 +3 1268 1269 1316 +3 1268 1316 1315 +3 1269 1270 1317 +3 1269 1317 1316 +3 1270 1271 1318 +3 1270 1318 1317 +3 1271 1272 1319 +3 1271 1319 1318 +3 1272 1273 1320 +3 1272 1320 1319 +3 1273 1274 1321 +3 1273 1321 1320 +3 1274 1275 1322 +3 1274 1322 1321 +3 1275 1276 1323 +3 1275 1323 1322 +3 1276 1277 1324 +3 1276 1324 1323 +3 1278 1279 1326 +3 1278 1326 1325 +3 1279 1280 1327 +3 1279 1327 1326 +3 1280 1281 1328 +3 1280 1328 1327 +3 1281 1282 1329 +3 1281 1329 1328 +3 1282 1283 1330 +3 1282 1330 1329 +3 1283 1284 1331 +3 1283 1331 1330 +3 1284 1285 1332 +3 1284 1332 1331 +3 1285 1286 1333 +3 1285 1333 1332 +3 1286 1287 1334 +3 1286 1334 1333 +3 1287 1288 1335 +3 1287 1335 1334 +3 1288 1289 1336 +3 1288 1336 1335 +3 1289 1290 1337 +3 1289 1337 1336 +3 1290 1291 1338 +3 1290 1338 1337 +3 1291 1292 1339 +3 1291 1339 1338 +3 1292 1293 1340 +3 1292 1340 1339 +3 1293 1294 1341 +3 1293 1341 1340 +3 1294 1295 1342 +3 1294 1342 1341 +3 1295 1296 1343 +3 1295 1343 1342 +3 1296 1297 1344 +3 1296 1344 1343 +3 1297 1298 1345 +3 1297 1345 1344 +3 1298 1299 1346 +3 1298 1346 1345 +3 1299 1300 1347 +3 1299 1347 1346 +3 1300 1301 1348 +3 1300 1348 1347 +3 1301 1302 1349 +3 1301 1349 1348 +3 1302 1303 1350 +3 1302 1350 1349 +3 1303 1304 1351 +3 1303 1351 1350 +3 1304 1305 1352 +3 1304 1352 1351 +3 1305 1306 1353 +3 1305 1353 1352 +3 1306 1307 1354 +3 1306 1354 1353 +3 1307 1308 1355 +3 1307 1355 1354 +3 1308 1309 1356 +3 1308 1356 1355 +3 1309 1310 1357 +3 1309 1357 1356 +3 1310 1311 1358 +3 1310 1358 1357 +3 1311 1312 1359 +3 1311 1359 1358 +3 1312 1313 1360 +3 1312 1360 1359 +3 1313 1314 1361 +3 1313 1361 1360 +3 1314 1315 1362 +3 1314 1362 1361 +3 1315 1316 1363 +3 1315 1363 1362 +3 1316 1317 1364 +3 1316 1364 1363 +3 1317 1318 1365 +3 1317 1365 1364 +3 1318 1319 1366 +3 1318 1366 1365 +3 1319 1320 1367 +3 1319 1367 1366 +3 1320 1321 1368 +3 1320 1368 1367 +3 1321 1322 1369 +3 1321 1369 1368 +3 1322 1323 1370 +3 1322 1370 1369 +3 1323 1324 1371 +3 1323 1371 1370 +3 1325 1326 1373 +3 1325 1373 1372 +3 1326 1327 1374 +3 1326 1374 1373 +3 1327 1328 1375 +3 1327 1375 1374 +3 1328 1329 1376 +3 1328 1376 1375 +3 1329 1330 1377 +3 1329 1377 1376 +3 1330 1331 1378 +3 1330 1378 1377 +3 1331 1332 1379 +3 1331 1379 1378 +3 1332 1333 1380 +3 1332 1380 1379 +3 1333 1334 1381 +3 1333 1381 1380 +3 1334 1335 1382 +3 1334 1382 1381 +3 1335 1336 1383 +3 1335 1383 1382 +3 1336 1337 1384 +3 1336 1384 1383 +3 1337 1338 1385 +3 1337 1385 1384 +3 1338 1339 1386 +3 1338 1386 1385 +3 1339 1340 1387 +3 1339 1387 1386 +3 1340 1341 1388 +3 1340 1388 1387 +3 1341 1342 1389 +3 1341 1389 1388 +3 1342 1343 1390 +3 1342 1390 1389 +3 1343 1344 1391 +3 1343 1391 1390 +3 1344 1345 1392 +3 1344 1392 1391 +3 1345 1346 1393 +3 1345 1393 1392 +3 1346 1347 1394 +3 1346 1394 1393 +3 1347 1348 1395 +3 1347 1395 1394 +3 1348 1349 1396 +3 1348 1396 1395 +3 1349 1350 1397 +3 1349 1397 1396 +3 1350 1351 1398 +3 1350 1398 1397 +3 1351 1352 1399 +3 1351 1399 1398 +3 1352 1353 1400 +3 1352 1400 1399 +3 1353 1354 1401 +3 1353 1401 1400 +3 1354 1355 1402 +3 1354 1402 1401 +3 1355 1356 1403 +3 1355 1403 1402 +3 1356 1357 1404 +3 1356 1404 1403 +3 1357 1358 1405 +3 1357 1405 1404 +3 1358 1359 1406 +3 1358 1406 1405 +3 1359 1360 1407 +3 1359 1407 1406 +3 1360 1361 1408 +3 1360 1408 1407 +3 1361 1362 1409 +3 1361 1409 1408 +3 1362 1363 1410 +3 1362 1410 1409 +3 1363 1364 1411 +3 1363 1411 1410 +3 1364 1365 1412 +3 1364 1412 1411 +3 1365 1366 1413 +3 1365 1413 1412 +3 1366 1367 1414 +3 1366 1414 1413 +3 1367 1368 1415 +3 1367 1415 1414 +3 1368 1369 1416 +3 1368 1416 1415 +3 1369 1370 1417 +3 1369 1417 1416 +3 1370 1371 1418 +3 1370 1418 1417 +3 1372 1373 1420 +3 1372 1420 1419 +3 1373 1374 1421 +3 1373 1421 1420 +3 1374 1375 1422 +3 1374 1422 1421 +3 1375 1376 1423 +3 1375 1423 1422 +3 1376 1377 1424 +3 1376 1424 1423 +3 1377 1378 1425 +3 1377 1425 1424 +3 1378 1379 1426 +3 1378 1426 1425 +3 1379 1380 1427 +3 1379 1427 1426 +3 1380 1381 1428 +3 1380 1428 1427 +3 1381 1382 1429 +3 1381 1429 1428 +3 1382 1383 1430 +3 1382 1430 1429 +3 1383 1384 1431 +3 1383 1431 1430 +3 1384 1385 1432 +3 1384 1432 1431 +3 1385 1386 1433 +3 1385 1433 1432 +3 1386 1387 1434 +3 1386 1434 1433 +3 1387 1388 1435 +3 1387 1435 1434 +3 1388 1389 1436 +3 1388 1436 1435 +3 1389 1390 1437 +3 1389 1437 1436 +3 1390 1391 1438 +3 1390 1438 1437 +3 1391 1392 1439 +3 1391 1439 1438 +3 1392 1393 1440 +3 1392 1440 1439 +3 1393 1394 1441 +3 1393 1441 1440 +3 1394 1395 1442 +3 1394 1442 1441 +3 1395 1396 1443 +3 1395 1443 1442 +3 1396 1397 1444 +3 1396 1444 1443 +3 1397 1398 1445 +3 1397 1445 1444 +3 1398 1399 1446 +3 1398 1446 1445 +3 1399 1400 1447 +3 1399 1447 1446 +3 1400 1401 1448 +3 1400 1448 1447 +3 1401 1402 1449 +3 1401 1449 1448 +3 1402 1403 1450 +3 1402 1450 1449 +3 1403 1404 1451 +3 1403 1451 1450 +3 1404 1405 1452 +3 1404 1452 1451 +3 1405 1406 1453 +3 1405 1453 1452 +3 1406 1407 1454 +3 1406 1454 1453 +3 1407 1408 1455 +3 1407 1455 1454 +3 1408 1409 1456 +3 1408 1456 1455 +3 1409 1410 1457 +3 1409 1457 1456 +3 1410 1411 1458 +3 1410 1458 1457 +3 1411 1412 1459 +3 1411 1459 1458 +3 1412 1413 1460 +3 1412 1460 1459 +3 1413 1414 1461 +3 1413 1461 1460 +3 1414 1415 1462 +3 1414 1462 1461 +3 1415 1416 1463 +3 1415 1463 1462 +3 1416 1417 1464 +3 1416 1464 1463 +3 1417 1418 1465 +3 1417 1465 1464 +3 1419 1420 1467 +3 1419 1467 1466 +3 1420 1421 1468 +3 1420 1468 1467 +3 1421 1422 1469 +3 1421 1469 1468 +3 1422 1423 1470 +3 1422 1470 1469 +3 1423 1424 1471 +3 1423 1471 1470 +3 1424 1425 1472 +3 1424 1472 1471 +3 1425 1426 1473 +3 1425 1473 1472 +3 1426 1427 1474 +3 1426 1474 1473 +3 1427 1428 1475 +3 1427 1475 1474 +3 1428 1429 1476 +3 1428 1476 1475 +3 1429 1430 1477 +3 1429 1477 1476 +3 1430 1431 1478 +3 1430 1478 1477 +3 1431 1432 1479 +3 1431 1479 1478 +3 1432 1433 1480 +3 1432 1480 1479 +3 1433 1434 1481 +3 1433 1481 1480 +3 1434 1435 1482 +3 1434 1482 1481 +3 1435 1436 1483 +3 1435 1483 1482 +3 1436 1437 1484 +3 1436 1484 1483 +3 1437 1438 1485 +3 1437 1485 1484 +3 1438 1439 1486 +3 1438 1486 1485 +3 1439 1440 1487 +3 1439 1487 1486 +3 1440 1441 1488 +3 1440 1488 1487 +3 1441 1442 1489 +3 1441 1489 1488 +3 1442 1443 1490 +3 1442 1490 1489 +3 1443 1444 1491 +3 1443 1491 1490 +3 1444 1445 1492 +3 1444 1492 1491 +3 1445 1446 1493 +3 1445 1493 1492 +3 1446 1447 1494 +3 1446 1494 1493 +3 1447 1448 1495 +3 1447 1495 1494 +3 1448 1449 1496 +3 1448 1496 1495 +3 1449 1450 1497 +3 1449 1497 1496 +3 1450 1451 1498 +3 1450 1498 1497 +3 1451 1452 1499 +3 1451 1499 1498 +3 1452 1453 1500 +3 1452 1500 1499 +3 1453 1454 1501 +3 1453 1501 1500 +3 1454 1455 1502 +3 1454 1502 1501 +3 1455 1456 1503 +3 1455 1503 1502 +3 1456 1457 1504 +3 1456 1504 1503 +3 1457 1458 1505 +3 1457 1505 1504 +3 1458 1459 1506 +3 1458 1506 1505 +3 1459 1460 1507 +3 1459 1507 1506 +3 1460 1461 1508 +3 1460 1508 1507 +3 1461 1462 1509 +3 1461 1509 1508 +3 1462 1463 1510 +3 1462 1510 1509 +3 1463 1464 1511 +3 1463 1511 1510 +3 1464 1465 1512 +3 1464 1512 1511 +3 1466 1467 1514 +3 1466 1514 1513 +3 1467 1468 1515 +3 1467 1515 1514 +3 1468 1469 1516 +3 1468 1516 1515 +3 1469 1470 1517 +3 1469 1517 1516 +3 1470 1471 1518 +3 1470 1518 1517 +3 1471 1472 1519 +3 1471 1519 1518 +3 1472 1473 1520 +3 1472 1520 1519 +3 1473 1474 1521 +3 1473 1521 1520 +3 1474 1475 1522 +3 1474 1522 1521 +3 1475 1476 1523 +3 1475 1523 1522 +3 1476 1477 1524 +3 1476 1524 1523 +3 1477 1478 1525 +3 1477 1525 1524 +3 1478 1479 1526 +3 1478 1526 1525 +3 1479 1480 1527 +3 1479 1527 1526 +3 1480 1481 1528 +3 1480 1528 1527 +3 1481 1482 1529 +3 1481 1529 1528 +3 1482 1483 1530 +3 1482 1530 1529 +3 1483 1484 1531 +3 1483 1531 1530 +3 1484 1485 1532 +3 1484 1532 1531 +3 1485 1486 1533 +3 1485 1533 1532 +3 1486 1487 1534 +3 1486 1534 1533 +3 1487 1488 1535 +3 1487 1535 1534 +3 1488 1489 1536 +3 1488 1536 1535 +3 1489 1490 1537 +3 1489 1537 1536 +3 1490 1491 1538 +3 1490 1538 1537 +3 1491 1492 1539 +3 1491 1539 1538 +3 1492 1493 1540 +3 1492 1540 1539 +3 1493 1494 1541 +3 1493 1541 1540 +3 1494 1495 1542 +3 1494 1542 1541 +3 1495 1496 1543 +3 1495 1543 1542 +3 1496 1497 1544 +3 1496 1544 1543 +3 1497 1498 1545 +3 1497 1545 1544 +3 1498 1499 1546 +3 1498 1546 1545 +3 1499 1500 1547 +3 1499 1547 1546 +3 1500 1501 1548 +3 1500 1548 1547 +3 1501 1502 1549 +3 1501 1549 1548 +3 1502 1503 1550 +3 1502 1550 1549 +3 1503 1504 1551 +3 1503 1551 1550 +3 1504 1505 1552 +3 1504 1552 1551 +3 1505 1506 1553 +3 1505 1553 1552 +3 1506 1507 1554 +3 1506 1554 1553 +3 1507 1508 1555 +3 1507 1555 1554 +3 1508 1509 1556 +3 1508 1556 1555 +3 1509 1510 1557 +3 1509 1557 1556 +3 1510 1511 1558 +3 1510 1558 1557 +3 1511 1512 1559 +3 1511 1559 1558 +3 1513 1514 1561 +3 1513 1561 1560 +3 1514 1515 1562 +3 1514 1562 1561 +3 1515 1516 1563 +3 1515 1563 1562 +3 1516 1517 1564 +3 1516 1564 1563 +3 1517 1518 1565 +3 1517 1565 1564 +3 1518 1519 1566 +3 1518 1566 1565 +3 1519 1520 1567 +3 1519 1567 1566 +3 1520 1521 1568 +3 1520 1568 1567 +3 1521 1522 1569 +3 1521 1569 1568 +3 1522 1523 1570 +3 1522 1570 1569 +3 1523 1524 1571 +3 1523 1571 1570 +3 1524 1525 1572 +3 1524 1572 1571 +3 1525 1526 1573 +3 1525 1573 1572 +3 1526 1527 1574 +3 1526 1574 1573 +3 1527 1528 1575 +3 1527 1575 1574 +3 1528 1529 1576 +3 1528 1576 1575 +3 1529 1530 1577 +3 1529 1577 1576 +3 1530 1531 1578 +3 1530 1578 1577 +3 1531 1532 1579 +3 1531 1579 1578 +3 1532 1533 1580 +3 1532 1580 1579 +3 1533 1534 1581 +3 1533 1581 1580 +3 1534 1535 1582 +3 1534 1582 1581 +3 1535 1536 1583 +3 1535 1583 1582 +3 1536 1537 1584 +3 1536 1584 1583 +3 1537 1538 1585 +3 1537 1585 1584 +3 1538 1539 1586 +3 1538 1586 1585 +3 1539 1540 1587 +3 1539 1587 1586 +3 1540 1541 1588 +3 1540 1588 1587 +3 1541 1542 1589 +3 1541 1589 1588 +3 1542 1543 1590 +3 1542 1590 1589 +3 1543 1544 1591 +3 1543 1591 1590 +3 1544 1545 1592 +3 1544 1592 1591 +3 1545 1546 1593 +3 1545 1593 1592 +3 1546 1547 1594 +3 1546 1594 1593 +3 1547 1548 1595 +3 1547 1595 1594 +3 1548 1549 1596 +3 1548 1596 1595 +3 1549 1550 1597 +3 1549 1597 1596 +3 1550 1551 1598 +3 1550 1598 1597 +3 1551 1552 1599 +3 1551 1599 1598 +3 1552 1553 1600 +3 1552 1600 1599 +3 1553 1554 1601 +3 1553 1601 1600 +3 1554 1555 1602 +3 1554 1602 1601 +3 1555 1556 1603 +3 1555 1603 1602 +3 1556 1557 1604 +3 1556 1604 1603 +3 1557 1558 1605 +3 1557 1605 1604 +3 1558 1559 1606 +3 1558 1606 1605 +3 1560 1561 1608 +3 1560 1608 1607 +3 1561 1562 1609 +3 1561 1609 1608 +3 1562 1563 1610 +3 1562 1610 1609 +3 1563 1564 1611 +3 1563 1611 1610 +3 1564 1565 1612 +3 1564 1612 1611 +3 1565 1566 1613 +3 1565 1613 1612 +3 1566 1567 1614 +3 1566 1614 1613 +3 1567 1568 1615 +3 1567 1615 1614 +3 1568 1569 1616 +3 1568 1616 1615 +3 1569 1570 1617 +3 1569 1617 1616 +3 1570 1571 1618 +3 1570 1618 1617 +3 1571 1572 1619 +3 1571 1619 1618 +3 1572 1573 1620 +3 1572 1620 1619 +3 1573 1574 1621 +3 1573 1621 1620 +3 1574 1575 1622 +3 1574 1622 1621 +3 1575 1576 1623 +3 1575 1623 1622 +3 1576 1577 1624 +3 1576 1624 1623 +3 1577 1578 1625 +3 1577 1625 1624 +3 1578 1579 1626 +3 1578 1626 1625 +3 1579 1580 1627 +3 1579 1627 1626 +3 1580 1581 1628 +3 1580 1628 1627 +3 1581 1582 1629 +3 1581 1629 1628 +3 1582 1583 1630 +3 1582 1630 1629 +3 1583 1584 1631 +3 1583 1631 1630 +3 1584 1585 1632 +3 1584 1632 1631 +3 1585 1586 1633 +3 1585 1633 1632 +3 1586 1587 1634 +3 1586 1634 1633 +3 1587 1588 1635 +3 1587 1635 1634 +3 1588 1589 1636 +3 1588 1636 1635 +3 1589 1590 1637 +3 1589 1637 1636 +3 1590 1591 1638 +3 1590 1638 1637 +3 1591 1592 1639 +3 1591 1639 1638 +3 1592 1593 1640 +3 1592 1640 1639 +3 1593 1594 1641 +3 1593 1641 1640 +3 1594 1595 1642 +3 1594 1642 1641 +3 1595 1596 1643 +3 1595 1643 1642 +3 1596 1597 1644 +3 1596 1644 1643 +3 1597 1598 1645 +3 1597 1645 1644 +3 1598 1599 1646 +3 1598 1646 1645 +3 1599 1600 1647 +3 1599 1647 1646 +3 1600 1601 1648 +3 1600 1648 1647 +3 1601 1602 1649 +3 1601 1649 1648 +3 1602 1603 1650 +3 1602 1650 1649 +3 1603 1604 1651 +3 1603 1651 1650 +3 1604 1605 1652 +3 1604 1652 1651 +3 1605 1606 1653 +3 1605 1653 1652 +3 1607 1608 1655 +3 1607 1655 1654 +3 1608 1609 1656 +3 1608 1656 1655 +3 1609 1610 1657 +3 1609 1657 1656 +3 1610 1611 1658 +3 1610 1658 1657 +3 1611 1612 1659 +3 1611 1659 1658 +3 1612 1613 1660 +3 1612 1660 1659 +3 1613 1614 1661 +3 1613 1661 1660 +3 1614 1615 1662 +3 1614 1662 1661 +3 1615 1616 1663 +3 1615 1663 1662 +3 1616 1617 1664 +3 1616 1664 1663 +3 1617 1618 1665 +3 1617 1665 1664 +3 1618 1619 1666 +3 1618 1666 1665 +3 1619 1620 1667 +3 1619 1667 1666 +3 1620 1621 1668 +3 1620 1668 1667 +3 1621 1622 1669 +3 1621 1669 1668 +3 1622 1623 1670 +3 1622 1670 1669 +3 1623 1624 1671 +3 1623 1671 1670 +3 1624 1625 1672 +3 1624 1672 1671 +3 1625 1626 1673 +3 1625 1673 1672 +3 1626 1627 1674 +3 1626 1674 1673 +3 1627 1628 1675 +3 1627 1675 1674 +3 1628 1629 1676 +3 1628 1676 1675 +3 1629 1630 1677 +3 1629 1677 1676 +3 1630 1631 1678 +3 1630 1678 1677 +3 1631 1632 1679 +3 1631 1679 1678 +3 1632 1633 1680 +3 1632 1680 1679 +3 1633 1634 1681 +3 1633 1681 1680 +3 1634 1635 1682 +3 1634 1682 1681 +3 1635 1636 1683 +3 1635 1683 1682 +3 1636 1637 1684 +3 1636 1684 1683 +3 1637 1638 1685 +3 1637 1685 1684 +3 1638 1639 1686 +3 1638 1686 1685 +3 1639 1640 1687 +3 1639 1687 1686 +3 1640 1641 1688 +3 1640 1688 1687 +3 1641 1642 1689 +3 1641 1689 1688 +3 1642 1643 1690 +3 1642 1690 1689 +3 1643 1644 1691 +3 1643 1691 1690 +3 1644 1645 1692 +3 1644 1692 1691 +3 1645 1646 1693 +3 1645 1693 1692 +3 1646 1647 1694 +3 1646 1694 1693 +3 1647 1648 1695 +3 1647 1695 1694 +3 1648 1649 1696 +3 1648 1696 1695 +3 1649 1650 1697 +3 1649 1697 1696 +3 1650 1651 1698 +3 1650 1698 1697 +3 1651 1652 1699 +3 1651 1699 1698 +3 1652 1653 1700 +3 1652 1700 1699 +3 1654 1655 1702 +3 1654 1702 1701 +3 1655 1656 1703 +3 1655 1703 1702 +3 1656 1657 1704 +3 1656 1704 1703 +3 1657 1658 1705 +3 1657 1705 1704 +3 1658 1659 1706 +3 1658 1706 1705 +3 1659 1660 1707 +3 1659 1707 1706 +3 1660 1661 1708 +3 1660 1708 1707 +3 1661 1662 1709 +3 1661 1709 1708 +3 1662 1663 1710 +3 1662 1710 1709 +3 1663 1664 1711 +3 1663 1711 1710 +3 1664 1665 1712 +3 1664 1712 1711 +3 1665 1666 1713 +3 1665 1713 1712 +3 1666 1667 1714 +3 1666 1714 1713 +3 1667 1668 1715 +3 1667 1715 1714 +3 1668 1669 1716 +3 1668 1716 1715 +3 1669 1670 1717 +3 1669 1717 1716 +3 1670 1671 1718 +3 1670 1718 1717 +3 1671 1672 1719 +3 1671 1719 1718 +3 1672 1673 1720 +3 1672 1720 1719 +3 1673 1674 1721 +3 1673 1721 1720 +3 1674 1675 1722 +3 1674 1722 1721 +3 1675 1676 1723 +3 1675 1723 1722 +3 1676 1677 1724 +3 1676 1724 1723 +3 1677 1678 1725 +3 1677 1725 1724 +3 1678 1679 1726 +3 1678 1726 1725 +3 1679 1680 1727 +3 1679 1727 1726 +3 1680 1681 1728 +3 1680 1728 1727 +3 1681 1682 1729 +3 1681 1729 1728 +3 1682 1683 1730 +3 1682 1730 1729 +3 1683 1684 1731 +3 1683 1731 1730 +3 1684 1685 1732 +3 1684 1732 1731 +3 1685 1686 1733 +3 1685 1733 1732 +3 1686 1687 1734 +3 1686 1734 1733 +3 1687 1688 1735 +3 1687 1735 1734 +3 1688 1689 1736 +3 1688 1736 1735 +3 1689 1690 1737 +3 1689 1737 1736 +3 1690 1691 1738 +3 1690 1738 1737 +3 1691 1692 1739 +3 1691 1739 1738 +3 1692 1693 1740 +3 1692 1740 1739 +3 1693 1694 1741 +3 1693 1741 1740 +3 1694 1695 1742 +3 1694 1742 1741 +3 1695 1696 1743 +3 1695 1743 1742 +3 1696 1697 1744 +3 1696 1744 1743 +3 1697 1698 1745 +3 1697 1745 1744 +3 1698 1699 1746 +3 1698 1746 1745 +3 1699 1700 1747 +3 1699 1747 1746 +3 1701 1702 1749 +3 1701 1749 1748 +3 1702 1703 1750 +3 1702 1750 1749 +3 1703 1704 1751 +3 1703 1751 1750 +3 1704 1705 1752 +3 1704 1752 1751 +3 1705 1706 1753 +3 1705 1753 1752 +3 1706 1707 1754 +3 1706 1754 1753 +3 1707 1708 1755 +3 1707 1755 1754 +3 1708 1709 1756 +3 1708 1756 1755 +3 1709 1710 1757 +3 1709 1757 1756 +3 1710 1711 1758 +3 1710 1758 1757 +3 1711 1712 1759 +3 1711 1759 1758 +3 1712 1713 1760 +3 1712 1760 1759 +3 1713 1714 1761 +3 1713 1761 1760 +3 1714 1715 1762 +3 1714 1762 1761 +3 1715 1716 1763 +3 1715 1763 1762 +3 1716 1717 1764 +3 1716 1764 1763 +3 1717 1718 1765 +3 1717 1765 1764 +3 1718 1719 1766 +3 1718 1766 1765 +3 1719 1720 1767 +3 1719 1767 1766 +3 1720 1721 1768 +3 1720 1768 1767 +3 1721 1722 1769 +3 1721 1769 1768 +3 1722 1723 1770 +3 1722 1770 1769 +3 1723 1724 1771 +3 1723 1771 1770 +3 1724 1725 1772 +3 1724 1772 1771 +3 1725 1726 1773 +3 1725 1773 1772 +3 1726 1727 1774 +3 1726 1774 1773 +3 1727 1728 1775 +3 1727 1775 1774 +3 1728 1729 1776 +3 1728 1776 1775 +3 1729 1730 1777 +3 1729 1777 1776 +3 1730 1731 1778 +3 1730 1778 1777 +3 1731 1732 1779 +3 1731 1779 1778 +3 1732 1733 1780 +3 1732 1780 1779 +3 1733 1734 1781 +3 1733 1781 1780 +3 1734 1735 1782 +3 1734 1782 1781 +3 1735 1736 1783 +3 1735 1783 1782 +3 1736 1737 1784 +3 1736 1784 1783 +3 1737 1738 1785 +3 1737 1785 1784 +3 1738 1739 1786 +3 1738 1786 1785 +3 1739 1740 1787 +3 1739 1787 1786 +3 1740 1741 1788 +3 1740 1788 1787 +3 1741 1742 1789 +3 1741 1789 1788 +3 1742 1743 1790 +3 1742 1790 1789 +3 1743 1744 1791 +3 1743 1791 1790 +3 1744 1745 1792 +3 1744 1792 1791 +3 1745 1746 1793 +3 1745 1793 1792 +3 1746 1747 1794 +3 1746 1794 1793 +3 1748 1749 1796 +3 1748 1796 1795 +3 1749 1750 1797 +3 1749 1797 1796 +3 1750 1751 1798 +3 1750 1798 1797 +3 1751 1752 1799 +3 1751 1799 1798 +3 1752 1753 1800 +3 1752 1800 1799 +3 1753 1754 1801 +3 1753 1801 1800 +3 1754 1755 1802 +3 1754 1802 1801 +3 1755 1756 1803 +3 1755 1803 1802 +3 1756 1757 1804 +3 1756 1804 1803 +3 1757 1758 1805 +3 1757 1805 1804 +3 1758 1759 1806 +3 1758 1806 1805 +3 1759 1760 1807 +3 1759 1807 1806 +3 1760 1761 1808 +3 1760 1808 1807 +3 1761 1762 1809 +3 1761 1809 1808 +3 1762 1763 1810 +3 1762 1810 1809 +3 1763 1764 1811 +3 1763 1811 1810 +3 1764 1765 1812 +3 1764 1812 1811 +3 1765 1766 1813 +3 1765 1813 1812 +3 1766 1767 1814 +3 1766 1814 1813 +3 1767 1768 1815 +3 1767 1815 1814 +3 1768 1769 1816 +3 1768 1816 1815 +3 1769 1770 1817 +3 1769 1817 1816 +3 1770 1771 1818 +3 1770 1818 1817 +3 1771 1772 1819 +3 1771 1819 1818 +3 1772 1773 1820 +3 1772 1820 1819 +3 1773 1774 1821 +3 1773 1821 1820 +3 1774 1775 1822 +3 1774 1822 1821 +3 1775 1776 1823 +3 1775 1823 1822 +3 1776 1777 1824 +3 1776 1824 1823 +3 1777 1778 1825 +3 1777 1825 1824 +3 1778 1779 1826 +3 1778 1826 1825 +3 1779 1780 1827 +3 1779 1827 1826 +3 1780 1781 1828 +3 1780 1828 1827 +3 1781 1782 1829 +3 1781 1829 1828 +3 1782 1783 1830 +3 1782 1830 1829 +3 1783 1784 1831 +3 1783 1831 1830 +3 1784 1785 1832 +3 1784 1832 1831 +3 1785 1786 1833 +3 1785 1833 1832 +3 1786 1787 1834 +3 1786 1834 1833 +3 1787 1788 1835 +3 1787 1835 1834 +3 1788 1789 1836 +3 1788 1836 1835 +3 1789 1790 1837 +3 1789 1837 1836 +3 1790 1791 1838 +3 1790 1838 1837 +3 1791 1792 1839 +3 1791 1839 1838 +3 1792 1793 1840 +3 1792 1840 1839 +3 1793 1794 1841 +3 1793 1841 1840 +3 1795 1796 1843 +3 1795 1843 1842 +3 1796 1797 1844 +3 1796 1844 1843 +3 1797 1798 1845 +3 1797 1845 1844 +3 1798 1799 1846 +3 1798 1846 1845 +3 1799 1800 1847 +3 1799 1847 1846 +3 1800 1801 1848 +3 1800 1848 1847 +3 1801 1802 1849 +3 1801 1849 1848 +3 1802 1803 1850 +3 1802 1850 1849 +3 1803 1804 1851 +3 1803 1851 1850 +3 1804 1805 1852 +3 1804 1852 1851 +3 1805 1806 1853 +3 1805 1853 1852 +3 1806 1807 1854 +3 1806 1854 1853 +3 1807 1808 1855 +3 1807 1855 1854 +3 1808 1809 1856 +3 1808 1856 1855 +3 1809 1810 1857 +3 1809 1857 1856 +3 1810 1811 1858 +3 1810 1858 1857 +3 1811 1812 1859 +3 1811 1859 1858 +3 1812 1813 1860 +3 1812 1860 1859 +3 1813 1814 1861 +3 1813 1861 1860 +3 1814 1815 1862 +3 1814 1862 1861 +3 1815 1816 1863 +3 1815 1863 1862 +3 1816 1817 1864 +3 1816 1864 1863 +3 1817 1818 1865 +3 1817 1865 1864 +3 1818 1819 1866 +3 1818 1866 1865 +3 1819 1820 1867 +3 1819 1867 1866 +3 1820 1821 1868 +3 1820 1868 1867 +3 1821 1822 1869 +3 1821 1869 1868 +3 1822 1823 1870 +3 1822 1870 1869 +3 1823 1824 1871 +3 1823 1871 1870 +3 1824 1825 1872 +3 1824 1872 1871 +3 1825 1826 1873 +3 1825 1873 1872 +3 1826 1827 1874 +3 1826 1874 1873 +3 1827 1828 1875 +3 1827 1875 1874 +3 1828 1829 1876 +3 1828 1876 1875 +3 1829 1830 1877 +3 1829 1877 1876 +3 1830 1831 1878 +3 1830 1878 1877 +3 1831 1832 1879 +3 1831 1879 1878 +3 1832 1833 1880 +3 1832 1880 1879 +3 1833 1834 1881 +3 1833 1881 1880 +3 1834 1835 1882 +3 1834 1882 1881 +3 1835 1836 1883 +3 1835 1883 1882 +3 1836 1837 1884 +3 1836 1884 1883 +3 1837 1838 1885 +3 1837 1885 1884 +3 1838 1839 1886 +3 1838 1886 1885 +3 1839 1840 1887 +3 1839 1887 1886 +3 1840 1841 1888 +3 1840 1888 1887 +3 1842 1843 1890 +3 1842 1890 1889 +3 1843 1844 1891 +3 1843 1891 1890 +3 1844 1845 1892 +3 1844 1892 1891 +3 1845 1846 1893 +3 1845 1893 1892 +3 1846 1847 1894 +3 1846 1894 1893 +3 1847 1848 1895 +3 1847 1895 1894 +3 1848 1849 1896 +3 1848 1896 1895 +3 1849 1850 1897 +3 1849 1897 1896 +3 1850 1851 1898 +3 1850 1898 1897 +3 1851 1852 1899 +3 1851 1899 1898 +3 1852 1853 1900 +3 1852 1900 1899 +3 1853 1854 1901 +3 1853 1901 1900 +3 1854 1855 1902 +3 1854 1902 1901 +3 1855 1856 1903 +3 1855 1903 1902 +3 1856 1857 1904 +3 1856 1904 1903 +3 1857 1858 1905 +3 1857 1905 1904 +3 1858 1859 1906 +3 1858 1906 1905 +3 1859 1860 1907 +3 1859 1907 1906 +3 1860 1861 1908 +3 1860 1908 1907 +3 1861 1862 1909 +3 1861 1909 1908 +3 1862 1863 1910 +3 1862 1910 1909 +3 1863 1864 1911 +3 1863 1911 1910 +3 1864 1865 1912 +3 1864 1912 1911 +3 1865 1866 1913 +3 1865 1913 1912 +3 1866 1867 1914 +3 1866 1914 1913 +3 1867 1868 1915 +3 1867 1915 1914 +3 1868 1869 1916 +3 1868 1916 1915 +3 1869 1870 1917 +3 1869 1917 1916 +3 1870 1871 1918 +3 1870 1918 1917 +3 1871 1872 1919 +3 1871 1919 1918 +3 1872 1873 1920 +3 1872 1920 1919 +3 1873 1874 1921 +3 1873 1921 1920 +3 1874 1875 1922 +3 1874 1922 1921 +3 1875 1876 1923 +3 1875 1923 1922 +3 1876 1877 1924 +3 1876 1924 1923 +3 1877 1878 1925 +3 1877 1925 1924 +3 1878 1879 1926 +3 1878 1926 1925 +3 1879 1880 1927 +3 1879 1927 1926 +3 1880 1881 1928 +3 1880 1928 1927 +3 1881 1882 1929 +3 1881 1929 1928 +3 1882 1883 1930 +3 1882 1930 1929 +3 1883 1884 1931 +3 1883 1931 1930 +3 1884 1885 1932 +3 1884 1932 1931 +3 1885 1886 1933 +3 1885 1933 1932 +3 1886 1887 1934 +3 1886 1934 1933 +3 1887 1888 1935 +3 1887 1935 1934 +3 1889 1890 1937 +3 1889 1937 1936 +3 1890 1891 1938 +3 1890 1938 1937 +3 1891 1892 1939 +3 1891 1939 1938 +3 1892 1893 1940 +3 1892 1940 1939 +3 1893 1894 1941 +3 1893 1941 1940 +3 1894 1895 1942 +3 1894 1942 1941 +3 1895 1896 1943 +3 1895 1943 1942 +3 1896 1897 1944 +3 1896 1944 1943 +3 1897 1898 1945 +3 1897 1945 1944 +3 1898 1899 1946 +3 1898 1946 1945 +3 1899 1900 1947 +3 1899 1947 1946 +3 1900 1901 1948 +3 1900 1948 1947 +3 1901 1902 1949 +3 1901 1949 1948 +3 1902 1903 1950 +3 1902 1950 1949 +3 1903 1904 1951 +3 1903 1951 1950 +3 1904 1905 1952 +3 1904 1952 1951 +3 1905 1906 1953 +3 1905 1953 1952 +3 1906 1907 1954 +3 1906 1954 1953 +3 1907 1908 1955 +3 1907 1955 1954 +3 1908 1909 1956 +3 1908 1956 1955 +3 1909 1910 1957 +3 1909 1957 1956 +3 1910 1911 1958 +3 1910 1958 1957 +3 1911 1912 1959 +3 1911 1959 1958 +3 1912 1913 1960 +3 1912 1960 1959 +3 1913 1914 1961 +3 1913 1961 1960 +3 1914 1915 1962 +3 1914 1962 1961 +3 1915 1916 1963 +3 1915 1963 1962 +3 1916 1917 1964 +3 1916 1964 1963 +3 1917 1918 1965 +3 1917 1965 1964 +3 1918 1919 1966 +3 1918 1966 1965 +3 1919 1920 1967 +3 1919 1967 1966 +3 1920 1921 1968 +3 1920 1968 1967 +3 1921 1922 1969 +3 1921 1969 1968 +3 1922 1923 1970 +3 1922 1970 1969 +3 1923 1924 1971 +3 1923 1971 1970 +3 1924 1925 1972 +3 1924 1972 1971 +3 1925 1926 1973 +3 1925 1973 1972 +3 1926 1927 1974 +3 1926 1974 1973 +3 1927 1928 1975 +3 1927 1975 1974 +3 1928 1929 1976 +3 1928 1976 1975 +3 1929 1930 1977 +3 1929 1977 1976 +3 1930 1931 1978 +3 1930 1978 1977 +3 1931 1932 1979 +3 1931 1979 1978 +3 1932 1933 1980 +3 1932 1980 1979 +3 1933 1934 1981 +3 1933 1981 1980 +3 1934 1935 1982 +3 1934 1982 1981 +3 1936 1937 1984 +3 1936 1984 1983 +3 1937 1938 1985 +3 1937 1985 1984 +3 1938 1939 1986 +3 1938 1986 1985 +3 1939 1940 1987 +3 1939 1987 1986 +3 1940 1941 1988 +3 1940 1988 1987 +3 1941 1942 1989 +3 1941 1989 1988 +3 1942 1943 1990 +3 1942 1990 1989 +3 1943 1944 1991 +3 1943 1991 1990 +3 1944 1945 1992 +3 1944 1992 1991 +3 1945 1946 1993 +3 1945 1993 1992 +3 1946 1947 1994 +3 1946 1994 1993 +3 1947 1948 1995 +3 1947 1995 1994 +3 1948 1949 1996 +3 1948 1996 1995 +3 1949 1950 1997 +3 1949 1997 1996 +3 1950 1951 1998 +3 1950 1998 1997 +3 1951 1952 1999 +3 1951 1999 1998 +3 1952 1953 2000 +3 1952 2000 1999 +3 1953 1954 2001 +3 1953 2001 2000 +3 1954 1955 2002 +3 1954 2002 2001 +3 1955 1956 2003 +3 1955 2003 2002 +3 1956 1957 2004 +3 1956 2004 2003 +3 1957 1958 2005 +3 1957 2005 2004 +3 1958 1959 2006 +3 1958 2006 2005 +3 1959 1960 2007 +3 1959 2007 2006 +3 1960 1961 2008 +3 1960 2008 2007 +3 1961 1962 2009 +3 1961 2009 2008 +3 1962 1963 2010 +3 1962 2010 2009 +3 1963 1964 2011 +3 1963 2011 2010 +3 1964 1965 2012 +3 1964 2012 2011 +3 1965 1966 2013 +3 1965 2013 2012 +3 1966 1967 2014 +3 1966 2014 2013 +3 1967 1968 2015 +3 1967 2015 2014 +3 1968 1969 2016 +3 1968 2016 2015 +3 1969 1970 2017 +3 1969 2017 2016 +3 1970 1971 2018 +3 1970 2018 2017 +3 1971 1972 2019 +3 1971 2019 2018 +3 1972 1973 2020 +3 1972 2020 2019 +3 1973 1974 2021 +3 1973 2021 2020 +3 1974 1975 2022 +3 1974 2022 2021 +3 1975 1976 2023 +3 1975 2023 2022 +3 1976 1977 2024 +3 1976 2024 2023 +3 1977 1978 2025 +3 1977 2025 2024 +3 1978 1979 2026 +3 1978 2026 2025 +3 1979 1980 2027 +3 1979 2027 2026 +3 1980 1981 2028 +3 1980 2028 2027 +3 1981 1982 2029 +3 1981 2029 2028 +3 1983 1984 2031 +3 1983 2031 2030 +3 1984 1985 2032 +3 1984 2032 2031 +3 1985 1986 2033 +3 1985 2033 2032 +3 1986 1987 2034 +3 1986 2034 2033 +3 1987 1988 2035 +3 1987 2035 2034 +3 1988 1989 2036 +3 1988 2036 2035 +3 1989 1990 2037 +3 1989 2037 2036 +3 1990 1991 2038 +3 1990 2038 2037 +3 1991 1992 2039 +3 1991 2039 2038 +3 1992 1993 2040 +3 1992 2040 2039 +3 1993 1994 2041 +3 1993 2041 2040 +3 1994 1995 2042 +3 1994 2042 2041 +3 1995 1996 2043 +3 1995 2043 2042 +3 1996 1997 2044 +3 1996 2044 2043 +3 1997 1998 2045 +3 1997 2045 2044 +3 1998 1999 2046 +3 1998 2046 2045 +3 1999 2000 2047 +3 1999 2047 2046 +3 2000 2001 2048 +3 2000 2048 2047 +3 2001 2002 2049 +3 2001 2049 2048 +3 2002 2003 2050 +3 2002 2050 2049 +3 2003 2004 2051 +3 2003 2051 2050 +3 2004 2005 2052 +3 2004 2052 2051 +3 2005 2006 2053 +3 2005 2053 2052 +3 2006 2007 2054 +3 2006 2054 2053 +3 2007 2008 2055 +3 2007 2055 2054 +3 2008 2009 2056 +3 2008 2056 2055 +3 2009 2010 2057 +3 2009 2057 2056 +3 2010 2011 2058 +3 2010 2058 2057 +3 2011 2012 2059 +3 2011 2059 2058 +3 2012 2013 2060 +3 2012 2060 2059 +3 2013 2014 2061 +3 2013 2061 2060 +3 2014 2015 2062 +3 2014 2062 2061 +3 2015 2016 2063 +3 2015 2063 2062 +3 2016 2017 2064 +3 2016 2064 2063 +3 2017 2018 2065 +3 2017 2065 2064 +3 2018 2019 2066 +3 2018 2066 2065 +3 2019 2020 2067 +3 2019 2067 2066 +3 2020 2021 2068 +3 2020 2068 2067 +3 2021 2022 2069 +3 2021 2069 2068 +3 2022 2023 2070 +3 2022 2070 2069 +3 2023 2024 2071 +3 2023 2071 2070 +3 2024 2025 2072 +3 2024 2072 2071 +3 2025 2026 2073 +3 2025 2073 2072 +3 2026 2027 2074 +3 2026 2074 2073 +3 2027 2028 2075 +3 2027 2075 2074 +3 2028 2029 2076 +3 2028 2076 2075 +3 2030 2031 2078 +3 2030 2078 2077 +3 2031 2032 2079 +3 2031 2079 2078 +3 2032 2033 2080 +3 2032 2080 2079 +3 2033 2034 2081 +3 2033 2081 2080 +3 2034 2035 2082 +3 2034 2082 2081 +3 2035 2036 2083 +3 2035 2083 2082 +3 2036 2037 2084 +3 2036 2084 2083 +3 2037 2038 2085 +3 2037 2085 2084 +3 2038 2039 2086 +3 2038 2086 2085 +3 2039 2040 2087 +3 2039 2087 2086 +3 2040 2041 2088 +3 2040 2088 2087 +3 2041 2042 2089 +3 2041 2089 2088 +3 2042 2043 2090 +3 2042 2090 2089 +3 2043 2044 2091 +3 2043 2091 2090 +3 2044 2045 2092 +3 2044 2092 2091 +3 2045 2046 2093 +3 2045 2093 2092 +3 2046 2047 2094 +3 2046 2094 2093 +3 2047 2048 2095 +3 2047 2095 2094 +3 2048 2049 2096 +3 2048 2096 2095 +3 2049 2050 2097 +3 2049 2097 2096 +3 2050 2051 2098 +3 2050 2098 2097 +3 2051 2052 2099 +3 2051 2099 2098 +3 2052 2053 2100 +3 2052 2100 2099 +3 2053 2054 2101 +3 2053 2101 2100 +3 2054 2055 2102 +3 2054 2102 2101 +3 2055 2056 2103 +3 2055 2103 2102 +3 2056 2057 2104 +3 2056 2104 2103 +3 2057 2058 2105 +3 2057 2105 2104 +3 2058 2059 2106 +3 2058 2106 2105 +3 2059 2060 2107 +3 2059 2107 2106 +3 2060 2061 2108 +3 2060 2108 2107 +3 2061 2062 2109 +3 2061 2109 2108 +3 2062 2063 2110 +3 2062 2110 2109 +3 2063 2064 2111 +3 2063 2111 2110 +3 2064 2065 2112 +3 2064 2112 2111 +3 2065 2066 2113 +3 2065 2113 2112 +3 2066 2067 2114 +3 2066 2114 2113 +3 2067 2068 2115 +3 2067 2115 2114 +3 2068 2069 2116 +3 2068 2116 2115 +3 2069 2070 2117 +3 2069 2117 2116 +3 2070 2071 2118 +3 2070 2118 2117 +3 2071 2072 2119 +3 2071 2119 2118 +3 2072 2073 2120 +3 2072 2120 2119 +3 2073 2074 2121 +3 2073 2121 2120 +3 2074 2075 2122 +3 2074 2122 2121 +3 2075 2076 2123 +3 2075 2123 2122 +3 2077 2078 2125 +3 2077 2125 2124 +3 2078 2079 2126 +3 2078 2126 2125 +3 2079 2080 2127 +3 2079 2127 2126 +3 2080 2081 2128 +3 2080 2128 2127 +3 2081 2082 2129 +3 2081 2129 2128 +3 2082 2083 2130 +3 2082 2130 2129 +3 2083 2084 2131 +3 2083 2131 2130 +3 2084 2085 2132 +3 2084 2132 2131 +3 2085 2086 2133 +3 2085 2133 2132 +3 2086 2087 2134 +3 2086 2134 2133 +3 2087 2088 2135 +3 2087 2135 2134 +3 2088 2089 2136 +3 2088 2136 2135 +3 2089 2090 2137 +3 2089 2137 2136 +3 2090 2091 2138 +3 2090 2138 2137 +3 2091 2092 2139 +3 2091 2139 2138 +3 2092 2093 2140 +3 2092 2140 2139 +3 2093 2094 2141 +3 2093 2141 2140 +3 2094 2095 2142 +3 2094 2142 2141 +3 2095 2096 2143 +3 2095 2143 2142 +3 2096 2097 2144 +3 2096 2144 2143 +3 2097 2098 2145 +3 2097 2145 2144 +3 2098 2099 2146 +3 2098 2146 2145 +3 2099 2100 2147 +3 2099 2147 2146 +3 2100 2101 2148 +3 2100 2148 2147 +3 2101 2102 2149 +3 2101 2149 2148 +3 2102 2103 2150 +3 2102 2150 2149 +3 2103 2104 2151 +3 2103 2151 2150 +3 2104 2105 2152 +3 2104 2152 2151 +3 2105 2106 2153 +3 2105 2153 2152 +3 2106 2107 2154 +3 2106 2154 2153 +3 2107 2108 2155 +3 2107 2155 2154 +3 2108 2109 2156 +3 2108 2156 2155 +3 2109 2110 2157 +3 2109 2157 2156 +3 2110 2111 2158 +3 2110 2158 2157 +3 2111 2112 2159 +3 2111 2159 2158 +3 2112 2113 2160 +3 2112 2160 2159 +3 2113 2114 2161 +3 2113 2161 2160 +3 2114 2115 2162 +3 2114 2162 2161 +3 2115 2116 2163 +3 2115 2163 2162 +3 2116 2117 2164 +3 2116 2164 2163 +3 2117 2118 2165 +3 2117 2165 2164 +3 2118 2119 2166 +3 2118 2166 2165 +3 2119 2120 2167 +3 2119 2167 2166 +3 2120 2121 2168 +3 2120 2168 2167 +3 2121 2122 2169 +3 2121 2169 2168 +3 2122 2123 2170 +3 2122 2170 2169 +3 2124 2125 2172 +3 2124 2172 2171 +3 2125 2126 2173 +3 2125 2173 2172 +3 2126 2127 2174 +3 2126 2174 2173 +3 2127 2128 2175 +3 2127 2175 2174 +3 2128 2129 2176 +3 2128 2176 2175 +3 2129 2130 2177 +3 2129 2177 2176 +3 2130 2131 2178 +3 2130 2178 2177 +3 2131 2132 2179 +3 2131 2179 2178 +3 2132 2133 2180 +3 2132 2180 2179 +3 2133 2134 2181 +3 2133 2181 2180 +3 2134 2135 2182 +3 2134 2182 2181 +3 2135 2136 2183 +3 2135 2183 2182 +3 2136 2137 2184 +3 2136 2184 2183 +3 2137 2138 2185 +3 2137 2185 2184 +3 2138 2139 2186 +3 2138 2186 2185 +3 2139 2140 2187 +3 2139 2187 2186 +3 2140 2141 2188 +3 2140 2188 2187 +3 2141 2142 2189 +3 2141 2189 2188 +3 2142 2143 2190 +3 2142 2190 2189 +3 2143 2144 2191 +3 2143 2191 2190 +3 2144 2145 2192 +3 2144 2192 2191 +3 2145 2146 2193 +3 2145 2193 2192 +3 2146 2147 2194 +3 2146 2194 2193 +3 2147 2148 2195 +3 2147 2195 2194 +3 2148 2149 2196 +3 2148 2196 2195 +3 2149 2150 2197 +3 2149 2197 2196 +3 2150 2151 2198 +3 2150 2198 2197 +3 2151 2152 2199 +3 2151 2199 2198 +3 2152 2153 2200 +3 2152 2200 2199 +3 2153 2154 2201 +3 2153 2201 2200 +3 2154 2155 2202 +3 2154 2202 2201 +3 2155 2156 2203 +3 2155 2203 2202 +3 2156 2157 2204 +3 2156 2204 2203 +3 2157 2158 2205 +3 2157 2205 2204 +3 2158 2159 2206 +3 2158 2206 2205 +3 2159 2160 2207 +3 2159 2207 2206 +3 2160 2161 2208 +3 2160 2208 2207 +3 2161 2162 2209 +3 2161 2209 2208 +3 2162 2163 2210 +3 2162 2210 2209 +3 2163 2164 2211 +3 2163 2211 2210 +3 2164 2165 2212 +3 2164 2212 2211 +3 2165 2166 2213 +3 2165 2213 2212 +3 2166 2167 2214 +3 2166 2214 2213 +3 2167 2168 2215 +3 2167 2215 2214 +3 2168 2169 2216 +3 2168 2216 2215 +3 2169 2170 2217 +3 2169 2217 2216 +3 2171 2172 2219 +3 2171 2219 2218 +3 2172 2173 2220 +3 2172 2220 2219 +3 2173 2174 2221 +3 2173 2221 2220 +3 2174 2175 2222 +3 2174 2222 2221 +3 2175 2176 2223 +3 2175 2223 2222 +3 2176 2177 2224 +3 2176 2224 2223 +3 2177 2178 2225 +3 2177 2225 2224 +3 2178 2179 2226 +3 2178 2226 2225 +3 2179 2180 2227 +3 2179 2227 2226 +3 2180 2181 2228 +3 2180 2228 2227 +3 2181 2182 2229 +3 2181 2229 2228 +3 2182 2183 2230 +3 2182 2230 2229 +3 2183 2184 2231 +3 2183 2231 2230 +3 2184 2185 2232 +3 2184 2232 2231 +3 2185 2186 2233 +3 2185 2233 2232 +3 2186 2187 2234 +3 2186 2234 2233 +3 2187 2188 2235 +3 2187 2235 2234 +3 2188 2189 2236 +3 2188 2236 2235 +3 2189 2190 2237 +3 2189 2237 2236 +3 2190 2191 2238 +3 2190 2238 2237 +3 2191 2192 2239 +3 2191 2239 2238 +3 2192 2193 2240 +3 2192 2240 2239 +3 2193 2194 2241 +3 2193 2241 2240 +3 2194 2195 2242 +3 2194 2242 2241 +3 2195 2196 2243 +3 2195 2243 2242 +3 2196 2197 2244 +3 2196 2244 2243 +3 2197 2198 2245 +3 2197 2245 2244 +3 2198 2199 2246 +3 2198 2246 2245 +3 2199 2200 2247 +3 2199 2247 2246 +3 2200 2201 2248 +3 2200 2248 2247 +3 2201 2202 2249 +3 2201 2249 2248 +3 2202 2203 2250 +3 2202 2250 2249 +3 2203 2204 2251 +3 2203 2251 2250 +3 2204 2205 2252 +3 2204 2252 2251 +3 2205 2206 2253 +3 2205 2253 2252 +3 2206 2207 2254 +3 2206 2254 2253 +3 2207 2208 2255 +3 2207 2255 2254 +3 2208 2209 2256 +3 2208 2256 2255 +3 2209 2210 2257 +3 2209 2257 2256 +3 2210 2211 2258 +3 2210 2258 2257 +3 2211 2212 2259 +3 2211 2259 2258 +3 2212 2213 2260 +3 2212 2260 2259 +3 2213 2214 2261 +3 2213 2261 2260 +3 2214 2215 2262 +3 2214 2262 2261 +3 2215 2216 2263 +3 2215 2263 2262 +3 2216 2217 2264 +3 2216 2264 2263 +3 2218 2219 2266 +3 2218 2266 2265 +3 2219 2220 2267 +3 2219 2267 2266 +3 2220 2221 2268 +3 2220 2268 2267 +3 2221 2222 2269 +3 2221 2269 2268 +3 2222 2223 2270 +3 2222 2270 2269 +3 2223 2224 2271 +3 2223 2271 2270 +3 2224 2225 2272 +3 2224 2272 2271 +3 2225 2226 2273 +3 2225 2273 2272 +3 2226 2227 2274 +3 2226 2274 2273 +3 2227 2228 2275 +3 2227 2275 2274 +3 2228 2229 2276 +3 2228 2276 2275 +3 2229 2230 2277 +3 2229 2277 2276 +3 2230 2231 2278 +3 2230 2278 2277 +3 2231 2232 2279 +3 2231 2279 2278 +3 2232 2233 2280 +3 2232 2280 2279 +3 2233 2234 2281 +3 2233 2281 2280 +3 2234 2235 2282 +3 2234 2282 2281 +3 2235 2236 2283 +3 2235 2283 2282 +3 2236 2237 2284 +3 2236 2284 2283 +3 2237 2238 2285 +3 2237 2285 2284 +3 2238 2239 2286 +3 2238 2286 2285 +3 2239 2240 2287 +3 2239 2287 2286 +3 2240 2241 2288 +3 2240 2288 2287 +3 2241 2242 2289 +3 2241 2289 2288 +3 2242 2243 2290 +3 2242 2290 2289 +3 2243 2244 2291 +3 2243 2291 2290 +3 2244 2245 2292 +3 2244 2292 2291 +3 2245 2246 2293 +3 2245 2293 2292 +3 2246 2247 2294 +3 2246 2294 2293 +3 2247 2248 2295 +3 2247 2295 2294 +3 2248 2249 2296 +3 2248 2296 2295 +3 2249 2250 2297 +3 2249 2297 2296 +3 2250 2251 2298 +3 2250 2298 2297 +3 2251 2252 2299 +3 2251 2299 2298 +3 2252 2253 2300 +3 2252 2300 2299 +3 2253 2254 2301 +3 2253 2301 2300 +3 2254 2255 2302 +3 2254 2302 2301 +3 2255 2256 2303 +3 2255 2303 2302 +3 2256 2257 2304 +3 2256 2304 2303 +3 2257 2258 2305 +3 2257 2305 2304 +3 2258 2259 2306 +3 2258 2306 2305 +3 2259 2260 2307 +3 2259 2307 2306 +3 2260 2261 2308 +3 2260 2308 2307 +3 2261 2262 2309 +3 2261 2309 2308 +3 2262 2263 2310 +3 2262 2310 2309 +3 2263 2264 2311 +3 2263 2311 2310 +3 369 41 34 +3 651 48 41 +3 980 55 48 +3 1138 49 50 +3 1143 50 51 +3 1149 51 52 +3 1154 52 53 +3 1160 53 54 +3 1165 54 55 + diff --git a/Examples/GUI/Win32/SimpleCxx/CMakeLists.txt b/Examples/GUI/Win32/SimpleCxx/CMakeLists.txt new file mode 100644 index 0000000..952f0b6 --- /dev/null +++ b/Examples/GUI/Win32/SimpleCxx/CMakeLists.txt @@ -0,0 +1,18 @@ +PROJECT (Win32Cone) + +FIND_PACKAGE(VTK) +IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") +ENDIF(NOT VTK_DIR) +INCLUDE(${VTK_USE_FILE}) + +LINK_LIBRARIES( + vtkRendering + vtkGraphics + vtkImaging + vtkIO + vtkFiltering + vtkCommon +) + +ADD_EXECUTABLE(Win32Cone WIN32 Win32Cone.cxx) diff --git a/Examples/GUI/Win32/SimpleCxx/Win32Cone.cxx b/Examples/GUI/Win32/SimpleCxx/Win32Cone.cxx new file mode 100644 index 0000000..00811ff --- /dev/null +++ b/Examples/GUI/Win32/SimpleCxx/Win32Cone.cxx @@ -0,0 +1,177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Win32Cone.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example is a windows application (instead of a console application) +// version of Examples/Tutorial/Step1/Cxx/Cone.cxx. It is organized in a more +// object oriented manner and shows a fairly minimal windows VTK application. +// + +#include "windows.h" + +// first include the required header files for the vtk classes we are using +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" + +static HANDLE hinst; +long FAR PASCAL WndProc(HWND, UINT, UINT, LONG); +// define the vtk part as a simple c++ class +class myVTKApp +{ +public: + myVTKApp(HWND parent); + ~myVTKApp(); +private: + vtkRenderWindow *renWin; + vtkRenderer *renderer; + vtkRenderWindowInteractor *iren; + vtkConeSource *cone; + vtkPolyDataMapper *coneMapper; + vtkActor *coneActor; +}; + + +int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpszCmdParam, int nCmdShow) +{ + static char szAppName[] = "Win32Cone"; + HWND hwnd ; + MSG msg ; + WNDCLASS wndclass ; + + if (!hPrevInstance) + { + wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wndclass.lpfnWndProc = WndProc ; + wndclass.cbClsExtra = 0 ; + wndclass.cbWndExtra = 0 ; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.lpszMenuName = NULL; + wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndclass.lpszClassName = szAppName; + RegisterClass (&wndclass); + } + + hinst = hInstance; + hwnd = CreateWindow ( szAppName, + "Draw Window", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + 400, + 480, + NULL, + NULL, + hInstance, + NULL); + ShowWindow (hwnd, nCmdShow); + UpdateWindow (hwnd); + while (GetMessage (&msg, NULL, 0, 0)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + return msg.wParam; +} + +long FAR PASCAL WndProc (HWND hwnd, UINT message, + UINT wParam, LONG lParam) +{ + static HWND ewin; + static myVTKApp *theVTKApp; + + switch (message) + { + case WM_CREATE: + { + ewin = CreateWindow("button","Exit", + WS_CHILD | WS_VISIBLE | SS_CENTER, + 0,400,400,60, + hwnd,(HMENU)2, + (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE), + NULL); + theVTKApp = new myVTKApp(hwnd); + return 0; + } + + case WM_COMMAND: + switch (wParam) + { + case 2: + PostQuitMessage (0); + if (theVTKApp) + { + delete theVTKApp; + theVTKApp = NULL; + } + break; + } + return 0; + + case WM_DESTROY: + PostQuitMessage (0); + if (theVTKApp) + { + delete theVTKApp; + theVTKApp = NULL; + } + return 0; + } + return DefWindowProc (hwnd, message, wParam, lParam); +} + +myVTKApp::myVTKApp(HWND hwnd) +{ + // Similar to Examples/Tutorial/Step1/Cxx/Cone.cxx + // We create the basic parts of a pipeline and connect them + this->renderer = vtkRenderer::New(); + this->renWin = vtkRenderWindow::New(); + this->renWin->AddRenderer(this->renderer); + + // setup the parent window + this->renWin->SetParentId(hwnd); + this->iren = vtkRenderWindowInteractor::New(); + this->iren->SetRenderWindow(this->renWin); + + this->cone = vtkConeSource::New(); + this->cone->SetHeight( 3.0 ); + this->cone->SetRadius( 1.0 ); + this->cone->SetResolution( 10 ); + this->coneMapper = vtkPolyDataMapper::New(); + this->coneMapper->SetInputConnection(this->cone->GetOutputPort()); + this->coneActor = vtkActor::New(); + this->coneActor->SetMapper(this->coneMapper); + + this->renderer->AddActor(this->coneActor); + this->renderer->SetBackground(0.2,0.4,0.3); + this->renWin->SetSize(400,400); + + // Finally we start the interactor so that event will be handled + this->renWin->Render(); +} + +myVTKApp::~myVTKApp() +{ + renWin->Delete(); + renderer->Delete(); + iren->Delete(); + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); +} diff --git a/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindow.cpp b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindow.cpp new file mode 100644 index 0000000..72bebcf --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindow.cpp @@ -0,0 +1,403 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +#include + +#include "vtkBorlandRenderWindow.h" + +#include "vtkInteractorStyleSwitch.h" +#include "vtkInteractorStyleFlight.h" +#include "vtkInteractorStyleImage.h" +#include "vtkInteractorStyleUser.h" + +#pragma package(smart_init) + +//--------------------------------------------------------------------------- +// ValidCtrCheck is used to assure that the components created do not have +// any pure virtual functions. +// +static inline void ValidCtrCheck(TvtkBorlandRenderWindow *) +{ + new TvtkBorlandRenderWindow(NULL); +} + +//--------------------------------------------------------------------------- +namespace Vtkborlandrenderwindow +{ + void __fastcall PACKAGE Register() + { + TComponentClass classes[1] = {__classid(TvtkBorlandRenderWindow)}; + RegisterComponents("Samples", classes, 0); + } +} + +//--------------------------------------------------------------------------- +__fastcall TvtkBorlandRenderWindow::TvtkBorlandRenderWindow(TComponent* Owner) + : inherited(Owner) +{ + // Do want these + ControlStyle << csCaptureMouse << csClickEvents << csOpaque << csDoubleClicks; + // Don't want these + ControlStyle >> csAcceptsControls >> csSetCaption; + + FUsevtkInteractor = true; + FInteractorMode = IM_TrackballCamera; + FInteractor = 0; + FOnVtkClose = 0; + FRenderWindow = 0; + FRenderer = 0; + FAbortCallback = vtkAbortCallback::New(); +} + +//--------------------------------------------------------------------------- +__fastcall TvtkBorlandRenderWindow::~TvtkBorlandRenderWindow() +{ + // Delete this first because Renderwindow has a hold on it too + if ( FInteractor ) + { + FInteractor->Delete(); + FInteractor = 0; + } + if ( FRenderer ) + { + FRenderer->GetViewProps()->RemoveAllItems(); + FRenderWindow->RemoveRenderer(FRenderer); + FRenderer->Delete(); + FRenderer = 0; + } + if ( FRenderWindow ) + { + FRenderWindow->RemoveObserver(FAbortCallback); + FRenderWindow->Delete(); + FRenderWindow = 0; + } + FAbortCallback->Delete(); +} + +//--------------------------------------------------------------------------- +vtkWin32OpenGLRenderWindow * __fastcall TvtkBorlandRenderWindow::GetRenderWindow(void) +{ + if ( ! FRenderWindow ) + { + // Stuff the renderwindow into our window + FRenderWindow = vtkWin32OpenGLRenderWindow::New(); + FRenderWindow->AddObserver( vtkCommand::AbortCheckEvent, FAbortCallback); + FRenderWindow->SetParentId(Parent->Handle); + FRenderWindow->SetWindowId(Handle); + FRenderWindow->DoubleBufferOn(); + FRenderWindow->SwapBuffersOn(); + // Frame to avoid unsightly garbage during initial + // display which may be long when a complex scene is first rendered + FRenderWindow->Frame(); + Invalidate(); + } + // We create the interactor here because it makes maintenance better + if (!FInteractor) + { + FInteractor = vtkWin32RenderWindowInteractor::New(); + FInteractor->SetRenderWindow(FRenderWindow); + FInteractor->SetInstallMessageProc(false); + SetInteractorMode(FInteractorMode); + FInteractor->UpdateSize(Width,Height); + FInteractor->Initialize(); + } + return FRenderWindow; +} + +//--------------------------------------------------------------------------- +vtkWin32RenderWindowInteractor * __fastcall TvtkBorlandRenderWindow::GetInteractor(void) +{ + if (FRenderWindow) + { + if (!FInteractor) + { + throw Exception("Window exists but no Interactor, this shouldn't happen"); + } + } + else + { + this->GetRenderWindow(); + } + return FInteractor; +} + +//--------------------------------------------------------------------------- +vtkRenderer * __fastcall TvtkBorlandRenderWindow::GetRenderer(void) +{ + if (!FRenderer) + { + FRenderer = vtkRenderer::New(); + GetRenderWindow()->AddRenderer(FRenderer); + FRenderer->ResetCamera(); + DWORD L = ColorToRGB(Color); + double rgb[3] = { GetRValue(L)/255.0, GetGValue(L)/255.0, GetBValue(L)/255.0 }; + FRenderer->SetBackground(rgb); + } + return FRenderer; +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::SetInteractorMode(const vtkBorlandInteractorMode& im) +{ + if ( im <= IM_TrackballActor && im >= IM_JoystickCamera ) + { + vtkInteractorStyleSwitch *iass = dynamic_cast(FInteractor->GetInteractorStyle()); + if (!iass) + { + iass = vtkInteractorStyleSwitch::New(); + FInteractor->SetInteractorStyle(iass); + iass->Delete(); + } + + switch ( im ) + { + case IM_JoystickCamera: iass->SetCurrentStyleToJoystickCamera(); break; + case IM_JoystickActor: iass->SetCurrentStyleToJoystickActor(); break; + case IM_TrackballCamera: iass->SetCurrentStyleToTrackballCamera(); break; + case IM_TrackballActor: iass->SetCurrentStyleToTrackballActor(); break; + default: break; + } + FInteractorMode = im; + } + else if (im==IM_Flight) + { + vtkInteractorStyleFlight *iafl = dynamic_cast(FInteractor->GetInteractorStyle()); + if (!iafl) + { + iafl = vtkInteractorStyleFlight::New(); + FInteractor->SetInteractorStyle(iafl); + iafl->Delete(); + } + FInteractorMode = IM_Flight; + } + else if (im==IM_Image) + { + vtkInteractorStyleImage *iasi = dynamic_cast(FInteractor->GetInteractorStyle()); + if (!iasi) + { + iasi = vtkInteractorStyleImage::New(); + FInteractor->SetInteractorStyle(iasi); + iasi->Delete(); + } + FInteractorMode = IM_Image; + } + else if (im==IM_User) + { + vtkInteractorStyleUser *iasu = dynamic_cast(FInteractor->GetInteractorStyle()); + if (!iasu) + { + iasu = vtkInteractorStyleUser::New(); + FInteractor->SetInteractorStyle(iasu); + iasu->Delete(); + } + FInteractorMode = IM_User; + } + else + { + return; + } +} + +//--------------------------------------------------------------------------- +// Paint +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::Paint(void) +{ + if (FRenderWindow) + { + try + { + FRenderWindow->Render(); + } + catch (...) + { + // Some error trap should occurr here + ShowMessage("An exception occurred whilst rendering"); + } + } + else + { // Design time or before RenderWindow creation + inherited::Paint(); + } +} + +//--------------------------------------------------------------------------- +// Event handlers +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::WMEraseBkgnd(TWMEraseBkgnd &Message) +{ + if (!FRenderWindow) + { + inherited::Dispatch(&Message); + } + else + { + Message.Result = 1; // No, but thanks for asking. + } +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::WMGetDlgCode(TMessage &Message) +{ + Message.Result = DLGC_WANTARROWS; +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::WMChar(TWMKey &Message) +{ + switch (Message.CharCode) + { + case 'e': + case 'E': + case 'q': + case 'Q': if (!FOnVtkClose || (FOnVtkClose && FOnVtkClose(this))) + { + FInteractor->OnChar(Handle,Message.CharCode, 0, 0); + } + break; + default: FInteractor->OnChar(Handle,Message.CharCode, 0, 0); + } +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::WMKeyDown(TWMKey &Message) +{ + FInteractor->OnKeyDown(Handle,Message.CharCode, 0, 0); +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::WMKeyUp(TWMKey &Message) +{ + FInteractor->OnKeyUp(Handle,Message.CharCode, 0, 0); +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::MouseMove(TShiftState shift, int x, int y ) +{ + if(this->OnMouseMove && shift.Contains(ssCtrl)) + { + this->OnMouseMove(this,shift,x,y); + return; + } + + if (FInteractor && FUsevtkInteractor) + { + int flags = 0; + if (shift.Contains(ssShift)) flags += MK_SHIFT; + if (shift.Contains(ssCtrl)) flags += MK_CONTROL; + FInteractor->OnMouseMove(Handle, flags, x, y ); + } +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::MouseDown(TMouseButton button, TShiftState shift, int x, int y ) +{ + if (::GetFocus()!=Handle) SetFocus(); + + if(this->OnMouseDown && shift.Contains(ssCtrl)) + { + this->OnMouseDown(this,button,shift,x,y); + return; + } + + if (FInteractor && FUsevtkInteractor) + { + int flags = 0; + if (shift.Contains(ssShift)) flags += MK_SHIFT; + if (shift.Contains(ssCtrl)) flags += MK_CONTROL; + switch (button) + { + case mbLeft: FInteractor->OnLButtonDown(Handle, flags, x,y); break; + case mbRight: FInteractor->OnRButtonDown(Handle, flags, x,y); break; + case mbMiddle: FInteractor->OnMButtonDown(Handle, flags, x,y); break; + } + } +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::MouseUp(TMouseButton button, TShiftState shift, int x, int y ) +{ + if(this->OnMouseUp && shift.Contains(ssCtrl)) + { + this->OnMouseUp(this,button,shift,x,y); + return; + } + + if (FInteractor && FUsevtkInteractor) + { + int flags = 0; + if (shift.Contains(ssShift)) flags += MK_SHIFT; + if (shift.Contains(ssCtrl)) flags += MK_CONTROL; + switch (button) + { + case mbLeft: FInteractor->OnLButtonUp(Handle, flags, x,y); break; + case mbRight: FInteractor->OnRButtonUp(Handle, flags, x,y); break; + case mbMiddle: FInteractor->OnMButtonUp(Handle, flags, x,y); break; + } + } +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::Resize(void) +{ + if (FInteractor) + { + FInteractor->OnSize(this->Handle, 0, this->Width, this->Height); + } +} + +//--------------------------------------------------------------------------- +void __fastcall TvtkBorlandRenderWindow::WMTimer(TWMTimer &Message) +{ + if (FInteractor) + { + FInteractor->OnTimer(Handle,Message.TimerID); + } +} + +//--------------------------------------------------------------------------- +bool __fastcall TvtkBorlandRenderWindow::DoMouseWheelDown(TShiftState Shift, const TPoint &MousePos) +{ + bool result; + if (this->OnMouseWheelDown && Shift.Contains(ssCtrl)) + { + this->OnMouseWheelDown(this,Shift,MousePos,result); + return result; + } + + if (FInteractor && FUsevtkInteractor) + { + int flags = 0; + if (Shift.Contains(ssShift)) { flags += MK_SHIFT; } + if (Shift.Contains(ssCtrl)) { flags += MK_CONTROL; } + FInteractor->OnMouseWheelBackward(Handle, flags, MousePos.x,MousePos.y); + result = true; + } + return result; +} + +//--------------------------------------------------------------------------- +bool __fastcall TvtkBorlandRenderWindow::DoMouseWheelUp(TShiftState Shift, const TPoint &MousePos) +{ + bool result; + if (this->OnMouseWheelUp && Shift.Contains(ssCtrl)) + { + this->OnMouseWheelUp(this,Shift,MousePos,result); + return result; + } + + if (FInteractor && FUsevtkInteractor) + { + int flags = 0; + if (Shift.Contains(ssShift)) { flags += MK_SHIFT; } + if (Shift.Contains(ssCtrl)) { flags += MK_CONTROL; } + FInteractor->OnMouseWheelForward(Handle, flags, MousePos.x,MousePos.y); + result = true; + } + return result; +} + + + + diff --git a/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindow.h b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindow.h new file mode 100644 index 0000000..336fb72 --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindow.h @@ -0,0 +1,168 @@ +//--------------------------------------------------------------------------- +#ifndef vtkBorlandRenderWindowH +#define vtkBorlandRenderWindowH +//--------------------------------------------------------------------------- +#include +#include +#include +#include + +#include "vtkCommand.h" +#include "vtkRenderer.h"; +#include "vtkWin32OpenGLRenderWindow.h"; +#include "vtkWin32RenderWindowInteractor.h"; + +typedef bool __fastcall (__closure *TvtkBorlandCloseEvent)(TObject *Sender); + +// Callback for abort check +class vtkAbortCallback : public vtkCommand +{ +public: + static vtkAbortCallback *New() + { return new vtkAbortCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkWin32OpenGLRenderWindow* ptrWin = reinterpret_cast(caller); + if (ptrWin) + { + if(ptrWin->GetEventPending()) + { + ptrWin->SetAbortRender( 1 ); + // Beep(); + } + } + } + vtkAbortCallback(){}; +}; + +//--------------------------------------------------------------------------- +enum vtkBorlandInteractorMode { IM_JoystickCamera,IM_JoystickActor, + IM_TrackballCamera, IM_TrackballActor, + IM_Flight, IM_Image,IM_User }; + +//--------------------------------------------------------------------------- +class PACKAGE TvtkBorlandRenderWindow : public TCustomControl +{ + typedef TCustomControl inherited; +private: +protected: + // + // Events and control related stuff + // + DYNAMIC void __fastcall MouseMove(TShiftState shift, int x, int y ); + DYNAMIC void __fastcall MouseDown(TMouseButton button, TShiftState shift, int x, int y ); + DYNAMIC void __fastcall MouseUp(TMouseButton button, TShiftState shift, int x, int y ); + DYNAMIC bool __fastcall DoMouseWheelDown(TShiftState Shift, const TPoint &MousePos); + DYNAMIC bool __fastcall DoMouseWheelUp(TShiftState Shift, const TPoint &MousePos); + + // + // Messages : We want to directly intercept these + // + void __fastcall WMEraseBkgnd(TWMEraseBkgnd &Message); + void __fastcall WMGetDlgCode(TMessage &Message); + void __fastcall WMKeyDown(TWMKey &Message); + void __fastcall WMKeyUp(TWMKey &Message); + void __fastcall WMChar(TWMKey &Message); + void __fastcall WMTimer(TWMTimer &Message); + // Here's the Dispatch(void &Message) message map for the above functions + BEGIN_MESSAGE_MAP + MESSAGE_HANDLER(WM_ERASEBKGND, TWMEraseBkgnd, WMEraseBkgnd) + MESSAGE_HANDLER(WM_GETDLGCODE, TMessage, WMGetDlgCode) + MESSAGE_HANDLER(WM_KEYDOWN, TWMKeyDown, WMKeyDown) + MESSAGE_HANDLER(WM_KEYUP, TWMKeyUp, WMKeyUp) + MESSAGE_HANDLER(WM_CHAR, TWMChar, WMChar) + MESSAGE_HANDLER(WM_TIMER, TWMTimer, WMTimer) + END_MESSAGE_MAP(inherited) + // + DYNAMIC void __fastcall Resize(void); + // + // This does all the work + // + virtual void __fastcall Paint(void); + // + // Our Data Members + // + vtkWin32OpenGLRenderWindow *FRenderWindow; + vtkRenderer *FRenderer; + vtkWin32RenderWindowInteractor *FInteractor; + // + TvtkBorlandCloseEvent FOnVtkClose; + bool FUsevtkInteractor; + vtkBorlandInteractorMode FInteractorMode; + vtkAbortCallback *FAbortCallback; + + // +public: + // + // Constructor and Destructor + // + __fastcall TvtkBorlandRenderWindow(TComponent* Owner); + virtual __fastcall ~TvtkBorlandRenderWindow(void); + // + // Make user friendly by handling a single rendererer and + // assorted bits for the user + // + virtual vtkWin32OpenGLRenderWindow * __fastcall GetRenderWindow(void); + virtual vtkRenderer * __fastcall GetRenderer(void); + virtual vtkWin32RenderWindowInteractor * __fastcall GetInteractor(void); + virtual void __fastcall SetInteractorMode(const vtkBorlandInteractorMode& im); + +__published: + // Some + __property bool UsevtkInteractor = {read=FUsevtkInteractor, write=FUsevtkInteractor, default=true, stored=true}; + __property vtkBorlandInteractorMode InteractorMode = {read=FInteractorMode, write=FInteractorMode, default=IM_TrackballCamera, stored=true}; + // + // Cosmetic Properties inherited from TCustomControl + // + __property Align; + __property Anchors; + __property Color; + __property Constraints; + __property Enabled; + __property ParentColor; + __property PopupMenu; + __property TabOrder; + __property TabStop; + __property Visible; + // + // Cosmetic Properties inherited from TWinControl + // + __property BevelEdges; + __property BevelInner; + __property BevelOuter; + __property BevelKind; + __property BevelWidth; + __property BorderWidth; + + // + // Useful Event notifications + // + __property OnCanResize; + __property OnClick; + __property OnConstrainedResize; + __property OnDblClick; + __property OnDragDrop; + __property OnDragOver; + __property OnEnter; + __property OnExit; + __property OnResize; + __property OnStartDrag; + __property TvtkBorlandCloseEvent OnVtkClose = {read=FOnVtkClose, write=FOnVtkClose}; + // + // Main events for user interaction + // + __property OnKeyUp; + __property OnKeyDown; + __property OnKeyPress; + __property OnMouseDown; + __property OnMouseMove; + __property OnMouseUp; + __property OnMouseWheelDown; + __property OnMouseWheelUp; +}; +//--------------------------------------------------------------------------- +#endif + +void CheckAbortFunc(void *); + + diff --git a/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindowPkg.bpk b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindowPkg.bpk new file mode 100644 index 0000000..e525272 --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindowPkg.bpk @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=1 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2057 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=3 +Item0=C:\Program Files\Borland\CBuilder6\Bin;D:\VTK\Examples\GUI\Win32\vtkBorland\Package;$(BCB)\include;$(BCB)\include\vcl;D:\VTK\Common;D:\VTK\Filtering;D:\VTK\Graphics;D:\VTK\Hybrid;D:\VTK\Imaging;D:\VTK\IO;D:\VTK\Rendering;D:\cmakebuild\vtkDebug +Item1=C:\Program Files\Borland\CBuilder6\Bin;D:\VTK\Examples\GUI\Win32\vtkBorland\Package;$(BCB)\include;$(BCB)\include\vcl;D:\VTK\Common;D:\VTK\Filtering;D:\VTK\Graphics;D:\VTK\Hybrid;D:\VTK\Imaging;D:\VTK\IO;D:\VTK\Rendering +Item2=C:\Program Files\Borland\CBuilder6\Bin;D:\VTK\Examples\GUI\Win32\vtkBorland\Package;$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=C:\Program Files\Borland\CBuilder6\Bin;D:\VTK\Examples\GUI\Win32\vtkBorland\Package;$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=2 +Item0=_DEBUG;STRICT +Item1=_DEBUG + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + +[Linker] +LibPrefix= +LibSuffix= +LibVersion= + + \ No newline at end of file diff --git a/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindowPkg.cpp b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindowPkg.cpp new file mode 100644 index 0000000..49510d3 --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/Package/vtkBorlandRenderWindowPkg.cpp @@ -0,0 +1,14 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +#pragma package(smart_init) +//--------------------------------------------------------------------------- +// Package source. +//--------------------------------------------------------------------------- +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} +//--------------------------------------------------------------------------- + diff --git a/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.cpp b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.cpp new file mode 100644 index 0000000..c4768fb --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.cpp @@ -0,0 +1,208 @@ +//--------------------------------------------------------------------------- +// +// Demo Borland + vtk Project, +// +//--------------------------------------------------------------------------- +#include +#pragma hdrstop + +//--------------------------------------------------------------------------- +#include "Form_Test.h" +// +#include "vtkActor.h" +#include "vtkAssemblyPath.h" +#include "vtkAssemblyNode.h" +#include "vtkElevationFilter.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkShrinkPolyData.h" +#include "vtkSphereSource.h" +#include "vtkTriangleFilter.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" + +//--------------------------------------------------------------------------- + +#pragma package(smart_init) +#pragma link "vtkBorlandRenderWindow" +#pragma resource "*.dfm" + +TVTK_Form *VTK_Form; +//--------------------------------------------------------------------------- +__fastcall TVTK_Form::TVTK_Form(TComponent* Owner) : TForm(Owner) +{ + shrink = NULL; +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::FormDestroy(TObject *Sender) +{ + if (shrink) + { + shrink->Delete(); + } + + // The release of graphics resources is required here in + // the event that an actor is switched between solid + // and wireframe representations. This cannot be implemented within + // vtkBorlandRenderWindow, since ReleaseGraphicsResources, when called + // by a vtkProp's mapper, will cause the internal vtkWin32OpenGLRenderWindow + // to fail during MakeCurrent. + + vtkRenderer* ren1 = vtkWindow1->GetRenderer(); + vtkRenderWindow* renwin1 = vtkWindow1->GetRenderWindow(); + + vtkPropCollection* collection = ren1->GetViewProps(); + if(collection) + { + collection->InitTraversal(); + for (int i = 0; i < collection->GetNumberOfItems(); i++) + { + vtkActor *actor = vtkActor::SafeDownCast(collection->GetNextProp()); + if(actor) + { + actor->ReleaseGraphicsResources(renwin1); + ren1->RemoveViewProp(actor); + } + } + } +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::HeaderControl1SectionClick(THeaderControl *HeaderControl, THeaderSection *Section) +{ + if (Section->Text=="Mode") + { + TPoint p = HeaderControl->ClientToScreen(TPoint(0,0)); + ModeMenu->Popup(p.x + Section->Left, p.y - 0); + } + else if (Section->Text=="Window") + { + TPoint p = HeaderControl->ClientToScreen(TPoint(0,0)); + WindowMenu->Popup(p.x + Section->Left, p.y - 0); + } +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::TrackBallMode1Click(TObject *Sender) +{ + if (Sender==JoystickMode1) + { + vtkWindow1->SetInteractorMode(IM_JoystickCamera); + JoystickMode1->Checked = true; + } + if (Sender==TrackBallMode1) + { + vtkWindow1->SetInteractorMode(IM_TrackballCamera); + TrackBallMode1->Checked = true; + } + if (Sender==FlightMode1) + { + vtkWindow1->SetInteractorMode(IM_Flight); + FlightMode1->Checked = true; + } +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::BackgroundColour1Click(TObject *Sender) +{ + if (!backgroundcolor->Execute()) + { + return; + } + DWORD L = ColorToRGB(backgroundcolor->Color); + double rgb[3] = { GetRValue(L)/255.0, GetGValue(L)/255.0, GetBValue(L)/255.0 }; + vtkWindow1->GetRenderer()->SetBackground(rgb); + vtkWindow1->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::ResetCamera1Click(TObject *Sender) +{ + vtkWindow1->GetRenderer()->ResetCamera(); + vtkWindow1->Invalidate(); +} +//--------------------------------------------------------------------------- +// +// +// Here's a demo +// +// +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::bc1Click(TObject *Sender) +{ + if (shrink) + { + return; + } + + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(36.0); + sphere->SetPhiResolution(18.0); + sphere->SetRadius(1.0); + + shrink = vtkShrinkPolyData::New(); + shrink->SetShrinkFactor( ShrinkScroll->Position/100.0 ); + shrink->SetInput( sphere->GetOutput() ); + + vtkElevationFilter *elev = vtkElevationFilter::New(); + elev->SetInput( shrink->GetOutput() ); + elev->SetLowPoint(-1,-1,-1); + elev->SetHighPoint( 1, 1, 1); + elev->SetScalarRange(0,1); + + vtkPolyDataMapper *aMapper = vtkPolyDataMapper::New(); + aMapper->SetInput( elev->GetPolyDataOutput() ); + aMapper->SetScalarRange(0,1); + + vtkActor *anActor = vtkActor::New(); + anActor->SetMapper(aMapper); + + // Use these functions to get the actual RenderWindow/Renderers. + vtkWindow1->GetRenderer()->AddActor(anActor); + + // We don't need these any more, they are reference counted by the + // pipeline and we can delete them. They'll be destructed when everything + // finishes. We'll keep a pointer to the shrinkfilter so we can use our + // scroller. + + anActor->Delete(); + aMapper->Delete(); + sphere->Delete(); + elev->Delete(); + + vtkWindow1->GetRenderer()->ResetCamera(); + vtkWindow1->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::ShrinkScrollChange(TObject *Sender) +{ + if (!shrink) + { + return; + } + shrink->SetShrinkFactor( ShrinkScroll->Position/100.0 ); + vtkWindow1->Invalidate(); +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::vtkWindow1Enter(TObject *Sender) +{ + BorderWindow->Color = clMaroon; +} +//--------------------------------------------------------------------------- +void __fastcall TVTK_Form::vtkWindow1Exit(TObject *Sender) +{ + BorderWindow->Color = clBtnFace; +} +//--------------------------------------------------------------------------- + +void __fastcall TVTK_Form::FormShow(TObject *Sender) +{ + // These calls are made to enforce creation of the internal + // vtk components of the vtkBorlandRenderWindow. If this were + // not done, clicking on the component would attempt to pass + // window messages to non-existent entities. This behaviour + // could be changed in future. + + vtkRenderWindowInteractor * iact = vtkWindow1->GetInteractor(); + vtkRenderer* ren1 = vtkWindow1->GetRenderer(); +} +//--------------------------------------------------------------------------- + + diff --git a/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.dfm b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.dfm new file mode 100644 index 0000000..905d79c --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.dfm @@ -0,0 +1,152 @@ +object VTK_Form: TVTK_Form + Left = 287 + Top = 176 + Width = 610 + Height = 480 + Caption = 'VTK_Form' + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + OldCreateOrder = True + OnDestroy = FormDestroy + OnShow = FormShow + PixelsPerInch = 96 + TextHeight = 13 + object Panel3: TPanel + Left = 0 + Top = 0 + Width = 101 + Height = 455 + Align = alLeft + BevelInner = bvLowered + BorderWidth = 2 + TabOrder = 0 + object Label1: TLabel + Left = 10 + Top = 46 + Width = 48 + Height = 13 + Caption = 'Shrinker...' + OnClick = BackgroundColour1Click + end + object bc1: TButton + Left = 11 + Top = 8 + Width = 75 + Height = 25 + Caption = 'Create 1' + TabOrder = 0 + OnClick = bc1Click + end + object ShrinkScroll: TScrollBar + Left = 10 + Top = 62 + Width = 72 + Height = 13 + PageSize = 0 + Position = 50 + TabOrder = 1 + OnChange = ShrinkScrollChange + end + end + object BorderWindow: TPanel + Left = 101 + Top = 0 + Width = 501 + Height = 455 + Align = alClient + BevelInner = bvLowered + BevelWidth = 2 + BorderWidth = 2 + TabOrder = 1 + object Panel2: TPanel + Left = 6 + Top = 432 + Width = 489 + Height = 17 + Align = alBottom + AutoSize = True + BevelOuter = bvNone + TabOrder = 0 + object HeaderControl1: THeaderControl + Left = 0 + Top = 0 + Width = 489 + Height = 17 + Align = alBottom + DragReorder = False + Sections = < + item + ImageIndex = -1 + MaxWidth = 60 + MinWidth = 60 + Text = 'Mode' + Width = 60 + end + item + ImageIndex = -1 + MaxWidth = 60 + MinWidth = 60 + Text = 'Window' + Width = 60 + end> + OnSectionClick = HeaderControl1SectionClick + end + end + object vtkWindow1: TvtkBorlandRenderWindow + Left = 6 + Top = 6 + Width = 489 + Height = 426 + Align = alClient + Color = clMenuText + ParentColor = False + TabOrder = 1 + OnEnter = vtkWindow1Enter + OnExit = vtkWindow1Exit + end + end + object ModeMenu: TPopupMenu + Left = 193 + Top = 56 + object TrackBallMode1: TMenuItem + Caption = 'TrackBall Mode' + Checked = True + GroupIndex = 1 + RadioItem = True + OnClick = TrackBallMode1Click + end + object JoystickMode1: TMenuItem + Caption = 'Joystick Mode' + GroupIndex = 1 + RadioItem = True + OnClick = TrackBallMode1Click + end + object FlightMode1: TMenuItem + Caption = 'Flight Mode' + GroupIndex = 1 + RadioItem = True + OnClick = TrackBallMode1Click + end + end + object WindowMenu: TPopupMenu + Left = 221 + Top = 56 + object BackgroundColour1: TMenuItem + Caption = 'Background Colour' + OnClick = BackgroundColour1Click + end + object ResetCamera1: TMenuItem + Caption = 'Reset Camera' + OnClick = ResetCamera1Click + end + end + object backgroundcolor: TColorDialog + Ctl3D = True + Left = 301 + Top = 56 + end +end diff --git a/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.h b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.h new file mode 100644 index 0000000..90a9c65 --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Form_Test.h @@ -0,0 +1,63 @@ +//--------------------------------------------------------------------------- +// +// Demo Borland + vtk Project, +// +//--------------------------------------------------------------------------- +#ifndef Form_TestH +#define Form_TestH +//--------------------------------------------------------------------------- +// VCL stuff +#include +#include +#include +#include +#include +#include +#include +#include +// + +#include "vtkBorlandRenderWindow.h" +// +class vtkShrinkPolyData; +//--------------------------------------------------------------------------- +class TVTK_Form : public TForm { + __published: // IDE-managed Components + TPanel *Panel3; + TButton *bc1; + TPanel *BorderWindow; + TPopupMenu *ModeMenu; + TMenuItem *TrackBallMode1; + TMenuItem *JoystickMode1; + TPopupMenu *WindowMenu; + TMenuItem *BackgroundColour1; + TMenuItem *ResetCamera1; + TColorDialog *backgroundcolor; + TPanel *Panel2; + THeaderControl *HeaderControl1; + TScrollBar *ShrinkScroll; + TLabel *Label1; + TMenuItem *FlightMode1; + TvtkBorlandRenderWindow *vtkWindow1; + void __fastcall FormDestroy(TObject *Sender); + void __fastcall bc1Click(TObject *Sender); + void __fastcall HeaderControl1SectionClick(THeaderControl *HeaderControl, THeaderSection *Section); + void __fastcall TrackBallMode1Click(TObject *Sender); + void __fastcall BackgroundColour1Click(TObject *Sender); + void __fastcall ResetCamera1Click(TObject *Sender); + void __fastcall ShrinkScrollChange(TObject *Sender); + void __fastcall vtkWindow1Enter(TObject *Sender); + void __fastcall vtkWindow1Exit(TObject *Sender); + void __fastcall FormShow(TObject *Sender); + + private: + public: + __fastcall TVTK_Form(TComponent* Owner); + + vtkShrinkPolyData *shrink; +}; +//--------------------------------------------------------------------------- +extern TVTK_Form *VTK_Form; +//--------------------------------------------------------------------------- +#endif + diff --git a/Examples/GUI/Win32/vtkBorland/ProjectDemo/Project_vtkDemo.bpr b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Project_vtkDemo.bpr new file mode 100644 index 0000000..798bb60 --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Project_vtkDemo.bpr @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=2057 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=Files\Borland\CBuilder6\Bin;D:\VTK\Examples\GUI\Win32\vtkBorland\Package;$(BCB)\include;$(BCB)\include\vcl;D:\VTK\Common;D:\VTK\Filtering;D:\VTK\Graphics;D:\VTK\Hybrid;D:\VTK\Imaging;D:\VTK\IO;D:\VTK\Rendering;D:\cmakebuild\vtkDebug +Item1=C:\Program Files\Borland\CBuilder6\Bin;D:\VTK\Examples\GUI\Win32\vtkBorland\ProjectDemo;$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=C:\Program Files\Borland\CBuilder6\Bin;D:\VTK\Examples\GUI\Win32\vtkBorland\ProjectDemo;c:\bin;$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[HistoryLists\hlConditionals] +Count=2 +Item0=_DEBUG;STRICT +Item1=_DEBUG + +[Debugging] +DebugSourceDirs=$(BCB)\source\vcl + +[Parameters] +RunParams= +Launcher= +UseLauncher=0 +DebugCWD= +HostApplication= +RemoteHost= +RemotePath= +RemoteLauncher= +RemoteCWD= +RemoteDebug=0 + +[Compiler] +ShowInfoMsgs=0 +LinkDebugVcl=0 +LinkCGLIB=0 + +[Language] +ActiveLang= +ProjectLang= +RootDir= + + \ No newline at end of file diff --git a/Examples/GUI/Win32/vtkBorland/ProjectDemo/Project_vtkDemo.cpp b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Project_vtkDemo.cpp new file mode 100644 index 0000000..a087f57 --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/ProjectDemo/Project_vtkDemo.cpp @@ -0,0 +1,32 @@ +//--------------------------------------------------------------------------- +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +USEFORM("Form_Test.cpp", VTK_Form); +//--------------------------------------------------------------------------- +WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + try + { + Application->Initialize(); + Application->CreateForm(__classid(TVTK_Form), &VTK_Form); + Application->Run(); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + catch (...) + { + try + { + throw Exception(""); + } + catch (Exception &exception) + { + Application->ShowException(&exception); + } + } + return 0; +} +//--------------------------------------------------------------------------- diff --git a/Examples/GUI/Win32/vtkBorland/Readme.txt b/Examples/GUI/Win32/vtkBorland/Readme.txt new file mode 100644 index 0000000..c646f2b --- /dev/null +++ b/Examples/GUI/Win32/vtkBorland/Readme.txt @@ -0,0 +1,163 @@ +Some Tips for Borland (C++ Builder) and VTK (4.n) +------------------------------------------------- + +Package Directory +----------------- +This contains a simple package which includes a RenderWindow Component. +Build the package and install it to the palette. If you have trouble loading +the package project, just create a new one and add in the code. +If you can't get the package built or you do not know how to do this, then +you ought to learn about C++ Builder before you play with VTK (the package +project is CBuilder 6, if you are using CBuilder 5, just create an empty +package and add vtkBorlandRenderWindow into it, then compile and install). + +Package creation steps +---------------------- +The following steps apply specifically to the Borland C++ Builder +(BCB) 5 IDE, but may work with later/earlier versions of the IDE. +These steps will establish a BCB package with one component, a +vtkBorlandRenderWindow, which may be dropped onto a form (etc.) +during GUI development in the IDE. These steps bypass the use of +and enable one to overwrite/create the package from scratch using the +unit file /vtkBorland/Package/vtkBorlandRenderWindow.cpp and its +header file /vtkBorland/Package/vtkBorlandRenderWindow.h. + +In the Borland C++ Builder IDE: + +1. Component->Install Component + Into new package + Unit file name: (Browse) + /vtkBorland/Package/vtkBorlandRenderWindow.cpp + Package file name: (Browse for directory and type) + vtkBorlandRenderWindowPkg + Package description: (as a suggestion) + VTK-Borland render window + a Confirm dialogue pops up: + 'Package vtkBorlandRenderWindowPkg will be built then installed' + choose no +2. Options->Compiler + choose debug or release +3. Options->Directories/Conditionals + Include path: + /VTK/Common + /VTK/Filtering + /VTK/Rendering + path to vtkConfigure.h + Library path: + path to vtk libs + Conditionals: + Add + 'STRICT' + *optionally, if you compile VTK with VTK_DEBUG_LEAKS:BOOL=ON, + you can also add VTK_DEBUG_LEAKS as a conditional. If so, + then you must add the following additional include directories: + /VTK/Graphics + /VTK/Imaging + /VTK/IO + /VTK/Utilities/vtkjpeg + /VTK/Utilities/vtkpng + /VTK/Utilities/vtkzlib + /VTK/Utilities/vtkfreetype + /VTK/Utilities/vtkftgl + and add the corresponding libs as in step 4 + +4. Add->Add Unit->Browse + Files of type: + choose Library file (*.lib) + find and choose + vtkCommon.lib + vtkFiltering.lib + vtkRendering.lib +5. Compile +6. Install + an Information popup should appear: + 'Package ...vtkBorlandRenderWindowPkg.bpl has been installed. + The following new component(s) have been registered: TvtkBorlandRenderWindow.' +7. File->Close All + choose Save +8. Check that there is an icon for the component on the palette under the Samples tab + + +ProjectDemo Directory +--------------------- +A simple project is provided that uses the vtkBorlandRenderWindow Component +above. The project files have been created in C++ Builder 6 and you may need to +delete/re-create them if you are using an earlier version of C++ Builder. +In particular, if you get link errors to rtl.bpi or rtl.lib, these used +to be named rtl50.bpi and vcl50.bpi, etc. + +The best thing to do is delete the project, create a new one, add in the files +and off you go. The demo project is very simple and should get you started. +Steps for building the demo project are the same as the package above, however +you will need to "use" the package too. + +Building the example in the IDE: + +1. File->New Application + this creates a blank form and unit +2. Project->Add to Project + browse and add the unit ..\vtkBorland\ProjectDemo\Form_Test.cpp +3. Project->Remove from Project + choose the default created 'Unit1.cpp' +4. Project->Options->Forms + choose VTK_Form form the list of available forms and add it to the + list of Auto-create forms if the list is empty + select VTK_Form as the sample project's Main form +5. Project->Options->Compiler + choose debug or release +6. Project->Options->Directories/Conditionals + Include path to header files: + path to /VTK/Common + path to /VTK/Filtering + path to /VTK/Graphics + path to /VTK/Rendering + path to vtkConfigure.h (in-source or out-of-source VTK build directory) + path to vtkBorlandRenderwindow.h + Library path: + path to Borland compiled VTK libs + Conditionals: + Add + 'STRICT' + Intermediate output: + your choice + Final output: + your choice +7. Project->Add to Project + browse and add the VTK libs: vtkCommon, vtkFiltering, vtkGraphics, vtkRendering +8. File->Save Project As + choose a name and save (e.g., Project1) +9. Project->Build Project1 + debug as required +10. Project->Run + +*This project was last successfully tested 140304 in both the BCB5 and BCB6 IDEs by Dean Inglis + +Conditional Defines +------------------- +You should use conditional defines STRICT; in each VTK based project you +work on. It may help solve some linking problems. STRICT causes the compiler +to strongly type HWND and prevents a compiler cough caused by defining +certain functions twice (because it thinks void* and HWND are the same +otherwise). + + +Directories +----------- +You must ensure that your project/options/directories includes the correct +VTK directory paths: e.g., +D:\vtk\Common;D:\vtk\Filtering;D:\vtk\Imaging;D:\vtk\Graphics;D:\vtk\IO; +D:\vtk\Rendering;D:\vtk\Hybrid; +and you also need to add in something like +D:\vtkbuild or wherever you build VTK into using cmake because the file +vtkConfigure.h is placed there and you need to include it. + +Make sure that you're projects link to the VTK libs and have the correct +directory in your lib dirs. You will usually need to link to +vtkCommon.lib; vtkFiltering.lib; vtkImaging.lib; vtkGraphics.lib; vtkO.lib; +vtkRendering.lib; vtkHybrid.lib. + +You can save some trouble by getting a project working with a minimal setup +and adding it to your repository as a vtk_project_template. This may save +re-doing directories and stuff frequently. + + diff --git a/Examples/GUI/Win32/vtkMFC/CMakeLists.txt b/Examples/GUI/Win32/vtkMFC/CMakeLists.txt new file mode 100644 index 0000000..95da16a --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/CMakeLists.txt @@ -0,0 +1,13 @@ +PROJECT(vtkMFC) + +FIND_PACKAGE(VTK) +IF(NOT VTK_DIR) + MESSAGE(FATAL_ERROR "Please set VTK_DIR.") +ENDIF(NOT VTK_DIR) +INCLUDE(${VTK_USE_FILE}) + +SUBDIRS( + vtkMDI + vtkSDI + vtkDLG +) diff --git a/Examples/GUI/Win32/vtkMFC/MDI_Instructions.chm b/Examples/GUI/Win32/vtkMFC/MDI_Instructions.chm new file mode 100644 index 0000000..070433c Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/MDI_Instructions.chm differ diff --git a/Examples/GUI/Win32/vtkMFC/Readme.txt b/Examples/GUI/Win32/vtkMFC/Readme.txt new file mode 100644 index 0000000..3c63916 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/Readme.txt @@ -0,0 +1,15 @@ +vtkMFC : Example MDI and SDI programs. +Contributed by Andrew J, P, Maclean + +The MDI_Instructions.chm and SDI_Instructions.chm help files included in +this directory refer to building/creating MSVC project files manually. + +It is preferable to use CMake to generate project files for these demos. + +To do this, run cmake and use the project directory of +your_path_here/VTK/Examples/GUI/Win32/vtkMFC +after CMake has completed, check the build directory that you chose in CMake +and there will be project files for either MSVC 6 or MSVC 7 etc depending +upon your output/compiler selection. + +You can now load these projects into VC and build them. \ No newline at end of file diff --git a/Examples/GUI/Win32/vtkMFC/SDI_Instructions.chm b/Examples/GUI/Win32/vtkMFC/SDI_Instructions.chm new file mode 100644 index 0000000..de71f7b Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/SDI_Instructions.chm differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/CMakeLists.txt b/Examples/GUI/Win32/vtkMFC/vtkDLG/CMakeLists.txt new file mode 100644 index 0000000..de700f0 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/CMakeLists.txt @@ -0,0 +1,26 @@ + +SET( vtkDLG_SRCS + StdAfx + vtkDLG + vtkDLGDlg + vtkDLG.rc + res/vtkDLG.ico + res/vtkDLG.rc2 +) + +LINK_LIBRARIES( + vtkMFC + vtkRendering + vtkGraphics + vtkImaging + vtkIO + vtkFiltering + vtkCommon +) + + +# add stuff to use MFC in this executable +ADD_DEFINITIONS(-D_AFXDLL) +SET(CMAKE_MFC_FLAG 6) + +ADD_EXECUTABLE(vtkDLG WIN32 ${vtkDLG_SRCS}) diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/res/vtkDLG.ico b/Examples/GUI/Win32/vtkMFC/vtkDLG/res/vtkDLG.ico new file mode 100644 index 0000000..8a84ca3 Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/vtkDLG/res/vtkDLG.ico differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/res/vtkDLG.rc2 b/Examples/GUI/Win32/vtkMFC/vtkDLG/res/vtkDLG.rc2 new file mode 100644 index 0000000..4299e99 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/res/vtkDLG.rc2 @@ -0,0 +1,13 @@ +// +// vtkDLG.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/resource.h b/Examples/GUI/Win32/vtkMFC/vtkDLG/resource.h new file mode 100644 index 0000000..d0eff57 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/resource.h @@ -0,0 +1,24 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by vtkDLG.rc +// +#define IDM_ABOUTBOX 0x0010 +#define IDD_ABOUTBOX 100 +#define IDS_ABOUTBOX 101 +#define IDD_VTKDLG_DIALOG 102 +#define ID_LOADFILE 103 +#define ID_LOADFILE2 104 +#define ID_RESETSCENE 105 +#define IDR_MAINFRAME 128 +#define IDC_MAIN_WND 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 106 +#endif +#endif diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/stdafx.cpp b/Examples/GUI/Win32/vtkMFC/vtkDLG/stdafx.cpp new file mode 100644 index 0000000..1120942 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/stdafx.cpp @@ -0,0 +1,7 @@ +// stdafx.cpp : source file that includes just the standard includes +// vtkDLG.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/stdafx.h b/Examples/GUI/Win32/vtkMFC/vtkDLG/stdafx.h new file mode 100644 index 0000000..57c9d49 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/stdafx.h @@ -0,0 +1,52 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. +#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. +#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. +#define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later. +#endif + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off MFC's hiding of some common and often safely ignored warning messages +#define _AFX_ALL_WARNINGS + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +// Include the required header files for the vtk classes we are using +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.cpp b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.cpp new file mode 100644 index 0000000..2895001 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.cpp @@ -0,0 +1,73 @@ +// vtkDLG.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "vtkDLG.h" +#include "vtkDLGDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CvtkDLGApp + +BEGIN_MESSAGE_MAP(CvtkDLGApp, CWinApp) + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + + +// CvtkDLGApp construction + +CvtkDLGApp::CvtkDLGApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + + +// The one and only CvtkDLGApp object + +CvtkDLGApp theApp; + + +// CvtkDLGApp initialization + +BOOL CvtkDLGApp::InitInstance() +{ + // InitCommonControls() is required on Windows XP if an application + // manifest specifies use of ComCtl32.dll version 6 or later to enable + // visual styles. Otherwise, any window creation will fail. + InitCommonControls(); + + CWinApp::InitInstance(); + + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need + // Change the registry key under which our settings are stored + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + + CvtkDLGDlg dlg; + m_pMainWnd = &dlg; + INT_PTR nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.h b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.h new file mode 100644 index 0000000..69b99a2 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.h @@ -0,0 +1,31 @@ +// vtkDLG.h : main header file for the PROJECT_NAME application +// + +#pragma once + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + + +// CvtkDLGApp: +// See vtkDLG.cpp for the implementation of this class +// + +class CvtkDLGApp : public CWinApp +{ +public: + CvtkDLGApp(); + +// Overrides + public: + virtual BOOL InitInstance(); + +// Implementation + + DECLARE_MESSAGE_MAP() +}; + +extern CvtkDLGApp theApp; diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.rc b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.rc new file mode 100644 index 0000000..b855945 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLG.rc @@ -0,0 +1,212 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#include ""res\\vtkDLG.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\vtkDLG.ico" +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "About vtkDLG" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "vtkDLG Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2004",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,16,WS_GROUP +END + +IDD_VTKDLG_DIALOG DIALOGEX 0, 0, 320, 200 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +EXSTYLE WS_EX_APPWINDOW +CAPTION "vtkDLG" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,7,50,16 + CONTROL "",IDC_MAIN_WND,"Static",SS_OWNERDRAW,65,7,248,186 + PUSHBUTTON "Load File",ID_LOADFILE,7,36,50,16 + PUSHBUTTON "Reset Scene",ID_RESETSCENE,7,65,50,16 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "TODO: " + VALUE "FileDescription", "TODO: " + VALUE "FileVersion", "1.0.0.1" + VALUE "InternalName", "vtkDLG.exe" + VALUE "LegalCopyright", "TODO: (c) . All rights reserved." + VALUE "OriginalFilename", "vtkDLG.exe" + VALUE "ProductName", "TODO: " + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END + + IDD_VTKDLG_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 313 + TOPMARGIN, 7 + BOTTOMMARGIN, 193 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_ABOUTBOX "&About vtkDLG..." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#include "res\vtkDLG.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLGDlg.cpp b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLGDlg.cpp new file mode 100644 index 0000000..7c07197 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLGDlg.cpp @@ -0,0 +1,311 @@ +// vtkDLGDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "vtkDLG.h" +#include "vtkDLGDlg.h" + +#include "vtkCallbackCommand.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + enum { IDD = IDD_ABOUTBOX }; + + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + +// Implementation +protected: + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) +END_MESSAGE_MAP() + + +// CvtkDLGDlg dialog + +CvtkDLGDlg::CvtkDLGDlg(CWnd* pParent /*=NULL*/) + : CDialog(CvtkDLGDlg::IDD, pParent) +{ + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); + + this->pvtkMFCWindow = NULL; + + // set data reader to null + this->pvtkDataSetReader = NULL; + + // Create the the renderer, window and interactor objects. + this->pvtkRenderer = vtkRenderer::New(); + + // Create the the objects used to form the visualisation. + this->pvtkDataSetMapper = vtkDataSetMapper::New(); + this->pvtkActor = vtkActor::New(); + this->pvtkActor2D = vtkActor2D::New(); + this->pvtkTextMapper = vtkTextMapper::New(); + + this->ptBorder = CPoint(0,0); +} + +void CvtkDLGDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CvtkDLGDlg, CDialog) + ON_WM_SYSCOMMAND() + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP + ON_WM_DESTROY() + ON_WM_SIZE() + ON_BN_CLICKED(ID_LOADFILE, OnBtnLoadFile) + ON_BN_CLICKED(ID_RESETSCENE, OnBtnResetScene) +END_MESSAGE_MAP() + + +// CvtkDLGDlg message handlers + +void CvtkDLGDlg::ExecutePipeline() +{ + if (pvtkDataSetReader) // have file + { + this->pvtkDataSetMapper->SetInput(pvtkDataSetReader->GetOutput()); + this->pvtkActor->SetMapper(this->pvtkDataSetMapper); + + this->pvtkTextMapper->SetInput(pvtkDataSetReader->GetFileName()); + this->pvtkTextMapper->GetTextProperty()->SetFontSize(12); + this->pvtkActor2D->SetMapper(this->pvtkTextMapper); + + this->pvtkRenderer->SetBackground(0.0,0.0,0.4); + this->pvtkRenderer->AddActor(this->pvtkActor); + this->pvtkRenderer->AddActor(this->pvtkActor2D); + } + else // have no file + { + this->pvtkTextMapper->SetInput("Hello World"); + this->pvtkTextMapper->GetTextProperty()->SetFontSize(24); + this->pvtkActor2D->SetMapper(this->pvtkTextMapper); + + this->pvtkRenderer->SetBackground(0.0,0.0,0.4); + this->pvtkRenderer->AddActor(this->pvtkActor2D); + } + this->pvtkRenderer->ResetCamera(); +} + +static void handle_double_click(vtkObject* obj, unsigned long, + void*, void*) +{ + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj); + if(iren && iren->GetRepeatCount()) + { + AfxMessageBox("Double Click"); + } +} + + +BOOL CvtkDLGDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Add "About..." menu item to system menu. + + // IDM_ABOUTBOX must be in the system command range. + ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); + ASSERT(IDM_ABOUTBOX < 0xF000); + + CMenu* pSysMenu = GetSystemMenu(FALSE); + if (pSysMenu != NULL) + { + CString strAboutMenu; + strAboutMenu.LoadString(IDS_ABOUTBOX); + if (!strAboutMenu.IsEmpty()) + { + pSysMenu->AppendMenu(MF_SEPARATOR); + pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); + } + } + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // adjust dialog & window size + this->pvtkMFCWindow = new vtkMFCWindow(this->GetDlgItem(IDC_MAIN_WND)); + // get double click events + vtkCallbackCommand* callback = vtkCallbackCommand::New(); + callback->SetCallback(handle_double_click); + this->pvtkMFCWindow->GetInteractor()->AddObserver(vtkCommand::LeftButtonPressEvent, callback, 1.0); + + + CRect cRectVTK; + this->pvtkMFCWindow->GetClientRect(&cRectVTK); + + CRect cRectClient; + GetClientRect(&cRectClient); + + this->ptBorder.x = cRectClient.Width() - cRectVTK.Width(); + this->ptBorder.y = cRectClient.Height() - cRectVTK.Height(); + + // set the vtk renderer, windows, etc + this->pvtkMFCWindow->GetRenderWindow()->AddRenderer(this->pvtkRenderer); + + // execute object pipeline + ExecutePipeline(); + + return TRUE; // return TRUE unless you set the focus to a control +} + +void CvtkDLGDlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xFFF0) == IDM_ABOUTBOX) + { + CAboutDlg dlgAbout; + dlgAbout.DoModal(); + } + else + { + CDialog::OnSysCommand(nID, lParam); + } +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CvtkDLGDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this function to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CvtkDLGDlg::OnQueryDragIcon() +{ + return static_cast(m_hIcon); +} + +void CvtkDLGDlg::OnDestroy() +{ + // delete data + if (this->pvtkDataSetReader) this->pvtkDataSetReader->Delete(); + + // Delete the the renderer, window and interactor objects. + if (this->pvtkRenderer) this->pvtkRenderer->Delete(); + + // Delete the the objects used to form the visualisation. + if (this->pvtkDataSetMapper) this->pvtkDataSetMapper->Delete(); + if (this->pvtkActor) this->pvtkActor->Delete(); + if (this->pvtkActor2D) this->pvtkActor2D->Delete(); + if (this->pvtkTextMapper) this->pvtkTextMapper->Delete(); + + if (this->pvtkMFCWindow) + { + delete this->pvtkMFCWindow; + } + + CDialog::OnDestroy(); +} + +void CvtkDLGDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + + if (::IsWindow(this->GetSafeHwnd())) + { + if (this->pvtkMFCWindow) + { + cx -= ptBorder.x; + cy -= ptBorder.y; + this->GetDlgItem(IDC_MAIN_WND)->SetWindowPos(NULL, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + this->pvtkMFCWindow->SetWindowPos(NULL, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + } + } +} + +void CvtkDLGDlg::OnBtnLoadFile() +{ + static char BASED_CODE szFilter[] = "VTK Files (*.vtk)|*.vtk|All Files (*.*)|*.*||"; + CFileDialog cFileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter); + + if (cFileDialog.DoModal() == IDOK) + { + // remove old actors + this->pvtkRenderer->RemoveActor(this->pvtkActor); + this->pvtkRenderer->RemoveActor(this->pvtkActor2D); + + // read new data + if (!this->pvtkDataSetReader) + this->pvtkDataSetReader = vtkDataSetReader::New(); + this->pvtkDataSetReader->SetFileName(cFileDialog.GetPathName()); + + // execute object pipeline + ExecutePipeline(); + + // update window + if (this->pvtkMFCWindow) + this->pvtkMFCWindow->RedrawWindow(); + } +} + +void CvtkDLGDlg::OnBtnResetScene() +{ + // remove old actors + this->pvtkRenderer->RemoveActor(this->pvtkActor); + this->pvtkRenderer->RemoveActor(this->pvtkActor2D); + + // delete data + if (this->pvtkDataSetReader) + { + this->pvtkDataSetReader->Delete(); + this->pvtkDataSetReader = NULL; + } + + // execute object pipeline + ExecutePipeline(); + + // update window + if (this->pvtkMFCWindow) + this->pvtkMFCWindow->RedrawWindow(); +} diff --git a/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLGDlg.h b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLGDlg.h new file mode 100644 index 0000000..b3e41f7 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkDLG/vtkDLGDlg.h @@ -0,0 +1,44 @@ +// vtkDLGDlg.h : header file +// + +#pragma once + +#include "vtkMFCWindow.h" + +// CvtkDLGDlg dialog +class CvtkDLGDlg : public CDialog +{ +public: + CvtkDLGDlg(CWnd* pParent = NULL); // standard constructor + + enum { IDD = IDD_VTKDLG_DIALOG }; + + afx_msg void OnDestroy(); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnBtnLoadFile(); + afx_msg void OnBtnResetScene(); + +private: + void ExecutePipeline(); + + vtkMFCWindow *pvtkMFCWindow; + + vtkDataSetReader *pvtkDataSetReader; + vtkRenderer *pvtkRenderer; + vtkDataSetMapper *pvtkDataSetMapper; + vtkActor *pvtkActor; + vtkActor2D *pvtkActor2D; + vtkTextMapper *pvtkTextMapper; + + POINT ptBorder; + HICON m_hIcon; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + + DECLARE_MESSAGE_MAP() +}; diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/CMakeLists.txt b/Examples/GUI/Win32/vtkMFC/vtkMDI/CMakeLists.txt new file mode 100644 index 0000000..9912d42 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/CMakeLists.txt @@ -0,0 +1,30 @@ +SET( vtkMDI_SRCS + MainFrm + ChildFrm + StdAfx + vtkMDI + vtkMDI.rc + vtkMDIDoc + vtkMDIView + res/vtkMDI.ico + res/vtkMDI.rc2 + res/vtkMDIDoc.ico + res/Toolbar.bmp +) + +LINK_LIBRARIES( + vtkMFC + vtkRendering + vtkGraphics + vtkImaging + vtkIO + vtkFiltering + vtkCommon +) + + +# add stuff to use MFC in this executable +ADD_DEFINITIONS(-D_AFXDLL) +SET(CMAKE_MFC_FLAG 6) + +ADD_EXECUTABLE(vtkMDI WIN32 ${vtkMDI_SRCS}) diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/ChildFrm.cpp b/Examples/GUI/Win32/vtkMFC/vtkMDI/ChildFrm.cpp new file mode 100644 index 0000000..0d67d5c --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/ChildFrm.cpp @@ -0,0 +1,59 @@ +// ChildFrm.cpp : implementation of the CChildFrame class +// +#include "stdafx.h" +#include "vtkMDI.h" + +#include "ChildFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CChildFrame + +IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) + +BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) +END_MESSAGE_MAP() + + +// CChildFrame construction/destruction + +CChildFrame::CChildFrame() +{ + // TODO: add member initialization code here +} + +CChildFrame::~CChildFrame() +{ +} + + +BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying the CREATESTRUCT cs + if( !CMDIChildWnd::PreCreateWindow(cs) ) + return FALSE; + + return TRUE; +} + + +// CChildFrame diagnostics + +#ifdef _DEBUG +void CChildFrame::AssertValid() const +{ + CMDIChildWnd::AssertValid(); +} + +void CChildFrame::Dump(CDumpContext& dc) const +{ + CMDIChildWnd::Dump(dc); +} + +#endif //_DEBUG + + +// CChildFrame message handlers diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/ChildFrm.h b/Examples/GUI/Win32/vtkMFC/vtkMDI/ChildFrm.h new file mode 100644 index 0000000..fe1b7a0 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/ChildFrm.h @@ -0,0 +1,34 @@ +// ChildFrm.h : interface of the CChildFrame class +// + + +#pragma once + + +class CChildFrame : public CMDIChildWnd +{ + DECLARE_DYNCREATE(CChildFrame) +public: + CChildFrame(); + +// Attributes +public: + +// Operations +public: + +// Overrides + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + +// Implementation +public: + virtual ~CChildFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + DECLARE_MESSAGE_MAP() +}; diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/MainFrm.cpp b/Examples/GUI/Win32/vtkMFC/vtkMDI/MainFrm.cpp new file mode 100644 index 0000000..d16b212 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/MainFrm.cpp @@ -0,0 +1,99 @@ +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "vtkMDI.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CMainFrame + +IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) + ON_WM_CREATE() +END_MESSAGE_MAP() + +static UINT indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + + +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here +} + +CMainFrame::~CMainFrame() +{ +} + + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + // TODO: Delete these three lines if you don't want the toolbar to be dockable + m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + DockControlBar(&m_wndToolBar); + + return 0; +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CMDIFrameWnd::PreCreateWindow(cs) ) + return FALSE; + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return TRUE; +} + + +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CMDIFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CMDIFrameWnd::Dump(dc); +} + +#endif //_DEBUG + + +// CMainFrame message handlers + diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/MainFrm.h b/Examples/GUI/Win32/vtkMFC/vtkMDI/MainFrm.h new file mode 100644 index 0000000..d233b76 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/MainFrm.h @@ -0,0 +1,40 @@ +// MainFrm.h : interface of the CMainFrame class +// + + +#pragma once +class CMainFrame : public CMDIFrameWnd +{ + DECLARE_DYNAMIC(CMainFrame) +public: + CMainFrame(); + +// Attributes +public: + +// Operations +public: + +// Overrides +public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + +// Generated message map functions +protected: + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + DECLARE_MESSAGE_MAP() +}; + + diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/Resource.h b/Examples/GUI/Win32/vtkMFC/vtkMDI/Resource.h new file mode 100644 index 0000000..540346b --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/Resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by vtkMDI.rc +// +#define IDD_ABOUTBOX 100 +#define IDR_MAINFRAME 128 +#define IDR_vtkMDITYPE 129 +#define IDR_MANIFEST CREATEPROCESS_MANIFEST_RESOURCE_ID + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 32771 +#endif +#endif diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/StdAfx.cpp b/Examples/GUI/Win32/vtkMFC/vtkMDI/StdAfx.cpp new file mode 100644 index 0000000..ec18fd3 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/StdAfx.cpp @@ -0,0 +1,7 @@ +// stdafx.cpp : source file that includes just the standard includes +// vtkMDI.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/StdAfx.h b/Examples/GUI/Win32/vtkMFC/vtkMDI/StdAfx.h new file mode 100644 index 0000000..2d6cfba --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/StdAfx.h @@ -0,0 +1,52 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. +#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. +#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. +#define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later. +#endif + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off MFC's hiding of some common and often safely ignored warning messages +#define _AFX_ALL_WARNINGS + +#include // MFC core and standard components +#include // MFC extensions + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +// Include the required header files for the vtk classes we are using +#include +#include +#include +#include +#include +#include +#include +#include +#include + diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/res/Toolbar.bmp b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/Toolbar.bmp new file mode 100644 index 0000000..d501723 Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/Toolbar.bmp differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDI.ico b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDI.ico new file mode 100644 index 0000000..7eef0bc Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDI.ico differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDI.rc2 b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDI.rc2 new file mode 100644 index 0000000..0678b47 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDI.rc2 @@ -0,0 +1,13 @@ +// +// VTKMDI.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDIDoc.ico b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDIDoc.ico new file mode 100644 index 0000000..2a1f1ae Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/vtkMDI/res/vtkMDIDoc.ico differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.cpp b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.cpp new file mode 100644 index 0000000..828c12f --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.cpp @@ -0,0 +1,133 @@ +// vtkMDI.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "vtkMDI.h" +#include "MainFrm.h" + +#include "ChildFrm.h" +#include "vtkMDIDoc.h" +#include "vtkMDIView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CvtkMDIApp + +BEGIN_MESSAGE_MAP(CvtkMDIApp, CWinApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) + // Standard print setup command + ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) +END_MESSAGE_MAP() + + +// CvtkMDIApp construction + +CvtkMDIApp::CvtkMDIApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + + +// The one and only CvtkMDIApp object + +CvtkMDIApp theApp; + +// CvtkMDIApp initialization + +BOOL CvtkMDIApp::InitInstance() +{ + // InitCommonControls() is required on Windows XP if an application + // manifest specifies use of ComCtl32.dll version 6 or later to enable + // visual styles. Otherwise, any window creation will fail. + InitCommonControls(); + + CWinApp::InitInstance(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need + // Change the registry key under which our settings are stored + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + LoadStdProfileSettings(4); // Load standard INI file options (including MRU) + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views + CMultiDocTemplate* pDocTemplate; + pDocTemplate = new CMultiDocTemplate(IDR_vtkMDITYPE, + RUNTIME_CLASS(CvtkMDIDoc), + RUNTIME_CLASS(CChildFrame), // custom MDI child frame + RUNTIME_CLASS(CvtkMDIView)); + if (!pDocTemplate) + return FALSE; + AddDocTemplate(pDocTemplate); + // create main MDI Frame window + CMainFrame* pMainFrame = new CMainFrame; + if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) + return FALSE; + m_pMainWnd = pMainFrame; + // call DragAcceptFiles only if there's a suffix + // In an MDI app, this should occur immediately after setting m_pMainWnd + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + // Dispatch commands specified on the command line. Will return FALSE if + // app was launched with /RegServer, /Register, /Unregserver or /Unregister. + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + // The main window has been initialized, so show and update it + pMainFrame->ShowWindow(m_nCmdShow); + pMainFrame->UpdateWindow(); + return TRUE; +} + + + +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + enum { IDD = IDD_ABOUTBOX }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + +// Implementation +protected: + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) +END_MESSAGE_MAP() + +// App command to run the dialog +void CvtkMDIApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + + +// CvtkMDIApp message handlers + diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.h b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.h new file mode 100644 index 0000000..f894069 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.h @@ -0,0 +1,31 @@ +// vtkMDI.h : main header file for the vtkMDI application +// +#pragma once + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + + +// CvtkMDIApp: +// See vtkMDI.cpp for the implementation of this class +// + +class CvtkMDIApp : public CWinApp +{ +public: + CvtkMDIApp(); + + +// Overrides +public: + virtual BOOL InitInstance(); + +// Implementation + afx_msg void OnAppAbout(); + DECLARE_MESSAGE_MAP() +}; + +extern CvtkMDIApp theApp; diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.rc b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.rc new file mode 100644 index 0000000..eafa5d3 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDI.rc @@ -0,0 +1,436 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#include ""res\\vtkMDI.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#include ""afxprint.rc"" // printing/print preview resources\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\vtkMDI.ico" +IDR_vtkMDITYPE ICON "res\\vtkMDIDoc.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP "res\\Toolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_MAINFRAME TOOLBAR 16, 15 +BEGIN + BUTTON ID_FILE_NEW + BUTTON ID_FILE_OPEN + BUTTON ID_FILE_SAVE + SEPARATOR + BUTTON ID_EDIT_CUT + BUTTON ID_EDIT_COPY + BUTTON ID_EDIT_PASTE + SEPARATOR + BUTTON ID_FILE_PRINT + BUTTON ID_APP_ABOUT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN + MENUITEM SEPARATOR + MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP + MENUITEM SEPARATOR + MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Close", ID_FILE_CLOSE + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&View" + BEGIN + MENUITEM "&Toolbar", ID_VIEW_TOOLBAR + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About vtkMDI...", ID_APP_ABOUT + END +END + +IDR_vtkMDITYPE MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN + MENUITEM "&Close", ID_FILE_CLOSE + MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE + MENUITEM "Save &As...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT + MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW + MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP + MENUITEM SEPARATOR + MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT + MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE + END + POPUP "&View" + BEGIN + MENUITEM "&Toolbar", ID_VIEW_TOOLBAR + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Window" + BEGIN + MENUITEM "&New Window", ID_WINDOW_NEW + MENUITEM "&Cascade", ID_WINDOW_CASCADE + MENUITEM "&Tile", ID_WINDOW_TILE_HORZ + MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE + END + POPUP "&Help" + BEGIN + MENUITEM "&About vtkMDI...", ID_APP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS +BEGIN + "N", ID_FILE_NEW, VIRTKEY, CONTROL + "O", ID_FILE_OPEN, VIRTKEY, CONTROL + "S", ID_FILE_SAVE, VIRTKEY, CONTROL + "P", ID_FILE_PRINT, VIRTKEY, CONTROL + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL + "X", ID_EDIT_CUT, VIRTKEY, CONTROL + "C", ID_EDIT_COPY, VIRTKEY, CONTROL + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL + VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT + VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT + VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL + VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT + VK_F6, ID_NEXT_PANE, VIRTKEY + VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "About vtkMDI" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "vtkMDI Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2004",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,16,WS_GROUP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "TODO: " + VALUE "FileDescription", "TODO: " + VALUE "FileVersion", "1.0.0.1" + VALUE "InternalName", "vtkMDI.exe" + VALUE "LegalCopyright", "TODO: (c) . All rights reserved." + VALUE "OriginalFilename", "vtkMDI.exe" + VALUE "ProductName", "TODO: " + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDR_MAINFRAME "vtkMDI" + IDR_vtkMDITYPE "\nvtkMDI\nvtkMDI\nVTK Files (*.vtk)\n.vtk\nvtkMDI.Document\nvtkMDI.Document" +END + +STRINGTABLE +BEGIN + AFX_IDS_APP_TITLE "vtkMDI" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE +BEGIN + ID_FILE_NEW "Create a new document\nNew" + ID_FILE_OPEN "Open an existing document\nOpen" + ID_FILE_CLOSE "Close the active document\nClose" + ID_FILE_SAVE "Save the active document\nSave" + ID_FILE_SAVE_AS "Save the active document with a new name\nSave As" + ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup" + ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup" + ID_FILE_PRINT "Print the active document\nPrint" + ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview" +END + +STRINGTABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright\nAbout" + ID_APP_EXIT "Quit the application; prompts to save documents\nExit" +END + +STRINGTABLE +BEGIN + ID_FILE_MRU_FILE1 "Open this document" + ID_FILE_MRU_FILE2 "Open this document" + ID_FILE_MRU_FILE3 "Open this document" + ID_FILE_MRU_FILE4 "Open this document" + ID_FILE_MRU_FILE5 "Open this document" + ID_FILE_MRU_FILE6 "Open this document" + ID_FILE_MRU_FILE7 "Open this document" + ID_FILE_MRU_FILE8 "Open this document" + ID_FILE_MRU_FILE9 "Open this document" + ID_FILE_MRU_FILE10 "Open this document" + ID_FILE_MRU_FILE11 "Open this document" + ID_FILE_MRU_FILE12 "Open this document" + ID_FILE_MRU_FILE13 "Open this document" + ID_FILE_MRU_FILE14 "Open this document" + ID_FILE_MRU_FILE15 "Open this document" + ID_FILE_MRU_FILE16 "Open this document" +END + +STRINGTABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane\nNext Pane" + ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" +END + +STRINGTABLE +BEGIN + ID_WINDOW_NEW "Open another window for the active document\nNew Window" + ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons" + ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows" + ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows" + ID_WINDOW_SPLIT "Split the active window into panes\nSplit" +END + +STRINGTABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection\nErase" + ID_EDIT_CLEAR_ALL "Erase everything\nErase All" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" + ID_EDIT_FIND "Find the specified text\nFind" + ID_EDIT_PASTE "Insert Clipboard contents\nPaste" + ID_EDIT_REPEAT "Repeat the last action\nRepeat" + ID_EDIT_REPLACE "Replace specific text with different text\nReplace" + ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" + ID_EDIT_UNDO "Undo the last action\nUndo" + ID_EDIT_REDO "Redo the previously undone action\nRedo" +END + +STRINGTABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" + ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" + AFX_IDS_MDICHILD "Activate this window" +END + +STRINGTABLE +BEGIN + AFX_IDS_PREVIEW_CLOSE "Close print preview mode\nCancel Preview" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#include "res\vtkMDI.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#include "afxprint.rc" // printing/print preview resources +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIDoc.cpp b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIDoc.cpp new file mode 100644 index 0000000..f9d2820 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIDoc.cpp @@ -0,0 +1,97 @@ +// vtkMDIDoc.cpp : implementation of the CvtkMDIDoc class +// + +#include "stdafx.h" +#include "vtkMDI.h" + +#include "vtkMDIDoc.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CvtkMDIDoc + +IMPLEMENT_DYNCREATE(CvtkMDIDoc, CDocument) + +BEGIN_MESSAGE_MAP(CvtkMDIDoc, CDocument) +END_MESSAGE_MAP() + + +// CvtkMDIDoc construction/destruction + +CvtkMDIDoc::CvtkMDIDoc() +{ + // TODO: add one-time construction code here + this->pvtkDataSetReader = NULL; +} + +CvtkMDIDoc::~CvtkMDIDoc() +{ +} + +BOOL CvtkMDIDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + + + + +// CvtkMDIDoc serialization + +void CvtkMDIDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + + +// CvtkMDIDoc diagnostics + +#ifdef _DEBUG +void CvtkMDIDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CvtkMDIDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + + +// CvtkMDIDoc commands + +BOOL CvtkMDIDoc::OnOpenDocument(LPCTSTR lpszPathName) +{ + if (!CDocument::OnOpenDocument(lpszPathName)) + return FALSE; + + this->pvtkDataSetReader = vtkDataSetReader::New(); + this->pvtkDataSetReader->SetFileName(lpszPathName); + + return TRUE; +} + +void CvtkMDIDoc::OnCloseDocument() +{ + // delete data + if (this->pvtkDataSetReader) this->pvtkDataSetReader->Delete(); + + CDocument::OnCloseDocument(); +} diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIDoc.h b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIDoc.h new file mode 100644 index 0000000..2b91991 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIDoc.h @@ -0,0 +1,41 @@ +// vtkMDIDoc.h : interface of the CvtkMDIDoc class +// + + +#pragma once + +class CvtkMDIDoc : public CDocument +{ +protected: // create from serialization only + CvtkMDIDoc(); + DECLARE_DYNCREATE(CvtkMDIDoc) + +// Attributes +public: + vtkDataSetReader *pvtkDataSetReader; + +// Operations +public: + +// Overrides + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + +// Implementation +public: + virtual ~CvtkMDIDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +// Generated message map functions +protected: + DECLARE_MESSAGE_MAP() +public: + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual void OnCloseDocument(); +}; + + diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIView.cpp b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIView.cpp new file mode 100644 index 0000000..38ce24b --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIView.cpp @@ -0,0 +1,187 @@ +#include "stdafx.h" +#include "vtkMDI.h" + +#include "vtkMDIDoc.h" +#include "vtkMDIView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +IMPLEMENT_DYNCREATE(CvtkMDIView, CView) + +BEGIN_MESSAGE_MAP(CvtkMDIView, CView) + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_WM_DESTROY() + ON_WM_CREATE() + ON_WM_LBUTTONDBLCLK() + ON_WM_SIZE() + ON_WM_ERASEBKGND() + ON_WM_SIZE() +END_MESSAGE_MAP() + + +CvtkMDIView::CvtkMDIView() +{ + this->pvtkMFCWindow = NULL; + + // Create the the renderer, window and interactor objects. + this->pvtkRenderer = vtkRenderer::New(); + + // Create the the objects used to form the visualisation. + this->pvtkDataSetMapper = vtkDataSetMapper::New(); + this->pvtkActor = vtkActor::New(); + this->pvtkActor2D = vtkActor2D::New(); + this->pvtkTextMapper = vtkTextMapper::New(); +} + +CvtkMDIView::~CvtkMDIView() +{ + // delete generic vtk window + if (this->pvtkMFCWindow) delete this->pvtkMFCWindow; +} + +// CvtkMDIView drawing +void CvtkMDIView::OnDraw(CDC* pDC) +{ + CvtkMDIDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if (this->pvtkMFCWindow) + { + if (pDC->IsPrinting()) + this->pvtkMFCWindow->DrawDC(pDC); + } +} + + +// CvtkMDIView printing + +BOOL CvtkMDIView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CvtkMDIView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CvtkMDIView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + + +// CvtkMDIView diagnostics + +#ifdef _DEBUG +void CvtkMDIView::AssertValid() const +{ + CView::AssertValid(); +} + +void CvtkMDIView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CvtkMDIDoc* CvtkMDIView::GetDocument() const // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CvtkMDIDoc))); + return (CvtkMDIDoc*)m_pDocument; +} +#endif //_DEBUG + + +// CvtkMDIView message handlers + +void CvtkMDIView::ExecutePipeline() +{ + CvtkMDIDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + if (!pDoc) + return; + + if (pDoc->pvtkDataSetReader) // have file + { + this->pvtkDataSetMapper->SetInput(this->GetDocument()->pvtkDataSetReader->GetOutput()); + this->pvtkActor->SetMapper(this->pvtkDataSetMapper); + + this->pvtkTextMapper->SetInput(this->GetDocument()->pvtkDataSetReader->GetFileName()); + this->pvtkTextMapper->GetTextProperty()->SetFontSize(12); + this->pvtkActor2D->SetMapper(this->pvtkTextMapper); + + this->pvtkRenderer->SetBackground(0.0,0.0,0.4); + this->pvtkRenderer->AddActor(this->pvtkActor); + this->pvtkRenderer->AddActor(this->pvtkActor2D); + } + else // have no file + { + this->pvtkTextMapper->SetInput("Hello World"); + this->pvtkTextMapper->GetTextProperty()->SetFontSize(24); + this->pvtkActor2D->SetMapper(this->pvtkTextMapper); + + this->pvtkRenderer->SetBackground(0.0,0.0,0.4); + this->pvtkRenderer->AddActor(this->pvtkActor2D); + } +} + +void CvtkMDIView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + this->pvtkMFCWindow = new vtkMFCWindow(this); + + this->pvtkMFCWindow->GetRenderWindow()->AddRenderer(this->pvtkRenderer); + + // execute object pipeline + ExecutePipeline(); +} + +void CvtkMDIView::OnDestroy() +{ + // Delete the the renderer, window and interactor objects. + if (this->pvtkRenderer) this->pvtkRenderer->Delete(); + + // Delete the the objects used to form the visualisation. + if (this->pvtkDataSetMapper) this->pvtkDataSetMapper->Delete(); + if (this->pvtkActor) this->pvtkActor->Delete(); + if (this->pvtkActor2D) this->pvtkActor2D->Delete(); + if (this->pvtkTextMapper) this->pvtkTextMapper->Delete(); + + // destroy base + CView::OnDestroy(); +} + +int CvtkMDIView::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CView::OnCreate(lpCreateStruct) == -1) + return -1; + + return 0; +} + +BOOL CvtkMDIView::OnEraseBkgnd(CDC*) +{ + return TRUE; +} + +void CvtkMDIView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + if (this->pvtkMFCWindow) + this->pvtkMFCWindow->MoveWindow(0, 0, cx, cy); +} + +void CvtkMDIView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + AfxMessageBox("You made a double click"); + + CView::OnLButtonDblClk(nFlags, point); +} diff --git a/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIView.h b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIView.h new file mode 100644 index 0000000..988c6a9 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkMDI/vtkMDIView.h @@ -0,0 +1,56 @@ +// vtkMDIView.h : interface of the CvtkMDIView class +// + + +#pragma once + +#include "vtkMFCWindow.h" + +class CvtkMDIView : public CView +{ +protected: // create from serialization only + CvtkMDIView(); + DECLARE_DYNCREATE(CvtkMDIView) + +// Attributes +public: + virtual ~CvtkMDIView(); + CvtkMDIDoc* GetDocument() const; + virtual void OnDraw(CDC* pDC); // overridden to draw this view + +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +private: + void ExecutePipeline(); + + vtkMFCWindow *pvtkMFCWindow; + + vtkRenderer *pvtkRenderer; + vtkDataSetMapper *pvtkDataSetMapper; + vtkActor *pvtkActor; + vtkActor2D *pvtkActor2D; + vtkTextMapper *pvtkTextMapper; + +public: + virtual void OnInitialUpdate(); + afx_msg void OnDestroy(); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnSize(UINT nType, int cx, int cy); + +protected: + BOOL OnEraseBkgnd(CDC* pDC); + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in vtkMDIView.cpp +inline CvtkMDIDoc* CvtkMDIView::GetDocument() const + { return reinterpret_cast(m_pDocument); } +#endif + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/CMakeLists.txt b/Examples/GUI/Win32/vtkMFC/vtkSDI/CMakeLists.txt new file mode 100644 index 0000000..7069287 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/CMakeLists.txt @@ -0,0 +1,30 @@ +SET( vtkSDI_SRCS + MainFrm + StdAfx + vtkSDI + vtkSDI.rc + vtkSDIDoc + vtkSDIView + res/vtkSDI.ico + res/vtkSDI.rc2 + res/vtkSDIDoc.ico + res/Toolbar.bmp +) + +LINK_LIBRARIES( + vtkMFC + vtkRendering + vtkGraphics + vtkImaging + vtkIO + vtkFiltering + vtkCommon + vtkHybrid +) + + +# add stuff to use MFC in this executable +ADD_DEFINITIONS(-D_AFXDLL) +SET(CMAKE_MFC_FLAG 6) + +ADD_EXECUTABLE(vtkSDI WIN32 ${vtkSDI_SRCS}) diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/MainFrm.cpp b/Examples/GUI/Win32/vtkMFC/vtkSDI/MainFrm.cpp new file mode 100644 index 0000000..37a594e --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/MainFrm.cpp @@ -0,0 +1,99 @@ +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "vtkSDI.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CMainFrame + +IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + ON_WM_CREATE() +END_MESSAGE_MAP() + +static UINT indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + + +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here +} + +CMainFrame::~CMainFrame() +{ +} + + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + // TODO: Delete these three lines if you don't want the toolbar to be dockable + m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + DockControlBar(&m_wndToolBar); + + return 0; +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CFrameWnd::PreCreateWindow(cs) ) + return FALSE; + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return TRUE; +} + + +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + + +// CMainFrame message handlers + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/MainFrm.h b/Examples/GUI/Win32/vtkMFC/vtkSDI/MainFrm.h new file mode 100644 index 0000000..703a0b2 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/MainFrm.h @@ -0,0 +1,41 @@ +// MainFrm.h : interface of the CMainFrame class +// + + +#pragma once +class CMainFrame : public CFrameWnd +{ + +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + +// Operations +public: + +// Overrides +public: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + +// Generated message map functions +protected: + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + DECLARE_MESSAGE_MAP() +}; + + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/StdAfx.cpp b/Examples/GUI/Win32/vtkMFC/vtkSDI/StdAfx.cpp new file mode 100644 index 0000000..9488d3c --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/StdAfx.cpp @@ -0,0 +1,7 @@ +// stdafx.cpp : source file that includes just the standard includes +// vtkSDI.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/StdAfx.h b/Examples/GUI/Win32/vtkMFC/vtkSDI/StdAfx.h new file mode 100644 index 0000000..0397c9a --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/StdAfx.h @@ -0,0 +1,53 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#pragma once + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. +#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. +#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. +#define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later. +#endif + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off MFC's hiding of some common and often safely ignored warning messages +#define _AFX_ALL_WARNINGS + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +// Include the required header files for the vtk classes we are using +#include +#include +#include +#include +#include +#include +#include +#include +#include + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/res/Toolbar.bmp b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/Toolbar.bmp new file mode 100644 index 0000000..d501723 Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/Toolbar.bmp differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDI.ico b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDI.ico new file mode 100644 index 0000000..8a84ca3 Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDI.ico differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDI.rc2 b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDI.rc2 new file mode 100644 index 0000000..6153e17 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDI.rc2 @@ -0,0 +1,13 @@ +// +// vtkSDI.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDIDoc.ico b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDIDoc.ico new file mode 100644 index 0000000..2a1f1ae Binary files /dev/null and b/Examples/GUI/Win32/vtkMFC/vtkSDI/res/vtkSDIDoc.ico differ diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/resource.h b/Examples/GUI/Win32/vtkMFC/vtkSDI/resource.h new file mode 100644 index 0000000..e9e485d --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/resource.h @@ -0,0 +1,20 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by vtkSDI.rc +// +#define IDD_ABOUTBOX 100 +#define IDP_OLE_INIT_FAILED 100 +#define IDR_MAINFRAME 128 +#define IDR_vtkSDITYPE 129 +#define IDR_MANIFEST CREATEPROCESS_MANIFEST_RESOURCE_ID + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 32771 +#endif +#endif diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.cpp b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.cpp new file mode 100644 index 0000000..85ee385 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.cpp @@ -0,0 +1,135 @@ +// vtkSDI.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "vtkSDI.h" +#include "MainFrm.h" + +#include "vtkSDIDoc.h" +#include "vtkSDIView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CvtkSDIApp + +BEGIN_MESSAGE_MAP(CvtkSDIApp, CWinApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) + // Standard print setup command + ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) +END_MESSAGE_MAP() + + +// CvtkSDIApp construction + +CvtkSDIApp::CvtkSDIApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + + +// The one and only CvtkSDIApp object + +CvtkSDIApp theApp; + +// CvtkSDIApp initialization + +BOOL CvtkSDIApp::InitInstance() +{ + // InitCommonControls() is required on Windows XP if an application + // manifest specifies use of ComCtl32.dll version 6 or later to enable + // visual styles. Otherwise, any window creation will fail. + InitCommonControls(); + + CWinApp::InitInstance(); + + // Initialize OLE libraries + if (!AfxOleInit()) + { + AfxMessageBox(IDP_OLE_INIT_FAILED); + return FALSE; + } + AfxEnableControlContainer(); + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need + // Change the registry key under which our settings are stored + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + LoadStdProfileSettings(4); // Load standard INI file options (including MRU) + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(CvtkSDIDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CvtkSDIView)); + if (!pDocTemplate) + return FALSE; + AddDocTemplate(pDocTemplate); + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + // Dispatch commands specified on the command line. Will return FALSE if + // app was launched with /RegServer, /Register, /Unregserver or /Unregister. + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + // The one and only window has been initialized, so show and update it + m_pMainWnd->ShowWindow(SW_SHOW); + m_pMainWnd->UpdateWindow(); + // call DragAcceptFiles only if there's a suffix + // In an SDI app, this should occur after ProcessShellCommand + return TRUE; +} + + + +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + enum { IDD = IDD_ABOUTBOX }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + +// Implementation +protected: + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) +END_MESSAGE_MAP() + +// App command to run the dialog +void CvtkSDIApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + + +// CvtkSDIApp message handlers + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.h b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.h new file mode 100644 index 0000000..c594b8a --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.h @@ -0,0 +1,31 @@ +// vtkSDI.h : main header file for the vtkSDI application +// +#pragma once + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + + +// CvtkSDIApp: +// See vtkSDI.cpp for the implementation of this class +// + +class CvtkSDIApp : public CWinApp +{ +public: + CvtkSDIApp(); + + +// Overrides +public: + virtual BOOL InitInstance(); + +// Implementation + afx_msg void OnAppAbout(); + DECLARE_MESSAGE_MAP() +}; + +extern CvtkSDIApp theApp; diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.rc b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.rc new file mode 100644 index 0000000..bf7c92f --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDI.rc @@ -0,0 +1,396 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#include ""res\\vtkSDI.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#include ""afxprint.rc"" // printing/print preview resources\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\vtkSDI.ico" +IDR_vtkSDITYPE ICON "res\\vtkSDIDoc.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP "res\\Toolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_MAINFRAME TOOLBAR 16, 15 +BEGIN + BUTTON ID_FILE_NEW + BUTTON ID_FILE_OPEN + BUTTON ID_FILE_SAVE + SEPARATOR + BUTTON ID_EDIT_CUT + BUTTON ID_EDIT_COPY + BUTTON ID_EDIT_PASTE + SEPARATOR + BUTTON ID_FILE_PRINT + BUTTON ID_APP_ABOUT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New\tCtrl+N", ID_FILE_NEW + MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN + MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE + MENUITEM "Save &As...", ID_FILE_SAVE_AS + MENUITEM SEPARATOR + MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT + MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW + MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP + MENUITEM SEPARATOR + MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT + MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE + END + POPUP "&View" + BEGIN + MENUITEM "&Toolbar", ID_VIEW_TOOLBAR + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About vtkSDI...", ID_APP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS +BEGIN + "N", ID_FILE_NEW, VIRTKEY, CONTROL + "O", ID_FILE_OPEN, VIRTKEY, CONTROL + "S", ID_FILE_SAVE, VIRTKEY, CONTROL + "P", ID_FILE_PRINT, VIRTKEY, CONTROL + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL + "X", ID_EDIT_CUT, VIRTKEY, CONTROL + "C", ID_EDIT_COPY, VIRTKEY, CONTROL + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL + VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT + VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT + VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL + VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT + VK_F6, ID_NEXT_PANE, VIRTKEY + VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "About vtkSDI" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "vtkSDI Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2004",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,16,WS_GROUP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "TODO: " + VALUE "FileDescription", "TODO: " + VALUE "FileVersion", "1.0.0.1" + VALUE "InternalName", "vtkSDI.exe" + VALUE "LegalCopyright", "TODO: (c) . All rights reserved." + VALUE "OriginalFilename", "vtkSDI.exe" + VALUE "ProductName", "TODO: " + VALUE "ProductVersion", "1.0.0.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDR_MAINFRAME "vtkSDI\n\nvtkSDI\nVTK Files (*.vtk)\n.vtk\nvtkSDI.Document\nvtkSDI.Document" +END + +STRINGTABLE +BEGIN + AFX_IDS_APP_TITLE "vtkSDI" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE +BEGIN + ID_FILE_NEW "Create a new document\nNew" + ID_FILE_OPEN "Open an existing document\nOpen" + ID_FILE_CLOSE "Close the active document\nClose" + ID_FILE_SAVE "Save the active document\nSave" + ID_FILE_SAVE_AS "Save the active document with a new name\nSave As" + ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup" + ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup" + ID_FILE_PRINT "Print the active document\nPrint" + ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview" +END + +STRINGTABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright\nAbout" + ID_APP_EXIT "Quit the application; prompts to save documents\nExit" +END + +STRINGTABLE +BEGIN + ID_FILE_MRU_FILE1 "Open this document" + ID_FILE_MRU_FILE2 "Open this document" + ID_FILE_MRU_FILE3 "Open this document" + ID_FILE_MRU_FILE4 "Open this document" + ID_FILE_MRU_FILE5 "Open this document" + ID_FILE_MRU_FILE6 "Open this document" + ID_FILE_MRU_FILE7 "Open this document" + ID_FILE_MRU_FILE8 "Open this document" + ID_FILE_MRU_FILE9 "Open this document" + ID_FILE_MRU_FILE10 "Open this document" + ID_FILE_MRU_FILE11 "Open this document" + ID_FILE_MRU_FILE12 "Open this document" + ID_FILE_MRU_FILE13 "Open this document" + ID_FILE_MRU_FILE14 "Open this document" + ID_FILE_MRU_FILE15 "Open this document" + ID_FILE_MRU_FILE16 "Open this document" +END + +STRINGTABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane\nNext Pane" + ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" +END + +STRINGTABLE +BEGIN + ID_WINDOW_SPLIT "Split the active window into panes\nSplit" +END + +STRINGTABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection\nErase" + ID_EDIT_CLEAR_ALL "Erase everything\nErase All" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" + ID_EDIT_FIND "Find the specified text\nFind" + ID_EDIT_PASTE "Insert Clipboard contents\nPaste" + ID_EDIT_REPEAT "Repeat the last action\nRepeat" + ID_EDIT_REPLACE "Replace specific text with different text\nReplace" + ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" + ID_EDIT_UNDO "Undo the last action\nUndo" + ID_EDIT_REDO "Redo the previously undone action\nRedo" +END + +STRINGTABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" + ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + +STRINGTABLE +BEGIN + AFX_IDS_PREVIEW_CLOSE "Close print preview mode\nCancel Preview" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#include "res\vtkSDI.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#include "afxprint.rc" // printing/print preview resources +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIDoc.cpp b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIDoc.cpp new file mode 100644 index 0000000..17b613f --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIDoc.cpp @@ -0,0 +1,184 @@ +// vtkSDIDoc.cpp : implementation of the CvtkSDIDoc class +// + +#include "stdafx.h" +#include "vtkSDI.h" + +#include "vtkSDIDoc.h" +#include "vtkSDIView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CvtkSDIDoc + +IMPLEMENT_DYNCREATE(CvtkSDIDoc, CDocument) + +BEGIN_MESSAGE_MAP(CvtkSDIDoc, CDocument) +END_MESSAGE_MAP() + + +// CvtkSDIDoc construction/destruction + +CvtkSDIDoc::CvtkSDIDoc() +{ + this->pvtkDataSetReader = NULL; + + // Create the the objects used to form the visualisation. + this->pvtkDataSetMapper = vtkDataSetMapper::New(); + this->pvtkActor = vtkActor::New(); + this->pvtkActor2D = vtkActor2D::New(); + this->pvtkTextMapper = vtkTextMapper::New(); +} + +CvtkSDIDoc::~CvtkSDIDoc() +{ +} + +BOOL CvtkSDIDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // remove old actors + RemoveActors(); + + // execute object pipeline + ExecutePipeline(); + + return TRUE; +} + + + + +// CvtkSDIDoc serialization + +void CvtkSDIDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + + +// CvtkSDIDoc diagnostics + +#ifdef _DEBUG +void CvtkSDIDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CvtkSDIDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + + +// CvtkSDIDoc commands + +void CvtkSDIDoc::RemoveActors() +{ + // get our renderer first + POSITION pos = this->GetFirstViewPosition(); + CvtkSDIView *pcvtkSDIView = NULL; + + if (pos) + { + pcvtkSDIView = (CvtkSDIView *)GetNextView(pos); + } + else // return + { + ASSERT(FALSE); + return; + } + + // remove old actors + pcvtkSDIView->GetRenderer()->RemoveActor(this->pvtkActor); + pcvtkSDIView->GetRenderer()->RemoveActor(this->pvtkActor2D); +} + +BOOL CvtkSDIDoc::OnOpenDocument(LPCTSTR lpszPathName) +{ + if (!CDocument::OnOpenDocument(lpszPathName)) + return FALSE; + + // remove old actors + RemoveActors(); + + // create new data reader + this->pvtkDataSetReader = vtkDataSetReader::New(); + this->pvtkDataSetReader->SetFileName(lpszPathName); + + // execute object pipeline + ExecutePipeline(); + + return TRUE; +} + +void CvtkSDIDoc::OnCloseDocument() +{ + // delete data + if (this->pvtkDataSetReader) this->pvtkDataSetReader->Delete(); + + // Delete the the objects used to form the visualisation. + if (this->pvtkDataSetMapper) this->pvtkDataSetMapper->Delete(); + if (this->pvtkActor) this->pvtkActor->Delete(); + if (this->pvtkActor2D) this->pvtkActor2D->Delete(); + if (this->pvtkTextMapper) this->pvtkTextMapper->Delete(); + + CDocument::OnCloseDocument(); +} + +void CvtkSDIDoc::ExecutePipeline() +{ + // get our renderer first + POSITION pos = this->GetFirstViewPosition(); + CvtkSDIView *pcvtkSDIView = NULL; + + if (pos) + { + pcvtkSDIView = (CvtkSDIView *)GetNextView(pos); + } + else // return + { + ASSERT(FALSE); + return; + } + + if (pvtkDataSetReader) // have file + { + this->pvtkDataSetMapper->SetInput(this->pvtkDataSetReader->GetOutput()); + this->pvtkActor->SetMapper(this->pvtkDataSetMapper); + + this->pvtkTextMapper->SetInput(this->pvtkDataSetReader->GetFileName()); + this->pvtkTextMapper->GetTextProperty()->SetFontSize(12); + this->pvtkActor2D->SetMapper(this->pvtkTextMapper); + + pcvtkSDIView->GetRenderer()->SetBackground(0.0,0.0,0.4); + pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor); + pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor2D); + pcvtkSDIView->GetRenderer()->ResetCamera(); + pvtkDataSetReader->Delete(); + pvtkDataSetReader = NULL; + } + else // have no file + { + this->pvtkTextMapper->SetInput("Hello World"); + this->pvtkTextMapper->GetTextProperty()->SetFontSize(24); + this->pvtkActor2D->SetMapper(this->pvtkTextMapper); + + pcvtkSDIView->GetRenderer()->SetBackground(0.0,0.0,0.4); + pcvtkSDIView->GetRenderer()->AddActor(this->pvtkActor2D); + pcvtkSDIView->GetRenderer()->ResetCamera(); + } +} diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIDoc.h b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIDoc.h new file mode 100644 index 0000000..a082371 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIDoc.h @@ -0,0 +1,51 @@ +// vtkSDIDoc.h : interface of the CvtkSDIDoc class +// + + +#pragma once + +class CvtkSDIDoc : public CDocument +{ +protected: // create from serialization only + CvtkSDIDoc(); + DECLARE_DYNCREATE(CvtkSDIDoc) + +// Attributes +private: + vtkDataSetReader *pvtkDataSetReader; + +// Operations +public: + +// Overrides + public: + virtual BOOL OnNewDocument(); + virtual void Serialize(CArchive& ar); + +// Implementation +public: + virtual ~CvtkSDIDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +private: + void ExecutePipeline(); + void RemoveActors(); + + vtkDataSetMapper *pvtkDataSetMapper; + vtkActor *pvtkActor; + + vtkActor2D *pvtkActor2D; + vtkTextMapper *pvtkTextMapper; + +// Generated message map functions +protected: + DECLARE_MESSAGE_MAP() +public: + virtual void OnCloseDocument(); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); +}; + + diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIView.cpp b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIView.cpp new file mode 100644 index 0000000..1c8bd69 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIView.cpp @@ -0,0 +1,147 @@ +// vtkSDIView.cpp : implementation of the CvtkSDIView class +// + +#include "stdafx.h" +#include "vtkSDI.h" + +#include "vtkSDIDoc.h" +#include "vtkSDIView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CvtkSDIView + +IMPLEMENT_DYNCREATE(CvtkSDIView, CView) + +BEGIN_MESSAGE_MAP(CvtkSDIView, CView) + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_WM_CREATE() + ON_WM_DESTROY() + ON_WM_ERASEBKGND() + ON_WM_SIZE() + ON_WM_LBUTTONDBLCLK() +END_MESSAGE_MAP() + +// CvtkSDIView construction/destruction + +CvtkSDIView::CvtkSDIView() +{ + this->pvtkMFCWindow = NULL; + + // Create the the renderer, window and interactor objects. + this->pvtkRenderer = vtkRenderer::New(); +} + +CvtkSDIView::~CvtkSDIView() +{ + // delete generic vtk window + if (this->pvtkMFCWindow) delete this->pvtkMFCWindow; +} + +void CvtkSDIView::OnDraw(CDC* pDC) +{ + CvtkSDIDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + if (this->pvtkMFCWindow) + { + if (pDC->IsPrinting()) + this->pvtkMFCWindow->DrawDC(pDC); + } +} + + +// CvtkSDIView printing + +BOOL CvtkSDIView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CvtkSDIView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CvtkSDIView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + + +// CvtkSDIView diagnostics + +#ifdef _DEBUG +void CvtkSDIView::AssertValid() const +{ + CView::AssertValid(); +} + +void CvtkSDIView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CvtkSDIDoc* CvtkSDIView::GetDocument() const // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CvtkSDIDoc))); + return (CvtkSDIDoc*)m_pDocument; +} +#endif //_DEBUG + + +// CvtkSDIView message handlers + +int CvtkSDIView::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CView::OnCreate(lpCreateStruct) == -1) + return -1; + + return 0; +} + +void CvtkSDIView::OnDestroy() +{ + // Delete the the renderer, window and interactor objects. + if (this->pvtkRenderer) this->pvtkRenderer->Delete(); + + // destroy base + CView::OnDestroy(); +} + +BOOL CvtkSDIView::OnEraseBkgnd(CDC* pDC) +{ + return TRUE; +} + +void CvtkSDIView::OnSize(UINT nType, int cx, int cy) +{ + CView::OnSize(nType, cx, cy); + + if (this->pvtkMFCWindow) + this->pvtkMFCWindow->MoveWindow(0, 0, cx, cy); +} + +void CvtkSDIView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + AfxMessageBox("You made a double click"); + + CView::OnLButtonDblClk(nFlags, point); +} + +void CvtkSDIView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); + + if (this->pvtkMFCWindow) delete this->pvtkMFCWindow; + this->pvtkMFCWindow = new vtkMFCWindow(this); + + this->pvtkMFCWindow->GetRenderWindow()->AddRenderer(this->pvtkRenderer); +} diff --git a/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIView.h b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIView.h new file mode 100644 index 0000000..16994f9 --- /dev/null +++ b/Examples/GUI/Win32/vtkMFC/vtkSDI/vtkSDIView.h @@ -0,0 +1,50 @@ +// vtkSDIView.h : interface of the CvtkSDIView class +// + + +#pragma once + +#include "vtkMFCWindow.h" + +class CvtkSDIView : public CView +{ +public: + virtual ~CvtkSDIView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + CvtkSDIDoc* GetDocument() const; + vtkRenderer* GetRenderer() { ASSERT(pvtkRenderer); return pvtkRenderer; } + + virtual void OnDraw(CDC* pDC); // overridden to draw this view + + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnDestroy(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + +private: + vtkRenderer *pvtkRenderer; + vtkMFCWindow *pvtkMFCWindow; + +protected: + DECLARE_DYNCREATE(CvtkSDIView) + CvtkSDIView(); + + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + + DECLARE_MESSAGE_MAP() +public: + virtual void OnInitialUpdate(); +}; + +#ifndef _DEBUG // debug version in vtkSDIView.cpp +inline CvtkSDIDoc* CvtkSDIView::GetDocument() const + { return reinterpret_cast(m_pDocument); } +#endif + diff --git a/Examples/IO/Python/flamingo.py b/Examples/IO/Python/flamingo.py new file mode 100644 index 0000000..e86343c --- /dev/null +++ b/Examples/IO/Python/flamingo.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtk3DSImporter. +# vtk3DSImporter is used to load 3D Studio files. Unlike writers, +# importers can load scenes (data as well as lights, cameras, actors +# etc.). Importers will either generate an instance of vtkRenderWindow +# and/or vtkRenderer or will use the ones you specify. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + + +# Create the importer and read a file +importer = vtk.vtk3DSImporter() +importer.ComputeNormalsOn() +importer.SetFileName(VTK_DATA_ROOT + "/Data/iflamigm.3ds") +importer.Read() + +# Here we let the importer create a renderer and a render window for +# us. We could have also create and assigned those ourselves like so: +# renWin = vtk.vtkRenderWindow() +# importer.SetRenderWindow(renWin) + +# Assign an interactor. +# We have to ask the importer for it's render window. +renWin = importer.GetRenderWindow() +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Set the render window's size +renWin.SetSize(300, 300) + +# Set some properties on the renderer. +# We have to ask the importer for it's renderer. +ren = importer.GetRenderer() +ren.SetBackground(0.1, 0.2, 0.4) + +# Position the camera: +# change view up to +z +camera = ren.GetActiveCamera() +camera.SetPosition(0, 1, 0) +camera.SetFocalPoint(0, 0, 0) +camera.SetViewUp(0, 0, 1) +# let the renderer compute good position and focal point +ren.ResetCamera() +camera.Dolly(1.4) +ren.ResetCameraClippingRange() + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/IO/Python/stl.py b/Examples/IO/Python/stl.py new file mode 100644 index 0000000..a9cb50d --- /dev/null +++ b/Examples/IO/Python/stl.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkSTLReader to load data into +# VTK from a file. This example also uses vtkLODActor which changes +# its graphical representation of the data to maintain interactive +# performance. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create the reader and read a data file. Connect the mapper and +# actor. +sr = vtk.vtkSTLReader() +sr.SetFileName(VTK_DATA_ROOT + "/Data/42400-IDGH.stl") + +stlMapper = vtk.vtkPolyDataMapper() +stlMapper.SetInputConnection(sr.GetOutputPort()) + +stlActor = vtk.vtkLODActor() +stlActor.SetMapper(stlMapper) + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the render; set the background and size +ren.AddActor(stlActor) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(500, 500) + +# Zoom in closer +ren.ResetCamera() +cam1 = ren.GetActiveCamera() +cam1.Zoom(1.4) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/IO/Tcl/flamingo.tcl b/Examples/IO/Tcl/flamingo.tcl new file mode 100644 index 0000000..1b7c2fd --- /dev/null +++ b/Examples/IO/Tcl/flamingo.tcl @@ -0,0 +1,55 @@ +# This example demonstrates the use of vtk3DSImporter. +# vtk3DSImporter is used to load 3D Studio files. Unlike writers, +# importers can load scenes (data as well as lights, cameras, actors +# etc.). Importers will either generate an instance of vtkRenderWindow +# and/or vtkRenderer or will use the ones you specify. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create the importer and read a file +vtk3DSImporter importer + importer ComputeNormalsOn + importer SetFileName "$VTK_DATA_ROOT/Data/iflamigm.3ds" + importer Read +# Here we let the importer create a renderer and a render window +# for us. We could have also create and assigned those ourselves: +# vtkRenderWindow renWin +# importer SetRenderWindow renWin + +# Assign an interactor. +# We have to ask the importer for it's render window. +set renWin [importer GetRenderWindow] +vtkRenderWindowInteractor iren + iren SetRenderWindow $renWin + +# Set the render window's size +$renWin SetSize 300 300 + +# Set some properties on the renderer. +# We have to ask the importer for it's renderer. +set ren [importer GetRenderer] +$ren SetBackground 0.1 0.2 0.4 + +# Position the camera: +# change view up to +z +set camera [$ren GetActiveCamera] +$camera SetPosition 0 1 0 +$camera SetFocalPoint 0 0 0 +$camera SetViewUp 0 0 1 +# let the renderer compute good position and focal point +$ren ResetCamera +$camera Dolly 1.4 +$ren ResetCameraClippingRange + +# Set the user method (bound to key 'u') +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# Withdraw the default tk window +wm withdraw . + diff --git a/Examples/IO/Tcl/stl.tcl b/Examples/IO/Tcl/stl.tcl new file mode 100644 index 0000000..6fdb3bf --- /dev/null +++ b/Examples/IO/Tcl/stl.tcl @@ -0,0 +1,46 @@ +# This example demonstrates the use of vtkSTLReader to load data into VTK from +# a file. This example also uses vtkLODActor which changes its graphical +# representation of the data to maintain interactive performance. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create the reader and read a data file. Connect the mapper and actor. +vtkSTLReader sr + sr SetFileName $VTK_DATA_ROOT/Data/42400-IDGH.stl + +vtkPolyDataMapper stlMapper + stlMapper SetInputConnection [sr GetOutputPort] + +vtkLODActor stlActor + stlActor SetMapper stlMapper + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the render; set the background and size +# +ren1 AddActor stlActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 500 500 + +# Zoom in closer +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 + +# Set the user method (bound to key 'u') +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# Withdraw the default tk window +wm withdraw . diff --git a/Examples/ImageProcessing/Python/Contours2D.py b/Examples/ImageProcessing/Python/Contours2D.py new file mode 100644 index 0000000..edd434c --- /dev/null +++ b/Examples/ImageProcessing/Python/Contours2D.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python + +# This example shows how to sample a mathematical function over a +# volume. A slice from the volume is then extracted and then contoured +# to produce 2D contour lines. +# +import vtk + +# Quadric definition. This is a type of implicit function. Here the +# coefficients to the equations are set. +quadric = vtk.vtkQuadric() +quadric.SetCoefficients(.5, 1, .2, 0, .1, 0, 0, .2, 0, 0) + +# The vtkSampleFunction uses the quadric function and evaluates function +# value over a regular lattice (i.e., a volume). +sample = vtk.vtkSampleFunction() +sample.SetSampleDimensions(30, 30, 30) +sample.SetImplicitFunction(quadric) +sample.ComputeNormalsOff() +sample.Update() + +# Here a single slice (i.e., image) is extracted from the volume. (Note: in +# actuality the VOI request causes the sample function to operate on just the +# slice.) +extract = vtk.vtkExtractVOI() +extract.SetInputConnection(sample.GetOutputPort()) +extract.SetVOI(0, 29, 0, 29, 15, 15) +extract.SetSampleRate(1, 2, 3) + +# The image is contoured to produce contour lines. Thirteen contour values +# ranging from (0,1.2) inclusive are produced. +contours = vtk.vtkContourFilter() +contours.SetInputConnection(extract.GetOutputPort()) +contours.GenerateValues(13, 0.0, 1.2) + +# The contour lines are mapped to the graphics library. +contMapper = vtk.vtkPolyDataMapper() +contMapper.SetInputConnection(contours.GetOutputPort()) +contMapper.SetScalarRange(0.0, 1.2) + +contActor = vtk.vtkActor() +contActor.SetMapper(contMapper) + +# Create outline an outline of the sampled data. +outline = vtk.vtkOutlineFilter() +outline.SetInputConnection(sample.GetOutputPort()) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) + +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Create the renderer, render window, and interactor. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Set the background color to white. Associate the actors with the +# renderer. +ren.SetBackground(1, 1, 1) +ren.AddActor(contActor) +ren.AddActor(outlineActor) + +# Zoom in a little bit. +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.5) + +# Initialize and start the event loop. +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/ImageProcessing/Python/ImageInteractor.py b/Examples/ImageProcessing/Python/ImageInteractor.py new file mode 100644 index 0000000..f98f7ec --- /dev/null +++ b/Examples/ImageProcessing/Python/ImageInteractor.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python + +# This example shows how to use the InteractorStyleImage and add your +# own event handling. The InteractorStyleImage is a special +# interactor designed to be used with vtkImageActor in a rendering +# window context. It forces the camera to stay perpendicular to the +# x-y plane. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create the image +reader = vtk.vtkPNGReader() +reader.SetDataSpacing(0.8, 0.8, 1.5) +reader.SetFileName(VTK_DATA_ROOT + "/Data/fullhead15.png") + +shiftScale = vtk.vtkImageShiftScale() +shiftScale.SetInputConnection(reader.GetOutputPort()) +shiftScale.SetShift(0) +shiftScale.SetScale(0.07) +shiftScale.SetOutputScalarTypeToUnsignedChar() + +ia = vtk.vtkImageActor() +ia.SetInput(shiftScale.GetOutput()) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) +iren.Initialize() + +# Add the actors to the renderer, set the background and size +ren.AddActor(ia) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(400, 400) + +renWin.Render() + +cam1 = ren.GetActiveCamera() + +ren.ResetCameraClippingRange() +renWin.Render() + +### Supporting data for callbacks +pts = vtk.vtkPoints() +pts.SetNumberOfPoints(4) +lines = vtk.vtkCellArray() +lines.InsertNextCell(5) +lines.InsertCellPoint(0) +lines.InsertCellPoint(1) +lines.InsertCellPoint(2) +lines.InsertCellPoint(3) +lines.InsertCellPoint(0) +pd = vtk.vtkPolyData() +pd.SetPoints(pts) +pd.SetLines(lines) +bboxMapper = vtk.vtkPolyDataMapper2D() +bboxMapper.SetInput(pd) +bboxActor = vtk.vtkActor2D() +bboxActor.SetMapper(bboxMapper) +bboxActor.GetProperty().SetColor(1, 0, 0) +ren.AddViewProp(bboxActor) + +### Functions for callbacks +X = 0 +Y = 0 +bboxEnabled = 0 + +def StartZoom(obj, event): + global X, Y, bboxEnabled + xy = iren.GetEventPosition() + X, Y = xy + + pts.SetPoint(0, X, Y, 0) + pts.SetPoint(1, X, Y, 0) + pts.SetPoint(2, X, Y, 0) + pts.SetPoint(3, X, Y, 0) + + bboxEnabled = 1 + bboxActor.VisibilityOn() + + +def MouseMove(obj, event): + global X, Y, bboxEnabled + + if bboxEnabled: + xy = iren.GetEventPosition() + x, y = xy + pts.SetPoint(1, x, Y, 0) + pts.SetPoint(2, x, y, 0) + pts.SetPoint(3, X, y, 0) + renWin.Render() + + +# Do the hard stuff: pan and dolly +def EndZoom(obj, event): + global bboxEnabled + + p1 = pts.GetPoint(0) + + p2 = pts.GetPoint(2) + x1, y1, z1 = p1 + x2, y2, z2 = p2 + + ren.SetDisplayPoint(x1, y1, 0) + ren.DisplayToWorld() + p1 = ren.GetWorldPoint() + ren.SetDisplayPoint(x2, y2, 0) + ren.DisplayToWorld() + p2 = ren.GetWorldPoint() + + p1X, p1Y, p1Z = p1[:3] + + p2X, p2Y, p2Z = p2[:3] + + camera = ren.GetActiveCamera() + focalPt = camera.GetFocalPoint() + focalX, focalY, focalZ = focalPt + + position = camera.GetPosition() + positionX, positionY, positionZ = position + + deltaX = focalX-(p1X+p2X)/2.0 + deltaY = focalY-(p1Y+p2Y)/2.0 + + # Set camera focal point to the center of the box + camera.SetFocalPoint((p1X+p2X)/2.0, (p1Y+p2Y)/2.0, focalZ) + camera.SetPosition(positionX-deltaX, positionY-deltaY,positionZ) + + # Now dolly the camera to fill the box + # This is a half-assed hack for demonstration purposes + if p1X > p2X: + deltaX = p1X-p2X + else: + deltaX = p2X-p1X + if p1Y > p2Y: + deltaY = p1Y-p2Y + else: + deltaY = p2Y-p1Y + + winSize = renWin.GetSize() + winX, winY = winSize + + sx = deltaX/winX + sy = deltaY/winY + + + if sx > sy: + dolly = 1.0+1.0/(2.0*sx) + else: + dolly = 1.0+1.0/(2.0*sy) + + camera.Dolly(dolly) + ren.ResetCameraClippingRange() + + bboxEnabled = 0 + bboxActor.VisibilityOff() + renWin.Render() + +# Create an image interactor style and associate it with the +# interactive renderer. Then assign some callbacks with the +# appropriate events. THe callbacks are implemented as Python functions. +interactor = vtk.vtkInteractorStyleImage() +iren.SetInteractorStyle(interactor) +interactor.AddObserver("LeftButtonPressEvent", StartZoom) +interactor.AddObserver("MouseMoveEvent", MouseMove) +interactor.AddObserver("LeftButtonReleaseEvent", EndZoom) + +renWin.Render() +iren.Start() diff --git a/Examples/ImageProcessing/Tcl/Contours2D.tcl b/Examples/ImageProcessing/Tcl/Contours2D.tcl new file mode 100644 index 0000000..7e4785e --- /dev/null +++ b/Examples/ImageProcessing/Tcl/Contours2D.tcl @@ -0,0 +1,74 @@ +# This example shows how to sample a mathematical function over a +# volume. A slice from the volume is then extracted and then contoured +# to produce 2D contour lines. +# +package require vtk +package require vtkinteraction + +# Quadric definition. This is a type of implicit function. Here the +# coefficients to the equations are set. +vtkQuadric quadric + quadric SetCoefficients .5 1 .2 0 .1 0 0 .2 0 0 + +# The vtkSampleFunction uses the quadric function and evaluates function +# value over a regular lattice (i.e., a volume). +vtkSampleFunction sample + sample SetSampleDimensions 30 30 30 + sample SetImplicitFunction quadric + sample ComputeNormalsOff + +# Here a single slice (i.e., image) is extracted from the volume. (Note: in +# actuality the VOI request causes the sample function to operate on just the +# slice.) +vtkExtractVOI extract + extract SetInputConnection [sample GetOutputPort] + extract SetVOI 0 29 0 29 15 15 + extract SetSampleRate 1 2 3 + +# The image is contoured to produce contour lines. Thirteen contour values +# ranging from (0,1.2) inclusive are produced. +vtkContourFilter contours + contours SetInputConnection [extract GetOutputPort] + contours GenerateValues 13 0.0 1.2 + +# The contour lines are mapped to the graphics library. +vtkPolyDataMapper contMapper + contMapper SetInputConnection [contours GetOutputPort] + contMapper SetScalarRange 0.0 1.2 + +vtkActor contActor + contActor SetMapper contMapper + +# Create outline an outline of the sampled data. +vtkOutlineFilter outline + outline SetInputConnection [sample GetOutputPort] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# Create the renderer, render window, and interactor. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Set the background color to white. Associate the actors with the +# renderer. +ren1 SetBackground 1 1 1 +ren1 AddActor contActor +ren1 AddActor outlineActor + +# Zoom in a little bit. Associate the Tk interactor popup with a user +# keypress-u (the UserEvent). +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize; + +# Don't show the root Tk window "." +wm withdraw . diff --git a/Examples/ImageProcessing/Tcl/Histogram.tcl b/Examples/ImageProcessing/Tcl/Histogram.tcl new file mode 100644 index 0000000..ff73859 --- /dev/null +++ b/Examples/ImageProcessing/Tcl/Histogram.tcl @@ -0,0 +1,124 @@ +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl + +package require vtk +package require vtkinteraction + +# Create the image reader + +vtkImageReader reader + reader SetDataByteOrderToLittleEndian + reader SetDataExtent 0 63 0 63 1 93 + reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + reader SetDataMask 0x7fff + +reader Update +scan [[reader GetOutput] GetWholeExtent] "%d %d %d %d %d %d" \ + xMin xMax yMin yMax zMin zMax + +# Magnify the image + +set mag_factor 3 +vtkImageMagnify magnify + magnify SetInputConnection [reader GetOutputPort] + magnify SetMagnificationFactors $mag_factor $mag_factor 1 + +# Create the image viewer + +vtkImageViewer viewer2 + viewer2 SetInputConnection [magnify GetOutputPort] + viewer2 SetZSlice 14 + viewer2 SetColorWindow 2000 + viewer2 SetColorLevel 1000 + +# Create the GUI, i.e. two Tk image viewer, one for the image +# the other for the histogram, and a slice slider + +wm withdraw . +toplevel .top + +# Set the window manager (wm command) so that it registers a +# command to handle the WM_DELETE_WINDOW protocal request. This +# request is triggered when the widget is closed using the standard +# window manager icons or buttons. In this case the exit callback +# will be called and it will free up any objects we created then exit +# the application. + +wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit + +# Create the vtkTkImageViewerWidget + +frame .top.f1 + +set vtkiw [vtkTkImageViewerWidget .top.f1.r1 \ + -width [expr ($xMax - $xMin + 1) * $mag_factor] \ + -height [expr ($yMax - $yMin + 1) * $mag_factor] \ + -iv viewer2] + +# Setup some Tk bindings, a generic renwin interactor and VTK observers +# for that widget + +::vtk::bind_tk_imageviewer_widget $vtkiw + +# Create the histogram widget + +source HistogramWidget.tcl + +set hist [vtkHistogramWidget .top.f1.r2 512 192] + +set slice_number [viewer2 GetZSlice] + +HistogramWidgetSetInput $hist [reader GetOutput] +HistogramWidgetSetExtent $hist $xMin $xMax $yMin $yMax $slice_number $slice_number + +HistogramWidgetBind .top.f1.r2 + +# Add a 'Quit' button that will call the usual cb_exit callback and destroy +# all VTK objects + +button .top.btn \ + -text Quit \ + -command ::vtk::cb_exit + +# Add a slice scale to browse the whole stack + +scale .top.slice \ + -from $zMin \ + -to $zMax \ + -orient horizontal \ + -command SetSlice \ + -variable slice_number \ + -label "Z Slice" + +proc SetSlice {slice} { + global hist xMin xMax yMin yMax + + viewer2 SetZSlice $slice + viewer2 Render + + HistogramWidgetSetExtent $hist $xMin $xMax $yMin $yMax $slice $slice + HistogramWidgetRender $hist +} + +# Pack all gui elements + +pack $vtkiw \ + -side left -anchor n \ + -padx 3 -pady 3 \ + -fill x -expand f + +pack $hist \ + -side left \ + -padx 3 -pady 3 \ + -fill both -expand t + +pack .top.f1 \ + -fill both -expand t + +pack .top.slice .top.btn \ + -fill x -expand f + +# You only need this line if you run this script from a Tcl shell +# (tclsh) instead of a Tk shell (wish) + +tkwait window . diff --git a/Examples/ImageProcessing/Tcl/HistogramWidget.tcl b/Examples/ImageProcessing/Tcl/HistogramWidget.tcl new file mode 100644 index 0000000..8e8ecce --- /dev/null +++ b/Examples/ImageProcessing/Tcl/HistogramWidget.tcl @@ -0,0 +1,174 @@ +# Creates a meta object which clips a region of the input, and +# draws a histogram for the data. + +# Create a histogram object + +proc vtkHistogramWidget {widget {width 512} {height 192}} { + + set clip [::vtk::new_widget_object $widget vtkImageClip Clip] + + set accumulate \ + [::vtk::new_widget_object $widget vtkImageAccumulate Accumulate] + $accumulate SetInputConnection [$clip GetOutputPort] + + set canvas [::vtk::new_widget_object $widget vtkImageCanvasSource2D Canvas] + $canvas SetScalarTypeToUnsignedChar + $canvas SetNumberOfScalarComponents 3 + + set viewer [::vtk::new_widget_object $widget vtkImageViewer Viewer] + $viewer SetInputConnection [$canvas GetOutputPort] + $viewer SetColorWindow 256 + $viewer SetColorLevel 127 + + vtkTkImageViewerWidget $widget \ + -width $width \ + -height $height \ + -iv $viewer + + return $widget +} + +# Set the input + +proc HistogramWidgetSetInput {widget input} { + set clip [::vtk::get_widget_variable_value $widget Clip] + $clip SetInput $input +} + +# Set the extent + +proc HistogramWidgetSetExtent {widget x1 x2 y1 y2 z1 z2} { + set clip [::vtk::get_widget_variable_value $widget Clip] + $clip SetOutputWholeExtent $x1 $x2 $y1 $y2 $z1 $z2 +} + +# Render + +proc HistogramWidgetRender {widget} { + + # Get the size of the histogram window + + set width [lindex [$widget configure -width] 4] + set height [lindex [$widget configure -height] 4] + + # Setup the bins of the accumulate filter from the range of input data + + set accumulate [::vtk::get_widget_variable_value $widget Accumulate] + set numBins [expr $width / 2] + + set data [$accumulate GetInput] + $data Update + + set inputRange [[[$data GetPointData] GetScalars] GetRange] + set origin [lindex $inputRange 0] + set spacing [expr 1.0 * ([lindex $inputRange 1] - $origin) / $numBins] + + $accumulate SetComponentExtent 0 [expr $numBins - 1] 0 0 0 0 + $accumulate SetComponentOrigin $origin 0.0 0.0 + $accumulate SetComponentSpacing $spacing 1.0 1.0 + + # Initialize the canvas + + set canvas [::vtk::get_widget_variable_value $widget Canvas] + $canvas SetExtent 0 [expr $width - 1] 0 [expr $height - 1] 0 0 + $canvas SetDrawColor 255 + $canvas SetDrawColor 172 174 241 + $canvas FillBox 0 [expr $width - 1] 0 [expr $height - 1] + $canvas SetDrawColor 0 + $canvas SetDrawColor 137 28 28 + + # Get the histogram data + + set data [$accumulate GetOutput] + $data Update + + # Scale the histogram max to fit the window + + set histRange [[[$data GetPointData] GetScalars] GetRange] + set scale [expr 0.9 * $height / [lindex $histRange 1]] + + for {set idx 0} {$idx < $numBins} {incr idx} { + set y [$data GetScalarComponentAsDouble $idx 0 0 0] + set y1 [expr $y * $scale] + set y2 [lindex [split $y1 .] 0] + set x [expr $idx * 2] + $canvas DrawSegment $x 0 $x $y2 + } + + $widget Render +} + +# Set the bindings + +proc HistogramWidgetBind {widget} { + + # The usual vtkTkImageRenderWidget bindings + + ::vtk::bind_tk_imageviewer_widget $widget + + set iren [[[$widget GetImageViewer] GetRenderWindow] GetInteractor] + + # Remove the usual ConfigureEvent and ExposeEvent observers and + # use ours + + $iren RemoveObservers ConfigureEvent + $iren RemoveObservers ExposeEventTag + $iren AddObserver ExposeEvent \ + [list HistogramWidgetRender $widget] + + # Remove the usual PickEvent and use ours for probing + + set istyle [$iren GetInteractorStyle] + + $istyle RemoveObservers PickEvent + $istyle AddObserver PickEvent \ + [list HistogramWidgetUpdateInteraction $widget] + + # Bind the left button so that it acts like the right button + + $istyle RemoveObservers LeftButtonPressEvent + $istyle AddObserver LeftButtonPressEvent \ + "::vtk::cb_istyleimg_right_button_press_event $istyle" + + $istyle RemoveObservers LeftButtonReleaseEvent + $istyle AddObserver LeftButtonReleaseEvent \ + "::vtk::cb_istyleimg_right_button_release_event $istyle" +} + +# Probe the histogram + +proc HistogramWidgetUpdateInteraction {widget} { + + set pos [[[[$widget GetImageViewer] GetRenderWindow] GetInteractor] GetEventPosition] + set x [lindex $pos 0] + set y [lindex $pos 1] + + # Compute the bin selected by the mouse + + set x [expr $x / 2] + set accumulate [::vtk::get_widget_variable_value $widget Accumulate] + set origin [lindex [$accumulate GetComponentOrigin] 0] + set spacing [lindex [$accumulate GetComponentSpacing] 0] + set binMin [expr $origin + $spacing * $x] + set binMax [expr $binMin + $spacing] + + # Now get the height of the histogram + + set data [$accumulate GetOutput] + $data Update + + # Make sure value is in extent + + set max [lindex [$data GetExtent] 1] + if {$x < 0 || $x > $max} { + return + } + set y [$data GetScalarComponentAsDouble $x 0 0 0] + + # Display the value + + set mapper [::vtk::get_widget_variable_value $widget text1_mapper] + $mapper SetInput [format "\[%.1f, %.1f): %d" $binMin $binMax $y] + + $widget Render +} diff --git a/Examples/ImageProcessing/Tcl/ImageInteractor.tcl b/Examples/ImageProcessing/Tcl/ImageInteractor.tcl new file mode 100644 index 0000000..7a73458 --- /dev/null +++ b/Examples/ImageProcessing/Tcl/ImageInteractor.tcl @@ -0,0 +1,191 @@ +# This example shows how to use the InteractorStyleImage and add your own +# event handling. The InteractorStyleImage is a special interactor designed +# to be used with vtkImageActor in a rendering window context. It forces the +# camera to stay perpendicular to the x-y plane. + +package require vtk +package require vtkinteraction + +# Create the image +# +vtkPNGReader reader + reader SetDataSpacing 0.8 0.8 1.5 + reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageShiftScale shiftScale + shiftScale SetInputConnection [reader GetOutputPort] + shiftScale SetShift 0 + shiftScale SetScale 0.07 + shiftScale SetOutputScalarTypeToUnsignedChar + +vtkImageActor ia + ia SetInput [shiftScale GetOutput] + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create an image interactor style and associate it with the +# interactive renderer. Then assign some callbacks with the +# appropriate events. THe callbacks are implemented as Tcl procs. +vtkInteractorStyleImage interactor + iren SetInteractorStyle interactor + interactor AddObserver LeftButtonPressEvent {StartZoom} + interactor AddObserver MouseMoveEvent {MouseMove} + interactor AddObserver LeftButtonReleaseEvent {EndZoom} + +# Add the actors to the renderer, set the background and size +ren1 AddActor ia +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 400 400 + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +set cam1 [ren1 GetActiveCamera] + +ren1 ResetCameraClippingRange +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +### Supporting data for callbacks +vtkPoints pts + pts SetNumberOfPoints 4 +vtkCellArray lines + lines InsertNextCell 5 + lines InsertCellPoint 0 + lines InsertCellPoint 1 + lines InsertCellPoint 2 + lines InsertCellPoint 3 + lines InsertCellPoint 0 +vtkPolyData pd + pd SetPoints pts + pd SetLines lines +vtkPolyDataMapper2D bboxMapper + bboxMapper SetInput pd +vtkActor2D bboxActor + bboxActor SetMapper bboxMapper + [bboxActor GetProperty] SetColor 1 0 0 +ren1 AddViewProp bboxActor + +### Procedures for callbacks--------------------- +set X 0 +set Y 0 +set bboxEnabled 0 + +proc StartZoom {} { + global X Y bboxEnabled + + set xy [iren GetEventPosition] + set X [lindex $xy 0] + set Y [lindex $xy 1] + + pts SetPoint 0 $X $Y 0 + pts SetPoint 1 $X $Y 0 + pts SetPoint 2 $X $Y 0 + pts SetPoint 3 $X $Y 0 + + set bboxEnabled 1 + bboxActor VisibilityOn +} + +proc MouseMove {} { + global X Y bboxEnabled + + if { $bboxEnabled } { + set xy [iren GetEventPosition] + set x [lindex $xy 0] + set y [lindex $xy 1] + + pts SetPoint 1 $x $Y 0 + pts SetPoint 2 $x $y 0 + pts SetPoint 3 $X $y 0 + + renWin Render + } +} + +#Do the hard stuff: pan and dolly +proc EndZoom {} { + global bboxEnabled + + set p1 [pts GetPoint 0] + set p2 [pts GetPoint 2] + set x1 [lindex $p1 0] + set y1 [lindex $p1 1] + set x2 [lindex $p2 0] + set y2 [lindex $p2 1] + + ren1 SetDisplayPoint $x1 $y1 0 + ren1 DisplayToWorld + set p1 [ren1 GetWorldPoint] + ren1 SetDisplayPoint $x2 $y2 0 + ren1 DisplayToWorld + set p2 [ren1 GetWorldPoint] + + set p1X [lindex $p1 0] + set p1Y [lindex $p1 1] + set p1Z [lindex $p1 2] + + set p2X [lindex $p2 0] + set p2Y [lindex $p2 1] + set p2Z [lindex $p2 2] + + set camera [ren1 GetActiveCamera] + set focalPt [$camera GetFocalPoint] + set focalX [lindex $focalPt 0] + set focalY [lindex $focalPt 1] + set focalZ [lindex $focalPt 2] + set position [$camera GetPosition] + set positionX [lindex $position 0] + set positionY [lindex $position 1] + set positionZ [lindex $position 2] + + set deltaX [expr $focalX - ($p1X + $p2X)/2.0] + set deltaY [expr $focalY - ($p1Y + $p2Y)/2.0] + + #Set camera focal point to the center of the box + $camera SetFocalPoint [expr ($p1X + $p2X)/2.0] \ + [expr ($p1Y + $p2Y)/2.0] $focalZ + $camera SetPosition [expr $positionX - $deltaX] \ + [expr $positionY - $deltaY] $positionZ + + #Now dolly the camera to fill the box + #This is a half-assed hack for demonstration purposes + if { $p1X > $p2X } { + set deltaX [expr $p1X - $p2X] + } else { + set deltaX [expr $p2X - $p1X] + } + if { $p1Y > $p2Y } { + set deltaY [expr $p1Y - $p2Y] + } else { + set deltaY [expr $p2Y - $p1Y] + } + + set winSize [renWin GetSize] + set winX [lindex $winSize 0] + set winY [lindex $winSize 1] + + set sx [expr $deltaX / $winX] + set sy [expr $deltaY / $winY] + + if { $sx > $sy } { + set dolly [expr 1.0 + 1.0/(2.0*$sx)] + } else { + set dolly [expr 1.0 + 1.0/(2.0*$sy)] + } + $camera Dolly $dolly + ren1 ResetCameraClippingRange + + set bboxEnabled 0 + bboxActor VisibilityOff + renWin Render +} + diff --git a/Examples/ImageProcessing/Tcl/MandelbrotViewer.tcl b/Examples/ImageProcessing/Tcl/MandelbrotViewer.tcl new file mode 100644 index 0000000..29840ca --- /dev/null +++ b/Examples/ImageProcessing/Tcl/MandelbrotViewer.tcl @@ -0,0 +1,358 @@ +# +# This script uses a vtkTkRenderWidget to create a +# Tk widget that is associated with a vtkRenderWindow. +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +set RANGE 150 +set MAX_ITERATIONS_1 $RANGE +set MAX_ITERATIONS_2 $RANGE +set XRAD 200 +set YRAD 200 + +# +# Create firt Mandelbrot viewer +# +vtkImageMandelbrotSource mandelbrot1 + mandelbrot1 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_1)] + mandelbrot1 SetWholeExtent [expr -$XRAD] [expr $XRAD-1] \ + [expr -$YRAD] [expr $YRAD-1] \ + 0 0 + set sample [expr 1.3 / $XRAD] + mandelbrot1 SetSampleCX $sample $sample $sample $sample + mandelbrot1 SetOriginCX -0.72 0.22 0.0 0.0 + mandelbrot1 SetProjectionAxes 0 1 2 + +vtkLookupTable table1 + table1 SetTableRange 0 $RANGE + table1 SetNumberOfColors $RANGE + table1 Build + table1 SetTableValue [expr $RANGE - 1] 0.0 0.0 0.0 0.0 + +vtkImageMapToColors map1 + map1 SetInputConnection [mandelbrot1 GetOutputPort] + map1 SetOutputFormatToRGB + map1 SetLookupTable table1 + +vtkImageViewer viewer + viewer SetInputConnection [map1 GetOutputPort] + viewer SetColorWindow 255.0 + viewer SetColorLevel 127.5 + [viewer GetActor2D] SetPosition $XRAD $YRAD + +# +# Create second Mandelbrot viewer +# +vtkImageMandelbrotSource mandelbrot2 + mandelbrot2 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_2)] + mandelbrot2 SetWholeExtent [expr -$XRAD] [expr $XRAD-1] \ + [expr -$YRAD] [expr $YRAD-1] \ + 0 0 + set sample [expr 1.3 / $XRAD] + mandelbrot2 SetSampleCX $sample $sample $sample $sample + mandelbrot2 SetOriginCX -0.72 0.22 0.0 0.0 + mandelbrot2 SetProjectionAxes 2 3 1 + +vtkLookupTable table2 + table2 SetTableRange 0 $RANGE + table2 SetNumberOfColors $RANGE + table2 Build + table2 SetTableValue [expr $RANGE - 1] 0.0 0.0 0.0 0.0 + +vtkImageMapToColors map2 + map2 SetInputConnection [mandelbrot2 GetOutputPort] + map2 SetOutputFormatToRGB + map2 SetLookupTable table2 + +vtkImageViewer viewer2 + viewer2 SetInputConnection [map2 GetOutputPort] + viewer2 SetColorWindow 256.0 + viewer2 SetColorLevel 127.5 + [viewer2 GetActor2D] SetPosition $XRAD $YRAD + +# +# Create the GUI: two vtkTkImageViewer widgets and a quit/reset buttons +# +wm withdraw . +set top [toplevel .top] +wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit +wm title .top "Mandelbrot Viewer" + +set f1 [frame $top.f1] + +pack $f1 \ + -side bottom \ + -fill both -expand f + +# +# Create the image viewer widget for set 1 +# +set manFrame [frame $f1.man] +set julFrame [frame $f1.jul] + +pack $manFrame $julFrame \ + -side left \ + -padx 3 -pady 3 \ + -fill both -expand f + +set manView [vtkTkImageViewerWidget $manFrame.view \ + -iv viewer \ + -width [expr $XRAD*2] \ + -height [expr $YRAD*2]] + +set manRange [label $manFrame.range \ + -text "Mandelbrot Range: 0 - $RANGE"] + +set quit [button $manFrame.quit \ + -text "Quit" \ + -command ::vtk::cb_exit] + +# +# Create the image viewer widget for set 2 +# +pack $manView $manRange $quit \ + -side top \ + -padx 2 -pady 2 \ + -fill both -expand f + +set julView [vtkTkImageViewerWidget $julFrame.view \ + -iv viewer2 \ + -width [expr $XRAD*2] \ + -height [expr $YRAD*2]] + +set julRange [label $julFrame.range \ + -text "Julia Range: 0 - $RANGE"] + +set reset [button $julFrame.reset \ + -text "Reset" \ + -command Reset] + +pack $julView $julRange $reset \ + -side top \ + -padx 2 -pady 2 \ + -fill both -expand f +# +# The equation label +# +set equation [label $top.equation \ + -text "X = X^2 + C"] + +pack $equation \ + -side bottom \ + -fill x -expand f + +# +# Create the default bindings +# +::vtk::bind_tk_imageviewer_widget $manView +::vtk::bind_tk_imageviewer_widget $julView + +# +# Override some of the bindings +# +foreach {widget master slave} [list $manView 1 2 $julView 2 1] { + + set iren [[[$widget GetImageViewer] GetRenderWindow] GetInteractor] + set istyle [$iren GetInteractorStyle] + + # Zoom in + + $istyle RemoveObservers LeftButtonPressEvent + $istyle AddObserver LeftButtonPressEvent \ + [list StartZoom $iren] + + $istyle RemoveObservers LeftButtonReleaseEvent + $istyle AddObserver LeftButtonReleaseEvent \ + [list EndZoom $iren $master $slave] + + # Zoom out + + $istyle RemoveObservers RightButtonPressEvent + $istyle AddObserver RightButtonPressEvent \ + [list ZoomOut $iren $master $slave] + + $istyle RemoveObservers RightButtonReleaseEvent + + # Pan + + $istyle RemoveObservers MiddleButtonPressEvent + $istyle AddObserver MiddleButtonPressEvent \ + [list Pan $iren $master $slave] + + $istyle RemoveObservers MiddleButtonReleaseEvent +} + +# +# Update the display +# +proc MandelbrotUpdate {} { + global MAX_ITERATIONS_1 MAX_ITERATIONS_2 RANGE + global manView julView manRange julRange + + mandelbrot1 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_1)] + mandelbrot2 SetMaximumNumberOfIterations [expr int($MAX_ITERATIONS_1)] + + set tmp [mandelbrot1 GetOriginCX] + set cr [lindex $tmp 0] + set ci [lindex $tmp 1] + set xr [lindex $tmp 2] + set xi [lindex $tmp 3] + + mandelbrot1 Update + set tmp [[mandelbrot1 GetOutput] GetScalarRange] + set min [lindex $tmp 0] + set max [lindex $tmp 1] + $manRange configure -text "C = $cr + i $ci, Mandelbrot Range: $min - $max" + eval table1 SetTableRange [expr $min - 1] $max + set MAX_ITERATIONS_1 [expr $min + $RANGE] + + mandelbrot2 Update + set tmp [[mandelbrot2 GetOutput] GetScalarRange] + set min [lindex $tmp 0] + set max [lindex $tmp 1] + $julRange configure -text "X = $xr + i $xi, Julia Range: $min - $max" + eval table2 SetTableRange [expr $min - 1] $max + set MAX_ITERATIONS_2 [expr $min + $RANGE] + + $manView Render + $julView Render +} + +# +# Reset both sets +# +proc Reset {} { + global MAX_ITERATIONS_1 MAX_ITERATIONS_2 RANGE XRAD + + set MAX_ITERATIONS_2 $RANGE + set MAX_ITERATIONS_1 $RANGE + + set sample [expr 1.3 / $XRAD] + mandelbrot1 SetSampleCX $sample $sample $sample $sample + mandelbrot1 SetOriginCX -0.72 0.22 0.0 0.0 + + set sample [expr 1.3 / $XRAD] + mandelbrot2 SetSampleCX $sample $sample $sample $sample + mandelbrot2 SetOriginCX -0.72 0.22 0.0 0.0 + + MandelbrotUpdate +} + +# +# Zoom in +# +proc StartZoom {iren} { + global X Y + + set pos [$iren GetEventPosition] + set X [lindex $pos 0] + set Y [lindex $pos 1] +} + +proc EndZoom {iren master slave} { + global X Y XRAD YRAD + + # Put origin in middle. + + set pos [$iren GetEventPosition] + set x [expr [lindex $pos 0] - $XRAD] + set y [expr [lindex $pos 1] - $YRAD] + set X [expr $X - $XRAD] + set Y [expr $Y - $YRAD] + + # Sort + + if {$X < $x} { + set tmp $X + set X $x + set x $tmp + } + if {$Y < $y} { + set tmp $Y + set Y $y + set y $tmp + } + + # Middle/radius + + set xMid [expr 0.5 * ($x + $X)] + set yMid [expr 0.5 * ($y + $Y)] + set xDim [expr ($X - $x)] + set yDim [expr ($Y - $y)] + + # Determine scale + + if { $xDim <= 4 && $yDim <= 4} { + # Box too small. Zoom into point. + set scale 0.5 + } else { + # Relative to window dimensions + set xDim [expr 1.0 * $xDim / (2*$XRAD)] + set yDim [expr 1.0 * $yDim / (2*$YRAD)] + # Take the largest + if {$xDim > $yDim} { + set scale $xDim + } else { + set scale $yDim + } + } + + mandelbrot$master Pan $xMid $yMid 0.0 + mandelbrot$master Zoom $scale + mandelbrot$slave CopyOriginAndSample mandelbrot$master + + MandelbrotUpdate +} + +# +# Zoom out +# +proc ZoomOut {iren master slave} { + global XRAD YRAD + + # Put origin in middle. + + set pos [$iren GetEventPosition] + set x [expr [lindex $pos 0] - $XRAD] + set y [expr [lindex $pos 1] - $YRAD] + + set scale 2.0 + + # Compute new origin. + + mandelbrot$master Pan $x $y 0.0 + mandelbrot$master Zoom $scale + mandelbrot$slave CopyOriginAndSample mandelbrot$master + + MandelbrotUpdate +} + +# +# Pan +# +proc Pan {iren master slave} { + global XRAD YRAD + + # Put origin in middle. + + set pos [$iren GetEventPosition] + set x [expr [lindex $pos 0] - $XRAD] + set y [expr [lindex $pos 1] - $YRAD] + + set scale 2.0 + + # Compute new origin. + + mandelbrot$master Pan $x $y 0.0 + mandelbrot$slave CopyOriginAndSample mandelbrot$master + + MandelbrotUpdate +} + +MandelbrotUpdate + + diff --git a/Examples/MangledMesa/README.txt b/Examples/MangledMesa/README.txt new file mode 100644 index 0000000..d7becc5 --- /dev/null +++ b/Examples/MangledMesa/README.txt @@ -0,0 +1,41 @@ +Here is how to compile VTK with mangled Mesa: + +1) Build and install mangled Mesa. Since the included file names are + identical to the files provided by OpenGL, it is required to install + Mesa such that the include directory is not the same as some other + package used by VTK. For example, if Tcl/Tk headers are in + /usr/local/include and if you install Mesa in /usr/local, VTK will + wrongly use the Mesa headers even for the OpenGL classes. To avoid + this, install Mesa away from any other package used by VTK. I + recommend creating a directory under your home and installing it there. + It also important that you name the Mesa library differently. I + prefer to name it MesaGL. + +2) When the VTK build configuring with CMake, set the following options: + +//Use mangled Mesa with OpenGL +VTK_USE_MANGLED_MESA:BOOL=ON + +//What is the path where the file GL/gl_mangle.h can be found +MANGLED_MESA_INCLUDE_DIR:PATH=/home/berk/mesa/include + +//Where can the MesaGL library be found +MANGLED_MESA_LIBRARY:FILEPATH=/home/berk/mesa/lib/libMGL.a + +//Where can the OSMesa library be found +MANGLED_OSMESA_LIBRARY:FILEPATH=/home/berk/mesalib/libOSMesa.a + +Note that the Mesa library is named differently than the OpenGL library +(which is usually something like libGL.a). MesaOS is the offscreen +library which exists on some Mesa distributions, it might not be +needed (in which case, you should leave it as NOTFOUND). + +Note: The MANGLED_* variables will not be in the cache until +VTK_USED_MANGLE_MESA has been turned on, and cmake has been run again. + + +3) Compile VTK. + + + + \ No newline at end of file diff --git a/Examples/MangledMesa/Tcl/OffScreenCone.tcl b/Examples/MangledMesa/Tcl/OffScreenCone.tcl new file mode 100644 index 0000000..eaece92 --- /dev/null +++ b/Examples/MangledMesa/Tcl/OffScreenCone.tcl @@ -0,0 +1,45 @@ +# This example demonstrates how the off-screen capabilities +# of Mesa can be used in VTK. +# Note that to be able to run this example, you need to compile +# VTK with mangled Mesa. See the README.txt file in this directory +# for instructions on how this can be done. + +package require vtk +package require vtkinteraction + +# Create Mesa specific render window and renderer +# When using Mesa, you should always create Mesa specific renderers, +# render windows, mappers, actors, lights, cameras etc... +# See the Mesa classes in the Rendering directory for a list of +# existing classes. +vtkXMesaRenderWindow renWin +# Will render in memory. +renWin OffScreenRenderingOn + +vtkMesaRenderer ren +renWin AddRenderer ren + +vtkConeSource cone + +vtkMesaPolyDataMapper mp +mp SetInputConnection [cone GetOutputPort] + +vtkMesaActor actor +actor SetMapper mp + +ren AddActor actor + +renWin Render + +# Save the window to a png file +vtkWindowToImageFilter w2if +w2if SetInput renWin + +vtkPNGWriter wr +wr SetInputConnection [w2if GetOutputPort] +wr SetFileName "MangledMesaTest.png" +wr Write + +# Exit without displaying anything +vtkCommand DeleteAllObjects +exit diff --git a/Examples/MangledMesa/Tcl/OffScreenPrinting.tcl b/Examples/MangledMesa/Tcl/OffScreenPrinting.tcl new file mode 100644 index 0000000..a18b77e --- /dev/null +++ b/Examples/MangledMesa/Tcl/OffScreenPrinting.tcl @@ -0,0 +1,112 @@ +package require vtk +package require vtkinteraction + +# This script demonstrates the use of mangled Mesa to generate an +# off-screen copy of the OpenGL render window. A cone is created +# and added to the OpenGL renderer. When the user press the Print +# button, a copy of the scene is rendered on the Mesa window +# (which is set to render in memory) and then the scene is save to +# a png file using the png writer. + +# Create the pipeline +# Note that an equivalent Mesa object has to be created for each +# OpenGL object. + +# The OpenGL render window +vtkRenderWindow rw +# The Mesa equivalent +vtkXMesaRenderWindow mrw +mrw OffScreenRenderingOn + +# OpenGL +vtkRenderer ren +rw AddRenderer ren +# Mesa +vtkMesaRenderer mren +mrw AddRenderer mren + +vtkConeSource cone + +# OpenGL +vtkPolyDataMapper map +map SetInputConnection [cone GetOutputPort] +# Mesa +vtkMesaPolyDataMapper mmap +mmap SetInputConnection [cone GetOutputPort] + +# OpenGL +vtkActor actor +actor SetMapper map +# Mesa +vtkMesaActor mactor +mactor SetMapper mmap + +# Add the actor to the renderer +ren AddActor actor +mren AddActor mactor + +# These are for creating an image from the Mesa render window +vtkWindowToImageFilter w2if +w2if SetInput mrw + +vtkPNGWriter writer +writer SetInputConnection [w2if GetOutputPort] +writer SetFileName "MesaPrintout.png" + +set mesaCamera [mren GetActiveCamera] +set openGLCamera [ren GetActiveCamera] + +proc PrintWithMesa {} { + global mesaCamera openGLCamera + + # This is needed to create a default mesa light + mrw Render + + set mesaLights [mren GetLights] + eval $mesaLights InitTraversal + set mesaLight [$mesaLights GetNextItem] + set openGLLights [ren GetLights] + eval $openGLLights InitTraversal + set openGLLight [$openGLLights GetNextItem] + + eval $mesaCamera SetPosition [$openGLCamera GetPosition] + eval $mesaCamera SetFocalPoint [$openGLCamera GetFocalPoint] + eval $mesaCamera SetViewUp [$openGLCamera GetViewUp] + eval $mesaCamera SetClippingRange [$openGLCamera GetClippingRange] + + eval $mesaLight DeepCopy $openGLLight + + mrw Render + + # This is here to force the window to image filter to + # update it's image. Required. + w2if Modified + + writer Write +} + +# ------------------- Create the UI --------------------- +wm withdraw . + +# Create the toplevel window +toplevel .top +wm title .top {Printing with Mesa Offscreen Demo} + +# Create two frames +frame .top.f1 +frame .top.f2 +pack .top.f1 .top.f2 -side top -expand 1 -fill both + +vtkTkRenderWidget .top.f1.rw -width 400 -height 400 -rw rw +::vtk::bind_tk_render_widget .top.f1.rw +pack .top.f1.rw -expand 1 -fill both + + +button .top.f2.b0 -text "Print" -command {PrintWithMesa} +button .top.f2.b1 -text "Quit" -command ::vtk::cb_exit +pack .top.f2.b0 -expand 1 -fill x +pack .top.f2.b1 -expand 1 -fill x + + + + diff --git a/Examples/Medical/Cxx/CMakeLists.txt b/Examples/Medical/Cxx/CMakeLists.txt new file mode 100644 index 0000000..46ee969 --- /dev/null +++ b/Examples/Medical/Cxx/CMakeLists.txt @@ -0,0 +1,15 @@ +PROJECT (Medical) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Medical1 Medical1.cxx) +ADD_EXECUTABLE(Medical2 Medical2.cxx) +ADD_EXECUTABLE(Medical3 Medical3.cxx) + +TARGET_LINK_LIBRARIES(Medical1 vtkRendering vtkIO) +TARGET_LINK_LIBRARIES(Medical2 vtkRendering vtkIO) +TARGET_LINK_LIBRARIES(Medical3 vtkRendering vtkIO) diff --git a/Examples/Medical/Cxx/Medical1.cxx b/Examples/Medical/Cxx/Medical1.cxx new file mode 100644 index 0000000..1a43318 --- /dev/null +++ b/Examples/Medical/Cxx/Medical1.cxx @@ -0,0 +1,142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Medical1.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example reads a volume dataset, extracts an isosurface that +// represents the skin and displays it. +// + +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkVolume16Reader.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkOutlineFilter.h" +#include "vtkCamera.h" +#include "vtkProperty.h" +#include "vtkPolyDataNormals.h" +#include "vtkContourFilter.h" + +int main (int argc, char **argv) +{ + if (argc < 2) + { + cout << "Usage: " << argv[0] << " DATADIR/headsq/quarter" << endl; + return 1; + } + + // Create the renderer, the render window, and the interactor. The renderer + // draws into the render window, the interactor enables mouse- and + // keyboard-based interaction with the data within the render window. + // + vtkRenderer *aRenderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(aRenderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The following reader is used to read a series of 2D slices (images) + // that compose the volume. The slice dimensions are set, and the + // pixel spacing. The data Endianness must also be specified. The reader + // usese the FilePrefix in combination with the slice number to construct + // filenames using the format FilePrefix.%d. (In this case the FilePrefix + // is the root name of the file: quarter.) + vtkVolume16Reader *v16 = vtkVolume16Reader::New(); + v16->SetDataDimensions (64,64); + v16->SetImageRange (1,93); + v16->SetDataByteOrderToLittleEndian(); + v16->SetFilePrefix (argv[1]); + v16->SetDataSpacing (3.2, 3.2, 1.5); + + // An isosurface, or contour value of 500 is known to correspond to the + // skin of the patient. Once generated, a vtkPolyDataNormals filter is + // is used to create normals for smooth surface shading during rendering. + vtkContourFilter *skinExtractor = vtkContourFilter::New(); + skinExtractor->SetInputConnection(v16->GetOutputPort()); + skinExtractor->SetValue(0, 500); + vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New(); + skinNormals->SetInputConnection(skinExtractor->GetOutputPort()); + skinNormals->SetFeatureAngle(60.0); + vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New(); + skinMapper->SetInputConnection(skinNormals->GetOutputPort()); + skinMapper->ScalarVisibilityOff(); + vtkActor *skin = vtkActor::New(); + skin->SetMapper(skinMapper); + + // An outline provides context around the data. + // + vtkOutlineFilter *outlineData = vtkOutlineFilter::New(); + outlineData->SetInputConnection(v16->GetOutputPort()); + vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New(); + mapOutline->SetInputConnection(outlineData->GetOutputPort()); + vtkActor *outline = vtkActor::New(); + outline->SetMapper(mapOutline); + outline->GetProperty()->SetColor(0,0,0); + + // It is convenient to create an initial view of the data. The FocalPoint + // and Position form a vector direction. Later on (ResetCamera() method) + // this vector is used to position the camera to look at the data in + // this direction. + vtkCamera *aCamera = vtkCamera::New(); + aCamera->SetViewUp (0, 0, -1); + aCamera->SetPosition (0, 1, 0); + aCamera->SetFocalPoint (0, 0, 0); + aCamera->ComputeViewPlaneNormal(); + + // Actors are added to the renderer. An initial camera view is created. + // The Dolly() method moves the camera towards the FocalPoint, + // thereby enlarging the image. + aRenderer->AddActor(outline); + aRenderer->AddActor(skin); + aRenderer->SetActiveCamera(aCamera); + aRenderer->ResetCamera (); + aCamera->Dolly(1.5); + + // Set a background color for the renderer and set the size of the + // render window (expressed in pixels). + aRenderer->SetBackground(1,1,1); + renWin->SetSize(640, 480); + + // Note that when camera movement occurs (as it does in the Dolly() + // method), the clipping planes often need adjusting. Clipping planes + // consist of two planes: near and far along the view direction. The + // near plane clips out objects in front of the plane; the far plane + // clips out objects behind the plane. This way only what is drawn + // between the planes is actually rendered. + aRenderer->ResetCameraClippingRange (); + + // Initialize the event loop and then start it. + iren->Initialize(); + iren->Start(); + + // It is important to delete all objects created previously to prevent + // memory leaks. In this case, since the program is on its way to + // exiting, it is not so important. But in applications it is + // essential. + v16->Delete(); + skinExtractor->Delete(); + skinNormals->Delete(); + skinMapper->Delete(); + skin->Delete(); + outlineData->Delete(); + mapOutline->Delete(); + outline->Delete(); + aCamera->Delete(); + iren->Delete(); + renWin->Delete(); + aRenderer->Delete(); + + return 0; +} diff --git a/Examples/Medical/Cxx/Medical2.cxx b/Examples/Medical/Cxx/Medical2.cxx new file mode 100644 index 0000000..3db90d6 --- /dev/null +++ b/Examples/Medical/Cxx/Medical2.cxx @@ -0,0 +1,180 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Medical2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example reads a volume dataset, extracts two isosurfaces that +// represent the skin and bone, and then displays them. +// + +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkVolume16Reader.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkProperty.h" +#include "vtkOutlineFilter.h" +#include "vtkCamera.h" +#include "vtkPolyDataMapper.h" +#include "vtkStripper.h" +#include "vtkPolyDataNormals.h" +#include "vtkContourFilter.h" + +int main (int argc, char **argv) +{ + if (argc < 2) + { + cout << "Usage: " << argv[0] << " DATADIR/headsq/quarter" << endl; + return 1; + } + + // Create the renderer, the render window, and the interactor. The renderer + // draws into the render window, the interactor enables mouse- and + // keyboard-based interaction with the data within the render window. + // + vtkRenderer *aRenderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(aRenderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The following reader is used to read a series of 2D slices (images) + // that compose the volume. The slice dimensions are set, and the + // pixel spacing. The data Endianness must also be specified. The reader + // usese the FilePrefix in combination with the slice number to construct + // filenames using the format FilePrefix.%d. (In this case the FilePrefix + // is the root name of the file: quarter.) + vtkVolume16Reader *v16 = vtkVolume16Reader::New(); + v16->SetDataDimensions(64,64); + v16->SetDataByteOrderToLittleEndian(); + v16->SetFilePrefix (argv[1]); + v16->SetImageRange(1, 93); + v16->SetDataSpacing (3.2, 3.2, 1.5); + + // An isosurface, or contour value of 500 is known to correspond to the + // skin of the patient. Once generated, a vtkPolyDataNormals filter is + // is used to create normals for smooth surface shading during rendering. + // The triangle stripper is used to create triangle strips from the + // isosurface; these render much faster on may systems. + vtkContourFilter *skinExtractor = vtkContourFilter::New(); + skinExtractor->SetInputConnection(v16->GetOutputPort()); + skinExtractor->SetValue(0, 500); + vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New(); + skinNormals->SetInputConnection(skinExtractor->GetOutputPort()); + skinNormals->SetFeatureAngle(60.0); + vtkStripper *skinStripper = vtkStripper::New(); + skinStripper->SetInputConnection(skinNormals->GetOutputPort()); + vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New(); + skinMapper->SetInputConnection(skinStripper->GetOutputPort()); + skinMapper->ScalarVisibilityOff(); + vtkActor *skin = vtkActor::New(); + skin->SetMapper(skinMapper); + skin->GetProperty()->SetDiffuseColor(1, .49, .25); + skin->GetProperty()->SetSpecular(.3); + skin->GetProperty()->SetSpecularPower(20); + skin->GetProperty()->SetOpacity(1.0); + + // An isosurface, or contour value of 1150 is known to correspond to the + // skin of the patient. Once generated, a vtkPolyDataNormals filter is + // is used to create normals for smooth surface shading during rendering. + // The triangle stripper is used to create triangle strips from the + // isosurface; these render much faster on may systems. + vtkContourFilter *boneExtractor = vtkContourFilter::New(); + boneExtractor->SetInputConnection(v16->GetOutputPort()); + boneExtractor->SetValue(0, 1150); + vtkPolyDataNormals *boneNormals = vtkPolyDataNormals::New(); + boneNormals->SetInputConnection(boneExtractor->GetOutputPort()); + boneNormals->SetFeatureAngle(60.0); + vtkStripper *boneStripper = vtkStripper::New(); + boneStripper->SetInputConnection(boneNormals->GetOutputPort()); + vtkPolyDataMapper *boneMapper = vtkPolyDataMapper::New(); + boneMapper->SetInputConnection(boneStripper->GetOutputPort()); + boneMapper->ScalarVisibilityOff(); + vtkActor *bone = vtkActor::New(); + bone->SetMapper(boneMapper); + bone->GetProperty()->SetDiffuseColor(1, 1, .9412); + + // An outline provides context around the data. + // + vtkOutlineFilter *outlineData = vtkOutlineFilter::New(); + outlineData->SetInputConnection(v16->GetOutputPort()); + vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New(); + mapOutline->SetInputConnection(outlineData->GetOutputPort()); + vtkActor *outline = vtkActor::New(); + outline->SetMapper(mapOutline); + outline->GetProperty()->SetColor(0,0,0); + + // It is convenient to create an initial view of the data. The FocalPoint + // and Position form a vector direction. Later on (ResetCamera() method) + // this vector is used to position the camera to look at the data in + // this direction. + vtkCamera *aCamera = vtkCamera::New(); + aCamera->SetViewUp (0, 0, -1); + aCamera->SetPosition (0, 1, 0); + aCamera->SetFocalPoint (0, 0, 0); + aCamera->ComputeViewPlaneNormal(); + + // Actors are added to the renderer. An initial camera view is created. + // The Dolly() method moves the camera towards the FocalPoint, + // thereby enlarging the image. + aRenderer->AddActor(outline); + aRenderer->AddActor(skin); + aRenderer->AddActor(bone); + aRenderer->SetActiveCamera(aCamera); + aRenderer->ResetCamera (); + aCamera->Dolly(1.5); + + // Set a background color for the renderer and set the size of the + // render window (expressed in pixels). + aRenderer->SetBackground(1,1,1); + renWin->SetSize(640, 480); + + // Note that when camera movement occurs (as it does in the Dolly() + // method), the clipping planes often need adjusting. Clipping planes + // consist of two planes: near and far along the view direction. The + // near plane clips out objects in front of the plane; the far plane + // clips out objects behind the plane. This way only what is drawn + // between the planes is actually rendered. + aRenderer->ResetCameraClippingRange (); + + // Set a background color for the renderer and set the size of the + // render window (expressed in pixels). + iren->Initialize(); + iren->Start(); + + // It is important to delete all objects created previously to prevent + // memory leaks. In this case, since the program is on its way to + // exiting, it is not so important. But in applications it is + // essential. + v16->Delete(); + skinExtractor->Delete(); + skinNormals->Delete(); + skinStripper->Delete(); + skinMapper->Delete(); + skin->Delete(); + boneExtractor->Delete(); + boneNormals->Delete(); + boneStripper->Delete(); + boneMapper->Delete(); + bone->Delete(); + outlineData->Delete(); + mapOutline->Delete(); + outline->Delete(); + aCamera->Delete(); + aRenderer->Delete(); + renWin->Delete(); + iren->Delete(); + + return 0; +} diff --git a/Examples/Medical/Cxx/Medical3.cxx b/Examples/Medical/Cxx/Medical3.cxx new file mode 100644 index 0000000..1ae5f16 --- /dev/null +++ b/Examples/Medical/Cxx/Medical3.cxx @@ -0,0 +1,271 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Medical3.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// +// This example reads a volume dataset, extracts two isosurfaces that +// represent the skin and bone, creates three orthogonal planes +// (saggital, axial, coronal), and displays them. +// +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkVolume16Reader.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkOutlineFilter.h" +#include "vtkCamera.h" +#include "vtkStripper.h" +#include "vtkLookupTable.h" +#include "vtkImageDataGeometryFilter.h" +#include "vtkProperty.h" +#include "vtkPolyDataNormals.h" +#include "vtkContourFilter.h" +#include "vtkImageData.h" +#include "vtkImageMapToColors.h" +#include "vtkImageActor.h" + +int main (int argc, char **argv) +{ + if (argc < 2) + { + cout << "Usage: " << argv[0] << " DATADIR/headsq/quarter" << endl; + return 1; + } + + // Create the renderer, the render window, and the interactor. The + // renderer draws into the render window, the interactor enables + // mouse- and keyboard-based interaction with the data within the + // render window. + // + vtkRenderer *aRenderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(aRenderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The following reader is used to read a series of 2D slices (images) + // that compose the volume. The slice dimensions are set, and the + // pixel spacing. The data Endianness must also be specified. The + // reader usese the FilePrefix in combination with the slice number to + // construct filenames using the format FilePrefix.%d. (In this case + // the FilePrefix is the root name of the file: quarter.) + vtkVolume16Reader *v16 = vtkVolume16Reader::New(); + v16->SetDataDimensions(64,64); + v16->SetDataByteOrderToLittleEndian(); + v16->SetFilePrefix (argv[1]); + v16->SetImageRange(1, 93); + v16->SetDataSpacing (3.2, 3.2, 1.5); + + // An isosurface, or contour value of 500 is known to correspond to + // the skin of the patient. Once generated, a vtkPolyDataNormals + // filter is is used to create normals for smooth surface shading + // during rendering. The triangle stripper is used to create triangle + // strips from the isosurface; these render much faster on may + // systems. + vtkContourFilter *skinExtractor = vtkContourFilter::New(); + skinExtractor->SetInputConnection( v16->GetOutputPort()); + skinExtractor->SetValue(0, 500); + vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New(); + skinNormals->SetInputConnection(skinExtractor->GetOutputPort()); + skinNormals->SetFeatureAngle(60.0); + vtkStripper *skinStripper = vtkStripper::New(); + skinStripper->SetInputConnection(skinNormals->GetOutputPort()); + vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New(); + skinMapper->SetInputConnection(skinStripper->GetOutputPort()); + skinMapper->ScalarVisibilityOff(); + vtkActor *skin = vtkActor::New(); + skin->SetMapper(skinMapper); + skin->GetProperty()->SetDiffuseColor(1, .49, .25); + skin->GetProperty()->SetSpecular(.3); + skin->GetProperty()->SetSpecularPower(20); + + // An isosurface, or contour value of 1150 is known to correspond to + // the skin of the patient. Once generated, a vtkPolyDataNormals + // filter is is used to create normals for smooth surface shading + // during rendering. The triangle stripper is used to create triangle + // strips from the isosurface; these render much faster on may + // systems. + vtkContourFilter *boneExtractor = vtkContourFilter::New(); + boneExtractor->SetInputConnection(v16->GetOutputPort()); + boneExtractor->SetValue(0, 1150); + vtkPolyDataNormals *boneNormals = vtkPolyDataNormals::New(); + boneNormals->SetInputConnection(boneExtractor->GetOutputPort()); + boneNormals->SetFeatureAngle(60.0); + vtkStripper *boneStripper = vtkStripper::New(); + boneStripper->SetInputConnection(boneNormals->GetOutputPort()); + vtkPolyDataMapper *boneMapper = vtkPolyDataMapper::New(); + boneMapper->SetInputConnection(boneStripper->GetOutputPort()); + boneMapper->ScalarVisibilityOff(); + vtkActor *bone = vtkActor::New(); + bone->SetMapper(boneMapper); + bone->GetProperty()->SetDiffuseColor(1, 1, .9412); + + // An outline provides context around the data. + // + vtkOutlineFilter *outlineData = vtkOutlineFilter::New(); + outlineData->SetInputConnection(v16->GetOutputPort()); + vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New(); + mapOutline->SetInputConnection(outlineData->GetOutputPort()); + vtkActor *outline = vtkActor::New(); + outline->SetMapper(mapOutline); + outline->GetProperty()->SetColor(0,0,0); + + // Now we are creating three orthogonal planes passing through the + // volume. Each plane uses a different texture map and therefore has + // diferent coloration. + + // Start by creatin a black/white lookup table. + vtkLookupTable *bwLut = vtkLookupTable::New(); + bwLut->SetTableRange (0, 2000); + bwLut->SetSaturationRange (0, 0); + bwLut->SetHueRange (0, 0); + bwLut->SetValueRange (0, 1); + bwLut->Build(); //effective built + + // Now create a lookup table that consists of the full hue circle + // (from HSV). + vtkLookupTable *hueLut = vtkLookupTable::New(); + hueLut->SetTableRange (0, 2000); + hueLut->SetHueRange (0, 1); + hueLut->SetSaturationRange (1, 1); + hueLut->SetValueRange (1, 1); + hueLut->Build(); //effective built + + // Finally, create a lookup table with a single hue but having a range + // in the saturation of the hue. + vtkLookupTable *satLut = vtkLookupTable::New(); + satLut->SetTableRange (0, 2000); + satLut->SetHueRange (.6, .6); + satLut->SetSaturationRange (0, 1); + satLut->SetValueRange (1, 1); + satLut->Build(); //effective built + + // Create the first of the three planes. The filter vtkImageMapToColors + // maps the data through the corresponding lookup table created above. The + // vtkImageActor is a type of vtkProp and conveniently displays an image on + // a single quadrilateral plane. It does this using texture mapping and as + // a result is quite fast. (Note: the input image has to be unsigned char + // values, which the vtkImageMapToColors produces.) Note also that by + // specifying the DisplayExtent, the pipeline requests data of this extent + // and the vtkImageMapToColors only processes a slice of data. + vtkImageMapToColors *saggitalColors = vtkImageMapToColors::New(); + saggitalColors->SetInputConnection(v16->GetOutputPort()); + saggitalColors->SetLookupTable(bwLut); + vtkImageActor *saggital = vtkImageActor::New(); + saggital->SetInput(saggitalColors->GetOutput()); + saggital->SetDisplayExtent(32,32, 0,63, 0,92); + + // Create the second (axial) plane of the three planes. We use the + // same approach as before except that the extent differs. + vtkImageMapToColors *axialColors = vtkImageMapToColors::New(); + axialColors->SetInputConnection(v16->GetOutputPort()); + axialColors->SetLookupTable(hueLut); + vtkImageActor *axial = vtkImageActor::New(); + axial->SetInput(axialColors->GetOutput()); + axial->SetDisplayExtent(0,63, 0,63, 46,46); + + // Create the third (coronal) plane of the three planes. We use + // the same approach as before except that the extent differs. + vtkImageMapToColors *coronalColors = vtkImageMapToColors::New(); + coronalColors->SetInputConnection(v16->GetOutputPort()); + coronalColors->SetLookupTable(satLut); + vtkImageActor *coronal = vtkImageActor::New(); + coronal->SetInput(coronalColors->GetOutput()); + coronal->SetDisplayExtent(0,63, 32,32, 0,92); + + // It is convenient to create an initial view of the data. The + // FocalPoint and Position form a vector direction. Later on + // (ResetCamera() method) this vector is used to position the camera + // to look at the data in this direction. + vtkCamera *aCamera = vtkCamera::New(); + aCamera->SetViewUp (0, 0, -1); + aCamera->SetPosition (0, 1, 0); + aCamera->SetFocalPoint (0, 0, 0); + aCamera->ComputeViewPlaneNormal(); + + // Actors are added to the renderer. + aRenderer->AddActor(outline); + aRenderer->AddActor(saggital); + aRenderer->AddActor(axial); + aRenderer->AddActor(coronal); + aRenderer->AddActor(axial); + aRenderer->AddActor(coronal); + aRenderer->AddActor(skin); + aRenderer->AddActor(bone); + + // Turn off bone for this example. + bone->VisibilityOff(); + + // Set skin to semi-transparent. + skin->GetProperty()->SetOpacity(0.5); + + // An initial camera view is created. The Dolly() method moves + // the camera towards the FocalPoint, thereby enlarging the image. + aRenderer->SetActiveCamera(aCamera); + aRenderer->Render(); + aRenderer->ResetCamera (); + aCamera->Dolly(1.5); + + // Set a background color for the renderer and set the size of the + // render window (expressed in pixels). + aRenderer->SetBackground(1,1,1); + renWin->SetSize(640, 480); + + // Note that when camera movement occurs (as it does in the Dolly() + // method), the clipping planes often need adjusting. Clipping planes + // consist of two planes: near and far along the view direction. The + // near plane clips out objects in front of the plane; the far plane + // clips out objects behind the plane. This way only what is drawn + // between the planes is actually rendered. + aRenderer->ResetCameraClippingRange (); + + // interact with data + iren->Initialize(); + iren->Start(); + + // It is important to delete all objects created previously to prevent + // memory leaks. In this case, since the program is on its way to + // exiting, it is not so important. But in applications it is + // essential. + v16->Delete(); + skinExtractor->Delete(); + skinNormals->Delete(); + skinStripper->Delete(); + skinMapper->Delete(); + skin->Delete(); + boneExtractor->Delete(); + boneNormals->Delete(); + boneStripper->Delete(); + boneMapper->Delete(); + bone->Delete(); + outlineData->Delete(); + mapOutline->Delete(); + outline->Delete(); + bwLut->Delete(); + hueLut->Delete(); + satLut->Delete(); + saggitalColors->Delete(); + saggital->Delete(); + axialColors->Delete(); + axial->Delete(); + coronalColors->Delete(); + coronal->Delete(); + aCamera->Delete(); + aRenderer->Delete(); + renWin->Delete(); + iren->Delete(); + + return 0; +} diff --git a/Examples/Medical/Python/Medical1.py b/Examples/Medical/Python/Medical1.py new file mode 100644 index 0000000..f3cfa9c --- /dev/null +++ b/Examples/Medical/Python/Medical1.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +# This example reads a volume dataset, extracts an isosurface that +# represents the skin and displays it. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create the renderer, the render window, and the interactor. The +# renderer draws into the render window, the interactor enables mouse- +# and keyboard-based interaction with the scene. +aRenderer = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(aRenderer) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# The following reader is used to read a series of 2D slices (images) +# that compose the volume. The slice dimensions are set, and the +# pixel spacing. The data Endianness must also be specified. The reader +# usese the FilePrefix in combination with the slice number to construct +# filenames using the format FilePrefix.%d. (In this case the FilePrefix +# is the root name of the file: quarter.) +v16 = vtk.vtkVolume16Reader() +v16.SetDataDimensions(64, 64) +v16.SetDataByteOrderToLittleEndian() +v16.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter") +v16.SetImageRange(1, 93) +v16.SetDataSpacing(3.2, 3.2, 1.5) + +# An isosurface, or contour value of 500 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +skinExtractor = vtk.vtkContourFilter() +skinExtractor.SetInputConnection(v16.GetOutputPort()) +skinExtractor.SetValue(0, 500) +skinNormals = vtk.vtkPolyDataNormals() +skinNormals.SetInputConnection(skinExtractor.GetOutputPort()) +skinNormals.SetFeatureAngle(60.0) +skinMapper = vtk.vtkPolyDataMapper() +skinMapper.SetInputConnection(skinNormals.GetOutputPort()) +skinMapper.ScalarVisibilityOff() +skin = vtk.vtkActor() +skin.SetMapper(skinMapper) + +# An outline provides context around the data. +outlineData = vtk.vtkOutlineFilter() +outlineData.SetInputConnection(v16.GetOutputPort()) +mapOutline = vtk.vtkPolyDataMapper() +mapOutline.SetInputConnection(outlineData.GetOutputPort()) +outline = vtk.vtkActor() +outline.SetMapper(mapOutline) +outline.GetProperty().SetColor(0, 0, 0) + +# It is convenient to create an initial view of the data. The FocalPoint +# and Position form a vector direction. Later on (ResetCamera() method) +# this vector is used to position the camera to look at the data in +# this direction. +aCamera = vtk.vtkCamera() +aCamera.SetViewUp(0, 0, -1) +aCamera.SetPosition(0, 1, 0) +aCamera.SetFocalPoint(0, 0, 0) +aCamera.ComputeViewPlaneNormal() + +# Actors are added to the renderer. An initial camera view is created. +# The Dolly() method moves the camera towards the FocalPoint, +# thereby enlarging the image. +aRenderer.AddActor(outline) +aRenderer.AddActor(skin) +aRenderer.SetActiveCamera(aCamera) +aRenderer.ResetCamera() +aCamera.Dolly(1.5) + +# Set a background color for the renderer and set the size of the +# render window (expressed in pixels). +aRenderer.SetBackground(1, 1, 1) +renWin.SetSize(640, 480) + +# Note that when camera movement occurs (as it does in the Dolly() +# method), the clipping planes often need adjusting. Clipping planes +# consist of two planes: near and far along the view direction. The +# near plane clips out objects in front of the plane the far plane +# clips out objects behind the plane. This way only what is drawn +# between the planes is actually rendered. +aRenderer.ResetCameraClippingRange() + +# Interact with the data. +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Medical/Python/Medical2.py b/Examples/Medical/Python/Medical2.py new file mode 100644 index 0000000..835e9fa --- /dev/null +++ b/Examples/Medical/Python/Medical2.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +# This example reads a volume dataset, extracts two isosurfaces that +# represent the skin and bone, and then displays them. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create the renderer, the render window, and the interactor. The +# renderer draws into the render window, the interactor enables mouse- +# and keyboard-based interaction with the scene. +aRenderer = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(aRenderer) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# The following reader is used to read a series of 2D slices (images) +# that compose the volume. The slice dimensions are set, and the +# pixel spacing. The data Endianness must also be specified. The reader +# usese the FilePrefix in combination with the slice number to construct +# filenames using the format FilePrefix.%d. (In this case the FilePrefix +# is the root name of the file: quarter.) +v16 = vtk.vtkVolume16Reader() +v16.SetDataDimensions(64, 64) +v16.SetDataByteOrderToLittleEndian() +v16.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter") +v16.SetImageRange(1, 93) +v16.SetDataSpacing(3.2, 3.2, 1.5) + +# An isosurface, or contour value of 500 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +skinExtractor = vtk.vtkContourFilter() +skinExtractor.SetInputConnection(v16.GetOutputPort()) +skinExtractor.SetValue(0, 500) +skinNormals = vtk.vtkPolyDataNormals() +skinNormals.SetInputConnection(skinExtractor.GetOutputPort()) +skinNormals.SetFeatureAngle(60.0) +skinStripper = vtk.vtkStripper() +skinStripper.SetInputConnection(skinNormals.GetOutputPort()) +skinMapper = vtk.vtkPolyDataMapper() +skinMapper.SetInputConnection(skinStripper.GetOutputPort()) +skinMapper.ScalarVisibilityOff() +skin = vtk.vtkActor() +skin.SetMapper(skinMapper) +skin.GetProperty().SetDiffuseColor(1, .49, .25) +skin.GetProperty().SetSpecular(.3) +skin.GetProperty().SetSpecularPower(20) + +# An isosurface, or contour value of 1150 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +boneExtractor = vtk.vtkContourFilter() +boneExtractor.SetInputConnection(v16.GetOutputPort()) +boneExtractor.SetValue(0, 1150) +boneNormals = vtk.vtkPolyDataNormals() +boneNormals.SetInputConnection(boneExtractor.GetOutputPort()) +boneNormals.SetFeatureAngle(60.0) +boneStripper = vtk.vtkStripper() +boneStripper.SetInputConnection(boneNormals.GetOutputPort()) +boneMapper = vtk.vtkPolyDataMapper() +boneMapper.SetInputConnection(boneStripper.GetOutputPort()) +boneMapper.ScalarVisibilityOff() +bone = vtk.vtkActor() +bone.SetMapper(boneMapper) +bone.GetProperty().SetDiffuseColor(1, 1, .9412) + +# An outline provides context around the data. +outlineData = vtk.vtkOutlineFilter() +outlineData.SetInputConnection(v16.GetOutputPort()) +mapOutline = vtk.vtkPolyDataMapper() +mapOutline.SetInputConnection(outlineData.GetOutputPort()) +outline = vtk.vtkActor() +outline.SetMapper(mapOutline) +outline.GetProperty().SetColor(0, 0, 0) + +# It is convenient to create an initial view of the data. The FocalPoint +# and Position form a vector direction. Later on (ResetCamera() method) +# this vector is used to position the camera to look at the data in +# this direction. +aCamera = vtk.vtkCamera() +aCamera.SetViewUp(0, 0, -1) +aCamera.SetPosition(0, 1, 0) +aCamera.SetFocalPoint(0, 0, 0) +aCamera.ComputeViewPlaneNormal() + +# Actors are added to the renderer. An initial camera view is created. +# The Dolly() method moves the camera towards the FocalPoint, +# thereby enlarging the image. +aRenderer.AddActor(outline) +aRenderer.AddActor(skin) +aRenderer.AddActor(bone) +aRenderer.SetActiveCamera(aCamera) +aRenderer.ResetCamera() +aCamera.Dolly(1.5) + +# Set a background color for the renderer and set the size of the +# render window (expressed in pixels). +aRenderer.SetBackground(1, 1, 1) +renWin.SetSize(640, 480) + +# Note that when camera movement occurs (as it does in the Dolly() +# method), the clipping planes often need adjusting. Clipping planes +# consist of two planes: near and far along the view direction. The +# near plane clips out objects in front of the plane the far plane +# clips out objects behind the plane. This way only what is drawn +# between the planes is actually rendered. +aRenderer.ResetCameraClippingRange() + +# Interact with the data. +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Medical/Python/Medical3.py b/Examples/Medical/Python/Medical3.py new file mode 100644 index 0000000..4960597 --- /dev/null +++ b/Examples/Medical/Python/Medical3.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python + +# This example reads a volume dataset, extracts two isosurfaces that +# represent the skin and bone, creates three orthogonal planes +# (saggital, axial, coronal), and displays them. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create the renderer, the render window, and the interactor. The +# renderer draws into the render window, the interactor enables mouse- +# and keyboard-based interaction with the scene. +aRenderer = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(aRenderer) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# The following reader is used to read a series of 2D slices (images) +# that compose the volume. The slice dimensions are set, and the +# pixel spacing. The data Endianness must also be specified. The reader +# usese the FilePrefix in combination with the slice number to construct +# filenames using the format FilePrefix.%d. (In this case the FilePrefix +# is the root name of the file: quarter.) +v16 = vtk.vtkVolume16Reader() +v16.SetDataDimensions(64, 64) +v16.SetDataByteOrderToLittleEndian() +v16.SetFilePrefix(VTK_DATA_ROOT + "/Data/headsq/quarter") +v16.SetImageRange(1, 93) +v16.SetDataSpacing(3.2, 3.2, 1.5) + +# An isosurface, or contour value of 500 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +skinExtractor = vtk.vtkContourFilter() +skinExtractor.SetInputConnection(v16.GetOutputPort()) +skinExtractor.SetValue(0, 500) +skinNormals = vtk.vtkPolyDataNormals() +skinNormals.SetInputConnection(skinExtractor.GetOutputPort()) +skinNormals.SetFeatureAngle(60.0) +skinStripper = vtk.vtkStripper() +skinStripper.SetInputConnection(skinNormals.GetOutputPort()) +skinMapper = vtk.vtkPolyDataMapper() +skinMapper.SetInputConnection(skinStripper.GetOutputPort()) +skinMapper.ScalarVisibilityOff() +skin = vtk.vtkActor() +skin.SetMapper(skinMapper) +skin.GetProperty().SetDiffuseColor(1, .49, .25) +skin.GetProperty().SetSpecular(.3) +skin.GetProperty().SetSpecularPower(20) + +# An isosurface, or contour value of 1150 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +boneExtractor = vtk.vtkContourFilter() +boneExtractor.SetInputConnection(v16.GetOutputPort()) +boneExtractor.SetValue(0, 1150) +boneNormals = vtk.vtkPolyDataNormals() +boneNormals.SetInputConnection(boneExtractor.GetOutputPort()) +boneNormals.SetFeatureAngle(60.0) +boneStripper = vtk.vtkStripper() +boneStripper.SetInputConnection(boneNormals.GetOutputPort()) +boneMapper = vtk.vtkPolyDataMapper() +boneMapper.SetInputConnection(boneStripper.GetOutputPort()) +boneMapper.ScalarVisibilityOff() +bone = vtk.vtkActor() +bone.SetMapper(boneMapper) +bone.GetProperty().SetDiffuseColor(1, 1, .9412) + +# An outline provides context around the data. +outlineData = vtk.vtkOutlineFilter() +outlineData.SetInputConnection(v16.GetOutputPort()) +mapOutline = vtk.vtkPolyDataMapper() +mapOutline.SetInputConnection(outlineData.GetOutputPort()) +outline = vtk.vtkActor() +outline.SetMapper(mapOutline) +outline.GetProperty().SetColor(0, 0, 0) + +# Now we are creating three orthogonal planes passing through the +# volume. Each plane uses a different texture map and therefore has +# diferent coloration. + +# Start by creatin a black/white lookup table. +bwLut = vtk.vtkLookupTable() +bwLut.SetTableRange(0, 2000) +bwLut.SetSaturationRange(0, 0) +bwLut.SetHueRange(0, 0) +bwLut.SetValueRange(0, 1) +bwLut.Build() + +# Now create a lookup table that consists of the full hue circle (from +# HSV). +hueLut = vtk.vtkLookupTable() +hueLut.SetTableRange(0, 2000) +hueLut.SetHueRange(0, 1) +hueLut.SetSaturationRange(1, 1) +hueLut.SetValueRange(1, 1) +hueLut.Build() + +# Finally, create a lookup table with a single hue but having a range +# in the saturation of the hue. +satLut = vtk.vtkLookupTable() +satLut.SetTableRange(0, 2000) +satLut.SetHueRange(.6, .6) +satLut.SetSaturationRange(0, 1) +satLut.SetValueRange(1, 1) +satLut.Build() + +# Create the first of the three planes. The filter vtkImageMapToColors +# maps the data through the corresponding lookup table created above. +# The vtkImageActor is a type of vtkProp and conveniently displays an +# image on a single quadrilateral plane. It does this using texture +# mapping and as a result is quite fast. (Note: the input image has to +# be unsigned char values, which the vtkImageMapToColors produces.) +# Note also that by specifying the DisplayExtent, the pipeline +# requests data of this extent and the vtkImageMapToColors only +# processes a slice of data. +saggitalColors = vtk.vtkImageMapToColors() +saggitalColors.SetInputConnection(v16.GetOutputPort()) +saggitalColors.SetLookupTable(bwLut) +saggital = vtk.vtkImageActor() +saggital.SetInput(saggitalColors.GetOutput()) +saggital.SetDisplayExtent(32, 32, 0, 63, 0, 92) + +# Create the second (axial) plane of the three planes. We use the same +# approach as before except that the extent differs. +axialColors = vtk.vtkImageMapToColors() +axialColors.SetInputConnection(v16.GetOutputPort()) +axialColors.SetLookupTable(hueLut) +axial = vtk.vtkImageActor() +axial.SetInput(axialColors.GetOutput()) +axial.SetDisplayExtent(0, 63, 0, 63, 46, 46) + +# Create the third (coronal) plane of the three planes. We use the same +# approach as before except that the extent differs. +coronalColors = vtk.vtkImageMapToColors() +coronalColors.SetInputConnection(v16.GetOutputPort()) +coronalColors.SetLookupTable(satLut) +coronal = vtk.vtkImageActor() +coronal.SetInput(coronalColors.GetOutput()) +coronal.SetDisplayExtent(0, 63, 32, 32, 0, 92) + +# It is convenient to create an initial view of the data. The FocalPoint +# and Position form a vector direction. Later on (ResetCamera() method) +# this vector is used to position the camera to look at the data in +# this direction. +aCamera = vtk.vtkCamera() +aCamera.SetViewUp(0, 0, -1) +aCamera.SetPosition(0, 1, 0) +aCamera.SetFocalPoint(0, 0, 0) +aCamera.ComputeViewPlaneNormal() + +# Actors are added to the renderer. +aRenderer.AddActor(outline) +aRenderer.AddActor(saggital) +aRenderer.AddActor(axial) +aRenderer.AddActor(coronal) +#aRenderer.AddActor(axial) +#aRenderer.AddActor(coronal) +aRenderer.AddActor(skin) +aRenderer.AddActor(bone) + +# Turn off bone for this example. +bone.VisibilityOff() + +# Set skin to semi-transparent. +skin.GetProperty().SetOpacity(0.5) + +# An initial camera view is created. The Dolly() method moves +# the camera towards the FocalPoint, thereby enlarging the image. +aRenderer.SetActiveCamera(aCamera) +aRenderer.ResetCamera() +aCamera.Dolly(1.5) + +# Set a background color for the renderer and set the size of the +# render window (expressed in pixels). +aRenderer.SetBackground(1, 1, 1) +renWin.SetSize(640, 480) + +# Note that when camera movement occurs (as it does in the Dolly() +# method), the clipping planes often need adjusting. Clipping planes +# consist of two planes: near and far along the view direction. The +# near plane clips out objects in front of the plane the far plane +# clips out objects behind the plane. This way only what is drawn +# between the planes is actually rendered. +aRenderer.ResetCameraClippingRange() + +# Interact with the data. +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Medical/Tcl/Medical1.tcl b/Examples/Medical/Tcl/Medical1.tcl new file mode 100644 index 0000000..eee31a9 --- /dev/null +++ b/Examples/Medical/Tcl/Medical1.tcl @@ -0,0 +1,98 @@ +package require vtk +package require vtkinteraction + +# +# This example reads a volume dataset, extracts an isosurface that +# represents the skin and displays it. +# + +# Create the renderer, the render window, and the interactor. The renderer +# draws into the render window, the interactor enables mouse- and +# keyboard-based interaction with the scene. +# +vtkRenderer aRenderer +vtkRenderWindow renWin + renWin AddRenderer aRenderer +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# The following reader is used to read a series of 2D slices (images) +# that compose the volume. The slice dimensions are set, and the +# pixel spacing. The data Endianness must also be specified. The reader +# usese the FilePrefix in combination with the slice number to construct +# filenames using the format FilePrefix.%d. (In this case the FilePrefix +# is the root name of the file: quarter.) +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + +# An isosurface, or contour value of 500 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +vtkContourFilter skinExtractor + skinExtractor SetInputConnection [v16 GetOutputPort] + skinExtractor SetValue 0 500 +vtkPolyDataNormals skinNormals + skinNormals SetInputConnection [skinExtractor GetOutputPort] + skinNormals SetFeatureAngle 60.0 +vtkPolyDataMapper skinMapper + skinMapper SetInputConnection [skinNormals GetOutputPort] + skinMapper ScalarVisibilityOff +vtkActor skin + skin SetMapper skinMapper + +# An outline provides context around the data. +# +vtkOutlineFilter outlineData + outlineData SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outlineData GetOutputPort] +vtkActor outline + outline SetMapper mapOutline + [outline GetProperty] SetColor 0 0 0 + +# It is convenient to create an initial view of the data. The FocalPoint +# and Position form a vector direction. Later on (ResetCamera() method) +# this vector is used to position the camera to look at the data in +# this direction. +vtkCamera aCamera + aCamera SetViewUp 0 0 -1 + aCamera SetPosition 0 1 0 + aCamera SetFocalPoint 0 0 0 + aCamera ComputeViewPlaneNormal + +# Actors are added to the renderer. An initial camera view is created. +# The Dolly() method moves the camera towards the FocalPoint, +# thereby enlarging the image. +aRenderer AddActor outline +aRenderer AddActor skin +aRenderer SetActiveCamera aCamera +aRenderer ResetCamera +aCamera Dolly 1.5 + +# Set a background color for the renderer and set the size of the +# render window (expressed in pixels). +aRenderer SetBackground 1 1 1 +renWin SetSize 640 480 + +# Note that when camera movement occurs (as it does in the Dolly() +# method), the clipping planes often need adjusting. Clipping planes +# consist of two planes: near and far along the view direction. The +# near plane clips out objects in front of the plane the far plane +# clips out objects behind the plane. This way only what is drawn +# between the planes is actually rendered. +aRenderer ResetCameraClippingRange + +# Set up a callback (using command/observer) to bring up the Tcl +# command GUI when the keypress-u (UserEvent) key is pressed. +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Interact with data. The Tcl/Tk event loop is started automatically. +iren Initialize +wm withdraw . + diff --git a/Examples/Medical/Tcl/Medical2.tcl b/Examples/Medical/Tcl/Medical2.tcl new file mode 100644 index 0000000..9651511 --- /dev/null +++ b/Examples/Medical/Tcl/Medical2.tcl @@ -0,0 +1,124 @@ +package require vtk +package require vtkinteraction + +# +# This example reads a volume dataset, extracts two isosurfaces that +# represent the skin and bone, and then displays them. +# + +# Create the renderer, the render window, and the interactor. The renderer +# draws into the render window, the interactor enables mouse- and +# keyboard-based interaction with the scene. +# +vtkRenderer aRenderer +vtkRenderWindow renWin + renWin AddRenderer aRenderer +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# The following reader is used to read a series of 2D slices (images) +# that compose the volume. The slice dimensions are set, and the +# pixel spacing. The data Endianness must also be specified. The reader +# usese the FilePrefix in combination with the slice number to construct +# filenames using the format FilePrefix.%d. (In this case the FilePrefix +# is the root name of the file: quarter.) +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + +# An isosurface, or contour value of 500 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +vtkContourFilter skinExtractor + skinExtractor SetInputConnection [v16 GetOutputPort] + skinExtractor SetValue 0 500 +vtkPolyDataNormals skinNormals + skinNormals SetInputConnection [skinExtractor GetOutputPort] + skinNormals SetFeatureAngle 60.0 +vtkStripper skinStripper + skinStripper SetInputConnection [skinNormals GetOutputPort] +vtkPolyDataMapper skinMapper + skinMapper SetInputConnection [skinStripper GetOutputPort] + skinMapper ScalarVisibilityOff +vtkActor skin + skin SetMapper skinMapper + [skin GetProperty] SetDiffuseColor 1 .49 .25 + [skin GetProperty] SetSpecular .3 + [skin GetProperty] SetSpecularPower 20 + +# An isosurface, or contour value of 1150 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +vtkContourFilter boneExtractor + boneExtractor SetInputConnection [v16 GetOutputPort] + boneExtractor SetValue 0 1150 +vtkPolyDataNormals boneNormals + boneNormals SetInputConnection [boneExtractor GetOutputPort] + boneNormals SetFeatureAngle 60.0 +vtkStripper boneStripper + boneStripper SetInputConnection [boneNormals GetOutputPort] +vtkPolyDataMapper boneMapper + boneMapper SetInputConnection [boneStripper GetOutputPort] + boneMapper ScalarVisibilityOff +vtkActor bone + bone SetMapper boneMapper + [bone GetProperty] SetDiffuseColor 1 1 .9412 + +# An outline provides context around the data. +# +vtkOutlineFilter outlineData + outlineData SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outlineData GetOutputPort] +vtkActor outline + outline SetMapper mapOutline + [outline GetProperty] SetColor 0 0 0 + +# It is convenient to create an initial view of the data. The FocalPoint +# and Position form a vector direction. Later on (ResetCamera() method) +# this vector is used to position the camera to look at the data in +# this direction. +vtkCamera aCamera + aCamera SetViewUp 0 0 -1 + aCamera SetPosition 0 1 0 + aCamera SetFocalPoint 0 0 0 + aCamera ComputeViewPlaneNormal + +# Actors are added to the renderer. An initial camera view is created. +# The Dolly() method moves the camera towards the FocalPoint, +# thereby enlarging the image. +aRenderer AddActor outline +aRenderer AddActor skin +aRenderer AddActor bone +aRenderer SetActiveCamera aCamera +aRenderer ResetCamera +aCamera Dolly 1.5 + +# Set a background color for the renderer and set the size of the +# render window (expressed in pixels). +aRenderer SetBackground 1 1 1 +renWin SetSize 640 480 + +# Note that when camera movement occurs (as it does in the Dolly() +# method), the clipping planes often need adjusting. Clipping planes +# consist of two planes: near and far along the view direction. The +# near plane clips out objects in front of the plane the far plane +# clips out objects behind the plane. This way only what is drawn +# between the planes is actually rendered. +aRenderer ResetCameraClippingRange + +# Set up a callback (using command/observer) to bring up the Tcl +# command GUI when the keypress-u (UserEvent) key is pressed. +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Interact with data. The Tcl/Tk event loop is started automatically. +iren Initialize +wm withdraw . + diff --git a/Examples/Medical/Tcl/Medical3.tcl b/Examples/Medical/Tcl/Medical3.tcl new file mode 100644 index 0000000..af561c4 --- /dev/null +++ b/Examples/Medical/Tcl/Medical3.tcl @@ -0,0 +1,196 @@ +package require vtk +package require vtkinteraction + +# +# This example reads a volume dataset, extracts two isosurfaces that +# represent the skin and bone, creates three orthogonal planes (saggital, +# axial, coronal), and displays them. +# + +# Create the renderer, the render window, and the interactor. The renderer +# draws into the render window, the interactor enables mouse- and +# keyboard-based interaction with the scene. +# +vtkRenderer aRenderer +vtkRenderWindow renWin + renWin AddRenderer aRenderer +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# The following reader is used to read a series of 2D slices (images) +# that compose the volume. The slice dimensions are set, and the +# pixel spacing. The data Endianness must also be specified. The reader +# usese the FilePrefix in combination with the slice number to construct +# filenames using the format FilePrefix.%d. (In this case the FilePrefix +# is the root name of the file: quarter.) +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + +# An isosurface, or contour value of 500 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +vtkContourFilter skinExtractor + skinExtractor SetInputConnection [v16 GetOutputPort] + skinExtractor SetValue 0 500 +vtkPolyDataNormals skinNormals + skinNormals SetInputConnection [skinExtractor GetOutputPort] + skinNormals SetFeatureAngle 60.0 +vtkStripper skinStripper + skinStripper SetInputConnection [skinNormals GetOutputPort] +vtkPolyDataMapper skinMapper + skinMapper SetInputConnection [skinStripper GetOutputPort] + skinMapper ScalarVisibilityOff +vtkActor skin + skin SetMapper skinMapper + [skin GetProperty] SetDiffuseColor 1 .49 .25 + [skin GetProperty] SetSpecular .3 + [skin GetProperty] SetSpecularPower 20 + +# An isosurface, or contour value of 1150 is known to correspond to the +# skin of the patient. Once generated, a vtkPolyDataNormals filter is +# is used to create normals for smooth surface shading during rendering. +# The triangle stripper is used to create triangle strips from the +# isosurface these render much faster on may systems. +vtkContourFilter boneExtractor + boneExtractor SetInputConnection [v16 GetOutputPort] + boneExtractor SetValue 0 1150 +vtkPolyDataNormals boneNormals + boneNormals SetInputConnection [boneExtractor GetOutputPort] + boneNormals SetFeatureAngle 60.0 +vtkStripper boneStripper + boneStripper SetInputConnection [boneNormals GetOutputPort] +vtkPolyDataMapper boneMapper + boneMapper SetInputConnection [boneStripper GetOutputPort] + boneMapper ScalarVisibilityOff +vtkActor bone + bone SetMapper boneMapper + [bone GetProperty] SetDiffuseColor 1 1 .9412 + +# An outline provides context around the data. +# +vtkOutlineFilter outlineData + outlineData SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outlineData GetOutputPort] +vtkActor outline + outline SetMapper mapOutline + [outline GetProperty] SetColor 0 0 0 + +# Now we are creating three orthogonal planes passing through the +# volume. Each plane uses a different texture map and therefore has +# diferent coloration. + +# Start by creatin a black/white lookup table. +vtkLookupTable bwLut + bwLut SetTableRange 0 2000 + bwLut SetSaturationRange 0 0 + bwLut SetHueRange 0 0 + bwLut SetValueRange 0 1 + +# Now create a lookup table that consists of the full hue circle (from HSV). +vtkLookupTable hueLut + hueLut SetTableRange 0 2000 + hueLut SetHueRange 0 1 + hueLut SetSaturationRange 1 1 + hueLut SetValueRange 1 1 + +# Finally, create a lookup table with a single hue but having a range +# in the saturation of the hue. +vtkLookupTable satLut + satLut SetTableRange 0 2000 + satLut SetHueRange .6 .6 + satLut SetSaturationRange 0 1 + satLut SetValueRange 1 1 + +# Create the first of the three planes. The filter vtkImageMapToColors +# maps the data through the corresponding lookup table created above. +# The vtkImageActor is a type of vtkProp and conveniently displays an image +# on a single quadrilateral plane. It does this using texture mapping and +# as a result is quite fast. (Note: the input image has to be unsigned +# char values, which the vtkImageMapToColors produces.) Note also that +# by specifying the DisplayExtent, the pipeline requests data of this +# extent and the vtkImageMapToColors only processes a slice of data. +vtkImageMapToColors saggitalColors + saggitalColors SetInputConnection [v16 GetOutputPort] + saggitalColors SetLookupTable bwLut +vtkImageActor saggital + saggital SetInput [saggitalColors GetOutput] + saggital SetDisplayExtent 32 32 0 63 0 92 + +# Create the second (axial) plane of the three planes. We use the same +# approach as before except that the extent differs. +vtkImageMapToColors axialColors + axialColors SetInputConnection [v16 GetOutputPort] + axialColors SetLookupTable hueLut +vtkImageActor axial + axial SetInput [axialColors GetOutput] + axial SetDisplayExtent 0 63 0 63 46 46 + +# Create the third (coronal) plane of the three planes. We use the same +# approach as before except that the extent differs. +vtkImageMapToColors coronalColors + coronalColors SetInputConnection [v16 GetOutputPort] + coronalColors SetLookupTable satLut +vtkImageActor coronal + coronal SetInput [coronalColors GetOutput] + coronal SetDisplayExtent 0 63 32 32 0 92 + +# It is convenient to create an initial view of the data. The FocalPoint +# and Position form a vector direction. Later on (ResetCamera() method) +# this vector is used to position the camera to look at the data in +# this direction. +vtkCamera aCamera + aCamera SetViewUp 0 0 -1 + aCamera SetPosition 0 1 0 + aCamera SetFocalPoint 0 0 0 + aCamera ComputeViewPlaneNormal + +# Actors are added to the renderer. +aRenderer AddActor outline +aRenderer AddActor saggital +aRenderer AddActor axial +aRenderer AddActor coronal +aRenderer AddActor axial +aRenderer AddActor coronal +aRenderer AddActor skin +aRenderer AddActor bone + +# Turn off bone for this example. +bone VisibilityOff + +# Set skin to semi-transparent. +[skin GetProperty] SetOpacity 0.5 + +# An initial camera view is created. The Dolly() method moves +# the camera towards the FocalPoint, thereby enlarging the image. +aRenderer SetActiveCamera aCamera +aRenderer ResetCamera +aCamera Dolly 1.5 + +# Set a background color for the renderer and set the size of the +# render window (expressed in pixels). +aRenderer SetBackground 1 1 1 +renWin SetSize 640 480 + +# Note that when camera movement occurs (as it does in the Dolly() +# method), the clipping planes often need adjusting. Clipping planes +# consist of two planes: near and far along the view direction. The +# near plane clips out objects in front of the plane the far plane +# clips out objects behind the plane. This way only what is drawn +# between the planes is actually rendered. +aRenderer ResetCameraClippingRange + +# Set up a callback (using command/observer) to bring up the Tcl +# command GUI when the keypress-u (UserEvent) key is pressed. +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Interact with data. The Tcl/Tk event loop is started automatically. +iren Initialize +wm withdraw . + diff --git a/Examples/Modelling/Cxx/CMakeLists.txt b/Examples/Modelling/Cxx/CMakeLists.txt new file mode 100644 index 0000000..30aca82 --- /dev/null +++ b/Examples/Modelling/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (finance) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(finance finance.cxx) +TARGET_LINK_LIBRARIES(finance vtkRendering) diff --git a/Examples/Modelling/Cxx/finance.cxx b/Examples/Modelling/Cxx/finance.cxx new file mode 100644 index 0000000..5b48205 --- /dev/null +++ b/Examples/Modelling/Cxx/finance.cxx @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: finance.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkAxes.h" +#include "vtkContourFilter.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkGaussianSplatter.h" +#include "vtkImageData.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkTubeFilter.h" +#include "vtkUnstructuredGrid.h" +#include "vtkTestUtilities.h" + +static vtkDataSet *ReadFinancialData(const char *fname, const char *x, const char *y, const char *z, const char *s); +static int ParseFile(FILE *file, const char *tag, float *data); + +int main( int argc, char *argv[] ) +{ + double bounds[6]; + + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/financial.txt"); + // read data + vtkDataSet *dataSet = ReadFinancialData(fname, "MONTHLY_PAYMENT","INTEREST_RATE", + "LOAN_AMOUNT","TIME_LATE"); + delete[] fname; + if ( ! dataSet ) exit(0); + + // construct pipeline for original population + vtkGaussianSplatter *popSplatter = vtkGaussianSplatter::New(); + popSplatter->SetInput(dataSet); + popSplatter->SetSampleDimensions(50,50,50); + popSplatter->SetRadius(0.05); + popSplatter->ScalarWarpingOff(); + vtkContourFilter *popSurface = vtkContourFilter::New(); + popSurface->SetInputConnection(popSplatter->GetOutputPort()); + popSurface->SetValue(0,0.01); + vtkPolyDataMapper *popMapper = vtkPolyDataMapper::New(); + popMapper->SetInputConnection(popSurface->GetOutputPort()); + popMapper->ScalarVisibilityOff(); + vtkActor *popActor = vtkActor::New(); + popActor->SetMapper(popMapper); + popActor->GetProperty()->SetOpacity(0.3); + popActor->GetProperty()->SetColor(.9,.9,.9); + + // construct pipeline for delinquent population + vtkGaussianSplatter *lateSplatter = vtkGaussianSplatter::New(); + lateSplatter->SetInput(dataSet); + lateSplatter->SetSampleDimensions(50,50,50); + lateSplatter->SetRadius(0.05); + lateSplatter->SetScaleFactor(0.005); + vtkContourFilter *lateSurface = vtkContourFilter::New(); + lateSurface->SetInputConnection(lateSplatter->GetOutputPort()); + lateSurface->SetValue(0,0.01); + vtkPolyDataMapper *lateMapper = vtkPolyDataMapper::New(); + lateMapper->SetInputConnection(lateSurface->GetOutputPort()); + lateMapper->ScalarVisibilityOff(); + vtkActor *lateActor = vtkActor::New(); + lateActor->SetMapper(lateMapper); + lateActor->GetProperty()->SetColor(1.0,0.0,0.0); + + // create axes + popSplatter->Update(); + popSplatter->GetOutput()->GetBounds(bounds); + vtkAxes *axes = vtkAxes::New(); + axes->SetOrigin(bounds[0], bounds[2], bounds[4]); + axes->SetScaleFactor(popSplatter->GetOutput()->GetLength()/5); + vtkTubeFilter *axesTubes = vtkTubeFilter::New(); + axesTubes->SetInputConnection(axes->GetOutputPort()); + axesTubes->SetRadius(axes->GetScaleFactor()/25.0); + axesTubes->SetNumberOfSides(6); + vtkPolyDataMapper *axesMapper = vtkPolyDataMapper::New(); + axesMapper->SetInputConnection(axesTubes->GetOutputPort()); + vtkActor *axesActor = vtkActor::New(); + axesActor->SetMapper(axesMapper); + + // graphics stuff + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // read data //set up renderer + renderer->AddActor(lateActor); + renderer->AddActor(axesActor); + renderer->AddActor(popActor); + renderer->SetBackground(1,1,1); + renWin->SetSize(300,300); + + // interact with data + iren->Initialize(); + + renWin->Render(); + iren->Start(); + + // Clean up + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + popSplatter->Delete(); + popSurface->Delete(); + popMapper->Delete(); + popActor->Delete(); + lateSplatter->Delete(); + lateSurface->Delete(); + lateMapper->Delete(); + lateActor->Delete(); + axes->Delete(); + axesTubes->Delete(); + axesMapper->Delete(); + axesActor->Delete(); + dataSet->Delete(); + + return 0; +} + +static vtkDataSet *ReadFinancialData(const char* filename, const char *x, const char *y, const char *z, const char *s) +{ + float xyz[3]; + FILE *file; + int i, npts; + char tag[80]; + + if ( (file = fopen(filename,"r")) == 0 ) + { + cerr << "ERROR: Can't read file: " << filename << "\n"; + return NULL; + } + + fscanf (file, "%s %d", tag, &npts); // read number of points + + vtkUnstructuredGrid *dataSet = vtkUnstructuredGrid::New(); + float *xV = new float[npts]; + float *yV = new float[npts]; + float *zV = new float[npts]; + float *sV = new float[npts]; + + if ( ! ParseFile(file, x, xV) || ! ParseFile(file, y, yV) || + ! ParseFile(file, z, zV) || ! ParseFile(file, s, sV) ) + { + cerr << "Couldn't read data!\n"; + delete [] xV; + delete [] yV; + delete [] zV; + delete [] sV; + dataSet->Delete(); + return NULL; + } + + vtkPoints *newPts = vtkPoints::New(); + vtkFloatArray *newScalars = vtkFloatArray::New(); + + for (i=0; iInsertPoint(i, xyz); + newScalars->InsertValue(i, sV[i]); + } + + dataSet->SetPoints(newPts); + dataSet->GetPointData()->SetScalars(newScalars); + + newPts->Delete(); //reference counted - it's okay + newScalars->Delete(); + + return dataSet; +} + +static int ParseFile(FILE *file, const char *label, float *data) +{ + char tag[80]; + int i, npts, readData=0; + float min=VTK_LARGE_FLOAT; + float max=(-VTK_LARGE_FLOAT); + + if ( file == NULL || label == NULL ) return 0; + + rewind(file); + + fscanf(file, "%s %d", tag, &npts); + + while ( !readData && fscanf(file, "%s", tag) == 1 ) + { + if ( ! strcmp(tag,label) ) + { + readData = 1; + for (i=0; i min ) max = data[i]; + } + // normalize data + for (i=0; i => path to the data (VTKData); the data should be in /Data/ + +#include "vtkActor.h" +#include "vtkCellDataToPointData.h" +#include "vtkContourFilter.h" +#include "vtkDebugLeaks.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkHierarchicalDataSetGeometryFilter.h" +#include "vtkOutlineCornerFilter.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkShrinkPolyData.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridOutlineFilter.h" +#include "vtkTestUtilities.h" +#include "vtkXMLStructuredGridReader.h" + +int main(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *ren = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // We will read three files and collect them together in one + // multi-block dataset. I broke the combustor dataset into + // three pieces and wrote them out separately. + int i; + vtkXMLStructuredGridReader* reader = vtkXMLStructuredGridReader::New(); + + // vtkMultiBlockDataSet respresents multi-block datasets. See + // the class documentation for more information. + vtkHierarchicalDataSet* mb = vtkHierarchicalDataSet::New(); + + for (i=0; i<3; i++) + { + // Here we load the three separate files (each containing + // a structured grid dataset) + ostrstream fname; + fname << "Data/multicomb_" << i << ".vts" << ends; + char* fstr = fname.str(); + char* cfname = + vtkTestUtilities::ExpandDataFileName(argc, argv, fstr); + reader->SetFileName(cfname); + // We have to update since we are working without a VTK pipeline. + // This will read the file and the output of the reader will be + // a valid structured grid data. + reader->Update(); + delete[] fstr; + delete[] cfname; + + // We create a copy to avoid adding the same data three + // times (the output object of the reader does not change + // when the filename changes) + vtkStructuredGrid* sg = vtkStructuredGrid::New(); + sg->ShallowCopy(reader->GetOutput()); + + // Add the structured grid to the multi-block dataset + mb->SetDataSet(0, i, sg); + sg->Delete(); + } + reader->Delete(); + + // Multi-block can be processed with regular VTK filters in two ways: + // 1. Pass through a multi-block aware consumer. Since a multi-block + // aware mapper is not yet available, vtkHierarchicalDataSetGeometryFilter + // can be used + // 2. Assign the composite executive (vtkCompositeDataPipeline) to + // all "simple" (that work only on simple, non-composite datasets) filters + + // outline + vtkStructuredGridOutlineFilter* of = vtkStructuredGridOutlineFilter::New(); + of->SetInput(mb); + + // geometry filter + // This filter is multi-block aware and will request blocks from the + // input. These blocks will be processed by simple processes as if they + // are the whole dataset + vtkHierarchicalDataSetGeometryFilter* geom1 = + vtkHierarchicalDataSetGeometryFilter::New(); + geom1->SetInputConnection(0, of->GetOutputPort(0)); + + // Rendering objects + vtkPolyDataMapper* geoMapper = vtkPolyDataMapper::New(); + geoMapper->SetInputConnection(0, geom1->GetOutputPort(0)); + + vtkActor* geoActor = vtkActor::New(); + geoActor->SetMapper(geoMapper); + geoActor->GetProperty()->SetColor(0, 0, 0); + ren->AddActor(geoActor); + + // cell 2 point and contour + vtkCellDataToPointData* c2p = vtkCellDataToPointData::New(); + c2p->SetInput(mb); + + vtkContourFilter* contour = vtkContourFilter::New(); + contour->SetInputConnection(0, c2p->GetOutputPort(0)); + contour->SetValue(0, 0.45); + + // geometry filter + vtkHierarchicalDataSetGeometryFilter* geom2 = + vtkHierarchicalDataSetGeometryFilter::New(); + geom2->SetInputConnection(0, contour->GetOutputPort(0)); + + // Rendering objects + vtkPolyDataMapper* contMapper = vtkPolyDataMapper::New(); + contMapper->SetInputConnection(0, geom2->GetOutputPort(0)); + + vtkActor* contActor = vtkActor::New(); + contActor->SetMapper(contMapper); + contActor->GetProperty()->SetColor(1, 0, 0); + ren->AddActor(contActor); + + ren->SetBackground(1,1,1); + renWin->SetSize(300,300); + iren->Start(); + + // Cleanup + of->Delete(); + geom1->Delete(); + geoMapper->Delete(); + geoActor->Delete(); + c2p->Delete(); + contour->Delete(); + geom2->Delete(); + contMapper->Delete(); + contActor->Delete(); + ren->Delete(); + renWin->Delete(); + iren->Delete(); + mb->Delete(); + + return 0; +} diff --git a/Examples/ParallelProcessing/CMakeLists.txt b/Examples/ParallelProcessing/CMakeLists.txt new file mode 100644 index 0000000..546cfff --- /dev/null +++ b/Examples/ParallelProcessing/CMakeLists.txt @@ -0,0 +1,2 @@ +SUBDIRS(Generic) + diff --git a/Examples/ParallelProcessing/Generic/CMakeLists.txt b/Examples/ParallelProcessing/Generic/CMakeLists.txt new file mode 100644 index 0000000..1336591 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/CMakeLists.txt @@ -0,0 +1,2 @@ +SUBDIRS(Cxx) + diff --git a/Examples/ParallelProcessing/Generic/Cxx/CMakeLists.txt b/Examples/ParallelProcessing/Generic/Cxx/CMakeLists.txt new file mode 100644 index 0000000..4a48d80 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/CMakeLists.txt @@ -0,0 +1,20 @@ +INCLUDE_REGULAR_EXPRESSION("^(lex|vtk|png|j|Task|Pipe).*$") + +IF (VTK_USE_MPI) + IF (VTK_USE_RENDERING) + ADD_EXECUTABLE(ParallelIso ParallelIso.cxx) + TARGET_LINK_LIBRARIES(ParallelIso vtkParallel vtkHybrid) + IF(APPLE) + TARGET_LINK_LIBRARIES(ParallelIso "-framework Carbon") + ENDIF(APPLE) + ENDIF (VTK_USE_RENDERING) + + SET(TaskPara_SRCS TaskParallelism.cxx task1.cxx task2.cxx) + + ADD_EXECUTABLE(TaskParallelism ${TaskPara_SRCS}) + + TARGET_LINK_LIBRARIES (TaskParallelism vtkParallel) + IF(APPLE) + TARGET_LINK_LIBRARIES(TaskParallelism "-framework Carbon") + ENDIF(APPLE) +ENDIF (VTK_USE_MPI) diff --git a/Examples/ParallelProcessing/Generic/Cxx/ParallelIso.cxx b/Examples/ParallelProcessing/Generic/Cxx/ParallelIso.cxx new file mode 100644 index 0000000..2ea312d --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/ParallelIso.cxx @@ -0,0 +1,272 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ParallelIso.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates the use of data parallelism in VTK. The +// pipeline ( vtkImageReader -> vtkContourFilter -> vtkElevationFilter ) +// is created in parallel and each process is assigned 1 piece to process. +// All satellite processes send the result to the first process which +// collects and renders them. + +#include "vtkActor.h" +#include "vtkAppendPolyData.h" +#include "vtkCamera.h" +#include "vtkConeSource.h" +#include "vtkContourFilter.h" +#include "vtkDataSet.h" +#include "vtkElevationFilter.h" +#include "vtkImageReader.h" +#include "vtkMath.h" +#include "vtkMPIController.h" +#include "vtkParallelFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkWindowToImageFilter.h" +#include "vtkImageData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkInformation.h" + +#include "vtkDebugLeaks.h" + +#include + +static const float ISO_START=4250.0; +static const float ISO_STEP=-1250.0; +static const int ISO_NUM=3; +// Just pick a tag which is available +static const int ISO_VALUE_RMI_TAG=300; +static const int ISO_OUTPUT_TAG=301; + +struct ParallelIsoArgs_tmp +{ + int* retVal; + int argc; + char** argv; +}; + +struct ParallelIsoRMIArgs_tmp +{ + vtkContourFilter* ContourFilter; + vtkMultiProcessController* Controller; + vtkElevationFilter* Elevation; +}; + +// call back to set the iso surface value. +void SetIsoValueRMI(void *localArg, void* vtkNotUsed(remoteArg), + int vtkNotUsed(remoteArgLen), int vtkNotUsed(id)) +{ + ParallelIsoRMIArgs_tmp* args = (ParallelIsoRMIArgs_tmp*)localArg; + + float val; + + vtkContourFilter *iso = args->ContourFilter; + val = iso->GetValue(0); + iso->SetValue(0, val + ISO_STEP); + args->Elevation->Update(); + + vtkMultiProcessController* contrl = args->Controller; + contrl->Send(args->Elevation->GetOutput(), 0, ISO_OUTPUT_TAG); +} + + +// This will be called by all processes +void MyMain( vtkMultiProcessController *controller, void *arg ) +{ + vtkImageReader *reader; + vtkContourFilter *iso; + vtkElevationFilter *elev; + int myid, numProcs; + float val; + ParallelIsoArgs_tmp* args = reinterpret_cast(arg); + + // Obtain the id of the running process and the total + // number of processes + myid = controller->GetLocalProcessId(); + numProcs = controller->GetNumberOfProcesses(); + + // Create the reader, the data file name might have + // to be changed depending on where the data files are. + char* fname = vtkTestUtilities::ExpandDataFileName(args->argc, args->argv, + "Data/headsq/quarter"); + reader = vtkImageReader::New(); + reader->SetDataByteOrderToLittleEndian(); + reader->SetDataExtent(0, 63, 0, 63, 1, 93); + reader->SetFilePrefix(fname); + reader->SetDataSpacing(3.2, 3.2, 1.5); + delete[] fname; + + // Iso-surface. + iso = vtkContourFilter::New(); + iso->SetInputConnection(reader->GetOutputPort()); + iso->SetValue(0, ISO_START); + iso->ComputeScalarsOff(); + iso->ComputeGradientsOff(); + + // Compute a different color for each process. + elev = vtkElevationFilter::New(); + elev->SetInputConnection(iso->GetOutputPort()); + val = (myid+1) / static_cast(numProcs); + elev->SetScalarRange(val, val+0.001); + + // Tell the pipeline which piece we want to update. + vtkStreamingDemandDrivenPipeline* exec = + vtkStreamingDemandDrivenPipeline::SafeDownCast(elev->GetExecutive()); + exec->SetUpdateNumberOfPieces(exec->GetOutputInformation(0), numProcs); + exec->SetUpdatePiece(exec->GetOutputInformation(0), myid); + + if (myid != 0) + { + // If I am not the root process + ParallelIsoRMIArgs_tmp args; + args.ContourFilter = iso; + args.Controller = controller; + args.Elevation = elev; + + // Last, set up a RMI call back to change the iso surface value. + // This is done so that the root process can let this process + // know that it wants the contour value to change. + controller->AddRMI(SetIsoValueRMI, (void *)&args, ISO_VALUE_RMI_TAG); + controller->ProcessRMIs(); + } + else + { + // Create the rendering part of the pipeline + vtkAppendPolyData *app = vtkAppendPolyData::New(); + vtkRenderer *ren = vtkRenderer::New(); + vtkRenderWindow *renWindow = vtkRenderWindow::New(); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + vtkActor *actor = vtkActor::New(); + vtkCamera *cam = vtkCamera::New(); + renWindow->AddRenderer(ren); + iren->SetRenderWindow(renWindow); + ren->SetBackground(0.9, 0.9, 0.9); + renWindow->SetSize( 400, 400); + mapper->SetInputConnection(app->GetOutputPort()); + actor->SetMapper(mapper); + ren->AddActor(actor); + cam->SetFocalPoint(100, 100, 65); + cam->SetPosition(100, 450, 65); + cam->SetViewUp(0, 0, -1); + cam->SetViewAngle(30); + cam->SetClippingRange(177.0, 536.0); + ren->SetActiveCamera(cam); + + // loop through some iso surface values. + for (int j = 0; j < ISO_NUM; ++j) + { + // set the local value + iso->SetValue(0, iso->GetValue(0) + ISO_STEP); + elev->Update(); + + for (int i = 1; i < numProcs; ++i) + { + // trigger the RMI to change the iso surface value. + controller->TriggerRMI(i, ISO_VALUE_RMI_TAG); + } + for (int i = 1; i < numProcs; ++i) + { + vtkPolyData* pd = vtkPolyData::New(); + controller->Receive(pd, i, ISO_OUTPUT_TAG); + if (j == ISO_NUM - 1) + { + app->AddInput(pd); + } + pd->Delete(); + } + } + + // Tell the other processors to stop processing RMIs. + for (int i = 1; i < numProcs; ++i) + { + controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG); + } + + vtkPolyData* outputCopy = vtkPolyData::New(); + outputCopy->ShallowCopy(elev->GetOutput()); + app->AddInput(outputCopy); + outputCopy->Delete(); + app->Update(); + renWindow->Render(); + + *(args->retVal) = + vtkRegressionTester::Test(args->argc, args->argv, renWindow, 10); + + if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + app->Delete(); + ren->Delete(); + renWindow->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + cam->Delete(); + } + + // clean up objects in all processes. + reader->Delete(); + iso->Delete(); + elev->Delete(); +} + + +int main( int argc, char* argv[] ) +{ + // This is here to avoid false leak messages from vtkDebugLeaks when + // using mpich. It appears that the root process which spawns all the + // main processes waits in MPI_Init() and calls exit() when + // the others are done, causing apparent memory leaks for any objects + // created before MPI_Init(). + MPI_Init(&argc, &argv); + + // Note that this will create a vtkMPIController if MPI + // is configured, vtkThreadedController otherwise. + vtkMPIController* controller = vtkMPIController::New(); + + controller->Initialize(&argc, &argv, 1); + + vtkParallelFactory* pf = vtkParallelFactory::New(); + vtkObjectFactory::RegisterFactory(pf); + pf->Delete(); + + // Added for regression test. + // ---------------------------------------------- + int retVal = 1; + ParallelIsoArgs_tmp args; + args.retVal = &retVal; + args.argc = argc; + args.argv = argv; + // ---------------------------------------------- + + controller->SetSingleMethod(MyMain, &args); + controller->SingleMethodExecute(); + + controller->Finalize(); + controller->Delete(); + + return !retVal; +} + + + + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/PipelineParallelism.cxx b/Examples/ParallelProcessing/Generic/Cxx/PipelineParallelism.cxx new file mode 100644 index 0000000..f87b1d4 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/PipelineParallelism.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: PipelineParallelism.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to write a pipeline parallel application +// with VTK. It creates two parts of a pipeline on a two different +// processors and connects them with ports. The two processes can then +// process the data in a pipeline mode, i.e: +// 1. Consumer asks the producer to start producing data, +// 2. Consumer receives data and starts processing it, +// 3. Producer starts producing new data, +// 4. Goto 2 unless done. +// The pipeline used in this example is as follows: +// rtSource -> OutputPort --- InputPort -> contour -> Render +// process 0 process 1 +// See pipe1.cxx and pipe2.cxx for the pipelines. + +#include "PipelineParallelism.h" + +int main( int argc, char* argv[] ) +{ + + // Note that this will create a vtkMPIController if MPI + // is configured, vtkThreadedController otherwise. + vtkMultiProcessController* controller = vtkMultiProcessController::New(); + controller->Initialize(&argc, &argv); + + // When using MPI, the number of processes is determined + // by the external program which launches this application. + // However, when using threads, we need to set it ourselves. + if (controller->IsA("vtkThreadedController")) + { + // Set the number of processes to 2 for this example. + controller->SetNumberOfProcesses(2); + } + int numProcs = controller->GetNumberOfProcesses(); + + if (numProcs != 2) + { + cerr << "This example requires two processes." << endl; + controller->Finalize(); + controller->Delete(); + return 1; + } + + // Assign the functions and execute them + controller->SetMultipleMethod(0, pipe1, 0); + controller->SetMultipleMethod(1, pipe2, 0); + controller->MultipleMethodExecute(); + + // Clean-up and exit + controller->Finalize(); + controller->Delete(); + + return 0; +} + + + + + + + + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/PipelineParallelism.h b/Examples/ParallelProcessing/Generic/Cxx/PipelineParallelism.h new file mode 100644 index 0000000..f39d177 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/PipelineParallelism.h @@ -0,0 +1,18 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: PipelineParallelism.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMultiProcessController.h" + +void pipe1(vtkMultiProcessController* controller, void* arg); +void pipe2(vtkMultiProcessController* controller, void* arg); diff --git a/Examples/ParallelProcessing/Generic/Cxx/TaskParallelism.cxx b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelism.cxx new file mode 100644 index 0000000..7ab54ac --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelism.cxx @@ -0,0 +1,132 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TaskParallelism.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to write a task parallel application +// with VTK. It creates two different pipelines and assigns each to +// one processor. These pipelines are: +// 1. rtSource -> contour -> probe +// \ / +// -> gradient magnitude +// 2. rtSource -> gradient -> shrink -> glyph3D +// See task1.cxx and task2.cxx for the pipelines. + +#include "TaskParallelism.h" +#include "vtkCompositeRenderManager.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" + +// This function sets up properties common to both processes +// and executes the task corresponding to the current process +void process(vtkMultiProcessController* controller, void* vtkNotUsed(arg)) +{ + taskFunction task; + int myId = controller->GetLocalProcessId(); + + // Chose the appropriate task (see task1.cxx and task2.cxx) + if ( myId == 0 ) + { + task = task1; + } + else + { + task = task2; + } + + + // Setup camera + vtkCamera* cam = vtkCamera::New(); + cam->SetPosition( -0.6105, 1.467, -6.879 ); + cam->SetFocalPoint( -0.0617558, 0.127043, 0 ); + cam->SetViewUp( -0.02, 0.98, 0.193 ); + cam->SetClippingRange( 3.36, 11.67); + cam->Dolly(0.8); + + // Create the render objects + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->SetSize( WINDOW_WIDTH, WINDOW_HEIGHT ); + + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // This class allows all processes to composite their images. + // The root process then displays it in it's render window. + vtkCompositeRenderManager* tc = vtkCompositeRenderManager::New(); + tc->SetRenderWindow(renWin); + + // Generate the pipeline see task1.cxx and task2.cxx) + vtkPolyDataMapper* mapper = (*task)(renWin, EXTENT, cam); + + // Only the root process will have an active interactor. All + // the other render windows will be slaved to the root. + tc->StartInteractor(); + + // Clean-up + iren->Delete(); + if (mapper) + { + mapper->Delete(); + } + renWin->Delete(); + cam->Delete(); + +} + + +int main( int argc, char* argv[] ) +{ + + // Note that this will create a vtkMPIController if MPI + // is configured, vtkThreadedController otherwise. + vtkMPIController* controller = vtkMPIController::New(); + controller->Initialize(&argc, &argv); + + // When using MPI, the number of processes is determined + // by the external program which launches this application. + // However, when using threads, we need to set it ourselves. + if (controller->IsA("vtkThreadedController")) + { + // Set the number of processes to 2 for this example. + controller->SetNumberOfProcesses(2); + } + int numProcs = controller->GetNumberOfProcesses(); + + if (numProcs != 2) + { + cerr << "This example requires two processes." << endl; + controller->Finalize(); + controller->Delete(); + return 1; + } + + + // Execute the function named "process" on both processes + controller->SetSingleMethod(process, 0); + controller->SingleMethodExecute(); + + // Clean-up and exit + controller->Finalize(); + controller->Delete(); + + return 0; +} + + + + + + + + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/TaskParallelism.h b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelism.h new file mode 100644 index 0000000..6da64ec --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelism.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TaskParallelism.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __TASKPARA_H +#define __TASKPARA_H + +#include "vtkMPIController.h" +#include "vtkRTAnalyticSource.h" +#include "vtkFieldDataToAttributeDataFilter.h" +#include "vtkAttributeDataToFieldDataFilter.h" +#include "vtkImageShrink3D.h" +#include "vtkGlyph3D.h" +#include "vtkGlyphSource2D.h" +#include "vtkImageGradient.h" +#include "vtkImageGradientMagnitude.h" +#include "vtkImageGaussianSmooth.h" +#include "vtkProbeFilter.h" +#include "vtkDataSetMapper.h" +#include "vtkContourFilter.h" +#include "vtkActor.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkCamera.h" +#include "vtkAssignAttribute.h" + + +typedef vtkPolyDataMapper* (*taskFunction)(vtkRenderWindow* renWin, + double data, vtkCamera* cam); + + +vtkPolyDataMapper* task1(vtkRenderWindow* renWin, double data,vtkCamera* cam); +vtkPolyDataMapper* task2(vtkRenderWindow* renWin, double data,vtkCamera* cam); + + +static const double EXTENT = 20; + +static const int WINDOW_WIDTH = 400; +static const int WINDOW_HEIGHT = 300; + +#endif diff --git a/Examples/ParallelProcessing/Generic/Cxx/TaskParallelismWithPorts.cxx b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelismWithPorts.cxx new file mode 100644 index 0000000..a46b5a1 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelismWithPorts.cxx @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TaskParallelismWithPorts.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to write a task parallel application +// with VTK. It creates two different pipelines and assigns each to +// one processor. These pipelines are: +// 1. rtSource -> contour -> probe .-> append +// \ / port +// -> gradient magnitude / +// 2. rtSource -> gradient -> shrink -> glyph3D -> port +// See task3.cxx and task4.cxx for the pipelines. + +#include "TaskParallelismWithPorts.h" + +// This function sets up properties common to both processes +// and executes the task corresponding to the current process +void process(vtkMultiProcessController* controller, void* vtkNotUsed(arg)) +{ + taskFunction task; + int myId = controller->GetLocalProcessId(); + + // Chose the appropriate task (see task3.cxx and task4.cxx) + if ( myId == 0 ) + { + task = task3; + } + else + { + task = task4; + } + + // Run the tasks (see task3.cxx and task4.cxx) + (*task)(EXTENT); +} + + +int main( int argc, char* argv[] ) +{ + + // Note that this will create a vtkMPIController if MPI + // is configured, vtkThreadedController otherwise. + vtkMultiProcessController* controller = vtkMultiProcessController::New(); + controller->Initialize(&argc, &argv); + + // When using MPI, the number of processes is determined + // by the external program which launches this application. + // However, when using threads, we need to set it ourselves. + if (controller->IsA("vtkThreadedController")) + { + // Set the number of processes to 2 for this example. + controller->SetNumberOfProcesses(2); + } + int numProcs = controller->GetNumberOfProcesses(); + + if (numProcs != 2) + { + cerr << "This example requires two processes." << endl; + controller->Finalize(); + controller->Delete(); + return 1; + } + + + // Execute the function named "process" on both processes + controller->SetSingleMethod(process, 0); + controller->SingleMethodExecute(); + + // Clean-up and exit + controller->Finalize(); + controller->Delete(); + + return 0; +} + + + + + + + + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/TaskParallelismWithPorts.h b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelismWithPorts.h new file mode 100644 index 0000000..911e3f3 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/TaskParallelismWithPorts.h @@ -0,0 +1,49 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TaskParallelismWithPorts.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __TASKPARA_H +#define __TASKPARA_H + +#include "vtkMultiProcessController.h" +#include "vtkRTAnalyticSource.h" +#include "vtkFieldDataToAttributeDataFilter.h" +#include "vtkAttributeDataToFieldDataFilter.h" +#include "vtkImageShrink3D.h" +#include "vtkGlyph3D.h" +#include "vtkGlyphSource2D.h" +#include "vtkImageGradient.h" +#include "vtkImageGradientMagnitude.h" +#include "vtkImageGaussianSmooth.h" +#include "vtkProbeFilter.h" +#include "vtkDataSetMapper.h" +#include "vtkContourFilter.h" +#include "vtkActor.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkAssignAttribute.h" + + +typedef void (*taskFunction)(double data); + + +void task3(double data); +void task4(double data); + + +static const double EXTENT = 20; + +static const int WINDOW_WIDTH = 400; +static const int WINDOW_HEIGHT = 300; + +#endif diff --git a/Examples/ParallelProcessing/Generic/Cxx/pipe1.cxx b/Examples/ParallelProcessing/Generic/Cxx/pipe1.cxx new file mode 100644 index 0000000..3927994 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/pipe1.cxx @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: pipe1.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkCallbackCommand.h" +#include "vtkImageData.h" +#include "vtkOutputPort.h" +#include "vtkRTAnalyticSource.h" + +#include "PipelineParallelism.h" + +static float XFreq = 60; + +// Increments XFreq of the synthetic source +static void IncrementXFreq(vtkObject *vtkNotUsed( caller ), + unsigned long vtkNotUsed(eventId), + void *sr, void *) +{ + vtkRTAnalyticSource* source1 = reinterpret_cast(sr); + XFreq = XFreq + 10; + source1->SetXFreq(XFreq); +} + + +// Pipe 1 for PipelineParallelism. +// See PipelineParallelism.cxx for more information. +void pipe1(vtkMultiProcessController* vtkNotUsed(controller), + void* vtkNotUsed(arg)) +{ + double extent = 20; + int iextent = static_cast(extent); + + // Synthetic image source. + vtkRTAnalyticSource* source1 = vtkRTAnalyticSource::New(); + source1->SetWholeExtent (-1*iextent, iextent, -1*iextent, iextent, + -1*iextent, iextent ); + source1->SetCenter(0, 0, 0); + source1->SetStandardDeviation( 0.5 ); + source1->SetMaximum( 255.0 ); + source1->SetXFreq( XFreq ); + source1->SetXMag( 10 ); + source1->SetYFreq( 30 ); + source1->SetYMag( 18 ); + source1->SetZFreq( 40 ); + source1->SetZMag( 5 ); + source1->GetOutput()->SetSpacing(2.0/extent,2.0/extent,2.0/extent); + + // Output port + vtkOutputPort* op = vtkOutputPort::New(); + op->SetInputConnection(source1->GetOutputPort()); + op->SetTag(11); + + // Called every time data is requested from the output port + vtkCallbackCommand *cbc = vtkCallbackCommand::New(); + cbc->SetCallback(IncrementXFreq); + cbc->SetClientData((void *)source1); + op->AddObserver(vtkCommand::EndEvent,cbc); + cbc->Delete(); + + // Process requests + op->WaitForUpdate(); + + // Cleanup + op->Delete(); + source1->Delete(); + +} + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/pipe2.cxx b/Examples/ParallelProcessing/Generic/Cxx/pipe2.cxx new file mode 100644 index 0000000..852ae41 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/pipe2.cxx @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: pipe2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkContourFilter.h" +#include "vtkImageData.h" +#include "vtkInputPort.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" + +#include "PipelineParallelism.h" + +// Pipe 2 for PipelineParallelism. +// See PipelineParallelism.cxx for more information. +void pipe2(vtkMultiProcessController* vtkNotUsed(controller), + void* vtkNotUsed(arg)) +{ + // Input port + vtkInputPort* ip = vtkInputPort::New(); + ip->SetRemoteProcessId(0); + ip->SetTag(11); + + // Iso-surface + vtkContourFilter* cf = vtkContourFilter::New(); + cf->SetInput(ip->GetImageDataOutput()); + cf->SetNumberOfContours(1); + cf->SetValue(0, 220); + + // Rendering objects + vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(cf->GetOutputPort()); + + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + + vtkRenderer* ren = vtkRenderer::New(); + ren->AddActor(actor); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + + // Normally, the Render() call on a RenderWindow() calls + // update on it's actors two times. This is not appropriate + // for this example because with each Update(), the data + // changes. For this reason, we will use a separate PolyData + // object and (shallow) copy the data to it. + vtkPolyData* pd = vtkPolyData::New(); + mapper->SetInput(pd); + + // Prime the pipeline. Tell the producer to start computing. + ip->Update(); + + // Get the first data, adjust camera appropriatly + cf->GetOutput()->Update(); + pd->ShallowCopy(cf->GetOutput()); + ren->ResetCamera(); + // Display data + renWin->Render(); + + // Get more data. With every update the XFreq of the rtSource + // is increased. + for (int i=0; i<17; i++) + { + cf->GetOutput()->Update(); + pd->ShallowCopy(cf->GetOutput()); + // Display + renWin->Render(); + } + // Tell the producer that we are done. + ip->GetController()->TriggerRMI(0, vtkMultiProcessController::BREAK_RMI_TAG); + + pd->Delete(); + ip->Delete(); + cf->Delete(); + mapper->Delete(); + actor->Delete(); + ren->Delete(); + renWin->Delete(); + +} + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/task1.cxx b/Examples/ParallelProcessing/Generic/Cxx/task1.cxx new file mode 100644 index 0000000..f0f722a --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/task1.cxx @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: task1.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "TaskParallelism.h" + +#include "vtkImageData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" + +// Task 1 for TaskParallelism. +// See TaskParallelism.cxx for more information. +vtkPolyDataMapper* task1(vtkRenderWindow* renWin, double data, + vtkCamera* cam) +{ + double extent = data; + int iextent = static_cast(data); + // The pipeline + + // Synthetic image source. + vtkRTAnalyticSource* source1 = vtkRTAnalyticSource::New(); + source1->SetWholeExtent (-1*iextent, iextent, -1*iextent, iextent, + -1*iextent, iextent ); + source1->SetCenter(0, 0, 0); + source1->SetStandardDeviation( 0.5 ); + source1->SetMaximum( 255.0 ); + source1->SetXFreq( 60 ); + source1->SetXMag( 10 ); + source1->SetYFreq( 30 ); + source1->SetYMag( 18 ); + source1->SetZFreq( 40 ); + source1->SetZMag( 5 ); + source1->GetOutput()->SetSpacing(2.0/extent,2.0/extent,2.0/extent); + + // Iso-surfacing. + vtkContourFilter* contour = vtkContourFilter::New(); + contour->SetInputConnection(source1->GetOutputPort()); + contour->SetNumberOfContours(1); + contour->SetValue(0, 220); + + // Magnitude of the gradient vector. + vtkImageGradientMagnitude* magn = vtkImageGradientMagnitude::New(); + magn->SetDimensionality(3); + magn->SetInputConnection(source1->GetOutputPort()); + + // Probe magnitude with iso-surface. + vtkProbeFilter* probe = vtkProbeFilter::New(); + probe->SetInputConnection(contour->GetOutputPort()); + probe->SetSource(magn->GetOutput()); + probe->SpatialMatchOn(); + + // Rendering objects. + vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); + mapper->SetInput(probe->GetPolyDataOutput()); + mapper->SetScalarRange(50, 180); + mapper->ImmediateModeRenderingOn(); + + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + + vtkRenderer* ren = vtkRenderer::New(); + renWin->AddRenderer(ren); + + ren->AddActor(actor); + ren->SetActiveCamera( cam ); + + // Cleanup + source1->Delete(); + contour->Delete(); + magn->Delete(); + probe->Delete(); + actor->Delete(); + ren->Delete(); + + return mapper; + +} + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/task2.cxx b/Examples/ParallelProcessing/Generic/Cxx/task2.cxx new file mode 100644 index 0000000..7734a12 --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/task2.cxx @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: task2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "TaskParallelism.h" + +#include "vtkImageData.h" +#include "vtkPolyDataMapper.h" + +// Task 2 for TaskParallelism. +// See TaskParallelism.cxx for more information. +vtkPolyDataMapper* task2(vtkRenderWindow* renWin, double data, + vtkCamera* cam) +{ + double extent = data; + int iextent = static_cast(data); + // The pipeline + + // Synthetic image source. + vtkRTAnalyticSource* source1 = vtkRTAnalyticSource::New(); + source1->SetWholeExtent (-1*iextent, iextent, -1*iextent, iextent, + -1*iextent, iextent ); + source1->SetCenter(0, 0, 0); + source1->SetStandardDeviation( 0.5 ); + source1->SetMaximum( 255.0 ); + source1->SetXFreq( 60 ); + source1->SetXMag( 10 ); + source1->SetYFreq( 30 ); + source1->SetYMag( 18 ); + source1->SetZFreq( 40 ); + source1->SetZMag( 5 ); + source1->GetOutput()->SetSpacing(2.0/extent,2.0/extent,2.0/extent); + + // Gradient vector. + vtkImageGradient* grad = vtkImageGradient::New(); + grad->SetDimensionality( 3 ); + grad->SetInputConnection(source1->GetOutputPort()); + + vtkImageShrink3D* mask = vtkImageShrink3D::New(); + mask->SetInputConnection(grad->GetOutputPort()); + mask->SetShrinkFactors(5, 5, 5); + + + // Label the scalar field as the active vectors. + vtkAssignAttribute* aa = vtkAssignAttribute::New(); + aa->SetInputConnection(mask->GetOutputPort()); + aa->Assign(vtkDataSetAttributes::SCALARS, vtkDataSetAttributes::VECTORS, + vtkAssignAttribute::POINT_DATA); + + vtkGlyphSource2D* arrow = vtkGlyphSource2D::New(); + arrow->SetGlyphTypeToArrow(); + arrow->SetScale(0.2); + arrow->FilledOff(); + + // Glyph the gradient vector (with arrows) + vtkGlyph3D* glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(aa->GetOutputPort()); + glyph->SetSource(arrow->GetOutput()); + glyph->ScalingOff(); + glyph->OrientOn(); + glyph->SetVectorModeToUseVector(); + glyph->SetColorModeToColorByVector(); + + // Rendering objects. + vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(glyph->GetOutputPort()); + mapper->SetScalarRange(50, 180); + mapper->ImmediateModeRenderingOn(); + + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + + vtkRenderer* ren = vtkRenderer::New(); + renWin->AddRenderer(ren); + + ren->AddActor(actor); + ren->SetActiveCamera( cam ); + + // Cleanup + source1->Delete(); + grad->Delete(); + aa->Delete(); + mask->Delete(); + glyph->Delete(); + arrow->Delete(); + actor->Delete(); + ren->Delete(); + + return mapper; +} + + + + + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/task3.cxx b/Examples/ParallelProcessing/Generic/Cxx/task3.cxx new file mode 100644 index 0000000..130408e --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/task3.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: task3.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "TaskParallelismWithPorts.h" + +#include "vtkAppendPolyData.h" +#include "vtkImageData.h" +#include "vtkInputPort.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" + +// Task 3 for TaskParallelismWithPorts. +// See TaskParallelismWithPorts.cxx for more information. +void task3(double data) +{ + double extent = data; + int iextent = static_cast(data); + // The pipeline + + // Synthetic image source. + vtkRTAnalyticSource* source1 = vtkRTAnalyticSource::New(); + source1->SetWholeExtent (-1*iextent, iextent, -1*iextent, iextent, + -1*iextent, iextent ); + source1->SetCenter(0, 0, 0); + source1->SetStandardDeviation( 0.5 ); + source1->SetMaximum( 255.0 ); + source1->SetXFreq( 60 ); + source1->SetXMag( 10 ); + source1->SetYFreq( 30 ); + source1->SetYMag( 18 ); + source1->SetZFreq( 40 ); + source1->SetZMag( 5 ); + source1->GetOutput()->SetSpacing(2.0/extent,2.0/extent,2.0/extent); + + // Iso-surfacing. + vtkContourFilter* contour = vtkContourFilter::New(); + contour->SetInputConnection(source1->GetOutputPort()); + contour->SetNumberOfContours(1); + contour->SetValue(0, 220); + + // Magnitude of the gradient vector. + vtkImageGradientMagnitude* magn = vtkImageGradientMagnitude::New(); + magn->SetDimensionality(3); + magn->SetInputConnection(source1->GetOutputPort()); + + // Probe magnitude with iso-surface. + vtkProbeFilter* probe = vtkProbeFilter::New(); + probe->SetInputConnection(contour->GetOutputPort()); + probe->SetSource(magn->GetOutput()); + probe->SpatialMatchOn(); + + // Input port + vtkInputPort* ip = vtkInputPort::New(); + ip->SetRemoteProcessId(1); + ip->SetTag(11); + + // Append the local and remote data + vtkAppendPolyData* append = vtkAppendPolyData::New(); + append->AddInput(ip->GetPolyDataOutput()); + append->AddInput(probe->GetPolyDataOutput()); + + + // Rendering objects. + vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(append->GetOutputPort()); + mapper->SetScalarRange(50, 180); + mapper->ImmediateModeRenderingOn(); + + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + + // Create the render objects + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->SetSize( WINDOW_WIDTH, WINDOW_HEIGHT ); + + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkRenderer* ren = vtkRenderer::New(); + renWin->AddRenderer(ren); + + ren->AddActor(actor); + + iren->Initialize(); + iren->Start(); + + // Tell the other process we are done + ip->GetController()->TriggerRMI(1, + vtkMultiProcessController::BREAK_RMI_TAG); + + // Cleanup + iren->Delete(); + renWin->Delete(); + ip->Delete(); + append->Delete(); + source1->Delete(); + contour->Delete(); + magn->Delete(); + probe->Delete(); + actor->Delete(); + ren->Delete(); + mapper->Delete(); + +} + + diff --git a/Examples/ParallelProcessing/Generic/Cxx/task4.cxx b/Examples/ParallelProcessing/Generic/Cxx/task4.cxx new file mode 100644 index 0000000..bfd875d --- /dev/null +++ b/Examples/ParallelProcessing/Generic/Cxx/task4.cxx @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: task4.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "TaskParallelismWithPorts.h" + +#include "vtkImageData.h" +#include "vtkOutputPort.h" +#include "vtkPolyData.h" + +// Task 4 for TaskParallelism. +// See TaskParallelismWithPorts.cxx for more information. +void task4(double data) +{ + double extent = data; + int iextent = static_cast(data); + // The pipeline + + // Synthetic image source. + vtkRTAnalyticSource* source1 = vtkRTAnalyticSource::New(); + source1->SetWholeExtent (-1*iextent, iextent, -1*iextent, iextent, + -1*iextent, iextent ); + source1->SetCenter(0, 0, 0); + source1->SetStandardDeviation( 0.5 ); + source1->SetMaximum( 255.0 ); + source1->SetXFreq( 60 ); + source1->SetXMag( 10 ); + source1->SetYFreq( 30 ); + source1->SetYMag( 18 ); + source1->SetZFreq( 40 ); + source1->SetZMag( 5 ); + source1->GetOutput()->SetSpacing(2.0/extent,2.0/extent,2.0/extent); + + // Gradient vector. + vtkImageGradient* grad = vtkImageGradient::New(); + grad->SetDimensionality( 3 ); + grad->SetInputConnection(source1->GetOutputPort()); + + vtkImageShrink3D* mask = vtkImageShrink3D::New(); + mask->SetInputConnection(grad->GetOutputPort()); + mask->SetShrinkFactors(5, 5, 5); + + + // Label the scalar field as the active vectors. + vtkAssignAttribute* aa = vtkAssignAttribute::New(); + aa->SetInputConnection(mask->GetOutputPort()); + aa->Assign(vtkDataSetAttributes::SCALARS, vtkDataSetAttributes::VECTORS, + vtkAssignAttribute::POINT_DATA); + + vtkGlyphSource2D* arrow = vtkGlyphSource2D::New(); + arrow->SetGlyphTypeToArrow(); + arrow->SetScale(0.2); + arrow->FilledOff(); + + // Glyph the gradient vector (with arrows) + vtkGlyph3D* glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(aa->GetOutputPort()); + glyph->SetSource(arrow->GetOutput()); + glyph->ScalingOff(); + glyph->OrientOn(); + glyph->SetVectorModeToUseVector(); + glyph->SetColorModeToColorByVector(); + + // Output port + vtkOutputPort* op = vtkOutputPort::New(); + op->SetInputConnection(glyph->GetOutputPort()); + op->SetTag(11); + + // Process requests + op->WaitForUpdate(); + + // Cleanup + op->Delete(); + source1->Delete(); + grad->Delete(); + aa->Delete(); + mask->Delete(); + glyph->Delete(); + arrow->Delete(); + +} + + + + + + diff --git a/Examples/ParallelProcessing/MPI/Python/ParallelCone.py b/Examples/ParallelProcessing/MPI/Python/ParallelCone.py new file mode 100644 index 0000000..547be38 --- /dev/null +++ b/Examples/ParallelProcessing/MPI/Python/ParallelCone.py @@ -0,0 +1,85 @@ +from vtk import * +import sys +import os +import time + +myProcId = 0 +numProcs = 1 + +compManager = vtkCompositeManager() +if compManager.GetController(): + myProcId = compManager.GetController().GetLocalProcessId() + numProcs = compManager.GetController().GetNumberOfProcesses() + +try: + v = vtkMesaRenderer() + if myProcId > 0: + _graphics_fact=vtkGraphicsFactory() + _graphics_fact.SetUseMesaClasses(1) + del _graphics_fact + del v +except Exception, (bar): + print "No mesa", bar + + + +#print "I am process: %d / %d" % (myProcId, numProcs) + +# create a rendering window and renderer +ren = vtkRenderer() +renWin = vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.SetSize(300,300) + +if myProcId: + renWin.OffScreenRenderingOn() + + +# create an actor and give it cone geometry +cone = vtkConeSource() +cone.SetResolution(8) +coneMapper = vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) +coneActor = vtkActor() +coneActor.SetMapper(coneMapper) + +# assign our actor to the renderer +ren.AddActor(coneActor) + +renWin.SetWindowName("I am node %d" % myProcId) + +if numProcs > 1: + compManager.SetRenderWindow(renWin) + compManager.InitializePieces() + +#print "Pid of process %d is %d" % (myProcId, os.getpid()) + +def ExitMaster(a, b): + #print "ExitMaster; I am %d / %d" % ( myProcId, numProcs ) + if numProcs > 1 and myProcId == 0: + #print "Trigger exit RMI on all satellite nodes" + for a in range(1, numProcs): + #print "Trigger exit in satellite node %d" % a + compManager.GetController().TriggerRMI(a, 239954) + +if myProcId == 0: + iren = vtkRenderWindowInteractor() + iren.SetRenderWindow(renWin) + iren.AddObserver("ExitEvent", ExitMaster) + iren.Start() + #renWin.Render() + #renWin.Render() + #renWin.Render() +else: + compManager.InitializeRMIs() + compManager.GetController().ProcessRMIs() + compManager.GetController().Finalize() + #print "**********************************" + #print "Done on the slave node" + #print "**********************************" + sys.exit() + +ExitMaster(0, 0) + +#time.sleep(5) + diff --git a/Examples/ParallelProcessing/MPI/Tcl/PVTKDemo.tcl b/Examples/ParallelProcessing/MPI/Tcl/PVTKDemo.tcl new file mode 100644 index 0000000..d22027e --- /dev/null +++ b/Examples/ParallelProcessing/MPI/Tcl/PVTKDemo.tcl @@ -0,0 +1,90 @@ +# This example demonstrates the use of pvtk. +# pvtk is a slightly different version of wish specially modified +# to be used with MPI. It allows Tcl scripts to be interpreted in +# parallel. +# +# In this example, a synthetic source (vtkRTAnalyticSource) generates +# image data (only one piece of the data is generated on each processor). +# Next, an isosurface (vtkContourFilter) is generated by each process. +# The resulting polygonal data is then rendered and then composited +# (vtkCompositeManager) and displayed on the first process (all processes +# will create render windows but only the render window of the root +# process will contain the composited image). + +package require vtk +package require vtkinteraction + +# Create a controller. At this point, MPI has already been initialized +# therefore there is no need to call Initialize. +vtkMPIController controller +# Get the local process id to be used later +set myId [controller GetLocalProcessId] + +# The "global" extent of the source is (2*EXTENT+1)*(2*EXTENT+1)*(2*EXTENT+1) +# Each processor will generate one piece of this extent. +set EXTENT 20 + +# This is a synthetic source. The equation is: +# Maximum*Gaussian*XMag*sin(XFreq*x)*sin(YFreq*y)*cos(ZFreq*z) +vtkRTAnalyticSource source1 +source1 SetWholeExtent [expr -1*$EXTENT] $EXTENT [expr -1*$EXTENT] $EXTENT \ + [expr -1*$EXTENT] $EXTENT +source1 SetCenter 0 0 0 +source1 SetStandardDeviation 0.5 +source1 SetMaximum 255.0 +source1 SetXFreq 60 +source1 SetXMag 10 +source1 SetYFreq 30 +source1 SetYMag 18 +source1 SetZFreq 40 +source1 SetZMag 5 +eval [source1 GetOutput] SetSpacing [expr 2.0/$EXTENT] \ + [expr 2.0/$EXTENT] [expr 2.0/$EXTENT] + +# Generate an isosurface +vtkContourFilter cf +cf SetInputConnection [source1 GetOutputPort] +cf SetNumberOfContours 1 +cf SetValue 0 220 + +vtkElevationFilter elev +elev SetInputConnection [cf GetOutputPort] +elev SetScalarRange $myId [expr $myId + 0.001] + +# Create the rendering part of the pipeline +vtkPolyDataMapper mapper +mapper SetInputConnection [elev GetOutputPort] +mapper SetScalarRange 0 [expr [controller GetNumberOfProcesses]] +vtkActor actor +actor SetMapper mapper + +vtkRenderer ren +ren AddActor actor + +vtkRenderWindow renWin +renWin AddRenderer ren + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# This class allows all processes to composite their images. +# The root process then displays it in it's render window. +vtkCompositeManager tc +tc SetRenderWindow renWin +# Tell the pipeline that we requests pieces not the whole +# data. +tc InitializePieces +# Reset camera so that a global clipping range is computed +# before the first render +ren ResetCamera + +wm withdraw . + +# Only the root process will have an active interactor. All +# the other render windows will be slaved to the root. +tc StartInteractor + +# This has to be called to clean-up. If it is not called, MPI +# will most probably complain at exit. +vtkCommand DeleteAllObjects +exit \ No newline at end of file diff --git a/Examples/README.txt b/Examples/README.txt new file mode 100644 index 0000000..d5ce5f2 --- /dev/null +++ b/Examples/README.txt @@ -0,0 +1,65 @@ +VTK Examples Directory +---------------------- +The following directory contains many well-commented examples showing how to +use VTK. Examples are available in the C++, Tcl, Python and Java programming +languages. In no way should these examples be considered comprehensive; VTK +is a large system, we have tried to pick examples that demonstrate key +features. + + +Table Of Contents +----------------- +A brief table of contents of the contents of this directory follows. +Beginners should start with the examples found in the Tutorial subdirectory. +The topics listed here have corresponding subdirectories in VTK/Examples. + +Annotation - Classes for 2D and 3D annotation such as text, scalar bar, + x-y plotting. + +DataManipulation - Examples show how to rearrange and manipulate data + in the visualization pipeline. + +GUI - Examples of interfacing to various GUI's including Motif, Windows, + and Tcl. + +IO - Examples how how to read and write data; and how to import and export + scenes. + +ImageProcessing - Selected examples demonstrating how to use VTK's + many image processing filters. + +MangledMesa - Use Mesa for on and offscreen rendering. + +Modelling - A variety of examples showing how to construct, edit, and + process surfaces. + +ParallelProcessing - Use VTK for parallel processing, including MPI and + threaded approaches. + +Rendering - Examples showing how to use VTK's many rendering, and related + facilities, such as LOD actors, assemblies, picking, and + camera manipulation. + +Tutorial - Some simple step-by-step instructions looking at things like + creating pipelines, processing events, and creating data. + +VisualizationAlgorithms - A variety of examples showing how to use common + visualization algorithms such as contouring, + cutting, probing, and streamlines. + +VolumeRendering - Learn how to perform volume rendering from the examples + in this directory. + + +Additional Resources +-------------------- +* The VTK Testing directories (e.g., VTK/Graphics/Testing) contain other + examples. These are not commented, and designed for testing. + +* The VTK Mailing List http://public.kitware.com/mailman/listinfo/vtkusers + +* The VTK Web Pages http://public.kitware.com/ + +* Commercial support and resources from Kitware: + - The VTK User's Guide http://www.kitware.com/products/vtkguide.html + - Support Contracts http://www.kitware.com/products/vtksupport.html diff --git a/Examples/Rendering/Cxx/AmbientSpheres.cxx b/Examples/Rendering/Cxx/AmbientSpheres.cxx new file mode 100644 index 0000000..c061bf8 --- /dev/null +++ b/Examples/Rendering/Cxx/AmbientSpheres.cxx @@ -0,0 +1,182 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: AmbientSpheres.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This examples demonstrates the effect of specular lighting. +// +#include "vtkSphereSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkProperty.h" +#include "vtkCamera.h" +#include "vtkLight.h" + +int main() +{ + // The following lines create a sphere represented by polygons. + // + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(100); + sphere->SetPhiResolution(50); + + // The mapper is responsible for pushing the geometry into the graphics + // library. It may also do color mapping, if scalars or other attributes + // are defined. + // + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + + // The actor is a grouping mechanism: besides the geometry (mapper), it + // also has a property, transformation matrix, and/or texture map. + // In this example we create eight different spheres (two rows of four + // spheres) and set the specular lighting coefficients. A little ambient + // is turned on so the sphere is not completely black on the back side. + // + vtkActor *sphere1 = vtkActor::New(); + sphere1->SetMapper(sphereMapper); + sphere1->GetProperty()->SetColor(1,0,0); + sphere1->GetProperty()->SetAmbient(0.125); + sphere1->GetProperty()->SetDiffuse(0.0); + sphere1->GetProperty()->SetSpecular(0.0); + + vtkActor *sphere2 = vtkActor::New(); + sphere2->SetMapper(sphereMapper); + sphere2->GetProperty()->SetColor(1,0,0); + sphere2->GetProperty()->SetAmbient(0.25); + sphere2->GetProperty()->SetDiffuse(0.0); + sphere2->GetProperty()->SetSpecular(0.0); + sphere2->AddPosition(1.25,0,0); + + vtkActor *sphere3 = vtkActor::New(); + sphere3->SetMapper(sphereMapper); + sphere3->GetProperty()->SetColor(1,0,0); + sphere3->GetProperty()->SetAmbient(0.375); + sphere3->GetProperty()->SetDiffuse(0.0); + sphere3->GetProperty()->SetSpecular(0.0); + sphere3->AddPosition(2.5,0,0); + + vtkActor *sphere4 = vtkActor::New(); + sphere4->SetMapper(sphereMapper); + sphere4->GetProperty()->SetColor(1,0,0); + sphere4->GetProperty()->SetAmbient(0.5); + sphere4->GetProperty()->SetDiffuse(0.0); + sphere4->GetProperty()->SetSpecular(0.0); + sphere4->AddPosition(3.75,0,0); + + vtkActor *sphere5 = vtkActor::New(); + sphere5->SetMapper(sphereMapper); + sphere5->GetProperty()->SetColor(1,0,0); + sphere5->GetProperty()->SetAmbient(0.625); + sphere5->GetProperty()->SetDiffuse(0.0); + sphere5->GetProperty()->SetSpecular(0.0); + sphere5->AddPosition(0.0,1.25,0); + + vtkActor *sphere6 = vtkActor::New(); + sphere6->SetMapper(sphereMapper); + sphere6->GetProperty()->SetColor(1,0,0); + sphere6->GetProperty()->SetAmbient(0.75); + sphere6->GetProperty()->SetDiffuse(0.0); + sphere6->GetProperty()->SetSpecular(0.0); + sphere6->AddPosition(1.25,1.25,0); + + vtkActor *sphere7 = vtkActor::New(); + sphere7->SetMapper(sphereMapper); + sphere7->GetProperty()->SetColor(1,0,0); + sphere7->GetProperty()->SetAmbient(0.875); + sphere7->GetProperty()->SetDiffuse(0.0); + sphere7->GetProperty()->SetSpecular(0.0); + sphere7->AddPosition(2.5,1.25,0); + + vtkActor *sphere8 = vtkActor::New(); + sphere8->SetMapper(sphereMapper); + sphere8->GetProperty()->SetColor(1,0,0); + sphere8->GetProperty()->SetAmbient(1.0); + sphere8->GetProperty()->SetDiffuse(0.0); + sphere8->GetProperty()->SetSpecular(0.0); + sphere8->AddPosition(3.75,1.25,0); + + // Create the graphics structure. The renderer renders into the + // render window. The render window interactor captures mouse events + // and will perform appropriate camera or actor manipulation + // depending on the nature of the events. + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Add the actors to the renderer, set the background and size. + // + ren1->AddActor(sphere1); + ren1->AddActor(sphere2); + ren1->AddActor(sphere3); + ren1->AddActor(sphere4); + ren1->AddActor(sphere5); + ren1->AddActor(sphere6); + ren1->AddActor(sphere7); + ren1->AddActor(sphere8); + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(400, 200); + + // Set up the lighting. + // + vtkLight *light = vtkLight::New(); + light->SetFocalPoint(1.875,0.6125,0); + light->SetPosition(0.875,1.6125,1); + ren1->AddLight(light); + + // We want to eliminate perspective effects on the apparent lighting. + // Parallel camera projection will be used. To zoom in parallel projection + // mode, the ParallelScale is set. + // + ren1->GetActiveCamera()->SetFocalPoint(0,0,0); + ren1->GetActiveCamera()->SetPosition(0,0,1); + ren1->GetActiveCamera()->SetViewUp(0,1,0); + ren1->GetActiveCamera()->ParallelProjectionOn(); + ren1->ResetCamera(); + ren1->GetActiveCamera()->SetParallelScale(1.5); + + // This starts the event loop and invokes an initial render. + // + iren->Initialize(); + iren->Start(); + + // Exiting from here, we have to delete all the instances that + // have been created. + // + sphere->Delete(); + sphereMapper->Delete(); + sphere1->Delete(); + sphere2->Delete(); + sphere3->Delete(); + sphere4->Delete(); + sphere5->Delete(); + sphere6->Delete(); + sphere7->Delete(); + sphere8->Delete(); + ren1->Delete(); + renWin->Delete(); + iren->Delete(); + light->Delete(); + + return 0; +} + + + + diff --git a/Examples/Rendering/Cxx/CMakeLists.txt b/Examples/Rendering/Cxx/CMakeLists.txt new file mode 100644 index 0000000..ea0f36d --- /dev/null +++ b/Examples/Rendering/Cxx/CMakeLists.txt @@ -0,0 +1,20 @@ +PROJECT (Rendering) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Cylinder Cylinder.cxx) +TARGET_LINK_LIBRARIES(Cylinder vtkRendering) + +ADD_EXECUTABLE(SpecularSpheres SpecularSpheres.cxx) +TARGET_LINK_LIBRARIES(SpecularSpheres vtkRendering) + +ADD_EXECUTABLE(DiffuseSpheres DiffuseSpheres.cxx) +TARGET_LINK_LIBRARIES(DiffuseSpheres vtkRendering) + +ADD_EXECUTABLE(AmbientSpheres AmbientSpheres.cxx) +TARGET_LINK_LIBRARIES(AmbientSpheres vtkRendering) + diff --git a/Examples/Rendering/Cxx/Cylinder.cxx b/Examples/Rendering/Cxx/Cylinder.cxx new file mode 100644 index 0000000..2ef0416 --- /dev/null +++ b/Examples/Rendering/Cxx/Cylinder.cxx @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cylinder.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This simple example shows how to do basic rendering and pipeline +// creation using C++. +// +#include "vtkCylinderSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkProperty.h" +#include "vtkCamera.h" + +int main() +{ + // This creates a polygonal cylinder model with eight circumferential facets. + // + vtkCylinderSource *cylinder = vtkCylinderSource::New(); + cylinder->SetResolution(8); + + // The mapper is responsible for pushing the geometry into the graphics + // library. It may also do color mapping, if scalars or other attributes + // are defined. + // + vtkPolyDataMapper *cylinderMapper = vtkPolyDataMapper::New(); + cylinderMapper->SetInputConnection(cylinder->GetOutputPort()); + + // The actor is a grouping mechanism: besides the geometry (mapper), it + // also has a property, transformation matrix, and/or texture map. + // Here we set its color and rotate it -22.5 degrees. + vtkActor *cylinderActor = vtkActor::New(); + cylinderActor->SetMapper(cylinderMapper); + cylinderActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784); + cylinderActor->RotateX(30.0); + cylinderActor->RotateY(-45.0); + + // Create the graphics structure. The renderer renders into the + // render window. The render window interactor captures mouse events + // and will perform appropriate camera or actor manipulation + // depending on the nature of the events. + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Add the actors to the renderer, set the background and size + // + ren1->AddActor(cylinderActor); + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(200, 200); + + // We'll zoom in a little by accessing the camera and invoking a "Zoom" + // method on it. + ren1->ResetCamera(); + ren1->GetActiveCamera()->Zoom(1.5); + renWin->Render(); + + // This starts the event loop and as a side effect causes an initial render. + iren->Start(); + + // Exiting from here, we have to delete all the instances that + // have been created. + cylinder->Delete(); + cylinderMapper->Delete(); + cylinderActor->Delete(); + ren1->Delete(); + renWin->Delete(); + iren->Delete(); + + return 0; +} + + + + diff --git a/Examples/Rendering/Cxx/DiffuseSpheres.cxx b/Examples/Rendering/Cxx/DiffuseSpheres.cxx new file mode 100644 index 0000000..8529b90 --- /dev/null +++ b/Examples/Rendering/Cxx/DiffuseSpheres.cxx @@ -0,0 +1,184 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: DiffuseSpheres.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This examples demonstrates the effect of diffuse lighting. +// +#include "vtkSphereSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkProperty.h" +#include "vtkCamera.h" +#include "vtkLight.h" + +int main() +{ + // The following lines create a sphere represented by polygons. + // + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(100); + sphere->SetPhiResolution(50); + + // The mapper is responsible for pushing the geometry into the graphics + // library. It may also do color mapping, if scalars or other attributes + // are defined. + // + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + + // The actor is a grouping mechanism: besides the geometry (mapper), it + // also has a property, transformation matrix, and/or texture map. + // In this example we create eight different spheres (two rows of four + // spheres) and set the specular lighting coefficients. A little ambient + // is turned on so the sphere is not completely black on the back side. + // + vtkActor *sphere1 = vtkActor::New(); + sphere1->SetMapper(sphereMapper); + sphere1->GetProperty()->SetColor(1,0,0); + sphere1->GetProperty()->SetAmbient(0.3); + sphere1->GetProperty()->SetDiffuse(0.0); + sphere1->GetProperty()->SetSpecular(0.0); + sphere1->GetProperty()->SetSpecularPower(5.0); + + vtkActor *sphere2 = vtkActor::New(); + sphere2->SetMapper(sphereMapper); + sphere2->GetProperty()->SetColor(1,0,0); + sphere2->GetProperty()->SetAmbient(0.3); + sphere2->GetProperty()->SetDiffuse(0.125); + sphere2->GetProperty()->SetSpecular(0.0); + sphere2->GetProperty()->SetSpecularPower(10.0); + sphere2->AddPosition(1.25,0,0); + + vtkActor *sphere3 = vtkActor::New(); + sphere3->SetMapper(sphereMapper); + sphere3->GetProperty()->SetColor(1,0,0); + sphere3->GetProperty()->SetAmbient(0.3); + sphere3->GetProperty()->SetDiffuse(0.25); + sphere3->GetProperty()->SetSpecular(0.0); + sphere3->AddPosition(2.5,0,0); + + vtkActor *sphere4 = vtkActor::New(); + sphere4->SetMapper(sphereMapper); + sphere4->GetProperty()->SetColor(1,0,0); + sphere4->GetProperty()->SetAmbient(0.3); + sphere4->GetProperty()->SetDiffuse(0.375); + sphere4->GetProperty()->SetSpecular(0.0); + sphere4->AddPosition(3.75,0,0); + + vtkActor *sphere5 = vtkActor::New(); + sphere5->SetMapper(sphereMapper); + sphere5->GetProperty()->SetColor(1,0,0); + sphere5->GetProperty()->SetAmbient(0.3); + sphere5->GetProperty()->SetDiffuse(0.5); + sphere5->GetProperty()->SetSpecular(0.0); + sphere5->AddPosition(0.0,1.25,0); + + vtkActor *sphere6 = vtkActor::New(); + sphere6->SetMapper(sphereMapper); + sphere6->GetProperty()->SetColor(1,0,0); + sphere6->GetProperty()->SetAmbient(0.3); + sphere6->GetProperty()->SetDiffuse(0.625); + sphere6->GetProperty()->SetSpecular(0.0); + sphere6->AddPosition(1.25,1.25,0); + + vtkActor *sphere7 = vtkActor::New(); + sphere7->SetMapper(sphereMapper); + sphere7->GetProperty()->SetColor(1,0,0); + sphere7->GetProperty()->SetAmbient(0.3); + sphere7->GetProperty()->SetDiffuse(0.75); + sphere7->GetProperty()->SetSpecular(0.0); + sphere7->AddPosition(2.5,1.25,0); + + vtkActor *sphere8 = vtkActor::New(); + sphere8->SetMapper(sphereMapper); + sphere8->GetProperty()->SetColor(1,0,0); + sphere8->GetProperty()->SetAmbient(0.3); + sphere8->GetProperty()->SetDiffuse(0.875); + sphere8->GetProperty()->SetSpecular(0.0); + sphere8->AddPosition(3.75,1.25,0); + + // Create the graphics structure. The renderer renders into the + // render window. The render window interactor captures mouse events + // and will perform appropriate camera or actor manipulation + // depending on the nature of the events. + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Add the actors to the renderer, set the background and size. + // + ren1->AddActor(sphere1); + ren1->AddActor(sphere2); + ren1->AddActor(sphere3); + ren1->AddActor(sphere4); + ren1->AddActor(sphere5); + ren1->AddActor(sphere6); + ren1->AddActor(sphere7); + ren1->AddActor(sphere8); + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(400, 200); + + // Set up the lighting. + // + vtkLight *light = vtkLight::New(); + light->SetFocalPoint(1.875,0.6125,0); + light->SetPosition(0.875,1.6125,1); + ren1->AddLight(light); + + // We want to eliminate perspective effects on the apparent lighting. + // Parallel camera projection will be used. To zoom in parallel projection + // mode, the ParallelScale is set. + // + ren1->GetActiveCamera()->SetFocalPoint(0,0,0); + ren1->GetActiveCamera()->SetPosition(0,0,1); + ren1->GetActiveCamera()->SetViewUp(0,1,0); + ren1->GetActiveCamera()->ParallelProjectionOn(); + ren1->ResetCamera(); + ren1->GetActiveCamera()->SetParallelScale(1.5); + + // This starts the event loop and invokes an initial render. + // + iren->Initialize(); + iren->Start(); + + // Exiting from here, we have to delete all the instances that + // have been created. + // + sphere->Delete(); + sphereMapper->Delete(); + sphere1->Delete(); + sphere2->Delete(); + sphere3->Delete(); + sphere4->Delete(); + sphere5->Delete(); + sphere6->Delete(); + sphere7->Delete(); + sphere8->Delete(); + ren1->Delete(); + renWin->Delete(); + iren->Delete(); + light->Delete(); + + return 0; +} + + + + diff --git a/Examples/Rendering/Cxx/SpecularSpheres.cxx b/Examples/Rendering/Cxx/SpecularSpheres.cxx new file mode 100644 index 0000000..d1e8116 --- /dev/null +++ b/Examples/Rendering/Cxx/SpecularSpheres.cxx @@ -0,0 +1,190 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SpecularSpheres.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This examples demonstrates the effect of specular lighting. +// +#include "vtkSphereSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkProperty.h" +#include "vtkCamera.h" +#include "vtkLight.h" + +int main() +{ + // The following lines create a sphere represented by polygons. + // + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(100); + sphere->SetPhiResolution(50); + + // The mapper is responsible for pushing the geometry into the graphics + // library. It may also do color mapping, if scalars or other attributes + // are defined. + // + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + + // The actor is a grouping mechanism: besides the geometry (mapper), it + // also has a property, transformation matrix, and/or texture map. + // In this example we create eight different spheres (two rows of four + // spheres) and set the specular lighting coefficients. A little ambient + // is turned on so the sphere is not completely black on the back side. + // + vtkActor *sphere1 = vtkActor::New(); + sphere1->SetMapper(sphereMapper); + sphere1->GetProperty()->SetColor(1,0,0); + sphere1->GetProperty()->SetAmbient(0.3); + sphere1->GetProperty()->SetDiffuse(0.0); + sphere1->GetProperty()->SetSpecular(1.0); + sphere1->GetProperty()->SetSpecularPower(5.0); + + vtkActor *sphere2 = vtkActor::New(); + sphere2->SetMapper(sphereMapper); + sphere2->GetProperty()->SetColor(1,0,0); + sphere2->GetProperty()->SetAmbient(0.3); + sphere2->GetProperty()->SetDiffuse(0.0); + sphere2->GetProperty()->SetSpecular(1.0); + sphere2->GetProperty()->SetSpecularPower(10.0); + sphere2->AddPosition(1.25,0,0); + + vtkActor *sphere3 = vtkActor::New(); + sphere3->SetMapper(sphereMapper); + sphere3->GetProperty()->SetColor(1,0,0); + sphere3->GetProperty()->SetAmbient(0.3); + sphere3->GetProperty()->SetDiffuse(0.0); + sphere3->GetProperty()->SetSpecular(1.0); + sphere3->GetProperty()->SetSpecularPower(20.0); + sphere3->AddPosition(2.5,0,0); + + vtkActor *sphere4 = vtkActor::New(); + sphere4->SetMapper(sphereMapper); + sphere4->GetProperty()->SetColor(1,0,0); + sphere4->GetProperty()->SetAmbient(0.3); + sphere4->GetProperty()->SetDiffuse(0.0); + sphere4->GetProperty()->SetSpecular(1.0); + sphere4->GetProperty()->SetSpecularPower(40.0); + sphere4->AddPosition(3.75,0,0); + + vtkActor *sphere5 = vtkActor::New(); + sphere5->SetMapper(sphereMapper); + sphere5->GetProperty()->SetColor(1,0,0); + sphere5->GetProperty()->SetAmbient(0.3); + sphere5->GetProperty()->SetDiffuse(0.0); + sphere5->GetProperty()->SetSpecular(0.5); + sphere5->GetProperty()->SetSpecularPower(5.0); + sphere5->AddPosition(0.0,1.25,0); + + vtkActor *sphere6 = vtkActor::New(); + sphere6->SetMapper(sphereMapper); + sphere6->GetProperty()->SetColor(1,0,0); + sphere6->GetProperty()->SetAmbient(0.3); + sphere6->GetProperty()->SetDiffuse(0.0); + sphere6->GetProperty()->SetSpecular(0.5); + sphere6->GetProperty()->SetSpecularPower(10.0); + sphere6->AddPosition(1.25,1.25,0); + + vtkActor *sphere7 = vtkActor::New(); + sphere7->SetMapper(sphereMapper); + sphere7->GetProperty()->SetColor(1,0,0); + sphere7->GetProperty()->SetAmbient(0.3); + sphere7->GetProperty()->SetDiffuse(0.0); + sphere7->GetProperty()->SetSpecular(0.5); + sphere7->GetProperty()->SetSpecularPower(20.0); + sphere7->AddPosition(2.5,1.25,0); + + vtkActor *sphere8 = vtkActor::New(); + sphere8->SetMapper(sphereMapper); + sphere8->GetProperty()->SetColor(1,0,0); + sphere8->GetProperty()->SetAmbient(0.3); + sphere8->GetProperty()->SetDiffuse(0.0); + sphere8->GetProperty()->SetSpecular(0.5); + sphere8->GetProperty()->SetSpecularPower(40.0); + sphere8->AddPosition(3.75,1.25,0); + + // Create the graphics structure. The renderer renders into the + // render window. The render window interactor captures mouse events + // and will perform appropriate camera or actor manipulation + // depending on the nature of the events. + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Add the actors to the renderer, set the background and size. + // + ren1->AddActor(sphere1); + ren1->AddActor(sphere2); + ren1->AddActor(sphere3); + ren1->AddActor(sphere4); + ren1->AddActor(sphere5); + ren1->AddActor(sphere6); + ren1->AddActor(sphere7); + ren1->AddActor(sphere8); + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(400, 200); + + // Set up the lighting. + // + vtkLight *light = vtkLight::New(); + light->SetFocalPoint(1.875,0.6125,0); + light->SetPosition(0.875,1.6125,1); + ren1->AddLight(light); + + // We want to eliminate perspective effects on the apparent lighting. + // Parallel camera projection will be used. To zoom in parallel projection + // mode, the ParallelScale is set. + // + ren1->GetActiveCamera()->SetFocalPoint(0,0,0); + ren1->GetActiveCamera()->SetPosition(0,0,1); + ren1->GetActiveCamera()->SetViewUp(0,1,0); + ren1->GetActiveCamera()->ParallelProjectionOn(); + ren1->ResetCamera(); + ren1->GetActiveCamera()->SetParallelScale(1.5); + + // This starts the event loop and invokes an initial render. + // + iren->Initialize(); + iren->Start(); + + // Exiting from here, we have to delete all the instances that + // have been created. + // + sphere->Delete(); + sphereMapper->Delete(); + sphere1->Delete(); + sphere2->Delete(); + sphere3->Delete(); + sphere4->Delete(); + sphere5->Delete(); + sphere6->Delete(); + sphere7->Delete(); + sphere8->Delete(); + ren1->Delete(); + renWin->Delete(); + iren->Delete(); + light->Delete(); + + return 0; +} + + + + diff --git a/Examples/Rendering/Python/CADPart.py b/Examples/Rendering/Python/CADPart.py new file mode 100644 index 0000000..39182bf --- /dev/null +++ b/Examples/Rendering/Python/CADPart.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +# This simple example shows how to do basic rendering and pipeline +# creation. It also demonstrates the use of the LODActor. + +# Import the VTK-Python module +import vtk +from vtk.util.misc import vtkGetDataRoot +from vtk.util.colors import * +# Get the location of the data. +VTK_DATA_ROOT = vtkGetDataRoot() + +# This creates a polygonal cylinder model with eight circumferential +# facets. +part = vtk.vtkSTLReader() +part.SetFileName(VTK_DATA_ROOT + "/Data/42400-IDGH.stl") + +# The mapper is responsible for pushing the geometry into the graphics +# library. It may also do color mapping, if scalars or other +# attributes are defined. +partMapper = vtk.vtkPolyDataMapper() +partMapper.SetInputConnection(part.GetOutputPort()) + +# The LOD actor is a special type of actor. It will change appearance +# in order to render faster. At the highest resolution, it renders +# ewverything just like an actor. The middle level is a point cloud, +# and the lowest level is a simple bounding box. +partActor = vtk.vtkLODActor() +partActor.SetMapper(partMapper) +partActor.GetProperty().SetColor(light_grey) +partActor.RotateX(30.0) +partActor.RotateY(-45.0) + +# Create the graphics structure. The renderer renders into the render +# window. The render window interactor captures mouse events and will +# perform appropriate camera or actor manipulation depending on the +# nature of the events. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(partActor) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(200, 200) + +# We'll zoom in a little by accessing the camera and invoking a "Zoom" +# method on it. +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.5) + +# This starts the event loop. +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Rendering/Python/CSpline.py b/Examples/Rendering/Python/CSpline.py new file mode 100644 index 0000000..8a728ee --- /dev/null +++ b/Examples/Rendering/Python/CSpline.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkCardinalSpline. +# It creates random points and connects them with a spline + +import vtk +from vtk.util.colors import tomato, banana + +# This will be used later to get random numbers. +math = vtk.vtkMath() + +# Total number of points. +numberOfInputPoints = 10 + +# One spline for each direction. +aSplineX = vtk.vtkCardinalSpline() +aSplineY = vtk.vtkCardinalSpline() +aSplineZ = vtk.vtkCardinalSpline() + +# Generate random (pivot) points and add the corresponding +# coordinates to the splines. +# aSplineX will interpolate the x values of the points +# aSplineY will interpolate the y values of the points +# aSplineZ will interpolate the z values of the points +inputPoints = vtk.vtkPoints() +for i in range(0, numberOfInputPoints): + x = math.Random(0, 1) + y = math.Random(0, 1) + z = math.Random(0, 1) + aSplineX.AddPoint(i, x) + aSplineY.AddPoint(i, y) + aSplineZ.AddPoint(i, z) + inputPoints.InsertPoint(i, x, y, z) + + +# The following section will create glyphs for the pivot points +# in order to make the effect of the spline more clear. + +# Create a polydata to be glyphed. +inputData = vtk.vtkPolyData() +inputData.SetPoints(inputPoints) + +# Use sphere as glyph source. +balls = vtk.vtkSphereSource() +balls.SetRadius(.01) +balls.SetPhiResolution(10) +balls.SetThetaResolution(10) + +glyphPoints = vtk.vtkGlyph3D() +glyphPoints.SetInput(inputData) +glyphPoints.SetSource(balls.GetOutput()) + +glyphMapper = vtk.vtkPolyDataMapper() +glyphMapper.SetInputConnection(glyphPoints.GetOutputPort()) + +glyph = vtk.vtkActor() +glyph.SetMapper(glyphMapper) +glyph.GetProperty().SetDiffuseColor(tomato) +glyph.GetProperty().SetSpecular(.3) +glyph.GetProperty().SetSpecularPower(30) + +# Generate the polyline for the spline. +points = vtk.vtkPoints() +profileData = vtk.vtkPolyData() + +# Number of points on the spline +numberOfOutputPoints = 400 + +# Interpolate x, y and z by using the three spline filters and +# create new points +for i in range(0, numberOfOutputPoints): + t = (numberOfInputPoints-1.0)/(numberOfOutputPoints-1.0)*i + points.InsertPoint(i, aSplineX.Evaluate(t), aSplineY.Evaluate(t), + aSplineZ.Evaluate(t)) + + +# Create the polyline. +lines = vtk.vtkCellArray() +lines.InsertNextCell(numberOfOutputPoints) +for i in range(0, numberOfOutputPoints): + lines.InsertCellPoint(i) + +profileData.SetPoints(points) +profileData.SetLines(lines) + +# Add thickness to the resulting line. +profileTubes = vtk.vtkTubeFilter() +profileTubes.SetNumberOfSides(8) +profileTubes.SetInput(profileData) +profileTubes.SetRadius(.005) + +profileMapper = vtk.vtkPolyDataMapper() +profileMapper.SetInputConnection(profileTubes.GetOutputPort()) + +profile = vtk.vtkActor() +profile.SetMapper(profileMapper) +profile.GetProperty().SetDiffuseColor(banana) +profile.GetProperty().SetSpecular(.3) +profile.GetProperty().SetSpecularPower(30) + +# Now create the RenderWindow, Renderer and Interactor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors +ren.AddActor(glyph) +ren.AddActor(profile) + +renWin.SetSize(500, 500) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Rendering/Python/Cylinder.py b/Examples/Rendering/Python/Cylinder.py new file mode 100644 index 0000000..ba4e705 --- /dev/null +++ b/Examples/Rendering/Python/Cylinder.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +# This simple example shows how to do basic rendering and pipeline +# creation. + +import vtk +# The colors module defines various useful colors. +from vtk.util.colors import tomato + +# This creates a polygonal cylinder model with eight circumferential +# facets. +cylinder = vtk.vtkCylinderSource() +cylinder.SetResolution(8) + +# The mapper is responsible for pushing the geometry into the graphics +# library. It may also do color mapping, if scalars or other +# attributes are defined. +cylinderMapper = vtk.vtkPolyDataMapper() +cylinderMapper.SetInputConnection(cylinder.GetOutputPort()) + +# The actor is a grouping mechanism: besides the geometry (mapper), it +# also has a property, transformation matrix, and/or texture map. +# Here we set its color and rotate it -22.5 degrees. +cylinderActor = vtk.vtkActor() +cylinderActor.SetMapper(cylinderMapper) +cylinderActor.GetProperty().SetColor(tomato) +cylinderActor.RotateX(30.0) +cylinderActor.RotateY(-45.0) + +# Create the graphics structure. The renderer renders into the render +# window. The render window interactor captures mouse events and will +# perform appropriate camera or actor manipulation depending on the +# nature of the events. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(cylinderActor) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(200, 200) + +# This allows the interactor to initalize itself. It has to be +# called before an event loop. +iren.Initialize() + +# We'll zoom in a little by accessing the camera and invoking a "Zoom" +# method on it. +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.5) +renWin.Render() + +# Start the event loop. +iren.Start() diff --git a/Examples/Rendering/Python/FilterCADPart.py b/Examples/Rendering/Python/FilterCADPart.py new file mode 100644 index 0000000..7786e73 --- /dev/null +++ b/Examples/Rendering/Python/FilterCADPart.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +# This simple example shows how to do simple filtering in a pipeline. +# See CADPart.py and Cylinder.py for related information. + +import vtk +from vtk.util.colors import light_grey +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# This creates a polygonal cylinder model with eight circumferential +# facets. +part = vtk.vtkSTLReader() +part.SetFileName(VTK_DATA_ROOT + "/Data/42400-IDGH.stl") + +# A filter is a module that takes at least one input and produces at +# least one output. The SetInput and GetOutput methods are used to do +# the connection. What is returned by GetOutput is a particulat +# dataset type. If the type is compatible with the SetInput method, +# then the filters can be connected together. +# +# Here we add a filter that computes surface normals from the geometry. +shrink = vtk.vtkShrinkPolyData() +shrink.SetInputConnection(part.GetOutputPort()) +shrink.SetShrinkFactor(0.85) + +# The mapper is responsible for pushing the geometry into the graphics +# library. It may also do color mapping, if scalars or other +# attributes are defined. +partMapper = vtk.vtkPolyDataMapper() +partMapper.SetInputConnection(shrink.GetOutputPort()) + +# The LOD actor is a special type of actor. It will change appearance +# in order to render faster. At the highest resolution, it renders +# ewverything just like an actor. The middle level is a point cloud, +# and the lowest level is a simple bounding box. +partActor = vtk.vtkLODActor() +partActor.SetMapper(partMapper) +partActor.GetProperty().SetColor(light_grey) +partActor.RotateX(30.0) +partActor.RotateY(-45.0) + +# Create the graphics structure. The renderer renders into the +# render window. The render window interactor captures mouse events +# and will perform appropriate camera or actor manipulation +# depending on the nature of the events. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(partActor) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(200, 200) + +# We'll zoom in a little by accessing the camera and invoking a "Zoom" +# method on it. +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.5) + +iren.Initialize() +renWin.Render() +# Start the event loop. +iren.Start() diff --git a/Examples/Rendering/Python/RenderLargeImage.py b/Examples/Rendering/Python/RenderLargeImage.py new file mode 100644 index 0000000..91a7b54 --- /dev/null +++ b/Examples/Rendering/Python/RenderLargeImage.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# This simple example shows how to render a very large image (i.e. +# one that cannot fit on the screen). + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# We'll import some data to start. Since we are using an importer, +# we've got to give it a render window and such. Note that the render +# window size is set fairly small. +ren = vtk.vtkRenderer() +ren.SetBackground(0.1, 0.2, 0.4) +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.SetSize(125, 125) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +importer = vtk.vtk3DSImporter() +importer.SetRenderWindow(renWin) +importer.SetFileName(VTK_DATA_ROOT + "/Data/Viewpoint/iflamigm.3ds") +importer.ComputeNormalsOn() +importer.Read() + +# We'll set up the view we want. +ren.GetActiveCamera().SetPosition(0, 1, 0) +ren.GetActiveCamera().SetFocalPoint(0, 0, 0) +ren.GetActiveCamera().SetViewUp(0, 0, 1) + +# Let the renderer compute a good position and focal point. +ren.ResetCamera() +ren.GetActiveCamera().Dolly(1.4) +ren.ResetCameraClippingRange() + +renderLarge = vtk.vtkRenderLargeImage() +renderLarge.SetInput(ren) +renderLarge.SetMagnification(4) + +# We write out the image which causes the rendering to occur. If you +# watch your screen you might see the pieces being rendered right +# after one another. +writer = vtk.vtkPNGWriter() +writer.SetInputConnection(renderLarge.GetOutputPort()) +writer.SetFileName("largeImage.png") +writer.Write() diff --git a/Examples/Rendering/Python/TPlane.py b/Examples/Rendering/Python/TPlane.py new file mode 100644 index 0000000..3b9d402 --- /dev/null +++ b/Examples/Rendering/Python/TPlane.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# This simple example shows how to do basic texture mapping. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Load in the texture map. A texture is any unsigned char image. If it +# is not of this type, you will have to map it through a lookup table +# or by using vtkImageShiftScale. +bmpReader = vtk.vtkBMPReader() +bmpReader.SetFileName(VTK_DATA_ROOT + "/Data/masonry.bmp") +atext = vtk.vtkTexture() +atext.SetInputConnection(bmpReader.GetOutputPort()) +atext.InterpolateOn() + +# Create a plane source and actor. The vtkPlanesSource generates +# texture coordinates. +plane = vtk.vtkPlaneSource() +planeMapper = vtk.vtkPolyDataMapper() +planeMapper.SetInputConnection(plane.GetOutputPort()) +planeActor = vtk.vtkActor() +planeActor.SetMapper(planeMapper) +planeActor.SetTexture(atext) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(planeActor) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(500, 500) + +ren.ResetCamera() +cam1 = ren.GetActiveCamera() +cam1.Elevation(-30) +cam1.Roll(-20) +ren.ResetCameraClippingRange() + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Rendering/Python/assembly.py b/Examples/Rendering/Python/assembly.py new file mode 100644 index 0000000..27d5dcd --- /dev/null +++ b/Examples/Rendering/Python/assembly.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkAssembly. In an assembly, +# the motion of one actor affects the position of other actors. + +import vtk + +# Create four parts: a top level assembly (in this case, a +# vtkCylinder) and three primitives (using vtkSphereSource, +# vtkCubeSource, and vtkConeSource). Set up mappers and actors for +# each part of the assembly to carry information about material +# properties and associated geometry. +sphere = vtk.vtkSphereSource() +sphereMapper = vtk.vtkPolyDataMapper() +sphereMapper.SetInputConnection(sphere.GetOutputPort()) +sphereActor = vtk.vtkActor() +sphereActor.SetMapper(sphereMapper) +sphereActor.SetOrigin(2, 1, 3) +sphereActor.RotateY(6) +sphereActor.SetPosition(2.25, 0, 0) +sphereActor.GetProperty().SetColor(1, 0, 1) + +cube = vtk.vtkCubeSource() +cubeMapper = vtk.vtkPolyDataMapper() +cubeMapper.SetInputConnection(cube.GetOutputPort()) +cubeActor = vtk.vtkActor() +cubeActor.SetMapper(cubeMapper) +cubeActor.SetPosition(0.0, .25, 0) +cubeActor.GetProperty().SetColor(0, 0, 1) + +cone = vtk.vtkConeSource() +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) +coneActor = vtk.vtkActor() +coneActor.SetMapper(coneMapper) +coneActor.SetPosition(0, 0, .25) +coneActor.GetProperty().SetColor(0, 1, 0) + +# top part of the assembly +cylinder = vtk.vtkCylinderSource() +cylinderMapper = vtk.vtkPolyDataMapper() +cylinderMapper.SetInputConnection(cylinder.GetOutputPort()) +cylinderMapper.SetResolveCoincidentTopologyToPolygonOffset() +cylinderActor = vtk.vtkActor() +cylinderActor.SetMapper(cylinderMapper) +cylinderActor.GetProperty().SetColor(1, 0, 0) + +# Create the assembly and add the 4 parts to it. Also set the origin, +# position and orientation in space. +assembly = vtk.vtkAssembly() +assembly.AddPart(cylinderActor) +assembly.AddPart(sphereActor) +assembly.AddPart(cubeActor) +assembly.AddPart(coneActor) +assembly.SetOrigin(5, 10, 15) +assembly.AddPosition(5, 0, 0) +assembly.RotateX(15) + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(assembly) +ren.AddActor(coneActor) +ren.SetBackground(0.1, 0.2, 0.4) +renWin.SetSize(200, 200) + +# Set up the camera to get a particular view of the scene +camera = vtk.vtkCamera() +camera.SetClippingRange(21.9464, 30.0179) +camera.SetFocalPoint(3.49221, 2.28844, -0.970866) +camera.SetPosition(3.49221, 2.28844, 24.5216) +camera.SetViewAngle(30) +camera.SetViewUp(0, 1, 0) +ren.SetActiveCamera(camera) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Rendering/Python/rainbow.py b/Examples/Rendering/Python/rainbow.py new file mode 100644 index 0000000..9cbab9d --- /dev/null +++ b/Examples/Rendering/Python/rainbow.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +# This example demonstrates the use and manipulation of lookup tables. + +import vtk +from vtk.util.colors import * +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# First create pipeline a simple pipeline that reads a structure grid +# and then extracts a plane from the grid. The plane will be colored +# differently by using different lookup tables. +# +# Note: the Update method is manually invoked because it causes the +# reader to read; later on we use the output of the reader to set +# a range for the scalar values. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() +plane = vtk.vtkStructuredGridGeometryFilter() +plane.SetInputConnection(pl3d.GetOutputPort()) +plane.SetExtent(1, 100, 1, 100, 7, 7) +lut = vtk.vtkLookupTable() +planeMapper = vtk.vtkPolyDataMapper() +planeMapper.SetLookupTable(lut) +planeMapper.SetInputConnection(plane.GetOutputPort()) +planeMapper.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +planeActor = vtk.vtkActor() +planeActor.SetMapper(planeMapper) + +# This creates an outline around the data. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# Much of the following is commented out. To try different lookup tables, +# uncommented the appropriate portions. + +# This creates a black to white lut. +##lut.SetHueRange(0, 0) +##lut.SetSaturationRange(0, 0) +##lut.SetValueRange(0.2, 1.0) + +# This creates a red to blue lut. +##lut.SetHueRange(0.0, 0.667) + +# This creates a blue to red lut. +##lut.SetHueRange(0.667, 0.0) + +# This creates a wierd effect. The Build() method causes the lookup +# table to allocate memory and create a table based on the currect +# hue, saturation, value, and alpha (transparency) range. Here we then +# manually overwrite the values generated by the Build() method. +lut.SetNumberOfColors(256) +lut.Build() +for i in range(0, 16): + lut.SetTableValue(i*16, red[0], red[1], red[2], 1) + lut.SetTableValue(i*16+1, green[0], green[1], green[2], 1) + lut.SetTableValue(i*16+2, blue[0], blue[1], blue[2], 1) + lut.SetTableValue(i*16+3, black[0], black[1], black[2], 1) + + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(planeActor) + +ren.SetBackground(0.1, 0.2, 0.4) +ren.TwoSidedLightingOff() + +renWin.SetSize(250, 250) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(8.88908, 0.595038, 29.3342) +cam1.SetPosition(-12.3332, 31.7479, 41.2387) +cam1.SetViewUp(0.060772, -0.319905, 0.945498) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/Rendering/Tcl/AbortCheckEvent.tcl b/Examples/Rendering/Tcl/AbortCheckEvent.tcl new file mode 100644 index 0000000..eeb3163 --- /dev/null +++ b/Examples/Rendering/Tcl/AbortCheckEvent.tcl @@ -0,0 +1,53 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create a sphere source and actor +vtkSphereSource sphere + sphere SetThetaResolution 40 + sphere SetPhiResolution 40 +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +# Create the spikes using a cone source and the sphere source +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSourceConnection [cone GetOutputPort] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] +vtkLODActor spikeActor + spikeActor SetMapper spikeMapper + +# Add the actors to the renderer, set the background and size renWin +ren1 AddActor sphereActor +ren1 AddActor spikeActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# Render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +iren Initialize + +proc TkCheckAbort {} { + if {[renWin GetEventPending] != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent TkCheckAbort + +# Prevent the tk window from appearing; start the event loop +wm withdraw . diff --git a/Examples/Rendering/Tcl/CADPart.tcl b/Examples/Rendering/Tcl/CADPart.tcl new file mode 100644 index 0000000..3e45640 --- /dev/null +++ b/Examples/Rendering/Tcl/CADPart.tcl @@ -0,0 +1,71 @@ +# +# This simple example shows how to do basic rendering and pipeline +# creation. It also demonstrates the use of the LODActor. +# +# We start off by loading some Tcl modules. One is the basic VTK library; +# the second is a package for rendering, and the last includes a set +# of color definitions. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# This creates a polygonal cylinder model with eight circumferential facets. +# +vtkSTLReader part + part SetFileName "$VTK_DATA_ROOT/Data/42400-IDGH.stl" + +# The mapper is responsible for pushing the geometry into the graphics +# library. It may also do color mapping, if scalars or other attributes +# are defined. +# +vtkPolyDataMapper partMapper + partMapper SetInputConnection [part GetOutputPort] + +# The LOD actor is a special type of actor. It will change appearance in +# order to render faster. At the highest resolution, it renders ewverything +# just like an actor. The middle level is a point cloud, and the lowest +# level is a simple bounding box. +vtkLODActor partActor + partActor SetMapper partMapper + eval [partActor GetProperty] SetColor $light_grey + partActor RotateX 30.0 + partActor RotateY -45.0 + +# Create the graphics structure. The renderer renders into the +# render window. The render window interactor captures mouse events +# and will perform appropriate camera or actor manipulation +# depending on the nature of the events. +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor partActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 200 200 + +# The next line associates a Tcl proc with a "keypress-u" event +# in the rendering window. In this case the proc deiconifies the +# .vtkInteract Tk form that was defined when we loaded +# "package require vtkinteraction". +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# This starts the event loop and as a side effect causes an initial render. +iren Initialize + +# We'll zoom in a little by accessing the camera and invoking a "Zoom" +# method on it. +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/Rendering/Tcl/CSpline.tcl b/Examples/Rendering/Tcl/CSpline.tcl new file mode 100644 index 0000000..6245d7b --- /dev/null +++ b/Examples/Rendering/Tcl/CSpline.tcl @@ -0,0 +1,127 @@ +# This example demonstrates the use of vtkCardinalSpline. +# It creates random points and connects them with a spline + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction +package require vtktesting + +# This will be used later to get random numbers. +vtkMath math + +# Total number of points. +set numberOfInputPoints 10 + +# One spline for each direction. +vtkCardinalSpline aSplineX +vtkCardinalSpline aSplineY +vtkCardinalSpline aSplineZ + +# Generate random (pivot) points and add the corresponding +# coordinates to the splines. +# aSplineX will interpolate the x values of the points +# aSplineY will interpolate the y values of the points +# aSplineZ will interpolate the z values of the points +vtkPoints inputPoints +for {set i 0} {$i < $numberOfInputPoints} {incr i 1} { + set x [math Random 0 1] + set y [math Random 0 1] + set z [math Random 0 1] + aSplineX AddPoint $i $x + aSplineY AddPoint $i $y + aSplineZ AddPoint $i $z + inputPoints InsertPoint $i $x $y $z +} + +# The following section will create glyphs for the pivot points +# in order to make the effect of the spline more clear. + +# Create a polydata to be glyphed. +vtkPolyData inputData +inputData SetPoints inputPoints + +# Use sphere as glyph source. +vtkSphereSource balls +balls SetRadius .01 +balls SetPhiResolution 10 +balls SetThetaResolution 10 + +vtkGlyph3D glyphPoints +glyphPoints SetInput inputData +glyphPoints SetSource [balls GetOutput] + +vtkPolyDataMapper glyphMapper +glyphMapper SetInputConnection [glyphPoints GetOutputPort] + +vtkActor glyph +glyph SetMapper glyphMapper +eval [glyph GetProperty] SetDiffuseColor $tomato +[glyph GetProperty] SetSpecular .3 +[glyph GetProperty] SetSpecularPower 30 + +# Generate the polyline for the spline. +vtkPoints points +vtkPolyData profileData + +# Number of points on the spline +set numberOfOutputPoints 400 + +# Interpolate x, y and z by using the three spline filters and +# create new points +for {set i 0} {$i< $numberOfOutputPoints} {incr i 1} { + set t [expr ( $numberOfInputPoints - 1.0 ) / ( $numberOfOutputPoints - 1.0 ) * $i] + points InsertPoint $i [aSplineX Evaluate $t] [aSplineY Evaluate $t] [aSplineZ Evaluate $t] +} + +# Create the polyline. +vtkCellArray lines +lines InsertNextCell $numberOfOutputPoints +for {set i 0} {$i < $numberOfOutputPoints} {incr i 1} { + lines InsertCellPoint $i +} +profileData SetPoints points +profileData SetLines lines + +# Add thickness to the resulting line. +vtkTubeFilter profileTubes +profileTubes SetNumberOfSides 8 +profileTubes SetInput profileData +profileTubes SetRadius .005 + +vtkPolyDataMapper profileMapper +profileMapper SetInputConnection [profileTubes GetOutputPort] + +vtkActor profile +profile SetMapper profileMapper +eval [profile GetProperty] SetDiffuseColor $banana +[profile GetProperty] SetSpecular .3 +[profile GetProperty] SetSpecularPower 30 + + +# Now create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin +renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# Add the actors +ren1 AddActor glyph +ren1 AddActor profile + +renWin SetSize 500 500 + +# render the image +# +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up +wm withdraw . + + diff --git a/Examples/Rendering/Tcl/Cylinder.tcl b/Examples/Rendering/Tcl/Cylinder.tcl new file mode 100644 index 0000000..b28a195 --- /dev/null +++ b/Examples/Rendering/Tcl/Cylinder.tcl @@ -0,0 +1,73 @@ +# +# This simple example shows how to do basic rendering and pipeline +# creation. +# +# We start off by loading some Tcl modules. One is the basic VTK library; +# the second is a package for rendering, and the last includes a set +# of color definitions. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# This creates a polygonal cylinder model with eight circumferential facets. +# +vtkCylinderSource cylinder + cylinder SetResolution 8 + +# The mapper is responsible for pushing the geometry into the graphics +# library. It may also do color mapping, if scalars or other attributes +# are defined. +# +vtkPolyDataMapper cylinderMapper + cylinderMapper SetInputConnection [cylinder GetOutputPort] + +# The actor is a grouping mechanism: besides the geometry (mapper), it +# also has a property, transformation matrix, and/or texture map. +# Here we set its color and rotate it -22.5 degrees. +vtkActor cylinderActor + cylinderActor SetMapper cylinderMapper + eval [cylinderActor GetProperty] SetColor $tomato + cylinderActor RotateX 30.0 + cylinderActor RotateY -45.0 + +# Create the graphics structure. The renderer renders into the +# render window. The render window interactor captures mouse events +# and will perform appropriate camera or actor manipulation +# depending on the nature of the events. +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cylinderActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 200 200 + +# The next line associates a Tcl proc with a "keypress-u" event +# in the rendering window. In this case the proc deiconifies the +# .vtkInteract Tk form that was defined when we loaded +# "package require vtkinteraction". +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# This allows the interactor to initalize itself. It has to be +# called before an event loop. In this example, we allow Tk to +# start the event loop (this is done automatically by Tk after +# the user script is executed). +iren Initialize + +# We'll zoom in a little by accessing the camera and invoking a "Zoom" +# method on it. +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/Rendering/Tcl/FilterCADPart.tcl b/Examples/Rendering/Tcl/FilterCADPart.tcl new file mode 100644 index 0000000..f0bf5b6 --- /dev/null +++ b/Examples/Rendering/Tcl/FilterCADPart.tcl @@ -0,0 +1,83 @@ +# +# This simple example shows how to do simple filtering in a pipeline. +# See CADPart.tcl and Cylinder.tcl for related information. +# +# We start off by loading some Tcl modules. One is the basic VTK library; +# the second is a package for rendering, and the last includes a set +# of color definitions. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# This creates a polygonal cylinder model with eight circumferential facets. +# +vtkSTLReader part + part SetFileName "$VTK_DATA_ROOT/Data/42400-IDGH.stl" + +# A filter is a module that takes at least one input and produces at +# least one output. The SetInput and GetOutput methods are used to do +# the connection. What is returned by GetOutput is a particulat dataset +# type. If the type is compatible with the SetInput method, then the +# filters can be connected together. +# +# Here we add a filter that computes surface normals from the geometry. +# +vtkShrinkPolyData shrink + shrink SetInputConnection [part GetOutputPort] + shrink SetShrinkFactor 0.85 + +# The mapper is responsible for pushing the geometry into the graphics +# library. It may also do color mapping, if scalars or other attributes +# are defined. +# +vtkPolyDataMapper partMapper + partMapper SetInputConnection [shrink GetOutputPort] + +# The LOD actor is a special type of actor. It will change appearance in +# order to render faster. At the highest resolution, it renders ewverything +# just like an actor. The middle level is a point cloud, and the lowest +# level is a simple bounding box. +vtkLODActor partActor + partActor SetMapper partMapper + eval [partActor GetProperty] SetColor $light_grey + partActor RotateX 30.0 + partActor RotateY -45.0 + +# Create the graphics structure. The renderer renders into the +# render window. The render window interactor captures mouse events +# and will perform appropriate camera or actor manipulation +# depending on the nature of the events. +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor partActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 200 200 + +# The next line associates a Tcl proc with a "keypress-u" event +# in the rendering window. In this case the proc deiconifies the +# .vtkInteract Tk form that was defined when we loaded +# "package require vtkinteraction". +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# This starts the event loop and as a side effect causes an initial render. +iren Initialize + +# We'll zoom in a little by accessing the camera and invoking a "Zoom" +# method on it. +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/Rendering/Tcl/KeyFrame.tcl b/Examples/Rendering/Tcl/KeyFrame.tcl new file mode 100644 index 0000000..bc49ae1 --- /dev/null +++ b/Examples/Rendering/Tcl/KeyFrame.tcl @@ -0,0 +1,106 @@ +# KeyFrame.tcl - Keyframes for vtk +# +# These procs provide a simple (yet powerful) keyframing capability +# for vtk tcl applications +# A keyframe contains a time sorted ordering of methods +# and arguments for an object. Key locations, colors, and +# other parameters are stored and can be interpolated +# at intermediate points. +# The protocol for keyframing is illustrated in the following +# example to keyframe the position of the camera camera1: +# the renderer ren1: +# 1) KeyNew CameraPosition camera1 SetPosition +# create a keyframe for camera1 that will use the +# SetPosition method of the camera +# 2) KeyAdd CameraPosition camera1 [camera1 GetPosition] +# adds the current camera position as a key frame +# 3) Repeat 2, changing the camera position for each step +# 4) KeyRun CameraPosition 30 +# runs key frame for 30 steps. Steps that lie +# between keyframes are interpolated with Cubic Splines. +# After each step is interpolated, the proc KeyRender +# is invoked. This proc can be redefined by the use to +# do something more sophisticated. The default proc does +# a: renWin Render +# +############################################ +# Create a new keyframe for object and method +proc KeyNew {keyFrame object method} { + upvar $keyFrame a + set a(object) $object + set a(method) $method + set a(counter) 0 + set a(debug) 0 +} + +# +# Reset the keyframe count to 0 +proc KeyReset {keyFrame} { + upvar $keyFrame a + set a(counter) 0 + if { $a(debug) == 1} {puts "Resetting $keyFrame"} +} + +# +# Add a new keyframe with contents value +proc KeyAdd {keyFrame value} { + upvar $keyFrame a + set a($a(counter)) $value + incr a(counter) +} + +# +# Run a keyframe for "frames" frames +proc KeyRun {keyFrame frames} { + upvar $keyFrame a + set object $a(object) + set method $a(method) + set depends [llength $a(0)] + # + # create splines if they do not exist + # + for {set j 0} {$j < $depends} {incr j} { + set spline $object${method}Spline$j + if {[info commands $spline] == ""} { + vtkKochanekSpline $spline + } + $spline RemoveAllPoints + } + # + # add points to the splines + # + for {set i 0} {$i < $a(counter)} {incr i} { + for {set j 0} {$j < $depends} {incr j} { + $object${method}Spline$j AddPoint $i [lindex $a($i) $j] + } + } + # + # evaluate splines at key frames + # + for {set i 0} {$i < $frames} {incr i} { + set t [expr ( $a(counter) - 1.0 ) / ( $frames - 1) * $i] + KeyGoto a $t + } +} + +# Goto keyframe # +proc KeyGoto {keyFrame t} { + upvar $keyFrame a + set object $a(object) + set method $a(method) + set depends [llength $a(0)] + set keyCommand "$object $method " + for {set j 0} {$j < $depends} {incr j} { + lappend keyCommand "[$object${method}Spline$j Evaluate $t]" + } + if {$a(debug) == 1} {puts "$keyCommand"} + eval $keyCommand + KeyRender +} + +# Called after keyframe is executed +proc KeyRender {} { + renWin Render +} + + diff --git a/Examples/Rendering/Tcl/LightKitViewer.tcl b/Examples/Rendering/Tcl/LightKitViewer.tcl new file mode 100644 index 0000000..434a880 --- /dev/null +++ b/Examples/Rendering/Tcl/LightKitViewer.tcl @@ -0,0 +1,309 @@ +# This example builds a user interface to set the parameters for +# a vtkLightKit object. The default parameters for a LightKit +# are pretty reasonable, but moving the lights around may help +# a user light a particular object. + +package require vtk +package require vtkinteraction +package require vtktesting + +# demonstrate LightKit functionality. + +set root [toplevel .top -visual {truecolor 24}] +wm title .top "LightKit Viewer" +wm protocol .top WM_DELETE_WINDOW exit +wm withdraw . + +vtkRenderWindow renWin +set renWidget [vtkTkRenderWidget $root.ren -width 400 -height 400 -rw renWin] +::vtk::bind_tk_render_widget $renWidget + +vtkRenderer ren1 +renWin AddRenderer ren1 + +vtkLightKit lightKit +lightKit AddLightsToRenderer ren1 + +set TitleFont {-size 12 -family Helvetica -weight bold} + + +# Key Light panel +set keyfrm [frame $root.keyfrm] +set keylbl [label $keyfrm.lbl -text "Key Light" -anchor w -font $TitleFont] +set keywarmlbl [label $keyfrm.warmlbl -text "Warmth" -anchor se] +set keywarm [scale $keyfrm.warm -from 0 -to 1 -res 0.01 -orient horizontal] + +set keyelevlbl [label $keyfrm.elevlbl -text "Elevation" -anchor se] +set keyelev [scale $keyfrm.elev -from 0 -to 90 -orient horizontal] + +set keyazimlbl [label $keyfrm.azimlbl -text "Azimuth" -anchor se] +set keyazim [scale $keyfrm.azim -from -90 -to 90 -orient horizontal] + +set keyintlbl [label $keyfrm.intlbl -text "Intensity" -anchor se] +set keyint [scale $keyfrm.int -from 0 -to 2 -orient horizontal -res 0.05] + +grid $keylbl - -sticky news +grid $keywarmlbl $keywarm -sticky news +grid $keyintlbl $keyint -sticky news + +grid $keyelevlbl $keyelev -sticky news +grid $keyazimlbl $keyazim -sticky news + +# Fill Light Panel +set fillfrm [frame $root.fillfrm] +set filllbl [label $fillfrm.lbl -text "Fill Light" -anchor w -font $TitleFont] + +set fillwarmlbl [label $fillfrm.warmlbl -text "Warmth" -anchor se] +set fillwarm [scale $fillfrm.warm -from 0 -to 1 -res 0.01 -orient horizontal] + +set fillelevlbl [label $fillfrm.elevlbl -text "Elevation" -anchor se] +set fillelev [scale $fillfrm.elev -from -90 -to 10 -orient horizontal] + +set fillazimlbl [label $fillfrm.azimlbl -text "Azimuth" -anchor se] +set fillazim [scale $fillfrm.azim -from -90 -to 90 -orient horizontal] + +set fillratlbl [label $fillfrm.ratlbl -text "K:F Ratio" -anchor se] +set fillrat [scale $fillfrm.rat -from 1 -to 15 -res 0.1 -orient horizontal] + +grid $filllbl - -sticky news +grid $fillwarmlbl $fillwarm -sticky news +grid $fillratlbl $fillrat -sticky news + +grid $fillelevlbl $fillelev -sticky news +grid $fillazimlbl $fillazim -sticky news + +# Back Light panel +set backfrm [frame $root.backfrm] +set backlbl [label $backfrm.lbl -text "Back Light" -anchor w -font $TitleFont] +set backwarmlbl [label $backfrm.warmlbl -text "Warmth" -anchor se] +set backwarm [scale $backfrm.warm -from 0 -to 1 -res 0.01 -orient horizontal] + +set backelevlbl [label $backfrm.elevlbl -text "Elevation" -anchor se] +set backelev [scale $backfrm.elev -from -45 -to 45 -orient horizontal] + +set backazimlbl [label $backfrm.azimlbl -text "Azimuth" -anchor se] +set backazim [scale $backfrm.azim -from 60 -to 170 -orient horizontal] + +set backratlbl [label $backfrm.ratlbl -text "K:B Ratio" -anchor se] +set backrat [scale $backfrm.rat -from 1 -to 15 -res 0.1 -orient horizontal] + +grid $backlbl - -sticky news +grid $backwarmlbl $backwarm -sticky news +grid $backratlbl $backrat -sticky news + +grid $backelevlbl $backelev -sticky news +grid $backazimlbl $backazim -sticky news + +# HeadLight panel +set headfrm [frame $root.headfrm] +set headlbl [label $headfrm.lbl -text "Head Light" -anchor w -font $TitleFont] +set headwarmlbl [label $headfrm.warmlbl -text "Warmth" -anchor se] +set headwarm [scale $headfrm.warm -from 0 -to 1 -res 0.01 -orient horizontal] + +set headratlbl [label $headfrm.ratlbl -text "K:H Ratio" -anchor se] +set headrat [scale $headfrm.rat -from 1 -to 15 -res 0.1 -orient horizontal] + + +set f1 [canvas $headfrm.f1 -border 1 -relief raised -width 0 -height 0] +set f2 [canvas $headfrm.f2 -border 1 -relief raised -width 0 -height 0] + +set maintlumlbl [label $headfrm.maintlumlbl -text "Maintain Luminance" -anchor w -font $TitleFont] +set maintlum [checkbutton $headfrm.maintlum -variable MaintainLuminance] + +set butfrm [frame $headfrm.butfrm] +set helpbut [button $butfrm.helpbut -text "Help" -command showHelp] +set quitbut [button $butfrm.quitbut -text "Quit" -command exit] +pack $helpbut -side left -expand true -fill x +pack $quitbut -side right -expand true -fill x + +grid $headlbl - -sticky nw +grid $headwarmlbl $headwarm -sticky news +grid $headratlbl $headrat -sticky news +grid $f1 - -sticky ew +grid $maintlumlbl - -sticky news +grid $maintlum - -sticky news +grid $f2 - -sticky ew +grid $butfrm - -sticky ew +grid [frame $headfrm.f0] -sticky news + +grid rowconfigure $headfrm 7 -weight 1 + +set f0 [canvas $root.f0 -border 1 -relief raised -width 0 -height 0] +set f1 [canvas $root.f1 -border 1 -relief raised -width 0 -height 0] +set f2 [canvas $root.f2 -border 1 -relief raised -width 0 -height 0] +set f3 [canvas $root.f3 -border 1 -relief raised -width 0 -height 0] + + +grid $renWidget - - - - - - -sticky news +grid $keyfrm $f0 $fillfrm $f1 $backfrm $f2 $headfrm -sticky news + +vtkSuperquadricSource squad + squad SetPhiResolution 20 + squad SetThetaResolution 25 +squad SetPhiRoundness 1.5 +squad SetThickness 0.43 +squad SetThetaRoundness 0.7 +squad ToroidalOn + +vtkAppendPolyData appendSquads + appendSquads AddInput [squad GetOutput] + +vtkPolyDataMapper mapper + mapper SetInputConnection [squad GetOutputPort] + mapper ScalarVisibilityOff + +vtkActor actor + actor SetMapper mapper + eval [actor GetProperty] SetDiffuseColor 1 1 1 + eval [actor GetProperty] SetSpecularColor 1 1 1 + eval [actor GetProperty] SetSpecularPower 20 + eval [actor GetProperty] SetSpecular 0.4 + eval [actor GetProperty] SetDiffuse 0.7 + +ren1 AddActor actor +ren1 SetBackground 0.1 0.1 0.15 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +[ren1 GetActiveCamera] Elevation 40 +[ren1 GetActiveCamera] Azimuth -20 + +proc SetLightWarmth {lt x} { + lightKit Set${lt}LightWarmth $x + renWin Render +} + +proc SetHeadLightWarmth {x} { + lightKit SetHeadLightWarmth $x + renWin Render +} + +proc SetLightElevation {lt x} { + lightKit Set${lt}LightElevation $x + renWin Render +} + +proc SetLightAzimuth {lt x} { + lightKit Set${lt}LightAzimuth $x + renWin Render +} + +proc SetKeyToFillRatio {x} { + lightKit SetKeyToFillRatio $x + renWin Render +} + +proc SetKeyToBackRatio {x} { + lightKit SetKeyToBackRatio $x + renWin Render +} + +proc SetKeyToHeadRatio {x} { + lightKit SetKeyToHeadRatio $x + renWin Render +} + +proc SetKeyLightIntensity {x} { + lightKit SetKeyLightIntensity $x + renWin Render +} + +proc SetMaintainLuminance {} { + global MaintainLuminance + lightKit SetMaintainLuminance $MaintainLuminance + renWin Render +} + +# get defaults directly from the LightKit + +$keywarm set [lightKit GetKeyLightWarmth] +$keyelev set [lightKit GetKeyLightElevation] +$keyazim set [lightKit GetKeyLightAzimuth] +$keyint set [lightKit GetKeyLightIntensity] + +$fillwarm set [lightKit GetFillLightWarmth] +$fillelev set [lightKit GetFillLightElevation] +$fillazim set [lightKit GetFillLightAzimuth] +$fillrat set [lightKit GetKeyToFillRatio] + +$backwarm set [lightKit GetBackLightWarmth] +$backrat set [lightKit GetKeyToBackRatio] +$backelev set [lightKit GetBackLightElevation] +$backazim set [lightKit GetBackLightAzimuth] + +$headwarm set [lightKit GetHeadLightWarmth] +$headrat set [lightKit GetKeyToHeadRatio] + +set MaintainLuminance [lightKit GetMaintainLuminance] + +$keywarm config -command "SetLightWarmth Key" +$keyelev config -command "SetLightElevation Key" +$keyazim config -command "SetLightAzimuth Key" +$keyint config -command "SetKeyLightIntensity" + +$fillwarm config -command "SetLightWarmth Fill" +$fillelev config -command "SetLightElevation Fill" +$fillazim config -command "SetLightAzimuth Fill" +$fillrat config -command "SetKeyToFillRatio" + +$backwarm config -command "SetLightWarmth Back" +$backrat config -command "SetKeyToBackRatio" +$backelev config -command "SetLightElevation Back" +$backazim config -command "SetLightAzimuth Back" + +$headwarm config -command "SetHeadLightWarmth" +$headrat config -command "SetKeyToHeadRatio" + +$maintlum config -command SetMaintainLuminance + +proc showHelp {} { + +set helpfrm .helpfrm + +if {[winfo exists $helpfrm]} { + wm deiconify $helpfrm + raise $helpfrm + return +} + +toplevel $helpfrm +wm title $helpfrm "Help for LightKitViewer" +set msg [label $helpfrm.msg -justify left \ + -wraplength 350 -font {-weight normal -family Helvetica}] +$msg config -text \ +{The key light is the dominant light in the scene, located in front of\ +and above the object. The fill light is usually positioned to shine\ +on the parts of the object not illuminated by the key light. The headlight\ +reduces the contrast of the scene by shining from the camera position. + +Fill, back, and headlights are dimmer than the key light; K:F K:B and K:H \ +control the key-to-fill, key-to-back and key-to-headlight intensity\ +respectively. The key light intensity, in effect, controls the entire\ +scene brightness level. + +Lights always shine on the point where the camera looking, but their angles\ +can be adjusted. The position of the key, back, and fill lights are \ +controlled by their elevation (latitude) and azimuth (longitude) \ +expressed in degrees. Both angles are specified with respect to the camera.\ +(elevation=0, azimuth=0) is located at the camera (a headlight).\ +(elevation=90, azimuth=0) is directly over the object\ +shining down. Negative azimuth angles position a light to the left of the\ +camera, positive values right. + +The back light is actually two lights, one on the left and one on the\ +right. The two lights have the same elevation, but opposite azimuth.\ +When you adjust the angle of the back light, both lights are moved\ +automatically for you. + +The warmth parameter controls the color of the lights: 0.5 is white, 0 is\ +cold blue, and 1 is deep sunset red. Use extreme colors with restraint. + +If MaintainLuminance is set, the\ +brightness of the lights is scaled to compensate for their reduced\ +perceptual brightness.} + +pack $msg -ipadx 5 -ipady 5 +} + +update + + diff --git a/Examples/Rendering/Tcl/RenderLargeImage.tcl b/Examples/Rendering/Tcl/RenderLargeImage.tcl new file mode 100644 index 0000000..1b9d9d7 --- /dev/null +++ b/Examples/Rendering/Tcl/RenderLargeImage.tcl @@ -0,0 +1,63 @@ +# +# This simple example shows how to render a very large image (i.e., one +# that cannot fit on the screen). +# + +# We start off by loading some Tcl modules. One is the basic VTK library; +# the second is a package for rendering, and the last includes a set +# of color definitions. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# We'll import some data to start. Since we are using an importer, we've +# got to give it a render window and such. Note that the render window +# size is set fairly small. +vtkRenderer ren + ren SetBackground 0.1 0.2 0.4 +vtkRenderWindow renWin + renWin AddRenderer ren + renWin SetSize 125 125 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtk3DSImporter importer + importer SetRenderWindow renWin + importer SetFileName "$VTK_DATA_ROOT/Data/Viewpoint/iflamigm.3ds" + importer ComputeNormalsOn + importer Read + +# We'll set up the view we want. +# +[ren GetActiveCamera] SetPosition 0 1 0 +[ren GetActiveCamera] SetFocalPoint 0 0 0 +[ren GetActiveCamera] SetViewUp 0 0 1 + +# Let the renderer compute a good position and focal point. +# +ren ResetCamera +[ren GetActiveCamera] Dolly 1.4 +ren ResetCameraClippingRange + +# render the large image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +wm withdraw . + +# Here we request that the large image is four times bigger than the +# renderers image. +# +vtkRenderLargeImage renderLarge + renderLarge SetInput ren + renderLarge SetMagnification 4 + +# We write out the image which causes the rendering to occur. If you +# watch your screen you will see the pieces being rendered right after +# one another. +# +vtkTIFFWriter writer + writer SetInputConnection [renderLarge GetOutputPort] + writer SetFileName largeImage.tif + writer Write + diff --git a/Examples/Rendering/Tcl/TPlane.tcl b/Examples/Rendering/Tcl/TPlane.tcl new file mode 100644 index 0000000..cf908c7 --- /dev/null +++ b/Examples/Rendering/Tcl/TPlane.tcl @@ -0,0 +1,59 @@ +# +# This simple example shows how to do basic texture mapping. +# +# We start off by loading some Tcl modules. One is the basic VTK library; +# the other is a package for rendering. +# +package require vtk +package require vtkinteraction + +# Load in the texture map. A texture is any unsigned char image. If it +# is not of this type, you will have to map it through a lookup table +# or by using vtkImageShiftScale. +# +vtkBMPReader bmpReader + bmpReader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" +vtkTexture atext + atext SetInputConnection [bmpReader GetOutputPort] + atext InterpolateOn + +# Create a plane source and actor. The vtkPlanesSource generates +# texture coordinates. +# +vtkPlaneSource plane +vtkPolyDataMapper planeMapper + planeMapper SetInputConnection [plane GetOutputPort] +vtkActor planeActor + planeActor SetMapper planeMapper + planeActor SetTexture atext + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor planeActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 500 500 + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Elevation -30 +$cam1 Roll -20 +ren1 ResetCameraClippingRange +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + diff --git a/Examples/Rendering/Tcl/assembly.tcl b/Examples/Rendering/Tcl/assembly.tcl new file mode 100644 index 0000000..ba8cc56 --- /dev/null +++ b/Examples/Rendering/Tcl/assembly.tcl @@ -0,0 +1,94 @@ +# This example demonstrates the use of vtkAssembly. In an assembly, the motion +# of one actor affects the position of other actors. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# Create four parts: a top level assembly (in this case, a vtkCylinder) +# and three primitives (using vtkSphereSource, vtkCubeSource, and +# vtkConeSource). Set up mappers and actors for each part of the assembly to +# carry information about material properties and associated geometry. +# +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +vtkActor sphereActor + sphereActor SetMapper sphereMapper + sphereActor SetOrigin 2 1 3 + sphereActor RotateY 6 + sphereActor SetPosition 2.25 0 0 + [sphereActor GetProperty] SetColor 1 0 1 + +vtkCubeSource cube +vtkPolyDataMapper cubeMapper + cubeMapper SetInputConnection [cube GetOutputPort] +vtkActor cubeActor + cubeActor SetMapper cubeMapper + cubeActor SetPosition 0.0 .25 0 + [cubeActor GetProperty] SetColor 0 0 1 + +vtkConeSource cone +vtkPolyDataMapper coneMapper + coneMapper SetInputConnection [cone GetOutputPort] +vtkActor coneActor + coneActor SetMapper coneMapper + coneActor SetPosition 0 0 .25 + [coneActor GetProperty] SetColor 0 1 0 + +# top part of the assembly +vtkCylinderSource cylinder; +vtkPolyDataMapper cylinderMapper + cylinderMapper SetInputConnection [cylinder GetOutputPort] + cylinderMapper SetResolveCoincidentTopologyToPolygonOffset +vtkActor cylinderActor + cylinderActor SetMapper cylinderMapper + [cylinderActor GetProperty] SetColor 1 0 0 + +# Create the assembly and add the 4 parts to it. Also set the origin, position +# and orientation in space. +vtkAssembly assembly + assembly AddPart cylinderActor + assembly AddPart sphereActor + assembly AddPart cubeActor + assembly AddPart coneActor + assembly SetOrigin 5 10 15 + assembly AddPosition 5 0 0 + assembly RotateX 15 + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor assembly +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 200 200 + +# Set up the camera to get a particular view of the scene +vtkCamera camera + camera SetClippingRange 21.9464 30.0179 + camera SetFocalPoint 3.49221 2.28844 -0.970866 + camera SetPosition 3.49221 2.28844 24.5216 + camera SetViewAngle 30 + camera SetViewUp 0 1 0 +ren1 SetActiveCamera camera + +# Set the user method (bound to key 'u') +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# Withdraw the default tk window +wm withdraw . + + diff --git a/Examples/Rendering/Tcl/keyBottle.tcl b/Examples/Rendering/Tcl/keyBottle.tcl new file mode 100644 index 0000000..fbf7cab --- /dev/null +++ b/Examples/Rendering/Tcl/keyBottle.tcl @@ -0,0 +1,120 @@ +# This example demonstrates keyframe animation. It changes the +# camera's azimuth by interpolating given azimuth values (using splines) + +package require vtk + +# Get keyframe procs +# See KeyFrame.tcl for details. +source KeyFrame.tcl + +# Reduce the number of frames if this example +# is taking too long +set NumberOfFrames 1200 + +# Create bottle profile. This is the object to be rendered. +vtkPoints points +points InsertPoint 0 0.01 0.0 0.0 +points InsertPoint 1 1.5 0.0 0.0 +points InsertPoint 2 1.5 0.0 3.5 +points InsertPoint 3 1.25 0.0 3.75 +points InsertPoint 4 0.75 0.0 4.00 +points InsertPoint 5 0.6 0.0 4.35 +points InsertPoint 6 0.7 0.0 4.65 +points InsertPoint 7 1.0 0.0 4.75 +points InsertPoint 8 1.0 0.0 5.0 +points InsertPoint 9 0.01 0.0 5.0 + +vtkCellArray lines +lines InsertNextCell 10;#number of points +lines InsertCellPoint 0 +lines InsertCellPoint 1 +lines InsertCellPoint 2 +lines InsertCellPoint 3 +lines InsertCellPoint 4 +lines InsertCellPoint 5 +lines InsertCellPoint 6 +lines InsertCellPoint 7 +lines InsertCellPoint 8 +lines InsertCellPoint 9 + +vtkPolyData profile +profile SetPoints points +profile SetLines lines + +# Extrude profile to make bottle +vtkRotationalExtrusionFilter extrude +extrude SetInput profile +extrude SetResolution 60 + +vtkPolyDataMapper map +map SetInputConnection [extrude GetOutputPort] + +vtkActor bottle +bottle SetMapper map +[bottle GetProperty] SetColor 0.3800 0.7000 0.1600 + +# Create the RenderWindow, Renderer +vtkRenderer ren1 +vtkRenderWindow renWin +renWin AddRenderer ren1 + +# Add the actor to the renderer, set the background and size# +ren1 AddActor bottle +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +# First render, forces the renderer to create a camera with a +# good initial position +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# Initialize keyframe recording by passing the camera object +# and the method used to change the position +set camera [ren1 GetActiveCamera] +KeyNew Azimuth $camera SetPosition + +# Define the key frames. +# This is done by changing the position of the camera with +# $camera Azimuth and recording it with KeyAdd +# This is far simpler than calculating the new position by hand. +KeyAdd Azimuth [$camera GetPosition] +$camera Azimuth 1 +KeyAdd Azimuth [$camera GetPosition] +$camera Azimuth 2 +KeyAdd Azimuth [$camera GetPosition] +for {set i 0} {$i <= 36} {incr i} { + $camera Azimuth 10 + KeyAdd Azimuth [$camera GetPosition] +} +$camera Azimuth 2 +KeyAdd Azimuth [$camera GetPosition] +$camera Azimuth 1 +KeyAdd Azimuth [$camera GetPosition] + +$camera Azimuth 0 +KeyAdd Azimuth [$camera GetPosition] + +$camera Azimuth -1 +KeyAdd Azimuth [$camera GetPosition] +$camera Azimuth -2 +KeyAdd Azimuth [$camera GetPosition] +for {set i 0} {$i <= 36} {incr i} { + $camera Azimuth -10 + KeyAdd Azimuth [$camera GetPosition] +} +$camera Azimuth -2 +KeyAdd Azimuth [$camera GetPosition] +$camera Azimuth -1 +KeyAdd Azimuth [$camera GetPosition] + +# Run the animation - NumberOfFrames frames - +# using interpolation +KeyRun Azimuth $NumberOfFrames + +# Clean-up and exit +vtkCommand DeleteAllObjects +exit + + + diff --git a/Examples/Rendering/Tcl/rainbow.tcl b/Examples/Rendering/Tcl/rainbow.tcl new file mode 100644 index 0000000..5a9d29a --- /dev/null +++ b/Examples/Rendering/Tcl/rainbow.tcl @@ -0,0 +1,105 @@ +# This example demonstrates the use and manipulation of lookup tables. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. The vtktesting package includes a +# predefined set of colors. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# First create pipeline a simple pipeline that reads a structure grid +# and then extracts a plane from the grid. The plane will be colored +# differently by using different lookup tables. +# +# Note: the Update method is manually invoked because it causes the +# reader to read; later on we use the output of the reader to set +# a range for the scalar values. +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +vtkStructuredGridGeometryFilter plane + plane SetInputConnection [pl3d GetOutputPort] + plane SetExtent 1 100 1 100 7 7 +vtkLookupTable lut +vtkPolyDataMapper planeMapper + planeMapper SetLookupTable lut + planeMapper SetInputConnection [plane GetOutputPort] + eval planeMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor planeActor + planeActor SetMapper planeMapper + +# This creates an outline around the data. +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Much of the following is commented out. To try different lookup tables, +# uncommented the appropriate portions. +# + +# This creates a black to white lut. +# lut SetHueRange 0 0 +# lut SetSaturationRange 0 0 +# lut SetValueRange 0.2 1.0 + +# This creates a red to blue lut. +# lut SetHueRange 0.0 0.667 + +# This creates a blue to red lut. +# lut SetHueRange 0.667 0.0 + +# This creates a wierd effect. The Build() method causes the lookup table +# to allocate memory and create a table based on the currect hue, saturation, +# value, and alpha (transparency) range. Here we then manually overwrite the +# values generated by the Build() method. +lut SetNumberOfColors 256 +lut Build +for {set i 0} {$i<16} {incr i 1} { + eval lut SetTableValue [expr $i*16] $red 1 + eval lut SetTableValue [expr $i*16+1] $green 1 + eval lut SetTableValue [expr $i*16+2] $blue 1 + eval lut SetTableValue [expr $i*16+3] $black 1 +} + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor + +ren1 SetBackground 0.1 0.2 0.4 +ren1 TwoSidedLightingOff + +renWin SetSize 250 250 + +iren Initialize + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 8.88908 0.595038 29.3342 +$cam1 SetPosition -12.3332 31.7479 41.2387 +$cam1 SetViewUp 0.060772 -0.319905 0.945498 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/Tutorial/README.txt b/Examples/Tutorial/README.txt new file mode 100644 index 0000000..da59a8a --- /dev/null +++ b/Examples/Tutorial/README.txt @@ -0,0 +1,19 @@ +These examples demonstrate some basic VTK concepts. They are organized in +increasing order of complexity. These examples are described in more detail +in the textbook "The Visualization Toolkit An Object-Oriented Approach to 3D +Graphics" Third Edition available for purchase from Kitware. The examples are +implemented in the programming languages C++, Tcl, Python, and Java. (Note: +in order to use Tcl, Python, and/or Java, you will need to compile with +wrapping on.) + +Step1 - A "Hello World" style example of a simple visualization pipeline +Step2 - Adding observers to Step1 (i.e., processing events) +Step3 - Rendering with multiple renderers +Step4 - Modifying properties and transformations +Step5 - Specifying a particular interaction style +Step6 - Adding a 3D widget + +Once you finish this mini-tutorial, you may wish to explore the other +VTK/Examples/ subdirectories. In particular, the VTK/Examples/Rendering +and VTK/Examples/VisualizationAlgorithms are worth exploring. The +subdirectory VTK/Examples/GUI has other 3D widget examples. \ No newline at end of file diff --git a/Examples/Tutorial/Step1/Cxx/CMakeLists.txt b/Examples/Tutorial/Step1/Cxx/CMakeLists.txt new file mode 100644 index 0000000..9adae3b --- /dev/null +++ b/Examples/Tutorial/Step1/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (Step1) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Cone Cone.cxx) +TARGET_LINK_LIBRARIES(Cone vtkRendering) diff --git a/Examples/Tutorial/Step1/Cxx/Cone.cxx b/Examples/Tutorial/Step1/Cxx/Cone.cxx new file mode 100644 index 0000000..8192727 --- /dev/null +++ b/Examples/Tutorial/Step1/Cxx/Cone.cxx @@ -0,0 +1,107 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cone.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example creates a polygonal model of a cone, and then renders it to +// the screen. It will rotate the cone 360 degrees and then exit. The basic +// setup of source -> mapper -> actor -> renderer -> renderwindow is +// typical of most VTK programs. +// + +// First include the required header files for the VTK classes we are using. +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkCamera.h" +#include "vtkActor.h" +#include "vtkRenderer.h" + +int main() +{ + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces data + // (output type is vtkPolyData) which other filters may process. + // + vtkConeSource *cone = vtkConeSource::New(); + cone->SetHeight( 3.0 ); + cone->SetRadius( 1.0 ); + cone->SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New(); + coneMapper->SetInputConnection( cone->GetOutputPort() ); + + // + // Create an actor to represent the cone. The actor orchestrates rendering + // of the mapper's graphics primitives. An actor also refers to properties + // via a vtkProperty instance, and includes an internal transformation + // matrix. We set this actor's mapper to be coneMapper which we created + // above. + // + vtkActor *coneActor = vtkActor::New(); + coneActor->SetMapper( coneMapper ); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the background + // color here. + // + vtkRenderer *ren1= vtkRenderer::New(); + ren1->AddActor( coneActor ); + ren1->SetBackground( 0.1, 0.2, 0.4 ); + + // + // Finally we create the render window which will show up on the screen. + // We put our renderer into the render window using AddRenderer. We also + // set the size to be 300 pixels by 300. + // + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer( ren1 ); + renWin->SetSize( 300, 300 ); + + // + // Now we loop over 360 degreeees and render the cone each time. + // + int i; + for (i = 0; i < 360; ++i) + { + // render the image + renWin->Render(); + // rotate the active camera by one degree + ren1->GetActiveCamera()->Azimuth( 1 ); + } + + // + // Free up any objects we created. All instances in VTK are deleted by + // using the Delete() method. + // + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); + ren1->Delete(); + renWin->Delete(); + + return 0; +} + + diff --git a/Examples/Tutorial/Step1/Java/Cone.java b/Examples/Tutorial/Step1/Java/Cone.java new file mode 100644 index 0000000..83c9296 --- /dev/null +++ b/Examples/Tutorial/Step1/Java/Cone.java @@ -0,0 +1,91 @@ +// +// This example creates a polygonal model of a cone, and then renders it to +// the screen. It will rotate the cone 360 degrees and then exit. The basic +// setup of source -> mapper -> actor -> renderer -> renderwindow is +// typical of most VTK programs. +// + +// We import the vtk wrapped classes first. +import vtk.*; + +// Then we define our class. +public class Cone { + + // In the static contructor we load in the native code. + // The libraries must be in your path to work. + static { + System.loadLibrary("vtkCommonJava"); + System.loadLibrary("vtkFilteringJava"); + System.loadLibrary("vtkIOJava"); + System.loadLibrary("vtkImagingJava"); + System.loadLibrary("vtkGraphicsJava"); + System.loadLibrary("vtkRenderingJava"); + } + + // now the main program + public static void main (String []args) { + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces data + // (output type is vtkPolyData) which other filters may process. + // + vtkConeSource cone = new vtkConeSource(); + cone.SetHeight( 3.0 ); + cone.SetRadius( 1.0 ); + cone.SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInputConnection( cone.GetOutputPort() ); + + // + // Create an actor to represent the cone. The actor orchestrates rendering + // of the mapper's graphics primitives. An actor also refers to properties + // via a vtkProperty instance, and includes an internal transformation + // matrix. We set this actor's mapper to be coneMapper which we created + // above. + // + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper( coneMapper ); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the background + // color here + // + vtkRenderer ren1 = new vtkRenderer(); + ren1.AddActor( coneActor ); + ren1.SetBackground( 0.1, 0.2, 0.4 ); + + // + // Finally we create the render window which will show up on the screen + // We put our renderer into the render window using AddRenderer. We also + // set the size to be 300 pixels by 300 + // + vtkRenderWindow renWin = new vtkRenderWindow(); + renWin.AddRenderer( ren1 ); + renWin.SetSize( 300, 300 ); + + // + // now we loop over 360 degreeees and render the cone each time + // + int i; + for (i = 0; i < 360; ++i) + { + // render the image + renWin.Render(); + // rotate the active camera by one degree + ren1.GetActiveCamera().Azimuth( 1 ); + } + + } +} + diff --git a/Examples/Tutorial/Step1/Python/Cone.py b/Examples/Tutorial/Step1/Python/Cone.py new file mode 100644 index 0000000..2d7c9a5 --- /dev/null +++ b/Examples/Tutorial/Step1/Python/Cone.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# This example creates a polygonal model of a cone, and then renders it to +# the screen. It will rotate the cone 360 degrees and then exit. The basic +# setup of source -> mapper -> actor -> renderer -> renderwindow is +# typical of most VTK programs. +# + +# +# First we include the VTK Python packages that will make available +# all of the VTK commands to Python. +# +import vtk +import time + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +cone = vtk.vtkConeSource() +cone.SetHeight( 3.0 ) +cone.SetRadius( 1.0 ) +cone.SetResolution( 10 ) + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection( cone.GetOutputPort() ) + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +coneActor = vtk.vtkActor() +coneActor.SetMapper( coneMapper ) + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is +# responsible for drawing the actors it has. We also set the background +# color here +# +ren1= vtk.vtkRenderer() +ren1.AddActor( coneActor ) +ren1.SetBackground( 0.1, 0.2, 0.4 ) + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300 +# +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren1 ) +renWin.SetSize( 300, 300 ) + +# +# now we loop over 360 degreeees and render the cone each time +# +for i in range(0,360): + time.sleep(0.03) + + renWin.Render() + ren1.GetActiveCamera().Azimuth( 1 ) diff --git a/Examples/Tutorial/Step1/Tcl/Cone.tcl b/Examples/Tutorial/Step1/Tcl/Cone.tcl new file mode 100644 index 0000000..fd8dbb8 --- /dev/null +++ b/Examples/Tutorial/Step1/Tcl/Cone.tcl @@ -0,0 +1,84 @@ +# +# This example creates a polygonal model of a cone, and then renders it to +# the screen. It will rotate the cone 360 degrees and then exit. The basic +# setup of source -> mapper -> actor -> renderer -> renderwindow is +# typical of most VTK programs. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the VTK commands to Tcl. +# +package require vtk + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +vtkActor coneActor +coneActor SetMapper coneMapper + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300. +# +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +# +# Now we loop over 360 degreeees and render the cone each time. +# +for {set i 0} {$i < 360} {incr i} { + after 10 + # render the image + renWin Render + # rotate the active camera by one degree + [ren1 GetActiveCamera] Azimuth 1 +} + +# +# Free up any objects we created. +# +vtkCommand DeleteAllObjects + +# +# Exit the application. +# +exit + + + diff --git a/Examples/Tutorial/Step2/Cxx/CMakeLists.txt b/Examples/Tutorial/Step2/Cxx/CMakeLists.txt new file mode 100644 index 0000000..af46b3b --- /dev/null +++ b/Examples/Tutorial/Step2/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (Step2) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Cone2 Cone2.cxx) +TARGET_LINK_LIBRARIES(Cone2 vtkRendering) diff --git a/Examples/Tutorial/Step2/Cxx/Cone2.cxx b/Examples/Tutorial/Step2/Cxx/Cone2.cxx new file mode 100644 index 0000000..6f4a33c --- /dev/null +++ b/Examples/Tutorial/Step2/Cxx/Cone2.cxx @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cone2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example shows how to add an observer to a C++ program. It extends +// the Step1/Cxx/Cone.cxx C++ example (see that example for information on +// the basic setup). +// +// VTK uses a command/observer design pattern. That is, observers watch for +// particular events that any vtkObject (or subclass) may invoke on +// itself. For example, the vtkRenderer invokes a "StartEvent" as it begins +// to render. Here we add an observer that invokes a command when this event +// is observed. +// + +// first include the required header files for the vtk classes we are using +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkCommand.h" +#include "vtkCamera.h" +#include "vtkActor.h" +#include "vtkRenderer.h" + +// Callback for the interaction +class vtkMyCallback : public vtkCommand +{ +public: + static vtkMyCallback *New() + { return new vtkMyCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkRenderer *renderer = reinterpret_cast(caller); + cout << renderer->GetActiveCamera()->GetPosition()[0] << " " + << renderer->GetActiveCamera()->GetPosition()[1] << " " + << renderer->GetActiveCamera()->GetPosition()[2] << "\n"; + } +}; + +int main() +{ + // + // The pipeline creation is documented in Step1 + // + vtkConeSource *cone = vtkConeSource::New(); + cone->SetHeight( 3.0 ); + cone->SetRadius( 1.0 ); + cone->SetResolution( 10 ); + + vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New(); + coneMapper->SetInputConnection( cone->GetOutputPort() ); + vtkActor *coneActor = vtkActor::New(); + coneActor->SetMapper( coneMapper ); + + vtkRenderer *ren1= vtkRenderer::New(); + ren1->AddActor( coneActor ); + ren1->SetBackground( 0.1, 0.2, 0.4 ); + ren1->ResetCamera(); + + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer( ren1 ); + renWin->SetSize( 300, 300 ); + + // Here is where we setup the observer, we do a new and ren1 will + // eventually free the observer + vtkMyCallback *mo1 = vtkMyCallback::New(); + ren1->AddObserver(vtkCommand::StartEvent,mo1); + mo1->Delete(); + + // + // now we loop over 360 degrees and render the cone each time + // + int i; + for (i = 0; i < 360; ++i) + { + // render the image + renWin->Render(); + // rotate the active camera by one degree + ren1->GetActiveCamera()->Azimuth( 1 ); + } + + // + // Free up any objects we created + // + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); + ren1->Delete(); + renWin->Delete(); + + return 0; +} + + diff --git a/Examples/Tutorial/Step2/Java/Cone2.java b/Examples/Tutorial/Step2/Java/Cone2.java new file mode 100644 index 0000000..70d2d89 --- /dev/null +++ b/Examples/Tutorial/Step2/Java/Cone2.java @@ -0,0 +1,82 @@ +// +// This example shows how to add an observer to a Java program. It extends +// the Step1/Java/Cone.java Java example (see that example for information on +// the basic setup). +// +// VTK uses a command/observer design pattern. That is, observers watch for +// particular events that any vtkObject (or subclass) may invoke on +// itself. For example, the vtkRenderer invokes a "StartEvent" as it begins +// to render. Here we add an observer that invokes a command when this event +// is observed. +// +// +// Show how to add an observer to the Cone example +// + +// we import the vtk wrapped classes forst +import vtk.*; + +// then we define our class +public class Cone2 { + // in the static contructor we load in the native code + // The libraries must be in your path to work + static { + System.loadLibrary("vtkCommonJava"); + System.loadLibrary("vtkFilteringJava"); + System.loadLibrary("vtkIOJava"); + System.loadLibrary("vtkImagingJava"); + System.loadLibrary("vtkGraphicsJava"); + System.loadLibrary("vtkRenderingJava"); + } + + // Define the callback + public void myCallback() + { + System.out.println("Starting a render"); + } + + // now the main program + public static void main (String []args) { + // + // Now we create the pipeline as usual, see Cone.java in Step1 for details + // + vtkConeSource cone = new vtkConeSource(); + cone.SetHeight( 3.0 ); + cone.SetRadius( 1.0 ); + cone.SetResolution( 10 ); + + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInputConnection( cone.GetOutputPort() ); + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper( coneMapper ); + + vtkRenderer ren1 = new vtkRenderer(); + ren1.AddActor( coneActor ); + ren1.SetBackground( 0.1, 0.2, 0.4 ); + + // Add the observer here, the first argument is the event name + // the second argument is the instance to invoke the method on + // the third argument is which method to invoke + Cone2 me = new Cone2(); + ren1.AddObserver("StartEvent",me,"myCallback"); + + // setup the window + vtkRenderWindow renWin = new vtkRenderWindow(); + renWin.AddRenderer( ren1 ); + renWin.SetSize( 300, 300 ); + + // + // now we loop over 360 degreeees and render the cone each time + // + int i; + for (i = 0; i < 360; ++i) + { + // render the image + renWin.Render(); + // rotate the active camera by one degree + ren1.GetActiveCamera().Azimuth( 1 ); + } + + } +} + diff --git a/Examples/Tutorial/Step2/Python/Cone2.py b/Examples/Tutorial/Step2/Python/Cone2.py new file mode 100644 index 0000000..ba38935 --- /dev/null +++ b/Examples/Tutorial/Step2/Python/Cone2.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# +# This example shows how to add an observer to a Python program. It extends +# the Step1/Python/Cone.py Python example (see that example for information on +# the basic setup). +# +# VTK uses a command/observer design pattern. That is, observers watch for +# particular events that any vtkObject (or subclass) may invoke on +# itself. For example, the vtkRenderer invokes a "StartEvent" as it begins +# to render. Here we add an observer that invokes a command when this event +# is observed. +# + +import vtk +import time + +# +# define the callback +# +def myCallback(obj,string): + print "Starting a render" + + +# +# create the basic pipeline as in Step1 +# +cone = vtk.vtkConeSource() +cone.SetHeight( 3.0 ) +cone.SetRadius( 1.0 ) +cone.SetResolution( 10 ) + +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection( cone.GetOutputPort() ) +coneActor = vtk.vtkActor() +coneActor.SetMapper( coneMapper ) + +ren1= vtk.vtkRenderer() +ren1.AddActor( coneActor ) +ren1.SetBackground( 0.1, 0.2, 0.4 ) + +# +# Add the observer here +# +ren1.AddObserver("StartEvent", myCallback) + +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren1 ) +renWin.SetSize( 300, 300 ) + +# +# now we loop over 360 degreeees and render the cone each time +# +for i in range(0,360): + time.sleep(0.03) + renWin.Render() + ren1.GetActiveCamera().Azimuth( 1 ) + diff --git a/Examples/Tutorial/Step2/Tcl/Cone2.tcl b/Examples/Tutorial/Step2/Tcl/Cone2.tcl new file mode 100644 index 0000000..5875978 --- /dev/null +++ b/Examples/Tutorial/Step2/Tcl/Cone2.tcl @@ -0,0 +1,72 @@ +# +# This example shows how to add an observer to a Tcl program. It extends +# the Step1/Tcl/Cone.tcl Tcl example (see that example for information on +# the basic setup). +# +# VTK uses a command/observer design pattern. That is, observers watch for +# particular events that any vtkObject (or subclass) may invoke on +# itself. For example, the vtkRenderer invokes a "StartEvent" as it begins +# to render. Here we add an observer that invokes a command when this event +# is observed. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk + +# +# Here we define our callback +# +proc myCallback {} { + puts "Starting to render" +} + +# +# Next we create the pipelinne +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] +vtkActor coneActor +coneActor SetMapper coneMapper + +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 + +# here we setup the callback +ren1 AddObserver StartEvent myCallback + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +# +# now we loop over 360 degreeees and render the cone each time +# +for {set i 0} {$i < 360} {incr i} { + after 10 + # render the image + renWin Render + # rotate the active camera by one degree + [ren1 GetActiveCamera] Azimuth 1 +} + +# +# Free up any objects we created +# +vtkCommand DeleteAllObjects + +# +# exit the application +# +exit + + + diff --git a/Examples/Tutorial/Step3/Cxx/CMakeLists.txt b/Examples/Tutorial/Step3/Cxx/CMakeLists.txt new file mode 100644 index 0000000..b1222fd --- /dev/null +++ b/Examples/Tutorial/Step3/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (Step3) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Cone3 Cone3.cxx) +TARGET_LINK_LIBRARIES(Cone3 vtkRendering) diff --git a/Examples/Tutorial/Step3/Cxx/Cone3.cxx b/Examples/Tutorial/Step3/Cxx/Cone3.cxx new file mode 100644 index 0000000..7a9e9ed --- /dev/null +++ b/Examples/Tutorial/Step3/Cxx/Cone3.cxx @@ -0,0 +1,121 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cone3.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example demonstrates how to use multiple renderers within a +// render window. It is a variation of the Cone.cxx example. Please +// refer to that example for additional documentation. +// + +// First include the required header files for the VTK classes we are using. +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkCamera.h" +#include "vtkActor.h" +#include "vtkRenderer.h" + +int main() +{ + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces data + // (output type is vtkPolyData) which other filters may process. + // + vtkConeSource *cone = vtkConeSource::New(); + cone->SetHeight( 3.0 ); + cone->SetRadius( 1.0 ); + cone->SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New(); + coneMapper->SetInputConnection( cone->GetOutputPort() ); + + // + // Create an actor to represent the cone. The actor orchestrates rendering + // of the mapper's graphics primitives. An actor also refers to properties + // via a vtkProperty instance, and includes an internal transformation + // matrix. We set this actor's mapper to be coneMapper which we created + // above. + // + vtkActor *coneActor = vtkActor::New(); + coneActor->SetMapper( coneMapper ); + + // + // Create two renderers and assign actors to them. A renderer renders into + // a viewport within the vtkRenderWindow. It is part or all of a window on + // the screen and it is responsible for drawing the actors it has. We also + // set the background color here. In this example we are adding the same + // actor to two different renderers; it is okay to add different actors to + // different renderers as well. + // + vtkRenderer *ren1= vtkRenderer::New(); + ren1->AddActor( coneActor ); + ren1->SetBackground( 0.1, 0.2, 0.4 ); + ren1->SetViewport(0.0, 0.0, 0.5, 1.0); + + vtkRenderer *ren2= vtkRenderer::New(); + ren2->AddActor( coneActor ); + ren2->SetBackground( 0.2, 0.3, 0.5 ); + ren2->SetViewport(0.5, 0.0, 1.0, 1.0); + + // + // Finally we create the render window which will show up on the screen. + // We put our renderer into the render window using AddRenderer. We also + // set the size to be 300 pixels by 300. + // + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer( ren1 ); + renWin->AddRenderer( ren2 ); + renWin->SetSize( 600, 300 ); + + // + // Make one view 90 degrees from other. + // + ren1->ResetCamera(); + ren1->GetActiveCamera()->Azimuth(90); + + // + // Now we loop over 360 degreeees and render the cone each time. + // + int i; + for (i = 0; i < 360; ++i) + { + // render the image + renWin->Render(); + // rotate the active camera by one degree + ren1->GetActiveCamera()->Azimuth( 1 ); + ren2->GetActiveCamera()->Azimuth( 1 ); + } + + // + // Free up any objects we created. All instances in VTK are deleted by + // using the Delete() method. + // + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); + ren1->Delete(); + ren2->Delete(); + renWin->Delete(); + + return 0; +} diff --git a/Examples/Tutorial/Step3/Java/Cone3.java b/Examples/Tutorial/Step3/Java/Cone3.java new file mode 100644 index 0000000..dc632c3 --- /dev/null +++ b/Examples/Tutorial/Step3/Java/Cone3.java @@ -0,0 +1,105 @@ +// +// This example demonstrates how to use multiple renderers within a +// render window. It is a variation of the Cone.py example. Please +// refer to that example for additional documentation. +// + +import java.lang.Thread; + +// we import the vtk wrapped classes forst +import vtk.*; + +// then we define our class +public class Cone3 { + // in the static contructor we load in the native code + // The libraries must be in your path to work + static { + System.loadLibrary("vtkCommonJava"); + System.loadLibrary("vtkFilteringJava"); + System.loadLibrary("vtkIOJava"); + System.loadLibrary("vtkImagingJava"); + System.loadLibrary("vtkGraphicsJava"); + System.loadLibrary("vtkRenderingJava"); + } + + // now the main program + public static void main (String []args) throws Exception { + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces + // data (output type is vtkPolyData) which other filters may process. + // + vtkConeSource cone = new vtkConeSource(); + cone.SetHeight( 3.0 ); + cone.SetRadius( 1.0 ); + cone.SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInputConnection(cone.GetOutputPort()); + + // + // Create an actor to represent the cone. The actor orchestrates rendering of + // the mapper's graphics primitives. An actor also refers to properties via a + // vtkProperty instance, and includes an internal transformation matrix. We + // set this actor's mapper to be coneMapper which we created above. + // + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper(coneMapper); + + // + // Create two renderers and assign actors to them. A renderer renders into a + // viewport within the vtkRenderWindow. It is part or all of a window on the + // screen and it is responsible for drawing the actors it has. We also set + // the background color here. In this example we are adding the same actor + // to two different renderers; it is okay to add different actors to + // different renderers as well. + // + vtkRenderer ren1 = new vtkRenderer(); + ren1.AddActor(coneActor); + ren1.SetBackground(0.1, 0.2, 0.4); + ren1.SetViewport(0.0, 0.0, 0.5, 1.0); + + vtkRenderer ren2 = new vtkRenderer(); + ren2.AddActor(coneActor); + ren2.SetBackground(0.1, 0.2, 0.4); + ren2.SetViewport(0.5, 0.0, 1.0, 1.0); + + // + // Finally we create the render window which will show up on the screen. + // We add our two renderers into the render window using AddRenderer. We also + // set the size to be 600 pixels by 300. + // + vtkRenderWindow renWin = new vtkRenderWindow(); + renWin.AddRenderer( ren1 ); + renWin.AddRenderer( ren2 ); + renWin.SetSize(600, 300); + + // + // Make one camera view 90 degrees from other. + // + ren1.ResetCamera(); + ren1.GetActiveCamera().Azimuth(90); + + // + // now we loop over 360 degreeees and render the cone each time + // + int i; + for (i = 0; i < 360; ++i) + { + Thread.sleep(10); + // render the image + renWin.Render(); + // rotate the active camera by one degree + ren1.GetActiveCamera().Azimuth( 1 ); + ren2.GetActiveCamera().Azimuth( 1 ); + } + } +} diff --git a/Examples/Tutorial/Step3/Python/Cone3.py b/Examples/Tutorial/Step3/Python/Cone3.py new file mode 100644 index 0000000..2783fa2 --- /dev/null +++ b/Examples/Tutorial/Step3/Python/Cone3.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# This example demonstrates how to use multiple renderers within a +# render window. It is a variation of the Cone.py example. Please +# refer to that example for additional documentation. +# + +import vtk +import time + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +cone = vtk.vtkConeSource() +cone.SetHeight( 3.0 ) +cone.SetRadius( 1.0 ) +cone.SetResolution( 10 ) + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +coneActor = vtk.vtkActor() +coneActor.SetMapper(coneMapper) + +# +# Create two renderers and assign actors to them. A renderer renders into a +# viewport within the vtkRenderWindow. It is part or all of a window on the +# screen and it is responsible for drawing the actors it has. We also set +# the background color here. In this example we are adding the same actor +# to two different renderers; it is okay to add different actors to +# different renderers as well. +# +ren1 = vtk.vtkRenderer() +ren1.AddActor(coneActor) +ren1.SetBackground(0.1, 0.2, 0.4) +ren1.SetViewport(0.0, 0.0, 0.5, 1.0) + +ren2 = vtk.vtkRenderer() +ren2.AddActor(coneActor) +ren2.SetBackground(0.1, 0.2, 0.4) +ren2.SetViewport(0.5, 0.0, 1.0, 1.0) + +# +# Finally we create the render window which will show up on the screen. +# We add our two renderers into the render window using AddRenderer. We also +# set the size to be 600 pixels by 300. +# +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren1 ) +renWin.AddRenderer( ren2 ) +renWin.SetSize(600, 300) + +# +# Make one camera view 90 degrees from other. +# +ren1.ResetCamera() +ren1.GetActiveCamera().Azimuth(90) + +# +# Now we loop over 360 degreeees and render the cone each time. +# +for i in range(0,360): + time.sleep(0.03) + + renWin.Render() + ren1.GetActiveCamera().Azimuth( 1 ) + ren2.GetActiveCamera().Azimuth( 1 ) diff --git a/Examples/Tutorial/Step3/Tcl/Cone3.tcl b/Examples/Tutorial/Step3/Tcl/Cone3.tcl new file mode 100644 index 0000000..f2660f1 --- /dev/null +++ b/Examples/Tutorial/Step3/Tcl/Cone3.tcl @@ -0,0 +1,97 @@ +# +# This example demonstrates how to use multiple renderers within a +# render window. It is a variation of the Cone.tcl example. Please +# refer to that example for additional documentation. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the VTK commands to Tcl. +# +package require vtk + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +vtkActor coneActor +coneActor SetMapper coneMapper + +# +# Create two renderers and assign actors to them. A renderer renders into a +# viewport within the vtkRenderWindow. It is part or all of a window on the +# screen and it is responsible for drawing the actors it has. We also set +# the background color here. In this example we are adding the same actor +# to two different renderers; it is okay to add different actors to +# different renderers as well. +# +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 +ren1 SetViewport 0.0 0.0 0.5 1.0 + +vtkRenderer ren2 +ren2 AddActor coneActor +ren2 SetBackground 0.1 0.2 0.4 +ren2 SetViewport 0.5 0.0 1.0 1.0 + +# +# Finally we create the render window which will show up on the screen. +# We add our two renderers into the render window using AddRenderer. We also +# set the size to be 600 pixels by 300. +# +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin AddRenderer ren2 +renWin SetSize 600 300 + +# +# Make one camera view 90 degrees from other. +# +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 90 + +# +# Now we loop over 360 degreeees and render the cone each time. +# +for {set i 0} {$i < 360} {incr i} { + after 10 + # render the image + renWin Render + # rotate the active camera by one degree + [ren1 GetActiveCamera] Azimuth 1 + [ren2 GetActiveCamera] Azimuth 1 +} + +# +# Free up any objects we created. +# +vtkCommand DeleteAllObjects + +# +# Exit the application. +# +exit diff --git a/Examples/Tutorial/Step4/Cxx/CMakeLists.txt b/Examples/Tutorial/Step4/Cxx/CMakeLists.txt new file mode 100644 index 0000000..93bea84 --- /dev/null +++ b/Examples/Tutorial/Step4/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (Step4) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Cone4 Cone4.cxx) +TARGET_LINK_LIBRARIES(Cone4 vtkRendering) diff --git a/Examples/Tutorial/Step4/Cxx/Cone4.cxx b/Examples/Tutorial/Step4/Cxx/Cone4.cxx new file mode 100644 index 0000000..7b22a4e --- /dev/null +++ b/Examples/Tutorial/Step4/Cxx/Cone4.cxx @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cone4.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example demonstrates the creation of multiple actors and the +// manipulation of their properties and transformations. It is a +// derivative of Cone.tcl, see that example for more information. +// + +// First include the required header files for the VTK classes we are using. +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkCamera.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkProperty.h" + +int main() +{ + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces data + // (output type is vtkPolyData) which other filters may process. + // + vtkConeSource *cone = vtkConeSource::New(); + cone->SetHeight( 3.0 ); + cone->SetRadius( 1.0 ); + cone->SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New(); + coneMapper->SetInputConnection( cone->GetOutputPort() ); + + // + // Create an actor to represent the first cone. The actor's properties are + // modified to give it different surface properties. By default, an actor + // is create with a property so the GetProperty() method can be used. + // + vtkActor *coneActor = vtkActor::New(); + coneActor->SetMapper( coneMapper ); + coneActor->GetProperty()->SetColor(0.2, 0.63, 0.79); + coneActor->GetProperty()->SetDiffuse(0.7); + coneActor->GetProperty()->SetSpecular(0.4); + coneActor->GetProperty()->SetSpecularPower(20); + + // + // Create a property and directly manipulate it. Assign it to the + // second actor. + // + vtkProperty *property = vtkProperty::New(); + property->SetColor(1.0, 0.3882, 0.2784); + property->SetDiffuse(0.7); + property->SetSpecular(0.4); + property->SetSpecularPower(20); + + // + // Create a second actor and a property. The property is directly + // manipulated and then assigned to the actor. In this way, a single + // property can be shared among many actors. Note also that we use the + // same mapper as the first actor did. This way we avoid duplicating + // geometry, which may save lots of memory if the geoemtry is large. + vtkActor *coneActor2 = vtkActor::New(); + coneActor2->SetMapper(coneMapper); + coneActor2->GetProperty()->SetColor(0.2, 0.63, 0.79); + coneActor2->SetProperty(property); + coneActor2->SetPosition(0, 2, 0); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the background + // color here. + // + vtkRenderer *ren1= vtkRenderer::New(); + ren1->AddActor( coneActor ); + ren1->AddActor( coneActor2 ); + ren1->SetBackground( 0.1, 0.2, 0.4 ); + + // + // Finally we create the render window which will show up on the screen. + // We put our renderer into the render window using AddRenderer. We also + // set the size to be 300 pixels by 300. + // + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer( ren1 ); + renWin->SetSize( 300, 300 ); + + // + // Now we loop over 360 degreeees and render the cone each time. + // + int i; + for (i = 0; i < 360; ++i) + { + // render the image + renWin->Render(); + // rotate the active camera by one degree + ren1->GetActiveCamera()->Azimuth( 1 ); + } + + // + // Free up any objects we created. All instances in VTK are deleted by + // using the Delete() method. + // + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); + property->Delete(); + coneActor2->Delete(); + ren1->Delete(); + renWin->Delete(); + + return 0; +} + + diff --git a/Examples/Tutorial/Step4/Java/Cone4.java b/Examples/Tutorial/Step4/Java/Cone4.java new file mode 100644 index 0000000..c5aa8cf --- /dev/null +++ b/Examples/Tutorial/Step4/Java/Cone4.java @@ -0,0 +1,122 @@ +// +// This example demonstrates the creation of multiple actors and the +// manipulation of their properties and transformations. It is a +// derivative of Cone.py, see that example for more information. +// + +import java.lang.Thread; + +// we import the vtk wrapped classes forst +import vtk.*; + +// then we define our class +public class Cone4 { + // in the static contructor we load in the native code + // The libraries must be in your path to work + static { + System.loadLibrary("vtkCommonJava"); + System.loadLibrary("vtkFilteringJava"); + System.loadLibrary("vtkIOJava"); + System.loadLibrary("vtkImagingJava"); + System.loadLibrary("vtkGraphicsJava"); + System.loadLibrary("vtkRenderingJava"); + } + + // now the main program + public static void main (String []args) throws Exception { + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces + // data (output type is vtkPolyData) which other filters may process. + // + vtkConeSource cone = new vtkConeSource(); + cone.SetHeight( 3.0 ); + cone.SetRadius( 1.0 ); + cone.SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInputConnection(cone.GetOutputPort()); + + // + // Create an actor to represent the first cone. The actor's properties are + // modified to give it different surface properties. By default, an actor + // is create with a property so the GetProperty() method can be used. + // + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper(coneMapper); + coneActor.GetProperty().SetColor(0.2, 0.63, 0.79); + coneActor.GetProperty().SetDiffuse(0.7); + coneActor.GetProperty().SetSpecular(0.4); + coneActor.GetProperty().SetSpecularPower(20); + + // + // Create a property and directly manipulate it. Assign it to the + // second actor. + // + vtkProperty property = new vtkProperty(); + property.SetColor(1.0, 0.3882, 0.2784); + property.SetDiffuse(0.7); + property.SetSpecular(0.4); + property.SetSpecularPower(20); + + // + // Create a second actor and a property. The property is directly + // manipulated and then assigned to the actor. In this way, a single + // property can be shared among many actors. Note also that we use the + // same mapper as the first actor did. This way we avoid duplicating + // geometry, which may save lots of memory if the geoemtry is large. + vtkActor coneActor2 = new vtkActor(); + coneActor2.SetMapper(coneMapper); + coneActor2.GetProperty().SetColor(0.2, 0.63, 0.79); + coneActor2.SetProperty(property); + coneActor2.SetPosition(0, 2, 0); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the + // background color here. + // + vtkRenderer ren1 = new vtkRenderer(); + ren1.AddActor(coneActor); + ren1.AddActor(coneActor2); + ren1.SetBackground(0.1, 0.2, 0.4); + + // + // Finally we create the render window which will show up on the screen. + // We add our two renderers into the render window using AddRenderer. We also + // set the size to be 600 pixels by 300. + // + vtkRenderWindow renWin = new vtkRenderWindow(); + renWin.AddRenderer( ren1 ); + renWin.SetSize(300, 300); + + // + // Make one camera view 90 degrees from other. + // + ren1.ResetCamera(); + ren1.GetActiveCamera().Azimuth(90); + + // + // now we loop over 360 degreeees and render the cone each time + // + int i; + for (i = 0; i < 360; ++i) + { + Thread.sleep(10); + // render the image + renWin.Render(); + // rotate the active camera by one degree + ren1.GetActiveCamera().Azimuth( 1 ); + } + } +} + diff --git a/Examples/Tutorial/Step4/Python/Cone4.py b/Examples/Tutorial/Step4/Python/Cone4.py new file mode 100644 index 0000000..0efd2ac --- /dev/null +++ b/Examples/Tutorial/Step4/Python/Cone4.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# +# This example demonstrates the creation of multiple actors and the +# manipulation of their properties and transformations. It is a +# derivative of Cone.py, see that example for more information. +# + +import vtk +import time + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +cone = vtk.vtkConeSource () +cone.SetHeight( 3.0 ) +cone.SetRadius( 1.0 ) +cone.SetResolution( 10 ) + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) + +# +# Create an actor to represent the first cone. The actor's properties are +# modified to give it different surface properties. By default, an actor +# is create with a property so the GetProperty() method can be used. +# +coneActor = vtk.vtkActor() +coneActor.SetMapper(coneMapper) +coneActor.GetProperty().SetColor(0.2, 0.63, 0.79) +coneActor.GetProperty().SetDiffuse(0.7) +coneActor.GetProperty().SetSpecular(0.4) +coneActor.GetProperty().SetSpecularPower(20) + +# +# Create a property and directly manipulate it. Assign it to the +# second actor. +# +property = vtk.vtkProperty() +property.SetColor(1.0, 0.3882, 0.2784) +property.SetDiffuse(0.7) +property.SetSpecular(0.4) +property.SetSpecularPower(20) + +# +# Create a second actor and a property. The property is directly +# manipulated and then assigned to the actor. In this way, a single +# property can be shared among many actors. Note also that we use the +# same mapper as the first actor did. This way we avoid duplicating +# geometry, which may save lots of memory if the geoemtry is large. +coneActor2 = vtk.vtkActor() +coneActor2.SetMapper(coneMapper) +coneActor2.GetProperty().SetColor(0.2, 0.63, 0.79) +coneActor2.SetProperty(property) +coneActor2.SetPosition(0, 2, 0) + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +ren1 = vtk.vtkRenderer() +ren1.AddActor(coneActor) +ren1.AddActor(coneActor2) +ren1.SetBackground(0.1, 0.2, 0.4) + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300. +# +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren1) +renWin.SetSize(300, 300) + +# +# Now we loop over 360 degreeees and render the cone each time. +# +for i in range(0,360): + time.sleep(0.03) + + renWin.Render() + ren1.GetActiveCamera().Azimuth( 1 ) + diff --git a/Examples/Tutorial/Step4/Tcl/Cone4.tcl b/Examples/Tutorial/Step4/Tcl/Cone4.tcl new file mode 100644 index 0000000..fd5116f --- /dev/null +++ b/Examples/Tutorial/Step4/Tcl/Cone4.tcl @@ -0,0 +1,109 @@ +# +# This example demonstrates the creation of multiple actors and the +# manipulation of their properties and transformations. It is a +# derivative of Cone.tcl, see that example for more information. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the VTK commands to Tcl. +# +package require vtk + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] + +# +# Create an actor to represent the first cone. The actor's properties are +# modified to give it different surface properties. By default, an actor +# is create with a property so the GetProperty() method can be used. +# +vtkActor coneActor +coneActor SetMapper coneMapper +[coneActor GetProperty] SetColor 0.2 0.63 0.79 +[coneActor GetProperty] SetDiffuse 0.7 +[coneActor GetProperty] SetSpecular 0.4 +[coneActor GetProperty] SetSpecularPower 20 + +# +# Create a property and directly manipulate it. Assign it to the +# second actor. +# +vtkProperty property +property SetColor 1.0 0.3882 0.2784 +property SetDiffuse 0.7 +property SetSpecular 0.4 +property SetSpecularPower 20 + +# +# Create a second actor and a property. The property is directly +# manipulated and then assigned to the actor. In this way, a single +# property can be shared among many actors. Note also that we use the +# same mapper as the first actor did. This way we avoid duplicating +# geometry, which may save lots of memory if the geoemtry is large. +vtkActor coneActor2 +coneActor2 SetMapper coneMapper +[coneActor2 GetProperty] SetColor 0.2 0.63 0.79 +coneActor2 SetProperty property +coneActor2 SetPosition 0 2 0 + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 AddActor coneActor2 +ren1 SetBackground 0.1 0.2 0.4 + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300. +# +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +# +# Now we loop over 360 degreeees and render the cone each time. +# +for {set i 0} {$i < 360} {incr i} { + after 10 + # render the image + renWin Render + # rotate the active camera by one degree + [ren1 GetActiveCamera] Azimuth 1 +} + +# +# Free up any objects we created. +# +vtkCommand DeleteAllObjects + +# +# Exit the application. +# +exit + + + diff --git a/Examples/Tutorial/Step5/Cxx/CMakeLists.txt b/Examples/Tutorial/Step5/Cxx/CMakeLists.txt new file mode 100644 index 0000000..c7bb2bb --- /dev/null +++ b/Examples/Tutorial/Step5/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (Step5) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Cone5 Cone5.cxx) +TARGET_LINK_LIBRARIES(Cone5 vtkRendering) diff --git a/Examples/Tutorial/Step5/Cxx/Cone5.cxx b/Examples/Tutorial/Step5/Cxx/Cone5.cxx new file mode 100644 index 0000000..67449e2 --- /dev/null +++ b/Examples/Tutorial/Step5/Cxx/Cone5.cxx @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cone5.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example introduces the concepts of interaction into the +// C++ environment. A different interaction style (than +// the default) is defined. +// + +// First include the required header files for the VTK classes we are using. +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkCamera.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkInteractorStyleTrackballCamera.h" + +int main() +{ + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces data + // (output type is vtkPolyData) which other filters may process. + // + vtkConeSource *cone = vtkConeSource::New(); + cone->SetHeight( 3.0 ); + cone->SetRadius( 1.0 ); + cone->SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New(); + coneMapper->SetInputConnection( cone->GetOutputPort() ); + + // + // Create an actor to represent the cone. The actor orchestrates rendering + // of the mapper's graphics primitives. An actor also refers to properties + // via a vtkProperty instance, and includes an internal transformation + // matrix. We set this actor's mapper to be coneMapper which we created + // above. + // + vtkActor *coneActor = vtkActor::New(); + coneActor->SetMapper( coneMapper ); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the background + // color here. + // + vtkRenderer *ren1= vtkRenderer::New(); + ren1->AddActor( coneActor ); + ren1->SetBackground( 0.1, 0.2, 0.4 ); + + // + // Finally we create the render window which will show up on the screen. + // We put our renderer into the render window using AddRenderer. We also + // set the size to be 300 pixels by 300. + // + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer( ren1 ); + renWin->SetSize( 300, 300 ); + + // + // The vtkRenderWindowInteractor class watches for events (e.g., keypress, + // mouse) in the vtkRenderWindow. These events are translated into + // event invocations that VTK understands (see VTK/Common/vtkCommand.h + // for all events that VTK processes). Then observers of these VTK + // events can process them as appropriate. + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // + // By default the vtkRenderWindowInteractor instantiates an instance + // of vtkInteractorStyle. vtkInteractorStyle translates a set of events + // it observes into operations on the camera, actors, and/or properties + // in the vtkRenderWindow associated with the vtkRenderWinodwInteractor. + // Here we specify a particular interactor style. + vtkInteractorStyleTrackballCamera *style = + vtkInteractorStyleTrackballCamera::New(); + iren->SetInteractorStyle(style); + + // + // Unlike the previous scripts where we performed some operations and then + // exited, here we leave an event loop running. The user can use the mouse + // and keyboard to perform the operations on the scene according to the + // current interaction style. When the user presses the "e" key, by default + // an ExitEvent is invoked by the vtkRenderWindowInteractor which is caught + // and drops out of the event loop (triggered by the Start() method that + // follows. + // + iren->Initialize(); + iren->Start(); + + // + // Final note: recall that an observers can watch for particular events and + // take appropriate action. Pressing "u" in the render window causes the + // vtkRenderWindowInteractor to invoke a UserEvent. This can be caught to + // popup a GUI, etc. So the Tcl Cone5.tcl example for an idea of how this + // works. + + // + // Free up any objects we created. All instances in VTK are deleted by + // using the Delete() method. + // + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); + ren1->Delete(); + renWin->Delete(); + iren->Delete(); + style->Delete(); + + return 0; +} + + diff --git a/Examples/Tutorial/Step5/Java/Cone5.java b/Examples/Tutorial/Step5/Java/Cone5.java new file mode 100644 index 0000000..0e278d9 --- /dev/null +++ b/Examples/Tutorial/Step5/Java/Cone5.java @@ -0,0 +1,117 @@ +// +// This example introduces the concepts of user interaction with VTK. +// First, a different interaction style (than the default) is defined. +// Second, the interaction is started. +// +// + +// we import the vtk wrapped classes forst +import vtk.*; + +// then we define our class +public class Cone5 { + // in the static contructor we load in the native code + // The libraries must be in your path to work + static { + System.loadLibrary("vtkCommonJava"); + System.loadLibrary("vtkFilteringJava"); + System.loadLibrary("vtkIOJava"); + System.loadLibrary("vtkImagingJava"); + System.loadLibrary("vtkGraphicsJava"); + System.loadLibrary("vtkRenderingJava"); + } + + // now the main program + public static void main (String []args) throws Exception { + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces + // data (output type is vtkPolyData) which other filters may process. + // + vtkConeSource cone = new vtkConeSource(); + cone.SetHeight( 3.0 ); + cone.SetRadius( 1.0 ); + cone.SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInputConnection(cone.GetOutputPort()); + + // + // Create an actor to represent the cone. The actor orchestrates rendering of + // the mapper's graphics primitives. An actor also refers to properties via a + // vtkProperty instance, and includes an internal transformation matrix. We + // set this actor's mapper to be coneMapper which we created above. + // + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper(coneMapper); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the + // background color here. + // + vtkRenderer ren1 = new vtkRenderer(); + ren1.AddActor(coneActor); + ren1.SetBackground(0.1, 0.2, 0.4); + + // + // Finally we create the render window which will show up on the screen. + // We add our two renderers into the render window using AddRenderer. We also + // set the size to be 600 pixels by 300. + // + vtkRenderWindow renWin = new vtkRenderWindow(); + renWin.AddRenderer( ren1 ); + renWin.SetSize(300, 300); + + // + // Make one camera view 90 degrees from other. + // + ren1.ResetCamera(); + ren1.GetActiveCamera().Azimuth(90); + + // + // The vtkRenderWindowInteractor class watches for events (e.g., keypress, + // mouse) in the vtkRenderWindow. These events are translated into event + // invocations that VTK understands (see VTK/Common/vtkCommand.h for all + // events that VTK processes). Then observers of these VTK events can + // process them as appropriate. + vtkRenderWindowInteractor iren = new vtkRenderWindowInteractor(); + iren.SetRenderWindow(renWin); + + // + // By default the vtkRenderWindowInteractor instantiates an instance + // of vtkInteractorStyle. vtkInteractorStyle translates a set of events + // it observes into operations on the camera, actors, and/or properties + // in the vtkRenderWindow associated with the vtkRenderWinodwInteractor. + // Here we specify a particular interactor style. + vtkInteractorStyleTrackballCamera style = + new vtkInteractorStyleTrackballCamera(); + iren.SetInteractorStyle(style); + + // + // Unlike the previous examples where we performed some operations and then + // exited, here we leave an event loop running. The user can use the mouse + // and keyboard to perform the operations on the scene according to the + // current interaction style. + // + + // + // Initialize and start the event loop. Once the render window appears, + // mouse in the window to move the camera. The Start() method executes + // an event loop which listens to user mouse and keyboard events. Note + // that keypress-e exits the event loop. (Look in vtkInteractorStyle.h + // for a summary of events, or the appropriate Doxygen documentation.) + // + iren.Initialize(); + iren.Start(); + } +} diff --git a/Examples/Tutorial/Step5/Python/Cone5.py b/Examples/Tutorial/Step5/Python/Cone5.py new file mode 100644 index 0000000..1380583 --- /dev/null +++ b/Examples/Tutorial/Step5/Python/Cone5.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +# +# This example introduces the concepts of user interaction with VTK. +# First, a different interaction style (than the default) is defined. +# Second, the interaction is started. +# +# + +import vtk + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +cone = vtk.vtkConeSource() +cone.SetHeight( 3.0 ) +cone.SetRadius( 1.0 ) +cone.SetResolution( 10 ) + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +coneActor = vtk.vtkActor() +coneActor.SetMapper(coneMapper) + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +ren1 = vtk.vtkRenderer() +ren1.AddActor(coneActor) +ren1.SetBackground(0.1, 0.2, 0.4) + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300. +# +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren1) +renWin.SetSize(300, 300) + +# +# The vtkRenderWindowInteractor class watches for events (e.g., keypress, +# mouse) in the vtkRenderWindow. These events are translated into +# event invocations that VTK understands (see VTK/Common/vtkCommand.h +# for all events that VTK processes). Then observers of these VTK +# events can process them as appropriate. +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# +# By default the vtkRenderWindowInteractor instantiates an instance +# of vtkInteractorStyle. vtkInteractorStyle translates a set of events +# it observes into operations on the camera, actors, and/or properties +# in the vtkRenderWindow associated with the vtkRenderWinodwInteractor. +# Here we specify a particular interactor style. +style = vtk.vtkInteractorStyleTrackballCamera() +iren.SetInteractorStyle(style) + +# +# Unlike the previous scripts where we performed some operations and then +# exited, here we leave an event loop running. The user can use the mouse +# and keyboard to perform the operations on the scene according to the +# current interaction style. +# + +# +# Initialize and start the event loop. Once the render window appears, mouse +# in the window to move the camera. The Start() method executes an event +# loop which listens to user mouse and keyboard events. Note that keypress-e +# exits the event loop. (Look in vtkInteractorStyle.h for a summary of events, or +# the appropriate Doxygen documentation.) +# +iren.Initialize() +iren.Start() diff --git a/Examples/Tutorial/Step5/Tcl/Cone5.tcl b/Examples/Tutorial/Step5/Tcl/Cone5.tcl new file mode 100644 index 0000000..e26394d --- /dev/null +++ b/Examples/Tutorial/Step5/Tcl/Cone5.tcl @@ -0,0 +1,120 @@ +# +# This example introduces the concepts of interaction into the +# Tcl environment. First, a different interaction style (than +# the default) is defined. Second, because Tcl is an interpretive +# language, the VTK Tcl interaction GUI is set up. +# +# +# +# First we include the VTK Tcl packages which will make available +# all of the VTK commands to Tcl. Note that package vtkinteraction +# is required; thios package defines the Tcl/Tk GUI widget .vtkInteract +# that is referred to later. +# +package require vtk +package require vtkinteraction + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +vtkActor coneActor +coneActor SetMapper coneMapper + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300. +# +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +# +# The vtkRenderWindowInteractor class watches for events (e.g., keypress, +# mouse) in the vtkRenderWindow. These events are translated into +# event invocations that VTK understands (see VTK/Common/vtkCommand.h +# for all events that VTK processes). Then observers of these VTK +# events can process them as appropriate. +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# +# By default the vtkRenderWindowInteractor instantiates an instance +# of vtkInteractorStyle. vtkInteractorStyle translates a set of events +# it observes into operations on the camera, actors, and/or properties +# in the vtkRenderWindow associated with the vtkRenderWinodwInteractor. +# Here we specify a particular interactor style. +vtkInteractorStyleTrackballCamera style +iren SetInteractorStyle style + +# +# Unlike the previous scripts where we performed some operations and then +# exited, here we leave an event loop running. The user can use the mouse +# and keyboard to perform the operations on the scene according to the +# current interaction style. +# + +# +# Another feature of Tcl/Tk is that in VTK a simple GUI for typing in +# interpreted Tcl commands is provided. The so-called vtkInteractor appears +# when the user types the "u" (for user) keypress. The "u" keypress is +# translated into a UserEvent by the vtkRenderWindowInteractor. We observe +# this event and invoke a commands to deiconify the vtkInteractor. (The +# vtkInteractor is defined in the vtkinteraction package reference at the +# beginning of this script.) +# +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# +# Initialize the event loop. The actual interaction starts after +# wm withdraw . with the Tk event loop. Once the render window appears, +# mouse in the window to move the camera. Note that keypress-e exits this +# example. (Look in vtkInteractorStyle.h for a summary of events, or +# the appropriate Doxygen documentation.) +# +iren Initialize + +# +# Since we are in the Tcl/Tk environment, we prevent the empty "." +# window from appearing with the Tk "withdraw" command. +# +wm withdraw . + + + + + diff --git a/Examples/Tutorial/Step6/Cxx/CMakeLists.txt b/Examples/Tutorial/Step6/Cxx/CMakeLists.txt new file mode 100644 index 0000000..efb2841 --- /dev/null +++ b/Examples/Tutorial/Step6/Cxx/CMakeLists.txt @@ -0,0 +1,10 @@ +PROJECT (Step6) + +FIND_PACKAGE(VTK REQUIRED) +IF(NOT VTK_USE_RENDERING) + MESSAGE(FATAL_ERROR "Example ${PROJECT_NAME} requires VTK_USE_RENDERING.") +ENDIF(NOT VTK_USE_RENDERING) +INCLUDE(${VTK_USE_FILE}) + +ADD_EXECUTABLE(Cone6 Cone6.cxx) +TARGET_LINK_LIBRARIES(Cone6 vtkWidgets) diff --git a/Examples/Tutorial/Step6/Cxx/Cone6.cxx b/Examples/Tutorial/Step6/Cxx/Cone6.cxx new file mode 100644 index 0000000..f4d2324 --- /dev/null +++ b/Examples/Tutorial/Step6/Cxx/Cone6.cxx @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Cone6.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// This example introduces 3D widgets. 3D widgets take advantage of the +// event/observer design pattern introduced previously. They typically +// have a particular representation in the scene which can be interactively +// selected and manipulated using the mouse and keyboard. As the widgets +// are manipulated, they in turn invoke events such as StartInteractionEvent, +// InteractionEvent, and EndInteractionEvent which can be used to manipulate +// the scene that the widget is embedded in. 3D widgets work in the context +// of the event loop which was set up in the previous example. +// +// Note: there are more 3D widget examples in VTK/Examples/GUI/. +// + +// First include the required header files for the VTK classes we are using. +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkCamera.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkCommand.h" +#include "vtkBoxWidget.h" +#include "vtkTransform.h" +#include "vtkInteractorStyleTrackballCamera.h" + +// +// Similar to Cone2.cxx, we define a callback for interaction. +// +class vtkMyCallback : public vtkCommand +{ +public: + static vtkMyCallback *New() + { return new vtkMyCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkTransform *t = vtkTransform::New(); + vtkBoxWidget *widget = reinterpret_cast(caller); + widget->GetTransform(t); + widget->GetProp3D()->SetUserTransform(t); + t->Delete(); + } +}; + +int main() +{ + // + // Next we create an instance of vtkConeSource and set some of its + // properties. The instance of vtkConeSource "cone" is part of a + // visualization pipeline (it is a source process object); it produces data + // (output type is vtkPolyData) which other filters may process. + // + vtkConeSource *cone = vtkConeSource::New(); + cone->SetHeight( 3.0 ); + cone->SetRadius( 1.0 ); + cone->SetResolution( 10 ); + + // + // In this example we terminate the pipeline with a mapper process object. + // (Intermediate filters such as vtkShrinkPolyData could be inserted in + // between the source and the mapper.) We create an instance of + // vtkPolyDataMapper to map the polygonal data into graphics primitives. We + // connect the output of the cone souece to the input of this mapper. + // + vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New(); + coneMapper->SetInputConnection( cone->GetOutputPort() ); + + // + // Create an actor to represent the cone. The actor orchestrates rendering + // of the mapper's graphics primitives. An actor also refers to properties + // via a vtkProperty instance, and includes an internal transformation + // matrix. We set this actor's mapper to be coneMapper which we created + // above. + // + vtkActor *coneActor = vtkActor::New(); + coneActor->SetMapper( coneMapper ); + + // + // Create the Renderer and assign actors to it. A renderer is like a + // viewport. It is part or all of a window on the screen and it is + // responsible for drawing the actors it has. We also set the background + // color here. + // + vtkRenderer *ren1= vtkRenderer::New(); + ren1->AddActor( coneActor ); + ren1->SetBackground( 0.1, 0.2, 0.4 ); + + // + // Finally we create the render window which will show up on the screen. + // We put our renderer into the render window using AddRenderer. We also + // set the size to be 300 pixels by 300. + // + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer( ren1 ); + renWin->SetSize( 300, 300 ); + + // + // The vtkRenderWindowInteractor class watches for events (e.g., keypress, + // mouse) in the vtkRenderWindow. These events are translated into + // event invocations that VTK understands (see VTK/Common/vtkCommand.h + // for all events that VTK processes). Then observers of these VTK + // events can process them as appropriate. + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // + // By default the vtkRenderWindowInteractor instantiates an instance + // of vtkInteractorStyle. vtkInteractorStyle translates a set of events + // it observes into operations on the camera, actors, and/or properties + // in the vtkRenderWindow associated with the vtkRenderWinodwInteractor. + // Here we specify a particular interactor style. + vtkInteractorStyleTrackballCamera *style = + vtkInteractorStyleTrackballCamera::New(); + iren->SetInteractorStyle(style); + + // + // Here we use a vtkBoxWidget to transform the underlying coneActor (by + // manipulating its transformation matrix). Many other types of widgets + // are available for use, see the documentation for more details. + // + // The SetInteractor method is how 3D widgets are associated with the render + // window interactor. Internally, SetInteractor sets up a bunch of callbacks + // using the Command/Observer mechanism (AddObserver()). The place factor + // controls the initial size of the widget with respect to the bounding box + // of the input to the widget. + vtkBoxWidget *boxWidget = vtkBoxWidget::New(); + boxWidget->SetInteractor(iren); + boxWidget->SetPlaceFactor(1.25); + + // + // Place the interactor initially. The input to a 3D widget is used to + // initially position and scale the widget. The EndInteractionEvent is + // observed which invokes the SelectPolygons callback. + // + boxWidget->SetProp3D(coneActor); + boxWidget->PlaceWidget(); + vtkMyCallback *callback = vtkMyCallback::New(); + boxWidget->AddObserver(vtkCommand::InteractionEvent, callback); + + // + // Normally the user presses the "i" key to bring a 3D widget to life. Here + // we will manually enable it so it appears with the cone. + // + boxWidget->On(); + + // + // Start the event loop. + // + iren->Initialize(); + iren->Start(); + + // + // Free up any objects we created. All instances in VTK are deleted by + // using the Delete() method. + // + cone->Delete(); + coneMapper->Delete(); + coneActor->Delete(); + callback->Delete(); + boxWidget->Delete(); + ren1->Delete(); + renWin->Delete(); + iren->Delete(); + style->Delete(); + + return 0; +} + + diff --git a/Examples/Tutorial/Step6/Python/Cone6.py b/Examples/Tutorial/Step6/Python/Cone6.py new file mode 100644 index 0000000..3f7e889 --- /dev/null +++ b/Examples/Tutorial/Step6/Python/Cone6.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# +# This example introduces 3D widgets. 3D widgets take advantage of the +# event/observer design pattern introduced previously. They typically +# have a particular representation in the scene which can be interactively +# selected and manipulated using the mouse and keyboard. As the widgets +# are manipulated, they in turn invoke events such as StartInteractionEvent, +# InteractionEvent, and EndInteractionEvent which can be used to manipulate +# the scene that the widget is embedded in. 3D widgets work in the context +# of the event loop which was set up in the previous example. +# +# Note: there are more 3D widget examples in VTK/Examples/GUI/. +# + +# First we import the VTK Python package that will make available all +# of the VTK commands to Python. +import vtk + +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a +# visualization pipeline (it is a source process object); it produces +# data (output type is vtkPolyData) which other filters may process. +cone = vtk.vtkConeSource() +cone.SetHeight(3.0) +cone.SetRadius(1.0) +cone.SetResolution(10) + +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) + +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +coneActor = vtk.vtkActor() +coneActor.SetMapper(coneMapper) + +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is +# responsible for drawing the actors it has. We also set the +# background color here. +ren1 = vtk.vtkRenderer() +ren1.AddActor(coneActor) +ren1.SetBackground(0.1, 0.2, 0.4) + +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We +# also set the size to be 300 pixels by 300. +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren1) +renWin.SetSize(300, 300) + +# The vtkRenderWindowInteractor class watches for events (e.g., keypress, +# mouse) in the vtkRenderWindow. These events are translated into +# event invocations that VTK understands (see VTK/Common/vtkCommand.h +# for all events that VTK processes). Then observers of these VTK +# events can process them as appropriate. +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# By default the vtkRenderWindowInteractor instantiates an instance +# of vtkInteractorStyle. vtkInteractorStyle translates a set of events +# it observes into operations on the camera, actors, and/or properties +# in the vtkRenderWindow associated with the vtkRenderWinodwInteractor. +# Here we specify a particular interactor style. +style = vtk.vtkInteractorStyleTrackballCamera() +iren.SetInteractorStyle(style) + + +# Here we use a vtkBoxWidget to transform the underlying coneActor (by +# manipulating its transformation matrix). Many other types of widgets +# are available for use, see the documentation for more details. +# +# The SetInteractor method is how 3D widgets are associated with the render +# window interactor. Internally, SetInteractor sets up a bunch of callbacks +# using the Command/Observer mechanism (AddObserver()). The place factor +# controls the initial size of the widget with respect to the bounding box +# of the input to the widget. +boxWidget = vtk.vtkBoxWidget() +boxWidget.SetInteractor(iren) +boxWidget.SetPlaceFactor(1.25) + +# Place the interactor initially. The input to a 3D widget is used to +# initially position and scale the widget. The EndInteractionEvent is +# observed which invokes the SelectPolygons callback. +boxWidget.SetProp3D(coneActor) +boxWidget.PlaceWidget() + +# Similar to Step2/Python/Cone2.py, we define a callback for +# interaction. As can be seen the callback takes two arguments. The +# first being the object that generates the event and the second +# argument the event name (which is a string). +def myCallback(widget, event_string): + t = vtk.vtkTransform() + boxWidget.GetTransform(t) + boxWidget.GetProp3D().SetUserTransform(t) + + +# Now for every interaction event that is generated by the boxWidget, +# call our callback function. +boxWidget.AddObserver("InteractionEvent", myCallback) + +# Normally the user presses the "i" key to bring a 3D widget to +# life. Here we will manually enable it so it appears with the cone. +boxWidget.On() + +# Start the event loop. +iren.Initialize() +iren.Start() + +# There is no explicit need to free any objects at this point. +# Once Python exits, memory is automatically freed. diff --git a/Examples/Tutorial/Step6/Tcl/Cone6.tcl b/Examples/Tutorial/Step6/Tcl/Cone6.tcl new file mode 100644 index 0000000..6898df1 --- /dev/null +++ b/Examples/Tutorial/Step6/Tcl/Cone6.tcl @@ -0,0 +1,146 @@ +# +# This example introduces 3D widgets. 3D widgets take advantage of the +# event/observer design pattern introduced previously. They typically +# have a particular representation in the scene which can be interactively +# selected and manipulated using the mouse and keyboard. As the widgets +# are manipulated, they in turn invoke events such as StartInteractionEvent, +# InteractionEvent, and EndInteractionEvent which can be used to manipulate +# the scene that the widget is embedded in. 3D widgets work in the context +# of the event loop which was set up in the previous example. +# +# Note: there are more 3D widget examples in VTK/Examples/GUI/. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the VTK commands to Tcl. +# +package require vtk + +# +# Next we create an instance of vtkConeSource and set some of its +# properties. The instance of vtkConeSource "cone" is part of a visualization +# pipeline (it is a source process object); it produces data (output type is +# vtkPolyData) which other filters may process. +# +vtkConeSource cone +cone SetHeight 3.0 +cone SetRadius 1.0 +cone SetResolution 10 + +# +# In this example we terminate the pipeline with a mapper process object. +# (Intermediate filters such as vtkShrinkPolyData could be inserted in +# between the source and the mapper.) We create an instance of +# vtkPolyDataMapper to map the polygonal data into graphics primitives. We +# connect the output of the cone souece to the input of this mapper. +# +vtkPolyDataMapper coneMapper +coneMapper SetInputConnection [cone GetOutputPort] + +# +# Create an actor to represent the cone. The actor orchestrates rendering of +# the mapper's graphics primitives. An actor also refers to properties via a +# vtkProperty instance, and includes an internal transformation matrix. We +# set this actor's mapper to be coneMapper which we created above. +# +vtkActor coneActor +coneActor SetMapper coneMapper + +# +# Create the Renderer and assign actors to it. A renderer is like a +# viewport. It is part or all of a window on the screen and it is responsible +# for drawing the actors it has. We also set the background color here. +# +vtkRenderer ren1 +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 + +# +# Finally we create the render window which will show up on the screen +# We put our renderer into the render window using AddRenderer. We also +# set the size to be 300 pixels by 300. +# +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +# +# The vtkRenderWindowInteractor class watches for events (e.g., keypress, +# mouse) in the vtkRenderWindow. These events are translated into +# event invocations that VTK understands (see VTK/Common/vtkCommand.h +# for all events that VTK processes). Then observers of these VTK +# events can process them as appropriate. +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# +# By default the vtkRenderWindowInteractor instantiates an instance +# of vtkInteractorStyle. vtkInteractorStyle translates a set of events +# it observes into operations on the camera, actors, and/or properties +# in the vtkRenderWindow associated with the vtkRenderWinodwInteractor. +# Here we specify a particular interactor style. +vtkInteractorStyleTrackballCamera style +iren SetInteractorStyle style + +# +# Here we use a vtkBoxWidget to transform the underlying coneActor (by +# manipulating its transformation matrix). Many other types of widgets +# are available for use, see the documentation for more details. +# +# The SetInteractor method is how 3D widgets are associated with the render +# window interactor. Internally, SetInteractor sets up a bunch of callbacks +# using the Command/Observer mechanism (AddObserver()). The place factor +# controls the initial size of the widget with respect to the bounding box +# of the input to the widget. +vtkBoxWidget boxWidget +boxWidget SetInteractor iren +boxWidget SetPlaceFactor 1.25 + +# +# Place the interactor initially. The input to a 3D widget is used to +# initially position and scale the widget. The EndInteractionEvent is +# observed which invokes the SelectPolygons callback. +# +boxWidget SetInput [cone GetOutput] +boxWidget PlaceWidget +boxWidget AddObserver InteractionEvent TransformActor + +# +# Normally the user presses the "i" key to bring a 3D widget to life. Here +# we will manually enable it so it appears with the cone. +# +boxWidget On + +# +# We can use the vtkInteract Tcl/Tk interactor at the same time as +# the box widget. +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# +# Initialize starts the event loop. Once the render window appears, mouse +# in the window to move the camera. If you select the box widget, +# depending on what is selected, the widget will change shape. As this +# is happening, it will invoke InteractionEvents on itself. These are +# caught by the observer which in turn invokes the Tcl proc TransformActor +# (defined below). If you do not select the box widget, then the events +# are received by the interactor style, which manipulates the camera as +# usual. It is possible to have many widgets running simultaneously, and to +# prioritize the processing of events. +# +iren Initialize + +# +# Since we are in the Tcl/Tk environment, we prevent the empty "." +# window from appearing with the Tk "withdraw" command. +# +wm withdraw . + +# As the box widget is interacted with, it produces a transformation +# matrix that is set on the actor. +vtkTransform t +proc TransformActor {} { + boxWidget GetTransform t + coneActor SetUserTransform t +} diff --git a/Examples/VisualizationAlgorithms/Python/BandContourTerrain.py b/Examples/VisualizationAlgorithms/Python/BandContourTerrain.py new file mode 100644 index 0000000..7911b2d --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/BandContourTerrain.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python + +# In this example we show the use of the +# vtkBandedPolyDataContourFilter. This filter creates separate, +# constant colored bands for a range of scalar values. Each band is +# bounded by two scalar values, and the cell data lying within the +# value has the same cell scalar value. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + + +# The lookup table is similar to that used by maps. Two hues are used: +# a brown for land, and a blue for water. The value of the hue is +# changed to give the effect of elevation. +Scale = 5 +lutWater = vtk.vtkLookupTable() +lutWater.SetNumberOfColors(10) +lutWater.SetHueRange(0.58, 0.58) +lutWater.SetSaturationRange(0.5, 0.1) +lutWater.SetValueRange(0.5, 1.0) +lutWater.Build() +lutLand = vtk.vtkLookupTable() +lutLand.SetNumberOfColors(10) +lutLand.SetHueRange(0.1, 0.1) +lutLand.SetSaturationRange(0.4, 0.1) +lutLand.SetValueRange(0.55, 0.9) +lutLand.Build() + + +# The DEM reader reads data and creates an output image. +demModel = vtk.vtkDEMReader() +demModel.SetFileName(VTK_DATA_ROOT + "/Data/SainteHelens.dem") +demModel.Update() + +# We shrink the terrain data down a bit to yield better performance for +# this example. +shrinkFactor = 4 +shrink = vtk.vtkImageShrink3D() +shrink.SetShrinkFactors(shrinkFactor, shrinkFactor, 1) +shrink.SetInputConnection(demModel.GetOutputPort()) +shrink.AveragingOn() + +# Convert the image into polygons. +geom = vtk.vtkImageDataGeometryFilter() +geom.SetInputConnection(shrink.GetOutputPort()) + +# Warp the polygons based on elevation. +warp = vtk.vtkWarpScalar() +warp.SetInputConnection(geom.GetOutputPort()) +warp.SetNormal(0, 0, 1) +warp.UseNormalOn() +warp.SetScaleFactor(Scale) + +# Create the contour bands. +bcf = vtk.vtkBandedPolyDataContourFilter() +bcf.SetInput(warp.GetPolyDataOutput()) +bcf.GenerateValues(15, demModel.GetOutput().GetScalarRange()) +bcf.SetScalarModeToIndex() +bcf.GenerateContourEdgesOn() + +# Compute normals to give a better look. +normals = vtk.vtkPolyDataNormals() +normals.SetInputConnection(bcf.GetOutputPort()) +normals.SetFeatureAngle(60) +normals.ConsistencyOff() +normals.SplittingOff() + +demMapper = vtk.vtkPolyDataMapper() +demMapper.SetInputConnection(normals.GetOutputPort()) +demMapper.SetScalarRange(0, 10) +demMapper.SetLookupTable(lutLand) +demMapper.SetScalarModeToUseCellData() + +demActor = vtk.vtkLODActor() +demActor.SetMapper(demMapper) + +## Create contour edges +edgeMapper = vtk.vtkPolyDataMapper() +edgeMapper.SetInput(bcf.GetContourEdgesOutput()) +edgeMapper.SetResolveCoincidentTopologyToPolygonOffset() +edgeActor = vtk.vtkActor() +edgeActor.SetMapper(edgeMapper) +edgeActor.GetProperty().SetColor(0, 0, 0) + +## Test clipping +# Create the contour bands. +bcf2 = vtk.vtkBandedPolyDataContourFilter() +bcf2.SetInput(warp.GetPolyDataOutput()) +bcf2.ClippingOn() +bcf2.GenerateValues(10, 1000, 2000) +bcf2.SetScalarModeToValue() + +# Compute normals to give a better look. +normals2 = vtk.vtkPolyDataNormals() +normals2.SetInputConnection(bcf2.GetOutputPort()) +normals2.SetFeatureAngle(60) +normals2.ConsistencyOff() +normals2.SplittingOff() + +lut = vtk.vtkLookupTable() +lut.SetNumberOfColors(10) +demMapper2 = vtk.vtkPolyDataMapper() +demMapper2.SetInputConnection(normals2.GetOutputPort()) +demMapper2.SetScalarRange(demModel.GetOutput().GetScalarRange()) +demMapper2.SetLookupTable(lut) +demMapper2.SetScalarModeToUseCellData() + +demActor2 = vtk.vtkLODActor() +demActor2.SetMapper(demMapper2) +demActor2.AddPosition(0, 15000, 0) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(demActor) +ren.AddActor(demActor2) +ren.AddActor(edgeActor) + +ren.SetBackground(.4, .4, .4) +renWin.SetSize(375, 200) + +cam = vtk.vtkCamera() +cam.SetPosition(-17438.8, 2410.62, 25470.8) +cam.SetFocalPoint(3985.35, 11930.6, 5922.14) +cam.SetViewUp(0, 0, 1) +ren.SetActiveCamera(cam) +ren.ResetCamera() +cam.Zoom(2) + +iren.Initialize() +iren.SetDesiredUpdateRate(1) + +def CheckAbort(obj, event): + foo = renWin.GetEventPending() + if foo != 0: + renWin.SetAbortRender(1) + +renWin.AddObserver("AbortCheckEvent", CheckAbort) +renWin.Render() + +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/ClipCow.py b/Examples/VisualizationAlgorithms/Python/ClipCow.py new file mode 100644 index 0000000..78428a4 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/ClipCow.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python + +# In this example vtkClipPolyData is used to cut a polygonal model +# of a cow in half. In addition, the open clip is closed by triangulating +# the resulting complex polygons. + +import vtk +from vtk.util.misc import vtkGetDataRoot +from vtk.util.colors import peacock, tomato +VTK_DATA_ROOT = vtkGetDataRoot() + +# First start by reading a cow model. We also generate surface normals for +# prettier rendering. +cow = vtk.vtkBYUReader() +cow.SetGeometryFileName(VTK_DATA_ROOT + "/Data/Viewpoint/cow.g") +cowNormals = vtk.vtkPolyDataNormals() +cowNormals.SetInputConnection(cow.GetOutputPort()) + +# We clip with an implicit function. Here we use a plane positioned near +# the center of the cow model and oriented at an arbitrary angle. +plane = vtk.vtkPlane() +plane.SetOrigin(0.25, 0, 0) +plane.SetNormal(-1, -1, 0) + +# vtkClipPolyData requires an implicit function to define what it is to +# clip with. Any implicit function, including complex boolean combinations +# can be used. Notice that we can specify the value of the implicit function +# with the SetValue method. +clipper = vtk.vtkClipPolyData() +clipper.SetInputConnection(cowNormals.GetOutputPort()) +clipper.SetClipFunction(plane) +clipper.GenerateClipScalarsOn() +clipper.GenerateClippedOutputOn() +clipper.SetValue(0.5) +clipMapper = vtk.vtkPolyDataMapper() +clipMapper.SetInputConnection(clipper.GetOutputPort()) +clipMapper.ScalarVisibilityOff() +backProp = vtk.vtkProperty() +backProp.SetDiffuseColor(tomato) +clipActor = vtk.vtkActor() +clipActor.SetMapper(clipMapper) +clipActor.GetProperty().SetColor(peacock) +clipActor.SetBackfaceProperty(backProp) + +# Here we are cutting the cow. Cutting creates lines where the cut +# function intersects the model. (Clipping removes a portion of the +# model but the dimension of the data does not change.) +# +# The reason we are cutting is to generate a closed polygon at the +# boundary of the clipping process. The cutter generates line +# segments, the stripper then puts them together into polylines. We +# then pull a trick and define polygons using the closed line +# segements that the stripper created. +cutEdges = vtk.vtkCutter() +cutEdges.SetInputConnection(cowNormals.GetOutputPort()) +cutEdges.SetCutFunction(plane) +cutEdges.GenerateCutScalarsOn() +cutEdges.SetValue(0, 0.5) +cutStrips = vtk.vtkStripper() +cutStrips.SetInputConnection(cutEdges.GetOutputPort()) +cutStrips.Update() +cutPoly = vtk.vtkPolyData() +cutPoly.SetPoints(cutStrips.GetOutput().GetPoints()) +cutPoly.SetPolys(cutStrips.GetOutput().GetLines()) + +# Triangle filter is robust enough to ignore the duplicate point at +# the beginning and end of the polygons and triangulate them. +cutTriangles = vtk.vtkTriangleFilter() +cutTriangles.SetInput(cutPoly) +cutMapper = vtk.vtkPolyDataMapper() +cutMapper.SetInput(cutPoly) +cutMapper.SetInputConnection(cutTriangles.GetOutputPort()) +cutActor = vtk.vtkActor() +cutActor.SetMapper(cutMapper) +cutActor.GetProperty().SetColor(peacock) + +# The clipped part of the cow is rendered wireframe. +restMapper = vtk.vtkPolyDataMapper() +restMapper.SetInput(clipper.GetClippedOutput()) +restMapper.ScalarVisibilityOff() +restActor = vtk.vtkActor() +restActor.SetMapper(restMapper) +restActor.GetProperty().SetRepresentationToWireframe() + +# Create graphics stuff +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(clipActor) +ren.AddActor(cutActor) +ren.AddActor(restActor) +ren.SetBackground(1, 1, 1) +ren.ResetCamera() +ren.GetActiveCamera().Azimuth(30) +ren.GetActiveCamera().Elevation(30) +ren.GetActiveCamera().Dolly(1.5) +ren.ResetCameraClippingRange() + +renWin.SetSize(300, 300) +iren.Initialize() + +# Lets you move the cut plane back and forth by invoking the function +# Cut with the appropriate plane value (essentially a distance from +# the original plane). This is not used in this code but should give +# you an idea of how to define a function to do this. +def Cut(v): + clipper.SetValue(v) + cutEdges.SetValue(0, v) + cutStrips.Update() + cutPoly.SetPoints(cutStrips.GetOutput().GetPoints()) + cutPoly.SetPolys(cutStrips.GetOutput().GetLines()) + cutMapper.Update() + renWin.Render() + +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/ColorIsosurface.py b/Examples/VisualizationAlgorithms/Python/ColorIsosurface.py new file mode 100644 index 0000000..9b61c90 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/ColorIsosurface.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +# This example shows how to color an isosurface with other +# data. Basically an isosurface is generated, and a data array is +# selected and used by the mapper to color the surface. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read some data. The important thing here is to read a function as a +# data array as well as the scalar and vector. (here function 153 is +# named "Velocity Magnitude").Later this data array will be used to +# color the isosurface. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.AddFunction(153) +pl3d.Update() +pl3d.DebugOn() + +# The contour filter uses the labeled scalar (function number 100 +# above to generate the contour surface; all other data is +# interpolated during the contouring process. +iso = vtk.vtkContourFilter() +iso.SetInputConnection(pl3d.GetOutputPort()) +iso.SetValue(0, .24) + +normals = vtk.vtkPolyDataNormals() +normals.SetInputConnection(iso.GetOutputPort()) +normals.SetFeatureAngle(45) + +# We indicate to the mapper to use the velcoity magnitude, which is a +# vtkDataArray that makes up part of the point attribute data. +isoMapper = vtk.vtkPolyDataMapper() +isoMapper.SetInputConnection(normals.GetOutputPort()) +isoMapper.ScalarVisibilityOn() +isoMapper.SetScalarRange(0, 1500) +isoMapper.SetScalarModeToUsePointFieldData() +isoMapper.ColorByArrayComponent("VelocityMagnitude", 0) + +isoActor = vtk.vtkLODActor() +isoActor.SetMapper(isoMapper) +isoActor.SetNumberOfCloudPoints(1000) + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# Create the usual rendering stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(isoActor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(500, 500) +ren.SetBackground(0.1, 0.2, 0.4) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(9.71821, 0.458166, 29.3999) +cam1.SetPosition(2.7439, -37.3196, 38.7167) +cam1.SetViewUp(-0.16123, 0.264271, 0.950876) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/CutCombustor.py b/Examples/VisualizationAlgorithms/Python/CutCombustor.py new file mode 100644 index 0000000..78a546d --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/CutCombustor.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# This example shows how to use cutting (vtkCutter) and how it +# compares with extracting a plane from a computational grid. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read some data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# The cutter uses an implicit function to perform the cutting. +# Here we define a plane, specifying its center and normal. +# Then we assign the plane to the cutter. +plane = vtk.vtkPlane() +plane.SetOrigin(pl3d.GetOutput().GetCenter()) +plane.SetNormal(-0.287, 0, 0.9579) +planeCut = vtk.vtkCutter() +planeCut.SetInputConnection(pl3d.GetOutputPort()) +planeCut.SetCutFunction(plane) +cutMapper = vtk.vtkPolyDataMapper() +cutMapper.SetInputConnection(planeCut.GetOutputPort()) +cutMapper.SetScalarRange(pl3d.GetOutput().GetPointData().GetScalars().GetRange()) +cutActor = vtk.vtkActor() +cutActor.SetMapper(cutMapper) + +# Here we extract a computational plane from the structured grid. +# We render it as wireframe. +compPlane = vtk.vtkStructuredGridGeometryFilter() +compPlane.SetInputConnection(pl3d.GetOutputPort()) +compPlane.SetExtent(0, 100, 0, 100, 9, 9) +planeMapper = vtk.vtkPolyDataMapper() +planeMapper.SetInputConnection(compPlane.GetOutputPort()) +planeMapper.ScalarVisibilityOff() +planeActor = vtk.vtkActor() +planeActor.SetMapper(planeMapper) +planeActor.GetProperty().SetRepresentationToWireframe() +planeActor.GetProperty().SetColor(0, 0, 0) + +# The outline of the data puts the data in context. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineProp = outlineActor.GetProperty() +outlineProp.SetColor(0, 0, 0) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(planeActor) +ren.AddActor(cutActor) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(400, 300) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(11.1034, 59.5328) +cam1.SetFocalPoint(9.71821, 0.458166, 29.3999) +cam1.SetPosition(-2.95748, -26.7271, 44.5309) +cam1.SetViewUp(0.0184785, 0.479657, 0.877262) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/DepthSort.py b/Examples/VisualizationAlgorithms/Python/DepthSort.py new file mode 100644 index 0000000..845bf6d --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/DepthSort.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +# This example demonstrates the use of vtkDepthSortPolyData. This is a +# poor man's algorithm to sort polygons for proper transparent +# blending. It sorts polygons based on a single point (i.e., +# centroid) so the sorting may not work for overlapping or +# intersection polygons. + +import vtk + +# Create a bunch of spheres that overlap and cannot be easily arranged +# so that the blending works without sorting. They are appended into a +# single vtkPolyData because the filter only sorts within a single +# vtkPolyData input. +sphere = vtk.vtkSphereSource() +sphere.SetThetaResolution(80) +sphere.SetPhiResolution(40) +sphere.SetRadius(1) +sphere.SetCenter(0, 0, 0) +sphere2 = vtk.vtkSphereSource() +sphere2.SetThetaResolution(80) +sphere2.SetPhiResolution(40) +sphere2.SetRadius(0.5) +sphere2.SetCenter(1, 0, 0) +sphere3 = vtk.vtkSphereSource() +sphere3.SetThetaResolution(80) +sphere3.SetPhiResolution(40) +sphere3.SetRadius(0.5) +sphere3.SetCenter(-1, 0, 0) +sphere4 = vtk.vtkSphereSource() +sphere4.SetThetaResolution(80) +sphere4.SetPhiResolution(40) +sphere4.SetRadius(0.5) +sphere4.SetCenter(0, 1, 0) +sphere5 = vtk.vtkSphereSource() +sphere5.SetThetaResolution(80) +sphere5.SetPhiResolution(40) +sphere5.SetRadius(0.5) +sphere5.SetCenter(0, -1, 0) +appendData = vtk.vtkAppendPolyData() +appendData.AddInput(sphere.GetOutput()) +appendData.AddInput(sphere2.GetOutput()) +appendData.AddInput(sphere3.GetOutput()) +appendData.AddInput(sphere4.GetOutput()) +appendData.AddInput(sphere5.GetOutput()) + +# The dephSort object is set up to generate scalars representing +# the sort depth. A camera is assigned for the sorting. The camera +# define the sort vector (position and focal point). +camera = vtk.vtkCamera() +depthSort = vtk.vtkDepthSortPolyData() +depthSort.SetInputConnection(appendData.GetOutputPort()) +depthSort.SetDirectionToBackToFront() +depthSort.SetVector(1, 1, 1) +depthSort.SetCamera(camera) +depthSort.SortScalarsOn() +depthSort.Update() + +mapper = vtk.vtkPolyDataMapper() +mapper.SetInputConnection(depthSort.GetOutputPort()) +mapper.SetScalarRange(0, depthSort.GetOutput().GetNumberOfCells()) +actor = vtk.vtkActor() +actor.SetMapper(mapper) +actor.GetProperty().SetOpacity(0.5) +actor.GetProperty().SetColor(1, 0, 0) +actor.RotateX(-72) + +# If an Prop3D is supplied, then its transformation matrix is taken +# into account during sorting. +depthSort.SetProp3D(actor) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +ren.SetActiveCamera(camera) +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(actor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 200) + +ren.ResetCamera() +ren.GetActiveCamera().Zoom(2.2) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/ExtractGeometry.py b/Examples/VisualizationAlgorithms/Python/ExtractGeometry.py new file mode 100644 index 0000000..8a6fda3 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/ExtractGeometry.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +# This example shows how to extract a piece of a dataset using an +# implicit function. In this case the implicit function is formed by +# the boolean combination of two ellipsoids. + +import vtk + +# Here we create two ellipsoidal implicit functions and boolean them +# together tto form a "cross" shaped implicit function. +quadric = vtk.vtkQuadric() +quadric.SetCoefficients(.5, 1, .2, 0, .1, 0, 0, .2, 0, 0) +sample = vtk.vtkSampleFunction() +sample.SetSampleDimensions(50, 50, 50) +sample.SetImplicitFunction(quadric) +sample.ComputeNormalsOff() +trans = vtk.vtkTransform() +trans.Scale(1, .5, .333) +sphere = vtk.vtkSphere() +sphere.SetRadius(0.25) +sphere.SetTransform(trans) +trans2 = vtk.vtkTransform() +trans2.Scale(.25, .5, 1.0) +sphere2 = vtk.vtkSphere() +sphere2.SetRadius(0.25) +sphere2.SetTransform(trans2) +union = vtk.vtkImplicitBoolean() +union.AddFunction(sphere) +union.AddFunction(sphere2) +union.SetOperationType(0) #union + +# Here is where it gets interesting. The implicit function is used to +# extract those cells completely inside the function. They are then +# shrunk to help show what was extracted. +extract = vtk.vtkExtractGeometry() +extract.SetInputConnection(sample.GetOutputPort()) +extract.SetImplicitFunction(union) +shrink = vtk.vtkShrinkFilter() +shrink.SetInputConnection(extract.GetOutputPort()) +shrink.SetShrinkFactor(0.5) +dataMapper = vtk.vtkDataSetMapper() +dataMapper.SetInputConnection(shrink.GetOutputPort()) +dataActor = vtk.vtkActor() +dataActor.SetMapper(dataMapper) + +# The outline gives context to the original data. +outline = vtk.vtkOutlineFilter() +outline.SetInputConnection(sample.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineProp = outlineActor.GetProperty() +outlineProp.SetColor(0, 0, 0) + +# The usual rendering stuff is created. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(dataActor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(500, 500) +ren.ResetCamera() +ren.GetActiveCamera().Zoom(1.5) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/ExtractUGrid.py b/Examples/VisualizationAlgorithms/Python/ExtractUGrid.py new file mode 100644 index 0000000..58ca0f2 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/ExtractUGrid.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +# This example shows how to extract portions of an unstructured grid +# using vtkExtractUnstructuredGrid. vtkConnectivityFilter is also used +# to extract connected components. +# +# The data found here represents a blow molding process. Blow molding +# requires a mold and parison (hot, viscous plastic) which is shaped +# by the mold into the final form. The data file contains several steps +# in time for the analysis. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create a reader to read the unstructured grid data. We use a +# vtkDataSetReader which means the type of the output is unknown until +# the data file is read. So we follow the reader with a +# vtkCastToConcrete and cast the output to vtkUnstructuredGrid. +reader = vtk.vtkDataSetReader() +reader.SetFileName(VTK_DATA_ROOT + "/Data/blow.vtk") +reader.SetScalarsName("thickness9") +reader.SetVectorsName("displacement9") +castToUnstructuredGrid = vtk.vtkCastToConcrete() +castToUnstructuredGrid.SetInputConnection(reader.GetOutputPort()) +warp = vtk.vtkWarpVector() +warp.SetInput(castToUnstructuredGrid.GetUnstructuredGridOutput()) + +# The connectivity filter extracts the first two regions. These are +# know to represent the mold. +connect = vtk.vtkConnectivityFilter() +connect.SetInputConnection(warp.GetOutputPort()) +connect.SetExtractionModeToSpecifiedRegions() +connect.AddSpecifiedRegion(0) +connect.AddSpecifiedRegion(1) +moldMapper = vtk.vtkDataSetMapper() +moldMapper.SetInputConnection(reader.GetOutputPort()) +moldMapper.ScalarVisibilityOff() +moldActor = vtk.vtkActor() +moldActor.SetMapper(moldMapper) +moldActor.GetProperty().SetColor(.2, .2, .2) +moldActor.GetProperty().SetRepresentationToWireframe() + +# Another connectivity filter is used to extract the parison. +connect2 = vtk.vtkConnectivityFilter() +connect2.SetInputConnection(warp.GetOutputPort()) +connect2.SetExtractionModeToSpecifiedRegions() +connect2.AddSpecifiedRegion(2) + +# We use vtkExtractUnstructuredGrid because we are interested in +# looking at just a few cells. We use cell clipping via cell id to +# extract the portion of the grid we are interested in. +extractGrid = vtk.vtkExtractUnstructuredGrid() +extractGrid.SetInputConnection(connect2.GetOutputPort()) +extractGrid.CellClippingOn() +extractGrid.SetCellMinimum(0) +extractGrid.SetCellMaximum(23) +parison = vtk.vtkGeometryFilter() +parison.SetInputConnection(extractGrid.GetOutputPort()) +normals2 = vtk.vtkPolyDataNormals() +normals2.SetInputConnection(parison.GetOutputPort()) +normals2.SetFeatureAngle(60) +lut = vtk.vtkLookupTable() +lut.SetHueRange(0.0, 0.66667) +parisonMapper = vtk.vtkPolyDataMapper() +parisonMapper.SetInputConnection(normals2.GetOutputPort()) +parisonMapper.SetLookupTable(lut) +parisonMapper.SetScalarRange(0.12, 1.0) +parisonActor = vtk.vtkActor() +parisonActor.SetMapper(parisonMapper) + +# graphics stuff +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(parisonActor) +ren.AddActor(moldActor) +ren.SetBackground(1, 1, 1) +ren.ResetCamera() +ren.GetActiveCamera().Azimuth(60) +ren.GetActiveCamera().Roll(-90) +ren.GetActiveCamera().Dolly(2) +ren.ResetCameraClippingRange() +renWin.SetSize(500, 375) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/GenerateTextureCoords.py b/Examples/VisualizationAlgorithms/Python/GenerateTextureCoords.py new file mode 100644 index 0000000..06b463d --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/GenerateTextureCoords.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +# This example shows how to generate and manipulate texture coordinates. +# A random cloud of points is generated and then triangulated with +# vtkDelaunay3D. Since these points do not have texture coordinates, +# we generate them with vtkTextureMapToCylinder. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Begin by generating 25 random points in the unit sphere. +sphere = vtk.vtkPointSource() +sphere.SetNumberOfPoints(25) + +# Triangulate the points with vtkDelaunay3D. This generates a convex hull +# of tetrahedron. +delny = vtk.vtkDelaunay3D() +delny.SetInputConnection(sphere.GetOutputPort()) +delny.SetTolerance(0.01) + +# The triangulation has texture coordinates generated so we can map +# a texture onto it. +tmapper = vtk.vtkTextureMapToCylinder() +tmapper.SetInputConnection(delny.GetOutputPort()) +tmapper.PreventSeamOn() + +# We scale the texture coordinate to get some repeat patterns. +xform = vtk.vtkTransformTextureCoords() +xform.SetInputConnection(tmapper.GetOutputPort()) +xform.SetScale(4, 4, 1) + +# vtkDataSetMapper internally uses a vtkGeometryFilter to extract the +# surface from the triangulation. The output (which is vtkPolyData) is +# then passed to an internal vtkPolyDataMapper which does the +# rendering. +mapper = vtk.vtkDataSetMapper() +mapper.SetInputConnection(xform.GetOutputPort()) + +# A texture is loaded using an image reader. Textures are simply images. +# The texture is eventually associated with an actor. +bmpReader = vtk.vtkBMPReader() +bmpReader.SetFileName(VTK_DATA_ROOT + "/Data/masonry.bmp") +atext = vtk.vtkTexture() +atext.SetInputConnection(bmpReader.GetOutputPort()) +atext.InterpolateOn() +triangulation = vtk.vtkActor() +triangulation.SetMapper(mapper) +triangulation.SetTexture(atext) + +# Create the standard rendering stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(triangulation) +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 300) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/SubsampleGrid.py b/Examples/VisualizationAlgorithms/Python/SubsampleGrid.py new file mode 100644 index 0000000..50bec35 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/SubsampleGrid.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +# This example demonstrates the subsampling of a structured grid. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read some structured data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# Here we subsample the grid. The SetVOI method requires six values +# specifying (imin,imax, jmin,jmax, kmin,kmax) extents. In this +# example we extracting a plane. Note that the VOI is clamped to zero +# (min) and the maximum i-j-k value; that way we can use the +# -1000,1000 specification and be sure the values are clamped. The +# SampleRate specifies that we take every point in the i-direction; +# every other point in the j-direction; and every third point in the +# k-direction. IncludeBoundaryOn makes sure that we get the boundary +# points even if the SampleRate does not coincident with the boundary. +extract = vtk.vtkExtractGrid() +extract.SetInputConnection(pl3d.GetOutputPort()) +extract.SetVOI(30, 30, -1000, 1000, -1000, 1000) +extract.SetSampleRate(1, 2, 3) +extract.IncludeBoundaryOn() +mapper = vtk.vtkDataSetMapper() +mapper.SetInputConnection(extract.GetOutputPort()) +mapper.SetScalarRange(.18, .7) +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Add the usual rendering stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(actor) + +ren.SetBackground(1, 1, 1) +renWin.SetSize(300, 180) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(2.64586, 47.905) +cam1.SetFocalPoint(8.931, 0.358127, 31.3526) +cam1.SetPosition(29.7111, -0.688615, 37.1495) +cam1.SetViewUp(-0.268328, 0.00801595, 0.963294) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/TextureThreshold.py b/Examples/VisualizationAlgorithms/Python/TextureThreshold.py new file mode 100644 index 0000000..61fb9e8 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/TextureThreshold.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +# This example shows how to use a transparent texture map to perform +# thresholding. The key is the vtkThresholdTextureCoords filter which +# creates texture coordinates based on a threshold value. These +# texture coordinates are used in conjuntion with a texture map with +# varying opacity and intensity to create an inside, transition, and +# outside region. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Begin by reading some structure grid data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/bluntfinxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/bluntfinq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# Now extract surfaces from the grid corresponding to boundary +# geometry. First the wall. +wall = vtk.vtkStructuredGridGeometryFilter() +wall.SetInputConnection(pl3d.GetOutputPort()) +wall.SetExtent(0, 100, 0, 0, 0, 100) +wallMap = vtk.vtkPolyDataMapper() +wallMap.SetInputConnection(wall.GetOutputPort()) +wallMap.ScalarVisibilityOff() +wallActor = vtk.vtkActor() +wallActor.SetMapper(wallMap) +wallActor.GetProperty().SetColor(0.8, 0.8, 0.8) + +# Now the fin. +fin = vtk.vtkStructuredGridGeometryFilter() +fin.SetInputConnection(pl3d.GetOutputPort()) +fin.SetExtent(0, 100, 0, 100, 0, 0) +finMap = vtk.vtkPolyDataMapper() +finMap.SetInputConnection(fin.GetOutputPort()) +finMap.ScalarVisibilityOff() +finActor = vtk.vtkActor() +finActor.SetMapper(finMap) +finActor.GetProperty().SetColor(0.8, 0.8, 0.8) + +# Extract planes to threshold. Start by reading the specially designed +# texture map that has three regions: an inside, boundary, and outside +# region. The opacity and intensity of this texture map are varied. +tmap = vtk.vtkStructuredPointsReader() +tmap.SetFileName(VTK_DATA_ROOT + "/Data/texThres2.vtk") +texture = vtk.vtkTexture() +texture.SetInputConnection(tmap.GetOutputPort()) +texture.InterpolateOff() +texture.RepeatOff() + +# Here are the three planes which will be texture thresholded. +plane1 = vtk.vtkStructuredGridGeometryFilter() +plane1.SetInputConnection(pl3d.GetOutputPort()) +plane1.SetExtent(10, 10, 0, 100, 0, 100) +thresh1 = vtk.vtkThresholdTextureCoords() +thresh1.SetInputConnection(plane1.GetOutputPort()) +thresh1.ThresholdByUpper(1.5) +plane1Map = vtk.vtkDataSetMapper() +plane1Map.SetInputConnection(thresh1.GetOutputPort()) +plane1Map.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +plane1Actor = vtk.vtkActor() +plane1Actor.SetMapper(plane1Map) +plane1Actor.SetTexture(texture) +plane1Actor.GetProperty().SetOpacity(0.999) + +plane2 = vtk.vtkStructuredGridGeometryFilter() +plane2.SetInputConnection(pl3d.GetOutputPort()) +plane2.SetExtent(30, 30, 0, 100, 0, 100) +thresh2 = vtk.vtkThresholdTextureCoords() +thresh2.SetInputConnection(plane2.GetOutputPort()) +thresh2.ThresholdByUpper(1.5) +plane2Map = vtk.vtkDataSetMapper() +plane2Map.SetInputConnection(thresh2.GetOutputPort()) +plane2Map.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +plane2Actor = vtk.vtkActor() +plane2Actor.SetMapper(plane2Map) +plane2Actor.SetTexture(texture) +plane2Actor.GetProperty().SetOpacity(0.999) + +plane3 = vtk.vtkStructuredGridGeometryFilter() +plane3.SetInputConnection(pl3d.GetOutputPort()) +plane3.SetExtent(35, 35, 0, 100, 0, 100) +thresh3 = vtk.vtkThresholdTextureCoords() +thresh3.SetInputConnection(plane3.GetOutputPort()) +thresh3.ThresholdByUpper(1.5) +plane3Map = vtk.vtkDataSetMapper() +plane3Map.SetInputConnection(thresh3.GetOutputPort()) +plane3Map.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +plane3Actor = vtk.vtkActor() +plane3Actor.SetMapper(plane3Map) +plane3Actor.SetTexture(texture) +plane3Actor.GetProperty().SetOpacity(0.999) + +# For context create an outline around the data. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineProp = outlineActor.GetProperty() +outlineProp.SetColor(0, 0, 0) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +ren.AddActor(wallActor) +ren.AddActor(finActor) +ren.AddActor(plane1Actor) +ren.AddActor(plane2Actor) +ren.AddActor(plane3Actor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(500, 500) + +# Set up a nice view. +cam1 = vtk.vtkCamera() +cam1.SetClippingRange(1.51176, 75.5879) +cam1.SetFocalPoint(2.33749, 2.96739, 3.61023) +cam1.SetPosition(10.8787, 5.27346, 15.8687) +cam1.SetViewAngle(30) +cam1.SetViewUp(-0.0610856, 0.987798, -0.143262) +ren.SetActiveCamera(cam1) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/VisQuad.py b/Examples/VisualizationAlgorithms/Python/VisQuad.py new file mode 100644 index 0000000..bb2b003 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/VisQuad.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +# This example demonstrates the use of the contour filter, and the use of +# the vtkSampleFunction to generate a volume of data samples from an +# implicit function. + +import vtk + +# VTK supports implicit functions of the form f(x,y,z)=constant. These +# functions can represent things spheres, cones, etc. Here we use a +# general form for a quadric to create an elliptical data field. +quadric = vtk.vtkQuadric() +quadric.SetCoefficients(.5, 1, .2, 0, .1, 0, 0, .2, 0, 0) + +# vtkSampleFunction samples an implicit function over the x-y-z range +# specified (here it defaults to -1,1 in the x,y,z directions). +sample = vtk.vtkSampleFunction() +sample.SetSampleDimensions(30, 30, 30) +sample.SetImplicitFunction(quadric) + +# Create five surfaces F(x,y,z) = constant between range specified. The +# GenerateValues() method creates n isocontour values between the range +# specified. +contours = vtk.vtkContourFilter() +contours.SetInputConnection(sample.GetOutputPort()) +contours.GenerateValues(5, 0.0, 1.2) + +contMapper = vtk.vtkPolyDataMapper() +contMapper.SetInputConnection(contours.GetOutputPort()) +contMapper.SetScalarRange(0.0, 1.2) + +contActor = vtk.vtkActor() +contActor.SetMapper(contMapper) + +# We'll put a simple outline around the data. +outline = vtk.vtkOutlineFilter() +outline.SetInputConnection(sample.GetOutputPort()) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) + +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineActor.GetProperty().SetColor(0,0,0) + +# The usual rendering stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +ren.SetBackground(1, 1, 1) +ren.AddActor(contActor) +ren.AddActor(outlineActor) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/deciFran.py b/Examples/VisualizationAlgorithms/Python/deciFran.py new file mode 100644 index 0000000..87bcbc9 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/deciFran.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# This example shows how to use decimation to reduce a polygonal +# mesh. We also use mesh smoothing and generate surface normals to +# give a pleasing result. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# We start by reading some data that was originally captured from a +# Cyberware laser digitizing system. +fran = vtk.vtkPolyDataReader() +fran.SetFileName(VTK_DATA_ROOT + "/Data/fran_cut.vtk") + +# We want to preserve topology (not let any cracks form). This may +# limit the total reduction possible, which we have specified at 90%. +deci = vtk.vtkDecimatePro() +deci.SetInputConnection(fran.GetOutputPort()) +deci.SetTargetReduction(0.9) +deci.PreserveTopologyOn() +normals = vtk.vtkPolyDataNormals() +normals.SetInputConnection(fran.GetOutputPort()) +normals.FlipNormalsOn() +franMapper = vtk.vtkPolyDataMapper() +franMapper.SetInputConnection(normals.GetOutputPort()) +franActor = vtk.vtkActor() +franActor.SetMapper(franMapper) +franActor.GetProperty().SetColor(1.0, 0.49, 0.25) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(franActor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(250, 250) + +cam1 = vtk.vtkCamera() +cam1.SetClippingRange(0.0475572, 2.37786) +cam1.SetFocalPoint(0.052665, -0.129454, -0.0573973) +cam1.SetPosition(0.327637, -0.116299, -0.256418) +cam1.SetViewUp(-0.0225386, 0.999137, 0.034901) +ren.SetActiveCamera(cam1) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/imageWarp.py b/Examples/VisualizationAlgorithms/Python/imageWarp.py new file mode 100644 index 0000000..4a2c37c --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/imageWarp.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python + +# This example shows how to combine data from both the imaging and +# graphics pipelines. The vtkMergeFilter is used to merge the data +# from each together. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read in an image and compute a luminance value. The image is +# extracted as a set of polygons (vtkImageDataGeometryFilter). We then +# will warp the plane using the scalar (luminance) values. +reader = vtk.vtkBMPReader() +reader.SetFileName(VTK_DATA_ROOT + "/Data/masonry.bmp") +luminance = vtk.vtkImageLuminance() +luminance.SetInputConnection(reader.GetOutputPort()) +geometry = vtk.vtkImageDataGeometryFilter() +geometry.SetInputConnection(luminance.GetOutputPort()) +warp = vtk.vtkWarpScalar() +warp.SetInputConnection(geometry.GetOutputPort()) +warp.SetScaleFactor(-0.1) + +# Use vtkMergeFilter to combine the original image with the warped +# geometry. +merge = vtk.vtkMergeFilter() +merge.SetGeometry(warp.GetOutput()) +merge.SetScalars(reader.GetOutput()) +mapper = vtk.vtkDataSetMapper() +mapper.SetInputConnection(merge.GetOutputPort()) +mapper.SetScalarRange(0, 255) +mapper.ImmediateModeRenderingOff() +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +# Create renderer stuff +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(actor) +ren.ResetCamera() +ren.GetActiveCamera().Azimuth(20) +ren.GetActiveCamera().Elevation(30) +ren.SetBackground(0.1, 0.2, 0.4) +ren.ResetCameraClippingRange() + +renWin.SetSize(250, 250) + +cam1 = ren.GetActiveCamera() +cam1.Zoom(1.4) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/officeTube.py b/Examples/VisualizationAlgorithms/Python/officeTube.py new file mode 100644 index 0000000..e00dcf5 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/officeTube.py @@ -0,0 +1,303 @@ +#!/usr/bin/env python + +# This example demonstrates the use of a single streamline and the +# tube filter to create a streamtube. + +import vtk +from vtk.util.misc import vtkGetDataRoot +from vtk.util.colors import * +VTK_DATA_ROOT = vtkGetDataRoot() + +# We read a data file the is a CFD analysis of airflow in an office +# (with ventilation and a burning cigarette). We force an update so +# that we can query the output for its length, i.e., the length of the +# diagonal of the bounding box. This is useful for normalizing the +# data. +reader = vtk.vtkStructuredGridReader() +reader.SetFileName(VTK_DATA_ROOT + "/Data/office.binary.vtk") +reader.Update() + +length = reader.GetOutput().GetLength() + +maxVelocity =reader.GetOutput().GetPointData().GetVectors().GetMaxNorm() +maxTime = 35.0*length/maxVelocity + +# Now we will generate a single streamline in the data. We select the +# integration order to use (RungeKutta order 4) and associate it with +# the streamer. The start position is the position in world space +# where we want to begin streamline integration; and we integrate in +# both directions. The step length is the length of the line segments +# that make up the streamline (i.e., related to display). The +# IntegrationStepLength specifies the integration step length as a +# fraction of the cell size that the streamline is in. +integ = vtk.vtkRungeKutta4() +streamer = vtk.vtkStreamLine() +streamer.SetInputConnection(reader.GetOutputPort()) +streamer.SetStartPosition(0.1, 2.1, 0.5) +streamer.SetMaximumPropagationTime(500) +streamer.SetStepLength(0.5) +streamer.SetIntegrationStepLength(0.05) +streamer.SetIntegrationDirectionToIntegrateBothDirections() +streamer.SetIntegrator(integ) + +# The tube is wrapped around the generated streamline. By varying the +# radius by the inverse of vector magnitude, we are creating a tube +# whose radius is proportional to mass flux (in incompressible flow). +streamTube = vtk.vtkTubeFilter() +streamTube.SetInputConnection(streamer.GetOutputPort()) +streamTube.SetRadius(0.02) +streamTube.SetNumberOfSides(12) +streamTube.SetVaryRadiusToVaryRadiusByVector() +mapStreamTube = vtk.vtkPolyDataMapper() +mapStreamTube.SetInputConnection(streamTube.GetOutputPort()) +mapStreamTube.SetScalarRange(reader.GetOutput().GetPointData().GetScalars().GetRange()) +streamTubeActor = vtk.vtkActor() +streamTubeActor.SetMapper(mapStreamTube) +streamTubeActor.GetProperty().BackfaceCullingOn() + +# From here on we generate a whole bunch of planes which correspond to +# the geometry in the analysis; tables, bookshelves and so on. +table1 = vtk.vtkStructuredGridGeometryFilter() +table1.SetInputConnection(reader.GetOutputPort()) +table1.SetExtent(11, 15, 7, 9, 8, 8) +mapTable1 = vtk.vtkPolyDataMapper() +mapTable1.SetInputConnection(table1.GetOutputPort()) +mapTable1.ScalarVisibilityOff() +table1Actor = vtk.vtkActor() +table1Actor.SetMapper(mapTable1) +table1Actor.GetProperty().SetColor(.59, .427, .392) + +table2 = vtk.vtkStructuredGridGeometryFilter() +table2.SetInputConnection(reader.GetOutputPort()) +table2.SetExtent(11, 15, 10, 12, 8, 8) +mapTable2 = vtk.vtkPolyDataMapper() +mapTable2.SetInputConnection(table2.GetOutputPort()) +mapTable2.ScalarVisibilityOff() +table2Actor = vtk.vtkActor() +table2Actor.SetMapper(mapTable2) +table2Actor.GetProperty().SetColor(.59, .427, .392) + +FilingCabinet1 = vtk.vtkStructuredGridGeometryFilter() +FilingCabinet1.SetInputConnection(reader.GetOutputPort()) +FilingCabinet1.SetExtent(15, 15, 7, 9, 0, 8) +mapFilingCabinet1 = vtk.vtkPolyDataMapper() +mapFilingCabinet1.SetInputConnection(FilingCabinet1.GetOutputPort()) +mapFilingCabinet1.ScalarVisibilityOff() +FilingCabinet1Actor = vtk.vtkActor() +FilingCabinet1Actor.SetMapper(mapFilingCabinet1) +FilingCabinet1Actor.GetProperty().SetColor(.8, .8, .6) + +FilingCabinet2 = vtk.vtkStructuredGridGeometryFilter() +FilingCabinet2.SetInputConnection(reader.GetOutputPort()) +FilingCabinet2.SetExtent(15, 15, 10, 12, 0, 8) +mapFilingCabinet2 = vtk.vtkPolyDataMapper() +mapFilingCabinet2.SetInputConnection(FilingCabinet2.GetOutputPort()) +mapFilingCabinet2.ScalarVisibilityOff() +FilingCabinet2Actor = vtk.vtkActor() +FilingCabinet2Actor.SetMapper(mapFilingCabinet2) +FilingCabinet2Actor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Top = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Top.SetInputConnection(reader.GetOutputPort()) +bookshelf1Top.SetExtent(13, 13, 0, 4, 0, 11) +mapBookshelf1Top = vtk.vtkPolyDataMapper() +mapBookshelf1Top.SetInputConnection(bookshelf1Top.GetOutputPort()) +mapBookshelf1Top.ScalarVisibilityOff() +bookshelf1TopActor = vtk.vtkActor() +bookshelf1TopActor.SetMapper(mapBookshelf1Top) +bookshelf1TopActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Bottom = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Bottom.SetInputConnection(reader.GetOutputPort()) +bookshelf1Bottom.SetExtent(20, 20, 0, 4, 0, 11) +mapBookshelf1Bottom = vtk.vtkPolyDataMapper() +mapBookshelf1Bottom.SetInputConnection(bookshelf1Bottom.GetOutputPort()) +mapBookshelf1Bottom.ScalarVisibilityOff() +bookshelf1BottomActor = vtk.vtkActor() +bookshelf1BottomActor.SetMapper(mapBookshelf1Bottom) +bookshelf1BottomActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Front = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Front.SetInputConnection(reader.GetOutputPort()) +bookshelf1Front.SetExtent(13, 20, 0, 0, 0, 11) +mapBookshelf1Front = vtk.vtkPolyDataMapper() +mapBookshelf1Front.SetInputConnection(bookshelf1Front.GetOutputPort()) +mapBookshelf1Front.ScalarVisibilityOff() +bookshelf1FrontActor = vtk.vtkActor() +bookshelf1FrontActor.SetMapper(mapBookshelf1Front) +bookshelf1FrontActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Back = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Back.SetInputConnection(reader.GetOutputPort()) +bookshelf1Back.SetExtent(13, 20, 4, 4, 0, 11) +mapBookshelf1Back = vtk.vtkPolyDataMapper() +mapBookshelf1Back.SetInputConnection(bookshelf1Back.GetOutputPort()) +mapBookshelf1Back.ScalarVisibilityOff() +bookshelf1BackActor = vtk.vtkActor() +bookshelf1BackActor.SetMapper(mapBookshelf1Back) +bookshelf1BackActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1LHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf1LHS.SetInputConnection(reader.GetOutputPort()) +bookshelf1LHS.SetExtent(13, 20, 0, 4, 0, 0) +mapBookshelf1LHS = vtk.vtkPolyDataMapper() +mapBookshelf1LHS.SetInputConnection(bookshelf1LHS.GetOutputPort()) +mapBookshelf1LHS.ScalarVisibilityOff() +bookshelf1LHSActor = vtk.vtkActor() +bookshelf1LHSActor.SetMapper(mapBookshelf1LHS) +bookshelf1LHSActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1RHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf1RHS.SetInputConnection(reader.GetOutputPort()) +bookshelf1RHS.SetExtent(13, 20, 0, 4, 11, 11) +mapBookshelf1RHS = vtk.vtkPolyDataMapper() +mapBookshelf1RHS.SetInputConnection(bookshelf1RHS.GetOutputPort()) +mapBookshelf1RHS.ScalarVisibilityOff() +bookshelf1RHSActor = vtk.vtkActor() +bookshelf1RHSActor.SetMapper(mapBookshelf1RHS) +bookshelf1RHSActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Top = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Top.SetInputConnection(reader.GetOutputPort()) +bookshelf2Top.SetExtent(13, 13, 15, 19, 0, 11) +mapBookshelf2Top = vtk.vtkPolyDataMapper() +mapBookshelf2Top.SetInputConnection(bookshelf2Top.GetOutputPort()) +mapBookshelf2Top.ScalarVisibilityOff() +bookshelf2TopActor = vtk.vtkActor() +bookshelf2TopActor.SetMapper(mapBookshelf2Top) +bookshelf2TopActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Bottom = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Bottom.SetInputConnection(reader.GetOutputPort()) +bookshelf2Bottom.SetExtent(20, 20, 15, 19, 0, 11) +mapBookshelf2Bottom = vtk.vtkPolyDataMapper() +mapBookshelf2Bottom.SetInputConnection(bookshelf2Bottom.GetOutputPort()) +mapBookshelf2Bottom.ScalarVisibilityOff() +bookshelf2BottomActor = vtk.vtkActor() +bookshelf2BottomActor.SetMapper(mapBookshelf2Bottom) +bookshelf2BottomActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Front = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Front.SetInputConnection(reader.GetOutputPort()) +bookshelf2Front.SetExtent(13, 20, 15, 15, 0, 11) +mapBookshelf2Front = vtk.vtkPolyDataMapper() +mapBookshelf2Front.SetInputConnection(bookshelf2Front.GetOutputPort()) +mapBookshelf2Front.ScalarVisibilityOff() +bookshelf2FrontActor = vtk.vtkActor() +bookshelf2FrontActor.SetMapper(mapBookshelf2Front) +bookshelf2FrontActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Back = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Back.SetInputConnection(reader.GetOutputPort()) +bookshelf2Back.SetExtent(13, 20, 19, 19, 0, 11) +mapBookshelf2Back = vtk.vtkPolyDataMapper() +mapBookshelf2Back.SetInputConnection(bookshelf2Back.GetOutputPort()) +mapBookshelf2Back.ScalarVisibilityOff() +bookshelf2BackActor = vtk.vtkActor() +bookshelf2BackActor.SetMapper(mapBookshelf2Back) +bookshelf2BackActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2LHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf2LHS.SetInputConnection(reader.GetOutputPort()) +bookshelf2LHS.SetExtent(13, 20, 15, 19, 0, 0) +mapBookshelf2LHS = vtk.vtkPolyDataMapper() +mapBookshelf2LHS.SetInputConnection(bookshelf2LHS.GetOutputPort()) +mapBookshelf2LHS.ScalarVisibilityOff() +bookshelf2LHSActor = vtk.vtkActor() +bookshelf2LHSActor.SetMapper(mapBookshelf2LHS) +bookshelf2LHSActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2RHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf2RHS.SetInputConnection(reader.GetOutputPort()) +bookshelf2RHS.SetExtent(13, 20, 15, 19, 11, 11) +mapBookshelf2RHS = vtk.vtkPolyDataMapper() +mapBookshelf2RHS.SetInputConnection(bookshelf2RHS.GetOutputPort()) +mapBookshelf2RHS.ScalarVisibilityOff() +bookshelf2RHSActor = vtk.vtkActor() +bookshelf2RHSActor.SetMapper(mapBookshelf2RHS) +bookshelf2RHSActor.GetProperty().SetColor(.8, .8, .6) + +window = vtk.vtkStructuredGridGeometryFilter() +window.SetInputConnection(reader.GetOutputPort()) +window.SetExtent(20, 20, 6, 13, 10, 13) +mapWindow = vtk.vtkPolyDataMapper() +mapWindow.SetInputConnection(window.GetOutputPort()) +mapWindow.ScalarVisibilityOff() +windowActor = vtk.vtkActor() +windowActor.SetMapper(mapWindow) +windowActor.GetProperty().SetColor(.3, .3, .5) + +outlet = vtk.vtkStructuredGridGeometryFilter() +outlet.SetInputConnection(reader.GetOutputPort()) +outlet.SetExtent(0, 0, 9, 10, 14, 16) +mapOutlet = vtk.vtkPolyDataMapper() +mapOutlet.SetInputConnection(outlet.GetOutputPort()) +mapOutlet.ScalarVisibilityOff() +outletActor = vtk.vtkActor() +outletActor.SetMapper(mapOutlet) +outletActor.GetProperty().SetColor(0, 0, 0) + +inlet = vtk.vtkStructuredGridGeometryFilter() +inlet.SetInputConnection(reader.GetOutputPort()) +inlet.SetExtent(0, 0, 9, 10, 0, 6) +mapInlet = vtk.vtkPolyDataMapper() +mapInlet.SetInputConnection(inlet.GetOutputPort()) +mapInlet.ScalarVisibilityOff() +inletActor = vtk.vtkActor() +inletActor.SetMapper(mapInlet) +inletActor.GetProperty().SetColor(0, 0, 0) + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(reader.GetOutputPort()) +mapOutline = vtk.vtkPolyDataMapper() +mapOutline.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(mapOutline) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Now create the usual graphics stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +ren.AddActor(table1Actor) +ren.AddActor(table2Actor) +ren.AddActor(FilingCabinet1Actor) +ren.AddActor(FilingCabinet2Actor) +ren.AddActor(bookshelf1TopActor) +ren.AddActor(bookshelf1BottomActor) +ren.AddActor(bookshelf1FrontActor) +ren.AddActor(bookshelf1BackActor) +ren.AddActor(bookshelf1LHSActor) +ren.AddActor(bookshelf1RHSActor) +ren.AddActor(bookshelf2TopActor) +ren.AddActor(bookshelf2BottomActor) +ren.AddActor(bookshelf2FrontActor) +ren.AddActor(bookshelf2BackActor) +ren.AddActor(bookshelf2LHSActor) +ren.AddActor(bookshelf2RHSActor) +ren.AddActor(windowActor) +ren.AddActor(outletActor) +ren.AddActor(inletActor) +ren.AddActor(outlineActor) +ren.AddActor(streamTubeActor) + +ren.SetBackground(slate_grey) + +# Here we specify a particular view. +aCamera = vtk.vtkCamera() +aCamera.SetClippingRange(0.726079, 36.3039) +aCamera.SetFocalPoint(2.43584, 2.15046, 1.11104) +aCamera.SetPosition(-4.76183, -10.4426, 3.17203) +aCamera.SetViewUp(0.0511273, 0.132773, 0.989827) +aCamera.SetViewAngle(18.604) +aCamera.Zoom(1.2) + +ren.SetActiveCamera(aCamera) +renWin.SetSize(500, 300) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/officeTubes.py b/Examples/VisualizationAlgorithms/Python/officeTubes.py new file mode 100644 index 0000000..7d8bce4 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/officeTubes.py @@ -0,0 +1,311 @@ +#!/usr/bin/env python + +# This example demonstrates the use of streamlines generated from seeds, +# combined with a tube filter to create several streamtubes. + +import vtk +from vtk.util.misc import vtkGetDataRoot +from vtk.util.colors import * +VTK_DATA_ROOT = vtkGetDataRoot() + +# We read a data file the is a CFD analysis of airflow in an office +# (with ventilation and a burning cigarette). We force an update so +# that we can query the output for its length, i.e., the length of the +# diagonal of the bounding box. This is useful for normalizing the +# data. +reader = vtk.vtkStructuredGridReader() +reader.SetFileName(VTK_DATA_ROOT + "/Data/office.binary.vtk") +reader.Update() + +length = reader.GetOutput().GetLength() + +maxVelocity =reader.GetOutput().GetPointData().GetVectors().GetMaxNorm() +maxTime = 35.0*length/maxVelocity + +# Now we will generate multiple streamlines in the data. We create a +# random cloud of points and then use those as integration seeds. We +# select the integration order to use (RungeKutta order 4) and +# associate it with the streamer. The start position is the position +# in world space where we want to begin streamline integration; and we +# integrate in both directions. The step length is the length of the +# line segments that make up the streamline (i.e., related to +# display). The IntegrationStepLength specifies the integration step +# length as a fraction of the cell size that the streamline is in. + +# Create source for streamtubes +seeds = vtk.vtkPointSource() +seeds.SetRadius(0.15) +seeds.SetCenter(0.1, 2.1, 0.5) +seeds.SetNumberOfPoints(6) + +integ = vtk.vtkRungeKutta4() +streamer = vtk.vtkStreamLine() +streamer.SetInputConnection(reader.GetOutputPort()) +streamer.SetSource(seeds.GetOutput()) +streamer.SetMaximumPropagationTime(500) +streamer.SetStepLength(0.5) +streamer.SetIntegrationStepLength(0.05) +streamer.SetIntegrationDirectionToIntegrateBothDirections() +streamer.SetIntegrator(integ) + +# The tube is wrapped around the generated streamline. By varying the +# radius by the inverse of vector magnitude, we are creating a tube +# whose radius is proportional to mass flux (in incompressible flow). +streamTube = vtk.vtkTubeFilter() +streamTube.SetInputConnection(streamer.GetOutputPort()) +streamTube.SetRadius(0.02) +streamTube.SetNumberOfSides(12) +streamTube.SetVaryRadiusToVaryRadiusByVector() +mapStreamTube = vtk.vtkPolyDataMapper() +mapStreamTube.SetInputConnection(streamTube.GetOutputPort()) +mapStreamTube.SetScalarRange(reader.GetOutput().GetPointData().GetScalars().GetRange()) +streamTubeActor = vtk.vtkActor() +streamTubeActor.SetMapper(mapStreamTube) +streamTubeActor.GetProperty().BackfaceCullingOn() + +# From here on we generate a whole bunch of planes which correspond to +# the geometry in the analysis; tables, bookshelves and so on. +table1 = vtk.vtkStructuredGridGeometryFilter() +table1.SetInputConnection(reader.GetOutputPort()) +table1.SetExtent(11, 15, 7, 9, 8, 8) +mapTable1 = vtk.vtkPolyDataMapper() +mapTable1.SetInputConnection(table1.GetOutputPort()) +mapTable1.ScalarVisibilityOff() +table1Actor = vtk.vtkActor() +table1Actor.SetMapper(mapTable1) +table1Actor.GetProperty().SetColor(.59, .427, .392) + +table2 = vtk.vtkStructuredGridGeometryFilter() +table2.SetInputConnection(reader.GetOutputPort()) +table2.SetExtent(11, 15, 10, 12, 8, 8) +mapTable2 = vtk.vtkPolyDataMapper() +mapTable2.SetInputConnection(table2.GetOutputPort()) +mapTable2.ScalarVisibilityOff() +table2Actor = vtk.vtkActor() +table2Actor.SetMapper(mapTable2) +table2Actor.GetProperty().SetColor(.59, .427, .392) + +FilingCabinet1 = vtk.vtkStructuredGridGeometryFilter() +FilingCabinet1.SetInputConnection(reader.GetOutputPort()) +FilingCabinet1.SetExtent(15, 15, 7, 9, 0, 8) +mapFilingCabinet1 = vtk.vtkPolyDataMapper() +mapFilingCabinet1.SetInputConnection(FilingCabinet1.GetOutputPort()) +mapFilingCabinet1.ScalarVisibilityOff() +FilingCabinet1Actor = vtk.vtkActor() +FilingCabinet1Actor.SetMapper(mapFilingCabinet1) +FilingCabinet1Actor.GetProperty().SetColor(.8, .8, .6) + +FilingCabinet2 = vtk.vtkStructuredGridGeometryFilter() +FilingCabinet2.SetInputConnection(reader.GetOutputPort()) +FilingCabinet2.SetExtent(15, 15, 10, 12, 0, 8) +mapFilingCabinet2 = vtk.vtkPolyDataMapper() +mapFilingCabinet2.SetInputConnection(FilingCabinet2.GetOutputPort()) +mapFilingCabinet2.ScalarVisibilityOff() +FilingCabinet2Actor = vtk.vtkActor() +FilingCabinet2Actor.SetMapper(mapFilingCabinet2) +FilingCabinet2Actor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Top = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Top.SetInputConnection(reader.GetOutputPort()) +bookshelf1Top.SetExtent(13, 13, 0, 4, 0, 11) +mapBookshelf1Top = vtk.vtkPolyDataMapper() +mapBookshelf1Top.SetInputConnection(bookshelf1Top.GetOutputPort()) +mapBookshelf1Top.ScalarVisibilityOff() +bookshelf1TopActor = vtk.vtkActor() +bookshelf1TopActor.SetMapper(mapBookshelf1Top) +bookshelf1TopActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Bottom = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Bottom.SetInputConnection(reader.GetOutputPort()) +bookshelf1Bottom.SetExtent(20, 20, 0, 4, 0, 11) +mapBookshelf1Bottom = vtk.vtkPolyDataMapper() +mapBookshelf1Bottom.SetInputConnection(bookshelf1Bottom.GetOutputPort()) +mapBookshelf1Bottom.ScalarVisibilityOff() +bookshelf1BottomActor = vtk.vtkActor() +bookshelf1BottomActor.SetMapper(mapBookshelf1Bottom) +bookshelf1BottomActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Front = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Front.SetInputConnection(reader.GetOutputPort()) +bookshelf1Front.SetExtent(13, 20, 0, 0, 0, 11) +mapBookshelf1Front = vtk.vtkPolyDataMapper() +mapBookshelf1Front.SetInputConnection(bookshelf1Front.GetOutputPort()) +mapBookshelf1Front.ScalarVisibilityOff() +bookshelf1FrontActor = vtk.vtkActor() +bookshelf1FrontActor.SetMapper(mapBookshelf1Front) +bookshelf1FrontActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1Back = vtk.vtkStructuredGridGeometryFilter() +bookshelf1Back.SetInputConnection(reader.GetOutputPort()) +bookshelf1Back.SetExtent(13, 20, 4, 4, 0, 11) +mapBookshelf1Back = vtk.vtkPolyDataMapper() +mapBookshelf1Back.SetInputConnection(bookshelf1Back.GetOutputPort()) +mapBookshelf1Back.ScalarVisibilityOff() +bookshelf1BackActor = vtk.vtkActor() +bookshelf1BackActor.SetMapper(mapBookshelf1Back) +bookshelf1BackActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1LHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf1LHS.SetInputConnection(reader.GetOutputPort()) +bookshelf1LHS.SetExtent(13, 20, 0, 4, 0, 0) +mapBookshelf1LHS = vtk.vtkPolyDataMapper() +mapBookshelf1LHS.SetInputConnection(bookshelf1LHS.GetOutputPort()) +mapBookshelf1LHS.ScalarVisibilityOff() +bookshelf1LHSActor = vtk.vtkActor() +bookshelf1LHSActor.SetMapper(mapBookshelf1LHS) +bookshelf1LHSActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf1RHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf1RHS.SetInputConnection(reader.GetOutputPort()) +bookshelf1RHS.SetExtent(13, 20, 0, 4, 11, 11) +mapBookshelf1RHS = vtk.vtkPolyDataMapper() +mapBookshelf1RHS.SetInputConnection(bookshelf1RHS.GetOutputPort()) +mapBookshelf1RHS.ScalarVisibilityOff() +bookshelf1RHSActor = vtk.vtkActor() +bookshelf1RHSActor.SetMapper(mapBookshelf1RHS) +bookshelf1RHSActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Top = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Top.SetInputConnection(reader.GetOutputPort()) +bookshelf2Top.SetExtent(13, 13, 15, 19, 0, 11) +mapBookshelf2Top = vtk.vtkPolyDataMapper() +mapBookshelf2Top.SetInputConnection(bookshelf2Top.GetOutputPort()) +mapBookshelf2Top.ScalarVisibilityOff() +bookshelf2TopActor = vtk.vtkActor() +bookshelf2TopActor.SetMapper(mapBookshelf2Top) +bookshelf2TopActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Bottom = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Bottom.SetInputConnection(reader.GetOutputPort()) +bookshelf2Bottom.SetExtent(20, 20, 15, 19, 0, 11) +mapBookshelf2Bottom = vtk.vtkPolyDataMapper() +mapBookshelf2Bottom.SetInputConnection(bookshelf2Bottom.GetOutputPort()) +mapBookshelf2Bottom.ScalarVisibilityOff() +bookshelf2BottomActor = vtk.vtkActor() +bookshelf2BottomActor.SetMapper(mapBookshelf2Bottom) +bookshelf2BottomActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Front = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Front.SetInputConnection(reader.GetOutputPort()) +bookshelf2Front.SetExtent(13, 20, 15, 15, 0, 11) +mapBookshelf2Front = vtk.vtkPolyDataMapper() +mapBookshelf2Front.SetInputConnection(bookshelf2Front.GetOutputPort()) +mapBookshelf2Front.ScalarVisibilityOff() +bookshelf2FrontActor = vtk.vtkActor() +bookshelf2FrontActor.SetMapper(mapBookshelf2Front) +bookshelf2FrontActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2Back = vtk.vtkStructuredGridGeometryFilter() +bookshelf2Back.SetInputConnection(reader.GetOutputPort()) +bookshelf2Back.SetExtent(13, 20, 19, 19, 0, 11) +mapBookshelf2Back = vtk.vtkPolyDataMapper() +mapBookshelf2Back.SetInputConnection(bookshelf2Back.GetOutputPort()) +mapBookshelf2Back.ScalarVisibilityOff() +bookshelf2BackActor = vtk.vtkActor() +bookshelf2BackActor.SetMapper(mapBookshelf2Back) +bookshelf2BackActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2LHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf2LHS.SetInputConnection(reader.GetOutputPort()) +bookshelf2LHS.SetExtent(13, 20, 15, 19, 0, 0) +mapBookshelf2LHS = vtk.vtkPolyDataMapper() +mapBookshelf2LHS.SetInputConnection(bookshelf2LHS.GetOutputPort()) +mapBookshelf2LHS.ScalarVisibilityOff() +bookshelf2LHSActor = vtk.vtkActor() +bookshelf2LHSActor.SetMapper(mapBookshelf2LHS) +bookshelf2LHSActor.GetProperty().SetColor(.8, .8, .6) + +bookshelf2RHS = vtk.vtkStructuredGridGeometryFilter() +bookshelf2RHS.SetInputConnection(reader.GetOutputPort()) +bookshelf2RHS.SetExtent(13, 20, 15, 19, 11, 11) +mapBookshelf2RHS = vtk.vtkPolyDataMapper() +mapBookshelf2RHS.SetInputConnection(bookshelf2RHS.GetOutputPort()) +mapBookshelf2RHS.ScalarVisibilityOff() +bookshelf2RHSActor = vtk.vtkActor() +bookshelf2RHSActor.SetMapper(mapBookshelf2RHS) +bookshelf2RHSActor.GetProperty().SetColor(.8, .8, .6) + +window = vtk.vtkStructuredGridGeometryFilter() +window.SetInputConnection(reader.GetOutputPort()) +window.SetExtent(20, 20, 6, 13, 10, 13) +mapWindow = vtk.vtkPolyDataMapper() +mapWindow.SetInputConnection(window.GetOutputPort()) +mapWindow.ScalarVisibilityOff() +windowActor = vtk.vtkActor() +windowActor.SetMapper(mapWindow) +windowActor.GetProperty().SetColor(.3, .3, .5) + +outlet = vtk.vtkStructuredGridGeometryFilter() +outlet.SetInputConnection(reader.GetOutputPort()) +outlet.SetExtent(0, 0, 9, 10, 14, 16) +mapOutlet = vtk.vtkPolyDataMapper() +mapOutlet.SetInputConnection(outlet.GetOutputPort()) +mapOutlet.ScalarVisibilityOff() +outletActor = vtk.vtkActor() +outletActor.SetMapper(mapOutlet) +outletActor.GetProperty().SetColor(0, 0, 0) + +inlet = vtk.vtkStructuredGridGeometryFilter() +inlet.SetInputConnection(reader.GetOutputPort()) +inlet.SetExtent(0, 0, 9, 10, 0, 6) +mapInlet = vtk.vtkPolyDataMapper() +mapInlet.SetInputConnection(inlet.GetOutputPort()) +mapInlet.ScalarVisibilityOff() +inletActor = vtk.vtkActor() +inletActor.SetMapper(mapInlet) +inletActor.GetProperty().SetColor(0, 0, 0) + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(reader.GetOutputPort()) +mapOutline = vtk.vtkPolyDataMapper() +mapOutline.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(mapOutline) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Now create the usual graphics stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +ren.AddActor(table1Actor) +ren.AddActor(table2Actor) +ren.AddActor(FilingCabinet1Actor) +ren.AddActor(FilingCabinet2Actor) +ren.AddActor(bookshelf1TopActor) +ren.AddActor(bookshelf1BottomActor) +ren.AddActor(bookshelf1FrontActor) +ren.AddActor(bookshelf1BackActor) +ren.AddActor(bookshelf1LHSActor) +ren.AddActor(bookshelf1RHSActor) +ren.AddActor(bookshelf2TopActor) +ren.AddActor(bookshelf2BottomActor) +ren.AddActor(bookshelf2FrontActor) +ren.AddActor(bookshelf2BackActor) +ren.AddActor(bookshelf2LHSActor) +ren.AddActor(bookshelf2RHSActor) +ren.AddActor(windowActor) +ren.AddActor(outletActor) +ren.AddActor(inletActor) +ren.AddActor(outlineActor) +ren.AddActor(streamTubeActor) + +ren.SetBackground(slate_grey) + +# Here we specify a particular view. +aCamera = vtk.vtkCamera() +aCamera.SetClippingRange(0.726079, 36.3039) +aCamera.SetFocalPoint(2.43584, 2.15046, 1.11104) +aCamera.SetPosition(-4.76183, -10.4426, 3.17203) +aCamera.SetViewUp(0.0511273, 0.132773, 0.989827) +aCamera.SetViewAngle(18.604) +aCamera.Zoom(1.2) + +ren.SetActiveCamera(aCamera) +renWin.SetSize(500, 300) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/probeComb.py b/Examples/VisualizationAlgorithms/Python/probeComb.py new file mode 100644 index 0000000..0a323a5 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/probeComb.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +# This shows how to probe a dataset with a plane. The probed data is +# then contoured. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# We create three planes and position them in the correct position +# using transform filters. They are then appended together and used as +# a probe. +plane = vtk.vtkPlaneSource() +plane.SetResolution(50, 50) +transP1 = vtk.vtkTransform() +transP1.Translate(3.7, 0.0, 28.37) +transP1.Scale(5, 5, 5) +transP1.RotateY(90) +tpd1 = vtk.vtkTransformPolyDataFilter() +tpd1.SetInputConnection(plane.GetOutputPort()) +tpd1.SetTransform(transP1) +outTpd1 = vtk.vtkOutlineFilter() +outTpd1.SetInputConnection(tpd1.GetOutputPort()) +mapTpd1 = vtk.vtkPolyDataMapper() +mapTpd1.SetInputConnection(outTpd1.GetOutputPort()) +tpd1Actor = vtk.vtkActor() +tpd1Actor.SetMapper(mapTpd1) +tpd1Actor.GetProperty().SetColor(0, 0, 0) + +transP2 = vtk.vtkTransform() +transP2.Translate(9.2, 0.0, 31.20) +transP2.Scale(5, 5, 5) +transP2.RotateY(90) +tpd2 = vtk.vtkTransformPolyDataFilter() +tpd2.SetInputConnection(plane.GetOutputPort()) +tpd2.SetTransform(transP2) +outTpd2 = vtk.vtkOutlineFilter() +outTpd2.SetInputConnection(tpd2.GetOutputPort()) +mapTpd2 = vtk.vtkPolyDataMapper() +mapTpd2.SetInputConnection(outTpd2.GetOutputPort()) +tpd2Actor = vtk.vtkActor() +tpd2Actor.SetMapper(mapTpd2) +tpd2Actor.GetProperty().SetColor(0, 0, 0) + +transP3 = vtk.vtkTransform() +transP3.Translate(13.27, 0.0, 33.30) +transP3.Scale(5, 5, 5) +transP3.RotateY(90) +tpd3 = vtk.vtkTransformPolyDataFilter() +tpd3.SetInputConnection(plane.GetOutputPort()) +tpd3.SetTransform(transP3) +outTpd3 = vtk.vtkOutlineFilter() +outTpd3.SetInputConnection(tpd3.GetOutputPort()) +mapTpd3 = vtk.vtkPolyDataMapper() +mapTpd3.SetInputConnection(outTpd3.GetOutputPort()) +tpd3Actor = vtk.vtkActor() +tpd3Actor.SetMapper(mapTpd3) +tpd3Actor.GetProperty().SetColor(0, 0, 0) + +appendF = vtk.vtkAppendPolyData() +appendF.AddInput(tpd1.GetOutput()) +appendF.AddInput(tpd2.GetOutput()) +appendF.AddInput(tpd3.GetOutput()) + +# The vtkProbeFilter takes two inputs. One is a dataset to use as the +# probe geometry (SetInput); the other is the data to probe +# (SetSource). The output dataset structure (geometry and topology) of +# the probe is the same as the structure of the input. The probing +# process generates new data values resampled from the source. +probe = vtk.vtkProbeFilter() +probe.SetInputConnection(appendF.GetOutputPort()) +probe.SetSource(pl3d.GetOutput()) + +contour = vtk.vtkContourFilter() +contour.SetInputConnection(probe.GetOutputPort()) +contour.GenerateValues(50, pl3d.GetOutput().GetScalarRange()) +contourMapper = vtk.vtkPolyDataMapper() +contourMapper.SetInputConnection(contour.GetOutputPort()) +contourMapper.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +planeActor = vtk.vtkActor() +planeActor.SetMapper(contourMapper) + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +ren.AddActor(outlineActor) +ren.AddActor(planeActor) +ren.AddActor(tpd1Actor) +ren.AddActor(tpd2Actor) +ren.AddActor(tpd3Actor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(400, 400) + +ren.ResetCamera() +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(8.88908, 0.595038, 29.3342) +cam1.SetPosition(-12.3332, 31.7479, 41.2387) +cam1.SetViewUp(0.060772, -0.319905, 0.945498) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/smoothFran.py b/Examples/VisualizationAlgorithms/Python/smoothFran.py new file mode 100644 index 0000000..a640e4d --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/smoothFran.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +# This example shows how to use decimation to reduce a polygonal +# mesh. We also use mesh smoothing and generate surface normals to +# give a pleasing result. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# We start by reading some data that was originally captured from a +# Cyberware laser digitizing system. +fran = vtk.vtkPolyDataReader() +fran.SetFileName(VTK_DATA_ROOT + "/Data/fran_cut.vtk") + +# We want to preserve topology (not let any cracks form). This may +# limit the total reduction possible, which we have specified at 90%. +deci = vtk.vtkDecimatePro() +deci.SetInputConnection(fran.GetOutputPort()) +deci.SetTargetReduction(0.9) +deci.PreserveTopologyOn() +smoother = vtk.vtkSmoothPolyDataFilter() +smoother.SetInputConnection(deci.GetOutputPort()) +smoother.SetNumberOfIterations(50) +normals = vtk.vtkPolyDataNormals() +normals.SetInputConnection(smoother.GetOutputPort()) +normals.FlipNormalsOn() +franMapper = vtk.vtkPolyDataMapper() +franMapper.SetInputConnection(normals.GetOutputPort()) +franActor = vtk.vtkActor() +franActor.SetMapper(franMapper) +franActor.GetProperty().SetColor(1.0, 0.49, 0.25) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(franActor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(250, 250) + +cam1 = vtk.vtkCamera() +cam1.SetClippingRange(0.0475572, 2.37786) +cam1.SetFocalPoint(0.052665, -0.129454, -0.0573973) +cam1.SetPosition(0.327637, -0.116299, -0.256418) +cam1.SetViewUp(-0.0225386, 0.999137, 0.034901) +ren.SetActiveCamera(cam1) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/spikeF.py b/Examples/VisualizationAlgorithms/Python/spikeF.py new file mode 100644 index 0000000..d1e97a2 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/spikeF.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python + +# This example demonstrates the use of glyphing. We also use a mask filter +# to select a subset of points to glyph. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read a data file. This originally was a Cyberware laser digitizer scan +# of Fran J.'s face. Surface normals are generated based on local geometry +# (i.e., the polygon normals surrounding eash point are averaged). We flip +# the normals because we want them to point out from Fran's face. +fran = vtk.vtkPolyDataReader() +fran.SetFileName(VTK_DATA_ROOT + "/Data/fran_cut.vtk") +normals = vtk.vtkPolyDataNormals() +normals.SetInputConnection(fran.GetOutputPort()) +normals.FlipNormalsOn() +franMapper = vtk.vtkPolyDataMapper() +franMapper.SetInputConnection(normals.GetOutputPort()) +franActor = vtk.vtkActor() +franActor.SetMapper(franMapper) +franActor.GetProperty().SetColor(1.0, 0.49, 0.25) + +# We subsample the dataset because we want to glyph just a subset of +# the points. Otherwise the display is cluttered and cannot be easily +# read. The RandonModeOn and SetOnRatio combine to random select one out +# of every 10 points in the dataset. +ptMask = vtk.vtkMaskPoints() +ptMask.SetInputConnection(normals.GetOutputPort()) +ptMask.SetOnRatio(10) +ptMask.RandomModeOn() + +# In this case we are using a cone as a glyph. We transform the cone so +# its base is at 0,0,0. This is the point where glyph rotation occurs. +cone = vtk.vtkConeSource() +cone.SetResolution(6) +transform = vtk.vtkTransform() +transform.Translate(0.5, 0.0, 0.0) +transformF = vtk.vtkTransformPolyDataFilter() +transformF.SetInputConnection(cone.GetOutputPort()) +transformF.SetTransform(transform) + +# vtkGlyph3D takes two inputs: the input point set (SetInput) which can be +# any vtkDataSet; and the glyph (SetSource) which must be a vtkPolyData. +# We are interested in orienting the glyphs by the surface normals that +# we previosuly generated. +glyph = vtk.vtkGlyph3D() +glyph.SetInputConnection(ptMask.GetOutputPort()) +glyph.SetSource(transformF.GetOutput()) +glyph.SetVectorModeToUseNormal() +glyph.SetScaleModeToScaleByVector() +glyph.SetScaleFactor(0.004) +spikeMapper = vtk.vtkPolyDataMapper() +spikeMapper.SetInputConnection(glyph.GetOutputPort()) +spikeActor = vtk.vtkActor() +spikeActor.SetMapper(spikeMapper) +spikeActor.GetProperty().SetColor(0.0, 0.79, 0.34) + +# Create the RenderWindow, Renderer and both Actors +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(franActor) +ren.AddActor(spikeActor) + +renWin.SetSize(500, 500) +ren.SetBackground(0.1, 0.2, 0.4) + +# Set a nice camera position. +ren.ResetCamera() +cam1 = ren.GetActiveCamera() +cam1.Zoom(1.4) +cam1.Azimuth(110) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/streamSurface.py b/Examples/VisualizationAlgorithms/Python/streamSurface.py new file mode 100644 index 0000000..19e62e0 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/streamSurface.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python + +# This example demonstrates the generation of a streamsurface. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Read the data and specify which scalars and vectors to read. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# We use a rake to generate a series of streamline starting points +# scattered along a line. Each point will generate a streamline. These +# streamlines are then fed to the vtkRuledSurfaceFilter which stitches +# the lines together to form a surface. +rake = vtk.vtkLineSource() +rake.SetPoint1(15, -5, 32) +rake.SetPoint2(15, 5, 32) +rake.SetResolution(21) +rakeMapper = vtk.vtkPolyDataMapper() +rakeMapper.SetInputConnection(rake.GetOutputPort()) +rakeActor = vtk.vtkActor() +rakeActor.SetMapper(rakeMapper) + +integ = vtk.vtkRungeKutta4() +sl = vtk.vtkStreamLine() +sl.SetInputConnection(pl3d.GetOutputPort()) +sl.SetSource(rake.GetOutput()) +sl.SetIntegrator(integ) +sl.SetMaximumPropagationTime(0.1) +sl.SetIntegrationStepLength(0.1) +sl.SetIntegrationDirectionToBackward() +sl.SetStepLength(0.001) + +# The ruled surface stiches together lines with triangle strips. +# Note the SetOnRatio method. It turns on every other strip that +# the filter generates (only when multiple lines are input). +scalarSurface = vtk.vtkRuledSurfaceFilter() +scalarSurface.SetInputConnection(sl.GetOutputPort()) +scalarSurface.SetOffset(0) +scalarSurface.SetOnRatio(2) +scalarSurface.PassLinesOn() +scalarSurface.SetRuledModeToPointWalk() +scalarSurface.SetDistanceFactor(30) +mapper = vtk.vtkPolyDataMapper() +mapper.SetInputConnection(scalarSurface.GetOutputPort()) +mapper.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +# Put an outline around for context. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Now create the usual graphics stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +ren.AddActor(rakeActor) +ren.AddActor(actor) +ren.AddActor(outlineActor) +ren.SetBackground(1, 1, 1) + +renWin.SetSize(300, 300) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Python/warpComb.py b/Examples/VisualizationAlgorithms/Python/warpComb.py new file mode 100644 index 0000000..de5673d --- /dev/null +++ b/Examples/VisualizationAlgorithms/Python/warpComb.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +# This example demonstrates how to extract "computational planes" from +# a structured dataset. Structured data has a natural, logical +# coordinate system based on i-j-k indices. Specifying imin,imax, +# jmin,jmax, kmin,kmax pairs can indicate a point, line, plane, or +# volume of data. +# +# In this example, we extract three planes and warp them using scalar +# values in the direction of the local normal at each point. This +# gives a sort of "velocity profile" that indicates the nature of the +# flow. + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Here we read data from a annular combustor. A combustor burns fuel +# and air in a gas turbine (e.g., a jet engine) and the hot gas +# eventually makes its way to the turbine section. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# Planes are specified using a imin,imax, jmin,jmax, kmin,kmax +# coordinate specification. Min and max i,j,k values are clamped to 0 +# and maximum value. +plane = vtk.vtkStructuredGridGeometryFilter() +plane.SetInputConnection(pl3d.GetOutputPort()) +plane.SetExtent(10, 10, 1, 100, 1, 100) +plane2 = vtk.vtkStructuredGridGeometryFilter() +plane2.SetInputConnection(pl3d.GetOutputPort()) +plane2.SetExtent(30, 30, 1, 100, 1, 100) +plane3 = vtk.vtkStructuredGridGeometryFilter() +plane3.SetInputConnection(pl3d.GetOutputPort()) +plane3.SetExtent(45, 45, 1, 100, 1, 100) + +# We use an append filter because that way we can do the warping, +# etc. just using a single pipeline and actor. +appendF = vtk.vtkAppendPolyData() +appendF.AddInput(plane.GetOutput()) +appendF.AddInput(plane2.GetOutput()) +appendF.AddInput(plane3.GetOutput()) +warp = vtk.vtkWarpScalar() +warp.SetInputConnection(appendF.GetOutputPort()) +warp.UseNormalOn() +warp.SetNormal(1.0, 0.0, 0.0) +warp.SetScaleFactor(2.5) +normals = vtk.vtkPolyDataNormals() +normals.SetInput(warp.GetPolyDataOutput()) +normals.SetFeatureAngle(60) +planeMapper = vtk.vtkPolyDataMapper() +planeMapper.SetInputConnection(normals.GetOutputPort()) +planeMapper.SetScalarRange(pl3d.GetOutput().GetScalarRange()) +planeActor = vtk.vtkActor() +planeActor.SetMapper(planeMapper) + +# The outline provides context for the data and the planes. +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) +outlineActor.GetProperty().SetColor(0, 0, 0) + +# Create the usual graphics stuff. +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +ren.AddActor(outlineActor) +ren.AddActor(planeActor) +ren.SetBackground(1, 1, 1) +renWin.SetSize(500, 500) + +# Create an initial view. +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(8.88908, 0.595038, 29.3342) +cam1.SetPosition(-12.3332, 31.7479, 41.2387) +cam1.SetViewUp(0.060772, -0.319905, 0.945498) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VisualizationAlgorithms/Tcl/BandContourTerrain.tcl b/Examples/VisualizationAlgorithms/Tcl/BandContourTerrain.tcl new file mode 100644 index 0000000..10cb243 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/BandContourTerrain.tcl @@ -0,0 +1,145 @@ +# In this example we show the use of the vtkBandedPolyDataContourFilter. +# This filter creates separate, constant colored bands for a range of scalar +# values. Each band is bounded by two scalar values, and the cell data lying +# within the value has the same cell scalar value. + +package require vtk +package require vtkinteraction +package require vtktesting + +# The lookup table is similar to that used by maps. Two hues are used: a +# brown for land, and a blue for water. The value of the hue is changed to +# give the effect of elevation. +set Scale 5 +vtkLookupTable lutWater + lutWater SetNumberOfColors 10 + lutWater SetHueRange 0.58 0.58 + lutWater SetSaturationRange 0.5 0.1 + lutWater SetValueRange 0.5 1.0 + lutWater Build +vtkLookupTable lutLand + lutLand SetNumberOfColors 10 + lutLand SetHueRange 0.1 0.1 + lutLand SetSaturationRange 0.4 0.1 + lutLand SetValueRange 0.55 0.9 + lutLand Build + + +# The DEM reader reads data and creates an output image. +vtkDEMReader demModel + demModel SetFileName $VTK_DATA_ROOT/Data/SainteHelens.dem + demModel Update + +# We shrink the terrain data down a bit to yield better performance for +# this example. +set shrinkFactor 4 +vtkImageShrink3D shrink + shrink SetShrinkFactors $shrinkFactor $shrinkFactor 1 + shrink SetInputConnection [demModel GetOutputPort] + shrink AveragingOn + +# Convert the image into polygons. +vtkImageDataGeometryFilter geom + geom SetInputConnection [shrink GetOutputPort] + +# Warp the polygons based on elevation. +vtkWarpScalar warp + warp SetInputConnection [geom GetOutputPort] + warp SetNormal 0 0 1 + warp UseNormalOn + warp SetScaleFactor $Scale + +# Create the contour bands. +vtkBandedPolyDataContourFilter bcf + bcf SetInput [warp GetPolyDataOutput] + eval bcf GenerateValues 15 [[demModel GetOutput] GetScalarRange] + bcf SetScalarModeToIndex + bcf GenerateContourEdgesOn + +# Compute normals to give a better look. +vtkPolyDataNormals normals + normals SetInputConnection [bcf GetOutputPort] + normals SetFeatureAngle 60 + normals ConsistencyOff + normals SplittingOff + +vtkPolyDataMapper demMapper + demMapper SetInputConnection [normals GetOutputPort] + eval demMapper SetScalarRange 0 10 + demMapper SetLookupTable lutLand + demMapper SetScalarModeToUseCellData + +vtkLODActor demActor + demActor SetMapper demMapper + +## Create contour edges +vtkPolyDataMapper edgeMapper + edgeMapper SetInput [bcf GetContourEdgesOutput] + edgeMapper SetResolveCoincidentTopologyToPolygonOffset +vtkActor edgeActor + edgeActor SetMapper edgeMapper + [edgeActor GetProperty] SetColor 0 0 0 + +## Test clipping +# Create the contour bands. +vtkBandedPolyDataContourFilter bcf2 + bcf2 SetInput [warp GetPolyDataOutput] + bcf2 ClippingOn + eval bcf2 GenerateValues 10 1000 2000 + bcf2 SetScalarModeToValue + +# Compute normals to give a better look. +vtkPolyDataNormals normals2 + normals2 SetInputConnection [bcf2 GetOutputPort] + normals2 SetFeatureAngle 60 + normals2 ConsistencyOff + normals2 SplittingOff + +vtkLookupTable lut +lut SetNumberOfColors 10 +vtkPolyDataMapper demMapper2 + demMapper2 SetInputConnection [normals2 GetOutputPort] + eval demMapper2 SetScalarRange [[demModel GetOutput] GetScalarRange] + demMapper2 SetLookupTable lut + demMapper2 SetScalarModeToUseCellData + +vtkLODActor demActor2 + demActor2 SetMapper demMapper2 + demActor2 AddPosition 0 15000 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor demActor +ren1 AddActor demActor2 +ren1 AddActor edgeActor + +ren1 SetBackground .4 .4 .4 +renWin SetSize 375 200 + +vtkCamera cam + cam SetPosition -17438.8 2410.62 25470.8 + cam SetFocalPoint 3985.35 11930.6 5922.14 + cam SetViewUp 0 0 1 +ren1 SetActiveCamera cam +ren1 ResetCamera +cam Zoom 2 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren SetDesiredUpdateRate 1 + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} +renWin Render + +wm withdraw . diff --git a/Examples/VisualizationAlgorithms/Tcl/ClipCow.tcl b/Examples/VisualizationAlgorithms/Tcl/ClipCow.tcl new file mode 100644 index 0000000..976a871 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/ClipCow.tcl @@ -0,0 +1,123 @@ +# In this example vtkClipPolyData is used to cut a polygonal model +# of a cow in half. In addition, the open clip is closed by triangulating +# the resulting complex polygons. + +package require vtk +package require vtkinteraction +package require vtktesting + +# First start by reading a cow model. We also generate surface normals for +# prettier rendering. +vtkBYUReader cow + cow SetGeometryFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.g" +vtkPolyDataNormals cowNormals + cowNormals SetInputConnection [cow GetOutputPort] + +# We clip with an implicit function. Here we use a plane positioned near +# the center of the cow model and oriented at an arbitrary angle. +vtkPlane plane + plane SetOrigin 0.25 0 0 + plane SetNormal -1 -1 0 + +# vtkClipPolyData requires an implicit function to define what it is to +# clip with. Any implicit function, including complex boolean combinations +# can be used. Notice that we can specify the value of the implicit function +# with the SetValue method. +vtkClipPolyData clipper + clipper SetInputConnection [cowNormals GetOutputPort] + clipper SetClipFunction plane + clipper GenerateClipScalarsOn + clipper GenerateClippedOutputOn + clipper SetValue 0.5 +vtkPolyDataMapper clipMapper + clipMapper SetInputConnection [clipper GetOutputPort] + clipMapper ScalarVisibilityOff +vtkProperty backProp + eval backProp SetDiffuseColor $tomato +vtkActor clipActor + clipActor SetMapper clipMapper + eval [clipActor GetProperty] SetColor $peacock + clipActor SetBackfaceProperty backProp + +# Here we are cutting the cow. Cutting creates lines where the cut function +# intersects the model. (Clipping removes a portion of the model but the +# dimension of the data does not change.) +# +# The reason we are cutting is to generate a closed polygon at the boundary +# of the clipping process. The cutter generates line segments, the stripper +# then puts them together into polylines. We then pull a trick and define +# polygons using the closed line segements that the stripper created. +# +vtkCutter cutEdges; #Generate cut lines + cutEdges SetInputConnection [cowNormals GetOutputPort] + cutEdges SetCutFunction plane + cutEdges GenerateCutScalarsOn + cutEdges SetValue 0 0.5 +vtkStripper cutStrips; #Forms loops (closed polylines) from cutter + cutStrips SetInputConnection [cutEdges GetOutputPort] + cutStrips Update +vtkPolyData cutPoly; #This trick defines polygons as polyline loop + cutPoly SetPoints [[cutStrips GetOutput] GetPoints] + cutPoly SetPolys [[cutStrips GetOutput] GetLines] + +# Triangle filter is robust enough to ignore the duplicate point at the +# beginning and end of the polygons and triangulate them. +vtkTriangleFilter cutTriangles + cutTriangles SetInput cutPoly +vtkPolyDataMapper cutMapper + cutMapper SetInput cutPoly + cutMapper SetInputConnection [cutTriangles GetOutputPort] +vtkActor cutActor + cutActor SetMapper cutMapper + eval [cutActor GetProperty] SetColor $peacock + +# The clipped part of the cow is rendered wireframe. +vtkPolyDataMapper restMapper + restMapper SetInputConnection [clipper GetClippedOutputPort] + restMapper ScalarVisibilityOff +vtkActor restActor + restActor SetMapper restMapper + [restActor GetProperty] SetRepresentationToWireframe + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor clipActor +ren1 AddActor cutActor +ren1 AddActor restActor +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCameraClippingRange + +renWin SetSize 300 300 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# Lets you move the cut plane back and forth by invoking the proc Cut with +# the appropriate plane value (essentially a distance from the original +# plane. +# +proc Cut {v} { + clipper SetValue $v + cutEdges SetValue 0 $v + cutStrips Update + cutPoly SetPoints [[cutStrips GetOutput] GetPoints] + cutPoly SetPolys [[cutStrips GetOutput] GetLines] + cutMapper Update + renWin Render +} diff --git a/Examples/VisualizationAlgorithms/Tcl/ColorIsosurface.tcl b/Examples/VisualizationAlgorithms/Tcl/ColorIsosurface.tcl new file mode 100644 index 0000000..bc22a5e --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/ColorIsosurface.tcl @@ -0,0 +1,85 @@ +# This example shows how to color an isosurface with other data. Basically +# an isosurface is generated, and a data array is selected and used by the +# mapper to color the surface. + +package require vtk +package require vtkinteraction + +# Read some data. The important thing here is to read a function as a data +# array as well as the scalar and vector. (here function 153 is named +# "Velocity Magnitude").Later this data array will be used to color the +# isosurface. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d AddFunction 153 + pl3d Update + pl3d DebugOn + +# The contoru filter uses the labeled scalar (function number 100 +# above to generate the contour surface; all other data is interpolated +# during the contouring process. +# +vtkContourFilter iso + iso SetInputConnection [pl3d GetOutputPort] + iso SetValue 0 .24 + +vtkPolyDataNormals normals + normals SetInputConnection [iso GetOutputPort] + normals SetFeatureAngle 45 + +# We indicate to the mapper to use the velcoity magnitude, which is a +# vtkDataArray that makes up part of the point attribute data. +# +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOn + isoMapper SetScalarRange 0 1500 + isoMapper SetScalarModeToUsePointFieldData + isoMapper ColorByArrayComponent "VelocityMagnitude" 0 + +vtkLODActor isoActor + isoActor SetMapper isoMapper + isoActor SetNumberOfCloudPoints 1000 + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the usual rendering stuff. +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Examples/VisualizationAlgorithms/Tcl/CutCombustor.tcl b/Examples/VisualizationAlgorithms/Tcl/CutCombustor.tcl new file mode 100644 index 0000000..a4a2e7d --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/CutCombustor.tcl @@ -0,0 +1,87 @@ +# This example shows how to use cutting (vtkCutter) and how it compares +# with extracting a plane from a computational grid. +# + +package require vtk +package require vtkinteraction + +# Read some data. +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# The cutter uses an implicit function to perform the cutting. +# Here we define a plane, specifying its center and normal. +# Then we assign the plane to the cutter. +vtkPlane plane + eval plane SetOrigin [[pl3d GetOutput] GetCenter] + plane SetNormal -0.287 0 0.9579 +vtkCutter planeCut + planeCut SetInputConnection [pl3d GetOutputPort] + planeCut SetCutFunction plane +vtkPolyDataMapper cutMapper + cutMapper SetInputConnection [planeCut GetOutputPort] + eval cutMapper SetScalarRange \ + [[[[pl3d GetOutput] GetPointData] GetScalars] GetRange] +vtkActor cutActor + cutActor SetMapper cutMapper + +# Here we extract a computational plane from the structured grid. +# We render it as wireframe. +vtkStructuredGridGeometryFilter compPlane + compPlane SetInputConnection [pl3d GetOutputPort] + compPlane SetExtent 0 100 0 100 9 9 +vtkPolyDataMapper planeMapper + planeMapper SetInputConnection [compPlane GetOutputPort] + planeMapper ScalarVisibilityOff +vtkActor planeActor + planeActor SetMapper planeMapper + [planeActor GetProperty] SetRepresentationToWireframe + [planeActor GetProperty] SetColor 0 0 0 + +# The outline of the data puts the data in context. +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper +set outlineProp [outlineActor GetProperty] +eval $outlineProp SetColor 0 0 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor cutActor + +ren1 SetBackground 1 1 1 +renWin SetSize 400 300 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 11.1034 59.5328 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition -2.95748 -26.7271 44.5309 +$cam1 SetViewUp 0.0184785 0.479657 0.877262 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/VisualizationAlgorithms/Tcl/DepthSort.tcl b/Examples/VisualizationAlgorithms/Tcl/DepthSort.tcl new file mode 100644 index 0000000..6920e67 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/DepthSort.tcl @@ -0,0 +1,95 @@ +# This example demonstrates the use of vtkDepthSortPolyData. This is a +# poor man's algorithm to sort polygons for proper transparent blending. +# It sorts polygons based on a single point (i.e., centroid) so the sorting +# may not work for overlapping or intersection polygons. +# +package require vtk +package require vtkinteraction + +# Create a bunch of spheres that overlap and cannot be easily arranged +# so that the blending works without sorting. They are appended into a +# single vtkPolyData because the filter only sorts within a single +# vtkPolyData input. +# +vtkSphereSource sphere + sphere SetThetaResolution 80 + sphere SetPhiResolution 40 + sphere SetRadius 1 + sphere SetCenter 0 0 0 +vtkSphereSource sphere2 + sphere2 SetThetaResolution 80 + sphere2 SetPhiResolution 40 + sphere2 SetRadius 0.5 + sphere2 SetCenter 1 0 0 +vtkSphereSource sphere3 + sphere3 SetThetaResolution 80 + sphere3 SetPhiResolution 40 + sphere3 SetRadius 0.5 + sphere3 SetCenter -1 0 0 +vtkSphereSource sphere4 + sphere4 SetThetaResolution 80 + sphere4 SetPhiResolution 40 + sphere4 SetRadius 0.5 + sphere4 SetCenter 0 1 0 +vtkSphereSource sphere5 + sphere5 SetThetaResolution 80 + sphere5 SetPhiResolution 40 + sphere5 SetRadius 0.5 + sphere5 SetCenter 0 -1 0 +vtkAppendPolyData appendData + appendData AddInput [sphere GetOutput] + appendData AddInput [sphere2 GetOutput] + appendData AddInput [sphere3 GetOutput] + appendData AddInput [sphere4 GetOutput] + appendData AddInput [sphere5 GetOutput] + +# The dephSort object is set up to generate scalars representing +# the sort depth. A camera is assigned for the sorting. The camera +# define the sort vector (position and focal point). +vtkCamera camera +vtkDepthSortPolyData depthSort + depthSort SetInputConnection [appendData GetOutputPort] + depthSort SetDirectionToBackToFront + depthSort SetVector 1 1 1 + depthSort SetCamera camera + depthSort SortScalarsOn + depthSort Update + +vtkPolyDataMapper mapper + mapper SetInputConnection [depthSort GetOutputPort] + mapper SetScalarRange 0 [[depthSort GetOutput] GetNumberOfCells] +vtkActor actor + actor SetMapper mapper + [actor GetProperty] SetOpacity 0.5 + [actor GetProperty] SetColor 1 0 0 + actor RotateX -72 + +# If an Prop3D is supplied, then its transformation matrix is taken +# into account during sorting. +depthSort SetProp3D actor + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 + ren1 SetActiveCamera camera +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 300 200 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 2.2 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Examples/VisualizationAlgorithms/Tcl/ExtractGeometry.tcl b/Examples/VisualizationAlgorithms/Tcl/ExtractGeometry.tcl new file mode 100644 index 0000000..38efe4b --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/ExtractGeometry.tcl @@ -0,0 +1,79 @@ +# This example shows how to extract a piece of a dataset using an implicit +# function. In this case the implicit function is formed by the boolean +# combination of two ellipsoids. +# + +package require vtk +package require vtkinteraction + +# Here we create two ellipsoidal implicit functions and boolean them +# together tto form a "cross" shaped implicit function. +vtkQuadric quadric + quadric SetCoefficients .5 1 .2 0 .1 0 0 .2 0 0 +vtkSampleFunction sample + sample SetSampleDimensions 50 50 50 + sample SetImplicitFunction quadric + sample ComputeNormalsOff +vtkTransform trans + trans Scale 1 .5 .333 +vtkSphere sphere + sphere SetRadius 0.25 + sphere SetTransform trans +vtkTransform trans2 + trans2 Scale .25 .5 1.0 +vtkSphere sphere2 + sphere2 SetRadius 0.25 + sphere2 SetTransform trans2 +vtkImplicitBoolean union + union AddFunction sphere + union AddFunction sphere2 + union SetOperationType 0;#union + + +# Here is where it gets interesting. The implicit function is used to +# extract those cells completely inside the function. They are then +# shrunk to help show what was extracted. +vtkExtractGeometry extract + extract SetInputConnection [sample GetOutputPort] + extract SetImplicitFunction union +vtkShrinkFilter shrink + shrink SetInputConnection [extract GetOutputPort] + shrink SetShrinkFactor 0.5 +vtkDataSetMapper dataMapper + dataMapper SetInputConnection [shrink GetOutputPort] +vtkActor dataActor + dataActor SetMapper dataMapper + +# The outline gives context to the original data. +vtkOutlineFilter outline + outline SetInputConnection [sample GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper +set outlineProp [outlineActor GetProperty] +eval $outlineProp SetColor 0 0 0 + +# The usual rendering stuff is created. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor dataActor +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Examples/VisualizationAlgorithms/Tcl/ExtractUGrid.tcl b/Examples/VisualizationAlgorithms/Tcl/ExtractUGrid.tcl new file mode 100644 index 0000000..6be08d7 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/ExtractUGrid.tcl @@ -0,0 +1,89 @@ +# This example shows how to extract portions of an unstructured grid +# using vtkExtractUnstructuredGrid. vtkConnectivityFilter is also used +# to extract connected components. +# +# The data found here represents a blow molding process. Blow molding +# requires a mold and parison (hot, viscous plastic) which is shaped +# by the mold into the final form. The data file contains several steps +# in time for the analysis. +# + +package require vtk + +# Create a reader to read the unstructured grid data. We use a +# vtkDataSetReader which means the type of the output is unknown until +# the data file is read. SO we follow the reader with a vtkCastToConcrete +# and cast the output to vtkUnstructuredGrid. +vtkDataSetReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/blow.vtk" + reader SetScalarsName "thickness9" + reader SetVectorsName "displacement9" +vtkCastToConcrete castToUnstructuredGrid + castToUnstructuredGrid SetInputConnection [reader GetOutputPort] +vtkWarpVector warp + warp SetInput [castToUnstructuredGrid GetUnstructuredGridOutput] + +# The connectivity filter extracts the first two regions. These are +# know to represent the mold. +vtkConnectivityFilter connect + connect SetInputConnection [warp GetOutputPort] + connect SetExtractionModeToSpecifiedRegions + connect AddSpecifiedRegion 0 + connect AddSpecifiedRegion 1 +vtkDataSetMapper moldMapper + moldMapper SetInputConnection [reader GetOutputPort] + moldMapper ScalarVisibilityOff +vtkActor moldActor + moldActor SetMapper moldMapper + [moldActor GetProperty] SetColor .2 .2 .2 + [moldActor GetProperty] SetRepresentationToWireframe + +# Another connectivity filter is used to extract the parison. +vtkConnectivityFilter connect2 + connect2 SetInputConnection [warp GetOutputPort] + connect2 SetExtractionModeToSpecifiedRegions + connect2 AddSpecifiedRegion 2 +# We use vtkExtractUnstructuredGrid because we are interested in +# looking at just a few cells. We use cell clipping via cell id to +# extract the portion of the grid we are interested in. +vtkExtractUnstructuredGrid extractGrid + extractGrid SetInputConnection [connect2 GetOutputPort] + extractGrid CellClippingOn + extractGrid SetCellMinimum 0 + extractGrid SetCellMaximum 23 +vtkGeometryFilter parison + parison SetInputConnection [extractGrid GetOutputPort] +vtkPolyDataNormals normals2 + normals2 SetInputConnection [parison GetOutputPort] + normals2 SetFeatureAngle 60 +vtkLookupTable lut + lut SetHueRange 0.0 0.66667 +vtkPolyDataMapper parisonMapper + parisonMapper SetInputConnection [normals2 GetOutputPort] + parisonMapper SetLookupTable lut + parisonMapper SetScalarRange 0.12 1.0 +vtkActor parisonActor + parisonActor SetMapper parisonMapper + +# graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor parisonActor +ren1 AddActor moldActor +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 60 +[ren1 GetActiveCamera] Roll -90 +[ren1 GetActiveCamera] Dolly 2 +ren1 ResetCameraClippingRange +renWin SetSize 500 375 +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Examples/VisualizationAlgorithms/Tcl/GenerateTextureCoords.tcl b/Examples/VisualizationAlgorithms/Tcl/GenerateTextureCoords.tcl new file mode 100644 index 0000000..9020906 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/GenerateTextureCoords.tcl @@ -0,0 +1,73 @@ +# This example shows how to generate and manipulate texture coordinates. +# A random cloud of points is generated and then triangulated with +# vtkDelaunay3D. Since these points do not have texture coordinates, +# we generate them with vtkTextureMapToCylinder. + +package require vtk + +# Begin by generating 25 random points in the unit sphere. +# +vtkPointSource sphere + sphere SetNumberOfPoints 25 + +# Triangulate the points with vtkDelaunay3D. This generates a convex hull +# of tetrahedron. +# +vtkDelaunay3D del + del SetInputConnection [sphere GetOutputPort] + del SetTolerance 0.01 + +# The triangulation has texture coordinates generated so we can map +# a texture onto it. +# +vtkTextureMapToCylinder tmapper + tmapper SetInputConnection [del GetOutputPort] + tmapper PreventSeamOn + +# We scale the texture coordinate to get some repeat patterns. +vtkTransformTextureCoords xform + xform SetInputConnection [tmapper GetOutputPort] + xform SetScale 4 4 1 + +# vtkDataSetMapper internally uses a vtkGeometryFilter to extract the +# surface from the triangulation. The output (which is vtkPolyData) is +# then passed to an internal vtkPolyDataMapper which does the +# rendering. +vtkDataSetMapper mapper + mapper SetInputConnection [xform GetOutputPort] + +# A texture is loaded using an image reader. Textures are simply images. +# The texture is eventually associated with an actor. +# +vtkBMPReader bmpReader + bmpReader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" +vtkTexture atext + atext SetInputConnection [bmpReader GetOutputPort] + atext InterpolateOn +vtkActor triangulation + triangulation SetMapper mapper + triangulation SetTexture atext + +# Create the standard rendering stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor triangulation +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +renWin Render + +# render the image +# +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/VisualizationAlgorithms/Tcl/SubsampleGrid.tcl b/Examples/VisualizationAlgorithms/Tcl/SubsampleGrid.tcl new file mode 100644 index 0000000..b016771 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/SubsampleGrid.tcl @@ -0,0 +1,77 @@ +# This example demonstrates the subsampling of a structured grid. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. +# +package require vtk +package require vtkinteraction + +# Read some structured data. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# Here we subsample the grid. The SetVOI method requires six values +# specifying (imin,imax, jmin,jmax, kmin,kmax) extents. In this example +# we extracting a plane. Note that the VOI is clamped to zero (min) and +# the maximum i-j-k value; that way we can use the -1000,1000 specification +# and be sure the values are clamped. The SampleRate specifies that we take +# every point in the i-direction; every other point in the j-direction; and +# every third point in the k-direction. IncludeBoundaryOn makes sure that we +# get the boundary points even if the SampleRate does not coincident with +# the boundary. +# +vtkExtractGrid extract + extract SetInputConnection [pl3d GetOutputPort] + extract SetVOI 30 30 -1000 1000 -1000 1000 + extract SetSampleRate 1 2 3 + extract IncludeBoundaryOn +vtkDataSetMapper mapper + mapper SetInputConnection [extract GetOutputPort] + mapper SetScalarRange .18 .7 +vtkActor actor + actor SetMapper mapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Add the usual rendering stuff. +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor actor + +ren1 SetBackground 1 1 1 +renWin SetSize 300 180 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 2.64586 47.905 +$cam1 SetFocalPoint 8.931 0.358127 31.3526 +$cam1 SetPosition 29.7111 -0.688615 37.1495 +$cam1 SetViewUp -0.268328 0.00801595 0.963294 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Examples/VisualizationAlgorithms/Tcl/TextureThreshold.tcl b/Examples/VisualizationAlgorithms/Tcl/TextureThreshold.tcl new file mode 100644 index 0000000..a40f351 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/TextureThreshold.tcl @@ -0,0 +1,153 @@ +# Load libraries for VTK +package require vtk +package require vtkinteraction +package require vtktesting + +# This example shows how to use a transparent texture map to perform +# thresholding. The key is the vtkThresholdTextureCoords filter which +# creates texture coordinates based on a threshold value. These texture +# coordinates are used in conjuntion with a texture map with varying +# opacity and intensity to create an inside, transition, and outside +# region. +# + +# Begin by reading some structure grid data. +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/bluntfinxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/bluntfinq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# Now extract surfaces from the grid corresponding to boundary geometry. +# First the wall. +vtkStructuredGridGeometryFilter wall + wall SetInputConnection [pl3d GetOutputPort] + wall SetExtent 0 100 0 0 0 100 +vtkPolyDataMapper wallMap + wallMap SetInputConnection [wall GetOutputPort] + wallMap ScalarVisibilityOff +vtkActor wallActor + wallActor SetMapper wallMap + eval [wallActor GetProperty] SetColor 0.8 0.8 0.8 + +# Now the fin. +# +vtkStructuredGridGeometryFilter fin + fin SetInputConnection [pl3d GetOutputPort] + fin SetExtent 0 100 0 100 0 0 +vtkPolyDataMapper finMap + finMap SetInputConnection [fin GetOutputPort] + finMap ScalarVisibilityOff +vtkActor finActor + finActor SetMapper finMap + eval [finActor GetProperty] SetColor 0.8 0.8 0.8 + +# Extract planes to threshold. Start by reading the specially +# designed texture map that has three regions: an inside, boundary, +# and outside region. The opacity and intensity of this texture map +# are varied. +vtkStructuredPointsReader tmap + tmap SetFileName "$VTK_DATA_ROOT/Data/texThres2.vtk" +vtkTexture texture + texture SetInputConnection [tmap GetOutputPort] + texture InterpolateOff + texture RepeatOff + +# Here are the three planes which will be texture thresholded. +# +vtkStructuredGridGeometryFilter plane1 + plane1 SetInputConnection [pl3d GetOutputPort] + plane1 SetExtent 10 10 0 100 0 100 +vtkThresholdTextureCoords thresh1 + thresh1 SetInputConnection [plane1 GetOutputPort] + thresh1 ThresholdByUpper 1.5 +vtkDataSetMapper plane1Map + plane1Map SetInputConnection [thresh1 GetOutputPort] + eval plane1Map SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor plane1Actor + plane1Actor SetMapper plane1Map + plane1Actor SetTexture texture +[plane1Actor GetProperty] SetOpacity 0.999 + +vtkStructuredGridGeometryFilter plane2 + plane2 SetInputConnection [pl3d GetOutputPort] + plane2 SetExtent 30 30 0 100 0 100 +vtkThresholdTextureCoords thresh2 + thresh2 SetInputConnection [plane2 GetOutputPort] + thresh2 ThresholdByUpper 1.5 +vtkDataSetMapper plane2Map + plane2Map SetInputConnection [thresh2 GetOutputPort] + eval plane2Map SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor plane2Actor + plane2Actor SetMapper plane2Map + plane2Actor SetTexture texture + [plane2Actor GetProperty] SetOpacity 0.999 + +vtkStructuredGridGeometryFilter plane3 + plane3 SetInputConnection [pl3d GetOutputPort] + plane3 SetExtent 35 35 0 100 0 100 +vtkThresholdTextureCoords thresh3 + thresh3 SetInputConnection [plane3 GetOutputPort] + thresh3 ThresholdByUpper 1.5 +vtkDataSetMapper plane3Map + plane3Map SetInputConnection [thresh3 GetOutputPort] + eval plane3Map SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor plane3Actor + plane3Actor SetMapper plane3Map + plane3Actor SetTexture texture + [plane3Actor GetProperty] SetOpacity 0.999 + +# For context create an outline around the data. +# +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + set outlineProp [outlineActor GetProperty] + eval $outlineProp SetColor 0 0 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor wallActor +ren1 AddActor finActor +ren1 AddActor plane1Actor +ren1 AddActor plane2Actor +ren1 AddActor plane3Actor +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 + +# Set up a nice view. +# +vtkCamera cam1 + cam1 SetClippingRange 1.51176 75.5879 + cam1 SetFocalPoint 2.33749 2.96739 3.61023 + cam1 SetPosition 10.8787 5.27346 15.8687 + cam1 SetViewAngle 30 + cam1 SetViewPlaneNormal 0.564986 0.152542 0.810877 + cam1 SetViewUp -0.0610856 0.987798 -0.143262 +ren1 SetActiveCamera cam1 + +iren Initialize + +# Set up an observer to invoke a proc when the UserEvent (keypress-u) +# is invoked. +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/VisualizationAlgorithms/Tcl/TransformTextureCoords.tcl b/Examples/VisualizationAlgorithms/Tcl/TransformTextureCoords.tcl new file mode 100644 index 0000000..97b536a --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/TransformTextureCoords.tcl @@ -0,0 +1,452 @@ +# +# This example shows how to generate and manipulate texture coordinates. +# The user can interact with the vtkTransformTextureCoords object to +# modify the texture coordinates interactively. Different objects, textures +# and texture mappers can be selected. +# + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl. +# +package require vtk +package require vtkinteraction + +# +# These are the different choices made available to the user. +# They include: models, textures (relative to VTK_DATA_ROOT) +# and mapper types. +# +set models { \ + "teapot.g" \ + "Viewpoint/cow.g" \ + "motor.g" \ + } + +set textures { \ + "vtk.png" \ + "masonry.bmp" \ + "earth.ppm" \ + "B.pgm" \ + "beach.jpg" \ + "fran_cut.png" \ + } + +set texture_mapper_types { \ + vtkTextureMapToPlane \ + vtkTextureMapToSphere \ + vtkTextureMapToCylinder \ + } + +# +# A 3D model is loaded using an BYU reader. +# Compute normals, in case they are not provided with the model. +# +vtkBYUReader model_reader + model_reader SetGeometryFileName "$VTK_DATA_ROOT/Data/[lindex $models 0]" + +vtkPolyDataNormals model_normals + model_normals SetInputConnection [model_reader GetOutputPort] + +# +# Create all texture coordinates generators/mappers and use the first one +# for the current pipeline. +# +foreach texture_mapper_type $texture_mapper_types { + set texture_mapper \ + [$texture_mapper_type [string tolower $texture_mapper_type]] + $texture_mapper SetInputConnection [model_normals GetOutputPort] +} + +# +# Create a texture coordinate transformer, which can be used to +# translate, scale or flip the texture. +# +set texture_mapper_type [lindex $texture_mapper_types 0] +vtkTransformTextureCoords transform_texture + transform_texture SetInput [[string tolower $texture_mapper_type] GetOutput] + +# +# Create polydata mapper. +# +vtkPolyDataMapper mapper + mapper SetInputConnection [transform_texture GetOutputPort] + +# +# A texture is loaded using an image reader. +# Textures are simply images. +# The texture is eventually associated with an actor. +# +set filename "$VTK_DATA_ROOT/Data/[lindex $textures 0]" +vtkImageReader2Factory create_reader + set texture_reader [create_reader CreateImageReader2 $filename] + $texture_reader SetFileName $filename + +vtkTexture texture + texture SetInputConnection [$texture_reader GetOutputPort] + texture InterpolateOn + +vtkActor actor + actor SetMapper mapper + actor SetTexture texture + +# +# Create a triangle filter that will feed the model geometry to +# the feature edge extractor. Create the corresponding mapper +# and actor. +# +vtkTriangleFilter triangle_filter + triangle_filter SetInputConnection [model_normals GetOutputPort] + +vtkFeatureEdges edges_extractor + edges_extractor SetInputConnection [triangle_filter GetOutputPort] + edges_extractor ColoringOff + edges_extractor BoundaryEdgesOn + edges_extractor ManifoldEdgesOn + edges_extractor NonManifoldEdgesOn + +vtkPolyDataMapper edges_mapper + edges_mapper SetInputConnection [edges_extractor GetOutputPort] + edges_mapper SetResolveCoincidentTopologyToPolygonOffset + +vtkActor edges_actor + edges_actor SetMapper edges_mapper + eval [edges_actor GetProperty] SetColor 0 0 0 + eval [edges_actor GetProperty] SetLineStipplePattern 4369 + edges_actor VisibilityOff + +# +# Create the standard rendering stuff. +# +vtkRenderer ren1 + +vtkRenderWindow renWin + renWin AddRenderer ren1 + +# +# Add the actors to the renderer, set the background +# +ren1 AddActor actor +ren1 AddActor edges_actor +ren1 SetBackground 1 1 1 + +# +# Create the Tk widget, associate it with the renderwindow. +# +set vtkw [vtkTkRenderWidget .ren \ + -width 500 \ + -height 400 \ + -rw renWin] + +# +# Pack the Tk widget. +# +pack $vtkw -side top -fill both -expand yes + +# +# Sets event handlers +# +::vtk::bind_tk_render_widget $vtkw + +# +# Create a menubar. +# +set menubar [menu .menubar] +. config -menu $menubar + +# +# Create a "File" menu. +# +set file_menu [menu $menubar.file] + +$file_menu add command \ + -label "Quit" \ + -command ::vtk::cb_exit + +$menubar add cascade -label "File" -menu $file_menu + +# +# Create a "Model" menu. +# Each model is a radio menu entry, associated to +# the load_model callback. +# +set model_menu [menu $menubar.model] + +set gui_vars(model_reader,filename) \ + [model_reader GetGeometryFileName] + +foreach model $models { + set filename "$VTK_DATA_ROOT/Data/$model" + $model_menu add radio \ + -label $model \ + -command [list load_model $filename] \ + -value $filename \ + -variable gui_vars(model_reader,filename) +} + +proc load_model {filename} { + model_reader SetGeometryFileName $filename + ren1 ResetCamera + renWin Render +} + +$menubar add cascade -label "Model" -menu $model_menu + +# +# Create a "Texture" menu. +# Each texture is a radio menu entry, associated to +# the load_texture callback. +# +set texture_menu [menu $menubar.texture] + +set gui_vars(texture_reader,filename) \ + [[[texture GetInputConnection 0 0] GetProducer] GetFileName] + +foreach texture $textures { + set filename "$VTK_DATA_ROOT/Data/$texture" + $texture_menu add radio \ + -label $texture \ + -command [list load_texture $filename] \ + -value $filename \ + -variable gui_vars(texture_reader,filename) +} + +proc load_texture {filename} { + set texture_reader [create_reader CreateImageReader2 $filename] + $texture_reader SetFileName $filename + texture SetInputConnection [$texture_reader GetOutputPort] + renWin Render +} + +$menubar add cascade -label "Texture" -menu $texture_menu + +# +# Create a "Mapper" menu. +# Each mapper type is a radio menu entry, associated to +# the use_texture_mapper_type callback. +# +set texture_mapper_type_menu [menu $menubar.texture_mapper_type] + +set gui_vars(texture_mapper_type) \ + [[[transform_texture GetInputConnection 0 0] GetProducer] GetClassName] + +foreach texture_mapper_type $texture_mapper_types { + $texture_mapper_type_menu add radio \ + -label $texture_mapper_type \ + -command [list use_texture_mapper_type $texture_mapper_type] \ + -value $texture_mapper_type \ + -variable gui_vars(texture_mapper_type) +} + +proc use_texture_mapper_type {texture_mapper_type} { + transform_texture SetInputConnection \ + [[string tolower $texture_mapper_type] GetOutputPort] + renWin Render +} + +$menubar add cascade -label "Mapper" -menu $texture_mapper_type_menu + +# +# Create a "View" menu. +# It stores various properties. +# +set view_menu [menu $menubar.view] + +set gui_vars(view,edges) [edges_actor GetVisibility] + +$view_menu add radio \ + -label "Edges" \ + -command toggle_edges_visibility \ + -value 1 \ + -variable gui_vars(view,edges) + +proc toggle_edges_visibility {} { + if {[edges_actor GetVisibility]} { + edges_actor VisibilityOff + } else { + edges_actor VisibilityOn + } + set gui_vars(view,edges) [edges_actor GetVisibility] + renWin Render +} + +$menubar add cascade -label "View" -menu $view_menu + +# +# Create the vtkTransformTextureCoords gui. +# +# Each entry in the following array describe a "control" in the GUI: +# - unique name of the control, +# - title for the control, +# - texture coordinates parametrized by that control, +# - name of the corresponding vtkTransformTextureCoords attribute, +# - start, end, increment value of each Tk scale widget in the control. +# +set transform_texture_coords_gui_controls \ + { \ + position "Texture position" {r s} Position 0.0 2.0 0.01 \ + scale "Texture scale" {r s} Scale 0.0 5.0 0.05 \ + origin "Texture origin" {r s} Origin 0.0 1.0 0.01 \ + } + +proc create_transform_texture_coords_gui {parent obj} { + + global gui_vars transform_texture_coords_gui_controls + + # + # Create a main frame + # + if {$parent == "."} { + set main_frame [frame .main] + } else { + set main_frame [frame $parent.main] + } + + set scale_width 9 + set command [list update_transform_texture_from_gui_vars $obj] + + # + # Loop over each "control" description + # + foreach {control label coords obj_method scale_from scale_to scale_res} \ + $transform_texture_coords_gui_controls { + + # + # Create a frame for the control, a label for its title, and a + # sub-frame that will hold all Tk scale widgets. + # + upvar ${control}_frame control_frame + set control_frame [frame $main_frame.$control -relief groove -border 2] + + upvar ${control}_label control_label + set control_label [label $control_frame.label \ + -text "$label:" -anchor w] + + upvar ${control}_rst control_rst + set control_rst [frame $control_frame.rst] + + # + # Add (r,s,t) texture coordinate widgets to the control. + # Each one is made of a label for the coordinate's name, a label + # for the coordinate's value and a Tk scale widget to control + # that value. + # All scale widgets are associated to the same callback: + # update_transform_texture_from_gui_vars + # + for {set i 0} {$i < [llength $coords]} {incr i} { + + set coord [lindex $coords $i] + + label $control_rst.${coord}_label \ + -text "$coord:" -anchor w + + set gui_vars($obj,$control,$coord) \ + [lindex [$obj Get$obj_method] $i] + + scale $control_rst.${coord}_scale \ + -from $scale_from -to $scale_to -resolution $scale_res \ + -orient horizontal \ + -width $scale_width \ + -showvalue false \ + -var gui_vars($obj,$control,$coord) \ + -command $command + + label $control_rst.${coord}_value \ + -textvariable gui_vars($obj,$control,$coord) + + # + # For "origin", add flip checkbuttons. + # Pack the 3 (or 5) elements into a single row. + # + if {$control == "origin"} { + + label $control_rst.${coord}_flip_label \ + -text "Flip:" -anchor w + + set get_flip "GetFlip[string toupper $coord]" + set gui_vars($obj,$control,${coord}_flip) [$obj $get_flip] + + checkbutton $control_rst.${coord}_flip \ + -variable gui_vars($obj,$control,${coord}_flip) \ + -borderwidth 0 -padx 0 -pady 0 \ + -command $command + + grid $control_rst.${coord}_label \ + $control_rst.${coord}_value \ + $control_rst.${coord}_scale \ + $control_rst.${coord}_flip_label \ + $control_rst.${coord}_flip \ + -sticky news + } else { + grid $control_rst.${coord}_label \ + $control_rst.${coord}_value \ + $control_rst.${coord}_scale \ + -sticky news + } + + # + # Allow the scale widgets to grow when the GUI is expanded. + # + grid columnconfigure $control_rst 2 -weight 1 + } + + # + # Pack everything + # + pack $control_frame \ + -side top -fill x -expand true -padx 1 -pady 2 + + pack $control_label \ + $control_rst \ + -side top -fill x -expand true + } + + return $main_frame +} + +# +# This callback is used whenever the value of a Tk scale is changed. +# It recovers the gui values from the gui_vars global array, and +# change the corresponding vtkTransformTextureCoords attribute. +# The render window is re-rendered. +# +proc update_transform_texture_from_gui_vars {obj args} { + + global gui_vars transform_texture_coords_gui_controls + + foreach {control label coords obj_method scale_from scale_to scale_res} \ + $transform_texture_coords_gui_controls { + set values [$obj Get$obj_method] + for {set i 0} {$i < [llength $coords]} {incr i} { + set coord [lindex $coords $i] + set values [lreplace $values $i $i $gui_vars($obj,$control,$coord)] + + if {$control == "origin"} { + set flip_method "Flip[string toupper $coord]" + $obj Set$flip_method $gui_vars($obj,$control,${coord}_flip) + } + } + eval $obj Set$obj_method $values + } + renWin Render +} + +# +# Create the gui and pack it. +# +set gui [create_transform_texture_coords_gui . transform_texture] + +pack $gui -side top -anchor s -fill x -expand yes + +# +# We set the window manager (wm command) so that it registers a +# command to handle the WM_DELETE_WINDOW protocal request.. +# +wm title . "Texture mapper/transform demo" +wm protocol . WM_DELETE_WINDOW ::vtk::cb_exit + +# +# You only need this line if you run this script from a Tcl shell +# (tclsh) instead of a Tk shell (wish) +# +tkwait window . diff --git a/Examples/VisualizationAlgorithms/Tcl/VisQuad.tcl b/Examples/VisualizationAlgorithms/Tcl/VisQuad.tcl new file mode 100644 index 0000000..b2135ac --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/VisQuad.tcl @@ -0,0 +1,64 @@ +# This example demonstrates the use of the contour filter, and the use of +# the vtkSampleFunction to generate a volume of data samples from an +# implicit function. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. +# +package require vtk +package require vtkinteraction + +# VTK supports implicit functions of the form f(x,y,z)=constant. These +# functions can represent things spheres, cones, etc. Here we use a +# general form for a quadric to create an elliptical data field. +vtkQuadric quadric + quadric SetCoefficients .5 1 .2 0 .1 0 0 .2 0 0 + +# vtkSampleFunction samples an implicit function over the x-y-z range +# specified (here it defaults to -1,1 in the x,y,z directions). +vtkSampleFunction sample + sample SetSampleDimensions 30 30 30 + sample SetImplicitFunction quadric + +# Create five surfaces F(x,y,z) = constant between range specified. The +# GenerateValues() method creates n isocontour values between the range +# specified. +vtkContourFilter contours + contours SetInputConnection [sample GetOutputPort] + contours GenerateValues 5 0.0 1.2 + +vtkPolyDataMapper contMapper + contMapper SetInputConnection [contours GetOutputPort] + contMapper SetScalarRange 0.0 1.2 + +vtkActor contActor + contActor SetMapper contMapper + +# We'll put a simple outline around the data. +vtkOutlineFilter outline + outline SetInputConnection [sample GetOutputPort] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# The usual rendering stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 1 1 1 +ren1 AddActor contActor +ren1 AddActor outlineActor + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . diff --git a/Examples/VisualizationAlgorithms/Tcl/deciFran.tcl b/Examples/VisualizationAlgorithms/Tcl/deciFran.tcl new file mode 100644 index 0000000..bc7bbb0 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/deciFran.tcl @@ -0,0 +1,61 @@ +# This example shows how to use decimation to reduce a polygonal mesh. We also +# use mesh smoothing and generate surface normals to give a pleasing result. +# + +package require vtk +package require vtkinteraction + +# We start by reading some data that was originally captured from +# a Cyberware laser digitizing system. +# +vtkPolyDataReader fran + fran SetFileName "$VTK_DATA_ROOT/Data/fran_cut.vtk" + +# We want to preserve topology (not let any cracks form). This may limit +# the total reduction possible, which we have specified at 90%. +# +vtkDecimatePro deci + deci SetInputConnection [fran GetOutputPort] + deci SetTargetReduction 0.9 + deci PreserveTopologyOn +vtkPolyDataNormals normals + normals SetInputConnection [fran GetOutputPort] + normals FlipNormalsOn +vtkPolyDataMapper franMapper + franMapper SetInputConnection [normals GetOutputPort] +vtkActor franActor + franActor SetMapper franMapper + eval [franActor GetProperty] SetColor 1.0 0.49 0.25 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor franActor +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +vtkCamera cam1 + cam1 SetClippingRange 0.0475572 2.37786 + cam1 SetFocalPoint 0.052665 -0.129454 -0.0573973 + cam1 SetPosition 0.327637 -0.116299 -0.256418 + cam1 SetViewUp -0.0225386 0.999137 0.034901 +ren1 SetActiveCamera cam1 + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/VisualizationAlgorithms/Tcl/imageWarp.tcl b/Examples/VisualizationAlgorithms/Tcl/imageWarp.tcl new file mode 100644 index 0000000..febadc7 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/imageWarp.tcl @@ -0,0 +1,63 @@ +# This example shows how to combine data from both the imaging +# and graphics pipelines. The vtkMergeData filter is used to +# merge the data from each together. + +package require vtk +package require vtkinteraction + +# Read in an image and compute a luminance value. The image is extracted +# as a set of polygons (vtkImageDataGeometryFilter). We then will +# warp the plane using the scalar (luminance) values. +# +vtkBMPReader reader + reader SetFileName $VTK_DATA_ROOT/Data/masonry.bmp +vtkImageLuminance luminance + luminance SetInputConnection [reader GetOutputPort] +vtkImageDataGeometryFilter geometry + geometry SetInputConnection [luminance GetOutputPort] +vtkWarpScalar warp + warp SetInputConnection [geometry GetOutputPort] + warp SetScaleFactor -0.1 + +# Use vtkMergeFilter to combine the original image with the warped geometry. +# +vtkMergeFilter merge + merge SetGeometryConnection [warp GetOutputPort] + merge SetScalarsConnection [reader GetOutputPort] +vtkDataSetMapper mapper + mapper SetInputConnection [merge GetOutputPort] + mapper SetScalarRange 0 255 + mapper ImmediateModeRenderingOff +vtkActor actor + actor SetMapper mapper + +# Create renderer stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 20 +[ren1 GetActiveCamera] Elevation 30 +ren1 SetBackground 0.1 0.2 0.4 +ren1 ResetCameraClippingRange + +renWin SetSize 250 250 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Examples/VisualizationAlgorithms/Tcl/officeTube.tcl b/Examples/VisualizationAlgorithms/Tcl/officeTube.tcl new file mode 100644 index 0000000..bb72930 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/officeTube.tcl @@ -0,0 +1,311 @@ +# This example demonstrates the use of a single streamline and the tube +# filter to create a streamtube. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# We read a data file the is a CFD analysis of airflow in an office (with +# ventilation and a burning cigarette). We force an update so that we +# can query the output for its length, i.e., the length of the diagonal +# of the bounding box. This is useful for normalizing the data. +# +vtkStructuredGridReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/office.binary.vtk" + reader Update;#force a read to occur + +set length [[reader GetOutput] GetLength] + +set maxVelocity \ + [[[[reader GetOutput] GetPointData] GetVectors] GetMaxNorm] +set maxTime [expr 35.0 * $length / $maxVelocity] + +# Now we will generate a single streamline in the data. We select the +# integration order to use (RungeKutta order 4) and associate it with +# the streamer. The start position is the position in world space where +# we want to begin streamline integration; and we integrate in both +# directions. The step length is the length of the line segments that +# make up the streamline (i.e., related to display). The +# IntegrationStepLength specifies the integration step length as a +# fraction of the cell size that the streamline is in. +vtkRungeKutta4 integ +vtkStreamTracer streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition 0.1 2.1 0.5 + streamer SetMaximumPropagation 500 + streamer SetMaximumPropagationUnitToTimeUnit + streamer SetInitialIntegrationStep 0.05 + streamer SetInitialIntegrationStepUnitToCellLengthUnit + streamer SetIntegrationDirectionToBoth + streamer SetIntegrator integ + +# The tube is wrapped around the generated streamline. By varying the radius +# by the inverse of vector magnitude, we are creating a tube whose radius is +# proportional to mass flux (in incompressible flow). +vtkTubeFilter streamTube + streamTube SetInputConnection [streamer GetOutputPort] + streamTube SetInputArrayToProcess 1 0 0 vtkDataObject::FIELD_ASSOCIATION_POINTS vectors + streamTube SetRadius 0.02 + streamTube SetNumberOfSides 12 + streamTube SetVaryRadiusToVaryRadiusByVector +vtkPolyDataMapper mapStreamTube + mapStreamTube SetInputConnection [streamTube GetOutputPort] + eval mapStreamTube SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor streamTubeActor + streamTubeActor SetMapper mapStreamTube + [streamTubeActor GetProperty] BackfaceCullingOn + +# From here on we generate a whole bunch of planes which correspond to +# the geometry in the analysis; tables, bookshelves and so on. +vtkStructuredGridGeometryFilter table1 + table1 SetInputConnection [reader GetOutputPort] + table1 SetExtent 11 15 7 9 8 8 +vtkPolyDataMapper mapTable1 + mapTable1 SetInputConnection [table1 GetOutputPort] + mapTable1 ScalarVisibilityOff +vtkActor table1Actor + table1Actor SetMapper mapTable1 + [table1Actor GetProperty] SetColor .59 .427 .392 + +vtkStructuredGridGeometryFilter table2 + table2 SetInputConnection [reader GetOutputPort] + table2 SetExtent 11 15 10 12 8 8 +vtkPolyDataMapper mapTable2 + mapTable2 SetInputConnection [table2 GetOutputPort] + mapTable2 ScalarVisibilityOff +vtkActor table2Actor + table2Actor SetMapper mapTable2 + [table2Actor GetProperty] SetColor .59 .427 .392 + +vtkStructuredGridGeometryFilter FilingCabinet1 + FilingCabinet1 SetInputConnection [reader GetOutputPort] + FilingCabinet1 SetExtent 15 15 7 9 0 8 +vtkPolyDataMapper mapFilingCabinet1 + mapFilingCabinet1 SetInputConnection [FilingCabinet1 GetOutputPort] + mapFilingCabinet1 ScalarVisibilityOff +vtkActor FilingCabinet1Actor + FilingCabinet1Actor SetMapper mapFilingCabinet1 + [FilingCabinet1Actor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter FilingCabinet2 + FilingCabinet2 SetInputConnection [reader GetOutputPort] + FilingCabinet2 SetExtent 15 15 10 12 0 8 +vtkPolyDataMapper mapFilingCabinet2 + mapFilingCabinet2 SetInputConnection [FilingCabinet2 GetOutputPort] + mapFilingCabinet2 ScalarVisibilityOff +vtkActor FilingCabinet2Actor + FilingCabinet2Actor SetMapper mapFilingCabinet2 + [FilingCabinet2Actor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Top + bookshelf1Top SetInputConnection [reader GetOutputPort] + bookshelf1Top SetExtent 13 13 0 4 0 11 +vtkPolyDataMapper mapBookshelf1Top + mapBookshelf1Top SetInputConnection [bookshelf1Top GetOutputPort] + mapBookshelf1Top ScalarVisibilityOff +vtkActor bookshelf1TopActor + bookshelf1TopActor SetMapper mapBookshelf1Top + [bookshelf1TopActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Bottom + bookshelf1Bottom SetInputConnection [reader GetOutputPort] + bookshelf1Bottom SetExtent 20 20 0 4 0 11 +vtkPolyDataMapper mapBookshelf1Bottom + mapBookshelf1Bottom SetInputConnection [bookshelf1Bottom GetOutputPort] + mapBookshelf1Bottom ScalarVisibilityOff +vtkActor bookshelf1BottomActor + bookshelf1BottomActor SetMapper mapBookshelf1Bottom + [bookshelf1BottomActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Front + bookshelf1Front SetInputConnection [reader GetOutputPort] + bookshelf1Front SetExtent 13 20 0 0 0 11 +vtkPolyDataMapper mapBookshelf1Front + mapBookshelf1Front SetInputConnection [bookshelf1Front GetOutputPort] + mapBookshelf1Front ScalarVisibilityOff +vtkActor bookshelf1FrontActor + bookshelf1FrontActor SetMapper mapBookshelf1Front + [bookshelf1FrontActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Back + bookshelf1Back SetInputConnection [reader GetOutputPort] + bookshelf1Back SetExtent 13 20 4 4 0 11 +vtkPolyDataMapper mapBookshelf1Back + mapBookshelf1Back SetInputConnection [bookshelf1Back GetOutputPort] + mapBookshelf1Back ScalarVisibilityOff +vtkActor bookshelf1BackActor + bookshelf1BackActor SetMapper mapBookshelf1Back + [bookshelf1BackActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1LHS + bookshelf1LHS SetInputConnection [reader GetOutputPort] + bookshelf1LHS SetExtent 13 20 0 4 0 0 +vtkPolyDataMapper mapBookshelf1LHS + mapBookshelf1LHS SetInputConnection [bookshelf1LHS GetOutputPort] + mapBookshelf1LHS ScalarVisibilityOff +vtkActor bookshelf1LHSActor + bookshelf1LHSActor SetMapper mapBookshelf1LHS + [bookshelf1LHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1RHS + bookshelf1RHS SetInputConnection [reader GetOutputPort] + bookshelf1RHS SetExtent 13 20 0 4 11 11 +vtkPolyDataMapper mapBookshelf1RHS + mapBookshelf1RHS SetInputConnection [bookshelf1RHS GetOutputPort] + mapBookshelf1RHS ScalarVisibilityOff +vtkActor bookshelf1RHSActor + bookshelf1RHSActor SetMapper mapBookshelf1RHS + [bookshelf1RHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Top + bookshelf2Top SetInputConnection [reader GetOutputPort] + bookshelf2Top SetExtent 13 13 15 19 0 11 +vtkPolyDataMapper mapBookshelf2Top + mapBookshelf2Top SetInputConnection [bookshelf2Top GetOutputPort] + mapBookshelf2Top ScalarVisibilityOff +vtkActor bookshelf2TopActor + bookshelf2TopActor SetMapper mapBookshelf2Top + [bookshelf2TopActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Bottom + bookshelf2Bottom SetInputConnection [reader GetOutputPort] + bookshelf2Bottom SetExtent 20 20 15 19 0 11 +vtkPolyDataMapper mapBookshelf2Bottom + mapBookshelf2Bottom SetInputConnection [bookshelf2Bottom GetOutputPort] + mapBookshelf2Bottom ScalarVisibilityOff +vtkActor bookshelf2BottomActor + bookshelf2BottomActor SetMapper mapBookshelf2Bottom + [bookshelf2BottomActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Front + bookshelf2Front SetInputConnection [reader GetOutputPort] + bookshelf2Front SetExtent 13 20 15 15 0 11 +vtkPolyDataMapper mapBookshelf2Front + mapBookshelf2Front SetInputConnection [bookshelf2Front GetOutputPort] + mapBookshelf2Front ScalarVisibilityOff +vtkActor bookshelf2FrontActor + bookshelf2FrontActor SetMapper mapBookshelf2Front + [bookshelf2FrontActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Back + bookshelf2Back SetInputConnection [reader GetOutputPort] + bookshelf2Back SetExtent 13 20 19 19 0 11 +vtkPolyDataMapper mapBookshelf2Back + mapBookshelf2Back SetInputConnection [bookshelf2Back GetOutputPort] + mapBookshelf2Back ScalarVisibilityOff +vtkActor bookshelf2BackActor + bookshelf2BackActor SetMapper mapBookshelf2Back + [bookshelf2BackActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2LHS + bookshelf2LHS SetInputConnection [reader GetOutputPort] + bookshelf2LHS SetExtent 13 20 15 19 0 0 +vtkPolyDataMapper mapBookshelf2LHS + mapBookshelf2LHS SetInputConnection [bookshelf2LHS GetOutputPort] + mapBookshelf2LHS ScalarVisibilityOff +vtkActor bookshelf2LHSActor + bookshelf2LHSActor SetMapper mapBookshelf2LHS + [bookshelf2LHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2RHS + bookshelf2RHS SetInputConnection [reader GetOutputPort] + bookshelf2RHS SetExtent 13 20 15 19 11 11 +vtkPolyDataMapper mapBookshelf2RHS + mapBookshelf2RHS SetInputConnection [bookshelf2RHS GetOutputPort] + mapBookshelf2RHS ScalarVisibilityOff +vtkActor bookshelf2RHSActor + bookshelf2RHSActor SetMapper mapBookshelf2RHS + [bookshelf2RHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter window + window SetInputConnection [reader GetOutputPort] + window SetExtent 20 20 6 13 10 13 +vtkPolyDataMapper mapWindow + mapWindow SetInputConnection [window GetOutputPort] + mapWindow ScalarVisibilityOff +vtkActor windowActor + windowActor SetMapper mapWindow + [windowActor GetProperty] SetColor .3 .3 .5 + +vtkStructuredGridGeometryFilter outlet + outlet SetInputConnection [reader GetOutputPort] + outlet SetExtent 0 0 9 10 14 16 +vtkPolyDataMapper mapOutlet + mapOutlet SetInputConnection [outlet GetOutputPort] + mapOutlet ScalarVisibilityOff +vtkActor outletActor + outletActor SetMapper mapOutlet + [outletActor GetProperty] SetColor 0 0 0 + +vtkStructuredGridGeometryFilter inlet + inlet SetInputConnection [reader GetOutputPort] + inlet SetExtent 0 0 9 10 0 6 +vtkPolyDataMapper mapInlet + mapInlet SetInputConnection [inlet GetOutputPort] + mapInlet ScalarVisibilityOff +vtkActor inletActor + inletActor SetMapper mapInlet + [inletActor GetProperty] SetColor 0 0 0 + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Now create the usual graphics stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor table1Actor +ren1 AddActor table2Actor +ren1 AddActor FilingCabinet1Actor +ren1 AddActor FilingCabinet2Actor +ren1 AddActor bookshelf1TopActor +ren1 AddActor bookshelf1BottomActor +ren1 AddActor bookshelf1FrontActor +ren1 AddActor bookshelf1BackActor +ren1 AddActor bookshelf1LHSActor +ren1 AddActor bookshelf1RHSActor +ren1 AddActor bookshelf2TopActor +ren1 AddActor bookshelf2BottomActor +ren1 AddActor bookshelf2FrontActor +ren1 AddActor bookshelf2BackActor +ren1 AddActor bookshelf2LHSActor +ren1 AddActor bookshelf2RHSActor +ren1 AddActor windowActor +ren1 AddActor outletActor +ren1 AddActor inletActor +ren1 AddActor outlineActor +ren1 AddActor streamTubeActor + +eval ren1 SetBackground $slate_grey + +# Here we specify a particular view. +vtkCamera aCamera + aCamera SetClippingRange 0.726079 36.3039 + aCamera SetFocalPoint 2.43584 2.15046 1.11104 + aCamera SetPosition -4.76183 -10.4426 3.17203 + aCamera SetViewUp 0.0511273 0.132773 0.989827 + aCamera SetViewAngle 18.604; + aCamera Zoom 1.2 + +ren1 SetActiveCamera aCamera + +renWin SetSize 500 300 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . diff --git a/Examples/VisualizationAlgorithms/Tcl/officeTubes.tcl b/Examples/VisualizationAlgorithms/Tcl/officeTubes.tcl new file mode 100644 index 0000000..b11c783 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/officeTubes.tcl @@ -0,0 +1,317 @@ +# This example demonstrates the use of streamlines generated from seeds, +# combined with a tube filter to create several streamtubes. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# We read a data file the is a CFD analysis of airflow in an office (with +# ventilation and a burning cigarette). We force an update so that we +# can query the output for its length, i.e., the length of the diagonal +# of the bounding box. This is useful for normalizing the data. +# +vtkStructuredGridReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/office.binary.vtk" + reader Update;#force a read to occur + +set length [[reader GetOutput] GetLength] + +set maxVelocity \ + [[[[reader GetOutput] GetPointData] GetVectors] GetMaxNorm] +set maxTime [expr 35.0 * $length / $maxVelocity] + +# Now we will generate multiple streamlines in the data. We create a random +# cloud of points and then use those as integration seeds. We select the +# integration order to use (RungeKutta order 4) and associate it with the +# streamer. The start position is the position in world space where we want +# to begin streamline integration; and we integrate in both directions. The +# step length is the length of the line segments that make up the streamline +# (i.e., related to display). The IntegrationStepLength specifies the +# integration step length as a fraction of the cell size that the streamline +# is in. +# Create source for streamtubes +vtkPointSource seeds + seeds SetRadius 0.15 + eval seeds SetCenter 0.1 2.1 0.5 + seeds SetNumberOfPoints 6 +vtkRungeKutta4 integ +vtkStreamTracer streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetSourceConnection [seeds GetOutputPort] + streamer SetMaximumPropagation 500 + streamer SetMaximumPropagationUnitToTimeUnit + streamer SetInitialIntegrationStep 0.05 + streamer SetInitialIntegrationStepUnitToCellLengthUnit + streamer SetIntegrationDirectionToBoth + streamer SetIntegrator integ + +# The tube is wrapped around the generated streamline. By varying the radius +# by the inverse of vector magnitude, we are creating a tube whose radius is +# proportional to mass flux (in incompressible flow). +vtkTubeFilter streamTube + streamTube SetInputConnection [streamer GetOutputPort] + streamTube SetInputArrayToProcess 1 0 0 vtkDataObject::FIELD_ASSOCIATION_POINTS vectors + streamTube SetRadius 0.02 + streamTube SetNumberOfSides 12 + streamTube SetVaryRadiusToVaryRadiusByVector +vtkPolyDataMapper mapStreamTube + mapStreamTube SetInputConnection [streamTube GetOutputPort] + eval mapStreamTube SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor streamTubeActor + streamTubeActor SetMapper mapStreamTube + [streamTubeActor GetProperty] BackfaceCullingOn + +# From here on we generate a whole bunch of planes which correspond to +# the geometry in the analysis; tables, bookshelves and so on. +vtkStructuredGridGeometryFilter table1 + table1 SetInputConnection [reader GetOutputPort] + table1 SetExtent 11 15 7 9 8 8 +vtkPolyDataMapper mapTable1 + mapTable1 SetInputConnection [table1 GetOutputPort] + mapTable1 ScalarVisibilityOff +vtkActor table1Actor + table1Actor SetMapper mapTable1 + [table1Actor GetProperty] SetColor .59 .427 .392 + +vtkStructuredGridGeometryFilter table2 + table2 SetInputConnection [reader GetOutputPort] + table2 SetExtent 11 15 10 12 8 8 +vtkPolyDataMapper mapTable2 + mapTable2 SetInputConnection [table2 GetOutputPort] + mapTable2 ScalarVisibilityOff +vtkActor table2Actor + table2Actor SetMapper mapTable2 + [table2Actor GetProperty] SetColor .59 .427 .392 + +vtkStructuredGridGeometryFilter FilingCabinet1 + FilingCabinet1 SetInputConnection [reader GetOutputPort] + FilingCabinet1 SetExtent 15 15 7 9 0 8 +vtkPolyDataMapper mapFilingCabinet1 + mapFilingCabinet1 SetInputConnection [FilingCabinet1 GetOutputPort] + mapFilingCabinet1 ScalarVisibilityOff +vtkActor FilingCabinet1Actor + FilingCabinet1Actor SetMapper mapFilingCabinet1 + [FilingCabinet1Actor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter FilingCabinet2 + FilingCabinet2 SetInputConnection [reader GetOutputPort] + FilingCabinet2 SetExtent 15 15 10 12 0 8 +vtkPolyDataMapper mapFilingCabinet2 + mapFilingCabinet2 SetInputConnection [FilingCabinet2 GetOutputPort] + mapFilingCabinet2 ScalarVisibilityOff +vtkActor FilingCabinet2Actor + FilingCabinet2Actor SetMapper mapFilingCabinet2 + [FilingCabinet2Actor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Top + bookshelf1Top SetInputConnection [reader GetOutputPort] + bookshelf1Top SetExtent 13 13 0 4 0 11 +vtkPolyDataMapper mapBookshelf1Top + mapBookshelf1Top SetInputConnection [bookshelf1Top GetOutputPort] + mapBookshelf1Top ScalarVisibilityOff +vtkActor bookshelf1TopActor + bookshelf1TopActor SetMapper mapBookshelf1Top + [bookshelf1TopActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Bottom + bookshelf1Bottom SetInputConnection [reader GetOutputPort] + bookshelf1Bottom SetExtent 20 20 0 4 0 11 +vtkPolyDataMapper mapBookshelf1Bottom + mapBookshelf1Bottom SetInputConnection [bookshelf1Bottom GetOutputPort] + mapBookshelf1Bottom ScalarVisibilityOff +vtkActor bookshelf1BottomActor + bookshelf1BottomActor SetMapper mapBookshelf1Bottom + [bookshelf1BottomActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Front + bookshelf1Front SetInputConnection [reader GetOutputPort] + bookshelf1Front SetExtent 13 20 0 0 0 11 +vtkPolyDataMapper mapBookshelf1Front + mapBookshelf1Front SetInputConnection [bookshelf1Front GetOutputPort] + mapBookshelf1Front ScalarVisibilityOff +vtkActor bookshelf1FrontActor + bookshelf1FrontActor SetMapper mapBookshelf1Front + [bookshelf1FrontActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Back + bookshelf1Back SetInputConnection [reader GetOutputPort] + bookshelf1Back SetExtent 13 20 4 4 0 11 +vtkPolyDataMapper mapBookshelf1Back + mapBookshelf1Back SetInputConnection [bookshelf1Back GetOutputPort] + mapBookshelf1Back ScalarVisibilityOff +vtkActor bookshelf1BackActor + bookshelf1BackActor SetMapper mapBookshelf1Back + [bookshelf1BackActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1LHS + bookshelf1LHS SetInputConnection [reader GetOutputPort] + bookshelf1LHS SetExtent 13 20 0 4 0 0 +vtkPolyDataMapper mapBookshelf1LHS + mapBookshelf1LHS SetInputConnection [bookshelf1LHS GetOutputPort] + mapBookshelf1LHS ScalarVisibilityOff +vtkActor bookshelf1LHSActor + bookshelf1LHSActor SetMapper mapBookshelf1LHS + [bookshelf1LHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1RHS + bookshelf1RHS SetInputConnection [reader GetOutputPort] + bookshelf1RHS SetExtent 13 20 0 4 11 11 +vtkPolyDataMapper mapBookshelf1RHS + mapBookshelf1RHS SetInputConnection [bookshelf1RHS GetOutputPort] + mapBookshelf1RHS ScalarVisibilityOff +vtkActor bookshelf1RHSActor + bookshelf1RHSActor SetMapper mapBookshelf1RHS + [bookshelf1RHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Top + bookshelf2Top SetInputConnection [reader GetOutputPort] + bookshelf2Top SetExtent 13 13 15 19 0 11 +vtkPolyDataMapper mapBookshelf2Top + mapBookshelf2Top SetInputConnection [bookshelf2Top GetOutputPort] + mapBookshelf2Top ScalarVisibilityOff +vtkActor bookshelf2TopActor + bookshelf2TopActor SetMapper mapBookshelf2Top + [bookshelf2TopActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Bottom + bookshelf2Bottom SetInputConnection [reader GetOutputPort] + bookshelf2Bottom SetExtent 20 20 15 19 0 11 +vtkPolyDataMapper mapBookshelf2Bottom + mapBookshelf2Bottom SetInputConnection [bookshelf2Bottom GetOutputPort] + mapBookshelf2Bottom ScalarVisibilityOff +vtkActor bookshelf2BottomActor + bookshelf2BottomActor SetMapper mapBookshelf2Bottom + [bookshelf2BottomActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Front + bookshelf2Front SetInputConnection [reader GetOutputPort] + bookshelf2Front SetExtent 13 20 15 15 0 11 +vtkPolyDataMapper mapBookshelf2Front + mapBookshelf2Front SetInputConnection [bookshelf2Front GetOutputPort] + mapBookshelf2Front ScalarVisibilityOff +vtkActor bookshelf2FrontActor + bookshelf2FrontActor SetMapper mapBookshelf2Front + [bookshelf2FrontActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Back + bookshelf2Back SetInputConnection [reader GetOutputPort] + bookshelf2Back SetExtent 13 20 19 19 0 11 +vtkPolyDataMapper mapBookshelf2Back + mapBookshelf2Back SetInputConnection [bookshelf2Back GetOutputPort] + mapBookshelf2Back ScalarVisibilityOff +vtkActor bookshelf2BackActor + bookshelf2BackActor SetMapper mapBookshelf2Back + [bookshelf2BackActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2LHS + bookshelf2LHS SetInputConnection [reader GetOutputPort] + bookshelf2LHS SetExtent 13 20 15 19 0 0 +vtkPolyDataMapper mapBookshelf2LHS + mapBookshelf2LHS SetInputConnection [bookshelf2LHS GetOutputPort] + mapBookshelf2LHS ScalarVisibilityOff +vtkActor bookshelf2LHSActor + bookshelf2LHSActor SetMapper mapBookshelf2LHS + [bookshelf2LHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2RHS + bookshelf2RHS SetInputConnection [reader GetOutputPort] + bookshelf2RHS SetExtent 13 20 15 19 11 11 +vtkPolyDataMapper mapBookshelf2RHS + mapBookshelf2RHS SetInputConnection [bookshelf2RHS GetOutputPort] + mapBookshelf2RHS ScalarVisibilityOff +vtkActor bookshelf2RHSActor + bookshelf2RHSActor SetMapper mapBookshelf2RHS + [bookshelf2RHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter window + window SetInputConnection [reader GetOutputPort] + window SetExtent 20 20 6 13 10 13 +vtkPolyDataMapper mapWindow + mapWindow SetInputConnection [window GetOutputPort] + mapWindow ScalarVisibilityOff +vtkActor windowActor + windowActor SetMapper mapWindow + [windowActor GetProperty] SetColor .3 .3 .5 + +vtkStructuredGridGeometryFilter outlet + outlet SetInputConnection [reader GetOutputPort] + outlet SetExtent 0 0 9 10 14 16 +vtkPolyDataMapper mapOutlet + mapOutlet SetInputConnection [outlet GetOutputPort] + mapOutlet ScalarVisibilityOff +vtkActor outletActor + outletActor SetMapper mapOutlet + [outletActor GetProperty] SetColor 0 0 0 + +vtkStructuredGridGeometryFilter inlet + inlet SetInputConnection [reader GetOutputPort] + inlet SetExtent 0 0 9 10 0 6 +vtkPolyDataMapper mapInlet + mapInlet SetInputConnection [inlet GetOutputPort] + mapInlet ScalarVisibilityOff +vtkActor inletActor + inletActor SetMapper mapInlet + [inletActor GetProperty] SetColor 0 0 0 + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Now create the usual graphics stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor table1Actor +ren1 AddActor table2Actor +ren1 AddActor FilingCabinet1Actor +ren1 AddActor FilingCabinet2Actor +ren1 AddActor bookshelf1TopActor +ren1 AddActor bookshelf1BottomActor +ren1 AddActor bookshelf1FrontActor +ren1 AddActor bookshelf1BackActor +ren1 AddActor bookshelf1LHSActor +ren1 AddActor bookshelf1RHSActor +ren1 AddActor bookshelf2TopActor +ren1 AddActor bookshelf2BottomActor +ren1 AddActor bookshelf2FrontActor +ren1 AddActor bookshelf2BackActor +ren1 AddActor bookshelf2LHSActor +ren1 AddActor bookshelf2RHSActor +ren1 AddActor windowActor +ren1 AddActor outletActor +ren1 AddActor inletActor +ren1 AddActor outlineActor +ren1 AddActor streamTubeActor + +eval ren1 SetBackground $slate_grey + +# Here we specify a particular view. +vtkCamera aCamera + aCamera SetClippingRange 0.726079 36.3039 + aCamera SetFocalPoint 2.43584 2.15046 1.11104 + aCamera SetPosition -4.76183 -10.4426 3.17203 + aCamera SetViewUp 0.0511273 0.132773 0.989827 + aCamera SetViewAngle 18.604; + aCamera Zoom 1.2 + +ren1 SetActiveCamera aCamera + +renWin SetSize 500 300 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . diff --git a/Examples/VisualizationAlgorithms/Tcl/probeComb.tcl b/Examples/VisualizationAlgorithms/Tcl/probeComb.tcl new file mode 100644 index 0000000..e0422e9 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/probeComb.tcl @@ -0,0 +1,127 @@ +# This shows how to probe a dataset with a plane. The probed data is then +# contoured. + +package require vtk +package require vtkinteraction + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# We create three planes and position them in the correct position +# using transform filters. They are then appended together and used as +# a probe. +vtkPlaneSource plane + plane SetResolution 50 50 +vtkTransform transP1 + transP1 Translate 3.7 0.0 28.37 + transP1 Scale 5 5 5 + transP1 RotateY 90 +vtkTransformPolyDataFilter tpd1 + tpd1 SetInputConnection [plane GetOutputPort] + tpd1 SetTransform transP1 +vtkOutlineFilter outTpd1 + outTpd1 SetInputConnection [tpd1 GetOutputPort] +vtkPolyDataMapper mapTpd1 + mapTpd1 SetInputConnection [outTpd1 GetOutputPort] +vtkActor tpd1Actor + tpd1Actor SetMapper mapTpd1 + [tpd1Actor GetProperty] SetColor 0 0 0 + +vtkTransform transP2 + transP2 Translate 9.2 0.0 31.20 + transP2 Scale 5 5 5 + transP2 RotateY 90 +vtkTransformPolyDataFilter tpd2 + tpd2 SetInputConnection [plane GetOutputPort] + tpd2 SetTransform transP2 +vtkOutlineFilter outTpd2 + outTpd2 SetInputConnection [tpd2 GetOutputPort] +vtkPolyDataMapper mapTpd2 + mapTpd2 SetInputConnection [outTpd2 GetOutputPort] +vtkActor tpd2Actor + tpd2Actor SetMapper mapTpd2 + [tpd2Actor GetProperty] SetColor 0 0 0 + +vtkTransform transP3 + transP3 Translate 13.27 0.0 33.30 + transP3 Scale 5 5 5 + transP3 RotateY 90 +vtkTransformPolyDataFilter tpd3 + tpd3 SetInputConnection [plane GetOutputPort] + tpd3 SetTransform transP3 +vtkOutlineFilter outTpd3 + outTpd3 SetInputConnection [tpd3 GetOutputPort] +vtkPolyDataMapper mapTpd3 + mapTpd3 SetInputConnection [outTpd3 GetOutputPort] +vtkActor tpd3Actor + tpd3Actor SetMapper mapTpd3 + [tpd3Actor GetProperty] SetColor 0 0 0 + +vtkAppendPolyData appendF + appendF AddInputConnection [tpd1 GetOutputPort] + appendF AddInputConnection [tpd2 GetOutputPort] + appendF AddInputConnection [tpd3 GetOutputPort] + +# The vtkProbeFilter takes two inputs. One is a dataset to use as the probe +# geometry (SetInputConnection); the other is the data to probe +# (SetSourceConnection). The output dataset structure (geometry and +# topology) of the probe is the same as the structure of the input. The +# probing process generates new data values resampled from the source. +vtkProbeFilter probe + probe SetInputConnection [appendF GetOutputPort] + probe SetSourceConnection [pl3d GetOutputPort] + +vtkContourFilter contour + contour SetInputConnection [probe GetOutputPort] + eval contour GenerateValues 50 [[pl3d GetOutput] GetScalarRange] +vtkPolyDataMapper contourMapper + contourMapper SetInputConnection [contour GetOutputPort] + eval contourMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor planeActor + planeActor SetMapper contourMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# create planes +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor tpd1Actor +ren1 AddActor tpd2Actor +ren1 AddActor tpd3Actor +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 8.88908 0.595038 29.3342 +$cam1 SetPosition -12.3332 31.7479 41.2387 +$cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/VisualizationAlgorithms/Tcl/smoothFran.tcl b/Examples/VisualizationAlgorithms/Tcl/smoothFran.tcl new file mode 100644 index 0000000..e114df4 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/smoothFran.tcl @@ -0,0 +1,63 @@ +# This example shows how to use decimation to reduce a polygonal mesh. We also +# use mesh smoothing and generate surface normals to give a pleasing result. +# + +package require vtk +package require vtkinteraction + +# We start by reading some data that was originally captured from +# a Cyberware laser digitizing system. +# +vtkPolyDataReader fran + fran SetFileName "$VTK_DATA_ROOT/Data/fran_cut.vtk" + +# We want to preserve topology (not let any cracks form). This may limit +# the total reduction possible, which we have specified at 90%. +# +vtkDecimatePro deci + deci SetInputConnection [fran GetOutputPort] + deci SetTargetReduction 0.9 + deci PreserveTopologyOn +vtkSmoothPolyDataFilter smoother + smoother SetInputConnection [deci GetOutputPort] + smoother SetNumberOfIterations 50 +vtkPolyDataNormals normals + normals SetInputConnection [smoother GetOutputPort] + normals FlipNormalsOn +vtkPolyDataMapper franMapper + franMapper SetInputConnection [normals GetOutputPort] +vtkActor franActor + franActor SetMapper franMapper + eval [franActor GetProperty] SetColor 1.0 0.49 0.25 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor franActor +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +vtkCamera cam1 + cam1 SetClippingRange 0.0475572 2.37786 + cam1 SetFocalPoint 0.052665 -0.129454 -0.0573973 + cam1 SetPosition 0.327637 -0.116299 -0.256418 + cam1 SetViewUp -0.0225386 0.999137 0.034901 +ren1 SetActiveCamera cam1 + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Examples/VisualizationAlgorithms/Tcl/spikeF.tcl b/Examples/VisualizationAlgorithms/Tcl/spikeF.tcl new file mode 100644 index 0000000..75818e8 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/spikeF.tcl @@ -0,0 +1,94 @@ +# This example demonstrates the use of glyphing. We also use a mask filter +# to select a subset of points to glyph. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# Read a data file. This originally was a Cyberware laser digitizer scan +# of Fran J.'s face. Surface normals are generated based on local geometry +# (i.e., the polygon normals surrounding eash point are averaged). We flip +# the normals because we want them to point out from Fran's face. +# +vtkPolyDataReader fran + fran SetFileName "$VTK_DATA_ROOT/Data/fran_cut.vtk" +vtkPolyDataNormals normals + normals SetInputConnection [fran GetOutputPort] + normals FlipNormalsOn +vtkPolyDataMapper franMapper + franMapper SetInputConnection [normals GetOutputPort] +vtkActor franActor + franActor SetMapper franMapper + eval [franActor GetProperty] SetColor 1.0 0.49 0.25 + +# We subsample the dataset because we want to glyph just a subset of +# the points. Otherwise the display is cluttered and cannot be easily +# read. The RandonModeOn and SetOnRatio combine to random select one out +# of every 10 points in the dataset. +# +vtkMaskPoints ptMask + ptMask SetInputConnection [normals GetOutputPort] + ptMask SetOnRatio 10 + ptMask RandomModeOn + +# In this case we are using a cone as a glyph. We transform the cone so +# its base is at 0,0,0. This is the point where glyph rotation occurs. +vtkConeSource cone + cone SetResolution 6 +vtkTransform transform + transform Translate 0.5 0.0 0.0 +vtkTransformPolyDataFilter transformF + transformF SetInputConnection [cone GetOutputPort] + transformF SetTransform transform + +# vtkGlyph3D takes two inputs: the input point set (SetInputConnection) +# which can be any vtkDataSet; and the glyph (SetSourceConnection) which +# must be a vtkPolyData. We are interested in orienting the glyphs by the +# surface normals that we previosuly generated. +vtkGlyph3D glyph + glyph SetInputConnection [ptMask GetOutputPort] + glyph SetSourceConnection [transformF GetOutputPort] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.004 +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] +vtkActor spikeActor + spikeActor SetMapper spikeMapper + eval [spikeActor GetProperty] SetColor 0.0 0.79 0.34 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor franActor +ren1 AddActor spikeActor + +renWin SetSize 500 500 +ren1 SetBackground 0.1 0.2 0.4 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +$cam1 Azimuth 110 +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Examples/VisualizationAlgorithms/Tcl/streamSurface.tcl b/Examples/VisualizationAlgorithms/Tcl/streamSurface.tcl new file mode 100644 index 0000000..ed02197 --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/streamSurface.tcl @@ -0,0 +1,93 @@ +# This example demonstrates the generation of a streamsurface. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. +# +package require vtk +package require vtkinteraction +package require vtktesting + +# Read the data and specify which scalars and vectors to read. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# We use a rake to generate a series of streamline starting points +# scattered along a line. Each point will generate a streamline. These +# streamlines are then fed to the vtkRuledSurfaceFilter which stitches +# the lines together to form a surface. +# +vtkLineSource rake + rake SetPoint1 15 -5 32 + rake SetPoint2 15 5 32 + rake SetResolution 21 +vtkPolyDataMapper rakeMapper + rakeMapper SetInputConnection [rake GetOutputPort] +vtkActor rakeActor + rakeActor SetMapper rakeMapper + +vtkRungeKutta4 integ +vtkStreamTracer sl + sl SetInputConnection [pl3d GetOutputPort] + sl SetSourceConnection [rake GetOutputPort] + sl SetIntegrator integ + sl SetMaximumPropagation 0.1 + sl SetMaximumPropagationUnitToTimeUnit + sl SetInitialIntegrationStep 0.1 + sl SetInitialIntegrationStepUnitToCellLengthUnit + sl SetIntegrationDirectionToBackward + +# +# The ruled surface stiches together lines with triangle strips. +# Note the SetOnRatio method. It turns on every other strip that +# the filter generates (only when multiple lines are input). +# +vtkRuledSurfaceFilter scalarSurface + scalarSurface SetInputConnection [sl GetOutputPort] + scalarSurface SetOffset 0 + scalarSurface SetOnRatio 2 + scalarSurface PassLinesOn + scalarSurface SetRuledModeToPointWalk + scalarSurface SetDistanceFactor 30 +vtkPolyDataMapper mapper + mapper SetInputConnection [scalarSurface GetOutputPort] + eval mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor actor + actor SetMapper mapper + +# Put an outline around for context. +# +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Now create the usual graphics stuff. +vtkRenderer ren +vtkRenderWindow renWin + renWin AddRenderer ren +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren AddActor rakeActor +ren AddActor actor +ren AddActor outlineActor +ren SetBackground 1 1 1 + +renWin SetSize 300 300 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . + diff --git a/Examples/VisualizationAlgorithms/Tcl/warpComb.tcl b/Examples/VisualizationAlgorithms/Tcl/warpComb.tcl new file mode 100644 index 0000000..e92f84c --- /dev/null +++ b/Examples/VisualizationAlgorithms/Tcl/warpComb.tcl @@ -0,0 +1,102 @@ +# This example demonstrates how to extract "computational planes" from a +# structured dataset. Structured data has a natural, logical coordinate +# system based on i-j-k indices. Specifying imin,imax, jmin,jmax, kmin,kmax +# pairs can indicate a point, line, plane, or volume of data. +# +# In this example, we extract three planes and warp them using scalar values +# in the direction of the local normal at each point. This gives a sort of +# "velocity profile" that indicates the nature of the flow. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands from Tcl. The vtkinteraction package defines +# a simple Tcl/Tk interactor widget. +# +package require vtk +package require vtkinteraction + +# Here we read data from a annular combustor. A combustor burns fuel and air +# in a gas turbine (e.g., a jet engine) and the hot gas eventually makes its +# way to the turbine section. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# Planes are specified using a imin,imax, jmin,jmax, kmin,kmax coordinate +# specification. Min and max i,j,k values are clamped to 0 and maximum value. +# +vtkStructuredGridGeometryFilter plane + plane SetInputConnection [pl3d GetOutputPort] + plane SetExtent 10 10 1 100 1 100 +vtkStructuredGridGeometryFilter plane2 + plane2 SetInputConnection [pl3d GetOutputPort] + plane2 SetExtent 30 30 1 100 1 100 +vtkStructuredGridGeometryFilter plane3 + plane3 SetInputConnection [pl3d GetOutputPort] + plane3 SetExtent 45 45 1 100 1 100 + +# We use an append filter because that way we can do the warping, etc. just +# using a single pipeline and actor. +# +vtkAppendPolyData appendF + appendF AddInputConnection [plane GetOutputPort] + appendF AddInputConnection [plane2 GetOutputPort] + appendF AddInputConnection [plane3 GetOutputPort] +vtkWarpScalar warp + warp SetInputConnection [appendF GetOutputPort] + warp UseNormalOn + warp SetNormal 1.0 0.0 0.0 + warp SetScaleFactor 2.5 +vtkPolyDataNormals normals + normals SetInputConnection [warp GetOutputPort] + normals SetFeatureAngle 60 +vtkPolyDataMapper planeMapper + planeMapper SetInputConnection [normals GetOutputPort] + eval planeMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor planeActor + planeActor SetMapper planeMapper + +# The outline provides context for the data and the planes. +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Create the usual graphics stuff/ +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 + +# Create an initial view. +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 8.88908 0.595038 29.3342 +$cam1 SetPosition -12.3332 31.7479 41.2387 +$cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Examples/VolumeRendering/Python/PseudoVolumeRendering.py b/Examples/VolumeRendering/Python/PseudoVolumeRendering.py new file mode 100644 index 0000000..7c48e49 --- /dev/null +++ b/Examples/VolumeRendering/Python/PseudoVolumeRendering.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python + +# Perform psuedo volume rendering in a structured grid by compositing +# translucent cut planes. This same trick can be used for unstructured +# grids. Note that for better results, more planes can be created. Also, +# if your data is vtkImageData, there are much faster methods for volume +# rendering. + +import vtk +from vtk.util.colors import * +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create pipeline. Read structured grid data. +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName(VTK_DATA_ROOT + "/Data/combxyz.bin") +pl3d.SetQFileName(VTK_DATA_ROOT + "/Data/combq.bin") +pl3d.SetScalarFunctionNumber(100) +pl3d.SetVectorFunctionNumber(202) +pl3d.Update() + +# A convenience, use this filter to limit data for experimentation. +extract = vtk.vtkExtractGrid() +extract.SetVOI(1, 55, -1000, 1000, -1000, 1000) +extract.SetInputConnection(pl3d.GetOutputPort()) + +# The (implicit) plane is used to do the cutting +plane = vtk.vtkPlane() +plane.SetOrigin(0, 4, 2) +plane.SetNormal(0, 1, 0) + +# The cutter is set up to process each contour value over all cells +# (SetSortByToSortByCell). This results in an ordered output of polygons +# which is key to the compositing. +cutter = vtk.vtkCutter() +cutter.SetInputConnection(extract.GetOutputPort()) +cutter.SetCutFunction(plane) +cutter.GenerateCutScalarsOff() +cutter.SetSortByToSortByCell() + +clut = vtk.vtkLookupTable() +clut.SetHueRange(0, .67) +clut.Build() + +cutterMapper = vtk.vtkPolyDataMapper() +cutterMapper.SetInputConnection(cutter.GetOutputPort()) +cutterMapper.SetScalarRange(.18, .7) +cutterMapper.SetLookupTable(clut) + +cut = vtk.vtkActor() +cut.SetMapper(cutterMapper) + +# Add in some surface geometry for interest. +iso = vtk.vtkContourFilter() +iso.SetInputConnection(pl3d.GetOutputPort()) +iso.SetValue(0, .22) +normals = vtk.vtkPolyDataNormals() +normals.SetInputConnection(iso.GetOutputPort()) +normals.SetFeatureAngle(45) +isoMapper = vtk.vtkPolyDataMapper() +isoMapper.SetInputConnection(normals.GetOutputPort()) +isoMapper.ScalarVisibilityOff() +isoActor = vtk.vtkActor() +isoActor.SetMapper(isoMapper) +isoActor.GetProperty().SetDiffuseColor(tomato) +isoActor.GetProperty().SetSpecularColor(white) +isoActor.GetProperty().SetDiffuse(.8) +isoActor.GetProperty().SetSpecular(.5) +isoActor.GetProperty().SetSpecularPower(30) + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) +outlineTubes = vtk.vtkTubeFilter() +outlineTubes.SetInputConnection(outline.GetOutputPort()) +outlineTubes.SetRadius(.1) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outlineTubes.GetOutputPort()) +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +# Create the RenderWindow, Renderer and Interactor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Add the actors to the renderer, set the background and size +ren.AddActor(outlineActor) +outlineActor.GetProperty().SetColor(banana) +ren.AddActor(isoActor) +isoActor.VisibilityOn() +ren.AddActor(cut) +opacity = .1 +cut.GetProperty().SetOpacity(1) +ren.SetBackground(1, 1, 1) +renWin.SetSize(640, 480) + +cam1 = ren.GetActiveCamera() +cam1.SetClippingRange(3.95297, 50) +cam1.SetFocalPoint(9.71821, 0.458166, 29.3999) +cam1.SetPosition(2.7439, -37.3196, 38.7167) +cam1.ComputeViewPlaneNormal() +cam1.SetViewUp(-0.16123, 0.264271, 0.950876) + +# Cut: generates n cut planes normal to camera's view plane +def Cut(n): + global cam1, opacity + plane.SetNormal(cam1.GetViewPlaneNormal()) + plane.SetOrigin(cam1.GetFocalPoint()) + cutter.GenerateValues(n, -5, 5) + clut.SetAlphaRange(opacity, opacity) + renWin.Render() + + +# Generate 10 cut planes +Cut(20) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VolumeRendering/Python/SimpleRayCast.py b/Examples/VolumeRendering/Python/SimpleRayCast.py new file mode 100644 index 0000000..6032523 --- /dev/null +++ b/Examples/VolumeRendering/Python/SimpleRayCast.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +# This is a simple volume rendering example that uses a +# vtkVolumeRayCast mapper + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create the standard renderer, render window and interactor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Create the reader for the data +reader = vtk.vtkStructuredPointsReader() +reader.SetFileName(VTK_DATA_ROOT + "/Data/ironProt.vtk") + +# Create transfer mapping scalar value to opacity +opacityTransferFunction = vtk.vtkPiecewiseFunction() +opacityTransferFunction.AddPoint(20, 0.0) +opacityTransferFunction.AddPoint(255, 0.2) + +# Create transfer mapping scalar value to color +colorTransferFunction = vtk.vtkColorTransferFunction() +colorTransferFunction.AddRGBPoint(0.0, 0.0, 0.0, 0.0) +colorTransferFunction.AddRGBPoint(64.0, 1.0, 0.0, 0.0) +colorTransferFunction.AddRGBPoint(128.0, 0.0, 0.0, 1.0) +colorTransferFunction.AddRGBPoint(192.0, 0.0, 1.0, 0.0) +colorTransferFunction.AddRGBPoint(255.0, 0.0, 0.2, 0.0) + +# The property describes how the data will look +volumeProperty = vtk.vtkVolumeProperty() +volumeProperty.SetColor(colorTransferFunction) +volumeProperty.SetScalarOpacity(opacityTransferFunction) +volumeProperty.ShadeOn() +volumeProperty.SetInterpolationTypeToLinear() + +# The mapper / ray cast function know how to render the data +compositeFunction = vtk.vtkVolumeRayCastCompositeFunction() +volumeMapper = vtk.vtkVolumeRayCastMapper() +volumeMapper.SetVolumeRayCastFunction(compositeFunction) +volumeMapper.SetInputConnection(reader.GetOutputPort()) + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +volume = vtk.vtkVolume() +volume.SetMapper(volumeMapper) +volume.SetProperty(volumeProperty) + +ren.AddVolume(volume) +ren.SetBackground(1, 1, 1) +renWin.SetSize(600, 600) +renWin.Render() + +def CheckAbort(obj, event): + if obj.GetEventPending() != 0: + obj.SetAbortRender(1) + +renWin.AddObserver("AbortCheckEvent", CheckAbort) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VolumeRendering/Python/SimpleTextureMap2D.py b/Examples/VolumeRendering/Python/SimpleTextureMap2D.py new file mode 100644 index 0000000..997f994 --- /dev/null +++ b/Examples/VolumeRendering/Python/SimpleTextureMap2D.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python + +# This is a simple volume rendering example that uses a +# vtkVolumeTextureMapper2D mapper + +import vtk +from vtk.util.misc import vtkGetDataRoot +VTK_DATA_ROOT = vtkGetDataRoot() + +# Create the standard renderer, render window and interactor +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# Create the reader for the data +reader = vtk.vtkStructuredPointsReader() +reader.SetFileName(VTK_DATA_ROOT + "/Data/ironProt.vtk") + +# Create transfer mapping scalar value to opacity +opacityTransferFunction = vtk.vtkPiecewiseFunction() +opacityTransferFunction.AddPoint(20, 0.0) +opacityTransferFunction.AddPoint(255, 0.2) + +# Create transfer mapping scalar value to color +colorTransferFunction = vtk.vtkColorTransferFunction() +colorTransferFunction.AddRGBPoint(0.0, 0.0, 0.0, 0.0) +colorTransferFunction.AddRGBPoint(64.0, 1.0, 0.0, 0.0) +colorTransferFunction.AddRGBPoint(128.0, 0.0, 0.0, 1.0) +colorTransferFunction.AddRGBPoint(192.0, 0.0, 1.0, 0.0) +colorTransferFunction.AddRGBPoint(255.0, 0.0, 0.2, 0.0) + +# The property describes how the data will look +volumeProperty = vtk.vtkVolumeProperty() +volumeProperty.SetColor(colorTransferFunction) +volumeProperty.SetScalarOpacity(opacityTransferFunction) + +# The mapper knows how to render the data +volumeMapper = vtk.vtkVolumeTextureMapper2D() +volumeMapper.SetInputConnection(reader.GetOutputPort()) + +# The volume holds the mapper and the property and can be used to +# position/orient the volume +volume = vtk.vtkVolume() +volume.SetMapper(volumeMapper) +volume.SetProperty(volumeProperty) + +ren.AddVolume(volume) +renWin.Render() + +def CheckAbort(obj, event): + if obj.GetEventPending() != 0: + obj.SetAbortRender(1) + +renWin.AddObserver("AbortCheckEvent", CheckAbort) + +iren.Initialize() +renWin.Render() +iren.Start() diff --git a/Examples/VolumeRendering/Tcl/IntermixedUnstructuredGrid.tcl b/Examples/VolumeRendering/Tcl/IntermixedUnstructuredGrid.tcl new file mode 100644 index 0000000..1be3371 --- /dev/null +++ b/Examples/VolumeRendering/Tcl/IntermixedUnstructuredGrid.tcl @@ -0,0 +1,110 @@ +# This is an example of volume rendering unstructured grid data. +# Two data sets are loaded (both vtkImageData) - one is converted +# to a set of tetrahedra (through the use of a vtkThreshold filter +# and a vtkDataSetTriangleFilter) and the other is contoured. +# The geometry and the volume rendering are them displayed together. + +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create the reader for the data +# This is the data the will be volume rendered +vtkStructuredPointsReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +# create a reader for the other data that will +# be contoured and displayed as a polygonal mesh +vtkSLCReader reader2 + reader2 SetFileName "$VTK_DATA_ROOT/Data/neghip.slc" + +# convert from vtkImageData to vtkUnstructuredGrid, remove +# any cells where all values are below 80 +vtkThreshold thresh + thresh ThresholdByUpper 80 + thresh AllScalarsOff + thresh SetInputConnection [reader GetOutputPort] + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [thresh GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 80 0.0 + opacityTransferFunction AddPoint 120 0.2 + opacityTransferFunction AddPoint 255 0.2 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 80.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 120.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 160.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 200.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 1.0 1.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + +# The mapper / ray cast function know how to render the data +vtkUnstructuredGridVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# contour the second dataset +vtkContourFilter contour + contour SetValue 0 80 + contour SetInputConnection [reader2 GetOutputPort] + +# create a mapper for the polygonal data +vtkPolyDataMapper mapper + mapper SetInputConnection [contour GetOutputPort] + mapper ScalarVisibilityOff + +# create an actor for the polygonal data +vtkActor actor + actor SetMapper mapper + +ren1 AddViewProp actor + +ren1 AddVolume volume +renWin SetSize 300 300 + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 10.0 +[ren1 GetActiveCamera] Zoom 1.5 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Examples/VolumeRendering/Tcl/PseudoVolumeRendering.tcl b/Examples/VolumeRendering/Tcl/PseudoVolumeRendering.tcl new file mode 100644 index 0000000..56bac57 --- /dev/null +++ b/Examples/VolumeRendering/Tcl/PseudoVolumeRendering.tcl @@ -0,0 +1,126 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Perform psuedo volume rendering in a structured grid by compositing +# translucent cut planes. This same trick can be used for unstructured +# grids. Note that for better results, more planes can be created. Also, +# if your data is vtkImageData, there are much faster methods for volume +# rendering. + +# Create pipeline. Read structured grid data. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# A convenience, use this filter to limit data for experimentation. +vtkExtractGrid extract + extract SetVOI 1 55 -1000 1000 -1000 1000 + extract SetInputConnection [pl3d GetOutputPort] + +# The (implicit) plane is used to do the cutting +vtkPlane plane + plane SetOrigin 0 4 2 + plane SetNormal 0 1 0 + +# The cutter is set up to process each contour value over all cells +# (SetSortByToSortByCell). This results in an ordered output of polygons +# which is key to the compositing. +vtkCutter cutter + cutter SetInputConnection [extract GetOutputPort] + cutter SetCutFunction plane + cutter GenerateCutScalarsOff + cutter SetSortByToSortByCell + +vtkLookupTable clut + clut SetHueRange 0 .67 + clut Build + +vtkPolyDataMapper cutterMapper +cutterMapper SetInputConnection [cutter GetOutputPort] +cutterMapper SetScalarRange .18 .7 +cutterMapper SetLookupTable clut + +vtkActor cut + cut SetMapper cutterMapper + +# Add in some surface geometry for interest. +vtkContourFilter iso + iso SetInputConnection [pl3d GetOutputPort] + iso SetValue 0 .22 +vtkPolyDataNormals normals + normals SetInputConnection [iso GetOutputPort] + normals SetFeatureAngle 45 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOff +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetDiffuseColor $tomato + eval [isoActor GetProperty] SetSpecularColor $white + eval [isoActor GetProperty] SetDiffuse .8 + eval [isoActor GetProperty] SetSpecular .5 + eval [isoActor GetProperty] SetSpecularPower 30 + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkTubeFilter outlineTubes + outlineTubes SetInputConnection [outline GetOutputPort] + outlineTubes SetRadius .1 + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outlineTubes GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +eval [outlineActor GetProperty] SetColor $banana +ren1 AddActor isoActor +isoActor VisibilityOn +ren1 AddActor cut +set opacity .1 +[cut GetProperty] SetOpacity 1 +ren1 SetBackground 1 1 1 +renWin SetSize 640 480 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 ComputeViewPlaneNormal +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Cut: generates n cut planes normal to camera's view plane +# +proc Cut {n} { + global cam1 opacity + eval plane SetNormal [$cam1 GetViewPlaneNormal] + eval plane SetOrigin [$cam1 GetFocalPoint] + eval cutter GenerateValues $n -5 5 + clut SetAlphaRange $opacity $opacity + renWin Render +} + +# Generate 10 cut planes +Cut 20 + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Examples/VolumeRendering/Tcl/SimpleRayCast.tcl b/Examples/VolumeRendering/Tcl/SimpleRayCast.tcl new file mode 100644 index 0000000..7d9e235 --- /dev/null +++ b/Examples/VolumeRendering/Tcl/SimpleRayCast.tcl @@ -0,0 +1,68 @@ +# This is a simple volume rendering example that +# uses a vtkVolumeRayCast mapper + +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create the reader for the data +vtkStructuredPointsReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 20 0.0 + opacityTransferFunction AddPoint 255 0.2 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOn + volumeProperty SetInterpolationTypeToLinear + +# The mapper / ray cast function know how to render the data +vtkVolumeRayCastCompositeFunction compositeFunction +vtkVolumeRayCastMapper volumeMapper + volumeMapper SetVolumeRayCastFunction compositeFunction + volumeMapper SetInputConnection [reader GetOutputPort] + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +ren1 SetBackground 1 1 1 +renWin SetSize 600 600 +renWin Render + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Examples/VolumeRendering/Tcl/SimpleTextureMap2D.tcl b/Examples/VolumeRendering/Tcl/SimpleTextureMap2D.tcl new file mode 100644 index 0000000..3f761e6 --- /dev/null +++ b/Examples/VolumeRendering/Tcl/SimpleTextureMap2D.tcl @@ -0,0 +1,62 @@ +# This is a simple volume rendering example that +# uses a vtkVolumeRayCast mapper + +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create the reader for the data +vtkStructuredPointsReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 20 0.0 + opacityTransferFunction AddPoint 255 0.2 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + +# The mapper knows how to render the data +vtkVolumeTextureMapper2D volumeMapper + volumeMapper SetInputConnection [reader GetOutputPort] + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +renWin Render + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Examples/VolumeRendering/Tcl/volSimpleLOD.tcl b/Examples/VolumeRendering/Tcl/volSimpleLOD.tcl new file mode 100644 index 0000000..c24e4b9 --- /dev/null +++ b/Examples/VolumeRendering/Tcl/volSimpleLOD.tcl @@ -0,0 +1,356 @@ +# This example demonstrates volume rendering and the use of vtkLODProp3D. +# vtkLODProp3D allows the user to set different graphical representations of +# the data to achieve different levels of interactivity. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +# +# Create an SLC reader and read in the data. +# +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/neghip.slc" + +# +# Create transfer functions for opacity and color to be used in volume +# properties. +# +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 20 0.0 + opacityTransferFunction AddPoint 255 0.2 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# +# Create volume properties +# +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToNearest + +vtkVolumeProperty volumeProperty2 + volumeProperty2 SetColor colorTransferFunction + volumeProperty2 SetScalarOpacity opacityTransferFunction + volumeProperty2 SetInterpolationTypeToLinear + +# +# Create a volume ray cast mapper. The volume is used for levels 1 and 2 of +# LODProp3D. +# +vtkVolumeRayCastCompositeFunction compositeFunction +vtkVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [reader GetOutputPort] + volumeMapper SetVolumeRayCastFunction compositeFunction + +# +# Set up the color lookup table for the probe planes to be used in levels 3 and +# 4 of the LODProp3D +# +vtkLookupTable ColorLookupTable +ColorLookupTable SetNumberOfTableValues 256 + +for { set i 0 } { $i < 256 } { incr i } { + set r [colorTransferFunction GetRedValue $i] + set g [colorTransferFunction GetGreenValue $i] + set b [colorTransferFunction GetBlueValue $i] + set a [opacityTransferFunction GetValue $i] + set a [expr $a * 10.0] + if { $a > 1.0 } { set a 1.0 } + ColorLookupTable SetTableValue $i $r $g $b $a +} + +# +# Create planes or different resolutions to probe the data read in using the +# SLC reader. The probe results are used as levels 3 and 4 of the LODProp3D. +# +set types [list hres lres] +foreach type $types { + for { set i 0 } { $i < 3 } { incr i } { + vtkPlaneSource plane${i}_${type} + + vtkTransform transform${i}_${type} + transform${i}_${type} Identity + + vtkTransformPolyDataFilter transpd${i}_${type} + transpd${i}_${type} SetInputConnection [plane${i}_${type} GetOutputPort] + transpd${i}_${type} SetTransform transform${i}_${type} + + vtkProbeFilter probe${i}_${type} + probe${i}_${type} SetInputConnection [transpd${i}_${type} GetOutputPort] + probe${i}_${type} SetSource [reader GetOutput] + + vtkCastToConcrete cast${i}_${type} + cast${i}_${type} SetInputConnection [probe${i}_${type} GetOutputPort] + + vtkTriangleFilter tf${i}_${type} + tf${i}_${type} SetInput [cast${i}_${type} GetPolyDataOutput] + + vtkStripper strip${i}_${type} + strip${i}_${type} SetInputConnection [tf${i}_${type} GetOutputPort] + } + + transform0_${type} Translate 33.0 33.0 33.0 + transform0_${type} Scale 66.0 66.0 66.0 + transform1_${type} Translate 33.0 33.0 33.0 + transform1_${type} RotateX 90 + transform1_${type} Scale 66.0 66.0 66.0 + transform2_${type} Translate 33.0 33.0 33.0 + transform2_${type} RotateY 90 + transform2_${type} Scale 66.0 66.0 66.0 + + vtkAppendPolyData apd_${type} + apd_${type} AddInput [tf0_${type} GetOutput] + apd_${type} AddInput [tf1_${type} GetOutput] + apd_${type} AddInput [tf2_${type} GetOutput] + + vtkPolyDataMapper probeMapper_${type} + probeMapper_${type} SetInputConnection [apd_${type} GetOutputPort] + probeMapper_${type} SetColorModeToMapScalars + probeMapper_${type} SetLookupTable ColorLookupTable + probeMapper_${type} SetScalarRange 0 255 +} + +# +# Set the resolution of each of the planes just created +# +plane0_hres SetResolution 60 60 +plane1_hres SetResolution 60 60 +plane2_hres SetResolution 60 60 +plane0_lres SetResolution 25 25 +plane1_lres SetResolution 25 25 +plane2_lres SetResolution 25 25 + +# +# Set the opacity to be used in the probe mappers +# +vtkProperty probeProperty + probeProperty SetOpacity 0.99 + +# +# Create outline to be used as level 5 in the LODProp3D +# +vtkOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkProperty outlineProperty +outlineProperty SetColor 1 1 1 + +# +# Create the LODProp3D and add the mappers to it. +# +vtkLODProp3D lod +set level1 [lod AddLOD volumeMapper volumeProperty2 0.0] +set level2 [lod AddLOD volumeMapper volumeProperty 0.0] +set level3 [lod AddLOD probeMapper_hres probeProperty 0.0] +set level4 [lod AddLOD probeMapper_lres probeProperty 0.0] +set level5 [lod AddLOD outlineMapper outlineProperty 0.0] + +# +# Create the render window and the renderer. +# +vtkRenderWindow renWin +vtkRenderer ren1 +renWin AddRenderer ren1 + +# +# Add the LODProp3D to the renderer and set the background +# +ren1 AddViewProp lod +ren1 SetBackground 0.1 0.2 0.4 + +# +# Withdraw the default tk window +# +wm withdraw . + +# +# Create the user interface including the RenderWindow +# +toplevel .top \ + -visual best +wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit + +frame .top.ren +frame .top.controls + +pack .top.controls \ + -side left -anchor n \ + -padx 3 -pady 3 + +pack .top.ren \ + -side right -anchor n \ + -padx 3 -pady 3 \ + -expand t -fill both + +# +# Create Tk renderwidget, bind events +# +vtkTkRenderWidget .top.ren.rw \ + -rw renWin \ + -width 300 \ + -height 300 + +::vtk::bind_tk_render_widget .top.ren.rw + +pack .top.ren.rw \ + -expand t -fill both + +# +# Create LOD display controls +# +label .top.controls.lod \ + -text "LOD Selected:" + +pack .top.controls.lod \ + -side top -anchor w \ + -padx 5 -pady 6 + +label .top.controls.l1 -text "Level 1 FPS:" +label .top.controls.l2 -text "Level 2 FPS:" +label .top.controls.l3 -text "Level 3 FPS:" +label .top.controls.l4 -text "Level 4 FPS:" +label .top.controls.l5 -text "Level 5 FPS:" + +pack .top.controls.l1 .top.controls.l2 .top.controls.l3 .top.controls.l4 .top.controls.l5 \ + -side top -anchor w \ + -padx 5 -pady 2 + +# +# Create frame rate controls +# +set still_update_rate 0.5 +set interactive_update_rate 5.0 + +proc update_rates {{foo 0}} { + global still_update_rate interactive_update_rate + set iren [renWin GetInteractor] + $iren SetStillUpdateRate $still_update_rate + $iren SetDesiredUpdateRate $interactive_update_rate +} + +update_rates + +scale .top.controls.s1 \ + -label "Still FPS:" \ + -orient horizontal \ + -length 150 \ + -from 0.05 -to 1.0 -resolution 0.05 \ + -variable still_update_rate \ + -command update_rates \ + -highlightthickness 0 + +scale .top.controls.s2 \ + -label "Moving FPS:" \ + -orient horizontal \ + -length 150 \ + -from 1.0 -to 100.0 -resolution 1.0 \ + -variable interactive_update_rate \ + -command update_rates \ + -highlightthickness 0 + +pack .top.controls.s1 .top.controls.s2 \ + -side top \ + -anchor w -padx 5 -pady 6 + +button .top.controls.quit \ + -text "Quit" \ + -command ::vtk::cb_exit + +pack .top.controls.quit \ + -side top \ + -padx 5 -pady 6 \ + -expand 1 -fill both + +# +# Determine whether to allow automatic LOD selection. +# +if { [info command rtExMath] != "" } { + lod AutomaticLODSelectionOff + lod SetSelectedLODID $level3 +} + +# +# Create a Tcl procedure to display (in the user interface) which LOD is +# currently active. +# This proc is called each time an EndEvent is triggered by the renderer. +# +renWin AddObserver EndEvent ChangeLabels + +proc ChangeLabels { } { + + global level1 level2 level3 level4 level5 + + set value [lod GetLastRenderedLODID] + if { $value == $level1 } { + .top.controls.lod configure -text "LOD Selected: Level 1" + } elseif { $value == $level2 } { + .top.controls.lod configure -text "LOD Selected: Level 2" + } elseif { $value == $level3 } { + .top.controls.lod configure -text "LOD Selected: Level 3" + } elseif { $value == $level4 } { + .top.controls.lod configure -text "LOD Selected: Level 4" + } elseif { $value == $level5 } { + .top.controls.lod configure -text "LOD Selected: Level 5" + } + + set value [lod GetLODEstimatedRenderTime $level1] + if { $value == 0 } { + .top.controls.l1 configure -text "Level 1 FPS: unknown" + } else { + .top.controls.l1 configure -text \ + "Level 1 FPS: [format "%.2f" [expr 1.0 / $value]]" + } + + set value [lod GetLODEstimatedRenderTime $level2] + if { $value == 0 } { + .top.controls.l2 configure -text "Level 2 FPS: unknown" + } else { + .top.controls.l2 configure -text \ + "Level 2 FPS: [format "%.2f" [expr 1.0 / $value]]" + } + + set value [lod GetLODEstimatedRenderTime $level3] + if { $value == 0 } { + .top.controls.l3 configure -text "Level 3 FPS: unknown" + } else { + .top.controls.l3 configure -text \ + "Level 3 FPS: [format "%.2f" [expr 1.0 / $value]]" + } + + set value [lod GetLODEstimatedRenderTime $level4] + if { $value == 0 } { + .top.controls.l4 configure -text "Level 4 FPS: unknown" + } else { + .top.controls.l4 configure -text \ + "Level 4 FPS: [format "%.2f" [expr 1.0 / $value]]" + } + + set value [lod GetLODEstimatedRenderTime $level5] + if { $value == 0 } { + .top.controls.l5 configure -text "Level 5 FPS: unknown" + } else { + .top.controls.l5 configure -text \ + "Level 5 FPS: [format "%.2f" [expr 1.0 / $value]]" + } +} + +# +# Render into the RenderWindow +# +renWin Render + +tkwait window . + diff --git a/Filtering/CMakeLists.txt b/Filtering/CMakeLists.txt new file mode 100644 index 0000000..b56b226 --- /dev/null +++ b/Filtering/CMakeLists.txt @@ -0,0 +1,320 @@ +SET(KIT Filtering) +SET(UKIT FILTERING) +SET(KIT_TCL_LIBS vtkCommonTCL) +SET(KIT_PYTHON_LIBS vtkCommonPythonD) +SET(KIT_JAVA_LIBS vtkCommonJava) +SET(KIT_LIBS vtkCommon) + +SET( Kit_SRCS +vtkAbstractMapper.cxx +vtkActor2D.cxx +vtkActor2DCollection.cxx +vtkAlgorithm.cxx +vtkAlgorithmOutput.cxx +vtkCachedStreamingDemandDrivenPipeline.cxx +vtkCardinalSpline.cxx +vtkCastToConcrete.cxx +vtkCell.cxx +vtkCell3D.cxx +vtkCellArray.cxx +vtkCellData.cxx +vtkCellLinks.cxx +vtkCellLocator.cxx +vtkCellTypes.cxx +vtkColorTransferFunction.cxx +vtkCompositeDataIterator.cxx +vtkCompositeDataPipeline.cxx +vtkCompositeDataSet.cxx +vtkCone.cxx +vtkConvexPointSet.cxx +vtkCoordinate.cxx +vtkCylinder.cxx +vtkDataObject.cxx +vtkDataObjectAlgorithm.cxx +vtkDataObjectCollection.cxx +vtkDataObjectSource.cxx +vtkDataSet.cxx +vtkDataSetAlgorithm.cxx +vtkDataSetAttributes.cxx +vtkDataSetCollection.cxx +vtkDataSetSource.cxx +vtkDataSetToDataSetFilter.cxx +vtkDataSetToImageFilter.cxx +vtkDataSetToPolyDataFilter.cxx +vtkDataSetToStructuredGridFilter.cxx +vtkDataSetToStructuredPointsFilter.cxx +vtkDataSetToUnstructuredGridFilter.cxx +vtkDemandDrivenPipeline.cxx +vtkEmptyCell.cxx +vtkExecutive.cxx +vtkExplicitCell.cxx +vtkFieldData.cxx +vtkFilteringInformationKeyManager.cxx +vtkGenericAdaptorCell.cxx +vtkGenericAttribute.cxx +vtkGenericAttributeCollection.cxx +vtkGenericCell.cxx +vtkGenericCellIterator.cxx +vtkGenericCellTessellator.cxx +vtkSimpleCellTessellator.cxx +vtkGenericDataSet.cxx +vtkGenericDataSetAlgorithm.cxx +vtkGenericEdgeTable.cxx +vtkGenericPointIterator.cxx +vtkGenericSubdivisionErrorMetric.cxx +vtkGeometricErrorMetric.cxx +vtkAttributesErrorMetric.cxx +vtkHexagonalPrism.cxx +vtkHexahedron.cxx +vtkHierarchicalBoxDataSet.cxx +vtkHierarchicalDataInformation.cxx +vtkHierarchicalDataIterator.cxx +vtkHierarchicalDataSet.cxx +vtkHierarchicalDataSetAlgorithm.cxx +vtkImageAlgorithm.cxx +vtkImageData.cxx +vtkImageInPlaceFilter.cxx +vtkImageIterator.cxx +vtkImageMultipleInputFilter.cxx +vtkImageMultipleInputOutputFilter.cxx +vtkImageProgressIterator.cxx +vtkImageSource.cxx +vtkImageToImageFilter.cxx +vtkImageToStructuredPoints.cxx +vtkImageTwoInputFilter.cxx +vtkImplicitBoolean.cxx +vtkImplicitDataSet.cxx +vtkImplicitSelectionLoop.cxx +vtkImplicitSum.cxx +vtkImplicitVolume.cxx +vtkImplicitWindowFunction.cxx +vtkInformation.cxx +vtkInformationDataObjectKey.cxx +vtkInformationDoubleKey.cxx +vtkInformationDoubleVectorKey.cxx +vtkInformationExecutivePortKey.cxx +vtkInformationExecutivePortVectorKey.cxx +vtkInformationIdTypeKey.cxx +vtkInformationInformationKey.cxx +vtkInformationInformationVectorKey.cxx +vtkInformationIntegerKey.cxx +vtkInformationIntegerPointerKey.cxx +vtkInformationIntegerVectorKey.cxx +vtkInformationKey.cxx +vtkInformationKeyVectorKey.cxx +vtkInformationObjectBaseKey.cxx +vtkInformationRequestKey.cxx +vtkInformationStringKey.cxx +vtkInformationUnsignedLongKey.cxx +vtkInformationVector.cxx +vtkInterpolatedVelocityField.cxx +vtkKochanekSpline.cxx +vtkLine.cxx +vtkLocator.cxx +vtkMapper2D.cxx +vtkMergePoints.cxx +vtkNonLinearCell.cxx +vtkOrderedTriangulator.cxx +vtkParametricSpline.cxx +vtkPentagonalPrism.cxx +vtkPerlinNoise.cxx +vtkPiecewiseFunction.cxx +vtkPiecewiseFunctionAlgorithm.cxx +vtkPiecewiseFunctionShiftScale.cxx +vtkPixel.cxx +vtkPointData.cxx +vtkPointLocator.cxx +vtkPointSet.cxx +vtkPointSetAlgorithm.cxx +vtkPointSetSource.cxx +vtkPointSetToPointSetFilter.cxx +vtkPolyData.cxx +vtkPolyDataAlgorithm.cxx +vtkPolyDataCollection.cxx +vtkPolyDataSource.cxx +vtkPolyDataToPolyDataFilter.cxx +vtkPolyLine.cxx +vtkPolyVertex.cxx +vtkPolygon.cxx +vtkProcessObject.cxx +vtkPropAssembly.cxx +vtkPyramid.cxx +vtkQuad.cxx +vtkQuadraticEdge.cxx +vtkQuadraticHexahedron.cxx +vtkQuadraticPyramid.cxx +vtkQuadraticQuad.cxx +vtkQuadraticTetra.cxx +vtkQuadraticTriangle.cxx +vtkQuadraticWedge.cxx +vtkRectilinearGrid.cxx +vtkRectilinearGridAlgorithm.cxx +vtkRectilinearGridSource.cxx +vtkRectilinearGridToPolyDataFilter.cxx +vtkScalarTree.cxx +vtkSimpleImageToImageFilter.cxx +vtkSimpleScalarTree.cxx +vtkSmoothErrorMetric.cxx +vtkSphere.cxx +vtkSource.cxx +vtkSpline.cxx +vtkStreamingDemandDrivenPipeline.cxx +vtkStructuredGrid.cxx +vtkStructuredGridAlgorithm.cxx +vtkStructuredGridSource.cxx +vtkStructuredGridToPolyDataFilter.cxx +vtkStructuredGridToStructuredGridFilter.cxx +vtkStructuredPoints.cxx +vtkStructuredPointsCollection.cxx +vtkStructuredPointsSource.cxx +vtkStructuredPointsToPolyDataFilter.cxx +vtkStructuredPointsToStructuredPointsFilter.cxx +vtkStructuredPointsToUnstructuredGridFilter.cxx +vtkSuperquadric.cxx +vtkTetra.cxx +vtkThreadedImageAlgorithm.cxx +vtkTriangle.cxx +vtkTriangleStrip.cxx +vtkTrivialProducer.cxx +vtkUniformGrid.cxx +vtkUnstructuredGrid.cxx +vtkUnstructuredGridAlgorithm.cxx +vtkUnstructuredGridSource.cxx +vtkUnstructuredGridToPolyDataFilter.cxx +vtkUnstructuredGridToUnstructuredGridFilter.cxx +vtkVertex.cxx +vtkViewDependentErrorMetric.cxx +vtkVoxel.cxx +vtkWedge.cxx +vtkViewport.cxx +vtkGenericInterpolatedVelocityField.cxx +) + +SET_SOURCE_FILES_PROPERTIES( +vtkAbstractMapper +vtkCell +vtkCell3D +vtkCompositeDataIterator +vtkCompositeDataSet +vtkDataObjectSource +vtkDataSet +vtkDataSetSource +vtkDataSetToDataSetFilter +vtkDataSetToImageFilter +vtkDataSetToPolyDataFilter +vtkDataSetToStructuredGridFilter +vtkDataSetToStructuredPointsFilter +vtkDataSetToUnstructuredGridFilter +vtkExecutive +vtkExplicitCell +vtkFilteringInformationKeyManager +vtkGenericAdaptorCell +vtkGenericAttribute +vtkGenericCellIterator +vtkGenericCellTessellator +vtkGenericDataSet +vtkGenericDataSetAlgorithm +vtkGenericPointIterator +vtkGenericSubdivisionErrorMetric +vtkHierarchicalDataSetAlgorithm +vtkImageAlgorithm +vtkImageInPlaceFilter +vtkImageIterator +vtkImageMultipleInputFilter +vtkImageMultipleInputOutputFilter +vtkImageProgressIterator +vtkImageSource +vtkImageToImageFilter +vtkImageTwoInputFilter +vtkInformationDataObjectKey +vtkInformationDoubleKey +vtkInformationDoubleVectorKey +vtkInformationExecutivePortKey +vtkInformationExecutivePortVectorKey +vtkInformationIdTypeKey +vtkInformationInformationKey +vtkInformationInformationVectorKey +vtkInformationIntegerKey +vtkInformationIntegerPointerKey +vtkInformationIntegerVectorKey +vtkInformationKey +vtkInformationKeyVectorKey +vtkInformationObjectBaseKey +vtkInformationRequestKey +vtkInformationStringKey +vtkInformationUnsignedLongKey +vtkLocator +vtkMapper2D +vtkNonLinearCell +vtkPointSet +vtkPointSetSource +vtkPointSetToPointSetFilter +vtkPolyDataSource +vtkPolyDataToPolyDataFilter +vtkProcessObject +vtkRectilinearGridSource +vtkRectilinearGridToPolyDataFilter +vtkScalarTree +vtkSimpleImageToImageFilter +vtkSource +vtkSpline +vtkStructuredGridSource +vtkStructuredGridToPolyDataFilter +vtkStructuredGridToStructuredGridFilter +vtkStructuredPointsSource +vtkStructuredPointsToPolyDataFilter +vtkStructuredPointsToStructuredPointsFilter +vtkStructuredPointsToUnstructuredGridFilter +vtkThreadedImageAlgorithm +vtkUnstructuredGridSource +vtkUnstructuredGridToPolyDataFilter +vtkUnstructuredGridToUnstructuredGridFilter +vtkViewport + ABSTRACT +) + +SET_SOURCE_FILES_PROPERTIES( + vtkFilteringInformationKeyManager.cxx + vtkImageIterator.cxx + vtkImageProgressIterator.cxx + WRAP_EXCLUDE +) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- + +IF(CMAKE_COMPILER_IS_GNUCXX AND MINGW) + # MinGW fails to dllexport the explicit instantiations of + # the image iterators, so we must export all symbols. + GET_TARGET_PROPERTY(VTK_FILTERING_LINK_FLAGS vtkFiltering LINK_FLAGS) + IF(VTK_FILTERING_LINK_FLAGS) + SET(VTK_FILTERING_LINK_FLAGS "${VTK_FILTERING_LINK_FLAGS} ") + ELSE(VTK_FILTERING_LINK_FLAGS) + SET(VTK_FILTERING_LINK_FLAGS) + ENDIF(VTK_FILTERING_LINK_FLAGS) + SET_TARGET_PROPERTIES(vtkFiltering PROPERTIES + LINK_FLAGS "${VTK_FILTERING_LINK_FLAGS}-Wl,--export-all-symbols") +ENDIF(CMAKE_COMPILER_IS_GNUCXX AND MINGW) + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtkAMRBox + vtkCellType + ) + + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .txx + vtkImageIterator + vtkImageProgressIterator + ) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Filtering/Testing/CMakeLists.txt b/Filtering/Testing/CMakeLists.txt new file mode 100644 index 0000000..db0d5bc --- /dev/null +++ b/Filtering/Testing/CMakeLists.txt @@ -0,0 +1,32 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Filtering ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Filtering" + VTK_FILTERING_EXPORT + vtkActor2DCollection.h + vtkAMRBox.h + vtkApplyFilterCommandInternal.h + vtkCellType.h + vtkDataSetCollection.h + vtkFilteringInformationKeyManager.h + vtkImageIterator.h + vtkImageProgressIterator.h + vtkMarchingCubesCases.h + vtkMarchingSquaresCases.h + vtkMultiBlockDataSetInternal.h + vtkDataObjectCollection.h + vtkHierarchicalDataSetInternal.h + vtkHierarchicalBoxDataSetInternal.h + vtkStructuredPoints.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/Filtering/Testing/Cxx/CMakeLists.txt b/Filtering/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..1bddc87 --- /dev/null +++ b/Filtering/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,22 @@ +SET(KIT Filtering) +# +# Create a test lists +CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx + quadCellConsistency.cxx + otherColorTransferFunction.cxx + EXTRA_INCLUDE vtkTestDriver.h +) + +ADD_EXECUTABLE(${KIT}CxxTests ${Tests}) +TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkFiltering) + +SET (TestsToRun ${Tests}) +REMOVE (TestsToRun ${KIT}CxxTests.cxx) + +# +# Add all the executables +FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) +ENDFOREACH (test) + diff --git a/Filtering/Testing/Cxx/otherColorTransferFunction.cxx b/Filtering/Testing/Cxx/otherColorTransferFunction.cxx new file mode 100644 index 0000000..543269c --- /dev/null +++ b/Filtering/Testing/Cxx/otherColorTransferFunction.cxx @@ -0,0 +1,152 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherColorTransferFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the ColorTransferFunction + +#include "vtkColorTransferFunction.h" +#include "vtkDebugLeaks.h" + +int Test(ostream& strm) +{ + int i, j, k; + vtkColorTransferFunction *ctf1 = vtkColorTransferFunction::New(); + + // actual test + strm << "Test vtkColorTransferFunction Start" << endl; + + ctf1->AddRGBPoint (0.0, 1, 0, 0); + ctf1->AddHSVPoint (1.0, 1, 1, .6); + ctf1->AddRGBSegment (2.0, 1, 1, 1, 10.0, 0, 0, 0); + ctf1->AddHSVSegment (11.0, 1, 1, 6, 15.0, .1, .2, .3); + strm << *ctf1; + + double rgb[3]; + ctf1->GetColor(.5, rgb); + strm << "GetColor(.5) = " + << rgb[0] << ", " << rgb[1] << ", " << rgb[2] << endl; + + strm << "GetRedValue(.5) = " << ctf1->GetRedValue(.5) << endl; + strm << "GetGreenValue(.5) = " << ctf1->GetGreenValue(.5) << endl; + strm << "GetBlueValue(.5) = " << ctf1->GetBlueValue(.5) << endl; + + strm << "MapValue(12) = " + << (int) ctf1->MapValue(12)[0] << ", " + << (int) ctf1->MapValue(12)[1] << ", " + << (int) ctf1->MapValue(12)[2] << endl; + + strm << "GetRange = " + << ctf1->GetRange()[0] << "," + << ctf1->GetRange()[1] << endl; + + double table[3][256]; + + ctf1->GetTable(0, 15, 256, &table[0][0]); + strm << "GetTable(0, 15, 256, &table[0][0])" << endl; + for (i = 0; i < 256; i++) + { + for (j = 0; j < 3; j++) + { + strm << table[j][i] << " "; + } + strm << endl; + } + + strm << "BuildFunctionFrom(0, 15, 256, &table[0][0])" << endl; + vtkColorTransferFunction *ctf2 = vtkColorTransferFunction::New(); + ctf2->BuildFunctionFromTable(0, 15, 256, &table[0][0]); + + ctf2->SetColorSpaceToRGB(); + ctf2->GetTable(0,15,512); + + ctf2->SetColorSpaceToHSV(); + ctf2->GetTable(0,15,512); + + ctf1->DeepCopy(ctf2); + strm << "ctf1->DeepCopy(ctf2)" << endl; + strm << *ctf1; + + ctf1->RemovePoint (10); + strm << *ctf1; + + ctf1->RemoveAllPoints(); + strm << *ctf1; + + char *cData = new char[128]; + unsigned char *ucData = new unsigned char[128]; + short *sData = new short[128]; + unsigned short *usData = new unsigned short[128]; + int *iData = new int[128]; + unsigned int *uiData = new unsigned int[128]; + long *lData = new long[128]; + unsigned long *ulData = new unsigned long[128]; + float *fData = new float[128]; + double *dData = new double[128]; + + for (k = 0; k < 128; k++) + { + *(cData+k) = static_cast(static_cast(k)/255.0); + *(ucData+k) = static_cast(static_cast(k)/255.0); + *(sData+k) = static_cast(static_cast(k)/255.0); + *(usData+k) = static_cast(static_cast(k)/255.0); + *(iData+k) = static_cast(static_cast(k)/255.0); + *(uiData+k) = static_cast(static_cast(k)/255.0); + *(lData+k) = static_cast(static_cast(k)/255.0); + *(ulData+k) = static_cast(static_cast(k)/255.0); + *(fData+k) = static_cast(static_cast(k)/255.0); + *(dData+k) = static_cast(static_cast(k)/255.0); + } + + unsigned char *ucResult = new unsigned char[128*4]; + for (k = 1; k <= 4; k++) + { + ctf2->MapScalarsThroughTable2((void *) cData, ucResult, VTK_CHAR, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) ucData, ucResult, VTK_UNSIGNED_CHAR, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) sData, ucResult, VTK_SHORT, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) usData, ucResult, VTK_UNSIGNED_SHORT, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) iData, ucResult, VTK_INT, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) uiData, ucResult, VTK_UNSIGNED_INT, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) lData, ucResult, VTK_LONG, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) ulData, ucResult, VTK_UNSIGNED_LONG, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) fData, ucResult, VTK_FLOAT, 128, 1, k); + ctf2->MapScalarsThroughTable2((void *) dData, ucResult, VTK_DOUBLE, 128, 1, k); + } + + ctf1->Delete(); + ctf2->Delete(); + + delete []ucResult; + delete []cData; + delete []ucData; + delete []sData; + delete []usData; + delete []iData; + delete []uiData; + delete []lData; + delete []ulData; + delete []fData; + delete []dData; + + strm << "Test vtkColorTransferFunction End" << endl; + return 0; +} + + +int otherColorTransferFunction(int, char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return Test(vtkmsg_with_warning_C4701); +} diff --git a/Filtering/Testing/Cxx/quadCellConsistency.cxx b/Filtering/Testing/Cxx/quadCellConsistency.cxx new file mode 100644 index 0000000..237b3b2 --- /dev/null +++ b/Filtering/Testing/Cxx/quadCellConsistency.cxx @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: quadCellConsistency.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the consistency of face/edge ids between linear and quadratic cells + +#include "vtkLine.h" +#include "vtkQuadraticEdge.h" +#include "vtkTriangle.h" +#include "vtkQuadraticTriangle.h" +#include "vtkQuad.h" +#include "vtkQuadraticQuad.h" +#include "vtkTetra.h" +#include "vtkQuadraticTetra.h" +#include "vtkHexahedron.h" +#include "vtkQuadraticHexahedron.h" +#include "vtkPyramid.h" +#include "vtkQuadraticPyramid.h" +#include "vtkWedge.h" +#include "vtkQuadraticWedge.h" + +void InitializeCell(vtkCell *cell) +{ + // Default initialize the cell ids to 0,1,2 ... n + int n = cell->GetNumberOfPoints(); + for(int i=0; iGetPointIds()->SetId(i, i); + } +} + +// Check that corner points id match quad ones for each edges +int CompareCellEdges(vtkCell *linear, vtkCell *quadratic) +{ + int dif; + int sum = 0; + int nEdges = linear->GetNumberOfEdges(); + for(int edge = 0; edge < nEdges; edge++) + { + vtkCell *lEdge = linear->GetEdge(edge); + vtkCell *qEdge = quadratic->GetEdge(edge); + + int n = lEdge->GetNumberOfPoints(); + // Check that the points of the linear cell match the one from the quadratic one + for( int i=0; iGetPointIds()->GetId(i) - qEdge->GetPointIds()->GetId(i); + sum += dif; + } + } + return sum; +} + +// Check that corner points id match quad ones for each faces +int CompareCellFaces(vtkCell *linear, vtkCell *quadratic) +{ + int dif; + int sum = 0; + int nFaces = linear->GetNumberOfFaces(); + for(int face = 0; face < nFaces; face++) + { + vtkCell *lFace = linear->GetFace(face); + vtkCell *qFace = quadratic->GetFace(face); + + int n = lFace->GetNumberOfPoints(); + // Check that linear Triangle match quad Tri + if( lFace->GetCellType() == VTK_TRIANGLE ) + sum += (qFace->GetCellType() != VTK_QUADRATIC_TRIANGLE); + // Check that linear Quad match quad Quad + if( lFace->GetCellType() == VTK_QUAD ) + sum += (qFace->GetCellType() != VTK_QUADRATIC_QUAD ); + // Check that the points of the linear cell match the one from the quadratic one + for( int i=0; iGetPointIds()->GetId(i) - qFace->GetPointIds()->GetId(i); + sum += dif; + } + } + return sum; +} + +int quadCellConsistency(int, char *[]) +{ + int ret = 0; + // Line / vtkQuadraticEdge: + vtkLine *edge = vtkLine::New(); + vtkQuadraticEdge *qedge = vtkQuadraticEdge::New(); + + InitializeCell(edge); + InitializeCell(qedge); + ret += CompareCellEdges(edge, qedge); + ret += CompareCellFaces(edge, qedge); + + edge->Delete(); + qedge->Delete(); + + // Triangles: + vtkTriangle *tri = vtkTriangle::New(); + vtkQuadraticTriangle *qtri = vtkQuadraticTriangle::New(); + + InitializeCell(tri); + InitializeCell(qtri); + ret += CompareCellEdges(tri, qtri); + ret += CompareCellFaces(tri, qtri); + + tri->Delete(); + qtri->Delete(); + + // Quad + vtkQuad *quad = vtkQuad::New(); + vtkQuadraticQuad *qquad = vtkQuadraticQuad::New(); + + InitializeCell(quad); + InitializeCell(qquad); + ret += CompareCellEdges(quad, qquad); + ret += CompareCellFaces(quad, qquad); + + quad->Delete(); + qquad->Delete(); + + // Tetra + vtkTetra *tetra = vtkTetra::New(); + vtkQuadraticTetra *qtetra = vtkQuadraticTetra::New(); + + InitializeCell(tetra); + InitializeCell(qtetra); + ret += CompareCellEdges(tetra, qtetra); + ret += CompareCellFaces(tetra, qtetra); + + tetra->Delete(); + qtetra->Delete(); + + // Hexhedron + vtkHexahedron *hex = vtkHexahedron::New(); + vtkQuadraticHexahedron *qhex = vtkQuadraticHexahedron::New(); + + InitializeCell(hex); + InitializeCell(qhex); + ret += CompareCellEdges(hex, qhex); + ret += CompareCellFaces(hex, qhex); + + hex->Delete(); + qhex->Delete(); + + // Pyramid + vtkPyramid *pyr= vtkPyramid::New(); + vtkQuadraticPyramid *qpyr = vtkQuadraticPyramid::New(); + + InitializeCell(pyr); + InitializeCell(qpyr); + ret += CompareCellEdges(pyr, qpyr); + ret += CompareCellFaces(pyr, qpyr); + + pyr->Delete(); + qpyr->Delete(); + + // Wedge cells + vtkWedge *wedge = vtkWedge::New(); + vtkQuadraticWedge *qwedge = vtkQuadraticWedge::New(); + + InitializeCell(wedge); + InitializeCell(qwedge); + ret += CompareCellEdges(wedge, qwedge); + ret += CompareCellFaces(wedge, qwedge); + + wedge->Delete(); + qwedge->Delete(); + + return ret; +} diff --git a/Filtering/Testing/Python/CMakeLists.txt b/Filtering/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..c8ece1f --- /dev/null +++ b/Filtering/Testing/Python/CMakeLists.txt @@ -0,0 +1,22 @@ +INCLUDE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake) +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + IF (VTK_PYTHON_EXE) + SET(tests + closedSplines + CSpline + KSpline + SelectionLoop + ImplicitSum + PerlinNoise + ) + + CONVERT_TCL_TEST_TO_PY ( + tests + Filtering) + ENDIF (VTK_PYTHON_EXE) + ENDIF (VTK_DATA_ROOT) +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) diff --git a/Filtering/Testing/Tcl/CMakeLists.txt b/Filtering/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..ceddb5a --- /dev/null +++ b/Filtering/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,51 @@ +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + FOREACH ( tfile + closedSplines + CSpline + KSpline + SelectionLoop + ImplicitSum + PerlinNoise + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Filtering/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Filtering/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + IF(VTK_USE_TK) + ADD_TEST(squadViewer-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Filtering/Testing/Tcl/squadViewer.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Filtering/squadViewer.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDIF(VTK_USE_TK) + # + # If we do not have the data, still run the tests that we can + # + ELSE (VTK_DATA_ROOT) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + +ADD_TEST(PrintSelf-Filtering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Filtering) + +ADD_TEST(TestSetObjectMacro-Filtering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Filtering/vtk\\\\*.h" + "vtkSetObjectMacro" + ) +ADD_TEST(otherDataSetAttributes ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Filtering/Testing/Tcl/otherDataSetAttributes.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) diff --git a/Filtering/Testing/Tcl/CSpline.tcl b/Filtering/Testing/Tcl/CSpline.tcl new file mode 100644 index 0000000..56d9756 --- /dev/null +++ b/Filtering/Testing/Tcl/CSpline.tcl @@ -0,0 +1,162 @@ +package require vtk +package require vtkinteraction + +# Now create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkMath math +set numberOfInputPoints 30 + +vtkCardinalSpline aSplineX +vtkCardinalSpline aSplineY +vtkCardinalSpline aSplineZ + +# generate random points + +vtkPoints inputPoints +for {set i 0} {$i < $numberOfInputPoints} {incr i 1} { + set x [math Random 0 1] + set y [math Random 0 1] + set z [math Random 0 1] + aSplineX AddPoint $i $x + aSplineY AddPoint $i $y + aSplineZ AddPoint $i $z + inputPoints InsertPoint $i $x $y $z +} + +vtkPolyData inputData + inputData SetPoints inputPoints + +vtkSphereSource balls + balls SetRadius .01 + balls SetPhiResolution 10 + balls SetThetaResolution 10 + +vtkGlyph3D glyphPoints + glyphPoints SetInput inputData + glyphPoints SetSource [balls GetOutput] + +vtkPolyDataMapper glyphMapper + glyphMapper SetInputConnection [glyphPoints GetOutputPort] + +vtkActor glyph + glyph SetMapper glyphMapper + eval [glyph GetProperty] SetDiffuseColor 1 0.4 0.4 + [glyph GetProperty] SetSpecular .3 + [glyph GetProperty] SetSpecularPower 30 + +ren1 AddActor glyph + +# create a polyline +vtkPoints points +vtkPolyData profileData + +set numberOfOutputPoints 400 +set offset 1.0 +proc fit {} { + global numberOfInputPoints numberOfOutputPoints offset + points Reset + for {set i 0} {$i< $numberOfOutputPoints} {incr i 1} { + set t [expr ( $numberOfInputPoints - $offset ) / ( $numberOfOutputPoints - 1) * $i] + points InsertPoint $i [aSplineX Evaluate $t] [aSplineY Evaluate $t] [aSplineZ Evaluate $t] + } + profileData Modified +} +fit + +vtkCellArray lines + lines InsertNextCell $numberOfOutputPoints + +for {set i 0} {$i < $numberOfOutputPoints} {incr i 1} { + lines InsertCellPoint $i +} +profileData SetPoints points +profileData SetLines lines + +vtkTubeFilter profileTubes + profileTubes SetNumberOfSides 8 + profileTubes SetInput profileData + profileTubes SetRadius .005 + +vtkPolyDataMapper profileMapper + profileMapper SetInputConnection [profileTubes GetOutputPort] + +vtkActor profile + profile SetMapper profileMapper + eval [profile GetProperty] SetDiffuseColor 1 1 0.6 + [profile GetProperty] SetSpecular .3 + [profile GetProperty] SetSpecularPower 30 + +ren1 AddActor profile + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCameraClippingRange + +renWin SetSize 400 400 + +# render the image +# +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +proc opened {} { + global offset + + set offset 1.0 + aSplineX ClosedOff + aSplineY ClosedOff + aSplineZ ClosedOff + fit + renWin Render +} + +proc varyLeft {} { + for {set left -1} { $left <= 1 } {set left [expr $left + .05]} { + aSplineX SetLeftValue $left + aSplineY SetLeftValue $left + aSplineZ SetLeftValue $left + fit + renWin Render + } +} + +proc varyRight {} { + for {set right -1} { $right <= 1 } {set right [expr $right + .05]} { + aSplineX SetRightValue $right + aSplineY SetRightValue $right + aSplineZ SetRightValue $right + fit + renWin Render + } +} + +proc constraint {value } { + aSplineX SetLeftConstraint $value + aSplineY SetLeftConstraint $value + aSplineZ SetLeftConstraint $value + aSplineX SetRightConstraint $value + aSplineY SetRightConstraint $value + aSplineZ SetRightConstraint $value +} + +proc closed {} { + global offset + + set offset 0.0 + aSplineX ClosedOn + aSplineY ClosedOn + aSplineZ ClosedOn + fit + renWin Render +} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Filtering/Testing/Tcl/ImplicitSum.tcl b/Filtering/Testing/Tcl/ImplicitSum.tcl new file mode 100644 index 0000000..c81fad4 --- /dev/null +++ b/Filtering/Testing/Tcl/ImplicitSum.tcl @@ -0,0 +1,64 @@ +# This example demonstrates adding two implicit models +# to produce an (unexpected!) result + +# first we load in the standard vtk packages into tcl +package require vtk +package require vtkinteraction +package require vtktesting + +vtkCone geomObject1 + +vtkSphere geomObject2 + geomObject2 SetRadius 0.5 + geomObject2 SetCenter 0.5 0 0 + +vtkImplicitSum sum + sum SetNormalizeByWeight 1 + sum AddFunction geomObject1 2 + sum AddFunction geomObject2 1 + +vtkSampleFunction sample + sample SetImplicitFunction sum + sample SetSampleDimensions 60 60 60 + sample ComputeNormalsOn + +vtkContourFilter surface + surface SetInputConnection [sample GetOutputPort] + surface SetValue 0 0.0 + +vtkPolyDataMapper mapper + mapper SetInputConnection [surface GetOutputPort] + mapper ScalarVisibilityOff +vtkActor actor + actor SetMapper mapper + eval [actor GetProperty] SetDiffuseColor 0.2 0.4 0.6 + eval [actor GetProperty] SetSpecular 0.4 + eval [actor GetProperty] SetDiffuse 0.7 + eval [actor GetProperty] SetSpecularPower 40 + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 60 +[ren1 GetActiveCamera] Elevation -10 +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCameraClippingRange +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + diff --git a/Filtering/Testing/Tcl/KSpline.tcl b/Filtering/Testing/Tcl/KSpline.tcl new file mode 100644 index 0000000..ecb7b91 --- /dev/null +++ b/Filtering/Testing/Tcl/KSpline.tcl @@ -0,0 +1,189 @@ +package require vtk +package require vtkinteraction + +# Now create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkMath math +set numberOfInputPoints 30 + +vtkKochanekSpline aSplineX +vtkKochanekSpline aSplineY +vtkKochanekSpline aSplineZ + +# generate random points +vtkPoints inputPoints +for {set i 0} {$i<$numberOfInputPoints} {incr i 1} { + set x [math Random 0 1] + set y [math Random 0 1] + set z [math Random 0 1] + aSplineX AddPoint $i $x + aSplineY AddPoint $i $y + aSplineZ AddPoint $i $z + inputPoints InsertPoint $i $x $y $z +} + +vtkPolyData inputData + inputData SetPoints inputPoints + +vtkSphereSource balls + balls SetRadius .01 + balls SetPhiResolution 10 + balls SetThetaResolution 10 + +vtkGlyph3D glyphPoints + glyphPoints SetInput inputData + glyphPoints SetSource [balls GetOutput] + +vtkPolyDataMapper glyphMapper + glyphMapper SetInputConnection [glyphPoints GetOutputPort] + +vtkActor glyph + glyph SetMapper glyphMapper +eval [glyph GetProperty] SetDiffuseColor 1 0.6 0.6 + [glyph GetProperty] SetSpecular .3 + [glyph GetProperty] SetSpecularPower 30 + +ren1 AddActor glyph + + +vtkPoints points +# create a line +set tension 0 +set bias 0 +set continuity 0 + aSplineX SetDefaultTension $tension + aSplineX SetDefaultBias $bias + aSplineX SetDefaultContinuity $continuity + aSplineY SetDefaultTension $tension + aSplineY SetDefaultBias $bias + aSplineY SetDefaultContinuity $continuity + aSplineZ SetDefaultTension $tension + aSplineZ SetDefaultBias $bias + aSplineZ SetDefaultContinuity $continuity + +vtkPolyData profileData +set numberOfOutputPoints 300 +set offset 1.0 +proc fit {} { + global numberOfInputPoints numberOfOutputPoints offset + points Reset + for {set i 0} {$i< $numberOfOutputPoints} {incr i 1} { + set t [expr ( $numberOfInputPoints - $offset ) / ($numberOfOutputPoints - 1) * $i] + points InsertPoint $i [aSplineX Evaluate $t] [aSplineY Evaluate $t] [aSplineZ Evaluate $t] + } + profileData Modified +} +fit + +vtkCellArray lines + lines InsertNextCell $numberOfOutputPoints + +for {set i 0} {$i< $numberOfOutputPoints} {incr i 1} { + lines InsertCellPoint $i +} + +profileData SetPoints points +profileData SetLines lines + + +vtkTubeFilter profileTubes + profileTubes SetNumberOfSides 8 + profileTubes SetInput profileData + profileTubes SetRadius .005 + +vtkPolyDataMapper profileMapper +profileMapper SetInputConnection [profileTubes GetOutputPort] + +vtkActor profile + profile SetMapper profileMapper +eval [profile GetProperty] SetDiffuseColor 1 1 0.7 + [profile GetProperty] SetSpecular .3 + [profile GetProperty] SetSpecularPower 30 + +ren1 AddActor profile +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCamera +ren1 ResetCameraClippingRange +renWin SetSize 400 400 + +# render the image +# +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +proc defaults {} { + aSplineX SetDefaultBias 0 + aSplineX SetDefaultTension 0 + aSplineX SetDefaultContinuity 0 + aSplineY SetDefaultBias 0 + aSplineY SetDefaultTension 0 + aSplineY SetDefaultContinuity 0 + aSplineZ SetDefaultBias 0 + aSplineZ SetDefaultTension 0 + aSplineZ SetDefaultContinuity 0 + fit + renWin Render +} +proc varyBias {} { + defaults + for {set bias -1} { $bias <= 1 } {set bias [expr $bias + .05]} { + aSplineX SetDefaultBias $bias + aSplineY SetDefaultBias $bias + aSplineZ SetDefaultBias $bias + fit + renWin Render + } +} +proc varyTension {} { + defaults + for {set tension -1} { $tension <= 1 } {set tension [expr $tension + .05]} { + aSplineX SetDefaultTension $tension + aSplineY SetDefaultTension $tension + aSplineZ SetDefaultTension $tension + fit + renWin Render + } +} +proc varyContinuity {} { + defaults + for {set Continuity -1} { $Continuity <= 1 } {set Continuity [expr $Continuity + .05]} { + aSplineX SetDefaultContinuity $Continuity + aSplineY SetDefaultContinuity $Continuity + aSplineZ SetDefaultContinuity $Continuity + fit + renWin Render + } +} + +proc closed {} { + global offset + + set offset 0.0 + aSplineX ClosedOn + aSplineY ClosedOn + aSplineZ ClosedOn + fit + renWin Render +} + +proc opened {} { + global offset + + set offset 1.0 + aSplineX ClosedOff + aSplineY ClosedOff + aSplineZ ClosedOff + fit + renWin Render +} + + diff --git a/Filtering/Testing/Tcl/PerlinNoise.tcl b/Filtering/Testing/Tcl/PerlinNoise.tcl new file mode 100644 index 0000000..f1ac3e4 --- /dev/null +++ b/Filtering/Testing/Tcl/PerlinNoise.tcl @@ -0,0 +1,49 @@ +# A simple example of a three-dimensional noise pattern. + +# first we load in the standard vtk packages into tcl +package require vtk +package require vtkinteraction +package require vtktesting + +vtkPerlinNoise perlin +perlin SetFrequency 2 1.25 1.5 +perlin SetPhase 0 0 0 + +vtkSampleFunction sample + sample SetImplicitFunction perlin + sample SetSampleDimensions 65 65 20 + sample ComputeNormalsOff +vtkContourFilter surface + surface SetInputConnection [sample GetOutputPort] + surface SetValue 0 0.0 + +vtkPolyDataMapper mapper + mapper SetInputConnection [surface GetOutputPort] + mapper ScalarVisibilityOff +vtkActor actor + actor SetMapper mapper + eval [actor GetProperty] SetColor 0.2 0.4 0.6 + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.35 +ren1 ResetCameraClippingRange +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Filtering/Testing/Tcl/SelectionLoop.tcl b/Filtering/Testing/Tcl/SelectionLoop.tcl new file mode 100644 index 0000000..67c1a7e --- /dev/null +++ b/Filtering/Testing/Tcl/SelectionLoop.tcl @@ -0,0 +1,68 @@ +package require vtk +package require vtktesting + +# +# Demonstrate the use of implicit selection loop as well as closest point +# connectivity +# + +# create pipeline +# +vtkSphereSource sphere + sphere SetRadius 1 + sphere SetPhiResolution 100 + sphere SetThetaResolution 100 +vtkPoints selectionPoints + selectionPoints InsertPoint 0 0.07325 0.8417 0.5612 + selectionPoints InsertPoint 1 0.07244 0.6568 0.7450 + selectionPoints InsertPoint 2 0.1727 0.4597 0.8850 + selectionPoints InsertPoint 3 0.3265 0.6054 0.7309 + selectionPoints InsertPoint 4 0.5722 0.5848 0.5927 + selectionPoints InsertPoint 5 0.4305 0.8138 0.4189 +vtkImplicitSelectionLoop loop + loop SetLoop selectionPoints +vtkExtractGeometry extract + extract SetInputConnection [sphere GetOutputPort] + extract SetImplicitFunction loop +vtkConnectivityFilter connect + connect SetInputConnection [extract GetOutputPort] + connect SetExtractionModeToClosestPointRegion + eval connect SetClosestPoint [selectionPoints GetPoint 0] +vtkDataSetMapper clipMapper + clipMapper SetInputConnection [connect GetOutputPort] +vtkProperty backProp + eval backProp SetDiffuseColor $tomato +vtkActor clipActor + clipActor SetMapper clipMapper + eval [clipActor GetProperty] SetColor $peacock + clipActor SetBackfaceProperty backProp + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor clipActor +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +renWin SetSize 400 400 +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Filtering/Testing/Tcl/closedSplines.tcl b/Filtering/Testing/Tcl/closedSplines.tcl new file mode 100644 index 0000000..ca5badc --- /dev/null +++ b/Filtering/Testing/Tcl/closedSplines.tcl @@ -0,0 +1,240 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# get the interactor ui + +# Now create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkMath math +set numberOfInputPoints 30 + +vtkKochanekSpline aKSplineX + aKSplineX ClosedOn +vtkKochanekSpline aKSplineY + aKSplineY ClosedOn +vtkKochanekSpline aKSplineZ + aKSplineZ ClosedOn + +vtkCardinalSpline aCSplineX + aCSplineX ClosedOn +vtkCardinalSpline aCSplineY + aCSplineY ClosedOn +vtkCardinalSpline aCSplineZ + aCSplineZ ClosedOn + +# add some points +vtkPoints inputPoints +set x -1.0; set y -1.0; set z 0.0 +aKSplineX AddPoint 0 $x +aKSplineY AddPoint 0 $y +aKSplineZ AddPoint 0 $z +aCSplineX AddPoint 0 $x +aCSplineY AddPoint 0 $y +aCSplineZ AddPoint 0 $z +inputPoints InsertPoint 0 $x $y $z + +set x 1.0; set y -1.0; set z 0.0 +aKSplineX AddPoint 1 $x +aKSplineY AddPoint 1 $y +aKSplineZ AddPoint 1 $z +aCSplineX AddPoint 1 $x +aCSplineY AddPoint 1 $y +aCSplineZ AddPoint 1 $z +inputPoints InsertPoint 1 $x $y $z + +set x 1.0; set y 1.0; set z 0.0 +aKSplineX AddPoint 2 $x +aKSplineY AddPoint 2 $y +aKSplineZ AddPoint 2 $z +aCSplineX AddPoint 2 $x +aCSplineY AddPoint 2 $y +aCSplineZ AddPoint 2 $z +inputPoints InsertPoint 2 $x $y $z + +set x -1.0; set y 1.0; set z 0.0 +aKSplineX AddPoint 3 $x +aKSplineY AddPoint 3 $y +aKSplineZ AddPoint 3 $z +aCSplineX AddPoint 3 $x +aCSplineY AddPoint 3 $y +aCSplineZ AddPoint 3 $z +inputPoints InsertPoint 3 $x $y $z + +vtkPolyData inputData + inputData SetPoints inputPoints + +vtkSphereSource balls + balls SetRadius .04 + balls SetPhiResolution 10 + balls SetThetaResolution 10 + +vtkGlyph3D glyphPoints + glyphPoints SetInput inputData + glyphPoints SetSource [balls GetOutput] + +vtkPolyDataMapper glyphMapper + glyphMapper SetInputConnection [glyphPoints GetOutputPort] + +vtkActor glyph + glyph SetMapper glyphMapper +eval [glyph GetProperty] SetDiffuseColor $tomato + [glyph GetProperty] SetSpecular .3 + [glyph GetProperty] SetSpecularPower 30 + +ren1 AddActor glyph + + +vtkPoints Kpoints +vtkPoints Cpoints + +vtkPolyData profileKData +vtkPolyData profileCData +set numberOfInputPoints 5 +set numberOfOutputPoints 100 +set offset 1.0 +proc fit {} { + global numberOfInputPoints numberOfOutputPoints offset + Kpoints Reset + Cpoints Reset + for {set i 0} {$i< $numberOfOutputPoints} {incr i 1} { + set t [expr ( $numberOfInputPoints - $offset ) / ($numberOfOutputPoints - 1) * $i] + Kpoints InsertPoint $i [aKSplineX Evaluate $t] [aKSplineY Evaluate $t] [aKSplineZ Evaluate $t] + Cpoints InsertPoint $i [aCSplineX Evaluate $t] [aCSplineY Evaluate $t] [aCSplineZ Evaluate $t] + } + profileKData Modified + profileCData Modified +} +fit + +vtkCellArray lines + lines InsertNextCell $numberOfOutputPoints + +for {set i 0} {$i< $numberOfOutputPoints} {incr i 1} { + lines InsertCellPoint $i +} + +profileKData SetPoints Kpoints +profileKData SetLines lines +profileCData SetPoints Cpoints +profileCData SetLines lines + + +vtkTubeFilter profileKTubes + profileKTubes SetNumberOfSides 8 + profileKTubes SetInput profileKData + profileKTubes SetRadius .01 + +vtkPolyDataMapper profileKMapper +profileKMapper SetInputConnection [profileKTubes GetOutputPort] + +vtkActor profileK + profileK SetMapper profileKMapper +eval [profileK GetProperty] SetDiffuseColor $banana + [profileK GetProperty] SetSpecular .3 + [profileK GetProperty] SetSpecularPower 30 + +ren1 AddActor profileK + +vtkTubeFilter profileCTubes + profileCTubes SetNumberOfSides 8 + profileCTubes SetInput profileCData + profileCTubes SetRadius .01 + +vtkPolyDataMapper profileCMapper +profileCMapper SetInputConnection [profileCTubes GetOutputPort] + +vtkActor profileC + profileC SetMapper profileCMapper +eval [profileC GetProperty] SetDiffuseColor $peacock + [profileC GetProperty] SetSpecular .3 + [profileC GetProperty] SetSpecularPower 30 + +ren1 AddActor profileC +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCameraClippingRange + +renWin SetSize 300 300 + +# render the image +# +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +proc defaults {} { + aSplineX SetDefaultBias 0 + aSplineX SetDefaultTension 0 + aSplineX SetDefaultContinuity 0 + aSplineY SetDefaultBias 0 + aSplineY SetDefaultTension 0 + aSplineY SetDefaultContinuity 0 + aSplineZ SetDefaultBias 0 + aSplineZ SetDefaultTension 0 + aSplineZ SetDefaultContinuity 0 + fit + renWin Render +} +proc varyBias {} { + defaults + for {set bias -1} { $bias <= 1 } {set bias [expr $bias + .05]} { + aSplineX SetDefaultBias $bias + aSplineY SetDefaultBias $bias + aSplineZ SetDefaultBias $bias + fit + renWin Render + } +} +proc varyTension {} { + defaults + for {set tension -1} { $tension <= 1 } {set tension [expr $tension + .05]} { + aSplineX SetDefaultTension $tension + aSplineY SetDefaultTension $tension + aSplineZ SetDefaultTension $tension + fit + renWin Render + } +} +proc varyContinuity {} { + defaults + for {set Continuity -1} { $Continuity <= 1 } {set Continuity [expr $Continuity + .05]} { + aSplineX SetDefaultContinuity $Continuity + aSplineY SetDefaultContinuity $Continuity + aSplineZ SetDefaultContinuity $Continuity + fit + renWin Render + } +} + +proc closed {} { + global offset + + set offset 0.0 + aSplineX ClosedOn + aSplineY ClosedOn + aSplineZ ClosedOn + fit + renWin Render +} + +proc opened {} { + global offset + + set offset 1.0 + aSplineX ClosedOff + aSplineY ClosedOff + aSplineZ ClosedOff + fit + renWin Render +} + + diff --git a/Filtering/Testing/Tcl/otherDataSetAttributes.tcl b/Filtering/Testing/Tcl/otherDataSetAttributes.tcl new file mode 100644 index 0000000..40cd281 --- /dev/null +++ b/Filtering/Testing/Tcl/otherDataSetAttributes.tcl @@ -0,0 +1,75 @@ +for {set i 0} {$i < [expr $argc - 1]} {incr i} { + if {[lindex $argv $i] == "-A"} { + set auto_path "$auto_path [lindex $argv [expr $i +1]]" + } +} + +package require vtk + +vtkDataSetAttributes dsa + +foreach array "Bit Char Double Float Int Long Short UnsignedChar UnsignedInt UnsignedLong UnsignedShort" { + + vtk${array}Array a${array}Array + a${array}Array Allocate 1 1 + a${array}Array SetNumberOfComponents 3 + a${array}Array SetNumberOfTuples 4 + a${array}Array SetName a${array}Array + + # SetComponent + set k 0 + for {set i 0} {$i < [a${array}Array GetNumberOfTuples]} {incr i} { + for {set j 0} {$j < [a${array}Array GetNumberOfComponents]} {incr j} { + a${array}Array SetComponent $i $j 1 + incr k + } + } + + dsa AddArray a${array}Array + a${array}Array Delete +} + +foreach attribute "Scalars Vectors Normals TCoords" { + dsa SetActive${attribute} aFloatArray + dsa Get${attribute} aFloatArray + dsa Get${attribute} foo +} + +vtkFloatArray aFloatTensors +aFloatTensors Allocate 1 1 +aFloatTensors SetNumberOfComponents 9 +aFloatTensors SetNumberOfTuples 4 +aFloatTensors SetName aFloatTensors +for {set i 0} {$i < [aFloatTensors GetNumberOfTuples]} {incr i} { + for {set j 0} {$j < [aFloatTensors GetNumberOfComponents]} {incr j} { + aFloatTensors SetComponent $i $j 1 + incr k + } +} +dsa AddArray aFloatTensors +aFloatTensors Delete +dsa SetActiveTensors aFloatTensors +dsa GetTensors aFloatTensors +dsa GetTensors foo + +dsa RemoveArray aFloatArray + +vtkDataSetAttributes dsa2 +dsa2 CopyAllocate dsa 4 4 +dsa2 CopyData dsa 0 0 +dsa2 Delete + +vtkDataSetAttributes dsa3 +dsa3 InterpolateAllocate dsa 4 4 +dsa3 InterpolateEdge dsa 0 0 1 0.5 + +vtkDataSetAttributes dsa4 +dsa4 InterpolateAllocate dsa 4 4 +dsa4 InterpolateTime dsa dsa3 0 0.5 +dsa4 Delete + +dsa3 Delete + + +dsa Delete +exit diff --git a/Filtering/Testing/Tcl/squadViewer.tcl b/Filtering/Testing/Tcl/squadViewer.tcl new file mode 100644 index 0000000..a1a5cf9 --- /dev/null +++ b/Filtering/Testing/Tcl/squadViewer.tcl @@ -0,0 +1,136 @@ +package require vtk +package require vtkinteraction + +set root [toplevel .top -visual {truecolor 24}] +wm title .top "superquadric viewer" +wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit + +# create render window +vtkRenderWindow renWin +set ren [vtkTkRenderWidget $root.ren -width 550 -height 450 -rw renWin] +::vtk::bind_tk_render_widget $ren + +# create parameter sliders +set prs [scale $root.prs -from 0 -to 3.5 -res 0.1 -orient horizontal \ + -label "phi roundness"] + +set trs [scale $root.trs -from 0 -to 3.5 -res 0.1 -orient horizontal \ + -label "theta roundness"] + +set thicks [scale $root.thicks -from 0.01 -to 1 -res 0.01 -orient horizontal \ + -label "thickness"] + +set rframe [frame $root.rframe] +set torbut [checkbutton $rframe.torbut -text "Toroid" -variable toroid] +set texbut [checkbutton $rframe.texbut -text "Texture" -variable doTexture] + +grid $ren - -sticky news +grid $rframe $thicks -sticky news -padx 10 -ipady 5 +grid $rframe -sticky news +grid $prs $trs -sticky news -padx 10 -ipady 5 +pack $torbut $texbut -padx 10 -pady 5 -ipadx 20 -ipady 5 -side right -anchor s +pack propagate $rframe no + +set renWin1 [$ren GetRenderWindow] + +# create pipeline +vtkSuperquadricSource squad +squad SetPhiResolution 20 +squad SetThetaResolution 25 + +vtkPNMReader pnmReader + pnmReader SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" +vtkTexture atext + atext SetInputConnection [pnmReader GetOutputPort] + atext InterpolateOn + +vtkAppendPolyData appendSquads + appendSquads AddInput [squad GetOutput] + +vtkPolyDataMapper mapper + mapper SetInputConnection [squad GetOutputPort] + mapper ScalarVisibilityOff +vtkActor actor + actor SetMapper mapper + actor SetTexture atext + eval [actor GetProperty] SetDiffuseColor 0.5 0.8 0.8 + eval [actor GetProperty] SetAmbient 0.2 + eval [actor GetProperty] SetAmbientColor 0.2 0.2 0.2 + + +proc setTexture {actor texture win} { + global doTexture + if $doTexture { + $actor SetTexture $texture + } else { + $actor SetTexture {} + } + $win Render +} + +proc setPhi {squad win phi} { + $squad SetPhiRoundness $phi + $win Render +} + +proc setTheta {squad win theta} { + $squad SetThetaRoundness $theta + $win Render +} + +proc setThickness {squad win thickness} { + $squad SetThickness $thickness + $win Render +} + +proc setToroid {squad scale win} { + global toroid + $squad SetToroidal $toroid + if {$toroid} { + $scale config -state normal -fg black + } else { + $scale config -state disabled -fg gray + } + $win Render +} + +$prs set 1.0 +$trs set 0.7 +$thicks set 0.3 +set toroid 1 +set doTexture 0 + +squad SetPhiRoundness [$prs get] +squad SetThetaRoundness [$trs get] +squad SetToroidal $toroid +squad SetThickness [$thicks get] +squad SetScale 1 1 1 +setTexture actor atext $renWin1 + +# Create renderer stuff +# +vtkRenderer ren1 +ren1 SetAmbient 1 1 1 +$renWin1 AddRenderer ren1 + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground 0.25 0.2 0.2 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.2 +[ren1 GetActiveCamera] Elevation 40 +[ren1 GetActiveCamera] Azimuth -20 + +# prevent the tk window from showing up then start the event loop +wm withdraw . +update + +$prs config -command "setPhi squad $renWin1" +$trs config -command "setTheta squad $renWin1" +$thicks config -command "setThickness squad $renWin1" +$torbut config -command "setToroid squad $thicks $renWin1" +$texbut config -command "setTexture actor atext $renWin1" + + diff --git a/Filtering/vtkAMRBox.h b/Filtering/vtkAMRBox.h new file mode 100644 index 0000000..d78b128 --- /dev/null +++ b/Filtering/vtkAMRBox.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAMRBox.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAMRBox - represents a 3D uniform region in space +// .SECTION Description +// vtkAMRBox is similar to Chombo's Box. It represents a 3D +// region by storing indices for two corners (LoCorner, HiCorner). +// A few utility methods are provided. + +#ifndef __vtkAMRBox_h +#define __vtkAMRBox_h + +#include "vtkObject.h" + +class VTK_FILTERING_EXPORT vtkAMRBox +{ +public: + // public for quick access + int LoCorner[3]; + int HiCorner[3]; + + vtkAMRBox() + { + for(int i=0; i<3; i++) + { + this->LoCorner[i] = this->HiCorner[i] = 0; + } + } + + vtkAMRBox(int dimensionality, int* loCorner, int* hiCorner) + { + this->LoCorner[2] = this->HiCorner[2] = 0; + memcpy(this->LoCorner, loCorner, dimensionality*sizeof(int)); + memcpy(this->HiCorner, hiCorner, dimensionality*sizeof(int)); + } + + // Description: + // Returns the number of cells (aka elements, zones etc.) in + // the given region (for the specified refinement, see Coarsen() + // and Refine() ). + vtkIdType GetNumberOfCells() + { + vtkIdType numCells=1; + for(int i=0; i<3; i++) + { + numCells *= HiCorner[i] - LoCorner[i] + 1; + } + return numCells; + } + + // Description: + // Modify LoCorner and HiCorner by coarsening with the given + // refinement ratio. + void Coarsen(int refinement) + { + for (int i=0; i<3; i++) + { + this->LoCorner[i] = + ( this->LoCorner[i] < 0 ? + -abs(this->LoCorner[i]+1)/refinement - 1 : + this->LoCorner[i]/refinement ); + this->HiCorner[i] = + ( this->HiCorner[i] < 0 ? + -abs(this->HiCorner[i]+1)/refinement - 1 : + this->HiCorner[i]/refinement ); + } + } + + // Description: + // Modify LoCorner and HiCorner by refining with the given + // refinement ratio. + void Refine(int refinement) + { + for (int i=0; i<3; i++) + { + this->LoCorner[i] = this->LoCorner[i]*refinement; + this->HiCorner[i] = this->HiCorner[i]*refinement; + } + } + + // Description: + // Returns non-zero if the box contains the cell with + // given indices. + int DoesContainCell(int i, int j, int k) + { + return + i >= this->LoCorner[0] && i <= this->HiCorner[0] && + j >= this->LoCorner[1] && j <= this->HiCorner[1] && + k >= this->LoCorner[2] && k <= this->HiCorner[2]; + } + +}; + +#endif + + + + + + diff --git a/Filtering/vtkAbstractMapper.cxx b/Filtering/vtkAbstractMapper.cxx new file mode 100644 index 0000000..aa2f0c4 --- /dev/null +++ b/Filtering/vtkAbstractMapper.cxx @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAbstractMapper.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkObjectFactory.h" +#include "vtkPlaneCollection.h" +#include "vtkPlanes.h" +#include "vtkPointData.h" +#include "vtkTimerLog.h" + +vtkCxxRevisionMacro(vtkAbstractMapper, "$Revision: 1.4.4.1 $"); + +vtkCxxSetObjectMacro(vtkAbstractMapper,ClippingPlanes,vtkPlaneCollection); + + +// Construct object. +vtkAbstractMapper::vtkAbstractMapper() +{ + this->TimeToDraw = 0.0; + this->LastWindow = NULL; + this->ClippingPlanes = NULL; + this->Timer = vtkTimerLog::New(); + this->SetNumberOfOutputPorts(0); + this->SetNumberOfInputPorts(1); +} + +vtkAbstractMapper::~vtkAbstractMapper() +{ + this->Timer->Delete(); + if (this->ClippingPlanes) + { + this->ClippingPlanes->UnRegister(this); + } +} + +// Description: +// Override Modifiedtime as we have added Clipping planes +unsigned long vtkAbstractMapper::GetMTime() +{ + unsigned long mTime = this->Superclass::GetMTime(); + unsigned long clipMTime; + + if ( this->ClippingPlanes != NULL ) + { + clipMTime = this->ClippingPlanes->GetMTime(); + mTime = ( clipMTime > mTime ? clipMTime : mTime ); + } + + return mTime; +} + +void vtkAbstractMapper::AddClippingPlane(vtkPlane *plane) +{ + if (this->ClippingPlanes == NULL) + { + this->ClippingPlanes = vtkPlaneCollection::New(); + this->ClippingPlanes->Register(this); + this->ClippingPlanes->Delete(); + } + + this->ClippingPlanes->AddItem(plane); + this->Modified(); +} + +void vtkAbstractMapper::RemoveClippingPlane(vtkPlane *plane) +{ + if (this->ClippingPlanes == NULL) + { + vtkErrorMacro(<< "Cannot remove clipping plane: mapper has none"); + } + this->ClippingPlanes->RemoveItem(plane); + this->Modified(); +} + +void vtkAbstractMapper::RemoveAllClippingPlanes() +{ + if ( this->ClippingPlanes ) + { + this->ClippingPlanes->RemoveAllItems(); + } +} + +void vtkAbstractMapper::SetClippingPlanes(vtkPlanes *planes) +{ + vtkPlane *plane; + if (!planes) + { + return; + } + + int numPlanes = planes->GetNumberOfPlanes(); + + this->RemoveAllClippingPlanes(); + for (int i=0; iGetPlane(i, plane); + this->AddClippingPlane(plane); + plane->Delete(); + } +} + +vtkDataArray *vtkAbstractMapper::GetScalars(vtkDataSet *input, + int scalarMode, + int arrayAccessMode, + int arrayId, + const char *arrayName, + int& cellFlag) +{ + vtkDataArray *scalars=NULL; + vtkPointData *pd; + vtkCellData *cd; + vtkFieldData *fd; + + // make sure we have an input + if ( !input ) + { + return NULL; + } + + // get and scalar data according to scalar mode + if ( scalarMode == VTK_SCALAR_MODE_DEFAULT ) + { + scalars = input->GetPointData()->GetScalars(); + cellFlag = 0; + if (!scalars) + { + scalars = input->GetCellData()->GetScalars(); + cellFlag = 1; + } + } + else if ( scalarMode == VTK_SCALAR_MODE_USE_POINT_DATA ) + { + scalars = input->GetPointData()->GetScalars(); + cellFlag = 0; + } + else if ( scalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ) + { + scalars = input->GetCellData()->GetScalars(); + cellFlag = 1; + } + else if ( scalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA ) + { + pd = input->GetPointData(); + if (arrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + scalars = pd->GetArray(arrayId); + } + else + { + scalars = pd->GetArray(arrayName); + } + cellFlag = 0; + } + else if ( scalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + cd = input->GetCellData(); + if (arrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + scalars = cd->GetArray(arrayId); + } + else + { + scalars = cd->GetArray(arrayName); + } + cellFlag = 1; + } + else if ( scalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA ) + { + fd = input->GetFieldData(); + if (arrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + scalars = fd->GetArray(arrayId); + } + else + { + scalars = fd->GetArray(arrayName); + } + cellFlag = 1; + } + + return scalars; +} + + +// Shallow copy of vtkProp. +void vtkAbstractMapper::ShallowCopy(vtkAbstractMapper *mapper) +{ + this->SetClippingPlanes( mapper->GetClippingPlanes() ); +} + +void vtkAbstractMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "TimeToDraw: " << this->TimeToDraw << "\n"; + + if ( this->ClippingPlanes ) + { + os << indent << "ClippingPlanes:\n"; + this->ClippingPlanes->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "ClippingPlanes: (none)\n"; + } +} + + diff --git a/Filtering/vtkAbstractMapper.h b/Filtering/vtkAbstractMapper.h new file mode 100644 index 0000000..42a6788 --- /dev/null +++ b/Filtering/vtkAbstractMapper.h @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAbstractMapper - abstract class specifies interface to map data +// .SECTION Description +// vtkAbstractMapper is an abstract class to specify interface between data and +// graphics primitives or software rendering techniques. Subclasses of +// vtkAbstractMapper can be used for rendering 2D data, geometry, or volumetric +// data. +// +// .SECTION See Also +// vtkAbstractMapper3D vtkMapper vtkPolyDataMapper vtkVolumeMapper + +#ifndef __vtkAbstractMapper_h +#define __vtkAbstractMapper_h + +#include "vtkAlgorithm.h" + +#define VTK_SCALAR_MODE_DEFAULT 0 +#define VTK_SCALAR_MODE_USE_POINT_DATA 1 +#define VTK_SCALAR_MODE_USE_CELL_DATA 2 +#define VTK_SCALAR_MODE_USE_POINT_FIELD_DATA 3 +#define VTK_SCALAR_MODE_USE_CELL_FIELD_DATA 4 +#define VTK_SCALAR_MODE_USE_FIELD_DATA 5 + +#define VTK_GET_ARRAY_BY_ID 0 +#define VTK_GET_ARRAY_BY_NAME 1 + +class vtkDataArray; +class vtkDataSet; +class vtkPlane; +class vtkPlaneCollection; +class vtkPlanes; +class vtkTimerLog; +class vtkWindow; + +class VTK_FILTERING_EXPORT vtkAbstractMapper : public vtkAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkAbstractMapper,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Override Modifiedtime as we have added Clipping planes + virtual unsigned long GetMTime(); + + // Description: + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *) {}; + + // Description: + // Get the time required to draw the geometry last time it was rendered + vtkGetMacro( TimeToDraw, double ); + + // Description: + // Specify clipping planes to be applied when the data is mapped + // (at most 6 clipping planes can be specified). + void AddClippingPlane(vtkPlane *plane); + void RemoveClippingPlane(vtkPlane *plane); + void RemoveAllClippingPlanes(); + + // Description: + // Get/Set the vtkPlaneCollection which specifies the + // clipping planes. + virtual void SetClippingPlanes(vtkPlaneCollection*); + vtkGetObjectMacro(ClippingPlanes,vtkPlaneCollection); + + // Description: + // An alternative way to set clipping planes: use up to six planes found + // in the supplied instance of the implicit function vtkPlanes. + void SetClippingPlanes(vtkPlanes *planes); + + // Description: + // Make a shallow copy of this mapper. + void ShallowCopy(vtkAbstractMapper *m); + + // Description: + // Internal helper function for getting the active scalars. The scalar + // mode indicates where the scalars come from. The cellFlag is a + // return value that is set when the scalars actually are cell scalars. + // the arrayAccessMode is used to indicate how to retrieve the scalars from + // field data (if the scalarMode indicates that). The component is used to + // indicate which component in the data array to use as the scalars. + static vtkDataArray *GetScalars(vtkDataSet *input, int scalarMode, + int arrayAccessMode, int arrayId, + const char *arrayName, int& cellFlag); + +protected: + vtkAbstractMapper(); + ~vtkAbstractMapper(); + + vtkTimerLog *Timer; + double TimeToDraw; + vtkWindow *LastWindow; // Window used for the previous render + vtkPlaneCollection *ClippingPlanes; + +private: + vtkAbstractMapper(const vtkAbstractMapper&); // Not implemented. + void operator=(const vtkAbstractMapper&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkActor2D.cxx b/Filtering/vtkActor2D.cxx new file mode 100644 index 0000000..fbb452b --- /dev/null +++ b/Filtering/vtkActor2D.cxx @@ -0,0 +1,283 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActor2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor2D.h" + +#include "vtkProperty2D.h" +#include "vtkMapper2D.h" +#include "vtkPropCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkActor2D, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkActor2D); + +vtkCxxSetObjectMacro(vtkActor2D,Property, vtkProperty2D); + +// Creates an actor2D with the following defaults: +// position -1, -1 (view coordinates) +// orientation 0, scale (1,1), layer 0, visibility on +vtkActor2D::vtkActor2D() +{ + this->Mapper = (vtkMapper2D*) NULL; + this->LayerNumber = 0; + this->Property = (vtkProperty2D*) NULL; + // + this->PositionCoordinate = vtkCoordinate::New(); + this->PositionCoordinate->SetCoordinateSystem(VTK_VIEWPORT); + // + this->Position2Coordinate = vtkCoordinate::New(); + this->Position2Coordinate->SetCoordinateSystemToNormalizedViewport(); + this->Position2Coordinate->SetValue(0.5, 0.5); + this->Position2Coordinate->SetReferenceCoordinate(this->PositionCoordinate); +} + +// Destroy an actor2D. +vtkActor2D::~vtkActor2D() +{ + if (this->Property) + { + this->Property->UnRegister(this); + this->Property = NULL; + } + if (this->PositionCoordinate) + { + this->PositionCoordinate->Delete(); + this->PositionCoordinate = NULL; + } + if (this->Position2Coordinate) + { + this->Position2Coordinate->Delete(); + this->Position2Coordinate = NULL; + } + if (this->Mapper != NULL) + { + this->Mapper->UnRegister(this); + this->Mapper = NULL; + } +} + +void vtkActor2D::ReleaseGraphicsResources(vtkWindow *win) +{ + // pass this information onto the mapper + if (this->Mapper) + { + this->Mapper->ReleaseGraphicsResources(win); + } +} + +// Renders an actor2D's property and then it's mapper. +int vtkActor2D::RenderOverlay(vtkViewport* viewport) +{ + vtkDebugMacro(<< "vtkActor2D::RenderOverlay"); + + if (!this->Property) + { + vtkDebugMacro(<< "vtkActor2D::Render - Creating Property2D"); + // Force creation of default property + this->GetProperty(); + } + + this->Property->Render(viewport); + + if (!this->Mapper) + { + vtkErrorMacro(<< "vtkActor2D::Render - No mapper set"); + return 0; + } + + this->Mapper->RenderOverlay(viewport, this); + + return 1; +} + +// Renders an actor2D's property and then it's mapper. +int vtkActor2D::RenderOpaqueGeometry(vtkViewport* viewport) +{ + vtkDebugMacro(<< "vtkActor2D::RenderOpaqueGeometry"); + + if (!this->Property) + { + vtkDebugMacro(<< "vtkActor2D::Render - Creating Property2D"); + // Force creation of default property + this->GetProperty(); + } + + this->Property->Render(viewport); + + if (!this->Mapper) + { + vtkErrorMacro(<< "vtkActor2D::Render - No mapper set"); + return 0; + } + + this->Mapper->RenderOpaqueGeometry(viewport, this); + + return 1; +} + +// Renders an actor2D's property and then it's mapper. +int vtkActor2D::RenderTranslucentGeometry(vtkViewport* viewport) +{ + vtkDebugMacro(<< "vtkActor2D::RenderTranslucentGeometry"); + + if (!this->Property) + { + vtkDebugMacro(<< "vtkActor2D::Render - Creating Property2D"); + // Force creation of default property + this->GetProperty(); + } + + this->Property->Render(viewport); + + if (!this->Mapper) + { + vtkErrorMacro(<< "vtkActor2D::Render - No mapper set"); + return 0; + } + + this->Mapper->RenderTranslucentGeometry(viewport, this); + + return 1; +} + +void vtkActor2D::SetMapper(vtkMapper2D *mapper) +{ + if (this->Mapper != mapper) + { + if (this->Mapper != NULL) + { + this->Mapper->UnRegister(this); + } + this->Mapper = mapper; + if (this->Mapper != NULL) + { + this->Mapper->Register(this); + } + this->Modified(); + } +} + + +unsigned long int vtkActor2D::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + time = this->PositionCoordinate->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + time = this->Position2Coordinate->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + + if ( this->Property != NULL ) + { + time = this->Property->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +// Set the Prop2D's position in display coordinates. +void vtkActor2D::SetDisplayPosition(int XPos, int YPos) +{ + this->PositionCoordinate->SetCoordinateSystem(VTK_DISPLAY); + this->PositionCoordinate->SetValue((float)XPos,(float)YPos,0.0); +} + +void vtkActor2D::SetWidth(double w) +{ + double *pos; + + pos = this->Position2Coordinate->GetValue(); + this->Position2Coordinate->SetCoordinateSystemToNormalizedViewport(); + this->Position2Coordinate->SetValue(w,pos[1]); +} + +void vtkActor2D::SetHeight(double w) +{ + double *pos; + + pos = this->Position2Coordinate->GetValue(); + this->Position2Coordinate->SetCoordinateSystemToNormalizedViewport(); + this->Position2Coordinate->SetValue(pos[0],w); +} + +double vtkActor2D::GetWidth() +{ + return this->Position2Coordinate->GetValue()[0]; +} + +double vtkActor2D::GetHeight() +{ + return this->Position2Coordinate->GetValue()[1]; +} + +// Returns an Prop2D's property2D. Creates a property if one +// doesn't already exist. +vtkProperty2D *vtkActor2D::GetProperty() +{ + if (this->Property == NULL) + { + this->Property = vtkProperty2D::New(); + this->Property->Register(this); + this->Property->Delete(); + this->Modified(); + } + return this->Property; +} + +void vtkActor2D::GetActors2D(vtkPropCollection *ac) +{ + ac->AddItem(this); +} + +void vtkActor2D::ShallowCopy(vtkProp *prop) +{ + vtkActor2D *a = vtkActor2D::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetMapper(a->GetMapper()); + this->SetLayerNumber(a->GetLayerNumber()); + this->SetProperty(a->GetProperty()); + this->SetPosition(a->GetPosition()); + this->SetPosition2(a->GetPosition2()); + } + + // Now do superclass + this->vtkProp::ShallowCopy(prop); +} + +void vtkActor2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Layer Number: " << this->LayerNumber << "\n"; + os << indent << "PositionCoordinate: " << this->PositionCoordinate << "\n"; + this->PositionCoordinate->PrintSelf(os, indent.GetNextIndent()); + + os << indent << "Position2 Coordinate: " << this->Position2Coordinate << "\n"; + this->Position2Coordinate->PrintSelf(os, indent.GetNextIndent()); + + os << indent << "Property: " << this->Property << "\n"; + if (this->Property) + { + this->Property->PrintSelf(os, indent.GetNextIndent()); + } + os << indent << "Mapper: " << this->Mapper << "\n"; + if (this->Mapper) + { + this->Mapper->PrintSelf(os, indent.GetNextIndent()); + } +} + diff --git a/Filtering/vtkActor2D.h b/Filtering/vtkActor2D.h new file mode 100644 index 0000000..1ef4d95 --- /dev/null +++ b/Filtering/vtkActor2D.h @@ -0,0 +1,149 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActor2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkActor2D - a actor that draws 2D data +// .SECTION Description +// vtkActor2D is similar to vtkActor, but it is made to be used with two +// dimensional images and annotation. vtkActor2D has a position but does not +// use a transformation matrix like vtkActor (see the superclass vtkProp +// for information on positioning vtkActor2D). vtkActor2D has a reference to +// a vtkMapper2D object which does the rendering. + +// .SECTION See Also +// vtkProp vtkMapper2D vtkProperty2D + +#ifndef __vtkActor2D_h +#define __vtkActor2D_h + +#include "vtkProp.h" +#include "vtkCoordinate.h" // For vtkViewportCoordinateMacro + +class vtkMapper2D; +class vtkProperty2D; + +class VTK_FILTERING_EXPORT vtkActor2D : public vtkProp +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkActor2D,vtkProp); + + // Description: + // Creates an actor2D with the following defaults: + // position (0,0) (coordinate system is viewport); + // at layer 0. + static vtkActor2D* New(); + + // Description: + // Support the standard render methods. + int RenderOverlay(vtkViewport *viewport); + int RenderOpaqueGeometry(vtkViewport *viewport); + int RenderTranslucentGeometry(vtkViewport *viewport); + + // Description: + // Set/Get the vtkMapper2D which defines the data to be drawn. + virtual void SetMapper(vtkMapper2D *mapper); + vtkGetObjectMacro(Mapper, vtkMapper2D); + + // Description: + // Set/Get the layer number in the overlay planes into which to render. + vtkSetMacro(LayerNumber, int); + vtkGetMacro(LayerNumber, int); + + // Description: + // Returns this actor's vtkProperty2D. Creates a property if one + // doesn't already exist. + vtkProperty2D* GetProperty(); + + // Description: + // Set this vtkProp's vtkProperty2D. + virtual void SetProperty(vtkProperty2D*); + + // Description: + // Get the PositionCoordinate instance of vtkCoordinate. + // This is used for for complicated or relative positioning. + // The position variable controls the lower left corner of the Actor2D + vtkViewportCoordinateMacro(Position); + + // Description: + // Set the Prop2D's position in display coordinates. + void SetDisplayPosition(int,int); + + // Description: + // Access the Position2 instance variable. This variable controls + // the upper right corner of the Actor2D. It is by default + // relative to Position and in normalized viewport coordinates. + // Some 2D actor subclasses ignore the position2 variable + vtkViewportCoordinateMacro(Position2); + + // Description: + // Set/Get the height and width of the Actor2D. The value is expressed + // as a fraction of the viewport. This really is just another way of + // setting the Position2 instance variable. + void SetWidth(double w); + double GetWidth(); + void SetHeight(double h); + double GetHeight(); + + // Description: + // Return this objects MTime. + unsigned long GetMTime(); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. These methods + // are used in that process. + virtual void GetActors2D(vtkPropCollection *pc); + + // Description: + // Shallow copy of this vtkActor2D. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Return the actual vtkCoordinate reference that the mapper should use + // to position the actor. This is used internally by the mappers and should + // be overridden in specialized subclasses and otherwise ignored. + virtual vtkCoordinate *GetActualPositionCoordinate(void) + { return this->PositionCoordinate; } + + // Description: + // Return the actual vtkCoordinate reference that the mapper should use + // to position the actor. This is used internally by the mappers and should + // be overridden in specialized subclasses and otherwise ignored. + virtual vtkCoordinate *GetActualPosition2Coordinate(void) + { return this->Position2Coordinate; } + +protected: + vtkActor2D(); + ~vtkActor2D(); + + vtkMapper2D *Mapper; + int LayerNumber; + vtkProperty2D *Property; + vtkCoordinate *PositionCoordinate; + vtkCoordinate *Position2Coordinate; +private: + vtkActor2D(const vtkActor2D&); // Not implemented. + void operator=(const vtkActor2D&); // Not implemented. +}; + +#endif + + + diff --git a/Filtering/vtkActor2DCollection.cxx b/Filtering/vtkActor2DCollection.cxx new file mode 100644 index 0000000..46587f3 --- /dev/null +++ b/Filtering/vtkActor2DCollection.cxx @@ -0,0 +1,195 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActor2DCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkActor2DCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkActor2DCollection, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkActor2DCollection); + +// protected function to delete an element. Internal use only. +void vtkActor2DCollection::DeleteElement(vtkCollectionElement *e) +{ + vtkCollection::DeleteElement(e); +} + +// Desctructor for the vtkActor2DCollection class. This removes all +// objects from the collection. +vtkActor2DCollection::~vtkActor2DCollection() +{ + this->RemoveAllItems(); +} + +// Sort and then render the collection of 2D actors. +void vtkActor2DCollection::RenderOverlay(vtkViewport* viewport) +{ + if (this->NumberOfItems != 0) + { + this->Sort(); + vtkActor2D* tempActor; + vtkCollectionSimpleIterator adit; + for ( this->InitTraversal(adit); + (tempActor = this->GetNextActor2D(adit));) + { + // Make sure that the actor is visible before rendering + if (tempActor->GetVisibility() == 1) + { + tempActor->RenderOverlay(viewport); + } + } + } +} + +// Add an actor to the list. The new actor is +// inserted in the list according to it's layer +// number. +void vtkActor2DCollection::AddItem(vtkActor2D *a) +{ + vtkCollectionElement* indexElem; + vtkCollectionElement* elem = new vtkCollectionElement; + + // Check if the top item is NULL + if (this->Top == NULL) + { + vtkDebugMacro(<<"vtkActor2DCollection::AddItem - Adding item to top of the list"); + + this->Top = elem; + elem->Item = a; + elem->Next = NULL; + this->Bottom = elem; + this->NumberOfItems++; + a->Register(this); + return; + } + + for (indexElem = this->Top; + indexElem != NULL; + indexElem = indexElem->Next) + { + + vtkActor2D* tempActor = (vtkActor2D*) indexElem->Item; + if (a->GetLayerNumber() < tempActor->GetLayerNumber()) + { + // The indexElem item's layer number is larger, so swap + // the new item and the indexElem item. + vtkDebugMacro(<<"vtkActor2DCollection::AddItem - Inserting item"); + elem->Item = indexElem->Item; + elem->Next = indexElem->Next; + indexElem->Item = a; + indexElem->Next = elem; + this->NumberOfItems++; + a->Register(this); + return; + } + + } + + //End of list found before a larger layer number + vtkDebugMacro(<<"vtkActor2DCollection::AddItem - Adding item to end of the list"); + elem->Item = a; + elem->Next = NULL; + this->Bottom->Next = elem; + this->Bottom = elem; + this->NumberOfItems++; + a->Register(this); + +} + +// Sorts the vtkActor2DCollection by layer number. Smaller layer +// numbers are first. Layer numbers can be any integer value. +void vtkActor2DCollection::Sort() +{ + int index; + + vtkDebugMacro(<<"vtkActor2DCollection::Sort"); + + int numElems = this->GetNumberOfItems(); + + // Create an array of pointers to actors + vtkActor2D** actorPtrArr = new vtkActor2D* [numElems]; + + vtkDebugMacro(<<"vtkActor2DCollection::Sort - Getting actors from collection"); + + // Start at the beginning of the collection + vtkCollectionSimpleIterator ait; + this->InitTraversal(ait); + + + // Fill the actor array with the items in the collection + for (index = 0; index < numElems; index++) + { + actorPtrArr[index] = this->GetNextActor2D(ait); + } + + vtkDebugMacro(<<"vtkActor2DCollection::Sort - Starting selection sort"); + // Start the sorting - selection sort + int i, j, min; + vtkActor2D* t; + + for (i = 0; i < numElems - 1; i++) + { + min = i; + for (j = i + 1; j < numElems ; j++) + { + if(actorPtrArr[j]->GetLayerNumber() < actorPtrArr[min]->GetLayerNumber()) + { + min = j; + } + } + t = actorPtrArr[min]; + actorPtrArr[min] = actorPtrArr[i]; + actorPtrArr[i] = t; + } + + vtkDebugMacro(<<"vtkActor2DCollection::Sort - Selection sort done."); + + for (index = 0; index < numElems; index++) + { + vtkDebugMacro(<<"vtkActor2DCollection::Sort - actorPtrArr["<GetLayerNumber()); + } + + vtkDebugMacro(<<"vtkActor2DCollection::Sort - Rearraging the linked list."); + // Now move the items around in the linked list - + // keep the links the same, but swap around the items + + vtkCollectionElement* elem = this->Top; + elem->Item = actorPtrArr[0]; + + for (i = 1; i < numElems; i++) + { + elem = elem->Next; + elem->Item = actorPtrArr[i]; + } + + delete[] actorPtrArr; +} + + + + + + + + + + + + + + + + + diff --git a/Filtering/vtkActor2DCollection.h b/Filtering/vtkActor2DCollection.h new file mode 100644 index 0000000..2d58a3f --- /dev/null +++ b/Filtering/vtkActor2DCollection.h @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActor2DCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkActor2DCollection - a list of 2D actors +// .SECTION Description +// vtkActor2DCollection is a subclass of vtkCollection. vtkActor2DCollection +// maintains a collection of vtkActor2D objects that is sorted by layer +// number, with lower layer numbers at the start of the list. This allows +// the vtkActor2D objects to be rendered in the correct order. + +// .SECTION See Also +// vtkActor2D vtkCollection + +#ifndef __vtkActor2DCollection_h +#define __vtkActor2DCollection_h + +#include "vtkPropCollection.h" + +#include "vtkActor2D.h" // Needed for inline methods + +class vtkViewport; + +class VTK_FILTERING_EXPORT vtkActor2DCollection : public vtkPropCollection +{ + public: + // Description: + // Desctructor for the vtkActor2DCollection class. This removes all + // objects from the collection. + static vtkActor2DCollection *New(); + + vtkTypeRevisionMacro(vtkActor2DCollection,vtkPropCollection); + + // Description: + // Sorts the vtkActor2DCollection by layer number. Smaller layer + // numbers are first. Layer numbers can be any integer value. + void Sort(); + + // Description: + // Add an actor to the list. The new actor is inserted in the list + // according to it's layer number. + void AddItem(vtkActor2D *a); + + // Description: + // Standard Collection methods + int IsItemPresent(vtkActor2D *a); + vtkActor2D *GetNextActor2D(); + vtkActor2D *GetLastActor2D(); + + // Description: + // Access routines that are provided for compatibility with previous + // version of VTK. Please use the GetNextActor2D(), GetLastActor2D() + // variants where possible. + vtkActor2D *GetNextItem(); + vtkActor2D *GetLastItem(); + + + // Description: + // Sort and then render the collection of 2D actors. + void RenderOverlay(vtkViewport* viewport); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkActor2D *GetNextActor2D(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkActor2DCollection() {}; + ~vtkActor2DCollection(); + + virtual void DeleteElement(vtkCollectionElement *); + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + void AddItem(vtkProp *o) { this->vtkPropCollection::AddItem(o); }; + int IsItemPresent(vtkObject *o) { return this->vtkCollection::IsItemPresent(o); }; + +private: + vtkActor2DCollection(const vtkActor2DCollection&); // Not implemented. + void operator=(const vtkActor2DCollection&); // Not implemented. +}; + +inline int vtkActor2DCollection::IsItemPresent(vtkActor2D *a) +{ + return this->vtkCollection::IsItemPresent((vtkObject *)a); +} + +inline vtkActor2D *vtkActor2DCollection::GetNextActor2D() +{ + return static_cast(this->GetNextItemAsObject()); +} + +inline vtkActor2D *vtkActor2DCollection::GetLastActor2D() +{ + if ( this->Bottom == NULL ) + { + return NULL; + } + else + { + return static_cast(this->Bottom->Item); + } +} + +inline vtkActor2D *vtkActor2DCollection::GetNextItem() +{ + return this->GetNextActor2D(); +} + +inline vtkActor2D *vtkActor2DCollection::GetLastItem() +{ + return this->GetLastActor2D(); +} + +#endif + + + + + diff --git a/Filtering/vtkAlgorithm.cxx b/Filtering/vtkAlgorithm.cxx new file mode 100644 index 0000000..156ec8f --- /dev/null +++ b/Filtering/vtkAlgorithm.cxx @@ -0,0 +1,1196 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAlgorithm.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkCellData.h" +#include "vtkCommand.h" +#include "vtkDataObject.h" +#include "vtkDataSet.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationInformationVectorKey.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationStringKey.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkSmartPointer.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include +#include + +vtkCxxRevisionMacro(vtkAlgorithm, "$Revision: 1.27.4.3 $"); +vtkStandardNewMacro(vtkAlgorithm); + +vtkCxxSetObjectMacro(vtkAlgorithm,Information,vtkInformation); + +vtkInformationKeyMacro(vtkAlgorithm, INPUT_REQUIRED_DATA_TYPE, String); +vtkInformationKeyMacro(vtkAlgorithm, INPUT_IS_OPTIONAL, Integer); +vtkInformationKeyMacro(vtkAlgorithm, INPUT_IS_REPEATABLE, Integer); +vtkInformationKeyMacro(vtkAlgorithm, INPUT_REQUIRED_FIELDS, InformationVector); +vtkInformationKeyMacro(vtkAlgorithm, PORT_REQUIREMENTS_FILLED, Integer); +vtkInformationKeyMacro(vtkAlgorithm, INPUT_PORT, Integer); +vtkInformationKeyMacro(vtkAlgorithm, INPUT_CONNECTION, Integer); +vtkInformationKeyMacro(vtkAlgorithm, INPUT_ARRAYS_TO_PROCESS, InformationVector); + +vtkExecutive* vtkAlgorithm::DefaultExecutivePrototype = 0; + +//---------------------------------------------------------------------------- +class vtkAlgorithmInternals +{ +public: + // Proxy object instances for use in establishing connections from + // the output ports to other algorithms. + vtkstd::vector< vtkSmartPointer > Outputs; +}; + +//---------------------------------------------------------------------------- +class vtkAlgorithmToExecutiveFriendship +{ +public: + static void SetAlgorithm(vtkExecutive* executive, vtkAlgorithm* algorithm) + { + executive->SetAlgorithm(algorithm); + } +}; + +//---------------------------------------------------------------------------- +vtkAlgorithm::vtkAlgorithm() +{ + this->AbortExecute = 0; + this->ErrorCode = 0; + this->Progress = 0.0; + this->ProgressText = NULL; + this->Executive = 0; + this->InputPortInformation = vtkInformationVector::New(); + this->OutputPortInformation = vtkInformationVector::New(); + this->AlgorithmInternal = new vtkAlgorithmInternals; + this->Information = vtkInformation::New(); + this->Information->Register(this); + this->Information->Delete(); +} + +//---------------------------------------------------------------------------- +vtkAlgorithm::~vtkAlgorithm() +{ + this->SetInformation(0); + if(this->Executive) + { + this->Executive->UnRegister(this); + this->Executive = 0; + } + this->InputPortInformation->Delete(); + this->OutputPortInformation->Delete(); + delete this->AlgorithmInternal; + delete [] this->ProgressText; + this->ProgressText = NULL; +} + +//---------------------------------------------------------------------------- +// Update the progress of the process object. If a ProgressMethod exists, +// executes it. Then set the Progress ivar to amount. The parameter amount +// should range between (0,1). +void vtkAlgorithm::UpdateProgress(double amount) +{ + this->Progress = amount; + this->InvokeEvent(vtkCommand::ProgressEvent,(void *)&amount); +} + + +//---------------------------------------------------------------------------- +vtkInformation *vtkAlgorithm +::GetInputArrayFieldInformation(int idx, vtkInformationVector **inputVector) +{ + // first get out association + vtkInformation *info = this->GetInputArrayInformation(idx); + + // then get the actual info object from the pinfo + int port = info->Get(INPUT_PORT()); + int connection = info->Get(INPUT_CONNECTION()); + int fieldAssoc = info->Get(vtkDataObject::FIELD_ASSOCIATION()); + vtkInformation *inInfo = inputVector[port]->GetInformationObject(connection); + + if (info->Has(vtkDataObject::FIELD_NAME())) + { + const char *name = info->Get(vtkDataObject::FIELD_NAME()); + return vtkDataObject::GetNamedFieldInformation(inInfo, fieldAssoc, name); + } + int fType = info->Get(vtkDataObject::FIELD_ATTRIBUTE_TYPE()); + return vtkDataObject::GetActiveFieldInformation(inInfo, fieldAssoc, fType); +} + +//---------------------------------------------------------------------------- +vtkInformation *vtkAlgorithm::GetInputArrayInformation(int idx) +{ + // add this info into the algorithms info object + vtkInformationVector *inArrayVec = + this->Information->Get(INPUT_ARRAYS_TO_PROCESS()); + if (!inArrayVec) + { + inArrayVec = vtkInformationVector::New(); + this->Information->Set(INPUT_ARRAYS_TO_PROCESS(),inArrayVec); + inArrayVec->Delete(); + } + vtkInformation *inArrayInfo = inArrayVec->GetInformationObject(idx); + if (!inArrayInfo) + { + inArrayInfo = vtkInformation::New(); + inArrayVec->SetInformationObject(idx,inArrayInfo); + inArrayInfo->Delete(); + } + return inArrayInfo; +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetInputArrayToProcess(int idx, vtkInformation *inInfo) +{ + vtkInformation *info = this->GetInputArrayInformation(idx); + info->Copy(inInfo,1); + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetInputArrayToProcess(int idx, int port, int connection, + int fieldAssociation, + int attributeType) +{ + vtkInformation *info = this->GetInputArrayInformation(idx); + + info->Set(INPUT_PORT(), port); + info->Set(INPUT_CONNECTION(), connection); + info->Set(vtkDataObject::FIELD_ASSOCIATION(),fieldAssociation); + info->Set(vtkDataObject::FIELD_ATTRIBUTE_TYPE(), attributeType); + + // remove name if there is one + info->Remove(vtkDataObject::FIELD_NAME()); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetInputArrayToProcess( + int idx, int port, int connection, + const char* fieldAssociation, + const char* fieldAttributeTypeOrName) +{ + if (!fieldAssociation) + { + vtkErrorMacro("Association is requied"); + return; + } + if (!fieldAttributeTypeOrName) + { + vtkErrorMacro("Attribute type or array name is required"); + return ; + } + + int i; + + // Try to convert the string argument to an enum value + int association = -1; + for (i=0; iSetInputArrayToProcess( + idx, port, connection, association, fieldAttributeTypeOrName); + return; + } + + // Set by association and attribute type + this->SetInputArrayToProcess( + idx, port, connection, association, attributeType); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetInputArrayToProcess(int idx, int port, int connection, + int fieldAssociation, + const char *name) +{ + // ignore empty string + if (!name || name[0] == '\0') + { + return; + } + + vtkInformation *info = this->GetInputArrayInformation(idx); + + info->Set(INPUT_PORT(), port); + info->Set(INPUT_CONNECTION(), connection); + info->Set(vtkDataObject::FIELD_ASSOCIATION(),fieldAssociation); + info->Set(vtkDataObject::FIELD_NAME(),name); + + // remove fieldAttr if there is one + info->Remove(vtkDataObject::FIELD_ATTRIBUTE_TYPE()); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkDataArray *vtkAlgorithm::GetInputArrayToProcess( + int idx, vtkInformationVector **inputVector) +{ + vtkInformationVector *inArrayVec = + this->Information->Get(INPUT_ARRAYS_TO_PROCESS()); + if (!inArrayVec) + { + vtkErrorMacro + ("Attempt to get an input array for an index that has not been specified"); + return NULL; + } + vtkInformation *inArrayInfo = inArrayVec->GetInformationObject(idx); + if (!inArrayInfo) + { + vtkErrorMacro + ("Attempt to get an input array for an index that has not been specified"); + return NULL; + } + + int connection = inArrayInfo->Get(INPUT_CONNECTION()); + return this->GetInputArrayToProcess(idx, connection, inputVector); +} + +//---------------------------------------------------------------------------- +vtkDataArray *vtkAlgorithm::GetInputArrayToProcess( + int idx, int connection, vtkInformationVector **inputVector) +{ + vtkInformationVector *inArrayVec = + this->Information->Get(INPUT_ARRAYS_TO_PROCESS()); + if (!inArrayVec) + { + vtkErrorMacro + ("Attempt to get an input array for an index that has not been specified"); + return NULL; + } + vtkInformation *inArrayInfo = inArrayVec->GetInformationObject(idx); + if (!inArrayInfo) + { + vtkErrorMacro + ("Attempt to get an input array for an index that has not been specified"); + return NULL; + } + + int port = inArrayInfo->Get(INPUT_PORT()); + int fieldAssoc = inArrayInfo->Get(vtkDataObject::FIELD_ASSOCIATION()); + vtkInformation *inInfo = inputVector[port]->GetInformationObject(connection); + vtkDataObject *input = inInfo->Get(vtkDataObject::DATA_OBJECT()); + + if (inArrayInfo->Has(vtkDataObject::FIELD_NAME())) + { + const char *name = inArrayInfo->Get(vtkDataObject::FIELD_NAME()); + + if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_NONE) + { + vtkFieldData *fd = input->GetFieldData(); + return fd->GetArray(name); + } + + vtkDataSet *inputDS = vtkDataSet::SafeDownCast(input); + if (!inputDS) + { + vtkErrorMacro("Attempt to get point or cell data from a data object"); + return NULL; + } + if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS) + { + return inputDS->GetPointData()->GetArray(name); + } + if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS + && inputDS->GetPointData()->GetArray(name)) + { + return inputDS->GetPointData()->GetArray(name); + } + + return inputDS->GetCellData()->GetArray(name); + } + else + { + int fType = inArrayInfo->Get(vtkDataObject::FIELD_ATTRIBUTE_TYPE()); + // must have a data set + vtkDataSet *inputDS = vtkDataSet::SafeDownCast(input); + if (!inputDS) + { + vtkErrorMacro("Attempt to get point or cell data from a data object"); + return NULL; + } + if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS) + { + return inputDS->GetPointData()->GetAttribute(fType); + } + if (fieldAssoc == vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS + && inputDS->GetPointData()->GetAttribute(fType)) + { + return inputDS->GetPointData()->GetAttribute(fType); + } + + return inputDS->GetCellData()->GetAttribute(fType); + } +} + + +//---------------------------------------------------------------------------- +void vtkAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if(this->HasExecutive()) + { + os << indent << "Executive: " << this->Executive << "\n"; + } + else + { + os << indent << "Executive: (none)\n"; + } + + os << indent << "ErrorCode: " << + vtkErrorCode::GetStringFromErrorCode(this->ErrorCode) << endl; + + if ( this->Information ) + { + os << indent << "Information: " << this->Information << "\n"; + } + else + { + os << indent << "Information: (none)\n"; + } + + os << indent << "AbortExecute: " << (this->AbortExecute ? "On\n" : "Off\n"); + os << indent << "Progress: " << this->Progress << "\n"; + if ( this->ProgressText ) + { + os << indent << "Progress Text: " << this->ProgressText << "\n"; + } + else + { + os << indent << "Progress Text: (None)\n"; + } +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::HasExecutive() +{ + return this->Executive ? 1 : 0; +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkAlgorithm::GetExecutive() +{ + // Create the default executive if we do not have one already. + if(!this->HasExecutive()) + { + vtkExecutive* e = this->CreateDefaultExecutive(); + this->SetExecutive(e); + e->Delete(); + } + return this->Executive; +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetExecutive(vtkExecutive* newExecutive) +{ + vtkExecutive* oldExecutive = this->Executive; + if(newExecutive != oldExecutive) + { + if(newExecutive) + { + newExecutive->Register(this); + vtkAlgorithmToExecutiveFriendship::SetAlgorithm(newExecutive, this); + } + this->Executive = newExecutive; + if(oldExecutive) + { + vtkAlgorithmToExecutiveFriendship::SetAlgorithm(oldExecutive, 0); + oldExecutive->UnRegister(this); + } + } +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::ProcessRequest(vtkInformation* /* request */, + vtkInformationVector**, + vtkInformationVector*) +{ + return 1; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::ComputePipelineMTime(vtkInformation* /* request */, + vtkInformationVector**, + vtkInformationVector*, + int /* requestFromOutputPort */, + unsigned long* mtime) +{ + // By default algorithms contribute only their own modified time. + *mtime = this->GetMTime(); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::ModifyRequest(vtkInformation* /*request*/, int /*when*/) +{ + return 1; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::GetNumberOfInputPorts() +{ + return this->InputPortInformation->GetNumberOfInformationObjects(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetNumberOfInputPorts(int n) +{ + // Sanity check. + if(n < 0) + { + vtkErrorMacro("Attempt to set number of input ports to " << n); + n = 0; + } + + // We must remove all connections from ports that are removed. + for(int i=n; i < this->GetNumberOfInputPorts(); ++i) + { + this->SetNumberOfInputConnections(i, 0); + } + + // Set the number of input port information objects. + this->InputPortInformation->SetNumberOfInformationObjects(n); +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::GetNumberOfOutputPorts() +{ + return this->OutputPortInformation->GetNumberOfInformationObjects(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetNumberOfOutputPorts(int n) +{ + // Sanity check. + if(n < 0) + { + vtkErrorMacro("Attempt to set number of output ports to " << n); + n = 0; + } + + // We must remove all connections from ports that are removed. + for(int i=n; i < this->GetNumberOfOutputPorts(); ++i) + { + // Get the producer and its output information for this port. + vtkExecutive* producer = this->GetExecutive(); + vtkInformation* info = producer->GetOutputInformation(i); + + // Remove all consumers' references to this producer on this port. + vtkExecutive** consumers = info->GetExecutives(vtkExecutive::CONSUMERS()); + int* consumerPorts = info->GetPorts(vtkExecutive::CONSUMERS()); + int consumerCount = info->Length(vtkExecutive::CONSUMERS()); + for(int j=0; j < consumerCount; ++j) + { + vtkInformationVector* inputs = + consumers[j]->GetInputInformation(consumerPorts[j]); + inputs->Remove(info); + } + + // Remove this producer's references to all consumers on this port. + info->Remove(vtkExecutive::CONSUMERS()); + } + + // Set the number of output port information objects. + this->OutputPortInformation->SetNumberOfInformationObjects(n); + + // Set the number of connection proxy objects. + this->AlgorithmInternal->Outputs.resize(n); +} + +//---------------------------------------------------------------------------- +vtkInformation* vtkAlgorithm::GetInputPortInformation(int port) +{ + if(!this->InputPortIndexInRange(port, "get information object for")) + { + return 0; + } + + // Get the input port information object. + vtkInformation* info = + this->InputPortInformation->GetInformationObject(port); + + // Fill it if it has not yet been filled. + if(!info->Has(PORT_REQUIREMENTS_FILLED())) + { + if(this->FillInputPortInformation(port, info)) + { + info->Set(PORT_REQUIREMENTS_FILLED(), 1); + } + else + { + info->Clear(); + } + } + + // Return ths information object. + return info; +} + +//---------------------------------------------------------------------------- +vtkInformation* vtkAlgorithm::GetOutputPortInformation(int port) +{ + if(!this->OutputPortIndexInRange(port, "get information object for")) + { + return 0; + } + + // Get the output port information object. + vtkInformation* info = + this->OutputPortInformation->GetInformationObject(port); + + // Fill it if it has not yet been filled. + if(!info->Has(PORT_REQUIREMENTS_FILLED())) + { + if(this->FillOutputPortInformation(port, info)) + { + info->Set(PORT_REQUIREMENTS_FILLED(), 1); + } + else + { + info->Clear(); + } + } + + // Return ths information object. + return info; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::FillInputPortInformation(int, vtkInformation*) +{ + vtkErrorMacro("FillInputPortInformation is not implemented."); + return 0; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::FillOutputPortInformation(int, vtkInformation*) +{ + vtkErrorMacro("FillOutputPortInformation is not implemented."); + return 0; +} + + +//---------------------------------------------------------------------------- +int vtkAlgorithm::InputPortIndexInRange(int index, const char* action) +{ + // Make sure the index of the input port is in range. + if(index < 0 || index >= this->GetNumberOfInputPorts()) + { + vtkErrorMacro("Attempt to " << (action?action:"access") + << " input port index " << index + << " for an algorithm with " + << this->GetNumberOfInputPorts() << " input ports."); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::OutputPortIndexInRange(int index, const char* action) +{ + // Make sure the index of the output port is in range. + if(index < 0 || index >= this->GetNumberOfOutputPorts()) + { + vtkErrorMacro("Attempt to " << (action?action:"access") + << " output port index " << index + << " for an algorithm with " + << this->GetNumberOfOutputPorts() << " output ports."); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetDefaultExecutivePrototype(vtkExecutive* proto) +{ + if (vtkAlgorithm::DefaultExecutivePrototype == proto) + { + return; + } + if (vtkAlgorithm::DefaultExecutivePrototype) + { + vtkAlgorithm::DefaultExecutivePrototype->UnRegister(0); + vtkAlgorithm::DefaultExecutivePrototype = 0; + } + proto->Register(0); + vtkAlgorithm::DefaultExecutivePrototype = proto; +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkAlgorithm::CreateDefaultExecutive() +{ + if (vtkAlgorithm::DefaultExecutivePrototype) + { + return vtkAlgorithm::DefaultExecutivePrototype->NewInstance(); + } + return vtkStreamingDemandDrivenPipeline::New(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->Executive, "Executive"); +} + + + +/// These are convenience methods to forward to the executive + + +//---------------------------------------------------------------------------- +vtkDataObject* vtkAlgorithm::GetOutputDataObject(int port) +{ + return this->GetExecutive()->GetOutputData(port); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::RemoveAllInputs() +{ + this->SetInputConnection(0, 0); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetInputConnection(vtkAlgorithmOutput* input) +{ + this->SetInputConnection(0,input); +} +void vtkAlgorithm::SetInputConnection(int port, vtkAlgorithmOutput* input) +{ + if(!this->InputPortIndexInRange(port, "connect")) + { + return; + } + + // Get the producer/consumer pair for the connection. + vtkExecutive* producer = + (input && input->GetProducer())? input->GetProducer()->GetExecutive() : 0; + int producerPort = producer? input->GetIndex() : 0; + vtkExecutive* consumer = this->GetExecutive(); + int consumerPort = port; + + // Get the vector of connected input information objects. + vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort); + + // Get the information object from the producer of the new input. + vtkInformation* newInfo = + producer? producer->GetOutputInformation(producerPort) : 0; + + // Check if the connection is already present. + if(!newInfo && inputs->GetNumberOfInformationObjects() == 0) + { + return; + } + else if(newInfo == inputs->GetInformationObject(0) && + inputs->GetNumberOfInformationObjects() == 1) + { + return; + } + + // The connection is not present. + vtkDebugMacro("Setting connection to input port index " << consumerPort + << " from output port index " << producerPort + << " on algorithm " + << (producer? producer->GetAlgorithm()->GetClassName() : "") + << "(" << (producer? producer->GetAlgorithm() : 0) << ")."); + + // Add this consumer to the new input's list of consumers. + if(newInfo) + { + newInfo->Append(vtkExecutive::CONSUMERS(), consumer, consumerPort); + } + + // Remove this consumer from all old inputs' lists of consumers. + for(int i=0; i < inputs->GetNumberOfInformationObjects(); ++i) + { + if(vtkInformation* oldInfo = inputs->GetInformationObject(i)) + { + oldInfo->Remove(vtkExecutive::CONSUMERS(), consumer, consumerPort); + } + } + + // Make the new input the only connection. + if(newInfo) + { + inputs->SetInformationObject(0, newInfo); + inputs->SetNumberOfInformationObjects(1); + } + else + { + inputs->SetNumberOfInformationObjects(0); + } + + // This algorithm has been modified. + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::AddInputConnection(vtkAlgorithmOutput* input) +{ + this->AddInputConnection(0, input); +} +void vtkAlgorithm::AddInputConnection(int port, vtkAlgorithmOutput* input) +{ + if(!this->InputPortIndexInRange(port, "connect")) + { + return; + } + + // If there is no input do nothing. + if(!input || !input->GetProducer()) + { + return; + } + + // Get the producer/consumer pair for the connection. + vtkExecutive* producer = input->GetProducer()->GetExecutive(); + int producerPort = input->GetIndex(); + vtkExecutive* consumer = this->GetExecutive(); + int consumerPort = port; + + // Get the vector of connected input information objects. + vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort); + + // Add the new connection. + vtkDebugMacro("Adding connection to input port index " << consumerPort + << " from output port index " << producerPort + << " on algorithm " + << (producer? producer->GetAlgorithm()->GetClassName() : "") + << "(" << (producer? producer->GetAlgorithm() : 0) << ")."); + + // Get the information object from the producer of the new input. + vtkInformation* newInfo = producer->GetOutputInformation(producerPort); + + // Add this consumer to the input's list of consumers. + newInfo->Append(vtkExecutive::CONSUMERS(), consumer, consumerPort); + + // Add the information object to the list of inputs. + inputs->Append(newInfo); + + // This algorithm has been modified. + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::RemoveInputConnection(int port, vtkAlgorithmOutput* input) +{ + if(!this->InputPortIndexInRange(port, "disconnect")) + { + return; + } + + // If there is no input do nothing. + if(!input || !input->GetProducer()) + { + return; + } + + // Get the producer/consumer pair for the connection. + vtkExecutive* producer = input->GetProducer()->GetExecutive(); + int producerPort = input->GetIndex(); + vtkExecutive* consumer = this->GetExecutive(); + int consumerPort = port; + + // Get the vector of connected input information objects. + vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort); + + // Remove the connection. + vtkDebugMacro("Removing connection to input port index " << consumerPort + << " from output port index " << producerPort + << " on algorithm " + << (producer? producer->GetAlgorithm()->GetClassName() : "") + << "(" << (producer? producer->GetAlgorithm() : 0) << ")."); + + // Get the information object from the producer of the old input. + vtkInformation* oldInfo = producer->GetOutputInformation(producerPort); + + // Remove this consumer from the old input's list of consumers. + oldInfo->Remove(vtkExecutive::CONSUMERS(), consumer, consumerPort); + + // Remove the information object from the list of inputs. + inputs->Remove(oldInfo); + + // This algorithm has been modified. + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetNthInputConnection(int port, int index, + vtkAlgorithmOutput* input) +{ + if(!this->InputPortIndexInRange(port, "replace connection")) + { + return; + } + + // Get the producer/consumer pair for the connection. + vtkExecutive* producer = + (input && input->GetProducer())? input->GetProducer()->GetExecutive() : 0; + int producerPort = producer? input->GetIndex() : 0; + vtkExecutive* consumer = this->GetExecutive(); + int consumerPort = port; + + // Get the vector of connected input information objects. + vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort); + + // Check for any existing connection with this index. + vtkInformation* oldInfo = inputs->GetInformationObject(index); + + // Get the information object from the producer of the input. + vtkInformation* newInfo = + producer? producer->GetOutputInformation(producerPort) : 0; + + // If the connection has not changed, do nothing. + if(newInfo == oldInfo) + { + return; + } + + // Set the connection. + vtkDebugMacro("Setting connection index " << index + << " to input port index " << consumerPort + << " from output port index " << producerPort + << " on algorithm " + << (producer? producer->GetAlgorithm()->GetClassName() : "") + << "(" << (producer? producer->GetAlgorithm() : 0) << ")."); + + // Add the consumer to the new input's list of consumers. + if(newInfo) + { + newInfo->Append(vtkExecutive::CONSUMERS(), consumer, consumerPort); + } + + // Remove the consumer from the old input's list of consumers. + if(oldInfo) + { + oldInfo->Remove(vtkExecutive::CONSUMERS(), consumer, consumerPort); + } + + // Store the information object in the vector of input connections. + inputs->SetInformationObject(index, newInfo); + + // This algorithm has been modified. + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetNumberOfInputConnections(int port, int n) +{ + // Get the consumer executive and port number. + vtkExecutive* consumer = this->GetExecutive(); + int consumerPort = port; + + // Get the vector of connected input information objects. + vtkInformationVector* inputs = consumer->GetInputInformation(consumerPort); + + // If the number of connections has not changed, do nothing. + if(n == inputs->GetNumberOfInformationObjects()) + { + return; + } + + // Remove connections beyond the new number. + for(int i=n; i < inputs->GetNumberOfInformationObjects(); ++i) + { + // Remove each input's reference to this consumer. + if(vtkInformation* oldInfo = inputs->GetInformationObject(i)) + { + oldInfo->Remove(vtkExecutive::CONSUMERS(), consumer, consumerPort); + } + } + + // Set the number of connected inputs. Non-existing inputs will be + // empty information objects. + inputs->SetNumberOfInformationObjects(n); + + // This algorithm has been modified. + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkAlgorithmOutput* vtkAlgorithm::GetOutputPort(int port) +{ + if(!this->OutputPortIndexInRange(port, "get")) + { + return 0; + } + + // Create the vtkAlgorithmOutput proxy object if there is not one. + if(!this->AlgorithmInternal->Outputs[port]) + { + this->AlgorithmInternal->Outputs[port] = + vtkSmartPointer::New(); + this->AlgorithmInternal->Outputs[port]->SetProducer(this); + this->AlgorithmInternal->Outputs[port]->SetIndex(port); + } + + // Return the proxy object instance. + return this->AlgorithmInternal->Outputs[port]; +} + + +//---------------------------------------------------------------------------- +int vtkAlgorithm::GetNumberOfInputConnections(int port) +{ + if(this->Executive) + { + return this->Executive->GetNumberOfInputConnections(port); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::GetTotalNumberOfInputConnections() +{ + int i; + int total = 0; + for (i = 0; i < this->GetNumberOfInputPorts(); ++i) + { + total += this->GetNumberOfInputConnections(i); + } + return total; +} + +//---------------------------------------------------------------------------- +vtkAlgorithmOutput* vtkAlgorithm::GetInputConnection(int port, int index) +{ + if(index < 0 || index >= this->GetNumberOfInputConnections(port)) + { + vtkErrorMacro("Attempt to get connection index " << index + << " for input port " << port << ", which has " + << this->GetNumberOfInputConnections(port) + << " connections."); + return 0; + } + if(vtkInformation* info = + this->GetExecutive()->GetInputInformation(port, index)) + { + // Get the executive producing this input. If there is none, then + // it is a NULL input. + vtkExecutive* producer; + int producerPort; + info->Get(vtkExecutive::PRODUCER(),producer,producerPort); + if(producer) + { + return producer->GetAlgorithm()->GetOutputPort(producerPort); + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::Update() +{ + this->GetExecutive()->Update(); +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::UpdateInformation() +{ + vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); + if (ddp) + { + ddp->UpdateInformation(); + } +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::UpdateWholeExtent() +{ + vtkStreamingDemandDrivenPipeline* sddp = + vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); + if (sddp) + { + sddp->UpdateWholeExtent(); + } + else + { + this->Update(); + } +} + + +//---------------------------------------------------------------------------- +void vtkAlgorithm::ConvertTotalInputToPortConnection( + int ind, int &port, int &conn) +{ + port = 0; + conn = 0; + while (ind && port < this->GetNumberOfInputPorts()) + { + int pNumCon; + pNumCon = this->GetNumberOfInputConnections(port); + if (ind >= pNumCon) + { + port++; + ind -= pNumCon; + } + else + { + return; + } + } +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::ReleaseDataFlagOn() +{ + if(vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + ddp->SetReleaseDataFlag(i, 1); + } + } +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::ReleaseDataFlagOff() +{ + if(vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + ddp->SetReleaseDataFlag(i, 0); + } + } +} + +//---------------------------------------------------------------------------- +void vtkAlgorithm::SetReleaseDataFlag(int val) +{ + if(vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + ddp->SetReleaseDataFlag(i, val); + } + } +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::GetReleaseDataFlag() +{ + if(vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + return ddp->GetReleaseDataFlag(0); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithm::UpdateExtentIsEmpty(vtkDataObject *output) +{ + if (output == NULL) + { + return 1; + } + + // get the pinfo object then call the info signature + return this->UpdateExtentIsEmpty( + output->GetPipelineInformation(), + output->GetInformation()->Get(vtkDataObject::DATA_EXTENT_TYPE())); +} + + +//---------------------------------------------------------------------------- +int vtkAlgorithm::UpdateExtentIsEmpty(vtkInformation *info, int extentType) +{ + if (!info) + { + return 1; + } + + int *ext; + + switch (extentType) + { + case VTK_PIECES_EXTENT: + // Special way of asking for no input. + if (info->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()) == 0 ) + { + return 1; + } + break; + + case VTK_3D_EXTENT: + ext = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + // Special way of asking for no input. (zero volume) + if (!ext || ext[0] == (ext[1] + 1) || + ext[2] == (ext[3] + 1) || + ext[4] == (ext[5] + 1)) + { + return 1; + } + break; + + // We should never have this case occur + default: + vtkErrorMacro( << "Internal error - invalid extent type!" ); + break; + } + + return 0; +} diff --git a/Filtering/vtkAlgorithm.h b/Filtering/vtkAlgorithm.h new file mode 100644 index 0000000..8b2ac22 --- /dev/null +++ b/Filtering/vtkAlgorithm.h @@ -0,0 +1,465 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAlgorithm - Superclass for all sources, filters, and sinks in VTK. +// .SECTION Description +// vtkAlgorithm is the superclass for all sources, filters, and sinks +// in VTK. It defines a generalized interface for executing data +// processing algorithms. Pipeline connections are associated with +// input and output ports that are independent of the type of data +// passing through the connections. +// +// Instances may be used independently or within pipelines with a +// variety of architectures and update mechanisms. Pipelines are +// controlled by instances of vtkExecutive. Every vtkAlgorithm +// instance has an associated vtkExecutive when it is used in a +// pipeline. The executive is responsible for data flow. + +#ifndef __vtkAlgorithm_h +#define __vtkAlgorithm_h + +#include "vtkObject.h" + +class vtkAlgorithmInternals; +class vtkAlgorithmOutput; +class vtkDataArray; +class vtkDataObject; +class vtkExecutive; +class vtkInformation; +class vtkInformationInformationVectorKey; +class vtkInformationIntegerKey; +class vtkInformationStringKey; +class vtkInformationVector; + +class VTK_FILTERING_EXPORT vtkAlgorithm : public vtkObject +{ +public: + static vtkAlgorithm *New(); + vtkTypeRevisionMacro(vtkAlgorithm,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Check whether this algorithm has an assigned executive. This + // will NOT create a default executive. + int HasExecutive(); + + // Description: + // Get this algorithm's executive. If it has none, a default + // executive will be created. + vtkExecutive* GetExecutive(); + + // Description: + // Set this algorithm's executive. This algorithm is removed from + // any executive to which it has previously been assigned and then + // assigned to the given executive. + virtual void SetExecutive(vtkExecutive* executive); + + // Description: + // Upstream/Downstream requests form the generalized interface + // through which executives invoke a algorithm's functionality. + // Upstream requests correspond to information flow from the + // algorithm's outputs to its inputs. Downstream requests + // correspond to information flow from the algorithm's inputs to its + // outputs. + // + // A downstream request is defined by the contents of the request + // information object. The input to the request is stored in the + // input information vector passed to ProcessRequest. The results + // of an downstream request are stored in the output information + // vector passed to ProcessRequest. + // + // An upstream request is defined by the contents of the request + // information object. The input to the request is stored in the + // output information vector passed to ProcessRequest. The results + // of an upstream request are stored in the input information vector + // passed to ProcessRequest. + // + // It returns the boolean status of the pipeline (false + // means failure). + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + // Description: + // A special version of ProcessRequest meant specifically for the + // pipeline modified time request. See + // vtkExecutive::ComputePipelineMTime() for details. + virtual int + ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int requestFromOutputPort, + unsigned long* mtime); + + // Description: + // This method gives the algorithm a chance to modify the contents of a + // request before or after (specified in the when argument) it is + // forwarded. The default implementation is empty. Returns 1 on success, + // 0 on failure. When can be either vtkExecutive::BeforeForward or + // vtkExecutive::AfterForward. + virtual int ModifyRequest(vtkInformation* request, int when); + + // Description: + // Get the information object associated with an input port. There + // is one input port per kind of input to the algorithm. Each input + // port tells executives what kind of data and downstream requests + // this algorithm can handle for that input. + vtkInformation* GetInputPortInformation(int port); + + // Description: + // Get the information object associated with an output port. There + // is one output port per output from the algorithm. Each output + // port tells executives what kind of upstream requests this + // algorithm can handle for that output. + vtkInformation* GetOutputPortInformation(int port); + + // Description: + // Set/Get the information object associated with this algorithm. + vtkGetObjectMacro(Information, vtkInformation); + virtual void SetInformation(vtkInformation*); + + // Description: + // Get the number of input ports used by the algorithm. + int GetNumberOfInputPorts(); + + // Description: + // Get the number of output ports provided by the algorithm. + int GetNumberOfOutputPorts(); + + // Description: + // Participate in garbage collection. + virtual void Register(vtkObjectBase* o); + virtual void UnRegister(vtkObjectBase* o); + + // Description: + // Set/Get the AbortExecute flag for the process object. Process objects + // may handle premature termination of execution in different ways. + vtkSetMacro(AbortExecute,int); + vtkGetMacro(AbortExecute,int); + vtkBooleanMacro(AbortExecute,int); + + // Description: + // Set/Get the execution progress of a process object. + vtkSetClampMacro(Progress,double,0.0,1.0); + vtkGetMacro(Progress,double); + + // Description: + // Update the progress of the process object. If a ProgressMethod exists, + // executes it. Then set the Progress ivar to amount. The parameter amount + // should range between (0,1). + void UpdateProgress(double amount); + + // Description: + // Set the current text message associated with the progress state. + // This may be used by a calling process/GUI. + vtkSetStringMacro(ProgressText); + vtkGetStringMacro(ProgressText); + + // Description: + // The error code contains a possible error that occured while + // reading or writing the file. + vtkGetMacro( ErrorCode, unsigned long ); + + // left public for performance since it is used in inner loops + int AbortExecute; + + // Description: + // Keys used to specify input port requirements. + static vtkInformationIntegerKey* INPUT_IS_OPTIONAL(); + static vtkInformationIntegerKey* INPUT_IS_REPEATABLE(); + static vtkInformationInformationVectorKey* INPUT_REQUIRED_FIELDS(); + static vtkInformationStringKey* INPUT_REQUIRED_DATA_TYPE(); + static vtkInformationInformationVectorKey* INPUT_ARRAYS_TO_PROCESS(); + static vtkInformationIntegerKey* INPUT_PORT(); + static vtkInformationIntegerKey* INPUT_CONNECTION(); + + + // Description: + // Set the input data arrays that this algorithm will + // process. Specifically the idx array that this algorithm will process + // (starting from 0) is the array on port, connection with the specified + // association and name or attribute type (such as SCALARS). The + // fieldAssociation refers to which field in the data object the array is + // stored. See vtkDataObject::FieldAssociations for detail. + void SetInputArrayToProcess(int idx, int port, int connection, + int fieldAssociation, + const char *name); + void SetInputArrayToProcess(int idx, int port, int connection, + int fieldAssociation, + int fieldAttributeType); + void SetInputArrayToProcess(int idx, vtkInformation *info); + + // Description: + // String based versions of SetInputArrayToProcess(). Because + // fieldAssociation and fieldAttributeType are enums, they cannot be + // easily accessed from scripting language. These methods provides an + // easy and safe way of passing association and attribute type + // information. Field association is one of the following: + // @verbatim + // vtkDataObject::FIELD_ASSOCIATION_POINTS + // vtkDataObject::FIELD_ASSOCIATION_CELLS + // vtkDataObject::FIELD_ASSOCIATION_NONE + // vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS + // @endverbatim + // Attribute type is one of the following: + // @verbatim + // vtkDataSetAttributes::SCALARS + // vtkDataSetAttributes::VECTORS + // vtkDataSetAttributes::NORMALS + // vtkDataSetAttributes::TCOORDS + // vtkDataSetAttributes::TENSORS + // @endverbatim + // If the last argument is not an attribute type, it is assumed to + // be an array name. + void SetInputArrayToProcess(int idx, int port, int connection, + const char* fieldAssociation, + const char* attributeTypeorName); + + // Description: + // Get the info object for the specified input array to this algorithm + vtkInformation *GetInputArrayInformation(int idx); + + // from here down are convenience methods that really are executive methods + + + + // Description: + // Remove all the input data. + void RemoveAllInputs(); + + // Description: + // Get the data object that will contain the algorithm output for + // the given port. + vtkDataObject* GetOutputDataObject(int port); + + // Description: + // Set the connection for the given input port index. Each input + // port of a filter has a specific purpose. A port may have zero or + // more connections and the required number is specified by each + // filter. Setting the connection with this method removes all + // other connections from the port. To add more than one connection + // use AddInputConnection(). + // + // The input for the connection is the output port of another + // filter, which is obtained with GetOutputPort(). Typical usage is + // + // filter2->SetInputConnection(0, filter1->GetOutputPort(0)). + virtual void SetInputConnection(int port, vtkAlgorithmOutput* input); + virtual void SetInputConnection(vtkAlgorithmOutput* input); + + // Description: + // Add a connection to the given input port index. See + // SetInputConnection() for details on input connections. This + // method is the complement to RemoveInputConnection() in that it + // adds only the connection specified without affecting other + // connections. Typical usage is + // + // filter2->AddInputConnection(0, filter1->GetOutputPort(0)). + virtual void AddInputConnection(int port, vtkAlgorithmOutput* input); + virtual void AddInputConnection(vtkAlgorithmOutput* input); + + // Description: + // Remove a connection from the given input port index. See + // SetInputConnection() for details on input connection. This + // method is the complement to AddInputConnection() in that it + // removes only the connection specified without affecting other + // connections. Typical usage is + // + // filter2->RemoveInputConnection(0, filter1->GetOutputPort(0)). + virtual void RemoveInputConnection(int port, vtkAlgorithmOutput* input); + + // Description: + // Get a proxy object corresponding to the given output port of this + // algorithm. The proxy object can be passed to another algorithm's + // SetInputConnection(), AddInputConnection(), and + // RemoveInputConnection() methods to modify pipeline connectivity. + vtkAlgorithmOutput* GetOutputPort(int index); + vtkAlgorithmOutput* GetOutputPort() { + return this->GetOutputPort(0); } + + // Description: + // Get the number of inputs currently connected to a port. + int GetNumberOfInputConnections(int port); + + // Description: + // Get the total number of inputs for this algorithm + int GetTotalNumberOfInputConnections(); + + // Description: + // Get the algorithm output port connected to an input port. + vtkAlgorithmOutput* GetInputConnection(int port, int index); + + // Description: + // Bring this algorithm's outputs up-to-date. + virtual void Update(); + + // Description: + // Backward compatibility method to invoke UpdateInformation on executive. + virtual void UpdateInformation(); + + // Description: + // Bring this algorithm's outputs up-to-date. + virtual void UpdateWholeExtent(); + + // Description: + // Convenience routine to convert from a linear ordering of input + // connections to a port/connection pair. + void ConvertTotalInputToPortConnection(int ind, int& port, int& conn); + + //====================================================================== + //The following block of code is to support old style VTK applications. If + //you are using these calls there are better ways to do it in the new + //pipeline + //====================================================================== + + // Description: + // Turn release data flag on or off for all output ports. + virtual void SetReleaseDataFlag(int); + virtual int GetReleaseDataFlag(); + void ReleaseDataFlagOn(); + void ReleaseDataFlagOff(); + + //======================================================================== + + // Description: + // This detects when the UpdateExtent will generate no data + // This condition is satisfied when the UpdateExtent has + // zero volume (0,-1,...) or the UpdateNumberOfPieces is 0. + // The source uses this call to determine whether to call Execute. + int UpdateExtentIsEmpty(vtkDataObject *output); + int UpdateExtentIsEmpty(vtkInformation *pinfo, int extentType); + +protected: + vtkAlgorithm(); + ~vtkAlgorithm(); + + // Keys used to indicate that input/output port information has been + // filled. + static vtkInformationIntegerKey* PORT_REQUIREMENTS_FILLED(); + + // Arbitrary extra information associated with this algorithm + vtkInformation* Information; + + // Description: + // Fill the input port information objects for this algorithm. This + // is invoked by the first call to GetInputPortInformation for each + // port so subclasses can specify what they can handle. + virtual int FillInputPortInformation(int port, vtkInformation* info); + + // Description: + // Fill the output port information objects for this algorithm. + // This is invoked by the first call to GetOutputPortInformation for + // each port so subclasses can specify what they can handle. + virtual int FillOutputPortInformation(int port, vtkInformation* info); + + // Description: + // Set the number of input ports used by the algorithm. + virtual void SetNumberOfInputPorts(int n); + + // Description: + // Set the number of output ports provided by the algorithm. + virtual void SetNumberOfOutputPorts(int n); + + // Helper methods to check input/output port index ranges. + int InputPortIndexInRange(int index, const char* action); + int OutputPortIndexInRange(int index, const char* action); + + // Description: + // Get the actual data array for the input array sepcified by idx, this is + // only reasonable during the REQUEST_DATA pass + vtkDataArray *GetInputArrayToProcess(int idx,vtkInformationVector **inputVector); + + // Description: + // Filters that have multiple connections on one port can use + // this signature. This will override the connection id that the + // user set in SetInputArrayToProcess() with the connection id + // passed. This way, the user specifies one array to process and + // that information is used to obtain arrays for all the connection + // on the port with the appropriate connection id substituted. + vtkDataArray *GetInputArrayToProcess(int idx, + int connection, + vtkInformationVector **inputVector); + + // Description: + // This method takes in an index (as specified in SetInputArrayToProcess) + // and a pipeline information vector. It then finds the information about + // input array idx and then uses that information to find the field + // information from the relevent field in the pifo vector (as done by + // vtkDataObject::GetActiveFieldInformation) + vtkInformation *GetInputArrayFieldInformation(int idx, + vtkInformationVector **inputVector); + + + // Description: + // If the DefaultExecutivePrototype is set, a copy of it is created + // in CreateDefaultExecutive() using NewInstance(). + static void SetDefaultExecutivePrototype(vtkExecutive* proto); + + // Description: + // Create a default executive. + // If the DefaultExecutivePrototype is set, a copy of it is created + // in CreateDefaultExecutive() using NewInstance(). + // Otherwise, vtkStreamingDemandDrivenPipeline is created. + virtual vtkExecutive* CreateDefaultExecutive(); + + // Description: + // The error code contains a possible error that occured while + // reading or writing the file. + vtkSetMacro( ErrorCode, unsigned long ); + unsigned long ErrorCode; + + // Progress/Update handling + double Progress; + char *ProgressText; + + // Garbage collection support. + virtual void ReportReferences(vtkGarbageCollector*); + + // executive methods below + + // Description: + // Replace the Nth connection on the given input port. For use only + // by this class and subclasses. If this is used to store a NULL + // input then the subclass must be able to handle NULL inputs in its + // ProcessRequest method. + virtual void SetNthInputConnection(int port, int index, + vtkAlgorithmOutput* input); + + // Description: + // Set the number of input connections on the given input port. For + // use only by this class and subclasses. If this is used to store + // a NULL input then the subclass must be able to handle NULL inputs + // in its ProcessRequest method. + virtual void SetNumberOfInputConnections(int port, int n); + + static vtkExecutive* DefaultExecutivePrototype; + +private: + vtkExecutive* Executive; + vtkInformationVector* InputPortInformation; + vtkInformationVector* OutputPortInformation; + vtkAlgorithmInternals* AlgorithmInternal; + static void ConnectionAdd(vtkAlgorithm* producer, int producerPort, + vtkAlgorithm* consumer, int consumerPort); + static void ConnectionRemove(vtkAlgorithm* producer, int producerPort, + vtkAlgorithm* consumer, int consumerPort); + static void ConnectionRemoveAllInput(vtkAlgorithm* consumer, int port); + static void ConnectionRemoveAllOutput(vtkAlgorithm* producer, int port); + +private: + vtkAlgorithm(const vtkAlgorithm&); // Not implemented. + void operator=(const vtkAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkAlgorithmOutput.cxx b/Filtering/vtkAlgorithmOutput.cxx new file mode 100644 index 0000000..089050d --- /dev/null +++ b/Filtering/vtkAlgorithmOutput.cxx @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAlgorithmOutput.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAlgorithmOutput.h" + +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkAlgorithmOutput, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkAlgorithmOutput); + +//---------------------------------------------------------------------------- +vtkAlgorithmOutput::vtkAlgorithmOutput() +{ + this->Producer = 0; + this->Index = 0; +} + +//---------------------------------------------------------------------------- +vtkAlgorithmOutput::~vtkAlgorithmOutput() +{ +} + +//---------------------------------------------------------------------------- +void vtkAlgorithmOutput::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if(this->Producer) + { + os << indent << "Producer: " << this->Producer << "\n"; + } + else + { + os << indent << "Producer: (none)\n"; + } + os << indent << "Index: " << this->Index << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkAlgorithmOutput::SetIndex(int index) +{ + this->Index = index; +} + +//---------------------------------------------------------------------------- +int vtkAlgorithmOutput::GetIndex() +{ + return this->Index; +} + +//---------------------------------------------------------------------------- +vtkAlgorithm* vtkAlgorithmOutput::GetProducer() +{ + return this->Producer; +} + +//---------------------------------------------------------------------------- +void vtkAlgorithmOutput::SetProducer(vtkAlgorithm* producer) +{ + this->Producer = producer; +} diff --git a/Filtering/vtkAlgorithmOutput.h b/Filtering/vtkAlgorithmOutput.h new file mode 100644 index 0000000..d29876c --- /dev/null +++ b/Filtering/vtkAlgorithmOutput.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAlgorithmOutput.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAlgorithmOutput - Proxy object to connect input/output ports. +// .SECTION Description +// vtkAlgorithmOutput is a proxy object returned by the GetOutputPort +// method of vtkAlgorithm. It may be passed to the +// SetInputConnection, AddInputConnection, or RemoveInputConnection +// methods of another vtkAlgorithm to establish a connection between +// an output and input port. The connection is not stored in the +// proxy object: it is simply a convenience for creating or removing +// connections. + +#ifndef __vtkAlgorithmOutput_h +#define __vtkAlgorithmOutput_h + +#include "vtkObject.h" + +class vtkAlgorithm; + +class VTK_FILTERING_EXPORT vtkAlgorithmOutput : public vtkObject +{ +public: + static vtkAlgorithmOutput *New(); + vtkTypeRevisionMacro(vtkAlgorithmOutput,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + void SetIndex(int index); + int GetIndex(); + + vtkAlgorithm* GetProducer(); + void SetProducer(vtkAlgorithm* producer); + +protected: + vtkAlgorithmOutput(); + ~vtkAlgorithmOutput(); + + int Index; + vtkAlgorithm* Producer; + +private: + vtkAlgorithmOutput(const vtkAlgorithmOutput&); // Not implemented. + void operator=(const vtkAlgorithmOutput&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkAttributesErrorMetric.cxx b/Filtering/vtkAttributesErrorMetric.cxx new file mode 100644 index 0000000..347270e --- /dev/null +++ b/Filtering/vtkAttributesErrorMetric.cxx @@ -0,0 +1,273 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAttributesErrorMetric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAttributesErrorMetric.h" + +#include "vtkObjectFactory.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericDataSet.h" +#include + +vtkCxxRevisionMacro(vtkAttributesErrorMetric,"$Revision: 1.9 $"); +vtkStandardNewMacro(vtkAttributesErrorMetric); + +//----------------------------------------------------------------------------- +vtkAttributesErrorMetric::vtkAttributesErrorMetric() +{ + this->AttributeTolerance = 0.1; // arbitrary + this->AbsoluteAttributeTolerance = 0.1; // arbitrary + this->SquareAbsoluteAttributeTolerance=this->AbsoluteAttributeTolerance*this->AbsoluteAttributeTolerance; + this->Range=0; + this->DefinedByAbsolute=1; +} + +//----------------------------------------------------------------------------- +vtkAttributesErrorMetric::~vtkAttributesErrorMetric() +{ +} + +//----------------------------------------------------------------------------- +// Description: +// Set the absolute attribute accuracy to `value'. See +// GetAbsoluteAttributeTolerance() for details. +// \pre valid_range_value: value>0 +void vtkAttributesErrorMetric::SetAbsoluteAttributeTolerance(double value) +{ + assert("pre: valid_range_value" && value>0); + if(this->AbsoluteAttributeTolerance!=value || !this->DefinedByAbsolute) + { + this->AbsoluteAttributeTolerance=value; + this->SquareAbsoluteAttributeTolerance=this->AbsoluteAttributeTolerance*this->AbsoluteAttributeTolerance; + this->Range=0; + this->DefinedByAbsolute=1; + this->Modified(); + } +} + +//----------------------------------------------------------------------------- +// Description: +// Set the relative attribute accuracy to `value'. See +// GetAttributeTolerance() for details. +// \pre valid_range_value: value>0 && value<1 +void vtkAttributesErrorMetric::SetAttributeTolerance(double value) +{ + assert("pre: valid_range_value" && value>0 && value<1); + if(this->AttributeTolerance!=value || this->DefinedByAbsolute) + { + this->AttributeTolerance=value; + this->DefinedByAbsolute=0; + this->Modified(); + } +} + +//----------------------------------------------------------------------------- +int vtkAttributesErrorMetric::RequiresEdgeSubdivision(double *leftPoint, + double *midPoint, + double *rightPoint, + double alpha) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); + assert("pre: clamped_alpha" && alpha>0 && alpha<1); + + int result; + double ae; + vtkGenericAttributeCollection *ac; + + this->ComputeSquareAbsoluteAttributeTolerance(); + + const int ATTRIBUTE_OFFSET=6; + + ac=this->DataSet->GetAttributes(); + vtkGenericAttribute *a=ac->GetAttribute(ac->GetActiveAttribute()); + + if(this->GenericCell->IsAttributeLinear(a)) + { + //don't need to do anything: + ae=0; + } + else + { + if(ac->GetActiveComponent()>=0) + { + int i=ac->GetAttributeIndex(ac->GetActiveAttribute())+ac->GetActiveComponent()+ATTRIBUTE_OFFSET; + double tmp=leftPoint[i]+alpha*(rightPoint[i]-leftPoint[i])-midPoint[i]; + ae=tmp*tmp; + } + else // module of the vector + { + int i=ac->GetAttributeIndex(ac->GetActiveAttribute())+ATTRIBUTE_OFFSET; + int j=0; + int c=ac->GetNumberOfComponents(); + double tmp; +#if 0 + // If x and y are two vectors, we compute: ||x|-|y|| + double interpolatedValueMod=0; + double midValueMod=0; + while(j=0); + } + + if(this->SquareAbsoluteAttributeTolerance==0) + { + result=fabs(ae)>0.0001; + } + else + { + result=ae>this->SquareAbsoluteAttributeTolerance; + } + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the error at the mid-point. The type of error depends on the state +// of the concrete error metric. For instance, it can return an absolute +// or relative error metric. +// See RequiresEdgeSubdivision() for a description of the arguments. +// \post positive_result: result>=0 +double vtkAttributesErrorMetric::GetError(double *leftPoint, + double *midPoint, + double *rightPoint, + double alpha) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); + assert("pre: clamped_alpha" && alpha>0 && alpha<1); + + double ae; + vtkGenericAttributeCollection *ac; + + this->ComputeSquareAbsoluteAttributeTolerance(); + + const int ATTRIBUTE_OFFSET=6; + + ac=this->DataSet->GetAttributes(); + vtkGenericAttribute *a=ac->GetAttribute(ac->GetActiveAttribute()); + + + if(this->GenericCell->IsAttributeLinear(a)) + { + //don't need to do anything: + ae=0; + } + else + { + if(ac->GetActiveComponent()>=0) // one component + { + int i=ac->GetAttributeIndex(ac->GetActiveAttribute())+ac->GetActiveComponent()+ATTRIBUTE_OFFSET; + double tmp=leftPoint[i]+alpha*(rightPoint[i]-leftPoint[i])-midPoint[i]; + ae=tmp*tmp; + } + else // module of the vector + { + // If x and y are two vectors, we compute: |x-y| + // We should compute ||x|-|y|| but |x-y| is usually enough + // and tends to produce less degenerated edges. + // Remind that: ||x|-|y||<=|x-y| + int i=ac->GetAttributeIndex(ac->GetActiveAttribute())+ATTRIBUTE_OFFSET; + int j=0; + int c=ac->GetNumberOfComponents(); + double tmp; + + ae=0; + while(jRange!=0) + { + result=sqrt(ae)/this->Range; + } + else + { + result=0; + } + + assert("post: positive_result" && result>=0); + + return result; +} + +//----------------------------------------------------------------------------- +void vtkAttributesErrorMetric::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "AttributeTolerance: " << this->AttributeTolerance << endl; + os << indent << "AbsoluteAttributeTolerance: " << this->AbsoluteAttributeTolerance << endl; +} + +//----------------------------------------------------------------------------- +// Description: +// Compute the absolute attribute tolerance, only if the cached value is +// obsolete. +void vtkAttributesErrorMetric::ComputeSquareAbsoluteAttributeTolerance() +{ + if(!this->DefinedByAbsolute) + { + if ( this->GetMTime() > this->SquareAbsoluteAttributeToleranceComputeTime ) + { + vtkGenericAttributeCollection *ac=this->DataSet->GetAttributes(); + vtkGenericAttribute *a=ac->GetAttribute(ac->GetActiveAttribute()); + + int i=ac->GetActiveComponent(); + + double r[2]; + + a->GetRange(i,r); + + double tmp=(r[1]-r[0])*this->AttributeTolerance; + + this->Range=r[1]-r[0]; + + this->SquareAbsoluteAttributeTolerance=tmp*tmp; + this->SquareAbsoluteAttributeToleranceComputeTime.Modified(); + this->AbsoluteAttributeTolerance=sqrt(this->SquareAbsoluteAttributeTolerance); + } + } +} diff --git a/Filtering/vtkAttributesErrorMetric.h b/Filtering/vtkAttributesErrorMetric.h new file mode 100644 index 0000000..f4067aa --- /dev/null +++ b/Filtering/vtkAttributesErrorMetric.h @@ -0,0 +1,146 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAttributesErrorMetric.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAttributesErrorMetric - Objects that compute +// attribute-based error during cell tessellation. +// +// .SECTION Description +// It is a concrete error metric, based on an attribute criterium: +// the variation of the active attribute/component value from a linear ramp +// +// .SECTION See Also +// vtkGenericCellTessellator vtkGenericSubdivisionErrorMetric + +#ifndef __vtkAttributesErrorMetric_h +#define __vtkAttributesErrorMetric_h + +#include "vtkGenericSubdivisionErrorMetric.h" + +class vtkGenericAttributeCollection; +class vtkGenericDataSet; + +class VTK_FILTERING_EXPORT vtkAttributesErrorMetric : public vtkGenericSubdivisionErrorMetric +{ +public: + // Description: + // Construct the error metric with a default relative attribute accuracy + // equal to 0.1. + static vtkAttributesErrorMetric *New(); + + // Description: + // Standard VTK type and error macros. + vtkTypeRevisionMacro(vtkAttributesErrorMetric,vtkGenericSubdivisionErrorMetric); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Absolute tolerance of the active scalar (attribute+component). + // Subdivision is required if the square distance between the real attribute + // at the mid point on the edge and the interpolated attribute is greater + // than AbsoluteAttributeTolerance. + // This is the attribute accuracy. + // 0.01 will give better result than 0.1. + vtkGetMacro(AbsoluteAttributeTolerance, double); + + // Description: + // Set the absolute attribute accuracy to `value'. See + // GetAbsoluteAttributeTolerance() for details. + // It is particularly useful when some concrete implementation of + // vtkGenericAttribute does not support GetRange() request, called + // internally in SetAttributeTolerance(). It may happen when the + // implementation support higher order attributes but + // cannot compute the range. + // \pre valid_range_value: value>0 + void SetAbsoluteAttributeTolerance(double value); + + // Description: + // Relative tolerance of the active scalar (attribute+component). + // Subdivision is required if the square distance between the real attribute + // at the mid point on the edge and the interpolated attribute is greater + // than AttributeTolerance. + // This is the attribute accuracy. + // 0.01 will give better result than 0.1. + vtkGetMacro(AttributeTolerance, double); + + // Description: + // Set the relative attribute accuracy to `value'. See + // GetAttributeTolerance() for details. + // \pre valid_range_value: value>0 && value<1 + void SetAttributeTolerance(double value); + + // Description: + // Does the edge need to be subdivided according to the distance between + // the value of the active attribute/component at the midpoint and the mean + // value between the endpoints? + // The edge is defined by its `leftPoint' and its `rightPoint'. + // `leftPoint', `midPoint' and `rightPoint' have to be initialized before + // calling RequiresEdgeSubdivision(). + // Their format is global coordinates, parametric coordinates and + // point centered attributes: xyx rst abc de... + // `alpha' is the normalized abscissa of the midpoint along the edge. + // (close to 0 means close to the left point, close to 1 means close to the + // right point) + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + int RequiresEdgeSubdivision(double *leftPoint, double *midPoint, double *rightPoint, + double alpha); + + // Description: + // Return the error at the mid-point. The type of error depends on the state + // of the concrete error metric. For instance, it can return an absolute + // or relative error metric. + // See RequiresEdgeSubdivision() for a description of the arguments. + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + // \post positive_result: result>=0 + double GetError(double *leftPoint, double *midPoint, + double *rightPoint, double alpha); + +protected: + vtkAttributesErrorMetric(); + virtual ~vtkAttributesErrorMetric(); + + // Description: + // Compute the square absolute attribute tolerance, only if the cached value + // is obsolete. + void ComputeSquareAbsoluteAttributeTolerance(); + + double AttributeTolerance; + + double SquareAbsoluteAttributeTolerance; // cached value computed from + // AttributeTolerance and active attribute/component + + double AbsoluteAttributeTolerance; + int DefinedByAbsolute; + + vtkTimeStamp SquareAbsoluteAttributeToleranceComputeTime; + + double Range; // cached value computed from active attribute/component + + vtkGenericAttributeCollection *AttributeCollection; + +private: + vtkAttributesErrorMetric(const vtkAttributesErrorMetric&); // Not implemented. + void operator=(const vtkAttributesErrorMetric&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkCachedStreamingDemandDrivenPipeline.cxx b/Filtering/vtkCachedStreamingDemandDrivenPipeline.cxx new file mode 100644 index 0000000..25d978d --- /dev/null +++ b/Filtering/vtkCachedStreamingDemandDrivenPipeline.cxx @@ -0,0 +1,337 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCachedStreamingDemandDrivenPipeline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCachedStreamingDemandDrivenPipeline.h" + +#include "vtkInformationIntegerKey.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkObjectFactory.h" + +#include "vtkAlgorithm.h" +#include "vtkAlgorithmOutput.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkCachedStreamingDemandDrivenPipeline, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkCachedStreamingDemandDrivenPipeline); + + +//---------------------------------------------------------------------------- +vtkCachedStreamingDemandDrivenPipeline +::vtkCachedStreamingDemandDrivenPipeline() +{ + this->CacheSize = 0; + this->Data = NULL; + this->Times = NULL; + + this->SetCacheSize(10); +} + +//---------------------------------------------------------------------------- +vtkCachedStreamingDemandDrivenPipeline +::~vtkCachedStreamingDemandDrivenPipeline() +{ + this->SetCacheSize(0); +} + +//---------------------------------------------------------------------------- +void vtkCachedStreamingDemandDrivenPipeline::SetCacheSize(int size) +{ + int idx; + + if (size == this->CacheSize) + { + return; + } + + this->Modified(); + + // free the old data + for (idx = 0; idx < this->CacheSize; ++idx) + { + if (this->Data[idx]) + { + this->Data[idx]->Delete(); + this->Data[idx] = NULL; + } + } + if (this->Data) + { + delete [] this->Data; + this->Data = NULL; + } + if (this->Times) + { + delete [] this->Times; + this->Times = NULL; + } + + this->CacheSize = size; + if (size == 0) + { + return; + } + + this->Data = new vtkDataObject* [size]; + this->Times = new unsigned long [size]; + + for (idx = 0; idx < size; ++idx) + { + this->Data[idx] = NULL; + this->Times[idx] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkCachedStreamingDemandDrivenPipeline +::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "CacheSize: " << this->CacheSize << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkCachedStreamingDemandDrivenPipeline::Update() +{ + return this->Superclass::Update(); +} + +//---------------------------------------------------------------------------- +int vtkCachedStreamingDemandDrivenPipeline::Update(int port) +{ + if(!this->UpdateInformation()) + { + return 0; + } + if(port >= 0 && port < this->Algorithm->GetNumberOfOutputPorts()) + { + int retval = 1; + // some streaming filters can request that the pipeline execute multiple + // times for a single update + do + { + retval = + this->PropagateUpdateExtent(port) && this->UpdateData(port) && retval; + } + while (this->ContinueExecuting); + return retval; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +int vtkCachedStreamingDemandDrivenPipeline +::NeedToExecuteData(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // If no port is specified, check all ports. This behavior is + // implemented by the superclass. + if(outputPort < 0) + { + return this->Superclass::NeedToExecuteData(outputPort, + inInfoVec, outInfoVec); + } + + // Does the superclass want to execute? We must skip our direct superclass + // because it looks at update extents but does not know about the cache + if(this->vtkDemandDrivenPipeline::NeedToExecuteData(outputPort, + inInfoVec, outInfoVec)) + { + return 1; + } + + // Has the algorithm asked to be executed again? + if(this->ContinueExecuting) + { + return 1; + } + + // First look through the cached data to see if it is still valid. + int i; + unsigned long pmt = this->GetPipelineMTime(); + for (i = 0; i < this->CacheSize; ++i) + { + if (this->Data[i] && this->Times[i] < pmt) + { + this->Data[i]->Delete(); + this->Data[i] = NULL; + this->Times[i] = 0; + } + } + + // We need to check the requested update extent. Get the output + // port information and data information. We do not need to check + // existence of values because it has already been verified by + // VerifyOutputInformation. + vtkInformation* outInfo = outInfoVec->GetInformationObject(outputPort); + vtkDataObject* dataObject = outInfo->Get(vtkDataObject::DATA_OBJECT()); + vtkInformation* dataInfo = dataObject->GetInformation(); + if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_PIECES_EXTENT) + { + int updatePiece = outInfo->Get(UPDATE_PIECE_NUMBER()); + int updateNumberOfPieces = outInfo->Get(UPDATE_NUMBER_OF_PIECES()); + int updateGhostLevel = outInfo->Get(UPDATE_NUMBER_OF_GHOST_LEVELS()); + + // check to see if any data in the cache fits this request + for (i = 0; i < this->CacheSize; ++i) + { + if (this->Data[i]) + { + dataInfo = this->Data[i]->GetInformation(); + + // Check the unstructured extent. If we do not have the requested + // piece, we need to execute. + int dataPiece = dataInfo->Get(vtkDataObject::DATA_PIECE_NUMBER()); + int dataNumberOfPieces = + dataInfo->Get(vtkDataObject::DATA_NUMBER_OF_PIECES()); + int dataGhostLevel = + dataInfo->Get(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS()); + if (dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == + VTK_PIECES_EXTENT && dataPiece == updatePiece && + dataNumberOfPieces == updateNumberOfPieces && + dataGhostLevel == updateGhostLevel) + { + // we have a matching data we must copy it to our output, but for + // now we don't support polydata + return 1; + } + } + } + } + else if (dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_3D_EXTENT) + { + // Check the structured extent. If the update extent is outside + // of the extent and not empty, we need to execute. + int dataExtent[6]; + int updateExtent[6]; + outInfo->Get(UPDATE_EXTENT(), updateExtent); + + // check to see if any data in the cache fits this request + for (i = 0; i < this->CacheSize; ++i) + { + if (this->Data[i]) + { + dataInfo = this->Data[i]->GetInformation(); + dataInfo->Get(vtkDataObject::DATA_EXTENT(), dataExtent); + if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == + VTK_3D_EXTENT && + !(updateExtent[0] < dataExtent[0] || + updateExtent[1] > dataExtent[1] || + updateExtent[2] < dataExtent[2] || + updateExtent[3] > dataExtent[3] || + updateExtent[4] < dataExtent[4] || + updateExtent[5] > dataExtent[5]) && + (updateExtent[0] <= updateExtent[1] && + updateExtent[2] <= updateExtent[3] && + updateExtent[4] <= updateExtent[5])) + { + // we have a match + // Pass this data to output. + vtkImageData *id = vtkImageData::SafeDownCast(dataObject); + vtkImageData *id2 = vtkImageData::SafeDownCast(this->Data[i]); + if (id && id2) + { + id->SetExtent(dataExtent); + id->GetPointData()->PassData(id2->GetPointData()); + // not sure if we need this + dataObject->DataHasBeenGenerated(); + return 0; + } + } + } + } + } + + // We do need to execute + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkCachedStreamingDemandDrivenPipeline +::ExecuteData(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // only works for one in one out algorithms + if (request->Get(FROM_OUTPUT_PORT()) != 0) + { + vtkErrorMacro("vtkCachedStreamingDemandDrivenPipeline can only be used for algorithms with one output and one input"); + return 0; + } + + // first do the ususal thing + int result = this->Superclass::ExecuteData(request, inInfoVec, outInfoVec); + + // then save the newly generated data + unsigned long bestTime = VTK_LARGE_INTEGER; + int bestIdx = 0; + + // Save the image in cache. + // Find a spot to put the data. + for (int i = 0; i < this->CacheSize; ++i) + { + if (this->Data[i] == NULL) + { + bestIdx = i; + bestTime = 0; + break; + } + if (this->Times[i] < bestTime) + { + bestIdx = i; + bestTime = this->Times[i]; + } + } + + vtkInformation* outInfo = outInfoVec->GetInformationObject(0); + vtkDataObject* dataObject = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if (this->Data[bestIdx] == NULL) + { + this->Data[bestIdx] = dataObject->NewInstance(); + } + this->Data[bestIdx]->ReleaseData(); + + vtkImageData *id = vtkImageData::SafeDownCast(dataObject); + if (id) + { + vtkInformation* inInfo = inInfoVec[0]->GetInformationObject(0); + vtkImageData *input = + vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + id->SetExtent(input->GetExtent()); + id->GetPointData()->PassData(input->GetPointData()); + id->DataHasBeenGenerated(); + } + + vtkImageData *id2 = vtkImageData::SafeDownCast(this->Data[bestIdx]); + if (id && id2) + { + id2->SetExtent(id->GetExtent()); + id2->SetScalarType(id->GetScalarType()); + id2->SetNumberOfScalarComponents( + id->GetNumberOfScalarComponents()); + id2->GetPointData()->SetScalars( + id->GetPointData()->GetScalars()); + } + + this->Times[bestIdx] = dataObject->GetUpdateTime(); + + return result; +} diff --git a/Filtering/vtkCachedStreamingDemandDrivenPipeline.h b/Filtering/vtkCachedStreamingDemandDrivenPipeline.h new file mode 100644 index 0000000..d437e30 --- /dev/null +++ b/Filtering/vtkCachedStreamingDemandDrivenPipeline.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCachedStreamingDemandDrivenPipeline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCachedStreamingDemandDrivenPipeline - +// .SECTION Description +// vtkCachedStreamingDemandDrivenPipeline + +#ifndef __vtkCachedStreamingDemandDrivenPipeline_h +#define __vtkCachedStreamingDemandDrivenPipeline_h + +#include "vtkStreamingDemandDrivenPipeline.h" + +class vtkInformationIntegerKey; +class vtkInformationIntegerVectorKey; +class vtkCachedStreamingDemandDrivenPipelineInternals; + +class VTK_FILTERING_EXPORT vtkCachedStreamingDemandDrivenPipeline : + public vtkStreamingDemandDrivenPipeline +{ +public: + static vtkCachedStreamingDemandDrivenPipeline* New(); + vtkTypeRevisionMacro(vtkCachedStreamingDemandDrivenPipeline, + vtkStreamingDemandDrivenPipeline); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Bring the algorithm's outputs up-to-date. + virtual int Update(); + virtual int Update(int port); + + // Description: + // This is the maximum number of images that can be retained in memory. + // it defaults to 10. + void SetCacheSize(int size); + vtkGetMacro(CacheSize, int); + +protected: + vtkCachedStreamingDemandDrivenPipeline(); + ~vtkCachedStreamingDemandDrivenPipeline(); + + virtual int NeedToExecuteData(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + virtual int ExecuteData(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + int CacheSize; + + vtkDataObject **Data; + unsigned long *Times; + +private: + vtkCachedStreamingDemandDrivenPipelineInternals* CachedStreamingDemandDrivenInternal; +private: + vtkCachedStreamingDemandDrivenPipeline(const vtkCachedStreamingDemandDrivenPipeline&); // Not implemented. + void operator=(const vtkCachedStreamingDemandDrivenPipeline&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkCardinalSpline.cxx b/Filtering/vtkCardinalSpline.cxx new file mode 100644 index 0000000..7330341 --- /dev/null +++ b/Filtering/vtkCardinalSpline.cxx @@ -0,0 +1,461 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCardinalSpline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCardinalSpline.h" + +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" + +vtkCxxRevisionMacro(vtkCardinalSpline, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkCardinalSpline); + +//---------------------------------------------------------------------------- +// Construct a Cardinal Spline. +vtkCardinalSpline::vtkCardinalSpline () +{ +} + +//---------------------------------------------------------------------------- +// Evaluate a 1D Spline +double vtkCardinalSpline::Evaluate (double t) +{ + int index; + double *intervals; + double *coefficients; + + // check to see if we need to recompute the spline + if (this->ComputeTime < this->GetMTime ()) + { + this->Compute (); + } + + // make sure we have at least 2 points + int size = this->PiecewiseFunction->GetSize (); + if (size < 2) + { + return 0.0; + } + + intervals = this->Intervals; + coefficients = this->Coefficients; + + if ( this->Closed ) + { + size = size + 1; + } + + // clamp the function at both ends + if (t < intervals[0]) + { + t = intervals[0]; + } + if (t > intervals[size - 1]) + { + t = intervals[size - 1]; + } + + // find pointer to cubic spline coefficient using bisection method + index = this->FindIndex(size,t); + + // calculate offset within interval + t = (t - intervals[index]); + + // evaluate intervals value y + return (t * (t * (t * *(coefficients + index * 4 + 3) + + *(coefficients + index * 4 + 2)) + + *(coefficients + index * 4 + 1)) + + *(coefficients + index * 4)); +} + +//---------------------------------------------------------------------------- +// Compute Cardinal Splines for each dependent variable +void vtkCardinalSpline::Compute () +{ + double *ts, *xs; + double *work; + double *coefficients; + double *dependent; + int size; + int i; + + // Make sure the function is up to date. + this->PiecewiseFunction->Update(); + + // get the size of the independent variables + size = this->PiecewiseFunction->GetSize (); + + if(size < 2) + { + vtkErrorMacro("Cannot compute a spline with less than 2 points. # of points is: " << size); + return; + } + + // copy the independent variables. Note that if the spline + // is closed the first and last point are assumed repeated - + // so we add and extra point + if (this->Intervals) + { + delete [] this->Intervals; + } + + if ( !this->Closed ) + { + this->Intervals = new double[size]; + ts = this->PiecewiseFunction->GetDataPointer (); + for (i = 0; i < size; i++) + { + this->Intervals[i] = *(ts + 2*i); + } + + // allocate memory for work arrays + work = new double[size]; + + // allocate memory for coefficients + if (this->Coefficients) + { + delete [] this->Coefficients; + } + this->Coefficients = new double [4*size]; + + // allocate memory for dependent variables + dependent = new double [size]; + + // get start of coefficients for this dependent variable + coefficients = this->Coefficients; + + // get the dependent variable values + xs = this->PiecewiseFunction->GetDataPointer () + 1; + for (int j = 0; j < size; j++) + { + *(dependent + j) = *(xs + 2*j); + } + + this->Fit1D (size, this->Intervals, dependent, + work, (double (*)[4])coefficients, + this->LeftConstraint, this->LeftValue, + this->RightConstraint, this->RightValue); + } + + else //add extra "fictitious" point to close loop + { + size = size + 1; + this->Intervals = new double[size]; + ts = this->PiecewiseFunction->GetDataPointer (); + for (i = 0; i < size-1; i++) + { + this->Intervals[i] = *(ts + 2*i); + } + if ( this->ParametricRange[0] != this->ParametricRange[1] ) + { + this->Intervals[size-1] = this->ParametricRange[1]; + } + else + { + this->Intervals[size-1] = this->Intervals[size-2] + 1.0; + } + + // allocate memory for work arrays + work = new double[size]; + + // allocate memory for coefficients + if (this->Coefficients) + { + delete [] this->Coefficients; + } + this->Coefficients = new double [4*size]; + + // allocate memory for dependent variables + dependent = new double [size]; + + // get start of coefficients for this dependent variable + coefficients = this->Coefficients; + + // get the dependent variable values + xs = this->PiecewiseFunction->GetDataPointer () + 1; + for (int j = 0; j < size-1; j++) + { + *(dependent + j) = *(xs + 2*j); + } + dependent[size-1] = *xs; + + this->FitClosed1D (size, this->Intervals, dependent, + work, (double (*)[4])coefficients); + } + + // free the work array and dependent variable storage + delete [] work; + delete [] dependent; + + // update compute time + this->ComputeTime = this->GetMTime(); +} + + +//---------------------------------------------------------------------------- +// Compute the coefficients for a 1D spline. The spline is open. +void vtkCardinalSpline::Fit1D (int size, double *x, double *y, + double *work, double coefficients[][4], + int leftConstraint, double leftValue, + int rightConstraint, double rightValue) +{ + double b = 0.0; + double xlk; + double xlkp; + int k; + + // develop constraint at leftmost point. + switch (leftConstraint) + { + case 0: + // desired slope at leftmost point is derivative from two points + coefficients[0][1] = 1.0; + coefficients[0][2] = 0.0; + work[0] = this->ComputeLeftDerivative(); + break; + case 1: + // desired slope at leftmost point is leftValue. + coefficients[0][1] = 1.0; + coefficients[0][2] = 0.0; + work[0] = leftValue; + break; + case 2: + // desired second derivative at leftmost point is leftValue. + coefficients[0][1] = 2.0; + coefficients[0][2] = 1.0; + work[0]= 3.0 * ((y[1] - y[0]) / (x[1] - x[0])) - + 0.5 * (x[1] - x[0]) * leftValue; + break; + case 3: + // desired second derivative at leftmost point is + // leftValue times second derivative at first interior point. + coefficients[0][1] = 2.0; + coefficients[0][2] = 4.0 * ((0.5 + leftValue) / + (2.0 + leftValue)); + work[0]= 6.0 * ((1.0 + leftValue) / (2.0 + leftValue)) * + ((y[1] - y[0]) / (x[1]-x[0])); + break; + } + + // develop body of band matrix. + for (k = 1; k < size - 1; k++) + { + xlk = x[k] - x[k-1]; + xlkp = x[k+1] - x[k]; + coefficients[k][0] = xlkp; + coefficients[k][1] = 2.0 * (xlkp + xlk); + coefficients[k][2] = xlk; + work[k] = 3.0 * (((xlkp * (y[k] - y[k-1])) / xlk) + + ((xlk * (y[k+1] - y[k])) / xlkp)); + } + + + // develop constraint at rightmost point. + switch (rightConstraint) + { + case 0: + // desired slope at leftmost point is derivative from two points + coefficients[size - 1][0] = 0.0; + coefficients[size - 1][1] = 1.0; + work[size - 1] = this->ComputeRightDerivative(); + break; + case 1: + // desired slope at rightmost point is rightValue + coefficients[size - 1][0] = 0.0; + coefficients[size - 1][1] = 1.0; + work[size - 1] = rightValue; + break; + case 2: + // desired second derivative at rightmost point is rightValue. + coefficients[size-1][0] = 1.0; + coefficients[size-1][1] = 2.0; + work[size-1] = 3.0 * ((y[size-1] - y[size-2]) / + (x[size-1] - x[size-2])) + + 0.5 * (x[size-1]-x[size-2]) * rightValue; + break; + case 3: + // desired second derivative at rightmost point is + // rightValue times second derivative at last interior point. + coefficients[size-1][0] = 4.0 * ((0.5 + rightValue) / + (2.0 + rightValue)); + coefficients[size-1][1] = 2.0; + work[size-1] = 6.0 * ((1.0 + rightValue) / (2.0 + rightValue)) * + ((y[size-1] - y[size-2]) / + (x[size-1] - x[size-2])); + break; + } + + // solve resulting set of equations. + coefficients[0][2] = coefficients[0][2] / coefficients[0][1]; + work[0] = work[0] / coefficients[0][1]; + coefficients[size-1][2] = 0.0; + + for (k = 1; k < size; k++) + { + coefficients[k][1] = coefficients[k][1] - (coefficients[k][0] * + coefficients[k-1][2]); + coefficients[k][2] = coefficients[k][2] / coefficients[k][1]; + work[k] = (work[k] - (coefficients[k][0] * work[k-1])) + / coefficients[k][1]; + } + + for (k = size - 2; k >= 0; k--) + { + work[k] = work[k] - (coefficients[k][2] * work[k+1]); + } + + // the column vector work now contains the first + // derivative of the spline function at each joint. + // compute the coefficients of the cubic between + // each pair of joints. + for (k = 0; k < size - 1; k++) + { + b = x[k+1] - x[k]; + coefficients[k][0] = y[k]; + coefficients[k][1] = work[k]; + coefficients[k][2] = (3.0 * (y[k+1] - y[k])) / (b * b) - + (work[k+1] + 2.0 * work[k]) / b; + coefficients[k][3] = (2.0 * (y[k] - y[k+1])) / (b * b * b) + + (work[k+1] + work[k]) / (b * b); + } + + // the coefficients of a fictitious nth cubic + // are evaluated. This may simplify + // algorithms which include both end points. + + coefficients[size-1][0] = y[size-1]; + coefficients[size-1][1] = work[size-1]; + coefficients[size-1][2] = coefficients[size-2][2] + + 3.0 * coefficients[size-2][3] * b; + coefficients[size-1][3] = coefficients[size-2][3]; + +} + +//---------------------------------------------------------------------------- +// Compute the coefficients for a 1D spline. The spline is closed +// (i.e., the first and last point are assumed the same) and the +// spline is continous in value and derivatives. +void vtkCardinalSpline::FitClosed1D (int size, double *x, double *y, + double *work, double coefficients[][4]) +{ + double b; + double xlk; + double xlkp; + int k; + double aN, bN, cN, dN; + int N; + + N = size - 1; + + // develop body of band matrix. + // + for (k = 1; k < N; k++) + { + xlk = x[k] - x[k-1]; + xlkp = x[k+1] - x[k]; + coefficients[k][0] = xlkp; + coefficients[k][1] = 2.0 * (xlkp + xlk); + coefficients[k][2] = xlk; + work[k] = 3.0 * (((xlkp * (y[k] - y[k-1])) / xlk) + + ((xlk * (y[k+1] - y[k])) / xlkp)); + } + + xlk = x[N] - x[N-1]; + xlkp = x[1] - x[0]; + aN = coefficients[N][0] = xlkp; + bN = coefficients[N][1] = 2.0 * (xlkp + xlk); + cN = coefficients[N][2] = xlk; + dN = work[N] = 3.0 * (((xlkp * (y[N] - y[N-1])) / xlk) + + ((xlk * (y[1] - y[0])) / xlkp)); + + // solve resulting set of equations. + // + coefficients[0][2] = 0.0; + work[0] = 0.0; + coefficients[0][3] = 1.0; + + for (k = 1; k <= N; k++) + { + coefficients[k][1] = coefficients[k][1] - + (coefficients[k][0] * coefficients[k-1][2]); + coefficients[k][2] = coefficients[k][2] / coefficients[k][1]; + work[k] = (work[k] - (coefficients[k][0] * work[k-1])) + / coefficients[k][1]; + coefficients[k][3] = (-1.0 * coefficients[k][0] * + coefficients[k-1][3]) / coefficients[k][1]; + } + + coefficients[N][0] = 1.0; + coefficients[N][1] = 0.0; + + for (k = N - 1; k > 0; k--) + { + coefficients[k][0] = coefficients[k][3] - + coefficients[k][2] * coefficients[k+1][0]; + coefficients[k][1] = work[k] - coefficients[k][2] * coefficients[k+1][1]; + } + + work[0] = work[N] = (dN - cN * coefficients[1][1] - + aN * coefficients[N-1][1]) / ( bN + + cN * coefficients[1][0] + aN * coefficients[N-1][0]); + + for (k=1; k < N; k++) + { + work[k] = coefficients[k][0] * work[N] + coefficients[k][1]; + } + + // the column vector work now contains the first + // derivative of the spline function at each joint. + // compute the coefficients of the cubic between + // each pair of joints. + for (k = 0; k < N; k++) + { + b = x[k+1] - x[k]; + coefficients[k][0] = y[k]; + coefficients[k][1] = work[k]; + coefficients[k][2] = (3.0 * (y[k+1] - y[k])) / (b * b) - + (work[k+1] + 2.0 * work[k]) / b; + coefficients[k][3] = (2.0 * (y[k] - y[k+1])) / (b * b * b) + + (work[k+1] + work[k]) / (b * b); + } + + + // the coefficients of a fictitious nth cubic + // are the same as the coefficients in the first interval + // + coefficients[N][0] = y[N]; + coefficients[N][1] = work[N]; + coefficients[N][2] = coefficients[0][2]; + coefficients[N][3] = coefficients[0][3]; +} + +//---------------------------------------------------------------------------- +void vtkCardinalSpline::DeepCopy(vtkSpline *s) +{ + vtkCardinalSpline *spline = vtkCardinalSpline::SafeDownCast(s); + + if ( spline != NULL ) + { + //nothing to do + } + + // Now do superclass + this->vtkSpline::DeepCopy(s); +} + +//---------------------------------------------------------------------------- +void vtkCardinalSpline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Filtering/vtkCardinalSpline.h b/Filtering/vtkCardinalSpline.h new file mode 100644 index 0000000..1ebc1e9 --- /dev/null +++ b/Filtering/vtkCardinalSpline.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCardinalSpline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCardinalSpline - computes an interpolating spline using a +// a Cardinal basis. + +// .SECTION Description +// vtkCardinalSpline is a concrete implementation of vtkSpline using a +// Cardinal basis. + +// .SECTION See Also +// vtkSpline vtkKochanekSpline + + +#ifndef __vtkCardinalSpline_h +#define __vtkCardinalSpline_h + +#include "vtkSpline.h" + +class VTK_FILTERING_EXPORT vtkCardinalSpline : public vtkSpline +{ +public: + static vtkCardinalSpline *New(); + + vtkTypeRevisionMacro(vtkCardinalSpline,vtkSpline); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Compute Cardinal Splines for each dependent variable + void Compute (); + + // Description: + // Evaluate a 1D cardinal spline. + virtual double Evaluate (double t); + + // Description: + // Deep copy of cardinal spline data. + virtual void DeepCopy(vtkSpline *s); + +protected: + vtkCardinalSpline(); + ~vtkCardinalSpline() {} + + void Fit1D (int n, double *x, double *y, double *w, double coefficients[][4], + int leftConstraint, double leftValue, int rightConstraint, + double rightValue); + + void FitClosed1D (int n, double *x, double *y, double *w, + double coefficients[][4]); + +private: + vtkCardinalSpline(const vtkCardinalSpline&); // Not implemented. + void operator=(const vtkCardinalSpline&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkCastToConcrete.cxx b/Filtering/vtkCastToConcrete.cxx new file mode 100644 index 0000000..d0a72de --- /dev/null +++ b/Filtering/vtkCastToConcrete.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCastToConcrete.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCastToConcrete.h" +#include "vtkPolyData.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkRectilinearGrid.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkCastToConcrete, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkCastToConcrete); + +int vtkCastToConcrete::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Casting to concrete type..."); + + output->ShallowCopy(input); + + return 1; +} + + +int vtkCastToConcrete::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()), + 6); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES())); + outInfo->Set(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkCastToConcrete::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkCastToConcrete.h b/Filtering/vtkCastToConcrete.h new file mode 100644 index 0000000..c7ab97b --- /dev/null +++ b/Filtering/vtkCastToConcrete.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCastToConcrete.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCastToConcrete - works around type-checking limitations +// .SECTION Description +// vtkCastToConcrete is a filter that works around type-checking limitations +// in the filter classes. Some filters generate abstract types on output, +// and cannot be connected to the input of filters requiring a concrete +// input type. For example, vtkElevationFilter generates vtkDataSet for output, +// and cannot be connected to vtkDecimate, because vtkDecimate requires +// vtkPolyData as input. This is true even though (in this example) the input +// to vtkElevationFilter is of type vtkPolyData, and you know the output of +// vtkElevationFilter is the same type as its input. +// +// vtkCastToConcrete performs run-time checking to insure that output type +// is of the right type. An error message will result if you try to cast +// an input type improperly. Otherwise, the filter performs the appropriate +// cast and returns the data. + +// .SECTION Caveats +// You must specify the input before you can get the output. Otherwise an +// error results. + +// .SECTION See Also +// vtkDataSetAlgorithm vtkPointSetToPointSetFilter + +#ifndef __vtkCastToConcrete_h +#define __vtkCastToConcrete_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_FILTERING_EXPORT vtkCastToConcrete : public vtkDataSetAlgorithm +{ + +public: + static vtkCastToConcrete *New(); + vtkTypeRevisionMacro(vtkCastToConcrete,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkCastToConcrete() {}; + ~vtkCastToConcrete() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); //insures compatibility; satisfies abstract api in vtkFilter + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); +private: + vtkCastToConcrete(const vtkCastToConcrete&); // Not implemented. + void operator=(const vtkCastToConcrete&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkCell.cxx b/Filtering/vtkCell.cxx new file mode 100644 index 0000000..4ccc04c --- /dev/null +++ b/Filtering/vtkCell.cxx @@ -0,0 +1,241 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCell.h" + +#include "vtkMath.h" +#include "vtkMarchingSquaresCases.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkCell, "$Revision: 1.1 $"); + +// Construct cell. +vtkCell::vtkCell() +{ + this->Points = vtkPoints::New(); + this->Points->SetDataTypeToDouble(); + this->PointIds = vtkIdList::New(); + // Consistent Register/Deletes (ShallowCopy uses Register.) + this->Points->Register(this); + this->Points->Delete(); + this->PointIds->Register(this); + this->PointIds->Delete(); +} + +vtkCell::~vtkCell() +{ + this->Points->UnRegister(this); + this->PointIds->UnRegister(this); +} + +// Instantiate cell from outside +// +void vtkCell::Initialize(int npts, vtkIdType *pts, vtkPoints *p) +{ + this->PointIds->Reset(); + this->Points->Reset(); + + for (int i=0; iPointIds->InsertId(i,pts[i]); + this->Points->InsertPoint(i,p->GetPoint(pts[i])); + } +} + +void vtkCell::ShallowCopy(vtkCell *c) +{ + this->Points->ShallowCopy(c->Points); + if ( this->PointIds ) + { + this->PointIds->UnRegister(this); + this->PointIds = c->PointIds; + this->PointIds->Register(this); + } +} + +void vtkCell::DeepCopy(vtkCell *c) +{ + this->Points->DeepCopy(c->Points); + this->PointIds->DeepCopy(c->PointIds); +} + +// Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Return pointer +// to array of six double values. +double *vtkCell::GetBounds () +{ + double x[3]; + int i, numPts=this->Points->GetNumberOfPoints(); + + if (numPts) + { + this->Points->GetPoint(0, x); + this->Bounds[0] = x[0]; + this->Bounds[2] = x[1]; + this->Bounds[4] = x[2]; + this->Bounds[1] = x[0]; + this->Bounds[3] = x[1]; + this->Bounds[5] = x[2]; + for (i=1; iPoints->GetPoint(i, x); + this->Bounds[0] = (x[0] < this->Bounds[0] ? x[0] : this->Bounds[0]); + this->Bounds[1] = (x[0] > this->Bounds[1] ? x[0] : this->Bounds[1]); + this->Bounds[2] = (x[1] < this->Bounds[2] ? x[1] : this->Bounds[2]); + this->Bounds[3] = (x[1] > this->Bounds[3] ? x[1] : this->Bounds[3]); + this->Bounds[4] = (x[2] < this->Bounds[4] ? x[2] : this->Bounds[4]); + this->Bounds[5] = (x[2] > this->Bounds[5] ? x[2] : this->Bounds[5]); + } + } + else + { + vtkMath::UninitializeBounds(this->Bounds); + } + return this->Bounds; +} + +// Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Copy result into +// user provided array. +void vtkCell::GetBounds(double bounds[6]) +{ + this->GetBounds(); + for (int i=0; i < 6; i++) + { + bounds[i] = this->Bounds[i]; + } +} + +// Compute Length squared of cell (i.e., bounding box diagonal squared). +double vtkCell::GetLength2 () +{ + double diff, l=0.0; + int i; + + this->GetBounds(); + for (i=0; i<3; i++) + { + diff = this->Bounds[2*i+1] - this->Bounds[2*i]; + l += diff * diff; + } + return l; +} + +// Return center of the cell in parametric coordinates. +// Note that the parametric center is not always located +// at (0.5,0.5,0.5). The return value is the subId that +// the center is in (if a composite cell). If you want the +// center in x-y-z space, invoke the EvaluateLocation() method. +int vtkCell::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = pcoords[2] = 0.5; + return 0; +} + +// This method works fine for all "rectangular" cells, not triangular +// and tetrahedral topologies. +double vtkCell::GetParametricDistance(double pcoords[3]) +{ + int i; + double pDist, pDistMax=0.0; + + for (i=0; i<3; i++) + { + if ( pcoords[i] < 0.0 ) + { + pDist = -pcoords[i]; + } + else if ( pcoords[i] > 1.0 ) + { + pDist = pcoords[i] - 1.0; + } + else //inside the cell in the parametric direction + { + pDist = 0.0; + } + if ( pDist > pDistMax ) + { + pDistMax = pDist; + } + } + return pDistMax; +} + + +void vtkCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int numIds=this->PointIds->GetNumberOfIds(); + + os << indent << "Number Of Points: " << numIds << "\n"; + + if ( numIds > 0 ) + { + double *bounds=this->GetBounds(); + + os << indent << "Bounds: \n"; + os << indent << " Xmin,Xmax: (" << bounds[0] << ", " << bounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << bounds[2] << ", " << bounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << bounds[4] << ", " << bounds[5] << ")\n"; + + os << indent << " Point ids are: "; + for (int i=0; i < numIds; i++) + { + os << this->PointIds->GetId(i); + if ( i && !(i % 12) ) + { + os << "\n\t"; + } + else + { + if ( i != (numIds-1) ) + { + os << ", "; + } + } + } + os << indent << "\n"; + } +} + +// Note: the following code is placed here to deal with cross-library +// symbol export and import on Microsoft compilers. +static vtkMarchingSquaresLineCases VTK_MARCHING_SQUARES_LINECASES[] = { + {{-1, -1, -1, -1, -1}}, + {{0, 3, -1, -1, -1}}, + {{1, 0, -1, -1, -1}}, + {{1, 3, -1, -1, -1}}, + {{2, 1, -1, -1, -1}}, + {{0, 3, 2, 1, -1}}, + {{2, 0, -1, -1, -1}}, + {{2, 3, -1, -1, -1}}, + {{3, 2, -1, -1, -1}}, + {{0, 2, -1, -1, -1}}, + {{1, 0, 3, 2, -1}}, + {{1, 2, -1, -1, -1}}, + {{3, 1, -1, -1, -1}}, + {{0, 1, -1, -1, -1}}, + {{3, 0, -1, -1, -1}}, + {{-1, -1, -1, -1, -1}} +}; + +vtkMarchingSquaresLineCases* vtkMarchingSquaresLineCases::GetCases() +{ + return VTK_MARCHING_SQUARES_LINECASES; +} + +// Usually overridden. Only composite cells do not override this. +double *vtkCell::GetParametricCoords() +{ + return static_cast(NULL); +} diff --git a/Filtering/vtkCell.h b/Filtering/vtkCell.h new file mode 100644 index 0000000..97a5eeb --- /dev/null +++ b/Filtering/vtkCell.h @@ -0,0 +1,308 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCell - abstract class to specify cell behavior +// .SECTION Description +// vtkCell is an abstract class that specifies the interfaces for data cells. +// Data cells are simple topological elements like points, lines, polygons, +// and tetrahedra of which visualization datasets are composed. In some +// cases visualization datasets may explicitly represent cells (e.g., +// vtkPolyData, vtkUnstructuredGrid), and in some cases, the datasets are +// implicitly composed of cells (e.g., vtkStructuredPoints). +// +// .SECTION Caveats +// The #define VTK_CELL_SIZE is a parameter used to construct cells and provide +// a general guideline for controlling object execution. This parameter is +// not a hard boundary: you can create cells with more points. + +// .SECTION See Also +// vtkHexahedron vtkLine vtkPixel vtkPolyLine vtkPolyVertex +// vtkPolygon vtkQuad vtkTetra vtkTriangle +// vtkTriangleStrip vtkVertex vtkVoxel vtkWedge vtkPyramid + +#ifndef __vtkCell_h +#define __vtkCell_h + +#define VTK_CELL_SIZE 512 +#define VTK_TOL 1.e-05 // Tolerance for geometric calculation + +#include "vtkObject.h" + +#include "vtkIdList.h" // Needed for inline methods +#include "vtkCellType.h" // Needed to define cell types + +class vtkCellArray; +class vtkCellData; +class vtkDataArray; +class vtkPointData; +class vtkPointLocator; +class vtkPoints; + +class VTK_FILTERING_EXPORT vtkCell : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCell,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initialize cell from outside with point ids and point + // coordinates specified. + void Initialize(int npts, vtkIdType *pts, vtkPoints *p); + + // Description: + // Copy this cell by reference counting the internal data structures. + // This is safe if you want a "read-only" copy. If you modify the cell + // you might wish to use DeepCopy(). + virtual void ShallowCopy(vtkCell *c); + + // Description: + // Copy this cell by completely copying internal data structures. This is + // slower but safer than ShallowCopy(). + virtual void DeepCopy(vtkCell *c); + + // Description: + // Return the type of cell. + virtual int GetCellType() = 0; + + // Description: + // Return the topological dimensional of the cell (0,1,2, or 3). + virtual int GetCellDimension() = 0; + + // Description: + // Non-linear cells require special treatment beyond the usual cell type + // and connectivity list information. Most cells in VTK are implicit + // cells. + virtual int IsLinear() {return 1;} + + // Description: + // Some cells require initialization prior to access. For example, they + // may have to triangulate themselves or set up internal data structures. + virtual int RequiresInitialization() {return 0;} + virtual void Initialize() {} + + // Description: + // Explicit cells require additional representational information + // beyond the usual cell type and connectivity list information. + // Most cells in VTK are implicit cells. + virtual int IsExplicitCell() {return 0;} + + // Description: + // Get the point coordinates for the cell. + vtkPoints *GetPoints() {return this->Points;} + + // Description: + // Return the number of points in the cell. + int GetNumberOfPoints() {return this->PointIds->GetNumberOfIds();} + + // Description: + // Return the number of edges in the cell. + virtual int GetNumberOfEdges() = 0; + + // Description: + // Return the number of faces in the cell. + virtual int GetNumberOfFaces() = 0; + + // Description: + // Return the list of point ids defining the cell. + vtkIdList *GetPointIds() {return this->PointIds;} + + // Description: + // For cell point i, return the actual point id. + vtkIdType GetPointId(int ptId) {return this->PointIds->GetId(ptId);} + + // Description: + // Return the edge cell from the edgeId of the cell. + virtual vtkCell *GetEdge(int edgeId) = 0; + + // Description: + // Return the face cell from the faceId of the cell. + virtual vtkCell *GetFace(int faceId) = 0; + + // Description: + // Given parametric coordinates of a point, return the closest cell + // boundary, and whether the point is inside or outside of the cell. The + // cell boundary is defined by a list of points (pts) that specify a face + // (3D cell), edge (2D cell), or vertex (1D cell). If the return value of + // the method is != 0, then the point is inside the cell. + virtual int CellBoundary(int subId, double pcoords[3], vtkIdList *pts) = 0; + + // Description: + // Given a point x[3] return inside(=1) or outside(=0) cell; evaluate + // parametric coordinates, sub-cell id (!=0 only if cell is composite), + // distance squared of point x[3] to cell (in particular, the sub-cell + // indicated), closest point on cell to x[3] (unless closestPoint is null, + // in which case, the closest point and dist2 are not found), and + // interpolation weights in cell. (The number of weights is equal to the + // number of points defining the cell). Note: on rare occasions a -1 is + // returned from the method. This means that numerical error has occurred + // and all data returned from this method should be ignored. Also, + // inside/outside is determine parametrically. That is, a point is inside + // if it satisfies parametric limits. This can cause problems for cells of + // topological dimension 2 or less, since a point in 3D can project onto + // the cell within parametric limits but be "far" from the cell. Thus the + // value dist2 may be checked to determine true in/out. + virtual int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) = 0; + + // Description: + // Determine global coordinate (x[3]) from subId and parametric coordinates. + // Also returns interpolation weights. (The number of weights is equal to + // the number of points in the cell.) + virtual void EvaluateLocation(int& subId, double pcoords[3], + double x[3], double *weights) = 0; + + // Description: + // Generate contouring primitives. The scalar list cellScalars are + // scalar values at each cell point. The point locator is essentially a + // points list that merges points as they are inserted (i.e., prevents + // duplicates). Contouring primitives can be vertices, lines, or + // polygons. It is possible to interpolate point data along the edge + // by providing input and output point data - if outPd is NULL, then + // no interpolation is performed. Also, if the output cell data is + // non-NULL, the cell data from the contoured cell is passed to the + // generated contouring primitives. (Note: the CopyAllocate() method + // must be invoked on both the output cell and point data. The + // cellId refers to the cell from which the cell data is copied.) + virtual void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) = 0; + + // Description: + // Cut (or clip) the cell based on the input cellScalars and the + // specified value. The output of the clip operation will be one or + // more cells of the same topological dimension as the original cell. + // The flag insideOut controls what part of the cell is considered inside - + // normally cell points whose scalar value is greater than "value" are + // considered inside. If insideOut is on, this is reversed. Also, if the + // output cell data is non-NULL, the cell data from the clipped cell is + // passed to the generated contouring primitives. (Note: the CopyAllocate() + // method must be invoked on both the output cell and point data. The + // cellId refers to the cell from which the cell data is copied.) + virtual void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *connectivity, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut) = 0; + + // Description: + // Intersect with a ray. Return parametric coordinates (both line and cell) + // and global intersection coordinates, given ray definition and tolerance. + // The method returns non-zero value if intersection occurs. + virtual int IntersectWithLine(double p1[3], double p2[3], + double tol, double& t, double x[3], + double pcoords[3], int& subId) = 0; + + // Description: + // Generate simplices of proper dimension. If cell is 3D, tetrahedron are + // generated; if 2D triangles; if 1D lines; if 0D points. The form of the + // output is a sequence of points, each n+1 points (where n is topological + // cell dimension) defining a simplex. The index is a parameter that controls + // which triangulation to use (if more than one is possible). If numerical + // degeneracy encountered, 0 is returned, otherwise 1 is returned. + // This method does not insert new points: all the points that define the + // simplices are the points that define the cell. + virtual int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts) = 0; + + // Description: + // Compute derivatives given cell subId and parametric coordinates. The + // values array is a series of data value(s) at the cell points. There is a + // one-to-one correspondence between cell point and data value(s). Dim is + // the number of data values per cell point. Derivs are derivatives in the + // x-y-z coordinate directions for each data value. Thus, if computing + // derivatives for a scalar function in a hexahedron, dim=1, 8 values are + // supplied, and 3 deriv values are returned (i.e., derivatives in x-y-z + // directions). On the other hand, if computing derivatives of velocity + // (vx,vy,vz) dim=3, 24 values are supplied ((vx,vy,vz)1, (vx,vy,vz)2, + // ....()8), and 9 deriv values are returned + // ((d(vx)/dx),(d(vx)/dy),(d(vx)/dz), (d(vy)/dx),(d(vy)/dy), (d(vy)/dz), + // (d(vz)/dx),(d(vz)/dy),(d(vz)/dz)). + virtual void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs) = 0; + + + // Description: + // Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Copy result + // into user provided array. + void GetBounds(double bounds[6]); + + + // Description: + // Compute cell bounding box (xmin,xmax,ymin,ymax,zmin,zmax). Return pointer + // to array of six double values. + double *GetBounds(); + + + // Description: + // Compute Length squared of cell (i.e., bounding box diagonal squared). + double GetLength2(); + + + // Description: + // Return center of the cell in parametric coordinates. Note that the + // parametric center is not always located at (0.5,0.5,0.5). The return + // value is the subId that the center is in (if a composite cell). If you + // want the center in x-y-z space, invoke the EvaluateLocation() method. + virtual int GetParametricCenter(double pcoords[3]); + + + // Description: + // Return the distance of the parametric coordinate provided to the + // cell. If inside the cell, a distance of zero is returned. This is + // used during picking to get the correct cell picked. (The tolerance + // will occasionally allow cells to be picked who are not really + // intersected "inside" the cell.) + virtual double GetParametricDistance(double pcoords[3]); + + + // Description: + // Return whether this cell type has a fixed topology or whether the + // topology varies depending on the data (e.g., vtkConvexPointSet). + // This compares to composite cells that are typically composed of + // primary cells (e.g., a triangle strip composite cell is made up of + // triangle primary cells). + virtual int IsPrimaryCell() {return 1;} + + + // Description: + // Return a contiguous array of parametric coordinates of the points + // defining this cell. In other words, (px,py,pz, px,py,pz, etc..) The + // coordinates are ordered consistent with the definition of the point + // ordering for the cell. This method returns a non-NULL pointer when + // the cell is a primary type (i.e., IsPrimaryCell() is true). Note that + // 3D parametric coordinates are returned no matter what the topological + // dimension of the cell. + virtual double *GetParametricCoords(); + + // left public for quick computational access + vtkPoints *Points; + vtkIdList *PointIds; + +protected: + vtkCell(); + ~vtkCell(); + + double Bounds[6]; + +private: + vtkCell(const vtkCell&); // Not implemented. + void operator=(const vtkCell&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkCell3D.cxx b/Filtering/vtkCell3D.cxx new file mode 100644 index 0000000..d676b53 --- /dev/null +++ b/Filtering/vtkCell3D.cxx @@ -0,0 +1,698 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCell3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCell3D.h" + +#include "vtkOrderedTriangulator.h" +#include "vtkPointLocator.h" +#include "vtkMarchingCubesCases.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkTetra.h" +#include "vtkPoints.h" +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" + +vtkCxxRevisionMacro(vtkCell3D, "$Revision: 1.1 $"); + +vtkCell3D::vtkCell3D() +{ + this->Triangulator = NULL; + this->MergeTolerance = 0.01; + this->ClipTetra = NULL; + this->ClipScalars = NULL; +} + +vtkCell3D::~vtkCell3D() +{ + if ( this->Triangulator ) + { + this->Triangulator->Delete(); + this->Triangulator = NULL; + } + if ( this->ClipTetra ) + { + this->ClipTetra->Delete(); + this->ClipTetra = NULL; + this->ClipScalars->Delete(); + this->ClipScalars = NULL; + } +} + +void vtkCell3D::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + int numPts=this->GetNumberOfPoints(); + int numEdges=this->GetNumberOfEdges(); + int *tets, v1, v2; + int i, j; + int type; + vtkIdType id, ptId; + vtkIdType internalId[VTK_CELL_SIZE]; + double s1, s2, x[3], t, p1[3], p2[3], deltaScalar; + + // Create a triangulator if necessary. + if ( ! this->Triangulator ) + { + this->Triangulator = vtkOrderedTriangulator::New(); + this->Triangulator->PreSortedOff(); + this->Triangulator->UseTemplatesOn(); + this->ClipTetra = vtkTetra::New(); + this->ClipScalars = vtkDoubleArray::New(); + this->ClipScalars->SetNumberOfTuples(4); + } + + // If here, the ordered triangulator is going to be used so the triangulation + // has to be initialized. + this->Triangulator->InitTriangulation(0.0,1.0, 0.0,1.0, 0.0,1.0, + (numPts + numEdges)); + + // Cells with fixed topology are triangulated with templates. + double *p, *pPtr = this->GetParametricCoords(); + if ( this->IsPrimaryCell() ) + { + // Some cell types support templates for interior clipping. Templates + // are a heck of a lot faster. + type = 0; //inside + for (p=pPtr, i=0; iPointIds->GetId(i); + this->Points->GetPoint(i, x); + this->Triangulator->InsertPoint(ptId, x, p, type); + }//for all cell points of fixed topology + + this->Triangulator->TemplateTriangulate(this->GetCellType(), + numPts,numEdges); + + // Otherwise we have produced tetrahedra and now contour these using + // the faster vtkTetra::Contour() method. + for ( this->Triangulator->InitTetraTraversal(); + this->Triangulator->GetNextTetra(0,this->ClipTetra, + cellScalars,this->ClipScalars);) + { + this->ClipTetra->Contour(value, this->ClipScalars, locator, + verts, lines, polys, inPd, outPd, inCd, + cellId, outCd); + } + return; + } //if we are clipping fixed topology + + // If here we're left with a non-fixed topology cell (e.g. convex point set). + // Inject cell points into triangulation. Recall that the PreSortedOff() + // flag was set which means that the triangulator will order the points + // according to point id. + for (p=pPtr, i=0; iPointIds->GetId(i); + + // Currently all points are injected because of the possibility + // of intersection point merging. + s1 = cellScalars->GetComponent(i,0); + if ( (s1 >= value) || (s1 < value) ) + { + type = 0; //inside + } + else + { + type = 4; //outside, its type might change later (nearby intersection) + } + + this->Points->GetPoint(i, x); + if ( locator->InsertUniquePoint(x, id) ) + { + outPd->CopyData(inPd,ptId, id); + } + internalId[i] = this->Triangulator->InsertPoint(id, x, p, type); + }//for all points + + // For each edge intersection point, insert into triangulation. Edge + // intersections come from contouring value. Have to be careful of + // intersections near exisiting points (causes bad Delaunay behavior). + // Intersections near existing points are collapsed to existing point. + double pc[3], *pc1, *pc2; + for (int edgeNum=0; edgeNum < numEdges; edgeNum++) + { + this->GetEdgePoints(edgeNum, tets); + + // Calculate a preferred interpolation direction. + // Has to be done in same direction to insure coincident points are + // merged (different interpolation direction causes pertubations). + s1 = cellScalars->GetComponent(tets[0],0); + s2 = cellScalars->GetComponent(tets[1],0); + + if ( (s1 <= value && s2 >= value) || (s1 >= value && s2 <= value) ) + { + deltaScalar = s2 - s1; + + if (deltaScalar > 0) + { + v1 = tets[0]; v2 = tets[1]; + } + else + { + v1 = tets[1]; v2 = tets[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + (value - cellScalars->GetComponent(v1,0)) / deltaScalar ); + + if ( t < this->MergeTolerance ) + { + this->Triangulator->UpdatePointType(internalId[v1], 2); + continue; + } + else if ( t > (1.0 - this->MergeTolerance) ) + { + this->Triangulator->UpdatePointType(internalId[v2], 2); + continue; + } + + this->Points->GetPoint(v1, p1); + this->Points->GetPoint(v2, p2); + pc1 = pPtr + 3*v1; + pc2 = pPtr + 3*v2; + + for (j=0; j<3; j++) + { + x[j] = p1[j] + t*(p2[j] - p1[j]); + pc[j] = pc1[j] + t*(pc2[j] - pc1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + if ( locator->InsertUniquePoint(x, ptId) ) + { + outPd->InterpolateEdge(inPd, ptId, this->PointIds->GetId(v1), + this->PointIds->GetId(v2), t); + } + + //Insert intersection point into Delaunay triangulation + this->Triangulator->InsertPoint(ptId,x,pc,2); + + }//if edge intersects value + }//for all edges + + // triangulate the points + this->Triangulator->Triangulate(); + + // Add the triangulation to the mesh + this->Triangulator->AddTetras(0,polys); + +} + +void vtkCell3D::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, + vtkCellData *outCD, int insideOut) +{ + vtkCell3D *cell3D = (vtkCell3D *)this; //has to be to be in this method + int numPts=this->GetNumberOfPoints(); + int numEdges=this->GetNumberOfEdges(); + int *verts, v1, v2; + int i, j; + int type; + vtkIdType id, ptId; + vtkIdType internalId[VTK_CELL_SIZE]; + double s1, s2, x[3], t, p1[3], p2[3], deltaScalar; + int allInside=1, allOutside=1; + + // Create a triangulator if necessary. + if ( ! this->Triangulator ) + { + this->Triangulator = vtkOrderedTriangulator::New(); + this->Triangulator->PreSortedOff(); + this->Triangulator->UseTemplatesOn(); + this->ClipTetra = vtkTetra::New(); + this->ClipScalars = vtkDoubleArray::New(); + this->ClipScalars->SetNumberOfTuples(4); + } + + // Make sure it's worth continuing by treating the interior and exterior + // cases as special cases. + for (i=0; iGetComponent(i,0); + if ( (s1 >= value && !insideOut) || (s1 < value && insideOut) ) + { + allOutside = 0; + } + else + { + allInside = 0; + } + } + + if ( allOutside ) + { + return; + } + + // If here, the ordered triangulator is going to be used so the triangulation + // has to be initialized. + this->Triangulator->InitTriangulation(0.0,1.0, 0.0,1.0, 0.0,1.0, + (numPts + numEdges)); + + // Cells with fixed topology are triangulated with templates. + double *p, *pPtr = this->GetParametricCoords(); + if ( this->IsPrimaryCell() ) + { + // Some cell types support templates for interior clipping. Templates + // are a heck of a lot faster. + type = 0; //inside + for (p=pPtr, i=0; iPointIds->GetId(i); + this->Points->GetPoint(i, x); + if ( locator->InsertUniquePoint(x, id) ) + { + outPD->CopyData(inPD,ptId, id); + } + this->Triangulator->InsertPoint(id, x, p, type); + }//for all cell points of fixed topology + + this->Triangulator->TemplateTriangulate(this->GetCellType(), + numPts,numEdges); + // If the cell is interior we are done. + if ( allInside ) + { + vtkIdType numTetras = tets->GetNumberOfCells(); + this->Triangulator->AddTetras(0,tets); + vtkIdType numAddedTetras = tets->GetNumberOfCells() - numTetras; + for (j=0; jCopyData(inCD, cellId, numTetras+j); + } + } + // Otherwise we have produced tetrahedra and now clip these using + // the faster vtkTetra::Clip() method. + else + { + for ( this->Triangulator->InitTetraTraversal(); + this->Triangulator->GetNextTetra(0,this->ClipTetra, + cellScalars,this->ClipScalars);) + { + // VERY IMPORTANT: Notice that the outPD is used twice. This is because the + // tetra has been defined in terms of point ids that are defined in the + // output (because of the templates). + this->ClipTetra->Clip(value, this->ClipScalars, locator, tets, outPD, + outPD, inCD, cellId, outCD, insideOut); + } + }//if boundary cell + return; + } //if we are clipping fixed topology + + // If here we're left with a non-fixed topology cell (e.g. convex point set). + // Inject cell points into triangulation. Recall that the PreSortedOff() + // flag was set which means that the triangulator will order the points + // according to point id. + for (p=pPtr, i=0; iPointIds->GetId(i); + + // Currently all points are injected because of the possibility + // of intersection point merging. + s1 = cellScalars->GetComponent(i,0); + if ( (s1 >= value && !insideOut) || (s1 < value && insideOut) ) + { + type = 0; //inside + } + else + { + type = 4; //outside, its type might change later (nearby intersection) + } + + this->Points->GetPoint(i, x); + if ( locator->InsertUniquePoint(x, id) ) + { + outPD->CopyData(inPD,ptId, id); + } + internalId[i] = this->Triangulator->InsertPoint(id, x, p, type); + }//for all points + + // For each edge intersection point, insert into triangulation. Edge + // intersections come from clipping value. Have to be careful of + // intersections near exisiting points (causes bad Delaunay behavior). + // Intersections near existing points are collapsed to existing point. + double pc[3], *pc1, *pc2; + for (int edgeNum=0; edgeNum < numEdges; edgeNum++) + { + cell3D->GetEdgePoints(edgeNum, verts); + + // Calculate a preferred interpolation direction. + // Has to be done in same direction to insure coincident points are + // merged (different interpolation direction causes pertubations). + s1 = cellScalars->GetComponent(verts[0],0); + s2 = cellScalars->GetComponent(verts[1],0); + + if ( (s1 <= value && s2 >= value) || (s1 >= value && s2 <= value) ) + { + deltaScalar = s2 - s1; + + if (deltaScalar > 0) + { + v1 = verts[0]; v2 = verts[1]; + } + else + { + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + (value - cellScalars->GetComponent(v1,0)) / deltaScalar ); + + if ( t < this->MergeTolerance ) + { + this->Triangulator->UpdatePointType(internalId[v1], 2); + continue; + } + else if ( t > (1.0 - this->MergeTolerance) ) + { + this->Triangulator->UpdatePointType(internalId[v2], 2); + continue; + } + + this->Points->GetPoint(v1, p1); + this->Points->GetPoint(v2, p2); + pc1 = pPtr + 3*v1; + pc2 = pPtr + 3*v2; + + for (j=0; j<3; j++) + { + x[j] = p1[j] + t*(p2[j] - p1[j]); + pc[j] = pc1[j] + t*(pc2[j] - pc1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + if ( locator->InsertUniquePoint(x, ptId) ) + { + outPD->InterpolateEdge(inPD, ptId, this->PointIds->GetId(v1), + this->PointIds->GetId(v2), t); + } + + //Insert intersection point into Delaunay triangulation + this->Triangulator->InsertPoint(ptId,x,pc,2); + + }//if edge intersects value + }//for all edges + + // triangulate the points + this->Triangulator->Triangulate(); + + // Add the triangulation to the mesh + this->Triangulator->AddTetras(0,tets); +} + +void vtkCell3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Merge Tolerance: " << this->MergeTolerance << "\n"; +} + +// Note: the following code is placed here to deal with cross-library +// symbol export and import on Microsoft compilers. + +// +// Edges to intersect. Three at a time form a triangle. Comments at +// end of line indicate case number (0->255) and base case number (0->15). +// +static vtkMarchingCubesTriangleCases VTK_MARCHING_CUBES_TRICASES[] = { +{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 0 0 */ +{{ 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 1 1 */ +{{ 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 2 1 */ +{{ 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 3 2 */ +{{ 1, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 4 1 */ +{{ 0, 3, 8, 1, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 5 3 */ +{{ 9, 11, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 6 2 */ +{{ 2, 3, 8, 2, 8, 11, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}}, /* 7 5 */ +{{ 3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 8 1 */ +{{ 0, 2, 10, 8, 0, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 9 2 */ +{{ 1, 0, 9, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 10 3 */ +{{ 1, 2, 10, 1, 10, 9, 9, 10, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 11 5 */ +{{ 3, 1, 11, 10, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 12 2 */ +{{ 0, 1, 11, 0, 11, 8, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}}, /* 13 5 */ +{{ 3, 0, 9, 3, 9, 10, 10, 9, 11, -1, -1, -1, -1, -1, -1, -1}}, /* 14 5 */ +{{ 9, 11, 8, 11, 10, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 15 8 */ +{{ 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 16 1 */ +{{ 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 17 2 */ +{{ 0, 9, 1, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 18 3 */ +{{ 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 19 5 */ +{{ 1, 11, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 20 4 */ +{{ 3, 7, 4, 3, 4, 0, 1, 11, 2, -1, -1, -1, -1, -1, -1, -1}}, /* 21 7 */ +{{ 9, 11, 2, 9, 2, 0, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 22 7 */ +{{ 2, 9, 11, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}}, /* 23 14 */ +{{ 8, 7, 4, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 24 3 */ +{{10, 7, 4, 10, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}}, /* 25 5 */ +{{ 9, 1, 0, 8, 7, 4, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 26 6 */ +{{ 4, 10, 7, 9, 10, 4, 9, 2, 10, 9, 1, 2, -1, -1, -1, -1}}, /* 27 9 */ +{{ 3, 1, 11, 3, 11, 10, 7, 4, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 28 7 */ +{{ 1, 11, 10, 1, 10, 4, 1, 4, 0, 7, 4, 10, -1, -1, -1, -1}}, /* 29 11 */ +{{ 4, 8, 7, 9, 10, 0, 9, 11, 10, 10, 3, 0, -1, -1, -1, -1}}, /* 30 12 */ +{{ 4, 10, 7, 4, 9, 10, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}}, /* 31 5 */ +{{ 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 32 1 */ +{{ 9, 4, 5, 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 33 3 */ +{{ 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 34 2 */ +{{ 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}}, /* 35 5 */ +{{ 1, 11, 2, 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 36 3 */ +{{ 3, 8, 0, 1, 11, 2, 4, 5, 9, -1, -1, -1, -1, -1, -1, -1}}, /* 37 6 */ +{{ 5, 11, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}}, /* 38 5 */ +{{ 2, 5, 11, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}}, /* 39 9 */ +{{ 9, 4, 5, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 40 4 */ +{{ 0, 2, 10, 0, 10, 8, 4, 5, 9, -1, -1, -1, -1, -1, -1, -1}}, /* 41 7 */ +{{ 0, 4, 5, 0, 5, 1, 2, 10, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 42 7 */ +{{ 2, 5, 1, 2, 8, 5, 2, 10, 8, 4, 5, 8, -1, -1, -1, -1}}, /* 43 11 */ +{{11, 10, 3, 11, 3, 1, 9, 4, 5, -1, -1, -1, -1, -1, -1, -1}}, /* 44 7 */ +{{ 4, 5, 9, 0, 1, 8, 8, 1, 11, 8, 11, 10, -1, -1, -1, -1}}, /* 45 12 */ +{{ 5, 0, 4, 5, 10, 0, 5, 11, 10, 10, 3, 0, -1, -1, -1, -1}}, /* 46 14 */ +{{ 5, 8, 4, 5, 11, 8, 11, 10, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 47 5 */ +{{ 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 48 2 */ +{{ 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 49 5 */ +{{ 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}}, /* 50 5 */ +{{ 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 51 8 */ +{{ 9, 8, 7, 9, 7, 5, 11, 2, 1, -1, -1, -1, -1, -1, -1, -1}}, /* 52 7 */ +{{11, 2, 1, 9, 0, 5, 5, 0, 3, 5, 3, 7, -1, -1, -1, -1}}, /* 53 12 */ +{{ 8, 2, 0, 8, 5, 2, 8, 7, 5, 11, 2, 5, -1, -1, -1, -1}}, /* 54 11 */ +{{ 2, 5, 11, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}}, /* 55 5 */ +{{ 7, 5, 9, 7, 9, 8, 3, 2, 10, -1, -1, -1, -1, -1, -1, -1}}, /* 56 7 */ +{{ 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 10, 7, -1, -1, -1, -1}}, /* 57 14 */ +{{ 2, 10, 3, 0, 8, 1, 1, 8, 7, 1, 7, 5, -1, -1, -1, -1}}, /* 58 12 */ +{{10, 1, 2, 10, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}}, /* 59 5 */ +{{ 9, 8, 5, 8, 7, 5, 11, 3, 1, 11, 10, 3, -1, -1, -1, -1}}, /* 60 10 */ +{{ 5, 0, 7, 5, 9, 0, 7, 0, 10, 1, 11, 0, 10, 0, 11, -1}}, /* 61 7 */ +{{10, 0, 11, 10, 3, 0, 11, 0, 5, 8, 7, 0, 5, 0, 7, -1}}, /* 62 7 */ +{{10, 5, 11, 7, 5, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 63 2 */ +{{11, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 64 1 */ +{{ 0, 3, 8, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 65 4 */ +{{ 9, 1, 0, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 66 3 */ +{{ 1, 3, 8, 1, 8, 9, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1}}, /* 67 7 */ +{{ 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 68 2 */ +{{ 1, 5, 6, 1, 6, 2, 3, 8, 0, -1, -1, -1, -1, -1, -1, -1}}, /* 69 7 */ +{{ 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}}, /* 70 5 */ +{{ 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}}, /* 71 11 */ +{{ 2, 10, 3, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 72 3 */ +{{10, 8, 0, 10, 0, 2, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 73 7 */ +{{ 0, 9, 1, 2, 10, 3, 5, 6, 11, -1, -1, -1, -1, -1, -1, -1}}, /* 74 6 */ +{{ 5, 6, 11, 1, 2, 9, 9, 2, 10, 9, 10, 8, -1, -1, -1, -1}}, /* 75 12 */ +{{ 6, 10, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}}, /* 76 5 */ +{{ 0, 10, 8, 0, 5, 10, 0, 1, 5, 5, 6, 10, -1, -1, -1, -1}}, /* 77 14 */ +{{ 3, 6, 10, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}}, /* 78 9 */ +{{ 6, 9, 5, 6, 10, 9, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}}, /* 79 5 */ +{{ 5, 6, 11, 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 80 3 */ +{{ 4, 0, 3, 4, 3, 7, 6, 11, 5, -1, -1, -1, -1, -1, -1, -1}}, /* 81 7 */ +{{ 1, 0, 9, 5, 6, 11, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 82 6 */ +{{11, 5, 6, 1, 7, 9, 1, 3, 7, 7, 4, 9, -1, -1, -1, -1}}, /* 83 12 */ +{{ 6, 2, 1, 6, 1, 5, 4, 8, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 84 7 */ +{{ 1, 5, 2, 5, 6, 2, 3, 4, 0, 3, 7, 4, -1, -1, -1, -1}}, /* 85 10 */ +{{ 8, 7, 4, 9, 5, 0, 0, 5, 6, 0, 6, 2, -1, -1, -1, -1}}, /* 86 12 */ +{{ 7, 9, 3, 7, 4, 9, 3, 9, 2, 5, 6, 9, 2, 9, 6, -1}}, /* 87 7 */ +{{ 3, 2, 10, 7, 4, 8, 11, 5, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 88 6 */ +{{ 5, 6, 11, 4, 2, 7, 4, 0, 2, 2, 10, 7, -1, -1, -1, -1}}, /* 89 12 */ +{{ 0, 9, 1, 4, 8, 7, 2, 10, 3, 5, 6, 11, -1, -1, -1, -1}}, /* 90 13 */ +{{ 9, 1, 2, 9, 2, 10, 9, 10, 4, 7, 4, 10, 5, 6, 11, -1}}, /* 91 6 */ +{{ 8, 7, 4, 3, 5, 10, 3, 1, 5, 5, 6, 10, -1, -1, -1, -1}}, /* 92 12 */ +{{ 5, 10, 1, 5, 6, 10, 1, 10, 0, 7, 4, 10, 0, 10, 4, -1}}, /* 93 7 */ +{{ 0, 9, 5, 0, 5, 6, 0, 6, 3, 10, 3, 6, 8, 7, 4, -1}}, /* 94 6 */ +{{ 6, 9, 5, 6, 10, 9, 4, 9, 7, 7, 9, 10, -1, -1, -1, -1}}, /* 95 3 */ +{{11, 9, 4, 6, 11, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 96 2 */ +{{ 4, 6, 11, 4, 11, 9, 0, 3, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 97 7 */ +{{11, 1, 0, 11, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 98 5 */ +{{ 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 11, 1, -1, -1, -1, -1}}, /* 99 14 */ +{{ 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 100 5 */ +{{ 3, 8, 0, 1, 9, 2, 2, 9, 4, 2, 4, 6, -1, -1, -1, -1}}, /* 101 12 */ +{{ 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 102 8 */ +{{ 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}}, /* 103 5 */ +{{11, 9, 4, 11, 4, 6, 10, 3, 2, -1, -1, -1, -1, -1, -1, -1}}, /* 104 7 */ +{{ 0, 2, 8, 2, 10, 8, 4, 11, 9, 4, 6, 11, -1, -1, -1, -1}}, /* 105 10 */ +{{ 3, 2, 10, 0, 6, 1, 0, 4, 6, 6, 11, 1, -1, -1, -1, -1}}, /* 106 12 */ +{{ 6, 1, 4, 6, 11, 1, 4, 1, 8, 2, 10, 1, 8, 1, 10, -1}}, /* 107 7 */ +{{ 9, 4, 6, 9, 6, 3, 9, 3, 1, 10, 3, 6, -1, -1, -1, -1}}, /* 108 11 */ +{{ 8, 1, 10, 8, 0, 1, 10, 1, 6, 9, 4, 1, 6, 1, 4, -1}}, /* 109 7 */ +{{ 3, 6, 10, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 110 5 */ +{{ 6, 8, 4, 10, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 111 2 */ +{{ 7, 6, 11, 7, 11, 8, 8, 11, 9, -1, -1, -1, -1, -1, -1, -1}}, /* 112 5 */ +{{ 0, 3, 7, 0, 7, 11, 0, 11, 9, 6, 11, 7, -1, -1, -1, -1}}, /* 113 11 */ +{{11, 7, 6, 1, 7, 11, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}}, /* 114 9 */ +{{11, 7, 6, 11, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 115 5 */ +{{ 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}}, /* 116 14 */ +{{ 2, 9, 6, 2, 1, 9, 6, 9, 7, 0, 3, 9, 7, 9, 3, -1}}, /* 117 7 */ +{{ 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}}, /* 118 5 */ +{{ 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 119 2 */ +{{ 2, 10, 3, 11, 8, 6, 11, 9, 8, 8, 7, 6, -1, -1, -1, -1}}, /* 120 12 */ +{{ 2, 7, 0, 2, 10, 7, 0, 7, 9, 6, 11, 7, 9, 7, 11, -1}}, /* 121 7 */ +{{ 1, 0, 8, 1, 8, 7, 1, 7, 11, 6, 11, 7, 2, 10, 3, -1}}, /* 122 6 */ +{{10, 1, 2, 10, 7, 1, 11, 1, 6, 6, 1, 7, -1, -1, -1, -1}}, /* 123 3 */ +{{ 8, 6, 9, 8, 7, 6, 9, 6, 1, 10, 3, 6, 1, 6, 3, -1}}, /* 124 7 */ +{{ 0, 1, 9, 10, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 125 4 */ +{{ 7, 0, 8, 7, 6, 0, 3, 0, 10, 10, 0, 6, -1, -1, -1, -1}}, /* 126 3 */ +{{ 7, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 127 1 */ +{{ 7, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 128 1 */ +{{ 3, 8, 0, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 129 3 */ +{{ 0, 9, 1, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 130 4 */ +{{ 8, 9, 1, 8, 1, 3, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 131 7 */ +{{11, 2, 1, 6, 7, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 132 3 */ +{{ 1, 11, 2, 3, 8, 0, 6, 7, 10, -1, -1, -1, -1, -1, -1, -1}}, /* 133 6 */ +{{ 2, 0, 9, 2, 9, 11, 6, 7, 10, -1, -1, -1, -1, -1, -1, -1}}, /* 134 7 */ +{{ 6, 7, 10, 2, 3, 11, 11, 3, 8, 11, 8, 9, -1, -1, -1, -1}}, /* 135 12 */ +{{ 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 136 2 */ +{{ 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}}, /* 137 5 */ +{{ 2, 6, 7, 2, 7, 3, 0, 9, 1, -1, -1, -1, -1, -1, -1, -1}}, /* 138 7 */ +{{ 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}}, /* 139 14 */ +{{11, 6, 7, 11, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 140 5 */ +{{11, 6, 7, 1, 11, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}}, /* 141 9 */ +{{ 0, 7, 3, 0, 11, 7, 0, 9, 11, 6, 7, 11, -1, -1, -1, -1}}, /* 142 11 */ +{{ 7, 11, 6, 7, 8, 11, 8, 9, 11, -1, -1, -1, -1, -1, -1, -1}}, /* 143 5 */ +{{ 6, 4, 8, 10, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 144 2 */ +{{ 3, 10, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 145 5 */ +{{ 8, 10, 6, 8, 6, 4, 9, 1, 0, -1, -1, -1, -1, -1, -1, -1}}, /* 146 7 */ +{{ 9, 6, 4, 9, 3, 6, 9, 1, 3, 10, 6, 3, -1, -1, -1, -1}}, /* 147 11 */ +{{ 6, 4, 8, 6, 8, 10, 2, 1, 11, -1, -1, -1, -1, -1, -1, -1}}, /* 148 7 */ +{{ 1, 11, 2, 3, 10, 0, 0, 10, 6, 0, 6, 4, -1, -1, -1, -1}}, /* 149 12 */ +{{ 4, 8, 10, 4, 10, 6, 0, 9, 2, 2, 9, 11, -1, -1, -1, -1}}, /* 150 10 */ +{{11, 3, 9, 11, 2, 3, 9, 3, 4, 10, 6, 3, 4, 3, 6, -1}}, /* 151 7 */ +{{ 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 152 5 */ +{{ 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 153 8 */ +{{ 1, 0, 9, 2, 4, 3, 2, 6, 4, 4, 8, 3, -1, -1, -1, -1}}, /* 154 12 */ +{{ 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 155 5 */ +{{ 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 11, -1, -1, -1, -1}}, /* 156 14 */ +{{11, 0, 1, 11, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}}, /* 157 5 */ +{{ 4, 3, 6, 4, 8, 3, 6, 3, 11, 0, 9, 3, 11, 3, 9, -1}}, /* 158 7 */ +{{11, 4, 9, 6, 4, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 159 2 */ +{{ 4, 5, 9, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 160 3 */ +{{ 0, 3, 8, 4, 5, 9, 10, 6, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 161 6 */ +{{ 5, 1, 0, 5, 0, 4, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 162 7 */ +{{10, 6, 7, 8, 4, 3, 3, 4, 5, 3, 5, 1, -1, -1, -1, -1}}, /* 163 12 */ +{{ 9, 4, 5, 11, 2, 1, 7, 10, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 164 6 */ +{{ 6, 7, 10, 1, 11, 2, 0, 3, 8, 4, 5, 9, -1, -1, -1, -1}}, /* 165 13 */ +{{ 7, 10, 6, 5, 11, 4, 4, 11, 2, 4, 2, 0, -1, -1, -1, -1}}, /* 166 12 */ +{{ 3, 8, 4, 3, 4, 5, 3, 5, 2, 11, 2, 5, 10, 6, 7, -1}}, /* 167 6 */ +{{ 7, 3, 2, 7, 2, 6, 5, 9, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 168 7 */ +{{ 9, 4, 5, 0, 6, 8, 0, 2, 6, 6, 7, 8, -1, -1, -1, -1}}, /* 169 12 */ +{{ 3, 2, 6, 3, 6, 7, 1, 0, 5, 5, 0, 4, -1, -1, -1, -1}}, /* 170 10 */ +{{ 6, 8, 2, 6, 7, 8, 2, 8, 1, 4, 5, 8, 1, 8, 5, -1}}, /* 171 7 */ +{{ 9, 4, 5, 11, 6, 1, 1, 6, 7, 1, 7, 3, -1, -1, -1, -1}}, /* 172 12 */ +{{ 1, 11, 6, 1, 6, 7, 1, 7, 0, 8, 0, 7, 9, 4, 5, -1}}, /* 173 6 */ +{{ 4, 11, 0, 4, 5, 11, 0, 11, 3, 6, 7, 11, 3, 11, 7, -1}}, /* 174 7 */ +{{ 7, 11, 6, 7, 8, 11, 5, 11, 4, 4, 11, 8, -1, -1, -1, -1}}, /* 175 3 */ +{{ 6, 5, 9, 6, 9, 10, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 176 5 */ +{{ 3, 10, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}}, /* 177 9 */ +{{ 0, 8, 10, 0, 10, 5, 0, 5, 1, 5, 10, 6, -1, -1, -1, -1}}, /* 178 14 */ +{{ 6, 3, 10, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 179 5 */ +{{ 1, 11, 2, 9, 10, 5, 9, 8, 10, 10, 6, 5, -1, -1, -1, -1}}, /* 180 12 */ +{{ 0, 3, 10, 0, 10, 6, 0, 6, 9, 5, 9, 6, 1, 11, 2, -1}}, /* 181 6 */ +{{10, 5, 8, 10, 6, 5, 8, 5, 0, 11, 2, 5, 0, 5, 2, -1}}, /* 182 7 */ +{{ 6, 3, 10, 6, 5, 3, 2, 3, 11, 11, 3, 5, -1, -1, -1, -1}}, /* 183 3 */ +{{ 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}}, /* 184 11 */ +{{ 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}}, /* 185 5 */ +{{ 1, 8, 5, 1, 0, 8, 5, 8, 6, 3, 2, 8, 6, 8, 2, -1}}, /* 186 7 */ +{{ 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 187 2 */ +{{ 1, 6, 3, 1, 11, 6, 3, 6, 8, 5, 9, 6, 8, 6, 9, -1}}, /* 188 7 */ +{{11, 0, 1, 11, 6, 0, 9, 0, 5, 5, 0, 6, -1, -1, -1, -1}}, /* 189 3 */ +{{ 0, 8, 3, 5, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 190 4 */ +{{11, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 191 1 */ +{{10, 11, 5, 7, 10, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 192 2 */ +{{10, 11, 5, 10, 5, 7, 8, 0, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 193 7 */ +{{ 5, 7, 10, 5, 10, 11, 1, 0, 9, -1, -1, -1, -1, -1, -1, -1}}, /* 194 7 */ +{{11, 5, 7, 11, 7, 10, 9, 1, 8, 8, 1, 3, -1, -1, -1, -1}}, /* 195 10 */ +{{10, 2, 1, 10, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}}, /* 196 5 */ +{{ 0, 3, 8, 1, 7, 2, 1, 5, 7, 7, 10, 2, -1, -1, -1, -1}}, /* 197 12 */ +{{ 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 10, -1, -1, -1, -1}}, /* 198 14 */ +{{ 7, 2, 5, 7, 10, 2, 5, 2, 9, 3, 8, 2, 9, 2, 8, -1}}, /* 199 7 */ +{{ 2, 11, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 200 5 */ +{{ 8, 0, 2, 8, 2, 5, 8, 5, 7, 11, 5, 2, -1, -1, -1, -1}}, /* 201 11 */ +{{ 9, 1, 0, 5, 3, 11, 5, 7, 3, 3, 2, 11, -1, -1, -1, -1}}, /* 202 12 */ +{{ 9, 2, 8, 9, 1, 2, 8, 2, 7, 11, 5, 2, 7, 2, 5, -1}}, /* 203 7 */ +{{ 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 204 8 */ +{{ 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}}, /* 205 5 */ +{{ 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}}, /* 206 5 */ +{{ 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 207 2 */ +{{ 5, 4, 8, 5, 8, 11, 11, 8, 10, -1, -1, -1, -1, -1, -1, -1}}, /* 208 5 */ +{{ 5, 4, 0, 5, 0, 10, 5, 10, 11, 10, 0, 3, -1, -1, -1, -1}}, /* 209 14 */ +{{ 0, 9, 1, 8, 11, 4, 8, 10, 11, 11, 5, 4, -1, -1, -1, -1}}, /* 210 12 */ +{{11, 4, 10, 11, 5, 4, 10, 4, 3, 9, 1, 4, 3, 4, 1, -1}}, /* 211 7 */ +{{ 2, 1, 5, 2, 5, 8, 2, 8, 10, 4, 8, 5, -1, -1, -1, -1}}, /* 212 11 */ +{{ 0, 10, 4, 0, 3, 10, 4, 10, 5, 2, 1, 10, 5, 10, 1, -1}}, /* 213 7 */ +{{ 0, 5, 2, 0, 9, 5, 2, 5, 10, 4, 8, 5, 10, 5, 8, -1}}, /* 214 7 */ +{{ 9, 5, 4, 2, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 215 4 */ +{{ 2, 11, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}}, /* 216 9 */ +{{ 5, 2, 11, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}}, /* 217 5 */ +{{ 3, 2, 11, 3, 11, 5, 3, 5, 8, 4, 8, 5, 0, 9, 1, -1}}, /* 218 6 */ +{{ 5, 2, 11, 5, 4, 2, 1, 2, 9, 9, 2, 4, -1, -1, -1, -1}}, /* 219 3 */ +{{ 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}}, /* 220 5 */ +{{ 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 221 2 */ +{{ 8, 5, 4, 8, 3, 5, 9, 5, 0, 0, 5, 3, -1, -1, -1, -1}}, /* 222 3 */ +{{ 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 223 1 */ +{{ 4, 7, 10, 4, 10, 9, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}}, /* 224 5 */ +{{ 0, 3, 8, 4, 7, 9, 9, 7, 10, 9, 10, 11, -1, -1, -1, -1}}, /* 225 12 */ +{{ 1, 10, 11, 1, 4, 10, 1, 0, 4, 7, 10, 4, -1, -1, -1, -1}}, /* 226 11 */ +{{ 3, 4, 1, 3, 8, 4, 1, 4, 11, 7, 10, 4, 11, 4, 10, -1}}, /* 227 7 */ +{{ 4, 7, 10, 9, 4, 10, 9, 10, 2, 9, 2, 1, -1, -1, -1, -1}}, /* 228 9 */ +{{ 9, 4, 7, 9, 7, 10, 9, 10, 1, 2, 1, 10, 0, 3, 8, -1}}, /* 229 6 */ +{{10, 4, 7, 10, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}}, /* 230 5 */ +{{10, 4, 7, 10, 2, 4, 8, 4, 3, 3, 4, 2, -1, -1, -1, -1}}, /* 231 3 */ +{{ 2, 11, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}}, /* 232 14 */ +{{ 9, 7, 11, 9, 4, 7, 11, 7, 2, 8, 0, 7, 2, 7, 0, -1}}, /* 233 7 */ +{{ 3, 11, 7, 3, 2, 11, 7, 11, 4, 1, 0, 11, 4, 11, 0, -1}}, /* 234 7 */ +{{ 1, 2, 11, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 235 4 */ +{{ 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}}, /* 236 5 */ +{{ 4, 1, 9, 4, 7, 1, 0, 1, 8, 8, 1, 7, -1, -1, -1, -1}}, /* 237 3 */ +{{ 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 238 2 */ +{{ 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 239 1 */ +{{ 9, 8, 11, 11, 8, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 240 8 */ +{{ 3, 9, 0, 3, 10, 9, 10, 11, 9, -1, -1, -1, -1, -1, -1, -1}}, /* 241 5 */ +{{ 0, 11, 1, 0, 8, 11, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}}, /* 242 5 */ +{{ 3, 11, 1, 10, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 243 2 */ +{{ 1, 10, 2, 1, 9, 10, 9, 8, 10, -1, -1, -1, -1, -1, -1, -1}}, /* 244 5 */ +{{ 3, 9, 0, 3, 10, 9, 1, 9, 2, 2, 9, 10, -1, -1, -1, -1}}, /* 245 3 */ +{{ 0, 10, 2, 8, 10, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 246 2 */ +{{ 3, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 247 1 */ +{{ 2, 8, 3, 2, 11, 8, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}}, /* 248 5 */ +{{ 9, 2, 11, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 249 2 */ +{{ 2, 8, 3, 2, 11, 8, 0, 8, 1, 1, 8, 11, -1, -1, -1, -1}}, /* 250 3 */ +{{ 1, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 251 1 */ +{{ 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 252 2 */ +{{ 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 253 1 */ +{{ 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, /* 254 1 */ +{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}}; /* 255 0 */ + +vtkMarchingCubesTriangleCases* vtkMarchingCubesTriangleCases::GetCases() +{ + return VTK_MARCHING_CUBES_TRICASES; +} diff --git a/Filtering/vtkCell3D.h b/Filtering/vtkCell3D.h new file mode 100644 index 0000000..ef26c11 --- /dev/null +++ b/Filtering/vtkCell3D.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCell3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCell3D - abstract class to specify 3D cell interface +// .SECTION Description +// vtkCell3D is an abstract class that extends the interfaces for 3D data +// cells, and implements methods needed to satisfy the vtkCell API. The +// 3D cells include hexehedra, tetrahedra, wedge, pyramid, and voxel. + +// .SECTION See Also +// vtkTetra vtkHexahedron vtkVoxel vtkWedge vtkPyramid + +#ifndef __vtkCell3D_h +#define __vtkCell3D_h + +#include "vtkCell.h" + +class vtkOrderedTriangulator; +class vtkTetra; +class vtkCellArray; +class vtkDoubleArray; + +class VTK_FILTERING_EXPORT vtkCell3D : public vtkCell +{ +public: + vtkTypeRevisionMacro(vtkCell3D,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the pair of vertices that define an edge. The method returns the + // number of vertices, along with an array of vertices. Note that the + // vertices are 0-offset; that is, they refer to the ids of the cell, not + // the point ids of the mesh that the cell belongs to. The edgeId must + // range between 0<=edgeIdGetNumberOfEdges(). + virtual void GetEdgePoints(int edgeId, int* &pts) = 0; + + // Description: + // Get the list of vertices that define a face. The list is terminated + // with a negative number. Note that the vertices are 0-offset; that is, + // they refer to the ids of the cell, not the point ids of the mesh that + // the cell belongs to. The faceId must range between + // 0<=faceIdGetNumberOfFaces(). + virtual void GetFacePoints(int faceId, int* &pts) = 0; + + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + + // Description: + // Cut (or clip) the cell based on the input cellScalars and the specified + // value. The output of the clip operation will be one or more cells of the + // same topological dimension as the original cell. The flag insideOut + // controls what part of the cell is considered inside - normally cell + // points whose scalar value is greater than "value" are considered + // inside. If insideOut is on, this is reversed. Also, if the output cell + // data is non-NULL, the cell data from the clipped cell is passed to the + // generated contouring primitives. (Note: the CopyAllocate() method must + // be invoked on both the output cell and point data. The cellId refers to + // the cell from which the cell data is copied.) (Satisfies vtkCell API.) + virtual void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *connectivity, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // The topological dimension of the cell. (Satisfies vtkCell API.) + virtual int GetCellDimension() {return 3;} + + // Description: + // Set the tolerance for merging clip intersection points that are near + // the vertices of cells. This tolerance is used to prevent the generation + // of degenerate tetrahedra during clipping. + vtkSetClampMacro(MergeTolerance,double,0.0001,0.25); + vtkGetMacro(MergeTolerance,double); + +protected: + vtkCell3D(); + ~vtkCell3D(); + + vtkOrderedTriangulator *Triangulator; + double MergeTolerance; + + //used to support clipping + vtkTetra *ClipTetra; + vtkDoubleArray *ClipScalars; + +private: + vtkCell3D(const vtkCell3D&); // Not implemented. + void operator=(const vtkCell3D&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkCellArray.cxx b/Filtering/vtkCellArray.cxx new file mode 100644 index 0000000..01ad518 --- /dev/null +++ b/Filtering/vtkCellArray.cxx @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCellArray, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkCellArray); + +//---------------------------------------------------------------------------- +vtkCellArray::vtkCellArray() +{ + this->Ia = vtkIdTypeArray::New(); + this->NumberOfCells = 0; + this->InsertLocation = 0; + this->TraversalLocation = 0; +} + +//---------------------------------------------------------------------------- +void vtkCellArray::DeepCopy (vtkCellArray *ca) +{ + // Do nothing on a NULL input. + if (ca == NULL) + { + return; + } + + this->Ia->DeepCopy(ca->Ia); + this->NumberOfCells = ca->NumberOfCells; + this->InsertLocation = ca->InsertLocation; + this->TraversalLocation = ca->TraversalLocation; +} + +//---------------------------------------------------------------------------- +vtkCellArray::~vtkCellArray() +{ + this->Ia->Delete(); +} + + +//---------------------------------------------------------------------------- +// Returns the size of the largest cell. The size is the number of points +// defining the cell. +int vtkCellArray::GetMaxCellSize() +{ + int i, npts=0, maxSize=0; + + for (i=0; iIa->GetMaxId(); i+=(npts+1)) + { + if ( (npts=this->Ia->GetValue(i)) > maxSize ) + { + maxSize = npts; + } + } + return maxSize; +} + +//---------------------------------------------------------------------------- +// Specify a group of cells. +void vtkCellArray::SetCells(vtkIdType ncells, vtkIdTypeArray *cells) +{ + if ( cells && cells != this->Ia ) + { + this->Modified(); + this->Ia->Delete(); + this->Ia = cells; + this->Ia->Register(this); + + this->NumberOfCells = ncells; + this->InsertLocation = cells->GetMaxId() + 1; + this->TraversalLocation = 0; + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkCellArray::GetActualMemorySize() +{ + return this->Ia->GetActualMemorySize(); +} + +//---------------------------------------------------------------------------- +void vtkCellArray::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Cells: " << this->NumberOfCells << endl; + os << indent << "Insert Location: " << this->InsertLocation << endl; + os << indent << "Traversal Location: " << this->TraversalLocation << endl; +} diff --git a/Filtering/vtkCellArray.h b/Filtering/vtkCellArray.h new file mode 100644 index 0000000..e02d896 --- /dev/null +++ b/Filtering/vtkCellArray.h @@ -0,0 +1,379 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellArray - object to represent cell connectivity +// .SECTION Description +// vtkCellArray is a supporting object that explicitly represents cell +// connectivity. The cell array structure is a raw integer list +// of the form: (n,id1,id2,...,idn, n,id1,id2,...,idn, ...) +// where n is the number of points in the cell, and id is a zero-offset index +// into an associated point list. +// +// Advantages of this data structure are its compactness, simplicity, and +// easy interface to external data. However, it is totally inadequate for +// random access. This functionality (when necessary) is accomplished by +// using the vtkCellTypes and vtkCellLinks objects to extend the definition of +// the data structure. +// +// .SECTION See Also +// vtkCellTypes vtkCellLinks + +#ifndef __vtkCellArray_h +#define __vtkCellArray_h + +#include "vtkObject.h" + +#include "vtkIdTypeArray.h" // Needed for inline methods +#include "vtkCell.h" // Needed for inline methods + +class VTK_FILTERING_EXPORT vtkCellArray : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCellArray,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate cell array (connectivity list). + static vtkCellArray *New(); + + // Description: + // Allocate memory and set the size to extend by. + int Allocate(const vtkIdType sz, const int ext=1000) + {return this->Ia->Allocate(sz,ext);} + + // Description: + // Free any memory and reset to an empty state. + void Initialize() + {this->Ia->Initialize();} + + // Description: + // Get the number of cells in the array. + vtkGetMacro(NumberOfCells, vtkIdType); + + // Description: + // Set the number of cells in the array. + // DO NOT do any kind of allocation, advanced use only. + vtkSetMacro(NumberOfCells, vtkIdType); + + // Description: + // Utility routines help manage memory of cell array. EstimateSize() + // returns a value used to initialize and allocate memory for array based + // on number of cells and maximum number of points making up cell. If + // every cell is the same size (in terms of number of points), then the + // memory estimate is guaranteed exact. (If not exact, use Squeeze() to + // reclaim any extra memory.) + vtkIdType EstimateSize(vtkIdType numCells, int maxPtsPerCell) + {return numCells*(1+maxPtsPerCell);} + + // Description: + // A cell traversal methods that is more efficient than vtkDataSet traversal + // methods. InitTraversal() initializes the traversal of the list of cells. + void InitTraversal() {this->TraversalLocation=0;}; + + // Description: + // A cell traversal methods that is more efficient than vtkDataSet traversal + // methods. GetNextCell() gets the next cell in the list. If end of list + // is encountered, 0 is returned. + int GetNextCell(vtkIdType& npts, vtkIdType* &pts); + + // Description: + // Get the size of the allocated connectivity array. + vtkIdType GetSize() + {return this->Ia->GetSize();} + + // Description: + // Get the total number of entries (i.e., data values) in the connectivity + // array. This may be much less than the allocated size (i.e., return value + // from GetSize().) + vtkIdType GetNumberOfConnectivityEntries() + {return this->Ia->GetMaxId()+1;} + + // Description: + // Internal method used to retrieve a cell given an offset into + // the internal array. + void GetCell(vtkIdType loc, vtkIdType &npts, vtkIdType* &pts); + + // Description: + // Insert a cell object. Return the cell id of the cell. + vtkIdType InsertNextCell(vtkCell *cell); + + // Description: + // Create a cell by specifying the number of points and an array of point + // id's. Return the cell id of the cell. + vtkIdType InsertNextCell(vtkIdType npts, const vtkIdType* pts); + + // Description: + // Create a cell by specifying a list of point ids. Return the cell id of + // the cell. + vtkIdType InsertNextCell(vtkIdList *pts); + + // Description: + // Create cells by specifying count, and then adding points one at a time + // using method InsertCellPoint(). If you don't know the count initially, + // use the method UpdateCellCount() to complete the cell. Return the cell + // id of the cell. + vtkIdType InsertNextCell(int npts); + + // Description: + // Used in conjunction with InsertNextCell(int npts) to add another point + // to the list of cells. + void InsertCellPoint(vtkIdType id); + + // Description: + // Used in conjunction with InsertNextCell(int npts) and InsertCellPoint() to + // update the number of points defining the cell. + void UpdateCellCount(int npts); + + // Description: + // Computes the current insertion location within the internal array. + // Used in conjunction with GetCell(int loc,...). + vtkIdType GetInsertLocation(int npts) + {return (this->InsertLocation - npts - 1);}; + + // Description: + // Get/Set the current traversal location. + vtkIdType GetTraversalLocation() + {return this->TraversalLocation;} + void SetTraversalLocation(vtkIdType loc) + {this->TraversalLocation = loc;} + + // Description: + // Computes the current traversal location within the internal array. Used + // in conjunction with GetCell(int loc,...). + vtkIdType GetTraversalLocation(vtkIdType npts) + {return(this->TraversalLocation-npts-1);} + + // Description: + // Special method inverts ordering of current cell. Must be called + // carefully or the cell topology may be corrupted. + void ReverseCell(vtkIdType loc); + + // Description: + // Replace the point ids of the cell with a different list of point ids. + void ReplaceCell(vtkIdType loc, int npts, const vtkIdType *pts); + + // Description: + // Returns the size of the largest cell. The size is the number of points + // defining the cell. + int GetMaxCellSize(); + + // Description: + // Get pointer to array of cell data. + vtkIdType *GetPointer() + {return this->Ia->GetPointer(0);} + + // Description: + // Get pointer to data array for purpose of direct writes of data. Size is the + // total storage consumed by the cell array. ncells is the number of cells + // represented in the array. + vtkIdType *WritePointer(const vtkIdType ncells, const vtkIdType size); + + // Description: + // Define multiple cells by providing a connectivity list. The list is in + // the form (npts,p0,p1,...p(npts-1), repeated for each cell). Be careful + // using this method because it discards the old cells, and anything + // referring these cells becomes invalid (for example, if BuildCells() has + // been called see vtkPolyData). The traversal location is reset to the + // beginning of the list; the insertion location is set to the end of the + // list. + void SetCells(vtkIdType ncells, vtkIdTypeArray *cells); + + // Description: + // Perform a deep copy (no reference counting) of the given cell array. + void DeepCopy(vtkCellArray *ca); + + // Description: + // Return the underlying data as a data array. + vtkIdTypeArray* GetData() + {return this->Ia;} + + // Description: + // Reuse list. Reset to initial condition. + void Reset(); + + // Description: + // Reclaim any extra memory. + void Squeeze() + {this->Ia->Squeeze();} + + // Description: + // Return the memory in kilobytes consumed by this cell array. Used to + // support streaming and reading/writing data. The value returned is + // guaranteed to be greater than or equal to the memory required to + // actually represent the data represented by this object. The + // information returned is valid only after the pipeline has + // been updated. + unsigned long GetActualMemorySize(); + +protected: + vtkCellArray(); + ~vtkCellArray(); + + vtkIdType NumberOfCells; + vtkIdType InsertLocation; //keep track of current insertion point + vtkIdType TraversalLocation; //keep track of traversal position + vtkIdTypeArray *Ia; + +private: + vtkCellArray(const vtkCellArray&); // Not implemented. + void operator=(const vtkCellArray&); // Not implemented. +}; + + +//---------------------------------------------------------------------------- +inline vtkIdType vtkCellArray::InsertNextCell(vtkIdType npts, + const vtkIdType* pts) +{ + vtkIdType i = this->Ia->GetMaxId() + 1; + vtkIdType *ptr = this->Ia->WritePointer(i, npts+1); + + for ( *ptr++ = npts, i = 0; i < npts; i++) + { + *ptr++ = *pts++; + } + + this->NumberOfCells++; + this->InsertLocation += npts + 1; + + return this->NumberOfCells - 1; +} + +//---------------------------------------------------------------------------- +inline vtkIdType vtkCellArray::InsertNextCell(vtkIdList *pts) +{ + vtkIdType npts = pts->GetNumberOfIds(); + vtkIdType i = this->Ia->GetMaxId() + 1; + vtkIdType *ptr = this->Ia->WritePointer(i,npts+1); + + for ( *ptr++ = npts, i = 0; i < npts; i++) + { + *ptr++ = pts->GetId(i); + } + + this->NumberOfCells++; + this->InsertLocation += npts + 1; + + return this->NumberOfCells - 1; +} + +//---------------------------------------------------------------------------- +inline vtkIdType vtkCellArray::InsertNextCell(int npts) +{ + this->InsertLocation = this->Ia->InsertNextValue(npts) + 1; + this->NumberOfCells++; + + return this->NumberOfCells - 1; +} + +//---------------------------------------------------------------------------- +inline void vtkCellArray::InsertCellPoint(vtkIdType id) +{ + this->Ia->InsertValue(this->InsertLocation++, id); +} + +//---------------------------------------------------------------------------- +inline void vtkCellArray::UpdateCellCount(int npts) +{ + this->Ia->SetValue(this->InsertLocation-npts-1, npts); +} + +//---------------------------------------------------------------------------- +inline vtkIdType vtkCellArray::InsertNextCell(vtkCell *cell) +{ + int npts = cell->GetNumberOfPoints(); + vtkIdType i = this->Ia->GetMaxId() + 1; + vtkIdType *ptr = this->Ia->WritePointer(i,npts+1); + + for ( *ptr++ = npts, i = 0; i < npts; i++) + { + *ptr++ = cell->PointIds->GetId(i); + } + + this->NumberOfCells++; + this->InsertLocation += npts + 1; + + return this->NumberOfCells - 1; +} + +//---------------------------------------------------------------------------- +inline void vtkCellArray::Reset() +{ + this->NumberOfCells = 0; + this->InsertLocation = 0; + this->TraversalLocation = 0; + this->Ia->Reset(); +} + +//---------------------------------------------------------------------------- +inline int vtkCellArray::GetNextCell(vtkIdType& npts, vtkIdType* &pts) +{ + if ( this->Ia->GetMaxId() >= 0 && + this->TraversalLocation <= this->Ia->GetMaxId() ) + { + npts = this->Ia->GetValue(this->TraversalLocation++); + pts = this->Ia->GetPointer(this->TraversalLocation); + this->TraversalLocation += npts; + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +inline void vtkCellArray::GetCell(vtkIdType loc, vtkIdType &npts, + vtkIdType* &pts) +{ + npts = this->Ia->GetValue(loc++); + pts = this->Ia->GetPointer(loc); +} + +//---------------------------------------------------------------------------- +inline void vtkCellArray::ReverseCell(vtkIdType loc) +{ + int i; + vtkIdType tmp; + vtkIdType npts=this->Ia->GetValue(loc); + vtkIdType *pts=this->Ia->GetPointer(loc+1); + for (i=0; i < (npts/2); i++) + { + tmp = pts[i]; + pts[i] = pts[npts-i-1]; + pts[npts-i-1] = tmp; + } +} + +//---------------------------------------------------------------------------- +inline void vtkCellArray::ReplaceCell(vtkIdType loc, int npts, + const vtkIdType *pts) +{ + vtkIdType *oldPts=this->Ia->GetPointer(loc+1); + for (int i=0; i < npts; i++) + { + oldPts[i] = pts[i]; + } +} + +//---------------------------------------------------------------------------- +inline vtkIdType *vtkCellArray::WritePointer(const vtkIdType ncells, + const vtkIdType size) +{ + this->NumberOfCells = ncells; + this->InsertLocation = 0; + this->TraversalLocation = 0; + return this->Ia->WritePointer(0,size); +} + +#endif diff --git a/Filtering/vtkCellData.cxx b/Filtering/vtkCellData.cxx new file mode 100644 index 0000000..6f57df6 --- /dev/null +++ b/Filtering/vtkCellData.cxx @@ -0,0 +1,24 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCellData, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkCellData); + +void vtkCellData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkCellData.h b/Filtering/vtkCellData.h new file mode 100644 index 0000000..35bd469 --- /dev/null +++ b/Filtering/vtkCellData.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellData - represent and manipulate cell attribute data +// .SECTION Description +// vtkCellData is a class that is used to represent and manipulate +// cell attribute data (e.g., scalars, vectors, normals, texture +// coordinates, etc.) Special methods are provided to work with filter +// objects, such as passing data through filter, copying data from one +// cell to another, and interpolating data given cell interpolation weights. + +#ifndef __vtkCellData_h +#define __vtkCellData_h + +#include "vtkDataSetAttributes.h" + +class VTK_FILTERING_EXPORT vtkCellData : public vtkDataSetAttributes +{ +public: + static vtkCellData *New(); + + vtkTypeRevisionMacro(vtkCellData,vtkDataSetAttributes); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkCellData() {}; //make sure constructor and desctructor are protected + ~vtkCellData() {}; + +private: + vtkCellData(const vtkCellData&); // Not implemented. + void operator=(const vtkCellData&); // Not implemented. +}; + +#endif + + + diff --git a/Filtering/vtkCellLinks.cxx b/Filtering/vtkCellLinks.cxx new file mode 100644 index 0000000..9e2bcc2 --- /dev/null +++ b/Filtering/vtkCellLinks.cxx @@ -0,0 +1,296 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellLinks.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellLinks.h" + +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkGenericCell.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkCellLinks, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkCellLinks); + +//---------------------------------------------------------------------------- +void vtkCellLinks::Allocate(vtkIdType sz, vtkIdType ext) +{ + static vtkCellLinks::Link linkInit = {0,NULL}; + + this->Size = sz; + if ( this->Array != NULL ) + { + delete [] this->Array; + } + this->Array = new vtkCellLinks::Link[sz]; + this->Extend = ext; + this->MaxId = -1; + + for (vtkIdType i=0; i < sz; i++) + { + this->Array[i] = linkInit; + } +} + +//---------------------------------------------------------------------------- +vtkCellLinks::~vtkCellLinks() +{ + if ( this->Array == NULL ) + { + return; + } + + for (vtkIdType i=0; i<=this->MaxId; i++) + { + if ( this->Array[i].cells != NULL ) + { + delete [] this->Array[i].cells; + } + } + + delete [] this->Array; +} + +//---------------------------------------------------------------------------- +// Allocate memory for the list of lists of cell ids. +void vtkCellLinks::AllocateLinks(vtkIdType n) +{ + for (vtkIdType i=0; i < n; i++) + { + this->Array[i].cells = new vtkIdType[this->Array[i].ncells]; + } +} + +//---------------------------------------------------------------------------- +// Reclaim any unused memory. +void vtkCellLinks::Squeeze() +{ + this->Resize (this->MaxId+1); +} + + +//---------------------------------------------------------------------------- +void vtkCellLinks::Reset() +{ + this->MaxId = -1; +} + +//---------------------------------------------------------------------------- +// +// Private function does "reallocate" +// +vtkCellLinks::Link *vtkCellLinks::Resize(vtkIdType sz) +{ + vtkIdType i; + vtkCellLinks::Link *newArray; + vtkIdType newSize; + vtkCellLinks::Link linkInit = {0,NULL}; + + if ( sz >= this->Size ) + { + newSize = this->Size + sz; + } + else + { + newSize = sz; + } + + newArray = new vtkCellLinks::Link[newSize]; + + for (i=0; iSize; i++) + { + newArray[i] = this->Array[i]; + } + + for (i=this->Size; i < newSize ; i++) + { + newArray[i] = linkInit; + } + + this->Size = newSize; + delete [] this->Array; + this->Array = newArray; + + return this->Array; +} + +//---------------------------------------------------------------------------- +// Build the link list array. +void vtkCellLinks::BuildLinks(vtkDataSet *data) +{ + vtkIdType numPts = data->GetNumberOfPoints(); + vtkIdType numCells = data->GetNumberOfCells(); + int j; + vtkIdType cellId; + unsigned short *linkLoc; + + // fill out lists with number of references to cells + linkLoc = new unsigned short[numPts]; + memset(linkLoc, 0, numPts*sizeof(unsigned short)); + + // Use fast path if polydata + if ( data->GetDataObjectType() == VTK_POLY_DATA ) + { + vtkIdType *pts, npts; + + vtkPolyData *pdata = (vtkPolyData *)data; + // traverse data to determine number of uses of each point + for (cellId=0; cellId < numCells; cellId++) + { + pdata->GetCellPoints(cellId, npts, pts); + for (j=0; j < npts; j++) + { + this->IncrementLinkCount(pts[j]); + } + } + + // now allocate storage for the links + this->AllocateLinks(numPts); + this->MaxId = numPts - 1; + + for (cellId=0; cellId < numCells; cellId++) + { + pdata->GetCellPoints(cellId, npts, pts); + for (j=0; j < npts; j++) + { + this->InsertCellReference(pts[j], (linkLoc[pts[j]])++, cellId); + } + } + } + + else //any other type of dataset + { + vtkIdType numberOfPoints, ptId; + vtkGenericCell *cell=vtkGenericCell::New(); + + // traverse data to determine number of uses of each point + for (cellId=0; cellId < numCells; cellId++) + { + data->GetCell(cellId,cell); + numberOfPoints = cell->GetNumberOfPoints(); + for (j=0; j < numberOfPoints; j++) + { + this->IncrementLinkCount(cell->PointIds->GetId(j)); + } + } + + // now allocate storage for the links + this->AllocateLinks(numPts); + this->MaxId = numPts - 1; + + for (cellId=0; cellId < numCells; cellId++) + { + data->GetCell(cellId,cell); + numberOfPoints = cell->GetNumberOfPoints(); + for (j=0; j < numberOfPoints; j++) + { + ptId = cell->PointIds->GetId(j); + this->InsertCellReference(ptId, (linkLoc[ptId])++, cellId); + } + } + cell->Delete(); + }//end else + + delete [] linkLoc; +} + +//---------------------------------------------------------------------------- +// Build the link list array. +void vtkCellLinks::BuildLinks(vtkDataSet *data, vtkCellArray *Connectivity) +{ + vtkIdType numPts = data->GetNumberOfPoints(); + vtkIdType j, cellId; + unsigned short *linkLoc; + vtkIdType npts=0; + vtkIdType *pts=0; + vtkIdType loc = Connectivity->GetTraversalLocation(); + + // traverse data to determine number of uses of each point + for (Connectivity->InitTraversal(); + Connectivity->GetNextCell(npts,pts);) + { + for (j=0; j < npts; j++) + { + this->IncrementLinkCount(pts[j]); + } + } + + // now allocate storage for the links + this->AllocateLinks(numPts); + this->MaxId = numPts - 1; + + // fill out lists with references to cells + linkLoc = new unsigned short[numPts]; + memset(linkLoc, 0, numPts*sizeof(unsigned short)); + + cellId = 0; + for (Connectivity->InitTraversal(); + Connectivity->GetNextCell(npts,pts); cellId++) + { + for (j=0; j < npts; j++) + { + this->InsertCellReference(pts[j], (linkLoc[pts[j]])++, cellId); + } + } + delete [] linkLoc; + Connectivity->SetTraversalLocation(loc); +} + +//---------------------------------------------------------------------------- +// Insert a new point into the cell-links data structure. The size parameter +// is the initial size of the list. +vtkIdType vtkCellLinks::InsertNextPoint(int numLinks) +{ + if ( ++this->MaxId >= this->Size ) + { + this->Resize(this->MaxId + 1); + } + this->Array[this->MaxId].cells = new vtkIdType[numLinks]; + return this->MaxId; +} + +//---------------------------------------------------------------------------- +unsigned long vtkCellLinks::GetActualMemorySize() +{ + unsigned long size=0; + vtkIdType ptId; + + for (ptId=0; ptId < (this->MaxId+1); ptId++) + { + size += this->GetNcells(ptId); + } + + size *= sizeof(int *); //references to cells + size += (this->MaxId+1) * sizeof(vtkCellLinks::Link); //list of cell lists + + return (unsigned long) ceil((float)size/1000.0); //kilobytes +} + +//---------------------------------------------------------------------------- +void vtkCellLinks::DeepCopy(vtkCellLinks *src) +{ + this->Allocate(src->Size, src->Extend); + memcpy(this->Array, src->Array, this->Size * sizeof(vtkCellLinks::Link)); + this->MaxId = src->MaxId; +} + +//---------------------------------------------------------------------------- +void vtkCellLinks::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Size: " << this->Size << "\n"; + os << indent << "MaxId: " << this->MaxId << "\n"; + os << indent << "Extend: " << this->Extend << "\n"; +} diff --git a/Filtering/vtkCellLinks.h b/Filtering/vtkCellLinks.h new file mode 100644 index 0000000..8537249 --- /dev/null +++ b/Filtering/vtkCellLinks.h @@ -0,0 +1,216 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellLinks.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellLinks - object represents upward pointers from points to list of cells using each point +// .SECTION Description +// vtkCellLinks is a supplemental object to vtkCellArray and vtkCellTypes, +// enabling access from points to the cells using the points. vtkCellLinks is +// a list of Links, each link represents a dynamic list of cell id's using the +// point. The information provided by this object can be used to determine +// neighbors and construct other local topological information. +// .SECTION See Also +// vtkCellArray vtkCellTypes + +#ifndef __vtkCellLinks_h +#define __vtkCellLinks_h + +#include "vtkObject.h" +class vtkDataSet; +class vtkCellArray; + +class VTK_FILTERING_EXPORT vtkCellLinks : public vtkObject +{ +public: + + //BTX + class Link { + public: + unsigned short ncells; + vtkIdType *cells; + }; + //ETX + + static vtkCellLinks *New(); + vtkTypeRevisionMacro(vtkCellLinks,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate the specified number of links (i.e., number of points) that + // will be built. + void Allocate(vtkIdType numLinks, vtkIdType ext=1000); + + // Description: + // Get a link structure given a point id. + Link &GetLink(vtkIdType ptId) {return this->Array[ptId];}; + + // Description: + // Get the number of cells using the point specified by ptId. + unsigned short GetNcells(vtkIdType ptId) { return this->Array[ptId].ncells;}; + + // Description: + // Build the link list array. + void BuildLinks(vtkDataSet *data); + + // Description: + // Build the link list array. + void BuildLinks(vtkDataSet *data, vtkCellArray *Connectivity); + + // Description: + // Return a list of cell ids using the point. + vtkIdType *GetCells(vtkIdType ptId) {return this->Array[ptId].cells;}; + + // Description: + // Insert a new point into the cell-links data structure. The size parameter + // is the initial size of the list. + vtkIdType InsertNextPoint(int numLinks); + + // Description: + // Insert a cell id into the list of cells (at the end) using the cell id + // provided. (Make sure to extend the link list (if necessary) using the + // method ResizeCellList().) + void InsertNextCellReference(vtkIdType ptId, vtkIdType cellId); + + // Description: + // Delete point (and storage) by destroying links to using cells. + void DeletePoint(vtkIdType ptId); + + // Description: + // Delete the reference to the cell (cellId) from the point (ptId). This + // removes the reference to the cellId from the cell list, but does not + // resize the list (recover memory with ResizeCellList(), if necessary). + void RemoveCellReference(vtkIdType cellId, vtkIdType ptId); + + // Description: + // Add the reference to the cell (cellId) from the point (ptId). This + // adds a reference to the cellId from the cell list, but does not resize + // the list (extend memory with ResizeCellList(), if necessary). + void AddCellReference(vtkIdType cellId, vtkIdType ptId); + + // Description: + // Change the length of a point's link list (i.e., list of cells using a + // point) by the size specified. + void ResizeCellList(vtkIdType ptId, int size); + + // Description: + // Reclaim any unused memory. + void Squeeze(); + + // Description: + // Reset to a state of no entries without freeing the memory. + void Reset(); + + // Description: + // Return the memory in kilobytes consumed by this cell links array. + // Used to support streaming and reading/writing data. The value + // returned is guaranteed to be greater than or equal to the memory + // required to actually represent the data represented by this object. + // The information returned is valid only after the pipeline has + // been updated. + unsigned long GetActualMemorySize(); + + // Description: + // Standard DeepCopy method. Since this object contains no reference + // to other objects, there is no ShallowCopy. + void DeepCopy(vtkCellLinks *src); + +protected: + vtkCellLinks():Array(NULL),Size(0),MaxId(-1),Extend(1000) {}; + ~vtkCellLinks(); + + // Description: + // Increment the count of the number of cells using the point. + void IncrementLinkCount(vtkIdType ptId) { this->Array[ptId].ncells++;}; + + void AllocateLinks(vtkIdType n); + + // Description: + // Insert a cell id into the list of cells using the point. + void InsertCellReference(vtkIdType ptId, unsigned short pos, + vtkIdType cellId); + + Link *Array; // pointer to data + vtkIdType Size; // allocated size of data + vtkIdType MaxId; // maximum index inserted thus far + vtkIdType Extend; // grow array by this point + Link *Resize(vtkIdType sz); // function to resize data +private: + vtkCellLinks(const vtkCellLinks&); // Not implemented. + void operator=(const vtkCellLinks&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline void vtkCellLinks::InsertCellReference(vtkIdType ptId, + unsigned short pos, + vtkIdType cellId) +{ + this->Array[ptId].cells[pos] = cellId; +} + +//---------------------------------------------------------------------------- +inline void vtkCellLinks::DeletePoint(vtkIdType ptId) +{ + this->Array[ptId].ncells = 0; + delete [] this->Array[ptId].cells; + this->Array[ptId].cells = NULL; +} + +//---------------------------------------------------------------------------- +inline void vtkCellLinks::InsertNextCellReference(vtkIdType ptId, + vtkIdType cellId) +{ + this->Array[ptId].cells[this->Array[ptId].ncells++] = cellId; +} + +//---------------------------------------------------------------------------- +inline void vtkCellLinks::RemoveCellReference(vtkIdType cellId, vtkIdType ptId) +{ + vtkIdType *cells=this->Array[ptId].cells; + int ncells=this->Array[ptId].ncells; + + for (int i=0; i < ncells; i++) + { + if (cells[i] == cellId) + { + for (int j=i; j < (ncells-1); j++) + { + cells[j] = cells[j+1]; + } + this->Array[ptId].ncells--; + break; + } + } +} + +//---------------------------------------------------------------------------- +inline void vtkCellLinks::AddCellReference(vtkIdType cellId, vtkIdType ptId) +{ + this->Array[ptId].cells[this->Array[ptId].ncells++] = cellId; +} + +//---------------------------------------------------------------------------- +inline void vtkCellLinks::ResizeCellList(vtkIdType ptId, int size) +{ + int newSize; + vtkIdType *cells; + + newSize = this->Array[ptId].ncells + size; + cells = new vtkIdType[newSize]; + memcpy(cells, this->Array[ptId].cells, + this->Array[ptId].ncells*sizeof(vtkIdType)); + delete [] this->Array[ptId].cells; + this->Array[ptId].cells = cells; +} + +#endif + diff --git a/Filtering/vtkCellLocator.cxx b/Filtering/vtkCellLocator.cxx new file mode 100644 index 0000000..da06d3c --- /dev/null +++ b/Filtering/vtkCellLocator.cxx @@ -0,0 +1,1671 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellLocator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellLocator.h" + +#include "vtkCellArray.h" +#include "vtkGenericCell.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkBox.h" + +#include + +vtkCxxRevisionMacro(vtkCellLocator, "$Revision: 1.81 $"); +vtkStandardNewMacro(vtkCellLocator); + +#define VTK_CELL_OUTSIDE 0 +#define VTK_CELL_INSIDE 1 + +typedef vtkIdList *vtkIdListPtr; + +class vtkNeighborCells +{ + public: + vtkNeighborCells(const int sz, const int ext=1000) + {this->P = vtkIntArray::New(); this->P->Allocate(3*sz,3*ext);}; + ~vtkNeighborCells(){this->P->Delete();}; + int GetNumberOfNeighbors() {return (this->P->GetMaxId()+1)/3;}; + void Reset() {this->P->Reset();}; + + int *GetPoint(int i) {return this->P->GetPointer(3*i);}; + int InsertNextPoint(int *x); + + protected: + vtkIntArray *P; +}; + +inline int vtkNeighborCells::InsertNextPoint(int *x) +{ + int id = this->P->GetMaxId() + 3; + this->P->InsertValue(id,x[2]); + this->P->SetValue(id-2, x[0]); + this->P->SetValue(id-1, x[1]); + return id/3; +} + +// Construct with automatic computation of divisions, averaging +// 25 cells per bucket. +vtkCellLocator::vtkCellLocator() +{ + this->NumberOfCellsPerBucket = 25; + this->Tree = NULL; + this->CellHasBeenVisited = NULL; + this->QueryNumber = 0; + this->H[0] = this->H[1] = this->H[2] = 1.0; + this->NumberOfDivisions = 1; + + this->Buckets = new vtkNeighborCells(10, 10); + this->CacheCellBounds = 0; + this->CellBounds = NULL; +} + +vtkCellLocator::~vtkCellLocator() +{ + if (this->Buckets) + { + delete this->Buckets; + this->Buckets = NULL; + } + + this->FreeSearchStructure(); + + if (this->CellHasBeenVisited) + { + delete [] this->CellHasBeenVisited; + this->CellHasBeenVisited = NULL; + } + + if (this->CellBounds) + { + delete [] this->CellBounds; + this->CellBounds = NULL; + } +} + +void vtkCellLocator::FreeSearchStructure() +{ + vtkIdList *cellIds; + int i; + + if ( this->Tree ) + { + for (i=0; iNumberOfOctants; i++) + { + cellIds = this->Tree[i]; + if (cellIds == (void *)VTK_CELL_INSIDE) + { + cellIds = 0; + } + if (cellIds) + { + cellIds->Delete(); + } + } + delete [] this->Tree; + this->Tree = NULL; + } +} + +// Given an offset into the structure, the number of divisions in the octree, +// an i,j,k location in the octree; return the index (idx) into the structure. +// Method returns 1 is the specified i,j,k location is "outside" of the octree. +int vtkCellLocator::GenerateIndex(int offset, int numDivs, int i, int j, + int k, vtkIdType &idx) +{ + if ( i < 0 || i >= numDivs || + j < 0 || j >= numDivs || k < 0 || k >= numDivs ) + { + return 1; + } + + idx = offset + i + j*numDivs + k*numDivs*numDivs; + + return 0; +} + + +// Return intersection point (if any) of finite line with cells contained +// in cell locator. +int vtkCellLocator::IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId) +{ + vtkIdType cellId = -1; + + return this->IntersectWithLine( a0, a1, tol, t, x, pcoords, + subId, cellId); +} + +void vtkCellLocator::ComputeOctantBounds(int i, int j, int k) +{ + this->OctantBounds[0] = this->Bounds[0] + i*H[0]; + this->OctantBounds[1] = this->OctantBounds[0] + H[0]; + this->OctantBounds[2] = this->Bounds[2] + j*H[1]; + this->OctantBounds[3] = this->OctantBounds[2] + H[1]; + this->OctantBounds[4] = this->Bounds[4] + k*H[2]; + this->OctantBounds[5] = this->OctantBounds[4] + H[2]; +} + +// Return intersection point (if any) AND the cell which was intersected by +// finite line +int vtkCellLocator::IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId) +{ + vtkGenericCell *cell=vtkGenericCell::New(); + int returnVal; + + returnVal = this->IntersectWithLine( a0, a1, tol, t, x, pcoords, subId, + cellId, cell); + + cell->Delete(); + return returnVal; +} + + +// Return intersection point (if any) AND the cell which was intersected by +// finite line +int vtkCellLocator::IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId, + vtkGenericCell *cell) +{ + double origin[3]; + double direction1[3]; + double direction2[3]; + double direction3[3]; + double hitPosition[3]; + double hitCellBoundsPosition[3], cellBounds[6]; + int hitCellBounds; + double result; + double bounds2[6]; + int i, leafStart, prod, loop; + vtkIdType bestCellId = -1, cId; + int idx; + double tMax, dist[3]; + int npos[3]; + int pos[3]; + int bestDir; + double stopDist, currDist; + double deltaT, pDistance, minPDistance=1.0e38; + double length, maxLength=0.0; + + // convert the line into i,j,k coordinates + tMax = 0.0; + for (i=0; i < 3; i++) + { + direction1[i] = a1[i] - a0[i]; + length = this->Bounds[2*i+1] - this->Bounds[2*i]; + if ( length > maxLength ) + { + maxLength = length; + } + origin[i] = (a0[i] - this->Bounds[2*i]) / length; + direction2[i] = direction1[i]/length; + + bounds2[2*i] = 0.0; + bounds2[2*i+1] = 1.0; + tMax += direction2[i]*direction2[i]; + } + + // create a parametric range around the tolerance + deltaT = tol/maxLength; + + stopDist = tMax*this->NumberOfDivisions; + for (i = 0; i < 3; i++) + { + direction3[i] = direction2[i]/tMax; + } + + if (vtkBox::IntersectBox(bounds2, origin, direction2, hitPosition, result)) + { + // start walking through the octants + prod = this->NumberOfDivisions*this->NumberOfDivisions; + leafStart = this->NumberOfOctants - this->NumberOfDivisions*prod; + bestCellId = -1; + + // Clear the array that indicates whether we have visited this cell. + // The array is only cleared when the query number rolls over. This + // saves a number of calls to memset. + this->QueryNumber++; + if (this->QueryNumber == 0) + { + this->ClearCellHasBeenVisited(); + this->QueryNumber++; // can't use 0 as a marker + } + + // set up curr and stop dist + currDist = 0; + for (i = 0; i < 3; i++) + { + currDist += (hitPosition[i] - origin[i])*(hitPosition[i] - origin[i]); + } + currDist = sqrt(currDist)*this->NumberOfDivisions; + + // add one offset due to the problems around zero + for (loop = 0; loop <3; loop++) + { + hitPosition[loop] = hitPosition[loop]*this->NumberOfDivisions + 1.0; + pos[loop] = (int)hitPosition[loop]; + // Adjust right boundary condition: if we intersect from the top, right, + // or back; then pos must be adjusted to a valid octant index + if (pos[loop] > this->NumberOfDivisions) + { + pos[loop] = this->NumberOfDivisions; + } + } + + idx = leafStart + pos[0] - 1 + (pos[1] - 1)*this->NumberOfDivisions + + (pos[2] - 1)*prod; + + while ((bestCellId < 0) && (pos[0] > 0) && (pos[1] > 0) && (pos[2] > 0) && + (pos[0] <= this->NumberOfDivisions) && + (pos[1] <= this->NumberOfDivisions) && + (pos[2] <= this->NumberOfDivisions) && + (currDist < stopDist)) + { + if (this->Tree[idx]) + { + this->ComputeOctantBounds(pos[0]-1,pos[1]-1,pos[2]-1); + for (tMax = VTK_DOUBLE_MAX, cellId=0; + cellId < this->Tree[idx]->GetNumberOfIds(); cellId++) + { + cId = this->Tree[idx]->GetId(cellId); + if (this->CellHasBeenVisited[cId] != this->QueryNumber) + { + this->CellHasBeenVisited[cId] = this->QueryNumber; + hitCellBounds = 0; + + // check whether we intersect the cell bounds + if (this->CacheCellBounds) + { + hitCellBounds = vtkBox::IntersectBox(this->CellBounds[cId], + a0, direction1, + hitCellBoundsPosition, result); + } + else + { + this->DataSet->GetCellBounds(cId, cellBounds); + hitCellBounds = vtkBox::IntersectBox(cellBounds, + a0, direction1, + hitCellBoundsPosition, result); + } + + if (hitCellBounds) + { + // now, do the expensive GetCell call and the expensive + // intersect with line call + this->DataSet->GetCell(cId, cell); + if (cell->IntersectWithLine(a0, a1, tol, t, x, pcoords, subId) ) + { + if ( ! this->IsInOctantBounds(x) ) + { + this->CellHasBeenVisited[cId] = 0; //mark the cell non-visited + } + else + { + if ( t < (tMax+deltaT) ) //it might be close + { + pDistance = cell->GetParametricDistance(pcoords); + if ( pDistance < minPDistance || + (pDistance == minPDistance && t < tMax) ) + { + tMax = t; + minPDistance = pDistance; + bestCellId = cId; + } + } //intersection point is in current octant + } //if within current parametric range + } // if intersection + } // if (hitCellBounds) + } // if (!this->CellHasBeenVisited[cId]) + } + } + + // move to the next octant + tMax = VTK_DOUBLE_MAX; + bestDir = 0; + for (loop = 0; loop < 3; loop++) + { + if (direction3[loop] > 0) + { + npos[loop] = pos[loop] + 1; + dist[loop] = (1.0 - hitPosition[loop] + pos[loop])/direction3[loop]; + if (dist[loop] == 0) + { + dist[loop] = 1.0/direction3[loop]; + } + if (dist[loop] < 0) + { + dist[loop] = 0; + } + if (dist[loop] < tMax) + { + bestDir = loop; + tMax = dist[loop]; + } + } + if (direction3[loop] < 0) + { + npos[loop] = pos[loop] - 1; + dist[loop] = (pos[loop] - hitPosition[loop])/direction3[loop]; + if (dist[loop] == 0) + { + dist[loop] = -0.01/direction3[loop]; + } + if (dist[loop] < 0) + { + dist[loop] = 0; + } + if (dist[loop] < tMax) + { + bestDir = loop; + tMax = dist[loop]; + } + } + } + // update our position + for (loop = 0; loop < 3; loop++) + { + hitPosition[loop] += dist[bestDir]*direction3[loop]; + } + currDist += dist[bestDir]; + // now make the move, find the smallest distance + // only cross one boundry at a time + pos[bestDir] = npos[bestDir]; + + idx = leafStart + pos[0] - 1 + (pos[1]-1)*this->NumberOfDivisions + + (pos[2]-1)*prod; + } + } + + if (bestCellId >= 0) + { + this->DataSet->GetCell(bestCellId, cell); + cell->IntersectWithLine(a0, a1, tol, t, x, pcoords, subId); + + // store the best cell id in the return "parameter" + cellId = bestCellId; + return 1; + } + + return 0; +} + +// Return closest point (if any) AND the cell on which this closest point lies +void vtkCellLocator::FindClosestPoint(double x[3], double closestPoint[3], + vtkGenericCell *cell, vtkIdType &cellId, + int &subId, double& dist2) +{ + int i; + vtkIdType j; + int *nei; + vtkIdType closestCell = -1; + int closestSubCell = -1; + int leafStart; + int level; + int ijk[3]; + double minDist2, refinedRadius2, distance2ToBucket; + double distance2ToCellBounds, cellBounds[6]; + double pcoords[3], point[3], cachedPoint[3], weightsArray[6]; + double *weights = weightsArray; + int nWeights = 6, nPoints; + vtkIdList *cellIds; + + leafStart = this->NumberOfOctants + - this->NumberOfDivisions*this->NumberOfDivisions*this->NumberOfDivisions; + + // Clear the array that indicates whether we have visited this cell. + // The array is only cleared when the query number rolls over. This + // saves a number of calls to memset. + this->QueryNumber++; + if (this->QueryNumber == 0) + { + this->ClearCellHasBeenVisited(); + this->QueryNumber++; // can't use 0 as a marker + } + + // init + dist2 = -1.0; + refinedRadius2 = VTK_DOUBLE_MAX; + + // + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)((x[j] - this->Bounds[2*j]) / this->H[j]); + + if (ijk[j] < 0) + { + ijk[j] = 0; + } + else if (ijk[j] >= this->NumberOfDivisions) + { + ijk[j] = this->NumberOfDivisions-1; + } + } + // + // Need to search this bucket for closest point. If there are no + // cells in this bucket, search 1st level neighbors, and so on, + // until closest point found. + // + for (closestCell=(-1),minDist2=VTK_DOUBLE_MAX,level=0; + (closestCell == -1) && (level < this->NumberOfDivisions); level++) + { + this->GetBucketNeighbors(ijk, this->NumberOfDivisions, level); + + for (i=0; iBuckets->GetNumberOfNeighbors(); i++) + { + nei = this->Buckets->GetPoint(i); + + // if a neighboring bucket has cells, + if ( (cellIds = + this->Tree[leafStart + nei[0] + nei[1]*this->NumberOfDivisions + + nei[2]*this->NumberOfDivisions*this->NumberOfDivisions]) != NULL ) + { + // do we still need to test this bucket? + distance2ToBucket = this->Distance2ToBucket(x, nei); + + if (distance2ToBucket < refinedRadius2) + { + // still a viable bucket + for (j=0; j < cellIds->GetNumberOfIds(); j++) + { + // get the cell + cellId = cellIds->GetId(j); + if (this->CellHasBeenVisited[cellId] != this->QueryNumber) + { + this->CellHasBeenVisited[cellId] = this->QueryNumber; + + // check whether we could be close enough to the cell by + // testing the cell bounds + if (this->CacheCellBounds) + { + distance2ToCellBounds = + this->Distance2ToBounds(x, this->CellBounds[cellId]); + } + else + { + this->DataSet->GetCellBounds(cellId, cellBounds); + distance2ToCellBounds = this->Distance2ToBounds(x, cellBounds); + } + + if (distance2ToCellBounds < refinedRadius2) + { + this->DataSet->GetCell(cellId, cell); + + // make sure we have enough storage space for the weights + nPoints = cell->GetPointIds()->GetNumberOfIds(); + if (nPoints > nWeights) + { + if (nWeights > 6) + { + delete [] weights; + } + weights = new double[2*nPoints]; // allocate some extra room + nWeights = 2*nPoints; + } + + // evaluate the position to find the closest point + int stat=cell->EvaluatePosition(x, point, subId, pcoords, + dist2, weights); + + if ( stat != -1 && dist2 < minDist2 ) + { + closestCell = cellId; + closestSubCell = subId; + minDist2 = dist2; + cachedPoint[0] = point[0]; + cachedPoint[1] = point[1]; + cachedPoint[2] = point[2]; + refinedRadius2 = dist2; + } + } + } // if (!this->CellHasBeenVisited[cellId]) + } + } + } + } + } + + // Because of the relative location of the points in the buckets, the + // cell found previously may not be the closest cell. Have to + // search those bucket neighbors that might also contain nearby cells. + // + if ( (minDist2 > 0.0) && (level < this->NumberOfDivisions)) + { + int prevMinLevel[3], prevMaxLevel[3]; + // setup prevMinLevel and prevMaxLevel to indicate previously visited + // buckets + if (--level < 0) + { + level = 0; + } + for (i = 0; i < 3; i++) + { + prevMinLevel[i] = ijk[i] - level; + if (prevMinLevel[i] < 0) + { + prevMinLevel[i] = 0; + } + prevMaxLevel[i] = ijk[i] + level; + if (prevMaxLevel[i] >= this->NumberOfDivisions) + { + prevMaxLevel[i] = this->NumberOfDivisions - 1; + } + } + this->GetOverlappingBuckets(x, ijk, sqrt(minDist2), prevMinLevel, + prevMaxLevel); + + for (i=0; iBuckets->GetNumberOfNeighbors(); i++) + { + nei = this->Buckets->GetPoint(i); + + if ( (cellIds = + this->Tree[leafStart + nei[0] + nei[1]*this->NumberOfDivisions + + nei[2]*this->NumberOfDivisions*this->NumberOfDivisions]) != NULL ) + { + // do we still need to test this bucket? + distance2ToBucket = this->Distance2ToBucket(x, nei); + + if (distance2ToBucket < refinedRadius2) + { + // still a viable bucket + for (j=0; j < cellIds->GetNumberOfIds(); j++) + { + // get the cell + cellId = cellIds->GetId(j); + if (this->CellHasBeenVisited[cellId] != this->QueryNumber) + { + this->CellHasBeenVisited[cellId] = this->QueryNumber; + + // check whether we could be close enough to the cell by + // testing the cell bounds + if (this->CacheCellBounds) + { + distance2ToCellBounds = + this->Distance2ToBounds(x, this->CellBounds[cellId]); + } + else + { + this->DataSet->GetCellBounds(cellId, cellBounds); + distance2ToCellBounds = this->Distance2ToBounds(x, cellBounds); + } + + if (distance2ToCellBounds < refinedRadius2) + { + this->DataSet->GetCell(cellId, cell); + + // make sure we have enough storage space for the weights + nPoints = cell->GetPointIds()->GetNumberOfIds(); + if (nPoints > nWeights) + { + if (nWeights > 6) + { + delete [] weights; + } + weights = new double[2*nPoints]; // allocate some extra room + nWeights = 2*nPoints; + } + + // evaluate the position to find the closest point + cell->EvaluatePosition(x, point, subId, pcoords, + dist2, weights); + + if ( dist2 < minDist2 ) + { + closestCell = cellId; + closestSubCell = subId; + minDist2 = dist2; + cachedPoint[0] = point[0]; + cachedPoint[1] = point[1]; + cachedPoint[2] = point[2]; + refinedRadius2 = dist2; + } + }//if point close enough to cell bounds + }//if cell has not been visited + }//for each cell + }//if bucket is still viable + }//if cells in bucket + }//for each overlapping bucket + }//if not identical point + + if (closestCell != -1) + { + dist2 = minDist2; + cellId = closestCell; + subId = closestSubCell; + closestPoint[0] = cachedPoint[0]; + closestPoint[1] = cachedPoint[1]; + closestPoint[2] = cachedPoint[2]; + this->DataSet->GetCell(cellId, cell); + } + + if (nWeights > 6) + { + delete [] weights; + } +} + + +// Return closest point (if any) AND the cell on which this closest point lies +void vtkCellLocator::FindClosestPoint(double x[3], double closestPoint[3], + vtkIdType &cellId, int &subId, + double& dist2) +{ + vtkGenericCell *cell = vtkGenericCell::New(); + + this->FindClosestPoint(x, closestPoint, cell, cellId, subId, dist2); + + cell->Delete(); +} + +int vtkCellLocator::FindClosestPointWithinRadius(double x[3], double radius, + double closestPoint[3], + vtkGenericCell *cell, + vtkIdType &cellId, int &subId, + double& dist2, int &inside) +{ + int i; + vtkIdType j; + int tmpInside; + int *nei; + int closestCell = -1; + int closestSubCell = -1; + int leafStart; + int ijk[3]; + double minDist2; + double pcoords[3], point[3], cachedPoint[3], weightsArray[6]; + double *weights = weightsArray; + int nWeights = 6, nPoints; + int returnVal = 0; + vtkIdList *cellIds; + + double refinedRadius, radius2, refinedRadius2, distance2ToBucket; + double distance2ToCellBounds, cellBounds[6], currentRadius; + double distance2ToDataBounds, maxDistance; + int ii, radiusLevels[3], radiusLevel, prevMinLevel[3], prevMaxLevel[3]; + + leafStart = this->NumberOfOctants + - this->NumberOfDivisions*this->NumberOfDivisions*this->NumberOfDivisions; + + // Clear the array that indicates whether we have visited this cell. + // The array is only cleared when the query number rolls over. This + // saves a number of calls to memset. + this->QueryNumber++; + if (this->QueryNumber == 0) + { + this->ClearCellHasBeenVisited(); + this->QueryNumber++; // can't use 0 as a marker + } + + // init + dist2 = -1.0; + closestCell = -1; + radius2 = radius*radius; + minDist2 = 1.1*radius2; // something slightly bigger.... + refinedRadius = radius; + refinedRadius2 = radius2; + + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)((x[j] - this->Bounds[2*j]) / this->H[j]); + + if (ijk[j] < 0) + { + ijk[j] = 0; + } + else if (ijk[j] >= this->NumberOfDivisions) + { + ijk[j] = this->NumberOfDivisions-1; + } + } + + // Start by searching the bucket that the point is in. + // + if ((cellIds = + this->Tree[leafStart + ijk[0] + ijk[1]*this->NumberOfDivisions + + ijk[2]*this->NumberOfDivisions*this->NumberOfDivisions]) != NULL ) + { + // query each cell + for (j=0; j < cellIds->GetNumberOfIds(); j++) + { + // get the cell + cellId = cellIds->GetId(j); + if (this->CellHasBeenVisited[cellId] != this->QueryNumber) + { + this->CellHasBeenVisited[cellId] = this->QueryNumber; + + // check whether we could be close enough to the cell by + // testing the cell bounds + if (this->CacheCellBounds) + { + distance2ToCellBounds = + this->Distance2ToBounds(x, this->CellBounds[cellId]); + } + else + { + this->DataSet->GetCellBounds(cellId, cellBounds); + distance2ToCellBounds = this->Distance2ToBounds(x, cellBounds); + } + + if (distance2ToCellBounds < refinedRadius2) + { + this->DataSet->GetCell(cellId, cell); + + // make sure we have enough storage space for the weights + nPoints = cell->GetPointIds()->GetNumberOfIds(); + if (nPoints > nWeights) + { + if (nWeights > 6) + { + delete [] weights; + } + weights = new double[2*nPoints]; // allocate some extra room + nWeights = 2*nPoints; + } + + // evaluate the position to find the closest point + tmpInside = cell->EvaluatePosition(x, point, subId, pcoords, + dist2, weights); + if ( dist2 < minDist2 ) + { + inside = tmpInside; + closestCell = cellId; + closestSubCell = subId; + minDist2 = dist2; + cachedPoint[0] = point[0]; + cachedPoint[1] = point[1]; + cachedPoint[2] = point[2]; + refinedRadius = sqrt(dist2); + refinedRadius2 = dist2; + } + } + } // if (this->CellHasBeenVisited[cellId]) + } + } + + // Now, search only those buckets that are within a radius. The radius used + // is the smaller of sqrt(dist2) and the radius that is passed in. To avoid + // checking a large number of buckets unnecessarily, if the radius is + // larger than the dimensions of a bucket, we search outward using a + // simple heuristic of rings. This heuristic ends up collecting inner + // buckets multiple times, but this only happens in the case where these + // buckets are empty, so they are discarded quickly. + // + if (dist2 < radius2 && dist2 >= 0.0) + { + refinedRadius = sqrt(dist2); + refinedRadius2 = dist2; + } + else + { + refinedRadius = radius; + refinedRadius2 = radius2; + } + + + distance2ToDataBounds = this->Distance2ToBounds(x, this->Bounds); + maxDistance = sqrt(distance2ToDataBounds) + this->DataSet->GetLength(); + if (refinedRadius > maxDistance) + { + refinedRadius = maxDistance; + refinedRadius2 = maxDistance*maxDistance; + } + + radiusLevels[0] = (int)(refinedRadius/this->H[0]); + radiusLevels[1] = (int)(refinedRadius/this->H[1]); + radiusLevels[2] = (int)(refinedRadius/this->H[2]); + + radiusLevel = radiusLevels[0]; + radiusLevel = radiusLevels[1] > radiusLevel ? radiusLevels[1] : radiusLevel; + radiusLevel = radiusLevels[2] > radiusLevel ? radiusLevels[2] : radiusLevel; + + if (radiusLevel > this->NumberOfDivisions / 2 ) + { + radiusLevel = this->NumberOfDivisions / 2; + } + if (radiusLevel == 0) + { + radiusLevel = 1; + } + + // radius schedule increases the radius each iteration, this is currently + // implemented by decreasing ii by 1 each iteration. another alternative + // is to double the radius each iteration, i.e. ii = ii >> 1 + // In practice, reducing ii by one has been found to be more efficient. + int numberOfBucketsPerPlane; + numberOfBucketsPerPlane = this->NumberOfDivisions*this->NumberOfDivisions; + prevMinLevel[0] = prevMaxLevel[0] = ijk[0]; + prevMinLevel[1] = prevMaxLevel[1] = ijk[1]; + prevMinLevel[2] = prevMaxLevel[2] = ijk[2]; + for (ii=radiusLevel; ii >= 1; ii--) + { + currentRadius = refinedRadius; // used in if at bottom of this for loop + + // Build up a list of buckets that are arranged in rings + this->GetOverlappingBuckets(x, ijk, refinedRadius/ii, prevMinLevel, + prevMaxLevel); + + for (i=0; iBuckets->GetNumberOfNeighbors(); i++) + { + nei = this->Buckets->GetPoint(i); + + if ( (cellIds = + this->Tree[leafStart + nei[0] + nei[1]*this->NumberOfDivisions + + nei[2]*numberOfBucketsPerPlane]) != NULL ) + { + // do we still need to test this bucket? + distance2ToBucket = this->Distance2ToBucket(x, nei); + + if (distance2ToBucket < refinedRadius2) + { + // still a viable bucket + for (j=0; j < cellIds->GetNumberOfIds(); j++) + { + // get the cell + cellId = cellIds->GetId(j); + if (this->CellHasBeenVisited[cellId] != this->QueryNumber) + { + this->CellHasBeenVisited[cellId] = this->QueryNumber; + + // check whether we could be close enough to the cell by + // testing the cell bounds + if (this->CacheCellBounds) + { + distance2ToCellBounds = + this->Distance2ToBounds(x, this->CellBounds[cellId]); + } + else + { + this->DataSet->GetCellBounds(cellId, cellBounds); + distance2ToCellBounds = this->Distance2ToBounds(x, cellBounds); + } + + if (distance2ToCellBounds < refinedRadius2) + { + this->DataSet->GetCell(cellId, cell); + + // make sure we have enough storage space for the weights + nPoints = cell->GetPointIds()->GetNumberOfIds(); + if (nPoints > nWeights) + { + if (nWeights > 6) + { + delete [] weights; + } + weights = new double[2*nPoints]; // allocate some extra room + nWeights = 2*nPoints; + } + + // evaluate the position to find the closest point + tmpInside = cell->EvaluatePosition(x, point, subId, pcoords, + dist2, weights); + + if ( dist2 < minDist2 ) + { + inside = tmpInside; + closestCell = cellId; + closestSubCell = subId; + minDist2 = dist2; + cachedPoint[0] = point[0]; + cachedPoint[1] = point[1]; + cachedPoint[2] = point[2]; + refinedRadius = sqrt(minDist2); + refinedRadius2 = minDist2; + } + }//if point close enough to cell bounds + }//if cell has not been visited + }//for each cell in bucket + }//if bucket is within the current best distance + }//if cells in bucket + }//for each overlapping bucket + + // don't want to checker a smaller radius than we just checked so update + // ii appropriately + if (refinedRadius < currentRadius && ii > 2) //always check ii==1 + { + ii = (int)((double)ii * (refinedRadius / currentRadius)) + 1; + if (ii < 2) + { + ii = 2; + } + } + }//for each radius in the radius schedule + + if ((closestCell != -1) && (minDist2 <= radius2)) + { + dist2 = minDist2; + cellId = closestCell; + subId = closestSubCell; + closestPoint[0] = cachedPoint[0]; + closestPoint[1] = cachedPoint[1]; + closestPoint[2] = cachedPoint[2]; + this->DataSet->GetCell(cellId, cell); + returnVal = 1; + } + + if (nWeights > 6) + { + delete [] weights; + } + + return returnVal; +} + +int vtkCellLocator::FindClosestPointWithinRadius(double x[3], double radius, + double closestPoint[3], + vtkGenericCell *cell, + vtkIdType &cellId, + int &subId, double& dist2) +{ + int inside; + + return + this->FindClosestPointWithinRadius(x, radius, closestPoint, + cell, cellId, subId, dist2, inside); +} + +int vtkCellLocator::FindClosestPointWithinRadius(double x[3], double radius, + double closestPoint[3], + vtkIdType &cellId, int &subId, + double& dist2) +{ + vtkGenericCell *cell = vtkGenericCell::New(); + int found, inside; + + found = + this->FindClosestPointWithinRadius(x, radius, closestPoint, + cell, cellId, subId, dist2, inside); + cell->Delete(); + return found; +} + +// +// Internal function to get bucket neighbors at specified "level". The +// bucket neighbors are indices into the "leaf-node" layer of the octree. +// These indices must be offset by number of octants before the leaf node +// layer before they can be used. Only those buckets with cells are returned. +// +void vtkCellLocator::GetBucketNeighbors(int ijk[3], int ndivs, int level) +{ + int i, j, k, min, max, minLevel[3], maxLevel[3]; + int nei[3]; + int leafStart; + int numberOfBucketsPerPlane; + + numberOfBucketsPerPlane = this->NumberOfDivisions*this->NumberOfDivisions; + leafStart = this->NumberOfOctants + - numberOfBucketsPerPlane*this->NumberOfDivisions; + + // Initialize + // + this->Buckets->Reset(); + + // If at this bucket, just place into list + // + if ( level == 0 ) + { + if (this->Tree[leafStart + ijk[0] + ijk[1]*this->NumberOfDivisions + + ijk[2]*numberOfBucketsPerPlane]) + { + this->Buckets->InsertNextPoint(ijk); + } + return; + } + + // Create permutations of the ijk indices that are at the level + // required. If these are legal buckets, add to list for searching. + // + for ( i=0; i<3; i++ ) + { + min = ijk[i] - level; + max = ijk[i] + level; + minLevel[i] = ( min > 0 ? min : 0); + maxLevel[i] = ( max < (ndivs-1) ? max : (ndivs-1)); + } + + for ( k= minLevel[2]; k <= maxLevel[2]; k++ ) + { + for ( j= minLevel[1]; j <= maxLevel[1]; j++ ) + { + for ( i= minLevel[0]; i <= maxLevel[0]; i++ ) + { + if (i == (ijk[0] + level) || i == (ijk[0] - level) || + j == (ijk[1] + level) || j == (ijk[1] - level) || + k == (ijk[2] + level) || k == (ijk[2] - level) ) + { + if (this->Tree[leafStart + i + j*this->NumberOfDivisions + + k*numberOfBucketsPerPlane]) + { + nei[0]=i; nei[1]=j; nei[2]=k; + this->Buckets->InsertNextPoint(nei); + } + } + } + } + } + + return; +} + +// Internal method to find those buckets that are within distance specified. +// Only those buckets outside of level radiuses of ijk are returned. The +// bucket neighbors are indices into the "leaf-node" layer of the octree. +// These indices must be offset by number of octants before the leaf node +// layer before they can be used. Only buckets that have cells are placed +// in the bucket list. +// +void vtkCellLocator::GetOverlappingBuckets(double x[3], int vtkNotUsed(ijk)[3], + double dist, + int prevMinLevel[3], + int prevMaxLevel[3]) +{ + int i, j, k, nei[3], minLevel[3], maxLevel[3]; + int leafStart, kFactor, jFactor; + int numberOfBucketsPerPlane, jkSkipFlag, kSkipFlag; + + numberOfBucketsPerPlane = this->NumberOfDivisions*this->NumberOfDivisions; + leafStart = this->NumberOfOctants + - numberOfBucketsPerPlane*this->NumberOfDivisions; + + // Initialize + this->Buckets->Reset(); + + // Determine the range of indices in each direction + for (i=0; i < 3; i++) + { + minLevel[i] = (int) ((double) (((x[i]-dist) - this->Bounds[2*i]) + / this->H[i])); + maxLevel[i] = (int) ((double) (((x[i]+dist) - this->Bounds[2*i]) + / this->H[i])); + + if ( minLevel[i] < 0 ) + { + minLevel[i] = 0; + } + else if (minLevel[i] >= this->NumberOfDivisions ) + { + minLevel[i] = this->NumberOfDivisions - 1; + } + if ( maxLevel[i] >= this->NumberOfDivisions ) + { + maxLevel[i] = this->NumberOfDivisions - 1; + } + else if ( maxLevel[i] < 0 ) + { + maxLevel[i] = 0; + } + } + + if (minLevel[0] == prevMinLevel[0] && maxLevel[0] == prevMaxLevel[0] && + minLevel[1] == prevMinLevel[1] && maxLevel[1] == prevMaxLevel[1] && + minLevel[2] == prevMinLevel[2] && maxLevel[2] == prevMaxLevel[2] ) + { + return; + } + + for ( k= minLevel[2]; k <= maxLevel[2]; k++ ) + { + kFactor = k*numberOfBucketsPerPlane; + if (k >= prevMinLevel[2] && k <= prevMaxLevel[2]) + { + kSkipFlag = 1; + } + else + { + kSkipFlag = 0; + } + for ( j= minLevel[1]; j <= maxLevel[1]; j++ ) + { + if (kSkipFlag && j >= prevMinLevel[1] && j <= prevMaxLevel[1]) + { + jkSkipFlag = 1; + } + else + { + jkSkipFlag = 0; + } + jFactor = j*this->NumberOfDivisions; + for ( i= minLevel[0]; i <= maxLevel[0]; i++ ) + { + if ( jkSkipFlag && i == prevMinLevel[0] ) + { + i = prevMaxLevel[0]; + continue; + } + // if this bucket has any cells, add it to the list + if (this->Tree[leafStart + i + jFactor + kFactor]) + { + nei[0]=i; nei[1]=j; nei[2]=k; + this->Buckets->InsertNextPoint(nei); + } + } + } + } + + prevMinLevel[0] = minLevel[0]; + prevMinLevel[1] = minLevel[1]; + prevMinLevel[2] = minLevel[2]; + prevMaxLevel[0] = maxLevel[0]; + prevMaxLevel[1] = maxLevel[1]; + prevMaxLevel[2] = maxLevel[2]; +} + +// number of buckets available +int vtkCellLocator::GetNumberOfBuckets(void) +{ + if (this->Tree) + { + return this->NumberOfOctants; + } + else + { + vtkWarningMacro(<<"Attempting to access Tree before Locator has been built"); + return 0; + } +} + +// Get the cells in a bucket. +vtkIdList* vtkCellLocator::GetCells(int octantId) +{ + // handle parents ? + return this->Tree[octantId]; +} + + +// Method to form subdivision of space based on the cells provided and +// subject to the constraints of levels and NumberOfCellsPerBucket. +// The result is directly addressable and of uniform subdivision. +// +void vtkCellLocator::BuildLocator() + { + double *bounds, length, cellBounds[6], *boundsPtr; + vtkIdType numCells; + int ndivs, product; + int i, j, k, ijkMin[3], ijkMax[3]; + vtkIdType cellId, idx; + int parentOffset; + vtkIdList *octant; + int numCellsPerBucket = this->NumberOfCellsPerBucket; + typedef vtkIdList *vtkIdListPtr; + int prod, numOctants; + double hTol[3]; + + if ( (this->Tree != NULL) && (this->BuildTime > this->MTime) + && (this->BuildTime > this->DataSet->GetMTime()) ) + { + return; + } + + vtkDebugMacro( << "Subdividing octree..." ); + + if ( !this->DataSet || (numCells = this->DataSet->GetNumberOfCells()) < 1 ) + { + vtkErrorMacro( << "No cells to subdivide"); + return; + } + + // Make sure the appropriate data is available + // + if ( this->Tree ) + { + this->FreeSearchStructure(); + } + if ( this->CellHasBeenVisited ) + { + delete [] this->CellHasBeenVisited; + this->CellHasBeenVisited = NULL; + } + if (this->CellBounds) + { + delete [] this->CellBounds; + this->CellBounds = NULL; + } + + // Size the root cell. Initialize cell data structure, compute + // level and divisions. + // + bounds = this->DataSet->GetBounds(); + length = this->DataSet->GetLength(); + for (i=0; i<3; i++) + { + this->Bounds[2*i] = bounds[2*i]; + this->Bounds[2*i+1] = bounds[2*i+1]; + if ( (this->Bounds[2*i+1] - this->Bounds[2*i]) <= (length/1000.0) ) + { + // bump out the bounds a little of if min==max + this->Bounds[2*i] -= length/100.0; + this->Bounds[2*i+1] += length/100.0; + } + } + + if ( this->Automatic ) + { + this->Level = (int) (ceil(log((double)numCells/numCellsPerBucket) / + (log((double) 8.0)))); + } + this->Level =(this->Level > this->MaxLevel ? this->MaxLevel : this->Level); + + // compute number of octants and number of divisions + for (ndivs=1,prod=1,numOctants=1,i=0; iLevel; i++) + { + ndivs *= 2; + prod *= 8; + numOctants += prod; + } + this->NumberOfDivisions = ndivs; + this->NumberOfOctants = numOctants; + + this->Tree = new vtkIdListPtr[numOctants]; + memset (this->Tree, 0, numOctants*sizeof(vtkIdListPtr)); + + this->CellHasBeenVisited = new unsigned char [ numCells ]; + this->ClearCellHasBeenVisited(); + this->QueryNumber = 0; + + if (this->CacheCellBounds) + { + this->CellBounds = new double [numCells][6]; + } + + // Compute width of leaf octant in three directions + // + for (i=0; i<3; i++) + { + this->H[i] = (this->Bounds[2*i+1] - this->Bounds[2*i]) / ndivs; + hTol[i] = this->H[i]/100.0; + } + + // Insert each cell into the appropriate octant. Make sure cell + // falls within octant. + // + parentOffset = numOctants - (ndivs * ndivs * ndivs); + product = ndivs * ndivs; + boundsPtr = cellBounds; + for (cellId=0; cellIdCacheCellBounds) + { + boundsPtr = this->CellBounds[cellId]; + this->DataSet->GetCellBounds(cellId, boundsPtr); + } + else + { + this->DataSet->GetCellBounds(cellId, cellBounds); + } + + // find min/max locations of bounding box + for (i=0; i<3; i++) + { + ijkMin[i] = (int)((boundsPtr[2*i] - this->Bounds[2*i] - hTol[i]) + / this->H[i]); + ijkMax[i] = (int)((boundsPtr[2*i+1] - this->Bounds[2*i] + hTol[i]) + / this->H[i]); + + if (ijkMin[i] < 0) + { + ijkMin[i] = 0; + } + if (ijkMax[i] >= ndivs) + { + ijkMax[i] = ndivs-1; + } + } + + // each octant inbetween min/max point may have cell in it + for ( k = ijkMin[2]; k <= ijkMax[2]; k++ ) + { + for ( j = ijkMin[1]; j <= ijkMax[1]; j++ ) + { + for ( i = ijkMin[0]; i <= ijkMax[0]; i++ ) + { + idx = parentOffset + i + j*ndivs + k*product; + this->MarkParents((void*)VTK_CELL_INSIDE,i,j,k,ndivs,this->Level); + octant = this->Tree[idx]; + if ( ! octant ) + { + octant = vtkIdList::New(); + octant->Allocate(numCellsPerBucket,numCellsPerBucket/2); + this->Tree[idx] = octant; + } + octant->InsertNextId(cellId); + } + } + } + + } //for all cells + + this->BuildTime.Modified(); +} + +void vtkCellLocator::MarkParents(void* a, int i, int j, int k, + int ndivs, int level) +{ + int offset, prod, ii; + vtkIdType parentIdx; + + for (offset=0, prod=1, ii=0; ii 0 ) + { + i = i >> 1; + j = j >> 1; + k = k >> 1; + ndivs = ndivs >> 1; + level--; + + parentIdx = offset + i + j*ndivs + k*ndivs*ndivs; + + // if it already matches just return + if (a == this->Tree[parentIdx]) + { + return; + } + + this->Tree[parentIdx] = (vtkIdList *)a; + + prod = prod >> 3; + offset -= prod; + } +} + +void vtkCellLocator::GenerateRepresentation(int level, vtkPolyData *pd) +{ + vtkPoints *pts; + vtkCellArray *polys; + int l, i, j, k, ii, boundary[3]; + vtkIdType idx; + vtkIdList *inside, *Inside[3]; + int numDivs=1; + + if ( this->Tree == NULL ) + { + vtkErrorMacro(<<"No tree to generate representation from"); + return; + } + + pts = vtkPoints::New(); + pts->Allocate(5000); + polys = vtkCellArray::New(); + polys->Allocate(10000); + + // Compute idx into tree at appropriate level; determine if + // faces of octants are visible. + // + int parentIdx = 0; + int numOctants = 1; + + if ( level < 0 ) + { + level = this->Level; + } + for (l=0; l < level; l++) + { + numDivs *= 2; + parentIdx += numOctants; + numOctants *= 8; + } + + //loop over all octabts generating visible faces + for ( k=0; k < numDivs; k++) + { + for ( j=0; j < numDivs; j++) + { + for ( i=0; i < numDivs; i++) + { + this->GenerateIndex(parentIdx,numDivs,i,j,k,idx); + inside = this->Tree[idx]; + + if ( !(boundary[0]=this->GenerateIndex(parentIdx,numDivs,i-1,j,k,idx))) + { + Inside[0] = this->Tree[idx]; + } + if ( !(boundary[1]=this->GenerateIndex(parentIdx,numDivs,i,j-1,k,idx))) + { + Inside[1] = this->Tree[idx]; + } + if ( !(boundary[2]=this->GenerateIndex(parentIdx,numDivs,i,j,k-1,idx))) + { + Inside[2] = this->Tree[idx]; + } + + for (ii=0; ii < 3; ii++) + { + if ( boundary[ii] ) + { + if ( inside ) + { + this->GenerateFace(ii,numDivs,i,j,k,pts,polys); + } + } + else + { + if ( (Inside[ii] && !inside) || (!Inside[ii] && inside) ) + { + this->GenerateFace(ii,numDivs,i,j,k,pts,polys); + } + } + //those buckets on "positive" boundaries can generate faces specially + if ( (i+1) >= numDivs && inside ) + { + this->GenerateFace(0,numDivs,i+1,j,k,pts,polys); + } + if ( (j+1) >= numDivs && inside ) + { + this->GenerateFace(1,numDivs,i,j+1,k,pts,polys); + } + if ( (k+1) >= numDivs && inside ) + { + this->GenerateFace(2,numDivs,i,j,k+1,pts,polys); + } + + }//over negative faces + }//over i divisions + }//over j divisions + }//over k divisions + + pd->SetPoints(pts); + pts->Delete(); + pd->SetPolys(polys); + polys->Delete(); + pd->Squeeze(); +} + +void vtkCellLocator::GenerateFace(int face, int numDivs, int i, int j, int k, + vtkPoints *pts, vtkCellArray *polys) +{ + int ii; + vtkIdType ids[4]; + double origin[3], x[3]; + double h[3]; + + // define first corner; use ids[] as temporary array + ids[0] = i; ids[1] = j; ids[2] = k; + for (ii=0; ii<3; ii++) + { + h[ii] = (this->Bounds[2*ii+1] - this->Bounds[2*ii]) / numDivs; + origin[ii] = this->Bounds[2*ii] + ids[ii]*h[ii]; + } + + ids[0] = pts->InsertNextPoint(origin); + + if ( face == 0 ) //x face + { + x[0] = origin[0]; + x[1] = origin[1] + h[1]; + x[2] = origin[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1] + h[1]; + x[2] = origin[2] + h[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1]; + x[2] = origin[2] + h[2]; + ids[3] = pts->InsertNextPoint(x); + } + + else if ( face == 1 ) //y face + { + x[0] = origin[0] + h[0]; + x[1] = origin[1]; + x[2] = origin[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = origin[0] + h[0]; + x[1] = origin[1]; + x[2] = origin[2] + h[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1]; + x[2] = origin[2] + h[2]; + ids[3] = pts->InsertNextPoint(x); + } + + else //z face + { + x[0] = origin[0] + h[0]; + x[1] = origin[1]; + x[2] = origin[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = origin[0] + h[0]; + x[1] = origin[1] + h[1]; + x[2] = origin[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1] + h[1]; + x[2] = origin[2]; + ids[3] = pts->InsertNextPoint(x); + } + + polys->InsertNextCell(4,ids); +} + +void vtkCellLocator::ClearCellHasBeenVisited() +{ + if (this->CellHasBeenVisited && this->DataSet) + { + memset(this->CellHasBeenVisited, 0, this->DataSet->GetNumberOfCells()); + } +} + +void vtkCellLocator::ClearCellHasBeenVisited(int id) +{ + if (this->CellHasBeenVisited + && this->DataSet && id < this->DataSet->GetNumberOfCells()) + { + this->CellHasBeenVisited[id] = 0; + } +} + +// Calculate the distance between the point x to the bucket "nei". +// +// WARNING!!!!! Be very careful altering this routine. Simple changes to this +// routine can make is 25% slower!!!! +// +double vtkCellLocator::Distance2ToBucket(double x[3], int nei[3]) +{ + double bounds[6]; + + bounds[0] = nei[0]*this->H[0] + this->Bounds[0]; + bounds[1] = (nei[0]+1)*this->H[0] + this->Bounds[0]; + bounds[2] = nei[1]*this->H[1] + this->Bounds[2]; + bounds[3] = (nei[1]+1)*this->H[1] + this->Bounds[2]; + bounds[4] = nei[2]*this->H[2] + this->Bounds[4]; + bounds[5] = (nei[2]+1)*this->H[2] + this->Bounds[4]; + + return this->Distance2ToBounds(x, bounds); +} + +// Calculate the distance between the point x and the specified bounds +// +// WARNING!!!!! Be very careful altering this routine. Simple changes to this +// routine can make it 25% slower!!!! +double vtkCellLocator::Distance2ToBounds(double x[3], double bounds[6]) +{ + double distance; + double deltas[3]; + + // Are we within the bounds? + if (x[0] >= bounds[0] && x[0] <= bounds[1] + && x[1] >= bounds[2] && x[1] <= bounds[3] + && x[2] >= bounds[4] && x[2] <= bounds[5]) + { + return 0.0; + } + + deltas[0] = deltas[1] = deltas[2] = 0.0; + + // dx + // + if (x[0] < bounds[0]) + { + deltas[0] = bounds[0] - x[0]; + } + else if (x[0] > bounds[1]) + { + deltas[0] = x[0] - bounds[1]; + } + + // dy + // + if (x[1] < bounds[2]) + { + deltas[1] = bounds[2] - x[1]; + } + else if (x[1] > bounds[3]) + { + deltas[1] = x[1] - bounds[3]; + } + + // dz + // + if (x[2] < bounds[4]) + { + deltas[2] = bounds[4] - x[2]; + } + else if (x[2] > bounds[5]) + { + deltas[2] = x[2] - bounds[5]; + } + + distance = vtkMath::Dot(deltas, deltas); + return distance; +} + + +void vtkCellLocator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of Cells Per Bucket: " + << this->NumberOfCellsPerBucket << "\n"; + os << indent << "Cache Cell Bounds: " << this->CacheCellBounds << "\n"; +} + diff --git a/Filtering/vtkCellLocator.h b/Filtering/vtkCellLocator.h new file mode 100644 index 0000000..2f372eb --- /dev/null +++ b/Filtering/vtkCellLocator.h @@ -0,0 +1,239 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellLocator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellLocator - octree-based spatial search object to quickly locate cells +// .SECTION Description +// vtkCellLocator is a spatial search object to quickly locate cells in 3D. +// vtkCellLocator uses a uniform-level octree subdivision, where each octant +// (an octant is also referred to as a bucket) carries an indication of +// whether it is empty or not, and each leaf octant carries a list of the +// cells inside of it. (An octant is not empty if it has one or more cells +// inside of it.) Typical operations are intersection with a line to return +// candidate cells, or intersection with another vtkCellLocator to return +// candidate cells. + +// .SECTION Caveats +// Many other types of spatial locators have been developed, such as +// variable depth octrees and kd-trees. These are often more efficient +// for the operations described here. vtkCellLocator has been designed +// for subclassing; so these locators can be derived if necessary. + +// .SECTION See Also +// vtkLocator vtkPointLocator vtkOBBTree + +#ifndef __vtkCellLocator_h +#define __vtkCellLocator_h + +#include "vtkLocator.h" + +class vtkCellArray; +class vtkGenericCell; +class vtkIdList; +class vtkNeighborCells; +class vtkPoints; + +class VTK_FILTERING_EXPORT vtkCellLocator : public vtkLocator +{ +public: + vtkTypeRevisionMacro(vtkCellLocator,vtkLocator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with automatic computation of divisions, averaging + // 25 cells per bucket. + static vtkCellLocator *New(); + + // Description: + // Specify the average number of cells in each octant. + vtkSetClampMacro(NumberOfCellsPerBucket,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfCellsPerBucket,int); + + // Description: + // Boolean controls whether the bounds of each cell are computed only + // once and then saved. Should be 10 to 20% faster if repeatedly + // calling any of the FindClosestPoint routines and the extra memory + // won't cause disk caching (24 extra bytes per cell are required to + // save the bounds). + vtkSetMacro(CacheCellBounds,int); + vtkGetMacro(CacheCellBounds,int); + vtkBooleanMacro(CacheCellBounds,int); + + // Description: + // Return intersection point (if any) of finite line with cells contained + // in cell locator. + virtual int IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId); + + // Description: + // Return intersection point (if any) AND the cell which was intersected by + // the finite line. + virtual int IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId); + + // Description: + // Return intersection point (if any) AND the cell which was intersected by + // the finite line. The cell is returned as a cell id and as a generic cell. + virtual int IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId, + vtkGenericCell *cell); + + // Description: + // Return the closest point and the cell which is closest to the point x. + // The closest point is somewhere on a cell, it need not be one of the + // vertices of the cell. + void FindClosestPoint(double x[3], double closestPoint[3], vtkIdType &cellId, + int &subId, double& dist2); + + // Description: + // Return the closest point and the cell which is closest to the point x. + // The closest point is somewhere on a cell, it need not be one of the + // vertices of the cell. This version takes in a vtkGenericCell + // to avoid allocating and deallocating the cell. This is much faster than + // the version which does not take a *cell, especially when this function is + // called many times in a row such as by a for loop, where the allocation and + // deallocation can be done only once outside the for loop. If a cell is + // found, "cell" contains the points and ptIds for the cell "cellId" upon + // exit. + void FindClosestPoint(double x[3], double closestPoint[3], + vtkGenericCell *cell, vtkIdType &cellId, int &subId, + double& dist2); + + // Description: + // Return the closest point within a specified radius and the cell which is + // closest to the point x. The closest point is somewhere on a cell, it + // need not be one of the vertices of the cell. This method returns 1 if + // a point is found within the specified radius. If there are no cells within + // the specified radius, the method returns 0 and the values of closestPoint, + // cellId, subId, and dist2 are undefined. + int FindClosestPointWithinRadius(double x[3], double radius, + double closestPoint[3], vtkIdType &cellId, + int &subId, double& dist2); + + // Description: + // Return the closest point within a specified radius and the cell which is + // closest to the point x. The closest point is somewhere on a cell, it + // need not be one of the vertices of the cell. This method returns 1 if a + // point is found within the specified radius. If there are no cells within + // the specified radius, the method returns 0 and the values of + // closestPoint, cellId, subId, and dist2 are undefined. This version takes + // in a vtkGenericCell to avoid allocating and deallocating the cell. This + // is much faster than the version which does not take a *cell, especially + // when this function is called many times in a row such as by a for loop, + // where the allocation and deallocation can be done only once outside the + // for loop. If a closest point is found, "cell" contains the points and + // ptIds for the cell "cellId" upon exit. + int FindClosestPointWithinRadius(double x[3], double radius, + double closestPoint[3], + vtkGenericCell *cell, vtkIdType &cellId, + int &subId, double& dist2); + + // Description: + // Return the closest point within a specified radius and the cell which is + // closest to the point x. The closest point is somewhere on a cell, it + // need not be one of the vertices of the cell. This method returns 1 if a + // point is found within the specified radius. If there are no cells within + // the specified radius, the method returns 0 and the values of + // closestPoint, cellId, subId, and dist2 are undefined. This version takes + // in a vtkGenericCell to avoid allocating and deallocating the cell. This + // is much faster than the version which does not take a *cell, especially + // when this function is called many times in a row such as by a for loop, + // where the allocation and dealloction can be done only once outside the + // for loop. If a closest point is found, "cell" contains the points and + // ptIds for the cell "cellId" upon exit. If a closest point is found, + // inside returns the return value of the EvaluatePosition call to the + // closest cell; inside(=1) or outside(=0). + int FindClosestPointWithinRadius(double x[3], double radius, + double closestPoint[3], + vtkGenericCell *cell, vtkIdType &cellId, + int &subId, double& dist2, int &inside); + + // Description: + // Get the cells in a particular bucket. + virtual vtkIdList *GetCells(int bucket); + + // Description: + // Return number of buckets available. Insure that the locator has been + // built before attempting to access buckets (octants). + virtual int GetNumberOfBuckets(void); + + // Description: + // Satisfy vtkLocator abstract interface. + void FreeSearchStructure(); + void BuildLocator(); + void GenerateRepresentation(int level, vtkPolyData *pd); + +protected: + vtkCellLocator(); + ~vtkCellLocator(); + + void GetBucketNeighbors(int ijk[3], int ndivs, int level); + void GetOverlappingBuckets(double x[3], int ijk[3], double dist, + int prevMinLevel[3], int prevMaxLevel[3]); + + void ClearCellHasBeenVisited(); + void ClearCellHasBeenVisited(int id); + + double Distance2ToBucket(double x[3], int nei[3]); + double Distance2ToBounds(double x[3], double bounds[6]); + + int NumberOfCellsPerBucket; // cells per octant + int NumberOfOctants; // number of octants in tree + double Bounds[6]; // bounding box root octant + int NumberOfParents; // number of parent octants + double H[3]; // width of leaf octant in x-y-z directions + int NumberOfDivisions; // number of "leaf" octant sub-divisions + vtkIdList **Tree; // octree + + void MarkParents(void*, int, int, int, int, int); + void GetChildren(int idx, int level, int children[8]); + int GenerateIndex(int offset, int numDivs, int i, int j, int k, + vtkIdType &idx); + void GenerateFace(int face, int numDivs, int i, int j, int k, + vtkPoints *pts, vtkCellArray *polys); + + vtkNeighborCells *Buckets; + unsigned char *CellHasBeenVisited; + unsigned char QueryNumber; + int CacheCellBounds; +//BTX - begin tcl exclude + double (*CellBounds)[6]; +//ETX - end tcl exclude + + void ComputeOctantBounds(int i, int j, int k); + double OctantBounds[6]; //the bounds of the current octant + int IsInOctantBounds(double x[3]) + { + if ( this->OctantBounds[0] <= x[0] && x[0] <= this->OctantBounds[1] && + this->OctantBounds[2] <= x[1] && x[1] <= this->OctantBounds[3] && + this->OctantBounds[4] <= x[2] && x[2] <= this->OctantBounds[5] ) + { + return 1; + } + else + { + return 0; + } + } + +private: + vtkCellLocator(const vtkCellLocator&); // Not implemented. + void operator=(const vtkCellLocator&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkCellType.h b/Filtering/vtkCellType.h new file mode 100644 index 0000000..277dd22 --- /dev/null +++ b/Filtering/vtkCellType.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellType.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellType - define types of cells +// .SECTION Description +// vtkCellType defines the allowable cell types in the visualization +// library (vtk). In vtk, datasets consist of collections of cells. +// Different datasets consist of different cell types. The cells may be +// explicitly represented (as in vtkPolyData), or may be implicit to the +// data type (as in vtkStructuredPoints). + +#ifndef __vtkCellType_h +#define __vtkCellType_h + +// To add a new cell type, define a new integer type flag here, then +// create a subclass of vtkCell to implement the proper behavior. You +// may have to modify the following methods: vtkDataSet (and subclasses) +// GetCell() and vtkGenericCell::SetCellType(). Also, to do the job right, +// you'll also have to modify the readers/writers and regression tests +// (example scripts) to reflect the new cell addition. + +// Linear cells +#define VTK_EMPTY_CELL 0 +#define VTK_VERTEX 1 +#define VTK_POLY_VERTEX 2 +#define VTK_LINE 3 +#define VTK_POLY_LINE 4 +#define VTK_TRIANGLE 5 +#define VTK_TRIANGLE_STRIP 6 +#define VTK_POLYGON 7 +#define VTK_PIXEL 8 +#define VTK_QUAD 9 +#define VTK_TETRA 10 +#define VTK_VOXEL 11 +#define VTK_HEXAHEDRON 12 +#define VTK_WEDGE 13 +#define VTK_PYRAMID 14 +#define VTK_PENTAGONAL_PRISM 15 +#define VTK_HEXAGONAL_PRISM 16 + +// Quadratic, isoparametric cells +#define VTK_QUADRATIC_EDGE 21 +#define VTK_QUADRATIC_TRIANGLE 22 +#define VTK_QUADRATIC_QUAD 23 +#define VTK_QUADRATIC_TETRA 24 +#define VTK_QUADRATIC_HEXAHEDRON 25 +#define VTK_QUADRATIC_WEDGE 26 +#define VTK_QUADRATIC_PYRAMID 27 + +// Special class of cells formed by convex group of points +#define VTK_CONVEX_POINT_SET 41 + +// Higher order cells in parametric form +#define VTK_PARAMETRIC_CURVE 51 +#define VTK_PARAMETRIC_SURFACE 52 +#define VTK_PARAMETRIC_TRI_SURFACE 53 +#define VTK_PARAMETRIC_QUAD_SURFACE 54 +#define VTK_PARAMETRIC_TETRA_REGION 55 +#define VTK_PARAMETRIC_HEX_REGION 56 + +// Higher order cells +#define VTK_HIGHER_ORDER_EDGE 60 +#define VTK_HIGHER_ORDER_TRIANGLE 61 +#define VTK_HIGHER_ORDER_QUAD 62 +#define VTK_HIGHER_ORDER_POLYGON 63 +#define VTK_HIGHER_ORDER_TETRAHEDRON 64 +#define VTK_HIGHER_ORDER_WEDGE 65 +#define VTK_HIGHER_ORDER_PYRAMID 66 +#define VTK_HIGHER_ORDER_HEXAHEDRON 67 + +#endif diff --git a/Filtering/vtkCellTypes.cxx b/Filtering/vtkCellTypes.cxx new file mode 100644 index 0000000..7f5b68c --- /dev/null +++ b/Filtering/vtkCellTypes.cxx @@ -0,0 +1,212 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellTypes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellTypes.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCellTypes, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkCellTypes); + +//---------------------------------------------------------------------------- +vtkCellTypes::vtkCellTypes () +{ + + this->TypeArray = NULL; + this->LocationArray = NULL; + this->Size = 0; + this->MaxId = -1; + this->Extend = 1000; + this->Allocate(1000,this->Extend); + +} + +//---------------------------------------------------------------------------- +vtkCellTypes::~vtkCellTypes() +{ + + if ( this->TypeArray ) + { + this->TypeArray->UnRegister(this); + this->TypeArray = NULL; + } + + if ( this->LocationArray ) + { + this->LocationArray->UnRegister(this); + this->LocationArray = NULL; + } + +} + +//---------------------------------------------------------------------------- +// Allocate memory for this array. Delete old storage only if necessary. +int vtkCellTypes::Allocate(int sz, int ext) +{ + + this->Size = ( sz > 0 ? sz : 1); + this->Extend = ( ext > 0 ? ext : 1); + this->MaxId = -1; + + if ( this->TypeArray ) + { + this->TypeArray->UnRegister(this); + } + this->TypeArray = vtkUnsignedCharArray::New(); + this->TypeArray->Allocate(sz,ext); + this->TypeArray->Register(this); + this->TypeArray->Delete(); + + if ( this->LocationArray ) + { + this->LocationArray->UnRegister(this); + } + this->LocationArray = vtkIntArray::New(); + this->LocationArray->Allocate(sz,ext); + this->LocationArray->Register(this); + this->LocationArray->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +// Add a cell at specified id. +void vtkCellTypes::InsertCell(int cellId, unsigned char type, int loc) +{ + vtkDebugMacro(<<"Insert Cell id: " << cellId << " at location " << loc); + TypeArray->InsertValue(cellId, type); + + LocationArray->InsertValue(cellId, loc); + + if ( cellId > this->MaxId ) + { + this->MaxId = cellId; + } + return; +} + +//---------------------------------------------------------------------------- +// Add a cell to the object in the next available slot. +int vtkCellTypes::InsertNextCell(unsigned char type, int loc) +{ + vtkDebugMacro(<<"Insert Next Cell " << type << " location " << loc); + this->InsertCell (++this->MaxId,type,loc); + return this->MaxId; +} + +//---------------------------------------------------------------------------- +// Specify a group of cell types. +void vtkCellTypes::SetCellTypes(int ncells, vtkUnsignedCharArray *cellTypes, vtkIntArray *cellLocations) +{ + this->Size = ncells; + + if (this->TypeArray) + { + this->TypeArray->Delete(); + } + + this->TypeArray = cellTypes; + cellTypes->Register(this); + + if (this->LocationArray) + { + this->LocationArray->Delete(); + } + this->LocationArray = cellLocations; + cellLocations->Register(this); + this->Extend = 1; + this->MaxId = -1; + +} + +//---------------------------------------------------------------------------- +// Reclaim any extra memory. +void vtkCellTypes::Squeeze() +{ + this->TypeArray->Squeeze(); + this->LocationArray->Squeeze(); +} + +//---------------------------------------------------------------------------- +// Initialize object without releasing memory. +void vtkCellTypes::Reset() +{ + this->MaxId = -1; +} + +//---------------------------------------------------------------------------- +unsigned long vtkCellTypes::GetActualMemorySize() +{ + unsigned long size=0; + + if ( this->TypeArray ) + { + size += this->TypeArray->GetActualMemorySize(); + } + + if ( this->LocationArray ) + { + size += this->LocationArray->GetActualMemorySize(); + } + + return (unsigned long) ceil((float)size/1000.0); //kilobytes +} + + +//---------------------------------------------------------------------------- +void vtkCellTypes::DeepCopy(vtkCellTypes *src) +{ + if (this->TypeArray) + { + this->TypeArray->UnRegister(this); + this->TypeArray = NULL; + } + if (src->TypeArray) + { + this->TypeArray = vtkUnsignedCharArray::New(); + this->TypeArray->DeepCopy(src->TypeArray); + this->TypeArray->Register(this); + this->TypeArray->Delete(); + } + + if (this->LocationArray) + { + this->LocationArray->UnRegister(this); + this->LocationArray = NULL; + } + if (src->LocationArray) + { + this->LocationArray = vtkIntArray::New(); + this->LocationArray->DeepCopy(src->LocationArray); + this->LocationArray->Register(this); + this->LocationArray->Delete(); + } + + this->Allocate(src->Size, src->Extend); + this->MaxId = src->MaxId; +} + +//---------------------------------------------------------------------------- +void vtkCellTypes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "TypeArray:\n"; + this->TypeArray->PrintSelf(os,indent.GetNextIndent()); + os << indent << "LocationArray:\n"; + this->LocationArray->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Size: " << this->Size << "\n"; + os << indent << "MaxId: " << this->MaxId << "\n"; + os << indent << "Extend: " << this->Extend << "\n"; +} diff --git a/Filtering/vtkCellTypes.h b/Filtering/vtkCellTypes.h new file mode 100644 index 0000000..889682f --- /dev/null +++ b/Filtering/vtkCellTypes.h @@ -0,0 +1,142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellTypes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellTypes - object provides direct access to cells in vtkCellArray and type information +// .SECTION Description +// This class is a supplemental object to vtkCellArray to allow random access +// into cells as well as representing cell type information. The "location" +// field is the location in the vtkCellArray list in terms of an integer +// offset. An integer offset was used instead of a pointer for easy storage +// and inter-process communication. The type information is defined in the +// file vtkCellType.h. +// +// .SECTION Caveats +// Sometimes this class is used to pass type information independent of the +// random access (i.e., location) information. For example, see +// vtkDataSet::GetCellTypes(). If you use the class in this way, you can use +// a location value of -1. +// +// .SECTION See Also +// vtkCellArray vtkCellLinks + +#ifndef __vtkCellTypes_h +#define __vtkCellTypes_h + +#include "vtkObject.h" + +#include "vtkIntArray.h" // Needed for inline methods +#include "vtkUnsignedCharArray.h" // Needed for inline methods +#include "vtkCellType.h" // Needed for VTK_EMPTY_CELL + +class VTK_FILTERING_EXPORT vtkCellTypes : public vtkObject +{ +public: + static vtkCellTypes *New(); + vtkTypeRevisionMacro(vtkCellTypes,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate memory for this array. Delete old storage only if necessary. + int Allocate(int sz=512, int ext=1000); + + // Description: + // Add a cell at specified id. + void InsertCell(int id, unsigned char type, int loc); + + // Description: + // Add a cell to the object in the next available slot. + int InsertNextCell(unsigned char type, int loc); + + // Description: + // Specify a group of cell types. + void SetCellTypes(int ncells, vtkUnsignedCharArray *cellTypes, vtkIntArray *cellLocations); + + // Description: + // Return the location of the cell in the associated vtkCellArray. + int GetCellLocation(int cellId) { return this->LocationArray->GetValue(cellId);}; + + // Description: + // Delete cell by setting to NULL cell type. + void DeleteCell(int cellId) { this->TypeArray->SetValue(cellId, VTK_EMPTY_CELL);}; + + // Description: + // Return the number of types in the list. + int GetNumberOfTypes() { return (this->MaxId + 1);}; + + // Description: + // Return 1 if type specified is contained in list; 0 otherwise. + int IsType(unsigned char type); + + // Description: + // Add the type specified to the end of the list. Range checking is performed. + int InsertNextType(unsigned char type){return this->InsertNextCell(type,-1);}; + + // Description: + // Return the type of cell. + unsigned char GetCellType(int cellId) { return this->TypeArray->GetValue(cellId);}; + + // Description: + // Reclaim any extra memory. + void Squeeze(); + + // Description: + // Initialize object without releasing memory. + void Reset(); + + // Description: + // Return the memory in kilobytes consumed by this cell type array. + // Used to support streaming and reading/writing data. The value + // returned is guaranteed to be greater than or equal to the memory + // required to actually represent the data represented by this object. + // The information returned is valid only after the pipeline has + // been updated. + unsigned long GetActualMemorySize(); + + // Description: + // Standard DeepCopy method. Since this object contains no reference + // to other objects, there is no ShallowCopy. + void DeepCopy(vtkCellTypes *src); + +protected: + vtkCellTypes(); + ~vtkCellTypes(); + + vtkUnsignedCharArray *TypeArray; // pointer to types array + vtkIntArray *LocationArray; // pointer to array of offsets + int Size; // allocated size of data + int MaxId; // maximum index inserted thus far + int Extend; // grow array by this point +private: + vtkCellTypes(const vtkCellTypes&); // Not implemented. + void operator=(const vtkCellTypes&); // Not implemented. +}; + + +//---------------------------------------------------------------------------- +inline int vtkCellTypes::IsType(unsigned char type) +{ + int numTypes=this->GetNumberOfTypes(); + + for (int i=0; iGetCellType(i)) + { + return 1; + } + } + return 0; +} + + +#endif diff --git a/Filtering/vtkColorTransferFunction.cxx b/Filtering/vtkColorTransferFunction.cxx new file mode 100644 index 0000000..e4feda9 --- /dev/null +++ b/Filtering/vtkColorTransferFunction.cxx @@ -0,0 +1,1173 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkColorTransferFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkColorTransferFunction.h" + +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" + +vtkCxxRevisionMacro(vtkColorTransferFunction, "$Revision: 1.56.6.1 $"); +vtkStandardNewMacro(vtkColorTransferFunction); + +//---------------------------------------------------------------------------- +// Construct a new vtkColorTransferFunction with default values +vtkColorTransferFunction::vtkColorTransferFunction() +{ + // Remove these when old methods are removed + this->Red = vtkPiecewiseFunction::New(); + this->Green = vtkPiecewiseFunction::New(); + this->Blue = vtkPiecewiseFunction::New(); + + this->UnsignedCharRGBAValue[0] = 0; + this->UnsignedCharRGBAValue[1] = 0; + this->UnsignedCharRGBAValue[2] = 0; + this->UnsignedCharRGBAValue[3] = 0; + + this->Range[0] = 0; + this->Range[1] = 0; + + this->Clamping = 1; + this->ColorSpace = VTK_CTF_RGB; + this->HSVWrap = 1; //By default HSV will be wrap + + this->Function = NULL; + this->FunctionSize = 0; + this->NumberOfPoints = 0; + + this->Table = NULL; + this->TableSize = 0; +} + +//---------------------------------------------------------------------------- +// Destruct a vtkColorTransferFunction +vtkColorTransferFunction::~vtkColorTransferFunction() +{ + this->Red->Delete(); + this->Red = NULL; + this->Green->Delete(); + this->Green = NULL; + this->Blue->Delete(); + this->Blue = NULL; + + delete [] this->Function; + delete [] this->Table; +} + +//---------------------------------------------------------------------------- +// Add a point defined in RGB +int vtkColorTransferFunction::AddRGBPoint( double x, double r, + double g, double b ) +{ + double *fptr = this->Function; + int i; + + + for ( i = 0; i < this->NumberOfPoints; i++, fptr+=4 ) + { + if ( x <= *fptr ) + { + break; + } + } + + // Do we have an exact match? + if ( i < this->NumberOfPoints && this->Function[4*i] == x ) + { + if (this->Function[4*i+1] != r || + this->Function[4*i+2] != g || + this->Function[4*i+3] != b) + { + this->Function[4*i+1] = r; + this->Function[4*i+2] = g; + this->Function[4*i+3] = b; + this->Modified(); + } + + return i; + } + + // otherwise we have to add it before the current location + // We need more space + if ( this->NumberOfPoints == this->FunctionSize ) + { + if ( this->FunctionSize ) + { + this->FunctionSize *= 2; + } + else + { + this->FunctionSize = 100; + } + + double *tmp = new double[this->FunctionSize*4]; + if ( i > 0 ) + { + memcpy( tmp, this->Function, i*sizeof(double)*4 ); + } + if ( i < this->NumberOfPoints ) + { + memcpy( tmp+((i+1)*4), this->Function+(i*4), + (this->NumberOfPoints-i)*sizeof(double)*4 ); + } + if ( this->Function ) + { + delete [] this->Function; + } + this->Function = tmp; + } + else + { + for ( int j = this->NumberOfPoints - 1; j >= i; j-- ) + { + this->Function[4*(j+1) ] = this->Function[4*j ]; + this->Function[4*(j+1)+1] = this->Function[4*j+1]; + this->Function[4*(j+1)+2] = this->Function[4*j+2]; + this->Function[4*(j+1)+3] = this->Function[4*j+3]; + } + } + + this->Function[i*4 ] = x; + this->Function[i*4+1] = r; + this->Function[i*4+2] = g; + this->Function[i*4+3] = b; + + this->NumberOfPoints++; + + this->Range[0] = *this->Function; + this->Range[1] = *(this->Function + (this->NumberOfPoints-1)*4); + + this->Modified(); + + return i; +} + +//---------------------------------------------------------------------------- +// Add a point defined in HSV +int vtkColorTransferFunction::AddHSVPoint( double x, double h, + double s, double v ) +{ + double r, b, g; + + vtkMath::HSVToRGB(h, s, v, &r, &g, &b); + return this->AddRGBPoint( x, r, g, b ); +} + +//---------------------------------------------------------------------------- +// Remove a point +int vtkColorTransferFunction::RemovePoint( double x ) +{ + double *fptr = this->Function; + int i; + + + // find the point to remove + for ( i = 0; i < this->NumberOfPoints; i++, fptr+=4 ) + { + if ( x == *fptr ) + { + break; + } + } + + if ( i < this->NumberOfPoints ) + { + this->NumberOfPoints--; + + for ( int j = i; j < this->NumberOfPoints; j++ ) + { + this->Function[4*j ] = this->Function[4*(j+1) ]; + this->Function[4*j+1] = this->Function[4*(j+1)+1]; + this->Function[4*j+2] = this->Function[4*(j+1)+2]; + this->Function[4*j+3] = this->Function[4*(j+1)+3]; + } + + if ( this->NumberOfPoints ) + { + this->Range[0] = *this->Function; + this->Range[1] = *(this->Function + (this->NumberOfPoints-1)*4); + } + else + { + this->Range[0] = 0.0; + this->Range[1] = 0.0; + } + + this->Modified(); + + return i; + } + + return -1; +} + + +//---------------------------------------------------------------------------- +// Remove all points +void vtkColorTransferFunction::RemoveAllPoints() +{ + if (!this->NumberOfPoints) + { + return; + } + + this->NumberOfPoints = 0; + + this->Range[0] = 0; + this->Range[1] = 0; + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Add a line defined in RGB +void vtkColorTransferFunction::AddRGBSegment( double x1, double r1, + double g1, double b1, + double x2, double r2, + double g2, double b2 ) +{ + double x; + this->AddRGBPoint( x1, r1, g1, b1 ); + this->AddRGBPoint( x2, r2, g2, b2 ); + + int i, j; + double *fptr = this->Function; + + // swap them if necessary + if ( x1 > x2 ) + { + x = x1; + x1 = x2; + x2 = x; + } + + // find the first point + for ( i = 0; i < this->NumberOfPoints; i++, fptr+=4 ) + { + if ( x1 == *fptr ) + { + break; + } + } + + // find the next one + for ( j = i; j < this->NumberOfPoints; j++, fptr+=4 ) + { + if ( x2 == *fptr ) + { + break; + } + } + + int d = j-i-1; + + if ( j < this->NumberOfPoints && d ) + { + this->NumberOfPoints -= d; + for ( int k = i+1; k < this->NumberOfPoints; k++ ) + { + this->Function[4*k ] = this->Function[4*(k+d) ]; + this->Function[4*k+1] = this->Function[4*(k+d)+1]; + this->Function[4*k+2] = this->Function[4*(k+d)+2]; + this->Function[4*k+3] = this->Function[4*(k+d)+3]; + } + } + + this->Range[0] = *this->Function; + this->Range[1] = *(this->Function + (this->NumberOfPoints-1)*4); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Add a line defined in HSV +void vtkColorTransferFunction::AddHSVSegment( double x1, double h1, + double s1, double v1, + double x2, double h2, + double s2, double v2 ) +{ + double r1, r2, b1, b2, g1, g2; + + vtkMath::HSVToRGB(h1, s1, v1, &r1, &g1, &b1); + vtkMath::HSVToRGB(h2, s2, v2, &r2, &g2, &b2); + this->AddRGBSegment( x1, r1, g1, b1, x2, r2, g2, b2 ); +} + +//---------------------------------------------------------------------------- +// Returns the RGBA color evaluated at the specified location +unsigned char *vtkColorTransferFunction::MapValue( double x ) +{ + double rgb[3]; + this->GetColor( x, rgb ); + + this->UnsignedCharRGBAValue[0] = (unsigned char) (255.0*rgb[0]); + this->UnsignedCharRGBAValue[1] = (unsigned char) (255.0*rgb[1]); + this->UnsignedCharRGBAValue[2] = (unsigned char) (255.0*rgb[2]); + this->UnsignedCharRGBAValue[3] = 255; + return this->UnsignedCharRGBAValue; +} + +//---------------------------------------------------------------------------- +// Returns the RGB color evaluated at the specified location +void vtkColorTransferFunction::GetColor(double x, double rgb[3]) +{ + this->GetTable( x, x, 1, rgb ); +} + +//---------------------------------------------------------------------------- +// Returns the red color evaluated at the specified location +double vtkColorTransferFunction::GetRedValue( double x ) +{ + double rgb[3]; + this->GetColor( x, rgb ); + + return rgb[0]; +} + +//---------------------------------------------------------------------------- +// Returns the green color evaluated at the specified location +double vtkColorTransferFunction::GetGreenValue( double x ) +{ + double rgb[3]; + this->GetColor( x, rgb ); + + return rgb[1]; +} + +//---------------------------------------------------------------------------- +// Returns the blue color evaluated at the specified location +double vtkColorTransferFunction::GetBlueValue( double x ) +{ + double rgb[3]; + this->GetColor( x, rgb ); + + return rgb[2]; +} + +//---------------------------------------------------------------------------- +// Returns a table of RGB colors at regular intervals along the function +void vtkColorTransferFunction::GetTable( double x1, double x2, + int size, double* table ) +{ + double x, xinc=0; + double *tptr = table; + double *fptr = this->Function; + int loc; + int i; + double weight; + + if ( this->NumberOfPoints == 0 ) + { + vtkErrorMacro( + "Attempting to lookup a value with no points in the function"); + return; + } + + if ( size > 1 ) + { + xinc = (x2 - x1) / (double)(size-1); + } + + loc = 0; + + for ( i = 0, x = x1; i < size; i++, x += xinc ) + { + while ( (loc < this->NumberOfPoints) && (x > *fptr) ) + { + loc++; + fptr+=4; + } + + // Are we past the outside edge? if so, fill in according to Clamping + if ( loc == this->NumberOfPoints ) + { + if ( this->Clamping ) + { + *(tptr++) = *(fptr-3); + *(tptr++) = *(fptr-2); + *(tptr++) = *(fptr-1); + } + else + { + *(tptr++) = 0.0; + *(tptr++) = 0.0; + *(tptr++) = 0.0; + } + } + else + { + // Do we have an exact match? + if ( x == *fptr ) + { + *(tptr++) = *(fptr+1); + *(tptr++) = *(fptr+2); + *(tptr++) = *(fptr+3); + } + // Are we before the beginning? + else if ( loc == 0 ) + { + if ( this->Clamping ) + { + *(tptr++) = *(fptr+1); + *(tptr++) = *(fptr+2); + *(tptr++) = *(fptr+3); + } + else + { + *(tptr++) = 0.0; + *(tptr++) = 0.0; + *(tptr++) = 0.0; + } + } + // We are somewhere in the middle. Use the correct interpolation. + else + { + weight = (x - *(fptr-4)) / (*fptr - *(fptr-4)); + + // RGB space + if ( this->ColorSpace == VTK_CTF_RGB ) + { + *(tptr++) = (1.0-weight) * *(fptr-3) + weight * *(fptr+1); + *(tptr++) = (1.0-weight) * *(fptr-2) + weight * *(fptr+2); + *(tptr++) = (1.0-weight) * *(fptr-1) + weight * *(fptr+3); + } + // HSV space + else + { + double h1, h2, h3, s1, s2, s3, v1, v2, v3; + vtkMath::RGBToHSV(*(fptr-3), *(fptr-2), *(fptr-1), &h1, &s1, &v1); + vtkMath::RGBToHSV(*(fptr+1), *(fptr+2), *(fptr+3), &h2, &s2, &v2); + s3 = (1.0-weight)*s1 + weight*s2; + v3 = (1.0-weight)*v1 + weight*v2; + // Do we need to cross the 0/1 boundary? + if ( this->HSVWrap && + (h1 - h2 > 0.5 || h2 - h1 > 0.5) ) + { + //Yes, we are crossing the boundary + if ( h1 > h2 ) + { + h1 -= 1.0; + } + else + { + h2 -= 1.0; + } + h3 = (1.0-weight)*h1 + weight*h2; + if ( h3 < 0.0 ) + { + h3 += 1.0; + } + } + else // HSV No Wrap + { + // No we are not crossing the boundary + h3 = (1.0-weight)*h1 + weight*h2; + } + // Make sure they are between 0 and 1 + h3 = (h3>1.0)?(1.0):((h3<0.0)?(0.0):(h3)); + s3 = (s3>1.0)?(1.0):((s3<0.0)?(0.0):(s3)); + v3 = (v3>1.0)?(1.0):((v3<0.0)?(0.0):(v3)); + vtkMath::HSVToRGB(h3, s3, v3, tptr, tptr + 1, tptr + 2); + tptr += 3; + } + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkColorTransferFunction::GetTable( double x1, double x2, + int size, float* table ) +{ + double x, xinc=0; + float *tptr = table; + double *fptr = this->Function; + int loc; + int i; + double weight; + + if ( this->NumberOfPoints == 0 ) + { + vtkErrorMacro( + "Attempting to lookup a value with no points in the function"); + return; + } + + if ( size > 1 ) + { + xinc = (x2 - x1) / (double)(size-1); + } + + loc = 0; + + for ( i = 0, x = x1; i < size; i++, x += xinc ) + { + while ( (loc < this->NumberOfPoints) && (x > *fptr) ) + { + loc++; + fptr+=4; + } + + // Are we past the outside edge? if so, fill in according to Clamping + if ( loc == this->NumberOfPoints ) + { + if ( this->Clamping ) + { + *(tptr++) = static_cast(*(fptr-3)); + *(tptr++) = static_cast(*(fptr-2)); + *(tptr++) = static_cast(*(fptr-1)); + } + else + { + *(tptr++) = 0.0f; + *(tptr++) = 0.0f; + *(tptr++) = 0.0f; + } + } + else + { + // Do we have an exact match? + if ( x == *fptr ) + { + *(tptr++) = static_cast(*(fptr+1)); + *(tptr++) = static_cast(*(fptr+2)); + *(tptr++) = static_cast(*(fptr+3)); + } + // Are we before the beginning? + else if ( loc == 0 ) + { + if ( this->Clamping ) + { + *(tptr++) = static_cast(*(fptr+1)); + *(tptr++) = static_cast(*(fptr+2)); + *(tptr++) = static_cast(*(fptr+3)); + } + else + { + *(tptr++) = 0.0f; + *(tptr++) = 0.0f; + *(tptr++) = 0.0f; + } + } + // We are somewhere in the middle. Use the correct interpolation. + else + { + weight = (x - *(fptr-4)) / (*fptr - *(fptr-4)); + + // RGB space + if ( this->ColorSpace == VTK_CTF_RGB ) + { + *(tptr++) = + static_cast((1.0-weight) * *(fptr-3) + weight * *(fptr+1)); + *(tptr++) = + static_cast((1.0-weight) * *(fptr-2) + weight * *(fptr+2)); + *(tptr++) = + static_cast((1.0-weight) * *(fptr-1) + weight * *(fptr+3)); + } + // HSV space + else + { + double h1, h2, h3, s1, s2, s3, v1, v2, v3; + vtkMath::RGBToHSV(*(fptr-3), *(fptr-2), *(fptr-1), &h1, &s1, &v1); + vtkMath::RGBToHSV(*(fptr+1), *(fptr+2), *(fptr+3), &h2, &s2, &v2); + s3 = (1.0-weight)*s1 + weight*s2; + v3 = (1.0-weight)*v1 + weight*v2; + // Do we need to cross the 0/1 boundary? + if ( this->HSVWrap && + (h1 - h2 > 0.5 || h2 - h1 > 0.5) ) + { + //Yes, we are crossing the boundary + if ( h1 > h2 ) + { + h1 -= 1.0; + } + else + { + h2 -= 1.0; + } + h3 = (1.0-weight)*h1 + weight*h2; + if ( h3 < 0.0 ) + { + h3 += 1.0; + } + } + else + { + // No we are not crossing the boundary + h3 = (1.0-weight)*h1 + weight*h2; + } + // Make sure they are between 0 and 1 + h3 = (h3>1.0)?(1.0):((h3<0.0)?(0.0):(h3)); + s3 = (s3>1.0)?(1.0):((s3<0.0)?(0.0):(s3)); + v3 = (v3>1.0)?(1.0):((v3<0.0)?(0.0):(v3)); + vtkMath::HSVToRGB(static_cast(h3), + static_cast(s3), + static_cast(v3), + tptr, tptr + 1, tptr + 2); + tptr += 3; + } + } + } + } +} + +//---------------------------------------------------------------------------- +const unsigned char *vtkColorTransferFunction::GetTable( double x1, double x2, + int size) +{ + double x, xinc=0; + double *fptr = this->Function; + int loc; + int i; + double weight; + + if (this->GetMTime() <= this->BuildTime && + this->TableSize == size) + { + return this->Table; + } + + if ( this->NumberOfPoints == 0 ) + { + vtkErrorMacro( + "Attempting to lookup a value with no points in the function"); + return this->Table; + } + + if (this->TableSize != size) + { + delete [] this->Table; + this->Table = new unsigned char [size*3]; + this->TableSize = size; + } + unsigned char *tptr = this->Table; + + if ( size > 1 ) + { + xinc = (x2 - x1) / (double)(size-1); + } + + loc = 0; + for ( i = 0, x = x1; i < size; i++, x += xinc ) + { + while ( (loc < this->NumberOfPoints) && (x > *fptr) ) + { + loc++; + fptr+=4; + } + + // Are we past the outside edge? if so, fill in according to Clamping + if ( loc == this->NumberOfPoints ) + { + if ( this->Clamping ) + { + *(tptr++) = (unsigned char)(*(fptr-3)*255); + *(tptr++) = (unsigned char)(*(fptr-2)*255); + *(tptr++) = (unsigned char)(*(fptr-1)*255); + } + else + { + *(tptr++) = 0; + *(tptr++) = 0; + *(tptr++) = 0; + } + } + else + { + // Do we have an exact match? + if ( x == *fptr ) + { + *(tptr++) = (unsigned char)(*(fptr+1)*255); + *(tptr++) = (unsigned char)(*(fptr+2)*255); + *(tptr++) = (unsigned char)(*(fptr+3)*255); + } + // Are we before the beginning? + else if ( loc == 0 ) + { + if ( this->Clamping ) + { + *(tptr++) = (unsigned char)(*(fptr+1)*255); + *(tptr++) = (unsigned char)(*(fptr+2)*255); + *(tptr++) = (unsigned char)(*(fptr+3)*255); + } + else + { + *(tptr++) = 0; + *(tptr++) = 0; + *(tptr++) = 0; + } + } + // We are somewhere in the middle. Use the correct interpolation. + else + { + weight = (x - *(fptr-4)) / (*fptr - *(fptr-4)); + + // RGB space + if ( this->ColorSpace == VTK_CTF_RGB ) + { + *(tptr++) = (unsigned char) + (255*((1.0-weight) * *(fptr-3) + weight * *(fptr+1))); + *(tptr++) = (unsigned char) + (255*((1.0-weight) * *(fptr-2) + weight * *(fptr+2))); + *(tptr++) = (unsigned char) + (255*((1.0-weight) * *(fptr-1) + weight * *(fptr+3))); + } + // HSV space + else + { + double h1, h2, h3, s1, s2, s3, v1, v2, v3; + vtkMath::RGBToHSV(*(fptr-3), *(fptr-2), *(fptr-1), &h1, &s1, &v1); + vtkMath::RGBToHSV(*(fptr+1), *(fptr+2), *(fptr+3), &h2, &s2, &v2); + s3 = (1.0-weight)*s1 + weight*s2; + v3 = (1.0-weight)*v1 + weight*v2; + // Do we need to cross the 0/1 boundary? + if ( this->HSVWrap && + (h1 - h2 > 0.5 || h2 - h1 > 0.5) ) + { + //Yes, we are crossing the boundary + if ( h1 > h2 ) + { + h1 -= 1.0; + } + else + { + h2 -= 1.0; + } + h3 = (1.0-weight)*h1 + weight*h2; + if ( h3 < 0.0 ) + { + h3 += 1.0; + } + } + else // HSV No Wrap + { + // No we are not crossing the boundary + h3 = (1.0-weight)*h1 + weight*h2; + } + // Make sure they are between 0 and 1 + h3 = (h3>1.0)?(1.0):((h3<0.0)?(0.0):(h3)); + s3 = (s3>1.0)?(1.0):((s3<0.0)?(0.0):(s3)); + v3 = (v3>1.0)?(1.0):((v3<0.0)?(0.0):(v3)); + vtkMath::HSVToRGB(h3, s3, v3, &h1, &s1, &v1); + *(tptr++) = (unsigned char)(255*h1); + *(tptr++) = (unsigned char)(255*s1); + *(tptr++) = (unsigned char)(255*v1); + } + } + } + } + this->BuildTime.Modified(); + return this->Table; +} + +//---------------------------------------------------------------------------- +void vtkColorTransferFunction::BuildFunctionFromTable( double x1, double x2, + int size, double *table) +{ + // We are assuming the table is in ascending order + + double *fptr; + double *tptr = table; + double x, xinc; + int i; + + xinc = (x2 - x1) / (double)(size-1); + + this->RemoveAllPoints(); + + // Is it big enough? + if ( this->FunctionSize < size ) + { + delete [] this->Function; + this->FunctionSize = size*2; + this->Function = new double [4*this->FunctionSize]; + } + + fptr = this->Function; + + for (i = 0, x = x1; i < size; i++, x += xinc ) + { + *(fptr++) = x; + *(fptr++) = *(tptr++); + *(fptr++) = *(tptr++); + *(fptr++) = *(tptr++); + } + + this->NumberOfPoints = size; + + this->Modified(); +} + + +//---------------------------------------------------------------------------- +// Print method for vtkColorTransferFunction +void vtkColorTransferFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Size: " << this->NumberOfPoints << endl; + if ( this->Clamping ) + { + os << indent << "Clamping: On\n"; + } + else + { + os << indent << "Clamping: Off\n"; + } + + if ( this->ColorSpace == VTK_CTF_RGB ) + { + os << indent << "Color Space: RGB\n"; + } + else if ( this->ColorSpace == VTK_CTF_HSV && this->HSVWrap ) + { + os << indent << "Color Space: HSV\n"; + } + else + { + os << indent << "Color Space: HSV (No Wrap)\n"; + } + + + os << indent << "Range: " << this->Range[0] << " to " + << this->Range[1] << endl; + + if ( this->NumberOfPoints < 100 ) + { + for ( int i = 0; i < this->NumberOfPoints; i++ ) + { + os << indent << " Point " << i << ": " << this->Function[i*4] << " maps to " + << this->Function[i*4+1] << " " + << this->Function[i*4+2] << " " + << this->Function[i*4+3] << endl; + } + } + + // These are old + // os << indent << "Color Transfer Function Total Points: " << this->GetTotalSize() << "\n"; + // os << indent << "Red Transfer Function: "; + // os << this->Red << "\n"; + // os << indent << "Green Transfer Function: "; + // os << this->Green << "\n"; + // os << indent << "Blue Transfer Function: "; + // os << this->Blue << "\n"; + +} + + +//---------------------------------------------------------------------------- +void vtkColorTransferFunction::DeepCopy( vtkColorTransferFunction *f ) +{ + delete [] this->Function; + delete [] this->Table; + this->TableSize = 0; + + this->Clamping = f->Clamping; + this->ColorSpace = f->ColorSpace; + this->FunctionSize = f->FunctionSize; + this->NumberOfPoints = f->NumberOfPoints; + this->Range[0] = f->Range[0]; + this->Range[1] = f->Range[1]; + + if ( this->FunctionSize > 0 ) + { + this->Function = new double [4*this->FunctionSize]; + memcpy(this->Function, f->Function, 4*sizeof(double)*this->FunctionSize); + } + else + { + this->Function = NULL; + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Accelerate the mapping by copying the data in 32-bit chunks instead +// of 8-bit chunks. The extra "long" argument is to help broken +// compilers select the non-templates below for unsigned char +// and unsigned short. +template +void vtkColorTransferFunctionMapData(vtkColorTransferFunction* self, + T* input, + unsigned char* output, + int length, int inIncr, + int outFormat, long) +{ + double x; + int i = length; + double rgb[3]; + unsigned char *optr = output; + T *iptr = input; + unsigned char alpha = (unsigned char)(self->GetAlpha()*255.0); + + if(self->GetSize() == 0) + { + vtkGenericWarningMacro("Transfer Function Has No Points!"); + return; + } + + while (--i >= 0) + { + x = (double) *iptr; + self->GetColor(x, rgb); + + if (outFormat == VTK_RGB || outFormat == VTK_RGBA) + { + *(optr++) = (unsigned char)(rgb[0]*255.0); + *(optr++) = (unsigned char)(rgb[1]*255.0); + *(optr++) = (unsigned char)(rgb[2]*255.0); + } + else // LUMINANCE use coeffs of (0.30 0.59 0.11)*255.0 + { + *(optr++) = (unsigned char)(rgb[0]*76.5 + rgb[1]*150.45 + rgb[2]*28.05); + } + + if (outFormat == VTK_RGBA || outFormat == VTK_LUMINANCE_ALPHA) + { + *(optr++) = alpha; + } + iptr += inIncr; + } +} + + + +//---------------------------------------------------------------------------- +// Special implementation for unsigned char input. +void vtkColorTransferFunctionMapData(vtkColorTransferFunction* self, + unsigned char* input, + unsigned char* output, + int length, int inIncr, + int outFormat, int) +{ + int x; + int i = length; + unsigned char *optr = output; + unsigned char *iptr = input; + + if(self->GetSize() == 0) + { + vtkGenericWarningMacro("Transfer Function Has No Points!"); + return; + } + + const unsigned char *table = self->GetTable(0,255,256); + switch (outFormat) + { + case VTK_RGB: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + *(optr++) = table[x+1]; + *(optr++) = table[x+2]; + iptr += inIncr; + } + break; + case VTK_RGBA: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + *(optr++) = table[x+1]; + *(optr++) = table[x+2]; + *(optr++) = 255; + iptr += inIncr; + } + break; + case VTK_LUMINANCE_ALPHA: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + *(optr++) = 255; + iptr += inIncr; + } + break; + case VTK_LUMINANCE: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + iptr += inIncr; + } + break; + } +} + +//---------------------------------------------------------------------------- +// Special implementation for unsigned short input. +void vtkColorTransferFunctionMapData(vtkColorTransferFunction* self, + unsigned short* input, + unsigned char* output, + int length, int inIncr, + int outFormat, int) +{ + int x; + int i = length; + unsigned char *optr = output; + unsigned short *iptr = input; + + if(self->GetSize() == 0) + { + vtkGenericWarningMacro("Transfer Function Has No Points!"); + return; + } + + + const unsigned char *table = self->GetTable(0,65535,65536); + switch (outFormat) + { + case VTK_RGB: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + *(optr++) = table[x+1]; + *(optr++) = table[x+2]; + iptr += inIncr; + } + break; + case VTK_RGBA: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + *(optr++) = table[x+1]; + *(optr++) = table[x+2]; + *(optr++) = 255; + iptr += inIncr; + } + break; + case VTK_LUMINANCE_ALPHA: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + *(optr++) = 255; + iptr += inIncr; + } + break; + case VTK_LUMINANCE: + while (--i >= 0) + { + x = *iptr*3; + *(optr++) = table[x]; + iptr += inIncr; + } + break; + } +} + +//---------------------------------------------------------------------------- +void vtkColorTransferFunction::MapScalarsThroughTable2(void *input, + unsigned char *output, + int inputDataType, + int numberOfValues, + int inputIncrement, + int outputFormat) +{ + switch (inputDataType) + { + vtkTemplateMacro( + vtkColorTransferFunctionMapData(this, static_cast(input), + output, numberOfValues, inputIncrement, + outputFormat, 1) + ); + default: + vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkColorTransferFunction::FillFromDataPointer(int nb, double *ptr) +{ + if (nb <= 0 || !ptr) + { + return; + } + + this->RemoveAllPoints(); + + while (nb) + { + this->AddRGBPoint(ptr[0], ptr[1], ptr[2], ptr[3]); + ptr += 4; + nb--; + } +} + +//---------------------------------------------------------------------------- +int vtkColorTransferFunction::AdjustRange(double range[2]) +{ + if (!range) + { + return 0; + } + + double *function_range = this->GetRange(); + + // Make sure we have points at each end of the range + + double rgb[3]; + if (function_range[0] < range[0]) + { + this->GetColor(range[0], rgb); + this->AddRGBPoint(range[0], rgb[0], rgb[1], rgb[2]); + } + else + { + this->GetColor(function_range[0], rgb); + this->AddRGBPoint(range[0], rgb[0], rgb[1], rgb[2]); + } + + if (function_range[1] > range[1]) + { + this->GetColor(range[1], rgb); + this->AddRGBPoint(range[1], rgb[0], rgb[1], rgb[2]); + } + else + { + this->GetColor(function_range[1], rgb); + this->AddRGBPoint(range[1], rgb[0], rgb[1], rgb[2]); + } + + // Remove all points out-of-range + + int func_size = this->GetSize(); + double *func_ptr = this->GetDataPointer(); + + int i; + for (i = func_size - 1; i >= 0; i--) + { + double x = func_ptr[i * 4]; + if (x < range[0] || x > range[1]) + { + this->RemovePoint(x); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +void vtkColorTransferFunction::SetColorSpaceToHSVNoWrap() +{ + this->SetColorSpace(VTK_CTF_HSV); + this->SetHSVWrap(0); +}; +#endif diff --git a/Filtering/vtkColorTransferFunction.h b/Filtering/vtkColorTransferFunction.h new file mode 100644 index 0000000..9f910b2 --- /dev/null +++ b/Filtering/vtkColorTransferFunction.h @@ -0,0 +1,189 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkColorTransferFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkColorTransferFunction - Defines a transfer function for mapping a property to an RGB color value. + +// .SECTION Description +// vtkColorTransferFunction encapsulates three vtkPiecewiseFunction instances +// to provide a full RGB transfer function. + +// .SECTION see also +// vtkPiecewiseFunction + +#ifndef __vtkColorTransferFunction_h +#define __vtkColorTransferFunction_h + +#include "vtkScalarsToColors.h" + +class vtkPiecewiseFunction; + +#define VTK_CTF_RGB 0 +#define VTK_CTF_HSV 1 + +class VTK_FILTERING_EXPORT vtkColorTransferFunction : public vtkScalarsToColors +{ +public: + static vtkColorTransferFunction *New(); + vtkTypeRevisionMacro(vtkColorTransferFunction,vtkScalarsToColors); + void DeepCopy( vtkColorTransferFunction *f ); + + // Description: + // Print method for vtkColorTransferFunction + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // How many points are there defining this function? + int GetSize() {return this->NumberOfPoints;}; + + // Description: + // Add/Remove a point to/from the function defined in RGB or HSV + // Return the index of the point (0 based), or -1 on error. + int AddRGBPoint( double x, double r, double g, double b ); + int AddHSVPoint( double x, double h, double s, double v ); + int RemovePoint( double x ); + + // Description: + // Add two points to the function and remove all the points + // between them + void AddRGBSegment( double x1, double r1, double g1, double b1, + double x2, double r2, double g2, double b2 ); + void AddHSVSegment( double x1, double h1, double s1, double v1, + double x2, double h2, double s2, double v2 ); + + // Description: + // Remove all points + void RemoveAllPoints(); + + // Description: + // Returns an RGB color for the specified scalar value + double *GetColor(double x) { + return vtkScalarsToColors::GetColor(x); } + void GetColor(double x, double rgb[3]); + + // Description: + // Get the color components individually. + double GetRedValue( double x ); + double GetGreenValue( double x ); + double GetBlueValue( double x ); + + // Description: + // Map one value through the lookup table. + virtual unsigned char *MapValue(double v); + + // Description: + // Returns min and max position of all function points. + vtkGetVector2Macro( Range, double ); + + // Description: + // Remove all points out of the new range, and make sure there is a point + // at each end of that range. + // Return 1 on success, 0 otherwise. + int AdjustRange(double range[2]); + + // Description: + // Fills in a table of n function values between x1 and x2 + void GetTable( double x1, double x2, int n, double* table ); + void GetTable( double x1, double x2, int n, float* table ); + const unsigned char *GetTable( double x1, double x2, int n); + + // Description: + // Construct a color transfer function from a table. Function range is + // is set to [x1, x2], each function size is set to size, and function + // points are regularly spaced between x1 and x2. Parameter "table" is + // assumed to be a block of memory of size [3*size] + void BuildFunctionFromTable( double x1, double x2, int size, double *table); + + // Description: + // Sets and gets the clamping value for this transfer function. + vtkSetClampMacro( Clamping, int, 0, 1 ); + vtkGetMacro( Clamping, int ); + vtkBooleanMacro( Clamping, int ); + + // Description: + // Set/Get the color space used for interpolation: RGB, or HSV. + // In HSV mode, if HSVWrap is on, it will take the shortest path in Hue + // (going back through 0 if that is the shortest way around the hue circle) + // whereas if HSVWrap is off it will not go through 0 (in order the match + // the current functionality of vtkLookupTable) + vtkSetClampMacro( ColorSpace, int, VTK_CTF_RGB, VTK_CTF_HSV ); + void SetColorSpaceToRGB(){this->SetColorSpace(VTK_CTF_RGB);}; + void SetColorSpaceToHSV(){this->SetColorSpace(VTK_CTF_HSV);}; + vtkGetMacro( ColorSpace, int ); + vtkSetMacro(HSVWrap, int); + vtkGetMacro(HSVWrap, int); + vtkBooleanMacro(HSVWrap, int); + VTK_LEGACY(void SetColorSpaceToHSVNoWrap()); + + // Description: + // Returns a list of all nodes + // Fills from a pointer to data stored in a similar list of nodes. + double *GetDataPointer() {return this->Function;}; + void FillFromDataPointer(int, double*); + + // Description: + // map a set of scalars through the lookup table + virtual void MapScalarsThroughTable2(void *input, unsigned char *output, + int inputDataType, int numberOfValues, + int inputIncrement, int outputIncrement); + +protected: + vtkColorTransferFunction(); + ~vtkColorTransferFunction(); + + // Determines the function value outside of defined points + // Zero = always return 0.0 outside of defined points + // One = clamp to the lowest value below defined points and + // highest value above defined points + int Clamping; + + // The color space in which interpolation is performed + int ColorSpace; + + // Specify if HSW is warp or not + int HSVWrap; + + // The color function + double *Function; + int FunctionSize; + int NumberOfPoints; + + // An evaluated color (0 to 255 RGBA A=255) + unsigned char UnsignedCharRGBAValue[4]; + + // The min and max point locations for all three transfer functions + double Range[2]; + + // Transfer functions for each color component + // Remove after corresponding depricated methods are removed + vtkPiecewiseFunction *Red; + vtkPiecewiseFunction *Green; + vtkPiecewiseFunction *Blue; + vtkTimeStamp BuildTime; + unsigned char *Table; + int TableSize; + + // Description: + // Set the range of scalars being mapped. The set has no functionality + // in this subclass of vtkScalarsToColors. + virtual void SetRange(double, double) {}; + void SetRange(double rng[2]) {this->SetRange(rng[0],rng[1]);}; + + +private: + vtkColorTransferFunction(const vtkColorTransferFunction&); // Not implemented. + void operator=(const vtkColorTransferFunction&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkCompositeDataIterator.cxx b/Filtering/vtkCompositeDataIterator.cxx new file mode 100644 index 0000000..e2d0368 --- /dev/null +++ b/Filtering/vtkCompositeDataIterator.cxx @@ -0,0 +1,34 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositeDataIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCompositeDataIterator.h" + +vtkCxxRevisionMacro(vtkCompositeDataIterator, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +vtkCompositeDataIterator::vtkCompositeDataIterator() +{ +} + +//---------------------------------------------------------------------------- +vtkCompositeDataIterator::~vtkCompositeDataIterator() +{ +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Filtering/vtkCompositeDataIterator.h b/Filtering/vtkCompositeDataIterator.h new file mode 100644 index 0000000..9b68caf --- /dev/null +++ b/Filtering/vtkCompositeDataIterator.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositeDataIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCompositeDataIterator - abstract superclass for composite data iterators +// .SECTION Description +// vtkCompositeDataIterator provides an interface for accessing datasets +// in a collection (vtkCompositeDataIterator). Sub-classes provide the +// actual implementation. + +#ifndef __vtkCompositeDataIterator_h +#define __vtkCompositeDataIterator_h + +#include "vtkObject.h" + +class vtkDataObject; + +class VTK_FILTERING_EXPORT vtkCompositeDataIterator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCompositeDataIterator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move the iterator to the beginning of the collection. + void InitTraversal() { this->GoToFirstItem(); } + + // Description: + // Move the iterator to the beginning of the collection. + virtual void GoToFirstItem() = 0; + + // Description: + // Move the iterator to the next item in the collection. + virtual void GoToNextItem() = 0; + + // Description: + // Test whether the iterator is currently pointing to a valid + // item. Returns 1 for yes, 0 for no. + virtual int IsDoneWithTraversal() = 0; + + // Description: + // Get the current item. Valid only when IsDoneWithTraversal() + // returns 1. + virtual vtkDataObject* GetCurrentDataObject() = 0; + +protected: + vtkCompositeDataIterator(); + virtual ~vtkCompositeDataIterator(); + +private: + vtkCompositeDataIterator(const vtkCompositeDataIterator&); // Not implemented. + void operator=(const vtkCompositeDataIterator&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkCompositeDataPipeline.cxx b/Filtering/vtkCompositeDataPipeline.cxx new file mode 100644 index 0000000..7d1e074 --- /dev/null +++ b/Filtering/vtkCompositeDataPipeline.cxx @@ -0,0 +1,1350 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkCompositeDataPipeline.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCompositeDataPipeline.h" + +#include "vtkAlgorithm.h" +#include "vtkAlgorithmOutput.h" +#include "vtkHierarchicalDataInformation.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationDoubleKey.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationKey.h" +#include "vtkInformationObjectBaseKey.h" +#include "vtkInformationStringKey.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkSmartPointer.h" + +#include "vtkImageData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkUniformGrid.h" + +vtkCxxRevisionMacro(vtkCompositeDataPipeline, "$Revision: 1.23.2.4 $"); +vtkStandardNewMacro(vtkCompositeDataPipeline); + +vtkInformationKeyMacro(vtkCompositeDataPipeline,BEGIN_LOOP,Integer); +vtkInformationKeyMacro(vtkCompositeDataPipeline,END_LOOP,Integer); +vtkInformationKeyMacro(vtkCompositeDataPipeline,COMPOSITE_DATA_TYPE_NAME,String); +vtkInformationKeyMacro(vtkCompositeDataPipeline,COMPOSITE_DATA_INFORMATION,ObjectBase); +vtkInformationKeyMacro(vtkCompositeDataPipeline,MARKED_FOR_UPDATE,Integer); +vtkInformationKeyMacro(vtkCompositeDataPipeline,INPUT_REQUIRED_COMPOSITE_DATA_TYPE, String); +vtkInformationKeyMacro(vtkCompositeDataPipeline,UPDATE_BLOCKS, ObjectBase); + +//---------------------------------------------------------------------------- +vtkCompositeDataPipeline::vtkCompositeDataPipeline() +{ + this->InLocalLoop = 0; + this->InSubPass = 0; + this->InformationCache = vtkInformation::New(); + + this->GenericRequest = vtkInformation::New(); + + this->DataObjectRequest = vtkInformation::New(); + this->DataObjectRequest->Set(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()); + // The request is forwarded upstream through the pipeline. + this->DataObjectRequest->Set( + vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request after it is forwarded. + this->DataObjectRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + + this->InformationRequest = vtkInformation::New(); + this->InformationRequest->Set(vtkDemandDrivenPipeline::REQUEST_INFORMATION()); + // The request is forwarded upstream through the pipeline. + this->InformationRequest->Set( + vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request after it is forwarded. + this->InformationRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + + this->UpdateExtentRequest = vtkInformation::New(); + this->UpdateExtentRequest->Set( + vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()); + // The request is forwarded upstream through the pipeline. + this->UpdateExtentRequest->Set( + vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request before it is forwarded. + this->UpdateExtentRequest->Set(vtkExecutive::ALGORITHM_BEFORE_FORWARD(), 1); + + this->DataRequest = vtkInformation::New(); + this->DataRequest->Set(REQUEST_DATA()); + // The request is forwarded upstream through the pipeline. + this->DataRequest->Set( + vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request after it is forwarded. + this->DataRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + + +} + +//---------------------------------------------------------------------------- +vtkCompositeDataPipeline::~vtkCompositeDataPipeline() +{ + this->InformationCache->Delete(); + + this->GenericRequest->Delete(); + this->DataObjectRequest->Delete(); + this->InformationRequest->Delete(); + this->UpdateExtentRequest->Delete(); + this->DataRequest->Delete(); +} + +//---------------------------------------------------------------------------- +int +vtkCompositeDataPipeline::ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int requestFromOutputPort, + unsigned long* mtime) +{ + // if not a subpass then just do normal stuff + if (!this->InSubPass) + { + return this->Superclass::ComputePipelineMTime(request, + inInfoVec, outInfoVec, + requestFromOutputPort, + mtime); + } + + // if in subpass then Update the time only if it is the beginning of the + // next pass in the loop. + if (request->Has(vtkCompositeDataSet::INDEX())) + { + this->SubPassTime.Modified(); + } + *mtime = this->SubPassTime; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + + if(this->Algorithm && request->Has(BEGIN_LOOP())) + { + this->InSubPass = 1; + return 1; + } + + if(this->Algorithm && request->Has(END_LOOP())) + { + this->InSubPass = 0; + return 1; + } + + + if(this->Algorithm && request->Has(REQUEST_DATA_OBJECT())) + { + if (this->InSubPass) + { + int result = 1; + if (this->SubPassTime > this->DataObjectTime.GetMTime()) + { + // Request information from the algorithm. + result = this->ExecuteDataObjectForBlock(request); + } + return result; + } + } + + if(this->Algorithm && request->Has(REQUEST_INFORMATION())) + { + // Make sure our output information is up-to-date. + int result = 1; + if (this->InSubPass) + { + if(this->SubPassTime > this->InformationTime.GetMTime()) + { + result = this->ExecuteInformationForBlock(request); + + // Information is now up to date. + this->InformationTime.Modified(); + } + } + else + { + int appendKey = 1; + vtkInformationKey** keys = request->Get(vtkExecutive::KEYS_TO_COPY()); + if (keys) + { + int len = request->Length(vtkExecutive::KEYS_TO_COPY()); + for (int i=0; iAppend(vtkExecutive::KEYS_TO_COPY(), + vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION()); + } + + result = this->Superclass::ProcessRequest(request, inInfoVec,outInfoVec); + } + return result; + } + + if(request->Has(REQUEST_UPDATE_EXTENT())) + { + if (this->InSubPass) + { + return 1; + } + } + + if(this->Algorithm && request->Has(REQUEST_DATA())) + { + if (this->InSubPass) + { + return this->ExecuteDataForBlock(request); + } + + // Get the output port from which the request was made. + int outputPort = -1; + if(request->Has(FROM_OUTPUT_PORT())) + { + outputPort = request->Get(FROM_OUTPUT_PORT()); + } + + + // UPDATE_BLOCKS() is the key that tells filters downstream which + // blocks of a composite dataset is available. This consumers will then + // ask for these blocks if they have to loop (simple filters in the + // middle) + int appendKey = 1; + vtkInformationKey** keys = request->Get(vtkExecutive::KEYS_TO_COPY()); + if (keys) + { + int len = request->Length(vtkExecutive::KEYS_TO_COPY()); + for (int i=0; iAppend(vtkExecutive::KEYS_TO_COPY(), + vtkCompositeDataPipeline::UPDATE_BLOCKS()); + } + + if(this->NeedToExecuteData(outputPort,inInfoVec,outInfoVec)) + { + // We have to check whether an input is marked for update before + // ExecuteData() is entered. When looping over blocks, the + // composite data producer up the pipeline will trick the + // intermediate simple filters to execute by sending an update + // mtime. However, if none of those filters are modified, this + // would cause unnecessary execution of the whole intermediate + // pipeline. Here, NeedToExecuteData() is called and the result + // cached so that the blocks that are up to date can be skipped + // later. + + // Loop over all input ports. + for(int i=0; i < this->Algorithm->GetNumberOfInputPorts(); ++i) + { + // Loop over all connections on this input port. + int numInConnections = inInfoVec[i]->GetNumberOfInformationObjects(); + for (int j=0; jGetInformationObject(j); + vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast( + inInfo->GetExecutive(vtkExecutive::PRODUCER())); + inInfo->Remove(MARKED_FOR_UPDATE()); + if (ddp) + { + if (ddp->NeedToExecuteData(-1,ddp->GetInputInformation(), + ddp->GetOutputInformation())) + { + inInfo->Set(MARKED_FOR_UPDATE(), 1); + } + } + } + } + } + } + + // Let the superclass handle other requests. + return this->Superclass::ProcessRequest(request, inInfoVec, outInfoVec); +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::VerifyOutputInformation( + int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) + +{ + if (outputPort < 0) + { + return this->Superclass::VerifyOutputInformation( + outputPort, inInfoVec, outInfoVec); + } + + vtkInformation* portInfo = + this->Algorithm->GetOutputPortInformation(outputPort); + if (portInfo->Has(COMPOSITE_DATA_TYPE_NAME())) + { + vtkInformation* outInfo = outInfoVec->GetInformationObject(outputPort); + // For an unstructured extent, make sure the update request + // exists. We do not need to check if it is valid because + // out-of-range requests produce empty data. + if(!outInfo->Has(MAXIMUM_NUMBER_OF_PIECES())) + { + vtkErrorMacro("No maximum number of pieces has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + if(!outInfo->Has(UPDATE_PIECE_NUMBER())) + { + vtkErrorMacro("No update piece number has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + if(!outInfo->Has(UPDATE_NUMBER_OF_PIECES())) + { + vtkErrorMacro("No update number of pieces has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + if(!outInfo->Has(UPDATE_NUMBER_OF_GHOST_LEVELS())) + { + // Use zero ghost levels by default. + outInfo->Set(UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); + } + return 1; + } + return this->Superclass::VerifyOutputInformation( + outputPort, inInfoVec, outInfoVec); +} + + +//---------------------------------------------------------------------------- +// Handle REQUEST_DATA_OBJECT +int vtkCompositeDataPipeline::ExecuteDataObject( + vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Invoke the request on the algorithm. + int result = this->CallAlgorithm(request, vtkExecutive::RequestDownstream, + inInfoVec, outInfoVec); + if (!result) + { + return result; + } + + result = this->ExecuteDataObjectForBlock(request); + if (!result) + { + return result; + } + + int i; + // Make sure a valid data object exists for all output ports. + for(i=0; result && i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + result = this->CheckDataObject(i, outInfoVec); + } + + // Make sure a valid composite data object exists for all output ports. + for(i=0; result && i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + result = this->CheckCompositeData(i, outInfoVec); + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::ExecuteDataObjectForBlock(vtkInformation* request) +{ + int result = 1; + + vtkInformationVector* outputVector = this->GetOutputInformation(); + int numOut = outputVector->GetNumberOfInformationObjects(); + for (int i=0; iAlgorithm->GetOutputPortInformation(0); + if (portInfo->Has(COMPOSITE_DATA_TYPE_NAME())) + { + vtkInformation* info = outputVector->GetInformationObject(i); + + vtkDataObject* doOutput = + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkCompositeDataSet* output = vtkCompositeDataSet::SafeDownCast(doOutput); + + vtkDataObject* simpleOutput = 0; + + if (output) + { + vtkDataObject* dobj; + + // If the index is specified, use it. Otherwise, use (0,0) + if (request->Has(vtkCompositeDataSet::INDEX())) + { + dobj = output->GetDataSet(request); + } + else + { + vtkSmartPointer r = + vtkSmartPointer::New(); + r->Set(vtkHierarchicalDataSet::LEVEL(), 0); + r->Set(vtkCompositeDataSet::INDEX(), 0); + dobj = output->GetDataSet(r); + } + + if (dobj) + { + this->DataObjectTime.Modified(); + + vtkDataObject* currDObj = info->Get(vtkDataObject::DATA_OBJECT()); + + if (currDObj && + strcmp(currDObj->GetClassName(), dobj->GetClassName()) == 0) + { + continue; + } + + simpleOutput = dobj->NewInstance(); + if (!simpleOutput) + { + vtkErrorMacro("Could not create a copy of " << dobj->GetClassName() + << "."); + return 0; + } + } + } + + if (!simpleOutput) + { + // If there was no current data object in the composite data object + // and there is already any data object in the output, move to the + // next port + if(info->Get(vtkDataObject::DATA_OBJECT())) + { + continue; + } + // Otherwise, simply create a polydata so that filters that + // must have a data object (such as datasettodataset filters) + // have a dummy dataset + simpleOutput = vtkPolyData::New(); + } + + simpleOutput->SetPipelineInformation(info); + simpleOutput->Delete(); + } + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::ExecuteInformationForBlock(vtkInformation* request) +{ + vtkInformationVector* outputVector = this->GetOutputInformation(); + int numOut = outputVector->GetNumberOfInformationObjects(); + for (int i=0; iGetInformationObject(i); + + vtkDataObject* doOutput = + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkCompositeDataSet* output = vtkCompositeDataSet::SafeDownCast(doOutput); + + if (output) + { + vtkDataObject* dobj = output->GetDataSet(request); + vtkDataObject* dobjCopy = + info->Get(vtkDataObject::DATA_OBJECT()); + if (dobj && dobjCopy) + { + dobjCopy->ShallowCopy(dobj); + dobjCopy->CopyInformation(dobj); + } + } + } + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::ExecuteDataStart( + vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + this->Superclass::ExecuteDataStart(request, inInfoVec, outInfoVec); + + // True when the pipeline is iterating over the current (simple) filter + // to produce composite output. In this case, ExecuteDataStart() should + // NOT Initialize() the composite output. + if (!this->InLocalLoop) + { + // Prepare outputs that will be generated to receive new data. + for(int i=0; i < outInfoVec->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outInfoVec->GetInformationObject(i); + vtkDataObject* data = + outInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + if(data && !outInfo->Get(DATA_NOT_GENERATED())) + { + data->PrepareForNewData(); + data->CopyInformationFromPipeline(request); + } + } + } +} + +//---------------------------------------------------------------------------- +// Handle REQUEST_DATA +int vtkCompositeDataPipeline::ExecuteData(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + int result = 1; + int outputPort = request->Get(FROM_OUTPUT_PORT()); + int i, j; + + for(i=0; i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* info = outInfoVec->GetInformationObject(i); + info->Remove(UPDATE_BLOCKS()); + } + + // Loop over all input ports. + for(i=0; i < this->Algorithm->GetNumberOfInputPorts(); ++i) + { + // Loop over all connections on this input port. + int numInConnections = inInfoVec[i]->GetNumberOfInformationObjects(); + for (j=0; jGetInformationObject(j); + vtkCompositeDataSet* input = vtkCompositeDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + // There is a composite input, no need to loop + if (input) + { + continue; + } + + vtkHierarchicalDataSet* updateInfo = + vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataPipeline::UPDATE_BLOCKS())); + + // Tell the producer upstream that looping is about to start + int retVal = this->SendBeginLoop(i, j, inInfo, updateInfo); + if (retVal == vtkCompositeDataPipeline::EXECUTE_BLOCK_CONTINUE) + { + continue; + } + if (retVal == vtkCompositeDataPipeline::EXECUTE_BLOCK_ERROR) + { + return 0; + } + + input = this->CreateInputCompositeData(i, inInfo); + + this->UpdateBlocks(i, j, outputPort, updateInfo, input, inInfo); + + if (!this->SendEndLoop(i, j)) + { + return 0; + } + } + } + + int inputPortIsComposite; + int inputIsComposite; + int compositePort; + this->CheckInputPorts(inputPortIsComposite, inputIsComposite, compositePort); + if (inputIsComposite && !inputPortIsComposite) + { + this->ExecuteSimpleAlgorithm( + request, inInfoVec, outInfoVec, compositePort); + } + else + { + result = this->Superclass::ExecuteData(request,inInfoVec,outInfoVec); + } + + for(int jj=0; jj < this->Algorithm->GetNumberOfOutputPorts(); ++jj) + { + vtkInformation* info = this->GetOutputInformation(jj); + vtkObject* dobj= info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + if (dobj) + { + info->Set(UPDATE_BLOCKS(), dobj); + } + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::CheckInputPorts(int& inputPortIsComposite, + int& inputIsComposite, + int& compositePort) +{ + inputPortIsComposite = 0; + inputIsComposite = 0; + compositePort = -1; + // Loop over all input ports and check if any of them asks + // for composite data and has composite data. + // Find the first port that asks for composite data and that + // has composite data and break. + // TODO: This should be changed to handle multiple ports that are + // a mix of composite and simple data. + for(int i=0; i < this->Algorithm->GetNumberOfInputPorts(); ++i) + { + vtkInformation* inPortInfo = + this->Algorithm->GetInputPortInformation(i); + if (inPortInfo->Has(INPUT_REQUIRED_COMPOSITE_DATA_TYPE())) + { + inputPortIsComposite = 1; + } + int numInConnections = this->Algorithm->GetNumberOfInputConnections(i); + if (numInConnections > 0) + { + vtkInformation* inInfo = this->GetInputInformation(i, 0); + if (inInfo->Has(vtkCompositeDataSet::COMPOSITE_DATA_SET())) + { + inputIsComposite = 1; + compositePort = i; + } + } + } +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::UpdateBlocks( + int i, int j, int outputPort, + vtkHierarchicalDataSet* updateInfo, + vtkCompositeDataSet* input, + vtkInformation* inInfo) +{ + // Get the producer and its output port for input connection i,j. + vtkExecutive* producer = 0; + int producerPort = -1; + if(vtkInformation* info = this->GetInputInformation(i, j)) + { + // Get the executive producing this input. If there is none, then + // it is a NULL input. + info->Get(vtkExecutive::PRODUCER(), producer, producerPort); + } + if(!producer) + { + this->SendEndLoop(i,j); + return EXECUTE_BLOCK_ERROR; + } + + // Execute the streaming demand driven pipeline for each block + unsigned int numLevels = updateInfo->GetNumberOfLevels(); + for (unsigned int k=0; kGetNumberOfDataSets(k); + for (unsigned l=0; lGetDataSet(k,l)) + { + vtkDebugMacro(<< k << "," << l << " not marked for update"); + continue; + } + // First pipeline mtime + + // Setup the request for pipeline modification time. + this->GenericRequest->Set(vtkHierarchicalDataSet::LEVEL(), k); + this->GenericRequest->Set(vtkCompositeDataSet::INDEX(), l); + unsigned long mtime; + producer->ComputePipelineMTime(this->GenericRequest, + producer->GetInputInformation(), + producer->GetOutputInformation(), + producerPort, &mtime); + + // Do the data-object creation pass before the information pass. + + // Send the request for data object creation. + this->DataObjectRequest->Set(vtkHierarchicalDataSet::LEVEL(), k); + this->DataObjectRequest->Set(vtkCompositeDataSet::INDEX(), l); + if (!this->ForwardUpstream(i, j, this->DataObjectRequest)) + { + this->SendEndLoop(i,j); + return EXECUTE_BLOCK_ERROR; + } + + // Send the request for information. + this->InformationRequest->Set(vtkHierarchicalDataSet::LEVEL(), k); + this->InformationRequest->Set(vtkCompositeDataSet::INDEX(), l); + if (!this->ForwardUpstream(i, j, this->InformationRequest)) + { + this->SendEndLoop(i,j); + return EXECUTE_BLOCK_ERROR; + } + + // Update the whole thing + // TODO: This might change + if (inInfo->Has(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())) + { + int extent[6] = {0,-1,0,-1,0,-1}; + inInfo->Get( + vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED(), 1); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 1); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + } + + // Send the request for update extent propagation. + this->UpdateExtentRequest->Set(vtkHierarchicalDataSet::LEVEL(), k); + this->UpdateExtentRequest->Set(vtkCompositeDataSet::INDEX(), l); + this->UpdateExtentRequest->Set( + vtkExecutive::FROM_OUTPUT_PORT(), outputPort); + if (!this->ForwardUpstream(i, j, this->UpdateExtentRequest)) + { + this->SendEndLoop(i,j); + return EXECUTE_BLOCK_ERROR; + } + + // Send the request for data. + this->DataRequest->Set(vtkHierarchicalDataSet::LEVEL(), k); + this->DataRequest->Set(vtkCompositeDataSet::INDEX(), l); + this->DataRequest->Set(FROM_OUTPUT_PORT(), outputPort); + + // Send the request. + if (!this->ForwardUpstream(i, j, this->DataRequest)) + { + this->SendEndLoop(i,j); + return EXECUTE_BLOCK_ERROR; + } + + vtkDataObject* block = inInfo->Get(vtkDataObject::DATA_OBJECT()); + if (block && input) + { + vtkDataObject* blockCopy = block->NewInstance(); + blockCopy->ShallowCopy(block); + input->AddDataSet(this->DataRequest, blockCopy); + blockCopy->Delete(); + } + } + } + return EXECUTE_BLOCK_OK; +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::SendBeginLoop( + int i, int j, vtkInformation* inInfo, vtkHierarchicalDataSet* updateInfo) +{ + + // Tell the producer upstream that looping is about to start + this->GenericRequest->Set(BEGIN_LOOP(), 1); + + // The request is forwarded upstream through the pipeline. + this->GenericRequest->Set( + vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + + this->GenericRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + + // Send the request. + if (!this->ForwardUpstream(i, j, this->GenericRequest)) + { + this->GenericRequest->Remove(BEGIN_LOOP()); + return vtkCompositeDataPipeline::EXECUTE_BLOCK_ERROR; + } + + if (!updateInfo) + { + // This means no composite data producer was found upstream. + vtkDebugMacro(<< "No UPDATE_BLOCKS() for input " << i << "," << j + << " was provided. Skipping."); + this->SendEndLoop(i,j); + this->GenericRequest->Remove(BEGIN_LOOP()); + return vtkCompositeDataPipeline::EXECUTE_BLOCK_CONTINUE; + } + + // If the input is up-to-date (not MARKED_FOR_UPDATE() by ProcessRequest -> + // REQUEST_DATA()), there is no need to loop the input. If the input is + // looped, it will cause unnecessary execution(s) + if (!inInfo->Has(MARKED_FOR_UPDATE())) + { + this->SendEndLoop(i,j); + this->GenericRequest->Remove(BEGIN_LOOP()); + return vtkCompositeDataPipeline::EXECUTE_BLOCK_CONTINUE; + } + this->GenericRequest->Remove(BEGIN_LOOP()); + + return vtkCompositeDataPipeline::EXECUTE_BLOCK_OK; +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::SendEndLoop(int i, int j) +{ + // Tell the producer upstream that looping is over + vtkSmartPointer re = + vtkSmartPointer::New(); + re->Set(END_LOOP(), 1); + + // The request is forwarded upstream through the pipeline. + re->Set(vtkExecutive::FORWARD_DIRECTION(), + vtkExecutive::RequestUpstream); + + // Send the request. + if (!this->ForwardUpstream(i, j, re)) + { + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::ExecuteSimpleAlgorithm( + vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int compositePort) +{ + int outputInitialized = 0; + + this->ExecuteDataStart(request,inInfoVec,outInfoVec); + + vtkInformation* outInfo = 0; + vtkSmartPointer prevOutput; + + if (this->GetNumberOfOutputPorts() > 0) + { + outInfo = outInfoVec->GetInformationObject(0); + } + + // Make sure a valid composite data object exists for all output ports. + for(int i=0; i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + this->CheckCompositeData(i, outInfoVec); + } + + // Loop using the first input on the first port. + // This might not be valid for all cases but it is a decent + // assumption to start with. + // TODO: Loop over all inputs + vtkInformation* inInfo = this->GetInputInformation(compositePort, 0); + vtkCompositeDataSet* input = vtkCompositeDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + vtkHierarchicalDataSet* updateInfo = + vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataPipeline::UPDATE_BLOCKS())); + + vtkCompositeDataSet* output = + vtkCompositeDataSet::SafeDownCast( + outInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + prevOutput = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if (input && updateInfo) + { + vtkSmartPointer r = + vtkSmartPointer::New(); + + r->Set(FROM_OUTPUT_PORT(), inInfo->GetPort(PRODUCER())); + + // The request is forwarded upstream through the pipeline. + r->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + + // Algorithms process this request after it is forwarded. + r->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + + unsigned int numLevels = updateInfo->GetNumberOfLevels(); + vtkSmartPointer prevInput = + inInfo->Get(vtkDataObject::DATA_OBJECT()); + + vtkDebugMacro("EXECUTING: " << this->Algorithm->GetClassName()); + + // True when the pipeline is iterating over the current (simple) + // filter to produce composite output. In this case, + // ExecuteDataStart() should NOT Initialize() the composite output. + this->InLocalLoop = 1; + + // Store the information (whole_extent and maximum_number_of_pieces) + // before looping. Otherwise, executeinformation will cause + // changes (because we pretend that the max. number of pieces is + // one to process the whole block) + this->PushInformation(inInfo); + for (unsigned int k=0; kGetNumberOfDataSets(k); + for (unsigned l=0; lGetDataSet(k,l)) + { + r->Set(vtkHierarchicalDataSet::LEVEL(), k); + r->Set(vtkCompositeDataSet::INDEX(), l); + vtkDataObject* dobj = input->GetDataSet(r); + // There must be a bug somehwere. If this Remove() + // is not called, the following Set() has the effect + // of removing (!) the key. + inInfo->Remove(vtkDataObject::DATA_OBJECT()); + inInfo->Set(vtkDataObject::DATA_OBJECT(), dobj); + + // Process the whole dataset + this->CopyFromDataToInformation(dobj, inInfo); + + r->Set(REQUEST_DATA_OBJECT()); + this->Superclass::ExecuteDataObject + (r,this->GetInputInformation(),this->GetOutputInformation()); + r->Remove(REQUEST_DATA_OBJECT()); + + r->Set(REQUEST_INFORMATION()); + this->Superclass::ExecuteInformation(r,inInfoVec,outInfoVec); + r->Remove(REQUEST_INFORMATION()); + + for(int m=0; m < this->Algorithm->GetNumberOfOutputPorts(); ++m) + { + vtkInformation* info = this->GetOutputInformation(m); + + // Update the whole thing + // TODO: This might change + if (info->Has( + vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())) + { + int extent[6] = {0,-1,0,-1,0,-1}; + info->Get( + vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + extent); + info->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + extent, + 6); + info->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED(), + 1); + info->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + info->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + } + } + + r->Set(REQUEST_UPDATE_EXTENT()); + this->CallAlgorithm(r, vtkExecutive::RequestUpstream, + inInfoVec, outInfoVec); + this->ForwardUpstream(r); + r->Remove(REQUEST_UPDATE_EXTENT()); + + r->Set(REQUEST_DATA()); + this->Superclass::ExecuteData(r,inInfoVec,outInfoVec); + r->Remove(REQUEST_DATA()); + + if (output && outInfo) + { + if (!outputInitialized) + { + output->PrepareForNewData(); + outputInitialized = 1; + } + vtkDataObject* tmpOutput = + outInfo->Get(vtkDataObject::DATA_OBJECT()); + vtkDataObject* outputCopy = tmpOutput->NewInstance(); + outputCopy->ShallowCopy(tmpOutput); + output->AddDataSet(r, outputCopy); + outputCopy->Delete(); + } + } + } + } + // True when the pipeline is iterating over the current (simple) + // filter to produce composite output. In this case, + // ExecuteDataStart() should NOT Initialize() the composite output. + this->InLocalLoop = 0; + // Restore the extent information and force it to be + // copied to the output. Composite sources should set + // MAXIMUM_NUMBER_OF_PIECES to -1 anyway (and handle + // piece requests properly). + this->PopInformation(inInfo); + r->Set(REQUEST_INFORMATION()); + this->CopyDefaultInformation(r, vtkExecutive::RequestDownstream, + this->GetInputInformation(), + this->GetOutputInformation()); + + vtkDataObject* curInput = inInfo->Get(vtkDataObject::DATA_OBJECT()); + if (curInput != prevInput) + { + inInfo->Remove(vtkDataObject::DATA_OBJECT()); + inInfo->Set(vtkDataObject::DATA_OBJECT(), prevInput); + } + vtkDataObject* curOutput = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if (curOutput != prevOutput) + { + prevOutput->SetPipelineInformation(outInfo); + } + } + this->ExecuteDataEnd(request,inInfoVec,outInfoVec); +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::ExecuteDataForBlock(vtkInformation* request) +{ + vtkInformationVector* outputVector = this->GetOutputInformation(); + int numOut = outputVector->GetNumberOfInformationObjects(); + for (int i=0; iGetInformationObject(i); + + vtkDataObject* doOutput = + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkCompositeDataSet* output = vtkCompositeDataSet::SafeDownCast(doOutput); + + if (output) + { + vtkDataObject* dobj = output->GetDataSet(request); + if (dobj) + { + vtkDataObject* dobjCopy = + info->Get(vtkDataObject::DATA_OBJECT()); + + if (dobj && dobjCopy) + { + dobjCopy->ShallowCopy(dobj); + } + } + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::ForwardUpstream(vtkInformation* request) +{ + return this->Superclass::ForwardUpstream(request); +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::ForwardUpstream( + int i, int j, vtkInformation* request) +{ + // Do not forward upstream if input information is shared. + if(this->SharedInputInformation) + { + return 1; + } + + if (!this->Algorithm->ModifyRequest(request, BeforeForward)) + { + return 0; + } + + int result = 1; + if(vtkExecutive* e = this->GetInputExecutive(i, j)) + { + vtkAlgorithmOutput* input = this->Algorithm->GetInputConnection(i, j); + int port = request->Get(FROM_OUTPUT_PORT()); + request->Set(FROM_OUTPUT_PORT(), input->GetIndex()); + if(!e->ProcessRequest(request, + e->GetInputInformation(), + e->GetOutputInformation())) + { + result = 0; + } + request->Set(FROM_OUTPUT_PORT(), port); + } + + if (!this->Algorithm->ModifyRequest(request, AfterForward)) + { + return 0; + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::CopyDefaultInformation( + vtkInformation* request, int direction, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + int hasUpdateBlocks = 0; + if(direction == vtkExecutive::RequestDownstream) + { + vtkInformationKey** keys = request->Get(vtkExecutive::KEYS_TO_COPY()); + if (keys) + { + int len = request->Length(vtkExecutive::KEYS_TO_COPY()); + for (int i=0; iRemove(vtkExecutive::KEYS_TO_COPY(), + vtkCompositeDataPipeline::UPDATE_BLOCKS()); + } + } + } + this->Superclass::CopyDefaultInformation(request, direction, + inInfoVec, outInfoVec); + if (hasUpdateBlocks) + { + request->Append(vtkExecutive::KEYS_TO_COPY(), + vtkCompositeDataPipeline::UPDATE_BLOCKS()); + } +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::CopyFromDataToInformation( + vtkDataObject* dobj, vtkInformation* inInfo) +{ + if (dobj->IsA("vtkImageData")) + { + inInfo->Set( + WHOLE_EXTENT(), static_cast(dobj)->GetExtent(), 6); + } + else if (dobj->IsA("vtkStructuredGrid")) + { + inInfo->Set( + WHOLE_EXTENT(), static_cast(dobj)->GetExtent(), 6); + } + else if (dobj->IsA("vtkRectilinearGrid")) + { + inInfo->Set( + WHOLE_EXTENT(), static_cast(dobj)->GetExtent(), 6); + } + else if (dobj->IsA("vtkUniformGrid")) + { + inInfo->Set( + WHOLE_EXTENT(), static_cast(dobj)->GetExtent(), 6); + } + else + { + inInfo->Set(MAXIMUM_NUMBER_OF_PIECES(), 1); + } +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::PushInformation(vtkInformation* inInfo) +{ + this->InformationCache->CopyEntry(inInfo, WHOLE_EXTENT()); + this->InformationCache->CopyEntry(inInfo, MAXIMUM_NUMBER_OF_PIECES()); +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::PopInformation(vtkInformation* inInfo) +{ + inInfo->CopyEntry(this->InformationCache, WHOLE_EXTENT()); + inInfo->CopyEntry(this->InformationCache, MAXIMUM_NUMBER_OF_PIECES()); +} + +//---------------------------------------------------------------------------- +vtkCompositeDataSet* vtkCompositeDataPipeline::CreateInputCompositeData( + int i, vtkInformation* inInfo) +{ + vtkCompositeDataSet* input = 0; + + // If the input requires a composite dataset and one is not available, + // create it. This means that there are "simple" filters between the + // composite data producer and this filter + vtkInformation* inPortInfo = + this->Algorithm->GetInputPortInformation(i); + const char* dt = + inPortInfo->Get(INPUT_REQUIRED_COMPOSITE_DATA_TYPE()); + if (dt) + { + if (strcmp(dt, "vtkCompositeDataSet") == 0) + { + // If vtkCompositeDataSet is specified, the algorithm + // will work with all sub-classes. Create a vtkHierarchicalDataSet + dt = "vtkHierarchicalDataSet"; + } + // If the composite data input to the algorithm is not + // set, create and assign it. This happens when the producer + // of the input data actually produces a simple data object + // (in a loop) + vtkDataObject* dobj = this->NewDataObject(dt); + if (dobj) + { + dobj->SetPipelineInformation(inInfo); + input = vtkCompositeDataSet::SafeDownCast(dobj); + dobj->Delete(); + } + else + { + vtkErrorMacro("Cannot instantiate " << dt + << ". The INPUT_REQUIRED_COMPOSITE_DATA_TYPE() of " + << this->Algorithm->GetClassName() + << " is not set properly."); + + } + } + return input; +} + + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::CheckDataObject( + int port, vtkInformationVector *outInfoVec) +{ + // Check that the given output port has a valid data object. + vtkInformation* outInfo = + outInfoVec->GetInformationObject(port); + vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT()); + vtkInformation* portInfo = this->Algorithm->GetOutputPortInformation(port); + if(const char* dt = portInfo->Get(vtkDataObject::DATA_TYPE_NAME())) + { + // The output port specifies a data type. Make sure the data + // object exists and is of the right type. + if(!data || !data->IsA(dt)) + { + // Try to create an instance of the correct type. + data = this->NewDataObject(dt); + this->SetOutputData(port, data, outInfo); + if(data) + { + data->Delete(); + } + } + if(!data) + { + // The algorithm has a bug and did not create the data object. + vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" + << this->Algorithm + << ") did not create output for port " << port + << " when asked by REQUEST_DATA_OBJECT and does not" + << " specify a concrete DATA_TYPE_NAME."); + return 0; + } + return 1; + } + else if(data || outInfo->Has(vtkCompositeDataSet::COMPOSITE_DATA_SET())) + { + // The algorithm did not specify its output data type. Just assume + // the data object is of the correct type. + return 1; + } + else + { + // The algorithm did not specify its output data type and no + // object exists. + vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" + << this->Algorithm + << ") did not create output for port " << port + << " when asked by REQUEST_DATA_OBJECT and does not" + << " specify any DATA_TYPE_NAME."); + return 0; + } +} + +//---------------------------------------------------------------------------- +int vtkCompositeDataPipeline::CheckCompositeData( + int port, vtkInformationVector* outInfoVec) +{ + // Check that the given output port has a valid data object. + vtkInformation* outInfo = outInfoVec->GetInformationObject(port); + vtkDataObject* data = + outInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkInformation* portInfo = this->Algorithm->GetOutputPortInformation(port); + if (const char* dt = portInfo->Get(COMPOSITE_DATA_TYPE_NAME())) + { + if(!data || !data->IsA(dt)) + { + // Try to create an instance of the correct type. + data = this->NewDataObject(dt); + data->SetPipelineInformation(outInfo); + if(data) + { + data->Delete(); + } + } + } + + // If this is a simple filter but has composite input, create a composite + // output. + int inputPortIsComposite; + int inputIsComposite; + int compositePort; + this->CheckInputPorts(inputPortIsComposite, inputIsComposite, compositePort); + if (inputIsComposite && !inputPortIsComposite) + { + // This assumes that the filter has one output. + vtkDataObject* doOutput = + outInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkCompositeDataSet* output = vtkCompositeDataSet::SafeDownCast(doOutput); + if (!output) + { + output = vtkHierarchicalDataSet::New(); + output->SetPipelineInformation(outInfo); + output->Delete(); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkCompositeDataPipeline::GetCompositeOutputData(int port) +{ + if(!this->OutputPortIndexInRange(port, "get data for")) + { + return 0; + } + + // Check that the given output port has a valid data object. + this->CheckCompositeData(port, this->GetOutputInformation()); + + // Return the data object. + if(vtkInformation* info = this->GetOutputInformation(port)) + { + return info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataPipeline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + diff --git a/Filtering/vtkCompositeDataPipeline.h b/Filtering/vtkCompositeDataPipeline.h new file mode 100644 index 0000000..4388d18 --- /dev/null +++ b/Filtering/vtkCompositeDataPipeline.h @@ -0,0 +1,216 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositeDataPipeline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCompositeDataPipeline - Executive supporting composite datasets. +// .SECTION Description +// vtkCompositeDataPipeline is an executive that supports the processing of +// composite dataset. It supports algorithms that are aware of composite +// dataset as well as those that are not. Portions of the pipeline that are +// note composite dataset-aware are looped by the next consumer that is +// composite dataset-aware. Type checking is performed at run +// time. Algorithms that are not composite dataset-aware have to support +// all dataset types contained in the composite dataset. The pipeline +// execution can be summarized as follows: +// +// * REQUEST_INFORMATION: The producers have to provide information about +// the contents of the composite dataset in this pass. This is accomplished +// by creating and populating a vtkHierarchicalDataInformation and setting +// it using the COMPOSITE_DATA_INFORMATION() key in the output information +// vector. Sources that can produce more than one piece (note that a piece is +// different than a block; each piece consistes of 0 or more blocks) should +// set MAXIMUM_NUMBER_OF_PIECES to -1. +// +// * REQUEST_UPDATE_EXTENT: This pass is identical to the one implemented +// in vtkStreamingDemandDrivenPipeline +// +// * BEGIN_LOOP: The source is told that looping is about to start. +// The source has to perform "extent translation". This is the process +// by which the piece request is converted to a block request. +// This is done by adding a MARKED_FOR_UPDATE() key to the appropriate blocks +// in UPDATE_BLOCKS(). +// +// * REQUEST_DATA: This is where the algorithms execute. If a composite +// data algorithm is consuming the output of a simple data algorithm, the +// executive will execute the streaming demand driven pipeline passes for +// each block: +// @verbatim +// for each block +// REQUEST_PIPELINE_MODIFIED_TIME() +// REQUEST_DATA_OBJECT() +// REQUEST_INFORMATION() +// REQUEST_DATA() +// @endverbatim +// The request passed to these passes will contain a LEVEL() and INDEX() key +// of each block to be updated. +// Shallow copies of individual blocks are added to the composite input +// of the algorithm. Finally, the request is passed to the algorithm. +// If the algorithm it points to is simple, the executive will also call +// it on each block and collect the results as the output. +// Furthermore, if the vtkCompositeDataPipeline is assigned to a simple filter, +// it will invoke the vtkStreamingDemandDrivenPipeline passes in a loop, +// passing a different block each time and will collect the results in a +// composite dataset (vtkHierarchicalDataSet). +// .SECTION See also +// vtkHierarchicalDataInformation vtkCompositeDataSet vtkHierarchicalDataSet + +#ifndef __vtkCompositeDataPipeline_h +#define __vtkCompositeDataPipeline_h + +#include "vtkStreamingDemandDrivenPipeline.h" + +class vtkCompositeDataSet; +class vtkHierarchicalDataSet; +class vtkInformationDoubleKey; +class vtkInformationIntegerVectorKey; +class vtkInformationObjectBaseKey; +class vtkInformationStringKey; +class vtkInformationDataObjectKey; + +class VTK_FILTERING_EXPORT vtkCompositeDataPipeline : public vtkStreamingDemandDrivenPipeline +{ +public: + static vtkCompositeDataPipeline* New(); + vtkTypeRevisionMacro(vtkCompositeDataPipeline,vtkStreamingDemandDrivenPipeline); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Generalized interface for asking the executive to fullfill update + // requests. + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + // Description: + // Override the pipeline modified time request to support + // sub-passes. + virtual int + ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int reqeustFromOutputPort, + unsigned long* mtime); + + // Description: + // Returns the data object stored with the COMPOSITE_DATA_SET() in the + // output port + vtkDataObject* GetCompositeOutputData(int port); + + // Description: + // vtkCompositeDataPipeline specific keys + static vtkInformationIntegerKey* BEGIN_LOOP(); + static vtkInformationIntegerKey* END_LOOP(); + static vtkInformationStringKey* COMPOSITE_DATA_TYPE_NAME(); + static vtkInformationObjectBaseKey* COMPOSITE_DATA_INFORMATION(); + static vtkInformationIntegerKey* MARKED_FOR_UPDATE(); + static vtkInformationStringKey* INPUT_REQUIRED_COMPOSITE_DATA_TYPE(); + static vtkInformationObjectBaseKey* UPDATE_BLOCKS(); + +protected: + vtkCompositeDataPipeline(); + ~vtkCompositeDataPipeline(); + + // Check whether the data object in the pipeline information for an + // output port exists and has a valid type. + virtual int CheckDataObject(int port, vtkInformationVector *outInfo); + + virtual int ForwardUpstream(vtkInformation* request); + virtual int ForwardUpstream(int i, int j, vtkInformation* request); + + // Copy information for the given request. + virtual void CopyDefaultInformation(vtkInformation* request, int direction, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + virtual void CopyFromDataToInformation( + vtkDataObject* dobj, vtkInformation* inInfo); + virtual void PushInformation(vtkInformation*); + virtual void PopInformation (vtkInformation*); + + // Composite data pipeline times. Similar to superclass' + vtkTimeStamp SubPassTime; + + // If true, the producer is being driven in a loop (dumb filters + // between composite consumer and producer) + int InSubPass; + + virtual int ExecuteDataObjectForBlock(vtkInformation* request); + virtual int ExecuteDataObject(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + virtual int ExecuteInformationForBlock(vtkInformation* request); + + virtual int ExecuteDataForBlock(vtkInformation* request); + virtual int ExecuteData(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + virtual void ExecuteDataStart(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + // Helper to check output information before propagating it to inputs. + virtual int VerifyOutputInformation(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + + int CheckCompositeData(int port, vtkInformationVector* outInfoVec); + int SendEndLoop(int i, int j); + + // True when the pipeline is iterating over the current (simple) filter + // to produce composite output. In this case, ExecuteDataStart() should + // NOT Initialize() the composite output. + int InLocalLoop; + + virtual int SendBeginLoop(int i, int j, + vtkInformation* inInfo, + vtkHierarchicalDataSet* updateInfo); + virtual vtkCompositeDataSet* CreateInputCompositeData( + int i, vtkInformation* inInfo); + virtual int UpdateBlocks(int i, int j, int outputPort, + vtkHierarchicalDataSet* updateInfo, + vtkCompositeDataSet* input, + vtkInformation* inInfo); + virtual void ExecuteSimpleAlgorithm(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int compositePort); + void CheckInputPorts(int& inputPortIsComposite, + int& inputIsComposite, + int& compositePort); + + vtkInformation* InformationCache; + + vtkInformation* GenericRequest; + vtkInformation* DataObjectRequest; + vtkInformation* InformationRequest; + vtkInformation* UpdateExtentRequest; + vtkInformation* DataRequest; + +//BTX + enum BeginForward + { + EXECUTE_BLOCK_OK, + EXECUTE_BLOCK_CONTINUE, + EXECUTE_BLOCK_ERROR + }; +//ETX + +private: + vtkCompositeDataPipeline(const vtkCompositeDataPipeline&); // Not implemented. + void operator=(const vtkCompositeDataPipeline&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkCompositeDataSet.cxx b/Filtering/vtkCompositeDataSet.cxx new file mode 100644 index 0000000..0ac864d --- /dev/null +++ b/Filtering/vtkCompositeDataSet.cxx @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositeDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCompositeDataSet.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkCompositeDataIterator.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkInformationDataObjectKey.h" +#include "vtkInformationIntegerKey.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkCompositeDataSet, "$Revision: 1.7.8.1 $"); + +vtkInformationKeyMacro(vtkCompositeDataSet,INDEX,Integer); +vtkInformationKeyMacro(vtkCompositeDataSet,COMPOSITE_DATA_SET,DataObject); + +//---------------------------------------------------------------------------- +vtkCompositeDataSet::vtkCompositeDataSet() +{ +} + +//---------------------------------------------------------------------------- +vtkCompositeDataSet::~vtkCompositeDataSet() +{ +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataSet::Initialize() +{ + this->Superclass::Initialize(); +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataSet::SetPipelineInformation(vtkInformation* newInfo) +{ + vtkInformation* oldInfo = this->PipelineInformation; + if(newInfo != oldInfo) + { + if(newInfo) + { + // Reference the new information. + newInfo->Register(this); + + // Detach the output that used to be held by the new information. + if(vtkDataObject* oldData = + newInfo->Get(COMPOSITE_DATA_SET())) + { + oldData->Register(this); + oldData->SetPipelineInformation(0); + oldData->UnRegister(this); + } + + // Tell the new information about this object. + newInfo->Set(COMPOSITE_DATA_SET(), this); + } + + // Save the pointer to the new information. + this->PipelineInformation = newInfo; + + if(oldInfo) + { + // Remove the old information's reference to us. + oldInfo->Set(COMPOSITE_DATA_SET(), 0); + + // Remove our reference to the old information. + oldInfo->UnRegister(this); + } + } +} + +//---------------------------------------------------------------------------- +vtkAlgorithmOutput* vtkCompositeDataSet::GetProducerPort() +{ + // Make sure there is an executive. + if(!this->GetExecutive()) + { + vtkTrivialProducer* tp = vtkTrivialProducer::New(); + vtkCompositeDataPipeline* exec = vtkCompositeDataPipeline::New(); + tp->SetExecutive(exec); + vtkInformation* portInfo = + tp->GetOutputPortInformation(0); + portInfo->Set(vtkCompositeDataPipeline::COMPOSITE_DATA_TYPE_NAME(), + this->GetClassName()); + exec->Delete(); + tp->SetOutput(this); + tp->Delete(); + } + + // Get the port from the executive. + return this->GetExecutive()->GetProducerPort(this); +} + +//---------------------------------------------------------------------------- +vtkCompositeDataSet* vtkCompositeDataSet::GetData(vtkInformation* info) +{ + return info? vtkCompositeDataSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkCompositeDataSet* vtkCompositeDataSet::GetData(vtkInformationVector* v, + int i) +{ + return vtkCompositeDataSet::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +void vtkCompositeDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + // this->UpdateExtent + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Filtering/vtkCompositeDataSet.h b/Filtering/vtkCompositeDataSet.h new file mode 100644 index 0000000..98d358d --- /dev/null +++ b/Filtering/vtkCompositeDataSet.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositeDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCompositeDataSet - abstact superclass for composite (multi-block or AMR) datasets +// .SECTION Description +// vtkCompositeDataSet is an abstract class that represents a collection +// of datasets (including other composite datasets). This superclass +// does not implement an actual method for storing datasets. It +// only provides an interface to access the datasets through iterators. + +// .SECTION See Also +// vtkCompositeDataIterator + +#ifndef __vtkCompositeDataSet_h +#define __vtkCompositeDataSet_h + +#include "vtkDataObject.h" + +class vtkCompositeDataIterator; +class vtkInformation; +class vtkInformationDataObjectKey; + +class VTK_FILTERING_EXPORT vtkCompositeDataSet : public vtkDataObject +{ +public: + vtkTypeRevisionMacro(vtkCompositeDataSet,vtkDataObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return a new (forward) iterator + // (the iterator has to be deleted by user) + virtual vtkCompositeDataIterator* NewIterator() = 0; + + // Description: + // Return class name of data type (see vtkSystemIncludes.h for + // definitions). + virtual int GetDataObjectType() {return VTK_COMPOSITE_DATA_SET;} + + // Description: + // Restore data object to initial state, + virtual void Initialize(); + + // Description: + // Adds dobj to the composite dataset. Where the dataset goes is determined + // by appropriate keys in the index information object. Which keys are used + // depends on the actual subclass. + virtual void AddDataSet(vtkInformation* index, vtkDataObject* dobj) = 0; + + // Description: + // Returns a dataset pointed by appropriate keys in the index information + // object. Which keys are used depends on the actual subclass. + virtual vtkDataObject* GetDataSet(vtkInformation* index) = 0; + + // Description: + // Set the pipeline information object that owns this data + // object. + virtual void SetPipelineInformation(vtkInformation*); + + // Description: + // Get the port currently producing this object. + virtual vtkAlgorithmOutput* GetProducerPort(); + + static vtkInformationIntegerKey* INDEX(); + static vtkInformationDataObjectKey* COMPOSITE_DATA_SET(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkCompositeDataSet* GetData(vtkInformation* info); + static vtkCompositeDataSet* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkCompositeDataSet(); + ~vtkCompositeDataSet(); + +private: + vtkCompositeDataSet(const vtkCompositeDataSet&); // Not implemented. + void operator=(const vtkCompositeDataSet&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkCone.cxx b/Filtering/vtkCone.cxx new file mode 100644 index 0000000..a223690 --- /dev/null +++ b/Filtering/vtkCone.cxx @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCone.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCone.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCone, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkCone); + +// Construct cone with angle of 45 degrees. +vtkCone::vtkCone() +{ + this->Angle = 45.0; +} + +// Evaluate cone equation. +double vtkCone::EvaluateFunction(double x[3]) +{ + double tanTheta = (double) + tan((double)this->Angle*vtkMath::DegreesToRadians()); + return x[1]*x[1] + x[2]*x[2] - x[0]*x[0]*tanTheta*tanTheta; +} + +// Evaluate cone normal. +void vtkCone::EvaluateGradient(double x[3], double g[3]) +{ + double tanTheta = (double) + tan((double)this->Angle*vtkMath::DegreesToRadians()); + g[0] = -2.0*x[0]*tanTheta*tanTheta; + g[1] = 2.0*x[1]; + g[2] = 2.0*x[2]; +} + +void vtkCone::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Angle: " << this->Angle << "\n"; +} diff --git a/Filtering/vtkCone.h b/Filtering/vtkCone.h new file mode 100644 index 0000000..9009507 --- /dev/null +++ b/Filtering/vtkCone.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCone.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCone - implicit function for a cone +// .SECTION Description +// vtkCone computes the implicit function and function gradient for a cone. +// vtkCone is a concrete implementation of vtkImplicitFunction. The cone vertex +// is located at the origin with axis of rotation coincident with x-axis. (Use +// the superclass' vtkImplicitFunction transformation matrix if necessary to +// reposition.) The angle specifies the angle between the axis of rotation +// and the side of the cone. + +// .SECTION Caveats +// The cone is infinite in extent. To truncate the cone use the +// vtkImplicitBoolean in combination with clipping planes. + +#ifndef __vtkCone_h +#define __vtkCone_h + +#include "vtkImplicitFunction.h" + +class VTK_FILTERING_EXPORT vtkCone : public vtkImplicitFunction +{ +public: + // Description + // Construct cone with angle of 45 degrees. + static vtkCone *New(); + + vtkTypeRevisionMacro(vtkCone,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Evaluate cone equation. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate cone normal. + void EvaluateGradient(double x[3], double g[3]); + + // Description: + // Set/Get the cone angle (expressed in degrees). + vtkSetClampMacro(Angle,double,0.0,89.0); + vtkGetMacro(Angle,double); + +protected: + vtkCone(); + ~vtkCone() {}; + + double Angle; + +private: + vtkCone(const vtkCone&); // Not implemented. + void operator=(const vtkCone&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkConvexPointSet.cxx b/Filtering/vtkConvexPointSet.cxx new file mode 100644 index 0000000..3b5fa3d --- /dev/null +++ b/Filtering/vtkConvexPointSet.cxx @@ -0,0 +1,421 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkConvexPointSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkConvexPointSet.h" + +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkOrderedTriangulator.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" +#include "vtkTetra.h" +#include "vtkTriangle.h" + +vtkCxxRevisionMacro(vtkConvexPointSet, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkConvexPointSet); + +//---------------------------------------------------------------------------- +// Construct the hexahedron with eight points. +vtkConvexPointSet::vtkConvexPointSet() +{ + this->Tetra = vtkTetra::New(); + this->TetraIds = vtkIdList::New(); + this->TetraPoints = vtkPoints::New(); + this->TetraScalars = vtkDoubleArray::New(); + this->TetraScalars->SetNumberOfTuples(4); + this->BoundaryTris = vtkCellArray::New(); + this->BoundaryTris->Allocate(100); + this->Triangle = vtkTriangle::New(); + this->Triangulator = vtkOrderedTriangulator::New(); + this->Triangulator->PreSortedOff(); + this->Triangulator->UseTemplatesOff(); + this->ParametricCoords = NULL; +} + +//---------------------------------------------------------------------------- +vtkConvexPointSet::~vtkConvexPointSet() +{ + this->Tetra->Delete(); + this->TetraIds->Delete(); + this->TetraPoints->Delete(); + this->TetraScalars->Delete(); + this->BoundaryTris->Delete(); + this->Triangle->Delete(); +} + +//---------------------------------------------------------------------------- +// Should be called by GetCell() prior to any other method invocation +void vtkConvexPointSet::Initialize() +{ + // Initialize + vtkIdType numPts=this->GetNumberOfPoints(); + if ( numPts < 1 ) return; + + this->Triangulate(0, this->TetraIds,this->TetraPoints); +} + +//---------------------------------------------------------------------------- +int vtkConvexPointSet::GetNumberOfFaces() +{ + this->BoundaryTris->Reset(); + this->Triangulator->AddTriangles(this->BoundaryTris); + return this->BoundaryTris->GetNumberOfCells(); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkConvexPointSet::GetFace(int faceId) +{ + int numCells = this->BoundaryTris->GetNumberOfCells(); + if ( faceId < 0 || faceId >=numCells ) {return NULL;} + + vtkIdType *cells = this->BoundaryTris->GetPointer(); + + // Each triangle has three points plus number of points + vtkIdType *cptr = cells + 4*faceId; + for (int i=0; i<3; i++) + { + this->Triangle->PointIds->SetId(i,this->PointIds->GetId(cptr[i+1])); + this->Triangle->Points->SetPoint(i,this->Points->GetPoint(cptr[i+1])); + } + + return this->Triangle; +} + +//---------------------------------------------------------------------------- +int vtkConvexPointSet::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + int numPts=this->GetNumberOfPoints(); + int i; + double x[3]; + vtkIdType ptId; + + // Initialize + ptIds->Reset(); + pts->Reset(); + if ( numPts < 1 ) return 0; + + // Initialize Delaunay insertion process. + // No more than numPts points can be inserted. + this->Triangulator->InitTriangulation(this->GetBounds(), numPts); + + // Inject cell points into triangulation. Recall that the PreSortedOff() + // flag was set which means that the triangulator will order the points + // according to point id. We insert points with id == the index into the + // vtkConvexPointSet::PointIds and Points; but sort on the global point + // id. + for (i=0; iPointIds->GetId(i); + this->Points->GetPoint(i, x); + this->Triangulator->InsertPoint(i, ptId, x, x, 0); + }//for all points + + // triangulate the points + this->Triangulator->Triangulate(); + + // Add the triangulation to the mesh + this->Triangulator->AddTetras(0,ptIds,pts); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkConvexPointSet::Contour(double value, + vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + // For each tetra, contour it + int i, j; + vtkIdType ptId, localId; + int numTets = this->TetraIds->GetNumberOfIds() / 4; + for (i=0; iTetraIds->GetId(4*i+j); + ptId = this->PointIds->GetId(localId); + this->Tetra->PointIds->SetId(j,ptId); + this->Tetra->Points->SetPoint(j,this->TetraPoints->GetPoint(4*i+j)); + this->TetraScalars->SetValue(j,cellScalars->GetTuple1(localId)); + } + this->Tetra->Contour(value,this->TetraScalars,locator,verts,lines,polys, + inPd,outPd,inCd,cellId,outCd); + } +} + + + +//---------------------------------------------------------------------------- +void vtkConvexPointSet::Clip(double value, + vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, + vtkCellData *outCD, int insideOut) +{ + // For each tetra, contour it + int i, j; + vtkIdType ptId, localId; + int numTets = this->TetraIds->GetNumberOfIds() / 4; + for (i=0; iTetraIds->GetId(4*i+j); + ptId = this->PointIds->GetId(localId); + this->Tetra->PointIds->SetId(j,ptId); + this->Tetra->Points->SetPoint(j,this->TetraPoints->GetPoint(4*i+j)); + this->TetraScalars->SetValue(j,cellScalars->GetTuple1(localId)); + } + this->Tetra->Clip(value,this->TetraScalars,locator,tets,inPD,outPD,inCD, + cellId, outCD, insideOut); + } +} + +//---------------------------------------------------------------------------- +int vtkConvexPointSet::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + int i, status, returnStatus=(-1); + double p[3], x[3], dist2, minDist2=VTK_DOUBLE_MAX, pMin[3]; + double closest[3], pc[3]; + double weights[4]; + + // Get the current global coordinate + this->EvaluateLocation(subId, pcoords, p, weights); + + // Find the closest point + vtkIdType numPts = this->PointIds->GetNumberOfIds(); + for (i=0; i < numPts; i++) + { + this->Points->GetPoint(i, x); + dist2 = vtkMath::Distance2BetweenPoints(x,p); + if ( dist2 < minDist2 ) + { + pMin[0] = x[0]; + pMin[1] = x[1]; + pMin[2] = x[2]; + minDist2 = dist2; + } + } + + // Get the faces connected to the point, find the closest face + this->BoundaryTris->Reset(); + this->Triangulator->AddTriangles(this->BoundaryTris); + + vtkIdType npts, *tpts=0; + for ( minDist2=VTK_DOUBLE_MAX, this->BoundaryTris->InitTraversal(); + this->BoundaryTris->GetNextCell(npts,tpts); ) + { + this->Triangle->PointIds->SetId(0,tpts[0]); + this->Triangle->PointIds->SetId(1,tpts[1]); + this->Triangle->PointIds->SetId(2,tpts[2]); + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(tpts[0])); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(tpts[1])); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(tpts[2])); + status = this->Triangle-> + EvaluatePosition(pMin, closest, subId, pc, dist2, weights); + + if ( status != -1 && dist2 < minDist2) + { + returnStatus = 1; + pts->SetNumberOfIds(3); + pts->SetId(0,this->PointIds->GetId(tpts[0])); + pts->SetId(1,this->PointIds->GetId(tpts[1])); + pts->SetId(2,this->PointIds->GetId(tpts[2])); + minDist2 = dist2; + } + } + + return returnStatus; +} + +//---------------------------------------------------------------------------- +int vtkConvexPointSet::EvaluatePosition(double x[3], + double* vtkNotUsed(closestPoint), + int& subId, double pcoords[3], + double& minDist2, double *weights) +{ + double pc[3], dist2; + int ignoreId, i, j, returnStatus=0, status; + double tempWeights[4]; + double closest[3]; + vtkIdType ptId; + int numTets = this->TetraIds->GetNumberOfIds() / 4; + + + for (minDist2=VTK_DOUBLE_MAX, i=0; iPointIds->GetId(this->TetraIds->GetId(4*i+j)); + this->Tetra->PointIds->SetId(j,ptId); + this->Tetra->Points->SetPoint(j,this->TetraPoints->GetPoint(4*i+j)); + } + + status = this->Tetra->EvaluatePosition(x,closest,ignoreId,pc,dist2, + tempWeights); + if ( status != -1 && dist2 < minDist2 ) + { + returnStatus = status; + minDist2 = dist2; + subId = i; + pcoords[0] = pc[0]; + pcoords[1] = pc[1]; + pcoords[2] = pc[2]; + weights[0] = tempWeights[0]; + weights[1] = tempWeights[1]; + weights[2] = tempWeights[2]; + weights[3] = tempWeights[3]; + } + } + + return returnStatus; +} + +//---------------------------------------------------------------------------- +void vtkConvexPointSet::EvaluateLocation(int& subId, double pcoords[3], + double x[3], double *weights) +{ + vtkIdType ptId; + + for (int j=0; j<4; j++) + { + ptId = this->PointIds->GetId(this->TetraIds->GetId(4*subId+j)); + this->Tetra->PointIds->SetId(j,ptId); + this->Tetra->Points->SetPoint(j,this->TetraPoints->GetPoint(4*subId+j)); + } + + this->Tetra->EvaluateLocation(subId, pcoords, x, weights); +} + +//---------------------------------------------------------------------------- +int vtkConvexPointSet::IntersectWithLine(double p1[3], double p2[3], double tol, + double& minT, double x[3], + double pcoords[3], int& subId) +{ + int subTest, i, j; + vtkIdType ptId; + double t, pc[3], xTemp[3]; + + + int numTets = this->TetraIds->GetNumberOfIds() / 4; + int status = 0; + + for (minT=VTK_DOUBLE_MAX, i=0; iPointIds->GetId(this->TetraIds->GetId(4*i+j)); + this->Tetra->PointIds->SetId(j,ptId); + this->Tetra->Points->SetPoint(j,this->TetraPoints->GetPoint(4*i+j)); + } + + if (this->Tetra->IntersectWithLine(p1,p2,tol,t,xTemp,pc,subTest) && + t < minT ) + { + status = 1; + subId = i; + minT = t; + x[0] = xTemp[0]; + x[1] = xTemp[1]; + x[2] = xTemp[2]; + pcoords[0] = pc[0]; + pcoords[1] = pc[1]; + pcoords[2] = pc[2]; + } + } + + return status; +} + +//---------------------------------------------------------------------------- +void vtkConvexPointSet::Derivatives(int subId, double pcoords[3], + double *values, int dim, double *derivs) +{ + vtkIdType ptId; + + for (int j=0; j<4; j++) + { + ptId = this->PointIds->GetId(this->TetraIds->GetId(4*subId+j)); + this->Tetra->PointIds->SetId(j,ptId); + this->Tetra->Points->SetPoint(j,this->TetraPoints->GetPoint(4*subId+j)); + } + + this->Tetra->Derivatives(subId, pcoords, values, dim, derivs); +} + +//---------------------------------------------------------------------------- +double *vtkConvexPointSet::GetParametricCoords() +{ + int numPts = this->PointIds->GetNumberOfIds(); + if ( ! this->ParametricCoords ) + { + this->ParametricCoords = vtkDoubleArray::New(); + } + + this->ParametricCoords->SetNumberOfComponents(3); + this->ParametricCoords->SetNumberOfTuples(numPts); + double p[3], x[3], *bounds = this->GetBounds(); + int i, j; + for (i=0; i < numPts; i++) + { + this->Points->GetPoint(i, x); + for (j=0; j<3; j++) + { + p[j] = (x[j] - bounds[2*j]) / (bounds[2*j+1] - bounds[2*j]); + } + this->ParametricCoords->SetTuple(i,p); + } + + return this->ParametricCoords->GetPointer(0); +} + +//---------------------------------------------------------------------------- +void vtkConvexPointSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Tetra:\n"; + this->Tetra->PrintSelf(os,indent.GetNextIndent()); + os << indent << "TetraIds:\n"; + this->TetraIds->PrintSelf(os,indent.GetNextIndent()); + os << indent << "TetraPoints:\n"; + this->TetraPoints->PrintSelf(os,indent.GetNextIndent()); + os << indent << "TetraScalars:\n"; + this->TetraScalars->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "BoundaryTris:\n"; + this->BoundaryTris->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Triangle:\n"; + this->Triangle->PrintSelf(os,indent.GetNextIndent()); + if ( this->ParametricCoords ) + { + os << indent << "ParametricCoords " << this->ParametricCoords << "\n"; + } + else + { + os << indent << "ParametricCoords: (null)\n"; + } + +} diff --git a/Filtering/vtkConvexPointSet.h b/Filtering/vtkConvexPointSet.h new file mode 100644 index 0000000..c7f6255 --- /dev/null +++ b/Filtering/vtkConvexPointSet.h @@ -0,0 +1,169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkConvexPointSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkConvexPointSet - a 3D cell defined by a set of convex points +// .SECTION Description +// vtkConvexPointSet is a concrete implementation that represents a 3D cell +// defined by a convex set of points. An example of such a cell is an octant +// (from an octree). vtkConvexPointSet uses the ordered triangulations +// approach (vtkOrderedTriangulator) to create triangulations guaranteed to +// be compatible across shared faces. This allows a general approach to +// processing complex, convex cell types. + +// .SECTION See Also +// vtkHexahedron vtkPyramid vtkTetra vtkVoxel vtkWedge + +#ifndef __vtkConvexPointSet_h +#define __vtkConvexPointSet_h + +#include "vtkCell3D.h" + +class vtkUnstructuredGrid; +class vtkCellArray; +class vtkTriangle; +class vtkTetra; +class vtkDoubleArray; + +class VTK_FILTERING_EXPORT vtkConvexPointSet : public vtkCell3D +{ +public: + static vtkConvexPointSet *New(); + vtkTypeRevisionMacro(vtkConvexPointSet,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of this method. + virtual int HasFixedTopology() {return 0;} + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int vtkNotUsed(edgeId), int* &vtkNotUsed(pts)) {} + virtual void GetFacePoints(int vtkNotUsed(faceId), int* &vtkNotUsed(pts)) {} + virtual double *GetParametricCoords(); + + // Description: + // See the vtkCell API for descriptions of these methods. + virtual int GetCellType() {return VTK_CONVEX_POINT_SET;} + + // Description: + // This cell requires that it be initialized prior to access. + virtual int RequiresInitialization() {return 1;} + virtual void Initialize(); + + // Description: + // A convex point set has no explicit cell edge or faces; however + // implicitly (after triangulation) it does. Currently the method + // GetNumberOfEdges() always returns 0 while the GetNumberOfFaces() returns + // the number of boundary triangles of the triangulation of the convex + // point set. The method GetNumberOfFaces() triggers a triangulation of the + // convex point set; repeated calls to GetFace() then return the boundary + // faces. (Note: GetNumberOfEdges() currently returns 0 because it is a + // rarely used method and hard to implement. It can be changed in the future. + virtual int GetNumberOfEdges() {return 0;} + virtual vtkCell *GetEdge(int) {return NULL;} + virtual int GetNumberOfFaces(); + virtual vtkCell *GetFace(int faceId); + + // Description: + // Satisfy the vtkCell API. This method contours by triangulating the + // cell and then contouring the resulting tetrahedra. + virtual void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + + // Description: + // Satisfy the vtkCell API. This method contours by triangulating the + // cell and then adding clip-edge intersection points into the + // triangulation; extracting the clipped region. + virtual void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *connectivity, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Satisfy the vtkCell API. This method determines the subId, pcoords, + // and weights by triangulating the convex point set, and then + // determining which tetrahedron the point lies in. + virtual int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + + // Description: + // The inverse of EvaluatePosition. + virtual void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + + // Description: + // Triangulates the cells and then intersects them to determine the + // intersection point. + virtual int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + // Description: + // Triangulate using methods of vtkOrderedTriangulator. + virtual int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + + // Description: + // Computes derivatives by triangulating and from subId and pcoords, + // evaluating derivatives on the resulting tetrahedron. + virtual void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + + // Description: + // Returns the set of points forming a face of the triangulation of these + // points that are on the boundary of the cell that are closest + // parametrically to the point specified. + virtual int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + + // Description: + // Return the center of the cell in parametric coordinates. + virtual int GetParametricCenter(double pcoords[3]); + + // Description: + // A convex point set is triangulated prior to any operations on it so + // it is not a primary cell, it is a composite cell. + int IsPrimaryCell() {return 0;} + +protected: + vtkConvexPointSet(); + ~vtkConvexPointSet(); + + vtkTetra *Tetra; + vtkIdList *TetraIds; + vtkPoints *TetraPoints; + vtkDoubleArray *TetraScalars; + + vtkCellArray *BoundaryTris; + vtkTriangle *Triangle; + vtkDoubleArray *ParametricCoords; + +private: + vtkConvexPointSet(const vtkConvexPointSet&); // Not implemented. + void operator=(const vtkConvexPointSet&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkConvexPointSet::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = pcoords[2] = 0.5; + return 0; +} + +#endif + + + diff --git a/Filtering/vtkCoordinate.cxx b/Filtering/vtkCoordinate.cxx new file mode 100644 index 0000000..04fad0e --- /dev/null +++ b/Filtering/vtkCoordinate.cxx @@ -0,0 +1,462 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCoordinate.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCoordinate.h" +#include "vtkViewport.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCoordinate, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkCoordinate); + +vtkCxxSetObjectMacro(vtkCoordinate,ReferenceCoordinate,vtkCoordinate); + +#define VTK_RINT(x) ((x > 0.0) ? (int)(x + 0.5) : (int)(x - 0.5)) + +// Creates an Coordinate with the following defaults: +// value of 0, 0, 0 in world coordinates +vtkCoordinate::vtkCoordinate() +{ + this->CoordinateSystem = VTK_WORLD; + this->Value[0] = 0.0; + this->Value[1] = 0.0; + this->Value[2] = 0.0; + this->Viewport = NULL; + this->ReferenceCoordinate = NULL; + this->Computing = 0; +} + +// Destroy a Coordinate. +vtkCoordinate::~vtkCoordinate() +{ + // To get rid of references (Refence counting). + this->SetReferenceCoordinate(NULL); + this->SetViewport(NULL); +} + +const char *vtkCoordinate::GetCoordinateSystemAsString() +{ + switch (this->CoordinateSystem) + { + case VTK_DISPLAY: + return "Display"; + case VTK_NORMALIZED_DISPLAY: + return "Normalized Display"; + case VTK_VIEWPORT: + return "Viewport"; + case VTK_NORMALIZED_VIEWPORT: + return "Normalized Viewport"; + case VTK_VIEW: + return "View"; + case VTK_WORLD: + return "World"; + case VTK_USERDEFINED: + return "User Defined"; + default: + return "UNKNOWN!"; + } +} + +void vtkCoordinate::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + + os << indent << "Coordinate System: " << + this->GetCoordinateSystemAsString() << "\n"; + os << indent << "Value: (" << this->Value[0] << "," + << this->Value[1] << "," << this->Value[2] << ")\n"; + if (this->ReferenceCoordinate) + { + os << indent << "ReferenceCoordinate: " << + this->ReferenceCoordinate << "\n"; + } + else + { + os << indent << "ReferenceCoordinate: (none)\n"; + } + if (this->Viewport) + { + os << indent << "Viewport: " << this->Viewport << "\n"; + } + else + { + os << indent << "Viewport: (none)\n"; + } +} + + +void vtkCoordinate::SetViewport(vtkViewport *viewport) +{ + if (this->Viewport != viewport) + { + if (this->Viewport != NULL) + { + this->Viewport->UnRegister(this); + } + this->Viewport = viewport; + if (this->Viewport != NULL) + { + this->Viewport->Register(this); + } + this->Modified(); + } +} + + +double *vtkCoordinate::GetComputedWorldValue(vtkViewport* viewport) +{ + double *val = this->ComputedWorldValue; + + // prevent infinite loops + if (this->Computing) + { + return val; + } + this->Computing = 1; + + val[0] = this->Value[0]; + val[1] = this->Value[1]; + val[2] = this->Value[2]; + + // use our viewport if set + if (this->Viewport) + { + viewport = this->Viewport; + } + + // if viewport is NULL then we can only do minimal calculations + if (!viewport) + { + if (this->CoordinateSystem == VTK_WORLD) + { + if (this->ReferenceCoordinate) + { + double *RefValue; + RefValue = + this->ReferenceCoordinate->GetComputedWorldValue(viewport); + val[0] += RefValue[0]; + val[1] += RefValue[1]; + val[2] += RefValue[2]; + } + this->Computing = 0; + } + else + { + vtkErrorMacro("Attempt to compute world coordinates from another coordinate system without a viewport"); + } + return val; + } + + if (this->ReferenceCoordinate && this->CoordinateSystem != VTK_WORLD) + { + double RefValue[3]; + double *fval; + + fval = this->ReferenceCoordinate->GetComputedDoubleDisplayValue(viewport); + RefValue[0] = fval[0]; + RefValue[1] = fval[1]; + RefValue[2] = 0.0; + + // convert to current coordinate system + switch (this->CoordinateSystem) + { + case VTK_NORMALIZED_DISPLAY: + viewport->DisplayToNormalizedDisplay(RefValue[0],RefValue[1]); + break; + case VTK_VIEWPORT: + viewport->DisplayToNormalizedDisplay(RefValue[0],RefValue[1]); + viewport->NormalizedDisplayToViewport(RefValue[0],RefValue[1]); + break; + case VTK_NORMALIZED_VIEWPORT: + viewport->DisplayToNormalizedDisplay(RefValue[0],RefValue[1]); + viewport->NormalizedDisplayToViewport(RefValue[0],RefValue[1]); + viewport->ViewportToNormalizedViewport(RefValue[0],RefValue[1]); + break; + case VTK_VIEW: + viewport->DisplayToNormalizedDisplay(RefValue[0],RefValue[1]); + viewport->NormalizedDisplayToViewport(RefValue[0],RefValue[1]); + viewport->ViewportToNormalizedViewport(RefValue[0],RefValue[1]); + viewport->NormalizedViewportToView(RefValue[0], + RefValue[1], + RefValue[2]); + break; + } + + // add to current value + val[0] += RefValue[0]; + val[1] += RefValue[1]; + val[2] += RefValue[2]; + } + + // compute our WC + switch (this->CoordinateSystem) + { + case VTK_DISPLAY: + viewport->DisplayToNormalizedDisplay(val[0],val[1]); + case VTK_NORMALIZED_DISPLAY: + viewport->NormalizedDisplayToViewport(val[0],val[1]); + case VTK_VIEWPORT: + viewport->ViewportToNormalizedViewport(val[0],val[1]); + case VTK_NORMALIZED_VIEWPORT: + viewport->NormalizedViewportToView(val[0],val[1],val[2]); + case VTK_VIEW: + viewport->ViewToWorld(val[0],val[1],val[2]); + } + + if (this->ReferenceCoordinate && this->CoordinateSystem == VTK_WORLD) + { + double *RefValue; + RefValue = this->ReferenceCoordinate->GetComputedWorldValue(viewport); + val[0] += RefValue[0]; + val[1] += RefValue[1]; + val[2] += RefValue[2]; + } + + this->Computing = 0; + vtkDebugMacro("Returning WorldValue of : " << + this->ComputedWorldValue[0] << " , " << + this->ComputedWorldValue[1] << " , " << + this->ComputedWorldValue[2]); + return val; +} + + +double *vtkCoordinate::GetComputedDoubleViewportValue(vtkViewport* viewport) +{ + // use our viewport if set + if (this->Viewport) + { + viewport = this->Viewport; + } + + double *d = this->GetComputedDoubleDisplayValue(viewport); + + if (!viewport) + { + vtkDebugMacro("Attempt to convert to compute viewport coordinates without a viewport, results may not be valid"); + return d; + } + + double f[2]; + f[0] = d[0]; + f[1] = d[1]; + + viewport->DisplayToNormalizedDisplay(f[0],f[1]); + viewport->NormalizedDisplayToViewport(f[0],f[1]); + + this->ComputedDoubleViewportValue[0] = f[0]; + this->ComputedDoubleViewportValue[1] = f[1]; + + return this->ComputedDoubleViewportValue; +} + +int *vtkCoordinate::GetComputedViewportValue(vtkViewport* viewport) +{ + double *f = this->GetComputedDoubleViewportValue(viewport); + + this->ComputedViewportValue[0] = (int)VTK_RINT(f[0]); + this->ComputedViewportValue[1] = (int)VTK_RINT(f[1]); + + return this->ComputedViewportValue; +} + +int *vtkCoordinate::GetComputedLocalDisplayValue(vtkViewport* viewport) +{ + double a[2]; + + // use our viewport if set + if (this->Viewport) + { + viewport = this->Viewport; + } + this->GetComputedDisplayValue(viewport); + + if (!viewport) + { + vtkErrorMacro("Attempt to convert to local display coordinates without a viewport"); + return this->ComputedDisplayValue; + } + + a[0] = (double)this->ComputedDisplayValue[0]; + a[1] = (double)this->ComputedDisplayValue[1]; + + viewport->DisplayToLocalDisplay(a[0],a[1]); + + this->ComputedDisplayValue[0] = (int)VTK_RINT(a[0]); + this->ComputedDisplayValue[1] = (int)VTK_RINT(a[1]); + + vtkDebugMacro("Returning LocalDisplayValue of : " << + this->ComputedDisplayValue[0] << " , " << + this->ComputedDisplayValue[1]); + + return this->ComputedDisplayValue; +} + +double *vtkCoordinate::GetComputedDoubleDisplayValue(vtkViewport* viewport) +{ + double val[3]; + + // prevent infinite loops + if (this->Computing) + { + return this->ComputedDoubleDisplayValue; + } + this->Computing = 1; + + val[0] = this->Value[0]; + val[1] = this->Value[1]; + val[2] = this->Value[2]; + + // use our viewport if set + if (this->Viewport) + { + viewport = this->Viewport; + } + + // if viewport is NULL, there is very little we can do + if (viewport == NULL) + { + // for DISPLAY and VIEWPORT just use the value + if (this->CoordinateSystem == VTK_DISPLAY) + { + this->ComputedDoubleDisplayValue[0] = val[0]; + this->ComputedDoubleDisplayValue[1] = val[1]; + if (this->ReferenceCoordinate) + { + double *RefValue; + RefValue = this->ReferenceCoordinate-> + GetComputedDoubleDisplayValue(viewport); + this->ComputedDoubleDisplayValue[0] += RefValue[0]; + this->ComputedDoubleDisplayValue[1] += RefValue[1]; + } + } + else + { + vtkErrorMacro("Request for coordinate transformation without required viewport"); + } + return this->ComputedDoubleDisplayValue; + } + + // compute our DC + switch (this->CoordinateSystem) + { + case VTK_WORLD: + if (this->ReferenceCoordinate) + { + double *RefValue; + RefValue = this->ReferenceCoordinate->GetComputedWorldValue(viewport); + val[0] += RefValue[0]; + val[1] += RefValue[1]; + val[2] += RefValue[2]; + } + viewport->WorldToView(val[0],val[1],val[2]); + case VTK_VIEW: + viewport->ViewToNormalizedViewport(val[0],val[1],val[2]); + case VTK_NORMALIZED_VIEWPORT: + viewport->NormalizedViewportToViewport(val[0],val[1]); + case VTK_VIEWPORT: + if ((this->CoordinateSystem == VTK_NORMALIZED_VIEWPORT || + this->CoordinateSystem == VTK_VIEWPORT) && + this->ReferenceCoordinate) + { + double *RefValue; + RefValue = this->ReferenceCoordinate-> + GetComputedDoubleViewportValue(viewport); + val[0] += RefValue[0]; + val[1] += RefValue[1]; + } + viewport->ViewportToNormalizedDisplay(val[0],val[1]); + case VTK_NORMALIZED_DISPLAY: + viewport->NormalizedDisplayToDisplay(val[0],val[1]); + break; // do not remove this break statement! + case VTK_USERDEFINED: + this->GetComputedUserDefinedValue(viewport); + val[0] = this->ComputedUserDefinedValue[0]; + val[1] = this->ComputedUserDefinedValue[1]; + val[2] = this->ComputedUserDefinedValue[2]; + break; + } + + // if we have a reference coordinate and we haven't handled it yet + if (this->ReferenceCoordinate && + (this->CoordinateSystem == VTK_DISPLAY || + this->CoordinateSystem == VTK_NORMALIZED_DISPLAY)) + { + double *RefValue; + RefValue = + this->ReferenceCoordinate->GetComputedDoubleDisplayValue(viewport); + val[0] += RefValue[0]; + val[1] += RefValue[1]; + } + this->ComputedDoubleDisplayValue[0] = val[0]; + this->ComputedDoubleDisplayValue[1] = val[1]; + + this->Computing = 0; + return this->ComputedDoubleDisplayValue; +} + + +int *vtkCoordinate::GetComputedDisplayValue(vtkViewport* viewport) +{ + double *val = this->GetComputedDoubleDisplayValue(viewport); + + this->ComputedDisplayValue[0] = (int)(val[0]); + this->ComputedDisplayValue[1] = (int)(val[1]); + + vtkDebugMacro("Returning DisplayValue of : " << + this->ComputedDisplayValue[0] << " , " << + this->ComputedDisplayValue[1]); + return this->ComputedDisplayValue; +} + + + +double *vtkCoordinate::GetComputedValue(vtkViewport* viewport) +{ + // use our viewport if set + if (this->Viewport) + { + viewport = this->Viewport; + } + + switch (this->CoordinateSystem) + { + case VTK_WORLD: + return this->GetComputedWorldValue(viewport); + case VTK_VIEW: + case VTK_NORMALIZED_VIEWPORT: + case VTK_VIEWPORT: + { + // result stored in computed world value due to double + // but is really a viewport value + int *v = this->GetComputedViewportValue(viewport); + this->ComputedWorldValue[0] = v[0]; + this->ComputedWorldValue[1] = v[1]; + break; + } + case VTK_NORMALIZED_DISPLAY: + case VTK_DISPLAY: + { + // result stored in computed world value due to double + // but is really a display value + int *d = this->GetComputedDisplayValue(viewport); + this->ComputedWorldValue[0] = d[0]; + this->ComputedWorldValue[1] = d[1]; + break; + } + } + + return this->ComputedWorldValue; +} + diff --git a/Filtering/vtkCoordinate.h b/Filtering/vtkCoordinate.h new file mode 100644 index 0000000..3e05d0d --- /dev/null +++ b/Filtering/vtkCoordinate.h @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCoordinate.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCoordinate - perform coordinate transformation, and represent position, in a variety of vtk coordinate systems +// .SECTION Description +// vtkCoordinate represents position in a variety of coordinate systems, and +// converts position to other coordinate systems. It also supports relative +// positioning, so you can create a cascade of vtkCoordinate objects (no loops +// please!) that refer to each other. The typical usage of this object is +// to set the coordinate system in which to represent a position (e.g., +// SetCoordinateSystemToNormalizedDisplay()), set the value of the coordinate +// (e.g., SetValue()), and then invoke the appropriate method to convert to +// another coordinate system (e.g., GetComputedWorldValue()). +// +// The coordinate systems in vtk are as follows: +//
+//  DISPLAY -             x-y pixel values in window
+//  NORMALIZED DISPLAY -  x-y (0,1) normalized values
+//  VIEWPORT -            x-y pixel values in viewport
+//  NORMALIZED VIEWPORT - x-y (0,1) normalized value in viewport
+//  VIEW -                x-y-z (-1,1) values in camera coordinates. (z is depth)
+//  WORLD -               x-y-z global coordinate values
+//  USERDEFINED -         x-y-z in User defined space
+//
+// +// If you cascade vtkCoordinate objects, you refer to another vtkCoordinate +// object which in turn can refer to others, and so on. This allows you to +// create composite groups of things like vtkActor2D that are positioned +// relative to one another. Note that in cascaded sequences, each +// vtkCoordinate object may be specified in different coordinate systems! + +// .SECTION See Also +// vtkActor2D vtkScalarBarActor + +#ifndef __vtkCoordinate_h +#define __vtkCoordinate_h + +#include "vtkObject.h" +class vtkViewport; + +#define VTK_DISPLAY 0 +#define VTK_NORMALIZED_DISPLAY 1 +#define VTK_VIEWPORT 2 +#define VTK_NORMALIZED_VIEWPORT 3 +#define VTK_VIEW 4 +#define VTK_WORLD 5 +#define VTK_USERDEFINED 6 + +class VTK_FILTERING_EXPORT vtkCoordinate : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCoordinate,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates an instance of this class with the following defaults: + // value of (0,0,0) in world coordinates. + static vtkCoordinate* New(); + + // Description: + // Set/get the coordinate system which this coordinate + // is defined in. The options are Display, Normalized Display, + // Viewport, Normalized Viewport, View, and World. + vtkSetMacro(CoordinateSystem, int); + vtkGetMacro(CoordinateSystem, int); + void SetCoordinateSystemToDisplay() {this->SetCoordinateSystem(VTK_DISPLAY);} + void SetCoordinateSystemToNormalizedDisplay() + {this->SetCoordinateSystem(VTK_NORMALIZED_DISPLAY);} + void SetCoordinateSystemToViewport() + {this->SetCoordinateSystem(VTK_VIEWPORT);} + void SetCoordinateSystemToNormalizedViewport() + {this->SetCoordinateSystem(VTK_NORMALIZED_VIEWPORT);} + void SetCoordinateSystemToView() {this->SetCoordinateSystem(VTK_VIEW);} + void SetCoordinateSystemToWorld() {this->SetCoordinateSystem(VTK_WORLD);} + + const char *GetCoordinateSystemAsString (); + + // Description: + // Set/get the value of this coordinate. This can be thought of as + // the position of this coordinate in its coordinate system. + vtkSetVector3Macro(Value,double); + vtkGetVector3Macro(Value,double); + void SetValue(double a, double b) { this->SetValue(a,b,0.0);} + + // Description: + // If this coordinate is relative to another coordinate, + // then specify that coordinate as the ReferenceCoordinate. + // If this is NULL the coordinate is assumed to be absolute. + virtual void SetReferenceCoordinate(vtkCoordinate*); + vtkGetObjectMacro(ReferenceCoordinate,vtkCoordinate); + + // Description: + // If you want this coordinate to be relative to a specific + // vtkViewport (vtkRenderer) then you can specify + // that here. + void SetViewport(vtkViewport *viewport); + vtkGetObjectMacro(Viewport,vtkViewport); + + // Description: + // Return the computed value in a specified coordinate system. + double *GetComputedWorldValue(vtkViewport *); + int *GetComputedViewportValue(vtkViewport *); + int *GetComputedDisplayValue(vtkViewport *); + int *GetComputedLocalDisplayValue(vtkViewport *); + + double *GetComputedDoubleViewportValue(vtkViewport *); + double *GetComputedDoubleDisplayValue(vtkViewport *); + + // Description: + // GetComputedValue() will return either World, Viewport or + // Display based on what has been set as the coordinate system. + // This is good for objects like vtkLineSource, where the + // user might want to use them as World or Viewport coordinates + double *GetComputedValue(vtkViewport *); + + // Description: + // GetComputedUserDefinedValue() is to be used only when + // the coordinate system is VTK_USERDEFINED. The user + // must subclass vtkCoordinate and override this function, + // when set as the TransformCoordinate in 2D-Mappers, the user + // can customize display of 2D polygons + virtual double *GetComputedUserDefinedValue(vtkViewport *) + { return this->Value; } + +protected: + vtkCoordinate(); + ~vtkCoordinate(); + + double Value[3]; + int CoordinateSystem; + vtkCoordinate *ReferenceCoordinate; + vtkViewport *Viewport; + double ComputedWorldValue[3]; + int ComputedDisplayValue[2]; + int ComputedViewportValue[2]; + int Computing; + + double ComputedDoubleDisplayValue[2]; + double ComputedDoubleViewportValue[2]; + double ComputedUserDefinedValue[3]; + +private: + vtkCoordinate(const vtkCoordinate&); // Not implemented. + void operator=(const vtkCoordinate&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkCylinder.cxx b/Filtering/vtkCylinder.cxx new file mode 100644 index 0000000..f02bb81 --- /dev/null +++ b/Filtering/vtkCylinder.cxx @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCylinder.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCylinder.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCylinder, "$Revision: 1.27 $"); +vtkStandardNewMacro(vtkCylinder); + +// Construct cylinder radius of 0.5. +vtkCylinder::vtkCylinder() +{ + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + this->Radius = 0.5; +} + +// Evaluate cylinder equation F(x,y,z) = (x-x0)^2 + (z-z0)^2 - R^2. +double vtkCylinder::EvaluateFunction(double xyz[3]) +{ + double x = xyz[0] - this->Center[0]; + double z = xyz[2] - this->Center[2]; + + return ( x * x + z * z - this->Radius*this->Radius ); +} + +// Evaluate cylinder function gradient. +void vtkCylinder::EvaluateGradient(double xyz[3], double g[3]) +{ + double x = xyz[0] - this->Center[0]; + double z = xyz[2] - this->Center[2]; + + g[0] = 2.0 * (x - this->Center[0]); + g[1] = 0.0; + g[2] = 2.0 * (z - this->Center[2]); +} + +void vtkCylinder::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Center: " << "( " << this->Center[0] << ", " << + this->Center[1] << ", " << this->Center[2] << " )"; + + os << indent << "Radius: " << this->Radius << "\n"; +} diff --git a/Filtering/vtkCylinder.h b/Filtering/vtkCylinder.h new file mode 100644 index 0000000..57da1b6 --- /dev/null +++ b/Filtering/vtkCylinder.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCylinder.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCylinder - implicit function for a cylinder +// .SECTION Description +// vtkCylinder computes the implicit function and function gradient for a +// cylinder. vtkCylinder is a concrete implementation of vtkImplicitFunction. +// Cylinder is centered at Center and axes of rotation is along the +// y-axis. (Use the superclass' vtkImplicitFunction transformation matrix if +// necessary to reposition.) + +// .SECTION Caveats +// The cylinder is infinite in extent. To truncate the cylinder use the +// vtkImplicitBoolean in combination with clipping planes. + + +#ifndef __vtkCylinder_h +#define __vtkCylinder_h + +#include "vtkImplicitFunction.h" + +class VTK_FILTERING_EXPORT vtkCylinder : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkCylinder,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct cylinder radius of 0.5. + static vtkCylinder *New(); + + // Description + // Evaluate cylinder equation F(x,y,z) = (x-x0)^2 + (z-z0)^2 - R^2. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate cylinder function gradient. + void EvaluateGradient(double x[3], double g[3]); + + // Description: + // Set/Get cylinder radius. + vtkSetMacro(Radius,double); + vtkGetMacro(Radius,double); + + // Description: + // Set/Get cylinder center + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); +protected: + vtkCylinder(); + ~vtkCylinder() {}; + + double Radius; + double Center[3]; + +private: + vtkCylinder(const vtkCylinder&); // Not implemented. + void operator=(const vtkCylinder&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkDataObject.cxx b/Filtering/vtkDataObject.cxx new file mode 100644 index 0000000..ced0110 --- /dev/null +++ b/Filtering/vtkDataObject.cxx @@ -0,0 +1,1397 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkDataObject.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataObject.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkExtentTranslator.h" +#include "vtkFieldData.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkSource.h" +#include "vtkTrivialProducer.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkInformationDataObjectKey.h" +#include "vtkInformationDoubleKey.h" +#include "vtkInformationDoubleVectorKey.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationIntegerPointerKey.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationInformationVectorKey.h" +#include "vtkInformationStringKey.h" +#include "vtkInformationVector.h" +#include "vtkDataSetAttributes.h" + +vtkCxxRevisionMacro(vtkDataObject, "$Revision: 1.26.4.2 $"); +vtkStandardNewMacro(vtkDataObject); + +vtkCxxSetObjectMacro(vtkDataObject,Information,vtkInformation); +vtkCxxSetObjectMacro(vtkDataObject,FieldData,vtkFieldData); + +vtkInformationKeyMacro(vtkDataObject, DATA_TYPE_NAME, String); +vtkInformationKeyMacro(vtkDataObject, DATA_OBJECT, DataObject); +vtkInformationKeyMacro(vtkDataObject, DATA_EXTENT_TYPE, Integer); +vtkInformationKeyMacro(vtkDataObject, DATA_PIECE_NUMBER, Integer); +vtkInformationKeyMacro(vtkDataObject, DATA_NUMBER_OF_PIECES, Integer); +vtkInformationKeyMacro(vtkDataObject, DATA_NUMBER_OF_GHOST_LEVELS, Integer); +vtkInformationKeyMacro(vtkDataObject, DATA_TIME_INDEX, Integer); +vtkInformationKeyMacro(vtkDataObject, DATA_TIME, Double); +vtkInformationKeyMacro(vtkDataObject, POINT_DATA_VECTOR, InformationVector); +vtkInformationKeyMacro(vtkDataObject, CELL_DATA_VECTOR, InformationVector); +vtkInformationKeyMacro(vtkDataObject, FIELD_ARRAY_TYPE, Integer); +vtkInformationKeyMacro(vtkDataObject, FIELD_ASSOCIATION, Integer); +vtkInformationKeyMacro(vtkDataObject, FIELD_ATTRIBUTE_TYPE, Integer); +vtkInformationKeyMacro(vtkDataObject, FIELD_ACTIVE_ATTRIBUTE, Integer); +vtkInformationKeyMacro(vtkDataObject, FIELD_NAME, String); +vtkInformationKeyMacro(vtkDataObject, FIELD_NUMBER_OF_COMPONENTS, Integer); +vtkInformationKeyMacro(vtkDataObject, FIELD_NUMBER_OF_TUPLES, Integer); +vtkInformationKeyMacro(vtkDataObject, FIELD_OPERATION, Integer); +vtkInformationKeyRestrictedMacro(vtkDataObject, DATA_EXTENT, IntegerPointer, 6); +vtkInformationKeyRestrictedMacro(vtkDataObject, ORIGIN, DoubleVector, 3); +vtkInformationKeyRestrictedMacro(vtkDataObject, SPACING, DoubleVector, 3); + +class vtkDataObjectToSourceFriendship +{ +public: + static void SetOutput(vtkSource* source, int i, vtkDataObject* newData) + { + if(source) + { + // Make sure there is room in the source for this output. + if(i >= source->NumberOfOutputs) + { + source->SetNumberOfOutputs(i+1); + } + + // Update the source's Outputs array. + vtkDataObject* oldData = source->Outputs[i]; + if(newData) + { + newData->Register(source); + } + source->Outputs[i] = newData; + if(oldData) + { + oldData->UnRegister(source); + } + } + } +}; + +// Initialize static member that controls global data release +// after use by filter +static int vtkDataObjectGlobalReleaseDataFlag = 0; + +const char vtkDataObject +::AssociationNames[vtkDataObject::NUMBER_OF_ASSOCIATIONS][55] = +{ + "vtkDataObject::FIELD_ASSOCIATION_POINTS", + "vtkDataObject::FIELD_ASSOCIATION_CELLS", + "vtkDataObject::FIELD_ASSOCIATION_NONE", + "vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS" +}; + +//---------------------------------------------------------------------------- +vtkDataObject::vtkDataObject() +{ + this->Source = NULL; + this->PipelineInformation = 0; + + this->Information = vtkInformation::New(); + this->Information->Register(this); + this->Information->Delete(); + + // We have to assume that if a user is creating the data on their own, + // then they will fill it with valid data. + this->DataReleased = 0; + + this->FieldData = NULL; + vtkFieldData *fd = vtkFieldData::New(); + this->SetFieldData(fd); + fd->Delete(); +} + +//---------------------------------------------------------------------------- +vtkDataObject::~vtkDataObject() +{ + this->SetPipelineInformation(0); + this->SetInformation(0); + this->SetFieldData(NULL); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Source ) + { + os << indent << "Source: " << this->Source << "\n"; + } + else + { + os << indent << "Source: (none)\n"; + } + + if ( this->Information ) + { + os << indent << "Information: " << this->Information << "\n"; + } + else + { + os << indent << "Information: (none)\n"; + } + + os << indent << "Data Released: " + << (this->DataReleased ? "True\n" : "False\n"); + os << indent << "Global Release Data: " + << (vtkDataObjectGlobalReleaseDataFlag ? "On\n" : "Off\n"); + + os << indent << "UpdateTime: " << this->UpdateTime << endl; + + if(vtkInformation* pInfo = this->GetPipelineInformation()) + { + os << indent << "Release Data: " + << (this->GetReleaseDataFlag() ? "On\n" : "Off\n"); + if(pInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED())) + { + os << indent << "UpdateExtent: Initialized\n"; + } + else + { + os << indent << "UpdateExtent: Not Initialized\n"; + } + if(pInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT())) + { + int updateExtent[6] = {0,-1,0,-1,0,-1}; + this->GetUpdateExtent(updateExtent); + os << indent << "UpdateExtent: " << updateExtent[0] << ", " + << updateExtent[1] << ", " << updateExtent[2] << ", " + << updateExtent[3] << ", " << updateExtent[4] << ", " + << updateExtent[5] << endl; + } + if(pInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())) + { + os << indent << "Update Number Of Pieces: " + << pInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()) + << endl; + } + if(pInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())) + { + os << indent << "Update Piece: " + << pInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) + << endl; + } + if(pInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())) + { + os << indent << "Update Ghost Level: " + << pInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()) + << endl; + } + if(pInfo->Has(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())) + { + int wholeExtent[6] = {0,-1,0,-1,0,-1}; + this->GetWholeExtent(wholeExtent); + os << indent << "WholeExtent: " << wholeExtent[0] << ", " + << wholeExtent[1] << ", " << wholeExtent[2] << ", " + << wholeExtent[3] << ", " << wholeExtent[4] << ", " + << wholeExtent[5] << endl; + } + if(pInfo->Has(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES())) + { + os << indent << "MaximumNumberOfPieces: " + << pInfo->Get(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES()) + << endl; + } + if(pInfo->Has(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())) + { + os << indent << "ExtentTranslator: (" + << pInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR()) + << ")\n"; + } + if(pInfo->Get(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT())) + { + os << indent << "RequestExactExtent: On\n "; + } + else + { + os << indent << "RequestExactExtent: Off\n "; + } + } + + os << indent << "Field Data:\n"; + this->FieldData->PrintSelf(os,indent.GetNextIndent()); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetUpdateExtent(int piece, int numPieces, int ghostLevel) +{ + if(SDDP* sddp = this->TrySDDP("SetUpdateExtent")) + { + // this code used to check the return value of the + // SetUpdateExtent method which would indicate if the + // UpdatePiece, UpdateNumberOfPieces, or UpdateGhostLevel + // had changed, and call Modified(). We actually don't want + // to do this - just a change in the update extent does not + // make this object modified! + sddp->SetUpdateExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), piece, numPieces, ghostLevel); + } +} + + +//---------------------------------------------------------------------------- +void vtkDataObject::SetPipelineInformation(vtkInformation* newInfo) +{ + vtkInformation* oldInfo = this->PipelineInformation; + if(newInfo != oldInfo) + { + // Remove any existing compatibility link to a source. + this->Source = 0; + + if(newInfo) + { + // Reference the new information. + newInfo->Register(this); + + // Detach the output that used to be held by the new information. + if(vtkDataObject* oldData = newInfo->Get(vtkDataObject::DATA_OBJECT())) + { + oldData->Register(this); + oldData->SetPipelineInformation(0); + oldData->UnRegister(this); + } + + // Tell the new information about this object. + newInfo->Set(vtkDataObject::DATA_OBJECT(), this); + + // If the new producer is a vtkSource then setup the backward + // compatibility link. + vtkExecutive* newExec = newInfo->GetExecutive(vtkExecutive::PRODUCER()); + int newPort = newInfo->GetPort(vtkExecutive::PRODUCER()); + if(newExec) + { + vtkSource* newSource = vtkSource::SafeDownCast(newExec->GetAlgorithm()); + if(newSource) + { + vtkDataObjectToSourceFriendship::SetOutput(newSource, newPort, this); + this->Source = newSource; + } + } + } + + // Save the pointer to the new information. + this->PipelineInformation = newInfo; + + if(oldInfo) + { + // If the old producer was a vtkSource then remove the backward + // compatibility link. + vtkExecutive* oldExec = oldInfo->GetExecutive(vtkExecutive::PRODUCER()); + int oldPort = oldInfo->GetPort(vtkExecutive::PRODUCER()); + if(oldExec) + { + vtkSource* oldSource = vtkSource::SafeDownCast(oldExec->GetAlgorithm()); + if(oldSource) + { + vtkDataObjectToSourceFriendship::SetOutput(oldSource, oldPort, 0); + } + } + + // Remove the old information's reference to us. + oldInfo->Set(vtkDataObject::DATA_OBJECT(), 0); + + // Remove our reference to the old information. + oldInfo->UnRegister(this); + } + } +} + +//---------------------------------------------------------------------------- +vtkAlgorithmOutput* vtkDataObject::GetProducerPort() +{ + // Make sure there is an executive. + if(!this->GetExecutive()) + { + vtkTrivialProducer* tp = vtkTrivialProducer::New(); + tp->SetOutput(this); + tp->Delete(); + } + + // Get the port from the executive. + return this->GetExecutive()->GetProducerPort(this); +} + +//---------------------------------------------------------------------------- +// Determine the modified time of this object +unsigned long int vtkDataObject::GetMTime() +{ + unsigned long result; + + result = vtkObject::GetMTime(); + if ( this->FieldData ) + { + unsigned long mtime = this->FieldData->GetMTime(); + result = ( mtime > result ? mtime : result); + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::Initialize() +{ + this->FieldData->Initialize(); + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetGlobalReleaseDataFlag(int val) +{ + if (val == vtkDataObjectGlobalReleaseDataFlag) + { + return; + } + vtkDataObjectGlobalReleaseDataFlag = val; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::CopyInformationToPipeline(vtkInformation *request, + vtkInformation *input) +{ + // Set default pipeline information during a request for information. + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + // Copy point and cell data from the input if available. Otherwise use our + // current settings. + vtkInformation* output = this->PipelineInformation; + + if (input) + { + // copy point data. + if (input->Has(POINT_DATA_VECTOR())) + { + output->CopyEntry(input, POINT_DATA_VECTOR(), 1); + } + // copy cell data. + if (input && input->Has(CELL_DATA_VECTOR())) + { + output->CopyEntry(input, CELL_DATA_VECTOR(), 1); + } + // copy the actual time + if (input->Has(DATA_TIME())) + { + output->CopyEntry(input, DATA_TIME()); + } + // copy the time index + if (input->Has(DATA_TIME_INDEX())) + { + output->CopyEntry(input, DATA_TIME_INDEX()); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::CopyInformationFromPipeline(vtkInformation*) +{ + // Copy nothing by default. +} + +//---------------------------------------------------------------------------- +vtkInformation *vtkDataObject::GetActiveFieldInformation(vtkInformation *info, + int fieldAssociation, int attributeType) +{ + int i; + vtkInformation *fieldDataInfo; + vtkInformationVector *fieldDataInfoVector; + + if (fieldAssociation == FIELD_ASSOCIATION_POINTS) + { + fieldDataInfoVector = info->Get(POINT_DATA_VECTOR()); + } + else if (fieldAssociation == FIELD_ASSOCIATION_CELLS) + { + fieldDataInfoVector = info->Get(CELL_DATA_VECTOR()); + } + else + { + vtkGenericWarningMacro("Unrecognized field association!"); + return NULL; + } + + if (!fieldDataInfoVector) + { + return NULL; + } + + for (i = 0; i < fieldDataInfoVector->GetNumberOfInformationObjects(); i++) + { + fieldDataInfo = fieldDataInfoVector->GetInformationObject(i); + if ( fieldDataInfo->Has(FIELD_ACTIVE_ATTRIBUTE()) && + (fieldDataInfo->Get(FIELD_ACTIVE_ATTRIBUTE()) & (1 << attributeType )) ) + { + return fieldDataInfo; + } + } + return NULL; +} + +//---------------------------------------------------------------------------- +vtkInformation *vtkDataObject::GetNamedFieldInformation(vtkInformation *info, + int fieldAssociation, + const char *name) +{ + int i; + vtkInformation *fieldDataInfo; + vtkInformationVector *fieldDataInfoVector; + + if (fieldAssociation == FIELD_ASSOCIATION_POINTS) + { + fieldDataInfoVector = info->Get(POINT_DATA_VECTOR()); + } + else if (fieldAssociation == FIELD_ASSOCIATION_CELLS) + { + fieldDataInfoVector = info->Get(CELL_DATA_VECTOR()); + } + else + { + vtkGenericWarningMacro("Unrecognized field association!"); + return NULL; + } + + if (!fieldDataInfoVector) + { + return NULL; + } + + for (i = 0; i < fieldDataInfoVector->GetNumberOfInformationObjects(); i++) + { + fieldDataInfo = fieldDataInfoVector->GetInformationObject(i); + if ( fieldDataInfo->Has(FIELD_NAME()) && + !strcmp(fieldDataInfo->Get(FIELD_NAME()),name)) + { + return fieldDataInfo; + } + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::RemoveNamedFieldInformation(vtkInformation *info, + int fieldAssociation, + const char *name) +{ + int i; + vtkInformation *fieldDataInfo; + vtkInformationVector *fieldDataInfoVector; + + if (fieldAssociation == FIELD_ASSOCIATION_POINTS) + { + fieldDataInfoVector = info->Get(POINT_DATA_VECTOR()); + } + else if (fieldAssociation == FIELD_ASSOCIATION_CELLS) + { + fieldDataInfoVector = info->Get(CELL_DATA_VECTOR()); + } + else + { + vtkGenericWarningMacro("Unrecognized field association!"); + return; + } + + if (!fieldDataInfoVector) + { + return; + } + + for (i = 0; i < fieldDataInfoVector->GetNumberOfInformationObjects(); i++) + { + fieldDataInfo = fieldDataInfoVector->GetInformationObject(i); + if ( fieldDataInfo->Has(FIELD_NAME()) && + !strcmp(fieldDataInfo->Get(FIELD_NAME()),name)) + { + fieldDataInfoVector->Remove(fieldDataInfo); + return; + } + } + return; +} + +//---------------------------------------------------------------------------- +vtkInformation *vtkDataObject::SetActiveAttribute(vtkInformation *info, + int fieldAssociation, + const char *attributeName, + int attributeType) +{ + int i; + vtkInformation *fieldDataInfo; + vtkInformationVector *fieldDataInfoVector; + + if (fieldAssociation == FIELD_ASSOCIATION_POINTS) + { + fieldDataInfoVector = info->Get(POINT_DATA_VECTOR()); + } + else if (fieldAssociation == FIELD_ASSOCIATION_CELLS) + { + fieldDataInfoVector = info->Get(CELL_DATA_VECTOR()); + } + else + { + vtkGenericWarningMacro("Unrecognized field association!"); + return NULL; + } + if (!fieldDataInfoVector) + { + fieldDataInfoVector = vtkInformationVector::New(); + if (fieldAssociation == FIELD_ASSOCIATION_POINTS) + { + info->Set(POINT_DATA_VECTOR(), fieldDataInfoVector); + } + else // (fieldAssociation == FIELD_ASSOCIATION_CELLS) + { + info->Set(CELL_DATA_VECTOR(), fieldDataInfoVector); + } + fieldDataInfoVector->Delete(); + } + + // if we find a matching field, turn it on (active); if another field of same + // attribute type was active, turn it off (not active) + vtkInformation *activeField = NULL; + int activeAttribute; + const char *fieldName; + for (i = 0; i < fieldDataInfoVector->GetNumberOfInformationObjects(); i++) + { + fieldDataInfo = fieldDataInfoVector->GetInformationObject(i); + activeAttribute = fieldDataInfo->Get( FIELD_ACTIVE_ATTRIBUTE() ); + fieldName = fieldDataInfo->Get(FIELD_NAME()); + // if names match (or both empty... no field name), then set active + if ( (attributeName && fieldName && !strcmp(attributeName, fieldName)) || + (!attributeName && !fieldName) ) + { + activeAttribute |= 1 << attributeType; + fieldDataInfo->Set( FIELD_ACTIVE_ATTRIBUTE(), activeAttribute ); + activeField = fieldDataInfo; + } + else if ( activeAttribute & (1 << attributeType) ) + { + activeAttribute &= ~(1 << attributeType); + fieldDataInfo->Set( FIELD_ACTIVE_ATTRIBUTE(), activeAttribute ); + } + } + + // if we didn't find a matching field, create one + if (!activeField) + { + activeField = vtkInformation::New(); + activeField->Set( FIELD_ACTIVE_ATTRIBUTE(), 1 << attributeType); + activeField->Set(FIELD_ASSOCIATION(), fieldAssociation); + if (attributeName) + { + activeField->Set( FIELD_NAME(), attributeName ); + } + fieldDataInfoVector->Append(activeField); + activeField->Delete(); + } + + return activeField; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetActiveAttributeInfo(vtkInformation *info, + int fieldAssociation, + int attributeType, + const char *name, + int arrayType, + int numComponents, + int numTuples) +{ + vtkInformation *attrInfo = vtkDataObject::GetActiveFieldInformation(info, + fieldAssociation, attributeType); + if (!attrInfo) + { + // create an entry and set it as active + attrInfo = SetActiveAttribute(info, fieldAssociation, name, attributeType); + } + + if (name) + { + attrInfo->Set(FIELD_NAME(), name); + } + + // Set the scalar type if it was given. If it was not given and + // there is no current scalar type set the default to VTK_DOUBLE. + if (arrayType != -1) + { + attrInfo->Set(FIELD_ARRAY_TYPE(), arrayType); + } + else if(!attrInfo->Has(FIELD_ARRAY_TYPE())) + { + attrInfo->Set(FIELD_ARRAY_TYPE(), VTK_DOUBLE); + } + + // Set the number of components if it was given. If it was not + // given and there is no current number of components set the + // default to 1. + if (numComponents != -1) + { + attrInfo->Set(FIELD_NUMBER_OF_COMPONENTS(), numComponents); + } + else if(!attrInfo->Has(FIELD_NUMBER_OF_COMPONENTS())) + { + attrInfo->Set(FIELD_NUMBER_OF_COMPONENTS(), 1); + } + + if (numTuples != -1) + { + attrInfo->Set(FIELD_NUMBER_OF_TUPLES(), numTuples); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetPointDataActiveScalarInfo(vtkInformation *info, + int arrayType, int numComponents) + { + vtkDataObject::SetActiveAttributeInfo(info, FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS, NULL, arrayType, numComponents, -1); + } + +//---------------------------------------------------------------------------- +void vtkDataObject::DataHasBeenGenerated() +{ + this->DataReleased = 0; + this->UpdateTime.Modified(); + + // This is here so that the data can be easlily marked as up to date. + // It is used specifically when the filter vtkQuadricClustering + // is executed manually with the append methods. + this->Information->Set(DATA_PIECE_NUMBER(), this->GetUpdatePiece()); + this->Information->Set(DATA_NUMBER_OF_PIECES(), this->GetUpdateNumberOfPieces()); + this->Information->Set(DATA_NUMBER_OF_GHOST_LEVELS(), this->GetUpdateGhostLevel()); +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetGlobalReleaseDataFlag() +{ + return vtkDataObjectGlobalReleaseDataFlag; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::ReleaseData() +{ + this->Initialize(); + this->DataReleased = 1; +} + +//---------------------------------------------------------------------------- +int vtkDataObject::ShouldIReleaseData() +{ + return vtkDataObjectGlobalReleaseDataFlag || this->GetReleaseDataFlag(); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetSource(vtkSource* newSource) +{ + vtkDebugMacro( << this->GetClassName() << " (" + << this << "): setting Source to " << newSource ); + if(newSource) + { + // Find the output index on the source producing this data object. + int index = newSource->GetOutputIndex(this); + if(index >= 0) + { + newSource->GetExecutive()->SetOutputData(index, this); + } + else + { + vtkErrorMacro("SetSource cannot find the output index of this " + "data object from the source."); + this->SetPipelineInformation(0); + } + } + else + { + this->SetPipelineInformation(0); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +unsigned long vtkDataObject::GetUpdateTime() +{ + return this->UpdateTime.GetMTime(); +} + +unsigned long vtkDataObject::GetEstimatedMemorySize() +{ + // This should be implemented in a subclass. If not, default to + // estimating that no memory is used. + return 0; +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkDataObject::GetExecutive() +{ + if(this->PipelineInformation) + { + return this->PipelineInformation->GetExecutive(vtkExecutive::PRODUCER()); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetPortNumber() +{ + if(this->PipelineInformation) + { + return this->PipelineInformation->GetPort(vtkExecutive::PRODUCER()); + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkStreamingDemandDrivenPipeline* vtkDataObject::TrySDDP(const char* method) +{ + // Make sure there is an executive. + if(!this->GetExecutive()) + { + vtkTrivialProducer* tp = vtkTrivialProducer::New(); + tp->SetOutput(this); + tp->Delete(); + } + + // Try downcasting the executive to the proper type. + if(SDDP* sddp = SDDP::SafeDownCast(this->GetExecutive())) + { + return sddp; + } + else if(method) + { + vtkErrorMacro("Method " << method << " cannot be called unless the " + "data object is managed by a " + "vtkStreamingDemandDrivenPipeline."); + } + return 0; +} + +//---------------------------------------------------------------------------- + +unsigned long vtkDataObject::GetActualMemorySize() +{ + return this->FieldData->GetActualMemorySize(); +} + +//---------------------------------------------------------------------------- + +void vtkDataObject::CopyInformation( vtkDataObject *data ) +{ + if ( this->GetExtentType() == VTK_3D_EXTENT && + data->GetExtentType() == VTK_3D_EXTENT ) + { + this->SetWholeExtent(data->GetWholeExtent()); + } + else + { + this->SetMaximumNumberOfPieces(data->GetMaximumNumberOfPieces()); + } + this->SetExtentTranslator(data->GetExtentTranslator()); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::ShallowCopy(vtkDataObject *src) +{ + if (!src) + { + vtkWarningMacro("Attempted to ShallowCopy from null."); + return; + } + + this->InternalDataObjectCopy(src); + + if (!src->FieldData) + { + this->SetFieldData(0); + } + else + { + if (this->FieldData) + { + this->FieldData->ShallowCopy(src->FieldData); + } + else + { + vtkFieldData* fd = vtkFieldData::New(); + fd->ShallowCopy(src->FieldData); + this->SetFieldData(fd); + fd->Delete(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::DeepCopy(vtkDataObject *src) +{ + vtkFieldData *srcFieldData = src->GetFieldData(); + + this->InternalDataObjectCopy(src); + + if (srcFieldData) + { + vtkFieldData *newFieldData = vtkFieldData::New(); + newFieldData->DeepCopy(srcFieldData); + this->SetFieldData(newFieldData); + newFieldData->Delete(); + } + else + { + this->SetFieldData(NULL); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::InternalDataObjectCopy(vtkDataObject *src) +{ + // If the input data object has pipeline information and this object + // does not, setup a trivial producer so that this object will have + // pipeline information into which to copy values. + if(src->GetPipelineInformation() && !this->GetPipelineInformation()) + { + this->GetProducerPort(); + } + + this->DataReleased = src->DataReleased; + if(src->Information->Has(DATA_PIECE_NUMBER())) + { + this->Information->Set(DATA_PIECE_NUMBER(), + src->Information->Get(DATA_PIECE_NUMBER())); + } + if(src->Information->Has(DATA_NUMBER_OF_PIECES())) + { + this->Information->Set(DATA_NUMBER_OF_PIECES(), + src->Information->Get(DATA_NUMBER_OF_PIECES())); + } + if(src->Information->Has(DATA_NUMBER_OF_GHOST_LEVELS())) + { + this->Information->Set(DATA_NUMBER_OF_GHOST_LEVELS(), + src->Information->Get(DATA_NUMBER_OF_GHOST_LEVELS())); + } + vtkInformation* thatPInfo = src->GetPipelineInformation(); + vtkInformation* thisPInfo = this->GetPipelineInformation(); + if(thisPInfo && thatPInfo) + { + // copy the pipeline info if it is available + if(thisPInfo) + { + // Do not override info if it exists. Normally WHOLE_EXTENT + // and MAXIMUM_NUMBER_OF_PIECES should not be copied here since + // they belong to the pipeline not the data object. + // However, removing the copy can break things in older filters + // that rely on ShallowCopy to set these (mostly, sources/filters + // that use another source/filter internally and shallow copy + // in RequestInformation). As a compromise, I changed the following + // code such that these entries are only copied if they do not + // exist in the output. + if (!thisPInfo->Has(SDDP::WHOLE_EXTENT())) + { + thisPInfo->CopyEntry(thatPInfo, SDDP::WHOLE_EXTENT()); + } + if (!thisPInfo->Has(SDDP::MAXIMUM_NUMBER_OF_PIECES())) + { + thisPInfo->CopyEntry(thatPInfo, SDDP::MAXIMUM_NUMBER_OF_PIECES()); + } + thisPInfo->CopyEntry(thatPInfo, vtkDemandDrivenPipeline::RELEASE_DATA()); + } + } + // This also caused a pipeline problem. + // An input pipelineMTime was copied to output. Pipeline did not execute... + // We do not copy MTime of object, so why should we copy these. + //this->PipelineMTime = src->PipelineMTime; + //this->UpdateTime = src->UpdateTime; + //this->Locality = src->Locality; +} + +//---------------------------------------------------------------------------- +// This should be a pure virutal method. +void vtkDataObject::Crop() +{ +} + +//---------------------------------------------------------------------------- +void vtkDataObject::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->Information, "Information"); + vtkGarbageCollectorReport(collector, this->PipelineInformation, + "PipelineInformation"); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::Update() +{ + if(SDDP* sddp = this->TrySDDP("Update")) + { + sddp->Update(this->GetPortNumber()); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::UpdateInformation() +{ + if(SDDP* sddp = this->TrySDDP("UpdateInformation")) + { + sddp->UpdateInformation(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::PropagateUpdateExtent() +{ + if(SDDP* sddp = this->TrySDDP("PropagateUpdateExtent")) + { + sddp->PropagateUpdateExtent(this->GetPortNumber()); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::TriggerAsynchronousUpdate() +{ +} + +//---------------------------------------------------------------------------- +void vtkDataObject::UpdateData() +{ + if(SDDP* sddp = this->TrySDDP("UpdateData")) + { + sddp->UpdateData(this->GetPortNumber()); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetUpdateExtentToWholeExtent() +{ + if(SDDP* sddp = this->TrySDDP("SetUpdateExtentToWholeExtent")) + { + // this code used to check the return value of the + // SetUpdateExtentToWholeExtent method which would + // indicate if the update extent had changed, and call + // Modified(). We actually don't want to do this - just + // a change in the update extent does not make this object + // modified! + sddp->SetUpdateExtentToWholeExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetMaximumNumberOfPieces(int n) +{ + if(SDDP* sddp = this->TrySDDP("SetMaximumNumberOfPieces")) + { + if(sddp->SetMaximumNumberOfPieces + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), n)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetMaximumNumberOfPieces() +{ + if(SDDP* sddp = this->TrySDDP("GetMaximumNumberOfPieces")) + { + return sddp->GetMaximumNumberOfPieces + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } + return -1; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetWholeExtent(int x0, int x1, int y0, int y1, + int z0, int z1) +{ + int extent[6] = {x0, x1, y0, y1, z0, z1}; + this->SetWholeExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetWholeExtent(int extent[6]) +{ + if(SDDP* sddp = this->TrySDDP("SetWholeExtent")) + { + if(sddp->SetWholeExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), extent)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +int* vtkDataObject::GetWholeExtent() +{ + if(SDDP* sddp = this->TrySDDP("GetWholeExtent")) + { + return sddp->GetWholeExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } + else + { + static int extent[6] = {0,-1,0,-1,0,-1}; + return extent; + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::GetWholeExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1) +{ + int extent[6]; + this->GetWholeExtent(extent); + x0 = extent[0]; + x1 = extent[1]; + y0 = extent[2]; + y1 = extent[3]; + z0 = extent[4]; + z1 = extent[5]; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::GetWholeExtent(int extent[6]) +{ + if(SDDP* sddp = this->TrySDDP("GetWholeExtent")) + { + sddp->GetWholeExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), extent); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetWholeBoundingBox(double x0, double x1, double y0, + double y1, double z0, double z1) +{ + double bb[6] = {x0, x1, y0, y1, z0, z1}; + this->SetWholeBoundingBox(bb); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetWholeBoundingBox(double bb[6]) +{ + if(SDDP* sddp = this->TrySDDP("SetWholeBoundingBox")) + { + if(sddp->SetWholeBoundingBox(this->GetPortNumber(), bb)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +double* vtkDataObject::GetWholeBoundingBox() +{ + if(SDDP* sddp = this->TrySDDP("GetWholeBoundingBox")) + { + return sddp->GetWholeBoundingBox(this->GetPortNumber()); + } + else + { + static double bb[6] = {0,-1,0,-1,0,-1}; + return bb; + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::GetWholeBoundingBox(double& x0, double& x1, double& y0, + double& y1, double& z0, double& z1) +{ + double extent[6]; + this->GetWholeBoundingBox(extent); + x0 = extent[0]; + x1 = extent[1]; + y0 = extent[2]; + y1 = extent[3]; + z0 = extent[4]; + z1 = extent[5]; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::GetWholeBoundingBox(double extent[6]) +{ + if(SDDP* sddp = this->TrySDDP("GetWholeBoundingBox")) + { + sddp->GetWholeBoundingBox(this->GetPortNumber(), extent); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetUpdateExtent(int x0, int x1, int y0, int y1, + int z0, int z1) +{ + int extent[6] = {x0, x1, y0, y1, z0, z1}; + this->SetUpdateExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetUpdateExtent(int extent[6]) +{ + if(SDDP* sddp = this->TrySDDP("SetUpdateExtent")) + { + // this code used to check the return value of the + // SetUpdateExtent method which would indicate if the + // update extent had changed, and call Modified(). We + // actually don't want to do this - just a change in + // the update extent does not make this object modified! + sddp->SetUpdateExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), extent); + } +} + +//---------------------------------------------------------------------------- +int* vtkDataObject::GetUpdateExtent() +{ + if(SDDP* sddp = this->TrySDDP("GetUpdateExtent")) + { + return sddp->GetUpdateExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } + else + { + static int extent[6] = {0,-1,0,-1,0,-1}; + return extent; + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::GetUpdateExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1) +{ + int extent[6]; + this->GetUpdateExtent(extent); + x0 = extent[0]; + x1 = extent[1]; + y0 = extent[2]; + y1 = extent[3]; + z0 = extent[4]; + z1 = extent[5]; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::GetUpdateExtent(int extent[6]) +{ + if(SDDP* sddp = this->TrySDDP("GetUpdateExtent")) + { + sddp->GetUpdateExtent + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), extent); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetUpdatePiece(int piece) +{ + if(SDDP* sddp = this->TrySDDP("SetUpdatePiece")) + { + if(sddp->SetUpdatePiece + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), piece)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetUpdatePiece() +{ + if(SDDP* sddp = this->TrySDDP("GetUpdatePiece")) + { + return sddp->GetUpdatePiece + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetUpdateNumberOfPieces(int n) +{ + if(SDDP* sddp = this->TrySDDP("SetUpdateNumberOfPieces")) + { + if(sddp->SetUpdateNumberOfPieces + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), n)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetUpdateNumberOfPieces() +{ + if(SDDP* sddp = this->TrySDDP("GetUpdateNumberOfPieces")) + { + return sddp->GetUpdateNumberOfPieces + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetUpdateGhostLevel(int level) +{ + if(SDDP* sddp = this->TrySDDP("SetUpdateGhostLevel")) + { + if(sddp->SetUpdateGhostLevel + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), level)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetUpdateGhostLevel() +{ + if(SDDP* sddp = this->TrySDDP("GetUpdateGhostLevel")) + { + return sddp->GetUpdateGhostLevel + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetExtentTranslator(vtkExtentTranslator* translator) +{ + if(SDDP* sddp = this->TrySDDP("SetExtentTranslator")) + { + if(sddp->SetExtentTranslator + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber()), translator)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +vtkExtentTranslator* vtkDataObject::GetExtentTranslator() +{ + if(SDDP* sddp = this->TrySDDP("GetExtentTranslator")) + { + return sddp->GetExtentTranslator + (sddp->GetOutputInformation()->GetInformationObject + (this->GetPortNumber())); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetReleaseDataFlag(int value) +{ + if(SDDP* sddp = this->TrySDDP("SetReleaseDataFlag")) + { + if(sddp->SetReleaseDataFlag(this->GetPortNumber(), value)) + { + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetReleaseDataFlag() +{ + if(SDDP* sddp = this->TrySDDP("GetReleaseDataFlag")) + { + return sddp->GetReleaseDataFlag(this->GetPortNumber()); + } + return 0; +} + +//---------------------------------------------------------------------------- +unsigned long vtkDataObject::GetPipelineMTime() +{ + if(SDDP* sddp = this->TrySDDP("GetPipelineMTime")) + { + return sddp->GetPipelineMTime(); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkDataObject::SetRequestExactExtent(int flag) +{ + if(SDDP* sddp = this->TrySDDP("SetRequestExactExtent")) + { + sddp->SetRequestExactExtent(this->GetPortNumber(), flag); + } +} + +//---------------------------------------------------------------------------- +int vtkDataObject::GetRequestExactExtent() +{ + if(SDDP* sddp = this->TrySDDP("GetRequestExactExtent")) + { + return sddp->GetRequestExactExtent(this->GetPortNumber()); + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataObject::GetData(vtkInformation* info) +{ + return info? info->Get(DATA_OBJECT()) : 0; +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataObject::GetData(vtkInformationVector* v, int i) +{ + return vtkDataObject::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +const char* vtkDataObject::GetAssociationTypeAsString(int associationType) +{ + if (associationType < 0 || associationType >= NUMBER_OF_ASSOCIATIONS) + { + vtkGenericWarningMacro("Bad association type."); + return NULL; + } + return vtkDataObject::AssociationNames[associationType]; +} diff --git a/Filtering/vtkDataObject.h b/Filtering/vtkDataObject.h new file mode 100644 index 0000000..8f327e8 --- /dev/null +++ b/Filtering/vtkDataObject.h @@ -0,0 +1,518 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObject.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataObject - general representation of visualization data +// .SECTION Description +// vtkDataObject is an general representation of visualization data. It serves +// to encapsulate instance variables and methods for visualization network +// execution, as well as representing data consisting of a field (i.e., just +// an unstructured pile of data). This is to be compared with a vtkDataSet, +// which is data with geometric and/or topological structure. +// +// vtkDataObjects are used to represent arbitrary repositories of data via the +// vtkFieldData instance variable. These data must be eventually mapped into a +// concrete subclass of vtkDataSet before they can actually be displayed. +// +// .SECTION See Also +// vtkDataSet vtkFieldData vtkDataObjectSource vtkDataObjectFilter +// vtkDataObjectMapper vtkDataObjectToDataSet +// vtkFieldDataToAttributeDataFilter + +#ifndef __vtkDataObject_h +#define __vtkDataObject_h + +#include "vtkObject.h" + +class vtkAlgorithmOutput; +class vtkExecutive; +class vtkFieldData; +class vtkInformation; +class vtkProcessObject; +class vtkSource; +class vtkStreamingDemandDrivenPipelineToDataObjectFriendship; +class vtkExtentTranslator; +class vtkInformationDataObjectKey; +class vtkInformationDoubleKey; +class vtkInformationDoubleVectorKey; +class vtkInformationIntegerKey; +class vtkInformationIntegerPointerKey; +class vtkInformationIntegerVectorKey; +class vtkInformationStringKey; +class vtkInformationVector; +class vtkStreamingDemandDrivenPipeline; +class vtkInformationInformationVectorKey; + +#define VTK_PIECES_EXTENT 0 +#define VTK_3D_EXTENT 1 + +class VTK_FILTERING_EXPORT vtkDataObject : public vtkObject +{ +public: + static vtkDataObject *New(); + + vtkTypeRevisionMacro(vtkDataObject,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the source object creating this data object. + vtkGetObjectMacro(Source,vtkSource); + void SetSource(vtkSource *s); + + // Description: + // Set/Get the information object associated with this data object. + vtkGetObjectMacro(Information, vtkInformation); + virtual void SetInformation(vtkInformation*); + + // Description: + // Get/Set the pipeline information object that owns this data + // object. + vtkGetObjectMacro(PipelineInformation, vtkInformation); + virtual void SetPipelineInformation(vtkInformation*); + + // Description: + // Get the port currently producing this object. + virtual vtkAlgorithmOutput* GetProducerPort(); + + // Description: + // Data objects are composite objects and need to check each part for MTime. + // The information object also needs to be considered. + unsigned long int GetMTime(); + + // Description: + // Restore data object to initial state, + virtual void Initialize(); + + // Description: + // Release data back to system to conserve memory resource. Used during + // visualization network execution. Releasing this data does not make + // down-stream data invalid, so it does not modify the MTime of this + // data object. + void ReleaseData(); + + // Description: + // Return flag indicating whether data should be released after use + // by a filter. + int ShouldIReleaseData(); + + // Description: + // Get the flag indicating the data has been released. + vtkGetMacro(DataReleased,int); + + // Description: + // Turn on/off flag to control whether this object's data is released + // after being used by a filter. + void SetReleaseDataFlag(int); + int GetReleaseDataFlag(); + vtkBooleanMacro(ReleaseDataFlag,int); + + // Description: + // Turn on/off flag to control whether every object releases its data + // after being used by a filter. + static void SetGlobalReleaseDataFlag(int val); + void GlobalReleaseDataFlagOn() {this->SetGlobalReleaseDataFlag(1);}; + void GlobalReleaseDataFlagOff() {this->SetGlobalReleaseDataFlag(0);}; + static int GetGlobalReleaseDataFlag(); + + // Description: + // Assign or retrieve field data to this data object. + virtual void SetFieldData(vtkFieldData*); + vtkGetObjectMacro(FieldData,vtkFieldData); + + // Handle the source/data loop. + virtual void Register(vtkObjectBase* o); + virtual void UnRegister(vtkObjectBase* o); + + // Description: + // Provides opportunity for the data object to insure internal + // consistency before access. Also causes owning source/filter + // (if any) to update itself. The Update() method is composed of + // UpdateInformation(), PropagateUpdateExtent(), + // TriggerAsynchronousUpdate(), and UpdateData(). + virtual void Update(); + + // Description: + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE. + // THIS METHOD IS PART OF THE PIPELINE UPDATE FUNCTIONALITY. + // Update all the "easy to update" information about the object such + // as the extent which will be used to control the update. + // This propagates all the way up then back down the pipeline. + // As a by-product the PipelineMTime is updated. + virtual void UpdateInformation(); + + // Description: + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE. + // THIS METHOD IS PART OF THE PIPELINE UPDATE FUNCTIONALITY. + // The update extent for this object is propagated up the pipeline. + // This propagation may early terminate based on the PipelineMTime. + virtual void PropagateUpdateExtent(); + + // Description: + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE. + // THIS METHOD IS PART OF THE PIPELINE UPDATE FUNCTIONALITY. + // Propagate back up the pipeline for ports and trigger the update on the + // other side of the port to allow for asynchronous parallel processing in + // the pipeline. + // This propagation may early terminate based on the PipelineMTime. + virtual void TriggerAsynchronousUpdate(); + + // Description: + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE. + // THIS METHOD IS PART OF THE PIPELINE UPDATE FUNCTIONALITY. + // Propagate the update back up the pipeline, and perform the actual + // work of updating on the way down. When the propagate arrives at a + // port, block and wait for the asynchronous update to finish on the + // other side. + // This propagation may early terminate based on the PipelineMTime. + virtual void UpdateData(); + + // Description: + // Get the estimated size of this data object itself. Should be called + // after UpdateInformation() and PropagateUpdateExtent() have both been + // called. Should be overridden in a subclass - otherwise the default + // is to assume that this data object requires no memory. + // The size is returned in kilobytes. + virtual unsigned long GetEstimatedMemorySize(); + + // Description: + // A generic way of specifying an update extent. Subclasses + // must decide what a piece is. When the NumberOfPieces is zero, then + // no data is requested, and the source will not execute. + virtual void SetUpdateExtent(int piece,int numPieces, int ghostLevel); + void SetUpdateExtent(int piece, int numPieces) + {this->SetUpdateExtent(piece, numPieces, 0);} + + // Description: + // Set the update extent for data objects that use 3D extents. Using this + // method on data objects that set extents as pieces (such as vtkPolyData or + // vtkUnstructuredGrid) has no real effect. + // Don't use the set macro to set the update extent + // since we don't want this object to be modified just due to + // a change in update extent. When the volume of the extent is zero (0, -1,..), + // then no data is requested, and the source will not execute. + virtual void SetUpdateExtent(int x0, int x1, int y0, int y1, int z0, int z1); + virtual void SetUpdateExtent(int extent[6]); + virtual int* GetUpdateExtent(); + virtual void GetUpdateExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1); + virtual void GetUpdateExtent(int extent[6]); + + // Description: + // Return class name of data type. This is one of VTK_STRUCTURED_GRID, + // VTK_STRUCTURED_POINTS, VTK_UNSTRUCTURED_GRID, VTK_POLY_DATA, or + // VTK_RECTILINEAR_GRID (see vtkSetGet.h for definitions). + // THIS METHOD IS THREAD SAFE + virtual int GetDataObjectType() {return VTK_DATA_OBJECT;} + + // Description: + // Used by Threaded ports to determine if they should initiate an + // asynchronous update (still in development). + unsigned long GetUpdateTime(); + + // Description: + // If the whole input extent is required to generate the requested output + // extent, this method can be called to set the input update extent to the + // whole input extent. This method assumes that the whole extent is known + // (that UpdateInformation has been called) + void SetUpdateExtentToWholeExtent(); + + // Description: + // Get the cumulative modified time of everything upstream. Does + // not include the MTime of this object. + unsigned long GetPipelineMTime(); + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). + virtual unsigned long GetActualMemorySize(); + + // Description: + // Copy the generic information (WholeExtent ...) + void CopyInformation( vtkDataObject *data ); + + // Description: + // By default, there is no type specific information + virtual void CopyTypeSpecificInformation( vtkDataObject *data ) + {this->CopyInformation( data );}; + + // Description: + // Set / Get the update piece and the update number of pieces. Similar + // to update extent in 3D. + void SetUpdatePiece(int piece); + void SetUpdateNumberOfPieces(int num); + virtual int GetUpdatePiece(); + virtual int GetUpdateNumberOfPieces(); + + // Description: + // Set / Get the update ghost level and the update number of ghost levels. + // Similar to update extent in 3D. + void SetUpdateGhostLevel(int level); + virtual int GetUpdateGhostLevel(); + + // Description: + // This request flag indicates whether the requester can handle + // more data than requested. Right now it is used in vtkImageData. + // Image filters can return more data than requested. The the + // consumer cannot handle this (i.e. DataSetToDataSetFitler) + // the image will crop itself. This functionality used to be in + // ImageToStructuredPoints. + virtual void SetRequestExactExtent(int flag); + virtual int GetRequestExactExtent(); + vtkBooleanMacro(RequestExactExtent, int); + + // Description: + // Set/Get the whole extent of this data object. + // The whole extent is meta data for structured data sets. + // It gets set by the source during the update information call. + virtual void SetWholeExtent(int x0, int x1, int y0, int y1, int z0, int z1); + virtual void SetWholeExtent(int extent[6]); + virtual int* GetWholeExtent(); + virtual void GetWholeExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1); + virtual void GetWholeExtent(int extent[6]); + + // Description: + // Set/Get the whole bounding box of this data object. + // The whole whole bounding box is meta data for data sets + // It gets set by the source during the update information call. + virtual void SetWholeBoundingBox(double x0, double x1, double y0, + double y1, double z0, double z1); + virtual void SetWholeBoundingBox(double bb[6]); + virtual double* GetWholeBoundingBox(); + virtual void GetWholeBoundingBox(double& x0, double& x1, double& y0, + double& y1, double& z0, double& z1); + virtual void GetWholeBoundingBox(double extent[6]); + + // Description: + // Set/Get the maximum number of pieces that can be requested. + // The maximum number of pieces is meta data for unstructured data sets. + // It gets set by the source during the update information call. + // A value of -1 indicates that there is no maximum. A value of + virtual void SetMaximumNumberOfPieces(int); + virtual int GetMaximumNumberOfPieces(); + + // Description: + // Copy information about this data object to its + // PipelineInformation from its own Information for the given + // request. If the second argument is not NULL then it is the + // pipeline information object for the input to this data object's + // producer. + virtual void CopyInformationToPipeline(vtkInformation* request, + vtkInformation* input); + + // Description: + // Copy information about this data object from the + // PipelineInformation to its own Information for the given request. + virtual void CopyInformationFromPipeline(vtkInformation* request); + + // Description: + // Return the information object within the input information object's + // field data corresponding to the specified association + // (FIELD_ASSOCIATION_POINTS or FIELD_ASSOCIATION_CELLS) and attribute + // (SCALARS, VECTORS, NORMALS, TCOORDS, or TENSORS) + static vtkInformation *GetActiveFieldInformation(vtkInformation *info, + int fieldAssociation, int attributeType); + + // Description: + // Return the information object within the input information object's + // field data corresponding to the specified association + // (FIELD_ASSOCIATION_POINTS or FIELD_ASSOCIATION_CELLS) and name. + static vtkInformation *GetNamedFieldInformation(vtkInformation *info, + int fieldAssociation, const char *name); + + // Description: + // Remove the info associated with an array + static void RemoveNamedFieldInformation(vtkInformation *info, + int fieldAssociation, + const char *name); + + // Description: + // Set the named array to be the active field for the specified type + // (SCALARS, VECTORS, NORMALS, TCOORDS, or TENSORS) and association + // (FIELD_ASSOCIATION_POINTS or FIELD_ASSOCIATION_CELLS). Returns the + // active field information object and creates on entry if one not found. + static vtkInformation *SetActiveAttribute(vtkInformation *info, + int fieldAssociation, const char *attributeName, int attributeType); + + // Description: + // Set the name, array type, number of components, and number of tuples + // within the passed information object for the active attribute of type + // attributeType (in specified association, FIELD_ASSOCIATION_POINTS or + // FIELD_ASSOCIATION_CELLS). If there is not an active attribute of the + // specified type, an entry in the information object is created. If + // arrayType, numComponents, or numTuples equal to -1, or name=NULL the + // value is not changed. + static void SetActiveAttributeInfo(vtkInformation *info, + int fieldAssociation, int attributeType, const char *name, int arrayType, + int numComponents, int numTuples); + + // Description: + // Convenience version of previous method for use (primarily) by the Imaging + // filters. If arrayType or numComponents == -1, the value is not changed. + static void SetPointDataActiveScalarInfo(vtkInformation *info, + int arrayType, int numComponents); + + // Description: + // This method is called by the source when it executes to generate data. + // It is sort of the opposite of ReleaseData. + // It sets the DataReleased flag to 0, and sets a new UpdateTime. + void DataHasBeenGenerated(); + + // Description: + // make the output data ready for new data to be inserted. For most + // objects we just call Initialize. But for vtkImageData we leave the old + // data in case the memory can be reused. + virtual void PrepareForNewData() {this->Initialize();}; + + // Description: + // Shallow and Deep copy. These copy the data, but not any of the + // pipeline connections. + virtual void ShallowCopy(vtkDataObject *src); + virtual void DeepCopy(vtkDataObject *src); + + // Description: + // An object that will translate pieces into structured extents. + void SetExtentTranslator(vtkExtentTranslator* translator); + vtkExtentTranslator* GetExtentTranslator(); + + // Description: + // The ExtentType will be left as VTK_PIECES_EXTENT for data objects + // such as vtkPolyData and vtkUnstructuredGrid. The ExtentType will be + // changed to VTK_3D_EXTENT for data objects with 3D structure such as + // vtkImageData (and its subclass vtkStructuredPoints), vtkRectilinearGrid, + // and vtkStructuredGrid. The default is the have an extent in pieces, + // with only one piece (no streaming possible). + virtual int GetExtentType() { return VTK_PIECES_EXTENT; }; + + // Description: + // This method crops the data object (if necesary) so that the extent + // matches the update extent. + virtual void Crop(); + + //BTX + // Description: + // Possible values for the FIELD_ASSOCIATION information entry. + enum FieldAssociations + { + FIELD_ASSOCIATION_POINTS, + FIELD_ASSOCIATION_CELLS, + FIELD_ASSOCIATION_NONE, + FIELD_ASSOCIATION_POINTS_THEN_CELLS, + NUMBER_OF_ASSOCIATIONS + }; + //ETX + + //BTX + // Description: + // Possible values for the FIELD_OPERATION information entry. + enum FieldOperations + { + FIELD_OPERATION_PRESERVED, + FIELD_OPERATION_REINTERPOLATED, + FIELD_OPERATION_MODIFIED, + FIELD_OPERATION_REMOVED + }; + //ETX + + // Description: + // Given an integer association type, this static method returns a string type + // for the attribute (i.e. type = 0: returns "Points"). + static const char* GetAssociationTypeAsString(int associationType); + + static vtkInformationStringKey* DATA_TYPE_NAME(); + static vtkInformationDataObjectKey* DATA_OBJECT(); + static vtkInformationIntegerKey* DATA_EXTENT_TYPE(); + static vtkInformationIntegerPointerKey* DATA_EXTENT(); + static vtkInformationIntegerKey* DATA_PIECE_NUMBER(); + static vtkInformationIntegerKey* DATA_NUMBER_OF_PIECES(); + static vtkInformationIntegerKey* DATA_NUMBER_OF_GHOST_LEVELS(); + static vtkInformationIntegerKey* DATA_TIME_INDEX(); + static vtkInformationDoubleKey* DATA_TIME(); + static vtkInformationInformationVectorKey* POINT_DATA_VECTOR(); + static vtkInformationInformationVectorKey* CELL_DATA_VECTOR(); + static vtkInformationIntegerKey* FIELD_ARRAY_TYPE(); + static vtkInformationIntegerKey* FIELD_ASSOCIATION(); + static vtkInformationIntegerKey* FIELD_ATTRIBUTE_TYPE(); + static vtkInformationIntegerKey* FIELD_ACTIVE_ATTRIBUTE(); + static vtkInformationIntegerKey* FIELD_NUMBER_OF_COMPONENTS(); + static vtkInformationIntegerKey* FIELD_NUMBER_OF_TUPLES(); + static vtkInformationIntegerKey* FIELD_OPERATION(); + static vtkInformationStringKey* FIELD_NAME(); + static vtkInformationDoubleVectorKey* ORIGIN(); + static vtkInformationDoubleVectorKey* SPACING(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkDataObject* GetData(vtkInformation* info); + static vtkDataObject* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + + vtkDataObject(); + ~vtkDataObject(); + + // General field data associated with data object + vtkFieldData *FieldData; + + // Who generated this data as output? + vtkSource *Source; + + // Keep track of data release during network execution + int DataReleased; + + // When was this data last generated? + vtkTimeStamp UpdateTime; + + // Get the executive that manages this data object. + vtkExecutive* GetExecutive(); + + // Get the port number producing this data object. + int GetPortNumber(); + + virtual void ReportReferences(vtkGarbageCollector*); + + // Arbitrary extra information associated with this data object. + vtkInformation* Information; + + // Reference the pipeline information object that owns this data + // object. + vtkInformation* PipelineInformation; + + //BTX + // Check whether this data object is owned by a vtkStreamingDemandDrivenPipeline. + vtkStreamingDemandDrivenPipeline* TrySDDP(const char* method); + typedef vtkStreamingDemandDrivenPipeline SDDP; + //ETX + + //BTX + friend class vtkStreamingDemandDrivenPipelineToDataObjectFriendship; + //ETX + + static const char AssociationNames[NUMBER_OF_ASSOCIATIONS][55]; + +private: + // Helper method for the ShallowCopy and DeepCopy methods. + void InternalDataObjectCopy(vtkDataObject *src); + +private: + vtkDataObject(const vtkDataObject&); // Not implemented. + void operator=(const vtkDataObject&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkDataObjectAlgorithm.cxx b/Filtering/vtkDataObjectAlgorithm.cxx new file mode 100644 index 0000000..cb5ffef --- /dev/null +++ b/Filtering/vtkDataObjectAlgorithm.cxx @@ -0,0 +1,258 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataObjectAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkDataObject.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkDataObjectAlgorithm, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkDataObjectAlgorithm); + +//---------------------------------------------------------------------------- +vtkDataObjectAlgorithm::vtkDataObjectAlgorithm() +{ + // by default assume filters have one input and one output + // subclasses that deviate should modify this setting + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataObjectAlgorithm::~vtkDataObjectAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkDataObjectAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataObjectAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataObjectAlgorithm::GetOutput(int port) +{ + return this->GetOutputDataObject(port); +} + +//---------------------------------------------------------------------------- +void vtkDataObjectAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataObjectAlgorithm::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataObjectAlgorithm::GetInput(int port) +{ + if (this->GetNumberOfInputConnections(port) < 1) + { + return 0; + } + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +int vtkDataObjectAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkDataObjectAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectAlgorithm::RequestInformation( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* vtkNotUsed(outputVector)) +{ + // do nothing let subclasses handle it + return 1; +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkDataObjectAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + return 1; +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkDataObjectAlgorithm::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (output && this->UpdateExtentIsEmpty(output)) + { + output->Initialize(); + return; + } + + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkDataObjectAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + +//---------------------------------------------------------------------------- +int vtkDataObjectAlgorithm::UpdateExtentIsEmpty(vtkDataObject *output) +{ + if (output == NULL) + { + return 1; + } + + int *ext = output->GetUpdateExtent(); + switch ( output->GetExtentType() ) + { + case VTK_PIECES_EXTENT: + // Special way of asking for no input. + if ( output->GetUpdateNumberOfPieces() == 0 ) + { + return 1; + } + break; + + case VTK_3D_EXTENT: + // Special way of asking for no input. (zero volume) + if (ext[0] == (ext[1] + 1) || + ext[2] == (ext[3] + 1) || + ext[4] == (ext[5] + 1)) + { + return 1; + } + break; + + // We should never have this case occur + default: + vtkErrorMacro( << "Internal error - invalid extent type!" ); + break; + } + + return 0; +} + + +//---------------------------------------------------------------------------- +void vtkDataObjectAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkDataObjectAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObjectAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkDataObjectAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} diff --git a/Filtering/vtkDataObjectAlgorithm.h b/Filtering/vtkDataObjectAlgorithm.h new file mode 100644 index 0000000..f8767ba --- /dev/null +++ b/Filtering/vtkDataObjectAlgorithm.h @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataObjectAlgorithm - Superclass for algorithms that produce only data object as output +// .SECTION Description + +// vtkDataObjectAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// constructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be DataObject. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// ExecuteData and ExecuteInformation. For new algorithms you should +// implement RequestData( request, inputVec, outputVec) but for older filters +// there is a default implementation that calls the old ExecuteData(output) +// signature, for even older filters that don;t implement ExecuteData the +// default implementation calls the even older Execute() signature. + +#ifndef __vtkDataObjectAlgorithm_h +#define __vtkDataObjectAlgorithm_h + +#include "vtkAlgorithm.h" +#include "vtkDataObject.h" // makes things a bit easier + +class vtkDataSet; +class vtkDataObject; + +class VTK_FILTERING_EXPORT vtkDataObjectAlgorithm : public vtkAlgorithm +{ +public: + static vtkDataObjectAlgorithm *New(); + vtkTypeRevisionMacro(vtkDataObjectAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkDataObject* GetOutput(); + vtkDataObject* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject* GetInput(); + vtkDataObject *GetInput(int port); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(int, vtkDataObject*); + +protected: + vtkDataObjectAlgorithm(); + ~vtkDataObjectAlgorithm(); + + // convenience method + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) + { + return 1; + }; + + // Description: + // This detects when the UpdateExtent will generate no data. + // This condition is satisfied when the UpdateExtent has + // zero volume (0,-1,...) or the UpdateNumberOfPieces is 0. + // The source uses this call to determine whether to call Execute. + int UpdateExtentIsEmpty(vtkDataObject *output); + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkDataObjectAlgorithm(const vtkDataObjectAlgorithm&); // Not implemented. + void operator=(const vtkDataObjectAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkDataObjectCollection.cxx b/Filtering/vtkDataObjectCollection.cxx new file mode 100644 index 0000000..18beb63 --- /dev/null +++ b/Filtering/vtkDataObjectCollection.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataObjectCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDataObjectCollection, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkDataObjectCollection); diff --git a/Filtering/vtkDataObjectCollection.h b/Filtering/vtkDataObjectCollection.h new file mode 100644 index 0000000..519abe1 --- /dev/null +++ b/Filtering/vtkDataObjectCollection.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataObjectCollection - maintain an unordered list of data objects +// .SECTION Description +// vtkDataObjectCollection is an object that creates and manipulates lists of +// data objects. See also vtkCollection and subclasses. + +#ifndef __vtkDataObjectCollection_h +#define __vtkDataObjectCollection_h + +#include "vtkCollection.h" + +#include "vtkDataObject.h" // Needed for inline methods + +class VTK_FILTERING_EXPORT vtkDataObjectCollection : public vtkCollection +{ +public: + static vtkDataObjectCollection *New(); + vtkTypeRevisionMacro(vtkDataObjectCollection,vtkCollection); + + // Description: + // Add a data object to the list. + void AddItem(vtkDataObject *ds) { + this->vtkCollection::AddItem((vtkObject *)ds);}; + + // Description: + // Get the next data object in the list. + vtkDataObject *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + // Description: + // Get the ith data object in the list. + vtkDataObject *GetItem(int i) { + return static_cast(this->GetItemAsObject(i));}; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkDataObject *GetNextDataObject(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkDataObjectCollection() {}; + ~vtkDataObjectCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkDataObjectCollection(const vtkDataObjectCollection&); // Not implemented. + void operator=(const vtkDataObjectCollection&); // Not implemented. +}; + + +#endif diff --git a/Filtering/vtkDataObjectSource.cxx b/Filtering/vtkDataObjectSource.cxx new file mode 100644 index 0000000..c745aa7 --- /dev/null +++ b/Filtering/vtkDataObjectSource.cxx @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataObjectSource.h" + +#include "vtkDataObject.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDataObjectSource, "$Revision: 1.17 $"); + +vtkDataObjectSource::vtkDataObjectSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + + this->SetOutput(vtkDataObject::New()); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); +} + + +//---------------------------------------------------------------------------- +vtkDataObject *vtkDataObjectSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkDataObject *)(this->Outputs[0]); +} + +//---------------------------------------------------------------------------- +void vtkDataObjectSource::SetOutput(vtkDataObject *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + +//---------------------------------------------------------------------------- +int vtkDataObjectSource::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataObjectSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataObjectSource.h b/Filtering/vtkDataObjectSource.h new file mode 100644 index 0000000..7f269a7 --- /dev/null +++ b/Filtering/vtkDataObjectSource.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataObjectSource - abstract class specifies interface for +// field source (or objects that generate field output) + +// .SECTION Description +// vtkDataObjectSource is an abstract object that specifies behavior and +// interface of field source objects. Field source objects are source objects +// that create vtkFieldData (field data) on output. +// +// Concrete subclasses of vtkDataObjectSource must define Update() and +// Execute() methods. The public method Update() invokes network execution +// and will bring the network up-to-date. The protected Execute() method +// actually does the work of data creation/generation. The difference between +// the two methods is that Update() implements input consistency checks and +// modified time comparisons and then invokes the Execute() which is an +// implementation of a particular algorithm. +// +// vtkDataObjectSource provides a mechanism for invoking the methods +// StartMethod() and EndMethod() before and after object execution (via +// Execute()). These are convenience methods you can use for any purpose +// (e.g., debugging info, highlighting/notifying user interface, etc.) These +// methods accept a single void* pointer that can be used to send data to the +// methods. It is also possible to specify a function to delete the argument +// via StartMethodArgDelete and EndMethodArgDelete. +// +// Another method, ProgressMethod() can be specified. Some filters invoke this +// method periodically during their execution. The use is similar to that of +// StartMethod() and EndMethod(). +// +// An important feature of subclasses of vtkDataObjectSource is that it is +// possible to control the memory-management model (i.e., retain output +// versus delete output data). If enabled the ReleaseDataFlag enables the +// deletion of the output data once the downstream process object finishes +// processing the data (please see text). + +// .SECTION See Also +// vtkSource vtkFilter vtkFieldDataFilter + +#ifndef __vtkDataObjectSource_h +#define __vtkDataObjectSource_h + +#include "vtkSource.h" + +class vtkDataObject; + +class VTK_FILTERING_EXPORT vtkDataObjectSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkDataObjectSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output field of this source. + vtkDataObject *GetOutput(); + vtkDataObject *GetOutput(int idx) + {return (vtkDataObject *) this->vtkSource::GetOutput(idx); }; + void SetOutput(vtkDataObject *); + +protected: + vtkDataObjectSource(); + ~vtkDataObjectSource() {}; + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkDataObjectSource(const vtkDataObjectSource&); // Not implemented. + void operator=(const vtkDataObjectSource&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkDataSet.cxx b/Filtering/vtkDataSet.cxx new file mode 100644 index 0000000..47121fd --- /dev/null +++ b/Filtering/vtkDataSet.cxx @@ -0,0 +1,650 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSet.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkCellTypes.h" +#include "vtkExtentTranslator.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkPointData.h" +#include "vtkSource.h" + +#include + +vtkCxxRevisionMacro(vtkDataSet, "$Revision: 1.3.12.1 $"); + +//---------------------------------------------------------------------------- +// Constructor with default bounds (0,1, 0,1, 0,1). +vtkDataSet::vtkDataSet () +{ + vtkMath::UninitializeBounds(this->Bounds); + + this->PointData = vtkPointData::New(); + this->CellData = vtkCellData::New(); + this->ScalarRange[0] = 0.0; + this->ScalarRange[1] = 1.0; +} + +//---------------------------------------------------------------------------- +vtkDataSet::~vtkDataSet () +{ + this->PointData->Delete(); + this->CellData->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkDataSet::Initialize() +{ + // We don't modify ourselves because the "ReleaseData" methods depend upon + // no modification when initialized. + vtkDataObject::Initialize(); + + this->CellData->Initialize(); + this->PointData->Initialize(); +} + +//---------------------------------------------------------------------------- +// Compute the data bounding box from data points. +void vtkDataSet::ComputeBounds() +{ + int j; + vtkIdType i; + double *x; + + if ( this->GetMTime() > this->ComputeTime ) + { + if (this->GetNumberOfPoints()) + { + x = this->GetPoint(0); + this->Bounds[0] = x[0]; + this->Bounds[2] = x[1]; + this->Bounds[4] = x[2]; + this->Bounds[1] = x[0]; + this->Bounds[3] = x[1]; + this->Bounds[5] = x[2]; + for (i=1; iGetNumberOfPoints(); i++) + { + x = this->GetPoint(i); + for (j=0; j<3; j++) + { + if ( x[j] < this->Bounds[2*j] ) + { + this->Bounds[2*j] = x[j]; + } + if ( x[j] > this->Bounds[2*j+1] ) + { + this->Bounds[2*j+1] = x[j]; + } + } + } + } + else + { + vtkMath::UninitializeBounds(this->Bounds); + } + this->ComputeTime.Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataSet::GetScalarRange(double range[2]) +{ + vtkDataArray *ptScalars, *cellScalars; + ptScalars = this->PointData->GetScalars(); + cellScalars = this->CellData->GetScalars(); + + if ( ptScalars && cellScalars) + { + double r1[2], r2[2]; + ptScalars->GetRange(r1,0); + cellScalars->GetRange(r2,0); + range[0] = (r1[0] < r2[0] ? r1[0] : r2[0]); + range[1] = (r1[1] > r2[1] ? r1[1] : r2[1]); + } + else if ( ptScalars ) + { + ptScalars->GetRange(range,0); + } + else if ( cellScalars ) + { + cellScalars->GetRange(range,0); + } + else + { + range[0] = 0.0; + range[1] = 1.0; + } +} + +//---------------------------------------------------------------------------- +double *vtkDataSet::GetScalarRange() +{ + this->GetScalarRange(this->ScalarRange); + return this->ScalarRange; +} + +//---------------------------------------------------------------------------- +// Return a pointer to the geometry bounding box in the form +// (xmin,xmax, ymin,ymax, zmin,zmax). +double *vtkDataSet::GetBounds() +{ + this->ComputeBounds(); + return this->Bounds; +} + +//---------------------------------------------------------------------------- +void vtkDataSet::GetBounds(double bounds[6]) +{ + this->ComputeBounds(); + for (int i=0; i<6; i++) + { + bounds[i] = this->Bounds[i]; + } +} + +//---------------------------------------------------------------------------- +// Get the center of the bounding box. +double *vtkDataSet::GetCenter() +{ + this->ComputeBounds(); + for (int i=0; i<3; i++) + { + this->Center[i] = (this->Bounds[2*i+1] + this->Bounds[2*i]) / 2.0; + } + return this->Center; +} + +//---------------------------------------------------------------------------- +void vtkDataSet::GetCenter(double center[3]) +{ + this->ComputeBounds(); + for (int i=0; i<3; i++) + { + center[i] = (this->Bounds[2*i+1] + this->Bounds[2*i]) / 2.0; + } +} + +//---------------------------------------------------------------------------- +// Return the length of the diagonal of the bounding box. +double vtkDataSet::GetLength() +{ + double diff, l=0.0; + int i; + + this->ComputeBounds(); + for (i=0; i<3; i++) + { + diff = static_cast(this->Bounds[2*i+1]) - + static_cast(this->Bounds[2*i]); + l += diff * diff; + } + diff = sqrt(l); + return diff; +} + +//---------------------------------------------------------------------------- +unsigned long int vtkDataSet::GetMTime() +{ + unsigned long mtime, result; + + result = vtkDataObject::GetMTime(); + + mtime = this->PointData->GetMTime(); + result = ( mtime > result ? mtime : result ); + + mtime = this->CellData->GetMTime(); + return ( mtime > result ? mtime : result ); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkDataSet::FindAndGetCell (double x[3], vtkCell *cell, + vtkIdType cellId, double tol2, int& subId, + double pcoords[3], double *weights) +{ + int newCell = this->FindCell(x,cell,cellId,tol2,subId,pcoords,weights); + if (newCell >= 0 ) + { + cell = this->GetCell (newCell); + } + else + { + return NULL; + } + return cell; +} + +//---------------------------------------------------------------------------- +void vtkDataSet::GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds) +{ + vtkIdType i, numPts; + vtkIdList *otherCells = vtkIdList::New(); + otherCells->Allocate(VTK_CELL_SIZE); + + // load list with candidate cells, remove current cell + this->GetPointCells(ptIds->GetId(0), cellIds); + cellIds->DeleteId(cellId); + + // now perform multiple intersections on list + if ( cellIds->GetNumberOfIds() > 0 ) + { + for ( numPts=ptIds->GetNumberOfIds(), i=1; i < numPts; i++) + { + this->GetPointCells(ptIds->GetId(i), otherCells); + cellIds->IntersectWith(*otherCells); + } + } + + otherCells->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkDataSet::GetCellTypes(vtkCellTypes *types) +{ + vtkIdType cellId, numCells=this->GetNumberOfCells(); + unsigned char type; + + types->Reset(); + for (cellId=0; cellId < numCells; cellId++) + { + type = this->GetCellType(cellId); + if ( ! types->IsType(type) ) + { + types->InsertNextType(type); + } + } +} + + +//---------------------------------------------------------------------------- +// Default implementation. This is very slow way to compute this information. +// Subclasses should override this method for efficiency. +void vtkDataSet::GetCellBounds(vtkIdType cellId, double bounds[6]) +{ + vtkGenericCell *cell = vtkGenericCell::New(); + + this->GetCell(cellId, cell); + cell->GetBounds(bounds); + cell->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkDataSet::Squeeze() +{ + this->CellData->Squeeze(); + this->PointData->Squeeze(); +} + +//---------------------------------------------------------------------------- +unsigned long vtkDataSet::GetActualMemorySize() +{ + unsigned long size=this->vtkDataObject::GetActualMemorySize(); + size += this->PointData->GetActualMemorySize(); + size += this->CellData->GetActualMemorySize(); + return size; +} + +//---------------------------------------------------------------------------- +void vtkDataSet::ShallowCopy(vtkDataObject *dataObject) +{ + vtkDataSet *dataSet = vtkDataSet::SafeDownCast(dataObject); + + if ( dataSet != NULL ) + { + this->InternalDataSetCopy(dataSet); + this->CellData->ShallowCopy(dataSet->GetCellData()); + this->PointData->ShallowCopy(dataSet->GetPointData()); + } + // Do superclass + this->vtkDataObject::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkDataSet::DeepCopy(vtkDataObject *dataObject) +{ + vtkDataSet *dataSet = vtkDataSet::SafeDownCast(dataObject); + + if ( dataSet != NULL ) + { + this->InternalDataSetCopy(dataSet); + this->CellData->DeepCopy(dataSet->GetCellData()); + this->PointData->DeepCopy(dataSet->GetPointData()); + } + + // Do superclass + this->vtkDataObject::DeepCopy(dataObject); +} + +//---------------------------------------------------------------------------- +// This copies all the local variables (but not objects). +void vtkDataSet::InternalDataSetCopy(vtkDataSet *src) +{ + int idx; + + this->ComputeTime = src->ComputeTime; + this->ScalarRange[0] = src->ScalarRange[0]; + this->ScalarRange[1] = src->ScalarRange[1]; + for (idx = 0; idx < 3; ++idx) + { + this->Bounds[2*idx] = src->Bounds[2*idx]; + this->Bounds[2*idx+1] = src->Bounds[2*idx+1]; + } +} + + +//---------------------------------------------------------------------------- +int vtkDataSet::CheckAttributes() +{ + int numPts, numCells; + int numArrays, idx; + vtkDataArray *array; + int numTuples; + const char* name; + + numPts = this->GetNumberOfPoints(); + numCells = this->GetNumberOfCells(); + + numArrays = this->GetPointData()->GetNumberOfArrays(); + for (idx = 0; idx < numArrays; ++idx) + { + array = this->GetPointData()->GetArray(idx); + numTuples = array->GetNumberOfTuples(); + name = array->GetName(); + if (name == NULL) + { + name = ""; + } + if (numTuples < numPts) + { + vtkErrorMacro("Point array " << name << " with " + << array->GetNumberOfComponents() + << " components, only has " << numTuples << " tuples but there are " + << numPts << " points"); + return 1; + } + if (numTuples > numPts) + { + vtkWarningMacro("Point array " << name << " with " + << array->GetNumberOfComponents() + << " components, has " << numTuples << " tuples but there are only " + << numPts << " points"); + } + } + + numArrays = this->GetCellData()->GetNumberOfArrays(); + for (idx = 0; idx < numArrays; ++idx) + { + array = this->GetCellData()->GetArray(idx); + numTuples = array->GetNumberOfTuples(); + name = array->GetName(); + if (name == NULL) + { + name = ""; + } + if (numTuples < numCells) + { + vtkErrorMacro("Cell array " << name << " with " + << array->GetNumberOfComponents() + << " components, has only " << numTuples << " tuples but there are " + << numCells << " cells"); + return 1; + } + if (numTuples > numCells) + { + vtkWarningMacro("Cell array " << name << " with " + << array->GetNumberOfComponents() + << " components, has " << numTuples << " tuples but there are only " + << numCells << " cells"); + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +void vtkDataSet::GenerateGhostLevelArray() +{ + // Make sure this is a structured data set. + if(this->GetExtentType() != VTK_3D_EXTENT) + { + return; + } + + if (this->GetUpdateNumberOfPieces() == 1) + { + // Either the piece has not been used to set the update extent, + // or the whole image was requested. + return; + } + + // Avoid generating these if the producer has generated them. + if(!this->PointData->GetArray("vtkGhostLevels")) + { // Create ghost levels for cells and points. + vtkUnsignedCharArray *levels; + int zeroExt[6], extent[6]; + int i, j, k, di, dj, dk, dist; + + this->Information->Get(vtkDataObject::DATA_EXTENT(), extent); + vtkExtentTranslator* translator = this->GetExtentTranslator(); + // Get the extent with ghost level 0. + translator->SetWholeExtent(this->GetWholeExtent()); + translator->SetPiece(this->GetUpdatePiece()); + translator->SetNumberOfPieces(this->GetUpdateNumberOfPieces()); + translator->SetGhostLevel(0); + translator->PieceToExtent(); + translator->GetExtent(zeroExt); + + // ---- POINTS ---- + // Allocate the appropriate number levels (number of points). + levels = vtkUnsignedCharArray::New(); + levels->Allocate((extent[1]-extent[0] + 1) * + (extent[3]-extent[2] + 1) * + (extent[5]-extent[4] + 1)); + + //cerr << "max: " << extent[0] << ", " << extent[1] << ", " + // << extent[2] << ", " << extent[3] << ", " + // << extent[4] << ", " << extent[5] << endl; + //cerr << "zero: " << zeroExt[0] << ", " << zeroExt[1] << ", " + // << zeroExt[2] << ", " << zeroExt[3] << ", " + // << zeroExt[4] << ", " << zeroExt[5] << endl; + + int wholeExtent[6] = {0,-1,0,-1,0,-1}; + this->GetWholeExtent(wholeExtent); + // Loop through the points in this image. + for (k = extent[4]; k <= extent[5]; ++k) + { + dk = 0; + if (k < zeroExt[4]) + { + dk = zeroExt[4] - k; + } + if (k >= zeroExt[5] && k < wholeExtent[5]) + { // Special case for last tile. + dk = k - zeroExt[5] + 1; + } + for (j = extent[2]; j <= extent[3]; ++j) + { + dj = 0; + if (j < zeroExt[2]) + { + dj = zeroExt[2] - j; + } + if (j >= zeroExt[3] && j < wholeExtent[3]) + { // Special case for last tile. + dj = j - zeroExt[3] + 1; + } + for (i = extent[0]; i <= extent[1]; ++i) + { + di = 0; + if (i < zeroExt[0]) + { + di = zeroExt[0] - i; + } + if (i >= zeroExt[1] && i < wholeExtent[1]) + { // Special case for last tile. + di = i - zeroExt[1] + 1; + } + // Compute Manhatten distance. + dist = di; + if (dj > dist) + { + dist = dj; + } + if (dk > dist) + { + dist = dk; + } + + //cerr << " " << i << ", " << j << ", " << k << endl; + //cerr << " " << di << ", " << dj << ", " << dk << endl; + //cerr << dist << endl; + + levels->InsertNextValue((unsigned char)dist); + } + } + } + levels->SetName("vtkGhostLevels"); + this->PointData->AddArray(levels); + levels->Delete(); + + // Only generate ghost call levels if zero levels are requested. + // (Although we still need ghost points.) + if (this->GetUpdateGhostLevel() == 0) + { + return; + } + + // ---- CELLS ---- + // Allocate the appropriate number levels (number of cells). + levels = vtkUnsignedCharArray::New(); + levels->Allocate((extent[1]-extent[0]) * + (extent[3]-extent[2]) * + (extent[5]-extent[4])); + + // Loop through the cells in this image. + // Cells may be 2d or 1d ... Treat all as 3D + if (extent[0] == extent[1]) + { + ++extent[1]; + ++zeroExt[1]; + } + if (extent[2] == extent[3]) + { + ++extent[3]; + ++zeroExt[3]; + } + if (extent[4] == extent[5]) + { + ++extent[5]; + ++zeroExt[5]; + } + + // Loop + for (k = extent[4]; k < extent[5]; ++k) + { // Determine the Manhatten distances to zero extent. + dk = 0; + if (k < zeroExt[4]) + { + dk = zeroExt[4] - k; + } + if (k >= zeroExt[5]) + { + dk = k - zeroExt[5] + 1; + } + for (j = extent[2]; j < extent[3]; ++j) + { + dj = 0; + if (j < zeroExt[2]) + { + dj = zeroExt[2] - j; + } + if (j >= zeroExt[3]) + { + dj = j - zeroExt[3] + 1; + } + for (i = extent[0]; i < extent[1]; ++i) + { + di = 0; + if (i < zeroExt[0]) + { + di = zeroExt[0] - i; + } + if (i >= zeroExt[1]) + { + di = i - zeroExt[1] + 1; + } + // Compute Manhatten distance. + dist = di; + if (dj > dist) + { + dist = dj; + } + if (dk > dist) + { + dist = dk; + } + + levels->InsertNextValue((unsigned char)dist); + } + } + } + levels->SetName("vtkGhostLevels"); + this->CellData->AddArray(levels); + levels->Delete(); + } + +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkDataSet::GetData(vtkInformation* info) +{ + return info? vtkDataSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkDataSet::GetData(vtkInformationVector* v, int i) +{ + return vtkDataSet::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +void vtkDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + double *bounds; + + os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n"; + os << indent << "Number Of Cells: " << this->GetNumberOfCells() << "\n"; + + os << indent << "Cell Data:\n"; + this->CellData->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Point Data:\n"; + this->PointData->PrintSelf(os,indent.GetNextIndent()); + + bounds = this->GetBounds(); + os << indent << "Bounds: \n"; + os << indent << " Xmin,Xmax: (" <ComputeTime.GetMTime() << "\n"; +} + diff --git a/Filtering/vtkDataSet.h b/Filtering/vtkDataSet.h new file mode 100644 index 0000000..ce348b2 --- /dev/null +++ b/Filtering/vtkDataSet.h @@ -0,0 +1,356 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSet - abstract class to specify dataset behavior +// .SECTION Description +// vtkDataSet is an abstract class that specifies an interface for dataset +// objects. vtkDataSet also provides methods to provide informations about +// the data, such as center, bounding box, and representative length. +// +// In vtk a dataset consists of a structure (geometry and topology) and +// attribute data. The structure is defined implicitly or explicitly as +// a collection of cells. The geometry of the structure is contained in +// point coordinates plus the cell interpolation functions. The topology +// of the dataset structure is defined by cell types and how the cells +// share their defining points. +// +// Attribute data in vtk is either point data (data at points) or cell data +// (data at cells). Typically filters operate on point data, but some may +// operate on cell data, both cell and point data, either one, or none. + +// .SECTION See Also +// vtkPointSet vtkStructuredPoints vtkStructuredGrid vtkUnstructuredGrid +// vtkRectilinearGrid vtkPolyData vtkPointData vtkCellData +// vtkDataObject vtkFieldData + +#ifndef __vtkDataSet_h +#define __vtkDataSet_h + +#include "vtkDataObject.h" + +class vtkCell; +class vtkCellData; +class vtkCellTypes; +class vtkGenericCell; +class vtkIdList; +class vtkPointData; +class vtkSourceToDataSetFriendship; + +class VTK_FILTERING_EXPORT vtkDataSet : public vtkDataObject +{ +public: + vtkTypeRevisionMacro(vtkDataSet,vtkDataObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Copy the geometric and topological structure of an object. Note that + // the invoking object and the object pointed to by the parameter ds must + // be of the same type. + // THIS METHOD IS NOT THREAD SAFE. + virtual void CopyStructure(vtkDataSet *ds) = 0; + + // Description: + // Determine the number of points composing the dataset. + // THIS METHOD IS THREAD SAFE + virtual vtkIdType GetNumberOfPoints() = 0; + + // Description: + // Determine the number of cells composing the dataset. + // THIS METHOD IS THREAD SAFE + virtual vtkIdType GetNumberOfCells() = 0; + + // Description: + // Get point coordinates with ptId such that: 0 <= ptId < NumberOfPoints. + // THIS METHOD IS NOT THREAD SAFE. + virtual double *GetPoint(vtkIdType ptId) = 0; + + // Description: + // Copy point coordinates into user provided array x[3] for specified + // point id. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetPoint(vtkIdType id, double x[3]); + + // Description: + // Get cell with cellId such that: 0 <= cellId < NumberOfCells. + // THIS METHOD IS NOT THREAD SAFE. + virtual vtkCell *GetCell(vtkIdType cellId) = 0; + + // Description: + // Get cell with cellId such that: 0 <= cellId < NumberOfCells. + // This is a thread-safe alternative to the previous GetCell() + // method. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetCell(vtkIdType cellId, vtkGenericCell *cell) = 0; + + // Description: + // Get the bounds of the cell with cellId such that: + // 0 <= cellId < NumberOfCells. + // A subclass may be able to determine the bounds of cell without using + // an expensive GetCell() method. A default implementation is provided + // that actually uses a GetCell() call. This is to ensure the method + // is available to all datasets. Subclasses should override this method + // to provide an efficient implementation. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetCellBounds(vtkIdType cellId, double bounds[6]); + + // Description: + // Get type of cell with cellId such that: 0 <= cellId < NumberOfCells. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual int GetCellType(vtkIdType cellId) = 0; + + // Description: + // Get a list of types of cells in a dataset. The list consists of an array + // of types (not necessarily in any order), with a single entry per type. + // For example a dataset 5 triangles, 3 lines, and 100 hexahedra would + // result a list of three entries, corresponding to the types VTK_TRIANGLE, + // VTK_LINE, and VTK_HEXAHEDRON. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetCellTypes(vtkCellTypes *types); + + // Description: + // Topological inquiry to get points defining cell. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds) = 0; + + // Description: + // Topological inquiry to get cells using point. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetPointCells(vtkIdType ptId, vtkIdList *cellIds) = 0; + + // Description: + // Topological inquiry to get all cells using list of points exclusive of + // cell specified (e.g., cellId). Note that the list consists of only + // cells that use ALL the points provided. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds); + + // Description: + // Locate the closest point to the global coordinate x. Return the + // point id. If point id < 0; then no point found. (This may arise + // when point is outside of dataset.) + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + vtkIdType FindPoint(double x, double y, double z) + { + double xyz[3]; + xyz[0] = x; xyz[1] = y; xyz[2] = z; + return this->FindPoint (xyz); + } + virtual vtkIdType FindPoint(double x[3]) = 0; + + // Description: + // Locate cell based on global coordinate x and tolerance + // squared. If cell and cellId is non-NULL, then search starts from + // this cell and looks at immediate neighbors. Returns cellId >= 0 + // if inside, < 0 otherwise. The parametric coordinates are + // provided in pcoords[3]. The interpolation weights are returned in + // weights[]. (The number of weights is equal to the number of + // points in the found cell). Tolerance is used to control how close + // the point is to be considered "in" the cell. + // THIS METHOD IS NOT THREAD SAFE. + virtual vtkIdType FindCell(double x[3], vtkCell *cell, vtkIdType cellId, + double tol2, int& subId, double pcoords[3], + double *weights) = 0; + + // Description: + // This is a version of the above method that can be used with + // multithreaded applications. A vtkGenericCell must be passed in + // to be used in internal calls that might be made to GetCell() + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual vtkIdType FindCell(double x[3], vtkCell *cell, + vtkGenericCell *gencell, vtkIdType cellId, + double tol2, int& subId, double pcoords[3], + double *weights) = 0; + + // Description: + // Locate the cell that contains a point and return the cell. Also returns + // the subcell id, parametric coordinates and weights for subsequent + // interpolation. This method combines the derived class methods + // int FindCell and vtkCell *GetCell. Derived classes may provide a more + // efficient implementation. See for example vtkStructuredPoints. + // THIS METHOD IS NOT THREAD SAFE. + virtual vtkCell *FindAndGetCell(double x[3], vtkCell *cell, vtkIdType cellId, + double tol2, int& subId, double pcoords[3], + double *weights); + + // Description: + // Datasets are composite objects and need to check each part for MTime + // THIS METHOD IS THREAD SAFE + unsigned long int GetMTime(); + + // Description: + // return pointer to this dataset's point data + // THIS METHOD IS THREAD SAFE + vtkCellData *GetCellData() {return this->CellData;}; + + // Description: + // return pointer to this dataset's point data + // THIS METHOD IS THREAD SAFE + vtkPointData *GetPointData() {return this->PointData;}; + + // Description: + // Reclaim any extra memory used to store data. + // THIS METHOD IS NOT THREAD SAFE. + virtual void Squeeze(); + + // Description: + // Compute the data bounding box from data points. + // THIS METHOD IS NOT THREAD SAFE. + virtual void ComputeBounds(); + + // Description: + // Return a pointer to the geometry bounding box in the form + // (xmin,xmax, ymin,ymax, zmin,zmax). + // THIS METHOD IS NOT THREAD SAFE. + double *GetBounds(); + + // Description: + // Return a pointer to the geometry bounding box in the form + // (xmin,xmax, ymin,ymax, zmin,zmax). + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + void GetBounds(double bounds[6]); + + // Description: + // Get the center of the bounding box. + // THIS METHOD IS NOT THREAD SAFE. + double *GetCenter(); + + // Description: + // Get the center of the bounding box. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + void GetCenter(double center[3]); + + // Description: + // Return the length of the diagonal of the bounding box. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + double GetLength(); + + // Description: + // Restore data object to initial state, + // THIS METHOD IS NOT THREAD SAFE. + void Initialize(); + + // Description: + // Convenience method to get the range of the scalar data (if there is any + // scalar data). Returns the (min/max) range of combined point and cell data. + // If there are no point or cell scalars the method will return (0,1). + // Note: Update needs to be called to create the scalars. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetScalarRange(double range[2]); + + // Description: + // Convenience method to get the range of the scalar data (if there is any + // scalar data). + // THIS METHOD IS NOT THREAD SAFE. + double *GetScalarRange(); + + // Description: + // Convenience method returns largest cell size in dataset. This is generally + // used to allocate memory for supporting data structures. + // THIS METHOD IS THREAD SAFE + virtual int GetMaxCellSize() = 0; + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). THIS METHOD + // IS THREAD SAFE. + unsigned long GetActualMemorySize(); + + // Description: + // Return the type of data object. + int GetDataObjectType() + {return VTK_DATA_SET;} + + // Description: + // Shallow and Deep copy. + void ShallowCopy(vtkDataObject *src); + void DeepCopy(vtkDataObject *src); + +//BTX + enum FieldDataType + { + DATA_OBJECT_FIELD=0, + POINT_DATA_FIELD=1, + CELL_DATA_FIELD=2 + }; +//ETX + + // Description: + // This method checks to see if the cell and point attributes + // match the geometry. Many filters will crash if the number of + // tupples in an array is less than the number of points/cells. + // This method returns 1 if there is a mismatch, + // and 0 if everything is ok. It prints an error if an + // array is too short, and a warning if an array is too long. + int CheckAttributes(); + + // Description: + // Normally called by pipeline executives or algoritgms only. This method + // computes the ghost arrays for a given dataset. + virtual void GenerateGhostLevelArray(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkDataSet* GetData(vtkInformation* info); + static vtkDataSet* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + // Constructor with default bounds (0,1, 0,1, 0,1). + vtkDataSet(); + ~vtkDataSet(); + + vtkCellData *CellData; // Scalars, vectors, etc. associated w/ each cell + vtkPointData *PointData; // Scalars, vectors, etc. associated w/ each point + vtkTimeStamp ComputeTime; // Time at which bounds, center, etc. computed + double Bounds[6]; // (xmin,xmax, ymin,ymax, zmin,zmax) geometric bounds + double ScalarRange[2]; + double Center[3]; + +private: + void InternalDataSetCopy(vtkDataSet *src); + //BTX + friend class vtkSourceToDataSetFriendship; + friend class vtkImageAlgorithmToDataSetFriendship; + //ETX +private: + vtkDataSet(const vtkDataSet&); // Not implemented. + void operator=(const vtkDataSet&); // Not implemented. +}; + +inline void vtkDataSet::GetPoint(vtkIdType id, double x[3]) +{ + double *pt = this->GetPoint(id); + x[0] = pt[0]; x[1] = pt[1]; x[2] = pt[2]; +} + +#endif diff --git a/Filtering/vtkDataSetAlgorithm.cxx b/Filtering/vtkDataSetAlgorithm.cxx new file mode 100644 index 0000000..88a7447 --- /dev/null +++ b/Filtering/vtkDataSetAlgorithm.cxx @@ -0,0 +1,256 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkDataSetAlgorithm, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkDataSetAlgorithm); + +//---------------------------------------------------------------------------- +// Instantiate object so that cell data is not passed to output. +vtkDataSetAlgorithm::vtkDataSetAlgorithm() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkDataSetAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkDataSetAlgorithm::GetOutput(int port) +{ + return vtkDataSet::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkImageData +vtkImageData *vtkDataSetAlgorithm::GetImageDataOutput() +{ + return vtkImageData::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkPolyData. +vtkPolyData *vtkDataSetAlgorithm::GetPolyDataOutput() +{ + return vtkPolyData::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkStructuredPoints. +vtkStructuredPoints *vtkDataSetAlgorithm::GetStructuredPointsOutput() +{ + return vtkStructuredPoints::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkStructuredGrid. +vtkStructuredGrid *vtkDataSetAlgorithm::GetStructuredGridOutput() +{ + return vtkStructuredGrid::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkUnstructuredGrid. +vtkUnstructuredGrid *vtkDataSetAlgorithm::GetUnstructuredGridOutput() +{ + return vtkUnstructuredGrid::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkRectilinearGrid. +vtkRectilinearGrid *vtkDataSetAlgorithm::GetRectilinearGridOutput() +{ + return vtkRectilinearGrid::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::SetInput(vtkDataSet* input) +{ + this->SetInput(0, static_cast(input)); +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::SetInput(int index, vtkDataSet* input) +{ + this->SetInput(index, static_cast(input)); +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::AddInput(vtkDataSet* input) +{ + this->AddInput(0, static_cast(input)); +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::AddInput(int index, vtkDataSet* input) +{ + this->AddInput(index, static_cast(input)); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataSetAlgorithm::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataSetAlgorithm::GetInput(int port) +{ + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +int vtkDataSetAlgorithm::ProcessRequest( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + // create the output + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + return this->RequestDataObject(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + // set update extent + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkDataSetAlgorithm::RequestDataObject( + vtkInformation*, + vtkInformationVector** inputVector , + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + if (!inInfo) + { + return 0; + } + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (input) + { + // for each output + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* info = outputVector->GetInformationObject(i); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + if (!output || !output->IsA(input->GetClassName())) + { + vtkDataSet* newOutput = input->NewInstance(); + newOutput->SetPipelineInformation(info); + newOutput->Delete(); + this->GetOutputPortInformation(0)->Set( + vtkDataObject::DATA_EXTENT_TYPE(), newOutput->GetExtentType()); + } + } + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDataSetAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataSetAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetAlgorithm.h b/Filtering/vtkDataSetAlgorithm.h new file mode 100644 index 0000000..25fb484 --- /dev/null +++ b/Filtering/vtkDataSetAlgorithm.h @@ -0,0 +1,163 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetAlgorithm - Superclass for algorithms that produce output of the same type as input +// .SECTION Description +// vtkDataSetAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// contstructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be DataSet. If that isn't +// the case then please override this method in your subclass. This class +// breaks out the downstream requests into seperate functions such as +// RequestDataObject RequestData and RequestInformation. The default +// implementation of RequestDataObject will create an output data of the +// same type as the input. + + +#ifndef __vtkDataSetAlgorithm_h +#define __vtkDataSetAlgorithm_h + +#include "vtkAlgorithm.h" + +class vtkDataSet; +class vtkImageData; +class vtkPolyData; +class vtkStructuredPoints; +class vtkStructuredGrid; +class vtkUnstructuredGrid; +class vtkRectilinearGrid; + +class VTK_FILTERING_EXPORT vtkDataSetAlgorithm : public vtkAlgorithm +{ +public: + static vtkDataSetAlgorithm *New(); + vtkTypeRevisionMacro(vtkDataSetAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkDataSet* GetOutput(); + vtkDataSet* GetOutput(int); + + // Description: + // Get the input data object. This method is not recommended for use, but + // lots of old style filters use it. + vtkDataObject* GetInput(); + + // Description: + // Get the output as vtkPolyData. + vtkPolyData *GetPolyDataOutput(); + + // Description: + // Get the output as vtkStructuredPoints. + vtkStructuredPoints *GetStructuredPointsOutput(); + + // Description: + // Get the output as vtkStructuredPoints. + vtkImageData *GetImageDataOutput(); + + // Description: + // Get the output as vtkStructuredGrid. + vtkStructuredGrid *GetStructuredGridOutput(); + + // Description: + // Get the output as vtkUnstructuredGrid. + vtkUnstructuredGrid *GetUnstructuredGridOutput(); + + // Description: + // Get the output as vtkRectilinearGrid. + vtkRectilinearGrid *GetRectilinearGridOutput(); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject*); + void SetInput(int, vtkDataObject*); + void SetInput(vtkDataSet*); + void SetInput(int, vtkDataSet*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(vtkDataSet*); + void AddInput(int, vtkDataSet*); + void AddInput(int, vtkDataObject*); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +protected: + vtkDataSetAlgorithm(); + ~vtkDataSetAlgorithm() {}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestDataObject(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) {return 1;}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) {return 1;}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) + { + return 1; + }; + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + + vtkDataObject *GetInput(int port); + +private: + vtkDataSetAlgorithm(const vtkDataSetAlgorithm&); // Not implemented. + void operator=(const vtkDataSetAlgorithm&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkDataSetAttributes.cxx b/Filtering/vtkDataSetAttributes.cxx new file mode 100644 index 0000000..c87d476 --- /dev/null +++ b/Filtering/vtkDataSetAttributes.cxx @@ -0,0 +1,1498 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetAttributes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetAttributes.h" +#include "vtkCell.h" +#include "vtkMath.h" +#include "vtkBitArray.h" +#include "vtkCharArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkShortArray.h" +#include "vtkUnsignedShortArray.h" +#include "vtkIntArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkLongArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIdTypeArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDataSetAttributes, "$Revision: 1.4.6.1 $"); +vtkStandardNewMacro(vtkDataSetAttributes); + +//-------------------------------------------------------------------------- +const char vtkDataSetAttributes +::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10] = +{ "Scalars", + "Vectors", + "Normals", + "TCoords", + "Tensors" }; + +const char vtkDataSetAttributes +::LongAttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][35] = +{ "vtkDataSetAttributes::SCALARS", + "vtkDataSetAttributes::VECTORS", + "vtkDataSetAttributes::NORMALS", + "vtkDataSetAttributes::TCOORDS", + "vtkDataSetAttributes::TENSORS" }; + +// Construct object with copying turned on for all data. +vtkDataSetAttributes::vtkDataSetAttributes() +{ + for(int attributeType=0; attributeTypeAttributeIndices[attributeType] = -1; + this->CopyAttributeFlags[attributeType] = 1; + } + this->TargetIndices=0; +} + +// Destructor for the vtkDataSetAttributes objects. +vtkDataSetAttributes::~vtkDataSetAttributes() +{ + this->Initialize(); + delete[] this->TargetIndices; + this->TargetIndices = 0; +} + +// Turn on copying of all data. +void vtkDataSetAttributes::CopyAllOn() +{ + this->vtkFieldData::CopyAllOn(); + this->CopyScalarsOn(); + this->CopyVectorsOn(); + this->CopyNormalsOn(); + this->CopyTCoordsOn(); + this->CopyTensorsOn(); +} + +// Turn off copying of all data. +void vtkDataSetAttributes::CopyAllOff() +{ + this->vtkFieldData::CopyAllOff(); + this->CopyScalarsOff(); + this->CopyVectorsOff(); + this->CopyNormalsOff(); + this->CopyTCoordsOff(); + this->CopyTensorsOff(); +} + +// Deep copy of data (i.e., create new data arrays and +// copy from input data). Note that attribute data is +// not copied. +void vtkDataSetAttributes::DeepCopy(vtkFieldData *fd) +{ + this->Initialize(); //free up memory + + vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(fd); + // If the source is a vtkDataSetAttributes + if (dsa) + { + int numArrays = fd->GetNumberOfArrays(); + int attributeType; + vtkDataArray *data, *newData; + + // Allocate space for numArrays + this->AllocateArrays(numArrays); + for ( int i=0; i < numArrays; i++ ) + { + data = fd->GetArray(i); + newData = data->NewInstance(); //instantiate same type of object + newData->DeepCopy(data); + newData->SetName(data->GetName()); + if ((attributeType=dsa->IsArrayAnAttribute(i)) != -1) + { + // If this array is an attribute in the source, make it so + // in the target as well. + this->SetAttribute(newData, attributeType); + } + else + { + this->AddArray(newData); + } + newData->Delete(); + } + // Copy the copy flags + for(attributeType=0; attributeTypeCopyAttributeFlags[attributeType] = + dsa->CopyAttributeFlags[attributeType]; + } + this->CopyFlags(dsa); + } + // If the source is field data, do a field data copy + else + { + this->vtkFieldData::DeepCopy(fd); + } + +} + +// Shallow copy of data (i.e., use reference counting). +void vtkDataSetAttributes::ShallowCopy(vtkFieldData *fd) +{ + this->Initialize(); //free up memory + + vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(fd); + // If the source is a vtkDataSetAttributes + if (dsa) + { + int numArrays = fd->GetNumberOfArrays(); + int attributeType; + + // Allocate space for numArrays + this->AllocateArrays(numArrays); + this->NumberOfActiveArrays = 0; + for ( int i=0; i < numArrays; i++ ) + { + this->NumberOfActiveArrays++; + this->SetArray(i, fd->GetArray(i)); + if ((attributeType=dsa->IsArrayAnAttribute(i)) != -1) + { + // If this array is an attribute in the source, make it so + // in the target as well. + this->SetActiveAttribute(i, attributeType); + } + } + // Copy the copy flags + for(attributeType=0; attributeTypeCopyAttributeFlags[attributeType] = + dsa->CopyAttributeFlags[attributeType]; + } + this->CopyFlags(dsa); + } + // If the source is field data, do a field data copy + else + { + this->vtkFieldData::ShallowCopy(fd); + } +} + +// Initialize all of the object's data to NULL +void vtkDataSetAttributes::InitializeFields() +{ + this->vtkFieldData::InitializeFields(); + for(int attributeType=0; attributeTypeAttributeIndices[attributeType] = -1; + } +} + +// Initialize all of the object's data to NULL +void vtkDataSetAttributes::Initialize() +{ +// +// We don't modify ourselves because the "ReleaseData" methods depend upon +// no modification when initialized. +// + +// Call superclass' Initialize() + this->vtkFieldData::Initialize(); +// +// Free up any memory +// + for(int attributeType=0; attributeTypeAttributeIndices[attributeType] = -1; + } +} + +// This method is used to determine which arrays +// will be copied to this object after PassData or PassNoReplaceData +vtkFieldData::BasicIterator vtkDataSetAttributes::ComputeRequiredArrays( + vtkDataSetAttributes* pd) +{ + // We need to do some juggling to find the number of arrays + // which will be passed. + + // First, find the number of arrays to be copied because they + // are in the list of _fields_ to be copied (and the actual data + // pointer is non-NULL). Also, we keep those indices in a list. + int* copyFlags = new int[pd->GetNumberOfArrays()]; + int index, i, numArrays = 0; + for(i=0; iGetNumberOfArrays(); i++) + { + const char* arrayName = pd->GetArrayName(i); + // If there is no blocker for the given array + // and both CopyAllOff and CopyOn for that array are not true + if ( (this->GetFlag(arrayName) != 0) && + !(this->DoCopyAllOff && (this->GetFlag(arrayName) != 1)) && + pd->GetArray(i)) + { + copyFlags[numArrays] = i; + numArrays++; + } + } + + // Next, we check the arrays to be copied because they are one of + // the _attributes_ to be copied (and the data array in non-NULL). + // We make sure that we don't count anything twice. + int alreadyCopied; + for(int attributeType=0; attributeTypeAttributeIndices[attributeType]; + int flag = this->GetFlag(pd->GetArrayName(index)); + // If this attribute is to be copied + if (this->CopyAttributeFlags[attributeType] && flag) + { + // Find out if it is also in the list of fields to be copied + if (pd->GetArray(index)) + { + alreadyCopied = 0; + for(i=0; i in the list of _fields_ to be copied or + // 2> in the list of _attributes_ to be copied. + // Note that NULL data arrays are not copied + vtkFieldData::BasicIterator it = this->ComputeRequiredArrays(dsa); + + if ( it.GetListSize() > this->NumberOfArrays ) + { + this->AllocateArrays(it.GetListSize()); + } + if (it.GetListSize() == 0) + { + return; + } + + // Since we are replacing, remove old attributes + int attributeType; //will change// + for(attributeType=0; attributeTypeCopyAttributeFlags[attributeType]) + { + this->RemoveArray(this->AttributeIndices[attributeType]); + this->AttributeIndices[attributeType] = -1; + } + } + + int i, arrayIndex; + for(i=it.BeginIndex(); !it.End(); i=it.NextIndex()) + { + arrayIndex = this->AddArray(dsa->GetArray(i)); + // If necessary, make the array an attribute + if ( ((attributeType = dsa->IsArrayAnAttribute(i)) != -1 ) && + this->CopyAttributeFlags[attributeType] ) + { + this->SetActiveAttribute(arrayIndex, attributeType); + } + } + } + else + { + this->vtkFieldData::PassData(fd); + } +} + + + + +//---------------------------------------------------------------------------- +// This is used in the imaging pipeline for copying arrays. +// CopyAllocate needs to be called before this method. +void vtkDataSetAttributes::CopyStructuredData(vtkDataSetAttributes *fromPd, + const int *inExt, const int *outExt) +{ + int i; + + for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); + i=this->RequiredArrays.NextIndex()) + { + vtkDataArray *inArray = fromPd->Data[i]; + vtkDataArray *outArray = this->Data[this->TargetIndices[i]]; + unsigned char *inPtr; + unsigned char *outPtr; + unsigned char *inZPtr; + unsigned char *outZPtr; + int inIncs[3]; + int outIncs[3]; + int rowLength; + int yIdx, zIdx; + + // Compute increments + inIncs[0] = inArray->GetDataTypeSize() * inArray->GetNumberOfComponents(); + inIncs[1] = inIncs[0] * (inExt[1]-inExt[0]+1); + inIncs[2] = inIncs[1] * (inExt[3]-inExt[2]+1); + outIncs[0] = inIncs[0]; + outIncs[1] = outIncs[0] * (outExt[1]-outExt[0]+1); + outIncs[2] = outIncs[1] * (outExt[3]-outExt[2]+1); + // Length of continuous data to copy (one row). + rowLength = (outExt[1]-outExt[0]+1)*outIncs[0]; + + // Make sure the input extents match the actual array lengths. + zIdx = (inExt[1]-inExt[0]+1)*(inExt[3]-inExt[2]+1)*(inExt[5]-inExt[4]+1); + if (inArray->GetNumberOfTuples() != zIdx) + { + vtkErrorMacro("Input extent (" << inExt[0] << ", " << inExt[1] << ", " + << inExt[2] << ", " << inExt[3] << ", " << inExt[4] << ", " + << inExt[5] << ") does not match array length: " << zIdx); + // Skip copying this array. + continue; + } + // Make sure the output extents match the actual array lengths. + zIdx = (outExt[1]-outExt[0]+1)*(outExt[3]-outExt[2]+1)*(outExt[5]-outExt[4]+1); + if (outArray->GetNumberOfTuples() != zIdx) + { + // The "CopyAllocate" method only sets the size, not the number of tuples. + outArray->SetNumberOfTuples(zIdx); + } + + // Get the starting input pointer. + inZPtr = (unsigned char*)(inArray->GetVoidPointer(0)); + // Shift to the start of the subextent. + inZPtr += (outExt[0]-outExt[0])*inIncs[0] + + (outExt[2] - outExt[2])*inIncs[1] + + (outExt[4] - outExt[4])*inIncs[2]; + + // Get output pointer. + outZPtr = (unsigned char*)(outArray->GetVoidPointer(0)); + + // Loop over z axis. + for (zIdx = outExt[4]; zIdx <= outExt[5]; ++zIdx) + { + inPtr = inZPtr; + outPtr = outZPtr; + for (yIdx = outExt[2]; yIdx <= outExt[3]; ++yIdx) + { + memcpy(outPtr, inPtr, rowLength); + inPtr += inIncs[1]; + outPtr += outIncs[1]; + } + inZPtr += inIncs[2]; + outZPtr += outIncs[2]; + } + } +} + + + + + +// Allocates point data for point-by-point (or cell-by-cell) copy operation. +// If sze=0, then use the input DataSetAttributes to create (i.e., find +// initial size of) new objects; otherwise use the sze variable. +void vtkDataSetAttributes::CopyAllocate(vtkDataSetAttributes* pd, + vtkIdType sze, vtkIdType ext) +{ + vtkDataArray* newDA; + int i; + + // Create various point data depending upon input + // + if ( !pd ) + { + return; + } + + this->RequiredArrays = this->ComputeRequiredArrays(pd); + if (this->RequiredArrays.GetListSize() == 0) + { + return; + } + delete[] this->TargetIndices; + this->TargetIndices = new int[pd->GetNumberOfArrays()]; + for(i=0; iGetNumberOfArrays(); i++) + { + this->TargetIndices[i] = -1; + } + + vtkDataArray* da=0; + // If we are not copying on self + if ( pd != this ) + { + int attributeType; + + for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); + i=this->RequiredArrays.NextIndex()) + { + // Create all required arrays + da = pd->GetArray(i); + newDA = da->NewInstance(); + newDA->SetNumberOfComponents(da->GetNumberOfComponents()); + newDA->SetName(da->GetName()); + if ( sze > 0 ) + { + newDA->Allocate(sze*da->GetNumberOfComponents(),ext); + } + else + { + newDA->Allocate(da->GetNumberOfTuples()); + } + newDA->SetLookupTable(da->GetLookupTable()); + this->TargetIndices[i] = this->AddArray(newDA); + // If necessary, make the array an attribute + if ( ((attributeType = pd->IsArrayAnAttribute(i)) != -1 ) && + this->CopyAttributeFlags[attributeType] ) + { + this->SetActiveAttribute(this->TargetIndices[i], attributeType); + } + newDA->Delete(); + } + } + else + { + // If copying on self, resize the arrays and initialize + // TargetIndices + for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); + i=this->RequiredArrays.NextIndex()) + { + da = pd->GetArray(i); + da->Resize(sze); + this->TargetIndices[i] = i; + } + } +} + +void vtkDataSetAttributes::RemoveArray(int index) +{ + if ( (index<0) || (index>=this->NumberOfActiveArrays)) + { + return; + } + this->vtkFieldData::RemoveArray(index); + int attributeType; + for(attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++) + { + if (this->AttributeIndices[attributeType] == index) + { + this->AttributeIndices[attributeType] = -1; + } + else if (this->AttributeIndices[attributeType] > index) + { + this->AttributeIndices[attributeType]--; + } + } +} + +// Copy the attribute data from one id to another. Make sure CopyAllocate() has +// been invoked before using this method. +void vtkDataSetAttributes::CopyData(vtkDataSetAttributes* fromPd, + vtkIdType fromId, vtkIdType toId) +{ + int i; + for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); + i=this->RequiredArrays.NextIndex()) + { + this->CopyTuple(fromPd->Data[i], this->Data[this->TargetIndices[i]], + fromId, toId); + } +} + +// Initialize point interpolation method. +void vtkDataSetAttributes::InterpolateAllocate(vtkDataSetAttributes* pd, + vtkIdType sze, vtkIdType ext) +{ + this->CopyAllocate(pd, sze, ext); +} + +// Interpolate data from points and interpolation weights. Make sure that the +// method InterpolateAllocate() has been invoked before using this method. +void vtkDataSetAttributes::InterpolatePoint(vtkDataSetAttributes *fromPd, + vtkIdType toId, vtkIdList *ptIds, + double *weights) +{ + int i; + for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); + i=this->RequiredArrays.NextIndex()) + { + this->InterpolateTuple(fromPd->Data[i], + this->Data[this->TargetIndices[i]], + toId, ptIds, weights); + } +} + +// Interpolate data from the two points p1,p2 (forming an edge) and an +// interpolation factor, t, along the edge. The weight ranges from (0,1), +// with t=0 located at p1. Make sure that the method InterpolateAllocate() +// has been invoked before using this method. +void vtkDataSetAttributes::InterpolateEdge(vtkDataSetAttributes *fromPd, + vtkIdType toId, vtkIdType p1, + vtkIdType p2, double t) +{ + int i; + for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); + i=this->RequiredArrays.NextIndex()) + { + this->InterpolateTuple(fromPd->Data[i], + this->Data[this->TargetIndices[i]], + toId, p1, p2, t); + } +} + +// Interpolate data from the two points p1,p2 (forming an edge) and an +// interpolation factor, t, along the edge. The weight ranges from (0,1), +// with t=0 located at p1. Make sure that the method InterpolateAllocate() +// has been invoked before using this method. +void vtkDataSetAttributes::InterpolateTime(vtkDataSetAttributes *from1, + vtkDataSetAttributes *from2, + vtkIdType id, double t) +{ + for(int attributeType=0; attributeTypeCopyAttributeFlags[attributeType]) + { + if (from1->GetAttribute(attributeType) && + from2->GetAttribute(attributeType)) + { + this->InterpolateTuple(from1->GetAttribute(attributeType), + from2->GetAttribute(attributeType), + this->GetAttribute(attributeType), id, t); + } + } + } +} + +template +void vtkDataSetAttributesCopyTuple(T* from, T* to, int numComp) +{ + for(int i=0; i < numComp; ++i) + { + *to++ = *from++; + } +} + +// Copy a tuple of data from one data array to another. This method (and +// following ones) assume that the fromData and toData objects are of the +// same type, and have the same number of components. This is true if you +// invoke CopyAllocate() or InterpolateAllocate(). +void vtkDataSetAttributes::CopyTuple(vtkDataArray *fromData, + vtkDataArray *toData, vtkIdType fromId, + vtkIdType toId) +{ + int i; + int numComp=fromData->GetNumberOfComponents(); + switch (fromData->GetDataType()) + { + vtkTemplateMacro( + void* vto = toData->WriteVoidPointer(toId*numComp, numComp); + void* vfrom = fromData->GetVoidPointer(fromId*numComp); + vtkDataSetAttributesCopyTuple(static_cast(vfrom), + static_cast(vto), numComp) + ); + case VTK_BIT: + { + vtkBitArray *from=(vtkBitArray *)fromData; + vtkBitArray *to=(vtkBitArray *)toData; + for (i=0; iInsertValue(toId+i, from->GetValue(fromId+i)); + } + } + break; + default: + vtkErrorMacro("Unsupported data type " << fromData->GetDataType() + << " during copy!"); + } +} + +template +void vtkDataSetAttributesInterpolateTuple(T* from, T* to, int numComp, + vtkIdType* ids, vtkIdType numIds, + double* weights) +{ + for(int i=0; i < numComp; ++i) + { + double c = 0; + for(vtkIdType j=0; j < numIds; ++j) + { + c += weights[j]*from[ids[j]*numComp+i]; + } + *to++ = static_cast(c); + } +} + +// double versions +void vtkDataSetAttributes::InterpolateTuple(vtkDataArray *fromData, + vtkDataArray *toData, + vtkIdType toId, vtkIdList *ptIds, + double *weights) +{ + int numComp=fromData->GetNumberOfComponents(), i; + vtkIdType j, numIds=ptIds->GetNumberOfIds(); + vtkIdType *ids=ptIds->GetPointer(0); + vtkIdType idx=toId*numComp; + double c; + + switch (fromData->GetDataType()) + { + case VTK_BIT: + { + vtkBitArray *from=(vtkBitArray *)fromData; + vtkBitArray *to=(vtkBitArray *)toData; + for (i=0; iGetValue(ids[j]*numComp+i); + } + to->InsertValue(idx+i, (int)c); + } + } + break; + vtkTemplateMacro( + void* vfrom = fromData->GetVoidPointer(0); + void* vto = toData->WriteVoidPointer(idx, numComp); + vtkDataSetAttributesInterpolateTuple(static_cast(vfrom), + static_cast(vto), + numComp, ids, numIds, weights) + ); + default: + vtkErrorMacro("Unsupported data type " << fromData->GetDataType() + << " during interpolation!"); + } +} + +template +void vtkDataSetAttributesInterpolateTuple(T* from, T* to, int numComp, + vtkIdType idx1, vtkIdType idx2, + double t) +{ + for(int i=0; i < numComp; ++i) + { + double c = (1.0 - t) * from[idx1+i] + t * from[idx2+i]; + *to++ = static_cast(c); + } +} + +void vtkDataSetAttributes::InterpolateTuple(vtkDataArray *fromData, + vtkDataArray *toData, + vtkIdType toId, vtkIdType id1, + vtkIdType id2, double t) +{ + int i, numComp=fromData->GetNumberOfComponents(); + vtkIdType idx=toId*numComp; + vtkIdType idx1=id1*numComp, idx2=id2*numComp; + double c; + + switch (fromData->GetDataType()) + { + case VTK_BIT: + { + vtkBitArray *from=(vtkBitArray *)fromData; + vtkBitArray *to=(vtkBitArray *)toData; + for (i=0; iGetValue(idx1+i)+ t * (from->GetValue(idx2+i) - from->GetValue(idx1+i)); + to->InsertValue(idx+i, (int)c); + } + } + break; + vtkTemplateMacro( + void* vfrom = fromData->GetVoidPointer(0); + void* vto = toData->WriteVoidPointer(idx, numComp); + vtkDataSetAttributesInterpolateTuple(static_cast(vfrom), + static_cast(vto), + numComp, idx1, idx2, t) + ); + default: + vtkErrorMacro("Unsupported data type " << fromData->GetDataType() + << " during interpolation!"); + } +} + +template +void vtkDataSetAttributesInterpolateTuple(T* from1, T* from2, T* to, + int numComp, vtkIdType idx, double t) +{ + for(int i=0; i < numComp; ++i) + { + vtkIdType ii = idx + i; + double c = (1.0 - t) * from1[ii] + t * from2[ii]; + *to++ = static_cast(c); + } +} + +void vtkDataSetAttributes::InterpolateTuple(vtkDataArray *fromData1, + vtkDataArray *fromData2, + vtkDataArray *toData, vtkIdType id, + double t) +{ + int i, numComp=fromData1->GetNumberOfComponents(); + vtkIdType idx=id*numComp, ii; + double c; + + switch (fromData1->GetDataType()) + { + case VTK_BIT: + { + vtkBitArray *from1=(vtkBitArray *)fromData1; + vtkBitArray *from2=(vtkBitArray *)fromData2; + vtkBitArray *to=(vtkBitArray *)toData; + for (i=0; iGetValue(ii) + t * (from2->GetValue(ii) - from1->GetValue(ii)); + to->InsertValue(ii, (int)c); + } + } + break; + vtkTemplateMacro( + void* vfrom1 = fromData1->GetVoidPointer(0); + void* vfrom2 = fromData2->GetVoidPointer(0); + void* vto = toData->WriteVoidPointer(idx, numComp); + vtkDataSetAttributesInterpolateTuple(static_cast(vfrom1), + static_cast(vfrom2), + static_cast(vto), + numComp, idx, t) + ); + default: + vtkErrorMacro("Unsupported data type " << fromData1->GetDataType() + << " during interpolation!"); + } +} + +int vtkDataSetAttributes::SetScalars(vtkDataArray* da) +{ + return this->SetAttribute(da, SCALARS); +} + +int vtkDataSetAttributes::SetActiveScalars(const char* name) +{ + return this->SetActiveAttribute(name, SCALARS); +} + +int vtkDataSetAttributes::SetActiveAttribute(const char* name, + int attributeType) +{ + int index; + this->GetArray(name, index); + return this->SetActiveAttribute(index, attributeType); +} + +vtkDataArray* vtkDataSetAttributes::GetScalars() +{ + return this->GetAttribute(SCALARS); +} + +int vtkDataSetAttributes::SetVectors(vtkDataArray* da) +{ +return this->SetAttribute(da, VECTORS); +} + +int vtkDataSetAttributes::SetActiveVectors(const char* name) +{ + return this->SetActiveAttribute(name, VECTORS); +} + +vtkDataArray* vtkDataSetAttributes::GetVectors() +{ + return this->GetAttribute(VECTORS); +} + +int vtkDataSetAttributes::SetNormals(vtkDataArray* da) +{ + return this->SetAttribute(da, NORMALS); +} + +int vtkDataSetAttributes::SetActiveNormals(const char* name) +{ + return this->SetActiveAttribute(name, NORMALS); +} + +vtkDataArray* vtkDataSetAttributes::GetNormals() +{ + return this->GetAttribute(NORMALS); +} + +int vtkDataSetAttributes::SetTCoords(vtkDataArray* da) +{ + return this->SetAttribute(da, TCOORDS); +} + +int vtkDataSetAttributes::SetActiveTCoords(const char* name) +{ + return this->SetActiveAttribute(name, TCOORDS); +} +vtkDataArray* vtkDataSetAttributes::GetTCoords() +{ + return this->GetAttribute(TCOORDS); +} + +int vtkDataSetAttributes::SetTensors(vtkDataArray* da) +{ + return this->SetAttribute(da, TENSORS); +} + +int vtkDataSetAttributes::SetActiveTensors(const char* name) +{ + return this->SetActiveAttribute(name, TENSORS); +} + +vtkDataArray* vtkDataSetAttributes::GetTensors() +{ + return this->GetAttribute(TENSORS); +} + +vtkDataArray* vtkDataSetAttributes::GetScalars(const char* name) +{ + if (name == NULL || name[0] == '\0') + { + return this->GetScalars(); + } + return this->GetArray(name); +} + +vtkDataArray* vtkDataSetAttributes::GetVectors(const char* name) +{ + if (name == NULL || name[0] == '\0') + { + return this->GetVectors(); + } + return this->GetArray(name); +} + +vtkDataArray* vtkDataSetAttributes::GetNormals(const char* name) +{ + if (name == NULL || name[0] == '\0') + { + return this->GetNormals(); + } + return this->GetArray(name); +} + +vtkDataArray* vtkDataSetAttributes::GetTCoords(const char* name) +{ + if (name == NULL || name[0] == '\0') + { + return this->GetTCoords(); + } + return this->GetArray(name); +} + +vtkDataArray* vtkDataSetAttributes::GetTensors(const char* name) +{ + if (name == NULL || name[0] == '\0') + { + return this->GetTensors(); + } + return this->GetArray(name); +} + +int vtkDataSetAttributes::SetActiveAttribute(int index, int attributeType) +{ + if ( (index >= 0) && (index < this->GetNumberOfArrays())) + { + if (!this->CheckNumberOfComponents(this->Data[index], attributeType)) + { + vtkWarningMacro("Can not set attribute " + << vtkDataSetAttributes::AttributeNames[attributeType] + << ". Incorrect number of components."); + return -1; + } + this->AttributeIndices[attributeType] = index; + this->Modified(); + return index; + } + else if (index == -1) + { + this->AttributeIndices[attributeType] = index; + this->Modified(); + } + + return -1; +} + +const int vtkDataSetAttributes +::NumberOfAttributeComponents[vtkDataSetAttributes::NUM_ATTRIBUTES] = +{ 0, + 3, + 3, + 3, + 9}; + +// Scalars set to NOLIMIT +const int vtkDataSetAttributes +::AttributeLimits[vtkDataSetAttributes::NUM_ATTRIBUTES] = +{ NOLIMIT, + EXACT, + EXACT, + MAX, + EXACT }; + +int vtkDataSetAttributes::CheckNumberOfComponents(vtkDataArray* da, + int attributeType) +{ + int numComp = da->GetNumberOfComponents(); + + if ( vtkDataSetAttributes::AttributeLimits[attributeType] == MAX ) + { + if ( numComp > + vtkDataSetAttributes::NumberOfAttributeComponents[attributeType] ) + { + return 0; + } + else + { + return 1; + } + } + else if ( vtkDataSetAttributes::AttributeLimits[attributeType] == EXACT ) + { + if ( numComp != + vtkDataSetAttributes::NumberOfAttributeComponents[attributeType] ) + { + return 0; + } + else + { + return 1; + } + } + else if ( vtkDataSetAttributes::AttributeLimits[attributeType] == NOLIMIT ) + { + return 1; + } + else + { + return 0; + } +} + +vtkDataArray* vtkDataSetAttributes::GetAttribute(int attributeType) +{ + int index = this->AttributeIndices[attributeType]; + if (index == -1) + { + return 0; + } + else + { + return this->Data[index]; + } +} + +// This method lets the user add an array and make it the current +// scalars, vectors etc... (this is determined by the attribute type +// which is an enum defined vtkDataSetAttributes) +int vtkDataSetAttributes::SetAttribute(vtkDataArray* da, int attributeType) +{ + if (da && !this->CheckNumberOfComponents(da, attributeType)) + { + vtkWarningMacro("Can not set attribute " + << vtkDataSetAttributes::AttributeNames[attributeType] + << ". Incorrect number of components."); + return -1; + } + + int currentAttribute = this->AttributeIndices[attributeType]; + + // If there is an existing attribute, replace it + if ( (currentAttribute >= 0) && + (currentAttribute < this->GetNumberOfArrays()) ) + { + if (this->GetArray(currentAttribute) == da) + { + return currentAttribute; + } + this->RemoveArray(currentAttribute); + } + + if (da) + { + // Add the array + currentAttribute = this->AddArray(da); + this->AttributeIndices[attributeType] = currentAttribute; + } + else + { + this->AttributeIndices[attributeType] = -1; //attribute of this type doesn't exist + } + this->Modified(); + return this->AttributeIndices[attributeType]; +} + +void vtkDataSetAttributes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + // Print the copy flags + os << indent << "Copy Flags: ( "; + for (int i=0; iCopyAttributeFlags[i] << " "; + } + os << ")" << endl; + + // Now print the various attributes + vtkDataArray* da; + int attributeType; + for (attributeType=0; attributeTypeGetAttribute(attributeType)) ) + { + os << endl; + da->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)" << endl; + } + } + +} + +void vtkDataSetAttributes::GetAttributeIndices(int* indexArray) +{ + for(int i=0; iAttributeIndices[i]; + } +} + +int vtkDataSetAttributes::IsArrayAnAttribute(int idx) +{ + for (int i=0; iAttributeIndices[i] ) + { + return i; + } + } + return -1; +} + +void vtkDataSetAttributes::SetCopyAttribute (int index, int value) +{ + if (this->CopyAttributeFlags[ index ] != value) + { + this->CopyAttributeFlags[ index ] = value; + this->Modified(); + } +} + +void vtkDataSetAttributes::SetCopyScalars(int i) +{ + this->SetCopyAttribute(SCALARS, i); +} +int vtkDataSetAttributes::GetCopyScalars() { + return this->CopyAttributeFlags[SCALARS]; +} + +void vtkDataSetAttributes::SetCopyVectors(int i) +{ + this->SetCopyAttribute(VECTORS, i); +} +int vtkDataSetAttributes::GetCopyVectors() +{ + return this->CopyAttributeFlags[VECTORS]; +} + +void vtkDataSetAttributes::SetCopyNormals(int i) +{ + this->SetCopyAttribute(NORMALS, i); +} +int vtkDataSetAttributes::GetCopyNormals() +{ + return this->CopyAttributeFlags[NORMALS]; +} + +void vtkDataSetAttributes::SetCopyTCoords(int i) +{ + this->SetCopyAttribute(TCOORDS, i); +} +int vtkDataSetAttributes::GetCopyTCoords() +{ + return this->CopyAttributeFlags[TCOORDS]; +} + +void vtkDataSetAttributes::SetCopyTensors(int i) +{ + this->SetCopyAttribute(TENSORS, i); +} +int vtkDataSetAttributes::GetCopyTensors() { + return this->CopyAttributeFlags[TENSORS]; +} + +void vtkDataSetAttributes::RemoveArray(const char *name) +{ + int i; + this->GetArray(name, i); + this->RemoveArray(i); +} + +void vtkDataSetAttributes::CopyAllocate(vtkDataSetAttributes::FieldList& list, + vtkIdType sze, vtkIdType ext) +{ + vtkDataArray* newDA=0; + int i; + + // Allocate attributes if any + for (i=0; i < list.NumberOfFields; i++) + { + if ( list.FieldIndices[i] >= 0 ) + { + newDA = vtkDataArray::CreateDataArray(list.FieldTypes[i]); + newDA->SetName(list.Fields[i]); + newDA->SetNumberOfComponents(list.FieldComponents[i]); + + if ( sze > 0 ) + { + newDA->Allocate(sze,ext); + } + else + { + newDA->Allocate(list.NumberOfTuples,ext); + } + newDA->SetLookupTable(list.LUT[i]); + + // If attribute data, do something extra + if ( i < NUM_ATTRIBUTES ) + { + if ( this->CopyAttributeFlags[i] ) + { + list.FieldIndices[i] = this->AddArray(newDA); + this->SetActiveAttribute(list.FieldIndices[i], i); + } + else + { + list.FieldIndices[i] = -1; + } + } + else //check if this field is to be copied + { + if ( (this->GetFlag(list.Fields[i]) != 0) && + !(this->DoCopyAllOff && (this->GetFlag(list.Fields[i]) != 1)) ) + { + list.FieldIndices[i] = this->AddArray(newDA); + } + else + { + list.FieldIndices[i] = -1; + } + } + + newDA->Delete(); //okay, reference counting + }//data array defined + } +} + +// Description: +// A special form of CopyData() to be used with FieldLists. Use it when you are +// copying data from a set of vtkDataSetAttributes. Make sure that you have +// called the special form of CopyAllocate that accepts FieldLists. +void vtkDataSetAttributes::CopyData(vtkDataSetAttributes::FieldList& list, + vtkDataSetAttributes* fromDSA, + int idx, vtkIdType fromId, vtkIdType toId) +{ + vtkDataArray *fromDA; + vtkDataArray *toDA; + + for (int i=0; i < list.NumberOfFields; i++) + { + if ( list.FieldIndices[i] >= 0 ) + { + toDA = this->GetArray(list.FieldIndices[i]); + fromDA = fromDSA->GetArray(list.DSAIndices[idx][i]); + this->CopyTuple(fromDA, toDA, fromId, toId); + } + } +} + +// FieldList support --------------------------------------------------------- +// To perform intersection of attribute data, use IntializeFieldList() to grab +// an initial vtkDataSetAttributes. Then use IntersectFieldList() to add (and +// intersect) additional vtkDataSetAttributes. +void vtkDataSetAttributes::FieldList::InitializeFieldList(vtkDataSetAttributes* dsa) +{ + int i, idx; + + this->ClearFields(); + + // Allocate space for the arrays plus five attributes + this->NumberOfFields = dsa->GetNumberOfArrays() + NUM_ATTRIBUTES; + this->Fields = new char*[this->NumberOfFields]; + this->FieldTypes = new int [this->NumberOfFields]; + this->FieldComponents = new int [this->NumberOfFields]; + this->FieldIndices = new int [this->NumberOfFields]; + this->LUT = new vtkLookupTable* [this->NumberOfFields]; + for(i=0; i < this->NumberOfFields; i++) + { + this->Fields[i] = 0; + this->FieldTypes[i] = -1; + this->FieldComponents[i] = 0; + this->FieldIndices[i] = -1; + } + this->CurrentInput = 0; + this->NumberOfTuples = 0; + + //there may be no data hence dsa->Data + for(i=0; dsa->Data && i < dsa->GetNumberOfArrays(); i++) + { + if ( (idx=dsa->IsArrayAnAttribute(i)) >= 0 ) //it's an attribute + { + this->FieldIndices[idx] = idx; + this->SetField(idx, dsa->Data[i]); + } + else + { + this->FieldIndices[NUM_ATTRIBUTES+i] = i; + this->SetField(NUM_ATTRIBUTES+i, dsa->Data[i]); + } + } + + // The first dataset is added to the field list + this->IntersectFieldList(dsa); +} + +void vtkDataSetAttributes::FieldList::IntersectFieldList(vtkDataSetAttributes* dsa) +{ + int i; + vtkDataArray *da; + + // Initialize the indices for this dataset + this->DSAIndices[this->CurrentInput] = new int [this->NumberOfFields]; + for (i=0; i < this->NumberOfFields; i++) + { + this->DSAIndices[this->CurrentInput][i]= -1; + } + + // Keep a running total of the number of tuples...might be useful + // for later allocation. + if ( (da=dsa->GetArray(0)) ) + { + this->NumberOfTuples += da->GetNumberOfTuples(); + } + + // Intersect the attributes + int attributeIndices[NUM_ATTRIBUTES]; + dsa->GetAttributeIndices(attributeIndices); + for(i=0; i < NUM_ATTRIBUTES; i++) + { + if ( this->FieldIndices[i] >= 0 ) + { + da = dsa->GetAttribute(i); + if ((da) && (da->GetDataType() == this->FieldTypes[i]) && + (da->GetNumberOfComponents() == this->FieldComponents[i])) + { + this->DSAIndices[this->CurrentInput][i] = attributeIndices[i]; + } + else + { + this->FieldIndices[i] = -1; //Attribute not present + } + } + } + // Intersect the fields + int index; + for(i=NUM_ATTRIBUTES; i < this->NumberOfFields; i++) + { + if (this->FieldIndices[i] >= 0) + { + da = dsa->GetArray(this->Fields[i], index); + if ((da) && (da->GetDataType() == this->FieldTypes[i]) && + (da->GetNumberOfComponents() == this->FieldComponents[i])) + { + this->DSAIndices[this->CurrentInput][i] = index; + } + else + { + this->FieldIndices[i] = -1; //Field not present + } + } + } + + + this->CurrentInput++; +} + +int vtkDataSetAttributes::FieldList::IsAttributePresent(int attrType) +{ + return this->FieldIndices[attrType]; +} + + +vtkDataSetAttributes::FieldList::FieldList(int numInputs) +{ + this->Fields = 0; + this->FieldTypes = 0; + this->FieldComponents = 0; + this->FieldIndices = 0; + this->NumberOfFields = 0; + this->LUT = 0; + this->NumberOfDSAIndices = numInputs; + this->DSAIndices = new int*[numInputs]; + for (int i=0; iDSAIndices[i] = 0; + } +} + +vtkDataSetAttributes::FieldList::~FieldList() +{ + this->ClearFields(); + delete [] this->DSAIndices; + this->DSAIndices = 0; +} + +void vtkDataSetAttributes::FieldList::ClearFields() +{ + if ( this->Fields ) + { + for (int i=0; iNumberOfFields; i++) + { + delete [] this->Fields[i]; + this->Fields[i] = 0; + } + } + if ( this->DSAIndices ) + { + for (int i=0; iNumberOfDSAIndices; i++) + { + delete[] this->DSAIndices[i]; + this->DSAIndices[i] = 0; + } + } + delete [] this->LUT; + this->LUT = 0; + delete [] this->Fields; + this->Fields = 0; + delete [] this->FieldTypes; + this->FieldTypes = 0; + delete [] this->FieldComponents; + this->FieldComponents = 0; + delete [] this->FieldIndices; + this->FieldIndices = 0; + + this->NumberOfFields = 0; + this->CurrentInput = 0; +} + +void vtkDataSetAttributes::FieldList::SetField(int index, vtkDataArray *da) +{ + const char* name=da->GetName(); + int dataType=da->GetDataType(); + vtkLookupTable *lut=da->GetLookupTable(); + + if ( this->Fields[index] ) + { + delete [] this->Fields[index]; + this->Fields[index] = 0; + } + + this->FieldTypes[index] = dataType; + this->FieldComponents[index] = da->GetNumberOfComponents(); + this->LUT[index] = lut; + if (name) + { + int len = static_cast(strlen(name)); + if (len > 0) + { + this->Fields[index] = new char[len+1]; + strcpy(this->Fields[index], name); + } + } + else + { + this->Fields[index] = 0; + } + +} + +void vtkDataSetAttributes::FieldList::RemoveField(const char *name) +{ + if ( !name ) + { + return; + } + + for (int i=NUM_ATTRIBUTES; i < this->NumberOfFields; i++) + { + if ( this->Fields[i] && !strcmp(this->Fields[i],name) ) + { + delete [] this->Fields[i]; + this->Fields[i] = 0; + this->FieldIndices[i] = -1; + return; + } + } +} + + +const char* vtkDataSetAttributes::GetAttributeTypeAsString(int attributeType) +{ + if (attributeType < 0 || attributeType >= NUM_ATTRIBUTES) + { + vtkGenericWarningMacro("Bad attribute type."); + return NULL; + } + return vtkDataSetAttributes::AttributeNames[attributeType]; +} + +//-------------------------------------------------------------------------- +const char* vtkDataSetAttributes::GetLongAttributeTypeAsString(int attributeType) +{ + if (attributeType < 0 || attributeType >= NUM_ATTRIBUTES) + { + vtkGenericWarningMacro("Bad attribute type."); + return NULL; + } + return vtkDataSetAttributes::LongAttributeNames[attributeType]; +} diff --git a/Filtering/vtkDataSetAttributes.h b/Filtering/vtkDataSetAttributes.h new file mode 100644 index 0000000..466b7f9 --- /dev/null +++ b/Filtering/vtkDataSetAttributes.h @@ -0,0 +1,463 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetAttributes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetAttributes - represent and manipulate attribute data in a dataset +// .SECTION Description +// vtkDataSetAttributes is a class that is used to represent and manipulate +// attribute data (e.g., scalars, vectors, normals, texture coordinates, +// tensors, and field data) Special methods are provided to work with filter +// objects, such as passing data through filter, copying data from one +// attribute set to another, and interpolating data given cell interpolation +// weights. + +#ifndef __vtkDataSetAttributes_h +#define __vtkDataSetAttributes_h + +#include "vtkFieldData.h" + +class VTK_FILTERING_EXPORT vtkDataSetAttributes : public vtkFieldData +{ +public: + // Description: + // Construct object with copying turned on for all data. + static vtkDataSetAttributes *New(); + + vtkTypeRevisionMacro(vtkDataSetAttributes,vtkFieldData); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initialize all of the object's data to NULL + // Also, clear the copy flags. + virtual void Initialize(); + + // Description: + // Attributes have a chance to bring themselves up to date; right + // now this is ignored. + virtual void Update() {} + + // Description: + // Pass entire arrays of input data through to output. Obey the "copy" + // flags. When passing a field, the following copying rules are + // followed: 1) Check if a field is an attribute, if yes and if there + // is a copy flag for that attribute (on or off), obey the flag for + // that attribute, ignore (2) and (3), 2) if there is a copy field for + // that field (on or off), obey the flag, ignore (3) 3) obey + // CopyAllOn/Off + virtual void PassData(vtkFieldData* fd); + + // Description: + // Allocates point data for point-by-point (or cell-by-cell) copy operation. + // If sze=0, then use the input DataSetAttributes to create (i.e., find + // initial size of) new objects; otherwise use the sze variable. + // Note that pd HAS to be the vtkDataSetAttributes object which + // will later be used with CopyData. If this is not the case, + // consider using the alternative forms of CopyAllocate and CopyData. + // ext is no longer used. + void CopyAllocate(vtkDataSetAttributes* pd, vtkIdType sze=0, + vtkIdType ext=1000); + + // Description: + // Copy the attribute data from one id to another. Make sure CopyAllocate() + // has been invoked before using this method. When copying a field, + // the following copying rules are + // followed: 1) Check if a field is an attribute, if yes and if there + // is a copy flag for that attribute (on or off), obey the flag for + // that attribute, ignore (2) and (3), 2) if there is a copy field for + // that field (on or off), obey the flag, ignore (3) 3) obey + // CopyAllOn/Off + void CopyData(vtkDataSetAttributes *fromPd, vtkIdType fromId, vtkIdType toId); + + // Description: + // Initialize point interpolation method. + // Note that pd HAS to be the vtkDataSetAttributes object which + // will later be used with InterpolatePoint or InterpolateEdge. + // ext is no longer used. + void InterpolateAllocate(vtkDataSetAttributes* pd, vtkIdType sze=0, + vtkIdType ext=1000); + + // Description: + // This method is used to copy data arrays in images. + // You should not call "CopyAllocate" before calling this method. + // This method is called once to copy all of the data. + // If the two extents are the same, this method calls "PassData". + void CopyStructuredData(vtkDataSetAttributes *inDsa, + const int *inExt, const int *outExt); + + // Description: + // Interpolate data set attributes from other data set attributes + // given cell or point ids and associated interpolation weights. + void InterpolatePoint(vtkDataSetAttributes *fromPd, vtkIdType toId, + vtkIdList *ids, double *weights); + + // Description: + // Interpolate data from the two points p1,p2 (forming an edge) and an + // interpolation factor, t, along the edge. The weight ranges from (0,1), + // with t=0 located at p1. Make sure that the method InterpolateAllocate() + // has been invoked before using this method. + void InterpolateEdge(vtkDataSetAttributes *fromPd, vtkIdType toId, + vtkIdType p1, vtkIdType p2, double t); + + // Description: + // Interpolate data from the same id (point or cell) at different points + // in time (parameter t). Two input data set attributes objects are input. + // The parameter t lies between (0<=t<=1). IMPORTANT: it is assumed that + // the number of attributes and number of components is the same for both + // from1 and from2, and the type of data for from1 and from2 are the same. + // Make sure that the method InterpolateAllocate() has been invoked before + // using this method. + void InterpolateTime(vtkDataSetAttributes *from1, + vtkDataSetAttributes *from2, + vtkIdType id, double t); + + // Description: + // Deep copy of data (i.e., create new data arrays and + // copy from input data). + virtual void DeepCopy(vtkFieldData *pd); + + // Description: + // Shallow copy of data (i.e., use reference counting). + virtual void ShallowCopy(vtkFieldData *pd); + + // Description: + // Set/Get the scalar data. + int SetScalars(vtkDataArray* da); + int SetActiveScalars(const char* name); + vtkDataArray* GetScalars(); + + // Description: + // Set/Get the vector data. + int SetVectors(vtkDataArray* da); + int SetActiveVectors(const char* name); + vtkDataArray* GetVectors(); + + // Description: + // Set/get the normal data. + int SetNormals(vtkDataArray* da); + int SetActiveNormals(const char* name); + vtkDataArray* GetNormals(); + + // Description: + // Set/Get the texture coordinate data. + int SetTCoords(vtkDataArray* da); + int SetActiveTCoords(const char* name); + vtkDataArray* GetTCoords(); + + // Description: + // Set/Get the tensor data. + int SetTensors(vtkDataArray* da); + int SetActiveTensors(const char* name); + vtkDataArray* GetTensors(); + + // Description: + // This will first look for an array with the correct name. + // If one exists, it is returned. Otherwise, the name argument + // is ignored, and the active attribute is returned. + vtkDataArray* GetScalars(const char* name); + vtkDataArray* GetVectors(const char* name); + vtkDataArray* GetNormals(const char* name); + vtkDataArray* GetTCoords(const char* name); + vtkDataArray* GetTensors(const char* name); + + // Description: + // Make the array with the given name the active attribute. + // Attribute types are: + // vtkDataSetAttributes::SCALARS = 0 + // vtkDataSetAttributes::VECTORS = 1 + // vtkDataSetAttributes::NORMALS = 2 + // vtkDataSetAttributes::TCOORDS = 3 + // vtkDataSetAttributes::TENSORS = 4 + // Returns the index of the array if succesful, -1 if the array + // is not in the list of arrays. + int SetActiveAttribute(const char* name, int attributeType); + + // Description: + // Make the array with the given index the active attribute. + int SetActiveAttribute(int index, int attributeType); + + // Description: + // Specify whether to copy the data attribute referred to by index i. + void SetCopyAttribute (int index, int value); + + // Description: + // Turn on/off the copying of scalar data. + // During the copy/pass, the following rules are followed for each + // array: + // 1. If the copy flag for an attribute is set (on or off), it is applied. + // This overrides rules 2 and 3. + // 2. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 3. + // 3. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + void SetCopyScalars(int i); + int GetCopyScalars(); + vtkBooleanMacro(CopyScalars, int); + + // Description: + // Turn on/off the copying of vector data. + // During the copy/pass, the following rules are followed for each + // array: + // 1. If the copy flag for an attribute is set (on or off), it is applied. + // This overrides rules 2 and 3. + // 2. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 3. + // 3. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + void SetCopyVectors(int i); + int GetCopyVectors(); + vtkBooleanMacro(CopyVectors, int); + + // Description: + // Turn on/off the copying of normals data. + // During the copy/pass, the following rules are followed for each + // array: + // 1. If the copy flag for an attribute is set (on or off), it is applied. + // This overrides rules 2 and 3. + // 2. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 3. + // 3. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + void SetCopyNormals(int i); + int GetCopyNormals(); + vtkBooleanMacro(CopyNormals, int); + + // Description: + // Turn on/off the copying of texture coordinates data. + // During the copy/pass, the following rules are followed for each + // array: + // 1. If the copy flag for an attribute is set (on or off), it is applied. + // This overrides rules 2 and 3. + // 2. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 3. + // 3. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + void SetCopyTCoords(int i); + int GetCopyTCoords(); + vtkBooleanMacro(CopyTCoords, int); + + // Description: + // Turn on/off the copying of tensor data. + // During the copy/pass, the following rules are followed for each + // array: + // 1. If the copy flag for an attribute is set (on or off), it is applied. + // This overrides rules 2 and 3. + // 2. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 3. + // 3. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + void SetCopyTensors(int i); + int GetCopyTensors(); + vtkBooleanMacro(CopyTensors, int); + + // Description: + // Turn on copying of all data. + // During the copy/pass, the following rules are followed for each + // array: + // 1. If the copy flag for an attribute is set (on or off), it is applied. + // This overrides rules 2 and 3. + // 2. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 3. + // 3. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + virtual void CopyAllOn(); + + // Description: + // Turn off copying of all data. + // During the copy/pass, the following rules are followed for each + // array: + // 1. If the copy flag for an attribute is set (on or off), it is applied. + // This overrides rules 2 and 3. + // 2. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 3. + // 3. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + virtual void CopyAllOff(); + + // Description: + // Copy a tuple of data from one data array to another. This method (and + // following ones) assume that the fromData and toData objects are of the + // same type, and have the same number of components. This is true if you + // invoke CopyAllocate() or InterpolateAllocate(). + void CopyTuple(vtkDataArray *fromData, vtkDataArray *toData, + vtkIdType fromId, vtkIdType toId); + + // Description: + // Get the field data array indices corresponding to scalars, + // vectors, tensors, etc. + void GetAttributeIndices(int* indexArray); + + // Description: + // Determine whether a data array of index idx is considered a data set + // attribute (i.e., scalar, vector, tensor, etc). Return less-than zero + // if it is, otherwise an index 0<=idxNumberOfFields; } + int GetFieldIndex(int i) { return this->FieldIndices[i]; } + int GetDSAIndex(int index, int i) { return this->DSAIndices[index][i]; } + + friend class vtkDataSetAttributes; + + protected: + FieldList(const FieldList&) {} //prevent these methods from being used + void operator=(const FieldList&) {} + + private: + void SetField(int index, vtkDataArray *da); + void RemoveField(const char *name); + void ClearFields(); + + //These keep track of what is common across datasets + char** Fields; //the names of the fields (first five are named attributes) + int *FieldTypes; //the types of the fields (first five are named + //attributes) + int *FieldComponents; //the number of components in each fields + // (first five are named attributes) + int *FieldIndices; //output data array index + // (first five are named attributes) + vtkLookupTable **LUT; //luts associated with each array + vtkIdType NumberOfTuples; //a running total of values + int NumberOfFields; //the number of fields + + //For every vtkDataSetAttributes that are processed, keep track of the + //indices into various things. The indices are organized so that the + //first NUM_ATTRIBUTES refer to attributes, the next refer to the + //non-attribute fields, for a total of NUM_ATTRIBUTES + NumberOfFields. + //CurrentInput is the current input being processed. + int **DSAIndices; + int NumberOfDSAIndices; + int CurrentInput; + }; + +//ETX +}; + +#endif + + diff --git a/Filtering/vtkDataSetCollection.cxx b/Filtering/vtkDataSetCollection.cxx new file mode 100644 index 0000000..0455562 --- /dev/null +++ b/Filtering/vtkDataSetCollection.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDataSetCollection, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkDataSetCollection); diff --git a/Filtering/vtkDataSetCollection.h b/Filtering/vtkDataSetCollection.h new file mode 100644 index 0000000..297a3ad --- /dev/null +++ b/Filtering/vtkDataSetCollection.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetCollection - maintain an unordered list of dataset objects +// .SECTION Description +// vtkDataSetCollection is an object that creates and manipulates lists of +// datasets. See also vtkCollection and subclasses. + +#ifndef __vtkDataSetCollection_h +#define __vtkDataSetCollection_h + +#include "vtkCollection.h" + +#include "vtkDataSet.h" // Needed for inline methods. + +class VTK_FILTERING_EXPORT vtkDataSetCollection : public vtkCollection +{ +public: + static vtkDataSetCollection *New(); + vtkTypeRevisionMacro(vtkDataSetCollection,vtkCollection); + + // Description: + // Add a dataset to the list. + void AddItem(vtkDataSet *ds) { + this->vtkCollection::AddItem((vtkObject *)ds);}; + + // Description: + // Get the next dataset in the list. + vtkDataSet *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + vtkDataSet *GetNextDataSet() { + return static_cast(this->GetNextItemAsObject());}; + + // Description: + // Get the ith dataset in the list. + vtkDataSet *GetItem(int i) { + return static_cast(this->GetItemAsObject(i));}; + vtkDataSet *GetDataSet(int i) { + return static_cast(this->GetItemAsObject(i));}; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkDataSet *GetNextDataSet(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkDataSetCollection() {}; + ~vtkDataSetCollection() {}; + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkDataSetCollection(const vtkDataSetCollection&); // Not implemented. + void operator=(const vtkDataSetCollection&); // Not implemented. +}; + + +#endif diff --git a/Filtering/vtkDataSetSource.cxx b/Filtering/vtkDataSetSource.cxx new file mode 100644 index 0000000..fef1bcc --- /dev/null +++ b/Filtering/vtkDataSetSource.cxx @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetSource.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkDataSet.h" + +vtkCxxRevisionMacro(vtkDataSetSource, "$Revision: 1.17 $"); + +vtkDataSetSource::vtkDataSetSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataSet *vtkDataSetSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Outputs[0]); +} + +//---------------------------------------------------------------------------- +void vtkDataSetSource::SetOutput(vtkDataSet *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + +//---------------------------------------------------------------------------- +vtkDataSet *vtkDataSetSource::GetOutput(int idx) +{ + return static_cast( this->vtkSource::GetOutput(idx) ); +} + +//---------------------------------------------------------------------------- +int vtkDataSetSource::FillOutputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetSource.h b/Filtering/vtkDataSetSource.h new file mode 100644 index 0000000..43d2361 --- /dev/null +++ b/Filtering/vtkDataSetSource.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetSource - abstract class whose subclasses generate datasets +// .SECTION Description +// vtkDataSetSource is an abstract class whose subclasses generate datasets. + +#ifndef __vtkDataSetSource_h +#define __vtkDataSetSource_h + +#include "vtkSource.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkDataSetSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkDataSetSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this source. + vtkDataSet *GetOutput(); + vtkDataSet *GetOutput(int idx); + + void SetOutput(vtkDataSet *); + +protected: + vtkDataSetSource(); + ~vtkDataSetSource() {}; + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkDataSetSource(const vtkDataSetSource&); // Not implemented. + void operator=(const vtkDataSetSource&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkDataSetToDataSetFilter.cxx b/Filtering/vtkDataSetToDataSetFilter.cxx new file mode 100644 index 0000000..f77ade3 --- /dev/null +++ b/Filtering/vtkDataSetToDataSetFilter.cxx @@ -0,0 +1,267 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToDataSetFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetToDataSetFilter.h" + +#include "vtkDemandDrivenPipeline.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPolyData.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkRectilinearGrid.h" + +vtkCxxRevisionMacro(vtkDataSetToDataSetFilter, "$Revision: 1.69 $"); + +// Construct object. +vtkDataSetToDataSetFilter::vtkDataSetToDataSetFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +vtkDataSetToDataSetFilter::~vtkDataSetToDataSetFilter() +{ +} + +int vtkDataSetToDataSetFilter::RequestDataObject(vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + if (!inInfo) + { + return 0; + } + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (input) + { + vtkInformation* info = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + if (!output || !output->IsA(input->GetClassName())) + { + output = input->NewInstance(); + output->SetPipelineInformation(info); + output->Delete(); + this->GetOutputPortInformation(0)->Set( + vtkDataObject::DATA_EXTENT_TYPE(), output->GetExtentType()); + } + return 1; + } + return 0; +} + +int vtkDataSetToDataSetFilter::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // Handling REQUEST_DATA_OBJECT because if the filter is connected + // with SetInputConnection() as opposed to SetInput(), the output + // never gets created + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + return this->RequestDataObject(request, inputVector, outputVector); + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkDataSetToDataSetFilter::SetInput(vtkDataSet *input) +{ + vtkDataSet *oldInput = this->GetInput(); + + if (oldInput != NULL) + { + if (input == NULL || + oldInput->GetDataObjectType() != input->GetDataObjectType()) + { + vtkWarningMacro("Changing input type. Deleting output"); + this->SetOutput(NULL); + } + } + if (input != NULL && this->vtkSource::GetOutput(0) == NULL) + { + this->vtkSource::SetNthOutput(0, input->NewInstance()); + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); + } + + this->vtkProcessObject::SetNthInput(0, input); +} + +// Get the output of this filter. If output is NULL then input hasn't been set +// which is necessary for abstract objects. +vtkDataSet *vtkDataSetToDataSetFilter::GetOutput() +{ + if (this->GetInput() == NULL ) + { + vtkErrorMacro(<<"Abstract filters require input to be set before output can be retrieved"); + return NULL; + } + + // sanity check + if (this->NumberOfOutputs < 1) + { + vtkErrorMacro("Sanity check failed. We should have an output"); + return NULL; + } + + return (vtkDataSet *)this->Superclass::GetOutput(0); +} + +// Get the output as vtkPolyData. +vtkPolyData *vtkDataSetToDataSetFilter::GetPolyDataOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_POLY_DATA) + { + return (vtkPolyData *)ds; + } + return NULL; +} + +// Get the output as vtkStructuredPoints. +vtkStructuredPoints *vtkDataSetToDataSetFilter::GetStructuredPointsOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_STRUCTURED_POINTS) + { + return (vtkStructuredPoints *)ds; + } + return NULL; +} + +// Get the output as vtkStructuredGrid. +vtkStructuredGrid *vtkDataSetToDataSetFilter::GetStructuredGridOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_STRUCTURED_GRID) + { + return (vtkStructuredGrid *)ds; + } + return NULL; +} + +// Get the output as vtkUnstructuredGrid. +vtkUnstructuredGrid *vtkDataSetToDataSetFilter::GetUnstructuredGridOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_UNSTRUCTURED_GRID) + { + return (vtkUnstructuredGrid *)ds; + } + return NULL; +} + +// Get the output as vtkRectilinearGrid. +vtkRectilinearGrid *vtkDataSetToDataSetFilter::GetRectilinearGridOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_RECTILINEAR_GRID) + { + return (vtkRectilinearGrid *)ds; + } + return NULL; +} + + + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkDataSetToDataSetFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +// We know input and output match in type - call the type specific version of +// copy information +void vtkDataSetToDataSetFilter::ExecuteInformation() +{ + vtkDataSet* output = this->GetOutput(); + if(output) + { + output->CopyTypeSpecificInformation( this->GetInput() ); + } +} + +//---------------------------------------------------------------------------- + +// Copy the update information across +void vtkDataSetToDataSetFilter::ComputeInputUpdateExtents(vtkDataObject *output) +{ + vtkDataObject *input = this->GetInput(); + + input->SetUpdatePiece( output->GetUpdatePiece() ); + input->SetUpdateNumberOfPieces( output->GetUpdateNumberOfPieces() ); + input->SetUpdateGhostLevel( output->GetUpdateGhostLevel() ); + input->SetUpdateExtent( output->GetUpdateExtent() ); + input->RequestExactExtentOn(); +} + +//---------------------------------------------------------------------------- +vtkDataSet *vtkDataSetToDataSetFilter::GetOutput(int idx) +{ + return (vtkDataSet *) this->vtkDataSetSource::GetOutput(idx); +} + +//---------------------------------------------------------------------------- +int +vtkDataSetToDataSetFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetToDataSetFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetToDataSetFilter.h b/Filtering/vtkDataSetToDataSetFilter.h new file mode 100644 index 0000000..db807b6 --- /dev/null +++ b/Filtering/vtkDataSetToDataSetFilter.h @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToDataSetFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetToDataSetFilter - abstract filter class +// .SECTION Description +// vtkDataSetToDataSetFilter is an abstract filter class. Subclasses of +// vtkDataSetToDataSetFilter take a dataset as input and create a dataset as +// output. The form of the input geometry is not changed in these filters, +// only the point attributes (e.g. scalars, vectors, etc.). +// +// This is an abstract filter type. What that means is that the output of the +// filter is an abstract type (i.e., vtkDataSet), no matter what the input of +// the filter is. This can cause problems connecting together filters due to +// the change in dataset type. (For example, in a series of filters +// processing vtkPolyData, when a vtkDataSetToDataSetFilter or subclass is +// introduced into the pipeline, if the filter downstream of it takes +// vtkPolyData as input, the pipeline connection cannot be made.) To get +// around this problem, use one of the convenience methods to return a +// concrete type (e.g., vtkGetPolyDataOutput(), GetStructuredPointsOutput(), +// etc.). + +// .SECTION See Also +// vtkBrownianPoints vtkProbeFilter vtkThresholdTextureCoords vtkDicer +// vtkElevationFilter vtkImplicitTextureCoords vtkTextureMapToBox +// vtkTextureMapToPlane vtkVectorDot vtkVectorNorm + +#ifndef __vtkDataSetToDataSetFilter_h +#define __vtkDataSetToDataSetFilter_h + +#include "vtkDataSetSource.h" + +class vtkDataSet; +class vtkPolyData; +class vtkRectilinearGrid; +class vtkStructuredGrid; +class vtkStructuredPoints; +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkDataSetToDataSetFilter : public vtkDataSetSource +{ + +public: + vtkTypeRevisionMacro(vtkDataSetToDataSetFilter,vtkDataSetSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the input data or filter. + void SetInput(vtkDataSet *input); + + // Description: + // Get the output of this filter. If output is NULL then input + // hasn't been set which is necessary for abstract objects. + vtkDataSet *GetOutput(); + vtkDataSet *GetOutput(int idx); + + // Description: + // Get the output as vtkPolyData. + virtual vtkPolyData *GetPolyDataOutput(); + + // Description: + // Get the output as vtkStructuredPoints. + virtual vtkStructuredPoints *GetStructuredPointsOutput(); + + // Description: + // Get the output as vtkStructuredGrid. + virtual vtkStructuredGrid *GetStructuredGridOutput(); + + // Description: + // Get the output as vtkUnstructuredGrid. + virtual vtkUnstructuredGrid *GetUnstructuredGridOutput(); + + // Description: + // Get the output as vtkRectilinearGrid. + virtual vtkRectilinearGrid *GetRectilinearGridOutput(); + + // Description: + // Get the input data or filter. + vtkDataSet *GetInput(); + + // Description: + // By default copy the output update extent to the input + virtual void ComputeInputUpdateExtents( vtkDataObject *output ); + + // Description: + // Transform pipeline requests from executives into old-style + // pipeline calls. This works with the + // vtkStreamingDemandDrivenPipeline executive to maintain backward + // compatibility for filters written as subclasses of vtkSource. + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkDataSetToDataSetFilter(); + ~vtkDataSetToDataSetFilter(); + + void ExecuteInformation(); + + virtual int FillInputPortInformation(int, vtkInformation*); + + // This is called by the superclass. + // This is the method you should override. + virtual int RequestDataObject(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +private: + vtkDataSetToDataSetFilter(const vtkDataSetToDataSetFilter&); // Not implemented. + void operator=(const vtkDataSetToDataSetFilter&); // Not implemented. +}; + +#endif + + + diff --git a/Filtering/vtkDataSetToImageFilter.cxx b/Filtering/vtkDataSetToImageFilter.cxx new file mode 100644 index 0000000..f1c9193 --- /dev/null +++ b/Filtering/vtkDataSetToImageFilter.cxx @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToImageFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetToImageFilter.h" + +#include "vtkDataSet.h" +#include "vtkImageData.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkDataSetToImageFilter, "$Revision: 1.6 $"); + +//---------------------------------------------------------------------------- +vtkDataSetToImageFilter::vtkDataSetToImageFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataSetToImageFilter::~vtkDataSetToImageFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkDataSetToImageFilter::SetInput(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkDataSetToImageFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +// All the DataSetToImageFilters require all their input. +void vtkDataSetToImageFilter::ComputeInputUpdateExtents( + vtkDataObject *data) +{ + vtkImageData *output = (vtkImageData *)data; + vtkDataSet *input = this->GetInput(); + int *ext; + + if (input == NULL) + { + return; + } + + // Lets just check to see if the outputs UpdateExtent is valid. + ext = output->GetUpdateExtent(); + if (ext[0] > ext[1] || ext[2] > ext[3] || ext[4] > ext[5]) + { + return; + } + + input->SetUpdateExtent(0, 1, 0); +} + +//---------------------------------------------------------------------------- +int +vtkDataSetToImageFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetToImageFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetToImageFilter.h b/Filtering/vtkDataSetToImageFilter.h new file mode 100644 index 0000000..4eeec1b --- /dev/null +++ b/Filtering/vtkDataSetToImageFilter.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToImageFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetToImageFilter - abstract filter class +// .SECTION Description +// vtkDataSetToImageFilter is an abstract filter class whose subclasses take +// as input any dataset and generate image data on output. + +// .SECTION See Also +// vtkGaussianSplatter vtkImplicitModeller vtkShepardMethod vtkVoxelModeller + +#ifndef __vtkDataSetToImageFilter_h +#define __vtkDataSetToImageFilter_h + +#include "vtkImageSource.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkDataSetToImageFilter : public vtkImageSource +{ +public: + vtkTypeRevisionMacro(vtkDataSetToImageFilter,vtkImageSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkDataSet *input); + vtkDataSet *GetInput(); + +protected: + vtkDataSetToImageFilter(); + ~vtkDataSetToImageFilter(); + + // All the DataSetToImageFilters require all their input. + void ComputeInputUpdateExtents(vtkDataObject *output); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkDataSetToImageFilter(const vtkDataSetToImageFilter&); // Not implemented. + void operator=(const vtkDataSetToImageFilter&); // Not implemented. +}; + +#endif + + + + + diff --git a/Filtering/vtkDataSetToPolyDataFilter.cxx b/Filtering/vtkDataSetToPolyDataFilter.cxx new file mode 100644 index 0000000..0c453f8 --- /dev/null +++ b/Filtering/vtkDataSetToPolyDataFilter.cxx @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetToPolyDataFilter.h" + +#include "vtkDataSet.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkDataSetToPolyDataFilter, "$Revision: 1.18 $"); + +//---------------------------------------------------------------------------- +vtkDataSetToPolyDataFilter::vtkDataSetToPolyDataFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataSetToPolyDataFilter::~vtkDataSetToPolyDataFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkDataSetToPolyDataFilter::SetInput(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkDataSetToPolyDataFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Inputs[0]); +} + + +//---------------------------------------------------------------------------- +// Copy the update information across +void vtkDataSetToPolyDataFilter::ComputeInputUpdateExtents(vtkDataObject *output) +{ + vtkDataObject *input = this->GetInput(); + + if (input == NULL) + { + return; + } + + this->vtkPolyDataSource::ComputeInputUpdateExtents(output); + input->RequestExactExtentOn(); +} + +//---------------------------------------------------------------------------- +int +vtkDataSetToPolyDataFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetToPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetToPolyDataFilter.h b/Filtering/vtkDataSetToPolyDataFilter.h new file mode 100644 index 0000000..48c6022 --- /dev/null +++ b/Filtering/vtkDataSetToPolyDataFilter.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetToPolyDataFilter - abstract filter class +// .SECTION Description +// vtkDataSetToPolyDataFilter is an abstract filter class whose subclasses +// take as input any dataset and generate polygonal data on output. + +// .SECTION See Also +// vtkContourFilter vtkCutter vtkEdgePoints vtkExtractEdges +// vtkGeometryFilter vtkGlyph3D vtkHedgeHog vtkHyperStreamline +// vtkMaskPoints vtkOutlineFilter vtkStreamer vtkTensorGlyph +// vtkThresholdPoints vtkVectorTopology + +#ifndef __vtkDataSetToPolyDataFilter_h +#define __vtkDataSetToPolyDataFilter_h + +#include "vtkPolyDataSource.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkDataSetToPolyDataFilter : public vtkPolyDataSource +{ +public: + vtkTypeRevisionMacro(vtkDataSetToPolyDataFilter,vtkPolyDataSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkDataSet *input); + vtkDataSet *GetInput(); + + // Description: + // Do not let images return more than requested. + virtual void ComputeInputUpdateExtents( vtkDataObject *output ); + +protected: + vtkDataSetToPolyDataFilter(); + ~vtkDataSetToPolyDataFilter(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkDataSetToPolyDataFilter(const vtkDataSetToPolyDataFilter&); // Not implemented. + void operator=(const vtkDataSetToPolyDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkDataSetToStructuredGridFilter.cxx b/Filtering/vtkDataSetToStructuredGridFilter.cxx new file mode 100644 index 0000000..341cd45 --- /dev/null +++ b/Filtering/vtkDataSetToStructuredGridFilter.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToStructuredGridFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetToStructuredGridFilter.h" + +#include "vtkInformation.h" +#include "vtkStructuredGrid.h" + +vtkCxxRevisionMacro(vtkDataSetToStructuredGridFilter, "$Revision: 1.21 $"); + +//---------------------------------------------------------------------------- +vtkDataSetToStructuredGridFilter::vtkDataSetToStructuredGridFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataSetToStructuredGridFilter::~vtkDataSetToStructuredGridFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkDataSetToStructuredGridFilter::SetInput(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkDataSetToStructuredGridFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +int +vtkDataSetToStructuredGridFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetToStructuredGridFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetToStructuredGridFilter.h b/Filtering/vtkDataSetToStructuredGridFilter.h new file mode 100644 index 0000000..49b7d9a --- /dev/null +++ b/Filtering/vtkDataSetToStructuredGridFilter.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToStructuredGridFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetToStructuredGridFilter - abstract filter class +// .SECTION Description +// vtkDataSetToStructuredGridFilter is an abstract filter class whose +// subclasses take as input any dataset and generate a structured +// grid on output. + +#ifndef __vtkDataSetToStructuredGridFilter_h +#define __vtkDataSetToStructuredGridFilter_h + +#include "vtkStructuredGridSource.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkDataSetToStructuredGridFilter : public vtkStructuredGridSource +{ +public: + vtkTypeRevisionMacro(vtkDataSetToStructuredGridFilter,vtkStructuredGridSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkDataSet *input); + vtkDataSet *GetInput(); + +protected: + vtkDataSetToStructuredGridFilter(); + ~vtkDataSetToStructuredGridFilter(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkDataSetToStructuredGridFilter(const vtkDataSetToStructuredGridFilter&); // Not implemented. + void operator=(const vtkDataSetToStructuredGridFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkDataSetToStructuredPointsFilter.cxx b/Filtering/vtkDataSetToStructuredPointsFilter.cxx new file mode 100644 index 0000000..33be44c --- /dev/null +++ b/Filtering/vtkDataSetToStructuredPointsFilter.cxx @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToStructuredPointsFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetToStructuredPointsFilter.h" + +#include "vtkInformation.h" +#include "vtkStructuredPoints.h" + +vtkCxxRevisionMacro(vtkDataSetToStructuredPointsFilter, "$Revision: 1.32 $"); + +//---------------------------------------------------------------------------- +vtkDataSetToStructuredPointsFilter::vtkDataSetToStructuredPointsFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataSetToStructuredPointsFilter::~vtkDataSetToStructuredPointsFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkDataSetToStructuredPointsFilter::SetInput(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkDataSetToStructuredPointsFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +// All the DataSetToStructuredPointsFilters require all their input. +void vtkDataSetToStructuredPointsFilter::ComputeInputUpdateExtents( + vtkDataObject *data) +{ + vtkStructuredPoints *output = (vtkStructuredPoints*)data; + vtkDataSet *input = this->GetInput(); + int *ext; + + if (input == NULL) + { + return; + } + + // Lets just check to see if the outputs UpdateExtent is valid. + ext = output->GetUpdateExtent(); + if (ext[0] > ext[1] || ext[2] > ext[3] || ext[4] > ext[5]) + { + return; + } + + input->SetUpdateExtent(0, 1, 0); + input->RequestExactExtentOn(); +} + +//---------------------------------------------------------------------------- +int +vtkDataSetToStructuredPointsFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetToStructuredPointsFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetToStructuredPointsFilter.h b/Filtering/vtkDataSetToStructuredPointsFilter.h new file mode 100644 index 0000000..3d4a3ed --- /dev/null +++ b/Filtering/vtkDataSetToStructuredPointsFilter.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToStructuredPointsFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetToStructuredPointsFilter - abstract filter class +// .SECTION Description +// vtkDataSetToStructuredPointsFilter is an abstract filter class whose +// subclasses take as input any dataset and generate structured points +// data on output. + +// .SECTION See Also +// vtkGaussianSplatter vtkImplicitModeller vtkShepardMethod vtkVoxelModeller + +#ifndef __vtkDataSetToStructuredPointsFilter_h +#define __vtkDataSetToStructuredPointsFilter_h + +#include "vtkStructuredPointsSource.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkDataSetToStructuredPointsFilter : public vtkStructuredPointsSource +{ +public: + vtkTypeRevisionMacro(vtkDataSetToStructuredPointsFilter,vtkStructuredPointsSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkDataSet *input); + vtkDataSet *GetInput(); + +protected: + vtkDataSetToStructuredPointsFilter(); + ~vtkDataSetToStructuredPointsFilter(); + + // All the DataSetToStructuredPointsFilters require all their input. + void ComputeInputUpdateExtents(vtkDataObject *output); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkDataSetToStructuredPointsFilter(const vtkDataSetToStructuredPointsFilter&); // Not implemented. + void operator=(const vtkDataSetToStructuredPointsFilter&); // Not implemented. +}; + +#endif + + + + + diff --git a/Filtering/vtkDataSetToUnstructuredGridFilter.cxx b/Filtering/vtkDataSetToUnstructuredGridFilter.cxx new file mode 100644 index 0000000..67414d9 --- /dev/null +++ b/Filtering/vtkDataSetToUnstructuredGridFilter.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToUnstructuredGridFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetToUnstructuredGridFilter.h" + +#include "vtkInformation.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkDataSetToUnstructuredGridFilter, "$Revision: 1.28 $"); + +//---------------------------------------------------------------------------- +vtkDataSetToUnstructuredGridFilter::vtkDataSetToUnstructuredGridFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkDataSetToUnstructuredGridFilter::~vtkDataSetToUnstructuredGridFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkDataSetToUnstructuredGridFilter::SetInput(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkDataSetToUnstructuredGridFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +int +vtkDataSetToUnstructuredGridFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetToUnstructuredGridFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkDataSetToUnstructuredGridFilter.h b/Filtering/vtkDataSetToUnstructuredGridFilter.h new file mode 100644 index 0000000..92a5853 --- /dev/null +++ b/Filtering/vtkDataSetToUnstructuredGridFilter.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToUnstructuredGridFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetToUnstructuredGridFilter - abstract filter class +// .SECTION Description +// vtkDataSetToUnstructuredGridFilter is an abstract filter class whose +// subclasses take as input any dataset and generate an unstructured +// grid on output. + +// .SECTION See Also +// vtkAppendFilter vtkConnectivityFilter vtkExtractGeometry +// vtkShrinkFilter vtkThreshold + +#ifndef __vtkDataSetToUnstructuredGridFilter_h +#define __vtkDataSetToUnstructuredGridFilter_h + +#include "vtkUnstructuredGridSource.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkDataSetToUnstructuredGridFilter : public vtkUnstructuredGridSource +{ +public: + vtkTypeRevisionMacro(vtkDataSetToUnstructuredGridFilter,vtkUnstructuredGridSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkDataSet *input); + vtkDataSet *GetInput(); + +protected: + vtkDataSetToUnstructuredGridFilter(); + ~vtkDataSetToUnstructuredGridFilter(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkDataSetToUnstructuredGridFilter(const vtkDataSetToUnstructuredGridFilter&); // Not implemented. + void operator=(const vtkDataSetToUnstructuredGridFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkDemandDrivenPipeline.cxx b/Filtering/vtkDemandDrivenPipeline.cxx new file mode 100644 index 0000000..389cd10 --- /dev/null +++ b/Filtering/vtkDemandDrivenPipeline.cxx @@ -0,0 +1,1134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDemandDrivenPipeline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDemandDrivenPipeline.h" + +#include "vtkAlgorithm.h" +#include "vtkAlgorithmOutput.h" +#include "vtkCellData.h" +#include "vtkCommand.h" +#include "vtkDataObject.h" +#include "vtkDataSet.h" +#include "vtkGarbageCollector.h" +#include "vtkHierarchicalBoxDataSet.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationKeyVectorKey.h" +#include "vtkInformationRequestKey.h" +#include "vtkInformationUnsignedLongKey.h" +#include "vtkInformationVector.h" +#include "vtkInstantiator.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +#include "vtkImageData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +#include + +vtkCxxRevisionMacro(vtkDemandDrivenPipeline, "$Revision: 1.37.4.5 $"); +vtkStandardNewMacro(vtkDemandDrivenPipeline); + +vtkInformationKeyMacro(vtkDemandDrivenPipeline, DATA_NOT_GENERATED, Integer); +vtkInformationKeyMacro(vtkDemandDrivenPipeline, RELEASE_DATA, Integer); +vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_DATA, Request); +vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_DATA_NOT_GENERATED, Request); +vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_DATA_OBJECT, Request); +vtkInformationKeyMacro(vtkDemandDrivenPipeline, REQUEST_INFORMATION, Request); + +//---------------------------------------------------------------------------- +vtkDemandDrivenPipeline::vtkDemandDrivenPipeline() +{ + this->InfoRequest = 0; + this->DataObjectRequest = 0; + this->DataRequest = 0; +} + +//---------------------------------------------------------------------------- +vtkDemandDrivenPipeline::~vtkDemandDrivenPipeline() +{ + if (this->InfoRequest) + { + this->InfoRequest->Delete(); + } + if (this->DataObjectRequest) + { + this->DataObjectRequest->Delete(); + } + if (this->DataRequest) + { + this->DataRequest->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkDemandDrivenPipeline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "PipelineMTime: " << this->PipelineMTime << "\n"; +} + + +//---------------------------------------------------------------------------- +int +vtkDemandDrivenPipeline::ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int requestFromOutputPort, + unsigned long* mtime) +{ + // The pipeline's MTime starts with this algorithm's MTime. + // Invoke the request on the algorithm. + this->InAlgorithm = 1; + int result = + this->Algorithm->ComputePipelineMTime(request, + inInfoVec, outInfoVec, + requestFromOutputPort, + &this->PipelineMTime); + this->InAlgorithm = 0; + + // If the algorithm failed report it now. + if(!result) + { + if(request) + { + vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm + << ") returned failure for pipeline" + << " modified time request from output port " + << requestFromOutputPort<< ": " << *request); + } + else + { + vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm + << ") returned failure for pipeline" + << " modified time request from output port " + << requestFromOutputPort<< "."); + } + return 0; + } + + // Forward the request upstream if not sharing input information. + if(!this->SharedInputInformation) + { + // We want the maximum PipelineMTime of all inputs. + for(int i=0; i < this->Algorithm->GetNumberOfInputPorts(); ++i) + { + for(int j=0; j < inInfoVec[i]->GetNumberOfInformationObjects(); ++j) + { + vtkInformation* info = inInfoVec[i]->GetInformationObject(j); + // call ComputePipelineMTime on the input + vtkExecutive* e; + int producerPort; + info->Get(vtkExecutive::PRODUCER(),e,producerPort); + if(e) + { + unsigned long pmtime; + if(!e->ComputePipelineMTime(request, + e->GetInputInformation(), + e->GetOutputInformation(), + producerPort, &pmtime)) + { + return 0; + } + if(pmtime > this->PipelineMTime) + { + this->PipelineMTime = pmtime; + } + } + } + } + } + *mtime = this->PipelineMTime; + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // The algorithm should not invoke anything on the executive. + if(!this->CheckAlgorithm("ProcessRequest", request)) + { + return 0; + } + + if(this->Algorithm && request->Has(REQUEST_DATA_OBJECT())) + { + // if we are up to date then short circuit + if (this->PipelineMTime < this->DataObjectTime.GetMTime()) + { + return 1; + } + // Update inputs first if they are out of date + if(!this->ForwardUpstream(request)) + { + return 0; + } + + // Make sure our output data type is up-to-date. + int result = 1; + if(this->PipelineMTime > this->DataObjectTime.GetMTime()) + { + // Request data type from the algorithm. + result = this->ExecuteDataObject(request,inInfoVec,outInfoVec); + + // Make sure the data object exists for all output ports. + for(int i=0; + result && i < outInfoVec->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* info = outInfoVec->GetInformationObject(i); + if(!info->Get(vtkDataObject::DATA_OBJECT())) + { + result = 0; + } + } + + if(result) + { + // Data object is now up to date. + this->DataObjectTime.Modified(); + } + } + + return result; + } + + if(this->Algorithm && request->Has(REQUEST_INFORMATION())) + { + // if we are up to date then short circuit + if (this->PipelineMTime < this->InformationTime.GetMTime()) + { + return 1; + } + // Update inputs first. + if(!this->ForwardUpstream(request)) + { + return 0; + } + + // Make sure our output information is up-to-date. + int result = 1; + if(this->PipelineMTime > this->InformationTime.GetMTime()) + { + // Make sure input types are valid before algorithm does anything. + if(!this->InputCountIsValid(inInfoVec) || + !this->InputTypeIsValid(inInfoVec)) + { + return 0; + } + + // Request information from the algorithm. + result = this->ExecuteInformation(request,inInfoVec,outInfoVec); + + // Information is now up to date. + this->InformationTime.Modified(); + } + + return result; + } + + if(this->Algorithm && request->Has(REQUEST_DATA())) + { + // Get the output port from which the request was made. + int outputPort = -1; + if(request->Has(FROM_OUTPUT_PORT())) + { + outputPort = request->Get(FROM_OUTPUT_PORT()); + } + + // Make sure our outputs are up-to-date. + int result = 1; + if(this->NeedToExecuteData(outputPort,inInfoVec,outInfoVec)) + { + // Update inputs first. + if(!this->ForwardUpstream(request)) + { + return 0; + } + + // Make sure inputs are valid before algorithm does anything. + if(!this->InputCountIsValid(inInfoVec) || + !this->InputTypeIsValid(inInfoVec) || + !this->InputFieldsAreValid(inInfoVec)) + { + return 0; + } + + // Request data from the algorithm. + result = this->ExecuteData(request,inInfoVec,outInfoVec); + + // Data are now up to date. + this->DataTime.Modified(); + + // Some filters may modify themselves while processing + // REQUEST_DATA. Since we mark the filter execution end time + // here this behavior does not cause re-execution, so it should + // be allowed. The filter is now considered up-to-date. + // However, we must prevent the REQUEST_DATA_OBJECT and + // REQUEST_INFORMATION passes from re-running, so mark them + // up-do-date also. It is up to the filter to not modify itself + // in a way that would change the result of any pass. + this->InformationTime.Modified(); + this->DataObjectTime.Modified(); + } + return result; + } + + // Let the superclass handle other requests. + return this->Superclass::ProcessRequest(request, inInfoVec, outInfoVec); +} + +//---------------------------------------------------------------------------- +void vtkDemandDrivenPipeline::ResetPipelineInformation(int, + vtkInformation* info) +{ + info->Remove(RELEASE_DATA()); +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::Update() +{ + return this->Superclass::Update(); +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::Update(int port) +{ + if(!this->UpdateInformation()) + { + return 0; + } + if(port >= -1 && port < this->Algorithm->GetNumberOfOutputPorts()) + { + return this->UpdateData(port); + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::UpdatePipelineMTime() +{ + // The algorithm should not invoke anything on the executive. + if(!this->CheckAlgorithm("UpdatePipelineMTime", 0)) + { + return 0; + } + + // Send the request for pipeline modified time. + unsigned long mtime; + this->ComputePipelineMTime(0, + this->GetInputInformation(), + this->GetOutputInformation(), + -1, &mtime); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::UpdateDataObject() +{ + // The algorithm should not invoke anything on the executive. + if(!this->CheckAlgorithm("UpdateDataObject", 0)) + { + return 0; + } + + // Update the pipeline mtime first. + if(!this->UpdatePipelineMTime()) + { + return 0; + } + + // Setup the request for data object creation. + if (!this->DataObjectRequest) + { + this->DataObjectRequest = vtkInformation::New(); + this->DataObjectRequest->Set(REQUEST_DATA_OBJECT()); + // The request is forwarded upstream through the pipeline. + this->DataObjectRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request after it is forwarded. + this->DataObjectRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + } + + // Send the request. + return this->ProcessRequest(this->DataObjectRequest, + this->GetInputInformation(), + this->GetOutputInformation()); +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::UpdateInformation() +{ + // The algorithm should not invoke anything on the executive. + if(!this->CheckAlgorithm("UpdateInformation", 0)) + { + return 0; + } + + // Do the data-object creation pass before the information pass. + if(!this->UpdateDataObject()) + { + return 0; + } + + // Setup the request for information. + if (!this->InfoRequest) + { + this->InfoRequest = vtkInformation::New(); + this->InfoRequest->Set(REQUEST_INFORMATION()); + // The request is forwarded upstream through the pipeline. + this->InfoRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request after it is forwarded. + this->InfoRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + } + + // Send the request. + return this->ProcessRequest(this->InfoRequest, + this->GetInputInformation(), + this->GetOutputInformation()); +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::UpdateData(int outputPort) +{ + // The algorithm should not invoke anything on the executive. + if(!this->CheckAlgorithm("UpdateData", 0)) + { + return 0; + } + + // Range check. + if(outputPort < -1 || + outputPort >= this->Algorithm->GetNumberOfOutputPorts()) + { + vtkErrorMacro("UpdateData given output port index " + << outputPort << " on an algorithm with " + << this->Algorithm->GetNumberOfOutputPorts() + << " output ports."); + return 0; + } + + // Setup the request for data. + if (!this->DataRequest) + { + this->DataRequest = vtkInformation::New(); + this->DataRequest->Set(REQUEST_DATA()); + // The request is forwarded upstream through the pipeline. + this->DataRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request after it is forwarded. + this->DataRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1); + } + + // Send the request. + this->DataRequest->Set(FROM_OUTPUT_PORT(), outputPort); + return this->ProcessRequest(this->DataRequest, + this->GetInputInformation(), + this->GetOutputInformation()); +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::ExecuteDataObject(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo) +{ + // Invoke the request on the algorithm. + int result = this->CallAlgorithm(request, vtkExecutive::RequestDownstream, + inInfo, outInfo); + + // Make sure a valid data object exists for all output ports. + for(int i=0; result && i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + result = this->CheckDataObject(i, outInfo); + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::ExecuteInformation +(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Give each output data object a chance to set default values in + // its pipeline information. Provide the first input's information + // to each output. + vtkInformation* inInfo = 0; + if(this->GetNumberOfInputPorts() > 0) + { + inInfo = inInfoVec[0]->GetInformationObject(0); + } + for(int i=0; i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* outInfo = outInfoVec->GetInformationObject(i); + if(vtkDataObject* outData = outInfo->Get(vtkDataObject::DATA_OBJECT())) + { + outData->CopyInformationToPipeline(request, inInfo); + } + } + + // Invoke the request on the algorithm. + return this->CallAlgorithm(request, vtkExecutive::RequestDownstream, + inInfoVec, outInfoVec); +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::ExecuteData(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo) +{ + this->ExecuteDataStart(request, inInfo, outInfo); + // Invoke the request on the algorithm. + int result = this->CallAlgorithm(request, vtkExecutive::RequestDownstream, + inInfo, outInfo); + this->ExecuteDataEnd(request, inInfo, outInfo); + + return result; +} + +//---------------------------------------------------------------------------- +void vtkDemandDrivenPipeline::ExecuteDataStart(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outputs) +{ + int i; + + // Ask the algorithm to mark outputs that it will not generate. + request->Remove(REQUEST_DATA()); + request->Set(REQUEST_DATA_NOT_GENERATED()); + this->CallAlgorithm(request, vtkExecutive::RequestDownstream, + inInfo, outputs); + request->Remove(REQUEST_DATA_NOT_GENERATED()); + request->Set(REQUEST_DATA()); + + // Prepare outputs that will be generated to receive new data. + for(i=0; i < outputs->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outputs->GetInformationObject(i); + vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if(data && !outInfo->Get(DATA_NOT_GENERATED())) + { + data->PrepareForNewData(); + data->CopyInformationFromPipeline(request); + } + } + + // Pass the vtkDataObject's field data from the first input to all + // outputs. + if (this->GetNumberOfInputPorts() > 0) + { + vtkDataObject* input = this->GetInputData(0, 0); + if (input && input->GetFieldData()) + { + for(i=0; i < outputs->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outputs->GetInformationObject(i); + vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if(output) + { + output->GetFieldData()->PassData(input->GetFieldData()); + } + } + } + } + + // Tell observers the algorithm is about to execute. + this->Algorithm->InvokeEvent(vtkCommand::StartEvent,NULL); + + // The algorithm has not yet made any progress. + this->Algorithm->SetAbortExecute(0); + this->Algorithm->UpdateProgress(0.0); +} + +//---------------------------------------------------------------------------- +void vtkDemandDrivenPipeline::ExecuteDataEnd(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outputs) +{ + // The algorithm has either finished or aborted. + if(!this->Algorithm->GetAbortExecute()) + { + this->Algorithm->UpdateProgress(1.0); + } + + // Tell observers the algorithm is done executing. + this->Algorithm->InvokeEvent(vtkCommand::EndEvent,NULL); + + // Tell outputs they have been generated. + this->MarkOutputsGenerated(request,inInfoVec,outputs); + + // Remove any not-generated mark. + int i, j; + for(i=0; i < outputs->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outputs->GetInformationObject(i); + outInfo->Remove(DATA_NOT_GENERATED()); + } + + // Release input data if requested. + for(i=0; i < this->Algorithm->GetNumberOfInputPorts(); ++i) + { + for(j=0; j < inInfoVec[i]->GetNumberOfInformationObjects(); ++j) + { + vtkInformation* inInfo = inInfoVec[i]->GetInformationObject(j); + vtkDataObject* dataObject = inInfo->Get(vtkDataObject::DATA_OBJECT()); + if(dataObject && (dataObject->GetGlobalReleaseDataFlag() || + inInfo->Get(RELEASE_DATA()))) + { + dataObject->ReleaseData(); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkDemandDrivenPipeline::MarkOutputsGenerated +(vtkInformation*, + vtkInformationVector** /* inInfoVec */, + vtkInformationVector* outputs) +{ + // Tell all generated outputs that they have been generated. + for(int i=0; i < outputs->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outputs->GetInformationObject(i); + vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if(data && !outInfo->Get(DATA_NOT_GENERATED())) + { + data->DataHasBeenGenerated(); + } + } +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::CheckDataObject(int port, + vtkInformationVector* outInfoVec) +{ + // Check that the given output port has a valid data object. + vtkInformation* outInfo = outInfoVec->GetInformationObject(port); + vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT()); + vtkInformation* portInfo = this->Algorithm->GetOutputPortInformation(port); + if(const char* dt = portInfo->Get(vtkDataObject::DATA_TYPE_NAME())) + { + // The output port specifies a data type. Make sure the data + // object exists and is of the right type. + if(!data || !data->IsA(dt)) + { + // Try to create an instance of the correct type. + data = this->NewDataObject(dt); + this->SetOutputData(port, data, outInfo); + if(data) + { + data->FastDelete(); + } + } + if(!data) + { + // The algorithm has a bug and did not create the data object. + vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" + << this->Algorithm + << ") did not create output for port " << port + << " when asked by REQUEST_DATA_OBJECT and does not" + << " specify a concrete DATA_TYPE_NAME."); + return 0; + } + return 1; + } + else if(data) + { + // The algorithm did not specify its output data type. Just assume + // the data object is of the correct type. + return 1; + } + else + { + // The algorithm did not specify its output data type and no + // object exists. + vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() << "(" + << this->Algorithm + << ") did not create output for port " << port + << " when asked by REQUEST_DATA_OBJECT and does not" + << " specify any DATA_TYPE_NAME."); + return 0; + } +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputCountIsValid +(vtkInformationVector **inInfoVec) +{ + // Check the number of connections for each port. + int result = 1; + for(int p=0; p < this->Algorithm->GetNumberOfInputPorts(); ++p) + { + if(!this->InputCountIsValid(p,inInfoVec)) + { + result = 0; + } + } + return result; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputCountIsValid +(int port, vtkInformationVector **inInfoVec) +{ + // Get the number of connections for this port. + if (!inInfoVec[port]) + { + return 0; + } + int connections = inInfoVec[port]->GetNumberOfInformationObjects(); + + // If the input port is optional, there may be less than one connection. + if(!this->InputIsOptional(port) && (connections < 1)) + { + vtkErrorMacro("Input port " << port << " of algorithm " + << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ") has " << connections + << " connections but is not optional."); + return 0; + } + + // If the input port is repeatable, there may be more than one connection. + if(!this->InputIsRepeatable(port) && (connections > 1)) + { + vtkErrorMacro("Input port " << port << " of algorithm " + << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ") has " << connections + << " connections but is not repeatable."); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputTypeIsValid +(vtkInformationVector **inInfoVec) +{ + // Check the connection types for each port. + int result = 1; + for(int p=0; p < this->Algorithm->GetNumberOfInputPorts(); ++p) + { + if(!this->InputTypeIsValid(p, inInfoVec)) + { + result = 0; + } + } + return result; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputTypeIsValid +(int port, vtkInformationVector **inInfoVec) +{ + // Check the type of each connection on this port. + int result = 1; + if (!inInfoVec[port]) + { + return 0; + } + for(int i=0; i < inInfoVec[port]->GetNumberOfInformationObjects(); ++i) + { + if(!this->InputTypeIsValid(port, i, inInfoVec)) + { + result = 0; + } + } + return result; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputTypeIsValid +(int port, int index, vtkInformationVector **inInfoVec) +{ + if (!inInfoVec[port]) + { + return 0; + } + vtkInformation* info = this->Algorithm->GetInputPortInformation(port); + vtkDataObject* input = this->GetInputData(port, index, inInfoVec); + + // Enforce required type, if any. + if(const char* dt = info->Get(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE())) + { + // The input cannot be NULL unless the port is optional. + if(!input && !info->Get(vtkAlgorithm::INPUT_IS_OPTIONAL())) + { + vtkErrorMacro("Input for connection index " << index + << " on input port index " << port + << " for algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ") is NULL, but a " << dt + << " is required."); + return 0; + } + + // The input must be of required type or NULL. + if(input && !input->IsA(dt)) + { + vtkErrorMacro("Input for connection index " << index + << " on input port index " << port + << " for algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ") is of type " + << input->GetClassName() << ", but a " << dt + << " is required."); + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputFieldsAreValid +(vtkInformationVector **inInfoVec) +{ + // Check the fields for each port. + int result = 1; + for(int p=0; p < this->Algorithm->GetNumberOfInputPorts(); ++p) + { + if(!this->InputFieldsAreValid(p,inInfoVec)) + { + result = 0; + } + } + return result; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputFieldsAreValid +(int port, vtkInformationVector **inInfoVec) +{ + // Check the fields for each connection on this port. + if (!inInfoVec[port]) + { + return 0; + } + int result = 1; + for(int i=0; i < inInfoVec[port]->GetNumberOfInformationObjects(); ++i) + { + if(!this->InputFieldsAreValid(port, i, inInfoVec)) + { + result = 0; + } + } + return result; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputFieldsAreValid +(int port, int index, vtkInformationVector **inInfoVec) +{ + vtkInformation* info = this->Algorithm->GetInputPortInformation(port); + vtkInformationVector* fields = + info->Get(vtkAlgorithm::INPUT_REQUIRED_FIELDS()); + + // If there are no required fields, there is nothing to check. + if(!fields) + { + return 1; + } + vtkDataObject* input = this->GetInputData(port, index, inInfoVec); + + // NULL inputs do not have to have the proper fields. + if(!input) + { + return 1; + } + + // Check availability of each required field. + int result = 1; + for(int i=0; i < fields->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* field = fields->GetInformationObject(i); + + // Decide which kinds of fields to check. + int checkPoints = 1; + int checkCells = 1; + int checkFields = 1; + if(field->Has(vtkDataObject::FIELD_ASSOCIATION())) + { + switch(field->Get(vtkDataObject::FIELD_ASSOCIATION())) + { + case vtkDataObject::FIELD_ASSOCIATION_POINTS: + checkCells = 0; checkFields = 0; break; + case vtkDataObject::FIELD_ASSOCIATION_CELLS: + checkPoints = 0; checkFields = 0; break; + case vtkDataObject::FIELD_ASSOCIATION_NONE: + checkPoints = 0; checkCells = 0; break; + } + } + + // Point and cell data arrays only exist in vtkDataSet instances. + vtkDataSet* dataSet = vtkDataSet::SafeDownCast(input); + + // Look for a point data, cell data, or field data array matching + // the requirements. + if(!(checkPoints && dataSet && dataSet->GetPointData() && + this->DataSetAttributeExists(dataSet->GetPointData(), field)) && + !(checkCells && dataSet && dataSet->GetCellData() && + this->DataSetAttributeExists(dataSet->GetCellData(), field)) && + !(checkFields && input && input->GetFieldData() && + this->FieldArrayExists(input->GetFieldData(), field))) + { + /* TODO: Construct more descriptive error message from field + requirements. */ + vtkErrorMacro("Required field not found in input."); + result = 0; + } + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::DataSetAttributeExists(vtkDataSetAttributes* dsa, + vtkInformation* field) +{ + if(field->Has(vtkDataObject::FIELD_ATTRIBUTE_TYPE())) + { + // A specific attribute must match the requirements. + int attrType = field->Get(vtkDataObject::FIELD_ATTRIBUTE_TYPE()); + return this->ArrayIsValid(dsa->GetAttribute(attrType), field); + } + else + { + // Search for an array matching the requirements. + return this->FieldArrayExists(dsa, field); + } +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::FieldArrayExists(vtkFieldData* data, + vtkInformation* field) +{ + // Search the field data instance for an array matching the requirements. + for(int a=0; a < data->GetNumberOfArrays(); ++a) + { + if(this->ArrayIsValid(data->GetArray(a), field)) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::ArrayIsValid(vtkDataArray* array, + vtkInformation* field) +{ + // Enforce existence of the array. + if(!array) + { + return 0; + } + + // Enforce name of the array. This should really only be used for + // field data (not point or cell data). + if(const char* name = field->Get(vtkDataObject::FIELD_NAME())) + { + if(!array->GetName() || (strcmp(name, array->GetName()) != 0)) + { + return 0; + } + } + + // Enforce component type for the array. + if(field->Has(vtkDataObject::FIELD_ARRAY_TYPE())) + { + int arrayType = field->Get(vtkDataObject::FIELD_ARRAY_TYPE()); + if(array->GetDataType() != arrayType) + { + return 0; + } + } + + // Enforce number of components for the array. + if(field->Has(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS())) + { + int arrayNumComponents = + field->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()); + if(array->GetNumberOfComponents() != arrayNumComponents) + { + return 0; + } + } + + // Enforce number of tuples. This should really only be used for + // field data (not point or cell data). + if(field->Has(vtkDataObject::FIELD_NUMBER_OF_TUPLES())) + { + int arrayNumTuples = field->Get(vtkDataObject::FIELD_NUMBER_OF_TUPLES()); + if(array->GetNumberOfTuples() != arrayNumTuples) + { + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputIsOptional(int port) +{ + if(vtkInformation* info = this->Algorithm->GetInputPortInformation(port)) + { + return info->Get(vtkAlgorithm::INPUT_IS_OPTIONAL()); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::InputIsRepeatable(int port) +{ + if(vtkInformation* info = this->Algorithm->GetInputPortInformation(port)) + { + return info->Get(vtkAlgorithm::INPUT_IS_REPEATABLE()); + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDemandDrivenPipeline::NewDataObject(const char* type) +{ + // Check for some standard types and then try the instantiator. + if(strcmp(type, "vtkImageData") == 0) + { + return vtkImageData::New(); + } + else if(strcmp(type, "vtkPolyData") == 0) + { + return vtkPolyData::New(); + } + else if(strcmp(type, "vtkRectilinearGrid") == 0) + { + return vtkRectilinearGrid::New(); + } + else if(strcmp(type, "vtkStructuredGrid") == 0) + { + return vtkStructuredGrid::New(); + } + else if(strcmp(type, "vtkStructuredPoints") == 0) + { + return vtkStructuredPoints::New(); + } + else if(strcmp(type, "vtkUnstructuredGrid") == 0) + { + return vtkUnstructuredGrid::New(); + } + else if(strcmp(type, "vtkHierarchicalDataSet") == 0) + { + return vtkHierarchicalDataSet::New(); + } + else if(strcmp(type, "vtkHierarchicalBoxDataSet") == 0) + { + return vtkHierarchicalBoxDataSet::New(); + } + else if(vtkObject* obj = vtkInstantiator::CreateInstance(type)) + { + vtkDataObject* data = vtkDataObject::SafeDownCast(obj); + if(!data) + { + obj->Delete(); + } + return data; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline +::NeedToExecuteData(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // If the filter parameters or input have been modified since the + // last execution then we must execute. This is a shortcut for most + // filters since all outputs will have the same UpdateTime. This + // also handles the case in which there are no outputs. + if(this->PipelineMTime > this->DataTime.GetMTime()) + { + return 1; + } + + if(outputPort >= 0) + { + // If the output on the port making the request is out-of-date + // then we must execute. + vtkInformation* info = outInfoVec->GetInformationObject(outputPort); + vtkDataObject* data = info->Get(vtkDataObject::DATA_OBJECT()); + if(!data || this->PipelineMTime > data->GetUpdateTime()) + { + return 1; + } + } + else + { + // No port is specified. Check all ports. + for(int i=0; i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + if(this->NeedToExecuteData(i,inInfoVec,outInfoVec)) + { + return 1; + } + } + } + + // We do not need to execute. + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::SetReleaseDataFlag(int port, int n) +{ + if(!this->OutputPortIndexInRange(port, "set release data flag on")) + { + return 0; + } + vtkInformation* info = this->GetOutputInformation(port); + if(this->GetReleaseDataFlag(port) != n) + { + info->Set(RELEASE_DATA(), n); + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkDemandDrivenPipeline::GetReleaseDataFlag(int port) +{ + if(!this->OutputPortIndexInRange(port, "get release data flag from")) + { + return 0; + } + vtkInformation* info = this->GetOutputInformation(port); + if(!info->Has(RELEASE_DATA())) + { + info->Set(RELEASE_DATA(), 0); + } + return info->Get(RELEASE_DATA()); +} diff --git a/Filtering/vtkDemandDrivenPipeline.h b/Filtering/vtkDemandDrivenPipeline.h new file mode 100644 index 0000000..e3bd9b1 --- /dev/null +++ b/Filtering/vtkDemandDrivenPipeline.h @@ -0,0 +1,212 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDemandDrivenPipeline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDemandDrivenPipeline - Executive supporting on-demand execution. +// .SECTION Description +// vtkDemandDrivenPipeline is an executive that will execute an +// algorithm only when its outputs are out-of-date with respect to its +// inputs. + +#ifndef __vtkDemandDrivenPipeline_h +#define __vtkDemandDrivenPipeline_h + +#include "vtkExecutive.h" + +class vtkDataArray; +class vtkDataSetAttributes; +class vtkDemandDrivenPipelineInternals; +class vtkFieldData; +class vtkInformation; +class vtkInformationIntegerKey; +class vtkInformationVector; +class vtkInformationKeyVectorKey; +class vtkInformationUnsignedLongKey; + +class VTK_FILTERING_EXPORT vtkDemandDrivenPipeline : public vtkExecutive +{ +public: + static vtkDemandDrivenPipeline* New(); + vtkTypeRevisionMacro(vtkDemandDrivenPipeline,vtkExecutive); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Generalized interface for asking the executive to fullfill update + // requests. + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + // Description: + // Implement the pipeline modified time request. + virtual int + ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int requestFromOutputPort, + unsigned long* mtime); + + // Description: + // Bring the algorithm's outputs up-to-date. Returns 1 for success + // and 0 for failure. + virtual int Update(); + virtual int Update(int port); + + // Description: + // Get the PipelineMTime for this exective. + vtkGetMacro(PipelineMTime, unsigned long); + + // Description: + // Set whether the given output port releases data when it is + // consumed. Returns 1 if the the value changes and 0 otherwise. + virtual int SetReleaseDataFlag(int port, int n); + + // Description: + // Get whether the given output port releases data when it is consumed. + virtual int GetReleaseDataFlag(int port); + + // Description: + // Bring the PipelineMTime up to date. + virtual int UpdatePipelineMTime(); + + // Description: + // Bring the output data object's existence up to date. This does + // not actually produce data, but does create the data object that + // will store data produced during the UpdateData step. + virtual int UpdateDataObject(); + + // Description: + // Bring the output information up to date. + virtual int UpdateInformation(); + + // Description: + // Bring the output data up to date. This should be called only + // when information is up to date. Use the Update method if it is + // not known that the information is up to date. + virtual int UpdateData(int outputPort); + + // Description: + // Key defining a request to make sure the output data objects exist. + static vtkInformationRequestKey* REQUEST_DATA_OBJECT(); + + // Description: + // Key defining a request to make sure the output information is up to date. + static vtkInformationRequestKey* REQUEST_INFORMATION(); + + // Description: + // Key defining a request to make sure the output data are up to date. + static vtkInformationRequestKey* REQUEST_DATA(); + + // Description: + // Key defining a request to mark outputs that will NOT be generated + // during a REQUEST_DATA. + static vtkInformationRequestKey* REQUEST_DATA_NOT_GENERATED(); + + // Description: + // Key to specify in pipeline information the request that data be + // released after it is used. + static vtkInformationIntegerKey* RELEASE_DATA(); + + // Description: + // Key to store a mark for an output that will not be generated. + // Algorithms use this to tell the executive that they will not + // generate certain outputs for a REQUEST_DATA. + static vtkInformationIntegerKey* DATA_NOT_GENERATED(); + + // Description: + // Create (New) and return a data object of the given type. + static vtkDataObject* NewDataObject(const char* type); + +protected: + vtkDemandDrivenPipeline(); + ~vtkDemandDrivenPipeline(); + + // Helper methods to send requests to the algorithm. + virtual int ExecuteDataObject(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + virtual int ExecuteInformation(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + virtual int ExecuteData(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + + // Reset the pipeline update values in the given output information object. + virtual void ResetPipelineInformation(int port, vtkInformation*); + + // Check whether the data object in the pipeline information for an + // output port exists and has a valid type. + virtual int CheckDataObject(int port, vtkInformationVector* outInfo); + + + // Input connection validity checkers. + int InputCountIsValid(vtkInformationVector **); + int InputCountIsValid(int port,vtkInformationVector **); + int InputTypeIsValid(vtkInformationVector **); + int InputTypeIsValid(int port,vtkInformationVector **); + int InputTypeIsValid(int port, int index,vtkInformationVector **); + int InputFieldsAreValid(vtkInformationVector **); + int InputFieldsAreValid(int port,vtkInformationVector **); + int InputFieldsAreValid(int port, int index,vtkInformationVector **); + + // Field existence checkers. + int DataSetAttributeExists(vtkDataSetAttributes* dsa, vtkInformation* field); + int FieldArrayExists(vtkFieldData* data, vtkInformation* field); + int ArrayIsValid(vtkDataArray* array, vtkInformation* field); + + // Input port information checkers. + int InputIsOptional(int port); + int InputIsRepeatable(int port); + + // Decide whether the output data need to be generated. + virtual int NeedToExecuteData(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + // Handle before/after operations for ExecuteData method. + virtual void ExecuteDataStart(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + virtual void ExecuteDataEnd(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + virtual void MarkOutputsGenerated(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + // Largest MTime of any algorithm on this executive or preceding + // executives. + unsigned long PipelineMTime; + + // Time when information or data were last generated. + vtkTimeStamp DataObjectTime; + vtkTimeStamp InformationTime; + vtkTimeStamp DataTime; + +//BTX + friend class vtkCompositeDataPipeline; +//ETX + + + vtkInformation *InfoRequest; + vtkInformation *DataObjectRequest; + vtkInformation *DataRequest; + +private: + vtkDemandDrivenPipeline(const vtkDemandDrivenPipeline&); // Not implemented. + void operator=(const vtkDemandDrivenPipeline&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkEmptyCell.cxx b/Filtering/vtkEmptyCell.cxx new file mode 100644 index 0000000..37cfb18 --- /dev/null +++ b/Filtering/vtkEmptyCell.cxx @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEmptyCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEmptyCell.h" + +#include "vtkCellArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkEmptyCell, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkEmptyCell); + +//---------------------------------------------------------------------------- +int vtkEmptyCell::EvaluatePosition(double vtkNotUsed(x)[3], + double vtkNotUsed(closestPoint)[3], + int& vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], + double& vtkNotUsed(dist2), + double *vtkNotUsed(weights)) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkEmptyCell::EvaluateLocation(int& vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], + double vtkNotUsed(x)[3], + double *vtkNotUsed(weights)) +{ +} + +//---------------------------------------------------------------------------- +int vtkEmptyCell::CellBoundary(int vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], + vtkIdList *vtkNotUsed(pts)) +{ + return 0; +} + +//---------------------------------------------------------------------------- +void vtkEmptyCell::Contour(double vtkNotUsed(value), + vtkDataArray *vtkNotUsed(cellScalars), + vtkPointLocator *vtkNotUsed(locator), + vtkCellArray *vtkNotUsed(verts), + vtkCellArray *vtkNotUsed(lines), + vtkCellArray *vtkNotUsed(polys), + vtkPointData *vtkNotUsed(inPd), + vtkPointData *vtkNotUsed(outPd), + vtkCellData *vtkNotUsed(inCd), + vtkIdType vtkNotUsed(cellId), + vtkCellData *vtkNotUsed(outCd)) +{ +} + +//---------------------------------------------------------------------------- +// Project point on line. If it lies between 0<=t<=1 and distance off line +// is less than tolerance, intersection detected. +int vtkEmptyCell::IntersectWithLine(double vtkNotUsed(p1)[3], + double vtkNotUsed(p2)[3], + double vtkNotUsed(tol), + double& vtkNotUsed(t), + double vtkNotUsed(x)[3], + double pcoords[3], + int& vtkNotUsed(subId)) +{ + pcoords[0] = -10.0; + return 0; +} + +//---------------------------------------------------------------------------- +int vtkEmptyCell::Triangulate(int vtkNotUsed(index), + vtkIdList *ptIds, vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkEmptyCell::Derivatives(int vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], + double *vtkNotUsed(values), + int vtkNotUsed(dim), + double *vtkNotUsed(derivs)) +{ +} + +//---------------------------------------------------------------------------- +void vtkEmptyCell::Clip(double vtkNotUsed(value), + vtkDataArray *vtkNotUsed(cellScalars), + vtkPointLocator *vtkNotUsed(locator), + vtkCellArray *vtkNotUsed(verts), + vtkPointData *vtkNotUsed(inPD), + vtkPointData *vtkNotUsed(outPD), + vtkCellData *vtkNotUsed(inCD), + vtkIdType vtkNotUsed(cellId), + vtkCellData *vtkNotUsed(outCD), + int vtkNotUsed(insideOut)) +{ +} + +//---------------------------------------------------------------------------- +void vtkEmptyCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkEmptyCell.h b/Filtering/vtkEmptyCell.h new file mode 100644 index 0000000..c2c1a76 --- /dev/null +++ b/Filtering/vtkEmptyCell.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEmptyCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEmptyCell - an empty cell used as a place-holder during processing +// .SECTION Description +// vtkEmptyCell is a concrete implementation of vtkCell. It is used +// during processing to represented a deleted element. + +#ifndef __vtkEmptyCell_h +#define __vtkEmptyCell_h + +#include "vtkCell.h" + +class VTK_FILTERING_EXPORT vtkEmptyCell : public vtkCell +{ +public: + static vtkEmptyCell *New(); + vtkTypeRevisionMacro(vtkEmptyCell,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_EMPTY_CELL;}; + int GetCellDimension() {return 0;}; + int GetNumberOfEdges() {return 0;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int) {return 0;}; + vtkCell *GetFace(int) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts1, + vtkCellArray *lines, vtkCellArray *verts2, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *pts, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + +protected: + vtkEmptyCell() {}; + ~vtkEmptyCell() {}; + + +private: + vtkEmptyCell(const vtkEmptyCell&); // Not implemented. + void operator=(const vtkEmptyCell&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkExecutive.cxx b/Filtering/vtkExecutive.cxx new file mode 100644 index 0000000..733289f --- /dev/null +++ b/Filtering/vtkExecutive.cxx @@ -0,0 +1,795 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExecutive.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExecutive.h" + +#include "vtkAlgorithm.h" +#include "vtkAlgorithmOutput.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkDataObject.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationExecutivePortKey.h" +#include "vtkInformationExecutivePortVectorKey.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationKeyVectorKey.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkSmartPointer.h" + +#include +#include + +vtkCxxRevisionMacro(vtkExecutive, "$Revision: 1.27.4.3 $"); +vtkInformationKeyMacro(vtkExecutive, ALGORITHM_AFTER_FORWARD, Integer); +vtkInformationKeyMacro(vtkExecutive, ALGORITHM_BEFORE_FORWARD, Integer); +vtkInformationKeyMacro(vtkExecutive, ALGORITHM_DIRECTION, Integer); +vtkInformationKeyMacro(vtkExecutive, CONSUMERS, ExecutivePortVector); +vtkInformationKeyMacro(vtkExecutive, FORWARD_DIRECTION, Integer); +vtkInformationKeyMacro(vtkExecutive, FROM_OUTPUT_PORT, Integer); +vtkInformationKeyMacro(vtkExecutive, KEYS_TO_COPY, KeyVector); +vtkInformationKeyMacro(vtkExecutive, PRODUCER, ExecutivePort); + +//---------------------------------------------------------------------------- +class vtkExecutiveInternals +{ +public: + vtkstd::vector InputInformation; + vtkExecutiveInternals(); + ~vtkExecutiveInternals(); + vtkInformationVector** GetInputInformation(int newNumberOfPorts); +}; + +//---------------------------------------------------------------------------- +vtkExecutiveInternals::vtkExecutiveInternals() +{ +} + +//---------------------------------------------------------------------------- +vtkExecutiveInternals::~vtkExecutiveInternals() +{ + // Delete all the input information vectors. + for(vtkstd::vector::iterator + i = this->InputInformation.begin(); + i != this->InputInformation.end(); ++i) + { + if(vtkInformationVector* v = *i) + { + v->Delete(); + } + } +} + +//---------------------------------------------------------------------------- +vtkInformationVector** +vtkExecutiveInternals::GetInputInformation(int newNumberOfPorts) +{ + // Adjust the number of vectors. + int oldNumberOfPorts = static_cast(this->InputInformation.size()); + if(newNumberOfPorts > oldNumberOfPorts) + { + // Create new vectors. + this->InputInformation.resize(newNumberOfPorts, 0); + for(int i=oldNumberOfPorts; i < newNumberOfPorts; ++i) + { + this->InputInformation[i] = vtkInformationVector::New(); + } + } + else if(newNumberOfPorts < oldNumberOfPorts) + { + // Delete old vectors. + for(int i=newNumberOfPorts; i < oldNumberOfPorts; ++i) + { + if(vtkInformationVector* v = this->InputInformation[i]) + { + // Set the pointer to NULL first to avoid reporting of the + // entry if deleting the vector causes a garbage collection + // reference walk. + this->InputInformation[i] = 0; + v->Delete(); + } + } + this->InputInformation.resize(newNumberOfPorts); + } + + // Return the array of information vector pointers. + if(newNumberOfPorts > 0) + { + return &this->InputInformation[0]; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +vtkExecutive::vtkExecutive() +{ + this->ExecutiveInternal = new vtkExecutiveInternals; + this->OutputInformation = vtkInformationVector::New(); + this->Algorithm = 0; + this->InAlgorithm = 0; + this->SharedInputInformation = 0; + this->SharedOutputInformation = 0; +} + +//---------------------------------------------------------------------------- +vtkExecutive::~vtkExecutive() +{ + this->SetAlgorithm(0); + if(this->OutputInformation) + { + this->OutputInformation->Delete(); + } + delete this->ExecutiveInternal; +} + +//---------------------------------------------------------------------------- +void vtkExecutive::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if(this->Algorithm) + { + os << indent << "Algorithm: " << this->Algorithm << "\n"; + } + else + { + os << indent << "Algorithm: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkExecutive::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkExecutive::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkExecutive::SetAlgorithm(vtkAlgorithm* newAlgorithm) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this + << "): setting Algorithm to " << newAlgorithm); + vtkAlgorithm* oldAlgorithm = this->Algorithm; + if(oldAlgorithm != newAlgorithm) + { + if(newAlgorithm) + { + newAlgorithm->Register(this); + } + this->Algorithm = newAlgorithm; + if(oldAlgorithm) + { + oldAlgorithm->UnRegister(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +vtkAlgorithm* vtkExecutive::GetAlgorithm() +{ + return this->Algorithm; +} + +//---------------------------------------------------------------------------- +vtkInformationVector** vtkExecutive::GetInputInformation() +{ + // Use the shared input information vector if any is set. + if(this->SharedInputInformation) + { + return this->SharedInputInformation; + } + + // Use this executive's input information vector. + if(this->Algorithm) + { + int numPorts = this->Algorithm->GetNumberOfInputPorts(); + return this->ExecutiveInternal->GetInputInformation(numPorts); + } + else + { + return this->ExecutiveInternal->GetInputInformation(0); + } +} + +//---------------------------------------------------------------------------- +vtkInformation* vtkExecutive::GetInputInformation(int port, int connection) +{ + if(!this->InputPortIndexInRange(port, "get connected input information from")) + { + return 0; + } + vtkInformationVector* inVector = this->GetInputInformation()[port]; + return inVector->GetInformationObject(connection); +} + +//---------------------------------------------------------------------------- +vtkInformationVector* vtkExecutive::GetInputInformation(int port) +{ + if(!this->InputPortIndexInRange(port, "get input information vector from")) + { + return 0; + } + return this->GetInputInformation()[port]; +} + +//---------------------------------------------------------------------------- +vtkInformationVector* vtkExecutive::GetOutputInformation() +{ + // Use the shared output information vector if any is set. + if(this->SharedOutputInformation) + { + return this->SharedOutputInformation; + } + + // Use this executive's output information vector. + if (!this->Algorithm) + { + return 0; + } + // Set the length of the vector to match the number of ports. + int oldNumberOfPorts = + this->OutputInformation->GetNumberOfInformationObjects(); + this->OutputInformation + ->SetNumberOfInformationObjects(this->GetNumberOfOutputPorts()); + + // For any new information obects, set the executive pointer and + // port number on the information object to tell it what produces + // it. + int nop = this->Algorithm->GetNumberOfOutputPorts(); + for(int i = oldNumberOfPorts; i < nop; ++i) + { + vtkInformation* info = this->OutputInformation->GetInformationObject(i); + info->Set(vtkExecutive::PRODUCER(), this, i); + } + + return this->OutputInformation; +} + +//---------------------------------------------------------------------------- +vtkInformation* vtkExecutive::GetOutputInformation(int port) +{ + return this->GetOutputInformation()->GetInformationObject(port); +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkExecutive::GetInputExecutive(int port, int index) +{ + if(index < 0 || index >= this->GetNumberOfInputConnections(port)) + { + vtkErrorMacro("Attempt to get executive for connection index " << index + << " on input port " << port << " of algorithm " + << this->Algorithm->GetClassName() << "(" << this->Algorithm + << "), which has " + << this->GetNumberOfInputConnections(port) + << " connections."); + return 0; + } + if(vtkAlgorithmOutput* input = this->Algorithm->GetInputConnection(port, index)) + { + return input->GetProducer()->GetExecutive(); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkExecutive::ReportReferences(vtkGarbageCollector* collector) +{ + // Report reference to our algorithm. + vtkGarbageCollectorReport(collector, this->Algorithm, "Algorithm"); + for(int i=0; i < int(this->ExecutiveInternal->InputInformation.size()); ++i) + { + vtkGarbageCollectorReport(collector, + this->ExecutiveInternal->InputInformation[i], + "Input Information Vector"); + } + vtkGarbageCollectorReport(collector, this->OutputInformation, + "Output Information Vector"); + this->Superclass::ReportReferences(collector); +} + +//---------------------------------------------------------------------------- +int vtkExecutive::Update() +{ + if (this->Algorithm->GetNumberOfOutputPorts()) + { + return this->Update(0); + } + return this->Update(-1); +} + +//---------------------------------------------------------------------------- +int vtkExecutive::Update(int) +{ + vtkErrorMacro("This class does not implement Update."); + return 0; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::GetNumberOfInputPorts() +{ + if(this->Algorithm) + { + return this->Algorithm->GetNumberOfInputPorts(); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::GetNumberOfOutputPorts() +{ + if(this->Algorithm) + { + return this->Algorithm->GetNumberOfOutputPorts(); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::GetNumberOfInputConnections(int port) +{ + vtkInformationVector* inputs = this->GetInputInformation(port); + if (inputs) + { + return inputs->GetNumberOfInformationObjects(); + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::InputPortIndexInRange(int port, const char* action) +{ + // Make sure the algorithm is set. + if(!this->Algorithm) + { + vtkErrorMacro("Attempt to " << (action?action:"access") << + " input port index " << port << " with no algorithm set."); + return 0; + } + + // Make sure the index of the input port is in range. + if(port < 0 || port >= this->Algorithm->GetNumberOfInputPorts()) + { + vtkErrorMacro("Attempt to " << (action?action:"access") + << " input port index " << port << " for algorithm " + << this->Algorithm->GetClassName() + << "(" << this->Algorithm << "), which has " + << this->Algorithm->GetNumberOfInputPorts() + << " input ports."); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::OutputPortIndexInRange(int port, const char* action) +{ + // Make sure the algorithm is set. + if(!this->Algorithm) + { + vtkErrorMacro("Attempt to " << (action?action:"access") << + " output port index " << port << " with no algorithm set."); + return 0; + } + + // Make sure the index of the output port is in range. + if(port < 0 || port >= this->Algorithm->GetNumberOfOutputPorts()) + { + vtkErrorMacro("Attempt to " << (action?action:"access") + << " output port index " << port << " for algorithm " + << this->Algorithm->GetClassName() + << "(" << this->Algorithm << "), which has " + << this->Algorithm->GetNumberOfOutputPorts() + << " output ports."); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +vtkAlgorithmOutput* vtkExecutive::GetProducerPort(vtkDataObject* d) +{ + if(this->Algorithm && d) + { + vtkInformation* info = d->GetPipelineInformation(); + vtkExecutive* dExecutive; + int port; + info->Get(vtkExecutive::PRODUCER(),dExecutive,port); + if(dExecutive == this) + { + return this->Algorithm->GetOutputPort(port); + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkExecutive::SetSharedInputInformation(vtkInformationVector** inInfoVec) +{ + this->SharedInputInformation = inInfoVec; +} + +//---------------------------------------------------------------------------- +void vtkExecutive::SetSharedOutputInformation(vtkInformationVector* outInfoVec) +{ + this->SharedOutputInformation = outInfoVec; +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkExecutive::GetOutputData(int port) +{ + if(!this->OutputPortIndexInRange(port, "get data for")) + { + return 0; + } + + vtkInformation* info = this->GetOutputInformation(port); + if (!info) + { + return 0; + } + + // for backward compatibility we bring Outputs up to date if they do not + // already exist + if (!this->InAlgorithm && !info->Has(vtkDataObject::DATA_OBJECT())) + { + // Bring the data object up to date only if it isn't already there + this->UpdateDataObject(); + } + + // Return the data object. + return info->Get(vtkDataObject::DATA_OBJECT()); +} + +//---------------------------------------------------------------------------- +void vtkExecutive::SetOutputData(int newPort, vtkDataObject* newOutput) +{ + vtkInformation *info = this->GetOutputInformation(newPort); + this->SetOutputData(newPort, newOutput, info); +} + +//---------------------------------------------------------------------------- +void vtkExecutive::SetOutputData(int newPort, vtkDataObject* newOutput, + vtkInformation* info) +{ + if(info) + { + if(!newOutput || newOutput->GetPipelineInformation() != info) + { + if(newOutput) + { + newOutput->SetPipelineInformation(info); + } + else if(vtkDataObject* oldOutput = info->Get(vtkDataObject::DATA_OBJECT())) + { + oldOutput->Register(this); + oldOutput->SetPipelineInformation(0); + oldOutput->UnRegister(this); + } + + // Output has changed. Reset the pipeline information. + this->ResetPipelineInformation(newPort, info); + } + } + else + { + vtkErrorMacro("Could not set output on port " << newPort << "."); + } +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkExecutive::GetInputData(int port, int index) +{ + if(index < 0 || index >= this->GetNumberOfInputConnections(port)) + { + return 0; + } + + vtkInformationVector* inVector = this->GetInputInformation()[port]; + vtkInformation* info = inVector->GetInformationObject(index); + vtkExecutive* e; + int producerPort; + info->Get(vtkExecutive::PRODUCER(),e,producerPort); + if(e) + { + return e->GetOutputData(producerPort); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkExecutive::GetInputData +(int port, int index, vtkInformationVector **inInfoVec) +{ + if (!inInfoVec[port]) + { + return 0; + } + vtkInformation *info = inInfoVec[port]->GetInformationObject(index); + if (!info) + { + return 0; + } + return info->Get(vtkDataObject::DATA_OBJECT()); +} + +//---------------------------------------------------------------------------- +int vtkExecutive::ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo) +{ + if(request->Has(FORWARD_DIRECTION())) + { + // Request will be forwarded. + if(request->Get(FORWARD_DIRECTION()) == vtkExecutive::RequestUpstream) + { + if(this->Algorithm && request->Get(ALGORITHM_BEFORE_FORWARD())) + { + if(!this->CallAlgorithm(request, vtkExecutive::RequestUpstream, + inInfo, outInfo)) + { + return 0; + } + } + if(!this->ForwardUpstream(request)) + { + return 0; + } + if(this->Algorithm && request->Get(ALGORITHM_AFTER_FORWARD())) + { + if(!this->CallAlgorithm(request, vtkExecutive::RequestDownstream, + inInfo, outInfo)) + { + return 0; + } + } + } + if(request->Get(FORWARD_DIRECTION()) == vtkExecutive::RequestDownstream) + { + vtkErrorMacro("Downstream forwarding not yet implemented."); + return 0; + } + } + else + { + // Request will not be forwarded. + vtkErrorMacro("Non-forwarded requests are not yet implemented."); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::ComputePipelineMTime(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*, + int, unsigned long*) +{ + // Demand-driven executives that use this request should implement + // this method. + vtkErrorMacro("ComputePipelineMTime not implemented for this executive."); + return 0; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::ForwardDownstream(vtkInformation*) +{ + // Do not forward downstream if the output is shared with another + // executive. + if(this->SharedOutputInformation) + { + return 1; + } + + // Forwarding downstream is not yet implemented. + vtkErrorMacro("ForwardDownstream not yet implemented."); + return 0; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::ForwardUpstream(vtkInformation* request) +{ + // Do not forward upstream if the input is shared with another + // executive. + if(this->SharedInputInformation) + { + return 1; + } + + if (!this->Algorithm->ModifyRequest(request, BeforeForward)) + { + return 0; + } + + // Forward the request upstream through all input connections. + int result = 1; + for(int i=0; i < this->GetNumberOfInputPorts(); ++i) + { + int nic = this->Algorithm->GetNumberOfInputConnections(i); + vtkInformationVector* inVector = this->GetInputInformation()[i]; + for(int j=0; j < nic; ++j) + { + vtkInformation* info = inVector->GetInformationObject(j); + // Get the executive producing this input. If there is none, then + // it is a NULL input. + vtkExecutive* e; + int producerPort; + info->Get(vtkExecutive::PRODUCER(),e,producerPort); + if(e) + { + int port = request->Get(FROM_OUTPUT_PORT()); + request->Set(FROM_OUTPUT_PORT(), producerPort); + if(!e->ProcessRequest(request, + e->GetInputInformation(), + e->GetOutputInformation())) + { + result = 0; + } + request->Set(FROM_OUTPUT_PORT(), port); + } + } + } + + if (!this->Algorithm->ModifyRequest(request, AfterForward)) + { + return 0; + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkExecutive::CopyDefaultInformation(vtkInformation* request, + int direction, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) + +{ + if(direction == vtkExecutive::RequestDownstream) + { + // Copy information from the first input to all outputs. + if(this->GetNumberOfInputPorts() > 0 && + inInfoVec[0]->GetNumberOfInformationObjects() > 0) + { + vtkInformationKey** keys = request->Get(KEYS_TO_COPY()); + int length = request->Length(KEYS_TO_COPY()); + vtkInformation* inInfo = inInfoVec[0]->GetInformationObject(0); + int oiobj = outInfoVec->GetNumberOfInformationObjects(); + for(int i=0; i < oiobj; ++i) + { + vtkInformation* outInfo = outInfoVec->GetInformationObject(i); + for(int j=0; j < length; ++j) + { + // Copy the entry. + outInfo->CopyEntry(inInfo, keys[j]); + + // If the entry is a key vector, copy all the keys listed. + if(vtkInformationKeyVectorKey* vkey = + vtkInformationKeyVectorKey::SafeDownCast(keys[j])) + { + outInfo->CopyEntries(inInfo, vkey); + } + } + } + } + } + else + { + // Get the output port from which the request was made. Use zero + // if output port was not specified. + int outputPort = 0; + if(request->Has(FROM_OUTPUT_PORT())) + { + outputPort = request->Get(FROM_OUTPUT_PORT()); + } + + // Copy information from the requesting output to all inputs. + if(outputPort >= 0 && + outputPort < outInfoVec->GetNumberOfInformationObjects()) + { + vtkInformationKey** keys = request->Get(KEYS_TO_COPY()); + int length = request->Length(KEYS_TO_COPY()); + vtkInformation* outInfo = outInfoVec->GetInformationObject(outputPort); + for(int i=0; i < this->GetNumberOfInputPorts(); ++i) + { + for(int j=0; j < inInfoVec[i]->GetNumberOfInformationObjects(); ++j) + { + vtkInformation* inInfo = inInfoVec[i]->GetInformationObject(j); + for(int k=0; k < length; ++k) + { + // Copy the entry. + inInfo->CopyEntry(outInfo, keys[k]); + + // If the entry is a key vector, copy all the keys listed. + if(vtkInformationKeyVectorKey* vkey = + vtkInformationKeyVectorKey::SafeDownCast(keys[k])) + { + inInfo->CopyEntries(outInfo, vkey); + } + } + } + } + } + } +} + +//---------------------------------------------------------------------------- +int vtkExecutive::CallAlgorithm(vtkInformation* request, int direction, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo) +{ + // Copy default information in the direction of information flow. + this->CopyDefaultInformation(request, direction, inInfo, outInfo); + + // Invoke the request on the algorithm. + this->InAlgorithm = 1; + int result = this->Algorithm->ProcessRequest(request, inInfo, outInfo); + this->InAlgorithm = 0; + + // If the algorithm failed report it now. + if(!result) + { + vtkErrorMacro("Algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm + << ") returned failure for request: " + << *request); + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkExecutive::CheckAlgorithm(const char* method, + vtkInformation* request) +{ + if(this->InAlgorithm) + { + if(request) + { + vtksys_ios::ostringstream rqmsg; + request->Print(rqmsg); + vtkErrorMacro(<< method << " invoked during another request. " + "Returning failure to algorithm " + << this->Algorithm->GetClassName() << "(" + << this->Algorithm << ") for the recursive request:\n" + << rqmsg.str().c_str()); + } + else + { + vtkErrorMacro(<< method << " invoked during another request. " + "Returning failure to algorithm " + << this->Algorithm->GetClassName() << "(" + << this->Algorithm << ")."); + } + + // Tests should fail when this happens because there is a bug in + // the code. + if(getenv("DASHBOARD_TEST_FROM_CTEST") || getenv("DART_TEST_FROM_DART")) + { + abort(); + } + return 0; + } + return 1; +} diff --git a/Filtering/vtkExecutive.h b/Filtering/vtkExecutive.h new file mode 100644 index 0000000..a6674bb --- /dev/null +++ b/Filtering/vtkExecutive.h @@ -0,0 +1,246 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExecutive.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExecutive - Superclass for all pipeline executives in VTK. +// .SECTION Description +// vtkExecutive is the superclass for all pipeline executives in VTK. +// A VTK executive is responsible for controlling one instance of +// vtkAlgorithm. A pipeline consists of one or more executives that +// control data flow. Every reader, source, writer, or data +// processing algorithm in the pipeline is implemented in an instance +// of vtkAlgorithm. + +#ifndef __vtkExecutive_h +#define __vtkExecutive_h + +#include "vtkObject.h" + +class vtkAlgorithm; +class vtkAlgorithmOutput; +class vtkAlgorithmToExecutiveFriendship; +class vtkDataObject; +class vtkExecutiveInternals; +class vtkInformation; +class vtkInformationExecutivePortKey; +class vtkInformationExecutivePortVectorKey; +class vtkInformationIntegerKey; +class vtkInformationRequestKey; +class vtkInformationKeyVectorKey; +class vtkInformationVector; + +class VTK_FILTERING_EXPORT vtkExecutive : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkExecutive,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the algorithm to which this executive has been assigned. + vtkAlgorithm* GetAlgorithm(); + + // Description: + // Generalized interface for asking the executive to fullfill + // pipeline requests. + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + // Description: + // A special version of ProcessRequest meant specifically for the + // pipeline modified time request. This is an optimization since + // the request is called so often and it travels the full length of + // the pipeline. We augment the signature with method arguments + // containing the common information, specifically the output port + // through which the request was made and the resulting modified + // time. Note that unlike ProcessRequest the request information + // object may be NULL for this method. It also does not contain a + // request identifcation key because the request is known from the + // method name. + virtual int + ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int requestFromOutputPort, + unsigned long* mtime); + + // Description: + // Bring the algorithm's outputs up-to-date. Returns 1 for success + // and 0 for failure. + virtual int Update(); + virtual int Update(int port); + + // Description: + // Get the number of input/output ports for the algorithm associated + // with this executive. Returns 0 if no algorithm is set. + int GetNumberOfInputPorts(); + int GetNumberOfOutputPorts(); + + // Description: + // Get the number of input connections on the given port. + int GetNumberOfInputConnections(int port); + + // Description: + // Get the pipeline information object for the given output port. + virtual vtkInformation* GetOutputInformation(int port); + + // Description: + // Get the pipeline information object for all output ports. + vtkInformationVector* GetOutputInformation(); + + // Description: + // Get the pipeline information for the given input connection. + vtkInformation* GetInputInformation(int port, int connection); + + // Description: + // Get the pipeline information vectors for the given input port. + vtkInformationVector* GetInputInformation(int port); + + // Description: + // Get the pipeline information vectors for all inputs + vtkInformationVector** GetInputInformation(); + + // Description: + // Get the executive managing the given input connection. + vtkExecutive* GetInputExecutive(int port, int connection); + + // Description: + // Get/Set the data object for an output port of the algorithm. + virtual vtkDataObject* GetOutputData(int port); + virtual void SetOutputData(int port, vtkDataObject*, vtkInformation *info); + virtual void SetOutputData(int port, vtkDataObject*); + + // Description: + // Get the data object for an output port of the algorithm. + virtual vtkDataObject* GetInputData(int port, int connection); + virtual vtkDataObject* GetInputData(int port, int connection, + vtkInformationVector **inInfoVec); + + // Description: + // Get the output port that produces the given data object. + virtual vtkAlgorithmOutput* GetProducerPort(vtkDataObject*); + + // Description: + // Set a pointer to an outside instance of input or output + // information vectors. No references are held to the given + // vectors, and setting this does not change the executive object + // modification time. This is a preliminary interface to use in + // implementing filters with internal pipelines, and may change + // without notice when a future interface is created. + void SetSharedInputInformation(vtkInformationVector** inInfoVec); + void SetSharedOutputInformation(vtkInformationVector* outInfoVec); + + // Description: + // Participate in garbage collection. + virtual void Register(vtkObjectBase* o); + virtual void UnRegister(vtkObjectBase* o); + + // Description: + // Information key to store the executive/port number producing an + // information object. + static vtkInformationExecutivePortKey* PRODUCER(); + + // Description: + // Information key to store the executive/port number pairs + // consuming an information object. + static vtkInformationExecutivePortVectorKey* CONSUMERS(); + + // Description: + // Information key to store the output port number from which a + // request is made. + static vtkInformationIntegerKey* FROM_OUTPUT_PORT(); + + // Description: + // Keys to program vtkExecutive::ProcessRequest with the default + // behavior for unknown requests. + static vtkInformationIntegerKey* ALGORITHM_BEFORE_FORWARD(); + static vtkInformationIntegerKey* ALGORITHM_AFTER_FORWARD(); + static vtkInformationIntegerKey* ALGORITHM_DIRECTION(); + static vtkInformationIntegerKey* FORWARD_DIRECTION(); + static vtkInformationKeyVectorKey* KEYS_TO_COPY(); + //BTX + enum { RequestUpstream, RequestDownstream }; + enum { BeforeForward, AfterForward }; + //ETX + + // Description: + // An API to CallAlgorithm that allows you to pass in the info objects to + // be used + virtual int CallAlgorithm(vtkInformation* request, int direction, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + +protected: + vtkExecutive(); + ~vtkExecutive(); + + // Helper methods for subclasses. + int InputPortIndexInRange(int port, const char* action); + int OutputPortIndexInRange(int port, const char* action); + + // Called by methods to check for a recursive pipeline update. A + // request should be fulfilled without making another request. This + // is used to help enforce that behavior. Returns 1 if no recursive + // request is occurring, and 0 otherwise. An error message is + // produced automatically if 0 is returned. The first argument is + // the name of the calling method (the one that should not be + // invoked recursively during an update). The second argument is + // the recursive request information object, if any. It is used to + // construct the error message. + int CheckAlgorithm(const char* method, vtkInformation* request); + + virtual int ForwardDownstream(vtkInformation* request); + virtual int ForwardUpstream(vtkInformation* request); + virtual void CopyDefaultInformation(vtkInformation* request, int direction, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + // Reset the pipeline update values in the given output information object. + virtual void ResetPipelineInformation(int port, vtkInformation*)=0; + + // Bring the existence of output data objects up to date. + virtual int UpdateDataObject()=0; + + // Garbage collection support. + virtual void ReportReferences(vtkGarbageCollector*); + + virtual void SetAlgorithm(vtkAlgorithm* algorithm); + + // The algorithm managed by this executive. + vtkAlgorithm* Algorithm; + + // Flag set when the algorithm is processing a request. + int InAlgorithm; + + // Pointers to an outside instance of input or output information. + // No references are held. These are used to implement internal + // pipelines. + vtkInformationVector** SharedInputInformation; + vtkInformationVector* SharedOutputInformation; + +private: + // Store an information object for each output port of the algorithm. + vtkInformationVector* OutputInformation; + + // Internal implementation details. + vtkExecutiveInternals* ExecutiveInternal; + + //BTX + friend class vtkAlgorithmToExecutiveFriendship; + //ETX +private: + vtkExecutive(const vtkExecutive&); // Not implemented. + void operator=(const vtkExecutive&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkExplicitCell.cxx b/Filtering/vtkExplicitCell.cxx new file mode 100644 index 0000000..19cbbf4 --- /dev/null +++ b/Filtering/vtkExplicitCell.cxx @@ -0,0 +1,36 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExplicitCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExplicitCell.h" + +#include "vtkCellArray.h" +#include "vtkObjectFactory.h" +#include "vtkDataSet.h" + +vtkCxxRevisionMacro(vtkExplicitCell, "$Revision: 1.1 $"); +vtkCxxSetObjectMacro(vtkExplicitCell,DataSet,vtkDataSet); + +vtkExplicitCell::vtkExplicitCell() +{ + this->CellId = -1; + this->DataSet = NULL; +} + +void vtkExplicitCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cell Id: " << this->CellId << "\n"; + os << indent << "Data Set: " << this->DataSet << "\n"; +} diff --git a/Filtering/vtkExplicitCell.h b/Filtering/vtkExplicitCell.h new file mode 100644 index 0000000..70e583e --- /dev/null +++ b/Filtering/vtkExplicitCell.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExplicitCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExplicitCell - abstract superclass for cells requiring an explicit representation +// .SECTION Description +// vtkExplicitCell is an abstract superclass for cells that cannot be +// represented implicitly. An implicit representation requires only a +// cell type and connectivity list (e.g., triangle). Explicit cells +// require information beyond this; e.g., a NURBS surface or cells that +// require explicit face/edge descriptions. Most cells in VTK are +// implicitly represented. + +#ifndef __vtkExplicitCell_h +#define __vtkExplicitCell_h + +#include "vtkNonLinearCell.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkExplicitCell : public vtkNonLinearCell +{ +public: + vtkTypeRevisionMacro(vtkExplicitCell,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Explicit cells require additional representational information + // beyond the usual cell type and connectivity list information. + // Most cells in VTK are implicit cells. The vtkCell::IsImplicitCell() + // virtual function is overloaded to reflect this requirement. + virtual int IsExplicitCell() {return 1;} + + // Description: + // Set/Get the cell id. This is necessary for explicit cells because they + // often need to keep extra information (typically contained in the + // cell data of a point set). This information might be things like + // knot points/weights, boundaries, etc. + vtkSetMacro(CellId,vtkIdType); + vtkGetMacro(CellId,vtkIdType); + + // Description: + // Set/Get the mesh that owns this cell. This is necessary for explicit + // cells because they often need to keep extra information (typically + // contained in the cell data of a point set). This information might be + // things like knot points/weights, boundaries, etc. + virtual void SetDataSet(vtkDataSet*); + vtkGetObjectMacro(DataSet,vtkDataSet); + +protected: + vtkExplicitCell(); + ~vtkExplicitCell() {} + + vtkIdType CellId; //used to index into other arrays + vtkDataSet *DataSet; //dataset from which this cell came + +private: + vtkExplicitCell(const vtkExplicitCell&); // Not implemented. + void operator=(const vtkExplicitCell&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkFieldData.cxx b/Filtering/vtkFieldData.cxx new file mode 100644 index 0000000..760783c --- /dev/null +++ b/Filtering/vtkFieldData.cxx @@ -0,0 +1,898 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFieldData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFieldData.h" + +#include "vtkObjectFactory.h" +#include "vtkIdList.h" + +vtkCxxRevisionMacro(vtkFieldData, "$Revision: 1.2.6.2 $"); +vtkStandardNewMacro(vtkFieldData); + +//---------------------------------------------------------------------------- +vtkFieldData::BasicIterator::BasicIterator(const int* list, + unsigned int listSize) +{ + if (list) + { + if (listSize>0) + { + this->List = new int[listSize]; + memcpy(this->List, list, listSize*sizeof(int)); + } + else + { + this->List = 0; + } + this->ListSize = listSize; + } + else + { + this->ListSize = 0; + } + this->Position = 0; +} + +//---------------------------------------------------------------------------- +vtkFieldData::Iterator::Iterator(vtkFieldData* dsa, const int* list, + unsigned int listSize) + : vtkFieldData::BasicIterator(list, listSize) +{ + this->Fields = dsa; + dsa->Register(0); + if (!list) + { + this->ListSize = dsa->GetNumberOfArrays(); + this->List = new int[this->ListSize]; + for(int i=0; iListSize; i++) { this->List[i] = i; } + } + this->Detached = 0; +} + +//---------------------------------------------------------------------------- +vtkFieldData::BasicIterator::BasicIterator() +{ + this->List = 0; + this->ListSize = 0; +} + +//---------------------------------------------------------------------------- +vtkFieldData::BasicIterator::BasicIterator(const vtkFieldData::BasicIterator& + source) +{ + this->ListSize = source.ListSize; + + if (this->ListSize > 0) + { + this->List = new int[this->ListSize]; + memcpy(this->List, source.List, this->ListSize*sizeof(int)); + } + else + { + this->List = 0; + } +} + +//---------------------------------------------------------------------------- +vtkFieldData::Iterator::Iterator(const vtkFieldData::Iterator& source) + : vtkFieldData::BasicIterator(source) +{ + this->Detached = source.Detached; + this->Fields = source.Fields; + if (this->Fields && !this->Detached) + { + this->Fields->Register(0); + } +} + +//---------------------------------------------------------------------------- +vtkFieldData::BasicIterator& vtkFieldData::BasicIterator::operator=( + const vtkFieldData::BasicIterator& source) +{ + if (this == &source) + { + return *this; + } + delete[] this->List; + this->ListSize = source.ListSize; + if (this->ListSize > 0) + { + this->List = new int[this->ListSize]; + memcpy(this->List, source.List, this->ListSize*sizeof(int)); + } + else + { + this->List = 0; + } + return *this; +} + +//---------------------------------------------------------------------------- +vtkFieldData::Iterator& vtkFieldData::Iterator::operator=( + const vtkFieldData::Iterator& source) +{ + if (this == &source) + { + return *this; + } + this->BasicIterator::operator=(source); + if (this->Fields && !this->Detached) + { + this->Fields->UnRegister(0); + } + this->Fields = source.Fields; + this->Detached = source.Detached; + if (this->Fields && !this->Detached) + { + this->Fields->Register(0); + } + return *this; +} + +//---------------------------------------------------------------------------- +vtkFieldData::BasicIterator::~BasicIterator() +{ + delete[] this->List; +} + +//---------------------------------------------------------------------------- +vtkFieldData::Iterator::~Iterator() +{ + if (this->Fields && !this->Detached) + { + this->Fields->UnRegister(0); + } +} + +//---------------------------------------------------------------------------- +void vtkFieldData::Iterator::DetachFieldData() +{ + if (this->Fields && !this->Detached) + { + this->Fields->UnRegister(0); + this->Detached = 1; + } +} + +//---------------------------------------------------------------------------- +// Construct object with no data initially. +vtkFieldData::vtkFieldData() +{ + this->NumberOfArrays = 0; + this->Data = NULL; + + this->TupleSize = 0; + this->Tuple = NULL; + + this->NumberOfActiveArrays = 0; + + this->CopyFieldFlags = 0; + this->NumberOfFieldFlags = 0; + + this->DoCopyAllOn = 1; + this->DoCopyAllOff = 0; + + this->CopyAllOn(); +} + +//---------------------------------------------------------------------------- +vtkFieldData::~vtkFieldData() +{ + this->Initialize(); + delete[] this->Tuple; + this->ClearFieldFlags(); +} + +//---------------------------------------------------------------------------- +// Release all data but do not delete object. +void vtkFieldData::InitializeFields() +{ + int i; + + if ( this->Data ) + { + for ( i=0; iGetNumberOfArrays(); i++ ) + { + this->Data[i]->UnRegister(this); + } + + delete [] this->Data; + this->Data = NULL; + } + + this->NumberOfArrays = 0; + this->NumberOfActiveArrays = 0; + this->Modified(); + +} + +//---------------------------------------------------------------------------- +// Release all data but do not delete object. +// Also initialize copy flags. +void vtkFieldData::Initialize() +{ + this->InitializeFields(); + this->CopyAllOn(); + this->ClearFieldFlags(); +} + +//---------------------------------------------------------------------------- +// Allocate data for each array. +int vtkFieldData::Allocate(const vtkIdType sz, const vtkIdType ext) +{ + int i; + int status = 0; + + for ( i=0; i < this->GetNumberOfArrays(); i++ ) + { + if ( (status = this->Data[i]->Allocate(sz,ext)) == 0 ) + { + break; + } + } + + return status; +} + +//---------------------------------------------------------------------------- +void vtkFieldData::CopyStructure(vtkFieldData* r) +{ + // Free old fields. + this->InitializeFields(); + + // Allocate new fields. + this->AllocateArrays(r->GetNumberOfArrays()); + this->NumberOfActiveArrays = r->GetNumberOfArrays(); + + // Copy the data arrays without data. + int i; + vtkDataArray *data; + for(i=0; i < r->GetNumberOfArrays(); ++i) + { + data = r->Data[i]->NewInstance(); + data->SetNumberOfComponents(r->Data[i]->GetNumberOfComponents()); + data->SetName(r->Data[i]->GetName()); + this->SetArray(i, data); + data->Delete(); + } +} + +//---------------------------------------------------------------------------- +// Set the number of arrays used to define the field. +void vtkFieldData::AllocateArrays(int num) +{ + int i; + + if ( num < 0 ) + { + num = 0; + } + + if ( num == this->NumberOfArrays ) + { + return; + } + else + { + this->Modified(); + } + + if ( num == 0 ) + { + this->Initialize(); + } + else if ( num < this->NumberOfArrays ) + { + for ( i=num; i < this->NumberOfArrays; i++) + { + if( this->Data[i] ) + { + this->Data[i]->UnRegister(this); + } + } + this->NumberOfArrays = num; + } + else //num > this->NumberOfArrays + { + vtkDataArray **data=new vtkDataArray * [num]; + // copy the original data + for ( i=0; i < this->NumberOfArrays; i++ ) + { + data[i] = this->Data[i]; + } + + //initialize the new arrays + for ( i=this->NumberOfArrays; i < num; i++ ) + { + data[i] = 0; + } + + // get rid of the old data + delete [] this->Data; + + // update object + this->Data = data; + this->NumberOfArrays = num; + } +} + +//---------------------------------------------------------------------------- +// Set an array to define the field. +void vtkFieldData::SetArray(int i, vtkDataArray *data) +{ + if (!data || (i > this->NumberOfActiveArrays)) + { + vtkWarningMacro("Can not set array " << i << " to " << data << endl); + return; + } + + int numComp; + + if ( i < 0 ) + { + vtkWarningMacro("Array index should be >= 0"); + return; + } + else if (i >= this->NumberOfArrays) + { + this->AllocateArrays(i+1); + this->NumberOfActiveArrays = i+1; + } + + if ( this->Data[i] != data ) + { + this->Modified(); + if ( this->Data[i] != NULL ) + { + this->Data[i]->UnRegister(this); + } + this->Data[i] = data; + if ( this->Data[i] != NULL ) + { + this->Data[i]->Register(this); + } + } + + // adjust scratch tuple array + numComp = this->GetNumberOfComponents(); + if ( numComp != this->TupleSize ) + { + this->TupleSize = numComp; + if ( this->Tuple ) + { + delete [] this->Tuple; + } + this->Tuple = new double[this->TupleSize]; + } +} + +//---------------------------------------------------------------------------- +// Return the ith array in the field. A NULL is returned if the index i is out +// if range. +vtkDataArray *vtkFieldData::GetArray(int i) +{ + if ( i < 0 || i >= this->GetNumberOfArrays() ) + { + return 0; + } + return this->Data[i]; +} + +//---------------------------------------------------------------------------- +// Copy a field by reference counting the data arrays. +void vtkFieldData::DeepCopy(vtkFieldData *f) +{ + vtkDataArray *data, *newData; + + this->AllocateArrays(f->GetNumberOfArrays()); + for ( int i=0; i < f->GetNumberOfArrays(); i++ ) + { + data = f->GetArray(i); + newData = data->NewInstance(); //instantiate same type of object + newData->DeepCopy(data); + newData->SetName(data->GetName()); + this->AddArray(newData); + newData->Delete(); + } +} + +//---------------------------------------------------------------------------- +// Copy a field by reference counting the data arrays. +void vtkFieldData::ShallowCopy(vtkFieldData *f) +{ + this->AllocateArrays(f->GetNumberOfArrays()); + this->NumberOfActiveArrays = 0; + + for ( int i=0; i < f->GetNumberOfArrays(); i++ ) + { + this->NumberOfActiveArrays++; + this->SetArray(i, f->GetArray(i)); + } + this->CopyFlags(f); +} + + +//---------------------------------------------------------------------------- +// Squeezes each data array in the field (Squeeze() reclaims unused memory.) +void vtkFieldData::Squeeze() +{ + for ( int i=0; i < this->GetNumberOfArrays(); i++ ) + { + this->Data[i]->Squeeze(); + } +} + +//---------------------------------------------------------------------------- +// Resets each data array in the field (Reset() does not release memory but +// it makes the arrays look like they are empty.) +void vtkFieldData::Reset() +{ + int i; + + for ( i=0; i < this->GetNumberOfArrays(); i++ ) + { + this->Data[i]->Reset(); + } +} + +//---------------------------------------------------------------------------- +// Get a field from a list of ids. Supplied field f should have same +// types and number of data arrays as this one (i.e., like +// CopyStructure() creates). +void vtkFieldData::GetField(vtkIdList *ptIds, vtkFieldData *f) +{ + int i, numIds=ptIds->GetNumberOfIds(); + + for (i=0; i < numIds; i++) + { + f->InsertTuple(i, this->GetTuple(ptIds->GetId(i))); + } +} + +//---------------------------------------------------------------------------- +// Return the array containing the ith component of the field. The return value +// is an integer number n 0<=nNumberOfArrays. Also, an integer value is +// returned indicating the component in the array is returned. Method returns +// -1 if specified component is not in field. +int vtkFieldData::GetArrayContainingComponent(int i, int& arrayComp) +{ + int numComp, count=0; + + for ( int j=0; j < this->GetNumberOfArrays(); j++ ) + { + if ( this->Data[j] != NULL ) + { + numComp = this->Data[j]->GetNumberOfComponents(); + if ( i < (numComp + count) ) + { + arrayComp = i - count; + return j; + } + count += numComp; + } + } + return -1; +} + +//---------------------------------------------------------------------------- +vtkDataArray *vtkFieldData::GetArray(const char *arrayName, int &index) +{ + int i; + const char *name; + index = -1; + if (!arrayName) + { + return NULL; + } + for (i=0; i < this->GetNumberOfArrays(); i++) + { + name = this->GetArrayName(i); + if ( name && !strcmp(name,arrayName) ) + { + index = i; + return this->GetArray(i); + } + } + return NULL; +} + +//---------------------------------------------------------------------------- +int vtkFieldData::AddArray(vtkDataArray *array) +{ + if (!array) + { + return -1; + } + + int index; + this->GetArray(array->GetName(), index); + + if (index == -1) + { + index = this->NumberOfActiveArrays; + this->NumberOfActiveArrays++; + } + this->SetArray(index, array); + return index; +} + +//---------------------------------------------------------------------------- +void vtkFieldData::RemoveArray(int index) +{ + if ( (index<0) || (index>=this->NumberOfActiveArrays)) + { + return; + } + this->Data[index]->UnRegister(this); + this->Data[index] = 0; + this->NumberOfActiveArrays--; + for(int i=index; iNumberOfActiveArrays; i++) + { + this->Data[i] = this->Data[i+1]; + } + this->Data[this->NumberOfActiveArrays] = 0; +} + +//---------------------------------------------------------------------------- +unsigned long vtkFieldData::GetActualMemorySize() +{ + unsigned long size=0; + + for ( int i=0; i < this->GetNumberOfArrays(); i++ ) + { + if ( this->Data[i] != NULL ) + { + size += this->Data[i]->GetActualMemorySize(); + } + } + + return size; +} + +//---------------------------------------------------------------------------- +unsigned long int vtkFieldData::GetMTime() +{ + unsigned long int mTime = this->MTime; + unsigned long int otherMTime; + vtkDataArray* da; + + for(int i=0; i < this->NumberOfActiveArrays; i++) + { + if ((da=this->Data[i])) + { + otherMTime = da->GetMTime(); + if ( otherMTime > mTime ) + { + mTime = otherMTime; + } + } + } + + return mTime; +} + +//---------------------------------------------------------------------------- +void vtkFieldData::CopyFieldOnOff(const char* field, int onOff) +{ + if (!field) { return; } + + int index; + // If the array is in the list, simply set IsCopied to onOff + if ((index=this->FindFlag(field)) != -1) + { + if (this->CopyFieldFlags[index].IsCopied != onOff) + { + this->CopyFieldFlags[index].IsCopied = onOff; + this->Modified(); + } + } + else + { + // We need to reallocate the list of fields + vtkFieldData::CopyFieldFlag* newFlags = + new vtkFieldData::CopyFieldFlag[this->NumberOfFieldFlags+1]; + // Copy old flags (pointer copy for name) + for(int i=0; iNumberOfFieldFlags; i++) + { + newFlags[i].ArrayName = this->CopyFieldFlags[i].ArrayName; + newFlags[i].IsCopied = this->CopyFieldFlags[i].IsCopied; + } + // Copy new flag (strcpy) + char* newName = new char[strlen(field)+1]; + strcpy(newName, field); + newFlags[this->NumberOfFieldFlags].ArrayName = newName; + newFlags[this->NumberOfFieldFlags].IsCopied = onOff; + this->NumberOfFieldFlags++; + delete[] this->CopyFieldFlags; + this->CopyFieldFlags = newFlags; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Turn on copying of all data. +void vtkFieldData::CopyAllOn() +{ + if ( !DoCopyAllOn || DoCopyAllOff ) + { + this->DoCopyAllOn = 1; + this->DoCopyAllOff = 0; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Turn off copying of all data. +void vtkFieldData::CopyAllOff() +{ + if ( DoCopyAllOn || !DoCopyAllOff ) + { + this->DoCopyAllOn = 0; + this->DoCopyAllOff = 1; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Deallocate and clear the list of fields. +void vtkFieldData::ClearFieldFlags() +{ + if (this->NumberOfFieldFlags > 0) + { + for(int i=0; iNumberOfFieldFlags; i++) + { + delete[] this->CopyFieldFlags[i].ArrayName; + } + } + delete[] this->CopyFieldFlags; + this->CopyFieldFlags=0; + this->NumberOfFieldFlags=0; +} + +//---------------------------------------------------------------------------- +// Find if field is in CopyFieldFlags. +// If it is, it returns the index otherwise it returns -1 +int vtkFieldData::FindFlag(const char* field) +{ + if ( !field ) return -1; + for(int i=0; iNumberOfFieldFlags; i++) + { + if (this->CopyFieldFlags[i].ArrayName && + !strcmp(field, this->CopyFieldFlags[i].ArrayName)) + { + return i; + } + } + return -1; +} + +//---------------------------------------------------------------------------- +// If there is no flag for this array, return -1. +// If there is one: return 0 if off, 1 if on +int vtkFieldData::GetFlag(const char* field) +{ + int index = this->FindFlag(field); + if ( index == -1 ) + { + return -1; + } + else + { + return this->CopyFieldFlags[index].IsCopied; + } +} + +//---------------------------------------------------------------------------- +// Copy the fields list (with strcpy) +void vtkFieldData::CopyFlags(const vtkFieldData* source) +{ + this->ClearFieldFlags(); + this->NumberOfFieldFlags = source->NumberOfFieldFlags; + if ( this->NumberOfFieldFlags > 0 ) + { + this->CopyFieldFlags = new + vtkFieldData::CopyFieldFlag[this->NumberOfFieldFlags]; + for(int i=0; iNumberOfFieldFlags; i++) + { + this->CopyFieldFlags[i].ArrayName = + new char[strlen(source->CopyFieldFlags[i].ArrayName)+1]; + strcpy(this->CopyFieldFlags[i].ArrayName, + source->CopyFieldFlags[i].ArrayName); + } + } + else + { + this->CopyFieldFlags = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkFieldData::PassData(vtkFieldData* fd) +{ + for(int i=0; iGetNumberOfArrays(); i++) + { + const char* arrayName = fd->GetArrayName(i); + // If there is no blocker for the given array + // and both CopyAllOff and CopyOn for that array are not true + if ( (this->GetFlag(arrayName) != 0) && + !(this->DoCopyAllOff && (this->GetFlag(arrayName) != 1)) && + fd->GetArray(i)) + { + this->AddArray(fd->GetArray(i)); + } + } +} + +//---------------------------------------------------------------------------- +void vtkFieldData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Arrays: " << this->GetNumberOfArrays() << "\n"; + for (int i=0; iGetNumberOfArrays(); i++) + { + if (this->GetArrayName(i)) + { + os << indent << "Array " << i << " name = " + << this->GetArrayName(i) << "\n"; + } + else + { + os << indent << "Array " << i << " name = NULL\n"; + } + } + os << indent << "Number Of Components: " << this->GetNumberOfComponents() + << "\n"; + os << indent << "Number Of Tuples: " << this->GetNumberOfTuples() << "\n"; +} + +//---------------------------------------------------------------------------- +// Get the number of components in the field. This is determined by adding +// up the components in each non-NULL array. +int vtkFieldData::GetNumberOfComponents() +{ + int i, numComp; + + for ( i=numComp=0; i < this->GetNumberOfArrays(); i++ ) + { + if (this->Data[i]) + { + numComp += this->Data[i]->GetNumberOfComponents(); + } + } + + return numComp; +} + +//---------------------------------------------------------------------------- +// Get the number of tuples in the field. +vtkIdType vtkFieldData::GetNumberOfTuples() +{ + vtkDataArray* da; + if ((da=this->GetArray(0))) + { + return da->GetNumberOfTuples(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +// Set the number of tuples for each data array in the field. +void vtkFieldData::SetNumberOfTuples(const vtkIdType number) +{ + for ( int i=0; i < this->GetNumberOfArrays(); i++ ) + { + this->Data[i]->SetNumberOfTuples(number); + } +} + +//---------------------------------------------------------------------------- +// Return a tuple consisting of a concatentation of all data from all +// the different arrays. Note that everything is converted to and from +// double values. +double *vtkFieldData::GetTuple(const vtkIdType i) +{ + int count=0; + + for ( int j=0; j < this->GetNumberOfArrays(); j++ ) + { + this->Data[j]->GetTuple(i, this->Tuple + count); + count += this->Data[j]->GetNumberOfComponents(); + } + + return this->Tuple; +} + +//---------------------------------------------------------------------------- +// Copy the ith tuple value into a user provided tuple array. Make +// sure that you've allocated enough space for the copy. +void vtkFieldData::GetTuple(const vtkIdType i, double * tuple) +{ + this->GetTuple(i); //side effect fills in this->Tuple + for (int j=0; jTupleSize; j++) + { + tuple[j] = this->Tuple[j]; + } +} + +//---------------------------------------------------------------------------- +// Set the tuple value at the ith location. Set operations +// mean that no range chaecking is performed, so they're faster. +void vtkFieldData::SetTuple(const vtkIdType i, const double * tuple) +{ + int count=0; + + for ( int j=0; j < this->GetNumberOfArrays(); j++ ) + { + this->Data[j]->SetTuple(i, tuple + count); + count += this->Data[j]->GetNumberOfComponents(); + } +} + +//---------------------------------------------------------------------------- +// Insert the tuple value at the ith location. Range checking is +// performed and memory allocates as necessary. +void vtkFieldData::InsertTuple(const vtkIdType i, const double * tuple) +{ + int count=0; + + for ( int j=0; j < this->GetNumberOfArrays(); j++ ) + { + this->Data[j]->InsertTuple(i, tuple + count); + count += this->Data[j]->GetNumberOfComponents(); + } +} + +//---------------------------------------------------------------------------- +// Insert the tuple value at the end of the tuple matrix. Range +// checking is performed and memory is allocated as necessary. +vtkIdType vtkFieldData::InsertNextTuple(const double * tuple) +{ + vtkIdType id=this->GetNumberOfTuples(); + + this->InsertTuple(id, tuple); + return id; +} + +//---------------------------------------------------------------------------- +// Get the component value at the ith tuple (or row) and jth component (or column). +double vtkFieldData::GetComponent(const vtkIdType i, const int j) +{ + this->GetTuple(i); + return this->Tuple[j]; +} + +//---------------------------------------------------------------------------- +// Set the component value at the ith tuple (or row) and jth component (or column). +// Range checking is not performed, so set the object up properly before invoking. +void vtkFieldData::SetComponent(const vtkIdType i, const int j, const double c) +{ + this->GetTuple(i); + this->Tuple[j] = c; + this->SetTuple(i,this->Tuple); +} + +//---------------------------------------------------------------------------- +// Insert the component value at the ith tuple (or row) and jth component (or column). +// Range checking is performed and memory allocated as necessary o hold data. +void vtkFieldData::InsertComponent(const vtkIdType i, const int j, + const double c) +{ + this->GetTuple(i); + this->Tuple[j] = c; + this->InsertTuple(i,this->Tuple); +} diff --git a/Filtering/vtkFieldData.h b/Filtering/vtkFieldData.h new file mode 100644 index 0000000..8bf6018 --- /dev/null +++ b/Filtering/vtkFieldData.h @@ -0,0 +1,467 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFieldData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFieldData - represent and manipulate fields of data +// .SECTION Description +// vtkFieldData represents and manipulates fields of data. The model of a field +// is a m x n matrix of data values, where m is the number of tuples, and n +// is the number of components. (A tuple is a row of n components in the +// matrix.) The field is assumed to be composed of a set of one or more data +// arrays, where the data in the arrays are of different types (e.g., int, +// double, char, etc.), and there may be variable numbers of components in +// each array. Note that each data array is assumed to be "m" in length +// (i.e., number of tuples), which typically corresponds to the number of +// points or cells in a dataset. Also, each data array must have a +// character-string name. (This is used to manipulate data.) +// +// There are two ways of manipulating and interfacing to fields. You can do +// it generically by manipulating components/tuples via a double-type data +// exchange, or you can do it by grabbing the arrays and manipulating them +// directly. The former is simpler but performs type conversion, which is bad +// if your data has non-castable types like (void) pointers, or you lose +// information as a result of the cast. The, more efficient method means +// managing each array in the field. Using this method you can create +// faster, more efficient algorithms that do not lose information. + +// .SECTION See Also +// vtkDataArray vtkDataSetAttributes vtkPointData vtkCellData + +#ifndef __vtkFieldData_h +#define __vtkFieldData_h + +#include "vtkObject.h" + +#include "vtkDataArray.h" // Needed for inline methods + +class vtkIdList; + +class VTK_FILTERING_EXPORT vtkFieldData : public vtkObject +{ +public: + static vtkFieldData *New(); + + vtkTypeRevisionMacro(vtkFieldData,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Release all data but do not delete object. + // Also, clear the copy flags. + virtual void Initialize(); + + // Description: + // Allocate data for each array. + // Note that ext is no longer used. + int Allocate(const vtkIdType sz, const vtkIdType ext=1000); + + // Description: + // Copy data array structure from a given field. The same arrays + // will exist with the same types, but will contain nothing in the + // copy. + void CopyStructure(vtkFieldData*); + + // Description: + // AllocateOfArrays actually sets the number of + // vtkDataArray pointers in the vtkFieldData object, not the + // number of used pointers (arrays). Adding more arrays will + // cause the object to dynamically adjust the number of pointers + // if it needs to extend. Although AllocateArrays can + // be used if the number of arrays which will be added is + // known, it can be omitted with a small computation cost. + void AllocateArrays(int num); + + // Description: + // Get the number of arrays of data available. + // This does not include NULL array pointers therefore after + // fd->AllocateArray(n); nArrays = GetNumberOfArrays() + // nArrays is not necessarily equal to n. + int GetNumberOfArrays() + { + return this->NumberOfActiveArrays; + } + + // Description: + // Add an array to the array list. If an array with the same name + // already exists - then the added array will replace it. + int AddArray(vtkDataArray *array); + + // Description: + // Remove an array (with the given name) from the list of arrays. + virtual void RemoveArray(const char *name) + { + int i; + this->GetArray(name, i); + this->RemoveArray(i); + } + + // Description: + // Return the ith array in the field. A NULL is returned if the + // index i is out of range. + vtkDataArray *GetArray(int i); + + // Description: + // Return the array with the name given. Returns NULL is array not found. + // Also returns index of array if found, -1 otherwise + vtkDataArray *GetArray(const char *arrayName, int &index); + + // Description: + // Return the array with the name given. Returns NULL is array not found. + vtkDataArray *GetArray(const char *arrayName) + { + int i; + return this->GetArray(arrayName, i); + } + + // Description: + // Return 1 if an array with the given name could be found. 0 otherwise. + int HasArray(const char *name) + { + int i; + vtkDataArray *array = this->GetArray(name, i); + // assert( i == -1); + return array ? 1 : 0; + } + + // Description: + // Get the name of ith array. + // Note that this is equivalent to: + // GetArray(i)->GetName() if ith array pointer is not NULL + const char* GetArrayName(int i) + { + vtkDataArray* da = this->GetArray(i); + return da ? da->GetName() : 0; + } + + // Description: + // Pass entire arrays of input data through to output. Obey the "copy" + // flags. + virtual void PassData(vtkFieldData* fd); + + // Description: + // Turn on/off the copying of the field specified by name. + // During the copying/passing, the following rules are followed for each + // array: + // 1. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 2. + // 2. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + void CopyFieldOn(const char* name) { this->CopyFieldOnOff(name, 1); } + void CopyFieldOff(const char* name) { this->CopyFieldOnOff(name, 0); } + + // Description: + // Turn on copying of all data. + // During the copying/passing, the following rules are followed for each + // array: + // 1. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 2. + // 2. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + virtual void CopyAllOn(); + + // Description: + // Turn off copying of all data. + // During the copying/passing, the following rules are followed for each + // array: + // 1. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 2. + // 2. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + virtual void CopyAllOff(); + + // Description: + // Copy a field by creating new data arrays (i.e., duplicate storage). + virtual void DeepCopy(vtkFieldData *da); + + // Description: + // Copy a field by reference counting the data arrays. + virtual void ShallowCopy(vtkFieldData *da); + + // Description: + // Squeezes each data array in the field (Squeeze() reclaims unused memory.) + void Squeeze(); + + // Description: + // Resets each data array in the field (Reset() does not release memory but + // it makes the arrays look like they are empty.) + void Reset(); + + // Description: + // Return the memory in kilobytes consumed by this field data. Used to + // support streaming and reading/writing data. The value returned is + // guaranteed to be greater than or equal to the memory required to + // actually represent the data represented by this object. + virtual unsigned long GetActualMemorySize(); + + // Description: + // Check object's components for modified times. + unsigned long int GetMTime(); + + // Description: + // Get a field from a list of ids. Supplied field f should have same + // types and number of data arrays as this one (i.e., like + // CopyStructure() creates). This method should not be used if the + // instance is from a subclass of vtkFieldData (vtkPointData or + // vtkCellData). This is because in those cases, the attribute data + // is stored with the other fields and will cause the method to + // behave in an unexpected way. + void GetField(vtkIdList *ptId, vtkFieldData *f); + + // Description: + // Return the array containing the ith component of the field. The + // return value is an integer number n 0<=nNumberOfArrays. Also, + // an integer value is returned indicating the component in the array + // is returned. Method returns -1 if specified component is not + // in the field. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + int GetArrayContainingComponent(int i, int& arrayComp); + + // Description: + // Get the number of components in the field. This is determined by adding + // up the components in each non-NULL array. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + int GetNumberOfComponents(); + + // Description: + // Get the number of tuples in the field. Note: some fields have arrays with + // different numbers of tuples; this method returns the number of tuples in + // the first array. Mixed-length arrays may have to be treated specially. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + vtkIdType GetNumberOfTuples(); + + // Description: + // Set the number of tuples for each data array in the field. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + void SetNumberOfTuples(const vtkIdType number); + + // Description: + // Return a tuple consisting of a concatenation of all data from all + // the different arrays. Note that everything is converted to and from + // double values. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + double *GetTuple(const vtkIdType i); + + // Description: + // Copy the ith tuple value into a user provided tuple array. Make + // sure that you've allocated enough space for the copy. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + void GetTuple(const vtkIdType i, double * tuple); + + // Description: + // Set the tuple value at the ith location. Set operations + // mean that no range checking is performed, so they're faster. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + void SetTuple(const vtkIdType i, const double * tuple); + + // Description: + // Insert the tuple value at the ith location. Range checking is + // performed and memory allocates as necessary. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + void InsertTuple(const vtkIdType i, const double * tuple); + + // Description: + // Insert the tuple value at the end of the tuple matrix. Range + // checking is performed and memory is allocated as necessary. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + vtkIdType InsertNextTuple(const double * tuple); + + // Description: + // Get the component value at the ith tuple (or row) and jth component (or + // column). + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + double GetComponent(const vtkIdType i, const int j); + + // Description: + // Set the component value at the ith tuple (or row) and jth component (or + // column). Range checking is not performed, so set the object up properly + // before invoking. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + void SetComponent(const vtkIdType i, const int j, const double c); + + // Description: + // Insert the component value at the ith tuple (or row) and jth component + // (or column). Range checking is performed and memory allocated as + // necessary o hold data. + // This method should not be used if the instance is from a + // subclass of vtkFieldData (vtkPointData or vtkCellData). + // This is because in those cases, the attribute data is + // stored with the other fields and will cause the method + // to behave in an unexpected way. + void InsertComponent(const vtkIdType i, const int j, const double c); + +protected: + + vtkFieldData(); + ~vtkFieldData(); + + int NumberOfArrays; + int NumberOfActiveArrays; + vtkDataArray **Data; + + int TupleSize; //used for type conversion + double *Tuple; + + // Description: + // Set an array to define the field. + void SetArray(int i, vtkDataArray *array); + + virtual void RemoveArray(int index); + + // Description: + // Release all data but do not delete object. + virtual void InitializeFields(); + +//BTX + + struct CopyFieldFlag + { + char* ArrayName; + int IsCopied; + }; + + CopyFieldFlag* CopyFieldFlags; //the names of fields not to be copied + int NumberOfFieldFlags; //the number of fields not to be copied + void CopyFieldOnOff(const char* name, int onOff); + void ClearFieldFlags(); + int FindFlag(const char* field); + int GetFlag(const char* field); + void CopyFlags(const vtkFieldData* source); + int DoCopyAllOn; + int DoCopyAllOff; + + +private: + vtkFieldData(const vtkFieldData&); // Not implemented. + void operator=(const vtkFieldData&); // Not implemented. + +public: + + class VTK_FILTERING_EXPORT BasicIterator + { + public: + BasicIterator(); + BasicIterator(const BasicIterator& source); + BasicIterator(const int* list, unsigned int listSize); + BasicIterator& operator=(const BasicIterator& source); + virtual ~BasicIterator(); + + int GetListSize() const + { + return this->ListSize; + } + int GetCurrentIndex() + { + return this->List[this->Position]; + } + int BeginIndex() + { + this->Position = -1; + return this->NextIndex(); + } + int End() const + { + return (this->Position >= this->ListSize); + } + int NextIndex() + { + this->Position++; + return (this->End() ? -1 : this->List[this->Position]); + } + + protected: + + int* List; + int ListSize; + int Position; + }; + + class VTK_FILTERING_EXPORT Iterator : public BasicIterator + { + public: + + Iterator(const Iterator& source); + Iterator& operator=(const Iterator& source); + virtual ~Iterator(); + Iterator(vtkFieldData* dsa, const int* list=0, + unsigned int listSize=0); + + vtkDataArray* Begin() + { + this->Position = -1; + return this->Next(); + } + + vtkDataArray* Next() + { + this->Position++; + return (this->End() ? 0 : + Fields->GetArray(this->List[this->Position])); + } + + void DetachFieldData(); + + protected: + vtkFieldData* Fields; + int Detached; + }; + + +//ETX + +}; + + +#endif diff --git a/Filtering/vtkFilteringInformationKeyManager.cxx b/Filtering/vtkFilteringInformationKeyManager.cxx new file mode 100644 index 0000000..3cd9517 --- /dev/null +++ b/Filtering/vtkFilteringInformationKeyManager.cxx @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFilteringInformationKeyManager.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFilteringInformationKeyManager.h" + +#include "vtkInformationKey.h" + +#include + +// Subclass vector so we can directly call constructor. This works +// around problems on Borland C++. +struct vtkFilteringInformationKeyManagerKeysType: + public vtkstd::vector +{ + typedef vtkstd::vector Superclass; + typedef Superclass::iterator iterator; +}; + +//---------------------------------------------------------------------------- +// Must NOT be initialized. Default initialization to zero is +// necessary. +static unsigned int vtkFilteringInformationKeyManagerCount; +static vtkFilteringInformationKeyManagerKeysType* vtkFilteringInformationKeyManagerKeys; + +//---------------------------------------------------------------------------- +vtkFilteringInformationKeyManager::vtkFilteringInformationKeyManager() +{ + if(++vtkFilteringInformationKeyManagerCount == 1) + { + vtkFilteringInformationKeyManager::ClassInitialize(); + } +} + +//---------------------------------------------------------------------------- +vtkFilteringInformationKeyManager::~vtkFilteringInformationKeyManager() +{ + if(--vtkFilteringInformationKeyManagerCount == 0) + { + vtkFilteringInformationKeyManager::ClassFinalize(); + } +} + +//---------------------------------------------------------------------------- +void vtkFilteringInformationKeyManager::Register(vtkInformationKey* key) +{ + // Register this instance for deletion by the singleton. + vtkFilteringInformationKeyManagerKeys->push_back(key); +} + +//---------------------------------------------------------------------------- +void vtkFilteringInformationKeyManager::ClassInitialize() +{ + // Allocate the singleton storing pointers to information keys. + // This must be a malloc/free pair instead of new/delete to work + // around problems on MachO (Mac OSX) runtime systems that do lazy + // symbol loading. Calling operator new here causes static + // initialization to occur in other translation units immediately, + // which then may try to access the vector before it is set here. + void* keys = malloc(sizeof(vtkFilteringInformationKeyManagerKeysType)); + vtkFilteringInformationKeyManagerKeys = + new (keys) vtkFilteringInformationKeyManagerKeysType; +} + +//---------------------------------------------------------------------------- +void vtkFilteringInformationKeyManager::ClassFinalize() +{ + if(vtkFilteringInformationKeyManagerKeys) + { + // Delete information keys. + for(vtkFilteringInformationKeyManagerKeysType::iterator i = + vtkFilteringInformationKeyManagerKeys->begin(); + i != vtkFilteringInformationKeyManagerKeys->end(); ++i) + { + vtkInformationKey* key = *i; + delete key; + } + + // Delete the singleton storing pointers to information keys. See + // ClassInitialize above for why this is a free instead of a + // delete. + vtkFilteringInformationKeyManagerKeys->~vtkFilteringInformationKeyManagerKeysType(); + free(vtkFilteringInformationKeyManagerKeys); + vtkFilteringInformationKeyManagerKeys = 0; + } +} diff --git a/Filtering/vtkFilteringInformationKeyManager.h b/Filtering/vtkFilteringInformationKeyManager.h new file mode 100644 index 0000000..d1778d6 --- /dev/null +++ b/Filtering/vtkFilteringInformationKeyManager.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFilteringInformationKeyManager.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFilteringInformationKeyManager - Manages key types in vtkFiltering. +// .SECTION Description +// vtkFilteringInformationKeyManager is included in the header of any +// subclass of vtkInformationKey defined in the vtkFiltering library. +// It makes sure that the table of keys is created before and +// destroyed after it is used. + +#ifndef __vtkFilteringInformationKeyManager_h +#define __vtkFilteringInformationKeyManager_h + +#include "vtkSystemIncludes.h" + +#include "vtkDebugLeaksManager.h" // DebugLeaks exists longer than info keys. + +class vtkInformationKey; + +class VTK_FILTERING_EXPORT vtkFilteringInformationKeyManager +{ +public: + vtkFilteringInformationKeyManager(); + ~vtkFilteringInformationKeyManager(); + + // Description: + // Called by constructors of vtkInformationKey subclasses defined in + // vtkFiltering to register themselves with the manager. The + // instances will be deleted when vtkFiltering is unloaded on + // program exit. + static void Register(vtkInformationKey* key); + +private: + static void ClassInitialize(); + static void ClassFinalize(); +}; + +// This instance will show up in any translation unit that uses key +// types defined in vtkFiltering or that has a singleton. It will +// make sure vtkFilteringInformationKeyManager's vector of keys is +// initialized before and destroyed after it is used. +static vtkFilteringInformationKeyManager vtkFilteringInformationKeyManagerInstance; + +#endif diff --git a/Filtering/vtkGenericAdaptorCell.cxx b/Filtering/vtkGenericAdaptorCell.cxx new file mode 100644 index 0000000..71761a6 --- /dev/null +++ b/Filtering/vtkGenericAdaptorCell.cxx @@ -0,0 +1,1099 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericAdaptorCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericAdaptorCell.h" + +#include + +#include "vtkPoints.h" +#include "vtkPointLocator.h" +#include "vtkTetra.h" +#include "vtkTriangle.h" +#include "vtkLine.h" +#include "vtkVertex.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkCellArray.h" +#include "vtkContourValues.h" +#include "vtkImplicitFunction.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericCellTessellator.h" +#include "vtkUnsignedCharArray.h" +#include "vtkQuad.h" +#include "vtkHexahedron.h" + +vtkCxxRevisionMacro(vtkGenericAdaptorCell, "$Revision: 1.21 $"); + +vtkGenericAdaptorCell::vtkGenericAdaptorCell() +{ + this->Tetra = vtkTetra::New(); + this->Triangle = vtkTriangle::New(); + this->Line = vtkLine::New(); + this->Vertex = vtkVertex::New(); + this->Hexa=vtkHexahedron::New(); + this->Quad=vtkQuad::New(); + + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(4); + this->PointData = vtkPointData::New(); + this->CellData = vtkCellData::New(); + + + // Internal array to avoid New/ Delete + this->InternalPoints = vtkDoubleArray::New(); + this->InternalPoints->SetNumberOfComponents(3); + this->InternalScalars = vtkDoubleArray::New(); + this->InternalCellArray = vtkCellArray::New(); + this->InternalIds = vtkIdList::New(); + + this->PointDataScalars = vtkDoubleArray::New(); + this->PointData->SetScalars( this->PointDataScalars ); + this->PointDataScalars->Delete(); + + this->Tuples=0; + this->TuplesCapacity=0; +} + +//---------------------------------------------------------------------------- +vtkGenericAdaptorCell::~vtkGenericAdaptorCell() +{ + this->Tetra->Delete(); + this->Triangle->Delete(); + this->Line->Delete(); + this->Vertex->Delete(); + this->Hexa->Delete(); + this->Quad->Delete(); + + this->Scalars->Delete(); + this->PointData->Delete(); + this->CellData->Delete(); + + this->InternalPoints->Delete(); + this->InternalScalars->Delete(); + this->InternalCellArray->Delete(); + this->InternalIds->Delete(); + + if(this->Tuples!=0) + { + delete[] this->Tuples; + } +} + +//---------------------------------------------------------------------------- + +void vtkGenericAdaptorCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} +//---------------------------------------------------------------------------- +// Description: +// Does the cell have no higher-order interpolation for geometry? +// \post definition: result==(GetGeometryOrder()==1) +int vtkGenericAdaptorCell::IsGeometryLinear() +{ + return this->GetGeometryOrder() == 1; +} + +//---------------------------------------------------------------------------- +// Description: +// Return the index of the first point centered attribute with the highest +// order in `ac'. +// \pre ac_exists: ac!=0 +// \post valid_result: result>=-1 && resultGetNumberOfAttributes() +int vtkGenericAdaptorCell::GetHighestOrderAttribute(vtkGenericAttributeCollection *ac) +{ + assert("pre: ac_exists" && ac!=0); + int result=-1; + int highestOrder=-1; + int order; + vtkGenericAttribute *a; + int c = ac->GetNumberOfAttributes(); + int i=0; + while(iGetAttribute(i); + if(a->GetCentering()==vtkPointCentered) + { + order=this->GetAttributeOrder(a); + if(order>highestOrder) + { + highestOrder=order; + result=i; + } + } + ++i; + } + assert("post: valid_result" && result>=-1 && resultGetNumberOfAttributes()); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Does the attribute `a' have no higher-order interpolation for the cell? +// \pre a_exists: a!=0 +// \post definition: result==(GetAttributeOrder()==1) +int vtkGenericAdaptorCell::IsAttributeLinear(vtkGenericAttribute *a) +{ + return this->GetAttributeOrder(a) == 1; +} + +//---------------------------------------------------------------------------- +void vtkGenericAdaptorCell::GetBounds(double bounds[6]) +{ +#if 0 + double x[3]; + int i, numPts=this->GetNumberOfPoints(); + + if (numPts) + { + this->GetPoints()->GetPoint(0, x); + bounds[0] = x[0]; + bounds[2] = x[1]; + bounds[4] = x[2]; + bounds[1] = x[0]; + bounds[3] = x[1]; + bounds[5] = x[2]; + for (i=1; iGetPoints()->GetPoint(i, x); + bounds[0] = (x[0] < bounds[0] ? x[0] : bounds[0]); + bounds[1] = (x[0] > bounds[1] ? x[0] : bounds[1]); + bounds[2] = (x[1] < bounds[2] ? x[1] : bounds[2]); + bounds[3] = (x[1] > bounds[3] ? x[1] : bounds[3]); + bounds[4] = (x[2] < bounds[4] ? x[2] : bounds[4]); + bounds[5] = (x[2] > bounds[5] ? x[2] : bounds[5]); + } + } +#endif + memset(bounds,0,sizeof(double)); + vtkErrorMacro("TO BE DONE"); +} + +//---------------------------------------------------------------------------- +double *vtkGenericAdaptorCell::GetBounds() +{ + this->GetBounds(this->Bounds); + + return this->Bounds; +} + +//---------------------------------------------------------------------------- +// Description: +// Return the bounding box diagonal squared of the current cell. +// \post positive_result: result>=0 +double vtkGenericAdaptorCell::GetLength2() +{ + double diff, l=0.0; + int i; + + this->GetBounds(this->Bounds); + for (i=0; i<3; i++) + { + diff = this->Bounds[2*i+1] - this->Bounds[2*i]; + l += diff * diff; + } + return l; +} + +//---------------------------------------------------------------------------- +// Reset +void vtkGenericAdaptorCell::Reset() +{ + this->InternalPoints->Reset(); + this->InternalCellArray->Reset(); + this->InternalScalars->Reset(); +} + +//---------------------------------------------------------------------------- +void vtkGenericAdaptorCell::Contour(vtkContourValues *contourValues, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *outPd, + vtkCellData *outCd, + vtkPointData *internalPd, + vtkPointData *secondaryPd, + vtkCellData *secondaryCd) +{ + assert("pre: values_exist" && ((contourValues!=0 && f==0) || (contourValues!=0 && f!=0))); + assert("pre: attributes_exist" && attributes!=0); + assert("pre: tessellator_exists" && tess!=0); + assert("pre: locator_exists" && locator!=0); + assert("pre: verts_exist" && verts!=0); + assert("pre: lines_exist" && lines!=0); + assert("pre: polys_exist" && polys!=0); + assert("pre: internalPd_exists" && internalPd!=0); + assert("pre: secondaryPd_exists" && secondaryPd!=0); + assert("pre: secondaryCd_exists" && secondaryCd!=0); + + int i; + int j; + int c; + double range[2]; + double contVal=-1000; + double *values; + + vtkCell *linearCell; + vtkIdType ptsCount; + + this->Reset(); + + // for each cell-centered attribute: copy the value in the secondary + // cell data. + secondaryCd->Reset(); + int attrib=0; + while(attribGetNumberOfAttributes()) + { + if(attributes->GetAttribute(attrib)->GetCentering()==vtkCellCentered) + { + vtkDataArray *array = secondaryCd->GetArray(attributes->GetAttribute(attrib)->GetName()); + values = attributes->GetAttribute(attrib)->GetTuple(this); + array->InsertNextTuple(values); + } + attrib++; + } + + int attribute = this->GetHighestOrderAttribute(attributes); + if(this->IsGeometryLinear() &&(attribute==-1 || this->IsAttributeLinear(attributes->GetAttribute(attribute)))) + { + // linear case + switch(this->GetType()) + { + case VTK_HIGHER_ORDER_TRIANGLE: + linearCell=this->Triangle; + ptsCount=3; + break; + case VTK_HIGHER_ORDER_QUAD: + linearCell=this->Quad; + ptsCount=4; + break; + case VTK_HIGHER_ORDER_TETRAHEDRON: + linearCell=this->Tetra; + ptsCount=4; + break; + case VTK_HIGHER_ORDER_HEXAHEDRON: + linearCell=this->Hexa; + ptsCount=8; + break; + default: + assert("check: impossible case" && 0); + linearCell=0; // just to fix warning of some compilers + ptsCount=0; // just to fix warning of some compilers + break; + } + int currComp=attributes->GetActiveComponent(); + + double *locals=this->GetParametricCoords(); + double point[3]; + + vtkGenericAttribute *a; + int count = attributes->GetNumberOfAttributes(); + int attribute_idx; + + values = contourValues->GetValues(); + int numContours = contourValues->GetNumberOfContours(); + + this->AllocateTuples(attributes->GetMaxNumberOfComponents()); + + int activeAttributeIdx = attributes->GetActiveAttribute(); + + // build the cell + i=0; + while(iEvaluateLocation(0,locals,point); + linearCell->PointIds->SetId(i, i); + linearCell->Points->SetPoint(i, point ); + + // for each point-centered attribute + secondaryPd->Reset(); + attribute_idx=0; + j=0; + while(attribute_idxGetAttribute(attribute_idx); + if(a->GetCentering()==vtkPointCentered) + { + this->InterpolateTuple(a,locals,this->Tuples); + secondaryPd->GetArray(j)->InsertTuple(i,this->Tuples); + if(attribute_idx==activeAttributeIdx) + { + if(f==0) + { + contVal = this->Tuples[currComp]; + } + } + ++j; + } + ++attribute_idx; + } + + if(f) + { + contVal = f->FunctionValue( point ); + } + this->Scalars->SetTuple1( i, contVal ); // value at point i of the + // current linear cell. + if(i==0) + { + range[0]=range[1]=contVal; + } + else + { + range[0] = range[0] < contVal ? range[0] : contVal; + range[1] = range[1] > contVal ? range[1] : contVal; + } + + ++i; + locals=locals+3; + } + + // call contour on each value + for( int vv = 0; vv < numContours; vv++ ) + { + if(values[vv] >= range[0] && values[vv] <= range[1]) + { + linearCell->Contour(values[vv],this->Scalars,locator,verts,lines, + polys,secondaryPd, outPd, secondaryCd, + 0, outCd); + } + } + + return; + } + // not linear case + internalPd->Reset(); + + switch(this->GetDimension()) + { + case 3: + tess->Tessellate(this, attributes, this->InternalPoints, + this->InternalCellArray, internalPd); + linearCell=this->Tetra; + ptsCount=4; + break; + case 2: + tess->Triangulate(this, attributes, this->InternalPoints, + this->InternalCellArray, internalPd); + linearCell=this->Triangle; + ptsCount=3; + break; + default: + linearCell=0; + ptsCount=0; + assert("TODO: dimension 1 and 0" && 0); + } + + vtkIdType npts, *pts = 0; + double *point = this->InternalPoints->GetPointer(0); + + vtkDataArray *scalars = internalPd->GetArray(attributes->GetActiveAttribute()); + int currComp = attributes->GetActiveComponent(); + + values = contourValues->GetValues(); + int numContours = contourValues->GetNumberOfContours(); + + c = internalPd->GetNumberOfArrays(); + int dataIndex=0; + + // for each linear sub-tetra, Build it and its pointdata + // then contour it. + for(this->InternalCellArray->InitTraversal(); + this->InternalCellArray->GetNextCell(npts, pts);) + { + assert("check: valid number of points" && npts == ptsCount); + range[1] = range[0] = scalars->GetComponent(dataIndex,currComp); + for(i=0; iPointIds->SetId(i, pts[i]); + linearCell->Points->SetPoint(i, point ); + if(f) + { + contVal = f->FunctionValue( point ); + } + else + { + contVal = scalars->GetComponent(dataIndex,currComp); + } + this->Scalars->SetTuple1( i, contVal ); // value at point i of the + // current linear simplex. + + range[0] = range[0] < contVal ? range[0] : contVal; + range[1] = range[1] > contVal ? range[1] : contVal; + // for each point-centered attribute + secondaryPd->Reset(); + j=0; + while(jGetArray(j)->InsertTuple(pts[i], + internalPd->GetArray(j)->GetTuple(dataIndex)); + ++j; + } + ++dataIndex; + + } + for( int vv = 0; vv < numContours; vv++ ) + { + if(values[vv] >= range[0] && values[vv] <= range[1]) + { + linearCell->Contour(values[vv],this->Scalars,locator,verts,lines, + polys,secondaryPd, outPd, secondaryCd, + 0, outCd); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkGenericAdaptorCell::Clip(double value, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + int insideOut, + vtkPointLocator *locator, + vtkCellArray *connectivity, + vtkPointData *outPd, + vtkCellData *outCd, + vtkPointData *internalPd, + vtkPointData *secondaryPd, + vtkCellData *secondaryCd) +{ + assert("pre: attributes_exist" && attributes!=0); + assert("pre: tessellator_exists" && tess!=0); + assert("pre: locator_exists" && locator!=0); + assert("pre: connectivity_exist" && connectivity!=0); + assert("pre: internalPd_exists" && internalPd!=0); + assert("pre: secondaryPd_exists" && secondaryPd!=0); + assert("pre: secondaryCd_exists" && secondaryCd!=0); + + int i; + int j; + int c; + double contVal=-1000; + double *values; + + vtkCell *linearCell; + vtkIdType ptsCount; + + this->Reset(); + + // for each cell-centered attribute: copy the value in the secondary + // cell data. + secondaryCd->Reset(); + int attrib=0; + while(attribGetNumberOfAttributes()) + { + if(attributes->GetAttribute(attrib)->GetCentering()==vtkCellCentered) + { + vtkDataArray *array=secondaryCd->GetArray(attributes->GetAttribute(attrib)->GetName()); + values=attributes->GetAttribute(attrib)->GetTuple(this); + array->InsertNextTuple(values); + } + attrib++; + } + + int attribute=this->GetHighestOrderAttribute(attributes); + if(this->IsGeometryLinear() &&(attribute==-1 || this->IsAttributeLinear(attributes->GetAttribute(attribute)))) + { + // linear case + switch(this->GetType()) + { + case VTK_HIGHER_ORDER_TRIANGLE: + linearCell=this->Triangle; + ptsCount=3; + break; + case VTK_HIGHER_ORDER_QUAD: + linearCell=this->Quad; + ptsCount=4; + break; + case VTK_HIGHER_ORDER_TETRAHEDRON: + linearCell=this->Tetra; + ptsCount=4; + break; + case VTK_HIGHER_ORDER_HEXAHEDRON: + linearCell=this->Hexa; + ptsCount=8; + break; + default: + assert("check: impossible case" && 0); + linearCell=0; // just to fix warning of some compilers + ptsCount=0;// just to fix warning of some compilers + break; + } + int currComp=attributes->GetActiveComponent(); + + double *locals=this->GetParametricCoords(); + double point[3]; + + vtkGenericAttribute *a; + int count = attributes->GetNumberOfAttributes(); + int attribute_idx; + + this->AllocateTuples(attributes->GetMaxNumberOfComponents()); + + int activeAttributeIdx=attributes->GetActiveAttribute(); + + // build the cell + i=0; + while(iEvaluateLocation(0,locals,point); + linearCell->PointIds->SetId(i, i); + linearCell->Points->SetPoint(i, point ); + + // for each point-centered attribute + secondaryPd->Reset(); + attribute_idx=0; + j=0; + while(attribute_idxGetAttribute(attribute_idx); + if(a->GetCentering()==vtkPointCentered) + { + this->InterpolateTuple(a,locals,this->Tuples); + secondaryPd->GetArray(j)->InsertTuple(i,this->Tuples); + if(attribute_idx==activeAttributeIdx) + { + if(f==0) + { + contVal = this->Tuples[currComp]; + } + } + ++j; + } + ++attribute_idx; + } + + if(f) + { + contVal = f->FunctionValue( point ); + } + this->Scalars->SetTuple1( i, contVal ); // value at point i of the + // current linear cell. + + ++i; + locals=locals+3; + } + + linearCell->Clip(value,this->Scalars,locator,connectivity, + secondaryPd, outPd, secondaryCd, 0, outCd, + insideOut); + return; + } + + // Not linear case + internalPd->Reset(); + + switch(this->GetDimension()) + { + case 3: + tess->Tessellate(this, attributes, this->InternalPoints, + this->InternalCellArray, internalPd); + linearCell=this->Tetra; + ptsCount=4; + break; + case 2: + tess->Triangulate(this, attributes, this->InternalPoints, + this->InternalCellArray, internalPd); + linearCell=this->Triangle; + ptsCount=3; + break; + default: + linearCell=0; + ptsCount=0; + assert("TODO: dimension 1 and 0" && 0); + } + + vtkIdType npts, *pts = 0; + double *point = this->InternalPoints->GetPointer(0); + + vtkDataArray *scalars=internalPd->GetArray(attributes->GetActiveAttribute()); + int currComp=attributes->GetActiveComponent(); + + c=internalPd->GetNumberOfArrays(); + int dataIndex=0; + + // for each linear sub-tetra, Build it and its pointdata + // then contour it. + for(this->InternalCellArray->InitTraversal(); + this->InternalCellArray->GetNextCell(npts, pts);) + { + assert("check: valid number of points" && npts == ptsCount); + for(i=0; iPointIds->SetId(i, pts[i]); + linearCell->Points->SetPoint(i, point ); + if(f) + { + contVal = f->FunctionValue( point ); + } + else + { + contVal = scalars->GetComponent(dataIndex,currComp); + } + this->Scalars->SetTuple1( i, contVal ); // value at point i of the + // current linear simplex. + + // for each point-centered attribute + secondaryPd->Reset(); + j=0; + while(jGetArray(j)->InsertTuple(pts[i], + internalPd->GetArray(j)->GetTuple(dataIndex)); + ++j; + } + ++dataIndex; + + } + linearCell->Clip(value,this->Scalars,locator,connectivity, + secondaryPd, outPd, secondaryCd, 0, outCd, + insideOut); + } +} + +//---------------------------------------------------------------------------- +// Description: +// Tessellate the cell if it is not linear or if at least one attribute of +// `attributes' is not linear. The output are linear cells of the same +// dimension than than cell. If the cell is linear and all attributes are +// linear, the output is just a copy of the current cell. +// `points', `cellArray', `pd' and `cd' are cumulative output data arrays +// over cell iterations: they store the result of each call to Tessellate(). +// If it is not null, `types' is fill with the types of the linear cells. +// `types' is null when it is called from vtkGenericGeometryFilter and not +// null when it is called from vtkGenericDatasetTessellator. +// \pre attributes_exist: attributes!=0 +// \pre points_exist: points!=0 +// \pre cellArray_exists: cellArray!=0 +// // \pre scalars_exists: scalars!=0 +// \pre pd_exist: pd!=0 +// \pre cd_exists: cd!=0 +void vtkGenericAdaptorCell::Tessellate(vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + vtkPoints *points, + vtkPointLocator *locator, + vtkCellArray *cellArray, + vtkPointData *internalPd, + vtkPointData *pd, + vtkCellData *cd, + vtkUnsignedCharArray *types) +{ + assert("pre: attributes_exist" && attributes!=0); + assert("pre: tessellator_exists" && tess!=0); + assert("pre: points_exist" && points!=0); + assert("pre: cellArray_exists" && cellArray!=0); + assert("pre: internalPd_exists" && internalPd!=0); + assert("pre: pd_exist" && pd!=0); + assert("pre: cd_exist" && cd!=0); + + int i; + int j; +#ifndef NDEBUG + vtkIdType valid_npts=0; // for the check assertion +#endif + int linearCellType; + this->Reset(); + + assert("check: TODO: Tessellate only works with 2D and 3D cells" && this->GetDimension() == 3 || this->GetDimension() == 2); + + int attribute=this->GetHighestOrderAttribute(attributes); + if(this->IsGeometryLinear() &&(attribute==-1 || this->IsAttributeLinear(attributes->GetAttribute(attribute)))) + { + // linear case + this->AllocateTuples(attributes->GetMaxNumberOfComponents()); + + // for each cell-centered attribute: copy the value + int attrib=0; + while(attribGetNumberOfAttributes()) + { + if(attributes->GetAttribute(attrib)->GetCentering()==vtkCellCentered) + { + vtkDataArray *array=cd->GetArray(attributes->GetAttribute(attrib)->GetName()); + double *values=attributes->GetAttribute(attrib)->GetTuple(this); + array->InsertNextTuple(values); + } + attrib++; + } + int numVerts; + + switch(this->GetType()) + { + case VTK_HIGHER_ORDER_TRIANGLE: + linearCellType=VTK_TRIANGLE; + numVerts=3; + break; + case VTK_HIGHER_ORDER_QUAD: + linearCellType=VTK_QUAD; + numVerts=4; + break; + case VTK_HIGHER_ORDER_TETRAHEDRON: + linearCellType=VTK_TETRA; + numVerts=4; + break; + case VTK_HIGHER_ORDER_HEXAHEDRON: + linearCellType=VTK_HEXAHEDRON; + numVerts=8; + break; + default: + assert("check: impossible case" && 0); + linearCellType=0; // just to fix warning of some compilers + numVerts=0; // just to fix warning of some compilers + break; + } + double *locals=this->GetParametricCoords(); + this->InternalIds->Reset(); + double point[3]; + vtkIdType ptId; + i=0; + + vtkGenericAttribute *a; + int count = attributes->GetNumberOfAttributes(); + int attribute_idx; + int newpoint=1; + + while(iEvaluateLocation(0,locals,point); + if(locator==0) // no merging + { + ptId=points->InsertNextPoint(point ); + } + else // merging + { + newpoint=locator->InsertUniquePoint(point,ptId); + } + this->InternalIds->InsertId(i,ptId); + if(newpoint) + { + // for each point-centered attribute + attribute_idx=0; + j=0; + while(attribute_idxGetAttribute(attribute_idx); + if(a->GetCentering()==vtkPointCentered) + { + this->InterpolateTuple(a,locals,this->Tuples); + pd->GetArray(j)->InsertTuple(ptId,this->Tuples); + ++j; + } + ++attribute_idx; + } + } + ++i; + locals=locals+3; + } + + cellArray->InsertNextCell(this->InternalIds ); + if(types!=0) + { + types->InsertNextValue(linearCellType); + } + } + else // not linear + { + if( this->GetDimension() == 3) + { + internalPd->Reset(); + tess->Tessellate(this, attributes, this->InternalPoints, this->InternalCellArray, internalPd); + linearCellType=VTK_TETRA; +#ifndef NDEBUG + valid_npts=4; +#endif + } + else + { + if( this->GetDimension() == 2) + { + internalPd->Reset(); + tess->Triangulate(this, attributes, this->InternalPoints, this->InternalCellArray, internalPd); + linearCellType=VTK_TRIANGLE; +#ifndef NDEBUG + valid_npts=3; +#endif + } + else + { + linearCellType=0; // for compiler warning + } + } + + vtkIdType npts = 0; + vtkIdType *pts = 0; + double *point = this->InternalPoints->GetPointer(0); + + + // for each cell-centered attribute: copy the value + int c=this->InternalCellArray->GetNumberOfCells(); + int attrib=0; + while(attribGetNumberOfAttributes()) + { + if(attributes->GetAttribute(attrib)->GetCentering()==vtkCellCentered) + { + vtkDataArray *array=cd->GetArray(attributes->GetAttribute(attrib)->GetName()); + double *values=attributes->GetAttribute(attrib)->GetTuple(this); + i=0; + while(iInsertNextTuple(values); + ++i; + } + } + attrib++; + } + + c=internalPd->GetNumberOfArrays(); // same as pd->GetNumberOfArrays(); + + int dataIndex=0; + int newpoint=1; + + for(this->InternalCellArray->InitTraversal(); + this->InternalCellArray->GetNextCell(npts, pts);) + { + assert("check: is_a_simplex" && npts == valid_npts); + this->InternalIds->Reset(); + + for(i=0;iInsertNextPoint(point ); + } + else // merging + { + newpoint=locator->InsertUniquePoint(point,ptId); + } + this->InternalIds->InsertId(i,ptId); + if(newpoint) + { + // for each point-centered attribute + j=0; + while(jGetArray(j)->InsertTuple(ptId, + internalPd->GetArray(j)->GetTuple(dataIndex)); + ++j; + } + } + ++dataIndex; + } + cellArray->InsertNextCell(this->InternalIds ); + if(types!=0) + { + types->InsertNextValue(linearCellType); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkGenericAdaptorCell::TriangulateFace(vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + int index, + vtkPoints *points, + vtkPointLocator *locator, + vtkCellArray *cellArray, + vtkPointData *internalPd, + vtkPointData *pd, + vtkCellData *cd ) +{ + assert("pre: cell_is_3d" && this->GetDimension()==3); + assert("pre: attributes_exist" && attributes!=0); + assert("pre: tessellator_exists" && tess!=0); + assert("pre: valid_face" && index>=0 && indexGetNumberOfBoundaries(2)); + assert("pre: points_exist" && points!=0); + assert("pre: cellArray_exists" && cellArray!=0); + assert("pre: internalPd_exists" && internalPd!=0); + assert("pre: pd_exist" && pd!=0); + assert("pre: cd_exists" && cd!=0); + + int i; + int j; + int c; + + this->Reset(); + + internalPd->Reset(); + + // if simplex (tetra) just one sub-tetra [0,1,2,3] + // otherwise build sub-tetra: HOW? + + int attribute=this->GetHighestOrderAttribute(attributes); + if(this->IsGeometryLinear() &&(attribute==-1 || this->IsAttributeLinear(attributes->GetAttribute(attribute)))) + { + // LINEAR CASE + // the cell is linear both in geometry and attributes + // just create a linear cell of the same type and return + // the relevant face: basically, do what the Graphics/vtkGeometryFilter + // do with the linear cells + this->AllocateTuples(attributes->GetMaxNumberOfComponents()); + + // for each cell-centered attribute: copy the value + int attrib=0; + while(attribGetNumberOfAttributes()) + { + if(attributes->GetAttribute(attrib)->GetCentering()==vtkCellCentered) + { + vtkDataArray *array=cd->GetArray(attributes->GetAttribute(attrib)->GetName()); + double *values=attributes->GetAttribute(attrib)->GetTuple(this); + array->InsertNextTuple(values); + } + attrib++; + } + vtkGenericAttribute *a; + int count = attributes->GetNumberOfAttributes(); + + int attribute_idx; + + this->InternalIds->Reset(); + int *faceVerts=this->GetFaceArray(index); + int numVerts=this->GetNumberOfVerticesOnFace(index); + double *locals=this->GetParametricCoords(); + double *local; + double point[3]; + vtkIdType ptId; + + + i=0; + int newpoint=1; + while(iEvaluateLocation(0,local,point); + if(locator==0) // no merging + { + ptId=points->InsertNextPoint(point ); + } + else // merging + { + newpoint=locator->InsertUniquePoint(point,ptId); + } + this->InternalIds->InsertId(i,ptId); + if(newpoint) + { + // for each point-centered attribute + attribute_idx=0; + j=0; + while(attribute_idxGetAttribute(attribute_idx); + if(a->GetCentering()==vtkPointCentered) + { + this->InterpolateTuple(a,local,this->Tuples); + pd->GetArray(j)->InsertTuple(ptId,this->Tuples); + ++j; + } + ++attribute_idx; + } + } + ++i; + } + cellArray->InsertNextCell(this->InternalIds ); + return; + } + + // NOT LINEAR + tess->TessellateFace(this, attributes,index, + this->InternalPoints, + this->InternalCellArray, internalPd); + + vtkIdType npts=0; + vtkIdType *pts = 0; + double *point = this->InternalPoints->GetPointer(0); + + // for each cell-centered attribute: copy the value + c=this->InternalCellArray->GetNumberOfCells(); + int attrib=0; + while(attribGetNumberOfAttributes()) + { + if(attributes->GetAttribute(attrib)->GetCentering()==vtkCellCentered) + { + vtkDataArray *array=cd->GetArray(attributes->GetAttribute(attrib)->GetName()); + double *values=attributes->GetAttribute(attrib)->GetTuple(this); + i=0; + while(iInsertNextTuple(values); + ++i; + } + } + attrib++; + } + + c=internalPd->GetNumberOfArrays(); + int dataIndex=0; + + int newpoint=1; + + for(this->InternalCellArray->InitTraversal(); + this->InternalCellArray->GetNextCell(npts, pts);) + { + assert("check: is_a_triangle" && npts == 3); + this->InternalIds->Reset(); + + for(i=0;iInsertNextPoint(point ); + } + else // merging + { + newpoint=locator->InsertUniquePoint(point,ptId); + } + this->InternalIds->InsertId(i,ptId); + if(newpoint) + { + // for each point-centered attribute + j=0; + while(jGetArray(j)->InsertTuple(ptId, + internalPd->GetArray(j)->GetTuple(dataIndex)); + ++j; + } + } + ++dataIndex; + } + cellArray->InsertNextCell(this->InternalIds ); + } +} + +//---------------------------------------------------------------------------- +// Description: +// Allocate some memory if Tuples does not exist or is smaller than size. +// \pre positive_size: size>0 +void vtkGenericAdaptorCell::AllocateTuples(int size) +{ + assert("pre: positive_size" && size>0); + + if(this->TuplesCapacityTuples!=0) + { + delete[] this->Tuples; + } + this->Tuples=new double[size]; + this->TuplesCapacity=size; + } +} diff --git a/Filtering/vtkGenericAdaptorCell.h b/Filtering/vtkGenericAdaptorCell.h new file mode 100644 index 0000000..287df11 --- /dev/null +++ b/Filtering/vtkGenericAdaptorCell.h @@ -0,0 +1,604 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericAdaptorCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericAdaptorCell - defines cell interface +// .SECTION Description +// In VTK, spatial-temporal data is defined in terms of a dataset which is +// composed of cells. The cells are topological entities over which an +// interpolation field is applied. Cells are defined in terms of a topology +// (e.g., vertices, lines, triangles, polygons, tetrahedra, etc.), points +// that instantiate the geometry of the cells, and interpolation fields +// (in the general case one interpolation field is for geometry, the other +// is for attribute data associated with the cell). +// +// Currently most algorithms in VTK use vtkCell and vtkDataSet, which make +// assumptions about the nature of datasets, cells, and attributes. In +// particular, this abstraction assumes that cell interpolation functions +// are linear, or products of linear functions. Further, VTK implements +// most of the interpolation functions. This implementation starts breaking +// down as the complexity of the interpolation (or basis) functions +// increases. +// +// vtkGenericAdaptorCell addresses these issues by providing more general +// abstraction for cells. It also adopts modern C++ practices including using +// iterators. The vtkGenericAdaptorCell is designed to fit within the adaptor +// framework; meaning that it is meant to adapt VTK to external simulation +// systems (see the GenericFiltering/README.html). +// +// Please note that most cells are defined in terms of other cells (the +// boundary cells). They are also defined in terms of points, which are +// not the same as vertices (vertices are a 0-D cell; points represent a +// position in space). +// +// Another important concept is the notion of DOFNodes. These concept +// supports cell types with complex interpolation functions. For example, +// higher-order p-method finite elements may have different functions on each +// of their topological features (edges, faces, region). The coefficients of +// these polynomial functions are associated with DOFNodes. (There is a +// single DOFNode for each topological feature.) Note that from this +// perspective, points are used to establish the topological form of the +// cell; mid-side nodes and such are considered DOFNodes. + +// .SECTION See Also +// vtkGenericDataSet + +#ifndef __vtkGenericAdaptorCell_h +#define __vtkGenericAdaptorCell_h + + +#include "vtkObject.h" + +class vtkLine; +class vtkTetra; +class vtkPoints; +class vtkPointLocator; +class vtkVertex; +class vtkTriangle; +class vtkCellData; +class vtkPointData; +class vtkCellArray; +class vtkDoubleArray; +class vtkGenericCellIterator; +class vtkPointLocator; +class vtkContourValues; +class vtkImplicitFunction; +class vtkGenericCellTessellator; +class vtkGenericAttributeCollection; +class vtkGenericAttribute; +class vtkGenericPointIterator; +class vtkIdList; +class vtkOrderedTriangulator; +class vtkPolygon; +class vtkUnsignedCharArray; +class vtkQuad; +class vtkHexahedron; + +class VTK_FILTERING_EXPORT vtkGenericAdaptorCell : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkGenericAdaptorCell,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Unique identification number of the cell over the whole + // data set. This unique key may not be contiguous. + virtual vtkIdType GetId() = 0; + + // Description: + // Does `this' a cell of a dataset? (otherwise, it is a boundary cell) + virtual int IsInDataSet()=0; + + // Description: + // Return the type of the current cell. + // \post (result==VTK_HIGHER_ORDER_EDGE)|| + // (result==VTK_HIGHER_ORDER_TRIANGLE)|| + // (result==VTK_HIGHER_ORDER_TETRAHEDRON) + virtual int GetType()=0; + + // Description: + // Return the topological dimension of the current cell. + // \post valid_result: result>=0 && result<=3 + virtual int GetDimension() = 0; + + // Description: + // Return the interpolation order of the geometry. + // \post positive_result: result>=0 + virtual int GetGeometryOrder()=0; + + // Description: + // Does the cell have a non-linear interpolation for the geometry? + // \post definition: result==(GetGeometryOrder()==1) + int IsGeometryLinear(); + + // Description: + // Return the Interpolation order of attribute `a' on the cell + // (may differ by cell). + // \pre a_exists: a!=0 + // \post positive_result: result>=0 + virtual int GetAttributeOrder(vtkGenericAttribute *a)=0; + + // Description: + // Return the index of the first point centered attribute with the highest + // order in `ac'. + // \pre ac_exists: ac!=0 + // \post valid_result: result>=-1 && resultGetNumberOfAttributes() + virtual int GetHighestOrderAttribute(vtkGenericAttributeCollection *ac); + + // Description: + // Does the attribute `a' have a non-linear interpolation? + // \pre a_exists: a!=0 + // \post definition: result==(GetAttributeOrder()==1) + int IsAttributeLinear(vtkGenericAttribute *a); + + // Description: + // Is the cell primary (i.e. not composite) ? + virtual int IsPrimary()=0; + + // Description: + // Return the number of points that compose the cell. + // \post positive_result: result>=0 + virtual int GetNumberOfPoints()=0; + + // Description: + // Return the number of boundaries of dimension `dim' (or all dimensions + // greater than 0 and less than GetDimension() if -1) of the cell. + // When \a dim is -1, the number of vertices is not included in the + // count because vertices are a special case: a vertex will have + // at most a single field value associated with it; DOF nodes may have + // an arbitrary number of field values associated with them. + // \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dim=0 + virtual int GetNumberOfBoundaries(int dim=-1)=0; + + // Description: + // Accumulated number of DOF nodes of the current cell. A DOF node is + // a component of cell with a given topological dimension. e.g.: a triangle + // has 4 DOF: 1 face and 3 edges. An hexahedron has 19 DOF: + // 1 region, 6 faces, and 12 edges. + // + // The number of vertices is not included in the + // count because vertices are a special case: a vertex will have + // at most a single field value associated with it; DOF nodes may have + // an arbitrary number of field values associated with them. + // \post valid_result: result==GetNumberOfBoundaries(-1)+1 + virtual int GetNumberOfDOFNodes()=0; + + // Description: + // Return the points of cell into `it'. + // \pre it_exists: it!=0 + virtual void GetPointIterator(vtkGenericPointIterator *it)=0; + + // Description: + // Create an empty cell iterator. The user is responsible for deleting it. + // \post result_exists: result!=0 + virtual vtkGenericCellIterator *NewCellIterator()=0; + + // Description: + // Return the `boundaries' the cells of dimension `dim' (or all dimensions + // less than GetDimension() if -1) that are part of the boundary of the cell. + // \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dimboundary->GetDimension()) of the dataset + // that share the boundary `boundary' of `this'. + // `this' IS NOT INCLUDED. + // \pre boundary_exists: boundary!=0 + // \pre real_boundary: !boundary->IsInDataSet() + // \pre cell_of_the_dataset: IsInDataSet() + // \pre boundary: HasBoundary(boundary) + // \post positive_result: result>=0 + virtual int CountNeighbors(vtkGenericAdaptorCell *boundary)=0; + virtual void CountEdgeNeighbors( int* sharing ) = 0; + + // Description: + // Put into `neighbors' the cells (dimension>boundary->GetDimension()) + // of the dataset that share the boundary `boundary' with this cell. + // `this' IS NOT INCLUDED. + // \pre boundary_exists: boundary!=0 + // \pre real_boundary: !boundary->IsInDataSet() + // \pre cell_of_the_dataset: IsInDataSet() + // \pre boundary: HasBoundary(boundary) + // \pre neighbors_exist: neighbors!=0 + virtual void GetNeighbors(vtkGenericAdaptorCell *boundary, + vtkGenericCellIterator *neighbors)=0; + + // Description: + // Compute the closest boundary of the current sub-cell `subId' for point + // `pcoord' (in parametric coordinates) in `boundary', and return whether + // the point is inside the cell or not. `boundary' is of dimension + // GetDimension()-1. + // \pre positive_subId: subId>=0 + virtual int FindClosestBoundary(int subId, + double pcoords[3], + vtkGenericCellIterator* &boundary)=0; + + // Description: + // Is `x' inside the current cell? It also evaluate parametric coordinates + // `pcoords', sub-cell id `subId' (0 means primary cell), distance squared + // to the sub-cell in `dist2' and closest corner point `closestPoint'. + // `dist2' and `closestPoint' are not evaluated if `closestPoint'==0. + // If a numerical error occurred, -1 is returned and all other results + // should be ignored. + // \post valid_result: result==-1 || result==0 || result==1 + // \post positive_distance: result!=-1 implies (closestPoint!=0 implies + // dist2>=0) + virtual int EvaluatePosition(double x[3], + double *closestPoint, + int &subId, + double pcoords[3], + double &dist2)=0; + + // Description: + // Determine the global coordinates `x' from sub-cell `subId' and parametric + // coordinates `pcoords' in the cell. + // \pre positive_subId: subId>=0 + // \pre clamped_pcoords: (0<=pcoords[0])&&(pcoords[0]<=1)&&(0<=pcoords[1]) + // &&(pcoords[1]<=1)&&(0<=pcoords[2])&&(pcoords[2]<=1) + virtual void EvaluateLocation(int subId, + double pcoords[3], + double x[3])=0; + + // Description: + // Interpolate the attribute `a' at local position `pcoords' of the cell into + // `val'. + // \pre a_exists: a!=0 + // \pre a_is_point_centered: a->GetCentering()==vtkPointCentered + // \pre clamped_point: pcoords[0]>=0 && pcoords[0]<=1 && pcoords[1]>=0 && + // pcoords[1]<=1 && pcoords[2]>=0 && pcoords[2]<=1 + // \pre val_exists: val!=0 + // \pre valid_size: sizeof(val)==a->GetNumberOfComponents() + virtual void InterpolateTuple(vtkGenericAttribute *a, double pcoords[3], + double *val) = 0; + + // Description: + // Interpolate the whole collection of attributes `c' at local position + // `pcoords' of the cell into `val'. Only point centered attributes are + // taken into account. + // \pre c_exists: c!=0 + // \pre clamped_point: pcoords[0]>=0 && pcoords[0]<=1 && pcoords[1]>=0 && + // pcoords[1]<=1 && pcoords[2]>=0 && pcoords[2]<=1 + // \pre val_exists: val!=0 + // \pre valid_size: sizeof(val)==c->GetNumberOfPointCenteredComponents() + virtual void InterpolateTuple(vtkGenericAttributeCollection *c, + double pcoords[3], + double *val) = 0; + + // Description: + // Generate a contour (contouring primitives) for each `values' or with + // respect to an implicit function `f'. Contouring is performed on the + // scalar attribute (`attributes->GetActiveAttribute()' + // `attributes->GetActiveComponent()'). Contouring interpolates the + // `attributes->GetNumberOfattributesToInterpolate()' attributes + // `attributes->GetAttributesToInterpolate()'. The `locator', `verts', + // `lines', `polys', `outPd' and `outCd' are cumulative data arrays over + // cell iterations: they store the result of each call to Contour(): + // - `locator' is points list that merges points as they are inserted (i.e., + // prevents duplicates). + // - `verts' is an array of generated vertices + // - `lines' is an array of generated lines + // - `polys' is an array of generated polygons + // - `outPd' is an array of interpolated point data along the edge (if + // not-NULL) + // - `outCd' is an array of copied cell data of the current cell (if + // not-NULL) + // `internalPd', `secondaryPd' and `secondaryCd' are initialized by the + // filter that call it from `attributes'. + // - `internalPd' stores the result of the tessellation pass: the + // higher-order cell is tessellated into linear sub-cells. + // - `secondaryPd' and `secondaryCd' are used internally as inputs to the + // Contour() method on linear sub-cells. + // Note: the CopyAllocate() method must be invoked on both `outPd' and + // `outCd', from `secondaryPd' and `secondaryCd'. + // + // NOTE: `vtkGenericAttributeCollection *attributes' will be replaced by a + // `vtkInformation'. + // + // \pre values_exist: (values!=0 && f==0) || (values==0 && f!=0) + // \pre attributes_exist: attributes!=0 + // \pre tessellator_exists: tess!=0 + // \pre locator_exists: locator!=0 + // \pre verts_exist: verts!=0 + // \pre lines_exist: lines!=0 + // \pre polys_exist: polys!=0 + // \pre internalPd_exists: internalPd!=0 + // \pre secondaryPd_exists: secondaryPd!=0 + // \pre secondaryCd_exists: secondaryCd!=0 + virtual void Contour(vtkContourValues *values, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *outPd, + vtkCellData *outCd, + vtkPointData *internalPd, + vtkPointData *secondaryPd, + vtkCellData *secondaryCd); + + // Description: + // Cut (or clip) the current cell with respect to the contour defined by + // the `value' or the implicit function `f' of the scalar attribute + // (`attributes->GetActiveAttribute()',`attributes->GetActiveComponent()'). + // If `f' exists, `value' is not used. The output is the part of the + // current cell which is inside the contour. The output is a set of zero, + // one or more cells of the same topological dimension as the current + // cell. Normally, cell points whose scalar value is greater than "value" + // are considered inside. If `insideOut' is on, this is reversed. Clipping + // interpolates the `attributes->GetNumberOfattributesToInterpolate()' + // attributes `attributes->GetAttributesToInterpolate()'. `locator', + // `connectivity', `outPd' and `outCd' are cumulative data arrays over cell + // iterations: they store the result of each call to Clip(): + // - `locator' is points list that merges points as they are inserted (i.e., + // prevents duplicates). + // - `connectivity' is an array of generated cells + // - `outPd' is an array of interpolated point data along the edge (if + // not-NULL) + // - `outCd' is an array of copied cell data of the current cell (if + // not-NULL) + // `internalPd', `secondaryPd' and `secondaryCd' are initialized by the + // filter that call it from `attributes'. + // - `internalPd' stores the result of the tessellation pass: the + // higher-order cell is tessellated into linear sub-cells. + // - `secondaryPd' and `secondaryCd' are used internally as inputs to the + // Clip() method on linear sub-cells. + // Note: the CopyAllocate() method must be invoked on both `outPd' and + // `outCd', from `secondaryPd' and `secondaryCd'. + // + // NOTE: `vtkGenericAttributeCollection *attributes' will be replaced by a + // `vtkInformation'. + // + // \pre attributes_exist: attributes!=0 + // \pre tessellator_exists: tess!=0 + // \pre locator_exists: locator!=0 + // \pre connectivity_exists: connectivity!=0 + // \pre internalPd_exists: internalPd!=0 + // \pre secondaryPd_exists: secondaryPd!=0 + // \pre secondaryCd_exists: secondaryCd!=0 + virtual void Clip(double value, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + int insideOut, + vtkPointLocator *locator, + vtkCellArray *connectivity, + vtkPointData *outPd, + vtkCellData *outCd, + vtkPointData *internalPd, + vtkPointData *secondaryPd, + vtkCellData *secondaryCd); + + // Description: + // Is there an intersection between the current cell and the ray (`p1',`p2') + // according to a tolerance `tol'? If true, `x' is the global intersection, + // `t' is the parametric coordinate for the line, `pcoords' are the + // parametric coordinates for cell. `subId' is the sub-cell where + // the intersection occurs. + // \pre positive_tolerance: tol>0 + virtual int IntersectWithLine(double p1[3], + double p2[3], + double tol, + double &t, + double x[3], + double pcoords[3], + int &subId)=0; + + // Description: + // Compute derivatives `derivs' of the attribute `attribute' (from its + // values at the corner points of the cell) given sub-cell `subId' (0 means + // primary cell) and parametric coordinates `pcoords'. + // Derivatives are in the x-y-z coordinate directions for each data value. + // \pre positive_subId: subId>=0 + // \pre clamped_pcoords: (0<=pcoords[0])&&(pcoords[0]<=1)&&(0<=pcoords[1]) + // &&(pcoords[1]<=1)&&(0<=pcoords[2])%%(pcoords[2]<=1) + // \pre attribute_exists: attribute!=0 + // \pre derivs_exists: derivs!=0 + // \pre valid_size: sizeof(derivs)>=attribute->GetNumberOfComponents()*3 + virtual void Derivatives(int subId, + double pcoords[3], + vtkGenericAttribute *attribute, + double *derivs)=0; + + // Description: + // Compute the bounding box of the current cell in `bounds' in global + // coordinates. + // THREAD SAFE + virtual void GetBounds(double bounds[6])=0; + + // Description: + // Return the bounding box of the current cell in global coordinates. + // NOT THREAD SAFE + // \post result_exists: result!=0 + // \post valid_size: sizeof(result)>=6 + virtual double *GetBounds(); + + // Description: + // Return the bounding box diagonal squared of the current cell. + // \post positive_result: result>=0 + virtual double GetLength2(); + + // Description: + // Get the center of the current cell (in parametric coordinates)and place + // in the `pcoords'. If the current cell is a composite, the return value + // is the sub-cell id that the center is in. \post valid_result: + // (result>=0) && (IsPrimary() implies result==0) + virtual int GetParametricCenter(double pcoords[3])=0; + + // Description: + // Return the distance of the parametric coordinate `pcoords' to the + // current cell. If inside the cell, a distance of zero is returned. This + // is used during picking to get the correct cell picked. (The tolerance + // will occasionally allow cells to be picked who are not really + // intersected "inside" the cell.) \post positive_result: result>=0 + virtual double GetParametricDistance(double pcoords[3])=0; + + // Description: + // Return a contiguous array of parametric coordinates of the points defining + // the current cell. In other words, (px,py,pz, px,py,pz, etc..) The + // coordinates are ordered consistent with the definition of the point + // ordering for the cell. Note that 3D parametric coordinates are returned + // no matter what the topological dimension of the cell. It includes the DOF + // nodes. + // \post valid_result_exists: ((IsPrimary()) && (result!=0)) || + // ((!IsPrimary()) && (result==0)) + // result!=0 implies sizeof(result)==GetNumberOfPoints() + virtual double *GetParametricCoords()=0; + + // Description: + // Tessellate the cell if it is not linear or if at least one attribute of + // `attributes' is not linear. The output are linear cells of the same + // dimension than than cell. If the cell is linear and all attributes are + // linear, the output is just a copy of the current cell. + // `points', `cellArray', `pd' and `cd' are cumulative output data arrays + // over cell iterations: they store the result of each call to Tessellate(). + // `internalPd' is initialized by the calling filter and stores the + // result of the tessellation. + // If it is not null, `types' is fill with the types of the linear cells. + // `types' is null when it is called from vtkGenericGeometryFilter and not + // null when it is called from vtkGenericDatasetTessellator. + // \pre attributes_exist: attributes!=0 + // \pre tessellator_exists: tess!=0 + // \pre points_exist: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + // \pre pd_exist: pd!=0 + // \pre cd_exists: cd!=0 + virtual void Tessellate(vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + vtkPoints *points, + vtkPointLocator *locator, + vtkCellArray* cellArray, + vtkPointData *internalPd, + vtkPointData *pd, vtkCellData* cd, + vtkUnsignedCharArray *types); + + // The following methods are for the internals of the tesselation algorithm + // (the hash table in particular) + + // Description: + // Is the face `faceId' of the current cell on a exterior boundary of the + // dataset? + // \pre 3d: GetDimension()==3 + virtual int IsFaceOnBoundary(vtkIdType faceId) = 0; + + // Description: + // Is the cell on the exterior boundary of the dataset? + // \pre 2d: GetDimension()==2 + virtual int IsOnBoundary() = 0; + + // Description: + // Put into `id' the list of ids the point of the cell. + // \pre id_exists: id!=0 + // \pre valid_size: sizeof(id)==GetNumberOfPoints(); + virtual void GetPointIds(vtkIdType *id) = 0; + + // Description: + // Tessellate face `index' of the cell. See Tessellate() for further + // explanations. + // \pre cell_is_3d: GetDimension()==3 + // \pre attributes_exist: attributes!=0 + // \pre tessellator_exists: tess!=0 + // \pre valid_face: index>=0 + // \pre points_exist: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + // \pre pd_exist: pd!=0 + // \pre cd_exists: cd!=0 + virtual void TriangulateFace(vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, int index, + vtkPoints *points, + vtkPointLocator *locator, + vtkCellArray *cellArray, + vtkPointData *internalPd, + vtkPointData *pd, vtkCellData *cd ); + + // Description: + // Return the ids of the vertices defining face `faceId'. + // \pre is_3d: this->GetDimension()==3 + // \pre valid_faceId_range: faceId>=0 && faceIdGetNumberOfBoundaries(2) + // \post result_exists: result!=0 + // \post valid_size: sizeof(result)>=GetNumberOfVerticesOnFace(faceId) + virtual int *GetFaceArray(int faceId)=0; + + // Description: + // Return the number of vertices defining face `faceId'. + // \pre is_3d: this->GetDimension()==3 + // \pre valid_faceId_range: faceId>=0 && faceIdGetNumberOfBoundaries(2) + // \post positive_result: && result>0 + virtual int GetNumberOfVerticesOnFace(int faceId)=0; + + // Description: + // Return the ids of the vertices defining edge `edgeId'. + // \pre valid_dimension: this->GetDimension()>=2 + // \pre valid_edgeId_range: edgeId>=0 && edgeIdGetNumberOfBoundaries(1) + // \post result_exists: result!=0 + // \post valid_size: sizeof(result)==2 + virtual int *GetEdgeArray(int edgeId)=0; + +protected: + vtkGenericAdaptorCell(); + virtual ~vtkGenericAdaptorCell(); + + // Description: + // Reset internal structures. + void Reset(); + + // Description: + // Allocate some memory if Tuples does not exist or is smaller than size. + // \pre positive_size: size>0 + void AllocateTuples(int size); + + //Internal tetra used for the contouring/clipping algoirthm + vtkTetra *Tetra; + vtkTriangle *Triangle; + vtkLine *Line; + vtkVertex *Vertex; //is it used ? + vtkQuad *Quad; + vtkHexahedron *Hexa; + + // Internal locator when tessellating on a cell basis, this is different + // from the main locator used in contour/clip filter, this locator is used for + // points for + // Be carefull the use of a vtkLocator in conjuction with the table fast + // tessellator is very sensitive, we need to keep all the points we used + vtkDoubleArray *InternalPoints; + vtkCellArray *InternalCellArray; + vtkDoubleArray *InternalScalars; + vtkDoubleArray *PointDataScalars; + + vtkIdList *InternalIds; // used by Tessellate() and TriangulateFace() + + //Attributes to mimic the vtk cell look and feel, internal use only + vtkDoubleArray *Scalars; + vtkPointData *PointData; + vtkCellData *CellData; + + // Scalar buffer to store the attributes values at some location + // There are variable members to reduce memory allocations. + double *Tuples; + int TuplesCapacity; + + // Cached Bounds. + double Bounds[6]; + +private: + vtkGenericAdaptorCell(const vtkGenericAdaptorCell&); // Not implemented. + void operator=(const vtkGenericAdaptorCell&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericAttribute.cxx b/Filtering/vtkGenericAttribute.cxx new file mode 100644 index 0000000..f5a2853 --- /dev/null +++ b/Filtering/vtkGenericAttribute.cxx @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericAttribute.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericAttribute - Objects that manage some attribute data. +// .SECTION Description + +#include "vtkGenericAttribute.h" +#include + +vtkCxxRevisionMacro(vtkGenericAttribute, "$Revision: 1.1 $"); + +//--------------------------------------------------------------------------- +vtkGenericAttribute::vtkGenericAttribute() +{ +} + +//--------------------------------------------------------------------------- +vtkGenericAttribute::~vtkGenericAttribute() +{ +} + +//--------------------------------------------------------------------------- +void vtkGenericAttribute::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Name: " << this->GetName() << endl; + os << indent << "Number of components: " << this->GetNumberOfComponents() << endl; + os << indent << "Centering: "; + + switch(this->GetCentering()) + { + case vtkPointCentered: + os << "on points"; + break; + case vtkCellCentered: + os << "on cells"; + break; + case vtkBoundaryCentered: + os << "on boundaries"; + break; + default: + assert("check: Impossible case" && 0); + break; + } + os << endl; +} diff --git a/Filtering/vtkGenericAttribute.h b/Filtering/vtkGenericAttribute.h new file mode 100644 index 0000000..9c61309 --- /dev/null +++ b/Filtering/vtkGenericAttribute.h @@ -0,0 +1,202 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericAttribute.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericAttribute - abstract class defined API for attribute data +// .SECTION Description +// vtkGenericAttribute is an abstract class that defines an API for attribute +// data. Attribute data is data associated with the topology or geometry of +// a dataset (i.e., points, cells, etc.). vtkGenericAttribute is part of the +// adaptor framework (see GenericFiltering/README.html). +// +// vtkGenericAttribute provides a more general interface to attribute data +// than its counterpart vtkDataArray (which assumes a linear, contiguous +// array). It adopts an iterator interface, and allows attributes to be +// associated with points, edges, faces, or edges. + +#ifndef __vtkGenericAttribute_h +#define __vtkGenericAttribute_h + +#include "vtkObject.h" + +class vtkGenericCellIterator; +class vtkGenericAdaptorCell; +class vtkGenericPointIterator; + +enum +{ + vtkPointCentered, + vtkCellCentered, + vtkBoundaryCentered +}; + +class VTK_FILTERING_EXPORT vtkGenericAttribute : public vtkObject +{ + public: + vtkTypeRevisionMacro(vtkGenericAttribute,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Name of the attribute. (e.g. "velocity") + // \post result_may_not_exist: result!=0 || result==0 + virtual const char *GetName() = 0; + + // Description: + // Dimension of the attribute. (1 for scalar, 3 for velocity) + // \post positive_result: result>=0 + // \post GetType()==VTK_SCALARS implies result==1 + // \post (GetType()==VTK_VECTORS||(GetType()==VTK_NORMALS)||(GetType()==VTK_TCOORDS) implies result==3 + // \post GetType()==VTK_TENSORS implies result==6 + virtual int GetNumberOfComponents() = 0; + + // Description: + // Is the attribute centered either on points, cells or boundaries? + // \post valid_result: (result==vtkPointCentered)||(result==vtkCellCentered) + virtual int GetCentering() = 0; + + // Description: + // Type of the attribute: scalar, vector, normal, texture coordinate, tensor + // \post valid_result: (result==vtkDataSetAttributes::SCALARS) + // ||(result==vtkDataSetAttributes::VECTORS) + // ||(result==vtkDataSetAttributes::NORMALS) + // ||(result==vtkDataSetAttributes::TCOORDS) + // ||(result==vtkDataSetAttributes::TENSORS) + virtual int GetType()=0; + + // Description: + // Type of the components of the attribute: int, float, double + // \post valid_result: (result==VTK_BIT) ||(result==VTK_CHAR) + // ||(result==VTK_UNSIGNED_CHAR) ||(result==VTK_SHORT) + // ||(result==VTK_UNSIGNED_SHORT)||(result==VTK_INT) + // ||(result==VTK_UNSIGNED_INT) ||(result==VTK_LONG) + // ||(result==VTK_UNSIGNED_LONG) ||(result==VTK_FLOAT) + // ||(result==VTK_DOUBLE) ||(result==VTK_ID_TYPE) + virtual int GetComponentType() = 0; + + // Description: + // Number of tuples. + // \post valid_result: result>=0 + virtual vtkIdType GetSize() = 0; + + // Description: + // Size in kilobytes taken by the attribute. + virtual unsigned long GetActualMemorySize() = 0; + + // Description: + // Range of the attribute component `component'. If `component'==-1, it + // returns the range of the magnitude (euclidean norm). + // It returns double, even if GetType()==VTK_INT. + // NOT THREAD SAFE + // \pre valid_component: (component>=-1)&&(component=-1)&&(component=0 + virtual double GetMaxNorm()=0; + + // Description: + // Attribute at all points of cell `c'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \post result_exists: result!=0 + // \post valid_result: sizeof(result)==GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + virtual double *GetTuple(vtkGenericAdaptorCell *c) = 0; + + // Description: + // Put attribute at all points of cell `c' in `tuple'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \pre tuple_exists: tuple!=0 + // \pre valid_tuple: sizeof(tuple)>=GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + virtual void GetTuple(vtkGenericAdaptorCell *c, double *tuple) = 0; + + // Description: + // Attribute at all points of cell `c'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \post result_exists: result!=0 + // \post valid_result: sizeof(result)==GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + virtual double *GetTuple(vtkGenericCellIterator *c) = 0; + + // Description: + // Put attribute at all points of cell `c' in `tuple'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \pre tuple_exists: tuple!=0 + // \pre valid_tuple: sizeof(tuple)>=GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + virtual void GetTuple(vtkGenericCellIterator *c, double *tuple) = 0; + + // Description: + // Value of the attribute at position `p'. + // \pre p_exists: p!=0 + // \pre p_valid: !p->IsAtEnd() + // \post result_exists: result!=0 + // \post valid_result_size: sizeof(result)==GetNumberOfComponents() + virtual double *GetTuple(vtkGenericPointIterator *p) = 0; + + // Description: + // Put the value of the attribute at position `p' into `tuple'. + // \pre p_exists: p!=0 + // \pre p_valid: !p->IsAtEnd() + // \pre tuple_exists: tuple!=0 + // \pre valid_tuple_size: sizeof(tuple)>=GetNumberOfComponents() + virtual void GetTuple(vtkGenericPointIterator *p, double *tuple) = 0; + + // Description: + // Put component `i' of the attribute at all points of cell `c' in `values'. + // \pre valid_component: (i>=0) && (iIsAtEnd() + // \pre values_exist: values!=0 + // \pre valid_values: sizeof(values)>=c->GetCell()->GetNumberOfPoints() + virtual void GetComponent(int i,vtkGenericCellIterator *c, double *values) = 0; + + // Description: + // Value of the component `i' of the attribute at position `p'. + // \pre valid_component: (i>=0) && (iIsAtEnd() + virtual double GetComponent(int i,vtkGenericPointIterator *p) = 0; + + // Description: + // Recursive duplication of `other' in `this'. + // \pre other_exists: other!=0 + // \pre not_self: other!=this + virtual void DeepCopy(vtkGenericAttribute *other) = 0; + + // Description: + // Update `this' using fields of `other'. + // \pre other_exists: other!=0 + // \pre not_self: other!=this + virtual void ShallowCopy(vtkGenericAttribute *other) = 0; + +protected: + vtkGenericAttribute(); + ~vtkGenericAttribute(); + +private: + vtkGenericAttribute(const vtkGenericAttribute&); // Not implemented. + void operator=(const vtkGenericAttribute&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericAttributeCollection.cxx b/Filtering/vtkGenericAttributeCollection.cxx new file mode 100644 index 0000000..f296788 --- /dev/null +++ b/Filtering/vtkGenericAttributeCollection.cxx @@ -0,0 +1,525 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericAttributeCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkGenericAttributeCollection.h" + +#include "vtkObjectFactory.h" +#include "vtkGenericAttribute.h" + + +#include +#include + +vtkCxxRevisionMacro(vtkGenericAttributeCollection,"$Revision: 1.9 $"); +vtkStandardNewMacro(vtkGenericAttributeCollection); + +class vtkGenericAttributeInternalVector +{ +public: + typedef vtkstd::vector VectorType; + VectorType Vector; +}; + +class vtkIntInternalVector +{ +public: + typedef vtkstd::vector VectorType; + VectorType Vector; +}; + +//---------------------------------------------------------------------------- +// Description: +// Default constructor: empty collection +vtkGenericAttributeCollection::vtkGenericAttributeCollection() +{ + this->AttributeInternalVector = new vtkGenericAttributeInternalVector; + this->AttributeIndices = new vtkIntInternalVector; + this->ActiveAttribute = 0; + this->ActiveComponent = 0; + this->NumberOfAttributesToInterpolate = 0; + this->NumberOfComponents = 0; + this->NumberOfPointCenteredComponents = 0; + this->MaxNumberOfComponents = 0; // cache + this->ActualMemorySize = 0; +} + +//---------------------------------------------------------------------------- +vtkGenericAttributeCollection::~vtkGenericAttributeCollection() +{ + for(unsigned int i=0; i < this->AttributeInternalVector->Vector.size(); ++i) + { + this->AttributeInternalVector->Vector[i]->Delete(); + } + delete this->AttributeInternalVector; + delete this->AttributeIndices; +} + +//---------------------------------------------------------------------------- +void vtkGenericAttributeCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int i; + int c = this->GetNumberOfAttributes(); + + os << indent << "Number Of Attributes: " << this->GetNumberOfAttributes() << "\n"; + for(i=0; iGetAttribute(i)->PrintSelf(os,indent.GetNextIndent()); + } + + c=this->GetNumberOfAttributesToInterpolate(); + os << indent << "Number Of Attributes to interpolate: " << c << endl; + + os << indent << "Attributes to interpolate:"; + + for(i=0; iAttributesToInterpolate[i]; + } + os << endl; + + os << indent << "Active Attribute: " << this->ActiveAttribute << endl; + + os << indent << "Active Component" << this->ActiveComponent << endl; +} + +//---------------------------------------------------------------------------- +// Description: +// Number of attributes. +int vtkGenericAttributeCollection::GetNumberOfAttributes() +{ + int result = this->AttributeInternalVector->Vector.size(); + //assert("post: positive_result" && result>=0); size() is an unsigned type according to STL vector definition + return result; +} + +//---------------------------------------------------------------------------- +int vtkGenericAttributeCollection::GetNumberOfComponents() +{ + this->ComputeNumbers(); + + return this->NumberOfComponents; +} + +//---------------------------------------------------------------------------- +// Description: +// Return the number of components. This is the sum of all components +// found in all point centered attributes. +// \post positive_result: result>=0 +int vtkGenericAttributeCollection::GetNumberOfPointCenteredComponents() +{ + this->ComputeNumbers(); + + return this->NumberOfPointCenteredComponents; +} + +//---------------------------------------------------------------------------- +// Description: +// Maximum number of components encountered among all attributes. +// \post positive_result: result>=0 +// \post valid_result: result<=GetNumberOfComponents() +int vtkGenericAttributeCollection::GetMaxNumberOfComponents() +{ + this->ComputeNumbers(); + + assert("post: positive_result" && this->MaxNumberOfComponents>=0); + assert("post: valid_result" && this->MaxNumberOfComponents<=GetNumberOfComponents()); + return this->MaxNumberOfComponents; +} + +//---------------------------------------------------------------------------- +// Description: +// Actual size of the data in kilobytes; only valid after the pipeline has +// updated. It is guaranteed to be greater than or equal to the memory +// required to represent the data. +unsigned long vtkGenericAttributeCollection::GetActualMemorySize() +{ + this->ComputeNumbers(); + return this->ActualMemorySize; +} + +//---------------------------------------------------------------------------- +// Description: +// Does `this' have no attribute? +int vtkGenericAttributeCollection::IsEmpty() +{ + return this->GetNumberOfAttributes()==0; +} + +//---------------------------------------------------------------------------- +// Description: +// Attribute `i'. +vtkGenericAttribute *vtkGenericAttributeCollection::GetAttribute(int i) +{ + assert("pre: not_empty" && !IsEmpty()); + assert("pre: valid_i" && (i>=0)&&(iGetNumberOfAttributes())); + vtkGenericAttribute *result=this->AttributeInternalVector->Vector[i]; + assert("post: result_exists" && result!=0); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Return the index of attribute `name', if found. Return -1 otherwise. +int vtkGenericAttributeCollection::FindAttribute(const char *name) +{ + assert("pre: name_exists:" && name!=0); + + int result=-1; + + const char *attributeName; + int numAtt = this->GetNumberOfAttributes(); + int i=0; + + while((iGetAttribute(i)->GetName(); + if(attributeName!=0) + { + if(strcmp( attributeName, name ) == 0) + { + result=i; + } + } + ++i; + } + + assert("post: valid_result" && ((result==-1) || + ((result>=0) && + (result<=this->GetNumberOfAttributes())))); + + return result; +} +//---------------------------------------------------------------------------- +// Description: +// Return the index of the first component of attribute `i' in an array of +// format attrib0comp0 attrib0comp1 ... attrib4comp0 ... +// \pre valid_i: i>=0 && iGetCentering()==vtkPointCentered +int vtkGenericAttributeCollection::GetAttributeIndex(int i) +{ + assert("pre: valid_i" && i>=0 && iGetNumberOfAttributes()); + assert("pre: is_point_centered" && this->GetAttribute(i)->GetCentering()==vtkPointCentered); + this->ComputeNumbers(); + return this->AttributeIndices->Vector[i]; +} + +//---------------------------------------------------------------------------- +// Description: +// Add attribute `a' at the end. +void vtkGenericAttributeCollection::InsertNextAttribute(vtkGenericAttribute *a) +{ + assert("pre: a_exists" && a!=0); +#ifndef NDEBUG + int oldnumber=this->GetNumberOfAttributes(); +#endif + + this->AttributeInternalVector->Vector.push_back(a); + this->AttributeIndices->Vector.push_back(0); // a dummy default value + a->Register( this ); + this->Modified(); + + assert("post: more_items" && this->GetNumberOfAttributes()==oldnumber+1); + assert("post: a_is_set" && this->GetAttribute(this->GetNumberOfAttributes()-1)==a); +} + +//---------------------------------------------------------------------------- +// Description: +// Replace attribute at index `i' by `a'. +void vtkGenericAttributeCollection::InsertAttribute(int i, vtkGenericAttribute *a) +{ + assert("pre: not_empty" && !this->IsEmpty()); + assert("pre: a_exists" && a!=0); + assert("pre: valid_i" && (i>=0)&&(iGetNumberOfAttributes())); + +#ifndef NDEBUG + int oldnumber = this->GetNumberOfAttributes(); +#endif + + if(this->AttributeInternalVector->Vector[i]!=0) + { + this->AttributeInternalVector->Vector[i]->Delete(); + } + this->AttributeInternalVector->Vector[i] = a; + a->Register( this ); + this->Modified(); + + assert("post: more_items" && this->GetNumberOfAttributes()==oldnumber); + assert("post: a_is_set" && this->GetAttribute(i)==a); +} + +//---------------------------------------------------------------------------- +// Description: +// Remove Attribute at `i'. +void vtkGenericAttributeCollection::RemoveAttribute(int i) +{ + assert("pre: not_empty" && !this->IsEmpty()); + assert("pre: valid_i" && (i>=0)&&(iGetNumberOfAttributes())); + +#ifndef NDEBUG + int oldnumber=this->GetNumberOfAttributes(); +#endif + + this->AttributeInternalVector->Vector[i]->UnRegister( this ); + this->AttributeInternalVector->Vector.erase( + this->AttributeInternalVector->Vector.begin()+i); + + this->AttributeIndices->Vector.erase( + this->AttributeIndices->Vector.begin()+i); + + this->Modified(); + + assert("post: fewer_items" && this->GetNumberOfAttributes()==(oldnumber-1)); +} + +//---------------------------------------------------------------------------- +// Description: +// Remove all attributes. +void vtkGenericAttributeCollection::Reset() +{ + for(unsigned int i = 0; i < this->AttributeInternalVector->Vector.size(); ++i) + { + this->AttributeInternalVector->Vector[i]->Delete(); + } + this->AttributeInternalVector->Vector.clear(); + this->AttributeIndices->Vector.clear(); + this->Modified(); + + assert("post: is_empty" && this->IsEmpty()); +} + +//---------------------------------------------------------------------------- +// Description: +// Recursive duplication of `other' in `this'. +void vtkGenericAttributeCollection::DeepCopy(vtkGenericAttributeCollection *other) +{ + assert("pre: other_exists" && other!=0); + assert("pre: not_self" && other!=this); + + this->AttributeInternalVector->Vector.resize( + other->AttributeInternalVector->Vector.size()); + + this->AttributeIndices->Vector.resize( + other->AttributeIndices->Vector.size()); + + int c = this->AttributeInternalVector->Vector.size(); + for(int i=0; iAttributeInternalVector->Vector[i] == 0) + { + this->AttributeInternalVector->Vector[i] = + other->AttributeInternalVector->Vector[i]->NewInstance(); + } + this->AttributeInternalVector->Vector[i]->DeepCopy( + other->AttributeInternalVector->Vector[i]); + // Dont need to copy the contents of AttributeIndices: it will be + // recomputed because of the following Moditied call. + } + this->Modified(); + + assert("post: same_size" && this->GetNumberOfAttributes()==other->GetNumberOfAttributes()); +} + +//---------------------------------------------------------------------------- +// Description: +// Update `this' using fields of `other'. +void vtkGenericAttributeCollection::ShallowCopy(vtkGenericAttributeCollection *other) +{ + assert("pre: other_exists" && other!=0); + assert("pre: not_self" && other!=this); + + this->AttributeInternalVector->Vector = + other->AttributeInternalVector->Vector; + this->AttributeIndices->Vector = other->AttributeIndices->Vector; + int c = this->AttributeInternalVector->Vector.size(); + for (int i=0; iAttributeInternalVector->Vector[i] != 0) + { + this->AttributeInternalVector->Vector[i]->Register( this ); + } + } + this->Modified(); + + assert("post: same_size" && this->GetNumberOfAttributes()==other->GetNumberOfAttributes()); +} + +//---------------------------------------------------------------------------- +// Description: +// Collection is composite object and need to check each part for MTime. +unsigned long int vtkGenericAttributeCollection::GetMTime() +{ + unsigned long result; + unsigned long mtime; + + result = vtkObject::GetMTime(); + + for(int i = 0; i < this->GetNumberOfAttributes(); ++i) + { + mtime = this->GetAttribute(i)->GetMTime(); + result = ( mtime > result ? mtime : result ); + } + + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Compute number of components, max number of components and actual memory +// size. +void vtkGenericAttributeCollection::ComputeNumbers() +{ + if ( this->GetMTime() > this->ComputeTime ) + { + int nb = 0; + int pnb = 0; + int count; + int maxNb = 0; + unsigned long memory=0; + int firstComponentIndex=0; + + int c = this->GetNumberOfAttributes(); + + for(int i = 0; i < c; ++i) + { + count = this->GetAttribute(i)->GetNumberOfComponents(); + memory=memory+this->GetAttribute(i)->GetActualMemorySize(); + if(count > maxNb) + { + maxNb = count; + } + nb += count; + if(this->GetAttribute(i)->GetCentering()==vtkPointCentered) + { + pnb += count; + this->AttributeIndices->Vector[i]=firstComponentIndex; + firstComponentIndex=firstComponentIndex+count; + } + } + this->NumberOfComponents = nb; + this->NumberOfPointCenteredComponents = pnb; + this->MaxNumberOfComponents = maxNb; + this->ActualMemorySize = memory; + + assert("check: positive_number" && this->NumberOfComponents>=0); + assert("check: positive_point_centered_number" && this->NumberOfPointCenteredComponents>=0); + assert("check: positiveMaxNumber" && this->MaxNumberOfComponents>=0); + assert("check: valid_number" && this->MaxNumberOfComponents<=this->NumberOfComponents); + this->ComputeTime.Modified(); + } +} + +//---------------------------------------------------------------------------- +// *** ALL THE FOLLOWING METHODS SHOULD BE REMOVED WHEN vtkInformation +// will be ready. +// *** BEGIN + +// Description: +// Set the scalar attribute to be processed. -1 means module. +void vtkGenericAttributeCollection::SetActiveAttribute(int attribute, + int component) +{ + assert("pre: not_empty" && !IsEmpty()); + assert("pre: valid_attribute" && (attribute>=0)&&(attributeGetNumberOfAttributes())); + assert("pre: valid_component" && (component>=-1)&&(componentGetAttribute(attribute)->GetNumberOfComponents())); + + this->ActiveAttribute = attribute; + this->ActiveComponent = component; + + assert("post: is_set" && (this->GetActiveAttribute()==attribute) && (this->GetActiveComponent()==component)); +} + +//---------------------------------------------------------------------------- +// Description: +// Indices of attributes to interpolate. +// \pre not_empty: !IsEmpty() +// \post valid_result: GetNumberOfAttributesToInterpolate()>0 implies +// result!=0 +int *vtkGenericAttributeCollection::GetAttributesToInterpolate() +{ + assert("pre: not_empty" && !IsEmpty()); + + assert("post: valid_result" && ((!(this->NumberOfAttributesToInterpolate>0)) + || this->AttributesToInterpolate!=0)); + // A=>B !A||B + + return this->AttributesToInterpolate; +} + +//---------------------------------------------------------------------------- +// Description +// Does the array `attributes' of size `size' have `attribute'? +int vtkGenericAttributeCollection::HasAttribute(int size, + int *attributes, + int attribute) +{ + assert("pre: positive_size" && size>=0); + assert("pre: valid_attributes" && ((!(size>0))||(attributes!=0))); // size>0 => attributes!=0 (A=>B: !A||B ) + + int result = 0; // false + int i; + + if(size != 0) + { + i = 0; + while( !result && i++ < size ) + { + result = attributes[i] == attribute; + } + } + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Set the attributes to interpolate. +void vtkGenericAttributeCollection::SetAttributesToInterpolate(int size, + int *attributes) +{ + assert("pre: not_empty" && !this->IsEmpty()); + assert("pre: positive_size" && size>=0); + assert("pre: magic_number" && size<=10); + assert("pre: valid_attributes" && ((!(size>0))||(attributes!=0))); // size>0 => attributes!=0 (A=>B: !A||B ) + assert("pre: valid_attributes_contents" && (!(attributes!=0) || !(!this->HasAttribute(size,attributes,this->GetActiveAttribute())))); // attributes!=0 => !this->HasAttribute(size,attributes,this->GetActiveAttribute()) (A=>B: !A||B ) + + this->NumberOfAttributesToInterpolate = size; + for(int i=0; iAttributesToInterpolate[i] = attributes[i]; + } + + assert("post: is_set" && (this->GetNumberOfAttributesToInterpolate()==size)); +} + +//---------------------------------------------------------------------------- +// Description: +// Set the attributes to interpolate. +void vtkGenericAttributeCollection::SetAttributesToInterpolateToAll() +{ + assert("pre: not_empty" && !this->IsEmpty()); + + this->NumberOfAttributesToInterpolate = this->GetMaxNumberOfComponents(); + for(int i=0; iNumberOfAttributesToInterpolate; ++i) + { + this->AttributesToInterpolate[i] = i; + } +} + +//---------------------------------------------------------------------------- +// *** ALL THE PREVIOUS METHODS SHOULD BE REMOVED WHEN vtkInformation +// will be ready. +// *** END diff --git a/Filtering/vtkGenericAttributeCollection.h b/Filtering/vtkGenericAttributeCollection.h new file mode 100644 index 0000000..6f2857d --- /dev/null +++ b/Filtering/vtkGenericAttributeCollection.h @@ -0,0 +1,240 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericAttributeCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericAttributeCollection - a collection of attributes +// .SECTION Description +// vtkGenericAttributeCollection is a class that collects attributes +// (represented by vtkGenericAttribute). + +#ifndef __vtkGenericAttributeCollection_h +#define __vtkGenericAttributeCollection_h + +#include "vtkObject.h" + +class vtkGenericAttributeInternalVector; +class vtkIntInternalVector; +class vtkGenericAttribute; + +class VTK_FILTERING_EXPORT vtkGenericAttributeCollection : public vtkObject +{ +public: + // Description: + // Create an empty collection. + static vtkGenericAttributeCollection *New(); + + // Description: + // Standard type definition and print methods for a VTK class. + vtkTypeRevisionMacro(vtkGenericAttributeCollection,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the number of attributes (e.g., instances of vtkGenericAttribute) + // in the collection. + // \post positive_result: result>=0 + int GetNumberOfAttributes(); + + // Description: + // Return the number of components. This is the sum of all components + // found in all attributes. + // \post positive_result: result>=0 + int GetNumberOfComponents(); + + // Description: + // Return the number of components. This is the sum of all components + // found in all point centered attributes. + // \post positive_result: result>=0 + int GetNumberOfPointCenteredComponents(); + + // Description: + // Maximum number of components encountered among all attributes. + // \post positive_result: result>=0 + // \post valid_result: result<=GetNumberOfComponents() + int GetMaxNumberOfComponents(); + + // Description: + // Actual size of the data in kilobytes; only valid after the pipeline has + // updated. It is guaranteed to be greater than or equal to the memory + // required to represent the data. + unsigned long GetActualMemorySize(); + + // Description: + // Indicate whether the collection contains any attributes. + // \post definition: result==(GetNumberOfAttributes()==0) + int IsEmpty(); + + // Description: + // Return a pointer to the ith instance of vtkGenericAttribute. + // \pre not_empty: !IsEmpty() + // \pre valid_i: i>=0 && i=0) && (result<=GetNumberOfAttributes()) + int FindAttribute(const char *name); + + // Description: + // Return the index of the first component of attribute `i' in an array of + // format attrib0comp0 attrib0comp1 ... attrib4comp0 ... + // \pre valid_i: i>=0 && iGetCentering()==vtkPointCentered + int GetAttributeIndex(int i); + + // Description: + // Add the attribute `a' to the end of the collection. + // \pre a_exists: a!=0 + // \post more_items: GetNumberOfAttributes()==old GetNumberOfAttributes()+1 + // \post a_is_set: GetAttribute(GetNumberOfAttributes()-1)==a + void InsertNextAttribute(vtkGenericAttribute *a); + + // Description: + // Replace the attribute at index `i' by `a'. + // \pre not_empty: !IsEmpty() + // \pre a_exists: a!=0 + // \pre valid_i: i>=0 && i=0 && iGetNumberOfAttributes() + void DeepCopy(vtkGenericAttributeCollection *other); + + // Description: + // Copy, via reference counting, the other attribute array. + // \pre other_exists: other!=0 + // \pre not_self: other!=this + // \post same_size: GetNumberOfAttributes()==other->GetNumberOfAttributes() + void ShallowCopy(vtkGenericAttributeCollection *other); + + // Description: + // vtkAttributeCollection is a composite object and needs to check each + // member of its collection for modified time. + virtual unsigned long int GetMTime(); + + // *** ALL THE FOLLOWING METHODS SHOULD BE REMOVED WHEN when the + // new pipeline update mechanism is checked in. + // *** BEGIN + + // Description: + // Index of the attribute to be processed (not necessarily scalar). + // \pre not_empty: !IsEmpty() + // \post valid_result: result>=0 && result0 + // \post valid_result: result>=-1 && + // resultGetNumberOfComponents() + vtkGetMacro(ActiveComponent, int); + + // Description: + // Set the scalar attribute to be processed. -1 means module. + // \pre not_empty: !IsEmpty() + // \pre valid_attribute: attribute>=0 && attribute=-1 && + // componentGetNumberOfComponents() + // \post is_set: GetActiveAttribute()==attribute && + // GetActiveComponent()==component + void SetActiveAttribute(int attribute, int component = 0); + + // Description: + // Number of attributes to interpolate. + // \pre not_empty: !IsEmpty() + // \post positive_result: result>=0 + vtkGetMacro(NumberOfAttributesToInterpolate, int); + + //BTX + // Description: + // Indices of attributes to interpolate. + // \pre not_empty: !IsEmpty() + // \post valid_result: GetNumberOfAttributesToInterpolate()>0 implies + // result!=0 + int *GetAttributesToInterpolate(); + //ETX + + // Description + // Does the array `attributes' of size `size' have `attribute'? + // \pre positive_size: size>=0 + // \pre valid_attributes: size>0 implies attributes!=0 + int HasAttribute(int size, int *attributes, int attribute); + + // Description: + // Set the attributes to interpolate. + // \pre not_empty: !IsEmpty() + // \pre positive_size: size>=0 + // \pre valid_attributes: size>0 implies attributes!=0 + // \pre valid_attributes_contents: attributes!=0 implies + // !HasAttributes(size,attributes,GetActiveAttribute()) + // \post is_set: (GetNumberOfAttributesToInterpolate()==size)&& + // (GetAttributesToInterpolate()==attributes) + void SetAttributesToInterpolate(int size, int *attributes); + void SetAttributesToInterpolateToAll(); + +protected: + // Description: + // Default constructor: empty collection. + vtkGenericAttributeCollection(); + + // Description: + // Destructor. + virtual ~vtkGenericAttributeCollection(); + + // Description: + // STL vector for storing attributes + vtkGenericAttributeInternalVector* AttributeInternalVector; + // Description: + // STL vector for storing index of point centered attributes + vtkIntInternalVector *AttributeIndices; + + int ActiveAttribute; + int ActiveComponent; + int NumberOfAttributesToInterpolate; + int AttributesToInterpolate[10]; + + int NumberOfComponents; // cache + int NumberOfPointCenteredComponents; // cache + int MaxNumberOfComponents; // cache + unsigned long ActualMemorySize; // cache + vtkTimeStamp ComputeTime; // cache time stamp + + // Description: + // Compute number of components, max number of components and actual + // memory size. + void ComputeNumbers(); + +private: + vtkGenericAttributeCollection(const vtkGenericAttributeCollection &); // Not implemented. + void operator=(const vtkGenericAttributeCollection &); // Not implemented. +}; +#endif diff --git a/Filtering/vtkGenericCell.cxx b/Filtering/vtkGenericCell.cxx new file mode 100644 index 0000000..711b445 --- /dev/null +++ b/Filtering/vtkGenericCell.cxx @@ -0,0 +1,317 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericCell.h" +#include "vtkEmptyCell.h" +#include "vtkVertex.h" +#include "vtkPolyVertex.h" +#include "vtkLine.h" +#include "vtkPolyLine.h" +#include "vtkTriangle.h" +#include "vtkTriangleStrip.h" +#include "vtkQuad.h" +#include "vtkPixel.h" +#include "vtkPolygon.h" +#include "vtkTetra.h" +#include "vtkHexahedron.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" +#include "vtkPyramid.h" +#include "vtkPentagonalPrism.h" +#include "vtkHexagonalPrism.h" +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticTriangle.h" +#include "vtkQuadraticQuad.h" +#include "vtkQuadraticTetra.h" +#include "vtkQuadraticHexahedron.h" +#include "vtkQuadraticWedge.h" +#include "vtkQuadraticPyramid.h" +#include "vtkConvexPointSet.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkGenericCell, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkGenericCell); + +//---------------------------------------------------------------------------- +// Construct cell. +vtkGenericCell::vtkGenericCell() +{ + this->Cell = vtkEmptyCell::New(); +} + +//---------------------------------------------------------------------------- +vtkGenericCell::~vtkGenericCell() +{ + this->Cell->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::ShallowCopy(vtkCell *c) +{ + this->Cell->ShallowCopy(c); +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::DeepCopy(vtkCell *c) +{ + this->Cell->DeepCopy(c); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::GetCellType() +{ + return this->Cell->GetCellType(); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::GetCellDimension() +{ + return this->Cell->GetCellDimension(); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::IsLinear() +{ + return this->Cell->IsLinear(); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::RequiresInitialization() +{ + return this->Cell->RequiresInitialization(); +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::Initialize() +{ + this->Cell->Initialize(); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::GetNumberOfEdges() +{ + return this->Cell->GetNumberOfEdges(); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::GetNumberOfFaces() +{ + return this->Cell->GetNumberOfFaces(); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkGenericCell::GetEdge(int edgeId) +{ + return this->Cell->GetEdge(edgeId); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkGenericCell::GetFace(int faceId) +{ + return this->Cell->GetFace(faceId); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::CellBoundary(int subId, double pcoords[3], vtkIdList *pts) +{ + return this->Cell->CellBoundary(subId, pcoords, pts); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::EvaluatePosition(double x[3], double closestPoint[3], + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + return this->Cell->EvaluatePosition(x, closestPoint, subId, + pcoords, dist2, weights); +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::EvaluateLocation(int& subId, double pcoords[3], + double x[3], double *weights) +{ + this->Cell->EvaluateLocation(subId, pcoords, x, weights); +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + this->Cell->Contour(value, cellScalars, locator, verts, lines, polys, + inPd, outPd, inCd, cellId, outCd); +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *connectivity, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd, int insideOut) +{ + this->Cell->Clip(value, cellScalars, locator, connectivity, inPd, + outPd, inCd, cellId, outCd, insideOut); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::IntersectWithLine(double p1[3], double p2[3], double tol, + double& t, double x[3], double pcoords[3], + int& subId) +{ + return this->Cell->IntersectWithLine(p1, p2, tol, t, x, pcoords, subId); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts) +{ + return this->Cell->Triangulate(index, ptIds, pts); +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs) +{ + this->Cell->Derivatives(subId, pcoords, values, dim, derivs); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::GetParametricCenter(double pcoords[3]) +{ + return this->Cell->GetParametricCenter(pcoords); +} + +//---------------------------------------------------------------------------- +double *vtkGenericCell::GetParametricCoords() +{ + return this->Cell->GetParametricCoords(); +} + +//---------------------------------------------------------------------------- +int vtkGenericCell::IsPrimaryCell() +{ + return this->Cell->IsPrimaryCell(); +} + +//---------------------------------------------------------------------------- +// Set the type of dereferenced cell. Checks to see whether cell type +// has changed and creates a new cell only if necessary. +void vtkGenericCell::SetCellType(int cellType) +{ + if ( this->Cell->GetCellType() != cellType ) + { + this->Points->UnRegister(this); + this->PointIds->UnRegister(this); + this->PointIds = NULL; + this->Cell->Delete(); + + switch (cellType) + { + case VTK_EMPTY_CELL: + this->Cell = vtkEmptyCell::New(); + break; + case VTK_VERTEX: + this->Cell = vtkVertex::New(); + break; + case VTK_POLY_VERTEX: + this->Cell = vtkPolyVertex::New(); + break; + case VTK_LINE: + this->Cell = vtkLine::New(); + break; + case VTK_POLY_LINE: + this->Cell = vtkPolyLine::New(); + break; + case VTK_TRIANGLE: + this->Cell = vtkTriangle::New(); + break; + case VTK_TRIANGLE_STRIP: + this->Cell = vtkTriangleStrip::New(); + break; + case VTK_POLYGON: + this->Cell = vtkPolygon::New(); + break; + case VTK_PIXEL: + this->Cell = vtkPixel::New(); + break; + case VTK_QUAD: + this->Cell = vtkQuad::New(); + break; + case VTK_TETRA: + this->Cell = vtkTetra::New(); + break; + case VTK_VOXEL: + this->Cell = vtkVoxel::New(); + break; + case VTK_HEXAHEDRON: + this->Cell = vtkHexahedron::New(); + break; + case VTK_WEDGE: + this->Cell = vtkWedge::New(); + break; + case VTK_PYRAMID: + this->Cell = vtkPyramid::New(); + break; + case VTK_PENTAGONAL_PRISM: + this->Cell = vtkPentagonalPrism::New(); + break; + case VTK_HEXAGONAL_PRISM: + this->Cell = vtkHexagonalPrism::New(); + break; + case VTK_QUADRATIC_EDGE: + this->Cell = vtkQuadraticEdge::New(); + break; + case VTK_QUADRATIC_TRIANGLE: + this->Cell = vtkQuadraticTriangle::New(); + break; + case VTK_QUADRATIC_QUAD: + this->Cell = vtkQuadraticQuad::New(); + break; + case VTK_QUADRATIC_TETRA: + this->Cell = vtkQuadraticTetra::New(); + break; + case VTK_QUADRATIC_HEXAHEDRON: + this->Cell = vtkQuadraticHexahedron::New(); + break; + case VTK_QUADRATIC_WEDGE: + this->Cell = vtkQuadraticWedge::New(); + break; + case VTK_QUADRATIC_PYRAMID: + this->Cell = vtkQuadraticPyramid::New(); + break; + case VTK_CONVEX_POINT_SET: + this->Cell = vtkConvexPointSet::New(); + break; + default: + vtkErrorMacro(<<"Unsupported cell type! Setting to vtkEmptyCell"); + this->SetCellType(VTK_EMPTY_CELL); + } + this->Points = this->Cell->Points; + this->Points->Register(this); + this->PointIds = this->Cell->PointIds; + this->PointIds->Register(this); + }//need to change cell type +} + +//---------------------------------------------------------------------------- +void vtkGenericCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cell:\n"; + this->Cell->PrintSelf(os,indent.GetNextIndent()); +} + diff --git a/Filtering/vtkGenericCell.h b/Filtering/vtkGenericCell.h new file mode 100644 index 0000000..c5d80ab --- /dev/null +++ b/Filtering/vtkGenericCell.h @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericCell - provides thread-safe access to cells +// .SECTION Description +// vtkGenericCell is a class that provides access to concrete types of cells. +// It's main purpose is to allow thread-safe access to cells, supporting +// the vtkDataSet::GetCell(vtkGenericCell *) method. vtkGenericCell acts +// like any type of cell, it just dereferences an internal representation. +// The SetCellType() methods use #define constants; these are defined in +// the file vtkCellType.h. + +// .SECTION See Also +// vtkCell vtkDataSet + +#ifndef __vtkGenericCell_h +#define __vtkGenericCell_h + +#include "vtkCell.h" + +class VTK_FILTERING_EXPORT vtkGenericCell : public vtkCell +{ +public: + // Description: + // Create handle to any type of cell; by default a vtkEmptyCell. + static vtkGenericCell *New(); + + vtkTypeRevisionMacro(vtkGenericCell,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + void ShallowCopy(vtkCell *c); + void DeepCopy(vtkCell *c); + int GetCellType(); + int GetCellDimension(); + int IsLinear(); + int RequiresInitialization(); + void Initialize(); + int GetNumberOfEdges(); + int GetNumberOfFaces(); + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], + double x[3], double *weights); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *connectivity, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + int GetParametricCenter(double pcoords[3]); + double *GetParametricCoords(); + int IsPrimaryCell(); + + // Description: + // This method is used to support the vtkDataSet::GetCell(vtkGenericCell *) + // method. It allows vtkGenericCell to act like any cell type by + // dereferencing an internal instance of a concrete cell type. When + // you set the cell type, you are resetting a pointer to an internal + // cell which is then used for computation. + void SetCellType(int cellType); + void SetCellTypeToEmptyCell() {this->SetCellType(VTK_EMPTY_CELL);} + void SetCellTypeToVertex() {this->SetCellType(VTK_VERTEX);} + void SetCellTypeToPolyVertex() {this->SetCellType(VTK_POLY_VERTEX);} + void SetCellTypeToLine() {this->SetCellType(VTK_LINE);} + void SetCellTypeToPolyLine() {this->SetCellType(VTK_POLY_LINE);} + void SetCellTypeToTriangle() {this->SetCellType(VTK_TRIANGLE);} + void SetCellTypeToTriangleStrip() {this->SetCellType(VTK_TRIANGLE_STRIP);} + void SetCellTypeToPolygon() {this->SetCellType(VTK_POLYGON);} + void SetCellTypeToPixel() {this->SetCellType(VTK_PIXEL);} + void SetCellTypeToQuad() {this->SetCellType(VTK_QUAD);} + void SetCellTypeToTetra() {this->SetCellType(VTK_TETRA);} + void SetCellTypeToVoxel() {this->SetCellType(VTK_VOXEL);} + void SetCellTypeToHexahedron() {this->SetCellType(VTK_HEXAHEDRON);} + void SetCellTypeToWedge() {this->SetCellType(VTK_WEDGE);} + void SetCellTypeToPyramid() {this->SetCellType(VTK_PYRAMID);} + void SetCellTypeToPentagonalPrism() {this->SetCellType(VTK_PENTAGONAL_PRISM);} + void SetCellTypeToHexagonalPrism() {this->SetCellType(VTK_HEXAGONAL_PRISM);} + void SetCellTypeToConvexPointSet() {this->SetCellType(VTK_CONVEX_POINT_SET);} + void SetCellTypeToQuadraticEdge() {this->SetCellType(VTK_QUADRATIC_EDGE);} + void SetCellTypeToQuadraticTriangle() {this->SetCellType(VTK_QUADRATIC_TRIANGLE);} + void SetCellTypeToQuadraticQuad() {this->SetCellType(VTK_QUADRATIC_QUAD);} + void SetCellTypeToQuadraticTetra() {this->SetCellType(VTK_QUADRATIC_TETRA);} + void SetCellTypeToQuadraticHexahedron() {this->SetCellType(VTK_QUADRATIC_HEXAHEDRON);} + void SetCellTypeToQuadraticWedge() {this->SetCellType(VTK_QUADRATIC_WEDGE);} + void SetCellTypeToQuadraticPyramid() {this->SetCellType(VTK_QUADRATIC_PYRAMID);} + +protected: + vtkGenericCell(); + ~vtkGenericCell(); + + vtkCell *Cell; + +private: + vtkGenericCell(const vtkGenericCell&); // Not implemented. + void operator=(const vtkGenericCell&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkGenericCellIterator.cxx b/Filtering/vtkGenericCellIterator.cxx new file mode 100644 index 0000000..8529d9f --- /dev/null +++ b/Filtering/vtkGenericCellIterator.cxx @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCellIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericCellIterator.h" + +vtkCxxRevisionMacro(vtkGenericCellIterator, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +vtkGenericCellIterator::vtkGenericCellIterator() +{ +} + +//---------------------------------------------------------------------------- +vtkGenericCellIterator::~vtkGenericCellIterator() +{ +} + +//---------------------------------------------------------------------------- +void vtkGenericCellIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + +} + diff --git a/Filtering/vtkGenericCellIterator.h b/Filtering/vtkGenericCellIterator.h new file mode 100644 index 0000000..b951846 --- /dev/null +++ b/Filtering/vtkGenericCellIterator.h @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCellIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericCellIterator - iterator used to traverse cells +// .SECTION Description +// This class (and subclasses) are used to iterate over cells. Use it +// only in conjunction with vtkGenericDataSet (i.e., the adaptor framework). +// +// Typical use is: +//
+// vtkGenericDataSet *dataset;
+// vtkGenericCellIterator *it = dataset->NewCellIterator(2);
+// for (it->Begin(); !it->IsAtEnd(); it->Next());
+//   {
+//   spec=it->GetCell();
+//   }
+// 
+ +#ifndef __vtkGenericCellIterator_h +#define __vtkGenericCellIterator_h + +#include "vtkObject.h" + +class vtkGenericAdaptorCell; + +class VTK_FILTERING_EXPORT vtkGenericCellIterator : public vtkObject +{ +public: + // Description: + // Standard VTK construction and type macros. + vtkTypeRevisionMacro(vtkGenericCellIterator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + virtual void Begin() = 0; + + // Description: + // Is the iterator at the end of traversal? + virtual int IsAtEnd() = 0; + + // Description: + // Create an empty cell. The user is responsible for deleting it. + // \post result_exists: result!=0 + virtual vtkGenericAdaptorCell *NewCell() = 0; + + // Description: + // Get the cell at current position. The cell should be instantiated + // with the NewCell() method. + // \pre not_at_end: !IsAtEnd() + // \pre c_exists: c!=0 + // THREAD SAFE + virtual void GetCell(vtkGenericAdaptorCell *c) = 0; + + // Description: + // Get the cell at the current traversal position. + // NOT THREAD SAFE + // \pre not_at_end: !IsAtEnd() + // \post result_exits: result!=0 + virtual vtkGenericAdaptorCell *GetCell() = 0; + + // Description: + // Move the iterator to the next position in the list. + // \pre not_at_end: !IsAtEnd() + virtual void Next() = 0; + +protected: + vtkGenericCellIterator(); + virtual ~vtkGenericCellIterator(); + +private: + vtkGenericCellIterator(const vtkGenericCellIterator&); // Not implemented. + void operator=(const vtkGenericCellIterator&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericCellTessellator.cxx b/Filtering/vtkGenericCellTessellator.cxx new file mode 100644 index 0000000..1af524b --- /dev/null +++ b/Filtering/vtkGenericCellTessellator.cxx @@ -0,0 +1,257 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCellTessellator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericCellTessellator.h" +#include "vtkObjectFactory.h" + +#include "vtkPoints.h" +#include "vtkIdList.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkPointData.h" +#include "vtkDoubleArray.h" +#include "vtkMergePoints.h" +#include "vtkCellArray.h" +#include "vtkCollection.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericCellIterator.h" + + +#include + +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkGenericCellTessellator, "$Revision: 1.11 $"); +vtkCxxSetObjectMacro(vtkGenericCellTessellator, ErrorMetrics, vtkCollection); + +//----------------------------------------------------------------------------- +// Create the tessellator helper with a default of 0.25 for threshold +// +vtkGenericCellTessellator::vtkGenericCellTessellator() +{ + this->ErrorMetrics = vtkCollection::New(); + this->MaxErrorsCapacity=0; + this->MaxErrors=0; + this->Measurement=0; +} + +//----------------------------------------------------------------------------- +vtkGenericCellTessellator::~vtkGenericCellTessellator() +{ + this->SetErrorMetrics( 0 ); + if(this->MaxErrors!=0) + { + delete[] this->MaxErrors; + } +} + + +//----------------------------------------------------------------------------- +void vtkGenericCellTessellator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ErrorMetrics: " + << this->ErrorMetrics << endl; + +} + +//----------------------------------------------------------------------------- +// Description: +// If true, measure the quality of the fixed subdivision. +int vtkGenericCellTessellator::GetMeasurement() +{ + return this->Measurement; +} + +//----------------------------------------------------------------------------- +// Description: +// If true, measure the quality of the fixed subdivision. +void vtkGenericCellTessellator::SetMeasurement(int flag) +{ + this->Measurement=flag; +} + +//----------------------------------------------------------------------------- +// Description: +// Does the edge need to be subdivided according to at least one error +// metric? The edge is defined by its `leftPoint' and its `rightPoint'. +// `leftPoint', `midPoint' and `rightPoint' have to be initialized before +// calling RequiresEdgeSubdivision(). +// Their format is global coordinates, parametric coordinates and +// point centered attributes: xyx rst abc de... +// `alpha' is the normalized abscissa of the midpoint along the edge. +// (close to 0 means close to the left point, close to 1 means close to the +// right point) +// \pre leftPoint_exists: leftPoint!=0 +// \pre midPoint_exists: midPoint!=0 +// \pre rightPoint_exists: rightPoint!=0 +// \pre clamped_alpha: alpha>0 && alpha<1 +// \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) +// =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 +int vtkGenericCellTessellator::RequiresEdgeSubdivision(double *leftPoint, + double *midPoint, + double *rightPoint, + double alpha) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); + assert("pre: clamped_alpha" && alpha>0 && alpha<1); + + int result=0; + this->ErrorMetrics->InitTraversal(); + vtkGenericSubdivisionErrorMetric *e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + + // Once we found at least one error metric that need subdivision, + // the subdivision has to be done and there is no need to check for other + // error metrics. + while(!result&&(e!=0)) + { + result=e->RequiresEdgeSubdivision(leftPoint,midPoint,rightPoint,alpha); + e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + } + + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Update the max error of each error metric according to the error at the +// mid-point. The type of error depends on the state +// of the concrete error metric. For instance, it can return an absolute +// or relative error metric. +// See RequiresEdgeSubdivision() for a description of the arguments. +// \pre leftPoint_exists: leftPoint!=0 +// \pre midPoint_exists: midPoint!=0 +// \pre rightPoint_exists: rightPoint!=0 +// \pre clamped_alpha: alpha>0 && alpha<1 +// \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) +// =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 +void vtkGenericCellTessellator::UpdateMaxError(double *leftPoint, + double *midPoint, + double *rightPoint, + double alpha) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); + assert("pre: clamped_alpha" && alpha>0 && alpha<1); + + this->ErrorMetrics->InitTraversal(); + vtkGenericSubdivisionErrorMetric *e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + + // Once we found at least one error metric that need subdivision, + // the subdivision has to be done and there is no need to check for other + // error metrics. + int i=0; + while(e!=0) + { + double error=e->GetError(leftPoint,midPoint,rightPoint,alpha); + assert("check: positive_error" && error>=0); + if(error>this->MaxErrors[i]) + { + this->MaxErrors[i]=error; + } + e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + ++i; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Init the error metric with the dataset. Should be called in each filter +// before any tessellation of any cell. +void vtkGenericCellTessellator::InitErrorMetrics(vtkGenericDataSet *ds) +{ + this->ErrorMetrics->InitTraversal(); + vtkGenericSubdivisionErrorMetric *e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + + while(e!=0) + { + e->SetDataSet(ds); + e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + } + + if(this->Measurement) + { + this->ResetMaxErrors(); + } +} + +//----------------------------------------------------------------------------- +// Description: +// Reset the maximal error of each error metric. The purpose of the maximal +// error is to measure the quality of a fixed subdivision. +void vtkGenericCellTessellator::ResetMaxErrors() +{ + int c=this->ErrorMetrics->GetNumberOfItems(); + + // Allocate the array. + if(c>this->MaxErrorsCapacity) + { + this->MaxErrorsCapacity=c; + if(this->MaxErrors!=0) + { + delete[] this->MaxErrors; + } + this->MaxErrors=new double[this->MaxErrorsCapacity]; + } + + int i=0; + while(iMaxErrors[i]=0; + ++i; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Get the maximum error measured after the fixed subdivision. +// \pre errors_exists: errors!=0 +// \pre valid_size: sizeof(errors)==GetErrorMetrics()->GetNumberOfItems() +void vtkGenericCellTessellator::GetMaxErrors(double *errors) +{ + assert("pre: errors_exists" && errors!=0); + + int c=this->ErrorMetrics->GetNumberOfItems(); + int i=0; + while(iMaxErrors[i]; + ++i; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Send the current cell to error metrics. Should be called at the beginning +// of the implementation of Tessellate(), Triangulate() +// or TessellateTriangleFace() +// \pre cell_exists: cell!=0 +void vtkGenericCellTessellator::SetGenericCell(vtkGenericAdaptorCell *cell) +{ + assert("pre: cell_exists" && cell!=0); + + this->ErrorMetrics->InitTraversal(); + vtkGenericSubdivisionErrorMetric *e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + + while(e!=0) + { + e->SetGenericCell(cell); + e=static_cast(this->ErrorMetrics->GetNextItemAsObject()); + } +} diff --git a/Filtering/vtkGenericCellTessellator.h b/Filtering/vtkGenericCellTessellator.h new file mode 100644 index 0000000..23f9f63 --- /dev/null +++ b/Filtering/vtkGenericCellTessellator.h @@ -0,0 +1,203 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCellTessellator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericCellTessellator - helper class to perform cell tessellation +// .SECTION Description +// vtkGenericCellTessellator is a helper class to perform adaptive tessellation +// of particular cell topologies. The major purpose for this class is to +// transform higher-order cell types (e.g., higher-order finite elements) +// into linear cells that can then be easily visualized by VTK. This class +// works in conjunction with the vtkGenericDataSet and vtkGenericAdaptorCell +// classes. +// +// This algorithm is based on edge subdivision. An error metric along each +// edge is evaluated, and if the error is greater than some tolerance, the +// edge is subdivided (as well as all connected 2D and 3D cells). The process +// repeats until the error metric is satisfied. +// +// A significant issue addressed by this algorithm is to insure face +// compatibility across neigboring cells. That is, diagaonals due to face +// triangulation must match to insure that the mesh is compatible. The +// algorithm employs a precomputed table to accelerate the tessellation +// process. The table was generated with the help of vtkOrderedTriangulator; +// the basic idea is that the choice of diagonal is made by considering the +// relative value of the point ids. + + +#ifndef __vtkGenericCellTessellator_h +#define __vtkGenericCellTessellator_h + +#include "vtkObject.h" + +class vtkCellArray; +class vtkDoubleArray; +class vtkCollection; +class vtkGenericAttributeCollection; +class vtkGenericAdaptorCell; +class vtkGenericCellIterator; +class vtkPointData; +class vtkGenericDataSet; + +//----------------------------------------------------------------------------- +// +// The tessellation object +class VTK_FILTERING_EXPORT vtkGenericCellTessellator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkGenericCellTessellator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Tessellate a face of a 3D `cell'. The face is specified by the + // index value. + // The result is a set of smaller linear triangles in `cellArray' with + // `points' and point data `internalPd'. + // \pre cell_exists: cell!=0 + // \pre valid_dimension: cell->GetDimension()==3 + // \pre valid_index_range: (index>=0) && (indexGetNumberOfBoundaries(2)) + // \pre att_exists: att!=0 + // \pre points_exists: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + virtual void TessellateFace(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkIdType index, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd)=0; + + // Description: + // Tessellate a 3D `cell'. The result is a set of smaller linear + // tetrahedra in `cellArray' with `points' and point data `internalPd'. + // \pre cell_exists: cell!=0 + // \pre valid_dimension: cell->GetDimension()==3 + // \pre att_exists: att!=0 + // \pre points_exists: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + virtual void Tessellate(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd )=0; + + // Description: + // Triangulate a 2D `cell'. The result is a set of smaller linear triangles + // in `cellArray' with `points' and point data `internalPd'. + // \pre cell_exists: cell!=0 + // \pre valid_dimension: cell->GetDimension()==2 + // \pre att_exists: att!=0 + // \pre points_exists: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + virtual void Triangulate(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd)=0; + + // Description: + // Specify the list of error metrics used to decide if an edge has to be + // splitted or not. It is a collection of vtkGenericSubdivisionErrorMetric-s. + virtual void SetErrorMetrics(vtkCollection *someErrorMetrics); + vtkGetObjectMacro(ErrorMetrics,vtkCollection); + + // Description: + // Initialize the tessellator with a data set `ds'. + virtual void Initialize(vtkGenericDataSet *ds)=0; + + // Description: + // Init the error metric with the dataset. Should be called in each filter + // before any tessellation of any cell. + void InitErrorMetrics(vtkGenericDataSet *ds); + + // Description: + // If true, measure the quality of the fixed subdivision. + int GetMeasurement(); + void SetMeasurement(int flag); + + // Description: + // Get the maximum error measured after the fixed subdivision. + // \pre errors_exists: errors!=0 + // \pre valid_size: sizeof(errors)==GetErrorMetrics()->GetNumberOfItems() + void GetMaxErrors(double *errors); + +protected: + vtkGenericCellTessellator(); + ~vtkGenericCellTessellator(); + + // Description: + // Does the edge need to be subdivided according to at least one error + // metric? The edge is defined by its `leftPoint' and its `rightPoint'. + // `leftPoint', `midPoint' and `rightPoint' have to be initialized before + // calling RequiresEdgeSubdivision(). + // Their format is global coordinates, parametric coordinates and + // point centered attributes: xyx rst abc de... + // `alpha' is the normalized abscissa of the midpoint along the edge. + // (close to 0 means close to the left point, close to 1 means close to the + // right point) + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + int RequiresEdgeSubdivision(double *left, double *mid, double *right, + double alpha); + + + // Description: + // Update the max error of each error metric according to the error at the + // mid-point. The type of error depends on the state + // of the concrete error metric. For instance, it can return an absolute + // or relative error metric. + // See RequiresEdgeSubdivision() for a description of the arguments. + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + virtual void UpdateMaxError(double *leftPoint, double *midPoint, + double *rightPoint, double alpha); + + // Description: + // Reset the maximal error of each error metric. The purpose of the maximal + // error is to measure the quality of a fixed subdivision. + void ResetMaxErrors(); + + // Description: + // List of error metrics. Collection of vtkGenericSubdivisionErrorMetric + vtkCollection *ErrorMetrics; + + // Description: + // Send the current cell to error metrics. Should be called at the beginning + // of the implementation of Tessellate(), Triangulate() + // or TessellateTriangleFace() + // \pre cell_exists: cell!=0 + void SetGenericCell(vtkGenericAdaptorCell *cell); + + vtkGenericDataSet *DataSet; + + int Measurement; // if true, measure the quality of the fixed subdivision. + double *MaxErrors; // max error for each error metric, for measuring the + // quality of a fixed subdivision. + int MaxErrorsCapacity; + +private: + vtkGenericCellTessellator(const vtkGenericCellTessellator&); // Not implemented. + void operator=(const vtkGenericCellTessellator&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericDataSet.cxx b/Filtering/vtkGenericDataSet.cxx new file mode 100644 index 0000000..0090637 --- /dev/null +++ b/Filtering/vtkGenericDataSet.cxx @@ -0,0 +1,214 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericDataSet.h" + +#include "vtkCellTypes.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericCellTessellator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" + +#include + +vtkCxxRevisionMacro(vtkGenericDataSet, "$Revision: 1.5.12.1 $"); +vtkCxxSetObjectMacro(vtkGenericDataSet, Tessellator,vtkGenericCellTessellator); + +//---------------------------------------------------------------------------- +vtkGenericDataSet::vtkGenericDataSet() +{ + this->Tessellator = 0; + this->Attributes = vtkGenericAttributeCollection::New(); + vtkMath::UninitializeBounds(this->Bounds); +} + +//---------------------------------------------------------------------------- +vtkGenericDataSet::~vtkGenericDataSet() +{ + if(this->Tessellator!=0) + { + this->Tessellator->Delete(); + } + this->Attributes->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n"; + os << indent << "Number Of Cells: " << this->GetNumberOfCells() << "\n"; + + os << indent << "Attributes:\n"; + this->GetAttributes()->PrintSelf(os,indent.GetNextIndent()); + + this->ComputeBounds(); + os << indent << "Bounds: \n"; + os << indent << " Xmin,Xmax: (" <Bounds[0] << ", " << this->Bounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" <Bounds[2] << ", " << this->Bounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" <Bounds[4] << ", " << this->Bounds[5] << ")\n"; + + os << indent << "Tessellator:" << this->Tessellator << endl; +} + +//---------------------------------------------------------------------------- +// Description: +// Get a list of types of cells in a dataset. The list consists of an array +// of types (not necessarily in any order), with a single entry per type. +// For example a dataset 5 triangles, 3 lines, and 100 hexahedra would +// result a list of three entries, corresponding to the types VTK_TRIANGLE, +// VTK_LINE, and VTK_HEXAHEDRON. +// THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND +// THE DATASET IS NOT MODIFIED +// \pre types_exist: types!=0 +void vtkGenericDataSet::GetCellTypes(vtkCellTypes *types) +{ + assert("pre: types_exist" && types!=0); + + unsigned char type; + vtkGenericCellIterator *it=this->NewCellIterator(-1); + vtkGenericAdaptorCell *c=it->NewCell(); + + types->Reset(); + it->Begin(); + while(!it->IsAtEnd()) + { + it->GetCell(c); + type=c->GetType(); + if ( ! types->IsType(type) ) + { + types->InsertNextType(type); + } + it->Next(); + } + c->Delete(); + it->Delete(); +} + +//---------------------------------------------------------------------------- +// Return a pointer to the geometry bounding box in the form +// (xmin,xmax, ymin,ymax, zmin,zmax). +// The return value is VOLATILE. +// \post result_exists: result!=0 +double *vtkGenericDataSet::GetBounds() +{ + this->ComputeBounds(); + return this->Bounds; +} + +//---------------------------------------------------------------------------- + // Description: +// Return the geometry bounding box in global coordinates in +// the form (xmin,xmax, ymin,ymax, zmin,zmax) into `bounds'. +void vtkGenericDataSet::GetBounds(double bounds[6]) +{ + this->ComputeBounds(); + memcpy(bounds,this->Bounds,sizeof(double)*6); +} + +//---------------------------------------------------------------------------- +// Description: +// Get the center of the bounding box in global coordinates. +// The return value is VOLATILE. +// - \post result_exists: result!=0 +double *vtkGenericDataSet::GetCenter() +{ + this->ComputeBounds(); + for (int i=0; i<3; i++) + { + this->Center[i] = (this->Bounds[2*i+1] + this->Bounds[2*i]) * 0.5; + } + return this->Center; +} + +//---------------------------------------------------------------------------- +// Description: +// Get the center of the bounding box in global coordinates. +void vtkGenericDataSet::GetCenter(double center[3]) +{ + this->ComputeBounds(); + for (int i=0; i<3; i++) + { + center[i] = (this->Bounds[2*i+1] + this->Bounds[2*i]) * 0.5; + } +} + +//---------------------------------------------------------------------------- +// Description: +// Length of the diagonal of the bounding box. +double vtkGenericDataSet::GetLength() +{ + double result, l=0.0; + int i; + + this->ComputeBounds(); + for (i=0; i<3; i++) + { + result = this->Bounds[2*i+1] - this->Bounds[2*i]; + l += result * result; + } + result = sqrt(l); + assert("post: positive_result" && result>=0); + return result; +} + +//---------------------------------------------------------------------------- +unsigned long int vtkGenericDataSet::GetMTime() +{ + unsigned long result; + unsigned long mtime; + + result = vtkDataObject::GetMTime(); + + mtime = this->Attributes->GetMTime(); + result = ( mtime > result ? mtime : result ); + + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Actual size of the data in kilobytes; only valid after the pipeline has +// updated. It is guaranteed to be greater than or equal to the memory +// required to represent the data. +unsigned long vtkGenericDataSet::GetActualMemorySize() +{ + unsigned long result=this->vtkDataObject::GetActualMemorySize(); + result += this->Attributes->GetActualMemorySize(); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Return the type of data object. +int vtkGenericDataSet::GetDataObjectType() +{ + return VTK_GENERIC_DATA_SET; +} + +//---------------------------------------------------------------------------- +vtkGenericDataSet* vtkGenericDataSet::GetData(vtkInformation* info) +{ + return info? vtkGenericDataSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkGenericDataSet* vtkGenericDataSet::GetData(vtkInformationVector* v, int i) +{ + return vtkGenericDataSet::GetData(v->GetInformationObject(i)); +} diff --git a/Filtering/vtkGenericDataSet.h b/Filtering/vtkGenericDataSet.h new file mode 100644 index 0000000..805be90 --- /dev/null +++ b/Filtering/vtkGenericDataSet.h @@ -0,0 +1,250 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericDataSet - defines dataset interface +// .SECTION Description +// In VTK, spatial-temporal data is defined in terms of a dataset. The +// dataset consists of geometry (e.g., points), topology (e.g., cells), and +// attributes (e.g., scalars, vectors, etc.) vtkGenericDataSet is an abstract +// class defining this abstraction. +// +// Since vtkGenericDataSet provides a general interface to manipulate data, +// algorithms that process it tend to be slower than those specialized for a +// particular data type. For this reason, there are concrete, non-abstract +// subclasses that represent and provide access to data more efficiently. +// Note that filters to process this dataset type are currently found in the +// VTK/GenericFiltering/ subdirectory. +// +// Unlike the vtkDataSet class, vtkGenericDataSet provides a more flexible +// interface including support for iterators. vtkGenericDataSet is also +// designed to interface VTK to external simulation packages without the +// penalty of copying memory (see VTK/GenericFiltering/README.html) for +// more information. Thus vtkGenericDataSet plays a central role in the +// adaptor framework. +// +// Please note that this class introduces the concepts of "boundary cells". +// This refers to the boundaries of a cell (e.g., face of a tetrahedron) +// which may in turn be represented as a cell. Boundary cells are derivative +// topological features of cells, and are therefore never explicitly +// represented in the dataset. Often in visualization algorithms, looping +// over boundaries (edges or faces) is employed, while the actual dataset +// cells may not traversed. Thus there are methods to loop over these +// boundary cells. +// +// Finally, as a point of clarification, points are not the same as vertices. +// Vertices refer to points, and points specify a position is space. Vertices +// are a type of 0-D cell. Also, the concept of a DOFNode, which is where +// coefficients for higher-order cells are kept, is a new concept introduced +// by the adaptor framework (see vtkGenericAdaptorCell for more information). +// +// .SECTION See Also +// vtkGenericAdaptorCell vtkDataSet + +#ifndef __vtkGenericDataSet_h +#define __vtkGenericDataSet_h + +#include "vtkDataObject.h" + +class vtkCellTypes; +class vtkGenericCellIterator; +class vtkGenericAttributeCollection; +class vtkGenericCellTessellator; +class vtkGenericPointIterator; +class vtkRenderer; + +class VTK_FILTERING_EXPORT vtkGenericDataSet : public vtkDataObject +{ +public: + // Description: + // Standard VTK type and print macros. + vtkTypeRevisionMacro(vtkGenericDataSet,vtkDataObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the number of points composing the dataset. See NewPointIterator() + // for more details. + // \post positive_result: result>=0 + virtual vtkIdType GetNumberOfPoints() = 0; + + // Description: + // Return the number of cells that explicitly define the dataset. See + // NewCellIterator() for more details. + // \pre valid_dim_range: (dim>=-1) && (dim<=3) + // \post positive_result: result>=0 + virtual vtkIdType GetNumberOfCells(int dim=-1) = 0; + + // Description: + // Return -1 if the dataset is explicitly defined by cells of varying + // dimensions or if there are no cells. If the dataset is explicitly + // defined by cells of a unique dimension, return this dimension. + // \post valid_range: (result>=-1) && (result<=3) + virtual int GetCellDimension() = 0; + + // Description: + // Get a list of types of cells in a dataset. The list consists of an array + // of types (not necessarily in any order), with a single entry per type. + // For example a dataset 5 triangles, 3 lines, and 100 hexahedra would + // result a list of three entries, corresponding to the types VTK_TRIANGLE, + // VTK_LINE, and VTK_HEXAHEDRON. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + // \pre types_exist: types!=0 + virtual void GetCellTypes(vtkCellTypes *types); + + // Description: + // Return an iterator to traverse cells of dimension `dim' (or all + // dimensions if -1) that explicitly define the dataset. For instance, it + // will return only tetrahedra if the mesh is defined by tetrahedra. If the + // mesh is composed of two parts, one with tetrahedra and another part with + // triangles, it will return both, but will not return the boundary edges + // and vertices of these cells. The user is responsible for deleting the + // iterator. + // \pre valid_dim_range: (dim>=-1) && (dim<=3) + // \post result_exists: result!=0 + virtual vtkGenericCellIterator *NewCellIterator(int dim=-1) = 0; + + // Description: + // Return an iterator to traverse cell boundaries of dimension `dim' (or + // all dimensions if -1) of the dataset. If `exteriorOnly' is true, only + // the exterior cell boundaries of the dataset will be returned, otherwise + // it will return exterior and interior cell boundaries. The user is + // responsible for deleting the iterator. + // \pre valid_dim_range: (dim>=-1) && (dim<=2) + // \post result_exists: result!=0 + virtual vtkGenericCellIterator *NewBoundaryIterator(int dim=-1, + int exteriorOnly=0) = 0; + + // Description: + // Return an iterator to traverse the points composing the dataset; they + // can be points that define a cell or isolated. The user is responsible + // for deleting the iterator. + // \post result_exists: result!=0 + virtual vtkGenericPointIterator *NewPointIterator()=0; + + // Description: + // Locate the closest cell to position `x' (global coordinates) with + // respect to a tolerance squared `tol2' and an initial guess `cell' (if + // valid). The result consists in the `cell', the `subId' of the sub-cell + // (0 if primary cell), the parametric coordinates `pcoord' of the + // position. It returns whether the position is inside the cell or + // not (boolean). Tolerance is used to control how close the point is to be + // considered "in" the cell. + // THIS METHOD IS NOT THREAD SAFE. + // \pre not_empty: GetNumberOfCells()>0 + // \pre cell_exists: cell!=0 + // \pre positive_tolerance: tol2>0 + virtual int FindCell(double x[3], + vtkGenericCellIterator* &cell, + double tol2, + int &subId, + double pcoords[3]) = 0; + + // Description: + // Locate the closest point `p' to position `x' (global coordinates). + // \pre not_empty: GetNumberOfPoints()>0 + // \pre p_exists: p!=0 + virtual void FindPoint(double x[3], + vtkGenericPointIterator *p)=0; + + // Description: + // Datasets are composite objects and need to check each part for their + // modified time. + virtual unsigned long int GetMTime(); + + // Description: + // Compute the geometry bounding box. + virtual void ComputeBounds()=0; + + // Description: + // Return a pointer to the geometry bounding box in the form + // (xmin,xmax, ymin,ymax, zmin,zmax). + // The return value is VOLATILE. + // \post result_exists: result!=0 + virtual double *GetBounds(); + + // Description: + // Return the geometry bounding box in global coordinates in + // the form (xmin,xmax, ymin,ymax, zmin,zmax) in the `bounds' array. + virtual void GetBounds(double bounds[6]); + + // Description: + // Get the center of the bounding box in global coordinates. + // The return value is VOLATILE. + // \post result_exists: result!=0 + virtual double *GetCenter(); + + // Description: + // Get the center of the bounding box in global coordinates. + virtual void GetCenter(double center[3]); + + // Description: + // Return the length of the diagonal of the bounding box. + // \post positive_result: result>=0 + virtual double GetLength(); + + // Description: + // Get the collection of attributes associated with this dataset. + vtkGetObjectMacro(Attributes, vtkGenericAttributeCollection); + + // Description: + // Set/Get a cell tessellator if cells must be tessellated during + // processing. + // \pre tessellator_exists: tessellator!=0 + virtual void SetTessellator(vtkGenericCellTessellator *tessellator); + vtkGetObjectMacro(Tessellator,vtkGenericCellTessellator); + + // Description: + // Actual size of the data in kilobytes; only valid after the pipeline has + // updated. It is guaranteed to be greater than or equal to the memory + // required to represent the data. + virtual unsigned long GetActualMemorySize(); + + // Description: + // Return the type of data object. + int GetDataObjectType(); + + // Description: + // Estimated size needed after tessellation (or special operation) + virtual vtkIdType GetEstimatedSize() = 0; + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkGenericDataSet* GetData(vtkInformation* info); + static vtkGenericDataSet* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + // Description: + // Constructor with uninitialized bounds (1,-1, 1,-1, 1,-1), + // empty attribute collection and default tessellator. + vtkGenericDataSet(); + + virtual ~vtkGenericDataSet(); + + vtkGenericAttributeCollection *Attributes; + + //Main helper class to tesselate a higher order cell into linear ones. + vtkGenericCellTessellator *Tessellator; + + double Bounds[6]; // (xmin,xmax, ymin,ymax, zmin,zmax) geometric bounds + double Center[3]; // Center of the geometric bounding box + vtkTimeStamp ComputeTime; // Time at which bounds, center, etc. computed + +private: + vtkGenericDataSet(const vtkGenericDataSet&); // Not implemented. + void operator=(const vtkGenericDataSet&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericDataSetAlgorithm.cxx b/Filtering/vtkGenericDataSetAlgorithm.cxx new file mode 100644 index 0000000..b427716 --- /dev/null +++ b/Filtering/vtkGenericDataSetAlgorithm.cxx @@ -0,0 +1,250 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericDataSetAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericDataSetAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkGenericDataSet.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkGenericDataSetAlgorithm, "$Revision: 1.2 $"); + +//---------------------------------------------------------------------------- +vtkGenericDataSetAlgorithm::vtkGenericDataSetAlgorithm() +{ + // by default assume filters have one input and one output + // subclasses that deviate should modify this setting + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkGenericDataSetAlgorithm::~vtkGenericDataSetAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkGenericDataSet* vtkGenericDataSetAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkGenericDataSet* vtkGenericDataSetAlgorithm::GetOutput(int port) +{ + return vtkGenericDataSet::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkGenericDataSetAlgorithm::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkGenericDataSetAlgorithm::GetInput(int port) +{ + if (this->GetNumberOfInputConnections(port) < 1) + { + return 0; + } + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +vtkGenericDataSet* vtkGenericDataSetAlgorithm::GetGenericDataSetInput(int port) +{ + return vtkGenericDataSet::SafeDownCast(this->GetInput(port)); +} + +//---------------------------------------------------------------------------- +int vtkGenericDataSetAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + return this->RequestDataObject(request, inputVector, outputVector); + } + + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkGenericDataSetAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkGenericDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericDataSetAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericDataSetAlgorithm::RequestInformation( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* vtkNotUsed(outputVector)) +{ + // do nothing let subclasses handle it + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericDataSetAlgorithm::RequestUpdateExtent( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed(outputVector)) +{ + int numInputPorts = this->GetNumberOfInputPorts(); + for (int i=0; iGetNumberOfInputConnections(i); + for (int j=0; jGetInformationObject(j); + inputInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + } + } + return 1; +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkGenericDataSetAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + return 1; +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkGenericDataSetAlgorithm::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (output && this->UpdateExtentIsEmpty(output)) + { + output->Initialize(); + return; + } + + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + + +//---------------------------------------------------------------------------- +void vtkGenericDataSetAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} diff --git a/Filtering/vtkGenericDataSetAlgorithm.h b/Filtering/vtkGenericDataSetAlgorithm.h new file mode 100644 index 0000000..25588f6 --- /dev/null +++ b/Filtering/vtkGenericDataSetAlgorithm.h @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericDataSetAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericDataSetAlgorithm - Objects that generate adapted data sets +// .SECTION Description + +// vtkGenericDataSetAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// constructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be GenericDataSet. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// ExecuteData and ExecuteInformation. For new algorithms you should +// implement RequestData( request, inputVec, outputVec) but for older filters +// there is a default implementation that calls the old ExecuteData(output) +// signature, for even older filters that don;t implement ExecuteData the +// default implementation calls the even older Execute() signature. + +#ifndef __vtkGenericDataSetAlgorithm_h +#define __vtkGenericDataSetAlgorithm_h + +#include "vtkAlgorithm.h" +#include "vtkGenericDataSet.h" // makes things a bit easier + +class vtkDataSet; +class vtkGenericDataSet; + +class VTK_FILTERING_EXPORT vtkGenericDataSetAlgorithm : public vtkAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGenericDataSetAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkGenericDataSet* GetOutput(); + vtkGenericDataSet* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject* GetInput(); + vtkDataObject *GetInput(int port); + vtkGenericDataSet *GetGenericDataSetInput(int port); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(int, vtkDataObject*); + +protected: + vtkGenericDataSetAlgorithm(); + ~vtkGenericDataSetAlgorithm(); + + // convenience method + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + // See ProcessRequest for details about arguments and return value. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + // See ProcessRequest for details about arguments and return value. + virtual int RequestDataObject(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector)=0; + + // Description: + // This is called by the superclass. + // This is the method you should override. + // See ProcessRequest for details about arguments and return value. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkGenericDataSetAlgorithm(const vtkGenericDataSetAlgorithm&); // Not implemented. + void operator=(const vtkGenericDataSetAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericEdgeTable.cxx b/Filtering/vtkGenericEdgeTable.cxx new file mode 100644 index 0000000..7dfbd20 --- /dev/null +++ b/Filtering/vtkGenericEdgeTable.cxx @@ -0,0 +1,790 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericEdgeTable.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericEdgeTable.h" +#include "vtkObjectFactory.h" + +#include +#include + +vtkCxxRevisionMacro(vtkGenericEdgeTable, "$Revision: 1.10.10.1 $"); +vtkStandardNewMacro(vtkGenericEdgeTable); + +static int PRIME_NUMBERS[] = {1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, + 2039, 4093}; + +// Description: +// Constructor with a scalar field of `size' doubles. +// \pre positive_number_of_components: size>0 +vtkGenericEdgeTable::PointEntry::PointEntry(int size) +{ + assert("pre: positive_number_of_components" && size>0); + this->Reference = -10; + + this->Coord[0] = -100; + this->Coord[1] = -100; + this->Coord[2] = -100; + this->Scalar = new double[size]; + this->numberOfComponents = size; +} + +class vtkEdgeTablePoints +{ +public: + typedef vtkstd::vector VectorPointTableType; + typedef vtkstd::vector PointTableType; + + void Resize(vtkIdType size); + void LoadFactor(); + void DumpPoints(); + + PointTableType PointVector; + vtkIdType Modulo; +}; + +//----------------------------------------------------------------------------- +void vtkEdgeTablePoints::Resize(vtkIdType newSize) +{ + vtkIdType size = PointVector.size(); + + if( size <= newSize ) + { + PointVector.resize(newSize); + int index = (int)(log((double)newSize)/log(2.)); + this->Modulo = PRIME_NUMBERS[index]; + //cout << "this->Modulo:" << newSize << "," << index << "," + // << this->Modulo << endl; + } + + assert((unsigned)size < PointVector.size() ); // valid size + // For now you are not supposed to use this method + assert( 0 ); +} + +//----------------------------------------------------------------------------- +void vtkEdgeTablePoints::LoadFactor() +{ + vtkIdType numEntries = 0; + vtkIdType numBins = 0; + + vtkIdType size = PointVector.size(); + cerr << "EdgeTablePoints:\n"; + for(int i=0; iPointId << " " << it->Reference << ":(" << + it->Coord[0] << "," << it->Coord[1] << "," << it->Coord[2] << ")" + << endl; + } + } +} + +//----------------------------------------------------------------------------- +class vtkEdgeTableEdge +{ +public: + typedef vtkstd::vector VectorEdgeTableType; + typedef vtkstd::vector EdgeTableType; + + void Resize(vtkIdType size); + void LoadFactor(); + void DumpEdges(); + + EdgeTableType Vector; + vtkIdType Modulo; +}; + +//----------------------------------------------------------------------------- +void vtkEdgeTableEdge::Resize(vtkIdType newSize) +{ + vtkIdType size = Vector.size(); + + if( size <= newSize ) + { + Vector.resize(newSize); + int index = (int)(log((double)newSize)/log(2.)); + this->Modulo = PRIME_NUMBERS[index]; + cout << "this->Modulo:" << index << ":" << this->Modulo << endl; + } + + // For now you are not supposed to use this method + assert(0); +} + +//----------------------------------------------------------------------------- +void vtkEdgeTableEdge::LoadFactor() +{ + vtkIdType numEntry = 0; + vtkIdType numBins = 0; + + vtkIdType size = Vector.size(); + cerr << "EdgeTableEdge:\n"; + for(int i=0; iE1 << "," << it->E2 << ") " << + it->Reference << "," << it->ToSplit << "," << it->PtId << endl; + } + } +} + +//----------------------------------------------------------------------------- +static inline void OrderEdge(vtkIdType &e1, vtkIdType &e2) +{ + vtkIdType temp1 = e1; + vtkIdType temp2 = e2; + e1 = temp1 < temp2 ? temp1 : temp2; + e2 = temp1 > temp2 ? temp1 : temp2; +} + +//----------------------------------------------------------------------------- +// Instantiate object based on maximum point id. +vtkGenericEdgeTable::vtkGenericEdgeTable() +{ + this->EdgeTable = new vtkEdgeTableEdge; + this->HashPoints = new vtkEdgeTablePoints; + + // Default to only one component + this->NumberOfComponents = 1; + + // The whole problem is here to find the proper size for a descent hash table + // Since we do not allow check our size as we go the hash table + // Should be big enough from the begining otherwise we'll loose the + // constant time access + // But on the other hand we do not want it to be too big for mem consumption + // A compromise of 4093 was found fo be working in a lot of case +#if 1 + this->EdgeTable->Vector.resize(4093); + this->EdgeTable->Modulo = 4093; + this->HashPoints->PointVector.resize(4093); //127 + this->HashPoints->Modulo = 4093; +#else + this->EdgeTable->Vector.resize(509); + this->EdgeTable->Modulo = 509; + this->HashPoints->PointVector.resize(127); + this->HashPoints->Modulo = 127; +#endif + + this->LastPointId = 0; +} + +//----------------------------------------------------------------------------- +vtkGenericEdgeTable::~vtkGenericEdgeTable() +{ + delete this->EdgeTable; + delete this->HashPoints; +} + +//----------------------------------------------------------------------------- +// We assume the edge is not being split: +void vtkGenericEdgeTable::InsertEdge(vtkIdType e1, vtkIdType e2, + vtkIdType cellId, int ref ) +{ + vtkIdType ptId; + this->InsertEdge(e1, e2, cellId, ref, 0, ptId); +} + +//----------------------------------------------------------------------------- +// the edge is being split and we want the new ptId +void vtkGenericEdgeTable::InsertEdge(vtkIdType e1, vtkIdType e2, + vtkIdType cellId, int ref, + vtkIdType &ptId ) +{ + this->InsertEdge(e1, e2, cellId, ref, 1, ptId ); +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::InsertEdge(vtkIdType e1, vtkIdType e2, + vtkIdType cellId, int ref, int toSplit, + vtkIdType &ptId ) +{ + if( e1 == e2 ) + { + vtkErrorMacro( << "Not an edge:" << e1 << "," << e2 ); + } + assert("pre: not degenerated edge" && e1!=e2); + + //reorder so that e1 < e2; + OrderEdge(e1, e2); + + vtkIdType pos = this->HashFunction(e1, e2); + + //Be carefull with reference the equal is not overloaded + vtkEdgeTableEdge::VectorEdgeTableType &vect = this->EdgeTable->Vector[pos]; + + //Need to check size again + //Here we just puch_back at the end, + //the vector should not be very long and should not contain any empty spot. + EdgeEntry newEntry; + newEntry.E1 = e1; + newEntry.E2 = e2; + newEntry.Reference = ref; + newEntry.ToSplit = toSplit; + newEntry.CellId = cellId; + + if(newEntry.ToSplit) + { + newEntry.PtId = ptId = this->LastPointId++; + } + else + { + newEntry.PtId = ptId = -1; + } + +// vtkDebugMacro( << "Inserting Edge:" << e1 << "," << e2 << ": ref=" << +// newEntry.Reference << ", cellId=" << cellId << ", split=" << toSplit << +// ", ptId=" << newEntry.PtId ); + + vect.push_back( newEntry ); +} + +//----------------------------------------------------------------------------- +// Try to remove an edge, in fact decrement the ref count +int vtkGenericEdgeTable::RemoveEdge(vtkIdType e1, vtkIdType e2) +{ + int ref = 0; + //reorder so that e1 < e2; + OrderEdge(e1, e2); + + //vtkDebugMacro( << "RemoveEdge:" << e1 << "," << e2 ); + + vtkIdType pos = this->HashFunction(e1, e2); + assert("check: valid range po" && (unsigned)pos < this->EdgeTable->Vector.size() ); + + //Need to check size first + vtkEdgeTableEdge::VectorEdgeTableType &vect = this->EdgeTable->Vector[pos]; + + int found = 0; + + vtkEdgeTableEdge::VectorEdgeTableType::iterator it; + for(it = vect.begin(); it != vect.end(); ) + { + if( it->E1 == e1 && it->E2 == e2 ) + { + if( --it->Reference == 0 ) + { + // Ok this edge is about to be physically removed, remove also the point + // is contained, if one: + if( it->ToSplit ) + { + assert("check: positive id" && it->PtId >= 0 ); + + this->RemovePoint( it->PtId ); + } + } + found = 1; + ref = it->Reference; + } + + if( it->E1 == e1 && it->E2 == e2 && it->Reference == 0 ) + { + it = vect.erase( it ); + } + else + { + ++it; + } + } + + if( !found ) + { + //We did not find any corresponding entry to erase, warn user + vtkErrorMacro( << "No entry were found in the hash table for edge:" << e1 + << "," << e2 ); + assert("check: not found" && 0 ); + } + + return ref; +} + +//----------------------------------------------------------------------------- +int vtkGenericEdgeTable::CheckEdge(vtkIdType e1, vtkIdType e2, vtkIdType &ptId) +{ + //int index; + EdgeEntry ent; + //reorder so that e1 < e2; + OrderEdge(e1, e2); + + //vtkDebugMacro( << "Checking edge:" << e1 << "," << e2 ); + + vtkIdType pos = this->HashFunction(e1, e2); + + if( (unsigned)pos >= this->EdgeTable->Vector.size() ) + { + vtkDebugMacro( << "No entry were found in the hash table" ); + return -1; + } + + assert("check: valid range pos" && (unsigned)posEdgeTable->Vector.size() ); + //Need to check size first + vtkEdgeTableEdge::VectorEdgeTableType &vect = this->EdgeTable->Vector[pos]; + +#if USE_CONST_ITERATOR + vtkEdgeTableEdge::VectorEdgeTableType::const_iterator it; + for(it = vect.begin(); it != vect.end(); ++it) + { + if( (it->E1 == e1) && (it->E2 == e2)) + { + ptId = it->PtId; + break; + } + } + + if( it == vect.end()) + { + //We did not find any corresponding entry, warn user + vtkDebugMacro( << "No entry were found in the hash table" ); + return -1; + } + + return it->ToSplit; +#else + int vectsize = vect.size(); + int index; + for (index=0; indexHashFunction(e1, e2); + assert("check: valid range pos" && (unsigned)pos < this->EdgeTable->Vector.size()); + + //Need to check size first + vtkEdgeTableEdge::VectorEdgeTableType &vect = this->EdgeTable->Vector[pos]; + + int vectsize = vect.size(); + for (index=0; indexHashFunction(e1, e2); + assert("check: valid range pos" && (unsigned)pos < this->EdgeTable->Vector.size()); + + //Need to check size first + vtkEdgeTableEdge::VectorEdgeTableType &vect = this->EdgeTable->Vector[pos]; + + int vectsize = vect.size(); + for (index=0; index= 0 ); + return ent.Reference; + } + } + + //We did not find any corresponding entry, warn user + vtkErrorMacro( << "No entry were found in the hash table" ); + return -1; +} + +//----------------------------------------------------------------------------- +vtkIdType vtkGenericEdgeTable::HashFunction(vtkIdType e1, vtkIdType e2) +{ + return (e1 + e2) % this->EdgeTable->Modulo; +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::Initialize(vtkIdType start) +{ + if(this->LastPointId) + { + //if different from zero then raise problem: + vtkDebugMacro( << "You are not supposed to initialize during algorithm" ); + return; + } + + this->LastPointId = start; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the total number of components for the point-centered attributes. +// \post positive_result: result>0 +int vtkGenericEdgeTable::GetNumberOfComponents() +{ + return this->NumberOfComponents; +} + +//----------------------------------------------------------------------------- +// Description: +// Set the total number of components for the point-centered attributes. +void vtkGenericEdgeTable::SetNumberOfComponents(int count) +{ + assert("pre: positive_count" && count>0); + this->NumberOfComponents=count; +} + +//----------------------------------------------------------------------------- +vtkIdType vtkGenericEdgeTable::HashFunction(vtkIdType ptId) +{ + return ptId % this->HashPoints->Modulo; +} +//----------------------------------------------------------------------------- +// Check if point ptId exist in the hash table +int vtkGenericEdgeTable::CheckPoint(vtkIdType ptId) +{ + int index; + vtkIdType pos = this->HashFunction(ptId); + + if( (unsigned)pos >= this->HashPoints->PointVector.size() ) + { + return 0; + } + + assert("check: valid range pos" && + (unsigned)posHashPoints->PointVector.size() ); + + //Be carefull with reference the equal is not overloaded + vtkEdgeTablePoints::VectorPointTableType &vect = + this->HashPoints->PointVector[pos]; + + int vectsize = vect.size(); + for (index=0; indexHashFunction(ptId); + assert("check: valid range pos" && + (unsigned)pos < this->HashPoints->PointVector.size() ); + + // Be carefull with reference the equal is not overloaded + vtkEdgeTablePoints::VectorPointTableType &vect = + this->HashPoints->PointVector[pos]; + + //Need to check size again + + int vectsize = vect.size(); + for (index=0; indexNumberOfComponents); + return 1; + } + } + + if( index == vectsize ) + { + //We did not find any corresponding entry, warn user + vtkErrorMacro( << "No entry were found in the hash table:" << ptId ); + return 0; + } + + assert("check: TODO" && 0 ); + return 1; +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::InsertPoint(vtkIdType ptId, double point[3]) +{ + vtkIdType pos = this->HashFunction(ptId); + + //Need to check size first + //this->HashPoints->Resize( pos ); + assert("check: valid range pos" && + (unsigned)pos < this->HashPoints->PointVector.size() ); + + //Be carefull with reference the equal is not overloaded + vtkEdgeTablePoints::VectorPointTableType &vect = + this->HashPoints->PointVector[pos]; + + //Need to check size again + //Here we just puch_back at the end, + //the vector should not be very long and should not contain any empty spot. + PointEntry newEntry(this->NumberOfComponents); // = vect.back(); + newEntry.PointId = ptId; + memcpy(newEntry.Coord,point,sizeof(double)*3); + newEntry.Reference = 1; + +// vtkDebugMacro( << "Inserting Point:" << ptId << ":" +// << point[0] << "," << point[1] << "," << point[2] ); + vect.push_back( newEntry ); +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::RemovePoint(vtkIdType ptId) +{ + int found = 0; + vtkIdType pos = this->HashFunction(ptId); + + //Need to check size first + assert("check: valid range pos" && + (unsigned)pos < this->HashPoints->PointVector.size() ); + + //Be carefull with reference the equal is not overloaded + vtkEdgeTablePoints::VectorPointTableType &vect = + this->HashPoints->PointVector[pos]; + + //vtkDebugMacro( << "Remove Point:" << ptId << ":" << vect.size() ); + + vtkEdgeTablePoints::VectorPointTableType::iterator it; + for (it= vect.begin(); it!= vect.end(); ) + { + PointEntry &ent = *it; + + if( ent.PointId == ptId ) + { + --ent.Reference; + found = 1; + } + + if( ent.PointId == ptId && ent.Reference == 0 ) + { + it = vect.erase(it); + } + else + { + ++it; + } + } + + if( !found ) + { + //We did not find any corresponding entry, warn user + vtkErrorMacro( << "No entry were found in the hash table" ); + } +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::InsertPointAndScalar(vtkIdType ptId, double pt[3], + double *s) +{ + // sizeof(s)=this->NumberOfComponents + vtkIdType pos = this->HashFunction(ptId); + + //Need to check size first + //this->HashPoints->Resize( pos ); + if( !((unsigned)pos < this->HashPoints->PointVector.size() )) + { + int kk = 2; + kk++; + } + + //Be carefull with reference the equal is not overloaded + vtkEdgeTablePoints::VectorPointTableType &vect = this->HashPoints->PointVector[pos]; + + //Please keep the following: +#if 0 + //Need to check size again + //Here we just puch_back at the end, + //the vector should not be very long and should not contain any empty spot. + for (index=0; indexNumberOfComponents); // = vect.back(); + newEntry.PointId = ptId; + memcpy(newEntry.Coord,pt,sizeof(double)*3); + memcpy(newEntry.Scalar,s,sizeof(double)*this->NumberOfComponents); + newEntry.Reference = 1; + +// vtkDebugMacro( << "InsertPointAndScalar:" << ptId << ":" +// << pt[0] << "," << pt[1] << "," << pt[2] << "->" +// << s[0] << "," << s[1] << "," << s[2] ); + + vect.push_back( newEntry ); +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::DumpTable() +{ + this->EdgeTable->DumpEdges(); + this->HashPoints->DumpPoints(); +} + +//----------------------------------------------------------------------------- +void vtkGenericEdgeTable::IncrementPointReferenceCount(vtkIdType ptId ) +{ + unsigned int index; + int found = 0; + vtkIdType pos = this->HashFunction(ptId); + + //Need to check size first + assert("check: valid range pos" && + (unsigned)pos < this->HashPoints->PointVector.size() ); + + //Be carefull with reference the equal is not overloaded + vtkEdgeTablePoints::VectorPointTableType &vect = this->HashPoints->PointVector[pos]; + + //vtkDebugMacro(<< "IncrementPointReferenceCount:" << ptId << ":" << vect.size() ); + + for (index=0; indexEdgeTable->LoadFactor(); + this->HashPoints->LoadFactor(); +} diff --git a/Filtering/vtkGenericEdgeTable.h b/Filtering/vtkGenericEdgeTable.h new file mode 100644 index 0000000..0b92990 --- /dev/null +++ b/Filtering/vtkGenericEdgeTable.h @@ -0,0 +1,256 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericEdgeTable.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericEdgeTable - keep track of edges (defined by pair of integer id's) +// .SECTION Description +// vtkGenericEdgeTable is used to indicate the existance of and hold +// information about edges. Similar to vtkEdgeTable, this class is +// more sophisticated in that it uses reference counting to keep track +// of when information about an edge should be deleted. +// +// vtkGenericEdgeTable is a helper class used in the adaptor framework. It +// is used during the tessellation process to hold information about the +// error metric on each edge. This avoids recomputing the error metric each +// time the same edge is visited. + +#ifndef __vtkGenericEdgeTable_h +#define __vtkGenericEdgeTable_h + +#include "vtkObject.h" + +class vtkEdgeTableEdge; +class vtkEdgeTablePoints; + +class VTK_FILTERING_EXPORT vtkGenericEdgeTable : public vtkObject +{ +public: + // Description: + // Instantiate an empty edge table. + static vtkGenericEdgeTable *New(); + + // Description: + // Standard VTK type and print macros. + vtkTypeRevisionMacro(vtkGenericEdgeTable,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Split the edge with the indicated point id. + void InsertEdge(vtkIdType e1, vtkIdType e2, vtkIdType cellId, + int ref, vtkIdType &ptId ); + + // Description: + // Insert an edge but do not split it. + void InsertEdge(vtkIdType e1, vtkIdType e2, vtkIdType cellId, int ref = 1 ); + + // Description: + // Method to remove an edge from the table. The method returns the + // current reference count. + int RemoveEdge(vtkIdType e1, vtkIdType e2); + + // Description: + // Method to determine whether an edge is in the table (0 or 1), or not (-1). + // It returns whether the edge was split (1) or not (0), + // and the point id exists. + int CheckEdge(vtkIdType e1, vtkIdType e2, vtkIdType &ptId); + + // Description: + // Method that increments the referencecount and returns it. + int IncrementEdgeReferenceCount(vtkIdType e1, vtkIdType e2, + vtkIdType cellId); + + // Description: + // Return the edge reference count. + int CheckEdgeReferenceCount(vtkIdType e1, vtkIdType e2); + + // Description: + // To specify the starting point id. It will initialize LastPointId + // This is very sensitive the start point should be cautiously chosen + void Initialize(vtkIdType start); + + // Description: + // Return the total number of components for the point-centered attributes. + // \post positive_result: result>0 + int GetNumberOfComponents(); + + // Description: + // Set the total number of components for the point-centered attributes. + // \pre positive_count: count>0 + void SetNumberOfComponents(int count); + + // Description: + // Check if a point is already in the point table. + int CheckPoint(vtkIdType ptId); + + // Description: + // Check for the existence of a point and return its coordinate value. + // \pre scalar_size: sizeof(scalar)==this->GetNumberOfComponents() + int CheckPoint(vtkIdType ptId, double point[3], double *scalar); + + // Description: + // Insert point associated with an edge. + void InsertPoint(vtkIdType ptId, double point[3]); + // \pre: sizeof(s)==GetNumberOfComponents() + void InsertPointAndScalar(vtkIdType ptId, double pt[3], double *s); + + // Description: + // Remove a point from the point table. + void RemovePoint(vtkIdType ptId); + + // Description: + // Increment the reference count for the indicated point. + void IncrementPointReferenceCount(vtkIdType ptId ); + + // Description: + // For debugging purposes. It is particularly useful to dump the table + // and check that nothing is left after a complete iteration. LoadFactor + // should ideally be very low to be able to have a constant time access + void DumpTable(); + void LoadFactor(); + +//BTX +class PointEntry +{ +public: + vtkIdType PointId; + double Coord[3]; + double *Scalar; // point data: all point-centered attributes at this point + int numberOfComponents; + + int Reference; //signed char + + // Description: + // Constructor with a scalar field of `size' doubles. + // \pre positive_number_of_components: size>0 + PointEntry(int size); + + ~PointEntry() + { + delete[] this->Scalar; + } + + PointEntry(const PointEntry &other) + { + this->PointId = other.PointId; + + memcpy(this->Coord,other.Coord,sizeof(double)*3); + + int c = other.numberOfComponents; + this->numberOfComponents = c; + this->Scalar = new double[c]; + memcpy(this->Scalar, other.Scalar, sizeof(double)*c); + this->Reference = other.Reference; + } + + void operator=(const PointEntry &other) + { + if(this != &other) + { + this->PointId = other.PointId; + + memcpy(this->Coord, other.Coord, sizeof(double)*3); + + int c = other.numberOfComponents; + + if(this->numberOfComponents!=c) + { + delete[] this->Scalar; + this->Scalar = new double[c]; + this->numberOfComponents = c; + } + memcpy(this->Scalar, other.Scalar, sizeof(double)*c); + this->Reference = other.Reference; + } + } +}; + +class EdgeEntry +{ +public: + vtkIdType E1; + vtkIdType E2; + + int Reference; //signed char + int ToSplit; //signed char + vtkIdType PtId; + vtkIdType CellId; //CellId the edge refer to at a step in tesselation + + EdgeEntry() + { + this->Reference = 0; + this->CellId = -1; + } + ~EdgeEntry() {} + + EdgeEntry(const EdgeEntry& copy) + { + this->E1 = copy.E1; + this->E2 = copy.E2; + + this->Reference = copy.Reference; + this->ToSplit = copy.ToSplit; + this->PtId = copy.PtId; + this->CellId = copy.CellId; + } + + void operator=(const EdgeEntry& entry) + { + if(this == &entry) + { + return; + } + this->E1 = entry.E1; + this->E2 = entry.E2; + this->Reference = entry.Reference; + this->ToSplit = entry.ToSplit; + this->PtId = entry.PtId; + this->CellId = entry.CellId; + } +}; +//ETX + +protected: + vtkGenericEdgeTable(); + ~vtkGenericEdgeTable(); + + // Description: + // Split the edge with the indicated point id. + void InsertEdge(vtkIdType e1, vtkIdType e2, vtkIdType cellId, + int ref, int toSplit, vtkIdType &ptId ); + + //Hash table that contiain entry based on edges: + vtkEdgeTableEdge *EdgeTable; + + //At end of process we should be able to retrieve points coord based on pointid + vtkEdgeTablePoints *HashPoints; + + // Main hash functions + //For edge table: + vtkIdType HashFunction(vtkIdType e1, vtkIdType e2); + + //For point table: + vtkIdType HashFunction(vtkIdType ptId); + + // Keep track of the last point id we inserted, increment it each time: + vtkIdType LastPointId; + + vtkIdType NumberOfComponents; + +private: + vtkGenericEdgeTable(const vtkGenericEdgeTable&); // Not implemented. + void operator=(const vtkGenericEdgeTable&); // Not implemented. + +}; + +#endif + diff --git a/Filtering/vtkGenericInterpolatedVelocityField.cxx b/Filtering/vtkGenericInterpolatedVelocityField.cxx new file mode 100644 index 0000000..b92db8b --- /dev/null +++ b/Filtering/vtkGenericInterpolatedVelocityField.cxx @@ -0,0 +1,314 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericInterpolatedVelocityField.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericInterpolatedVelocityField.h" + +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericDataSet.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkObjectFactory.h" +#include "vtkDataSetAttributes.h" // for vtkDataSetAttributes::VECTORS + +#include + +vtkCxxRevisionMacro(vtkGenericInterpolatedVelocityField, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkGenericInterpolatedVelocityField); + +typedef vtkstd::vector< vtkGenericDataSet* > DataSetsTypeBase; +class vtkGenericInterpolatedVelocityFieldDataSetsType: public DataSetsTypeBase {}; + +vtkGenericInterpolatedVelocityField::vtkGenericInterpolatedVelocityField() +{ + this->NumFuncs = 3; // u, v, w + this->NumIndepVars = 4; // x, y, z, t + this->GenCell = 0; + this->CacheHit = 0; + this->CacheMiss = 0; + this->Caching = 1; // Caching on by default + + this->VectorsSelection = 0; + + this->DataSets = new vtkGenericInterpolatedVelocityFieldDataSetsType; + this->LastDataSet = 0; +} + +vtkGenericInterpolatedVelocityField::~vtkGenericInterpolatedVelocityField() +{ + this->NumFuncs = 0; + this->NumIndepVars = 0; + if(this->GenCell!=0) + { + this->GenCell->Delete(); + } + + this->SetVectorsSelection(0); + + delete this->DataSets; +} + +static int tmp_count=0; +// Evaluate u,v,w at x,y,z,t +int vtkGenericInterpolatedVelocityField::FunctionValues(double* x, double* f) +{ + vtkGenericDataSet* ds; + if(!this->LastDataSet && !this->DataSets->empty()) + { + ds = (*this->DataSets)[0]; + this->LastDataSet = ds; + } + else + { + ds = this->LastDataSet; + } + int retVal = this->FunctionValues(ds, x, f); + if (!retVal) + { + tmp_count = 0; + for(DataSetsTypeBase::iterator i = this->DataSets->begin(); + i != this->DataSets->end(); ++i) + { + ds = *i; + if(ds && ds != this->LastDataSet) + { + this->ClearLastCell(); + retVal = this->FunctionValues(ds, x, f); + if (retVal) + { + this->LastDataSet = ds; + return retVal; + } + } + } + this->ClearLastCell(); + return 0; + } + tmp_count++; + return retVal; +} + +const double vtkGenericInterpolatedVelocityField::TOLERANCE_SCALE = 1.0E-8; + +// Evaluate u,v,w at x,y,z,t +int vtkGenericInterpolatedVelocityField::FunctionValues( + vtkGenericDataSet* dataset, + double* x, + double* f) +{ + int i, subId; + vtkGenericAttribute *vectors=0; + double dist2; + int ret; + int attrib; + + for(i=0; i<3; i++) + { + f[i] = 0; + } + + // See if a dataset has been specified and if there are input vectors + int validState=dataset!=0; + if(validState) + { + if(this->VectorsSelection!=0) + { + attrib=dataset->GetAttributes()->FindAttribute(this->VectorsSelection); + validState=attrib>=0; + if(validState) + { + vectors=dataset->GetAttributes()->GetAttribute(attrib); + validState=(vectors->GetType()==vtkDataSetAttributes::VECTORS)||(vectors->GetCentering()==vtkPointCentered); + } + } + else + { + // Find the first attribute, point centered and with vector type. + attrib=0; + validState=0; + int c=dataset->GetAttributes()->GetNumberOfAttributes(); + while(attribGetAttributes()->GetAttribute(attrib)->GetType()==vtkDataSetAttributes::VECTORS)&&(dataset->GetAttributes()->GetAttribute(attrib)->GetCentering()==vtkPointCentered); + ++attrib; + } + if(validState) + { + vectors=dataset->GetAttributes()->GetAttribute(attrib-1); + } + } + } + + if (!validState) + { + vtkErrorMacro(<<"Can't evaluate dataset!"); + return 0; + } + + double tol2 = + dataset->GetLength() * vtkGenericInterpolatedVelocityField::TOLERANCE_SCALE; + + int found = 0; + + if (this->Caching) + { + // See if the point is in the cached cell + if (this->GenCell==0 || this->GenCell->IsAtEnd() || + !(ret=this->GenCell->GetCell()->EvaluatePosition(x, 0, subId, + this->LastPCoords, + dist2)) + || ret == -1) + { + // if not, find and get it + if (this->GenCell!=0 && !this->GenCell->IsAtEnd()) + { + this->CacheMiss++; + found=dataset->FindCell(x,this->GenCell,tol2,subId, + this->LastPCoords); + } + } + else + { + this->CacheHit++; + found = 1; + } + } + + if (!found) + { + // if the cell is not found, do a global search (ignore initial + // cell if there is one) + if(this->GenCell==0) + { + this->GenCell=dataset->NewCellIterator(); + } + found=dataset->FindCell(x,this->GenCell,tol2,subId,this->LastPCoords); + if(!found) + { + return 0; + } + } + + this->GenCell->GetCell()->InterpolateTuple(vectors,this->LastPCoords,f); + + return 1; +} + +//----------------------------------------------------------------------------- +void vtkGenericInterpolatedVelocityField::AddDataSet(vtkGenericDataSet* dataset) +{ + if (!dataset) + { + return; + } + + this->DataSets->push_back(dataset); +} + +//----------------------------------------------------------------------------- +// Description: +// Set the last cell id to -1 so that the next search does not +// start from the previous cell +void vtkGenericInterpolatedVelocityField::ClearLastCell() +{ + if(this->GenCell!=0) + { + if(!this->GenCell->IsAtEnd()) + { + this->GenCell->Next(); + } + } +} +//----------------------------------------------------------------------------- +// Description: +// Return the cell cached from last evaluation. +vtkGenericAdaptorCell *vtkGenericInterpolatedVelocityField::GetLastCell() +{ + vtkGenericAdaptorCell *result; + if(this->GenCell!=0 && !this->GenCell->IsAtEnd()) + { + result=this->GenCell->GetCell(); + } + else + { + result=0; + } + return result; +} + +//----------------------------------------------------------------------------- +int vtkGenericInterpolatedVelocityField::GetLastLocalCoordinates(double pcoords[3]) +{ + int j; + + // If last cell is valid, fill p with the local coordinates + // and return true + if (this->GenCell!=0 && !this->GenCell->IsAtEnd()) + { + for (j=0; j < 3; j++) + { + pcoords[j] = this->LastPCoords[j]; + } + return 1; + } + // otherwise, return false + else + { + return 0; + } +} + +void vtkGenericInterpolatedVelocityField::CopyParameters( + vtkGenericInterpolatedVelocityField* from) +{ + this->Caching = from->Caching; +} + +void vtkGenericInterpolatedVelocityField::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if ( this->VectorsSelection ) + { + os << indent << "VectorsSelection: " << this->VectorsSelection << endl; + } + else + { + os << indent << "VectorsSelection: (none)" << endl; + } + if ( this->GenCell ) + { + os << indent << "Last cell: " << this->GenCell << endl; + } + else + { + os << indent << "Last cell: (none)" << endl; + } + os << indent << "Cache hit: " << this->CacheHit << endl; + os << indent << "Cache miss: " << this->CacheMiss << endl; + os << indent << "Caching: "; + if ( this->Caching ) + { + os << "on." << endl; + } + else + { + os << "off." << endl; + } + + os << indent << "VectorsSelection: " + << (this->VectorsSelection?this->VectorsSelection:"(none)") << endl; + os << indent << "LastDataSet : " + << this->LastDataSet << endl; + +} diff --git a/Filtering/vtkGenericInterpolatedVelocityField.h b/Filtering/vtkGenericInterpolatedVelocityField.h new file mode 100644 index 0000000..42bcd80 --- /dev/null +++ b/Filtering/vtkGenericInterpolatedVelocityField.h @@ -0,0 +1,148 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericInterpolatedVelocityField.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericInterpolatedVelocityField - Interface for obtaining +// interpolated velocity values +// .SECTION Description +// vtkGenericInterpolatedVelocityField acts as a continuous velocity field +// by performing cell interpolation on the underlying vtkDataSet. +// This is a concrete sub-class of vtkFunctionSet with +// NumberOfIndependentVariables = 4 (x,y,z,t) and +// NumberOfFunctions = 3 (u,v,w). Normally, every time an evaluation +// is performed, the cell which contains the point (x,y,z) has to +// be found by calling FindCell. This is a computationally expansive +// operation. In certain cases, the cell search can be avoided or shortened +// by providing a guess for the cell iterator. For example, in streamline +// integration, the next evaluation is usually in the same or a neighbour +// cell. For this reason, vtkGenericInterpolatedVelocityField stores the last +// cell iterator. If caching is turned on, it uses this iterator as the +// starting point. + +// .SECTION Caveats +// vtkGenericInterpolatedVelocityField is not thread safe. A new instance +// should be created by each thread. + +// .SECTION See Also +// vtkFunctionSet vtkGenericStreamTracer + +#ifndef __vtkGenericInterpolatedVelocityField_h +#define __vtkGenericInterpolatedVelocityField_h + +#include "vtkFunctionSet.h" + +class vtkGenericDataSet; +class vtkGenericCellIterator; +class vtkGenericAdaptorCell; + +class vtkGenericInterpolatedVelocityFieldDataSetsType; + +class VTK_FILTERING_EXPORT vtkGenericInterpolatedVelocityField : public vtkFunctionSet +{ +public: + vtkTypeRevisionMacro(vtkGenericInterpolatedVelocityField,vtkFunctionSet); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a vtkGenericInterpolatedVelocityField with no initial data set. + // Caching is on. LastCellId is set to -1. + static vtkGenericInterpolatedVelocityField *New(); + + // Description: + // Evaluate the velocity field, f, at (x, y, z, t). + // For now, t is ignored. + virtual int FunctionValues(double* x, double* f); + + // Description: + // Add a dataset used for the implicit function evaluation. + // If more than one dataset is added, the evaluation point is + // searched in all until a match is found. THIS FUNCTION + // DOES NOT CHANGE THE REFERENCE COUNT OF dataset FOR THREAD + // SAFETY REASONS. + virtual void AddDataSet(vtkGenericDataSet* dataset); + + // Description: + // Set the last cell id to -1 so that the next search does not + // start from the previous cell + void ClearLastCell(); + + // Description: + // Return the cell cached from last evaluation. + vtkGenericAdaptorCell *GetLastCell(); + + // Description: + // Returns the interpolation weights cached from last evaluation + // if the cached cell is valid (returns 1). Otherwise, it does not + // change w and returns 0. + int GetLastLocalCoordinates(double pcoords[3]); + + // Description: + // Turn caching on/off. + vtkGetMacro(Caching, int); + vtkSetMacro(Caching, int); + vtkBooleanMacro(Caching, int); + + // Description: + // Caching statistics. + vtkGetMacro(CacheHit, int); + vtkGetMacro(CacheMiss, int); + + // Description: + // If you want to work with an arbitrary vector array, then set its name + // here. By default this in NULL and the filter will use the active vector + // array. + vtkGetStringMacro(VectorsSelection); + void SelectVectors(const char *fieldName) + {this->SetVectorsSelection(fieldName);} + + // Description: + // Returns the last dataset that was visited. Can be used + // as a first guess as to where the next point will be as + // well as to avoid searching through all datasets to get + // more information about the point. + vtkGetObjectMacro(LastDataSet, vtkGenericDataSet); + + // Description: + // Copy the user set parameters from source. This copies + // the Caching parameters. Sub-classes can add more after + // chaining. + virtual void CopyParameters(vtkGenericInterpolatedVelocityField* from); + +protected: + vtkGenericInterpolatedVelocityField(); + ~vtkGenericInterpolatedVelocityField(); + + vtkGenericCellIterator *GenCell; // last cell + + double LastPCoords[3]; // last local coordinates + int CacheHit; + int CacheMiss; + int Caching; + + vtkGenericDataSet* LastDataSet; + + vtkSetStringMacro(VectorsSelection); + char *VectorsSelection; + + vtkGenericInterpolatedVelocityFieldDataSetsType* DataSets; + + int FunctionValues(vtkGenericDataSet* ds, double* x, double* f); + + static const double TOLERANCE_SCALE; + +private: + vtkGenericInterpolatedVelocityField(const vtkGenericInterpolatedVelocityField&); // Not implemented. + void operator=(const vtkGenericInterpolatedVelocityField&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericPointIterator.cxx b/Filtering/vtkGenericPointIterator.cxx new file mode 100644 index 0000000..cc44bd0 --- /dev/null +++ b/Filtering/vtkGenericPointIterator.cxx @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericPointIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericPointIterator.h" + +vtkCxxRevisionMacro(vtkGenericPointIterator, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +vtkGenericPointIterator::vtkGenericPointIterator() +{ +} + +//---------------------------------------------------------------------------- +vtkGenericPointIterator::~vtkGenericPointIterator() +{ +} + +//---------------------------------------------------------------------------- +void vtkGenericPointIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + +} + diff --git a/Filtering/vtkGenericPointIterator.h b/Filtering/vtkGenericPointIterator.h new file mode 100644 index 0000000..3ca6421 --- /dev/null +++ b/Filtering/vtkGenericPointIterator.h @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericPointIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericPointIterator - iterator used to traverse points +// .SECTION Description +// This class (and subclasses) are used to iterate over points. Use it +// only in conjunction with vtkGenericDataSet (i.e., the adaptor framework). +// +// Typical use is: +//
+// vtkGenericDataSet *dataset;
+// vtkGenericPointIterator *it = dataset->NewPointIterator();
+// for (it->Begin(); !it->IsAtEnd(); it->Next());
+//   {
+//   x=it->GetPosition();
+//   }
+// 
+ + +#ifndef __vtkGenericPointIterator_h +#define __vtkGenericPointIterator_h + +#include "vtkObject.h" + +class VTK_FILTERING_EXPORT vtkGenericPointIterator : public vtkObject +{ +public: + // Description: + // Standard VTK construction and type macros. + vtkTypeRevisionMacro(vtkGenericPointIterator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + virtual void Begin() = 0; + + // Description: + // Is the iterator at the end of traversal? + virtual int IsAtEnd() = 0; + + // Description: + // Move the iterator to the next position in the list. + // \pre not_off: !IsAtEnd() + virtual void Next() = 0; + + // Description: + // Get the coordinates of the point at the current iterator position. + // \pre not_off: !IsAtEnd() + // \post result_exists: result!=0 + virtual double *GetPosition() = 0; + + // Description: + // Get the coordinates of the point at the current iterator position. + // \pre not_off: !IsAtEnd() + // \pre x_exists: x!=0 + virtual void GetPosition(double x[3]) = 0; + + // Description: + // Return the unique identifier for the point, could be non-contiguous. + // \pre not_off: !IsAtEnd() + virtual vtkIdType GetId() = 0; + +protected: + // Description: + // Destructor. + vtkGenericPointIterator(); + virtual ~vtkGenericPointIterator(); + +private: + vtkGenericPointIterator(const vtkGenericPointIterator&); // Not implemented. + void operator=(const vtkGenericPointIterator&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGenericSubdivisionErrorMetric.cxx b/Filtering/vtkGenericSubdivisionErrorMetric.cxx new file mode 100644 index 0000000..38dc367 --- /dev/null +++ b/Filtering/vtkGenericSubdivisionErrorMetric.cxx @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericSubdivisionErrorMetric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericSubdivisionErrorMetric.h" + +#include "vtkObjectFactory.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericDataSet.h" +#include "vtkMath.h" +#include + +vtkCxxRevisionMacro(vtkGenericSubdivisionErrorMetric,"$Revision: 1.5 $"); + +//----------------------------------------------------------------------------- +vtkGenericSubdivisionErrorMetric::vtkGenericSubdivisionErrorMetric() +{ + this->GenericCell = NULL; + this->DataSet = 0; +} + +//----------------------------------------------------------------------------- +vtkGenericSubdivisionErrorMetric::~vtkGenericSubdivisionErrorMetric() +{ +} + +//----------------------------------------------------------------------------- +// Avoid reference loop +void vtkGenericSubdivisionErrorMetric::SetGenericCell(vtkGenericAdaptorCell *c) +{ + this->GenericCell = c; + this->Modified(); +} + +//----------------------------------------------------------------------------- +// Avoid reference loop +void vtkGenericSubdivisionErrorMetric::SetDataSet(vtkGenericDataSet *ds) +{ + this->DataSet = ds; + this->Modified(); +} + +//----------------------------------------------------------------------------- +void vtkGenericSubdivisionErrorMetric::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "GenericCell: " << this->GenericCell << endl; + os << indent << "DataSet: " << this->DataSet << endl; +} diff --git a/Filtering/vtkGenericSubdivisionErrorMetric.h b/Filtering/vtkGenericSubdivisionErrorMetric.h new file mode 100644 index 0000000..4c8c3ee --- /dev/null +++ b/Filtering/vtkGenericSubdivisionErrorMetric.h @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericSubdivisionErrorMetric.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericSubdivisionErrorMetric - Objects that compute +// error during cell tessellation. +// +// .SECTION Description +// Objects of that class answer the following question during the cell +// subdivision: "does the edge need to be subdivided?" through +// RequiresEdgeSubdivision(). +// The answer depends on the criterium actually used in the subclass of this +// abstract class: a geometric-based error +// metric (variation of edge from a straight line), an attribute-based error +// metric (variation of the active attribute/component value from a linear +// ramp) , a view-depend error metric, ... +// Cell subdivision is performed in the context of the adaptor +// framework: higher-order, or complex cells, are automatically tessellated +// into simplices so that they can be processed with conventional +// visualization algorithms. + +// .SECTION See Also +// vtkGenericCellTessellator + +#ifndef __vtkGenericSubdivisionErrorMetric_h +#define __vtkGenericSubdivisionErrorMetric_h + +#include "vtkObject.h" + +class vtkGenericAttributeCollection; +class vtkGenericAdaptorCell; +class vtkGenericDataSet; + +class VTK_FILTERING_EXPORT vtkGenericSubdivisionErrorMetric : public vtkObject +{ +public: + // Description: + // Standard VTK type and error macros. + vtkTypeRevisionMacro(vtkGenericSubdivisionErrorMetric,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Does the edge need to be subdivided according to the implemented + // computation? + // The edge is defined by its `leftPoint' and its `rightPoint'. + // `leftPoint', `midPoint' and `rightPoint' have to be initialized before + // calling RequiresEdgeSubdivision(). + // Their format is global coordinates, parametric coordinates and + // point centered attributes: xyx rst abc de... + // `alpha' is the normalized abscissa of the midpoint along the edge. + // (close to 0 means close to the left point, close to 1 means close to the + // right point) + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + virtual int RequiresEdgeSubdivision(double *leftPoint, double *midPoint, + double *rightPoint, double alpha)=0; + + // Description: + // Return the error at the mid-point. The type of error depends on the state + // of the concrete error metric. For instance, it can return an absolute + // or relative error metric. + // See RequiresEdgeSubdivision() for a description of the arguments. + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + // \post positive_result: result>=0 + virtual double GetError(double *leftPoint, double *midPoint, + double *rightPoint, double alpha)=0; + + // Description: + // The cell that the edge belongs to. + void SetGenericCell(vtkGenericAdaptorCell *cell); + vtkGetObjectMacro(GenericCell,vtkGenericAdaptorCell); + + // Description: + // Set/Get the dataset to be tessellated. + void SetDataSet(vtkGenericDataSet *ds); + vtkGetObjectMacro(DataSet,vtkGenericDataSet); + +protected: + vtkGenericSubdivisionErrorMetric(); + ~vtkGenericSubdivisionErrorMetric(); + + vtkGenericAdaptorCell *GenericCell; + vtkGenericDataSet *DataSet; + +private: + vtkGenericSubdivisionErrorMetric(const vtkGenericSubdivisionErrorMetric&); // Not implemented. + void operator=(const vtkGenericSubdivisionErrorMetric&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkGeometricErrorMetric.cxx b/Filtering/vtkGeometricErrorMetric.cxx new file mode 100644 index 0000000..e7ae716 --- /dev/null +++ b/Filtering/vtkGeometricErrorMetric.cxx @@ -0,0 +1,242 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGeometricErrorMetric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGeometricErrorMetric.h" + +#include "vtkObjectFactory.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericDataSet.h" +#include "vtkMath.h" +#include + +vtkCxxRevisionMacro(vtkGeometricErrorMetric,"$Revision: 1.7 $"); +vtkStandardNewMacro(vtkGeometricErrorMetric); + +//----------------------------------------------------------------------------- +vtkGeometricErrorMetric::vtkGeometricErrorMetric() +{ + this->AbsoluteGeometricTolerance = 1.0; // arbitrary positive value + this->Relative=0; // GetError() will return the square absolute error. + this->SmallestSize=1; +} + +//----------------------------------------------------------------------------- +vtkGeometricErrorMetric::~vtkGeometricErrorMetric() +{ +} + +//----------------------------------------------------------------------------- +// Description : +// Set the geometric accuracy with an absolute value. +// Subdivision will be required if the square distance is greater than +// value. For instance 0.01 will give better result than 0.1. +// \pre positive_value: value>0 +void vtkGeometricErrorMetric::SetAbsoluteGeometricTolerance(double value) +{ + assert("pre: positive_value" && value>0); + this->Relative=0; + if(this->AbsoluteGeometricTolerance!=value) + { + this->AbsoluteGeometricTolerance=value; + this->Modified(); + } +} + +//----------------------------------------------------------------------------- +// Description : +// Set the geometric accuracy with a value relative to the bounding box of +// the dataset. Internally compute the absolute tolerance. +// For instance 0.01 will give better result than 0.1. +// \pre valid_range_value: value>0 && value<1 +// \pre ds_exists: ds!=0 +void vtkGeometricErrorMetric::SetRelativeGeometricTolerance(double value, + vtkGenericDataSet *ds) +{ + assert("pre: valid_range_value" && value>0 && value<1); + assert("pre: ds_exists" && ds!=0); + + double bounds[6]; + ds->GetBounds(bounds); + double smallest; + double length; + smallest = bounds[1] - bounds[0]; + length = bounds[3] - bounds[2]; + if(length < smallest || smallest == 0.0) + { + smallest = length; + } + length = bounds[5] - bounds[4]; + if(length < smallest || smallest == 0.0) + { + smallest = length; + } + length = ds->GetLength(); + if(length < smallest || smallest == 0.0) + { + smallest = length; + } + if(smallest == 0) + { + smallest = 1; + } + double tmp = value*smallest; + this->SmallestSize=smallest; + cout<<"this->SmallestSize="<SmallestSize<Relative=1; + tmp=tmp*tmp; + + if(this->AbsoluteGeometricTolerance!=tmp) + { + this->AbsoluteGeometricTolerance = tmp; + this->Modified(); + } +} + +#define VTK_DISTANCE_LINE_POINT + +//----------------------------------------------------------------------------- +int vtkGeometricErrorMetric::RequiresEdgeSubdivision(double *leftPoint, + double *midPoint, + double *rightPoint, +#ifdef VTK_DISTANCE_LINE_POINT + double vtkNotUsed(alpha) +#else + double alpha +#endif + ) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); +// assert("pre: clamped_alpha" && alpha>0 && alpha<1); // or else true + if( this->GenericCell->IsGeometryLinear() ) + { + //don't need to do anything: + return 0; + } + // distance between the line (leftPoint,rightPoint) and the point midPoint. +#ifdef VTK_DISTANCE_LINE_POINT + return this->Distance2LinePoint(leftPoint,rightPoint,midPoint)>this->AbsoluteGeometricTolerance; +#else + // Interpolated point + double interpolatedPoint[3]; + int i=0; + while(i<3) + { + interpolatedPoint[i]=leftPoint[i] + alpha*(rightPoint[i] - leftPoint[i]); + ++i; + } + return vtkMath::Distance2BetweenPoints(midPoint,interpolatedPoint)>this->AbsoluteGeometricTolerance; +#endif +} + +//----------------------------------------------------------------------------- +// Description: +// Return the error at the mid-point. The type of error depends on the state +// of the concrete error metric. For instance, it can return an absolute +// or relative error metric. +// See RequiresEdgeSubdivision() for a description of the arguments. +// \post positive_result: result>=0 +double vtkGeometricErrorMetric::GetError(double *leftPoint, + double *midPoint, + double *rightPoint, +#ifdef VTK_DISTANCE_LINE_POINT + double vtkNotUsed(alpha) +#else + double alpha +#endif + ) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); +// assert("pre: clamped_alpha" && alpha>0 && alpha<1); // or else true + if( this->GenericCell->IsGeometryLinear() ) + { + //don't need to do anything: + return 0; + } + // distance between the line (leftPoint,rightPoint) and the point midPoint. +#ifdef VTK_DISTANCE_LINE_POINT + double squareAbsoluteError=this->Distance2LinePoint(leftPoint,rightPoint,midPoint); +#else + // Interpolated point + double interpolatedPoint[3]; + int i=0; + while(i<3) + { + interpolatedPoint[i]=leftPoint[i] + alpha*(rightPoint[i] - leftPoint[i]); + ++i; + } + double squareAbsoluteError=vtkMath::Distance2BetweenPoints(midPoint,interpolatedPoint); +#endif + if(this->Relative) + { + return sqrt(squareAbsoluteError)/this->SmallestSize; + } + else + { + return squareAbsoluteError; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Return the type of output of GetError() +int vtkGeometricErrorMetric::GetRelative() +{ + return this->Relative; +} + +//----------------------------------------------------------------------------- +// Description: +// Square distance between a straight line (defined by points x and y) +// and a point z. Property: if x and y are equal, the line is a point and +// the result is the square distance between points x and z. +double vtkGeometricErrorMetric::Distance2LinePoint(double x[3], + double y[3], + double z[3]) +{ + double u[3]; + double v[3]; + double w[3]; + + u[0] = y[0] - x[0]; + u[1] = y[1] - x[1]; + u[2] = y[2] - x[2]; + + vtkMath::Normalize(u); + + v[0] = z[0] - x[0]; + v[1] = z[1] - x[1]; + v[2] = z[2] - x[2]; + + double dot = vtkMath::Dot(u,v); + + w[0] = v[0] - dot*u[0]; + w[1] = v[1] - dot*u[1]; + w[2] = v[2] - dot*u[2]; + + return vtkMath::Dot(w,w); +} + +//----------------------------------------------------------------------------- +void vtkGeometricErrorMetric::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "AbsoluteGeometricTolerance: " << this->AbsoluteGeometricTolerance << endl; +} diff --git a/Filtering/vtkGeometricErrorMetric.h b/Filtering/vtkGeometricErrorMetric.h new file mode 100644 index 0000000..a1e9e78 --- /dev/null +++ b/Filtering/vtkGeometricErrorMetric.h @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGeometricErrorMetric.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGeometricErrorMetric - Objects that compute +// geometry-based error during cell tessellation. +// +// .SECTION Description +// It is a concrete error metric, based on a geometric criterium: +// the variation of the edge from a straight line. +// +// .SECTION See Also +// vtkGenericCellTessellator vtkGenericSubdivisionErrorMetric + +#ifndef __vtkGeometricErrorMetric_h +#define __vtkGeometricErrorMetric_h + +#include "vtkGenericSubdivisionErrorMetric.h" + +class vtkGenericDataSet; + +class VTK_FILTERING_EXPORT vtkGeometricErrorMetric : public vtkGenericSubdivisionErrorMetric +{ +public: + // Description: + // Construct the error metric with a default squared absolute geometric + // accuracy equal to 1. + static vtkGeometricErrorMetric *New(); + + // Description: + // Standard VTK type and error macros. + vtkTypeRevisionMacro(vtkGeometricErrorMetric,vtkGenericSubdivisionErrorMetric); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the squared absolute geometric accuracy. See + // SetAbsoluteGeometricTolerance() for details. + // \post positive_result: result>0 + vtkGetMacro(AbsoluteGeometricTolerance, double); + + // Description: + // Set the geometric accuracy with a squared absolute value. + // This is the geometric object-based accuracy. + // Subdivision will be required if the square distance between the real + // point and the straight line passing through the vertices of the edge is + // greater than `value'. For instance 0.01 will give better result than 0.1. + // \pre positive_value: value>0 + void SetAbsoluteGeometricTolerance(double value); + + // Description: + // Set the geometric accuracy with a value relative to the length of the + // bounding box of the dataset. Internally compute the absolute tolerance. + // For instance 0.01 will give better result than 0.1. + // \pre valid_range_value: value>0 && value<1 + // \pre ds_exists: ds!=0 + void SetRelativeGeometricTolerance(double value, + vtkGenericDataSet *ds); + + // Description: + // Does the edge need to be subdivided according to the distance between + // the line passing through its endpoints and the mid point? + // The edge is defined by its `leftPoint' and its `rightPoint'. + // `leftPoint', `midPoint' and `rightPoint' have to be initialized before + // calling RequiresEdgeSubdivision(). + // Their format is global coordinates, parametric coordinates and + // point centered attributes: xyx rst abc de... + // `alpha' is the normalized abscissa of the midpoint along the edge. + // (close to 0 means close to the left point, close to 1 means close to the + // right point) + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + int RequiresEdgeSubdivision(double *leftPoint, double *midPoint, double *rightPoint, + double alpha); + + // Description: + // Return the error at the mid-point. It will return an error relative to + // the bounding box size if GetRelative() is true, a square absolute error + // otherwise. + // See RequiresEdgeSubdivision() for a description of the arguments. + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + // \post positive_result: result>=0 + double GetError(double *leftPoint, double *midPoint, + double *rightPoint, double alpha); + + // Description: + // Return the type of output of GetError() + int GetRelative(); + +protected: + vtkGeometricErrorMetric(); + virtual ~vtkGeometricErrorMetric(); + + // Description: + // Square distance between a straight line (defined by points x and y) + // and a point z. Property: if x and y are equal, the line is a point and + // the result is the square distance between points x and z. + double Distance2LinePoint(double x[3], + double y[3], + double z[3]); + + double AbsoluteGeometricTolerance; + double SmallestSize; + int Relative; // Control the type of output of GetError() + +private: + vtkGeometricErrorMetric(const vtkGeometricErrorMetric&); // Not implemented. + void operator=(const vtkGeometricErrorMetric&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkHexagonalPrism.cxx b/Filtering/vtkHexagonalPrism.cxx new file mode 100644 index 0000000..92e6811 --- /dev/null +++ b/Filtering/vtkHexagonalPrism.cxx @@ -0,0 +1,745 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHexagonalPrism.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// Thanks to Philippe Guerville who developed this class. +// Thanks to Charles Pignerol (CEA-DAM, France) who ported this class under +// VTK 4. +// Thanks to Jean Favre (CSCS, Switzerland) who contributed to integrate this +// class in VTK. +// Please address all comments to Jean Favre (jfavre at cscs.ch). + +#include "vtkHexagonalPrism.h" + +#include "vtkObjectFactory.h" +#include "vtkLine.h" +#include "vtkQuad.h" +#include "vtkPolygon.h" +#include "vtkMath.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkHexagonalPrism, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkHexagonalPrism); + +static const double VTK_DIVERGED = 1.e6; + +// You can recompute the value by doing: +// const double a = sqrt(3.0)/4.0 + 0.5; +#define EXPRA 0.933012701892219298 + +// You can recompute the value by doing: +// const double b = 0.5 - sqrt(3.0)/4.0; +// Thus EXPRA + EXPRB = 1.0 +#define EXPRB 0.066987298107780702 + +//---------------------------------------------------------------------------- +// Construct the prism with twelve points. +vtkHexagonalPrism::vtkHexagonalPrism() +{ + int i; + this->Points->SetNumberOfPoints(12); + this->PointIds->SetNumberOfIds(12); + + for (i = 0; i < 12; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + + this->Line = vtkLine::New(); + this->Quad = vtkQuad::New(); + this->Polygon = vtkPolygon::New(); + this->Polygon->PointIds->SetNumberOfIds(6); + this->Polygon->Points->SetNumberOfPoints(6); + + for (i = 0; i < 6; i++) + { + this->Polygon->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->Polygon->PointIds->SetId(i,0); + } +} + +//---------------------------------------------------------------------------- +vtkHexagonalPrism::~vtkHexagonalPrism() +{ + this->Line->Delete(); + this->Quad->Delete(); + this->Polygon->Delete(); +} + +// Method to calculate parametric coordinates in an eight noded +// linear hexahedron element from global coordinates. +// +static const int VTK_HEX_MAX_ITERATION=10; +static const double VTK_HEX_CONVERGED=1.e-03; + +//---------------------------------------------------------------------------- +int vtkHexagonalPrism::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[36]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.5; + + // enter iteration loop + for (iteration=converged=0; + !converged && (iteration < VTK_HEX_MAX_ITERATION); iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<12; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+12]; + tcol[j] += pt[j] * derivs[i+24]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_HEX_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_HEX_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_HEX_CONVERGED) ) + { + converged = 1; + } + + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside hexahedron + } + return 1; + } + else + { + double pc[3], w[12]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +// +// Compute iso-parametric interpolation functions +// +void vtkHexagonalPrism::InterpolationFunctions(double pcoords[3], double sf[12]) +{ + double r, s, t; + r = pcoords[0]; + s = pcoords[1]; + t = pcoords[2]; + const double a = EXPRA; + const double b = EXPRB; + + //First hexagon + sf[0] = -16./3.*(r - a )*(r - b)*(s - 1.0 )*(t - 1.0); + sf[1] = 16./3.*(r - 0.5)*(r - b)*(s - 0.75)*(t - 1.0); + sf[2] = -16./3.*(r - 0.5)*(r - b)*(s - 0.25)*(t - 1.0); + sf[3] = 16./3.*(r - a )*(r - b)*(s - 0.0 )*(t - 1.0); + sf[4] = -16./3.*(r - 0.5)*(r - a)*(s - 0.25)*(t - 1.0); + sf[5] = 16./3.*(r - 0.5)*(r - a)*(s - 0.75)*(t - 1.0); + + //Second hexagon + sf[6] = 16./3.*(r - a )*(r - b)*(s - 1.0 )*(t - 0.0); + sf[7] = -16./3.*(r - 0.5)*(r - b)*(s - 0.75)*(t - 0.0); + sf[8] = 16./3.*(r - 0.5)*(r - b)*(s - 0.25)*(t - 0.0); + sf[9] = -16./3.*(r - a )*(r - b)*(s - 0.0 )*(t - 0.0); + sf[10] = 16./3.*(r - 0.5)*(r - a)*(s - 0.25)*(t - 0.0); + sf[11] = -16./3.*(r - 0.5)*(r - a)*(s - 0.75)*(t - 0.0); +} + +//---------------------------------------------------------------------------- +void vtkHexagonalPrism::InterpolationDerivs(double pcoords[3], double derivs[36]) +{ + double r, s, t; + r = pcoords[0]; + s = pcoords[1]; + t = pcoords[2]; + const double a = EXPRA; + const double b = EXPRB; + //note: a+b=1.0 + + // r-derivatives + //First hexagon + derivs[0] = -16./3.*( 2*r - 1.0) *(s - 1.0 )*(t - 1.0); + derivs[1] = 16./3.*( 2*r - b - 0.5)*(s - 0.75)*(t - 1.0); + derivs[2] = -16./3.*( 2*r - b - 0.5)*(s - 0.25)*(t - 1.0); + derivs[3] = 16./3.*( 2*r - 1.0) *(s - 0.0 )*(t - 1.0); + derivs[4] = -16./3.*( 2*r - a - 0.5)*(s - 0.25)*(t - 1.0); + derivs[5] = 16./3.*( 2*r - a - 0.5)*(s - 0.75)*(t - 1.0); + //Second hexagon + derivs[6] = 16./3.*( 2*r - 1.0) *(s - 1.0 )*(t - 0.0); + derivs[7] = -16./3.*( 2*r - b - 0.5)*(s - 0.75)*(t - 0.0); + derivs[8] = 16./3.*( 2*r - b - 0.5)*(s - 0.25)*(t - 0.0); + derivs[9] = -16./3.*( 2*r - 1.0) *(s - 0.0 )*(t - 0.0); + derivs[10] = 16./3.*( 2*r - a - 0.5)*(s - 0.25)*(t - 0.0); + derivs[11] = -16./3.*( 2*r - a - 0.5)*(s - 0.75)*(t - 0.0); + + // s-derivatives + //First hexagon + derivs[12] = -16./3.*(r - a )*(r - b)*(t - 1.0); + derivs[13] = 16./3.*(r - 0.5)*(r - b)*(t - 1.0); + derivs[14] = -16./3.*(r - 0.5)*(r - b)*(t - 1.0); + derivs[15] = 16./3.*(r - a )*(r - b)*(t - 1.0); + derivs[16] = -16./3.*(r - 0.5)*(r - a)*(t - 1.0); + derivs[17] = 16./3.*(r - 0.5)*(r - a)*(t - 1.0); + //Second hexagon + derivs[18] = 16./3.*(r - a )*(r - b)*(t - 0.0); + derivs[19] = -16./3.*(r - 0.5)*(r - b)*(t - 0.0); + derivs[20] = 16./3.*(r - 0.5)*(r - b)*(t - 0.0); + derivs[21] = -16./3.*(r - a )*(r - b)*(t - 0.0); + derivs[22] = 16./3.*(r - 0.5)*(r - a)*(t - 0.0); + derivs[23] = -16./3.*(r - 0.5)*(r - a)*(t - 0.0); + + // t-derivatives + //First hexagon + derivs[24] = -16./3.*(r - a )*(r - b)*(s - 1.0 ); + derivs[25] = 16./3.*(r - 0.5)*(r - b)*(s - 0.75); + derivs[26] = -16./3.*(r - 0.5)*(r - b)*(s - 0.25); + derivs[27] = 16./3.*(r - a )*(r - b)*(s - 0.0 ); + derivs[28] = -16./3.*(r - 0.5)*(r - a)*(s - 0.25); + derivs[29] = 16./3.*(r - 0.5)*(r - a)*(s - 0.75); + //Second hexagon + derivs[30] = 16./3.*(r - a )*(r - b)*(s - 1.0 ); + derivs[31] = -16./3.*(r - 0.5)*(r - b)*(s - 0.75); + derivs[32] = 16./3.*(r - 0.5)*(r - b)*(s - 0.25); + derivs[33] = -16./3.*(r - a )*(r - b)*(s - 0.0 ); + derivs[34] = 16./3.*(r - 0.5)*(r - a)*(s - 0.25); + derivs[35] = -16./3.*(r - 0.5)*(r - a)*(s - 0.75); +} + +//---------------------------------------------------------------------------- +void vtkHexagonalPrism::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], double x[3], + double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i = 0; i < 12; i++) + { + this->Points->GetPoint (i, pt); + for (j = 0; j < 3; j++) + { + x[j] += pt [j] * weights [i]; + } + } +} +//---------------------------------------------------------------------------- +static int edges[18][2] = { {0,1}, {1, 2}, {2, 3}, + {3,4}, {4, 5}, {5, 0}, + {6,7}, {7, 8}, {8, 9}, + {9,10}, {10,11}, {11, 6}, + {0,6}, {1, 7}, {2, 8}, + {3,9}, {4, 10}, {5, 11} }; + +static int faces[8][6] = { {0,5,4,3,2,1}, {6,7,8,9,10,11}, + {0,1,7,6,-1,-1}, {1,2,8,7,-1,-1}, + {2,3,9,8,-1,-1}, {3,4,10,9,-1,-1}, + {4,5,11,10,-1,-1}, {5,0,6,11,-1,-1} }; + +#define VTK_MAX(a,b) (((a)>(b))?(a):(b)) +#define VTK_MIN(a,b) (((a)<(b))?(a):(b)) + +//---------------------------------------------------------------------------- +// Returns the closest face to the point specified. Closeness is measured +// parametrically. +int vtkHexagonalPrism::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + // load coordinates + double *points = this->GetParametricCoords(); + for(int i=0;i<6;i++) + { + this->Polygon->PointIds->SetId(i, i); + this->Polygon->Points->SetPoint(i, &points[3*i]); + } + + this->Polygon->CellBoundary( subId, pcoords, pts); + + int min = VTK_MIN(pts->GetId( 0 ), pts->GetId( 1 )); + int max = VTK_MAX(pts->GetId( 0 ), pts->GetId( 1 )); + + //Base on the edge find the quad that correspond: + int index; + if( (index = (max - min)) > 1) + { + index = 7; + } + else + { + index += min + 1; + } + + double a[3], b[3], u[3], v[3]; + this->Polygon->Points->GetPoint(pts->GetId( 0 ), a); + this->Polygon->Points->GetPoint(pts->GetId( 1 ), b); + u[0] = b[0] - a[0]; + u[1] = b[1] - a[1]; + v[0] = pcoords[0] - a[0]; + v[1] = pcoords[1] - a[1]; + + double dot = vtkMath::Dot2D(v, u); + double uNorm = vtkMath::Norm2D( u ); + if (uNorm) + { + dot /= uNorm; + } + dot = (v[0]*v[0] + v[1]*v[1]) - dot*dot; + // mathematically dot must be >= zero but, suprise suprise, it can actually + // be negative + if (dot > 0) + { + dot = sqrt( dot ); + } + else + { + dot = 0; + } + int *verts; + + if(pcoords[2] < 0.5) + { + //could be closer to face 1 + //compare that distance to the distance to the quad. + + if(dot < pcoords[2]) + { + //We are closer to the quad face + verts = faces[index]; + for(int i=0; i<4; i++) + { + pts->InsertId(i, verts[i]); + } + } + else + { + //we are closer to the hexa face 1 + for(int i=0; i<6; i++) + { + pts->InsertId(i, faces[0][i]); + } + } + } + else + { + //could be closer to face 2 + //compare that distance to the distance to the quad. + + if(dot < (1. - pcoords[2]) ) + { + //We are closer to the quad face + verts = faces[index]; + for(int i=0; i<4; i++) + { + pts->InsertId(i, verts[i]); + } + } + else + { + //we are closer to the hexa face 2 + for(int i=0; i<6; i++) + { + pts->InsertId(i, faces[1][i]); + } + } + } + + // determine whether point is inside of hexagon + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 || + pcoords[2] < 0.0 || pcoords[2] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} +//---------------------------------------------------------------------------- +int *vtkHexagonalPrism::GetEdgeArray(int edgeId) +{ + return edges[edgeId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkHexagonalPrism::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} +//---------------------------------------------------------------------------- +int *vtkHexagonalPrism::GetFaceArray(int faceId) +{ + return faces[faceId]; +} +//---------------------------------------------------------------------------- +vtkCell *vtkHexagonalPrism::GetFace(int faceId) +{ + int *verts; + + verts = faces[faceId]; + + if ( verts[4] != -1 ) // polys cell + { + // load point id's + this->Polygon->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Polygon->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Polygon->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + this->Polygon->PointIds->SetId(3,this->PointIds->GetId(verts[3])); + this->Polygon->PointIds->SetId(4,this->PointIds->GetId(verts[4])); + this->Polygon->PointIds->SetId(5,this->PointIds->GetId(verts[5])); + + // load coordinates + this->Polygon->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Polygon->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Polygon->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + this->Polygon->Points->SetPoint(3,this->Points->GetPoint(verts[3])); + this->Polygon->Points->SetPoint(4,this->Points->GetPoint(verts[4])); + this->Polygon->Points->SetPoint(5,this->Points->GetPoint(verts[5])); + + return this->Polygon; + } + else + { + // load point id's + this->Quad->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Quad->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Quad->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + this->Quad->PointIds->SetId(3,this->PointIds->GetId(verts[3])); + + // load coordinates + this->Quad->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Quad->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Quad->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + this->Quad->Points->SetPoint(3,this->Points->GetPoint(verts[3])); + + return this->Quad; + } +} +//---------------------------------------------------------------------------- +// +// Intersect prism faces against line. Each prism face is a quadrilateral. +// +int vtkHexagonalPrism::IntersectWithLine(double p1[3], double p2[3], double tol, + double &t, double x[3], double pcoords[3], + int& subId) +{ + int intersection=0; + double pt1[3], pt2[3], pt3[3], pt4[3], pt5[3], pt6[3]; + double tTemp; + double pc[3], xTemp[3], dist2, weights[12]; + int faceNum; + + t = VTK_DOUBLE_MAX; + + //first intersect the penta faces + for (faceNum=0; faceNum<2; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + this->Points->GetPoint(faces[faceNum][3], pt4); + this->Points->GetPoint(faces[faceNum][4], pt5); + this->Points->GetPoint(faces[faceNum][5], pt6); + + this->Polygon->Points->SetPoint(0,pt1); + this->Polygon->Points->SetPoint(1,pt2); + this->Polygon->Points->SetPoint(2,pt3); + this->Polygon->Points->SetPoint(3,pt4); + this->Polygon->Points->SetPoint(4,pt5); + this->Polygon->Points->SetPoint(5,pt6); + + if ( this->Polygon->IntersectWithLine(p1, p2, tol, tTemp, xTemp, + pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 1: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 1.0; + break; + } + } + } + } + + //now intersect the quad faces + for (faceNum=2; faceNum<8; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + this->Points->GetPoint(faces[faceNum][3], pt4); + + this->Quad->Points->SetPoint(0,pt1); + this->Quad->Points->SetPoint(1,pt2); + this->Quad->Points->SetPoint(2,pt3); + this->Quad->Points->SetPoint(3,pt4); + + if ( this->Quad->IntersectWithLine(p1, p2, tol, tTemp, xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + this->EvaluatePosition(x, xTemp, subId, pcoords, dist2, weights); + } + } + } + + return intersection; +} +//---------------------------------------------------------------------------- +int vtkHexagonalPrism::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, vtkPoints *pts) +{ + ptIds->Reset(); + pts->Reset(); + + for ( int i=0; i < 4; i++ ) + { + ptIds->InsertId(i,this->PointIds->GetId(i)); + pts->InsertPoint(i,this->Points->GetPoint(i)); + } + + return 1; +} +//---------------------------------------------------------------------------- +// +// Compute derivatives in x-y-z directions. Use chain rule in combination +// with interpolation function derivatives. +// +void vtkHexagonalPrism::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[36], sum[3], value; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 12; i++) //loop over interp. function derivatives + { + value = values[dim*i + k]; + sum[0] += functionDerivs[i] * value; + sum[1] += functionDerivs[12 + i] * value; + sum[2] += functionDerivs[24 + i] * value; + } + + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. +void vtkHexagonalPrism::JacobianInverse(double pcoords[3], double **inverse, + double derivs[36]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords, derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 12; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[12 + j]; + m2[i] += x[i] * derivs[24 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkHexagonalPrism::GetEdgePoints(int edgeId, int* &pts) +{ + pts = this->GetEdgeArray(edgeId); +} + +//---------------------------------------------------------------------------- +void vtkHexagonalPrism::GetFacePoints(int faceId, int* &pts) +{ + pts = this->GetFaceArray(faceId); +} + +static double vtkHexagonalPrismCellPCoords[36] = { + 0.5, 0.0 , 0.0, + EXPRA, 0.25, 0.0, + EXPRA, 0.75, 0.0, + 0.5, 1.0 , 0.0, + EXPRB, 0.75, 0.0, + EXPRB, 0.25, 0.0, + 0.5, 0.0 , 1.0, + EXPRA, 0.25, 1.0, + EXPRA, 0.75, 1.0, + 0.5, 1.0 , 1.0, + EXPRB, 0.75, 1.0, + EXPRB, 0.25, 1.0, +}; + +//---------------------------------------------------------------------------- +double *vtkHexagonalPrism::GetParametricCoords() +{ + return vtkHexagonalPrismCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkHexagonalPrism::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Quad:\n"; + this->Quad->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Polygon:\n"; + this->Polygon->PrintSelf(os,indent.GetNextIndent()); +} + diff --git a/Filtering/vtkHexagonalPrism.h b/Filtering/vtkHexagonalPrism.h new file mode 100644 index 0000000..eb4e034 --- /dev/null +++ b/Filtering/vtkHexagonalPrism.h @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHexagonalPrism.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHexagonalPrism - a 3D cell that represents a prism with +// hexagonal base +// .SECTION Description +// vtkHexagonalPrism is a concrete implementation of vtkCell to represent a +// linear 3D prism with hexagonal base. Such prism is defined by the twelve points +// (0-12) where (0,1,2,3,4,5) is the base of the prism which, using the right +// hand rule, forms a hexagon whose normal points is in the direction of the +// opposite face (6,7,8,9,10,11). + +// .SECTION Thanks +// Thanks to Philippe Guerville who developed this class. +// Thanks to Charles Pignerol (CEA-DAM, France) who ported this class under +// VTK 4. +// Thanks to Jean Favre (CSCS, Switzerland) who contributed to integrate this +// class in VTK. +// Please address all comments to Jean Favre (jfavre at cscs.ch). + + +#ifndef __vtkHexagonalPrism_h +#define __vtkHexagonalPrism_h + +#include "vtkCell3D.h" + +class vtkLine; +class vtkPolygon; +class vtkQuad; + +class VTK_FILTERING_EXPORT vtkHexagonalPrism : public vtkCell3D +{ +public: + static vtkHexagonalPrism *New(); + vtkTypeRevisionMacro(vtkHexagonalPrism,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int edgeId, int* &pts); + virtual void GetFacePoints(int faceId, int* &pts); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_HEXAGONAL_PRISM;}; + int GetCellDimension() {return 3;}; + int GetNumberOfEdges() {return 18;}; + int GetNumberOfFaces() {return 8;}; + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + double *GetParametricCoords(); + + // Description: + // Return the center of the wedge in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Hexagonal prism specific + static void InterpolationFunctions(double pcoords[3], double weights[12]); + static void InterpolationDerivs(double pcoords[3], double derivs[36]); + static int *GetEdgeArray(int edgeId); + static int *GetFaceArray(int faceId); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. + void JacobianInverse(double pcoords[3], double **inverse, double derivs[36]); + +protected: + vtkHexagonalPrism(); + ~vtkHexagonalPrism(); + + vtkLine *Line; + vtkQuad *Quad; + vtkPolygon *Polygon; + +private: + vtkHexagonalPrism(const vtkHexagonalPrism&); // Not implemented. + void operator=(const vtkHexagonalPrism&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkHexagonalPrism::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.5; + pcoords[2] = 0.5; + return 0; +} +#endif + + diff --git a/Filtering/vtkHexahedron.cxx b/Filtering/vtkHexahedron.cxx new file mode 100644 index 0000000..aa9b7ad --- /dev/null +++ b/Filtering/vtkHexahedron.cxx @@ -0,0 +1,744 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHexahedron.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHexahedron.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" +#include "vtkQuad.h" + +vtkCxxRevisionMacro(vtkHexahedron, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkHexahedron); + +static const double VTK_DIVERGED = 1.e6; + +//---------------------------------------------------------------------------- +// Construct the hexahedron with eight points. +vtkHexahedron::vtkHexahedron() +{ + this->Points->SetNumberOfPoints(8); + this->PointIds->SetNumberOfIds(8); + + for (int i = 0; i < 8; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); + this->Quad = vtkQuad::New(); +} + +//---------------------------------------------------------------------------- +vtkHexahedron::~vtkHexahedron() +{ + this->Line->Delete(); + this->Quad->Delete(); +} + +//---------------------------------------------------------------------------- +// Method to calculate parametric coordinates in an eight noded +// linear hexahedron element from global coordinates. +// +static const int VTK_HEX_MAX_ITERATION=10; +static const double VTK_HEX_CONVERGED=1.e-03; + +int vtkHexahedron::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[24]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.5; + + // enter iteration loop + for (iteration=converged=0; + !converged && (iteration < VTK_HEX_MAX_ITERATION); iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<8; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+8]; + tcol[j] += pt[j] * derivs[i+16]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_HEX_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_HEX_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_HEX_CONVERGED) ) + { + converged = 1; + } + + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside hexahedron + } + return 1; + } + else + { + double pc[3], w[8]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +// Compute iso-parametric interpolation functions +// +void vtkHexahedron::InterpolationFunctions(double pcoords[3], double sf[8]) +{ + double rm, sm, tm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + tm = 1. - pcoords[2]; + + sf[0] = rm*sm*tm; + sf[1] = pcoords[0]*sm*tm; + sf[2] = pcoords[0]*pcoords[1]*tm; + sf[3] = rm*pcoords[1]*tm; + sf[4] = rm*sm*pcoords[2]; + sf[5] = pcoords[0]*sm*pcoords[2]; + sf[6] = pcoords[0]*pcoords[1]*pcoords[2]; + sf[7] = rm*pcoords[1]*pcoords[2]; +} + +//---------------------------------------------------------------------------- +void vtkHexahedron::InterpolationDerivs(double pcoords[3], double derivs[24]) +{ + double rm, sm, tm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + tm = 1. - pcoords[2]; + + // r-derivatives + derivs[0] = -sm*tm; + derivs[1] = sm*tm; + derivs[2] = pcoords[1]*tm; + derivs[3] = -pcoords[1]*tm; + derivs[4] = -sm*pcoords[2]; + derivs[5] = sm*pcoords[2]; + derivs[6] = pcoords[1]*pcoords[2]; + derivs[7] = -pcoords[1]*pcoords[2]; + + // s-derivatives + derivs[8] = -rm*tm; + derivs[9] = -pcoords[0]*tm; + derivs[10] = pcoords[0]*tm; + derivs[11] = rm*tm; + derivs[12] = -rm*pcoords[2]; + derivs[13] = -pcoords[0]*pcoords[2]; + derivs[14] = pcoords[0]*pcoords[2]; + derivs[15] = rm*pcoords[2]; + + // t-derivatives + derivs[16] = -rm*sm; + derivs[17] = -pcoords[0]*sm; + derivs[18] = -pcoords[0]*pcoords[1]; + derivs[19] = -rm*pcoords[1]; + derivs[20] = rm*sm; + derivs[21] = pcoords[0]*sm; + derivs[22] = pcoords[0]*pcoords[1]; + derivs[23] = rm*pcoords[1]; +} + +//---------------------------------------------------------------------------- +void vtkHexahedron::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<8; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkHexahedron::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + double t1=pcoords[0]-pcoords[1]; + double t2=1.0-pcoords[0]-pcoords[1]; + double t3=pcoords[1]-pcoords[2]; + double t4=1.0-pcoords[1]-pcoords[2]; + double t5=pcoords[2]-pcoords[0]; + double t6=1.0-pcoords[2]-pcoords[0]; + + pts->SetNumberOfIds(4); + + // compare against six planes in parametric space that divide element + // into six pieces. + if ( t3 >= 0.0 && t4 >= 0.0 && t5 < 0.0 && t6 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(2)); + pts->SetId(3,this->PointIds->GetId(3)); + } + + else if ( t1 >= 0.0 && t2 < 0.0 && t5 < 0.0 && t6 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(2)); + pts->SetId(2,this->PointIds->GetId(6)); + pts->SetId(3,this->PointIds->GetId(5)); + } + + else if ( t1 >= 0.0 && t2 >= 0.0 && t3 < 0.0 && t4 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(5)); + pts->SetId(3,this->PointIds->GetId(4)); + } + + else if ( t3 < 0.0 && t4 < 0.0 && t5 >= 0.0 && t6 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(4)); + pts->SetId(1,this->PointIds->GetId(5)); + pts->SetId(2,this->PointIds->GetId(6)); + pts->SetId(3,this->PointIds->GetId(7)); + } + + else if ( t1 < 0.0 && t2 >= 0.0 && t5 >= 0.0 && t6 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(4)); + pts->SetId(2,this->PointIds->GetId(7)); + pts->SetId(3,this->PointIds->GetId(3)); + } + + else // if ( t1 < 0.0 && t2 < 0.0 && t3 >= 0.0 && t6 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(2)); + pts->SetId(1,this->PointIds->GetId(3)); + pts->SetId(2,this->PointIds->GetId(7)); + pts->SetId(3,this->PointIds->GetId(6)); + } + + + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 || + pcoords[2] < 0.0 || pcoords[2] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +static int edges[12][2] = { {0,1}, {1,2}, {3,2}, {0,3}, + {4,5}, {5,6}, {7,6}, {4,7}, + {0,4}, {1,5}, {3,7}, {2,6}}; +static int faces[6][4] = { {0,4,7,3}, {1,2,6,5}, + {0,1,5,4}, {3,7,6,2}, + {0,3,2,1}, {4,5,6,7} }; + +// Marching cubes case table +// +#include "vtkMarchingCubesCases.h" + +void vtkHexahedron::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + static int CASE_MASK[8] = {1,2,4,8,16,32,64,128}; + vtkMarchingCubesTriangleCases *triCase; + EDGE_LIST *edge; + int i, j, index, *vert; + int v1, v2, newCellId; + vtkIdType pts[3]; + double t, x1[3], x2[3], x[3], deltaScalar; + vtkIdType offset = verts->GetNumberOfCells() + lines->GetNumberOfCells(); + + // Build the case table + for ( i=0, index = 0; i < 8; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + triCase = vtkMarchingCubesTriangleCases::GetCases() + index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (i=0; i<3; i++) // insert triangle + { + vert = edges[edge[i]]; + + // calculate a preferred interpolation direction + deltaScalar = (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + v1 = vert[0]; v2 = vert[1]; + } + else + { + v1 = vert[1]; v2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + (value - cellScalars->GetComponent(v1,0)) / deltaScalar ); + + this->Points->GetPoint(v1, x1); + this->Points->GetPoint(v2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + vtkIdType p1 = this->PointIds->GetId(v1); + vtkIdType p2 = this->PointIds->GetId(v2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + + // check for degenerate triangle + if ( pts[0] != pts[1] && pts[0] != pts[2] && pts[1] != pts[2] ) + { + newCellId = offset + polys->InsertNextCell(3,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +int *vtkHexahedron::GetEdgeArray(int edgeId) +{ + return edges[edgeId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkHexahedron::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} + +//---------------------------------------------------------------------------- +int *vtkHexahedron::GetFaceArray(int faceId) +{ + return faces[faceId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkHexahedron::GetFace(int faceId) +{ + int *verts, i; + + verts = faces[faceId]; + + for (i=0; i<4; i++) + { + this->Quad->PointIds->SetId(i,this->PointIds->GetId(verts[i])); + this->Quad->Points->SetPoint(i,this->Points->GetPoint(verts[i])); + } + + return this->Quad; +} + +//---------------------------------------------------------------------------- +// +// Intersect hexa faces against line. Each hexa face is a quadrilateral. +// +int vtkHexahedron::IntersectWithLine(double p1[3], double p2[3], double tol, + double &t, double x[3], double pcoords[3], + int& subId) +{ + int intersection=0; + double pt1[3], pt2[3], pt3[3], pt4[3]; + double tTemp; + double pc[3], xTemp[3]; + int faceNum; + + t = VTK_DOUBLE_MAX; + for (faceNum=0; faceNum<6; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + this->Points->GetPoint(faces[faceNum][3], pt4); + + this->Quad->Points->SetPoint(0,pt1); + this->Quad->Points->SetPoint(1,pt2); + this->Quad->Points->SetPoint(2,pt3); + this->Quad->Points->SetPoint(3,pt4); + + if ( this->Quad->IntersectWithLine(p1, p2, tol, tTemp, xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = 0.0; pcoords[0] = pc[0]; pcoords[1] = 0.0; + break; + + case 1: + pcoords[0] = 1.0; pcoords[0] = pc[0]; pcoords[1] = 0.0; + break; + + case 2: + pcoords[0] = pc[0]; pcoords[1] = 0.0; pcoords[2] = pc[1]; + break; + + case 3: + pcoords[0] = pc[0]; pcoords[1] = 1.0; pcoords[2] = pc[1]; + break; + + case 4: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 5: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 1.0; + break; + } + } + } + } + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkHexahedron::Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts) +{ + int p[4], i; + + ptIds->Reset(); + pts->Reset(); + + // Create five tetrahedron. Triangulation varies depending upon index. This + // is necessary to insure compatible voxel triangulations. + if ( (index % 2) ) + { + p[0] = 0; p[1] = 1; p[2] = 3; p[3] = 4; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 1; p[1] = 4; p[2] = 5; p[3] = 6; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 1; p[1] = 4; p[2] = 6; p[3] = 3; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 1; p[1] = 3; p[2] = 6; p[3] = 2; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 3; p[1] = 6; p[2] = 7; p[3] = 4; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + } + else + { + p[0] = 2; p[1] = 1; p[2] = 5; p[3] = 0; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 0; p[1] = 2; p[2] = 3; p[3] = 7; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 2; p[1] = 5; p[2] = 6; p[3] = 7; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 0; p[1] = 7; p[2] = 4; p[3] = 5; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 0; p[1] = 2; p[2] = 7; p[3] = 5; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Compute derivatives in x-y-z directions. Use chain rule in combination +// with interpolation function derivatives. +// +void vtkHexahedron::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[24], sum[3]; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 8; i++) //loop over interp. function derivatives + { + sum[0] += functionDerivs[i] * values[dim*i + k]; + sum[1] += functionDerivs[8 + i] * values[dim*i + k]; + sum[2] += functionDerivs[16 + i] * values[dim*i + k]; + } + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. +void vtkHexahedron::JacobianInverse(double pcoords[3], double **inverse, + double derivs[24]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords, derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 8; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[8 + j]; + m2[i] += x[i] * derivs[16 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkHexahedron::GetEdgePoints(int edgeId, int* &pts) +{ + pts = this->GetEdgeArray(edgeId); +} + +//---------------------------------------------------------------------------- +void vtkHexahedron::GetFacePoints(int faceId, int* &pts) +{ + pts = this->GetFaceArray(faceId); +} + +//---------------------------------------------------------------------------- +static double vtkHexahedronCellPCoords[24] = {0.0,0.0,0.0, 1.0,0.0,0.0, + 1.0,1.0,0.0, 0.0,1.0,0.0, + 0.0,0.0,1.0, 1.0,0.0,1.0, + 1.0,1.0,1.0, 0.0,1.0,1.0}; + +double *vtkHexahedron::GetParametricCoords() +{ + return vtkHexahedronCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkHexahedron::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Quad:\n"; + this->Quad->PrintSelf(os,indent.GetNextIndent()); +} + diff --git a/Filtering/vtkHexahedron.h b/Filtering/vtkHexahedron.h new file mode 100644 index 0000000..408564b --- /dev/null +++ b/Filtering/vtkHexahedron.h @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHexahedron.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHexahedron - a cell that represents a linear 3D hexahedron +// .SECTION Description +// vtkHexahedron is a concrete implementation of vtkCell to represent a +// linear, 3D rectangular hexahedron (e.g., "brick" topology). vtkHexahedron +// uses the standard isoparametric shape functions for a linear +// hexahedron. The hexahedron is defined by the eight points (0-7) where +// (0,1,2,3) is the base of the hexahedron which, using the right hand rule, +// forms a quadrilaterial whose normal points in the direction of the +// opposite face (4,5,6,7). + +// .SECTION See Also +// vtkConvexPointSet vtkPyramid vtkTetra vtkVoxel vtkWedge + +#ifndef __vtkHexahedron_h +#define __vtkHexahedron_h + +#include "vtkCell3D.h" + +class vtkLine; +class vtkQuad; + +class VTK_FILTERING_EXPORT vtkHexahedron : public vtkCell3D +{ +public: + static vtkHexahedron *New(); + vtkTypeRevisionMacro(vtkHexahedron,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int edgeId, int* &pts); + virtual void GetFacePoints(int faceId, int* &pts); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_HEXAHEDRON;} + int GetNumberOfEdges() {return 12;} + int GetNumberOfFaces() {return 6;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Hexahedron specific. + static void InterpolationFunctions(double pcoords[3], double weights[8]); + static void InterpolationDerivs(double pcoords[3], double derivs[24]); + static int *GetEdgeArray(int edgeId); + static int *GetFaceArray(int faceId); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. + void JacobianInverse(double pcoords[3], double **inverse, double derivs[24]); + +protected: + vtkHexahedron(); + ~vtkHexahedron(); + + vtkLine *Line; + vtkQuad *Quad; + +private: + vtkHexahedron(const vtkHexahedron&); // Not implemented. + void operator=(const vtkHexahedron&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkHierarchicalBoxDataSet.cxx b/Filtering/vtkHierarchicalBoxDataSet.cxx new file mode 100644 index 0000000..eb145a3 --- /dev/null +++ b/Filtering/vtkHierarchicalBoxDataSet.cxx @@ -0,0 +1,371 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalBoxDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalBoxDataSet.h" + +#include "vtkHierarchicalBoxDataSetInternal.h" + +#include "vtkHierarchicalDataInformation.h" +#include "vtkInformation.h" +#include "vtkInformationIdTypeKey.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationKey.h" +#include "vtkObjectFactory.h" +#include "vtkUniformGrid.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkHierarchicalBoxDataSet, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkHierarchicalBoxDataSet); + +vtkInformationKeyMacro(vtkHierarchicalBoxDataSet,BOX,IntegerVector); +vtkInformationKeyMacro(vtkHierarchicalBoxDataSet,NUMBER_OF_BLANKED_POINTS,IdType); + +//---------------------------------------------------------------------------- +vtkHierarchicalBoxDataSet::vtkHierarchicalBoxDataSet() +{ + this->BoxInternal = new vtkHierarchicalBoxDataSetInternal; +} + +//---------------------------------------------------------------------------- +vtkHierarchicalBoxDataSet::~vtkHierarchicalBoxDataSet() +{ + delete this->BoxInternal; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalBoxDataSet::SetDataSet( + unsigned int level, unsigned int id, vtkAMRBox& box, vtkUniformGrid* dataSet) +{ + this->Superclass::SetDataSet(level, id, dataSet); + + vtkInformation* info = + this->HierarchicalDataInformation->GetInformation(level, id); + if (info) + { + info->Set(BOX(), + box.LoCorner[0], box.LoCorner[1], box.LoCorner[2], + box.HiCorner[0], box.HiCorner[1], box.HiCorner[2]); + } +} + +//---------------------------------------------------------------------------- +vtkUniformGrid* vtkHierarchicalBoxDataSet::GetDataSet(unsigned int level, + unsigned int id, + vtkAMRBox& box) +{ + if (this->Internal->DataSets.size() <= level) + { + return 0; + } + + vtkHierarchicalDataSetInternal::LevelDataSetsType& ldataSets = + this->Internal->DataSets[level]; + if (ldataSets.size() <= id) + { + return 0; + } + + if (!ldataSets[id]) + { + return 0; + } + + vtkInformation* info = + this->HierarchicalDataInformation->GetInformation(level, id); + if (info) + { + int* boxVec = info->Get(BOX()); + if (boxVec) + { + memcpy(&box.LoCorner, boxVec , 3*sizeof(int)); + memcpy(&box.HiCorner, boxVec+3, 3*sizeof(int)); + } + } + return static_cast(ldataSets[id].GetPointer()); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalBoxDataSet::SetRefinementRatio(unsigned int level, + int ratio) +{ + if (level >= this->BoxInternal->RefinementRatios.size()) + { + this->BoxInternal->RefinementRatios.resize(level+1); + } + this->BoxInternal->RefinementRatios[level] = ratio; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalBoxDataSet::GetRefinementRatio(unsigned int level) +{ + if (level >= this->BoxInternal->RefinementRatios.size()) + { + return 0; + } + return this->BoxInternal->RefinementRatios[level]; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalBoxDataSetIsInBoxes(vtkstd::vector& boxes, + int i, int j, int k) +{ + vtkstd::vector::iterator it; + for(it = boxes.begin(); it != boxes.end(); it++) + { + if (it->DoesContainCell(i, j, k)) + { + return 1; + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalBoxDataSet::GenerateVisibilityArrays() +{ + if (!this->HierarchicalDataInformation) + { + vtkErrorMacro("No information about data layout is specified. " + "Cannot generate visibility arrays"); + return; + } + + unsigned int numLevels = this->GetNumberOfLevels(); + + for (unsigned int levelIdx=0; levelIdx boxes; + unsigned int numDataSets = this->GetNumberOfDataSets(levelIdx+1); + unsigned int dataSetIdx; + if (levelIdx < numLevels - 1) + { + for (dataSetIdx=0; dataSetIdxHierarchicalDataInformation->HasInformation( + levelIdx+1, dataSetIdx)) + { + continue; + } + vtkInformation* info = + this->HierarchicalDataInformation->GetInformation( + levelIdx+1,dataSetIdx); + int* boxVec = info->Get(BOX()); + vtkAMRBox coarsebox(3, boxVec, boxVec+3); + if (this->BoxInternal->RefinementRatios.size() <= levelIdx) + { + continue; + } + coarsebox.Coarsen(this->BoxInternal->RefinementRatios[levelIdx]); + boxes.push_back(coarsebox); + } + } + + numDataSets = this->GetNumberOfDataSets(levelIdx); + for (dataSetIdx=0; dataSetIdxGetDataSet(levelIdx, dataSetIdx, box); + + if (grid) + { + int i; + int cellDims[3]; + for (i=0; i<3; i++) + { + cellDims[i] = box.HiCorner[i] - box.LoCorner[i] + 1; + } + vtkUnsignedCharArray* vis = vtkUnsignedCharArray::New(); + vtkIdType numCells = box.GetNumberOfCells(); + vis->SetNumberOfTuples(numCells); + for (i=0; iSetValue(i, 1); + } + vtkIdType numBlankedPts = 0; + for (int iz=box.LoCorner[2]; iz<=box.HiCorner[2]; iz++) + { + for (int iy=box.LoCorner[1]; iy<=box.HiCorner[1]; iy++) + { + for (int ix=box.LoCorner[0]; ix<=box.HiCorner[0]; ix++) + { + // Blank if cell is covered by a box of higher level + if (vtkHierarchicalBoxDataSetIsInBoxes(boxes, ix, iy, iz)) + { + vtkIdType id = + (iz-box.LoCorner[2])*cellDims[0]*cellDims[1] + + (iy-box.LoCorner[1])*cellDims[0] + + (ix-box.LoCorner[0]); + vis->SetValue(id, 0); + numBlankedPts++; + } + } + } + } + grid->SetCellVisibilityArray(vis); + vis->Delete(); + if (this->HierarchicalDataInformation->HasInformation( + levelIdx, dataSetIdx)) + { + vtkInformation* infotmp = + this->HierarchicalDataInformation->GetInformation( + levelIdx,dataSetIdx); + infotmp->Set(NUMBER_OF_BLANKED_POINTS(), numBlankedPts); + } + } + } + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkHierarchicalBoxDataSet::GetNumberOfPoints() +{ + vtkIdType numPts = 0; + + unsigned int numLevels = this->GetNumberOfLevels(); + for (unsigned int level=0; levelGetNumberOfDataSets(level); + for (unsigned int dataIdx=0; dataIdxHierarchicalDataInformation->GetInformation(level, dataIdx); + if (blockInfo) + { + if (blockInfo->Has( + vtkHierarchicalBoxDataSet::NUMBER_OF_BLANKED_POINTS())) + { + numBlankedPts = blockInfo->Get(NUMBER_OF_BLANKED_POINTS()); + } + } + vtkDataSet* ds = vtkDataSet::SafeDownCast( + this->GetDataSet(level, dataIdx)); + if (ds) + { + numPts += ds->GetNumberOfPoints() - numBlankedPts; + } + } + } + + return numPts; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalBoxDataSet::ShallowCopy(vtkDataObject *src) +{ + if (src == this) + { + return; + } + this->InitializeDataSets(); + this->Modified(); + + vtkHierarchicalBoxDataSet* from = + vtkHierarchicalBoxDataSet::SafeDownCast(src); + if (from) + { + // If the source is a vtkHierarchicalBoxDataSet, do not call + // superclass' ShallowCopy, instead skip to vtkCompositeDataSet's + // constructor + this->vtkCompositeDataSet::ShallowCopy(src); + + unsigned int numLevels = from->GetNumberOfLevels(); + this->SetNumberOfLevels(numLevels); + for (unsigned int i=0; iGetNumberOfDataSets(i); + this->SetNumberOfDataSets(i, numDataSets); + for (unsigned int j=0; jGetDataSet(i, j, box); + this->SetDataSet(i, j, box, grid); + } + } + } + else + { + this->Superclass::ShallowCopy(src); + } +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalBoxDataSet::DeepCopy(vtkDataObject *src) +{ + if (src == this) + { + return; + } + this->InitializeDataSets(); + this->Modified(); + + vtkHierarchicalBoxDataSet* from = + vtkHierarchicalBoxDataSet::SafeDownCast(src); + if (from) + { + // If the source is a vtkHierarchicalBoxDataSet, do not call + // superclass' DeepCopy, instead skip to vtkCompositeDataSet's + // constructor + this->vtkCompositeDataSet::ShallowCopy(src); + + unsigned int numLevels = from->GetNumberOfLevels(); + this->SetNumberOfLevels(numLevels); + for (unsigned int i=0; iGetNumberOfDataSets(i); + this->SetNumberOfDataSets(i, numDataSets); + for (unsigned int j=0; jGetDataSet(i, j, box); + if (ds) + { + vtkUniformGrid* copy = ds->NewInstance(); + copy->DeepCopy(ds); + this->SetDataSet(i, j, box, copy); + } + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalBoxDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + unsigned int numLevels = this->GetNumberOfLevels(); + os << indent << "Number of levels: " << numLevels << endl; + for (unsigned int i=0; iGetNumberOfDataSets(i); + os << indent << "Level " << i << " number of datasets: " << numDataSets + << endl; + for (unsigned j=0; jGetDataSet(i, j); + if (dobj) + { + os << endl; + dobj->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)" << endl; + } + } + } +} + diff --git a/Filtering/vtkHierarchicalBoxDataSet.h b/Filtering/vtkHierarchicalBoxDataSet.h new file mode 100644 index 0000000..703f1e2 --- /dev/null +++ b/Filtering/vtkHierarchicalBoxDataSet.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalBoxDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalBoxDataSet - hierarchical dataset of vtkUniformGrids +// .SECTION Description +// vtkHierarchicalBoxDataSet is a concrete implementation of +// vtkHierarchicalDataSet. The dataset type is restricted to +// vtkUniformGrid. Each dataset has an associated vtkAMRBox +// that represents it's region (similar to extent) in space. + +#ifndef __vtkHierarchicalBoxDataSet_h +#define __vtkHierarchicalBoxDataSet_h + +#include "vtkHierarchicalDataSet.h" + +//BTX +struct vtkHierarchicalBoxDataSetInternal; +//ETX +class vtkDataObject; +class vtkInformationIdTypeKey; +class vtkUniformGrid; +class vtkAMRBox; + +class VTK_FILTERING_EXPORT vtkHierarchicalBoxDataSet : public vtkHierarchicalDataSet +{ +public: + static vtkHierarchicalBoxDataSet *New(); + + vtkTypeRevisionMacro(vtkHierarchicalBoxDataSet,vtkHierarchicalDataSet); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return class name of data type (see vtkSystemIncludes.h for + // definitions). + virtual int GetDataObjectType() {return VTK_HIERARCHICAL_BOX_DATA_SET;} + +//BTX + // Description: + // Set the dataset pointer for a given node. This method does + // not remove the existing parent/child links. It only replaces + // the dataset pointer. + void SetDataSet(unsigned int level, + unsigned int id, + vtkAMRBox& box, + vtkUniformGrid* dataSet); + void SetDataSet(unsigned int level, unsigned int id, vtkDataObject* dataSet) + { + this->Superclass::SetDataSet(level, id, dataSet); + } + + // Description: + // Get a dataset give a level and an id. + vtkUniformGrid* GetDataSet(unsigned int level, + unsigned int id, + vtkAMRBox& box); +//ETX + vtkDataObject* GetDataSet(unsigned int level, unsigned int id) + { return this->Superclass::GetDataSet(level, id); } + + vtkDataObject* GetDataSet(vtkInformation* index) + { return this->Superclass::GetDataSet(index); } + + // Description: + // Sets the refinement of a given level. + void SetRefinementRatio(unsigned int level, int refRatio); + + // Description: + // Returns the refinement of a given level. + int GetRefinementRatio(unsigned int level); + + // Description: + // Blank lower level cells if they are overlapped by higher + // level ones. + void GenerateVisibilityArrays(); + + // Description: + // Shallow and Deep copy. + virtual void ShallowCopy(vtkDataObject *src); + virtual void DeepCopy(vtkDataObject *src); + + static vtkInformationIntegerVectorKey* BOX(); + static vtkInformationIdTypeKey* NUMBER_OF_BLANKED_POINTS(); + + // Description: + // Returns the total number of points of all blocks. This will + // iterate over all blocks and call GetNumberOfPoints() so it + // might be expansive. Does not include the number of blanked + // points. + virtual vtkIdType GetNumberOfPoints(); + +protected: + vtkHierarchicalBoxDataSet(); + ~vtkHierarchicalBoxDataSet(); + + vtkHierarchicalBoxDataSetInternal* BoxInternal; + +private: + vtkHierarchicalBoxDataSet(const vtkHierarchicalBoxDataSet&); // Not implemented. + void operator=(const vtkHierarchicalBoxDataSet&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkHierarchicalBoxDataSetInternal.h b/Filtering/vtkHierarchicalBoxDataSetInternal.h new file mode 100644 index 0000000..551cb11 --- /dev/null +++ b/Filtering/vtkHierarchicalBoxDataSetInternal.h @@ -0,0 +1,27 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalBoxDataSetInternal.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __vtkHierarchicalBoxDataSetInternal_h +#define __vtkHierarchicalBoxDataSetInternal_h + +#include "vtkHierarchicalDataSetInternal.h" +#include "vtkAMRBox.h" + +struct vtkHierarchicalBoxDataSetInternal +{ + vtkstd::vector RefinementRatios; +}; + +#endif diff --git a/Filtering/vtkHierarchicalDataInformation.cxx b/Filtering/vtkHierarchicalDataInformation.cxx new file mode 100644 index 0000000..7ea7064 --- /dev/null +++ b/Filtering/vtkHierarchicalDataInformation.cxx @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataInformation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataInformation.h" + +#include "vtkHierarchicalDataInformation.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkSmartPointer.h" + +vtkCxxRevisionMacro(vtkHierarchicalDataInformation, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkHierarchicalDataInformation); + +#include + +struct vtkHierarchicalDataInformationInternal +{ + typedef vtkstd::vector > LevelInformationType; + typedef vtkstd::vector DataInformationType; + + DataInformationType DataInformation; +}; + +//---------------------------------------------------------------------------- +vtkHierarchicalDataInformation::vtkHierarchicalDataInformation() +{ + this->Internal = new vtkHierarchicalDataInformationInternal; +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataInformation::~vtkHierarchicalDataInformation() +{ + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataInformation::Clear() +{ + this->Internal->DataInformation.clear(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataInformation::DeepCopy( + vtkHierarchicalDataInformation* from) +{ + unsigned int numLevels = from->GetNumberOfLevels(); + this->SetNumberOfLevels(numLevels); + for (unsigned int i=0; iGetNumberOfDataSets(i); + this->SetNumberOfDataSets(i, numDataSets); + for (unsigned int j=0; jGetInformation(i, j); + vtkInformation* fromInf = from->GetInformation(i, j); + toInf->Copy(fromInf); + } + } +} + +//---------------------------------------------------------------------------- +unsigned int vtkHierarchicalDataInformation::GetNumberOfLevels() +{ + return this->Internal->DataInformation.size(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataInformation::SetNumberOfLevels(unsigned int numLevels) +{ + if (numLevels <= this->GetNumberOfLevels()) + { + return; + } + this->Internal->DataInformation.resize(numLevels); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +unsigned int vtkHierarchicalDataInformation::GetNumberOfDataSets( + unsigned int level) +{ + if (this->Internal->DataInformation.size() <= level) + { + return 0; + } + + vtkHierarchicalDataInformationInternal::LevelInformationType& linf = + this->Internal->DataInformation[level]; + + return linf.size(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataInformation::SetNumberOfDataSets( + unsigned int level, unsigned int numDataSets) +{ + if (numDataSets <= this->GetNumberOfDataSets(level)) + { + return; + } + // Make sure that there is a vector allocated for this level + if (this->Internal->DataInformation.size() <= level) + { + this->SetNumberOfLevels(level+1); + } + + vtkHierarchicalDataInformationInternal::LevelInformationType& linf = + this->Internal->DataInformation[level]; + linf.resize(numDataSets); + + this->Modified(); +} + + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataInformation::HasInformation( + unsigned int level, unsigned int id) +{ + if (this->Internal->DataInformation.size() <= level) + { + return 0; + } + + vtkHierarchicalDataInformationInternal::LevelInformationType& linf = + this->Internal->DataInformation[level]; + if (linf.size() <= id) + { + return 0; + } + + vtkInformation* inf = linf[id].GetPointer(); + if (!inf) + { + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +vtkInformation* vtkHierarchicalDataInformation::GetInformation( + unsigned int level, unsigned int id) +{ + if (this->Internal->DataInformation.size() <= level) + { + return 0; + } + + vtkHierarchicalDataInformationInternal::LevelInformationType& linf = + this->Internal->DataInformation[level]; + if (linf.size() <= id) + { + return 0; + } + + vtkInformation* inf = linf[id].GetPointer(); + if (!inf) + { + inf = vtkInformation::New(); + linf[id] = inf; + inf->Delete(); + } + + return inf; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataInformation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + diff --git a/Filtering/vtkHierarchicalDataInformation.h b/Filtering/vtkHierarchicalDataInformation.h new file mode 100644 index 0000000..8fc369d --- /dev/null +++ b/Filtering/vtkHierarchicalDataInformation.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataInformation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataInformation - hierarchical information collection +// .SECTION Description +// vtkHierarchicalDataInformation stores information objects in a structure +// corresponding to that of a hierarchical dataset. This is essentially a +// vector of vectors of information object pointers. Each entry in the +// outer vector corresponds to one levels, whereas each entry in the inner +// vector corresponds to one dataset. +// .SECTION See Also +// vtkHierarchicalDataSet vtkCompositeDataPipeline + +#ifndef __vtkHierarchicalDataInformation_h +#define __vtkHierarchicalDataInformation_h + +#include "vtkObject.h" + +class vtkInformation; +//BTX +struct vtkHierarchicalDataInformationInternal; +//ETX + +class VTK_FILTERING_EXPORT vtkHierarchicalDataInformation : public vtkObject +{ +public: + static vtkHierarchicalDataInformation *New(); + vtkTypeRevisionMacro(vtkHierarchicalDataInformation,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Returns the number of hierarchy levels. + unsigned int GetNumberOfLevels(); + + // Description: + // Set the number of hierarchy levels. + void SetNumberOfLevels(unsigned int numLevels); + + // Description: + // Given a level, returns the number of datasets. + unsigned int GetNumberOfDataSets(unsigned int level); + + // Description: + // Given a level, sets the number of datasets. + void SetNumberOfDataSets(unsigned int level, unsigned int numDataSets); + + // Description: + // Given a level and a dataset id, returns the corresponding information + // object. If the information does not exist, one is created. Use + // HasInformation() to check whether the information already exists. + vtkInformation* GetInformation(unsigned int level, unsigned int id); + + // Description: + // Returns 1 if information exists, 0 otherwise. + int HasInformation(unsigned int level, unsigned int id); + + // Description: + // Creates a duplicate hierarchy and calls Copy() on each information + // object. + void DeepCopy(vtkHierarchicalDataInformation* from); + + // Description: + // Initializes the data structure to empty. + void Clear(); + +protected: + vtkHierarchicalDataInformation(); + ~vtkHierarchicalDataInformation(); + +private: + vtkHierarchicalDataInformationInternal* Internal; + + vtkHierarchicalDataInformation(const vtkHierarchicalDataInformation&); // Not implemented. + void operator=(const vtkHierarchicalDataInformation&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkHierarchicalDataIterator.cxx b/Filtering/vtkHierarchicalDataIterator.cxx new file mode 100644 index 0000000..5076b56 --- /dev/null +++ b/Filtering/vtkHierarchicalDataIterator.cxx @@ -0,0 +1,194 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataIterator.h" + +#include "vtkHierarchicalDataSet.h" +#include "vtkHierarchicalDataSetInternal.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkHierarchicalDataIterator, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkHierarchicalDataIterator); + +class vtkHierarchicalDataIteratorInternal +{ +public: + // We store two iterators. + // DSIterator (DataSets) iterators over the levels + // LDSIteator (LevelDataSets) iterates over the nodes in the current level + vtkHierarchicalDataSetInternal::LevelDataSetsIterator LDSIterator; + vtkHierarchicalDataSetInternal::DataSetsIterator DSIterator; +}; + +//---------------------------------------------------------------------------- +vtkHierarchicalDataIterator::vtkHierarchicalDataIterator() +{ + this->DataSet = 0; + this->Internal = new vtkHierarchicalDataIteratorInternal; +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataIterator::~vtkHierarchicalDataIterator() +{ + this->SetDataSet(0); + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataIterator::SetDataSet(vtkHierarchicalDataSet* dataset) +{ + if (this->DataSet != dataset) + { + if (this->DataSet) + { + this->DataSet->UnRegister(this); + } + this->DataSet = dataset; + if (this->DataSet) + { + this->DataSet->Register(this); + this->GoToFirstItem(); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataIterator::GoToFirstItem() +{ + if (!this->DataSet) + { + vtkErrorMacro("No data object has been set."); + return; + } + // Initialize to the first level + this->Internal->DSIterator = this->DataSet->Internal->DataSets.begin(); + if ( !this->DataSet->Internal->DataSets.empty() ) + { + // Initialize to the first node in the first level + this->Internal->LDSIterator = this->Internal->DSIterator->begin(); + if (this->Internal->LDSIterator == this->Internal->DSIterator->end()) + { + this->GoToNextNonEmptyLevel(); + } + // Skip nodes with NULL dataset pointers. + if (!this->IsDoneWithTraversal() && !this->GetCurrentDataObject()) + { + this->GoToNextItem(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataIterator::GoToNextNonEmptyLevel() +{ + if (!this->IsDoneWithTraversal()) + { + while (1) + { + this->Internal->DSIterator++; + if (this->IsDoneWithTraversal()) + { + break; + } + this->Internal->LDSIterator = this->Internal->DSIterator->begin(); + if (this->Internal->LDSIterator != this->Internal->DSIterator->end()) + { + break; + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataIterator::GoToNextItem() +{ + if (!this->DataSet) + { + vtkErrorMacro("No data object has been set."); + return; + } + if (!this->IsDoneWithTraversal()) + { + // In case the first level is empty + if (this->Internal->LDSIterator == this->Internal->DSIterator->end()) + { + this->GoToNextNonEmptyLevel(); + if (this->IsDoneWithTraversal()) + { + return; + } + } + + this->Internal->LDSIterator++; + if (this->Internal->LDSIterator == this->Internal->DSIterator->end()) + { + this->GoToNextNonEmptyLevel(); + if (this->IsDoneWithTraversal()) + { + return; + } + } + // Skip nodes with NULL dataset pointers. + if (!this->GetCurrentDataObject()) + { + this->GoToNextItem(); + } + } +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataIterator::IsDoneWithTraversal() +{ + if (!this->DataSet) + { + vtkErrorMacro("No data object has been set."); + return 1; + } + + if ( this->DataSet->Internal->DataSets.empty() || + this->Internal->DSIterator == this->DataSet->Internal->DataSets.end() ) + { + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkHierarchicalDataIterator::GetCurrentDataObject() +{ + if ( !this->DataSet || this->DataSet->Internal->DataSets.empty() ) + { + return 0; + } + return this->Internal->LDSIterator->GetPointer(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "DataSet: "; + if (this->DataSet) + { + os << endl; + this->DataSet->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)" << endl; + } +} + diff --git a/Filtering/vtkHierarchicalDataIterator.h b/Filtering/vtkHierarchicalDataIterator.h new file mode 100644 index 0000000..2e59f6f --- /dev/null +++ b/Filtering/vtkHierarchicalDataIterator.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataIterator - iterator to access datasets in a vtkHierarchicalDataIterator +// .SECTION Description +// vtkHierarchicalDataIterator is a concrete implementation of +// vtkCompositeDataIterator for vtkHierarchicalDataSet. It allows flat +// and forward access to the datasets in the hierchical dataset. + +#ifndef __vtkHierarchicalDataIterator_h +#define __vtkHierarchicalDataIterator_h + +#include "vtkCompositeDataIterator.h" + +class vtkHierarchicalDataSet; +class vtkHierarchicalDataIteratorInternal; + +class VTK_FILTERING_EXPORT vtkHierarchicalDataIterator : public vtkCompositeDataIterator +{ +public: + static vtkHierarchicalDataIterator *New(); + + vtkTypeRevisionMacro(vtkHierarchicalDataIterator,vtkCompositeDataIterator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move the iterator to the beginning of the collection. + virtual void GoToFirstItem(); + + // Description: + // Move the iterator to the next item in the collection. + virtual void GoToNextItem(); + + // Description: + // Test whether the iterator is currently pointing to a valid + // item. Returns 1 for yes, 0 for no. + virtual int IsDoneWithTraversal(); + + // Description: + // Get the current item. Valid only when IsDoneWithTraversal() + // returns 1. + virtual vtkDataObject* GetCurrentDataObject(); + + // Description: + // Set the data object to iterator over. + void SetDataSet(vtkHierarchicalDataSet* dataset); + vtkGetObjectMacro(DataSet, vtkHierarchicalDataSet); + +protected: + vtkHierarchicalDataIterator(); + virtual ~vtkHierarchicalDataIterator(); + + void GoToNextNonEmptyLevel(); + + vtkHierarchicalDataSet* DataSet; + vtkHierarchicalDataIteratorInternal* Internal; + +private: + vtkHierarchicalDataIterator(const vtkHierarchicalDataIterator&); // Not implemented. + void operator=(const vtkHierarchicalDataIterator&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkHierarchicalDataSet.cxx b/Filtering/vtkHierarchicalDataSet.cxx new file mode 100644 index 0000000..64d36bc --- /dev/null +++ b/Filtering/vtkHierarchicalDataSet.cxx @@ -0,0 +1,369 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataSet.h" + +#include "vtkDataSet.h" +#include "vtkHierarchicalDataInformation.h" +#include "vtkHierarchicalDataIterator.h" +#include "vtkHierarchicalDataSetInternal.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkInformationIntegerKey.h" + +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkHierarchicalDataSet, "$Revision: 1.7.6.1 $"); +vtkStandardNewMacro(vtkHierarchicalDataSet); + +vtkCxxSetObjectMacro(vtkHierarchicalDataSet,HierarchicalDataInformation,vtkHierarchicalDataInformation); + +vtkInformationKeyMacro(vtkHierarchicalDataSet,LEVEL,Integer); + +//---------------------------------------------------------------------------- +vtkHierarchicalDataSet::vtkHierarchicalDataSet() +{ + this->Internal = new vtkHierarchicalDataSetInternal; + this->HierarchicalDataInformation = vtkHierarchicalDataInformation::New(); +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataSet::~vtkHierarchicalDataSet() +{ + this->InitializeDataSets(); + delete this->Internal; + this->SetHierarchicalDataInformation(0); +} + +//---------------------------------------------------------------------------- +vtkCompositeDataIterator* vtkHierarchicalDataSet::NewIterator() +{ + vtkHierarchicalDataIterator* iter = vtkHierarchicalDataIterator::New(); + iter->SetDataSet(this); + return iter; +} + +//---------------------------------------------------------------------------- +vtkHDSNode* vtkHierarchicalDataSet::NewNode() +{ + return new vtkHDSNode; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::InitializeDataSets() +{ + this->Internal->DataSets.clear(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::Initialize() +{ + this->Superclass::Initialize(); + this->InitializeDataSets(); + this->SetHierarchicalDataInformation(0); + this->HierarchicalDataInformation = vtkHierarchicalDataInformation::New(); +} + +//---------------------------------------------------------------------------- +unsigned int vtkHierarchicalDataSet::GetNumberOfLevels() +{ + return this->Internal->DataSets.size(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::SetNumberOfLevels(unsigned int numLevels) +{ + this->HierarchicalDataInformation->SetNumberOfLevels(numLevels); + if (numLevels == this->GetNumberOfLevels()) + { + return; + } + this->Internal->DataSets.resize(numLevels); + this->Modified(); +} + +//---------------------------------------------------------------------------- +unsigned int vtkHierarchicalDataSet::GetNumberOfDataSets(unsigned int level) +{ + if (this->Internal->DataSets.size() <= level) + { + return 0; + } + + vtkHierarchicalDataSetInternal::LevelDataSetsType& ldataSets = + this->Internal->DataSets[level]; + + return ldataSets.size(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::SetNumberOfDataSets(unsigned int level, + unsigned int numDataSets) +{ + this->HierarchicalDataInformation->SetNumberOfDataSets(level, numDataSets); + if (numDataSets == this->GetNumberOfDataSets(level)) + { + return; + } + // Make sure that there is a vector allocated for this level + if (this->Internal->DataSets.size() <= level) + { + this->SetNumberOfLevels(level+1); + } + + vtkHierarchicalDataSetInternal::LevelDataSetsType& ldataSets = + this->Internal->DataSets[level]; + + // We need to delete all extra nodes since we manage memory for them. + unsigned int curNumDataSets = ldataSets.size(); + ldataSets.resize(numDataSets); + + // Assign NULL to all new pointers. We use this later to figure out + // whether a node allocated for a particular entry. + if (curNumDataSets < numDataSets) + { + for (unsigned int i=curNumDataSets; iModified(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::InitializeNode(unsigned int level, + unsigned int id) +{ + + // Make sure that there is a vector allocated for this level + if (this->Internal->DataSets.size() <= level) + { + this->SetNumberOfLevels(level+1); + } + + vtkHierarchicalDataSetInternal::LevelDataSetsType& ldataSets = + this->Internal->DataSets[level]; + + // Make sure that the size of the vector for this level is big enough. + if (ldataSets.size() <= id) + { + this->SetNumberOfDataSets(level, id+1); + } + + ldataSets[id] = 0; + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::SetDataSet(unsigned int level, + unsigned int id, + vtkDataObject* ds) +{ + // Make sure that there is a vector allocated for this level + if (this->Internal->DataSets.size() <= level) + { + this->SetNumberOfLevels(level+1); + } + + vtkHierarchicalDataSetInternal::LevelDataSetsType& ldataSets = + this->Internal->DataSets[level]; + + // Make sure that the size of the vector for this level is big enough. + if (ldataSets.size() <= id) + { + this->SetNumberOfDataSets(level, id+1); + } + + ldataSets[id] = ds; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::AddDataSet(vtkInformation* index, vtkDataObject* dobj) +{ + if (index->Has(INDEX()) && index->Has(LEVEL())) + { + this->SetDataSet(index->Get(LEVEL()), index->Get(INDEX()), dobj); + } +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkHierarchicalDataSet::GetDataSet(unsigned int level, + unsigned int id) +{ + if (this->Internal->DataSets.size() <= level) + { + return 0; + } + + vtkHierarchicalDataSetInternal::LevelDataSetsType& ldataSets = + this->Internal->DataSets[level]; + if (ldataSets.size() <= id) + { + return 0; + } + + if (!ldataSets[id]) + { + return 0; + } + + return ldataSets[id]; +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkHierarchicalDataSet::GetDataSet(vtkInformation* index) +{ + if (index->Has(INDEX()) && index->Has(LEVEL())) + { + return this->GetDataSet(index->Get(LEVEL()), index->Get(INDEX())); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::ShallowCopy(vtkDataObject *src) +{ + if (src == this) + { + return; + } + this->InitializeDataSets(); + this->Superclass::ShallowCopy(src); + + vtkHierarchicalDataSet* from = vtkHierarchicalDataSet::SafeDownCast(src); + if (from) + { + this->SetHierarchicalDataInformation(from->HierarchicalDataInformation); + unsigned int numLevels = from->GetNumberOfLevels(); + this->SetNumberOfLevels(numLevels); + for (unsigned int i=0; iGetNumberOfDataSets(i); + this->SetNumberOfDataSets(i, numDataSets); + for (unsigned int j=0; jSetDataSet(i, j, from->GetDataSet(i,j)); + } + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::DeepCopy(vtkDataObject *src) +{ + if (src == this) + { + return; + } + this->InitializeDataSets(); + this->Superclass::ShallowCopy(src); + this->SetHierarchicalDataInformation(0); + this->HierarchicalDataInformation = vtkHierarchicalDataInformation::New(); + + vtkHierarchicalDataSet* from = vtkHierarchicalDataSet::SafeDownCast(src); + if (from) + { + this->HierarchicalDataInformation->DeepCopy( + from->HierarchicalDataInformation); + unsigned int numLevels = from->GetNumberOfLevels(); + this->SetNumberOfLevels(numLevels); + for (unsigned int i=0; iGetNumberOfDataSets(i); + this->SetNumberOfDataSets(i, numDataSets); + for (unsigned int j=0; jGetDataSet(i,j); + if (ds) + { + vtkDataObject* copy = ds->NewInstance(); + copy->DeepCopy(ds); + this->SetDataSet(i, j, copy); + } + } + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkHierarchicalDataSet::GetNumberOfPoints() +{ + vtkIdType numPts = 0; + + vtkCompositeDataIterator* iterator = this->NewIterator(); + iterator->InitTraversal(); + while (!iterator->IsDoneWithTraversal()) + { + vtkDataObject* dObj = iterator->GetCurrentDataObject(); + if (dObj) + { + vtkDataSet* ds = vtkDataSet::SafeDownCast(dObj); + if (ds) + { + numPts += ds->GetNumberOfPoints(); + } + else + { + vtkHierarchicalDataSet* hds = + vtkHierarchicalDataSet::SafeDownCast(dObj); + if (hds) + { + numPts += hds->GetNumberOfPoints(); + } + } + } + iterator->GoToNextItem(); + } + iterator->Delete(); + + return numPts; +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataSet* vtkHierarchicalDataSet::GetData(vtkInformation* info) +{ + return + info? vtkHierarchicalDataSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataSet* +vtkHierarchicalDataSet::GetData(vtkInformationVector* v, int i) +{ + return vtkHierarchicalDataSet::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "HierarchicalDataInformation: "; + if (this->HierarchicalDataInformation) + { + os << endl; + this->HierarchicalDataInformation->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)" << endl; + } +} + diff --git a/Filtering/vtkHierarchicalDataSet.h b/Filtering/vtkHierarchicalDataSet.h new file mode 100644 index 0000000..33548ca --- /dev/null +++ b/Filtering/vtkHierarchicalDataSet.h @@ -0,0 +1,151 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataSet - abstract superclass for hierarchical datasets +// .SECTION Description +// vtkHierarchicalDataSet is a vtkCompositeDataSet that stores +// a hierarchy of datasets. The dataset collection consists of +// multiple levels. Each dataset can have an arbitrary number of +// parents and children at levels above and below. Currently, +// the interface for connecting parents-children is incomplete. + +#ifndef __vtkHierarchicalDataSet_h +#define __vtkHierarchicalDataSet_h + +#include "vtkCompositeDataSet.h" + +//BTX +struct vtkHierarchicalDataSetInternal; +//ETX +class vtkDataObject; +class vtkHDSNode; +class vtkHierarchicalDataInformation; + +class VTK_FILTERING_EXPORT vtkHierarchicalDataSet : public vtkCompositeDataSet +{ +public: + static vtkHierarchicalDataSet *New(); + + vtkTypeRevisionMacro(vtkHierarchicalDataSet,vtkCompositeDataSet); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return a new (forward) iterator + // (the iterator has to be deleted by user) + virtual vtkCompositeDataIterator* NewIterator(); + + // Description: + // Return class name of data type (see vtkSystemIncludes.h for + // definitions). + virtual int GetDataObjectType() {return VTK_HIERARCHICAL_DATA_SET;} + + // Description: + // Restore data object to initial state, + virtual void Initialize(); + + // Description: + // Set the number of refinement levels. This call might cause + // allocation if the new number of levels is larger than the + // current one. + void SetNumberOfLevels(unsigned int numLevels); + + // Description: + // Returns the number of levels. + unsigned int GetNumberOfLevels(); + + // Description: + // Set the number of datasets in a given level. This call might + // cause allocation if the new number of datasets is larger + // than the current one. + void SetNumberOfDataSets(unsigned int level, unsigned int numDataSets); + + // Description: + // Returns the number of datasets in a given level. + unsigned int GetNumberOfDataSets(unsigned int level); + + // Description: + // Initialize the entry for a dataset node. This removes all + // parent/child links between the given node and others. + void InitializeNode(unsigned int level, unsigned int id); + + // Description: + // Set the dataset pointer for a given node. This method does + // not remove the existing parent/child links. It only replaces + // the dataset pointer. + void SetDataSet(unsigned int level, unsigned int id, vtkDataObject* dataSet); + + // Description: + // Uses keys LEVEL() and INDEX() to call SetDataSet(LEVEL, INDEX, dobj) + virtual void AddDataSet(vtkInformation* index, vtkDataObject* dobj); + + // Description: + // Get a dataset give a level and an id. + vtkDataObject* GetDataSet(unsigned int level, unsigned int id); + + // Description: + // Uses keys LEVEL() and INDEX() to call GetDataSet(LEVEL, INDEX) + virtual vtkDataObject* GetDataSet(vtkInformation* index); + + // Description: + // Shallow and Deep copy. + virtual void ShallowCopy(vtkDataObject *src); + virtual void DeepCopy(vtkDataObject *src); + + // Description: + // Returns the data structure containing information about + // the datasets. + vtkGetObjectMacro(HierarchicalDataInformation,vtkHierarchicalDataInformation); + + // Description: + // Set the information about the datasets. + void SetHierarchicalDataInformation(vtkHierarchicalDataInformation* info); + + // Description: + // Returns the total number of points of all blocks. This will + // iterate over all blocks and call GetNumberOfPoints() so it + // might be expansive. + virtual vtkIdType GetNumberOfPoints(); + +//BTX + friend class vtkHierarchicalDataIterator; +//ETX + + static vtkInformationIntegerKey* LEVEL(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkHierarchicalDataSet* GetData(vtkInformation* info); + static vtkHierarchicalDataSet* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkHierarchicalDataSet(); + ~vtkHierarchicalDataSet(); + + vtkHierarchicalDataSetInternal* Internal; + + void InitializeDataSets(); + + virtual vtkHDSNode* NewNode(); + + vtkHierarchicalDataInformation* HierarchicalDataInformation; + +private: + vtkHierarchicalDataSet(const vtkHierarchicalDataSet&); // Not implemented. + void operator=(const vtkHierarchicalDataSet&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkHierarchicalDataSetAlgorithm.cxx b/Filtering/vtkHierarchicalDataSetAlgorithm.cxx new file mode 100644 index 0000000..6429538 --- /dev/null +++ b/Filtering/vtkHierarchicalDataSetAlgorithm.cxx @@ -0,0 +1,159 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkHierarchicalDataSetAlgorithm.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataSetAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkDataSet.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkHierarchicalDataSetAlgorithm, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkHierarchicalDataSetAlgorithm); + +//---------------------------------------------------------------------------- +// Instantiate object so that cell data is not passed to output. +vtkHierarchicalDataSetAlgorithm::vtkHierarchicalDataSetAlgorithm() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataSet* vtkHierarchicalDataSetAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataSet* vtkHierarchicalDataSetAlgorithm::GetOutput(int port) +{ + vtkDataObject* output = + vtkCompositeDataPipeline::SafeDownCast(this->GetExecutive())-> + GetCompositeOutputData(port); + return vtkHierarchicalDataSet::SafeDownCast(output); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSetAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSetAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkHierarchicalDataSetAlgorithm::GetInput(int port) +{ + if (this->GetNumberOfInputConnections(port) < 1) + { + return 0; + } + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataSetAlgorithm::ProcessRequest( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // create the output + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + return this->RequestDataObject(request, inputVector, outputVector); + } + + // generate the data + if(request->Has(vtkCompositeDataPipeline::REQUEST_DATA())) + { + int retVal = this->RequestData(request, inputVector, outputVector); + return retVal; + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + if(request->Has(vtkStreamingDemandDrivenPipeline::FROM_OUTPUT_PORT())) + { + int outputPort = request->Get( + vtkStreamingDemandDrivenPipeline::FROM_OUTPUT_PORT()); + vtkInformation* info = outputVector->GetInformationObject(outputPort); + if (info) + { + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1); + } + } + return this->RequestInformation(request, inputVector, outputVector); + } + + // set update extent + if(request->Has( + vtkCompositeDataPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataSetAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject"); + info->Set(vtkCompositeDataPipeline::COMPOSITE_DATA_TYPE_NAME(), + "vtkHierarchicalDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataSetAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject"); + info->Set(vtkCompositeDataPipeline::INPUT_REQUIRED_COMPOSITE_DATA_TYPE(), + "vtkHierarchicalDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkHierarchicalDataSetAlgorithm::CreateDefaultExecutive() +{ + return vtkCompositeDataPipeline::New(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataSetAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkHierarchicalDataSetAlgorithm.h b/Filtering/vtkHierarchicalDataSetAlgorithm.h new file mode 100644 index 0000000..015411d --- /dev/null +++ b/Filtering/vtkHierarchicalDataSetAlgorithm.h @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataSetAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataSetAlgorithm - Superclass for algorithms that produce only vtkHierarchicalDataSet as output +// .SECTION Description +// Algorithms that take any type of data object (including composite dataset) +// and produce a vtkHierarchicalDataSet in the output can subclass from this +// class. + + +#ifndef __vtkHierarchicalDataSetAlgorithm_h +#define __vtkHierarchicalDataSetAlgorithm_h + +#include "vtkAlgorithm.h" + +class vtkHierarchicalDataSet; + +class VTK_FILTERING_EXPORT vtkHierarchicalDataSetAlgorithm : public vtkAlgorithm +{ +public: + static vtkHierarchicalDataSetAlgorithm *New(); + vtkTypeRevisionMacro(vtkHierarchicalDataSetAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkHierarchicalDataSet* GetOutput(); + vtkHierarchicalDataSet* GetOutput(int); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject*); + void SetInput(int, vtkDataObject*); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +protected: + vtkHierarchicalDataSetAlgorithm(); + ~vtkHierarchicalDataSetAlgorithm() {}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestDataObject(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) {return 1;}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) {return 1;}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) {return 1;}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) + { + return 1; + }; + + // Create a default executive. + virtual vtkExecutive* CreateDefaultExecutive(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + + vtkDataObject *GetInput(int port); + +private: + vtkHierarchicalDataSetAlgorithm(const vtkHierarchicalDataSetAlgorithm&); // Not implemented. + void operator=(const vtkHierarchicalDataSetAlgorithm&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkHierarchicalDataSetInternal.h b/Filtering/vtkHierarchicalDataSetInternal.h new file mode 100644 index 0000000..63ce058 --- /dev/null +++ b/Filtering/vtkHierarchicalDataSetInternal.h @@ -0,0 +1,171 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataSetInternal.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataSetInternal - internal structure for vtkHierarchicalDataSet +// .SECTION Description +// vtkHierarchicalDataSetInternal is + +#ifndef __vtkHierarchicalDataSetInternal_h +#define __vtkHierarchicalDataSetInternal_h + +#include +#include + +#include "vtkDataObject.h" +#include "vtkSmartPointer.h" + +class vtkHDSNode; + +struct vtkHierarchicalDataSetInternal +{ + typedef vtkstd::vector > LevelDataSetsType; + typedef LevelDataSetsType::iterator LevelDataSetsIterator; + typedef vtkstd::vector DataSetsType; + typedef DataSetsType::iterator DataSetsIterator; + + DataSetsType DataSets; +}; + +struct vtkHDSNodeRef +{ + vtkHDSNodeRef(int level, int index) : Level(level), Index(index) {} + + vtkstd_bool operator==(const vtkHDSNodeRef& rhs) + { + return (this->Level == rhs.Level) && (this->Index == rhs.Index); + } + vtkstd_bool operator!=(const vtkHDSNodeRef& rhs) + { + return (this->Level != rhs.Level) || (this->Index != rhs.Index); + } + + int Level; + int Index; +}; + +class vtkHDSNode +{ +public: + +// void AddParent(const vtkHDSNodeRef& parent); +// void AddChild (const vtkHDSNodeRef& child ); + +// void RemoveParent(const vtkHDSNodeRef& parent); +// void RemoveChild (const vtkHDSNodeRef& child ); + +// void DisconnectFromParent(const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& parent, +// vtkHierarchicalDataSetInternal::DataSetsType& ds); +// void DisconnectFromChild (const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& child, +// vtkHierarchicalDataSetInternal::DataSetsType& ds); +// void ConnectToParent(const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& parent, +// vtkHierarchicalDataSetInternal::DataSetsType& ds); +// void ConnectToChild (const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& child, +// vtkHierarchicalDataSetInternal::DataSetsType& ds); + +// void DisconnectAll(const vtkHDSNodeRef& self, +// vtkHierarchicalDataSetInternal::DataSetsType& ds); + +protected: + vtkstd::vector Parents; + vtkstd::vector Children; +}; + +// inline void vtkHDSNode::AddParent(const vtkHDSNodeRef& parent) +// { +// this->Parents.push_back(parent); +// } + +// inline void vtkHDSNode::AddChild(const vtkHDSNodeRef& child) +// { +// this->Children.push_back(child); +// } + +// inline void vtkHDSNode::RemoveParent(const vtkHDSNodeRef& parent) +// { +// vtkstd::vector::iterator it = +// vtkstd::find(this->Parents.begin(), this->Parents.end(), parent); +// if (it != this->Parents.end()) +// { +// this->Parents.erase(it); +// } +// } + +// inline void vtkHDSNode::RemoveChild (const vtkHDSNodeRef& child) +// { +// vtkstd::vector::iterator it = +// vtkstd::find(this->Children.begin(), this->Children.end(), child); +// if (it != this->Children.end()) +// { +// this->Children.erase(it); +// } +// } + +// inline void vtkHDSNode::ConnectToParent( +// const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& parent, +// vtkHierarchicalDataSetInternal::DataSetsType& ds) +// { +// this->AddParent(parent); +// ds[parent.Level][parent.Index]->AddChild(self); +// } + +// inline void vtkHDSNode::ConnectToChild( +// const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& child, +// vtkHierarchicalDataSetInternal::DataSetsType& ds) +// { +// this->AddChild(child); +// ds[child.Level][child.Index]->AddParent(self); +// } + +// inline void vtkHDSNode::DisconnectFromParent( +// const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& parent, +// vtkHierarchicalDataSetInternal::DataSetsType& ds) +// { +// this->RemoveParent(parent); +// ds[parent.Level][parent.Index]->RemoveChild(self); +// } + +// inline void vtkHDSNode::DisconnectFromChild( +// const vtkHDSNodeRef& self, +// const vtkHDSNodeRef& child, +// vtkHierarchicalDataSetInternal::DataSetsType& ds) +// { +// this->RemoveChild(child); +// ds[child.Level][child.Index]->RemoveParent(self); +// } + +// inline void vtkHDSNode::DisconnectAll( +// const vtkHDSNodeRef& self, vtkHierarchicalDataSetInternal::DataSetsType& ds) +// { +// vtkstd::vector::iterator it; + +// for(it=this->Parents.begin(); it!=this->Parents.end(); ++it) +// { +// this->DisconnectFromParent(self, *it, ds); +// } + +// for(it=this->Children.begin(); it!=this->Children.end(); ++it) +// { +// this->DisconnectFromChild(self, *it, ds); +// } + +// } + +#endif diff --git a/Filtering/vtkImageAlgorithm.cxx b/Filtering/vtkImageAlgorithm.cxx new file mode 100644 index 0000000..5d0c344 --- /dev/null +++ b/Filtering/vtkImageAlgorithm.cxx @@ -0,0 +1,408 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageAlgorithm.h" + +#include "vtkObjectFactory.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageAlgorithm, "$Revision: 1.25.4.1 $"); + +//---------------------------------------------------------------------------- +vtkImageAlgorithm::vtkImageAlgorithm() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//---------------------------------------------------------------------------- +vtkImageAlgorithm::~vtkImageAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkImageAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + if (outInfo) + { + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + } + else + { + this->ExecuteData(NULL); + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + // propagate update extent + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkImageAlgorithm::ExecuteData(vtkDataObject *) +{ + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::CopyInputArrayAttributesToOutput +(vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // for image data to image data + if (this->GetNumberOfInputPorts() && this->GetNumberOfOutputPorts()) + { + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + // if the input is image data + if (vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()))) + { + vtkInformation *info = + this->GetInputArrayFieldInformation(0, inputVector); + if (info) + { + int scalarType = info->Get( vtkDataObject::FIELD_ARRAY_TYPE()); + int numComp = info->Get( vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()); + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* outInfo = outputVector->GetInformationObject(i); + // if the output is image data + if (vtkImageData::SafeDownCast + (outInfo->Get(vtkDataObject::DATA_OBJECT()))) + { + // copy scalar type and scalar number of components + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, + scalarType, numComp); + } + } + } + } + } +} + +//---------------------------------------------------------------------------- +int vtkImageAlgorithm::RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // do nothing except copy scalar type info + this->CopyInputArrayAttributesToOutput(request,inputVector,outputVector); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageAlgorithm::RequestUpdateExtent( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* vtkNotUsed(outputVector)) +{ + // do nothing let subclasses handle it + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::AllocateOutputData(vtkImageData *output, + int *uExtent) +{ + // set the extent to be the update extent + output->SetExtent(uExtent); + output->AllocateScalars(); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageAlgorithm::AllocateOutputData(vtkDataObject *output) +{ + // set the extent to be the update extent + vtkImageData *out = vtkImageData::SafeDownCast(output); + if (out) + { + // this needs to be fixed -Ken + vtkStreamingDemandDrivenPipeline *sddp = + vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); + if (sddp) + { + int extent[6]; + sddp->GetOutputInformation(0)->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),extent); + out->SetExtent(extent); + } + out->AllocateScalars(); + } + return out; +} + +//---------------------------------------------------------------------------- +// by default copy the attr from the first input to the first output +void vtkImageAlgorithm::CopyAttributeData(vtkImageData *input, + vtkImageData *output, + vtkInformationVector **inputVector) +{ + if (!input || !output) + { + return; + } + + int inExt[6]; + int outExt[6]; + vtkDataArray *inArray; + vtkDataArray *outArray; + + input->GetExtent(inExt); + output->GetExtent(outExt); + + // Do not copy the array we will be generating. + inArray = this->GetInputArrayToProcess(0,inputVector); + + // Conditionally copy point and cell data. Only copy if corresponding + // indexes refer to identical points. + double *oIn = input->GetOrigin(); + double *sIn = input->GetSpacing(); + double *oOut = output->GetOrigin(); + double *sOut = output->GetSpacing(); + if (oIn[0] == oOut[0] && oIn[1] == oOut[1] && oIn[2] == oOut[2] && + sIn[0] == sOut[0] && sIn[1] == sOut[1] && sIn[2] == sOut[2]) + { + output->GetPointData()->CopyAllOn(); + output->GetCellData()->CopyAllOn(); + output->GetPointData()->CopyScalarsOff(); + + // If the extents are the same, then pass the attribute data for + // efficiency. + if (inExt[0] == outExt[0] && inExt[1] == outExt[1] && + inExt[2] == outExt[2] && inExt[3] == outExt[3] && + inExt[4] == outExt[4] && inExt[5] == outExt[5]) + {// Pass + // set the name of the output to match the input name + outArray = output->GetPointData()->GetScalars(); + if (inArray) + { + outArray->SetName(inArray->GetName()); + } + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + } + else + {// Copy + // Since this can be expensive to copy all of these values, + // lets make sure there are arrays to copy (other than the scalars) + if (input->GetPointData()->GetNumberOfArrays() > 1) + { + // Copy the point data. + // CopyAllocate frees all arrays. + // Keep the old scalar array (not being copied). + // This is a hack, but avoids reallocation ... + vtkDataArray *tmp = NULL; + if ( ! output->GetPointData()->GetCopyScalars() ) + { + tmp = output->GetPointData()->GetScalars(); + // set the name of the output to match the input name + if (inArray) + { + tmp->SetName(inArray->GetName()); + } + } + output->GetPointData()->CopyAllocate(input->GetPointData(), + output->GetNumberOfPoints()); + if (tmp) + { // Restore the array. + output->GetPointData()->SetScalars(tmp); + } + // Now Copy The point data, but only if output is a subextent of the + // input. + if (outExt[0] >= inExt[0] && outExt[1] <= inExt[1] && + outExt[2] >= inExt[2] && outExt[3] <= inExt[3] && + outExt[4] >= inExt[4] && outExt[5] <= inExt[5]) + { + output->GetPointData()->CopyStructuredData(input->GetPointData(), + inExt, outExt); + } + } + + if (input->GetCellData()->GetNumberOfArrays() > 0) + { + output->GetCellData()->CopyAllocate(input->GetCellData(), + output->GetNumberOfCells()); + // Cell extent is one less than point extent. + // Conditional to handle a colapsed axis (lower dimensional cells). + if (inExt[0] < inExt[1]) {--inExt[1];} + if (inExt[2] < inExt[3]) {--inExt[3];} + if (inExt[4] < inExt[5]) {--inExt[5];} + // Cell extent is one less than point extent. + if (outExt[0] < outExt[1]) {--outExt[1];} + if (outExt[2] < outExt[3]) {--outExt[3];} + if (outExt[4] < outExt[5]) {--outExt[5];} + // Now Copy The cell data, but only if output is a subextent of the input. + if (outExt[0] >= inExt[0] && outExt[1] <= inExt[1] && + outExt[2] >= inExt[2] && outExt[3] <= inExt[3] && + outExt[4] >= inExt[4] && outExt[5] <= inExt[5]) + { + output->GetCellData()->CopyStructuredData(input->GetCellData(), + inExt, outExt); + } + } + } + } +} + + +//---------------------------------------------------------------------------- +vtkImageData* vtkImageAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkImageAlgorithm::GetOutput(int port) +{ + return vtkImageData::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +int vtkImageAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkImageAlgorithm::GetInput(int port) +{ + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkImageAlgorithm::GetImageDataInput(int port) +{ + return vtkImageData::SafeDownCast(this->GetInput(port)); +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkImageAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} diff --git a/Filtering/vtkImageAlgorithm.h b/Filtering/vtkImageAlgorithm.h new file mode 100644 index 0000000..3b5fa14 --- /dev/null +++ b/Filtering/vtkImageAlgorithm.h @@ -0,0 +1,132 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageAlgorithm - Generic algorithm superclass for image algs +// .SECTION Description +// vtkImageToImageAlgorithm is a filter superclass that hides much of the +// pipeline complexity. It handles breaking the pipeline execution +// into smaller extents so that the vtkImageData limits are observed. It +// also provides support for multithreading. If you don't need any of this +// functionality, consider using vtkSimpleImageToImageAlgorithm instead. +// .SECTION See also +// vtkSimpleImageToImageAlgorithm + +#ifndef __vtkImageAlgorithm_h +#define __vtkImageAlgorithm_h + +#include "vtkAlgorithm.h" + +class vtkDataSet; +class vtkImageData; + +class VTK_FILTERING_EXPORT vtkImageAlgorithm : public vtkAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImageAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkImageData* GetOutput(); + vtkImageData* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject *GetInput(int port); + vtkDataObject *GetInput() { return this->GetInput(0); }; + vtkImageData *GetImageDataInput(int port); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + virtual void AddInput(vtkDataObject *); + virtual void AddInput(int, vtkDataObject*); + +protected: + vtkImageAlgorithm(); + ~vtkImageAlgorithm(); + + // convenience method + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // convenience method to copy the selected scalars type and num components + // to the output info. Call this from inside your RequestInformation + virtual void CopyInputArrayAttributesToOutput(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // just allocate the output data + virtual void AllocateOutputData(vtkImageData *out, + int *uExtent); + virtual vtkImageData *AllocateOutputData(vtkDataObject *out); + + // copy the other point and cell data + virtual void CopyAttributeData(vtkImageData *in, vtkImageData *out, + vtkInformationVector** inputVector); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkImageAlgorithm(const vtkImageAlgorithm&); // Not implemented. + void operator=(const vtkImageAlgorithm&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkImageData.cxx b/Filtering/vtkImageData.cxx new file mode 100644 index 0000000..aaec8f0 --- /dev/null +++ b/Filtering/vtkImageData.cxx @@ -0,0 +1,2125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageData.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkExtentTranslator.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationVector.h" +#include "vtkLargeInteger.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPixel.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkVertex.h" +#include "vtkVoxel.h" + +vtkCxxRevisionMacro(vtkImageData, "$Revision: 1.15.4.2 $"); +vtkStandardNewMacro(vtkImageData); + +//---------------------------------------------------------------------------- +vtkImageData::vtkImageData() +{ + int idx; + + this->Vertex = vtkVertex::New(); + this->Line = vtkLine::New(); + this->Pixel = vtkPixel::New(); + this->Voxel = vtkVoxel::New(); + + this->DataDescription = VTK_EMPTY; + + for (idx = 0; idx < 3; ++idx) + { + this->Dimensions[idx] = 0; + this->Increments[idx] = 0; + this->Origin[idx] = 0.0; + this->Spacing[idx] = 1.0; + } + this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_3D_EXTENT); + this->Information->Set(vtkDataObject::DATA_EXTENT(), this->Extent, 6); + + int extent[6] = {0, -1, 0, -1, 0, -1}; + memcpy(this->Extent, extent, 6*sizeof(int)); + +} + +//---------------------------------------------------------------------------- +vtkImageData::~vtkImageData() +{ + this->Vertex->Delete(); + this->Line->Delete(); + this->Pixel->Delete(); + this->Voxel->Delete(); +} + +//---------------------------------------------------------------------------- +// Copy the geometric and topological structure of an input structured points +// object. +void vtkImageData::CopyStructure(vtkDataSet *ds) +{ + vtkImageData *sPts=(vtkImageData *)ds; + this->Initialize(); + + int i; + for (i=0; i<3; i++) + { + this->Dimensions[i] = sPts->Dimensions[i]; + this->Spacing[i] = sPts->Spacing[i]; + this->Origin[i] = sPts->Origin[i]; + } + this->SetExtent(sPts->GetExtent()); + + vtkInformation* thisPInfo = this->GetPipelineInformation(); + vtkInformation* thatPInfo = ds->GetPipelineInformation(); + if(thisPInfo && thatPInfo) + { + // copy point data. + if (thatPInfo->Has(POINT_DATA_VECTOR())) + { + thisPInfo->CopyEntry(thatPInfo, POINT_DATA_VECTOR()); + } + // copy cell data. + if (thatPInfo->Has(CELL_DATA_VECTOR())) + { + thisPInfo->CopyEntry(thatPInfo, CELL_DATA_VECTOR()); + } + } + this->DataDescription = sPts->DataDescription; + this->CopyInformation(sPts); +} + +//---------------------------------------------------------------------------- +void vtkImageData::Initialize() +{ + this->Superclass::Initialize(); + if(this->Information) + { + this->SetDimensions(0,0,0); + } +} + + +//---------------------------------------------------------------------------- +void vtkImageData::CopyInformationToPipeline(vtkInformation* request, + vtkInformation* input) +{ + // Let the superclass copy whatever it wants. + this->Superclass::CopyInformationToPipeline(request, input); + + // Set default pipeline information during a request for information. + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + // Copy settings from the input if available. Otherwise use our + // current settings. + vtkInformation* output = this->PipelineInformation; + + if(input && input->Has(ORIGIN())) + { + output->CopyEntry(input, ORIGIN()); + } + else if (!output->Has(ORIGIN())) + { + // Set origin (only if it is not set). + output->Set(ORIGIN(), this->GetOrigin(), 3); + } + + if(input && input->Has(SPACING())) + { + output->CopyEntry(input, SPACING()); + } + else if (!output->Has(SPACING())) + { + // Set spacing (only if it is not set). + output->Set(SPACING(), this->GetSpacing(), 3); + } + + // copy of input to output (if input exists) occurs in vtkDataObject, so + // only to to check need to check if the scalar info exists in the field + // data info of the output. If it exists, then we assume the type and + // number of components are set; if not, set type and number of components + // to default values + vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(output, + FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!scalarInfo) + { + vtkDataObject::SetPointDataActiveScalarInfo(output, VTK_DOUBLE, 1); + } + } +} + +//---------------------------------------------------------------------------- +void vtkImageData::CopyInformationFromPipeline(vtkInformation* request) +{ + // Let the superclass copy whatever it wants. + this->Superclass::CopyInformationFromPipeline(request); + + // Copy pipeline information to data information before the producer + // executes. + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->CopyOriginAndSpacingFromPipeline(); + } +} + +//---------------------------------------------------------------------------- +// Graphics filters reallocate every execute. Image filters try to reuse +// the scalars. +void vtkImageData::PrepareForNewData() +{ + // free everything but the scalars + vtkDataArray *scalars = this->GetPointData()->GetScalars(); + if (scalars) + { + scalars->Register(this); + } + this->Initialize(); + if (scalars) + { + this->GetPointData()->SetScalars(scalars); + scalars->UnRegister(this); + } +} + + +//---------------------------------------------------------------------------- + +// The input data object must be of type vtkImageData or a subclass! +void vtkImageData::CopyTypeSpecificInformation( vtkDataObject *data ) +{ + vtkImageData *image = (vtkImageData *)data; + + // Copy the generic stuff + this->CopyInformation( data ); + + // Now do the specific stuff + this->SetOrigin( image->GetOrigin() ); + this->SetSpacing( image->GetSpacing() ); + this->SetScalarType( image->GetScalarType() ); + this->SetNumberOfScalarComponents( + image->GetNumberOfScalarComponents() ); +} + +//---------------------------------------------------------------------------- +template +unsigned long vtkImageDataGetTypeSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- + +unsigned long vtkImageData::GetEstimatedMemorySize() +{ + vtkLargeInteger size; + int idx; + int *uExt; + unsigned long lsize; + + // Start with the number of scalar components + size = (unsigned long)(this->GetNumberOfScalarComponents()); + + // Multiply by the number of bytes per scalar + switch (this->GetScalarType()) + { + vtkTemplateMacro( + size *= vtkImageDataGetTypeSize(static_cast(0)) + ); + case VTK_BIT: + size = size / 8; + break; + default: + vtkWarningMacro(<< "GetExtentMemorySize: " + << "Cannot determine input scalar type"); + } + + // Multiply by the number of scalars. + uExt = this->GetUpdateExtent(); + for (idx = 0; idx < 3; ++idx) + { + size = size*(uExt[idx*2+1] - uExt[idx*2] + 1); + } + + // In case the extent is set improperly, set the size to 0 + if (size < 0) + { + vtkWarningMacro("Oops, size should not be negative."); + size = 0; + } + + // Convert from double bytes to unsigned long kilobytes + size = size >> 10; + lsize = size.CastToUnsignedLong(); + return lsize; +} + +//---------------------------------------------------------------------------- + +vtkCell *vtkImageData::GetCell(vtkIdType cellId) +{ + vtkCell *cell = NULL; + int loc[3]; + vtkIdType idx, npts; + int iMin, iMax, jMin, jMax, kMin, kMax; + double x[3]; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + const int* extent = this->Extent; + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + + int d01 = dims[0]*dims[1]; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0) + { + vtkErrorMacro("Requesting a cell from an empty image."); + return NULL; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + //cell = this->EmptyCell; + return NULL; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell = this->Vertex; + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + cell = this->Line; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + cell = this->Line; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + cell = this->Line; + break; + + case VTK_XY_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + jMin = cellId / (dims[0]-1); + jMax = jMin + 1; + cell = this->Pixel; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (dims[1]-1); + jMax = jMin + 1; + kMin = cellId / (dims[1]-1); + kMax = kMin + 1; + cell = this->Pixel; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + kMin = cellId / (dims[0]-1); + kMax = kMin + 1; + cell = this->Pixel; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (dims[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((dims[0] - 1) * (dims[1] - 1)); + kMax = kMin + 1; + cell = this->Voxel; + break; + } + + // Extract point coordinates and point ids + // Ids are relative to extent min. + npts = 0; + for (loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2]; + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1]; + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0]; + + idx = loc[0] + loc[1]*dims[0] + loc[2]*d01; + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,x); + } + } + } + + return cell; +} + +//---------------------------------------------------------------------------- +void vtkImageData::GetCell(vtkIdType cellId, vtkGenericCell *cell) +{ + vtkIdType npts, idx; + int loc[3]; + int iMin, iMax, jMin, jMax, kMin, kMax; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + double x[3]; + const int* extent = this->Extent; + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + int d01 = dims[0]*dims[1]; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0) + { + vtkErrorMacro("Requesting a cell from an empty image."); + cell->SetCellTypeToEmptyCell(); + return; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + cell->SetCellTypeToEmptyCell(); + return; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell->SetCellTypeToVertex(); + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_XY_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + jMin = cellId / (dims[0]-1); + jMax = jMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_YZ_PLANE: + jMin = cellId % (dims[1]-1); + jMax = jMin + 1; + kMin = cellId / (dims[1]-1); + kMax = kMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_XZ_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + kMin = cellId / (dims[0]-1); + kMax = kMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_XYZ_GRID: + iMin = cellId % (dims[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((dims[0] - 1) * (dims[1] - 1)); + kMax = kMin + 1; + cell->SetCellTypeToVoxel(); + break; + } + + // Extract point coordinates and point ids + for (npts=0,loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2]; + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1]; + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0]; + + idx = loc[0] + loc[1]*dims[0] + loc[2]*d01; + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,x); + } + } + } +} + + +//---------------------------------------------------------------------------- +// Fast implementation of GetCellBounds(). Bounds are calculated without +// constructing a cell. +void vtkImageData::GetCellBounds(vtkIdType cellId, double bounds[6]) +{ + int loc[3], iMin, iMax, jMin, jMax, kMin, kMax; + double x[3]; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + const int* extent = this->Extent; + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0) + { + vtkErrorMacro("Requesting cell bounds from an empty image."); + bounds[0] = bounds[1] = bounds[2] = bounds[3] + = bounds[4] = bounds[5] = 0.0; + return; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + return; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + break; + + case VTK_XY_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + jMin = cellId / (dims[0]-1); + jMax = jMin + 1; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (dims[1]-1); + jMax = jMin + 1; + kMin = cellId / (dims[1]-1); + kMax = kMin + 1; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + kMin = cellId / (dims[0]-1); + kMax = kMin + 1; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (dims[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((dims[0] - 1) * (dims[1] - 1)); + kMax = kMin + 1; + break; + } + + + // carefully compute the bounds + if (kMax >= kMin && jMax >= jMin && iMax >= iMin) + { + bounds[0] = bounds[2] = bounds[4] = VTK_DOUBLE_MAX; + bounds[1] = bounds[3] = bounds[5] = -VTK_DOUBLE_MAX; + + // Extract point coordinates + for (loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2]; + bounds[4] = (x[2] < bounds[4] ? x[2] : bounds[4]); + bounds[5] = (x[2] > bounds[5] ? x[2] : bounds[5]); + } + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1]; + bounds[2] = (x[1] < bounds[2] ? x[1] : bounds[2]); + bounds[3] = (x[1] > bounds[3] ? x[1] : bounds[3]); + } + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0]; + bounds[0] = (x[0] < bounds[0] ? x[0] : bounds[0]); + bounds[1] = (x[0] > bounds[1] ? x[0] : bounds[1]); + } + } + else + { + vtkMath::UninitializeBounds(bounds); + } +} + +//---------------------------------------------------------------------------- +double *vtkImageData::GetPoint(vtkIdType ptId) +{ + static double x[3]; + int i, loc[3]; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + const int* extent = this->Extent; + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + + x[0] = x[1] = x[2] = 0.0; + if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0) + { + vtkErrorMacro("Requesting a point from an empty image."); + return x; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + return x; + + case VTK_SINGLE_POINT: + loc[0] = loc[1] = loc[2] = 0; + break; + + case VTK_X_LINE: + loc[1] = loc[2] = 0; + loc[0] = ptId; + break; + + case VTK_Y_LINE: + loc[0] = loc[2] = 0; + loc[1] = ptId; + break; + + case VTK_Z_LINE: + loc[0] = loc[1] = 0; + loc[2] = ptId; + break; + + case VTK_XY_PLANE: + loc[2] = 0; + loc[0] = ptId % dims[0]; + loc[1] = ptId / dims[0]; + break; + + case VTK_YZ_PLANE: + loc[0] = 0; + loc[1] = ptId % dims[1]; + loc[2] = ptId / dims[1]; + break; + + case VTK_XZ_PLANE: + loc[1] = 0; + loc[0] = ptId % dims[0]; + loc[2] = ptId / dims[0]; + break; + + case VTK_XYZ_GRID: + loc[0] = ptId % dims[0]; + loc[1] = (ptId / dims[0]) % dims[1]; + loc[2] = ptId / (dims[0]*dims[1]); + break; + } + + for (i=0; i<3; i++) + { + x[i] = origin[i] + (loc[i]+extent[i*2]) * spacing[i]; + } + + return x; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkImageData::FindPoint(double x[3]) +{ + int i, loc[3]; + double d; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + const int* extent = this->Extent; + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + + // + // Compute the ijk location + // + for (i=0; i<3; i++) + { + d = x[i] - origin[i]; + loc[i] = (int) ((d / spacing[i]) + 0.5); + if ( loc[i] < extent[i*2] || loc[i] > extent[i*2+1] ) + { + return -1; + } + // since point id is relative to the first point actually stored + loc[i] -= extent[i*2]; + } + // + // From this location get the point id + // + return loc[2]*dims[0]*dims[1] + loc[1]*dims[0] + loc[0]; + +} + +//---------------------------------------------------------------------------- +vtkIdType vtkImageData::FindCell(double x[3], vtkCell *vtkNotUsed(cell), + vtkGenericCell *vtkNotUsed(gencell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), + int& subId, double pcoords[3], + double *weights) +{ + return + this->FindCell( x, (vtkCell *)NULL, 0, 0.0, subId, pcoords, weights ); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkImageData::FindCell(double x[3], vtkCell *vtkNotUsed(cell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), + int& subId, double pcoords[3], double *weights) +{ + int loc[3]; + int *dims = this->GetDimensions(); + + if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 ) + { + return -1; + } + + vtkVoxel::InterpolationFunctions(pcoords,weights); + + // + // From this location get the cell id + // + subId = 0; + return loc[2] * (dims[0]-1)*(dims[1]-1) + + loc[1] * (dims[0]-1) + loc[0]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkImageData::FindAndGetCell(double x[3], + vtkCell *vtkNotUsed(cell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), int& subId, + double pcoords[3], double *weights) +{ + int i, j, k, loc[3]; + vtkIdType npts, idx; + double xOut[3]; + int iMax = 0; + int jMax = 0; + int kMax = 0;; + vtkCell *cell = NULL; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + const int* extent = this->Extent; + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + vtkIdType d01 = dims[0]*dims[1]; + + if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 ) + { + return NULL; + } + + // + // Get the parametric coordinates and weights for interpolation + // + switch (this->DataDescription) + { + case VTK_EMPTY: + return NULL; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + vtkVertex::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1]; + kMax = loc[2]; + cell = this->Vertex; + break; + + case VTK_X_LINE: + vtkLine::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1]; + kMax = loc[2]; + cell = this->Line; + break; + + case VTK_Y_LINE: + vtkLine::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1] + 1; + kMax = loc[2]; + cell = this->Line; + break; + + case VTK_Z_LINE: + vtkLine::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1]; + kMax = loc[2] + 1; + cell = this->Line; + break; + + case VTK_XY_PLANE: + vtkPixel::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1] + 1; + kMax = loc[2]; + cell = this->Pixel; + break; + + case VTK_YZ_PLANE: + vtkPixel::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1] + 1; + kMax = loc[2] + 1; + cell = this->Pixel; + break; + + case VTK_XZ_PLANE: + vtkPixel::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1]; + kMax = loc[2] + 1; + cell = this->Pixel; + break; + + case VTK_XYZ_GRID: + vtkVoxel::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1] + 1; + kMax = loc[2] + 1; + cell = this->Voxel; + break; + } + + npts = 0; + for (k = loc[2]; k <= kMax; k++) + { + xOut[2] = origin[2] + k * spacing[2]; + for (j = loc[1]; j <= jMax; j++) + { + xOut[1] = origin[1] + j * spacing[1]; + // make idx relative to the extent not the whole extent + idx = loc[0]-extent[0] + (j-extent[2])*dims[0] + + (k-extent[4])*d01; + for (i = loc[0]; i <= iMax; i++, idx++) + { + xOut[0] = origin[0] + i * spacing[0]; + + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,xOut); + } + } + } + subId = 0; + + return cell; +} + +//---------------------------------------------------------------------------- +int vtkImageData::GetCellType(vtkIdType vtkNotUsed(cellId)) +{ + switch (this->DataDescription) + { + case VTK_EMPTY: + return VTK_EMPTY_CELL; + + case VTK_SINGLE_POINT: + return VTK_VERTEX; + + case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: + return VTK_LINE; + + case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: + return VTK_PIXEL; + + case VTK_XYZ_GRID: + return VTK_VOXEL; + + default: + vtkErrorMacro(<<"Bad data description!"); + return VTK_EMPTY_CELL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageData::ComputeBounds() +{ + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + const int* extent = this->Extent; + + if ( extent[0] > extent[1] || + extent[2] > extent[3] || + extent[4] > extent[5] ) + { + vtkMath::UninitializeBounds(this->Bounds); + return; + } + + int swapXBounds = (spacing[0] < 0); // 1 if true, 0 if false + int swapYBounds = (spacing[1] < 0); // 1 if true, 0 if false + int swapZBounds = (spacing[2] < 0); // 1 if true, 0 if false + + this->Bounds[0] = origin[0] + (extent[0+swapXBounds] * spacing[0]); + this->Bounds[2] = origin[1] + (extent[2+swapYBounds] * spacing[1]); + this->Bounds[4] = origin[2] + (extent[4+swapZBounds] * spacing[2]); + + this->Bounds[1] = origin[0] + (extent[1-swapXBounds] * spacing[0]); + this->Bounds[3] = origin[1] + (extent[3-swapYBounds] * spacing[1]); + this->Bounds[5] = origin[2] + (extent[5-swapZBounds] * spacing[2]); +} + +//---------------------------------------------------------------------------- +// Given structured coordinates (i,j,k) for a voxel cell, compute the eight +// gradient values for the voxel corners. The order in which the gradient +// vectors are arranged corresponds to the ordering of the voxel points. +// Gradient vector is computed by central differences (except on edges of +// volume where forward difference is used). The scalars s are the scalars +// from which the gradient is to be computed. This method will treat +// only 3D structured point datasets (i.e., volumes). +void vtkImageData::GetVoxelGradient(int i, int j, int k, vtkDataArray *s, + vtkDataArray *g) +{ + double gv[3]; + int ii, jj, kk, idx=0; + + for ( kk=0; kk < 2; kk++) + { + for ( jj=0; jj < 2; jj++) + { + for ( ii=0; ii < 2; ii++) + { + this->GetPointGradient(i+ii, j+jj, k+kk, s, gv); + g->SetTuple(idx++, gv); + } + } + } +} + +//---------------------------------------------------------------------------- +// Given structured coordinates (i,j,k) for a point in a structured point +// dataset, compute the gradient vector from the scalar data at that point. +// The scalars s are the scalars from which the gradient is to be computed. +// This method will treat structured point datasets of any dimension. +void vtkImageData::GetPointGradient(int i,int j,int k, vtkDataArray *s, + double g[3]) +{ + int *dims=this->GetDimensions(); + double *ar=this->GetSpacing(); + vtkIdType ijsize=dims[0]*dims[1]; + double sp, sm; + + // x-direction + if ( dims[0] == 1 ) + { + g[0] = 0.0; + } + else if ( i == 0 ) + { + sp = s->GetComponent(i+1 + j*dims[0] + k*ijsize, 0); + sm = s->GetComponent(i + j*dims[0] + k*ijsize, 0); + g[0] = (sm - sp) / ar[0]; + } + else if ( i == (dims[0]-1) ) + { + sp = s->GetComponent(i + j*dims[0] + k*ijsize,0); + sm = s->GetComponent(i-1 + j*dims[0] + k*ijsize,0); + g[0] = (sm - sp) / ar[0]; + } + else + { + sp = s->GetComponent(i+1 + j*dims[0] + k*ijsize,0); + sm = s->GetComponent(i-1 + j*dims[0] + k*ijsize,0); + g[0] = 0.5 * (sm - sp) / ar[0]; + } + + // y-direction + if ( dims[1] == 1 ) + { + g[1] = 0.0; + } + else if ( j == 0 ) + { + sp = s->GetComponent(i + (j+1)*dims[0] + k*ijsize,0); + sm = s->GetComponent(i + j*dims[0] + k*ijsize,0); + g[1] = (sm - sp) / ar[1]; + } + else if ( j == (dims[1]-1) ) + { + sp = s->GetComponent(i + j*dims[0] + k*ijsize,0); + sm = s->GetComponent(i + (j-1)*dims[0] + k*ijsize,0); + g[1] = (sm - sp) / ar[1]; + } + else + { + sp = s->GetComponent(i + (j+1)*dims[0] + k*ijsize,0); + sm = s->GetComponent(i + (j-1)*dims[0] + k*ijsize,0); + g[1] = 0.5 * (sm - sp) / ar[1]; + } + + // z-direction + if ( dims[2] == 1 ) + { + g[2] = 0.0; + } + else if ( k == 0 ) + { + sp = s->GetComponent(i + j*dims[0] + (k+1)*ijsize,0); + sm = s->GetComponent(i + j*dims[0] + k*ijsize,0); + g[2] = (sm - sp) / ar[2]; + } + else if ( k == (dims[2]-1) ) + { + sp = s->GetComponent(i + j*dims[0] + k*ijsize,0); + sm = s->GetComponent(i + j*dims[0] + (k-1)*ijsize,0); + g[2] = (sm - sp) / ar[2]; + } + else + { + sp = s->GetComponent(i + j*dims[0] + (k+1)*ijsize,0); + sm = s->GetComponent(i + j*dims[0] + (k-1)*ijsize,0); + g[2] = 0.5 * (sm - sp) / ar[2]; + } +} + +//---------------------------------------------------------------------------- +// Set dimensions of structured points dataset. +void vtkImageData::SetDimensions(int i, int j, int k) +{ + this->SetExtent(0, i-1, 0, j-1, 0, k-1); +} + +//---------------------------------------------------------------------------- +// Set dimensions of structured points dataset. +void vtkImageData::SetDimensions(int dim[3]) +{ + this->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); +} + + +// streaming change: ijk is in extent coordinate system. +//---------------------------------------------------------------------------- +// Convenience function computes the structured coordinates for a point x[3]. +// The voxel is specified by the array ijk[3], and the parametric coordinates +// in the cell are specified with pcoords[3]. The function returns a 0 if the +// point x is outside of the volume, and a 1 if inside the volume. +int vtkImageData::ComputeStructuredCoordinates(double x[3], int ijk[3], + double pcoords[3]) +{ + int i; + double d, doubleLoc; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + const int* extent = this->Extent; + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + + // + // Compute the ijk location + // + for (i=0; i<3; i++) + { + d = x[i] - origin[i]; + doubleLoc = d / spacing[i]; + // Floor for negtive indexes. + ijk[i] = (int) (floor(doubleLoc)); + if ( ijk[i] >= extent[i*2] && ijk[i] < extent[i*2 + 1] ) + { + pcoords[i] = doubleLoc - (double)ijk[i]; + } + + else if ( ijk[i] < extent[i*2] || ijk[i] > extent[i*2+1] ) + { + return 0; + } + + else //if ( ijk[i] == extent[i*2+1] ) + { + if (dims[i] == 1) + { + pcoords[i] = 0.0; + } + else + { + ijk[i] -= 1; + pcoords[i] = 1.0; + } + } + + } + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkImageData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + int *dims = this->GetDimensions(); + const int* extent = this->Extent; + + os << indent << "ScalarType: " << this->GetScalarType() << endl; + os << indent << "NumberOfScalarComponents: " << + this->GetNumberOfScalarComponents() << endl; + os << indent << "Spacing: (" << this->Spacing[0] << ", " + << this->Spacing[1] << ", " + << this->Spacing[2] << ")\n"; + os << indent << "Origin: (" << this->Origin[0] << ", " + << this->Origin[1] << ", " + << this->Origin[2] << ")\n"; + os << indent << "Dimensions: (" << dims[0] << ", " + << dims[1] << ", " + << dims[2] << ")\n"; + os << indent << "Increments: (" << this->Increments[0] << ", " + << this->Increments[1] << ", " + << this->Increments[2] << ")\n"; + os << indent << "Extent: (" << extent[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << extent[idx]; + } + os << ")\n"; +} + +//---------------------------------------------------------------------------- +void vtkImageData::UpdateInformation() +{ + // Use the compatibility method in the superclass to update the + // information. + this->Superclass::UpdateInformation(); + + // Now copy the information the caller is probably expecting to get + // from this data object instead of the pipeline information. This + // preserves compatibility. + this->CopyOriginAndSpacingFromPipeline(); +} + +//---------------------------------------------------------------------------- +void vtkImageData::SetNumberOfScalarComponents(int num) +{ + this->GetProducerPort(); + if(vtkInformation* info = this->GetPipelineInformation()) + { + vtkDataObject::SetPointDataActiveScalarInfo(info, -1, num); + } + else + { + vtkErrorMacro("SetNumberOfScalarComponents called with no " + "executive producing this image data object."); + } + this->ComputeIncrements(); +} + +//---------------------------------------------------------------------------- +int vtkImageData::GetNumberOfScalarComponents() +{ + this->GetProducerPort(); + if(vtkInformation* info = this->GetPipelineInformation()) + { + vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(info, + FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (scalarInfo && scalarInfo->Has(FIELD_NUMBER_OF_COMPONENTS())) + { + return scalarInfo->Get( FIELD_NUMBER_OF_COMPONENTS() ); + } + } + return 1; +} + +//---------------------------------------------------------------------------- +vtkIdType *vtkImageData::GetIncrements() +{ + // Make sure the increments are up to date. The filter bypass and update + // mechanism make it tricky to update the increments anywhere other than here + this->ComputeIncrements(); + + return this->Increments; +} + +void vtkImageData::GetIncrements(vtkIdType &incX, vtkIdType &incY, vtkIdType &incZ) +{ + // Make sure the increments are up to date. The filter bypass and update + // mechanism make it tricky to update the increments anywhere other than here + this->ComputeIncrements(); + + incX = this->Increments[0]; + incY = this->Increments[1]; + incZ = this->Increments[2]; +} + +void vtkImageData::GetIncrements(vtkIdType inc[3]) +{ + // Make sure the increments are up to date. The filter bypass and update + // mechanism make it tricky to update the increments anywhere other than here + this->ComputeIncrements(); + + inc[0] = this->Increments[0]; + inc[1] = this->Increments[1]; + inc[2] = this->Increments[2]; +} + + +//---------------------------------------------------------------------------- +void vtkImageData::GetContinuousIncrements(int extent[6], vtkIdType &incX, + vtkIdType &incY, vtkIdType &incZ) +{ + int e0, e1, e2, e3; + + incX = 0; + const int* selfExtent = this->Extent; + + e0 = extent[0]; + if (e0 < selfExtent[0]) + { + e0 = selfExtent[0]; + } + e1 = extent[1]; + if (e1 > selfExtent[1]) + { + e1 = selfExtent[1]; + } + e2 = extent[2]; + if (e2 < selfExtent[2]) + { + e2 = selfExtent[2]; + } + e3 = extent[3]; + if (e3 > selfExtent[3]) + { + e3 = selfExtent[3]; + } + + // Make sure the increments are up to date + this->ComputeIncrements(); + + incY = this->Increments[1] - (e1 - e0 + 1)*this->Increments[0]; + incZ = this->Increments[2] - (e3 - e2 + 1)*this->Increments[1]; +} + + +//---------------------------------------------------------------------------- +// This method computes the increments from the MemoryOrder and the extent. +void vtkImageData::ComputeIncrements() +{ + int idx; + // make sure we have data before computing incrments to traverse it + if (!this->GetPointData()->GetScalars()) + { + return; + } + vtkIdType inc = this->GetPointData()->GetScalars()->GetNumberOfComponents(); + const int* extent = this->Extent; + + for (idx = 0; idx < 3; ++idx) + { + this->Increments[idx] = inc; + inc *= (extent[idx*2+1] - extent[idx*2] + 1); + } +} + +//---------------------------------------------------------------------------- +void vtkImageData::CopyOriginAndSpacingFromPipeline() +{ + // Copy origin and spacing from pipeline information to the internal + // copies. + vtkInformation* info = this->PipelineInformation; + if(info->Has(SPACING())) + { + this->SetSpacing(info->Get(SPACING())); + } + if(info->Has(ORIGIN())) + { + this->SetOrigin(info->Get(ORIGIN())); + } +} + +//---------------------------------------------------------------------------- +template +void vtkImageDataConvertScalar(TIn* in, TOut* out) +{ + *out = static_cast(*in); +} + +//---------------------------------------------------------------------------- +double vtkImageData::GetScalarComponentAsDouble(int x, int y, int z, int comp) +{ + // Check the component index. + if(comp < 0 || comp >= this->GetNumberOfScalarComponents()) + { + vtkErrorMacro("Bad component index " << comp); + return 0.0; + } + + // Get a pointer to the scalar tuple. + void* ptr = this->GetScalarPointer(x, y, z); + if(!ptr) + { + // An error message was already generated by GetScalarPointer. + return 0.0; + } + double result = 0.0; + + // Convert the scalar type. + switch (this->GetScalarType()) + { + vtkTemplateMacro(vtkImageDataConvertScalar(static_cast(ptr)+comp, + &result)); + default: + { + vtkErrorMacro("Unknown Scalar type " << this->GetScalarType()); + } + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkImageData::SetScalarComponentFromDouble(int x, int y, int z, int comp, + double value) +{ + // Check the component index. + if(comp < 0 || comp >= this->GetNumberOfScalarComponents()) + { + vtkErrorMacro("Bad component index " << comp); + return; + } + + // Get a pointer to the scalar tuple. + void* ptr = this->GetScalarPointer(x, y, z); + if(!ptr) + { + // An error message was already generated by GetScalarPointer. + return; + } + + // Convert the scalar type. + switch (this->GetScalarType()) + { + vtkTemplateMacro(vtkImageDataConvertScalar( + &value, static_cast(ptr)+comp)); + default: + { + vtkErrorMacro("Unknown Scalar type " << this->GetScalarType()); + } + } +} + +//---------------------------------------------------------------------------- +float vtkImageData::GetScalarComponentAsFloat(int x, int y, int z, int comp) +{ + return this->GetScalarComponentAsDouble(x, y, z, comp); +} + +//---------------------------------------------------------------------------- +void vtkImageData::SetScalarComponentFromFloat(int x, int y, int z, int comp, + float value) +{ + this->SetScalarComponentFromDouble(x, y, z, comp, value); +} + +//---------------------------------------------------------------------------- +// This Method returns a pointer to a location in the vtkImageData. +// Coordinates are in pixel units and are relative to the whole +// image origin. +void *vtkImageData::GetScalarPointer(int x, int y, int z) +{ + int tmp[3]; + tmp[0] = x; + tmp[1] = y; + tmp[2] = z; + return this->GetScalarPointer(tmp); +} + +//---------------------------------------------------------------------------- +// This Method returns a pointer to a location in the vtkImageData. +// Coordinates are in pixel units and are relative to the whole +// image origin. +void *vtkImageData::GetScalarPointerForExtent(int extent[6]) +{ + int tmp[3]; + tmp[0] = extent[0]; + tmp[1] = extent[2]; + tmp[2] = extent[4]; + return this->GetScalarPointer(tmp); +} + +//---------------------------------------------------------------------------- +void *vtkImageData::GetScalarPointer(int coordinate[3]) +{ + vtkDataArray *scalars = this->GetPointData()->GetScalars(); + + // Make sure the array has been allocated. + if (scalars == NULL) + { + vtkDebugMacro("Allocating scalars in ImageData"); + this->AllocateScalars(); + scalars = this->PointData->GetScalars(); + } + + if (scalars == NULL) + { + vtkErrorMacro("Could not allocate scalars."); + return NULL; + } + + const int* extent = this->Extent; + // error checking: since most access will be from pointer arithmetic. + // this should not waste much time. + for (int idx = 0; idx < 3; ++idx) + { + if (coordinate[idx] < extent[idx*2] || + coordinate[idx] > extent[idx*2+1]) + { + vtkErrorMacro(<< "GetScalarPointer: Pixel (" << coordinate[0] << ", " + << coordinate[1] << ", " + << coordinate[2] << ") not in memory.\n Current extent= (" + << extent[0] << ", " << extent[1] << ", " + << extent[2] << ", " << extent[3] << ", " + << extent[4] << ", " << extent[5] << ")"); + return NULL; + } + } + + return this->GetArrayPointer(scalars, coordinate); +} + +//---------------------------------------------------------------------------- +// This method returns a pointer to the origin of the vtkImageData. +void *vtkImageData::GetScalarPointer() +{ + if (this->PointData->GetScalars() == NULL) + { + vtkDebugMacro("Allocating scalars in ImageData"); + this->AllocateScalars(); + } + return this->PointData->GetScalars()->GetVoidPointer(0); +} + +//---------------------------------------------------------------------------- +void vtkImageData::SetScalarType(int type) +{ + this->GetProducerPort(); + if(vtkInformation* info = this->GetPipelineInformation()) + { + vtkDataObject::SetPointDataActiveScalarInfo(info, type, -1); + } + else + { + vtkErrorMacro("SetScalarType called with no " + "executive producing this image data object."); + } +} + +//---------------------------------------------------------------------------- +int vtkImageData::GetScalarType() +{ + this->GetProducerPort(); + if(vtkInformation* info = this->GetPipelineInformation()) + { + vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(info, + FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (scalarInfo) + { + return scalarInfo->Get( FIELD_ARRAY_TYPE() ); + } + } + return VTK_DOUBLE; +} + +//---------------------------------------------------------------------------- +void vtkImageData::AllocateScalars() +{ + int newType = VTK_DOUBLE; + int newNumComp = 1; + + // basically allocate the scalars based om the + this->GetProducerPort(); + if(vtkInformation* info = this->GetPipelineInformation()) + { + vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(info, + FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (scalarInfo) + { + newType = scalarInfo->Get( FIELD_ARRAY_TYPE() ); + if ( scalarInfo->Has(FIELD_NUMBER_OF_COMPONENTS()) ) + { + newNumComp = scalarInfo->Get( FIELD_NUMBER_OF_COMPONENTS() ); + } + } + } + + vtkDataArray *scalars; + + // if the scalar type has not been set then we have a problem + if (newType == VTK_VOID) + { + vtkErrorMacro("Attempt to allocate scalars before scalar type was set!."); + return; + } + + const int* extent = this->Extent; + + // if we currently have scalars then just adjust the size + scalars = this->PointData->GetScalars(); + if (scalars && scalars->GetDataType() == newType + && scalars->GetReferenceCount() == 1) + { + scalars->SetNumberOfComponents(newNumComp); + scalars->SetNumberOfTuples((extent[1] - extent[0] + 1)* + (extent[3] - extent[2] + 1)* + (extent[5] - extent[4] + 1)); + // Since the execute method will be modifying the scalars + // directly. + scalars->Modified(); + return; + } + + // allocate the new scalars + scalars = vtkDataArray::CreateDataArray(newType); + scalars->SetNumberOfComponents(newNumComp); + + // allocate enough memory + scalars-> + SetNumberOfTuples((extent[1] - extent[0] + 1)* + (extent[3] - extent[2] + 1)* + (extent[5] - extent[4] + 1)); + + this->PointData->SetScalars(scalars); + scalars->Delete(); +} + + +//---------------------------------------------------------------------------- +int vtkImageData::GetScalarSize() +{ + return vtkDataArray::GetDataTypeSize(this->GetScalarType()); +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageDataCastExecute(vtkImageData *inData, IT *inPtr, + vtkImageData *outData, OT *outPtr, + int outExt[6]) +{ + int idxR, idxY, idxZ; + int maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int rowLength; + + // find the region to loop over + rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents(); + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; idxY <= maxY; idxY++) + { + for (idxR = 0; idxR < rowLength; idxR++) + { + // Pixel operation + *outPtr = (OT)(*inPtr); + outPtr++; + inPtr++; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + + + +//---------------------------------------------------------------------------- +template +void vtkImageDataCastExecute(vtkImageData *inData, T *inPtr, + vtkImageData *outData, int outExt[6]) +{ + void *outPtr = outData->GetScalarPointerForExtent(outExt); + + if (outPtr == NULL) + { + vtkGenericWarningMacro("Scalars not allocated."); + return; + } + + switch (outData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageDataCastExecute(inData, + (T *)(inPtr), + outData, + (VTK_TT *)(outPtr), + outExt) ); + default: + vtkGenericWarningMacro("Execute: Unknown output ScalarType"); + return; + } +} + + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output region, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageData::CopyAndCastFrom(vtkImageData *inData, int extent[6]) +{ + void *inPtr = inData->GetScalarPointerForExtent(extent); + + if (inPtr == NULL) + { + vtkErrorMacro("Scalars not allocated."); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro(vtkImageDataCastExecute(inData, (VTK_TT *)(inPtr), + this, extent) ); + default: + vtkErrorMacro(<< "Execute: Unknown input ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkImageData::Crop() +{ + int nExt[6]; + int idxX, idxY, idxZ; + int maxX, maxY, maxZ; + vtkIdType outId, inId, inIdY, inIdZ, incZ, incY; + vtkImageData *newImage; + int numPts, numCells, tmp; + const int* extent = this->Extent; + + int updateExtent[6] = {0,-1,0,-1,0,-1}; + this->GetUpdateExtent(updateExtent); + + // If extents already match, then we need to do nothing. + if (extent[0] == updateExtent[0] + && extent[1] == updateExtent[1] + && extent[2] == updateExtent[2] + && extent[3] == updateExtent[3] + && extent[4] == updateExtent[4] + && extent[5] == updateExtent[5]) + { + return; + } + + // Take the intersection of the two extent so that + // we are not asking for more than the extent. + this->GetUpdateExtent(nExt); + if (nExt[0] < extent[0]) { nExt[0] = extent[0];} + if (nExt[1] > extent[1]) { nExt[1] = extent[1];} + if (nExt[2] < extent[2]) { nExt[2] = extent[2];} + if (nExt[3] > extent[3]) { nExt[3] = extent[3];} + if (nExt[4] < extent[4]) { nExt[4] = extent[4];} + if (nExt[5] > extent[5]) { nExt[5] = extent[5];} + + // If the extents are the same just return. + if (extent[0] == nExt[0] && extent[1] == nExt[1] + && extent[2] == nExt[2] && extent[3] == nExt[3] + && extent[4] == nExt[4] && extent[5] == nExt[5]) + { + vtkDebugMacro("Extents already match."); + return; + } + + // How many point/cells. + numPts = (nExt[1]-nExt[0]+1)*(nExt[3]-nExt[2]+1)*(nExt[5]-nExt[4]+1); + // Conditional are to handle 3d, 2d, and even 1d images. + tmp = nExt[1] - nExt[0]; + if (tmp <= 0) + { + tmp = 1; + } + numCells = tmp; + tmp = nExt[3] - nExt[2]; + if (tmp <= 0) + { + tmp = 1; + } + numCells *= tmp; + tmp = nExt[5] - nExt[4]; + if (tmp <= 0) + { + tmp = 1; + } + numCells *= tmp; + + // Create a new temporary image. + newImage = vtkImageData::New(); + newImage->SetScalarType(this->GetScalarType()); + newImage->SetNumberOfScalarComponents(this->GetNumberOfScalarComponents()); + newImage->SetExtent(nExt); + vtkPointData *npd = newImage->GetPointData(); + vtkCellData *ncd = newImage->GetCellData(); + npd->CopyAllocate(this->PointData, numPts); + ncd->CopyAllocate(this->CellData, numCells); + + // Loop through outData points + incY = extent[1]-extent[0]+1; + incZ = (extent[3]-extent[2]+1)*incY; + outId = 0; + inIdZ = incZ * (nExt[4]-extent[4]) + + incY * (nExt[2]-extent[2]) + + (nExt[0]-extent[0]); + + for (idxZ = nExt[4]; idxZ <= nExt[5]; idxZ++) + { + inIdY = inIdZ; + for (idxY = nExt[2]; idxY <= nExt[3]; idxY++) + { + inId = inIdY; + for (idxX = nExt[0]; idxX <= nExt[1]; idxX++) + { + npd->CopyData( this->PointData, inId, outId); + ++inId; + ++outId; + } + inIdY += incY; + } + inIdZ += incZ; + } + + // Loop through outData cells + // Have to handle the 2d and 1d cases. + maxX = nExt[1]; + maxY = nExt[3]; + maxZ = nExt[5]; + if (maxX == nExt[0]) + { + ++maxX; + } + if (maxY == nExt[2]) + { + ++maxY; + } + if (maxZ == nExt[4]) + { + ++maxZ; + } + incY = extent[1]-extent[0]; + incZ = (extent[3]-extent[2])*incY; + outId = 0; + inIdZ = incZ * (nExt[4]-extent[4]) + + incY * (nExt[2]-extent[2]) + + (nExt[0]-extent[0]); + for (idxZ = nExt[4]; idxZ < maxZ; idxZ++) + { + inIdY = inIdZ; + for (idxY = nExt[2]; idxY < maxY; idxY++) + { + inId = inIdY; + for (idxX = nExt[0]; idxX < maxX; idxX++) + { + ncd->CopyData(this->CellData, inId, outId); + ++inId; + ++outId; + } + inIdY += incY; + } + inIdZ += incZ; + } + + this->PointData->ShallowCopy(npd); + this->CellData->ShallowCopy(ncd); + this->SetExtent(nExt); + newImage->Delete(); +} + + + +//---------------------------------------------------------------------------- +double vtkImageData::GetScalarTypeMin() +{ + return vtkDataArray::GetDataTypeMin(this->GetScalarType()); +} + + +//---------------------------------------------------------------------------- +double vtkImageData::GetScalarTypeMax() +{ + return vtkDataArray::GetDataTypeMax(this->GetScalarType()); +} + +//---------------------------------------------------------------------------- +void vtkImageData::SetExtent(int x1, int x2, int y1, int y2, int z1, int z2) +{ + int ext[6]; + ext[0] = x1; + ext[1] = x2; + ext[2] = y1; + ext[3] = y2; + ext[4] = z1; + ext[5] = z2; + this->SetExtent(ext); +} + +//---------------------------------------------------------------------------- +void vtkImageData::SetExtent(int *extent) +{ + int description; + + description = vtkStructuredData::SetExtent(extent, this->Extent); + if ( description < 0 ) //improperly specified + { + vtkErrorMacro (<< "Bad Extent, retaining previous values"); + } + + if (description == VTK_UNCHANGED) + { + return; + } + + this->DataDescription = description; + + this->Modified(); +} + + + +//---------------------------------------------------------------------------- +int *vtkImageData::GetDimensions() +{ + const int* extent = this->Extent; + this->Dimensions[0] = extent[1] - extent[0] + 1; + this->Dimensions[1] = extent[3] - extent[2] + 1; + this->Dimensions[2] = extent[5] - extent[4] + 1; + + return this->Dimensions; +} + +//---------------------------------------------------------------------------- +void vtkImageData::GetDimensions(int *dOut) +{ + int *dims = this->GetDimensions(); + dOut[0] = dims[0]; + dOut[1] = dims[1]; + dOut[2] = dims[2]; +} + +//---------------------------------------------------------------------------- +void vtkImageData::SetAxisUpdateExtent(int idx, int min, int max) +{ + int modified = 0; + + if (idx > 2) + { + vtkWarningMacro("illegal axis!"); + return; + } + + int updateExtent[6] = {0,-1,0,-1,0,-1}; + this->GetUpdateExtent(updateExtent); + + if (updateExtent[idx*2] != min) + { + modified = 1; + updateExtent[idx*2] = min; + } + if (updateExtent[idx*2+1] != max) + { + modified = 1; + updateExtent[idx*2+1] = max; + } + + this->SetUpdateExtent(updateExtent); + if (modified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageData::GetAxisUpdateExtent(int idx, int &min, int &max) +{ + if (idx > 2) + { + vtkWarningMacro("illegal axis!"); + return; + } + + int updateExtent[6] = {0,-1,0,-1,0,-1}; + this->GetUpdateExtent(updateExtent); + min = updateExtent[idx*2]; + max = updateExtent[idx*2+1]; +} + + +//---------------------------------------------------------------------------- +unsigned long vtkImageData::GetActualMemorySize() +{ + return this->vtkDataSet::GetActualMemorySize(); +} + + +//---------------------------------------------------------------------------- +void vtkImageData::ShallowCopy(vtkDataObject *dataObject) +{ + vtkImageData *imageData = vtkImageData::SafeDownCast(dataObject); + + if ( imageData != NULL ) + { + this->InternalImageDataCopy(imageData); + } + + // Do superclass + this->vtkDataSet::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkImageData::DeepCopy(vtkDataObject *dataObject) +{ + vtkImageData *imageData = vtkImageData::SafeDownCast(dataObject); + + if ( imageData != NULL ) + { + this->InternalImageDataCopy(imageData); + } + + // Do superclass + this->vtkDataSet::DeepCopy(dataObject); +} + +//---------------------------------------------------------------------------- +// This copies all the local variables (but not objects). +void vtkImageData::InternalImageDataCopy(vtkImageData *src) +{ + int idx; + + this->DataDescription = src->DataDescription; + this->SetScalarType(src->GetScalarType()); + this->SetNumberOfScalarComponents(src->GetNumberOfScalarComponents()); + for (idx = 0; idx < 3; ++idx) + { + this->Dimensions[idx] = src->Dimensions[idx]; + this->Increments[idx] = src->Increments[idx]; + this->Origin[idx] = src->Origin[idx]; + this->Spacing[idx] = src->Spacing[idx]; + } + memcpy(this->Extent, src->GetExtent(), 6*sizeof(int)); +} + + + +//---------------------------------------------------------------------------- +vtkIdType vtkImageData::GetNumberOfCells() +{ + vtkIdType nCells=1; + int i; + int *dims = this->GetDimensions(); + + for (i=0; i<3; i++) + { + if (dims[i] == 0) + { + return 0; + } + if (dims[i] > 1) + { + nCells *= (dims[i]-1); + } + } + + return nCells; +} + +//============================================================================ +// Starting to make some more general methods that deal with any array +// (not just scalars). +//============================================================================ + + +//---------------------------------------------------------------------------- +// This Method returns a pointer to a location in the vtkImageData. +// Coordinates are in pixel units and are relative to the whole +// image origin. +void vtkImageData::GetArrayIncrements(vtkDataArray* array, vtkIdType increments[3]) +{ + const int* extent = this->Extent; + // We could store tupple increments and just + // multiply by the number of componenets... + increments[0] = array->GetNumberOfComponents(); + increments[1] = increments[0] * (extent[1]-extent[0]+1); + increments[2] = increments[1] * (extent[3]-extent[2]+1); +} + +//---------------------------------------------------------------------------- +void *vtkImageData::GetArrayPointerForExtent(vtkDataArray* array, + int extent[6]) +{ + int tmp[3]; + tmp[0] = extent[0]; + tmp[1] = extent[2]; + tmp[2] = extent[4]; + return this->GetArrayPointer(array, tmp); +} + +//---------------------------------------------------------------------------- +// This Method returns a pointer to a location in the vtkImageData. +// Coordinates are in pixel units and are relative to the whole +// image origin. +void *vtkImageData::GetArrayPointer(vtkDataArray* array, int coordinate[3]) +{ + vtkIdType incs[3]; + int idx; + + if (array == NULL) + { + return NULL; + } + + const int* extent = this->Extent; + // error checking: since most acceses will be from pointer arithmetic. + // this should not waste much time. + for (idx = 0; idx < 3; ++idx) + { + if (coordinate[idx] < extent[idx*2] || + coordinate[idx] > extent[idx*2+1]) + { + vtkErrorMacro(<< "GetPointer: Pixel (" << coordinate[0] << ", " + << coordinate[1] << ", " + << coordinate[2] << ") not in current extent: (" + << extent[0] << ", " << extent[1] << ", " + << extent[2] << ", " << extent[3] << ", " + << extent[4] << ", " << extent[5] << ")"); + return NULL; + } + } + + // compute the index of the vector. + this->GetArrayIncrements(array, incs); + idx = ((coordinate[0] - extent[0]) * incs[0] + + (coordinate[1] - extent[2]) * incs[1] + + (coordinate[2] - extent[4]) * incs[2]); + // I could check to see if the array has the correct number + // of tupples for the extent, but that would be an extra multiply. + if (idx < 0 || idx > array->GetMaxId()) + { + vtkErrorMacro("Coordinate (" << coordinate[0] << ", " << coordinate[1] + << ", " << coordinate[2] << ") out side of array (max = " + << array->GetMaxId()); + return NULL; + } + + return array->GetVoidPointer(idx); +} + + +//---------------------------------------------------------------------------- +void vtkImageData::ComputeInternalExtent(int *intExt, int *tgtExt, int *bnds) +{ + int i; + const int* extent = this->Extent; + for (i = 0; i < 3; ++i) + { + intExt[i*2] = tgtExt[i*2]; + if (intExt[i*2] - bnds[i*2] < extent[i*2]) + { + intExt[i*2] = extent[i*2] + bnds[i*2]; + } + intExt[i*2+1] = tgtExt[i*2+1]; + if (intExt[i*2+1] + bnds[i*2+1] > extent[i*2+1]) + { + intExt[i*2+1] = extent[i*2+1] - bnds[i*2+1]; + } + } +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkImageData::GetData(vtkInformation* info) +{ + return info? vtkImageData::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkImageData::GetData(vtkInformationVector* v, int i) +{ + return vtkImageData::GetData(v->GetInformationObject(i)); +} diff --git a/Filtering/vtkImageData.h b/Filtering/vtkImageData.h new file mode 100644 index 0000000..1648039 --- /dev/null +++ b/Filtering/vtkImageData.h @@ -0,0 +1,406 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageData - topologically and geometrically regular array of data +// .SECTION Description +// vtkImageData is a data object that is a concrete implementation of +// vtkDataSet. vtkImageData represents a geometric structure that is +// a topological and geometrical regular array of points. Examples include +// volumes (voxel data) and pixmaps. + +#ifndef __vtkImageData_h +#define __vtkImageData_h + +#include "vtkDataSet.h" + +#include "vtkStructuredData.h" // Needed for inline methods + +class vtkDataArray; +class vtkLine; +class vtkPixel; +class vtkVertex; +class vtkVoxel; + +class VTK_FILTERING_EXPORT vtkImageData : public vtkDataSet +{ +public: + static vtkImageData *New(); + + vtkTypeRevisionMacro(vtkImageData,vtkDataSet); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Copy the geometric and topological structure of an input image data + // object. + virtual void CopyStructure(vtkDataSet *ds); + + // Description: + // Return what type of dataset this is. + virtual int GetDataObjectType() {return VTK_IMAGE_DATA;}; + + // Description: + // Standard vtkDataSet API methods. See vtkDataSet for more information. + virtual vtkIdType GetNumberOfCells(); + virtual vtkIdType GetNumberOfPoints(); + virtual double *GetPoint(vtkIdType ptId); + virtual void GetPoint(vtkIdType id, double x[3]); + virtual vtkCell *GetCell(vtkIdType cellId); + virtual void GetCell(vtkIdType cellId, vtkGenericCell *cell); + virtual void GetCellBounds(vtkIdType cellId, double bounds[6]); + virtual vtkIdType FindPoint(double x, double y, double z) + { + return this->vtkDataSet::FindPoint(x, y, z); + }; + virtual vtkIdType FindPoint(double x[3]); + virtual vtkIdType FindCell( + double x[3], vtkCell *cell, vtkIdType cellId, double tol2, + int& subId, double pcoords[3], double *weights); + virtual vtkIdType FindCell( + double x[3], vtkCell *cell, vtkGenericCell *gencell, + vtkIdType cellId, double tol2, int& subId, + double pcoords[3], double *weights); + virtual vtkCell *FindAndGetCell(double x[3], vtkCell *cell, vtkIdType cellId, + double tol2, int& subId, double pcoords[3], + double *weights); + virtual int GetCellType(vtkIdType cellId); + virtual void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds) + {vtkStructuredData::GetCellPoints(cellId,ptIds,this->DataDescription, + this->GetDimensions());} + virtual void GetPointCells(vtkIdType ptId, vtkIdList *cellIds) + {vtkStructuredData::GetPointCells(ptId,cellIds,this->GetDimensions());} + virtual void ComputeBounds(); + virtual int GetMaxCellSize() {return 8;}; //voxel is the largest + + // Description: + // Restore data object to initial state, + virtual void Initialize(); + + // Description: + // Set dimensions of structured points dataset. + virtual void SetDimensions(int i, int j, int k); + + // Description: + // Set dimensions of structured points dataset. + virtual void SetDimensions(int dims[3]); + + // Description: + // Get dimensions of this structured points dataset. + // It is the number of points on each axis. + // Dimensions are computed from Extents during this call. + virtual int *GetDimensions(); + virtual void GetDimensions(int dims[3]); + + // Description: + // Convenience function computes the structured coordinates for a point x[3]. + // The voxel is specified by the array ijk[3], and the parametric coordinates + // in the cell are specified with pcoords[3]. The function returns a 0 if the + // point x is outside of the volume, and a 1 if inside the volume. + virtual int ComputeStructuredCoordinates( + double x[3], int ijk[3], double pcoords[3]); + + // Description: + // Given structured coordinates (i,j,k) for a voxel cell, compute the eight + // gradient values for the voxel corners. The order in which the gradient + // vectors are arranged corresponds to the ordering of the voxel points. + // Gradient vector is computed by central differences (except on edges of + // volume where forward difference is used). The scalars s are the scalars + // from which the gradient is to be computed. This method will treat + // only 3D structured point datasets (i.e., volumes). + virtual void GetVoxelGradient( + int i,int j,int k, vtkDataArray *s, vtkDataArray *g); + + // Description: + // Given structured coordinates (i,j,k) for a point in a structured point + // dataset, compute the gradient vector from the scalar data at that point. + // The scalars s are the scalars from which the gradient is to be computed. + // This method will treat structured point datasets of any dimension. + virtual void GetPointGradient( + int i, int j, int k, vtkDataArray *s, double g[3]); + + // Description: + // Return the dimensionality of the data. + virtual int GetDataDimension(); + + // Description: + // Given a location in structured coordinates (i-j-k), return the point id. + virtual vtkIdType ComputePointId(int ijk[3]) { + return vtkStructuredData::ComputePointId(this->GetDimensions(),ijk);}; + + // Description: + // Given a location in structured coordinates (i-j-k), return the cell id. + virtual vtkIdType ComputeCellId(int ijk[3]) { + return vtkStructuredData::ComputeCellId(this->GetDimensions(),ijk);}; + + // Description: + // Set / Get the extent on just one axis + virtual void SetAxisUpdateExtent(int axis, int min, int max); + virtual void GetAxisUpdateExtent(int axis, int &min, int &max); + + // Description: + // Override to copy information from pipeline information to data + // information for backward compatibility. See + // vtkDataObject::UpdateInformation for details. + virtual void UpdateInformation(); + + // Description: + // Set/Get the extent. On each axis, the extent is defined by the index + // of the first point and the index of the last point. The extent should + // be set before the "Scalars" are set or allocated. The Extent is + // stored in the order (X, Y, Z). + virtual void SetExtent(int extent[6]); + virtual void SetExtent(int x1, int x2, int y1, int y2, int z1, int z2); + vtkGetVector6Macro(Extent, int); + + // Description: + // Get the estimated size of this data object itself. Should be called + // after UpdateInformation() and PropagateUpdateExtent() have both been + // called. This estimate should be fairly accurate since this is structured + // data. + virtual unsigned long GetEstimatedMemorySize(); + + // Description: + // These returns the minimum and maximum values the ScalarType can hold + // without overflowing. + virtual double GetScalarTypeMin(); + virtual double GetScalarTypeMax(); + + // Description: + // Set the size of the scalar type in bytes. + virtual int GetScalarSize(); + + // Description: + // Different ways to get the increments for moving around the data. + // GetIncrements() calls ComputeIncrements() to ensure the increments are + // up to date. + virtual vtkIdType *GetIncrements(); + virtual void GetIncrements(vtkIdType &incX, vtkIdType &incY, vtkIdType &incZ); + virtual void GetIncrements(vtkIdType inc[3]); + + // Description: + // Different ways to get the increments for moving around the data. + // incX is always returned with 0. incY is returned with the + // increment needed to move from the end of one X scanline of data + // to the start of the next line. incZ is filled in with the + // increment needed to move from the end of one image to the start + // of the next. The proper way to use these values is to for a loop + // over Z, Y, X, C, incrementing the pointer by 1 after each + // component. When the end of the component is reached, the pointer + // is set to the beginning of the next pixel, thus incX is properly set to 0. + virtual void GetContinuousIncrements( + int extent[6], vtkIdType &incX, vtkIdType &incY, vtkIdType &incZ); + + // Description: + // Access the native pointer for the scalar data + virtual void *GetScalarPointerForExtent(int extent[6]); + virtual void *GetScalarPointer(int coordinates[3]); + virtual void *GetScalarPointer(int x, int y, int z); + virtual void *GetScalarPointer(); + + // Description: + // For access to data from tcl + virtual float GetScalarComponentAsFloat(int x, int y, int z, int component); + virtual void SetScalarComponentFromFloat( + int x, int y, int z, int component, float v); + virtual double GetScalarComponentAsDouble(int x, int y, int z, int component); + virtual void SetScalarComponentFromDouble( + int x, int y, int z, int component, double v); + + // Description: + // Allocate the vtkScalars object associated with this object. + virtual void AllocateScalars(); + + // Description: + // This method is passed a input and output region, and executes the filter + // algorithm to fill the output from the input. + // It just executes a switch statement to call the correct function for + // the regions data types. + virtual void CopyAndCastFrom(vtkImageData *inData, int extent[6]); + virtual void CopyAndCastFrom(vtkImageData *inData, int x0, int x1, + int y0, int y1, int z0, int z1) + {int e[6]; e[0]=x0; e[1]=x1; e[2]=y0; e[3]=y1; e[4]=z0; e[5]=z1; + this->CopyAndCastFrom(inData, e);} + + // Description: + // Reallocates and copies to set the Extent to the UpdateExtent. + // This is used internally when the exact extent is requested, + // and the source generated more than the update extent. + virtual void Crop(); + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). THIS METHOD + // IS THREAD SAFE. + virtual unsigned long GetActualMemorySize(); + + // Description: + // Set the spacing (width,height,length) of the cubical cells that + // compose the data set. + vtkSetVector3Macro(Spacing,double); + vtkGetVector3Macro(Spacing,double); + + // Description: + // Set the origin of the data. The origin plus spacing determine the + // position in space of the points. + vtkSetVector3Macro(Origin,double); + vtkGetVector3Macro(Origin,double); + + // Description: + // Set/Get the data scalar type (i.e VTK_DOUBLE). Note that these methods + // are setting and getting the pipeline scalar type. i.e. they are setting + // the type that the image data will be once it has executed. Until the + // REQUEST_DATA pass the actual scalars may be of some other type. This is + // for backwards compatibility + void SetScalarTypeToFloat(){this->SetScalarType(VTK_FLOAT);}; + void SetScalarTypeToDouble(){this->SetScalarType(VTK_DOUBLE);}; + void SetScalarTypeToInt(){this->SetScalarType(VTK_INT);}; + void SetScalarTypeToUnsignedInt() + {this->SetScalarType(VTK_UNSIGNED_INT);}; + void SetScalarTypeToLong(){this->SetScalarType(VTK_LONG);}; + void SetScalarTypeToUnsignedLong() + {this->SetScalarType(VTK_UNSIGNED_LONG);}; + void SetScalarTypeToShort(){this->SetScalarType(VTK_SHORT);}; + void SetScalarTypeToUnsignedShort() + {this->SetScalarType(VTK_UNSIGNED_SHORT);}; + void SetScalarTypeToUnsignedChar() + {this->SetScalarType(VTK_UNSIGNED_CHAR);}; + void SetScalarTypeToChar() + {this->SetScalarType(VTK_CHAR);}; + void SetScalarType(int); + int GetScalarType(); + const char* GetScalarTypeAsString() + { return vtkImageScalarTypeNameMacro ( this->GetScalarType() ); }; + + // Description: + // Set/Get the number of scalar components for points. As with the + // SetScalarType method this is setting pipeline info. + void SetNumberOfScalarComponents( int n ); + int GetNumberOfScalarComponents(); + + // Must only be called with vtkImageData (or subclass) as input + virtual void CopyTypeSpecificInformation( vtkDataObject *image ); + + // Description: + // Override these to handle origin, spacing, scalar type, and scalar + // number of components. See vtkDataObject for details. + virtual void CopyInformationToPipeline(vtkInformation* request, + vtkInformation* input); + virtual void CopyInformationFromPipeline(vtkInformation* request); + + // Description: + // make the output data ready for new data to be inserted. For most + // objects we just call Initialize. But for image data we leave the old + // data in case the memory can be reused. + virtual void PrepareForNewData(); + + // Description: + // Shallow and Deep copy. + virtual void ShallowCopy(vtkDataObject *src); + virtual void DeepCopy(vtkDataObject *src); + + //-------------------------------------------------------------------------- + // Methods that apply to any array (not just scalars). + // I am starting to experiment with generalizing imaging fitlers + // to operate on more than just scalars. + + // Description: + // These are convenience methods for getting a pointer + // from any filed array. It is a start at expanding image filters + // to process any array (not just scalars). + void *GetArrayPointerForExtent(vtkDataArray* array, int extent[6]); + void *GetArrayPointer(vtkDataArray* array, int coordinates[3]); + + // Description: + // Since various arrays have different number of components, + // the will have different increments. + void GetArrayIncrements(vtkDataArray *array, vtkIdType increments[3]); + + // Description: + // Given how many pixel are required on a side for bounrary conditions (in + // bnds), the target extent to traverse, compute the internal extent (the + // extent for this ImageData that does nto suffer from any boundary + // conditions) and place it in intExt + void ComputeInternalExtent(int *intExt, int *tgtExt, int *bnds); + + // Description: + // The extent type is a 3D extent + virtual int GetExtentType() { return VTK_3D_EXTENT; }; + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkImageData* GetData(vtkInformation* info); + static vtkImageData* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkImageData(); + ~vtkImageData(); + + // for the GetCell method + vtkVertex *Vertex; + vtkLine *Line; + vtkPixel *Pixel; + vtkVoxel *Voxel; + + // The extent of what is currently in the structured grid. + // Dimensions is just an array to return a value. + // Its contents are out of data until GetDimensions is called. + int Dimensions[3]; + int DataDescription; + vtkIdType Increments[3]; + + double Origin[3]; + double Spacing[3]; + + int Extent[6]; + + void ComputeIncrements(); + void CopyOriginAndSpacingFromPipeline(); + + vtkTimeStamp ExtentComputeTime; + +private: + void InternalImageDataCopy(vtkImageData *src); +private: + vtkImageData(const vtkImageData&); // Not implemented. + void operator=(const vtkImageData&); // Not implemented. +}; + + +inline void vtkImageData::GetPoint(vtkIdType id, double x[3]) +{ + double *p=this->GetPoint(id); + x[0] = p[0]; x[1] = p[1]; x[2] = p[2]; +} + + + +inline vtkIdType vtkImageData::GetNumberOfPoints() +{ + int *dims = this->GetDimensions(); + return dims[0]*dims[1]*dims[2]; +} + +inline int vtkImageData::GetDataDimension() +{ + return vtkStructuredData::GetDataDimension(this->DataDescription); +} + +#endif + + + diff --git a/Filtering/vtkImageInPlaceFilter.cxx b/Filtering/vtkImageInPlaceFilter.cxx new file mode 100644 index 0000000..f90cfc9 --- /dev/null +++ b/Filtering/vtkImageInPlaceFilter.cxx @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageInPlaceFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageInPlaceFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLargeInteger.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageInPlaceFilter, "$Revision: 1.45 $"); + +//---------------------------------------------------------------------------- +vtkImageInPlaceFilter::vtkImageInPlaceFilter() +{ +} + +//---------------------------------------------------------------------------- +vtkImageInPlaceFilter::~vtkImageInPlaceFilter() +{ +} + +//---------------------------------------------------------------------------- + +int vtkImageInPlaceFilter::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the data object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = + vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *input = + vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + + int *inExt, *outExt; + inExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + outExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + // if the total size of the data is the same then can be in place + vtkLargeInteger inSize; + vtkLargeInteger outSize; + inSize = (inExt[1] - inExt[0] + 1); + inSize = inSize * (inExt[3] - inExt[2] + 1); + inSize = inSize * (inExt[5] - inExt[4] + 1); + outSize = (outExt[1] - outExt[0] + 1); + outSize = outSize * (outExt[3] - outExt[2] + 1); + outSize = outSize * (outExt[5] - outExt[4] + 1); + if (inSize == outSize && + this->GetInput()->ShouldIReleaseData()) + { + // pass the data + output->GetPointData()->PassData(input->GetPointData()); + output->SetExtent(outExt); + } + else + { + output->SetExtent(outExt); + output->AllocateScalars(); + this->CopyData(input,output); + } + + return 1; +} + +void vtkImageInPlaceFilter::CopyData(vtkImageData *inData, + vtkImageData *outData) +{ + int *outExt = this->GetOutput()->GetUpdateExtent(); + char *inPtr = (char *) inData->GetScalarPointerForExtent(outExt); + char *outPtr = (char *) outData->GetScalarPointerForExtent(outExt); + int rowLength, size; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int idxY, idxZ, maxY, maxZ; + + rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents(); + size = inData->GetScalarSize(); + rowLength *= size; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // adjust increments for this loop + inIncY = inIncY*size + rowLength; + outIncY = outIncY*size + rowLength; + inIncZ *= size; + outIncZ *= size; + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; idxY <= maxY; idxY++) + { + memcpy(outPtr,inPtr,rowLength); + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + +//---------------------------------------------------------------------------- +void vtkImageInPlaceFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkImageInPlaceFilter.h b/Filtering/vtkImageInPlaceFilter.h new file mode 100644 index 0000000..387c510 --- /dev/null +++ b/Filtering/vtkImageInPlaceFilter.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageInPlaceFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageInPlaceFilter - Filter that operates in place. +// .SECTION Description +// vtkImageInPlaceFilter is a filter super class that +// operates directly on the input region. The data is copied +// if the requested region has different extent than the input region +// or some other object is referencing the input region. + +// .SECTION See Also +// vtkImageToImageFilter vtkImageMultipleInputFilter vtkImageTwoInputFilter + + +#ifndef __vtkImageInPlaceFilter_h +#define __vtkImageInPlaceFilter_h + +#include "vtkImageAlgorithm.h" + +class VTK_FILTERING_EXPORT vtkImageInPlaceFilter : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImageInPlaceFilter,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkImageInPlaceFilter(); + ~vtkImageInPlaceFilter(); + + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + void CopyData(vtkImageData *in, vtkImageData *out); + +private: + vtkImageInPlaceFilter(const vtkImageInPlaceFilter&); // Not implemented. + void operator=(const vtkImageInPlaceFilter&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkImageIterator.cxx b/Filtering/vtkImageIterator.cxx new file mode 100644 index 0000000..40d1107 --- /dev/null +++ b/Filtering/vtkImageIterator.cxx @@ -0,0 +1,40 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkImageIterator.txx" + +#ifndef VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION + +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +#if defined(VTK_TYPE_USE_LONG_LONG) +template class VTK_FILTERING_EXPORT vtkImageIterator; +template class VTK_FILTERING_EXPORT vtkImageIterator; +#endif +#if defined(VTK_TYPE_USE___INT64) +template class VTK_FILTERING_EXPORT vtkImageIterator<__int64>; +template class VTK_FILTERING_EXPORT vtkImageIterator; +#endif + +#endif diff --git a/Filtering/vtkImageIterator.h b/Filtering/vtkImageIterator.h new file mode 100644 index 0000000..46b3979 --- /dev/null +++ b/Filtering/vtkImageIterator.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageIterator - a simple image iterator +// .SECTION Description +// This is a simple image iterator that can be used to iterate over an +// image. This should be used internally by Filter writers. + +// .SECTION See also +// vtkImageData vtkImageProgressIterator + +#ifndef __vtkImageIterator_h +#define __vtkImageIterator_h + +#include "vtkSystemIncludes.h" +class vtkImageData; + +template +class vtkImageIterator +{ +public: + typedef DType *SpanIterator; + + // Description: + // Create an image iterator fora given image data and a given extent + vtkImageIterator(vtkImageData *id, int *ext); + + // Description: + // Move the iterator to the next span + void NextSpan(); + + // Description: + // Return an iterator (pointer) for the span + SpanIterator BeginSpan() + { + return this->Pointer; + } + + // Description: + // Return an iterator (pointer) for the end of the span + SpanIterator EndSpan() + { + return this->SpanEndPointer; + } + + // Description: + // tets if the end of the extent has been reached + int IsAtEnd() + { + return (this->Pointer >= this->EndPointer); + } + +protected: + DType *Pointer; + DType *SpanEndPointer; + DType *SliceEndPointer; + DType *EndPointer; + vtkIdType Increments[3]; + vtkIdType ContinuousIncrements[3]; +}; + +#ifdef VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION +#include "vtkImageIterator.txx" +#endif + +#endif diff --git a/Filtering/vtkImageIterator.txx b/Filtering/vtkImageIterator.txx new file mode 100644 index 0000000..9bbf41b --- /dev/null +++ b/Filtering/vtkImageIterator.txx @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIterator.txx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Include blockers needed since vtkImageIterator.h includes this file +// when VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION is defined. +#ifndef __vtkImageIterator_txx +#define __vtkImageIterator_txx + +#include "vtkImageIterator.h" +#include "vtkImageData.h" + +template +vtkImageIterator::vtkImageIterator(vtkImageData *id, int *ext) +{ + this->Pointer = (DType *)id->GetScalarPointerForExtent(ext); + id->GetIncrements(this->Increments[0], this->Increments[1], + this->Increments[2]); + id->GetContinuousIncrements(ext,this->ContinuousIncrements[0], + this->ContinuousIncrements[1], + this->ContinuousIncrements[2]); + this->EndPointer = + (DType *)id->GetScalarPointer(ext[1],ext[3],ext[5]) +this->Increments[0]; + + // if the extent is empty then the end pointer should equal the beg pointer + if (ext[1] < ext[0] || ext[3] < ext[2] || ext[5] < ext[4]) + { + this->EndPointer = this->Pointer; + } + + this->SpanEndPointer = + this->Pointer + this->Increments[0]*(ext[1] - ext[0] + 1); + this->SliceEndPointer = + this->Pointer + this->Increments[1]*(ext[3] - ext[2] + 1); +} + + +template +void vtkImageIterator::NextSpan() +{ + this->Pointer += this->Increments[1]; + this->SpanEndPointer += this->Increments[1]; + if (this->Pointer >= this->SliceEndPointer) + { + this->Pointer += this->ContinuousIncrements[2]; + this->SpanEndPointer += this->ContinuousIncrements[2]; + this->SliceEndPointer += this->Increments[2]; + } +} + +#endif diff --git a/Filtering/vtkImageMultipleInputFilter.cxx b/Filtering/vtkImageMultipleInputFilter.cxx new file mode 100644 index 0000000..d3627e2 --- /dev/null +++ b/Filtering/vtkImageMultipleInputFilter.cxx @@ -0,0 +1,314 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMultipleInputFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMultipleInputFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageMultipleInputFilter, "$Revision: 1.66 $"); + +//---------------------------------------------------------------------------- +vtkImageMultipleInputFilter::vtkImageMultipleInputFilter() +{ + this->NumberOfInputs = 0; + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); + this->Bypass = 0; + + this->Threader = vtkMultiThreader::New(); + this->NumberOfThreads = this->Threader->GetNumberOfThreads(); +} + +//---------------------------------------------------------------------------- +vtkImageMultipleInputFilter::~vtkImageMultipleInputFilter() +{ + this->Threader->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkImageMultipleInputFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfThreads: " << this->NumberOfThreads << "\n"; + if ( this->Bypass ) + { + os << indent << "Bypass: On\n"; + } + else + { + os << indent << "Bypass: Off\n"; + } +} + + +//---------------------------------------------------------------------------- +// Adds an input to the first null position in the input list. +// Expands the list memory if necessary +void vtkImageMultipleInputFilter::AddInput(vtkImageData *input) +{ + this->vtkProcessObject::AddInput(input); +} + +//---------------------------------------------------------------------------- +void vtkImageMultipleInputFilter::RemoveInput(vtkImageData *input) +{ + this->vtkProcessObject::RemoveInput(input); +} + +//---------------------------------------------------------------------------- +// Set an Input of this filter. +void vtkImageMultipleInputFilter::SetInput(int idx, vtkImageData *input) +{ + this->vtkProcessObject::SetNthInput(idx, input); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageMultipleInputFilter::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageMultipleInputFilter::GetInput(int idx) +{ + if (this->NumberOfInputs <= idx) + { + return NULL; + } + + return (vtkImageData*)(this->Inputs[idx]); +} + + + + + +//---------------------------------------------------------------------------- +void vtkImageMultipleInputFilter::ExecuteInformation() +{ + vtkImageData *output = this->GetOutput(); + vtkImageData *input = this->GetInput(0); + + if ( input == NULL || output == NULL) + { + return; + } + + // Set the defaults from input1 + output->CopyTypeSpecificInformation(input); + + // Let the subclass modify the default. + this->ExecuteInformation((vtkImageData**)(this->Inputs), output); +} + +// Call the alternate version of this method, and use the returned input +// update extent for all inputs +void vtkImageMultipleInputFilter::ComputeInputUpdateExtents( vtkDataObject + *output ) +{ + int outExt[6], inExt[6]; + + output->GetUpdateExtent( outExt ); + + for (int idx = 0; idx < this->NumberOfInputs; idx++) + { + if (this->Inputs[idx] != NULL) + { + this->ComputeInputUpdateExtent( inExt, outExt, idx ); + this->Inputs[idx]->SetUpdateExtent( inExt ); + } + } +} + +// By default, simply set the input update extent to match the given output +// extent +void vtkImageMultipleInputFilter::ComputeInputUpdateExtent( + int inExt[6], + int outExt[6], + int vtkNotUsed(whichInput) ) +{ + memcpy(inExt,outExt,sizeof(int)*6); +} + + +struct vtkImageMultiThreadStruct +{ + vtkImageMultipleInputFilter *Filter; + vtkImageData **Inputs; + vtkImageData *Output; +}; + +// this mess is really a simple function. All it does is call +// the ThreadedExecute method after setting the correct +// extent for this thread. Its just a pain to calculate +// the correct extent. +VTK_THREAD_RETURN_TYPE vtkImageMultiThreadedExecute( void *arg ) +{ + vtkImageMultiThreadStruct *str; + int ext[6], splitExt[6], total; + int threadId, threadCount; + + threadId = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + + str = (vtkImageMultiThreadStruct *)(((vtkMultiThreader::ThreadInfo *)(arg))->UserData); + + memcpy(ext,str->Filter->GetOutput()->GetUpdateExtent(), + sizeof(int)*6); + + // execute the actual method with appropriate extent + // first find out how many pieces extent can be split into. + total = str->Filter->SplitExtent(splitExt, ext, threadId, threadCount); + + if (threadId < total) + { + str->Filter->ThreadedExecute(str->Inputs, str->Output, splitExt, threadId); + } + // else + // { + // otherwise don't use this thread. Sometimes the threads dont + // break up very well and it is just as efficient to leave a + // few threads idle. + // } + + return VTK_THREAD_RETURN_VALUE; +} + + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkImageMultipleInputFilter::ExecuteData(vtkDataObject *out) +{ + // Make sure the Input has been set. + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<< "ExecuteData: Input is not set."); + return; + } + + // Too many filters have floating point exceptions to execute + // with empty input/ no request. + if (this->UpdateExtentIsEmpty(out)) + { + return; + } + + + vtkImageData *outdata = this->AllocateOutputData(out); + this->MultiThread((vtkImageData**)this->GetInputs(), outdata); +} + +//---------------------------------------------------------------------------- +void vtkImageMultipleInputFilter::MultiThread(vtkImageData **inputs, vtkImageData *output) +{ + vtkImageMultiThreadStruct str; + + str.Filter = this; + str.Inputs = inputs; + str.Output = output; + + this->Threader->SetNumberOfThreads(this->NumberOfThreads); + + // setup threading and the invoke threadedExecute + this->Threader->SetSingleMethod(vtkImageMultiThreadedExecute, &str); + this->Threader->SingleMethodExecute(); +} + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkImageMultipleInputFilter::ThreadedExecute(vtkImageData + **vtkNotUsed(inData), + vtkImageData *vtkNotUsed(outData), + int extent[6], int threadId) +{ + extent = extent; + if (threadId == 0) + { + vtkErrorMacro("subclass must override ThreadedExecute!!!"); + } +} + + +//---------------------------------------------------------------------------- +// For streaming and threads. Splits output update extent into num pieces. +// This method needs to be called num times. Results must not overlap for +// consistent starting extent. Subclass can override this method. +// This method returns the number of peices resulting from a successful split. +// This can be from 1 to "total". +// If 1 is returned, the extent cannot be split. +int vtkImageMultipleInputFilter::SplitExtent(int splitExt[6], int startExt[6], + int num, int total) +{ + int splitAxis; + int min, max; + + vtkDebugMacro("SplitExtent: ( " << startExt[0] << ", " << startExt[1] << ", " + << startExt[2] << ", " << startExt[3] << ", " + << startExt[4] << ", " << startExt[5] << "), " + << num << " of " << total); + + // start with same extent + memcpy(splitExt, startExt, 6 * sizeof(int)); + + splitAxis = 2; + min = startExt[4]; + max = startExt[5]; + while (min == max) + { + splitAxis--; + if (splitAxis < 0) + { // cannot split + vtkDebugMacro(" Cannot Split"); + return 1; + } + min = startExt[splitAxis*2]; + max = startExt[splitAxis*2+1]; + } + + // determine the actual number of pieces that will be generated + int range = max - min + 1; + int valuesPerThread = (int)ceil(range/(double)total); + int maxThreadIdUsed = (int)ceil(range/(double)valuesPerThread) - 1; + if (num < maxThreadIdUsed) + { + splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; + splitExt[splitAxis*2+1] = splitExt[splitAxis*2] + valuesPerThread - 1; + } + if (num == maxThreadIdUsed) + { + splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; + } + + vtkDebugMacro(" Split Piece: ( " <Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} diff --git a/Filtering/vtkImageMultipleInputFilter.h b/Filtering/vtkImageMultipleInputFilter.h new file mode 100644 index 0000000..af3fd7f --- /dev/null +++ b/Filtering/vtkImageMultipleInputFilter.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMultipleInputFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMultipleInputFilter - Generic filter that has N inputs. +// .SECTION Description +// vtkImageMultipleInputFilter is a super class for filters that +// have any number of inputs. Steaming is not available in this class yet. + +// .SECTION See Also +// vtkImageToImageFilter vtkImageInPlaceFilter vtkImageTwoInputFilter + + + +#ifndef __vtkImageMultipleInputFilter_h +#define __vtkImageMultipleInputFilter_h + +#include "vtkImageSource.h" + +class vtkMultiThreader; + +class VTK_FILTERING_EXPORT vtkImageMultipleInputFilter : public vtkImageSource +{ +public: + vtkTypeRevisionMacro(vtkImageMultipleInputFilter,vtkImageSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set an Input of this filter. + virtual void SetInput(int num, vtkImageData *input); + + // Description: + // Adds an input to the first null position in the input list. + // Expands the list memory if necessary + virtual void AddInput(vtkImageData *input); + virtual void RemoveInput(vtkImageData *input); + + // Description: + // Get one input to this filter. + vtkImageData *GetInput(int num); + vtkImageData *GetInput(); + + // Description: + // Turning bypass on will cause the filter to turn off and + // simply pass the data from the first input (input0) through. + // It is implemented for consistency with vtkImageToImageFilter. + vtkSetMacro(Bypass,int); + vtkGetMacro(Bypass,int); + vtkBooleanMacro(Bypass,int); + + // Description: + // Get/Set the number of threads to create when rendering + vtkSetClampMacro( NumberOfThreads, int, 1, VTK_MAX_THREADS ); + vtkGetMacro( NumberOfThreads, int ); + + // Description: + // Putting this here until I merge graphics and imaging streaming. + virtual int SplitExtent(int splitExt[6], int startExt[6], + int num, int total); + + // Description: + // The execute method created by the subclass. + // This is kept public instead of protected since it is called + // from a non-member thread function. + virtual void ThreadedExecute(vtkImageData **inDatas, + vtkImageData *outData, + int extent[6], int threadId); + + + +protected: + vtkImageMultipleInputFilter(); + ~vtkImageMultipleInputFilter(); + + vtkMultiThreader *Threader; + int Bypass; + int NumberOfThreads; + + void ComputeInputUpdateExtents( vtkDataObject *output ); + + virtual void ComputeInputUpdateExtent( int inExt[6], + int outExt[6], + int whichInput ); + + + void ExecuteData(vtkDataObject *output); + void MultiThread(vtkImageData **indatas, vtkImageData *outdata); + + // This one gets called by the superclass. + void ExecuteInformation(); + // This is the one you should override. + virtual void ExecuteInformation(vtkImageData **, vtkImageData *) {}; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + // hide the superclass' AddInput() from the user and the compiler + void AddInput(vtkDataObject *) + { vtkErrorMacro( << "AddInput() must be called with a vtkImageData not a vtkDataObject."); }; + void RemoveInput(vtkDataObject *) + { vtkErrorMacro( << "RemoveInput() must be called with a vtkImageData not a vtkDataObject."); }; +private: + vtkImageMultipleInputFilter(const vtkImageMultipleInputFilter&); // Not implemented. + void operator=(const vtkImageMultipleInputFilter&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkImageMultipleInputOutputFilter.cxx b/Filtering/vtkImageMultipleInputOutputFilter.cxx new file mode 100644 index 0000000..33653ac --- /dev/null +++ b/Filtering/vtkImageMultipleInputOutputFilter.cxx @@ -0,0 +1,225 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMultipleInputOutputFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMultipleInputOutputFilter.h" + +#include "vtkImageData.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageMultipleInputOutputFilter, "$Revision: 1.14 $"); + +//---------------------------------------------------------------------------- +vtkImageMultipleInputOutputFilter::vtkImageMultipleInputOutputFilter() +{ +} + +//---------------------------------------------------------------------------- +vtkImageMultipleInputOutputFilter::~vtkImageMultipleInputOutputFilter() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageMultipleInputOutputFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageMultipleInputOutputFilter::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageMultipleInputOutputFilter::GetOutput(int idx) +{ + if (this->NumberOfOutputs <= idx) + { + return NULL; + } + + return (vtkImageData*)(this->Outputs[idx]); +} + + +//---------------------------------------------------------------------------- +void vtkImageMultipleInputOutputFilter::ExecuteInformation() +{ + vtkImageData *output; + vtkImageData *input = this->GetInput(0); + + if ( input == NULL) + { + return; + } + + // Set the defaults from input1 to all outputs + for (int i = 0; i < this->NumberOfOutputs; i++) + { + output = this->GetOutput(i); + if (output) + { + output->CopyTypeSpecificInformation(input); + } + } + + // Let the subclass modify the default. + this->ExecuteInformation((vtkImageData**)(this->Inputs), + (vtkImageData**)(this->Outputs)); +} + +// Call the alternate version of this method, and use the returned input +// update extent for all inputs +void vtkImageMultipleInputOutputFilter:: +ComputeInputUpdateExtents( vtkDataObject *output ) +{ + int outExt[6], inExt[6]; + int idx; + + output->GetUpdateExtent( outExt ); + + for (idx = 0; idx < this->NumberOfInputs; idx++) + { + if (this->Inputs[idx] != NULL) + { + this->ComputeInputUpdateExtent( inExt, outExt, idx ); + this->Inputs[idx]->SetUpdateExtent( inExt ); + } + } + + // by default set other output's UpdateExtent to the same if they are unset + for (idx = 0; idx < this->NumberOfOutputs; idx++) + { + if (this->Outputs[idx] && this->Outputs[idx] != output) + { + int *uExtent = this->Outputs[idx]->GetUpdateExtent(); + if (uExtent[0] > uExtent[1]) + { + this->Outputs[idx]->SetUpdateExtent(outExt); + } + } + } +} + +// By default, simply set the input update extent to match the given output +// extent +void vtkImageMultipleInputOutputFilter::ComputeInputUpdateExtent( + int inExt[6], + int outExt[6], + int vtkNotUsed(whichInput) ) +{ + memcpy(inExt,outExt,sizeof(int)*6); +} + + +struct vtkImageMultiThreadStruct +{ + vtkImageMultipleInputOutputFilter *Filter; + vtkImageData **Inputs; + vtkImageData **Outputs; +}; + +// this mess is really a simple function. All it does is call +// the ThreadedExecute method after setting the correct +// extent for this thread. Its just a pain to calculate +// the correct extent. +VTK_THREAD_RETURN_TYPE vtkImageMultiInOutThreadedExecute( void *arg ) +{ + vtkImageMultiThreadStruct *str; + int ext[6], splitExt[6], total; + int threadId, threadCount; + + threadId = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + + str = (vtkImageMultiThreadStruct *)(((vtkMultiThreader::ThreadInfo *)(arg))->UserData); + + memcpy(ext,str->Filter->GetOutput()->GetUpdateExtent(), + sizeof(int)*6); + + // execute the actual method with appropriate extent + // first find out how many pieces extent can be split into. + total = str->Filter->SplitExtent(splitExt, ext, threadId, threadCount); + + if (threadId < total) + { + str->Filter->ThreadedExecute(str->Inputs, str->Outputs, splitExt, threadId); + } + // else + // { + // otherwise don't use this thread. Sometimes the threads dont + // break up very well and it is just as efficient to leave a + // few threads idle. + // } + + return VTK_THREAD_RETURN_VALUE; +} + + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkImageMultipleInputOutputFilter::ExecuteData(vtkDataObject *out) +{ + vtkImageData *output = vtkImageData::SafeDownCast(out); + if (!output) + { + vtkWarningMacro("ExecuteData called without ImageData output"); + return; + } + + // Too many filters have floating point exceptions to execute + // with empty input/ no request. + if (this->UpdateExtentIsEmpty(output)) + { + return; + } + + output->SetExtent(output->GetUpdateExtent()); + output->AllocateScalars(); + + vtkImageMultiThreadStruct str; + + str.Filter = this; + str.Inputs = (vtkImageData **)this->Inputs; + str.Outputs = (vtkImageData **)this->Outputs; + + this->Threader->SetNumberOfThreads(this->NumberOfThreads); + + // setup threading and the invoke threadedExecute + this->Threader->SetSingleMethod(vtkImageMultiInOutThreadedExecute, &str); + this->Threader->SingleMethodExecute(); +} + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkImageMultipleInputOutputFilter:: +ThreadedExecute(vtkImageData **vtkNotUsed(inData), + vtkImageData **vtkNotUsed(outData), + int extent[6], int vtkNotUsed(threadId)) +{ + extent = extent; + vtkErrorMacro("Subclass should override this method!!!"); +} + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkImageMultipleInputOutputFilter:: +ThreadedExecute(vtkImageData **vtkNotUsed(inData), + vtkImageData *vtkNotUsed(outData), + int extent[6], int vtkNotUsed(threadId)) +{ + extent = extent; + vtkErrorMacro("This method should not be called!"); +} diff --git a/Filtering/vtkImageMultipleInputOutputFilter.h b/Filtering/vtkImageMultipleInputOutputFilter.h new file mode 100644 index 0000000..d65ddb2 --- /dev/null +++ b/Filtering/vtkImageMultipleInputOutputFilter.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMultipleInputOutputFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMultipleInputOutputFilter - Generic filter that has N inputs. +// .SECTION Description +// vtkImageMultipleInputOutputFilter is a super class for filters that +// have any number of inputs. Steaming is not available in this class yet. + +// .SECTION See Also +// vtkImageToImageFilter vtkImageInPlaceFilter vtkImageTwoInputFilter + + + +#ifndef __vtkImageMultipleInputOutputFilter_h +#define __vtkImageMultipleInputOutputFilter_h + + +#include "vtkImageMultipleInputFilter.h" + + +class VTK_FILTERING_EXPORT vtkImageMultipleInputOutputFilter : public vtkImageMultipleInputFilter +{ +public: + vtkTypeRevisionMacro(vtkImageMultipleInputOutputFilter,vtkImageMultipleInputFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get one input to this filter. + vtkImageData *GetOutput(int num); + vtkImageData *GetOutput(); + + // Description: + // The execute method created by the subclass. + // This is kept public instead of protected since it is called + // from a non-member thread function. + virtual void ThreadedExecute(vtkImageData **inDatas, + vtkImageData **outDatas, + int extent[6], int threadId); + +protected: + vtkImageMultipleInputOutputFilter(); + ~vtkImageMultipleInputOutputFilter(); + + void ComputeInputUpdateExtents( vtkDataObject *output ); + + virtual void ComputeInputUpdateExtent( int inExt[6], + int outExt[6], + int whichInput ); + + + void ExecuteData(vtkDataObject *out); + + // this should never be called + virtual void ThreadedExecute(vtkImageData **inDatas, + vtkImageData *outData, + int extent[6], int threadId); + virtual void ExecuteInformation(vtkImageData **, vtkImageData *) {}; + + // This one gets called by the superclass. + void ExecuteInformation(); + // This is the one you should override. + virtual void ExecuteInformation(vtkImageData **, vtkImageData **) {}; +private: + vtkImageMultipleInputOutputFilter(const vtkImageMultipleInputOutputFilter&); // Not implemented. + void operator=(const vtkImageMultipleInputOutputFilter&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkImageProgressIterator.cxx b/Filtering/vtkImageProgressIterator.cxx new file mode 100644 index 0000000..9c9edb8 --- /dev/null +++ b/Filtering/vtkImageProgressIterator.cxx @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageProgressIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkConfigure.h" + +#if defined(_MSC_VER) && !defined(VTK_DISPLAY_WIN32_WARNINGS) +#pragma warning ( disable : 4275 ) +#endif + +#include "vtkImageIterator.txx" +#include "vtkImageProgressIterator.txx" + +#ifndef VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION + +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +#if defined(VTK_TYPE_USE_LONG_LONG) +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +#endif +#if defined(VTK_TYPE_USE___INT64) +template class VTK_FILTERING_EXPORT vtkImageProgressIterator<__int64>; +template class VTK_FILTERING_EXPORT vtkImageProgressIterator; +#endif + +#endif + diff --git a/Filtering/vtkImageProgressIterator.h b/Filtering/vtkImageProgressIterator.h new file mode 100644 index 0000000..9e20a8e --- /dev/null +++ b/Filtering/vtkImageProgressIterator.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageProgressIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageProgressIterator - a simple image iterator with progress +// .SECTION Description +// This is a simple image iterator that can be used to iterate over an +// image. Typically used to iterate over the output image + +// .SECTION See also +// vtkImageData vtkImageIterator + +#ifndef __vtkImageProgressIterator_h +#define __vtkImageProgressIterator_h + +#include "vtkImageIterator.h" +class vtkAlgorithm; + +template +class vtkImageProgressIterator : public vtkImageIterator +{ +public: + typedef vtkImageIterator Superclass; + + // Description: + // Create a progress iterator for the provided image data + // and extent to iterate over. The passes progress object will + // receive any UpdateProgress calls if the thread id is zero + vtkImageProgressIterator(vtkImageData *imgd, int *ext, + vtkAlgorithm *po, int id); + + // Description: + // Move the iterator to the next span, may call UpdateProgress on the + // filter (vtkAlgorithm) + void NextSpan(); + + // Description: + // Overridden from vtkImageIterator to check AbortExecute on the + // filter (vtkAlgorithm). + int IsAtEnd(); + +protected: + vtkAlgorithm *Algorithm; + unsigned long Count; + unsigned long Count2; + unsigned long Target; + int ID; +}; + +#ifdef VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION +#include "vtkImageProgressIterator.txx" +#endif + +#endif diff --git a/Filtering/vtkImageProgressIterator.txx b/Filtering/vtkImageProgressIterator.txx new file mode 100644 index 0000000..7196bcf --- /dev/null +++ b/Filtering/vtkImageProgressIterator.txx @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageProgressIterator.txx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Include blockers needed since vtkImageProgressIterator.h includes +// this file when VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION is defined. +#ifndef __vtkImageProgressIterator_txx +#define __vtkImageProgressIterator_txx + +#include "vtkImageProgressIterator.h" +#include "vtkImageData.h" +#include "vtkAlgorithm.h" + +template +vtkImageProgressIterator::vtkImageProgressIterator(vtkImageData *imgd, + int *ext, + vtkAlgorithm *po, + int id) : + vtkImageIterator(imgd,ext) +{ + this->Target = + (unsigned long)((ext[5] - ext[4]+1)*(ext[3] - ext[2]+1)/50.0); + this->Target++; + this->Count = 0; + this->Count2 = 0; + this->Algorithm = po; + this->ID = id; +} + +template +void vtkImageProgressIterator::NextSpan() +{ + this->Pointer += this->Increments[1]; + this->SpanEndPointer += this->Increments[1]; + if (this->Pointer >= this->SliceEndPointer) + { + this->Pointer += this->ContinuousIncrements[2]; + this->SpanEndPointer += this->ContinuousIncrements[2]; + this->SliceEndPointer += this->Increments[2]; + } + if (!this->ID) + { + if (this->Count2 == this->Target) + { + this->Count += this->Count2; + this->Algorithm->UpdateProgress(this->Count/(50.0*this->Target)); + this->Count2 = 0; + } + this->Count2++; + } +} + +template +int vtkImageProgressIterator::IsAtEnd() +{ + if(this->Algorithm->GetAbortExecute()) + { + return 1; + } + else + { + return this->Superclass::IsAtEnd(); + } +} + +#endif diff --git a/Filtering/vtkImageSource.cxx b/Filtering/vtkImageSource.cxx new file mode 100644 index 0000000..732abee --- /dev/null +++ b/Filtering/vtkImageSource.cxx @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSource.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageSource, "$Revision: 1.62 $"); + +//---------------------------------------------------------------------------- +vtkImageSource::vtkImageSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + + this->vtkSource::SetNthOutput(0,vtkImageData::New()); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkImageSource::SetOutput(vtkImageData *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkImageData *vtkImageSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkImageData *)(this->Outputs[0]); +} + + +//---------------------------------------------------------------------------- +// Convert to Imaging API +void vtkImageSource::Execute() +{ + vtkImageData *output = this->GetOutput(); + + // If we have multiple Outputs, they need to be allocate + // in a subclass. We cannot be sure all outputs are images. + output->SetExtent(output->GetUpdateExtent()); + output->AllocateScalars(); + output->GetPointData()->GetScalars()->SetName("Scalars"); + + this->Execute(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// This function can be defined in a subclass to generate the data +// for a region. +void vtkImageSource::Execute(vtkImageData *) +{ + vtkErrorMacro(<< "Execute(): Method not defined."); +} + + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageSource::AllocateOutputData(vtkDataObject *out) +{ + vtkImageData *res = vtkImageData::SafeDownCast(out); + if (!res) + { + vtkWarningMacro("Call to AllocateOutputData with non vtkImageData output"); + return NULL; + } + + // I would like to eliminate this method which requires extra "information" + // That is not computed in the graphics pipeline. + // Until I can eliminate the method, I will reexecute the ExecuteInformation + // before the execute. + this->ExecuteInformation(); + + res->SetExtent(res->GetUpdateExtent()); + res->AllocateScalars(); + + return res; +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageSource::GetOutput(int idx) +{ + return (vtkImageData *) this->vtkSource::GetOutput(idx); +} + +//---------------------------------------------------------------------------- +int vtkImageSource::FillOutputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkImageSource.h b/Filtering/vtkImageSource.h new file mode 100644 index 0000000..66a21f9 --- /dev/null +++ b/Filtering/vtkImageSource.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSource - Source of data for the imaging pipeline +// .SECTION Description +// vtkImageSource is the superclass for all imaging sources and filters. +// The method Update(), called by the cache, is the major interface +// to the source. + +// .SECTION See Also +// vtkImageToImageFilter + + +#ifndef __vtkImageSource_h +#define __vtkImageSource_h + +#include "vtkSource.h" + +class vtkImageData; + +class VTK_FILTERING_EXPORT vtkImageSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkImageSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this source. + void SetOutput(vtkImageData *output); + vtkImageData *GetOutput(); + vtkImageData *GetOutput(int idx); + +protected: + vtkImageSource(); + ~vtkImageSource() {}; + + void Execute(); + virtual void Execute(vtkImageData *data); + + // a helper method that sets the extent and allocates the output + // passed into it and returns it as an image data + virtual vtkImageData *AllocateOutputData(vtkDataObject *out); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkImageSource(const vtkImageSource&); // Not implemented. + void operator=(const vtkImageSource&); // Not implemented. +}; + + +#endif + + diff --git a/Filtering/vtkImageToImageFilter.cxx b/Filtering/vtkImageToImageFilter.cxx new file mode 100644 index 0000000..e47d479 --- /dev/null +++ b/Filtering/vtkImageToImageFilter.cxx @@ -0,0 +1,455 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToImageFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageToImageFilter.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageToImageFilter, "$Revision: 1.62 $"); + +//---------------------------------------------------------------------------- +vtkImageToImageFilter::vtkImageToImageFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); + this->Bypass = 0; + this->Threader = vtkMultiThreader::New(); + this->NumberOfThreads = this->Threader->GetNumberOfThreads(); + this->InputScalarsSelection = NULL; +} + +//---------------------------------------------------------------------------- +vtkImageToImageFilter::~vtkImageToImageFilter() +{ + this->Threader->Delete(); + this->SetInputScalarsSelection(NULL); +} + +//---------------------------------------------------------------------------- +void vtkImageToImageFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfThreads: " << this->NumberOfThreads << "\n"; + + if ( this->Bypass ) + { + os << indent << "Bypass: On\n"; + } + else + { + os << indent << "Bypass: Off\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkImageToImageFilter::SetInput(vtkImageData *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageToImageFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkImageData *)(this->Inputs[0]); +} + + + +//---------------------------------------------------------------------------- +// This method can be overriden in a subclass to compute the output +// Information: WholeExtent, Spacing, Origin, ScalarType and +// NumberOfScalarComponents. +void vtkImageToImageFilter::ExecuteInformation() +{ + vtkImageData *input = this->GetInput(); + vtkImageData *output = this->GetOutput(); + + // Make sure the Input has been set. + if ( input == NULL || output == NULL) + { + if (output) + { + // this means that input is NULL, but the output isn't + // in order to make this clear to filters down the line, we + // make sure outputData is completely empty + output->SetExtent(0, -1, 0, -1, 0, -1); + output->SetWholeExtent(0, -1, 0, -1, 0, -1); + output->SetUpdateExtent(0, -1, 0, -1, 0, -1); + output->AllocateScalars(); + } + vtkErrorMacro(<< "ExecuteInformation: Input is not set."); + return; + } + + // Start with some defaults. + output->CopyTypeSpecificInformation( input ); + + // take this opportunity to modify the defaults + this->ExecuteInformation(input, output); +} + +//---------------------------------------------------------------------------- +void vtkImageToImageFilter::ExecuteInformation( + vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)) +{ +} + +//---------------------------------------------------------------------------- + +// Call the alternate version of this method, and use the returned input +// update extent for all inputs +void vtkImageToImageFilter::ComputeInputUpdateExtents( vtkDataObject *output ) +{ + int outExt[6], inExt[6]; + + output->GetUpdateExtent( outExt ); + + if (this->NumberOfInputs) + { + this->ComputeInputUpdateExtent( inExt, outExt ); + } + + for (int idx = 0; idx < this->NumberOfInputs; ++idx) + { + if (this->Inputs[idx] != NULL) + { + if (this->Inputs[idx]->GetRequestExactExtent()) + { + int *currentExt = this->Inputs[idx]->GetUpdateExtent(); + for (int i = 0; i < 6; i += 2) + { + if (inExt[i] < currentExt[i] || + inExt[i+1] > currentExt[i+1]) + { + this->Inputs[idx]->SetUpdateExtent( inExt ); + break; + } + } + } + else + { + this->Inputs[idx]->SetUpdateExtent( inExt ); + } + } + } +} + +// By default, simply set the input update extent to match the given output +// extent +void vtkImageToImageFilter::ComputeInputUpdateExtent( int inExt[6], + int outExt[6] ) +{ + memcpy(inExt,outExt,sizeof(int)*6); +} + + + + +struct vtkImageThreadStruct +{ + vtkImageToImageFilter *Filter; + vtkImageData *Input; + vtkImageData *Output; +}; + + + +// this mess is really a simple function. All it does is call +// the ThreadedExecute method after setting the correct +// extent for this thread. Its just a pain to calculate +// the correct extent. +VTK_THREAD_RETURN_TYPE vtkImageThreadedExecute( void *arg ) +{ + vtkImageThreadStruct *str; + int ext[6], splitExt[6], total; + int threadId, threadCount; + vtkImageData *output; + + threadId = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + + str = (vtkImageThreadStruct *)(((vtkMultiThreader::ThreadInfo *)(arg))->UserData); + output = str->Output; + output->GetUpdateExtent( ext ); + + // execute the actual method with appropriate extent + // first find out how many pieces extent can be split into. + total = str->Filter->SplitExtent(splitExt, ext, threadId, threadCount); + //total = 1; + + if (threadId < total) + { + str->Filter->ThreadedExecute(str->Input, str->Output, splitExt, threadId); + } + // else + // { + // otherwise don't use this thread. Sometimes the threads dont + // break up very well and it is just as efficient to leave a + // few threads idle. + // } + + return VTK_THREAD_RETURN_VALUE; +} + +//---------------------------------------------------------------------------- +// For streaming and threads. Splits output update extent into num pieces. +// This method needs to be called num times. Results must not overlap for +// consistent starting extent. Subclass can override this method. +// This method returns the number of peices resulting from a successful split. +// This can be from 1 to "total". +// If 1 is returned, the extent cannot be split. +int vtkImageToImageFilter::SplitExtent(int splitExt[6], int startExt[6], + int num, int total) +{ + int splitAxis; + int min, max; + + vtkDebugMacro("SplitExtent: ( " << startExt[0] << ", " << startExt[1] << ", " + << startExt[2] << ", " << startExt[3] << ", " + << startExt[4] << ", " << startExt[5] << "), " + << num << " of " << total); + + // start with same extent + memcpy(splitExt, startExt, 6 * sizeof(int)); + + splitAxis = 2; + min = startExt[4]; + max = startExt[5]; + while (min == max) + { + --splitAxis; + if (splitAxis < 0) + { // cannot split + vtkDebugMacro(" Cannot Split"); + return 1; + } + min = startExt[splitAxis*2]; + max = startExt[splitAxis*2+1]; + } + + // determine the actual number of pieces that will be generated + int range = max - min + 1; + int valuesPerThread = (int)ceil(range/(double)total); + int maxThreadIdUsed = (int)ceil(range/(double)valuesPerThread) - 1; + if (num < maxThreadIdUsed) + { + splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; + splitExt[splitAxis*2+1] = splitExt[splitAxis*2] + valuesPerThread - 1; + } + if (num == maxThreadIdUsed) + { + splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; + } + + vtkDebugMacro(" Split Piece: ( " <GetInput(); + int inExt[6]; + int outExt[6]; + vtkDataArray *inArray; + vtkDataArray *outArray; + + input->GetExtent(inExt); + output->SetExtent(output->GetUpdateExtent()); + output->GetExtent(outExt); + + // Do not copy the array we will be generating. + inArray = input->GetPointData()->GetScalars(this->InputScalarsSelection); + + // Conditionally copy point and cell data. + // Only copy if corresponding indexes refer to identical points. + double *oIn = input->GetOrigin(); + double *sIn = input->GetSpacing(); + double *oOut = output->GetOrigin(); + double *sOut = output->GetSpacing(); + if (oIn[0] == oOut[0] && oIn[1] == oOut[1] && oIn[2] == oOut[2] && + sIn[0] == sOut[0] && sIn[1] == sOut[1] && sIn[2] == sOut[2]) + { + output->GetPointData()->CopyAllOn(); + output->GetCellData()->CopyAllOn(); + // Scalar copy flag trumps the array copy flag. + if (inArray == input->GetPointData()->GetScalars()) + { + output->GetPointData()->CopyScalarsOff(); + } + else + { + output->GetPointData()->CopyFieldOff(this->InputScalarsSelection); + } + + // If the extents are the same, then pass the attribute data for efficiency. + if (inExt[0] == outExt[0] && inExt[1] == outExt[1] && + inExt[2] == outExt[2] && inExt[3] == outExt[3] && + inExt[4] == outExt[4] && inExt[5] == outExt[5]) + {// Pass + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + } + else + {// Copy + // Since this can be expensive to copy all of these values, + // lets make sure there are arrays to copy (other than the scalars) + if (input->GetPointData()->GetNumberOfArrays() > 1) + { + // Copy the point data. + // CopyAllocate frees all arrays. + // Keep the old scalar array (not being copied). + // This is a hack, but avoids reallocation ... + vtkDataArray *tmp = NULL; + if ( ! output->GetPointData()->GetCopyScalars() ) + { + tmp = output->GetPointData()->GetScalars(); + } + output->GetPointData()->CopyAllocate(input->GetPointData(), + output->GetNumberOfPoints()); + if (tmp) + { // Restore the array. + output->GetPointData()->SetScalars(tmp); + } + // Now Copy The point data, but only if output is a subextent of the input. + if (outExt[0] >= inExt[0] && outExt[1] <= inExt[1] && + outExt[2] >= inExt[2] && outExt[3] <= inExt[3] && + outExt[4] >= inExt[4] && outExt[5] <= inExt[5]) + { + output->GetPointData()->CopyStructuredData(input->GetPointData(), + inExt, outExt); + } + } + + if (input->GetCellData()->GetNumberOfArrays() > 0) + { + output->GetCellData()->CopyAllocate(input->GetCellData(), + output->GetNumberOfCells()); + // Cell extent is one less than point extent. + // Conditional to handle a colapsed axis (lower dimensional cells). + if (inExt[0] < inExt[1]) {--inExt[1];} + if (inExt[2] < inExt[3]) {--inExt[3];} + if (inExt[4] < inExt[5]) {--inExt[5];} + // Cell extent is one less than point extent. + if (outExt[0] < outExt[1]) {--outExt[1];} + if (outExt[2] < outExt[3]) {--outExt[3];} + if (outExt[4] < outExt[5]) {--outExt[5];} + // Now Copy The cell data, but only if output is a subextent of the input. + if (outExt[0] >= inExt[0] && outExt[1] <= inExt[1] && + outExt[2] >= inExt[2] && outExt[3] <= inExt[3] && + outExt[4] >= inExt[4] && outExt[5] <= inExt[5]) + { + output->GetCellData()->CopyStructuredData(input->GetCellData(), + inExt, outExt); + } + } + } + } + + // Now create the scalars array that will hold the output data. + this->ExecuteInformation(); + output->AllocateScalars(); + outArray = output->GetPointData()->GetScalars(); + if (inArray) + { + outArray->SetName(inArray->GetName()); + } + return output; +} + + + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +void vtkImageToImageFilter::ExecuteData(vtkDataObject *out) +{ + // Make sure the Input has been set. + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<< "ExecuteData: Input is not set."); + return; + } + + // Too many filters have floating point exceptions to execute + // with empty input/ no request. + if (this->UpdateExtentIsEmpty(out)) + { + return; + } + + vtkImageData *outData = this->AllocateOutputData(out); + int debug = this->Debug; + this->Debug = 0; + this->MultiThread(this->GetInput(),outData); + this->Debug = debug; +} + +void vtkImageToImageFilter::MultiThread(vtkImageData *inData, + vtkImageData *outData) +{ + vtkImageThreadStruct str; + + str.Filter = this; + str.Input = inData; + str.Output = outData; + + this->Threader->SetNumberOfThreads(this->NumberOfThreads); + + // setup threading and the invoke threadedExecute + this->Threader->SetSingleMethod(vtkImageThreadedExecute, &str); + this->Threader->SingleMethodExecute(); +} + + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkImageToImageFilter::ThreadedExecute(vtkImageData *vtkNotUsed(inData), + vtkImageData *vtkNotUsed(outData), + int extent[6], int threadId) +{ + extent = extent; + if (threadId == 0) + { + vtkErrorMacro("subclass should override ThreadedExecute!!!"); + } +} + +//---------------------------------------------------------------------------- +int vtkImageToImageFilter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} diff --git a/Filtering/vtkImageToImageFilter.h b/Filtering/vtkImageToImageFilter.h new file mode 100644 index 0000000..fd8849e --- /dev/null +++ b/Filtering/vtkImageToImageFilter.h @@ -0,0 +1,118 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToImageFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageToImageFilter - Generic filter that has one input.. +// .SECTION Description +// vtkImageToImageFilter is a filter superclass that hides much of the +// pipeline complexity. It handles breaking the pipeline execution +// into smaller extents so that the vtkImageData limits are observed. It +// also provides support for multithreading. If you don't need any of this +// functionality, consider using vtkSimpleImageToImageFilter instead. +// .SECTION See also +// vtkSimpleImageToImageFilter + +#ifndef __vtkImageToImageFilter_h +#define __vtkImageToImageFilter_h + +#include "vtkImageSource.h" + +class vtkMultiThreader; + +class VTK_FILTERING_EXPORT vtkImageToImageFilter : public vtkImageSource +{ +public: + vtkTypeRevisionMacro(vtkImageToImageFilter,vtkImageSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the Input of a filter. + virtual void SetInput(vtkImageData *input); + vtkImageData *GetInput(); + + // Description: + // Obsolete feature - do not use. + void SetBypass( int ) {}; + void BypassOn() {}; + void BypassOff() {}; + vtkGetMacro(Bypass,int); + + // Description: + // If the subclass does not define an Execute method, then the task + // will be broken up, multiple threads will be spawned, and each thread + // will call this method. It is public so that the thread functions + // can call this method. + virtual void ThreadedExecute(vtkImageData *inData, + vtkImageData *outData, + int extent[6], int threadId); + + // Description: + // Get/Set the number of threads to create when rendering + vtkSetClampMacro( NumberOfThreads, int, 1, VTK_MAX_THREADS ); + vtkGetMacro( NumberOfThreads, int ); + + void SetInputMemoryLimit(int) + {vtkErrorMacro( << "SetInputMemoryLimit is obsolete: Use a vtkImageDataStreamer instead!" );}; + long GetInputMemoryLimit() + {vtkErrorMacro( << "GetInputMemoryLimit is obsolete: Use a vtkImageDataStreamer instead!" ); return 0;}; + + // Description: + // Putting this here until I merge graphics and imaging streaming. + virtual int SplitExtent(int splitExt[6], int startExt[6], + int num, int total); + +protected: + vtkImageToImageFilter(); + ~vtkImageToImageFilter(); + + vtkMultiThreader *Threader; + int Bypass; + int BypassWasOn; + int NumberOfThreads; + + // This is called by the superclass. + void ExecuteInformation(); + // This is the method you should override. + virtual void ExecuteInformation(vtkImageData *inData, vtkImageData *outData); + + // This is called by the superclass. + // This is the method you should override. + void ExecuteData(vtkDataObject *output); + + // This also copies other arrays from point and cell data from input to output. + virtual vtkImageData *AllocateOutputData(vtkDataObject *out); + + // The method that starts the multithreading + void MultiThread(vtkImageData *input, vtkImageData *output); + + void ComputeInputUpdateExtents( vtkDataObject *output ); + virtual void ComputeInputUpdateExtent(int inExt[6], int outExt[6]); + + char *InputScalarsSelection; + vtkSetStringMacro(InputScalarsSelection); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkImageToImageFilter(const vtkImageToImageFilter&); // Not implemented. + void operator=(const vtkImageToImageFilter&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkImageToStructuredPoints.cxx b/Filtering/vtkImageToStructuredPoints.cxx new file mode 100644 index 0000000..7cd2b2b --- /dev/null +++ b/Filtering/vtkImageToStructuredPoints.cxx @@ -0,0 +1,339 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToStructuredPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageToStructuredPoints.h" + +#include "vtkCellData.h" +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredPoints.h" + +#include + +vtkCxxRevisionMacro(vtkImageToStructuredPoints, "$Revision: 1.62 $"); +vtkStandardNewMacro(vtkImageToStructuredPoints); + +//---------------------------------------------------------------------------- +vtkImageToStructuredPoints::vtkImageToStructuredPoints() +{ + this->SetNumberOfInputPorts(2); + this->Translate[0] = this->Translate[1] = this->Translate[2] = 0; +} + +//---------------------------------------------------------------------------- +vtkImageToStructuredPoints::~vtkImageToStructuredPoints() +{ +} + + +//---------------------------------------------------------------------------- +void vtkImageToStructuredPoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +void vtkImageToStructuredPoints::SetVectorInput(vtkImageData *input) +{ + this->SetInput(1, input); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageToStructuredPoints::GetVectorInput() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + + return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(1, 0)); +} + +//---------------------------------------------------------------------------- +int vtkImageToStructuredPoints::RequestData( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *vectorInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int uExtent[6]; + int *wExtent; + + int idxX, idxY, idxZ; + int maxX = 0; + int maxY = 0; + int maxZ = 0;; + vtkIdType inIncX, inIncY, inIncZ; + int rowLength; + unsigned char *inPtr1, *inPtr, *outPtr; + vtkStructuredPoints *output = vtkStructuredPoints::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *data = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *vData = 0; + if (vectorInfo) + { + vData = vtkImageData::SafeDownCast( + vectorInfo->Get(vtkDataObject::DATA_OBJECT())); + } + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + uExtent); + output->SetExtent(uExtent); + + uExtent[0] += this->Translate[0]; + uExtent[1] += this->Translate[0]; + uExtent[2] += this->Translate[1]; + uExtent[3] += this->Translate[1]; + uExtent[4] += this->Translate[2]; + uExtent[5] += this->Translate[2]; + + // if the data extent matches the update extent then just pass the data + // otherwise we must reformat and copy the data + if (data) + { + wExtent = data->GetExtent(); + if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] && + wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] && + wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5]) + { + if (data->GetPointData()) + { + output->GetPointData()->PassData(data->GetPointData()); + } + if (data->GetCellData()) + { + output->GetCellData()->PassData(data->GetCellData()); + } + if (data->GetFieldData()) + { + output->GetFieldData()->ShallowCopy(data->GetFieldData()); + } + } + else + { + inPtr = (unsigned char *) data->GetScalarPointerForExtent(uExtent); + outPtr = (unsigned char *) output->GetScalarPointer(); + + // Make sure there are data. + if(!inPtr || !outPtr) + { + output->Initialize(); + return 1; + } + + // Get increments to march through data + data->GetIncrements(inIncX, inIncY, inIncZ); + + // find the region to loop over + rowLength = (uExtent[1] - uExtent[0]+1)*inIncX*data->GetScalarSize(); + maxX = uExtent[1] - uExtent[0]; + maxY = uExtent[3] - uExtent[2]; + maxZ = uExtent[5] - uExtent[4]; + inIncY *= data->GetScalarSize(); + inIncZ *= data->GetScalarSize(); + + // Loop through output pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + inPtr1 = inPtr + idxZ*inIncZ; + for (idxY = 0; idxY <= maxY; idxY++) + { + memcpy(outPtr,inPtr1,rowLength); + inPtr1 += inIncY; + outPtr += rowLength; + } + } + } + } + + if (vData) + { + // if the data extent matches the update extent then just pass the data + // otherwise we must reformat and copy the data + wExtent = vData->GetExtent(); + if (wExtent[0] == uExtent[0] && wExtent[1] == uExtent[1] && + wExtent[2] == uExtent[2] && wExtent[3] == uExtent[3] && + wExtent[4] == uExtent[4] && wExtent[5] == uExtent[5]) + { + output->GetPointData()->SetVectors(vData->GetPointData()->GetScalars()); + } + else + { + vtkDataArray *fv = vtkDataArray::CreateDataArray(vData->GetScalarType()); + float *inPtr2 = (float *)(vData->GetScalarPointerForExtent(uExtent)); + + // Make sure there are data. + if(!inPtr2) + { + output->Initialize(); + return 1; + } + + fv->SetNumberOfComponents(3); + fv->SetNumberOfTuples((maxZ+1)*(maxY+1)*(maxX+1)); + vData->GetContinuousIncrements(uExtent, inIncX, inIncY, inIncZ); + int numComp = vData->GetNumberOfScalarComponents(); + int idx = 0; + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; idxY <= maxY; idxY++) + { + for (idxX = 0; idxX <= maxX; idxX++) + { + fv->SetTuple(idx,inPtr2); + inPtr2 += numComp; + idx++; + } + inPtr2 += inIncY; + } + inPtr2 += inIncZ; + } + output->GetPointData()->SetVectors(fv); + fv->Delete(); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Copy WholeExtent, Spacing and Origin. +int vtkImageToStructuredPoints::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *vInfo = inputVector[1]->GetInformationObject(0); + + int whole[6], *tmp; + double *spacing, origin[3]; + + vtkInformation *inScalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!inScalarInfo) + { + vtkErrorMacro("Missing scalar field on input information!"); + return 0; + } + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, + inScalarInfo->Get( vtkDataObject::FIELD_ARRAY_TYPE() ), + inScalarInfo->Get( vtkDataObject::FIELD_NUMBER_OF_COMPONENTS() ) ); + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),whole); + spacing = inInfo->Get(vtkDataObject::SPACING()); + inInfo->Get(vtkDataObject::ORIGIN(), origin); + + // intersections for whole extent + if (vInfo) + { + tmp = vInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + if (tmp[0] > whole[0]) {whole[0] = tmp[0];} + if (tmp[2] > whole[2]) {whole[2] = tmp[2];} + if (tmp[4] > whole[4]) {whole[4] = tmp[4];} + if (tmp[1] < whole[1]) {whole[1] = tmp[1];} + if (tmp[3] < whole[1]) {whole[3] = tmp[3];} + if (tmp[5] < whole[1]) {whole[5] = tmp[5];} + } + + // slide min extent to 0,0,0 (I Hate this !!!!) + this->Translate[0] = whole[0]; + this->Translate[1] = whole[2]; + this->Translate[2] = whole[4]; + + origin[0] += spacing[0] * whole[0]; + origin[1] += spacing[1] * whole[2]; + origin[2] += spacing[2] * whole[4]; + whole[1] -= whole[0]; + whole[3] -= whole[2]; + whole[5] -= whole[4]; + whole[0] = whole[2] = whole[4] = 0; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),whole,6); + // Now should Origin and Spacing really be part of information? + // How about xyx arrays in RectilinearGrid of Points in StructuredGrid? + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageToStructuredPoints::RequestUpdateExtent( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *vInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int ext[6]; + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext); + ext[0] += this->Translate[0]; + ext[1] += this->Translate[0]; + ext[2] += this->Translate[1]; + ext[3] += this->Translate[1]; + ext[4] += this->Translate[2]; + ext[5] += this->Translate[2]; + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + + if (vInfo) + { + vInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageToStructuredPoints::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredPoints"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageToStructuredPoints::FillInputPortInformation(int port, + vtkInformation *info) +{ + if (!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + return 1; +} diff --git a/Filtering/vtkImageToStructuredPoints.h b/Filtering/vtkImageToStructuredPoints.h new file mode 100644 index 0000000..5f18da9 --- /dev/null +++ b/Filtering/vtkImageToStructuredPoints.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToStructuredPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageToStructuredPoints - Attaches image pipeline to VTK. +// .SECTION Description +// vtkImageToStructuredPoints changes an image cache format to +// a structured points dataset. It takes an Input plus an optional +// VectorInput. The VectorInput converts the RGB scalar components +// of the VectorInput to vector pointdata attributes. This filter +// will try to reference count the data but in some cases it must +// make a copy. + +#ifndef __vtkImageToStructuredPoints_h +#define __vtkImageToStructuredPoints_h + +#include "vtkImageAlgorithm.h" + +class vtkImageData; +class vtkStructuredPoints; + +class VTK_FILTERING_EXPORT vtkImageToStructuredPoints : public vtkImageAlgorithm +{ +public: + static vtkImageToStructuredPoints *New(); + vtkTypeRevisionMacro(vtkImageToStructuredPoints,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the input object from the image pipeline. + void SetVectorInput(vtkImageData *input); + vtkImageData *GetVectorInput(); + +protected: + vtkImageToStructuredPoints(); + ~vtkImageToStructuredPoints(); + + // to translate the wholeExtent to have min 0 ( I do not like this hack). + int Translate[3]; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillOutputPortInformation(int, vtkInformation*); + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkImageToStructuredPoints(const vtkImageToStructuredPoints&); // Not implemented. + void operator=(const vtkImageToStructuredPoints&); // Not implemented. +}; + + +#endif + + diff --git a/Filtering/vtkImageTwoInputFilter.cxx b/Filtering/vtkImageTwoInputFilter.cxx new file mode 100644 index 0000000..4f56bc5 --- /dev/null +++ b/Filtering/vtkImageTwoInputFilter.cxx @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageTwoInputFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageTwoInputFilter.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageTwoInputFilter, "$Revision: 1.27 $"); + +//---------------------------------------------------------------------------- +vtkImageTwoInputFilter::vtkImageTwoInputFilter() +{ + this->NumberOfRequiredInputs = 2; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +// Set the Input1 of this filter. If a ScalarType has not been set, +// then the ScalarType of the input is used. +void vtkImageTwoInputFilter::SetInput1(vtkImageData *input) +{ + this->vtkImageMultipleInputFilter::SetNthInput(0,input); +} + +//---------------------------------------------------------------------------- +// Set the Input2 of this filter. If a ScalarType has not been set, +// then the ScalarType of the input is used. +void vtkImageTwoInputFilter::SetInput2(vtkImageData *input) +{ + this->vtkImageMultipleInputFilter::SetNthInput(1,input); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageTwoInputFilter::GetInput1() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + return (vtkImageData *)this->Inputs[0]; +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageTwoInputFilter::GetInput2() +{ + if (this->NumberOfInputs < 2) + { + return NULL; + } + return (vtkImageData *)this->Inputs[1]; +} + +//---------------------------------------------------------------------------- +void vtkImageTwoInputFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkImageTwoInputFilter.h b/Filtering/vtkImageTwoInputFilter.h new file mode 100644 index 0000000..11df09d --- /dev/null +++ b/Filtering/vtkImageTwoInputFilter.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageTwoInputFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageTwoInputFilter - Generic superclass for filters that have +// two inputs. +// .SECTION Description +// vtkImageTwoInputFilter handles two inputs. +// It is just a subclass of vtkImageMultipleInputFilter with some +// methods that are specific to two inputs. Although the inputs are labeled +// input1 and input2, they are stored in an array indexed starting at 0. + +#ifndef __vtkImageTwoInputFilter_h +#define __vtkImageTwoInputFilter_h + +#include "vtkImageMultipleInputFilter.h" + +class VTK_FILTERING_EXPORT vtkImageTwoInputFilter : public vtkImageMultipleInputFilter +{ +public: + vtkTypeRevisionMacro(vtkImageTwoInputFilter,vtkImageMultipleInputFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the Input1 of this filter. If a ScalarType has not been set, + // then the ScalarType of the input is used. + virtual void SetInput1(vtkImageData *input); + + // Description: + // Set the Input2 of this filter. If a ScalarType has not been set, + // then the ScalarType of the input is used. + virtual void SetInput2(vtkImageData *input); + + // Description: + // Get the inputs to this filter. + vtkImageData *GetInput1(); + vtkImageData *GetInput2(); + +protected: + vtkImageTwoInputFilter(); + ~vtkImageTwoInputFilter() {}; + +private: + vtkImageTwoInputFilter(const vtkImageTwoInputFilter&); // Not implemented. + void operator=(const vtkImageTwoInputFilter&); // Not implemented. +}; + +#endif + + + + + + + + diff --git a/Filtering/vtkImplicitBoolean.cxx b/Filtering/vtkImplicitBoolean.cxx new file mode 100644 index 0000000..09b68a1 --- /dev/null +++ b/Filtering/vtkImplicitBoolean.cxx @@ -0,0 +1,251 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitBoolean.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitBoolean.h" + +#include "vtkImplicitFunctionCollection.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImplicitBoolean, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkImplicitBoolean); + +// Construct with union operation. +vtkImplicitBoolean::vtkImplicitBoolean() +{ + this->OperationType = VTK_UNION; + this->FunctionList = vtkImplicitFunctionCollection::New(); +} + +vtkImplicitBoolean::~vtkImplicitBoolean() +{ + this->FunctionList->Delete(); +} + +unsigned long int vtkImplicitBoolean::GetMTime() +{ + unsigned long int fMtime; + unsigned long int mtime = this->vtkImplicitFunction::GetMTime(); + vtkImplicitFunction *f; + + vtkCollectionSimpleIterator sit; + for (this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + fMtime = f->GetMTime(); + if ( fMtime > mtime ) + { + mtime = fMtime; + } + } + return mtime; +} + +// Add another implicit function to the list of functions. +void vtkImplicitBoolean::AddFunction(vtkImplicitFunction *f) +{ + if ( ! this->FunctionList->IsItemPresent(f) ) + { + this->Modified(); + this->FunctionList->AddItem(f); + } +} + +// Remove a function from the list of implicit functions to boolean. +void vtkImplicitBoolean::RemoveFunction(vtkImplicitFunction *f) +{ + if ( this->FunctionList->IsItemPresent(f) ) + { + this->Modified(); + this->FunctionList->RemoveItem(f); + } +} + +// Evaluate boolean combinations of implicit function using current operator. +double vtkImplicitBoolean::EvaluateFunction(double x[3]) +{ + double value = 0; + double v; + vtkImplicitFunction *f; + + if (this->FunctionList->GetNumberOfItems() == 0) + { + return value; + } + + vtkCollectionSimpleIterator sit; + if ( this->OperationType == VTK_UNION ) + { //take minimum value + for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( (v=f->FunctionValue(x)) < value ) + { + value = v; + } + } + } + + else if ( this->OperationType == VTK_INTERSECTION ) + { //take maximum value + for (value=-VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( (v=f->FunctionValue(x)) > value ) + { + value = v; + } + } + } + + else if ( this->OperationType == VTK_UNION_OF_MAGNITUDES ) + { //take minimum absolute value + for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( (v=fabs(f->FunctionValue(x))) < value ) + { + value = v; + } + } + } + + else //difference + { + vtkImplicitFunction *firstF; + this->FunctionList->InitTraversal(sit); + if ( (firstF = this->FunctionList->GetNextImplicitFunction(sit)) != NULL ) + { + value = firstF->FunctionValue(x); + } + + for (this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( f != firstF ) + { + if ( (v=(-1.0)*f->FunctionValue(x)) > value ) + { + value = v; + } + } + } + }//else + + return value; +} + +// Evaluate gradient of boolean combination. +void vtkImplicitBoolean::EvaluateGradient(double x[3], double g[3]) +{ + double value = 0; + double v; + vtkImplicitFunction *f; + vtkCollectionSimpleIterator sit; + + if (this->FunctionList->GetNumberOfItems() == 0) + { + g[0] = 0; g[1] = 0; g[2] = 0; + return; + } + + if ( this->OperationType == VTK_UNION ) + { //take minimum value + for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( (v=f->FunctionValue(x)) < value ) + { + value = v; + f->FunctionGradient(x,g); + } + } + } + + else if ( this->OperationType == VTK_INTERSECTION ) + { //take maximum value + for (value=-VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( (v=f->FunctionValue(x)) > value ) + { + value = v; + f->FunctionGradient(x,g); + } + } + } + + if ( this->OperationType == VTK_UNION_OF_MAGNITUDES ) + { //take minimum value + for (value = VTK_DOUBLE_MAX, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( (v=fabs(f->FunctionValue(x))) < value ) + { + value = v; + f->FunctionGradient(x,g); + } + } + } + + else //difference + { + double gTemp[3]; + vtkImplicitFunction *firstF; + this->FunctionList->InitTraversal(sit); + if ( (firstF = this->FunctionList->GetNextImplicitFunction(sit)) != NULL ) + { + value = firstF->FunctionValue(x); + firstF->FunctionGradient(x,gTemp); + g[0] = -1.0*gTemp[0]; g[1] = -1.0*gTemp[1]; g[2] = -1.0*gTemp[2]; + } + + for (this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + if ( f != firstF ) + { + if ( (v=(-1.0)*f->FunctionValue(x)) > value ) + { + value = v; + f->FunctionGradient(x,gTemp); + g[0] = -1.0*gTemp[0]; g[1] = -1.0*gTemp[1]; g[2] = -1.0*gTemp[2]; + } + } + } + }//else +} + +void vtkImplicitBoolean::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Function List:\n"; + this->FunctionList->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Operator Type: "; + if ( this->OperationType == VTK_INTERSECTION ) + { + os << "VTK_INTERSECTION\n"; + } + else if ( this->OperationType == VTK_UNION ) + { + os << "VTK_UNION\n"; + } + else + { + os << "VTK_INTERSECTION\n"; + } +} diff --git a/Filtering/vtkImplicitBoolean.h b/Filtering/vtkImplicitBoolean.h new file mode 100644 index 0000000..3cdfae1 --- /dev/null +++ b/Filtering/vtkImplicitBoolean.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitBoolean.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitBoolean - implicit function consisting of boolean combinations of implicit functions +// .SECTION Description +// vtkImplicitBoolean is an implicit function consisting of boolean +// combinations of implicit functions. The class has a list of functions +// (FunctionList) that are combined according to a specified operator +// (VTK_UNION or VTK_INTERSECTION or VTK_DIFFERENCE). You can use nested +// combinations of vtkImplicitFunction's (and/or vtkImplicitBoolean) to create +// elaborate implicit functions. vtkImplicitBoolean is a concrete +// implementation of vtkImplicitFunction. +// +// The operators work as follows. The VTK_UNION operator takes the minimum +// value of all implicit functions. The VTK_INTERSECTION operator takes the +// maximum value of all implicit functions. The VTK_DIFFERENCE operator +// subtracts the 2nd through last implicit functions from the first. The +// VTK_UNION_OF_MAGNITUDES takes the minimum absolute value of the +// implicit functions. + +#ifndef __vtkImplicitBoolean_h +#define __vtkImplicitBoolean_h + +#include "vtkImplicitFunction.h" + +class vtkImplicitFunctionCollection; + +#define VTK_UNION 0 +#define VTK_INTERSECTION 1 +#define VTK_DIFFERENCE 2 +#define VTK_UNION_OF_MAGNITUDES 3 + +class VTK_FILTERING_EXPORT vtkImplicitBoolean : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkImplicitBoolean,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Default boolean method is union. + static vtkImplicitBoolean *New(); + + // Description: + // Evaluate boolean combinations of implicit function using current operator. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description: + // Evaluate gradient of boolean combination. + void EvaluateGradient(double x[3], double g[3]); + + // Description: + // Override modified time retrieval because of object dependencies. + unsigned long GetMTime(); + + // Description: + // Add another implicit function to the list of functions. + void AddFunction(vtkImplicitFunction *in); + + // Description: + // Remove a function from the list of implicit functions to boolean. + void RemoveFunction(vtkImplicitFunction *in); + + // Description: + // Return the collection of implicit functions. + vtkImplicitFunctionCollection *GetFunction() {return this->FunctionList;}; + + // Description: + // Specify the type of boolean operation. + vtkSetClampMacro(OperationType,int,VTK_UNION,VTK_UNION_OF_MAGNITUDES); + vtkGetMacro(OperationType,int); + void SetOperationTypeToUnion() + {this->SetOperationType(VTK_UNION);}; + void SetOperationTypeToIntersection() + {this->SetOperationType(VTK_INTERSECTION);}; + void SetOperationTypeToDifference() + {this->SetOperationType(VTK_DIFFERENCE);}; + void SetOperationTypeToUnionOfMagnitudes() + {this->SetOperationType(VTK_UNION_OF_MAGNITUDES);}; + const char *GetOperationTypeAsString(); + +protected: + vtkImplicitBoolean(); + ~vtkImplicitBoolean(); + + vtkImplicitFunctionCollection *FunctionList; + + int OperationType; + +private: + vtkImplicitBoolean(const vtkImplicitBoolean&); // Not implemented. + void operator=(const vtkImplicitBoolean&); // Not implemented. +}; + +// Description: +// Return the boolean operation type as a descriptive character string. +inline const char *vtkImplicitBoolean::GetOperationTypeAsString(void) +{ + if ( this->OperationType == VTK_UNION ) + { + return "Union"; + } + else if ( this->OperationType == VTK_INTERSECTION ) + { + return "Intersection"; + } + else if ( this->OperationType == VTK_DIFFERENCE ) + { + return "Difference"; + } + else + { + return "UnionOfMagnitudes"; + } +} + +#endif + + diff --git a/Filtering/vtkImplicitDataSet.cxx b/Filtering/vtkImplicitDataSet.cxx new file mode 100644 index 0000000..e371665 --- /dev/null +++ b/Filtering/vtkImplicitDataSet.cxx @@ -0,0 +1,195 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitDataSet.h" + +#include "vtkCell.h" +#include "vtkDataSet.h" +#include "vtkGarbageCollector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImplicitDataSet, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkImplicitDataSet); +vtkCxxSetObjectMacro(vtkImplicitDataSet,DataSet,vtkDataSet); + +// Construct an vtkImplicitDataSet with no initial dataset; the OutValue +// set to a large negative number; and the OutGradient set to (0,0,1). +vtkImplicitDataSet::vtkImplicitDataSet() +{ + this->DataSet = NULL; + + this->OutValue = -VTK_DOUBLE_MAX; + + this->OutGradient[0] = 0.0; + this->OutGradient[1] = 0.0; + this->OutGradient[2] = 1.0; + + this->Weights = NULL; + this->Size = 0; +} + +vtkImplicitDataSet::~vtkImplicitDataSet() +{ + this->SetDataSet(NULL); + if ( this->Weights ) + { + delete [] this->Weights; + } +} + +// Evaluate the implicit function. This returns the interpolated scalar value +// at x[3]. +double vtkImplicitDataSet::EvaluateFunction(double x[3]) +{ + vtkDataArray *scalars; + vtkCell *cell; + vtkIdType id; + int subId, i, numPts; + double pcoords[3], s; + + if ( this->DataSet->GetMaxCellSize() > this->Size ) + { + if ( this->Weights ) + { + delete [] this->Weights; + } + this->Weights = new double[this->DataSet->GetMaxCellSize()]; + this->Size = this->DataSet->GetMaxCellSize(); + } + + // See if a dataset has been specified + if ( !this->DataSet || + !(scalars = this->DataSet->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"Can't evaluate dataset!"); + return this->OutValue; + } + + // Find the cell that contains xyz and get it + cell = this->DataSet->FindAndGetCell(x,NULL,-1,0.0,subId,pcoords,this->Weights); + + if (cell) + { // Interpolate the point data + numPts = cell->GetNumberOfPoints(); + for (s=0.0, i=0; i < numPts; i++) + { + id = cell->PointIds->GetId(i); + s += scalars->GetComponent(id,0) * this->Weights[i]; + } + return s; + } + else + { // use outside value + return this->OutValue; + } +} + +unsigned long vtkImplicitDataSet::GetMTime() +{ + unsigned long mTime=this->vtkImplicitFunction::GetMTime(); + unsigned long DataSetMTime; + + if ( this->DataSet != NULL ) + { + this->DataSet->Update (); + DataSetMTime = this->DataSet->GetMTime(); + mTime = ( DataSetMTime > mTime ? DataSetMTime : mTime ); + } + + return mTime; +} + + +// Evaluate implicit function gradient. +void vtkImplicitDataSet::EvaluateGradient(double x[3], double n[3]) +{ + vtkDataArray *scalars; + vtkCell *cell; + vtkIdType id; + int subId, i, numPts; + double pcoords[3]; + + if ( this->DataSet->GetMaxCellSize() > this->Size ) + { + if ( this->Weights ) + { + delete [] this->Weights; + } + this->Weights = new double[this->DataSet->GetMaxCellSize()]; + this->Size = this->DataSet->GetMaxCellSize(); + } + + // See if a dataset has been specified + if ( !this->DataSet || + !(scalars = this->DataSet->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"Can't evaluate gradient!"); + for ( i=0; i < 3; i++ ) + { + n[i] = this->OutGradient[i]; + } + return; + } + + // Find the cell that contains xyz and get it + cell = this->DataSet->FindAndGetCell(x,NULL,-1,0.0,subId,pcoords,this->Weights); + + if (cell) + { // Interpolate the point data + numPts = cell->GetNumberOfPoints(); + + for ( i=0; i < numPts; i++ ) //Weights used to hold scalar values + { + id = cell->PointIds->GetId(i); + this->Weights[i] = scalars->GetComponent(id,0); + } + cell->Derivatives(subId, pcoords, this->Weights, 1, n); + } + + else + { // use outside value + for ( i=0; i < 3; i++ ) + { + n[i] = this->OutGradient[i]; + } + } +} + +void vtkImplicitDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Out Value: " << this->OutValue << "\n"; + os << indent << "Out Gradient: (" << this->OutGradient[0] << ", " + << this->OutGradient[1] << ", " << this->OutGradient[2] << ")\n"; + + if ( this->DataSet ) + { + os << indent << "Data Set: " << this->DataSet << "\n"; + } + else + { + os << indent << "Data Set: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkImplicitDataSet::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->DataSet, "DataSet"); +} diff --git a/Filtering/vtkImplicitDataSet.h b/Filtering/vtkImplicitDataSet.h new file mode 100644 index 0000000..9b54fc2 --- /dev/null +++ b/Filtering/vtkImplicitDataSet.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitDataSet - treat a dataset as if it were an implicit function +// .SECTION Description +// vtkImplicitDataSet treats any type of dataset as if it were an +// implicit function. This means it computes a function value and +// gradient. vtkImplicitDataSet is a concrete implementation of +// vtkImplicitFunction. +// +// vtkImplicitDataSet computes the function (at the point x) by performing +// cell interpolation. That is, it finds the cell containing x, and then +// uses the cell's interpolation functions to compute an interpolated +// scalar value at x. (A similar approach is used to find the +// gradient, if requested.) Points outside of the dataset are assigned +// the value of the ivar OutValue, and the gradient value OutGradient. + +// .SECTION Caveats +// Any type of dataset can be used as an implicit function as long as it +// has scalar data associated with it. + +// .SECTION See Also +// vtkImplicitFunction vtkImplicitVolume vtkClipPolyData vtkCutter +// vtkImplicitWindowFunction + +#ifndef __vtkImplicitDataSet_h +#define __vtkImplicitDataSet_h + +#include "vtkImplicitFunction.h" + +class vtkDataSet; + +class VTK_FILTERING_EXPORT vtkImplicitDataSet : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkImplicitDataSet,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct an vtkImplicitDataSet with no initial dataset; the OutValue + // set to a large negative number; and the OutGradient set to (0,0,1). + static vtkImplicitDataSet *New(); + + // Description: + // Return the MTime also considering the DataSet dependency. + unsigned long GetMTime(); + + // Description + // Evaluate the implicit function. This returns the interpolated scalar value + // at x[3]. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate implicit function gradient. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Set / get the dataset used for the implicit function evaluation. + virtual void SetDataSet(vtkDataSet*); + vtkGetObjectMacro(DataSet,vtkDataSet); + + // Description: + // Set / get the function value to use for points outside of the dataset. + vtkSetMacro(OutValue,double); + vtkGetMacro(OutValue,double); + + // Description: + // Set / get the function gradient to use for points outside of the dataset. + vtkSetVector3Macro(OutGradient,double); + vtkGetVector3Macro(OutGradient,double); + +protected: + vtkImplicitDataSet(); + ~vtkImplicitDataSet(); + + virtual void ReportReferences(vtkGarbageCollector*); + + vtkDataSet *DataSet; + double OutValue; + double OutGradient[3]; + + double *Weights; //used to compute interpolation weights + int Size; //keeps track of length of weights array + +private: + vtkImplicitDataSet(const vtkImplicitDataSet&); // Not implemented. + void operator=(const vtkImplicitDataSet&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkImplicitSelectionLoop.cxx b/Filtering/vtkImplicitSelectionLoop.cxx new file mode 100644 index 0000000..5670c0f --- /dev/null +++ b/Filtering/vtkImplicitSelectionLoop.cxx @@ -0,0 +1,211 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitSelectionLoop.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitSelectionLoop.h" + +#include "vtkDoubleArray.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPoints.h" +#include "vtkPolygon.h" + +vtkCxxRevisionMacro(vtkImplicitSelectionLoop, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkImplicitSelectionLoop); +vtkCxxSetObjectMacro(vtkImplicitSelectionLoop, Loop,vtkPoints); + +//---------------------------------------------------------------------------- +// Instantiate object with no initial loop. +vtkImplicitSelectionLoop::vtkImplicitSelectionLoop() +{ + this->Loop = NULL; + this->AutomaticNormalGeneration = 1; + this->Normal[0] = 0.0; + this->Normal[1] = 0.0; + this->Normal[2] = 1.0; + this->Polygon = vtkPolygon::New(); +} + +//---------------------------------------------------------------------------- +vtkImplicitSelectionLoop::~vtkImplicitSelectionLoop() +{ + if (this->Loop) + { + this->Loop->Delete(); + } + this->Polygon->Delete(); + this->Polygon = NULL; +} + +//---------------------------------------------------------------------------- +#define VTK_DELTA 0.0001 +// Generate plane equations only once to avoid a lot of extra work +void vtkImplicitSelectionLoop::Initialize() +{ + int i, numPts; + double x[3], xProj[3]; + + numPts = this->Loop->GetNumberOfPoints(); + this->Polygon->Points->SetDataTypeToDouble(); + this->Polygon->Points->SetNumberOfPoints(numPts); + + if ( this->AutomaticNormalGeneration ) + { + // Make sure points define a loop with a normal + vtkPolygon::ComputeNormal(this->Loop, this->Normal); + if ( this->Normal[0] == 0.0 && this->Normal[1] == 0.0 && + this->Normal[2] == 0.0 ) + { + vtkErrorMacro(<<"Cannot determine inside/outside of loop"); + } + } + + // Determine origin point by taking average + this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.0; + for (i=0; iLoop->GetPoint(i, x); + this->Origin[0] += x[0]; + this->Origin[1] += x[1]; + this->Origin[2] += x[2]; + } + this->Origin[0] /= numPts; this->Origin[1] /= numPts; this->Origin[2] /= numPts; + + // Project points onto plane generating new coordinates + for (i=0; iLoop->GetPoint(i, x); + vtkPlane::ProjectPoint(x, this->Origin, this->Normal, xProj); + this->Polygon->Points->SetPoint(i, xProj); + } + + this->Polygon->GetBounds(this->Bounds); + this->DeltaX = VTK_DELTA*(this->Bounds[1]-this->Bounds[0]); + this->DeltaY = VTK_DELTA*(this->Bounds[3]-this->Bounds[2]); + this->DeltaZ = VTK_DELTA*(this->Bounds[5]-this->Bounds[4]); + this->InitializationTime.Modified(); +} + +//---------------------------------------------------------------------------- +// Evaluate plane equations. Return smallest absolute value. +double vtkImplicitSelectionLoop::EvaluateFunction(double x[3]) +{ + int i, numPts=this->Polygon->Points->GetNumberOfPoints(); + double xProj[3]; + double t, dist2, minDist2, closest[3]; + int inside=0; + + if ( this->InitializationTime < this->GetMTime() ) + { + this->Initialize(); + } + + // project point onto plane + vtkPlane::ProjectPoint(x, this->Origin, this->Normal, xProj); + + // determine whether it's in the selection loop and then evaluate point + // in polygon only if absolutely necessary. + if ( xProj[0] >= this->Bounds[0] && xProj[0] <= this->Bounds[1] && + xProj[1] >= this->Bounds[2] && xProj[1] <= this->Bounds[3] && + xProj[2] >= this->Bounds[4] && xProj[2] <= this->Bounds[5] && + this->Polygon-> + PointInPolygon(xProj , numPts, + vtkDoubleArray::SafeDownCast(this->Polygon->Points->GetData())->GetPointer(0), + this->Bounds,this->Normal) == 1 ) + { + inside = 1; + } + + // determine distance to boundary + for (minDist2=VTK_DOUBLE_MAX,i=0; iPolygon->Points->GetPoint(i, p1); + this->Polygon->Points->GetPoint((i+1)%numPts, p2); + dist2 = vtkLine::DistanceToLine(xProj, p1, p2, t, closest); + if ( dist2 < minDist2 ) + { + minDist2 = dist2; + } + } + + minDist2 = (double)sqrt(minDist2); + return (inside ? -minDist2 : minDist2); +} + +//---------------------------------------------------------------------------- +// Evaluate gradient of the implicit function. Use a numerical scheme: evaluate +// the function at four points (O,O+dx,O+dy,O+dz) and approximate the gradient. +// It's damn slow. +void vtkImplicitSelectionLoop::EvaluateGradient(double x[3], double n[3]) +{ + double xp[3], yp[3], zp[3], g0, gx, gy, gz; + int i; + + g0 = this->EvaluateFunction(x); //side-effect is to compute DeltaX, Y, and Z + + for (i=0; i<3; i++) + { + xp[i] = yp[i] = zp[i] = x[i]; + } + xp[0] += this->DeltaX; + yp[1] += this->DeltaY; + zp[2] += this->DeltaZ; + + gx = this->EvaluateFunction(xp); + gy = this->EvaluateFunction(yp); + gz = this->EvaluateFunction(zp); + + n[0] = (gx - g0) / this->DeltaX; + n[1] = (gy - g0) / this->DeltaY; + n[2] = (gz - g0) / this->DeltaZ; +} + +//---------------------------------------------------------------------------- +unsigned long int vtkImplicitSelectionLoop::GetMTime() +{ + unsigned long mTime=this->vtkImplicitFunction::GetMTime(); + unsigned long time; + + if ( this->Loop != NULL ) + { + time = this->Loop->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +void vtkImplicitSelectionLoop::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Loop ) + { + os << indent << "Loop of " << this->Loop->GetNumberOfPoints() + << " points defined\n"; + } + else + { + os << indent << "Loop not defined\n"; + } + + os << indent << "Automatic Normal Generation: " + << (this->AutomaticNormalGeneration ? "On\n" : "Off\n"); + + os << indent << "Normal: (" << this->Normal[0] << ", " + << this->Normal[1] << ", " << this->Normal[2] << ")\n"; +} diff --git a/Filtering/vtkImplicitSelectionLoop.h b/Filtering/vtkImplicitSelectionLoop.h new file mode 100644 index 0000000..930d70b --- /dev/null +++ b/Filtering/vtkImplicitSelectionLoop.h @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitSelectionLoop.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitSelectionLoop - implicit function for a selection loop +// .SECTION Description +// vtkImplicitSelectionLoop computes the implicit function value and +// function gradient for a irregular, cylinder-like object whose cross +// section is defined by a set of points forming a loop. The loop need +// not be convex nor its points coplanar. However, the loop must be +// non-self-intersecting when projected onto the plane defined by the +// accumulated cross product around the loop (i.e., the axis of the +// loop). (Alternatively, you can specify the normal to use.) +// +// The following procedure is used to compute the implicit function +// value for a point x. Each point of the loop is first projected onto +// the plane defined by the loop normal. This forms a polygon. Then, +// to evaluate the implicit function value, inside/outside tests are +// used to determine if x is inside the polygon, and the distance to +// the loop boundary is computed (negative values are inside the +// loop). +// +// One example application of this implicit function class is to draw a +// loop on the surface of a mesh, and use the loop to clip or extract +// cells from within the loop. Remember, the selection loop is "infinite" +// in length, you can use a plane (in boolean combination) to cap the extent +// of the selection loop. Another trick is to use a connectivity filter to +// extract the closest region to a given point (i.e., one of the points used +// to define the selection loop). + +// .SECTION See Also +// vtkImplicitFunction vtkImplicitBoolean vtkExtractGeometry vtkClipPolyData +// vtkConnectivityFilter vtkPolyDataConnectivityFilter + +#ifndef __vtkImplicitSelectionLoop_h +#define __vtkImplicitSelectionLoop_h + +#include "vtkImplicitFunction.h" + +class vtkPoints; +class vtkPolygon; + +class VTK_FILTERING_EXPORT vtkImplicitSelectionLoop : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkImplicitSelectionLoop,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with no initial loop. + static vtkImplicitSelectionLoop *New(); + + // Description: + // Evaluate selection loop returning a signed distance. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description: + // Evaluate selection loop returning the gradient. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Set/Get the array of point coordinates defining the loop. There must + // be at least three points used to define a loop. + virtual void SetLoop(vtkPoints*); + vtkGetObjectMacro(Loop,vtkPoints); + + // Description: + // Turn on/off automatic normal generation. By default, the normal is + // computed from the accumulated cross product of the edges. You can also + // specify the normal to use. + vtkSetMacro(AutomaticNormalGeneration,int); + vtkGetMacro(AutomaticNormalGeneration,int); + vtkBooleanMacro(AutomaticNormalGeneration,int); + + // Description: + // Set / get the normal used to determine what is inside and what is outside. + vtkSetVector3Macro(Normal,double); + vtkGetVectorMacro(Normal,double,3); + + // Description: + // Overload GetMTime() because we depend on the Loop + unsigned long GetMTime(); + +protected: + vtkImplicitSelectionLoop(); + ~vtkImplicitSelectionLoop(); + + vtkPoints *Loop; + double Normal[3]; + int AutomaticNormalGeneration; + +private: + void Initialize(); + vtkPolygon *Polygon; + + double Origin[3]; + double Bounds[6]; + double DeltaX; + double DeltaY; + double DeltaZ; + + vtkTimeStamp InitializationTime; + +private: + vtkImplicitSelectionLoop(const vtkImplicitSelectionLoop&); // Not implemented. + void operator=(const vtkImplicitSelectionLoop&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkImplicitSum.cxx b/Filtering/vtkImplicitSum.cxx new file mode 100644 index 0000000..79f90f6 --- /dev/null +++ b/Filtering/vtkImplicitSum.cxx @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitSum.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitSum.h" + +#include "vtkDoubleArray.h" +#include "vtkImplicitFunctionCollection.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImplicitSum, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkImplicitSum); + +// Constructor. +vtkImplicitSum::vtkImplicitSum() +{ + this->FunctionList = vtkImplicitFunctionCollection::New(); + this->Weights = vtkDoubleArray::New(); + this->Weights->SetNumberOfComponents(1); + this->TotalWeight = 0.0; + this->NormalizeByWeight = 0; +} + +vtkImplicitSum::~vtkImplicitSum() +{ + this->FunctionList->Delete(); + this->Weights->Delete(); +} + +unsigned long int vtkImplicitSum::GetMTime() +{ + unsigned long int fMtime; + unsigned long int mtime = this->vtkImplicitFunction::GetMTime(); + vtkImplicitFunction *f; + + fMtime = this->Weights->GetMTime(); + if ( fMtime > mtime ) + { + mtime = fMtime; + } + + vtkCollectionSimpleIterator sit; + for (this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); ) + { + fMtime = f->GetMTime(); + if ( fMtime > mtime ) + { + mtime = fMtime; + } + } + return mtime; +} + +// Add another implicit function to the list of functions. +void vtkImplicitSum::AddFunction(vtkImplicitFunction *f, double scale) +{ + this->Modified(); + this->FunctionList->AddItem(f); + this->Weights->InsertNextValue(scale); + this->CalculateTotalWeight(); +} + +void vtkImplicitSum::SetFunctionWeight(vtkImplicitFunction *f, double scale) +{ + int loc = this->FunctionList->IsItemPresent(f); + if (! loc) + { + vtkWarningMacro("Function not found in function list"); + return; + } + loc--; // IsItemPresent returns index+1. + + if ( this->Weights->GetValue(loc) != scale ) + { + this->Modified(); + this->Weights->SetValue(loc, scale); + this->CalculateTotalWeight(); + } +} + +void vtkImplicitSum::RemoveAllFunctions() +{ + this->Modified(); + this->FunctionList->RemoveAllItems(); + this->Weights->Initialize(); + this->TotalWeight = 0.0; +} + +void vtkImplicitSum::CalculateTotalWeight(void) +{ + this->TotalWeight = 0.0; + + for(int i = this->Weights->GetNumberOfTuples() - 1; i >= 0; i--) + { + this->TotalWeight += this->Weights->GetValue(i); + } +} + + +// Evaluate sum of implicit functions. +double vtkImplicitSum::EvaluateFunction(double x[3]) +{ + double sum = 0; + double c; + int i; + vtkImplicitFunction *f; + double *weights = this->Weights->GetPointer(0); + + vtkCollectionSimpleIterator sit; + for (i = 0, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); i++) + { + c = weights[i]; + if (c != 0.0) + { + sum += f->FunctionValue(x)*c; + } + } + if (this->NormalizeByWeight && this->TotalWeight != 0.0) + { + sum /= this->TotalWeight; + } + return sum; +} + +// Evaluate gradient of sum of functions (valid only if linear) +void vtkImplicitSum::EvaluateGradient(double x[3], double g[3]) +{ + double c; + int i; + double gtmp[3]; + vtkImplicitFunction *f; + double *weights = this->Weights->GetPointer(0); + + g[0] = g[1] = g[2] = 0.0; + vtkCollectionSimpleIterator sit; + for (i = 0, this->FunctionList->InitTraversal(sit); + (f=this->FunctionList->GetNextImplicitFunction(sit)); i++) + { + c = weights[i]; + if ( c != 0.0 ) + { + f->FunctionGradient(x, gtmp); + g[0] += gtmp[0]*c; + g[1] += gtmp[1]*c; + g[2] += gtmp[2]*c; + } + } + + if (this->NormalizeByWeight && this->TotalWeight != 0.0) + { + g[0] /= this->TotalWeight; + g[1] /= this->TotalWeight; + g[2] /= this->TotalWeight; + } +} + +void vtkImplicitSum::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NormalizeByWeight: " + << (this->NormalizeByWeight ? "On\n" : "Off\n"); + + os << indent << "Function List:\n"; + this->FunctionList->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Weights:\n"; + this->Weights->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkImplicitSum.h b/Filtering/vtkImplicitSum.h new file mode 100644 index 0000000..24a5521 --- /dev/null +++ b/Filtering/vtkImplicitSum.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitSum.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitSum - implicit sum of other implicit functions +// .SECTION Description +// vtkImplicitSum produces a linear combination of other implicit functions. +// The contribution of each function is weighted by a scalar coefficient. +// The NormalizeByWeight option normalizes the output so that the +// scalar weights add up to 1. Note that this function gives accurate +// sums and gradients only if the input functions are linear. + +#ifndef __vtkImplicitSum_h +#define __vtkImplicitSum_h + +#include "vtkImplicitFunction.h" + +class vtkDoubleArray; +class vtkImplicitFunctionCollection; + +class VTK_FILTERING_EXPORT vtkImplicitSum : public vtkImplicitFunction +{ +public: + static vtkImplicitSum *New(); + + vtkTypeRevisionMacro(vtkImplicitSum,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Evaluate implicit function using current functions and weights. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description: + // Evaluate gradient of the weighted sum of functions. Input functions + // should be linear. + void EvaluateGradient(double x[3], double g[3]); + + // Description: + // Override modified time retrieval because of object dependencies. + unsigned long GetMTime(); + + // Description: + // Add another implicit function to the list of functions, along with a + // weighting factor. + void AddFunction(vtkImplicitFunction *in, double weight); + + // Description: + // Add another implicit function to the list of functions, weighting it by + // a factor of 1. + void AddFunction(vtkImplicitFunction *in) { this->AddFunction(in, 1.0); } + + // Description: + // Remove all functions from the list. + void RemoveAllFunctions(); + + // Description: + // Set the weight (coefficient) of the given function to be weight. + void SetFunctionWeight(vtkImplicitFunction *f, double weight); + + // Description: + // When calculating the function and gradient values of the + // composite function, setting NormalizeByWeight on will divide the + // final result by the total weight of the component functions. + // This process does not otherwise normalize the gradient vector. + // By default, NormalizeByWeight is off. + vtkSetMacro(NormalizeByWeight, int); + vtkGetMacro(NormalizeByWeight, int); + vtkBooleanMacro(NormalizeByWeight, int); + +protected: + vtkImplicitSum(); + ~vtkImplicitSum(); + + vtkImplicitFunctionCollection *FunctionList; + vtkDoubleArray *Weights; + double TotalWeight; + + void CalculateTotalWeight(void); + int NormalizeByWeight; + +private: + vtkImplicitSum(const vtkImplicitSum&); // Not implemented. + void operator=(const vtkImplicitSum&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkImplicitVolume.cxx b/Filtering/vtkImplicitVolume.cxx new file mode 100644 index 0000000..2a2e2bc --- /dev/null +++ b/Filtering/vtkImplicitVolume.cxx @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitVolume.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitVolume.h" + +#include "vtkDoubleArray.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkVoxel.h" + +vtkCxxRevisionMacro(vtkImplicitVolume, "$Revision: 1.31 $"); +vtkStandardNewMacro(vtkImplicitVolume); +vtkCxxSetObjectMacro(vtkImplicitVolume,Volume,vtkImageData); + +// Construct an vtkImplicitVolume with no initial volume; the OutValue +// set to a large negative number; and the OutGradient set to (0,0,1). +vtkImplicitVolume::vtkImplicitVolume() +{ + this->Volume = NULL; + this->OutValue = -VTK_FLOAT_MAX; + + this->OutGradient[0] = 0.0; + this->OutGradient[1] = 0.0; + this->OutGradient[2] = 1.0; + + this->PointIds = vtkIdList::New(); + this->PointIds->Allocate(8); +} + +vtkImplicitVolume::~vtkImplicitVolume() +{ + if (this->Volume) + { + this->Volume->Delete(); + this->Volume = NULL; + } + this->PointIds->Delete(); +} + +// Evaluate the ImplicitVolume. This returns the interpolated scalar value +// at x[3]. +double vtkImplicitVolume::EvaluateFunction(double x[3]) +{ + vtkDataArray *scalars; + int ijk[3]; + vtkIdType numPts, i; + double pcoords[3], weights[8], s; + + // See if a volume is defined + if ( !this->Volume || + !(scalars = this->Volume->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"Can't evaluate volume!"); + return this->OutValue; + } + + // Find the cell that contains xyz and get it + if ( this->Volume->ComputeStructuredCoordinates(x,ijk,pcoords) ) + { + this->Volume->GetCellPoints(this->Volume->ComputeCellId(ijk),this->PointIds); + vtkVoxel::InterpolationFunctions(pcoords,weights); + + numPts = this->PointIds->GetNumberOfIds (); + for (s=0.0, i=0; i < numPts; i++) + { + s += scalars->GetComponent(this->PointIds->GetId(i),0) * weights[i]; + } + return s; + } + + else + { + return this->OutValue; + } +} + +unsigned long vtkImplicitVolume::GetMTime() +{ + unsigned long mTime=this->vtkImplicitFunction::GetMTime(); + unsigned long volumeMTime; + + if ( this->Volume != NULL ) + { + this->Volume->RequestExactExtentOn(); + this->Volume->UpdateInformation(); + this->Volume->SetUpdateExtentToWholeExtent(); + this->Volume->Update(); + volumeMTime = this->Volume->GetMTime(); + mTime = ( volumeMTime > mTime ? volumeMTime : mTime ); + } + + return mTime; +} + + +// Evaluate ImplicitVolume gradient. +void vtkImplicitVolume::EvaluateGradient(double x[3], double n[3]) +{ + vtkDataArray *scalars; + int i, ijk[3]; + double pcoords[3], weights[8], *v; + vtkDoubleArray *gradient; + + gradient = vtkDoubleArray::New(); + gradient->SetNumberOfComponents(3); + gradient->SetNumberOfTuples(8); + + // See if a volume is defined + if ( !this->Volume || + !(scalars = this->Volume->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"Can't evaluate volume!"); + return; + } + + // Find the cell that contains xyz and get it + if ( this->Volume->ComputeStructuredCoordinates(x,ijk,pcoords) ) + { + vtkVoxel::InterpolationFunctions(pcoords,weights); + this->Volume->GetVoxelGradient(ijk[0], ijk[1], ijk[2], scalars, gradient); + + n[0] = n[1] = n[2] = 0.0; + for (i=0; i < 8; i++) + { + v = gradient->GetTuple(i); + n[0] += v[0] * weights[i]; + n[1] += v[1] * weights[i]; + n[2] += v[2] * weights[i]; + } + } + + else + { // use outside value + for ( i=0; i < 3; i++ ) + { + n[i] = this->OutGradient[i]; + } + } + gradient->Delete(); +} + +void vtkImplicitVolume::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Out Value: " << this->OutValue << "\n"; + os << indent << "Out Gradient: (" << this->OutGradient[0] << ", " + << this->OutGradient[1] << ", " << this->OutGradient[2] << ")\n"; + + if ( this->Volume ) + { + os << indent << "Volume: " << this->Volume << "\n"; + } + else + { + os << indent << "Volume: (none)\n"; + } +} diff --git a/Filtering/vtkImplicitVolume.h b/Filtering/vtkImplicitVolume.h new file mode 100644 index 0000000..897d1b4 --- /dev/null +++ b/Filtering/vtkImplicitVolume.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitVolume.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitVolume - treat a volume as if it were an implicit function +// .SECTION Description +// vtkImplicitVolume treats a volume (e.g., structured point dataset) +// as if it were an implicit function. This means it computes a function +// value and gradient. vtkImplicitVolume is a concrete implementation of +// vtkImplicitFunction. +// +// vtkImplicitDataSet computes the function (at the point x) by performing +// cell interpolation. That is, it finds the cell containing x, and then +// uses the cell's interpolation functions to compute an interpolated +// scalar value at x. (A similar approach is used to find the +// gradient, if requested.) Points outside of the dataset are assigned +// the value of the ivar OutValue, and the gradient value OutGradient. + +// .SECTION Caveats +// The input volume data is only updated when GetMTime() is called. +// Works for 3D structured points datasets, 0D-2D datasets won't work properly. + +// .SECTION See Also +// vtkImplicitFunction vtkImplicitDataSet vtkClipPolyData vtkCutter +// vtkImplicitWindowFunction + +#ifndef __vtkImplicitVolume_h +#define __vtkImplicitVolume_h + +#include "vtkImplicitFunction.h" + +class vtkIdList; +class vtkImageData; + +class VTK_FILTERING_EXPORT vtkImplicitVolume : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkImplicitVolume,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct an vtkImplicitVolume with no initial volume; the OutValue + // set to a large negative number; and the OutGradient set to (0,0,1). + static vtkImplicitVolume *New(); + + // Description: + // Returns the mtime also considering the volume. This also calls Update + // on the volume, and it therefore must be called before the function is + // evaluated. + unsigned long GetMTime(); + + // Description + // Evaluate the ImplicitVolume. This returns the interpolated scalar value + // at x[3]. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate ImplicitVolume gradient. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Specify the volume for the implicit function. + virtual void SetVolume(vtkImageData*); + vtkGetObjectMacro(Volume,vtkImageData); + + // Description: + // Set the function value to use for points outside of the dataset. + vtkSetMacro(OutValue,double); + vtkGetMacro(OutValue,double); + + // Description: + // Set the function gradient to use for points outside of the dataset. + vtkSetVector3Macro(OutGradient,double); + vtkGetVector3Macro(OutGradient,double); + +protected: + vtkImplicitVolume(); + ~vtkImplicitVolume(); + + vtkImageData *Volume; // the structured points + double OutValue; + double OutGradient[3]; + // to replace a static + vtkIdList *PointIds; + +private: + vtkImplicitVolume(const vtkImplicitVolume&); // Not implemented. + void operator=(const vtkImplicitVolume&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkImplicitWindowFunction.cxx b/Filtering/vtkImplicitWindowFunction.cxx new file mode 100644 index 0000000..66af1da --- /dev/null +++ b/Filtering/vtkImplicitWindowFunction.cxx @@ -0,0 +1,158 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitWindowFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitWindowFunction.h" + +#include "vtkGarbageCollector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImplicitWindowFunction, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkImplicitWindowFunction); +vtkCxxSetObjectMacro(vtkImplicitWindowFunction,ImplicitFunction,vtkImplicitFunction); + +// Construct object with window range (0,1) and window values (0,1). +vtkImplicitWindowFunction::vtkImplicitWindowFunction() +{ + this->ImplicitFunction = NULL; + + this->WindowRange[0] = 0.0; + this->WindowRange[1] = 1.0; + + this->WindowValues[0] = 0.0; + this->WindowValues[1] = 1.0; +} + +vtkImplicitWindowFunction::~vtkImplicitWindowFunction() +{ + this->SetImplicitFunction(NULL); +} + +// Evaluate window function. +double vtkImplicitWindowFunction::EvaluateFunction(double x[3]) +{ + static int beenWarned=0; + double value, diff1, diff2, scaledRange; + + if ( ! this->ImplicitFunction && ! beenWarned ) + { + vtkErrorMacro(<<"Implicit function must be defined"); + beenWarned = 1; + return 0.0; + } + + value = this->ImplicitFunction->EvaluateFunction(x); + + diff1 = value - this->WindowRange[0]; + diff2 = value - this->WindowRange[1]; + + scaledRange = (this->WindowValues[1] - this->WindowValues[0]) / 2.0; + if ( scaledRange == 0.0 ) + { + scaledRange = 1.0; + } + + if ( diff1 >= 0.0 && diff2 <= 0.0 ) //within window + { + if ( diff1 <= (-diff2) ) + { + value = diff1 / scaledRange + this->WindowValues[0]; + } + else + { + value = (-diff2) / scaledRange + this->WindowValues[0]; + } + } + + else if ( diff1 < 0.0 ) //below window + { + value = diff1 / scaledRange + this->WindowValues[0]; + } + + else //above window + { + value = -diff2 / scaledRange + this->WindowValues[0]; + } + + return value; +} + +// Evaluate window function gradient. Just return implicit function gradient. +void vtkImplicitWindowFunction::EvaluateGradient(double x[3], double n[3]) +{ + if ( this->ImplicitFunction ) + { + this->ImplicitFunction->EvaluateGradient(x,n); + } +} + +unsigned long int vtkImplicitWindowFunction::GetMTime() +{ + unsigned long int fMtime; + unsigned long int mtime = this->vtkImplicitFunction::GetMTime(); + + if ( this->ImplicitFunction ) + { + fMtime = this->ImplicitFunction->GetMTime(); + if ( fMtime > mtime ) + { + mtime = fMtime; + } + } + return mtime; +} + +void vtkImplicitWindowFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->ImplicitFunction ) + { + os << indent << "Implicit Function: " << this->ImplicitFunction << "\n"; + } + else + { + os << indent << "No implicit function defined.\n"; + } + + os << indent << "Window Range: (" << this->WindowRange[0] + << ", " << this->WindowRange[1] << ")\n"; + + os << indent << "Window Values: (" << this->WindowValues[0] + << ", " << this->WindowValues[1] << ")\n"; + +} + +//---------------------------------------------------------------------------- +void vtkImplicitWindowFunction::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkImplicitWindowFunction::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void +vtkImplicitWindowFunction +::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->ImplicitFunction, + "ImplicitFunction"); +} diff --git a/Filtering/vtkImplicitWindowFunction.h b/Filtering/vtkImplicitWindowFunction.h new file mode 100644 index 0000000..dc7c45a --- /dev/null +++ b/Filtering/vtkImplicitWindowFunction.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitWindowFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitWindowFunction - implicit function maps another implicit function to lie within a specified range +// .SECTION Description +// vtkImplicitWindowFunction is used to modify the output of another +// implicit function to lie within a specified "window", or function +// range. This can be used to add "thickness" to cutting or clipping +// functions. +// +// This class works as follows. First, it evaluates the function value of the +// user-specified implicit function. Then, based on the window range specified, +// it maps the function value into the window values specified. +// + +// .SECTION See Also +// vtkImplicitFunction + +#ifndef __vtkImplicitWindowFunction_h +#define __vtkImplicitWindowFunction_h + +#include "vtkImplicitFunction.h" + +class VTK_FILTERING_EXPORT vtkImplicitWindowFunction : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkImplicitWindowFunction,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with window range (0,1) and window values (0,1). + static vtkImplicitWindowFunction *New(); + + // Description + // Evaluate window function. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate window function gradient. Just return implicit function gradient. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Specify an implicit function to operate on. + virtual void SetImplicitFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ImplicitFunction,vtkImplicitFunction); + + // Description: + // Specify the range of function values which are considered to lie within + // the window. WindowRange[0] is assumed to be less than WindowRange[1]. + vtkSetVector2Macro(WindowRange,double); + vtkGetVectorMacro(WindowRange,double,2); + + // Description: + // Specify the range of output values that the window range is mapped + // into. This is effectively a scaling and shifting of the original + // function values. + vtkSetVector2Macro(WindowValues,double); + vtkGetVectorMacro(WindowValues,double,2); + + // Description: + // Override modified time retrieval because of object dependencies. + unsigned long GetMTime(); + + // Description: + // Participate in garbage collection. + virtual void Register(vtkObjectBase* o); + virtual void UnRegister(vtkObjectBase* o); + +protected: + vtkImplicitWindowFunction(); + ~vtkImplicitWindowFunction(); + + virtual void ReportReferences(vtkGarbageCollector*); + + vtkImplicitFunction *ImplicitFunction; + double WindowRange[2]; + double WindowValues[2]; + +private: + vtkImplicitWindowFunction(const vtkImplicitWindowFunction&); // Not implemented. + void operator=(const vtkImplicitWindowFunction&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkInformation.cxx b/Filtering/vtkInformation.cxx new file mode 100644 index 0000000..6b7d13d --- /dev/null +++ b/Filtering/vtkInformation.cxx @@ -0,0 +1,989 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformation.h" + +#include "vtkGarbageCollector.h" +#include "vtkInformationDataObjectKey.h" +#include "vtkInformationDoubleKey.h" +#include "vtkInformationDoubleVectorKey.h" +#include "vtkInformationExecutivePortKey.h" +#include "vtkInformationExecutivePortVectorKey.h" +#include "vtkInformationIdTypeKey.h" +#include "vtkInformationInformationKey.h" +#include "vtkInformationInformationVectorKey.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationIntegerPointerKey.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationKeyVectorKey.h" +#include "vtkInformationObjectBaseKey.h" +#include "vtkInformationRequestKey.h" +#include "vtkInformationStringKey.h" +#include "vtkInformationUnsignedLongKey.h" +#include "vtkObjectFactory.h" +#include "vtkSmartPointer.h" + +#include +#include +#include + +#include + +vtkCxxRevisionMacro(vtkInformation, "$Revision: 1.25.4.2 $"); +vtkStandardNewMacro(vtkInformation); + +// Note: assumes long is at least 32 bits. +enum { _stl_num_primes = 16 }; +static const unsigned short _stl_prime_list[_stl_num_primes] = +{ + 5u, 11u, 23u, 31u, 41u, + 53u, 97u, 193u, 389u, 769u, + 1543u, 3079u, 6151u, 12289u, 24593u, + 49157u +}; + +// use a mod hash or a bit hash +#define USE_MOD 1 + +//---------------------------------------------------------------------------- +class vtkInformationInternals +{ +public: + // Vector to store ordered key/value pairs for efficient lookup with + // a binary search. Typically not many pairs are stored so linear + // insertion time is okay. + typedef vtkstd::pair value_type; + vtkInformationKey** Keys; + vtkObjectBase** Values; + unsigned short TableSize; + unsigned short HashKey; + + vtkInformationInternals() + { + this->ComputeHashKey(33); + this->Keys = new vtkInformationKey* [this->TableSize]; + this->Values = new vtkObjectBase* [this->TableSize]; + int i; + for (i = 0; i < this->TableSize; ++i) + { + this->Keys[i] = 0; + } + } + + vtkInformationInternals(int size) + { + assert(size < 65000 && "information cannot grow to more than 65000 entries"); + this->ComputeHashKey(size); + this->Keys = new vtkInformationKey* [this->TableSize]; + this->Values = new vtkObjectBase* [this->TableSize]; + int i; + for (i = 0; i < this->TableSize; ++i) + { + this->Keys[i] = 0; + } + } + + ~vtkInformationInternals() + { + unsigned short i; + for (i = 0; i < this->TableSize; ++i) + { + vtkObjectBase *value = this->Values[i]; + if (this->Keys[i] && value) + { + this->Keys[i] = 0; + this->Values[i] = 0; + value->UnRegister(0); + } + } + delete [] this->Keys; + delete [] this->Values; + } + + void ComputeHashKey(int size) + { + // finds the best hash key for the target table size + // and then adjust table size to fit the hash size +#if USE_MOD + unsigned short i = 1; + while(i < _stl_num_primes && _stl_prime_list[i] + 1 <= size) + { + i++; + } + this->HashKey = _stl_prime_list[i-1]; + this->TableSize = this->HashKey + 1; +#else + this->HashKey = 1; + while (this->HashKey + 1 <= size) + { + this->HashKey *= 2; + } + this->HashKey = this->HashKey/2-1; + this->TableSize = this->HashKey + 2; +#endif + } + + unsigned short Hash(unsigned long hv) + { +#if USE_MOD + return hv % this->HashKey; +#else + return (hv >> 2 & this->HashKey); +#endif + } +}; + +//---------------------------------------------------------------------------- +vtkInformation::vtkInformation() +{ + // Allocate the internal representation. + this->Internal = new vtkInformationInternals; + + // There is no request key stored initially. + this->Request = 0; +} + +//---------------------------------------------------------------------------- +vtkInformation::~vtkInformation() +{ + // Delete the internal representation. + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkInformation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + // Print the request if one is set. + if(this->Request) + { + os << indent << "Request: " << this->Request->GetName() << "\n"; + } + + // Give each key a chance to print its value. + unsigned short i; + for (i = 0; i < this->Internal->TableSize; ++i) + { + if (this->Internal->Keys[i]) + { + // Print the key name first. + vtkInformationKey* key = this->Internal->Keys[i]; + os << indent << key->GetName() << ": "; + + // Ask the key to print its value. + key->Print(os, this); + os << "\n"; + } + } +} + +//---------------------------------------------------------------------------- +// grow the table by a factor of 2 +void vtkInformation::ExpandTable() +{ + vtkInformationInternals* oldInternal = this->Internal; + this->Internal = new vtkInformationInternals( + static_cast(oldInternal->TableSize*2.2)); + + unsigned short i; + for (i = 0; i < oldInternal->TableSize; ++i) + { + if (oldInternal->Keys[i]) + { + this->SetAsObjectBase(oldInternal->Keys[i],oldInternal->Values[i]); + } + } + delete oldInternal; +} + + +//---------------------------------------------------------------------------- +void vtkInformation::SetAsObjectBase(vtkInformationKey* key, + vtkObjectBase* newvalue) +{ + if(!key) + { + return; + } + + // compute the hash + unsigned short ohash = this->Internal->Hash(reinterpret_cast(key)); + unsigned short hash = ohash; + + // Check for an existing entry. + vtkInformationKey *val = this->Internal->Keys[hash]; + // is there something in this hash slot + if (val) + { + while (val && val != key && hash < this->Internal->TableSize -1) + { + hash++; + val = this->Internal->Keys[hash]; + } + // if we have exceeded the table size or have two collisions + if ((hash == this->Internal->TableSize -1 && val != key) || hash - ohash > 1) + { + this->ExpandTable(); + this->SetAsObjectBase(key,newvalue); + return; + } + // if there is an entry for this key + if(val) + { + // Update the value. + vtkObjectBase* oldvalue = this->Internal->Values[hash]; + if(newvalue) + { + // There is a new value. Replace the entry. + this->Internal->Values[hash] = newvalue; + newvalue->Register(0); + } + // remove the value + else + { + // There is no new value. Erase the entry. and shift down any + // followup entries that hash to the same value, requires that they + // be sorted + hash++; + while (hash < this->Internal->TableSize && + this->Internal->Keys[hash] && + this->Internal->Hash(reinterpret_cast + (this->Internal->Keys[hash])) < hash) + { + this->Internal->Keys[hash-1] = this->Internal->Keys[hash]; + this->Internal->Values[hash-1] = this->Internal->Values[hash]; + hash++; + } + // clear the final entry + this->Internal->Keys[hash-1] = 0; + } + oldvalue->UnRegister(0); + } + // add an entry but after the desired hash location + else if (newvalue) + { + // start at ohash + 1 and find where we should instert this key + unsigned short hash2 = hash; + hash = ohash + 1; + while (this->Internal->Hash(reinterpret_cast + (this->Internal->Keys[hash])) == ohash) + { + hash++; + } + // insert and shift the rest, hash is the insertion point + for (;hash2 > hash; --hash2) + { + this->Internal->Keys[hash2] = this->Internal->Keys[hash2-1]; + this->Internal->Values[hash2] = this->Internal->Values[hash2-1]; + } + this->Internal->Keys[hash2] = key; + this->Internal->Values[hash2] = newvalue; + newvalue->Register(0); + } + } + else if (newvalue) + { + // There is no entry with this key. Create one and store the value. + newvalue->Register(0); + this->Internal->Keys[hash] = key; + this->Internal->Values[hash] = newvalue; + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkObjectBase* vtkInformation::GetAsObjectBase(vtkInformationKey* key) +{ + if(key) + { + // compute the hash + unsigned short hash = + this->Internal->Hash(reinterpret_cast(key)); + + // Check for an existing entry. + vtkInformationKey *val = this->Internal->Keys[hash]; + while (hash < this->Internal->TableSize - 1 && val && val != key) + { + hash++; + val = this->Internal->Keys[hash]; + } + if (val == key) + { + return this->Internal->Values[hash]; + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkInformation::Clear() +{ + this->Copy(0); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Copy(vtkInformation* from, int deep) +{ + vtkInformationInternals* oldInternal = this->Internal; + if(from) + { + this->Internal = new vtkInformationInternals(from->Internal->TableSize); + unsigned short i; + for (i = 0; i < from->Internal->TableSize; ++i) + { + if (from->Internal->Keys[i]) + { + this->CopyEntry(from, from->Internal->Keys[i], deep); + } + } + } + else + { + this->Internal = new vtkInformationInternals; + } + delete oldInternal; +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationDataObjectKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationExecutivePortKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationInformationKey* key, int deep) +{ + if (!deep) + { + key->ShallowCopy(from, this); + } + else + { + key->DeepCopy(from, this); + } +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationInformationVectorKey* key, + int deep) +{ + if (!deep) + { + key->ShallowCopy(from, this); + } + else + { + key->DeepCopy(from, this); + } +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationIntegerKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationRequestKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationIntegerVectorKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationDoubleVectorKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationStringKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntry(vtkInformation* from, + vtkInformationUnsignedLongKey* key, int) +{ + key->ShallowCopy(from, this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::CopyEntries(vtkInformation* from, + vtkInformationKeyVectorKey* key, int deep) +{ + int numberOfKeys = from->Length(key); + vtkInformationKey** keys = from->Get(key); + for(int i=0; i < numberOfKeys; ++i) + { + this->CopyEntry(from, keys[i], deep); + } +} + +void vtkInformation::Set(vtkInformationRequestKey* key) +{ + key->Set(this); +} +void vtkInformation::Remove(vtkInformationRequestKey* key) +{ + key->Remove(this); +} +int vtkInformation::Has(vtkInformationRequestKey* key) +{ + return key->Has(this); +} + +//---------------------------------------------------------------------------- +#define VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(name, type) \ + void vtkInformation::Set(vtkInformation##name##Key* key, type value) \ + { \ + key->Set(this, value); \ + } \ + void vtkInformation::Remove(vtkInformation##name##Key* key) \ + { \ + key->Remove(this); \ + } \ + type vtkInformation::Get(vtkInformation##name##Key* key) \ + { \ + return key->Get(this); \ + } \ + int vtkInformation::Has(vtkInformation##name##Key* key) \ + { \ + return key->Has(this); \ + } +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(IdType, vtkIdType); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(Integer, int); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(Double, double); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(UnsignedLong, unsigned long); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(String, const char*); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(DataObject, vtkDataObject*); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(Information, vtkInformation*); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(InformationVector, vtkInformationVector*); +VTK_INFORMATION_DEFINE_SCALAR_PROPERTY(ObjectBase, vtkObjectBase*); +#undef VTK_INFORMATION_DEFINE_SCALAR_PROPERTY + +//---------------------------------------------------------------------------- +#define VTK_INFORMATION_DEFINE_VECTOR_PROPERTY(name, type) \ + void vtkInformation::Append(vtkInformation##name##VectorKey* key, \ + type value) \ + { \ + key->Append(this, value); \ + } \ + void vtkInformation::Set(vtkInformation##name##VectorKey* key, \ + type* value, int length) \ + { \ + key->Set(this, value, length); \ + } \ + type* vtkInformation::Get(vtkInformation##name##VectorKey* key) \ + { \ + return key->Get(this); \ + } \ + void vtkInformation::Get(vtkInformation##name##VectorKey* key, \ + type* value) \ + { \ + key->Get(this, value); \ + } \ + int vtkInformation::Length(vtkInformation##name##VectorKey* key) \ + { \ + return key->Length(this); \ + } \ + void vtkInformation::Remove(vtkInformation##name##VectorKey* key) \ + { \ + key->Remove(this); \ + } \ + int vtkInformation::Has(vtkInformation##name##VectorKey* key) \ + { \ + return key->Has(this); \ + } +VTK_INFORMATION_DEFINE_VECTOR_PROPERTY(Integer, int); +VTK_INFORMATION_DEFINE_VECTOR_PROPERTY(Double, double); +VTK_INFORMATION_DEFINE_VECTOR_PROPERTY(Key, vtkInformationKey*); +#define VTK_INFORMATION_DEFINE_VECTOR_VALUE_PROPERTY(name, type) \ + void vtkInformation::Set(vtkInformation##name##VectorKey* key, \ + type value1, type value2, type value3, \ + type value4, type value5, type value6) \ + { \ + type value[6]; \ + value[0] = value1; \ + value[1] = value2; \ + value[2] = value3; \ + value[3] = value4; \ + value[4] = value5; \ + value[5] = value6; \ + key->Set(this, value, 6); \ + } \ + void vtkInformation::Set(vtkInformation##name##VectorKey* key, \ + type value1, type value2, type value3) \ + { \ + type value[3]; \ + value[0] = value1; \ + value[1] = value2; \ + value[2] = value3; \ + key->Set(this, value, 3); \ + } +VTK_INFORMATION_DEFINE_VECTOR_VALUE_PROPERTY(Integer, int); +VTK_INFORMATION_DEFINE_VECTOR_VALUE_PROPERTY(Double, double); +#undef VTK_INFORMATION_DEFINE_VECTOR_VALUE_PROPERTY + +#undef VTK_INFORMATION_DEFINE_VECTOR_PROPERTY + +//---------------------------------------------------------------------------- +#define VTK_INFORMATION_DEFINE_POINTER_PROPERTY(name, type) \ + void vtkInformation::Set(vtkInformation##name##PointerKey* key, \ + type* value, int length) \ + { \ + key->Set(this, value, length); \ + } \ + type* vtkInformation::Get(vtkInformation##name##PointerKey* key) \ + { \ + return key->Get(this); \ + } \ + void vtkInformation::Get(vtkInformation##name##PointerKey* key, \ + type* value) \ + { \ + key->Get(this, value); \ + } \ + int vtkInformation::Length(vtkInformation##name##PointerKey* key) \ + { \ + return key->Length(this); \ + } \ + void vtkInformation::Remove(vtkInformation##name##PointerKey* key) \ + { \ + key->Remove(this); \ + } \ + int vtkInformation::Has(vtkInformation##name##PointerKey* key) \ + { \ + return key->Has(this); \ + } +VTK_INFORMATION_DEFINE_POINTER_PROPERTY(Integer, int); +#undef VTK_INFORMATION_DEFINE_POINTER_PROPERTY + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationDataObjectKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationDoubleKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationDoubleVectorKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationExecutivePortKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationInformationKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Remove(vtkInformationKeyVectorKey* key, + vtkInformationKey* value) +{ + key->RemoveItem(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationInformationVectorKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationIntegerKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationIntegerVectorKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationStringKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationUnsignedLongKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationKeyVectorKey* key, + vtkInformationObjectBaseKey* value) +{ + key->Append(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationDataObjectKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationDoubleKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationDoubleVectorKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationExecutivePortKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationInformationKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationInformationVectorKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationIntegerKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationIntegerVectorKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationStringKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationUnsignedLongKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationObjectBaseKey* value) +{ + key->AppendUnique(this, value); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Set(vtkInformationExecutivePortKey* key, + vtkExecutive* executive, int port) +{ + key->Set(this, executive, port); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Remove(vtkInformationExecutivePortKey* key) +{ + key->Remove(this); +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkInformation::GetExecutive(vtkInformationExecutivePortKey* key) +{ + return key->GetExecutive(this); +} + +//---------------------------------------------------------------------------- +int vtkInformation::GetPort(vtkInformationExecutivePortKey* key) +{ + return key->GetPort(this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Get(vtkInformationExecutivePortKey* key, + vtkExecutive*& executive, int &port) +{ + key->Get(this,executive,port); +} + +//---------------------------------------------------------------------------- +int vtkInformation::Has(vtkInformationExecutivePortKey* key) +{ + return key->Has(this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Append(vtkInformationExecutivePortVectorKey* key, + vtkExecutive* executive, int port) +{ + key->Append(this, executive, port); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Remove(vtkInformationExecutivePortVectorKey* key, + vtkExecutive* executive, int port) +{ + key->Remove(this, executive, port); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Set(vtkInformationExecutivePortVectorKey* key, + vtkExecutive** executives, int* ports, int length) +{ + key->Set(this, executives, ports, length); +} + +//---------------------------------------------------------------------------- +vtkExecutive** +vtkInformation::GetExecutives(vtkInformationExecutivePortVectorKey* key) +{ + return key->GetExecutives(this); +} + +//---------------------------------------------------------------------------- +int* +vtkInformation::GetPorts(vtkInformationExecutivePortVectorKey* key) +{ + return key->GetPorts(this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Get(vtkInformationExecutivePortVectorKey* key, + vtkExecutive** executives, int* ports) +{ + key->Get(this, executives, ports); +} + +//---------------------------------------------------------------------------- +int vtkInformation::Length(vtkInformationExecutivePortVectorKey* key) +{ + return key->Length(this); +} + +//---------------------------------------------------------------------------- +void vtkInformation::Remove(vtkInformationExecutivePortVectorKey* key) +{ + key->Remove(this); +} + +//---------------------------------------------------------------------------- +int vtkInformation::Has(vtkInformationExecutivePortVectorKey* key) +{ + return key->Has(this); +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationDataObjectKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationExecutivePortKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationInformationKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationInformationVectorKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationIntegerKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationRequestKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationDoubleKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationIntegerVectorKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationDoubleVectorKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationStringKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +vtkInformationKey* vtkInformation::GetKey(vtkInformationUnsignedLongKey* key) +{ + return key; +} + +//---------------------------------------------------------------------------- +void vtkInformation::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkInformation::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkInformation::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + + // Ask each key/value pair to report any references it holds. + unsigned short i; + for (i = 0; i < this->Internal->TableSize; ++i) + { + if (this->Internal->Keys[i]) + { + this->Internal->Keys[i]->Report(this,collector); + } + } +} + +//---------------------------------------------------------------------------- +void vtkInformation::ReportAsObjectBase(vtkInformationKey* key, + vtkGarbageCollector* collector) +{ + if(key) + { + unsigned short ohash = + this->Internal->Hash(reinterpret_cast(key)); + while (this->Internal->Keys[ohash] && + this->Internal->Keys[ohash] != key && + ohash < this->Internal->TableSize) + { + ohash++; + } + if (this->Internal->Keys[ohash] && ohash < this->Internal->TableSize) + { + vtkGarbageCollectorReport(collector, this->Internal->Values[ohash], + key->GetName()); + return; + } + } +} diff --git a/Filtering/vtkInformation.h b/Filtering/vtkInformation.h new file mode 100644 index 0000000..5dd8b55 --- /dev/null +++ b/Filtering/vtkInformation.h @@ -0,0 +1,348 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformation - Store vtkAlgorithm input/output information. +// .SECTION Description +// vtkInformation represents information and/or data for one input or +// one output of a vtkAlgorithm. It maps from keys to values of +// several data types. Instances of this class are collected in +// vtkInformationVector instances and passed to +// vtkAlgorithm::ProcessRequest calls. The information and +// data referenced by the instance on a particular input or output +// define the request made to the vtkAlgorithm instance. + +#ifndef __vtkInformation_h +#define __vtkInformation_h + +#include "vtkObject.h" + +class vtkDataObject; +class vtkExecutive; +class vtkInformationDataObjectKey; +class vtkInformationDoubleKey; +class vtkInformationDoubleVectorKey; +class vtkInformationExecutivePortKey; +class vtkInformationExecutivePortVectorKey; +class vtkInformationIdTypeKey; +class vtkInformationInformationKey; +class vtkInformationInformationVectorKey; +class vtkInformationIntegerKey; +class vtkInformationIntegerPointerKey; +class vtkInformationIntegerVectorKey; +class vtkInformationInternals; +class vtkInformationKey; +class vtkInformationKeyToInformationFriendship; +class vtkInformationKeyVectorKey; +class vtkInformationObjectBaseKey; +class vtkInformationRequestKey; +class vtkInformationStringKey; +class vtkInformationUnsignedLongKey; +class vtkInformationVector; + +class VTK_FILTERING_EXPORT vtkInformation : public vtkObject +{ +public: + static vtkInformation *New(); + vtkTypeRevisionMacro(vtkInformation,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Clear all information entries. + void Clear(); + + // Description: + // Copy all information entries from the given vtkInformation + // instance. Any previously existing entries are removed. If + // deep==1, a deep copy of the information structure is performed (new + // instances of any contained vtkInformation and vtkInformationVector + // objects are created). + void Copy(vtkInformation* from, int deep=0); + + // Description: + // Copy the key/value pair associated with the given key in the + // given information object. If deep=1, a deep copy of the information + // structure is performed (new instances of any contained vtkInformation and + // vtkInformationVector objects are created). + void CopyEntry(vtkInformation* from, vtkInformationKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationDataObjectKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationDoubleVectorKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationExecutivePortKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationInformationKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationInformationVectorKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationIntegerKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationIntegerVectorKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationRequestKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationStringKey* key, int deep=0); + void CopyEntry(vtkInformation* from, vtkInformationUnsignedLongKey* key, int deep=0); + + // Description: + // Use the given key to lookup a list of other keys in the given + // information object. The key/value pairs associated with these + // other keys will be copied. If deep==1, a deep copy of the + // information structure is performed. + void CopyEntries(vtkInformation* from, vtkInformationKeyVectorKey* key, int deep=0); + + // Description: + // Get/Set a request-valued entry. + void Set(vtkInformationRequestKey* key); + void Remove(vtkInformationRequestKey* key); + int Has(vtkInformationRequestKey* key); + + // Description: + // Get/Set an integer-valued entry. + void Set(vtkInformationIntegerKey* key, int value); + int Get(vtkInformationIntegerKey* key); + void Remove(vtkInformationIntegerKey* key); + int Has(vtkInformationIntegerKey* key); + + // Description: + // Get/Set a vtkIdType-valued entry. + void Set(vtkInformationIdTypeKey* key, vtkIdType value); + vtkIdType Get(vtkInformationIdTypeKey* key); + void Remove(vtkInformationIdTypeKey* key); + int Has(vtkInformationIdTypeKey* key); + + // Description: + // Get/Set an double-valued entry. + void Set(vtkInformationDoubleKey* key, double value); + double Get(vtkInformationDoubleKey* key); + void Remove(vtkInformationDoubleKey* key); + int Has(vtkInformationDoubleKey* key); + + // Description: + // Get/Set an integer-vector-valued entry. + void Append(vtkInformationIntegerVectorKey* key, int value); + void Set(vtkInformationIntegerVectorKey* key, int* value, int length); + void Set(vtkInformationIntegerVectorKey* key, int value1, + int value2, int value3); + void Set(vtkInformationIntegerVectorKey* key, + int value1, int value2, int value3, + int value4, int value5, int value6); + int* Get(vtkInformationIntegerVectorKey* key); + void Get(vtkInformationIntegerVectorKey* key, int* value); + int Length(vtkInformationIntegerVectorKey* key); + void Remove(vtkInformationIntegerVectorKey* key); + int Has(vtkInformationIntegerVectorKey* key); + + // Description: + // Get/Set an integer-pointer-valued entry. + void Set(vtkInformationIntegerPointerKey* key, int* value, int length); + int* Get(vtkInformationIntegerPointerKey* key); + void Get(vtkInformationIntegerPointerKey* key, int* value); + int Length(vtkInformationIntegerPointerKey* key); + void Remove(vtkInformationIntegerPointerKey* key); + int Has(vtkInformationIntegerPointerKey* key); + + // Description: + // Get/Set an unsigned-long-valued entry. + void Set(vtkInformationUnsignedLongKey* key, unsigned long value); + unsigned long Get(vtkInformationUnsignedLongKey* key); + void Remove(vtkInformationUnsignedLongKey* key); + int Has(vtkInformationUnsignedLongKey* key); + + // Description: + // Get/Set an double-vector-valued entry. + void Append(vtkInformationDoubleVectorKey* key, double value); + void Set(vtkInformationDoubleVectorKey* key, double* value, int length); + void Set(vtkInformationDoubleVectorKey* key, double value1, + double value2, double value3); + void Set(vtkInformationDoubleVectorKey* key, + double value1, double value2, double value3, + double value4, double value5, double value6); + double* Get(vtkInformationDoubleVectorKey* key); + void Get(vtkInformationDoubleVectorKey* key, double* value); + int Length(vtkInformationDoubleVectorKey* key); + void Remove(vtkInformationDoubleVectorKey* key); + int Has(vtkInformationDoubleVectorKey* key); + + // Description: + // Get/Set an InformationKey-vector-valued entry. + void Append(vtkInformationKeyVectorKey* key, vtkInformationKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, vtkInformationKey* value); + void Set(vtkInformationKeyVectorKey* key, vtkInformationKey** value, int length); + void Remove(vtkInformationKeyVectorKey* key, vtkInformationKey* value); + vtkInformationKey** Get(vtkInformationKeyVectorKey* key); + void Get(vtkInformationKeyVectorKey* key, vtkInformationKey** value); + int Length(vtkInformationKeyVectorKey* key); + void Remove(vtkInformationKeyVectorKey* key); + int Has(vtkInformationKeyVectorKey* key); + + // Provide extra overloads of this method to avoid requiring user + // code to include the headers for these key types. Avoid wrapping + // them because the original method can be called from the wrappers + // anyway and this causes a python help string to be too long. + //BTX + void Append(vtkInformationKeyVectorKey* key, + vtkInformationDataObjectKey* value); + void Append(vtkInformationKeyVectorKey* key, vtkInformationDoubleKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationDoubleVectorKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationExecutivePortKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationInformationKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationInformationVectorKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationIntegerKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationIntegerVectorKey* value); + void Append(vtkInformationKeyVectorKey* key, vtkInformationStringKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationObjectBaseKey* value); + void Append(vtkInformationKeyVectorKey* key, + vtkInformationUnsignedLongKey* value); + + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationDataObjectKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationDoubleKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationDoubleVectorKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationExecutivePortKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationInformationKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationInformationVectorKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationIntegerKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationIntegerVectorKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationStringKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationObjectBaseKey* value); + void AppendUnique(vtkInformationKeyVectorKey* key, + vtkInformationUnsignedLongKey* value); + //ETX + + // Description: + // Get/Set a string-valued entry. + void Set(vtkInformationStringKey* key, const char*); + const char* Get(vtkInformationStringKey* key); + void Remove(vtkInformationStringKey* key); + int Has(vtkInformationStringKey* key); + + // Description: + // Get/Set an entry storing another vtkInformation instance. + void Set(vtkInformationInformationKey* key, vtkInformation*); + vtkInformation* Get(vtkInformationInformationKey* key); + void Remove(vtkInformationInformationKey* key); + int Has(vtkInformationInformationKey* key); + + // Description: + // Get/Set an entry storing a vtkInformationVector instance. + void Set(vtkInformationInformationVectorKey* key, vtkInformationVector*); + vtkInformationVector* Get(vtkInformationInformationVectorKey* key); + void Remove(vtkInformationInformationVectorKey* key); + int Has(vtkInformationInformationVectorKey* key); + + // Description: + // Get/Set an entry storing a vtkObjectBase instance. + void Set(vtkInformationObjectBaseKey* key, vtkObjectBase*); + vtkObjectBase* Get(vtkInformationObjectBaseKey* key); + void Remove(vtkInformationObjectBaseKey* key); + int Has(vtkInformationObjectBaseKey* key); + + // Description: + // Get/Set an entry storing a vtkDataObject instance. + void Set(vtkInformationDataObjectKey* key, vtkDataObject*); + vtkDataObject* Get(vtkInformationDataObjectKey* key); + void Remove(vtkInformationDataObjectKey* key); + int Has(vtkInformationDataObjectKey* key); + + // Description: + // Get/Set an entry storing a vtkExecutive/port number pair. + void Set(vtkInformationExecutivePortKey* key, vtkExecutive*, int); + vtkExecutive* GetExecutive(vtkInformationExecutivePortKey* key); + int GetPort(vtkInformationExecutivePortKey* key); + void Get(vtkInformationExecutivePortKey* key, vtkExecutive*& executive, int &port); + void Remove(vtkInformationExecutivePortKey* key); + int Has(vtkInformationExecutivePortKey* key); + + // Description: + // Get/Set an entry storing a vector of vtkExecutive/port number pairs. + void Append(vtkInformationExecutivePortVectorKey* key, + vtkExecutive* executive, int port); + void Remove(vtkInformationExecutivePortVectorKey* key, + vtkExecutive* executive, int port); + void Set(vtkInformationExecutivePortVectorKey* key, + vtkExecutive** executives, int* ports, int length); + vtkExecutive** GetExecutives(vtkInformationExecutivePortVectorKey* key); + int* GetPorts(vtkInformationExecutivePortVectorKey* key); + void Get(vtkInformationExecutivePortVectorKey* key, + vtkExecutive** executives, int* ports); + int Length(vtkInformationExecutivePortVectorKey* key); + void Remove(vtkInformationExecutivePortVectorKey* key); + int Has(vtkInformationExecutivePortVectorKey* key); + + // Description: + // Upcast the given key instance. + static vtkInformationKey* GetKey(vtkInformationDataObjectKey* key); + static vtkInformationKey* GetKey(vtkInformationDoubleKey* key); + static vtkInformationKey* GetKey(vtkInformationDoubleVectorKey* key); + static vtkInformationKey* GetKey(vtkInformationExecutivePortKey* key); + static vtkInformationKey* GetKey(vtkInformationInformationKey* key); + static vtkInformationKey* GetKey(vtkInformationInformationVectorKey* key); + static vtkInformationKey* GetKey(vtkInformationIntegerKey* key); + static vtkInformationKey* GetKey(vtkInformationIntegerVectorKey* key); + static vtkInformationKey* GetKey(vtkInformationRequestKey* key); + static vtkInformationKey* GetKey(vtkInformationStringKey* key); + static vtkInformationKey* GetKey(vtkInformationKey* key); + static vtkInformationKey* GetKey(vtkInformationUnsignedLongKey* key); + + // Description: + // Initiate garbage collection when a reference is removed. + virtual void Register(vtkObjectBase* o); + virtual void UnRegister(vtkObjectBase* o); + + // Description: + // Get/Set the Request ivar + void SetRequest(vtkInformationRequestKey *request) { this->Request = request; } + vtkInformationRequestKey *GetRequest() { return this->Request; } + +protected: + vtkInformation(); + ~vtkInformation(); + + // Get/Set a map entry directly through the vtkObjectBase instance + // representing the value. Used internally to manage the map. + void SetAsObjectBase(vtkInformationKey* key, vtkObjectBase* value); + vtkObjectBase* GetAsObjectBase(vtkInformationKey* key); + + // Expand the table to a larger size + void ExpandTable(); + + // Internal implementation details. + vtkInformationInternals* Internal; + + // Garbage collection support. + virtual void ReportReferences(vtkGarbageCollector*); + + // Report the object associated with the given key to the collector. + void ReportAsObjectBase(vtkInformationKey* key, + vtkGarbageCollector* collector); + +private: + //BTX + friend class vtkInformationKeyToInformationFriendship; + //ETX +private: + vtkInformation(const vtkInformation&); // Not implemented. + void operator=(const vtkInformation&); // Not implemented. + vtkInformationRequestKey *Request; +}; + +#endif diff --git a/Filtering/vtkInformationDataObjectKey.cxx b/Filtering/vtkInformationDataObjectKey.cxx new file mode 100644 index 0000000..e84c9ee --- /dev/null +++ b/Filtering/vtkInformationDataObjectKey.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationDataObjectKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationDataObjectKey.h" + +#include "vtkDataObject.h" + +vtkCxxRevisionMacro(vtkInformationDataObjectKey, "$Revision: 1.6 $"); + +//---------------------------------------------------------------------------- +vtkInformationDataObjectKey::vtkInformationDataObjectKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationDataObjectKey::~vtkInformationDataObjectKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationDataObjectKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkInformationDataObjectKey::Set(vtkInformation* info, + vtkDataObject* value) +{ + this->SetAsObjectBase(info, value); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkInformationDataObjectKey::Get(vtkInformation* info) +{ + return static_cast(this->GetAsObjectBase(info)); +} + +//---------------------------------------------------------------------------- +int vtkInformationDataObjectKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationDataObjectKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->Get(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationDataObjectKey::Report(vtkInformation* info, + vtkGarbageCollector* collector) +{ + this->ReportAsObjectBase(info, collector); +} diff --git a/Filtering/vtkInformationDataObjectKey.h b/Filtering/vtkInformationDataObjectKey.h new file mode 100644 index 0000000..d1dd2ae --- /dev/null +++ b/Filtering/vtkInformationDataObjectKey.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationDataObjectKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationDataObjectKey - Key for vtkDataObject values. +// .SECTION Description +// vtkInformationDataObjectKey is used to represent keys in +// vtkInformation for values that are vtkDataObject instances. + +#ifndef __vtkInformationDataObjectKey_h +#define __vtkInformationDataObjectKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class vtkDataObject; + +class VTK_FILTERING_EXPORT vtkInformationDataObjectKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationDataObjectKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationDataObjectKey(const char* name, const char* location); + ~vtkInformationDataObjectKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, vtkDataObject*); + vtkDataObject* Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Report a reference this key has in the given information object. + virtual void Report(vtkInformation* info, vtkGarbageCollector* collector); + +private: + vtkInformationDataObjectKey(const vtkInformationDataObjectKey&); // Not implemented. + void operator=(const vtkInformationDataObjectKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationDoubleKey.cxx b/Filtering/vtkInformationDoubleKey.cxx new file mode 100644 index 0000000..50c8af6 --- /dev/null +++ b/Filtering/vtkInformationDoubleKey.cxx @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationDoubleKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationDoubleKey.h" + +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationDoubleKey, "$Revision: 1.6 $"); + +//---------------------------------------------------------------------------- +vtkInformationDoubleKey::vtkInformationDoubleKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationDoubleKey::~vtkInformationDoubleKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationDoubleValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationDoubleValue, vtkObjectBase); + double Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationDoubleKey::Set(vtkInformation* info, double value) +{ + if(vtkInformationDoubleValue* oldv = + static_cast( + this->GetAsObjectBase(info))) + { + // Replace the existing value. + oldv->Value = value; + // Since this sets a value without call SetAsObjectBase(), + // the info has to be modified here (instead of + // vtkInformation::SetAsObjectBase() + info->Modified(); + } + else + { + // Allocate a new value. + vtkInformationDoubleValue* v = new vtkInformationDoubleValue; + this->ConstructClass("vtkInformationDoubleValue"); + v->Value = value; + this->SetAsObjectBase(info, v); + v->Delete(); + } +} + +//---------------------------------------------------------------------------- +double vtkInformationDoubleKey::Get(vtkInformation* info) +{ + vtkInformationDoubleValue* v = + static_cast( + this->GetAsObjectBase(info)); + return v?v->Value:0; +} + +//---------------------------------------------------------------------------- +int vtkInformationDoubleKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleKey::ShallowCopy(vtkInformation* from, vtkInformation* to) +{ + if (this->Has(from)) + { + this->Set(to, this->Get(from)); + } + else + { + this->SetAsObjectBase(to, 0); // doesn't exist in from, so remove the key + } +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + os << this->Get(info); + } +} + +//---------------------------------------------------------------------------- +double* vtkInformationDoubleKey::GetWatchAddress(vtkInformation* info) +{ + if(vtkInformationDoubleValue* v = + static_cast( + this->GetAsObjectBase(info))) + { + return &v->Value; + } + return 0; +} diff --git a/Filtering/vtkInformationDoubleKey.h b/Filtering/vtkInformationDoubleKey.h new file mode 100644 index 0000000..449234b --- /dev/null +++ b/Filtering/vtkInformationDoubleKey.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationDoubleKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationDoubleKey - Key for double values in vtkInformation. +// .SECTION Description +// vtkInformationDoubleKey is used to represent keys for double values +// in vtkInformation. + +#ifndef __vtkInformationDoubleKey_h +#define __vtkInformationDoubleKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationDoubleKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationDoubleKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationDoubleKey(const char* name, const char* location); + ~vtkInformationDoubleKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, double); + double Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + // Description: + // Get the address at which the actual value is stored. This is + // meant for use from a debugger to add watches and is therefore not + // a public method. + double* GetWatchAddress(vtkInformation* info); + +private: + vtkInformationDoubleKey(const vtkInformationDoubleKey&); // Not implemented. + void operator=(const vtkInformationDoubleKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationDoubleVectorKey.cxx b/Filtering/vtkInformationDoubleVectorKey.cxx new file mode 100644 index 0000000..a8501e3 --- /dev/null +++ b/Filtering/vtkInformationDoubleVectorKey.cxx @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationDoubleVectorKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationDoubleVectorKey.h" + +#include "vtkInformation.h" // For vtkErrorWithObjectMacro + +#include + +vtkCxxRevisionMacro(vtkInformationDoubleVectorKey, "$Revision: 1.8.6.1 $"); + +//---------------------------------------------------------------------------- +vtkInformationDoubleVectorKey +::vtkInformationDoubleVectorKey(const char* name, const char* location, + int length): + vtkInformationKey(name, location), RequiredLength(length) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationDoubleVectorKey::~vtkInformationDoubleVectorKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleVectorKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationDoubleVectorValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationDoubleVectorValue, vtkObjectBase); + vtkstd::vector Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationDoubleVectorKey::Append(vtkInformation* info, double value) +{ + vtkInformationDoubleVectorValue* v = + static_cast( + this->GetAsObjectBase(info)); + if(v) + { + v->Value.push_back(value); + } + else + { + this->Set(info, &value, 1); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleVectorKey::Set(vtkInformation* info, double* value, + int length) +{ + if(value) + { + if(this->RequiredLength >= 0 && length != this->RequiredLength) + { + vtkErrorWithObjectMacro( + info, + "Cannot store double vector of length " << length + << " with key " << this->Location << "::" << this->Name + << " which requires a vector of length " + << this->RequiredLength << ". Removing the key instead."); + this->SetAsObjectBase(info, 0); + return; + } + vtkInformationDoubleVectorValue* v = + new vtkInformationDoubleVectorValue; + this->ConstructClass("vtkInformationDoubleVectorValue"); + v->Value.insert(v->Value.begin(), value, value+length); + this->SetAsObjectBase(info, v); + v->Delete(); + } + else + { + this->SetAsObjectBase(info, 0); + } +} + +//---------------------------------------------------------------------------- +double* vtkInformationDoubleVectorKey::Get(vtkInformation* info) +{ + vtkInformationDoubleVectorValue* v = + static_cast( + this->GetAsObjectBase(info)); + return (v && !v->Value.empty())?(&v->Value[0]):0; +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleVectorKey::Get(vtkInformation* info, + double* value) +{ + vtkInformationDoubleVectorValue* v = + static_cast( + this->GetAsObjectBase(info)); + if(v && value) + { + for(vtkstd::vector::size_type i = 0; + i < v->Value.size(); ++i) + { + value[i] = v->Value[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkInformationDoubleVectorKey::Length(vtkInformation* info) +{ + vtkInformationDoubleVectorValue* v = + static_cast( + this->GetAsObjectBase(info)); + return v?static_cast(v->Value.size()):0; +} + +//---------------------------------------------------------------------------- +int vtkInformationDoubleVectorKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleVectorKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->Get(from), this->Length(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationDoubleVectorKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + double* value = this->Get(info); + int length = this->Length(info); + const char* sep = ""; + for(int i=0; i < length; ++i) + { + os << sep << value[i]; + sep = " "; + } + } +} diff --git a/Filtering/vtkInformationDoubleVectorKey.h b/Filtering/vtkInformationDoubleVectorKey.h new file mode 100644 index 0000000..76725a5 --- /dev/null +++ b/Filtering/vtkInformationDoubleVectorKey.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationDoubleVectorKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationDoubleVectorKey - Key for double vector values. +// .SECTION Description +// vtkInformationDoubleVectorKey is used to represent keys for double +// vector values in vtkInformation.h + +#ifndef __vtkInformationDoubleVectorKey_h +#define __vtkInformationDoubleVectorKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationDoubleVectorKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationDoubleVectorKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationDoubleVectorKey(const char* name, const char* location, + int length=-1); + ~vtkInformationDoubleVectorKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Append(vtkInformation* info, double value); + void Set(vtkInformation* info, double* value, int length); + double* Get(vtkInformation* info); + void Get(vtkInformation* info, double* value); + int Length(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + // The required length of the vector value (-1 is no restriction). + int RequiredLength; + +private: + vtkInformationDoubleVectorKey(const vtkInformationDoubleVectorKey&); // Not implemented. + void operator=(const vtkInformationDoubleVectorKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationExecutivePortKey.cxx b/Filtering/vtkInformationExecutivePortKey.cxx new file mode 100644 index 0000000..a2c4a91 --- /dev/null +++ b/Filtering/vtkInformationExecutivePortKey.cxx @@ -0,0 +1,166 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationExecutivePortKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationExecutivePortKey.h" + +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkSmartPointer.h" + +vtkCxxRevisionMacro(vtkInformationExecutivePortKey, "$Revision: 1.6 $"); + +//---------------------------------------------------------------------------- +vtkInformationExecutivePortKey::vtkInformationExecutivePortKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationExecutivePortKey::~vtkInformationExecutivePortKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationExecutivePortValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationExecutivePortValue, vtkObjectBase); + vtkSmartPointer Executive; + int Port; +}; + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortKey::Set(vtkInformation* info, + vtkExecutive* executive, int port) +{ + if(executive) + { + if(vtkInformationExecutivePortValue* oldv = + static_cast( + this->GetAsObjectBase(info))) + { + // Replace the existing value. + oldv->Executive = executive; + oldv->Port = port; + // Since this sets a value without call SetAsObjectBase(), + // the info has to be modified here (instead of + // vtkInformation::SetAsObjectBase() + info->Modified(); + } + else + { + // Allocate a new value. + vtkInformationExecutivePortValue* v = + new vtkInformationExecutivePortValue; + this->ConstructClass("vtkInformationExecutivePortValue"); + v->Executive = executive; + v->Port = port; + this->SetAsObjectBase(info, v); + v->Delete(); + } + } + else + { + this->SetAsObjectBase(info, 0); + } +} + +void vtkInformationExecutivePortKey::Get(vtkInformation *info, vtkExecutive*& executive, int &port) +{ + if(vtkInformationExecutivePortValue* v = + static_cast( + this->GetAsObjectBase(info))) + { + executive = v->Executive; + port = v->Port; + return; + } + + executive = 0; + port = 0; +} + +//---------------------------------------------------------------------------- +vtkExecutive* +vtkInformationExecutivePortKey::GetExecutive(vtkInformation* info) +{ + if(vtkInformationExecutivePortValue* v = + static_cast( + this->GetAsObjectBase(info))) + { + return v->Executive; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkInformationExecutivePortKey::GetPort(vtkInformation* info) +{ + vtkInformationExecutivePortValue* v = + static_cast( + this->GetAsObjectBase(info)); + return v?v->Port:0; +} + +//---------------------------------------------------------------------------- +int vtkInformationExecutivePortKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->GetExecutive(from), this->GetPort(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + vtkExecutive* executive = this->GetExecutive(info); + int port = this->GetPort(info); + if(executive) + { + os << executive->GetClassName() << "(" << executive << ") port " + << port; + } + else + { + os << "(NULL) port " << port; + } + } +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortKey::Report(vtkInformation* info, + vtkGarbageCollector* collector) +{ + if(vtkInformationExecutivePortValue* v = + static_cast( + this->GetAsObjectBase(info))) + { + v->Executive.Report(collector, this->GetName()); + } +} diff --git a/Filtering/vtkInformationExecutivePortKey.h b/Filtering/vtkInformationExecutivePortKey.h new file mode 100644 index 0000000..921eb3a --- /dev/null +++ b/Filtering/vtkInformationExecutivePortKey.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationExecutivePortKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationExecutivePortKey - Key for vtkExecutive/Port value pairs. +// .SECTION Description +// vtkInformationExecutivePortKey is used to represent keys in +// vtkInformation for values that are vtkExecutive instances paired +// with port numbers. + +#ifndef __vtkInformationExecutivePortKey_h +#define __vtkInformationExecutivePortKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class vtkExecutive; + +class VTK_FILTERING_EXPORT vtkInformationExecutivePortKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationExecutivePortKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationExecutivePortKey(const char* name, const char* location); + ~vtkInformationExecutivePortKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, vtkExecutive*, int); + vtkExecutive* GetExecutive(vtkInformation* info); + int GetPort(vtkInformation* info); + void Get(vtkInformation *info, vtkExecutive*& executive, int &port); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Report a reference this key has in the given information object. + virtual void Report(vtkInformation* info, vtkGarbageCollector* collector); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +private: + vtkInformationExecutivePortKey(const vtkInformationExecutivePortKey&); // Not implemented. + void operator=(const vtkInformationExecutivePortKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationExecutivePortVectorKey.cxx b/Filtering/vtkInformationExecutivePortVectorKey.cxx new file mode 100644 index 0000000..10382ad --- /dev/null +++ b/Filtering/vtkInformationExecutivePortVectorKey.cxx @@ -0,0 +1,320 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationExecutivePortVectorKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationExecutivePortVectorKey.h" + +#include "vtkExecutive.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" + +#include +#include + + +// should the pipeline be double or singly linked (referenced) list, single +// make garbage collecting easier but results in a weak reference. +#define VTK_USE_SINGLE_REF 1 + +vtkCxxRevisionMacro(vtkInformationExecutivePortVectorKey, "$Revision: 1.7.4.1 $"); + +//---------------------------------------------------------------------------- +vtkInformationExecutivePortVectorKey::vtkInformationExecutivePortVectorKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationExecutivePortVectorKey::~vtkInformationExecutivePortVectorKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationExecutivePortVectorValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationExecutivePortVectorValue, vtkObjectBase); + vtkstd::vector Executives; + vtkstd::vector Ports; + + virtual ~vtkInformationExecutivePortVectorValue(); + void UnRegisterAllExecutives(); +}; + +//---------------------------------------------------------------------------- +vtkInformationExecutivePortVectorValue +::~vtkInformationExecutivePortVectorValue() +{ + // Remove all our references to executives before erasing the vector. + this->UnRegisterAllExecutives(); +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorValue::UnRegisterAllExecutives() +{ +#ifndef VTK_USE_SINGLE_REF + for(vtkstd::vector::iterator i = this->Executives.begin(); + i != this->Executives.end(); ++i) + { + if(vtkExecutive* e = *i) + { + e->UnRegister(0); + } + } +#endif +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::Append(vtkInformation* info, + vtkExecutive* executive, + int port) +{ + if(vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + // The entry already exists. Append to its vector. +#ifndef VTK_USE_SINGLE_REF + executive->Register(0); +#endif + v->Executives.push_back(executive); + v->Ports.push_back(port); + } + else + { + // The entry does not yet exist. Just create it. + this->Set(info, &executive, &port, 1); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::Remove(vtkInformation* info, + vtkExecutive* executive, + int port) +{ + if(vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + // The entry exists. Find this executive/port pair and remove it. + for(unsigned int i=0; i < v->Executives.size(); ++i) + { + if(v->Executives[i] == executive && v->Ports[i] == port) + { + v->Executives.erase(v->Executives.begin()+i); + v->Ports.erase(v->Ports.begin()+i); +#ifndef VTK_USE_SINGLE_REF + executive->UnRegister(0); +#endif + break; + } + } + + // If the last entry was removed, remove the entire value. + if(v->Executives.empty()) + { + this->SetAsObjectBase(info, 0); + } + } +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::Set(vtkInformation* info, + vtkExecutive** executives, + int* ports, int length) +{ + if(executives && ports && length > 0) + { +#ifndef VTK_USE_SINGLE_REF + // Register our references to all the given executives. + for(int i=0; i < length; ++i) + { + if(executives[i]) + { + executives[i]->Register(0); + } + } +#endif + // Store the vector of pointers. + vtkInformationExecutivePortVectorValue* oldv = + static_cast + (this->GetAsObjectBase(info)); + if(oldv && static_cast(oldv->Executives.size()) == length) + { + // Replace the existing value. + oldv->UnRegisterAllExecutives(); + vtkstd::copy(executives, executives+length, oldv->Executives.begin()); + vtkstd::copy(ports, ports+length, oldv->Ports.begin()); + // Since this sets a value without call SetAsObjectBase(), + // the info has to be modified here (instead of + // vtkInformation::SetAsObjectBase() + info->Modified(); + } + else + { + // Allocate a new value. + vtkInformationExecutivePortVectorValue* v = + new vtkInformationExecutivePortVectorValue; + this->ConstructClass("vtkInformationExecutivePortVectorValue"); + v->Executives.insert(v->Executives.begin(), executives, executives+length); + v->Ports.insert(v->Ports.begin(), ports, ports+length); + this->SetAsObjectBase(info, v); + v->Delete(); + } + } + else + { + this->SetAsObjectBase(info, 0); + } +} + +//---------------------------------------------------------------------------- +vtkExecutive** +vtkInformationExecutivePortVectorKey::GetExecutives(vtkInformation* info) +{ + vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return (v && !v->Executives.empty())?(&v->Executives[0]):0; +} + +//---------------------------------------------------------------------------- +int* vtkInformationExecutivePortVectorKey::GetPorts(vtkInformation* info) +{ + vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return (v && !v->Ports.empty())?(&v->Ports[0]):0; +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::Get(vtkInformation* info, + vtkExecutive** executives, + int* ports) +{ + if(vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + vtkstd::copy(v->Executives.begin(), v->Executives.end(), executives); + vtkstd::copy(v->Ports.begin(), v->Ports.end(), ports); + } +} + +//---------------------------------------------------------------------------- +int vtkInformationExecutivePortVectorKey::Length(vtkInformation* info) +{ + vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v?static_cast(v->Executives.size()):0; +} + +//---------------------------------------------------------------------------- +int vtkInformationExecutivePortVectorKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->GetExecutives(from), this->GetPorts(from), + this->Length(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::Remove(vtkInformation* info) +{ + this->Superclass::Remove(info); +} + +//---------------------------------------------------------------------------- +void vtkInformationExecutivePortVectorKey::Print(ostream& os, + vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + vtkExecutive** executives = this->GetExecutives(info); + int* ports = this->GetPorts(info); + int length = this->Length(info); + const char* sep = ""; + for(int i=0; i < length; ++i) + { + if(executives[i]) + { + os << sep << executives[i]->GetClassName() + << "(" << executives[i] << ") port " << ports[i]; + } + else + { + os << sep << "(NULL) port " << ports[i]; + } + sep = ", "; + } + } +} + +//---------------------------------------------------------------------------- +void +#ifdef VTK_USE_SINGLE_REF +vtkInformationExecutivePortVectorKey::Report(vtkInformation*, + vtkGarbageCollector*) +{ +#else +vtkInformationExecutivePortVectorKey::Report(vtkInformation* info, + vtkGarbageCollector* collector) +{ + if(vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + for(vtkstd::vector::iterator i = v->Executives.begin(); + i != v->Executives.end(); ++i) + { + vtkGarbageCollectorReport(collector, *i, this->GetName()); + } + } +#endif +} + +//---------------------------------------------------------------------------- +vtkExecutive** +vtkInformationExecutivePortVectorKey +::GetExecutivesWatchAddress(vtkInformation* info) +{ + vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return (v && !v->Executives.empty())?(&v->Executives[0]):0; +} + +//---------------------------------------------------------------------------- +int* +vtkInformationExecutivePortVectorKey +::GetPortsWatchAddress(vtkInformation* info) +{ + vtkInformationExecutivePortVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return (v && !v->Ports.empty())?(&v->Ports[0]):0; +} diff --git a/Filtering/vtkInformationExecutivePortVectorKey.h b/Filtering/vtkInformationExecutivePortVectorKey.h new file mode 100644 index 0000000..b950eed --- /dev/null +++ b/Filtering/vtkInformationExecutivePortVectorKey.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationExecutivePortVectorKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationExecutivePortVectorKey - Key for vtkExecutive/Port value pair vectors. +// .SECTION Description +// vtkInformationExecutivePortVectorKey is used to represent keys in +// vtkInformation for values that are vectors of vtkExecutive +// instances paired with port numbers. + +#ifndef __vtkInformationExecutivePortVectorKey_h +#define __vtkInformationExecutivePortVectorKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class vtkExecutive; + +class VTK_FILTERING_EXPORT vtkInformationExecutivePortVectorKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationExecutivePortVectorKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationExecutivePortVectorKey(const char* name, const char* location); + ~vtkInformationExecutivePortVectorKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Append(vtkInformation* info, vtkExecutive* executive, int port); + void Remove(vtkInformation* info, vtkExecutive* executive, int port); + void Set(vtkInformation* info, vtkExecutive** executives, int* ports, int length); + vtkExecutive** GetExecutives(vtkInformation* info); + int* GetPorts(vtkInformation* info); + void Get(vtkInformation* info, vtkExecutive** executives, int* ports); + int Length(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Remove this key from the given information object. + virtual void Remove(vtkInformation* info); + + // Description: + // Report a reference this key has in the given information object. + virtual void Report(vtkInformation* info, vtkGarbageCollector* collector); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + + // Description: + // Get the address at which the actual value is stored. This is + // meant for use from a debugger to add watches and is therefore not + // a public method. + vtkExecutive** GetExecutivesWatchAddress(vtkInformation* info); + int* GetPortsWatchAddress(vtkInformation* info); + +private: + vtkInformationExecutivePortVectorKey(const vtkInformationExecutivePortVectorKey&); // Not implemented. + void operator=(const vtkInformationExecutivePortVectorKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationIdTypeKey.cxx b/Filtering/vtkInformationIdTypeKey.cxx new file mode 100644 index 0000000..a09e4bf --- /dev/null +++ b/Filtering/vtkInformationIdTypeKey.cxx @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIdTypeKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationIdTypeKey.h" + +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationIdTypeKey, "$Revision: 1.2 $"); + +//---------------------------------------------------------------------------- +vtkInformationIdTypeKey::vtkInformationIdTypeKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationIdTypeKey::~vtkInformationIdTypeKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationIdTypeKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationIdTypeValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationIdTypeValue, vtkObjectBase); + vtkIdType Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationIdTypeKey::Set(vtkInformation* info, vtkIdType value) +{ + if(vtkInformationIdTypeValue* oldv = + static_cast + (this->GetAsObjectBase(info))) + { + // Replace the existing value. + oldv->Value = value; + // Since this sets a value without call SetAsObjectBase(), + // the info has to be modified here (instead of + // vtkInformation::SetAsObjectBase() + info->Modified(); + } + else + { + // Allocate a new value. + vtkInformationIdTypeValue* v = new vtkInformationIdTypeValue; + this->ConstructClass("vtkInformationIdTypeValue"); + v->Value = value; + this->SetAsObjectBase(info, v); + v->Delete(); + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkInformationIdTypeKey::Get(vtkInformation* info) +{ + vtkInformationIdTypeValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v?v->Value:0; +} + +//---------------------------------------------------------------------------- +int vtkInformationIdTypeKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationIdTypeKey::ShallowCopy(vtkInformation* from, vtkInformation* to) +{ + if (this->Has(from)) + { + this->Set(to, this->Get(from)); + } + else + { + this->SetAsObjectBase(to, 0); // doesn't exist in from, so remove the key + } +} + +//---------------------------------------------------------------------------- +void vtkInformationIdTypeKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + os << this->Get(info); + } +} + +//---------------------------------------------------------------------------- +vtkIdType* vtkInformationIdTypeKey::GetWatchAddress(vtkInformation* info) +{ + if(vtkInformationIdTypeValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + return &v->Value; + } + return 0; +} diff --git a/Filtering/vtkInformationIdTypeKey.h b/Filtering/vtkInformationIdTypeKey.h new file mode 100644 index 0000000..7857713 --- /dev/null +++ b/Filtering/vtkInformationIdTypeKey.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIdTypeKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationIdTypeKey - Key for vtkIdType values in vtkInformation. +// .SECTION Description +// vtkInformationIdTypeKey is used to represent keys for vtkIdType values +// in vtkInformation. + +#ifndef __vtkInformationIdTypeKey_h +#define __vtkInformationIdTypeKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationIdTypeKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationIdTypeKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationIdTypeKey(const char* name, const char* location); + ~vtkInformationIdTypeKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, vtkIdType); + vtkIdType Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + // Description: + // Get the address at which the actual value is stored. This is + // meant for use from a debugger to add watches and is therefore not + // a public method. + vtkIdType* GetWatchAddress(vtkInformation* info); + +private: + vtkInformationIdTypeKey(const vtkInformationIdTypeKey&); // Not implemented. + void operator=(const vtkInformationIdTypeKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationInformationKey.cxx b/Filtering/vtkInformationInformationKey.cxx new file mode 100644 index 0000000..3cbb6c2 --- /dev/null +++ b/Filtering/vtkInformationInformationKey.cxx @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationInformationKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationInformationKey.h" + +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationInformationKey, "$Revision: 1.4 $"); + +//---------------------------------------------------------------------------- +vtkInformationInformationKey::vtkInformationInformationKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationInformationKey::~vtkInformationInformationKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationKey::Set(vtkInformation* info, + vtkInformation* value) +{ + this->SetAsObjectBase(info, value); +} + +//---------------------------------------------------------------------------- +vtkInformation* vtkInformationInformationKey::Get(vtkInformation* info) +{ + return static_cast(this->GetAsObjectBase(info)); +} + +//---------------------------------------------------------------------------- +int vtkInformationInformationKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->Get(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationKey::DeepCopy(vtkInformation* from, + vtkInformation* to) +{ + vtkInformation *toInfo = vtkInformation::New(); + toInfo->Copy(this->Get(from), 1); + this->Set(to, toInfo); + toInfo->Delete(); +} diff --git a/Filtering/vtkInformationInformationKey.h b/Filtering/vtkInformationInformationKey.h new file mode 100644 index 0000000..2c1859a --- /dev/null +++ b/Filtering/vtkInformationInformationKey.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationInformationKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationInformationKey - Key for vtkInformation values. +// .SECTION Description +// vtkInformationInformationKey is used to represent keys in vtkInformation +// for other information objects. + +#ifndef __vtkInformationInformationKey_h +#define __vtkInformationInformationKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationInformationKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationInformationKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationInformationKey(const char* name, const char* location); + ~vtkInformationInformationKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, vtkInformation*); + vtkInformation* Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Duplicate (new instance created) the entry associated with this key from + // one information object to another (new instances of any contained + // vtkInformation and vtkInformationVector objects are created). + virtual void DeepCopy(vtkInformation* from, vtkInformation* to); + +private: + vtkInformationInformationKey(const vtkInformationInformationKey&); // Not implemented. + void operator=(const vtkInformationInformationKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationInformationVectorKey.cxx b/Filtering/vtkInformationInformationVectorKey.cxx new file mode 100644 index 0000000..c6911df --- /dev/null +++ b/Filtering/vtkInformationInformationVectorKey.cxx @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationInformationVectorKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationInformationVectorKey.h" + +#include "vtkInformationVector.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationInformationVectorKey, "$Revision: 1.6 $"); + +//---------------------------------------------------------------------------- +vtkInformationInformationVectorKey::vtkInformationInformationVectorKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationInformationVectorKey::~vtkInformationInformationVectorKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationVectorKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationVectorKey::Set(vtkInformation* info, + vtkInformationVector* value) +{ + this->SetAsObjectBase(info, value); +} + +//---------------------------------------------------------------------------- +vtkInformationVector* +vtkInformationInformationVectorKey::Get(vtkInformation* info) +{ + return static_cast(this->GetAsObjectBase(info)); +} + +//---------------------------------------------------------------------------- +int vtkInformationInformationVectorKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationVectorKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->Get(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationVectorKey::DeepCopy(vtkInformation* from, + vtkInformation* to) +{ + vtkInformationVector *fromVector = this->Get(from); + vtkInformationVector *toVector = vtkInformationVector::New(); + vtkInformation *toInfo; + int i; + + for (i = 0; i < fromVector->GetNumberOfInformationObjects(); i++) + { + toInfo = vtkInformation::New(); + toInfo->Copy(fromVector->GetInformationObject(i), 1); + toVector->Append(toInfo); + toInfo->Delete(); + } + this->Set(to, toVector); + toVector->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkInformationInformationVectorKey::Report(vtkInformation* info, + vtkGarbageCollector* collector) +{ + this->ReportAsObjectBase(info, collector); +} diff --git a/Filtering/vtkInformationInformationVectorKey.h b/Filtering/vtkInformationInformationVectorKey.h new file mode 100644 index 0000000..a5f7da8 --- /dev/null +++ b/Filtering/vtkInformationInformationVectorKey.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationInformationVectorKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationInformationVectorKey - Key for vtkInformation vectors. +// .SECTION Description +// vtkInformationInformationVectorKey is used to represent keys in +// vtkInformation for vectors of other vtkInformation objects. + +#ifndef __vtkInformationInformationVectorKey_h +#define __vtkInformationInformationVectorKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class vtkInformationVector; + +class VTK_FILTERING_EXPORT vtkInformationInformationVectorKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationInformationVectorKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationInformationVectorKey(const char* name, const char* location); + ~vtkInformationInformationVectorKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, vtkInformationVector*); + vtkInformationVector* Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Duplicate (new instance created) the entry associated with this key from + // one information object to another (new instances of any contained + // vtkInformation and vtkInformationVector objects are created). + virtual void DeepCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Report a reference this key has in the given information object. + virtual void Report(vtkInformation* info, vtkGarbageCollector* collector); + +private: + vtkInformationInformationVectorKey(const vtkInformationInformationVectorKey&); // Not implemented. + void operator=(const vtkInformationInformationVectorKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationIntegerKey.cxx b/Filtering/vtkInformationIntegerKey.cxx new file mode 100644 index 0000000..ec29b32 --- /dev/null +++ b/Filtering/vtkInformationIntegerKey.cxx @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIntegerKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationIntegerKey.h" + +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationIntegerKey, "$Revision: 1.10 $"); + +//---------------------------------------------------------------------------- +vtkInformationIntegerKey::vtkInformationIntegerKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationIntegerKey::~vtkInformationIntegerKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationIntegerValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationIntegerValue, vtkObjectBase); + int Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationIntegerKey::Set(vtkInformation* info, int value) +{ + if(vtkInformationIntegerValue* oldv = + static_cast + (this->GetAsObjectBase(info))) + { + // Replace the existing value. + oldv->Value = value; + // Since this sets a value without call SetAsObjectBase(), + // the info has to be modified here (instead of + // vtkInformation::SetAsObjectBase() + info->Modified(); + } + else + { + // Allocate a new value. + vtkInformationIntegerValue* v = new vtkInformationIntegerValue; + this->ConstructClass("vtkInformationIntegerValue"); + v->Value = value; + this->SetAsObjectBase(info, v); + v->Delete(); + } +} + +//---------------------------------------------------------------------------- +int vtkInformationIntegerKey::Get(vtkInformation* info) +{ + vtkInformationIntegerValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v?v->Value:0; +} + +//---------------------------------------------------------------------------- +int vtkInformationIntegerKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerKey::ShallowCopy(vtkInformation* from, vtkInformation* to) +{ + if (this->Has(from)) + { + this->Set(to, this->Get(from)); + } + else + { + this->SetAsObjectBase(to, 0); // doesn't exist in from, so remove the key + } +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + os << this->Get(info); + } +} + +//---------------------------------------------------------------------------- +int* vtkInformationIntegerKey::GetWatchAddress(vtkInformation* info) +{ + if(vtkInformationIntegerValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + return &v->Value; + } + return 0; +} diff --git a/Filtering/vtkInformationIntegerKey.h b/Filtering/vtkInformationIntegerKey.h new file mode 100644 index 0000000..2389350 --- /dev/null +++ b/Filtering/vtkInformationIntegerKey.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIntegerKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationIntegerKey - Key for integer values in vtkInformation. +// .SECTION Description +// vtkInformationIntegerKey is used to represent keys for integer values +// in vtkInformation. + +#ifndef __vtkInformationIntegerKey_h +#define __vtkInformationIntegerKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationIntegerKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationIntegerKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationIntegerKey(const char* name, const char* location); + ~vtkInformationIntegerKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, int); + int Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + // Description: + // Get the address at which the actual value is stored. This is + // meant for use from a debugger to add watches and is therefore not + // a public method. + int* GetWatchAddress(vtkInformation* info); + +private: + vtkInformationIntegerKey(const vtkInformationIntegerKey&); // Not implemented. + void operator=(const vtkInformationIntegerKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationIntegerPointerKey.cxx b/Filtering/vtkInformationIntegerPointerKey.cxx new file mode 100644 index 0000000..a67c4e9 --- /dev/null +++ b/Filtering/vtkInformationIntegerPointerKey.cxx @@ -0,0 +1,157 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIntegerPointerKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationIntegerPointerKey.h" + +#include "vtkInformation.h" // For vtkErrorWithObjectMacro + +#include +#include + +vtkCxxRevisionMacro(vtkInformationIntegerPointerKey, "$Revision: 1.2 $"); + +//---------------------------------------------------------------------------- +vtkInformationIntegerPointerKey +::vtkInformationIntegerPointerKey(const char* name, const char* location, + int length): + vtkInformationKey(name, location), RequiredLength(length) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationIntegerPointerKey::~vtkInformationIntegerPointerKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerPointerKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationIntegerPointerValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationIntegerPointerValue, vtkObjectBase); + int* Value; + unsigned int Length; +}; + +//---------------------------------------------------------------------------- +void vtkInformationIntegerPointerKey::Set(vtkInformation* info, int* value, + int length) +{ + if(value) + { + if(this->RequiredLength >= 0 && length != this->RequiredLength) + { + vtkErrorWithObjectMacro( + info, + "Cannot store integer vector of length " << length + << " with key " << this->Location << "::" << this->Name + << " which requires a vector of length " + << this->RequiredLength << ". Removing the key instead."); + this->SetAsObjectBase(info, 0); + return; + } + + // Allocate a new value. + vtkInformationIntegerPointerValue* v = + new vtkInformationIntegerPointerValue; + this->ConstructClass("vtkInformationIntegerPointerValue"); + v->Value = value; + v->Length = length; + this->SetAsObjectBase(info, v); + v->Delete(); + } + else + { + this->SetAsObjectBase(info, 0); + } +} + +//---------------------------------------------------------------------------- +int* vtkInformationIntegerPointerKey::Get(vtkInformation* info) +{ + vtkInformationIntegerPointerValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v->Value; +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerPointerKey::Get(vtkInformation* info, + int* value) +{ + vtkInformationIntegerPointerValue* v = + static_cast + (this->GetAsObjectBase(info)); + if(v && value) + { + memcpy(value, v->Value, v->Length*sizeof(int)); + } +} + +//---------------------------------------------------------------------------- +int vtkInformationIntegerPointerKey::Length(vtkInformation* info) +{ + vtkInformationIntegerPointerValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v->Length; +} + +//---------------------------------------------------------------------------- +int vtkInformationIntegerPointerKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerPointerKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->Get(from), this->Length(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerPointerKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + int* value = this->Get(info); + int length = this->Length(info); + const char* sep = ""; + for(int i=0; i < length; ++i) + { + os << sep << value[i]; + sep = " "; + } + } +} + +//---------------------------------------------------------------------------- +int* vtkInformationIntegerPointerKey::GetWatchAddress(vtkInformation* info) +{ + if(vtkInformationIntegerPointerValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + return v->Value; + } + return 0; +} diff --git a/Filtering/vtkInformationIntegerPointerKey.h b/Filtering/vtkInformationIntegerPointerKey.h new file mode 100644 index 0000000..2708db1 --- /dev/null +++ b/Filtering/vtkInformationIntegerPointerKey.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIntegerPointerKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationIntegerPointerKey - Key for pointer to integer. +// .SECTION Description +// vtkInformationIntegerPointerKey is used to represent keys for pointer +// to integer values in vtkInformation.h + +#ifndef __vtkInformationIntegerPointerKey_h +#define __vtkInformationIntegerPointerKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationIntegerPointerKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationIntegerPointerKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationIntegerPointerKey(const char* name, const char* location, + int length=-1); + ~vtkInformationIntegerPointerKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, int* value, int length); + int* Get(vtkInformation* info); + void Get(vtkInformation* info, int* value); + int Length(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + // The required length of the vector value (-1 is no restriction). + int RequiredLength; + + // Description: + // Get the address at which the actual value is stored. This is + // meant for use from a debugger to add watches and is therefore not + // a public method. + int* GetWatchAddress(vtkInformation* info); + +private: + vtkInformationIntegerPointerKey(const vtkInformationIntegerPointerKey&); // Not implemented. + void operator=(const vtkInformationIntegerPointerKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationIntegerVectorKey.cxx b/Filtering/vtkInformationIntegerVectorKey.cxx new file mode 100644 index 0000000..2102c0e --- /dev/null +++ b/Filtering/vtkInformationIntegerVectorKey.cxx @@ -0,0 +1,187 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIntegerVectorKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationIntegerVectorKey.h" + +#include "vtkInformation.h" // For vtkErrorWithObjectMacro + +#include +#include + +vtkCxxRevisionMacro(vtkInformationIntegerVectorKey, "$Revision: 1.10.6.1 $"); + +//---------------------------------------------------------------------------- +vtkInformationIntegerVectorKey +::vtkInformationIntegerVectorKey(const char* name, const char* location, + int length): + vtkInformationKey(name, location), RequiredLength(length) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationIntegerVectorKey::~vtkInformationIntegerVectorKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerVectorKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationIntegerVectorValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationIntegerVectorValue, vtkObjectBase); + vtkstd::vector Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationIntegerVectorKey::Append(vtkInformation* info, int value) +{ + vtkInformationIntegerVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + if(v) + { + v->Value.push_back(value); + } + else + { + this->Set(info, &value, 1); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerVectorKey::Set(vtkInformation* info, int* value, + int length) +{ + if(value) + { + if(this->RequiredLength >= 0 && length != this->RequiredLength) + { + vtkErrorWithObjectMacro( + info, + "Cannot store integer vector of length " << length + << " with key " << this->Location << "::" << this->Name + << " which requires a vector of length " + << this->RequiredLength << ". Removing the key instead."); + this->SetAsObjectBase(info, 0); + return; + } + + vtkInformationIntegerVectorValue* oldv = + static_cast + (this->GetAsObjectBase(info)); + if(oldv && static_cast(oldv->Value.size()) == length) + { + // Replace the existing value. + vtkstd::copy(value, value+length, oldv->Value.begin()); + // Since this sets a value without call SetAsObjectBase(), + // the info has to be modified here (instead of + // vtkInformation::SetAsObjectBase() + info->Modified(); + } + else + { + // Allocate a new value. + vtkInformationIntegerVectorValue* v = + new vtkInformationIntegerVectorValue; + this->ConstructClass("vtkInformationIntegerVectorValue"); + v->Value.insert(v->Value.begin(), value, value+length); + this->SetAsObjectBase(info, v); + v->Delete(); + } + } + else + { + this->SetAsObjectBase(info, 0); + } +} + +//---------------------------------------------------------------------------- +int* vtkInformationIntegerVectorKey::Get(vtkInformation* info) +{ + vtkInformationIntegerVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return (v && !v->Value.empty())?(&v->Value[0]):0; +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerVectorKey::Get(vtkInformation* info, + int* value) +{ + vtkInformationIntegerVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + if(v && value) + { + for(vtkstd::vector::size_type i = 0; + i < v->Value.size(); ++i) + { + value[i] = v->Value[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkInformationIntegerVectorKey::Length(vtkInformation* info) +{ + vtkInformationIntegerVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v?static_cast(v->Value.size()):0; +} + +//---------------------------------------------------------------------------- +int vtkInformationIntegerVectorKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerVectorKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->Get(from), this->Length(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationIntegerVectorKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + int* value = this->Get(info); + int length = this->Length(info); + const char* sep = ""; + for(int i=0; i < length; ++i) + { + os << sep << value[i]; + sep = " "; + } + } +} + +//---------------------------------------------------------------------------- +int* vtkInformationIntegerVectorKey::GetWatchAddress(vtkInformation* info) +{ + vtkInformationIntegerVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return (v && !v->Value.empty())?(&v->Value[0]):0; +} diff --git a/Filtering/vtkInformationIntegerVectorKey.h b/Filtering/vtkInformationIntegerVectorKey.h new file mode 100644 index 0000000..d341d75 --- /dev/null +++ b/Filtering/vtkInformationIntegerVectorKey.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationIntegerVectorKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationIntegerVectorKey - Key for integer vector values. +// .SECTION Description +// vtkInformationIntegerVectorKey is used to represent keys for integer +// vector values in vtkInformation.h + +#ifndef __vtkInformationIntegerVectorKey_h +#define __vtkInformationIntegerVectorKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationIntegerVectorKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationIntegerVectorKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationIntegerVectorKey(const char* name, const char* location, + int length=-1); + ~vtkInformationIntegerVectorKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Append(vtkInformation* info, int value); + void Set(vtkInformation* info, int* value, int length); + int* Get(vtkInformation* info); + void Get(vtkInformation* info, int* value); + int Length(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + // The required length of the vector value (-1 is no restriction). + int RequiredLength; + + // Description: + // Get the address at which the actual value is stored. This is + // meant for use from a debugger to add watches and is therefore not + // a public method. + int* GetWatchAddress(vtkInformation* info); + +private: + vtkInformationIntegerVectorKey(const vtkInformationIntegerVectorKey&); // Not implemented. + void operator=(const vtkInformationIntegerVectorKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationKey.cxx b/Filtering/vtkInformationKey.cxx new file mode 100644 index 0000000..adf3824 --- /dev/null +++ b/Filtering/vtkInformationKey.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationKey.h" + +#include "vtkDebugLeaks.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationKey, "$Revision: 1.9 $"); + +class vtkInformationKeyToInformationFriendship +{ +public: + static void SetAsObjectBase(vtkInformation* info, vtkInformationKey* key, + vtkObjectBase* value) + { + info->SetAsObjectBase(key, value); + } + static vtkObjectBase* GetAsObjectBase(vtkInformation* info, + vtkInformationKey* key) + { + return info->GetAsObjectBase(key); + } + static void ReportAsObjectBase(vtkInformation* info, vtkInformationKey* key, + vtkGarbageCollector* collector) + { + info->ReportAsObjectBase(key, collector); + } +}; + +//---------------------------------------------------------------------------- +vtkInformationKey::vtkInformationKey(const char* name, const char* location) +{ + // Save the name and location. + this->Name = name; + this->Location = location; +} + +//---------------------------------------------------------------------------- +vtkInformationKey::~vtkInformationKey() +{ + this->SetReferenceCount(0); +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::Register(vtkObjectBase*) +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::UnRegister(vtkObjectBase*) +{ +} + +//---------------------------------------------------------------------------- +const char* vtkInformationKey::GetName() +{ + return this->Name; +} + +//---------------------------------------------------------------------------- +const char* vtkInformationKey::GetLocation() +{ + return this->Location; +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::SetAsObjectBase(vtkInformation* info, + vtkObjectBase* value) +{ + vtkInformationKeyToInformationFriendship::SetAsObjectBase(info, this, value); +} + +//---------------------------------------------------------------------------- +vtkObjectBase* vtkInformationKey::GetAsObjectBase(vtkInformation* info) +{ + return vtkInformationKeyToInformationFriendship::GetAsObjectBase(info, this); +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::Remove(vtkInformation* info) +{ + this->SetAsObjectBase(info, 0); +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::Report(vtkInformation*, vtkGarbageCollector*) +{ + // Report nothing by default. +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::Print(vtkInformation* info) +{ + this->Print(cout, info); +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::Print(ostream& os, vtkInformation* info) +{ + // Just print the value type and pointer by default. + if(vtkObjectBase* value = this->GetAsObjectBase(info)) + { + os << value->GetClassName() << "(" << value << ")"; + } +} + +//---------------------------------------------------------------------------- +void vtkInformationKey::ReportAsObjectBase(vtkInformation* info, + vtkGarbageCollector* collector) +{ + vtkInformationKeyToInformationFriendship::ReportAsObjectBase(info, this, + collector); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_DEBUG_LEAKS +void vtkInformationKey::ConstructClass(const char* name) +{ + vtkDebugLeaks::ConstructClass(name); +} +#else +void vtkInformationKey::ConstructClass(const char*) +{ +} +#endif diff --git a/Filtering/vtkInformationKey.h b/Filtering/vtkInformationKey.h new file mode 100644 index 0000000..293e014 --- /dev/null +++ b/Filtering/vtkInformationKey.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationKey - Superclass for vtkInformation keys. +// .SECTION Description +// vtkInformationKey is the superclass for all keys used to access the +// map represented by vtkInformation. The vtkInformation::Set and +// vtkInformation::Get methods of vtkInformation are accessed by +// information keys. A key is a pointer to an instance of a subclass +// of vtkInformationKey. The type of the subclass determines the +// overload of Set/Get that is selected. This ensures that the type +// of value stored in a vtkInformation instance corresponding to a +// given key matches the type expected for that key. + +#ifndef __vtkInformationKey_h +#define __vtkInformationKey_h + +#include "vtkObjectBase.h" +#include "vtkObject.h" // Need vtkTypeRevisionMacro + +class vtkInformation; + +class VTK_FILTERING_EXPORT vtkInformationKey : public vtkObjectBase +{ +public: + vtkTypeRevisionMacro(vtkInformationKey,vtkObjectBase); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Prevent normal vtkObject reference counting behavior. + virtual void Register(vtkObjectBase*); + + // Description: + // Prevent normal vtkObject reference counting behavior. + virtual void UnRegister(vtkObjectBase*); + + // Description: + // Get the name of the key. This is not the type of the key, but + // the name of the key instance. + const char* GetName(); + + // Description: + // Get the location of the key. This is the name of the class in + // which the key is defined. + const char* GetLocation(); + + // Description: + // Key instances are static data that need to be created and + // destroyed. The constructor and destructor must be public. The + // name of the static instance and the class in which it is defined + // should be passed to the constructor. They must be string + // literals because the strings are not copied. + vtkInformationKey(const char* name, const char* location); + ~vtkInformationKey(); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to)=0; + + // Description: + // Duplicate (new instance created) the entry associated with this key from + // one information object to another (new instances of any contained + // vtkInformation and vtkInformationVector objects are created). + virtual void DeepCopy(vtkInformation *vtkNotUsed(from), + vtkInformation *vtkNotUsed(to)) {} + + // Description: + // Remove this key from the given information object. + virtual void Remove(vtkInformation* info); + + // Description: + // Report a reference this key has in the given information object. + virtual void Report(vtkInformation* info, vtkGarbageCollector* collector); + + // Description: + // Print the key's value in an information object to a stream. + void Print(vtkInformation* info); + virtual void Print(ostream& os, vtkInformation* info); + +protected: + const char* Name; + const char* Location; + + // Set/Get the value associated with this key instance in the given + // information object. + void SetAsObjectBase(vtkInformation* info, vtkObjectBase* value); + vtkObjectBase* GetAsObjectBase(vtkInformation* info); + + // Report the object associated with this key instance in the given + // information object to the collector. + void ReportAsObjectBase(vtkInformation* info, + vtkGarbageCollector* collector); + + // Helper for debug leaks support. + void ConstructClass(const char*); + +private: + vtkInformationKey(const vtkInformationKey&); // Not implemented. + void operator=(const vtkInformationKey&); // Not implemented. +}; + +// Macros to define an information key instance in a C++ source file. +// The corresponding method declaration must appear in the class +// definition in the header file. +#define vtkInformationKeyMacro(CLASS, NAME, type) \ + static vtkInformation##type##Key* CLASS##_##NAME = \ + new vtkInformation##type##Key(#NAME, #CLASS); \ + vtkInformation##type##Key* CLASS::NAME() { return CLASS##_##NAME; } +#define vtkInformationKeyRestrictedMacro(CLASS, NAME, type, required) \ + static vtkInformation##type##Key* CLASS##_##NAME = \ + new vtkInformation##type##Key(#NAME, #CLASS, required); \ + vtkInformation##type##Key* CLASS::NAME() { return CLASS##_##NAME; } + +#endif diff --git a/Filtering/vtkInformationKeyVectorKey.cxx b/Filtering/vtkInformationKeyVectorKey.cxx new file mode 100644 index 0000000..e848984 --- /dev/null +++ b/Filtering/vtkInformationKeyVectorKey.cxx @@ -0,0 +1,194 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationKeyVectorKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationKeyVectorKey.h" + +#include +#include // find() + +vtkCxxRevisionMacro(vtkInformationKeyVectorKey, "$Revision: 1.10.6.2 $"); + +//---------------------------------------------------------------------------- +vtkInformationKeyVectorKey::vtkInformationKeyVectorKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationKeyVectorKey::~vtkInformationKeyVectorKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationKeyVectorValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationKeyVectorValue, vtkObjectBase); + vtkstd::vector Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::Append(vtkInformation* info, + vtkInformationKey* value) +{ + vtkInformationKeyVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + if(v) + { + v->Value.push_back(value); + } + else + { + this->Set(info, &value, 1); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::AppendUnique(vtkInformation* info, + vtkInformationKey* value) +{ + vtkInformationKeyVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + if(v) + { + int found = 0; + unsigned int len = v->Value.size(); + for (unsigned int i=0; iValue[i] == value) + { + found = 1; + break; + } + } + if (!found) + { + v->Value.push_back(value); + } + } + else + { + this->Set(info, &value, 1); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::Set(vtkInformation* info, + vtkInformationKey** value, int length) +{ + if(value) + { + vtkInformationKeyVectorValue* v = + new vtkInformationKeyVectorValue; + this->ConstructClass("vtkInformationKeyVectorValue"); + v->Value.insert(v->Value.begin(), value, value+length); + this->SetAsObjectBase(info, v); + v->Delete(); + } + else + { + this->SetAsObjectBase(info, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::RemoveItem(vtkInformation* info, + vtkInformationKey* value) +{ + vtkInformationKeyVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + + if(v) + { + vtkstd::vector::iterator it=vtkstd::find(v->Value.begin(),v->Value.end(),value); + if(it!=v->Value.end()) + { + v->Value.erase(it); + } + } +} + +//---------------------------------------------------------------------------- +vtkInformationKey** vtkInformationKeyVectorKey::Get(vtkInformation* info) +{ + vtkInformationKeyVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return (v && !v->Value.empty())?(&v->Value[0]):0; +} + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::Get(vtkInformation* info, + vtkInformationKey** value) +{ + vtkInformationKeyVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + if(v && value) + { + for(vtkstd::vector::size_type i = 0; + i < v->Value.size(); ++i) + { + value[i] = v->Value[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkInformationKeyVectorKey::Length(vtkInformation* info) +{ + vtkInformationKeyVectorValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v?static_cast(v->Value.size()):0; +} + +//---------------------------------------------------------------------------- +int vtkInformationKeyVectorKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::ShallowCopy(vtkInformation* from, vtkInformation* to) +{ + this->Set(to, this->Get(from), this->Length(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationKeyVectorKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + vtkInformationKey** value = this->Get(info); + int length = this->Length(info); + const char* sep = ""; + for(int i=0; i < length; ++i) + { + os << sep << (value[i]? value[i]->GetName() : "(NULL)"); + sep = " "; + } + } +} diff --git a/Filtering/vtkInformationKeyVectorKey.h b/Filtering/vtkInformationKeyVectorKey.h new file mode 100644 index 0000000..4dd16b4 --- /dev/null +++ b/Filtering/vtkInformationKeyVectorKey.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationKeyVectorKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationKeyVectorKey - Key for vector-of-keys values. +// .SECTION Description +// vtkInformationKeyVectorKey is used to represent keys for +// vector-of-keys values in vtkInformation. + +#ifndef __vtkInformationKeyVectorKey_h +#define __vtkInformationKeyVectorKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationKeyVectorKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationKeyVectorKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationKeyVectorKey(const char* name, const char* location); + ~vtkInformationKeyVectorKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Append(vtkInformation* info, vtkInformationKey* value); + void AppendUnique(vtkInformation* info, vtkInformationKey* value); + void Set(vtkInformation* info, vtkInformationKey** value, int length); + void RemoveItem(vtkInformation* info, vtkInformationKey* value); + vtkInformationKey** Get(vtkInformation* info); + void Get(vtkInformation* info, vtkInformationKey** value); + int Length(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +private: + vtkInformationKeyVectorKey(const vtkInformationKeyVectorKey&); // Not implemented. + void operator=(const vtkInformationKeyVectorKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationObjectBaseKey.cxx b/Filtering/vtkInformationObjectBaseKey.cxx new file mode 100644 index 0000000..f4c61d2 --- /dev/null +++ b/Filtering/vtkInformationObjectBaseKey.cxx @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationObjectBaseKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationObjectBaseKey.h" + +#include "vtkInformation.h" // For vtkErrorWithObjectMacro + +vtkCxxRevisionMacro(vtkInformationObjectBaseKey, "$Revision: 1.5 $"); + +//---------------------------------------------------------------------------- +vtkInformationObjectBaseKey +::vtkInformationObjectBaseKey(const char* name, const char* location, + const char* requiredClass): + vtkInformationKey(name, location), RequiredClass(requiredClass) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationObjectBaseKey::~vtkInformationObjectBaseKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationObjectBaseKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkInformationObjectBaseKey::Set(vtkInformation* info, + vtkObjectBase* value) +{ + if(value && this->RequiredClass && !value->IsA(this->RequiredClass)) + { + vtkErrorWithObjectMacro( + info, + "Cannot store object of type " << value->GetClassName() + << " with key " << this->Location << "::" << this->Name + << " which requires objects of type " + << this->RequiredClass << ". Removing the key instead."); + this->SetAsObjectBase(info, 0); + return; + } + this->SetAsObjectBase(info, value); +} + +//---------------------------------------------------------------------------- +vtkObjectBase* vtkInformationObjectBaseKey::Get(vtkInformation* info) +{ + return this->GetAsObjectBase(info); +} + +//---------------------------------------------------------------------------- +int vtkInformationObjectBaseKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationObjectBaseKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + this->Set(to, this->Get(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationObjectBaseKey::Report(vtkInformation* info, + vtkGarbageCollector* collector) +{ + this->ReportAsObjectBase(info, collector); +} diff --git a/Filtering/vtkInformationObjectBaseKey.h b/Filtering/vtkInformationObjectBaseKey.h new file mode 100644 index 0000000..137640a --- /dev/null +++ b/Filtering/vtkInformationObjectBaseKey.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationObjectBaseKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationObjectBaseKey - Key for vtkObjectBase values. +// .SECTION Description +// vtkInformationObjectBaseKey is used to represent keys in +// vtkInformation for values that are vtkObjectBase instances. + +#ifndef __vtkInformationObjectBaseKey_h +#define __vtkInformationObjectBaseKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class vtkObjectBase; + +class VTK_FILTERING_EXPORT vtkInformationObjectBaseKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationObjectBaseKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationObjectBaseKey(const char* name, const char* location, + const char* requiredClass=0); + ~vtkInformationObjectBaseKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, vtkObjectBase*); + vtkObjectBase* Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Report a reference this key has in the given information object. + virtual void Report(vtkInformation* info, vtkGarbageCollector* collector); + +protected: + // The type required of all objects stored with this key. + const char* RequiredClass; +private: + vtkInformationObjectBaseKey(const vtkInformationObjectBaseKey&); // Not implemented. + void operator=(const vtkInformationObjectBaseKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationRequestKey.cxx b/Filtering/vtkInformationRequestKey.cxx new file mode 100644 index 0000000..9bc5fae --- /dev/null +++ b/Filtering/vtkInformationRequestKey.cxx @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationRequestKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationRequestKey.h" + +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationRequestKey, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +vtkInformationRequestKey::vtkInformationRequestKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationRequestKey::~vtkInformationRequestKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationRequestKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkInformationRequestKey::Set(vtkInformation* info) +{ + if (info->GetRequest() != this) + { + if (info->GetRequest()) + { + vtkGenericWarningMacro("Setting request key when one is already set. Current request is " << info->GetRequest()->GetName() << " while setting " << this->GetName() << "\n"); + } + info->SetRequest(this); + info->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkInformationRequestKey::Has(vtkInformation* info) +{ + return (info->GetRequest() == this)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationRequestKey::Remove(vtkInformation* info) +{ + info->SetRequest(0); +} + +//---------------------------------------------------------------------------- +void vtkInformationRequestKey::ShallowCopy(vtkInformation* from, vtkInformation* to) +{ + to->SetRequest(from->GetRequest()); +} + +//---------------------------------------------------------------------------- +void vtkInformationRequestKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + os << "1\n"; + } +} + diff --git a/Filtering/vtkInformationRequestKey.h b/Filtering/vtkInformationRequestKey.h new file mode 100644 index 0000000..36307ef --- /dev/null +++ b/Filtering/vtkInformationRequestKey.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationRequestKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationRequestKey - Key for pointer to pointer. +// .SECTION Description +// vtkInformationRequestKey is used to represent keys for pointer +// to pointer values in vtkInformation.h + +#ifndef __vtkInformationRequestKey_h +#define __vtkInformationRequestKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationRequestKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationRequestKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationRequestKey(const char* name, const char* location); + ~vtkInformationRequestKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info); + void Remove(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +private: + vtkInformationRequestKey(const vtkInformationRequestKey&); // Not implemented. + void operator=(const vtkInformationRequestKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationStringKey.cxx b/Filtering/vtkInformationStringKey.cxx new file mode 100644 index 0000000..0726b2d --- /dev/null +++ b/Filtering/vtkInformationStringKey.cxx @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationStringKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationStringKey.h" + +#include + +vtkCxxRevisionMacro(vtkInformationStringKey, "$Revision: 1.7 $"); + +//---------------------------------------------------------------------------- +vtkInformationStringKey::vtkInformationStringKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationStringKey::~vtkInformationStringKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationStringKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationStringValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationStringValue, vtkObjectBase); + vtkstd::string Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationStringKey::Set(vtkInformation* info, const char* value) +{ + if(value) + { + vtkInformationStringValue* v = new vtkInformationStringValue; + this->ConstructClass("vtkInformationStringValue"); + v->Value = value; + this->SetAsObjectBase(info, v); + v->Delete(); + } + else + { + this->SetAsObjectBase(info, 0); + } +} + +//---------------------------------------------------------------------------- +const char* vtkInformationStringKey::Get(vtkInformation* info) +{ + vtkInformationStringValue* v = + static_cast(this->GetAsObjectBase(info)); + return v?v->Value.c_str():0; +} + +//---------------------------------------------------------------------------- +int vtkInformationStringKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationStringKey::ShallowCopy(vtkInformation* from, vtkInformation* to) +{ + this->Set(to, this->Get(from)); +} + +//---------------------------------------------------------------------------- +void vtkInformationStringKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + os << this->Get(info); + } +} diff --git a/Filtering/vtkInformationStringKey.h b/Filtering/vtkInformationStringKey.h new file mode 100644 index 0000000..ea29cc3 --- /dev/null +++ b/Filtering/vtkInformationStringKey.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationStringKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationStringKey - Key for string values in vtkInformation. +// .SECTION Description +// vtkInformationStringKey is used to represent keys for string values +// in vtkInformation. + +#ifndef __vtkInformationStringKey_h +#define __vtkInformationStringKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationStringKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationStringKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationStringKey(const char* name, const char* location); + ~vtkInformationStringKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, const char*); + const char* Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +private: + vtkInformationStringKey(const vtkInformationStringKey&); // Not implemented. + void operator=(const vtkInformationStringKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationUnsignedLongKey.cxx b/Filtering/vtkInformationUnsignedLongKey.cxx new file mode 100644 index 0000000..0811417 --- /dev/null +++ b/Filtering/vtkInformationUnsignedLongKey.cxx @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationUnsignedLongKey.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationUnsignedLongKey.h" + +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkInformationUnsignedLongKey, "$Revision: 1.10 $"); + +//---------------------------------------------------------------------------- +vtkInformationUnsignedLongKey::vtkInformationUnsignedLongKey(const char* name, const char* location): + vtkInformationKey(name, location) +{ + vtkFilteringInformationKeyManager::Register(this); +} + +//---------------------------------------------------------------------------- +vtkInformationUnsignedLongKey::~vtkInformationUnsignedLongKey() +{ +} + +//---------------------------------------------------------------------------- +void vtkInformationUnsignedLongKey::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +class vtkInformationUnsignedLongValue: public vtkObjectBase +{ +public: + vtkTypeMacro(vtkInformationUnsignedLongValue, vtkObjectBase); + unsigned long Value; +}; + +//---------------------------------------------------------------------------- +void vtkInformationUnsignedLongKey::Set(vtkInformation* info, + unsigned long value) +{ + if(vtkInformationUnsignedLongValue* oldv = + static_cast + (this->GetAsObjectBase(info))) + { + // Replace the existing value. + oldv->Value = value; + // Since this sets a value without call SetAsObjectBase(), + // the info has to be modified here (instead of + // vtkInformation::SetAsObjectBase() + info->Modified(); + } + else + { + // Allocate a new value. + vtkInformationUnsignedLongValue* v = new vtkInformationUnsignedLongValue; + this->ConstructClass("vtkInformationUnsignedLongValue"); + v->Value = value; + this->SetAsObjectBase(info, v); + v->Delete(); + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkInformationUnsignedLongKey::Get(vtkInformation* info) +{ + vtkInformationUnsignedLongValue* v = + static_cast + (this->GetAsObjectBase(info)); + return v?v->Value:0; +} + +//---------------------------------------------------------------------------- +int vtkInformationUnsignedLongKey::Has(vtkInformation* info) +{ + return this->GetAsObjectBase(info)?1:0; +} + +//---------------------------------------------------------------------------- +void vtkInformationUnsignedLongKey::ShallowCopy(vtkInformation* from, + vtkInformation* to) +{ + if (this->Has(from)) + { + this->Set(to, this->Get(from)); + } + else + { + this->SetAsObjectBase(to, 0); // doesn't exist in from, so remove the key + } +} + +//---------------------------------------------------------------------------- +void vtkInformationUnsignedLongKey::Print(ostream& os, vtkInformation* info) +{ + // Print the value. + if(this->Has(info)) + { + os << this->Get(info); + } +} + +//---------------------------------------------------------------------------- +unsigned long* +vtkInformationUnsignedLongKey::GetWatchAddress(vtkInformation* info) +{ + if(vtkInformationUnsignedLongValue* v = + static_cast + (this->GetAsObjectBase(info))) + { + return &v->Value; + } + return 0; +} diff --git a/Filtering/vtkInformationUnsignedLongKey.h b/Filtering/vtkInformationUnsignedLongKey.h new file mode 100644 index 0000000..63b9562 --- /dev/null +++ b/Filtering/vtkInformationUnsignedLongKey.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationUnsignedLongKey.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationUnsignedLongKey - Key for unsigned long values in vtkInformation. +// .SECTION Description +// vtkInformationUnsignedLongKey is used to represent keys for unsigned long values +// in vtkInformation. + +#ifndef __vtkInformationUnsignedLongKey_h +#define __vtkInformationUnsignedLongKey_h + +#include "vtkInformationKey.h" + +#include "vtkFilteringInformationKeyManager.h" // Manage instances of this type. + +class VTK_FILTERING_EXPORT vtkInformationUnsignedLongKey : public vtkInformationKey +{ +public: + vtkTypeRevisionMacro(vtkInformationUnsignedLongKey,vtkInformationKey); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkInformationUnsignedLongKey(const char* name, const char* location); + ~vtkInformationUnsignedLongKey(); + + // Description: + // Get/Set the value associated with this key in the given + // information object. + void Set(vtkInformation* info, unsigned long); + unsigned long Get(vtkInformation* info); + int Has(vtkInformation* info); + + // Description: + // Copy the entry associated with this key from one information + // object to another. If there is no entry in the first information + // object for this key, the value is removed from the second. + virtual void ShallowCopy(vtkInformation* from, vtkInformation* to); + + // Description: + // Print the key's value in an information object to a stream. + virtual void Print(ostream& os, vtkInformation* info); + +protected: + // Description: + // Get the address at which the actual value is stored. This is + // meant for use from a debugger to add watches and is therefore not + // a public method. + unsigned long* GetWatchAddress(vtkInformation* info); + +private: + vtkInformationUnsignedLongKey(const vtkInformationUnsignedLongKey&); // Not implemented. + void operator=(const vtkInformationUnsignedLongKey&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInformationVector.cxx b/Filtering/vtkInformationVector.cxx new file mode 100644 index 0000000..c2c9c08 --- /dev/null +++ b/Filtering/vtkInformationVector.cxx @@ -0,0 +1,230 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationVector.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInformationVector.h" + +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkInformationVector, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkInformationVector); + +class vtkInformationVectorInternals +{ +public: + vtkstd::vector Vector; + + ~vtkInformationVectorInternals(); +}; + +//---------------------------------------------------------------------------- +vtkInformationVectorInternals::~vtkInformationVectorInternals() +{ + // Delete all the information objects. + for(vtkstd::vector::iterator i = this->Vector.begin(); + i != this->Vector.end(); ++i) + { + if(vtkInformation* info = *i) + { + info->Delete(); + } + } +} + +//---------------------------------------------------------------------------- +vtkInformationVector::vtkInformationVector() +{ + this->Internal = new vtkInformationVectorInternals; + this->NumberOfInformationObjects = 0; +} + +//---------------------------------------------------------------------------- +vtkInformationVector::~vtkInformationVector() +{ + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Number of Information Objects: " << this->NumberOfInformationObjects << "\n"; + os << indent << "Information Objects:\n"; + for(int i=0; i < this->NumberOfInformationObjects; ++i) + { + vtkInformation* info = this->GetInformationObject(i); + vtkIndent nextIndent = indent.GetNextIndent(); + os << nextIndent << info->GetClassName() << "(" << info << "):\n"; + info->PrintSelf(os, nextIndent.GetNextIndent()); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::SetNumberOfInformationObjects(int newNumber) +{ + // Adjust the number of objects. + int oldNumber = this->NumberOfInformationObjects; + if(newNumber > oldNumber) + { + // Create new information objects. + this->Internal->Vector.resize(newNumber, 0); + for(int i=oldNumber; i < newNumber; ++i) + { + this->Internal->Vector[i] = vtkInformation::New(); + } + } + else if(newNumber < oldNumber) + { + // Delete old information objects. + for(int i=newNumber; i < oldNumber; ++i) + { + if(vtkInformation* info = this->Internal->Vector[i]) + { + // Set the pointer to NULL first to avoid reporting of the + // entry if deleting the information object causes a garbage + // collection reference walk. + this->Internal->Vector[i] = 0; + info->Delete(); + } + } + this->Internal->Vector.resize(newNumber); + } + this->NumberOfInformationObjects = newNumber; +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::SetInformationObject(int index, + vtkInformation* newInfo) +{ + if(newInfo && index >= 0 && index < this->NumberOfInformationObjects) + { + // Replace an existing information object. + vtkInformation* oldInfo = this->Internal->Vector[index]; + if(oldInfo != newInfo) + { + newInfo->Register(this); + this->Internal->Vector[index] = newInfo; + oldInfo->UnRegister(this); + } + } + else if(newInfo && index >= this->NumberOfInformationObjects) + { + // If a hole will be created fill it with empty objects. + if(index > this->NumberOfInformationObjects) + { + this->SetNumberOfInformationObjects(index); + } + + // Store the information object in a new entry. + newInfo->Register(this); + this->Internal->Vector.push_back(newInfo); + this->NumberOfInformationObjects++; + } + else if(!newInfo && index >= 0 && + index < this->NumberOfInformationObjects-1) + { + // We do not allow NULL information objects. Create an empty one + // to fill in the hole. + vtkInformation* oldInfo = this->Internal->Vector[index]; + this->Internal->Vector[index] = vtkInformation::New(); + oldInfo->UnRegister(this); + } + else if(!newInfo && index >= 0 && + index == this->NumberOfInformationObjects-1) + { + // Remove the last information object. + this->SetNumberOfInformationObjects(index); + } +} + +//---------------------------------------------------------------------------- +vtkInformation* vtkInformationVector::GetInformationObject(int index) +{ + if(index >= 0 && index < this->NumberOfInformationObjects) + { + return this->Internal->Vector[index]; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::Append(vtkInformation* info) +{ + // Setting an entry beyond the end will automatically append. + this->SetInformationObject(this->NumberOfInformationObjects, info); +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::Remove(vtkInformation* info) +{ + // Search for the information object and remove it. + for(int i=0; i < this->NumberOfInformationObjects; ++i) + { + if(this->Internal->Vector[i] == info) + { + this->Internal->Vector.erase(this->Internal->Vector.begin()+i); + info->UnRegister(this); + this->NumberOfInformationObjects--; + } + } +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::Copy(vtkInformationVector* from, int deep) +{ + // if deep we can reuse existing info objects + if (deep) + { + this->SetNumberOfInformationObjects(from->GetNumberOfInformationObjects()); + for (int i = 0; i < from->GetNumberOfInformationObjects(); ++i) + { + this->Internal->Vector[i]->Copy(from->GetInformationObject(i),deep); + } + return; + } + + // otherwise it is a shallow copy and we must copy pointers + this->SetNumberOfInformationObjects(0); + // copy the data + for (int i = 0; i < from->GetNumberOfInformationObjects(); ++i) + { + vtkInformation *fromI = from->GetInformationObject(i); + this->SetInformationObject(i,fromI); + } +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkInformationVector::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + for(int i=0; i < this->NumberOfInformationObjects; ++i) + { + vtkGarbageCollectorReport(collector, this->Internal->Vector[i], "Entry"); + } +} diff --git a/Filtering/vtkInformationVector.h b/Filtering/vtkInformationVector.h new file mode 100644 index 0000000..13a483d --- /dev/null +++ b/Filtering/vtkInformationVector.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInformationVector.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInformationVector - Store zero or more vtkInformation instances. +// .SECTION Description + +// vtkInformationVector stores a vector of zero or more vtkInformation +// objects corresponding to the input or output information for a +// vtkAlgorithm. An instance of this class is passed to +// vtkAlgorithm::ProcessRequest calls. + +#ifndef __vtkInformationVector_h +#define __vtkInformationVector_h + +#include "vtkObject.h" + +class vtkInformation; +class vtkInformationVectorInternals; + +class VTK_FILTERING_EXPORT vtkInformationVector : public vtkObject +{ +public: + static vtkInformationVector *New(); + vtkTypeRevisionMacro(vtkInformationVector,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get/Set the number of information objects in the vector. Setting + // the number to larger than the current number will create empty + // vtkInformation instances. Setting the number to smaller than the + // current number will remove entries from higher indices. + int GetNumberOfInformationObjects() { return this->NumberOfInformationObjects; }; + void SetNumberOfInformationObjects(int n); + + // Description: + // Get/Set the vtkInformation instance stored at the given index in + // the vector. The vector will automatically expand to include the + // index given if necessary. Missing entries in-between will be + // filled with empty vtkInformation instances. + void SetInformationObject(int index, vtkInformation* info); + vtkInformation* GetInformationObject(int index); + + // Description: + // Append/Remove an information object. + void Append(vtkInformation* info); + void Remove(vtkInformation* info); + + // Description: + // Initiate garbage collection when a reference is removed. + virtual void Register(vtkObjectBase* o); + virtual void UnRegister(vtkObjectBase* o); + + // Description: + // Copy all information entries from the given vtkInformation + // instance. Any previously existing entries are removed. If + // deep==1, a deep copy of the information structure is performed (new + // instances of any contained vtkInformation and vtkInformationVector + // objects are created). + void Copy(vtkInformationVector* from, int deep=0); + +protected: + vtkInformationVector(); + ~vtkInformationVector(); + + // Internal implementation details. + vtkInformationVectorInternals* Internal; + + int NumberOfInformationObjects; + + // Garbage collection support. + virtual void ReportReferences(vtkGarbageCollector*); +private: + vtkInformationVector(const vtkInformationVector&); // Not implemented. + void operator=(const vtkInformationVector&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkInterpolatedVelocityField.cxx b/Filtering/vtkInterpolatedVelocityField.cxx new file mode 100644 index 0000000..d32be1c --- /dev/null +++ b/Filtering/vtkInterpolatedVelocityField.cxx @@ -0,0 +1,315 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInterpolatedVelocityField.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInterpolatedVelocityField.h" + +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkGenericCell.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkInterpolatedVelocityField, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkInterpolatedVelocityField); + +typedef vtkstd::vector< vtkDataSet* > DataSetsTypeBase; +class vtkInterpolatedVelocityFieldDataSetsType: public DataSetsTypeBase {}; + +vtkInterpolatedVelocityField::vtkInterpolatedVelocityField() +{ + this->NumFuncs = 3; // u, v, w + this->NumIndepVars = 4; // x, y, z, t + this->Weights = 0; + this->WeightsSize = 0; + this->GenCell = vtkGenericCell::New(); + this->LastCellId = -1; + this->CacheHit = 0; + this->CacheMiss = 0; + this->Caching = 1; // Caching on by default + + this->Cell = vtkGenericCell::New(); + this->VectorsSelection = 0; + + this->DataSets = new vtkInterpolatedVelocityFieldDataSetsType; + this->LastDataSet = 0; +} + +vtkInterpolatedVelocityField::~vtkInterpolatedVelocityField() +{ + this->NumFuncs = 0; + this->NumIndepVars = 0; + this->GenCell->Delete(); + delete[] this->Weights; + this->Weights = 0; + + this->Cell->Delete(); + this->SetVectorsSelection(0); + + delete this->DataSets; +} + +static int tmp_count=0; +// Evaluate u,v,w at x,y,z,t +int vtkInterpolatedVelocityField::FunctionValues(double* x, double* f) +{ + vtkDataSet* ds; + if(!this->LastDataSet && !this->DataSets->empty()) + { + ds = (*this->DataSets)[0]; + this->LastDataSet = ds; + } + else + { + ds = this->LastDataSet; + } + int retVal = this->FunctionValues(ds, x, f); + if (!retVal) + { + tmp_count = 0; + for(DataSetsTypeBase::iterator i = this->DataSets->begin(); + i != this->DataSets->end(); ++i) + { + ds = *i; + if(ds && ds != this->LastDataSet) + { + this->ClearLastCellId(); + retVal = this->FunctionValues(ds, x, f); + if (retVal) + { + this->LastDataSet = ds; + return retVal; + } + } + } + this->ClearLastCellId(); + return 0; + } + tmp_count++; + return retVal; +} + +const double vtkInterpolatedVelocityField::TOLERANCE_SCALE = 1.0E-8; + +// Evaluate u,v,w at x,y,z,t +int vtkInterpolatedVelocityField::FunctionValues(vtkDataSet* dataset, + double* x, + double* f) +{ + int i, j, subId , numPts, id; + vtkDataArray* vectors; + double vec[3]; + double dist2; + int ret; + + for(i=0; i<3; i++) + { + f[i] = 0; + } + + // See if a dataset has been specified and if there are input vectors + if (!dataset || + !(vectors = dataset->GetPointData()->GetVectors(this->VectorsSelection))) + { + vtkErrorMacro(<<"Can't evaluate dataset!"); + return 0; + } + + double tol2 = + dataset->GetLength() * vtkInterpolatedVelocityField::TOLERANCE_SCALE; + + int found = 0; + + if (this->Caching) + { + // See if the point is in the cached cell + if (this->LastCellId == -1 || + !(ret=this->GenCell->EvaluatePosition(x, 0, subId, + this->LastPCoords, dist2, + this->Weights)) + || ret == -1) + { + // if not, find and get it + if (this->LastCellId != - 1 ) + { + this->CacheMiss++; + + dataset->GetCell(this->LastCellId, this->Cell); + + this->LastCellId = + dataset->FindCell(x, this->Cell, this->GenCell, -1, tol2, + subId, this->LastPCoords, this->Weights); + if (this->LastCellId != - 1) + { + dataset->GetCell(this->LastCellId, this->GenCell); + found = 1; + } + } + } + else + { + this->CacheHit++; + found = 1; + } + } + + if (!found) + { + // if the cell is not found, do a global search (ignore initial + // cell if there is one) + this->LastCellId = + dataset->FindCell(x, 0, this->GenCell, -1, tol2, + subId, this->LastPCoords, this->Weights); + if (this->LastCellId != - 1) + { + dataset->GetCell(this->LastCellId, this->GenCell); + } + else + { + return 0; + } + } + + // if the cell is valid + if (this->LastCellId >= 0) + { + numPts = this->GenCell->GetNumberOfPoints(); + // interpolate the vectors + for (j=0; j < numPts; j++) + { + id = this->GenCell->PointIds->GetId(j); + vectors->GetTuple(id, vec); + for (i=0; i < 3; i++) + { + f[i] += vec[i] * this->Weights[j]; + } + } + } + // if not, return false + else + { + return 0; + } + + return 1; +} + +void vtkInterpolatedVelocityField::AddDataSet(vtkDataSet* dataset) +{ + if (!dataset) + { + return; + } + + this->DataSets->push_back(dataset); + + int size = dataset->GetMaxCellSize(); + if (size > this->WeightsSize) + { + this->WeightsSize = size; + delete[] this->Weights; + this->Weights = new double[size]; + } +} + +int vtkInterpolatedVelocityField::GetLastWeights(double* w) +{ + int j, numPts; + + // If last cell is valid, fill w with the interpolation weights + // and return true + if (this->LastCellId >= 0) + { + numPts = this->GenCell->GetNumberOfPoints(); + for (j=0; j < numPts; j++) + { + w[j] = this->Weights[j]; + } + return 1; + } + // otherwise, return false + else + { + return 0; + } +} + +int vtkInterpolatedVelocityField::GetLastLocalCoordinates(double pcoords[3]) +{ + int j; + + // If last cell is valid, fill p with the local coordinates + // and return true + if (this->LastCellId >= 0) + { + for (j=0; j < 3; j++) + { + pcoords[j] = this->LastPCoords[j]; + } + return 1; + } + // otherwise, return false + else + { + return 0; + } +} + +void vtkInterpolatedVelocityField::CopyParameters( + vtkInterpolatedVelocityField* from) +{ + this->Caching = from->Caching; +} + +void vtkInterpolatedVelocityField::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if ( this->VectorsSelection ) + { + os << indent << "VectorsSelection: " << this->VectorsSelection << endl; + } + else + { + os << indent << "VectorsSelection: (none)" << endl; + } + if ( this->GenCell ) + { + os << indent << "Last cell: " << this->GenCell << endl; + } + else + { + os << indent << "Last cell: (none)" << endl; + } + os << indent << "Weights: " << this->Weights << endl; + os << indent << "Last cell Id: " << this->LastCellId << endl; + os << indent << "Cache hit: " << this->CacheHit << endl; + os << indent << "Cache miss: " << this->CacheMiss << endl; + os << indent << "Caching: "; + if ( this->Caching ) + { + os << "on." << endl; + } + else + { + os << "off." << endl; + } + + os << indent << "VectorsSelection: " + << (this->VectorsSelection?this->VectorsSelection:"(none)") << endl; + os << indent << "LastDataSet : " + << this->LastDataSet << endl; + +} + diff --git a/Filtering/vtkInterpolatedVelocityField.h b/Filtering/vtkInterpolatedVelocityField.h new file mode 100644 index 0000000..f5f22bb --- /dev/null +++ b/Filtering/vtkInterpolatedVelocityField.h @@ -0,0 +1,159 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInterpolatedVelocityField.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInterpolatedVelocityField - Interface for obtaining +// interpolated velocity values +// .SECTION Description +// vtkInterpolatedVelocityField acts as a continuous velocity field +// by performing cell interpolation on the underlying vtkDataSet. +// This is a concrete sub-class of vtkFunctionSet with +// NumberOfIndependentVariables = 4 (x,y,z,t) and +// NumberOfFunctions = 3 (u,v,w). Normally, every time an evaluation +// is performed, the cell which contains the point (x,y,z) has to +// be found by calling FindCell. This is a computationally expansive +// operation. In certain cases, the cell search can be avoided or shortened +// by providing a guess for the cell id. For example, in streamline +// integration, the next evaluation is usually in the same or a neighbour +// cell. For this reason, vtkInterpolatedVelocityField stores the last +// cell id. If caching is turned on, it uses this id as the starting point. + +// .SECTION Caveats +// vtkInterpolatedVelocityField is not thread safe. A new instance should +// be created by each thread. + +// .SECTION See Also +// vtkFunctionSet vtkStreamer + +#ifndef __vtkInterpolatedVelocityField_h +#define __vtkInterpolatedVelocityField_h + +#include "vtkFunctionSet.h" + +class vtkDataSet; +class vtkGenericCell; + +class vtkInterpolatedVelocityFieldDataSetsType; + +class VTK_FILTERING_EXPORT vtkInterpolatedVelocityField : public vtkFunctionSet +{ +public: + vtkTypeRevisionMacro(vtkInterpolatedVelocityField,vtkFunctionSet); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a vtkInterpolatedVelocityField with no initial data set. + // Caching is on. LastCellId is set to -1. + static vtkInterpolatedVelocityField *New(); + + // Description: + // Evaluate the velocity field, f, at (x, y, z, t). + // For now, t is ignored. + virtual int FunctionValues(double* x, double* f); + + // Description: + // Add a dataset used for the implicit function evaluation. + // If more than one dataset is added, the evaluation point is + // searched in all until a match is found. THIS FUNCTION + // DOES NOT CHANGE THE REFERENCE COUNT OF dataset FOR THREAD + // SAFETY REASONS. + virtual void AddDataSet(vtkDataSet* dataset); + + // Description: + // Return the cell id cached from last evaluation. + vtkGetMacro(LastCellId, vtkIdType); + vtkSetMacro(LastCellId, vtkIdType); + + // Description: + // Set the last cell id to -1 so that the next search does not + // start from the previous cell + void ClearLastCellId() { this->LastCellId = -1; } + + // Description: + // Returns the interpolation weights cached from last evaluation + // if the cached cell is valid (returns 1). Otherwise, it does not + // change w and returns 0. + int GetLastWeights(double* w); + int GetLastLocalCoordinates(double pcoords[3]); + + // Description: + // Turn caching on/off. + vtkGetMacro(Caching, int); + vtkSetMacro(Caching, int); + vtkBooleanMacro(Caching, int); + + // Description: + // Caching statistics. + vtkGetMacro(CacheHit, int); + vtkGetMacro(CacheMiss, int); + + // Description: + // If you want to work with an arbitrary vector array, then set its name + // here. By default this in NULL and the filter will use the active vector + // array. + vtkGetStringMacro(VectorsSelection); + void SelectVectors(const char *fieldName) + {this->SetVectorsSelection(fieldName);} + + // Description: + // Returns the last dataset that was visited. Can be used + // as a first guess as to where the next point will be as + // well as to avoid searching through all datasets to get + // more information about the point. + vtkGetObjectMacro(LastDataSet, vtkDataSet); + + // Description: + // Copy the user set parameters from source. This copies + // the Caching parameters. Sub-classes can add more after + // chaining. + virtual void CopyParameters(vtkInterpolatedVelocityField* from); + +protected: + vtkInterpolatedVelocityField(); + ~vtkInterpolatedVelocityField(); + + vtkGenericCell* GenCell; // last cell + vtkGenericCell* Cell; + double* Weights; // last weights + int WeightsSize; + double LastPCoords[3]; // last local coordinates + vtkIdType LastCellId; + int CacheHit; + int CacheMiss; + int Caching; + + vtkDataSet* LastDataSet; + + vtkSetStringMacro(VectorsSelection); + char *VectorsSelection; + + vtkInterpolatedVelocityFieldDataSetsType* DataSets; + + int FunctionValues(vtkDataSet* ds, double* x, double* f); + + static const double TOLERANCE_SCALE; + +private: + vtkInterpolatedVelocityField(const vtkInterpolatedVelocityField&); // Not implemented. + void operator=(const vtkInterpolatedVelocityField&); // Not implemented. +}; + +#endif + + + + + + + + diff --git a/Filtering/vtkKochanekSpline.cxx b/Filtering/vtkKochanekSpline.cxx new file mode 100644 index 0000000..1948384 --- /dev/null +++ b/Filtering/vtkKochanekSpline.cxx @@ -0,0 +1,406 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkKochanekSpline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkKochanekSpline.h" + +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" + +vtkCxxRevisionMacro(vtkKochanekSpline, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkKochanekSpline); + +//---------------------------------------------------------------------------- +// Construct a KochanekSpline wth the following defaults: +// DefaultBias = 0, +// DefaultTension = 0, +// DefaultContinuity = 0. +vtkKochanekSpline::vtkKochanekSpline () +{ + this->DefaultBias = 0.0; + this->DefaultTension = 0.0; + this->DefaultContinuity = 0.0; +} + +//---------------------------------------------------------------------------- +// Evaluate a 1D Spline +double vtkKochanekSpline::Evaluate (double t) +{ + int index = 0; + double *intervals; + double *coefficients; + + // check to see if we need to recompute the spline + if (this->ComputeTime < this->GetMTime ()) + { + this->Compute (); + } + + // make sure we have at least 2 points + int size = this->PiecewiseFunction->GetSize (); + if (size < 2) + { + return 0.0; + } + + intervals = this->Intervals; + coefficients = this->Coefficients; + + if ( this->Closed ) + { + size = size + 1; + } + + // clamp the function at both ends + if (t < intervals[0]) + { + t = intervals[0]; + } + if (t > intervals[size - 1]) + { + t = intervals[size - 1]; + } + + // find pointer to cubic spline coefficient + index = this->FindIndex(size,t); + + // calculate offset within interval + t = (t - intervals[index]) / (intervals[index+1] - intervals[index]); + + // evaluate y + return (t * (t * (t * *(coefficients + index * 4 + 3) + + *(coefficients + index * 4 + 2)) + + *(coefficients + index * 4 + 1)) + + *(coefficients + index * 4)); +} + +//---------------------------------------------------------------------------- +// Compute Kochanek Spline coefficients. +void vtkKochanekSpline::Compute () +{ + double *ts, *xs; + double *coefficients; + double *dependent; + int size; + int i; + + // Make sure the function is up to date. + this->PiecewiseFunction->Update(); + + // get the size of the independent variables + size = this->PiecewiseFunction->GetSize (); + + if(size < 2) + { + vtkErrorMacro("Spline requires at least 2 points. # of points is: " <Closed ) + { + // copy the independent variables + if (this->Intervals) + { + delete [] this->Intervals; + } + this->Intervals = new double[size]; + ts = this->PiecewiseFunction->GetDataPointer (); + for (i = 0; i < size; i++) + { + this->Intervals[i] = *(ts + 2*i); + } + + // allocate memory for coefficients + if (this->Coefficients) + { + delete [] this->Coefficients; + } + this->Coefficients = new double [4*size]; + + // allocate memory for dependent variables + dependent = new double [size]; + + // get start of coefficients for this dependent variable + coefficients = this->Coefficients; + + // get the dependent variable values + xs = this->PiecewiseFunction->GetDataPointer () + 1; + for (int j = 0; j < size; j++) + { + *(dependent + j) = *(xs + 2*j); + } + } + else //spline is closed, create extra "fictitious" point + { + size = size + 1; + // copy the independent variables + if (this->Intervals) + { + delete [] this->Intervals; + } + this->Intervals = new double[size]; + ts = this->PiecewiseFunction->GetDataPointer (); + for (i = 0; i < size-1; i++) + { + this->Intervals[i] = *(ts + 2 * i); + } + if ( this->ParametricRange[0] != this->ParametricRange[1] ) + { + this->Intervals[size-1] = this->ParametricRange[1]; + } + else + { + this->Intervals[size-1] = this->Intervals[size-2] + 1.0; + } + + // allocate memory for coefficients + if (this->Coefficients) + { + delete [] this->Coefficients; + } + this->Coefficients = new double [4 * size]; + + // allocate memory for dependent variables + dependent = new double [size]; + + // get start of coefficients for this dependent variable + coefficients = this->Coefficients; + + // get the dependent variable values + xs = this->PiecewiseFunction->GetDataPointer () + 1; + for (int j = 0; j < size-1; j++) + { + *(dependent + j) = *(xs + 2*j); + } + dependent[size-1] = *xs; + } + + this->Fit1D (size, this->Intervals, dependent, + this->DefaultTension, + this->DefaultBias, + this->DefaultContinuity, + (double (*)[4])coefficients, + this->LeftConstraint, this->LeftValue, + this->RightConstraint, this->RightValue); + + // free the dependent variable storage + delete [] dependent; + + // update compute time + this->ComputeTime = this->GetMTime(); +} + +#define VTK_EPSILON .0001 + +//---------------------------------------------------------------------------- +// Compute the coefficients for a 1D spline +void vtkKochanekSpline::Fit1D (int size, double *x, double *y, + double tension, double bias, double continuity, + double coefficients[][4], + int leftConstraint, double leftValue, + int rightConstraint, double rightValue) +{ + double cs; /* source chord */ + double cd; /* destination chord */ + double ds; /* source deriviative */ + double dd; /* destination deriviative */ + double n0, n1; /* number of frames btwn nodes */ + int N; /* top point number */ + int i; + + if (size == 2) + { + // two points, set coefficients for a straight line + coefficients[0][3] = 0.0; + coefficients[1][3] = 0.0; + coefficients[0][2] = 0.0; + coefficients[1][2] = 0.0; + coefficients[0][1] = (y[1] - y[0]) / (x[1] - x[0]); + coefficients[1][1] = coefficients[0][1]; + coefficients[0][0] = y[0]; + coefficients[1][0] = y[1]; + return; + } + + N = size - 1; + + for (i=1; i < N; i++) + { + cs = y[i] - y[i-1]; + cd = y[i+1] - y[i]; + + ds = cs*((1 - tension)*(1 - continuity)*(1 + bias)) / 2.0 + + cd*((1 - tension)*(1 + continuity)*(1 - bias)) / 2.0; + + dd = cs*((1 - tension)*(1 + continuity)*(1 + bias)) / 2.0 + + cd*((1 - tension)*(1 - continuity)*(1 - bias)) / 2.0; + + // adjust deriviatives for non uniform spacing between nodes + n1 = x[i+1] - x[i]; + n0 = x[i] - x[i-1]; + + ds *= (2 * n0 / (n0 + n1)); + dd *= (2 * n1 / (n0 + n1)); + + coefficients[i][0] = y[i]; + coefficients[i][1] = dd; + coefficients[i][2] = ds; + } + + // Calculate the deriviatives at the end points + coefficients[0][0] = y[0]; + coefficients[N][0] = y[N]; + + if ( this->Closed ) //the curve is continuous and closed at P0=Pn + { + cs = y[N] - y[N-1]; + cd = y[1] - y[0]; + + ds = cs*((1 - tension)*(1 - continuity)*(1 + bias)) / 2.0 + + cd*((1 - tension)*(1 + continuity)*(1 - bias)) / 2.0; + + dd = cs*((1 - tension)*(1 + continuity)*(1 + bias)) / 2.0 + + cd*((1 - tension)*(1 - continuity)*(1 - bias)) / 2.0; + + // adjust deriviatives for non uniform spacing between nodes + n1 = x[1] - x[0]; + n0 = x[N] - x[N-1]; + ds *= (2 * n1 / (n0 + n1)); + dd *= (2 * n0 / (n0 + n1)); + + coefficients[0][1] = dd; + coefficients[0][2] = ds; + coefficients[N][1] = dd; + coefficients[N][2] = ds; + } + else //curve is open + { + switch (leftConstraint) + { + case 0: + // desired slope at leftmost point is leftValue + coefficients[0][1] = this->ComputeLeftDerivative(); + break; + + case 1: + // desired slope at leftmost point is leftValue + coefficients[0][1] = leftValue; + break; + + case 2: + // desired second derivative at leftmost point is leftValue + coefficients[0][1] = (6*(y[1] - y[0]) - 2*coefficients[1][2] - leftValue) + / 4.0; + break; + + case 3: + // desired secord derivative at leftmost point is leftValue + // times secod derivative at first interior point + if ((leftValue > (-2.0 + VTK_EPSILON)) || + (leftValue < (-2.0 - VTK_EPSILON))) + { + coefficients[0][1] = (3*(1 + leftValue)*(y[1] - y[0]) - + (1 + 2*leftValue)*coefficients[1][2]) + / (2 + leftValue); + } + else + { + coefficients[0][1] = 0.0; + } + break; + } + + switch (rightConstraint) + { + case 0: + // desired slope at rightmost point is rightValue + coefficients[N][2] = this->ComputeRightDerivative(); + break; + + case 1: + // desired slope at rightmost point is rightValue + coefficients[N][2] = rightValue; + break; + + case 2: + // desired second derivative at rightmost point is rightValue + coefficients[N][2] = (6*(y[N] - y[N-1]) - 2*coefficients[N-1][1] + + rightValue) / 4.0; + break; + + case 3: + // desired secord derivative at rightmost point is rightValue + // times secord derivative at last interior point + if ((rightValue > (-2.0 + VTK_EPSILON)) || + (rightValue < (-2.0 - VTK_EPSILON))) + { + coefficients[N][2] = (3*(1 + rightValue)*(y[N] - y[N-1]) - + (1 + 2*rightValue)*coefficients[N-1][1]) + / (2 + rightValue); + } + else + { + coefficients[N][2] = 0.0; + } + break; + } + }//curve is open + + // Compute the Coefficients + for (i=0; i < N; i++) + { + // + // c0 = P ; c1 = DD ; + // i i i i + // + // c1 = P ; c2 = DS ; + // i+1 i+1 i+1 i+1 + // + // c2 = -3P + 3P - 2DD - DS ; + // i i i+1 i i+1 + // + // c3 = 2P - 2P + DD + DS ; + // i i i+1 i i+1 + // + coefficients[i][2] = (-3 * y[i]) + ( 3 * y[i+1]) + + (-2 * coefficients[i][1]) + (-1 * coefficients[i+1][2]); + coefficients[i][3] = ( 2 * y[i]) + (-2 * y[i+1]) + + ( 1 * coefficients[i][1]) + ( 1 * coefficients[i+1][2]); + } +} + +//---------------------------------------------------------------------------- +void vtkKochanekSpline::DeepCopy(vtkSpline *s) +{ + vtkKochanekSpline *spline = vtkKochanekSpline::SafeDownCast(s); + + if ( spline != NULL ) + { + this->DefaultBias = spline->DefaultBias; + this->DefaultTension = spline->DefaultTension; + this->DefaultContinuity = spline->DefaultContinuity; + } + + // Now do superclass + this->vtkSpline::DeepCopy(s); +} + +//---------------------------------------------------------------------------- +void vtkKochanekSpline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "DefaultBias: " << this->DefaultBias << "\n"; + os << indent << "DefaultTension: " << this->DefaultTension << "\n"; + os << indent << "DefaultContinuity: " << this->DefaultContinuity << "\n"; +} + diff --git a/Filtering/vtkKochanekSpline.h b/Filtering/vtkKochanekSpline.h new file mode 100644 index 0000000..6143503 --- /dev/null +++ b/Filtering/vtkKochanekSpline.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkKochanekSpline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkKochanekSpline - computes an interpolating spline using a Kochanek basis. +// .SECTION Description +// Implements the Kochenek interpolating spline described in: Kochanek, D., +// Bartels, R., "Interpolating Splines with Local Tension, Continuity, and +// Bias Control," Computer Graphics, vol. 18, no. 3, pp. 33-41, July 1984. +// These splines give the user more control over the shape of the curve than +// the cardinal splines implemented in vtkCardinalSpline. Three parameters +// can be specified. All have a range from -1 to 1. +// +// Tension controls how sharply the curve bends at an input point. A +// value of -1 produces more slack in the curve. A value of 1 tightens +// the curve. +// +// Continuity controls the continuity of the first derivative at input +// points. +// +// Bias controls the direction of the curve at it passes through an input +// point. A value of -1 undershoots the point while a value of 1 +// overshoots the point. +// +// These three parameters give the user broad control over the shape of +// the interpolating spline. The original Kochanek paper describes the +// effects nicely and is recommended reading. + +// .SECTION See Also +// vtkSpline vtkCardinalSpline + + +#ifndef __vtkKochanekSpline_h +#define __vtkKochanekSpline_h + +#include "vtkSpline.h" + +class VTK_FILTERING_EXPORT vtkKochanekSpline : public vtkSpline +{ +public: + vtkTypeRevisionMacro(vtkKochanekSpline,vtkSpline); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a KochanekSpline with the following defaults: DefaultBias = 0, + // DefaultTension = 0, DefaultContinuity = 0. + static vtkKochanekSpline *New(); + + // Description: + // Compute Kochanek Spline coefficients. + void Compute (); + + // Description: + // Evaluate a 1D Kochanek spline. + double Evaluate (double t); + + // Description: + // Set the bias for all points. Default is 0. + vtkSetMacro(DefaultBias,double); + vtkGetMacro(DefaultBias,double); + + // Description: + // Set the tension for all points. Default is 0. + vtkSetMacro(DefaultTension,double); + vtkGetMacro(DefaultTension,double); + + // Description: + // Set the continuity for all points. Default is 0. + vtkSetMacro(DefaultContinuity,double); + vtkGetMacro(DefaultContinuity,double); + + // Description: + // Deep copy of cardinal spline data. + virtual void DeepCopy(vtkSpline *s); + +protected: + vtkKochanekSpline(); + ~vtkKochanekSpline() {} + + void Fit1D (int n, double *x, double *y, double tension, double bias, + double continuity, double coefficients[][4], int leftConstraint, + double leftValue, int rightConstraint, double rightValue); + + double DefaultBias; + double DefaultTension; + double DefaultContinuity; + +private: + vtkKochanekSpline(const vtkKochanekSpline&); // Not implemented. + void operator=(const vtkKochanekSpline&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkLine.cxx b/Filtering/vtkLine.cxx new file mode 100644 index 0000000..23cfd59 --- /dev/null +++ b/Filtering/vtkLine.cxx @@ -0,0 +1,607 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLine.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLine.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkLine, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkLine); + +//---------------------------------------------------------------------------- +// Construct the line with two points. +vtkLine::vtkLine() +{ + this->Points->SetNumberOfPoints(2); + this->PointIds->SetNumberOfIds(2); + for (int i = 0; i < 2; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } +} + +//---------------------------------------------------------------------------- +static const int VTK_NO_INTERSECTION=0; +static const int VTK_YES_INTERSECTION=2; +static const int VTK_ON_LINE=3; + +int vtkLine::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + double a1[3], a2[3]; + + subId = 0; + pcoords[1] = pcoords[2] = 0.0; + + this->Points->GetPoint(0, a1); + this->Points->GetPoint(1, a2); + + if (closestPoint) + { + // DistanceToLine sets pcoords[0] to a value t, 0 <= t <= 1 + dist2 = this->DistanceToLine(x,a1,a2,pcoords[0],closestPoint); + } + + // pcoords[0] == t, need weights to be 1-t and t + weights[0] = 1.0 - pcoords[0]; + weights[1] = pcoords[0]; + + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +void vtkLine::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + int i; + double a1[3], a2[3]; + this->Points->GetPoint(0, a1); + this->Points->GetPoint(1, a2); + + for (i=0; i<3; i++) + { + x[i] = a1[i] + pcoords[0]*(a2[i] - a1[i]); + } + + weights[0] = 1.0 - pcoords[0]; + weights[1] = pcoords[0]; +} + +//---------------------------------------------------------------------------- +// Performs intersection of two finite 3D lines. An intersection is found if +// the projection of the two lines onto the plane perpendicular to the cross +// product of the two lines intersect. The parameters (u,v) are the +// parametric coordinates of the lines at the position of closest approach. +int vtkLine::Intersection (double a1[3], double a2[3], + double b1[3], double b2[3], + double& u, double& v) +{ + double a21[3], b21[3], b1a1[3]; + double c[2]; + double *A[2], row1[2], row2[2]; + + // Initialize + u = v = 0.0; + + // Determine line vectors. + a21[0] = a2[0] - a1[0]; b21[0] = b2[0] - b1[0]; b1a1[0] = b1[0] - a1[0]; + a21[1] = a2[1] - a1[1]; b21[1] = b2[1] - b1[1]; b1a1[1] = b1[1] - a1[1]; + a21[2] = a2[2] - a1[2]; b21[2] = b2[2] - b1[2]; b1a1[2] = b1[2] - a1[2]; + + // Compute the system (least squares) matrix. + A[0] = row1; + A[1] = row2; + row1[0] = vtkMath::Dot ( a21, a21 ); + row1[1] = -vtkMath::Dot ( a21, b21 ); + row2[0] = row1[1]; + row2[1] = vtkMath::Dot ( b21, b21 ); + + // Compute the least squares system constant term. + c[0] = vtkMath::Dot ( a21, b1a1 ); + c[1] = -vtkMath::Dot ( b21, b1a1 ); + + + // Solve the system of equations + if ( vtkMath::SolveLinearSystem(A,c,2) == 0 ) + { + return VTK_ON_LINE; + } + else + { + u = c[0]; + v = c[1]; + } + + // Check parametric coordinates for intersection. + if ( (0.0 <= u) && (u <= 1.0) && (0.0 <= v) && (v <= 1.0) ) + { + return VTK_YES_INTERSECTION; + } + else + { + return VTK_NO_INTERSECTION; + } +} + +//---------------------------------------------------------------------------- +int vtkLine::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + pts->SetNumberOfIds(1); + + if ( pcoords[0] >= 0.5 ) + { + pts->SetId(0,this->PointIds->GetId(1)); + if ( pcoords[0] > 1.0 ) + { + return 0; + } + else + { + return 1; + } + } + else + { + pts->SetId(0,this->PointIds->GetId(0)); + if ( pcoords[0] < 0.0 ) + { + return 0; + } + else + { + return 1; + } + } +} + +//---------------------------------------------------------------------------- +// +// marching lines case table +// +typedef int VERT_LIST; + +typedef struct { + VERT_LIST verts[2]; +} VERT_CASES; + +static VERT_CASES vertCases[4]= { + {{-1,-1}}, + {{1,0}}, + {{0,1}}, + {{-1,-1}}}; + +//---------------------------------------------------------------------------- +void vtkLine::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *vtkNotUsed(lines), + vtkCellArray *vtkNotUsed(polys), + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + static int CASE_MASK[2] = {1,2}; + int index, i, newCellId; + VERT_CASES *vertCase; + VERT_LIST *vert; + double t, x[3], x1[3], x2[3]; + vtkIdType pts[1]; + + // + // Build the case table + // + for ( i=0, index = 0; i < 2; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + vertCase = vertCases + index; + vert = vertCase->verts; + + if ( vert[0] > -1 ) + { + t = (value - cellScalars->GetComponent(vert[0],0)) / + (cellScalars->GetComponent(vert[1],0) - + cellScalars->GetComponent(vert[0],0)); + this->Points->GetPoint(vert[0], x1); + this->Points->GetPoint(vert[1], x2); + for (i=0; i<3; i++) + { + x[i] = x1[i] + t * (x2[i] - x1[i]); + } + + if ( locator->InsertUniquePoint(x, pts[0]) ) + { + if ( outPd ) + { + vtkIdType p1 = this->PointIds->GetId(vert[0]); + vtkIdType p2 = this->PointIds->GetId(vert[1]); + outPd->InterpolateEdge(inPd,pts[0],p1,p2,t); + } + } + newCellId = verts->InsertNextCell(1,pts); + outCd->CopyData(inCd,cellId,newCellId); + } +} + +//---------------------------------------------------------------------------- +// Compute distance to finite line. Returns parametric coordinate t +// and point location on line. +double vtkLine::DistanceToLine(double x[3], double p1[3], double p2[3], + double &t, double closestPoint[3]) +{ + double p21[3], denom, num; + double *closest; + double tolerance; + // + // Determine appropriate vectors + // + p21[0] = p2[0]- p1[0]; + p21[1] = p2[1]- p1[1]; + p21[2] = p2[2]- p1[2]; + + // + // Get parametric location + // + num = p21[0]*(x[0]-p1[0]) + p21[1]*(x[1]-p1[1]) + p21[2]*(x[2]-p1[2]); + denom = vtkMath::Dot(p21,p21); + + // trying to avoid an expensive fabs + tolerance = VTK_TOL*num; + if (tolerance < 0.0) + { + tolerance = -tolerance; + } + if ( -tolerance < denom && denom < tolerance ) //numerically bad! + { + closest = p1; //arbitrary, point is (numerically) far away + } + // + // If parametric coordinate is within 0<=p<=1, then the point is closest to + // the line. Otherwise, it's closest to a point at the end of the line. + // + else if ( (t=num/denom) < 0.0 ) + { + closest = p1; + } + else if ( t > 1.0 ) + { + closest = p2; + } + else + { + closest = p21; + p21[0] = p1[0] + t*p21[0]; + p21[1] = p1[1] + t*p21[1]; + p21[2] = p1[2] + t*p21[2]; + } + + closestPoint[0] = closest[0]; + closestPoint[1] = closest[1]; + closestPoint[2] = closest[2]; + return vtkMath::Distance2BetweenPoints(closest,x); +} + +//---------------------------------------------------------------------------- +// +// Determine the distance of the current vertex to the edge defined by +// the vertices provided. Returns distance squared. Note: line is assumed +// infinite in extent. +// +double vtkLine::DistanceToLine (double x[3], double p1[3], double p2[3]) +{ + int i; + double np1[3], p1p2[3], proj, den; + + for (i=0; i<3; i++) + { + np1[i] = x[i] - p1[i]; + p1p2[i] = p1[i] - p2[i]; + } + + if ( (den=vtkMath::Norm(p1p2)) != 0.0 ) + { + for (i=0; i<3; i++) + { + p1p2[i] /= den; + } + } + else + { + return vtkMath::Dot(np1,np1); + } + + proj = vtkMath::Dot(np1,p1p2); + + return (vtkMath::Dot(np1,np1) - proj*proj); +} + +//---------------------------------------------------------------------------- +// Line-line intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. +int vtkLine::IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId) +{ + double a1[3], a2[3]; + double projXYZ[3]; + int i; + + subId = 0; + pcoords[1] = pcoords[2] = 0.0; + + this->Points->GetPoint(0, a1); + this->Points->GetPoint(1, a2); + + if ( this->Intersection(p1, p2, a1, a2, t, pcoords[0]) == + VTK_YES_INTERSECTION ) + { + // make sure we are within tolerance + for (i=0; i<3; i++) + { + x[i] = a1[i] + pcoords[0]*(a2[i]-a1[i]); + projXYZ[i] = p1[i] + t*(p2[i]-p1[i]); + } + if ( vtkMath::Distance2BetweenPoints(x,projXYZ) <= tol*tol ) + { + return 1; + } + else + { + return 0; + } + } + + else //check to see if it lies within tolerance + { + // one of the parametric coords must be outside 0-1 + if (t < 0.0) + { + t = 0.0; + if (vtkLine::DistanceToLine(p1,a1,a2,pcoords[0],x) <= tol*tol) + { + return 1; + } + else + { + return 0; + } + } + if (t > 1.0) + { + t = 1.0; + if (vtkLine::DistanceToLine(p2,a1,a2,pcoords[0],x) <= tol*tol) + { + return 1; + } + else + { + return 0; + } + } + if (pcoords[0] < 0.0) + { + pcoords[0] = 0.0; + if (vtkLine::DistanceToLine(a1,p1,p2,t,x) <= tol*tol) + { + return 1; + } + else + { + return 0; + } + } + if (pcoords[0] > 1.0) + { + pcoords[0] = 1.0; + if (vtkLine::DistanceToLine(a2,p1,p2,t,x) <= tol*tol) + { + return 1; + } + else + { + return 0; + } + } + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkLine::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + ptIds->InsertId(0,this->PointIds->GetId(0)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + + ptIds->InsertId(1,this->PointIds->GetId(1)); + pts->InsertPoint(1,this->Points->GetPoint(1)); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkLine::Derivatives(int vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], + double *values, + int dim, double *derivs) +{ + double x0[3], x1[3], deltaX[3]; + int i, j; + + this->Points->GetPoint(0, x0); + this->Points->GetPoint(1, x1); + + for (i=0; i<3; i++) + { + deltaX[i] = x1[i] - x0[i]; + } + for (i=0; iGetComponent(i,0) <= value) + { + index |= CASE_MASK[i]; + } + } + } + else + { + for ( i=0, index = 0; i < 2; i++) + { + if (cellScalars->GetComponent(i,0) > value) + { + index |= CASE_MASK[i]; + } + } + } + + // Select the case based on the index and get the list of lines for this case + lineCase = lineCases + index; + vert = lineCase->lines; + + // generate clipped line + if ( vert[0] > -1 ) + { + for (i=0; i<2; i++) // insert line + { + // vertex exists, and need not be interpolated + if (vert[i] >= 100) + { + vertexId = vert[i] - 100; + this->Points->GetPoint(vertexId, x); + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + outPd->CopyData(inPd,this->PointIds->GetId(vertexId),pts[i]); + } + } + + else //new vertex, interpolate + { + t = (value - cellScalars->GetComponent(0,0)) / + (cellScalars->GetComponent(1,0) - cellScalars->GetComponent(0,0)); + + this->Points->GetPoint(0, x1); + this->Points->GetPoint(1, x2); + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + vtkIdType p1 = this->PointIds->GetId(0); + vtkIdType p2 = this->PointIds->GetId(1); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate lines + if ( pts[0] != pts[1] ) + { + newCellId = lines->InsertNextCell(2,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +// +// Compute interpolation functions +// +void vtkLine::InterpolationFunctions(double pcoords[3], double weights[2]) +{ + weights[0] = 1.0 - pcoords[0]; + weights[1] = pcoords[0]; +} + +//---------------------------------------------------------------------------- +static double vtkLineCellPCoords[6] = {0.0,0.0,0.0, 1.0,0.0,0.0}; +double *vtkLine::GetParametricCoords() +{ + return vtkLineCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkLine::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Filtering/vtkLine.h b/Filtering/vtkLine.h new file mode 100644 index 0000000..3777bed --- /dev/null +++ b/Filtering/vtkLine.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLine.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLine - cell represents a 1D line +// .SECTION Description +// vtkLine is a concrete implementation of vtkCell to represent a 1D line. + +#ifndef __vtkLine_h +#define __vtkLine_h + +#include "vtkCell.h" + +class VTK_FILTERING_EXPORT vtkLine : public vtkCell +{ +public: + static vtkLine *New(); + vtkTypeRevisionMacro(vtkLine,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_LINE;}; + int GetCellDimension() {return 1;}; + int GetNumberOfEdges() {return 0;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int) {return 0;}; + vtkCell *GetFace(int) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this line using scalar value provided. Like contouring, except + // that it cuts the line to produce other lines. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *lines, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Return the center of the triangle in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Line-line intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + + // Description: + // Performs intersection of two finite 3D lines. An intersection is found if + // the projection of the two lines onto the plane perpendicular to the cross + // product of the two lines intersect. The parameters (u,v) are the + // parametric coordinates of the lines at the position of closest approach. + static int Intersection(double p1[3], double p2[3], + double x1[3], double x2[3], + double& u, double& v); + + + // Description: + // Compute the distance of a point x to a finite line (p1,p2). The method + // computes the parametric coordinate t and the point location on the + // line. Note that t is unconstrained (i.e., it may lie outside the range + // [0,1]) but the closest point will lie within the finite line + // [p1,p2]. Also, the method returns the distance squared between x and the + // line (p1,p2). + static double DistanceToLine(double x[3], double p1[3], double p2[3], + double &t, double closestPoint[3]); + + + // Description: + // Determine the distance of the current vertex to the edge defined by + // the vertices provided. Returns distance squared. Note: line is assumed + // infinite in extent. + static double DistanceToLine(double x[3], double p1[3], double p2[3]); + + // Description: + // Line specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[2]); + +protected: + vtkLine(); + ~vtkLine() {}; + +private: + vtkLine(const vtkLine&); // Not implemented. + void operator=(const vtkLine&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkLine::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = 0.5; + pcoords[1] = pcoords[2] = 0.0; + return 0; +} + +#endif + + diff --git a/Filtering/vtkLocator.cxx b/Filtering/vtkLocator.cxx new file mode 100644 index 0000000..a95a7d8 --- /dev/null +++ b/Filtering/vtkLocator.cxx @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLocator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLocator.h" + +#include "vtkDataSet.h" +#include "vtkGarbageCollector.h" + +vtkCxxRevisionMacro(vtkLocator, "$Revision: 1.3 $"); + +vtkCxxSetObjectMacro(vtkLocator,DataSet,vtkDataSet); + +// Construct with automatic computation of divisions, averaging +// 25 points per bucket. +vtkLocator::vtkLocator() +{ + this->DataSet = NULL; + this->MaxLevel = 8; + this->Level = 8; + this->Tolerance = 0.001; + this->Automatic = 1; + this->RetainCellLists = 1; +} + +vtkLocator::~vtkLocator() +{ + // commented out because of compiler problems in g++ + // this->FreeSearchStructure(); + this->SetDataSet(NULL); +} + +void vtkLocator::Initialize() +{ + // free up hash table + this->FreeSearchStructure(); +} + +void vtkLocator::Update() +{ + if (!this->DataSet) + { + vtkErrorMacro(<< "Input not set!"); + return; + } + if ((this->MTime > this->BuildTime) || + (this->DataSet->GetMTime() > this->BuildTime)) + { + this->BuildLocator(); + } +} + +void vtkLocator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->DataSet ) + { + os << indent << "DataSet: " << this->DataSet << "\n"; + } + else + { + os << indent << "DataSet: (none)\n"; + } + + os << indent << "Automatic: " << (this->Automatic ? "On\n" : "Off\n"); + os << indent << "Tolerance: " << this->Tolerance << "\n" ; + os << indent << "Level: " << this->Level << "\n" ; + os << indent << "MaxLevel: " << this->MaxLevel << "\n" ; + os << indent << "Retain Cell Lists: " << (this->RetainCellLists ? "On\n" : "Off\n"); + os << indent << "Build Time: " << this->BuildTime.GetMTime() << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkLocator::Register(vtkObjectBase* o) +{ + this->RegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkLocator::UnRegister(vtkObjectBase* o) +{ + this->UnRegisterInternal(o, 1); +} + +//---------------------------------------------------------------------------- +void vtkLocator::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->DataSet, "DataSet"); +} diff --git a/Filtering/vtkLocator.h b/Filtering/vtkLocator.h new file mode 100644 index 0000000..8abe5e8 --- /dev/null +++ b/Filtering/vtkLocator.h @@ -0,0 +1,156 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLocator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLocator - abstract base class for objects that accelerate spatial searches +// .SECTION Description +// vtkLocator is an abstract base class for spatial search objects, or +// locators. The principle behind locators is that they divide 3-space into +// small pieces (or "buckets") that can be quickly found in response to +// queries like point location, line intersection, or object-object +// intersection. +// +// The purpose of this base class is to provide ivars and methods shared by +// all locators. The GenerateRepresentation() is one such interesting method. +// This method works in conjunction with vtkLocatorFilter to create polygonal +// representations for the locator. For example, if the locator is an OBB tree +// (i.e., vtkOBBTree.h), then the representation is a set of one or more +// oriented bounding boxes, depending upon the specified level. +// +// Locators typically work as follows. One or more "entities", such as +// points or cells, are inserted into the tree. These entities are associated +// with one or more buckets. Then, when performing geometric operations, the +// operations are performed first on the buckets, and then if the operation +// tests positive, then on the entities in the bucket. For example, during +// collision tests, the locators are collided first to identify intersecting +// buckets. If an intersection is found, more expensive operations are then +// carried out on the entities in the bucket. +// +// To obtain good performance, locators are often organized in a tree +// structure. In such a structure, there are frequently multiple "levels" +// corresponding to different nodes in the tree. So the word level (in the +// context of the locator) can be used to specify a particular representation +// in the tree. For example, in an octree (which is a tree with 8 children), +// level 0 is the bounding box, or root octant, and level 1 consists of its +// eight children. + +// .SECTION See Also +// vtkPointLocator vtkCellLocator vtkOBBTree vtkMergePoints + +#ifndef __vtkLocator_h +#define __vtkLocator_h + +#include "vtkObject.h" + +class vtkDataSet; +class vtkPolyData; + +class VTK_FILTERING_EXPORT vtkLocator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkLocator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Build the locator from the points/cells defining this dataset. + virtual void SetDataSet(vtkDataSet*); + vtkGetObjectMacro(DataSet,vtkDataSet); + + // Description: + // Set the maximum allowable level for the tree. If the Automatic ivar is + // off, this will be the target depth of the locator. + vtkSetClampMacro(MaxLevel,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(MaxLevel,int); + + // Description: + // Get the level of the locator (determined automatically if Automatic is + // true). The value of this ivar may change each time the locator is built. + vtkGetMacro(Level,int); + + // Description: + // Boolean controls whether locator depth/resolution of locator is computed + // automatically from average number of entities in bucket. If not set, + // there will be an explicit method to control the construction of the + // locator (found in the subclass). + vtkSetMacro(Automatic,int); + vtkGetMacro(Automatic,int); + vtkBooleanMacro(Automatic,int); + + // Description: + // Specify absolute tolerance (in world coordinates) for performing + // geometric operations. + vtkSetClampMacro(Tolerance,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Tolerance,double); + + // Description: + // Boolean controls whether to maintain list of entities in each bucket. + // Normally the lists are maintained, but if the locator is being used + // as a geometry simplification technique, there is no need to keep them. + vtkSetMacro(RetainCellLists,int); + vtkGetMacro(RetainCellLists,int); + vtkBooleanMacro(RetainCellLists,int); + + // Description: + // Cause the locator to rebuild itself if it or its input dataset has + // changed. + virtual void Update(); + + // Description: + // Initialize locator. Frees memory and resets object as appropriate. + virtual void Initialize(); + + // Description: + // Build the locator from the input dataset. + virtual void BuildLocator() = 0; + + // Description: + // Free the memory required for the spatial data structure. + virtual void FreeSearchStructure() = 0; + + // Description: + // Method to build a representation at a particular level. Note that the + // method GetLevel() returns the maximum number of levels available for + // the tree. You must provide a vtkPolyData object into which to place the + // data. + virtual void GenerateRepresentation(int level, vtkPolyData *pd) = 0; + + // Description: + // Return the time of the last data structure build. + vtkGetMacro(BuildTime, unsigned long); + + // Description: + // Handle the PointSet <-> Locator loop. + virtual void Register(vtkObjectBase *o); + virtual void UnRegister(vtkObjectBase *o); +protected: + vtkLocator(); + ~vtkLocator(); + + vtkDataSet *DataSet; + int Automatic; // boolean controls automatic subdivision (or uses user spec.) + double Tolerance; // for performing merging + int MaxLevel; + int Level; + int RetainCellLists; + + vtkTimeStamp BuildTime; // time at which locator was built + + virtual void ReportReferences(vtkGarbageCollector*); +private: + vtkLocator(const vtkLocator&); // Not implemented. + void operator=(const vtkLocator&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkMapper2D.cxx b/Filtering/vtkMapper2D.cxx new file mode 100644 index 0000000..7842b64 --- /dev/null +++ b/Filtering/vtkMapper2D.cxx @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMapper2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMapper2D.h" +#include "vtkViewport.h" +#include "vtkActor2D.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkMapper2D, "$Revision: 1.1 $"); + +void vtkMapper2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + diff --git a/Filtering/vtkMapper2D.h b/Filtering/vtkMapper2D.h new file mode 100644 index 0000000..e49dfe0 --- /dev/null +++ b/Filtering/vtkMapper2D.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMapper2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMapper2D - abstract class specifies interface for objects which render 2D actors +// .SECTION Description +// vtkMapper2D is an abstract class which defines the interface for objects +// which render two dimensional actors (vtkActor2D). + +// .SECTION See Also +// vtkActor2D + +#ifndef __vtkMapper2D_h +#define __vtkMapper2D_h + +#include "vtkAbstractMapper.h" + +class vtkViewport; +class vtkActor2D; + +class VTK_FILTERING_EXPORT vtkMapper2D : public vtkAbstractMapper +{ +public: + vtkTypeRevisionMacro(vtkMapper2D,vtkAbstractMapper); + void PrintSelf(ostream& os, vtkIndent indent); + + virtual void RenderOverlay(vtkViewport*, vtkActor2D*) {}; + virtual void RenderOpaqueGeometry(vtkViewport*, vtkActor2D*) {}; + virtual void RenderTranslucentGeometry(vtkViewport*, vtkActor2D*) {}; + +protected: + vtkMapper2D() {}; + ~vtkMapper2D() {}; + +private: + vtkMapper2D(const vtkMapper2D&); // Not implemented. + void operator=(const vtkMapper2D&); // Not implemented. +}; + +#endif + + + diff --git a/Filtering/vtkMarchingCubesCases.h b/Filtering/vtkMarchingCubesCases.h new file mode 100644 index 0000000..fe72cb6 --- /dev/null +++ b/Filtering/vtkMarchingCubesCases.h @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingCubesCases.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkMarchingCubesCases_h +#define __vtkMarchingCubesCases_h +// +// marching cubes case table for generating isosurfaces +// +typedef int EDGE_LIST; +struct VTK_FILTERING_EXPORT vtkMarchingCubesTriangleCases +{ + EDGE_LIST edges[16]; + static vtkMarchingCubesTriangleCases* GetCases(); +}; + +// +// Edges to intersect. Three at a time form a triangle. Comments at +// end of line indicate case number (0->255) and base case number (0->15). +// + +#endif diff --git a/Filtering/vtkMarchingSquaresCases.h b/Filtering/vtkMarchingSquaresCases.h new file mode 100644 index 0000000..df1d0a0 --- /dev/null +++ b/Filtering/vtkMarchingSquaresCases.h @@ -0,0 +1,28 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingSquaresCases.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkMarchingSquaresCases_h +#define __vtkMarchingSquaresCases_h +// +// marching squares cases for generating isolines +// + +typedef int EDGE_LIST; +struct VTK_FILTERING_EXPORT vtkMarchingSquaresLineCases +{ + EDGE_LIST edges[5]; + static vtkMarchingSquaresLineCases* GetCases(); +}; + +#endif diff --git a/Filtering/vtkMergePoints.cxx b/Filtering/vtkMergePoints.cxx new file mode 100644 index 0000000..5cc63ac --- /dev/null +++ b/Filtering/vtkMergePoints.cxx @@ -0,0 +1,198 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergePoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMergePoints.h" + +#include "vtkDataArray.h" +#include "vtkIdList.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkFloatArray.h" + +vtkCxxRevisionMacro(vtkMergePoints, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkMergePoints); + +// Determine whether point given by x[3] has been inserted into points list. +// Return id of previously inserted point if this is true, otherwise return +// -1. +vtkIdType vtkMergePoints::IsInsertedPoint(const double x[3]) +{ + int i, ijk0, ijk1, ijk2; + vtkIdType idx; + vtkIdList *bucket; + // + // Locate bucket that point is in. + // + ijk0 = (int) ((double) ((x[0] - this->Bounds[0]) / + (this->Bounds[1] - this->Bounds[0])) * (this->Divisions[0] - 1)); + ijk1 = (int) ((double) ((x[1] - this->Bounds[2]) / + (this->Bounds[3] - this->Bounds[2])) * (this->Divisions[1] - 1)); + ijk2 = (int) ((double) ((x[2] - this->Bounds[4]) / + (this->Bounds[5] - this->Bounds[4])) * (this->Divisions[2] - 1)); + + + idx = ijk0 + ijk1*this->Divisions[0] + + ijk2*this->Divisions[0]*this->Divisions[1]; + + bucket = this->HashTable[idx]; + + if ( ! bucket ) + { + return -1; + } + else // see whether we've got duplicate point + { + // + // Check the list of points in that bucket. + // + vtkIdType ptId; + int nbOfIds = bucket->GetNumberOfIds (); + + // For efficiency reasons, we break the data abstraction for points + // and ids (we are assuming and vtkIdList + // is storing ints). + vtkDataArray *dataArray = this->Points->GetData(); + vtkIdType *idArray = bucket->GetPointer(0); + if (dataArray->GetDataType() == VTK_FLOAT) + { + float f[3]; + f[0] = static_cast(x[0]); + f[1] = static_cast(x[1]); + f[2] = static_cast(x[2]); + vtkFloatArray *floatArray = static_cast(dataArray); + float *pt; + for (i=0; i < nbOfIds; i++) + { + ptId = idArray[i]; + pt = floatArray->GetPointer(0) + 3*ptId; + if ( f[0] == pt[0] && f[1] == pt[1] && f[2] == pt[2] ) + { + return ptId; + } + } + } + else + { + // Using the double interface + double *pt; + for (i=0; i < nbOfIds; i++) + { + ptId = idArray[i]; + pt = dataArray->GetTuple(ptId); + if ( x[0] == pt[0] && x[1] == pt[1] && x[2] == pt[2] ) + { + return ptId; + } + } + } + } + + return -1; +} + + +int vtkMergePoints::InsertUniquePoint(const double x[3], vtkIdType &id) +{ + int i, ijk0, ijk1, ijk2; + vtkIdType idx; + vtkIdList *bucket; + + // + // Locate bucket that point is in. + // + ijk0 = (int) ((double) ((x[0] - this->Bounds[0]) / + (this->Bounds[1] - this->Bounds[0])) * (this->Divisions[0] - 1)); + ijk1 = (int) ((double) ((x[1] - this->Bounds[2]) / + (this->Bounds[3] - this->Bounds[2])) * (this->Divisions[1] - 1)); + ijk2 = (int) ((double) ((x[2] - this->Bounds[4]) / + (this->Bounds[5] - this->Bounds[4])) * (this->Divisions[2] - 1)); + + idx = ijk0 + ijk1*this->Divisions[0] + + ijk2*this->Divisions[0]*this->Divisions[1]; + + bucket = this->HashTable[idx]; + + if (bucket) // see whether we've got duplicate point + { + // + // Check the list of points in that bucket. + // + vtkIdType ptId; + int nbOfIds = bucket->GetNumberOfIds (); + + // For efficiency reasons, we break the data abstraction for points + // and ids (we are assuming vtkPoints stores a vtkIdList + // is storing ints). + vtkDataArray *dataArray = this->Points->GetData(); + vtkIdType *idArray = bucket->GetPointer(0); + + if (dataArray->GetDataType() == VTK_FLOAT) + { + float f[3]; + f[0] = static_cast(x[0]); + f[1] = static_cast(x[1]); + f[2] = static_cast(x[2]); + vtkFloatArray *floatArray = static_cast(dataArray); + float *pt; + for (i=0; i < nbOfIds; i++) + { + ptId = idArray[i]; + pt = floatArray->GetPointer(0) + 3*ptId; + if ( f[0] == pt[0] && f[1] == pt[1] && f[2] == pt[2] ) + { + // point is already in the list, return 0 and set the id parameter + id = ptId; + return 0; + } + } + } + else + { + // Using the double interface + double *pt; + for (i=0; i < nbOfIds; i++) + { + ptId = idArray[i]; + pt = dataArray->GetTuple(ptId); + if ( x[0] == pt[0] && x[1] == pt[1] && x[2] == pt[2] ) + { + // point is already in the list, return 0 and set the id parameter + id = ptId; + return 0; + } + } + } + } + else + { + // create a bucket point list and insert the point + bucket = vtkIdList::New(); + bucket->Allocate(this->NumberOfPointsPerBucket/2, + this->NumberOfPointsPerBucket/3); + this->HashTable[idx] = bucket; + } + + // point has to be added + bucket->InsertNextId(this->InsertionPointId); + this->Points->InsertPoint(this->InsertionPointId,x); + id = this->InsertionPointId++; + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkMergePoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkMergePoints.h b/Filtering/vtkMergePoints.h new file mode 100644 index 0000000..7446620 --- /dev/null +++ b/Filtering/vtkMergePoints.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergePoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMergePoints - merge exactly coincident points +// .SECTION Description +// vtkMergePoints is a locator object to quickly locate points in 3D. +// The primary difference between vtkMergePoints and its superclass +// vtkPointLocator is that vtkMergePoints merges precisely coincident points +// and is therefore much faster. +// .SECTION See Also +// vtkCleanPolyData + +#ifndef __vtkMergePoints_h +#define __vtkMergePoints_h + +#include "vtkPointLocator.h" + +class VTK_FILTERING_EXPORT vtkMergePoints : public vtkPointLocator +{ +public: + static vtkMergePoints *New(); + vtkTypeRevisionMacro(vtkMergePoints,vtkPointLocator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Determine whether point given by x[3] has been inserted into points list. + // Return id of previously inserted point if this is true, otherwise return + // -1. + vtkIdType IsInsertedPoint(const double x[3]); + vtkIdType IsInsertedPoint(double x, double y, double z) + {return this->vtkPointLocator::IsInsertedPoint(x, y, z); }; + + // Description: + // Determine whether point given by x[3] has been inserted into points list. + // Return 0 if point was already in the list, otherwise return 1. If the + // point was not in the list, it will be ADDED. In either case, the id of + // the point (newly inserted or not) is returned in the ptId argument. + // Note this combines the functionality of IsInsertedPoint() followed + // by a call to InsertNextPoint(). + int InsertUniquePoint(const double x[3], vtkIdType &ptId); + +protected: + vtkMergePoints() {}; + ~vtkMergePoints() {}; + +private: + vtkMergePoints(const vtkMergePoints&); // Not implemented. + void operator=(const vtkMergePoints&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkNonLinearCell.cxx b/Filtering/vtkNonLinearCell.cxx new file mode 100644 index 0000000..cbdc569 --- /dev/null +++ b/Filtering/vtkNonLinearCell.cxx @@ -0,0 +1,50 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkNonLinearCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkNonLinearCell.h" +#include "vtkPolyData.h" +#include "vtkUnstructuredGrid.h" +#include "vtkDataSet.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkNonLinearCell, "$Revision: 1.1 $"); + +vtkNonLinearCell::vtkNonLinearCell() +{ + this->Error = 0.10; +} + +void vtkNonLinearCell::Tessellate(vtkIdType vtkNotUsed(cellId), + vtkDataSet* vtkNotUsed(input), + vtkPolyData* vtkNotUsed(output), + vtkPointLocator* vtkNotUsed(locator)) +{ + vtkWarningMacro(<<"This method should be implemented by a subclass"); +} + +void vtkNonLinearCell::Tessellate(vtkIdType vtkNotUsed(cellId), + vtkDataSet* vtkNotUsed(input), + vtkUnstructuredGrid* vtkNotUsed(output), + vtkPointLocator* vtkNotUsed(locator)) +{ + vtkWarningMacro(<<"This method should be implemented by a subclass"); +} + +void vtkNonLinearCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Error: " << this->Error << "\n"; +} + diff --git a/Filtering/vtkNonLinearCell.h b/Filtering/vtkNonLinearCell.h new file mode 100644 index 0000000..6c4d865 --- /dev/null +++ b/Filtering/vtkNonLinearCell.h @@ -0,0 +1,121 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkNonLinearCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkNonLinearCell - abstract superclass for non-linear cells +// .SECTION Description +// vtkNonLinearCell is an abstract superclass for non-linear cell types. +// Cells that are a direct subclass of vtkCell or vtkCell3D are linear; +// cells that are a subclass of vtkNonLinearCell have non-linear interpolation +// functions. Non-linear cells require special treatment when tessellating +// or converting to graphics primitives. Note that the linearity of the cell +// is a function of whether the cell needs tessellation, which does not +// strictly correlate with interpolation order (e.g., vtkHexahedron has +// non-linear interpolation functions (a product of three linear functions +// in r-s-t) even thought vtkHexahedron is considered linear.) +// +// The Error instance variable is used to control the tessellation of the +// cell. Error is normalized between (0.001,1) and typically measures the +// chordal deviation of linear (tessellated) primitives from the actual +// cell boundary. Each cell may have its own interpretation of this error +// measure. + +#ifndef __vtkNonLinearCell_h +#define __vtkNonLinearCell_h + +#include "vtkCell.h" + +#include "vtkPointLocator.h" // Needed for inline method +#include "vtkPoints.h" // Needed for inline method + +class vtkPolyData; +class vtkDataSet; +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkNonLinearCell : public vtkCell +{ +public: + vtkTypeRevisionMacro(vtkNonLinearCell,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the normalized error measure used to control the + // tessellation of the cell. + vtkSetClampMacro(Error,double,0.001,1.0); + vtkGetMacro(Error,double); + + // Description: + // Non-linear cells require special treatment (tessellation) when + // converting to graphics primitives (during mapping). The vtkCell + // API IsLinear() is modified to indicate this requirement. + virtual int IsLinear() {return 0;} + + // Description: + // This method tessellates the cell returning polydata. (The Error ivar + // controls the tessellation depth.) The new dataset will contain polydata + // primitives, possibly new points as well as interpolated point and cell + // data. The user must provide (the output) polydata which is filled in by + // the method. If the optional PointLocator is supplied, then any new + // points that are created are inserted through the vtkPointLocator, rather + // than directly in the vtkPolyData. (Note: the input dataset and cellId + // are used if the cell requires access to its owning dataset.) This method + // is called when the topological dimension of the cell is 2D or less. + virtual void Tessellate(vtkIdType cellId, + vtkDataSet *input, vtkPolyData *output, + vtkPointLocator *locator=NULL); + + // Description: + // This method tessellates the cell returning unstructured grid. (The Error + // ivar controls the tessellation depth.) The new dataset will contain + // unstructured grid primitives, possibly new points as well as + // interpolated point and cell data. The user must provide (the output) + // unstructured grid which is filled in by the method. If the optional + // PointLocator is supplied, then any new points that are created are + // inserted through the vtkPointLocator, rather than directly in the + // vtkUnstructuredGrid. (Note: the input dataset and cellId are used if + // the cell requires access to its owning dataset.) This method is called + // when the topological dimension of the cell is 3D. + virtual void Tessellate(vtkIdType cellId, + vtkDataSet *input, vtkUnstructuredGrid *output, + vtkPointLocator *locator=NULL); + + +protected: + vtkNonLinearCell(); + ~vtkNonLinearCell() {} + + double Error; + + // inline helper for tessellation- used by subclasses + vtkIdType InsertPoint(vtkPointLocator *locator, vtkPoints *pts, double *x) + { + if ( locator != NULL ) + { + vtkIdType p; + locator->InsertUniquePoint(x,p); + return p; + } + else + { + return pts->InsertNextPoint(x); + } + } + +private: + vtkNonLinearCell(const vtkNonLinearCell&); // Not implemented. + void operator=(const vtkNonLinearCell&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkOrderedTriangulator.cxx b/Filtering/vtkOrderedTriangulator.cxx new file mode 100644 index 0000000..17eac1b --- /dev/null +++ b/Filtering/vtkOrderedTriangulator.cxx @@ -0,0 +1,1709 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOrderedTriangulator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOrderedTriangulator.h" + +#include "vtkCellArray.h" +#include "vtkEdgeTable.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkTetra.h" +#include "vtkUnstructuredGrid.h" +#include "vtkHeap.h" +#include "vtkDataArray.h" +#include "vtkDoubleArray.h" +#include "vtkPointLocator.h" +#include "vtkPointData.h" +#include "vtkCellData.h" + +#include +#include +#include +#include +#include + +vtkCxxRevisionMacro(vtkOrderedTriangulator, "$Revision: 1.2.4.1 $"); +vtkStandardNewMacro(vtkOrderedTriangulator); + +#ifdef _WIN32_WCE +# ifndef __PLACEMENT_NEW_INLINE +# define __PLACEMENT_NEW_INLINE + inline void *__cdecl operator new(size_t, void *_P) { return (_P); } +# if _MSC_VER >= 1200 + inline void __cdecl operator delete(void *, void *) { return; } +# endif +# endif +#else +# ifdef VTK_USE_ANSI_STDLIB +# include +# else +# include +# endif +#endif + +// Old HP compiler does not support operator delete that is called +// when a constructor called by operator new throws. +// Might be supported in newer versions && (__HP_aCC <= 012100) +#if defined(__HP_aCC) +# define VTK_NO_PLACEMENT_DELETE +#endif +// SGI compiler does not support placement delete that is called when +// a constructor called by placement new throws. +#if defined(__sgi) && !defined(__GNUC__) +# define VTK_NO_PLACEMENT_DELETE +#endif + +// Classes are used to represent points, faces, and tetras------------------- +// This data structure consists of points and tetras, with the face used +// temporarily as a place holder during triangulation. +struct OTPoint; +struct OTFace; +struct OTTetra; + +//---Class represents a point (and related typedefs)-------------------------- +// Note that the points has two sets of coordinates: the first the actual +// position X[3] and the second the coordinate used for performing +// triangulation (usually a parametric coordinate P[3]). +struct OTPoint +{ + OTPoint() : Type(Inside), Id(0), SortId(0), SortId2(0), OriginalId(0), + InsertionId(0) + { + this->X[0] = this->X[1] = this->X[2] = 0.0; + this->P[0] = this->P[1] = this->P[2] = 0.0; + } + + enum PointClassification + {Inside=0,Outside=1,Boundary=2,Added=3,NoInsert=4}; + PointClassification Type; + double X[3]; //Actual position of point + double P[3]; //Triangulation coordinate (typically parametric coordinate) + + //Id of originating point + vtkIdType Id; + + //Id used to sort points prior to triangulation + vtkIdType SortId; + + //Second id used to sort in triangulation + //This can be used in situations where one id is not enough + //(for example, when the id is related to an edge which + // is described by two points) + vtkIdType SortId2; + + //Id based on order seen in InsertPoint() + vtkIdType OriginalId; + //Id after sorting the points (i.e. order inserted into mesh) + vtkIdType InsertionId; +}; +struct PointListType : public vtkstd::vector +{ + PointListType() : vtkstd::vector() {} + OTPoint* GetPointer(int ptId) + {return &( *(this->begin()+ptId) ); } +}; +typedef PointListType::iterator PointListIterator; + +//---Class represents a face (and related typedefs)-------------------------- +struct OTFace //used during tetra construction +{ + void *operator new(size_t size, vtkHeap *heap) + {return heap->AllocateMemory(size);} +#if !defined(VTK_NO_PLACEMENT_DELETE) + void operator delete(void*,vtkHeap*) {} +#endif + + OTPoint *Points[3]; //the three points of the face + OTTetra *Neighbor; + double Normal[3]; + double N2; + + void ComputePseudoNormal() + { + double v20[3], v10[3]; + v20[0] = this->Points[2]->P[0] - this->Points[0]->P[0]; + v20[1] = this->Points[2]->P[1] - this->Points[0]->P[1]; + v20[2] = this->Points[2]->P[2] - this->Points[0]->P[2]; + v10[0] = this->Points[1]->P[0] - this->Points[0]->P[0]; + v10[1] = this->Points[1]->P[1] - this->Points[0]->P[1]; + v10[2] = this->Points[1]->P[2] - this->Points[0]->P[2]; + vtkMath::Cross(v10,v20,this->Normal); + this->N2 = vtkMath::Dot(this->Normal,this->Normal); + } + int IsValidCavityFace(double X[3],double tol2) + { + double vp[3], d; + vp[0] = X[0] - this->Points[0]->P[0]; + vp[1] = X[1] - this->Points[0]->P[1]; + vp[2] = X[2] - this->Points[0]->P[2]; + d = vtkMath::Dot(vp,this->Normal); + return ( (d > 0.0L && (d*d) > (tol2*this->N2)) ? 1 : 0 ); + } +}; +typedef vtkstd::vector FaceListType; +typedef vtkstd::vector::iterator FaceListIterator; + +//---Class represents a tetrahedron (and related typedefs)-------------------- +typedef vtkstd::list TetraListType; +typedef vtkstd::list::iterator TetraListIterator; +struct TetraStackType : public vtkstd::stack +{ + TetraStackType() : vtkstd::stack() {} + void clear() {while (!this->empty()) this->pop();} +}; +typedef vtkstd::vector TetraQueueType; +typedef vtkstd::vector::iterator TetraQueueIterator; + +struct OTTetra +{ + void *operator new(size_t size, vtkHeap *heap) + {return heap->AllocateMemory(size);} +#if !defined(VTK_NO_PLACEMENT_DELETE) + void operator delete(void*,vtkHeap*) {} +#endif + + OTTetra() : Radius2(0.0L), CurrentPointId(-1), Type(OutsideCavity) + { + this->Center[0] = this->Center[1] = this->Center[2] = 0.0L; + this->Points[0] = this->Points[1] = this->Points[2] = this->Points[3] = 0; + this->Neighbors[0] = this->Neighbors[1] = + this->Neighbors[2] = this->Neighbors[3] = 0; + } + + // Center and radius squared of circumsphere of this tetra + double Radius2; + double Center[3]; + + // Note: there is a direct correlation between the points and the faces + // i.e., the ordering of the points and face neighbors. + OTTetra *Neighbors[4]; //the four face neighbors + OTPoint *Points[4]; //the four points + + // The following are used during point insertion + int CurrentPointId; //indicated current point being inserted + enum TetraClassification + {Inside=0,Outside=1,All=2,InCavity=3,OutsideCavity=4,Exterior=5}; + TetraClassification Type; + + // Supporting triangulation operators + void GetFacePoints(int i, OTFace *face); + int InCircumSphere(double x[3]); + TetraClassification DetermineType(); //inside, outside + TetraListIterator ListIterator; //points to the list of tetras +}; + +//---Class represents the Delaunay triangulation using points and tetras. +// Additional support for the Delaunay triangulation process. +struct vtkOTMesh +{ + vtkOTMesh(vtkHeap *heap) : + NumberOfTetrasClassifiedInside(0), NumberOfTemplates(0) + { + this->EdgeTable = vtkEdgeTable::New(); + this->Heap = heap; + } + ~vtkOTMesh() + { + this->EdgeTable->Delete(); + } + + PointListType Points; //Points in the mesh + TetraListType Tetras; //Tetrahedra in the mesh + FaceListType CavityFaces; //Faces forming an insertion cavity + TetraQueueType VisitedTetras; //Those tetra already visited during insertion + TetraStackType TetraStack; //Stack of tetra visited during point insertion + TetraQueueType DegenerateQueue; //Tetra involved in degenerate triangulation + vtkEdgeTable *EdgeTable; //Edges used to create triangulation of cavity + double Tolerance2; //Used to control error + vtkHeap *Heap; //Many allocations occur in efficent heap + + int NumberOfTetrasClassifiedInside; + int NumberOfTemplates; + TetraListIterator CurrentTetra; + + void Reset() + { + this->Points.clear(); + this->Tetras.clear(); + this->CavityFaces.clear(); + this->VisitedTetras.clear(); + this->TetraStack.clear(); + this->DegenerateQueue.clear(); + this->EdgeTable->Reset(); + } + + OTTetra *CreateTetra(OTPoint *p, OTFace *face); + OTTetra *WalkToTetra(OTTetra *t,double x[3],int depth,double bc[4]); + int CreateInsertionCavity(OTPoint* p, OTTetra *tetra, double bc[4]); + int ClassifyTetras(); + void DumpInsertionCavity(double x[3]); +}; + +//---Classes and typedefs used to support triangulation templates. +// Triangulation templates are used instead of Delaunay triangulation +// because they are so much faster. Because there are so many possible +// triangulations/templates possible, triangulation templates are +// computed on the fly and then cached. +// +// Two lists are kept. The first is a list of lists of templates for +// each cell type. The second is a list of templates for each cell. +// +// A specific template. The number of tetras and the tetra connectivity. +struct OTTemplate +{ + vtkIdType NumberOfTetras; + vtkIdType *Tetras; + + OTTemplate(vtkIdType numberOfTetras, vtkHeap *heap) + { + this->NumberOfTetras = numberOfTetras; + this->Tetras = static_cast( + heap->AllocateMemory(sizeof(vtkIdType)*numberOfTetras*4) ); + } + void *operator new(size_t size, vtkHeap *heap) + {return heap->AllocateMemory(size);} +#if !defined(VTK_NO_PLACEMENT_DELETE) + void operator delete(void*,vtkHeap*) {} +#endif +}; + + +// Typedefs for a list of templates for a particular cell. Key is the +// template index. +typedef vtkstd::map TemplateList; +typedef vtkstd::map::iterator TemplateListIterator; + +// +// Typedefs for a list of lists of templates keyed on cell type +struct vtkOTTemplates : public vtkstd::map {}; +typedef vtkstd::map::iterator TemplatesIterator; + + +//------------------------------------------------------------------------ +vtkOrderedTriangulator::vtkOrderedTriangulator() +{ + // In place news (using allocators) are done here + this->Heap = vtkHeap::New(); + this->Heap->SetBlockSize(500000); + + this->Mesh = new vtkOTMesh(this->Heap); + this->NumberOfPoints = 0; + this->PreSorted = 0; + this->UseTwoSortIds = 0; + + this->UseTemplates = 0; + this->NumberOfCellPoints = 0; + this->NumberOfCellEdges = 0; + this->Templates = new vtkOTTemplates; + this->TemplateHeap = vtkHeap::New(); + this->TemplateHeap->SetBlockSize(250000); +} + +//------------------------------------------------------------------------ +vtkOrderedTriangulator::~vtkOrderedTriangulator() +{ + delete this->Mesh; + this->Heap->Delete(); + + TemplatesIterator titer; + for (titer=this->Templates->begin(); titer != this->Templates->end(); ++titer) + { + delete (*titer).second; + } + delete this->Templates; + this->TemplateHeap->Delete(); +} + +//------------------------------------------------------------------------ +void vtkOrderedTriangulator::InitTriangulation(double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax, + int numPts) +{ + double bounds[6]; + bounds[0] = xmin; + bounds[1] = xmax; + bounds[2] = ymin; + bounds[3] = ymax; + bounds[4] = zmin; + bounds[5] = zmax; + + this->InitTriangulation(bounds,numPts); + + // The templates remain valid and are reused. +} + +//------------------------------------------------------------------------ +void vtkOrderedTriangulator::InitTriangulation(double bounds[6], int numPts) +{ + this->Heap->Reset(); + this->Mesh->Reset(); + this->NumberOfPoints = 0; + this->MaximumNumberOfPoints = numPts; + this->Mesh->Points.resize(numPts+6); + + for (int i=0; i<6; i++) + { + this->Bounds[i] = bounds[i]; + } +} + +//------------------------------------------------------------------------ +// Create an initial bounding Delaunay triangulation consisting of four +// tetras arranged in an octahedron. +void vtkOrderedTriangulator::Initialize() +{ + double length; + double center[3]; + double radius2; + + // Set up the internal data structures. Space for six extra points + // is allocated for the bounding triangulation. + int numPts = this->MaximumNumberOfPoints; + double *bounds=this->Bounds; + + // Create the initial Delaunay triangulation which is a + // bounding octahedron: 6 points & 4 tetra. + center[0] = (bounds[0]+bounds[1])/2.0; + center[1] = (bounds[2]+bounds[3])/2.0; + center[2] = (bounds[4]+bounds[5])/2.0; + length = 2.0 * sqrt( (radius2 = (bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])) ); + radius2 /= 2.0; + this->Mesh->Tolerance2 = length*length*1.0e-10; + + // Define the points (-x,+x,-y,+y,-z,+z). Theses added points are + // used to create a bounding octahedron. + this->Mesh->Points[numPts].P[0] = center[0] - length; + this->Mesh->Points[numPts].P[1] = center[1]; + this->Mesh->Points[numPts].P[2] = center[2]; + this->Mesh->Points[numPts].Id = numPts; + this->Mesh->Points[numPts].InsertionId = numPts; + this->Mesh->Points[numPts].Type = OTPoint::Added; + + this->Mesh->Points[numPts+1].P[0] = center[0] + length; + this->Mesh->Points[numPts+1].P[1] = center[1]; + this->Mesh->Points[numPts+1].P[2] = center[2]; + this->Mesh->Points[numPts+1].Id = numPts + 1; + this->Mesh->Points[numPts+1].InsertionId = numPts + 1; + this->Mesh->Points[numPts+1].Type = OTPoint::Added; + + this->Mesh->Points[numPts+2].P[0] = center[0]; + this->Mesh->Points[numPts+2].P[1] = center[1] - length; + this->Mesh->Points[numPts+2].P[2] = center[2]; + this->Mesh->Points[numPts+2].Id = numPts + 2; + this->Mesh->Points[numPts+2].InsertionId = numPts + 2; + this->Mesh->Points[numPts+2].Type = OTPoint::Added; + + this->Mesh->Points[numPts+3].P[0] = center[0]; + this->Mesh->Points[numPts+3].P[1] = center[1] + length; + this->Mesh->Points[numPts+3].P[2] = center[2]; + this->Mesh->Points[numPts+3].Id = numPts + 3; + this->Mesh->Points[numPts+3].InsertionId = numPts + 3; + this->Mesh->Points[numPts+3].Type = OTPoint::Added; + + this->Mesh->Points[numPts+4].P[0] = center[0]; + this->Mesh->Points[numPts+4].P[1] = center[1]; + this->Mesh->Points[numPts+4].P[2] = center[2] - length; + this->Mesh->Points[numPts+4].Id = numPts + 4; + this->Mesh->Points[numPts+4].InsertionId = numPts + 4; + this->Mesh->Points[numPts+4].Type = OTPoint::Added; + + this->Mesh->Points[numPts+5].P[0] = center[0]; + this->Mesh->Points[numPts+5].P[1] = center[1]; + this->Mesh->Points[numPts+5].P[2] = center[2] + length; + this->Mesh->Points[numPts+5].Id = numPts + 5; + this->Mesh->Points[numPts+5].InsertionId = numPts + 5; + this->Mesh->Points[numPts+5].Type = OTPoint::Added; + + // Create bounding tetras (there are four) as well as the associated faces + // They all share the same center and radius + OTTetra *tetras[4]; + for (int i=0; i<4; ++i) + { + tetras[i] = new(this->Heap) OTTetra(); + this->Mesh->Tetras.push_front(tetras[i]); + tetras[i]->ListIterator = this->Mesh->Tetras.begin(); + tetras[i]->Center[0] = center[0]; + tetras[i]->Center[1] = center[1]; + tetras[i]->Center[2] = center[2]; + tetras[i]->Radius2 = radius2; + } + + //Okay now set up the points and neighbors in the tetras + tetras[0]->Points[0] = this->Mesh->Points.GetPointer(numPts + 0); + tetras[0]->Points[1] = this->Mesh->Points.GetPointer(numPts + 2); + tetras[0]->Points[2] = this->Mesh->Points.GetPointer(numPts + 4); + tetras[0]->Points[3] = this->Mesh->Points.GetPointer(numPts + 5); + tetras[0]->Neighbors[0] = 0; //outside + tetras[0]->Neighbors[1] = tetras[1]; + tetras[0]->Neighbors[2] = tetras[3]; + tetras[0]->Neighbors[3] = 0; + + tetras[1]->Points[0] = this->Mesh->Points.GetPointer(numPts + 2); + tetras[1]->Points[1] = this->Mesh->Points.GetPointer(numPts + 1); + tetras[1]->Points[2] = this->Mesh->Points.GetPointer(numPts + 4); + tetras[1]->Points[3] = this->Mesh->Points.GetPointer(numPts + 5); + tetras[1]->Neighbors[0] = 0; + tetras[1]->Neighbors[1] = tetras[2]; + tetras[1]->Neighbors[2] = tetras[0]; + tetras[1]->Neighbors[3] = 0; + + tetras[2]->Points[0] = this->Mesh->Points.GetPointer(numPts + 1); + tetras[2]->Points[1] = this->Mesh->Points.GetPointer(numPts + 3); + tetras[2]->Points[2] = this->Mesh->Points.GetPointer(numPts + 4); + tetras[2]->Points[3] = this->Mesh->Points.GetPointer(numPts + 5); + tetras[2]->Neighbors[0] = 0; + tetras[2]->Neighbors[1] = tetras[3]; + tetras[2]->Neighbors[2] = tetras[1]; + tetras[2]->Neighbors[3] = 0; + + tetras[3]->Points[0] = this->Mesh->Points.GetPointer(numPts + 3); + tetras[3]->Points[1] = this->Mesh->Points.GetPointer(numPts + 0); + tetras[3]->Points[2] = this->Mesh->Points.GetPointer(numPts + 4); + tetras[3]->Points[3] = this->Mesh->Points.GetPointer(numPts + 5); + tetras[3]->Neighbors[0] = 0; + tetras[3]->Neighbors[1] = tetras[0]; + tetras[3]->Neighbors[2] = tetras[2]; + tetras[3]->Neighbors[3] = 0; +} + + +//------------------------------------------------------------------------ +// Add a point to the list of points to be triangulated. +vtkIdType vtkOrderedTriangulator::InsertPoint(vtkIdType id, double x[3], + double p[3], int type) +{ + vtkIdType idx = this->NumberOfPoints++; + if ( idx >= this->MaximumNumberOfPoints ) + { + vtkErrorMacro(<< "Trying to insert more points than specified max="<MaximumNumberOfPoints<<" idx="<Mesh->Points[idx].Id = id; + this->Mesh->Points[idx].SortId = id; + this->Mesh->Points[idx].SortId2 = -1; + this->Mesh->Points[idx].OriginalId = idx; + this->Mesh->Points[idx].InsertionId = -1; //dummy value until inserted + this->Mesh->Points[idx].X[0] = x[0]; + this->Mesh->Points[idx].X[1] = x[1]; + this->Mesh->Points[idx].X[2] = x[2]; + this->Mesh->Points[idx].P[0] = p[0]; + this->Mesh->Points[idx].P[1] = p[1]; + this->Mesh->Points[idx].P[2] = p[2]; + this->Mesh->Points[idx].Type = (OTPoint::PointClassification) type; + + return idx; +} + +//------------------------------------------------------------------------ +// Add a point to the list of points to be triangulated. +vtkIdType vtkOrderedTriangulator::InsertPoint(vtkIdType id, vtkIdType sortid, + double x[3], double p[3], int type) +{ + vtkIdType idx = this->NumberOfPoints++; + if ( idx >= this->MaximumNumberOfPoints ) + { + vtkErrorMacro(<< "Trying to insert more points than specified"); + return idx; + } + + this->Mesh->Points[idx].Id = id; + this->Mesh->Points[idx].SortId = sortid; + this->Mesh->Points[idx].SortId2 = -1; + this->Mesh->Points[idx].OriginalId = idx; + this->Mesh->Points[idx].InsertionId = -1; //dummy value until inserted + this->Mesh->Points[idx].X[0] = x[0]; + this->Mesh->Points[idx].X[1] = x[1]; + this->Mesh->Points[idx].X[2] = x[2]; + this->Mesh->Points[idx].P[0] = p[0]; + this->Mesh->Points[idx].P[1] = p[1]; + this->Mesh->Points[idx].P[2] = p[2]; + this->Mesh->Points[idx].Type = (OTPoint::PointClassification) type; + + return idx; +} + +//------------------------------------------------------------------------ +// Add a point to the list of points to be triangulated. +vtkIdType vtkOrderedTriangulator::InsertPoint(vtkIdType id, vtkIdType sortid, + vtkIdType sortid2, + double x[3], double p[3], int type) +{ + vtkIdType idx = this->NumberOfPoints++; + if ( idx >= this->MaximumNumberOfPoints ) + { + vtkErrorMacro(<< "Trying to insert more points than specified"); + return idx; + } + + this->Mesh->Points[idx].Id = id; + this->Mesh->Points[idx].SortId = sortid; + this->Mesh->Points[idx].SortId2 = sortid2; + this->Mesh->Points[idx].OriginalId = idx; + this->Mesh->Points[idx].InsertionId = -1; //dummy value until inserted + this->Mesh->Points[idx].X[0] = x[0]; + this->Mesh->Points[idx].X[1] = x[1]; + this->Mesh->Points[idx].X[2] = x[2]; + this->Mesh->Points[idx].P[0] = p[0]; + this->Mesh->Points[idx].P[1] = p[1]; + this->Mesh->Points[idx].P[2] = p[2]; + this->Mesh->Points[idx].Type = (OTPoint::PointClassification) type; + + return idx; +} + +//------------------------------------------------------------------------ +// Used when an already inserted point must have its classification changed +// (e.g., an intersection point is very near another point). +void vtkOrderedTriangulator::UpdatePointType(vtkIdType internalId, int type) +{ + assert("pre: valid_range" && internalId>=0 && + internalIdNumberOfPoints); + this->Mesh->Points[internalId].Type = (OTPoint::PointClassification) type; +} + +//------------------------------------------------------------------------ +double *vtkOrderedTriangulator::GetPointPosition(vtkIdType internalId) +{ + assert("pre: valid_range" && internalId>=0 && + internalIdNumberOfPoints); + return this->Mesh->Points[internalId].P; +} + +//------------------------------------------------------------------------ +double *vtkOrderedTriangulator::GetPointLocation(vtkIdType internalId) +{ + assert("pre: valid_range" && internalId>=0 && + internalIdNumberOfPoints); + return this->Mesh->Points[internalId].X; +} + +//------------------------------------------------------------------------ +vtkIdType vtkOrderedTriangulator::GetPointId(vtkIdType internalId) +{ + assert("pre: valid_range" && internalId>=0 && + internalIdNumberOfPoints); + return this->Mesh->Points[internalId].Id; +} +//------------------------------------------------------------------------ +// For a particular tetra and given a face id, return the three points +// defining the face. +void OTTetra::GetFacePoints(int i, OTFace *face) +{ + // The order is carefully choosen to produce a tetrahedron + // that is not inside out; i.e., the ordering produces a positive + // Jacobian (computed from first three points points to fourth). + switch (i) + { + case 0: + face->Points[0] = this->Points[0]; + face->Points[1] = this->Points[3]; + face->Points[2] = this->Points[1]; + break; + case 1: + face->Points[0] = this->Points[1]; + face->Points[1] = this->Points[3]; + face->Points[2] = this->Points[2]; + break; + case 2: + face->Points[0] = this->Points[0]; + face->Points[1] = this->Points[2]; + face->Points[2] = this->Points[3]; + break; + case 3: + face->Points[0] = this->Points[0]; + face->Points[1] = this->Points[1]; + face->Points[2] = this->Points[2]; + break; + } + face->ComputePseudoNormal(); +} + +//------------------------------------------------------------------------ +// Routines used to sort the points based on id. +extern "C" { +#ifdef _WIN32_WCE + int __cdecl vtkSortOnIds(const void *val1, const void *val2) +#else + int vtkSortOnIds(const void *val1, const void *val2) +#endif + { + if (((OTPoint *)val1)->SortId < ((OTPoint *)val2)->SortId) + { + return (-1); + } + else if (((OTPoint *)val1)->SortId > ((OTPoint *)val2)->SortId) + { + return (1); + } + else + { + return (0); + } + } +} + +extern "C" { +#ifdef _WIN32_WCE + int __cdecl vtkSortOnTwoIds(const void *val1, const void *val2) +#else + int vtkSortOnTwoIds(const void *val1, const void *val2) +#endif + { + if (((OTPoint *)val1)->SortId2 < ((OTPoint *)val2)->SortId2) + { + return (-1); + } + else if (((OTPoint *)val1)->SortId2 > ((OTPoint *)val2)->SortId2) + { + return (1); + } + + if (((OTPoint *)val1)->SortId < ((OTPoint *)val2)->SortId) + { + return (-1); + } + else if (((OTPoint *)val1)->SortId > ((OTPoint *)val2)->SortId) + { + return (1); + } + else + { + return (0); + } + } +} + +//------------------------------------------------------------------------ +// See whether point is in sphere of tetrahedron. +int OTTetra::InCircumSphere(double x[3]) +{ + double dist2; + + // check if inside/outside circumsphere + dist2 = (x[0] - this->Center[0]) * (x[0] - this->Center[0]) + + (x[1] - this->Center[1]) * (x[1] - this->Center[1]) + + (x[2] - this->Center[2]) * (x[2] - this->Center[2]); + + return (dist2 < (0.999999L * this->Radius2) ? 1 : 0); +} + +//------------------------------------------------------------------------ +// Determine the classification of a tetra based on point types. +inline OTTetra::TetraClassification OTTetra::DetermineType() +{ + if ( (this->Points[0]->Type == OTPoint::Inside || + this->Points[0]->Type == OTPoint::Boundary ) && + (this->Points[1]->Type == OTPoint::Inside || + this->Points[1]->Type == OTPoint::Boundary ) && + (this->Points[2]->Type == OTPoint::Inside || + this->Points[2]->Type == OTPoint::Boundary ) && + (this->Points[3]->Type == OTPoint::Inside || + this->Points[3]->Type == OTPoint::Boundary ) ) + { + this->Type = OTTetra::Inside; + return OTTetra::Inside; + } + else if ( (this->Points[0]->Type == OTPoint::Outside || + this->Points[0]->Type == OTPoint::Boundary ) && + (this->Points[1]->Type == OTPoint::Outside || + this->Points[1]->Type == OTPoint::Boundary ) && + (this->Points[2]->Type == OTPoint::Outside || + this->Points[2]->Type == OTPoint::Boundary ) && + (this->Points[3]->Type == OTPoint::Outside || + this->Points[3]->Type == OTPoint::Boundary ) ) + { + this->Type = OTTetra::Outside; + return OTTetra::Outside; + } + else + { + this->Type = OTTetra::Exterior; + return OTTetra::Exterior; + } +} + +//------------------------------------------------------------------------ +// Determine whether the point is used by a specified tetra. +inline static int IsAPoint(OTTetra *t, vtkIdType id) +{ + if ( id == t->Points[0]->InsertionId || id == t->Points[1]->InsertionId || + id == t->Points[2]->InsertionId || id == t->Points[3]->InsertionId ) + { + return 1; + } + else + { + return 0; + } +} + +//------------------------------------------------------------------------ +// Given two tetra face neighbors, assign the neighbor pointers to each tetra. +static void AssignNeighbors(OTTetra* t1, OTTetra* t2) +{ + static int CASE_MASK[4] = {1,2,4,8}; + int i, index; + + for (i=0, index=0; i<4; ++i) + { + if (IsAPoint(t2,t1->Points[i]->InsertionId) ) + { + index |= CASE_MASK[i]; + } + } + switch (index) + { + case 11: + t1->Neighbors[0] = t2; + break; + case 14: + t1->Neighbors[1] = t2; + break; + case 13: + t1->Neighbors[2] = t2; + break; + case 7: + t1->Neighbors[3] = t2; + break; + default: + vtkGenericWarningMacro(<<"Really bad"); + } + + for (i=0, index=0; i<4; ++i) + { + if (IsAPoint(t1,t2->Points[i]->InsertionId) ) + { + index |= CASE_MASK[i]; + } + } + switch (index) + { + case 11: + t2->Neighbors[0] = t1; + break; + case 14: + t2->Neighbors[1] = t1; + break; + case 13: + t2->Neighbors[2] = t1; + break; + case 7: + t2->Neighbors[3] = t1; + break; + default: + vtkGenericWarningMacro(<<"Really bad"); + } +} + +//------------------------------------------------------------------------ +// Instantiate and initialize a tetra. +OTTetra *vtkOTMesh::CreateTetra(OTPoint *p, OTFace *face) +{ + OTTetra *tetra = new(this->Heap) OTTetra; + this->Tetras.push_front(tetra); + tetra->ListIterator = this->Tetras.begin(); + tetra->Radius2 = vtkTetra::Circumsphere(p->P, + face->Points[0]->P, + face->Points[1]->P, + face->Points[2]->P, + tetra->Center); + + // the order is carefully choosen to produce a tetrahedron + // that is not inside out; i.e., the ordering produces a positive + // jacobian (normal computed from first three points points to fourth). + tetra->Points[0] = face->Points[0]; + tetra->Points[1] = face->Points[1]; + tetra->Points[2] = face->Points[2]; + tetra->Points[3] = p; + + if ( face->Neighbor ) + { + AssignNeighbors(tetra,face->Neighbor); + } + + return tetra; +} + +//------------------------------------------------------------------------ +// We start with a point that is inside a tetrahedron. We find face +// neighbors of the tetrahedron that also contain the point. The +// process continues recursively until no more tetrahedron are found. +// Faces that lie between a tetrahedron that is in the cavity and one +// that is not form the cavity boundary, these are kept track of in +// a list. Eventually the point and boundary faces form new tetrahedra. +int vtkOTMesh::CreateInsertionCavity(OTPoint* p, OTTetra *initialTet, + double [4]) +{ + // Prepare to insert deleted tetras and cavity faces + // + this->CavityFaces.clear(); //cavity face boundary + this->VisitedTetras.clear(); //tetras involved in creating cavity + this->TetraStack.clear(); //queue of tetras being processed + this->DegenerateQueue.clear(); //queue of tetras that have degenerate faces + this->TetraStack.push(initialTet); + initialTet->Type = OTTetra::InCavity; //the seed of the cavity + initialTet->CurrentPointId = p->InsertionId; //mark visited + this->VisitedTetras.push_back(initialTet); + + // Process queue of tetras until exhausted + // + int i, valid; + int somethingNotValid=0; + OTTetra *nei, *tetra; + TetraQueueIterator t; + for ( int numCycles=0; !this->TetraStack.empty(); numCycles++) + { + tetra = this->TetraStack.top(); + this->TetraStack.pop(); + + //for each face, see whether the neighbors are in the cavity + for (valid=1, i=0; i<4 && valid; ++i) + { + nei = tetra->Neighbors[i]; + // If a mesh boundary face, the face is added to the + // list of insertion cavity faces + if ( nei == 0 ) + { + OTFace *face = new(this->Heap) OTFace; + tetra->GetFacePoints(i,face); + face->Neighbor = 0; + this->CavityFaces.push_back(face); + valid = face->IsValidCavityFace(p->P,this->Tolerance2); + } + // Neighbor tetra has not been visited, check for possible face boundary + else if ( nei->CurrentPointId != p->InsertionId ) + { + this->VisitedTetras.push_back(nei); + nei->CurrentPointId = p->InsertionId; //mark visited + if ( nei->InCircumSphere(p->P) ) + { + nei->Type = OTTetra::InCavity; + this->TetraStack.push(nei); + } + else //a cavity boundary + { + nei->Type = OTTetra::OutsideCavity; + OTFace *face = new(this->Heap) OTFace; + tetra->GetFacePoints(i,face); + face->Neighbor = nei; + this->CavityFaces.push_back(face); + valid = face->IsValidCavityFace(p->P,this->Tolerance2); + } + }//if a not-visited face neighbor + // Visited before, add this face as a boundary + else if ( nei->Type == OTTetra::OutsideCavity ) + { + OTFace *face = new(this->Heap) OTFace; + tetra->GetFacePoints(i,face); + face->Neighbor = nei; + this->CavityFaces.push_back(face); + valid = face->IsValidCavityFace(p->P,this->Tolerance2); + } + }//for each of the four tetra faces + + //check for validity + if ( !valid ) //broke out due to invalid face + { + somethingNotValid++; + //add this tetra to queue + this->DegenerateQueue.push_back(tetra); + + //mark all current tetras unvisited + for (t = this->VisitedTetras.begin(); + t != this->VisitedTetras.end(); ++t) + { + (*t)->CurrentPointId = -1; + } + + //mark degenerate tetras visited and outside cavity + TetraQueueIterator titer; + for ( titer=this->DegenerateQueue.begin(); + titer != this->DegenerateQueue.end(); ++titer) + { + (*titer)->CurrentPointId = p->InsertionId; + (*titer)->Type = OTTetra::OutsideCavity; + } + + //reinitialize queue + this->CavityFaces.clear(); //cavity face boundary + this->VisitedTetras.clear(); //tetras visited during cavity creation + this->TetraStack.clear(); //reprocess + this->TetraStack.push(initialTet); + initialTet->CurrentPointId = p->InsertionId; + initialTet->Type = OTTetra::InCavity; + this->VisitedTetras.push_back(initialTet); + } + if ( numCycles > 1000 ) return 0; + }//while queue not empty + + // Make final pass and delete tetras inside the cavity + for (t = this->VisitedTetras.begin(); t != this->VisitedTetras.end(); ++t) + { + tetra = *t; + if ( tetra->CurrentPointId == p->InsertionId && + tetra->Type == OTTetra::InCavity ) + { + this->Tetras.erase(tetra->ListIterator); + } + } + +#if 0 + //please leave this for debugging purposes + if ( somethingNotValid ) + { + this->DumpInsertionCavity(p->P); +// exit(1); + } +#endif + + return 1; +} + +//------------------------------------------------------------------------ +// Returns the number of tetras classified inside; a side effect is that +// all tetra are classified. +int vtkOTMesh::ClassifyTetras() +{ + TetraListIterator t; + vtkIdType numInsideTetras=0; + + // loop over all tetras getting the ones with the classification requested + for (t=this->Tetras.begin(); t != this->Tetras.end(); ++t) + { + if ( (*t)->DetermineType() == OTTetra::Inside ) + { + numInsideTetras++; + } + }//for all tetras + + return numInsideTetras; +} + +//------------------------------------------------------------------------ +// Used to debug (writes a VTK file representing the current insertion cavity). +void vtkOTMesh::DumpInsertionCavity(double x[3]) +{ + OTFace *face; + FaceListIterator fptr; + + cout << "# vtk DataFile Version 3.0\n"; + cout << "ordered triangulator output\n"; + cout << "ASCII\n"; + cout << "DATASET POLYDATA\n"; + + //write out points + int numFaces = (int)this->CavityFaces.size(); + cout << "POINTS " << 3*numFaces+1 << " double\n"; + + for (fptr=this->CavityFaces.begin(); + fptr != this->CavityFaces.end(); ++fptr) + { + face = *fptr; + cout << face->Points[0]->P[0] << " " + << face->Points[0]->P[1] << " " + << face->Points[0]->P[2] << " " + << face->Points[1]->P[0] << " " + << face->Points[1]->P[1] << " " + << face->Points[1]->P[2] << " " + << face->Points[2]->P[0] << " " + << face->Points[2]->P[1] << " " + << face->Points[2]->P[2] << "\n"; + } + + //write out point insertion vertex + cout << x[0] << " " << x[1] << " " << x[2] << "\n\n"; + cout << "VERTICES 1 2 \n"; + cout << "1 " << 3*numFaces << "\n\n"; + + //write out triangles + cout << "POLYGONS " << numFaces << " " <<4*numFaces << "\n"; + + int idx=0; + for (fptr=this->CavityFaces.begin(); + fptr != this->CavityFaces.end(); ++fptr, idx+=3) + { + cout << 3 << " " << idx << " " << idx+1 << " " << idx+2 << "\n"; + } +} + +//------------------------------------------------------------------------ +// Walk to the tetra tha contains this point. Walking is done by moving +// in the direction of the most negative barycentric coordinate (i.e., +// into the face neighbor). +OTTetra* +vtkOTMesh::WalkToTetra(OTTetra *tetra, double x[3], int depth, double bc[4]) +{ + int neg = 0; + int j, numNeg; + double negValue; + + // prevent aimless wandering and death by recursion + if ( depth > 200 ) + { + return 0; + } + + vtkTetra::BarycentricCoords(x, tetra->Points[0]->P, tetra->Points[1]->P, + tetra->Points[2]->P, tetra->Points[3]->P, bc); + + // find the most negative face + for ( negValue=VTK_DOUBLE_MAX, numNeg=j=0; j<4; j++ ) + { + if ( bc[j] < -0.000001 ) //if close enough that's okay + { + numNeg++; + if ( bc[j] < negValue ) + { + negValue = bc[j]; + neg = j; + } + } + } + + // if no negatives, then inside this tetra + if ( numNeg <= 0 ) + { + return tetra; + } + + // okay, march towards the most negative direction + switch (neg) + { + case 0: + tetra = tetra->Neighbors[1]; + break; + case 1: + tetra = tetra->Neighbors[2]; + break; + case 2: + tetra = tetra->Neighbors[0]; + break; + case 3: + tetra = tetra->Neighbors[3]; + break; + } + + if ( tetra ) + { + return this->WalkToTetra(tetra, x, ++depth, bc); + } + else + { + return 0; + } +} + +//------------------------------------------------------------------------ +// Use an ordered insertion process in combination with a consistent +// degenerate resolution process to generate a unique Delaunay triangulation. +void vtkOrderedTriangulator::Triangulate() +{ + OTPoint *p; + int i; + vtkIdType ptId; + + // Sort the points according to id. The last six points are left + // where they are (at the end of the list). + if ( ! this->PreSorted ) + { + if (this->UseTwoSortIds) + { + qsort((void *)this->Mesh->Points.GetPointer(0), this->NumberOfPoints, + sizeof(OTPoint), vtkSortOnTwoIds); + } + else + { + qsort((void *)this->Mesh->Points.GetPointer(0), this->NumberOfPoints, + sizeof(OTPoint), vtkSortOnIds); + } + } + + // Prepare the data structures (e.g., mesh) for an ordererd triangulation. + this->Initialize(); + + // Insert each point into the triangulation. Assign internal ids + // as we progress. + for (ptId=0, p=this->Mesh->Points.GetPointer(0); + ptId < this->NumberOfPoints; ++p, ++ptId) + { + if ( p->Type == OTPoint::NoInsert ) + { + continue; //skip this point + } + + p->InsertionId = ptId; + + // Walk to a tetrahedron (start with first one on list) + double bc[4]; + OTTetra *tetra = + this->Mesh->WalkToTetra(*(this->Mesh->Tetras.begin()),p->P,0,bc); + + if ( tetra == 0 || !this->Mesh->CreateInsertionCavity(p, tetra, bc) ) + { + vtkDebugMacro(<<"Point not in tetrahedron"); + continue; + } + + // For each face on the boundary of the cavity, create a new + // tetrahedron with the face and point. We've also got to set + // up tetrahedron face neighbors, so we'll use an edge table + // to keep track of the tetrahedron that generated the face as + // a result of sweeping an edge. + vtkIdType v1, v2; + + this->Mesh->EdgeTable->InitEdgeInsertion(this->MaximumNumberOfPoints+6,2); + this->Mesh->TetraStack.clear(); + FaceListIterator fptr; + void *tptr; + OTTetra *neiTetra; + OTFace *face; + + for (fptr=this->Mesh->CavityFaces.begin(); + fptr != this->Mesh->CavityFaces.end(); ++fptr) + { + face = *fptr; + //create a tetra (it's added to the list of tetras as a side effect) + tetra = this->Mesh->CreateTetra(p,face); + + for (i=0; i<3; ++i) + { + v1 = face->Points[i%3]->InsertionId; + v2 = face->Points[(i+1)%3]->InsertionId; + this->Mesh->EdgeTable->IsEdge(v1,v2,tptr); + if ( ! tptr ) + { + this->Mesh->EdgeTable->InsertEdge(v1,v2,tetra); + } + else + { + neiTetra = static_cast(tptr); + AssignNeighbors(tetra, neiTetra); + } + }//for three edges + }//for each face on the insertion cavity + }//for all points to be inserted + + // Final classification + this->Mesh->NumberOfTetrasClassifiedInside = this->Mesh->ClassifyTetras(); +} + + +//------------------------------------------------------------------------ +// Perform triangulation using templates (when possible). +void vtkOrderedTriangulator::TemplateTriangulate(int cellType, + int numPts, int numEdges) +{ + this->CellType = cellType; + if ( ! this->UseTemplates ) + { + this->Triangulate(); + return; + } + + this->NumberOfCellPoints = numPts; + this->NumberOfCellEdges = numEdges; + + // Sort the points according to id. + if ( ! this->PreSorted ) + { + if (this->UseTwoSortIds) + { + qsort((void *)this->Mesh->Points.GetPointer(0), this->NumberOfPoints, + sizeof(OTPoint), vtkSortOnTwoIds); + } + else + { + qsort((void *)this->Mesh->Points.GetPointer(0), this->NumberOfPoints, + sizeof(OTPoint), vtkSortOnIds); + } + } + + if ( ! this->TemplateTriangulation() ) + {//template triangulation didn't work, triangulate it and add to template cache + int preSorted = this->PreSorted; //prevents resorting + this->PreSorted = 1; + this->Triangulate(); + this->AddTemplate(); + this->PreSorted = preSorted; + } +} + +//------------------------------------------------------------------------ +// Add the tetras classified as specified to an unstructured grid. +vtkIdType vtkOrderedTriangulator::GetTetras(int classification, + vtkUnstructuredGrid *ugrid) +{ + // Create the points + // + int i; + vtkIdType numTetras=0; + PointListIterator p; + vtkPoints *points = vtkPoints::New(); + points->SetNumberOfPoints(this->NumberOfPoints); + for ( i=0, p=this->Mesh->Points.begin(); iNumberOfPoints; ++i, ++p) + { + points->SetPoint(p->InsertionId,p->X); + } + ugrid->SetPoints(points); + points->Delete(); + + ugrid->Allocate(1000); + TetraListIterator t; + OTTetra *tetra; + + // loop over all tetras getting the ones with the classification requested + vtkIdType pts[4]; + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + tetra = *t; + + if ( tetra->Type == classification || classification == OTTetra::All) + { + numTetras++; + pts[0] = tetra->Points[0]->Id; + pts[1] = tetra->Points[1]->Id; + pts[2] = tetra->Points[2]->Id; + pts[3] = tetra->Points[3]->Id; + ugrid->InsertNextCell(VTK_TETRA,4,pts); + } + }//for all tetras + + return numTetras; +} + +//------------------------------------------------------------------------ +// Add the tetras classified as specified to an unstructured grid +vtkIdType vtkOrderedTriangulator::AddTetras(int classification, + vtkCellArray *outConnectivity) +{ + TetraListIterator t; + OTTetra *tetra; + vtkIdType numTetras=0; + + // loop over all tetras getting the ones with the classification requested + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + tetra = *t; + + if ( tetra->Type == classification || classification == OTTetra::All) + { + numTetras++; + outConnectivity->InsertNextCell(4); + outConnectivity->InsertCellPoint(tetra->Points[0]->Id); + outConnectivity->InsertCellPoint(tetra->Points[1]->Id); + outConnectivity->InsertCellPoint(tetra->Points[2]->Id); + outConnectivity->InsertCellPoint(tetra->Points[3]->Id); + } + }//for all tetras + + return numTetras; +} + +//----------------------------------------------------------------------------- +// Assuming that all the inserted points come from a cell `cellId' to +// triangulate, get the tetrahedra in outConnectivity, the points in locator +// and copy point data and cell data. Return the number of added tetras. +// \pre locator_exists: locator!=0 +// \pre outConnectivity: outConnectivity!=0 +// \pre inPD_exists: inPD!=0 +// \pre outPD_exists: outPD!=0 +// \pre inCD_exists: inCD!=0 +// \pre outCD_exists: outCD!=0 +vtkIdType vtkOrderedTriangulator::AddTetras(int classification, + vtkPointLocator *locator, + vtkCellArray *outConnectivity, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + assert("pre: locator_exists" && locator!=0); + assert("pre: outConnectivity" && outConnectivity!=0); + assert("inPD_exists" && inPD!=0); + assert("pre: outPD_exists" && outPD!=0); + assert("inCD_exists" && inCD!=0); + assert("pre: outCD_exists" && outCD!=0); + + TetraListIterator t; + OTTetra *tetra; + vtkIdType result=0; + + // loop over all tetras getting the ones with the classification requested + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + tetra = *t; + + if ( tetra->Type == classification || classification == OTTetra::All) + { + // Insert the points + vtkIdType pts[4]; + + int i=0; + while(i<4) + { + if(locator->InsertUniquePoint(tetra->Points[i]->X,pts[i])) + { + outPD->CopyData(inPD,tetra->Points[i]->Id,pts[i]); + } + ++i; + } + + // Insert the connectivity + result++; + vtkIdType newCellId = outConnectivity->InsertNextCell(4,pts); + outCD->CopyData(inCD,cellId,newCellId); + } + }//for all tetras + + return result; +} +//------------------------------------------------------------------------ +// Initialize tetra traversal. Used in conjunction with GetNextTetra(). +void vtkOrderedTriangulator::InitTetraTraversal() +{ + this->Mesh->CurrentTetra = this->Mesh->Tetras.begin(); +} + +//------------------------------------------------------------------------ +// Retrieve a single tetra. Used in conjunction with InitTetraTraversal(). +// Returns 0 when the list is exhausted. +int vtkOrderedTriangulator::GetNextTetra(int classification, vtkTetra *tet, + vtkDataArray *cellScalars, + vtkDoubleArray *tetScalars) +{ + OTTetra *tetra; + int i; + + // Find the next tetra with the right classification + while ( this->Mesh->CurrentTetra != this->Mesh->Tetras.end() && + (*this->Mesh->CurrentTetra)->Type != classification && + (*this->Mesh->CurrentTetra)->Type != OTTetra::All ) + { + tetra = *(this->Mesh->CurrentTetra); + ++this->Mesh->CurrentTetra; + } + + if ( this->Mesh->CurrentTetra != this->Mesh->Tetras.end() ) + { + tetra = *(this->Mesh->CurrentTetra); + for (i=0; i<4; i++) + { + tet->PointIds->SetId(i,tetra->Points[i]->Id); + tet->Points->SetPoint(i,tetra->Points[i]->X); + tetScalars->SetTuple(i, + cellScalars->GetTuple( + tetra->Points[i]->OriginalId)); + } + ++this->Mesh->CurrentTetra; + return 1; + } + else + { + return 0; + } +} + +//------------------------------------------------------------------------ +// Add the tetras classified as specified to a list of point ids and +// point coordinates. +vtkIdType vtkOrderedTriangulator::AddTetras(int classification, + vtkIdList *ptIds, + vtkPoints *pts) +{ + TetraListIterator t; + OTTetra *tetra; + vtkIdType numTetras=0; + int i; + + // loop over all tetras getting the ones with the classification requested + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + tetra = *t; + + if ( tetra->Type == classification || classification == OTTetra::All) + { + numTetras++; + for (i=0; i<4; i++) + { + ptIds->InsertNextId(tetra->Points[i]->Id); + pts->InsertNextPoint(tetra->Points[i]->X); + } + } + }//for all tetras + + return numTetras; +} + + +//------------------------------------------------------------------------ +// Add the tetras classified as specified to an unstructured grid +vtkIdType vtkOrderedTriangulator::AddTetras(int classification, + vtkUnstructuredGrid *ugrid) + +{ + vtkIdType numTetras=0; + TetraListIterator t; + OTTetra *tetra; + + // loop over all tetras getting the ones with the classification requested + vtkIdType pts[4]; + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + tetra = *t; + + if ( tetra->Type == classification || classification == OTTetra::All) + { + numTetras++; + pts[0] = tetra->Points[0]->Id; + pts[1] = tetra->Points[1]->Id; + pts[2] = tetra->Points[2]->Id; + pts[3] = tetra->Points[3]->Id; + ugrid->InsertNextCell(VTK_TETRA,4,pts); + } + }//for all tetras + + return numTetras; +} + +//------------------------------------------------------------------------ +// Add the tetras classified as specified to a call array (connectivity list) +vtkIdType vtkOrderedTriangulator::AddTriangles(vtkCellArray *tris) +{ + vtkIdType numTris=0; + int i; + + // Loop over all tetras examining each unvisited face. Faces whose + // points are all classified "boundary" are added to the list of + // faces. + TetraListIterator t; + OTTetra *tetra; + OTFace *face = new(this->Heap) OTFace; + + // loop over all tetras getting the faces classified on the boundary + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + tetra = *t; + tetra->CurrentPointId = VTK_LARGE_INTEGER; //mark visited + for (i=0; i<4; i++) + { + if ( tetra->Neighbors[i] && + tetra->Neighbors[i]->CurrentPointId != VTK_LARGE_INTEGER && + tetra->Type != tetra->Neighbors[i]->Type ) + {//face not yet visited + tetra->GetFacePoints(i,face); + numTris++; + tris->InsertNextCell(3); + tris->InsertCellPoint(face->Points[0]->Id); + tris->InsertCellPoint(face->Points[1]->Id); + tris->InsertCellPoint(face->Points[2]->Id); + } + } + }//for all tetras + + return numTris; +} + +//------------------------------------------------------------------------ +// Add faces classified on the boundary to a cell array (connectivity list) +vtkIdType vtkOrderedTriangulator::AddTriangles(vtkIdType id, vtkCellArray *tris) +{ + vtkIdType numTris=0; + int i; + + // Loop over all tetras examining each unvisited face. Faces whose + // points are all classified "boundary" are added to the list of + // faces. + TetraListIterator t; + OTTetra *tetra; + OTFace *face = new(this->Heap) OTFace; + + // loop over all tetras getting the faces classified on the boundary + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + tetra = *t; + tetra->CurrentPointId = VTK_LARGE_INTEGER; //mark visited + for (i=0; i<4; i++) + { + if ( tetra->Neighbors[i] && + tetra->Neighbors[i]->CurrentPointId != VTK_LARGE_INTEGER && + tetra->Type != tetra->Neighbors[i]->Type ) + {//face not yet visited + tetra->GetFacePoints(i,face); + if ( face->Points[0]->Id == id || face->Points[1]->Id == id || + face->Points[2]->Id == id ) + { + numTris++; + tris->InsertNextCell(3); + tris->InsertCellPoint(face->Points[0]->Id); + tris->InsertCellPoint(face->Points[1]->Id); + tris->InsertCellPoint(face->Points[2]->Id); + } + } + } + }//for all tetras + + return numTris; +} + +//---The following code supports templates---------------------------------- +// Rather than predefining templates for the many possible triangulations, the +// ordered triangulator is used to generate the template which is then cached +// for later use. The key is that templates are uniquely characterized by a +// template id---a number representing a permutation of the sort of the +// original points. + +//---Define template id type. Note: type must be 32 bits-------------------- +// Currently the templates are set up for a maximum of eight point ids per +// cell maximum (this is due to the use of the vtkHexahedron). Any point can +// be exchanged with any of the other ids during the sort operation, so each +// exchange is represented with four bits as follows: +// +// +----+----+----+----+----+----+----+----+ +// | p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7 | +// +----+----+----+----+----+----+----+----+ +// + +//------------------------------------------------------------------------ +// Given the results of the sorting, compute an index used to specify +// a template id. +inline TemplateIDType vtkOrderedTriangulator::ComputeTemplateIndex() +{ + static TemplateIDType mask[8]={0xF0000000,0x0F000000,0x00F00000,0x000F0000, + 0x0000F000,0x00000F00,0x000000F0,0x0000000F}; + + int i; + PointListIterator p; + TemplateIDType templateID=0; + + for (p=this->Mesh->Points.begin(), i=0; iNumberOfCellPoints; ++i, ++p) + { + templateID |= ((templateID & mask[i]) | (p->OriginalId << (32-4*(i+1)))); + } + + return templateID; +} + + +//------------------------------------------------------------------------ +// If a template is missing, add it to the list of templates. +void vtkOrderedTriangulator::AddTemplate() +{ + // Find the template list for the given cell type + int templateMayBeAvailable; + TemplateList *tlist; + TemplatesIterator titer = this->Templates->find(this->CellType); + if ( titer != this->Templates->end() ) //something found + { + templateMayBeAvailable = 1; + tlist = (*titer).second; + } + else //nothing found, have to create an entry for this cell type + { + templateMayBeAvailable = 0; + tlist = new TemplateList; + (*this->Templates)[this->CellType] = tlist; + } + + // Create the template: its index and connectivity list + TemplateIDType index = this->ComputeTemplateIndex(); + + // Make sure template has not been created before + TemplateListIterator tplate = tlist->find(index); + if ( templateMayBeAvailable && tplate != tlist->end() ) + { + vtkGenericWarningMacro(<<"Template found when it should not have been"); + } + else + { + this->Mesh->NumberOfTemplates++; + + // The tetras have been classified previously. So allocate space + // and add it as a template list. + OTTemplate *otplate = new(this->TemplateHeap) + OTTemplate(this->Mesh->NumberOfTetrasClassifiedInside,this->TemplateHeap); + (*tlist)[index] = otplate; + + // Now fill in the connectivity list + int i; + TetraListIterator t; + OTTetra *tetra; + vtkIdType *clist=otplate->Tetras; + for (t=this->Mesh->Tetras.begin(); t != this->Mesh->Tetras.end(); ++t) + { + if ( (*t)->Type == OTTetra::Inside ) + { + tetra = *t; + for (i=0; i<4; i++) + { + *clist++ = tetra->Points[i]->InsertionId; + } + } + }//for all tetras + } +} + + +//------------------------------------------------------------------------ +// Use a template to create the triangulation. Return 0 if a template +// could not be used. +int vtkOrderedTriangulator::TemplateTriangulation() +{ + TemplatesIterator titer = this->Templates->find(this->CellType); + if ( titer != this->Templates->end() ) //something found + { + TemplateIDType index = this->ComputeTemplateIndex(); + TemplateList *tlist = (*titer).second; + TemplateListIterator tlistIter=tlist->find(index); + if ( tlistIter != tlist->end() ) //something found + { + int i, j; + OTTemplate *tets = (*tlistIter).second; + vtkIdType numTets = tets->NumberOfTetras; + vtkIdType *clist = tets->Tetras; + OTTetra *tetra; + for (i=0; iHeap) OTTetra(); + this->Mesh->Tetras.push_front(tetra); + tetra->Type = OTTetra::Inside; + for (j=0; j<4; j++) + { + tetra->Points[j] = this->Mesh->Points.GetPointer(*clist++); + } + }//for all tetras in template + return 1; + }//if a template found + }//if a template list for this cell type found + + return 0; +} + + +//------------------------------------------------------------------------ +void vtkOrderedTriangulator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PreSorted: " << (this->PreSorted ? "On\n" : "Off\n"); + os << indent << "UseTwoSortIds: " << (this->UseTwoSortIds ? "On\n" : "Off\n"); + os << indent << "UseTemplates: " << (this->UseTemplates ? "On\n" : "Off\n"); + os << indent << "NumberOfPoints: " << this->NumberOfPoints << endl; + +} + diff --git a/Filtering/vtkOrderedTriangulator.h b/Filtering/vtkOrderedTriangulator.h new file mode 100644 index 0000000..ef0948a --- /dev/null +++ b/Filtering/vtkOrderedTriangulator.h @@ -0,0 +1,332 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOrderedTriangulator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOrderedTriangulator - helper class to generate triangulations +// .SECTION Description +// This class is used to generate unique triangulations of points. The +// uniqueness of the triangulation is controlled by the id of the inserted +// points in combination with a Delaunay criterion. The class is designed to +// be as fast as possible (since the algorithm can be slow) and uses block +// memory allocations to support rapid triangulation generation. Also, the +// assumption behind the class is that a maximum of hundreds of points are to +// be triangulated. If you desire more robust triangulation methods use +// vtkPolygon::Triangulate(), vtkDelaunay2D, or vtkDelaunay3D. +// +// .SECTION Background +// This work is documented in the technical paper: W.J. Schroeder, B. Geveci, +// M. Malaterre. Compatible Triangulations of Spatial Decompositions. In +// Proceedings of Visualization 2004, IEEE Press October 2004. +// +// Delaunay triangulations are unique assuming a random distribution of input +// points. The 3D Delaunay criterion is as follows: the circumsphere of each +// tetrahedron contains no other points of the triangulation except for the +// four points defining the tetrahedron. In application this property is +// hard to satisfy because objects like cubes are defined by eight points all +// sharing the same circumsphere (center and radius); hence the Delaunay +// triangulation is not unique. These so-called degenerate situations are +// typically resolved by arbitrary selecting a triangulation. This code does +// something different: it resolves degenerate triangulations by modifying +// the "InCircumsphere" method to use a slightly smaller radius. Hence, +// degenerate points are always considered "out" of the circumsphere. This, +// in combination with an ordering (based on id) of the input points, +// guarantees a unique triangulation. +// +// There is another related characteristic of Delaunay triangulations. Given +// a N-dimensional Delaunay triangulation, points lying on a (N-1) dimensional +// plane also form a (N-1) Delaunay triangulation. This means for example, +// that if a 3D cell is defined by a set of (2D) planar faces, then the +// face triangulations are Delaunay. Combining this with the method to +// generate unique triangulations described previously, the triangulations +// on the face are guaranteed unique. This fact can be used to triangulate +// 3D objects in such a way to guarantee compatible face triangulations. +// This is a very useful fact for parallel processing, or performing +// operations like clipping that require compatible triangulations across +// 3D cell faces. (See vtkClipVolume for an example.) +// +// A special feature of this class is that it can generate triangulation +// templates on the fly. If template triangulation is enabled, then the +// ordered triangulator will first triangulate the cell using the slower +// ordered Delaunay approach, and then store the result as a template. +// Later, if the same cell type and cell configuration is encountered, +// then the template is reused which greatly speeds the triangulation. + +// .SECTION Caveats +// Duplicate vertices will be ignored, i.e., if two points have the same +// coordinates the second one is discarded. The implications are that the +// user of this class must prevent duplicate points. Because the precision +// of this algorithm is double, it's also a good idea to merge points +// that are within some epsilon of one another. +// +// The triangulation is performed using the parametric coordinates of the +// inserted points. Therefore the bounds (see InitTriangulation()) should +// represent the range of the parametric coordinates of the inserted points. + +// .SECTION See Also +// vtkDelaunay2D vtkDelaunay3D vtkPolygon + +#ifndef __vtkOrderedTriangulator_h +#define __vtkOrderedTriangulator_h + +#include "vtkObject.h" + +class vtkUnstructuredGrid; +class vtkCellArray; +class vtkHeap; +class vtkIdList; +class vtkPoints; +class vtkTetra; +class vtkDataArray; +class vtkDoubleArray; +struct vtkOTMesh; +struct vtkOTTemplates; +class vtkPointLocator; +class vtkPointData; +class vtkCellData; + +// Template ID's must be 32-bits. See .cxx file for more information. +#if VTK_SIZEOF_SHORT == 4 +typedef unsigned short TemplateIDType; +#elif VTK_SIZEOF_INT == 4 +typedef unsigned int TemplateIDType; +#elif VTK_SIZEOF_LONG == 4 +typedef unsigned long TemplateIDType; +#endif + +class VTK_FILTERING_EXPORT vtkOrderedTriangulator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkOrderedTriangulator,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object. + static vtkOrderedTriangulator *New(); + + // Description: + // Initialize the triangulation process. Provide a bounding box and + // the maximum number of points to be inserted. Note that since the + // triangulation is performed using parametric coordinates (see + // InsertPoint()) the bounds should be represent the range of the + // parametric coordinates inserted. + // \post no_point_inserted: GetNumberOfPoints()==0 + void InitTriangulation(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax, int numPts); + void InitTriangulation(double bounds[6], int numPts); + + // Description: + // For each point to be inserted, provide an id, a position x, parametric + // coordinate p, and whether the point is inside (type=0), outside + // (type=1), or on the boundary (type=2). You must call InitTriangulation() + // prior to invoking this method. Make sure that the number of points + // inserted does not exceed the numPts specified in + // InitTriangulation(). Also note that the "id" can be any integer and can + // be greater than numPts. It is used to create tetras (in AddTetras()) with + // the appropriate connectivity ids. The method returns an internal id that + // can be used prior to the Triangulate() method to update the type of the + // point with UpdatePointType(). (Note: the algorithm triangulated with the + // parametric coordinate p[3] and creates tetras with the global coordinate + // x[3]. The parametric coordinates and global coordinates may be the same.) + vtkIdType InsertPoint(vtkIdType id, double x[3], double p[3], int type); + vtkIdType InsertPoint(vtkIdType id, vtkIdType sortid, double x[3], + double p[3], int type); + vtkIdType InsertPoint(vtkIdType id, vtkIdType sortid, vtkIdType sortid2, + double x[3], double p[3], int type); + + // Description: + // Perform the triangulation. (Complete all calls to InsertPoint() prior + // to invoking this method.) A special version is available when templates + // should be used. + void Triangulate(); + void TemplateTriangulate(int cellType, int numPts, int numEdges); + + // Description: + // Update the point type. This is useful when the merging of nearly + // coincident points is performed. The id is the internal id returned + // from InsertPoint(). The method should be invoked prior to the + // Triangulate method. The type is specified as inside (type=0), + // outside (type=1), or on the boundary (type=2). + // \pre valid_range: internalId>=0 && internalIdGetNumberOfPoints() + void UpdatePointType(vtkIdType internalId, int type); + + // Description: + // Return the parametric coordinates of point `internalId'. + // It assumes that the point has already been inserted. + // The method should be invoked prior to the Triangulate method. + // \pre valid_range: internalId>=0 && internalIdGetNumberOfPoints() + double *GetPointPosition(vtkIdType internalId); + + // Description: + // Return the global coordinates of point `internalId'. + // It assumes that the point has already been inserted. + // The method should be invoked prior to the Triangulate method. + // \pre valid_range: internalId>=0 && internalIdGetNumberOfPoints() + double *GetPointLocation(vtkIdType internalId); + + // Description: + // Return the Id of point `internalId'. This id is the one passed in + // argument of InsertPoint. + // It assumes that the point has already been inserted. + // The method should be invoked prior to the Triangulate method. + // \pre valid_range: internalId>=0 && internalIdGetNumberOfPoints() + vtkIdType GetPointId(vtkIdType internalId); + + // Description: + // Return the number of inserted points. + vtkGetMacro(NumberOfPoints,int); + + // Description: + // If this flag is set, then the ordered triangulator will create + // and use templates for the triangulation. To use templates, the + // TemplateTriangulate() method should be called when appropriate. + // (Note: the TemplateTriangulate() method works for complete + // (interior) cells without extra points due to intersection, etc.) + vtkSetMacro(UseTemplates,int); + vtkGetMacro(UseTemplates,int); + vtkBooleanMacro(UseTemplates,int); + + // Description: + // Boolean indicates whether the points have been pre-sorted. If + // pre-sorted is enabled, the points are not sorted on point id. + // By default, presorted is off. (The point id is defined in + // InsertPoint().) + vtkSetMacro(PreSorted,int); + vtkGetMacro(PreSorted,int); + vtkBooleanMacro(PreSorted,int); + + // Description: + // Tells the triangulator that a second sort id is provided + // for each point and should also be considered when sorting. + vtkSetMacro(UseTwoSortIds,int); + vtkGetMacro(UseTwoSortIds,int); + vtkBooleanMacro(UseTwoSortIds,int); + + // Description: + // Initialize and add the tetras and points from the triangulation to the + // unstructured grid provided. New points are created and the mesh is + // allocated. (This method differs from AddTetras() in that it inserts + // points and cells; AddTetras only adds the tetra cells.) The tetrahdera + // added are of the type specified (0=inside,1=outside,2=all). Inside + // tetrahedron are those whose points are classified "inside" or on the + // "boundary." Outside tetrahedron have at least one point classified + // "outside." The method returns the number of tetrahedrahedron of the + // type requested. + vtkIdType GetTetras(int classification, vtkUnstructuredGrid *ugrid); + + // Description: + // Add the tetras to the unstructured grid provided. The unstructured + // grid is assumed to have been initialized (with Allocate()) and + // points set (with SetPoints()). The tetrahdera added are of the type + // specified (0=inside,1=outside,2=all). Inside tetrahedron are + // those whose points are classified "inside" or on the "boundary." + // Outside tetrahedron have at least one point classified "outside." + // The method returns the number of tetrahedrahedron of the type + // requested. + vtkIdType AddTetras(int classification, vtkUnstructuredGrid *ugrid); + + // Description: + // Add the tetrahedra classified (0=inside,1=outside) to the connectivity + // list provided. Inside tetrahedron are those whose points are all + // classified "inside." Outside tetrahedron have at least one point + // classified "outside." The method returns the number of tetrahedron + // of the type requested. + vtkIdType AddTetras(int classification, vtkCellArray *connectivity); + + // Description: + // Assuming that all the inserted points come from a cell `cellId' to + // triangulate, get the tetrahedra in outConnectivity, the points in locator + // and copy point data and cell data. Return the number of added tetras. + // \pre locator_exists: locator!=0 + // \pre outConnectivity: outConnectivity!=0 + // \pre inPD_exists: inPD!=0 + // \pre outPD_exists: outPD!=0 + // \pre inCD_exists: inCD!=0 + // \pre outCD_exists: outCD!=0 + vtkIdType AddTetras(int classification, + vtkPointLocator *locator, + vtkCellArray *outConnectivity, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD); + + // Description: + // Add the tetrahedra classified (0=inside,1=outside) to the list + // of ids and coordinates provided. These assume that the first four points + // form a tetrahedron, the next four the next, and so on. + vtkIdType AddTetras(int classification, vtkIdList *ptIds, vtkPoints *pts); + + // Description: + // Add the triangle faces classified (2=boundary) to the connectivity + // list provided. The method returns the number of triangles. + vtkIdType AddTriangles(vtkCellArray *connectivity); + + // Description: + // Add the triangle faces classified (2=boundary) and attached to the + // specified point id to the connectivity list provided. (The id is the + // same as that specified in InsertPoint().) + vtkIdType AddTriangles(vtkIdType id, vtkCellArray *connectivity); + + // Description: + // Methods to get one tetra at a time. Start with InitTetraTraversal() + // and then invoke GetNextTetra() until the method returns 0. + void InitTetraTraversal(); + + // Description: + // Methods to get one tetra at a time. Start with InitTetraTraversal() + // and then invoke GetNextTetra() until the method returns 0. + // cellScalars are point-centered scalars on the original cell. + // tetScalars are point-centered scalars on the tetra: the values will be + // copied from cellScalars. + // \pre tet_exists: tet!=0 + // \pre cellScalars_exists: cellScalars!=0 + // \pre tetScalars_exists: tetScalars!=0 + // \pre tetScalars_valid_size: tetScalars->GetNumberOfTuples()==4 + int GetNextTetra(int classification, vtkTetra *tet, + vtkDataArray *cellScalars, vtkDoubleArray *tetScalars); + +protected: + vtkOrderedTriangulator(); + ~vtkOrderedTriangulator(); + +private: + void Initialize(); + + vtkOTMesh *Mesh; + int NumberOfPoints; //number of points inserted + int MaximumNumberOfPoints; //maximum possible number of points to be inserted + double Bounds[6]; + int PreSorted; + int UseTwoSortIds; + vtkHeap *Heap; + double Quanta; + + int UseTemplates; + int CellType; + int NumberOfCellPoints; + int NumberOfCellEdges; + vtkHeap *TemplateHeap; + vtkOTTemplates *Templates; + int TemplateTriangulation(); + void AddTemplate(); + TemplateIDType ComputeTemplateIndex(); + +private: + vtkOrderedTriangulator(const vtkOrderedTriangulator&); // Not implemented. + void operator=(const vtkOrderedTriangulator&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkParametricSpline.cxx b/Filtering/vtkParametricSpline.cxx new file mode 100644 index 0000000..9910bba --- /dev/null +++ b/Filtering/vtkParametricSpline.cxx @@ -0,0 +1,368 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricSpline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricSpline.h" +#include "vtkObjectFactory.h" +#include "vtkCardinalSpline.h" +#include "vtkPoints.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkParametricSpline, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkParametricSpline); + +//---------------------------------------------------------------------------- +vtkParametricSpline::vtkParametricSpline() +{ + this->MinimumU = 0; + this->MaximumU = 1.0; + this->JoinU = 0; + + this->Points = NULL; + + this->XSpline = vtkCardinalSpline::New(); + this->YSpline = vtkCardinalSpline::New(); + this->ZSpline = vtkCardinalSpline::New(); + + this->Closed = 0; + this->LeftConstraint = 1; + this->LeftValue = 0.0; + this->RightConstraint = 1; + this->RightValue = 0.0; + this->ParameterizeByLength = 1; + + this->InitializeTime = 0; +} + +//---------------------------------------------------------------------------- +vtkParametricSpline::~vtkParametricSpline() +{ + if (this->Points) + { + this->Points->Delete(); + } + if (this->XSpline) + { + this->XSpline->Delete(); + } + if (this->YSpline) + { + this->YSpline->Delete(); + } + if (this->ZSpline) + { + this->ZSpline->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkParametricSpline::SetPoints(vtkPoints *pts) +{ + if ( pts != this->Points ) + { + if ( this->Points != NULL ) + { + this->Points->Delete(); + } + this->Points = pts; + if ( this->Points != NULL ) + { + this->Points->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkParametricSpline::SetXSpline(vtkSpline *s) +{ + if ( s != this->XSpline ) + { + if ( this->XSpline != NULL ) + { + this->XSpline->Delete(); + } + this->XSpline = s; + if ( this->XSpline != NULL ) + { + this->XSpline->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkParametricSpline::SetYSpline(vtkSpline *s) +{ + if ( s != this->YSpline ) + { + if ( this->YSpline != NULL ) + { + this->YSpline->Delete(); + } + this->YSpline = s; + if ( this->YSpline != NULL ) + { + this->YSpline->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkParametricSpline::SetZSpline(vtkSpline *s) +{ + if ( s != this->ZSpline ) + { + if ( this->ZSpline != NULL ) + { + this->ZSpline->Delete(); + } + this->ZSpline = s; + if ( this->ZSpline != NULL ) + { + this->ZSpline->Register(this); + } + this->Modified(); + } +} + + +//---------------------------------------------------------------------------- +void vtkParametricSpline::Evaluate(double U[3], double Pt[3], double*) +{ + // make sure everything has been set up + if ( this->InitializeTime < this->GetMTime () ) + { + if ( ! this->Initialize() ) + { + return; + } + } + + double t = (U[0] < 0.0 ? 0.0 : (U[0] > 1.0 ? 1.0 : U[0])); + if ( this->Closed ) + { + t *= this->ClosedLength; + } + else + { + t *= this->Length; + } + + // Evaluate the spline at the parameter t + Pt[0] = this->XSpline->Evaluate(t); + Pt[1] = this->YSpline->Evaluate(t); + Pt[2] = this->ZSpline->Evaluate(t); +} + +//---------------------------------------------------------------------------- +double vtkParametricSpline::EvaluateScalar(double u[3], double*, double *) +{ + // make sure everything has been set up + if ( this->InitializeTime < this->GetMTime () ) + { + if ( ! this->Initialize() ) + { + return 0.0; + } + } + + return u[0]; //simply parametric value +} + +//---------------------------------------------------------------------------- +// Configure the splines for evaluation +int vtkParametricSpline::Initialize() +{ + // Check to make sure splines are available + if ( !this->XSpline || !this->YSpline || !this->ZSpline ) + { + vtkErrorMacro("Please specify splines"); + return 0; + } + if ( !this->Points ) + { + vtkErrorMacro("Please specify points"); + return 0; + } + + // Make sure that the splines are consistent with this instance + this->XSpline->SetClosed(this->GetClosed()); + this->XSpline->SetLeftConstraint(this->GetLeftConstraint()); + this->XSpline->SetRightConstraint(this->GetRightConstraint()); + this->XSpline->SetLeftValue(this->GetLeftValue()); + this->XSpline->SetRightValue(this->GetRightValue()); + + this->YSpline->SetClosed(this->GetClosed()); + this->YSpline->SetLeftConstraint(this->GetLeftConstraint()); + this->YSpline->SetRightConstraint(this->GetRightConstraint()); + this->YSpline->SetLeftValue(this->GetLeftValue()); + this->YSpline->SetRightValue(this->GetRightValue()); + + this->ZSpline->SetClosed(this->GetClosed()); + this->ZSpline->SetLeftConstraint(this->GetLeftConstraint()); + this->ZSpline->SetRightConstraint(this->GetRightConstraint()); + this->ZSpline->SetLeftValue(this->GetLeftValue()); + this->ZSpline->SetRightValue(this->GetRightValue()); + + // Construct the splines, parameterized by length + vtkIdType i; + double xPrev[3], x[3], len; + vtkIdType npts = this->Points->GetNumberOfPoints(); + if ( npts < 2 ) + { + vtkErrorMacro("Please specify at least two points"); + return 0; + } + + if ( this->ParameterizeByLength ) + { + this->Points->GetPoint(0,xPrev); + this->Length = 0.0; + for ( i = 1; i < npts; ++i ) + { + this->Points->GetPoint(i,x); + len = sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + if ( len <= 0.0 ) + { + vtkErrorMacro("Spline must have non-coincident points"); + return 0; //failure + } + this->Length += len; + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + if ( this->Length <= 0.0 ) + { + vtkErrorMacro("Spline must have non-zero length"); + return 0; //failure + } + if ( this->Closed ) + { + this->Points->GetPoint(0,x); + this->ClosedLength = this->Length + + sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + } + } + else + { + this->Length = npts - 1; + if ( this->Closed ) + { + this->ClosedLength = npts; + } + } + + this->XSpline->RemoveAllPoints(); + this->YSpline->RemoveAllPoints(); + this->ZSpline->RemoveAllPoints(); + + // Now we insert points into the splines with the parametric coordinate + // based on (polyline) length. We keep track of the parametric coordinates + // of the points for later point interpolation. + if ( this->ParameterizeByLength ) + { + this->Points->GetPoint(0,xPrev); + for ( len = 0.0, i = 0; i < npts; ++i ) + { + this->Points->GetPoint(i,x); + len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + + this->XSpline->AddPoint(len,x[0]); + this->YSpline->AddPoint(len,x[1]); + this->ZSpline->AddPoint(len,x[2]); + + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + } + else + { + for ( i = 0; i < npts; ++i ) + { + this->Points->GetPoint(i,x); + this->XSpline->AddPoint(i,x[0]); + this->YSpline->AddPoint(i,x[1]); + this->ZSpline->AddPoint(i,x[2]); + } + } + + // Specify the parametric range that the spline can take + if ( ! this->Closed ) + { + this->XSpline->SetParametricRange(0.0,this->Length); + this->YSpline->SetParametricRange(0.0,this->Length); + this->ZSpline->SetParametricRange(0.0,this->Length); + } + else + { + this->XSpline->SetParametricRange(0.0,this->ClosedLength); + this->YSpline->SetParametricRange(0.0,this->ClosedLength); + this->ZSpline->SetParametricRange(0.0,this->ClosedLength); + } + + this->InitializeTime = this->GetMTime(); + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkParametricSpline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Points: "; + if ( this->Points ) + { + os << this->Points << "\n"; + } + else + { + os << "(none)\n"; + } + + os << indent << "X Spline: "; + if ( this->XSpline ) + { + os << this->XSpline << "\n"; + } + else + { + os << "(none)\n"; + } + os << indent << "Y Spline: "; + if ( this->YSpline ) + { + os << this->YSpline << "\n"; + } + else + { + os << "(none)\n"; + } + os << indent << "Z Spline: "; + if ( this->ZSpline ) + { + os << this->ZSpline << "\n"; + } + else + { + os << "(none)\n"; + } + + os << indent << "Closed: " << (this->Closed ? "On\n" : "Off\n"); + os << indent << "Left Constraint: " << this->LeftConstraint << "\n"; + os << indent << "Right Constraint: " << this->RightConstraint << "\n"; + os << indent << "Left Value: " << this->LeftValue << "\n"; + os << indent << "Right Value: " << this->RightValue << "\n"; + os << indent << "Parameterize by length: " + << (this->ParameterizeByLength ? "On\n" : "Off\n"); +} diff --git a/Filtering/vtkParametricSpline.h b/Filtering/vtkParametricSpline.h new file mode 100644 index 0000000..e3f327e --- /dev/null +++ b/Filtering/vtkParametricSpline.h @@ -0,0 +1,165 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricSpline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricSpline - parametric function for 1D interpolating splines +// .SECTION Description +// vtkParametricSpline is a parametric function for 1D interpolating splines. +// vtkParametricSpline maps the single parameter u into a 3D point (x,y,z) +// using three instances of interpolating splines. This family of 1D splines +// is quaranteed to be parameterized in the interval [0,1]. Attempting to +// evaluate outside this interval will cause the parameter u to be clamped in +// the range [0,1]. +// +// When constructed, this class creates instances of vtkCardinalSpline for +// each of the x-y-z coordinates. The user may choose to replace these with +// their own instances of subclasses of vtkSpline. +// +// .SECTION Caveats +// If you wish to tessellate the spline, use the class +// vtkParametricFunctionSource. +// +// .SECTION See Also +// vtkSpline vtkKochanekSpline vtkCardinalSpline + +#ifndef __vtkParametricSpline_h +#define __vtkParametricSpline_h + +class vtkSpline; +class vtkPoints; + +#include "vtkParametricFunction.h" + +class VTK_FILTERING_EXPORT vtkParametricSpline : public vtkParametricFunction +{ +public: + vtkTypeRevisionMacro(vtkParametricSpline,vtkParametricFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct the spline with the following parameters: + // MinimumU = 0, MaximumU = 1, JoinU = 0 (unless the spline is + // closed, then JoinU = 1), TwistU = 0, DerivativesSupplied = 0 + // (the other vtkParametricFunction parameters are ignored). + static vtkParametricSpline *New(); + + // Description + // Return the parametric dimension of the class. + virtual int GetDimension() {return 1;} + + // Description: + // Evaluate the spline at parametric coordinate u[0] returning + // the point coordinate Pt[3]. + virtual void Evaluate(double u[3], double Pt[3], double Du[9]); + + // Description: + // Evaluate a scalar value at parametric coordinate u[0] and Pt[3]. + // The scalar value is just the parameter u[0]. + virtual double EvaluateScalar(double u[3], double Pt[3], double Du[9]); + + // Description: + // By default, this class is constructed with three instances of + // vtkCardinalSpline (for each of the x-y-z coordinate axes). The user may + // choose to create and assign their own instances of vtkSpline. + void SetXSpline(vtkSpline*); + void SetYSpline(vtkSpline*); + void SetZSpline(vtkSpline*); + vtkGetObjectMacro(XSpline,vtkSpline); + vtkGetObjectMacro(YSpline,vtkSpline); + vtkGetObjectMacro(ZSpline,vtkSpline); + + // Description: + // Specify the list of points defining the spline. Do this by + // specifying a vtkPoints array containing the points. Note that + // the order of the points in vtkPoints is the order that the + // splines will be fit. + void SetPoints(vtkPoints*); + vtkGetObjectMacro(Points,vtkPoints); + + // Description: + // Control whether the spline is open or closed. A closed spline forms + // a continuous loop: the first and last points are the same, and + // derivatives are continuous. + vtkSetMacro(Closed,int); + vtkGetMacro(Closed,int); + vtkBooleanMacro(Closed,int); + + // Description: + // Control whether the spline is parameterized by length or by point index. + // Default is by length. + vtkSetMacro(ParameterizeByLength,int); + vtkGetMacro(ParameterizeByLength,int); + vtkBooleanMacro(ParameterizeByLength,int); + + // Description: + // Set the type of constraint of the left(right) end points. Four + // constraints are available: + // + // 0: the first derivative at left(right) most point is determined + // from the line defined from the first(last) two points. + // + // 1: the first derivative at left(right) most point is set to + // Left(Right)Value. + // + // 2: the second derivative at left(right) most point is set to + // Left(Right)Value. + // + // 3: the second derivative at left(right)most points is Left(Right)Value + // times second derivative at first interior point. + vtkSetClampMacro(LeftConstraint,int,0,3); + vtkGetMacro(LeftConstraint,int); + vtkSetClampMacro(RightConstraint,int,0,3); + vtkGetMacro(RightConstraint,int); + + // Description: + // The values of the derivative on the left and right sides. The value + // is used only if the left(right) constraint is type 1-3. + vtkSetMacro(LeftValue,double); + vtkGetMacro(LeftValue,double); + vtkSetMacro(RightValue,double); + vtkGetMacro(RightValue,double); + +protected: + vtkParametricSpline(); + ~vtkParametricSpline(); + + // Points definition + vtkPoints *Points; + + // The interpolating splines for each of the x-y-z coordinates + vtkSpline *XSpline; + vtkSpline *YSpline; + vtkSpline *ZSpline; + + // Supplemental variables + int Closed; + int LeftConstraint; + int RightConstraint; + double LeftValue; + double RightValue; + int ParameterizeByLength; + + // Initializing the spline + unsigned long InitializeTime; + int Initialize(); + + // Internal variable for managing parametric coordinates + double Length; + double ClosedLength; + +private: + vtkParametricSpline(const vtkParametricSpline&); // Not implemented. + void operator=(const vtkParametricSpline&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkPentagonalPrism.cxx b/Filtering/vtkPentagonalPrism.cxx new file mode 100644 index 0000000..9e0df3e --- /dev/null +++ b/Filtering/vtkPentagonalPrism.cxx @@ -0,0 +1,789 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPentagonalPrism.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// Thanks to Philippe Guerville who developed this class. +// Thanks to Charles Pignerol (CEA-DAM, France) who ported this class under +// VTK 4. +// Thanks to Jean Favre (CSCS, Switzerland) who contributed to integrate this +// class in VTK. +// Please address all comments to Jean Favre (jfavre at cscs.ch). + +#include "vtkPentagonalPrism.h" + +#include "vtkObjectFactory.h" +#include "vtkLine.h" +#include "vtkQuad.h" +#include "vtkPolygon.h" +#include "vtkMath.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkPentagonalPrism, "$Revision: 1.6.6.1 $"); +vtkStandardNewMacro(vtkPentagonalPrism); + +static const double VTK_DIVERGED = 1.e6; + +//---------------------------------------------------------------------------- +// Construct the prism with ten points. +vtkPentagonalPrism::vtkPentagonalPrism() +{ + int i; + this->Points->SetNumberOfPoints(10); + this->PointIds->SetNumberOfIds(10); + + for (i = 0; i < 10; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + + this->Line = vtkLine::New(); + this->Quad = vtkQuad::New(); + this->Polygon = vtkPolygon::New(); + this->Polygon->PointIds->SetNumberOfIds(5); + this->Polygon->Points->SetNumberOfPoints(5); + + for (i = 0; i < 5; i++) + { + this->Polygon->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->Polygon->PointIds->SetId(i,0); + } +} + +//---------------------------------------------------------------------------- +vtkPentagonalPrism::~vtkPentagonalPrism() +{ + this->Line->Delete(); + this->Quad->Delete(); + this->Polygon->Delete(); +} + +// +// Method to calculate parametric coordinates in an ten noded +// linear prism element from global coordinates. +// +static const int VTK_PENTA_MAX_ITERATION=10; +static const double VTK_PENTA_CONVERGED=1.e-03; + +//---------------------------------------------------------------------------- +int vtkPentagonalPrism::EvaluatePosition(double x[3], double closestPoint[3], + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[30]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.5; + + // enter iteration loop + for (iteration=converged=0; + !converged && (iteration < VTK_PENTA_MAX_ITERATION); iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<10; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+10]; + tcol[j] += pt[j] * derivs[i+20]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_PENTA_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_PENTA_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_PENTA_CONVERGED) ) + { + converged = 1; + } + + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside hexahedron + } + return 1; + } + else + { + double pc[3], w[10]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +// +// Compute iso-parametric interpolation functions +// + +// see vtkPentagonalPrismCellPCoords for V#i values: +// The general idea is that for Point #0 (V1,V1,0) the shape function should be +// 0 on the 4 other node. So expr of the line passing through points +// (x1,y1) and (x2,y2) is as follow: +// (x1-x2)*y - (y1-y2)*x - (x1*y2 - x2*y1) = 0 +// x(i):=1/2+1/2*Cos( Pi + Pi/4 + i*2*Pi/5) +// y(i):=1/2+1/2*Sin( Pi + Pi/4 + i*2*Pi/5) +// For instance EXPRA is x(2)-x(1) +// EXPRB is y(2)-y(1) (== x(4)-x(3)) +// EXPRC is x(1)*y(2)-x(2)*y(1) +// EXPRD is x(2)-x(3) (because of sign) +// EXPRE is x(2)*y(3)-x(3)*y(2) +// EXPRF is x(0)-x(4) +// EXPRG is y(4)-y(0) +// EXPRH is x(0)*y(4)-x(4)*y(0) +// EXPRN was deducted to normalize the function +#define EXPRA 0.26684892042779546; +#define EXPRB 0.52372049461429937; +#define EXPRC 0.36619991616704034; +#define EXPRD 0.41562693777745341; +#define EXPRE 0.65339106685124182; +#define EXPRF 0.091949871500910163; +#define EXPRG 0.58054864046304711; +#define EXPRH 0.098485126908190265; +#define EXPRN 9.2621670111997307; + +void vtkPentagonalPrism::InterpolationFunctions(double pcoords[3], double sf[10]) +{ + double r, s, t; + r = pcoords[0]; + s = pcoords[1]; + t = pcoords[2]; + + const double a = EXPRA; + const double b = EXPRB; + const double c = EXPRC; + const double d = EXPRD; + const double e = EXPRE; + const double f = EXPRF; + const double g = EXPRG; + const double h = EXPRH; + const double n = EXPRN; + + //First pentagon + sf[0] = -n*(-a*s + b*r - c)*( b*s - a*r - c)*(t - 1.0); + sf[1] = n*( d*s + d*r - e)*( f*s + g*r - h)*(t - 1.0); + sf[2] = -n*( b*s - a*r - c)*(-g*s - f*r + h)*(t - 1.0); + sf[3] = n*(-a*s + b*r - c)*( f*s + g*r - h)*(t - 1.0); + sf[4] = -n*(-g*s - f*r + h)*( d*s + d*r - e)*(t - 1.0); + + //Second pentagon + sf[5] = n*(-a*s + b*r - c)*( b*s - a*r - c)*(t - 0.0); + sf[6] = -n*( d*s + d*r - e)*( f*s + g*r - h)*(t - 0.0); + sf[7] = n*( b*s - a*r - c)*(-g*s - f*r + h)*(t - 0.0); + sf[8] = -n*(-a*s + b*r - c)*( f*s + g*r - h)*(t - 0.0); + //sf[9] = n*(-g*s - f*r + h)*( d*s + d*r - e)*(t - 0.0); + sf[9] = 1. - (sf[0]+sf[1]+sf[2]+sf[3]+sf[4]+sf[5]+sf[6]+sf[7]+sf[8]); +} + +//---------------------------------------------------------------------------- +// +// Compute iso-parametric interpolation derivatives +// +void vtkPentagonalPrism::InterpolationDerivs(double pcoords[3], double derivs[30]) +{ + double r, s, t; + r = pcoords[0]; + s = pcoords[1]; + t = pcoords[2]; + + const double a = EXPRA; + const double b = EXPRB; + const double c = EXPRC; + const double d = EXPRD; + const double e = EXPRE; + const double f = EXPRF; + const double g = EXPRG; + const double h = EXPRH; + const double n = EXPRN; + + // r-derivatives + //First pentagon + derivs[0] = -n*(-2*a*b*r + (a*a + b*b)*s + a*c - b*c)*(t - 1.0); + derivs[1] = n*( 2*d*g*r + d*(f + g)*s - d*h - e*g)*(t - 1.0); + derivs[2] = -n*( 2*a*f*r + (a*g - b*f)*s - a*h + c*f)*(t - 1.0); + derivs[3] = n*( 2*b*g*r + (b*f - a*g)*s - b*h - c*g)*(t - 1.0); + derivs[4] = -n*(-2*d*f*r - d*(f + g)*s + d*h + e*f)*(t - 1.0); + //Second pentagon + derivs[5] = n*(-2*a*b*r + (a*a + b*b)*s + a*c - b*c)*(t - 0.0); + derivs[6] = -n*( 2*d*g*r + d*(f + g)*s - d*h - e*g)*(t - 0.0); + derivs[7] = n*( 2*a*f*r + (a*g - b*f)*s - a*h + c*f)*(t - 0.0); + derivs[8] = -n*( 2*b*g*r + (b*f - a*g)*s - b*h - c*g)*(t - 0.0); + //derivs[9] = n*(-2*d*f*r - d*(f + g)*s + d*h + e*f)*(t - 0.0); + derivs[9] = -(derivs[0]+derivs[1]+derivs[2]+derivs[3]+derivs[4]+derivs[5] + +derivs[6]+derivs[7]+derivs[8]); + + // s-derivatives + //First pentagon + derivs[10] = -n*(-2*a*b*s + (a*a + b*b)*r + a*c - b*c)*(t - 1.0); + derivs[11] = n*( 2*d*f*s + d*(f + g)*r - d*h - e*f)*(t - 1.0); + derivs[12] = -n*(-2*b*g*s + (a*g - b*f)*r + b*h + c*g)*(t - 1.0); + derivs[13] = n*(-2*a*f*s + (b*f - a*g)*r + a*h - c*f)*(t - 1.0); + derivs[14] = -n*(-2*d*g*s - d*(f + g)*r + d*h + e*g)*(t - 1.0); + //Second pentagon + derivs[15] = n*(-2*a*b*s + (a*a + b*b)*r + a*c - b*c)*(t - 0.0); + derivs[16] = -n*( 2*d*f*s + d*(f + g)*r - d*h - e*f)*(t - 0.0); + derivs[17] = n*(-2*b*g*s + (a*g - b*f)*r + b*h + c*g)*(t - 0.0); + derivs[18] = -n*(-2*a*f*s + (b*f - a*g)*r + a*h - c*f)*(t - 0.0); + //derivs[19] = n*(-2*d*g*s - d*(f + g)*r + d*h + e*g)*(t - 0.0); + derivs[19] = -(derivs[10]+derivs[11]+derivs[12]+derivs[13]+derivs[14]+derivs[15] + +derivs[16]+derivs[17]+derivs[18]); + + // t-derivatives + //First pentagon + derivs[20] = -n*(-a*s + b*r - c)*( b*s - a*r - c); + derivs[21] = n*( d*s + d*r - e)*( f*s + g*r - h); + derivs[22] = -n*( b*s - a*r - c)*(-g*s - f*r + h); + derivs[23] = n*(-a*s + b*r - c)*( f*s + g*r - h); + derivs[24] = -n*(-g*s - f*r + h)*( d*s + d*r - e); + //Second pentagon + derivs[25] = n*(-a*s + b*r - c)*( b*s - a*r - c); + derivs[26] = -n*( d*s + d*r - e)*( f*s + g*r - h); + derivs[27] = n*( b*s - a*r - c)*(-g*s - f*r + h); + derivs[28] = -n*(-a*s + b*r - c)*( f*s + g*r - h); + //derivs[29] = n*(-g*s - f*r + h)*( d*s + d*r - e); + derivs[29] = -(derivs[20]+derivs[21]+derivs[22]+derivs[23]+derivs[24]+derivs[25] + +derivs[26]+derivs[27]+derivs[28]); +} + +//---------------------------------------------------------------------------- +void vtkPentagonalPrism::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i = 0; i < 10; i++) + { + this->Points->GetPoint(i, pt); + for (j = 0; j < 3; j++) + { + x[j] += pt [j] * weights [i]; + } + } +} +static int edges[15][2] = { {0,1}, {1,2}, {2,3}, + {3,4}, {4,0}, {5,6}, + {6,7}, {7,8}, {8,9}, + {9,5}, {0,5}, {1,6}, + {2,7}, {3,8}, {4,9} }; + +static int faces[7][5] = { {0,4,3,2,1}, {5,6,7,8,9}, + {0,1,6,5,-1}, {1,2,7,6,-1}, + {2,3,8,7,-1}, {3,4,9,8,-1}, + {4,0,5,9,-1} }; + +#define VTK_MAX(a,b) (((a)>(b))?(a):(b)) +#define VTK_MIN(a,b) (((a)<(b))?(a):(b)) + +//---------------------------------------------------------------------------- +// Returns the closest face to the point specified. Closeness is measured +// parametrically. +int vtkPentagonalPrism::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + // load coordinates + double *points = this->GetParametricCoords(); + for(int i=0;i<5;i++) + { + this->Polygon->PointIds->SetId(i, i); + this->Polygon->Points->SetPoint(i, &points[3*i]); + } + + this->Polygon->CellBoundary( subId, pcoords, pts); + + int min = VTK_MIN(pts->GetId( 0 ), pts->GetId( 1 )); + int max = VTK_MAX(pts->GetId( 0 ), pts->GetId( 1 )); + + //Base on the edge find the quad that correspond: + int index; + if( (index = (max - min)) > 1) + { + index = 6; + } + else + { + index += min + 1; + } + + double a[3], b[3], u[3], v[3]; + this->Polygon->Points->GetPoint(pts->GetId( 0 ), a); + this->Polygon->Points->GetPoint(pts->GetId( 1 ), b); + u[0] = b[0] - a[0]; + u[1] = b[1] - a[1]; + v[0] = pcoords[0] - a[0]; + v[1] = pcoords[1] - a[1]; + + double dot = vtkMath::Dot2D(v, u); + double uNorm = vtkMath::Norm2D( u ); + if (uNorm) + { + dot /= uNorm; + } + dot = (v[0]*v[0] + v[1]*v[1]) - dot*dot; + // mathematically dot must be >= zero but, suprise suprise, it can actually + // be negative + if (dot > 0) + { + dot = sqrt( dot ); + } + else + { + dot = 0; + } + int *verts; + + if(pcoords[2] < 0.5) + { + //could be closer to face 1 + //compare that distance to the distance to the quad. + + if(dot < pcoords[2]) + { + //We are closer to the quad face + verts = faces[index]; + for(int i=0; i<4; i++) + { + pts->InsertId(i, verts[i]); + } + } + else + { + //we are closer to the penta face 1 + for(int i=0; i<5; i++) + { + pts->InsertId(i, faces[0][i]); + } + } + } + else + { + //could be closer to face 2 + //compare that distance to the distance to the quad. + + if(dot < (1. - pcoords[2]) ) + { + //We are closer to the quad face + verts = faces[index]; + for(int i=0; i<4; i++) + { + pts->InsertId(i, verts[i]); + } + } + else + { + //we are closer to the penta face 2 + for(int i=0; i<5; i++) + { + pts->InsertId(i, faces[1][i]); + } + } + } + + // determine whether point is inside of hexagon + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 || + pcoords[2] < 0.0 || pcoords[2] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +int *vtkPentagonalPrism::GetEdgeArray(int edgeId) +{ + return edges[edgeId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkPentagonalPrism::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} +//---------------------------------------------------------------------------- +int *vtkPentagonalPrism::GetFaceArray(int faceId) +{ + return faces[faceId]; +} +//---------------------------------------------------------------------------- +vtkCell *vtkPentagonalPrism::GetFace(int faceId) +{ + int *verts; + + verts = faces[faceId]; + + if ( verts[4] != -1 ) // polys cell + { + // load point id's + this->Polygon->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Polygon->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Polygon->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + this->Polygon->PointIds->SetId(3,this->PointIds->GetId(verts[3])); + this->Polygon->PointIds->SetId(4,this->PointIds->GetId(verts[4])); + + // load coordinates + this->Polygon->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Polygon->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Polygon->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + this->Polygon->Points->SetPoint(3,this->Points->GetPoint(verts[3])); + this->Polygon->Points->SetPoint(4,this->Points->GetPoint(verts[4])); + + return this->Polygon; + } + else + { + // load point id's + this->Quad->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Quad->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Quad->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + this->Quad->PointIds->SetId(3,this->PointIds->GetId(verts[3])); + + // load coordinates + this->Quad->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Quad->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Quad->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + this->Quad->Points->SetPoint(3,this->Points->GetPoint(verts[3])); + + return this->Quad; + } +} +//---------------------------------------------------------------------------- +// +// Intersect prism faces against line. Each prism face is a quadrilateral. +// +int vtkPentagonalPrism::IntersectWithLine(double p1[3], double p2[3], double tol, + double &t, double x[3], double pcoords[3], + int& subId) +{ + int intersection=0; + double pt1[3], pt2[3], pt3[3], pt4[3], pt5[3]; + double tTemp; + double pc[3], xTemp[3], dist2, weights[10]; + int faceNum; + + t = VTK_DOUBLE_MAX; + + //first intersect the penta faces + for (faceNum=0; faceNum<2; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + this->Points->GetPoint(faces[faceNum][3], pt4); + this->Points->GetPoint(faces[faceNum][4], pt5); + + this->Polygon->Points->SetPoint(0,pt1); + this->Polygon->Points->SetPoint(1,pt2); + this->Polygon->Points->SetPoint(2,pt3); + this->Polygon->Points->SetPoint(3,pt4); + this->Polygon->Points->SetPoint(4,pt5); + + if ( this->Polygon->IntersectWithLine(p1, p2, tol, tTemp, xTemp, + pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 1: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 1.0; + break; + } + } + } + } + + //now intersect the quad faces + for (faceNum=2; faceNum<7; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + this->Points->GetPoint(faces[faceNum][3], pt4); + + this->Quad->Points->SetPoint(0,pt1); + this->Quad->Points->SetPoint(1,pt2); + this->Quad->Points->SetPoint(2,pt3); + this->Quad->Points->SetPoint(3,pt4); + + if ( this->Quad->IntersectWithLine(p1, p2, tol, tTemp, xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + this->EvaluatePosition(x, xTemp, subId, pcoords, dist2, weights); + } + } + } + + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkPentagonalPrism::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, vtkPoints *pts) +{ + ptIds->Reset(); + pts->Reset(); + + for ( int i=0; i < 4; i++ ) + { + ptIds->InsertId(i,this->PointIds->GetId(i)); + pts->InsertPoint(i,this->Points->GetPoint(i)); + } + + return 1; +} +//---------------------------------------------------------------------------- +// +// Compute derivatives in x-y-z directions. Use chain rule in combination +// with interpolation function derivatives. +// +void vtkPentagonalPrism::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[30], sum[3]; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 10; i++) //loop over interp. function derivatives + { + sum[0] += functionDerivs[i] * values[dim*i + k]; + sum[1] += functionDerivs[10 + i] * values[dim*i + k]; + sum[2] += functionDerivs[20 + i] * values[dim*i + k]; + } + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. +void vtkPentagonalPrism::JacobianInverse(double pcoords[3], double **inverse, + double derivs[24]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords, derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 10; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[10 + j]; + m2[i] += x[i] * derivs[20 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } + +} + +//---------------------------------------------------------------------------- +void vtkPentagonalPrism::GetEdgePoints (int edgeId, int *&pts) +{ + pts = this->GetEdgeArray(edgeId); +} + +//---------------------------------------------------------------------------- +void vtkPentagonalPrism::GetFacePoints (int faceId, int *&pts) +{ + pts = this->GetFaceArray(faceId); +} + +// How to find the points for the pentagon: +// The points for the iso parametric pentagon have to be properly chosen so that +// the inverse Jacobian is defined. +// To be regular the points have to on the circle, center (1/2,1/2) with radius +// sqrt(2)/2 +// Then since there is an odd number of points they have to be simmetric +// to the first bisector +// Thus I pick the first point to be on this dividing line. +// We can then express point i (0, 4) to be: +// Vi_x = CenterOfCircle + 1/2 ( cos( pi + pi/4 + i*2*pi/5) ) +// Vi_y = CenterOfCircle + 1/2 ( sin( pi + pi/4 + i*2*pi/5) ) + +#define V1 0.14644660940672624 +#define V2 0.72699524986977337 +#define V3 0.054496737905816071 +#define V4 0.99384417029756889 +#define V5 0.57821723252011548 + +static double vtkPentagonalPrismCellPCoords[30] = { +V1 , V1 , 0.0, +V2 , V3 , 0.0, +V4 , V5 , 0.0, +V5 , V4 , 0.0, +V3 , V2 , 0.0, +V1 , V1 , 1.0, +V2 , V3 , 1.0, +V4 , V5 , 1.0, +V5 , V4 , 1.0, +V3 , V2 , 1.0}; + +//---------------------------------------------------------------------------- +double *vtkPentagonalPrism::GetParametricCoords() +{ + return vtkPentagonalPrismCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkPentagonalPrism::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Quad:\n"; + this->Quad->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Polygon:\n"; + this->Polygon->PrintSelf(os,indent.GetNextIndent()); +} + diff --git a/Filtering/vtkPentagonalPrism.h b/Filtering/vtkPentagonalPrism.h new file mode 100644 index 0000000..e5c8c22 --- /dev/null +++ b/Filtering/vtkPentagonalPrism.h @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPentagonalPrism.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPentagonalPrism - a 3D cell that represents a prism with +// pentagonal base +// .SECTION Description +// vtkPentagonalPrism is a concrete implementation of vtkCell to represent a +// linear 3D prism with pentagonal base. Such prism is defined by the ten points (0-9) +// where (0,1,2,3,4) is the base of the prism which, using the right hand +// rule, forms a pentagon whose normal points is in the direction of the +// opposite face (5,6,7,8,9). + +// .SECTION Thanks +// Thanks to Philippe Guerville who developed this class. +// Thanks to Charles Pignerol (CEA-DAM, France) who ported this class under +// VTK 4. +// Thanks to Jean Favre (CSCS, Switzerland) who contributed to integrate this +// class in VTK. +// Please address all comments to Jean Favre (jfavre at cscs.ch). + +#ifndef __vtkPentagonalPrism_h +#define __vtkPentagonalPrism_h + +#include "vtkCell3D.h" + +class vtkLine; +class vtkPolygon; +class vtkQuad; + +class VTK_FILTERING_EXPORT vtkPentagonalPrism : public vtkCell3D +{ +public: + static vtkPentagonalPrism *New(); + vtkTypeRevisionMacro(vtkPentagonalPrism,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int edgeId, int* &pts); + virtual void GetFacePoints(int faceId, int* &pts); + + // Description: + // See the vtkCell3D API for descriptions of these methods. + int GetCellType() {return VTK_PENTAGONAL_PRISM;}; + int GetCellDimension() {return 3;}; + int GetNumberOfEdges() {return 15;}; + int GetNumberOfFaces() {return 7;}; + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + double *GetParametricCoords(); + + // Description: + // Return the center of the wedge in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Pentagonal prism specific + static void InterpolationFunctions(double pcoords[3], double weights[10]); + static void InterpolationDerivs(double pcoords[3], double derivs[30]); + static int *GetEdgeArray(int edgeId); + static int *GetFaceArray(int faceId); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. + void JacobianInverse(double pcoords[3], double **inverse, double derivs[30]); + +protected: + vtkPentagonalPrism(); + ~vtkPentagonalPrism(); + + vtkLine *Line; + vtkQuad *Quad; + vtkPolygon *Polygon; + +private: + vtkPentagonalPrism(const vtkPentagonalPrism&); // Not implemented. + void operator=(const vtkPentagonalPrism&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkPentagonalPrism::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.5; + pcoords[2] = 0.5; + + return 0; +} +#endif + + diff --git a/Filtering/vtkPerlinNoise.cxx b/Filtering/vtkPerlinNoise.cxx new file mode 100644 index 0000000..944bb5b --- /dev/null +++ b/Filtering/vtkPerlinNoise.cxx @@ -0,0 +1,146 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPerlinNoise.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPerlinNoise.h" +#include "vtkObjectFactory.h" +#include + +vtkCxxRevisionMacro(vtkPerlinNoise, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkPerlinNoise); + +// These functions are from Greg Ward's recursive implementation in +// Graphics Gems II. I've kept the names the same for instructional +// purposes, and only changed things where optimizations could be made. + +static double hermite(double p0, double p1, + double r0, double r1, double t) +{ + double tt = t*t; + + return (p0*((2.0*t - 3.0)*tt + 1.0) + + p1*(-2.0*t + 3.0)*tt + + r0*((t-2.0)*t+1.0)*t + + r1*(t-1.0)*tt); +} + +// assumes 32 bit ints, but so it seems does VTK +static double frand(int s) +{ + s = (s<<13) ^ s; + s = (s*(s*s*15731 + 789221)+1376312589)&VTK_INT_MAX; + + return 1.0 - double(s)/(VTK_INT_MAX/2 + 1); +} + +static void rand3abcd(int x, int y, int z, double outv[4]) +{ + outv[0] = frand(67*x + 59*y + 71*z); + outv[1] = frand(73*x + 79*y + 83*z); + outv[2] = frand(89*x + 97*y + 101*z); + outv[3] = frand(103*x + 107*y + 109*z); +} + +static void interpolate(double f[4], int i, int n, + int xlim[3][2], double xarg[2]) +{ + double f0[4], f1[4]; + + if (n == 0) + { + rand3abcd(xlim[0][i&1], xlim[1][(i>>1) & 1], xlim[2][i>>2], f); + return; + } + n--; + interpolate(f0, i, n, xlim, xarg); + interpolate(f1, i | (1<Frequency[0] = 1.0; + this->Frequency[1] = 1.0; + this->Frequency[2] = 1.0; + + this->Phase[0] = 0.0; + this->Phase[1] = 0.0; + this->Phase[2] = 0.0; + + this->Amplitude = 1.0; +} + +double vtkPerlinNoise::EvaluateFunction(double x[3]) +{ + double xd[3]; + double noise[4]; + + xd[0] = x[0]*this->Frequency[0] - this->Phase[0]*2.0; + xd[1] = x[1]*this->Frequency[1] - this->Phase[1]*2.0; + xd[2] = x[2]*this->Frequency[2] - this->Phase[2]*2.0; + perlinNoise(xd, noise); + return noise[3]*this->Amplitude; +} + +// Evaluate PerlinNoise gradient. +void vtkPerlinNoise::EvaluateGradient(double* vtkNotUsed(x), // Was x[3] + double n[3]) +{ + // contrary to the paper, the vector computed as a byproduct of + // the Perlin Noise computation isn't a gradient; it's a tangent. + // Doing this right will take some work. + n[0] = 0.0; + n[1] = 0.0; + n[2] = 0.0; +} + +void vtkPerlinNoise::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Amplitude: " << this->Amplitude << "\n"; + os << indent << "Frequency: (" + << this->Frequency[0] << ", " + << this->Frequency[1] << ", " + << this->Frequency[2] << ")\n"; + + os << indent << "Phase: (" + << this->Phase[0] << ", " + << this->Phase[1] << ", " + << this->Phase[2] << ")\n"; +} diff --git a/Filtering/vtkPerlinNoise.h b/Filtering/vtkPerlinNoise.h new file mode 100644 index 0000000..b4836b8 --- /dev/null +++ b/Filtering/vtkPerlinNoise.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPerlinNoise.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPerlinNoise - an implicit function that implements Perlin noise +// .SECTION Description +// vtkPerlinNoise computes a Perlin noise field as an implicit function. +// vtkPerlinNoise is a concrete implementation of vtkImplicitFunction. +// Perlin noise, originally described by Ken Perlin, is a non-periodic and +// continuous noise function useful for modeling real-world objects. +// +// The amplitude and frequency of the noise pattern are adjustable. This +// implementation of Perlin noise is derived closely from Greg Ward's version +// in Graphics Gems II. + +// .SECTION See Also +// vtkImplicitFunction + +#ifndef __vtkPerlinNoise_h +#define __vtkPerlinNoise_h + +#include "vtkImplicitFunction.h" + +class VTK_FILTERING_EXPORT vtkPerlinNoise : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkPerlinNoise,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Instantiate the class. + static vtkPerlinNoise *New(); + + // Description: + // Evaluate PerlinNoise function. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description: + // Evaluate PerlinNoise gradient. Currently, the method returns a 0 + // gradient. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Set/get the frequency, or physical scale, of the noise function + // (higher is finer scale). The frequency can be adjusted per axis, or + // the same for all axes. + vtkSetVector3Macro(Frequency,double); + vtkGetVectorMacro(Frequency,double,3); + + // Description: + // Set/get the phase of the noise function. This parameter can be used to + // shift the noise function within space (perhaps to avoid a beat with a + // noise pattern at another scale). Phase tends to repeat about every + // unit, so a phase of 0.5 is a half-cycle shift. + vtkSetVector3Macro(Phase,double); + vtkGetVectorMacro(Phase,double,3); + + // Description: + // Set/get the amplitude of the noise function. By default, the amplitude + // is 1. + vtkSetMacro(Amplitude,double); + vtkGetMacro(Amplitude,double); + +protected: + vtkPerlinNoise(); + ~vtkPerlinNoise() {} + + double Frequency[3]; + double Phase[3]; + double Amplitude; + +private: + vtkPerlinNoise(const vtkPerlinNoise&); // Not implemented + void operator=(const vtkPerlinNoise&); // Not implemented +}; + +#endif diff --git a/Filtering/vtkPiecewiseFunction.cxx b/Filtering/vtkPiecewiseFunction.cxx new file mode 100644 index 0000000..070a960 --- /dev/null +++ b/Filtering/vtkPiecewiseFunction.cxx @@ -0,0 +1,902 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPiecewiseFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPiecewiseFunction.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPiecewiseFunction, "$Revision: 1.41.8.1 $"); +vtkStandardNewMacro(vtkPiecewiseFunction); + +// Construct a new vtkPiecewiseFunction with default values +vtkPiecewiseFunction::vtkPiecewiseFunction() +{ + this->ArraySize = 64; + this->Clamping = 1; + this->Function = new double[this->ArraySize*2]; + this->FunctionSize = 0; + this->FunctionRange[0] = 0; + this->FunctionRange[1] = 0; + + for (int i=0; i < this->ArraySize*2; i++) + { + this->Function[i] = 0.0; + } +} + +// Destruct a vtkPiecewiseFunction +vtkPiecewiseFunction::~vtkPiecewiseFunction() +{ + if( this->Function ) + { + delete [] this->Function; + } +} + +void vtkPiecewiseFunction::DeepCopy( vtkDataObject *o ) +{ + vtkPiecewiseFunction *f = vtkPiecewiseFunction::SafeDownCast(o); + + if (f != NULL) + { + this->ArraySize = f->ArraySize; + this->Clamping = f->Clamping; + this->FunctionSize = f->FunctionSize; + memcpy( this->FunctionRange, f->FunctionRange, 2*sizeof(double) ); + if ( this->ArraySize > 0 ) + { + delete [] this->Function; + this->Function = new double[this->ArraySize*2]; + memcpy( this->Function, f->Function, this->ArraySize*2*sizeof(double) ); + } + + this->Modified(); + } + + // Do the superclass + this->vtkDataObject::DeepCopy(o); +} + +void vtkPiecewiseFunction::ShallowCopy( vtkDataObject *o ) +{ + vtkPiecewiseFunction *f = vtkPiecewiseFunction::SafeDownCast(o); + + if (f != NULL) + { + this->ArraySize = f->ArraySize; + this->Clamping = f->Clamping; + this->Function = new double[this->ArraySize*2]; + this->FunctionSize = f->FunctionSize; + memcpy( this->FunctionRange, f->FunctionRange, 2*sizeof(double) ); + memcpy( this->Function, f->Function, this->ArraySize*2*sizeof(double) ); + } + + // Do the superclass + this->vtkDataObject::ShallowCopy(o); +} + +void vtkPiecewiseFunction::Initialize() +{ + if ( this->Function) + { + delete [] this->Function; + } + + this->ArraySize = 64; + this->Clamping = 1; + this->Function = new double[this->ArraySize*2]; + this->FunctionSize = 0; + this->FunctionRange[0] = 0; + this->FunctionRange[1] = 0; + + for (int i=0; i < this->ArraySize*2; i++) + { + this->Function[i] = 0.0; + } +} + + +// Return the number of points which specify this function +int vtkPiecewiseFunction::GetSize() +{ + return this->FunctionSize; +} + +// Return the type of function stored in object: +// Function Types: +// 0 : Constant (No change in slope between end points) +// 1 : NonDecreasing (Always increasing or zero slope) +// 2 : NonIncreasing (Always decreasing or zero slope) +// 3 : Varied (Contains both decreasing and increasing slopes) +// 4 : Unknown (Error condition) +// +const char *vtkPiecewiseFunction::GetType() +{ + int i; + double value; + double prev_value = 0.0; + int function_type; + + function_type = 0; + + if( this->FunctionSize ) + { + prev_value = this->Function[1]; + } + + for( i=1; i < this->FunctionSize; i++ ) + { + value = this->Function[(2*i+1)]; + + // Do not change the function type if equal + if( value != prev_value ) + { + if( value > prev_value ) + { + switch( function_type ) + { + case 0: + case 1: + function_type = 1; // NonDecreasing + break; + case 2: + function_type = 3; // Varied + break; + } + } + else // value < prev_value + { + switch( function_type ) + { + case 0: + case 2: + function_type = 2; // NonIncreasing + break; + case 1: + function_type = 3; // Varied + break; + } + } + } + + prev_value = value; + + // Exit loop if we find a Varied function + if( function_type == 3 ) + { + break; + } + } + + switch( function_type ) + { + case 0: + return "Constant"; + case 1: + return "NonDecreasing"; + case 2: + return "NonIncreasing"; + case 3: + return "Varied"; + } + + return "Unknown"; +} + + +// Returns the first point location which starts a non-zero segment of the +// function. Note that the value at this point may be zero. +double vtkPiecewiseFunction::GetFirstNonZeroValue() +{ + int i; + int all_zero = 1; + double x = 0.0; + + // Check if no points specified + if( this->FunctionSize == 0 ) + { + return 0; + } + + for( i=0; i < this->FunctionSize; i++ ) + { + if( this->Function[(2*i+1)] != 0.0 ) + { + x = this->Function[(2*i)]; + all_zero = 0; + break; + } + } + + // If every specified point has a zero value then return the first points + // position + if( all_zero ) + { + x = this->Function[0]; + } + else // A point was found with a non-zero value + { + if( i > 0 ) + // Return the value of the point that precedes this one + { + x = this->Function[2*(i-1)]; + } + else + // If this is the first point in the function, return its value + { + x = this->Function[0]; + } + } + + return x; +} + +// Adds a point to the function. If a duplicate point is inserted +// then the function value at that location is set to the new value. +int vtkPiecewiseFunction::AddPoint( double x, double val ) +{ + return this->InsertPoint( x, val ); +} + +// Adds a point to the function and returns the array index of the point. +int vtkPiecewiseFunction::InsertPoint( double x, double val ) +{ + int point_index; + int i; + + // Increase function size if we exceed array bound + if( (this->FunctionSize*2) >= this->ArraySize ) + { + this->IncreaseArraySize(); + } + + // Insert the first point + if( this->FunctionSize == 0 ) + { + // Set the point in the function + this->Function[0] = x; + this->Function[1] = val; + this->FunctionSize = 1; + + // Update function range + this->FunctionRange[0] = x; + this->FunctionRange[1] = x; + + point_index = 0; + } + else // Insert a point inside list + { + i = 0; + + // Find insertion index + while( (i < this->FunctionSize) && (this->Function[(i*2)] <= x) ) + { + // Check for duplicate entries + // Overwrite value if found + if( x == this->Function[(i*2)] ) + { + if (this->Function[(i*2 + 1)] != val) + { + this->Function[(i*2 + 1)] = val; + this->Modified(); + } + return i; + } + + // Move to next point + i++; + } + + this->FunctionSize++; + + // Move points down one element + this->MovePoints( i, 1 ); + + // Insert new point at index + this->Function[(2*i)] = x; + this->Function[(2*i+1)] = val; + point_index = i; + + // Update function range + if( x < this->FunctionRange[0] ) + { + this->FunctionRange[0] = x; + } + if( x > this->FunctionRange[1] ) + { + this->FunctionRange[1] = x; + } + } + + this->Modified(); + + return point_index; +} + +// Moves all points to the right of index down or up by one index value +// depending on the down flag. Assumes that memory for move is already +// allocated. +void vtkPiecewiseFunction::MovePoints( int index, int down ) +{ + int i; + + double swap1_x, swap1_y; + double swap2_x, swap2_y; + + i = index; + + // Moving down + if( down ) + { + // If it is the last point we don't need to move anything + if ( (i+1) < this->FunctionSize ) + { + // Move points down (i+1) = i + swap1_x = this->Function[(2*i)]; + swap1_y = this->Function[(2*i+1)]; + + i = i + 1; + + // Move following points down + while( i < this->FunctionSize ) + { + swap2_x = this->Function[(2*i)]; + swap2_y = this->Function[(2*i+1)]; + + this->Function[(2*i)] = swap1_x; + this->Function[(2*i+1)] = swap1_y; + + swap1_x = swap2_x; + swap1_y = swap2_y; + + i++; + } + } + } + // Moving up + else + { + // Move points up (i = i+1) + // This destroys values at index i + while( i < (this->FunctionSize-1) ) + { + this->Function[(2*i)] = this->Function[(2*(i+1))]; + this->Function[(2*i+1)] = this->Function[(2*(i+1)+1)]; + i++; + } + } +} + +// Removes a point from the function. If no point is found then function +// remains the same. +int vtkPiecewiseFunction::RemovePoint( double x ) +{ + int i; + double x1; + + if( this->FunctionSize ) + { + i = 0; + x1 = this->Function[0]; + + // Locate the point in the array + while( (x1 != x) && (i < this->FunctionSize) ) + { + // Move to next point + i++; + x1 = this->Function[(i*2)]; + } + + // Remove the point + if( i < this->FunctionSize ) + { + this->MovePoints( i, 0 ); + + this->FunctionSize--; + + if (this->FunctionSize > 0) + { + this->FunctionRange[0] = this->Function[0]; + this->FunctionRange[1] = this->Function[2*(this->FunctionSize-1)]; + } + else + { + this->FunctionRange[0] = this->FunctionRange[1] = 0.0; + } + this->Modified(); + return i; + } + } + return -1; +} + +// Removes all points from the function. +void vtkPiecewiseFunction::RemoveAllPoints() +{ + if (!this->FunctionSize) + { + return; + } + this->FunctionSize = 0; + this->FunctionRange[0] = 0; + this->FunctionRange[1] = 0; + this->Modified(); +} + +// Add in end points of line and remove any points between them +void vtkPiecewiseFunction::AddSegment( double x1, double val1, + double x2, double val2 ) +{ + int index1, index2; + int swap; + int distance; + int i; + + // Insert the two endpoints + index1 = this->InsertPoint( x1, val1 ); + index2 = this->InsertPoint( x2, val2 ); + + if( index1 == index2 ) + { + return; + } + + if( index1 > index2 ) + { + swap = index1; + index1 = index2; + index2 = swap; + } + + distance = index2 - index1 - 1; + + // Loop between index2 and last point and remove points + for( i=index2; i < this->FunctionSize; i++ ) + { + this->Function[(2*(i-distance))] = this->Function[(2*i)]; + this->Function[(2*(i-distance)+1)] = this->Function[(2*i+1)]; + } + + this->FunctionSize = this->FunctionSize - distance; +} + +// Return the value of the function at a position +double vtkPiecewiseFunction::GetValue( double x ) +{ + int i1, i2; + double x1, y1; // Point before x + double x2, y2; // Point after x + + double slope; + double value; + + if( this->FunctionSize == 0 ) + { + return 0.0; + } + + if( this->Clamping == 1 ) // Clamped to lowest value below range and highest above range + { + // Check to see if point is out of range + if( x < this->FunctionRange[0] ) + { + x = this->Function[0]; + } + else if( x > this->FunctionRange[1] ) + { + x = this->Function[(this->FunctionSize-1)*2]; + } + } + else if( this->Clamping == 0 ) // Always zero outside of range + { + if( (x < this->FunctionRange[0]) || (x > this->FunctionRange[1]) ) + { + return 0.0; + } + } + else + { + vtkErrorMacro( << "Error: vtkPiecewiseFunction has an unknown clamp type: " << this->Clamping << "\n" ); + return 0.0; + } + + i2 = 0; + x2 = this->Function[0]; + y2 = this->Function[1]; + + while( (x2 < x) && (i2 < this->FunctionSize) ) + { + i2 += 1; + x2 = this->Function[(i2*2)]; + y2 = this->Function[(i2*2+1)]; + } + + // Check if we have found the exact point + if( x2 == x ) + { + return this->Function[(i2*2 + 1)]; + } + else + { + i1 = i2 - 1; + x1 = this->Function[(i1*2)]; + y1 = this->Function[(i1*2 +1)]; + } + + // Now that we have the two points, use linear interpolation + slope = (y2-y1)/(x2-x1); + + value = y1 + slope*(x-x1); + + return value; +} + +// Return the smallest and largest position stored in function +double *vtkPiecewiseFunction::GetRange() +{ + return this->FunctionRange; +} + +int vtkPiecewiseFunction::AdjustRange(double range[2]) +{ + if (!range) + { + return 0; + } + + double *function_range = this->GetRange(); + + // Make sure we have points at each end of the range + + if (function_range[0] < range[0]) + { + this->AddPoint(range[0], this->GetValue(range[0])); + } + else + { + this->AddPoint(range[0], this->GetValue(function_range[0])); + } + + if (function_range[1] > range[1]) + { + this->AddPoint(range[1], this->GetValue(range[1])); + } + else + { + this->AddPoint(range[1], this->GetValue(function_range[1])); + } + + // Remove all points out-of-range + + int func_size = this->GetSize(); + double *func_ptr = this->GetDataPointer(); + + int i; + for (i = func_size - 1; i >= 0; i--) + { + double x = func_ptr[i * 2]; + if (x < range[0] || x > range[1]) + { + this->RemovePoint(x); + } + } + + return 1; +} + +// Returns a table of function values evaluated at regular intervals +void vtkPiecewiseFunction::GetTable( double x1, double x2, int size, + double* table, int stride ) +{ + double x, xi1, xi2, yi1, yi2, tx; + double inc, value, slope, *tbl; + int i, i1, i2; + + if( x1 == x2 ) + { + return; + } + + if( size > 1 ) + { + inc = (x2-x1)/(double)(size-1); + } + else + { + inc = 0; + } + + tbl = table; + x = x1; + i2 = 0; + xi2 = this->Function[0]; + yi2 = this->Function[1]; + for (i=0; i < size; i++) + { + tx = x; + + // Clamped to lowest value below range and highest above range + if( this->Clamping == 1 ) + { + if( x < this->FunctionRange[0] ) + { + tx = this->Function[0]; + } + else if( x > this->FunctionRange[1] ) + { + tx = this->Function[(this->FunctionSize-1)*2]; + } + } + else if( this->Clamping == 0 ) // Always zero outside of range + { + if( (x < this->FunctionRange[0]) || (x > this->FunctionRange[1]) ) + { + *tbl = 0.0; + tbl += stride; + x += inc; + continue; + } + } + else + { + vtkErrorMacro( << "Error: vtkPiecewiseFunction has an unknown clamp type: " << this->Clamping << "\n" ); + *tbl = 0.0; + tbl += stride; + x += inc; + continue; + } + + // search for the end of the interval containing x + while( (xi2 < tx) && (i2 < this->FunctionSize) ) + { + i2 += 1; + xi2 = this->Function[(i2*2)]; + yi2 = this->Function[(i2*2+1)]; + } + + // Check if we have found the exact point + if( xi2 == tx ) + { + value = this->Function[(i2*2 + 1)]; + } + else + { + i1 = i2 - 1; + xi1 = this->Function[(i1*2)]; + yi1 = this->Function[(i1*2 +1)]; + + // Now that we have the two points, use linear interpolation + slope = (yi2-yi1)/(xi2-xi1); + + value = yi1 + slope*(tx-xi1); + } + + *tbl = value; + tbl += stride; + x += inc; + } +} + +void vtkPiecewiseFunction::GetTable( double x1, double x2, int size, + float* table, int stride ) +{ + double x, xi1, xi2, yi1, yi2, tx; + double inc, value, slope; + float *tbl; + int i, i1, i2; + + if( x1 == x2 ) + { + return; + } + + if( size > 1 ) + { + inc = (x2-x1)/(double)(size-1); + } + else + { + inc = 0; + } + + tbl = table; + x = x1; + i2 = 0; + xi2 = this->Function[0]; + yi2 = this->Function[1]; + for (i=0; i < size; i++) + { + tx = x; + + // Clamped to lowest value below range and highest above range + if( this->Clamping == 1 ) + { + if( x < this->FunctionRange[0] ) + { + tx = this->Function[0]; + } + else if( x > this->FunctionRange[1] ) + { + tx = this->Function[(this->FunctionSize-1)*2]; + } + } + else if( this->Clamping == 0 ) // Always zero outside of range + { + if( (x < this->FunctionRange[0]) || (x > this->FunctionRange[1]) ) + { + *tbl = 0.0f; + tbl += stride; + x += inc; + continue; + } + } + else + { + vtkErrorMacro( << "Error: vtkPiecewiseFunction has an unknown clamp type: " << this->Clamping << "\n" ); + *tbl = 0.0f; + tbl += stride; + x += inc; + continue; + } + + // search for the end of the interval containing x + while( (xi2 < tx) && (i2 < this->FunctionSize) ) + { + i2 += 1; + xi2 = this->Function[(i2*2)]; + yi2 = this->Function[(i2*2+1)]; + } + + // Check if we have found the exact point + if( xi2 == tx ) + { + value = this->Function[(i2*2 + 1)]; + } + else + { + i1 = i2 - 1; + xi1 = this->Function[(i1*2)]; + yi1 = this->Function[(i1*2 +1)]; + + // Now that we have the two points, use linear interpolation + slope = (yi2-yi1)/(xi2-xi1); + + value = yi1 + slope*(tx-xi1); + } + + *tbl = static_cast(value); + tbl += stride; + x += inc; + } +} + +void vtkPiecewiseFunction::BuildFunctionFromTable( double x1, double x2, + int size, + double* table, int stride ) +{ + int i; + double inc = 0.0; + double *tptr = table; + + if (size > this->ArraySize) + { + delete [] this->Function; + this->ArraySize = size; + this->FunctionSize = size; + this->Function = new double[this->ArraySize*2]; + } + else + { + // no need to reallocate memory, just adjust the function size + this->FunctionSize = size; + } + + this->FunctionRange[0] = x1; + this->FunctionRange[1] = x2; + + if( size > 1 ) + { + inc = (x2-x1)/(double)(size-1); + } + + for (i=0; i < size; i++) + { + this->Function[2*i] = x1 + inc*i; + this->Function[2*i+1] = *tptr; + tptr += stride; + } + + this->Modified(); +} + +// Increase the size of the array used to store the function +void vtkPiecewiseFunction::IncreaseArraySize() +{ + double *old_function; + int old_size; + + int i; + + old_function = this->Function; + old_size = this->ArraySize; + + // Create larger array to store points + this->ArraySize = old_size * 2; + this->Function = new double[(this->ArraySize*2)]; + + // Copy points from old array to new array + for( i=0; iFunction[(2*i)] = old_function[(2*i)]; + this->Function[(2*i)+1] = old_function[(2*i)+1]; + } + + // Initialize the rest of the memory to avoid purify problems + for ( ; i < this->ArraySize; i++ ) + { + this->Function[(2*i)] = 0; + this->Function[(2*i)+1] = 0; + } + + delete [] old_function; +} + +void vtkPiecewiseFunction::FillFromDataPointer(int nb, double *ptr) +{ + if (nb <= 0 || !ptr) + { + return; + } + + this->RemoveAllPoints(); + + while (nb) + { + this->AddPoint(ptr[0], ptr[1]); + ptr += 2; + nb--; + } +} + +//---------------------------------------------------------------------------- +vtkPiecewiseFunction* vtkPiecewiseFunction::GetData(vtkInformation* info) +{ + return + info? vtkPiecewiseFunction::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkPiecewiseFunction* vtkPiecewiseFunction::GetData(vtkInformationVector* v, + int i) +{ + return vtkPiecewiseFunction::GetData(v->GetInformationObject(i)); +} + +// Print method for tkPiecewiseFunction +void vtkPiecewiseFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + int i; + + os << indent << "Clamping: " << this->Clamping << "\n"; + os << indent << "Function Points: " << this->GetSize() << "\n"; + for( i = 0; i < this->FunctionSize; i++ ) + { + os << indent << indent << i << ": " + << this->Function[(2*i)] << ", " << this->Function[(2*i+1)] << "\n"; + } +} diff --git a/Filtering/vtkPiecewiseFunction.h b/Filtering/vtkPiecewiseFunction.h new file mode 100644 index 0000000..dd6f3e5 --- /dev/null +++ b/Filtering/vtkPiecewiseFunction.h @@ -0,0 +1,172 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPiecewiseFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkPiecewiseFunction - Defines a 1D piecewise function. +// +// .SECTION Description +// Defines a piecewise linear function mapping. Used for transfer functions +// in volume rendering. + +#ifndef __vtkPiecewiseFunction_h +#define __vtkPiecewiseFunction_h + +#include "vtkDataObject.h" + +class VTK_FILTERING_EXPORT vtkPiecewiseFunction : public vtkDataObject +{ +public: + static vtkPiecewiseFunction *New(); + vtkTypeRevisionMacro(vtkPiecewiseFunction,vtkDataObject); + void PrintSelf(ostream& os, vtkIndent indent); + + void Initialize(); + void DeepCopy( vtkDataObject *f ); + void ShallowCopy( vtkDataObject *f ); + + // Description: + // Return what type of dataset this is. + int GetDataObjectType() {return VTK_PIECEWISE_FUNCTION;}; + + // Description: + // Get the number of points used to specify the function + int GetSize(); + + // Description: + // Add/Remove points to/from the function. If a duplicate point is added + // then the function value is changed at that location. + // Return the index of the point (0 based), or -1 on error. + int AddPoint( double x, double val ); + int RemovePoint( double x ); + + // Description: + // Removes all points from the function. + void RemoveAllPoints(); + + // Description: + // Add a line segment to the function. All points defined between the + // two points specified are removed from the function. + void AddSegment( double x1, double val1, double x2, double val2 ); + + // Description: + // Returns the value of the function at the specified location using + // the specified interpolation. Returns zero if the specified location + // is outside the min and max points of the function. + double GetValue( double x ); + + // Description: + // Returns a pointer to the data stored in the table. + // Fills from a pointer to data stored in a similar table. + double *GetDataPointer() {return this->Function;}; + void FillFromDataPointer(int, double*); + + // Description: + // Returns the min and max point locations of the function. + double *GetRange(); + + // Description: + // Remove all points out of the new range, and make sure there is a point + // at each end of that range. + // Return 1 on success, 0 otherwise. + int AdjustRange(double range[2]); + + // Description: + // Fills in an array of function values evaluated at regular intervals. + // Parameter "stride" is used to step through the output "table". It is + // used by vtkColorTransferFunction to fill in an rgb table using three + // separate piecewise functions and three separate calls to GetTable(). + void GetTable( double x1, double x2, int size, float *table, int stride=1 ); + void GetTable( double x1, double x2, int size, double *table, int stride=1 ); + + // Description: + // Constructs a piecewise function from a table. Function range is + // is set to [x1, x2], function size is set to size, and function points + // are regularly spaced between x1 and x2. Parameter "stride" is + // is step through the input table. It is used by vtkColorTransferFunction + // to construct 3 piecewise functions from an rgb table. + void BuildFunctionFromTable( double x1, double x2, int size, + double *table, int stride=1 ); + + // Description: + // When zero range clamping is Off, GetValue() returns 0.0 when a + // value is requested outside of the points specified. + // When zero range clamping is On, GetValue() returns the value at + // the value at the lowest point for a request below all points + // specified and returns the value at the highest point for a request + // above all points specified. On is the default. + vtkSetMacro( Clamping, int ); + vtkGetMacro( Clamping, int ); + vtkBooleanMacro( Clamping, int ); + + // Description: + // Return the type of function: + // Function Types: + // 0 : Constant (No change in slope between end points) + // 1 : NonDecreasing (Always increasing or zero slope) + // 2 : NonIncreasing (Always decreasing or zero slope) + // 3 : Varied (Contains both decreasing and increasing slopes) + const char *GetType(); + + // Description: + // Returns the first point location which precedes a non-zero segment of the + // function. Note that the value at this point may be zero. + double GetFirstNonZeroValue(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkPiecewiseFunction* GetData(vtkInformation* info); + static vtkPiecewiseFunction* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkPiecewiseFunction(); + ~vtkPiecewiseFunction(); + + // Size of the array used to store function points + int ArraySize; + + // Determines the function value outside of defined points + // Zero = always return 0.0 outside of defined points + // One = clamp to the lowest value below defined points and + // highest value above defined points + int Clamping; + + // Array of points ((X,Y) pairs) + double *Function; + + // Number of points used to specify function + int FunctionSize; + + // Min and max range of function point locations + double FunctionRange[2]; + + // Increases size of the function array. The array grows by a factor of 2 + // when the array limit has been reached. + void IncreaseArraySize(); + + // Private function to add a point to the function. Returns the array + // index of the inserted point. + int InsertPoint( double x, double val ); + + // Move points one index down or up in the array. This is useful for + // inserting and deleting points into the array. + void MovePoints( int index, int down ); +private: + vtkPiecewiseFunction(const vtkPiecewiseFunction&); // Not implemented. + void operator=(const vtkPiecewiseFunction&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkPiecewiseFunctionAlgorithm.cxx b/Filtering/vtkPiecewiseFunctionAlgorithm.cxx new file mode 100644 index 0000000..e6dc206 --- /dev/null +++ b/Filtering/vtkPiecewiseFunctionAlgorithm.cxx @@ -0,0 +1,237 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPiecewiseFunctionAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPiecewiseFunctionAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkDataObject.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkPiecewiseFunctionAlgorithm, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPiecewiseFunctionAlgorithm); + +//---------------------------------------------------------------------------- +vtkPiecewiseFunctionAlgorithm::vtkPiecewiseFunctionAlgorithm() +{ + // by default assume filters have one input and one output + // subclasses that deviate should modify this setting + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkPiecewiseFunctionAlgorithm::~vtkPiecewiseFunctionAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkPiecewiseFunctionAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkPiecewiseFunctionAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkPiecewiseFunctionAlgorithm::GetOutput(int port) +{ + return this->GetOutputDataObject(port); +} + +//---------------------------------------------------------------------------- +void vtkPiecewiseFunctionAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkPiecewiseFunctionAlgorithm::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkPiecewiseFunctionAlgorithm::GetInput(int port) +{ + if (this->GetNumberOfInputConnections(port) < 1) + { + return 0; + } + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +int vtkPiecewiseFunctionAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkPiecewiseFunctionAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPiecewiseFunction"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPiecewiseFunctionAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPiecewiseFunction"); + return 1; +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkPiecewiseFunctionAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + return 1; +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkPiecewiseFunctionAlgorithm::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (output && this->UpdateExtentIsEmpty(output)) + { + output->Initialize(); + return; + } + + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkPiecewiseFunctionAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + +//---------------------------------------------------------------------------- +int vtkPiecewiseFunctionAlgorithm::UpdateExtentIsEmpty(vtkDataObject *output) +{ + if (output == NULL) + { + return 1; + } + + int *ext = output->GetUpdateExtent(); + switch ( output->GetExtentType() ) + { + case VTK_PIECES_EXTENT: + // Special way of asking for no input. + if ( output->GetUpdateNumberOfPieces() == 0 ) + { + return 1; + } + break; + + case VTK_3D_EXTENT: + // Special way of asking for no input. (zero volume) + if (ext[0] == (ext[1] + 1) || + ext[2] == (ext[3] + 1) || + ext[4] == (ext[5] + 1)) + { + return 1; + } + break; + + // We should never have this case occur + default: + vtkErrorMacro( << "Internal error - invalid extent type!" ); + break; + } + + return 0; +} + + +//---------------------------------------------------------------------------- +void vtkPiecewiseFunctionAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkPiecewiseFunctionAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkPiecewiseFunctionAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkPiecewiseFunctionAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} diff --git a/Filtering/vtkPiecewiseFunctionAlgorithm.h b/Filtering/vtkPiecewiseFunctionAlgorithm.h new file mode 100644 index 0000000..60b1f67 --- /dev/null +++ b/Filtering/vtkPiecewiseFunctionAlgorithm.h @@ -0,0 +1,118 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPiecewiseFunctionAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPiecewiseFunctionAlgorithm - Superclass for algorithms that produce only piecewise function as output +// .SECTION Description + +// vtkPiecewiseFunctionAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// constructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be PiecewiseFunction. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// ExecuteData and ExecuteInformation. For new algorithms you should +// implement RequestData( request, inputVec, outputVec) but for older filters +// there is a default implementation that calls the old ExecuteData(output) +// signature, for even older filters that don;t implement ExecuteData the +// default implementation calls the even older Execute() signature. + +#ifndef __vtkPiecewiseFunctionAlgorithm_h +#define __vtkPiecewiseFunctionAlgorithm_h + +#include "vtkAlgorithm.h" +#include "vtkPiecewiseFunction.h" // makes things a bit easier + +class vtkDataSet; +class vtkDataObject; + +class VTK_FILTERING_EXPORT vtkPiecewiseFunctionAlgorithm : public vtkAlgorithm +{ +public: + static vtkPiecewiseFunctionAlgorithm *New(); + vtkTypeRevisionMacro(vtkPiecewiseFunctionAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkDataObject* GetOutput(); + vtkDataObject* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject* GetInput(); + vtkDataObject *GetInput(int port); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(int, vtkDataObject*); + +protected: + vtkPiecewiseFunctionAlgorithm(); + ~vtkPiecewiseFunctionAlgorithm(); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This detects when the UpdateExtent will generate no data. + // This condition is satisfied when the UpdateExtent has + // zero volume (0,-1,...) or the UpdateNumberOfPieces is 0. + // The source uses this call to determine whether to call Execute. + int UpdateExtentIsEmpty(vtkDataObject *output); + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkPiecewiseFunctionAlgorithm(const vtkPiecewiseFunctionAlgorithm&); // Not implemented. + void operator=(const vtkPiecewiseFunctionAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkPiecewiseFunctionShiftScale.cxx b/Filtering/vtkPiecewiseFunctionShiftScale.cxx new file mode 100644 index 0000000..ecd394f --- /dev/null +++ b/Filtering/vtkPiecewiseFunctionShiftScale.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPiecewiseFunctionShiftScale.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPiecewiseFunctionShiftScale.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" + +vtkCxxRevisionMacro(vtkPiecewiseFunctionShiftScale, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkPiecewiseFunctionShiftScale); + +vtkPiecewiseFunctionShiftScale::vtkPiecewiseFunctionShiftScale() +{ + this->PositionShift = 0.0; + this->PositionScale = 1.0; + this->ValueShift = 0.0; + this->ValueScale = 1.0; +} + +vtkPiecewiseFunctionShiftScale::~vtkPiecewiseFunctionShiftScale() +{ +} + +int vtkPiecewiseFunctionShiftScale::RequestData( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPiecewiseFunction *input = vtkPiecewiseFunction::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPiecewiseFunction *output = vtkPiecewiseFunction::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double *inFunction = input->GetDataPointer(); + int numInValues = input->GetSize(); + + output->RemoveAllPoints(); + + int i; + + for (i = 0; i < numInValues; i++) + { + output->AddPoint((inFunction[2*i] + this->PositionShift) * + this->PositionScale, + (inFunction[2*i+1] + this->ValueShift) * + this->ValueScale); + } + + return 1; +} + +void vtkPiecewiseFunctionShiftScale::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "PositionShift: " << this->PositionShift << "\n"; + os << indent << "PositionScale: " << this->PositionScale << "\n"; + os << indent << "ValueShift: " << this->ValueShift << "\n"; + os << indent << "ValueScale: " << this->ValueScale << "\n"; +} diff --git a/Filtering/vtkPiecewiseFunctionShiftScale.h b/Filtering/vtkPiecewiseFunctionShiftScale.h new file mode 100644 index 0000000..a467365 --- /dev/null +++ b/Filtering/vtkPiecewiseFunctionShiftScale.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPiecewiseFunctionShiftScale.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkPiecewiseFunctionShiftScale - +// +// .SECTION Description + +#ifndef __vtkPiecewiseFunctionShiftScale_h +#define __vtkPiecewiseFunctionShiftScale_h + +#include "vtkPiecewiseFunctionAlgorithm.h" + +class vtkPiecewiseFunction; + +class VTK_FILTERING_EXPORT vtkPiecewiseFunctionShiftScale : public vtkPiecewiseFunctionAlgorithm +{ +public: + static vtkPiecewiseFunctionShiftScale *New(); + vtkTypeRevisionMacro(vtkPiecewiseFunctionShiftScale, vtkPiecewiseFunctionAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkSetMacro(PositionShift, double); + vtkSetMacro(PositionScale, double); + vtkSetMacro(ValueShift, double); + vtkSetMacro(ValueScale, double); + + vtkGetMacro(PositionShift, double); + vtkGetMacro(PositionScale, double); + vtkGetMacro(ValueShift, double); + vtkGetMacro(ValueScale, double); + +protected: + vtkPiecewiseFunctionShiftScale(); + ~vtkPiecewiseFunctionShiftScale(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + double PositionShift; + double PositionScale; + double ValueShift; + double ValueScale; + +private: + vtkPiecewiseFunctionShiftScale(const vtkPiecewiseFunctionShiftScale&); // Not implemented + void operator=(const vtkPiecewiseFunctionShiftScale&); // Not implemented +}; + +#endif diff --git a/Filtering/vtkPixel.cxx b/Filtering/vtkPixel.cxx new file mode 100644 index 0000000..fade4d5 --- /dev/null +++ b/Filtering/vtkPixel.cxx @@ -0,0 +1,694 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPixel.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPixel.h" + +#include "vtkObjectFactory.h" +#include "vtkQuad.h" +#include "vtkTriangle.h" +#include "vtkPlane.h" +#include "vtkMath.h" +#include "vtkCellArray.h" +#include "vtkLine.h" +#include "vtkPointLocator.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkPixel, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkPixel); + +//---------------------------------------------------------------------------- +// Construct the pixel with four points. +vtkPixel::vtkPixel() +{ + int i; + + this->Points->SetNumberOfPoints(4); + this->PointIds->SetNumberOfIds(4); + for (i = 0; i < 4; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + } + for (i = 0; i < 4; i++) + { + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); +} + +//---------------------------------------------------------------------------- +vtkPixel::~vtkPixel() +{ + this->Line->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkPixel::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + double pt1[3], pt2[3], pt3[3]; + int i; + double p[3], p21[3], p31[3], cp[3]; + double l21, l31, n[3]; + + subId = 0; + pcoords[2] = 0.0; + + // Get normal for pixel + // + this->Points->GetPoint(0, pt1); + this->Points->GetPoint(1, pt2); + this->Points->GetPoint(2, pt3); + + vtkTriangle::ComputeNormal (pt1, pt2, pt3, n); + + // Project point to plane + // + vtkPlane::ProjectPoint(x,pt1,n,cp); + + for (i=0; i<3; i++) + { + p21[i] = pt2[i] - pt1[i]; + p31[i] = pt3[i] - pt1[i]; + p[i] = x[i] - pt1[i]; + } + + if ( (l21=vtkMath::Norm(p21)) == 0.0 ) + { + l21 = 1.0; + } + if ( (l31=vtkMath::Norm(p31)) == 0.0 ) + { + l31 = 1.0; + } + + pcoords[0] = vtkMath::Dot(p21,p) / (l21*l21); + pcoords[1] = vtkMath::Dot(p31,p) / (l31*l31); + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= 0.0 && pcoords[0] <= 1.0 && + pcoords[1] >= 0.0 && pcoords[1] <= 1.0 ) + { + if (closestPoint) + { + closestPoint[0] = cp[0]; + closestPoint[1] = cp[1]; + closestPoint[2] = cp[2]; + dist2 = + vtkMath::Distance2BetweenPoints(closestPoint,x); //projection distance + } + return 1; + } + else + { + double pc[3], w[4]; + if (closestPoint) + { + for (i=0; i<2; i++) + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkPixel::EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights) +{ + double pt1[3], pt2[3], pt3[3]; + int i; + + subId = 0; + + this->Points->GetPoint(0, pt1); + this->Points->GetPoint(1, pt2); + this->Points->GetPoint(2, pt3); + + for (i=0; i<3; i++) + { + x[i] = pt1[i] + pcoords[0]*(pt2[i] - pt1[i]) + + pcoords[1]*(pt3[i] - pt1[i]); + } + + this->InterpolationFunctions(pcoords, weights); +} + +//---------------------------------------------------------------------------- +int vtkPixel::CellBoundary(int vtkNotUsed(subId), double pcoords[3], vtkIdList *pts) +{ + double t1=pcoords[0]-pcoords[1]; + double t2=1.0-pcoords[0]-pcoords[1]; + + pts->SetNumberOfIds(2); + + // compare against two lines in parametric space that divide element + // into four pieces. + if ( t1 >= 0.0 && t2 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + } + + else if ( t1 >= 0.0 && t2 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(3)); + } + + else if ( t1 < 0.0 && t2 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(3)); + pts->SetId(1,this->PointIds->GetId(2)); + } + + else //( t1 < 0.0 && t2 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(2)); + pts->SetId(1,this->PointIds->GetId(0)); + } + + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +// +// Marching squares +// +#include "vtkMarchingSquaresCases.h" + +static int edges[4][2] = { {0,1}, {1,3}, {2,3}, {0,2} }; + +void vtkPixel::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *vtkNotUsed(verts), + vtkCellArray *lines, + vtkCellArray *vtkNotUsed(polys), + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + static int CASE_MASK[4] = {1,2,8,4}; //note differenceom quad! + vtkMarchingSquaresLineCases *lineCase; + EDGE_LIST *edge; + int i, j, index, *vert; + int newCellId; + vtkIdType pts[2]; + double t, x1[3], x2[3], x[3]; + + // Build the case table + for ( i=0, index = 0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + lineCase = vtkMarchingSquaresLineCases::GetCases() + index; + edge = lineCase->edges; + + for ( ; edge[0] > -1; edge += 2 ) + { + for (i=0; i<2; i++) // insert line + { + vert = edges[edge[i]]; + t = (value - cellScalars->GetComponent(vert[0],0)) / + (cellScalars->GetComponent(vert[1],0) - + cellScalars->GetComponent(vert[0],0)); + this->Points->GetPoint(vert[0], x1); + this->Points->GetPoint(vert[1], x2); + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + int p1 = this->PointIds->GetId(vert[0]); + int p2 = this->PointIds->GetId(vert[1]); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate line + if ( pts[0] != pts[1] ) + { + newCellId = lines->InsertNextCell(2,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +vtkCell *vtkPixel::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} + +//---------------------------------------------------------------------------- +// +// Compute interpolation functions (similar but different than Quad interpolation +// functions) +// +void vtkPixel::InterpolationFunctions(double pcoords[3], double sf[4]) +{ + double rm, sm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + + sf[0] = rm * sm; + sf[1] = pcoords[0] * sm; + sf[2] = rm * pcoords[1]; + sf[3] = pcoords[0] * pcoords[1]; +} + +//---------------------------------------------------------------------------- +// +// Compute derivatives of interpolation functions. +// +void vtkPixel::InterpolationDerivs(double pcoords[3], double derivs[8]) +{ + double rm, sm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + + // r derivatives + derivs[0] = -sm; + derivs[1] = sm; + derivs[2] = -pcoords[1]; + derivs[3] = pcoords[1]; + + // s derivatives + derivs[4] = -rm; + derivs[5] = -pcoords[0]; + derivs[6] = rm; + derivs[7] = pcoords[0]; +} + +//---------------------------------------------------------------------------- +// +// Intersect plane; see whether point is inside. +// +int vtkPixel::IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId) +{ + double pt1[3], pt4[3], n[3]; + double tol2 = tol*tol; + double closestPoint[3]; + double dist2, weights[4]; + int i; + + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; +// +// Get normal for triangle +// + this->Points->GetPoint(0, pt1); + this->Points->GetPoint(3, pt4); + + n[0] = n[1] = n[2] = 0.0; + for (i=0; i<3; i++) + { + if ( (pt4[i] - pt1[i]) <= 0.0 ) + { + n[i] = 1.0; + break; + } + } + // + // Intersect plane of pixel with line + // + if ( ! vtkPlane::IntersectWithLine(p1,p2,n,pt1,t,x) ) + { + return 0; + } + // + // Use evaluate position + // + if (this->EvaluatePosition(x, closestPoint, subId, pcoords, dist2, weights) ) + { + if ( dist2 <= tol2 ) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkPixel::Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + if ( (index % 2) ) + { + ptIds->InsertId(0,this->PointIds->GetId(0)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + ptIds->InsertId(1,this->PointIds->GetId(1)); + pts->InsertPoint(1,this->Points->GetPoint(1)); + ptIds->InsertId(2,this->PointIds->GetId(2)); + pts->InsertPoint(2,this->Points->GetPoint(2)); + + ptIds->InsertId(3,this->PointIds->GetId(1)); + pts->InsertPoint(3,this->Points->GetPoint(1)); + ptIds->InsertId(4,this->PointIds->GetId(3)); + pts->InsertPoint(4,this->Points->GetPoint(3)); + ptIds->InsertId(5,this->PointIds->GetId(2)); + pts->InsertPoint(5,this->Points->GetPoint(2)); + } + else + { + ptIds->InsertId(0,this->PointIds->GetId(0)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + ptIds->InsertId(1,this->PointIds->GetId(1)); + pts->InsertPoint(1,this->Points->GetPoint(1)); + ptIds->InsertId(2,this->PointIds->GetId(3)); + pts->InsertPoint(2,this->Points->GetPoint(3)); + + ptIds->InsertId(3,this->PointIds->GetId(0)); + pts->InsertPoint(3,this->Points->GetPoint(0)); + ptIds->InsertId(4,this->PointIds->GetId(3)); + pts->InsertPoint(4,this->Points->GetPoint(3)); + ptIds->InsertId(5,this->PointIds->GetId(2)); + pts->InsertPoint(5,this->Points->GetPoint(2)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPixel::Derivatives(int vtkNotUsed(subId), + double pcoords[3], + double *values, + int dim, double *derivs) +{ + double functionDerivs[8], sum; + int i, j, k, plane, idx[2], jj; + double x0[3], x1[3], x2[3], x3[3], spacing[3]; + + this->Points->GetPoint(0, x0); + this->Points->GetPoint(1, x1); + this->Points->GetPoint(2, x2); + this->Points->GetPoint(3, x3); + + //figure which plane this pixel is in + for (i=0; i < 3; i++) + { + spacing[i] = x3[i] - x0[i]; + } + + if ( spacing[0] > spacing[2] && spacing[1] > spacing[2] ) // z-plane + { + plane = 2; + idx[0] = 0; idx[1] = 1; + } + else if ( spacing[0] > spacing[1] && spacing[2] > spacing[1] ) // y-plane + { + plane = 1; + idx[0] = 0; idx[1] = 2; + } + else // x-plane + { + plane = 0; + idx[0] = 1; idx[1] = 2; + } + + spacing[0] = x1[idx[0]] - x0[idx[0]]; + spacing[1] = x2[idx[1]] - x0[idx[1]]; + + // get derivatives in r-s directions + this->InterpolationDerivs(pcoords, functionDerivs); + + // since two of the x-y-z axes are aligned with r-s axes, only need to scale + // the derivative values by the data spacing. + for (k=0; k < dim; k++) //loop over values per vertex + { + for (jj=j=0; j < 3; j++) //loop over derivative directions + { + if ( j == plane ) // 0-derivate values in this direction + { + sum = 0.0; + } + else //compute derivatives + { + for (sum=0.0, i=0; i < 4; i++) //loop over interp. function derivatives + { + sum += functionDerivs[4*jj + i] * values[dim*i + k]; + } + sum /= spacing[idx[jj++]]; + } + derivs[3*k + j] = sum; + } + } +} + +//---------------------------------------------------------------------------- +// support pixel clipping +typedef int PIXEL_EDGE_LIST; +typedef struct { + PIXEL_EDGE_LIST edges[14]; +} PIXEL_CASES; + +static PIXEL_CASES pixelCases[] = { +{{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 0 +{{ 3, 100, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 1 +{{ 3, 101, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 2 +{{ 4, 100, 101, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 3 +{{ 3, 103, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 4 +{{ 3, 100, 0, 3, 3, 103, 2, 1, 4, 0, 1, 2, 3, -1}}, // 5 +{{ 4, 101, 103, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 6 +{{ 3, 100, 101, 3, 3, 101, 2, 3, 3, 101, 103, 2, -1, -1}}, // 7 +{{ 3, 102, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 8 +{{ 4, 100, 0, 2, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 9 +{{ 3, 101, 1, 0, 3, 102, 3, 2, 4, 0, 1, 2, 3, -1}}, // 10 +{{ 3, 100, 101, 1, 3, 100, 1, 2, 3, 100, 2, 102, -1, -1}}, // 11 +{{ 4, 103, 102, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 12 +{{ 3, 100, 0, 102, 3, 0, 1, 102, 3, 1, 103, 102, -1, -1}}, // 13 +{{ 3, 0, 101, 103, 3, 0, 103, 3, 3, 103, 102, 3, -1, -1}}, // 14 +{{ 4, 100, 101, 103, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 15 +}; + +static PIXEL_CASES pixelCasesComplement[] = { +{{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 0 +{{ 3, 100, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 1 +{{ 3, 101, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 2 +{{ 4, 100, 101, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 3 +{{ 3, 103, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 4 +{{ 3, 100, 0, 3, 3, 103, 2, 1, -1, -1, -1, -1, -1, -1}}, // 5 +{{ 4, 101, 103, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 6 +{{ 3, 100, 101, 3, 3, 101, 2, 3, 3, 101, 103, 2, -1, -1}}, // 7 +{{ 3, 102, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 8 +{{ 4, 100, 0, 2, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 9 +{{ 3, 101, 1, 0, 3, 102, 3, 2, -1, -1, -1, -1, -1, -1}}, // 10 +{{ 3, 100, 101, 1, 3, 100, 1, 2, 3, 100, 2, 102, -1, -1}}, // 11 +{{ 4, 103, 102, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 12 +{{ 3, 100, 0, 102, 3, 0, 1, 102, 3, 1, 103, 102, -1, -1}}, // 13 +{{ 3, 0, 101, 103, 3, 0, 103, 3, 3, 103, 102, 3, -1, -1}}, // 14 +{{ 4, 100, 101, 103, 102, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 15 +}; + + +//---------------------------------------------------------------------------- +// Clip this pixel using scalar value provided. Like contouring, except +// that it cuts the pixel to produce quads and/or triangles. +void vtkPixel::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut) +{ + static int CASE_MASK[4] = {1,2,8,4}; //note difference from quad! + PIXEL_CASES *pixelCase; + PIXEL_EDGE_LIST *edge; + int i, j, index, *vert; + int e1, e2; + int newCellId; + vtkIdType pts[4]; + int vertexId; + double t, x1[3], x2[3], x[3], deltaScalar; + double scalar0, scalar1, e1Scalar; + + // Build the index into the case table + if ( insideOut ) + { + for ( i=0, index = 0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) <= value) + { + index |= CASE_MASK[i]; + } + } + // Select case based on the index and get the list of edges for this case + pixelCase = pixelCases + index; + } + else + { + for ( i=0, index = 0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) > value) + { + index |= CASE_MASK[i]; + } + } + // Select case based on the index and get the list of edges for this case + pixelCase = pixelCasesComplement + index; + } + + edge = pixelCase->edges; + + // generate each pixel + for ( ; edge[0] > -1; edge += edge[0]+1 ) + { + for (i=0; i < edge[0]; i++) // insert pixel or triangle + { + // vertex exists, and need not be interpolated + if (edge[i+1] >= 100) + { + vertexId = edge[i+1] - 100; + this->Points->GetPoint(vertexId, x); + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + outPd->CopyData(inPd,this->PointIds->GetId(vertexId),pts[i]); + } + } + + else //new vertex, interpolate + { + vert = edges[edge[i+1]]; + + // calculate a preferred interpolation direction + scalar0 = cellScalars->GetComponent(vert[0],0); + scalar1 = cellScalars->GetComponent(vert[1],0); + deltaScalar = scalar1 - scalar0; + + if (deltaScalar > 0) + { + e1 = vert[0]; e2 = vert[1]; + e1Scalar = scalar0; + } + else + { + e1 = vert[1]; e2 = vert[0]; + e1Scalar = scalar1; + deltaScalar = -deltaScalar; + } + + // linear interpolation + if (deltaScalar == 0.0) + { + t = 0.0; + } + else + { + t = (value - e1Scalar) / deltaScalar; + } + + this->Points->GetPoint(e1, x1); + this->Points->GetPoint(e2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + int p1 = this->PointIds->GetId(e1); + int p2 = this->PointIds->GetId(e2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate output + if ( edge[0] == 3 ) //i.e., a triangle + { + if (pts[0] == pts[1] || pts[0] == pts[2] || pts[1] == pts[2] ) + { + continue; + } + } + else // a pixel + { + if ((pts[0] == pts[3] && pts[1] == pts[2]) || + (pts[0] == pts[1] && pts[3] == pts[2]) ) + { + continue; + } + } + + newCellId = polys->InsertNextCell(edge[0],pts); + outCd->CopyData(inCd,cellId,newCellId); + } +} + +//---------------------------------------------------------------------------- +static double vtkPixelCellPCoords[12] = {0.0,0.0,0.0, 1.0,0.0,0.0, + 0.0,1.0,0.0, 1.0,1.0,0.0}; + +double *vtkPixel::GetParametricCoords() +{ + return vtkPixelCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkPixel::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); +} + diff --git a/Filtering/vtkPixel.h b/Filtering/vtkPixel.h new file mode 100644 index 0000000..0764985 --- /dev/null +++ b/Filtering/vtkPixel.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPixel.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPixel - a cell that represents an orthogonal quadrilateral +// .SECTION Description +// vtkPixel is a concrete implementation of vtkCell to represent a 2D +// orthogonal quadrilateral. Unlike vtkQuad, the corners are at right angles, +// and aligned along x-y-z coordinate axes leading to large increases in +// computational efficiency. + +#ifndef __vtkPixel_h +#define __vtkPixel_h + +#include "vtkCell.h" + +class vtkLine; + +class VTK_FILTERING_EXPORT vtkPixel : public vtkCell +{ +public: + static vtkPixel *New(); + vtkTypeRevisionMacro(vtkPixel,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_PIXEL;}; + int GetCellDimension() {return 2;}; + int GetNumberOfEdges() {return 4;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + + // Description: + // Return the center of the triangle in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Pixel specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[4]); + static void InterpolationDerivs(double pcoords[3], double derivs[8]); + + +protected: + vtkPixel(); + ~vtkPixel(); + + vtkLine *Line; + +private: + vtkPixel(const vtkPixel&); // Not implemented. + void operator=(const vtkPixel&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkPixel::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.5; + pcoords[2] = 0.0; + return 0; +} + +#endif + + diff --git a/Filtering/vtkPointData.cxx b/Filtering/vtkPointData.cxx new file mode 100644 index 0000000..2928724 --- /dev/null +++ b/Filtering/vtkPointData.cxx @@ -0,0 +1,44 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPointData, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPointData); + +void vtkPointData::NullPoint (vtkIdType ptId) +{ + vtkFieldData::Iterator it(this); + vtkDataArray* da; + for(da=it.Begin(); !it.End(); da=it.Next()) + { + if (da) + { + int length = da->GetNumberOfComponents(); + float* tuple = new float[length]; + for(int j=0; jInsertTuple(ptId, tuple); + delete[] tuple; + } + } +} + +void vtkPointData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkPointData.h b/Filtering/vtkPointData.h new file mode 100644 index 0000000..afe8234 --- /dev/null +++ b/Filtering/vtkPointData.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointData - represent and manipulate point attribute data +// .SECTION Description +// vtkPointData is a class that is used to represent and manipulate +// point attribute data (e.g., scalars, vectors, normals, texture +// coordinates, etc.) Most of the functionality is handled by +// vtkDataSetAttributes + +#ifndef __vtkPointData_h +#define __vtkPointData_h + +#include "vtkDataSetAttributes.h" + +class VTK_FILTERING_EXPORT vtkPointData : public vtkDataSetAttributes +{ +public: + static vtkPointData *New(); + + vtkTypeRevisionMacro(vtkPointData,vtkDataSetAttributes); + void PrintSelf(ostream& os, vtkIndent indent); + void NullPoint(vtkIdType ptId); + +protected: + vtkPointData() {}; + ~vtkPointData() {}; + +private: + vtkPointData(const vtkPointData&); // Not implemented. + void operator=(const vtkPointData&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkPointLocator.cxx b/Filtering/vtkPointLocator.cxx new file mode 100644 index 0000000..bc6dd9e --- /dev/null +++ b/Filtering/vtkPointLocator.cxx @@ -0,0 +1,1925 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointLocator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointLocator.h" + +#include "vtkCellArray.h" +#include "vtkIdList.h" +#include "vtkIntArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkPointLocator, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPointLocator); + +static const int VTK_INITIAL_SIZE=1000; + +// Utility class to store an array of ijk values +class vtkNeighborPoints +{ +public: + vtkNeighborPoints() + { + this->Count = 0; + this->P=&(this->InitialBuffer[0]); + this->MaxSize = VTK_INITIAL_SIZE; + } + ~vtkNeighborPoints() + { + this->Count = 0; + if ( this->P != &(this->InitialBuffer[0]) ) + { + delete[] this->P; + } + } + int GetNumberOfNeighbors() { return this->Count; } + void Reset() { this->Count = 0; } + + int *GetPoint(int i) + { + return (this->Count > i ? &(this->P[3*i]) : 0); + } + + int InsertNextPoint(const int x[3]) + { + int* tmp; + + // Re-allocate if beyond the current max size. + // (Increase by VTK_INITIAL_SIZE) + if (this->Count == this->MaxSize) + { + tmp = this->P; + + this->MaxSize += VTK_INITIAL_SIZE; + this->P = new int[this->MaxSize*3]; + + for(int i=0; i<3*this->Count; i++) + { + this->P[i] = tmp[i]; + } + if ( tmp != &(this->InitialBuffer[0]) ) + { + delete[] tmp; + } + } + + this->P[3*this->Count] = x[0]; + this->P[3*this->Count+1] = x[1]; + this->P[3*this->Count+2] = x[2]; + this->Count++; + return this->Count-1; + } + +protected: +// Start with an array to avoid memory allocation overhead + int InitialBuffer[VTK_INITIAL_SIZE*3]; + int *P; + int Count; + int MaxSize; +}; + + +// Construct with automatic computation of divisions, averaging +// 25 points per bucket. +vtkPointLocator::vtkPointLocator() +{ + + this->Points = NULL; + this->Divisions[0] = this->Divisions[1] = this->Divisions[2] = 50; + this->NumberOfPointsPerBucket = 3; + this->HashTable = NULL; + this->NumberOfBuckets = 0; + this->H[0] = this->H[1] = this->H[2] = 0.0; + this->InsertionPointId = 0; + this->InsertionTol2 = 0.0001; + this->InsertionLevel = 0; +} + +vtkPointLocator::~vtkPointLocator() +{ + if ( this->Points ) + { + this->Points->UnRegister(this); + this->Points = NULL; + } + this->FreeSearchStructure(); +} + +void vtkPointLocator::Initialize() +{ + if ( this->Points ) + { + this->Points->UnRegister(this); + this->Points = NULL; + } + this->FreeSearchStructure(); +} + +void vtkPointLocator::FreeSearchStructure() +{ + vtkIdList *ptIds; + vtkIdType i; + + if ( this->HashTable ) + { + for (i=0; iNumberOfBuckets; i++) + { + if ( (ptIds = this->HashTable[i]) ) + { + ptIds->Delete(); + } + } + delete [] this->HashTable; + this->HashTable = NULL; + } +} + +// Given a position x-y-z, return the id of the point closest to it. +vtkIdType vtkPointLocator::FindClosestPoint(double x, double y, double z) +{ + double xyz[3]; + + xyz[0] = x; xyz[1] = y; xyz[2] = z; + return this->FindClosestPoint(xyz); +} + +// Given a position x, return the id of the point closest to it. +vtkIdType vtkPointLocator::FindClosestPoint(const double x[3]) +{ + int i, j; + double minDist2; + double dist2 = VTK_DOUBLE_MAX; + double *pt; + int closest, level; + vtkIdType ptId, cno; + vtkIdList *ptIds; + int ijk[3], *nei; + vtkNeighborPoints buckets; + + this->BuildLocator(); // will subdivide if modified; otherwise returns + + // + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)(((x[j] - this->Bounds[2*j]) / + (this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]); + + if (ijk[j] < 0) + { + ijk[j] = 0; + } + else if (ijk[j] >= this->Divisions[j]) + { + ijk[j] = this->Divisions[j] - 1; + } + } + // + // Need to search this bucket for closest point. If there are no + // points in this bucket, search 1st level neighbors, and so on, + // until closest point found. + // + for (closest=(-1),minDist2=VTK_DOUBLE_MAX,level=0; (closest == -1) && + (level < this->Divisions[0] || level < this->Divisions[1] || + level < this->Divisions[2]); level++) + { + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level); + + for (i=0; iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + pt = this->DataSet->GetPoint(ptId); + if ( (dist2 = vtkMath::Distance2BetweenPoints(x,pt)) < minDist2 ) + { + closest = ptId; + minDist2 = dist2; + } + } + } + } + } + // + // Because of the relative location of the points in the buckets, the + // point found previously may not be the closest point. Have to + // search those bucket neighbors that might also contain point. + // + if ( dist2 > 0.0 ) + { + this->GetOverlappingBuckets (&buckets, x, ijk, sqrt(dist2),0); + for (i=0; iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + pt = this->DataSet->GetPoint(ptId); + if ( (dist2 = vtkMath::Distance2BetweenPoints(x,pt)) < minDist2 ) + { + closest = ptId; + minDist2 = dist2; + } + }//for each point + }//if points in bucket + }//for each overlapping bucket + }//if not identical point + + return closest; +} + + + +vtkIdType vtkPointLocator::FindClosestPointWithinRadius(double radius, + const double x[3], + double& dist2) + { + return FindClosestPointWithinRadius(radius, x, this->DataSet->GetLength(), + dist2); + } + + +vtkIdType vtkPointLocator::FindClosestPointWithinRadius(double radius, + const double x[3], + double inputDataLength, + double& dist2) +{ + int i, j; + double *pt; + vtkIdType ptId, closest = -1; + vtkIdList *ptIds; + int ijk[3], *nei; + double minDist2; + + double refinedRadius, radius2, refinedRadius2; + double currentRadius; + double distance2ToDataBounds, maxDistance; + int ii, radiusLevels[3], radiusLevel, prevMinLevel[3], prevMaxLevel[3]; + vtkNeighborPoints buckets; + + this->BuildLocator(); // will subdivide if modified; otherwise returns + + dist2 = -1.0; + radius2 = radius*radius; + minDist2 = 1.01*radius2; // something slightly bigger.... + + vtkDataArray *pointData = ((vtkPointSet *)this->DataSet)->GetPoints()->GetData(); + int flag = 1; + + // + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)(((x[j] - this->Bounds[2*j]) / + (this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]); + + if (ijk[j] < 0) + { + ijk[j] = 0; + } + else if (ijk[j] >= this->Divisions[j]) + { + ijk[j] = this->Divisions[j] - 1; + } + } + + // Start by searching the bucket that the point is in. + // + if ( (ptIds = this->HashTable[ijk[0] + ijk[1]*this->Divisions[0] + + ijk[2]*this->Divisions[0]*this->Divisions[1]]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + if (flag) + { + pt = pointData->GetTuple(ptId); + } + else + { + pt = this->DataSet->GetPoint(ptId); + } + if ( (dist2 = vtkMath::Distance2BetweenPoints(x,pt)) < minDist2 ) + { + closest = ptId; + minDist2 = dist2; + } + } + } + + + // Now, search only those buckets that are within a radius. The radius used + // is the smaller of sqrt(dist2) and the radius that is passed in. To avoid + // checking a large number of buckets unnecessarily, if the radius is + // larger than the dimensions of a bucket, we search outward using a + // simple heuristic of rings. This heuristic ends up collecting inner + // buckets multiple times, but this only happens in the case where these + // buckets are empty, so they are discarded quickly. + // + if (dist2 < radius2 && dist2 >= 0.0) + { + refinedRadius = sqrt(dist2); + refinedRadius2 = dist2; + } + else + { + refinedRadius = radius; + refinedRadius2 = radius2; + } + + if (inputDataLength) + { + distance2ToDataBounds = this->Distance2ToBounds(x, this->Bounds); + maxDistance = sqrt(distance2ToDataBounds) + inputDataLength; + if (refinedRadius > maxDistance) + { + refinedRadius = maxDistance; + refinedRadius2 = maxDistance*maxDistance; + } + } + + for (i = 0; i < 3; i++) + { + radiusLevels[i] = (int)(refinedRadius/this->H[i]); + if (radiusLevels[i] > this->Divisions[i] / 2) + { + radiusLevels[i] = this->Divisions[i] / 2; + } + } + + radiusLevel = radiusLevels[0]; + radiusLevel = radiusLevels[1] > radiusLevel ? radiusLevels[1] : radiusLevel; + radiusLevel = radiusLevels[2] > radiusLevel ? radiusLevels[2] : radiusLevel; + if (radiusLevel == 0) + { + radiusLevel = 1; + } + + // radius schedule increases the radius each iteration, this is currently + // implemented by decreasing ii by 1 each iteration. another alternative + // is to double the radius each iteration, i.e. ii = ii >> 1 + // In practice, reducing ii by one has been found to be more efficient. + int numberOfBucketsPerPlane; + numberOfBucketsPerPlane = this->Divisions[0]*this->Divisions[1]; + prevMinLevel[0] = prevMaxLevel[0] = ijk[0]; + prevMinLevel[1] = prevMaxLevel[1] = ijk[1]; + prevMinLevel[2] = prevMaxLevel[2] = ijk[2]; + for (ii=radiusLevel; ii >= 1; ii--) + { + currentRadius = refinedRadius; // used in if at bottom of this for loop + + // Build up a list of buckets that are arranged in rings + this->GetOverlappingBuckets(&buckets, x, refinedRadius/ii, prevMinLevel, + prevMaxLevel); + + for (i=0; iDistance2ToBucket(x, nei) < refinedRadius2) + { + ptIds = this->HashTable[nei[0] + nei[1]*this->Divisions[0] + + nei[2]*numberOfBucketsPerPlane]; + + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + if (flag) + { + pt = pointData->GetTuple(ptId); + } + else + { + pt = this->DataSet->GetPoint(ptId); + } + if ( (dist2 = vtkMath::Distance2BetweenPoints(x,pt)) < minDist2 ) + { + closest = ptId; + minDist2 = dist2; + refinedRadius = sqrt(minDist2); + refinedRadius2 = minDist2; + } + }//for each pt in bucket + }//if bucket is within the current best distance + }//for each overlapping bucket + + // don't want to checker a smaller radius than we just checked so update + // ii appropriately + if (refinedRadius < currentRadius && ii > 2) //always check ii==1 + { + ii = (int)((double)ii * (refinedRadius / currentRadius)) + 1; + if (ii < 2) + { + ii = 2; + } + } + }//for each radius in the radius schedule + + if ((closest != -1) && (minDist2 <= radius2)) + { + dist2 = minDist2; + } + else + { + closest = -1; + } + + return closest; + } + + + +struct idsort +{ + vtkIdType id; + double dist; +}; + +#ifdef _WIN32_WCE +static int __cdecl vtkidsortcompare(const void *arg1, const void *arg2) +#else +extern "C" +{ + int vtkidsortcompare(const void *arg1, const void *arg2) +#endif +{ + idsort *v1 = (idsort *)arg1; + idsort *v2 = (idsort *)arg2; + if (v1->dist < v2->dist) + { + return -1; + } + if (v1->dist > v2->dist) + { + return 1; + } + return 0; +} +#ifndef _WIN32_WCE +} // close extern "C" +#endif + +void vtkPointLocator::FindDistributedPoints(int N, double x, + double y, double z, + vtkIdList *result, int M) +{ + double p[3]; + p[0] = x; + p[1] = y; + p[2] = z; + this->FindDistributedPoints(N,p,result, M); +} + +static int GetOctent(const double x[3], const double pt[3]) +{ + double tmp[3]; + int res = 0; + + tmp[0] = pt[0] - x[0]; + tmp[1] = pt[1] - x[1]; + tmp[2] = pt[2] - x[2]; + + if (tmp[0] > 0.0) + { + res += 1; + } + if (tmp[1] > 0.0) + { + res += 2; + } + if (tmp[2] > 0.0) + { + res += 4; + } + + return res; +} + +static int GetMin(const int foo[8]) +{ + int result = foo[0]; + int i; + + for (i = 1; i < 8; i++) + { + if (foo[i] < result) + { + result = foo[i]; + } + } + return result; +} + +static double GetMax(const double foo[8]) +{ + double result = foo[0]; + int i; + + for (i = 1; i < 8; i++) + { + if (foo[i] > result) + { + result = foo[i]; + } + } + return result; +} + +void vtkPointLocator::FindDistributedPoints(int N, const double x[3], + vtkIdList *result, int M) +{ + int i, j; + double dist2; + double *pt; + int level; + vtkIdType ptId, cno; + vtkIdList *ptIds; + int ijk[3], *nei; + int oct; + int pointsChecked = 0; + vtkNeighborPoints buckets; + + // clear out the result + result->Reset(); + + this->BuildLocator(); // will subdivide if modified; otherwise returns + // + // Make sure candidate point is in bounds. If not, it is outside. + // + for (i=0; i<3; i++) + { + if ( x[i] < this->Bounds[2*i] || x[i] > this->Bounds[2*i+1] ) + { + return; + } + } + // + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)(((x[j] - this->Bounds[2*j]) / + (this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]); + if (ijk[j] >= this->Divisions[j]) + { + ijk[j] = this->Divisions[j] - 1; + } + } + + // there are two steps, first a simple expanding wave of buckets until + // we have enough points. Then a refinement to make sure we have the + // N closest points. + level = 0; + double maxDistance[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + int currentCount[8] = {0,0,0,0,0,0,0,0}; + int minCurrentCount = 0; + + idsort *res[8]; + for (i = 0; i < 8; i++) + { + res[i] = new idsort [N]; + } + + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level); + while (buckets.GetNumberOfNeighbors() && + minCurrentCount < N && + pointsChecked < M) + { + for (i=0; iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + pointsChecked++; + ptId = ptIds->GetId(j); + pt = this->DataSet->GetPoint(ptId); + dist2 = vtkMath::Distance2BetweenPoints(x,pt); + oct = GetOctent(x,pt); + if (currentCount[oct] < N) + { + res[oct][currentCount[oct]].dist = dist2; + res[oct][currentCount[oct]].id = ptId; + if (dist2 > maxDistance[oct]) + { + maxDistance[oct] = dist2; + } + currentCount[oct] = currentCount[oct] + 1; + // compute new minCurrentCount + minCurrentCount = GetMin(currentCount); + if (currentCount[oct] == N) + { + qsort(res[oct], currentCount[oct], sizeof(idsort),vtkidsortcompare); + } + } + else if (dist2 < maxDistance[oct]) + { + res[oct][N-1].dist = dist2; + res[oct][N-1].id = ptId; + qsort(res[oct], N, sizeof(idsort), vtkidsortcompare); + maxDistance[oct] = res[oct][N-1].dist; + } + } + } + } + level++; + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level); + } + + // do a sort + for (i = 0; i < 8; i++) + { + qsort(res[i], currentCount[i], sizeof(idsort), vtkidsortcompare); + } + + // Now do the refinement + this->GetOverlappingBuckets (&buckets, + x, ijk, sqrt(GetMax(maxDistance)),level-1); + + for (i=0; pointsChecked < M && iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + pointsChecked++; + ptId = ptIds->GetId(j); + pt = this->DataSet->GetPoint(ptId); + dist2 = vtkMath::Distance2BetweenPoints(x,pt); + oct = GetOctent(x,pt); + if (dist2 < maxDistance[oct]) + { + res[oct][N-1].dist = dist2; + res[oct][N-1].id = ptId; + qsort(res[oct], N, sizeof(idsort), vtkidsortcompare); + maxDistance[oct] = res[oct][N-1].dist; + } + } + } + } + + // Fill in the IdList + for (j = 0; j < 8; j++) + { + for (i = 0; i < currentCount[j]; i++) + { + result->InsertNextId(res[j][i].id); + } + delete [] res[j]; + } +} + +void vtkPointLocator::FindClosestNPoints(int N, double x, + double y, double z, + vtkIdList *result) +{ + double p[3]; + p[0] = x; + p[1] = y; + p[2] = z; + this->FindClosestNPoints(N,p,result); +} + +void vtkPointLocator::FindClosestNPoints(int N, const double x[3], + vtkIdList *result) +{ + int i, j; + double dist2; + double *pt; + int level; + vtkIdType ptId, cno; + vtkIdList *ptIds; + int ijk[3], *nei; + vtkNeighborPoints buckets; + + // clear out the result + result->Reset(); + + this->BuildLocator(); // will subdivide if modified; otherwise returns + + // + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)(((x[j] - this->Bounds[2*j]) / + (this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]); + + if (ijk[j] < 0) + { + ijk[j] = 0; + } + else if (ijk[j] >= this->Divisions[j]) + { + ijk[j] = this->Divisions[j] - 1; + } + } + + // there are two steps, first a simple expanding wave of buckets until + // we have enough points. Then a refinement to make sure we have the + // N closest points. + level = 0; + double maxDistance = 0.0; + int currentCount = 0; + idsort *res = new idsort [N]; + + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level); + while (buckets.GetNumberOfNeighbors() && currentCount < N) + { + for (i=0; iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + pt = this->DataSet->GetPoint(ptId); + dist2 = vtkMath::Distance2BetweenPoints(x,pt); + if (currentCount < N) + { + res[currentCount].dist = dist2; + res[currentCount].id = ptId; + if (dist2 > maxDistance) + { + maxDistance = dist2; + } + currentCount++; + if (currentCount == N) + { + qsort(res, currentCount, sizeof(idsort), vtkidsortcompare); + } + } + else if (dist2 < maxDistance) + { + res[N-1].dist = dist2; + res[N-1].id = ptId; + qsort(res, N, sizeof(idsort), vtkidsortcompare); + maxDistance = res[N-1].dist; + } + } + } + } + level++; + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level); + } + + // do a sort + qsort(res, currentCount, sizeof(idsort), vtkidsortcompare); + + // Now do the refinement + this->GetOverlappingBuckets (&buckets, x, ijk, sqrt(maxDistance),level-1); + + for (i=0; iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + pt = this->DataSet->GetPoint(ptId); + dist2 = vtkMath::Distance2BetweenPoints(x,pt); + if (dist2 < maxDistance) + { + res[N-1].dist = dist2; + res[N-1].id = ptId; + qsort(res, N, sizeof(idsort), vtkidsortcompare); + maxDistance = res[N-1].dist; + } + } + } + } + + // Fill in the IdList + result->SetNumberOfIds(currentCount); + for (i = 0; i < currentCount; i++) + { + result->SetId(i,res[i].id); + } + + delete [] res; +} + + +void vtkPointLocator::FindPointsWithinRadius(double R, double x, + double y, double z, + vtkIdList *result) +{ + double p[3]; + p[0] = x; + p[1] = y; + p[2] = z; + this->FindPointsWithinRadius(R,p,result); +} + + + +void vtkPointLocator::FindPointsWithinRadius(double R, const double x[3], + vtkIdList *result) +{ + int i, j; + double dist2; + double *pt; + vtkIdType ptId, cno; + vtkIdList *ptIds; + int ijk[3], *nei; + double R2 = R*R; + vtkNeighborPoints buckets; + + this->BuildLocator(); // will subdivide if modified; otherwise returns + // + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)(((x[j] - this->Bounds[2*j]) / + (this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]); + + if (ijk[j] < 0) + { + ijk[j] = 0; + } + else if (ijk[j] >= this->Divisions[j]) + { + ijk[j] = this->Divisions[j] - 1; + } + } + + // get all buckets within a distance + this->GetOverlappingBuckets (&buckets, x, ijk, R, 0); + // add the original bucket + buckets.InsertNextPoint(ijk); + + // clear out the result + result->Reset(); + + for (i=0; iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + pt = this->DataSet->GetPoint(ptId); + dist2 = vtkMath::Distance2BetweenPoints(x,pt); + if (dist2 <= R2) + { + result->InsertNextId(ptId); + } + } + } + } + +} + +// +// Method to form subdivision of space based on the points provided and +// subject to the constraints of levels and NumberOfPointsPerBucket. +// The result is directly addressable and of uniform subdivision. +// +void vtkPointLocator::BuildLocator() +{ + double *bounds; + vtkIdType numBuckets; + double level; + int ndivs[3], product; + int i, j, ijk[3]; + vtkIdType idx; + vtkIdList *bucket; + vtkIdType numPts; + double *x; + typedef vtkIdList *vtkIdListPtr; + + if ( (this->HashTable != NULL) && (this->BuildTime > this->MTime) + && (this->BuildTime > this->DataSet->GetMTime()) ) + { + return; + } + + vtkDebugMacro( << "Hashing points..." ); + this->Level = 1; //only single lowest level + + if ( !this->DataSet || (numPts = this->DataSet->GetNumberOfPoints()) < 1 ) + { + vtkErrorMacro( << "No points to subdivide"); + return; + } + // + // Make sure the appropriate data is available + // + if ( this->HashTable ) + { + this->FreeSearchStructure(); + } + // + // Size the root bucket. Initialize bucket data structure, compute + // level and divisions. + // + bounds = this->DataSet->GetBounds(); + for (i=0; i<3; i++) + { + this->Bounds[2*i] = bounds[2*i]; + this->Bounds[2*i+1] = bounds[2*i+1]; + if ( this->Bounds[2*i+1] <= this->Bounds[2*i] ) //prevent zero width + { + this->Bounds[2*i+1] = this->Bounds[2*i] + 1.0; + } + } + + if ( this->Automatic ) + { + level = (double) numPts / this->NumberOfPointsPerBucket; + level = ceil( pow((double)level,(double)0.33333333) ); + for (i=0; i<3; i++) + { + ndivs[i] = (int) level; + } + } + else + { + for (i=0; i<3; i++) + { + ndivs[i] = (int) this->Divisions[i]; + } + } + + for (i=0; i<3; i++) + { + ndivs[i] = (ndivs[i] > 0 ? ndivs[i] : 1); + this->Divisions[i] = ndivs[i]; + } + + this->NumberOfBuckets = numBuckets = ndivs[0]*ndivs[1]*ndivs[2]; + this->HashTable = new vtkIdListPtr[numBuckets]; + memset (this->HashTable, 0, numBuckets*sizeof(vtkIdListPtr)); + // + // Compute width of bucket in three directions + // + for (i=0; i<3; i++) + { + this->H[i] = (this->Bounds[2*i+1] - this->Bounds[2*i]) / ndivs[i] ; + } + // + // Insert each point into the appropriate bucket. Make sure point + // falls within bucket. + // + product = ndivs[0]*ndivs[1]; + for (i=0; iDataSet->GetPoint(i); + for (j=0; j<3; j++) + { + ijk[j] = (int) ((double) ((x[j] - this->Bounds[2*j]) / + (this->Bounds[2*j+1] - this->Bounds[2*j])) * ndivs[j]); + if (ijk[j] >= this->Divisions[j]) + { + ijk[j] = this->Divisions[j] - 1; + } + } + + idx = ijk[0] + ijk[1]*ndivs[0] + ijk[2]*product; + bucket = this->HashTable[idx]; + if ( ! bucket ) + { + bucket = vtkIdList::New(); + bucket->Allocate(this->NumberOfPointsPerBucket, + this->NumberOfPointsPerBucket/3); + this->HashTable[idx] = bucket; + } + bucket->InsertNextId(i); + } + + this->BuildTime.Modified(); +} + + +// +// Internal function to get bucket neighbors at specified level +// +void vtkPointLocator::GetBucketNeighbors(vtkNeighborPoints* buckets, + const int ijk[3], const int ndivs[3], + int level) +{ + int i, j, k, min, max, minLevel[3], maxLevel[3]; + int nei[3]; + // + // Initialize + // + buckets->Reset(); + // + // If at this bucket, just place into list + // + if ( level == 0 ) + { + buckets->InsertNextPoint(ijk); + return; + } + // + // Create permutations of the ijk indices that are at the level + // required. If these are legal buckets, add to list for searching. + // + for ( i=0; i<3; i++ ) + { + min = ijk[i] - level; + max = ijk[i] + level; + minLevel[i] = ( min > 0 ? min : 0); + maxLevel[i] = ( max < (ndivs[i]-1) ? max : (ndivs[i]-1)); + } + + for ( i= minLevel[0]; i <= maxLevel[0]; i++ ) + { + for ( j= minLevel[1]; j <= maxLevel[1]; j++ ) + { + for ( k= minLevel[2]; k <= maxLevel[2]; k++ ) + { + if (i == (ijk[0] + level) || i == (ijk[0] - level) || + j == (ijk[1] + level) || j == (ijk[1] - level) || + k == (ijk[2] + level) || k == (ijk[2] - level) ) + { + nei[0]=i; nei[1]=j; nei[2]=k; + buckets->InsertNextPoint(nei); + } + } + } + } + + return; +} + + +// +// Internal method to find those buckets that are within distance specified +// only those buckets outside of level radiuses of ijk are returned +void vtkPointLocator::GetOverlappingBuckets(vtkNeighborPoints* buckets, + const double x[3], + const int ijk[3], + double dist, int level) +{ + int i, j, k, nei[3], minLevel[3], maxLevel[3]; + + // Initialize + buckets->Reset(); + + // Determine the range of indices in each direction + for (i=0; i < 3; i++) + { + minLevel[i] = (int) ((double) (((x[i]-dist) - this->Bounds[2*i]) / + (this->Bounds[2*i+1] - this->Bounds[2*i])) * this->Divisions[i]); + maxLevel[i] = (int) ((double) (((x[i]+dist) - this->Bounds[2*i]) / + (this->Bounds[2*i+1] - this->Bounds[2*i])) * this->Divisions[i]); + + if ( minLevel[i] < 0 ) + { + minLevel[i] = 0; + } + if ( maxLevel[i] >= this->Divisions[i] ) + { + maxLevel[i] = this->Divisions[i] - 1; + } + } + + for ( i= minLevel[0]; i <= maxLevel[0]; i++ ) + { + for ( j= minLevel[1]; j <= maxLevel[1]; j++ ) + { + for ( k= minLevel[2]; k <= maxLevel[2]; k++ ) + { + if ( i < (ijk[0]-level) || i > (ijk[0]+level) || + j < (ijk[1]-level) || j > (ijk[1]+level) || + k < (ijk[2]-level) || k > (ijk[2]+level)) + { + nei[0]=i; nei[1]=j; nei[2]=k; + buckets->InsertNextPoint(nei); + } + } + } + } +} + + +// +// Internal method to find those buckets that are within distance specified +// only those buckets outside of level radiuses of ijk are returned +void vtkPointLocator::GetOverlappingBuckets(vtkNeighborPoints* buckets, + const double x[3], double dist, + int prevMinLevel[3], + int prevMaxLevel[3]) +{ + int i, j, k, nei[3], minLevel[3], maxLevel[3]; + int kFactor, jFactor; + int jkSkipFlag, kSkipFlag; + + // Initialize + buckets->Reset(); + + // Determine the range of indices in each direction + for (i=0; i < 3; i++) + { + minLevel[i] = (int) ((double) (((x[i]-dist) - this->Bounds[2*i]) + / this->H[i])); + maxLevel[i] = (int) ((double) (((x[i]+dist) - this->Bounds[2*i]) + / this->H[i])); + + if ( minLevel[i] < 0 ) + { + minLevel[i] = 0; + } + else if (minLevel[i] >= this->Divisions[i] ) + { + minLevel[i] = this->Divisions[i] - 1; + } + if ( maxLevel[i] >= this->Divisions[i] ) + { + maxLevel[i] = this->Divisions[i] - 1; + } + else if ( maxLevel[i] < 0 ) + { + maxLevel[i] = 0; + } + } + + + if (minLevel[0] == prevMinLevel[0] && maxLevel[0] == prevMaxLevel[0] && + minLevel[1] == prevMinLevel[1] && maxLevel[1] == prevMaxLevel[1] && + minLevel[2] == prevMinLevel[2] && maxLevel[2] == prevMaxLevel[2] ) + { + return; + } + + + for ( k= minLevel[2]; k <= maxLevel[2]; k++ ) + { + kFactor = k*this->Divisions[0]*this->Divisions[1]; + if (k >= prevMinLevel[2] && k <= prevMaxLevel[2]) + { + kSkipFlag = 1; + } + else + { + kSkipFlag = 0; + } + for ( j= minLevel[1]; j <= maxLevel[1]; j++ ) + { + if (kSkipFlag && j >= prevMinLevel[1] && j <= prevMaxLevel[1]) + { + jkSkipFlag = 1; + } + else + { + jkSkipFlag = 0; + } + jFactor = j*this->Divisions[0]; + for ( i= minLevel[0]; i <= maxLevel[0]; i++ ) + { + if ( jkSkipFlag && i == prevMinLevel[0] ) + { + i = prevMaxLevel[0]; + continue; + } + // if this bucket has any cells, add it to the list + if (this->HashTable[i + jFactor + kFactor]) + { + nei[0]=i; nei[1]=j; nei[2]=k; + buckets->InsertNextPoint(nei); + } + } + } + } + + prevMinLevel[0] = minLevel[0]; + prevMinLevel[1] = minLevel[1]; + prevMinLevel[2] = minLevel[2]; + prevMaxLevel[0] = maxLevel[0]; + prevMaxLevel[1] = maxLevel[1]; + prevMaxLevel[2] = maxLevel[2]; + } + + +// Initialize the point insertion process. The newPts is an object representing +// point coordinates into which incremental insertion methods place their +// data. Bounds are the box that the points lie in. +int vtkPointLocator::InitPointInsertion(vtkPoints *newPts, + const double bounds[6]) +{ + return this->InitPointInsertion(newPts,bounds,0); +} + +// Initialize the point insertion process. The newPts is an object representing +// point coordinates into which incremental insertion methods place their +// data. Bounds are the box that the points lie in. +int vtkPointLocator::InitPointInsertion(vtkPoints *newPts, + const double bounds[6], + vtkIdType estNumPts) +{ + int i; + int maxDivs; + typedef vtkIdList *vtkIdListPtr; + double hmin; + int ndivs[3]; + double level; + + this->InsertionPointId = 0; + if ( this->HashTable ) + { + this->FreeSearchStructure(); + } + if ( newPts == NULL ) + { + vtkErrorMacro(<<"Must define points for point insertion"); + return 0; + } + if (this->Points != NULL) + { + this->Points->UnRegister(this); + } + this->Points = newPts; + this->Points->Register(this); + + for (i=0; i<3; i++) + { + this->Bounds[2*i] = bounds[2*i]; + this->Bounds[2*i+1] = bounds[2*i+1]; + if ( this->Bounds[2*i+1] <= this->Bounds[2*i] ) + { + this->Bounds[2*i+1] = this->Bounds[2*i] + 1.0; + } + } + + if ( this->Automatic && (estNumPts > 0) ) + { + level = (double) estNumPts / this->NumberOfPointsPerBucket; + level = ceil( pow((double)level,(double)0.33333333) ); + for (i=0; i<3; i++) + { + ndivs[i] = (int) level; + } + } + else + { + for (i=0; i<3; i++) + { + ndivs[i] = (int) this->Divisions[i]; + } + } + + for (i=0; i<3; i++) + { + ndivs[i] = (ndivs[i] > 0 ? ndivs[i] : 1); + this->Divisions[i] = ndivs[i]; + } + + this->NumberOfBuckets = ndivs[0]*ndivs[1]*ndivs[2]; + this->HashTable = new vtkIdListPtr[this->NumberOfBuckets]; + memset (this->HashTable, 0, this->NumberOfBuckets* + sizeof(vtkIdListPtr)); + // + // Compute width of bucket in three directions + // + for (i=0; i<3; i++) + { + this->H[i] = (this->Bounds[2*i+1] - this->Bounds[2*i]) / ndivs[i] ; + } + + this->InsertionTol2 = this->Tolerance * this->Tolerance; + + for (maxDivs=0, hmin=VTK_DOUBLE_MAX, i=0; i<3; i++) + { + hmin = (this->H[i] < hmin ? this->H[i] : hmin); + maxDivs = (maxDivs > this->Divisions[i] ? maxDivs : this->Divisions[i]); + } + this->InsertionLevel = ceil ((double) this->Tolerance / hmin); + this->InsertionLevel = (this->InsertionLevel > maxDivs ? maxDivs : this->InsertionLevel); + return 1; +} + + +// Incrementally insert a point into search structure. The method returns +// the insertion location (i.e., point id). You should use the method +// IsInsertedPoint() to see whether this point has already been +// inserted (that is, if you desire to prevent dulicate points). +// Before using this method you must make sure that newPts have been +// supplied, the bounds has been set properly, and that divs are +// properly set. (See InitPointInsertion().) +vtkIdType vtkPointLocator::InsertNextPoint(const double x[3]) +{ + int i, ijk[3]; + vtkIdType idx; + vtkIdList *bucket; + // + // Locate bucket that point is in. + // + for (i=0; i<3; i++) + { + ijk[i] = (int) ((double) ((x[i] - this->Bounds[2*i]) / + (this->Bounds[2*i+1] - this->Bounds[2*i])) * this->Divisions[i]); + if (ijk[i] >= this->Divisions[i]) + { + ijk[i] = this->Divisions[i] - 1; + } + } + + idx = ijk[0] + ijk[1]*this->Divisions[0] + + ijk[2]*this->Divisions[0]*this->Divisions[1]; + + if ( ! (bucket = this->HashTable[idx]) ) + { + bucket = vtkIdList::New(); + bucket->Allocate(this->NumberOfPointsPerBucket/2, + this->NumberOfPointsPerBucket/3); + this->HashTable[idx] = bucket; + } + + bucket->InsertNextId(this->InsertionPointId); + this->Points->InsertPoint(this->InsertionPointId,x); + return this->InsertionPointId++; +} + +// Incrementally insert a point into search structure with a particular +// index value. You should use the method IsInsertedPoint() to see whether +// this point has already been inserted (that is, if you desire to prevent +// dulicate points). Before using this method you must make sure that +// newPts have been supplied, the bounds has been set properly, and that +// divs are properly set. (See InitPointInsertion().) +void vtkPointLocator::InsertPoint(vtkIdType ptId, const double x[3]) +{ + int i, ijk[3]; + vtkIdType idx; + vtkIdList *bucket; + // + // Locate bucket that point is in. + // + for (i=0; i<3; i++) + { + ijk[i] = (int) ((double) ((x[i] - this->Bounds[2*i]) / + (this->Bounds[2*i+1] - this->Bounds[2*i])) * this->Divisions[i]); + if (ijk[i] >= this->Divisions[i]) + { + ijk[i] = this->Divisions[i] - 1; + } + } + + idx = ijk[0] + ijk[1]*this->Divisions[0] + + ijk[2]*this->Divisions[0]*this->Divisions[1]; + + if ( ! (bucket = this->HashTable[idx]) ) + { + bucket = vtkIdList::New(); + bucket->Allocate(this->NumberOfPointsPerBucket, + this->NumberOfPointsPerBucket/3); + this->HashTable[idx] = bucket; + } + + bucket->InsertNextId(ptId); + this->Points->InsertPoint(ptId,x); +} + +// Determine whether point given by x[3] has been inserted into points list. +// Return id of previously inserted point if this is true, otherwise return +// -1. +vtkIdType vtkPointLocator::IsInsertedPoint(const double x[3]) +{ + int i, j, ijk[3]; + vtkNeighborPoints buckets; + + // Locate bucket that point is in. + // + for (i=0; i<3; i++) + { + ijk[i] = (int) ((double) ((x[i] - this->Bounds[2*i]) / + (this->Bounds[2*i+1] - this->Bounds[2*i])) * this->Divisions[i]); + if (ijk[i] >= this->Divisions[i]) + { + ijk[i] = this->Divisions[i] - 1; + } + } + + // Check the list of points in that bucket for merging. Also need to + // search all neighboring buckets within the tolerance. The number + // and level of neighbors to search depends upon the tolerance and + // the bucket width. + // + int *nei, lvtk; + vtkIdType ptId, cno; + vtkIdList *ptIds; + double pt[3]; + + for (lvtk=0; lvtk <= this->InsertionLevel; lvtk++) + { + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, lvtk); + + for ( i=0; i < buckets.GetNumberOfNeighbors(); i++ ) + { + nei = buckets.GetPoint(i); + cno = nei[0] + nei[1]*this->Divisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + this->Points->GetPoint(ptId, pt); + + if ( vtkMath::Distance2BetweenPoints(x,pt) <= this->InsertionTol2 ) + { + return ptId; + } + } + } //if points in bucket + } //for each neighbor + } //for neighbors at this level + + return -1; +} + +int vtkPointLocator::InsertUniquePoint(const double x[3], vtkIdType &id) +{ + vtkIdType ptId; + + ptId = this->IsInsertedPoint(x); + + if (ptId > -1) + { + id = ptId; + return 0; + } + else + { + id = this->InsertNextPoint(x); + return 1; + } +} + + +// Given a position x, return the id of the point closest to it. This method +// is used when performing incremental point insertion. +vtkIdType vtkPointLocator::FindClosestInsertedPoint(const double x[3]) +{ + int i; + double minDist2, dist2; + double pt[3]; + int level; + vtkIdType closest, j; + vtkIdType ptId, cno; + vtkIdList *ptIds; + int ijk[3], *nei; + int MULTIPLES; + double diff; + vtkNeighborPoints buckets; + + // + // Make sure candidate point is in bounds. If not, it is outside. + // + for (i=0; i<3; i++) + { + if ( x[i] < this->Bounds[2*i] || x[i] > this->Bounds[2*i+1] ) + { + return -1; + } + } + + // Find bucket point is in. + // + for (j=0; j<3; j++) + { + ijk[j] = (int)(((x[j] - this->Bounds[2*j]) / + (this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]); + if (ijk[j] >= this->Divisions[j]) + { + ijk[j] = this->Divisions[j] - 1; + } + } + + // Need to search this bucket for closest point. If there are no + // points in this bucket, search 1st level neighbors, and so on, + // until closest point found. + // + for (closest=0,minDist2=VTK_DOUBLE_MAX,level=0; (closest == 0) && + (level < this->Divisions[0] || level < this->Divisions[1] || + level < this->Divisions[2]); level++) + { + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level); + + for (i=0; iDivisions[0] + + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) != NULL ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + this->Points->GetPoint(ptId, pt); + if ( (dist2 = vtkMath::Distance2BetweenPoints(x,pt)) < minDist2 ) + { + closest = ptId; + minDist2 = dist2; + } + } + } + } + } + // + // Because of the relative location of the points in the spatial_hash, this + // may not be the closest point. Have to search those bucket + // neighbors (one level further out) that might also contain point. + // + this->GetBucketNeighbors (&buckets, ijk, this->Divisions, level); + // + // Don't want to search all the neighbors, only those that could + // possibly have points closer than the current closest. + // + for (i=0; inei[j] ? (nei[j]+1) : nei[j]); + diff = (this->Bounds[2*j] + MULTIPLES * this->H[j]) - x[j]; + dist2 += diff*diff; + } + } + + if ( dist2 < minDist2 ) + { + cno = nei[0] + nei[1]*this->Divisions[0] + nei[2]*this->Divisions[0]*this->Divisions[1]; + + if ( (ptIds = this->HashTable[cno]) ) + { + for (j=0; j < ptIds->GetNumberOfIds(); j++) + { + ptId = ptIds->GetId(j); + this->Points->GetPoint(ptId, pt); + if ( (dist2 = vtkMath::Distance2BetweenPoints(x,pt)) < minDist2 ) + { + closest = ptId; + minDist2 = dist2; + } + } + } + } + } + + return closest; +} + +// Return the list of points in the bucket containing x. +vtkIdList *vtkPointLocator::GetPointsInBucket(const double x[3], + int ijk[3]) +{ + int i; + + // Make sure candidate point is in bounds. If not, it is outside. + // + for (i=0; i<3; i++) + { + if ( x[i] < this->Bounds[2*i] || x[i] > this->Bounds[2*i+1] ) + { + return NULL; + } + } + + // Find bucket point is in. + // + for (i=0; i<3; i++) + { + ijk[i] = (int)(((x[i] - this->Bounds[2*i]) / + (this->Bounds[2*i+1] - this->Bounds[2*i])) * this->Divisions[i]); + if (ijk[i] >= this->Divisions[i]) + { + ijk[i] = this->Divisions[i] - 1; + } + } + + // Get the id list, if any + // + if ( this->HashTable ) + { + int idx = ijk[0] + ijk[1]*this->Divisions[0] + + ijk[2]*this->Divisions[0]*this->Divisions[1]; + + return this->HashTable[idx]; + } + + return NULL; +} + + +// Build polygonal representation of locator. Create faces that separate +// inside/outside buckets, or separate inside/boundary of locator. +void vtkPointLocator::GenerateRepresentation(int vtkNotUsed(level), + vtkPolyData *pd) +{ + vtkPoints *pts; + vtkCellArray *polys; + int ii, i, j, k, idx, offset[3], minusOffset[3], inside, sliceSize; + + if ( this->HashTable == NULL ) + { + vtkErrorMacro(<<"Can't build representation...no data!"); + return; + } + + pts = vtkPoints::New(); + pts->Allocate(5000); + polys = vtkCellArray::New(); + polys->Allocate(10000); + + // loop over all buckets, creating appropriate faces + sliceSize = this->Divisions[0] * this->Divisions[1]; + for ( k=0; k < this->Divisions[2]; k++) + { + offset[2] = k * sliceSize; + minusOffset[2] = (k-1) * sliceSize; + for ( j=0; j < this->Divisions[1]; j++) + { + offset[1] = j * this->Divisions[0]; + minusOffset[1] = (j-1) * this->Divisions[0]; + for ( i=0; i < this->Divisions[0]; i++) + { + offset[0] = i; + minusOffset[0] = i - 1; + idx = offset[0] + offset[1] + offset[2]; + if ( this->HashTable[idx] == NULL ) + { + inside = 0; + } + else + { + inside = 1; + } + + //check "negative" neighbors + for (ii=0; ii < 3; ii++) + { + if ( minusOffset[ii] < 0 ) + { + if ( inside ) + { + this->GenerateFace(ii,i,j,k,pts,polys); + } + } + else + { + if ( ii == 0 ) + { + idx = minusOffset[0] + offset[1] + offset[2]; + } + else if ( ii == 1 ) + { + idx = offset[0] + minusOffset[1] + offset[2]; + } + else + { + idx = offset[0] + offset[1] + minusOffset[2]; + } + + if ( (this->HashTable[idx] == NULL && inside) || + (this->HashTable[idx] != NULL && !inside) ) + { + this->GenerateFace(ii,i,j,k,pts,polys); + } + } + //those buckets on "positive" boundaries can generate faces specially + if ( (i+1) >= this->Divisions[0] && inside ) + { + this->GenerateFace(0,i+1,j,k,pts,polys); + } + if ( (j+1) >= this->Divisions[1] && inside ) + { + this->GenerateFace(1,i,j+1,k,pts,polys); + } + if ( (k+1) >= this->Divisions[2] && inside ) + { + this->GenerateFace(2,i,j,k+1,pts,polys); + } + + }//over negative faces + }//over i divisions + }//over j divisions + }//over k divisions + + + pd->SetPoints(pts); + pts->Delete(); + pd->SetPolys(polys); + polys->Delete(); + pd->Squeeze(); +} + +void vtkPointLocator::GenerateFace(int face, int i, int j, int k, + vtkPoints *pts, vtkCellArray *polys) +{ + vtkIdType ids[4]; + double origin[3], x[3]; + + // define first corner + origin[0] = this->Bounds[0] + i * this->H[0]; + origin[1] = this->Bounds[2] + j * this->H[1]; + origin[2] = this->Bounds[4] + k * this->H[2]; + ids[0] = pts->InsertNextPoint(origin); + + if ( face == 0 ) //x face + { + x[0] = origin[0]; + x[1] = origin[1] + this->H[1]; + x[2] = origin[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1] + this->H[1]; + x[2] = origin[2] + this->H[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1]; + x[2] = origin[2] + this->H[2]; + ids[3] = pts->InsertNextPoint(x); + } + + else if ( face == 1 ) //y face + { + x[0] = origin[0] + this->H[0]; + x[1] = origin[1]; + x[2] = origin[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = origin[0] + this->H[0]; + x[1] = origin[1]; + x[2] = origin[2] + this->H[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1]; + x[2] = origin[2] + this->H[2]; + ids[3] = pts->InsertNextPoint(x); + } + + else //z face + { + x[0] = origin[0] + this->H[0]; + x[1] = origin[1]; + x[2] = origin[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = origin[0] + this->H[0]; + x[1] = origin[1] + this->H[1]; + x[2] = origin[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = origin[0]; + x[1] = origin[1] + this->H[1]; + x[2] = origin[2]; + ids[3] = pts->InsertNextPoint(x); + } + + polys->InsertNextCell(4,ids); +} + + +// Calculate the distance between the point x to the bucket "nei". +// +// WARNING!!!!! Be very careful altering this routine. Simple changes to this +// routine can make is 25% slower!!!! +// +double vtkPointLocator::Distance2ToBucket(const double x[3], + const int nei[3]) +{ + double bounds[6]; + + bounds[0] = nei[0]*this->H[0] + this->Bounds[0]; + bounds[1] = (nei[0]+1)*this->H[0] + this->Bounds[0]; + bounds[2] = nei[1]*this->H[1] + this->Bounds[2]; + bounds[3] = (nei[1]+1)*this->H[1] + this->Bounds[2]; + bounds[4] = nei[2]*this->H[2] + this->Bounds[4]; + bounds[5] = (nei[2]+1)*this->H[2] + this->Bounds[4]; + + return this->Distance2ToBounds(x, bounds); +} + +// Calculate the distance between the point x and the specified bounds +// +// WARNING!!!!! Be very careful altering this routine. Simple changes to this +// routine can make is 25% slower!!!! +double vtkPointLocator::Distance2ToBounds(const double x[3], + const double bounds[6]) +{ + double distance; + double deltas[3]; + + // Are we within the bounds? + if (x[0] >= bounds[0] && x[0] <= bounds[1] + && x[1] >= bounds[2] && x[1] <= bounds[3] + && x[2] >= bounds[4] && x[2] <= bounds[5]) + { + return 0.0; + } + + deltas[0] = deltas[1] = deltas[2] = 0.0; + + // dx + // + if (x[0] < bounds[0]) + { + deltas[0] = bounds[0] - x[0]; + } + else if (x[0] > bounds[1]) + { + deltas[0] = x[0] - bounds[1]; + } + + // dy + // + if (x[1] < bounds[2]) + { + deltas[1] = bounds[2] - x[1]; + } + else if (x[1] > bounds[3]) + { + deltas[1] = x[1] - bounds[3]; + } + + // dz + // + if (x[2] < bounds[4]) + { + deltas[2] = bounds[4] - x[2]; + } + else if (x[2] > bounds[5]) + { + deltas[2] = x[2] - bounds[5]; + } + + distance = vtkMath::Dot(deltas, deltas); + return distance; +} + + +void vtkPointLocator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of Points Per Bucket: " << this->NumberOfPointsPerBucket << "\n"; + os << indent << "Divisions: (" << this->Divisions[0] << ", " + << this->Divisions[1] << ", " << this->Divisions[2] << ")\n"; + if ( this->Points ) + { + os << indent << "Points:\n"; + this->Points->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Points: (none)\n"; + } +} + diff --git a/Filtering/vtkPointLocator.h b/Filtering/vtkPointLocator.h new file mode 100644 index 0000000..ea0a772 --- /dev/null +++ b/Filtering/vtkPointLocator.h @@ -0,0 +1,245 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointLocator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointLocator - quickly locate points in 3-space +// .SECTION Description +// vtkPointLocator is a spatial search object to quickly locate points in 3D. +// vtkPointLocator works by dividing a specified region of space into a regular +// array of "rectangular" buckets, and then keeping a list of points that +// lie in each bucket. Typical operation involves giving a position in 3D +// and finding the closest point. +// +// vtkPointLocator has two distinct methods of interaction. In the first +// method, you supply it with a dataset, and it operates on the points in +// the dataset. In the second method, you supply it with an array of points, +// and the object operates on the array. + +// .SECTION Caveats +// Many other types of spatial locators have been developed such as +// octrees and kd-trees. These are often more efficient for the +// operations described here. + +// .SECTION See Also +// vtkCellPicker vtkPointPicker + +#ifndef __vtkPointLocator_h +#define __vtkPointLocator_h + +#include "vtkLocator.h" + +class vtkCellArray; +class vtkIdList; +class vtkNeighborPoints; +class vtkPoints; + +class VTK_FILTERING_EXPORT vtkPointLocator : public vtkLocator +{ +public: + // Description: + // Construct with automatic computation of divisions, averaging + // 25 points per bucket. + static vtkPointLocator *New(); + + vtkTypeRevisionMacro(vtkPointLocator,vtkLocator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the number of divisions in x-y-z directions. + vtkSetVector3Macro(Divisions,int); + vtkGetVectorMacro(Divisions,int,3); + + // Description: + // Specify the average number of points in each bucket. + vtkSetClampMacro(NumberOfPointsPerBucket,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfPointsPerBucket,int); + + // Description: + // Given a position x, return the id of the point closest to it. Alternative + // method requires separate x-y-z values. + // These methods are thread safe if BuildLocator() is directly or + // indirectly called from a single thread first. + virtual vtkIdType FindClosestPoint(const double x[3]); + vtkIdType FindClosestPoint(double x, double y, double z); + + // Description: + // Given a position x and a radius r, return the id of the point + // closest to the point in that radius. + // These methods are thread safe if BuildLocator() is directly or + // indirectly called from a single thread first. dist2 returns the squared + // distance to the point. + vtkIdType FindClosestPointWithinRadius(double radius, const double x[3], + double& dist2); + vtkIdType FindClosestPointWithinRadius(double radius, const double x[3], + double inputDataLength, double& dist2); + + // Description: + // Initialize the point insertion process. The newPts is an object + // representing point coordinates into which incremental insertion methods + // place their data. Bounds are the box that the points lie in. + // Not thread safe. + virtual int InitPointInsertion(vtkPoints *newPts, const double bounds[6]); + + // Description: + // Initialize the point insertion process. The newPts is an object + // representing point coordinates into which incremental insertion methods + // place their data. Bounds are the box that the points lie in. + // Not thread safe. + virtual int InitPointInsertion(vtkPoints *newPts, const double bounds[6], + vtkIdType estSize); + + // Description: + // Incrementally insert a point into search structure with a particular + // index value. You should use the method IsInsertedPoint() to see whether + // this point has already been inserted (that is, if you desire to prevent + // duplicate points). Before using this method you must make sure that + // newPts have been supplied, the bounds has been set properly, and that + // divs are properly set. (See InitPointInsertion().) + // Not thread safe. + virtual void InsertPoint(vtkIdType ptId, const double x[3]); + + // Description: + // Incrementally insert a point into search structure. The method returns + // the insertion location (i.e., point id). You should use the method + // IsInsertedPoint() to see whether this point has already been + // inserted (that is, if you desire to prevent duplicate points). + // Before using this method you must make sure that newPts have been + // supplied, the bounds has been set properly, and that divs are + // properly set. (See InitPointInsertion().) + // Not thread safe. + virtual vtkIdType InsertNextPoint(const double x[3]); + + // Description: + // Determine whether point given by x[3] has been inserted into points list. + // Return id of previously inserted point if this is true, otherwise return + // -1. This method is thread safe. + vtkIdType IsInsertedPoint(double x, double y, double z) + { + double xyz[3]; + xyz[0] = x; xyz[1] = y; xyz[2] = z; + return this->IsInsertedPoint (xyz); + }; + virtual vtkIdType IsInsertedPoint(const double x[3]); + + // Description: + // Determine whether point given by x[3] has been inserted into points list. + // Return 0 if point was already in the list, otherwise return 1. If the + // point was not in the list, it will be ADDED. In either case, the id of + // the point (newly inserted or not) is returned in the ptId argument. + // Note this combines the functionality of IsInsertedPoint() followed + // by a call to InsertNextPoint(). + // This method is not thread safe. + virtual int InsertUniquePoint(const double x[3], vtkIdType &ptId); + + // Description: + // Given a position x, return the id of the point closest to it. This method + // is used when performing incremental point insertion. Note that -1 + // indicates that no point was found. + // This method is thread safe if BuildLocator() is directly or + // indirectly called from a single thread first. + virtual vtkIdType FindClosestInsertedPoint(const double x[3]); + + // Description: + // Find the closest N points to a position. This returns the closest + // N points to a position. A faster method could be created that returned + // N close points to a position, but necessarily the exact N closest. + // The returned points are sorted from closest to farthest. + // These methods are thread safe if BuildLocator() is directly or + // indirectly called from a single thread first. + virtual void FindClosestNPoints(int N, const double x[3], vtkIdList *result); + virtual void FindClosestNPoints(int N, double x, double y, double z, + vtkIdList *result); + + // Description: + // Find the closest points to a position such that each octant of + // space around the position contains at least N points. Loosely + // limit the search to a maximum number of points evaluated, M. + // These methods are thread safe if BuildLocator() is directly or + // indirectly called from a single thread first. + virtual void FindDistributedPoints(int N, const double x[3], + vtkIdList *result, int M); + virtual void FindDistributedPoints(int N, double x, double y, + double z, vtkIdList *result, int M); + + // Description: + // Find all points within a specified radius R of position x. + // The result is not sorted in any specific manner. + // These methods are thread safe if BuildLocator() is directly or + // indirectly called from a single thread first. + virtual void FindPointsWithinRadius(double R, const double x[3], + vtkIdList *result); + virtual void FindPointsWithinRadius(double R, double x, double y, double z, + vtkIdList *result); + + // Description: + // Given a position x, return the list of points in the bucket that + // contains the point. It is possible that NULL is returned. The user + // provides an ijk array that is the indices into the locator. + // This method is thread safe. + virtual vtkIdList *GetPointsInBucket(const double x[3], int ijk[3]); + + // Description: + // Provide an accessor to the points. + vtkGetObjectMacro(Points, vtkPoints); + + // Description: + // Provide an accessor to the bounds. + double *GetBounds() { return this->Bounds; }; + + // Description: + // See vtkLocator interface documentation. + // These methods are not thread safe. + void Initialize(); + void FreeSearchStructure(); + void BuildLocator(); + void GenerateRepresentation(int level, vtkPolyData *pd); + +protected: + vtkPointLocator(); + ~vtkPointLocator(); + + // place points in appropriate buckets + void GetBucketNeighbors(vtkNeighborPoints* buckets, + const int ijk[3], const int ndivs[3], int level); + void GetOverlappingBuckets(vtkNeighborPoints* buckets, + const double x[3], const int ijk[3], double dist, + int level); + void GetOverlappingBuckets(vtkNeighborPoints* buckets, + const double x[3], double dist, + int prevMinLevel[3], + int prevMaxLevel[3]); + void GenerateFace(int face, int i, int j, int k, + vtkPoints *pts, vtkCellArray *polys); + double Distance2ToBucket(const double x[3], const int nei[3]); + double Distance2ToBounds(const double x[3], const double bounds[6]); + + vtkPoints *Points; // Used for merging points + int Divisions[3]; // Number of sub-divisions in x-y-z directions + int NumberOfPointsPerBucket; //Used with previous boolean to control subdivide + double Bounds[6]; // bounds of points + vtkIdList **HashTable; // lists of point ids in buckets + vtkIdType NumberOfBuckets; // total size of hash table + double H[3]; // width of each bucket in x-y-z directions + + double InsertionTol2; + vtkIdType InsertionPointId; + + double InsertionLevel; +private: + vtkPointLocator(const vtkPointLocator&); // Not implemented. + void operator=(const vtkPointLocator&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkPointSet.cxx b/Filtering/vtkPointSet.cxx new file mode 100644 index 0000000..8106c0e --- /dev/null +++ b/Filtering/vtkPointSet.cxx @@ -0,0 +1,403 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointSet.h" + +#include "vtkCell.h" +#include "vtkGarbageCollector.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPointLocator.h" +#include "vtkSource.h" + +vtkCxxRevisionMacro(vtkPointSet, "$Revision: 1.3.12.1 $"); + +vtkCxxSetObjectMacro(vtkPointSet,Points,vtkPoints); + +vtkPointSet::vtkPointSet () +{ + this->Points = NULL; + this->Locator = NULL; +} + +//---------------------------------------------------------------------------- +vtkPointSet::~vtkPointSet () +{ + this->Initialize(); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +//---------------------------------------------------------------------------- +// Copy the geometric structure of an input point set object. +void vtkPointSet::CopyStructure(vtkDataSet *ds) +{ + vtkPointSet *ps=(vtkPointSet *)ds; + + if ( this->Points != ps->Points ) + { + if ( this->Locator ) + { + this->Locator->Initialize(); + } + this->SetPoints(ps->Points); + } +} + + +//---------------------------------------------------------------------------- +void vtkPointSet::Initialize() +{ + vtkDataSet::Initialize(); + + if ( this->Points ) + { + this->Points->UnRegister(this); + this->Points = NULL; + } + + if ( this->Locator ) + { + this->Locator->Initialize(); + } +} +//---------------------------------------------------------------------------- +void vtkPointSet::ComputeBounds() +{ + double *bounds; + + if ( this->Points ) + { + bounds = this->Points->GetBounds(); + for (int i=0; i<6; i++) + { + this->Bounds[i] = bounds[i]; + } + this->ComputeTime.Modified(); + } +} + +//---------------------------------------------------------------------------- +unsigned long int vtkPointSet::GetMTime() +{ + unsigned long int dsTime = vtkDataSet::GetMTime(); + + if ( this->Points ) + { + if ( this->Points->GetMTime() > dsTime ) + { + dsTime = this->Points->GetMTime(); + } + } + + // don't get locator's mtime because its an internal object that cannot be + // modified directly from outside. Causes problems due to FindCell() + // SetPoints() method. + + return dsTime; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkPointSet::FindPoint(double x[3]) +{ + if ( !this->Points ) + { + return -1; + } + + if ( !this->Locator ) + { + this->Locator = vtkPointLocator::New(); + this->Locator->Register(this); + this->Locator->Delete(); + this->Locator->SetDataSet(this); + } + + if ( this->Points->GetMTime() > this->Locator->GetMTime() ) + { + this->Locator->SetDataSet(this); + } + + return this->Locator->FindClosestPoint(x); +} + +//the furthest the walk can be - prevents aimless wandering +#define VTK_MAX_WALK 12 + +//---------------------------------------------------------------------------- +vtkIdType vtkPointSet::FindCell(double x[3], vtkCell *cell, + vtkGenericCell *gencell, vtkIdType cellId, + double tol2, int& subId, double pcoords[3], + double *weights) +{ + vtkIdType ptId; + int walk; + double closestPoint[3]; + double dist2; + vtkIdList *cellIds, *ptIds; + int initialCellProvided = 1; + + // make sure everything is up to snuff + if ( !this->Points ) + { + return -1; + } + + cellIds = vtkIdList::New(); + cellIds->Allocate(8,100); + ptIds = vtkIdList::New(); + ptIds->Allocate(8,100); + + if ( !this->Locator ) + { + this->Locator = vtkPointLocator::New(); + this->Locator->Register(this); + this->Locator->Delete(); + this->Locator->SetDataSet(this); + } + + if ( this->Points->GetMTime() > this->Locator->GetMTime() ) + { + this->Locator->SetDataSet(this); + } + + // If we don't have a starting cell, we'll have to find one. Find + // the closest point to the input position, then get the cells that use + // the point. Then use one of the cells to begin the walking process. + if ( !cell ) + { + initialCellProvided = 0; + ptId = this->Locator->FindClosestPoint(x); + if ( ptId < 0 ) + { + cellIds->Delete(); + ptIds->Delete(); + return (-1); //if point completely outside of data + } + + this->GetPointCells(ptId, cellIds); + if ( cellIds->GetNumberOfIds() > 0 ) + { + cellId = cellIds->GetId(0); //arbitrarily use first cell in list + if ( gencell ) + { + this->GetCell(cellId, gencell); + } + else + { + cell = this->GetCell(cellId); + } + + // See whether this randomly choosen cell contains the point + double dx[3]; + dx[0] = x[0]; + dx[1] = x[1]; + dx[2] = x[2]; + if ( ( gencell && + gencell->EvaluatePosition(dx,closestPoint,subId, + pcoords, dist2,weights) == 1 + && dist2 <= tol2 ) || + ( !gencell && + cell->EvaluatePosition(dx,closestPoint,subId, + pcoords, dist2,weights) == 1 + && dist2 <= tol2 ) ) + { + cellIds->Delete(); + ptIds->Delete(); + return cellId; + } + } + } + else //EvaluatePosition insures that pcoords is defined + { + cell->EvaluatePosition(x,NULL,subId,pcoords,dist2,weights); + } + + // If a cell is supplied, or we didn't find a starting cell (in the + // previous chunk of code), then we use this to start our search. A + // walking scheme is used, where we walk towards the point and eventually + // locate the cell that contains the point. + if ( cell || cellIds->GetNumberOfIds() > 0 ) //we have a starting cell + { + for ( walk=0; walk < VTK_MAX_WALK; walk++ ) + { + if ( cell ) + { + cell->CellBoundary(subId, pcoords, ptIds); + } + else + { + gencell->CellBoundary(subId, pcoords, ptIds); + } + this->GetCellNeighbors(cellId, ptIds, cellIds); + if ( cellIds->GetNumberOfIds() > 0 ) + { + cellId = cellIds->GetId(0); + if ( gencell ) + { + cell = NULL; + this->GetCell(cellId, gencell); + } + else + { + cell = this->GetCell(cellId); + } + } + else + { + break; //outside of data + } + + if ( ( (!cell && + gencell->EvaluatePosition(x,closestPoint,subId,pcoords, + dist2,weights) == 1 ) || + (cell && cell->EvaluatePosition(x,closestPoint, + subId,pcoords, + dist2,weights) == 1 ) ) + && dist2 <= tol2 ) + { + cellIds->Delete(); + ptIds->Delete(); + return cellId; + } + + }//for a walk + }//if we have a starting cell + + cellIds->Delete(); + ptIds->Delete(); + + //sometimes the initial cell is a really bad guess so we'll + //just ignore it and start from scratch as a last resort + if ( initialCellProvided ) + { + return this->FindCell(x, NULL, gencell, cellId, tol2, + subId, pcoords, weights); + } + else + { + return -1; + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkPointSet::FindCell(double x[3], vtkCell *cell, vtkIdType cellId, + double tol2, int& subId,double pcoords[3], + double *weights) +{ + return + this->FindCell( x, cell, NULL, cellId, tol2, subId, pcoords, weights ); +} + +#undef VTK_MAX_WALK + + +//---------------------------------------------------------------------------- +void vtkPointSet::Squeeze() +{ + if ( this->Points ) + { + this->Points->Squeeze(); + } + vtkDataSet::Squeeze(); +} + +//---------------------------------------------------------------------------- +void vtkPointSet::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->Locator, "Locator"); +} + +//---------------------------------------------------------------------------- +unsigned long vtkPointSet::GetActualMemorySize() +{ + unsigned long size=this->vtkDataSet::GetActualMemorySize(); + if ( this->Points ) + { + size += this->Points->GetActualMemorySize(); + } + return size; +} + +//---------------------------------------------------------------------------- +void vtkPointSet::ShallowCopy(vtkDataObject *dataObject) +{ + vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject); + + if ( pointSet != NULL ) + { + this->SetPoints(pointSet->GetPoints()); + } + + // Do superclass + this->vtkDataSet::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkPointSet::DeepCopy(vtkDataObject *dataObject) +{ + vtkPointSet *pointSet = vtkPointSet::SafeDownCast(dataObject); + + if ( pointSet != NULL ) + { + if (this->Points == NULL) + { + if ( pointSet->GetPoints() != NULL ) + { + this->Points = pointSet->GetPoints()->NewInstance(); + this->Points->SetDataType(pointSet->GetPoints()->GetDataType()); + this->Points->Register(this); + this->Points->Delete(); + } + else + { + this->Points = vtkPoints::New(); + this->Points->Register(this); + this->Points->Delete(); + } + } + this->Points->DeepCopy(pointSet->GetPoints()); + } + + // Do superclass + this->vtkDataSet::DeepCopy(dataObject); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkPointSet::GetData(vtkInformation* info) +{ + return info? vtkPointSet::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkPointSet::GetData(vtkInformationVector* v, int i) +{ + return vtkPointSet::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +void vtkPointSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Points: " << this->GetNumberOfPoints() << "\n"; + os << indent << "Point Coordinates: " << this->Points << "\n"; + os << indent << "Locator: " << this->Locator << "\n"; +} + diff --git a/Filtering/vtkPointSet.h b/Filtering/vtkPointSet.h new file mode 100644 index 0000000..96abdd3 --- /dev/null +++ b/Filtering/vtkPointSet.h @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointSet - abstract class for specifying dataset behavior +// .SECTION Description +// vtkPointSet is an abstract class that specifies the interface for +// datasets that explicitly use "point" arrays to represent geometry. +// For example, vtkPolyData and vtkUnstructuredGrid require point arrays +// to specify point position, while vtkStructuredPoints generates point +// positions implicitly. + +// .SECTION See Also +// vtkPolyData vtkStructuredGrid vtkUnstructuredGrid + +#ifndef __vtkPointSet_h +#define __vtkPointSet_h + +#include "vtkDataSet.h" + +#include "vtkPoints.h" // Needed for inline methods + +class vtkPointLocator; + +class VTK_FILTERING_EXPORT vtkPointSet : public vtkDataSet +{ +public: + vtkTypeRevisionMacro(vtkPointSet,vtkDataSet); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Reset to an empty state and free any memory. + void Initialize(); + + // Description: + // Copy the geometric structure of an input point set object. + void CopyStructure(vtkDataSet *pd); + + // Description: + // See vtkDataSet for additional information. + vtkIdType GetNumberOfPoints(); + double *GetPoint(vtkIdType ptId) {return this->Points->GetPoint(ptId);}; + void GetPoint(vtkIdType ptId, double x[3]) {this->Points->GetPoint(ptId,x);}; + vtkIdType FindPoint(double x[3]); + vtkIdType FindPoint(double x, double y, double z) { return this->vtkDataSet::FindPoint(x, y, z);}; + vtkIdType FindCell(double x[3], vtkCell *cell, vtkIdType cellId, double tol2, + int& subId, double pcoords[3], double *weights); + vtkIdType FindCell(double x[3], vtkCell *cell, vtkGenericCell *gencell, + vtkIdType cellId, double tol2, int& subId, + double pcoords[3], double *weights); + + // Description: + // Get MTime which also considers its vtkPoints MTime. + unsigned long GetMTime(); + + // Description: + // Compute the (X, Y, Z) bounds of the data. + void ComputeBounds(); + + // Description: + // Reclaim any unused memory. + void Squeeze(); + + // Description: + // Specify point array to define point coordinates. + virtual void SetPoints(vtkPoints*); + vtkGetObjectMacro(Points,vtkPoints); + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). THIS METHOD + // IS THREAD SAFE. + unsigned long GetActualMemorySize(); + + // Description: + // Shallow and Deep copy. + void ShallowCopy(vtkDataObject *src); + void DeepCopy(vtkDataObject *src); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkPointSet* GetData(vtkInformation* info); + static vtkPointSet* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkPointSet(); + ~vtkPointSet(); + + vtkPoints *Points; + vtkPointLocator *Locator; + + virtual void ReportReferences(vtkGarbageCollector*); +private: + vtkPointSet(const vtkPointSet&); // Not implemented. + void operator=(const vtkPointSet&); // Not implemented. +}; + +inline vtkIdType vtkPointSet::GetNumberOfPoints() +{ + if (this->Points) + { + return this->Points->GetNumberOfPoints(); + } + else + { + return 0; + } +} + + +#endif + + diff --git a/Filtering/vtkPointSetAlgorithm.cxx b/Filtering/vtkPointSetAlgorithm.cxx new file mode 100644 index 0000000..b07240c --- /dev/null +++ b/Filtering/vtkPointSetAlgorithm.cxx @@ -0,0 +1,226 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSetAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointSetAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkPointSetAlgorithm, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkPointSetAlgorithm); + +//---------------------------------------------------------------------------- +// Instantiate object so that cell data is not passed to output. +vtkPointSetAlgorithm::vtkPointSetAlgorithm() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkPointSetAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkPointSetAlgorithm::GetOutput(int port) +{ + return vtkPointSet::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkPolyData. +vtkPolyData *vtkPointSetAlgorithm::GetPolyDataOutput() +{ + return vtkPolyData::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkStructuredGrid. +vtkStructuredGrid *vtkPointSetAlgorithm::GetStructuredGridOutput() +{ + return vtkStructuredGrid::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +// Get the output as vtkUnstructuredGrid. +vtkUnstructuredGrid *vtkPointSetAlgorithm::GetUnstructuredGridOutput() +{ + return vtkUnstructuredGrid::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::SetInput(vtkPointSet* input) +{ + this->SetInput(0, static_cast(input)); +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::SetInput(int index, vtkPointSet* input) +{ + this->SetInput(index, static_cast(input)); +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::AddInput(vtkPointSet* input) +{ + this->AddInput(0, static_cast(input)); +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::AddInput(int index, vtkPointSet* input) +{ + this->AddInput(index, static_cast(input)); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkPointSetAlgorithm::GetInput() +{ + return this->GetExecutive()->GetInputData(0, 0); +} + +//---------------------------------------------------------------------------- +int vtkPointSetAlgorithm::ProcessRequest( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + // create the output + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + return this->RequestDataObject(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->ExecuteInformation(request, inputVector, outputVector); + } + + // set update extent + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->ComputeInputUpdateExtent(request, inputVector, outputVector); + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkPointSetAlgorithm::RequestDataObject( + vtkInformation*, + vtkInformationVector** inputVector , + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + if (!inInfo) + { + return 0; + } + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (input) + { + // for each output + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* info = outputVector->GetInformationObject(i); + vtkPointSet *output = vtkPointSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + if (!output || !output->IsA(input->GetClassName())) + { + output = input->NewInstance(); + output->SetPipelineInformation(info); + output->Delete(); + this->GetOutputPortInformation(i)->Set( + vtkDataObject::DATA_EXTENT_TYPE(), output->GetExtentType()); + } + } + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkPointSetAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPointSet"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPointSetAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPointSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPointSetAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkPointSetAlgorithm.h b/Filtering/vtkPointSetAlgorithm.h new file mode 100644 index 0000000..2561d16 --- /dev/null +++ b/Filtering/vtkPointSetAlgorithm.h @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSetAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointSetAlgorithm - Superclass for algorithms that produce output of the same type as input +// .SECTION Description +// vtkPointSetAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// contstructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be PointSet. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// RequestDataObject RequestData and ExecuteInformation. The default +// implementation of RequestDataObject will create an output data of the +// same type as the input. + + +#ifndef __vtkPointSetAlgorithm_h +#define __vtkPointSetAlgorithm_h + +#include "vtkAlgorithm.h" + +class vtkPointSet; +class vtkPolyData; +class vtkStructuredGrid; +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkPointSetAlgorithm : public vtkAlgorithm +{ +public: + static vtkPointSetAlgorithm *New(); + vtkTypeRevisionMacro(vtkPointSetAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkPointSet* GetOutput(); + vtkPointSet* GetOutput(int); + + // Description: + // Get the output as vtkPolyData. + vtkPolyData *GetPolyDataOutput(); + + // Description: + // Get the output as vtkStructuredGrid. + vtkStructuredGrid *GetStructuredGridOutput(); + + // Description: + // Get the output as vtkUnstructuredGrid. + vtkUnstructuredGrid *GetUnstructuredGridOutput(); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject*); + void SetInput(int, vtkDataObject*); + void SetInput(vtkPointSet*); + void SetInput(int, vtkPointSet*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(vtkPointSet*); + void AddInput(int, vtkPointSet*); + void AddInput(int, vtkDataObject*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject *GetInput(); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +protected: + vtkPointSetAlgorithm(); + ~vtkPointSetAlgorithm() {}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestDataObject(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int ExecuteInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) {return 1;}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) {return 1;}; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int ComputeInputUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) + { + return 1; + }; + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkPointSetAlgorithm(const vtkPointSetAlgorithm&); // Not implemented. + void operator=(const vtkPointSetAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkPointSetSource.cxx b/Filtering/vtkPointSetSource.cxx new file mode 100644 index 0000000..af8f5f5 --- /dev/null +++ b/Filtering/vtkPointSetSource.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSetSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointSetSource.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPointSet.h" + +vtkCxxRevisionMacro(vtkPointSetSource, "$Revision: 1.13 $"); + +//---------------------------------------------------------------------------- +vtkPointSetSource::vtkPointSetSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkPointSet *vtkPointSetSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkPointSet *)(this->Outputs[0]); +} + + +//---------------------------------------------------------------------------- +vtkPointSet *vtkPointSetSource::GetOutput(int idx) +{ + return (vtkPointSet *) this->vtkSource::GetOutput(idx); +} + +//---------------------------------------------------------------------------- +void vtkPointSetSource::SetOutput(vtkPointSet *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + +//---------------------------------------------------------------------------- +int vtkPointSetSource::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPointSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPointSetSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkPointSetSource.h b/Filtering/vtkPointSetSource.h new file mode 100644 index 0000000..cb20ca3 --- /dev/null +++ b/Filtering/vtkPointSetSource.h @@ -0,0 +1,50 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSetSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointSetSource - abstract class whose subclasses generate point data +// .SECTION Description +// vtkPointSetSource is an abstract class whose subclasses generate pointdata. + +#ifndef __vtkPointDataSource_h +#define __vtkPointDataSource_h + +#include "vtkSource.h" + +class vtkPointSet; + +class VTK_FILTERING_EXPORT vtkPointSetSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkPointSetSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this source. + vtkPointSet *GetOutput(); + vtkPointSet *GetOutput(int idx); + void SetOutput(vtkPointSet *output); + +protected: + vtkPointSetSource(); + ~vtkPointSetSource() {}; + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkPointSetSource(const vtkPointSetSource&); // Not implemented. + void operator=(const vtkPointSetSource&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkPointSetToPointSetFilter.cxx b/Filtering/vtkPointSetToPointSetFilter.cxx new file mode 100644 index 0000000..724930f --- /dev/null +++ b/Filtering/vtkPointSetToPointSetFilter.cxx @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSetToPointSetFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointSetToPointSetFilter.h" +#include "vtkPolyData.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkPointSetToPointSetFilter, "$Revision: 1.61 $"); + +//---------------------------------------------------------------------------- +// Construct object. +vtkPointSetToPointSetFilter::vtkPointSetToPointSetFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkPointSetToPointSetFilter::~vtkPointSetToPointSetFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkPointSetToPointSetFilter::SetInput(vtkPointSet *input) +{ + vtkPointSet *oldInput = this->GetInput(); + + if (oldInput != NULL) + { + if (input == NULL || + oldInput->GetDataObjectType() != input->GetDataObjectType()) + { + vtkWarningMacro("Changing input type. Deleting output"); + this->SetOutput(NULL); + } + } + + if (input != NULL && this->vtkSource::GetOutput(0) == NULL) + { + this->vtkSource::SetNthOutput(0, input->NewInstance()); + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); + } + + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkPointSet *vtkPointSetToPointSetFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkPointSet *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +// Get the output of this filter. If output is NULL then input hasn't been set +// which is necessary for abstract objects. +vtkPointSet *vtkPointSetToPointSetFilter::GetOutput() +{ + if (this->GetInput() == NULL ) + { + vtkErrorMacro(<<"Abstract filters require input to be set before output can be retrieved"); + return NULL; + } + + return this->vtkPointSetSource::GetOutput(); +} + + +//---------------------------------------------------------------------------- +// Get the output as vtkPolyData. +vtkPolyData *vtkPointSetToPointSetFilter::GetPolyDataOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_POLY_DATA) + { + return (vtkPolyData *)ds; + } + return NULL; +} + +//---------------------------------------------------------------------------- +// Get the output as vtkStructuredGrid. Performs run-time checking. +vtkStructuredGrid *vtkPointSetToPointSetFilter::GetStructuredGridOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_STRUCTURED_GRID) + { + return (vtkStructuredGrid *)ds; + } + return NULL; +} + +//---------------------------------------------------------------------------- +// Get the output as vtkUnstructuredGrid. Performs run-time checking. +vtkUnstructuredGrid *vtkPointSetToPointSetFilter::GetUnstructuredGridOutput() +{ + vtkDataSet *ds = this->GetOutput(); + if (!ds) + { + return NULL; + } + if (ds->GetDataObjectType() == VTK_UNSTRUCTURED_GRID) + { + return (vtkUnstructuredGrid *)ds; + } + return NULL; +} + +//---------------------------------------------------------------------------- +// Copy the update information across +void vtkPointSetToPointSetFilter::ComputeInputUpdateExtents(vtkDataObject *output) +{ + vtkDataObject *input = this->GetInput(); + + input->SetUpdatePiece( output->GetUpdatePiece() ); + input->SetUpdateNumberOfPieces( output->GetUpdateNumberOfPieces() ); + input->SetUpdateGhostLevel( output->GetUpdateGhostLevel() ); + input->SetUpdateExtent( output->GetUpdateExtent() ); + input->RequestExactExtentOn(); +} + +//---------------------------------------------------------------------------- +void vtkPointSetToPointSetFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkPointSetToPointSetFilter.h b/Filtering/vtkPointSetToPointSetFilter.h new file mode 100644 index 0000000..d2adcc8 --- /dev/null +++ b/Filtering/vtkPointSetToPointSetFilter.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSetToPointSetFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointSetToPointSetFilter - abstract filter class +// .SECTION Description +// vtkPointSetToPointSetFilter is an abstract filter class whose subclasses +// take as input a point set and generates a point set on output. At a +// minimum, the concrete subclasses of vtkPointSetToPointSetFilter modify +// their point coordinates. They never modify their topological form, +// however. +// +// This is an abstract filter type. What that means is that the output of the +// filter is an abstract type (i.e., vtkPointSet), no matter what the input +// of the filter is. This can cause problems connecting together filters due +// to the change in dataset type. (For example, in a series of filters +// processing vtkPolyData, when a vtkPointSetToPointSetFilter or subclass is +// introduced into the pipeline, if the filter downstream of it takes +// vtkPolyData as input, the pipeline connection cannot be made.) To get +// around this problem, use one of the convenience methods to return a +// concrete type (e.g., vtkGetPolyDataOutput(), GetStructuredGridOutput(), +// etc.). + +// .SECTION See Also +// vtkTransformFilter vtkWarpScalar vtkWarpTo vtkWarpVector + +#ifndef __vtkPointSetToPointSetFilter_h +#define __vtkPointSetToPointSetFilter_h + +#include "vtkPointSetSource.h" + +class vtkPolyData; +class vtkStructuredGrid; +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkPointSetToPointSetFilter : public vtkPointSetSource +{ +public: + vtkTypeRevisionMacro(vtkPointSetToPointSetFilter,vtkPointSetSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the input data or filter. + void SetInput(vtkPointSet *input); + + // Description: + // Get the input data or filter. + vtkPointSet *GetInput(); + + // Description: + // Get the output of this filter. If output is NULL, then input hasn't been + // set, which is necessary for abstract filter objects. + vtkPointSet *GetOutput(); + vtkPointSet *GetOutput(int idx) + {return (vtkPointSet *) this->vtkPointSetSource::GetOutput(idx); }; + + // Description: + // Get the output as vtkPolyData. Performs run-time checking. + vtkPolyData *GetPolyDataOutput(); + + // Description: + // Get the output as vtkStructuredGrid. Performs run-time checking. + vtkStructuredGrid *GetStructuredGridOutput(); + + // Description: + // Get the output as vtkUnstructuredGrid. Performs run-time checking. + vtkUnstructuredGrid *GetUnstructuredGridOutput(); + + // Description: + // By default copy the output update extent to the input + virtual void ComputeInputUpdateExtents( vtkDataObject *output ); + +protected: + vtkPointSetToPointSetFilter(); + ~vtkPointSetToPointSetFilter(); + +private: + vtkPointSetToPointSetFilter(const vtkPointSetToPointSetFilter&); // Not implemented. + void operator=(const vtkPointSetToPointSetFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkPolyData.cxx b/Filtering/vtkPolyData.cxx new file mode 100644 index 0000000..04bb530 --- /dev/null +++ b/Filtering/vtkPolyData.cxx @@ -0,0 +1,2061 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyData.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCriticalSection.h" +#include "vtkEmptyCell.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPolyLine.h" +#include "vtkPolyVertex.h" +#include "vtkPolygon.h" +#include "vtkQuad.h" +#include "vtkTriangle.h" +#include "vtkTriangleStrip.h" +#include "vtkVertex.h" + +vtkCxxRevisionMacro(vtkPolyData, "$Revision: 1.5.12.1 $"); +vtkStandardNewMacro(vtkPolyData); + +//---------------------------------------------------------------------------- +// Initialize static member. This member is used to simplify traversal +// of verts, lines, polygons, and triangle strips lists. It basically +// "marks" empty lists so that the traveral method "GetNextCell" +// works properly. +vtkCellArray *vtkPolyData::Dummy = NULL; + +static vtkSimpleCriticalSection DummyCritSect; + +vtkPolyData::vtkPolyData () +{ + // Create these guys only when needed. This saves a huge amount + // of memory and time spent in memory allocation. + this->Vertex = NULL; + this->PolyVertex = NULL; + this->Line = NULL; + this->PolyLine = NULL; + this->Triangle = NULL; + this->Quad = NULL; + this->Polygon = NULL; + this->TriangleStrip = NULL; + this->EmptyCell = NULL; + + this->Verts = NULL; + this->Lines = NULL; + this->Polys = NULL; + this->Strips = NULL; + + this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_PIECES_EXTENT); + this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0); + + // static variable, initialized only once. + DummyCritSect.Lock(); + if (this->Dummy == NULL) + { + this->Dummy = vtkCellArray::New(); + this->Dummy->Register(this); + this->Dummy->Delete(); + } + else + { + this->Dummy->Register(this); + } + DummyCritSect.Unlock(); + + this->Cells = NULL; + this->Links = NULL; +} + +//---------------------------------------------------------------------------- +vtkPolyData::~vtkPolyData() +{ + vtkPolyData::Initialize(); + // Reference to static dummy persists. + // Keep destructed dummy from being used again. + DummyCritSect.Lock(); + if (this->Dummy->GetReferenceCount() == 1) + { + this->Dummy->UnRegister(this); + this->Dummy = NULL; + } + else + { + this->Dummy->UnRegister(this); + } + DummyCritSect.Unlock(); + + if (this->Vertex) + { + this->Vertex->Delete(); + } + + if (this->PolyVertex) + { + this->PolyVertex->Delete(); + } + + if (this->Line) + { + this->Line->Delete(); + } + + if (this->PolyLine) + { + this->PolyLine->Delete(); + } + + if (this->Triangle) + { + this->Triangle->Delete(); + } + + if (this->Quad) + { + this->Quad->Delete(); + } + + if (this->Polygon) + { + this->Polygon->Delete(); + } + + if (this->TriangleStrip) + { + this->TriangleStrip->Delete(); + } + + if (this->EmptyCell) + { + this->EmptyCell->Delete(); + } +} + +//---------------------------------------------------------------------------- +int vtkPolyData::GetPiece() +{ + return this->Information->Get(vtkDataObject::DATA_PIECE_NUMBER()); +} + +//---------------------------------------------------------------------------- +int vtkPolyData::GetNumberOfPieces() +{ + return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_PIECES()); +} + +//---------------------------------------------------------------------------- +int vtkPolyData::GetGhostLevel() +{ + return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS()); +} + +//---------------------------------------------------------------------------- +// Copy the geometric and topological structure of an input poly data object. +void vtkPolyData::CopyStructure(vtkDataSet *ds) +{ + vtkPolyData *pd=(vtkPolyData *)ds; + vtkPointSet::CopyStructure(ds); + + if (this->Verts != pd->Verts) + { + if (this->Verts) + { + this->Verts->UnRegister(this); + } + this->Verts = pd->Verts; + if (this->Verts) + { + this->Verts->Register(this); + } + } + + if (this->Lines != pd->Lines) + { + if (this->Lines) + { + this->Lines->UnRegister(this); + } + this->Lines = pd->Lines; + if (this->Lines) + { + this->Lines->Register(this); + } + } + + if (this->Polys != pd->Polys) + { + if (this->Polys) + { + this->Polys->UnRegister(this); + } + this->Polys = pd->Polys; + if (this->Polys) + { + this->Polys->Register(this); + } + } + + if (this->Strips != pd->Strips) + { + if (this->Strips) + { + this->Strips->UnRegister(this); + } + this->Strips = pd->Strips; + if (this->Strips) + { + this->Strips->Register(this); + } + } + + if ( this->Cells ) + { + this->Cells->UnRegister(this); + this->Cells = NULL; + } + + if ( this->Links ) + { + this->Links->UnRegister(this); + this->Links = NULL; + } + + // Reset this information to mantain the functionality that was present when + // CopyStructure called Initialize, which incorrectly wiped out attribute + // data. Someone MIGHT argue that this isn't the right thing to do. + this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 0); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0); +} + +//---------------------------------------------------------------------------- +int vtkPolyData::GetCellType(vtkIdType cellId) +{ + if ( !this->Cells ) + { + this->BuildCells(); + } + return this->Cells->GetCellType(cellId); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkPolyData::GetCell(vtkIdType cellId) +{ + int i, loc; + vtkIdType *pts, numPts; + vtkCell *cell = NULL; + unsigned char type; + + if ( !this->Cells ) + { + this->BuildCells(); + } + + type = this->Cells->GetCellType(cellId); + loc = this->Cells->GetCellLocation(cellId); + + switch (type) + { + case VTK_VERTEX: + if (!this->Vertex) + { + this->Vertex = vtkVertex::New(); + } + cell = this->Vertex; + this->Verts->GetCell(loc,numPts,pts); + break; + + case VTK_POLY_VERTEX: + if (! this->PolyVertex) + { + this->PolyVertex = vtkPolyVertex::New(); + } + cell = this->PolyVertex; + this->Verts->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + case VTK_LINE: + if (! this->Line ) + { + this->Line = vtkLine::New(); + } + cell = this->Line; + this->Lines->GetCell(loc,numPts,pts); + break; + + case VTK_POLY_LINE: + if (!this->PolyLine) + { + this->PolyLine = vtkPolyLine::New(); + } + cell = this->PolyLine; + this->Lines->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + case VTK_TRIANGLE: + if (!this->Triangle) + { + this->Triangle = vtkTriangle::New(); + } + cell = this->Triangle; + this->Polys->GetCell(loc,numPts,pts); + break; + + case VTK_QUAD: + if (!this->Quad) + { + this->Quad = vtkQuad::New(); + } + cell = this->Quad; + this->Polys->GetCell(loc,numPts,pts); + break; + + case VTK_POLYGON: + if (!this->Polygon) + { + this->Polygon = vtkPolygon::New(); + } + cell = this->Polygon; + this->Polys->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + case VTK_TRIANGLE_STRIP: + if (!this->TriangleStrip) + { + this->TriangleStrip = vtkTriangleStrip::New(); + } + cell = this->TriangleStrip; + this->Strips->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + default: + if (!this->EmptyCell) + { + this->EmptyCell = vtkEmptyCell::New(); + } + cell = this->EmptyCell; + numPts = 0; + return cell; + } + + for (i=0; i < numPts; i++) + { + cell->PointIds->SetId(i,pts[i]); + cell->Points->SetPoint(i,this->Points->GetPoint(pts[i])); + } + + return cell; +} + +//---------------------------------------------------------------------------- +void vtkPolyData::GetCell(vtkIdType cellId, vtkGenericCell *cell) +{ + int i, loc; + vtkIdType *pts=0; + vtkIdType numPts; + unsigned char type; + double x[3]; + + if ( !this->Cells ) + { + this->BuildCells(); + } + + type = this->Cells->GetCellType(cellId); + loc = this->Cells->GetCellLocation(cellId); + + switch (type) + { + case VTK_VERTEX: + cell->SetCellTypeToVertex(); + this->Verts->GetCell(loc,numPts,pts); + break; + + case VTK_POLY_VERTEX: + cell->SetCellTypeToPolyVertex(); + this->Verts->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + case VTK_LINE: + cell->SetCellTypeToLine(); + this->Lines->GetCell(loc,numPts,pts); + break; + + case VTK_POLY_LINE: + cell->SetCellTypeToPolyLine(); + this->Lines->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + case VTK_TRIANGLE: + cell->SetCellTypeToTriangle(); + this->Polys->GetCell(loc,numPts,pts); + break; + + case VTK_QUAD: + cell->SetCellTypeToQuad(); + this->Polys->GetCell(loc,numPts,pts); + break; + + case VTK_POLYGON: + cell->SetCellTypeToPolygon(); + this->Polys->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + case VTK_TRIANGLE_STRIP: + cell->SetCellTypeToTriangleStrip(); + this->Strips->GetCell(loc,numPts,pts); + cell->PointIds->SetNumberOfIds(numPts); //reset number of points + cell->Points->SetNumberOfPoints(numPts); + break; + + default: + cell->SetCellTypeToEmptyCell(); + numPts = 0; + } + + for (i=0; i < numPts; i++) + { + cell->PointIds->SetId(i,pts[i]); + this->Points->GetPoint(pts[i], x); + cell->Points->SetPoint(i, x); + } +} + +void vtkPolyData::CopyCells(vtkPolyData *pd, vtkIdList *idList, + vtkPointLocator *locator) +{ + vtkIdType cellId, ptId, newId, newCellId, locatorPtId; + int numPts, numCellPts, i; + vtkPoints *newPoints; + vtkIdList *pointMap = vtkIdList::New(); //maps old pt ids into new + vtkIdList *cellPts, *newCellPts = vtkIdList::New(); + vtkGenericCell *cell = vtkGenericCell::New(); + double x[3]; + vtkPointData *outPD = this->GetPointData(); + vtkCellData *outCD = this->GetCellData(); + + numPts = pd->GetNumberOfPoints(); + + if (this->GetPoints() == NULL) + { + this->Points = vtkPoints::New(); + } + + newPoints = this->GetPoints(); + + pointMap->SetNumberOfIds(numPts); + for (i=0; i < numPts; i++) + { + pointMap->SetId(i,-1); + } + + // Filter the cells + for (cellId=0; cellId < idList->GetNumberOfIds(); cellId++) + { + pd->GetCell(idList->GetId(cellId), cell); + cellPts = cell->GetPointIds(); + numCellPts = cell->GetNumberOfPoints(); + + for (i=0; i < numCellPts; i++) + { + ptId = cellPts->GetId(i); + if ( (newId = pointMap->GetId(ptId)) < 0 ) + { + pd->GetPoint(ptId, x); + if (locator != NULL) + { + if ((locatorPtId = locator->IsInsertedPoint(x)) == -1) + { + newId = newPoints->InsertNextPoint(x); + locator->InsertNextPoint(x); + pointMap->SetId(ptId, newId); + outPD->CopyData(pd->GetPointData(), ptId, newId); + } + else + { + newId = locatorPtId; + } + } + else + { + newId = newPoints->InsertNextPoint(x); + pointMap->SetId(ptId, newId); + outPD->CopyData(pd->GetPointData(), ptId, newId); + } + } + newCellPts->InsertId(i,newId); + } + newCellId = this->InsertNextCell(cell->GetCellType(), newCellPts); + outCD->CopyData(pd->GetCellData(), idList->GetId(cellId), newCellId); + newCellPts->Reset(); + } // for all cells + newCellPts->Delete(); + pointMap->Delete(); + cell->Delete(); +} + +//---------------------------------------------------------------------------- +// Fast implementation of GetCellBounds(). Bounds are calculated without +// constructing a cell. +void vtkPolyData::GetCellBounds(vtkIdType cellId, double bounds[6]) +{ + int i, loc; + vtkIdType *pts, numPts; + unsigned char type; + double x[3]; + + if ( !this->Cells ) + { + this->BuildCells(); + } + + type = this->Cells->GetCellType(cellId); + loc = this->Cells->GetCellLocation(cellId); + + switch (type) + { + case VTK_VERTEX: + case VTK_POLY_VERTEX: + this->Verts->GetCell(loc,numPts,pts); + break; + + case VTK_LINE: + case VTK_POLY_LINE: + this->Lines->GetCell(loc,numPts,pts); + break; + + case VTK_TRIANGLE: + case VTK_QUAD: + case VTK_POLYGON: + this->Polys->GetCell(loc,numPts,pts); + break; + + case VTK_TRIANGLE_STRIP: + this->Strips->GetCell(loc,numPts,pts); + break; + + default: + bounds[0] = bounds[1] = bounds[2] = bounds[3] = bounds[4] = bounds[5] + = 0.0; + return; + } + + // carefully compute the bounds + if (numPts) + { + this->Points->GetPoint( pts[0], x ); + bounds[0] = x[0]; + bounds[2] = x[1]; + bounds[4] = x[2]; + bounds[1] = x[0]; + bounds[3] = x[1]; + bounds[5] = x[2]; + for (i=1; i < numPts; i++) + { + this->Points->GetPoint( pts[i], x ); + bounds[0] = (x[0] < bounds[0] ? x[0] : bounds[0]); + bounds[1] = (x[0] > bounds[1] ? x[0] : bounds[1]); + bounds[2] = (x[1] < bounds[2] ? x[1] : bounds[2]); + bounds[3] = (x[1] > bounds[3] ? x[1] : bounds[3]); + bounds[4] = (x[2] < bounds[4] ? x[2] : bounds[4]); + bounds[5] = (x[2] > bounds[5] ? x[2] : bounds[5]); + } + } + else + { + vtkMath::UninitializeBounds(bounds); + } +} + + +//---------------------------------------------------------------------------- +void vtkPolyData::ComputeBounds() +{ + if (this->GetMTime() > this->ComputeTime) + { + // If there are no cells, but there are points, back to the + // bounds of the points set. + if (this->GetNumberOfCells() == 0 && this->GetNumberOfPoints()) + { + vtkPointSet::ComputeBounds(); + return; + } + + int t, i; + vtkIdType *pts = 0; + vtkIdType npts = 0; + double x[3]; + + vtkCellArray *cella[4]; + + cella[0] = this->GetVerts(); + cella[1] = this->GetLines(); + cella[2] = this->GetPolys(); + cella[3] = this->GetStrips(); + + // carefully compute the bounds + int doneOne = 0; + this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX; + this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX; + + // Iterate over cells's points + for (t = 0; t < 4; t++) + { + for (cella[t]->InitTraversal(); cella[t]->GetNextCell(npts,pts); ) + { + for (i = 0; i < npts; i++) + { + this->Points->GetPoint( pts[i], x ); + this->Bounds[0] = (x[0] < this->Bounds[0] ? x[0] : this->Bounds[0]); + this->Bounds[1] = (x[0] > this->Bounds[1] ? x[0] : this->Bounds[1]); + this->Bounds[2] = (x[1] < this->Bounds[2] ? x[1] : this->Bounds[2]); + this->Bounds[3] = (x[1] > this->Bounds[3] ? x[1] : this->Bounds[3]); + this->Bounds[4] = (x[2] < this->Bounds[4] ? x[2] : this->Bounds[4]); + this->Bounds[5] = (x[2] > this->Bounds[5] ? x[2] : this->Bounds[5]); + doneOne = 1; + } + } + } + if (!doneOne) + { + vtkMath::UninitializeBounds(this->Bounds); + } + this->ComputeTime.Modified(); + } +} + +//---------------------------------------------------------------------------- +// Set the cell array defining vertices. +void vtkPolyData::SetVerts (vtkCellArray* v) +{ + if (v == this->Dummy) + { + v = NULL; + } + if ( v != this->Verts) + { + if (this->Verts) + { + this->Verts->UnRegister(this); + } + this->Verts = v; + if (this->Verts) + { + this->Verts->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Get the cell array defining vertices. If there are no vertices, an +// empty array will be returned (convenience to simplify traversal). +vtkCellArray* vtkPolyData::GetVerts() +{ + if ( !this->Verts ) + { + return this->Dummy; + } + else + { + return this->Verts; + } +} + +//---------------------------------------------------------------------------- +// Set the cell array defining lines. +void vtkPolyData::SetLines (vtkCellArray* l) +{ + if (l == this->Dummy) + { + l = NULL; + } + if ( l != this->Lines) + { + if (this->Lines) + { + this->Lines->UnRegister(this); + } + this->Lines = l; + if (this->Lines) + { + this->Lines->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Get the cell array defining lines. If there are no lines, an +// empty array will be returned (convenience to simplify traversal). +vtkCellArray* vtkPolyData::GetLines() +{ + if ( !this->Lines ) + { + return this->Dummy; + } + else + { + return this->Lines; + } +} + +//---------------------------------------------------------------------------- +// Set the cell array defining polygons. +void vtkPolyData::SetPolys (vtkCellArray* p) +{ + if(p == this->Dummy) + { + p = NULL; + } + if ( p != this->Polys) + { + if (this->Polys) + { + this->Polys->UnRegister(this); + } + this->Polys = p; + if (this->Polys) + { + this->Polys->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Get the cell array defining polygons. If there are no polygons, an +// empty array will be returned (convenience to simplify traversal). +vtkCellArray* vtkPolyData::GetPolys() +{ + if ( !this->Polys ) + { + return this->Dummy; + } + else + { + return this->Polys; + } +} + +//---------------------------------------------------------------------------- +// Set the cell array defining triangle strips. +void vtkPolyData::SetStrips (vtkCellArray* s) +{ + if ( s == this->Dummy) + { + s = NULL; + } + if ( s != this->Strips) + { + if (this->Strips) + { + this->Strips->UnRegister(this); + } + this->Strips = s; + if (this->Strips) + { + this->Strips->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Get the cell array defining triangle strips. If there are no +// triangle strips, an empty array will be returned (convenience to +// simplify traversal). +vtkCellArray* vtkPolyData::GetStrips() +{ + if ( !this->Strips ) + { + return this->Dummy; + } + else + { + return this->Strips; + } +} + +//---------------------------------------------------------------------------- +// Restore object to initial state. Release memory back to system. +void vtkPolyData::Initialize() +{ + vtkPointSet::Initialize(); + + if ( this->Verts ) + { + this->Verts->UnRegister(this); + this->Verts = NULL; + } + + if ( this->Lines ) + { + this->Lines->UnRegister(this); + this->Lines = NULL; + } + + if ( this->Polys ) + { + this->Polys->UnRegister(this); + this->Polys = NULL; + } + + if ( this->Strips ) + { + this->Strips->UnRegister(this); + this->Strips = NULL; + } + + if ( this->Cells ) + { + this->Cells->UnRegister(this); + this->Cells = NULL; + } + + if ( this->Links ) + { + this->Links->UnRegister(this); + this->Links = NULL; + } + + if(this->Information) + { + this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 0); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0); + } +} + +//---------------------------------------------------------------------------- +int vtkPolyData::GetMaxCellSize() +{ + int maxCellSize=0, cellSize; + + if ( this->Verts ) + { + cellSize = this->Verts->GetMaxCellSize(); + if ( cellSize > maxCellSize ) + { + maxCellSize = cellSize; + } + } + + if ( this->Lines ) + { + cellSize = this->Lines->GetMaxCellSize(); + if ( cellSize > maxCellSize ) + { + maxCellSize = cellSize; + } + } + + if ( this->Polys ) + { + cellSize = this->Polys->GetMaxCellSize(); + if ( cellSize > maxCellSize ) + { + maxCellSize = cellSize; + } + } + + if ( this->Strips ) + { + cellSize = this->Strips->GetMaxCellSize(); + if ( cellSize > maxCellSize ) + { + maxCellSize = cellSize; + } + } + + return maxCellSize; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkPolyData::GetNumberOfCells() +{ + return this->GetNumberOfVerts() + this->GetNumberOfLines() + + this->GetNumberOfPolys() + this->GetNumberOfStrips(); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkPolyData::GetNumberOfVerts() +{ + return (this->Verts ? this->Verts->GetNumberOfCells() : 0); +} + +vtkIdType vtkPolyData::GetNumberOfLines() +{ + return (this->Lines ? this->Lines->GetNumberOfCells() : 0); +} + +vtkIdType vtkPolyData::GetNumberOfPolys() +{ + return (this->Polys ? this->Polys->GetNumberOfCells() : 0); +} + +vtkIdType vtkPolyData::GetNumberOfStrips() +{ + return (this->Strips ? this->Strips->GetNumberOfCells() : 0); +} + + +//---------------------------------------------------------------------------- +void vtkPolyData::DeleteCells() +{ + // if we have Links, we need to delete them (they are no longer valid) + if (this->Links) + { + this->Links->UnRegister( this ); + this->Links = NULL; + } + + if (this->Cells) + { + this->Cells->UnRegister( this ); + this->Cells = NULL; + } +} + +//---------------------------------------------------------------------------- +// Create data structure that allows random access of cells. +void vtkPolyData::BuildCells() +{ + vtkIdType numCells; + vtkCellArray *inVerts=this->GetVerts(); + vtkCellArray *inLines=this->GetLines(); + vtkCellArray *inPolys=this->GetPolys(); + vtkCellArray *inStrips=this->GetStrips(); + vtkIdType npts=0; + vtkIdType *pts=0; + vtkCellTypes *cells; + + vtkDebugMacro (<< "Building PolyData cells."); + + if ( (numCells = this->GetNumberOfCells()) < 1 ) + { + numCells = 1000; //may be allocating empty list to begin with + } + + if (this->Cells) + { + this->DeleteCells(); + } + + this->Cells = cells = vtkCellTypes::New(); + this->Cells->Allocate(numCells,3*numCells); + this->Cells->Register(this); + cells->Delete(); + // + // Traverse various lists to create cell array + // + for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); ) + { + if ( npts > 1 ) + { + cells->InsertNextCell(VTK_POLY_VERTEX, + inVerts->GetTraversalLocation(npts)); + } + else + { + cells->InsertNextCell(VTK_VERTEX,inVerts->GetTraversalLocation(npts)); + } + } + + for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); ) + { + if ( npts > 2 ) + { + cells->InsertNextCell(VTK_POLY_LINE,inLines->GetTraversalLocation(npts)); + } + else + { + cells->InsertNextCell(VTK_LINE,inLines->GetTraversalLocation(npts)); + } + } + + for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + if ( npts == 3 ) + { + cells->InsertNextCell(VTK_TRIANGLE,inPolys->GetTraversalLocation(npts)); + } + else if ( npts == 4 ) + { + cells->InsertNextCell(VTK_QUAD,inPolys->GetTraversalLocation(npts)); + } + else + { + cells->InsertNextCell(VTK_POLYGON,inPolys->GetTraversalLocation(npts)); + } + } + + for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + cells->InsertNextCell(VTK_TRIANGLE_STRIP, + inStrips->GetTraversalLocation(npts)); + } +} + +//---------------------------------------------------------------------------- +void vtkPolyData::DeleteLinks() +{ + if (this->Links) + { + this->Links->UnRegister( this ); + this->Links = NULL; + } +} + +//---------------------------------------------------------------------------- +// Create upward links from points to cells that use each point. Enables +// topologically complex queries. +void vtkPolyData::BuildLinks(int initialSize) +{ + if ( this->Links ) + { + this->DeleteLinks(); + } + + if ( this->Cells == NULL ) + { + this->BuildCells(); + } + + this->Links = vtkCellLinks::New(); + if ( initialSize > 0 ) + { + this->Links->Allocate(initialSize); + } + else + { + this->Links->Allocate(this->GetNumberOfPoints()); + } + this->Links->Register(this); + this->Links->Delete(); + + this->Links->BuildLinks(this); +} + +//---------------------------------------------------------------------------- +// Copy a cells point ids into list provided. (Less efficient.) +void vtkPolyData::GetCellPoints(vtkIdType cellId, vtkIdList *ptIds) +{ + vtkIdType i; + vtkIdType *pts, npts; + + ptIds->Reset(); + if ( this->Cells == NULL ) + { + this->BuildCells(); + } + + this->vtkPolyData::GetCellPoints(cellId, npts, pts); + ptIds->InsertId (npts-1,pts[npts-1]); + for (i=0; iSetId(i,pts[i]); + } +} + +//---------------------------------------------------------------------------- +// Return a pointer to a list of point ids defining cell. (More efficient.) +// Assumes that cells have been built (with BuildCells()). +void vtkPolyData::GetCellPoints(vtkIdType cellId, vtkIdType& npts, + vtkIdType* &pts) +{ + int loc; + unsigned char type; + + type = this->Cells->GetCellType(cellId); + loc = this->Cells->GetCellLocation(cellId); + + switch (type) + { + case VTK_VERTEX: case VTK_POLY_VERTEX: + this->Verts->GetCell(loc,npts,pts); + break; + + case VTK_LINE: case VTK_POLY_LINE: + this->Lines->GetCell(loc,npts,pts); + break; + + case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: + this->Polys->GetCell(loc,npts,pts); + break; + + case VTK_TRIANGLE_STRIP: + this->Strips->GetCell(loc,npts,pts); + break; + + default: + npts = 0; + pts = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkPolyData::GetPointCells(vtkIdType ptId, vtkIdList *cellIds) +{ + vtkIdType *cells; + vtkIdType numCells; + vtkIdType i; + + if ( ! this->Links ) + { + this->BuildLinks(); + } + cellIds->Reset(); + + numCells = this->Links->GetNcells(ptId); + cells = this->Links->GetCells(ptId); + + for (i=0; i < numCells; i++) + { + cellIds->InsertId(i,cells[i]); + } +} + +//---------------------------------------------------------------------------- +// Method allocates initial storage for vertex, line, polygon, and +// triangle strip arrays. Use this method before the method +// PolyData::InsertNextCell(). (Or, provide vertex, line, polygon, and +// triangle strip cell arrays.) +void vtkPolyData::Allocate(vtkIdType numCells, int extSize) +{ + vtkCellArray *cells; + + if (!this->Cells) + { + this->Cells = vtkCellTypes::New(); + this->Cells->Allocate(numCells,3*numCells); + // Consistent Register/UnRegister. (ShallowCopy). + this->Cells->Register(this); + this->Cells->Delete(); + } + + cells = vtkCellArray::New(); + cells->Allocate(numCells,extSize); + this->SetVerts(cells); + cells->Delete(); + + cells = vtkCellArray::New(); + cells->Allocate(numCells,extSize); + this->SetLines(cells); + cells->Delete(); + + cells = vtkCellArray::New(); + cells->Allocate(numCells,extSize); + this->SetPolys(cells); + cells->Delete(); + + cells = vtkCellArray::New(); + cells->Allocate(numCells,extSize); + this->SetStrips(cells); + cells->Delete(); +} + +void vtkPolyData::Allocate(vtkPolyData *inPolyData, vtkIdType numCells, + int extSize) +{ + vtkCellArray *cells; + int numVerts=inPolyData->GetVerts()->GetNumberOfCells(); + int numLines=inPolyData->GetLines()->GetNumberOfCells(); + int numPolys=inPolyData->GetPolys()->GetNumberOfCells(); + int numStrips=inPolyData->GetStrips()->GetNumberOfCells(); + int total=numVerts+numLines+numPolys+numStrips; + + if ( total <= 0 ) + { + return; + } + + if (!this->Cells) + { + this->Cells = vtkCellTypes::New(); + this->Cells->Allocate(numCells,3*numCells); + // Consistent Register/UnRegister. (ShallowCopy). + this->Cells->Register(this); + this->Cells->Delete(); + } + + if ( numVerts > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate((int)((double)numVerts/total*numCells),extSize); + this->SetVerts(cells); + cells->Delete(); + } + if ( numLines > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate((int)((double)numLines/total*numCells),extSize); + this->SetLines(cells); + cells->Delete(); + } + if ( numPolys > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate((int)((double)numPolys/total*numCells),extSize); + this->SetPolys(cells); + cells->Delete(); + } + if ( numStrips > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate((int)((double)numStrips/total*numCells),extSize); + this->SetStrips(cells); + cells->Delete(); + } +} + +//---------------------------------------------------------------------------- +// Insert a cell of type VTK_VERTEX, VTK_POLY_VERTEX, VTK_LINE, VTK_POLY_LINE, +// VTK_TRIANGLE, VTK_QUAD, VTK_POLYGON, or VTK_TRIANGLE_STRIP. Make sure that +// the PolyData::Allocate() function has been called first or that vertex, +// line, polygon, and triangle strip arrays have been supplied. +// Note: will also insert VTK_PIXEL, but converts it to VTK_QUAD. +int vtkPolyData::InsertNextCell(int type, int npts, vtkIdType *pts) +{ + int id; + + if ( !this->Cells ) + { + // if we get to this point, the user has not made any guess at the + // number of cells, so this guess is as good as any + this->Cells = vtkCellTypes::New(); + this->Cells->Allocate(5000,10000); + } + + switch (type) + { + case VTK_VERTEX: case VTK_POLY_VERTEX: + this->Verts->InsertNextCell(npts,pts); + id = this->Cells->InsertNextCell(type, + this->Verts->GetInsertLocation(npts)); + break; + + case VTK_LINE: case VTK_POLY_LINE: + this->Lines->InsertNextCell(npts,pts); + id = this->Cells->InsertNextCell(type, + this->Lines->GetInsertLocation(npts)); + break; + + case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: + this->Polys->InsertNextCell(npts,pts); + id = this->Cells->InsertNextCell(type, + this->Polys->GetInsertLocation(npts)); + break; + + case VTK_PIXEL: //need to rearrange vertices + { + static vtkIdType pixPts[4]; + pixPts[0] = pts[0]; + pixPts[1] = pts[1]; + pixPts[2] = pts[3]; + pixPts[3] = pts[2]; + this->Polys->InsertNextCell(npts,pixPts); + id = this->Cells->InsertNextCell(VTK_QUAD, + this->Polys->GetInsertLocation(npts)); + break; + } + + case VTK_TRIANGLE_STRIP: + this->Strips->InsertNextCell(npts,pts); + id = this->Cells->InsertNextCell(type, + this->Strips->GetInsertLocation(npts)); + break; + + default: + id = -1; + vtkErrorMacro(<<"Bad cell type! Can't insert!"); + } + return id; +} + +//---------------------------------------------------------------------------- +// Insert a cell of type VTK_VERTEX, VTK_POLY_VERTEX, VTK_LINE, VTK_POLY_LINE, +// VTK_TRIANGLE, VTK_QUAD, VTK_POLYGON, or VTK_TRIANGLE_STRIP. Make sure that +// the PolyData::Allocate() function has been called first or that vertex, +// line, polygon, and triangle strip arrays have been supplied. +// Note: will also insert VTK_PIXEL, but converts it to VTK_QUAD. +int vtkPolyData::InsertNextCell(int type, vtkIdList *pts) +{ + int id; + int npts=pts->GetNumberOfIds(); + + if ( !this->Cells ) + { + this->Cells = vtkCellTypes::New(); + this->Cells->Allocate(5000,10000); + } + + switch (type) + { + case VTK_VERTEX: case VTK_POLY_VERTEX: + this->Verts->InsertNextCell(pts); + id = this->Cells->InsertNextCell(type, this->Verts->GetInsertLocation(npts)); + break; + + case VTK_LINE: case VTK_POLY_LINE: + this->Lines->InsertNextCell(pts); + id = this->Cells->InsertNextCell(type, this->Lines->GetInsertLocation(npts)); + break; + + case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: + this->Polys->InsertNextCell(pts); + id = this->Cells->InsertNextCell(type, this->Polys->GetInsertLocation(npts)); + break; + + case VTK_PIXEL: //need to rearrange vertices + { + static vtkIdType pixPts[4]; + pixPts[0] = pts->GetId(0); + pixPts[1] = pts->GetId(1); + pixPts[2] = pts->GetId(3); + pixPts[3] = pts->GetId(2); + this->Polys->InsertNextCell(4,pixPts); + id = this->Cells->InsertNextCell(VTK_QUAD, this->Polys->GetInsertLocation(npts)); + break; + } + + case VTK_TRIANGLE_STRIP: + this->Strips->InsertNextCell(pts); + id = this->Cells->InsertNextCell(type, this->Strips->GetInsertLocation(npts)); + break; + + case VTK_EMPTY_CELL: + id = -1; + // do nothing + break; + + default: + id = -1; + vtkErrorMacro(<<"Bad cell type! Can't insert!"); + } + + return id; +} + +//---------------------------------------------------------------------------- +// Recover extra allocated memory when creating data whose initial size +// is unknown. Examples include using the InsertNextCell() method, or +// when using the CellArray::EstimateSize() method to create vertices, +// lines, polygons, or triangle strips. +void vtkPolyData::Squeeze() +{ + if ( this->Verts != NULL ) + { + this->Verts->Squeeze(); + } + if ( this->Lines != NULL ) + { + this->Lines->Squeeze(); + } + if ( this->Polys != NULL ) + { + this->Polys->Squeeze(); + } + if ( this->Strips != NULL ) + { + this->Strips->Squeeze(); + } + + vtkPointSet::Squeeze(); +} + +//---------------------------------------------------------------------------- +// Begin inserting data all over again. Memory is not freed but otherwise +// objects are returned to their initial state. +void vtkPolyData::Reset() +{ + if ( this->Verts != NULL ) + { + this->Verts->Reset(); + } + if ( this->Lines != NULL ) + { + this->Lines->Reset(); + } + if ( this->Polys != NULL ) + { + this->Polys->Reset(); + } + if ( this->Strips != NULL ) + { + this->Strips->Reset(); + } +} + +//---------------------------------------------------------------------------- +// Reverse the order of point ids defining the cell. +void vtkPolyData::ReverseCell(vtkIdType cellId) +{ + int loc, type; + + if ( this->Cells == NULL ) + { + this->BuildCells(); + } + loc = this->Cells->GetCellLocation(cellId); + type = this->Cells->GetCellType(cellId); + + switch (type) + { + case VTK_VERTEX: case VTK_POLY_VERTEX: + this->Verts->ReverseCell(loc); + break; + + case VTK_LINE: case VTK_POLY_LINE: + this->Lines->ReverseCell(loc); + break; + + case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: + this->Polys->ReverseCell(loc); + break; + + case VTK_TRIANGLE_STRIP: + this->Strips->ReverseCell(loc); + break; + + default: + break; + } +} + +//---------------------------------------------------------------------------- +// Add a point to the cell data structure (after cell pointers have been +// built). This method allocates memory for the links to the cells. (To +// use this method, make sure points are available and BuildLinks() has been invoked.) +int vtkPolyData::InsertNextLinkedPoint(int numLinks) +{ + return this->Links->InsertNextPoint(numLinks); +} + +//---------------------------------------------------------------------------- +// Add a point to the cell data structure (after cell pointers have been +// built). This method adds the point and then allocates memory for the +// links to the cells. (To use this method, make sure points are available +// and BuildLinks() has been invoked.) +int vtkPolyData::InsertNextLinkedPoint(double x[3], int numLinks) +{ + this->Links->InsertNextPoint(numLinks); + return this->Points->InsertNextPoint(x); +} + +//---------------------------------------------------------------------------- +// Add a new cell to the cell data structure (after cell pointers have been +// built). This method adds the cell and then updates the links from the points +// to the cells. (Memory is allocated as necessary.) +int vtkPolyData::InsertNextLinkedCell(int type, int npts, vtkIdType *pts) +{ + int i, id; + + id = this->InsertNextCell(type,npts,pts); + + for (i=0; iLinks->ResizeCellList(pts[i],1); + this->Links->AddCellReference(id,pts[i]); + } + + return id; +} + +//---------------------------------------------------------------------------- +// Remove a reference to a cell in a particular point's link list. You may also +// consider using RemoveCellReference() to remove the references from all the +// cell's points to the cell. This operator does not reallocate memory; use the +// operator ResizeCellList() to do this if necessary. +void vtkPolyData::RemoveReferenceToCell(vtkIdType ptId, vtkIdType cellId) +{ + this->Links->RemoveCellReference(cellId, ptId); +} + +//---------------------------------------------------------------------------- +// Add a reference to a cell in a particular point's link list. (You may also +// consider using AddCellReference() to add the references from all the +// cell's points to the cell.) This operator does not realloc memory; use the +// operator ResizeCellList() to do this if necessary. +void vtkPolyData::AddReferenceToCell(vtkIdType ptId, vtkIdType cellId) +{ + this->Links->AddCellReference(cellId, ptId); +} + +//---------------------------------------------------------------------------- +// Replace the points defining cell "cellId" with a new set of points. This +// operator is (typically) used when links from points to cells have not been +// built (i.e., BuildLinks() has not been executed). Use the operator +// ReplaceLinkedCell() to replace a cell when cell structure has been built. +void vtkPolyData::ReplaceCell(vtkIdType cellId, int npts, vtkIdType *pts) +{ + int loc, type; + + if ( this->Cells == NULL ) + { + this->BuildCells(); + } + loc = this->Cells->GetCellLocation(cellId); + type = this->Cells->GetCellType(cellId); + + switch (type) + { + case VTK_VERTEX: case VTK_POLY_VERTEX: + this->Verts->ReplaceCell(loc,npts,pts); + break; + + case VTK_LINE: case VTK_POLY_LINE: + this->Lines->ReplaceCell(loc,npts,pts); + break; + + case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: + this->Polys->ReplaceCell(loc,npts,pts); + break; + + case VTK_TRIANGLE_STRIP: + this->Strips->ReplaceCell(loc,npts,pts); + break; + + default: + break; + } +} + +//---------------------------------------------------------------------------- +// Replace one cell with another in cell structure. This operator updates the +// connectivity list and the point's link list. It does not delete references +// to the old cell in the point's link list. Use the operator +// RemoveCellReference() to delete all references from points to (old) cell. +// You may also want to consider using the operator ResizeCellList() if the +// link list is changing size. +void vtkPolyData::ReplaceLinkedCell(vtkIdType cellId, int npts, vtkIdType *pts) +{ + int loc = this->Cells->GetCellLocation(cellId); + int type = this->Cells->GetCellType(cellId); + + switch (type) + { + case VTK_VERTEX: case VTK_POLY_VERTEX: + this->Verts->ReplaceCell(loc,npts,pts); + break; + + case VTK_LINE: case VTK_POLY_LINE: + this->Lines->ReplaceCell(loc,npts,pts); + break; + + case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: + this->Polys->ReplaceCell(loc,npts,pts); + break; + + case VTK_TRIANGLE_STRIP: + this->Strips->ReplaceCell(loc,npts,pts); + break; + + default: + npts = 0; + } + + for (int i=0; i < npts; i++) + { + this->Links->InsertNextCellReference(pts[i],cellId); + } +} + +//---------------------------------------------------------------------------- +// Get the neighbors at an edge. More efficient than the general +// GetCellNeighbors(). Assumes links have been built (with BuildLinks()), +// and looks specifically for edge neighbors. +void vtkPolyData::GetCellEdgeNeighbors(vtkIdType cellId, vtkIdType p1, + vtkIdType p2, vtkIdList *cellIds) +{ + vtkIdType *cells; + vtkIdType numCells; + vtkIdType i,j; + vtkIdType *pts, npts; + + cellIds->Reset(); + + numCells = this->Links->GetNcells(p1); + cells = this->Links->GetCells(p1); + + for (i=0; i < numCells; i++) + { + if ( cells[i] != cellId ) + { + this->GetCellPoints(cells[i],npts,pts); + for (j=0; j < npts; j++) + { + if ( pts[j] == p2 ) + { + break; + } + } + if ( j < npts ) + { + cellIds->InsertNextId(cells[i]); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkPolyData::GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds) +{ + vtkIdType i, j, numPts, cellNum; + int allFound, oneFound; + + if ( ! this->Links ) + { + this->BuildLinks(); + } + + cellIds->Reset(); + + // load list with candidate cells, remove current cell + vtkIdType ptId = ptIds->GetId(0); + int numPrime = this->Links->GetNcells(ptId); + vtkIdType *primeCells = this->Links->GetCells(ptId); + numPts = ptIds->GetNumberOfIds(); + + // for each potential cell + for (cellNum = 0; cellNum < numPrime; cellNum++) + { + // ignore the original cell + if (primeCells[cellNum] != cellId) + { + // are all the remaining points in the cell ? + for (allFound=1, i=1; i < numPts && allFound; i++) + { + ptId = ptIds->GetId(i); + int numCurrent = this->Links->GetNcells(ptId); + vtkIdType *currentCells = this->Links->GetCells(ptId); + oneFound = 0; + for (j = 0; j < numCurrent; j++) + { + if (primeCells[cellNum] == currentCells[j]) + { + oneFound = 1; + break; + } + } + if (!oneFound) + { + allFound = 0; + } + } + if (allFound) + { + cellIds->InsertNextId(primeCells[cellNum]); + } + } + } +} + +int vtkPolyData::IsEdge(vtkIdType p1, vtkIdType p2) +{ + unsigned short int ncells; + vtkIdType cellType; + vtkIdType npts; + vtkIdType i, j; + vtkIdType *cells, *pts; + + this->GetPointCells(p1,ncells,cells); + for (i=0; iGetCellType(cells[i]); + switch (cellType) + { + case VTK_EMPTY_CELL: case VTK_VERTEX: case VTK_POLY_VERTEX: case VTK_LINE: case VTK_POLY_LINE: + break; + case VTK_TRIANGLE: + if ( this->IsPointUsedByCell(p2,cells[i]) ) + { + return 1; + } + break; + case VTK_QUAD: + this->GetCellPoints(cells[i],npts,pts); + for (j=0; jGetCellPoints(cells[i],npts,pts); + for (j=0; jGetCellPoints(cells[i],npts,pts); + for (j=0; jGetUpdatePiece(); + numPieces = this->GetUpdateNumberOfPieces(); + ghostLevel = this->GetUpdateGhostLevel(); +} + +//---------------------------------------------------------------------------- +int* vtkPolyData::GetUpdateExtent() +{ + return this->Superclass::GetUpdateExtent(); +} + +//---------------------------------------------------------------------------- +void vtkPolyData::GetUpdateExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1) +{ + this->Superclass::GetUpdateExtent(x0, x1, y0, y1, z0, z1); +} + +//---------------------------------------------------------------------------- +void vtkPolyData::GetUpdateExtent(int extent[6]) +{ + this->Superclass::GetUpdateExtent(extent); +} + +//---------------------------------------------------------------------------- + +unsigned long vtkPolyData::GetActualMemorySize() +{ + unsigned long size=this->vtkPointSet::GetActualMemorySize(); + if ( this->Verts ) + { + size += this->Verts->GetActualMemorySize(); + } + if ( this->Lines ) + { + size += this->Lines->GetActualMemorySize(); + } + if ( this->Polys ) + { + size += this->Polys->GetActualMemorySize(); + } + if ( this->Strips ) + { + size += this->Strips->GetActualMemorySize(); + } + if ( this->Cells ) + { + size += this->Cells->GetActualMemorySize(); + } + if ( this->Links ) + { + size += this->Links->GetActualMemorySize(); + } + return size; +} + +//---------------------------------------------------------------------------- +void vtkPolyData::ShallowCopy(vtkDataObject *dataObject) +{ + vtkPolyData *polyData = vtkPolyData::SafeDownCast(dataObject); + + if ( polyData != NULL ) + { + this->SetVerts(polyData->GetVerts()); + this->SetLines(polyData->GetLines()); + this->SetPolys(polyData->GetPolys()); + this->SetStrips(polyData->GetStrips()); + + // I do not know if this is correct but. + if (this->Cells) + { + this->Cells->UnRegister(this); + } + this->Cells = polyData->Cells; + if (this->Cells) + { + this->Cells->Register(this); + } + + if (this->Links) + { + this->Links->Delete(); + } + this->Links = polyData->Links; + if (this->Links) + { + this->Links->Register(this); + } + } + + // Do superclass + this->vtkPointSet::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkPolyData::DeepCopy(vtkDataObject *dataObject) +{ + // Do superclass + // We have to do this BEFORE we call BuildLinks, else there are no points + // to build the links on (the parent DeepCopy copies the points) + this->vtkPointSet::DeepCopy(dataObject); + + vtkPolyData *polyData = vtkPolyData::SafeDownCast(dataObject); + + if ( polyData != NULL ) + { + vtkCellArray *ca; + ca = vtkCellArray::New(); + ca->DeepCopy(polyData->GetVerts()); + this->SetVerts(ca); + ca->Delete(); + + ca = vtkCellArray::New(); + ca->DeepCopy(polyData->GetLines()); + this->SetLines(ca); + ca->Delete(); + + ca = vtkCellArray::New(); + ca->DeepCopy(polyData->GetPolys()); + this->SetPolys(ca); + ca->Delete(); + + ca = vtkCellArray::New(); + ca->DeepCopy(polyData->GetStrips()); + this->SetStrips(ca); + ca->Delete(); + + if ( this->Cells ) + { + this->Cells->UnRegister(this); + this->Cells = NULL; + } + if (polyData->Cells) + { + this->BuildCells(); + } + + if ( this->Links ) + { + this->Links->UnRegister(this); + this->Links = NULL; + } + if (polyData->Links) + { + this->BuildLinks(); + } + } +} + +void vtkPolyData::Crop() +{ +} + +void vtkPolyData::RemoveGhostCells(int level) +{ + vtkCellData *newCellData; + vtkCellArray *newVerts; + vtkCellArray *newLines; + vtkCellArray *newPolys; + vtkCellArray *newStrips; + vtkIdType inCellId, outCellId; + vtkIdType npts=0; + vtkIdType *pts=0; + + // Get a pointer to the cell ghost level array. + vtkDataArray* temp = this->CellData->GetArray("vtkGhostLevels"); + if (temp == NULL) + { + vtkDebugMacro("Could not find cell ghost level array."); + return; + } + if ( (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1) + || (temp->GetNumberOfTuples() < this->GetNumberOfCells())) + { + vtkErrorMacro("Poorly formed ghost level array."); + return; + } + unsigned char* cellGhostLevels =((vtkUnsignedCharArray*)temp)->GetPointer(0); + + // We may be able to get away wil just creating a CellData object. + newCellData = vtkCellData::New(); + newCellData->CopyAllocate(this->CellData, this->GetNumberOfCells()); + + inCellId = outCellId = 0; + if (this->Verts) + { + newVerts = vtkCellArray::New(); + newVerts->Allocate(this->Verts->GetSize()); + for (this->Verts->InitTraversal(); this->Verts->GetNextCell(npts, pts); ) + { + if (int(cellGhostLevels[inCellId]) < level) + { // Keep the cell. + newVerts->InsertNextCell(npts, pts); + newCellData->CopyData(this->CellData, inCellId, outCellId); + ++outCellId; + } // Keep this cell. + ++inCellId; + } // for all cells + this->SetVerts(newVerts); + newVerts->Delete(); + newVerts = NULL; + } + + if (this->Lines) + { + newLines = vtkCellArray::New(); + newLines->Allocate(this->Lines->GetSize()); + for (this->Lines->InitTraversal(); this->Lines->GetNextCell(npts, pts); ) + { + if (int(cellGhostLevels[inCellId]) < level) + { // Keep the cell. + newLines->InsertNextCell(npts, pts); + newCellData->CopyData(this->CellData, inCellId, outCellId); + ++outCellId; + } // Keep this cell. + ++inCellId; + } // for all cells + this->SetLines(newLines); + newLines->Delete(); + newLines = NULL; + } + + if (this->Polys) + { + newPolys = vtkCellArray::New(); + newPolys->Allocate(this->Polys->GetSize()); + for (this->Polys->InitTraversal(); this->Polys->GetNextCell(npts, pts); ) + { + if (int(cellGhostLevels[inCellId]) < level) + { // Keep the cell. + newPolys->InsertNextCell(npts, pts); + newCellData->CopyData(this->CellData, inCellId, outCellId); + ++outCellId; + } // Keep this cell. + ++inCellId; + } // for all cells + this->SetPolys(newPolys); + newPolys->Delete(); + newPolys = NULL; + } + + if (this->Strips) + { + newStrips = vtkCellArray::New(); + newStrips->Allocate(this->Strips->GetSize()); + for (this->Strips->InitTraversal(); this->Strips->GetNextCell(npts, pts); ) + { + if (int(cellGhostLevels[inCellId]) < level) + { // Keep the cell. + newStrips->InsertNextCell(npts, pts); + newCellData->CopyData(this->CellData, inCellId, outCellId); + ++outCellId; + } // Keep this cell. + ++inCellId; + } // for all cells + this->SetStrips(newStrips); + newStrips->Delete(); + newStrips = NULL; + } + + // Save the results. + this->CellData->ShallowCopy(newCellData); + newCellData->Delete(); + + // If there are no more ghost levels, then remove all arrays. + if (level <= 1) + { + this->CellData->RemoveArray("vtkGhostLevels"); + this->PointData->RemoveArray("vtkGhostLevels"); + } + + this->Squeeze(); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkPolyData::GetData(vtkInformation* info) +{ + return info? vtkPolyData::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkPolyData::GetData(vtkInformationVector* v, int i) +{ + return vtkPolyData::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +void vtkPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Vertices: " << this->GetNumberOfVerts() << "\n"; + os << indent << "Number Of Lines: " << this->GetNumberOfLines() << "\n"; + os << indent << "Number Of Polygons: " << this->GetNumberOfPolys() << "\n"; + os << indent << "Number Of Triangle Strips: " << this->GetNumberOfStrips() << "\n"; + + os << indent << "Number Of Pieces: " << this->GetNumberOfPieces() << endl; + os << indent << "Piece: " << this->GetPiece() << endl; + os << indent << "Ghost Level: " << this->GetGhostLevel() << endl; +} diff --git a/Filtering/vtkPolyData.h b/Filtering/vtkPolyData.h new file mode 100644 index 0000000..d2b0540 --- /dev/null +++ b/Filtering/vtkPolyData.h @@ -0,0 +1,558 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyData - concrete dataset represents vertices, lines, polygons, and triangle strips +// .SECTION Description +// vtkPolyData is a data object that is a concrete implementation of +// vtkDataSet. vtkPolyData represents a geometric structure consisting of +// vertices, lines, polygons, and/or triangle strips. Point and cell +// attribute values (e.g., scalars, vectors, etc.) also are represented. +// +// The actual cell types (vtkCellType.h) supported by vtkPolyData are: +// vtkVertex, vtkPolyVertex, vtkLine, vtkPolyLine, vtkTriangle, vtkQuad, +// vtkPolygon, and vtkTriangleStrip. +// +// One important feature of vtkPolyData objects is that special traversal and +// data manipulation methods are available to process data. These methods are +// generally more efficient than vtkDataSet methods and should be used +// whenever possible. For example, traversing the cells in a dataset we would +// use GetCell(). To traverse cells with vtkPolyData we would retrieve the +// cell array object representing polygons (for example using GetPolys()) and +// then use vtkCellArray's InitTraversal() and GetNextCell() methods. +// +// .SECTION Caveats +// Because vtkPolyData is implemented with four separate instances of +// vtkCellArray to represent 0D vertices, 1D lines, 2D polygons, and 2D +// triangle strips, it is possible to create vtkPolyData instances that +// consist of a mixture of cell types. Because of the design of the class, +// there are certain limitations on how mixed cell types are inserted into +// the vtkPolyData, and in turn the order in which they are processed and +// rendered. To preserve the consistency of cell ids, and to insure that +// cells with cell data are rendered properly, users must insert mixed cells +// in the order of vertices (vtkVertex and vtkPolyVertex), lines (vtkLine and +// vtkPolyLine), polygons (vtkTriangle, vtkQuad, vtkPolygon), and triangle +// strips (vtkTriangleStrip). +// +// Some filters when processing vtkPolyData with mixed cell types may process +// the cells in differing ways. Some will convert one type into another +// (e.g., vtkTriangleStrip into vtkTriangles) or expect a certain type +// (vtkDecimatePro expects triangles or triangle strips; vtkTubeFilter +// expects lines). Read the documentation for each filter carefully to +// understand how each part of vtkPolyData is processed. + +#ifndef __vtkPolyData_h +#define __vtkPolyData_h + +#include "vtkPointSet.h" + +#include "vtkCellTypes.h" // Needed for inline methods +#include "vtkCellLinks.h" // Needed for inline methods + +class vtkVertex; +class vtkPolyVertex; +class vtkLine; +class vtkPolyLine; +class vtkTriangle; +class vtkQuad; +class vtkPolygon; +class vtkTriangleStrip; +class vtkEmptyCell; + +class VTK_FILTERING_EXPORT vtkPolyData : public vtkPointSet +{ +public: + static vtkPolyData *New(); + + vtkTypeRevisionMacro(vtkPolyData,vtkPointSet); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return what type of dataset this is. + int GetDataObjectType() {return VTK_POLY_DATA;} + + // Description: + // Copy the geometric and topological structure of an input poly data object. + void CopyStructure(vtkDataSet *ds); + + // Description: + // Standard vtkDataSet interface. + vtkIdType GetNumberOfCells(); + vtkCell *GetCell(vtkIdType cellId); + void GetCell(vtkIdType cellId, vtkGenericCell *cell); + int GetCellType(vtkIdType cellId); + void GetCellBounds(vtkIdType cellId, double bounds[6]); + void GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds); + + // Description: + // Copy cells listed in idList from pd, including points, point data, + // and cell data. This method assumes that point and cell data have + // been allocated. If you pass in a point locator, then the points + // won't be duplicated in the output. + void CopyCells(vtkPolyData *pd, vtkIdList *idList, + vtkPointLocator *locator = NULL); + + // Description: + // Copy a cells point ids into list provided. (Less efficient.) + void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds); + + // Description: + // Efficient method to obtain cells using a particular point. Make sure that + // routine BuildLinks() has been called. + void GetPointCells(vtkIdType ptId, vtkIdList *cellIds); + + // Description: + // Compute the (X, Y, Z) bounds of the data. + void ComputeBounds(); + + // Description: + // Recover extra allocated memory when creating data whose initial size + // is unknown. Examples include using the InsertNextCell() method, or + // when using the CellArray::EstimateSize() method to create vertices, + // lines, polygons, or triangle strips. + void Squeeze(); + + // Description: + // Return the maximum cell size in this poly data. + int GetMaxCellSize(); + + // Description: + // Set the cell array defining vertices. + void SetVerts (vtkCellArray* v); + + // Description: + // Get the cell array defining vertices. If there are no vertices, an + // empty array will be returned (convenience to simplify traversal). + vtkCellArray *GetVerts(); + + // Description: + // Set the cell array defining lines. + void SetLines (vtkCellArray* l); + + // Description: + // Get the cell array defining lines. If there are no lines, an + // empty array will be returned (convenience to simplify traversal). + vtkCellArray *GetLines(); + + // Description: + // Set the cell array defining polygons. + void SetPolys (vtkCellArray* p); + + // Description: + // Get the cell array defining polygons. If there are no polygons, an + // empty array will be returned (convenience to simplify traversal). + vtkCellArray *GetPolys(); + + // Description: + // Set the cell array defining triangle strips. + void SetStrips (vtkCellArray* s); + + // Description: + // Get the cell array defining triangle strips. If there are no + // triangle strips, an empty array will be returned (convenience to + // simplify traversal). + vtkCellArray *GetStrips(); + + // Description: + // Return the number of primitives of a particular type held.. + vtkIdType GetNumberOfVerts(); + vtkIdType GetNumberOfLines(); + vtkIdType GetNumberOfPolys(); + vtkIdType GetNumberOfStrips(); + + // Description: + // Method allocates initial storage for vertex, line, polygon, and + // triangle strip arrays. Use this method before the method + // PolyData::InsertNextCell(). (Or, provide vertex, line, polygon, and + // triangle strip cell arrays.) + void Allocate(vtkIdType numCells=1000, int extSize=1000); + + // Description: + // Similar to the method above, this method allocates initial storage for + // vertex, line, polygon, and triangle strip arrays. It does this more + // intelligently, examining the supplied inPolyData to determine whether to + // allocate the verts, lines, polys, and strips arrays. (These arrays are + // allocated only if there is data in the corresponding arrays in the + // inPolyData.) Caution: if the inPolyData has no verts, and after + // allocating with this method an PolyData::InsertNextCell() is invoked + // where a vertex is inserted, bad things will happen. + void Allocate(vtkPolyData *inPolyData, vtkIdType numCells=1000, + int extSize=1000); + + // Description: + // Insert a cell of type VTK_VERTEX, VTK_POLY_VERTEX, VTK_LINE, VTK_POLY_LINE, + // VTK_TRIANGLE, VTK_QUAD, VTK_POLYGON, or VTK_TRIANGLE_STRIP. Make sure that + // the PolyData::Allocate() function has been called first or that vertex, + // line, polygon, and triangle strip arrays have been supplied. + // Note: will also insert VTK_PIXEL, but converts it to VTK_QUAD. + int InsertNextCell(int type, int npts, vtkIdType *pts); + + // Description: + // Insert a cell of type VTK_VERTEX, VTK_POLY_VERTEX, VTK_LINE, VTK_POLY_LINE, + // VTK_TRIANGLE, VTK_QUAD, VTK_POLYGON, or VTK_TRIANGLE_STRIP. Make sure that + // the PolyData::Allocate() function has been called first or that vertex, + // line, polygon, and triangle strip arrays have been supplied. + // Note: will also insert VTK_PIXEL, but converts it to VTK_QUAD. + int InsertNextCell(int type, vtkIdList *pts); + + // Description: + // Begin inserting data all over again. Memory is not freed but otherwise + // objects are returned to their initial state. + void Reset(); + + // Description: + // Create data structure that allows random access of cells. + void BuildCells(); + + // Description: + // Create upward links from points to cells that use each point. Enables + // topologically complex queries. Normally the links array is allocated + // based on the number of points in the vtkPolyData. The optional + // initialSize parameter can be used to allocate a larger size initially. + void BuildLinks(int initialSize=0); + + // Description: + // Release data structure that allows random access of the cells. This must + // be done before a 2nd call to BuildLinks(). DeleteCells implicitly deletes + // the links as well since they are no longer valid. + void DeleteCells(); + + // Description: + // Release the upward links from point to cells that use each point. + void DeleteLinks(); + + // Description: + // Special (efficient) operations on poly data. Use carefully. + void GetPointCells(vtkIdType ptId, unsigned short& ncells, + vtkIdType* &cells); + + // Description: + // Get the neighbors at an edge. More efficient than the general + // GetCellNeighbors(). Assumes links have been built (with BuildLinks()), + // and looks specifically for edge neighbors. + void GetCellEdgeNeighbors(vtkIdType cellId, vtkIdType p1, vtkIdType p2, + vtkIdList *cellIds); + + // Description: + // Return a pointer to a list of point ids defining cell. (More efficient.) + // Assumes that cells have been built (with BuildCells()). + void GetCellPoints(vtkIdType cellId, vtkIdType& npts, vtkIdType* &pts); + + // Description: + // Given three vertices, determine whether it's a triangle. Make sure + // BuildLinks() has been called first. + int IsTriangle(int v1, int v2, int v3); + + // Description: + // Determine whether two points form an edge. If they do, return non-zero. + // By definition PolyVertex and PolyLine have no edges since 1-dimensional + // edges are only found on cells 2D and higher. + // Edges are defined as 1-D boundary entities to cells. + // Make sure BuildLinks() has been called first. + int IsEdge(vtkIdType p1, vtkIdType p2); + + // Description: + // Determine whether a point is used by a particular cell. If it is, return + // non-zero. Make sure BuildCells() has been called first. + int IsPointUsedByCell(vtkIdType ptId, vtkIdType cellId); + + // Description: + // Replace the points defining cell "cellId" with a new set of points. This + // operator is (typically) used when links from points to cells have not been + // built (i.e., BuildLinks() has not been executed). Use the operator + // ReplaceLinkedCell() to replace a cell when cell structure has been built. + void ReplaceCell(vtkIdType cellId, int npts, vtkIdType *pts); + + // Description: + // Replace a point in the cell connectivity list with a different point. + void ReplaceCellPoint(vtkIdType cellId, vtkIdType oldPtId, + vtkIdType newPtId); + + // Description: + // Reverse the order of point ids defining the cell. + void ReverseCell(vtkIdType cellId); + + // Description: + // Mark a point/cell as deleted from this vtkPolyData. + void DeletePoint(vtkIdType ptId); + void DeleteCell(vtkIdType cellId); + + // Description: + // Add a point to the cell data structure (after cell pointers have been + // built). This method adds the point and then allocates memory for the + // links to the cells. (To use this method, make sure points are available + // and BuildLinks() has been invoked.) Of the two methods below, one inserts + // a point coordinate and the other just makes room for cell links. + int InsertNextLinkedPoint(int numLinks); + int InsertNextLinkedPoint(double x[3], int numLinks); + + // Description: + // Add a new cell to the cell data structure (after cell pointers have been + // built). This method adds the cell and then updates the links from the + // points to the cells. (Memory is allocated as necessary.) + int InsertNextLinkedCell(int type, int npts, vtkIdType *pts); + + // Description: + // Replace one cell with another in cell structure. This operator updates the + // connectivity list and the point's link list. It does not delete references + // to the old cell in the point's link list. Use the operator + // RemoveCellReference() to delete all references from points to (old) cell. + // You may also want to consider using the operator ResizeCellList() if the + // link list is changing size. + void ReplaceLinkedCell(vtkIdType cellId, int npts, vtkIdType *pts); + + // Description: + // Remove all references to cell in cell structure. This means the links from + // the cell's points to the cell are deleted. Memory is not reclaimed. Use the + // method ResizeCellList() to resize the link list from a point to its using + // cells. (This operator assumes BuildLinks() has been called.) + void RemoveCellReference(vtkIdType cellId); + + // Description: + // Add references to cell in cell structure. This means the links from + // the cell's points to the cell are modified. Memory is not extended. Use the + // method ResizeCellList() to resize the link list from a point to its using + // cells. (This operator assumes BuildLinks() has been called.) + void AddCellReference(vtkIdType cellId); + + // Description: + // Remove a reference to a cell in a particular point's link list. You may + // also consider using RemoveCellReference() to remove the references from + // all the cell's points to the cell. This operator does not reallocate + // memory; use the operator ResizeCellList() to do this if necessary. + void RemoveReferenceToCell(vtkIdType ptId, vtkIdType cellId); + + // Description: + // Add a reference to a cell in a particular point's link list. (You may also + // consider using AddCellReference() to add the references from all the + // cell's points to the cell.) This operator does not realloc memory; use the + // operator ResizeCellList() to do this if necessary. + void AddReferenceToCell(vtkIdType ptId, vtkIdType cellId); + + // Description: + // Resize the list of cells using a particular point. (This operator assumes + // that BuildLinks() has been called.) + void ResizeCellList(vtkIdType ptId, int size); + + // Description: + // Restore object to initial state. Release memory back to system. + virtual void Initialize(); + + // Description: + // For streaming. User/next filter specifies which piece they want updated. + // The source of this poly data has to return exactly this piece. + void GetUpdateExtent(int &piece, int &numPieces, int &ghostLevel); + + // Description: + // We need this here to avoid hiding superclass method + virtual int* GetUpdateExtent(); + virtual void GetUpdateExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1); + virtual void GetUpdateExtent(int extent[6]); + + // Description: + // Get the piece and the number of pieces. Similar to extent in 3D. + virtual int GetPiece(); + virtual int GetNumberOfPieces(); + + // Description: + // Get the ghost level. + virtual int GetGhostLevel(); + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). THIS METHOD + // IS THREAD SAFE. + unsigned long GetActualMemorySize(); + + // Description: + // Shallow and Deep copy. + void ShallowCopy(vtkDataObject *src); + void DeepCopy(vtkDataObject *src); + + // Description: + // This method will remove any cell that has a ghost level array value + // greater or equal to level. It does not remove unused points (yet). + void RemoveGhostCells(int level); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkPolyData* GetData(vtkInformation* info); + static vtkPolyData* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkPolyData(); + ~vtkPolyData(); + + // constant cell objects returned by GetCell called. + vtkVertex *Vertex; + vtkPolyVertex *PolyVertex; + vtkLine *Line; + vtkPolyLine *PolyLine; + vtkTriangle *Triangle; + vtkQuad *Quad; + vtkPolygon *Polygon; + vtkTriangleStrip *TriangleStrip; + vtkEmptyCell *EmptyCell; + + // points inherited + // point data (i.e., scalars, vectors, normals, tcoords) inherited + vtkCellArray *Verts; + vtkCellArray *Lines; + vtkCellArray *Polys; + vtkCellArray *Strips; + + // dummy static member below used as a trick to simplify traversal + static vtkCellArray *Dummy; + + // supporting structures for more complex topological operations + // built only when necessary + vtkCellTypes *Cells; + vtkCellLinks *Links; + + // This method is called during an update. + // If the CropFilter is set, the user reqquested a piece which the + // source cannot generate, then it will break up the + // data set in order to satisfy the request. + virtual void Crop(); + + +private: + // Hide these from the user and the compiler. + + // Description: + // For legacy compatibility. Do not use. + void GetCellNeighbors(vtkIdType cellId, vtkIdList& ptIds, vtkIdList& cellIds) + {this->GetCellNeighbors(cellId, &ptIds, &cellIds);} + +private: + vtkPolyData(const vtkPolyData&); // Not implemented. + void operator=(const vtkPolyData&); // Not implemented. +}; + +inline void vtkPolyData::GetPointCells(vtkIdType ptId, unsigned short& ncells, + vtkIdType* &cells) +{ + ncells = this->Links->GetNcells(ptId); + cells = this->Links->GetCells(ptId); +} + +inline int vtkPolyData::IsTriangle(int v1, int v2, int v3) +{ + unsigned short int n1; + int i, j, tVerts[3]; + vtkIdType *cells, *tVerts2, n2; + + tVerts[0] = v1; + tVerts[1] = v2; + tVerts[2] = v3; + + for (i=0; i<3; i++) + { + this->GetPointCells(tVerts[i], n1, cells); + for (j=0; jGetCellPoints(cells[j], n2, tVerts2); + if ( (tVerts[0] == tVerts2[0] || tVerts[0] == tVerts2[1] || + tVerts[0] == tVerts2[2]) && + (tVerts[1] == tVerts2[0] || tVerts[1] == tVerts2[1] || + tVerts[1] == tVerts2[2]) && + (tVerts[2] == tVerts2[0] || tVerts[2] == tVerts2[1] || + tVerts[2] == tVerts2[2]) ) + { + return 1; + } + } + } + return 0; +} + +inline int vtkPolyData::IsPointUsedByCell(vtkIdType ptId, vtkIdType cellId) +{ + vtkIdType *pts, npts; + + this->GetCellPoints(cellId, npts, pts); + for (vtkIdType i=0; i < npts; i++) + { + if ( pts[i] == ptId ) + { + return 1; + } + } + + return 0; +} + +inline void vtkPolyData::DeletePoint(vtkIdType ptId) +{ + this->Links->DeletePoint(ptId); +} + +inline void vtkPolyData::DeleteCell(vtkIdType cellId) +{ + this->Cells->DeleteCell(cellId); +} + +inline void vtkPolyData::RemoveCellReference(vtkIdType cellId) +{ + vtkIdType *pts, npts; + + this->GetCellPoints(cellId, npts, pts); + for (vtkIdType i=0; iLinks->RemoveCellReference(cellId, pts[i]); + } +} + +inline void vtkPolyData::AddCellReference(vtkIdType cellId) +{ + vtkIdType *pts, npts; + + this->GetCellPoints(cellId, npts, pts); + for (vtkIdType i=0; iLinks->AddCellReference(cellId, pts[i]); + } +} + +inline void vtkPolyData::ResizeCellList(vtkIdType ptId, int size) +{ + this->Links->ResizeCellList(ptId,size); +} + +inline void vtkPolyData::ReplaceCellPoint(vtkIdType cellId, vtkIdType oldPtId, + vtkIdType newPtId) +{ + int i; + vtkIdType *verts, nverts; + + this->GetCellPoints(cellId,nverts,verts); + for ( i=0; i < nverts; i++ ) + { + if ( verts[i] == oldPtId ) + { + verts[i] = newPtId; // this is very nasty! direct write! + return; + } + } +} + +#endif + + diff --git a/Filtering/vtkPolyDataAlgorithm.cxx b/Filtering/vtkPolyDataAlgorithm.cxx new file mode 100644 index 0000000..5ae1b02 --- /dev/null +++ b/Filtering/vtkPolyDataAlgorithm.cxx @@ -0,0 +1,242 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkPolyDataAlgorithm, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkPolyDataAlgorithm); + +//---------------------------------------------------------------------------- +vtkPolyDataAlgorithm::vtkPolyDataAlgorithm() +{ + // by default assume filters have one input and one output + // subclasses that deviate should modify this setting + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkPolyDataAlgorithm::~vtkPolyDataAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkPolyDataAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkPolyDataAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkPolyDataAlgorithm::GetOutput(int port) +{ + return vtkPolyData::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +void vtkPolyDataAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkPolyDataAlgorithm::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkPolyDataAlgorithm::GetInput(int port) +{ + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkPolyDataAlgorithm::GetPolyDataInput(int port) +{ + return vtkPolyData::SafeDownCast(this->GetInput(port)); +} + +//---------------------------------------------------------------------------- +int vtkPolyDataAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkPolyDataAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataAlgorithm::RequestInformation( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* vtkNotUsed(outputVector)) +{ + // do nothing let subclasses handle it + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataAlgorithm::RequestUpdateExtent( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed(outputVector)) +{ + int numInputPorts = this->GetNumberOfInputPorts(); + for (int i=0; iGetNumberOfInputConnections(i); + for (int j=0; jGetInformationObject(j); + inputInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + } + } + return 1; +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkPolyDataAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + return 1; +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkPolyDataAlgorithm::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (output && this->UpdateExtentIsEmpty(output)) + { + output->Initialize(); + return; + } + + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkPolyDataAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + + +//---------------------------------------------------------------------------- +void vtkPolyDataAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkPolyDataAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkPolyDataAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkPolyDataAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} + diff --git a/Filtering/vtkPolyDataAlgorithm.h b/Filtering/vtkPolyDataAlgorithm.h new file mode 100644 index 0000000..95865d5 --- /dev/null +++ b/Filtering/vtkPolyDataAlgorithm.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataAlgorithm - Superclass for algorithms that produce only polydata as output +// .SECTION Description + +// vtkPolyDataAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// constructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be PolyData. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// ExecuteData and ExecuteInformation. For new algorithms you should +// implement RequestData( request, inputVec, outputVec) but for older filters +// there is a default implementation that calls the old ExecuteData(output) +// signature, for even older filters that don;t implement ExecuteData the +// default implementation calls the even older Execute() signature. + +#ifndef __vtkPolyDataAlgorithm_h +#define __vtkPolyDataAlgorithm_h + +#include "vtkAlgorithm.h" +#include "vtkPolyData.h" // makes things a bit easier + +class vtkDataSet; +class vtkPolyData; + +class VTK_FILTERING_EXPORT vtkPolyDataAlgorithm : public vtkAlgorithm +{ +public: + static vtkPolyDataAlgorithm *New(); + vtkTypeRevisionMacro(vtkPolyDataAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkPolyData* GetOutput(); + vtkPolyData* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject* GetInput(); + vtkDataObject *GetInput(int port); + vtkPolyData *GetPolyDataInput(int port); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(int, vtkDataObject*); + +protected: + vtkPolyDataAlgorithm(); + ~vtkPolyDataAlgorithm(); + + // convenience method + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkPolyDataAlgorithm(const vtkPolyDataAlgorithm&); // Not implemented. + void operator=(const vtkPolyDataAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkPolyDataCollection.cxx b/Filtering/vtkPolyDataCollection.cxx new file mode 100644 index 0000000..9aa1e4c --- /dev/null +++ b/Filtering/vtkPolyDataCollection.cxx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPolyDataCollection, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkPolyDataCollection); + +//---------------------------------------------------------------------------- +void vtkPolyDataCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkPolyDataCollection.h b/Filtering/vtkPolyDataCollection.h new file mode 100644 index 0000000..c6b3acd --- /dev/null +++ b/Filtering/vtkPolyDataCollection.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataCollection - maintain a list of polygonal data objects +// .SECTION Description +// vtkPolyDataCollection is an object that creates and manipulates lists of +// datasets of type vtkPolyData. + +// .SECTION See Also +// vtkDataSetCollection vtkCollection + +#ifndef __vtkPolyDataCollection_h +#define __vtkPolyDataCollection_h + +#include "vtkCollection.h" + +#include "vtkPolyData.h" // Needed for static cast + +class VTK_FILTERING_EXPORT vtkPolyDataCollection : public vtkCollection +{ +public: + static vtkPolyDataCollection *New(); + vtkTypeRevisionMacro(vtkPolyDataCollection,vtkCollection); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a poly data to the list. + void AddItem(vtkPolyData *pd) { + this->vtkCollection::AddItem((vtkObject *)pd);}; + + // Description: + // Get the next poly data in the list. + vtkPolyData *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkPolyData *GetNextPolyData(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkPolyDataCollection() {}; + ~vtkPolyDataCollection() {}; + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkPolyDataCollection(const vtkPolyDataCollection&); // Not implemented. + void operator=(const vtkPolyDataCollection&); // Not implemented. +}; + + +#endif diff --git a/Filtering/vtkPolyDataSource.cxx b/Filtering/vtkPolyDataSource.cxx new file mode 100644 index 0000000..741f1a9 --- /dev/null +++ b/Filtering/vtkPolyDataSource.cxx @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataSource.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkPolyDataSource, "$Revision: 1.11 $"); + +//---------------------------------------------------------------------------- +vtkPolyDataSource::vtkPolyDataSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + this->vtkSource::SetNthOutput(0, vtkPolyData::New()); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); + this->ExecutePiece = this->ExecuteNumberOfPieces = 0; + this->ExecuteGhostLevel = 0; +} + +//---------------------------------------------------------------------------- +vtkPolyData *vtkPolyDataSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkPolyData *)(this->Outputs[0]); +} + +//---------------------------------------------------------------------------- +vtkPolyData *vtkPolyDataSource::GetOutput(int idx) +{ + return (vtkPolyData *) this->vtkSource::GetOutput(idx); +} + +//---------------------------------------------------------------------------- +void vtkPolyDataSource::SetOutput(vtkPolyData *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + + +//---------------------------------------------------------------------------- +void vtkPolyDataSource::ComputeInputUpdateExtents(vtkDataObject *data) +{ + int piece, numPieces, ghostLevel; + vtkPolyData *output = (vtkPolyData *)data; + int idx; + + output->GetUpdateExtent(piece, numPieces, ghostLevel); + + // make sure piece is valid + if (piece < 0 || piece >= numPieces) + { + return; + } + + if (ghostLevel < 0) + { + return; + } + + // just copy the Update extent as default behavior. + for (idx = 0; idx < this->NumberOfInputs; ++idx) + { + if (this->Inputs[idx]) + { + this->Inputs[idx]->SetUpdateExtent(piece, numPieces, ghostLevel); + } + } + + // Save the piece so execute can use this information. + this->ExecutePiece = piece; + this->ExecuteNumberOfPieces = numPieces; + + this->ExecuteGhostLevel = ghostLevel; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataSource::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPolyDataSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkPolyDataSource.h b/Filtering/vtkPolyDataSource.h new file mode 100644 index 0000000..b3e8c15 --- /dev/null +++ b/Filtering/vtkPolyDataSource.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataSource - abstract class whose subclasses generate polygonal data +// .SECTION Description +// vtkPolyDataSource is an abstract class whose subclasses generate polygonal +// data. + +// .SECTION See Also +// vtkPolyDataReader vtkAxes vtkBYUReader vtkConeSource vtkCubeSource +// vtkCursor3D vtkCyberReader vtkCylinderSource vtkDiskSource vtkLineSource +// vtkMCubesReader vtkOutlineSource vtkPlaneSource vtkPointSource vtkSTLReader +// vtkSphereSource vtkTextSource vtkUGFacetReader vtkVectorText + +#ifndef __vtkPolyDataSource_h +#define __vtkPolyDataSource_h + +#include "vtkSource.h" + +class vtkPolyData; + +class VTK_FILTERING_EXPORT vtkPolyDataSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkPolyDataSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this source. + vtkPolyData *GetOutput(); + vtkPolyData *GetOutput(int idx); + void SetOutput(vtkPolyData *output); + +protected: + vtkPolyDataSource(); + ~vtkPolyDataSource() {}; + + // Update extent of PolyData is specified in pieces. + // Since all DataObjects should be able to set UpdateExent as pieces, + // just copy output->UpdateExtent all Inputs. + void ComputeInputUpdateExtents(vtkDataObject *output); + + // Used by streaming: The extent of the output being processed + // by the execute method. Set in the ComputeInputUpdateExtents method. + int ExecutePiece; + int ExecuteNumberOfPieces; + + int ExecuteGhostLevel; + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkPolyDataSource(const vtkPolyDataSource&); // Not implemented. + void operator=(const vtkPolyDataSource&); // Not implemented. +}; + +#endif + + + + + diff --git a/Filtering/vtkPolyDataToPolyDataFilter.cxx b/Filtering/vtkPolyDataToPolyDataFilter.cxx new file mode 100644 index 0000000..b6b0935 --- /dev/null +++ b/Filtering/vtkPolyDataToPolyDataFilter.cxx @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataToPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataToPolyDataFilter.h" + +#include "vtkInformation.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkPolyDataToPolyDataFilter, "$Revision: 1.19 $"); + +//---------------------------------------------------------------------------- +vtkPolyDataToPolyDataFilter::vtkPolyDataToPolyDataFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkPolyDataToPolyDataFilter::SetInput(vtkPolyData *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkPolyData *vtkPolyDataToPolyDataFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkPolyData *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +int vtkPolyDataToPolyDataFilter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + //info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); HACK + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPolyDataToPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkPolyDataToPolyDataFilter.h b/Filtering/vtkPolyDataToPolyDataFilter.h new file mode 100644 index 0000000..7a7fcd9 --- /dev/null +++ b/Filtering/vtkPolyDataToPolyDataFilter.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataToPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataToPolyDataFilter - abstract filter class +// .SECTION Description +// vtkPolyDataToPolyDataFilter is an abstract filter class whose subclasses +// take as input polygonal data and generate polygonal data on output. + +// .SECTION See Also +// vtkCleanPolyData vtkDecimate vtkFeatureEdges +// vtkMaskPolyData vtkPolyDataNormals vtkSmoothPolyDataFilter vtkStripper +// vtkTransformPolyDataFilter vtkTriangleFilter vtkTubeFilter +// vtkLinearExtrusionFilter vtkRibbonFilter vtkRotationalExtrusionFilter +// vtkShrinkPolyData + +#ifndef __vtkPolyDataToPolyDataFilter_h +#define __vtkPolyDataToPolyDataFilter_h + +#include "vtkPolyDataSource.h" + +class vtkPolyData; + +class VTK_FILTERING_EXPORT vtkPolyDataToPolyDataFilter : public vtkPolyDataSource +{ +public: + vtkTypeRevisionMacro(vtkPolyDataToPolyDataFilter,vtkPolyDataSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkPolyData *input); + vtkPolyData *GetInput(); + +protected: + vtkPolyDataToPolyDataFilter(); + ~vtkPolyDataToPolyDataFilter() {}; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkPolyDataToPolyDataFilter(const vtkPolyDataToPolyDataFilter&); // Not implemented. + void operator=(const vtkPolyDataToPolyDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkPolyLine.cxx b/Filtering/vtkPolyLine.cxx new file mode 100644 index 0000000..8bf423c --- /dev/null +++ b/Filtering/vtkPolyLine.cxx @@ -0,0 +1,497 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyLine.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyLine.h" + +#include "vtkMath.h" +#include "vtkCellArray.h" +#include "vtkObjectFactory.h" +#include "vtkDoubleArray.h" +#include "vtkLine.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkPolyLine, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPolyLine); + +//---------------------------------------------------------------------------- +vtkPolyLine::vtkPolyLine() +{ + this->Line = vtkLine::New(); +} + +//---------------------------------------------------------------------------- +vtkPolyLine::~vtkPolyLine() +{ + this->Line->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkPolyLine::GenerateSlidingNormals(vtkPoints *pts, vtkCellArray *lines, + vtkDataArray *normals) +{ + return this->GenerateSlidingNormals(pts, lines, normals, 0); +} + +//---------------------------------------------------------------------------- +// Given points and lines, compute normals to lines. These are not true +// normals, they are "orientation" normals used by classes like vtkTubeFilter +// that control the rotation around the line. The normals try to stay pointing +// in the same direction as much as possible (i.e., minimal rotation). +int vtkPolyLine::GenerateSlidingNormals(vtkPoints *pts, vtkCellArray *lines, + vtkDataArray *normals, + double* firstNormal) +{ + vtkIdType npts=0; + vtkIdType *linePts=0; + double sPrev[3], sNext[3], q[3], w[3], normal[3], theta; + double p[3], pNext[3]; + double c[3], f1, f2; + int i, j, largeRotation; + + // Loop over all lines + // + for (lines->InitTraversal(); lines->GetNextCell(npts,linePts); ) + { + // Determine initial starting normal + // + if ( npts <= 0 ) + { + continue; + } + + else if ( npts == 1 ) //return arbitrary + { + normal[0] = normal[1] = 0.0; + normal[2] = 1.0; + normals->InsertTuple(linePts[0],normal); + } + + else //more than one point + { + // Compute first normal. All "new" normals try to point in the same + // direction. + // + for (j=0; jGetPoint(linePts[0],p); + pts->GetPoint(linePts[1],pNext); + + for (i=0; i<3; i++) + { + sPrev[i] = pNext[i] - p[i]; + sNext[i] = sPrev[i]; + } + + if ( vtkMath::Normalize(sNext) == 0.0 ) + { + vtkErrorMacro( + <<"Coincident points in polyline...can't compute normals"); + return 0; + } + + if (!firstNormal) + { + // the following logic will produce a normal orthogonal + // to the first line segment. If we have three points + // we use special logic to select a normal orthogonal + // to the first two line segments + int foundNormal=0; + if (npts > 2) + { + int ipt; + + // Look at the line segments (0,1), (ipt-1, ipt) + // until a pair which meets the following criteria + // is found: ||(0,1)x(ipt-1,ipt)|| > 1.0E-3. + // This is used to eliminate nearly parallel cases. + for(ipt=2; ipt < npts; ipt++) + { + double ftmp[3], ftmp2[3]; + + pts->GetPoint(linePts[ipt-1],ftmp); + pts->GetPoint(linePts[ipt] ,ftmp2); + + for (i=0; i<3; i++) + { + ftmp[i] = ftmp2[i] - ftmp[i]; + } + + if ( vtkMath::Normalize(ftmp) == 0.0 ) + { + continue; + } + + // now the starting normal should simply be the cross product + // in the following if statement we check for the case where + // the two segments are parallel + vtkMath::Cross(sNext,ftmp,normal); + if ( vtkMath::Norm(normal) > 1.0E-3 ) + { + foundNormal = 1; + break; + } + } + } + + if ((npts <= 2)|| !foundNormal) + { + for (i=0; i<3; i++) + { + // a little trick to find othogonal normal + if ( sNext[i] != 0.0 ) + { + normal[(i+2)%3] = 0.0; + normal[(i+1)%3] = 1.0; + normal[i] = -sNext[(i+1)%3]/sNext[i]; + break; + } + } + } + } + else + { + memcpy(normal, firstNormal, 3*sizeof(double)); + } + vtkMath::Normalize(normal); + normals->InsertTuple(linePts[0],normal); + } + + else if ( j == (npts-1) ) //last point; just insert previous + { + normals->InsertTuple(linePts[j],normal); + } + + else //inbetween points + { + // Generate normals for new point by projecting previous normal + for (i=0; i<3; i++) + { + p[i] = pNext[i]; + } + pts->GetPoint(linePts[j+1],pNext); + + for (i=0; i<3; i++) + { + sPrev[i] = sNext[i]; + sNext[i] = pNext[i] - p[i]; + } + + if ( vtkMath::Normalize(sNext) == 0.0 ) + { + vtkErrorMacro(<<"Coincident points in polyline...can't compute normals"); + return 0; + } + + //compute rotation vector + vtkMath::Cross(sPrev,normal,w); + if ( vtkMath::Normalize(w) == 0.0 ) + { + vtkErrorMacro(<<"normal and sPrev coincident"); + return 0; + } + + //see whether we rotate greater than 90 degrees. + if ( vtkMath::Dot(sPrev,sNext) < 0.0 ) + { + largeRotation = 1; + } + else + { + largeRotation = 0; + } + + //compute rotation of line segment + vtkMath::Cross (sNext, sPrev, q); + if ( (theta=asin((double)vtkMath::Normalize(q))) == 0.0 ) + { //no rotation, use previous normal + normals->InsertTuple(linePts[j],normal); + continue; + } + if ( largeRotation ) + { + if ( theta > 0.0 ) + { + theta = vtkMath::Pi() - theta; + } + else + { + theta = -vtkMath::Pi() - theta; + } + } + + // new method + for (i=0; i<3; i++) + { + c[i] = sNext[i] + sPrev[i]; + } + vtkMath::Normalize(c); + f1 = vtkMath::Dot(q,normal); + f2 = 1.0 - f1*f1; + if (f2 > 0.0) + { + f2 = sqrt(1.0 - f1*f1); + } + else + { + f2 = 0.0; + } + vtkMath::Cross(c,q,w); + vtkMath::Cross(sPrev,q,c); + if (vtkMath::Dot(normal,c)*vtkMath::Dot(w,c) < 0) + { + f2 = -1.0*f2; + } + for (i=0; i<3; i++) + { + normal[i] = f1*q[i] + f2*w[i]; + } + + normals->InsertTuple(linePts[j],normal); + }//for this point + }//else + }//else if + }//for this line + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPolyLine::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& minDist2, double *weights) +{ + double closest[3]; + double pc[3], dist2; + int ignoreId, i, return_status, status; + double lineWeights[2]; + + pcoords[1] = pcoords[2] = 0.0; + + return_status = 0; + weights[0] = 0.0; + for (minDist2=VTK_DOUBLE_MAX,i=0; iPoints->GetNumberOfPoints()-1; i++) + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(i)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(i+1)); + status = this->Line->EvaluatePosition(x,closest,ignoreId,pc, + dist2,lineWeights); + if ( status != -1 && dist2 < minDist2 ) + { + return_status = status; + if (closestPoint) + { + closestPoint[0] = closest[0]; + closestPoint[1] = closest[1]; + closestPoint[2] = closest[2]; + } + minDist2 = dist2; + subId = i; + pcoords[0] = pc[0]; + weights[i] = lineWeights[0]; + weights[i+1] = lineWeights[1]; + } + else + { + weights[i+1] = 0.0; + } + } + + return return_status; +} + +//---------------------------------------------------------------------------- +void vtkPolyLine::EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights) +{ + int i; + double a1[3]; + double a2[3]; + this->Points->GetPoint(subId, a1); + this->Points->GetPoint(subId+1, a2); + + for (i=0; i<3; i++) + { + x[i] = a1[i] + pcoords[0]*(a2[i] - a1[i]); + } + + weights[0] = 1.0 - pcoords[0]; + weights[1] = pcoords[0]; +} + +//---------------------------------------------------------------------------- +int vtkPolyLine::CellBoundary(int subId, double pcoords[3], vtkIdList *pts) +{ + pts->SetNumberOfIds(1); + + if ( pcoords[0] >= 0.5 ) + { + pts->SetId(0,this->PointIds->GetId(subId+1)); + if ( pcoords[0] > 1.0 ) + { + return 0; + } + else + { + return 1; + } + } + else + { + pts->SetId(0,this->PointIds->GetId(subId)); + if ( pcoords[0] < 0.0 ) + { + return 0; + } + else + { + return 1; + } + } +} + +//---------------------------------------------------------------------------- +void vtkPolyLine::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + int i, numLines=this->Points->GetNumberOfPoints() - 1; + vtkDataArray *lineScalars=cellScalars->NewInstance(); + lineScalars->SetNumberOfComponents(cellScalars->GetNumberOfComponents()); + lineScalars->SetNumberOfTuples(2); + + for ( i=0; i < numLines; i++) + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(i)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(i+1)); + + if ( outPd ) + { + this->Line->PointIds->SetId(0,this->PointIds->GetId(i)); + this->Line->PointIds->SetId(1,this->PointIds->GetId(i+1)); + } + + lineScalars->SetTuple(0,cellScalars->GetTuple(i)); + lineScalars->SetTuple(1,cellScalars->GetTuple(i+1)); + + this->Line->Contour(value, lineScalars, locator, verts, + lines, polys, inPd, outPd, inCd, cellId, outCd); + } + lineScalars->Delete(); +} + +//---------------------------------------------------------------------------- +// Intersect with sub-lines +// +int vtkPolyLine::IntersectWithLine(double p1[3], double p2[3],double tol,double& t, + double x[3], double pcoords[3], int& subId) +{ + int subTest, numLines=this->Points->GetNumberOfPoints() - 1; + + for (subId=0; subId < numLines; subId++) + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(subId)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(subId+1)); + + if ( this->Line->IntersectWithLine(p1, p2, tol, t, x, pcoords, subTest) ) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkPolyLine::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + int numLines=this->Points->GetNumberOfPoints() - 1; + pts->Reset(); + ptIds->Reset(); + + for (int subId=0; subId < numLines; subId++) + { + pts->InsertNextPoint(this->Points->GetPoint(subId)); + ptIds->InsertNextId(this->PointIds->GetId(subId)); + + pts->InsertNextPoint(this->Points->GetPoint(subId+1)); + ptIds->InsertNextId(this->PointIds->GetId(subId+1)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPolyLine::Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs) +{ + this->Line->PointIds->SetNumberOfIds(2); + + this->Line->Points->SetPoint(0,this->Points->GetPoint(subId)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(subId+1)); + + this->Line->Derivatives(0, pcoords, values+dim*subId, dim, derivs); +} + +//---------------------------------------------------------------------------- +void vtkPolyLine::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *lines, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut) +{ + int i, numLines=this->Points->GetNumberOfPoints() - 1; + vtkDoubleArray *lineScalars=vtkDoubleArray::New(); + lineScalars->SetNumberOfTuples(2); + + for ( i=0; i < numLines; i++) + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(i)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(i+1)); + + this->Line->PointIds->SetId(0,this->PointIds->GetId(i)); + this->Line->PointIds->SetId(1,this->PointIds->GetId(i+1)); + + lineScalars->SetComponent(0,0,cellScalars->GetComponent(i,0)); + lineScalars->SetComponent(1,0,cellScalars->GetComponent(i+1,0)); + + this->Line->Clip(value, lineScalars, locator, lines, inPd, outPd, + inCd, cellId, outCd, insideOut); + } + + lineScalars->Delete(); +} + +//---------------------------------------------------------------------------- +// Return the center of the point cloud in parametric coordinates. +int vtkPolyLine::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = 0.5; pcoords[1] = pcoords[2] = 0.0; + return ((this->Points->GetNumberOfPoints() - 1) / 2); +} + +//---------------------------------------------------------------------------- +void vtkPolyLine::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); +} + diff --git a/Filtering/vtkPolyLine.h b/Filtering/vtkPolyLine.h new file mode 100644 index 0000000..b5ff83f --- /dev/null +++ b/Filtering/vtkPolyLine.h @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyLine.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyLine - cell represents a set of 1D lines +// .SECTION Description +// vtkPolyLine is a concrete implementation of vtkCell to represent a set +// of 1D lines. + +#ifndef __vtkPolyLine_h +#define __vtkPolyLine_h + +#include "vtkCell.h" + +//#include "vtkPoints.h" +//#include "vtkCellArray.h" +//#include "vtkLine.h" +class vtkPoints; +class vtkCellArray; +class vtkLine; +class vtkDataArray; +class vtkPointLocator; +class vtkCellData; + +class VTK_FILTERING_EXPORT vtkPolyLine : public vtkCell +{ +public: + static vtkPolyLine *New(); + vtkTypeRevisionMacro(vtkPolyLine,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Given points and lines, compute normals to lines. These are not true + // normals, they are "orientation" normals used by classes like vtkTubeFilter + // that control the rotation around the line. The normals try to stay pointing + // in the same direction as much as possible (i.e., minimal rotation). + int GenerateSlidingNormals(vtkPoints *, vtkCellArray *, vtkDataArray *); + int GenerateSlidingNormals(vtkPoints *, vtkCellArray *, vtkDataArray *, + double* firstNormal); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_POLY_LINE;}; + int GetCellDimension() {return 1;}; + int GetNumberOfEdges() {return 0;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int vtkNotUsed(edgeId)) {return 0;}; + vtkCell *GetFace(int vtkNotUsed(faceId)) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *lines, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + int IsPrimaryCell() {return 0;} + + // Description: + // Return the center of the point cloud in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + +protected: + vtkPolyLine(); + ~vtkPolyLine(); + + vtkLine *Line; + +private: + vtkPolyLine(const vtkPolyLine&); // Not implemented. + void operator=(const vtkPolyLine&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkPolyVertex.cxx b/Filtering/vtkPolyVertex.cxx new file mode 100644 index 0000000..a404ed0 --- /dev/null +++ b/Filtering/vtkPolyVertex.cxx @@ -0,0 +1,241 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyVertex.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyVertex.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" +#include "vtkVertex.h" + +vtkCxxRevisionMacro(vtkPolyVertex, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPolyVertex); + +//---------------------------------------------------------------------------- +vtkPolyVertex::vtkPolyVertex() +{ + this->Vertex = vtkVertex::New(); +} + +//---------------------------------------------------------------------------- +vtkPolyVertex::~vtkPolyVertex() +{ + this->Vertex->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkPolyVertex::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& minDist2, double *weights) +{ + int numPts=this->Points->GetNumberOfPoints(); + double X[3]; + double dist2; + int i; + + for (minDist2=VTK_DOUBLE_MAX, i=0; iPoints->GetPoint(i, X); + dist2 = vtkMath::Distance2BetweenPoints(X,x); + if (dist2 < minDist2) + { + if (closestPoint) + { + closestPoint[0] = X[0]; closestPoint[1] = X[1]; closestPoint[2] = X[2]; + } + minDist2 = dist2; + subId = i; + } + } + + for (i=0; iPoints->GetPoint(subId, x); + + for (i=0; iGetNumberOfPoints(); i++) + { + weights[i] = 0.0; + } + weights[subId] = 1.0; +} + +//---------------------------------------------------------------------------- +int vtkPolyVertex::CellBoundary(int subId, double pcoords[3], vtkIdList *pts) +{ + pts->SetNumberOfIds(1); + pts->SetId(0,this->PointIds->GetId(subId)); + + if ( pcoords[0] != 0.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +void vtkPolyVertex::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *vtkNotUsed(lines), + vtkCellArray *vtkNotUsed(polys), + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + int i, numPts=this->Points->GetNumberOfPoints(), newCellId; + vtkIdType pts[1]; + + for (i=0; i < numPts; i++) + { + if ( value == cellScalars->GetComponent(i,0) ) + { + pts[0] = locator->InsertNextPoint(this->Points->GetPoint(i)); + if ( outPd ) + { + outPd->CopyData(inPd,this->PointIds->GetId(i),pts[0]); + } + newCellId = verts->InsertNextCell(1,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +// +// Intersect with sub-vertices +// +int vtkPolyVertex::IntersectWithLine(double p1[3], double p2[3], + double tol, double& t, double x[3], + double pcoords[3], int& subId) +{ + int subTest, numPts=this->Points->GetNumberOfPoints(); + + for (subId=0; subId < numPts; subId++) + { + this->Vertex->Points->SetPoint(0,this->Points->GetPoint(subId)); + + if ( this->Vertex->IntersectWithLine(p1, p2, tol, t, x, pcoords, subTest) ) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkPolyVertex::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + int subId; + + pts->Reset(); + ptIds->Reset(); + for (subId=0; subId < this->Points->GetNumberOfPoints(); subId++) + { + pts->InsertPoint(subId,this->Points->GetPoint(subId)); + ptIds->InsertId(subId,this->PointIds->GetId(subId)); + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPolyVertex::Derivatives(int vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], + double *vtkNotUsed(values), + int dim, double *derivs) +{ + int i, idx; + + for (i=0; iPoints->GetNumberOfPoints(); + vtkIdType pts[1]; + + for ( i=0; i < numPts; i++ ) + { + s = cellScalars->GetComponent(i, 0); + + if ( (!insideOut && s > value) || (insideOut && s <= value) ) + { + this->Points->GetPoint(i,x); + if ( locator->InsertUniquePoint(x, pts[0]) ) + { + outPd->CopyData(inPd,this->PointIds->GetId(i),pts[0]); + } + newCellId = verts->InsertNextCell(1,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +// Return the center of the point cloud in parametric coordinates. +int vtkPolyVertex::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = pcoords[2] = 0.5; + return (this->Points->GetNumberOfPoints() / 2); +} + +//---------------------------------------------------------------------------- +void vtkPolyVertex::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Vertex:\n"; + this->Vertex->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkPolyVertex.h b/Filtering/vtkPolyVertex.h new file mode 100644 index 0000000..3ca3628 --- /dev/null +++ b/Filtering/vtkPolyVertex.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyVertex.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyVertex - cell represents a set of 0D vertices +// .SECTION Description +// vtkPolyVertex is a concrete implementation of vtkCell to represent a +// set of 3D vertices. + +#ifndef __vtkPolyVertex_h +#define __vtkPolyVertex_h + +#include "vtkCell.h" + +class vtkVertex; + +class VTK_FILTERING_EXPORT vtkPolyVertex : public vtkCell +{ +public: + static vtkPolyVertex *New(); + vtkTypeRevisionMacro(vtkPolyVertex,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_POLY_VERTEX;}; + int GetCellDimension() {return 0;}; + int GetNumberOfEdges() {return 0;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int vtkNotUsed(edgeId)) {return 0;}; + vtkCell *GetFace(int vtkNotUsed(faceId)) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + int IsPrimaryCell() {return 0;} + + // Description: + // Return the center of the point cloud in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + +protected: + vtkPolyVertex(); + ~vtkPolyVertex(); + + vtkVertex *Vertex; + +private: + vtkPolyVertex(const vtkPolyVertex&); // Not implemented. + void operator=(const vtkPolyVertex&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkPolygon.cxx b/Filtering/vtkPolygon.cxx new file mode 100644 index 0000000..666ae1e --- /dev/null +++ b/Filtering/vtkPolygon.cxx @@ -0,0 +1,1415 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolygon.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolygon.h" + +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPoints.h" +#include "vtkPriorityQueue.h" +#include "vtkQuad.h" +#include "vtkTriangle.h" +#include "vtkBox.h" + +vtkCxxRevisionMacro(vtkPolygon, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkPolygon); + +// Instantiate polygon. +vtkPolygon::vtkPolygon() +{ + this->Tris = vtkIdList::New(); + this->Tris->Allocate(VTK_CELL_SIZE); + this->Triangle = vtkTriangle::New(); + this->Quad = vtkQuad::New(); + this->TriScalars = vtkDoubleArray::New(); + this->TriScalars->Allocate(3); + this->Line = vtkLine::New(); + this->Tolerance = 0.0; + this->SuccessfulTriangulation = 0; + this->Normal[0] = this->Normal[1] = this->Normal[2] = 0.0; +} + +vtkPolygon::~vtkPolygon() +{ + this->Tris->Delete(); + this->Triangle->Delete(); + this->Quad->Delete(); + this->TriScalars->Delete(); + this->Line->Delete(); +} + +#define VTK_POLYGON_FAILURE -1 +#define VTK_POLYGON_OUTSIDE 0 +#define VTK_POLYGON_INSIDE 1 +#define VTK_POLYGON_INTERSECTION 2 +#define VTK_POLYGON_ON_LINE 3 + +// +// In many of the functions that follow, the Points and PointIds members +// of the Cell are assumed initialized. This is usually done indirectly +// through the GetCell(id) method in the DataSet objects. +// + +// Compute the polygon normal from a points list, and a list of point ids +// that index into the points list. This version will handle non-convex +// polygons. +void vtkPolygon::ComputeNormal(vtkPoints *p, int numPts, vtkIdType *pts, + double *n) +{ + int i; + double v0[3], v1[3], v2[3]; + double ax, ay, az, bx, by, bz; +// +// Check for special triangle case. Saves extra work. +// + n[0] = n[1] = n[2] = 0.0; + if ( numPts == 2 || numPts == 1 ) + { + return; + } + + if ( numPts == 3 ) + { + p->GetPoint(pts[0],v0); + p->GetPoint(pts[1],v1); + p->GetPoint(pts[2],v2); + vtkTriangle::ComputeNormal(v0, v1, v2, n); + return; + } + + // Because polygon may be concave, need to accumulate cross products to + // determine true normal. + // + p->GetPoint(pts[0],v1); //set things up for loop + p->GetPoint(pts[1],v2); + + for (i=0; i < numPts; i++) + { + v0[0] = v1[0]; v0[1] = v1[1]; v0[2] = v1[2]; + v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; + p->GetPoint(pts[(i+2)%numPts],v2); + + // order is important!!! to maintain consistency with polygon vertex order + ax = v2[0] - v1[0]; ay = v2[1] - v1[1]; az = v2[2] - v1[2]; + bx = v0[0] - v1[0]; by = v0[1] - v1[1]; bz = v0[2] - v1[2]; + + n[0] += (ay * bz - az * by); + n[1] += (az * bx - ax * bz); + n[2] += (ax * by - ay * bx); + } + + vtkMath::Normalize(n); +} + +// Compute the polygon normal from a list of doubleing points. This version +// will handle non-convex polygons. +void vtkPolygon::ComputeNormal(vtkPoints *p, double *n) +{ + int i, numPts; + double v0[3], v1[3], v2[3]; + double ax, ay, az, bx, by, bz; + + // Polygon is assumed non-convex -> need to accumulate cross products to + // find correct normal. + // + numPts = p->GetNumberOfPoints(); + p->GetPoint(0, v1); //set things up for loop + p->GetPoint(1, v2); + n[0] = n[1] = n[2] = 0.0; + + for (i=0; i < numPts; i++) + { + memcpy(v0, v1, sizeof(v0)); + memcpy(v1, v2, sizeof(v1)); + p->GetPoint((i+2)%numPts, v2); + + // order is important!!! to maintain consistency with polygon vertex order + ax = v2[0] - v1[0]; ay = v2[1] - v1[1]; az = v2[2] - v1[2]; + bx = v0[0] - v1[0]; by = v0[1] - v1[1]; bz = v0[2] - v1[2]; + + n[0] += (ay * bz - az * by); + n[1] += (az * bx - ax * bz); + n[2] += (ax * by - ay * bx); + }//over all points + + vtkMath::Normalize(n); +} + +// Compute the polygon normal from an array of points. This version assumes +// that the polygon is convex, and looks for the first valid normal. +void vtkPolygon::ComputeNormal (int numPts, double *pts, double n[3]) +{ + int i; + double *v1, *v2, *v3; + double length; + double ax, ay, az; + double bx, by, bz; + + // Because some polygon vertices are colinear, need to make sure + // first non-zero normal is found. + // + v1 = pts; + v2 = pts + 3; + v3 = pts + 6; + + for (i=0; iParameterizePolygon(p0, p10, l10, p20, l20, n); + this->ComputeWeights(x,weights); + vtkPlane::ProjectPoint(x,p0,n,cp); + + for (i=0; i<3; i++) + { + ray[i] = cp[i] - p0[i]; + } + pcoords[0] = vtkMath::Dot(ray,p10) / (l10*l10); + pcoords[1] = vtkMath::Dot(ray,p20) / (l20*l20); + + if ( pcoords[0] >= 0.0 && pcoords[0] <= 1.0 && + pcoords[1] >= 0.0 && pcoords[1] <= 1.0 && + (this->PointInPolygon(cp, this->Points->GetNumberOfPoints(), + ((vtkDoubleArray *)this->Points->GetData()) + ->GetPointer(0), this->GetBounds(),n) + == VTK_POLYGON_INSIDE) ) + { + if (closestPoint) + { + closestPoint[0] = cp[0]; + closestPoint[1] = cp[1]; + closestPoint[2] = cp[2]; + minDist2 = vtkMath::Distance2BetweenPoints(x,closestPoint); + } + return 1; + } + + // If here, point is outside of polygon, so need to find distance to boundary + // + else + { + double t, dist2; + int numPts; + double closest[3]; + double pt1[3], pt2[3]; + + if (closestPoint) + { + numPts = this->Points->GetNumberOfPoints(); + for (minDist2=VTK_DOUBLE_MAX,i=0; iPoints->GetPoint(i, pt1); + this->Points->GetPoint((i+1)%numPts, pt2); + dist2 = vtkLine::DistanceToLine(x, pt1, pt2, t, closest); + if ( dist2 < minDist2 ) + { + closestPoint[0] = closest[0]; + closestPoint[1] = closest[1]; + closestPoint[2] = closest[2]; + minDist2 = dist2; + } + } + } + return 0; + } +} + +void vtkPolygon::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + int i; + double p0[3], p10[3], l10, p20[3], l20, n[3]; + + this->ParameterizePolygon(p0, p10, l10, p20, l20, n); + for (i=0; i<3; i++) + { + x[i] = p0[i] + pcoords[0]*p10[i] + pcoords[1]*p20[i]; + } + + this->ComputeWeights(x,weights); +} + +// Create a local s-t coordinate system for a polygon. The point p0 is +// the origin of the local system, p10 is s-axis vector, and p20 is the +// t-axis vector. (These are expressed in the modelling coordinate system and +// are vectors of dimension [3].) The values l20 and l20 are the lengths of +// the vectors p10 and p20, and n is the polygon normal. +int vtkPolygon::ParameterizePolygon(double *p0, double *p10, double& l10, + double *p20,double &l20, double *n) +{ + int i, j; + double s, t, p[3], p1[3], p2[3], sbounds[2], tbounds[2]; + int numPts=this->Points->GetNumberOfPoints(); + double x1[3], x2[3]; + + // This is a two pass process: first create a p' coordinate system + // that is then adjusted to insure that the polygon points are all in + // the range 0<=s,t<=1. The p' system is defined by the polygon normal, + // first vertex and the first edge. + // + this->ComputeNormal (this->Points,n); + this->Points->GetPoint(0, x1); + this->Points->GetPoint(1, x2); + for (i=0; i<3; i++) + { + p0[i] = x1[i]; + p10[i] = x2[i] - x1[i]; + } + vtkMath::Cross (n,p10,p20); + + // Determine lengths of edges + // + if ( (l10=vtkMath::Dot(p10,p10)) == 0.0 + || (l20=vtkMath::Dot(p20,p20)) == 0.0 ) + { + return 0; + } + + // Now evalute all polygon points to determine min/max parametric + // coordinate values. + // + // first vertex has (s,t) = (0,0) + sbounds[0] = 0.0; sbounds[1] = 0.0; + tbounds[0] = 0.0; tbounds[1] = 0.0; + + for(i=1; iPoints->GetPoint(i, x1); + for(j=0; j<3; j++) + { + p[j] = x1[j] - p0[j]; + } +#ifdef BAD_WITH_NODEBUG + s = vtkMath::Dot(p,p10) / l10; + t = vtkMath::Dot(p,p20) / l20; +#endif + s = (p[0]*p10[0] + p[1]*p10[1] + p[2]*p10[2]) / l10; + t = (p[0]*p20[0] + p[1]*p20[1] + p[2]*p20[2]) / l20; + sbounds[0] = (ssbounds[1]?s:sbounds[1]); + tbounds[0] = (ttbounds[1]?t:tbounds[1]); + } + + // Re-evaluate coordinate system + // + for (i=0; i<3; i++) + { + p1[i] = p0[i] + sbounds[1]*p10[i] + tbounds[0]*p20[i]; + p2[i] = p0[i] + sbounds[0]*p10[i] + tbounds[1]*p20[i]; + p0[i] = p0[i] + sbounds[0]*p10[i] + tbounds[0]*p20[i]; + p10[i] = p1[i] - p0[i]; + p20[i] = p2[i] - p0[i]; + } + l10 = vtkMath::Norm(p10); + l20 = vtkMath::Norm(p20); + + return 1; +} + +#define VTK_POLYGON_CERTAIN 1 +#define VTK_POLYGON_UNCERTAIN 0 +#define VTK_POLYGON_RAY_TOL 1.e-03 //Tolerance for ray firing +#define VTK_POLYGON_MAX_ITER 10 //Maximum iterations for ray-firing +#define VTK_POLYGON_VOTE_THRESHOLD 2 + +#ifndef TRUE +#define FALSE 0 +#define TRUE 1 +#endif + +// Determine whether point is inside polygon. Function uses ray-casting +// to determine if point is inside polygon. Works for arbitrary polygon shape +// (e.g., non-convex). Returns 0 if point is not in polygon; 1 if it is. +// Can also return -1 to indicate degenerate polygon. Note: a point in +// bounding box check is NOT performed prior to in/out check. You may want +// to do this to improve performance. +int vtkPolygon::PointInPolygon (double x[3], int numPts, double *pts, + double bounds[6], double *n) +{ + double *x1, *x2, xray[3], u, v; + double rayMag, mag=1, ray[3]; + int testResult, rayOK, status, numInts, i; + int iterNumber; + int maxComp, comps[2]; + int deltaVotes; + + // do a quick bounds check + if ( x[0] < bounds[0] || x[0] > bounds[1] || + x[1] < bounds[2] || x[1] > bounds[3] || + x[2] < bounds[4] || x[2] > bounds[5]) + { + return VTK_POLYGON_OUTSIDE; + } + + // + // Define a ray to fire. The ray is a random ray normal to the + // normal of the face. The length of the ray is a function of the + // size of the face bounding box. + // + for (i=0; i<3; i++) + { + ray[i] = ( bounds[2*i+1] - bounds[2*i] )*1.1 + + fabs((bounds[2*i+1] + bounds[2*i])/2.0 - x[i]); + } + + if ( (rayMag = vtkMath::Norm(ray)) == 0.0 ) + { + return VTK_POLYGON_OUTSIDE; + } + + // Get the maximum component of the normal. + // + if ( fabs(n[0]) > fabs(n[1]) ) + { + if ( fabs(n[0]) > fabs(n[2]) ) + { + maxComp = 0; + comps[0] = 1; + comps[1] = 2; + } + else + { + maxComp = 2; + comps[0] = 0; + comps[1] = 1; + } + } + else + { + if ( fabs(n[1]) > fabs(n[2]) ) + { + maxComp = 1; + comps[0] = 0; + comps[1] = 2; + } + else + { + maxComp = 2; + comps[0] = 0; + comps[1] = 1; + } + } + + // Check that max component is non-zero + // + if ( n[maxComp] == 0.0 ) + { + return VTK_POLYGON_FAILURE; + } + + // Enough information has been acquired to determine the random ray. + // Random rays are generated until one is satisfactory (i.e., + // produces a ray of non-zero magnitude). Also, since more than one + // ray may need to be fired, the ray-firing occurs in a large loop. + // + // The variable iterNumber counts the number of iterations and is + // limited by the defined variable VTK_POLYGON_MAX_ITER. + // + // The variable deltaVotes keeps track of the number of votes for + // "in" versus "out" of the face. When delta_vote > 0, more votes + // have counted for "in" than "out". When delta_vote < 0, more votes + // have counted for "out" than "in". When the delta_vote exceeds or + // equals the defined variable VTK_POLYGON_VOTE_THRESHOLD, than the + // appropriate "in" or "out" status is returned. + // + for (deltaVotes = 0, iterNumber = 1; + (iterNumber < VTK_POLYGON_MAX_ITER) + && (abs(deltaVotes) < VTK_POLYGON_VOTE_THRESHOLD); + iterNumber++) + { + // + // Generate ray + // + for (rayOK = FALSE; rayOK == FALSE; ) + { + ray[comps[0]] = vtkMath::Random(-rayMag, rayMag); + ray[comps[1]] = vtkMath::Random(-rayMag, rayMag); + ray[maxComp] = -(n[comps[0]]*ray[comps[0]] + + n[comps[1]]*ray[comps[1]]) / n[maxComp]; + if ( (mag = vtkMath::Norm(ray)) > rayMag*VTK_TOL ) + { + rayOK = TRUE; + } + } + + // The ray must be appropriately sized. + // + for (i=0; i<3; i++) + { + xray[i] = x[i] + (rayMag/mag)*ray[i]; + } + + // The ray may now be fired against all the edges + // + for (numInts=0, testResult=VTK_POLYGON_CERTAIN, i=0; iGetBounds(); + + d = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + this->Tolerance = VTK_POLYGON_TOLERANCE * d; + this->SuccessfulTriangulation = 1; + + this->Tris->Reset(); + success = this->EarCutTriangulation(); + + if ( !success ) //degenerate triangle encountered + { + vtkWarningMacro(<< "Degenerate polygon encountered during triangulation"); + } + + outTris->DeepCopy(this->Tris); + return success; +} + +// Special structures for building loops. This is a double-linked list. +typedef struct _vtkPolyVertex + { + int id; + double x[3]; + double measure; + _vtkPolyVertex* next; + _vtkPolyVertex* previous; + } vtkLocalPolyVertex; + +class vtkPolyVertexList { //structure to support triangulation +public: + vtkPolyVertexList(vtkIdList *ptIds, vtkPoints *pts, double tol2); + ~vtkPolyVertexList(); + + int ComputeNormal(); + double ComputeMeasure(vtkLocalPolyVertex *vtx); + void RemoveVertex(int i, vtkIdList *, vtkPriorityQueue *); + int CanRemoveVertex(int id, double tol); + + int NumberOfVerts; + vtkLocalPolyVertex *Array; + vtkLocalPolyVertex *Head; + double Normal[3]; +}; + +// tolerance is squared +vtkPolyVertexList::vtkPolyVertexList(vtkIdList *ptIds, vtkPoints *pts, + double tol2) +{ + int numVerts = ptIds->GetNumberOfIds(); + this->NumberOfVerts = numVerts; + this->Array = new vtkLocalPolyVertex [numVerts]; + int i; + + // now load the data into the array + double x[3]; + for (i=0; iArray[i].id = i; + pts->GetPoint(i,x); + this->Array[i].x[0] = x[0]; + this->Array[i].x[1] = x[1]; + this->Array[i].x[2] = x[2]; + this->Array[i].next = this->Array + (i+1)%numVerts; + if ( i == 0 ) + { + this->Array[i].previous = this->Array + numVerts - 1; + } + else + { + this->Array[i].previous = this->Array + i - 1; + } + } + + // Make sure that there are no coincident vertices. + // Beware of multiple coincident vertices. + vtkLocalPolyVertex *vtx, *next; + this->Head = this->Array; + + for (vtx=this->Head, i=0; inext; + if ( vtkMath::Distance2BetweenPoints(vtx->x,next->x) < tol2 ) + { + next->next->previous = vtx; + vtx->next = next->next; + if ( next == this->Head ) + { + this->Head = vtx; + } + this->NumberOfVerts--; + } + else //can move forward + { + vtx = next; + } + } +} + +vtkPolyVertexList::~vtkPolyVertexList() +{ + delete [] this->Array; +} + +// Remove the vertex from the polygon (forming a triangle with +// its previous and next neighbors, and reinsert the neighbors +// into the priority queue. +void vtkPolyVertexList::RemoveVertex(int i, vtkIdList *tris, + vtkPriorityQueue *queue) +{ + // Create triangle + tris->InsertNextId(this->Array[i].id); + tris->InsertNextId(this->Array[i].next->id); + tris->InsertNextId(this->Array[i].previous->id); + + // remove vertex; special case if single triangle left + if ( --this->NumberOfVerts < 3 ) + { + return; + } + if ( (this->Array + i) == this->Head ) + { + this->Head = this->Array[i].next; + } + this->Array[i].previous->next = this->Array[i].next; + this->Array[i].next->previous = this->Array[i].previous; + + // recompute measure, reinsert into queue + // note that id may have been previously deleted (with Pop()) if we + // are dealing with a concave polygon and vertex couldn't be split. + queue->DeleteId(this->Array[i].previous->id); + queue->DeleteId(this->Array[i].next->id); + if ( this->ComputeMeasure(this->Array[i].previous) > 0.0 ) + { + queue->Insert(this->Array[i].previous->measure, + this->Array[i].previous->id); + } + if ( this->ComputeMeasure(this->Array[i].next) > 0.0 ) + { + queue->Insert(this->Array[i].next->measure, + this->Array[i].next->id); + } +} + +int vtkPolyVertexList::ComputeNormal() +{ + vtkLocalPolyVertex *vtx=this->Head; + double v1[3], v2[3], n[3], *anchor=vtx->x; + + this->Normal[0] = this->Normal[1] = this->Normal[2] = 0.0; + for (vtx=vtx->next; vtx->next!=this->Head; vtx=vtx->next) + { + v1[0] = vtx->x[0] - anchor[0]; + v1[1] = vtx->x[1] - anchor[1]; + v1[2] = vtx->x[2] - anchor[2]; + v2[0] = vtx->next->x[0] - anchor[0]; + v2[1] = vtx->next->x[1] - anchor[1]; + v2[2] = vtx->next->x[2] - anchor[2]; + vtkMath::Cross(v1,v2,n); + this->Normal[0] += n[0]; + this->Normal[1] += n[1]; + this->Normal[2] += n[2]; + } + if ( vtkMath::Normalize(this->Normal) == 0.0 ) + { + return 0; + } + else + { + return 1; + } +} + +// The measure is the ratio of triangle perimeter^2 to area; +// the sign of the measure is determined by dotting the local +// vector with the normal (concave features return a negative +// measure). +double vtkPolyVertexList::ComputeMeasure(vtkLocalPolyVertex *vtx) +{ + double v1[3], v2[3], v3[3], v4[3], area, perimeter; + + for (int i=0; i<3; i++) + { + v1[i] = vtx->x[i] - vtx->previous->x[i]; + v2[i] = vtx->next->x[i] - vtx->x[i]; + v3[i] = vtx->previous->x[i] - vtx->next->x[i]; + } + vtkMath::Cross(v1,v2,v4); //|v4| is twice the area + if ( (area=vtkMath::Dot(v4,this->Normal)) < 0.0 ) + { + return (vtx->measure = -1.0); //concave or bad triangle + } + else if ( area == 0.0 ) + { + return (vtx->measure = -VTK_DOUBLE_MAX); //concave or bad triangle + } + else + { + perimeter = vtkMath::Norm(v1) + vtkMath::Norm(v2) + + vtkMath::Norm(v3); + return (vtx->measure = perimeter*perimeter/area); + } +} + +// returns != 0 if vertex can be removed. Uses half-space +// comparison to determine whether ear-cut is valid, and may +// resort to line-plane intersections to resolve possible +// instersections with ear-cut. +int vtkPolyVertexList::CanRemoveVertex(int id, double tolerance) +{ + int i, sign, currentSign; + double v[3], sN[3], *sPt, val, s, t; + vtkLocalPolyVertex *currentVtx, *previous, *next, *vtx; + + // Check for simple case + if ( this->NumberOfVerts <= 3 ) + { + return 1; + } + + // Compute split plane, the point to be cut off + // is always on the positive side of the plane. + currentVtx = this->Array + id; + previous = currentVtx->previous; + next = currentVtx->next; + + sPt = previous->x; //point on plane + for (i=0; i<3; i++) + { + v[i] = next->x[i] - previous->x[i]; //vector passing through point + } + + vtkMath::Cross (v,this->Normal,sN); + if ( (vtkMath::Normalize(sN)) == 0.0 ) + { + return 0; //bad split, indeterminant + } + + // Traverse the other points to see if a) they are all on the + // other side of the plane; and if not b) whether they intersect + // the split line. + int oneNegative=0; + val = vtkPlane::Evaluate(sN,sPt,next->next->x); + currentSign = (val > tolerance ? 1 : (val < -tolerance ? -1 : 0)); + oneNegative = (currentSign < 0 ? 1 : 0); //very important + + // Intersections are only computed when the split half-space is crossed + for (vtx=next->next->next; vtx != previous; vtx = vtx->next) + { + val = vtkPlane::Evaluate(sN,sPt,vtx->x); + sign = (val > tolerance ? 1 : (val < -tolerance ? -1 : 0)); + if ( sign != currentSign ) + { + if ( !oneNegative ) + { + oneNegative = (sign < 0 ? 1 : 0); //very important + } + if (vtkLine::Intersection(sPt,next->x,vtx->x,vtx->previous->x,s,t) != 0 ) + { + return 0; + } + else + { + currentSign = sign; + } + }//if crossing occurs + }//for the rest of the loop + + if ( !oneNegative ) + { + return 0; //entire loop is on this side of plane + } + else + { + return 1; + } +} + +// Triangulation method based on ear-cutting. Triangles, or ears, are +// cut off from the polygon based on the angle of the vertex. Small +// angles (narrow triangles) are cut off first. This implementation uses +// a priority queue to cut off ears with smallest angles. Also, the +// algorithm works in 3D (the points don't have to be projected into +// 2D, and the ordering direction of the points is nor important as +// long as the polygon edges do not self intersect). +int vtkPolygon::EarCutTriangulation () +{ + vtkPolyVertexList poly(this->PointIds, this->Points, + this->Tolerance*this->Tolerance); + vtkLocalPolyVertex *vtx; + int i, id; + + // First compute the polygon normal the correct way + // + if ( ! poly.ComputeNormal() ) + { + return (this->SuccessfulTriangulation=0); + } + + // Now compute the angles between edges incident to each + // vertex. Place the structure into a priority queue (those + // vertices with smallest angle are to be removed first). + // + vtkPriorityQueue *VertexQueue = vtkPriorityQueue::New(); + VertexQueue->Allocate(poly.NumberOfVerts); + for (i=0, vtx=poly.Head; i < poly.NumberOfVerts; i++, vtx=vtx->next) + { + //concave (negative measure) vertices are not elgible for removal + if ( poly.ComputeMeasure(vtx) > 0.0 ) + { + VertexQueue->Insert(vtx->measure, vtx->id); + } + } + + // For each vertex in priority queue, and as long as there + // are three or more vertices, remove the vertex (if possible) + // and create a new triangle. If the number of vertices in the + // queue is equal to the number of vertices, then the polygon + // is convex and triangle removal can proceed without intersection + // checks. + // + int numInQueue; + while ( poly.NumberOfVerts > 2 && + (numInQueue=VertexQueue->GetNumberOfItems()) > 0) + { + if ( numInQueue == poly.NumberOfVerts ) //convex, pop away + { + id = VertexQueue->Pop(); + poly.RemoveVertex(id,this->Tris,VertexQueue); + }//convex + else + { + id = VertexQueue->Pop(); //removes it, even if can't be split + if ( poly.CanRemoveVertex(id,this->Tolerance) ) + { + poly.RemoveVertex(id,this->Tris,VertexQueue); + } + }//concave + }//while + + // Clean up + VertexQueue->Delete(); + + if ( poly.NumberOfVerts > 2 ) //couldn't triangulate + { + return (this->SuccessfulTriangulation=0); + } + return (this->SuccessfulTriangulation=1); +} + + +int vtkPolygon::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + int i, numPts=this->PointIds->GetNumberOfIds(); + double x[3], *weights; + int closestPoint=0, previousPoint, nextPoint; + double largestWeight=0.0; + double p0[3], p10[3], l10, p20[3], l20, n[3]; + + pts->Reset(); + weights = new double[numPts]; + + // determine global coordinates given parametric coordinates + this->ParameterizePolygon(p0, p10, l10, p20, l20, n); + for (i=0; i<3; i++) + { + x[i] = p0[i] + pcoords[0]*p10[i] + pcoords[1]*p20[i]; + } + + //find edge with largest and next largest weight values. This will be + //the closest edge. + this->ComputeWeights(x,weights); + for ( i=0; i < numPts; i++ ) + { + if ( weights[i] > largestWeight ) + { + closestPoint = i; + largestWeight = weights[i]; + } + } + + pts->InsertId(0,this->PointIds->GetId(closestPoint)); + + previousPoint = closestPoint - 1; + nextPoint = closestPoint + 1; + if ( previousPoint < 0 ) + { + previousPoint = numPts - 1; + } + if ( nextPoint >= numPts ) + { + nextPoint = 0; + } + + if ( weights[previousPoint] > weights[nextPoint] ) + { + pts->InsertId(1,this->PointIds->GetId(previousPoint)); + } + else + { + pts->InsertId(1,this->PointIds->GetId(nextPoint)); + } + delete [] weights; + + // determine whether point is inside of polygon + if ( pcoords[0] >= 0.0 && pcoords[0] <= 1.0 && + pcoords[1] >= 0.0 && pcoords[1] <= 1.0 && + (this->PointInPolygon(x, this->Points->GetNumberOfPoints(), + ((vtkDoubleArray *)this->Points->GetData()) + ->GetPointer(0), this->GetBounds(),n) + == VTK_POLYGON_INSIDE) ) + { + return 1; + } + else + { + return 0; + } +} + +void vtkPolygon::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + int i, success; + double *bounds, d; + int p1, p2, p3; + + this->TriScalars->SetNumberOfTuples(3); + + bounds = this->GetBounds(); + + d = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + this->Tolerance = VTK_POLYGON_TOLERANCE * d; + this->SuccessfulTriangulation = 1; + this->ComputeNormal(this->Points, this->Normal); + + this->Tris->Reset(); + + success = this->EarCutTriangulation(); + + if ( !success ) // Just skip for now. + { + } + else // Contour triangle + { + for (i=0; iTris->GetNumberOfIds(); i += 3) + { + p1 = this->Tris->GetId(i); + p2 = this->Tris->GetId(i+1); + p3 = this->Tris->GetId(i+2); + + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(p1)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(p2)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(p3)); + + if ( outPd ) + { + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(p1)); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(p2)); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(p3)); + } + + this->TriScalars->SetTuple(0,cellScalars->GetTuple(p1)); + this->TriScalars->SetTuple(1,cellScalars->GetTuple(p2)); + this->TriScalars->SetTuple(2,cellScalars->GetTuple(p3)); + + this->Triangle->Contour(value, this->TriScalars, locator, verts, + lines, polys, inPd, outPd, inCd, cellId, outCd); + } + } +} + +vtkCell *vtkPolygon::GetEdge(int edgeId) +{ + int numPts=this->Points->GetNumberOfPoints(); + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(edgeId)); + this->Line->PointIds->SetId(1,this->PointIds->GetId((edgeId+1) % numPts)); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(edgeId)); + this->Line->Points->SetPoint(1,this->Points->GetPoint((edgeId+1) % numPts)); + + return this->Line; +} + +// +// Compute interpolation weights using 1/r**2 normalized sum. +// +void vtkPolygon::ComputeWeights(double x[3], double *weights) +{ + int i; + int numPts=this->Points->GetNumberOfPoints(); + double sum, pt[3]; + + for (sum=0.0, i=0; iPoints->GetPoint(i, pt); + weights[i] = vtkMath::Distance2BetweenPoints(x,pt); + if ( weights[i] == 0.0 ) //exact hit + { + for (int j=0; jGetNumberOfPoints(); + double *weights; + + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + + // Define a plane to intersect with + // + this->Points->GetPoint(1, pt1); + this->ComputeNormal (this->Points,n); + + // Intersect plane of the polygon with line + // + if ( ! vtkPlane::IntersectWithLine(p1,p2,n,pt1,t,x) ) + { + return 0; + } + + // Evaluate position + // + weights = new double[npts]; + if ( this->EvaluatePosition(x, closestPoint, subId, pcoords, dist2, weights) >= 0) + { + if ( dist2 <= tol2 ) + { + delete [] weights; + return 1; + } + } + delete [] weights; + return 0; + +} + +int vtkPolygon::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + int i, success; + double *bounds, d; + + pts->Reset(); + ptIds->Reset(); + + bounds = this->GetBounds(); + d = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + this->Tolerance = VTK_POLYGON_TOLERANCE * d; + this->SuccessfulTriangulation = 1; + this->ComputeNormal(this->Points, this->Normal); + + this->Tris->Reset(); + + success = this->EarCutTriangulation(); + + if ( !success ) // Indicate possible failure + { + vtkDebugMacro(<<"Possible triangulation failure"); + } + for (i=0; iTris->GetNumberOfIds(); i++) + { + ptIds->InsertId(i,this->PointIds->GetId(this->Tris->GetId(i))); + pts->InsertPoint(i,this->Points->GetPoint(this->Tris->GetId(i))); + } + + return this->SuccessfulTriangulation; +} + +// Samples at three points to compute derivatives in local r-s coordinate +// system and projects vectors into 3D model coordinate system. +// Note that the results are usually inaccurate because +// this method actually returns the derivative of the interpolation +// function which is obtained using 1/r**2 normalized sum. +#define VTK_SAMPLE_DISTANCE 0.01 +void vtkPolygon::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + int i, j, k, idx; + + if ( this->Points->GetNumberOfPoints() == 4 ) + { + for(i=0; i<4; i++) + { + this->Quad->Points->SetPoint(i,this->Points->GetPoint(i)); + } + this->Quad->Derivatives(0, pcoords, values, dim, derivs); + return; + } + else if ( this->Points->GetNumberOfPoints() == 3 ) + { + for(i=0; i<3; i++) + { + this->Triangle->Points->SetPoint(i,this->Points->GetPoint(i)); + } + this->Triangle->Derivatives(0, pcoords, values, dim, derivs); + return; + } + + double p0[3], p10[3], l10, p20[3], l20, n[3]; + double x[3][3], l1, l2, v1[3], v2[3]; + int numVerts=this->PointIds->GetNumberOfIds(); + double *weights = new double[numVerts]; + double *sample = new double[dim*3]; + + //setup parametric system and check for degeneracy + if ( this->ParameterizePolygon(p0, p10, l10, p20, l20, n) == 0 ) + { + for ( j=0; j < dim; j++ ) + { + for ( i=0; i < 3; i++ ) + { + derivs[j*dim + i] = 0.0; + } + } + return; + } + + //compute positions of three sample points + for (i=0; i<3; i++) + { + x[0][i] = p0[i] + pcoords[0]*p10[i] + pcoords[1]*p20[i]; + x[1][i] = p0[i] + (pcoords[0]+VTK_SAMPLE_DISTANCE)*p10[i] + + pcoords[1]*p20[i]; + x[2][i] = p0[i] + pcoords[0]*p10[i] + + (pcoords[1]+VTK_SAMPLE_DISTANCE)*p20[i]; + } + + //for each sample point, sample data values + for ( idx=0, k=0; k < 3; k++ ) //loop over three sample points + { + this->ComputeWeights(x[k],weights); + for ( j=0; j < dim; j++, idx++) //over number of derivates requested + { + sample[idx] = 0.0; + for ( i=0; i < numVerts; i++ ) + { + sample[idx] += weights[i] * values[j + i*dim]; + } + } + } + + //compute differences along the two axes + for ( i=0; i < 3; i++ ) + { + v1[i] = x[1][i] - x[0][i]; + v2[i] = x[2][i] - x[0][i]; + } + l1 = vtkMath::Normalize(v1); + l2 = vtkMath::Normalize(v2); + + //compute derivatives along x-y-z axes + double ddx, ddy; + for ( j=0; j < dim; j++ ) + { + ddx = (sample[dim+j] - sample[j]) / l1; + ddy = (sample[2*dim+j] - sample[j]) / l2; + + //project onto global x-y-z axes + derivs[3*j] = ddx*v1[0] + ddy*v2[0]; + derivs[3*j + 1] = ddx*v1[1] + ddy*v2[1]; + derivs[3*j + 2] = ddx*v1[2] + ddy*v2[2]; + } + + delete [] weights; + delete [] sample; +} + +void vtkPolygon::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tris, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData *outCD, + int insideOut) +{ + int i, success; + double *bounds, d; + int p1, p2, p3; + + this->TriScalars->SetNumberOfTuples(3); + + bounds = this->GetBounds(); + d = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + this->Tolerance = VTK_POLYGON_TOLERANCE * d; + + this->SuccessfulTriangulation = 1; + this->ComputeNormal(this->Points, this->Normal); + + this->Tris->Reset(); + + success = this->EarCutTriangulation(); + + if ( success ) // clip triangles + { + for (i=0; iTris->GetNumberOfIds(); i += 3) + { + p1 = this->Tris->GetId(i); + p2 = this->Tris->GetId(i+1); + p3 = this->Tris->GetId(i+2); + + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(p1)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(p2)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(p3)); + + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(p1)); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(p2)); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(p3)); + + this->TriScalars->SetTuple(0,cellScalars->GetTuple(p1)); + this->TriScalars->SetTuple(1,cellScalars->GetTuple(p2)); + this->TriScalars->SetTuple(2,cellScalars->GetTuple(p3)); + + this->Triangle->Clip(value, this->TriScalars, locator, tris, + inPD, outPD, inCD, cellId, outCD, insideOut); + } + } +} + +// Method intersects two polygons. You must supply the number of points and +// point coordinates (npts, *pts) and the bounding box (bounds) of the two +// polygons. Also supply a tolerance squared for controlling +// error. The method returns 1 if there is an intersection, and 0 if +// not. A single point of intersection x[3] is also returned if there +// is an intersection. +int vtkPolygon::IntersectPolygonWithPolygon(int npts, double *pts,double bounds[6], + int npts2, double *pts2, + double bounds2[6], double tol2, + double x[3]) +{ + double n[3], coords[3]; + int i, j; + double *p1, *p2, ray[3]; + double t; + + // Intersect each edge of first polygon against second + // + vtkPolygon::ComputeNormal(npts2, pts2, n); + + for (i=0; i3 + && vtkPolygon::PointInPolygon(x,npts2,pts2,bounds2,n) + ==VTK_POLYGON_INSIDE)) + { + return 1; + } + } + else + { + return 0; + } + } + + // Intersect each edge of second polygon against first + // + vtkPolygon::ComputeNormal(npts, pts, n); + + for (i=0; i3 && vtkPolygon::PointInPolygon(x,npts,pts,bounds,n) + ==VTK_POLYGON_INSIDE)) + { + return 1; + } + } + else + { + return 0; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +void vtkPolygon::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Tolerance: " << this->Tolerance << "\n"; + os << indent << "SuccessfulTriangulation: " << this->SuccessfulTriangulation << "\n"; + os << indent << "Normal: (" << this->Normal[0] << ", " + << this->Normal[1] << ", " << this->Normal[2] << ")\n"; + os << indent << "Tris:\n"; + this->Tris->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Triangle:\n"; + this->Triangle->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Quad:\n"; + this->Quad->PrintSelf(os,indent.GetNextIndent()); + os << indent << "TriScalars:\n"; + this->TriScalars->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkPolygon.h b/Filtering/vtkPolygon.h new file mode 100644 index 0000000..a62500f --- /dev/null +++ b/Filtering/vtkPolygon.h @@ -0,0 +1,151 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolygon.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolygon - a cell that represents an n-sided polygon +// .SECTION Description +// vtkPolygon is a concrete implementation of vtkCell to represent a 2D +// n-sided polygon. The polygons cannot have any internal holes, and cannot +// self-intersect. Define the polygon with n-points ordered in the counter- +// clockwise direction; do not repeat the last point. + +#ifndef __vtkPolygon_h +#define __vtkPolygon_h + +#include "vtkCell.h" + +class vtkDoubleArray; +class vtkLine; +class vtkPoints; +class vtkQuad; +class vtkTriangle; + +class VTK_FILTERING_EXPORT vtkPolygon : public vtkCell +{ +public: + static vtkPolygon *New(); + vtkTypeRevisionMacro(vtkPolygon,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_POLYGON;}; + int GetCellDimension() {return 2;}; + int GetNumberOfEdges() {return this->GetNumberOfPoints();}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator,vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tris, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + int IsPrimaryCell() {return 0;} + + // Description: + // Polygon specific methods. + static void ComputeNormal(vtkPoints *p, int numPts, vtkIdType *pts, + double n[3]); + static void ComputeNormal(vtkPoints *p, double n[3]); + + // Description: + // Compute the polygon normal from an array of points. This version assumes + // that the polygon is convex, and looks for the first valid normal. + static void ComputeNormal(int numPts, double *pts, double n[3]); + + // Description: + // Compute interpolation weights using 1/r**2 normalized sum. + void ComputeWeights(double x[3], double *weights); + + + // Description: + // Create a local s-t coordinate system for a polygon. The point p0 is + // the origin of the local system, p10 is s-axis vector, and p20 is the + // t-axis vector. (These are expressed in the modeling coordinate system and + // are vectors of dimension [3].) The values l20 and l20 are the lengths of + // the vectors p10 and p20, and n is the polygon normal. + int ParameterizePolygon(double p0[3], double p10[3], double &l10, + double p20[3], double &l20, double n[3]); + + // Description: + // Determine whether point is inside polygon. Function uses ray-casting + // to determine if point is inside polygon. Works for arbitrary polygon shape + // (e.g., non-convex). Returns 0 if point is not in polygon; 1 if it is. + // Can also return -1 to indicate degenerate polygon. + static int PointInPolygon(double x[3], int numPts, double *pts, + double bounds[6], double n[3]); + + // Description: + // Triangulate this polygon. The user must provide the vtkIdList outTris. + // On output, the outTris list contains the ids of the points defining + // the triangulation. The ids are ordered into groups of three: each + // three-group defines one triangle. + int Triangulate(vtkIdList *outTris); + + // Description: + // Method intersects two polygons. You must supply the number of points and + // point coordinates (npts, *pts) and the bounding box (bounds) of the two + // polygons. Also supply a tolerance squared for controlling + // error. The method returns 1 if there is an intersection, and 0 if + // not. A single point of intersection x[3] is also returned if there + // is an intersection. + static int IntersectPolygonWithPolygon(int npts, double *pts, double bounds[6], + int npts2, double *pts2, + double bounds2[3], double tol, + double x[3]); + +protected: + vtkPolygon(); + ~vtkPolygon(); + + // variables used by instances of this class + double Tolerance; // Intersection tolerance + int SuccessfulTriangulation; // Stops recursive tri. if necessary + double Normal[3]; //polygon normal + vtkIdList *Tris; + vtkTriangle *Triangle; + vtkQuad *Quad; + vtkDoubleArray *TriScalars; + vtkLine *Line; + + // Helper methods for triangulation------------------------------ + // Description: + // A fast triangulation method. Uses recursive divide and + // conquer based on plane splitting to reduce loop into triangles. + // The cell (e.g., triangle) is presumed properly initialized (i.e., + // Points and PointIds). + int EarCutTriangulation(); + +private: + vtkPolygon(const vtkPolygon&); // Not implemented. + void operator=(const vtkPolygon&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkProcessObject.cxx b/Filtering/vtkProcessObject.cxx new file mode 100644 index 0000000..5d97f6e --- /dev/null +++ b/Filtering/vtkProcessObject.cxx @@ -0,0 +1,291 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcessObject.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProcessObject.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkCommand.h" +#include "vtkDataObject.h" +#include "vtkDebugLeaks.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkSource.h" + +vtkCxxRevisionMacro(vtkProcessObject, "$Revision: 1.6.12.1 $"); + +//---------------------------------------------------------------------------- +vtkProcessObject::vtkProcessObject() +{ + this->NumberOfInputs = 0; + this->NumberOfRequiredInputs = 0; + this->Inputs = NULL; + + this->SetNumberOfInputPorts(1); +} + +// Destructor for the vtkProcessObject class +vtkProcessObject::~vtkProcessObject() +{ + int idx; + + for (idx = 0; idx < this->NumberOfInputs; ++idx) + { + if (this->Inputs[idx]) + { + this->Inputs[idx]->UnRegister(this); + this->Inputs[idx] = NULL; + } + } + if (this->Inputs) + { + delete [] this->Inputs; + this->Inputs = NULL; + this->NumberOfInputs = 0; + } +} + +//---------------------------------------------------------------------------- +vtkDataObject** vtkProcessObject::GetInputs() +{ + return this->Inputs; +} + +//---------------------------------------------------------------------------- +int vtkProcessObject::GetNumberOfInputs() +{ + return this->NumberOfInputs; +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::SetNumberOfInputs(int) +{ + // Input array size management is automatic. Do nothing. +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::AddInput(vtkDataObject* input) +{ + this->AddInputInternal(input); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::RemoveInput(vtkDataObject* input) +{ + this->RemoveInputInternal(input); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::SqueezeInputArray() +{ + // Array is always squeezed. Do nothing. +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::SetNthInput(int idx, vtkDataObject* input) +{ + int num = idx; + // Check whether anything will change. + if(num >= 0 && num < this->GetNumberOfInputConnections(0)) + { + if(this->Inputs[num] == input) + { + return; + } + } + else if(num < 0) + { + vtkErrorMacro("SetNthInput cannot set input index " << num << "."); + return; + } + + // Ask the superclass to connect the input. + this->SetNthInputConnection(0, idx, input? input->GetProducerPort() : 0); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::RemoveAllInputs() +{ + this->SetInputConnection(0, 0); +} + +//---------------------------------------------------------------------------- +int vtkProcessObject::FillInputPortInformation(int, vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + if(this->NumberOfRequiredInputs == 0) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkProcessObject::FillOutputPortInformation(int, vtkInformation*) +{ + return 1; +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + for(int i=0; i < this->NumberOfInputs; ++i) + { + vtkGarbageCollectorReport(collector, this->Inputs[i], "Inputs"); + } +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::SetInputConnection(int port, vtkAlgorithmOutput* input) +{ + this->Superclass::SetInputConnection(port, input); + this->SetupInputs(); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::AddInputConnection(int port, vtkAlgorithmOutput* input) +{ + this->Superclass::AddInputConnection(port, input); + this->SetupInputs(); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::RemoveInputConnection(int port, vtkAlgorithmOutput* input) +{ + this->Superclass::RemoveInputConnection(port, input); + this->SetupInputs(); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::SetNthInputConnection(int port, int index, + vtkAlgorithmOutput* input) +{ + this->Superclass::SetNthInputConnection(port, index, input); + this->SetupInputs(); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::SetNumberOfInputConnections(int port, int n) +{ + this->Superclass::SetNumberOfInputConnections(port, n); + this->SetupInputs(); +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::AddInputInternal(vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(0, input->GetProducerPort()); + } +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::RemoveInputInternal(vtkDataObject* input) +{ + if(input) + { + this->RemoveInputConnection(0, input->GetProducerPort()); + } +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::SetupInputs() +{ + // Construct a new array of input data objects using connections + // from input port 0. + typedef vtkDataObject* vtkDataObjectPointer; + vtkDataObject** newInputs = 0; + int newNumberOfInputs = this->GetNumberOfInputConnections(0); + if(newNumberOfInputs > 0) + { + newInputs = new vtkDataObjectPointer[newNumberOfInputs]; + int count=0; + for(int i=0; i < this->GetNumberOfInputConnections(0); ++i) + { + // Get the input connection, if any. + if(vtkAlgorithmOutput* ic = this->GetInputConnection(0, i)) + { + newInputs[count] = + ic->GetProducer()->GetOutputDataObject(ic->GetIndex()); + } + else + { + newInputs[count] = 0; + } + if(newInputs[count]) + { + // If the data object was already an input, avoid the + // Register/UnRegister cycle. + int found = 0; + for(int j=0; !found && j < this->NumberOfInputs; ++j) + { + if(newInputs[count] == this->Inputs[j]) + { + this->Inputs[j] = 0; + found = 1; + } + } + if(!found) + { + newInputs[count]->Register(this); + } + } + ++count; + } + newNumberOfInputs = count; + } + + // Remove the old array of input data objects. + if(this->NumberOfInputs) + { + for(int i=0; i < this->NumberOfInputs; ++i) + { + if(this->Inputs[i]) + { + this->Inputs[i]->UnRegister(this); + } + } + delete [] this->Inputs; + } + + // Save the new array of input data objects. + this->NumberOfInputs = newNumberOfInputs; + this->Inputs = newInputs; +} + +//---------------------------------------------------------------------------- +void vtkProcessObject::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Required Inputs: " + << this->NumberOfRequiredInputs << endl; + + if ( this->NumberOfInputs) + { + int idx; + for (idx = 0; idx < this->NumberOfInputs; ++idx) + { + os << indent << "Input " << idx << ": (" << this->Inputs[idx] << ")\n"; + } + } + else + { + os << indent <<"No Inputs\n"; + } + +} diff --git a/Filtering/vtkProcessObject.h b/Filtering/vtkProcessObject.h new file mode 100644 index 0000000..5506fd5 --- /dev/null +++ b/Filtering/vtkProcessObject.h @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcessObject.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProcessObject - abstract class specifies interface for visualization filters +// +// .SECTION Description +// vtkProcessObject is an abstract object that specifies behavior and +// interface of visualization network process objects (sources, filters, +// mappers). Source objects are creators of visualization data; filters +// input, process, and output visualization data; and mappers transform data +// into another form (like rendering primitives or write data to a file). +// +// vtkProcessObject fires events for Start and End events before and after +// object execution (via Execute()). These events can be used for any purpose +// (e.g., debugging info, highlighting/notifying user interface, etc.) +// +// Another event, Progress, can be observed. Some filters fire this +// event periodically during their execution. The use is similar to that of +// Start and End events. Filters may also check their AbortExecute +// flag to determine whether to prematurely end their execution. +// +// An important feature of subclasses of vtkProcessObject is that it is +// possible to control the memory-management model (i.e., retain output +// versus delete output data). If enabled the ReleaseDataFlag enables the +// deletion of the output data once the downstream process object finishes +// processing the data (please see text). +// +// .SECTION See Also +// vtkDataObject vtkSource vtkFilter vtkMapper vtkWriter + +#ifndef __vtkProcessObject_h +#define __vtkProcessObject_h + +#include "vtkAlgorithm.h" + +class vtkDataObject; + +class VTK_FILTERING_EXPORT vtkProcessObject : public vtkAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkProcessObject,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return an array with all the inputs of this process object. + // This is useful for tracing back in the pipeline to construct + // graphs etc. + vtkDataObject **GetInputs(); + int GetNumberOfInputs(); + + // Description: + // This method will rearrange the input array so that all NULL entries + // are removed. + void SqueezeInputArray(); + + // Description: + // Remove all the input data. + void RemoveAllInputs(); + + // Description: + // Reimplemented from vtkAlgorithm to maintain backward + // compatibility for vtkProcessObject. + virtual void SetInputConnection(vtkAlgorithmOutput* input) { + this->vtkAlgorithm::SetInputConnection(input); } + virtual void SetInputConnection(int port, vtkAlgorithmOutput* input); + virtual void AddInputConnection(int port, vtkAlgorithmOutput* input); + virtual void AddInputConnection(vtkAlgorithmOutput* input) + { + this->AddInputConnection(0, input); + } + virtual void RemoveInputConnection(int port, vtkAlgorithmOutput* input); + virtual void SetNthInputConnection(int port, int index, + vtkAlgorithmOutput* input); + virtual void SetNumberOfInputConnections(int port, int n); +protected: + vtkProcessObject(); + ~vtkProcessObject(); + + int NumberOfInputs; + int NumberOfRequiredInputs; + vtkDataObject **Inputs; //An array of the inputs to the filter + + // Called to allocate the input array. Copies old inputs. + void SetNumberOfInputs(int num); + + // protected methods for setting inputs. + virtual void SetNthInput(int num, vtkDataObject *input); + virtual void AddInput(vtkDataObject *input); + virtual void RemoveInput(vtkDataObject *input); + + virtual void ReportReferences(vtkGarbageCollector*); + + // Implement methods required by vtkAlgorithm. + virtual int FillInputPortInformation(int, vtkInformation*); + virtual int FillOutputPortInformation(int, vtkInformation*); + + // Helper methods for compatibility layer. + void AddInputInternal(vtkDataObject* input); + void RemoveInputInternal(vtkDataObject* input); + void SetupInputs(); + +private: + vtkProcessObject(const vtkProcessObject&); // Not implemented. + void operator=(const vtkProcessObject&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkPropAssembly.cxx b/Filtering/vtkPropAssembly.cxx new file mode 100644 index 0000000..b0d6c8a --- /dev/null +++ b/Filtering/vtkPropAssembly.cxx @@ -0,0 +1,364 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPropAssembly.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPropAssembly.h" + +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkAssemblyPaths.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkProp.h" +#include "vtkPropCollection.h" +#include "vtkViewport.h" + +vtkCxxRevisionMacro(vtkPropAssembly, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkPropAssembly); + +// Construct object with no children. +vtkPropAssembly::vtkPropAssembly() +{ + this->Parts = vtkPropCollection::New(); + vtkMath::UninitializeBounds(this->Bounds); +} + +vtkPropAssembly::~vtkPropAssembly() +{ + this->Parts->Delete(); + this->Parts = NULL; +} + +// Add a part to the list of Parts. +void vtkPropAssembly::AddPart(vtkProp *prop) +{ + if ( ! this->Parts->IsItemPresent(prop) ) + { + this->Parts->AddItem(prop); + this->Modified(); + } +} + +// Remove a part from the list of parts, +void vtkPropAssembly::RemovePart(vtkProp *prop) +{ + if ( this->Parts->IsItemPresent(prop) ) + { + this->Parts->RemoveItem(prop); + this->Modified(); + } +} + +// Get the list of parts for this prop assembly. +vtkPropCollection *vtkPropAssembly::GetParts() +{ + return this->Parts; +} + +// Render this assembly and all of its Parts. The rendering process is recursive. +int vtkPropAssembly::RenderTranslucentGeometry(vtkViewport *ren) +{ + vtkProp *prop; + vtkAssemblyPath *path; + double fraction; + int renderedSomething=0; + + fraction = this->AllocatedRenderTime / + (double)this->Parts->GetNumberOfItems(); + + // render the Paths + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { + prop->SetAllocatedRenderTime(fraction, ren); + prop->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop->RenderTranslucentGeometry(ren); + prop->PokeMatrix(NULL); + } + } + + return renderedSomething; +} + +// Render this assembly and all its parts. The rendering process is recursive. +int vtkPropAssembly::RenderOpaqueGeometry(vtkViewport *ren) +{ + vtkProp *prop; + vtkAssemblyPath *path; + double fraction; + int renderedSomething=0; + + // Make sure the paths are up-to-date + this->UpdatePaths(); + + fraction = this->AllocatedRenderTime / + (double)this->Parts->GetNumberOfItems(); + + // render the Paths + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { + prop->SetAllocatedRenderTime(fraction, ren); + prop->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop->RenderOpaqueGeometry(ren); + prop->PokeMatrix(NULL); + } + } + + return renderedSomething; +} + +// Render this assembly and all its parts. The rendering process is recursive. +int vtkPropAssembly::RenderOverlay(vtkViewport *ren) +{ + vtkProp *prop; + vtkAssemblyPath *path; + double fraction; + int renderedSomething=0; + + // Make sure the paths are up-to-date + this->UpdatePaths(); + + fraction = this->AllocatedRenderTime / + (double)this->Parts->GetNumberOfItems(); + + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop = path->GetLastNode()->GetViewProp(); + if ( prop->GetVisibility() ) + { + prop->SetAllocatedRenderTime(fraction, ren); + prop->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop->RenderOverlay(ren); + prop->PokeMatrix(NULL); + } + } + + return renderedSomething; +} + + +void vtkPropAssembly::ReleaseGraphicsResources(vtkWindow *renWin) +{ + vtkProp *part; + + vtkProp::ReleaseGraphicsResources(renWin); + + // broadcast the message down the Parts + vtkCollectionSimpleIterator pit; + for ( this->Parts->InitTraversal(pit); + (part=this->Parts->GetNextProp(pit)); ) + { + part->ReleaseGraphicsResources(renWin); + } +} + +// Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkPropAssembly::GetBounds() +{ + vtkProp *part; + int i, n; + double *bounds, bbox[24]; + int partVisible=0; + + // carefully compute the bounds + vtkCollectionSimpleIterator pit; + for ( this->Parts->InitTraversal(pit); + (part=this->Parts->GetNextProp(pit)); ) + { + if ( part->GetVisibility() ) + { + bounds = part->GetBounds(); + + if ( bounds != NULL ) + { + // For the purposes of GetBounds, an object is visisble only if + // its visibility is on and it has visible parts. + if (!partVisible) + { + // initialize the bounds + this->Bounds[0] =this->Bounds[2] =this->Bounds[4] = VTK_DOUBLE_MAX; + this->Bounds[1] =this->Bounds[3] =this->Bounds[5] = -VTK_DOUBLE_MAX; + partVisible = 1; + } + + // fill out vertices of a bounding box + bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5]; + bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5]; + bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5]; + bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5]; + bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4]; + bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4]; + bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4]; + bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4]; + + for (i = 0; i < 8; i++) + { + for (n = 0; n < 3; n++) + { + if (bbox[i*3+n] < this->Bounds[n*2]) + { + this->Bounds[n*2] = bbox[i*3+n]; + } + if (bbox[i*3+n] > this->Bounds[n*2+1]) + { + this->Bounds[n*2+1] = bbox[i*3+n]; + } + } + }//for each point of box + }//if bounds + }//for each part + }//for each part + + if ( ! partVisible ) + { + return NULL; + } + else + { + return this->Bounds; + } +} + +unsigned long int vtkPropAssembly::GetMTime() +{ + unsigned long mTime=this->vtkProp::GetMTime(); + unsigned long time; + vtkProp *part; + + vtkCollectionSimpleIterator pit; + for (this->Parts->InitTraversal(pit); + (part=this->Parts->GetNextProp(pit)); ) + { + time = part->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +// Shallow copy another vtkPropAssembly. +void vtkPropAssembly::ShallowCopy(vtkProp *prop) +{ + vtkPropAssembly *propAssembly = vtkPropAssembly::SafeDownCast(prop); + if ( propAssembly != NULL ) + { + this->Parts->RemoveAllItems(); + vtkCollectionSimpleIterator pit; + propAssembly->Parts->InitTraversal(pit); + for (int i=0; i<0; i++) + { + this->AddPart(propAssembly->Parts->GetNextProp(pit)); + } + } + + this->vtkProp::ShallowCopy(prop); +} + +void vtkPropAssembly::InitPathTraversal() +{ + this->UpdatePaths(); + this->Paths->InitTraversal(); +} + +vtkAssemblyPath *vtkPropAssembly::GetNextPath() +{ + if ( this->Paths ) + { + return this->Paths->GetNextItem(); + } + return NULL; +} + +int vtkPropAssembly::GetNumberOfPaths() +{ + this->UpdatePaths(); + return this->Paths->GetNumberOfItems(); +} + + +// Build the assembly paths if necessary. +void vtkPropAssembly::UpdatePaths() +{ + if ( this->GetMTime() > this->PathTime ) + { + if ( this->Paths != NULL ) + { + this->Paths->Delete(); + this->Paths = NULL; + } + + // Create the list to hold all the paths + this->Paths = vtkAssemblyPaths::New(); + vtkAssemblyPath *path = vtkAssemblyPath::New(); + + //add ourselves to the path to start things off + path->AddNode(this,NULL); + + vtkProp *prop; + // Add nodes as we proceed down the hierarchy + vtkCollectionSimpleIterator pit; + for ( this->Parts->InitTraversal(pit); + (prop = this->Parts->GetNextProp(pit)); ) + { + // add a matrix, if any + path->AddNode(prop,prop->GetMatrix()); + + // dive into the hierarchy + prop->BuildPaths(this->Paths,path); + + // when returned, pop the last node off of the + // current path + path->DeleteLastNode(); + } + + path->Delete(); + this->PathTime.Modified(); + } +} + +void vtkPropAssembly::BuildPaths(vtkAssemblyPaths *paths, + vtkAssemblyPath *path) +{ + vtkProp *prop; + + vtkCollectionSimpleIterator pit; + for ( this->Parts->InitTraversal(pit); + (prop = this->Parts->GetNextProp(pit)); ) + { + path->AddNode(prop,NULL); + + // dive into the hierarchy + prop->BuildPaths(paths,path); + + // when returned, pop the last node off of the + // current path + path->DeleteLastNode(); + } +} + + +void vtkPropAssembly::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "There are: " << this->Parts->GetNumberOfItems() + << " parts in this assembly\n"; +} diff --git a/Filtering/vtkPropAssembly.h b/Filtering/vtkPropAssembly.h new file mode 100644 index 0000000..28e3b2e --- /dev/null +++ b/Filtering/vtkPropAssembly.h @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPropAssembly.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPropAssembly - create hierarchies of props +// .SECTION Description +// vtkPropAssembly is an object that groups props and other prop assemblies +// into a tree-like hierarchy. The props can then be treated as a group +// (e.g., turning visibility on and off). +// +// A vtkPropAssembly object can be used in place of an vtkProp since it is a +// subclass of vtkProp. The difference is that vtkPropAssembly maintains a +// list of other prop and prop assembly instances (its "parts") that form the +// assembly. Note that this process is recursive: you can create groups +// consisting of prop assemblies to arbitrary depth. +// +// vtkPropAssembly's and vtkProp's that compose a prop assembly need not be +// added to a renderer's list of props, as long as the parent assembly is in +// the prop list. This is because they are automatically renderered during +// the hierarchical traversal process. + +// .SECTION Caveats +// vtkPropAssemblies can consist of hierarchies of assemblies, where one +// actor or assembly used in one hierarchy is also used in other +// hierarchies. However, make that there are no cycles (e.g., +// parent->child->parent), this will cause program failure. + +// .SECTION See Also +// vtkProp3D vtkActor vtkAssembly vtkActor2D vtkVolume + +#ifndef __vtkPropAssembly_h +#define __vtkPropAssembly_h + +#include "vtkProp.h" + +class VTK_FILTERING_EXPORT vtkPropAssembly : public vtkProp +{ +public: + vtkTypeRevisionMacro(vtkPropAssembly,vtkProp); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create with an empty parts list. + static vtkPropAssembly *New(); + + // Description: + // Add a part to the list of parts. + void AddPart(vtkProp *); + + // Description: + // Remove a part from the list of parts, + void RemovePart(vtkProp *); + + // Description: + // Return the list of parts. + vtkPropCollection *GetParts(); + + // Description: + // Render this assembly and all its parts. The rendering process is + // recursive. The parts of each assembly are rendered only if the + // visibility for the prop is turned on. + int RenderOpaqueGeometry(vtkViewport *ren); + int RenderTranslucentGeometry(vtkViewport *ren); + int RenderOverlay(vtkViewport *); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Get the bounds for this prop assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). + // May return NULL in some cases (meaning the bounds is undefined). + double *GetBounds(); + + // Description: + // Shallow copy of this vtkPropAssembly. + void ShallowCopy(vtkProp *Prop); + + // Description: + // Override default GetMTime method to also consider all of the + // prop assembly's parts. + unsigned long int GetMTime(); + + // Description: + // Methods to traverse the paths (i.e., leaf nodes) of a prop + // assembly. These methods should be contrasted to those that traverse the + // list of parts using GetParts(). GetParts() returns a list of children + // of this assembly, not necessarily the leaf nodes of the assembly. To use + // the methods below - first invoke InitPathTraversal() followed by + // repeated calls to GetNextPath(). GetNextPath() returns a NULL pointer + // when the list is exhausted. (See the superclass vtkProp for more + // information about paths.) + void InitPathTraversal(); + vtkAssemblyPath *GetNextPath(); + int GetNumberOfPaths(); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Overload the superclass' vtkProp BuildPaths() method. + void BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path); +//ETX + +protected: + vtkPropAssembly(); + ~vtkPropAssembly(); + + vtkPropCollection *Parts; + double Bounds[6]; + + // Support the BuildPaths() method, + vtkTimeStamp PathTime; + void UpdatePaths(); //apply transformations and properties recursively +private: + vtkPropAssembly(const vtkPropAssembly&); // Not implemented. + void operator=(const vtkPropAssembly&); // Not implemented. +}; + +#endif + + + + diff --git a/Filtering/vtkPyramid.cxx b/Filtering/vtkPyramid.cxx new file mode 100644 index 0000000..2d9b413 --- /dev/null +++ b/Filtering/vtkPyramid.cxx @@ -0,0 +1,761 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPyramid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPyramid.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkQuad.h" +#include "vtkTriangle.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkPyramid, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkPyramid); + +static const double VTK_DIVERGED = 1.e6; +//---------------------------------------------------------------------------- +// +// Construct the pyramid with five points. +// +vtkPyramid::vtkPyramid() +{ + this->Points->SetNumberOfPoints(5); + this->PointIds->SetNumberOfIds(5); + for (int i = 0; i < 5; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); + this->Triangle = vtkTriangle::New(); + this->Quad = vtkQuad::New(); +} + +//---------------------------------------------------------------------------- +vtkPyramid::~vtkPyramid() +{ + this->Line->Delete(); + this->Triangle->Delete(); + this->Quad->Delete(); +} + +static const int VTK_MAX_ITERATION=10; +static const double VTK_CONVERGED=1.e-03; +//---------------------------------------------------------------------------- +int vtkPyramid::EvaluatePosition(double x[3], double closestPoint[3], + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[15]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.5; + params[0] = params[1] = params[2] = 0.3333333; + + // enter iteration loop + for (iteration=converged=0; !converged && (iteration < VTK_MAX_ITERATION); + iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<5; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+5]; + tcol[j] += pt[j] * derivs[i+10]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_CONVERGED) ) + { + converged = 1; + } + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside pyramid + } + return 1; + } + else + { + double pc[3], w[5]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkPyramid::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<5; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +// Returns the closest face to the point specified. Closeness is measured +// parametrically. +int vtkPyramid::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + int i; + + // define 6 planes that separate regions + static double normals[6][3] = { + {0.0,-0.5547002,0.8320503}, {0.5547002,0.0,0.8320503}, {0.0,0.5547002,0.8320503}, + {-0.5547002,0.0,0.8320503}, {0.70710670,-0.70710670,0.0}, {0.70710670,0.70710670,0.0} }; + static double point[3] = {0.5,0.5,0.3333333}; + double vals[6]; + + // evaluate 6 plane equations + for (i=0; i<6; i++) + { + vals[i] = normals[i][0]*(pcoords[0]-point[0]) + + normals[i][1]*(pcoords[1]-point[1]) + normals[i][2]*(pcoords[2]-point[2]); + } + + // compare against six planes in parametric space that divide element + // into five pieces (each corresponding to a face). + if ( vals[4] >= 0.0 && vals[5] <= 0.0 && vals[0] >= 0.0 ) + { + pts->SetNumberOfIds(3); //triangle face + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(4)); + } + + else if ( vals[4] >= 0.0 && vals[5] >= 0.0 && vals[1] >= 0.0 ) + { + pts->SetNumberOfIds(3); //triangle face + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(2)); + pts->SetId(2,this->PointIds->GetId(4)); + } + + else if ( vals[4] <= 0.0 && vals[5] >= 0.0 && vals[2] >= 0.0 ) + { + pts->SetNumberOfIds(3); //triangle face + pts->SetId(0,this->PointIds->GetId(2)); + pts->SetId(1,this->PointIds->GetId(3)); + pts->SetId(2,this->PointIds->GetId(4)); + } + + else if ( vals[4] <= 0.0 && vals[5] <= 0.0 && vals[3] >= 0.0 ) + { + pts->SetNumberOfIds(3); //triangle face + pts->SetId(0,this->PointIds->GetId(3)); + pts->SetId(1,this->PointIds->GetId(0)); + pts->SetId(2,this->PointIds->GetId(4)); + } + + else + { + pts->SetNumberOfIds(4); //quad face + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(2)); + pts->SetId(3,this->PointIds->GetId(3)); + } + + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 || + pcoords[2] < 0.0 || pcoords[2] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +// Marching pyramids (contouring) +// +static int edges[8][2] = { {0,1}, {1,2}, {2,3}, + {3,0}, {0,4}, {1,4}, + {2,4}, {3,4} }; +static int faces[5][4] = { {0,3,2,1}, {0,1,4,-1}, + {1,2,4,-1}, {2,3,4,-1}, {3,0,4,-1} }; + +typedef int EDGE_LIST; +typedef struct { + EDGE_LIST edges[13]; +} TRIANGLE_CASES; + +static TRIANGLE_CASES triCases[] = { + {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //0 + {{ 3, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //1 + {{ 5, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //2 + {{ 5, 1, 4, 1, 3, 4, -1, -1, -1, -1, -1, -1, -1}}, //3 + {{ 6, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //4 + {{ 3, 4, 0, 6, 2, 1, -1, -1, -1, -1, -1, -1, -1}}, //5 + {{ 5, 2, 0, 6, 2, 5, -1, -1, -1, -1, -1, -1, -1}}, //6 + {{ 2, 3, 4, 2, 4, 6, 4, 5, 6, -1, -1, -1, -1}}, //7 + {{ 2, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //8 + {{ 2, 7, 4, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}}, //9 + {{ 5, 1, 0, 2, 7, 3, -1, -1, -1, -1, -1, -1, -1}}, //10 + {{ 5, 7, 4, 1, 7, 5, 2, 7, 1, -1, -1, -1, -1}}, //11 + {{ 6, 3, 1, 7, 3, 6, -1, -1, -1, -1, -1, -1, -1}}, //12 + {{ 4, 6, 7, 0, 6, 4, 1, 6, 0, -1, -1, -1, -1}}, //13 + {{ 7, 5, 6, 3, 5, 7, 0, 5, 3, -1, -1, -1, -1}}, //14 + {{ 7, 4, 5, 7, 5, 6, -1, -1, -1, -1, -1, -1, -1}}, //15 + {{ 5, 7, 4, 6, 7, 5, -1, -1, -1, -1, -1, -1, -1}}, //16 + {{ 0, 5, 3, 5, 6, 3, 6, 7, 3, -1, -1, -1, -1}}, //17 + {{ 0, 1, 4, 1, 7, 4, 1, 6, 7, -1, -1, -1, -1}}, //18 + {{ 1, 6, 3, 6, 7, 3, -1, -1, -1, -1, -1, -1, -1}}, //19 + {{ 7, 5, 4, 7, 1, 5, 7, 2, 1, -1, -1, -1, -1}}, //20 + {{ 3, 7, 0, 7, 5, 0, 7, 2, 5, 2, 1, 5, -1}}, //21 + {{ 4, 2, 0, 7, 2, 4, -1, -1, -1, -1, -1, -1, -1}}, //22 + {{ 7, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //23 + {{ 2, 4, 3, 5, 4, 2, 6, 5, 2, -1, -1, -1, -1}}, //24 + {{ 2, 5, 0, 2, 6, 5, -1, -1, -1, -1, -1, -1, -1}}, //25 + {{ 6, 1, 0, 4, 6, 0, 3, 6, 4, 3, 2, 6, -1}}, //26 + {{ 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //27 + {{ 1, 4, 3, 1, 5, 4, -1, -1, -1, -1, -1, -1, -1}}, //28 + {{ 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //29 + {{ 4, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //30 + {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}} //31 +}; + +//---------------------------------------------------------------------------- +void vtkPyramid::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + static int CASE_MASK[5] = {1,2,4,8,16}; + TRIANGLE_CASES *triCase; + EDGE_LIST *edge; + int i, j, index, *vert, v1, v2, newCellId; + vtkIdType pts[3]; + double t, x1[3], x2[3], x[3], deltaScalar; + vtkIdType offset = verts->GetNumberOfCells() + lines->GetNumberOfCells(); + + // Build the case table + for ( i=0, index = 0; i < 5; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + triCase = triCases + index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (i=0; i<3; i++) // insert triangle + { + vert = edges[edge[i]]; + + // calculate a preferred interpolation direction + deltaScalar = (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + v1 = vert[0]; v2 = vert[1]; + } + else + { + v1 = vert[1]; v2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + (value - cellScalars->GetComponent(v1,0)) / deltaScalar ); + + this->Points->GetPoint(v1, x1); + this->Points->GetPoint(v2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + vtkIdType p1 = this->PointIds->GetId(v1); + vtkIdType p2 = this->PointIds->GetId(v2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + + // check for degenerate triangle + if ( pts[0] != pts[1] && pts[0] != pts[2] && pts[1] != pts[2] ) + { + newCellId = offset + polys->InsertNextCell(3,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +int *vtkPyramid::GetEdgeArray(int edgeId) +{ + return edges[edgeId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkPyramid::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} + +//---------------------------------------------------------------------------- +int *vtkPyramid::GetFaceArray(int faceId) +{ + return faces[faceId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkPyramid::GetFace(int faceId) +{ + int *verts; + + verts = faces[faceId]; + + if ( verts[3] != -1 ) // quad cell + { + // load point id's + this->Quad->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Quad->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Quad->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + this->Quad->PointIds->SetId(3,this->PointIds->GetId(verts[3])); + + // load coordinates + this->Quad->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Quad->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Quad->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + this->Quad->Points->SetPoint(3,this->Points->GetPoint(verts[3])); + + return this->Quad; + } + else + { + // load point id's + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + + // load coordinates + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + + return this->Triangle; + } +} + +//---------------------------------------------------------------------------- +// Intersect faces against line. +// +int vtkPyramid::IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId) +{ + int intersection=0; + double pt1[3], pt2[3], pt3[3], pt4[3]; + double tTemp; + double pc[3], xTemp[3], dist2, weights[5]; + + int faceNum; + + t = VTK_DOUBLE_MAX; + + //first intersect the triangle faces + for (faceNum=1; faceNum<5; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + + this->Triangle->Points->SetPoint(0,pt1); + this->Triangle->Points->SetPoint(1,pt2); + this->Triangle->Points->SetPoint(2,pt3); + + if ( this->Triangle->IntersectWithLine(p1, p2, tol, tTemp, xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + this->EvaluatePosition(x, xTemp, subId, pcoords, dist2, weights); + } + } + } + + //now intersect the quad face + this->Points->GetPoint(faces[0][0], pt1); + this->Points->GetPoint(faces[0][1], pt2); + this->Points->GetPoint(faces[0][2], pt3); + this->Points->GetPoint(faces[0][3], pt4); + + this->Quad->Points->SetPoint(0,pt1); + this->Quad->Points->SetPoint(1,pt2); + this->Quad->Points->SetPoint(2,pt3); + this->Quad->Points->SetPoint(3,pt4); + + if ( this->Quad->IntersectWithLine(p1, p2, tol, tTemp, xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 0.0; + } + } + + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkPyramid::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, vtkPoints *pts) +{ + int p[4], i; + ptIds->Reset(); + pts->Reset(); + + // The base of the pyramid must be split into two triangles. There are two + // ways to do this (across either diagonal). Pick the shorter diagonal. + double base_points[4][3]; + for (i = 0; i < 4; i++) + { + this->Points->GetPoint(i, base_points[i]); + } + double diagonal1, diagonal2; + diagonal1 = vtkMath::Distance2BetweenPoints(base_points[0], base_points[2]); + diagonal2 = vtkMath::Distance2BetweenPoints(base_points[1], base_points[3]); + + if (diagonal1 < diagonal2) + { + for (i=0; i < 4; i++) + { + p[0] = 0; p[1] = 1; p[2] = 2; p[3] = 4; + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + for (i=0; i < 4; i++) + { + p[0] = 0; p[1] = 2; p[2] = 3; p[3] = 4; + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + } + else + { + for (i=0; i < 4; i++) + { + p[0] = 0; p[1] = 1; p[2] = 3; p[3] = 4; + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + for (i=0; i < 4; i++) + { + p[0] = 1; p[1] = 2; p[2] = 3; p[3] = 4; + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + } + + return !(diagonal1 == diagonal2); +} + +//---------------------------------------------------------------------------- +void vtkPyramid::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[15], sum[3], value; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 5; i++) //loop over interp. function derivatives + { + value = values[dim*i + k]; + sum[0] += functionDerivs[i] * value; + sum[1] += functionDerivs[5 + i] * value; + sum[2] += functionDerivs[10 + i] * value; + } + + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[0][j] + sum[1]*jI[1][j] + sum[2]*jI[2][j]; + } + } +} + +//---------------------------------------------------------------------------- +// Compute iso-parametric interpolation functions for pyramid +// +void vtkPyramid::InterpolationFunctions(double pcoords[3], double sf[5]) +{ + double rm, sm, tm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + tm = 1. - pcoords[2]; + + sf[0] = rm*sm*tm; + sf[1] = pcoords[0]*sm*tm; + sf[2] = pcoords[0]*pcoords[1]*tm; + sf[3] = rm*pcoords[1]*tm; + sf[4] = pcoords[2]; +} + +//---------------------------------------------------------------------------- +void vtkPyramid::InterpolationDerivs(double pcoords[3], double derivs[15]) +{ + double rm, sm, tm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + tm = 1. - pcoords[2]; + + // r-derivatives + derivs[0] = -sm*tm; + derivs[1] = sm*tm; + derivs[2] = pcoords[1]*tm; + derivs[3] = -pcoords[1]*tm; + derivs[4] = 0.0; + + // s-derivatives + derivs[5] = -rm*tm; + derivs[6] = -pcoords[0]*tm; + derivs[7] = pcoords[0]*tm; + derivs[8] = rm*tm; + derivs[9] = 0.0; + + // t-derivatives + derivs[10] = -rm*sm; + derivs[11] = -pcoords[0]*sm; + derivs[12] = -pcoords[0]*pcoords[1]; + derivs[13] = -rm*pcoords[1]; + derivs[14] = 1.0; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. Returns 0 if no inverse exists. +// Note for pyramid: the inverse Jacobian is undefined at the apex. +int vtkPyramid::JacobianInverse(double pcoords[3], double **inverse, double derivs[15]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords,derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 5; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[5 + j]; + m2[i] += x[i] * derivs[10 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { +#define VTK_MAX_WARNS 3 + static int numWarns=0; + if ( numWarns++ < VTK_MAX_WARNS ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + vtkErrorMacro(<<"Matrix:" << m[0][0] << " " << m[0][1] << " " << m[0][2] + << m[1][0] << " " << m[1][1] << " " << m[1][2] + << m[2][0] << " " << m[2][1] << " " << m[2][2] ); + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPyramid::GetEdgePoints(int edgeId, int* &pts) +{ + pts = this->GetEdgeArray(edgeId); +} + +//---------------------------------------------------------------------------- +void vtkPyramid::GetFacePoints(int faceId, int* &pts) +{ + pts = this->GetFaceArray(faceId); +} + +static double vtkPyramidCellPCoords[15] = {0.0,0.0,0.0, 1.0,0.0,0.0, + 1.0,1.0,0.0, 0.0,1.0,0.0, + 0.0,0.0,1.0}; + +//---------------------------------------------------------------------------- +double *vtkPyramid::GetParametricCoords() +{ + return vtkPyramidCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkPyramid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Triangle:\n"; + this->Triangle->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Quad:\n"; + this->Quad->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkPyramid.h b/Filtering/vtkPyramid.h new file mode 100644 index 0000000..797ac5e --- /dev/null +++ b/Filtering/vtkPyramid.h @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPyramid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPyramid - a 3D cell that represents a linear pyramid +// .SECTION Description +// vtkPyramid is a concrete implementation of vtkCell to represent a 3D +// pyramid. A pyramid consists of a rectangular base with four triangular +// faces. vtkPyramid uses the standard isoparametric shape functions for +// a linear pyramid. The pyramid is defined by the five points (0-4) where +// (0,1,2,3) is the base of the pyramid which, using the right hand rule, +// forms a quadrilaterial whose normal points in the direction of the +// pyramid apex at vertex #4. + +// .SECTION See Also +// vtkConvexPointSet vtkHexahedron vtkTetra vtkVoxel vtkWedge + +#ifndef __vtkPyramid_h +#define __vtkPyramid_h + +#include "vtkCell3D.h" + +class vtkLine; +class vtkQuad; +class vtkTriangle; +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkPyramid : public vtkCell3D +{ +public: + static vtkPyramid *New(); + vtkTypeRevisionMacro(vtkPyramid,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int edgeId, int* &pts); + virtual void GetFacePoints(int faceId, int* &pts); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_PYRAMID;} + int GetCellDimension() {return 3;} + int GetNumberOfEdges() {return 8;} + int GetNumberOfFaces() {return 5;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Return the center of the pyramid in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Pyramid specific methods for computing interpolation functions and + // derivatives. + static void InterpolationFunctions(double pcoords[3], double weights[5]); + static void InterpolationDerivs(double pcoords[3], double derivs[15]); + int JacobianInverse(double pcoords[3], double **inverse, double derivs[15]); + static int *GetEdgeArray(int edgeId); + static int *GetFaceArray(int faceId); + +protected: + vtkPyramid(); + ~vtkPyramid(); + + vtkLine *Line; + vtkTriangle *Triangle; + vtkQuad *Quad; + +private: + vtkPyramid(const vtkPyramid&); // Not implemented. + void operator=(const vtkPyramid&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkPyramid::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.4; + pcoords[2] = 0.2; + return 0; +} + +#endif + + + diff --git a/Filtering/vtkQuad.cxx b/Filtering/vtkQuad.cxx new file mode 100644 index 0000000..7e7b9e6 --- /dev/null +++ b/Filtering/vtkQuad.cxx @@ -0,0 +1,944 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuad.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuad.h" + +#include "vtkObjectFactory.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkLine.h" +#include "vtkTriangle.h" +#include "vtkMath.h" +#include "vtkPlane.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkQuad, "$Revision: 1.3.12.1 $"); +vtkStandardNewMacro(vtkQuad); + +static const double VTK_DIVERGED = 1.e6; + +//---------------------------------------------------------------------------- +// Construct the quad with four points. +vtkQuad::vtkQuad() +{ + this->Points->SetNumberOfPoints(4); + this->PointIds->SetNumberOfIds(4); + for (int i = 0; i < 4; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); + this->Triangle = vtkTriangle::New(); +} + +//---------------------------------------------------------------------------- +vtkQuad::~vtkQuad() +{ + this->Line->Delete(); + this->Triangle->Delete(); +} + +//---------------------------------------------------------------------------- +static const int VTK_QUAD_MAX_ITERATION=20; +static const double VTK_QUAD_CONVERGED=1.e-04; + +inline static void ComputeNormal(vtkQuad *self, double pt1[3], double pt2[3], + double pt3[3], double n[3]) +{ + vtkTriangle::ComputeNormal (pt1, pt2, pt3, n); + + // If first three points are co-linear, then use fourth point + // + double pt4[3]; + if ( n[0] == 0.0 && n[1] == 0.0 && n[2] == 0.0 ) + { + self->Points->GetPoint(3,pt4); + vtkTriangle::ComputeNormal (pt2, pt3, pt4, n); + } +} + +//---------------------------------------------------------------------------- +int vtkQuad::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int i, j; + double pt1[3], pt2[3], pt3[3], pt[3], n[3]; + double det; + double maxComponent; + int idx=0, indices[2]; + int iteration, converged; + double params[2]; + double fcol[2], rcol[2], scol[2], cp[3]; + double derivs[8]; + + subId = 0; + pcoords[0] = pcoords[1] = params[0] = params[1] = 0.5; + + // Get normal for quadrilateral + // + this->Points->GetPoint(0, pt1); + this->Points->GetPoint(1, pt2); + this->Points->GetPoint(2, pt3); + ComputeNormal (this, pt1, pt2, pt3, n); + + // Project point to plane + // + vtkPlane::ProjectPoint(x,pt1,n,cp); + + // Construct matrices. Since we have over determined system, need to find + // which 2 out of 3 equations to use to develop equations. (Any 2 should + // work since we've projected point to plane.) + // + for (maxComponent=0.0, i=0; i<3; i++) + { + if (fabs(n[i]) > maxComponent) + { + maxComponent = fabs(n[i]); + idx = i; + } + } + for (j=0, i=0; i<3; i++) + { + if ( i != idx ) + { + indices[j++] = i; + } + } + + // Use Newton's method to solve for parametric coordinates + // + for (iteration=converged=0; !converged + && (iteration < VTK_QUAD_MAX_ITERATION); + iteration++) + { + // calculate element interpolation functions and derivatives + // + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + // + for (i=0; i<2; i++) + { + fcol[i] = rcol[i] = scol[i] = 0.0; + } + for (i=0; i<4; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<2; j++) + { + fcol[j] += pt[indices[j]] * weights[i]; + rcol[j] += pt[indices[j]] * derivs[i]; + scol[j] += pt[indices[j]] * derivs[i+4]; + } + } + + for (j=0; j<2; j++) + { + fcol[j] -= cp[indices[j]]; + } + + // compute determinants and generate improvements + // + if ( (det=vtkMath::Determinant2x2(rcol,scol)) == 0.0 ) + { + return -1; + } + + pcoords[0] = params[0] - vtkMath::Determinant2x2 (fcol,scol) / det; + pcoords[1] = params[1] - vtkMath::Determinant2x2 (rcol,fcol) / det; + + // check for convergence + // + if ( ((fabs(pcoords[0]-params[0])) < VTK_QUAD_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_QUAD_CONVERGED) ) + { + converged = 1; + } + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + // + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + // + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 ) + { + if (closestPoint) + { + dist2 = + vtkMath::Distance2BetweenPoints(cp,x); //projection distance + closestPoint[0] = cp[0]; + closestPoint[1] = cp[1]; + closestPoint[2] = cp[2]; + } + return 1; + } + else + { + double t; + double pt4[3]; + + if (closestPoint) + { + this->Points->GetPoint(3, pt4); + + if ( pcoords[0] < 0.0 && pcoords[1] < 0.0 ) + { + dist2 = vtkMath::Distance2BetweenPoints(x,pt1); + for (i=0; i<3; i++) + { + closestPoint[i] = pt1[i]; + } + } + else if ( pcoords[0] > 1.0 && pcoords[1] < 0.0 ) + { + dist2 = vtkMath::Distance2BetweenPoints(x,pt2); + for (i=0; i<3; i++) + { + closestPoint[i] = pt2[i]; + } + } + else if ( pcoords[0] > 1.0 && pcoords[1] > 1.0 ) + { + dist2 = vtkMath::Distance2BetweenPoints(x,pt3); + for (i=0; i<3; i++) + { + closestPoint[i] = pt3[i]; + } + } + else if ( pcoords[0] < 0.0 && pcoords[1] > 1.0 ) + { + dist2 = vtkMath::Distance2BetweenPoints(x,pt4); + for (i=0; i<3; i++) + { + closestPoint[i] = pt4[i]; + } + } + else if ( pcoords[0] < 0.0 ) + { + dist2 = vtkLine::DistanceToLine(x,pt1,pt4,t,closestPoint); + } + else if ( pcoords[0] > 1.0 ) + { + dist2 = vtkLine::DistanceToLine(x,pt2,pt3,t,closestPoint); + } + else if ( pcoords[1] < 0.0 ) + { + dist2 = vtkLine::DistanceToLine(x,pt1,pt2,t,closestPoint); + } + else if ( pcoords[1] > 1.0 ) + { + dist2 = vtkLine::DistanceToLine(x,pt3,pt4,t,closestPoint); + } + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkQuad::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<4; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +// Compute iso-parametric interpolation functions +// +void vtkQuad::InterpolationFunctions(double pcoords[3], double sf[4]) +{ + double rm, sm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + + sf[0] = rm * sm; + sf[1] = pcoords[0] * sm; + sf[2] = pcoords[0] * pcoords[1]; + sf[3] = rm * pcoords[1]; +} + +//---------------------------------------------------------------------------- +void vtkQuad::InterpolationDerivs(double pcoords[3], double derivs[8]) +{ + double rm, sm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + + derivs[0] = -sm; + derivs[1] = sm; + derivs[2] = pcoords[1]; + derivs[3] = -pcoords[1]; + derivs[4] = -rm; + derivs[5] = -pcoords[0]; + derivs[6] = pcoords[0]; + derivs[7] = rm; +} + +//---------------------------------------------------------------------------- +int vtkQuad::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + double t1=pcoords[0]-pcoords[1]; + double t2=1.0-pcoords[0]-pcoords[1]; + + pts->SetNumberOfIds(2); + + // compare against two lines in parametric space that divide element + // into four pieces. + if ( t1 >= 0.0 && t2 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + } + + else if ( t1 >= 0.0 && t2 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(2)); + } + + else if ( t1 < 0.0 && t2 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(2)); + pts->SetId(1,this->PointIds->GetId(3)); + } + + else //( t1 < 0.0 && t2 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(3)); + pts->SetId(1,this->PointIds->GetId(0)); + } + + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +// Marching (convex) quadrilaterals +// +static int edges[4][2] = { {0,1}, {1,2}, {3,2}, {0,3} }; + +typedef int EDGE_LIST; +typedef struct { + EDGE_LIST edges[5]; +} LINE_CASES; + +static LINE_CASES lineCases[] = { + {{-1, -1, -1, -1, -1}}, + {{0, 3, -1, -1, -1}}, + {{1, 0, -1, -1, -1}}, + {{1, 3, -1, -1, -1}}, + {{2, 1, -1, -1, -1}}, + {{0, 3, 2, 1, -1}}, + {{2, 0, -1, -1, -1}}, + {{2, 3, -1, -1, -1}}, + {{3, 2, -1, -1, -1}}, + {{0, 2, -1, -1, -1}}, + {{1, 0, 3, 2, -1}}, + {{1, 2, -1, -1, -1}}, + {{3, 1, -1, -1, -1}}, + {{0, 1, -1, -1, -1}}, + {{3, 0, -1, -1, -1}}, + {{-1, -1, -1, -1, -1}} +}; + +//---------------------------------------------------------------------------- +void vtkQuad::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *vtkNotUsed(polys), + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + static int CASE_MASK[4] = {1,2,4,8}; + LINE_CASES *lineCase; + EDGE_LIST *edge; + int i, j, index, *vert; + int newCellId; + vtkIdType pts[2]; + int e1, e2; + double t, x1[3], x2[3], x[3], deltaScalar; + vtkIdType offset = verts->GetNumberOfCells(); + + // Build the case table + for ( i=0, index = 0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + lineCase = lineCases + index; + edge = lineCase->edges; + + for ( ; edge[0] > -1; edge += 2 ) + { + for (i=0; i<2; i++) // insert line + { + vert = edges[edge[i]]; + // calculate a preferred interpolation direction + deltaScalar = (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + e1 = vert[0]; e2 = vert[1]; + } + else + { + e1 = vert[1]; e2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + if (deltaScalar == 0.0) + { + t = 0.0; + } + else + { + t = (value - cellScalars->GetComponent(e1,0)) / deltaScalar; + } + + this->Points->GetPoint(e1, x1); + this->Points->GetPoint(e2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + vtkIdType p1 = this->PointIds->GetId(e1); + vtkIdType p2 = this->PointIds->GetId(e2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate line + if ( pts[0] != pts[1] ) + { + newCellId = offset + lines->InsertNextCell(2,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +vtkCell *vtkQuad::GetEdge(int edgeId) +{ + int edgeIdPlus1 = edgeId + 1; + + if (edgeIdPlus1 > 3) + { + edgeIdPlus1 = 0; + } + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(edgeId)); + this->Line->PointIds->SetId(1,this->PointIds->GetId(edgeIdPlus1)); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(edgeId)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(edgeIdPlus1)); + + return this->Line; +} + + +//---------------------------------------------------------------------------- +// Intersect plane; see whether point is in quadrilateral. This code +// splits the quad into two triangles and intersects them (because the +// quad may be non-planar). +// +int vtkQuad::IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId) +{ + int diagonalCase; + double d1 = vtkMath::Distance2BetweenPoints(this->Points->GetPoint(0), + this->Points->GetPoint(2)); + double d2 = vtkMath::Distance2BetweenPoints(this->Points->GetPoint(1), + this->Points->GetPoint(3)); + subId = 0; + + // Figure out how to uniquely tessellate the quad. Watch out for + // equivalent triangulations (i.e., the triangulation is equivalent + // no matter where the diagonal). In this case use the point ids as + // a tie breaker to insure unique triangulation across the quad. + // + if ( d1 == d2 ) //rare case; discriminate based on point id + { + int i, id, maxId=0, maxIdx=0; + for (i=0; i<4; i++) //find the maximum id + { + if ( (id=this->PointIds->GetId(i)) > maxId ) + { + maxId = id; + maxIdx = i; + } + } + if ( maxIdx == 0 || maxIdx == 2) diagonalCase = 0; + else diagonalCase = 1; + } + else if ( d1 < d2 ) + { + diagonalCase = 0; + } + else //d2 < d1 + { + diagonalCase = 1; + } + + // Note: in the following code the parametric coords must be adjusted to + // reflect the use of the triangle parametric coordinate system. + switch (diagonalCase) + { + case 0: + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(0)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(1)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(2)); + if (this->Triangle->IntersectWithLine(p1, p2, tol, t, x, pcoords, subId) ) + { + pcoords[0] = pcoords[0] + pcoords[1]; + return 1; + } + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(2)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(3)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(0)); + if (this->Triangle->IntersectWithLine(p1, p2, tol, t, x, pcoords, subId) ) + { + pcoords[0] = 1.0 - (pcoords[0]+pcoords[1]); + pcoords[1] = 1.0 - pcoords[1]; + return 1; + } + return 0; + + case 1: + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(0)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(1)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(3)); + if (this->Triangle->IntersectWithLine(p1, p2, tol, t, x, pcoords, subId) ) + { + return 1; + } + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(2)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(3)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(1)); + if (this->Triangle->IntersectWithLine(p1, p2, tol, t, x, pcoords, subId) ) + { + pcoords[0] = 1.0 - pcoords[0]; + pcoords[1] = 1.0 - pcoords[1]; + return 1; + } + + return 0; + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkQuad::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + double d1, d2; + + pts->Reset(); + ptIds->Reset(); + + // use minimum diagonal (Delaunay triangles) - assumed convex + d1 = vtkMath::Distance2BetweenPoints(this->Points->GetPoint(0), + this->Points->GetPoint(2)); + d2 = vtkMath::Distance2BetweenPoints(this->Points->GetPoint(1), + this->Points->GetPoint(3)); + + if ( d1 <= d2 ) + { + ptIds->InsertId(0,this->PointIds->GetId(0)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + ptIds->InsertId(1,this->PointIds->GetId(1)); + pts->InsertPoint(1,this->Points->GetPoint(1)); + ptIds->InsertId(2,this->PointIds->GetId(2)); + pts->InsertPoint(2,this->Points->GetPoint(2)); + + ptIds->InsertId(3,this->PointIds->GetId(0)); + pts->InsertPoint(3,this->Points->GetPoint(0)); + ptIds->InsertId(4,this->PointIds->GetId(2)); + pts->InsertPoint(4,this->Points->GetPoint(2)); + ptIds->InsertId(5,this->PointIds->GetId(3)); + pts->InsertPoint(5,this->Points->GetPoint(3)); + } + else + { + ptIds->InsertId(0,this->PointIds->GetId(0)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + ptIds->InsertId(1,this->PointIds->GetId(1)); + pts->InsertPoint(1,this->Points->GetPoint(1)); + ptIds->InsertId(2,this->PointIds->GetId(3)); + pts->InsertPoint(2,this->Points->GetPoint(3)); + + ptIds->InsertId(3,this->PointIds->GetId(1)); + pts->InsertPoint(3,this->Points->GetPoint(1)); + ptIds->InsertId(4,this->PointIds->GetId(2)); + pts->InsertPoint(4,this->Points->GetPoint(2)); + ptIds->InsertId(5,this->PointIds->GetId(3)); + pts->InsertPoint(5,this->Points->GetPoint(3)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkQuad::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + double v0[2], v1[2], v2[2], v3[2], v10[3], v20[3], lenX; + double x0[3], x1[3], x2[3], x3[3], n[3], vec20[3], vec30[3]; + double *J[2], J0[2], J1[2]; + double *JI[2], JI0[2], JI1[2]; + double funcDerivs[8], sum[2], dBydx, dBydy; + int i, j; + + // Project points of quad into 2D system + this->Points->GetPoint(0, x0); + this->Points->GetPoint(1, x1); + this->Points->GetPoint(2, x2); + ComputeNormal (this,x0, x1, x2, n); + this->Points->GetPoint(3, x3); + + for (i=0; i < 3; i++) + { + v10[i] = x1[i] - x0[i]; + vec20[i] = x2[i] - x0[i]; + vec30[i] = x3[i] - x0[i]; + } + + vtkMath::Cross(n,v10,v20); //creates local y' axis + + if ( (lenX=vtkMath::Normalize(v10)) <= 0.0 + || vtkMath::Normalize(v20) <= 0.0 ) //degenerate + { + for ( j=0; j < dim; j++ ) + { + for ( i=0; i < 3; i++ ) + { + derivs[j*dim + i] = 0.0; + } + } + return; + } + + v0[0] = v0[1] = 0.0; //convert points to 2D (i.e., local system) + v1[0] = lenX; v1[1] = 0.0; + v2[0] = vtkMath::Dot(vec20,v10); + v2[1] = vtkMath::Dot(vec20,v20); + v3[0] = vtkMath::Dot(vec30,v10); + v3[1] = vtkMath::Dot(vec30,v20); + + this->InterpolationDerivs(pcoords, funcDerivs); + + // Compute Jacobian and inverse Jacobian + J[0] = J0; J[1] = J1; + JI[0] = JI0; JI[1] = JI1; + + J[0][0] = v0[0]*funcDerivs[0] + v1[0]*funcDerivs[1] + + v2[0]*funcDerivs[2] + v3[0]*funcDerivs[3]; + J[0][1] = v0[1]*funcDerivs[0] + v1[1]*funcDerivs[1] + + v2[1]*funcDerivs[2] + v3[1]*funcDerivs[3]; + J[1][0] = v0[0]*funcDerivs[4] + v1[0]*funcDerivs[5] + + v2[0]*funcDerivs[6] + v3[0]*funcDerivs[7]; + J[1][1] = v0[1]*funcDerivs[4] + v1[1]*funcDerivs[5] + + v2[1]*funcDerivs[6] + v3[1]*funcDerivs[7]; + + // Compute inverse Jacobian, return if Jacobian is singular + if (!vtkMath::InvertMatrix(J,JI,2)) + { + for ( j=0; j < dim; j++ ) + { + for ( i=0; i < 3; i++ ) + { + derivs[j*dim + i] = 0.0; + } + } + return; + } + + // Loop over "dim" derivative values. For each set of values, + // compute derivatives + // in local system and then transform into modelling system. + // First compute derivatives in local x'-y' coordinate system + for ( j=0; j < dim; j++ ) + { + sum[0] = sum[1] = 0.0; + for ( i=0; i < 4; i++) //loop over interp. function derivatives + { + sum[0] += funcDerivs[i] * values[dim*i + j]; + sum[1] += funcDerivs[4 + i] * values[dim*i + j]; + } + dBydx = sum[0]*JI[0][0] + sum[1]*JI[0][1]; + dBydy = sum[0]*JI[1][0] + sum[1]*JI[1][1]; + + // Transform into global system (dot product with global axes) + derivs[3*j] = dBydx * v10[0] + dBydy * v20[0]; + derivs[3*j + 1] = dBydx * v10[1] + dBydy * v20[1]; + derivs[3*j + 2] = dBydx * v10[2] + dBydy * v20[2]; + } +} + +//---------------------------------------------------------------------------- +// support quad clipping +typedef int QUAD_EDGE_LIST; +typedef struct { + QUAD_EDGE_LIST edges[14]; +} QUAD_CASES; + +static QUAD_CASES quadCases[] = { +{{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 0 +{{ 3, 100, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 1 +{{ 3, 101, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 2 +{{ 4, 100, 101, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 3 +{{ 3, 102, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 4 +{{ 3, 100, 0, 3, 3, 102, 2, 1, 4, 0, 1, 2, 3, -1}}, // 5 +{{ 4, 101, 102, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 6 +{{ 3, 100, 101, 3, 3, 101, 2, 3, 3, 101, 102, 2, -1, -1}}, // 7 +{{ 3, 103, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 8 +{{ 4, 100, 0, 2, 103, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 9 +{{ 3, 101, 1, 0, 3, 103, 3, 2, 4, 0, 1, 2, 3, -1}}, // 10 +{{ 3, 100, 101, 1, 3, 100, 1, 2, 3, 100, 2, 103, -1, -1}}, // 11 +{{ 4, 102, 103, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 12 +{{ 3, 100, 0, 103, 3, 0, 1, 103, 3, 1, 102, 103, -1, -1}}, // 13 +{{ 3, 0, 101, 102, 3, 0, 102, 3, 3, 102, 103, 3, -1, -1}}, // 14 +{{ 4, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 15 +}; + +static QUAD_CASES quadCasesComplement[] = { +{{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 0 +{{ 3, 100, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 1 +{{ 3, 101, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 2 +{{ 4, 100, 101, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 3 +{{ 3, 102, 2, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 4 +{{ 3, 100, 0, 3, 3, 102, 2, 1, -1, -1, -1, -1, -1, -1}}, // 5 +{{ 4, 101, 102, 2, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 6 +{{ 3, 100, 101, 3, 3, 101, 2, 3, 3, 101, 102, 2, -1, -1}}, // 7 +{{ 3, 103, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 8 +{{ 4, 100, 0, 2, 103, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 9 +{{ 3, 101, 1, 0, 3, 103, 3, 2, -1, -1, -1, -1, -1, -1}}, // 10 +{{ 3, 100, 101, 1, 3, 100, 1, 2, 3, 100, 2, 103, -1, -1}}, // 11 +{{ 4, 102, 103, 3, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 12 +{{ 3, 100, 0, 103, 3, 0, 1, 103, 3, 1, 102, 103, -1, -1}}, // 13 +{{ 3, 0, 101, 102, 3, 0, 102, 3, 3, 102, 103, 3, -1, -1}}, // 14 +{{ 4, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, // 15 +}; + +//---------------------------------------------------------------------------- +// Clip this quad using scalar value provided. Like contouring, except +// that it cuts the quad to produce other quads and/or triangles. +void vtkQuad::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut) +{ + static int CASE_MASK[4] = {1,2,4,8}; + QUAD_CASES *quadCase; + QUAD_EDGE_LIST *edge; + int i, j, index, *vert; + int e1, e2; + int newCellId; + vtkIdType pts[4]; + int vertexId; + double t, x1[3], x2[3], x[3], deltaScalar; + double scalar0, scalar1, e1Scalar; + + // Build the index into the case table + if ( insideOut ) + { + for ( i=0, index = 0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) <= value) + { + index |= CASE_MASK[i]; + } + } + // Select case based on the index and get the list of edges for this case + quadCase = quadCases + index; + } + else + { + for ( i=0, index = 0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) > value) + { + index |= CASE_MASK[i]; + } + } + // Select case based on the index and get the list of edges for this case + quadCase = quadCasesComplement + index; + } + + edge = quadCase->edges; + + // generate each quad + for ( ; edge[0] > -1; edge += edge[0]+1 ) + { + for (i=0; i < edge[0]; i++) // insert quad or triangle + { + // vertex exists, and need not be interpolated + if (edge[i+1] >= 100) + { + vertexId = edge[i+1] - 100; + this->Points->GetPoint(vertexId, x); + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + outPd->CopyData(inPd,this->PointIds->GetId(vertexId),pts[i]); + } + } + + else //new vertex, interpolate + { + vert = edges[edge[i+1]]; + + // calculate a preferred interpolation direction + scalar0 = cellScalars->GetComponent(vert[0],0); + scalar1 = cellScalars->GetComponent(vert[1],0); + deltaScalar = scalar1 - scalar0; + + if (deltaScalar > 0) + { + e1 = vert[0]; e2 = vert[1]; + e1Scalar = scalar0; + } + else + { + e1 = vert[1]; e2 = vert[0]; + e1Scalar = scalar1; + deltaScalar = -deltaScalar; + } + + // linear interpolation + if (deltaScalar == 0.0) + { + t = 0.0; + } + else + { + t = (value - e1Scalar) / deltaScalar; + } + + this->Points->GetPoint(e1, x1); + this->Points->GetPoint(e2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + vtkIdType p1 = this->PointIds->GetId(e1); + vtkIdType p2 = this->PointIds->GetId(e2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate output + if ( edge[0] == 3 ) //i.e., a triangle + { + if (pts[0] == pts[1] || pts[0] == pts[2] || pts[1] == pts[2] ) + { + continue; + } + } + else // a quad + { + if ((pts[0] == pts[3] && pts[1] == pts[2]) || + (pts[0] == pts[1] && pts[3] == pts[2]) ) + { + continue; + } + } + + newCellId = polys->InsertNextCell(edge[0],pts); + outCd->CopyData(inCd,cellId,newCellId); + } +} + +//---------------------------------------------------------------------------- +static double vtkQuadCellPCoords[12] = {0.0,0.0,0.0, 1.0,0.0,0.0, + 1.0,1.0,0.0, 0.0,1.0,0.0}; +double *vtkQuad::GetParametricCoords() +{ + return vtkQuadCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuad::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Triangle:\n"; + this->Triangle->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuad.h b/Filtering/vtkQuad.h new file mode 100644 index 0000000..4e64659 --- /dev/null +++ b/Filtering/vtkQuad.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuad.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuad - a cell that represents a 2D quadrilateral +// .SECTION Description +// vtkQuad is a concrete implementation of vtkCell to represent a 2D +// quadrilateral. vtkQuad is defined by the four points (0,1,2,3) in +// counterclockwise order. vtkQuad uses the standard isoparametric +// interpolation functions for a linear quadrilateral. + +#ifndef __vtkQuad_h +#define __vtkQuad_h + +#include "vtkCell.h" + +class vtkLine; +class vtkTriangle; + +class VTK_FILTERING_EXPORT vtkQuad : public vtkCell +{ +public: + static vtkQuad *New(); + vtkTypeRevisionMacro(vtkQuad,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_QUAD;}; + int GetCellDimension() {return 2;}; + int GetNumberOfEdges() {return 4;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Return the center of the triangle in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Clip this quad using scalar value provided. Like contouring, except + // that it cuts the quad to produce other quads and/or triangles. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // vtkQuad specific methods. + static void InterpolationFunctions(double pcoords[3], double sf[4]); + static void InterpolationDerivs(double pcoords[3], double derivs[8]); + +protected: + vtkQuad(); + ~vtkQuad(); + + vtkLine *Line; + vtkTriangle *Triangle; + +private: + vtkQuad(const vtkQuad&); // Not implemented. + void operator=(const vtkQuad&); // Not implemented. +}; +//---------------------------------------------------------------------------- +inline int vtkQuad::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.5; + pcoords[2] = 0.0; + return 0; +} + + +#endif + + diff --git a/Filtering/vtkQuadraticEdge.cxx b/Filtering/vtkQuadraticEdge.cxx new file mode 100644 index 0000000..9a68eb3 --- /dev/null +++ b/Filtering/vtkQuadraticEdge.cxx @@ -0,0 +1,355 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticEdge.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadraticEdge.h" +#include "vtkPolyData.h" +#include "vtkPointLocator.h" +#include "vtkMath.h" +#include "vtkLine.h" +#include "vtkDoubleArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkQuadraticEdge, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkQuadraticEdge); + +//---------------------------------------------------------------------------- +// Construct the line with two points. +vtkQuadraticEdge::vtkQuadraticEdge() +{ + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(2); + this->Points->SetNumberOfPoints(3); + this->PointIds->SetNumberOfIds(3); + for (int i = 0; i < 3; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); +} + +//---------------------------------------------------------------------------- +vtkQuadraticEdge::~vtkQuadraticEdge() +{ + this->Line->Delete(); + this->Scalars->Delete(); +} + + +//---------------------------------------------------------------------------- +int vtkQuadraticEdge::EvaluatePosition(double* x, double* closestPoint, + int& subId, double pcoords[3], + double& minDist2, double *weights) +{ + double closest[3]; + double pc[3], dist2; + int ignoreId, i, returnStatus, status; + double lineWeights[2]; + + pcoords[1] = pcoords[2] = 0.0; + + returnStatus = -1; + weights[0] = 0.0; + for (minDist2=VTK_DOUBLE_MAX,i=0; i < 2; i++) + { + if ( i == 0) + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(0)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(2)); + } + else + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(2)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(1)); + } + + status = this->Line->EvaluatePosition(x,closest,ignoreId,pc, + dist2,lineWeights); + if ( status != -1 && dist2 < minDist2 ) + { + returnStatus = status; + minDist2 = dist2; + subId = i; + pcoords[0] = pc[0]; + } + } + + // adjust parametric coordinate + if ( returnStatus != -1 ) + { + if ( subId == 0 ) //first part + { + pcoords[0] = pcoords[0]/2.0; + } + else + { + pcoords[0] = 0.5 + pcoords[0]/2.0; + } + if(closestPoint!=0) + { + // Compute both closestPoint and weights + this->EvaluateLocation(subId,pcoords,closestPoint,weights); + } + else + { + // Compute weights only + this->InterpolationFunctions(pcoords,weights); + } + } + + return returnStatus; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticEdge::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], + double x[3], double *weights) +{ + int i; + double a0[3], a1[3], a2[3]; + this->Points->GetPoint(0, a0); + this->Points->GetPoint(1, a1); + this->Points->GetPoint(2, a2); //midside node + + this->InterpolationFunctions(pcoords,weights); + + for (i=0; i<3; i++) + { + x[i] = a0[i]*weights[0] + a1[i]*weights[1] + a2[i]*weights[2]; + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticEdge::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + return this->Line->CellBoundary(subId, pcoords, pts); +} + +//---------------------------------------------------------------------------- +static int LinearLines[2][2] = { {0,2}, {2,1} }; + + +void vtkQuadraticEdge::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + for (int i=0; i < 2; i++) //for each subdivided line + { + for ( int j=0; j<2; j++) //for each of the four vertices of the line + { + this->Line->Points->SetPoint(j,this->Points->GetPoint(LinearLines[i][j])); + this->Line->PointIds->SetId(j,this->PointIds->GetId(LinearLines[i][j])); + this->Scalars->SetValue(j,cellScalars->GetTuple1(LinearLines[i][j])); + } + this->Line->Contour(value, this->Scalars, locator, verts, + lines, polys, inPd, outPd, inCd, cellId, outCd); + } +} + +//---------------------------------------------------------------------------- +// Line-line intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. + +// The following arguments were modified to avoid warnings: +// double p1[3], double p2[3], double x[3], double pcoords[3], + +int vtkQuadraticEdge::IntersectWithLine(double p1[3], double p2[3], + double tol, double& t, + double x[3], double pcoords[3], + int& subId) +{ + int subTest, numLines=2; + + for (subId=0; subId < numLines; subId++) + { + if ( subId == 0) + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(0)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(2)); + } + else + { + this->Line->Points->SetPoint(0,this->Points->GetPoint(2)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(1)); + } + + if ( this->Line->IntersectWithLine(p1, p2, tol, t, x, pcoords, subTest) ) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkQuadraticEdge::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + // The first line + ptIds->InsertId(0,this->PointIds->GetId(0)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + + ptIds->InsertId(1,this->PointIds->GetId(2)); + pts->InsertPoint(1,this->Points->GetPoint(2)); + + // The second line + ptIds->InsertId(2,this->PointIds->GetId(2)); + pts->InsertPoint(2,this->Points->GetPoint(2)); + + ptIds->InsertId(3,this->PointIds->GetId(1)); + pts->InsertPoint(3,this->Points->GetPoint(1)); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticEdge::Derivatives(int vtkNotUsed(subId), + double pcoords[3], double *values, + int dim, double *derivs) +{ + double x0[3], x1[3], x2[3]; + this->Points->GetPoint(0, x0); + this->Points->GetPoint(1, x1); + this->Points->GetPoint(2, x2); //midside node + + // set up Jacobian matrix and inverse matrix + double *jTj[3], jTj0[3], jTj1[3], jTj2[3]; + jTj[0] = jTj0; jTj[1] = jTj1; jTj[2] = jTj2; + double *jI[3], jI0[3], jI1[3], jI2[3]; + jI[0] = jI0; jI[1] = jI1; jI[2] = jI2; + /* + double *iI[3], iI0[3], iI1[3], iI2[3]; + iI[0] = iI0; iI[1] = iI1; iI[2] = iI2; + */ + // Compute dx/dt, dy/dt, dz/dt + this->InterpolationDerivs(pcoords,derivs); + double dxdt = x0[0]*derivs[0] + x1[0]*derivs[1] + x2[0]*derivs[2]; + double dydt = x0[1]*derivs[0] + x1[1]*derivs[1] + x2[1]*derivs[2]; + double dzdt = x0[2]*derivs[0] + x1[2]*derivs[1] + x2[2]*derivs[2]; + + // Compute the psuedo inverse (we are dealing with an overconstrained system, + // i.e., a non-square Jacobian matrix). The pseudo inverse is ((jT*j)-1)*jT + // with jT Jacobian transpose, -1 notation means inverse. + // Compute jT * j + jTj[0][0] = dxdt*dxdt; + jTj[0][1] = dxdt*dydt; + jTj[0][2] = dxdt*dzdt; + jTj[1][0] = dydt*dxdt; + jTj[1][1] = dydt*dydt; + jTj[1][2] = dydt*dzdt; + jTj[2][0] = dzdt*dxdt; + jTj[2][1] = dzdt*dydt; + jTj[2][2] = dzdt*dzdt; + + // Compute (jT * j) inverse + // now find the inverse + if ( vtkMath::InvertMatrix(jTj,jI,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } + + // Multiply inverse by transpose (jT * j) * jT to yield pseudo inverse. + // Here the pseudo inverse is a 3x1 matrix. + double inv[3]; + inv[0] = jI[0][0]*dxdt + jI[0][1]*dydt + jI[0][2]*dzdt; + inv[1] = jI[1][0]*dxdt + jI[1][1]*dydt + jI[1][2]*dzdt; + inv[2] = jI[2][0]*dxdt + jI[2][1]*dydt + jI[2][2]*dzdt; + + //now compute the derivates of the data values + double sum; + int i, j, k; + for (k=0; kLine->Points->SetPoint(j,this->Points->GetPoint(LinearLines[i][j])); + this->Line->PointIds->SetId(j,this->PointIds->GetId(LinearLines[i][j])); + this->Scalars->SetValue(j,cellScalars->GetTuple1(LinearLines[i][j])); + } + this->Line->Clip(value, this->Scalars, locator, lines, inPd, outPd, + inCd, cellId, outCd, insideOut); + } +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions. Node [2] is the mid-edge node. +void vtkQuadraticEdge::InterpolationFunctions(double pcoords[3], + double weights[3]) +{ + double r = pcoords[0]; + + weights[0] = 2.0 * (r - 0.5) * (r - 1.0); + weights[1] = 2.0 * r * (r - 0.5); + weights[2] = 4.0 * r * (1.0 - r); +} + +//---------------------------------------------------------------------------- +// Derivatives in parametric space. +void vtkQuadraticEdge::InterpolationDerivs(double pcoords[3], double derivs[3]) +{ + double r = pcoords[0]; + + derivs[0] = 4.0 * r - 3.0; + derivs[1] = 4.0 * r - 1.0; + derivs[2] = 4.0 - r * 8.0; +} + +//---------------------------------------------------------------------------- +static double vtkQEdgeCellPCoords[9] = {0.0,0.0,0.0, 1.0,0.0,0.0, 0.5,0.0,0.0}; +double *vtkQuadraticEdge::GetParametricCoords() +{ + return vtkQEdgeCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticEdge::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuadraticEdge.h b/Filtering/vtkQuadraticEdge.h new file mode 100644 index 0000000..4d95351 --- /dev/null +++ b/Filtering/vtkQuadraticEdge.h @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticEdge.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadraticEdge - cell represents a parabolic, isoparametric edge +// .SECTION Description +// vtkQuadraticEdge is a concrete implementation of vtkNonLinearCell to +// represent a one-dimensional, 3-nodes, isoparametric parabolic line. The +// interpolation is the standard finite element, quadratic isoparametric +// shape function. The cell includes a mid-edge node. The ordering of the +// three points defining the cell is point ids (0,1,2) where id #2 is the +// midedge node. + +// .SECTION See Also +// vtkQuadraticTriangle vtkQuadraticTetra vtkQuadraticWedge +// vtkQuadraticQuad vtkQuadraticHexahedron vtkQuadraticPyramid + +#ifndef __vtkQuadraticEdge_h +#define __vtkQuadraticEdge_h + +#include "vtkNonLinearCell.h" + +class vtkLine; + +class VTK_FILTERING_EXPORT vtkQuadraticEdge : public vtkNonLinearCell +{ +public: + static vtkQuadraticEdge *New(); + vtkTypeRevisionMacro(vtkQuadraticEdge,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement the vtkCell API. See the vtkCell API for descriptions + // of these methods. + int GetCellType() {return VTK_QUADRATIC_EDGE;}; + int GetCellDimension() {return 1;} + int GetNumberOfEdges() {return 0;} + int GetNumberOfFaces() {return 0;} + vtkCell *GetEdge(int) {return 0;} + vtkCell *GetFace(int) {return 0;} + + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this edge using scalar value provided. Like contouring, except + // that it cuts the edge to produce linear line segments. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *lines, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Line-edge intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + // Description: + // Return the center of the quadratic tetra in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Quadratic edge specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[3]); + static void InterpolationDerivs(double pcoords[3], double derivs[3]); + +protected: + vtkQuadraticEdge(); + ~vtkQuadraticEdge(); + + vtkLine *Line; + vtkDoubleArray *Scalars; //used to avoid New/Delete in contouring/clipping + +private: + vtkQuadraticEdge(const vtkQuadraticEdge&); // Not implemented. + void operator=(const vtkQuadraticEdge&); // Not implemented. +}; +//---------------------------------------------------------------------------- +inline int vtkQuadraticEdge::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = 0.5; + pcoords[1] = pcoords[2] = 0.; + return 0; +} + +#endif + + diff --git a/Filtering/vtkQuadraticHexahedron.cxx b/Filtering/vtkQuadraticHexahedron.cxx new file mode 100644 index 0000000..97455ab --- /dev/null +++ b/Filtering/vtkQuadraticHexahedron.cxx @@ -0,0 +1,705 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticHexahedron.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadraticHexahedron.h" + +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkHexahedron.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPolyData.h" +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticQuad.h" + +vtkCxxRevisionMacro(vtkQuadraticHexahedron, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkQuadraticHexahedron); + +//---------------------------------------------------------------------------- +// Construct the hex with 20 points + 7 extra points for internal +// computation. +vtkQuadraticHexahedron::vtkQuadraticHexahedron() +{ + // At times the cell looks like it has 27 points (during interpolation) + // We initially allocate for 27. + this->Points->SetNumberOfPoints(27); + this->PointIds->SetNumberOfIds(27); + for (int i = 0; i < 27; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Points->SetNumberOfPoints(20); + this->PointIds->SetNumberOfIds(20); + + this->Edge = vtkQuadraticEdge::New(); + this->Face = vtkQuadraticQuad::New(); + this->Hex = vtkHexahedron::New(); + + this->PointData = vtkPointData::New(); + this->CellData = vtkCellData::New(); + this->CellScalars = vtkDoubleArray::New(); + this->CellScalars->SetNumberOfTuples(27); + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(8); +} + +//---------------------------------------------------------------------------- +vtkQuadraticHexahedron::~vtkQuadraticHexahedron() +{ + this->Edge->Delete(); + this->Face->Delete(); + this->Hex->Delete(); + + this->PointData->Delete(); + this->CellData->Delete(); + this->Scalars->Delete(); + this->CellScalars->Delete(); +} + + +static int LinearHexs[8][8] = { {0,8,24,11,16,22,26,20}, + {8,1,9,24,22,17,21,26}, + {11,24,10,3,20,26,23,19}, + {24,9,2,10,26,21,18,23}, + {16,22,26,20,4,12,25,15}, + {22,17,21,26,12,5,13,25}, + {20,26,23,19,15,25,14,7}, + {26,21,18,23,25,13,6,14} }; + +static int HexFaces[6][8] = { {0,4,7,3,16,15,19,11}, + {1,2,6,5,9,18,13,17}, + {0,1,5,4,8,17,12,16}, + {3,7,6,2,19,14,18,10}, + {0,3,2,1,11,10,9,8}, + {4,5,6,7,12,13,14,15} }; + +static int HexEdges[12][3] = { {0,1,8}, {1,2,9}, {3,2,10}, {0,3,11}, + {4,5,12}, {5,6,13}, {7,6,14}, {4,7,15}, + {0,4,16}, {1,5,17}, {3,7,19}, {2,6,18} }; + +static double MidPoints[7][3] = { {0.0,0.5,0.5}, {1.0,0.5,0.5}, + {0.5,0.0,0.5}, {0.5,1.0,0.5}, + {0.5,0.5,0.0}, {0.5,0.5,1.0}, + {0.5,0.5,0.5} }; + + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticHexahedron::GetEdge(int edgeId) +{ + edgeId = (edgeId < 0 ? 0 : (edgeId > 11 ? 11 : edgeId )); + + for (int i=0; i<3; i++) + { + this->Edge->PointIds->SetId(i,this->PointIds->GetId(HexEdges[edgeId][i])); + this->Edge->Points->SetPoint(i,this->Points->GetPoint(HexEdges[edgeId][i])); + } + + return this->Edge; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticHexahedron::GetFace(int faceId) +{ + faceId = (faceId < 0 ? 0 : (faceId > 5 ? 5 : faceId )); + + for (int i=0; i<8; i++) + { + this->Face->PointIds->SetId(i,this->PointIds->GetId(HexFaces[faceId][i])); + this->Face->Points->SetPoint(i,this->Points->GetPoint(HexFaces[faceId][i])); + } + + return this->Face; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticHexahedron::Subdivide(vtkPointData *inPd, vtkCellData *inCd, + vtkIdType cellId, vtkDataArray *cellScalars) +{ + int numMidPts, i, j; + double weights[20]; + double x[3]; + double s; + + //Copy point and cell attribute data, first make sure it's empty: + this->PointData->Initialize(); + this->CellData->Initialize(); + this->PointData->CopyAllocate(inPd,27); + this->CellData->CopyAllocate(inCd,8); + for (i=0; i<20; i++) + { + this->PointData->CopyData(inPd,this->PointIds->GetId(i),i); + this->CellScalars->SetValue( i, cellScalars->GetTuple1(i)); + } + this->CellData->CopyData(inCd,cellId,0); + + //Interpolate new values + double p[3]; + for ( numMidPts=0; numMidPts < 7; numMidPts++ ) + { + this->InterpolationFunctions(MidPoints[numMidPts], weights); + + x[0] = x[1] = x[2] = 0.0; + s = 0.0; + for (i=0; i<20; i++) + { + this->Points->GetPoint(i, p); + for (j=0; j<3; j++) + { + x[j] += p[j] * weights[i]; + } + s += cellScalars->GetTuple1(i) * weights[i]; + } + this->Points->SetPoint(20+numMidPts,x); + this->CellScalars->SetValue(20+numMidPts,s); + this->PointData->InterpolatePoint(inPd, 20+numMidPts, + this->PointIds, weights); + } +} + +//---------------------------------------------------------------------------- +static const double VTK_DIVERGED = 1.e6; +static const int VTK_HEX_MAX_ITERATION=10; +static const double VTK_HEX_CONVERGED=1.e-03; + +int vtkQuadraticHexahedron::EvaluatePosition(double* x, + double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[60]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.5; + + // enter iteration loop + for (iteration=converged=0; + !converged && (iteration < VTK_HEX_MAX_ITERATION); iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<20; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+20]; + tcol[j] += pt[j] * derivs[i+40]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - 0.5*vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - 0.5*vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - 0.5*vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_HEX_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_HEX_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_HEX_CONVERGED) ) + { + converged = 1; + } + + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside hexahedron + } + return 1; + } + else + { + double pc[3], w[20]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticHexahedron::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<20; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticHexahedron::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + return this->Hex->CellBoundary(subId, pcoords, pts); +} + +//---------------------------------------------------------------------------- +void vtkQuadraticHexahedron::Contour(double value, + vtkDataArray* cellScalars, + vtkPointLocator* locator, + vtkCellArray *verts, + vtkCellArray* lines, + vtkCellArray* polys, + vtkPointData* inPd, + vtkPointData* outPd, + vtkCellData* inCd, + vtkIdType cellId, + vtkCellData* outCd) +{ + //subdivide into 8 linear hexs + this->Subdivide(inPd,inCd,cellId, cellScalars); + + //contour each linear quad separately + for (int i=0; i<8; i++) // For each subdivided hexahedron + { + for (int j=0; j<8; j++) // For each of the eight vertices of the hexhedron + { + this->Hex->Points->SetPoint(j,this->Points->GetPoint(LinearHexs[i][j])); + this->Hex->PointIds->SetId(j,LinearHexs[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearHexs[i][j])); + } + this->Hex->Contour(value,this->Scalars,locator,verts,lines,polys, + this->PointData,outPd,this->CellData,cellId,outCd); + } +} + +//---------------------------------------------------------------------------- +// Line-hex intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. +int vtkQuadraticHexahedron::IntersectWithLine(double* p1, double* p2, + double tol, double& t, + double* x, double* pcoords, + int& subId) +{ + int intersection=0; + double tTemp; + double pc[3], xTemp[3]; + int faceNum; + + t = VTK_DOUBLE_MAX; + for (faceNum=0; faceNum<6; faceNum++) + { + for (int i=0; i<8; i++) + { + this->Face->Points->SetPoint(i, + this->Points->GetPoint(HexFaces[faceNum][i])); + } + + if ( this->Face->IntersectWithLine(p1, p2, tol, tTemp, + xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = 0.0; pcoords[1] = pc[1]; pcoords[2] = pc[0]; + break; + + case 1: + pcoords[0] = 1.0; pcoords[1] = pc[0]; pcoords[2] = pc[1]; + break; + + case 2: + pcoords[0] = pc[0]; pcoords[1] = 0.0; pcoords[2] = pc[1]; + break; + + case 3: + pcoords[0] = pc[1]; pcoords[1] = 1.0; pcoords[2] = pc[0]; + break; + + case 4: + pcoords[0] = pc[1]; pcoords[1] = pc[0]; pcoords[2] = 0.0; + break; + + case 5: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 1.0; + break; + } + } + } + } + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkQuadraticHexahedron::Triangulate(int vtkNotUsed(index), + vtkIdList *ptIds, vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + ptIds->InsertId(0,this->PointIds->GetId(0)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + + ptIds->InsertId(1,this->PointIds->GetId(1)); + pts->InsertPoint(1,this->Points->GetPoint(1)); + + return 1; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. +void vtkQuadraticHexahedron::JacobianInverse(double pcoords[3], + double **inverse, + double derivs[60]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords, derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 20; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[20 + j]; + m2[i] += x[i] * derivs[40 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticHexahedron::Derivatives(int vtkNotUsed(subId), + double pcoords[3], double *values, + int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[60], sum[3]; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 20; i++) //loop over interp. function derivatives + { + sum[0] += functionDerivs[i] * values[dim*i + k]; + sum[1] += functionDerivs[20 + i] * values[dim*i + k]; + sum[2] += functionDerivs[40 + i] * values[dim*i + k]; + } + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} + + +//---------------------------------------------------------------------------- +// Clip this quadratic hex using scalar value provided. Like contouring, +// except that it cuts the hex to produce tetrahedra. +void vtkQuadraticHexahedron::Clip(double value, + vtkDataArray* cellScalars, + vtkPointLocator* locator, vtkCellArray* tets, + vtkPointData* inPd, vtkPointData* outPd, + vtkCellData* inCd, vtkIdType cellId, + vtkCellData* outCd, int insideOut) +{ + //create eight linear hexes + this->Subdivide(inPd,inCd,cellId,cellScalars); + + //contour each linear hex separately + for (int i=0; i<8; i++) // For each subdivided hexahedron + { + for (int j=0; j<8; j++) // For each of the eight vertices of the hexhedron + { + this->Hex->Points->SetPoint(j,this->Points->GetPoint(LinearHexs[i][j])); + this->Hex->PointIds->SetId(j,LinearHexs[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearHexs[i][j])); + } + this->Hex->Clip(value,this->Scalars,locator,tets,this->PointData,outPd, + this->CellData,cellId,outCd,insideOut); + } +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions for the twenty nodes. +void vtkQuadraticHexahedron::InterpolationFunctions(double pcoords[3], + double weights[20]) +{ + //VTK needs parametric coordinates to be between (0,1). Isoparametric + //shape functions are formulated between (-1,1). Here we do a + //coordinate system conversion from (0,1) to (-1,1). + double r = 2.0*(pcoords[0]-0.5); + double s = 2.0*(pcoords[1]-0.5); + double t = 2.0*(pcoords[2]-0.5); + + double rm = 1.0 - r; + double rp = 1.0 + r; + double sm = 1.0 - s; + double sp = 1.0 + s; + double tm = 1.0 - t; + double tp = 1.0 + t; + double r2 = 1.0 - r*r; + double s2 = 1.0 - s*s; + double t2 = 1.0 - t*t; + + //The eight corner points + weights[0] = 0.125 * rm * sm * tm * (-r - s - t - 2.0); + weights[1] = 0.125 * rp * sm * tm * ( r - s - t - 2.0); + weights[2] = 0.125 * rp * sp * tm * ( r + s - t - 2.0); + weights[3] = 0.125 * rm * sp * tm * (-r + s - t - 2.0); + weights[4] = 0.125 * rm * sm * tp * (-r - s + t - 2.0); + weights[5] = 0.125 * rp * sm * tp * ( r - s + t - 2.0); + weights[6] = 0.125 * rp * sp * tp * ( r + s + t - 2.0); + weights[7] = 0.125 * rm * sp * tp * (-r + s + t - 2.0); + + //The mid-edge nodes + weights[8] = 0.25 * r2 * sm * tm; + weights[9] = 0.25 * s2 * rp * tm; + weights[10] = 0.25 * r2 * sp * tm; + weights[11] = 0.25 * s2 * rm * tm; + weights[12] = 0.25 * r2 * sm * tp; + weights[13] = 0.25 * s2 * rp * tp; + weights[14] = 0.25 * r2 * sp * tp; + weights[15] = 0.25 * s2 * rm * tp; + weights[16] = 0.25 * t2 * rm * sm; + weights[17] = 0.25 * t2 * rp * sm; + weights[18] = 0.25 * t2 * rp * sp; + weights[19] = 0.25 * t2 * rm * sp; +} + +//---------------------------------------------------------------------------- +// Derivatives in parametric space. +void vtkQuadraticHexahedron::InterpolationDerivs(double pcoords[3], + double derivs[60]) +{ + //VTK needs parametric coordinates to be between (0,1). Isoparametric + //shape functions are formulated between (-1,1). Here we do a + //coordinate system conversion from (0,1) to (-1,1). + double r = 2.0*(pcoords[0]-0.5); + double s = 2.0*(pcoords[1]-0.5); + double t = 2.0*(pcoords[2]-0.5); + + double rm = 1.0 - r; + double rp = 1.0 + r; + double sm = 1.0 - s; + double sp = 1.0 + s; + double tm = 1.0 - t; + double tp = 1.0 + t; + + //r-derivatives + derivs[0] = -0.125*(sm*tm - 2.0*r*sm*tm - s*sm*tm - t*sm*tm - 2.0*sm*tm); + derivs[1] = 0.125*(sm*tm + 2.0*r*sm*tm - s*sm*tm - t*sm*tm - 2.0*sm*tm); + derivs[2] = 0.125*(sp*tm + 2.0*r*sp*tm + s*sp*tm - t*sp*tm - 2.0*sp*tm); + derivs[3] = -0.125*(sp*tm - 2.0*r*sp*tm + s*sp*tm - t*sp*tm - 2.0*sp*tm); + derivs[4] = -0.125*(sm*tp - 2.0*r*sm*tp - s*sm*tp + t*sm*tp - 2.0*sm*tp); + derivs[5] = 0.125*(sm*tp + 2.0*r*sm*tp - s*sm*tp + t*sm*tp - 2.0*sm*tp); + derivs[6] = 0.125*(sp*tp + 2.0*r*sp*tp + s*sp*tp + t*sp*tp - 2.0*sp*tp); + derivs[7] = -0.125*(sp*tp - 2.0*r*sp*tp + s*sp*tp + t*sp*tp - 2.0*sp*tp); + derivs[8] = -0.5*r*sm*tm; + derivs[9] = 0.25*(tm - s*s*tm); + derivs[10] = -0.5*r*sp*tm; + derivs[11] = -0.25*(tm - s*s*tm); + derivs[12] = -0.5*r*sm*tp; + derivs[13] = 0.25*(tp - s*s*tp); + derivs[14] = -0.5*r*sp*tp; + derivs[15] = -0.25*(tp - s*s*tp); + derivs[16] = -0.25*(sm - t*t*sm); + derivs[17] = 0.25*(sm - t*t*sm); + derivs[18] = 0.25*(sp - t*t*sp); + derivs[19] = -0.25*(sp - t*t*sp); + + //s-derivatives + derivs[20] = -0.125*(rm*tm - 2.0*s*rm*tm - r*rm*tm - t*rm*tm - 2.0*rm*tm); + derivs[21] = -0.125*(rp*tm - 2.0*s*rp*tm + r*rp*tm - t*rp*tm - 2.0*rp*tm); + derivs[22] = 0.125*(rp*tm + 2.0*s*rp*tm + r*rp*tm - t*rp*tm - 2.0*rp*tm); + derivs[23] = 0.125*(rm*tm + 2.0*s*rm*tm - r*rm*tm - t*rm*tm - 2.0*rm*tm); + derivs[24] = -0.125*(rm*tp - 2.0*s*rm*tp - r*rm*tp + t*rm*tp - 2.0*rm*tp); + derivs[25] = -0.125*(rp*tp - 2.0*s*rp*tp + r*rp*tp + t*rp*tp - 2.0*rp*tp); + derivs[26] = 0.125*(rp*tp + 2.0*s*rp*tp + r*rp*tp + t*rp*tp - 2.0*rp*tp); + derivs[27] = 0.125*(rm*tp + 2.0*s*rm*tp - r*rm*tp + t*rm*tp - 2.0*rm*tp); + derivs[28] = -0.25*(tm - r*r*tm); + derivs[29] = -0.5*s*rp*tm; + derivs[30] = 0.25*(tm - r*r*tm); + derivs[31] = -0.5*s*rm*tm; + derivs[32] = -0.25*(tp - r*r*tp); + derivs[33] = -0.5*s*rp*tp; + derivs[34] = 0.25*(tp - r*r*tp); + derivs[35] = -0.5*s*rm*tp; + derivs[36] = -0.25*(rm - t*t*rm); + derivs[37] = -0.25*(rp - t*t*rp); + derivs[38] = 0.25*(rp - t*t*rp); + derivs[39] = 0.25*(rm - t*t*rm); + + //t-derivatives + derivs[40] = -0.125*(rm*sm - 2.0*t*rm*sm - r*rm*sm - s*rm*sm - 2.0*rm*sm); + derivs[41] = -0.125*(rp*sm - 2.0*t*rp*sm + r*rp*sm - s*rp*sm - 2.0*rp*sm); + derivs[42] = -0.125*(rp*sp - 2.0*t*rp*sp + r*rp*sp + s*rp*sp - 2.0*rp*sp); + derivs[43] = -0.125*(rm*sp - 2.0*t*rm*sp - r*rm*sp + s*rm*sp - 2.0*rm*sp); + derivs[44] = 0.125*(rm*sm + 2.0*t*rm*sm - r*rm*sm - s*rm*sm - 2.0*rm*sm); + derivs[45] = 0.125*(rp*sm + 2.0*t*rp*sm + r*rp*sm - s*rp*sm - 2.0*rp*sm); + derivs[46] = 0.125*(rp*sp + 2.0*t*rp*sp + r*rp*sp + s*rp*sp - 2.0*rp*sp); + derivs[47] = 0.125*(rm*sp + 2.0*t*rm*sp - r*rm*sp + s*rm*sp - 2.0*rm*sp); + derivs[48] = -0.25*(sm - r*r*sm); + derivs[49] = -0.25*(rp - s*s*rp); + derivs[50] = -0.25*(sp - r*r*sp); + derivs[51] = -0.25*(rm - s*s*rm); + derivs[52] = 0.25*(sm - r*r*sm); + derivs[53] = 0.25*(rp - s*s*rp); + derivs[54] = 0.25*(sp - r*r*sp); + derivs[55] = 0.25*(rm - s*s*rm); + derivs[56] = -0.5*t*rm*sm; + derivs[57] = -0.5*t*rp*sm; + derivs[58] = -0.5*t*rp*sp; + derivs[59] = -0.5*t*rm*sp; +} + +//---------------------------------------------------------------------------- +static double vtkQHexCellPCoords[60] = {0.0,0.0,0.0, 1.0,0.0,0.0, 1.0,1.0,0.0, + 0.0,1.0,0.0, 0.0,0.0,1.0, 1.0,0.0,1.0, + 1.0,1.0,1.0, 0.0,1.0,1.0, 0.5,0.0,0.0, + 1.0,0.5,0.0, 0.5,1.0,0.0, 0.0,0.5,0.0, + 0.5,0.0,1.0, 1.0,0.5,1.0, 0.5,1.0,1.0, + 0.0,0.5,1.0, 0.0,0.0,0.5, 1.0,0.0,0.5, + 1.0,1.0,0.5, 0.0,1.0,0.5}; +double *vtkQuadraticHexahedron::GetParametricCoords() +{ + return vtkQHexCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticHexahedron::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Edge:\n"; + this->Edge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Face:\n"; + this->Face->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Hex:\n"; + this->Hex->PrintSelf(os,indent.GetNextIndent()); + os << indent << "PointData:\n"; + this->PointData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "CellData:\n"; + this->CellData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Scalars:\n"; + this->Scalars->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuadraticHexahedron.h b/Filtering/vtkQuadraticHexahedron.h new file mode 100644 index 0000000..6d29b39 --- /dev/null +++ b/Filtering/vtkQuadraticHexahedron.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticHexahedron.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadraticHexahedron - cell represents a parabolic, 20-node isoparametric hexahedron +// .SECTION Description +// vtkQuadraticHexahedron is a concrete implementation of vtkNonLinearCell to +// represent a three-dimensional, 20-node isoparametric parabolic +// hexahedron. The interpolation is the standard finite element, quadratic +// isoparametric shape function. The cell includes a mid-edge node. The +// ordering of the twenty points defining the cell is point ids (0-7,8-19) +// where point ids 0-7 are the eight corner vertices of the cube; followed by +// twelve midedge nodes (8-19). Note that these midedge nodes correspond lie +// on the edges defined by (0,1), (1,2), (2,3), (3,0), (4,5), (5,6), (6,7), +// (7,4), (0,4), (1,5), (2,6), (3,7). + +// .SECTION See Also +// vtkQuadraticEdge vtkQuadraticTriangle vtkQuadraticTetra +// vtkQuadraticQuad vtkQuadraticPyramid vtkQuadraticWedge + +#ifndef __vtkQuadraticHexahedron_h +#define __vtkQuadraticHexahedron_h + +#include "vtkNonLinearCell.h" + +class vtkPolyData; +class vtkQuadraticEdge; +class vtkQuadraticQuad; +class vtkHexahedron; +class vtkDoubleArray; + +class VTK_FILTERING_EXPORT vtkQuadraticHexahedron : public vtkNonLinearCell +{ +public: + static vtkQuadraticHexahedron *New(); + vtkTypeRevisionMacro(vtkQuadraticHexahedron,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement the vtkCell API. See the vtkCell API for descriptions + // of these methods. + int GetCellType() {return VTK_QUADRATIC_HEXAHEDRON;} + int GetCellDimension() {return 3;} + int GetNumberOfEdges() {return 12;} + int GetNumberOfFaces() {return 6;} + vtkCell *GetEdge(int); + vtkCell *GetFace(int); + + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this quadratic hexahedron using scalar value provided. Like + // contouring, except that it cuts the hex to produce linear + // tetrahedron. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tetras, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Line-edge intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + + // Description: + // Quadratic hexahedron specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[20]); + static void InterpolationDerivs(double pcoords[3], double derivs[60]); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. + void JacobianInverse(double pcoords[3], double **inverse, double derivs[60]); + +protected: + vtkQuadraticHexahedron(); + ~vtkQuadraticHexahedron(); + + vtkQuadraticEdge *Edge; + vtkQuadraticQuad *Face; + vtkHexahedron *Hex; + vtkPointData *PointData; + vtkCellData *CellData; + vtkDoubleArray *CellScalars; + vtkDoubleArray *Scalars; + + void Subdivide(vtkPointData *inPd, vtkCellData *inCd, vtkIdType cellId, vtkDataArray *cellScalars); + +private: + vtkQuadraticHexahedron(const vtkQuadraticHexahedron&); // Not implemented. + void operator=(const vtkQuadraticHexahedron&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkQuadraticPyramid.cxx b/Filtering/vtkQuadraticPyramid.cxx new file mode 100644 index 0000000..fe28886 --- /dev/null +++ b/Filtering/vtkQuadraticPyramid.cxx @@ -0,0 +1,760 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticPyramid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadraticPyramid.h" + +#include "vtkObjectFactory.h" +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkTetra.h" +#include "vtkPyramid.h" +#include "vtkMath.h" +#include "vtkPointData.h" +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticQuad.h" +#include "vtkQuadraticTriangle.h" + +vtkCxxRevisionMacro(vtkQuadraticPyramid, "$Revision: 1.7.8.2 $"); +vtkStandardNewMacro(vtkQuadraticPyramid); + +//---------------------------------------------------------------------------- +// Construct the pyramid with 13 points + 1 extra point for internal +// computation. +// +vtkQuadraticPyramid::vtkQuadraticPyramid() +{ + // At creation time the cell looks like it has 14 points (during interpolation) + // We initially allocate for 14. + this->Points->SetNumberOfPoints(14); + this->PointIds->SetNumberOfIds(14); + for (int i = 0; i < 14; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Points->SetNumberOfPoints(13); + this->PointIds->SetNumberOfIds(13); + + this->Edge = vtkQuadraticEdge::New(); + this->Face = vtkQuadraticQuad::New(); + this->TriangleFace = vtkQuadraticTriangle::New(); + this->Tetra = vtkTetra::New(); + this->Pyramid = vtkPyramid::New(); + + this->PointData = vtkPointData::New(); + this->CellData = vtkCellData::New(); + this->CellScalars = vtkDoubleArray::New(); + this->CellScalars->SetNumberOfTuples(14); + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(5); //num of vertices +} + +//---------------------------------------------------------------------------- +vtkQuadraticPyramid::~vtkQuadraticPyramid() +{ + this->Edge->Delete(); + this->Face->Delete(); + this->TriangleFace->Delete(); + this->Tetra->Delete(); + this->Pyramid->Delete(); + + this->PointData->Delete(); + this->CellData->Delete(); + this->Scalars->Delete(); + this->CellScalars->Delete(); +} + +//---------------------------------------------------------------------------- +static int LinearPyramids[10][5] = { {0,5,13,8,9}, + {5,1,6,13,10}, + {8,13,7,3,12}, + {13,6,2,7,11}, + {9,10,11,12,4}, + {9,12,11,10,13}, + {5,10,9,13,0}, + {6,11,10,13,0}, + {7,12,11,13,0}, + {8,9,12,13,0} }; + +static int PyramidFaces[5][8] = { {0,3,2,1,8,7,6,5}, + {0,1,4,5,10,9,0,0}, + {1,2,4,6,11,10,0,0}, + {2,3,4,7,12,11,0,0}, + {3,0,4,8,9,12,0,0}}; + +static int PyramidEdges[8][3] = { {0,1,5}, {1,2,6}, {2,3,7}, + {3,0,8},{0,4,9},{1,4,10}, + {2,4,11}, {3,4,12} }; + +static double MidPoints[1][3] = { {0.5,0.5,0.0} }; + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticPyramid::GetEdge(int edgeId) +{ + edgeId = (edgeId < 0 ? 0 : (edgeId > 7 ? 7 : edgeId )); + + for (int i=0; i<3; i++) + { + this->Edge->PointIds->SetId(i,this->PointIds->GetId(PyramidEdges[edgeId][i])); + this->Edge->Points->SetPoint(i,this->Points->GetPoint(PyramidEdges[edgeId][i])); + } + + return this->Edge; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticPyramid::GetFace(int faceId) +{ + faceId = (faceId < 0 ? 0 : (faceId > 4 ? 4 : faceId )); + + // load point id's and coordinates + // be carefull with the first one: + if(faceId > 0) + { + for (int i=0; i<6; i++) + { + this->TriangleFace->PointIds->SetId(i,this->PointIds->GetId(PyramidFaces[faceId][i])); + this->TriangleFace->Points->SetPoint(i,this->Points->GetPoint(PyramidFaces[faceId][i])); + } + return this->TriangleFace; + } + else + { + for (int i=0; i<8; i++) + { + this->Face->PointIds->SetId(i,this->PointIds->GetId(PyramidFaces[faceId][i])); + this->Face->Points->SetPoint(i,this->Points->GetPoint(PyramidFaces[faceId][i])); + } + return this->Face; + } +} + +//---------------------------------------------------------------------------- +static const double VTK_DIVERGED = 1.e6; +static const int VTK_PYRAMID_MAX_ITERATION=10; +static const double VTK_PYRAMID_CONVERGED=1.e-03; + +int vtkQuadraticPyramid::EvaluatePosition(double* x, + double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[3*13]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.5; + + // enter iteration loop + for (iteration=converged=0; + !converged && (iteration < VTK_PYRAMID_MAX_ITERATION); iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<13; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+13]; + tcol[j] += pt[j] * derivs[i+26]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - 0.5*vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - 0.5*vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - 0.5*vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_PYRAMID_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_PYRAMID_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_PYRAMID_CONVERGED) ) + { + converged = 1; + } + + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside pyramid + } + return 1; + } + else + { + double pc[3], w[13]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticPyramid::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<13; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticPyramid::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + return this->Pyramid->CellBoundary(subId, pcoords, pts); +} + +//---------------------------------------------------------------------------- +void vtkQuadraticPyramid::Subdivide(vtkPointData *inPd, vtkCellData *inCd, + vtkIdType cellId, vtkDataArray *cellScalars) +{ + int numMidPts, i, j; + double weights[13]; + double x[3]; + double s; + + //Copy point and cell attribute data, first make sure it's empty: + this->PointData->Initialize(); + this->CellData->Initialize(); + this->PointData->CopyAllocate(inPd,14); + this->CellData->CopyAllocate(inCd,5); + for (i=0; i<13; i++) + { + this->PointData->CopyData(inPd,this->PointIds->GetId(i),i); + this->CellScalars->SetValue( i, cellScalars->GetTuple1(i)); + } + this->CellData->CopyData(inCd,cellId,0); + + //Interpolate new values + double p[3]; + for ( numMidPts=0; numMidPts < 1; numMidPts++ ) + { + this->InterpolationFunctions(MidPoints[numMidPts], weights); + + x[0] = x[1] = x[2] = 0.0; + s = 0.0; + for (i=0; i<13; i++) + { + this->Points->GetPoint(i, p); + for (j=0; j<3; j++) + { + x[j] += p[j] * weights[i]; + } + s += cellScalars->GetTuple1(i) * weights[i]; + } + this->Points->SetPoint(13+numMidPts,x); + this->CellScalars->SetValue(13+numMidPts,s); + this->PointData->InterpolatePoint(inPd, 13+numMidPts, + this->PointIds, weights); + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticPyramid::Contour(double value, + vtkDataArray* cellScalars, + vtkPointLocator* locator, + vtkCellArray *verts, + vtkCellArray* lines, + vtkCellArray* polys, + vtkPointData* inPd, + vtkPointData* outPd, + vtkCellData* inCd, + vtkIdType cellId, + vtkCellData* outCd) +{ + int i; + //subdivide into 6 linear pyramids + this->Subdivide(inPd,inCd,cellId,cellScalars); + + //contour each linear pyramid separately + this->Scalars->SetNumberOfTuples(5); //num of vertices + for (i=0; i<6; i++) //for each pyramid + { + for (int j=0; j<5; j++) //for each point of pyramid + { + this->Pyramid->Points->SetPoint(j,this->Points->GetPoint(LinearPyramids[i][j])); + this->Pyramid->PointIds->SetId(j,LinearPyramids[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearPyramids[i][j])); + } + this->Pyramid->Contour(value,this->Scalars,locator,verts,lines,polys, + this->PointData,outPd,this->CellData,cellId,outCd); + } + + //contour each linear tetra separately + this->Scalars->SetNumberOfTuples(4); //num of vertices + for (i=6; i<10; i++) //for each tetra + { + for (int j=0; j<4; j++) //for each point of tetra + { + this->Tetra->Points->SetPoint(j,this->Points->GetPoint(LinearPyramids[i][j])); + this->Tetra->PointIds->SetId(j,LinearPyramids[i][j]); + this->Scalars->SetTuple(j,this->CellScalars->GetTuple(LinearPyramids[i][j])); + } + this->Tetra->Contour(value,this->Scalars,locator,verts,lines,polys, + this->PointData,outPd,this->CellData,cellId,outCd); + } +} + +//---------------------------------------------------------------------------- +// Line-hex intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. +// +int vtkQuadraticPyramid::IntersectWithLine(double* p1, double* p2, + double tol, double& t, + double* x, double* pcoords, int& subId) +{ + int intersection=0; + double tTemp; + double pc[3], xTemp[3]; + int faceNum; + int inter; + + t = VTK_DOUBLE_MAX; + for (faceNum=0; faceNum<5; faceNum++) + { + // We have 8 nodes on rect face + // and 6 on triangle faces + if(faceNum > 0) + { + for (int i=0; i<6; i++) + { + this->TriangleFace->PointIds->SetId(i, + this->PointIds->GetId(PyramidFaces[faceNum][i])); + } + inter = this->TriangleFace->IntersectWithLine(p1, p2, tol, tTemp, + xTemp, pc, subId); + } + else + { + for (int i=0; i<8; i++) + { + this->Face->Points->SetPoint(i, + this->Points->GetPoint(PyramidFaces[faceNum][i])); + } + inter = this->Face->IntersectWithLine(p1, p2, tol, tTemp, + xTemp, pc, subId); + } + if ( inter ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = 0.0; pcoords[1] = pc[1]; pcoords[2] = pc[0]; + break; + + case 1: + pcoords[0] = 1.0; pcoords[1] = pc[0]; pcoords[2] = pc[1]; + break; + + case 2: + pcoords[0] = pc[0]; pcoords[1] = 0.0; pcoords[2] = pc[1]; + break; + + case 3: + pcoords[0] = pc[1]; pcoords[1] = 1.0; pcoords[2] = pc[0]; + break; + + case 4: + pcoords[0] = pc[1]; pcoords[1] = pc[0]; pcoords[2] = 0.0; + break; + + case 5: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 1.0; + break; + } + } + } + } + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkQuadraticPyramid::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + int i; + int ii; + pts->Reset(); + ptIds->Reset(); + + for (i=0; i < 6; i++) + { + for ( int j=0; j < 5; j++) + { + ptIds->InsertId(5*i+j,this->PointIds->GetId(LinearPyramids[i][j])); + pts->InsertPoint(5*i+j,this->Points->GetPoint(LinearPyramids[i][j])); + } + } + + for (ii=0, i=6 ; i < 10; i++, ii++) + { + for ( int j=0; j < 4; j++) + { + ptIds->InsertId(4*ii+j+30,this->PointIds->GetId(LinearPyramids[i][j])); + pts->InsertPoint(4*ii+j+30,this->Points->GetPoint(LinearPyramids[i][j])); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. +// +void vtkQuadraticPyramid::JacobianInverse(double pcoords[3], double **inverse, + double derivs[39]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords, derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 13; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[13 + j]; + m2[i] += x[i] * derivs[26 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticPyramid::Derivatives(int vtkNotUsed(subId), + double pcoords[3], double *values, + int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[3*13], sum[3]; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 13; i++) //loop over interp. function derivatives + { + sum[0] += functionDerivs[i] * values[dim*i + k]; + sum[1] += functionDerivs[13 + i] * values[dim*i + k]; + sum[2] += functionDerivs[26 + i] * values[dim*i + k]; + } + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} + +//---------------------------------------------------------------------------- +// Clip this quadratic pyramid using scalar value provided. Like contouring, +// except that it cuts the pyramid to produce tetrahedra. +// +void vtkQuadraticPyramid::Clip(double value, vtkDataArray* cellScalars, + vtkPointLocator* locator, vtkCellArray* tets, + vtkPointData* inPd, vtkPointData* outPd, + vtkCellData* inCd, vtkIdType cellId, + vtkCellData* outCd, int insideOut) +{ + int i; + // create six linear pyramid + 4 tetra + this->Subdivide(inPd,inCd,cellId,cellScalars); + + //contour each linear pyramid separately + this->Scalars->SetNumberOfTuples(5); //num of vertices + for (i=0; i<6; i++) //for each subdivided pyramid + { + for (int j=0; j<5; j++) //for each of the five vertices of the pyramid + { + this->Pyramid->Points->SetPoint(j,this->Points->GetPoint(LinearPyramids[i][j])); + this->Pyramid->PointIds->SetId(j,LinearPyramids[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearPyramids[i][j])); + } + this->Pyramid->Clip(value,this->Scalars,locator,tets,this->PointData,outPd, + this->CellData,cellId,outCd,insideOut); + } + + this->Scalars->SetNumberOfTuples(4); //num of vertices + for (i=6; i<10; i++) //for each subdivided tetra + { + for (int j=0; j<4; j++) //for each of the four vertices of the tetra + { + this->Tetra->Points->SetPoint(j,this->Points->GetPoint(LinearPyramids[i][j])); + this->Tetra->PointIds->SetId(j,LinearPyramids[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearPyramids[i][j])); + } + this->Tetra->Clip(value,this->Scalars,locator,tets,this->PointData,outPd, + this->CellData,cellId,outCd,insideOut); + } +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions for the fifteen nodes. +// +void vtkQuadraticPyramid::InterpolationFunctions(double pcoords[3], + double weights[13]) +{ + // VTK needs parametric coordinates to be between (0,1). Isoparametric + // shape functions are formulated between (-1,1). Here we do a + // coordinate system conversion from (0,1) to (-1,1). + double r = 2*pcoords[0] - 1; + double s = 2*pcoords[1] - 1; + double t = 2*pcoords[2] - 1; + + // corners + weights[0] = -0.0625 * (1 - r) * ( 1 - s ) * (1 - t) * (4 + 3*r + 3*s + 2*r*s + 2*t + r*t + s*t + 2*r*s*t); + weights[1] = -0.0625 * (1 + r) * ( 1 - s ) * (1 - t) * (4 - 3*r + 3*s - 2*r*s + 2*t - r*t + s*t - 2*r*s*t); + weights[2] = -0.0625 * (1 + r) * ( 1 + s ) * (1 - t) * (4 - 3*r - 3*s + 2*r*s + 2*t - r*t - s*t + 2*r*s*t); + weights[3] = -0.0625 * (1 - r) * ( 1 + s ) * (1 - t) * (4 + 3*r - 3*s - 2*r*s + 2*t + r*t - s*t - 2*r*s*t); + weights[4] = 0.5 * t * ( 1 + t ); + + // midsides of rectangles + weights[5] = 0.125 * ( 1 - r*r ) * (1 - s ) * (1 - t )*(2 + s + s*t); + weights[7] = 0.125 * ( 1 - r*r ) * (1 + s ) * (1 - t )*(2 - s - s*t); + weights[6] = 0.125 * ( 1 + r ) * (1 - s*s ) * (1 - t )*(2 - r - r*t); + weights[8] = 0.125 * ( 1 - r ) * (1 - s*s ) * (1 - t )*(2 + r + r*t); + + + // midsides of triangles + weights[9] = 0.25 * ( 1 - r ) * (1 - s ) * (1 - t*t ); + weights[10] = 0.25 * ( 1 + r ) * (1 - s ) * (1 - t*t ); + weights[11] = 0.25 * ( 1 + r ) * (1 + s ) * (1 - t*t ); + weights[12] = 0.25 * ( 1 - r ) * (1 + s ) * (1 - t*t ); +} + +//---------------------------------------------------------------------------- +// Derivatives in parametric space. +// +void vtkQuadraticPyramid::InterpolationDerivs(double pcoords[3], + double derivs[39]) +{ + //VTK needs parametric coordinates to be between (0,1). Isoparametric + //shape functions are formulated between (-1,1). Here we do a + //coordinate system conversion from (0,1) to (-1,1). + double r = 2*pcoords[0] - 1; + double s = 2*pcoords[1] - 1; + double t = 2*pcoords[2] - 1; + + //r-derivatives + // corners + derivs[0] = 0.0625 * (1 - s) * ( 1 - t ) * (1 + 6*r + s + 4*r*s + t + 2*r*t - s*t + 4*r*s*t); + derivs[1] = -0.0625 * (1 - s) * ( 1 - t ) * (1 - 6*r + s - 4*r*s + t - 2*r*t - s*t - 4*r*s*t); + derivs[2] = -0.0625 * (1 + s) * ( 1 - t ) * (1 - 6*r - s + 4*r*s + t - 2*r*t + s*t + 4*r*s*t); + derivs[3] = 0.0625 * (1 + s) * ( 1 - t ) * (1 + 6*r - s - 4*r*s + t + 2*r*t + s*t - 4*r*s*t); + derivs[4] = 0.0; + + // midsides of rectangles + derivs[5] = -0.25 * r * (1 - s ) * (1 - t )*(2 + s + s*t); + derivs[6] = 0.125 * (1 - s*s ) * (1 - t )*(1 - 2*r - t - 2*r*t); + derivs[7] = -0.25 * r * (1 + s ) * (1 - t )*(2 - s - s*t); + derivs[8] = -0.125 * (1 - s*s ) * (1 - t )*(1 + 2*r - t + 2*r*t); + + // midsides of triangles + derivs[9] = -0.25 * (1 - s ) * (1 - t*t ); + derivs[10] = 0.25 * (1 - s ) * (1 - t*t ); + derivs[11] = 0.25 * (1 + s ) * (1 - t*t ); + derivs[12] = -0.25 * (1 + s ) * (1 - t*t ); + + //s-derivatives + // corners + derivs[13] = 0.0625 * (1 - r) * (1 - t) * (1 + r + 6*s + 4*r*s + t - r*t + 2*s*t + 4*r*s*t); + derivs[14] = 0.0625 * (1 + r) * (1 - t) * (1 - r + 6*s - 4*r*s + t + r*t + 2*s*t - 4*r*s*t); + derivs[15] = -0.0625 * (1 + r) * (1 - t) * (1 - r - 6*s + 4*r*s + t + r*t - 2*s*t + 4*r*s*t); + derivs[16] = -0.0625 * (1 - r) * (1 - t) * (1 + r - 6*s - 4*r*s + t - r*t - 2*s*t - 4*r*s*t); + derivs[17] = 0.0; + + // midsides of rectangles + derivs[18] = -0.125 * ( 1 - r*r ) * (1 - t ) * (1 + 2*s - t + 2*s*t); + derivs[19] = -0.25 * ( 1 + r ) * s * (1 - t )*(2 - r - r*t); + derivs[20] = 0.125 * ( 1 - r*r ) * (1 - t ) * (1 - 2*s - t - 2*s*t); + derivs[21] = -0.25 * ( 1 - r ) * s * (1 - t )*(2 + r + r*t); + + // midsides of triangles + derivs[22] = -0.25 * ( 1 - r ) * (1 - t*t ); + derivs[23] = -0.25 * ( 1 + r ) * (1 - t*t ); + derivs[24] = 0.25 * ( 1 + r ) * (1 - t*t ); + derivs[25] = 0.25 * ( 1 - r ) * (1 - t*t ); + + //t-derivatives + // corners + derivs[26] = 0.125 * (1 - r) * ( 1 - s ) * (1 + r + s + 2*t + r*t + s*t + 2*r*s*t); + derivs[27] = 0.125 * (1 + r) * ( 1 - s ) * (1 - r + s + 2*t - r*t + s*t - 2*r*s*t); + derivs[28] = 0.125 * (1 + r) * ( 1 + s ) * (1 - r - s + 2*t - r*t - s*t + 2*r*s*t); + derivs[29] = 0.125 * (1 - r) * ( 1 + s ) * (1 + r - s + 2*t + r*t - s*t - 2*r*s*t); + derivs[30] = 0.5 + t; + + // midsides of rectangles + derivs[31] = -0.25 * ( 1 - r*r ) * (1 - s ) * (1 + s*t); + derivs[32] = -0.25 * ( 1 + r ) * (1 - s*s ) * (1 - r*t); + derivs[33] = -0.25 * ( 1 - r*r ) * (1 + s ) * (1 - s*t); + derivs[34] = -0.25 * ( 1 - r ) * (1 - s*s ) * (1 + r*t); + + + // midsides of triangles + derivs[35] = -0.5 * ( 1 - r ) * (1 - s ) * t; + derivs[36] = -0.5 * ( 1 + r ) * (1 - s ) * t; + derivs[37] = -0.5 * ( 1 + r ) * (1 + s ) * t; + derivs[38] = -0.5 * ( 1 - r ) * (1 + s ) * t; + +} + +static double vtkQPyramidCellPCoords[39] = {0.0,0.0,0.0, 1.0,0.0,0.0, 1.0,1.0,0.0, + 0.0,1.0,0.0, 0.0,0.0,1.0, 0.5,0.0,0.0, + 1.0,0.5,0.0, 0.5,1.0,0.0, 0.0,0.5,0.0, + 0.0,0.0,0.5, 1.0,0.0,0.5, + 1.0,1.0,0.5, 0.0,1.0,0.5 }; + +//---------------------------------------------------------------------------- +double *vtkQuadraticPyramid::GetParametricCoords() +{ + return vtkQPyramidCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticPyramid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Edge:\n"; + this->Edge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "TriangleFace:\n"; + this->TriangleFace->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Face:\n"; + this->Face->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Tetra:\n"; + this->Tetra->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Pyramid:\n"; + this->Pyramid->PrintSelf(os,indent.GetNextIndent()); + os << indent << "PointData:\n"; + this->PointData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "CellData:\n"; + this->CellData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Scalars:\n"; + this->Scalars->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuadraticPyramid.h b/Filtering/vtkQuadraticPyramid.h new file mode 100644 index 0000000..57ce74e --- /dev/null +++ b/Filtering/vtkQuadraticPyramid.h @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticPyramid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadraticPyramid - cell represents a parabolic, 13-node isoparametric pyramid +// .SECTION Description +// vtkQuadraticPyramid is a concrete implementation of vtkNonLinearCell to +// represent a three-dimensional, 13-node isoparametric parabolic +// pyramid. The interpolation is the standard finite element, quadratic +// isoparametric shape function. The cell includes a mid-edge node. The +// ordering of the thirteen points defining the cell is point ids (0-4,5-12) +// where point ids 0-4 are the five corner vertices of the pyramid; followed by +// eight midedge nodes (5-12). Note that these midedge nodes correspond lie +// on the edges defined by (0,1), (1,2), (2,3), (3,0), (0,4), (1,4), (2,4), +// (3,4). + +// .SECTION See Also +// vtkQuadraticEdge vtkQuadraticTriangle vtkQuadraticTetra +// vtkQuadraticHexahedron vtkQuadraticQuad vtkQuadraticWedge + +// .SECTION Thanks +// The shape functions and derivatives could be implemented thanks to +// the report Pyramid Solid Elements Linear and Quadratic Iso-P Models +// From Center For Aerospace Structures + +#ifndef __vtkQuadraticPyramid_h +#define __vtkQuadraticPyramid_h + +#include "vtkNonLinearCell.h" + +class vtkQuadraticEdge; +class vtkQuadraticQuad; +class vtkQuadraticTriangle; +class vtkTetra; +class vtkPyramid; + +class VTK_FILTERING_EXPORT vtkQuadraticPyramid : public vtkNonLinearCell +{ +public: + static vtkQuadraticPyramid *New(); + vtkTypeRevisionMacro(vtkQuadraticPyramid,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement the vtkCell API. See the vtkCell API for descriptions + // of these methods. + int GetCellType() {return VTK_QUADRATIC_PYRAMID;}; + int GetCellDimension() {return 3;} + int GetNumberOfEdges() {return 8;} + int GetNumberOfFaces() {return 5;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this quadratic triangle using scalar value provided. Like + // contouring, except that it cuts the triangle to produce linear + // triangles. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tets, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Line-edge intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + + // Description: + // Return the center of the quadratic pyramid in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Quadratic pyramid specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[13]); + static void InterpolationDerivs(double pcoords[3], double derivs[39]); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. + void JacobianInverse(double pcoords[3], double **inverse, double derivs[39]); + +protected: + vtkQuadraticPyramid(); + ~vtkQuadraticPyramid(); + + vtkQuadraticEdge *Edge; + vtkQuadraticTriangle *TriangleFace; + vtkQuadraticQuad *Face; + vtkTetra *Tetra; + vtkPyramid *Pyramid; + vtkPointData *PointData; + vtkCellData *CellData; + vtkDoubleArray *CellScalars; + vtkDoubleArray *Scalars; //used to avoid New/Delete in contouring/clipping + + void Subdivide(vtkPointData *inPd, vtkCellData *inCd, vtkIdType cellId, vtkDataArray *cellScalars); + +private: + vtkQuadraticPyramid(const vtkQuadraticPyramid&); // Not implemented. + void operator=(const vtkQuadraticPyramid&); // Not implemented. +}; +//---------------------------------------------------------------------------- +// Return the center of the quadratic pyramid in parametric coordinates. +// +inline int vtkQuadraticPyramid::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 6./13; + pcoords[2] = 3./13; + return 0; +} + + +#endif diff --git a/Filtering/vtkQuadraticQuad.cxx b/Filtering/vtkQuadraticQuad.cxx new file mode 100644 index 0000000..b835847 --- /dev/null +++ b/Filtering/vtkQuadraticQuad.cxx @@ -0,0 +1,563 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticQuad.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadraticQuad.h" + +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPolyData.h" +#include "vtkQuad.h" +#include "vtkQuadraticEdge.h" + +vtkCxxRevisionMacro(vtkQuadraticQuad, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkQuadraticQuad); + +//---------------------------------------------------------------------------- +// Construct the quad with eight points. +vtkQuadraticQuad::vtkQuadraticQuad() +{ + this->Edge = vtkQuadraticEdge::New(); + this->Quad = vtkQuad::New(); + this->PointData = vtkPointData::New(); + this->CellData = vtkCellData::New(); + this->CellScalars = vtkDoubleArray::New(); + this->CellScalars->SetNumberOfTuples(9); + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(4); + + // We add a fictitious ninth point in order to process the cell. The ninth + // point is in the center of the cell. + this->Points->SetNumberOfPoints(9); + this->PointIds->SetNumberOfIds(9); + for (int i = 0; i < 9; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Points->SetNumberOfPoints(8); + this->PointIds->SetNumberOfIds(8); +} + +//---------------------------------------------------------------------------- +vtkQuadraticQuad::~vtkQuadraticQuad() +{ + this->Edge->Delete(); + this->Quad->Delete(); + + this->PointData->Delete(); + this->CellData->Delete(); + this->CellScalars->Delete(); + this->Scalars->Delete(); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticQuad::GetEdge(int edgeId) +{ + edgeId = (edgeId < 0 ? 0 : (edgeId > 3 ? 3 : edgeId )); + int p = (edgeId+1) % 4; + + // load point id's + this->Edge->PointIds->SetId(0,this->PointIds->GetId(edgeId)); + this->Edge->PointIds->SetId(1,this->PointIds->GetId(p)); + this->Edge->PointIds->SetId(2,this->PointIds->GetId(edgeId+4)); + + // load coordinates + this->Edge->Points->SetPoint(0,this->Points->GetPoint(edgeId)); + this->Edge->Points->SetPoint(1,this->Points->GetPoint(p)); + this->Edge->Points->SetPoint(2,this->Points->GetPoint(edgeId+4)); + + return this->Edge; +} + +//---------------------------------------------------------------------------- +static int LinearQuads[4][4] = { {0,4,8,7}, {8,4,1,5}, + {8,5,2,6}, {7,8,6,3} }; + +void vtkQuadraticQuad::Subdivide(double *weights) +{ + int i, j; + double pc[3], x[3]; + + pc[0] = pc[1] = 0.5; + this->InterpolationFunctions(pc, weights); + + double p[3]; + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<8; i++) + { + this->Points->GetPoint(i, p); + for (j=0; j<3; j++) + { + x[j] += p[j] * weights[i]; + } + } + this->Points->SetPoint(8,x); +} + +//---------------------------------------------------------------------------- +int vtkQuadraticQuad::EvaluatePosition(double* x, + double* closestPoint, + int& subId, double pcoords[3], + double& minDist2, + double *weights) +{ + double pc[3], dist2; + int ignoreId, i, returnStatus=0, status; + double tempWeights[4]; + double closest[3]; + + // compute the midquad node + this->Subdivide(weights); + + //four linear quads are used + for (minDist2=VTK_DOUBLE_MAX, i=0; i < 4; i++) + { + this->Quad->Points->SetPoint( + 0,this->Points->GetPoint(LinearQuads[i][0])); + this->Quad->Points->SetPoint( + 1,this->Points->GetPoint(LinearQuads[i][1])); + this->Quad->Points->SetPoint( + 2,this->Points->GetPoint(LinearQuads[i][2])); + this->Quad->Points->SetPoint( + 3,this->Points->GetPoint(LinearQuads[i][3])); + + status = this->Quad->EvaluatePosition(x,closest,ignoreId,pc,dist2, + tempWeights); + if ( status != -1 && dist2 < minDist2 ) + { + returnStatus = status; + minDist2 = dist2; + subId = i; + pcoords[0] = pc[0]; + pcoords[1] = pc[1]; + } + } + + // adjust parametric coordinates + if ( returnStatus != -1 ) + { + if ( subId == 0 ) + { + pcoords[0] /= 2.0; + pcoords[1] /= 2.0; + } + else if ( subId == 1 ) + { + pcoords[0] = 0.5 + (pcoords[0]/2.0); + pcoords[1] /= 2.0; + } + else if ( subId == 2 ) + { + pcoords[0] = 0.5 + (pcoords[0]/2.0); + pcoords[1] = 0.5 + (pcoords[1]/2.0); + } + else + { + pcoords[0] /= 2.0; + pcoords[1] = 0.5 + (pcoords[1]/2.0); + } + pcoords[2] = 0.0; + if(closestPoint!=0) + { + // Compute both closestPoint and weights + this->EvaluateLocation(subId,pcoords,closestPoint,weights); + } + else + { + // Compute weigths only + this->InterpolationFunctions(pcoords,weights); + } + } + + return returnStatus; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticQuad::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double *p = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + + this->InterpolationFunctions(pcoords,weights); + + for (j=0; j<3; j++) + { + x[j] = 0.0; + for (i=0; i<8; i++) + { + x[j] += p[3*i+j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticQuad::CellBoundary(int subId, double pcoords[3], vtkIdList *pts) +{ + return this->Quad->CellBoundary(subId, pcoords, pts); +} + +static double MidPoints[1][3] = { {0.5,0.5,0.0} }; + +//---------------------------------------------------------------------------- +void vtkQuadraticQuad::InterpolateAttributes(vtkPointData *inPd, vtkCellData *inCd, + vtkIdType cellId, vtkDataArray *cellScalars) +{ + int numMidPts, i, j; + double weights[20]; + double x[3]; + double s; + + //Copy point and cell attribute data, first make sure it's empty: + this->PointData->Initialize(); + this->CellData->Initialize(); + this->PointData->CopyAllocate(inPd,9); + this->CellData->CopyAllocate(inCd,4); + + // copy the point data over into point ids 0->7 + for (i=0; i<8; i++) + { + this->PointData->CopyData(inPd,this->PointIds->GetId(i),i); + this->CellScalars->SetValue( i, cellScalars->GetTuple1(i)); + } + // copy the cell data over to the linear cell + this->CellData->CopyData(inCd,cellId,0); + + //Interpolate new values + double p[3]; + for ( numMidPts=0; numMidPts < 1; numMidPts++ ) + { + this->InterpolationFunctions(MidPoints[numMidPts], weights); + + x[0] = x[1] = x[2] = 0.0; + s = 0.0; + for (i=0; i<8; i++) + { + this->Points->GetPoint(i, p); + for (j=0; j<3; j++) + { + x[j] += p[j] * weights[i]; + } + s += cellScalars->GetTuple1(i) * weights[i]; + } + this->Points->SetPoint(8+numMidPts,x); + this->CellScalars->SetValue(8+numMidPts,s); + this->PointData->InterpolatePoint(inPd, 8+numMidPts, + this->PointIds, weights); + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticQuad::Contour(double value, + vtkDataArray* cellScalars, + vtkPointLocator* locator, + vtkCellArray *verts, + vtkCellArray* lines, + vtkCellArray* polys, + vtkPointData* inPd, + vtkPointData* outPd, + vtkCellData* inCd, + vtkIdType cellId, + vtkCellData* outCd) +{ + //interpolate point and cell data + this->InterpolateAttributes(inPd,inCd,cellId,cellScalars); + + //contour each linear quad separately + for (int i=0; i<4; i++) + { + for (int j=0; j<4; j++) + { + this->Quad->Points->SetPoint(j,this->Points->GetPoint(LinearQuads[i][j])); + this->Quad->PointIds->SetId(j,LinearQuads[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearQuads[i][j])); + } + + this->Quad->Contour(value,this->Scalars,locator,verts,lines,polys, + this->PointData,outPd,this->CellData,cellId,outCd); + } +} + +//---------------------------------------------------------------------------- +// Line-line intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. +int vtkQuadraticQuad::IntersectWithLine(double* p1, + double* p2, + double tol, + double& t, + double* x, + double* pcoords, + int& subId) +{ + int subTest, i; + subId = 0; + double weights[8]; + + //first define the midquad point + this->Subdivide(weights); + + //intersect the four linear quads + for (i=0; i < 4; i++) + { + this->Quad->Points->SetPoint(0,this->Points->GetPoint(LinearQuads[i][0])); + this->Quad->Points->SetPoint(1,this->Points->GetPoint(LinearQuads[i][1])); + this->Quad->Points->SetPoint(2,this->Points->GetPoint(LinearQuads[i][2])); + this->Quad->Points->SetPoint(3,this->Points->GetPoint(LinearQuads[i][3])); + + if (this->Quad->IntersectWithLine(p1, p2, tol, t, x, pcoords, subTest) ) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkQuadraticQuad::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + // Create six linear triangles: one at each corner and two + // to cover the remaining quadrilateral. + + // First the corner vertices + ptIds->InsertId(0,this->PointIds->GetId(0)); + ptIds->InsertId(1,this->PointIds->GetId(4)); + ptIds->InsertId(2,this->PointIds->GetId(7)); + pts->InsertPoint(0,this->Points->GetPoint(0)); + pts->InsertPoint(1,this->Points->GetPoint(4)); + pts->InsertPoint(2,this->Points->GetPoint(7)); + + ptIds->InsertId(3,this->PointIds->GetId(4)); + ptIds->InsertId(4,this->PointIds->GetId(1)); + ptIds->InsertId(5,this->PointIds->GetId(5)); + pts->InsertPoint(3,this->Points->GetPoint(4)); + pts->InsertPoint(4,this->Points->GetPoint(1)); + pts->InsertPoint(5,this->Points->GetPoint(5)); + + ptIds->InsertId(6,this->PointIds->GetId(5)); + ptIds->InsertId(7,this->PointIds->GetId(2)); + ptIds->InsertId(8,this->PointIds->GetId(6)); + pts->InsertPoint(6,this->Points->GetPoint(5)); + pts->InsertPoint(7,this->Points->GetPoint(2)); + pts->InsertPoint(8,this->Points->GetPoint(6)); + + ptIds->InsertId(9,this->PointIds->GetId(6)); + ptIds->InsertId(10,this->PointIds->GetId(3)); + ptIds->InsertId(11,this->PointIds->GetId(7)); + pts->InsertPoint(9,this->Points->GetPoint(6)); + pts->InsertPoint(10,this->Points->GetPoint(3)); + pts->InsertPoint(11,this->Points->GetPoint(7)); + + // Now the two remaining triangles + // Choose the triangulation that minimizes the edge length + // across the cell. + double x4[3], x5[3], x6[3], x7[3]; + this->Points->GetPoint(4, x4); + this->Points->GetPoint(5, x5); + this->Points->GetPoint(6, x6); + this->Points->GetPoint(7, x7); + + if ( vtkMath::Distance2BetweenPoints(x4,x6) <= + vtkMath::Distance2BetweenPoints(x5,x7) ) + { + ptIds->InsertId(12,this->PointIds->GetId(4)); + ptIds->InsertId(13,this->PointIds->GetId(6)); + ptIds->InsertId(14,this->PointIds->GetId(7)); + pts->InsertPoint(12,this->Points->GetPoint(4)); + pts->InsertPoint(13,this->Points->GetPoint(6)); + pts->InsertPoint(14,this->Points->GetPoint(7)); + + ptIds->InsertId(15,this->PointIds->GetId(4)); + ptIds->InsertId(16,this->PointIds->GetId(5)); + ptIds->InsertId(17,this->PointIds->GetId(6)); + pts->InsertPoint(15,this->Points->GetPoint(4)); + pts->InsertPoint(16,this->Points->GetPoint(5)); + pts->InsertPoint(17,this->Points->GetPoint(6)); + } + else + { + ptIds->InsertId(12,this->PointIds->GetId(5)); + ptIds->InsertId(13,this->PointIds->GetId(6)); + ptIds->InsertId(14,this->PointIds->GetId(7)); + pts->InsertPoint(12,this->Points->GetPoint(5)); + pts->InsertPoint(13,this->Points->GetPoint(6)); + pts->InsertPoint(14,this->Points->GetPoint(7)); + + ptIds->InsertId(15,this->PointIds->GetId(5)); + ptIds->InsertId(16,this->PointIds->GetId(7)); + ptIds->InsertId(17,this->PointIds->GetId(4)); + pts->InsertPoint(15,this->Points->GetPoint(5)); + pts->InsertPoint(16,this->Points->GetPoint(7)); + pts->InsertPoint(17,this->Points->GetPoint(4)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticQuad::Derivatives(int vtkNotUsed(subId), + double pcoords[3], double *values, + int dim, double *derivs) +{ + double x0[3], x1[3], x2[3], deltaX[3], weights[8]; + int i, j; + double functionDerivs[16]; + + this->Points->GetPoint(0, x0); + this->Points->GetPoint(1, x1); + this->Points->GetPoint(2, x2); + + this->InterpolationFunctions(pcoords,weights); + this->InterpolationDerivs(pcoords,functionDerivs); + + for (i=0; i<3; i++) + { + deltaX[i] = x1[i] - x0[i] - x2[i]; + } + for (i=0; iInterpolateAttributes(inPd,inCd,cellId,cellScalars); + + //contour each linear quad separately + for (int i=0; i<4; i++) + { + for ( int j=0; j<4; j++) //for each of the four vertices of the linear quad + { + this->Quad->Points->SetPoint(j,this->Points->GetPoint(LinearQuads[i][j])); + this->Quad->PointIds->SetId(j,LinearQuads[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearQuads[i][j])); + } + + this->Quad->Clip(value,this->Scalars,locator,polys,this->PointData, + outPd,this->CellData,cellId,outCd,insideOut); + } +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions. The first four nodes are the corner +// vertices; the others are mid-edge nodes. +void vtkQuadraticQuad::InterpolationFunctions(double pcoords[3], + double weights[8]) +{ + //VTK needs parametric coordinates to be between (0,1). Isoparametric + //shape functions are formulated between (-1,1). Here we do a + //coordinate system conversion from (0,1) to (-1,1). + double r = pcoords[0]; + double s = pcoords[1]; + + //midedge weights + weights[4] = 4 * r * (1.0 - r) * (1.0 - s); + weights[5] = 4 * r * (1.0 - s) * s; + weights[6] = 4 * r * (1.0 - r) * s; + weights[7] = 4 * (1.0 - r) * (1.0 - s) * s; + + //corner + weights[0] = (1.0 - r) * (1.0 - s) - 0.5*(weights[4]+weights[7]); + weights[1] = r * (1.0 - s) - 0.5*(weights[4]+weights[5]); + weights[2] = r * s - 0.5*(weights[5]+weights[6]); + weights[3] = (1.0 - r) * s - 0.5*(weights[6]+weights[7]);; + +} + +//---------------------------------------------------------------------------- +// Derivatives in parametric space. +void vtkQuadraticQuad::InterpolationDerivs(double pcoords[3], double derivs[16]) +{ + // Coordinate conversion + double r = pcoords[0]; + double s = pcoords[1]; + + // Derivatives in the r-direction + // midedge + derivs[4] = 4 * (1.0 - s) * (1.0 - 2*r); + derivs[5] = 4 * (1.0 - s) * s; + derivs[6] = 4 * s * (1.0 - 2*r); + derivs[7] =-4 * (1.0 - s) * s; + derivs[0] =-(1.0 - s) - 0.5*(derivs[4]+derivs[7]); + derivs[1] = (1.0 - s) - 0.5 * (derivs[4] + derivs[5]); + derivs[2] = s - 0.5 * (derivs[5] + derivs[6]); + derivs[3] = -s - 0.5 * (derivs[6] + derivs[7]); + + // Derivatives in the s-direction + // midedge + derivs[12] =-4 * r * (1.0 - r); + derivs[13] = 4 * r * (1.0 - 2*s); + derivs[14] = 4 * r * (1.0 - r); + derivs[15] = 4 * (1.0 - r) * (1.0 - 2*s); + derivs[8] = -(1.0 - r) - 0.5 * (derivs[15] + derivs[12]); + derivs[9] = - r - 0.5 * (derivs[12] + derivs[13]); + derivs[10] = r - 0.5 * (derivs[13] + derivs[14]); + derivs[11] = (1.0 - r) - 0.5 * (derivs[14] + derivs[15]); +} + +//---------------------------------------------------------------------------- +static double vtkQQuadCellPCoords[24] = {0.0,0.0,0.0, 1.0,0.0,0.0, + 1.0,1.0,0.0, 0.0,1.0,0.0, + 0.5,0.0,0.0, 1.0,0.5,0.0, + 0.5,1.0,0.0, 0.0,0.5,0.0}; +double *vtkQuadraticQuad::GetParametricCoords() +{ + return vtkQQuadCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticQuad::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Edge:\n"; + this->Edge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Quad:\n"; + this->Quad->PrintSelf(os,indent.GetNextIndent()); + os << indent << "PointData:\n"; + this->PointData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "CellData:\n"; + this->CellData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Scalars:\n"; + this->Scalars->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuadraticQuad.h b/Filtering/vtkQuadraticQuad.h new file mode 100644 index 0000000..2ce7c20 --- /dev/null +++ b/Filtering/vtkQuadraticQuad.h @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticQuad.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadraticQuad - cell represents a parabolic, 8-node isoparametric quad +// .SECTION Description +// vtkQuadraticQuad is a concrete implementation of vtkNonLinearCell to +// represent a two-dimensional, 8-node isoparametric parabolic quadrilateral +// element. The interpolation is the standard finite element, quadratic +// isoparametric shape function. The cell includes a mid-edge node for each +// of the four edges of the cell. The ordering of the eight points defining +// the cell are point ids (0-3,4-7) where ids 0-3 define the four corner +// vertices of the quad; ids 4-7 define the midedge nodes (0,1), (1,2), +// (2,3), (3,0). + +// .SECTION See Also +// vtkQuadraticEdge vtkQuadraticTriangle vtkQuadraticTetra +// vtkQuadraticHexahedron vtkQuadraticWedge vtkQuadraticPyramid + + +#ifndef __vtkQuadraticQuad_h +#define __vtkQuadraticQuad_h + +#include "vtkNonLinearCell.h" + +class vtkQuadraticEdge; +class vtkQuad; + +class VTK_FILTERING_EXPORT vtkQuadraticQuad : public vtkNonLinearCell +{ +public: + static vtkQuadraticQuad *New(); + vtkTypeRevisionMacro(vtkQuadraticQuad,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement the vtkCell API. See the vtkCell API for descriptions + // of these methods. + int GetCellType() {return VTK_QUADRATIC_QUAD;}; + int GetCellDimension() {return 2;} + int GetNumberOfEdges() {return 4;} + int GetNumberOfFaces() {return 0;} + vtkCell *GetEdge(int); + vtkCell *GetFace(int) {return 0;} + + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this quadratic quad using scalar value provided. Like contouring, + // except that it cuts the quad to produce linear triangles. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Line-edge intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + + // Description: + // Return the center of the pyramid in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Quadratic quad specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[8]); + static void InterpolationDerivs(double pcoords[3], double derivs[16]); + +protected: + vtkQuadraticQuad(); + ~vtkQuadraticQuad(); + + vtkQuadraticEdge *Edge; + vtkQuad *Quad; + vtkPointData *PointData; + vtkDoubleArray *Scalars; + + // In order to achieve some functionality we introduce a fake center point + // which require to have some extra functionalities compare to other non-linar + // cells + vtkCellData *CellData; + vtkDoubleArray *CellScalars; + void Subdivide(double *weights); + void InterpolateAttributes(vtkPointData *inPd, vtkCellData *inCd, vtkIdType cellId, + vtkDataArray *cellScalars); + +private: + vtkQuadraticQuad(const vtkQuadraticQuad&); // Not implemented. + void operator=(const vtkQuadraticQuad&); // Not implemented. +}; +//---------------------------------------------------------------------------- +inline int vtkQuadraticQuad::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.5; + pcoords[2] = 0.; + return 0; +} + +#endif + + diff --git a/Filtering/vtkQuadraticTetra.cxx b/Filtering/vtkQuadraticTetra.cxx new file mode 100644 index 0000000..afda86b --- /dev/null +++ b/Filtering/vtkQuadraticTetra.cxx @@ -0,0 +1,587 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticTetra.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadraticTetra.h" +#include "vtkPolyData.h" +#include "vtkPointLocator.h" +#include "vtkMath.h" +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticTriangle.h" +#include "vtkTetra.h" +#include "vtkDoubleArray.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkQuadraticTetra, "$Revision: 1.3.8.1 $"); +vtkStandardNewMacro(vtkQuadraticTetra); + +//---------------------------------------------------------------------------- +// Construct the tetra with ten points. +vtkQuadraticTetra::vtkQuadraticTetra() +{ + this->Edge = vtkQuadraticEdge::New(); + this->Face = vtkQuadraticTriangle::New(); + this->Tetra = vtkTetra::New(); + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(4); + + this->Points->SetNumberOfPoints(10); + this->PointIds->SetNumberOfIds(10); + for (int i = 0; i < 10; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } +} + +//---------------------------------------------------------------------------- +vtkQuadraticTetra::~vtkQuadraticTetra() +{ + this->Edge->Delete(); + this->Face->Delete(); + this->Tetra->Delete(); + this->Scalars->Delete(); +} + +//---------------------------------------------------------------------------- +//clip each of the four vertices; the remaining octahedron is +//divided into four tetrahedron. +static int LinearTetras[8][4] = { {0,4,6,7}, {4,1,5,8}, {6,5,2,9}, {7,8,9,3}, + {6,4,5,8}, {6,5,9,8}, {6,9,7,8}, {6,7,4,8} }; + +static int TetraFaces[4][6] = { {0,1,3,4,8,7}, {1,2,3,5,9,8}, + {2,0,3,6,7,9}, {0,2,1,6,5,4} }; + +static int TetraEdges[6][3] = { {0,1,4}, {1,2,5}, {2,0,6}, + {0,3,7}, {1,3,8}, {2,3,9} }; + + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticTetra::GetEdge(int edgeId) +{ + edgeId = (edgeId < 0 ? 0 : (edgeId > 5 ? 5 : edgeId )); + + // load point id's + this->Edge->PointIds->SetId(0,this->PointIds->GetId(TetraEdges[edgeId][0])); + this->Edge->PointIds->SetId(1,this->PointIds->GetId(TetraEdges[edgeId][1])); + this->Edge->PointIds->SetId(2,this->PointIds->GetId(TetraEdges[edgeId][2])); + + // load coordinates + this->Edge->Points->SetPoint(0,this->Points->GetPoint(TetraEdges[edgeId][0])); + this->Edge->Points->SetPoint(1,this->Points->GetPoint(TetraEdges[edgeId][1])); + this->Edge->Points->SetPoint(2,this->Points->GetPoint(TetraEdges[edgeId][2])); + + return this->Edge; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticTetra::GetFace(int faceId) +{ + faceId = (faceId < 0 ? 0 : (faceId > 3 ? 3 : faceId )); + + // load point id's and coordinates + for (int i=0; i< 6; i++) + { + this->Face->PointIds->SetId( + i,this->PointIds->GetId(TetraFaces[faceId][i])); + this->Face->Points->SetPoint( + i,this->Points->GetPoint(TetraFaces[faceId][i])); + } + + return this->Face; +} + +//---------------------------------------------------------------------------- +static const double VTK_DIVERGED = 1.e6; +static const int VTK_TETRA_MAX_ITERATION=10; +static const double VTK_TETRA_CONVERGED=1.e-03; + +int vtkQuadraticTetra::EvaluatePosition(double* x, + double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[30]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.25; + // enter iteration loop + for (iteration=converged=0; + !converged && (iteration < VTK_TETRA_MAX_ITERATION); iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<10; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+10]; + tcol[j] += pt[j] * derivs[i+20]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - 0.5*vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - 0.5*vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - 0.5*vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_TETRA_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_TETRA_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_TETRA_CONVERGED) ) + { + converged = 1; + } + + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside tetra + } + return 1; + } + else + { + double pc[3], w[10]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped tetra + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTetra::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<10; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticTetra::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + return this->Tetra->CellBoundary(subId, pcoords, pts); +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTetra::Contour(double value, vtkDataArray* cellScalars, + vtkPointLocator* locator, + vtkCellArray *verts, vtkCellArray* lines, + vtkCellArray* polys, + vtkPointData* inPd, vtkPointData* outPd, + vtkCellData* inCd, vtkIdType cellId, + vtkCellData* outCd) +{ + for ( int i=0; i < 8; i++) //for each subdivided tetra + { + for ( int j=0; j<4; j++) //for each of the four vertices of the tetra + { + this->Tetra->Points->SetPoint(j,this->Points->GetPoint(LinearTetras[i][j])); + this->Tetra->PointIds->SetId(j,this->PointIds->GetId(LinearTetras[i][j])); + this->Scalars->SetValue(j,cellScalars->GetTuple1(LinearTetras[i][j])); + } + this->Tetra->Contour(value, this->Scalars, locator, verts, + lines, polys, inPd, outPd, inCd, cellId, outCd); + } +} + +//---------------------------------------------------------------------------- +// Line-line intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. +int vtkQuadraticTetra::IntersectWithLine(double* p1, double* p2, + double tol, double& t, + double* x, double* pcoords, int& subId) +{ + int intersection=0; + double tTemp; + double pc[3], xTemp[3]; + int faceNum; + + t = VTK_DOUBLE_MAX; + for (faceNum=0; faceNum<4; faceNum++) + { + for (int i=0; i<4; i++) + { + this->Face->Points->SetPoint(i,this->Points->GetPoint(TetraFaces[faceNum][i])); + } + + if ( this->Face->IntersectWithLine(p1, p2, tol, tTemp, + xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 1: + pcoords[0] = 0.0; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 2: + pcoords[0] = pc[0]; pcoords[1] = 0.0; pcoords[2] = 0.0; + break; + + case 3: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = pc[2]; + break; + } + } + } + } + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkQuadraticTetra::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + for ( int i=0; i < 8; i++) + { + for ( int j=0; j < 4; j++) + { + ptIds->InsertId(4*i+j,this->PointIds->GetId(LinearTetras[i][j])); + pts->InsertPoint(4*i+j,this->Points->GetPoint(LinearTetras[i][j])); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. +void vtkQuadraticTetra::JacobianInverse(double pcoords[3], double **inverse, + double derivs[60]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords, derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 10; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[10 + j]; + m2[i] += x[i] * derivs[20 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTetra::Derivatives(int vtkNotUsed(subId), + double pcoords[3], double *values, + int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[30], sum[3]; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 10; i++) //loop over interp. function derivatives + { + sum[0] += functionDerivs[i] * values[dim*i + k]; + sum[1] += functionDerivs[10 + i] * values[dim*i + k]; + sum[2] += functionDerivs[20 + i] * values[dim*i + k]; + } + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} + +//---------------------------------------------------------------------------- +// Clip this quadratic tetra using the scalar value provided. Like contouring, +// except that it cuts the tetra to produce other tetra. +void vtkQuadraticTetra::Clip(double value, vtkDataArray* cellScalars, + vtkPointLocator* locator, vtkCellArray* tetras, + vtkPointData* inPd, vtkPointData* outPd, + vtkCellData* inCd, vtkIdType cellId, + vtkCellData* outCd, int insideOut) +{ + for ( int i=0; i < 8; i++) //for each subdivided tetra + { + for ( int j=0; j<4; j++) //for each of the four vertices of the tetra + { + this->Tetra->Points->SetPoint(j,this->Points->GetPoint(LinearTetras[i][j])); + this->Tetra->PointIds->SetId(j,this->PointIds->GetId(LinearTetras[i][j])); + this->Scalars->SetValue(j,cellScalars->GetTuple1(LinearTetras[i][j])); + } + this->Tetra->Clip(value, this->Scalars, locator, tetras, inPd, outPd, + inCd, cellId, outCd, insideOut); + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticTetra::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = pcoords[2] = 0.25; + return 0; +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions. First four nodes are the +// tetrahedron corner vertices; the others are mid-edge nodes. +void vtkQuadraticTetra::InterpolationFunctions(double pcoords[3], + double weights[10]) +{ + double r = pcoords[0]; + double s = pcoords[1]; + double t = pcoords[2]; + double u = 1.0 - r - s - t; + + // corners + weights[0] = u*(2.0*u - 1.0); + weights[1] = r*(2.0*r - 1.0); + weights[2] = s*(2.0*s - 1.0); + weights[3] = t*(2.0*t - 1.0); + + // midedge + weights[4] = 4.0 * u * r; + weights[5] = 4.0 * r * s; + weights[6] = 4.0 * s * u; + weights[7] = 4.0 * u * t; + weights[8] = 4.0 * r * t; + weights[9] = 4.0 * s * t; +} + +//---------------------------------------------------------------------------- +// Derivatives in parametric space. +void vtkQuadraticTetra::InterpolationDerivs(double pcoords[3], double derivs[30]) +{ + double r = pcoords[0]; + double s = pcoords[1]; + double t = pcoords[2]; + + // r-derivatives: dW0/dr to dW9/dr + derivs[0] = 4.0*(r + s + t) - 3.0; + derivs[1] = 4.0*r - 1.0; + derivs[2] = 0.0; + derivs[3] = 0.0; + derivs[4] = 4.0 - 8.0*r - 4.0*s - 4.0*t; + derivs[5] = 4.0*s; + derivs[6] = -4.0*s; + derivs[7] = -4.0*t; + derivs[8] = 4.0*t; + derivs[9] = 0.0; + + // s-derivatives: dW0/ds to dW9/ds + derivs[10] = 4.0*(r + s + t) - 3.0; + derivs[11] = 0.0; + derivs[12] = 4.0*s - 1.0; + derivs[13] = 0.0; + derivs[14] = -4.0*r; + derivs[15] = 4.0*r; + derivs[16] = 4.0 - 4.0*r - 8.0*s - 4.0*t; + derivs[17] = -4.0*t; + derivs[18] = 0.0; + derivs[19] = 4.0*t; + + // t-derivatives: dW0/dt to dW9/dt + derivs[20] = 4.0*(r + s + t) - 3.0; + derivs[21] = 0.0; + derivs[22] = 0.0; + derivs[23] = 4.0*t - 1.0; + derivs[24] = -4.0*r; + derivs[25] = 0.0; + derivs[26] = -4.0*s; + derivs[27] = 4.0 - 4.0*r - 4.0*s - 8.0*t; + derivs[28] = 4.0*r; + derivs[29] = 4.0*s; +} + +//---------------------------------------------------------------------------- +double vtkQuadraticTetra::GetParametricDistance(double pcoords[3]) +{ + int i; + double pDist, pDistMax=0.0; + double pc[4]; + + pc[0] = pcoords[0]; + pc[1] = pcoords[1]; + pc[2] = pcoords[2]; + pc[3] = 1.0 - pcoords[0] - pcoords[1] - pcoords[2]; + + for (i=0; i<4; i++) + { + if ( pc[i] < 0.0 ) + { + pDist = -pc[i]; + } + else if ( pc[i] > 1.0 ) + { + pDist = pc[i] - 1.0; + } + else //inside the cell in the parametric direction + { + pDist = 0.0; + } + if ( pDist > pDistMax ) + { + pDistMax = pDist; + } + } + + return pDistMax; +} + +//---------------------------------------------------------------------------- +static double vtkQTetraCellPCoords[30] = { + 0.0,0.0,0.0, 1.0,0.0,0.0, 0.0,1.0,0.0, + 0.0,0.0,1.0, 0.5,0.0,0.0, 0.5,0.5,0.0, + 0.0,0.5,0.0, 0.0,0.0,0.5, 0.5,0.0,0.5, + 0.0,0.5,0.5}; +double *vtkQuadraticTetra::GetParametricCoords() +{ + return vtkQTetraCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTetra::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Edge:\n"; + this->Edge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Face:\n"; + this->Face->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Tetra:\n"; + this->Tetra->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Scalars:\n"; + this->Scalars->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuadraticTetra.h b/Filtering/vtkQuadraticTetra.h new file mode 100644 index 0000000..4ed51a6 --- /dev/null +++ b/Filtering/vtkQuadraticTetra.h @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticTetra.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadraticTetra - cell represents a parabolic, 10-node isoparametric tetrahedron +// .SECTION Description +// vtkQuadraticTetra is a concrete implementation of vtkNonLinearCell to +// represent a three-dimensional, 10-node, isoparametric parabolic +// tetrahedron. The interpolation is the standard finite element, quadratic +// isoparametric shape function. The cell includes a mid-edge node on each of +// the size edges of the tetrahedron. The ordering of the ten points defining +// the cell is point ids (0-3,4-9) where ids 0-3 are the four tetra +// vertices; and point ids 4-9 are the midedge nodes between (0,1), (1,2), +// (2,0), (0,3), (1,3), and (2,3). +// +// .SECTION See Also +// vtkQuadraticEdge vtkQuadraticTriangle vtkQuadraticWedge +// vtkQuadraticQuad vtkQuadraticHexahedron vtkQuadraticPyramid + +#ifndef __vtkQuadraticTetra_h +#define __vtkQuadraticTetra_h + +#include "vtkNonLinearCell.h" + +class vtkPolyData; +class vtkQuadraticEdge; +class vtkQuadraticTriangle; +class vtkTetra; +class vtkDoubleArray; + +class VTK_FILTERING_EXPORT vtkQuadraticTetra : public vtkNonLinearCell +{ +public: + static vtkQuadraticTetra *New(); + vtkTypeRevisionMacro(vtkQuadraticTetra,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement the vtkCell API. See the vtkCell API for descriptions + // of these methods. + int GetCellType() {return VTK_QUADRATIC_TETRA;} + int GetCellDimension() {return 3;} + int GetNumberOfEdges() {return 6;} + int GetNumberOfFaces() {return 4;} + vtkCell *GetEdge(int); + vtkCell *GetFace(int); + + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this edge using scalar value provided. Like contouring, except + // that it cuts the tetra to produce new tetras. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tetras, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Line-edge intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + + // Description: + // Return the center of the quadratic tetra in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Return the distance of the parametric coordinate provided to the + // cell. If inside the cell, a distance of zero is returned. + double GetParametricDistance(double pcoords[3]); + + // Description: + // Quadratic tetra specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[10]); + static void InterpolationDerivs(double pcoords[3], double derivs[30]); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. + void JacobianInverse(double pcoords[3], double **inverse, double derivs[30]); + +protected: + vtkQuadraticTetra(); + ~vtkQuadraticTetra(); + + vtkQuadraticEdge *Edge; + vtkQuadraticTriangle *Face; + vtkTetra *Tetra; + vtkDoubleArray *Scalars; //used to avoid New/Delete in contouring/clipping + +private: + vtkQuadraticTetra(const vtkQuadraticTetra&); // Not implemented. + void operator=(const vtkQuadraticTetra&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkQuadraticTriangle.cxx b/Filtering/vtkQuadraticTriangle.cxx new file mode 100644 index 0000000..be8b2eb --- /dev/null +++ b/Filtering/vtkQuadraticTriangle.cxx @@ -0,0 +1,404 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticTriangle.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadraticTriangle.h" + +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include "vtkLine.h" +#include "vtkQuadraticEdge.h" +#include "vtkTriangle.h" +#include "vtkDoubleArray.h" + +vtkCxxRevisionMacro(vtkQuadraticTriangle, "$Revision: 1.4.8.2 $"); +vtkStandardNewMacro(vtkQuadraticTriangle); + +//---------------------------------------------------------------------------- +// Construct the line with two points. +vtkQuadraticTriangle::vtkQuadraticTriangle() +{ + this->Edge = vtkQuadraticEdge::New(); + this->Face = vtkTriangle::New(); + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(3); + + this->Points->SetNumberOfPoints(6); + this->PointIds->SetNumberOfIds(6); + for (int i = 0; i < 6; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } +} + +//---------------------------------------------------------------------------- +vtkQuadraticTriangle::~vtkQuadraticTriangle() +{ + this->Edge->Delete(); + this->Face->Delete(); + this->Scalars->Delete(); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticTriangle::GetEdge(int edgeId) +{ + edgeId = (edgeId < 0 ? 0 : (edgeId > 2 ? 2 : edgeId )); + int p = (edgeId+1) % 3; + + // load point id's + this->Edge->PointIds->SetId(0,this->PointIds->GetId(edgeId)); + this->Edge->PointIds->SetId(1,this->PointIds->GetId(p)); + this->Edge->PointIds->SetId(2,this->PointIds->GetId(edgeId+3)); + + // load coordinates + this->Edge->Points->SetPoint(0,this->Points->GetPoint(edgeId)); + this->Edge->Points->SetPoint(1,this->Points->GetPoint(p)); + this->Edge->Points->SetPoint(2,this->Points->GetPoint(edgeId+3)); + + return this->Edge; +} + +//---------------------------------------------------------------------------- +// order picked carefully for parametric coordinate conversion +static int LinearTris[4][3] = { {0,3,5}, {3, 1,4}, {5,4,2}, {4,5,3} }; + +int vtkQuadraticTriangle::EvaluatePosition(double* x, double* closestPoint, + int& subId, double pcoords[3], + double& minDist2, double *weights) +{ + double pc[3], dist2; + int ignoreId, i, returnStatus=0, status; + double tempWeights[3]; + double closest[3]; + + //four linear triangles are used + for (minDist2=VTK_DOUBLE_MAX, i=0; i < 4; i++) + { + this->Face->Points->SetPoint( + 0,this->Points->GetPoint(LinearTris[i][0])); + this->Face->Points->SetPoint( + 1,this->Points->GetPoint(LinearTris[i][1])); + this->Face->Points->SetPoint( + 2,this->Points->GetPoint(LinearTris[i][2])); + + status = this->Face->EvaluatePosition(x,closest,ignoreId,pc,dist2, + tempWeights); + if ( status != -1 && dist2 < minDist2 ) + { + returnStatus = status; + minDist2 = dist2; + subId = i; + pcoords[0] = pc[0]; + pcoords[1] = pc[1]; + } + } + + // adjust parametric coordinates + if ( returnStatus != -1 ) + { + if ( subId == 0 ) + { + pcoords[0] /= 2.0; + pcoords[1] /= 2.0; + } + else if ( subId == 1 ) + { + pcoords[0] = 0.5 + (pcoords[0]/2.0); + pcoords[1] /= 2.0; + } + else if ( subId == 2 ) + { + pcoords[0] /= 2.0; + pcoords[1] = 0.5 + (pcoords[1]/2.0); + } + else + { + pcoords[0] = 0.5 - pcoords[0]/2.0; + pcoords[1] = 0.5 - pcoords[1]/2.0; + } + pcoords[2] = 1.0 - pcoords[0] - pcoords[1]; + if(closestPoint!=0) + { + // Compute both closestPoint and weights + this->EvaluateLocation(subId,pcoords,closestPoint,weights); + } + else + { + // Compute weights only + this->InterpolationFunctions(pcoords,weights); + } + } + + return returnStatus; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTriangle::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], + double x[3], double *weights) +{ + int i; + double a0[3], a1[3], a2[3], a3[3], a4[3], a5[3]; + this->Points->GetPoint(0, a0); + this->Points->GetPoint(1, a1); + this->Points->GetPoint(2, a2); + this->Points->GetPoint(3, a3); + this->Points->GetPoint(4, a4); + this->Points->GetPoint(5, a5); + + this->InterpolationFunctions(pcoords,weights); + + for (i=0; i<3; i++) + { + x[i] = a0[i]*weights[0] + a1[i]*weights[1] + a2[i]*weights[2] + + a3[i]*weights[3] + a4[i]*weights[4] + a5[i]*weights[5]; + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticTriangle::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + return this->Face->CellBoundary(subId, pcoords, pts); +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTriangle::Contour(double value, + vtkDataArray* cellScalars, + vtkPointLocator* locator, + vtkCellArray *verts, + vtkCellArray* lines, + vtkCellArray* polys, + vtkPointData* inPd, + vtkPointData* outPd, + vtkCellData* inCd, + vtkIdType cellId, + vtkCellData* outCd) +{ + for ( int i=0; i < 4; i++) + { + this->Face->Points->SetPoint(0,this->Points->GetPoint(LinearTris[i][0])); + this->Face->Points->SetPoint(1,this->Points->GetPoint(LinearTris[i][1])); + this->Face->Points->SetPoint(2,this->Points->GetPoint(LinearTris[i][2])); + + if ( outPd ) + { + this->Face->PointIds->SetId(0,this->PointIds->GetId(LinearTris[i][0])); + this->Face->PointIds->SetId(1,this->PointIds->GetId(LinearTris[i][1])); + this->Face->PointIds->SetId(2,this->PointIds->GetId(LinearTris[i][2])); + } + + this->Scalars->SetTuple(0,cellScalars->GetTuple(LinearTris[i][0])); + this->Scalars->SetTuple(1,cellScalars->GetTuple(LinearTris[i][1])); + this->Scalars->SetTuple(2,cellScalars->GetTuple(LinearTris[i][2])); + + this->Face->Contour(value, this->Scalars, locator, verts, + lines, polys, inPd, outPd, inCd, cellId, outCd); + } +} + +//---------------------------------------------------------------------------- +// Line-line intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. +int vtkQuadraticTriangle::IntersectWithLine(double* p1, + double* p2, + double tol, + double& t, + double* x, + double* pcoords, + int& subId) +{ + int subTest, i; + subId = 0; + + for (i=0; i < 4; i++) + { + this->Face->Points->SetPoint(0,this->Points->GetPoint(LinearTris[i][0])); + this->Face->Points->SetPoint(1,this->Points->GetPoint(LinearTris[i][1])); + this->Face->Points->SetPoint(2,this->Points->GetPoint(LinearTris[i][2])); + + if (this->Face->IntersectWithLine(p1, p2, tol, t, x, pcoords, subTest) ) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkQuadraticTriangle::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + // Create four linear triangles + for ( int i=0; i < 4; i++) + { + ptIds->InsertId(3*i,this->PointIds->GetId(LinearTris[i][0])); + pts->InsertPoint(3*i,this->Points->GetPoint(LinearTris[i][0])); + ptIds->InsertId(3*i+1,this->PointIds->GetId(LinearTris[i][1])); + pts->InsertPoint(3*i+1,this->Points->GetPoint(LinearTris[i][1])); + ptIds->InsertId(3*i+2,this->PointIds->GetId(LinearTris[i][2])); + pts->InsertPoint(3*i+2,this->Points->GetPoint(LinearTris[i][2])); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTriangle::Derivatives(int vtkNotUsed(subId), + double pcoords[3], + double *vtkNotUsed(values), + int vtkNotUsed(dim), + double *vtkNotUsed(derivs)) +{ + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; +} + + +//---------------------------------------------------------------------------- +// Clip this quadratic triangle using the scalar value provided. Like +// contouring, except that it cuts the triangle to produce other quads +// and triangles. +void vtkQuadraticTriangle::Clip(double value, + vtkDataArray* cellScalars, + vtkPointLocator* locator, + vtkCellArray* polys, + vtkPointData* inPd, + vtkPointData* outPd, + vtkCellData* inCd, + vtkIdType cellId, + vtkCellData* outCd, + int insideOut) +{ + for ( int i=0; i < 4; i++) + { + this->Face->Points->SetPoint(0,this->Points->GetPoint(LinearTris[i][0])); + this->Face->Points->SetPoint(1,this->Points->GetPoint(LinearTris[i][1])); + this->Face->Points->SetPoint(2,this->Points->GetPoint(LinearTris[i][2])); + + this->Face->PointIds->SetId(0,this->PointIds->GetId(LinearTris[i][0])); + this->Face->PointIds->SetId(1,this->PointIds->GetId(LinearTris[i][1])); + this->Face->PointIds->SetId(2,this->PointIds->GetId(LinearTris[i][2])); + + this->Scalars->SetTuple(0,cellScalars->GetTuple(LinearTris[i][0])); + this->Scalars->SetTuple(1,cellScalars->GetTuple(LinearTris[i][1])); + this->Scalars->SetTuple(2,cellScalars->GetTuple(LinearTris[i][2])); + + this->Face->Clip(value, this->Scalars, locator, polys, inPd, outPd, + inCd, cellId, outCd, insideOut); + } +} + +//---------------------------------------------------------------------------- +// Compute maximum parametric distance to cell +double vtkQuadraticTriangle::GetParametricDistance(double pcoords[3]) +{ + int i; + double pDist, pDistMax=0.0; + double pc[3]; + + pc[0] = pcoords[0]; + pc[1] = pcoords[1]; + pc[2] = 1.0 - pcoords[0] - pcoords[1]; + + for (i=0; i<3; i++) + { + if ( pc[i] < 0.0 ) + { + pDist = -pc[i]; + } + else if ( pc[i] > 1.0 ) + { + pDist = pc[i] - 1.0; + } + else //inside the cell in the parametric direction + { + pDist = 0.0; + } + if ( pDist > pDistMax ) + { + pDistMax = pDist; + } + } + + return pDistMax; +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions. The first three nodes are the triangle +// vertices; the others are mid-edge nodes. +void vtkQuadraticTriangle::InterpolationFunctions(double pcoords[3], + double weights[6]) +{ + double r = pcoords[0]; + double s = pcoords[1]; + double t = 1.0 - r - s; + + weights[0] = t*(2.0*t - 1.0); + weights[1] = r*(2.0*r - 1.0); + weights[2] = s*(2.0*s - 1.0); + weights[3] = 4.0 * r * t; + weights[4] = 4.0 * r * s; + weights[5] = 4.0 * s * t; +} + +//---------------------------------------------------------------------------- +// Derivatives in parametric space. +void vtkQuadraticTriangle::InterpolationDerivs(double pcoords[3], + double derivs[12]) +{ + double r = pcoords[0]; + double s = pcoords[1]; + + // r-derivatives + derivs[0] = 4.0*r + 4.0*s - 3.0; + derivs[1] = 4.0*r - 1.0; + derivs[2] = 0.0; + derivs[3] = 4.0 - 8.0*r - 4.0*s; + derivs[4] = 4.0*s; + derivs[5] = -4.0*s; + + // s-derivatives + derivs[6] = 4.0*r + 4.0*s - 3.0; + derivs[7] = 0.0; + derivs[8] = 4.0*s - 1.0; + derivs[9] = -4.0*r; + derivs[10] = 4.0*r; + derivs[11] = 4.0 - 8.0*s - 4.0*r; +} + +//---------------------------------------------------------------------------- +static double vtkQTriangleCellPCoords[18] = { + 0.0,0.0,0.0, 1.0,0.0,0.0, 0.0,1.0,0.0, + 0.5,0.0,0.0, 0.5,0.5,0.0, 0.0,0.5,0.0}; +double *vtkQuadraticTriangle::GetParametricCoords() +{ + return vtkQTriangleCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticTriangle::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Edge:\n"; + this->Edge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Edge:\n"; + this->Edge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Scalars:\n"; + this->Scalars->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuadraticTriangle.h b/Filtering/vtkQuadraticTriangle.h new file mode 100644 index 0000000..ebc05a1 --- /dev/null +++ b/Filtering/vtkQuadraticTriangle.h @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticTriangle.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadraticTriangle - cell represents a parabolic, isoparametric triangle +// .SECTION Description +// vtkQuadraticTriangle is a concrete implementation of vtkNonLinearCell to +// represent a two-dimensional, 6-node, isoparametric parabolic triangle. The +// interpolation is the standard finite element, quadratic isoparametric +// shape function. The cell includes three mid-edge nodes besides the three +// triangle vertices. The ordering of the three points defining the cell is +// point ids (0-2,3-5) where id #3 is the midedge node between points +// (0,1); id #4 is the midedge node between points (1,2); and id #5 is the +// midedge node between points (2,0). + +// .SECTION See Also +// vtkQuadraticEdge vtkQuadraticTetra vtkQuadraticPyramid +// vtkQuadraticQuad vtkQuadraticHexahedron vtkQuadraticWedge + +#ifndef __vtkQuadraticTriangle_h +#define __vtkQuadraticTriangle_h + +#include "vtkNonLinearCell.h" + +class vtkQuadraticEdge; +class vtkTriangle; +class vtkDoubleArray; + +class VTK_FILTERING_EXPORT vtkQuadraticTriangle : public vtkNonLinearCell +{ +public: + static vtkQuadraticTriangle *New(); + vtkTypeRevisionMacro(vtkQuadraticTriangle,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement the vtkCell API. See the vtkCell API for descriptions + // of these methods. + int GetCellType() {return VTK_QUADRATIC_TRIANGLE;}; + int GetCellDimension() {return 2;} + int GetNumberOfEdges() {return 3;} + int GetNumberOfFaces() {return 0;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int) {return 0;} + + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this quadratic triangle using scalar value provided. Like + // contouring, except that it cuts the triangle to produce linear + // triangles. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Line-edge intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + + // Description: + // Return the center of the quadratic triangle in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Return the distance of the parametric coordinate provided to the + // cell. If inside the cell, a distance of zero is returned. + double GetParametricDistance(double pcoords[3]); + + // Description: + // Quadratic triangle specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[6]); + static void InterpolationDerivs(double pcoords[3], double derivs[12]); + +protected: + vtkQuadraticTriangle(); + ~vtkQuadraticTriangle(); + + vtkQuadraticEdge *Edge; + vtkTriangle *Face; + vtkDoubleArray *Scalars; //used to avoid New/Delete in contouring/clipping + +private: + vtkQuadraticTriangle(const vtkQuadraticTriangle&); // Not implemented. + void operator=(const vtkQuadraticTriangle&); // Not implemented. +}; +//---------------------------------------------------------------------------- +inline int vtkQuadraticTriangle::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 1./3; + pcoords[2] = 0.0; + return 0; +} + + +#endif + + diff --git a/Filtering/vtkQuadraticWedge.cxx b/Filtering/vtkQuadraticWedge.cxx new file mode 100644 index 0000000..93b541c --- /dev/null +++ b/Filtering/vtkQuadraticWedge.cxx @@ -0,0 +1,707 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticWedge.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadraticWedge.h" + +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkWedge.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticQuad.h" +#include "vtkQuadraticTriangle.h" + +vtkCxxRevisionMacro(vtkQuadraticWedge, "$Revision: 1.6.8.1 $"); +vtkStandardNewMacro(vtkQuadraticWedge); + +//---------------------------------------------------------------------------- +// Construct the wedge with 15 points + 3 extra points for internal +// computation. +vtkQuadraticWedge::vtkQuadraticWedge() +{ + // At times the cell looks like it has 18 points (during interpolation) + // We initially allocate for 18. + this->Points->SetNumberOfPoints(18); + this->PointIds->SetNumberOfIds(18); + for (int i = 0; i < 18; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Points->SetNumberOfPoints(15); + this->PointIds->SetNumberOfIds(15); + + this->Edge = vtkQuadraticEdge::New(); + this->Face = vtkQuadraticQuad::New(); + this->TriangleFace = vtkQuadraticTriangle::New(); + this->Wedge = vtkWedge::New(); + + this->PointData = vtkPointData::New(); + this->CellData = vtkCellData::New(); + this->CellScalars = vtkDoubleArray::New(); + this->CellScalars->SetNumberOfTuples(18); + this->Scalars = vtkDoubleArray::New(); + this->Scalars->SetNumberOfTuples(6); //num of vertices +} + +//---------------------------------------------------------------------------- +vtkQuadraticWedge::~vtkQuadraticWedge() +{ + this->Edge->Delete(); + this->Face->Delete(); + this->TriangleFace->Delete(); + this->Wedge->Delete(); + + this->PointData->Delete(); + this->CellData->Delete(); + this->CellScalars->Delete(); + this->Scalars->Delete(); +} + +//---------------------------------------------------------------------------- +// instead of using an hexahedron we could use two prims/wedge... +static int LinearWedges[8][6] = { {0,6,8,12,15,17}, + {6,7,8,15,16,17}, + {6,1,7,15,13,16}, + {8,7,2,17,16,14}, + {12,15,17,3,9,11}, + {15,16,17,9,10,11}, + {15,13,16,9,4,10}, + {17,16,14,11,10,5} }; + +static int WedgeFaces[5][8] = { {0,1,2,6,7,8,0,0}, + {3,5,4,11,10,9,0,0}, + {0,3,4,1,12,9,13,6}, + {1,4,5,2,13,10,14,7}, + {2,5,3,0,14,11,12,8}}; + +static int WedgeEdges[9][3] = { {0,1,6}, {1,2,7}, {2,0,8}, + {3,4,9}, {4,5,10}, {5,3,11}, + {0,3,12},{1,4,13}, {2,5,14} }; + +static double MidPoints[3][3] = { {0.5,0.0,0.5}, + {0.5,0.5,0.5}, + {0.0,0.5,0.5} }; + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticWedge::GetEdge(int edgeId) +{ + edgeId = (edgeId < 0 ? 0 : (edgeId > 8 ? 8 : edgeId )); + + for (int i=0; i<3; i++) + { + this->Edge->PointIds->SetId(i,this->PointIds->GetId(WedgeEdges[edgeId][i])); + this->Edge->Points->SetPoint(i,this->Points->GetPoint(WedgeEdges[edgeId][i])); + } + + return this->Edge; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkQuadraticWedge::GetFace(int faceId) +{ + faceId = (faceId < 0 ? 0 : (faceId > 4 ? 4 : faceId )); + + // load point id's and coordinates + // be carefull with the last two one: + if(faceId < 2) + { + for (int i=0; i<6; i++) + { + this->TriangleFace->PointIds->SetId(i,this->PointIds->GetId(WedgeFaces[faceId][i])); + this->TriangleFace->Points->SetPoint(i,this->Points->GetPoint(WedgeFaces[faceId][i])); + } + return this->TriangleFace; + } + else + { + for (int i=0; i<8; i++) + { + this->Face->PointIds->SetId(i,this->PointIds->GetId(WedgeFaces[faceId][i])); + this->Face->Points->SetPoint(i,this->Points->GetPoint(WedgeFaces[faceId][i])); + } + return this->Face; + } +} + +//---------------------------------------------------------------------------- +static const double VTK_DIVERGED = 1.e6; +static const int VTK_WEDGE_MAX_ITERATION=10; +static const double VTK_WEDGE_CONVERGED=1.e-03; + +int vtkQuadraticWedge::EvaluatePosition(double* x, + double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[3*15]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = params[0] = params[1] = params[2]=0.5; + + // enter iteration loop + for (iteration=converged=0; + !converged && (iteration < VTK_WEDGE_MAX_ITERATION); iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<15; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+15]; + tcol[j] += pt[j] * derivs[i+30]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - 0.5*vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - 0.5*vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - 0.5*vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_WEDGE_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_WEDGE_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_WEDGE_CONVERGED) ) + { + converged = 1; + } + + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside wedge + } + return 1; + } + else + { + double pc[3], w[15]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticWedge::EvaluateLocation(int& vtkNotUsed(subId), + double pcoords[3], + double x[3], double *weights) +{ + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (int i=0; i<15; i++) + { + this->Points->GetPoint(i, pt); + for (int j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkQuadraticWedge::CellBoundary(int subId, double pcoords[3], + vtkIdList *pts) +{ + return this->Wedge->CellBoundary(subId, pcoords, pts); +} + +//---------------------------------------------------------------------------- +void vtkQuadraticWedge::Subdivide(vtkPointData *inPd, vtkCellData *inCd, + vtkIdType cellId, vtkDataArray *cellScalars) +{ + int numMidPts, i, j; + double weights[15]; + double x[3]; + double s; + + //Copy point and cell attribute data, first make sure it's empty: + this->PointData->Initialize(); + this->CellData->Initialize(); + this->PointData->CopyAllocate(inPd,18); + this->CellData->CopyAllocate(inCd,6); + for (i=0; i<15; i++) + { + this->PointData->CopyData(inPd,this->PointIds->GetId(i),i); + this->CellScalars->SetValue( i, cellScalars->GetTuple1(i)); + } + this->CellData->CopyData(inCd,cellId,0); + + //Interpolate new values + double p[3]; + for ( numMidPts=0; numMidPts < 3; numMidPts++ ) + { + this->InterpolationFunctions(MidPoints[numMidPts], weights); + + x[0] = x[1] = x[2] = 0.0; + s = 0.0; + for (i=0; i<15; i++) + { + this->Points->GetPoint(i, p); + for (j=0; j<3; j++) + { + x[j] += p[j] * weights[i]; + } + s += cellScalars->GetTuple1(i) * weights[i]; + } + this->Points->SetPoint(15+numMidPts,x); + this->CellScalars->SetValue(15+numMidPts,s); + this->PointData->InterpolatePoint(inPd, 15+numMidPts, + this->PointIds, weights); + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticWedge::Contour(double value, + vtkDataArray* cellScalars, + vtkPointLocator* locator, + vtkCellArray *verts, + vtkCellArray* lines, + vtkCellArray* polys, + vtkPointData* inPd, + vtkPointData* outPd, + vtkCellData* inCd, + vtkIdType cellId, + vtkCellData* outCd) +{ + //subdivide into 8 linear wedges + this->Subdivide(inPd,inCd,cellId, cellScalars); + + //contour each linear wedge separately + for (int i=0; i<8; i++) //for each wedge + { + for (int j=0; j<6; j++) //for each point of wedge + { + this->Wedge->Points->SetPoint(j,this->Points->GetPoint(LinearWedges[i][j])); + this->Wedge->PointIds->SetId(j,LinearWedges[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearWedges[i][j])); + } + this->Wedge->Contour(value,this->Scalars,locator,verts,lines,polys, + this->PointData,outPd,this->CellData,cellId,outCd); + } + +} + +//---------------------------------------------------------------------------- +// Line-hex intersection. Intersection has to occur within [0,1] parametric +// coordinates and with specified tolerance. +int vtkQuadraticWedge::IntersectWithLine(double* p1, double* p2, + double tol, double& t, + double* x, double* pcoords, int& subId) +{ + int intersection=0; + double tTemp; + double pc[3], xTemp[3]; + int faceNum; + int inter; + + t = VTK_DOUBLE_MAX; + for (faceNum=0; faceNum<5; faceNum++) + { +// We have 8 nodes on rect face +// and 6 on triangle faces + if(faceNum > 2) + { + for (int i=0; i<6; i++) + { + this->TriangleFace->PointIds->SetId(i, + this->PointIds->GetId(WedgeFaces[faceNum][i])); + } + inter = this->TriangleFace->IntersectWithLine(p1, p2, tol, tTemp, + xTemp, pc, subId); + } + else + { + for (int i=0; i<8; i++) + { + this->Face->Points->SetPoint(i, + this->Points->GetPoint(WedgeFaces[faceNum][i])); + } + inter = this->Face->IntersectWithLine(p1, p2, tol, tTemp, + xTemp, pc, subId); + } + if ( inter ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = 0.0; pcoords[1] = pc[1]; pcoords[2] = pc[0]; + break; + + case 1: + pcoords[0] = 1.0; pcoords[1] = pc[0]; pcoords[2] = pc[1]; + break; + + case 2: + pcoords[0] = pc[0]; pcoords[1] = 0.0; pcoords[2] = pc[1]; + break; + + case 3: + pcoords[0] = pc[1]; pcoords[1] = 1.0; pcoords[2] = pc[0]; + break; + + case 4: + pcoords[0] = pc[1]; pcoords[1] = pc[0]; pcoords[2] = 0.0; + break; + + case 5: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 1.0; + break; + } + } + } + } + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkQuadraticWedge::Triangulate(int vtkNotUsed(index), + vtkIdList *ptIds, vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + for ( int i=0; i < 8; i++) + { + for ( int j=0; j < 6; j++) + { + ptIds->InsertId(6*i+j,this->PointIds->GetId(LinearWedges[i][j])); + pts->InsertPoint(6*i+j,this->Points->GetPoint(LinearWedges[i][j])); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. +void vtkQuadraticWedge::JacobianInverse(double pcoords[3], double **inverse, + double derivs[45]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords, derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 15; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[15 + j]; + m2[i] += x[i] * derivs[30 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadraticWedge::Derivatives(int vtkNotUsed(subId), + double pcoords[3], double *values, + int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[3*15], sum[3]; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 15; i++) //loop over interp. function derivatives + { + sum[0] += functionDerivs[i] * values[dim*i + k]; + sum[1] += functionDerivs[15 + i] * values[dim*i + k]; + sum[2] += functionDerivs[30 + i] * values[dim*i + k]; + } + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} + + +//---------------------------------------------------------------------------- +// Clip this quadratic wedge using scalar value provided. Like contouring, +// except that it cuts the wedge to produce tetrahedra. +void vtkQuadraticWedge::Clip(double value, vtkDataArray* cellScalars, + vtkPointLocator* locator, vtkCellArray* tets, + vtkPointData* inPd, vtkPointData* outPd, + vtkCellData* inCd, vtkIdType cellId, + vtkCellData* outCd, int insideOut) +{ + // create eight linear hexes + this->Subdivide(inPd,inCd,cellId, cellScalars); + + //contour each linear hex separately + for (int i=0; i<8; i++) //for each subdivided wedge + { + for (int j=0; j<6; j++) //for each of the six vertices of the wedge + { + this->Wedge->Points->SetPoint(j,this->Points->GetPoint(LinearWedges[i][j])); + this->Wedge->PointIds->SetId(j,LinearWedges[i][j]); + this->Scalars->SetValue(j,this->CellScalars->GetValue(LinearWedges[i][j])); + } + this->Wedge->Clip(value,this->Scalars,locator,tets,this->PointData,outPd, + this->CellData,cellId,outCd,insideOut); + } + +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions for the fifteen nodes. +void vtkQuadraticWedge::InterpolationFunctions(double pcoords[3], + double weights[15]) +{ + // VTK needs parametric coordinates to be between (0,1). Isoparametric + // shape functions are formulated between (-1,1). Here we do a + // coordinate system conversion from (0,1) to (-1,1). + double r = pcoords[0]; + double s = pcoords[1]; + double t = pcoords[2]; + // corners + weights[0] = 2*(1-r-s)*(1-t)*(.5-r-s-t); + weights[1] = 2*r*(1-t)*(r-t-0.5); + weights[2] = 2*s*(1-t)*(s-t-0.5); + weights[3] = 2*(1-r-s)*t*(t-r-s-0.5); + weights[4] = 2*r*t*(r+t-1.5); + weights[5] = 2*s*t*(s+t-1.5); + + // midsides of triangles + weights[6] = 4*r*(1-r-s)*(1-t); + weights[7] = 4*r*s*(1-t); + weights[8] = 4*(1-r-s)*s*(1-t); + weights[9] = 4*r*(1-r-s)*t; + weights[10] = 4*r*s*t; + weights[11] = 4*(1-r-s)*s*t; + + // midsides of rectangles + weights[12] = 4*t*(1-r-s)*(1-t); + weights[13] = 4*t*r*(1-t); + weights[14] = 4*t*s*(1-t); +} + +//---------------------------------------------------------------------------- +// Derivatives in parametric space. +void vtkQuadraticWedge::InterpolationDerivs(double pcoords[3], + double derivs[45]) +{ + //VTK needs parametric coordinates to be between (0,1). Isoparametric + //shape functions are formulated between (-1,1). Here we do a + //coordinate system conversion from (0,1) to (-1,1). + double r = pcoords[0]; + double s = pcoords[1]; + double t = pcoords[2]; + // r-derivatives + // corners + derivs[0] = 2*(1 - t)*(-1.5 + 2*r + 2*s + t); + derivs[1] = 2*(1 - t)*(-0.5 + 2*r - t); + derivs[2] = 0; + derivs[3] = 2*t*(-0.5 + 2*r + 2*s - t); + derivs[4] = 2*t*(-1.5 + 2*r + t); + derivs[5] = 0; + // midsides of triangles + derivs[6] = 4*(1 - t)*(1 - 2*r - s); + derivs[7] = 4*(1 - t)*s; + derivs[8] = -derivs[7]; + derivs[9] = 4*t*(1 - 2*r - s); + derivs[10] = 4*s*t; + derivs[11] = -derivs[10]; + // midsides of rectangles + derivs[12] = -4*t*(1 - t); + derivs[13] = -derivs[12]; + derivs[14] = 0; + + // s-derivatives + // corners + derivs[15] = derivs[0]; + derivs[16] = 0; + derivs[17] = 2*(1 - t)*(-0.5 + 2*s - t); + derivs[18] = derivs[3]; + derivs[19] = 0; + derivs[20] = 2*t*(-1.5 + 2*s + t); + // midsides of triangles + derivs[21] = -4*(1 - t)*r; + derivs[22] = -derivs[21]; + derivs[23] = 4*(1 - t)*(1 - r - 2*s); + derivs[24] = -4*r*t; + derivs[25] = -derivs[24]; + derivs[26] = 4*t*(1 - r - 2*s); + // midsides of rectangles + derivs[27] = derivs[12]; + derivs[28] = 0; + derivs[29] = -derivs[27]; + + // t-derivatives + // corners + derivs[30] = 2*(1 - r - s)*(-1.5 + r + s + 2*t); + derivs[31] = 2*r*(-0.5 - r + 2*t); + derivs[32] = 2*s*(-0.5 - s + 2*t); + derivs[33] = 2*(1 - r - s)*(-0.5 - r - s + 2*t); + derivs[34] = 2*r*(-1.5 + r + 2*t); + derivs[35] = 2*s*(-1.5 + s + 2*t); + // midsides of triangles + derivs[36] = -4*r*(1 - r - s); + derivs[37] = -4*r*s; + derivs[38] = -4*s*(1 - r - s); + derivs[39] = -derivs[36]; + derivs[40] = -derivs[37]; + derivs[41] = -derivs[38] ; + // midsides of rectangles + derivs[42] = 4*(1 - 2*t)*(1 - r - s); + derivs[43] = 4*(1 - 2*t)*r; + derivs[44] = 4*(1 - 2*t)*s; +} + +//---------------------------------------------------------------------------- +static double vtkQWedgeCellPCoords[45] = {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,1.0, 0.0,1.0,1.0, + 0.5,0.0,0.0, 0.5,0.5,0.0, 0.0,0.5,0.0, + 0.5,0.0,1.0, 0.5,0.5,1.0, 0.0,0.5,1.0, + 0.0,0.0,0.5, 1.0,0.0,0.5, 0.0,1.0,0.5}; +double *vtkQuadraticWedge::GetParametricCoords() +{ + return vtkQWedgeCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkQuadraticWedge::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Edge:\n"; + this->Edge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "TriangleFace:\n"; + this->TriangleFace->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Face:\n"; + this->Face->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Wedge:\n"; + this->Wedge->PrintSelf(os,indent.GetNextIndent()); + os << indent << "PointData:\n"; + this->PointData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "CellData:\n"; + this->CellData->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Scalars:\n"; + this->Scalars->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkQuadraticWedge.h b/Filtering/vtkQuadraticWedge.h new file mode 100644 index 0000000..cbbf5b0 --- /dev/null +++ b/Filtering/vtkQuadraticWedge.h @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadraticWedge.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadraticWedge - cell represents a parabolic, 15-node isoparametric wedge +// .SECTION Description +// vtkQuadraticWedge is a concrete implementation of vtkNonLinearCell to +// represent a three-dimensional, 15-node isoparametric parabolic +// wedge. The interpolation is the standard finite element, quadratic +// isoparametric shape function. The cell includes a mid-edge node. The +// ordering of the fifteen points defining the cell is point ids (0-5,6-15) +// where point ids 0-5 are the six corner vertices of the wedge; followed by +// nine midedge nodes (6-15). Note that these midedge nodes correspond lie +// on the edges defined by (0,1), (1,2), (2,0), (3,4), (4,5), (5,3), (0,3), +// (1,4), (2,5). + +// .SECTION See Also +// vtkQuadraticEdge vtkQuadraticTriangle vtkQuadraticTetra +// vtkQuadraticHexahedron vtkQuadraticQuad vtkQuadraticPyramid + +#ifndef __vtkQuadraticWedge_h +#define __vtkQuadraticWedge_h + +#include "vtkNonLinearCell.h" + +class vtkQuadraticEdge; +class vtkQuadraticQuad; +class vtkQuadraticTriangle; +class vtkWedge; +class vtkDoubleArray; + +class VTK_FILTERING_EXPORT vtkQuadraticWedge : public vtkNonLinearCell +{ +public: + static vtkQuadraticWedge *New(); + vtkTypeRevisionMacro(vtkQuadraticWedge,vtkNonLinearCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement the vtkCell API. See the vtkCell API for descriptions + // of these methods. + int GetCellType() {return VTK_QUADRATIC_WEDGE;} + int GetCellDimension() {return 3;} + int GetNumberOfEdges() {return 9;} + int GetNumberOfFaces() {return 5;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this quadratic hexahedron using scalar value provided. Like + // contouring, except that it cuts the hex to produce linear + // tetrahedron. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tetras, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // Line-edge intersection. Intersection has to occur within [0,1] parametric + // coordinates and with specified tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + + // Description: + // Return the center of the quadratic wedge in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Quadratic hexahedron specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[15]); + static void InterpolationDerivs(double pcoords[3], double derivs[45]); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. + void JacobianInverse(double pcoords[3], double **inverse, double derivs[45]); + +protected: + vtkQuadraticWedge(); + ~vtkQuadraticWedge(); + + vtkQuadraticEdge *Edge; + vtkQuadraticTriangle *TriangleFace; + vtkQuadraticQuad *Face; + vtkWedge *Wedge; + vtkPointData *PointData; + vtkCellData *CellData; + vtkDoubleArray *CellScalars; + vtkDoubleArray *Scalars; //used to avoid New/Delete in contouring/clipping + + void Subdivide(vtkPointData *inPd, vtkCellData *inCd, vtkIdType cellId, vtkDataArray *cellScalars); + +private: + vtkQuadraticWedge(const vtkQuadraticWedge&); // Not implemented. + void operator=(const vtkQuadraticWedge&); // Not implemented. +}; +//---------------------------------------------------------------------------- +// Return the center of the quadratic wedge in parametric coordinates. +inline int vtkQuadraticWedge::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 1./3; + pcoords[2] = 0.5; + return 0; +} + + +#endif + + diff --git a/Filtering/vtkRectilinearGrid.cxx b/Filtering/vtkRectilinearGrid.cxx new file mode 100644 index 0000000..5c06f63 --- /dev/null +++ b/Filtering/vtkRectilinearGrid.cxx @@ -0,0 +1,1115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGrid.h" + +#include "vtkCellData.h" +#include "vtkExtentTranslator.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPixel.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" +#include "vtkVertex.h" +#include "vtkVoxel.h" + +vtkCxxRevisionMacro(vtkRectilinearGrid, "$Revision: 1.5.4.1 $"); +vtkStandardNewMacro(vtkRectilinearGrid); + +vtkCxxSetObjectMacro(vtkRectilinearGrid,XCoordinates,vtkDataArray); +vtkCxxSetObjectMacro(vtkRectilinearGrid,YCoordinates,vtkDataArray); +vtkCxxSetObjectMacro(vtkRectilinearGrid,ZCoordinates,vtkDataArray); + +//---------------------------------------------------------------------------- +vtkRectilinearGrid::vtkRectilinearGrid() +{ + this->Vertex = vtkVertex::New(); + this->Line = vtkLine::New(); + this->Pixel = vtkPixel::New(); + this->Voxel = vtkVoxel::New(); + + this->Dimensions[0] = 0; + this->Dimensions[1] = 0; + this->Dimensions[2] = 0; + this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_3D_EXTENT); + this->Information->Set(vtkDataObject::DATA_EXTENT(), this->Extent, 6); + + int extent[6] = {0, -1, 0, -1, 0, -1}; + memcpy(this->Extent, extent, 6*sizeof(int)); + this->DataDescription = VTK_EMPTY; + + vtkDoubleArray *fs=vtkDoubleArray::New(); fs->Allocate(1); + fs->SetNumberOfTuples(1); + fs->SetComponent(0, 0, 0.0); + this->XCoordinates = fs; fs->Register(this); + this->YCoordinates = fs; fs->Register(this); + this->ZCoordinates = fs; fs->Register(this); + fs->Delete(); + + this->PointReturn[0] = 0.0; + this->PointReturn[1] = 0.0; + this->PointReturn[2] = 0.0; +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid::~vtkRectilinearGrid() +{ + this->Initialize(); + this->Vertex->Delete(); + this->Line->Delete(); + this->Pixel->Delete(); + this->Voxel->Delete(); + +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::Initialize() +{ + this->Superclass::Initialize(); + if(this->Information) + { + this->SetDimensions(0,0,0); + } + + if ( this->XCoordinates ) + { + this->XCoordinates->UnRegister(this); + this->XCoordinates = NULL; + } + + if ( this->YCoordinates ) + { + this->YCoordinates->UnRegister(this); + this->YCoordinates = NULL; + } + + if ( this->ZCoordinates ) + { + this->ZCoordinates->UnRegister(this); + this->ZCoordinates = NULL; + } +} + +//---------------------------------------------------------------------------- +// Copy the geometric and topological structure of an input rectilinear grid +// object. +void vtkRectilinearGrid::CopyStructure(vtkDataSet *ds) +{ + vtkRectilinearGrid *rGrid=(vtkRectilinearGrid *)ds; + int i; + this->Initialize(); + + for (i=0; i<3; i++) + { + this->Dimensions[i] = rGrid->Dimensions[i]; + } + this->SetExtent(rGrid->GetExtent()); + this->DataDescription = rGrid->DataDescription; + + this->SetXCoordinates(rGrid->XCoordinates); + this->SetYCoordinates(rGrid->YCoordinates); + this->SetZCoordinates(rGrid->ZCoordinates); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkRectilinearGrid::GetCell(vtkIdType cellId) +{ + vtkCell *cell = NULL; + vtkIdType idx, npts; + int loc[3]; + int iMin, iMax, jMin, jMax, kMin, kMax; + int d01 = this->Dimensions[0]*this->Dimensions[1]; + double x[3]; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + switch (this->DataDescription) + { + case VTK_EMPTY: + //return this->EmptyCell; + return NULL; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell = this->Vertex; + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + cell = this->Line; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + cell = this->Line; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + cell = this->Line; + break; + + case VTK_XY_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + jMin = cellId / (this->Dimensions[0]-1); + jMax = jMin + 1; + cell = this->Pixel; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (this->Dimensions[1]-1); + jMax = jMin + 1; + kMin = cellId / (this->Dimensions[1]-1); + kMax = kMin + 1; + cell = this->Pixel; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + kMin = cellId / (this->Dimensions[0]-1); + kMax = kMin + 1; + cell = this->Pixel; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (this->Dimensions[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + kMax = kMin + 1; + cell = this->Voxel; + break; + } + + + // Extract point coordinates and point ids + for (npts=0,loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = this->ZCoordinates->GetComponent(loc[2], 0); + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = this->YCoordinates->GetComponent(loc[1], 0); + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = this->XCoordinates->GetComponent(loc[0], 0); + + idx = loc[0] + loc[1]*this->Dimensions[0] + loc[2]*d01; + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,x); + } + } + } + + return cell; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::GetCell(vtkIdType cellId, vtkGenericCell *cell) +{ + vtkIdType idx, npts; + int loc[3]; + int iMin, iMax, jMin, jMax, kMin, kMax; + int d01 = this->Dimensions[0]*this->Dimensions[1]; + double x[3]; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + switch (this->DataDescription) + { + case VTK_EMPTY: + cell->SetCellTypeToEmptyCell(); + break; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell->SetCellTypeToVertex(); + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_XY_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + jMin = cellId / (this->Dimensions[0]-1); + jMax = jMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_YZ_PLANE: + jMin = cellId % (this->Dimensions[1]-1); + jMax = jMin + 1; + kMin = cellId / (this->Dimensions[1]-1); + kMax = kMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_XZ_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + kMin = cellId / (this->Dimensions[0]-1); + kMax = kMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_XYZ_GRID: + iMin = cellId % (this->Dimensions[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + kMax = kMin + 1; + cell->SetCellTypeToVoxel(); + break; + } + + // Extract point coordinates and point ids + for (npts=0,loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = this->ZCoordinates->GetComponent(loc[2], 0); + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = this->YCoordinates->GetComponent(loc[1], 0); + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = this->XCoordinates->GetComponent(loc[0], 0); + idx = loc[0] + loc[1]*this->Dimensions[0] + loc[2]*d01; + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,x); + } + } + } +} + +//---------------------------------------------------------------------------- +// Fast implementation of GetCellBounds(). Bounds are calculated without +// constructing a cell. +void vtkRectilinearGrid::GetCellBounds(vtkIdType cellId, double bounds[6]) +{ + int loc[3]; + int iMin, iMax, jMin, jMax, kMin, kMax; + double x[3]; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + switch (this->DataDescription) + { + case VTK_EMPTY: + return; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + break; + + case VTK_XY_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + jMin = cellId / (this->Dimensions[0]-1); + jMax = jMin + 1; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (this->Dimensions[1]-1); + jMax = jMin + 1; + kMin = cellId / (this->Dimensions[1]-1); + kMax = kMin + 1; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + kMin = cellId / (this->Dimensions[0]-1); + kMax = kMin + 1; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (this->Dimensions[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + kMax = kMin + 1; + break; + } + + // carefully compute the bounds + if (kMax >= kMin && jMax >= jMin && iMax >= iMin) + { + bounds[0] = bounds[2] = bounds[4] = VTK_DOUBLE_MAX; + bounds[1] = bounds[3] = bounds[5] = -VTK_DOUBLE_MAX; + + // Extract point coordinates + for (loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = this->ZCoordinates->GetComponent(loc[2], 0); + bounds[4] = (x[2] < bounds[4] ? x[2] : bounds[4]); + bounds[5] = (x[2] > bounds[5] ? x[2] : bounds[5]); + } + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = this->YCoordinates->GetComponent(loc[1], 0); + bounds[2] = (x[1] < bounds[2] ? x[1] : bounds[2]); + bounds[3] = (x[1] > bounds[3] ? x[1] : bounds[3]); + } + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = this->XCoordinates->GetComponent(loc[0], 0); + bounds[0] = (x[0] < bounds[0] ? x[0] : bounds[0]); + bounds[1] = (x[0] > bounds[1] ? x[0] : bounds[1]); + } + } + else + { + vtkMath::UninitializeBounds(bounds); + } +} + + +//---------------------------------------------------------------------------- +double *vtkRectilinearGrid::GetPoint(vtkIdType ptId) +{ + int loc[3]; + + switch (this->DataDescription) + { + case VTK_EMPTY: + this->PointReturn[0] = 0.0; + this->PointReturn[1] = 0.0; + this->PointReturn[2] = 0.0; + vtkErrorMacro("Requesting a point from an empty data set."); + return this->PointReturn; + + case VTK_SINGLE_POINT: + loc[0] = loc[1] = loc[2] = 0; + break; + + case VTK_X_LINE: + loc[1] = loc[2] = 0; + loc[0] = ptId; + break; + + case VTK_Y_LINE: + loc[0] = loc[2] = 0; + loc[1] = ptId; + break; + + case VTK_Z_LINE: + loc[0] = loc[1] = 0; + loc[2] = ptId; + break; + + case VTK_XY_PLANE: + loc[2] = 0; + loc[0] = ptId % this->Dimensions[0]; + loc[1] = ptId / this->Dimensions[0]; + break; + + case VTK_YZ_PLANE: + loc[0] = 0; + loc[1] = ptId % this->Dimensions[1]; + loc[2] = ptId / this->Dimensions[1]; + break; + + case VTK_XZ_PLANE: + loc[1] = 0; + loc[0] = ptId % this->Dimensions[0]; + loc[2] = ptId / this->Dimensions[0]; + break; + + case VTK_XYZ_GRID: + loc[0] = ptId % this->Dimensions[0]; + loc[1] = (ptId / this->Dimensions[0]) % this->Dimensions[1]; + loc[2] = ptId / (this->Dimensions[0]*this->Dimensions[1]); + break; + } + + this->PointReturn[0] = this->XCoordinates->GetComponent(loc[0], 0); + this->PointReturn[1] = this->YCoordinates->GetComponent(loc[1], 0); + this->PointReturn[2] = this->ZCoordinates->GetComponent(loc[2], 0); + + return this->PointReturn; +} + +void vtkRectilinearGrid::GetPoint(vtkIdType ptId, double x[3]) +{ + int loc[3]; + + switch (this->DataDescription) + { + case VTK_EMPTY: + vtkErrorMacro("Requesting a point from an empty data set."); + x[0] = x[1] = x[2] = 0.0; + return; + + case VTK_SINGLE_POINT: + loc[0] = loc[1] = loc[2] = 0; + break; + + case VTK_X_LINE: + loc[1] = loc[2] = 0; + loc[0] = ptId; + break; + + case VTK_Y_LINE: + loc[0] = loc[2] = 0; + loc[1] = ptId; + break; + + case VTK_Z_LINE: + loc[0] = loc[1] = 0; + loc[2] = ptId; + break; + + case VTK_XY_PLANE: + loc[2] = 0; + loc[0] = ptId % this->Dimensions[0]; + loc[1] = ptId / this->Dimensions[0]; + break; + + case VTK_YZ_PLANE: + loc[0] = 0; + loc[1] = ptId % this->Dimensions[1]; + loc[2] = ptId / this->Dimensions[1]; + break; + + case VTK_XZ_PLANE: + loc[1] = 0; + loc[0] = ptId % this->Dimensions[0]; + loc[2] = ptId / this->Dimensions[0]; + break; + + case VTK_XYZ_GRID: + loc[0] = ptId % this->Dimensions[0]; + loc[1] = (ptId / this->Dimensions[0]) % this->Dimensions[1]; + loc[2] = ptId / (this->Dimensions[0]*this->Dimensions[1]); + break; + } + + x[0] = this->XCoordinates->GetComponent(loc[0], 0); + x[1] = this->YCoordinates->GetComponent(loc[1], 0); + x[2] = this->ZCoordinates->GetComponent(loc[2], 0); + +} + +//---------------------------------------------------------------------------- +vtkIdType vtkRectilinearGrid::FindPoint(double x[3]) +{ + int i, j, loc[3]; + double xPrev, xNext; + vtkDataArray *scalars[3]; + + scalars[0] = this->XCoordinates; + scalars[1] = this->YCoordinates; + scalars[2] = this->ZCoordinates; +// +// Find coordinates in x-y-z direction +// + for ( j=0; j < 3; j++ ) + { + loc[j] = 0; + xPrev = scalars[j]->GetComponent(0, 0); + xNext = scalars[j]->GetComponent(scalars[j]->GetNumberOfTuples()-1, 0); + if ( x[j] < xPrev || x[j] > xNext ) + { + return -1; + } + + for (i=1; i < scalars[j]->GetNumberOfTuples(); i++) + { + xNext = scalars[j]->GetComponent(i, 0); + if ( x[j] >= xPrev && x[j] <= xNext ) + { + if ( (x[j]-xPrev) < (xNext-x[j]) ) + { + loc[j] = i-1; + } + else + { + loc[j] = i; + } + } + xPrev = xNext; + } + } +// +// From this location get the point id +// + return loc[2]*this->Dimensions[0]*this->Dimensions[1] + + loc[1]*this->Dimensions[0] + loc[0]; + +} +vtkIdType vtkRectilinearGrid::FindCell(double x[3], vtkCell *vtkNotUsed(cell), + vtkGenericCell *vtkNotUsed(gencell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), + int& subId, double pcoords[3], + double *weights) +{ + return + this->FindCell( x, (vtkCell *)NULL, 0, 0.0, subId, pcoords, weights ); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkRectilinearGrid::FindCell(double x[3], vtkCell *vtkNotUsed(cell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), + int& subId, double pcoords[3], + double *weights) +{ + int loc[3]; + + if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 ) + { + return -1; + } + + vtkVoxel::InterpolationFunctions(pcoords,weights); + +// +// From this location get the cell id +// + subId = 0; + return loc[2] * (this->Dimensions[0]-1)*(this->Dimensions[1]-1) + + loc[1] * (this->Dimensions[0]-1) + loc[0]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkRectilinearGrid::FindAndGetCell(double x[3], + vtkCell *vtkNotUsed(cell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), + int& subId, + double pcoords[3], double *weights) +{ + int loc[3]; + vtkIdType cellId; + + subId = 0; + if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 ) + { + return NULL; + } + // + // Get the parametric coordinates and weights for interpolation + // + vtkVoxel::InterpolationFunctions(pcoords,weights); + // + // Get the cell + // + cellId = loc[2] * (this->Dimensions[0]-1)*(this->Dimensions[1]-1) + + loc[1] * (this->Dimensions[0]-1) + loc[0]; + + return vtkRectilinearGrid::GetCell(cellId); +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGrid::GetCellType(vtkIdType vtkNotUsed(cellId)) +{ + switch (this->DataDescription) + { + case VTK_EMPTY: + return VTK_EMPTY_CELL; + + case VTK_SINGLE_POINT: + return VTK_VERTEX; + + case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: + return VTK_LINE; + + case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: + return VTK_PIXEL; + + case VTK_XYZ_GRID: + return VTK_VOXEL; + + default: + vtkErrorMacro(<<"Bad data description!"); + return VTK_EMPTY_CELL; + } +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::ComputeBounds() +{ + double tmp; + + if (this->XCoordinates == NULL || this->YCoordinates == NULL || + this->ZCoordinates == NULL) + { + vtkMath::UninitializeBounds(this->Bounds); + return; + } + + if ( this->XCoordinates->GetNumberOfTuples() == 0 || + this->YCoordinates->GetNumberOfTuples() == 0 || + this->ZCoordinates->GetNumberOfTuples() == 0 ) + { + vtkMath::UninitializeBounds(this->Bounds); + return; + } + + this->Bounds[0] = this->XCoordinates->GetComponent(0, 0); + this->Bounds[2] = this->YCoordinates->GetComponent(0, 0); + this->Bounds[4] = this->ZCoordinates->GetComponent(0, 0); + + this->Bounds[1] = this->XCoordinates->GetComponent( + this->XCoordinates->GetNumberOfTuples()-1, 0); + this->Bounds[3] = this->YCoordinates->GetComponent( + this->YCoordinates->GetNumberOfTuples()-1, 0); + this->Bounds[5] = this->ZCoordinates->GetComponent( + this->ZCoordinates->GetNumberOfTuples()-1, 0); + // ensure that the bounds are increasing + for (int i = 0; i < 5; i += 2) + { + if (this->Bounds[i + 1] < this->Bounds[i]) + { + tmp = this->Bounds[i + 1]; + this->Bounds[i + 1] = this->Bounds[i]; + this->Bounds[i] = tmp; + } + } +} + +//---------------------------------------------------------------------------- +// Set dimensions of rectilinear grid dataset. +void vtkRectilinearGrid::SetDimensions(int i, int j, int k) +{ + this->SetExtent(0, i-1, 0, j-1, 0, k-1); +} + +//---------------------------------------------------------------------------- +// Set dimensions of rectilinear grid dataset. +void vtkRectilinearGrid::SetDimensions(int dim[3]) +{ + this->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::SetExtent(int extent[6]) +{ + int description; + + description = vtkStructuredData::SetExtent(extent, this->Extent); + if ( description < 0 ) //improperly specified + { + vtkErrorMacro (<< "Bad Extent, retaining previous values"); + } + + if (description == VTK_UNCHANGED) + { + return; + } + + this->DataDescription = description; + + this->Modified(); + this->Dimensions[0] = extent[1] - extent[0] + 1; + this->Dimensions[1] = extent[3] - extent[2] + 1; + this->Dimensions[2] = extent[5] - extent[4] + 1; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::SetExtent(int xMin, int xMax, int yMin, int yMax, + int zMin, int zMax) +{ + int extent[6]; + + extent[0] = xMin; extent[1] = xMax; + extent[2] = yMin; extent[3] = yMax; + extent[4] = zMin; extent[5] = zMax; + + this->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +// Convenience function computes the structured coordinates for a point x[3]. +// The cell is specified by the array ijk[3], and the parametric coordinates +// in the cell are specified with pcoords[3]. The function returns a 0 if the +// point x is outside of the grid, and a 1 if inside the grid. +int vtkRectilinearGrid::ComputeStructuredCoordinates(double x[3], int ijk[3], + double pcoords[3]) +{ + int i, j; + double xPrev, xNext, tmp; + vtkDataArray *scalars[3]; + + scalars[0] = this->XCoordinates; + scalars[1] = this->YCoordinates; + scalars[2] = this->ZCoordinates; + // + // Find locations in x-y-z direction + // + ijk[0] = ijk[1] = ijk[2] = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + + for ( j=0; j < 3; j++ ) + { + xPrev = scalars[j]->GetComponent(0, 0); + xNext = scalars[j]->GetComponent(scalars[j]->GetNumberOfTuples()-1, 0); + if (xNext < xPrev) + { + tmp = xNext; + xNext = xPrev; + xPrev = tmp; + } + if ( x[j] < xPrev || x[j] > xNext ) + { + return 0; + } + if (x[j] == xNext && this->Dimensions[j] != 1) + { + return 0; + } + + for (i=1; i < scalars[j]->GetNumberOfTuples(); i++) + { + xNext = scalars[j]->GetComponent(i, 0); + if ( x[j] >= xPrev && x[j] < xNext ) + { + ijk[j] = i - 1; + pcoords[j] = (x[j]-xPrev) / (xNext-xPrev); + break; + } + + else if ( x[j] == xNext ) + { + ijk[j] = i - 1; + pcoords[j] = 1.0; + break; + } + xPrev = xNext; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +unsigned long vtkRectilinearGrid::GetActualMemorySize() +{ + unsigned long size=this->vtkDataSet::GetActualMemorySize(); + + if ( this->XCoordinates ) + { + size += this->XCoordinates->GetActualMemorySize(); + } + + if ( this->YCoordinates ) + { + size += this->YCoordinates->GetActualMemorySize(); + } + + if ( this->ZCoordinates ) + { + size += this->ZCoordinates->GetActualMemorySize(); + } + + return size; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds) +{ + int numPtIds=ptIds->GetNumberOfIds(); + + // Use special methods for speed + switch (numPtIds) + { + case 0: + cellIds->Reset(); + return; + + case 1: case 2: case 4: //vertex, edge, face neighbors + vtkStructuredData::GetCellNeighbors(cellId, ptIds, + cellIds, this->Dimensions); + break; + + default: + this->vtkDataSet::GetCellNeighbors(cellId, ptIds, cellIds); + } +} +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::ShallowCopy(vtkDataObject *dataObject) +{ + vtkRectilinearGrid *grid = vtkRectilinearGrid::SafeDownCast(dataObject); + + if ( grid != NULL ) + { + this->SetDimensions(grid->GetDimensions()); + memcpy(this->Extent, grid->GetExtent(), 6*sizeof(int)); + this->DataDescription = grid->DataDescription; + + this->SetXCoordinates(grid->GetXCoordinates()); + this->SetYCoordinates(grid->GetYCoordinates()); + this->SetZCoordinates(grid->GetZCoordinates()); + + } + + // Do superclass + this->vtkDataSet::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::DeepCopy(vtkDataObject *dataObject) +{ + vtkRectilinearGrid *grid = vtkRectilinearGrid::SafeDownCast(dataObject); + + if ( grid != NULL ) + { + vtkDoubleArray *s; + this->SetDimensions(grid->GetDimensions()); + memcpy(this->Extent, grid->GetExtent(), 6*sizeof(int)); + this->DataDescription = grid->DataDescription; + + s = vtkDoubleArray::New(); + s->DeepCopy(grid->GetXCoordinates()); + this->SetXCoordinates(s); + s->Delete(); + s = vtkDoubleArray::New(); + s->DeepCopy(grid->GetYCoordinates()); + this->SetYCoordinates(s); + s->Delete(); + s = vtkDoubleArray::New(); + s->DeepCopy(grid->GetZCoordinates()); + this->SetZCoordinates(s); + s->Delete(); + } + + // Do superclass + this->vtkDataSet::DeepCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::Crop() +{ + int i, j, k; + // What we want. + int uExt[6]; + // What we have. + int ext[6]; + const int* extent = this->Extent; + int updateExtent[6] = {0,-1,0,-1,0,-1}; + this->GetUpdateExtent(updateExtent); + + // If the update extent is larger than the extent, + // we cannot do anything about it here. + for (i = 0; i < 3; ++i) + { + uExt[i*2] = updateExtent[i*2]; + ext[i*2] = extent[i*2]; + if (uExt[i*2] < ext[i*2]) + { + uExt[i*2] = ext[i*2]; + } + uExt[i*2+1] = updateExtent[i*2+1]; + ext[i*2+1] = extent[i*2+1]; + if (uExt[i*2+1] > ext[i*2+1]) + { + uExt[i*2+1] = ext[i*2+1]; + } + } + + // If extents already match, then we need to do nothing. + if (ext[0] == uExt[0] && ext[1] == uExt[1] + && ext[2] == uExt[2] && ext[3] == uExt[3] + && ext[4] == uExt[4] && ext[5] == uExt[5]) + { + return; + } + else + { + vtkRectilinearGrid *newGrid; + vtkPointData *inPD, *outPD; + vtkCellData *inCD, *outCD; + int outSize, jOffset, kOffset; + vtkIdType idx, newId; + int inInc1, inInc2; + vtkDataArray *coords, *newCoords; + + vtkDebugMacro(<< "Cropping Grid"); + + newGrid = vtkRectilinearGrid::New(); + + inPD = this->GetPointData(); + inCD = this->GetCellData(); + outPD = newGrid->GetPointData(); + outCD = newGrid->GetCellData(); + + // Allocate necessary objects + // + newGrid->SetExtent(uExt); + outSize = (uExt[1]-uExt[0]+1)*(uExt[3]-uExt[2]+1)*(uExt[5]-uExt[4]+1); + outPD->CopyAllocate(inPD,outSize,outSize); + outCD->CopyAllocate(inCD,outSize,outSize); + + // Create the coordinate arrays. + // X + coords = this->GetXCoordinates(); + newCoords = coords->NewInstance(); + newCoords->SetNumberOfComponents(coords->GetNumberOfComponents()); + newCoords->SetNumberOfTuples(uExt[1] - uExt[0] + 1); + for (idx = uExt[0]; idx <= uExt[1]; ++idx) + { + newCoords->InsertComponent(idx-(vtkIdType)uExt[0], 0, + coords->GetComponent(idx-(vtkIdType)ext[0],0)); + } + newGrid->SetXCoordinates(newCoords); + newCoords->Delete(); + // Y + coords = this->GetYCoordinates(); + newCoords = coords->NewInstance(); + newCoords->SetNumberOfComponents(coords->GetNumberOfComponents()); + newCoords->SetNumberOfTuples(uExt[3] - uExt[2] + 1); + for (idx = uExt[2]; idx <= uExt[3]; ++idx) + { + newCoords->InsertComponent(idx-(vtkIdType)uExt[2], 0, + coords->GetComponent(idx-(vtkIdType)ext[2],0)); + } + newGrid->SetYCoordinates(newCoords); + newCoords->Delete(); + // Z + coords = this->GetZCoordinates(); + newCoords = coords->NewInstance(); + newCoords->SetNumberOfComponents(coords->GetNumberOfComponents()); + newCoords->SetNumberOfTuples(uExt[5] - uExt[4] + 1); + for (idx = uExt[4]; idx <= uExt[5]; ++idx) + { + newCoords->InsertComponent(idx-(vtkIdType)uExt[4], 0, + coords->GetComponent(idx-(vtkIdType)ext[4],0)); + } + newGrid->SetZCoordinates(newCoords); + newCoords->Delete(); + + + // Traverse this data and copy point attributes to output + newId = 0; + inInc1 = (extent[1]-extent[0]+1); + inInc2 = inInc1*(extent[3]-extent[2]+1); + for ( k=uExt[4]; k <= uExt[5]; ++k) + { + kOffset = (k - extent[4]) * inInc2; + for ( j=uExt[2]; j <= uExt[3]; ++j) + { + jOffset = (j - extent[2]) * inInc1; + for ( i=uExt[0]; i <= uExt[1]; ++i) + { + idx = (i - extent[0]) + jOffset + kOffset; + outPD->CopyData(inPD, idx, newId++); + } + } + } + + // Traverse input data and copy cell attributes to output + newId = 0; + inInc1 = (extent[1] - extent[0]); + inInc2 = inInc1*(extent[3] - extent[2]); + for ( k=uExt[4]; k < uExt[5]; ++k ) + { + kOffset = (k - extent[4]) * inInc2; + for ( j=uExt[2]; j < uExt[3]; ++j ) + { + jOffset = (j - extent[2]) * inInc1; + for ( i=uExt[0]; i < uExt[1]; ++i ) + { + idx = (i - extent[0]) + jOffset + kOffset; + outCD->CopyData(inCD, idx, newId++); + } + } + } + + this->SetExtent(uExt); + this->SetXCoordinates(newGrid->GetXCoordinates()); + this->SetYCoordinates(newGrid->GetYCoordinates()); + this->SetZCoordinates(newGrid->GetZCoordinates()); + inPD->ShallowCopy(outPD); + inCD->ShallowCopy(outCD); + newGrid->Delete(); + } +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkRectilinearGrid::GetData(vtkInformation* info) +{ + return info? vtkRectilinearGrid::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkRectilinearGrid::GetData(vtkInformationVector* v, int i) +{ + return vtkRectilinearGrid::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Dimensions: (" << this->Dimensions[0] << ", " + << this->Dimensions[1] << ", " + << this->Dimensions[2] << ")\n"; + + os << indent << "X Coordinates: " << this->XCoordinates << "\n"; + os << indent << "Y Coordinates: " << this->YCoordinates << "\n"; + os << indent << "Z Coordinates: " << this->ZCoordinates << "\n"; + + const int* extent = this->Extent; + os << indent << "Extent: " << extent[0] << ", " + << extent[1] << ", " << extent[2] << ", " + << extent[3] << ", " << extent[4] << ", " + << extent[5] << endl; + +} + + diff --git a/Filtering/vtkRectilinearGrid.h b/Filtering/vtkRectilinearGrid.h new file mode 100644 index 0000000..0a04c0e --- /dev/null +++ b/Filtering/vtkRectilinearGrid.h @@ -0,0 +1,254 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGrid - a dataset that is topologically regular with variable spacing in the three coordinate directions +// .SECTION Description +// vtkRectilinearGrid is a data object that is a concrete implementation of +// vtkDataSet. vtkRectilinearGrid represents a geometric structure that is +// topologically regular with variable spacing in the three coordinate +// directions x-y-z. +// +// To define a vtkRectilinearGrid, you must specify the dimensions of the +// data and provide three arrays of values specifying the coordinates +// along the x-y-z axes. The coordinate arrays are specified using three +// vtkDataArray objects (one for x, one for y, one for z). + +// .SECTION Caveats +// Make sure that the dimensions of the grid match the number of coordinates +// in the x-y-z directions. If not, unpredictable results (including +// program failure) may result. Also, you must supply coordinates in all +// three directions, even if the dataset topology is 2D, 1D, or 0D. + +#ifndef __vtkRectilinearGrid_h +#define __vtkRectilinearGrid_h + +#include "vtkDataSet.h" +#include "vtkStructuredData.h" // For inline methods + +class vtkVertex; +class vtkLine; +class vtkPixel; +class vtkVoxel; +class vtkDataArray; + +class VTK_FILTERING_EXPORT vtkRectilinearGrid : public vtkDataSet +{ +public: + static vtkRectilinearGrid *New(); + + vtkTypeRevisionMacro(vtkRectilinearGrid,vtkDataSet); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return what type of dataset this is. + int GetDataObjectType() {return VTK_RECTILINEAR_GRID;}; + + // Description: + // Copy the geometric and topological structure of an input rectilinear grid + // object. + void CopyStructure(vtkDataSet *ds); + + // Description: + // Restore object to initial state. Release memory back to system. + void Initialize(); + + // Description: + // Standard vtkDataSet API methods. See vtkDataSet for more information. + vtkIdType GetNumberOfCells(); + vtkIdType GetNumberOfPoints(); + double *GetPoint(vtkIdType ptId); + void GetPoint(vtkIdType id, double x[3]); + vtkCell *GetCell(vtkIdType cellId); + void GetCell(vtkIdType cellId, vtkGenericCell *cell); + void GetCellBounds(vtkIdType cellId, double bounds[6]); + int FindPoint(double x, double y, double z) { return this->vtkDataSet::FindPoint(x, y, z);}; + vtkIdType FindPoint(double x[3]); + vtkIdType FindCell(double x[3], vtkCell *cell, vtkIdType cellId, double tol2, + int& subId, double pcoords[3], double *weights); + vtkIdType FindCell(double x[3], vtkCell *cell, vtkGenericCell *gencell, + vtkIdType cellId, double tol2, int& subId, + double pcoords[3], double *weights); + vtkCell *FindAndGetCell(double x[3], vtkCell *cell, vtkIdType cellId, + double tol2, int& subId, double pcoords[3], + double *weights); + int GetCellType(vtkIdType cellId); + void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds) + {vtkStructuredData::GetCellPoints(cellId,ptIds,this->DataDescription, + this->Dimensions);} + void GetPointCells(vtkIdType ptId, vtkIdList *cellIds) + {vtkStructuredData::GetPointCells(ptId,cellIds,this->Dimensions);} + void ComputeBounds(); + int GetMaxCellSize() {return 8;}; //voxel is the largest + void GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds); + + // Description: + // Set dimensions of rectilinear grid dataset. + // This also sets the extent. + void SetDimensions(int i, int j, int k); + void SetDimensions(int dim[3]); + + // Description: + // Get dimensions of this rectilinear grid dataset. + vtkGetVectorMacro(Dimensions,int,3); + + // Description: + // Return the dimensionality of the data. + int GetDataDimension(); + + // Description: + // Convenience function computes the structured coordinates for a point x[3]. + // The cell is specified by the array ijk[3], and the parametric coordinates + // in the cell are specified with pcoords[3]. The function returns a 0 if the + // point x is outside of the grid, and a 1 if inside the grid. + int ComputeStructuredCoordinates(double x[3], int ijk[3], double pcoords[3]); + + // Description: + // Given a location in structured coordinates (i-j-k), return the point id. + vtkIdType ComputePointId(int ijk[3]); + + // Description: + // Given a location in structured coordinates (i-j-k), return the cell id. + vtkIdType ComputeCellId(int ijk[3]); + + // Description: + // Specify the grid coordinates in the x-direction. + virtual void SetXCoordinates(vtkDataArray*); + vtkGetObjectMacro(XCoordinates,vtkDataArray); + + // Description: + // Specify the grid coordinates in the y-direction. + virtual void SetYCoordinates(vtkDataArray*); + vtkGetObjectMacro(YCoordinates,vtkDataArray); + + // Description: + // Specify the grid coordinates in the z-direction. + virtual void SetZCoordinates(vtkDataArray*); + vtkGetObjectMacro(ZCoordinates,vtkDataArray); + + // Description: + // Different ways to set the extent of the data array. The extent + // should be set before the "Scalars" are set or allocated. + // The Extent is stored in the order (X, Y, Z). + void SetExtent(int extent[6]); + void SetExtent(int x1, int x2, int y1, int y2, int z1, int z2); + vtkGetVector6Macro(Extent, int); + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). THIS METHOD + // IS THREAD SAFE. + unsigned long GetActualMemorySize(); + + // Description: + // Shallow and Deep copy. + void ShallowCopy(vtkDataObject *src); + void DeepCopy(vtkDataObject *src); + + // Description: + // Structured extent. The extent type is a 3D extent + int GetExtentType() { return VTK_3D_EXTENT; }; + + // Description: + // Reallocates and copies to set the Extent to the UpdateExtent. + // This is used internally when the exact extent is requested, + // and the source generated more than the update extent. + virtual void Crop(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkRectilinearGrid* GetData(vtkInformation* info); + static vtkRectilinearGrid* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkRectilinearGrid(); + ~vtkRectilinearGrid(); + + // for the GetCell method + vtkVertex *Vertex; + vtkLine *Line; + vtkPixel *Pixel; + vtkVoxel *Voxel; + + int Dimensions[3]; + int DataDescription; + + int Extent[6]; + + vtkDataArray *XCoordinates; + vtkDataArray *YCoordinates; + vtkDataArray *ZCoordinates; + + // Hang on to some space for returning points when GetPoint(id) is called. + double PointReturn[3]; + +private: + // Description: + // For legacy compatibility. Do not use. + void GetCellNeighbors(vtkIdType cellId, vtkIdList& ptIds, vtkIdList& cellIds) + {this->GetCellNeighbors(cellId, &ptIds, &cellIds);} +private: + vtkRectilinearGrid(const vtkRectilinearGrid&); // Not implemented. + void operator=(const vtkRectilinearGrid&); // Not implemented. +}; + + + + +inline vtkIdType vtkRectilinearGrid::GetNumberOfCells() +{ + vtkIdType nCells=1; + int i; + + for (i=0; i<3; i++) + { + if (this->Dimensions[i] <= 0) + { + return 0; + } + if (this->Dimensions[i] > 1) + { + nCells *= (this->Dimensions[i]-1); + } + } + + return nCells; +} + +inline vtkIdType vtkRectilinearGrid::GetNumberOfPoints() +{ + return this->Dimensions[0]*this->Dimensions[1]*this->Dimensions[2]; +} + +inline int vtkRectilinearGrid::GetDataDimension() +{ + return vtkStructuredData::GetDataDimension(this->DataDescription); +} + +inline vtkIdType vtkRectilinearGrid::ComputePointId(int ijk[3]) +{ + return vtkStructuredData::ComputePointId(this->Dimensions,ijk); +} + +inline vtkIdType vtkRectilinearGrid::ComputeCellId(int ijk[3]) +{ + return vtkStructuredData::ComputeCellId(this->Dimensions,ijk); +} + +#endif diff --git a/Filtering/vtkRectilinearGridAlgorithm.cxx b/Filtering/vtkRectilinearGridAlgorithm.cxx new file mode 100644 index 0000000..b9aa313 --- /dev/null +++ b/Filtering/vtkRectilinearGridAlgorithm.cxx @@ -0,0 +1,222 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkRectilinearGridAlgorithm, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkRectilinearGridAlgorithm); + +//---------------------------------------------------------------------------- +vtkRectilinearGridAlgorithm::vtkRectilinearGridAlgorithm() +{ + // by default assume filters have one input and one output + // subclasses that deviate should modify this setting + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGridAlgorithm::~vtkRectilinearGridAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkRectilinearGridAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkRectilinearGridAlgorithm::GetOutput(int port) +{ + return vtkRectilinearGrid::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkRectilinearGridAlgorithm::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkRectilinearGridAlgorithm::GetInput(int port) +{ + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkRectilinearGridAlgorithm::GetRectilinearGridInput(int port) +{ + return vtkRectilinearGrid::SafeDownCast(this->GetInput(port)); +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkRectilinearGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridAlgorithm::RequestInformation( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* vtkNotUsed(outputVector)) +{ + // do nothing let subclasses handle it + return 1; +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkRectilinearGridAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + return 1; +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkRectilinearGridAlgorithm::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (output && this->UpdateExtentIsEmpty(output)) + { + output->Initialize(); + return; + } + + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} + diff --git a/Filtering/vtkRectilinearGridAlgorithm.h b/Filtering/vtkRectilinearGridAlgorithm.h new file mode 100644 index 0000000..8ad53ab --- /dev/null +++ b/Filtering/vtkRectilinearGridAlgorithm.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridAlgorithm - Superclass for algorithms that produce only rectilinear grid as output +// .SECTION Description + +// vtkRectilinearGridAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// constructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be RectilinearGrid. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// ExecuteData and ExecuteInformation. For new algorithms you should +// implement RequestData( request, inputVec, outputVec) but for older filters +// there is a default implementation that calls the old ExecuteData(output) +// signature, for even older filters that don;t implement ExecuteData the +// default implementation calls the even older Execute() signature. + +#ifndef __vtkRectilinearGridAlgorithm_h +#define __vtkRectilinearGridAlgorithm_h + +#include "vtkAlgorithm.h" +#include "vtkRectilinearGrid.h" // makes things a bit easier + +class vtkDataSet; +class vtkRectilinearGrid; + +class VTK_FILTERING_EXPORT vtkRectilinearGridAlgorithm : public vtkAlgorithm +{ +public: + static vtkRectilinearGridAlgorithm *New(); + vtkTypeRevisionMacro(vtkRectilinearGridAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkRectilinearGrid* GetOutput(); + vtkRectilinearGrid* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject* GetInput(); + vtkDataObject *GetInput(int port); + vtkRectilinearGrid *GetRectilinearGridInput(int port); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(int, vtkDataObject*); + +protected: + vtkRectilinearGridAlgorithm(); + ~vtkRectilinearGridAlgorithm(); + + // convenience method + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) + { + return 1; + }; + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkRectilinearGridAlgorithm(const vtkRectilinearGridAlgorithm&); // Not implemented. + void operator=(const vtkRectilinearGridAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkRectilinearGridSource.cxx b/Filtering/vtkRectilinearGridSource.cxx new file mode 100644 index 0000000..64f0a3a --- /dev/null +++ b/Filtering/vtkRectilinearGridSource.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridSource.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" + +vtkCxxRevisionMacro(vtkRectilinearGridSource, "$Revision: 1.21 $"); + +//---------------------------------------------------------------------------- +vtkRectilinearGridSource::vtkRectilinearGridSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + + this->vtkSource::SetNthOutput(0,vtkRectilinearGrid::New()); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid *vtkRectilinearGridSource::GetOutput(int idx) +{ + return (vtkRectilinearGrid *) this->vtkSource::GetOutput(idx); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid *vtkRectilinearGridSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkRectilinearGrid *)(this->Outputs[0]); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridSource::SetOutput(vtkRectilinearGrid *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridSource::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkRectilinearGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkRectilinearGridSource.h b/Filtering/vtkRectilinearGridSource.h new file mode 100644 index 0000000..c264e4c --- /dev/null +++ b/Filtering/vtkRectilinearGridSource.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridSource - Abstract class whose subclasses generates rectilinear grid data +// .SECTION Description +// vtkRectilinearGridSource is an abstract class whose subclasses generate +// rectilinear grid data. + +// .SECTION See Also +// vtkRectilinearGridReader + +#ifndef __vtkRectilinearGridSource_h +#define __vtkRectilinearGridSource_h + +#include "vtkSource.h" + +class vtkRectilinearGrid; + +class VTK_FILTERING_EXPORT vtkRectilinearGridSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkRectilinearGridSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this source. + vtkRectilinearGrid *GetOutput(); + vtkRectilinearGrid *GetOutput(int idx); + void SetOutput(vtkRectilinearGrid *output); + +protected: + vtkRectilinearGridSource(); + ~vtkRectilinearGridSource() {}; + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkRectilinearGridSource(const vtkRectilinearGridSource&); // Not implemented. + void operator=(const vtkRectilinearGridSource&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkRectilinearGridToPolyDataFilter.cxx b/Filtering/vtkRectilinearGridToPolyDataFilter.cxx new file mode 100644 index 0000000..e3e0823 --- /dev/null +++ b/Filtering/vtkRectilinearGridToPolyDataFilter.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridToPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridToPolyDataFilter.h" + +#include "vtkInformation.h" +#include "vtkRectilinearGrid.h" + +vtkCxxRevisionMacro(vtkRectilinearGridToPolyDataFilter, "$Revision: 1.17 $"); + +//---------------------------------------------------------------------------- +vtkRectilinearGridToPolyDataFilter::vtkRectilinearGridToPolyDataFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGridToPolyDataFilter::~vtkRectilinearGridToPolyDataFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkRectilinearGridToPolyDataFilter::SetInput(vtkRectilinearGrid *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkRectilinearGrid *vtkRectilinearGridToPolyDataFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkRectilinearGrid *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +int +vtkRectilinearGridToPolyDataFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridToPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkRectilinearGridToPolyDataFilter.h b/Filtering/vtkRectilinearGridToPolyDataFilter.h new file mode 100644 index 0000000..97ff788 --- /dev/null +++ b/Filtering/vtkRectilinearGridToPolyDataFilter.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridToPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridToPolyDataFilter - abstract filter class +// .SECTION Description +// vtkRectilinearGridToPolyDataFilter is a filter whose subclasses take as +// input rectilinear grid datasets and generate polygonal data on output. + +// .SECTION See Also +// vtkRectilinearGridGeometryFilter vtkRectilinearGridOutlineFilter + +#ifndef __vtkRectilinearGridToPolyDataFilter_h +#define __vtkRectilinearGridToPolyDataFilter_h + +#include "vtkPolyDataSource.h" + +class vtkRectilinearGrid; + +class VTK_FILTERING_EXPORT vtkRectilinearGridToPolyDataFilter : public vtkPolyDataSource +{ +public: + vtkTypeRevisionMacro(vtkRectilinearGridToPolyDataFilter,vtkPolyDataSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input Grid or filter. + void SetInput(vtkRectilinearGrid *input); + vtkRectilinearGrid *GetInput(); + +protected: + vtkRectilinearGridToPolyDataFilter(); + ~vtkRectilinearGridToPolyDataFilter(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkRectilinearGridToPolyDataFilter(const vtkRectilinearGridToPolyDataFilter&); // Not implemented. + void operator=(const vtkRectilinearGridToPolyDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkScalarTree.cxx b/Filtering/vtkScalarTree.cxx new file mode 100644 index 0000000..2ff74f1 --- /dev/null +++ b/Filtering/vtkScalarTree.cxx @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarTree.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkScalarTree.h" + +#include "vtkDataSet.h" +#include "vtkGarbageCollector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkScalarTree, "$Revision: 1.32 $"); +vtkCxxSetObjectMacro(vtkScalarTree,DataSet,vtkDataSet); + +// Instantiate scalar tree with maximum level of 20 and branching +// factor of 5. +vtkScalarTree::vtkScalarTree() +{ + this->DataSet = NULL; + this->ScalarValue = 0.0; +} + +vtkScalarTree::~vtkScalarTree() +{ + this->SetDataSet(NULL); +} + +void vtkScalarTree::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->DataSet ) + { + os << indent << "DataSet: " << this->DataSet << "\n"; + } + else + { + os << indent << "DataSet: (none)\n"; + } + + os << indent << "Build Time: " << this->BuildTime.GetMTime() << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkScalarTree::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->DataSet, "DataSet"); +} diff --git a/Filtering/vtkScalarTree.h b/Filtering/vtkScalarTree.h new file mode 100644 index 0000000..01afc14 --- /dev/null +++ b/Filtering/vtkScalarTree.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarTree.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkScalarTree - organize data according to scalar values (used to accelerate contouring operations) + +// .SECTION Description +// vtkScalarTree is an abstract class that defines the API to concrete +// scalar tree subclasses. A scalar tree is a data structure that organizes +// data according to its scalar value. This allows rapid access to data for +// those algorithms that access the data based on scalar value. For example, +// isocontouring operates on cells based on the scalar (isocontour) value. +// +// To use subclasses of this class, you must specify a dataset to operate on, +// and then specify a scalar value in the InitTraversal() method. Then +// calls to GetNextCell() return cells whose scalar data contains the +// scalar value specified. + +// .SECTION See Also +// vtkSimpleScalarTree + +#ifndef __vtkScalarTree_h +#define __vtkScalarTree_h + +#include "vtkObject.h" + +class vtkCell; +class vtkDataArray; +class vtkDataSet; +class vtkIdList; +class vtkTimeStamp; + +class VTK_FILTERING_EXPORT vtkScalarTree : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkScalarTree,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Build the tree from the points/cells defining this dataset. + virtual void SetDataSet(vtkDataSet*); + vtkGetObjectMacro(DataSet,vtkDataSet); + + // Description: + // Construct the scalar tree from the dataset provided. Checks build times + // and modified time from input and reconstructs the tree if necessary. + virtual void BuildTree() = 0; + + // Description: + // Initialize locator. Frees memory and resets object as appropriate. + virtual void Initialize() = 0; + + // Description: + // Begin to traverse the cells based on a scalar value. Returned cells + // will have scalar values that span the scalar value specified. + virtual void InitTraversal(double scalarValue) = 0; + + // Description: + // Return the next cell that may contain scalar value specified to + // initialize traversal. The value NULL is returned if the list is + // exhausted. Make sure that InitTraversal() has been invoked first or + // you'll get erratic behavior. + virtual vtkCell *GetNextCell(vtkIdType &cellId, vtkIdList* &ptIds, + vtkDataArray *cellScalars) = 0; + +protected: + vtkScalarTree(); + ~vtkScalarTree(); + + vtkDataSet *DataSet; //the dataset over which the scalar tree is built + vtkDataArray *Scalars; //the scalars of the DataSet + + vtkTimeStamp BuildTime; //time at which tree was built + double ScalarValue; //current scalar value for traversal + + virtual void ReportReferences(vtkGarbageCollector*); + +private: + vtkScalarTree(const vtkScalarTree&); // Not implemented. + void operator=(const vtkScalarTree&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkSimpleCellTessellator.cxx b/Filtering/vtkSimpleCellTessellator.cxx new file mode 100644 index 0000000..7404576 --- /dev/null +++ b/Filtering/vtkSimpleCellTessellator.cxx @@ -0,0 +1,2937 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleCellTessellator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSimpleCellTessellator.h" +#include "vtkObjectFactory.h" + +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericDataSet.h" +#include "vtkGenericEdgeTable.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include "vtkPointData.h" +#include "vtkPoints.h" + +#include "vtkOrderedTriangulator.h" +#include "vtkPolygon.h" +#include "vtkTetra.h" + +#include +#include +#include + +// format of the arrays LeftPoint, MidPoint, RightPoint is global, parametric, +// attributes: xyz rst [abc de...] +const int PARAMETRIC_OFFSET = 3; +const int ATTRIBUTES_OFFSET = 6; + +// Pre computed table for the point to edge equivalence: +// [edge][point] +static int TRIANGLE_EDGES_TABLE[3][2] = {{0, 1}, {1, 2}, {2, 0}}; + + +// Pre computed table for the tessellation of triangles +#define NO_TRIAN {-1,-1,-1} + +// Each edge can either be split or not therefore there is +// 2^3 = 8 differents cases of tessellation +// The last case is only a sentinel to avoid stepping out of table +// If we consider edge 3 the first edge, 4 the second and 5 the last one +// 'Index' can be computed by the decimal evaluation of the binary representing +// which is is split ex: 3 and 5 are split is noted: +// {1, 0, 1} = 1*2^0 + 0*2^1 + 1*2^2 = 5 +// [case][triangle][vertex] +static signed char vtkTessellatorTriangleCases[9][4][3] = { +// Index = 0, Case where no edges are split +{ NO_TRIAN, NO_TRIAN, NO_TRIAN, NO_TRIAN}, +// Index = 1, Case where edges 3 are split +{{0, 3, 2},{1, 2, 3}, NO_TRIAN, NO_TRIAN}, +// Index = 2, Case where edges 4 are split +{{0, 1, 4},{0, 4, 2}, NO_TRIAN, NO_TRIAN}, +// Index = 3, Case where edges 3,4 are split +{{0, 3, 2},{1, 4, 3},{3, 4, 2}, NO_TRIAN}, +// Index = 4, Case where edges 5 are split +{{0, 1, 5},{1, 2, 5}, NO_TRIAN, NO_TRIAN}, +// Index = 5, Case where edges 3,5 are split +{{0, 3, 5},{1, 5, 3},{1, 2, 5}, NO_TRIAN}, +// Index = 6, Case where edges 4,5 are split +{{0, 4, 5},{0, 1, 4},{2, 5, 4}, NO_TRIAN}, +// Index = 7, Case where edges 4,5,6 are split +{{0, 3, 5},{3, 4, 5},{1, 4, 3},{2, 5, 4}}, +// In case we reach outside the table +{ NO_TRIAN, NO_TRIAN, NO_TRIAN, NO_TRIAN}, +}; + +// Pre computed table for the point to edge equivalence: +// [edge][point] +static int TETRA_EDGES_TABLE[6][2] = { +{0, 1}, {1, 2}, {2, 0}, {0, 3}, {1, 3}, {2, 3} +}; + +// Pre computed table for the tessellation of tetras +// There is two cases for the tessellation of a tetra, it is either oriented +// with the right hand rule or with the left hand rule +#define NO_TETRA {-1,-1,-1,-1} + + +// Each edge can either be split or not therefore there is +// 2^6 = 64 differents cases of tessellation +// The last case is only a sentinel to avoid stepping out of table +// [case][tetra][vertex] +static signed char vtkTessellatorTetraCasesRight[65][8][4] = { +// Index = 0, Case where no edges are split +{{0,1,2,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 1, Case where edges: 4 are split +{{0,2,3,4},{1,2,4,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 2, Case where edges: 5 are split +{{0,1,5,3},{0,2,3,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 3, Case where edges: 4,5 are split +{{0,2,3,5},{0,3,4,5},{1,3,5,4}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 4, Case where edges: 6 are split +{{0,1,6,3},{1,2,6,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 5, Case where edges: 4,6 are split +{{0,3,4,6},{1,2,6,3},{1,3,6,4}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 6, Case where edges: 5,6 are split +{{0,1,5,3},{0,3,5,6},{2,3,6,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 7, Case where edges: 4,5,6 are split +{{0,3,4,6},{1,3,5,4},{2,3,6,5},{3,4,6,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 8, Case where edges: 7 are split +{{0,1,2,7},{1,2,7,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 9, Case where edges: 4,7 are split +{{0,2,7,4},{1,2,4,7},{1,2,7,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 10, Case where edges: 5,7 are split +{{0,1,5,7},{0,2,7,5},{1,3,5,7},{2,3,7,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 11, Case where edges: 4,5,7 are split +{{0,2,7,5},{0,4,5,7},{1,3,5,7},{1,4,7,5},{2,3,7,5}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 12, Case where edges: 6,7 are split +{{0,1,6,7},{1,2,6,7},{1,2,7,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 13, Case where edges: 4,6,7 are split +{{0,4,6,7},{1,2,6,7},{1,2,7,3},{1,4,7,6}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 14, Case where edges: 5,6,7 are split +{{0,1,5,7},{0,5,6,7},{1,3,5,7},{2,3,7,5},{2,5,7,6}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 15, Case where edges: 4,5,6,7 are split +{{0,4,6,7},{1,3,5,7},{1,4,7,5},{2,3,7,5},{2,5,7,6},{4,5,6,7}, NO_TETRA, NO_TETRA}, +// Index = 16, Case where edges: 8 are split +{{0,1,2,8},{0,2,3,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 17, Case where edges: 4,8 are split +{{0,2,3,8},{0,2,8,4},{1,2,4,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 18, Case where edges: 5,8 are split +{{0,1,5,8},{0,2,3,8},{0,2,8,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 19, Case where edges: 4,5,8 are split +{{0,2,3,8},{0,2,8,5},{0,4,5,8},{1,4,8,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 20, Case where edges: 6,8 are split +{{0,1,6,8},{0,3,8,6},{1,2,6,8},{2,3,6,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 21, Case where edges: 4,6,8 are split +{{0,3,8,6},{0,4,6,8},{1,2,6,8},{1,4,8,6},{2,3,6,8}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 22, Case where edges: 5,6,8 are split +{{0,1,5,8},{0,3,8,6},{0,5,6,8},{2,3,6,8},{2,5,8,6}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 23, Case where edges: 4,5,6,8 are split +{{0,3,8,6},{0,4,6,8},{1,4,8,5},{2,3,6,8},{2,5,8,6},{4,5,6,8}, NO_TETRA, NO_TETRA}, +// Index = 24, Case where edges: 7,8 are split +{{0,1,2,8},{0,2,7,8},{2,3,7,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 25, Case where edges: 4,7,8 are split +{{0,2,7,4},{1,2,4,8},{2,3,7,8},{2,4,8,7}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 26, Case where edges: 5,7,8 are split +{{0,1,5,8},{0,2,7,5},{0,5,7,8},{2,3,7,8},{2,5,8,7}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 27, Case where edges: 4,5,7,8 are split +{{0,2,7,5},{0,4,5,7},{1,4,8,5},{2,3,7,8},{2,5,8,7},{4,5,7,8}, NO_TETRA, NO_TETRA}, +// Index = 28, Case where edges: 6,7,8 are split +{{0,1,6,8},{0,6,7,8},{1,2,6,8},{2,3,7,8},{2,6,8,7}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 29, Case where edges: 4,6,7,8 are split +{{0,4,6,7},{1,2,6,8},{1,4,8,6},{2,3,7,8},{2,6,8,7},{4,6,7,8}, NO_TETRA, NO_TETRA}, +// Index = 30, Case where edges: 5,6,7,8 are split +{{0,1,5,8},{0,5,6,7},{0,5,7,8},{2,3,7,8},{2,5,7,6},{2,5,8,7}, NO_TETRA, NO_TETRA}, +// Index = 31, Case where edges: 4,5,6,7,8 are split +{{0,4,6,7},{1,4,8,5},{2,3,7,8},{2,5,7,6},{2,5,8,7},{4,5,6,7},{4,5,7,8}, NO_TETRA}, +// Index = 32, Case where edges: are split +{{0,1,2,9},{0,1,9,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 33, Case where edges: 4 are split +{{0,2,9,4},{0,3,4,9},{1,2,4,9},{1,3,9,4}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 34, Case where edges: 5 are split +{{0,1,5,9},{0,1,9,3},{0,2,9,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 35, Case where edges: 4,5 are split +{{0,2,9,5},{0,3,4,9},{0,4,5,9},{1,3,9,4},{1,4,9,5}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 36, Case where edges: 6 are split +{{0,1,6,9},{0,1,9,3},{1,2,6,9}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 37, Case where edges: 4,6 are split +{{0,3,4,9},{0,4,6,9},{1,2,6,9},{1,3,9,4},{1,4,9,6}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 38, Case where edges: 5,6 are split +{{0,1,5,9},{0,1,9,3},{0,5,6,9},{2,5,9,6}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 39, Case where edges: 4,5,6 are split +{{0,3,4,9},{0,4,6,9},{1,3,9,4},{1,4,9,5},{2,5,9,6},{4,5,6,9}, NO_TETRA, NO_TETRA}, +// Index = 40, Case where edges: 7 are split +{{0,1,2,9},{0,1,9,7},{1,3,9,7}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 41, Case where edges: 4,7 are split +{{0,2,9,4},{0,4,9,7},{1,2,4,9},{1,3,9,7},{1,4,7,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 42, Case where edges: 5,7 are split +{{0,1,5,7},{0,2,9,5},{0,5,9,7},{1,3,9,7},{1,5,7,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 43, Case where edges: 4,5,7 are split +{{0,2,9,5},{0,4,5,7},{0,5,9,7},{1,3,9,7},{1,4,7,5},{1,5,7,9}, NO_TETRA, NO_TETRA}, +// Index = 44, Case where edges: 6,7 are split +{{0,1,6,7},{1,2,6,9},{1,3,9,7},{1,6,7,9}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 45, Case where edges: 4,6,7 are split +{{0,4,6,7},{1,2,6,9},{1,3,9,7},{1,4,7,9},{1,4,9,6},{4,6,7,9}, NO_TETRA, NO_TETRA}, +// Index = 46, Case where edges: 5,6,7 are split +{{0,1,5,7},{0,5,6,7},{1,3,9,7},{1,5,7,9},{2,5,9,6},{5,6,7,9}, NO_TETRA, NO_TETRA}, +// Index = 47, Case where edges: 4,5,6,7 are split +{{0,4,6,7},{1,3,9,7},{1,4,7,5},{1,5,7,9},{2,5,9,6},{4,5,6,7},{5,6,7,9}, NO_TETRA}, +// Index = 48, Case where edges: 8 are split +{{0,1,2,9},{0,1,9,8},{0,3,8,9}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 49, Case where edges: 4,8 are split +{{0,2,9,4},{0,3,8,9},{0,4,9,8},{1,2,4,9},{1,4,8,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 50, Case where edges: 5,8 are split +{{0,1,5,8},{0,2,9,5},{0,3,8,9},{0,5,9,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 51, Case where edges: 4,5,8 are split +{{0,2,9,5},{0,3,8,9},{0,4,5,9},{0,4,9,8},{1,4,8,5},{4,5,9,8}, NO_TETRA, NO_TETRA}, +// Index = 52, Case where edges: 6,8 are split +{{0,1,6,8},{0,3,8,9},{0,6,9,8},{1,2,6,9},{1,6,8,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 53, Case where edges: 4,6,8 are split +{{0,3,8,9},{0,4,6,8},{0,6,9,8},{1,2,6,9},{1,4,8,6},{1,6,8,9}, NO_TETRA, NO_TETRA}, +// Index = 54, Case where edges: 5,6,8 are split +{{0,1,5,8},{0,3,8,9},{0,5,6,8},{0,6,9,8},{2,5,9,6},{5,6,8,9}, NO_TETRA, NO_TETRA}, +// Index = 55, Case where edges: 4,5,6,8 are split +{{0,3,8,9},{0,4,6,8},{0,6,9,8},{1,4,8,5},{2,5,9,6},{4,5,6,8},{5,6,8,9}, NO_TETRA}, +// Index = 56, Case where edges: 7,8 are split +{{0,1,2,9},{0,1,9,8},{0,7,8,9},{3,7,9,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 57, Case where edges: 4,7,8 are split +{{0,2,9,4},{0,4,9,7},{1,2,4,9},{1,4,8,9},{3,7,9,8},{4,7,8,9}, NO_TETRA, NO_TETRA}, +// Index = 58, Case where edges: 5,7,8 are split +{{0,1,5,8},{0,2,9,5},{0,5,7,8},{0,5,9,7},{3,7,9,8},{5,7,8,9}, NO_TETRA, NO_TETRA}, +// Index = 59, Case where edges: 4,5,7,8 are split +{{0,2,9,5},{0,4,5,7},{0,5,9,7},{1,4,8,5},{3,7,9,8},{4,5,7,8},{5,7,8,9}, NO_TETRA}, +// Index = 60, Case where edges: 6,7,8 are split +{{0,1,6,8},{0,6,7,8},{1,2,6,9},{1,6,8,9},{3,7,9,8},{6,7,8,9}, NO_TETRA, NO_TETRA}, +// Index = 61, Case where edges: 4,6,7,8 are split +{{0,4,6,7},{1,2,6,9},{1,4,8,6},{1,6,8,9},{3,7,9,8},{4,6,7,8},{6,7,8,9}, NO_TETRA}, +// Index = 62, Case where edges: 5,6,7,8 are split +{{0,1,5,8},{0,5,6,7},{0,5,7,8},{2,5,9,6},{3,7,9,8},{5,6,7,9},{5,7,8,9}, NO_TETRA}, +// Index = 63, Case where edges: 4,5,6,7,8 are split +{{0,4,6,7},{1,4,8,5},{2,5,9,6},{3,7,9,8},{4,5,6,7},{4,5,7,8},{5,6,7,9},{5,7,8,9}}, +// In case we reach outside the table +{ NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA} +}; + +//----------------------------------------------------------------------------- +// +// This table is for the case where the 'last edge' of the tetra could not be order +// properly, then we need a different case table +// +static signed char vtkTessellatorTetraCasesLeft[65][8][4] = { +// Index = 0, Case where no edges are split +{{0,1,2,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 1, Case where edges: 4 are split +{{0,2,3,4},{1,2,4,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 2, Case where edges: 5 are split +{{0,1,5,3},{0,2,3,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 3, Case where edges: 4,5 are split +{{0,2,3,5},{0,3,4,5},{1,3,5,4}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 4, Case where edges: 6 are split +{{0,1,6,3},{1,2,6,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 5, Case where edges: 4,6 are split +{{0,3,4,6},{1,2,6,3},{1,3,6,4}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 6, Case where edges: 5,6 are split +{{0,1,5,3},{0,3,5,6},{2,3,6,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 7, Case where edges: 4,5,6 are split +{{0,3,4,6},{1,3,5,4},{2,3,6,5},{3,4,6,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 8, Case where edges: 7 are split +{{0,1,2,7},{1,2,7,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 9, Case where edges: 4,7 are split +{{0,2,7,4},{1,2,4,7},{1,2,7,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 10, Case where edges: 5,7 are split +{{0,1,5,7},{0,2,7,5},{1,3,5,7},{2,3,7,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 11, Case where edges: 4,5,7 are split +{{0,2,7,5},{0,4,5,7},{1,3,5,7},{1,4,7,5},{2,3,7,5}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 12, Case where edges: 6,7 are split +{{0,1,6,7},{1,2,6,3},{1,3,6,7}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 13, Case where edges: 4,6,7 are split +{{0,4,6,7},{1,2,6,3},{1,3,6,7},{1,4,7,6}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 14, Case where edges: 5,6,7 are split +{{0,1,5,7},{0,5,6,7},{1,3,5,7},{2,3,6,5},{3,5,7,6}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 15, Case where edges: 4,5,6,7 are split +{{0,4,6,7},{1,3,5,7},{1,4,7,5},{2,3,6,5},{3,5,7,6},{4,5,6,7}, NO_TETRA, NO_TETRA}, +// Index = 16, Case where edges: 8 are split +{{0,1,2,8},{0,2,3,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 17, Case where edges: 4,8 are split +{{0,2,3,8},{0,2,8,4},{1,2,4,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 18, Case where edges: 5,8 are split +{{0,1,5,8},{0,2,3,5},{0,3,8,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 19, Case where edges: 4,5,8 are split +{{0,2,3,5},{0,3,8,5},{0,4,5,8},{1,4,8,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 20, Case where edges: 6,8 are split +{{0,1,6,8},{0,3,8,6},{1,2,6,8},{2,3,6,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 21, Case where edges: 4,6,8 are split +{{0,3,8,6},{0,4,6,8},{1,2,6,8},{1,4,8,6},{2,3,6,8}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 22, Case where edges: 5,6,8 are split +{{0,1,5,8},{0,3,8,6},{0,5,6,8},{2,3,6,5},{3,5,8,6}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 23, Case where edges: 4,5,6,8 are split +{{0,3,8,6},{0,4,6,8},{1,4,8,5},{2,3,6,5},{3,5,8,6},{4,5,6,8}, NO_TETRA, NO_TETRA}, +// Index = 24, Case where edges: 7,8 are split +{{0,1,2,8},{0,2,7,8},{2,3,7,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 25, Case where edges: 4,7,8 are split +{{0,2,7,4},{1,2,4,8},{2,3,7,8},{2,4,8,7}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 26, Case where edges: 5,7,8 are split +{{0,1,5,8},{0,2,7,5},{0,5,7,8},{2,3,7,5},{3,5,8,7}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 27, Case where edges: 4,5,7,8 are split +{{0,2,7,5},{0,4,5,7},{1,4,8,5},{2,3,7,5},{3,5,8,7},{4,5,7,8}, NO_TETRA, NO_TETRA}, +// Index = 28, Case where edges: 6,7,8 are split +{{0,1,6,8},{0,6,7,8},{1,2,6,8},{2,3,6,8},{3,6,8,7}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 29, Case where edges: 4,6,7,8 are split +{{0,4,6,7},{1,2,6,8},{1,4,8,6},{2,3,6,8},{3,6,8,7},{4,6,7,8}, NO_TETRA, NO_TETRA}, +// Index = 30, Case where edges: 5,6,7,8 are split +{{0,1,5,8},{0,5,6,7},{0,5,7,8},{2,3,6,5},{3,5,7,6},{3,5,8,7}, NO_TETRA, NO_TETRA}, +// Index = 31, Case where edges: 4,5,6,7,8 are split +{{0,4,6,7},{1,4,8,5},{2,3,6,5},{3,5,7,6},{3,5,8,7},{4,5,6,7},{4,5,7,8}, NO_TETRA}, +// Index = 32, Case where edges: are split +{{0,1,2,9},{0,1,9,3}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 33, Case where edges: 4 are split +{{0,2,9,4},{0,3,4,9},{1,2,4,9},{1,3,9,4}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 34, Case where edges: 5 are split +{{0,1,5,9},{0,1,9,3},{0,2,9,5}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 35, Case where edges: 4,5 are split +{{0,2,9,5},{0,3,4,9},{0,4,5,9},{1,3,9,4},{1,4,9,5}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 36, Case where edges: 6 are split +{{0,1,6,9},{0,1,9,3},{1,2,6,9}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 37, Case where edges: 4,6 are split +{{0,3,4,9},{0,4,6,9},{1,2,6,9},{1,3,9,4},{1,4,9,6}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 38, Case where edges: 5,6 are split +{{0,1,5,9},{0,1,9,3},{0,5,6,9},{2,5,9,6}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 39, Case where edges: 4,5,6 are split +{{0,3,4,9},{0,4,6,9},{1,3,9,4},{1,4,9,5},{2,5,9,6},{4,5,6,9}, NO_TETRA, NO_TETRA}, +// Index = 40, Case where edges: 7 are split +{{0,1,2,9},{0,1,9,7},{1,3,9,7}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 41, Case where edges: 4,7 are split +{{0,2,9,4},{0,4,9,7},{1,2,4,9},{1,3,9,7},{1,4,7,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 42, Case where edges: 5,7 are split +{{0,1,5,7},{0,2,9,5},{0,5,9,7},{1,3,9,7},{1,5,7,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 43, Case where edges: 4,5,7 are split +{{0,2,9,5},{0,4,5,7},{0,5,9,7},{1,3,9,7},{1,4,7,5},{1,5,7,9}, NO_TETRA, NO_TETRA}, +// Index = 44, Case where edges: 6,7 are split +{{0,1,6,7},{1,2,6,9},{1,3,9,7},{1,6,7,9}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 45, Case where edges: 4,6,7 are split +{{0,4,6,7},{1,2,6,9},{1,3,9,7},{1,4,7,9},{1,4,9,6},{4,6,7,9}, NO_TETRA, NO_TETRA}, +// Index = 46, Case where edges: 5,6,7 are split +{{0,1,5,7},{0,5,6,7},{1,3,9,7},{1,5,7,9},{2,5,9,6},{5,6,7,9}, NO_TETRA, NO_TETRA}, +// Index = 47, Case where edges: 4,5,6,7 are split +{{0,4,6,7},{1,3,9,7},{1,4,7,5},{1,5,7,9},{2,5,9,6},{4,5,6,7},{5,6,7,9}, NO_TETRA}, +// Index = 48, Case where edges: 8 are split +{{0,1,2,9},{0,1,9,8},{0,3,8,9}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 49, Case where edges: 4,8 are split +{{0,2,9,4},{0,3,8,9},{0,4,9,8},{1,2,4,9},{1,4,8,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 50, Case where edges: 5,8 are split +{{0,1,5,8},{0,2,9,5},{0,3,8,9},{0,5,9,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 51, Case where edges: 4,5,8 are split +{{0,2,9,5},{0,3,8,9},{0,4,5,9},{0,4,9,8},{1,4,8,5},{4,5,9,8}, NO_TETRA, NO_TETRA}, +// Index = 52, Case where edges: 6,8 are split +{{0,1,6,8},{0,3,8,9},{0,6,9,8},{1,2,6,9},{1,6,8,9}, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 53, Case where edges: 4,6,8 are split +{{0,3,8,9},{0,4,6,8},{0,6,9,8},{1,2,6,9},{1,4,8,6},{1,6,8,9}, NO_TETRA, NO_TETRA}, +// Index = 54, Case where edges: 5,6,8 are split +{{0,1,5,8},{0,3,8,9},{0,5,6,8},{0,6,9,8},{2,5,9,6},{5,6,8,9}, NO_TETRA, NO_TETRA}, +// Index = 55, Case where edges: 4,5,6,8 are split +{{0,3,8,9},{0,4,6,8},{0,6,9,8},{1,4,8,5},{2,5,9,6},{4,5,6,8},{5,6,8,9}, NO_TETRA}, +// Index = 56, Case where edges: 7,8 are split +{{0,1,2,9},{0,1,9,8},{0,7,8,9},{3,7,9,8}, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +// Index = 57, Case where edges: 4,7,8 are split +{{0,2,9,4},{0,4,9,7},{1,2,4,9},{1,4,8,9},{3,7,9,8},{4,7,8,9}, NO_TETRA, NO_TETRA}, +// Index = 58, Case where edges: 5,7,8 are split +{{0,1,5,8},{0,2,9,5},{0,5,7,8},{0,5,9,7},{3,7,9,8},{5,7,8,9}, NO_TETRA, NO_TETRA}, +// Index = 59, Case where edges: 4,5,7,8 are split +{{0,2,9,5},{0,4,5,7},{0,5,9,7},{1,4,8,5},{3,7,9,8},{4,5,7,8},{5,7,8,9}, NO_TETRA}, +// Index = 60, Case where edges: 6,7,8 are split +{{0,1,6,8},{0,6,7,8},{1,2,6,9},{1,6,8,9},{3,7,9,8},{6,7,8,9}, NO_TETRA, NO_TETRA}, +// Index = 61, Case where edges: 4,6,7,8 are split +{{0,4,6,7},{1,2,6,9},{1,4,8,6},{1,6,8,9},{3,7,9,8},{4,6,7,8},{6,7,8,9}, NO_TETRA}, +// Index = 62, Case where edges: 5,6,7,8 are split +{{0,1,5,8},{0,5,6,7},{0,5,7,8},{2,5,9,6},{3,7,9,8},{5,6,7,9},{5,7,8,9}, NO_TETRA}, +// Index = 63, Case where edges: 4,5,6,7,8 are split +{{0,4,6,7},{1,4,8,5},{2,5,9,6},{3,7,9,8},{4,5,6,7},{4,5,7,8},{5,6,7,9},{5,7,8,9}}, +// In case we reach outside the table +{ NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA, NO_TETRA}, +}; + + +vtkCxxRevisionMacro(vtkSimpleCellTessellator, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkSimpleCellTessellator); +//----------------------------------------------------------------------------- +// +// vtkTriangleTile +// + +class vtkTriangleTile; + +class vtkTriangleTile +{ +public: + vtkTriangleTile() + { +#ifndef NDEBUG + for(int i=0;i<6;i++) + { + this->PointId[i] = -1; + this->Vertex[i][0] = -100; + this->Vertex[i][1] = -100; + this->Vertex[i][2] = -100; + } +#endif + this->SubdivisionLevel = 0; + assert("inv: " && this->ClassInvariant()); + } + ~vtkTriangleTile() {}; + +#if 0 + int DifferentFromOriginals(double local[3]) + { + int result = 1; + int k = 0; + while(k<3 && result) + { + result = !((local[0] == this->Vertex[k][0]) + && (local[1] == this->Vertex[k][1]) + && (local[2] == this->Vertex[k][2])); + ++k; + } + return result; + } +#endif + +#ifndef NDEBUG + int ClassInvariant() + { + // Mid point are different from all original points. + int isValid = 1; + int j = 3; + int k; + while(j<6 && isValid) + { + // Don't even look at original points if the mid-point is not + // initialized + isValid = (this->Vertex[j][0] == -100) + && (this->Vertex[j][1] == -100) + && (this->Vertex[j][2] == -100); + if(!isValid) + { + k = 0; + isValid = 1; + while(k<3 && isValid) + { + isValid = !((this->Vertex[j][0] == this->Vertex[k][0]) + && (this->Vertex[j][1] == this->Vertex[k][1]) + && (this->Vertex[j][2] == this->Vertex[k][2])); + ++k; + } + } + ++j; + } + return isValid; + } +#endif + + void SetSubdivisionLevel(int level) + { + assert("pre: positive_level" && level>=0); + this->SubdivisionLevel = level; + } + + int GetSubdivisionLevel() + { + return this->SubdivisionLevel; + } + + void SetVertex( int i , double v[3] ) + { + this->Vertex[i][0] = v[0]; + this->Vertex[i][1] = v[1]; + this->Vertex[i][2] = v[2]; + } + + void SetPointId(int i, vtkIdType id) {this->PointId[i] = id;} + + void SetPointIds(vtkIdType id[3]) + { + this->PointId[0] = id[0]; + this->PointId[1] = id[1]; + this->PointId[2] = id[2]; + } + + double *GetVertex( int i ) + { + return this->Vertex[i]; + } + + vtkIdType GetPointId( int i ) + { + return this->PointId[i]; + } + + // Return true if (e1, e2) is an edge of the tri: + int IsAnEdge(vtkIdType e1, vtkIdType e2) + { + int sum = 0; + for(int i=0; i<3; i++) + { + if(e1 == this->PointId[i] || e2 == this->PointId[i]) + { + sum++; + } + } + return sum == 2; + } + + // Description: + // Copy point j of source into point i of the current tile. + void CopyPoint(int i, + vtkTriangleTile *source, + int j) + { + assert("pre: primary_i" && i>=0 && i<=2); + assert("pre: source_exists" && source!=0); + assert("pre: valid_j" && j>=0 && j<=5); + + this->PointId[i] = source->PointId[j]; + + this->Vertex[i][0] = source->Vertex[j][0]; + this->Vertex[i][1] = source->Vertex[j][1]; + this->Vertex[i][2] = source->Vertex[j][2]; + + this->Edges[i][0]=source->Edges[j][0]; + this->Edges[i][1]=source->Edges[j][1]; + + assert("inv: " && this->ClassInvariant()); + } + + + + // can tile be split; if so, return TessellatePointsing tiles + // vtkTriangleTile res[4] + int Refine( vtkSimpleCellTessellator* tess, vtkTriangleTile *res ); + + // Description: + // Initialize the Edges array as for a root triangle + void SetOriginal() + { + // key note: for each vertex, the edges number it belongs to are + // given in increasing order. + // vertex 0 + this->Edges[0][0]=0; + this->Edges[0][1]=2; + // vertex 1 + this->Edges[1][0]=0; + this->Edges[1][1]=1; + // vertex 2 + this->Edges[2][0]=1; + this->Edges[2][1]=2; + } + + // Description: + // Find the parent (if any) of the edge defined by the local point ids i and + // j. Return the local id of the parent edge, -1 otherwise. + signed char FindEdgeParent(int p1, + int p2) + { + assert("pre: primary point" && p1>=0 && p1<=2 && p2>=0 && p2<=2); + int p; + int q; + + // choose the point with minimal edge id. + if(this->Edges[p1][0]<=this->Edges[p2][0]) + { + p=p1; + q=p2; + } + else + { + p=p2; + q=p1; + } + int i=0; + signed char result=-1; + + while(result==-1 && i<2) + { + if(this->Edges[p][i]<0) + { + i=2; + } + else + { + int j=0; + while(result==-1 && j<2) + { + if(this->Edges[q][j]<0) + { + j=2; + } + else + { + if(this->Edges[p][i]==this->Edges[q][j]) + { + result=this->Edges[p][i]; + } + else + { + if(this->Edges[p][i]Edges[q][j]) + { + j=2; // no way to find a common edge + } + else + { + ++j; + } + } + } + } + ++i; + } + } + return result; + } + + // Description: + // Set the edge parent of mid as parentEdge. + void SetEdgeParent(int mid, + signed char parentEdge) + { + assert("pre: mid-point" && mid>=3 && mid<=5); + this->Edges[mid][0]=parentEdge; + this->Edges[mid][1]=-1; // always for mid-points + } + +private: + // Keep track of local coordinate in order to evaluate shape function + double Vertex[3+3][3]; //3 points + 3 mid edge points + vtkIdType PointId[3+3]; + int SubdivisionLevel; + + // local ids (-1 to 2) of the original edges on which the points are. + // a point can be on almost 2 edges: + // * only a vertex of the original triangle is on 2 edges + // * the mid-points can be only on 1 edge + // * -1 encodes no edge + // * each array is an increasing list of ids terminated by -1 is no edge + signed char Edges[3+3][2]; +}; +//----------------------------------------------------------------------------- +// +// vtkTetraTile +// + +class vtkTetraTile; + +// For each of the 4 original vertices, list of the 3 edges it belongs to +// each sub-array is in increasing order. +// [vertex][edge] +static int VERTEX_EDGES[4][3]={{0,2,3},{0,1,4},{1,2,5},{3,4,5}}; +// For each of the 4 original vertices, list of the 3 faces it belongs to +// each sub-array is in increasing order. +// [vertex][face] +static int VERTEX_FACES[4][3]={{0,2,3},{0,1,3},{1,2,3},{0,1,2}}; + +class vtkTetraTile +{ +public: + vtkTetraTile() + { +#ifndef NDEBUG + for(int i=0;i<10;i++) + { + this->PointId[i] = -1; + this->Vertex[i][0] = -100; + this->Vertex[i][1] = -100; + this->Vertex[i][2] = -100; + } +#endif + this->SubdivisionLevel = 0; + assert("inv: " && this->ClassInvariant()); + } + ~vtkTetraTile() {}; + +#if 0 + int DifferentFromOriginals(double local[3]) + { + int result=1; + int k=0; + while(k<4 && result) + { + result=!((local[0] ==this->Vertex[k][0]) && + (local[1] == this->Vertex[k][1]) + && (local[2] == this->Vertex[k][2])); + ++k; + } + return result; + } +#endif + +#ifndef NDEBUG + int ClassInvariant() + { + // Mid point are different from all original points. + int isValid = 1; + int j = 4; + int k; + while(j<10 && isValid) + { + // Don't even look at original points if the mid-point is not + // initialized + isValid = (this->Vertex[j][0] == -100) + && (this->Vertex[j][1] == -100) + && (this->Vertex[j][2] == -100); + if(!isValid) + { + k = 0; + isValid = 1; + while(k<4 && isValid) + { + isValid = !((this->Vertex[j][0] == this->Vertex[k][0]) + && (this->Vertex[j][1] == this->Vertex[k][1]) + && (this->Vertex[j][2] == this->Vertex[k][2])); + ++k; + } + } + ++j; + } + return isValid; + } +#endif + + void SetSubdivisionLevel(int level) + { + assert("pre: positive_level" && level>=0); + this->SubdivisionLevel=level; + } + + int GetSubdivisionLevel() + { + return this->SubdivisionLevel; + } + + void SetVertex( int i, double v[3] ) + { + this->Vertex[i][0] = v[0]; + this->Vertex[i][1] = v[1]; + this->Vertex[i][2] = v[2]; + assert("inv: " && this->ClassInvariant()); + } + + void SetPointId(int i, vtkIdType id) { this->PointId[i] = id; } + + void SetPointIds(vtkIdType id[4]) + { + this->PointId[0] = id[0]; + this->PointId[1] = id[1]; + this->PointId[2] = id[2]; + this->PointId[3] = id[3]; + } + + void GetVertex( int i, double pt[3] ) + { + pt[0] = this->Vertex[i][0]; + pt[1] = this->Vertex[i][1]; + pt[2] = this->Vertex[i][2]; + } + + double *GetVertex( int i ) { return Vertex[i]; } + + vtkIdType GetPointId( int i ) { return this->PointId[i]; } + + // Return true if (e1, e2) is an edge of the tetra: + int IsAnEdge(vtkIdType e1, vtkIdType e2) + { + int sum = 0; + for(int i=0; i<4; i++) + { + if(e1 == this->PointId[i] || e2 == this->PointId[i]) + { + sum++; + } + } + return sum == 2; + } + + // Description: + // Copy point j of source into point i of the current tile. + void CopyPoint(int i, + vtkTetraTile *source, + int j) + { + assert("pre: primary_i" && i>=0 && i<=3); + assert("pre: source_exists" && source!=0); + assert("pre: valid_j" && j>=0 && j<=9); + + this->PointId[i] = source->PointId[j]; + + this->Vertex[i][0] = source->Vertex[j][0]; + this->Vertex[i][1] = source->Vertex[j][1]; + this->Vertex[i][2] = source->Vertex[j][2]; + + this->Edges[i][0]=source->Edges[j][0]; + this->Edges[i][1]=source->Edges[j][1]; + this->Edges[i][2]=source->Edges[j][2]; + this->Faces[i][0]=source->Faces[j][0]; + this->Faces[i][1]=source->Faces[j][1]; + this->Faces[i][2]=source->Faces[j][2]; + + assert("inv: " && this->ClassInvariant()); + } + + // Description: + // Copy the pointer to the Edge and Face Ids on the + // top-level sub-tetrahedron. + void CopyEdgeAndFaceIds(vtkTetraTile *source) + { + assert("pre: source_exists" && source!=0); + this->EdgeIds= source->EdgeIds; + this->FaceIds= source->FaceIds; + } + + // Description: + // Return the local edge id the complex cell from the local edge id + // of the top-level subtetra + int GetEdgeIds(int idx) + { + assert("pre:" && idx>=0); // <=number of edges on a complex cell + return this->EdgeIds[idx]; + } + + // Description: + // Return the local face id the complex cell from the local face id + // of the top-level subtetra + int GetFaceIds(int idx) + { + assert("pre:" && idx>=0);// <=number of faces on a complex cell + return this->FaceIds[idx]; + } + + // can tile be split; if so, return TessellatePointsing tiles + // There can't be more than 8 tetras as it corresponds to the splitting + // of all edges + // vtkTetraTile res[8] + int Refine( vtkSimpleCellTessellator* tess, vtkTetraTile *res); + + // Description: + // Initialize the Edges and Faces arrays as for a root tetrahedron + void SetOriginal(vtkIdType order[4], + int *edgeIds, //6 + int *faceIds) // 4 + { + this->EdgeIds=edgeIds; + this->FaceIds=faceIds; + + int i=0; + while(i<4) // for each vertex + { + int j=order[i]; + int k=0; + int n=0; + int tmp; + while(n<3) // copy each edge + { + tmp=VERTEX_EDGES[j][n]; + if(edgeIds[tmp]!=-1) + { + this->Edges[i][k]=tmp; + ++k; + } + ++n; + } + while(k<3) + { + this->Edges[i][k]=-1; + ++k; + } + + k=0; + n=0; + while(n<3) // copy each face + { + tmp=VERTEX_FACES[j][n]; + if(faceIds[tmp]!=-1) + { + this->Faces[i][k]=tmp; + ++k; + } + ++n; + } + while(k<3) + { + this->Faces[i][k]=-1; + ++k; + } + ++i; + } + } + + // Description: + // Find the parent (if any) of the edge defined by the local point ids i and + // j. Return the local id of the parent edge, -1 otherwise. + int FindEdgeParent(int p1, + int p2, + signed char &parentId) + { + assert("pre: primary point" && p1>=0 && p1<=3 && p2>=0 && p2<=3); + + int p; + int q; + // choose the point with minimal edge id. + if(this->Edges[p1][0]<=this->Edges[p2][0]) + { + p=p1; + q=p2; + } + else + { + p=p2; + q=p1; + } + int i=0; + int result=3; + parentId=-1; + + while(result==3 && i<3) + { + if(this->Edges[p][i]<0) + { + i=3; //done + } + else + { + int j=0; + while(result==3 && j<3) + { + if(this->Edges[q][j]<0) + { + j=3; // end of the edges of q, skip to next i + } + else + { + if(this->Edges[p][i]==this->Edges[q][j]) + { + parentId=this->Edges[p][i]; + result=1; + } + else + { + if(this->Edges[p][i]Edges[q][j]) + { + j=3; // no way to find a common face for this i, skip to next i + } + else + { + ++j; + } + } + } + } + ++i; + } + } + + if(result==3) // there is no common edge + { + // it seems there is at most one common face + // choose the point with minimal face id. + if(this->Faces[p1][0]<=this->Faces[p2][0]) + { + p=p1; + q=p2; + } + else + { + p=p2; + q=p1; + } + i=0; + while(result==3 && i<3) + { + if(this->Faces[p][i]<0) + { + i=3; // no common face + } + else + { + int j=0; + while(result==3 && j<3) + { + if(this->Faces[q][j]<0) + { + j=3; // end of the edges of q, skip to next i + } + else + { + if(this->Faces[p][i]==this->Faces[q][j]) + { + parentId=this->Faces[p][i]; + result=2; + } + else + { + if(this->Faces[p][i]Faces[q][j]) + { + j=3; // no way to find a common face for this i, skip to next i + } + else + { + ++j; + } + } + } + } + ++i; + } + } + } + return result; + } + + + // Description: + // Set the edge parent of mid as parentEdge. + void SetParent(int mid, + signed char parentId, + int type) + { + assert("pre: mid-point" && mid>=4 && mid<=9); + assert("pre: valid_type" && type>=1 && type<=3); + assert("pre: id_match_type" && + ( (type==1 && parentId>=0 && parentId<=5) || + (type==2 && parentId>=0 && parentId<=3) || + (type==3 && parentId==-1) ) ); + + if(type==1) // edge + { + this->Edges[mid][0]=parentId; + // it means also that the point belongs to two faces + // the id of the faces can be found thanks to the edge id + switch(parentId) + { + case 0: + this->Faces[mid][0]=0; + this->Faces[mid][1]=3; + break; + case 1: + this->Faces[mid][0]=1; + this->Faces[mid][1]=3; + break; + case 2: + this->Faces[mid][0]=2; + this->Faces[mid][1]=3; + break; + case 3: + this->Faces[mid][0]=0; + this->Faces[mid][1]=2; + break; + case 4: + this->Faces[mid][0]=0; + this->Faces[mid][1]=1; + break; + case 5: + this->Faces[mid][0]=1; + this->Faces[mid][1]=2; + break; + default: + assert("check: impossible case" && 0); + } + + } + else // face (type==2 parentId!=-1) or no parent (parentId==-1 type==3) + { + this->Edges[mid][0]=-1; + this->Faces[mid][0]=parentId; + this->Faces[mid][1]=-1; + } + this->Edges[mid][1]=-1; // always for mid-points + this->Edges[mid][2]=-1; // always for mid-points + this->Faces[mid][2]=-1; // always for mid-points + } + + // Description: + // Return if the four corner points of the tetra are all differents +#ifndef NDEBUG + int PointsDifferents() + { + int result=1; + int i; + int j; + int k; + + i = 0; + while(i<3 && result) + { + j = i+1; + while(j<4 && result) + { + result = this->PointId[i] != this->PointId[j]; + ++j; + } + ++i; + } + if(result) // point id are ok, now test the coordinates + { + i = 0; + while(i<3 && result) + { + j = i+1; + while(j<4 && result) + { + k = 0; + result = 0; + while(k<3) + { + result = result || (this->Vertex[i][k] != this->Vertex[j][k]); + ++k; + } + ++j; + } + ++i; + } + } + + return result; + } +#endif + +private: + // Need to keep track of local coordinate to evaluate shape functions + // So all work is done in parametric coordinate + + double Vertex[4+6][3]; // 4 tetra points + 6 mid edge points + vtkIdType PointId[4+6]; + int SubdivisionLevel; + + // local ids (-1 to 5) of the original edges on which the points are. + // a point can be on almost 3 edges: + // * only a vertex of the original tetrahedron is on 3 edges + // * the mid-points can be only on 1 edge + // * -1 encodes no edge + // * each array is an increasing list of ids terminated by -1 is no edge + signed char Edges[4+6][3]; + // local ids (-1 to 3) of the original faces on which the points are. + // a point can be on almost 3 faces: + // * only a vertex of the original tetrahedron is on 3 faces + // * the mid-points can be only on 2 faces + // * a mid-point which is on two faces is also on one edge. + // * -1 encodes no face + // * each array is an increasing list of ids terminated by -1 is no face + signed char Faces[4+6][3]; + + int *EdgeIds; + int *FaceIds; +}; + +//----------------------------------------------------------------------------- +int vtkTriangleTile::Refine(vtkSimpleCellTessellator* tess, + vtkTriangleTile *res ) +{ + // The output will contain a maximum of 4 vtkTriangleTiles + int i, index; + int numTriangleCreated = 0; + + double edgeSplitList[3]; + vtkIdType ptId = 0; + int l, r; + + if(this->SubdivisionLevel < tess->GetMaxSubdivisionLevel()) + { + // loop over edges + for(i=0, index=0; i<3; i++) + { + // we have to calculate mid point between edge TRIANGLE_EDGES_TABLE[i][0] + // and TRIANGLE_EDGES_TABLE[i][1] + l = TRIANGLE_EDGES_TABLE[i][0]; + r = TRIANGLE_EDGES_TABLE[i][1]; + + edgeSplitList[i] = tess->EdgeTable->CheckEdge(this->PointId[l], + this->PointId[r], ptId); + + // On previous step we made sure to prepare the hash table + assert("check: edge table prepared" && edgeSplitList[i] != -1); + + // Build the case table + if (edgeSplitList[i]) + { + index |= 1 << i; + } + } + + if( index ) + { + // That mean at least one edge was split and thus index != 0 + signed char *cases = **(vtkTessellatorTriangleCases + index); + + for(; cases[0] > -1; cases+=3) + { + for(int j=0; j<3; j++) + { + res[numTriangleCreated].CopyPoint(j,this,cases[j]); +// res[numTriangleCreated].SetPointId( j, this->PointId[cases[j]] ); +// res[numTriangleCreated].SetVertex( j, this->Vertex[cases[j]] ); + } + //update number of triangles + numTriangleCreated++; + } + //Insert edges from new triangle into hash table: + for(int k=0; k < numTriangleCreated; k++) + { + res[k].SubdivisionLevel = this->SubdivisionLevel + 1; + tess->InsertEdgesIntoEdgeTable( res[k] ); + } + } + } + + if(numTriangleCreated == 0) + { + // no edge were split so recursion is done + // add the cell array to the list + tess->TessellateCellArray->InsertNextCell(3, this->PointId); + + for(int j=0; j<3; j++) + { + tess->CopyPoint(this->PointId[j]); + } + } + + return numTriangleCreated; +} + +//----------------------------------------------------------------------------- +// Description: +// Extract point `pointId' from the edge table to the output point and output +// point data. +void vtkSimpleCellTessellator::CopyPoint(vtkIdType pointId) +{ + double point[3]; + double *p = this->Scalars; + + this->EdgeTable->CheckPoint(pointId, point, p); + // There will some be duplicate points during a while but + // this is the cost for speed: + this->TessellatePoints->InsertNextTuple( point ); +// this->TessellatePointData->InsertNextTuple( tess->Scalars ); + + int c = this->TessellatePointData->GetNumberOfArrays(); + vtkDataArray *attribute; + + for(int i=0; iTessellatePointData->GetArray(i); + attribute->InsertNextTuple(p); + p += attribute->GetNumberOfComponents(); + } +} + +//----------------------------------------------------------------------------- +static void Reorder(vtkIdType in[4], vtkIdType order[4]) +{ + // Input: in[4] contains pointId of a tetra in right hand rule. + // Output: this function reorders so that: + // out[0] < out[1] + // out[0] < out[2] + // out[0] < out[3] + // out[1] < out[2] + // out[1] < out[3] + // and still respect the right hand rule for tetra: + + + vtkIdType min1 = in[0]; + vtkIdType min2 = in[1]; + vtkIdType idx1 = 0; + vtkIdType idx2 = 1; + for(int i=1;i<4;i++) + { + if(min1 > in[i]) + { + min2 = min1; + idx2 = idx1; + min1 = in[i]; + idx1 = i; + } + else if(min2 > in[i]) + { + min2 = in[i]; + idx2 = i; + } + } + + // For debug: + // order[0] = order[1] = order[2] = order[3] = -1; + order[0] = idx1; + order[1] = idx2; + + if(idx1 == 0) + { + if(idx2 == 1) + { + order[2] = 2; + order[3] = 3; + } + else if(idx2 == 2) + { + order[2] = 3; + order[3] = 1; + } + else if(idx2 == 3) + { + order[2] = 1; + order[3] = 2; + } + } + else if(idx1 == 1) + { + if(idx2 == 0) + { + order[2] = 3; + order[3] = 2; + } + else if(idx2 == 2) + { + order[2] = 0; + order[3] = 3; + } + else if(idx2 == 3) + { + order[2] = 2; + order[3] = 0; + } + } + else if(idx1 == 2) + { + if(idx2 == 0) + { + order[2] = 1; + order[3] = 3; + } + else if(idx2 == 1) + { + order[2] = 3; + order[3] = 0; + } + else if(idx2 == 3) + { + order[2] = 0; + order[3] = 1; + } + } + else if(idx1 == 3) + { + if(idx2 == 0) + { + order[2] = 2; + order[3] = 1; + } + else if(idx2 == 1) + { + order[2] = 0; + order[3] = 2; + } + else if(idx2 == 2) + { + order[2] = 1; + order[3] = 0; + } + } +} + + +//----------------------------------------------------------------------------- +int vtkTetraTile::Refine(vtkSimpleCellTessellator* tess, + vtkTetraTile *res) +{ + // The output will contains a maximum of 8 vtkTetraTiles + int i, index; + int numTetraCreated = 0; + + // We need to order the point by lower id first + // this will create an edge ordering and based on that we can + // find which edge is split this gives us a mask for the tessellation + + // There is only 6 edges in a tetra we need this structure to quickly + // determine in which case we are to tessellate the tetra. + int edgeSplitList[6]; + vtkIdType ptId = 0; + int l, r; + + if(this->SubdivisionLevel < tess->GetMaxSubdivisionLevel()) + { + // loop over edges: + for(i=0, index=0; i<6; i++) + { + // we have to calculate mid point between edge TETRA_EDGES_TABLE[i][0] and + // TETRA_EDGES_TABLE[i][1] + l = TETRA_EDGES_TABLE[i][0]; + r = TETRA_EDGES_TABLE[i][1]; + + edgeSplitList[i] = tess->EdgeTable->CheckEdge(this->PointId[l], + this->PointId[r], ptId); + + // On previous step we made sure to prepare the hash table + assert("check: edge table prepared" && edgeSplitList[i] != -1); + + // Build the case table + if (edgeSplitList[i]) + { + index |= 1 << i; + } + } + + if( index ) + { + // That mean at least one edge was split and thus index != 0 + vtkIdType tetra[4], order[4]; + signed char *cases; + + // we compare right away PointId[2] to PointId[3] because we assume + // input tetra is already ordered properly (cf. Reorder previous step) + if(this->PointId[2] < this->PointId[3]) + { + cases = **(vtkTessellatorTetraCasesRight + index); + } + else + { + cases = **(vtkTessellatorTetraCasesLeft + index); + } + + // For each sub-tetra, increment number of tetra created + // And check each of its edges if its in the hash table + int k; + + for(; cases[0]> -1; cases+=4) + { + for(k=0; k<4; k++) + { + tetra[k] = this->PointId[cases[k]]; + } + + // The whole purpose of Reorder is really to classify the tetra, the + // reordering is only useful for quick testing. The tet will either + // classify as Right ordered or Left ordered + Reorder(tetra, order); + + // Set the tetras point for the next recursion + for(int j=0;j<4;j++) + { + res[numTetraCreated].CopyPoint(j,this,cases[order[j]]); + } + res[numTetraCreated].CopyEdgeAndFaceIds(this); + numTetraCreated++; + } + k = 0; + while(k < numTetraCreated) + { + res[k].SubdivisionLevel = this->SubdivisionLevel + 1; + tess->InsertEdgesIntoEdgeTable( res[k] ); + ++k; + } + } + } + + if(numTetraCreated == 0) + { + // no edge were split so recursion is done + // add the cell array to the list + tess->TessellateCellArray->InsertNextCell(4, this->PointId); + + for(int j=0; j<4; j++) + { + tess->CopyPoint(this->PointId[j]); + } + } + + return numTetraCreated; +} + +//----------------------------------------------------------------------------- +// Create the tessellator helper with a default of 0.25 for threshold +// +vtkSimpleCellTessellator::vtkSimpleCellTessellator() +{ + this->GenericCell = NULL; + + this->TessellatePoints = NULL; + this->TessellateCellArray = NULL; + this->TessellatePointData = NULL; + + this->EdgeTable = vtkGenericEdgeTable::New(); + + this->AttributeCollection = NULL; + + this->CellIterator = 0; + this->Scalars = 0; + this->ScalarsCapacity = 0; + this->PointOffset = 0; + + this->DataSet = 0; + + this->FixedSubdivisions = 0; // 0 means no fixed subdivision + this->MaxSubdivisionLevel = 0; // 0 means no subdivision at all + this->CurrentSubdivisionLevel = 0; + + + this->Triangulator=vtkOrderedTriangulator::New(); + this->Triangulator->UseTemplatesOn(); + + this->PointIds=0; + this->PointIdsCapacity=0; + + this->Connectivity=vtkCellArray::New(); + this->Polygon=vtkPolygon::New(); + this->TriangleIds=vtkIdList::New(); + this->TriangleIds->Allocate(VTK_CELL_SIZE); +} + +//----------------------------------------------------------------------------- +vtkSimpleCellTessellator::~vtkSimpleCellTessellator() +{ + this->EdgeTable->Delete(); + if(this->CellIterator) + { + this->CellIterator->Delete(); + } + if(this->Scalars) + { + delete[] this->Scalars; + } + + this->Triangulator->Delete(); + if(this->PointIds!=0) + { + delete[] this->PointIds; + } + this->Connectivity->Delete(); + this->Polygon->Delete(); + this->TriangleIds->Delete(); +} + +//----------------------------------------------------------------------------- +// This function is supposed to be called only at toplevel (for passing data +// from third party to the hash point table) +void vtkSimpleCellTessellator::InsertPointsIntoEdgeTable(vtkTriangleTile &tri) +{ + double global[3]; + + for(int j=0; j<3; j++) + { + // Need to check first if point is not already in the hash table + // since EvaluateLocation / EvaluateTuple are expensive calls + if( !this->EdgeTable->CheckPoint(tri.GetPointId(j)) ) + { + // it's real space coordinate: + this->GenericCell->EvaluateLocation(0,tri.GetVertex(j), global); + + // Then scalar value associated with point: + this->GenericCell->InterpolateTuple(this->AttributeCollection, + tri.GetVertex(j), this->Scalars); + + //Put everything in ths point hash table + this->EdgeTable->InsertPointAndScalar(tri.GetPointId(j), global, + this->Scalars); + } + } +} + +//----------------------------------------------------------------------------- +// +void vtkSimpleCellTessellator::InsertEdgesIntoEdgeTable(vtkTriangleTile &tri ) +{ + double *local = 0; + vtkIdType tmp; + vtkIdType l, r; + vtkIdType cellId = this->GenericCell->GetId(); + + const double alpha = 0.5; + assert("check: normalized alpha" && alpha>0 && alpha<1); + + //First setup the point reference count: + for(int i = 0; i<3; i++) + { + this->EdgeTable->IncrementPointReferenceCount(tri.GetPointId(i)); + } + + double *leftPoint = this->Scalars; + double *midPoint = this->Scalars + this->PointOffset; + double *rightPoint = midPoint + this->PointOffset; + + + // Loop over all edges: + // For each edge: + // if in hash table: incr ref + // else: evaluate & put in table ref = 1 + for(int j=0; j<3; j++) + { + l = TRIANGLE_EDGES_TABLE[j][0]; + r = TRIANGLE_EDGES_TABLE[j][1]; + + vtkIdType leftId = tri.GetPointId(l); + vtkIdType rightId = tri.GetPointId(r); + + if(leftId > rightId) + { + // ensure that the left point has the smallest id + // hence, evaluation occurs in the same direction in any case + // the computations of error and interpolation will not suffer from + // numerical precision. + tmp = leftId; + leftId = rightId; + rightId = tmp; + + tmp = l; + l = r; + r = tmp; + } + + double *left = tri.GetVertex(l); + double *right = tri.GetVertex(r); + + memcpy(leftPoint + PARAMETRIC_OFFSET, left, sizeof(double)*3); + memcpy(rightPoint + PARAMETRIC_OFFSET, right, sizeof(double)*3); + + //Check first in the hash table + vtkIdType ptId = -1; + + // To calculate the edge ref count, we either: + // - find it in the hash table + // - calculate from higher order cell: + + int toSplit = this->EdgeTable->CheckEdge(leftId, rightId, ptId); + int doSubdivision; + + if( toSplit == -1) + { + // The edge was not found in the hash table, that mean we have to + // determine it's reference counting from the higher order cell: + + signed char parentEdge=tri.FindEdgeParent(l,r); + int refCount; + if(parentEdge==-1) + { + // no parent + refCount = 1; + } + else + { + refCount = this->GetNumberOfCellsUsingEdge(parentEdge); + } + + doSubdivision = tri.GetSubdivisionLevel() < this->GetMaxSubdivisionLevel(); + + // + // For measurement of the quality of a fixed subdivision. + // + if(!doSubdivision) // done + { + if(this->GetMaxSubdivisionLevel()==this->GetFixedSubdivisions()) + { + // fixed subdivision only + if(this->GetMeasurement()) + { + // global position and attributes at the left vertex + this->EdgeTable->CheckPoint(leftId,leftPoint, + leftPoint + ATTRIBUTES_OFFSET); + // global position and attributes at the right vertex + this->EdgeTable->CheckPoint(rightId,rightPoint, + rightPoint + ATTRIBUTES_OFFSET); + + // parametric center of the edge + local = midPoint + PARAMETRIC_OFFSET; + + for(int i=0; i<3; i++) + { + local[i] = left[i] + alpha*(right[i] - left[i]); + } + // global position of the center + this->GenericCell->EvaluateLocation(0,local,midPoint); + + // attributes at the center + this->GenericCell->InterpolateTuple(this->AttributeCollection, + local, + midPoint+ATTRIBUTES_OFFSET); + this->UpdateMaxError(leftPoint,midPoint,rightPoint,alpha); + } + } + } + // + // + // + + + if(doSubdivision) + { + // global position and attributes at the left vertex + this->EdgeTable->CheckPoint(leftId, leftPoint, + leftPoint + ATTRIBUTES_OFFSET); + // global position and attributes at the right vertex + this->EdgeTable->CheckPoint(rightId, rightPoint, + rightPoint + ATTRIBUTES_OFFSET); + + // parametric center of the edge + local = midPoint + PARAMETRIC_OFFSET; + for(int i=0; i < 3; i++) + { + local[i] = left[i] + alpha*(right[i] - left[i]); + } + // is the mid point different from both the left and right point? + // if not, we do not subdivide, it is a degenerated case. + //doSubdivision = tri.DifferentFromOriginals(local); + doSubdivision = (alpha != 0.0 && alpha != 1.0); + + if(doSubdivision) + { + // global position of the center + this->GenericCell->EvaluateLocation(0,local,midPoint); + + // attributes at the center + this->GenericCell->InterpolateTuple(this->AttributeCollection, local, + midPoint + ATTRIBUTES_OFFSET); + + doSubdivision = tri.GetSubdivisionLevel() < this->GetFixedSubdivisions(); + if(!doSubdivision) // fixed subdivision is done, need adaptive one? + { + doSubdivision = this->RequiresEdgeSubdivision(leftPoint,midPoint, + rightPoint,alpha); + } + } + } // first doSubdivision + + if(doSubdivision) + { + this->EdgeTable->InsertEdge(leftId, rightId, cellId, refCount, ptId); + assert("check: id exists" && ptId != -1 ); + + // And also the value we'll have to put to avoid recomputing them later: + + //Save mid point: + tri.SetVertex(j+3, local); + tri.SetPointId(j+3, ptId); + tri.SetEdgeParent(j+3,parentEdge); + + //Put everything in ths point hash table + this->EdgeTable->InsertPointAndScalar(ptId, midPoint, + midPoint + ATTRIBUTES_OFFSET); + } + else + { + // The edge does not need to be split simply insert it + this->EdgeTable->InsertEdge(leftId, rightId, cellId, refCount); + } + } + else + { + // else the edge is in the table we need to increment its ref count. + // This becomes tricky when we are incrementing an edge shared across + // cell, we should not increment edge ref count when first time in a cell + // Precondition third package have unique cellId. + this->EdgeTable->IncrementEdgeReferenceCount(leftId, rightId, cellId); + + if(toSplit == 1) // we cannot just right if(toSplit) because it can be -1 + { + tri.SetPointId(j+3, ptId); + + double pcoords[3]; + pcoords[0] = tri.GetVertex(l)[0] + alpha*(tri.GetVertex(r)[0] - tri.GetVertex(l)[0]); + pcoords[1] = tri.GetVertex(l)[1] + alpha*(tri.GetVertex(r)[1] - tri.GetVertex(l)[1]); + pcoords[2] = tri.GetVertex(l)[2] + alpha*(tri.GetVertex(r)[2] - tri.GetVertex(l)[2]); + + tri.SetVertex(j+3, pcoords); + // note we dont need to call SetEdgeParent() because + // if the edge is already in the hashtable it means that + // it is already tessellated. All other point using this + // edge will come from either inside the triangle either from + // and another edge. For sur the resulting edge will be inside (-1) + tri.SetEdgeParent(j+3,-1); + } + } + } +} + +//----------------------------------------------------------------------------- +// +void vtkSimpleCellTessellator::InsertEdgesIntoEdgeTable( vtkTetraTile &tetra ) +{ + double *local = 0; + + vtkIdType tmp; + vtkIdType l, r; + const vtkIdType cellId = this->GenericCell->GetId(); + +// double alpha=0.5+0.02*(rand()/(RAND_MAX+1.0)-0.5); + const double alpha = 0.5; + assert("check: normalized alpha" && alpha>0 && alpha<1); + + //First setup the point reference count: + for(int i=0; i<4; i++) + { + this->EdgeTable->IncrementPointReferenceCount(tetra.GetPointId(i)); + } + + double *leftPoint = this->Scalars; + double *midPoint = this->Scalars + this->PointOffset; + double *rightPoint = midPoint + this->PointOffset; + + // Loop over all edges: + // For each edge: + // if in hash table: incr ref + // else: evaluate & put in table ref = 1 + for(int j=0; j<6; j++) + { + l = TETRA_EDGES_TABLE[j][0]; + r = TETRA_EDGES_TABLE[j][1]; + + vtkIdType leftId = tetra.GetPointId(l); + vtkIdType rightId = tetra.GetPointId(r); + + if(leftId > rightId) + { + // ensure that the left point has the smallest id + // hence, evaluation occurs in the same direction in any case + // the computations of error and interpolation will not suffer from + // numerical precision. + tmp = leftId; + leftId = rightId; + rightId = tmp; + + tmp = l; + l = r; + r = tmp; + } + + double *left = tetra.GetVertex(l); + double *right = tetra.GetVertex(r); + + memcpy(leftPoint + PARAMETRIC_OFFSET, left, sizeof(double)*3); + memcpy(rightPoint + PARAMETRIC_OFFSET, right, sizeof(double)*3); + + //Check first in the hash table + vtkIdType ptId = -1; + int refCount = 1; + + //vtkDebugMacro( << "InsertEdgesIntoEdgeTable:" << leftId << "," << rightId ); + + // To calculate the edge ref count, we either: + // - find it in the hash table + // - calculate from higher order cell: + + int toSplit = this->EdgeTable->CheckEdge(leftId, rightId, ptId); + int doSubdivision; + + if( toSplit == -1) + { + // The edge was not found in the hash table, that mean we have to + // determine it's reference counting from the higher order cell: + + + signed char parentId; + int type=tetra.FindEdgeParent(l,r,parentId); + if(type == 1) + { + // On edge: + refCount = this->GetNumberOfCellsUsingEdge( tetra.GetEdgeIds(parentId) ); + } + else if(type == 2) + { + //On face: + refCount = this->GetNumberOfCellsUsingFace( tetra.GetFaceIds(parentId) ); + } + else if(type == 3) + { + // Inside: + refCount = 1; + } + + doSubdivision = tetra.GetSubdivisionLevel() < this->GetMaxSubdivisionLevel(); + + // + // For measurement of the quality of a fixed subdivision. + // + if(!doSubdivision) // done + { + if(this->GetMaxSubdivisionLevel()==this->GetFixedSubdivisions()) + { + // fixed subdivision only + if(this->GetMeasurement()) + { + // global position and attributes at the left vertex + this->EdgeTable->CheckPoint(leftId,leftPoint, + leftPoint + ATTRIBUTES_OFFSET); + // global position and attributes at the right vertex + this->EdgeTable->CheckPoint(rightId,rightPoint, + rightPoint + ATTRIBUTES_OFFSET); + + // parametric center of the edge + local = midPoint + PARAMETRIC_OFFSET; + + for(int i=0; i<3; i++) + { + local[i] = left[i] + alpha*(right[i] - left[i]); + } + // global position of the center + this->GenericCell->EvaluateLocation(0,local,midPoint); + + // attributes at the center + this->GenericCell->InterpolateTuple(this->AttributeCollection, + local, + midPoint+ATTRIBUTES_OFFSET); + this->UpdateMaxError(leftPoint,midPoint,rightPoint,alpha); + } + } + } + // + // + // + + if(doSubdivision) + { + // global position and attributes at the left vertex + this->EdgeTable->CheckPoint(leftId,leftPoint, + leftPoint + ATTRIBUTES_OFFSET); + // global position and attributes at the right vertex + this->EdgeTable->CheckPoint(rightId,rightPoint, + rightPoint + ATTRIBUTES_OFFSET); + + // parametric center of the edge + local = midPoint + PARAMETRIC_OFFSET; + + for(int i=0; i<3; i++) + { + local[i] = left[i] + alpha*(right[i] - left[i]); + } + // is the mid point different from both the left and right point? + // if not, we do not subdivide, it is a degenerated case. + //doSubdivision=tetra.DifferentFromOriginals(local); + doSubdivision = (alpha != 0.0 && alpha != 1.0); + + if(doSubdivision) + { + // global position of the center + this->GenericCell->EvaluateLocation(0,local,midPoint); + + // attributes at the center + this->GenericCell->InterpolateTuple(this->AttributeCollection, local, + midPoint + ATTRIBUTES_OFFSET); + + doSubdivision = tetra.GetSubdivisionLevel() < this->GetFixedSubdivisions(); + if(!doSubdivision) // fixed subdivision is done, need adaptive one? + { + doSubdivision = this->RequiresEdgeSubdivision(leftPoint,midPoint, + rightPoint,alpha); + } + } + + } // first doSubdivision + + if(doSubdivision) + { + this->EdgeTable->InsertEdge(leftId, rightId, cellId, refCount, ptId); + assert("check: id exists" && ptId != -1 ); + + // And also the value we'll have to put to avoid recomputing them later: + //Save mid point: + tetra.SetVertex(j+4, local); + tetra.SetPointId(j+4, ptId); + tetra.SetParent(j+4,parentId,type); + + //Put everything in the point hash table + this->EdgeTable->InsertPointAndScalar(ptId, midPoint, + midPoint + ATTRIBUTES_OFFSET); + } + else + { + // The edge does not need to be split simply insert it + this->EdgeTable->InsertEdge(leftId, rightId, cellId, refCount); + } + } + else + { + // else the edge is in the table we need to increment its ref count. + // This becomes tricky when we are incrementing an edge shared across + // cell, we should not increment edge ref count when first time in a cell + // Precondition third package have unique cellId. + this->EdgeTable->IncrementEdgeReferenceCount(leftId, rightId, cellId); + + //vtkDebugMacro( << "IncrementEdgeReferenceCount:" << ptId ); + + if(toSplit == 1) // we cannot just right if(toSplit) because it can be -1 + { + tetra.SetPointId(j+4, ptId); + + double pcoords[3]; + pcoords[0] = tetra.GetVertex(l)[0]+ alpha*(tetra.GetVertex(r)[0] - tetra.GetVertex(l)[0]); + pcoords[1] = tetra.GetVertex(l)[1]+ alpha*(tetra.GetVertex(r)[1] - tetra.GetVertex(l)[1]); + pcoords[2] = tetra.GetVertex(l)[2]+ alpha*(tetra.GetVertex(r)[2] - tetra.GetVertex(l)[2]); + assert("not degenerated" && !(((left[0] == pcoords[0]) + && (left[1] == pcoords[1]) + && (left[2] == pcoords[2])) + || ((right[0] == pcoords[0]) + && (right[1] == pcoords[1]) + && (right[2] == pcoords[2])))); + + tetra.SetVertex(j+4, pcoords); + + signed char parentId; + int type=tetra.FindEdgeParent(l,r,parentId); + + tetra.SetParent(j+4,parentId,type); //tetra.SetParent(j+4,-1,3); + } + } + } +} + +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::RemoveEdgesFromEdgeTable( vtkTriangleTile &tri ) +{ + vtkIdType l,r; + int i; + + // First setup the point reference count: + for(i=0; i<3; i++) + { + this->EdgeTable->RemovePoint( tri.GetPointId(i)); + } + + // Clean the hash table by removing all edges from this tet, loop over edges: + for(i=0; i<3; i++) + { + l = TRIANGLE_EDGES_TABLE[i][0]; + r = TRIANGLE_EDGES_TABLE[i][1]; + + this->EdgeTable->RemoveEdge(tri.GetPointId(l), tri.GetPointId(r)); + } +} +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::RemoveEdgesFromEdgeTable( vtkTetraTile &tetra ) +{ + vtkIdType l,r; + int i; + + // First setup the point reference count: + for(i=0; i<4; i++) + { + this->EdgeTable->RemovePoint( tetra.GetPointId(i)); + } + + // Clean the hash table by removing all edges from this tet, loop over edges: + for(i=0; i<6; i++) + { + l = TETRA_EDGES_TABLE[i][0]; + r = TETRA_EDGES_TABLE[i][1]; + + vtkIdType ll = tetra.GetPointId(l); + vtkIdType rr = tetra.GetPointId(r); + + this->EdgeTable->RemoveEdge(ll, rr); + } +} + +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::Reset() +{ + // No memory deletion should happen here, as one cell to another there + // should be the same amount of points to tessellate + this->TessellatePoints->Reset(); + this->TessellateCellArray->Reset(); +} + +//----------------------------------------------------------------------------- +// Description: +// Initialize the tessellator with a data set `ds'. +void vtkSimpleCellTessellator::Initialize(vtkGenericDataSet *ds) +{ + this->DataSet = ds; + + if(this->DataSet) + { + this->NumberOfPoints = this->DataSet->GetNumberOfPoints(); + this->EdgeTable->Initialize(this->NumberOfPoints); + } +} + +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::Tessellate(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd ) +{ + assert("pre: cell_exists" && cell!=0); + assert("pre: valid_dimension" && cell->GetDimension()==3); + assert("pre: att_exists" && att!=0); + assert("pre: points_exists" && points!=0); + assert("pre: cellArray_exists" && cellArray!=0); + assert("pre: internalPd_exists" && internalPd!=0); + + int j; + int numVertices; + + // Save parameter for later use + this->GenericCell = cell; + this->TessellatePoints = points; + this->TessellateCellArray = cellArray; + this->TessellatePointData = internalPd; + this->AttributeCollection = att; + if(this->CellIterator==0) + { + this->CellIterator = cell->NewCellIterator(); + } + + // send the cell to the error metrics + this->SetGenericCell( cell ); + + int complexCell=cell->GetType()!=VTK_HIGHER_ORDER_TETRAHEDRON; + + if(complexCell) + { + numVertices=cell->GetNumberOfBoundaries(0); + } + else + { + numVertices=4; + } + + this->AllocatePointIds(numVertices); + cell->GetPointIds(this->PointIds); + + + // Init the edge table + this->EdgeTable->SetNumberOfComponents(internalPd->GetNumberOfComponents()); + this->PointOffset = internalPd->GetNumberOfComponents()+6; + this->AllocateScalars(this->PointOffset*3); + + // Insert the points of the complex cell into the hashtable + double global[3]; + for(j=0; jEdgeTable->CheckPoint(this->PointIds[j]) ) + { + double *pcoords=cell->GetParametricCoords() + 3*j; + // its real space coordinate: + cell->EvaluateLocation(0,pcoords, global); + + // Then scalar value associated with point: + cell->InterpolateTuple(this->AttributeCollection, + pcoords, this->Scalars); + + //Put everything in the point hash table + this->EdgeTable->InsertPointAndScalar(this->PointIds[j], global, + this->Scalars); + } + } + + vtkstd::queue work; + vtkTetraTile roots[10]; // up to 10 top-level sub-tetra + + // Put the top-levels subtetra in the work queue. + + if(complexCell) + { + this->Triangulator->PreSortedOff(); + this->Triangulator->InitTriangulation(0,1,0,1,0,1,numVertices); + int i=0; + double *pcoords=cell->GetParametricCoords(); + while(iTriangulator->InsertPoint(i,pcoords,pcoords,0); // 2 + ++i; + pcoords+=3; + } + this->Triangulator->Triangulate(); + this->Connectivity->Reset(); + this->Triangulator->AddTetras(0,this->Connectivity); // 1 + this->Connectivity->InitTraversal(); + vtkIdType npts=0; + vtkIdType *pts=0; + vtkIdType ids[4]; + + int numEdges=cell->GetNumberOfBoundaries(1); + int numFaces=cell->GetNumberOfBoundaries(2); + + int edgesIdsArray[6*10]; // 6 edges per sub-tetra, max of 10 sub-tetra + int faceIdsArray[4*10]; // 4 faces per sub-tetra, max of 10 sub-tetra + int *edgeIds=edgesIdsArray; + int *faceIds=faceIdsArray; + + int tetraId=0; + while(this->Connectivity->GetNextCell(npts,pts)) + { + assert("check: is a tetra" && npts==4); + // Get the point Ids (global) + j=0; + while(j<4) + { + ids[j]=this->PointIds[pts[j]]; + ++j; + } + // Get the edges Ids (local) +// int edgeIds[6]; + int *originalEdge; + int edge[2]; + j=0; + while(j<6) + { + edge[0]=pts[vtkTetra::GetEdgeArray(j)[0]]; + edge[1]=pts[vtkTetra::GetEdgeArray(j)[1]]; + int k=0; + edgeIds[j]=-1; + while(kGetEdgeArray(k); + if((originalEdge[0]==edge[0]&&originalEdge[1]==edge[1])|| + (originalEdge[0]==edge[1]&&originalEdge[1]==edge[0])) + { + edgeIds[j]=k; + } + ++k; + } + ++j; + } + + // Get the face Ids (local) +// int faceIds[4]; + int *originalFace; + int face[3]; + j=0; + while(j<4) + { + face[0]=pts[vtkTetra::GetFaceArray(j)[0]]; + face[1]=pts[vtkTetra::GetFaceArray(j)[1]]; + face[2]=pts[vtkTetra::GetFaceArray(j)[2]]; + int k=0; + faceIds[j]=-1; + while(kGetFaceArray(k); + + if(this->FacesAreEqual(originalFace,face)) + { + faceIds[j]=k; + } + ++k; + } + ++j; + } + + this->InitTetraTile(roots[tetraId],pts,ids,edgeIds, faceIds); + work.push(roots[tetraId]); + + edgeIds=edgeIds+6; + faceIds=faceIds+4; + ++tetraId; + } // while(connectivity) + } + else + { + vtkIdType pts[4]={0,1,2,3}; // from sub-tetra tessellation + + // + // Get the edges Ids (local) + int edgeIds[6]; + int *originalEdge; + int edge[2]; + j=0; + while(j<6) + { + edge[0]=vtkTetra::GetEdgeArray(j)[0]; // faster that edge[0]=pts[vtkTetra::GetEdgeArray(j)[0]] + edge[1]=vtkTetra::GetEdgeArray(j)[1]; + int k=0; + edgeIds[j]=-1; + while(edgeIds[j]==-1) + { + originalEdge=cell->GetEdgeArray(k); + if((originalEdge[0]==edge[0]&&originalEdge[1]==edge[1])|| + (originalEdge[0]==edge[1]&&originalEdge[1]==edge[0])) + { + edgeIds[j]=k; + } + ++k; + } + ++j; + } + + // Get the face Ids (local) + int faceIds[4]; + int *originalFace; + int face[3]; + int numFaces=cell->GetNumberOfBoundaries(2); + j=0; + while(j<4) + { + face[0]=pts[vtkTetra::GetFaceArray(j)[0]]; + face[1]=pts[vtkTetra::GetFaceArray(j)[1]]; + face[2]=pts[vtkTetra::GetFaceArray(j)[2]]; + int k=0; + faceIds[j]=-1; + // kGetNumberOfBoundaries(2) is not required because with no tessellation + // all the faceIds array has to match with the original faces + while(kGetFaceArray(k); + if(this->FacesAreEqual(originalFace,face)) + { + faceIds[j]=k; + } + ++k; + } + ++j; + } + this->InitTetraTile(roots[0],pts,this->PointIds,edgeIds, faceIds); + work.push(roots[0]); + } + + // refine loop + int count=0; + while( !work.empty() ) + { + vtkTetraTile piece[8]; + vtkTetraTile curr = work.front(); + work.pop(); + + int n = curr.Refine( this, piece); + + for(int i = 0; iRemoveEdgesFromEdgeTable( curr ); + ++count; + } + + // remove the points of the complex cell from the hashtable + for(j=0; jEdgeTable->RemovePoint(this->PointIds[j]); + } +} + +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::InitTetraTile(vtkTetraTile &root, + vtkIdType *localIds, + vtkIdType *ids, + int *edgeIds, + int *faceIds) +{ + assert("pre: cell_exists" && this->GenericCell!=0); + assert("pre: localIds_exists" && localIds!=0); + assert("pre: ids_exists" && ids!=0); + assert("pre: edgeIds_exists" && edgeIds!=0); + assert("pre: faceIds_exists" && faceIds!=0); + +#ifndef NDEBUG + vtkIdType order[4] = {-1,-1,-1,-1}; +#else + vtkIdType order[4]; +#endif + int i; + double *point; + + Reorder(ids, order); + for(i=0; i<4; i++) + { + point = this->GenericCell->GetParametricCoords() + 3*localIds[order[i]]; + root.SetVertex(i, point); + root.SetPointId(i, ids[order[i]]); + } + root.SetOriginal(order,edgeIds,faceIds); + + //Prepare the hash table with the top-level edges: + this->InsertEdgesIntoEdgeTable( root ); +} +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "GenericCell: " << this->GenericCell << endl; + os << indent << "TessellatePointData: " + << this->TessellatePointData << endl; + os << indent << "TessellateCellArray: " + << this->TessellateCellArray << endl; + os << indent << "TessellatePoints: " + << this->TessellatePoints << endl; +} + +//----------------------------------------------------------------------------- +void +vtkSimpleCellTessellator::TessellateFace(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkIdType index, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd) +{ + assert("pre: cell_exists" && cell!=0); + assert("pre: valid_dimension" && cell->GetDimension()==3); + assert("pre: valid_index_range" && (index>=0) && (indexGetNumberOfBoundaries(2))); + assert("pre: att_exists" && att!=0); + assert("pre: points_exists" && points!=0); + assert("pre: cellArray_exists" && cellArray!=0); + assert("pre: internalPd_exists" && internalPd!=0); + + int j; + if(cell->GetType()!=VTK_HIGHER_ORDER_TETRAHEDRON) + { + // build a linear polygon, call tessellate() on it and iterate over each triangle + // by sending it to the tessellator + + int *faceVerts=cell->GetFaceArray(index); + int numVerts=cell->GetNumberOfVerticesOnFace(index); + this->Polygon->PointIds->SetNumberOfIds(numVerts); + this->Polygon->Points->SetNumberOfPoints(numVerts); + + this->AllocatePointIds(cell->GetNumberOfBoundaries(0)); + cell->GetPointIds(this->PointIds); + double *pcoords=cell->GetParametricCoords(); + + int i=0; + while(iPolygon->PointIds->SetId(i,i); // this->PointIds[i] + this->Polygon->Points->SetPoint(i, pcoords+3*faceVerts[i]); // should be global? + ++i; + } + + this->Polygon->Triangulate(this->TriangleIds); + + // now iterate over any sub-triangle and call triangulateface on it + vtkIdType pts[3]; + vtkIdType ids[3]; + int c=this->TriangleIds->GetNumberOfIds(); + i=0; + while(iTriangleIds->GetId(i)]; + // Get the point Ids (global) + ids[j]=this->PointIds[pts[j]]; + ++j; + ++i; + } + + // + // Get the edges Ids (local) + int edgeIds[3]; + int *originalEdge; + int edge[2]; + j=0; + int numEdges=cell->GetNumberOfBoundaries(1); + + while(j<3) + { + edge[0]=pts[TRIANGLE_EDGES_TABLE[j][0]]; + edge[1]=pts[TRIANGLE_EDGES_TABLE[j][1]]; + int k=0; + edgeIds[j]=-1; + while(kGetEdgeArray(k); + if((originalEdge[0]==edge[0]&&originalEdge[1]==edge[1])|| + (originalEdge[0]==edge[1]&&originalEdge[1]==edge[0])) + { + edgeIds[j]=k; + } + ++k; + } + ++j; + } + + // index is not used in the tessellator. + this->TriangulateTriangle(cell, pts,ids,edgeIds,att,points,cellArray, internalPd); + } + + } + else + { + vtkIdType pts[3]; // from sub-tetra tessellation + + this->AllocatePointIds(4); // tetra + cell->GetPointIds(this->PointIds); + + int *facepts = cell->GetFaceArray(index); + // we know we are using a tetra. + pts[0]=facepts[0]; + pts[1]=facepts[1]; + pts[2]=facepts[2]; + + vtkIdType ids[3]; + // Get the point Ids (global) + j=0; + while(j<3) + { + ids[j]=this->PointIds[pts[j]]; + ++j; + } + + // + // Get the edges Ids (local) + int edgeIds[3]; + int *originalEdge; + int edge[2]; + j=0; + while(j<3) + { + edge[0]=pts[TRIANGLE_EDGES_TABLE[j][0]]; + edge[1]=pts[TRIANGLE_EDGES_TABLE[j][1]]; + int k=0; + edgeIds[j]=-1; + while(edgeIds[j]==-1) + { + originalEdge=cell->GetEdgeArray(k); + if((originalEdge[0]==edge[0]&&originalEdge[1]==edge[1])|| + (originalEdge[0]==edge[1]&&originalEdge[1]==edge[0])) + { + edgeIds[j]=k; + } + ++k; + } + ++j; + } + + // index is not used in the tessellator. + this->TriangulateTriangle(cell, pts,ids,edgeIds,att,points,cellArray, internalPd); + } +} + +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::Triangulate(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd) +{ + assert("pre: cell_exists" && cell!=0); + assert("pre: valid_dimension" && cell->GetDimension()==2); + assert("pre: att_exists" && att!=0); + assert("pre: points_exists" && points!=0); + assert("pre: cellArray_exists" && cellArray!=0); + assert("pre: internalPd_exists" && internalPd!=0); + + int j; + + if(cell->GetType()!=VTK_HIGHER_ORDER_TRIANGLE) + { + // build a linear polygon, call tessellate() on it and iterate over each triangle + // by sending it to the tessellator + +// int *faceVerts=cell->GetFaceArray(index); // implicit +// int numVerts=cell->GetNumberOfVerticesOnFace(index); + int numVerts=cell->GetNumberOfBoundaries(0); + + this->Polygon->PointIds->SetNumberOfIds(numVerts); + this->Polygon->Points->SetNumberOfPoints(numVerts); + + this->AllocatePointIds(cell->GetNumberOfBoundaries(0)); + cell->GetPointIds(this->PointIds); + double *pcoords=cell->GetParametricCoords(); + + int i=0; + while(iPolygon->PointIds->SetId(i,i); // this->PointIds[i] + this->Polygon->Points->SetPoint(i, pcoords+3*i); // should be global? + ++i; + } + + this->Polygon->Triangulate(this->TriangleIds); + + // now iterate over any sub-triangle and call triangulateface on it + vtkIdType pts[3]; + vtkIdType ids[3]; + int c=this->TriangleIds->GetNumberOfIds(); + i=0; + while(iTriangleIds->GetId(i); + // Get the point Ids (global) + ids[j]=this->PointIds[pts[j]]; + ++j; + ++i; + } + + // + // Get the edges Ids (local) + int edgeIds[3]; + int *originalEdge; + int edge[2]; + j=0; + int numEdges=cell->GetNumberOfBoundaries(1); + + while(j<3) + { + edge[0]=pts[TRIANGLE_EDGES_TABLE[j][0]]; + edge[1]=pts[TRIANGLE_EDGES_TABLE[j][1]]; + int k=0; + edgeIds[j]=-1; + while(kGetEdgeArray(k); + if((originalEdge[0]==edge[0]&&originalEdge[1]==edge[1])|| + (originalEdge[0]==edge[1]&&originalEdge[1]==edge[0])) + { + edgeIds[j]=k; + } + ++k; + } + ++j; + } + + // index is not used in the tessellator. + this->TriangulateTriangle(cell, pts,ids,edgeIds,att,points,cellArray, internalPd); + } + } + else + { + vtkIdType pts[3]={0,1,2}; + int edgeIds[3]={0,1,2}; + this->AllocatePointIds(cell->GetNumberOfBoundaries(0)); + cell->GetPointIds(this->PointIds); + this->TriangulateTriangle(cell, pts, this->PointIds, edgeIds, att, + points, cellArray,internalPd); + + } +} + +//----------------------------------------------------------------------------- +void vtkSimpleCellTessellator::TriangulateTriangle(vtkGenericAdaptorCell *cell, + vtkIdType *localIds, + vtkIdType *ids, + int *edgeIds, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd) +{ + assert("pre: cell_exixts" && cell!=0); + assert("pre: localIds_exists" && localIds!=0); + assert("pre: ids_exists" && ids!=0); + assert("pre: edgeIds_exists" && edgeIds!=0); + + // Save parameter for later use + this->GenericCell = cell; + + this->TessellatePoints = points; + this->TessellateCellArray = cellArray; + this->TessellatePointData = internalPd; + + this->AttributeCollection = att; + + if(this->CellIterator==0) + { + this->CellIterator = cell->NewCellIterator(); + } + this->EdgeIds=edgeIds; + + this->SetGenericCell( cell ); + + vtkTriangleTile root; + double *point; + + int i; + for(i=0; i<3; i++) + { + point = this->GenericCell->GetParametricCoords() + 3*localIds[i]; + root.SetVertex(i, point); + root.SetPointId(i, ids[i]); + } + root.SetOriginal(); + + // Init the edge table + this->EdgeTable->SetNumberOfComponents(internalPd->GetNumberOfComponents()); + + this->PointOffset = internalPd->GetNumberOfComponents() + 6; + this->AllocateScalars(this->PointOffset*3); + + this->InsertPointsIntoEdgeTable( root ); + + //Prepare the hash table with the top-level edges: + this->InsertEdgesIntoEdgeTable( root ); + + vtkstd::queue< vtkTriangleTile > work; + vtkTriangleTile begin = vtkTriangleTile(root); + work.push( begin ); + + while( !work.empty() ) + { + vtkTriangleTile piece[4]; + vtkTriangleTile curr = work.front(); + work.pop(); + + int n = curr.Refine( this, piece ); + + for(i = 0; iRemoveEdgesFromEdgeTable( curr ); + } + + // remove top level points + for(i = 0; i<3; i++) + { + this->EdgeTable->RemovePoint( root.GetPointId(i) ); + } + + //this->EdgeTable->LoadFactor(); + //this->EdgeTable->DumpTable(); +} + +//#define SLOW_API 1 +//----------------------------------------------------------------------------- +// Return number of cells using edge #edgeId +int vtkSimpleCellTessellator::GetNumberOfCellsUsingEdge( int edgeId ) +{ + assert("pre: valid_range" && edgeId>=0 ); // && edgeId<=5); +#if SLOW_API + int result = 0; + this->GenericCell->GetBoundaryIterator(this->CellIterator, 1); + this->CellIterator->Begin(); + + int i = 0; + while(!this->CellIterator->IsAtEnd() && (i < edgeId) ) + { + this->CellIterator->Next(); + ++i; + } + + assert("check: cell_found" && i==edgeId); + // +1 because CountNeighbors does not include the cell itself. + result = this->GenericCell->CountNeighbors(this->CellIterator->GetCell())+1; + return result; +#else + // The cell with the greatest number of edges is the hexagonal prism + // 6*2+6 + int edgeSharing[18]; + this->GenericCell->CountEdgeNeighbors( edgeSharing ); + return edgeSharing[edgeId]+1; +#endif +} + +//----------------------------------------------------------------------------- +// Return number of cells using face #faceId +int vtkSimpleCellTessellator::GetNumberOfCellsUsingFace( int faceId ) +{ +#if SLOW_API + int result=0; + this->GenericCell->GetBoundaryIterator(this->CellIterator, 2); + this->CellIterator->Begin(); + + int i = 0; + while(!this->CellIterator->IsAtEnd() && ( i < faceId) ) + { + this->CellIterator->Next(); + ++i; + } + + assert("check: cell_found" && i==faceId); + // +1 because CountNeighbors does not include the cell itself. + result = this->GenericCell->CountNeighbors(this->CellIterator->GetCell())+1; + + return result; +#else + if( this->GenericCell->IsFaceOnBoundary( faceId ) ) + { + // So no other cell is using it: + return 1; + } + + //else this face is used by another cell + return 2; +#endif +} + +//----------------------------------------------------------------------------- +// Description: +// Allocate some memory if Scalars does not exists or is smaller than size. +// \pre positive_size: size>0 +void vtkSimpleCellTessellator::AllocateScalars(int size) +{ + assert("pre: positive_size" && size > 0); + + if(this->Scalars == 0) + { + this->Scalars = new double[size]; + this->ScalarsCapacity = size; + } + else + { + if(this->ScalarsCapacity < size) + { + delete[] this->Scalars; + this->Scalars = new double[size]; + this->ScalarsCapacity = size; + } + } +} + + +//----------------------------------------------------------------------------- +// Description: +// Return the number of fixed subdivisions. It is used to prevent from +// infinite loop in degenerated cases. For order 3 or higher, if the +// inflection point is exactly on the mid-point, error metric will not +// detect that a subdivision is required. 0 means no fixed subdivision: +// there will be only adaptive subdivisions. +// +// The algorithm first performs `GetFixedSubdivisions' non adaptive +// subdivisions followed by at most `GetMaxAdaptiveSubdivisions' adaptive +// subdivisions. Hence, there are at most `GetMaxSubdivisionLevel' +// subdivisions. +// \post positive_result: result>=0 && result<=GetMaxSubdivisionLevel() +int vtkSimpleCellTessellator::GetFixedSubdivisions() +{ + assert("post: positive_result" && this->FixedSubdivisions >= 0 && this->FixedSubdivisions <= this->MaxSubdivisionLevel); + return this->FixedSubdivisions; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the maximum level of subdivision. It is used to prevent from +// infinite loop in degenerated cases. For order 3 or higher, if the +// inflection point is exactly on the mid-point, error metric will not +// detect that a subdivision is required. 0 means no subdivision, +// neither fixed nor adaptive. +// \post positive_result: result>=GetFixedSubdivisions() +int vtkSimpleCellTessellator::GetMaxSubdivisionLevel() +{ + assert("post: positive_result" && this->MaxSubdivisionLevel >= this->FixedSubdivisions); + return this->MaxSubdivisionLevel; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the maximum number of adaptive subdivisions. +// \post valid_result: result==GetMaxSubdivisionLevel()-GetFixedSubdivisions() +int vtkSimpleCellTessellator::GetMaxAdaptiveSubdivisions() +{ + return this->MaxSubdivisionLevel - this->FixedSubdivisions; +} + +//----------------------------------------------------------------------------- +// Description: +// Set the number of fixed subdivisions. See GetFixedSubdivisions() for +// more explanations. +// \pre positive_level: level>=0 && level<=GetMaxSubdivisionLevel() +// \post is_set: GetFixedSubdivisions()==level +void vtkSimpleCellTessellator::SetFixedSubdivisions(int level) +{ + assert("pre: positive_level" && level >= 0 && level <= this->GetMaxSubdivisionLevel()); + this->FixedSubdivisions = level; +} + +//----------------------------------------------------------------------------- +// Description: +// Set the maximum level of subdivision. See GetMaxSubdivisionLevel() for +// more explanations. +// \pre positive_level: level>=GetFixedSubdivisions() +// \post is_set: level==GetMaxSubdivisionLevel() +void vtkSimpleCellTessellator::SetMaxSubdivisionLevel(int level) +{ + assert("pre: positive_level" && level >= this->GetFixedSubdivisions()); + this->MaxSubdivisionLevel = level; +} + +//----------------------------------------------------------------------------- +// Description: +// Set both the number of fixed subdivisions and the maximum level of +// subdivisions. See GetFixedSubdivisions(), GetMaxSubdivisionLevel() and +// GetMaxAdaptiveSubdivisions() for more explanations. +// \pre positive_fixed: fixed>=0 +// \pre valid_range: fixed<=maxLevel +// \post fixed_is_set: fixed==GetFixedSubdivisions() +// \post maxLevel_is_set: maxLevel==GetMaxSubdivisionLevel() +void vtkSimpleCellTessellator::SetSubdivisionLevels(int fixed, + int maxLevel) +{ + assert("pre: positive_fixed" && fixed >= 0); + assert("pre: valid_range" && fixed <= maxLevel); + this->FixedSubdivisions = fixed; + this->MaxSubdivisionLevel = maxLevel; +} + +//---------------------------------------------------------------------------- +// Description: +// Allocate some memory if PointIds does not exist or is smaller than size. +// \pre positive_size: size>0 +void vtkSimpleCellTessellator::AllocatePointIds(int size) +{ + assert("pre: positive_size" && size>0); + + if(this->PointIdsCapacityPointIds!=0) + { + delete[] this->PointIds; + } + this->PointIds=new vtkIdType[size]; + this->PointIdsCapacity=size; + } +} + +//---------------------------------------------------------------------------- +// Description: +// Are the faces `originalFace' and `face' equal? +// The result is independent from any order or orientation. +// \pre originalFace_exists: originalFace!=0 +int vtkSimpleCellTessellator::FacesAreEqual(int *originalFace, + int face[3]) +{ + assert("pre: originalFace_exists" && originalFace!=0); + + int result=0; + int i=0; + int j=1; + int k=2; + while(!result && i<3) + { + // counterclockwise + result=originalFace[0]==face[i] + && originalFace[1]==face[j] + && originalFace[2]==face[k]; + // clockwise + if(!result) + { + result=originalFace[0]==face[i] + && originalFace[2]==face[j] + && originalFace[1]==face[k]; + } + ++i; + ++j; + ++k; + + if(j>2) + { + j=0; + } + else + { + if(k>2) + { + k=0; + } + } + } + return result; +} diff --git a/Filtering/vtkSimpleCellTessellator.h b/Filtering/vtkSimpleCellTessellator.h new file mode 100644 index 0000000..b9d415a --- /dev/null +++ b/Filtering/vtkSimpleCellTessellator.h @@ -0,0 +1,389 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleCellTessellator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSimpleCellTessellator - helper class to perform cell tessellation +// .SECTION Description +// vtkSimpleCellTessellator is a helper class to perform adaptive tessellation +// of particular cell topologies. The major purpose for this class is to +// transform higher-order cell types (e.g., higher-order finite elements) +// into linear cells that can then be easily visualized by VTK. This class +// works in conjunction with the vtkGenericDataSet and vtkGenericAdaptorCell +// classes. +// +// This algorithm is based on edge subdivision. An error metric along each +// edge is evaluated, and if the error is greater than some tolerance, the +// edge is subdivided (as well as all connected 2D and 3D cells). The process +// repeats until the error metric is satisfied. Since the algorithm is based +// on edge subdivision it inherently avoid T-junctions. +// +// A significant issue addressed by this algorithm is to insure face +// compatibility across neigboring cells. That is, diagonals due to face +// triangulation must match to insure that the mesh is compatible. The +// algorithm employs a precomputed table to accelerate the tessellation +// process. The table was generated with the help of vtkOrderedTriangulator +// the basic idea is that the choice of diagonal is made only by considering the +// relative value of the point ids. +// +// .SECTION See Also +// vtkGenericCellTessellator vtkGenericSubdivisionErrorMetric vtkAttributesErrorMetric +// vtkGeometricErrorMetric vtkViewDependentErrorMetric + +#ifndef __vtkSimpleCellTessellator_h +#define __vtkSimpleCellTessellator_h + +#include "vtkGenericCellTessellator.h" + +class vtkTriangleTile; +class vtkTetraTile; +class vtkCellArray; +class vtkDoubleArray; +class vtkGenericEdgeTable; +class vtkGenericSubdivisionErrorMetric; +class vtkGenericAttributeCollection; +class vtkGenericAdaptorCell; +class vtkGenericCellIterator; +class vtkPointData; +class vtkOrderedTriangulator; +class vtkPolygon; +class vtkIdList; + +//----------------------------------------------------------------------------- +// +// The tessellation object +class VTK_FILTERING_EXPORT vtkSimpleCellTessellator : public vtkGenericCellTessellator +{ +public: + static vtkSimpleCellTessellator *New(); + vtkTypeRevisionMacro(vtkSimpleCellTessellator,vtkGenericCellTessellator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the higher order cell in order to access the evaluation function. + vtkGetObjectMacro(GenericCell, vtkGenericAdaptorCell); + + // Description: + // Tessellate a face of a 3D `cell'. The face is specified by the + // index value. + // The result is a set of smaller linear triangles in `cellArray' with + // `points' and point data `internalPd'. + // \pre cell_exists: cell!=0 + // \pre valid_dimension: cell->GetDimension()==3 + // \pre valid_index_range: (index>=0) && (indexGetNumberOfBoundaries(2)) + // \pre att_exists: att!=0 + // \pre points_exists: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + void TessellateFace(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkIdType index, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd); + + // Description: + // Tessellate a 3D `cell'. The result is a set of smaller linear + // tetrahedra in `cellArray' with `points' and point data `internalPd'. + // \pre cell_exists: cell!=0 + // \pre valid_dimension: cell->GetDimension()==3 + // \pre att_exists: att!=0 + // \pre points_exists: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + void Tessellate(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd ); + + // Description: + // Triangulate a 2D `cell'. The result is a set of smaller linear triangles + // in `cellArray' with `points' and point data `internalPd'. + // \pre cell_exists: cell!=0 + // \pre valid_dimension: cell->GetDimension()==2 + // \pre att_exists: att!=0 + // \pre points_exists: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre internalPd_exists: internalPd!=0 + void Triangulate(vtkGenericAdaptorCell *cell, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd); + + // Description: + // Reset the output for repeated use of this class. + void Reset(); + + + // Description: + // Initialize the tessellator with a data set `ds'. + void Initialize(vtkGenericDataSet *ds); + + // Description: + // Return the number of fixed subdivisions. It is used to prevent from + // infinite loop in degenerated cases. For order 3 or higher, if the + // inflection point is exactly on the mid-point, error metric will not + // detect that a subdivision is required. 0 means no fixed subdivision: + // there will be only adaptive subdivisions. + // + // The algorithm first performs `GetFixedSubdivisions' non adaptive + // subdivisions followed by at most `GetMaxAdaptiveSubdivisions' adaptive + // subdivisions. Hence, there are at most `GetMaxSubdivisionLevel' + // subdivisions. + // \post positive_result: result>=0 && result<=GetMaxSubdivisionLevel() + int GetFixedSubdivisions(); + + // Description: + // Return the maximum level of subdivision. It is used to prevent from + // infinite loop in degenerated cases. For order 3 or higher, if the + // inflection point is exactly on the mid-point, error metric will not + // detect that a subdivision is required. 0 means no subdivision, + // neither fixed nor adaptive. + // \post positive_result: result>=GetFixedSubdivisions() + int GetMaxSubdivisionLevel(); + + // Description: + // Return the maximum number of adaptive subdivisions. + // \post valid_result: result==GetMaxSubdivisionLevel()-GetFixedSubdivisions() + int GetMaxAdaptiveSubdivisions(); + + // Description: + // Set the number of fixed subdivisions. See GetFixedSubdivisions() for + // more explanations. + // \pre positive_level: level>=0 && level<=GetMaxSubdivisionLevel() + // \post is_set: GetFixedSubdivisions()==level + void SetFixedSubdivisions(int level); + + // Description: + // Set the maximum level of subdivision. See GetMaxSubdivisionLevel() for + // more explanations. + // \pre positive_level: level>=GetFixedSubdivisions() + // \post is_set: level==GetMaxSubdivisionLevel() + void SetMaxSubdivisionLevel(int level); + + // Description: + // Set both the number of fixed subdivisions and the maximum level of + // subdivisions. See GetFixedSubdivisions(), GetMaxSubdivisionLevel() and + // GetMaxAdaptiveSubdivisions() for more explanations. + // \pre positive_fixed: fixed>=0 + // \pre valid_range: fixed<=maxLevel + // \post fixed_is_set: fixed==GetFixedSubdivisions() + // \post maxLevel_is_set: maxLevel==GetMaxSubdivisionLevel() + void SetSubdivisionLevels(int fixed, + int maxLevel); + + +protected: + vtkSimpleCellTessellator(); + ~vtkSimpleCellTessellator(); + + // Description: + // Extract point `pointId' from the edge table to the output point and output + // point data. + void CopyPoint(vtkIdType pointId); + + // Description: + //HashTable instead of vtkPointLocator + vtkGenericEdgeTable *EdgeTable; + + void InsertEdgesIntoEdgeTable( vtkTriangleTile &tri ); + void RemoveEdgesFromEdgeTable( vtkTriangleTile &tri ); + void InsertPointsIntoEdgeTable( vtkTriangleTile &tri ); + + void InsertEdgesIntoEdgeTable( vtkTetraTile &tetra ); + void RemoveEdgesFromEdgeTable( vtkTetraTile &tetra ); + + // Description: + // Initialize `root' with the sub-tetra defined by the `localIds' points on + // the complex cell, `ids' are the global ids over the mesh of those points. + // The sub-tetra is also defined by the ids of its edges and of its faces + // relative to the complex cell. -1 means that the edge or the face of the + // sub-tetra is not an original edge or face of the complex cell. + // \pre cell_exists: this->GenericCell!=0 + // \pre localIds_exists: localIds!=0 + // \pre localIds_size: sizeof(localIds)==4 + // \pre ids_exists: ids!=0 + // \pre ids_size: sizeof(ids)==4 + // \pre edgeIds_exists: edgeIds!=0 + // \pre edgeIds_size: sizeof(edgeIds)==6 + // \pre faceIds_exists: faceIds!=0 + // \pre faceIds_size: sizeof(faceIds)==4 + void InitTetraTile(vtkTetraTile &root, + vtkIdType *localIds, + vtkIdType *ids, + int *edgeIds, + int *faceIds); + + // Description: + // Triangulate a triangle of `cell'. This triangle can be the top-level + // triangle if the cell is a triangle or a toplevel sub-triangle is the cell + // is a polygon, or a triangular face of a 3D cell or a top-level + // sub-triangle of a face of a 3D cell if the face is not a triangle. + // Arguments `localIds', `ids' and `edgeIds' have the same meaning than + // for InitTetraTile. + // \pre cell_exists: cell!=0 + // \pre localIds_exists: localIds!=0 + // \pre localIds_size: sizeof(localIds)==3 + // \pre ids_exists: ids!=0 + // \pre ids_size: sizeof(ids)==3 + // \pre edgeIds_exists: edgeIds!=0 + // \pre edgeIds_size: sizeof(edgeIds)==3 + void TriangulateTriangle(vtkGenericAdaptorCell *cell, + vtkIdType *localIds, + vtkIdType *ids, + int *edgeIds, + vtkGenericAttributeCollection *att, + vtkDoubleArray *points, + vtkCellArray *cellArray, + vtkPointData *internalPd); + + // Description: + // To access the higher order cell from third party library + vtkGenericAdaptorCell *GenericCell; + + // Description: + // Allocate some memory if Scalars does not exists or is smaller than size. + // \pre positive_size: size>0 + void AllocateScalars(int size); + + // Description: + // Scalar buffer used to save the interpolate values of the attributes + // The capacity is at least the number of components of the attribute + // collection ot the current cell. + + // Scalar buffer that stores the global coordinates, parametric coordinates, + // attributes at left, mid and right point. The format is: + // lxlylz lrlslt [lalb lcldle...] mxmymz mrmsmt [mamb mcmdme...] + // rxryrz rrrsrt [rarb rcrdre...] + // The ScalarsCapacity>=(6+attributeCollection->GetNumberOfComponents())*3 + + double *Scalars; + int ScalarsCapacity; + + // Description: + // Number of double value to skip to go to the next point into Scalars array + // It is 6+attributeCollection->GetNumberOfComponents() + int PointOffset; + + // Description: + // Used to iterate over edges boundaries in GetNumberOfCellsUsingEdges() + vtkGenericCellIterator *CellIterator; + + // Description: + // To access the higher order field from third party library + vtkGenericAttributeCollection *AttributeCollection; + + // Description: + // To avoid New/Delete + vtkDoubleArray *TessellatePoints; //Allow to use GetPointer + vtkCellArray *TessellateCellArray; + vtkPointData *TessellatePointData; + + int FindEdgeReferenceCount(double p1[3], double p2[3], + vtkIdType &e1, vtkIdType &e2); + + int GetNumberOfCellsUsingFace( int faceId ); + int GetNumberOfCellsUsingEdge( int edgeId ); + + // Description: + // Is the edge defined by vertices (`p1',`p2') in parametric coordinates on + // some edge of the original tetrahedron? If yes return on which edge it is, + // else return -1. + // \pre p1!=p2 + // \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) + // \post valid_result: (result==-1) || ( result>=0 && result<=5 ) + int IsEdgeOnFace(double p1[3], double p2[3]); + + // Description: + // Return 1 if the parent of edge defined by vertices (`p1',`p2') in + // parametric coordinates, is an edge; 3 if there is no parent (the edge is + // inside). If the parent is an edge, return its id in `localId'. + // \pre p1!=p2 + // \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) + // \post valid_result: (result==1)||(result==3) + int FindEdgeParent2D(double p1[3], double p2[3], int &localId); + + // Description: + // Return 1 if the parent of edge defined by vertices (`p1',`p2') in + // parametric coordinates, is an edge; 2 if the parent is a face, 3 if there + // is no parent (the edge is inside). If the parent is an edge or a face, + // return its id in `localId'. + // \pre p1!=p2 + // \pre p1 and p2 are in bounding box (0,0,0) (1,1,1) + // \post valid_result: result>=1 && result<=3 + int FindEdgeParent(double p1[3], double p2[3], int &localId); + + // Description: + // Allocate some memory if PointIds does not exist or is smaller than size. + // \pre positive_size: size>0 + void AllocatePointIds(int size); + + // Description: + // Are the faces `originalFace' and `face' equal? + // The result is independent from any order or orientation. + // \pre originalFace_exists: originalFace!=0 + int FacesAreEqual(int *originalFace, + int face[3]); + + // Description: + // Dataset to be tessellated. + vtkGenericDataSet *DataSet; + + // Description: + // Number of points in the dataset to be tessellated. + vtkIdType NumberOfPoints; + + int FixedSubdivisions; + int MaxSubdivisionLevel; + int CurrentSubdivisionLevel; + + // Description: + // For each edge (6) of the sub-tetra, there is the id of the original edge + // or -1 if the edge is not an original edge + int *EdgeIds; + // Description: + // For each face (4) of the sub-tetra, there is the id of the original face + // or -1 if the face is not an original face + int *FaceIds; + + // The following variables are for complex cells. + + // Used to create tetra from more complex cells, because the tessellator + // is supposed to deal with simplices only. + vtkOrderedTriangulator *Triangulator; + + // Used to store the sub-tetra during the tessellation of complex + // cells. + vtkCellArray *Connectivity; + + // Used to create triangles from a face of a complex cell. + vtkPolygon *Polygon; + + // Used to store the sub-triangles during the tessellation of complex cells. + vtkIdList *TriangleIds; + + vtkIdType *PointIds; + int PointIdsCapacity; + +private: + vtkSimpleCellTessellator(const vtkSimpleCellTessellator&); // Not implemented. + void operator=(const vtkSimpleCellTessellator&); // Not implemented. + + //BTX + friend class vtkTetraTile; + friend class vtkTriangleTile; + //ETX +}; + +#endif diff --git a/Filtering/vtkSimpleImageToImageFilter.cxx b/Filtering/vtkSimpleImageToImageFilter.cxx new file mode 100644 index 0000000..11356be --- /dev/null +++ b/Filtering/vtkSimpleImageToImageFilter.cxx @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleImageToImageFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSimpleImageToImageFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkSimpleImageToImageFilter, "$Revision: 1.15 $"); + +//---------------------------------------------------------------------------- +vtkSimpleImageToImageFilter::vtkSimpleImageToImageFilter() +{ +} + +//---------------------------------------------------------------------------- +vtkSimpleImageToImageFilter::~vtkSimpleImageToImageFilter() +{ +} + +int vtkSimpleImageToImageFilter::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed( outputVector )) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // always request the whole extent + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),6); + + return 1; +} + +int vtkSimpleImageToImageFilter::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the data object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + int inExt[6]; + input->GetExtent(inExt); + // if the input extent is empty then exit + if (inExt[1] < inExt[0] || + inExt[3] < inExt[2] || + inExt[5] < inExt[4]) + { + return 1; + } + + // Set the extent of the output and allocate memory. + output->SetExtent( + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); + output->AllocateScalars(); + + this->SimpleExecute(input, output); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkSimpleImageToImageFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkSimpleImageToImageFilter.h b/Filtering/vtkSimpleImageToImageFilter.h new file mode 100644 index 0000000..db89b2f --- /dev/null +++ b/Filtering/vtkSimpleImageToImageFilter.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleImageToImageFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSimpleImageToImageFilter - Generic image filter with one input. +// .SECTION Description +// vtkSimpleImageToImageFilter is a filter which aims to avoid much +// of the complexity associated with vtkImageAlgorithm (i.e. +// support for pieces, multi-threaded operation). If you need to write +// a simple image-image filter which operates on the whole input, use +// this as the superclass. The subclass has to provide only an execute +// method which takes input and output as arguments. Memory allocation +// is handled in vtkSimpleImageToImageFilter. Also, you are guaranteed to +// have a valid input in the Execute(input, output) method. By default, +// this filter +// requests it's input's whole extent and copies the input's information +// (spacing, whole extent etc...) to the output. If the output's setup +// is different (for example, if it performs some sort of sub-sampling), +// ExecuteInformation has to be overwritten. As an example of how this +// can be done, you can look at vtkImageShrink3D::ExecuteInformation. +// For a complete example which uses templates to support generic data +// types, see vtkSimpleFilterExample. + +// .SECTION See also +// vtkImageAlgorithm vtkSimpleImageFilterExample + +#ifndef __vtkSimpleImageToImageFilter_h +#define __vtkSimpleImageToImageFilter_h + +#include "vtkImageAlgorithm.h" + +class VTK_FILTERING_EXPORT vtkSimpleImageToImageFilter : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSimpleImageToImageFilter,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkSimpleImageToImageFilter(); + ~vtkSimpleImageToImageFilter(); + + // These are called by the superclass. + virtual int RequestUpdateExtent (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + // You don't have to touch this unless you have a good reason. + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + // In the simplest case, this is the only method you need to define. + virtual void SimpleExecute(vtkImageData* input, vtkImageData* output) = 0; + +private: + vtkSimpleImageToImageFilter(const vtkSimpleImageToImageFilter&); // Not implemented. + void operator=(const vtkSimpleImageToImageFilter&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkSimpleScalarTree.cxx b/Filtering/vtkSimpleScalarTree.cxx new file mode 100644 index 0000000..efa0bb6 --- /dev/null +++ b/Filtering/vtkSimpleScalarTree.cxx @@ -0,0 +1,352 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleScalarTree.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSimpleScalarTree.h" + +#include "vtkCell.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkIdList.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkSimpleScalarTree, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkSimpleScalarTree); + +class vtkScalarNode {}; + +template +class vtkScalarRange : public vtkScalarNode +{ +public: + TScalar min; + TScalar max; +}; + +// Instantiate scalar tree with maximum level of 20 and branching +// factor of 5. +vtkSimpleScalarTree::vtkSimpleScalarTree() +{ + this->DataSet = NULL; + this->Level = 0; + this->MaxLevel = 20; + this->BranchingFactor = 3; + this->Tree = NULL; + this->TreeSize = 0; +} + +vtkSimpleScalarTree::~vtkSimpleScalarTree() +{ + if ( this->Tree ) + { + delete [] this->Tree; + } +} + +// Initialize locator. Frees memory and resets object as appropriate. +void vtkSimpleScalarTree::Initialize() +{ + if ( this->Tree ) + { + delete [] this->Tree; + } + this->Tree = NULL; +} + +// Construct the scalar tree from the dataset provided. Checks build times +// and modified time from input and reconstructs the tree if necessaery. +void vtkSimpleScalarTree::BuildTree() +{ + vtkIdType numCells, cellId, i, j, numScalars; + int level, offset, parentOffset, prod; + vtkIdType numNodes, node, numLeafs, leaf, numParentLeafs; + vtkCell *cell; + vtkIdList *cellPts; + vtkScalarRange *tree, *parent; + double *s; + vtkDoubleArray *cellScalars; + + // Check input...see whether we have to rebuild + // + if ( !this->DataSet || (numCells = this->DataSet->GetNumberOfCells()) < 1 ) + { + vtkErrorMacro( << "No data to build tree with"); + return; + } + + if ( this->Tree != NULL && this->BuildTime > this->MTime + && this->BuildTime > this->DataSet->GetMTime() ) + { + return; + } + + vtkDebugMacro( << "Building scalar tree..." ); + + this->Scalars = this->DataSet->GetPointData()->GetScalars(); + if ( ! this->Scalars ) + { + vtkErrorMacro( << "No scalar data to build trees with"); + return; + } + + this->Initialize(); + cellScalars = vtkDoubleArray::New(); + cellScalars->Allocate(100); + + // Compute the number of levels in the tree + // + numLeafs = (int) ceil((double)numCells/this->BranchingFactor); + for (prod=1, numNodes=1, this->Level=0; + prod < numLeafs && this->Level <= this->MaxLevel; this->Level++ ) + { + prod *= this->BranchingFactor; + numNodes += prod; + } + + this->LeafOffset = offset = numNodes - prod; + vtkScalarRange *TTree; + this->TreeSize = numNodes - (prod - numLeafs); + this->Tree = TTree = new vtkScalarRange[this->TreeSize]; + for ( i=0; i < this->TreeSize; i++ ) + { + TTree[i].min = VTK_DOUBLE_MAX; + TTree[i].max = -VTK_DOUBLE_MAX; + } + + // Loop over all cells getting range of scalar data and place into leafs + // + for ( cellId=0, node=0; node < numLeafs; node++ ) + { + tree = TTree + offset + node; + for ( i=0; i < this->BranchingFactor && cellId < numCells; i++, cellId++ ) + { + cell = this->DataSet->GetCell(cellId); + cellPts = cell->GetPointIds(); + numScalars = cellPts->GetNumberOfIds(); + cellScalars->SetNumberOfTuples(numScalars); + this->Scalars->GetTuples(cellPts, cellScalars); + s = cellScalars->GetPointer(0); + + for ( j=0; j < numScalars; j++ ) + { + if ( s[j] < tree->min ) + { + tree->min = s[j]; + } + if ( s[j] > tree->max ) + { + tree->max = s[j]; + } + } + } + } + + // Now build top levels of tree in bottom-up fashion + // + for ( level=this->Level; level > 0; level-- ) + { + parentOffset = offset - prod/this->BranchingFactor; + prod /= this->BranchingFactor; + numParentLeafs = (int) ceil((double)numLeafs/this->BranchingFactor); + + for ( leaf=0, node=0; node < numParentLeafs; node++ ) + { + parent = TTree + parentOffset + node; + for ( i=0; i < this->BranchingFactor && leaf < numLeafs; i++, leaf++ ) + { + tree = TTree + offset + leaf; + if ( tree->min < parent->min ) + { + parent->min = tree->min; + } + if ( tree->max > parent->max ) + { + parent->max = tree->max; + } + } + } + + numLeafs = numParentLeafs; + offset = parentOffset; + } + + this->BuildTime.Modified(); + cellScalars->Delete(); +} + +// Begin to traverse the cells based on a scalar value. Returned cells +// will have scalar values that span the scalar value specified. +void vtkSimpleScalarTree::InitTraversal(double scalarValue) +{ + this->BuildTree(); + vtkScalarRange *TTree = + static_cast< vtkScalarRange * > (this->Tree); + + this->ScalarValue = scalarValue; + this->TreeIndex = this->TreeSize; + + // Check root of tree for overlap with scalar value + // + if ( TTree[0].min > scalarValue || TTree[0].max < scalarValue ) + { + return; + } + + else //find leaf that does overlap with scalar value + { + this->FindStartLeaf(0,0); //recursive function call + } +} + +int vtkSimpleScalarTree::FindStartLeaf(vtkIdType index, int level) +{ + if ( level < this->Level ) + { + int i; + vtkIdType childIndex=this->BranchingFactor*index+1; + + level++; + for ( i=0; i < this->BranchingFactor; i++ ) + { + index = childIndex + i; + if ( index >= this->TreeSize ) + { + this->TreeIndex = this->TreeSize; + return 0; + } + else if ( this->FindStartLeaf(childIndex+i, level) ) + { + return 1; + } + } + + return 0; + } + + else //recursion terminated + { + vtkScalarRange *tree = static_cast< + vtkScalarRange*>(this->Tree) + index; + + if ( tree->min > this->ScalarValue || tree->max < this->ScalarValue ) + { + return 0; + } + else + { + this->ChildNumber = 0; + this->TreeIndex = index; + this->CellId = (index - this->LeafOffset) * this->BranchingFactor; + return 1; + } + } +} + +int vtkSimpleScalarTree::FindNextLeaf(vtkIdType childIndex, int childLevel) +{ + vtkIdType myIndex=(childIndex-1)/this->BranchingFactor; + int myLevel=childLevel-1; + vtkIdType firstChildIndex, childNum, index; + + //Find which child invoked this method + firstChildIndex = myIndex*this->BranchingFactor + 1; + childNum = childIndex - firstChildIndex; + + for ( childNum++; childNum < this->BranchingFactor; childNum++ ) + { + index = firstChildIndex + childNum; + if ( index >= this->TreeSize ) + { + this->TreeIndex = this->TreeSize; + return 0; + } + else if ( this->FindStartLeaf(index, childLevel) ) + { + return 1; + } + } + + //If here, didn't find anything yet + if ( myLevel <= 0 ) //at root, can't go any higher in tree + { + this->TreeIndex = this->TreeSize; + return 0; + } + else + { + return this->FindNextLeaf(myIndex,myLevel); + } +} + + +// Return the next cell that may contain scalar value specified to +// initialize traversal. The value NULL is returned if the list is +// exhausted. Make sure that InitTraversal() has been invoked first or +// you'll get erratic behavior. +vtkCell *vtkSimpleScalarTree::GetNextCell(vtkIdType& cellId, + vtkIdList* &cellPts, + vtkDataArray *cellScalars) +{ + double s, min=VTK_DOUBLE_MAX, max=(-VTK_DOUBLE_MAX); + vtkIdType i, numScalars; + vtkCell *cell; + vtkIdType numCells = this->DataSet->GetNumberOfCells(); + + while ( this->TreeIndex < this->TreeSize ) + { + for ( ; this->ChildNumberBranchingFactor && this->CellIdChildNumber++, this->CellId++ ) + { + cell = this->DataSet->GetCell(this->CellId); + cellPts = cell->GetPointIds(); + numScalars = cellPts->GetNumberOfIds(); + cellScalars->SetNumberOfTuples(numScalars); + this->Scalars->GetTuples(cellPts, cellScalars); + for (i=0; i < numScalars; i++) + { + s = cellScalars->GetTuple1(i); + if ( s < min ) + { + min = s; + } + if ( s > max ) + { + max = s; + } + } + if ( this->ScalarValue >= min && this->ScalarValue <= max ) + { + cellId = this->CellId; + this->ChildNumber++; //prepare for next time + this->CellId++; + return cell; + } + } //for each cell in this leaf + + // If here, must have not found anything in this leaf + this->FindNextLeaf(this->TreeIndex, this->Level); + } //while not all leafs visited + + return NULL; +} + +void vtkSimpleScalarTree::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Level: " << this->Level << "\n" ; + os << indent << "Max Level: " << this->MaxLevel << "\n" ; + os << indent << "Branching Factor: " << this->BranchingFactor << "\n" ; +} + diff --git a/Filtering/vtkSimpleScalarTree.h b/Filtering/vtkSimpleScalarTree.h new file mode 100644 index 0000000..6679c74 --- /dev/null +++ b/Filtering/vtkSimpleScalarTree.h @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleScalarTree.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSimpleScalarTree - organize data according to scalar values (used to accelerate contouring operations) +// .SECTION Description +// vtkSimpleScalarTree creates a pointerless binary tree that helps search for +// cells that lie within a particular scalar range. This object is used to +// accelerate some contouring (and other scalar-based techniques). +// +// The tree consists of an array of (min,max) scalar range pairs per node in +// the tree. The (min,max) range is determined from looking at the range of +// the children of the tree node. If the node is a leaf, then the range is +// determined by scanning the range of scalar data in n cells in the +// dataset. The n cells are determined by arbitrary selecting cell ids from +// id(i) to id(i+n), and where n is specified using the BranchingFactor +// ivar. Note that leaf node i=0 contains the scalar range computed from +// cell ids (0,n-1); leaf node i=1 contains the range from cell ids (n,2n-1); +// and so on. The implication is that there are no direct lists of cell ids +// per leaf node, instead the cell ids are implicitly known. + +#ifndef __vtkSimpleScalarTree_h +#define __vtkSimpleScalarTree_h + +#include "vtkScalarTree.h" + +//BTX +class vtkScalarNode; +//ETX + +class VTK_FILTERING_EXPORT vtkSimpleScalarTree : public vtkScalarTree +{ +public: + // Description: + // Instantiate scalar tree with maximum level of 20 and branching + // factor of 5. + static vtkSimpleScalarTree *New(); + + // Description: + // Standard type related macros and PrintSelf() method. + vtkTypeRevisionMacro(vtkSimpleScalarTree,vtkScalarTree); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the branching factor for the tree. This is the number of + // children per tree node. Smaller values (minimum is 2) mean deeper + // trees and more memory overhead. Larger values mean shallower + // trees, less memory usage, but worse performance. + vtkSetClampMacro(BranchingFactor,int,2,VTK_LARGE_INTEGER); + vtkGetMacro(BranchingFactor,int); + + // Description: + // Get the level of the scalar tree. This value may change each time the + // scalar tree is built and the branching factor changes. + vtkGetMacro(Level,int); + + // Description: + // Set the maximum allowable level for the tree. + vtkSetClampMacro(MaxLevel,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(MaxLevel,int); + + // Description: + // Construct the scalar tree from the dataset provided. Checks build times + // and modified time from input and reconstructs the tree if necessary. + virtual void BuildTree(); + + // Description: + // Initialize locator. Frees memory and resets object as appropriate. + virtual void Initialize(); + + // Description: + // Begin to traverse the cells based on a scalar value. Returned cells + // will have scalar values that span the scalar value specified. + virtual void InitTraversal(double scalarValue); + + // Description: + // Return the next cell that may contain scalar value specified to + // initialize traversal. The value NULL is returned if the list is + // exhausted. Make sure that InitTraversal() has been invoked first or + // you'll get erratic behavior. + virtual vtkCell *GetNextCell(vtkIdType &cellId, vtkIdList* &ptIds, + vtkDataArray *cellScalars); + +protected: + vtkSimpleScalarTree(); + ~vtkSimpleScalarTree(); + + vtkDataArray *Scalars; + int MaxLevel; + int Level; + int BranchingFactor; //number of children per node + vtkScalarNode *Tree; //pointerless scalar range tree + int TreeSize; //allocated size of tree + +private: + vtkIdType TreeIndex; //traversal location within tree + vtkIdType LeafOffset; //offset to leaf nodes of tree + int ChildNumber; //current child in traversal + vtkIdType CellId; //current cell id being examined + int FindStartLeaf(vtkIdType index, int level); + int FindNextLeaf(vtkIdType index,int level); + +private: + vtkSimpleScalarTree(const vtkSimpleScalarTree&); // Not implemented. + void operator=(const vtkSimpleScalarTree&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkSmoothErrorMetric.cxx b/Filtering/vtkSmoothErrorMetric.cxx new file mode 100644 index 0000000..7904793 --- /dev/null +++ b/Filtering/vtkSmoothErrorMetric.cxx @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSmoothErrorMetric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSmoothErrorMetric.h" + +#include "vtkObjectFactory.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericDataSet.h" +#include "vtkMath.h" +#include + +vtkCxxRevisionMacro(vtkSmoothErrorMetric,"$Revision: 1.1 $"); +vtkStandardNewMacro(vtkSmoothErrorMetric); + +//----------------------------------------------------------------------------- +vtkSmoothErrorMetric::vtkSmoothErrorMetric() +{ + this->AngleTolerance=90.1; // in degrees + this->CosTolerance=cos(this->AngleTolerance*vtkMath::DoubleDegreesToRadians()); +} + +//----------------------------------------------------------------------------- +vtkSmoothErrorMetric::~vtkSmoothErrorMetric() +{ +} + +//----------------------------------------------------------------------------- +double vtkSmoothErrorMetric::GetAngleTolerance() +{ + return this->AngleTolerance; +} + +//----------------------------------------------------------------------------- +void vtkSmoothErrorMetric::SetAngleTolerance(double value) +{ +// assert("pre: positive_value" && value>90 && value<180); + if(this->AngleTolerance!=value) + { + // Clamp the value + if(value<=90) + { + vtkWarningMacro(<< "value " << value << " out of range ]90,180[, clamped to 90.1" ); + this->AngleTolerance=90.1; + } + else + { + if(value>=180) + { + vtkWarningMacro(<< "value " << value << " out of range ]90,180[, clamped to 179.9" ); + this->AngleTolerance=179.9; + } + else + { + this->AngleTolerance=value; + } + } + this->CosTolerance=cos(this->AngleTolerance*vtkMath::DoubleDegreesToRadians()); + this->Modified(); + } +} + +//----------------------------------------------------------------------------- +int vtkSmoothErrorMetric::RequiresEdgeSubdivision(double *leftPoint, + double *midPoint, + double *rightPoint, + double vtkNotUsed(alpha) + ) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); +// assert("pre: clamped_alpha" && alpha>0 && alpha<1); // or else true + if( this->GenericCell->IsGeometryLinear() ) + { + //don't need to do anything: + return 0; + } + + double a[3]; + double b[3]; + + a[0]=leftPoint[0]-midPoint[0]; + a[1]=leftPoint[1]-midPoint[1]; + a[2]=leftPoint[2]-midPoint[2]; + b[0]=rightPoint[0]-midPoint[0]; + b[1]=rightPoint[1]-midPoint[1]; + b[2]=rightPoint[2]-midPoint[2]; + + + double dota=vtkMath::Dot(a,a); + double dotb=vtkMath::Dot(b,b); + double cosa; + + if(dota==0 || dotb==0) + { + cosa=-1; + } + else + { + cosa=vtkMath::Dot(a,b)/sqrt(dota*dotb); + } + + int result=(cosa>this->CosTolerance); + + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the error at the mid-point. The type of error depends on the state +// of the concrete error metric. For instance, it can return an absolute +// or relative error metric. +// See RequiresEdgeSubdivision() for a description of the arguments. +// \post positive_result: result>=0 +double vtkSmoothErrorMetric::GetError(double *leftPoint, + double *midPoint, + double *rightPoint, + double vtkNotUsed(alpha) + ) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); +// assert("pre: clamped_alpha" && alpha>0 && alpha<1); + if( this->GenericCell->IsGeometryLinear() ) + { + //don't need to do anything: + return 0; + } + + double a[3]; + double b[3]; + + a[0]=leftPoint[0]-midPoint[0]; + a[1]=leftPoint[1]-midPoint[1]; + a[2]=leftPoint[2]-midPoint[2]; + b[0]=rightPoint[0]-midPoint[0]; + b[1]=rightPoint[1]-midPoint[1]; + b[2]=rightPoint[2]-midPoint[2]; + + + double dota=vtkMath::Dot(a,a); + double dotb=vtkMath::Dot(b,b); + double cosa; + + if(dota==0 || dotb==0) + { + cosa=-1; + } + else + { + cosa=vtkMath::Dot(a,b)/sqrt(dota*dotb); + } + + if(cosa>1) + { + cosa=1; + } + else if(cosa<-1) + { + cosa=-1; + } + double result=180-acos(cosa)*vtkMath::DoubleRadiansToDegrees(); + assert("post: positive_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +void vtkSmoothErrorMetric::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "AngleTolerance: " << this->AngleTolerance << endl; + os << indent << "CosTolerance: " << this->CosTolerance << endl; +} diff --git a/Filtering/vtkSmoothErrorMetric.h b/Filtering/vtkSmoothErrorMetric.h new file mode 100644 index 0000000..c5c246a --- /dev/null +++ b/Filtering/vtkSmoothErrorMetric.h @@ -0,0 +1,107 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSmoothErrorMetric.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSmoothErrorMetric - Objects that compute +// geometry-based error during cell tessellation according to +// some max angle. +// +// .SECTION Description +// It is a concrete error metric, based on a geometric criterium: +// a max angle between the chord passing through the midpoint and one of the +// endpoints and the other chord passing through the midpoint and the other +// endpoint of the edge. It is related to the flatness of an edge. +// +// .SECTION See Also +// vtkGenericCellTessellator vtkGenericSubdivisionErrorMetric + +#ifndef __vtkSmoothErrorMetric_h +#define __vtkSmoothErrorMetric_h + +#include "vtkGenericSubdivisionErrorMetric.h" + +class vtkGenericDataSet; + +class VTK_FILTERING_EXPORT vtkSmoothErrorMetric : public vtkGenericSubdivisionErrorMetric +{ +public: + // Description: + // Construct the error metric with a default flatness threshold of 90.1 + // degrees. + static vtkSmoothErrorMetric *New(); + + // Description: + // Standard VTK type and error macros. + vtkTypeRevisionMacro(vtkSmoothErrorMetric,vtkGenericSubdivisionErrorMetric); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the flatness threshold. + // \post positive_result: result>90 && result<180 + double GetAngleTolerance(); + + // Description: + // Set the flatness threshold with an angle in degrees. Internally + // compute the cosine. value is supposed to be in ]90,180[, if not + // it is clamped in [90.1,179.9]. + // For instance 178 will give better result than 150. + void SetAngleTolerance(double value); + + // Description: + // Does the edge need to be subdivided according to the cosine between + // the two chords passing through the mid-point and the endpoints? + // The edge is defined by its `leftPoint' and its `rightPoint'. + // `leftPoint', `midPoint' and `rightPoint' have to be initialized before + // calling RequiresEdgeSubdivision(). + // Their format is global coordinates, parametric coordinates and + // point centered attributes: xyx rst abc de... + // `alpha' is the normalized abscissa of the midpoint along the edge. + // (close to 0 means close to the left point, close to 1 means close to the + // right point) + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + int RequiresEdgeSubdivision(double *leftPoint, double *midPoint, + double *rightPoint, double alpha); + + // Description: + // Return the error at the mid-point. It will return an error relative to + // the bounding box size if GetRelative() is true, a square absolute error + // otherwise. + // See RequiresEdgeSubdivision() for a description of the arguments. + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + // \post positive_result: result>=0 + double GetError(double *leftPoint, double *midPoint, double *rightPoint, + double alpha); + +protected: + vtkSmoothErrorMetric(); + virtual ~vtkSmoothErrorMetric(); + + double AngleTolerance; + double CosTolerance; + +private: + vtkSmoothErrorMetric(const vtkSmoothErrorMetric&); // Not implemented. + void operator=(const vtkSmoothErrorMetric&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkSource.cxx b/Filtering/vtkSource.cxx new file mode 100644 index 0000000..33aaac3 --- /dev/null +++ b/Filtering/vtkSource.cxx @@ -0,0 +1,714 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSource.h" + +#include "vtkCommand.h" +#include "vtkDataObject.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +#include "vtkImageData.h" + +vtkCxxRevisionMacro(vtkSource, "$Revision: 1.16 $"); + +#ifndef NULL +#define NULL 0 +#endif + +class vtkSourceToDataSetFriendship +{ +public: + static void GenerateGhostLevelArray(vtkDataSet* ds) + { + ds->GenerateGhostLevelArray(); + } +}; + +//---------------------------------------------------------------------------- +vtkSource::vtkSource() +{ + this->NumberOfOutputs = 0; + this->Outputs = NULL; + this->Updating = 0; +} + +//---------------------------------------------------------------------------- +vtkSource::~vtkSource() +{ + this->UnRegisterAllOutputs(); + if(this->Outputs) + { + delete [] this->Outputs; + this->Outputs = NULL; + this->NumberOfOutputs = 0; + } +} + +int vtkSource::GetOutputIndex(vtkDataObject *out) +{ + int i; + + for (i = 0; i < this->NumberOfOutputs; i++) + { + if (this->Outputs[i] == out) + { + return i; + } + } + return -1; +} + + +//---------------------------------------------------------------------------- +vtkDataObject* vtkSource::GetOutput(int i) +{ + if(i >= 0 && i < this->NumberOfOutputs) + { + return this->Outputs[i]; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkSource::UnRegisterAllOutputs() +{ + for(int i=0; i < this->NumberOfOutputs; ++i) + { + this->SetNthOutput(i, 0); + } +} + +//---------------------------------------------------------------------------- +int vtkSource::GetReleaseDataFlag() +{ + if (this->GetOutput(0)) + { + return this->GetOutput(0)->GetReleaseDataFlag(); + } + vtkWarningMacro(<<"Output doesn't exist!"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkSource::SetReleaseDataFlag(int i) +{ + int idx; + + for (idx = 0; idx < this->NumberOfOutputs; idx++) + { + if (this->Outputs[idx]) + { + this->Outputs[idx]->SetReleaseDataFlag(i); + } + } +} + +//---------------------------------------------------------------------------- +void vtkSource::UpdateWholeExtent() +{ + this->UpdateInformation(); + + if (this->GetOutput(0)) + { + this->GetOutput(0)->SetUpdateExtentToWholeExtent(); + this->GetOutput(0)->Update(); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::Update() +{ + if(vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + ddp->Update(0); + } + else + { + vtkErrorMacro("Executive is not a vtkDemandDrivenPipeline."); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::UpdateInformation() +{ + if(vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + ddp->UpdateInformation(); + } + else + { + vtkErrorMacro("Executive is not a vtkDemandDrivenPipeline."); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::PropagateUpdateExtent(vtkDataObject* output) +{ + if(vtkStreamingDemandDrivenPipeline* sddp = + vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + if(output) + { + for(int i=0; i < this->NumberOfOutputs; ++i) + { + if(this->Outputs[i] == output) + { + sddp->PropagateUpdateExtent(i); + } + } + } + else + { + sddp->PropagateUpdateExtent(-1); + } + } +} + +//---------------------------------------------------------------------------- +// By default we require all the input to produce the output. This is +// overridden in the subclasses since we can often produce the output with +// just a portion of the input data. +void vtkSource::ComputeInputUpdateExtents( vtkDataObject *vtkNotUsed(output) ) +{ + for (int idx = 0; idx < this->NumberOfInputs; ++idx) + { + if (this->Inputs[idx] != NULL) + { + this->Inputs[idx]->RequestExactExtentOn(); + this->Inputs[idx]->SetUpdateExtentToWholeExtent(); + } + } +} + +//---------------------------------------------------------------------------- + +void vtkSource::TriggerAsynchronousUpdate() +{ + // check flag to avoid executing forever if there is a loop + if (this->Updating) + { + return; + } + + // Propagate the trigger to all the inputs + this->Updating = 1; + for (int idx = 0; idx < this->NumberOfInputs; ++idx) + { + if (this->Inputs[idx] != NULL) + { + this->Inputs[idx]->TriggerAsynchronousUpdate(); + } + } + this->Updating = 0; +} + +//---------------------------------------------------------------------------- +void vtkSource::UpdateData(vtkDataObject* output) +{ + if(vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive())) + { + if(output) + { + for(int i=0; i < this->NumberOfOutputs; ++i) + { + if(this->Outputs[i] == output) + { + ddp->UpdateData(i); + } + } + } + else + { + ddp->UpdateData(-1); + } + } + else + { + vtkErrorMacro("Executive is not a vtkDemandDrivenPipeline."); + } +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkSource::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (this->UpdateExtentIsEmpty(output) && output) + { + output->Initialize(); + return; + } + + this->Execute(); +} + + +//---------------------------------------------------------------------------- +void vtkSource::SetNumberOfOutputs(int newNumberOfOutputs) +{ + if(newNumberOfOutputs < 0) + { + vtkErrorMacro("Cannot set number of outputs to " << newNumberOfOutputs); + newNumberOfOutputs = 0; + } + + if(newNumberOfOutputs != this->NumberOfOutputs) + { + // Copy outputs that will still exist. + vtkDataObject** newOutputs = new vtkDataObject*[newNumberOfOutputs]; + int i; + for(i=0; i < newNumberOfOutputs; ++i) + { + newOutputs[i] = (i < this->NumberOfOutputs)? this->Outputs[i] : 0; + } + + // Delete outputs if number is decreasing. + for(;i < this->NumberOfOutputs; ++i) + { + this->SetNthOutput(i, 0); + } + + // Free old outputs array. + if(this->Outputs) + { + delete [] this->Outputs; + this->Outputs = 0; + this->NumberOfOutputs = 0; + } + + // Setup new outputs array. + this->Outputs = newOutputs; + this->NumberOfOutputs = newNumberOfOutputs; + this->SetNumberOfOutputPorts(this->NumberOfOutputs); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::AddOutput(vtkDataObject* output) +{ + if(output) + { + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + if(!this->Outputs[i]) + { + this->SetNthOutput(i, output); + return; + } + } + this->SetNthOutput(this->GetNumberOfOutputPorts(), output); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::RemoveOutput(vtkDataObject* output) +{ + if(output) + { + for(int i=0; i < this->NumberOfOutputs; ++i) + { + if(this->Outputs[i] == output) + { + this->SetNthOutput(i, 0); + return; + } + } + vtkErrorMacro("Could not remove " << output->GetClassName() + << "(" << output << ") because it is not an output."); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::SetNthOutput(int index, vtkDataObject* newOutput) +{ + if(index < 0) + { + vtkErrorMacro("SetNthOutput: " << index << ", cannot set output. "); + return; + } + + if(index >= this->NumberOfOutputs) + { + this->SetNumberOfOutputs(index+1); + } + + vtkDataObject* oldOutput = this->Outputs[index]; + if(newOutput == oldOutput) + { + return; + } + + // Ask the executive to setup the new output. + this->GetExecutive()->SetOutputData(index, newOutput); + + this->InvokeEvent(vtkCommand::SetOutputEvent,NULL); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkSource::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use ExecuteData(vtkDataObject *) instead"); +} + +//---------------------------------------------------------------------------- +vtkDataObject** vtkSource::GetOutputs() +{ + return this->Outputs; +} + + +//---------------------------------------------------------------------------- + +// Default implementation - copy information from first input to all outputs +void vtkSource::ExecuteInformation() +{ + vtkDataObject *input, *output; + + if (this->Inputs && this->Inputs[0]) + { + input = this->Inputs[0]; + + for (int idx = 0; idx < this->NumberOfOutputs; ++idx) + { + output = this->GetOutput(idx); + if (output) + { + output->CopyInformation(input); + } + } + } + else + { + for (int idx = 0; idx < this->NumberOfOutputs; ++idx) + { + output = this->GetOutput(idx); + if (output) + { + // Since most unstructured filters in VTK generate all their data once, + // make it the default. + // protected: if ( output->GetExtentType() == VTK_PIECES_EXTENT ) + if (output->IsA("vtkPolyData") || output->IsA("vtkUnstructuredGrid")) + { + output->SetMaximumNumberOfPieces(1); + } + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->NumberOfOutputs) + { + int idx; + for (idx = 0; idx < this->NumberOfOutputs; ++idx) + { + os << indent << "Output " << idx << ": (" << this->Outputs[idx] << ")\n"; + } + } + else + { + os << indent <<"No Outputs\n"; + } +} + +//---------------------------------------------------------------------------- +int vtkSource::FillOutputPortInformation(int port, vtkInformation* info) +{ + return this->Superclass::FillOutputPortInformation(port, info); +} + +//---------------------------------------------------------------------------- +void vtkSource::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + for(int i=0; i < this->NumberOfOutputs; ++i) + { + vtkGarbageCollectorReport(collector, this->Outputs[i], "Outputs"); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::SetExecutive(vtkExecutive* executive) +{ + // Set the executive normally. + this->Superclass::SetExecutive(executive); + // Copy our set of outputs to the information objects in the + // executive. + for(int i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + this->GetExecutive()->SetOutputData(i, this->Outputs[i]); + } +} + +//---------------------------------------------------------------------------- +void vtkSource::SetNumberOfOutputPorts(int n) +{ + if(n != this->GetNumberOfOutputPorts()) + { + this->Superclass::SetNumberOfOutputPorts(n); + this->SetNumberOfOutputs(n); + } +} + +//---------------------------------------------------------------------------- +int vtkSource::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + // The compatibility layer always keeps output data objects around + // because they are needed for connections. + return 1; + } + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + // Make sure the outputs are synchronized between the old and new + // style pipelines. + int i; + for(i=0; i < this->NumberOfOutputs; ++i) + { + vtkInformation* info = this->GetExecutive()->GetOutputInformation(i); + this->SetNthOutput(i, info->Get(vtkDataObject::DATA_OBJECT())); + } + + vtkDebugMacro("ProcessRequest(REQUEST_INFORMATION) " + "calling ExecuteInformation."); + + // Old-style filters will get origin and spacing from the input + // data objects themselves. We handle this here by copying the + // pipeline information version of these values into the data + // object's version. + for(i=0; i < this->NumberOfInputs; ++i) + { + vtkInformation* info = inputVector[0]->GetInformationObject(i); + if(vtkImageData* id = vtkImageData::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT()))) + { + if(info->Has(vtkDataObject::ORIGIN())) + { + id->SetOrigin(info->Get(vtkDataObject::ORIGIN())); + } + if(info->Has(vtkDataObject::SPACING())) + { + id->SetSpacing(info->Get(vtkDataObject::SPACING())); + } + } + } + + // Ask the subclass to fill in the information for the outputs. + this->InvokeEvent(vtkCommand::ExecuteInformationEvent, NULL); + this->ExecuteInformation(); + + // The number of outputs may have been changed by execute information. + outputVector->SetNumberOfInformationObjects(this->NumberOfOutputs); + + // Old-style filters will set the origin and spacing on the output + // data objects themselves. We handle this here by copying the + // information back to the pipeline information. + for(i=0; i < this->NumberOfOutputs; ++i) + { + vtkInformation* info = outputVector->GetInformationObject(i); + if(vtkImageData* id = vtkImageData::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT()))) + { + info->Set(vtkDataObject::ORIGIN(), id->GetOrigin(), 3); + info->Set(vtkDataObject::SPACING(), id->GetSpacing(), 3); + } + } + + return 1; + } + else if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + int i; + for(i=0; i < this->NumberOfOutputs; ++i) + { + vtkInformation* info = this->GetExecutive()->GetOutputInformation(i); + this->SetNthOutput(i, info->Get(vtkDataObject::DATA_OBJECT())); + } + + // If the user defines a ComputeInputUpdateExtent method, we want + // RequestExactUpdateExtent to be off by default (User does + // nothing else). Otherwise, the ComputeInputUpdateExtent in this + // superclass sets RequestExactExtent to on. The reason for this + // initialization here is if this sources shares an input with + // another, we do not want the input's RequestExactExtent "state" + // to interfere with each other. + for(i=0; i < this->NumberOfInputs; ++i) + { + if(this->Inputs[i]) + { + this->Inputs[i]->RequestExactExtentOff(); + } + } + + // Check inputs. + if(this->NumberOfRequiredInputs > 0 && + this->GetNumberOfInputPorts() < 1) + { + vtkErrorMacro("This filter requires " << this->NumberOfRequiredInputs + << " input(s) but has no input ports. A call to " + << "SetNumberOfInputPorts and an implementation of " + << "FillInputPortInformation may need to be added to " + << "this class."); + return 0; + } + + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + vtkDataObject* fromOutput = 0; + if(outputPort >= 0) + { + fromOutput = this->Outputs[outputPort]; + } + + // Give the subclass a chance to request a larger extent on the + // inputs. This is necessary when, for example, a filter requires + // more data at the "internal" boundaries to produce the boundary + // values - such as an image filter that derives a new pixel value + // by applying some operation to a neighborhood of surrounding + // original values. + vtkDebugMacro("ProcessRequest(REQUEST_UPDATE_EXTENT) " + "calling ComputeInputUpdateExtents using output port " + << outputPort); + this->ComputeInputUpdateExtents(fromOutput); + + return 1; + } + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_NOT_GENERATED())) + { + // Mark all outputs as not generated so that the executive does + // not try to handle initialization/finalization of the outputs. + // We will do it here. + int i; + for(i=0; i < outputVector->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outputVector->GetInformationObject(i); + outInfo->Set(vtkDemandDrivenPipeline::DATA_NOT_GENERATED(), 1); + } + } + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + // Make sure the outputs are synchronized between the old and new + // style pipelines. + int i; + for(i=0; i < this->NumberOfOutputs; ++i) + { + vtkInformation* info = this->GetExecutive()->GetOutputInformation(i); + this->SetNthOutput(i, info->Get(vtkDataObject::DATA_OBJECT())); + } + int outputPort = request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // Check inputs. + if(this->NumberOfRequiredInputs > 0 && + this->GetNumberOfInputPorts() < 1) + { + vtkErrorMacro("This filter requires " << this->NumberOfRequiredInputs + << " input(s) but has no input ports. A call to " + << "SetNumberOfInputPorts and an implementation of " + << "FillInputPortInformation may need to be added to " + << "this class."); + return 0; + } + + vtkDebugMacro("ProcessRequest(REQUEST_DATA) " + "calling ExecuteData for output port " << outputPort); + + // Prepare to execute the filter. + for(i=0; i < this->NumberOfOutputs; ++i) + { + if(this->Outputs[i]) + { + this->Outputs[i]->PrepareForNewData(); + } + } + + // Pass the vtkDataObject's field data from the first input to all + // outputs. + if(this->NumberOfInputs > 0 && this->Inputs[0] && + this->Inputs[0]->GetFieldData()) + { + for(i=0; i < this->NumberOfOutputs; ++i) + { + if(this->Outputs[i] && this->Outputs[i]->GetFieldData()) + { + this->Outputs[i]->GetFieldData()->PassData( + this->Inputs[0]->GetFieldData()); + } + } + } + + // Execute the filter. + vtkDataObject* output = (outputPort >= 0)? this->Outputs[outputPort] : 0; + this->ExecuteData(output); + + // Mark the data as up-to-date. + this->MarkGeneratedOutputs(output); + + // Cleanup the outputs. + for(i=0; i < this->NumberOfOutputs; ++i) + { + vtkInformation* info = outputVector->GetInformationObject(i); + + // Old-style filters will set the origin and spacing on the output + // data objects themselves. We handle this here by copying the + // information back to the pipeline information. + if(vtkImageData* id = vtkImageData::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT()))) + { + info->Set(vtkDataObject::ORIGIN(), id->GetOrigin(), 3); + info->Set(vtkDataObject::SPACING(), id->GetSpacing(), 3); + } + + // Compute the ghost level array for the output if necessary. + if(vtkDataSet* ds = vtkDataSet::SafeDownCast(this->Outputs[i])) + { + vtkSourceToDataSetFriendship::GenerateGhostLevelArray(ds); + } + } + return 1; + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +void vtkSource::MarkGeneratedOutputs(vtkDataObject*) +{ + // Mark the data as up-to-date. Mark all outputs by default. + for(int i=0; i < this->NumberOfOutputs; ++i) + { + if(this->Outputs[i]) + { + this->Outputs[i]->DataHasBeenGenerated(); + } + } +} diff --git a/Filtering/vtkSource.h b/Filtering/vtkSource.h new file mode 100644 index 0000000..3012378 --- /dev/null +++ b/Filtering/vtkSource.h @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSource - abstract class specifies interface for visualization network source +// .SECTION Description +// vtkSource is an abstract object that specifies behavior and interface +// of source objects. Source objects are objects that begin visualization +// pipeline. Sources include readers (read data from file or communications +// port) and procedural sources (generate data programmatically). vtkSource +// objects are also objects that generate output data. In this sense +// vtkSource is used as a superclass to vtkFilter. +// +// Concrete subclasses of vtkSource must define Update() and Execute() +// methods. The public method Update() invokes network execution and will +// bring the network up-to-date. The protected Execute() method actually +// does the work of data creation/generation. The difference between the two +// methods is that Update() implements input consistency checks and modified +// time comparisons and then invokes the Execute() which is an implementation +// of a particular algorithm. +// +// An important feature of subclasses of vtkSource is that it is possible +// to control the memory-management model (i.e., retain output versus delete +// output data). If enabled the ReleaseDataFlag enables the deletion of the +// output data once the downstream process object finishes processing the +// data (please see text). + +// .SECTION See Also +// vtkProcessObject vtkDataSetReader vtkFilter vtkPolyDataSource +// vtkStructuredGridSource vtkStructuredPointsSource vtkUnstructuredGridSource + +#ifndef __vtkSource_h +#define __vtkSource_h + +#include "vtkProcessObject.h" + +class vtkDataObject; +class vtkDataObjectToSourceFriendship; + +class VTK_FILTERING_EXPORT vtkSource : public vtkProcessObject +{ +public: + vtkTypeRevisionMacro(vtkSource,vtkProcessObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Bring object up-to-date before execution. Update() checks modified + // time against last execution time, and re-executes object if necessary. + virtual void Update(); + + // Description: + // Like update, but make sure the update extent is the whole extent in + // the output. + virtual void UpdateWholeExtent(); + + // Description: + // Updates any global information about the data + // (like spacing for images) + virtual void UpdateInformation(); + + // Description: + virtual void PropagateUpdateExtent(vtkDataObject *output); + + // Description: + virtual void TriggerAsynchronousUpdate(); + + // Description: + virtual void UpdateData(vtkDataObject *output); + + // Description: + // What is the input update extent that is required to produce the + // desired output? By default, the whole input is always required but + // this is overridden in many subclasses. + virtual void ComputeInputUpdateExtents( vtkDataObject *output ); + + // Description: + // Turn on/off flag to control whether this object's data is released + // after being used by a source. + virtual void SetReleaseDataFlag(int); + virtual int GetReleaseDataFlag(); + vtkBooleanMacro(ReleaseDataFlag,int); + + // Description: + // Return an array with all the inputs of this process object. + // This is useful for tracing back in the pipeline to construct + // graphs etc. + vtkDataObject **GetOutputs(); + vtkGetMacro(NumberOfOutputs,int); + + // Description: + // Release/disconnect all outputs of this source. This is intended to be + // called prior to Delete() if the user is concerned about outputs holding + // on to the filter/source. + void UnRegisterAllOutputs(void); + + // Description: + // Return what index output the passed in output is, return -1 if it + // does not match any of the outputs + int GetOutputIndex(vtkDataObject *out); + + // Description: + // Set this algorithm's executive. This algorithm is removed from + // any executive to which it has previously been assigned and then + // assigned to the given executive. + virtual void SetExecutive(vtkExecutive* executive); + + // Description: + // Transform pipeline requests from executives into old-style + // pipeline calls. This works with the + // vtkStreamingDemandDrivenPipeline executive to maintain backward + // compatibility for filters written as subclasses of vtkSource. + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkSource(); + ~vtkSource(); + + // Description: + // This method is the one that should be used by subclasses, right now the + // default implementation is to call the backwards compatibility method + virtual void ExecuteData(vtkDataObject *output); + + // Description: + // This method is the old style execute method + virtual void Execute(); + + // By default, UpdateInformation calls this method to copy information + // unmodified from the input to the output. + virtual void ExecuteInformation(); + + // Called after ExecuteData to call DataHasBeenGenerated on the + // outputs. It can be overridden by subclasses to call + // DataHasBeenGenerated on only a subset of the outputs. The + // argument is the pointer to the output data object that was passed + // to ExecuteData. + virtual void MarkGeneratedOutputs(vtkDataObject*); + + // Called to allocate the input array. Copies old inputs. + void SetNumberOfOutputs(int num); + + // method used internally for getting an output. + vtkDataObject *GetOutput(int idx); + + // protected methods for setting inputs. + virtual void SetNthOutput(int num, vtkDataObject *output); + virtual void AddOutput(vtkDataObject *output); + virtual void RemoveOutput(vtkDataObject *output); + + vtkDataObject **Outputs; // An Array of the outputs to the filter + int NumberOfOutputs; + int Updating; + // Time when ExecuteInformation was last called. + vtkTimeStamp InformationTime; + + virtual void ReportReferences(vtkGarbageCollector*); + + // Output port information must match the current outputs. + int FillOutputPortInformation(int, vtkInformation*); + + // Reimplemented from vtkAlgorithm to maintain backward + // compatibility for vtkProcessObject. + virtual void SetNumberOfOutputPorts(int n); + + //BTX + friend class vtkDataObjectToSourceFriendship; + //ETX + +private: + vtkSource(const vtkSource&); // Not implemented. + void operator=(const vtkSource&); // Not implemented. +}; + +#endif + + + diff --git a/Filtering/vtkSphere.cxx b/Filtering/vtkSphere.cxx new file mode 100644 index 0000000..edf0e67 --- /dev/null +++ b/Filtering/vtkSphere.cxx @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphere.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSphere.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkSphere, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkSphere); + +// Construct sphere with center at (0,0,0) and radius=0.5. +vtkSphere::vtkSphere() +{ + this->Radius = 0.5; + + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; +} + +// Evaluate sphere equation ((x-x0)^2 + (y-y0)^2 + (z-z0)^2) - R^2. +double vtkSphere::EvaluateFunction(double x[3]) +{ + return ( ((x[0] - this->Center[0]) * (x[0] - this->Center[0]) + + (x[1] - this->Center[1]) * (x[1] - this->Center[1]) + + (x[2] - this->Center[2]) * (x[2] - this->Center[2])) - + this->Radius*this->Radius ); +} + +// Evaluate sphere gradient. +void vtkSphere::EvaluateGradient(double x[3], double n[3]) +{ + n[0] = 2.0 * (x[0] - this->Center[0]); + n[1] = 2.0 * (x[1] - this->Center[1]); + n[2] = 2.0 * (x[2] - this->Center[2]); +} + +void vtkSphere::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << ")\n"; +} diff --git a/Filtering/vtkSphere.h b/Filtering/vtkSphere.h new file mode 100644 index 0000000..e03b6dd --- /dev/null +++ b/Filtering/vtkSphere.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphere.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSphere - implicit function for a sphere +// .SECTION Description +// vtkSphere computes the implicit function and/or gradient for a sphere. +// vtkSphere is a concrete implementation of vtkImplicitFunction. + +#ifndef __vtkSphere_h +#define __vtkSphere_h + +#include "vtkImplicitFunction.h" + +class VTK_FILTERING_EXPORT vtkSphere : public vtkImplicitFunction +{ +public: + vtkTypeRevisionMacro(vtkSphere,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct sphere with center at (0,0,0) and radius=0.5. + static vtkSphere *New(); + + // Description + // Evaluate sphere equation ((x-x0)^2 + (y-y0)^2 + (z-z0)^2) - R^2. + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + + // Description + // Evaluate sphere gradient. + void EvaluateGradient(double x[3], double n[3]); + + // Description: + // Set / get the radius of the sphere. + vtkSetMacro(Radius,double); + vtkGetMacro(Radius,double); + + // Description: + // Set / get the center of the sphere. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + +protected: + vtkSphere(); + ~vtkSphere() {}; + + double Radius; + double Center[3]; + +private: + vtkSphere(const vtkSphere&); // Not implemented. + void operator=(const vtkSphere&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkSpline.cxx b/Filtering/vtkSpline.cxx new file mode 100644 index 0000000..5538188 --- /dev/null +++ b/Filtering/vtkSpline.cxx @@ -0,0 +1,237 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSpline.h" + +#include "vtkPiecewiseFunction.h" + +vtkCxxRevisionMacro(vtkSpline, "$Revision: 1.28 $"); + +//---------------------------------------------------------------------------- +// Construct a spline wth the folloing defaults: +// ClampValueOff +vtkSpline::vtkSpline () +{ + this->ComputeTime = 0; + this->ClampValue = 0; + this->PiecewiseFunction = vtkPiecewiseFunction::New(); + this->Intervals = NULL; + this->Coefficients = NULL; + this->LeftConstraint = 1; + this->LeftValue = 0.0; + this->RightConstraint = 1; + this->RightValue = 0.0; + this->Closed = 0; + + this->ParametricRange[0] = -1; + this->ParametricRange[1] = -1; +} + +//---------------------------------------------------------------------------- +vtkSpline::~vtkSpline () +{ + this->PiecewiseFunction->Delete(); + if (this->Coefficients) + { + delete [] this->Coefficients; + } + if (this->Intervals) + { + delete [] this->Intervals; + } +} + +//---------------------------------------------------------------------------- +void vtkSpline::SetParametricRange(double tMin, double tMax) +{ + if ( tMin != this->ParametricRange[0] || tMax != this->ParametricRange[1] ) + { + if ( tMin >= tMax ) + { + tMax = tMin + 1; + } + + this->ParametricRange[0] = tMin; + this->ParametricRange[1] = tMax; + + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkSpline::GetParametricRange(double tRange[2]) const +{ + if ( this->ParametricRange[0] != this->ParametricRange[1] ) + { + tRange[0] = this->ParametricRange[0]; + tRange[1] = this->ParametricRange[1]; + } + else + { + tRange[0] = this->PiecewiseFunction->GetRange()[0]; + tRange[1] = this->PiecewiseFunction->GetRange()[1]; + } +} + +//---------------------------------------------------------------------------- +double vtkSpline::ComputeLeftDerivative() +{ + double *dptr = this->PiecewiseFunction->GetDataPointer(); + int size = this->PiecewiseFunction->GetSize(); + if ( dptr == NULL || size < 2 ) + { + return 0.0; + } + else + { + return (dptr[2]-dptr[0]); + } +} + +//---------------------------------------------------------------------------- +double vtkSpline::ComputeRightDerivative() +{ + double *dptr = this->PiecewiseFunction->GetDataPointer(); + int size = this->PiecewiseFunction->GetSize(); + if ( dptr == NULL || size < 2 ) + { + return 0.0; + } + else + { + return (dptr[(size-1)*2]-dptr[(size-2)*2]); + } +} + +//---------------------------------------------------------------------------- +int vtkSpline::GetNumberOfPoints() +{ + return this->PiecewiseFunction->GetSize(); +} + + +//---------------------------------------------------------------------------- +// Add a point to the Piecewise Functions containing the data +void vtkSpline::AddPoint (double t, double x) +{ + if ( this->ParametricRange[0] != this->ParametricRange[1] ) + { + t = (t < this->ParametricRange[0] ? this->ParametricRange[0] : + (t > this->ParametricRange[1] ? this->ParametricRange[1] : t)); + } + this->PiecewiseFunction->AddPoint (t, x); +} + +//---------------------------------------------------------------------------- +// Remove a point from the Piecewise Functions. +void vtkSpline::RemovePoint (double t) +{ + if ( this->ParametricRange[0] != this->ParametricRange[1] ) + { + t = (t < this->ParametricRange[0] ? this->ParametricRange[0] : + (t > this->ParametricRange[1] ? this->ParametricRange[1] : t)); + } + this->PiecewiseFunction->RemovePoint (t); +} + +//---------------------------------------------------------------------------- +// Remove all points from the Piecewise Functions. +void vtkSpline::RemoveAllPoints () +{ + this->PiecewiseFunction->RemoveAllPoints (); +} + +//---------------------------------------------------------------------------- +void vtkSpline::DeepCopy(vtkSpline *s) +{ + vtkSpline *spline = vtkSpline::SafeDownCast(s); + + if ( spline != NULL ) + { + this->ClampValue = s->ClampValue; + this->LeftConstraint = s->LeftConstraint; + this->LeftValue = s->LeftValue; + this->RightConstraint = s->RightConstraint; + this->RightValue = s->RightValue; + this->Closed = s->Closed; + this->PiecewiseFunction->DeepCopy(s->PiecewiseFunction); + } +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If data is modified, +// then this object is modified as well. +unsigned long vtkSpline::GetMTime() +{ + unsigned long mTime=this->vtkObject::GetMTime(); + unsigned long DataMTime; + + if ( this->PiecewiseFunction != NULL ) + { + DataMTime = this->PiecewiseFunction->GetMTime(); + mTime = ( DataMTime > mTime ? DataMTime : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +int vtkSpline::FindIndex(int size, double t) +{ + int index=0; + if ( size > 2 ) //bisection method for speed + { + int rightIdx = size - 1; + int centerIdx = rightIdx - size/2; + for (int converged=0; !converged; ) + { + if ( this->Intervals[index] <= t && t <= this->Intervals[centerIdx] ) + { + rightIdx = centerIdx; + } + else //if ( this->Intervals[centerIdx] < t && t <= this->Intervals[rightIdx] ) + { + index = centerIdx; + } + if ( (index + 1) == rightIdx ) + { + converged = 1; + } + else + { + centerIdx = index + (rightIdx-index)/2; + } + }//while not converged + } + return index; +} + + +//---------------------------------------------------------------------------- +void vtkSpline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Clamp Value: " << (this->ClampValue ? "On\n" : "Off\n"); + os << indent << "Left Constraint: " << this->LeftConstraint << "\n"; + os << indent << "Right Constraint: " << this->RightConstraint << "\n"; + os << indent << "Left Value: " << this->LeftValue << "\n"; + os << indent << "Right Value: " << this->RightValue << "\n"; + os << indent << "Closed: " << (this->Closed ? "On\n" : "Off\n"); + + os << indent << "Piecewise Function:\n"; + this->PiecewiseFunction->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Closed: " << (this->Closed ? "On\n" : "Off\n"); +} diff --git a/Filtering/vtkSpline.h b/Filtering/vtkSpline.h new file mode 100644 index 0000000..9878560 --- /dev/null +++ b/Filtering/vtkSpline.h @@ -0,0 +1,179 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSpline - spline abstract class for interpolating splines +// .SECTION Description +// vtkSpline interpolates a set of data points (i.e., interpolation means +// that the spline passes through the points). vtkSpline is an abstract +// class: its subclasses vtkCardinalSpline and vtkKochenekSpline do the +// interpolation. Note that this spline maps the 1D parametric coordinate +// t into a single value x. Thus if you want to use the spline to +// interpolate points (i.e. x[3]), you have to create three splines for +// each of the x-y-z coordinates. Fortunately, the vtkParametricSpline +// class does this for you. +// +// Typically a spline is used by adding a sequence of parametric coordinate / +// data (t,x) values followed by use of an evaluation function (e.g., +// vtkCardinalSpline::Evaluate()). Since these splines are 1D, a point in +// this context is an independent / dependent variable pair. +// +// Splines can also be set up to be closed or open. Closed splines continue +// from the last point to the first point with continuous function and +// derivative values. (You don't need to duplicate the first point to close +// the spline, just set ClosedOn.) +// +// This implementation of splines does not use a normalized parametric +// coordinate. If the spline is open, then the parameter space is (tMin <= t +// <= tMax) where tMin and tMax are the minimum and maximum parametric values +// seen when performing AddPoint(). If the spline is closed, then the +// parameter space is (tMin <= t <= (tMax+1)) where tMin and tMax are the +// minimum and maximum parametric values seen when performing AddPoint(). +// Note, however, that this behavior can be changed by explicitly setting +// the ParametricRange(tMin,tMax). If set, the parameter space remains +// (tMin <= t <= tMax), except that additions of data with parametric +// values outside this range are clamped within this range. + +// .SECTION See Also +// vtkCardinalSpline vtkKochenekSpline vtkParametricSpline +// vtkParametricFunctionSource + + +#ifndef __vtkSpline_h +#define __vtkSpline_h + +#include "vtkObject.h" + +class vtkPiecewiseFunction; + +class VTK_FILTERING_EXPORT vtkSpline : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkSpline,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the parametric range. If not set, the range is determined + // implicitly by keeping track of the (min,max) parameter values for + // t. If set, the AddPoint() method will clamp the t value to lie + // within the specified range. + void SetParametricRange(double tMin, double tMax); + void SetParametricRange(double tRange[2]) + {this->SetParametricRange(tRange[0],tRange[1]);} + void GetParametricRange(double tRange[2]) const; + + // Description: + // Set/Get ClampValue. If On, results of the interpolation will be + // clamped to the min/max of the input data. + vtkSetMacro(ClampValue,int); + vtkGetMacro(ClampValue,int); + vtkBooleanMacro(ClampValue,int); + + // Description: + // Compute the coefficients for the spline. + virtual void Compute () = 0; + + // Description: + // Interpolate the value of the spline at parametric location of t. + virtual double Evaluate (double t) = 0; + + // Description: + // Return the number of points inserted thus far. + int GetNumberOfPoints(); + + // Description: + // Add a pair of points to be fit with the spline. + void AddPoint (double t, double x); + + // Description: + // Remove a point from the data to be fit with the spline. + void RemovePoint (double t); + + // Description: + // Remove all points from the data. + void RemoveAllPoints (); + + // Description: + // Control whether the spline is open or closed. A closed spline forms + // a continuous loop: the first and last points are the same, and + // derivatives are continuous. + vtkSetMacro(Closed,int); + vtkGetMacro(Closed,int); + vtkBooleanMacro(Closed,int); + + // Description: + // Set the type of constraint of the left(right) end points. Four + // constraints are available: + // + // 0: the first derivative at left(right) most point is determined + // from the line defined from the first(last) two points. + // + // 1: the first derivative at left(right) most point is set to + // Left(Right)Value. + // + // 2: the second derivative at left(right) most point is set to + // Left(Right)Value. + // + // 3: the second derivative at left(right)most points is Left(Right)Value + // times second derivative at first interior point. + vtkSetClampMacro(LeftConstraint,int,0,3); + vtkGetMacro(LeftConstraint,int); + vtkSetClampMacro(RightConstraint,int,0,3); + vtkGetMacro(RightConstraint,int); + + // Description: + // The values of the derivative on the left and right sides. The value + // is used only if the left(right) constraint is type 1-3. + vtkSetMacro(LeftValue,double); + vtkGetMacro(LeftValue,double); + vtkSetMacro(RightValue,double); + vtkGetMacro(RightValue,double); + + // Description: + // Return the MTime also considering the Piecewise function. + unsigned long GetMTime(); + + // Description: + // Deep copy of spline data. + virtual void DeepCopy(vtkSpline *s); + +protected: + vtkSpline(); + ~vtkSpline(); + + unsigned long ComputeTime; + int ClampValue; + double *Intervals; + double *Coefficients; + int LeftConstraint; + double LeftValue; + int RightConstraint; + double RightValue; + vtkPiecewiseFunction *PiecewiseFunction; + int Closed; + + // Explicitly specify the parametric range. + double ParametricRange[2]; + + // Helper methods + double ComputeLeftDerivative(); + double ComputeRightDerivative(); + int FindIndex(int size, double t); + +private: + vtkSpline(const vtkSpline&); // Not implemented. + void operator=(const vtkSpline&); // Not implemented. +}; + +#endif + diff --git a/Filtering/vtkStreamingDemandDrivenPipeline.cxx b/Filtering/vtkStreamingDemandDrivenPipeline.cxx new file mode 100644 index 0000000..00e4de5 --- /dev/null +++ b/Filtering/vtkStreamingDemandDrivenPipeline.cxx @@ -0,0 +1,1251 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamingDemandDrivenPipeline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStreamingDemandDrivenPipeline.h" + +#include "vtkAlgorithm.h" +#include "vtkAlgorithmOutput.h" +#include "vtkDataObject.h" +#include "vtkDataSet.h" +#include "vtkExtentTranslator.h" +#include "vtkInformation.h" +#include "vtkInformationDoubleVectorKey.h" +#include "vtkInformationIntegerKey.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationObjectBaseKey.h" +#include "vtkInformationRequestKey.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkSmartPointer.h" + +vtkCxxRevisionMacro(vtkStreamingDemandDrivenPipeline, "$Revision: 1.35.2.1 $"); +vtkStandardNewMacro(vtkStreamingDemandDrivenPipeline); + +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, CONTINUE_EXECUTING, Integer); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, EXACT_EXTENT, Integer); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, REQUEST_UPDATE_EXTENT, Request); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, MAXIMUM_NUMBER_OF_PIECES, Integer); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, UPDATE_EXTENT_INITIALIZED, Integer); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, UPDATE_PIECE_NUMBER, Integer); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, UPDATE_NUMBER_OF_PIECES, Integer); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, UPDATE_NUMBER_OF_GHOST_LEVELS, Integer); +vtkInformationKeyRestrictedMacro(vtkStreamingDemandDrivenPipeline, WHOLE_EXTENT, IntegerVector, 6); +vtkInformationKeyRestrictedMacro(vtkStreamingDemandDrivenPipeline, UPDATE_EXTENT, IntegerVector, 6); +vtkInformationKeyRestrictedMacro(vtkStreamingDemandDrivenPipeline, + EXTENT_TRANSLATOR, ObjectBase, + "vtkExtentTranslator"); +vtkInformationKeyRestrictedMacro(vtkStreamingDemandDrivenPipeline, WHOLE_BOUNDING_BOX, DoubleVector, 6); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, TIME_STEPS, DoubleVector); +vtkInformationKeyMacro(vtkStreamingDemandDrivenPipeline, UPDATE_TIME_INDEX, Integer); + +//---------------------------------------------------------------------------- +class vtkStreamingDemandDrivenPipelineToDataObjectFriendship +{ +public: + static void Crop(vtkDataObject* obj) + { + obj->Crop(); + } +}; + +//---------------------------------------------------------------------------- +vtkStreamingDemandDrivenPipeline::vtkStreamingDemandDrivenPipeline() +{ + this->ContinueExecuting = 0; + this->UpdateExtentRequest = 0; + this->LastPropogateUpdateExtentShortCircuited = 0; +} + +//---------------------------------------------------------------------------- +vtkStreamingDemandDrivenPipeline::~vtkStreamingDemandDrivenPipeline() +{ + if (this->UpdateExtentRequest) + { + this->UpdateExtentRequest->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkStreamingDemandDrivenPipeline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // The algorithm should not invoke anything on the executive. + if(!this->CheckAlgorithm("ProcessRequest", request)) + { + return 0; + } + + // Look for specially supported requests. + if(request->Has(REQUEST_UPDATE_EXTENT())) + { + // Get the output port from which the request was made. + this->LastPropogateUpdateExtentShortCircuited = 1; + int outputPort = -1; + if(request->Has(FROM_OUTPUT_PORT())) + { + outputPort = request->Get(FROM_OUTPUT_PORT()); + } + + // Make sure the information on the output port is valid. + if(!this->VerifyOutputInformation(outputPort,inInfoVec,outInfoVec)) + { + return 0; + } + + // If we need to execute, propagate the update extent. + int result = 1; + if(this->NeedToExecuteData(outputPort,inInfoVec,outInfoVec)) + { + // Make sure input types are valid before algorithm does anything. + if(!this->InputCountIsValid(inInfoVec) || + !this->InputTypeIsValid(inInfoVec)) + { + return 0; + } + + // Invoke the request on the algorithm. + this->LastPropogateUpdateExtentShortCircuited = 0; + result = this->CallAlgorithm(request, vtkExecutive::RequestUpstream, + inInfoVec, outInfoVec); + + // Propagate the update extent to all inputs. + if(result) + { + result = this->ForwardUpstream(request); + } + result = 1; + } + return result; + } + + if(request->Has(REQUEST_DATA())) + { + // Let the superclass handle the request first. + if(this->Superclass::ProcessRequest(request, inInfoVec, outInfoVec)) + { + // Crop the output if the exact extent flag is set. + for(int i=0; i < outInfoVec->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* info = outInfoVec->GetInformationObject(i); + if(info->Has(EXACT_EXTENT()) && info->Get(EXACT_EXTENT())) + { + vtkDataObject* data = info->Get(vtkDataObject::DATA_OBJECT()); + vtkStreamingDemandDrivenPipelineToDataObjectFriendship::Crop(data); + } + } + return 1; + } + return 0; + } + + // Let the superclass handle other requests. + return this->Superclass::ProcessRequest(request, inInfoVec, outInfoVec); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline::Update() +{ + return this->Superclass::Update(); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline::Update(int port) +{ + if(!this->UpdateInformation()) + { + return 0; + } + if(port >= -1 && port < this->Algorithm->GetNumberOfOutputPorts()) + { + int retval = 1; + // some streaming filters can request that the pipeline execute multiple + // times for a single update + do + { + retval = retval && this->PropagateUpdateExtent(port); + if (retval && !this->LastPropogateUpdateExtentShortCircuited) + { + retval = retval && this->UpdateData(port); + } + } + while (this->ContinueExecuting); + return retval; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline::UpdateWholeExtent() +{ + this->UpdateInformation(); + // if we have an output then set the UE to WE for it + if (this->Algorithm->GetNumberOfOutputPorts()) + { + this->SetUpdateExtentToWholeExtent + (this->GetOutputInformation()->GetInformationObject(0)); + } + // otherwise do it for the inputs + else + { + // Loop over all input ports. + for(int i=0; i < this->Algorithm->GetNumberOfInputPorts(); ++i) + { + // Loop over all connections on this input port. + int numInConnections = this->Algorithm->GetNumberOfInputConnections(i); + for (int j=0; jGetInputInformation(i, j); + this->SetUpdateExtentToWholeExtent(inInfo); + } + } + } + return this->Update(); +} + +//---------------------------------------------------------------------------- +int +vtkStreamingDemandDrivenPipeline +::ExecuteInformation(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Let the superclass make the request to the algorithm. + if(this->Superclass::ExecuteInformation(request,inInfoVec,outInfoVec)) + { + for(int i=0; i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* info = outInfoVec->GetInformationObject(i); + vtkDataObject* data = info->Get(vtkDataObject::DATA_OBJECT()); + + if (!data) + { + return 0; + } + // Set default maximum request. + if(data->GetExtentType() == VTK_PIECES_EXTENT) + { + if(!info->Has(MAXIMUM_NUMBER_OF_PIECES())) + { + info->Set(MAXIMUM_NUMBER_OF_PIECES(), -1); + } + } + else if(data->GetExtentType() == VTK_3D_EXTENT) + { + if(!info->Has(WHOLE_EXTENT())) + { + int extent[6] = {0,-1,0,-1,0,-1}; + info->Set(WHOLE_EXTENT(), extent, 6); + } + } + + // Make sure an update request exists. + if(!info->Has(UPDATE_EXTENT_INITIALIZED()) || + !info->Get(UPDATE_EXTENT_INITIALIZED())) + { + // Request all data by default. + this->SetUpdateExtentToWholeExtent + (outInfoVec->GetInformationObject(i)); + } + } + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +void +vtkStreamingDemandDrivenPipeline +::CopyDefaultInformation(vtkInformation* request, int direction, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Let the superclass copy first. + this->Superclass::CopyDefaultInformation(request, direction, + inInfoVec, outInfoVec); + + if(request->Has(REQUEST_INFORMATION())) + { + if(this->GetNumberOfInputPorts() > 0) + { + if(vtkInformation* inInfo = inInfoVec[0]->GetInformationObject(0)) + { + // Copy information from the first input to all outputs. + for(int i=0; i < outInfoVec->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outInfoVec->GetInformationObject(i); + outInfo->CopyEntry(inInfo, WHOLE_BOUNDING_BOX()); + outInfo->CopyEntry(inInfo, WHOLE_EXTENT()); + outInfo->CopyEntry(inInfo, MAXIMUM_NUMBER_OF_PIECES()); + outInfo->CopyEntry(inInfo, EXTENT_TRANSLATOR()); + outInfo->CopyEntry(inInfo, TIME_STEPS()); + } + } + } + + // Setup default information for the outputs. + for(int i=0; i < outInfoVec->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outInfoVec->GetInformationObject(i); + + // The data object will exist because UpdateDataObject has already + // succeeded. Except when this method is called by a subclass + // that does not provide this key in certain cases. + vtkDataObject* dataObject = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if (!dataObject) + { + continue; + } + vtkInformation* dataInfo = dataObject->GetInformation(); + if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_PIECES_EXTENT) + { + if (!outInfo->Has(MAXIMUM_NUMBER_OF_PIECES())) + { + if (this->GetNumberOfInputPorts() > 0) + { + // must have structured input; MAXIMUM_NUMBER_OF_PIECES will + // not be copied above (CopyEntry does nothing since key not set + // in inInfo); set to -1 + outInfo->Set(MAXIMUM_NUMBER_OF_PIECES(), -1); + } + else + { + // Since most unstructured filters in VTK generate all their + // data once, set the default maximum number of pieces to 1. + outInfo->Set(MAXIMUM_NUMBER_OF_PIECES(), 1); + } + } + } + else if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_3D_EXTENT) + { + if(!outInfo->Has(EXTENT_TRANSLATOR()) || + !outInfo->Get(EXTENT_TRANSLATOR())) + { + // Create a default extent translator. + vtkExtentTranslator* translator = vtkExtentTranslator::New(); + outInfo->Set(EXTENT_TRANSLATOR(), translator); + translator->Delete(); + } + } + } + } + if(request->Has(REQUEST_UPDATE_EXTENT())) + { + // Get the output port from which to copy the extent. + int outputPort = -1; + if(request->Has(FROM_OUTPUT_PORT())) + { + outputPort = request->Get(FROM_OUTPUT_PORT()); + } + + // Setup default information for the inputs. + if(outInfoVec->GetNumberOfInformationObjects() > 0) + { + // Copy information from the output port that made the request. + // Since VerifyOutputInformation has already been called we know + // there is output information with a data object. + vtkInformation* outInfo = + outInfoVec->GetInformationObject((outputPort >= 0)? outputPort : 0); + vtkDataObject* outData = outInfo->Get(vtkDataObject::DATA_OBJECT()); + + // Loop over all input ports. + for(int i=0; i < this->Algorithm->GetNumberOfInputPorts(); ++i) + { + // Loop over all connections on this input port. + int numInConnections = inInfoVec[i]->GetNumberOfInformationObjects(); + for (int j=0; jGetInformationObject(j); + + // Copy the time request + if ( outInfo->Has(UPDATE_TIME_INDEX()) ) + { + inInfo->CopyEntry(outInfo, UPDATE_TIME_INDEX()); + } + + // If an algorithm wants an exact extent it must explicitly + // add it to the request. We do not want to get the setting + // from another consumer of the same input. + inInfo->Remove(EXACT_EXTENT()); + + // Get the input data object for this connection. It should + // have already been created by the UpdateDataObject pass. + vtkDataObject* inData = inInfo->Get(vtkDataObject::DATA_OBJECT()); + if(!inData) + { + vtkErrorMacro("Cannot copy default update request from output port " + << outputPort << " on algorithm " + << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ") to input connection " + << j << " on input port " << i + << " because there is no data object."); + continue; + } + + // Consider all combinations of extent types. + if(inData->GetExtentType() == VTK_PIECES_EXTENT) + { + if(outData->GetExtentType() == VTK_PIECES_EXTENT) + { + if (outInfo->Get(UPDATE_PIECE_NUMBER()) < 0) + { + return; + } + inInfo->CopyEntry(outInfo, UPDATE_PIECE_NUMBER()); + inInfo->CopyEntry(outInfo, UPDATE_NUMBER_OF_PIECES()); + inInfo->CopyEntry(outInfo, UPDATE_NUMBER_OF_GHOST_LEVELS()); + inInfo->CopyEntry(outInfo, UPDATE_EXTENT_INITIALIZED()); + } + else if(outData->GetExtentType() == VTK_3D_EXTENT) + { + // The conversion from structrued requests to + // unstrcutured requests is always to request the whole + // extent. + this->SetUpdateExtentToWholeExtent(inInfo); + } + } + else if(inData->GetExtentType() == VTK_3D_EXTENT) + { + if(outData->GetExtentType() == VTK_PIECES_EXTENT) + { + int piece = outInfo->Get(UPDATE_PIECE_NUMBER()); + int numPieces = outInfo->Get(UPDATE_NUMBER_OF_PIECES()); + int ghostLevel = outInfo->Get(UPDATE_NUMBER_OF_GHOST_LEVELS()); + if (piece >= 0) + { + this->SetUpdateExtent(inInfo, piece, numPieces, ghostLevel); + } + } + else if(outData->GetExtentType() == VTK_3D_EXTENT) + { + inInfo->CopyEntry(outInfo, UPDATE_EXTENT()); + inInfo->CopyEntry(outInfo, UPDATE_EXTENT_INITIALIZED()); + } + } + } + } + } + } +} + +//---------------------------------------------------------------------------- +void +vtkStreamingDemandDrivenPipeline +::ResetPipelineInformation(int port, vtkInformation* info) +{ + this->Superclass::ResetPipelineInformation(port, info); + info->Remove(WHOLE_EXTENT()); + info->Remove(MAXIMUM_NUMBER_OF_PIECES()); + info->Remove(EXTENT_TRANSLATOR()); + info->Remove(EXACT_EXTENT()); + info->Remove(UPDATE_EXTENT_INITIALIZED()); + info->Remove(UPDATE_EXTENT()); + info->Remove(UPDATE_PIECE_NUMBER()); + info->Remove(UPDATE_NUMBER_OF_PIECES()); + info->Remove(UPDATE_NUMBER_OF_GHOST_LEVELS()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline::PropagateUpdateExtent(int outputPort) +{ + // The algorithm should not invoke anything on the executive. + if(!this->CheckAlgorithm("PropagateUpdateExtent", 0)) + { + return 0; + } + + // Range check. + if(outputPort < -1 || + outputPort >= this->Algorithm->GetNumberOfOutputPorts()) + { + vtkErrorMacro("PropagateUpdateExtent given output port index " + << outputPort << " on an algorithm with " + << this->Algorithm->GetNumberOfOutputPorts() + << " output ports."); + return 0; + } + + // Setup the request for update extent propagation. + if (!this->UpdateExtentRequest) + { + this->UpdateExtentRequest = vtkInformation::New(); + this->UpdateExtentRequest->Set(REQUEST_UPDATE_EXTENT()); + // The request is forwarded upstream through the pipeline. + this->UpdateExtentRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); + // Algorithms process this request before it is forwarded. + this->UpdateExtentRequest->Set(vtkExecutive::ALGORITHM_BEFORE_FORWARD(), 1); + } + + this->UpdateExtentRequest->Set(FROM_OUTPUT_PORT(), outputPort); + + // Send the request. + return this->ProcessRequest(this->UpdateExtentRequest, + this->GetInputInformation(), + this->GetOutputInformation()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::VerifyOutputInformation(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // If no port is specified, check all ports. + if(outputPort < 0) + { + for(int i=0; i < this->Algorithm->GetNumberOfOutputPorts(); ++i) + { + if(!this->VerifyOutputInformation(i,inInfoVec,outInfoVec)) + { + return 0; + } + } + return 1; + } + + // Get the information object to check. + vtkInformation* outInfo = outInfoVec->GetInformationObject(outputPort); + + // Make sure there is a data object. It is supposed to be created + // by the UpdateDataObject step. + vtkDataObject* dataObject = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if(!dataObject) + { + vtkErrorMacro("No data object has been set in the information for " + "output port " << outputPort << "."); + return 0; + } + + // Check extents. + vtkInformation* dataInfo = dataObject->GetInformation(); + if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_PIECES_EXTENT) + { + // For an unstructured extent, make sure the update request + // exists. We do not need to check if it is valid because + // out-of-range requests produce empty data. + if(!outInfo->Has(MAXIMUM_NUMBER_OF_PIECES())) + { + vtkErrorMacro("No maximum number of pieces has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + if(!outInfo->Has(UPDATE_PIECE_NUMBER())) + { + vtkErrorMacro("No update piece number has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + if(!outInfo->Has(UPDATE_NUMBER_OF_PIECES())) + { + vtkErrorMacro("No update number of pieces has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + if(!outInfo->Has(UPDATE_NUMBER_OF_GHOST_LEVELS())) + { + // Use zero ghost levels by default. + outInfo->Set(UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); + } + } + else if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_3D_EXTENT) + { + // For a structured extent, make sure the update request + // exists. + if(!outInfo->Has(WHOLE_EXTENT())) + { + vtkErrorMacro("No whole extent has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + if(!outInfo->Has(UPDATE_EXTENT())) + { + vtkErrorMacro("No update extent has been set in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ")."); + return 0; + } + // Make sure the update request is inside the whole extent. + int wholeExtent[6]; + int updateExtent[6]; + outInfo->Get(WHOLE_EXTENT(), wholeExtent); + outInfo->Get(UPDATE_EXTENT(), updateExtent); + if((updateExtent[0] < wholeExtent[0] || + updateExtent[1] > wholeExtent[1] || + updateExtent[2] < wholeExtent[2] || + updateExtent[3] > wholeExtent[3] || + updateExtent[4] < wholeExtent[4] || + updateExtent[5] > wholeExtent[5]) && + (updateExtent[0] <= updateExtent[1] && + updateExtent[2] <= updateExtent[3] && + updateExtent[4] <= updateExtent[5])) + { + // Update extent is outside the whole extent and is not empty. + vtkErrorMacro("The update extent specified in the " + "information for output port " << outputPort + << " on algorithm " << this->Algorithm->GetClassName() + << "(" << this->Algorithm << ") is " + << updateExtent[0] << " " << updateExtent[1] << " " + << updateExtent[2] << " " << updateExtent[3] << " " + << updateExtent[4] << " " << updateExtent[5] + << ", which is outside the whole extent " + << wholeExtent[0] << " " << wholeExtent[1] << " " + << wholeExtent[2] << " " << wholeExtent[3] << " " + << wholeExtent[4] << " " << wholeExtent[5] << "."); + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void +vtkStreamingDemandDrivenPipeline +::ExecuteDataStart(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Preserve the execution continuation flag in the request across + // iterations of the algorithm. Perform start operations only if + // not in an execute continuation. + if(this->ContinueExecuting) + { + request->Set(CONTINUE_EXECUTING(), 1); + } + else + { + request->Remove(CONTINUE_EXECUTING()); + this->Superclass::ExecuteDataStart(request,inInfoVec,outInfoVec); + } +} + +//---------------------------------------------------------------------------- +void +vtkStreamingDemandDrivenPipeline +::ExecuteDataEnd(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Preserve the execution continuation flag in the request across + // iterations of the algorithm. Perform start operations only if + // not in an execute continuation. + if(request->Get(CONTINUE_EXECUTING())) + { + this->ContinueExecuting = 1; + } + else + { + this->ContinueExecuting = 0; + this->Superclass::ExecuteDataEnd(request,inInfoVec,outInfoVec); + } +} + +//---------------------------------------------------------------------------- +void +vtkStreamingDemandDrivenPipeline +::MarkOutputsGenerated(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Tell outputs they have been generated. + this->Superclass::MarkOutputsGenerated(request,inInfoVec,outInfoVec); + + // Compute ghost level arrays for generated outputs. + for(int i=0; i < outInfoVec->GetNumberOfInformationObjects(); ++i) + { + vtkInformation* outInfo = outInfoVec->GetInformationObject(i); + vtkDataObject* data = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if(data && !outInfo->Get(DATA_NOT_GENERATED())) + { + if(vtkDataSet* ds = vtkDataSet::SafeDownCast(data)) + { + ds->GenerateGhostLevelArray(); + } + } + } +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::NeedToExecuteData(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Has the algorithm asked to be executed again? + if(this->ContinueExecuting) + { + return 1; + } + + // If no port is specified, check all ports. This behavior is + // implemented by the superclass. + if(outputPort < 0) + { + return this->Superclass::NeedToExecuteData(outputPort, + inInfoVec,outInfoVec); + } + + // Does the superclass want to execute? + if(this->Superclass::NeedToExecuteData(outputPort,inInfoVec,outInfoVec)) + { + return 1; + } + + // We need to check the requested update extent. Get the output + // port information and data information. We do not need to check + // existence of values because it has already been verified by + // VerifyOutputInformation. + vtkInformation* outInfo = outInfoVec->GetInformationObject(outputPort); + vtkDataObject* dataObject = outInfo->Get(vtkDataObject::DATA_OBJECT()); + vtkInformation* dataInfo = dataObject->GetInformation(); + if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_PIECES_EXTENT) + { + // Check the unstructured extent. If we do not have the requested + // piece, we need to execute. + int updateNumberOfPieces = outInfo->Get(UPDATE_NUMBER_OF_PIECES()); + int dataNumberOfPieces = dataInfo->Get(vtkDataObject::DATA_NUMBER_OF_PIECES()); + if(dataNumberOfPieces != updateNumberOfPieces) + { + return 1; + } + int dataGhostLevel = dataInfo->Get(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS()); + int updateGhostLevel = outInfo->Get(UPDATE_NUMBER_OF_GHOST_LEVELS()); + if(dataGhostLevel != updateGhostLevel) + { + return 1; + } + if (dataNumberOfPieces != 1) + { + int dataPiece = dataInfo->Get(vtkDataObject::DATA_PIECE_NUMBER()); + int updatePiece = outInfo->Get(UPDATE_PIECE_NUMBER()); + if (dataPiece != updatePiece) + { + return 1; + } + } + } + else if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_3D_EXTENT) + { + // Check the structured extent. If the update extent is outside + // of the extent and not empty, we need to execute. + int dataExtent[6]; + int updateExtent[6]; + outInfo->Get(UPDATE_EXTENT(), updateExtent); + dataInfo->Get(vtkDataObject::DATA_EXTENT(), dataExtent); + // if the ue is out side the de + if((updateExtent[0] < dataExtent[0] || + updateExtent[1] > dataExtent[1] || + updateExtent[2] < dataExtent[2] || + updateExtent[3] > dataExtent[3] || + updateExtent[4] < dataExtent[4] || + updateExtent[5] > dataExtent[5]) && + // and the ue is set + (updateExtent[0] <= updateExtent[1] && + updateExtent[2] <= updateExtent[3] && + updateExtent[4] <= updateExtent[5])) + { + return 1; + } + } + + // if we are requesting a particular update time index, check + // if we have the desired time index + if ( outInfo->Has(UPDATE_TIME_INDEX()) ) + { + if (!dataInfo->Has(vtkDataObject::DATA_TIME_INDEX()) || + dataInfo->Get(vtkDataObject::DATA_TIME_INDEX()) != + outInfo->Get(UPDATE_TIME_INDEX())) + { + return 1; + } + } + + // We do not need to execute. + return 0; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetMaximumNumberOfPieces(vtkInformation *info, int n) +{ + if(!info) + { + vtkErrorMacro("SetMaximumNumberOfPieces on invalid output"); + return 0; + } + if(this->GetMaximumNumberOfPieces(info) != n) + { + info->Set(MAXIMUM_NUMBER_OF_PIECES(), n); + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::GetMaximumNumberOfPieces(vtkInformation *info) +{ + if(!info) + { + vtkErrorMacro("GetMaximumNumberOfPieces on invalid output"); + return 0; + } + if(!info->Has(MAXIMUM_NUMBER_OF_PIECES())) + { + info->Set(MAXIMUM_NUMBER_OF_PIECES(), -1); + } + return info->Get(MAXIMUM_NUMBER_OF_PIECES()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetWholeExtent(vtkInformation *info, int extent[6]) +{ + if(!info) + { + vtkErrorMacro("SetWholeExtent on invalid output"); + return 0; + } + int modified = 0; + int oldExtent[6]; + this->GetWholeExtent(info, oldExtent); + if(oldExtent[0] != extent[0] || oldExtent[1] != extent[1] || + oldExtent[2] != extent[2] || oldExtent[3] != extent[3] || + oldExtent[4] != extent[4] || oldExtent[5] != extent[5]) + { + modified = 1; + info->Set(WHOLE_EXTENT(), extent, 6); + } + return modified; +} + +//---------------------------------------------------------------------------- +void vtkStreamingDemandDrivenPipeline +::GetWholeExtent(vtkInformation *info, int extent[6]) +{ + static int emptyExtent[6] = {0,-1,0,-1,0,-1}; + if(!info) + { + memcpy(extent, emptyExtent, sizeof(int)*6); + return; + } + if(!info->Has(WHOLE_EXTENT())) + { + info->Set(WHOLE_EXTENT(), emptyExtent, 6); + } + info->Get(WHOLE_EXTENT(), extent); +} + +//---------------------------------------------------------------------------- +int* vtkStreamingDemandDrivenPipeline::GetWholeExtent(vtkInformation* info) +{ + static int emptyExtent[6] = {0,-1,0,-1,0,-1}; + if(!info) + { + return emptyExtent; + } + if(!info->Has(WHOLE_EXTENT())) + { + info->Set(WHOLE_EXTENT(), emptyExtent, 6); + } + return info->Get(WHOLE_EXTENT()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetUpdateExtentToWholeExtent(vtkInformation *info) +{ + // Request all data. + int modified = 0; + if(vtkDataObject* data = info->Get(vtkDataObject::DATA_OBJECT())) + { + if(data->GetExtentType() == VTK_PIECES_EXTENT) + { + modified |= this->SetUpdatePiece(info, 0); + modified |= this->SetUpdateNumberOfPieces(info, 1); + modified |= this->SetUpdateGhostLevel(info, 0); + } + else if(data->GetExtentType() == VTK_3D_EXTENT) + { + int extent[6] = {0,-1,0,-1,0,-1}; + info->Get(WHOLE_EXTENT(), extent); + modified |= this->SetUpdateExtent(info, extent); + } + } + else + { + vtkErrorMacro("SetUpdateExtentToWholeExtent called with no data object."); + } + + // Make sure the update extent will remain the whole extent until + // the update extent is explicitly set by the caller. + info->Set(UPDATE_EXTENT_INITIALIZED(), 0); + + return modified; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetUpdateExtent(vtkInformation *info, int extent[6]) +{ + if(!info) + { + vtkErrorMacro("SetUpdateExtent on invalid output"); + return 0; + } + int modified = 0; + int oldExtent[6]; + this->GetUpdateExtent(info, oldExtent); + if(oldExtent[0] != extent[0] || oldExtent[1] != extent[1] || + oldExtent[2] != extent[2] || oldExtent[3] != extent[3] || + oldExtent[4] != extent[4] || oldExtent[5] != extent[5]) + { + modified = 1; + info->Set(UPDATE_EXTENT(), extent, 6); + } + info->Set(UPDATE_EXTENT_INITIALIZED(), 1); + return modified; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetUpdateExtent(vtkInformation *info, int piece, + int numPieces, + int ghostLevel) +{ + if(!info) + { + vtkErrorMacro("SetUpdateExtent on invalid output"); + return 0; + } + int modified = 0; + modified |= this->SetUpdatePiece(info, piece); + modified |= this->SetUpdateNumberOfPieces(info, numPieces); + modified |= this->SetUpdateGhostLevel(info, ghostLevel); + if(vtkDataObject* data = info->Get(vtkDataObject::DATA_OBJECT())) + { + if(data->GetExtentType() == VTK_3D_EXTENT) + { + if(vtkExtentTranslator* translator = this->GetExtentTranslator(info)) + { + int wholeExtent[6]; + this->GetWholeExtent(info, wholeExtent); + translator->SetWholeExtent(wholeExtent); + translator->SetPiece(piece); + translator->SetNumberOfPieces(numPieces); + translator->SetGhostLevel(ghostLevel); + translator->PieceToExtent(); + modified |= this->SetUpdateExtent(info, translator->GetExtent()); + } + else + { + vtkErrorMacro("Cannot translate unstructured extent to structured " + "for algorithm " + << this->Algorithm->GetClassName() << "(" + << this->Algorithm << ")."); + } + } + } + return modified; +} + +//---------------------------------------------------------------------------- +void vtkStreamingDemandDrivenPipeline +::GetUpdateExtent(vtkInformation *info, int extent[6]) +{ + static int emptyExtent[6] = {0,-1,0,-1,0,-1}; + if(!info) + { + vtkErrorMacro("GetUpdateExtent on invalid output"); + memcpy(extent, emptyExtent, sizeof(int)*6); + return; + } + if(!info->Has(UPDATE_EXTENT())) + { + info->Set(UPDATE_EXTENT(), emptyExtent, 6); + info->Set(UPDATE_EXTENT_INITIALIZED(), 0); + } + info->Get(UPDATE_EXTENT(), extent); +} + +//---------------------------------------------------------------------------- +int* vtkStreamingDemandDrivenPipeline +::GetUpdateExtent(vtkInformation *info) +{ + static int emptyExtent[6] = {0,-1,0,-1,0,-1}; + if(!info) + { + vtkErrorMacro("GetUpdateExtent on invalid output"); + return emptyExtent; + } + if(!info->Has(UPDATE_EXTENT())) + { + info->Set(UPDATE_EXTENT(), emptyExtent, 6); + info->Set(UPDATE_EXTENT_INITIALIZED(), 0); + } + return info->Get(UPDATE_EXTENT()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetUpdatePiece(vtkInformation *info, int piece) +{ + if(!info) + { + vtkErrorMacro("SetUpdatePiece on invalid output"); + return 0; + } + int modified = 0; + if(this->GetUpdatePiece(info) != piece) + { + info->Set(UPDATE_PIECE_NUMBER(), piece); + modified = 1; + } + info->Set(UPDATE_EXTENT_INITIALIZED(), 1); + return modified; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::GetUpdatePiece(vtkInformation *info) +{ + if(!info) + { + vtkErrorMacro("GetUpdatePiece on invalid output"); + return 0; + } + if(!info->Has(UPDATE_PIECE_NUMBER())) + { + info->Set(UPDATE_PIECE_NUMBER(), 0); + } + return info->Get(UPDATE_PIECE_NUMBER()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetUpdateNumberOfPieces(vtkInformation *info, int n) +{ + if(!info) + { + vtkErrorMacro("SetUpdateNumberOfPieces on invalid output"); + return 0; + } + int modified = 0; + if(this->GetUpdateNumberOfPieces(info) != n) + { + info->Set(UPDATE_NUMBER_OF_PIECES(), n); + modified = 1; + } + info->Set(UPDATE_EXTENT_INITIALIZED(), 1); + return modified; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::GetUpdateNumberOfPieces(vtkInformation *info) +{ + if(!info) + { + vtkErrorMacro("GetUpdateNumberOfPieces on invalid output"); + return 1; + } + if(!info->Has(UPDATE_NUMBER_OF_PIECES())) + { + info->Set(UPDATE_NUMBER_OF_PIECES(), 1); + } + return info->Get(UPDATE_NUMBER_OF_PIECES()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::SetUpdateGhostLevel(vtkInformation *info, int n) +{ + if(!info) + { + vtkErrorMacro("SetUpdateGhostLevel on invalid output"); + return 0; + } + if(this->GetUpdateGhostLevel(info) != n) + { + info->Set(UPDATE_NUMBER_OF_GHOST_LEVELS(), n); + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline +::GetUpdateGhostLevel(vtkInformation *info) +{ + if(!info) + { + vtkErrorMacro("GetUpdateGhostLevel on invalid output"); + return 0; + } + if(!info->Has(UPDATE_NUMBER_OF_GHOST_LEVELS())) + { + info->Set(UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); + } + return info->Get(UPDATE_NUMBER_OF_GHOST_LEVELS()); +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline::SetRequestExactExtent(int port, int flag) +{ + if(!this->OutputPortIndexInRange(port, "set request exact extent flag on")) + { + return 0; + } + vtkInformation* info = this->GetOutputInformation(port); + if(this->GetRequestExactExtent(port) != flag) + { + info->Set(EXACT_EXTENT(), flag); + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline::GetRequestExactExtent(int port) +{ + if(!this->OutputPortIndexInRange(port, "get request exact extent flag from")) + { + return 0; + } + vtkInformation* info = this->GetOutputInformation(port); + if(!info->Has(EXACT_EXTENT())) + { + info->Set(EXACT_EXTENT(), 0); + } + return info->Get(EXACT_EXTENT()); +} + +//---------------------------------------------------------------------------- +int +vtkStreamingDemandDrivenPipeline +::SetExtentTranslator(vtkInformation *info, vtkExtentTranslator* translator) +{ + if(!info) + { + vtkErrorMacro("Attempt to set translator for invalid output"); + return 0; + } + vtkExtentTranslator* oldTranslator = + vtkExtentTranslator::SafeDownCast(info->Get(EXTENT_TRANSLATOR())); + if(translator != oldTranslator) + { + info->Set(EXTENT_TRANSLATOR(), translator); + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkExtentTranslator* +vtkStreamingDemandDrivenPipeline::GetExtentTranslator(vtkInformation *info) +{ + if(!info) + { + vtkErrorMacro("Attempt to get translator for invalid output"); + return 0; + } + vtkExtentTranslator* translator = + vtkExtentTranslator::SafeDownCast(info->Get(EXTENT_TRANSLATOR())); + if(!translator) + { + translator = vtkExtentTranslator::New(); + info->Set(EXTENT_TRANSLATOR(), translator); + translator->Delete(); + } + return translator; +} + +//---------------------------------------------------------------------------- +int vtkStreamingDemandDrivenPipeline::SetWholeBoundingBox(int port, + double extent[6]) +{ + if(!this->OutputPortIndexInRange(port, "set whole bounding box on")) + { + return 0; + } + vtkInformation* info = this->GetOutputInformation(port); + int modified = 0; + double oldBoundingBox[6]; + this->GetWholeBoundingBox(port, oldBoundingBox); + if(oldBoundingBox[0] != extent[0] || oldBoundingBox[1] != extent[1] || + oldBoundingBox[2] != extent[2] || oldBoundingBox[3] != extent[3] || + oldBoundingBox[4] != extent[4] || oldBoundingBox[5] != extent[5]) + { + modified = 1; + info->Set(WHOLE_BOUNDING_BOX(), extent, 6); + } + return modified; +} + +//---------------------------------------------------------------------------- +void vtkStreamingDemandDrivenPipeline::GetWholeBoundingBox(int port, double extent[6]) +{ + static double emptyBoundingBox[6] = {0,-1,0,-1,0,-1}; + if(!this->OutputPortIndexInRange(port, "get whole bounding box from")) + { + memcpy(extent, emptyBoundingBox, sizeof(double)*6); + return; + } + vtkInformation* info = this->GetOutputInformation(port); + if(!info->Has(WHOLE_BOUNDING_BOX())) + { + info->Set(WHOLE_BOUNDING_BOX(), emptyBoundingBox, 6); + } + info->Get(WHOLE_BOUNDING_BOX(), extent); +} + +//---------------------------------------------------------------------------- +double* vtkStreamingDemandDrivenPipeline::GetWholeBoundingBox(int port) +{ + static double emptyBoundingBox[6] = {0,-1,0,-1,0,-1}; + if(!this->OutputPortIndexInRange(port, "get whole bounding box from")) + { + return emptyBoundingBox; + } + vtkInformation* info = this->GetOutputInformation(port); + if(!info->Has(WHOLE_BOUNDING_BOX())) + { + info->Set(WHOLE_BOUNDING_BOX(), emptyBoundingBox, 6); + } + return info->Get(WHOLE_BOUNDING_BOX()); +} diff --git a/Filtering/vtkStreamingDemandDrivenPipeline.h b/Filtering/vtkStreamingDemandDrivenPipeline.h new file mode 100644 index 0000000..66abeea --- /dev/null +++ b/Filtering/vtkStreamingDemandDrivenPipeline.h @@ -0,0 +1,231 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamingDemandDrivenPipeline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStreamingDemandDrivenPipeline - Executive supporting partial updates. +// .SECTION Description +// vtkStreamingDemandDrivenPipeline is an executive that supports +// updating only a portion of the data set in the pipeline. This is +// the style of pipeline update that is provided by the old-style VTK +// 4.x pipeline. Instead of always updating an entire data set, this +// executive supports asking for pieces or sub-extents. + +#ifndef __vtkStreamingDemandDrivenPipeline_h +#define __vtkStreamingDemandDrivenPipeline_h + +#include "vtkDemandDrivenPipeline.h" + +class vtkExtentTranslator; +class vtkInformationDoubleVectorKey; +class vtkInformationIntegerKey; +class vtkInformationIntegerVectorKey; +class vtkInformationObjectBaseKey; + +class VTK_FILTERING_EXPORT vtkStreamingDemandDrivenPipeline : public vtkDemandDrivenPipeline +{ +public: + static vtkStreamingDemandDrivenPipeline* New(); + vtkTypeRevisionMacro(vtkStreamingDemandDrivenPipeline,vtkDemandDrivenPipeline); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Generalized interface for asking the executive to fullfill update + // requests. + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + + // Description: + // Bring the outputs up-to-date. + virtual int Update(); + virtual int Update(int port); + virtual int UpdateWholeExtent(); + + // Description: + // Propagate the update request from the given output port back + // through the pipeline. Should be called only when information is + // up to date. + int PropagateUpdateExtent(int outputPort); + + // Description: + // Set/Get the maximum number of pieces that can be requested from + // the given port. The maximum number of pieces is meta data for + // unstructured data sets. It gets set by the source during the + // update information call. A value of -1 indicates that there is + // no maximum. + int SetMaximumNumberOfPieces(vtkInformation *, int n); + int GetMaximumNumberOfPieces(vtkInformation *); + + // Description: + // Set/Get the whole extent of an output port. The whole extent is + // meta data for structured data sets. It gets set by the algorithm + // during the update information pass. + int SetWholeExtent(vtkInformation *, int extent[6]); + void GetWholeExtent(vtkInformation *, int extent[6]); + int* GetWholeExtent(vtkInformation *); + + // Description: + // If the whole input extent is required to generate the requested output + // extent, this method can be called to set the input update extent to the + // whole input extent. This method assumes that the whole extent is known + // (that UpdateInformation has been called) + int SetUpdateExtentToWholeExtent(vtkInformation *); + + // Description: + // Get/Set the update extent for output ports that use 3D extents. + int SetUpdateExtent(vtkInformation *, int extent[6]); + void GetUpdateExtent(vtkInformation *, int extent[6]); + int* GetUpdateExtent(vtkInformation *); + + // Description: + // Set/Get the update piece, update number of pieces, and update + // number of ghost levels for an output port. Similar to update + // extent in 3D. + int SetUpdateExtent(vtkInformation *, + int piece, int numPieces, int ghostLevel); + int SetUpdatePiece(vtkInformation *, int piece); + int GetUpdatePiece(vtkInformation *); + int SetUpdateNumberOfPieces(vtkInformation *, int n); + int GetUpdateNumberOfPieces(vtkInformation *); + int SetUpdateGhostLevel(vtkInformation *, int n); + int GetUpdateGhostLevel(vtkInformation *); + + // Description: + // This request flag indicates whether the requester can handle more + // data than requested for the given port. Right now it is used in + // vtkImageData. Image filters can return more data than requested. + // The the consumer cannot handle this (i.e. DataSetToDataSetFitler) + // the image will crop itself. This functionality used to be in + // ImageToStructuredPoints. + int SetRequestExactExtent(int port, int flag); + int GetRequestExactExtent(int port); + + // Description: + // Get/Set the object that will translate pieces into structured + // extents for an output port. + int SetExtentTranslator(vtkInformation *, vtkExtentTranslator* translator); + vtkExtentTranslator* GetExtentTranslator(vtkInformation *info); + + // Description: + // Set/Get the whole bounding box of an output port data object. + // The whole whole bounding box is meta data for data sets. It gets + // set by the algorithm during the update information pass. + int SetWholeBoundingBox(int port, double bb[6]); + void GetWholeBoundingBox(int port, double bb[6]); + double* GetWholeBoundingBox(int port); + + // Description: + // Key defining a request to propagate the update extent upstream. + static vtkInformationRequestKey* REQUEST_UPDATE_EXTENT(); + + // Description: + // Key for an algorithm to store in a request to tell this executive + // to keep executing it. + static vtkInformationIntegerKey* CONTINUE_EXECUTING(); + + // Description: + // Key to store an extent translator in pipeline information. + static vtkInformationObjectBaseKey* EXTENT_TRANSLATOR(); + + // Description: + // Keys to store an update request in pipeline information. + static vtkInformationIntegerKey* UPDATE_EXTENT_INITIALIZED(); + static vtkInformationIntegerVectorKey* UPDATE_EXTENT(); + static vtkInformationIntegerKey* UPDATE_PIECE_NUMBER(); + static vtkInformationIntegerKey* UPDATE_NUMBER_OF_PIECES(); + static vtkInformationIntegerKey* UPDATE_NUMBER_OF_GHOST_LEVELS(); + + // Description: + // Key to store the whole extent provided in pipeline information. + static vtkInformationIntegerVectorKey* WHOLE_EXTENT(); + + // Description: + // Key to store the maximum number of pieces provided in pipeline + // information. + static vtkInformationIntegerKey* MAXIMUM_NUMBER_OF_PIECES(); + + // Description: + // Key to store the bounding box of the entire data set in pipeline + // information. + static vtkInformationDoubleVectorKey* WHOLE_BOUNDING_BOX(); + + // Description: + // Key to specify the request for exact extent in pipeline information. + static vtkInformationIntegerKey* EXACT_EXTENT(); + + // Description: + // Key to store available time steps. + static vtkInformationDoubleVectorKey* TIME_STEPS(); + + // Description: + // Update time requested by the pipeline. + static vtkInformationIntegerKey* UPDATE_TIME_INDEX(); + +protected: + vtkStreamingDemandDrivenPipeline(); + ~vtkStreamingDemandDrivenPipeline(); + + // Setup default information on the output after the algorithm + // executes information. + virtual int ExecuteInformation(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + // Copy information for the given request. + virtual void CopyDefaultInformation(vtkInformation* request, int direction, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + // Helper to check output information before propagating it to inputs. + virtual int VerifyOutputInformation(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + + // Override this check to account for update extent. + virtual int NeedToExecuteData(int outputPort, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + // Override these to handle the continue-executing option. + virtual void ExecuteDataStart(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + virtual void ExecuteDataEnd(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + // Override this to handle cropping and ghost levels. + virtual void MarkOutputsGenerated(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec); + + + // Remove update/whole extent when resetting pipeline information. + virtual void ResetPipelineInformation(int port, vtkInformation*); + + // Flag for when an algorithm returns with CONTINUE_EXECUTING in the + // request. + int ContinueExecuting; + + vtkInformation *UpdateExtentRequest; + + // did the most recent PUE do anything ? + int LastPropogateUpdateExtentShortCircuited; + +private: + vtkStreamingDemandDrivenPipeline(const vtkStreamingDemandDrivenPipeline&); // Not implemented. + void operator=(const vtkStreamingDemandDrivenPipeline&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkStructuredGrid.cxx b/Filtering/vtkStructuredGrid.cxx new file mode 100644 index 0000000..d091ec1 --- /dev/null +++ b/Filtering/vtkStructuredGrid.cxx @@ -0,0 +1,1219 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGrid.h" + +#include "vtkCellData.h" +#include "vtkEmptyCell.h" +#include "vtkExtentTranslator.h" +#include "vtkGenericCell.h" +#include "vtkHexahedron.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredVisibilityConstraint.h" +#include "vtkQuad.h" +#include "vtkVertex.h" + +vtkCxxRevisionMacro(vtkStructuredGrid, "$Revision: 1.5.6.1 $"); +vtkStandardNewMacro(vtkStructuredGrid); + +vtkCxxSetObjectMacro(vtkStructuredGrid, + PointVisibility, + vtkStructuredVisibilityConstraint); +vtkCxxSetObjectMacro(vtkStructuredGrid, + CellVisibility, + vtkStructuredVisibilityConstraint); + +#define vtkAdjustBoundsMacro( A, B ) \ + A[0] = (B[0] < A[0] ? B[0] : A[0]); A[1] = (B[0] > A[1] ? B[0] : A[1]); \ + A[2] = (B[1] < A[2] ? B[1] : A[2]); A[3] = (B[1] > A[3] ? B[1] : A[3]); \ + A[4] = (B[2] < A[4] ? B[2] : A[4]); A[5] = (B[2] > A[5] ? B[2] : A[5]) + +vtkStructuredGrid::vtkStructuredGrid() +{ + this->Vertex = vtkVertex::New(); + this->Line = vtkLine::New(); + this->Quad = vtkQuad::New(); + this->Hexahedron = vtkHexahedron::New(); + this->EmptyCell = vtkEmptyCell::New(); + + this->Dimensions[0] = 0; + this->Dimensions[1] = 0; + this->Dimensions[2] = 0; + this->DataDescription = VTK_EMPTY; + + this->PointVisibility = vtkStructuredVisibilityConstraint::New(); + this->CellVisibility = vtkStructuredVisibilityConstraint::New(); + + this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_3D_EXTENT); + this->Information->Set(vtkDataObject::DATA_EXTENT(), this->Extent, 6); + + int extent[6] = {0, -1, 0, -1, 0, -1}; + memcpy(this->Extent, extent, 6*sizeof(int)); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid::~vtkStructuredGrid() +{ + this->Initialize(); + this->Vertex->Delete(); + this->Line->Delete(); + this->Quad->Delete(); + this->Hexahedron->Delete(); + this->EmptyCell->Delete(); + + this->PointVisibility->Delete(); + this->CellVisibility->Delete(); +} + +//---------------------------------------------------------------------------- +// Copy the geometric and topological structure of an input structured grid. +void vtkStructuredGrid::CopyStructure(vtkDataSet *ds) +{ + vtkStructuredGrid *sg=(vtkStructuredGrid *)ds; + vtkPointSet::CopyStructure(ds); + int i; + + for (i=0; i<3; i++) + { + this->Dimensions[i] = sg->Dimensions[i]; + } + this->SetExtent(sg->GetExtent()); + + this->DataDescription = sg->DataDescription; + + this->PointVisibility->Delete(); + this->PointVisibility = vtkStructuredVisibilityConstraint::New(); + this->PointVisibility->ShallowCopy(sg->PointVisibility); + + this->CellVisibility->Delete(); + this->CellVisibility = vtkStructuredVisibilityConstraint::New(); + this->CellVisibility->ShallowCopy(sg->CellVisibility); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::Initialize() +{ + this->Superclass::Initialize(); + + this->PointVisibility->Delete(); + this->PointVisibility = vtkStructuredVisibilityConstraint::New(); + + this->CellVisibility->Delete(); + this->CellVisibility = vtkStructuredVisibilityConstraint::New(); + + if(this->Information) + { + this->SetDimensions(0,0,0); + } +} + +//---------------------------------------------------------------------------- +int vtkStructuredGrid::GetCellType(vtkIdType cellId) +{ + // see whether the cell is blanked + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + return VTK_EMPTY_CELL; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + return VTK_EMPTY_CELL; + + case VTK_SINGLE_POINT: + return VTK_VERTEX; + + case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: + return VTK_LINE; + + case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: + return VTK_QUAD; + + case VTK_XYZ_GRID: + return VTK_HEXAHEDRON; + + default: + vtkErrorMacro(<<"Bad data description!"); + return VTK_EMPTY_CELL; + } +} + +//---------------------------------------------------------------------------- +vtkCell *vtkStructuredGrid::GetCell(vtkIdType cellId) +{ + vtkCell *cell = NULL; + vtkIdType idx; + int i, j, k; + int d01, offset1, offset2; + + // Make sure data is defined + if ( ! this->Points ) + { + vtkErrorMacro (<<"No data"); + return NULL; + } + + // see whether the cell is blanked + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + return this->EmptyCell; + } + + // Update dimensions + this->GetDimensions(); + + switch (this->DataDescription) + { + case VTK_EMPTY: + return this->EmptyCell; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell = this->Vertex; + cell->PointIds->SetId(0,0); + break; + + case VTK_X_LINE: + cell = this->Line; + cell->PointIds->SetId(0,cellId); + cell->PointIds->SetId(1,cellId+1); + break; + + case VTK_Y_LINE: + cell = this->Line; + cell->PointIds->SetId(0,cellId); + cell->PointIds->SetId(1,cellId+1); + break; + + case VTK_Z_LINE: + cell = this->Line; + cell->PointIds->SetId(0,cellId); + cell->PointIds->SetId(1,cellId+1); + break; + + case VTK_XY_PLANE: + cell = this->Quad; + i = cellId % (this->Dimensions[0]-1); + j = cellId / (this->Dimensions[0]-1); + idx = i + j*this->Dimensions[0]; + offset1 = 1; + offset2 = this->Dimensions[0]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + break; + + case VTK_YZ_PLANE: + cell = this->Quad; + j = cellId % (this->Dimensions[1]-1); + k = cellId / (this->Dimensions[1]-1); + idx = j + k*this->Dimensions[1]; + offset1 = 1; + offset2 = this->Dimensions[1]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + break; + + case VTK_XZ_PLANE: + cell = this->Quad; + i = cellId % (this->Dimensions[0]-1); + k = cellId / (this->Dimensions[0]-1); + idx = i + k*this->Dimensions[0]; + offset1 = 1; + offset2 = this->Dimensions[0]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + break; + + case VTK_XYZ_GRID: + cell = this->Hexahedron; + d01 = this->Dimensions[0]*this->Dimensions[1]; + i = cellId % (this->Dimensions[0] - 1); + j = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + k = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + idx = i+ j*this->Dimensions[0] + k*d01; + offset1 = 1; + offset2 = this->Dimensions[0]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + idx += d01; + cell->PointIds->SetId(4,idx); + cell->PointIds->SetId(5,idx+offset1); + cell->PointIds->SetId(6,idx+offset1+offset2); + cell->PointIds->SetId(7,idx+offset2); + break; + } + + // Extract point coordinates and point ids. NOTE: the ordering of the vtkQuad + // and vtkHexahedron cells are tricky. + int NumberOfIds = cell->PointIds->GetNumberOfIds(); + for (i=0; iPointIds->GetId(i); + cell->Points->SetPoint(i,this->Points->GetPoint(idx)); + } + + return cell; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::GetCell(vtkIdType cellId, vtkGenericCell *cell) +{ + vtkIdType idx; + int i, j, k; + int d01, offset1, offset2; + double x[3]; + + // Make sure data is defined + if ( ! this->Points ) + { + vtkErrorMacro (<<"No data"); + } + + // see whether the cell is blanked + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + cell->SetCellTypeToEmptyCell(); + return; + } + + // Update dimensions + this->GetDimensions(); + + switch (this->DataDescription) + { + case VTK_EMPTY: + cell->SetCellTypeToEmptyCell(); + return; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell->SetCellTypeToVertex(); + cell->PointIds->SetId(0,0); + break; + + case VTK_X_LINE: + cell->SetCellTypeToLine(); + cell->PointIds->SetId(0,cellId); + cell->PointIds->SetId(1,cellId+1); + break; + + case VTK_Y_LINE: + cell->SetCellTypeToLine(); + cell->PointIds->SetId(0,cellId); + cell->PointIds->SetId(1,cellId+1); + break; + + case VTK_Z_LINE: + cell->SetCellTypeToLine(); + cell->PointIds->SetId(0,cellId); + cell->PointIds->SetId(1,cellId+1); + break; + + case VTK_XY_PLANE: + cell->SetCellTypeToQuad(); + i = cellId % (this->Dimensions[0]-1); + j = cellId / (this->Dimensions[0]-1); + idx = i + j*this->Dimensions[0]; + offset1 = 1; + offset2 = this->Dimensions[0]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + break; + + case VTK_YZ_PLANE: + cell->SetCellTypeToQuad(); + j = cellId % (this->Dimensions[1]-1); + k = cellId / (this->Dimensions[1]-1); + idx = j + k*this->Dimensions[1]; + offset1 = 1; + offset2 = this->Dimensions[1]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + break; + + case VTK_XZ_PLANE: + cell->SetCellTypeToQuad(); + i = cellId % (this->Dimensions[0]-1); + k = cellId / (this->Dimensions[0]-1); + idx = i + k*this->Dimensions[0]; + offset1 = 1; + offset2 = this->Dimensions[0]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + break; + + case VTK_XYZ_GRID: + cell->SetCellTypeToHexahedron(); + d01 = this->Dimensions[0]*this->Dimensions[1]; + i = cellId % (this->Dimensions[0] - 1); + j = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + k = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + idx = i+ j*this->Dimensions[0] + k*d01; + offset1 = 1; + offset2 = this->Dimensions[0]; + + cell->PointIds->SetId(0,idx); + cell->PointIds->SetId(1,idx+offset1); + cell->PointIds->SetId(2,idx+offset1+offset2); + cell->PointIds->SetId(3,idx+offset2); + idx += d01; + cell->PointIds->SetId(4,idx); + cell->PointIds->SetId(5,idx+offset1); + cell->PointIds->SetId(6,idx+offset1+offset2); + cell->PointIds->SetId(7,idx+offset2); + break; + } + + // Extract point coordinates and point ids. NOTE: the ordering of the vtkQuad + // and vtkHexahedron cells are tricky. + int NumberOfIds = cell->PointIds->GetNumberOfIds(); + for (i=0; iPointIds->GetId(i); + this->Points->GetPoint(idx, x); + cell->Points->SetPoint(i, x); + } +} + + +//---------------------------------------------------------------------------- +// Fast implementation of GetCellBounds(). Bounds are calculated without +// constructing a cell. +void vtkStructuredGrid::GetCellBounds(vtkIdType cellId, double bounds[6]) +{ + vtkIdType idx = 0; + int i, j, k; + vtkIdType d01; + int offset1 = 0; + int offset2 = 0; + double x[3]; + + // Make sure data is defined + if ( ! this->Points ) + { + vtkErrorMacro (<<"No data"); + return; + } + + vtkMath::UninitializeBounds(bounds); + + // Update dimensions + this->GetDimensions(); + + switch (this->DataDescription) + { + case VTK_EMPTY: + return; + case VTK_SINGLE_POINT: // cellId can only be = 0 + this->Points->GetPoint( 0, x ); + bounds[0] = bounds[1] = x[0]; + bounds[2] = bounds[3] = x[1]; + bounds[4] = bounds[5] = x[2]; + break; + + case VTK_X_LINE: + case VTK_Y_LINE: + case VTK_Z_LINE: + this->Points->GetPoint( cellId, x ); + bounds[0] = bounds[1] = x[0]; + bounds[2] = bounds[3] = x[1]; + bounds[4] = bounds[5] = x[2]; + + this->Points->GetPoint( cellId +1, x ); + vtkAdjustBoundsMacro( bounds, x ); + break; + + case VTK_XY_PLANE: + case VTK_YZ_PLANE: + case VTK_XZ_PLANE: + if (this->DataDescription == VTK_XY_PLANE) + { + i = cellId % (this->Dimensions[0]-1); + j = cellId / (this->Dimensions[0]-1); + idx = i + j*this->Dimensions[0]; + offset1 = 1; + offset2 = this->Dimensions[0]; + } + else if (this->DataDescription == VTK_YZ_PLANE) + { + j = cellId % (this->Dimensions[1]-1); + k = cellId / (this->Dimensions[1]-1); + idx = j + k*this->Dimensions[1]; + offset1 = 1; + offset2 = this->Dimensions[1]; + } + else if (this->DataDescription == VTK_XZ_PLANE) + { + i = cellId % (this->Dimensions[0]-1); + k = cellId / (this->Dimensions[0]-1); + idx = i + k*this->Dimensions[0]; + offset1 = 1; + offset2 = this->Dimensions[0]; + } + + this->Points->GetPoint(idx, x); + bounds[0] = bounds[1] = x[0]; + bounds[2] = bounds[3] = x[1]; + bounds[4] = bounds[5] = x[2]; + + this->Points->GetPoint( idx+offset1, x); + vtkAdjustBoundsMacro( bounds, x ); + + this->Points->GetPoint( idx+offset1+offset2, x); + vtkAdjustBoundsMacro( bounds, x ); + + this->Points->GetPoint( idx+offset2, x); + vtkAdjustBoundsMacro( bounds, x ); + + break; + + case VTK_XYZ_GRID: + d01 = this->Dimensions[0]*this->Dimensions[1]; + i = cellId % (this->Dimensions[0] - 1); + j = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + k = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + idx = i+ j*this->Dimensions[0] + k*d01; + offset1 = 1; + offset2 = this->Dimensions[0]; + + this->Points->GetPoint(idx, x); + bounds[0] = bounds[1] = x[0]; + bounds[2] = bounds[3] = x[1]; + bounds[4] = bounds[5] = x[2]; + + this->Points->GetPoint( idx+offset1, x); + vtkAdjustBoundsMacro( bounds, x ); + + this->Points->GetPoint( idx+offset1+offset2, x); + vtkAdjustBoundsMacro( bounds, x ); + + this->Points->GetPoint( idx+offset2, x); + vtkAdjustBoundsMacro( bounds, x ); + + idx += d01; + + this->Points->GetPoint(idx, x); + vtkAdjustBoundsMacro( bounds, x ); + + this->Points->GetPoint( idx+offset1, x); + vtkAdjustBoundsMacro( bounds, x ); + + this->Points->GetPoint( idx+offset1+offset2, x); + vtkAdjustBoundsMacro( bounds, x ); + + this->Points->GetPoint( idx+offset2, x); + vtkAdjustBoundsMacro( bounds, x ); + + break; + } +} + + +//---------------------------------------------------------------------------- +// Turn off a particular data point. +void vtkStructuredGrid::BlankPoint(vtkIdType ptId) +{ + this->PointVisibility->Initialize(this->Dimensions); + this->PointVisibility->Blank(ptId); +} + +//---------------------------------------------------------------------------- +// Turn on a particular data point. +void vtkStructuredGrid::UnBlankPoint(vtkIdType ptId) +{ + this->PointVisibility->Initialize(this->Dimensions); + this->PointVisibility->UnBlank(ptId); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::SetPointVisibilityArray(vtkUnsignedCharArray *ptVis) +{ + this->PointVisibility->SetVisibilityById(ptVis); +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray* vtkStructuredGrid::GetPointVisibilityArray() +{ + return this->PointVisibility->GetVisibilityById(); +} + +//---------------------------------------------------------------------------- +// Turn off a particular data cell. +void vtkStructuredGrid::BlankCell(vtkIdType cellId) +{ + this->CellVisibility->Initialize(this->Dimensions); + this->CellVisibility->Blank(cellId); +} + +//---------------------------------------------------------------------------- +// Turn on a particular data cell. +void vtkStructuredGrid::UnBlankCell(vtkIdType cellId) +{ + this->CellVisibility->Initialize(this->Dimensions); + this->CellVisibility->UnBlank(cellId); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::SetCellVisibilityArray(vtkUnsignedCharArray *cellVis) +{ + this->CellVisibility->SetVisibilityById(cellVis); +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray* vtkStructuredGrid::GetCellVisibilityArray() +{ + return this->CellVisibility->GetVisibilityById(); +} + +//---------------------------------------------------------------------------- +unsigned char vtkStructuredGrid::IsPointVisible(vtkIdType pointId) +{ + return this->PointVisibility->IsVisible(pointId); +} + +//---------------------------------------------------------------------------- +// Return non-zero if the specified cell is visible (i.e., not blanked) +unsigned char vtkStructuredGrid::IsCellVisible(vtkIdType cellId) +{ + + if ( !this->CellVisibility->IsVisible(cellId) ) + { + return 0; + } + + // Update dimensions + this->GetDimensions(); + + int numIds=0; + vtkIdType ptIds[8]; + int iMin, iMax, jMin, jMax, kMin, kMax; + vtkIdType d01 = this->Dimensions[0]*this->Dimensions[1]; + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + switch (this->DataDescription) + { + case VTK_EMPTY: + return 0; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + numIds = 1; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + numIds = 2; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + ptIds[1] = iMax + jMin*this->Dimensions[0] + kMin*d01; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + numIds = 2; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + ptIds[1] = iMin + jMax*this->Dimensions[0] + kMin*d01; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + numIds = 2; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + ptIds[1] = iMin + jMin*this->Dimensions[0] + kMax*d01; + break; + + case VTK_XY_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + jMin = cellId / (this->Dimensions[0]-1); + jMax = jMin + 1; + numIds = 4; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + ptIds[1] = iMax + jMin*this->Dimensions[0] + kMin*d01; + ptIds[2] = iMax + jMax*this->Dimensions[0] + kMin*d01; + ptIds[3] = iMin + jMax*this->Dimensions[0] + kMin*d01; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (this->Dimensions[1]-1); + jMax = jMin + 1; + kMin = cellId / (this->Dimensions[1]-1); + kMax = kMin + 1; + numIds = 4; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + ptIds[1] = iMin + jMax*this->Dimensions[0] + kMin*d01; + ptIds[2] = iMin + jMax*this->Dimensions[0] + kMax*d01; + ptIds[3] = iMin + jMin*this->Dimensions[0] + kMax*d01; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + kMin = cellId / (this->Dimensions[0]-1); + kMax = kMin + 1; + numIds = 4; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + ptIds[1] = iMax + jMin*this->Dimensions[0] + kMin*d01; + ptIds[2] = iMax + jMin*this->Dimensions[0] + kMax*d01; + ptIds[3] = iMin + jMin*this->Dimensions[0] + kMax*d01; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (this->Dimensions[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + kMax = kMin + 1; + numIds = 8; + ptIds[0] = iMin + jMin*this->Dimensions[0] + kMin*d01; + ptIds[1] = iMax + jMin*this->Dimensions[0] + kMin*d01; + ptIds[2] = iMax + jMax*this->Dimensions[0] + kMin*d01; + ptIds[3] = iMin + jMax*this->Dimensions[0] + kMin*d01; + ptIds[4] = iMin + jMin*this->Dimensions[0] + kMax*d01; + ptIds[5] = iMax + jMin*this->Dimensions[0] + kMax*d01; + ptIds[6] = iMax + jMax*this->Dimensions[0] + kMax*d01; + ptIds[7] = iMin + jMax*this->Dimensions[0] + kMax*d01; + break; + } + + for (int i=0; iIsPointVisible(ptIds[i]) ) + { + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Set dimensions of structured grid dataset. +void vtkStructuredGrid::SetDimensions(int i, int j, int k) +{ + this->SetExtent(0, i-1, 0, j-1, 0, k-1); +} + +//---------------------------------------------------------------------------- +// Set dimensions of structured grid dataset. +void vtkStructuredGrid::SetDimensions(int dim[3]) +{ + this->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); +} + +//---------------------------------------------------------------------------- +// Get the points defining a cell. (See vtkDataSet for more info.) +void vtkStructuredGrid::GetCellPoints(vtkIdType cellId, vtkIdList *ptIds) +{ + // Update dimensions + this->GetDimensions(); + + int iMin, iMax, jMin, jMax, kMin, kMax; + vtkIdType d01 = this->Dimensions[0]*this->Dimensions[1]; + + ptIds->Reset(); + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + switch (this->DataDescription) + { + case VTK_EMPTY: + return; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + ptIds->SetNumberOfIds(1); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + ptIds->SetNumberOfIds(2); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(1, iMax + jMin*this->Dimensions[0] + kMin*d01); + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + ptIds->SetNumberOfIds(2); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(1, iMin + jMax*this->Dimensions[0] + kMin*d01); + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + ptIds->SetNumberOfIds(2); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(1, iMin + jMin*this->Dimensions[0] + kMax*d01); + break; + + case VTK_XY_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + jMin = cellId / (this->Dimensions[0]-1); + jMax = jMin + 1; + ptIds->SetNumberOfIds(4); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(1, iMax + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(2, iMax + jMax*this->Dimensions[0] + kMin*d01); + ptIds->SetId(3, iMin + jMax*this->Dimensions[0] + kMin*d01); + break; + + case VTK_YZ_PLANE: + jMin = cellId % (this->Dimensions[1]-1); + jMax = jMin + 1; + kMin = cellId / (this->Dimensions[1]-1); + kMax = kMin + 1; + ptIds->SetNumberOfIds(4); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(1, iMin + jMax*this->Dimensions[0] + kMin*d01); + ptIds->SetId(2, iMin + jMax*this->Dimensions[0] + kMax*d01); + ptIds->SetId(3, iMin + jMin*this->Dimensions[0] + kMax*d01); + break; + + case VTK_XZ_PLANE: + iMin = cellId % (this->Dimensions[0]-1); + iMax = iMin + 1; + kMin = cellId / (this->Dimensions[0]-1); + kMax = kMin + 1; + ptIds->SetNumberOfIds(4); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(1, iMax + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(2, iMax + jMin*this->Dimensions[0] + kMax*d01); + ptIds->SetId(3, iMin + jMin*this->Dimensions[0] + kMax*d01); + break; + + case VTK_XYZ_GRID: + iMin = cellId % (this->Dimensions[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (this->Dimensions[0] - 1)) % (this->Dimensions[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((this->Dimensions[0] - 1) * (this->Dimensions[1] - 1)); + kMax = kMin + 1; + ptIds->SetNumberOfIds(8); + ptIds->SetId(0, iMin + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(1, iMax + jMin*this->Dimensions[0] + kMin*d01); + ptIds->SetId(2, iMax + jMax*this->Dimensions[0] + kMin*d01); + ptIds->SetId(3, iMin + jMax*this->Dimensions[0] + kMin*d01); + ptIds->SetId(4, iMin + jMin*this->Dimensions[0] + kMax*d01); + ptIds->SetId(5, iMax + jMin*this->Dimensions[0] + kMax*d01); + ptIds->SetId(6, iMax + jMax*this->Dimensions[0] + kMax*d01); + ptIds->SetId(7, iMin + jMax*this->Dimensions[0] + kMax*d01); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::SetExtent(int extent[6]) +{ + int description; + + description = vtkStructuredData::SetExtent(extent, this->Extent); + + if ( description < 0 ) //improperly specified + { + vtkErrorMacro (<< "Bad Extent, retaining previous values"); + } + + if (description == VTK_UNCHANGED) + { + return; + } + + this->DataDescription = description; + + this->Modified(); + this->Dimensions[0] = extent[1] - extent[0] + 1; + this->Dimensions[1] = extent[3] - extent[2] + 1; + this->Dimensions[2] = extent[5] - extent[4] + 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::SetExtent(int xMin, int xMax, + int yMin, int yMax, + int zMin, int zMax) +{ + int extent[6]; + + extent[0] = xMin; extent[1] = xMax; + extent[2] = yMin; extent[3] = yMax; + extent[4] = zMin; extent[5] = zMax; + + this->SetExtent(extent); +} + +int *vtkStructuredGrid::GetDimensions () +{ + this->GetDimensions(this->Dimensions); + return this->Dimensions; +} + +void vtkStructuredGrid::GetDimensions (int dim[3]) +{ + const int* extent = this->Extent; + dim[0] = extent[1] - extent[0] + 1; + dim[1] = extent[3] - extent[2] + 1; + dim[2] = extent[5] - extent[4] + 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds) +{ + int numPtIds=ptIds->GetNumberOfIds(); + + // Use special methods for speed + switch (numPtIds) + { + case 0: + cellIds->Reset(); + return; + + case 1: case 2: case 4: //vertex, edge, face neighbors + vtkStructuredData::GetCellNeighbors(cellId, ptIds, + cellIds, this->GetDimensions()); + break; + + default: + this->vtkDataSet::GetCellNeighbors(cellId, ptIds, cellIds); + } + + // If blanking, remove blanked cells. + if ( this->PointVisibility->IsConstrained() ) + { + int xcellId; + for (int i=0; iGetNumberOfIds(); i++) + { + xcellId = cellIds->GetId(i); + if ( !this->IsCellVisible(xcellId) ) + { + cellIds->DeleteId(xcellId); + } + } + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkStructuredGrid::GetActualMemorySize() +{ + return this->vtkPointSet::GetActualMemorySize(); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::ShallowCopy(vtkDataObject *dataObject) +{ + vtkStructuredGrid *grid = vtkStructuredGrid::SafeDownCast(dataObject); + + if ( grid != NULL ) + { + this->InternalStructuredGridCopy(grid); + this->PointVisibility->ShallowCopy(grid->PointVisibility); + this->CellVisibility->ShallowCopy(grid->CellVisibility); + } + + + // Do superclass + this->vtkPointSet::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::DeepCopy(vtkDataObject *dataObject) +{ + vtkStructuredGrid *grid = vtkStructuredGrid::SafeDownCast(dataObject); + + if ( grid != NULL ) + { + this->InternalStructuredGridCopy(grid); + this->PointVisibility->DeepCopy(grid->PointVisibility); + this->CellVisibility->DeepCopy(grid->CellVisibility); + } + + // Do superclass + this->vtkPointSet::DeepCopy(dataObject); +} + +//---------------------------------------------------------------------------- +// This copies all the local variables (but not objects). +void vtkStructuredGrid::InternalStructuredGridCopy(vtkStructuredGrid *src) +{ + int idx; + + this->DataDescription = src->DataDescription; + + // Update dimensions + this->GetDimensions(); + + for (idx = 0; idx < 3; ++idx) + { + this->Dimensions[idx] = src->Dimensions[idx]; + } + memcpy(this->Extent, src->GetExtent(), 6*sizeof(int)); +} + +//---------------------------------------------------------------------------- +// Override this method because of blanking +void vtkStructuredGrid::GetScalarRange(double range[2]) +{ + vtkDataArray *ptScalars = this->PointData->GetScalars(); + vtkDataArray *cellScalars = this->CellData->GetScalars(); + double ptRange[2]; + double cellRange[2]; + double s; + int id, num; + + ptRange[0] = VTK_DOUBLE_MAX; + ptRange[1] = VTK_DOUBLE_MIN; + if ( ptScalars ) + { + num = this->GetNumberOfPoints(); + for (id=0; id < num; id++) + { + if ( this->IsPointVisible(id) ) + { + s = ptScalars->GetComponent(id,0); + if ( s < ptRange[0] ) + { + ptRange[0] = s; + } + if ( s > ptRange[1] ) + { + ptRange[1] = s; + } + } + } + } + + cellRange[0] = ptRange[0]; + cellRange[1] = ptRange[1]; + if ( cellScalars ) + { + num = this->GetNumberOfCells(); + for (id=0; id < num; id++) + { + if ( this->IsCellVisible(id) ) + { + s = cellScalars->GetComponent(id,0); + if ( s < cellRange[0] ) + { + cellRange[0] = s; + } + if ( s > cellRange[1] ) + { + cellRange[1] = s; + } + } + } + } + + range[0] = (cellRange[0] >= VTK_DOUBLE_MAX ? 0.0 : cellRange[0]); + range[1] = (cellRange[1] <= VTK_DOUBLE_MIN ? 1.0 : cellRange[1]); + + this->ComputeTime.Modified(); +} + + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::Crop() +{ + int i, j, k; + int uExt[6]; + const int* extent = this->Extent; + int updateExtent[6] = {0,-1,0,-1,0,-1}; + this->GetUpdateExtent(updateExtent); + + // If the update extent is larger than the extent, + // we cannot do anything about it here. + for (i = 0; i < 3; ++i) + { + uExt[i*2] = updateExtent[i*2]; + if (uExt[i*2] < extent[i*2]) + { + uExt[i*2] = extent[i*2]; + } + uExt[i*2+1] = updateExtent[i*2+1]; + if (uExt[i*2+1] > extent[i*2+1]) + { + uExt[i*2+1] = extent[i*2+1]; + } + } + + // If extents already match, then we need to do nothing. + if (extent[0] == uExt[0] && extent[1] == uExt[1] + && extent[2] == uExt[2] && extent[3] == uExt[3] + && extent[4] == uExt[4] && extent[5] == uExt[5]) + { + return; + } + else + { + vtkStructuredGrid *newGrid; + vtkPointData *inPD, *outPD; + vtkCellData *inCD, *outCD; + int outSize, jOffset, kOffset; + vtkIdType idx, newId; + vtkPoints *newPts, *inPts; + int inInc1, inInc2; + + // Get the points. Protect against empty data objects. + inPts = this->GetPoints(); + if (inPts == NULL) + { + return; + } + + vtkDebugMacro(<< "Cropping Grid"); + + newGrid = vtkStructuredGrid::New(); + inPD = this->GetPointData(); + inCD = this->GetCellData(); + outPD = newGrid->GetPointData(); + outCD = newGrid->GetCellData(); + + // Allocate necessary objects + // + newGrid->SetExtent(uExt); + outSize = (uExt[1]-uExt[0]+1)*(uExt[3]-uExt[2]+1)*(uExt[5]-uExt[4]+1); + newPts = inPts->NewInstance(); + newPts->SetDataType(inPts->GetDataType()); + newPts->SetNumberOfPoints(outSize); + outPD->CopyAllocate(inPD,outSize,outSize); + outCD->CopyAllocate(inCD,outSize,outSize); + + // Traverse this data and copy point attributes to output + newId = 0; + inInc1 = (extent[1]-extent[0]+1); + inInc2 = inInc1*(extent[3]-extent[2]+1); + for ( k=uExt[4]; k <= uExt[5]; ++k) + { + kOffset = (k - extent[4]) * inInc2; + for ( j=uExt[2]; j <= uExt[3]; ++j) + { + jOffset = (j - extent[2]) * inInc1; + for ( i=uExt[0]; i <= uExt[1]; ++i) + { + idx = (i - extent[0]) + jOffset + kOffset; + newPts->SetPoint(newId,inPts->GetPoint(idx)); + outPD->CopyData(inPD, idx, newId++); + } + } + } + + // Traverse input data and copy cell attributes to output + newId = 0; + inInc1 = (extent[1] - extent[0]); + inInc2 = inInc1*(extent[3] - extent[2]); + for ( k=uExt[4]; k < uExt[5]; ++k ) + { + kOffset = (k - extent[4]) * inInc2; + for ( j=uExt[2]; j < uExt[3]; ++j ) + { + jOffset = (j - extent[2]) * inInc1; + for ( i=uExt[0]; i < uExt[1]; ++i ) + { + idx = (i - extent[0]) + jOffset + kOffset; + outCD->CopyData(inCD, idx, newId++); + } + } + } + + this->SetExtent(uExt); + this->SetPoints(newPts); + newPts->Delete(); + inPD->ShallowCopy(outPD); + inCD->ShallowCopy(outCD); + newGrid->Delete(); + } +} + + +//---------------------------------------------------------------------------- +void vtkStructuredGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int dim[3]; + this->GetDimensions(dim); + os << indent << "Dimensions: (" << dim[0] << ", " + << dim[1] << ", " + << dim[2] << ")\n"; + + const int* extent = this->Extent; + os << indent << "Extent: " << extent[0] << ", " + << extent[1] << ", " << extent[2] << ", " + << extent[3] << ", " << extent[4] << ", " + << extent[5] << endl; + + os << ")\n"; +} + +//---------------------------------------------------------------------------- +unsigned char vtkStructuredGrid::GetPointBlanking() +{ + return this->PointVisibility->IsConstrained(); +} + +//---------------------------------------------------------------------------- +unsigned char vtkStructuredGrid::GetCellBlanking() +{ + return this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained(); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkStructuredGrid::GetData(vtkInformation* info) +{ + return info? vtkStructuredGrid::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkStructuredGrid::GetData(vtkInformationVector* v, int i) +{ + return vtkStructuredGrid::GetData(v->GetInformationObject(i)); +} diff --git a/Filtering/vtkStructuredGrid.h b/Filtering/vtkStructuredGrid.h new file mode 100644 index 0000000..37c803c --- /dev/null +++ b/Filtering/vtkStructuredGrid.h @@ -0,0 +1,278 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGrid - topologically regular array of data +// .SECTION Description +// vtkStructuredGrid is a data object that is a concrete implementation of +// vtkDataSet. vtkStructuredGrid represents a geometric structure that is a +// topologically regular array of points. The topology is that of a cube that +// has been subdivided into a regular array of smaller cubes. Each point/cell +// can be addressed with i-j-k indices. Examples include finite difference +// grids. +// +// The order and number of points must match that specified by the dimensions +// of the grid. The point order increases in i fastest (from 0<=ivtkPointSet::GetPoint(ptId);} + void GetPoint(vtkIdType ptId, double p[3]) + {this->vtkPointSet::GetPoint(ptId,p);} + vtkCell *GetCell(vtkIdType cellId); + void GetCell(vtkIdType cellId, vtkGenericCell *cell); + void GetCellBounds(vtkIdType cellId, double bounds[6]); + int GetCellType(vtkIdType cellId); + vtkIdType GetNumberOfCells(); + void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds); + void GetPointCells(vtkIdType ptId, vtkIdList *cellIds) + { + vtkStructuredData::GetPointCells(ptId,cellIds,this->GetDimensions()); + } + void Initialize(); + int GetMaxCellSize() {return 8;}; //hexahedron is the largest + void GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds); + virtual void GetScalarRange(double range[2]); + double *GetScalarRange() {return this->Superclass::GetScalarRange();} + + // Description: + // following methods are specific to structured grid + void SetDimensions(int i, int j, int k); + void SetDimensions(int dim[3]); + + // Description: + // Get dimensions of this structured points dataset. + virtual int *GetDimensions (); + virtual void GetDimensions (int dim[3]); + + // Description: + // Return the dimensionality of the data. + int GetDataDimension(); + + // Description: + // Different ways to set the extent of the data array. The extent + // should be set before the "Scalars" are set or allocated. + // The Extent is stored in the order (X, Y, Z). + void SetExtent(int extent[6]); + void SetExtent(int x1, int x2, int y1, int y2, int z1, int z2); + vtkGetVector6Macro(Extent, int); + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). THIS METHOD + // IS THREAD SAFE. + unsigned long GetActualMemorySize(); + + // Description: + // Shallow and Deep copy. + void ShallowCopy(vtkDataObject *src); + void DeepCopy(vtkDataObject *src); + + // Description: + // The extent type is a 3D extent + int GetExtentType() { return VTK_3D_EXTENT; } + + // Description: + // Methods for supporting blanking of cells. Blanking turns on or off + // points in the structured grid, and hence the cells connected to them. + // These methods should be called only after the dimensions of the + // grid are set. + void BlankPoint(vtkIdType ptId); + void UnBlankPoint(vtkIdType ptId); + + // Description: + // Methods for supporting blanking of cells. Blanking turns on or off + // cells in the structured grid, and hence the cells connected to them. + // These methods should be called only after the dimensions of the + // grid are set. + void BlankCell(vtkIdType ptId); + void UnBlankCell(vtkIdType ptId); + + // Description: + // Get the array that defines the blanking (visibility) of each point. + vtkUnsignedCharArray *GetPointVisibilityArray(); + + // Description: + // Set an array that defines the (blanking) visibility of the points + // in the grid. Make sure that length of the visibility array matches + // the number of points in the grid. + void SetPointVisibilityArray(vtkUnsignedCharArray *pointVisibility); + + // Description: + // Get the array that defines the blanking (visibility) of each cell. + vtkUnsignedCharArray *GetCellVisibilityArray(); + + // Description: + // Set an array that defines the (blanking) visibility of the cells + // in the grid. Make sure that length of the visibility array matches + // the number of points in the grid. + void SetCellVisibilityArray(vtkUnsignedCharArray *pointVisibility); + + // Description: + // Return non-zero value if specified point is visible. + // These methods should be called only after the dimensions of the + // grid are set. + unsigned char IsPointVisible(vtkIdType ptId); + + // Description: + // Return non-zero value if specified point is visible. + // These methods should be called only after the dimensions of the + // grid are set. + unsigned char IsCellVisible(vtkIdType cellId); + + // Description: + // Returns 1 if there is any visibility constraint on the points, + // 0 otherwise. + unsigned char GetPointBlanking(); + + // Description: + // Returns 1 if there is any visibility constraint on the cells, + // 0 otherwise. + unsigned char GetCellBlanking(); + + // Description: + // Reallocates and copies to set the Extent to the UpdateExtent. + // This is used internally when the exact extent is requested, + // and the source generated more than the update extent. + virtual void Crop(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkStructuredGrid* GetData(vtkInformation* info); + static vtkStructuredGrid* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkStructuredGrid(); + ~vtkStructuredGrid(); + + // for the GetCell method + vtkVertex *Vertex; + vtkLine *Line; + vtkQuad *Quad; + vtkHexahedron *Hexahedron; + vtkEmptyCell *EmptyCell; + + int Dimensions[3]; + int DataDescription; + + int Extent[6]; + + vtkStructuredVisibilityConstraint* PointVisibility; + + void SetPointVisibility(vtkStructuredVisibilityConstraint *pointVisibility); + vtkGetObjectMacro(PointVisibility, vtkStructuredVisibilityConstraint); + + vtkStructuredVisibilityConstraint* CellVisibility; + + void SetCellVisibility(vtkStructuredVisibilityConstraint *cellVisibility); + vtkGetObjectMacro(CellVisibility, vtkStructuredVisibilityConstraint); + +private: + // Description: + // For legacy compatibility. Do not use. + void GetCellNeighbors(vtkIdType cellId, vtkIdList& ptIds, vtkIdList& cellIds) + {this->GetCellNeighbors(cellId, &ptIds, &cellIds);} + + // Internal method used by DeepCopy and ShallowCopy. + void InternalStructuredGridCopy(vtkStructuredGrid *src); + +private: + vtkStructuredGrid(const vtkStructuredGrid&); // Not implemented. + void operator=(const vtkStructuredGrid&); // Not implemented. +}; + + +inline vtkIdType vtkStructuredGrid::GetNumberOfCells() +{ + int nCells=1; + int dims[3]; + int i; + + this->GetDimensions(dims); + for (i=0; i<3; i++) + { + if (dims[i] <= 0) + { + return 0; + } + if (dims[i] > 1) + { + nCells *= (dims[i]-1); + } + } + + return nCells; +} + +inline int vtkStructuredGrid::GetDataDimension() +{ + return vtkStructuredData::GetDataDimension(this->DataDescription); +} + +#endif + + + + + + diff --git a/Filtering/vtkStructuredGridAlgorithm.cxx b/Filtering/vtkStructuredGridAlgorithm.cxx new file mode 100644 index 0000000..63c0530 --- /dev/null +++ b/Filtering/vtkStructuredGridAlgorithm.cxx @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridAlgorithm.h" + +#include "vtkCommand.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkStructuredGridAlgorithm, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkStructuredGridAlgorithm); + +//---------------------------------------------------------------------------- +vtkStructuredGridAlgorithm::vtkStructuredGridAlgorithm() +{ + // by default assume filters have one input and one output + // subclasses that deviate should modify this setting + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkStructuredGridAlgorithm::~vtkStructuredGridAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkStructuredGridAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkStructuredGridAlgorithm::GetOutput(int port) +{ + return vtkStructuredGrid::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkStructuredGridAlgorithm::GetInput() +{ + return this->GetInput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkStructuredGridAlgorithm::GetInput(int port) +{ + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkStructuredGridAlgorithm::GetStructuredGridInput(int port) +{ + return vtkStructuredGrid::SafeDownCast(this->GetInput(port)); +} + +//---------------------------------------------------------------------------- +int vtkStructuredGridAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkStructuredGridAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkStructuredGridAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkStructuredGridAlgorithm::RequestInformation( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* vtkNotUsed(outputVector)) +{ + // do nothing let subclasses handle it + return 1; +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkStructuredGridAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + return 1; +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkStructuredGridAlgorithm::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (output && this->UpdateExtentIsEmpty(output)) + { + output->Initialize(); + return; + } + + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + + +//---------------------------------------------------------------------------- +void vtkStructuredGridAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} + diff --git a/Filtering/vtkStructuredGridAlgorithm.h b/Filtering/vtkStructuredGridAlgorithm.h new file mode 100644 index 0000000..bde82a2 --- /dev/null +++ b/Filtering/vtkStructuredGridAlgorithm.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridAlgorithm - Superclass for algorithms that produce only structured grid as output +// .SECTION Description + +// vtkStructuredGridAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// constructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be StructuredGrid. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// ExecuteData and ExecuteInformation. For new algorithms you should +// implement RequestData( request, inputVec, outputVec) but for older filters +// there is a default implementation that calls the old ExecuteData(output) +// signature, for even older filters that don;t implement ExecuteData the +// default implementation calls the even older Execute() signature. + +#ifndef __vtkStructuredGridAlgorithm_h +#define __vtkStructuredGridAlgorithm_h + +#include "vtkAlgorithm.h" +#include "vtkStructuredGrid.h" // makes things a bit easier + +class vtkDataSet; +class vtkStructuredGrid; + +class VTK_FILTERING_EXPORT vtkStructuredGridAlgorithm : public vtkAlgorithm +{ +public: + static vtkStructuredGridAlgorithm *New(); + vtkTypeRevisionMacro(vtkStructuredGridAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkStructuredGrid* GetOutput(); + vtkStructuredGrid* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject* GetInput(); + vtkDataObject *GetInput(int port); + vtkStructuredGrid *GetStructuredGridInput(int port); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(int, vtkDataObject*); + +protected: + vtkStructuredGridAlgorithm(); + ~vtkStructuredGridAlgorithm(); + + // convenience method + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*) + { + return 1; + }; + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkStructuredGridAlgorithm(const vtkStructuredGridAlgorithm&); // Not implemented. + void operator=(const vtkStructuredGridAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkStructuredGridSource.cxx b/Filtering/vtkStructuredGridSource.cxx new file mode 100644 index 0000000..8e01281 --- /dev/null +++ b/Filtering/vtkStructuredGridSource.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridSource.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkStructuredGrid.h" + +vtkCxxRevisionMacro(vtkStructuredGridSource, "$Revision: 1.31 $"); + +//---------------------------------------------------------------------------- +vtkStructuredGridSource::vtkStructuredGridSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + + this->vtkSource::SetNthOutput(0, vtkStructuredGrid::New()); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid *vtkStructuredGridSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkStructuredGrid *)(this->Outputs[0]); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid *vtkStructuredGridSource::GetOutput(int idx) +{ + return static_cast( this->vtkSource::GetOutput(idx) ); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridSource::SetOutput(vtkStructuredGrid *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + +//---------------------------------------------------------------------------- +int vtkStructuredGridSource::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredGridSource.h b/Filtering/vtkStructuredGridSource.h new file mode 100644 index 0000000..a3a0ef9 --- /dev/null +++ b/Filtering/vtkStructuredGridSource.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridSource - Abstract class whose subclasses generates structured grid data +// .SECTION Description +// vtkStructuredGridSource is an abstract class whose subclasses generate +// structured grid data. + +// .SECTION See Also +// vtkStructuredGridReader vtkPLOT3DReader + +#ifndef __vtkStructuredGridSource_h +#define __vtkStructuredGridSource_h + +#include "vtkSource.h" + +class vtkStructuredGrid; + +class VTK_FILTERING_EXPORT vtkStructuredGridSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkStructuredGridSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this source. + vtkStructuredGrid *GetOutput(); + vtkStructuredGrid *GetOutput(int idx); + void SetOutput(vtkStructuredGrid *output); + +protected: + vtkStructuredGridSource(); + ~vtkStructuredGridSource() {}; + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkStructuredGridSource(const vtkStructuredGridSource&); // Not implemented. + void operator=(const vtkStructuredGridSource&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkStructuredGridToPolyDataFilter.cxx b/Filtering/vtkStructuredGridToPolyDataFilter.cxx new file mode 100644 index 0000000..88c13ca --- /dev/null +++ b/Filtering/vtkStructuredGridToPolyDataFilter.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridToPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridToPolyDataFilter.h" + +#include "vtkInformation.h" +#include "vtkStructuredGrid.h" + +vtkCxxRevisionMacro(vtkStructuredGridToPolyDataFilter, "$Revision: 1.17 $"); + +//---------------------------------------------------------------------------- +vtkStructuredGridToPolyDataFilter::vtkStructuredGridToPolyDataFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkStructuredGridToPolyDataFilter::~vtkStructuredGridToPolyDataFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkStructuredGridToPolyDataFilter::SetInput(vtkStructuredGrid *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkStructuredGrid *vtkStructuredGridToPolyDataFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkStructuredGrid *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +int +vtkStructuredGridToPolyDataFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridToPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredGridToPolyDataFilter.h b/Filtering/vtkStructuredGridToPolyDataFilter.h new file mode 100644 index 0000000..5ff58f2 --- /dev/null +++ b/Filtering/vtkStructuredGridToPolyDataFilter.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridToPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridToPolyDataFilter - abstract filter class +// .SECTION Description +// vtkStructuredGridToPolyDataFilter is a filter whose subclasses take as input +// structured grid datasets and generate polygonal data on output. + +// .SECTION See Also +// vtkStructuredGridGeometryFilter vtkStructuredGridOutlineFilter + +#ifndef __vtkStructuredGridToPolyDataFilter_h +#define __vtkStructuredGridToPolyDataFilter_h + +#include "vtkPolyDataSource.h" + +class vtkStructuredGrid; + +class VTK_FILTERING_EXPORT vtkStructuredGridToPolyDataFilter : public vtkPolyDataSource +{ +public: + vtkTypeRevisionMacro(vtkStructuredGridToPolyDataFilter,vtkPolyDataSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input Grid or filter. + void SetInput(vtkStructuredGrid *input); + vtkStructuredGrid *GetInput(); + +protected: + vtkStructuredGridToPolyDataFilter(); + ~vtkStructuredGridToPolyDataFilter(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkStructuredGridToPolyDataFilter(const vtkStructuredGridToPolyDataFilter&); // Not implemented. + void operator=(const vtkStructuredGridToPolyDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkStructuredGridToStructuredGridFilter.cxx b/Filtering/vtkStructuredGridToStructuredGridFilter.cxx new file mode 100644 index 0000000..ef61c31 --- /dev/null +++ b/Filtering/vtkStructuredGridToStructuredGridFilter.cxx @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridToStructuredGridFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridToStructuredGridFilter.h" + +#include "vtkInformation.h" +#include "vtkStructuredGrid.h" + +vtkCxxRevisionMacro(vtkStructuredGridToStructuredGridFilter, "$Revision: 1.22 $"); + +//---------------------------------------------------------------------------- +vtkStructuredGridToStructuredGridFilter::vtkStructuredGridToStructuredGridFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkStructuredGridToStructuredGridFilter::~vtkStructuredGridToStructuredGridFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkStructuredGridToStructuredGridFilter::SetInput(vtkStructuredGrid *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkStructuredGrid *vtkStructuredGridToStructuredGridFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkStructuredGrid *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +int +vtkStructuredGridToStructuredGridFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + //info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); HACK + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridToStructuredGridFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredGridToStructuredGridFilter.h b/Filtering/vtkStructuredGridToStructuredGridFilter.h new file mode 100644 index 0000000..38ea030 --- /dev/null +++ b/Filtering/vtkStructuredGridToStructuredGridFilter.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridToStructuredGridFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridToStructuredGridFilter - abstract filter class +// .SECTION Description +// vtkStructuredPointsToStructuredPointsFilter is an abstract filter class +// whose subclasses take on input a structured grid and generate a +// structured grid on output. + +// .SECTION See Also +// vtkExtractGrid + +#ifndef __vtkStructuredGridToStructuredGridFilter_h +#define __vtkStructuredGridToStructuredGridFilter_h + +#include "vtkStructuredGridSource.h" + +class VTK_FILTERING_EXPORT vtkStructuredGridToStructuredGridFilter : public vtkStructuredGridSource +{ +public: + vtkTypeRevisionMacro(vtkStructuredGridToStructuredGridFilter,vtkStructuredGridSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input Grid or filter. + void SetInput(vtkStructuredGrid *input); + vtkStructuredGrid *GetInput(); + +protected: + vtkStructuredGridToStructuredGridFilter(); + ~vtkStructuredGridToStructuredGridFilter(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkStructuredGridToStructuredGridFilter(const vtkStructuredGridToStructuredGridFilter&); // Not implemented. + void operator=(const vtkStructuredGridToStructuredGridFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkStructuredPoints.cxx b/Filtering/vtkStructuredPoints.cxx new file mode 100644 index 0000000..d0ee80a --- /dev/null +++ b/Filtering/vtkStructuredPoints.cxx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPoints.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkStructuredPoints, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkStructuredPoints); + +vtkStructuredPoints::vtkStructuredPoints() +{ +} diff --git a/Filtering/vtkStructuredPoints.h b/Filtering/vtkStructuredPoints.h new file mode 100644 index 0000000..cdf7000 --- /dev/null +++ b/Filtering/vtkStructuredPoints.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPoints - A subclass of ImageData. +// .SECTION Description +// StructuredPoints is a subclass of ImageData that requires the data extent +// to exactly match the update extent. Normall image data allows that the +// data extent may be larger than the update extent. +// StructuredPoints also defines the origin differently that vtkImageData. +// For structured points the origin is the location of first point. +// Whereas images define the origin as the location of point 0, 0, 0. +// Image Origin is stored in ivar, and structured points +// have special methods for setting/getting the origin/extents. + + +#ifndef __vtkStructuredPoints_h +#define __vtkStructuredPoints_h + +#include "vtkImageData.h" + + +class VTK_FILTERING_EXPORT vtkStructuredPoints : public vtkImageData +{ +public: + static vtkStructuredPoints *New(); + vtkTypeRevisionMacro(vtkStructuredPoints,vtkImageData); + + // Description: + // To simplify filter superclasses, + int GetDataObjectType() {return VTK_STRUCTURED_POINTS;} + +protected: + vtkStructuredPoints(); + ~vtkStructuredPoints() {}; +private: + vtkStructuredPoints(const vtkStructuredPoints&); // Not implemented. + void operator=(const vtkStructuredPoints&); // Not implemented. +}; + +#endif + + + diff --git a/Filtering/vtkStructuredPointsCollection.cxx b/Filtering/vtkStructuredPointsCollection.cxx new file mode 100644 index 0000000..4b1c678 --- /dev/null +++ b/Filtering/vtkStructuredPointsCollection.cxx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkStructuredPointsCollection, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkStructuredPointsCollection); + +//---------------------------------------------------------------------------- +void vtkStructuredPointsCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredPointsCollection.h b/Filtering/vtkStructuredPointsCollection.h new file mode 100644 index 0000000..783c935 --- /dev/null +++ b/Filtering/vtkStructuredPointsCollection.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsCollection - maintain a list of structured points data objects +// .SECTION Description +// vtkStructuredPointsCollection is an object that creates and manipulates +// lists of structured points datasets. See also vtkCollection and +// subclasses. + +#ifndef __vtkStructuredPointsCollection_h +#define __vtkStructuredPointsCollection_h + +#include "vtkCollection.h" +#include "vtkStructuredPoints.h" // Needed for static cast + +class VTK_FILTERING_EXPORT vtkStructuredPointsCollection : public vtkCollection +{ +public: + static vtkStructuredPointsCollection *New(); + vtkTypeRevisionMacro(vtkStructuredPointsCollection,vtkCollection); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a pointer to a vtkStructuredPoints to the list. + void AddItem(vtkStructuredPoints *ds) { + this->vtkCollection::AddItem((vtkObject *)ds);}; + + // Description: + // Get the next item in the collection. NULL is returned if the collection + // is exhausted. + vtkStructuredPoints *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkStructuredPoints *GetNextStructuredPoints( + vtkCollectionSimpleIterator &cookie) { + return static_cast( + this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkStructuredPointsCollection() {}; + ~vtkStructuredPointsCollection() {}; + + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkStructuredPointsCollection(const vtkStructuredPointsCollection&); // Not implemented. + void operator=(const vtkStructuredPointsCollection&); // Not implemented. +}; + + +#endif diff --git a/Filtering/vtkStructuredPointsSource.cxx b/Filtering/vtkStructuredPointsSource.cxx new file mode 100644 index 0000000..0b96762 --- /dev/null +++ b/Filtering/vtkStructuredPointsSource.cxx @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsSource.h" + +#include "vtkDataArray.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStructuredPoints.h" + +vtkCxxRevisionMacro(vtkStructuredPointsSource, "$Revision: 1.39 $"); + +//---------------------------------------------------------------------------- +vtkStructuredPointsSource::vtkStructuredPointsSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + + this->SetOutput(vtkStructuredPoints::New()); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsSource::SetOutput(vtkStructuredPoints *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + +//---------------------------------------------------------------------------- +vtkStructuredPoints *vtkStructuredPointsSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkStructuredPoints *)(this->Outputs[0]); +} + +//---------------------------------------------------------------------------- +vtkStructuredPoints *vtkStructuredPointsSource::GetOutput(int idx) +{ + return (vtkStructuredPoints *) this->vtkSource::GetOutput(idx); +} + +//---------------------------------------------------------------------------- +// Default method performs Update to get information. Not all the old +// structured points sources compute information +void vtkStructuredPointsSource::ExecuteInformation() +{ + vtkStructuredPoints *output = this->GetOutput(); + vtkDataArray *scalars; + + output->UpdateData(); + scalars = output->GetPointData()->GetScalars(); + + if (scalars) + { + output->SetScalarType(scalars->GetDataType()); + output->SetNumberOfScalarComponents(scalars->GetNumberOfComponents()); + } + + output->SetWholeExtent(output->GetExtent()); +} + +//---------------------------------------------------------------------------- +int vtkStructuredPointsSource::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredPoints"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredPointsSource.h b/Filtering/vtkStructuredPointsSource.h new file mode 100644 index 0000000..54cf557 --- /dev/null +++ b/Filtering/vtkStructuredPointsSource.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsSource - Abstract class whose subclasses generates structured Points data +// .SECTION Description +// vtkStructuredPointsSource is an abstract class whose subclasses generate +// structured Points data. + +// .SECTION See Also +// vtkStructuredPointsReader vtkPLOT3DReader + +#ifndef __vtkStructuredPointsSource_h +#define __vtkStructuredPointsSource_h + +#include "vtkSource.h" + +class vtkStructuredPoints; + +class VTK_FILTERING_EXPORT vtkStructuredPointsSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkStructuredPointsSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the output of this source. + void SetOutput(vtkStructuredPoints *output); + vtkStructuredPoints *GetOutput(); + vtkStructuredPoints *GetOutput(int idx); + +protected: + vtkStructuredPointsSource(); + ~vtkStructuredPointsSource() {}; + + // Default method performs Update to get information. Not all the old + // structured points sources compute information + void ExecuteInformation(); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkStructuredPointsSource(const vtkStructuredPointsSource&); // Not implemented. + void operator=(const vtkStructuredPointsSource&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkStructuredPointsToPolyDataFilter.cxx b/Filtering/vtkStructuredPointsToPolyDataFilter.cxx new file mode 100644 index 0000000..0286948 --- /dev/null +++ b/Filtering/vtkStructuredPointsToPolyDataFilter.cxx @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsToPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsToPolyDataFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkStructuredPointsToPolyDataFilter, "$Revision: 1.30 $"); + +//---------------------------------------------------------------------------- +vtkStructuredPointsToPolyDataFilter::vtkStructuredPointsToPolyDataFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkStructuredPointsToPolyDataFilter::~vtkStructuredPointsToPolyDataFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkStructuredPointsToPolyDataFilter::SetInput(vtkImageData *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkImageData *vtkStructuredPointsToPolyDataFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkImageData *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsToPolyDataFilter::ComputeInputUpdateExtents( + vtkDataObject *output) +{ + this->vtkPolyDataSource::ComputeInputUpdateExtents(output); + + if (!this->GetInput()) + { + return; + } + // assume that we cannot handle more than the requested extent. + this->GetInput()->RequestExactExtentOn(); +} + +//---------------------------------------------------------------------------- +int vtkStructuredPointsToPolyDataFilter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsToPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredPointsToPolyDataFilter.h b/Filtering/vtkStructuredPointsToPolyDataFilter.h new file mode 100644 index 0000000..9e66a11 --- /dev/null +++ b/Filtering/vtkStructuredPointsToPolyDataFilter.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsToPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsToPolyDataFilter - abstract filter class +// .SECTION Description +// vtkStructuredPointsToPolyDataFilter is an abstract filter class whose +// subclasses take on input structured points and generate polygonal +// data on output. + +// .SECTION See Also +// vtkDividingCubes vtkMarchingCubes vtkMarchingSquares +// vtkRecursiveDividingCubes vtkImageDataGeometryFilter + +#ifndef __vtkStructuredPointsToPolyDataFilter_h +#define __vtkStructuredPointsToPolyDataFilter_h + +#include "vtkPolyDataSource.h" + +class vtkImageData; + +class VTK_FILTERING_EXPORT vtkStructuredPointsToPolyDataFilter : public vtkPolyDataSource +{ +public: + vtkTypeRevisionMacro(vtkStructuredPointsToPolyDataFilter,vtkPolyDataSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkImageData *input); + vtkImageData *GetInput(); + +protected: + vtkStructuredPointsToPolyDataFilter(); + ~vtkStructuredPointsToPolyDataFilter(); + + void ComputeInputUpdateExtents(vtkDataObject *output); + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkStructuredPointsToPolyDataFilter(const vtkStructuredPointsToPolyDataFilter&); // Not implemented. + void operator=(const vtkStructuredPointsToPolyDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkStructuredPointsToStructuredPointsFilter.cxx b/Filtering/vtkStructuredPointsToStructuredPointsFilter.cxx new file mode 100644 index 0000000..be4a1ad --- /dev/null +++ b/Filtering/vtkStructuredPointsToStructuredPointsFilter.cxx @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsToStructuredPointsFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsToStructuredPointsFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkStructuredPoints.h" + +vtkCxxRevisionMacro(vtkStructuredPointsToStructuredPointsFilter, "$Revision: 1.32 $"); + +//---------------------------------------------------------------------------- +vtkStructuredPointsToStructuredPointsFilter::vtkStructuredPointsToStructuredPointsFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkStructuredPointsToStructuredPointsFilter::~vtkStructuredPointsToStructuredPointsFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkStructuredPointsToStructuredPointsFilter::SetInput( + vtkImageData *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkImageData *vtkStructuredPointsToStructuredPointsFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkStructuredPoints *)(this->Inputs[0]); +} + + +//---------------------------------------------------------------------------- +// Copy WholeExtent, Spacing and Origin. +void vtkStructuredPointsToStructuredPointsFilter::ExecuteInformation() +{ + vtkImageData *input = this->GetInput(); + vtkStructuredPoints *output = this->GetOutput(); + + if (output == NULL || input == NULL) + { + return; + } + + output->SetWholeExtent(input->GetWholeExtent()); + output->SetSpacing(input->GetSpacing()); + output->SetOrigin(input->GetOrigin()); +} + + +//---------------------------------------------------------------------------- +void vtkStructuredPointsToStructuredPointsFilter::ComputeInputUpdateExtents( + vtkDataObject *output) +{ + this->vtkStructuredPointsSource::ComputeInputUpdateExtents(output); + + // assume that we cannot handle more than the requested extent. + this->GetInput()->RequestExactExtentOn(); +} + +//---------------------------------------------------------------------------- +int +vtkStructuredPointsToStructuredPointsFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsToStructuredPointsFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredPointsToStructuredPointsFilter.h b/Filtering/vtkStructuredPointsToStructuredPointsFilter.h new file mode 100644 index 0000000..e40cc55 --- /dev/null +++ b/Filtering/vtkStructuredPointsToStructuredPointsFilter.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsToStructuredPointsFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsToStructuredPointsFilter - abstract filter class +// .SECTION Description +// vtkStructuredPointsToStructuredPointsFilter is an abstract filter class +// whose subclasses take on input structured points and generate +// structured points on output. + +// .SECTION See Also +// vtkExtractVOI vtkImageDifference vtkSweptSurface +// vtkTransformStructuredPoints + +#ifndef __vtkStructuredPointsToStructuredPointsFilter_h +#define __vtkStructuredPointsToStructuredPointsFilter_h + +#include "vtkStructuredPointsSource.h" + +class vtkImageData; + +class VTK_FILTERING_EXPORT vtkStructuredPointsToStructuredPointsFilter : public vtkStructuredPointsSource +{ +public: + vtkTypeRevisionMacro(vtkStructuredPointsToStructuredPointsFilter,vtkStructuredPointsSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + void SetInput(vtkImageData *input); + vtkImageData *GetInput(); + +protected: + vtkStructuredPointsToStructuredPointsFilter(); + ~vtkStructuredPointsToStructuredPointsFilter(); + + // Since input[0] and output are of same type, we can create this + // method that defaults to just copying information. + void ExecuteInformation(); + + void ComputeInputUpdateExtents(vtkDataObject *output); + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkStructuredPointsToStructuredPointsFilter(const vtkStructuredPointsToStructuredPointsFilter&); // Not implemented. + void operator=(const vtkStructuredPointsToStructuredPointsFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkStructuredPointsToUnstructuredGridFilter.cxx b/Filtering/vtkStructuredPointsToUnstructuredGridFilter.cxx new file mode 100644 index 0000000..380891a --- /dev/null +++ b/Filtering/vtkStructuredPointsToUnstructuredGridFilter.cxx @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsToUnstructuredGridFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsToUnstructuredGridFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkStructuredPoints.h" + +vtkCxxRevisionMacro(vtkStructuredPointsToUnstructuredGridFilter, "$Revision: 1.18 $"); + +//---------------------------------------------------------------------------- +vtkStructuredPointsToUnstructuredGridFilter::vtkStructuredPointsToUnstructuredGridFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkStructuredPointsToUnstructuredGridFilter::~vtkStructuredPointsToUnstructuredGridFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkStructuredPointsToUnstructuredGridFilter::SetInput(vtkImageData *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkImageData *vtkStructuredPointsToUnstructuredGridFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return static_cast(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsToUnstructuredGridFilter::ComputeInputUpdateExtents( + vtkDataObject *output) +{ + this->vtkUnstructuredGridSource::ComputeInputUpdateExtents(output); + + // assume that we cannot handle more than the requested extent. + if (this->GetInput()) + { + this->GetInput()->RequestExactExtentOn(); + } +} + +//---------------------------------------------------------------------------- +int +vtkStructuredPointsToUnstructuredGridFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsToUnstructuredGridFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkStructuredPointsToUnstructuredGridFilter.h b/Filtering/vtkStructuredPointsToUnstructuredGridFilter.h new file mode 100644 index 0000000..0743a27 --- /dev/null +++ b/Filtering/vtkStructuredPointsToUnstructuredGridFilter.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsToUnstructuredGridFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsToUnstructuredGridFilter - abstract filter class +// .SECTION Description +// vtkStructuredPointsToUnstructuredGridFilter is an abstract filter class +// whose subclasses take on input structured points and generate unstructured +// grid data on output. + +// .SECTION See Also +// vtkClipVolume + +#ifndef __vtkStructuredPointsToUnstructuredGridFilter_h +#define __vtkStructuredPointsToUnstructuredGridFilter_h + +#include "vtkUnstructuredGridSource.h" + +class vtkImageData; + +class VTK_FILTERING_EXPORT vtkStructuredPointsToUnstructuredGridFilter : public vtkUnstructuredGridSource +{ +public: + vtkTypeRevisionMacro(vtkStructuredPointsToUnstructuredGridFilter,vtkUnstructuredGridSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + void SetInput(vtkImageData *input); + vtkImageData *GetInput(); + +protected: + vtkStructuredPointsToUnstructuredGridFilter(); + ~vtkStructuredPointsToUnstructuredGridFilter(); + + void ComputeInputUpdateExtents(vtkDataObject *output); + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkStructuredPointsToUnstructuredGridFilter(const vtkStructuredPointsToUnstructuredGridFilter&); // Not implemented. + void operator=(const vtkStructuredPointsToUnstructuredGridFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkSuperquadric.cxx b/Filtering/vtkSuperquadric.cxx new file mode 100644 index 0000000..c585fd3 --- /dev/null +++ b/Filtering/vtkSuperquadric.cxx @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSuperquadric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* vtkSuperQuadric originally written by Michael Halle, + Brigham and Women's Hospital, July 1998. + + Based on "Rigid physically based superquadrics", A. H. Barr, + in "Graphics Gems III", David Kirk, ed., Academic Press, 1992. +*/ + +#include "vtkSuperquadric.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkSuperquadric, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkSuperquadric); + +// Construct with superquadric radius of 0.5, toroidal off, center at 0.0, +// scale (1,1,1), size 0.5, phi roundness 1.0, and theta roundness 0.0. +vtkSuperquadric::vtkSuperquadric() +{ + this->Toroidal = 0; + this->Thickness = 0.3333; + this->PhiRoundness = 0.0; + this->SetPhiRoundness(1.0); + this->ThetaRoundness = 0.0; + this->SetThetaRoundness(1.0); + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + this->Scale[0] = this->Scale[1] = this->Scale[2] = 1.0; + this->Size = .5; +} + +static const double MAX_FVAL = 1e12; +static double VTK_MIN_SUPERQUADRIC_ROUNDNESS = 1e-24; + +void vtkSuperquadric::SetThetaRoundness(double e) +{ + if(e < VTK_MIN_SUPERQUADRIC_ROUNDNESS) + { + e = VTK_MIN_SUPERQUADRIC_ROUNDNESS; + } + + if (this->ThetaRoundness != e) + { + this->ThetaRoundness = e; + this->Modified(); + } +} + +void vtkSuperquadric::SetPhiRoundness(double e) +{ + if(e < VTK_MIN_SUPERQUADRIC_ROUNDNESS) + { + e = VTK_MIN_SUPERQUADRIC_ROUNDNESS; + } + + if (this->PhiRoundness != e) + { + this->PhiRoundness = e; + this->Modified(); + } +} + +// Evaluate Superquadric equation +double vtkSuperquadric::EvaluateFunction(double xyz[3]) +{ + double e = this->ThetaRoundness; + double n = this->PhiRoundness; + double p[3], s[3]; + double val; + + s[0] = this->Scale[0] * this->Size; + s[1] = this->Scale[1] * this->Size; + s[2] = this->Scale[2] * this->Size; + + if(this->Toroidal) { + double tval; + double alpha; + + alpha = (1.0 / this->Thickness); + s[0] /= (alpha + 1.0); + s[1] /= (alpha + 1.0); + s[2] /= (alpha + 1.0); + + p[0] = (xyz[0] - this->Center[0]) / s[0]; + p[1] = (xyz[1] - this->Center[1]) / s[1]; + p[2] = (xyz[2] - this->Center[2]) / s[2]; + + tval = pow((pow(fabs(p[2]), 2.0/e) + pow(fabs(p[0]), 2.0/e)), e/2.0); + val = pow(fabs(tval - alpha), 2.0/n) + pow(fabs(p[1]), 2.0/n) - 1.0; + } + else { // Ellipsoidal + p[0] = (xyz[0] - this->Center[0]) / s[0]; + p[1] = (xyz[1] - this->Center[1]) / s[1]; + p[2] = (xyz[2] - this->Center[2]) / s[2]; + + val = pow((pow(fabs(p[2]), 2.0/e) + pow(fabs(p[0]), 2.0/e)), e/n) + + pow(fabs(p[1]),2.0/n) - 1.0; + } + + if(val > MAX_FVAL){ + val = MAX_FVAL; + } + else if(val < -MAX_FVAL){ + val = -MAX_FVAL; + } + + return (double)(val); +} + +// Description +// Evaluate Superquadric function gradient. +void vtkSuperquadric::EvaluateGradient(double vtkNotUsed(xyz)[3], double g[3]) +{ + // bogus! lazy! + // if someone wants to figure these out, they are each the + // partial of x, then y, then z with respect to f as shown above. + // Careful for the fabs(). + + g[0] = g[1] = g[2] = 0.0; +} + +void vtkSuperquadric::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Toroidal: " << (this->Toroidal ? "On\n" : "Off\n"); + os << indent << "Size: " << this->Size << "\n"; + os << indent << "Thickness: " << this->Thickness << "\n"; + os << indent << "ThetaRoundness: " << this->ThetaRoundness << "\n"; + os << indent << "PhiRoundness: " << this->PhiRoundness << "\n"; + os << indent << "Center: (" + << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << ")\n"; + os << indent << "Scale: (" + << this->Scale[0] << ", " + << this->Scale[1] << ", " + << this->Scale[2] << ")\n"; + +} diff --git a/Filtering/vtkSuperquadric.h b/Filtering/vtkSuperquadric.h new file mode 100644 index 0000000..eb1bb79 --- /dev/null +++ b/Filtering/vtkSuperquadric.h @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSuperquadric.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSuperquadric - implicit function for a Superquadric +// .SECTION Description +// vtkSuperquadric computes the implicit function and function gradient +// for a superquadric. vtkSuperquadric is a concrete implementation of +// vtkImplicitFunction. The superquadric is centered at Center and axes +// of rotation is along the y-axis. (Use the superclass' +// vtkImplicitFunction transformation matrix if necessary to reposition.) +// Roundness parameters (PhiRoundness and ThetaRoundness) control +// the shape of the superquadric. The Toroidal boolean controls whether +// a toroidal superquadric is produced. If so, the Thickness parameter +// controls the thickness of the toroid: 0 is the thinnest allowable +// toroid, and 1 has a minimum sized hole. The Scale parameters allow +// the superquadric to be scaled in x, y, and z (normal vectors are correctly +// generated in any case). The Size parameter controls size of the +// superquadric. +// +// This code is based on "Rigid physically based superquadrics", A. H. Barr, +// in "Graphics Gems III", David Kirk, ed., Academic Press, 1992. +// +// .SECTION Caveats +// The Size and Thickness parameters control coefficients of superquadric +// generation, and may do not exactly describe the size of the superquadric. +// + +#ifndef __vtkSuperquadric_h +#define __vtkSuperquadric_h + +#include "vtkImplicitFunction.h" + +#define VTK_MIN_SUPERQUADRIC_THICKNESS 1e-4 + +class VTK_FILTERING_EXPORT vtkSuperquadric : public vtkImplicitFunction +{ +public: + // Description + // Construct with superquadric radius of 0.5, toroidal off, center at 0.0, + // scale (1,1,1), size 0.5, phi roundness 1.0, and theta roundness 0.0. + static vtkSuperquadric *New(); + + vtkTypeRevisionMacro(vtkSuperquadric,vtkImplicitFunction); + void PrintSelf(ostream& os, vtkIndent indent); + + // ImplicitFunction interface + double EvaluateFunction(double x[3]); + double EvaluateFunction(double x, double y, double z) + {return this->vtkImplicitFunction::EvaluateFunction(x, y, z); } ; + void EvaluateGradient(double x[3], double g[3]); + + // Description: + // Set the center of the superquadric. Default is 0,0,0. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set the scale factors of the superquadric. Default is 1,1,1. + vtkSetVector3Macro(Scale,double); + vtkGetVectorMacro(Scale,double,3); + + // Description: + // Set/Get Superquadric ring thickness (toroids only). + // Changing thickness maintains the outside diameter of the toroid. + vtkGetMacro(Thickness,double); + vtkSetClampMacro(Thickness,double,VTK_MIN_SUPERQUADRIC_THICKNESS,1.0); + + // Description: + // Set/Get Superquadric north/south roundness. + // Values range from 0 (rectangular) to 1 (circular) to higher orders. + vtkGetMacro(PhiRoundness,double); + void SetPhiRoundness(double e); + + // Description: + // Set/Get Superquadric east/west roundness. + // Values range from 0 (rectangular) to 1 (circular) to higher orders. + vtkGetMacro(ThetaRoundness,double); + void SetThetaRoundness(double e); + + // Description: + // Set/Get Superquadric isotropic size. + vtkSetMacro(Size,double); + vtkGetMacro(Size,double); + + // Description: + // Set/Get whether or not the superquadric is toroidal (1) or ellipsoidal (0). + vtkBooleanMacro(Toroidal,int); + vtkGetMacro(Toroidal,int); + vtkSetMacro(Toroidal,int); + +protected: + vtkSuperquadric(); + ~vtkSuperquadric() {}; + + int Toroidal; + double Thickness; + double Size; + double PhiRoundness; + double ThetaRoundness; + double Center[3]; + double Scale[3]; +private: + vtkSuperquadric(const vtkSuperquadric&); // Not implemented. + void operator=(const vtkSuperquadric&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkTetra.cxx b/Filtering/vtkTetra.cxx new file mode 100644 index 0000000..59a2519 --- /dev/null +++ b/Filtering/vtkTetra.cxx @@ -0,0 +1,993 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTetra.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTetra.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkTriangle.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkTetra, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkTetra); + +//---------------------------------------------------------------------------- +// Construct the tetra with four points. +vtkTetra::vtkTetra() +{ + int i; + + this->Points->SetNumberOfPoints(4); + this->PointIds->SetNumberOfIds(4); + for (i = 0; i < 4; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + } + for (i = 0; i < 4; i++) + { + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); + this->Triangle = vtkTriangle::New(); +} + +//---------------------------------------------------------------------------- +vtkTetra::~vtkTetra() +{ + this->Triangle->Delete(); + this->Line->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkTetra::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& minDist2, double *weights) +{ + double pt1[3], pt2[3], pt3[3], pt4[3]; + int i; + double rhs[3], c1[3], c2[3], c3[3]; + double det, p4; + + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + + this->Points->GetPoint(1, pt1); + this->Points->GetPoint(2, pt2); + this->Points->GetPoint(3, pt3); + this->Points->GetPoint(0, pt4); + + for (i=0; i<3; i++) + { + rhs[i] = x[i] - pt4[i]; + c1[i] = pt1[i] - pt4[i]; + c2[i] = pt2[i] - pt4[i]; + c3[i] = pt3[i] - pt4[i]; + } + + if ( (det = vtkMath::Determinant3x3(c1,c2,c3)) == 0.0 ) + { + return -1; + } + + pcoords[0] = vtkMath::Determinant3x3 (rhs,c2,c3) / det; + pcoords[1] = vtkMath::Determinant3x3 (c1,rhs,c3) / det; + pcoords[2] = vtkMath::Determinant3x3 (c1,c2,rhs) / det; + p4 = 1.0 - pcoords[0] - pcoords[1] - pcoords[2]; + + weights[0] = p4; + weights[1] = pcoords[0]; + weights[2] = pcoords[1]; + weights[3] = pcoords[2]; + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 && p4 >= -0.001 && p4 <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; + closestPoint[1] = x[1]; + closestPoint[2] = x[2]; + minDist2 = 0.0; //inside tetra + } + return 1; + } + else + { //could easily be sped up using parametric localization - next release + double dist2, w[3], closest[3], pc[3]; + int sub; + vtkTriangle *triangle; + + if (closestPoint) + { + for (minDist2=VTK_DOUBLE_MAX,i=0; i<4; i++) + { + triangle = (vtkTriangle *) this->GetFace (i); + triangle->EvaluatePosition(x,closest,sub,pc,dist2,(double *)w); + + if ( dist2 < minDist2 ) + { + closestPoint[0] = closest[0]; + closestPoint[1] = closest[1]; + closestPoint[2] = closest[2]; + minDist2 = dist2; + } + } + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkTetra::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + double u4; + double pt1[3], pt2[3], pt3[3], pt4[3]; + int i; + + this->Points->GetPoint(1, pt1); + this->Points->GetPoint(2, pt2); + this->Points->GetPoint(3, pt3); + this->Points->GetPoint(0, pt4); + + u4 = 1.0 - pcoords[0] - pcoords[1] - pcoords[2]; + + for (i=0; i<3; i++) + { + x[i] = pt1[i]*pcoords[0] + pt2[i]*pcoords[1] + pt3[i]*pcoords[2] + + pt4[i]*u4; + } + + weights[0] = u4; + weights[1] = pcoords[0]; + weights[2] = pcoords[1]; + weights[3] = pcoords[2]; +} + +//---------------------------------------------------------------------------- +// Returns the set of points that are on the boundary of the tetrahedron that +// are closest parametrically to the point specified. This may include faces, +// edges, or vertices. +int vtkTetra::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + double minPCoord = 1.0 - pcoords[0] - pcoords[1] - pcoords[2]; + int i, idx=3; + + for ( i=0; i < 3; i++ ) + { + if ( pcoords[i] < minPCoord ) + { + minPCoord = pcoords[i]; + idx = i; + } + } + + pts->SetNumberOfIds(3); + switch (idx) //find the face closest to the point + { + case 0: + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(2)); + pts->SetId(2,this->PointIds->GetId(3)); + break; + + case 1: + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(3)); + break; + + case 2: + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(2)); + break; + + case 3: + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(2)); + pts->SetId(2,this->PointIds->GetId(3)); + break; + } + + if ( pcoords[0] < 0.0 || pcoords[1] < 0.0 || pcoords[2] < 0.0 || + pcoords[0] > 1.0 || pcoords[1] > 1.0 || pcoords[2] > 1.0 || + (1.0 - pcoords[0] - pcoords[1] - pcoords[2]) < 0.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +// Marching tetrahedron +// +static int edges[6][2] = { {0,1}, {1,2}, {2,0}, + {0,3}, {1,3}, {2,3} }; +static int faces[4][3] = { {0,1,3}, {1,2,3}, {2,0,3}, {0,2,1} }; + +typedef int EDGE_LIST; +typedef struct { + EDGE_LIST edges[7]; +} TRIANGLE_CASES; + +static TRIANGLE_CASES triCases[] = { + {{-1, -1, -1, -1, -1, -1, -1}}, + {{ 0, 3, 2, -1, -1, -1, -1}}, + {{ 0, 1, 4, -1, -1, -1, -1}}, + {{ 3, 2, 4, 4, 2, 1, -1}}, + {{ 1, 2, 5, -1, -1, -1, -1}}, + {{ 3, 5, 1, 3, 1, 0, -1}}, + {{ 0, 2, 5, 0, 5, 4, -1}}, + {{ 3, 5, 4, -1, -1, -1, -1}}, + {{ 3, 4, 5, -1, -1, -1, -1}}, + {{ 0, 4, 5, 0, 5, 2, -1}}, + {{ 0, 5, 3, 0, 1, 5, -1}}, + {{ 5, 2, 1, -1, -1, -1, -1}}, + {{ 3, 4, 1, 3, 1, 2, -1}}, + {{ 0, 4, 1, -1, -1, -1, -1}}, + {{ 0, 2, 3, -1, -1, -1, -1}}, + {{-1, -1, -1, -1, -1, -1, -1}} +}; + +//---------------------------------------------------------------------------- +void vtkTetra::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + static int CASE_MASK[4] = {1,2,4,8}; + TRIANGLE_CASES *triCase; + EDGE_LIST *edge; + int i, j, index, *vert, v1, v2, newCellId; + vtkIdType pts[3]; + double t, x1[3], x2[3], x[3], deltaScalar; + vtkIdType offset = verts->GetNumberOfCells() + lines->GetNumberOfCells(); + + // Build the case table + for ( i=0, index = 0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + triCase = triCases + index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (i=0; i<3; i++) // insert triangle + { + vert = edges[edge[i]]; + + // calculate a preferred interpolation direction + deltaScalar = (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + v1 = vert[0]; v2 = vert[1]; + } + else + { + v1 = vert[1]; v2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation across edge + t = ( deltaScalar == 0.0 ? 0.0 : + (value - cellScalars->GetComponent(v1,0)) / deltaScalar ); + + this->Points->GetPoint(v1, x1); + this->Points->GetPoint(v2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + vtkIdType p1 = this->PointIds->GetId(v1); + vtkIdType p2 = this->PointIds->GetId(v2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + + // check for degenerate triangle + if ( pts[0] != pts[1] && pts[0] != pts[2] && pts[1] != pts[2] ) + { + newCellId = offset + polys->InsertNextCell(3,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +int *vtkTetra::GetEdgeArray(int edgeId) +{ + return edges[edgeId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkTetra::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} + +//---------------------------------------------------------------------------- +int *vtkTetra::GetFaceArray(int faceId) +{ + return faces[faceId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkTetra::GetFace(int faceId) +{ + int *verts; + + verts = faces[faceId]; + + // load point id's + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + + // load coordinates + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + + return this->Triangle; +} + +//---------------------------------------------------------------------------- +// +// Intersect triangle faces against line. +// +int vtkTetra::IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId) +{ + int intersection=0; + double pt1[3], pt2[3], pt3[3]; + double tTemp; + double pc[3], xTemp[3]; + int faceNum; + + t = VTK_DOUBLE_MAX; + for (faceNum=0; faceNum<4; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + + this->Triangle->Points->SetPoint(0,pt1); + this->Triangle->Points->SetPoint(1,pt2); + this->Triangle->Points->SetPoint(2,pt3); + + if ( this->Triangle->IntersectWithLine(p1, p2, tol, tTemp, + xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 1: + pcoords[0] = 0.0; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 2: + pcoords[0] = pc[0]; pcoords[1] = 0.0; pcoords[2] = 0.0; + break; + + case 3: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = pc[2]; + break; + } + } + } + } + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkTetra::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, vtkPoints *pts) +{ + ptIds->Reset(); + pts->Reset(); + + for ( int i=0; i < 4; i++ ) + { + ptIds->InsertId(i,this->PointIds->GetId(i)); + pts->InsertPoint(i,this->Points->GetPoint(i)); + } + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkTetra::Derivatives(int vtkNotUsed(subId), double vtkNotUsed(pcoords)[3], + double *values, int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[12], sum[3], value; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 4; i++) //loop over interp. function derivatives + { + value = values[dim*i + k]; + sum[0] += functionDerivs[i] * value; + sum[1] += functionDerivs[4 + i] * value; + sum[2] += functionDerivs[8 + i] * value; + } + + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} + +//---------------------------------------------------------------------------- +// Compute the center of the tetrahedron, +void vtkTetra::TetraCenter(double p1[3], double p2[3], double p3[3], + double p4[3], double center[3]) +{ + center[0] = (p1[0]+p2[0]+p3[0]+p4[0]) / 4.0; + center[1] = (p1[1]+p2[1]+p3[1]+p4[1]) / 4.0; + center[2] = (p1[2]+p2[2]+p3[2]+p4[2]) / 4.0; +} + +//---------------------------------------------------------------------------- +double vtkTetra::ComputeVolume(double p1[3], double p2[3], double p3[3], + double p4[3]) +{ + return (vtkMath::Determinant3x3(p2[0]-p1[0], p3[0]-p1[0], p4[0]-p1[0], + p2[1]-p1[1], p3[1]-p1[1], p4[1]-p1[1], + p2[2]-p1[2], p3[2]-p1[2], p4[2]-p1[2])/6.0); +} + +//---------------------------------------------------------------------------- +// Compute the circumcenter (center[3]) and radius squared (method +// return value) of a tetrahedron defined by the four points x1, x2, +// x3, and x4. +double vtkTetra::Circumsphere(double x1[3], double x2[3], double x3[3], + double x4[3], double center[3]) +{ + double n12[3], n13[3], n14[3], x12[3], x13[3], x14[3]; + double *A[3], rhs[3], sum, diff; + int i; + + // calculate normals and intersection points of bisecting planes. + // + for (i=0; i<3; i++) + { + n12[i] = x2[i] - x1[i]; + n13[i] = x3[i] - x1[i]; + n14[i] = x4[i] - x1[i]; + x12[i] = (x2[i] + x1[i]) / 2.0; + x13[i] = (x3[i] + x1[i]) / 2.0; + x14[i] = (x4[i] + x1[i]) / 2.0; + } + + // Compute solutions to the intersection of two bisecting lines + // (3-eqns. in 3-unknowns). + // + // form system matrices + // + A[0] = n12; + A[1] = n13; + A[2] = n14; + + rhs[0] = vtkMath::Dot(n12,x12); + rhs[1] = vtkMath::Dot(n13,x13); + rhs[2] = vtkMath::Dot(n14,x14); + + // Solve system of equations + // + if ( vtkMath::SolveLinearSystem(A,rhs,3) == 0 ) + { + center[0] = center[1] = center[2] = 0.0; + return VTK_DOUBLE_MAX; + } + else + { + for (i=0; i<3; i++) + { + center[i] = rhs[i]; + } + } + + //determine average value of radius squared + for (sum=0, i=0; i<3; i++) + { + diff = x1[i] - rhs[i]; + sum += diff*diff; + diff = x2[i] - rhs[i]; + sum += diff*diff; + diff = x3[i] - rhs[i]; + sum += diff*diff; + diff = x4[i] - rhs[i]; + sum += diff*diff; + } + + if ( (sum /= 4.0) > VTK_DOUBLE_MAX ) + { + return VTK_DOUBLE_MAX; + } + else + { + return sum; + } +} + +//---------------------------------------------------------------------------- +// Compute the incenter (center[3]) and radius (method return value) of +// a tetrahedron defined by the four points p1, p2, p3, and p4. +double vtkTetra::Insphere(double p1[3], double p2[3], double p3[3], + double p4[3], double center[3]) +{ + double u[3], v[3], w[3]; + double p[3], q[3], r[3]; + double O1[3],O2[3]; + double y[3], s[3], t; + + u[0] = p2[0]-p1[0]; + u[1] = p2[1]-p1[1]; + u[2] = p2[2]-p1[2]; + + v[0] = p3[0]-p1[0]; + v[1] = p3[1]-p1[1]; + v[2] = p3[2]-p1[2]; + + w[0] = p4[0]-p1[0]; + w[1] = p4[1]-p1[1]; + w[2] = p4[2]-p1[2]; + + vtkMath::Cross(u,v,p); + vtkMath::Normalize(p); + + vtkMath::Cross(v,w,q); + vtkMath::Normalize(q); + + vtkMath::Cross(w,u,r); + vtkMath::Normalize(r); + + O1[0] = p[0]-q[0]; + O1[1] = p[1]-q[1]; + O1[2] = p[2]-q[2]; + + O2[0] = q[0]-r[0]; + O2[1] = q[1]-r[1]; + O2[2] = q[2]-r[2]; + + vtkMath::Cross(O1,O2,y); + + O1[0] = u[0]-w[0]; + O1[1] = u[1]-w[1]; + O1[2] = u[2]-w[2]; + + O2[0] = v[0]-w[0]; + O2[1] = v[1]-w[1]; + O2[2] = v[2]-w[2]; + + vtkMath::Cross(O1,O2,s); + vtkMath::Normalize(s); + + s[0] = -1 * s[0]; + s[1] = -1 * s[1]; + s[2] = -1 * s[2]; + + O1[0] = s[0]-p[0]; + O1[1] = s[1]-p[1]; + O1[2] = s[2]-p[2]; + + t = vtkMath::Dot(w,s)/vtkMath::Dot(y,O1); + center[0] = p1[0] + (t * y[0]); + center[1] = p1[1] + (t * y[1]); + center[2] = p1[2] + (t * y[2]); + + return (fabs(t* vtkMath::Dot(y,p))); +} + +//---------------------------------------------------------------------------- +// Given a 3D point x[3], determine the barycentric coordinates of the point. +// Barycentric coordinates are a natural coordinate system for simplices that +// express a position as a linear combination of the vertices. For a +// tetrahedron, there are four barycentric coordinates (because there are +// four vertices), and the sum of the coordinates must equal 1. If a +// point x is inside a simplex, then all four coordinates will be strictly +// positive. If three coordinates are zero (so the fourth =1), then the +// point x is on a vertex. If two coordinates are zero, the point x is on an +// edge (and so on). In this method, you must specify the vertex coordinates +// x1->x4. Returns 0 if tetrahedron is degenerate. +int vtkTetra::BarycentricCoords(double x[3], double x1[3], double x2[3], + double x3[3], double x4[3], double bcoords[4]) +{ + double *A[4], p[4], a1[4], a2[4], a3[4], a4[4]; + int i; + + // Homogenize the variables; load into arrays. + // + a1[0] = x1[0]; a1[1] = x2[0]; a1[2] = x3[0]; a1[3] = x4[0]; + a2[0] = x1[1]; a2[1] = x2[1]; a2[2] = x3[1]; a2[3] = x4[1]; + a3[0] = x1[2]; a3[1] = x2[2]; a3[2] = x3[2]; a3[3] = x4[2]; + a4[0] = 1.0; a4[1] = 1.0; a4[2] = 1.0; a4[3] = 1.0; + p[0] = x[0]; p[1] = x[1]; p[2] = x[2]; p[3] = 1.0; + + // Now solve system of equations for barycentric coordinates + // + A[0] = a1; + A[1] = a2; + A[2] = a3; + A[3] = a4; + + if ( vtkMath::SolveLinearSystem(A,p,4) ) + { + for (i=0; i<4; i++) + { + bcoords[i] = p[i]; + } + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +// +// Compute iso-parametric interpolation functions +// +void vtkTetra::InterpolationFunctions(double pcoords[3], double sf[4]) +{ + sf[0] = 1.0 - pcoords[0] - pcoords[1] - pcoords[2]; + sf[1] = pcoords[0]; + sf[2] = pcoords[1]; + sf[3] = pcoords[2]; +} + +//---------------------------------------------------------------------------- +void vtkTetra::InterpolationDerivs(double derivs[12]) +{ + // r-derivatives + derivs[0] = -1.0; + derivs[1] = 1.0; + derivs[2] = 0.0; + derivs[3] = 0.0; + + // s-derivatives + derivs[4] = -1.0; + derivs[5] = 0.0; + derivs[6] = 1.0; + derivs[7] = 0.0; + + // t-derivatives + derivs[8] = -1.0; + derivs[9] = 0.0; + derivs[10] = 0.0; + derivs[11] = 1.0; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. Returns 0 if no inverse exists. +int vtkTetra::JacobianInverse(double **inverse, double derivs[12]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 4; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[4 + j]; + m2[i] += x[i] * derivs[8 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { +#define VTK_MAX_WARNS 3 + static int numWarns=0; + if ( numWarns++ < VTK_MAX_WARNS ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + vtkErrorMacro(<<"Matrix:" << m[0][0] << " " << m[0][1] << " " << m[0][2] + << m[1][0] << " " << m[1][1] << " " << m[1][2] + << m[2][0] << " " << m[2][1] << " " << m[2][2] ); + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkTetra::GetEdgePoints(int edgeId, int* &pts) +{ + pts = this->GetEdgeArray(edgeId); +} + +//---------------------------------------------------------------------------- +void vtkTetra::GetFacePoints(int faceId, int* &pts) +{ + pts = this->GetFaceArray(faceId); +} + +//---------------------------------------------------------------------------- +// The clip table produces either a single tetrahedron or a single wedge as +// output. The format of the case table is #pts, ptids. Points >= 100 are +// existing vertices; otherwise the number is an edge number requiring that +// an intersection is produced. + +// support tetra clipping +typedef int TETRA_EDGE_LIST; +typedef struct { + TETRA_EDGE_LIST edges[7]; +} TETRA_CASES; + +static TETRA_CASES tetraCases[] = { + {{ 0, 0, 0, 0, 0, 0, 0}}, // 0 + {{ 4, 0, 3, 2, 100, 0, 0}}, // 1 + {{ 4, 0, 1, 4, 101, 0, 0}}, // 2 + {{ 6, 101, 1, 4, 100, 2, 3}}, // 3 + {{ 4, 1, 2, 5, 102, 0, 0}}, // 4 + {{ 6, 102, 5, 1, 100, 3, 0}}, // 5 + {{ 6, 102, 2, 5, 101, 0, 4}}, // 6 + {{ 6, 3, 4, 5, 100, 101, 102}}, // 7 + {{ 4, 3, 4, 5, 103, 0, 0}}, // 8 + {{ 6, 103, 4, 5, 100, 0, 2}}, // 9 + {{ 6, 103, 5, 3, 101, 1, 0}}, // 10 + {{ 6, 100, 101, 103, 2, 1, 5}}, // 11 + {{ 6, 2, 102, 1, 3, 103, 4}}, // 12 + {{ 6, 0, 1, 4, 100, 102, 103}}, // 13 + {{ 6, 0, 3, 2, 101, 103, 102}}, // 14 + {{ 4, 100, 101, 102, 103, 0, 0}} // 15 +}; + +//---------------------------------------------------------------------------- +// Clip this tetra using scalar value provided. Like contouring, except that +// it cuts the tetra to produce other 3D cells (note that this method will +// produce a single tetrahedra or a single wedge). The table has been +// carefully designed to insure that face neighbors--after clipping--are +// remain compatible. +void vtkTetra::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData *outCD, + int insideOut) +{ + static int CASE_MASK[4] = {1,2,4,8}; + TETRA_CASES *tetraCase; + TETRA_EDGE_LIST *edge; + int i, j, index, *vert, newCellId; + vtkIdType pts[6]; + int vertexId; + double t, x1[3], x2[3], x[3]; + + // Build the case table + if ( insideOut ) + { + for ( i=0, index=0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) <= value) + { + index |= CASE_MASK[i]; + } + } + } + else + { + for ( i=0, index=0; i < 4; i++) + { + if (cellScalars->GetComponent(i,0) > value) + { + index |= CASE_MASK[i]; + } + } + } + + // Select the case based on the index and get the list of edges for this case + tetraCase = tetraCases + index; + edge = tetraCase->edges; + + // produce the clipped cell + for (i=1; i<=edge[0]; i++) // insert tetra + { + // vertex exists, and need not be interpolated + if (edge[i] >= 100) + { + vertexId = edge[i] - 100; + this->Points->GetPoint(vertexId, x); + if ( locator->InsertUniquePoint(x, pts[i-1]) ) + { + outPD->CopyData(inPD,this->PointIds->GetId(vertexId),pts[i-1]); + } + } + + else //new vertex, interpolate + { + int v1, v2; + vert = edges[edge[i]]; + + // calculate a preferred interpolation direction + double deltaScalar = (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + v1 = vert[0]; v2 = vert[1]; + } + else + { + v1 = vert[1]; v2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation across edge + t = ( deltaScalar == 0.0 ? 0.0 : + (value - cellScalars->GetComponent(v1,0)) / deltaScalar ); + + this->Points->GetPoint(v1, x1); + this->Points->GetPoint(v2, x2); + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + + if ( locator->InsertUniquePoint(x, pts[i-1]) ) + { + vtkIdType p1 = this->PointIds->GetId(v1); + vtkIdType p2 = this->PointIds->GetId(v2); + outPD->InterpolateEdge(inPD,pts[i-1],p1,p2,t); + } + } + } + + int allDifferent, numUnique=1; + for (i=0; i<(edge[0]-1); i++) + { + for (allDifferent=1, j=i+1; jInsertNextCell(edge[0],pts); + outCD->CopyData(inCD,cellId,newCellId); + } + else if ( edge[0] == 6 && numUnique > 3 ) // check for degenerate wedge + { + newCellId = tets->InsertNextCell(edge[0],pts); + outCD->CopyData(inCD,cellId,newCellId); + } +} + +//---------------------------------------------------------------------------- +static double vtkTetraCellPCoords[12] = {0.0,0.0,0.0, 1.0,0.0,0.0, + 0.0,1.0,0.0, 0.0,0.0,1.0}; + +double *vtkTetra::GetParametricCoords() +{ + return vtkTetraCellPCoords; +} + +//---------------------------------------------------------------------------- +double vtkTetra::GetParametricDistance(double pcoords[3]) +{ + int i; + double pDist, pDistMax=0.0; + double pc[4]; + + pc[0] = pcoords[0]; + pc[1] = pcoords[1]; + pc[2] = pcoords[2]; + pc[3] = 1.0 - pcoords[0] - pcoords[1] - pcoords[2]; + + for (i=0; i<4; i++) + { + if ( pc[i] < 0.0 ) + { + pDist = -pc[i]; + } + else if ( pc[i] > 1.0 ) + { + pDist = pc[i] - 1.0; + } + else //inside the cell in the parametric direction + { + pDist = 0.0; + } + if ( pDist > pDistMax ) + { + pDistMax = pDist; + } + } + + return pDistMax; +} + +//---------------------------------------------------------------------------- +void vtkTetra::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Triangle:\n"; + this->Triangle->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkTetra.h b/Filtering/vtkTetra.h new file mode 100644 index 0000000..7bf9553 --- /dev/null +++ b/Filtering/vtkTetra.h @@ -0,0 +1,165 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTetra.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTetra - a 3D cell that represents a tetrahedron +// .SECTION Description +// vtkTetra is a concrete implementation of vtkCell to represent a 3D +// tetrahedron. vtkTetra uses the standard isoparametric shape functions +// for a linear tetrahedron. The tetrahedron is defined by the four points +// (0-3); where (0,1,2) is the base of the tetrahedron which, using the +// right hand rule, forms a triangle whose normal points in the direction +// of the fourth point. + +// .SECTION See Also +// vtkConvexPointSet vtkHexahedron vtkPyramid vtkVoxel vtkWedge + +#ifndef __vtkTetra_h +#define __vtkTetra_h + +#include "vtkCell3D.h" + +class vtkLine; +class vtkTriangle; +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkTetra : public vtkCell3D +{ +public: + static vtkTetra *New(); + vtkTypeRevisionMacro(vtkTetra,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int edgeId, int* &pts); + virtual void GetFacePoints(int faceId, int* &pts); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_TETRA;} + int GetNumberOfEdges() {return 6;} + int GetNumberOfFaces() {return 4;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *connectivity, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Returns the set of points that are on the boundary of the tetrahedron that + // are closest parametrically to the point specified. This may include faces, + // edges, or vertices. + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + + // Description: + // Return the center of the tetrahedron in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Return the distance of the parametric coordinate provided to the + // cell. If inside the cell, a distance of zero is returned. + double GetParametricDistance(double pcoords[3]); + + // Description: + // Compute the center of the tetrahedron, + static void TetraCenter(double p1[3], double p2[3], double p3[3], double p4[3], + double center[3]); + + // Description: + // Compute the circumcenter (center[3]) and radius squared (method + // return value) of a tetrahedron defined by the four points x1, x2, + // x3, and x4. + static double Circumsphere(double p1[3], double p2[3], double p3[3], + double p4[3], double center[3]); + + // Description: + // Compute the center (center[3]) and radius (method return value) of + // a sphere that just fits inside the faces of a tetrahedron defined + // by the four points x1, x2, x3, and x4. + static double Insphere(double p1[3], double p2[3], double p3[3], + double p4[3], double center[3]); + + // Description: + // Given a 3D point x[3], determine the barycentric coordinates of the point. + // Barycentric coordinates are a natural coordinate system for simplices that + // express a position as a linear combination of the vertices. For a + // tetrahedron, there are four barycentric coordinates (because there are + // four vertices), and the sum of the coordinates must equal 1. If a + // point x is inside a simplex, then all four coordinates will be strictly + // positive. If three coordinates are zero (so the fourth =1), then the + // point x is on a vertex. If two coordinates are zero, the point x is on an + // edge (and so on). In this method, you must specify the vertex coordinates + // x1->x4. Returns 0 if tetrahedron is degenerate. + static int BarycentricCoords(double x[3], double x1[3], double x2[3], + double x3[3], double x4[3], double bcoords[4]); + + // Description: + // Compute the volume of a tetrahedron defined by the four points + // p1, p2, p3, and p4. + static double ComputeVolume(double p1[3], double p2[3], double p3[3], + double p4[3]); + + // Description: + // Given parametric coordinates compute inverse Jacobian transformation + // matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation + // function derivatives. Returns 0 if no inverse exists. + int JacobianInverse(double **inverse, double derivs[12]); + + // Description: + // Tetra specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[4]); + static void InterpolationDerivs(double derivs[12]); + static int *GetEdgeArray(int edgeId); + static int *GetFaceArray(int faceId); + +protected: + vtkTetra(); + ~vtkTetra(); + + vtkLine *Line; + vtkTriangle *Triangle; + +private: + vtkTetra(const vtkTetra&); // Not implemented. + void operator=(const vtkTetra&); // Not implemented. +}; + +inline int vtkTetra::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = pcoords[2] = 0.25; + return 0; +} + +#endif + + + diff --git a/Filtering/vtkThreadedImageAlgorithm.cxx b/Filtering/vtkThreadedImageAlgorithm.cxx new file mode 100644 index 0000000..0c571c2 --- /dev/null +++ b/Filtering/vtkThreadedImageAlgorithm.cxx @@ -0,0 +1,341 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThreadedImageAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkThreadedImageAlgorithm.h" + +#include "vtkCellData.h" +#include "vtkCommand.h" +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkThreadedImageAlgorithm, "$Revision: 1.11 $"); + +//---------------------------------------------------------------------------- +vtkThreadedImageAlgorithm::vtkThreadedImageAlgorithm() +{ + this->Threader = vtkMultiThreader::New(); + this->NumberOfThreads = this->Threader->GetNumberOfThreads(); +} + +//---------------------------------------------------------------------------- +vtkThreadedImageAlgorithm::~vtkThreadedImageAlgorithm() +{ + this->Threader->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkThreadedImageAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfThreads: " << this->NumberOfThreads << "\n"; +} + +struct vtkImageThreadStruct +{ + vtkThreadedImageAlgorithm *Filter; + vtkInformation *Request; + vtkInformationVector **InputsInfo; + vtkInformationVector *OutputsInfo; + vtkImageData ***Inputs; + vtkImageData **Outputs; +}; + +//---------------------------------------------------------------------------- +// For streaming and threads. Splits output update extent into num pieces. +// This method needs to be called num times. Results must not overlap for +// consistent starting extent. Subclass can override this method. +// This method returns the number of peices resulting from a successful split. +// This can be from 1 to "total". +// If 1 is returned, the extent cannot be split. +int vtkThreadedImageAlgorithm::SplitExtent(int splitExt[6], + int startExt[6], + int num, int total) +{ + int splitAxis; + int min, max; + + vtkDebugMacro("SplitExtent: ( " << startExt[0] << ", " << startExt[1] << ", " + << startExt[2] << ", " << startExt[3] << ", " + << startExt[4] << ", " << startExt[5] << "), " + << num << " of " << total); + + // start with same extent + memcpy(splitExt, startExt, 6 * sizeof(int)); + + splitAxis = 2; + min = startExt[4]; + max = startExt[5]; + while (min >= max) + { + // empty extent so cannot split + if (min > max) + { + return 1; + } + --splitAxis; + if (splitAxis < 0) + { // cannot split + vtkDebugMacro(" Cannot Split"); + return 1; + } + min = startExt[splitAxis*2]; + max = startExt[splitAxis*2+1]; + } + + // determine the actual number of pieces that will be generated + int range = max - min + 1; + int valuesPerThread = (int)ceil(range/(double)total); + int maxThreadIdUsed = (int)ceil(range/(double)valuesPerThread) - 1; + if (num < maxThreadIdUsed) + { + splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; + splitExt[splitAxis*2+1] = splitExt[splitAxis*2] + valuesPerThread - 1; + } + if (num == maxThreadIdUsed) + { + splitExt[splitAxis*2] = splitExt[splitAxis*2] + num*valuesPerThread; + } + + vtkDebugMacro(" Split Piece: ( " <ThreadID; + threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + + str = (vtkImageThreadStruct *) + (((vtkMultiThreader::ThreadInfo *)(arg))->UserData); + + // if we have an output + if (str->Filter->GetNumberOfOutputPorts()) + { + // which output port did the request come from + int outputPort = + str->Request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, for now an error + if (outputPort == -1) + { + return VTK_THREAD_RETURN_VALUE; + } + + // get the update extent from the output port + vtkInformation *outInfo = + str->OutputsInfo->GetInformationObject(outputPort); + int updateExtent[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + updateExtent); + memcpy(ext,updateExtent, sizeof(int)*6); + } + else + { + // if there is no output, then use UE from input, use the first input + int inPort; + for (inPort = 0; inPort < str->Filter->GetNumberOfInputPorts(); ++inPort) + { + if (str->Filter->GetNumberOfInputConnections(inPort)) + { + int updateExtent[6]; + str->InputsInfo[inPort] + ->GetInformationObject(0) + ->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + updateExtent); + memcpy(ext,updateExtent, sizeof(int)*6); + break; + } + } + if (inPort >= str->Filter->GetNumberOfInputPorts()) + { + return VTK_THREAD_RETURN_VALUE; + } + } + + // execute the actual method with appropriate extent + // first find out how many pieces extent can be split into. + total = str->Filter->SplitExtent(splitExt, ext, threadId, threadCount); + + if (threadId < total) + { + // return if nothing to do + if (splitExt[1] < splitExt[0] || + splitExt[3] < splitExt[2] || + splitExt[5] < splitExt[4]) + { + return VTK_THREAD_RETURN_VALUE; + } + str->Filter->ThreadedRequestData(str->Request, + str->InputsInfo, str->OutputsInfo, + str->Inputs, str->Outputs, + splitExt, threadId); + } + // else + // { + // otherwise don't use this thread. Sometimes the threads dont + // break up very well and it is just as efficient to leave a + // few threads idle. + // } + + return VTK_THREAD_RETURN_VALUE; +} + + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkThreadedImageAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + int i; + + // setup the threasd structure + vtkImageThreadStruct str; + str.Filter = this; + str.Request = request; + str.InputsInfo = inputVector; + str.OutputsInfo = outputVector; + + // now we must create the output array + str.Outputs = 0; + if (this->GetNumberOfOutputPorts()) + { + str.Outputs = new vtkImageData * [this->GetNumberOfOutputPorts()]; + for (i = 0; i < this->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* info = outputVector->GetInformationObject(i); + vtkImageData *outData = static_cast( + info->Get(vtkDataObject::DATA_OBJECT())); + str.Outputs[i] = outData; + + int updateExtent[6]; + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + updateExtent); + + // for image filters as a convenience we usually allocate the output data + // in the superclass + this->AllocateOutputData(outData, updateExtent); + } + } + + // now create the inputs array + str.Inputs = 0; + if (this->GetNumberOfInputPorts()) + { + str.Inputs = new vtkImageData ** [this->GetNumberOfInputPorts()]; + for (i = 0; i < this->GetNumberOfInputPorts(); ++i) + { + str.Inputs[i] = 0; + vtkInformationVector* portInfo = inputVector[i]; + + if (portInfo->GetNumberOfInformationObjects()) + { + int j; + str.Inputs[i] = + new vtkImageData *[portInfo->GetNumberOfInformationObjects()]; + for (j = 0; j < portInfo->GetNumberOfInformationObjects(); ++j) + { + vtkInformation* info = portInfo->GetInformationObject(j); + str.Inputs[i][j] = + static_cast(info->Get(vtkDataObject::DATA_OBJECT())); + } + } + } + } + + // copy other arrays + if (str.Inputs && str.Inputs[0] && str.Outputs) + { + this->CopyAttributeData(str.Inputs[0][0],str.Outputs[0],inputVector); + } + + this->Threader->SetNumberOfThreads(this->NumberOfThreads); + this->Threader->SetSingleMethod(vtkThreadedImageAlgorithmThreadedExecute, &str); + + // always shut off debugging to avoid threading problems with GetMacros + int debug = this->Debug; + this->Debug = 0; + this->Threader->SingleMethodExecute(); + this->Debug = debug; + + // free up the arrays + for (i = 0; i < this->GetNumberOfInputPorts(); ++i) + { + if (str.Inputs[i]) + { + delete [] str.Inputs[i]; + } + } + // note the check isn't required by C++ standard but due to bad compilers + if (str.Inputs) + { + delete [] str.Inputs; + } + if (str.Outputs) + { + delete [] str.Outputs; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkThreadedImageAlgorithm::ThreadedRequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], + int threadId) +{ + this->ThreadedExecute(inData[0][0], outData[0], extent, threadId); +} + +//---------------------------------------------------------------------------- +// The execute method created by the subclass. +void vtkThreadedImageAlgorithm::ThreadedExecute( + vtkImageData *vtkNotUsed(inData), + vtkImageData *vtkNotUsed(outData), + int extent[6], + int vtkNotUsed(threadId)) +{ + extent = extent; + vtkErrorMacro("Subclass should override this method!!!"); +} + diff --git a/Filtering/vtkThreadedImageAlgorithm.h b/Filtering/vtkThreadedImageAlgorithm.h new file mode 100644 index 0000000..7ac8ade --- /dev/null +++ b/Filtering/vtkThreadedImageAlgorithm.h @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThreadedImageAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageToImageAlgorithm - Generic filter that has one input.. +// .SECTION Description +// vtkImageToImageAlgorithm is a filter superclass that hides much of the +// pipeline complexity. It handles breaking the pipeline execution +// into smaller extents so that the vtkImageData limits are observed. It +// also provides support for multithreading. If you don't need any of this +// functionality, consider using vtkSimpleImageToImageAlgorithm instead. +// .SECTION See also +// vtkSimpleImageToImageAlgorithm + +#ifndef __vtkThreadedImageAlgorithm_h +#define __vtkThreadedImageAlgorithm_h + +#include "vtkImageAlgorithm.h" + +class vtkImageData; +class vtkMultiThreader; + +class VTK_FILTERING_EXPORT vtkThreadedImageAlgorithm : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkThreadedImageAlgorithm,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // If the subclass does not define an Execute method, then the task + // will be broken up, multiple threads will be spawned, and each thread + // will call this method. It is public so that the thread functions + // can call this method. + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + + // also support the old signature + virtual void ThreadedExecute(vtkImageData *inData, + vtkImageData *outData, + int extent[6], int threadId); + + // Description: + // Get/Set the number of threads to create when rendering + vtkSetClampMacro( NumberOfThreads, int, 1, VTK_MAX_THREADS ); + vtkGetMacro( NumberOfThreads, int ); + + // Description: + // Putting this here until I merge graphics and imaging streaming. + virtual int SplitExtent(int splitExt[6], int startExt[6], + int num, int total); + +protected: + vtkThreadedImageAlgorithm(); + ~vtkThreadedImageAlgorithm(); + + vtkMultiThreader *Threader; + int NumberOfThreads; + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +private: + vtkThreadedImageAlgorithm(const vtkThreadedImageAlgorithm&); // Not implemented. + void operator=(const vtkThreadedImageAlgorithm&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkTriangle.cxx b/Filtering/vtkTriangle.cxx new file mode 100644 index 0000000..6953922 --- /dev/null +++ b/Filtering/vtkTriangle.cxx @@ -0,0 +1,1096 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangle.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTriangle.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" +#include "vtkPolygon.h" +#include "vtkQuadric.h" + +vtkCxxRevisionMacro(vtkTriangle, "$Revision: 1.4.10.1 $"); +vtkStandardNewMacro(vtkTriangle); + +//---------------------------------------------------------------------------- +// Construct the triangle with three points. +vtkTriangle::vtkTriangle() +{ + this->Points->SetNumberOfPoints(3); + this->PointIds->SetNumberOfIds(3); + for (int i = 0; i < 3; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); +} + +//---------------------------------------------------------------------------- +vtkTriangle::~vtkTriangle() +{ + this->Line->Delete(); +} + + +//---------------------------------------------------------------------------- +// Create a new cell and copy this triangle's information into the cell. +// Returns a poiner to the new cell created. +int vtkTriangle::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int i, j; + double pt1[3], pt2[3], pt3[3], n[3], fabsn; + double rhs[2], c1[2], c2[2]; + double det; + double maxComponent; + int idx=0, indices[2]; + double dist2Point, dist2Line1, dist2Line2; + double *closest, closestPoint1[3], closestPoint2[3], cp[3]; + + subId = 0; + + // Get normal for triangle, only the normal direction is needed, i.e. the + // normal need not be normalized (unit length) + // + this->Points->GetPoint(1, pt1); + this->Points->GetPoint(2, pt2); + this->Points->GetPoint(0, pt3); + + vtkTriangle::ComputeNormalDirection(pt1, pt2, pt3, n); + + // Project point to plane + // + vtkPlane::GeneralizedProjectPoint(x,pt1,n,cp); + + // Construct matrices. Since we have over determined system, need to find + // which 2 out of 3 equations to use to develop equations. (Any 2 should + // work since we've projected point to plane.) + // + for (maxComponent=0.0, i=0; i<3; i++) + { + // trying to avoid an expensive call to fabs() + if (n[i] < 0) + { + fabsn = -n[i]; + } + else + { + fabsn = n[i]; + } + if (fabsn > maxComponent) + { + maxComponent = fabsn; + idx = i; + } + } + for (j=0, i=0; i<3; i++) + { + if ( i != idx ) + { + indices[j++] = i; + } + } + + for (i=0; i<2; i++) + { + rhs[i] = cp[indices[i]] - pt3[indices[i]]; + c1[i] = pt1[indices[i]] - pt3[indices[i]]; + c2[i] = pt2[indices[i]] - pt3[indices[i]]; + } + + if ( (det = vtkMath::Determinant2x2(c1,c2)) == 0.0 ) + { + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + return -1; + } + + pcoords[0] = vtkMath::Determinant2x2(rhs,c2) / det; + pcoords[1] = vtkMath::Determinant2x2(c1,rhs) / det; + pcoords[2] = 1.0 - (pcoords[0] + pcoords[1]); + + // Okay, now find closest point to element + // + weights[0] = pcoords[2]; + weights[1] = pcoords[0]; + weights[2] = pcoords[1]; + + if ( pcoords[0] >= 0.0 && pcoords[0] <= 1.0 && + pcoords[1] >= 0.0 && pcoords[1] <= 1.0 && + pcoords[2] >= 0.0 && pcoords[2] <= 1.0 ) + { + //projection distance + if (closestPoint) + { + dist2 = vtkMath::Distance2BetweenPoints(cp,x); + closestPoint[0] = cp[0]; + closestPoint[1] = cp[1]; + closestPoint[2] = cp[2]; + } + return 1; + } + else + { + double t; + if (closestPoint) + { + if ( pcoords[0] < 0.0 && pcoords[1] < 0.0 ) + { + dist2Point = vtkMath::Distance2BetweenPoints(x,pt3); + dist2Line1 = vtkLine::DistanceToLine(x,pt1,pt3,t,closestPoint1); + dist2Line2 = vtkLine::DistanceToLine(x,pt3,pt2,t,closestPoint2); + if (dist2Point < dist2Line1) + { + dist2 = dist2Point; + closest = pt3; + } + else + { + dist2 = dist2Line1; + closest = closestPoint1; + } + if (dist2Line2 < dist2) + { + dist2 = dist2Line2; + closest = closestPoint2; + } + for (i=0; i<3; i++) + { + closestPoint[i] = closest[i]; + } + } + else if ( pcoords[1] < 0.0 && pcoords[2] < 0.0 ) + { + dist2Point = vtkMath::Distance2BetweenPoints(x,pt1); + dist2Line1 = vtkLine::DistanceToLine(x,pt1,pt3,t,closestPoint1); + dist2Line2 = vtkLine::DistanceToLine(x,pt1,pt2,t,closestPoint2); + if (dist2Point < dist2Line1) + { + dist2 = dist2Point; + closest = pt1; + } + else + { + dist2 = dist2Line1; + closest = closestPoint1; + } + if (dist2Line2 < dist2) + { + dist2 = dist2Line2; + closest = closestPoint2; + } + for (i=0; i<3; i++) + { + closestPoint[i] = closest[i]; + } + } + else if ( pcoords[0] < 0.0 && pcoords[2] < 0.0 ) + { + dist2Point = vtkMath::Distance2BetweenPoints(x,pt2); + dist2Line1 = vtkLine::DistanceToLine(x,pt2,pt3,t,closestPoint1); + dist2Line2 = vtkLine::DistanceToLine(x,pt1,pt2,t,closestPoint2); + if (dist2Point < dist2Line1) + { + dist2 = dist2Point; + closest = pt2; + } + else + { + dist2 = dist2Line1; + closest = closestPoint1; + } + if (dist2Line2 < dist2) + { + dist2 = dist2Line2; + closest = closestPoint2; + } + for (i=0; i<3; i++) + { + closestPoint[i] = closest[i]; + } + } + else if ( pcoords[0] < 0.0 ) + { + dist2 = vtkLine::DistanceToLine(x,pt2,pt3,t,closestPoint); + } + else if ( pcoords[1] < 0.0 ) + { + dist2 = vtkLine::DistanceToLine(x,pt1,pt3,t,closestPoint); + } + else if ( pcoords[2] < 0.0 ) + { + dist2 = vtkLine::DistanceToLine(x,pt1,pt2,t,closestPoint); + } + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkTriangle::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + double u3; + double pt0[3], pt1[3], pt2[3]; + int i; + + this->Points->GetPoint(0, pt0); + this->Points->GetPoint(1, pt1); + this->Points->GetPoint(2, pt2); + + u3 = 1.0 - pcoords[0] - pcoords[1]; + + for (i=0; i<3; i++) + { + x[i] = pt0[i]*u3 + pt1[i]*pcoords[0] + pt2[i]*pcoords[1]; + } + + weights[0] = u3; + weights[1] = pcoords[0]; + weights[2] = pcoords[1]; +} + +//---------------------------------------------------------------------------- +// Compute iso-parametric interpolation functions +// +void vtkTriangle::InterpolationFunctions(double pcoords[3], double sf[3]) +{ + sf[0] = 1. - pcoords[0] - pcoords[1]; + sf[1] = pcoords[0]; + sf[2] = pcoords[1]; +} + +//---------------------------------------------------------------------------- +void vtkTriangle::InterpolationDerivs(double *, double derivs[6]) +{ + //r-derivatives + derivs[0] = -1; + derivs[1] = 1; + derivs[2] = 0; + + //s-derivatives + derivs[3] = -1; + derivs[4] = 0; + derivs[5] = 1; +} + +//---------------------------------------------------------------------------- +int vtkTriangle::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + double t1=pcoords[0]-pcoords[1]; + double t2=0.5*(1.0-pcoords[0])-pcoords[1]; + double t3=2.0*pcoords[0]+pcoords[1]-1.0; + + pts->SetNumberOfIds(2); + + // compare against three lines in parametric space that divide element + // into three pieces + if ( t1 >= 0.0 && t2 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + } + + else if ( t2 < 0.0 && t3 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(2)); + } + + else //( t1 < 0.0 && t3 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(2)); + pts->SetId(1,this->PointIds->GetId(0)); + } + + if ( pcoords[0] < 0.0 || pcoords[1] < 0.0 || + pcoords[0] > 1.0 || pcoords[1] > 1.0 || + (1.0 - pcoords[0] - pcoords[1]) < 0.0 ) + { + return 0; + } + else + { + return 1; + } + +} + +//---------------------------------------------------------------------------- +// +// Marching triangles +// +typedef int EDGE_LIST; +typedef struct { + EDGE_LIST edges[3]; +} LINE_CASES; + +static LINE_CASES lineCases[] = { + {{-1, -1, -1}}, + {{0, 2, -1}}, + {{1, 0, -1}}, + {{1, 2, -1}}, + {{2, 1, -1}}, + {{0, 1, -1}}, + {{2, 0, -1}}, + {{-1, -1, -1}} +}; + +static int edges[3][2] = { {0,1}, {1,2}, {2,0} }; + +//---------------------------------------------------------------------------- +void vtkTriangle::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *vtkNotUsed(polys), + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + static int CASE_MASK[3] = {1,2,4}; + LINE_CASES *lineCase; + EDGE_LIST *edge; + int i, j, index, *vert; + vtkIdType pts[2]; + int e1, e2, newCellId; + double t, x1[3], x2[3], x[3], deltaScalar; + vtkIdType offset = verts->GetNumberOfCells(); + + // Build the case table + for ( i=0, index = 0; i < 3; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + lineCase = lineCases + index; + edge = lineCase->edges; + + for ( ; edge[0] > -1; edge += 2 ) + { + for (i=0; i<2; i++) // insert line + { + vert = edges[edge[i]]; + // calculate a preferred interpolation direction + deltaScalar = (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + e1 = vert[0]; e2 = vert[1]; + } + else + { + e1 = vert[1]; e2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + if (deltaScalar == 0.0) + { + t = 0.0; + } + else + { + t = (value - cellScalars->GetComponent(e1,0)) / deltaScalar; + } + + this->Points->GetPoint(e1, x1); + this->Points->GetPoint(e2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + vtkIdType p1 = this->PointIds->GetId(e1); + vtkIdType p2 = this->PointIds->GetId(e2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate line + if ( pts[0] != pts[1] ) + { + newCellId = offset + lines->InsertNextCell(2,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +// Get the edge specified by edgeId (range 0 to 2) and return that edge's +// coordinates. +vtkCell *vtkTriangle::GetEdge(int edgeId) +{ + int edgeIdPlus1 = (edgeId > 1 ? 0 : (edgeId+1) ); + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(edgeId)); + this->Line->PointIds->SetId(1,this->PointIds->GetId(edgeIdPlus1)); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(edgeId)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(edgeIdPlus1)); + + return this->Line; +} + +//---------------------------------------------------------------------------- +// Plane intersection plus in/out test on triangle. The in/out test is +// performed using tol as the tolerance. +int vtkTriangle::IntersectWithLine(double p1[3], double p2[3], double tol, + double& t, double x[3], double pcoords[3], + int& subId) +{ + double pt1[3], pt2[3], pt3[3], n[3]; + double tol2 = tol*tol; + double closestPoint[3]; + double dist2, weights[3]; + + subId = 0; + + // Get normal for triangle + // + this->Points->GetPoint(1, pt1); + this->Points->GetPoint(2, pt2); + this->Points->GetPoint(0, pt3); + + vtkTriangle::ComputeNormal (pt1, pt2, pt3, n); + + // Intersect plane of triangle with line + // + if ( ! vtkPlane::IntersectWithLine(p1,p2,n,pt1,t,x) ) + { + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + return 0; + } + + // Evaluate position + // + int inside; + if ( (inside = this->EvaluatePosition(x, closestPoint, subId, pcoords, + dist2, weights)) >= 0) + { + if ( dist2 <= tol2 ) + { + pcoords[2] = 0.0; + return 1; + } + return inside; + } + + // so the easy test failed. The line is not intersecting the triangle. + // Let's now do the 3d case check to see how close the line comes. + // basically we just need to test against the three lines of the triangle + this->Line->PointIds->InsertId(0,0); + this->Line->PointIds->InsertId(1,1); + + if (pcoords[2] < 0.0) + { + this->Line->Points->InsertPoint(0,pt1); + this->Line->Points->InsertPoint(1,pt2); + if (this->Line->IntersectWithLine(p1,p2,tol,t,x,pcoords,subId)) + { + pcoords[2] = 0.0; + return 1; + } + } + + if (pcoords[0] < 0.0) + { + this->Line->Points->InsertPoint(0,pt2); + this->Line->Points->InsertPoint(1,pt3); + if (this->Line->IntersectWithLine(p1,p2,tol,t,x,pcoords,subId)) + { + pcoords[2] = 0.0; + return 1; + } + } + + if (pcoords[1] < 0.0) + { + this->Line->Points->InsertPoint(0,pt3); + this->Line->Points->InsertPoint(1,pt1); + if (this->Line->IntersectWithLine(p1,p2,tol,t,x,pcoords,subId)) + { + pcoords[2] = 0.0; + return 1; + } + } + + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + return 0; +} + +//---------------------------------------------------------------------------- +int vtkTriangle::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + + for ( int i=0; i < 3; i++ ) + { + ptIds->InsertId(i,this->PointIds->GetId(i)); + pts->InsertPoint(i,this->Points->GetPoint(i)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Used a staged computation: first compute derivatives in local x'-y' +// coordinate system; then convert into x-y-z modelling system. +void vtkTriangle::Derivatives(int vtkNotUsed(subId), double vtkNotUsed(pcoords)[3], + double *values, int dim, double *derivs) +{ + double v0[2], v1[2], v2[2], v[3], v10[3], v20[3], lenX; + double x0[3], x1[3], x2[3], n[3]; + double *J[2], J0[2], J1[2]; + double *JI[2], JI0[2], JI1[2]; + double functionDerivs[6], sum[2], dBydx, dBydy; + int i, j; + + // Project points of triangle into 2D system + this->Points->GetPoint(0, x0); + this->Points->GetPoint(1, x1); + this->Points->GetPoint(2, x2); + vtkTriangle::ComputeNormal (x0, x1, x2, n); + + for (i=0; i < 3; i++) + { + v10[i] = x1[i] - x0[i]; + v[i] = x2[i] - x0[i]; + } + + vtkMath::Cross(n,v10,v20); //creates local y' axis + + if ( (lenX=vtkMath::Normalize(v10)) <= 0.0 + || vtkMath::Normalize(v20) <= 0.0 ) //degenerate + { + for ( j=0; j < dim; j++ ) + { + for ( i=0; i < 3; i++ ) + { + derivs[j*dim + i] = 0.0; + } + } + return; + } + + v0[0] = v0[1] = 0.0; //convert points to 2D (i.e., local system) + v1[0] = lenX; v1[1] = 0.0; + v2[0] = vtkMath::Dot(v,v10); + v2[1] = vtkMath::Dot(v,v20); + + // Compute interpolation function derivatives + vtkTriangle::InterpolationDerivs(NULL,functionDerivs); + + // Compute Jacobian: Jacobian is constant for a triangle. + J[0] = J0; J[1] = J1; + JI[0] = JI0; JI[1] = JI1; + + J[0][0] = v1[0] - v0[0]; + J[1][0] = v2[0] - v0[0]; + J[0][1] = v1[1] - v0[1]; + J[1][1] = v2[1] - v0[1]; + + // Compute inverse Jacobian + vtkMath::InvertMatrix(J,JI,2); + + // Loop over "dim" derivative values. For each set of values, compute + // derivatives in local system and then transform into modelling system. + // First compute derivatives in local x'-y' coordinate system + for ( j=0; j < dim; j++ ) + { + sum[0] = sum[1] = 0.0; + for ( i=0; i < 3; i++) //loop over interp. function derivatives + { + sum[0] += functionDerivs[i] * values[dim*i + j]; + sum[1] += functionDerivs[3 + i] * values[dim*i + j]; + } + dBydx = sum[0]*JI[0][0] + sum[1]*JI[0][1]; + dBydy = sum[0]*JI[1][0] + sum[1]*JI[1][1]; + + // Transform into global system (dot product with global axes) + derivs[3*j] = dBydx * v10[0] + dBydy * v20[0]; + derivs[3*j + 1] = dBydx * v10[1] + dBydy * v20[1]; + derivs[3*j + 2] = dBydx * v10[2] + dBydy * v20[2]; + } +} + +//---------------------------------------------------------------------------- +// Compute the triangle normal from a points list, and a list of point ids +// that index into the points list. +void vtkTriangle::ComputeNormal(vtkPoints *p, int vtkNotUsed(numPts), + vtkIdType *pts, double n[3]) +{ + double v1[3], v2[3], v3[3]; + + p->GetPoint(pts[0],v1); + p->GetPoint(pts[1],v2); + p->GetPoint(pts[2],v3); + + vtkTriangle::ComputeNormal(v1,v2,v3,n); +} + +//---------------------------------------------------------------------------- +// Compute the circumcenter (center[3]) and radius squared (method +// return value) of a triangle defined by the three points x1, x2, and +// x3. (Note that the coordinates are 2D. 3D points can be used but +// the z-component will be ignored.) +double vtkTriangle::Circumcircle(double x1[2], double x2[2], double x3[2], + double center[2]) +{ + double n12[2], n13[2], x12[2], x13[2]; + double *A[2], rhs[2], sum, diff; + int i; + + // calculate normals and intersection points of bisecting planes. + // + for (i=0; i<2; i++) + { + n12[i] = x2[i] - x1[i]; + n13[i] = x3[i] - x1[i]; + x12[i] = (x2[i] + x1[i])/2.0; + x13[i] = (x3[i] + x1[i])/2.0; + } + + // Compute solutions to the intersection of two bisecting lines + // (2-eqns. in 2-unknowns). + // + // form system matrices + // + A[0] = n12; + A[1] = n13; + + rhs[0] = vtkMath::Dot2D(n12,x12); + rhs[1] = vtkMath::Dot2D(n13,x13); + + // Solve system of equations + // + if ( vtkMath::SolveLinearSystem(A,rhs,2) == 0 ) + { + center[0] = center[1] = 0.0; + return VTK_DOUBLE_MAX; + } + else + { + center[0] = rhs[0]; center[1] = rhs[1]; + } + + //determine average value of radius squared + for (sum=0, i=0; i<2; i++) + { + diff = x1[i] - center[i]; + sum += diff*diff; + diff = x2[i] - center[i]; + sum += diff*diff; + diff = x3[i] - center[i]; + sum += diff*diff; + } + + if ( (sum /= 3.0) > VTK_DOUBLE_MAX ) + { + return VTK_DOUBLE_MAX; + } + else + { + return sum; + } +} + +//---------------------------------------------------------------------------- +// Given a 2D point x[2], determine the barycentric coordinates of the point. +// Barycentric coordinates are a natural coordinate system for simplices that +// express a position as a linear combination of the vertices. For a +// triangle, there are three barycentric coordinates (because there are +// fourthree vertices), and the sum of the coordinates must equal 1. If a +// point x is inside a simplex, then all three coordinates will be strictly +// positive. If two coordinates are zero (so the third =1), then the +// point x is on a vertex. If one coordinates are zero, the point x is on an +// edge. In this method, you must specify the vertex coordinates x1->x3. +// Returns 0 if triangle is degenerate. +int vtkTriangle::BarycentricCoords(double x[2], double x1[2], double x2[2], + double x3[2], double bcoords[3]) +{ + double *A[3], p[3], a1[3], a2[3], a3[3]; + int i; + + // Homogenize the variables; load into arrays. + // + a1[0] = x1[0]; a1[1] = x2[0]; a1[2] = x3[0]; + a2[0] = x1[1]; a2[1] = x2[1]; a2[2] = x3[1]; + a3[0] = 1.0; a3[1] = 1.0; a3[2] = 1.0; + p[0] = x[0]; p[1] = x[1]; p[2] = 1.0; + + // Now solve system of equations for barycentric coordinates + // + A[0] = a1; + A[1] = a2; + A[2] = a3; + + if ( vtkMath::SolveLinearSystem(A,p,3) ) + { + for (i=0; i<3; i++) + { + bcoords[i] = p[i]; + } + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +// Project triangle defined in 3D to 2D coordinates. Returns 0 if degenerate +// triangle; non-zero value otherwise. Input points are x1->x3; output 2D +// points are v1->v3. +int vtkTriangle::ProjectTo2D(double x1[3], double x2[3], double x3[3], + double v1[2], double v2[2], double v3[2]) +{ + double n[3], v21[3], v31[3], v[3], xLen; + + // Get normal for triangle + vtkTriangle::ComputeNormal (x1, x2, x3, n); + + for (int i=0; i < 3; i++) + { + v21[i] = x2[i] - x1[i]; + v31[i] = x3[i] - x1[i]; + } + + if ( (xLen=vtkMath::Normalize(v21)) <= 0.0 ) + { + return 0; + } + + // The first point is at (0,0); the next at (xLen,0); compute the other + // point relative to the first two. + v1[0] = v1[1] = 0.0; + v2[0] = xLen; v2[1] = 0.0; + + vtkMath::Cross(n,v21,v); + + v3[0] = vtkMath::Dot(v31,v21); + v3[1] = vtkMath::Dot(v31,v); + + return 1; +} + +//---------------------------------------------------------------------------- +// Support triangle clipping. Note that the table defines triangles (three ids +// at a time define a triangle, -1 ends the list). Numbers in the list >= 100 +// correspond to already existing vertices; otherwise the numbers refer to edge +// ids. +typedef int TRIANGLE_EDGE_LIST; +typedef struct { + TRIANGLE_EDGE_LIST edges[7]; +} TRIANGLE_CASES; + +static TRIANGLE_CASES triangleCases[] = { +{{-1, -1, -1, -1, -1, -1, -1}}, // 0 +{{0, 2, 100, -1, -1, -1, -1}}, // 1 +{{1, 0, 101, -1, -1, -1, -1}}, // 2 +{{1, 2, 100, 1, 100, 101, -1}}, // 3 +{{2, 1, 102, -1, -1, -1, -1}}, // 4 +{{0, 1, 102, 102, 100, 0, -1}}, // 5 +{{0, 101, 2, 2, 101, 102, -1}}, // 6 +{{100, 101, 102, -1, -1, -1, -1}} // 7 +}; + +//---------------------------------------------------------------------------- +// Clip this triangle using scalar value provided. Like contouring, except +// that it cuts the triangle to produce other triangles. +void vtkTriangle::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tris, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut) +{ + static int CASE_MASK[3] = {1,2,4}; + TRIANGLE_CASES *triangleCase; + TRIANGLE_EDGE_LIST *edge; + int i, j, index, *vert; + int e1, e2, newCellId; + vtkIdType pts[3]; + int vertexId; + double t, x1[3], x2[3], x[3], deltaScalar; + + // Build the case table + if ( insideOut ) + { + for ( i=0, index = 0; i < 3; i++) + { + if (cellScalars->GetComponent(i,0) <= value) + { + index |= CASE_MASK[i]; + } + } + } + else + { + for ( i=0, index = 0; i < 3; i++) + { + if (cellScalars->GetComponent(i,0) > value) + { + index |= CASE_MASK[i]; + } + } + } + + // Select the case based on the index and get the list of edges for this case + triangleCase = triangleCases + index; + edge = triangleCase->edges; + + // generate each triangle + for ( ; edge[0] > -1; edge += 3 ) + { + for (i=0; i<3; i++) // insert triangle + { + // vertex exists, and need not be interpolated + if (edge[i] >= 100) + { + vertexId = edge[i] - 100; + this->Points->GetPoint(vertexId, x); + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + outPd->CopyData(inPd,this->PointIds->GetId(vertexId),pts[i]); + } + } + + else //new vertex, interpolate + { + vert = edges[edge[i]]; + + // calculate a preferred interpolation direction + deltaScalar = (cellScalars->GetComponent(vert[1],0) - + cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + e1 = vert[0]; e2 = vert[1]; + } + else + { + e1 = vert[1]; e2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + if (deltaScalar == 0.0) + { + t = 0.0; + } + else + { + t = (value - cellScalars->GetComponent(e1,0)) / deltaScalar; + } + + this->Points->GetPoint(e1, x1); + this->Points->GetPoint(e2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + vtkIdType p1 = this->PointIds->GetId(e1); + vtkIdType p2 = this->PointIds->GetId(e2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate tri's + if (pts[0] == pts[1] || pts[0] == pts[2] || pts[1] == pts[2]) + { + continue; + } + + newCellId = tris->InsertNextCell(3,pts); + outCd->CopyData(inCd,cellId,newCellId); + } +} + +//---------------------------------------------------------------------------- +// Given a point x, determine whether it is inside (within the +// tolerance squared, tol2) the triangle defined by the three +// coordinate values p1, p2, p3. Method is via comparing dot products. +// (Note: in current implementation the tolerance only works in the +// neighborhood of the three vertices of the triangle. +int vtkTriangle::PointInTriangle(double x[3], double p1[3], double p2[3], + double p3[3], double tol2) +{ + double x1[3], x2[3], x3[3], v13[3], v21[3], v32[3]; + double n1[3], n2[3], n3[3]; + int i; + + // Compute appropriate vectors + // + for (i=0; i<3; i++) + { + x1[i] = x[i] - p1[i]; + x2[i] = x[i] - p2[i]; + x3[i] = x[i] - p3[i]; + v13[i] = p1[i] - p3[i]; + v21[i] = p2[i] - p1[i]; + v32[i] = p3[i] - p2[i]; + } + + // See whether intersection point is within tolerance of a vertex. + // + if ( (x1[0]*x1[0] + x1[1]*x1[1] + x1[2]*x1[2]) <= tol2 || + (x2[0]*x2[0] + x2[1]*x2[1] + x2[2]*x2[2]) <= tol2 || + (x3[0]*x3[0] + x3[1]*x3[1] + x3[2]*x3[2]) <= tol2 ) + { + return 1; + } + + // If not near a vertex, check whether point is inside of triangular face. + // + // Obtain normal off of triangular face + // + vtkMath::Cross (x1, v13, n1); + vtkMath::Cross (x2, v21, n2); + vtkMath::Cross (x3, v32, n3); + + // Check whether normals go in same direction + // + if ( (vtkMath::Dot(n1,n2) >= 0.0) && (vtkMath::Dot(n2,n3) >= 0.0) ) + { + return 1; + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +double vtkTriangle::GetParametricDistance(double pcoords[3]) +{ + int i; + double pDist, pDistMax=0.0; + double pc[3]; + + pc[0] = pcoords[0]; + pc[1] = pcoords[1]; + pc[2] = 1.0 - pcoords[0] - pcoords[1]; + + for (i=0; i<3; i++) + { + if ( pc[i] < 0.0 ) + { + pDist = -pc[i]; + } + else if ( pc[i] > 1.0 ) + { + pDist = pc[i] - 1.0; + } + else //inside the cell in the parametric direction + { + pDist = 0.0; + } + if ( pDist > pDistMax ) + { + pDistMax = pDist; + } + } + + return pDistMax; +} + + +//---------------------------------------------------------------------------- +void vtkTriangle::ComputeQuadric(double x1[3], double x2[3], double x3[3], + double quadric[4][4]) +{ + double crossX1X2[3], crossX2X3[3], crossX3X1[3]; + double determinantABC; + double ABCx[3][3]; + double n[4]; + int i, j; + + for (i = 0; i < 3; i++) + { + ABCx[0][i] = x1[i]; + ABCx[1][i] = x2[i]; + ABCx[2][i] = x3[i]; + } + + vtkMath::Cross(x1, x2, crossX1X2); + vtkMath::Cross(x2, x3, crossX2X3); + vtkMath::Cross(x3, x1, crossX3X1); + determinantABC = vtkMath::Determinant3x3(ABCx); + + n[0] = crossX1X2[0] + crossX2X3[0] + crossX3X1[0]; + n[1] = crossX1X2[1] + crossX2X3[1] + crossX3X1[1]; + n[2] = crossX1X2[2] + crossX2X3[2] + crossX3X1[2]; + n[3] = -determinantABC; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + quadric[i][j] = n[i] * n[j]; + } + } +} + +//---------------------------------------------------------------------------- +void vtkTriangle::ComputeQuadric(double x1[3], double x2[3], double x3[3], + vtkQuadric *quadric) +{ + double quadricMatrix[4][4]; + + ComputeQuadric(x1, x2, x3, quadricMatrix); + quadric->SetCoefficients(quadricMatrix[0][0], quadricMatrix[1][1], + quadricMatrix[2][2], 2*quadricMatrix[0][1], + 2*quadricMatrix[1][2], 2*quadricMatrix[0][2], + 2*quadricMatrix[0][3], 2*quadricMatrix[1][3], + 2*quadricMatrix[2][3], quadricMatrix[3][3]); +} + +//---------------------------------------------------------------------------- +static double vtkTriangleCellPCoords[9] = +{0.0,0.0,0.0, 1.0,0.0,0.0, 0.0,1.0,0.0}; +double *vtkTriangle::GetParametricCoords() +{ + return vtkTriangleCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkTriangle::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkTriangle.h b/Filtering/vtkTriangle.h new file mode 100644 index 0000000..4cd75c7 --- /dev/null +++ b/Filtering/vtkTriangle.h @@ -0,0 +1,239 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangle.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTriangle - a cell that represents a triangle +// .SECTION Description +// vtkTriangle is a concrete implementation of vtkCell to represent a triangle +// located in 3-space. + +#ifndef __vtkTriangle_h +#define __vtkTriangle_h + +#include "vtkCell.h" + +#include "vtkMath.h" // Needed for inline methods + +class vtkLine; +class vtkQuadric; + +class VTK_FILTERING_EXPORT vtkTriangle : public vtkCell +{ +public: + static vtkTriangle *New(); + vtkTypeRevisionMacro(vtkTriangle,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the edge specified by edgeId (range 0 to 2) and return that edge's + // coordinates. + vtkCell *GetEdge(int edgeId); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_TRIANGLE;}; + int GetCellDimension() {return 2;}; + int GetNumberOfEdges() {return 3;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetFace(int) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Clip this triangle using scalar value provided. Like contouring, except + // that it cuts the triangle to produce other triangles. + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + // Description: + // vtkTriangle specific methods. + static void InterpolationFunctions(double pcoords[3], double sf[3]); + static void InterpolationDerivs(double pcoords[3], double derivs[6]); + + // Description: + // Plane intersection plus in/out test on triangle. The in/out test is + // performed using tol as the tolerance. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + // Description: + // Return the center of the triangle in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Return the distance of the parametric coordinate provided to the + // cell. If inside the cell, a distance of zero is returned. + double GetParametricDistance(double pcoords[3]); + + // Description: + // Compute the center of the triangle. + static void TriangleCenter(double p1[3], double p2[3], double p3[3], + double center[3]); + + // Description: + // Compute the area of a triangle in 3D. + static double TriangleArea(double p1[3], double p2[3], double p3[3]); + + // Description: + // Compute the circumcenter (center[3]) and radius squared (method + // return value) of a triangle defined by the three points x1, x2, + // and x3. (Note that the coordinates are 2D. 3D points can be used + // but the z-component will be ignored.) + static double Circumcircle(double p1[2], double p2[2], double p3[2], + double center[2]); + + // Description: + // Given a 2D point x[2], determine the barycentric coordinates of the point. + // Barycentric coordinates are a natural coordinate system for simplices that + // express a position as a linear combination of the vertices. For a + // triangle, there are three barycentric coordinates (because there are + // three vertices), and the sum of the coordinates must equal 1. If a + // point x is inside a simplex, then all three coordinates will be strictly + // positive. If two coordinates are zero (so the third =1), then the + // point x is on a vertex. If one coordinates are zero, the point x is on an + // edge. In this method, you must specify the vertex coordinates x1->x3. + // Returns 0 if triangle is degenerate. + static int BarycentricCoords(double x[2], double x1[2], double x2[2], + double x3[2], double bcoords[3]); + + + // Description: + // Project triangle defined in 3D to 2D coordinates. Returns 0 if + // degenerate triangle; non-zero value otherwise. Input points are x1->x3; + // output 2D points are v1->v3. + static int ProjectTo2D(double x1[3], double x2[3], double x3[3], + double v1[2], double v2[2], double v3[2]); + + // Description: + // Compute the triangle normal from a points list, and a list of point ids + // that index into the points list. + static void ComputeNormal(vtkPoints *p, int numPts, vtkIdType *pts, + double n[3]); + + // Description: + // Compute the triangle normal from three points. + static void ComputeNormal(double v1[3], double v2[3], double v3[3], double n[3]); + + // Description: + // Compute the (unnormalized) triangle normal direction from three points. + static void ComputeNormalDirection(double v1[3], double v2[3], double v3[3], + double n[3]); + + // Description: + // Given a point x, determine whether it is inside (within the + // tolerance squared, tol2) the triangle defined by the three + // coordinate values p1, p2, p3. Method is via comparing dot products. + // (Note: in current implementation the tolerance only works in the + // neighborhood of the three vertices of the triangle. + static int PointInTriangle(double x[3], double x1[3], + double x2[3], double x3[3], + double tol2); + + // Description: + // Calculate the error quadric for this triangle. Return the + // quadric as a 4x4 matrix or a vtkQuadric. (from Peter + // Lindstrom's Siggraph 2000 paper, "Out-of-Core Simplification of + // Large Polygonal Models") + static void ComputeQuadric(double x1[3], double x2[3], double x3[3], + double quadric[4][4]); + static void ComputeQuadric(double x1[3], double x2[3], double x3[3], + vtkQuadric *quadric); + + +protected: + vtkTriangle(); + ~vtkTriangle(); + + vtkLine *Line; + +private: + vtkTriangle(const vtkTriangle&); // Not implemented. + void operator=(const vtkTriangle&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkTriangle::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 1./3; pcoords[2] = 0.0; + return 0; +} + +//---------------------------------------------------------------------------- +inline void vtkTriangle::ComputeNormalDirection(double v1[3], double v2[3], + double v3[3], double n[3]) +{ + double ax, ay, az, bx, by, bz; + + // order is important!!! maintain consistency with triangle vertex order + ax = v3[0] - v2[0]; ay = v3[1] - v2[1]; az = v3[2] - v2[2]; + bx = v1[0] - v2[0]; by = v1[1] - v2[1]; bz = v1[2] - v2[2]; + + n[0] = (ay * bz - az * by); + n[1] = (az * bx - ax * bz); + n[2] = (ax * by - ay * bx); +} + +//---------------------------------------------------------------------------- +inline void vtkTriangle::ComputeNormal(double v1[3], double v2[3], + double v3[3], double n[3]) +{ + double length; + + vtkTriangle::ComputeNormalDirection(v1, v2, v3, n); + + if ( (length = sqrt((n[0]*n[0] + n[1]*n[1] + n[2]*n[2]))) != 0.0 ) + { + n[0] /= length; + n[1] /= length; + n[2] /= length; + } +} + +//---------------------------------------------------------------------------- +inline void vtkTriangle::TriangleCenter(double p1[3], double p2[3], + double p3[3], double center[3]) +{ + center[0] = (p1[0]+p2[0]+p3[0]) / 3.0; + center[1] = (p1[1]+p2[1]+p3[1]) / 3.0; + center[2] = (p1[2]+p2[2]+p3[2]) / 3.0; +} + +//---------------------------------------------------------------------------- +inline double vtkTriangle::TriangleArea(double p1[3], double p2[3], double p3[3]) +{ + double a,b,c; + a = vtkMath::Distance2BetweenPoints(p1,p2); + b = vtkMath::Distance2BetweenPoints(p2,p3); + c = vtkMath::Distance2BetweenPoints(p3,p1); + return (0.25* sqrt(fabs(4.0*a*c - (a-b+c)*(a-b+c)))); +} + +#endif + + diff --git a/Filtering/vtkTriangleStrip.cxx b/Filtering/vtkTriangleStrip.cxx new file mode 100644 index 0000000..818ddb6 --- /dev/null +++ b/Filtering/vtkTriangleStrip.cxx @@ -0,0 +1,347 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangleStrip.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTriangleStrip.h" + +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkLine.h" +#include "vtkObjectFactory.h" +#include "vtkTriangle.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkTriangleStrip, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkTriangleStrip); + +//---------------------------------------------------------------------------- +vtkTriangleStrip::vtkTriangleStrip() +{ + this->Line = vtkLine::New(); + this->Triangle = vtkTriangle::New(); +} + +//---------------------------------------------------------------------------- +vtkTriangleStrip::~vtkTriangleStrip() +{ + this->Line->Delete(); + this->Triangle->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkTriangleStrip::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& minDist2, double *weights) +{ + double pc[3], dist2; + int ignoreId, i, return_status, status; + double tempWeights[3], activeWeights[3]; + double closest[3]; + + pcoords[2] = 0.0; + + return_status = 0; + for (minDist2=VTK_DOUBLE_MAX,i=0; iPoints->GetNumberOfPoints()-2; i++) + { + weights[i] = 0.0; + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(i)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(i+1)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(i+2)); + status = this->Triangle->EvaluatePosition(x,closest,ignoreId,pc,dist2,tempWeights); + if ( status != -1 && dist2 < minDist2 ) + { + return_status = status; + if (closestPoint) + { + closestPoint[0] = closest[0]; + closestPoint[1] = closest[1]; + closestPoint[2] = closest[2]; + } + subId = i; + pcoords[0] = pc[0]; + pcoords[1] = pc[1]; + pcoords[2] = 1.0 - pc[0] - pc[1]; + minDist2 = dist2; + activeWeights[0] = tempWeights[0]; + activeWeights[1] = tempWeights[1]; + activeWeights[2] = tempWeights[2]; + } + } + + weights[i] = 0.0; + weights[i+1] = 0.0; + + weights[subId] = activeWeights[0]; + weights[subId+1] = activeWeights[1]; + weights[subId+2] = activeWeights[2]; + + return return_status; +} + +//---------------------------------------------------------------------------- +void vtkTriangleStrip::EvaluateLocation(int& subId, double pcoords[3], + double x[3], double *weights) +{ + int i; + static int idx[2][3]={{0,1,2},{1,0,2}}; + int order = subId % 2; + + double pt1[3], pt2[3], pt3[3]; + this->Points->GetPoint(subId+idx[order][0], pt1); + this->Points->GetPoint(subId+idx[order][1], pt2); + this->Points->GetPoint(subId+idx[order][2], pt3); + double u3 = 1.0 - pcoords[0] - pcoords[1]; + + weights[0] = u3; + weights[1] = pcoords[0]; + weights[2] = pcoords[1]; + + for (i=0; i<3; i++) + { + x[i] = pt1[i]*weights[0] + pt2[i]*weights[1] + pt3[i]*weights[2]; + } +} + +//---------------------------------------------------------------------------- +int vtkTriangleStrip::CellBoundary(int subId, double pcoords[3], vtkIdList *pts) +{ + static int idx[2][3]={{0,1,2},{1,0,2}}; + int order; + + order = subId % 2; + + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(subId + idx[order][0])); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(subId + idx[order][1])); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(subId + idx[order][2])); + return this->Triangle->CellBoundary(0, pcoords, pts); +} + +//---------------------------------------------------------------------------- +void vtkTriangleStrip::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd) +{ + int i, numTris=this->Points->GetNumberOfPoints()-2; + vtkDataArray *triScalars=cellScalars->NewInstance(); + triScalars->SetNumberOfComponents(cellScalars->GetNumberOfComponents()); + triScalars->SetNumberOfTuples(3); + + for ( i=0; i < numTris; i++) + { + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(i)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(i+1)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(i+2)); + + if ( outPd ) + { + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(i)); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(i+1)); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(i+2)); + } + + triScalars->SetTuple(0,cellScalars->GetTuple(i)); + triScalars->SetTuple(1,cellScalars->GetTuple(i+1)); + triScalars->SetTuple(2,cellScalars->GetTuple(i+2)); + + this->Triangle->Contour(value, triScalars, locator, verts, + lines, polys, inPd, outPd, inCd, cellId, outCd); + } + triScalars->Delete(); +} + + +//---------------------------------------------------------------------------- +vtkCell *vtkTriangleStrip::GetEdge(int edgeId) +{ + int id1, id2; + + if ( edgeId == 0 ) + { + id1 = 0; + id2 = 1; + } + else if ( edgeId == (this->GetNumberOfPoints()-1) ) + { + id1 = edgeId - 1; + id2 = edgeId; + } + else + { + id1 = edgeId - 1; + id2 = edgeId + 1; + } + + this->Line->PointIds->SetId(0,this->PointIds->GetId(id1)); + this->Line->PointIds->SetId(1,this->PointIds->GetId(id2)); + this->Line->Points->SetPoint(0,this->Points->GetPoint(id1)); + this->Line->Points->SetPoint(1,this->Points->GetPoint(id2)); + + return this->Line; +} + +//---------------------------------------------------------------------------- +// +// Intersect sub-triangles +// +int vtkTriangleStrip::IntersectWithLine(double p1[3], double p2[3], double tol, + double& t, double x[3], double pcoords[3], + int& subId) +{ + int subTest, numTris=this->Points->GetNumberOfPoints()-2; + + for (subId=0; subId < numTris; subId++) + { + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(subId)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(subId+1)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(subId+2)); + + if (this->Triangle->IntersectWithLine(p1, p2, tol, t, x, pcoords, subTest) ) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkTriangleStrip::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + int numTris = this->Points->GetNumberOfPoints()-2; + int i, order; + static int idx[2][3]={{0,1,2},{1,0,2}}; + + pts->Reset(); + ptIds->Reset(); + + for (int subId=0; subId < numTris; subId++) + { + order = subId % 2; + + for ( i=0; i < 3; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(subId+idx[order][i])); + pts->InsertNextPoint(this->Points->GetPoint(subId+idx[order][i])); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkTriangleStrip::Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs) +{ + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(subId)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(subId+1)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(subId+2)); + + this->Triangle->Derivatives(0, pcoords, values+dim*subId, dim, derivs); +} + +//---------------------------------------------------------------------------- +// Given a triangle strip, decompose it into (triangle) polygons. The +// polygons are appended to the end of the list of polygons. +void vtkTriangleStrip::DecomposeStrip(int npts, vtkIdType *pts, + vtkCellArray *polys) +{ + int p1, p2, p3, i; + + p1 = pts[0]; + p2 = pts[1]; + for (i=0; i<(npts-2); i++) + { + p3 = pts[i+2]; + polys->InsertNextCell(3); + if ( (i % 2) ) // flip ordering to preserve consistency + { + polys->InsertCellPoint(p2); + polys->InsertCellPoint(p1); + polys->InsertCellPoint(p3); + } + else + { + polys->InsertCellPoint(p1); + polys->InsertCellPoint(p2); + polys->InsertCellPoint(p3); + } + p1 = p2; + p2 = p3; + } +} + +//---------------------------------------------------------------------------- +void vtkTriangleStrip::Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *tris, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, + vtkCellData *outCd, int insideOut) +{ + int i, numTris=this->Points->GetNumberOfPoints()-2; + int id1, id2, id3; + vtkDataArray *triScalars=cellScalars->NewInstance(); + triScalars->SetNumberOfComponents(cellScalars->GetNumberOfComponents()); + triScalars->SetNumberOfTuples(3); + + for ( i=0; i < numTris; i++) + { + if (i % 2) + { + id1 = i + 2; id2 = i + 1; id3 = i; + } + else + { + id1 = i; id2 = i + 1; id3 = i + 2; + } + + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(id1)); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(id2)); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(id3)); + + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(id1)); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(id2)); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(id3)); + + triScalars->SetTuple(0,cellScalars->GetTuple(id1)); + triScalars->SetTuple(1,cellScalars->GetTuple(id2)); + triScalars->SetTuple(2,cellScalars->GetTuple(id3)); + + this->Triangle->Clip(value, triScalars, locator, tris, inPd, outPd, + inCd, cellId, outCd, insideOut); + } + + triScalars->Delete(); +} + +//---------------------------------------------------------------------------- +// Return the center of the point cloud in parametric coordinates. +int vtkTriangleStrip::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.333333; pcoords[2] = 0.0; + return ((this->Points->GetNumberOfPoints()-2) / 2); +} + +//---------------------------------------------------------------------------- +void vtkTriangleStrip::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Triangle:\n"; + this->Triangle->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkTriangleStrip.h b/Filtering/vtkTriangleStrip.h new file mode 100644 index 0000000..67175d3 --- /dev/null +++ b/Filtering/vtkTriangleStrip.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangleStrip.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTriangleStrip - a cell that represents a triangle strip +// .SECTION Description +// vtkTriangleStrip is a concrete implementation of vtkCell to represent a 2D +// triangle strip. A triangle strip is a compact representation of triangles +// connected edge to edge in strip fashion. The connectivity of a triangle +// strip is three points defining an initial triangle, then for each +// additional triangle, a single point that, combined with the previous two +// points, defines the next triangle. + +#ifndef __vtkTriangleStrip_h +#define __vtkTriangleStrip_h + +#include "vtkCell.h" + +class vtkLine; +class vtkTriangle; + +class VTK_FILTERING_EXPORT vtkTriangleStrip : public vtkCell +{ +public: + static vtkTriangleStrip *New(); + vtkTypeRevisionMacro(vtkTriangleStrip,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_TRIANGLE_STRIP;}; + int GetCellDimension() {return 2;}; + int GetNumberOfEdges() {return this->GetNumberOfPoints();}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int vtkNotUsed(faceId)) {return 0;}; + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + int IsPrimaryCell() {return 0;} + + // Description: + // Return the center of the point cloud in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Given a triangle strip, decompose it into a list of (triangle) + // polygons. The polygons are appended to the end of the list of triangles. + static void DecomposeStrip(int npts, vtkIdType *pts, vtkCellArray *tris); + + +protected: + vtkTriangleStrip(); + ~vtkTriangleStrip(); + + vtkLine *Line; + vtkTriangle *Triangle; + +private: + vtkTriangleStrip(const vtkTriangleStrip&); // Not implemented. + void operator=(const vtkTriangleStrip&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkTrivialProducer.cxx b/Filtering/vtkTrivialProducer.cxx new file mode 100644 index 0000000..c5f58bb --- /dev/null +++ b/Filtering/vtkTrivialProducer.cxx @@ -0,0 +1,149 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTrivialProducer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTrivialProducer.h" + +#include "vtkImageData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkTrivialProducer, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkTrivialProducer); + +//---------------------------------------------------------------------------- +vtkTrivialProducer::vtkTrivialProducer() +{ + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); + this->Output = 0; +} + +//---------------------------------------------------------------------------- +vtkTrivialProducer::~vtkTrivialProducer() +{ + this->SetOutput(0); +} + +//---------------------------------------------------------------------------- +void vtkTrivialProducer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkTrivialProducer::SetOutput(vtkDataObject*newOutput) +{ + vtkDataObject* oldOutput = this->Output; + if(newOutput != oldOutput) + { + if(newOutput) + { + newOutput->Register(this); + } + this->Output = newOutput; + this->GetExecutive()->SetOutputData(0, newOutput); + if(oldOutput) + { + oldOutput->UnRegister(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkTrivialProducer::GetMTime() +{ + unsigned long mtime = this->Superclass::GetMTime(); + if(this->Output) + { + unsigned long omtime = this->Output->GetMTime(); + if(omtime > mtime) + { + mtime = omtime; + } + } + return mtime; +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkTrivialProducer::CreateDefaultExecutive() +{ + return vtkStreamingDemandDrivenPipeline::New(); +} + +//---------------------------------------------------------------------------- +int vtkTrivialProducer::FillInputPortInformation(int, vtkInformation*) +{ + return 1; +} + +//---------------------------------------------------------------------------- +int vtkTrivialProducer::FillOutputPortInformation(int, vtkInformation*) +{ + return 1; +} + +//---------------------------------------------------------------------------- +int +vtkTrivialProducer::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()) && + this->Output) + { + vtkInformation* outputInfo = outputVector->GetInformationObject(0); + vtkInformation* dataInfo = this->Output->GetInformation(); + if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_PIECES_EXTENT) + { + // There is no real source to change the output data, so we can + // produce exactly one piece. + outputInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), 1); + } + else if(dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_3D_EXTENT) + { + // The whole extent is just the extent because the output has no + // real source to change its data. + int extent[6]; + dataInfo->Get(vtkDataObject::DATA_EXTENT(), extent); + outputInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + extent, 6); + } + } + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_NOT_GENERATED())) + { + // We do not really generate the output. Do not let the executive + // initialize it. + vtkInformation* outputInfo = outputVector->GetInformationObject(0); + outputInfo->Set(vtkDemandDrivenPipeline::DATA_NOT_GENERATED(), 1); + } + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()) && this->Output) + { + // Pretend we generated the output. + vtkInformation* outputInfo = outputVector->GetInformationObject(0); + outputInfo->Remove(vtkDemandDrivenPipeline::DATA_NOT_GENERATED()); + } + + return this->Superclass::ProcessRequest(request,inputVector,outputVector); +} + +//---------------------------------------------------------------------------- +void vtkTrivialProducer::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->Output, "Output"); +} diff --git a/Filtering/vtkTrivialProducer.h b/Filtering/vtkTrivialProducer.h new file mode 100644 index 0000000..b62a3d7 --- /dev/null +++ b/Filtering/vtkTrivialProducer.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTrivialProducer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTrivialProducer - Producer for stand-alone data objects. +// .SECTION Description +// vtkTrivialProducer allows stand-alone data objects to be connected +// as inputs in a pipeline. All data objects that are connected to a +// pipeline involving vtkAlgorithm must have a producer. This trivial +// producer allows data objects that are hand-constructed in a program +// without another vtk producer to be connected. + +#ifndef __vtkTrivialProducer_h +#define __vtkTrivialProducer_h + +#include "vtkAlgorithm.h" + +class vtkDataObject; + +class VTK_FILTERING_EXPORT vtkTrivialProducer : public vtkAlgorithm +{ +public: + static vtkTrivialProducer *New(); + vtkTypeRevisionMacro(vtkTrivialProducer,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Process upstream/downstream requests trivially. The associated + // output data object is never modified, but it is queried to + // fulfill requests. + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // Description: + // Set the data object that is "produced" by this producer. It is + // never really modified. + virtual void SetOutput(vtkDataObject* output); + + // Description: + // The modified time of this producer is the newer of this object or + // the assigned output. + virtual unsigned long GetMTime(); +protected: + vtkTrivialProducer(); + ~vtkTrivialProducer(); + + virtual int FillInputPortInformation(int, vtkInformation*); + virtual int FillOutputPortInformation(int, vtkInformation*); + virtual vtkExecutive* CreateDefaultExecutive(); + + // The real data object. + vtkDataObject* Output; + + virtual void ReportReferences(vtkGarbageCollector*); +private: + vtkTrivialProducer(const vtkTrivialProducer&); // Not implemented. + void operator=(const vtkTrivialProducer&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkUniformGrid.cxx b/Filtering/vtkUniformGrid.cxx new file mode 100644 index 0000000..94f1c28 --- /dev/null +++ b/Filtering/vtkUniformGrid.cxx @@ -0,0 +1,850 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUniformGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUniformGrid.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkEmptyCell.h" +#include "vtkGenericCell.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPixel.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkStructuredVisibilityConstraint.h" +#include "vtkVertex.h" +#include "vtkVoxel.h" + +vtkCxxRevisionMacro(vtkUniformGrid, "$Revision: 1.10.6.1 $"); +vtkStandardNewMacro(vtkUniformGrid); + +vtkCxxSetObjectMacro(vtkUniformGrid, + PointVisibility, + vtkStructuredVisibilityConstraint); +vtkCxxSetObjectMacro(vtkUniformGrid, + CellVisibility, + vtkStructuredVisibilityConstraint); + +//---------------------------------------------------------------------------- +vtkUniformGrid::vtkUniformGrid() +{ + this->PointVisibility = vtkStructuredVisibilityConstraint::New(); + this->CellVisibility = vtkStructuredVisibilityConstraint::New(); + + this->EmptyCell = vtkEmptyCell::New(); +} + +//---------------------------------------------------------------------------- +vtkUniformGrid::~vtkUniformGrid() +{ + this->PointVisibility->Delete(); + this->CellVisibility->Delete(); + this->EmptyCell->Delete(); +} + +//---------------------------------------------------------------------------- +// Copy the geometric and topological structure of an input structured points +// object. +void vtkUniformGrid::CopyStructure(vtkDataSet *ds) +{ + this->Initialize(); + + this->Superclass::CopyStructure(ds); + + vtkUniformGrid *sPts=vtkUniformGrid::SafeDownCast(ds); + if (!sPts) + { + return; + } + + this->PointVisibility->ShallowCopy(sPts->PointVisibility); + this->CellVisibility->ShallowCopy(sPts->CellVisibility); +} + +//---------------------------------------------------------------------------- +void vtkUniformGrid::Initialize() +{ + this->Superclass::Initialize(); + + this->PointVisibility->Delete(); + this->PointVisibility = vtkStructuredVisibilityConstraint::New(); + + this->CellVisibility->Delete(); + this->CellVisibility = vtkStructuredVisibilityConstraint::New(); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkUniformGrid::GetCell(vtkIdType cellId) +{ + vtkCell *cell = NULL; + int loc[3]; + vtkIdType idx, npts; + int iMin, iMax, jMin, jMax, kMin, kMax; + double x[3]; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + int extent[6]; + this->GetExtent(extent); + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + int d01 = dims[0]*dims[1]; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0) + { + vtkErrorMacro("Requesting a cell from an empty image."); + return this->EmptyCell; + } + + // see whether the cell is blanked + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + return this->EmptyCell; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + return this->EmptyCell; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell = this->Vertex; + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + cell = this->Line; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + cell = this->Line; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + cell = this->Line; + break; + + case VTK_XY_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + jMin = cellId / (dims[0]-1); + jMax = jMin + 1; + cell = this->Pixel; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (dims[1]-1); + jMax = jMin + 1; + kMin = cellId / (dims[1]-1); + kMax = kMin + 1; + cell = this->Pixel; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + kMin = cellId / (dims[0]-1); + kMax = kMin + 1; + cell = this->Pixel; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (dims[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((dims[0] - 1) * (dims[1] - 1)); + kMax = kMin + 1; + cell = this->Voxel; + break; + } + + // Extract point coordinates and point ids + // Ids are relative to extent min. + npts = 0; + for (loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2]; + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1]; + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0]; + + idx = loc[0] + loc[1]*dims[0] + loc[2]*d01; + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,x); + } + } + } + + return cell; +} + +//---------------------------------------------------------------------------- +void vtkUniformGrid::GetCell(vtkIdType cellId, vtkGenericCell *cell) +{ + vtkIdType npts, idx; + int loc[3]; + int iMin, iMax, jMin, jMax, kMin, kMax; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + double x[3]; + int extent[6]; + this->GetExtent(extent); + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + int d01 = dims[0]*dims[1]; + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + if (dims[0] == 0 || dims[1] == 0 || dims[2] == 0) + { + vtkErrorMacro("Requesting a cell from an empty image."); + cell->SetCellTypeToEmptyCell(); + return; + } + + // see whether the cell is blanked + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + cell->SetCellTypeToEmptyCell(); + return; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + cell->SetCellTypeToEmptyCell(); + return; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + cell->SetCellTypeToVertex(); + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + cell->SetCellTypeToLine(); + break; + + case VTK_XY_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + jMin = cellId / (dims[0]-1); + jMax = jMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_YZ_PLANE: + jMin = cellId % (dims[1]-1); + jMax = jMin + 1; + kMin = cellId / (dims[1]-1); + kMax = kMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_XZ_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + kMin = cellId / (dims[0]-1); + kMax = kMin + 1; + cell->SetCellTypeToPixel(); + break; + + case VTK_XYZ_GRID: + iMin = cellId % (dims[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((dims[0] - 1) * (dims[1] - 1)); + kMax = kMin + 1; + cell->SetCellTypeToVoxel(); + break; + } + + // Extract point coordinates and point ids + for (npts=0,loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + x[2] = origin[2] + (loc[2]+extent[4]) * spacing[2]; + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + x[1] = origin[1] + (loc[1]+extent[2]) * spacing[1]; + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + x[0] = origin[0] + (loc[0]+extent[0]) * spacing[0]; + + idx = loc[0] + loc[1]*dims[0] + loc[2]*d01; + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,x); + } + } + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkUniformGrid::FindCell(double x[3], vtkCell *vtkNotUsed(cell), + vtkGenericCell *vtkNotUsed(gencell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), + int& subId, double pcoords[3], + double *weights) +{ + return + this->FindCell( x, (vtkCell *)NULL, 0, 0.0, subId, pcoords, weights ); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkUniformGrid::FindCell(double x[3], vtkCell *vtkNotUsed(cell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), + int& subId, double pcoords[3], double *weights) +{ + int loc[3]; + int *dims = this->GetDimensions(); + + if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 ) + { + return -1; + } + + vtkVoxel::InterpolationFunctions(pcoords,weights); + + // + // From this location get the cell id + // + subId = 0; + int extent[6]; + this->GetExtent(extent); + + vtkIdType cellId = (loc[2]-extent[4]) * (dims[0]-1)*(dims[1]-1) + + (loc[1]-extent[2]) * (dims[0]-1) + loc[0] - extent[0]; + + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + return -1; + } + return cellId; + +} + +//---------------------------------------------------------------------------- +vtkCell *vtkUniformGrid::FindAndGetCell(double x[3], + vtkCell *vtkNotUsed(cell), + vtkIdType vtkNotUsed(cellId), + double vtkNotUsed(tol2), int& subId, + double pcoords[3], double *weights) +{ + int i, j, k, loc[3]; + vtkIdType npts, idx; + double xOut[3]; + int iMax = 0; + int jMax = 0; + int kMax = 0;; + vtkCell *cell = NULL; + double *origin = this->GetOrigin(); + double *spacing = this->GetSpacing(); + int extent[6]; + this->GetExtent(extent); + + int dims[3]; + dims[0] = extent[1] - extent[0] + 1; + dims[1] = extent[3] - extent[2] + 1; + dims[2] = extent[5] - extent[4] + 1; + vtkIdType d01 = dims[0]*dims[1]; + + if ( this->ComputeStructuredCoordinates(x, loc, pcoords) == 0 ) + { + return NULL; + } + + vtkIdType cellId = loc[2] * (dims[0]-1)*(dims[1]-1) + + loc[1] * (dims[0]-1) + loc[0]; + + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + return NULL; + } + + // + // Get the parametric coordinates and weights for interpolation + // + switch (this->DataDescription) + { + case VTK_EMPTY: + return NULL; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + vtkVertex::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1]; + kMax = loc[2]; + cell = this->Vertex; + break; + + case VTK_X_LINE: + vtkLine::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1]; + kMax = loc[2]; + cell = this->Line; + break; + + case VTK_Y_LINE: + vtkLine::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1] + 1; + kMax = loc[2]; + cell = this->Line; + break; + + case VTK_Z_LINE: + vtkLine::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1]; + kMax = loc[2] + 1; + cell = this->Line; + break; + + case VTK_XY_PLANE: + vtkPixel::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1] + 1; + kMax = loc[2]; + cell = this->Pixel; + break; + + case VTK_YZ_PLANE: + vtkPixel::InterpolationFunctions(pcoords,weights); + iMax = loc[0]; + jMax = loc[1] + 1; + kMax = loc[2] + 1; + cell = this->Pixel; + break; + + case VTK_XZ_PLANE: + vtkPixel::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1]; + kMax = loc[2] + 1; + cell = this->Pixel; + break; + + case VTK_XYZ_GRID: + vtkVoxel::InterpolationFunctions(pcoords,weights); + iMax = loc[0] + 1; + jMax = loc[1] + 1; + kMax = loc[2] + 1; + cell = this->Voxel; + break; + } + + npts = 0; + for (k = loc[2]; k <= kMax; k++) + { + xOut[2] = origin[2] + k * spacing[2]; + for (j = loc[1]; j <= jMax; j++) + { + xOut[1] = origin[1] + j * spacing[1]; + // make idx relative to the extent not the whole extent + idx = loc[0]-extent[0] + (j-extent[2])*dims[0] + + (k-extent[4])*d01; + for (i = loc[0]; i <= iMax; i++, idx++) + { + xOut[0] = origin[0] + i * spacing[0]; + + cell->PointIds->SetId(npts,idx); + cell->Points->SetPoint(npts++,xOut); + } + } + } + subId = 0; + + return cell; +} + +//---------------------------------------------------------------------------- +int vtkUniformGrid::GetCellType(vtkIdType cellId) +{ + // see whether the cell is blanked + if ( (this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained()) + && !this->IsCellVisible(cellId) ) + { + return VTK_EMPTY_CELL; + } + + switch (this->DataDescription) + { + case VTK_EMPTY: + return VTK_EMPTY_CELL; + + case VTK_SINGLE_POINT: + return VTK_VERTEX; + + case VTK_X_LINE: case VTK_Y_LINE: case VTK_Z_LINE: + return VTK_LINE; + + case VTK_XY_PLANE: case VTK_YZ_PLANE: case VTK_XZ_PLANE: + return VTK_PIXEL; + + case VTK_XYZ_GRID: + return VTK_VOXEL; + + default: + vtkErrorMacro(<<"Bad data description!"); + return VTK_EMPTY_CELL; + } +} + +//---------------------------------------------------------------------------- +void vtkUniformGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkUniformGrid::NewImageDataCopy() +{ + vtkImageData* copy = vtkImageData::New(); + + copy->ShallowCopy(this); + + double origin[3]; + double spacing[3]; + this->GetOrigin(origin); + this->GetSpacing(spacing); + // First set the extent of the copy to empty so that + // the next call computes the DataDescription for us + copy->SetExtent(0, -1, 0, -1, 0, -1); + copy->SetExtent(this->GetExtent()); + copy->SetOrigin(origin); + copy->SetSpacing(spacing); + + return copy; +} + +//---------------------------------------------------------------------------- +void vtkUniformGrid::ShallowCopy(vtkDataObject *dataObject) +{ + vtkUniformGrid *ugData = vtkUniformGrid::SafeDownCast(dataObject); + + if ( ugData ) + { + this->PointVisibility->ShallowCopy(ugData->PointVisibility); + this->CellVisibility->ShallowCopy(ugData->CellVisibility); + } + + // Do superclass + this->Superclass::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkUniformGrid::DeepCopy(vtkDataObject *dataObject) +{ + vtkUniformGrid *ugData = vtkUniformGrid::SafeDownCast(dataObject); + + if ( ugData != NULL ) + { + this->PointVisibility->DeepCopy(ugData->PointVisibility); + this->CellVisibility->DeepCopy(ugData->CellVisibility); + } + // Do superclass + this->Superclass::DeepCopy(dataObject); +} + + +//---------------------------------------------------------------------------- +// Override this method because of blanking +void vtkUniformGrid::GetScalarRange(double range[2]) +{ + vtkDataArray *ptScalars = this->PointData->GetScalars(); + vtkDataArray *cellScalars = this->CellData->GetScalars(); + double ptRange[2]; + double cellRange[2]; + double s; + int id, num; + + ptRange[0] = VTK_DOUBLE_MAX; + ptRange[1] = -VTK_DOUBLE_MAX; + if ( ptScalars ) + { + num = this->GetNumberOfPoints(); + for (id=0; id < num; id++) + { + if ( this->IsPointVisible(id) ) + { + s = ptScalars->GetComponent(id,0); + if ( s < ptRange[0] ) + { + ptRange[0] = s; + } + if ( s > ptRange[1] ) + { + ptRange[1] = s; + } + } + } + } + + cellRange[0] = ptRange[0]; + cellRange[1] = ptRange[1]; + if ( cellScalars ) + { + num = this->GetNumberOfCells(); + for (id=0; id < num; id++) + { + if ( this->IsCellVisible(id) ) + { + s = cellScalars->GetComponent(id,0); + if ( s < cellRange[0] ) + { + cellRange[0] = s; + } + if ( s > cellRange[1] ) + { + cellRange[1] = s; + } + } + } + } + + range[0] = (cellRange[0] >= VTK_DOUBLE_MAX ? 0.0 : cellRange[0]); + range[1] = (cellRange[1] <= -VTK_DOUBLE_MAX ? 1.0 : cellRange[1]); + + this->ComputeTime.Modified(); +} + +//---------------------------------------------------------------------------- +// Turn off a particular data point. +void vtkUniformGrid::BlankPoint(vtkIdType ptId) +{ + this->PointVisibility->Initialize(this->Dimensions); + this->PointVisibility->Blank(ptId); +} + +//---------------------------------------------------------------------------- +// Turn on a particular data point. +void vtkUniformGrid::UnBlankPoint(vtkIdType ptId) +{ + this->PointVisibility->Initialize(this->Dimensions); + this->PointVisibility->UnBlank(ptId); +} + +//---------------------------------------------------------------------------- +void vtkUniformGrid::SetPointVisibilityArray(vtkUnsignedCharArray *ptVis) +{ + this->PointVisibility->SetVisibilityById(ptVis); +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray* vtkUniformGrid::GetPointVisibilityArray() +{ + return this->PointVisibility->GetVisibilityById(); +} + +//---------------------------------------------------------------------------- +// Turn off a particular data cell. +void vtkUniformGrid::BlankCell(vtkIdType cellId) +{ + this->CellVisibility->Initialize(this->Dimensions); + this->CellVisibility->Blank(cellId); +} + +//---------------------------------------------------------------------------- +// Turn on a particular data cell. +void vtkUniformGrid::UnBlankCell(vtkIdType cellId) +{ + this->CellVisibility->Initialize(this->Dimensions); + this->CellVisibility->UnBlank(cellId); +} + +//---------------------------------------------------------------------------- +void vtkUniformGrid::SetCellVisibilityArray(vtkUnsignedCharArray *cellVis) +{ + this->CellVisibility->SetVisibilityById(cellVis); +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray* vtkUniformGrid::GetCellVisibilityArray() +{ + return this->CellVisibility->GetVisibilityById(); +} + +//---------------------------------------------------------------------------- +unsigned char vtkUniformGrid::IsPointVisible(vtkIdType pointId) +{ + return this->PointVisibility->IsVisible(pointId); +} + +//---------------------------------------------------------------------------- +// Return non-zero if the specified cell is visible (i.e., not blanked) +unsigned char vtkUniformGrid::IsCellVisible(vtkIdType cellId) +{ + + if ( !this->CellVisibility->IsVisible(cellId) ) + { + return 0; + } + + int iMin, iMax, jMin, jMax, kMin, kMax; + int *dims = this->GetDimensions(); + + iMin = iMax = jMin = jMax = kMin = kMax = 0; + + switch (this->DataDescription) + { + case VTK_EMPTY: + return 0; + + case VTK_SINGLE_POINT: // cellId can only be = 0 + break; + + case VTK_X_LINE: + iMin = cellId; + iMax = cellId + 1; + break; + + case VTK_Y_LINE: + jMin = cellId; + jMax = cellId + 1; + break; + + case VTK_Z_LINE: + kMin = cellId; + kMax = cellId + 1; + break; + + case VTK_XY_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + jMin = cellId / (dims[0]-1); + jMax = jMin + 1; + break; + + case VTK_YZ_PLANE: + jMin = cellId % (dims[1]-1); + jMax = jMin + 1; + kMin = cellId / (dims[1]-1); + kMax = kMin + 1; + break; + + case VTK_XZ_PLANE: + iMin = cellId % (dims[0]-1); + iMax = iMin + 1; + kMin = cellId / (dims[0]-1); + kMax = kMin + 1; + break; + + case VTK_XYZ_GRID: + iMin = cellId % (dims[0] - 1); + iMax = iMin + 1; + jMin = (cellId / (dims[0] - 1)) % (dims[1] - 1); + jMax = jMin + 1; + kMin = cellId / ((dims[0] - 1) * (dims[1] - 1)); + kMax = kMin + 1; + break; + } + + // Extract point ids + // Ids are relative to extent min. + vtkIdType idx[8]; + vtkIdType npts = 0; + int loc[3]; + int d01 = dims[0]*dims[1]; + for (loc[2]=kMin; loc[2]<=kMax; loc[2]++) + { + for (loc[1]=jMin; loc[1]<=jMax; loc[1]++) + { + for (loc[0]=iMin; loc[0]<=iMax; loc[0]++) + { + idx[npts] = loc[0] + loc[1]*dims[0] + loc[2]*d01; + npts++; + } + } + } + + for (int i=0; iIsPointVisible(idx[i]) ) + { + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +unsigned char vtkUniformGrid::GetPointBlanking() +{ + return this->PointVisibility->IsConstrained(); +} + +//---------------------------------------------------------------------------- +unsigned char vtkUniformGrid::GetCellBlanking() +{ + return this->PointVisibility->IsConstrained() || + this->CellVisibility->IsConstrained(); +} + +//---------------------------------------------------------------------------- +vtkUniformGrid* vtkUniformGrid::GetData(vtkInformation* info) +{ + return info? vtkUniformGrid::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkUniformGrid* vtkUniformGrid::GetData(vtkInformationVector* v, int i) +{ + return vtkUniformGrid::GetData(v->GetInformationObject(i)); +} diff --git a/Filtering/vtkUniformGrid.h b/Filtering/vtkUniformGrid.h new file mode 100644 index 0000000..5827411 --- /dev/null +++ b/Filtering/vtkUniformGrid.h @@ -0,0 +1,168 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUniformGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUniformGrid - image data with blanking +// .SECTION Description +// vtkUniformGrid is a subclass of vtkImageData. In addition to all +// the image data functionality, it supports blanking. + +#ifndef __vtkUniformGrid_h +#define __vtkUniformGrid_h + +#include "vtkImageData.h" + +class vtkEmptyCell; +class vtkStructuredVisibilityConstraint; +class vtkUnsignedCharArray; + +class VTK_FILTERING_EXPORT vtkUniformGrid : public vtkImageData +{ +public: + static vtkUniformGrid *New(); + + vtkTypeRevisionMacro(vtkUniformGrid,vtkImageData); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Copy the geometric and topological structure of an input image data + // object. + virtual void CopyStructure(vtkDataSet *ds); + + // Description: + // Return what type of dataset this is. + virtual int GetDataObjectType() {return VTK_UNIFORM_GRID;}; + + // Description: + // Standard vtkDataSet API methods. See vtkDataSet for more information. + virtual vtkCell *GetCell(vtkIdType cellId); + virtual void GetCell(vtkIdType cellId, vtkGenericCell *cell); + virtual vtkIdType FindCell( + double x[3], vtkCell *cell, vtkIdType cellId, double tol2, + int& subId, double pcoords[3], double *weights); + virtual vtkIdType FindCell( + double x[3], vtkCell *cell, vtkGenericCell *gencell, + vtkIdType cellId, double tol2, int& subId, + double pcoords[3], double *weights); + virtual vtkCell *FindAndGetCell( + double x[3], vtkCell *cell, vtkIdType cellId, + double tol2, int& subId, double pcoords[3], + double *weights); + virtual int GetCellType(vtkIdType cellId); + virtual void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds) + {vtkStructuredData::GetCellPoints(cellId,ptIds,this->DataDescription, + this->GetDimensions());} + virtual void GetPointCells(vtkIdType ptId, vtkIdList *cellIds) + {vtkStructuredData::GetPointCells(ptId,cellIds,this->GetDimensions());} + virtual void Initialize(); + virtual int GetMaxCellSize() {return 8;}; //voxel is the largest + virtual void GetScalarRange(double range[2]); + + // Description: + // Shallow and Deep copy. + virtual void ShallowCopy(vtkDataObject *src); + virtual void DeepCopy(vtkDataObject *src); + + // Description: + // Methods for supporting blanking of cells. Blanking turns on or off + // points in the structured grid, and hence the cells connected to them. + // These methods should be called only after the dimensions of the + // grid are set. + virtual void BlankPoint(vtkIdType ptId); + virtual void UnBlankPoint(vtkIdType ptId); + + // Description: + // Methods for supporting blanking of cells. Blanking turns on or off + // cells in the structured grid. + // These methods should be called only after the dimensions of the + // grid are set. + virtual void BlankCell(vtkIdType ptId); + virtual void UnBlankCell(vtkIdType ptId); + + // Description: + // Get the array that defines the blanking (visibility) of each point. + virtual vtkUnsignedCharArray *GetPointVisibilityArray(); + + // Description: + // Set an array that defines the (blanking) visibility of the points + // in the grid. Make sure that length of the visibility array matches + // the number of points in the grid. + virtual void SetPointVisibilityArray(vtkUnsignedCharArray *pointVisibility); + + // Description: + // Get the array that defines the blanking (visibility) of each cell. + virtual vtkUnsignedCharArray *GetCellVisibilityArray(); + + // Description: + // Set an array that defines the (blanking) visibility of the cells + // in the grid. Make sure that length of the visibility array matches + // the number of points in the grid. + virtual void SetCellVisibilityArray(vtkUnsignedCharArray *pointVisibility); + + // Description: + // Return non-zero value if specified point is visible. + // These methods should be called only after the dimensions of the + // grid are set. + virtual unsigned char IsPointVisible(vtkIdType ptId); + + // Description: + // Return non-zero value if specified point is visible. + // These methods should be called only after the dimensions of the + // grid are set. + virtual unsigned char IsCellVisible(vtkIdType cellId); + + // Description: + // Returns 1 if there is any visibility constraint on the points, + // 0 otherwise. + virtual unsigned char GetPointBlanking(); + + // Description: + // Returns 1 if there is any visibility constraint on the cells, + // 0 otherwise. + virtual unsigned char GetCellBlanking(); + + virtual vtkImageData* NewImageDataCopy(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkUniformGrid* GetData(vtkInformation* info); + static vtkUniformGrid* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkUniformGrid(); + ~vtkUniformGrid(); + + vtkStructuredVisibilityConstraint* PointVisibility; + + void SetPointVisibility(vtkStructuredVisibilityConstraint *pointVisibility); + vtkGetObjectMacro(PointVisibility, vtkStructuredVisibilityConstraint); + + vtkStructuredVisibilityConstraint* CellVisibility; + + void SetCellVisibility(vtkStructuredVisibilityConstraint *cellVisibility); + vtkGetObjectMacro(CellVisibility, vtkStructuredVisibilityConstraint); + + vtkEmptyCell *EmptyCell; + +private: + vtkUniformGrid(const vtkUniformGrid&); // Not implemented. + void operator=(const vtkUniformGrid&); // Not implemented. +}; + + +#endif + + + diff --git a/Filtering/vtkUnstructuredGrid.cxx b/Filtering/vtkUnstructuredGrid.cxx new file mode 100644 index 0000000..02a7569 --- /dev/null +++ b/Filtering/vtkUnstructuredGrid.cxx @@ -0,0 +1,1448 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGrid.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCellLinks.h" +#include "vtkConvexPointSet.h" +#include "vtkEmptyCell.h" +#include "vtkGenericCell.h" +#include "vtkHexahedron.h" +#include "vtkIdTypeArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkObjectFactory.h" +#include "vtkPixel.h" +#include "vtkPointData.h" +#include "vtkPolyLine.h" +#include "vtkPolyVertex.h" +#include "vtkPolygon.h" +#include "vtkPyramid.h" +#include "vtkPentagonalPrism.h" +#include "vtkHexagonalPrism.h" +#include "vtkQuad.h" +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticHexahedron.h" +#include "vtkQuadraticWedge.h" +#include "vtkQuadraticPyramid.h" +#include "vtkQuadraticQuad.h" +#include "vtkQuadraticTetra.h" +#include "vtkQuadraticTriangle.h" +#include "vtkTetra.h" +#include "vtkTriangle.h" +#include "vtkTriangleStrip.h" +#include "vtkUnsignedCharArray.h" +#include "vtkVertex.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" + +vtkCxxRevisionMacro(vtkUnstructuredGrid, "$Revision: 1.8.6.1 $"); +vtkStandardNewMacro(vtkUnstructuredGrid); + +vtkUnstructuredGrid::vtkUnstructuredGrid () +{ + this->Vertex = NULL; + this->PolyVertex = NULL; + this->Line = NULL; + this->PolyLine = NULL; + this->Triangle = NULL; + this->TriangleStrip = NULL; + this->Pixel = NULL; + this->Quad = NULL; + this->Polygon = NULL; + this->Tetra = NULL; + this->Voxel = NULL; + this->Hexahedron = NULL; + this->Wedge = NULL; + this->Pyramid = NULL; + this->PentagonalPrism = NULL; + this->HexagonalPrism = NULL; + this->QuadraticEdge = NULL; + this->QuadraticTriangle =NULL; + this->QuadraticQuad = NULL; + this->QuadraticTetra = NULL; + this->QuadraticHexahedron = NULL; + this->QuadraticWedge = NULL; + this->QuadraticPyramid = NULL; + this->ConvexPointSet = NULL; + this->EmptyCell = NULL; + + + this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_PIECES_EXTENT); + this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0); + + this->Connectivity = NULL; + this->Links = NULL; + this->Types = NULL; + this->Locations = NULL; + this->Allocate(1000,1000); +} + +//---------------------------------------------------------------------------- +// Allocate memory space for data insertion. Execute this method before +// inserting any cells into object. +void vtkUnstructuredGrid::Allocate (vtkIdType numCells, int extSize) +{ + if ( numCells < 1 ) + { + numCells = 1000; + } + if ( extSize < 1 ) + { + extSize = 1000; + } + + if ( this->Connectivity ) + { + this->Connectivity->UnRegister(this); + } + this->Connectivity = vtkCellArray::New(); + this->Connectivity->Allocate(numCells,4*extSize); + this->Connectivity->Register(this); + this->Connectivity->Delete(); + + if ( this->Types ) + { + this->Types->UnRegister(this); + } + this->Types = vtkUnsignedCharArray::New(); + this->Types->Allocate(numCells,extSize); + this->Types->Register(this); + this->Types->Delete(); + + if ( this->Locations ) + { + this->Locations->UnRegister(this); + } + this->Locations = vtkIdTypeArray::New(); + this->Locations->Allocate(numCells,extSize); + this->Locations->Register(this); + this->Locations->Delete(); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid::~vtkUnstructuredGrid() +{ + vtkUnstructuredGrid::Initialize(); + if(this->Vertex) + { + this->Vertex->Delete(); + } + if(this->PolyVertex) + { + this->PolyVertex->Delete(); + } + if(this->Line) + { + this->Line->Delete(); + } + if(this->PolyLine) + { + this->PolyLine->Delete(); + } + if(this->Triangle) + { + this->Triangle->Delete(); + } + if(this->TriangleStrip) + { + this->TriangleStrip->Delete(); + } + if(this->Pixel) + { + this->Pixel->Delete(); + } + if(this->Quad) + { + this->Quad->Delete(); + } + if(this->Polygon) + { + this->Polygon->Delete(); + } + if(this->Tetra) + { + this->Tetra->Delete(); + } + if(this->Voxel) + { + this->Voxel->Delete(); + } + if(this->Hexahedron) + { + this->Hexahedron->Delete(); + } + if(this->Wedge) + { + this->Wedge->Delete(); + } + if(this->Pyramid) + { + this->Pyramid->Delete(); + } + if(this->PentagonalPrism) + { + this->PentagonalPrism->Delete(); + } + if(this->HexagonalPrism) + { + this->HexagonalPrism->Delete(); + } + if(this->QuadraticEdge) + { + this->QuadraticEdge->Delete(); + } + if(this->QuadraticTriangle) + { + this->QuadraticTriangle->Delete(); + } + if(this->QuadraticQuad) + { + this->QuadraticQuad->Delete(); + } + if(this->QuadraticTetra) + { + this->QuadraticTetra->Delete(); + } + if(this->QuadraticHexahedron) + { + this->QuadraticHexahedron->Delete(); + } + if(this->QuadraticWedge) + { + this->QuadraticWedge->Delete(); + } + if(this->QuadraticPyramid) + { + this->QuadraticPyramid->Delete(); + } + if(this->ConvexPointSet) + { + this->ConvexPointSet->Delete(); + } + if(this->EmptyCell) + { + this->EmptyCell->Delete(); + } +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGrid::GetPiece() +{ + return this->Information->Get(vtkDataObject::DATA_PIECE_NUMBER()); +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGrid::GetNumberOfPieces() +{ + return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_PIECES()); +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGrid::GetGhostLevel() +{ + return this->Information->Get(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS()); +} + +//---------------------------------------------------------------------------- +// Copy the geometric and topological structure of an input unstructured grid. +void vtkUnstructuredGrid::CopyStructure(vtkDataSet *ds) +{ + vtkUnstructuredGrid *ug=(vtkUnstructuredGrid *)ds; + vtkPointSet::CopyStructure(ds); + + if (this->Connectivity != ug->Connectivity) + { + if ( this->Connectivity ) + { + this->Connectivity->UnRegister(this); + } + this->Connectivity = ug->Connectivity; + if (this->Connectivity) + { + this->Connectivity->Register(this); + } + } + + if (this->Links != ug->Links) + { + if ( this->Links ) + { + this->Links->UnRegister(this); + } + this->Links = ug->Links; + if (this->Links) + { + this->Links->Register(this); + } + } + + if (this->Types != ug->Types) + { + if ( this->Types ) + { + this->Types->UnRegister(this); + } + this->Types = ug->Types; + if (this->Types) + { + this->Types->Register(this); + } + } + + if (this->Locations != ug->Locations) + { + if ( this->Locations ) + { + this->Locations->UnRegister(this); + } + this->Locations = ug->Locations; + if (this->Locations) + { + this->Locations->Register(this); + } + } + + // Reset this information to maintain the functionality that was present when + // CopyStructure called Initialize, which incorrectly wiped out attribute + // data. Someone MIGHT argue that this isn't the right thing to do. + this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 0); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::Initialize() +{ + vtkPointSet::Initialize(); + + if ( this->Connectivity ) + { + this->Connectivity->UnRegister(this); + this->Connectivity = NULL; + } + + if ( this->Links ) + { + this->Links->UnRegister(this); + this->Links = NULL; + } + + if ( this->Types ) + { + this->Types->UnRegister(this); + this->Types = NULL; + } + + if ( this->Locations ) + { + this->Locations->UnRegister(this); + this->Locations = NULL; + } + + if(this->Information) + { + this->Information->Set(vtkDataObject::DATA_PIECE_NUMBER(), -1); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_PIECES(), 0); + this->Information->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 0); + } +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGrid::GetCellType(vtkIdType cellId) +{ + + vtkDebugMacro(<< "Returning cell type " << (int)this->Types->GetValue(cellId)); + return (int)this->Types->GetValue(cellId); +} + +//---------------------------------------------------------------------------- +vtkCell *vtkUnstructuredGrid::GetCell(vtkIdType cellId) +{ + int i; + int loc; + vtkCell *cell = NULL; + vtkIdType *pts, numPts; + + switch ((int)this->Types->GetValue(cellId)) + { + case VTK_VERTEX: + if(!this->Vertex) + { + this->Vertex = vtkVertex::New(); + } + cell = this->Vertex; + break; + + case VTK_POLY_VERTEX: + if(!this->PolyVertex) + { + this->PolyVertex = vtkPolyVertex::New(); + } + cell = this->PolyVertex; + break; + + case VTK_LINE: + if(!this->Line) + { + this->Line = vtkLine::New(); + } + cell = this->Line; + break; + + case VTK_POLY_LINE: + if(!this->PolyLine) + { + this->PolyLine = vtkPolyLine::New(); + } + cell = this->PolyLine; + break; + + case VTK_TRIANGLE: + if(!this->Triangle) + { + this->Triangle = vtkTriangle::New(); + } + cell = this->Triangle; + break; + + case VTK_TRIANGLE_STRIP: + if(!this->TriangleStrip) + { + this->TriangleStrip = vtkTriangleStrip::New(); + } + cell = this->TriangleStrip; + break; + + case VTK_PIXEL: + if(!this->Pixel) + { + this->Pixel = vtkPixel::New(); + } + cell = this->Pixel; + break; + + case VTK_QUAD: + if(!this->Quad) + { + this->Quad = vtkQuad::New(); + } + cell = this->Quad; + break; + + case VTK_POLYGON: + if(!this->Polygon) + { + this->Polygon = vtkPolygon::New(); + } + cell = this->Polygon; + break; + + case VTK_TETRA: + if(!this->Tetra) + { + this->Tetra = vtkTetra::New(); + } + cell = this->Tetra; + break; + + case VTK_VOXEL: + if(!this->Voxel) + { + this->Voxel = vtkVoxel::New(); + } + cell = this->Voxel; + break; + + case VTK_HEXAHEDRON: + if(!this->Hexahedron) + { + this->Hexahedron = vtkHexahedron::New(); + } + cell = this->Hexahedron; + break; + + case VTK_WEDGE: + if(!this->Wedge) + { + this->Wedge = vtkWedge::New(); + } + cell = this->Wedge; + break; + + case VTK_PYRAMID: + if(!this->Pyramid) + { + this->Pyramid = vtkPyramid::New(); + } + cell = this->Pyramid; + break; + + case VTK_PENTAGONAL_PRISM: + if(!this->PentagonalPrism) + { + this->PentagonalPrism = vtkPentagonalPrism::New(); + } + cell = this->PentagonalPrism; + break; + + case VTK_HEXAGONAL_PRISM: + if(!this->HexagonalPrism) + { + this->HexagonalPrism = vtkHexagonalPrism::New(); + } + cell = this->HexagonalPrism; + break; + + case VTK_QUADRATIC_EDGE: + if(!this->QuadraticEdge) + { + this->QuadraticEdge = vtkQuadraticEdge::New(); + } + cell = this->QuadraticEdge; + break; + + case VTK_QUADRATIC_TRIANGLE: + if(!this->QuadraticTriangle) + { + this->QuadraticTriangle = vtkQuadraticTriangle::New(); + } + cell = this->QuadraticTriangle; + break; + + case VTK_QUADRATIC_QUAD: + if(!this->QuadraticQuad) + { + this->QuadraticQuad = vtkQuadraticQuad::New(); + } + cell = this->QuadraticQuad; + break; + + case VTK_QUADRATIC_TETRA: + if(!this->QuadraticTetra) + { + this->QuadraticTetra = vtkQuadraticTetra::New(); + } + cell = this->QuadraticTetra; + break; + + case VTK_QUADRATIC_HEXAHEDRON: + if(!this->QuadraticHexahedron) + { + this->QuadraticHexahedron = vtkQuadraticHexahedron::New(); + } + cell = this->QuadraticHexahedron; + break; + + case VTK_QUADRATIC_WEDGE: + if(!this->QuadraticWedge) + { + this->QuadraticWedge = vtkQuadraticWedge::New(); + } + cell = this->QuadraticWedge; + break; + + case VTK_QUADRATIC_PYRAMID: + if(!this->QuadraticPyramid) + { + this->QuadraticPyramid = vtkQuadraticPyramid::New(); + } + cell = this->QuadraticPyramid; + break; + + case VTK_CONVEX_POINT_SET: + if(!this->ConvexPointSet) + { + this->ConvexPointSet = vtkConvexPointSet::New(); + } + cell = this->ConvexPointSet; + break; + + case VTK_EMPTY_CELL: + if(!this->EmptyCell) + { + this->EmptyCell = vtkEmptyCell::New(); + } + cell = this->EmptyCell; + break; + } + + if( !cell ) + { + return NULL; + } + + loc = this->Locations->GetValue(cellId); + vtkDebugMacro(<< "location = " << loc); + this->Connectivity->GetCell(loc,numPts,pts); + + cell->PointIds->SetNumberOfIds(numPts); + cell->Points->SetNumberOfPoints(numPts); + + for (i=0; iPointIds->SetId(i,pts[i]); + cell->Points->SetPoint(i,this->Points->GetPoint(pts[i])); + } + + if ( cell->RequiresInitialization() ) + { + cell->Initialize(); //hack to make sure it retriangulates + } + + return cell; +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::GetCell(vtkIdType cellId, vtkGenericCell *cell) +{ + int i; + int loc; + double x[3]; + vtkIdType *pts, numPts; + + cell->SetCellType((int)Types->GetValue(cellId)); + + loc = this->Locations->GetValue(cellId); + this->Connectivity->GetCell(loc,numPts,pts); + + cell->PointIds->SetNumberOfIds(numPts); + cell->Points->SetNumberOfPoints(numPts); + + for (i=0; iPointIds->SetId(i,pts[i]); + this->Points->GetPoint(pts[i], x); + cell->Points->SetPoint(i, x); + } + + if ( cell->RequiresInitialization() ) + { + cell->Initialize(); //hack to make sure it retriangulates + } +} + +//---------------------------------------------------------------------------- +// Fast implementation of GetCellBounds(). Bounds are calculated without +// constructing a cell. +void vtkUnstructuredGrid::GetCellBounds(vtkIdType cellId, double bounds[6]) +{ + int i; + int loc; + double x[3]; + vtkIdType *pts, numPts; + + loc = this->Locations->GetValue(cellId); + this->Connectivity->GetCell(loc,numPts,pts); + + // carefully compute the bounds + if (numPts) + { + this->Points->GetPoint( pts[0], x ); + bounds[0] = x[0]; + bounds[2] = x[1]; + bounds[4] = x[2]; + bounds[1] = x[0]; + bounds[3] = x[1]; + bounds[5] = x[2]; + for (i=1; i < numPts; i++) + { + this->Points->GetPoint( pts[i], x ); + bounds[0] = (x[0] < bounds[0] ? x[0] : bounds[0]); + bounds[1] = (x[0] > bounds[1] ? x[0] : bounds[1]); + bounds[2] = (x[1] < bounds[2] ? x[1] : bounds[2]); + bounds[3] = (x[1] > bounds[3] ? x[1] : bounds[3]); + bounds[4] = (x[2] < bounds[4] ? x[2] : bounds[4]); + bounds[5] = (x[2] > bounds[5] ? x[2] : bounds[5]); + } + } + else + { + vtkMath::UninitializeBounds(bounds); + } + +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGrid::GetMaxCellSize() +{ + if (this->Connectivity) + { + return this->Connectivity->GetMaxCellSize(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkUnstructuredGrid::GetNumberOfCells() +{ + vtkDebugMacro(<< "NUMBER OF CELLS = " << (this->Connectivity ? this->Connectivity->GetNumberOfCells() : 0)); + return (this->Connectivity ? this->Connectivity->GetNumberOfCells() : 0); +} + +//---------------------------------------------------------------------------- +// Insert/create cell in object by type and list of point ids defining +// cell topology. +vtkIdType vtkUnstructuredGrid::InsertNextCell(int type, vtkIdList *ptIds) +{ + vtkIdType npts = ptIds->GetNumberOfIds(); + // insert connectivity + this->Connectivity->InsertNextCell(ptIds); + // insert type and storage information + vtkDebugMacro(<< "insert location " + << this->Connectivity->GetInsertLocation(npts)); + this->Locations->InsertNextValue(this->Connectivity->GetInsertLocation(npts)); + return this->Types->InsertNextValue((unsigned char) type); + +} + +//---------------------------------------------------------------------------- +// Insert/create cell in object by type and list of point ids defining +// cell topology. +vtkIdType vtkUnstructuredGrid::InsertNextCell(int type, vtkIdType npts, + vtkIdType *pts) +{ + // insert connectivity + this->Connectivity->InsertNextCell(npts,pts); + // insert type and storage information + vtkDebugMacro(<< "insert location " + << this->Connectivity->GetInsertLocation(npts)); + this->Locations->InsertNextValue(this->Connectivity->GetInsertLocation(npts)); + return this->Types->InsertNextValue((unsigned char) type); + +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::SetCells(int type, vtkCellArray *cells) +{ + int i; + vtkIdType *pts = 0; + vtkIdType npts = 0; + + // set cell array + if ( this->Connectivity ) + { + this->Connectivity->UnRegister(this); + } + this->Connectivity = cells; + if ( this->Connectivity ) + { + this->Connectivity->Register(this); + } + + // see whether there are cell types available + + if ( this->Types) + { + this->Types->UnRegister(this); + } + this->Types = vtkUnsignedCharArray::New(); + this->Types->Allocate(cells->GetNumberOfCells(),1000); + this->Types->Register(this); + this->Types->Delete(); + + if ( this->Locations) + { + this->Locations->UnRegister(this); + } + this->Locations = vtkIdTypeArray::New(); + this->Locations->Allocate(cells->GetNumberOfCells(),1000); + this->Locations->Register(this); + this->Locations->Delete(); + + // build types + for (i=0, cells->InitTraversal(); cells->GetNextCell(npts,pts); i++) + { + this->Types->InsertNextValue((unsigned char) type); + this->Locations->InsertNextValue(cells->GetTraversalLocation(npts)); + } +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::SetCells(int *types, vtkCellArray *cells) +{ + int i; + vtkIdType *pts = 0; + vtkIdType npts = 0; + + // set cell array + if ( this->Connectivity ) + { + this->Connectivity->UnRegister(this); + } + this->Connectivity = cells; + if ( this->Connectivity ) + { + this->Connectivity->Register(this); + } + + // see whether there are cell types available + + if ( this->Types) + { + this->Types->UnRegister(this); + } + this->Types = vtkUnsignedCharArray::New(); + this->Types->Allocate(cells->GetNumberOfCells(),1000); + this->Types->Register(this); + this->Types->Delete(); + + if ( this->Locations) + { + this->Locations->UnRegister(this); + } + this->Locations = vtkIdTypeArray::New(); + this->Locations->Allocate(cells->GetNumberOfCells(),1000); + this->Locations->Register(this); + this->Locations->Delete(); + + // build types + for (i=0, cells->InitTraversal(); cells->GetNextCell(npts,pts); i++) + { + this->Types->InsertNextValue((unsigned char) types[i]); + this->Locations->InsertNextValue(cells->GetTraversalLocation(npts)); + } +} + + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::SetCells(vtkUnsignedCharArray *cellTypes, + vtkIdTypeArray *cellLocations, + vtkCellArray *cells) +{ + // set cell array + if ( this->Connectivity ) + { + this->Connectivity->UnRegister(this); + } + this->Connectivity = cells; + if ( this->Connectivity ) + { + this->Connectivity->Register(this); + } + + // see whether there are cell types available + + if ( this->Types ) + { + this->Types->UnRegister(this); + } + this->Types = cellTypes; + if ( this->Types ) + { + this->Types->Register(this); + } + + if ( this->Locations ) + { + this->Locations->UnRegister(this); + } + this->Locations = cellLocations; + if ( this->Locations ) + { + this->Locations->Register(this); + } + +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::BuildLinks() +{ + this->Links = vtkCellLinks::New(); + this->Links->Allocate(this->GetNumberOfPoints()); + this->Links->Register(this); + this->Links->BuildLinks(this, this->Connectivity); + this->Links->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::GetCellPoints(vtkIdType cellId, vtkIdList *ptIds) +{ + int i; + int loc; + vtkIdType *pts, numPts; + + loc = this->Locations->GetValue(cellId); + this->Connectivity->GetCell(loc,numPts,pts); + ptIds->SetNumberOfIds(numPts); + for (i=0; iSetId(i,pts[i]); + } + +} + +//---------------------------------------------------------------------------- +// Return a pointer to a list of point ids defining cell. (More efficient than alternative +// method.) +void vtkUnstructuredGrid::GetCellPoints(vtkIdType cellId, vtkIdType& npts, + vtkIdType* &pts) +{ + int loc; + + loc = this->Locations->GetValue(cellId); + + this->Connectivity->GetCell(loc,npts,pts); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::GetPointCells(vtkIdType ptId, vtkIdList *cellIds) +{ + vtkIdType *cells; + int numCells; + int i; + + if ( ! this->Links ) + { + this->BuildLinks(); + } + cellIds->Reset(); + + numCells = this->Links->GetNcells(ptId); + cells = this->Links->GetCells(ptId); + + cellIds->SetNumberOfIds(numCells); + for (i=0; i < numCells; i++) + { + cellIds->SetId(i,cells[i]); + } +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::Reset() +{ + if ( this->Connectivity ) + { + this->Connectivity->Reset(); + } + if ( this->Links ) + { + this->Links->Reset(); + } + if ( this->Types ) + { + this->Types->Reset(); + } + if ( this->Locations ) + { + this->Locations->Reset(); + } +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::Squeeze() +{ + if ( this->Connectivity ) + { + this->Connectivity->Squeeze(); + } + if ( this->Links ) + { + this->Links->Squeeze(); + } + if ( this->Types ) + { + this->Types->Squeeze(); + } + if ( this->Locations ) + { + this->Locations->Squeeze(); + } + + vtkPointSet::Squeeze(); +} + +//---------------------------------------------------------------------------- +// Remove a reference to a cell in a particular point's link list. You may +// also consider using RemoveCellReference() to remove the references from +// all the cell's points to the cell. This operator does not reallocate +// memory; use the operator ResizeCellList() to do this if necessary. +void vtkUnstructuredGrid::RemoveReferenceToCell(vtkIdType ptId, + vtkIdType cellId) +{ + this->Links->RemoveCellReference(cellId, ptId); +} + +//---------------------------------------------------------------------------- +// Add a reference to a cell in a particular point's link list. (You may also +// consider using AddCellReference() to add the references from all the +// cell's points to the cell.) This operator does not realloc memory; use the +// operator ResizeCellList() to do this if necessary. +void vtkUnstructuredGrid::AddReferenceToCell(vtkIdType ptId, vtkIdType cellId) +{ + this->Links->AddCellReference(cellId, ptId); +} + +//---------------------------------------------------------------------------- +// Resize the list of cells using a particular point. (This operator assumes +// that BuildLinks() has been called.) +void vtkUnstructuredGrid::ResizeCellList(vtkIdType ptId, int size) +{ + this->Links->ResizeCellList(ptId,size); +} + +//---------------------------------------------------------------------------- +// Replace the points defining cell "cellId" with a new set of points. This +// operator is (typically) used when links from points to cells have not been +// built (i.e., BuildLinks() has not been executed). Use the operator +// ReplaceLinkedCell() to replace a cell when cell structure has been built. +void vtkUnstructuredGrid::ReplaceCell(vtkIdType cellId, int npts, + vtkIdType *pts) +{ + int loc; + + loc = this->Locations->GetValue(cellId); + this->Connectivity->ReplaceCell(loc,npts,pts); +} + +//---------------------------------------------------------------------------- +// Add a new cell to the cell data structure (after cell links have been +// built). This method adds the cell and then updates the links from the points +// to the cells. (Memory is allocated as necessary.) +int vtkUnstructuredGrid::InsertNextLinkedCell(int type, int npts, + vtkIdType *pts) +{ + int i, id; + + id = this->InsertNextCell(type,npts,pts); + + for (i=0; iLinks->ResizeCellList(pts[i],1); + this->Links->AddCellReference(id,pts[i]); + } + + return id; +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::GetUpdateExtent(int& piece, int& numPieces, int& ghostLevel) +{ + piece = this->GetUpdatePiece(); + numPieces = this->GetUpdateNumberOfPieces(); + ghostLevel = this->GetUpdateGhostLevel(); +} + +//---------------------------------------------------------------------------- +int* vtkUnstructuredGrid::GetUpdateExtent() +{ + return this->Superclass::GetUpdateExtent(); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::GetUpdateExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1) +{ + this->Superclass::GetUpdateExtent(x0, x1, y0, y1, z0, z1); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::GetUpdateExtent(int extent[6]) +{ + this->Superclass::GetUpdateExtent(extent); +} + +//---------------------------------------------------------------------------- +unsigned long vtkUnstructuredGrid::GetActualMemorySize() +{ + unsigned long size=this->vtkPointSet::GetActualMemorySize(); + if ( this->Connectivity ) + { + size += this->Connectivity->GetActualMemorySize(); + } + + if ( this->Links ) + { + size += this->Links->GetActualMemorySize(); + } + + if ( this->Types ) + { + size += this->Types->GetActualMemorySize(); + } + + if ( this->Locations ) + { + size += this->Locations->GetActualMemorySize(); + } + + return size; +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::ShallowCopy(vtkDataObject *dataObject) +{ + vtkUnstructuredGrid *grid = vtkUnstructuredGrid::SafeDownCast(dataObject); + + if ( grid != NULL ) + { + // I do not know if this is correct but. + + if (this->Connectivity) + { + this->Connectivity->UnRegister(this); + } + this->Connectivity = grid->Connectivity; + if (this->Connectivity) + { + this->Connectivity->Register(this); + } + + if (this->Links) + { + this->Links->Delete(); + } + this->Links = grid->Links; + if (this->Links) + { + this->Links->Register(this); + } + + if (this->Types) + { + this->Types->UnRegister(this); + } + this->Types = grid->Types; + if (this->Types) + { + this->Types->Register(this); + } + + if (this->Locations) + { + this->Locations->UnRegister(this); + } + this->Locations = grid->Locations; + if (this->Locations) + { + this->Locations->Register(this); + } + + } + + // Do superclass + this->vtkPointSet::ShallowCopy(dataObject); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::DeepCopy(vtkDataObject *dataObject) +{ + vtkUnstructuredGrid *grid = vtkUnstructuredGrid::SafeDownCast(dataObject); + + if ( grid != NULL ) + { + if ( this->Connectivity ) + { + this->Connectivity->UnRegister(this); + this->Connectivity = NULL; + } + if (grid->Connectivity) + { + this->Connectivity = vtkCellArray::New(); + this->Connectivity->DeepCopy(grid->Connectivity); + this->Connectivity->Register(this); + this->Connectivity->Delete(); + } + + if ( this->Links ) + { + this->Links->UnRegister(this); + this->Links = NULL; + } + if (grid->Links) + { + this->Links = vtkCellLinks::New(); + this->Links->DeepCopy(grid->Links); + this->Links->Register(this); + this->Links->Delete(); + } + + if ( this->Types ) + { + this->Types->UnRegister(this); + this->Types = NULL; + } + if (grid->Types) + { + this->Types = vtkUnsignedCharArray::New(); + this->Types->DeepCopy(grid->Types); + this->Types->Register(this); + this->Types->Delete(); + } + + if ( this->Locations ) + { + this->Locations->UnRegister(this); + this->Locations = NULL; + } + if (grid->Locations) + { + this->Locations = vtkIdTypeArray::New(); + this->Locations->DeepCopy(grid->Locations); + this->Locations->Register(this); + this->Locations->Delete(); + } + } + + // Do superclass + this->vtkPointSet::DeepCopy(dataObject); +} + + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Pieces: " << this->GetNumberOfPieces() << endl; + os << indent << "Piece: " << this->GetPiece() << endl; + os << indent << "Ghost Level: " << this->GetGhostLevel() << endl; +} + +//---------------------------------------------------------------------------- +// Determine neighbors as follows. Find the (shortest) list of cells that +// uses one of the points in ptIds. For each cell, in the list, see whether +// it contains the other points in the ptIds list. If so, it's a neighbor. +// +void vtkUnstructuredGrid::GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds) +{ + int i, j, k; + int numPts, minNumCells, numCells; + vtkIdType *pts, ptId, *cellPts, *cells; + vtkIdType *minCells = NULL; + int match; + vtkIdType minPtId = 0, npts; + + if ( ! this->Links ) + { + this->BuildLinks(); + } + + cellIds->Reset(); + + //Find the point used by the fewest number of cells + // + numPts = ptIds->GetNumberOfIds(); + pts = ptIds->GetPointer(0); + for (minNumCells=VTK_LARGE_INTEGER,i=0; iLinks->GetNcells(ptId); + cells = this->Links->GetCells(ptId); + if ( numCells < minNumCells ) + { + minNumCells = numCells; + minCells = cells; + minPtId = ptId; + } + } + + if (minNumCells == VTK_LARGE_INTEGER && numPts == 0) { + vtkErrorMacro("input point ids empty."); + minNumCells = 0; + } + //Now for each cell, see if it contains all the points + //in the ptIds list. + for (i=0; iGetCellPoints(minCells[i],npts,cellPts); + for (match=1, j=0; jInsertNextId(minCells[i]); + } + }//if not the reference cell + }//for all candidate cells attached to point +} + + +//---------------------------------------------------------------------------- +int vtkUnstructuredGrid::IsHomogeneous() +{ + unsigned char type; + if (this->Types && this->Types->GetMaxId() >= 0) + { + type = Types->GetValue(0); + for (int cellId = 0; cellId < this->GetNumberOfCells(); cellId++) + { + if (this->Types->GetValue(cellId) != type) + { + return 0; + } + } + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +// Fill container with indices of cells which match given type. +void vtkUnstructuredGrid::GetIdsOfCellsOfType(int type, vtkIdTypeArray *array) +{ + for (int cellId = 0; cellId < this->GetNumberOfCells(); cellId++) + { + if ((int)Types->GetValue(cellId) == type) + { + array->InsertNextValue(cellId); + } + } +} + + +//---------------------------------------------------------------------------- +void vtkUnstructuredGrid::RemoveGhostCells(int level) +{ + vtkUnstructuredGrid* newGrid = vtkUnstructuredGrid::New(); + vtkDataArray* temp; + unsigned char* cellGhostLevels; + + vtkIdType cellId, newCellId; + vtkIdList *cellPts, *pointMap; + vtkIdList *newCellPts; + vtkCell *cell; + vtkPoints *newPoints; + int i, ptId, newId, numPts; + int numCellPts; + double *x; + vtkPointData* pd = this->GetPointData(); + vtkPointData* outPD = newGrid->GetPointData(); + vtkCellData* cd = this->GetCellData(); + vtkCellData* outCD = newGrid->GetCellData(); + + + // Get a pointer to the cell ghost level array. + temp = this->CellData->GetArray("vtkGhostLevels"); + if (temp == NULL) + { + vtkDebugMacro("Could not find cell ghost level array."); + newGrid->Delete(); + return; + } + if ( (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1) + || (temp->GetNumberOfTuples() < this->GetNumberOfCells())) + { + vtkErrorMacro("Poorly formed ghost level array."); + newGrid->Delete(); + return; + } + cellGhostLevels =((vtkUnsignedCharArray*)temp)->GetPointer(0); + + + // Now threshold based on the cell ghost level array. + outPD->CopyAllocate(pd); + outCD->CopyAllocate(cd); + + numPts = this->GetNumberOfPoints(); + newGrid->Allocate(this->GetNumberOfCells()); + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + + pointMap = vtkIdList::New(); //maps old point ids into new + pointMap->SetNumberOfIds(numPts); + for (i=0; i < numPts; i++) + { + pointMap->SetId(i,-1); + } + + + newCellPts = vtkIdList::New(); + + // Check that the scalars of each cell satisfy the threshold criterion + for (cellId=0; cellId < this->GetNumberOfCells(); cellId++) + { + cell = this->GetCell(cellId); + cellPts = cell->GetPointIds(); + numCellPts = cell->GetNumberOfPoints(); + + if ( cellGhostLevels[cellId] < level ) // Keep the cell. + { + for (i=0; i < numCellPts; i++) + { + ptId = cellPts->GetId(i); + if ( (newId = pointMap->GetId(ptId)) < 0 ) + { + x = this->GetPoint(ptId); + newId = newPoints->InsertNextPoint(x); + pointMap->SetId(ptId,newId); + outPD->CopyData(pd,ptId,newId); + } + newCellPts->InsertId(i,newId); + } + newCellId = newGrid->InsertNextCell(cell->GetCellType(),newCellPts); + outCD->CopyData(cd,cellId,newCellId); + newCellPts->Reset(); + } // satisfied thresholding + } // for all cells + + // now clean up / update ourselves + pointMap->Delete(); + newCellPts->Delete(); + + newGrid->SetPoints(newPoints); + newPoints->Delete(); + + this->CopyStructure(newGrid); + this->GetPointData()->ShallowCopy(newGrid->GetPointData()); + this->GetCellData()->ShallowCopy(newGrid->GetCellData()); + newGrid->Delete(); + newGrid = NULL; + + this->Squeeze(); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkUnstructuredGrid::GetData(vtkInformation* info) +{ + return info? vtkUnstructuredGrid::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkUnstructuredGrid::GetData(vtkInformationVector* v, + int i) +{ + return vtkUnstructuredGrid::GetData(v->GetInformationObject(i)); +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +void vtkUnstructuredGrid::GetCellNeighbors(vtkIdType cellId, vtkIdList& ptIds, vtkIdList& cellIds) +{ + this->GetCellNeighbors(cellId, &ptIds, &cellIds); +} +#endif diff --git a/Filtering/vtkUnstructuredGrid.h b/Filtering/vtkUnstructuredGrid.h new file mode 100644 index 0000000..1e690cc --- /dev/null +++ b/Filtering/vtkUnstructuredGrid.h @@ -0,0 +1,232 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGrid - dataset represents arbitrary combinations of all possible cell types +// .SECTION Description +// vtkUnstructuredGrid is a data object that is a concrete implementation +// of vtkDataSet. vtkUnstructuredGrid represents any combinations of any cell +// types. This includes 0D (e.g., points), 1D (e.g., lines, polylines), 2D +// (e.g., triangles, polygons), and 3D (e.g., hexahedron, tetrahedron). + +#ifndef __vtkUnstructuredGrid_h +#define __vtkUnstructuredGrid_h + +#include "vtkPointSet.h" + +class vtkCellArray; +class vtkCellLinks; +class vtkConvexPointSet; +class vtkEmptyCell; +class vtkHexahedron; +class vtkIdList; +class vtkIdTypeArray; +class vtkLine; +class vtkPixel; +class vtkPolyLine; +class vtkPolyVertex; +class vtkPolygon; +class vtkPyramid; +class vtkPentagonalPrism; +class vtkHexagonalPrism; +class vtkQuad; +class vtkQuadraticEdge; +class vtkQuadraticHexahedron; +class vtkQuadraticWedge; +class vtkQuadraticPyramid; +class vtkQuadraticQuad; +class vtkQuadraticTetra; +class vtkQuadraticTriangle; +class vtkTetra; +class vtkTriangle; +class vtkTriangleStrip; +class vtkUnsignedCharArray; +class vtkVertex; +class vtkVoxel; +class vtkWedge; + +class VTK_FILTERING_EXPORT vtkUnstructuredGrid : public vtkPointSet +{ +public: + static vtkUnstructuredGrid *New(); + + vtkTypeRevisionMacro(vtkUnstructuredGrid,vtkPointSet); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Standard vtkDataSet API methods. See vtkDataSet for more information. + int GetDataObjectType() {return VTK_UNSTRUCTURED_GRID;}; + virtual void Allocate(vtkIdType numCells=1000, int extSize=1000); + + // Description: + // Insert/create cell in object by type and list of point ids defining + // cell topology. + vtkIdType InsertNextCell(int type, vtkIdType npts, vtkIdType *pts); + vtkIdType InsertNextCell(int type, vtkIdList *ptIds); + + void Reset(); + virtual void CopyStructure(vtkDataSet *ds); + vtkIdType GetNumberOfCells(); + virtual vtkCell *GetCell(vtkIdType cellId); + virtual void GetCell(vtkIdType cellId, vtkGenericCell *cell); + virtual void GetCellBounds(vtkIdType cellId, double bounds[6]); + virtual void GetCellPoints(vtkIdType cellId, vtkIdList *ptIds); + void GetPointCells(vtkIdType ptId, vtkIdList *cellIds); + + int GetCellType(vtkIdType cellId); + vtkUnsignedCharArray* GetCellTypesArray() { return this->Types; } + vtkIdTypeArray* GetCellLocationsArray() { return this->Locations; } + void Squeeze(); + void Initialize(); + int GetMaxCellSize(); + void BuildLinks(); + vtkCellLinks *GetCellLinks() {return this->Links;}; + virtual void GetCellPoints(vtkIdType cellId, vtkIdType& npts, + vtkIdType* &pts); + + // Description: + // Special methods specific to vtkUnstructuredGrid for defining the cells + // composing the dataset. + void SetCells(int type, vtkCellArray *cells); + void SetCells(int *types, vtkCellArray *cells); + void SetCells(vtkUnsignedCharArray *cellTypes, vtkIdTypeArray *cellLocations, + vtkCellArray *cells); + vtkCellArray *GetCells() {return this->Connectivity;}; + void ReplaceCell(vtkIdType cellId, int npts, vtkIdType *pts); + int InsertNextLinkedCell(int type, int npts, vtkIdType *pts); + void RemoveReferenceToCell(vtkIdType ptId, vtkIdType cellId); + void AddReferenceToCell(vtkIdType ptId, vtkIdType cellId); + void ResizeCellList(vtkIdType ptId, int size); + + // Description: + // Topological inquiry to get all cells using list of points exclusive of + // cell specified (e.g., cellId). + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + virtual void GetCellNeighbors(vtkIdType cellId, vtkIdList *ptIds, + vtkIdList *cellIds); + + // Description: + // For streaming. User/next filter specifies which piece the want updated. + // The source of this poly data has to return exactly this piece. + void GetUpdateExtent(int &piece, int &numPieces, int &ghostLevel); + + // Description: + // We need this here to avoid hiding superclass method + virtual int* GetUpdateExtent(); + virtual void GetUpdateExtent(int& x0, int& x1, int& y0, int& y1, + int& z0, int& z1); + virtual void GetUpdateExtent(int extent[6]); + + // Description: + // Set / Get the piece and the number of pieces. Similar to extent in 3D. + virtual int GetPiece(); + virtual int GetNumberOfPieces(); + + // Description: + // Get the ghost level. + virtual int GetGhostLevel(); + + // Description: + // Return the actual size of the data in kilobytes. This number + // is valid only after the pipeline has updated. The memory size + // returned is guaranteed to be greater than or equal to the + // memory required to represent the data (e.g., extra space in + // arrays, etc. are not included in the return value). THIS METHOD + // IS THREAD SAFE. + unsigned long GetActualMemorySize(); + + // Description: + // Shallow and Deep copy. + virtual void ShallowCopy(vtkDataObject *src); + virtual void DeepCopy(vtkDataObject *src); + + // Description: + // Fill vtkIdTypeArray container with list of cell Ids. This + // method traverses all cells and, for a particular cell type, + // inserts the cell Id into the container. + void GetIdsOfCellsOfType(int type, vtkIdTypeArray *array); + + // Description: + // Traverse cells and determine if cells are all of the same type. + int IsHomogeneous(); + + // Description: + // This method will remove any cell that has a ghost level array value + // greater or equal to level. + void RemoveGhostCells(int level); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkUnstructuredGrid* GetData(vtkInformation* info); + static vtkUnstructuredGrid* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkUnstructuredGrid(); + ~vtkUnstructuredGrid(); + + // used by GetCell method + vtkVertex *Vertex; + vtkPolyVertex *PolyVertex; + vtkLine *Line; + vtkPolyLine *PolyLine; + vtkTriangle *Triangle; + vtkTriangleStrip *TriangleStrip; + vtkPixel *Pixel; + vtkQuad *Quad; + vtkPolygon *Polygon; + vtkTetra *Tetra; + vtkVoxel *Voxel; + vtkHexahedron *Hexahedron; + vtkWedge *Wedge; + vtkPyramid *Pyramid; + vtkPentagonalPrism *PentagonalPrism; + vtkHexagonalPrism *HexagonalPrism; + vtkQuadraticEdge *QuadraticEdge; + vtkQuadraticTriangle *QuadraticTriangle; + vtkQuadraticQuad *QuadraticQuad; + vtkQuadraticTetra *QuadraticTetra; + vtkQuadraticHexahedron *QuadraticHexahedron; + vtkQuadraticWedge *QuadraticWedge; + vtkQuadraticPyramid *QuadraticPyramid; + vtkConvexPointSet *ConvexPointSet; + vtkEmptyCell *EmptyCell; + + // points inherited + // point data (i.e., scalars, vectors, normals, tcoords) inherited + vtkCellArray *Connectivity; + vtkCellLinks *Links; + vtkUnsignedCharArray *Types; + vtkIdTypeArray *Locations; + + private: + // Hide these from the user and the compiler. + + // Description: + // For legacy compatibility. Do not use. + VTK_LEGACY(void GetCellNeighbors(vtkIdType cellId, vtkIdList& ptIds, vtkIdList& cellIds)); + + vtkUnstructuredGrid(const vtkUnstructuredGrid&); // Not implemented. + void operator=(const vtkUnstructuredGrid&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Filtering/vtkUnstructuredGridAlgorithm.cxx b/Filtering/vtkUnstructuredGridAlgorithm.cxx new file mode 100644 index 0000000..86fd6f6 --- /dev/null +++ b/Filtering/vtkUnstructuredGridAlgorithm.cxx @@ -0,0 +1,234 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridAlgorithm.h" + +#include "vtkObjectFactory.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkUnstructuredGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTrivialProducer.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridAlgorithm, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkUnstructuredGridAlgorithm); + +//---------------------------------------------------------------------------- +vtkUnstructuredGridAlgorithm::vtkUnstructuredGridAlgorithm() +{ + // by default assume filters have one input and one output + // subclasses that deviate should modify this setting + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGridAlgorithm::~vtkUnstructuredGridAlgorithm() +{ +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkUnstructuredGridAlgorithm::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkUnstructuredGridAlgorithm::GetOutput(int port) +{ + return vtkUnstructuredGrid::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridAlgorithm::SetOutput(vtkDataObject* d) +{ + this->GetExecutive()->SetOutputData(0, d); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkUnstructuredGridAlgorithm::GetInput(int port) +{ + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkUnstructuredGridAlgorithm::GetUnstructuredGridInput(int port) +{ + return vtkUnstructuredGrid::SafeDownCast(this->GetInput(port)); +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridAlgorithm::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridAlgorithm::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridAlgorithm::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridAlgorithm::RequestInformation( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* vtkNotUsed(outputVector)) +{ + // do nothing let subclasses handle it + return 1; +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridAlgorithm::RequestUpdateExtent( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed(outputVector)) +{ + int numInputPorts = this->GetNumberOfInputPorts(); + for (int i=0; iGetNumberOfInputConnections(i); + for (int j=0; jGetInformationObject(j); + inputInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + } + } + return 1; +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkUnstructuredGridAlgorithm::RequestData( + vtkInformation* request, + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // the default implimentation is to do what the old pipeline did find what + // output is requesting the data, and pass that into ExecuteData + + // which output port did the request come from + int outputPort = + request->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT()); + + // if output port is negative then that means this filter is calling the + // update directly, in that case just assume port 0 + if (outputPort == -1) + { + outputPort = 0; + } + + // get the data object + vtkInformation *outInfo = + outputVector->GetInformationObject(outputPort); + // call ExecuteData + this->ExecuteData( outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + return 1; +} + +//---------------------------------------------------------------------------- +// Assume that any source that implements ExecuteData +// can handle an empty extent. +void vtkUnstructuredGridAlgorithm::ExecuteData(vtkDataObject *output) +{ + // I want to find out if the requested extent is empty. + if (output && this->UpdateExtentIsEmpty(output)) + { + output->Initialize(); + return; + } + + this->Execute(); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridAlgorithm::Execute() +{ + vtkErrorMacro(<< "Definition of Execute() method should be in subclass and you should really use the ExecuteData(vtkInformation *request,...) signature instead"); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridAlgorithm::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridAlgorithm::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridAlgorithm::AddInput(vtkDataObject* input) +{ + this->AddInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridAlgorithm::AddInput(int index, vtkDataObject* input) +{ + if(input) + { + this->AddInputConnection(index, input->GetProducerPort()); + } +} + diff --git a/Filtering/vtkUnstructuredGridAlgorithm.h b/Filtering/vtkUnstructuredGridAlgorithm.h new file mode 100644 index 0000000..533fbbd --- /dev/null +++ b/Filtering/vtkUnstructuredGridAlgorithm.h @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridAlgorithm - Superclass for algorithms that produce only unstructured grid as output +// .SECTION Description + +// vtkUnstructuredGridAlgorithm is a convenience class to make writing algorithms +// easier. It is also designed to help transition old algorithms to the new +// pipeline architecture. Ther are some assumptions and defaults made by this +// class you should be aware of. This class defaults such that your filter +// will have one input port and one output port. If that is not the case +// simply change it with SetNumberOfInputPorts etc. See this classes +// constructor for the default. This class also provides a FillInputPortInfo +// method that by default says that all inputs will be UnstructuredGrid. If that +// isn't the case then please override this method in your subclass. This +// class breaks out the downstream requests into seperate functions such as +// ExecuteData and ExecuteInformation. For new algorithms you should +// implement RequestData( request, inputVec, outputVec) but for older filters +// there is a default implementation that calls the old ExecuteData(output) +// signature, for even older filters that don;t implement ExecuteData the +// default implementation calls the even older Execute() signature. + +#ifndef __vtkUnstructuredGridAlgorithm_h +#define __vtkUnstructuredGridAlgorithm_h + +#include "vtkAlgorithm.h" + +class vtkDataSet; +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkUnstructuredGridAlgorithm : public vtkAlgorithm +{ +public: + static vtkUnstructuredGridAlgorithm *New(); + vtkTypeRevisionMacro(vtkUnstructuredGridAlgorithm,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output data object for a port on this algorithm. + vtkUnstructuredGrid* GetOutput(); + vtkUnstructuredGrid* GetOutput(int); + virtual void SetOutput(vtkDataObject* d); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // this method is not recommended for use, but lots of old style filters + // use it + vtkDataObject *GetInput(int port); + vtkDataObject *GetInput() { return this->GetInput(0); }; + vtkUnstructuredGrid *GetUnstructuredGridInput(int port); + + // Description: + // Set an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline. + // Note that these methods support old-style pipeline connections. + // When writing new code you should use the more general + // vtkAlgorithm::SetInputConnection(). These methods transform the + // input index to the input port index, not an index of a connection + // within a single port. + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + + // Description: + // Add an input of this algorithm. Note that these methods support + // old-style pipeline connections. When writing new code you should + // use the more general vtkAlgorithm::AddInputConnection(). See + // SetInput() for details. + void AddInput(vtkDataObject *); + void AddInput(int, vtkDataObject*); + +protected: + vtkUnstructuredGridAlgorithm(); + ~vtkUnstructuredGridAlgorithm(); + + // convenience method + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // This is called by the superclass. + // This is the method you should override. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // Description: + // This method is the old style execute method + virtual void ExecuteData(vtkDataObject *output); + virtual void Execute(); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkUnstructuredGridAlgorithm(const vtkUnstructuredGridAlgorithm&); // Not implemented. + void operator=(const vtkUnstructuredGridAlgorithm&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkUnstructuredGridSource.cxx b/Filtering/vtkUnstructuredGridSource.cxx new file mode 100644 index 0000000..aa95126 --- /dev/null +++ b/Filtering/vtkUnstructuredGridSource.cxx @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridSource.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridSource, "$Revision: 1.30 $"); + +//---------------------------------------------------------------------------- +vtkUnstructuredGridSource::vtkUnstructuredGridSource() +{ + // A source has no inputs by default. + this->SetNumberOfInputPorts(0); + + this->vtkSource::SetNthOutput(0, vtkUnstructuredGrid::New()); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + this->Outputs[0]->ReleaseData(); + this->Outputs[0]->Delete(); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid *vtkUnstructuredGridSource::GetOutput() +{ + if (this->NumberOfOutputs < 1) + { + return NULL; + } + + return (vtkUnstructuredGrid *)(this->Outputs[0]); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridSource::SetOutput(vtkUnstructuredGrid *output) +{ + this->vtkSource::SetNthOutput(0, output); +} + + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridSource::ComputeInputUpdateExtents(vtkDataObject *data) +{ + int piece, numPieces, ghostLevel; + vtkUnstructuredGrid *output = (vtkUnstructuredGrid *)data; + int idx; + + output->GetUpdateExtent(piece, numPieces, ghostLevel); + + // make sure piece is valid + if (piece < 0 || piece >= numPieces) + { + return; + } + + // just copy the Update extent as default behavior. + for (idx = 0; idx < this->NumberOfInputs; ++idx) + { + if (this->Inputs[idx]) + { + this->Inputs[idx]->SetUpdateExtent(piece, numPieces, ghostLevel); + } + } +} + +vtkUnstructuredGrid *vtkUnstructuredGridSource::GetOutput(int idx) +{ + return static_cast( this->vtkSource::GetOutput(idx) ); +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridSource::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillOutputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkUnstructuredGridSource.h b/Filtering/vtkUnstructuredGridSource.h new file mode 100644 index 0000000..6c19128 --- /dev/null +++ b/Filtering/vtkUnstructuredGridSource.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridSource - abstract class whose subclasses generate unstructured grid data +// .SECTION Description +// vtkUnstructuredGridSource is an abstract class whose subclasses generate +// unstructured grid data. + +// .SECTION See Also +// vtkUnstructuredGridReader + +#ifndef __vtkUnstructuredGridSource_h +#define __vtkUnstructuredGridSource_h + +#include "vtkSource.h" + +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkUnstructuredGridSource : public vtkSource +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridSource,vtkSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this source. + vtkUnstructuredGrid *GetOutput(); + vtkUnstructuredGrid *GetOutput(int idx); + void SetOutput(vtkUnstructuredGrid *output); + +protected: + vtkUnstructuredGridSource(); + ~vtkUnstructuredGridSource() {}; + + // Since the Outputs[0] has the same UpdateExtent format + // as the generic DataObject we can copy the UpdateExtent + // as a default behavior. + void ComputeInputUpdateExtents(vtkDataObject *output); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkUnstructuredGridSource(const vtkUnstructuredGridSource&); // Not implemented. + void operator=(const vtkUnstructuredGridSource&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkUnstructuredGridToPolyDataFilter.cxx b/Filtering/vtkUnstructuredGridToPolyDataFilter.cxx new file mode 100644 index 0000000..a7e652f --- /dev/null +++ b/Filtering/vtkUnstructuredGridToPolyDataFilter.cxx @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridToPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridToPolyDataFilter.h" + +#include "vtkInformation.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridToPolyDataFilter, "$Revision: 1.10 $"); + +//---------------------------------------------------------------------------- +vtkUnstructuredGridToPolyDataFilter::vtkUnstructuredGridToPolyDataFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGridToPolyDataFilter::~vtkUnstructuredGridToPolyDataFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkUnstructuredGridToPolyDataFilter::SetInput(vtkUnstructuredGrid *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkUnstructuredGrid *vtkUnstructuredGridToPolyDataFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkUnstructuredGrid *)(this->Inputs[0]); +} + + +//---------------------------------------------------------------------------- +// Copy the update information across +void vtkUnstructuredGridToPolyDataFilter::ComputeInputUpdateExtents(vtkDataObject *output) +{ + vtkDataObject *input = this->GetInput(); + + if (input) + { + this->vtkPolyDataSource::ComputeInputUpdateExtents(output); + input->RequestExactExtentOn(); + } +} + +//---------------------------------------------------------------------------- +int +vtkUnstructuredGridToPolyDataFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridToPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkUnstructuredGridToPolyDataFilter.h b/Filtering/vtkUnstructuredGridToPolyDataFilter.h new file mode 100644 index 0000000..504002c --- /dev/null +++ b/Filtering/vtkUnstructuredGridToPolyDataFilter.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridToPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridToPolyDataFilter - abstract filter class +// .SECTION Description +// vtkUnstructuredGridToPolyDataFilter is an abstract filter class whose +// subclasses take as input datasets of type vtkUnstructuredGrid and +// generate polygonal data on output. + +// .SECTION See Also +// vtkContourGrid + +#ifndef __vtkUnstructuredGridToPolyDataFilter_h +#define __vtkUnstructuredGridToPolyDataFilter_h + +#include "vtkPolyDataSource.h" + +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkUnstructuredGridToPolyDataFilter : public vtkPolyDataSource +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridToPolyDataFilter,vtkPolyDataSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkUnstructuredGrid *input); + vtkUnstructuredGrid *GetInput(); + + // Description: + // Do not let datasets return more than requested. + virtual void ComputeInputUpdateExtents( vtkDataObject *output ); + +protected: + vtkUnstructuredGridToPolyDataFilter(); + ~vtkUnstructuredGridToPolyDataFilter(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkUnstructuredGridToPolyDataFilter(const vtkUnstructuredGridToPolyDataFilter&); // Not implemented. + void operator=(const vtkUnstructuredGridToPolyDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkUnstructuredGridToUnstructuredGridFilter.cxx b/Filtering/vtkUnstructuredGridToUnstructuredGridFilter.cxx new file mode 100644 index 0000000..4207c60 --- /dev/null +++ b/Filtering/vtkUnstructuredGridToUnstructuredGridFilter.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridToUnstructuredGridFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridToUnstructuredGridFilter.h" + +#include "vtkInformation.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridToUnstructuredGridFilter, "$Revision: 1.15 $"); + +//---------------------------------------------------------------------------- +vtkUnstructuredGridToUnstructuredGridFilter::vtkUnstructuredGridToUnstructuredGridFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGridToUnstructuredGridFilter::~vtkUnstructuredGridToUnstructuredGridFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkUnstructuredGridToUnstructuredGridFilter::SetInput(vtkUnstructuredGrid *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkUnstructuredGrid *vtkUnstructuredGridToUnstructuredGridFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkUnstructuredGrid *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +int +vtkUnstructuredGridToUnstructuredGridFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridToUnstructuredGridFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkUnstructuredGridToUnstructuredGridFilter.h b/Filtering/vtkUnstructuredGridToUnstructuredGridFilter.h new file mode 100644 index 0000000..9656935 --- /dev/null +++ b/Filtering/vtkUnstructuredGridToUnstructuredGridFilter.h @@ -0,0 +1,49 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridToUnstructuredGridFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridToUnstructuredGridFilter - abstract filter class +// .SECTION Description + +// .SECTION See Also +// vtkExtractGrid + +#ifndef __vtkUnstructuredGridToUnstructuredGridFilter_h +#define __vtkUnstructuredGridToUnstructuredGridFilter_h + +#include "vtkUnstructuredGridSource.h" + +class VTK_FILTERING_EXPORT vtkUnstructuredGridToUnstructuredGridFilter : public vtkUnstructuredGridSource +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridToUnstructuredGridFilter,vtkUnstructuredGridSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input Grid or filter. + void SetInput(vtkUnstructuredGrid *input); + vtkUnstructuredGrid *GetInput(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +protected: + vtkUnstructuredGridToUnstructuredGridFilter(); + ~vtkUnstructuredGridToUnstructuredGridFilter(); +private: + vtkUnstructuredGridToUnstructuredGridFilter(const vtkUnstructuredGridToUnstructuredGridFilter&); // Not implemented. + void operator=(const vtkUnstructuredGridToUnstructuredGridFilter&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkVertex.cxx b/Filtering/vtkVertex.cxx new file mode 100644 index 0000000..f272e1a --- /dev/null +++ b/Filtering/vtkVertex.cxx @@ -0,0 +1,264 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVertex.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVertex.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkVertex, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkVertex); + +//---------------------------------------------------------------------------- +// Construct the vertex with a single point. +vtkVertex::vtkVertex() +{ + this->Points->SetNumberOfPoints(1); + this->PointIds->SetNumberOfIds(1); + for (int i = 0; i < 1; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } +} + +//---------------------------------------------------------------------------- +// Make a new vtkVertex object with the same information as this object. +int vtkVertex::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + double X[3]; + + subId = 0; + pcoords[1] = pcoords[2] = 0.0; + + this->Points->GetPoint(0, X); + if (closestPoint) + { + closestPoint[0] = X[0]; closestPoint[1] = X[1]; closestPoint[2] = X[2]; + } + + dist2 = vtkMath::Distance2BetweenPoints(X,x); + weights[0] = 1.0; + + if (dist2 == 0.0) + { + pcoords[0] = 0.0; + return 1; + } + else + { + pcoords[0] = -10.0; + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkVertex::EvaluateLocation(int& vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], double x[3], + double *weights) +{ + this->Points->GetPoint(0, x); + + weights[0] = 1.0; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates of a point, return the closest cell boundary, +// and whether the point is inside or outside of the cell. The cell boundary +// is defined by a list of points (pts) that specify a vertex (1D cell). +// If the return value of the method is != 0, then the point is inside the cell. +int vtkVertex::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + + pts->SetNumberOfIds(1); + pts->SetId(0,this->PointIds->GetId(0)); + + if ( pcoords[0] != 0.0 ) + { + return 0; + } + else + { + return 1; + } + +} + +//---------------------------------------------------------------------------- +// Generate contouring primitives. The scalar list cellScalars are +// scalar values at each cell point. The point locator is essentially a +// points list that merges points as they are inserted (i.e., prevents +// duplicates). +void vtkVertex::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *vtkNotUsed(lines), + vtkCellArray *vtkNotUsed(polys), + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + if ( value == cellScalars->GetComponent(0,0) ) + { + int newCellId; + vtkIdType pts[1]; + pts[0] = locator->InsertNextPoint(this->Points->GetPoint(0)); + if ( outPd ) + { + outPd->CopyData(inPd,this->PointIds->GetId(0),pts[0]); + } + newCellId = verts->InsertNextCell(1,pts); + outCd->CopyData(inCd,cellId,newCellId); + } +} + +//---------------------------------------------------------------------------- +// Intersect with a ray. Return parametric coordinates (both line and cell) +// and global intersection coordinates, given ray definition and tolerance. +// The method returns non-zero value if intersection occurs. +int vtkVertex::IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId) +{ + int i; + double X[3], ray[3], rayFactor, projXYZ[3]; + + subId = 0; + pcoords[1] = pcoords[2] = 0.0; + + this->Points->GetPoint(0, X); + + for (i=0; i<3; i++) + { + ray[i] = p2[i] - p1[i]; + } + if (( rayFactor = vtkMath::Dot(ray,ray)) == 0.0 ) + { + return 0; + } + // + // Project each point onto ray. Determine whether point is within tolerance. + // + t = (ray[0]*(X[0]-p1[0]) + ray[1]*(X[1]-p1[1]) + ray[2]*(X[2]-p1[2])) + / rayFactor; + + if ( t >= 0.0 && t <= 1.0 ) + { + for (i=0; i<3; i++) + { + projXYZ[i] = p1[i] + t*ray[i]; + if ( fabs(X[i]-projXYZ[i]) > tol ) + { + break; + } + } + + if ( i > 2 ) // within tolerance + { + pcoords[0] = 0.0; + x[0] = X[0]; x[1] = X[1]; x[2] = X[2]; + return 1; + } + } + + pcoords[0] = -10.0; + return 0; +} + +//---------------------------------------------------------------------------- +// Triangulate the vertex. This method fills pts and ptIds with information +// from the only point in the vertex. +int vtkVertex::Triangulate(int vtkNotUsed(index),vtkIdList *ptIds, + vtkPoints *pts) +{ + pts->Reset(); + ptIds->Reset(); + pts->InsertPoint(0,this->Points->GetPoint(0)); + ptIds->InsertId(0,this->PointIds->GetId(0)); + + return 1; +} + +//---------------------------------------------------------------------------- +// Get the derivative of the vertex. Returns (0.0, 0.0, 0.0) for all +// dimensions. +void vtkVertex::Derivatives(int vtkNotUsed(subId), + double vtkNotUsed(pcoords)[3], + double *vtkNotUsed(values), + int dim, double *derivs) +{ + int i, idx; + + for (i=0; iGetComponent(0,0); + + if ( ( !insideOut && s > value) || (insideOut && s <= value) ) + { + this->Points->GetPoint(0, x); + if ( locator->InsertUniquePoint(x, pts[0]) ) + { + outPd->CopyData(inPd,this->PointIds->GetId(0),pts[0]); + } + newCellId = verts->InsertNextCell(1,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + +} + +//---------------------------------------------------------------------------- +// Compute interpolation functions +// +void vtkVertex::InterpolationFunctions(double vtkNotUsed(pcoords)[3], + double weights[1]) +{ + weights[0] = 1.0; +} + +//---------------------------------------------------------------------------- +static double vtkVertexCellPCoords[3] = {0.0,0.0,0.0}; +double *vtkVertex::GetParametricCoords() +{ + return vtkVertexCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkVertex::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Filtering/vtkVertex.h b/Filtering/vtkVertex.h new file mode 100644 index 0000000..449bd28 --- /dev/null +++ b/Filtering/vtkVertex.h @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVertex.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVertex - a cell that represents a 3D point +// .SECTION Description +// vtkVertex is a concrete implementation of vtkCell to represent a 3D point. + +#ifndef __vtkVertex_h +#define __vtkVertex_h + +#include "vtkCell.h" + +class VTK_FILTERING_EXPORT vtkVertex : public vtkCell +{ +public: + static vtkVertex *New(); + vtkTypeRevisionMacro(vtkVertex,vtkCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Make a new vtkVertex object with the same information as this object. + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_VERTEX;}; + int GetCellDimension() {return 0;}; + int GetNumberOfEdges() {return 0;}; + int GetNumberOfFaces() {return 0;}; + vtkCell *GetEdge(int) {return 0;}; + vtkCell *GetFace(int) {return 0;}; + void Clip(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *pts, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd, + int insideOut); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + virtual double *GetParametricCoords(); + + // Description: + // Given parametric coordinates of a point, return the closest cell + // boundary, and whether the point is inside or outside of the cell. The + // cell boundary is defined by a list of points (pts) that specify a vertex + // (1D cell). If the return value of the method is != 0, then the point is + // inside the cell. + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + + // Description: + // Generate contouring primitives. The scalar list cellScalars are + // scalar values at each cell point. The point locator is essentially a + // points list that merges points as they are inserted (i.e., prevents + // duplicates). + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts1, + vtkCellArray *lines, vtkCellArray *verts2, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + + // Description: + // Return the center of the triangle in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Intersect with a ray. Return parametric coordinates (both line and cell) + // and global intersection coordinates, given ray definition and tolerance. + // The method returns non-zero value if intersection occurs. + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + + // Description: + // Triangulate the vertex. This method fills pts and ptIds with information + // from the only point in the vertex. + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + + // Description: + // Get the derivative of the vertex. Returns (0.0, 0.0, 0.0) for all + // dimensions. + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + + // Description: + // Vertex specific methods. + static void InterpolationFunctions(double pcoords[3], double weights[1]); + +protected: + vtkVertex(); + ~vtkVertex() {}; + +private: + vtkVertex(const vtkVertex&); // Not implemented. + void operator=(const vtkVertex&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline int vtkVertex::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = pcoords[2] = 0.0; + return 0; +} + +#endif + + diff --git a/Filtering/vtkViewDependentErrorMetric.cxx b/Filtering/vtkViewDependentErrorMetric.cxx new file mode 100644 index 0000000..38d7940 --- /dev/null +++ b/Filtering/vtkViewDependentErrorMetric.cxx @@ -0,0 +1,221 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkViewDependentErrorMetric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkViewDependentErrorMetric.h" + +#include "vtkObjectFactory.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericDataSet.h" +#include "vtkMath.h" +#include +#include "vtkCoordinate.h" +#include "vtkViewport.h" + +vtkCxxRevisionMacro(vtkViewDependentErrorMetric,"$Revision: 1.7 $"); +vtkStandardNewMacro(vtkViewDependentErrorMetric); + +//----------------------------------------------------------------------------- +vtkViewDependentErrorMetric::vtkViewDependentErrorMetric() +{ + this->PixelTolerance = 0.25; // arbitrary positive value + this->Viewport = 0; + this->Coordinate = vtkCoordinate::New(); + this->Coordinate->SetCoordinateSystemToWorld(); +} + +//----------------------------------------------------------------------------- +vtkViewDependentErrorMetric::~vtkViewDependentErrorMetric() +{ + this->Coordinate->Delete(); +} + +//----------------------------------------------------------------------------- +// Description: +// Set the squared screen-based geometric accuracy measured in pixels. +// Subdivision will be required if the square distance between the projection +// of the real point and the straight line passing through the projection +// of the vertices of the edge is greater than `value'. +// For instance, 0.25 will give better result than 1. +// \pre positive_value: value>0 +void vtkViewDependentErrorMetric::SetPixelTolerance(double value) +{ + assert("pre: positive_value" && value>0); + if(this->PixelTolerance!=value) + { + this->PixelTolerance=value; + this->Modified(); + } +} + +//----------------------------------------------------------------------------- +// Avoid reference loop +void vtkViewDependentErrorMetric::SetViewport(vtkViewport *viewport) +{ + if(this->Viewport!=viewport) + { + this->Viewport = viewport; + this->Modified(); + } +} + +//----------------------------------------------------------------------------- +int vtkViewDependentErrorMetric::RequiresEdgeSubdivision(double *leftPoint, + double *midPoint, + double *rightPoint, + double vtkNotUsed(alpha)) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); +// assert("pre: clamped_alpha" && alpha>0 && alpha<1); // or else true + if( this->GenericCell->IsGeometryLinear() ) + { + //don't need to do anything: + return 0; + } +#if 0 + if( !this->RayFrustumIntersection(leftPoint,rightPoint,frustum) && !this->PointFrustumIntersection(midPoint,frustum)) + { + // not in the frustum, don't need subdivision + return 0; + } +#endif + + // Get the projection of the left, mid and right points + double leftProjPoint[2]; + double midProjPoint[2]; +// double rightProjPoint[2]; + + this->Coordinate->SetValue(leftPoint); + double *pix = this->Coordinate->GetComputedDoubleDisplayValue(this->Viewport); + + // pix is a volatile pointer + leftProjPoint[0] = pix[0]; + leftProjPoint[1] = pix[1]; + + this->Coordinate->SetValue(midPoint); + pix = this->Coordinate->GetComputedDoubleDisplayValue(this->Viewport); + + // pix is a volatile pointer + midProjPoint[0] = pix[0]; + midProjPoint[1] = pix[1]; + + this->Coordinate->SetValue(rightPoint); + pix = this->Coordinate->GetComputedDoubleDisplayValue(this->Viewport); + + // distance between the line (leftProjPoint,rightProjPoint) and the point midProjPoint. + return this->Distance2LinePoint(leftProjPoint,pix,midProjPoint)>this->PixelTolerance; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the error at the mid-point. The type of error depends on the state +// of the concrete error metric. For instance, it can return an absolute +// or relative error metric. +// See RequiresEdgeSubdivision() for a description of the arguments. +// \pre leftPoint_exists: leftPoint!=0 +// \pre midPoint_exists: midPoint!=0 +// \pre rightPoint_exists: rightPoint!=0 +// \pre clamped_alpha: alpha>0 && alpha<1 +// \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) +// =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 +// \post positive_result: result>=0 +double vtkViewDependentErrorMetric::GetError(double *leftPoint, + double *midPoint, + double *rightPoint, + double vtkNotUsed(alpha)) +{ + assert("pre: leftPoint_exists" && leftPoint!=0); + assert("pre: midPoint_exists" && midPoint!=0); + assert("pre: rightPoint_exists" && rightPoint!=0); +// assert("pre: clamped_alpha" && alpha>0 && alpha<1); // or else true + if( this->GenericCell->IsGeometryLinear() ) + { + //don't need to do anything: + return 0; + } + + // Get the projection of the left, mid and right points + double leftProjPoint[2]; + double midProjPoint[2]; +// double rightProjPoint[2]; + + this->Coordinate->SetValue(leftPoint); + double *pix = this->Coordinate->GetComputedDoubleDisplayValue(this->Viewport); + + // pix is a volatile pointer + leftProjPoint[0] = pix[0]; + leftProjPoint[1] = pix[1]; + + this->Coordinate->SetValue(midPoint); + pix = this->Coordinate->GetComputedDoubleDisplayValue(this->Viewport); + + // pix is a volatile pointer + midProjPoint[0] = pix[0]; + midProjPoint[1] = pix[1]; + + this->Coordinate->SetValue(rightPoint); + pix = this->Coordinate->GetComputedDoubleDisplayValue(this->Viewport); + + // distance between the line (leftProjPoint,rightProjPoint) and the point midProjPoint. + return this->Distance2LinePoint(leftProjPoint,pix,midProjPoint); +} + +//----------------------------------------------------------------------------- +// Description: +// Square distance between a straight line (defined by points x and y) +// and a point z. Property: if x and y are equal, the line is a point and +// the result is the square distance between points x and z. +double vtkViewDependentErrorMetric::Distance2LinePoint(double x[2], + double y[2], + double z[2]) +{ + double u[2]; + double v[2]; + double w[2]; + + u[0] = y[0] - x[0]; + u[1] = y[1] - x[1]; + + vtkMath::Normalize2D(u); + + v[0] = z[0] - x[0]; + v[1] = z[1] - x[1]; + + double dot = vtkMath::Dot2D(u,v); + + w[0] = v[0] - dot*u[0]; + w[1] = v[1] - dot*u[1]; + + return vtkMath::Dot2D(w,w); +} + +//----------------------------------------------------------------------------- +void vtkViewDependentErrorMetric::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PixelTolerance: " << this->PixelTolerance << endl; + os << indent << "ViewPort: "; + if( this->Viewport ) + { + this->Viewport->PrintSelf( os << endl, indent.GetNextIndent()); + } + else + { + os << "(none)" << endl; + } +} diff --git a/Filtering/vtkViewDependentErrorMetric.h b/Filtering/vtkViewDependentErrorMetric.h new file mode 100644 index 0000000..fea0ea3 --- /dev/null +++ b/Filtering/vtkViewDependentErrorMetric.h @@ -0,0 +1,130 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkViewDependentErrorMetric.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkViewDependentErrorMetric - Objects that compute a +// screen-based error during cell tessellation. +// +// .SECTION Description +// It is a concrete error metric, based on a geometric criterium in +// the screen space: the variation of the projected edge from a projected +// straight line +// +// .SECTION See Also +// vtkGenericCellTessellator vtkGenericSubdivisionErrorMetric + +#ifndef __vtkViewDependentErrorMetric_h +#define __vtkViewDependentErrorMetric_h + +#include "vtkGenericSubdivisionErrorMetric.h" + +class vtkViewport; +class vtkCoordinate; + +class VTK_FILTERING_EXPORT vtkViewDependentErrorMetric : public vtkGenericSubdivisionErrorMetric +{ +public: + // Description: + // Construct the error metric with a default squared screen-based geometric + // accuracy measured in pixels equal to 0.25 (0.5^2). + static vtkViewDependentErrorMetric *New(); + + // Description: + // Standard VTK type and error macros. + vtkTypeRevisionMacro(vtkViewDependentErrorMetric,vtkGenericSubdivisionErrorMetric); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the squared screen-based geometric accurary measured in pixels. + // An accuracy less or equal to 0.25 (0.5^2) ensures that the screen-space + // interpolation of a mid-point matchs exactly with the projection of the + // mid-point (a value less than 1 but greater than 0.25 is not enough, + // because of 8-neighbors). Maybe it is useful for lower accuracy in case of + // anti-aliasing? + // \post positive_result: result>0 + vtkGetMacro(PixelTolerance, double); + + // Description: + // Set the squared screen-based geometric accuracy measured in pixels. + // Subdivision will be required if the square distance between the projection + // of the real point and the straight line passing through the projection + // of the vertices of the edge is greater than `value'. + // For instance, 0.25 will give better result than 1. + // \pre positive_value: value>0 + void SetPixelTolerance(double value); + + // Description: + // Set/Get the renderer with `renderer' on which the error metric + // is based. The error metric use the active camera of the renderer. + vtkGetObjectMacro(Viewport,vtkViewport); + void SetViewport(vtkViewport *viewport); + + // Description: + // Does the edge need to be subdivided according to the distance between + // the line passing through its endpoints in screen space and the projection + // of its mid point? + // The edge is defined by its `leftPoint' and its `rightPoint'. + // `leftPoint', `midPoint' and `rightPoint' have to be initialized before + // calling RequiresEdgeSubdivision(). + // Their format is global coordinates, parametric coordinates and + // point centered attributes: xyx rst abc de... + // `alpha' is the normalized abscissa of the midpoint along the edge. + // (close to 0 means close to the left point, close to 1 means close to the + // right point) + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + int RequiresEdgeSubdivision(double *leftPoint, double *midPoint, double *rightPoint, + double alpha); + + // Description: + // Return the error at the mid-point. The type of error depends on the state + // of the concrete error metric. For instance, it can return an absolute + // or relative error metric. + // See RequiresEdgeSubdivision() for a description of the arguments. + // \pre leftPoint_exists: leftPoint!=0 + // \pre midPoint_exists: midPoint!=0 + // \pre rightPoint_exists: rightPoint!=0 + // \pre clamped_alpha: alpha>0 && alpha<1 + // \pre valid_size: sizeof(leftPoint)=sizeof(midPoint)=sizeof(rightPoint) + // =GetAttributeCollection()->GetNumberOfPointCenteredComponents()+6 + // \post positive_result: result>=0 + double GetError(double *leftPoint, double *midPoint, + double *rightPoint, double alpha); + +protected: + vtkViewDependentErrorMetric(); + ~vtkViewDependentErrorMetric(); + + // Description: + // Square distance between a straight line (defined by points x and y) + // and a point z. Property: if x and y are equal, the line is a point and + // the result is the square distance between points x and z. + double Distance2LinePoint(double x[2], + double y[2], + double z[2]); + + double PixelTolerance; + vtkViewport *Viewport; + // used to get display coordinates from world coordinates + vtkCoordinate *Coordinate; + +private: + vtkViewDependentErrorMetric(const vtkViewDependentErrorMetric&); // Not implemented. + void operator=(const vtkViewDependentErrorMetric&); // Not implemented. +}; + +#endif diff --git a/Filtering/vtkViewport.cxx b/Filtering/vtkViewport.cxx new file mode 100644 index 0000000..d37c871 --- /dev/null +++ b/Filtering/vtkViewport.cxx @@ -0,0 +1,780 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkViewport.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkViewport.h" + +#include "vtkActor2DCollection.h" +#include "vtkAssemblyPath.h" +#include "vtkProp.h" +#include "vtkPropCollection.h" +#include "vtkWindow.h" + +vtkCxxRevisionMacro(vtkViewport, "$Revision: 1.5.4.1 $"); + +//---------------------------------------------------------------------------- +// Create a vtkViewport with a black background, a white ambient light, +// two-sided lighting turned on, a viewport of (0,0,1,1), and backface culling +// turned off. +vtkViewport::vtkViewport() +{ + this->VTKWindow = NULL; + + this->Background[0] = 0; + this->Background[1] = 0; + this->Background[2] = 0; + + this->Viewport[0] = 0; + this->Viewport[1] = 0; + this->Viewport[2] = 1; + this->Viewport[3] = 1; + + this->WorldPoint[0] = 0; + this->WorldPoint[1] = 0; + this->WorldPoint[2] = 0; + this->WorldPoint[3] = 0; + + this->DisplayPoint[0] = 0; + this->DisplayPoint[1] = 0; + this->DisplayPoint[2] = 0; + + this->ViewPoint[0] = 0; + this->ViewPoint[1] = 0; + this->ViewPoint[2] = 0; + + this->Aspect[0] = this->Aspect[1] = 1.0; + this->PixelAspect[0] = this->PixelAspect[1] = 1.0; + this->Center[0] = 0.0; + this->Center[1] = 0.0; + + this->Size[0] = 0; + this->Size[1] = 0; + + this->Origin[0] = 0; + this->Origin[1] = 0; + + this->PickedProp = NULL; + this->PickFromProps = NULL; + this->IsPicking = 0; + this->CurrentPickId = 0; + this->PickX = -1; + this->PickY = -1; + + + this->Props = vtkPropCollection::New(); + this->Actors2D = vtkActor2DCollection::New(); +} + +//---------------------------------------------------------------------------- +vtkViewport::~vtkViewport() +{ + this->Actors2D->Delete(); + this->Actors2D = NULL; + + this->RemoveAllViewProps(); + this->Props->Delete(); + this->Props = NULL; + + if (this->VTKWindow != NULL) + { + // renderer never reference counted the window. + // loop is too hard to detect. + // this->VTKWindow->UnRegister(this); + this->VTKWindow = NULL; + } + + if ( this->PickedProp != NULL ) + { + this->PickedProp->UnRegister(this); + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::AddActor2D(vtkProp* p) +{ + this->AddViewProp(p); +} + +//---------------------------------------------------------------------------- +void vtkViewport::RemoveActor2D(vtkProp* p) +{ + this->Actors2D->RemoveItem(p); + this->RemoveViewProp(p); +} + +//---------------------------------------------------------------------------- +int vtkViewport::HasViewProp(vtkProp *p) +{ + return (p && this->Props->IsItemPresent(p)); +} + +//---------------------------------------------------------------------------- +void vtkViewport::AddViewProp(vtkProp *p) +{ + if (p && !this->HasViewProp(p)) + { + this->Props->AddItem(p); + p->AddConsumer(this); + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::RemoveViewProp(vtkProp *p) +{ + if (p && this->HasViewProp(p)) + { + p->ReleaseGraphicsResources(this->VTKWindow); + p->RemoveConsumer(this); + this->Props->RemoveItem(p); + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::RemoveAllViewProps(void) +{ + vtkProp *aProp; + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + aProp->ReleaseGraphicsResources(this->VTKWindow); + aProp->RemoveConsumer(this); + } + this->Props->RemoveAllItems(); +} + +//---------------------------------------------------------------------------- +// look through the props and get all the actors +vtkActor2DCollection *vtkViewport::GetActors2D() +{ + vtkProp *aProp; + + // clear the collection first + this->Actors2D->RemoveAllItems(); + + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + aProp->GetActors2D(this->Actors2D); + } + return this->Actors2D; +} + +// Convert display coordinates to view coordinates. +void vtkViewport::DisplayToView() +{ + if ( this->VTKWindow ) + { + double vx,vy,vz; + int sizex,sizey; + int *size; + + /* get physical window dimensions */ + size = this->VTKWindow->GetSize(); + sizex = size[0]; + sizey = size[1]; + + vx = 2.0 * (this->DisplayPoint[0] - sizex*this->Viewport[0])/ + (sizex*(this->Viewport[2]-this->Viewport[0])) - 1.0; + vy = 2.0 * (this->DisplayPoint[1] - sizey*this->Viewport[1])/ + (sizey*(this->Viewport[3]-this->Viewport[1])) - 1.0; + vz = this->DisplayPoint[2]; + + this->SetViewPoint(vx,vy,vz); + } +} + +//---------------------------------------------------------------------------- +// Convert view coordinates to display coordinates. +void vtkViewport::ViewToDisplay() +{ + if ( this->VTKWindow ) + { + double dx,dy; + int sizex,sizey; + int *size; + + /* get physical window dimensions */ + size = this->VTKWindow->GetSize(); + sizex = size[0]; + sizey = size[1]; + + dx = (this->ViewPoint[0] + 1.0) * + (sizex*(this->Viewport[2]-this->Viewport[0])) / 2.0 + + sizex*this->Viewport[0]; + dy = (this->ViewPoint[1] + 1.0) * + (sizey*(this->Viewport[3]-this->Viewport[1])) / 2.0 + + sizey*this->Viewport[1]; + + this->SetDisplayPoint(dx,dy,this->ViewPoint[2]); + } +} + +//---------------------------------------------------------------------------- +// Convert view point coordinates to world coordinates. +void vtkViewport::ViewToWorld() +{ + this->SetWorldPoint(this->ViewPoint[0], this->ViewPoint[1], + this->ViewPoint[2], 1); +} + +//---------------------------------------------------------------------------- +// Convert world point coordinates to view coordinates. +void vtkViewport::WorldToView() +{ + + this->SetViewPoint(this->WorldPoint[0], this->WorldPoint[1], + this->WorldPoint[2]); + +} + +//---------------------------------------------------------------------------- +// Return the size of the viewport in display coordinates. +int *vtkViewport::GetSize() +{ + if ( this->VTKWindow ) + { + int lowerLeft[2]; + double *vport = this->GetViewport(); + + double vpu, vpv; + vpu = vport[0]; + vpv = vport[1]; + this->NormalizedDisplayToDisplay(vpu,vpv); + lowerLeft[0] = (int)(vpu+0.5); + lowerLeft[1] = (int)(vpv+0.5); + double vpu2, vpv2; + vpu2 = vport[2]; + vpv2 = vport[3]; + this->NormalizedDisplayToDisplay(vpu2,vpv2); + this->Size[0] = (int)(vpu2 + 0.5) - lowerLeft[0]; + this->Size[1] = (int)(vpv2 + 0.5) - lowerLeft[1]; + } + else + { + this->Size[0] = this->Size[1] = 0; + } + + return this->Size; +} + +//---------------------------------------------------------------------------- +// Return the origin of the viewport in display coordinates. +int *vtkViewport::GetOrigin() +{ + if ( this->VTKWindow ) + { + int* winSize = this->VTKWindow->GetSize(); + + // Round the origin up a pixel + this->Origin[0] = (int) (this->Viewport[0] * (double) winSize[0] + 0.5); + this->Origin[1] = (int) (this->Viewport[1] * (double) winSize[1] + 0.5); + } + else + { + this->Origin[0] = this->Origin[1] = 0; + } + + return this->Origin; +} + +//---------------------------------------------------------------------------- +// Return the center of this Viewport in display coordinates. +double *vtkViewport::GetCenter() +{ + if ( this->VTKWindow ) + { + int *size; + + // get physical window dimensions + size = this->GetVTKWindow()->GetSize(); + + this->Center[0] = ((this->Viewport[2]+this->Viewport[0]) + /2.0*(double)size[0]); + this->Center[1] = ((this->Viewport[3]+this->Viewport[1]) + /2.0*(double)size[1]); + } + else + { + this->Center[0] = this->Center[1] = 0; + } + + return this->Center; +} + +//---------------------------------------------------------------------------- +// Is a given display point in this Viewport's viewport. +int vtkViewport::IsInViewport(int x,int y) +{ + if ( this->VTKWindow ) + { + int *size; + + // get physical window dimensions + size = this->GetVTKWindow()->GetSize(); + + if ((this->Viewport[0]*size[0] <= x)&& + (this->Viewport[2]*size[0] >= x)&& + (this->Viewport[1]*size[1] <= y)&& + (this->Viewport[3]*size[1] >= y)) + { + return 1; + } + } + + return 0; +} + +//---------------------------------------------------------------------------- +void vtkViewport::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Aspect: (" << this->Aspect[0] << ", " + << this->Aspect[1] << ")\n"; + + os << indent << "PixelAspect: (" << this->PixelAspect[0] << ", " + << this->PixelAspect[1] << ")\n"; + + os << indent << "Background: (" << this->Background[0] << ", " + << this->Background[1] << ", " << this->Background[2] << ")\n"; + + os << indent << "Viewport: (" << this->Viewport[0] << ", " + << this->Viewport[1] << ", " << this->Viewport[2] << ", " + << this->Viewport[3] << ")\n"; + + os << indent << "Displaypoint: (" << this->DisplayPoint[0] << ", " + << this->DisplayPoint[1] << ", " << this->DisplayPoint[2] << ")\n"; + + os << indent << "Viewpoint: (" << this->ViewPoint[0] << ", " + << this->ViewPoint[1] << ", " << this->ViewPoint[2] << ")\n"; + + os << indent << "Worldpoint: (" << this->WorldPoint[0] << ", " + << this->WorldPoint[1] << ", " << this->WorldPoint[2] << ", " + << this->WorldPoint[3] << ")\n"; + + os << indent << "Pick Position X Y: " << this->PickX + << " " << this->PickY << endl; + os << indent << "IsPicking boolean: " << this->IsPicking << endl; + os << indent << "Props:\n"; + this->Props->PrintSelf(os,indent.GetNextIndent()); + +} + +//---------------------------------------------------------------------------- +void vtkViewport::LocalDisplayToDisplay(double &vtkNotUsed(u), double &v) +{ + if ( this->VTKWindow ) + { + int *size; + + /* get physical window dimensions */ + size = this->VTKWindow->GetSize(); + + v = size[1] - v - 1; + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::DisplayToLocalDisplay(double &vtkNotUsed(u), double &v) +{ + if ( this->VTKWindow ) + { + int *size; + + /* get physical window dimensions */ + size = this->VTKWindow->GetSize(); + + v = size[1] - v - 1; + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::DisplayToNormalizedDisplay(double &u, double &v) +{ + if ( this->VTKWindow ) + { + int *size; + + /* get physical window dimensions */ + size = this->VTKWindow->GetSize(); + + u = u/size[0]; + v = v/size[1]; + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::NormalizedDisplayToViewport(double &u, double &v) +{ + if ( this->VTKWindow ) + { + // get the pixel value for the viewport origin + double vpou, vpov; + vpou = this->Viewport[0]; + vpov = this->Viewport[1]; + this->NormalizedDisplayToDisplay(vpou,vpov); + + // get the pixel value for the coordinate + this->NormalizedDisplayToDisplay(u,v); + + // subtract the vpo + u = u - vpou - 0.5; + v = v - vpov - 0.5; + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::ViewportToNormalizedViewport(double &u, double &v) +{ + if ( this->VTKWindow ) + { + int *size; + + /* get physical window dimensions */ +/* + double vpsizeu, vpsizev; + size = this->VTKWindow->GetSize(); + vpsizeu = size[0]*(this->Viewport[2] - this->Viewport[0]); + vpsizev = size[1]*(this->Viewport[3] - this->Viewport[1]); + + u = u/(vpsizeu - 1.0); + v = v/(vpsizev - 1.0); +*/ + size = this->GetSize(); + u = u/(size[0] - 1.0); + v = v/(size[1] - 1.0); + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::NormalizedViewportToView(double &x, double &y, + double &vtkNotUsed(z)) +{ + // for tiling we must consider the tiledViewport + double *tvport = this->VTKWindow->GetTileViewport(); + + // what part of the full viewport is the current tiled viewport? + double *vport = this->GetViewport(); + double nvport[4]; + this->GetViewport(nvport); + + // clip the viewport to the tiled viewport + if (nvport[0] < tvport[0]) + { + nvport[0] = tvport[0]; + } + if (nvport[1] < tvport[1]) + { + nvport[1] = tvport[1]; + } + if (nvport[2] > tvport[2]) + { + nvport[2] = tvport[2]; + } + if (nvport[3] > tvport[3]) + { + nvport[3] = tvport[3]; + } + + x = x*(vport[2] - vport[0]) + vport[0]; + y = y*(vport[3] - vport[1]) + vport[1]; + + x = (x - nvport[0])/(nvport[2] - nvport[0]); + y = (y - nvport[1])/(nvport[3] - nvport[1]); + + x = (2.0*x - 1.0); + y = (2.0*y - 1.0); +} + +//---------------------------------------------------------------------------- +void vtkViewport::NormalizedDisplayToDisplay(double &u, double &v) +{ + if ( this->VTKWindow ) + { + int *size; + + /* get physical window dimensions */ + size = this->VTKWindow->GetSize(); + + u = u*size[0]; + v = v*size[1]; + } +} + + +//---------------------------------------------------------------------------- +void vtkViewport::ViewportToNormalizedDisplay(double &u, double &v) +{ + if ( this->VTKWindow ) + { + // get the pixel value for the viewport origin + double vpou, vpov; + vpou = this->Viewport[0]; + vpov = this->Viewport[1]; + this->NormalizedDisplayToDisplay(vpou,vpov); + + // add the vpo + // the 0.5 offset is here because the viewport uses pixel centers + // while the display uses pixel edges. + u = u + vpou + 0.5; + v = v + vpov + 0.5; + + // get the pixel value for the coordinate + this->DisplayToNormalizedDisplay(u,v); + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::NormalizedViewportToViewport(double &u, double &v) +{ + if ( this->VTKWindow ) + { + int *size; + + /* get physical window dimensions */ +/* + double vpsizeu, vpsizev; + size = this->VTKWindow->GetSize(); + vpsizeu = size[0]*(this->Viewport[2] - this->Viewport[0]); + vpsizev = size[1]*(this->Viewport[3] - this->Viewport[1]); + u = u * (vpsizeu - 1.0); + v = v * (vpsizev - 1.0); +*/ + size = this->GetSize(); + u = u * (size[0] - 1.0); + v = v * (size[1] - 1.0); + } +} + +//---------------------------------------------------------------------------- +void vtkViewport::ViewToNormalizedViewport(double &x, double &y, + double &vtkNotUsed(z)) +{ + // for tiling we must consider the tiledViewport + double *tvport = this->VTKWindow->GetTileViewport(); + + // what part of the full viewport is the current tiled viewport? + double *vport = this->GetViewport(); + double nvport[4]; + this->GetViewport(nvport); + + // clip the viewport to the tiled viewport + if (nvport[0] < tvport[0]) + { + nvport[0] = tvport[0]; + } + if (nvport[1] < tvport[1]) + { + nvport[1] = tvport[1]; + } + if (nvport[2] > tvport[2]) + { + nvport[2] = tvport[2]; + } + if (nvport[3] > tvport[3]) + { + nvport[3] = tvport[3]; + } + + x = (x + 1.0) / 2.0; + y = (y + 1.0) / 2.0; + + // now x and y are in the normalized viewport of the clipped viewport + // we need to convert that to the normalized viewport of the entire + // viewport + x = nvport[0] + x*(nvport[2] - nvport[0]); + y = nvport[1] + y*(nvport[3] - nvport[1]); + x = (x - vport[0])/(vport[2] - vport[0]); + y = (y - vport[1])/(vport[3] - vport[1]); +} + +void vtkViewport::ComputeAspect() +{ + if ( this->VTKWindow ) + { + double aspect[2]; + double *vport; + int *size, lowerLeft[2], upperRight[2]; + + // get the bounds of the window + size = this->VTKWindow->GetSize(); + + vport = this->GetViewport(); + + lowerLeft[0] = (int)(vport[0]*size[0] + 0.5); + lowerLeft[1] = (int)(vport[1]*size[1] + 0.5); + upperRight[0] = (int)(vport[2]*size[0] + 0.5); + upperRight[1] = (int)(vport[3]*size[1] + 0.5); + upperRight[0]--; + upperRight[1]--; + + aspect[0] = (double)(upperRight[0]-lowerLeft[0]+1)/ + (double)(upperRight[1]-lowerLeft[1]+1)*this->PixelAspect[0]; + aspect[1] = 1.0*this->PixelAspect[1]; + + this->SetAspect(aspect); + } +} + +//---------------------------------------------------------------------------- +vtkAssemblyPath* vtkViewport::PickPropFrom(double selectionX, + double selectionY, + vtkPropCollection* pickfrom) +{ + this->PickFromProps = pickfrom; + return this->PickProp(selectionX, selectionY); +} + +//---------------------------------------------------------------------------- +#define vtkViewportBound(vpu, vpv) \ +{ \ + if (vpu > 1.0) \ + { \ + vpu = 1.0; \ + } \ + if (vpu < 0.0) \ + { \ + vpu = 0.0; \ + } \ + if (vpv > 1.0) \ + { \ + vpv = 1.0; \ + } \ + if (vpv < 0.0) \ + { \ + vpv = 0.0; \ + } \ +} + +//---------------------------------------------------------------------------- +// This complicated method determines the size of the current tile in pixels +// this is useful in computeing the actual aspcet ration of the current tile +void vtkViewport::GetTiledSize(int *usize, int *vsize) +{ + int llx, lly; + this->GetTiledSizeAndOrigin(usize,vsize,&llx,&lly); +} + +//---------------------------------------------------------------------------- +void vtkViewport::GetTiledSizeAndOrigin(int *usize, int *vsize, + int *lowerLeftU, int *lowerLeftV) +{ + double *vport; + + // find out if we should stereo render + vport = this->GetViewport(); + + // if there is no window assume 0 1 + double tileViewPort[4]; + if (this->GetVTKWindow()) + { + this->GetVTKWindow()->GetTileViewport(tileViewPort); + } + else + { + tileViewPort[0] = 0; + tileViewPort[1] = 0; + tileViewPort[2] = 1; + tileViewPort[3] = 1; + } + + double vpu, vpv; + // find the lower left corner of the viewport, taking into account the + // lower left boundary of this tile + vpu = (vport[0] - tileViewPort[0]); + vpv = (vport[1] - tileViewPort[1]); + vtkViewportBound(vpu,vpv); + // store the result as a pixel value + this->NormalizedDisplayToDisplay(vpu,vpv); + *lowerLeftU = (int)(vpu+0.5); + *lowerLeftV = (int)(vpv+0.5); + double vpu2, vpv2; + // find the upper right corner of the viewport, taking into account the + // lower left boundary of this tile + vpu2 = (vport[2] - tileViewPort[0]); + vpv2 = (vport[3] - tileViewPort[1]); + vtkViewportBound(vpu2,vpv2); + // also watch for the upper right boundary of the tile + if (vpu2 > (tileViewPort[2] - tileViewPort[0])) + { + vpu2 = tileViewPort[2] - tileViewPort[0]; + } + if (vpv2 > (tileViewPort[3] - tileViewPort[1])) + { + vpv2 = tileViewPort[3] - tileViewPort[1]; + } + this->NormalizedDisplayToDisplay(vpu2,vpv2); + // now compute the size of the intersection of the viewport with the + // current tile + *usize = (int)(vpu2 + 0.5) - *lowerLeftU; + *vsize = (int)(vpv2 + 0.5) - *lowerLeftV; + if (*usize < 0) + { + *usize = 0; + } + if (*vsize < 0) + { + *vsize = 0; + } +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef RemoveProp +void vtkViewport::RemovePropA(vtkProp* p) +{ + VTK_LEGACY_REPLACED_BODY(vtkViewport::RemoveProp, "VTK 5.0", + vtkViewport::RemoveViewProp); + this->RemoveViewProp(p); +} +void vtkViewport::RemovePropW(vtkProp* p) +{ + VTK_LEGACY_REPLACED_BODY(vtkViewport::RemoveProp, "VTK 5.0", + vtkViewport::RemoveViewProp); + this->RemoveViewProp(p); +} +# endif +void vtkViewport::RemoveProp(vtkProp* p) +{ + VTK_LEGACY_REPLACED_BODY(vtkViewport::RemoveProp, "VTK 5.0", + vtkViewport::RemoveViewProp); + this->RemoveViewProp(p); +} +void vtkViewport::AddProp(vtkProp* p) +{ + VTK_LEGACY_REPLACED_BODY(vtkViewport::AddProp, "VTK 5.0", + vtkViewport::AddViewProp); + this->AddViewProp(p); +} +vtkPropCollection* vtkViewport::GetProps() +{ + VTK_LEGACY_REPLACED_BODY(vtkViewport::GetProps, "VTK 5.0", + vtkViewport::GetViewProps); + return this->GetViewProps(); +} +int vtkViewport::HasProp(vtkProp* p) +{ + VTK_LEGACY_REPLACED_BODY(vtkViewport::HasProp, "VTK 5.0", + vtkViewport::HasViewProp); + return this->HasViewProp(p); +} +void vtkViewport::RemoveAllProps() +{ + VTK_LEGACY_REPLACED_BODY(vtkViewport::RemoveAllProps, "VTK 5.0", + vtkViewport::RemoveAllViewProps); + this->RemoveAllViewProps(); +} +#endif diff --git a/Filtering/vtkViewport.h b/Filtering/vtkViewport.h new file mode 100644 index 0000000..f1de9b8 --- /dev/null +++ b/Filtering/vtkViewport.h @@ -0,0 +1,303 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkViewport.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkViewport - abstract specification for Viewports +// .SECTION Description +// vtkViewport provides an abstract specification for Viewports. A Viewport +// is an object that controls the rendering process for objects. Rendering +// is the process of converting geometry, a specification for lights, and +// a camera view into an image. vtkViewport also performs coordinate +// transformation between world coordinates, view coordinates (the computer +// graphics rendering coordinate system), and display coordinates (the +// actual screen coordinates on the display device). Certain advanced +// rendering features such as two-sided lighting can also be controlled. + +// .SECTION See Also +// vtkWindow vtkRenderer + +#ifndef __vtkViewport_h +#define __vtkViewport_h + +#include "vtkObject.h" + +class vtkActor2DCollection; +class vtkAssemblyPath; +class vtkProp; +class vtkPropCollection; +class vtkWindow; + +class VTK_FILTERING_EXPORT vtkViewport : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkViewport,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a prop to the list of props. Prop is the superclass of all + // actors, volumes, 2D actors, composite props etc. + void AddViewProp(vtkProp *); + + // Description: + // Return any props in this viewport. + vtkPropCollection *GetViewProps() {return this->Props;}; + + // Description: + // Query if a prop is in the list of props. + int HasViewProp(vtkProp *); + + // Description: + // Remove an actor from the list of actors. + void RemoveViewProp(vtkProp *); + + // Description: + // Remove all actors from the list of actors. + void RemoveAllViewProps(void); + + // Description: + // Add/Remove different types of props to the renderer. + // These methods are all synonyms to AddViewProp and RemoveViewProp. + // They are here for convenience and backwards compatibility. + void AddActor2D(vtkProp* p); + void RemoveActor2D(vtkProp* p); + vtkActor2DCollection *GetActors2D(); + + // Description: + // Set/Get the background color of the rendering screen using an rgb color + // specification. + vtkSetVector3Macro(Background,double); + vtkGetVector3Macro(Background,double); + + // Description: + // Set the aspect ratio of the rendered image. This is computed + // automatically and should not be set by the user. + vtkSetVector2Macro(Aspect,double); + vtkGetVectorMacro(Aspect,double,2); + virtual void ComputeAspect(); + + // Description: + // Set the aspect ratio of a pixel in the rendered image. + // This factor permits the image to rendered anisotropically + // (i.e., stretched in one direction or the other). + vtkSetVector2Macro(PixelAspect,double); + vtkGetVectorMacro(PixelAspect,double,2); + + // Description: + // Specify the viewport for the Viewport to draw in the rendering window. + // Coordinates are expressed as (xmin,ymin,xmax,ymax), where each + // coordinate is 0 <= coordinate <= 1.0. + vtkSetVector4Macro(Viewport,double); + vtkGetVectorMacro(Viewport,double,4); + + // Description: + // Set/get a point location in display (or screen) coordinates. + // The lower left corner of the window is the origin and y increases + // as you go up the screen. + vtkSetVector3Macro(DisplayPoint,double); + vtkGetVectorMacro(DisplayPoint,double,3); + + // Description: + // Specify a point location in view coordinates. The origin is in the + // middle of the viewport and it extends from -1 to 1 in all three + // dimensions. + vtkSetVector3Macro(ViewPoint,double); + vtkGetVectorMacro(ViewPoint,double,3); + + // Description: + // Specify a point location in world coordinates. This method takes + // homogeneous coordinates. + vtkSetVector4Macro(WorldPoint,double); + vtkGetVectorMacro(WorldPoint,double,4); + + // Description: + // Return the center of this viewport in display coordinates. + virtual double *GetCenter(); + + // Description: + // Is a given display point in this Viewport's viewport. + virtual int IsInViewport(int x,int y); + + // Description: + // Return the vtkWindow that owns this vtkViewport. + virtual vtkWindow *GetVTKWindow() = 0; + + // Description: + // Convert display coordinates to view coordinates. + virtual void DisplayToView(); // these get modified in subclasses + + // Description: + // Convert view coordinates to display coordinates. + virtual void ViewToDisplay(); // to handle stereo rendering + + // Description: + // Convert world point coordinates to view coordinates. + virtual void WorldToView(); + + // Description: + // Convert view point coordinates to world coordinates. + virtual void ViewToWorld(); + + // Description: + // Convert display (or screen) coordinates to world coordinates. + void DisplayToWorld() {this->DisplayToView(); this->ViewToWorld();}; + + // Description: + // Convert world point coordinates to display (or screen) coordinates. + void WorldToDisplay() {this->WorldToView(); this->ViewToDisplay();}; + + // Description: + // These methods map from one coordinate system to another. + // They are primarily used by the vtkCoordinate object and + // are often strung together. These methods return valid information + // only if the window has been realized (e.g., GetSize() returns + // something other than (0,0)). + virtual void LocalDisplayToDisplay(double &x, double &y); + virtual void DisplayToNormalizedDisplay(double &u, double &v); + virtual void NormalizedDisplayToViewport(double &x, double &y); + virtual void ViewportToNormalizedViewport(double &u, double &v); + virtual void NormalizedViewportToView(double &x, double &y, double &z); + virtual void ViewToWorld(double &, double &, double &) {}; + virtual void DisplayToLocalDisplay(double &x, double &y); + virtual void NormalizedDisplayToDisplay(double &u, double &v); + virtual void ViewportToNormalizedDisplay(double &x, double &y); + virtual void NormalizedViewportToViewport(double &u, double &v); + virtual void ViewToNormalizedViewport(double &x, double &y, double &z); + virtual void WorldToView(double &, double &, double &) {}; + + // Description: + // Get the size and origin of the viewport in display coordinates. Note: + // if the window has not yet been realized, GetSize() and GetOrigin() + // return (0,0). + int *GetSize(); + int *GetOrigin(); + void GetTiledSize(int *width, int *height); + void GetTiledSizeAndOrigin(int *width, int *height, + int *lowerLeftX, int *lowerLeftY); + + // The following methods describe the public pick interface for picking + // Props in a viewport. + + // Description: + // Return the Prop that has the highest z value at the given x, y position + // in the viewport. Basically, the top most prop that renders the pixel at + // selectionX, selectionY will be returned. If no Props are there NULL is + // returned. This method selects from the Viewports Prop list. + virtual vtkAssemblyPath* PickProp(double selectionX, double selectionY) = 0; + + // Description: + // Same as PickProp with two arguments, but selects from the given + // collection of Props instead of the Renderers props. Make sure + // the Props in the collection are in this renderer. + vtkAssemblyPath* PickPropFrom(double selectionX, double selectionY, + vtkPropCollection*); + + // Description: + // Methods used to return the pick (x,y) in local display coordinates (i.e., + // it's that same as selectionX and selectionY). + vtkGetMacro(PickX, double); + vtkGetMacro(PickY, double); + vtkGetMacro(IsPicking, int); + + // Description: + // Return the Z value for the last picked Prop. + virtual double GetPickedZ() = 0; + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define RemovePropA RemoveProp +# define RemovePropW RemoveProp +#endif + + // Description: + // @deprecated Replaced by vtkViewport::RemoveViewProp() as of VTK 5.0. + VTK_LEGACY(void RemoveProp(vtkProp*)); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef RemovePropA +# undef RemovePropW + //BTX + VTK_LEGACY(void RemovePropA(vtkProp*)); + VTK_LEGACY(void RemovePropW(vtkProp*)); + //ETX +#endif + + // Description: + // @deprecated Replaced by vtkViewport::AddViewProp() as of VTK 5.0. + VTK_LEGACY(void AddProp(vtkProp *)); + + // Description: + // @deprecated Replaced by vtkViewport::GetViewProps() as of VTK 5.0. + VTK_LEGACY(vtkPropCollection *GetProps()); + + // Description: + // @deprecated Replaced by vtkViewport::HasViewProp() as of VTK 5.0. + VTK_LEGACY(int HasProp(vtkProp *)); + + // Description: + // @deprecated Replaced by vtkViewport::RemoveAllViewProps() as of VTK 5.0. + VTK_LEGACY(void RemoveAllProps()); + +protected: + // Create a vtkViewport with a black background, a white ambient light, + // two-sided lighting turned on, a viewport of (0,0,1,1), and back face + // culling turned off. + vtkViewport(); + ~vtkViewport(); + + //BTX + // Picking functions to be implemented by sub-classes + // Perform the main picking loop + virtual void DevicePickRender() = 0; + // Enter a pick mode + virtual void StartPick(unsigned int pickFromSize) = 0; + // Set the pick id to the next id before drawing an object + virtual void UpdatePickId() = 0; + // Exit Pick mode + virtual void DonePick() = 0; + // Return the id of the picked object, only valid after a call to DonePick + virtual unsigned int GetPickedId() = 0; + //ETX + + // Ivars for picking + // Store a picked Prop (contained in an assembly path) + vtkAssemblyPath* PickedProp; + vtkPropCollection* PickFromProps; + // Boolean flag to determine if picking is enabled for this render + int IsPicking; + unsigned int CurrentPickId; + double PickX; + double PickY; + // End Ivars for picking + + vtkPropCollection *Props; + vtkActor2DCollection *Actors2D; + vtkWindow *VTKWindow; + double Background[3]; + double Viewport[4]; + double Aspect[2]; + double PixelAspect[2]; + double Center[2]; + + int Size[2]; + int Origin[2]; + double DisplayPoint[3]; + double ViewPoint[3]; + double WorldPoint[4]; + +private: + vtkViewport(const vtkViewport&); // Not implemented. + void operator=(const vtkViewport&); // Not implemented. +}; + + + +#endif diff --git a/Filtering/vtkVoxel.cxx b/Filtering/vtkVoxel.cxx new file mode 100644 index 0000000..f39b72d --- /dev/null +++ b/Filtering/vtkVoxel.cxx @@ -0,0 +1,607 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoxel.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVoxel.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPixel.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" +#include "vtkBox.h" + +vtkCxxRevisionMacro(vtkVoxel, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkVoxel); + +//---------------------------------------------------------------------------- +// Construct the voxel with eight points. +vtkVoxel::vtkVoxel() +{ + int i; + + this->Points->SetNumberOfPoints(8); + this->PointIds->SetNumberOfIds(8); + for (i = 0; i < 8; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + } + for (i = 0; i < 8; i++) + { + this->PointIds->SetId(i,0); + } + this->Line = vtkLine::New(); + this->Pixel = vtkPixel::New(); +} + +//---------------------------------------------------------------------------- +vtkVoxel::~vtkVoxel() +{ + this->Line->Delete(); + this->Pixel->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkVoxel::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + double pt1[3], pt2[3], pt3[3], pt4[3]; + int i; + + subId = 0; +// +// Get coordinate system +// + this->Points->GetPoint(0, pt1); + this->Points->GetPoint(1, pt2); + this->Points->GetPoint(2, pt3); + this->Points->GetPoint(4, pt4); +// +// Develop parametric coordinates +// + pcoords[0] = (x[0] - pt1[0]) / (pt2[0] - pt1[0]); + pcoords[1] = (x[1] - pt1[1]) / (pt3[1] - pt1[1]); + pcoords[2] = (x[2] - pt1[2]) / (pt4[2] - pt1[2]); + + if ( pcoords[0] >= 0.0 && pcoords[0] <= 1.0 && + pcoords[1] >= 0.0 && pcoords[1] <= 1.0 && + pcoords[2] >= 0.0 && pcoords[2] <= 1.0 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + } + dist2 = 0.0; // inside voxel + this->InterpolationFunctions(pcoords,weights); + return 1; + } + else + { + double pc[3], w[8]; + if (closestPoint) + { + for (i=0; i<3; i++) + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkVoxel::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + double pt1[3], pt2[3], pt3[3], pt4[3]; + int i; + + this->Points->GetPoint(0, pt1); + this->Points->GetPoint(1, pt2); + this->Points->GetPoint(2, pt3); + this->Points->GetPoint(4, pt4); + + for (i=0; i<3; i++) + { + x[i] = pt1[i] + pcoords[0]*(pt2[i] - pt1[i]) + + pcoords[1]*(pt3[i] - pt1[i]) + + pcoords[2]*(pt4[i] - pt1[i]); + } + + this->InterpolationFunctions(pcoords,weights); +} + +//---------------------------------------------------------------------------- +// +// Compute Interpolation functions +// +void vtkVoxel::InterpolationFunctions(double pcoords[3], double sf[8]) +{ + double rm, sm, tm; + + double r = pcoords[0], s = pcoords[1], t = pcoords[2]; + + rm = 1. - r; + sm = 1. - s; + tm = 1. - t; + + sf[0] = rm * sm * tm; + sf[1] = r * sm * tm; + sf[2] = rm * s * tm; + sf[3] = r * s * tm; + sf[4] = rm * sm * t; + sf[5] = r * sm * t; + sf[6] = rm * s * t; + sf[7] = r * s * t; +} + +//---------------------------------------------------------------------------- +void vtkVoxel::InterpolationDerivs(double pcoords[3], double derivs[24]) +{ + double rm, sm, tm; + + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + tm = 1. - pcoords[2]; + + // r derivatives + derivs[0] = -sm*tm; + derivs[1] = sm*tm; + derivs[2] = -pcoords[1]*tm; + derivs[3] = pcoords[1]*tm; + derivs[4] = -sm*pcoords[2]; + derivs[5] = sm*pcoords[2]; + derivs[6] = -pcoords[1]*pcoords[2]; + derivs[7] = pcoords[1]*pcoords[2]; + + // s derivatives + derivs[8] = -rm*tm; + derivs[9] = -pcoords[0]*tm; + derivs[10] = rm*tm; + derivs[11] = pcoords[0]*tm; + derivs[12] = -rm*pcoords[2]; + derivs[13] = -pcoords[0]*pcoords[2]; + derivs[14] = rm*pcoords[2]; + derivs[15] = pcoords[0]*pcoords[2]; + + // t derivatives + derivs[16] = -rm*sm; + derivs[17] = -pcoords[0]*sm; + derivs[18] = -rm*pcoords[1]; + derivs[19] = -pcoords[0]*pcoords[1]; + derivs[20] = rm*sm; + derivs[21] = pcoords[0]*sm; + derivs[22] = rm*pcoords[1]; + derivs[23] = pcoords[0]*pcoords[1]; +} + +//---------------------------------------------------------------------------- +int vtkVoxel::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + double t1=pcoords[0]-pcoords[1]; + double t2=1.0-pcoords[0]-pcoords[1]; + double t3=pcoords[1]-pcoords[2]; + double t4=1.0-pcoords[1]-pcoords[2]; + double t5=pcoords[2]-pcoords[0]; + double t6=1.0-pcoords[2]-pcoords[0]; + + pts->SetNumberOfIds(4); + + // compare against six planes in parametric space that divide element + // into six pieces. + if ( t3 >= 0.0 && t4 >= 0.0 && t5 < 0.0 && t6 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(3)); + pts->SetId(3,this->PointIds->GetId(2)); + } + + else if ( t1 >= 0.0 && t2 < 0.0 && t5 < 0.0 && t6 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(3)); + pts->SetId(2,this->PointIds->GetId(7)); + pts->SetId(3,this->PointIds->GetId(5)); + } + + else if ( t1 >= 0.0 && t2 >= 0.0 && t3 < 0.0 && t4 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(5)); + pts->SetId(3,this->PointIds->GetId(4)); + } + + else if ( t3 < 0.0 && t4 < 0.0 && t5 >= 0.0 && t6 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(4)); + pts->SetId(1,this->PointIds->GetId(5)); + pts->SetId(2,this->PointIds->GetId(7)); + pts->SetId(3,this->PointIds->GetId(6)); + } + + else if ( t1 < 0.0 && t2 >= 0.0 && t5 >= 0.0 && t6 >= 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(4)); + pts->SetId(2,this->PointIds->GetId(6)); + pts->SetId(3,this->PointIds->GetId(2)); + } + + else // if ( t1 < 0.0 && t2 < 0.0 && t3 >= 0.0 && t6 < 0.0 ) + { + pts->SetId(0,this->PointIds->GetId(3)); + pts->SetId(1,this->PointIds->GetId(2)); + pts->SetId(2,this->PointIds->GetId(6)); + pts->SetId(3,this->PointIds->GetId(7)); + } + + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 || + pcoords[2] < 0.0 || pcoords[2] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +static int edges[12][2] = { {0,1}, {1,3}, {2,3}, {0,2}, + {4,5}, {5,7}, {6,7}, {4,6}, + {0,4}, {1,5}, {2,6}, {3,7}}; +// define in terms vtkPixel understands +static int faces[6][4] = { {2,0,6,4}, {1,3,5,7}, + {0,1,4,5}, {3,2,7,6}, + {1,0,3,2}, {4,5,6,7} }; + +//---------------------------------------------------------------------------- +// +// Marching cubes case table +// +#include "vtkMarchingCubesCases.h" + +void vtkVoxel::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + static int CASE_MASK[8] = {1,2,4,8,16,32,64,128}; + vtkMarchingCubesTriangleCases *triCase; + EDGE_LIST *edge; + int i, j, index, *vert; + static int vertMap[8] = { 0, 1, 3, 2, 4, 5, 7, 6 }; + int newCellId; + vtkIdType pts[3]; + double t, x1[3], x2[3], x[3]; + vtkIdType offset = verts->GetNumberOfCells() + lines->GetNumberOfCells(); + + // Build the case table + for ( i=0, index = 0; i < 8; i++) + { + if (cellScalars->GetComponent(vertMap[i],0) >= value) + { + index |= CASE_MASK[i]; + } + } + + triCase = vtkMarchingCubesTriangleCases::GetCases() + index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (i=0; i<3; i++) // insert triangle + { + vert = edges[edge[i]]; + t = (value - cellScalars->GetComponent(vert[0],0)) / + (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + this->Points->GetPoint(vert[0], x1); + this->Points->GetPoint(vert[1], x2); + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + int p1 = this->PointIds->GetId(vert[0]); + int p2 = this->PointIds->GetId(vert[1]); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate triangle + if ( pts[0] != pts[1] && + pts[0] != pts[2] && + pts[1] != pts[2] ) + { + newCellId = offset + polys->InsertNextCell(3,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + + +//---------------------------------------------------------------------------- +int *vtkVoxel::GetEdgeArray(int edgeId) +{ + return edges[edgeId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkVoxel::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} + +//---------------------------------------------------------------------------- +int *vtkVoxel::GetFaceArray(int faceId) +{ + return faces[faceId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkVoxel::GetFace(int faceId) +{ + int *verts, i; + + verts = faces[faceId]; + + for (i=0; i<4; i++) + { + this->Pixel->PointIds->SetId(i,this->PointIds->GetId(verts[i])); + this->Pixel->Points->SetPoint(i,this->Points->GetPoint(verts[i])); + } + + return this->Pixel; +} + +//---------------------------------------------------------------------------- +// +// Intersect voxel with line using "bounding box" intersection. +// +int vtkVoxel::IntersectWithLine(double p1[3], double p2[3], + double vtkNotUsed(tol), + double& t, double x[3], + double pcoords[3], int& subId) +{ + double minPt[3], maxPt[3]; + double bounds[6]; + double p21[3]; + int i; + + subId = 0; + + this->Points->GetPoint(0, minPt); + this->Points->GetPoint(7, maxPt); + + for (i=0; i<3; i++) + { + p21[i] = p2[i] - p1[i]; + bounds[2*i] = minPt[i]; + bounds[2*i+1] = maxPt[i]; + } + + if ( ! vtkBox::IntersectBox(bounds, p1, p21, x, t) ) + { + return 0; + } + + // + // Evaluate intersection + // + for (i=0; i<3; i++) + { + pcoords[i] = (x[i] - minPt[i]) / (maxPt[i] - minPt[i]); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkVoxel::Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts) +{ + int p[4], i; + + ptIds->Reset(); + pts->Reset(); + // + // Create five tetrahedron. Triangulation varies depending upon index. This + // is necessary to insure compatible voxel triangulations. + // + if ( (index % 2) ) + { + p[0] = 0; p[1] = 1; p[2] = 2; p[3] = 4; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 1; p[1] = 4; p[2] = 5; p[3] = 7; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 1; p[1] = 4; p[2] = 7; p[3] = 2; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 1; p[1] = 2; p[2] = 7; p[3] = 3; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 2; p[1] = 7; p[2] = 6; p[3] = 4; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + } + else + { + p[0] = 3; p[1] = 1; p[2] = 5; p[3] = 0; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 0; p[1] = 3; p[2] = 2; p[3] = 6; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 3; p[1] = 5; p[2] = 7; p[3] = 6; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 0; p[1] = 6; p[2] = 4; p[3] = 5; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + + p[0] = 0; p[1] = 3; p[2] = 6; p[3] = 5; + for ( i=0; i < 4; i++ ) + { + ptIds->InsertNextId(this->PointIds->GetId(p[i])); + pts->InsertNextPoint(this->Points->GetPoint(p[i])); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkVoxel::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + double functionDerivs[24], sum; + int i, j, k; + double x0[3], x1[3], x2[3], x4[3], spacing[3]; + + this->Points->GetPoint(0, x0); + this->Points->GetPoint(1, x1); + spacing[0] = x1[0] - x0[0]; + + this->Points->GetPoint(2, x2); + spacing[1] = x2[1] - x0[1]; + + this->Points->GetPoint(4, x4); + spacing[2] = x4[2] - x0[2]; + + // get derivatives in r-s-t directions + this->InterpolationDerivs(pcoords, functionDerivs); + + // since the x-y-z axes are aligned with r-s-t axes, only need to scale + // the derivative values by the data spacing. + for (k=0; k < dim; k++) //loop over values per vertex + { + for (j=0; j < 3; j++) //loop over derivative directions + { + for (sum=0.0, i=0; i < 8; i++) //loop over interp. function derivatives + { + sum += functionDerivs[8*j + i] * values[dim*i + k]; + } + derivs[3*k + j] = sum / spacing[j]; + } + } +} + +//---------------------------------------------------------------------------- +void vtkVoxel::GetEdgePoints(int edgeId, int* &pts) +{ + pts = this->GetEdgeArray(edgeId); +} + +//---------------------------------------------------------------------------- +void vtkVoxel::GetFacePoints(int faceId, int* &pts) +{ + pts = this->GetFaceArray(faceId); +} + +static double vtkVoxelCellPCoords[24] = {0.0,0.0,0.0, 1.0,0.0,0.0, + 0.0,1.0,0.0, 1.0,1.0,0.0, + 0.0,0.0,1.0, 1.0,0.0,1.0, + 0.0,1.0,1.0, 1.0,1.0,1.0}; + +//---------------------------------------------------------------------------- +double *vtkVoxel::GetParametricCoords() +{ + return vtkVoxelCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkVoxel::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Pixel:\n"; + this->Pixel->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkVoxel.h b/Filtering/vtkVoxel.h new file mode 100644 index 0000000..6c7a834 --- /dev/null +++ b/Filtering/vtkVoxel.h @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoxel.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVoxel - a cell that represents a 3D orthogonal parallelepiped +// .SECTION Description +// vtkVoxel is a concrete implementation of vtkCell to represent a 3D +// orthogonal parallelepiped. Unlike vtkHexahedron, vtkVoxel has interior +// angles of 90 degrees, and sides are parallel to coordinate axes. This +// results in large increases in computational performance. + +// .SECTION See Also +// vtkConvexPointSet vtkHexahedron vtkPyramid vtkTetra vtkWedge + +#ifndef __vtkVoxel_h +#define __vtkVoxel_h + +#include "vtkCell3D.h" + +class vtkLine; +class vtkPixel; + +class VTK_FILTERING_EXPORT vtkVoxel : public vtkCell3D +{ +public: + static vtkVoxel *New(); + vtkTypeRevisionMacro(vtkVoxel,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int edgeId, int* &pts); + virtual void GetFacePoints(int faceId, int* &pts); + virtual double *GetParametricCoords(); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_VOXEL;} + int GetCellDimension() {return 3;} + int GetNumberOfEdges() {return 12;} + int GetNumberOfFaces() {return 6;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + + // Description: + // Voxel specific methods for interpolation and derivatives. + static void InterpolationFunctions(double pcoords[3], double weights[8]); + static void InterpolationDerivs(double pcoords[3], double derivs[24]); + static int *GetEdgeArray(int edgeId); + static int *GetFaceArray(int faceId); + +protected: + vtkVoxel(); + ~vtkVoxel(); + + vtkLine *Line; + vtkPixel *Pixel; + +private: + vtkVoxel(const vtkVoxel&); // Not implemented. + void operator=(const vtkVoxel&); // Not implemented. +}; + +#endif + + diff --git a/Filtering/vtkWedge.cxx b/Filtering/vtkWedge.cxx new file mode 100644 index 0000000..506ad4b --- /dev/null +++ b/Filtering/vtkWedge.cxx @@ -0,0 +1,778 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWedge.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWedge.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkQuad.h" +#include "vtkTriangle.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkWedge, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkWedge); + +static const double VTK_DIVERGED = 1.e6; + +//---------------------------------------------------------------------------- +// Construct the wedge with six points. +vtkWedge::vtkWedge() +{ + this->Points->SetNumberOfPoints(6); + this->PointIds->SetNumberOfIds(6); + + for (int i = 0; i < 6; i++) + { + this->Points->SetPoint(i, 0.0, 0.0, 0.0); + this->PointIds->SetId(i,0); + } + + this->Line = vtkLine::New(); + this->Triangle = vtkTriangle::New(); + this->Quad = vtkQuad::New(); +} + +//---------------------------------------------------------------------------- +vtkWedge::~vtkWedge() +{ + this->Line->Delete(); + this->Triangle->Delete(); + this->Quad->Delete(); +} + + +static const int VTK_WEDGE_MAX_ITERATION=10; +static const double VTK_WEDGE_CONVERGED=1.e-03; + +//---------------------------------------------------------------------------- +int vtkWedge::EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights) +{ + int iteration, converged; + double params[3]; + double fcol[3], rcol[3], scol[3], tcol[3]; + int i, j; + double d, pt[3]; + double derivs[18]; + + // set initial position for Newton's method + subId = 0; + pcoords[0] = pcoords[1] = pcoords[2] = 0.5; + params[0] = params[1] = params[2] = 0.5; + + // enter iteration loop + for (iteration=converged=0; !converged && (iteration < VTK_WEDGE_MAX_ITERATION); + iteration++) + { + // calculate element interpolation functions and derivatives + this->InterpolationFunctions(pcoords, weights); + this->InterpolationDerivs(pcoords, derivs); + + // calculate newton functions + for (i=0; i<3; i++) + { + fcol[i] = rcol[i] = scol[i] = tcol[i] = 0.0; + } + for (i=0; i<6; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + fcol[j] += pt[j] * weights[i]; + rcol[j] += pt[j] * derivs[i]; + scol[j] += pt[j] * derivs[i+6]; + tcol[j] += pt[j] * derivs[i+12]; + } + } + + for (i=0; i<3; i++) + { + fcol[i] -= x[i]; + } + + // compute determinants and generate improvements + d=vtkMath::Determinant3x3(rcol,scol,tcol); + if ( fabs(d) < 1.e-20) + { + return -1; + } + + pcoords[0] = params[0] - vtkMath::Determinant3x3 (fcol,scol,tcol) / d; + pcoords[1] = params[1] - vtkMath::Determinant3x3 (rcol,fcol,tcol) / d; + pcoords[2] = params[2] - vtkMath::Determinant3x3 (rcol,scol,fcol) / d; + + // check for convergence + if ( ((fabs(pcoords[0]-params[0])) < VTK_WEDGE_CONVERGED) && + ((fabs(pcoords[1]-params[1])) < VTK_WEDGE_CONVERGED) && + ((fabs(pcoords[2]-params[2])) < VTK_WEDGE_CONVERGED) ) + { + converged = 1; + } + // Test for bad divergence (S.Hirschberg 11.12.2001) + else if ((fabs(pcoords[0]) > VTK_DIVERGED) || + (fabs(pcoords[1]) > VTK_DIVERGED) || + (fabs(pcoords[2]) > VTK_DIVERGED)) + { + return -1; + } + // if not converged, repeat + else + { + params[0] = pcoords[0]; + params[1] = pcoords[1]; + params[2] = pcoords[2]; + } + } + + // if not converged, set the parametric coordinates to arbitrary values + // outside of element + if ( !converged ) + { + return -1; + } + + this->InterpolationFunctions(pcoords, weights); + + if ( pcoords[0] >= -0.001 && pcoords[0] <= 1.001 && + pcoords[1] >= -0.001 && pcoords[1] <= 1.001 && + pcoords[2] >= -0.001 && pcoords[2] <= 1.001 ) + { + if (closestPoint) + { + closestPoint[0] = x[0]; closestPoint[1] = x[1]; closestPoint[2] = x[2]; + dist2 = 0.0; //inside wedge + } + return 1; + } + else + { + double pc[3], w[6]; + if (closestPoint) + { + for (i=0; i<3; i++) //only approximate, not really true for warped hexa + { + if (pcoords[i] < 0.0) + { + pc[i] = 0.0; + } + else if (pcoords[i] > 1.0) + { + pc[i] = 1.0; + } + else + { + pc[i] = pcoords[i]; + } + } + this->EvaluateLocation(subId, pc, closestPoint, (double *)w); + dist2 = vtkMath::Distance2BetweenPoints(closestPoint,x); + } + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkWedge::EvaluateLocation(int& vtkNotUsed(subId), double pcoords[3], + double x[3], double *weights) +{ + int i, j; + double pt[3]; + + this->InterpolationFunctions(pcoords, weights); + + x[0] = x[1] = x[2] = 0.0; + for (i=0; i<6; i++) + { + this->Points->GetPoint(i, pt); + for (j=0; j<3; j++) + { + x[j] += pt[j] * weights[i]; + } + } +} + +//---------------------------------------------------------------------------- +// Returns the closest face to the point specified. Closeness is measured +// parametrically. +int vtkWedge::CellBoundary(int vtkNotUsed(subId), double pcoords[3], + vtkIdList *pts) +{ + int i; + + // define 9 planes that separate regions + static double normals[9][3] = { + {0.0,0.83205,-0.5547}, {-0.639602,-0.639602,-0.426401}, {0.83205,0.0,-0.5547}, + {0.0,0.83205,0.5547}, {-0.639602,-0.639602,0.426401}, {0.83205,0.0,0.5547}, + {-0.707107,0.707107,0.0}, {0.447214,0.894427,0.0}, {0.894427,0.447214,0.0} }; + static double point[3] = {0.333333,0.333333,0.5}; + double vals[9]; + + // evaluate 9 plane equations + for (i=0; i<9; i++) + { + vals[i] = normals[i][0]*(pcoords[0]-point[0]) + + normals[i][1]*(pcoords[1]-point[1]) + normals[i][2]*(pcoords[2]-point[2]); + } + + // compare against nine planes in parametric space that divide element + // into five pieces (each corresponding to a face). + if ( vals[0] >= 0.0 && vals[1] >= 0.0 && vals[2] >= 0.0 ) + { + pts->SetNumberOfIds(3); //triangle face + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(2)); + } + + else if ( vals[3] >= 0.0 && vals[4] >= 0.0 && vals[5] >= 0.0 ) + { + pts->SetNumberOfIds(3); //triangle face + pts->SetId(0,this->PointIds->GetId(3)); + pts->SetId(1,this->PointIds->GetId(4)); + pts->SetId(2,this->PointIds->GetId(5)); + } + + else if ( vals[0] <= 0.0 && vals[3] <= 0.0 && + vals[6] <= 0.0 && vals[7] <= 0.0 ) + { + pts->SetNumberOfIds(4); //quad face + pts->SetId(0,this->PointIds->GetId(0)); + pts->SetId(1,this->PointIds->GetId(1)); + pts->SetId(2,this->PointIds->GetId(4)); + pts->SetId(3,this->PointIds->GetId(3)); + } + + else if ( vals[1] <= 0.0 && vals[4] <= 0.0 && + vals[7] >= 0.0 && vals[8] >= 0.0 ) + { + pts->SetNumberOfIds(4); //quad face + pts->SetId(0,this->PointIds->GetId(1)); + pts->SetId(1,this->PointIds->GetId(2)); + pts->SetId(2,this->PointIds->GetId(5)); + pts->SetId(3,this->PointIds->GetId(4)); + } + + else //vals[2] <= 0.0 && vals[5] <= 0.0 && vals[8] <= 0.0 && vals[6] >= 0.0 + { + pts->SetNumberOfIds(4); //quad face + pts->SetId(0,this->PointIds->GetId(2)); + pts->SetId(1,this->PointIds->GetId(0)); + pts->SetId(2,this->PointIds->GetId(3)); + pts->SetId(3,this->PointIds->GetId(5)); + } + + if ( pcoords[0] < 0.0 || pcoords[0] > 1.0 || + pcoords[1] < 0.0 || pcoords[1] > 1.0 || + pcoords[2] < 0.0 || pcoords[2] > 1.0 ) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +// Marching (convex) wedge +// +static int edges[9][2] = { {0,1}, {1,2}, {2,0}, + {3,4}, {4,5}, {5,3}, + {0,3}, {1,4}, {2,5} }; +static int faces[5][4] = { {0,1,2,-1}, {3,5,4,-1}, + {0,3,4,1}, {1,4,5,2}, {2,5,3,0} }; + +typedef int EDGE_LIST; +typedef struct { + EDGE_LIST edges[13]; +} TRIANGLE_CASES; + +static TRIANGLE_CASES triCases[] = { + {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //0 + {{ 0, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //1 + {{ 0, 1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //2 + {{ 6, 1, 7, 6, 2, 1, -1, -1, -1, -1, -1, -1, -1}}, //3 + {{ 1, 2, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //4 + {{ 6, 1, 0, 6, 8, 1, -1, -1, -1, -1, -1, -1, -1}}, //5 + {{ 0, 2, 8, 7, 0, 8, -1, -1, -1, -1, -1, -1, -1}}, //6 + {{ 7, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //7 + {{ 3, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //8 + {{ 3, 5, 0, 5, 2, 0, -1, -1, -1, -1, -1, -1, -1}}, //9 + {{ 0, 1, 7, 6, 3, 5, -1, -1, -1, -1, -1, -1, -1}}, //10 + {{ 1, 7, 3, 1, 3, 5, 1, 5, 2, -1, -1, -1, -1}}, //11 + {{ 2, 8, 1, 6, 3, 5, -1, -1, -1, -1, -1, -1, -1}}, //12 + {{ 0, 3, 1, 1, 3, 5, 1, 5, 8, -1, -1, -1, -1}}, //13 + {{ 6, 3, 5, 0, 8, 7, 0, 2, 8, -1, -1, -1, -1}}, //14 + {{ 7, 3, 5, 7, 5, 8, -1, -1, -1, -1, -1, -1, -1}}, //15 + {{ 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //16 + {{ 7, 4, 3, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}}, //17 + {{ 0, 1, 3, 1, 4, 3, -1, -1, -1, -1, -1, -1, -1}}, //18 + {{ 1, 4, 3, 1, 3, 6, 1, 6, 2, -1, -1, -1, -1}}, //19 + {{ 7, 4, 3, 2, 8, 1, -1, -1, -1, -1, -1, -1, -1}}, //20 + {{ 7, 4, 3, 6, 1, 0, 6, 8, 1, -1, -1, -1, -1}}, //21 + {{ 0, 4, 3, 0, 8, 4, 0, 2, 8, -1, -1, -1, -1}}, //22 + {{ 6, 8, 3, 3, 8, 4, -1, -1, -1, -1, -1, -1, -1}}, //23 + {{ 6, 7, 4, 6, 4, 5, -1, -1, -1, -1, -1, -1, -1}}, //24 + {{ 0, 7, 5, 7, 4, 5, 2, 0, 5, -1, -1, -1, -1}}, //25 + {{ 1, 6, 0, 1, 5, 6, 1, 4, 5, -1, -1, -1, -1}}, //26 + {{ 2, 1, 5, 5, 1, 4, -1, -1, -1, -1, -1, -1, -1}}, //27 + {{ 2, 8, 1, 6, 7, 5, 7, 4, 5, -1, -1, -1, -1}}, //28 + {{ 0, 7, 5, 7, 4, 5, 0, 5, 1, 1, 5, 8, -1}}, //29 + {{ 0, 2, 8, 0, 8, 4, 0, 4, 5, 0, 5, 6, -1}}, //30 + {{ 8, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //31 + {{ 4, 8, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //32 + {{ 4, 8, 5, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}}, //33 + {{ 4, 8, 5, 0, 1, 7, -1, -1, -1, -1, -1, -1, -1}}, //34 + {{ 4, 8, 5, 6, 1, 7, 6, 2, 1, -1, -1, -1, -1}}, //35 + {{ 1, 5, 4, 2, 5, 1, -1, -1, -1, -1, -1, -1, -1}}, //36 + {{ 1, 5, 4, 1, 6, 5, 1, 0, 6, -1, -1, -1, -1}}, //37 + {{ 5, 4, 7, 5, 7, 0, 5, 0, 2, -1, -1, -1, -1}}, //38 + {{ 6, 4, 7, 6, 5, 4, -1, -1, -1, -1, -1, -1, -1}}, //39 + {{ 6, 3, 8, 3, 4, 8, -1, -1, -1, -1, -1, -1, -1}}, //40 + {{ 0, 3, 4, 0, 4, 8, 0, 8, 2, -1, -1, -1, -1}}, //41 + {{ 7, 0, 1, 6, 3, 4, 6, 4, 8, -1, -1, -1, -1}}, //42 + {{ 1, 7, 3, 1, 3, 2, 2, 3, 8, 8, 3, 4, -1}}, //43 + {{ 2, 6, 1, 6, 3, 1, 3, 4, 1, -1, -1, -1, -1}}, //44 + {{ 0, 3, 1, 1, 3, 4, -1, -1, -1, -1, -1, -1, -1}}, //45 + {{ 7, 0, 4, 4, 0, 2, 4, 2, 3, 3, 2, 6, -1}}, //46 + {{ 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //47 + {{ 7, 8, 5, 7, 5, 3, -1, -1, -1, -1, -1, -1, -1}}, //48 + {{ 0, 6, 2, 7, 8, 5, 7, 5, 3, -1, -1, -1, -1}}, //49 + {{ 0, 1, 3, 1, 5, 3, 1, 8, 5, -1, -1, -1, -1}}, //50 + {{ 2, 1, 6, 6, 1, 3, 5, 1, 8, 3, 1, 5, -1}}, //51 + {{ 1, 3, 7, 1, 5, 3, 1, 2, 5, -1, -1, -1, -1}}, //52 + {{ 1, 0, 6, 1, 6, 5, 1, 5, 7, 7, 5, 3, -1}}, //53 + {{ 0, 2, 5, 0, 5, 3, -1, -1, -1, -1, -1, -1, -1}}, //54 + {{ 3, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //55 + {{ 7, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //56 + {{ 0, 7, 8, 0, 8, 2, -1, -1, -1, -1, -1, -1, -1}}, //57 + {{ 0, 1, 6, 1, 8, 6, -1, -1, -1, -1, -1, -1, -1}}, //58 + {{ 2, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //59 + {{ 6, 7, 1, 6, 1, 2, -1, -1, -1, -1, -1, -1, -1}}, //60 + {{ 0, 7, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //61 + {{ 0, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, //62 + {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}} //63 +}; + +//---------------------------------------------------------------------------- +void vtkWedge::Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) +{ + static int CASE_MASK[6] = {1,2,4,8,16,32}; + TRIANGLE_CASES *triCase; + EDGE_LIST *edge; + int i, j, index, *vert, v1, v2, newCellId; + vtkIdType pts[3]; + double t, x1[3], x2[3], x[3], deltaScalar; + vtkIdType offset = verts->GetNumberOfCells() + lines->GetNumberOfCells(); + + // Build the case table + for ( i=0, index = 0; i < 6; i++) + { + if (cellScalars->GetComponent(i,0) >= value) + { + index |= CASE_MASK[i]; + } + } + + triCase = triCases + index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (i=0; i<3; i++) // insert triangle + { + vert = edges[edge[i]]; + + // calculate a preferred interpolation direction + deltaScalar = (cellScalars->GetComponent(vert[1],0) + - cellScalars->GetComponent(vert[0],0)); + if (deltaScalar > 0) + { + v1 = vert[0]; v2 = vert[1]; + } + else + { + v1 = vert[1]; v2 = vert[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + (value - cellScalars->GetComponent(v1,0)) / deltaScalar ); + + this->Points->GetPoint(v1, x1); + this->Points->GetPoint(v2, x2); + + for (j=0; j<3; j++) + { + x[j] = x1[j] + t * (x2[j] - x1[j]); + } + if ( locator->InsertUniquePoint(x, pts[i]) ) + { + if ( outPd ) + { + vtkIdType p1 = this->PointIds->GetId(v1); + vtkIdType p2 = this->PointIds->GetId(v2); + outPd->InterpolateEdge(inPd,pts[i],p1,p2,t); + } + } + } + // check for degenerate triangle + if ( pts[0] != pts[1] && pts[0] != pts[2] && pts[1] != pts[2] ) + { + newCellId = offset + polys->InsertNextCell(3,pts); + outCd->CopyData(inCd,cellId,newCellId); + } + } +} + +//---------------------------------------------------------------------------- +int *vtkWedge::GetEdgeArray(int edgeId) +{ + return edges[edgeId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkWedge::GetEdge(int edgeId) +{ + int *verts; + + verts = edges[edgeId]; + + // load point id's + this->Line->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Line->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + + // load coordinates + this->Line->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Line->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + + return this->Line; +} + +//---------------------------------------------------------------------------- +int *vtkWedge::GetFaceArray(int faceId) +{ + return faces[faceId]; +} + +//---------------------------------------------------------------------------- +vtkCell *vtkWedge::GetFace(int faceId) +{ + int *verts = faces[faceId]; + + if ( verts[3] != -1 ) // quad cell + { + // load point id's + this->Quad->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Quad->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Quad->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + this->Quad->PointIds->SetId(3,this->PointIds->GetId(verts[3])); + + // load coordinates + this->Quad->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Quad->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Quad->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + this->Quad->Points->SetPoint(3,this->Points->GetPoint(verts[3])); + + return this->Quad; + } + else + { + // load point id's + this->Triangle->PointIds->SetId(0,this->PointIds->GetId(verts[0])); + this->Triangle->PointIds->SetId(1,this->PointIds->GetId(verts[1])); + this->Triangle->PointIds->SetId(2,this->PointIds->GetId(verts[2])); + + // load coordinates + this->Triangle->Points->SetPoint(0,this->Points->GetPoint(verts[0])); + this->Triangle->Points->SetPoint(1,this->Points->GetPoint(verts[1])); + this->Triangle->Points->SetPoint(2,this->Points->GetPoint(verts[2])); + + return this->Triangle; + } +} + +//---------------------------------------------------------------------------- +// Intersect faces against line. +// +int vtkWedge::IntersectWithLine(double p1[3], double p2[3], + double tol, double& t, + double x[3], double pcoords[3], int& subId) +{ + int intersection=0; + double pt1[3], pt2[3], pt3[3], pt4[3]; + double tTemp; + double pc[3], xTemp[3]; + int faceNum; + + t = VTK_DOUBLE_MAX; + + //first intersect the triangle faces + for (faceNum=0; faceNum<2; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + + this->Triangle->Points->SetPoint(0,pt1); + this->Triangle->Points->SetPoint(1,pt2); + this->Triangle->Points->SetPoint(2,pt3); + + if ( this->Triangle->IntersectWithLine(p1, p2, tol, tTemp, xTemp, + pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 0: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 0.0; + break; + + case 1: + pcoords[0] = pc[0]; pcoords[1] = pc[1]; pcoords[2] = 1.0; + break; + } + } + } + } + + //now intersect the quad faces + for (faceNum=2; faceNum<5; faceNum++) + { + this->Points->GetPoint(faces[faceNum][0], pt1); + this->Points->GetPoint(faces[faceNum][1], pt2); + this->Points->GetPoint(faces[faceNum][2], pt3); + this->Points->GetPoint(faces[faceNum][3], pt4); + + this->Quad->Points->SetPoint(0,pt1); + this->Quad->Points->SetPoint(1,pt2); + this->Quad->Points->SetPoint(2,pt3); + this->Quad->Points->SetPoint(3,pt4); + + if ( this->Quad->IntersectWithLine(p1, p2, tol, tTemp, xTemp, pc, subId) ) + { + intersection = 1; + if ( tTemp < t ) + { + t = tTemp; + x[0] = xTemp[0]; x[1] = xTemp[1]; x[2] = xTemp[2]; + switch (faceNum) + { + case 2: + pcoords[0] = pc[1]; pcoords[1] = 0.0; pcoords[2] = pc[0]; + break; + + case 3: + pcoords[0] = 1.0-pc[1]; pcoords[1] = pc[1]; pcoords[2] = pc[0]; + break; + + case 4: + pcoords[0] = 0.0; pcoords[1] = pc[1]; pcoords[2] = pc[0]; + break; + } + } + } + } + + return intersection; +} + +//---------------------------------------------------------------------------- +int vtkWedge::Triangulate(int vtkNotUsed(index), vtkIdList *ptIds, + vtkPoints *pts) +{ + ptIds->Reset(); + pts->Reset(); + + for ( int i=0; i < 4; i++ ) + { + ptIds->InsertId(i,this->PointIds->GetId(i)); + pts->InsertPoint(i,this->Points->GetPoint(i)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkWedge::Derivatives(int vtkNotUsed(subId), double pcoords[3], + double *values, int dim, double *derivs) +{ + double *jI[3], j0[3], j1[3], j2[3]; + double functionDerivs[18], sum[3], value; + int i, j, k; + + // compute inverse Jacobian and interpolation function derivatives + jI[0] = j0; jI[1] = j1; jI[2] = j2; + this->JacobianInverse(pcoords, jI, functionDerivs); + + // now compute derivates of values provided + for (k=0; k < dim; k++) //loop over values per vertex + { + sum[0] = sum[1] = sum[2] = 0.0; + for ( i=0; i < 6; i++) //loop over interp. function derivatives + { + value = values[dim*i + k]; + sum[0] += functionDerivs[i] * value; + sum[1] += functionDerivs[6 + i] * value; + sum[2] += functionDerivs[12 + i] * value; + } + + for (j=0; j < 3; j++) //loop over derivative directions + { + derivs[3*k + j] = sum[0]*jI[j][0] + sum[1]*jI[j][1] + sum[2]*jI[j][2]; + } + } +} + +//---------------------------------------------------------------------------- +// Compute iso-parametric interpolation functions +// +void vtkWedge::InterpolationFunctions(double pcoords[3], double sf[6]) +{ + sf[0] = (1.0 - pcoords[0] - pcoords[1]) * (1.0 - pcoords[2]); + sf[1] = pcoords[0] * (1.0 - pcoords[2]); + sf[2] = pcoords[1] * (1.0 - pcoords[2]); + sf[3] = (1.0 - pcoords[0] - pcoords[1]) * pcoords[2]; + sf[4] = pcoords[0] * pcoords[2]; + sf[5] = pcoords[1] * pcoords[2]; +} + +//---------------------------------------------------------------------------- +void vtkWedge::InterpolationDerivs(double pcoords[3], double derivs[18]) +{ + // r-derivatives + derivs[0] = -1.0 + pcoords[2]; + derivs[1] = 1.0 - pcoords[2]; + derivs[2] = 0.0; + derivs[3] = -pcoords[2]; + derivs[4] = pcoords[2]; + derivs[5] = 0.0; + + // s-derivatives + derivs[6] = -1.0 + pcoords[2]; + derivs[7] = 0.0; + derivs[8] = 1.0 - pcoords[2]; + derivs[9] = -pcoords[2]; + derivs[10] = 0.0; + derivs[11] = pcoords[2]; + + // t-derivatives + derivs[12] = -1.0 + pcoords[0] + pcoords[1]; + derivs[13] = -pcoords[0]; + derivs[14] = -pcoords[1]; + derivs[15] = 1.0 - pcoords[0] - pcoords[1]; + derivs[16] = pcoords[0]; + derivs[17] = pcoords[1]; +} + +//---------------------------------------------------------------------------- +// Given parametric coordinates compute inverse Jacobian transformation +// matrix. Returns 9 elements of 3x3 inverse Jacobian plus interpolation +// function derivatives. Returns 0 if no inverse exists. +int vtkWedge::JacobianInverse(double pcoords[3], double **inverse, + double derivs[18]) +{ + int i, j; + double *m[3], m0[3], m1[3], m2[3]; + double x[3]; + + // compute interpolation function derivatives + this->InterpolationDerivs(pcoords,derivs); + + // create Jacobian matrix + m[0] = m0; m[1] = m1; m[2] = m2; + for (i=0; i < 3; i++) //initialize matrix + { + m0[i] = m1[i] = m2[i] = 0.0; + } + + for ( j=0; j < 6; j++ ) + { + this->Points->GetPoint(j, x); + for ( i=0; i < 3; i++ ) + { + m0[i] += x[i] * derivs[j]; + m1[i] += x[i] * derivs[6 + j]; + m2[i] += x[i] * derivs[12 + j]; + } + } + + // now find the inverse + if ( vtkMath::InvertMatrix(m,inverse,3) == 0 ) + { +#define VTK_MAX_WARNS 3 + static int numWarns=0; + if ( numWarns++ < VTK_MAX_WARNS ) + { + vtkErrorMacro(<<"Jacobian inverse not found"); + vtkErrorMacro(<<"Matrix:" << m[0][0] << " " << m[0][1] << " " << m[0][2] + << m[1][0] << " " << m[1][1] << " " << m[1][2] + << m[2][0] << " " << m[2][1] << " " << m[2][2] ); + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkWedge::GetEdgePoints(int edgeId, int* &pts) +{ + pts = this->GetEdgeArray(edgeId); +} + +//---------------------------------------------------------------------------- +void vtkWedge::GetFacePoints(int faceId, int* &pts) +{ + pts = this->GetFaceArray(faceId); +} + +static double vtkWedgeCellPCoords[18] = {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,1.0, 0.0,1.0,1.0}; + +//---------------------------------------------------------------------------- +double *vtkWedge::GetParametricCoords() +{ + return vtkWedgeCellPCoords; +} + +//---------------------------------------------------------------------------- +void vtkWedge::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Line:\n"; + this->Line->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Triangle:\n"; + this->Triangle->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Quad:\n"; + this->Quad->PrintSelf(os,indent.GetNextIndent()); +} diff --git a/Filtering/vtkWedge.h b/Filtering/vtkWedge.h new file mode 100644 index 0000000..03bb469 --- /dev/null +++ b/Filtering/vtkWedge.h @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWedge.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWedge - a 3D cell that represents a linear wedge +// .SECTION Description +// vtkWedge is a concrete implementation of vtkCell to represent a linear 3D +// wedge. A wedge consists of two triangular and three quadrilateral faces +// and is defined by the six points (0-5). vtkWedge uses the standard +// isoparametric shape functions for a linear wedge. The wedge is defined +// by the six points (0-5) where (0,1,2) is the base of the wedge which, +// using the right hand rule, forms a triangle whose normal points outward +// (away from the triangular face (3,4,5)). + +// .SECTION See Also +// vtkConvexPointSet vtkHexahedron vtkPyramid vtkTetra vtkVoxel + +#ifndef __vtkWedge_h +#define __vtkWedge_h + +#include "vtkCell3D.h" + +class vtkLine; +class vtkTriangle; +class vtkQuad; + +class vtkUnstructuredGrid; + +class VTK_FILTERING_EXPORT vtkWedge : public vtkCell3D +{ +public: + static vtkWedge *New(); + vtkTypeRevisionMacro(vtkWedge,vtkCell3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // See vtkCell3D API for description of these methods. + virtual void GetEdgePoints(int edgeId, int* &pts); + virtual void GetFacePoints(int faceId, int* &pts); + + // Description: + // See the vtkCell API for descriptions of these methods. + int GetCellType() {return VTK_WEDGE;} + int GetCellDimension() {return 3;} + int GetNumberOfEdges() {return 9;} + int GetNumberOfFaces() {return 5;} + vtkCell *GetEdge(int edgeId); + vtkCell *GetFace(int faceId); + int CellBoundary(int subId, double pcoords[3], vtkIdList *pts); + void Contour(double value, vtkDataArray *cellScalars, + vtkPointLocator *locator, vtkCellArray *verts, + vtkCellArray *lines, vtkCellArray *polys, + vtkPointData *inPd, vtkPointData *outPd, + vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); + int EvaluatePosition(double x[3], double* closestPoint, + int& subId, double pcoords[3], + double& dist2, double *weights); + void EvaluateLocation(int& subId, double pcoords[3], double x[3], + double *weights); + int IntersectWithLine(double p1[3], double p2[3], double tol, double& t, + double x[3], double pcoords[3], int& subId); + int Triangulate(int index, vtkIdList *ptIds, vtkPoints *pts); + void Derivatives(int subId, double pcoords[3], double *values, + int dim, double *derivs); + virtual double *GetParametricCoords(); + + // Description: + // Return the center of the wedge in parametric coordinates. + int GetParametricCenter(double pcoords[3]); + + // Description: + // Wedge specific methods for computing interpolation functions and + // derivatives. + static void InterpolationFunctions(double pcoords[3], double weights[6]); + static void InterpolationDerivs(double pcoords[3], double derivs[18]); + int JacobianInverse(double pcoords[3], double **inverse, double derivs[18]); + static int *GetEdgeArray(int edgeId); + static int *GetFaceArray(int faceId); + +protected: + vtkWedge(); + ~vtkWedge(); + + vtkLine *Line; + vtkTriangle *Triangle; + vtkQuad *Quad; + +private: + vtkWedge(const vtkWedge&); // Not implemented. + void operator=(const vtkWedge&); // Not implemented. +}; + +inline int vtkWedge::GetParametricCenter(double pcoords[3]) +{ + pcoords[0] = pcoords[1] = 0.333333; + pcoords[2] = 0.5; + return 0; +} + +#endif + + + diff --git a/GUISupport/CMakeLists.txt b/GUISupport/CMakeLists.txt new file mode 100644 index 0000000..ef5664c --- /dev/null +++ b/GUISupport/CMakeLists.txt @@ -0,0 +1,26 @@ + + + +# Determine Qt GUI. +IF(APPLE) + # must use Carbon on the Mac to interface with Qt + VTK_DEPENDENT_OPTION(VTK_USE_QVTK "Build QVTK widget and plugin for Qt" OFF + "VTK_USE_GUISUPPORT;VTK_USE_RENDERING;VTK_USE_CARBON" OFF) +ELSE(APPLE) + VTK_DEPENDENT_OPTION(VTK_USE_QVTK "Build QVTK widget and plugin for Qt" OFF + "VTK_USE_GUISUPPORT;VTK_USE_RENDERING" OFF) +ENDIF(APPLE) + +IF(WIN32) + VTK_DEPENDENT_OPTION(VTK_USE_MFC "Build MFC classes for VTK" OFF + "VTK_USE_GUISUPPORT;VTK_USE_RENDERING" OFF) +ENDIF(WIN32) + +IF(VTK_USE_QVTK) + SUBDIRS(Qt) +ENDIF(VTK_USE_QVTK) + +IF(VTK_USE_MFC) + SUBDIRS(MFC) +ENDIF(VTK_USE_MFC) + diff --git a/GUISupport/MFC/CMakeLists.txt b/GUISupport/MFC/CMakeLists.txt new file mode 100644 index 0000000..9b876f5 --- /dev/null +++ b/GUISupport/MFC/CMakeLists.txt @@ -0,0 +1,35 @@ + +SET( MFC_SRCS + vtkMFCWindow.cpp +) + +# add stuff to use MFC in this executable +ADD_DEFINITIONS(-D_AFXDLL) +SET(CMAKE_MFC_FLAG 6) + +ADD_LIBRARY(vtkMFC ${MFC_SRCS}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkMFC PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +TARGET_LINK_LIBRARIES( vtkMFC + vtkRendering + vtkGraphics + vtkImaging + vtkIO + vtkFiltering + vtkCommon +) + +IF ( WIN32 ) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES( ${VTK_INSTALL_INCLUDE_DIR} .h ) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS( ${VTK_INSTALL_LIB_DIR} RUNTIME_DIRECTORY ${VTK_INSTALL_BIN_DIR} vtkMFC ) + ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +ENDIF ( WIN32 ) + + diff --git a/GUISupport/MFC/vtkMFCWindow.cpp b/GUISupport/MFC/vtkMFCWindow.cpp new file mode 100644 index 0000000..3583e81 --- /dev/null +++ b/GUISupport/MFC/vtkMFCWindow.cpp @@ -0,0 +1,279 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMFCWindow.cpp,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + + +#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. +#define WINVER 0x0400 +#endif + +#include "vtkMFCWindow.h" + +#include "vtkWin32OpenGLRenderWindow.h" +#include "vtkWin32RenderWindowInteractor.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +BEGIN_MESSAGE_MAP(vtkMFCWindow, CWnd) + ON_WM_SIZE() + ON_WM_PAINT() + ON_WM_DESTROY() + ON_WM_ERASEBKGND() + + ON_WM_LBUTTONDBLCLK() + ON_WM_LBUTTONDOWN() + ON_WM_MBUTTONDOWN() + ON_WM_RBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_MBUTTONUP() + ON_WM_RBUTTONUP() + ON_WM_MOUSEMOVE() + ON_WM_MOUSEWHEEL() + ON_WM_CHAR() + ON_WM_KEYUP() + ON_WM_KEYDOWN() + ON_WM_TIMER() + +END_MESSAGE_MAP() + +#ifdef _DEBUG +void vtkMFCWindow::AssertValid() const +{ + CWnd::AssertValid(); +} + +void vtkMFCWindow::Dump(CDumpContext& dc) const +{ + CWnd::Dump(dc); +} +#endif //_DEBUG + + +vtkMFCWindow::vtkMFCWindow(CWnd *pcWnd) +{ + this->pvtkWin32OpenGLRW = NULL; + + // create self as a child of passed in parent + DWORD style = WS_VISIBLE | WS_CLIPSIBLINGS; + if(pcWnd) + style |= WS_CHILD; + BOOL bCreated = CWnd::Create(NULL, _T("VTK-MFC Window"), + style, CRect(0, 0, 1, 1), + pcWnd, (UINT)IDC_STATIC); + + SUCCEEDED(bCreated); + + // create a default vtk window + vtkWin32OpenGLRenderWindow* win = vtkWin32OpenGLRenderWindow::New(); + this->SetRenderWindow(win); + win->Delete(); + +} + +vtkMFCWindow::~vtkMFCWindow() +{ + this->SetRenderWindow(NULL); +} + +void vtkMFCWindow::OnDestroy() +{ + if(this->pvtkWin32OpenGLRW && this->pvtkWin32OpenGLRW->GetMapped()) + this->pvtkWin32OpenGLRW->Finalize(); + + CWnd::OnDestroy(); +} + +void vtkMFCWindow::SetRenderWindow(vtkWin32OpenGLRenderWindow* win) +{ + + if(this->pvtkWin32OpenGLRW) + { + if(this->pvtkWin32OpenGLRW->GetMapped()) + this->pvtkWin32OpenGLRW->Finalize(); + this->pvtkWin32OpenGLRW->UnRegister(NULL); + } + + this->pvtkWin32OpenGLRW = win; + + if(this->pvtkWin32OpenGLRW) + { + this->pvtkWin32OpenGLRW->Register(NULL); + + vtkWin32RenderWindowInteractor* iren = vtkWin32RenderWindowInteractor::New(); + iren->SetInstallMessageProc(0); + + // setup the parent window + this->pvtkWin32OpenGLRW->SetWindowId(this->GetSafeHwnd()); + this->pvtkWin32OpenGLRW->SetParentId(::GetParent(this->GetSafeHwnd())); + iren->SetRenderWindow(this->pvtkWin32OpenGLRW); + + iren->Initialize(); + + // update size + CRect cRect = CRect(0,0,1,1); + if(this->GetParent()) + this->GetParent()->GetClientRect(&cRect); + if (iren->GetInitialized()) + iren->UpdateSize(cRect.Width(), cRect.Height()); + + // release our hold on interactor + iren->Delete(); + } +} + +vtkWin32OpenGLRenderWindow* vtkMFCWindow::GetRenderWindow() +{ + return this->pvtkWin32OpenGLRW; +} + +vtkRenderWindowInteractor* vtkMFCWindow::GetInteractor() +{ + if(!this->pvtkWin32OpenGLRW) + return NULL; + return this->pvtkWin32OpenGLRW->GetInteractor(); +} + +void vtkMFCWindow::OnPaint() +{ + CPaintDC dc(this); + if (this->GetInteractor() && this->GetInteractor()->GetInitialized()) + { + this->GetInteractor()->Render(); + } +} + +void vtkMFCWindow::DrawDC(CDC* pDC) +{ + // Obtain the size of the printer page in pixels. + int cxPage = pDC->GetDeviceCaps(HORZRES); + int cyPage = pDC->GetDeviceCaps(VERTRES); + + // Get the size of the window in pixels. + int *size = this->pvtkWin32OpenGLRW->GetSize(); + int cxWindow = size[0]; + int cyWindow = size[1]; + float fx = float(cxPage) / float(cxWindow); + float fy = float(cyPage) / float(cyWindow); + float scale = min(fx,fy); + int x = int(scale * float(cxWindow)); + int y = int(scale * float(cyWindow)); + this->pvtkWin32OpenGLRW->SetupMemoryRendering(cxWindow, cyWindow, pDC->GetSafeHdc()); + this->pvtkWin32OpenGLRW->Render(); + HDC memDC = this->pvtkWin32OpenGLRW->GetMemoryDC(); + StretchBlt(pDC->GetSafeHdc(),0,0,x,y,memDC,0,0,cxWindow,cyWindow,SRCCOPY); + this->pvtkWin32OpenGLRW->ResumeScreenRendering(); +} + +void vtkMFCWindow::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + if (this->GetInteractor() && this->GetInteractor()->GetInitialized()) + this->GetInteractor()->UpdateSize(cx, cy); +} + +BOOL vtkMFCWindow::OnEraseBkgnd(CDC*) +{ + return TRUE; +} + +void vtkMFCWindow::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + static_cast(this->GetInteractor())-> + OnLButtonDown(this->GetSafeHwnd(), nFlags, point.x, point.y, 1); +} + +void vtkMFCWindow::OnLButtonDown(UINT nFlags, CPoint point) +{ + this->SetFocus(); + static_cast(this->GetInteractor())-> + OnLButtonDown(this->GetSafeHwnd(), nFlags, point.x, point.y, 0); +} + +void vtkMFCWindow::OnMButtonDown(UINT nFlags, CPoint point) +{ + this->SetFocus(); + static_cast(this->GetInteractor())-> + OnMButtonDown(this->GetSafeHwnd(), nFlags, point.x, point.y, 0); +} + +void vtkMFCWindow::OnRButtonDown(UINT nFlags, CPoint point) +{ + this->SetFocus(); + static_cast(this->GetInteractor())-> + OnRButtonDown(this->GetSafeHwnd(), nFlags, point.x, point.y, 0); +} + +void vtkMFCWindow::OnLButtonUp(UINT nFlags, CPoint point) +{ + static_cast(this->GetInteractor())-> + OnLButtonUp(this->GetSafeHwnd(), nFlags, point.x, point.y); +} + +void vtkMFCWindow::OnMButtonUp(UINT nFlags, CPoint point) +{ + static_cast(this->GetInteractor())-> + OnMButtonUp(this->GetSafeHwnd(), nFlags, point.x, point.y); +} + +void vtkMFCWindow::OnRButtonUp(UINT nFlags, CPoint point) +{ + static_cast(this->GetInteractor())-> + OnRButtonUp(this->GetSafeHwnd(), nFlags, point.x, point.y); +} + +void vtkMFCWindow::OnMouseMove(UINT nFlags, CPoint point) +{ + static_cast(this->GetInteractor())-> + OnMouseMove(this->GetSafeHwnd(), nFlags, point.x, point.y); +} + +BOOL vtkMFCWindow::OnMouseWheel(UINT nFlags, short zDelta, CPoint point) +{ + if(zDelta > 0) + static_cast(this->GetInteractor())-> + OnMouseWheelForward(this->GetSafeHwnd(), nFlags, point.x, point.y); + else + static_cast(this->GetInteractor())-> + OnMouseWheelBackward(this->GetSafeHwnd(), nFlags, point.x, point.y); + return TRUE; +} + +void vtkMFCWindow::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + static_cast(this->GetInteractor())-> + OnChar(this->GetSafeHwnd(), nChar, nRepCnt, nFlags); +} + +void vtkMFCWindow::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + static_cast(this->GetInteractor())-> + OnKeyUp(this->GetSafeHwnd(), nChar, nRepCnt, nFlags); +} + +void vtkMFCWindow::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + static_cast(this->GetInteractor())-> + OnKeyDown(this->GetSafeHwnd(), nChar, nRepCnt, nFlags); +} + +void vtkMFCWindow::OnTimer(UINT nIDEvent) +{ + static_cast(this->GetInteractor())-> + OnTimer(this->GetSafeHwnd(), nIDEvent); +} + diff --git a/GUISupport/MFC/vtkMFCWindow.h b/GUISupport/MFC/vtkMFCWindow.h new file mode 100644 index 0000000..18e2d3c --- /dev/null +++ b/GUISupport/MFC/vtkMFCWindow.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMFCWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef C_VTK_MFC_WINDOW +#define C_VTK_MFC_WINDOW + +#include "afxwin.h" + +class vtkWin32OpenGLRenderWindow; +class vtkRenderWindowInteractor; + +#include "vtkConfigure.h" + +#if defined(VTK_BUILD_SHARED_LIBS) +# if defined(vtkMFC_EXPORTS) +# define VTK_MFC_EXPORT __declspec( dllexport ) +# else +# define VTK_MFC_EXPORT __declspec( dllimport ) +# endif +#else +# define VTK_MFC_EXPORT +#endif + +//! class to display a VTK window in an MFC window +class VTK_MFC_EXPORT vtkMFCWindow : public CWnd +{ +public: + //! constructor requires a parent + vtkMFCWindow(CWnd *pcWnd); + //! destructor + virtual ~vtkMFCWindow(); + +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + //! draw to a device context + void DrawDC(CDC* pDC); + + //! give an instance of a vtk render window to the mfc window + virtual void SetRenderWindow(vtkWin32OpenGLRenderWindow*); + //! get the render window + virtual vtkWin32OpenGLRenderWindow* GetRenderWindow(); + //! get the interactor + virtual vtkRenderWindowInteractor* GetInteractor(); + +protected: + + //! handle size events + afx_msg void OnSize(UINT nType, int cx, int cy); + //! handle paint events + afx_msg void OnPaint(); + //! handle destroy events + afx_msg void OnDestroy(); + //! don't clear background + BOOL OnEraseBkgnd(CDC* pDC); + + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnMButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMButtonUp(UINT nFlags, CPoint point); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnTimer(UINT nIDEvent); + + //! the vtk window + vtkWin32OpenGLRenderWindow* pvtkWin32OpenGLRW; + + DECLARE_MESSAGE_MAP() +}; + +#endif diff --git a/GUISupport/Qt/CMakeLists.txt b/GUISupport/Qt/CMakeLists.txt new file mode 100644 index 0000000..e1f2a4c --- /dev/null +++ b/GUISupport/Qt/CMakeLists.txt @@ -0,0 +1,186 @@ + +# we need Qt3 or Qt4 +INCLUDE( ${CMAKE_ROOT}/Modules/FindQt.cmake ) + +# set up sources to build +SET ( QVTKLibSrcs + vtkEventQtSlotConnect.cxx + QVTKWidget.cxx ) + +SET ( QVTKMocHeaders + QVTKWidget.h + vtkEventQtSlotConnect.h) + +INCLUDE_DIRECTORIES ( ${CMAKE_CURRENT_BINARY_DIR} ) + + +IF(DESIRED_QT_VERSION MATCHES 4) + + # import Qt4 build settings + INCLUDE(${QT_USE_FILE}) + + SET ( PluginLibSrcs + Q4VTKWidgetPlugin.cxx + QVTKWidget.cxx) + + SET ( PluginMocHeaders + Q4VTKWidgetPlugin.h + QVTKWidget.h) + + # CMake apparently doesn't do this automatically + SET_SOURCE_FILES_PROPERTIES(Q4VTKWidgetPlugin.cxx PROPERTIES + OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/QVTKWidget.xpm) + + QT4_WRAP_CPP ( QVTKLibMocSrcs ${QVTKMocHeaders} ) + QT4_WRAP_CPP ( PluginMocSrcs ${PluginMocHeaders} ) + + SET(QT_LIBS "${QT_LIBRARIES}") + +ELSE(DESIRED_QT_VERSION MATCHES 4) + + # Qt3 settings + INCLUDE_DIRECTORIES ( ${QT_INCLUDE_DIR} ) + # assume Qt dll + ADD_DEFINITIONS(-DQT_DLL) + # check for a multithreaded Qt3 dll + IF(QT_QT_LIBRARY MATCHES "mt") + ADD_DEFINITIONS(-DQT_THREAD_SUPPORT) + ENDIF(QT_QT_LIBRARY MATCHES "mt") + + SET ( PluginLibSrcs + Q3VTKWidgetPlugin.cxx + QVTKWidget.cxx) + + SET ( PluginMocHeaders + QVTKWidget.h) + + # CMake apparently doesn't do this automatically + SET_SOURCE_FILES_PROPERTIES(Q3VTKWidgetPlugin.cxx PROPERTIES + OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/QVTKWidget.xpm) + + + QT_WRAP_CPP ( QVTK QVTKLibMocSrcs ${QVTKMocHeaders} ) + QT_WRAP_CPP ( QVTKWidgetPlugin PluginMocSrcs ${PluginMocHeaders} ) + + SET(QT_LIBS ${QT_QT_LIBRARY} ) + +ENDIF(DESIRED_QT_VERSION MATCHES 4) + +SET_SOURCE_FILES_PROPERTIES(vtkEventQtSlotConnect.cxx PROPERTIES + OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_vtkEventQtSlotConnect.cxx) + +ADD_LIBRARY(QVTK ${QVTKLibSrcs} ${QVTKLibMocSrcs}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(QVTK PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +TARGET_LINK_LIBRARIES( QVTK + ${QT_LIBS} + vtkRendering + vtkGraphics + vtkImaging + vtkCommon) + + +# build plugin by default +# even if VTK is built as static libraries (for convenience) +SET(BUILD_QVTK_PLUGIN ON) + +# don't build plugin on systems that require dependents to be shared (PIC actually) +IF(NOT BUILD_SHARED_LIBS) + IF(CMAKE_SYSTEM MATCHES "HP-UX.*") + SET(BUILD_QVTK_PLUGIN OFF) + ENDIF(CMAKE_SYSTEM MATCHES "HP-UX.*") +ENDIF(NOT BUILD_SHARED_LIBS) + + +IF(BUILD_QVTK_PLUGIN) + + ADD_DEFINITIONS(-DQT_PLUGIN) + IF(DESIRED_QT_VERSION MATCHES 4) + # A release build of the designer must have + # a release build of this plugin to work properly + # if the QtGui exists, a release build of the designer is assumed + IF(QT_QTGUI_LIBRARY) + ADD_DEFINITIONS(-DQT_NO_DEBUG) + ENDIF(QT_QTGUI_LIBRARY) + ENDIF(DESIRED_QT_VERSION MATCHES 4) + +# add QVTK plugin from sources +# stand-alone as it doesn't depend on QVTK library + ADD_LIBRARY ( QVTKWidgetPlugin + SHARED + ${PluginLibSrcs} + ${PluginMocSrcs} + ) + +# link with release version of Qt libs + TARGET_LINK_LIBRARIES( QVTKWidgetPlugin + ${QT_LIBS} + vtkRendering + vtkIO + vtkImaging + vtkGraphics + vtkFiltering + vtkCommon + ) +ELSE(BUILD_QVTK_PLUGIN) + MESSAGE(STATUS "Will not build QVTK plugin because VTK isn't build as shared libraries") +ENDIF(BUILD_QVTK_PLUGIN) + + +# Configure the VTKConfigQt.cmake support file. +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/VTKConfigQt.cmake.in + ${VTK_BINARY_DIR}/VTKConfigQt.cmake @ONLY IMMEDIATE) + + +# install rules + +IF(BUILD_QVTK_PLUGIN) + # The VTK_INSTALL_QT_PLUGIN_DIR variable sets the location + # in which the Qt plugin will be installed. It may or may not contain + # variable references to CMAKE_INSTALL_PREFIX and VTK_INSTALL_QT_DIR. + # The default is to install to VTK_INSTALL_QT_DIR under the installation + # prefix. The default VTK_INSTALL_QT_DIR will allow the designer plugin + # path to be set to vtk-install-prefix/plugins to get the plugin. + IF(NOT VTK_INSTALL_QT_DIR) + SET(VTK_INSTALL_QT_DIR /plugins/designer) + ENDIF(NOT VTK_INSTALL_QT_DIR) + + # If no runtime is to be installed then do not install the qt plugin. + IF(VTK_INSTALL_NO_RUNTIME) + SET(VTK_INSTALL_NO_QT_PLUGIN 1) + ENDIF(VTK_INSTALL_NO_RUNTIME) + + IF(NOT VTK_INSTALL_NO_QT_PLUGIN) + # Set default plugin install directory. + SET(DOLLAR "$") + IF(DEFINED VTK_INSTALL_QT_PLUGIN_DIR) + ELSE(DEFINED VTK_INSTALL_QT_PLUGIN_DIR) + SET(VTK_INSTALL_QT_PLUGIN_DIR "${DOLLAR}{CMAKE_INSTALL_PREFIX}${DOLLAR}{VTK_INSTALL_QT_DIR}" + CACHE STRING "Directory in which the VTK Qt plugin is placed during installation.") + MARK_AS_ADVANCED(VTK_INSTALL_QT_PLUGIN_DIR) + ENDIF(DEFINED VTK_INSTALL_QT_PLUGIN_DIR) + + # Configure the plugin install script. This is used instead of + # INSTALL_TARGETS to allow the plugin to be installed outside the + # main install prefix. Attach the script as a post-install script. + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/PluginInstall.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/PluginInstall.cmake + @ONLY IMMEDIATE) + SET_TARGET_PROPERTIES(QVTK PROPERTIES POST_INSTALL_SCRIPT + ${CMAKE_CURRENT_BINARY_DIR}/PluginInstall.cmake + ) + ENDIF(NOT VTK_INSTALL_NO_QT_PLUGIN) +ENDIF(BUILD_QVTK_PLUGIN) + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES( ${VTK_INSTALL_INCLUDE_DIR} .h ${QVTKLibSrcs}) + INSTALL_FILES( ${VTK_INSTALL_PACKAGE_DIR} FILES ${VTK_BINARY_DIR}/VTKConfigQt.cmake ) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS( ${VTK_INSTALL_LIB_DIR} QVTK ) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) + diff --git a/GUISupport/Qt/PluginInstall.cmake.in b/GUISupport/Qt/PluginInstall.cmake.in new file mode 100644 index 0000000..dd6cae7 --- /dev/null +++ b/GUISupport/Qt/PluginInstall.cmake.in @@ -0,0 +1,11 @@ +# Configured file and directory locations. +SET(CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") +SET(VTK_LIB_DIR "@LIBRARY_OUTPUT_PATH@") +SET(VTK_INSTALL_QT_DIR "@VTK_INSTALL_QT_DIR@") +SET(VTK_INSTALL_QT_PLUGIN_DIR "@VTK_INSTALL_QT_PLUGIN_DIR@") +SET(VTK_INSTALL_QT_PLUGIN_FILE "@CMAKE_SHARED_LIBRARY_PREFIX@QVTKWidgetPlugin@CMAKE_SHARED_LIBRARY_SUFFIX@") + +# Install the file to the specified location. +MESSAGE(STATUS "Installing ${VTK_INSTALL_QT_PLUGIN_DIR}/${VTK_INSTALL_QT_PLUGIN_FILE}") +FILE(INSTALL DESTINATION "${VTK_INSTALL_QT_PLUGIN_DIR}" TYPE SHARED_LIBRARY + FILES "${VTK_LIB_DIR}/${VTK_INSTALL_QT_PLUGIN_FILE}") diff --git a/GUISupport/Qt/Q3VTKWidgetPlugin.cxx b/GUISupport/Qt/Q3VTKWidgetPlugin.cxx new file mode 100644 index 0000000..a028f7c --- /dev/null +++ b/GUISupport/Qt/Q3VTKWidgetPlugin.cxx @@ -0,0 +1,167 @@ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include "qwidgetplugin.h" + +// derive from QWidgetPlugin and implement the plugin interface +class QVTKWidgetPlugin : public QWidgetPlugin +{ + public: + QVTKWidgetPlugin(); + ~QVTKWidgetPlugin(); + + QStringList keys() const; + QWidget* create( const QString& key, QWidget* parent = 0, const char* name = 0); + QString group( const QString& ) const; + QIconSet iconSet( const QString& ) const; + QString includeFile( const QString& ) const; + QString toolTip( const QString& ) const; + QString whatsThis( const QString& ) const; + bool isContainer( const QString& ) const; +}; + +#include "QVTKWidget.h" +#include "QVTKWidget.xpm" + +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkDataSetMapper.h" +#include "vtkPolyData.h" +#include "vtkElevationFilter.h" +#include "vtkActor.h" + +// macro for debug printing +#define qDebug(a) +//#define qDebug(a) printf(a) + +QVTKWidgetPlugin::QVTKWidgetPlugin() +{ + qDebug("QVTKWidgetPlugin instantiated\n"); +} + +QVTKWidgetPlugin::~QVTKWidgetPlugin() +{ + qDebug("QVTKWidgetPlugin destructed\n"); +} + +//! return a list of keys for what widgets this plugin makes +QStringList QVTKWidgetPlugin::keys() const +{ + qDebug("QVTKWidgetPlugin::keys\n"); + QStringList list; + list << "QVTKWidget"; + return list; +} + +//! create a widget by key +QWidget* QVTKWidgetPlugin::create( const QString& key, QWidget* parent, const char* name) +{ + qDebug("QVTKWidgetPlugin::create\n"); + if(key == "QVTKWidget") + { + QVTKWidget* widget = new QVTKWidget(parent, name); + // gotta make a renderer so we get a nice black background in the designer + vtkRenderer* ren = vtkRenderer::New(); + widget->GetRenderWindow()->AddRenderer(ren); + + // also for fun, let's make a cylinder and put it in the window + // this REALLY lets the user know that a QVTKWidget works in the designer + vtkSphereSource* cyl = vtkSphereSource::New(); + vtkElevationFilter* ele = vtkElevationFilter::New(); + ele->SetLowPoint(0.0, -0.5, 0.0); + ele->SetHighPoint(0.0, 0.5, 0.0); + ele->SetInput(cyl->GetOutput()); + vtkDataSetMapper* mapper = vtkDataSetMapper::New(); + mapper->SetInput(ele->GetOutput()); + ele->Delete(); + cyl->Delete(); + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + mapper->Delete(); +#if (VTK_MAJOR_VERSION > 4) || (VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION >=5) + ren->AddViewProp(actor); +#else + ren->AddProp(actor); +#endif + actor->Delete(); + ren->Delete(); + + // return the widget + return widget; + } + return 0; +} + +//! what group this plugin shows up in the designer +QString QVTKWidgetPlugin::group( const QString& feature) const +{ + qDebug("QVTKWidgetPlugin::group\n"); + if(feature == "QVTKWidget") + return "QVTK"; + return QString::null; +} +//! the icons for the widgets +QIconSet QVTKWidgetPlugin::iconSet( const QString& ) const +{ + qDebug("QVTKWidgetPlugin::iconSet\n"); + return QIconSet( QPixmap( QVTKWidget_image ) ); +} + +//! the name of the include file for building an app with a widget +QString QVTKWidgetPlugin::includeFile( const QString& feature) const +{ + qDebug("QVTKWidgetPlugin::includeFile\n"); + if ( feature == "QVTKWidget" ) + return "QVTKWidget.h"; + return QString::null; +} + +//! tool tip text +QString QVTKWidgetPlugin::toolTip( const QString& feature) const +{ + qDebug("QVTKWidgetPlugin::toolTip\n"); + if(feature == "QVTKWidget") + return "Qt VTK Widget"; + return QString::null; +} + +//! what's this text +QString QVTKWidgetPlugin::whatsThis( const QString& feature) const +{ + qDebug("QVTKWidgetPlugin::whatsThis\n"); + if ( feature == "QVTKWidget" ) + return "A Qt/VTK Graphics Window"; + return QString::null; +} + +//! returns whether widget is a container +bool QVTKWidgetPlugin::isContainer( const QString& ) const +{ + qDebug("QVTKWidgetPlugin::isContainer\n"); + return false; +} + +Q_EXPORT_PLUGIN(QVTKWidgetPlugin) + diff --git a/GUISupport/Qt/Q4VTKWidgetPlugin.cxx b/GUISupport/Qt/Q4VTKWidgetPlugin.cxx new file mode 100644 index 0000000..9b7a9f3 --- /dev/null +++ b/GUISupport/Qt/Q4VTKWidgetPlugin.cxx @@ -0,0 +1,171 @@ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#if !defined(_DEBUG) +# if !defined(QT_NO_DEBUG) +# define QT_NO_DEBUG +# endif +#endif + +#include "Q4VTKWidgetPlugin.h" + +#include "qobject.h" +#include "QVTKWidget.h" +#include "QVTKWidget.xpm" + +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkDataSetMapper.h" +#include "vtkPolyData.h" +#include "vtkElevationFilter.h" +#include "vtkActor.h" + +// macro for debug printing +#define qDebug(a) +//#define qDebug(a) printf(a) + +QVTKWidgetPlugin::QVTKWidgetPlugin() +{ + qDebug("QVTKWidgetPlugin instantiated\n"); +} + +QVTKWidgetPlugin::~QVTKWidgetPlugin() +{ + qDebug("QVTKWidgetPlugin destructed\n"); +} + +//! return the name of this widget +QString QVTKWidgetPlugin::name() const +{ + qDebug("QVTKWidgetPlugin::name\n"); + return "QVTKWidget"; +} + +QString QVTKWidgetPlugin::domXml() const +{ + return QLatin1String("\n" + " \n" + " \n" + " 0\n" + " 0\n" + " 100\n" + " 100\n" + " \n" + " \n" + "\n"); +} + +QWidget* QVTKWidgetPlugin::createWidget(QWidget* parent) +{ + qDebug("QVTKWidgetPlugin::createWidget\n"); + QVTKWidget* widget = new QVTKWidget(parent); + // gotta make a renderer so we get a nice black background in the designer + vtkRenderer* ren = vtkRenderer::New(); + widget->GetRenderWindow()->AddRenderer(ren); + + // also for fun, let's make a cylinder and put it in the window + // this REALLY lets the user know that a QVTKWidget works in the designer + vtkSphereSource* cyl = vtkSphereSource::New(); + vtkElevationFilter* ele = vtkElevationFilter::New(); + ele->SetLowPoint(0.0, -0.5, 0.0); + ele->SetHighPoint(0.0, 0.5, 0.0); + ele->SetInput(cyl->GetOutput()); + vtkDataSetMapper* mapper = vtkDataSetMapper::New(); + mapper->SetInput(ele->GetOutput()); + ele->Delete(); + cyl->Delete(); + vtkActor* actor = vtkActor::New(); + actor->SetMapper(mapper); + mapper->Delete(); +#if (VTK_MAJOR_VERSION > 4) || (VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION >=5) + ren->AddViewProp(actor); +#else + ren->AddProp(actor); +#endif + actor->Delete(); + ren->Delete(); + + // return the widget + return widget; +} + +QString QVTKWidgetPlugin::group() const +{ + qDebug("QVTKWidgetPlugin::group\n"); + return "QVTK"; +} + +QIcon QVTKWidgetPlugin::icon() const +{ + qDebug("QVTKWidgetPlugin::icon\n"); + return QIcon( QPixmap( QVTKWidget_image ) ); +} + +//! the name of the include file for building an app with a widget +QString QVTKWidgetPlugin::includeFile() const +{ + qDebug("QVTKWidgetPlugin::includeFile\n"); + return "QVTKWidget.h"; +} + +//! tool tip text +QString QVTKWidgetPlugin::toolTip() const +{ + qDebug("QVTKWidgetPlugin::toolTip\n"); + return "Qt VTK Widget"; +} + +//! what's this text +QString QVTKWidgetPlugin::whatsThis() const +{ + qDebug("QVTKWidgetPlugin::whatsThis\n"); + return "A Qt/VTK Graphics Window"; +} + +//! returns whether widget is a container +bool QVTKWidgetPlugin::isContainer() const +{ + qDebug("QVTKWidgetPlugin::isContainer\n"); + return false; +} + +QVTKPlugin::QVTKPlugin() +{ + mQVTKWidgetPlugin = new QVTKWidgetPlugin; +} +QVTKPlugin::~QVTKPlugin() +{ + delete mQVTKWidgetPlugin; +} + +QList QVTKPlugin::customWidgets() const +{ + QList plugins; + plugins.append(mQVTKWidgetPlugin); + return plugins; +} + +Q_EXPORT_PLUGIN(QVTKPlugin) + diff --git a/GUISupport/Qt/Q4VTKWidgetPlugin.h b/GUISupport/Qt/Q4VTKWidgetPlugin.h new file mode 100644 index 0000000..d513dff --- /dev/null +++ b/GUISupport/Qt/Q4VTKWidgetPlugin.h @@ -0,0 +1,67 @@ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#ifndef QVTK_WIDGET_PLUGIN +#define QVTK_WIDGET_PLUGIN + +#include +#include +#include +#include "qobject.h" + + +// implement Designer Custom Widget interface +class QVTKWidgetPlugin : public QDesignerCustomWidgetInterface +{ + public: + QVTKWidgetPlugin(); + ~QVTKWidgetPlugin(); + + QString name() const; + QString domXml() const; + QWidget* createWidget(QWidget* parent = 0); + QString group() const; + QIcon icon() const; + QString includeFile() const; + QString toolTip() const; + QString whatsThis() const; + bool isContainer() const; +}; + +// implement designer widget collection interface +class QVTKPlugin : public QObject, public QDesignerCustomWidgetCollectionInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) + public: + QVTKPlugin(); + ~QVTKPlugin(); + + virtual QList customWidgets() const; + private: + QVTKWidgetPlugin* mQVTKWidgetPlugin; +}; + + +#endif //QVTK_WIDGET_PLUGIN diff --git a/GUISupport/Qt/QVTKWidget.cxx b/GUISupport/Qt/QVTKWidget.cxx new file mode 100644 index 0000000..a467cb3 --- /dev/null +++ b/GUISupport/Qt/QVTKWidget.cxx @@ -0,0 +1,1375 @@ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include "QVTKWidget.h" + +#include "qevent.h" +#include "qapplication.h" +#include "qpainter.h" +#if QT_VERSION >= 0x040000 && defined(Q_WS_X11) +#include "qx11info_x11.h" +#endif + +#include "vtkInteractorStyleTrackballCamera.h" +#include "vtkRenderWindow.h" +#if defined(Q_WS_MAC) +# include "vtkCarbonRenderWindow.h" +#endif +#include "vtkCommand.h" +#include "vtkOStrStreamWrapper.h" +#include "vtkObjectFactory.h" +#include "vtkCallbackCommand.h" +#include "vtkConfigure.h" +#include "vtkToolkits.h" +#include "vtkUnsignedCharArray.h" + + +// VTK 4.5 added some major functionality, so we'll make a short define to use +#if (VTK_MAJOR_VERSION > 4) || (VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION >=5) +#define QVTK_HAVE_VTK_4_5 +#endif + +#if QT_VERSION >= 0x040000 && !defined(QVTK_HAVE_VTK_4_5) +#error "Qt4 and VTK < 4.5 is not supported" +#endif + +// function to get VTK keysyms from ascii characters +static const char* ascii_to_key_sym(int); +// function to get VTK keysyms from Qt keys +static const char* qt_key_to_key_sym(Qt::Key); + +// function to dirty cache when a render occurs. +static void dirty_cache(vtkObject *, unsigned long, void *, void *); + + + +#if QT_VERSION < 0x040000 +/*! constructor */ +QVTKWidget::QVTKWidget(QWidget* parent, const char* name, Qt::WFlags f) +#if QT_VERSION < 0x030000 + : QWidget(parent, name, f | 0x10000000) // WWinOwnDC +#else + : QWidget(parent, name, f | Qt::WWinOwnDC ) +#endif + , mRenWin(NULL), + cachedImageCleanFlag(false), + automaticImageCache(false), maxImageCacheRenderRate(1.0) +{ + // no background + setBackgroundMode( Qt::NoBackground ); + + // default to strong focus + this->setFocusPolicy(QWidget::StrongFocus); + + // default to enable mouse events when a mouse button isn't down + // so we can send enter/leave events to VTK + this->setMouseTracking(true); + + // set expanding to take up space for better default layouts + this->setSizePolicy( + QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) + ); + + this->mCachedImage = vtkUnsignedCharArray::New(); +} +#endif + + +#if QT_VERSION >= 0x040000 +/*! constructor */ +QVTKWidget::QVTKWidget(QWidget* parent, Qt::WFlags f) + : QWidget(parent, f | Qt::MSWindowsOwnDC), mRenWin(NULL), + cachedImageCleanFlag(false), + automaticImageCache(false), maxImageCacheRenderRate(1.0) + +{ + // no background + this->setAttribute(Qt::WA_NoBackground); + // no double buffering + this->setAttribute(Qt::WA_PaintOnScreen); + + // default to strong focus + this->setFocusPolicy(Qt::StrongFocus); + + // default to enable mouse events when a mouse button isn't down + // so we can send enter/leave events to VTK + this->setMouseTracking(true); + + // set expanding to take up space for better default layouts + this->setSizePolicy( + QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) + ); + + this->mCachedImage = vtkUnsignedCharArray::New(); + +#if defined(Q_WS_MAC) + this->DirtyRegionHandler = 0; + this->DirtyRegionHandlerUPP = 0; +#endif + +} +#endif + + +/*! destructor */ + +QVTKWidget::~QVTKWidget() +{ + // get rid of the VTK window + this->SetRenderWindow(NULL); + + this->mCachedImage->Delete(); +} + +/*! get the render window + */ +vtkRenderWindow* QVTKWidget::GetRenderWindow() +{ + if (!this->mRenWin) + { + // create a default vtk window + vtkRenderWindow* win = vtkRenderWindow::New(); + this->SetRenderWindow(win); + win->Delete(); + } + + return this->mRenWin; +} + + + +/*! set the render window + this will bind a VTK window with the Qt window + it'll also replace an existing VTK window +*/ +void QVTKWidget::SetRenderWindow(vtkRenderWindow* window) +{ + // do nothing if we don't have to + if(window == this->mRenWin) + return; + + // unregister previous window + if(this->mRenWin) + { +#if defined(QVTK_HAVE_VTK_4_5) + //clean up window as one could remap it + if(this->mRenWin->GetMapped()) + this->mRenWin->Finalize(); +#endif + this->mRenWin->SetDisplayId(NULL); + this->mRenWin->SetParentId(NULL); + this->mRenWin->SetWindowId(NULL); + this->mRenWin->UnRegister(NULL); + } + + // now set the window + this->mRenWin = window; + + if(this->mRenWin) + { + // register new window + this->mRenWin->Register(NULL); + +#if defined(QVTK_HAVE_VTK_4_5) + // if it is mapped somewhere else, unmap it + if(this->mRenWin->GetMapped()) + this->mRenWin->Finalize(); +#endif + +#ifdef Q_WS_X11 + // give the qt display id to the vtk window +#if QT_VERSION < 0x040000 + this->mRenWin->SetDisplayId( this->x11Display() ); +#else + this->mRenWin->SetDisplayId(QX11Info::display()); +#endif +#endif + + // special x11 setup + x11_setup_window(); + + // give the qt window id to the vtk window + this->mRenWin->SetWindowId( reinterpret_cast(this->winId())); + + // mac compatibility issues +#ifdef Q_WS_MAC +# ifdef QVTK_HAVE_VTK_4_5 +# if QT_VERSION < 0x040000 + this->mRenWin->SetWindowId( NULL ); + static_cast(this->mRenWin)->SetRootWindow( + reinterpret_cast(this->handle())); +# endif +# else + // give the Qt/Mac window handle to VTK and flag whether we have a parent + this->mRenWin->SetWindowId(reinterpret_cast(this->handle())); + this->mRenWin->SetParentId(reinterpret_cast(0x1)); +# endif +# endif + + + // tell the vtk window what the size of this window is + this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height()); + this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y()); + + // have VTK start this window and create the necessary graphics resources + if(isVisible()) + { + this->mRenWin->Start(); +#if defined (Q_WS_MAC) && (QT_VERSION < 0x040000) + macFixRect(); +#endif + } + + // if an interactor wasn't provided, we'll make one by default + if(!this->mRenWin->GetInteractor()) + { + // create a default interactor + QVTKInteractor* iren = QVTKInteractor::New(); + this->mRenWin->SetInteractor(iren); + iren->Initialize(); + + // now set the default style + vtkInteractorStyle* style = vtkInteractorStyleTrackballCamera::New(); + iren->SetInteractorStyle(style); + + iren->Delete(); + style->Delete(); + } + + // tell the interactor the size of this window + this->mRenWin->GetInteractor()->SetSize(this->width(), this->height()); + + // Add an observer to monitor when the image changes. Should work most + // of the time. The application will have to call + // markCachedImageAsDirty for any other case. + vtkCallbackCommand *cbc = vtkCallbackCommand::New(); + cbc->SetClientData(this); + cbc->SetCallback(dirty_cache); + this->mRenWin->AddObserver(vtkCommand::EndEvent, cbc); + cbc->Delete(); + } + +#if defined(Q_WS_MAC) && QT_VERSION >= 0x040000 + if(mRenWin && !this->DirtyRegionHandlerUPP) + { + this->DirtyRegionHandlerUPP = NewEventHandlerUPP(QVTKWidget::DirtyRegionProcessor); + static EventTypeSpec events[] = { {'cute', 20} }; + // kEventClassQt, kEventQtRequestWindowChange from qt_mac_p.h + // Suggested by Sam Magnuson at Trolltech as best portabile hack + // around Apple's missing functionality in HI Toolbox. + InstallEventHandler(GetApplicationEventTarget(), this->DirtyRegionHandlerUPP, + GetEventTypeCount(events), events, + reinterpret_cast(this), &this->DirtyRegionHandler); + } + else if(!mRenWin && this->DirtyRegionHandlerUPP) + { + RemoveEventHandler(this->DirtyRegionHandler); + DisposeEventHandlerUPP(this->DirtyRegionHandlerUPP); + this->DirtyRegionHandler = 0; + this->DirtyRegionHandlerUPP = 0; + } +#endif +} + + + +/*! get the Qt/VTK interactor +*/ +QVTKInteractor* QVTKWidget::GetInteractor() +{ + return QVTKInteractor + ::SafeDownCast(this->GetRenderWindow()->GetInteractor()); +} + +void QVTKWidget::markCachedImageAsDirty() +{ + if (this->cachedImageCleanFlag) + { + this->cachedImageCleanFlag = false; + emit cachedImageDirty(); + } +} + +void QVTKWidget::saveImageToCache() +{ + if (this->cachedImageCleanFlag) return; + + this->mRenWin->GetPixelData(0, 0, this->width()-1, this->height()-1, 1, + this->mCachedImage); + this->cachedImageCleanFlag = true; + emit cachedImageClean(); +} + +void QVTKWidget::setAutomaticImageCacheEnabled(bool flag) +{ + this->automaticImageCache = flag; + if (!flag) + { + this->mCachedImage->Initialize(); + } +} +bool QVTKWidget::isAutomaticImageCacheEnabled() const +{ + return this->automaticImageCache; +} + +void QVTKWidget::setMaxRenderRateForImageCache(double rate) +{ + this->maxImageCacheRenderRate = rate; +} +double QVTKWidget::maxRenderRateForImageCache() const +{ + return this->maxImageCacheRenderRate; +} + +vtkUnsignedCharArray* QVTKWidget::cachedImage() +{ + // Make sure image is up to date. + this->paintEvent(NULL); + this->saveImageToCache(); + + return this->mCachedImage; +} + +/*! overloaded Qt's event handler to capture additional keys that Qt has + default behavior for (for example the Tab and Shift-Tab key) +*/ +bool QVTKWidget::event(QEvent* e) +{ +#if QT_VERSION >= 0x040000 && defined(QVTK_HAVE_VTK_4_5) + if(e->type() == QEvent::ParentAboutToChange) + { + this->markCachedImageAsDirty(); + if (this->mRenWin) + { + // Finalize the window to remove graphics resources associated with + // this window + if(this->mRenWin->GetMapped()) + this->mRenWin->Finalize(); + } + } + else if(e->type() == QEvent::ParentChange) + { + if(this->mRenWin) + { + x11_setup_window(); + // connect to new window + this->mRenWin->SetWindowId( reinterpret_cast(this->winId())); + + // start up the window to create graphics resources for this window + if(isVisible()) + this->mRenWin->Start(); + } + } +#endif + + if(QObject::event(e)) + return TRUE; + + if(e->type() == QEvent::KeyPress) + { + QKeyEvent* ke = static_cast(e); + keyPressEvent(ke); + return ke->isAccepted(); + } + + return QWidget::event(e); +} + + +/*! handle resize event + */ +void QVTKWidget::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + + if(!this->mRenWin) + return; + + // give the size to the interactor and vtk window + this->mRenWin->vtkRenderWindow::SetSize(this->width(), this->height()); + if(this->mRenWin->GetInteractor()) + this->mRenWin->GetInteractor()->SetSize(this->width(), this->height()); + this->markCachedImageAsDirty(); + +#if defined (Q_WS_MAC) && (QT_VERSION < 0x040000) + macFixRect(); +#endif +} + +void QVTKWidget::moveEvent(QMoveEvent* event) +{ + QWidget::moveEvent(event); + + if(!this->mRenWin) + return; + + // give the size to the interactor and vtk window + this->mRenWin->vtkRenderWindow::SetPosition(this->x(), this->y()); + +#if defined (Q_WS_MAC) && (QT_VERSION < 0x040000) + macFixRect(); +#endif +} + +/*! handle paint event + */ +void QVTKWidget::paintEvent(QPaintEvent* ) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + + // if we have a saved image, use it + if (this->cachedImageCleanFlag) + { + // put cached image into back buffer if we can + this->mRenWin->SetPixelData(0, 0, this->width()-1, this->height()-1, + this->mCachedImage, + !this->mRenWin->GetDoubleBuffer()); + // swap buffers, if double buffering + this->mRenWin->Frame(); + // or should we just put it on the front buffer? + return; + } + + + iren->Render(); +} + +/*! handle mouse press event + */ +void QVTKWidget::mousePressEvent(QMouseEvent* event) +{ + + // Emit a mouse press event for anyone who might be interested + emit mouseEvent(event); + + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // give interactor the event information +#if QT_VERSION < 0x040000 + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->state() & Qt::ControlButton), + (event->state() & Qt::ShiftButton ), + 0, + event->type() == QEvent::MouseButtonDblClick ? 1 : 0); +#else + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->modifiers() & Qt::ControlModifier), + (event->modifiers() & Qt::ShiftModifier ), + 0, + event->type() == QEvent::MouseButtonDblClick ? 1 : 0); +#endif + + // invoke appropriate vtk event + switch(event->button()) + { + case Qt::LeftButton: + iren->InvokeEvent(vtkCommand::LeftButtonPressEvent, event); + break; + + case Qt::MidButton: + iren->InvokeEvent(vtkCommand::MiddleButtonPressEvent, event); + break; + + case Qt::RightButton: + iren->InvokeEvent(vtkCommand::RightButtonPressEvent, event); + break; + + default: + break; + } +} + +/*! handle mouse move event + */ +void QVTKWidget::mouseMoveEvent(QMouseEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // give interactor the event information +#if QT_VERSION < 0x040000 + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->state() & Qt::ControlButton), + (event->state() & Qt::ShiftButton )); +#else + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->modifiers() & Qt::ControlModifier), + (event->modifiers() & Qt::ShiftModifier )); +#endif + + // invoke vtk event + iren->InvokeEvent(vtkCommand::MouseMoveEvent, event); +} + + +/*! handle enter event + */ +void QVTKWidget::enterEvent(QEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + iren->InvokeEvent(vtkCommand::EnterEvent, event); +} + +/*! handle leave event + */ +void QVTKWidget::leaveEvent(QEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + iren->InvokeEvent(vtkCommand::LeaveEvent, event); +} + +/*! handle mouse release event + */ +void QVTKWidget::mouseReleaseEvent(QMouseEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // give vtk event information +#if QT_VERSION < 0x040000 + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->state() & Qt::ControlButton), + (event->state() & Qt::ShiftButton )); +#else + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->modifiers() & Qt::ControlModifier), + (event->modifiers() & Qt::ShiftModifier )); +#endif + + // invoke appropriate vtk event + switch(event->button()) + { + case Qt::LeftButton: + iren->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, event); + break; + + case Qt::MidButton: + iren->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, event); + break; + + case Qt::RightButton: + iren->InvokeEvent(vtkCommand::RightButtonReleaseEvent, event); + break; + + default: + break; + } +} + +/*! handle key press event + */ +void QVTKWidget::keyPressEvent(QKeyEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // get key and keysym information +#if QT_VERSION < 0x040000 + int ascii_key = event->text().length() ? event->text().unicode()->latin1() : 0; +#else + int ascii_key = event->text().length() ? event->text().unicode()->toLatin1() : 0; +#endif + const char* keysym = ascii_to_key_sym(ascii_key); + if(!keysym) + { + // get virtual keys + keysym = qt_key_to_key_sym(static_cast(event->key())); + } + + if(!keysym) + { + keysym = "None"; + } + + // give interactor event information +#if QT_VERSION < 0x040000 + iren->SetKeyEventInformation( + (event->state() & Qt::ControlButton), + (event->state() & Qt::ShiftButton), + ascii_key, event->count(), keysym); +#else + iren->SetKeyEventInformation( + (event->modifiers() & Qt::ControlModifier), + (event->modifiers() & Qt::ShiftModifier), + ascii_key, event->count(), keysym); +#endif + + // invoke vtk event + iren->InvokeEvent(vtkCommand::KeyPressEvent, event); + + // invoke char event only for ascii characters + if(ascii_key) + iren->InvokeEvent(vtkCommand::CharEvent, event); +} + +/*! handle key release event + */ +void QVTKWidget::keyReleaseEvent(QKeyEvent* event) +{ + + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // get key and keysym info +#if QT_VERSION < 0x040000 + int ascii_key = event->text().length() ? event->text().unicode()->latin1() : 0; +#else + int ascii_key = event->text().length() ? event->text().unicode()->toLatin1() : 0; +#endif + const char* keysym = ascii_to_key_sym(ascii_key); + if(!keysym) + { + // get virtual keys + keysym = qt_key_to_key_sym((Qt::Key)event->key()); + } + + if(!keysym) + { + keysym = "None"; + } + + // give event information to interactor +#if QT_VERSION < 0x040000 + iren->SetKeyEventInformation( + (event->state() & Qt::ControlButton), + (event->state() & Qt::ShiftButton), + ascii_key, event->count(), keysym); +#else + iren->SetKeyEventInformation( + (event->modifiers() & Qt::ControlModifier), + (event->modifiers() & Qt::ShiftModifier), + ascii_key, event->count(), keysym); +#endif + + // invoke vtk event + iren->InvokeEvent(vtkCommand::KeyReleaseEvent, event); +} + +#ifndef QT_NO_WHEELEVENT +void QVTKWidget::wheelEvent(QWheelEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + +// VTK supports wheel mouse events only in version 4.5 or greater +#if defined(QVTK_HAVE_VTK_4_5) + + // give event information to interactor +#if QT_VERSION < 0x040000 + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->state() & Qt::ControlButton), + (event->state() & Qt::ShiftButton )); +#else + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->modifiers() & Qt::ControlModifier), + (event->modifiers() & Qt::ShiftModifier )); +#endif + + // invoke vtk event + // if delta is positive, it is a forward wheel event + if(event->delta() > 0) + iren->InvokeEvent(vtkCommand::MouseWheelForwardEvent, event); + else + iren->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, event); + +#else + QWidget::wheelEvent(event); +#endif +} +#endif + +void QVTKWidget::focusInEvent(QFocusEvent*) +{ + // These prevent updates when the window + // gains or loses focus. By default, Qt + // does an update because the color group's + // active status changes. We don't even use + // color groups so we do nothing here. +} + +void QVTKWidget::focusOutEvent(QFocusEvent*) +{ + // These prevent updates when the window + // gains or loses focus. By default, Qt + // does an update because the color group's + // active status changes. We don't even use + // color groups so we do nothing here. +} + + +void QVTKWidget::contextMenuEvent(QContextMenuEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // give interactor the event information +#if QT_VERSION < 0x040000 + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->state() & Qt::ControlButton), + (event->state() & Qt::ShiftButton )); +#else + iren->SetEventInformationFlipY(event->x(), event->y(), + (event->modifiers() & Qt::ControlModifier), + (event->modifiers() & Qt::ShiftModifier )); +#endif + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKWidget::ContextMenuEvent, event); + +} + +void QVTKWidget::dragEnterEvent(QDragEnterEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKWidget::DragEnterEvent, event); +} + +void QVTKWidget::dragMoveEvent(QDragMoveEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // give interactor the event information + iren->SetEventInformationFlipY(event->pos().x(), event->pos().y()); + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKWidget::DragMoveEvent, event); +} + +void QVTKWidget::dragLeaveEvent(QDragLeaveEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKWidget::DragLeaveEvent, event); +} + +void QVTKWidget::dropEvent(QDropEvent* event) +{ + vtkRenderWindowInteractor* iren = NULL; + if(this->mRenWin) + iren = this->mRenWin->GetInteractor(); + + if(!iren || !iren->GetEnabled()) + return; + + // give interactor the event information + iren->SetEventInformationFlipY(event->pos().x(), event->pos().y()); + + // invoke event and pass qt event for additional data as well + iren->InvokeEvent(QVTKWidget::DropEvent, event); +} + + +/*! handle reparenting of widgets + */ +#if QT_VERSION < 0x040000 +void QVTKWidget::reparent(QWidget* parent, Qt::WFlags f, const QPoint& p, bool showit) +{ + this->markCachedImageAsDirty(); + +#if defined(QVTK_HAVE_VTK_4_5) + if (this->mRenWin) + { + // Finalize the window to remove graphics resources associated with + // this window + if(this->mRenWin->GetMapped()) + this->mRenWin->Finalize(); + + // have QWidget reparent as normal, but don't show + QWidget::reparent(parent, f, p, false); + + x11_setup_window(); + + // connect to new window +#if defined(Q_WS_MAC) + this->mRenWin->SetWindowId(reinterpret_cast(this->handle())); +#else + this->mRenWin->SetWindowId( reinterpret_cast(this->winId())); +#endif + + // start up the window to create graphics resources for this window + if(isVisible()) + this->mRenWin->Start(); + } + + // show if requested + if(showit) + show(); +#endif +} +#endif + +void QVTKWidget::showEvent(QShowEvent* event) +{ + this->markCachedImageAsDirty(); + + QWidget::showEvent(event); +} + +QPaintEngine* QVTKWidget::paintEngine() const +{ + return NULL; +} + +/*! allocation method for Qt/VTK interactor +*/ +vtkStandardNewMacro(QVTKInteractor); + +/*! constructor for Qt/VTK interactor +*/ +QVTKInteractor::QVTKInteractor() +{ + QObject::connect(&mTimer, SIGNAL(timeout()), this, SLOT(TimerEvent()) ); +} + +/*! start method for interactor +*/ +void QVTKInteractor::Start() +{ + vtkErrorMacro(<<"QVTKInteractor cannot control the event loop."); +} + +/*! terminate the application +*/ +void QVTKInteractor::TerminateApp() +{ + // we are in a GUI so let's terminate the GUI the normal way + //qApp->exit(); +} + + +/*! handle timer event +*/ +void QVTKInteractor::TimerEvent() +{ + if ( !this->GetEnabled() ) + { + return; + } + this->InvokeEvent(vtkCommand::TimerEvent, NULL); +} + +/*! constructor + */ +QVTKInteractor::~QVTKInteractor() +{ +} + +/*! create Qt timer with an interval of 10 msec. +*/ +int QVTKInteractor::CreateTimer(int timer_type) +{ + if(timer_type == VTKI_TIMER_FIRST) + { + mTimer.start(10); + } + return 1; +} + +/*! destroy timer +*/ +int QVTKInteractor::DestroyTimer() +{ + mTimer.stop(); + return 1; +} + + +// ***** keysym stuff below ***** + +static const char *AsciiToKeySymTable[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, "Tab", 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", + "parenleft", "parenright", "asterisk", "plus", + "comma", "minus", "period", "slash", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "colon", "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", "E", "F", "G", + "H", "I", "J", "K", "L", "M", "N", "O", + "P", "Q", "R", "S", "T", "U", "V", "W", + "X", "Y", "Z", "bracketleft", + "backslash", "bracketright", "asciicircum", "underscore", + "quoteleft", "a", "b", "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", "m", "n", "o", + "p", "q", "r", "s", "t", "u", "v", "w", + "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete", + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +const char* ascii_to_key_sym(int i) +{ + return AsciiToKeySymTable[i]; +} + +#define QVTK_HANDLE(x,y) \ + case x : \ + ret = y; \ + break; + +const char* qt_key_to_key_sym(Qt::Key i) +{ + const char* ret = 0; + switch(i) + { + // Cancel + QVTK_HANDLE(Qt::Key_Backspace, "BackSpace") + QVTK_HANDLE(Qt::Key_Tab, "Tab") +#if QT_VERSION < 0x040000 + QVTK_HANDLE(Qt::Key_BackTab, "Tab") +#else + QVTK_HANDLE(Qt::Key_Backtab, "Tab") +#endif + //QVTK_HANDLE(Qt::Key_Clear, "Clear") + QVTK_HANDLE(Qt::Key_Return, "Return") + QVTK_HANDLE(Qt::Key_Enter, "Return") + QVTK_HANDLE(Qt::Key_Shift, "Shift_L") + QVTK_HANDLE(Qt::Key_Control, "Control_L") + QVTK_HANDLE(Qt::Key_Alt, "Alt_L") + QVTK_HANDLE(Qt::Key_Pause, "Pause") + QVTK_HANDLE(Qt::Key_CapsLock, "Caps_Lock") + QVTK_HANDLE(Qt::Key_Escape, "Escape") + QVTK_HANDLE(Qt::Key_Space, "space") + //QVTK_HANDLE(Qt::Key_Prior, "Prior") + //QVTK_HANDLE(Qt::Key_Next, "Next") + QVTK_HANDLE(Qt::Key_End, "End") + QVTK_HANDLE(Qt::Key_Home, "Home") + QVTK_HANDLE(Qt::Key_Left, "Left") + QVTK_HANDLE(Qt::Key_Up, "Up") + QVTK_HANDLE(Qt::Key_Right, "Right") + QVTK_HANDLE(Qt::Key_Down, "Down") + + // Select + // Execute + QVTK_HANDLE(Qt::Key_SysReq, "Snapshot") + QVTK_HANDLE(Qt::Key_Insert, "Insert") + QVTK_HANDLE(Qt::Key_Delete, "Delete") + QVTK_HANDLE(Qt::Key_Help, "Help") + QVTK_HANDLE(Qt::Key_0, "0") + QVTK_HANDLE(Qt::Key_1, "1") + QVTK_HANDLE(Qt::Key_2, "2") + QVTK_HANDLE(Qt::Key_3, "3") + QVTK_HANDLE(Qt::Key_4, "4") + QVTK_HANDLE(Qt::Key_5, "5") + QVTK_HANDLE(Qt::Key_6, "6") + QVTK_HANDLE(Qt::Key_7, "7") + QVTK_HANDLE(Qt::Key_8, "8") + QVTK_HANDLE(Qt::Key_9, "9") + QVTK_HANDLE(Qt::Key_A, "a") + QVTK_HANDLE(Qt::Key_B, "b") + QVTK_HANDLE(Qt::Key_C, "c") + QVTK_HANDLE(Qt::Key_D, "d") + QVTK_HANDLE(Qt::Key_E, "e") + QVTK_HANDLE(Qt::Key_F, "f") + QVTK_HANDLE(Qt::Key_G, "g") + QVTK_HANDLE(Qt::Key_H, "h") + QVTK_HANDLE(Qt::Key_I, "i") + QVTK_HANDLE(Qt::Key_J, "h") + QVTK_HANDLE(Qt::Key_K, "k") + QVTK_HANDLE(Qt::Key_L, "l") + QVTK_HANDLE(Qt::Key_M, "m") + QVTK_HANDLE(Qt::Key_N, "n") + QVTK_HANDLE(Qt::Key_O, "o") + QVTK_HANDLE(Qt::Key_P, "p") + QVTK_HANDLE(Qt::Key_Q, "q") + QVTK_HANDLE(Qt::Key_R, "r") + QVTK_HANDLE(Qt::Key_S, "s") + QVTK_HANDLE(Qt::Key_T, "t") + QVTK_HANDLE(Qt::Key_U, "u") + QVTK_HANDLE(Qt::Key_V, "v") + QVTK_HANDLE(Qt::Key_W, "w") + QVTK_HANDLE(Qt::Key_X, "x") + QVTK_HANDLE(Qt::Key_Y, "y") + QVTK_HANDLE(Qt::Key_Z, "z") + // KP_0 - KP_9 + QVTK_HANDLE(Qt::Key_Asterisk, "asterisk") + QVTK_HANDLE(Qt::Key_Plus, "plus") + // bar + QVTK_HANDLE(Qt::Key_Minus, "minus") + QVTK_HANDLE(Qt::Key_Period, "period") + QVTK_HANDLE(Qt::Key_Slash, "slash") + QVTK_HANDLE(Qt::Key_F1, "F1") + QVTK_HANDLE(Qt::Key_F2, "F2") + QVTK_HANDLE(Qt::Key_F3, "F3") + QVTK_HANDLE(Qt::Key_F4, "F4") + QVTK_HANDLE(Qt::Key_F5, "F5") + QVTK_HANDLE(Qt::Key_F6, "F6") + QVTK_HANDLE(Qt::Key_F7, "F7") + QVTK_HANDLE(Qt::Key_F8, "F8") + QVTK_HANDLE(Qt::Key_F9, "F9") + QVTK_HANDLE(Qt::Key_F10, "F10") + QVTK_HANDLE(Qt::Key_F11, "F11") + QVTK_HANDLE(Qt::Key_F12, "F12") + QVTK_HANDLE(Qt::Key_F13, "F13") + QVTK_HANDLE(Qt::Key_F14, "F14") + QVTK_HANDLE(Qt::Key_F15, "F15") + QVTK_HANDLE(Qt::Key_F16, "F16") + QVTK_HANDLE(Qt::Key_F17, "F17") + QVTK_HANDLE(Qt::Key_F18, "F18") + QVTK_HANDLE(Qt::Key_F19, "F19") + QVTK_HANDLE(Qt::Key_F20, "F20") + QVTK_HANDLE(Qt::Key_F21, "F21") + QVTK_HANDLE(Qt::Key_F22, "F22") + QVTK_HANDLE(Qt::Key_F23, "F23") + QVTK_HANDLE(Qt::Key_F24, "F24") + QVTK_HANDLE(Qt::Key_NumLock, "Num_Lock") + QVTK_HANDLE(Qt::Key_ScrollLock, "Scroll_Lock") + + default: + break; + } + return ret; +} + + + + +// X11 stuff near the bottom of the file +// to prevent namespace collisions with Qt headers + +#if defined Q_WS_X11 +#if defined(VTK_USE_OPENGL_LIBRARY) || (!defined(QVTK_HAVE_VTK_4_5) && defined(OPENGL_LIBRARY)) +#include "vtkXOpenGLRenderWindow.h" +#endif +#ifdef VTK_USE_MANGLED_MESA +#include "vtkXMesaRenderWindow.h" +#endif +#endif + + +void QVTKWidget::x11_setup_window() +{ +#if defined Q_WS_X11 + + // this whole function is to allow this window to have a + // different colormap and visual than the rest of the Qt application + // this is very important if Qt's default visual and colormap is + // not enough to get a decent graphics window + + + // save widget states + bool tracking = this->hasMouseTracking(); +#if QT_VERSION < 0x040000 + FocusPolicy focus_policy = focusPolicy(); +#else + Qt::FocusPolicy focus_policy = focusPolicy(); +#endif + bool visible = isVisible(); + if(visible) + hide(); + + + // get visual and colormap from VTK + XVisualInfo* vi = 0; + Colormap cmap = 0; + Display* display = reinterpret_cast(mRenWin->GetGenericDisplayId()); + + // check ogl and mesa and get information we need to create a decent window +#if defined(VTK_USE_OPENGL_LIBRARY) || (!defined(QVTK_HAVE_VTK_4_5) && defined(OPENGL_LIBRARY)) + vtkXOpenGLRenderWindow* ogl_win = vtkXOpenGLRenderWindow::SafeDownCast(mRenWin); + if(ogl_win) + { + vi = ogl_win->GetDesiredVisualInfo(); + cmap = ogl_win->GetDesiredColormap(); + } +#endif +#ifdef VTK_USE_MANGLED_MESA + if(!vi) + { + vtkXMesaRenderWindow* mgl_win = vtkXMesaRenderWindow::SafeDownCast(mRenWin); + if(mgl_win) + { + vi = mgl_win->GetDesiredVisualInfo(); + cmap = mgl_win->GetDesiredColormap(); + } + } +#endif + + // can't get visual, oh well. + // continue with Qt's default visual as it usually works + if(!vi) + { + if(visible) + show(); + return; + } + + // create the X window based on information VTK gave us + XSetWindowAttributes attrib; + attrib.colormap = cmap; + attrib.border_pixel = BlackPixel(display, DefaultScreen(display)); + + Window parent = RootWindow(display, DefaultScreen(display)); + if(parentWidget()) + parent = parentWidget()->winId(); + + XWindowAttributes a; + XGetWindowAttributes(display, this->winId(), &a); + + Window win = XCreateWindow(display, parent, a.x, a.y, a.width, a.height, + 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel|CWColormap, &attrib); + + // backup colormap stuff + Window *cmw; + Window *cmwret; + int count; + if ( XGetWMColormapWindows(display, topLevelWidget()->winId(), &cmwret, &count) ) + { + cmw = new Window[count+1]; + memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count ); + XFree( (char *)cmwret ); + int i; + for ( i=0; i= count ) + cmw[count++] = win; + } + else + { + count = 1; + cmw = new Window[count]; + cmw[0] = win; + } + + + // tell Qt to initialize anything it needs to for this window + create(win); + + // restore colormaps + XSetWMColormapWindows( display, topLevelWidget()->winId(), cmw, count ); + + delete [] cmw; + + XFlush(display); + + // restore widget states + this->setMouseTracking(tracking); +#if QT_VERSION < 0x040000 + setBackgroundMode( Qt::NoBackground ); +#else + this->setAttribute(Qt::WA_NoBackground); + this->setAttribute(Qt::WA_PaintOnScreen); +#endif + setFocusPolicy(focus_policy); + if(visible) + show(); + +#endif +} + +#if defined (Q_WS_MAC) && QT_VERSION >= 0x040000 +OSStatus QVTKWidget::DirtyRegionProcessor(EventHandlerCallRef, EventRef event, void* wid) +{ + QVTKWidget* widget = reinterpret_cast(wid); + UInt32 event_kind = GetEventKind(event); + UInt32 event_class = GetEventClass(event); + if(event_class == 'cute' && event_kind == 20) + static_cast(widget->GetRenderWindow())->UpdateGLRegion(); + return eventNotHandledErr; +} + +#endif + +#if defined (Q_WS_MAC) && QT_VERSION < 0x040000 + +// gotta do some special stuff on the MAC to make it work right +// this stuff will need changing when using Qt4 with HIViews + +#include + +void QVTKWidget::macFixRect() +{ + AGLContext context = static_cast(this->GetRenderWindow())->GetContextId(); + + if(!this->isTopLevel()) + { + GLint bufRect[4]; + + // always do AGL_BUFFER_RECT if we have a parent + if(!aglIsEnabled(context, AGL_BUFFER_RECT)) + aglEnable(context, AGL_BUFFER_RECT); + + // get the clip region + QRegion clip = this->clippedRegion(); + QRect clip_rect = clip.boundingRect(); + + // get the position of this widget with respect to the top level widget + QPoint mp(posInWindow(this)); + int win_height = this->topLevelWidget()->height(); + win_height -= win_height - this->topLevelWidget()->clippedRegion(FALSE).boundingRect().height(); + + // give the position and size to agl + bufRect[0] = mp.x(); + bufRect[1] = win_height -(mp.y() + this->height()); + bufRect[2] = this->width(); + bufRect[3] = this->height(); + aglSetInteger(context, AGL_BUFFER_RECT, bufRect); + + if(clip_rect.isEmpty()) + { + // no clipping, disable it + if(!aglIsEnabled(context, AGL_CLIP_REGION)) + aglDisable(context, AGL_CLIP_REGION); + + bufRect[0] = 0; + bufRect[1] = 0; + bufRect[2] = 0; + bufRect[3] = 0; + aglSetInteger(context, AGL_BUFFER_RECT, bufRect); + } + else + { + // we are clipping, so lets enable it + if(!aglIsEnabled(context, AGL_CLIP_REGION)) + aglEnable(context, AGL_CLIP_REGION); + + // give agl the clip region + aglSetInteger(context, AGL_CLIP_REGION, (const GLint*)clip.handle(TRUE)); + } + } + + // update the context + aglUpdateContext(context); +} + +void QVTKWidget::setRegionDirty(bool b) +{ + // the region is dirty and needs redrawn, but not yet + // signal that it needs to be done when it is possible + QWidget::setRegionDirty(b); + QTimer::singleShot(1, this, SLOT(internalMacFixRect())); + +} + +void QVTKWidget::macWidgetChangedWindow() +{ + macFixRect(); +} +#endif + +// slot to update the draw region and draw the scene +void QVTKWidget::internalMacFixRect() +{ +#if defined(Q_WS_MAC) && QT_VERSION < 0x040000 + this->macFixRect(); + this->update(); +#endif +} + +static void dirty_cache(vtkObject *caller, unsigned long, + void *clientdata, void *) +{ + QVTKWidget *widget = reinterpret_cast(clientdata); + widget->markCachedImageAsDirty(); + + vtkRenderWindow *renwin = vtkRenderWindow::SafeDownCast(caller); + if (renwin) + { + if ( widget->isAutomaticImageCacheEnabled() + && ( renwin->GetDesiredUpdateRate() + < widget->maxRenderRateForImageCache() ) ) + { + widget->saveImageToCache(); + } + } +} diff --git a/GUISupport/Qt/QVTKWidget.h b/GUISupport/Qt/QVTKWidget.h new file mode 100644 index 0000000..17d5d6f --- /dev/null +++ b/GUISupport/Qt/QVTKWidget.h @@ -0,0 +1,304 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +// .NAME QVTKWidget - Display a vtkRenderWindow in a Qt's QWidget. +// .SECTION Description +// QVTKWidget provides a way to display VTK data in a Qt widget. + +#ifndef Q_VTK_WIDGET_H +#define Q_VTK_WIDGET_H + +#include +#include +class QPaintEngine; + +class vtkRenderWindow; +class QVTKInteractor; +#include +#include +#include +class vtkUnsignedCharArray; + +#if defined(Q_WS_MAC) && QT_VERSION >= 0x040000 +#include // Event handling for dirty region +#endif + +#if defined(WIN32) && defined(VTK_BUILD_SHARED_LIBS) +#if defined(QVTK_EXPORTS) || defined(QVTKWidgetPlugin_EXPORTS) +#define QVTK_EXPORT __declspec( dllexport ) +#else +#define QVTK_EXPORT __declspec( dllimport ) +#endif +#else +#define QVTK_EXPORT +#endif + +//! QVTKWidget displays a VTK window in a Qt window. +class QVTK_EXPORT QVTKWidget : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(bool automaticImageCacheEnabled + READ isAutomaticImageCacheEnabled + WRITE setAutomaticImageCacheEnabled) + Q_PROPERTY(double maxRenderRateForImageCache + READ maxRenderRateForImageCache + WRITE setMaxRenderRateForImageCache) + + public: +#if QT_VERSION < 0x040000 + //! constructor for Qt 3 + QVTKWidget(QWidget* parent = NULL, const char* name = NULL, Qt::WFlags f = 0); +#else + //! constructor for Qt 4 + QVTKWidget(QWidget* parent = NULL, Qt::WFlags f = 0); +#endif + //! destructor + virtual ~QVTKWidget(); + + // Description: + // Set the vtk render window, if you wish to use your own vtkRenderWindow + void SetRenderWindow(vtkRenderWindow*); + + // Description: + // Get the vtk render window. + vtkRenderWindow* GetRenderWindow(); + + // Description: + // Get the Qt/vtk interactor that was either created by default or set by the user + QVTKInteractor* GetInteractor(); + + // Description: + // Enum for additional event types supported. + // These events can be picked up by command observers on the interactor + enum vtkCustomEvents + { + ContextMenuEvent = vtkCommand::UserEvent + 100, + DragEnterEvent, + DragMoveEvent, + DragLeaveEvent, + DropEvent + }; + + // Description: + // Enables/disables automatic image caching. If disabled (the default), + // QVTKWidget will not call saveImageToCache() on its own. + virtual void setAutomaticImageCacheEnabled(bool flag); + virtual bool isAutomaticImageCacheEnabled() const; + + // Description: + // If automatic image caching is enabled, then the image will be cached + // after every render with a DesiredUpdateRate that is greater than + // this parameter. By default, the vtkRenderWindowInteractor will + // change the desired render rate depending on the user's + // interactions. (See vtkRenderWindow::DesiredUpdateRate, + // vtkRenderWindowInteractor::DesiredUpdateRate and + // vtkRenderWindowInteractor::StillUpdateRate for more details.) + virtual void setMaxRenderRateForImageCache(double rate); + virtual double maxRenderRateForImageCache() const; + + // Description: + // Returns the current image in the window. If the image cache is up + // to date, that is returned to avoid grabbing other windows. + virtual vtkUnsignedCharArray* cachedImage(); + +#if QT_VERSION < 0x040000 + // Description: + // Handle reparenting of this widget in Qt 3.x + virtual void reparent(QWidget* parent, Qt::WFlags f, const QPoint& p, bool showit); +#endif + + // Description: + // Handle showing of the Widget + virtual void showEvent(QShowEvent*); + + virtual QPaintEngine* paintEngine() const; + + signals: + // Description: + // This signal will be emitted whenever a mouse event occurs + // within the QVTK window + void mouseEvent(QMouseEvent* event); + + // Description: + // This signal will be emitted whenever the cached image goes from clean + // to dirty. + void cachedImageDirty(); + + // Description: + // This signal will be emitted whenever the cached image is refreshed. + void cachedImageClean(); + + + public slots: + // Description: + // This will mark the cached image as dirty. This slot is automatically + // invoked whenever the render window has a render event or the widget is + // resized. Your application should invoke this slot whenever the image in + // the render window is changed by some other means. If the image goes + // from clean to dirty, the cachedImageDirty() signal is emitted. + void markCachedImageAsDirty(); + + // Description: + // If the cached image is dirty, it is updated with the current image in + // the render window and the cachedImageClean() signal is emitted. + void saveImageToCache(); + + protected: + // overloaded resize handler + virtual void resizeEvent(QResizeEvent* event); + // overloaded move handler + virtual void moveEvent(QMoveEvent* event); + // overloaded paint handler + virtual void paintEvent(QPaintEvent* event); + + // overloaded mouse press handler + virtual void mousePressEvent(QMouseEvent* event); + // overloaded mouse move handler + virtual void mouseMoveEvent(QMouseEvent* event); + // overloaded mouse release handler + virtual void mouseReleaseEvent(QMouseEvent* event); + // overloaded key press handler + virtual void keyPressEvent(QKeyEvent* event); + // overloaded key release handler + virtual void keyReleaseEvent(QKeyEvent* event); + // overloaded enter event + virtual void enterEvent(QEvent*); + // overloaded leave event + virtual void leaveEvent(QEvent*); +#ifndef QT_NO_WHEELEVENT + // overload wheel mouse event + virtual void wheelEvent(QWheelEvent*); +#endif + // overload focus event + virtual void focusInEvent(QFocusEvent*); + // overload focus event + virtual void focusOutEvent(QFocusEvent*); + // overload Qt's event() to capture more keys + bool event( QEvent* e ); + + // overload context menu event + virtual void contextMenuEvent(QContextMenuEvent*); + // overload drag enter event + virtual void dragEnterEvent(QDragEnterEvent*); + // overload drag move event + virtual void dragMoveEvent(QDragMoveEvent*); + // overload drag leave event + virtual void dragLeaveEvent(QDragLeaveEvent*); + // overload drop event + virtual void dropEvent(QDropEvent*); + + // the vtk render window + vtkRenderWindow* mRenWin; + + // set up an X11 window based on a visual and colormap + // that VTK chooses + void x11_setup_window(); + +#if defined(Q_WS_MAC) && QT_VERSION < 0x040000 + void macFixRect(); + virtual void setRegionDirty(bool); + virtual void macWidgetChangedWindow(); +#endif + +#if defined(Q_WS_MAC) && QT_VERSION >= 0x040000 + EventHandlerUPP DirtyRegionHandlerUPP; + EventHandlerRef DirtyRegionHandler; + static OSStatus DirtyRegionProcessor(EventHandlerCallRef er, EventRef event, void*); +#endif + + private slots: + void internalMacFixRect(); + + protected: + + vtkUnsignedCharArray* mCachedImage; + bool cachedImageCleanFlag; + bool automaticImageCache; + double maxImageCacheRenderRate; + + private: + //! unimplemented operator= + QVTKWidget const& operator=(QVTKWidget const&); + //! unimplemented copy + QVTKWidget(const QVTKWidget&); + +}; + +// .NAME QVTKInteractor - An interactor for the QVTKWidget. +// .SECTION Description +// QVTKInteractor is an interactor for a QVTKWiget. + +class QVTK_EXPORT QVTKInteractor : public QObject, public vtkRenderWindowInteractor +{ + Q_OBJECT +public: + static QVTKInteractor* New(); + vtkTypeMacro(QVTKInteractor,vtkRenderWindowInteractor); + + // Description: + // Overloaded terminiate app, which does nothing in Qt. + // Use qApp->exit() instead. + virtual void TerminateApp(); + + // Description: + // Overloaded start method does nothing. + // Use qApp->exec() instead. + virtual void Start(); + + // Description: + // Overloaded create timer method for creating Qt timers. + virtual int CreateTimer(int); + + // Description: + // Overloaded destroy timer method for destroying Qt timers. + virtual int DestroyTimer(); + +public slots: + // timer event slot + virtual void TimerEvent(); + +protected: + // constructor + QVTKInteractor(); + // destructor + ~QVTKInteractor(); +private: + + // the timer + QTimer mTimer; + + // unimplemented copy + QVTKInteractor(const QVTKInteractor&); + // unimplemented operator= + void operator=(const QVTKInteractor&); + +}; + + +#endif + + diff --git a/GUISupport/Qt/QVTKWidget.xpm b/GUISupport/Qt/QVTKWidget.xpm new file mode 100644 index 0000000..3530d4d --- /dev/null +++ b/GUISupport/Qt/QVTKWidget.xpm @@ -0,0 +1,368 @@ + +/*========================================================================= + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +/* XPM */ +static char const *QVTKWidget_image[]={ +"22 22 317 2", +"-- c none", +".# c #000c49", +".a c #00114b", +".b c #001f59", +".h c #002042", +".q c #002945", +".c c #003080", +"#F c #00311a", +".i c #003469", +".W c #003735", +".g c #00375c", +"#a c #003e28", +".f c #003f82", +".r c #004353", +".e c #00459f", +".d c #0045a0", +".G c #004655", +"ag c #004b0e", +"ay c #005004", +".p c #00546c", +".j c #00568e", +"#G c #005939", +"#Y c #005c12", +".o c #006391", +".s c #006579", +".n c #00659f", +"#b c #006758", +".k c #0068a3", +"#p c #006930", +".l c #006ea9", +".F c #006f7c", +".H c #007377", +".m c #0074b0", +".V c #007972", +"#Z c #008025", +"af c #00840a", +".t c #00859d", +".B c #00859e", +".C c #00859f", +".D c #00869f", +".E c #00879f", +".A c #0088a3", +".u c #008ba5", +"#q c #008e53", +".v c #0090ac", +"#E c #009246", +".w c #0096b3", +".z c #009ab9", +".x c #009aba", +".X c #009b7f", +"## c #009d7f", +"ah c #00a00f", +".y c #00a0c0", +"ax c #00a10c", +"#H c #00a23f", +".R c #00a29e", +".S c #00a39e", +"#X c #00a43a", +".T c #00a49e", +"#c c #00a570", +".U c #00a59e", +"#o c #00a667", +".I c #00a69f", +"#0 c #00ab30", +"ae c #00ac23", +"#D c #00ae50", +"#r c #00ae60", +".J c #00afaa", +"#. c #00b086", +".Y c #00b090", +"ai c #00b316", +".Q c #00b3b3", +"aw c #00b50c", +"#I c #00b651", +"#W c #00b739", +".K c #00b7b5", +"#d c #00b880", +"#n c #00b96a", +".L c #00bcbd", +"#1 c #00be3d", +"ad c #00bf22", +".7 c #00c09e", +"#C c #00c14f", +"#s c #00c171", +".8 c #00c19e", +".M c #00c1c3", +".9 c #00c29e", +".Z c #00c39e", +".P c #00c4c9", +"aj c #00c616", +".N c #00c6c9", +"av c #00c70c", +"#V c #00c937", +"#J c #00c961", +".0 c #00caa9", +".O c #00cad0", +"#e c #00cb8f", +".6 c #00cbad", +"#m c #00cc86", +"ac c #00d122", +"#2 c #00d13c", +".1 c #00d2b3", +"#t c #00d380", +"#B c #00d46b", +"ak c #00d815", +"au c #00d90c", +".2 c #00dabe", +"#U c #00db51", +"#K c #00db61", +".5 c #00dcc3", +"#f c #00dd9d", +".3 c #00e1c8", +"#3 c #00e23b", +"ab c #00e337", +"#l c #00e3a7", +"#g c #00e4a8", +"#u c #00e585", +"#A c #00e686", +"al c #00e715", +"#L c #00e760", +"#h c #00e7aa", +".4 c #00e7ce", +"#T c #00e860", +"#k c #00e8aa", +"#4 c #00e93a", +"#i c #00e9a9", +"aa c #00ea3b", +"#v c #00ea85", +"am c #00eb15", +"#j c #00eba8", +"#M c #00ec5f", +"#S c #00ec60", +"#w c #00ec84", +"#x c #00ed84", +"#5 c #00ee3a", +"a# c #00ee3b", +"#z c #00ee83", +"an c #00ef15", +"#y c #00ef83", +"at c #00f016", +"#N c #00f05f", +"#6 c #00f23a", +"#O c #00f25e", +"#R c #00f25f", +"ao c #00f315", +"#P c #00f35d", +"as c #00f416", +"#Q c #00f45e", +"#7 c #00f639", +"a. c #00f63a", +"ap c #00f814", +"ar c #00f815", +"#8 c #00f839", +"#9 c #00f83a", +"aq c #00fc15", +"az c #044d00", +"aV c #0a8100", +"aA c #0ba000", +"aB c #0bb400", +"aC c #0bc600", +"aD c #0bd800", +"aU c #0c5400", +"aT c #0fa200", +"bb c #125800", +"aQ c #12da00", +"aP c #12e700", +"aO c #12eb00", +"aN c #12f000", +"aM c #12f400", +"aL c #12f800", +"aK c #12fc00", +"aR c #13c800", +"aE c #13e700", +"aF c #13eb00", +"aG c #13ef00", +"aH c #13f400", +"aI c #13f800", +"aJ c #13fc00", +"aS c #14b500", +"bL c #1e3400", +"aY c #20d000", +"aX c #21be00", +"aW c #22ab00", +"ba c #238900", +"b2 c #283900", +"bM c #296500", +"b# c #30ad00", +"aZ c #32e200", +"be c #36c800", +"bd c #37b600", +"a7 c #37ea00", +"a6 c #37ee00", +"a5 c #37f200", +"a3 c #37f600", +"a4 c #37f800", +"a8 c #38e400", +"a0 c #38e900", +"a1 c #38ee00", +"a2 c #38f200", +"bc c #39a300", +"a9 c #39d200", +"b. c #3ac000", +"c4 c #3b1200", +"bs c #3d6300", +"ch c #3f4300", +"bt c #408e00", +"br c #40a400", +"cM c #492e00", +"cX c #4c2500", +"bv c #4cc000", +"bf c #4cdb00", +"bu c #4eae00", +"c5 c #501500", +"bK c #509600", +"bq c #51b800", +"c6 c #531100", +"cw c #574900", +"bk c #5bf400", +"cL c #5c4e00", +"bm c #5cec00", +"bl c #5cf000", +"bj c #5cf200", +"bn c #5de800", +"bh c #5dec00", +"bi c #5df000", +"bo c #5edc00", +"bg c #5ee800", +"cY c #603c00", +"bJ c #60b000", +"bp c #60cb00", +"b1 c #627100", +"c3 c #632400", +"bN c #65a500", +"bO c #66b800", +"bw c #67d300", +"ci c #6c7500", +"cN c #705800", +"b0 c #70a700", +"bI c #71c300", +"cW c #733f00", +"b3 c #7d9c00", +"cv c #7f7d00", +"cg c #7f9e00", +"cx c #807400", +"bZ c #80ba00", +"bH c #80d500", +"bD c #80ee00", +"bC c #80f000", +"bE c #81ec00", +"bA c #81ee00", +"bB c #81ef00", +"cK c #826f00", +"b4 c #82b000", +"bP c #82cb00", +"bx c #82e500", +"bG c #82e600", +"bF c #82ea00", +"bz c #82ec00", +"by c #83ea00", +"cZ c #864300", +"c2 c #883500", +"bY c #8fcd00", +"cf c #90b200", +"cO c #946600", +"cV c #976000", +"b7 c #9dc200", +"b5 c #9dc300", +"bQ c #9dde00", +"bX c #9ddf00", +"cB c #9e8700", +"cl c #9ea500", +"ck c #9ea600", +"cj c #9ea700", +"b6 c #9ec300", +"ce c #9ec400", +"c0 c #9f4700", +"cQ c #9f6700", +"cP c #9f6800", +"cA c #9f8700", +"cz c #9f8800", +"cy c #9f8900", +"cu c #9fa800", +"cJ c #a08a00", +"c1 c #a14900", +"cC c #a38900", +"cU c #a46c00", +"bT c #a6ea00", +"bU c #a6eb00", +"cI c #a78f00", +"bR c #a7e500", +"bV c #a7e800", +"bW c #a8e600", +"bS c #a8e800", +"cR c #a96f00", +"cd c #a9cc00", +"ct c #aab100", +"cT c #ab7100", +"b8 c #adcd00", +"cH c #ae9400", +"cS c #b27700", +"cm c #b3b400", +"cc c #b3d400", +"cG c #b59900", +"cs c #b5b900", +"cD c #b99c00", +"cF c #bb9e00", +"cr c #bec000", +"cb c #bedc00", +"cE c #c2a300", +"b9 c #c2de00", +"cq c #c5c500", +"cn c #c8c600", +"ca c #c8e300", +"cp c #cbc900", +"c# c #cbe700", +"c. c #cce700", +"co c #d1cd00", +"--------------------.#.a--------------------", +"----------------.b.c.d.e.f.g----------------", +"----------.h.i.j.k.l.m.l.n.n.o.p.q----------", +"------.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G------", +"------.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.I.V------", +"----.W.X.Y.Z.0.1.2.3.4.4.5.6.7.8.9#.###a----", +"----#b#c#d#e#f#g#h#i#j#j#i#k#l#f#m#n#o#p----", +"----#q#r#s#t#u#v#w#x#y#y#z#w#v#A#B#C#D#E#F--", +"--#G#H#I#J#K#L#M#N#O#P#Q#R#N#S#T#U#V#W#X#Y--", +"--#Z#0#1#2#3#4#5#6#7#8#9a.#6a#aaabacadaeaf--", +"agahaiajakalamanaoapaqaqarasatamalauavawaxay", +"azaAaBaCaDaEaFaGaHaIaJaKaLaMaNaOaPaQaRaSaTaU", +"--aVaWaXaYaZa0a1a2a3a4a4a3a5a6a7a8a9b.b#ba--", +"--bbbcbdbebfbgbhbibjbkbkbjblbmbnbobpbqbrbs--", +"----btbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbL--", +"----bMbNbObPbQbRbSbTbUbUbTbVbWbXbYbZb0b1----", +"----b2b3b4b5b6b7b8b9c.c#cacbcccdcecfcgch----", +"------cicjcjckckclcmcncocpcqcrcsctcucv------", +"------cwcxcyczcAcBcCcDcEcFcGcHcIcJcKcL------", +"----------cMcNcOcPcQcRcScTcUcVcWcX----------", +"----------------cYcZc0c1c2c3c4--------------", +"--------------------c5c6--------------------"}; diff --git a/GUISupport/Qt/README b/GUISupport/Qt/README new file mode 100644 index 0000000..8ab1efb --- /dev/null +++ b/GUISupport/Qt/README @@ -0,0 +1,12 @@ + +There are no restrictions for using this Qt code in any project. +To make changes to this code requires a commercial license of Qt +to keep it free for everyone. Using a free version of Qt causes +this Qt code to become GPL'd. We don't want that. If you want to +make changes with a free version of Qt, you can copy it and +make your own changes for yourself. + +Changes to the following files are restricted, but not limited to +any new ones added after this writing: + QVTKWidget.h QVTKWidget.cxx QVTKWidgetPlugin.cxx QVTKWidget.xpm + diff --git a/GUISupport/Qt/VTKConfigQt.cmake.in b/GUISupport/Qt/VTKConfigQt.cmake.in new file mode 100644 index 0000000..c46b1ac --- /dev/null +++ b/GUISupport/Qt/VTKConfigQt.cmake.in @@ -0,0 +1,21 @@ +#----------------------------------------------------------------------------- +# +# VTKConfigQt.cmake - VTK Qt CMake configuration file for external projects. +# +# This file is configured by VTK and used by the VTKConfig.cmake module +# to load VTK's Qt settings for an external project. + +# export for Qt3 +SET(VTK_QT_QT_LIBRARY "@QT_QT_LIBRARY@") +SET(VTK_QT_INCLUDE_DIR "@QT_INCLUDE_DIR@") +SET(VTK_QT_QASSISTANTCLIENT_LIBRARY "@QT_QASSISTANTCLIENT_LIBRARY@") + +# exports for Qt4 +SET(VTK_QT_RCC_EXECUTABLE "@QT_RCC_EXECUTABLE@") +SET(VTK_DESIRED_QT_VERSION "@DESIRED_QT_VERSION@") + +# exports for Qt3/Qt4 +SET(VTK_QT_MOC_EXECUTABLE "@QT_MOC_EXECUTABLE@") +SET(VTK_QT_UIC_EXECUTABLE "@QT_UIC_EXECUTABLE@") +SET(VTK_QT_QMAKE_EXECUTABLE "@QT_QMAKE_EXECUTABLE@") + diff --git a/GUISupport/Qt/vtkEventQtSlotConnect.cxx b/GUISupport/Qt/vtkEventQtSlotConnect.cxx new file mode 100644 index 0000000..c287e69 --- /dev/null +++ b/GUISupport/Qt/vtkEventQtSlotConnect.cxx @@ -0,0 +1,209 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +#include "vtkEventQtSlotConnect.h" +#include "vtkObjectFactory.h" +#include "vtkCallbackCommand.h" + +#include "vtkstd/vector" + +#include +#include + +// constructor +vtkQtConnection::vtkQtConnection() +{ + Callback = vtkCallbackCommand::New(); + Callback->SetCallback(vtkQtConnection::DoCallback); + this->Callback->SetClientData(this); +} + +// destructor, disconnect if necessary +vtkQtConnection::~vtkQtConnection() +{ + if(VTKObject) + { + VTKObject->RemoveObserver(this->Callback); + //Qt takes care of disconnecting slots + } + Callback->Delete(); +} + +void vtkQtConnection::DoCallback(vtkObject* vtk_obj, unsigned long event, + void* client_data, void* call_data) +{ + vtkQtConnection* conn = static_cast(client_data); + conn->Execute(vtk_obj, event, call_data); +} + + +// callback from VTK to emit signal +void vtkQtConnection::Execute(vtkObject* caller, unsigned long event, void*) +{ + if(event != vtkCommand::DeleteEvent || + event == vtkCommand::DeleteEvent && VTKEvent == vtkCommand::DeleteEvent) + { + emit EmitExecute(caller, event, ClientData, this->Callback); + } + + if(event == vtkCommand::DeleteEvent) + { + VTKObject->RemoveObserver(this->Callback); + VTKObject = NULL; + } +} + +bool vtkQtConnection::IsConnection(vtkObject* vtk_obj, unsigned long event, + QObject* qt_obj, const char* slot) +{ + if(VTKObject != vtk_obj) + return false; + + if(event != vtkCommand::NoEvent && event != VTKEvent) + return false; + + if(qt_obj && qt_obj != QtObject) + return false; + + if(slot && QtSlot != slot) + return false; + + return true; +} + +// set the connection +void vtkQtConnection::SetConnection(vtkObject* vtk_obj, unsigned long event, + QObject* qt_obj, const char* slot, void* client_data, float priority) +{ + // keep track of what we connected + VTKObject = vtk_obj; + QtObject = qt_obj; + VTKEvent = event; + ClientData = client_data; + QtSlot = slot; + + // make a connection between this and the vtk object + vtk_obj->AddObserver(event, this->Callback, priority); + + if(event != vtkCommand::DeleteEvent) + { + vtk_obj->AddObserver(vtkCommand::DeleteEvent, this->Callback); + } + + // make a connection between this and the Qt object + qt_obj->connect(this, SIGNAL(EmitExecute(vtkObject*,unsigned long,void*,vtkCommand*)), slot); +} + +void vtkQtConnection::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << + this->VTKObject->GetClassName() << ":" << + vtkCommand::GetStringFromEventId(this->VTKEvent) << " <----> " << + this->QtObject->metaObject()->className() << "::" << +#if QT_VERSION < 0x040000 + this->QtSlot << "\n"; +#else + this->QtSlot.toAscii().data() << "\n"; +#endif +} + + +// hold all the connections +class vtkQtConnections : public vtkstd::vector< vtkQtConnection* > {}; + +vtkStandardNewMacro(vtkEventQtSlotConnect) + +// constructor +vtkEventQtSlotConnect::vtkEventQtSlotConnect() +{ + Connections = new vtkQtConnections; +} + + +vtkEventQtSlotConnect::~vtkEventQtSlotConnect() +{ + // clean out connections + vtkQtConnections::iterator iter; + for(iter=Connections->begin(); iter!=Connections->end(); ++iter) + { + delete (*iter); + } + + delete Connections; +} + +void vtkEventQtSlotConnect::Connect(vtkObject* vtk_obj, unsigned long event, + QObject* qt_obj, const char* slot, void* client_data, float priority) +{ + vtkQtConnection* connection = new vtkQtConnection; + connection->SetConnection(vtk_obj, event, qt_obj, slot, client_data, priority); + Connections->push_back(connection); +} + + +void vtkEventQtSlotConnect::Disconnect(vtkObject* vtk_obj, unsigned long event, + QObject* qt_obj, const char* slot) +{ + bool all_info = true; + if(slot == NULL || qt_obj == NULL || event == vtkCommand::NoEvent) + all_info = false; + + vtkQtConnections::iterator iter; + for(iter=Connections->begin(); iter!=Connections->end();) + { + // if information matches, remove the connection + if((*iter)->IsConnection(vtk_obj, event, qt_obj, slot)) + { + delete (*iter); + iter = Connections->erase(iter); + // if user passed in all information, only remove one connection and quit + if(all_info) + iter = Connections->end(); + } + else + ++iter; + } +} + +void vtkEventQtSlotConnect::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if(Connections->empty()) + { + os << indent << "No Connections\n"; + } + else + { + os << indent << "Connections:\n"; + vtkQtConnections::iterator iter; + for(iter=Connections->begin(); iter!=Connections->end(); ++iter) + { + (*iter)->PrintSelf(os, indent.GetNextIndent()); + } + } +} + + diff --git a/GUISupport/Qt/vtkEventQtSlotConnect.h b/GUISupport/Qt/vtkEventQtSlotConnect.h new file mode 100644 index 0000000..a100b4f --- /dev/null +++ b/GUISupport/Qt/vtkEventQtSlotConnect.h @@ -0,0 +1,152 @@ +/*========================================================================= + + Copyright 2004 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +/*======================================================================== + For general information about using VTK and Qt, see: + http://www.trolltech.com/products/3rdparty/vtksupport.html +=========================================================================*/ + +/*======================================================================== + !!! WARNING for those who want to contribute code to this file. + !!! If you use a commercial edition of Qt, you can modify this code. + !!! If you use an open source version of Qt, you are free to modify + !!! and use this code within the guidelines of the GPL license. + !!! Unfortunately, you cannot contribute the changes back into this + !!! file. Doing so creates a conflict between the GPL and BSD-like VTK + !!! license. +=========================================================================*/ + +// .NAME vtkEventQtSlotConnect - Manage connections between VTK events and Qt slots. +// .SECTION Description +// vtkEventQtSlotConnect provides a way to manage connections between VTK events +// and Qt slots. +// Qt slots to connect with must have one of the following signatures: +// - MySlot() +// - MySlot(vtkObject* caller) +// - MySlot(vtkObject* caller, unsigned long vtk_event) +// - MySlot(vtkObject* caller, unsigned long vtk_event, void* client_data) +// - MySlot(vtkObject* caller, unsigned long vtk_event, void* client_data, vtkCommand*) + + +#ifndef VTK_EVENT_QT_SLOT_CONNECT +#define VTK_EVENT_QT_SLOT_CONNECT + +#include "vtkObject.h" +#include "vtkCommand.h" // for event defines +#include "qobject.h" + +class QObject; +class vtkCallbackCommand; +class vtkQtConnections; + +#if defined(WIN32) && defined(VTK_BUILD_SHARED_LIBS) +#if defined(QVTK_EXPORTS) || defined(QVTKWidgetPlugin_EXPORTS) +#define QVTK_EXPORT __declspec( dllexport ) +#else +#define QVTK_EXPORT __declspec( dllimport ) +#endif +#else +#define QVTK_EXPORT +#endif + +// manage connections between VTK object events and Qt slots +class QVTK_EXPORT vtkEventQtSlotConnect : public vtkObject +{ + public: + static vtkEventQtSlotConnect* New(); + vtkTypeMacro(vtkEventQtSlotConnect, vtkObject) + + // Description: + // Print the current connections between VTK and Qt + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Connect a vtk object's event with a Qt object's slot. + // Multiple connections which are identical are treated as separate connections. + virtual void Connect(vtkObject* vtk_obj, unsigned long event, + QObject* qt_obj, const char* slot, void* client_data=NULL, float priority=0.0); + + // Description: + // Disconnect a vtk object from a qt object. + // Passing in only a vtk object will disconnect all slots from it. + // Passing only a vtk object and event, will disconnect all slots matching the vtk object and event. + // Passing all information in will match all information. + virtual void Disconnect(vtkObject* vtk_obj, unsigned long event=vtkCommand::NoEvent, + QObject* qt_obj=NULL, const char* slot = 0); + + protected: + vtkQtConnections* Connections; + + vtkEventQtSlotConnect(); + ~vtkEventQtSlotConnect(); + + private: + // unimplemented + vtkEventQtSlotConnect(const vtkEventQtSlotConnect&); + void operator=(const vtkEventQtSlotConnect&); +}; + + + +// class for managing a single VTK/Qt connection +// not to be used directly, only here in header file for +// moc to process +class vtkQtConnection : public QObject +{ + Q_OBJECT + + public: + + // constructor + vtkQtConnection(); + + // destructor, disconnect if necessary + ~vtkQtConnection(); + + // print function + void PrintSelf(ostream& os, vtkIndent indent); + + // callback from VTK to emit signal + void Execute(vtkObject* caller, unsigned long event, void* client_data); + + // set the connection + void SetConnection(vtkObject* vtk_obj, unsigned long event, + QObject* qt_obj, const char* slot, void* client_data, float priority=0.0); + + // check if a connection matches input parameters + bool IsConnection(vtkObject* vtk_obj, unsigned long event, + QObject* qt_obj, const char* slot); + + static void DoCallback(vtkObject* vtk_obj, unsigned long event, + void* client_data, void* call_data); + + signals: + // the qt signal for moc to take care of + void EmitExecute(vtkObject*, unsigned long, void* client_data, vtkCommand*); + + protected: + + // the connection information + vtkObject* VTKObject; + vtkCallbackCommand* Callback; + QObject* QtObject; + void* ClientData; + unsigned long VTKEvent; + QString QtSlot; + + private: + vtkQtConnection(const vtkQtConnection&); + void operator=(const vtkQtConnection&); + +}; + +#endif + diff --git a/GenericFiltering/CMakeLists.txt b/GenericFiltering/CMakeLists.txt new file mode 100644 index 0000000..153585d --- /dev/null +++ b/GenericFiltering/CMakeLists.txt @@ -0,0 +1,32 @@ +SET(KIT GenericFiltering) +SET(UKIT GENERIC_FILTERING) +SET(KIT_TCL_LIBS vtkFilteringTCL vtkGraphicsTCL) +SET(KIT_PYTHON_LIBS vtkFilteringPythonD vtkGraphicsPythonD) +SET(KIT_JAVA_LIBS vtkFilteringJava vtkGraphicsJava) +SET(KIT_LIBS vtkFiltering vtkGraphics) + +SET( Kit_SRCS +vtkGenericContourFilter.cxx +vtkGenericGeometryFilter.cxx +vtkGenericClip.cxx +vtkGenericProbeFilter.cxx +vtkGenericDataSetTessellator.cxx +vtkGenericCutter.cxx +vtkGenericGlyph3DFilter.cxx +vtkGenericStreamTracer.cxx +vtkGenericOutlineFilter.cxx +) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- diff --git a/GenericFiltering/README.html b/GenericFiltering/README.html new file mode 100644 index 0000000..94a0201 --- /dev/null +++ b/GenericFiltering/README.html @@ -0,0 +1,145 @@ + +
+VTK Adaptor Framework README + + +
+ + +

+
+The VTK Adaptor Framework and Generic Filtering +

+ +
+

Overview

+The classes in this directory are part of a body of work that support the +interface of VTK to external simulation packages. These external packages may +be finite element programs, CFD systems, or other simulation systems that are +based on discretizing a domain into elements, where the element (or in VTK +terminology, cell) basis functions are of arbitrary complexity. The purpose +of this work is to avoid duplicating data in order to visualize it with VTK, +and to take advantage of basis function formulations that are already +implemented in existing simulation packages. (For further details, please see +the paper "Framework for Visualizing Higher-Order Basis Functions" by +Schroeder, Bertel, Malaterre, Thompson, Pebay, O'Bara and Tendulkar, in the +Proceedings of IEEE Visualization 2005, October 2005.) +

+In the past, systems that interface with VTK typically require writing output +data in VTK format, or require writing a special VTK reader. Further, cells +of higher-order basis (e.g., cubic, quadric, or even mixed-order +formulations) had no counterpart in VTK, so the user was responsible for +tessellating the cells into linear forms, often at the cost of excessive +memory consumption or inaccuracy. +

+We refer to this work as the "adaptor framework". That is, it adapts VTK to a +particular simulation system. It does this by generalizing the VTK dataset, +cell, and attribute classes, and providing special filters that operate on +these new general classes. Further, because we assume that the cells may be +of arbitrary complexity in terms of their basis functions, tessellation +functions (with associated error metric) are used to automatically subdivide +complex cells into linear primitives. This allows the use of standard linear +visualization algorithms: algorithms that have been proven to be robust, +fast, and dependable. +

+The adaptor framework consists of a few basic components: new implementations +of data objects (vtkGenericDataSet and vtkGenericAdaptorCell), classes to +support the tessellation of cells (vtkGenericCellTessellator and +vtkGenericSubdivisionErrorMetric), and classes that filter the new data +objects (e.g., vtkGenericContourFilter). +

+Note that we choose to implement a select number of filters. One filter +simply performs tessellation on a vtkGenericDataSet to produce a linearized +vtkUnstructuredGrid (vtkGenericDataSetTessellator). The others are common +filters used in a wide variety of visualization applications: +

    +
  • vtkGenericDataSetTessellator
  • +
  • vtkGenericContourFilter
  • +
  • vtkGenericCutter
  • +
  • vtkGenericClip
  • +
  • vtkGenericProbeFilter
  • +
  • vtkGenericGlyph3DFilter
  • +
  • vtkGenericStreamTracer
  • +
  • vtkGenericGeometryFilter
  • +
+ +At the same time that we were designing the adaptor framework, we also found +it necessary to rework the vtkDataSet/vtkCell/vtkDataArray API. We found that +the assumptions of contiguous data (manifested in the form of monotonically +increasing, contiguous, integral ids) to be overly limiting. Thus we moved +to an iterator-based framework. + +It is possible that in time the vtkGenericDataSet may replace the current +vtkDataSet, and that the existing filters that input vtkDataSet may be +rewritten. However, this is a future undertaking. + +
+

Compatibility Warning

+The classes in this directory (and the classes found in +VTK/Common/vtkGeneric*) are undergoing rapid development. The names of these +classes, and their API, may change. Please use them only if you are prepared +to deal with the inevitable changes that will occur over the next six +months.

+ +


+

Commercial Expression

+Kitware +http://www.kitware.com +is teaming with Simmetrix, Inc. +http://www.simmetrix.com +to create commercial tools that integrate the VTK visualization +environment to Simmetrix's products, and to integrate Simmetrix's +integration framework into ParaView. +

+If you are interested in building an adapted framework to VTK from +your analysis/simulation package, please email sales "at" kitware.com +for more information. + +


+

Acknowledgements

+This work has been supported through the efforts of several organizations +and individuals. +

+The National Science Foundation +

    +
  • NSF SBIR Phase II Grant #DMI-0238964
    + Title:Visualizing Arbitrary Basis Functions for Advanced Engineering + Analysis and Simulation
    + PI: William J. Schroeder
  • +
+

+The US National Tri-Lab Community (Sandia, Livermore, Los Alamos) +

    +
  • David Thompson
  • +
  • Philippe Pebay
  • +
  • Brian Wylie
  • +
  • Gary Templet
  • +
  • Jim Ahrens
  • +
+

+Kitware, Inc. +

    +
  • Will Schroeder
  • +
  • Francois Bertel
  • +
  • Mathieu Malaterre
  • +
+

+Simmetrix, Inc. +

    +
  • Bob O'Bara
  • +
  • Saurabh Tendulkar
  • +
  • Mark Beall
  • +
+LeHigh University. +
    +
  • Dr. Herman Nied
  • +
+ + + + diff --git a/GenericFiltering/Testing/CMakeLists.txt b/GenericFiltering/Testing/CMakeLists.txt new file mode 100644 index 0000000..c1d17c4 --- /dev/null +++ b/GenericFiltering/Testing/CMakeLists.txt @@ -0,0 +1,13 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-GenericFiltering ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/GenericFiltering" + VTK_GENERIC_FILTERING_EXPORT + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/GenericFiltering/Testing/Cxx/CMakeLists.txt b/GenericFiltering/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..8641d31 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,103 @@ +# The bridge serves two purposes: +# 1. Show the users how to implement a vtkGenericDataSet +# 2. Test and validate the filters on a vtkGenericDataset on standard VTK +# classes. + +# C++ tests for the bridge between standard VTK classes and the +# vtkGenericDataSet. + +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + +INCLUDE_DIRECTORIES( + ${VTK_SOURCE_DIR}/GenericFiltering/Testing/Cxx/Bridge + ) + +#SET(KIT Bridge) +SET(KIT GenericFiltering) +SET(UKIT BRIDGE) +SET( Kit_SRCS +vtkBridgeCell.cxx +vtkBridgeDataSet.cxx +vtkBridgeAttribute.cxx +vtkBridgeCellIterator.cxx +vtkBridgePointIterator.cxx +vtkBridgePointIteratorOnCell.cxx +vtkBridgePointIteratorOnDataSet.cxx +vtkBridgePointIteratorOne.cxx +vtkBridgeCellIteratorStrategy.cxx +vtkBridgeCellIteratorOnDataSet.cxx +vtkBridgeCellIteratorOne.cxx +vtkBridgeCellIteratorOnCellBoundaries.cxx +vtkBridgeCellIteratorOnCellList.cxx +) + +SET_SOURCE_FILES_PROPERTIES( +vtkBridgeCell.cxx +vtkBridgeCellIterator.cxx +vtkBridgePointIterator.cxx +vtkBridgePointIteratorOnCell.cxx +vtkBridgePointIteratorOnDataSet.cxx +vtkBridgePointIteratorOne.cxx +vtkBridgeAttribute.cxx +vtkBridgeCellIteratorStrategy.cxx +vtkBridgeCellIteratorOnDataSet.cxx +vtkBridgeCellIteratorOne.cxx +vtkBridgeCellIteratorOnCellBoundaries.cxx +vtkBridgeCellIteratorOnCellList.cxx + WRAP_EXCLUDE +) + +# add tests that do not require data +SET(MyTests + otherCreation.cxx +) + +# add tests that require data +IF (VTK_DATA_ROOT) + SET(MyTests ${MyTests} + TestGenericDataSetTessellator.cxx + TestGenericGeometryFilter.cxx + TestGenericGlyph3DFilter.cxx + TestGenericContourFilter.cxx + TestGenericClip.cxx + TestGenericCutter.cxx + TestGenericStreamTracer.cxx + TestSmoothErrorMetric.cxx + TestViewDependentErrorMetric.cxx + ) +ENDIF (VTK_DATA_ROOT) + +# +# Create a test lists +CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx ${MyTests} + EXTRA_INCLUDE vtkTestDriver.h +) + +ADD_EXECUTABLE(${KIT}CxxTests ${Tests} ${Kit_SRCS} ) +TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkGenericFiltering vtkRendering vtkIO) + +SET (TestsToRun ${Tests}) +REMOVE (TestsToRun ${KIT}CxxTests.cxx) + +# +# Add all the executables +#FOREACH (test ${TestsToRun}) +# GET_FILENAME_COMPONENT(TName ${test} NAME_WE) +# ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) +#ENDFOREACH (test) + + # + # Add all the executables + FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + IF (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName} + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/${KIT}/${TName}.png) + ELSE (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) + ENDIF (VTK_DATA_ROOT) + ENDFOREACH (test) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) diff --git a/GenericFiltering/Testing/Cxx/TestGenericClip.cxx b/GenericFiltering/Testing/Cxx/TestGenericClip.cxx new file mode 100644 index 0000000..3c1103f --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestGenericClip.cxx @@ -0,0 +1,185 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGenericClip.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +//#define WITH_GEOMETRY_FILTER +//#define WRITE_GENERIC_RESULT + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericClip.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkDataSetMapper.h" +#include "vtkPolyData.h" +#include "vtkPlane.h" +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkSimpleCellTessellator.h" +#include "vtkXMLUnstructuredGridWriter.h" + +#ifdef WITH_GEOMETRY_FILTER +#include "vtkGeometryFilter.h" +#include "vtkPolyDataMapper.h" +#endif + +int TestGenericClip(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); + +//char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/Test2_Volume.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadHexa01.vtu"); + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.01,ds); // 0.001 + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); + + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetSubdivisionLevels(0,100); + + vtkIndent indent; + ds->PrintSelf(cout,indent); + + // Create the filter + + vtkPlane *implicitPlane = vtkPlane::New(); + implicitPlane->SetOrigin(0.5, 0, 0); // (0.5, 0, 0); + implicitPlane->SetNormal(1, 1, 1); // (1, 1, 1); + + vtkGenericClip *clipper = vtkGenericClip::New(); + clipper->SetInput(ds); + + clipper->SetClipFunction(implicitPlane); + implicitPlane->Delete(); + clipper->SetValue( 0.5 ); + clipper->SetInsideOut(1); + + clipper->Update(); //So that we can call GetRange() on the scalars + + assert(clipper->GetOutput()!=0); + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + + +#ifdef WITH_GEOMETRY_FILTER + vtkGeometryFilter *geom = vtkGeometryFilter::New(); + geom->SetInputConnection(clipper->GetOutputPort()); + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection( geom->GetOutputPort() ); + geom->Delete(); +#else + vtkDataSetMapper *mapper = vtkDataSetMapper::New(); + mapper->SetInputConnection( clipper->GetOutputPort() ); +#endif + mapper->SetLookupTable(lut); + + if(clipper->GetOutput()->GetPointData()!=0) + { + if(clipper->GetOutput()->GetPointData()->GetScalars()!=0) + { + mapper->SetScalarRange( clipper->GetOutput()->GetPointData()-> + GetScalars()->GetRange()); + } + } + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + renderer->AddActor(actor); + +#ifdef WRITE_GENERIC_RESULT + // Save the result of the filter in a file + vtkXMLUnstructuredGridWriter *writer=vtkXMLUnstructuredGridWriter::New(); + writer->SetInputConnection(clipper->GetOutputPort()); + writer->SetFileName("clipped.vtu"); + writer->SetDataModeToAscii(); + writer->Write(); + writer->Delete(); +#endif // #ifdef WRITE_GENERIC_RESULT + + + // Standard testing code. + renderer->SetBackground(0.5,0.5,0.5); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + clipper->Delete(); + ds->Delete(); + lut->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestGenericContourFilter.cxx b/GenericFiltering/Testing/Cxx/TestGenericContourFilter.cxx new file mode 100644 index 0000000..e679d01 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestGenericContourFilter.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGenericContourFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericContourFilter.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyData.h" +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkSimpleCellTessellator.h" + +int TestGenericContourFilter(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadHexa01.vtu"); + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.1,ds); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); + + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetMaxSubdivisionLevel(10); + + vtkIndent indent; + ds->PrintSelf(cout,indent); + + // Create the filter + vtkGenericContourFilter *contour = vtkGenericContourFilter::New(); + contour->SetInput(ds); + contour->SetValue( 0, 0.1); + contour->Update(); //So that we can call GetRange() on the scalars + + assert(contour->GetOutput()!=0); + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetLookupTable(lut); + mapper->SetInputConnection( contour->GetOutputPort() ); + + if(contour->GetOutput()->GetPointData()!=0) + { + if(contour->GetOutput()->GetPointData()->GetScalars()!=0) + { + mapper->SetScalarRange( contour->GetOutput()->GetPointData()-> + GetScalars()->GetRange()); + } + } + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + renderer->AddActor(actor); + + // Standard testing code. + renderer->SetBackground(0.5,0.5,0.5); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + contour->Delete(); + ds->Delete(); + lut->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestGenericCutter.cxx b/GenericFiltering/Testing/Cxx/TestGenericCutter.cxx new file mode 100644 index 0000000..3262c06 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestGenericCutter.cxx @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGenericCutter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericCutter.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkDataSetMapper.h" +#include "vtkPolyData.h" +#include "vtkPlane.h" +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkSimpleCellTessellator.h" + +int TestGenericCutter(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadHexa01.vtu"); + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.1,ds); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetMaxSubdivisionLevel(10); + + vtkIndent indent; + ds->PrintSelf(cout,indent); + + // Create the filter + + vtkPlane *implicitPlane = vtkPlane::New(); + implicitPlane->SetOrigin(0.5, 0, 0); // 0, -1, 0 + implicitPlane->SetNormal(1, 1, 1); + + vtkGenericCutter *cutter = vtkGenericCutter::New(); + cutter->SetInput(ds); + + cutter->SetCutFunction(implicitPlane); + implicitPlane->Delete(); + cutter->SetValue( 0,0.5 ); + cutter->GenerateCutScalarsOn(); + + cutter->Update(); //So that we can call GetRange() on the scalars + + assert(cutter->GetOutput()!=0); + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + + vtkDataSetMapper *mapper = vtkDataSetMapper::New(); + mapper->SetLookupTable(lut); + mapper->SetInputConnection( cutter->GetOutputPort() ); + + if(cutter->GetOutput()->GetPointData()!=0) + { + if(cutter->GetOutput()->GetPointData()->GetScalars()!=0) + { + mapper->SetScalarRange( cutter->GetOutput()->GetPointData()-> + GetScalars()->GetRange()); + } + } + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + renderer->AddActor(actor); + + // Standard testing code. + renderer->SetBackground(0.5,0.5,0.5); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + cutter->Delete(); + ds->Delete(); + lut->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestGenericDataSetTessellator.cxx b/GenericFiltering/Testing/Cxx/TestGenericDataSetTessellator.cxx new file mode 100644 index 0000000..d8d6e76 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestGenericDataSetTessellator.cxx @@ -0,0 +1,266 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGenericDataSetTessellator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +#define WRITE_GENERIC_RESULT + +#define WITH_GEOMETRY_FILTER + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericDataSetTessellator.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkDataSetMapper.h" +#include "vtkLabeledDataMapper.h" +#include "vtkActor2D.h" +#include "vtkCommand.h" +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkSimpleCellTessellator.h" + +#ifdef WITH_GEOMETRY_FILTER +#include "vtkGeometryFilter.h" +#include "vtkPolyDataMapper.h" +#endif + +#ifdef WRITE_GENERIC_RESULT +# include "vtkXMLUnstructuredGridWriter.h" +#endif // #ifdef WRITE_GENERIC_RESULT + +// debugging when clipping on n=(1,1,1) c=(0.5,0,0) +//#include "vtkExtractGeometry.h" +//#include "vtkSphere.h" + +// Remark about the lookup tables that seem different between the +// GenericGeometryFilter and GenericDataSetTessellator: +// the lookup table is set for the whole unstructured grid, the tetra plus +// the triangle. The lookup table changed because of the tetra: the +// GenericDataSetTessellator need to create inside sub-tetra that have +// minimal attributes, the GenericGeometryFilter just need to tessellate the +// face of the tetra, for which the values at points are not minimal. + +class SwitchLabelsCallback + : public vtkCommand +{ +public: + static SwitchLabelsCallback *New() + { return new SwitchLabelsCallback; } + + void SetLabeledDataMapper(vtkLabeledDataMapper *aLabeledDataMapper) + { + this->LabeledDataMapper=aLabeledDataMapper; + } + void SetRenderWindow(vtkRenderWindow *aRenWin) + { + this->RenWin=aRenWin; + } + + virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*) + { + if(this->LabeledDataMapper->GetLabelMode()==VTK_LABEL_SCALARS) + { + this->LabeledDataMapper->SetLabelMode(VTK_LABEL_IDS); + } + else + { + this->LabeledDataMapper->SetLabelMode(VTK_LABEL_SCALARS); + } + this->RenWin->Render(); + } +protected: + vtkLabeledDataMapper *LabeledDataMapper; + vtkRenderWindow *RenWin; +}; + +int TestGenericDataSetTessellator(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadTet4.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/tetraMesh.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/Test2_Volume.vtu"); + +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadHexa01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadQuad01.vtu"); + + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.1,ds); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); // 0.11, 0.005 + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetSubdivisionLevels(0,100); + vtkIndent indent; + ds->PrintSelf(cout,indent); + + // Create the filter + vtkGenericDataSetTessellator *tessellator = vtkGenericDataSetTessellator::New(); + tessellator->SetInput(ds); + + tessellator->Update(); //So that we can call GetRange() on the scalars + + assert(tessellator->GetOutput()!=0); + + // for debugging clipping on the hexa +#if 0 + vtkExtractGeometry *eg=vtkExtractGeometry::New(); + eg->SetInputConnection(tessellator->GetOutputPort()); + + vtkSphere *sphere=vtkSphere::New(); + sphere->SetRadius(0.1); + sphere->SetCenter(0,0,0); + + eg->SetImplicitFunction(sphere); + eg->SetExtractInside(1); + eg->SetExtractBoundaryCells(0); + + vtkXMLUnstructuredGridWriter *cwriter=vtkXMLUnstructuredGridWriter::New(); + cwriter->SetInputConnection(eg->GetOutputPort()); + cwriter->SetFileName("extracted_tessellated.vtu"); + cwriter->SetDataModeToAscii(); + cwriter->Write(); + + cwriter->Delete(); + sphere->Delete(); + eg->Delete(); +#endif + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + +#ifdef WITH_GEOMETRY_FILTER + vtkGeometryFilter *geom = vtkGeometryFilter::New(); + geom->SetInputConnection(tessellator->GetOutputPort()); + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection( geom->GetOutputPort() ); + geom->Delete(); +#else + vtkDataSetMapper *mapper = vtkDataSetMapper::New(); + mapper->SetInputConnection( tessellator->GetOutputPort() ); +#endif + mapper->SetLookupTable(lut); + if(tessellator->GetOutput()->GetPointData()!=0) + { + if(tessellator->GetOutput()->GetPointData()->GetScalars()!=0) + { + mapper->SetScalarRange( tessellator->GetOutput()->GetPointData()-> + GetScalars()->GetRange()); + } + } + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + renderer->AddActor(actor); + +#ifdef WRITE_GENERIC_RESULT + // Save the result of the filter in a file + vtkXMLUnstructuredGridWriter *writer=vtkXMLUnstructuredGridWriter::New(); + writer->SetInputConnection(tessellator->GetOutputPort()); + writer->SetFileName("tessellated.vtu"); + writer->SetDataModeToAscii(); + writer->Write(); + writer->Delete(); +#endif // #ifdef WRITE_GENERIC_RESULT + + vtkActor2D *actorLabel=vtkActor2D::New(); + vtkLabeledDataMapper *labeledDataMapper=vtkLabeledDataMapper::New(); + labeledDataMapper->SetLabelMode(VTK_LABEL_IDS); + labeledDataMapper->SetInputConnection(tessellator->GetOutputPort()); + actorLabel->SetMapper(labeledDataMapper); + labeledDataMapper->Delete(); + renderer->AddActor(actorLabel); + actorLabel->SetVisibility(0); + actorLabel->Delete(); + + // Standard testing code. + renderer->SetBackground(0.5,0.5,0.5); + renWin->SetSize(300,300); + renWin->Render(); + + tessellator->GetOutput()->PrintSelf(cout,indent); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + SwitchLabelsCallback *switchLabels=SwitchLabelsCallback::New(); + switchLabels->SetRenderWindow(renWin); + switchLabels->SetLabeledDataMapper(labeledDataMapper); + iren->AddObserver(vtkCommand::UserEvent,switchLabels); + switchLabels->Delete(); + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + tessellator->Delete(); + ds->Delete(); + lut->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestGenericGeometryFilter.cxx b/GenericFiltering/Testing/Cxx/TestGenericGeometryFilter.cxx new file mode 100644 index 0000000..7f8b862 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestGenericGeometryFilter.cxx @@ -0,0 +1,172 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGenericGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +//#define WRITE_GENERIC_RESULT + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericGeometryFilter.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyData.h" +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkSimpleCellTessellator.h" + +#ifdef WRITE_GENERIC_RESULT +# include "vtkXMLPolyDataWriter.h" +#endif // #ifdef WRITE_GENERIC_RESULT + +// Remark about the lookup tables that seem different between the +// GenericGeometryFilter and GenericDataSetTessellator: +// the lookup table is set for the whole unstructured grid, the tetra plus +// the triangle. The lookup table changed because of the tetra: the +// GenericDataSetTessellator need to create inside sub-tetra that have +// minimal attributes, the GenericGeometryFilter just need to tessellate the +// face of the tetra, for which the values at points are not minimal. + +int TestGenericGeometryFilter(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadTet2.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/Test2_Volume.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadHexa01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadQuad01.vtu"); + + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.1,ds); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); + + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetMaxSubdivisionLevel(10); + + vtkIndent indent; + ds->PrintSelf(cout,indent); + + // Create the filter + vtkGenericGeometryFilter *geom = vtkGenericGeometryFilter::New(); + geom->SetInput(ds); + + geom->Update(); //So that we can call GetRange() on the scalars + + assert(geom->GetOutput()!=0); + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetLookupTable(lut); + mapper->SetInputConnection( geom->GetOutputPort() ); + + if(geom->GetOutput()->GetPointData()!=0) + { + if(geom->GetOutput()->GetPointData()->GetScalars()!=0) + { + mapper->SetScalarRange( geom->GetOutput()->GetPointData()-> + GetScalars()->GetRange()); + } + } + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + renderer->AddActor(actor); + +#ifdef WRITE_GENERIC_RESULT + // Save the result of the filter in a file + vtkXMLPolyDataWriter *writer=vtkXMLPolyDataWriter::New(); + writer->SetInputConnection(geom->GetOutputPort()); + writer->SetFileName("geometry.vtp"); + writer->SetDataModeToAscii(); + writer->Write(); + writer->Delete(); +#endif // #ifdef WRITE_GENERIC_RESULT + + // Standard testing code. + renderer->SetBackground(0.5,0.5,0.5); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + geom->Delete(); + ds->Delete(); + lut->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestGenericGlyph3DFilter.cxx b/GenericFiltering/Testing/Cxx/TestGenericGlyph3DFilter.cxx new file mode 100644 index 0000000..08ad86a --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestGenericGlyph3DFilter.cxx @@ -0,0 +1,163 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGenericGlyph3DFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericGeometryFilter.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyData.h" +#include "vtkArrowSource.h" +#include "vtkGenericGlyph3DFilter.h" +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkSimpleCellTessellator.h" + +int TestGenericGlyph3DFilter(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.1,ds); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetMaxSubdivisionLevel(10); + + vtkIndent indent; + ds->PrintSelf(cout,indent); + + // Create the filter + vtkArrowSource *arrow=vtkArrowSource::New(); + vtkGenericGlyph3DFilter *glyph=vtkGenericGlyph3DFilter::New(); + glyph->SetInput(ds); + glyph->SetSource(arrow->GetOutput()); + glyph->SetScaling(1); + glyph->SetScaleModeToScaleByScalar(); + glyph->SelectInputScalars("scalars"); + glyph->SetColorModeToColorByScale(); + + vtkPolyDataMapper *glyphMapper=vtkPolyDataMapper::New(); + glyphMapper->SetInputConnection(glyph->GetOutputPort()); + vtkActor *glyphActor=vtkActor::New(); + glyphActor->SetMapper(glyphMapper); + renderer->AddActor( glyphActor ); + + // Create the filter + vtkGenericGeometryFilter *geom = vtkGenericGeometryFilter::New(); + geom->SetInput(ds); + + geom->Update(); //So that we can call GetRange() on the scalars + + assert(geom->GetOutput()!=0); + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetLookupTable(lut); + mapper->SetInputConnection( geom->GetOutputPort() ); + + if(geom->GetOutput()->GetPointData()!=0) + { + if(geom->GetOutput()->GetPointData()->GetScalars()!=0) + { + mapper->SetScalarRange( geom->GetOutput()->GetPointData()-> + GetScalars()->GetRange()); + } + } + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + renderer->AddActor(actor); + + // Standard testing code. + renderer->SetBackground(0.5,0.5,0.5); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + geom->Delete(); + ds->Delete(); + lut->Delete(); + glyphActor->Delete(); + glyphMapper->Delete(); + glyph->Delete(); + arrow->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestGenericStreamTracer.cxx b/GenericFiltering/Testing/Cxx/TestGenericStreamTracer.cxx new file mode 100644 index 0000000..2b7786d --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestGenericStreamTracer.cxx @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestGenericStreamTracer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +//#define WRITE_GENERIC_RESULT + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkGenericOutlineFilter.h" +#include "vtkPolyDataMapper.h" +#include "vtkRungeKutta45.h" +#include "vtkGenericStreamTracer.h" +#include "vtkAssignAttribute.h" +#include "vtkPolyData.h" +#include "vtkRibbonFilter.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkCamera.h" + +#ifdef WRITE_GENERIC_RESULT +# include "vtkXMLPolyDataWriter.h" +#endif // #ifdef WRITE_GENERIC_RESULT + +int TestGenericStreamTracer(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkStructuredGridReader *reader = vtkStructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/office.binary.vtk"); + //char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadTet2.vtu"); + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.1,ds); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); + cout<<"input unstructured grid: "<PrintSelf(cout,indent); + + vtkGenericOutlineFilter *outline=vtkGenericOutlineFilter::New(); + outline->SetInput(ds); + vtkPolyDataMapper *mapOutline=vtkPolyDataMapper::New(); + mapOutline->SetInputConnection(outline->GetOutputPort()); + vtkActor *outlineActor=vtkActor::New(); + outlineActor->SetMapper(mapOutline); + outlineActor->GetProperty()->SetColor(0,0,0); + + vtkRungeKutta45 *rk=vtkRungeKutta45::New(); + + // Create source for streamtubes + vtkGenericStreamTracer *streamer=vtkGenericStreamTracer::New(); + streamer->SetInput(ds); + streamer->SetStartPosition(0.1,2.1,0.5); + streamer->SetMaximumPropagation(0,500); + streamer->SetMinimumIntegrationStep(1,0.1); + streamer->SetMaximumIntegrationStep(1,1.0); + streamer->SetInitialIntegrationStep(2,0.2); + streamer->SetIntegrationDirection(0); + streamer->SetIntegrator(rk); + streamer->SetRotationScale(0.5); + streamer->SetMaximumError(1.0E-8); + + vtkAssignAttribute *aa=vtkAssignAttribute::New(); + aa->SetInputConnection(streamer->GetOutputPort()); + aa->Assign("Normals",vtkDataSetAttributes::NORMALS, + vtkAssignAttribute::POINT_DATA); + + vtkRibbonFilter *rf1=vtkRibbonFilter::New(); + rf1->SetInput(aa->GetPolyDataOutput()); + rf1->SetWidth(0.1); + rf1->VaryWidthOff(); + + vtkPolyDataMapper *mapStream=vtkPolyDataMapper::New(); + mapStream->SetInputConnection(rf1->GetOutputPort()); + mapStream->SetScalarRange(ds->GetAttributes()->GetAttribute(0)->GetRange()); + vtkActor *streamActor=vtkActor::New(); + streamActor->SetMapper(mapStream); + + renderer->AddActor(outlineActor); + renderer->AddActor(streamActor); + + vtkCamera *cam=renderer->GetActiveCamera(); + cam->SetPosition(-2.35599,-3.35001,4.59236); + cam->SetFocalPoint(2.255,2.255,1.28413); + cam->SetViewUp(0.311311,0.279912,0.908149); + cam->SetClippingRange(1.12294,16.6226); + +#ifdef WRITE_GENERIC_RESULT + // Save the result of the filter in a file + vtkXMLPolyDataWriter *writer=vtkXMLPolyDataWriter::New(); + writer->SetInputConnection(streamer->GetOutputPort()); + writer->SetFileName("streamed.vtu"); + writer->SetDataModeToAscii(); + writer->Write(); + writer->Delete(); +#endif // #ifdef WRITE_GENERIC_RESULT + + // Standard testing code. + renderer->SetBackground(0.4,0.4,0.5); + renWin->SetSize(300,200); + renWin->Render(); + streamer->GetOutput()->PrintSelf(cout,indent); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + ds->Delete(); + + outline->Delete(); + mapOutline->Delete(); + outlineActor->Delete(); + + rk->Delete(); + streamer->Delete(); + aa->Delete(); + rf1->Delete(); + mapStream->Delete(); + streamActor->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestSmoothErrorMetric.cxx b/GenericFiltering/Testing/Cxx/TestSmoothErrorMetric.cxx new file mode 100644 index 0000000..789d54e --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestSmoothErrorMetric.cxx @@ -0,0 +1,189 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestSmoothErrorMetric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +//#define WRITE_GENERIC_RESULT + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericGeometryFilter.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyData.h" +#include "vtkSmoothErrorMetric.h" +#include "vtkSimpleCellTessellator.h" +#include "vtkPolyDataNormals.h" + +#ifdef WRITE_GENERIC_RESULT +# include "vtkXMLPolyDataWriter.h" +#endif // #ifdef WRITE_GENERIC_RESULT + +// Remark about the lookup tables that seem different between the +// GenericGeometryFilter and GenericDataSetTessellator: +// the lookup table is set for the whole unstructured grid, the tetra plus +// the triangle. The lookup table changed because of the tetra: the +// GenericDataSetTessellator need to create inside sub-tetra that have +// minimal attributes, the GenericGeometryFilter just need to tessellate the +// face of the tetra, for which the values at points are not minimal. + +int TestSmoothErrorMetric(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadTet2.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/Test2_Volume.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadHexa01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadQuad01.vtu"); + + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); + + + // Set the smooth error metric thresholds: + // 1. for the geometric error metric + vtkSmoothErrorMetric *smoothError=vtkSmoothErrorMetric::New(); + smoothError->SetAngleTolerance(179); + ds->GetTessellator()->GetErrorMetrics()->AddItem(smoothError); + smoothError->Delete(); + + // 2. for the attribute error metric +// vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); +// attributesError->SetAttributeTolerance(0.01); + +// ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); +// attributesError->Delete(); + + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetMaxSubdivisionLevel(100); + + vtkIndent indent; + ds->PrintSelf(cout,indent); + + // Create the filter + vtkGenericGeometryFilter *geom = vtkGenericGeometryFilter::New(); + geom->SetInput(ds); + + geom->Update(); //So that we can call GetRange() on the scalars + + assert(geom->GetOutput()!=0); + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); +// mapper->SetLookupTable(lut); + + mapper->ScalarVisibilityOff(); + +#if 0 + vtkPolyDataNormals *normalGenerator=vtkPolyDataNormals::New(); + normalGenerator->SetFeatureAngle(0.1); + normalGenerator->SetSplitting(1); + normalGenerator->SetConsistency(0); + normalGenerator->SetAutoOrientNormals(0); + normalGenerator->SetComputePointNormals(1); + normalGenerator->SetComputeCellNormals(0); + normalGenerator->SetFlipNormals(0); + normalGenerator->SetNonManifoldTraversal(1); + normalGenerator->SetInputConnection( geom->GetOutputPort() ); + mapper->SetInputConnection(normalGenerator->GetOutputPort() ); + normalGenerator->Delete( ); +#else + mapper->SetInputConnection( geom->GetOutputPort() ); +#endif + + if(geom->GetOutput()->GetPointData()!=0) + { + if(geom->GetOutput()->GetPointData()->GetScalars()!=0) + { + mapper->SetScalarRange( geom->GetOutput()->GetPointData()-> + GetScalars()->GetRange()); + } + } + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + renderer->AddActor(actor); + +#ifdef WRITE_GENERIC_RESULT + // Save the result of the filter in a file + vtkXMLPolyDataWriter *writer=vtkXMLPolyDataWriter::New(); + writer->SetInputConnection(geom->GetOutputPort()); + writer->SetFileName("geometry.vtp"); + writer->SetDataModeToAscii(); + writer->Write(); + writer->Delete(); +#endif // #ifdef WRITE_GENERIC_RESULT + + // Standard testing code. + renderer->SetBackground(0.5,0.5,0.5); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + geom->Delete(); + ds->Delete(); + lut->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/TestViewDependentErrorMetric.cxx b/GenericFiltering/Testing/Cxx/TestViewDependentErrorMetric.cxx new file mode 100644 index 0000000..5544f85 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/TestViewDependentErrorMetric.cxx @@ -0,0 +1,315 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestViewDependentErrorMetric.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how to implement a vtkGenericDataSet +// (here vtkBridgeDataSet) and to use vtkGenericDataSetTessellator filter on +// it. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +//#define WRITE_GENERIC_RESULT + +#include "vtkActor.h" +#include "vtkDebugLeaks.h" +#include "vtkPointData.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkBridgeDataSet.h" +#include "vtkGenericDataSetTessellator.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericSubdivisionErrorMetric.h" +#include +#include "vtkLookupTable.h" +#include "vtkDataSetMapper.h" +#include "vtkLabeledDataMapper.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor2D.h" +#include "vtkCommand.h" +#include "vtkGeometricErrorMetric.h" +#include "vtkAttributesErrorMetric.h" +#include "vtkSimpleCellTessellator.h" +#include "vtkViewDependentErrorMetric.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkCamera.h" +#include "vtkGenericOutlineFilter.h" +#include "vtkGenericGeometryFilter.h" +#include "vtkPolyData.h" + +#ifdef WRITE_GENERIC_RESULT +# include "vtkXMLUnstructuredGridWriter.h" +#endif // #ifdef WRITE_GENERIC_RESULT + +// Remark about the lookup tables that seem different between the +// GenericGeometryFilter and GenericDataSetTessellator: +// the lookup table is set for the whole unstructured grid, the tetra plus +// the triangle. The lookup table changed because of the tetra: the +// GenericDataSetTessellator need to create inside sub-tetra that have +// minimal attributes, the GenericGeometryFilter just need to tessellate the +// face of the tetra, for which the values at points are not minimal. + +class SwitchLabelsCallback + : public vtkCommand +{ +public: + static SwitchLabelsCallback *New() + { return new SwitchLabelsCallback; } + + void SetLabeledDataMapper(vtkLabeledDataMapper *aLabeledDataMapper) + { + this->LabeledDataMapper=aLabeledDataMapper; + } + void SetRenderWindow(vtkRenderWindow *aRenWin) + { + this->RenWin=aRenWin; + } + + virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*) + { + if(this->LabeledDataMapper->GetLabelMode()==VTK_LABEL_SCALARS) + { + this->LabeledDataMapper->SetLabelMode(VTK_LABEL_IDS); + } + else + { + this->LabeledDataMapper->SetLabelMode(VTK_LABEL_SCALARS); + } + this->RenWin->Render(); + } +protected: + vtkLabeledDataMapper *LabeledDataMapper; + vtkRenderWindow *RenWin; +}; + +int TestViewDependentErrorMetric(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderer *renderer2= vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + renWin->AddRenderer(renderer2); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // Load the mesh geometry and data from a file + vtkXMLUnstructuredGridReader *reader = vtkXMLUnstructuredGridReader::New(); + char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadraticTetra01.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/Test2_Volume.vtu"); +// char *cfname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/quadTet3.vtu"); + reader->SetFileName( cfname ); + delete[] cfname; + + // Force reading + reader->Update(); + + // Initialize the bridge + vtkBridgeDataSet *ds=vtkBridgeDataSet::New(); + ds->SetDataSet( reader->GetOutput() ); + reader->Delete(); +#if 0 + // Set the error metric thresholds: + // 1. for the geometric error metric + vtkGeometricErrorMetric *geometricError=vtkGeometricErrorMetric::New(); + geometricError->SetRelativeGeometricTolerance(0.01,ds); + + ds->GetTessellator()->GetErrorMetrics()->AddItem(geometricError); + geometricError->Delete(); + + // 2. for the attribute error metric + vtkAttributesErrorMetric *attributesError=vtkAttributesErrorMetric::New(); + attributesError->SetAttributeTolerance(0.01); // 0.11 + + ds->GetTessellator()->GetErrorMetrics()->AddItem(attributesError); + attributesError->Delete(); +#endif + + // 3. for the view dependent error metric on the first renderer + vtkViewDependentErrorMetric *viewError=vtkViewDependentErrorMetric::New(); + viewError->SetViewport(renderer); + viewError->SetPixelTolerance(10000); // 0.25; 0.0625 + ds->GetTessellator()->GetErrorMetrics()->AddItem(viewError); + viewError->Delete(); + + // 4. for the view dependent error metric on the first renderer + vtkViewDependentErrorMetric *viewError2=vtkViewDependentErrorMetric::New(); + viewError2->SetViewport(renderer2); + viewError2->SetPixelTolerance(0.25); // 0.25; 0.0625 + ds->GetTessellator()->GetErrorMetrics()->AddItem(viewError2); + viewError2->Delete(); + + cout<<"input unstructured grid: "<(ds->GetTessellator())->SetMaxSubdivisionLevel(10); + + vtkIndent indent; + ds->PrintSelf(cout,indent); + +#if 0 + // Create the filter + vtkGenericDataSetTessellator *tessellator = vtkGenericDataSetTessellator::New(); + tessellator->SetInput(ds); + + // DO NOT PERFORM UPDATE NOW, because the view dependent error metric + // need the window to be realized first + //tessellator->Update(); //So that we can call GetRange() on the scalars + + assert(tessellator->GetOutput()!=0); +#else + // Create the filter + vtkGenericGeometryFilter *tessellator = vtkGenericGeometryFilter::New(); + tessellator->SetInput(ds); + +// geom->Update(); //So that we can call GetRange() on the scalars + +#endif + + // This creates a blue to red lut. + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetHueRange (0.667, 0.0); + + vtkDataSetMapper *mapper = vtkDataSetMapper::New(); + mapper->SetLookupTable(lut); + mapper->SetInputConnection( tessellator->GetOutputPort() ); + + int i=0; + int n=ds->GetAttributes()->GetNumberOfAttributes(); + int found=0; + vtkGenericAttribute *attribute=0; + while(iGetAttributes()->GetAttribute(i); + found=(attribute->GetCentering()==vtkPointCentered + && attribute->GetNumberOfComponents()==1); + ++i; + } + if(found) + { + mapper->SetScalarRange( attribute->GetRange(0)); + } + mapper->ScalarVisibilityOff(); + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + + + vtkActor2D *actorLabel=vtkActor2D::New(); + vtkLabeledDataMapper *labeledDataMapper=vtkLabeledDataMapper::New(); + labeledDataMapper->SetLabelMode(VTK_LABEL_IDS); + labeledDataMapper->SetInputConnection(tessellator->GetOutputPort()); + actorLabel->SetMapper(labeledDataMapper); + labeledDataMapper->Delete(); + renderer->AddActor(actorLabel); + actorLabel->SetVisibility(0); + actorLabel->Delete(); + + // Standard testing code. + renderer->SetBackground(0.7,0.5,0.5); + renderer->SetViewport(0,0,0.5,1); + renderer2->SetBackground(0.5,0.5,0.8); + renderer2->SetViewport(0.5,0,1,1); + renWin->SetSize(600,300); // realized + + vtkGenericOutlineFilter *outlineFilter= vtkGenericOutlineFilter::New(); + outlineFilter->SetInput(ds); + vtkPolyDataMapper *mapperOutline=vtkPolyDataMapper::New(); + mapperOutline->SetInputConnection(outlineFilter->GetOutputPort()); + outlineFilter->Delete(); + + vtkActor *actorOutline=vtkActor::New(); + actorOutline->SetMapper(mapperOutline); + mapperOutline->Delete(); + + renderer->AddActor(actorOutline); + renderer2->AddActor(actorOutline); + actorOutline->Delete(); + // need an outline filter in the pipeline to ensure that the + // camera are set with the bounding box of the dataset. + +// vtkCamera *cam1=renderer->GetActiveCamera(); + vtkCamera *cam2=renderer2->GetActiveCamera(); + + renderer->ResetCamera(); + renderer2->ResetCamera(); + + cam2->Azimuth(90); + + // Those two lines have to be called AFTER GetActiveCamera: + // GetActiveCamera ask the mapper to update its input for the bounds + // If the actor is connected it actually ask the output of tessellator + // but the view dependent error metric are not yet initialized! + renderer->AddActor(actor); + renderer2->AddActor(actor); + + renWin->Render(); + +#ifdef WRITE_GENERIC_RESULT + // BE SURE to save AFTER a first rendering! + // Save the result of the filter in a file + vtkXMLUnstructuredGridWriter *writer=vtkXMLUnstructuredGridWriter::New(); + writer->SetInputConnection(tessellator->GetOutputPort()); + writer->SetFileName("viewdeptessellated.vtu"); + writer->SetDataModeToAscii(); + writer->DebugOn(); + writer->Write(); + writer->Delete(); + + // debug XML reader + vtkXMLUnstructuredGridReader *rreader=vtkXMLUnstructuredGridReader::New(); +// rreader->SetInputConnection(tessellator->GetOutputPort()); + rreader->SetFileName("viewdeptessellated.vtu"); +// rreader->SetDataModeToAscii(); + rreader->DebugOn(); + rreader->Update(); + rreader->Delete(); + +#endif // #ifdef WRITE_GENERIC_RESULT + + + tessellator->GetOutput()->PrintSelf(cout,indent); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + SwitchLabelsCallback *switchLabels=SwitchLabelsCallback::New(); + switchLabels->SetRenderWindow(renWin); + switchLabels->SetLabeledDataMapper(labeledDataMapper); + iren->AddObserver(vtkCommand::UserEvent,switchLabels); + switchLabels->Delete(); + iren->Start(); + } + + // Cleanup + renderer2->Delete(); + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + tessellator->Delete(); + ds->Delete(); + lut->Delete(); + + return !retVal; +} diff --git a/GenericFiltering/Testing/Cxx/otherCreation.cxx b/GenericFiltering/Testing/Cxx/otherCreation.cxx new file mode 100644 index 0000000..4841457 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/otherCreation.cxx @@ -0,0 +1,1714 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherCreation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests the creation of the BridgeDataSet + +#include "vtkBridgeDataSet.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkUnstructuredGrid.h" +#include "vtkMath.h" +#include "vtkIndent.h" +#include "vtkCellTypes.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericPointIterator.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkTetra.h" +#include "vtkTriangle.h" +#include "vtkLine.h" +#include "vtkVertex.h" +#include "vtkSystemIncludes.h" // vtkOStreamWrapper +#include "vtkDoubleArray.h" +#include "vtkPointData.h" +#include "vtkGenericAttribute.h" +#include +#include + +//----------------------------------------------------------------------------- +// Description: +// Display message for a test result and return the test value +int TestAssertion(ostream &strm, + vtkIndent indent, + const char *label, + int assertion); + +int TestEmpty(ostream &strm); + +//----------------------------------------------------------------------------- +// a dataset with points but no cells, and no pointdata and no celldata +int TestWithPoints(ostream &strm); + +//----------------------------------------------------------------------------- +// a dataset with points and cells, and no pointdata and no celldata +int TestWithPointsAndCells(ostream &strm); + +//----------------------------------------------------------------------------- +// a dataset with points and cells, pointdata but no celldata +int TestWithPointsAndCellsAndPointData(ostream &strm); + +//----------------------------------------------------------------------------- +// Description: +// Display message for a test result and return the test value +int TestAssertion(ostream &strm, + vtkIndent indent, + const char *label, + int assertion) +{ + strm<SetDataSet(g); + strm<<"vtkBridgeDataSet initialized with the empty unstructured grid"<GetNumberOfPoints()==0); + MacroTest(strm,indent,"number of cells -1",ds->GetNumberOfCells(-1)==0); + MacroTest(strm,indent,"number of cells 0",ds->GetNumberOfCells(0)==0); + MacroTest(strm,indent,"number of cells 1",ds->GetNumberOfCells(1)==0); + MacroTest(strm,indent,"number of cells 2",ds->GetNumberOfCells(2)==0); + MacroTest(strm,indent,"number of cells 3",ds->GetNumberOfCells(3)==0); + MacroTest(strm,indent,"cell dimension",ds->GetCellDimension()==-1); + + strm<<"GetCellTypes() start"<GetCellTypes(types); + MacroTest(strm,indent,"cell types",types->GetNumberOfTypes()==0); + types->Delete(); + strm<<"GetCellTypes() end"<NewCellIterator(-1); + MacroTest(strm,indent,"empty cell iterator -1 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator -1",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(0); + MacroTest(strm,indent,"empty cell iterator 0 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(1); + MacroTest(strm,indent,"empty cell iterator 1 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(2); + MacroTest(strm,indent,"empty cell iterator 2 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(3); + MacroTest(strm,indent,"empty cell iterator 3 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3",it->IsAtEnd()); + it->Delete(); + strm<<"NewCellIterator() end"<NewPointIterator(); + MacroTest(strm,indent,"empty point iterator exists",pit!=0); + pit->Begin(); + MacroTest(strm,indent,"empty point iterator",pit->IsAtEnd()); + pit->Delete(); + strm<<"NewPointIterator() end"<GetBounds(); + MacroTest(strm,indent,"volatile bounds exist",b!=0); + MacroTest(strm,indent,"default volatile bounds",!vtkMath::AreBoundsInitialized(b)); + + ds->GetBounds(bounds); + MacroTest(strm,indent,"default bounds",!vtkMath::AreBoundsInitialized(bounds)); + + c=ds->GetCenter(); + MacroTest(strm,indent,"volatile center exists",c!=0); + MacroTest(strm,indent,"default volatile center",(fabs(c[0])GetCenter(center); + MacroTest(strm,indent,"volatile center",(fabs(center[0])GetLength()-2*sqrt(3.0))GetAttributes(); + MacroTest(strm,indent,"attributes exist",attributes!=0); + MacroTest(strm,indent,"empty attributes",attributes->IsEmpty()); + MacroTest(strm,indent,"empty attributes",attributes->GetNumberOfAttributes()==0); + MacroTest(strm,indent,"empty attributes",attributes->GetNumberOfComponents()==0); + MacroTest(strm,indent,"empty attributes",attributes->GetMaxNumberOfComponents()==0); + +#if 0 + strm<<"NewBoundaryIterator() start"<NewBoundaryIterator(-1,0); + MacroTest(strm,indent,"empty boundary iterator -1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,0); + MacroTest(strm,indent,"empty boundary iterator 0,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,0); + MacroTest(strm,indent,"empty boundary iterator 1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,0); + MacroTest(strm,indent,"empty boundary iterator 2,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,0); + MacroTest(strm,indent,"empty boundary iterator 3,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(-1,1); + MacroTest(strm,indent,"empty boundary iterator -1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,1); + MacroTest(strm,indent,"empty boundary iterator 0,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,1); + MacroTest(strm,indent,"empty boundary iterator 1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,1); + MacroTest(strm,indent,"empty boundary iterator 2,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,1); + MacroTest(strm,indent,"empty boundary iterator 3,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,true",it->IsAtEnd()); + it->Delete(); + strm<<"NewBoundaryIterator() end"<Delete(); + strm<<"vtkBridgeDataSet deleted"<Delete(); + strm<<"Empty vtkUnstructuredGrid deleted"<InsertNextPoint(-1,-2,-3); + pts->InsertNextPoint(4,5,6); + strm<<"Add points to the vtkUnstructuredGrid"<SetPoints(pts); + strm<<"Points added to the vtkUnstructuredGrid"<SetDataSet(g); + strm<<"vtkBridgeDataSet initialized with the unstructured grid"<GetNumberOfPoints()==2); + MacroTest(strm,indent,"number of cells -1",ds->GetNumberOfCells(-1)==0); + MacroTest(strm,indent,"number of cells 0",ds->GetNumberOfCells(0)==0); + MacroTest(strm,indent,"number of cells 1",ds->GetNumberOfCells(1)==0); + MacroTest(strm,indent,"number of cells 2",ds->GetNumberOfCells(2)==0); + MacroTest(strm,indent,"number of cells 3",ds->GetNumberOfCells(3)==0); + MacroTest(strm,indent,"cell dimension",ds->GetCellDimension()==-1); + + strm<<"GetCellTypes() start"<GetCellTypes(types); + MacroTest(strm,indent,"cell types",types->GetNumberOfTypes()==0); + types->Delete(); + strm<<"GetCellTypes() end"<NewCellIterator(-1); + MacroTest(strm,indent,"empty cell iterator -1 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator -1",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(0); + MacroTest(strm,indent,"empty cell iterator 0 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(1); + MacroTest(strm,indent,"empty cell iterator 1 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(2); + MacroTest(strm,indent,"empty cell iterator 2 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2",it->IsAtEnd()); + it->Delete(); + it=ds->NewCellIterator(3); + MacroTest(strm,indent,"empty cell iterator 3 exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3",it->IsAtEnd()); + it->Delete(); + strm<<"NewCellIterator() end"<NewPointIterator(); + MacroTest(strm,indent,"point iterator exists",pit!=0); + pit->Begin(); + MacroTest(strm,indent,"point iterator",!pit->IsAtEnd()); + pit->GetPosition(x); + MacroTest(strm,indent,"point iterator",(x[0]==-1)&&(x[1]==-2)&&(x[2]==-3)); + MacroTest(strm,indent,"point iterator",pit->GetId()==0); + pit->Next(); + MacroTest(strm,indent,"point iterator",!pit->IsAtEnd()); + pit->GetPosition(x); + MacroTest(strm,indent,"point iterator",(x[0]==4)&&(x[1]==5)&&(x[2]==6)); + MacroTest(strm,indent,"point iterator",pit->GetId()==1); + pit->Next(); + MacroTest(strm,indent,"point iterator",pit->IsAtEnd()); + pit->Delete(); + strm<<"NewPointIterator() end"<GetBounds(); + MacroTest(strm,indent,"volatile bounds exist",b!=0); + + //strm<<"bounds=("<GetBounds(bounds); + MacroTest(strm,indent,"valid bounds",(bounds[0]==-1)&&(bounds[1]==4)&&(bounds[2]==-2)&&(bounds[3]==5)&&(bounds[4]==-3)&&(bounds[5]==6)); + + c=ds->GetCenter(); + MacroTest(strm,indent,"volatile center exists",c!=0); + MacroTest(strm,indent,"volatile center",(fabs(c[0]-1.5)GetCenter(center); + MacroTest(strm,indent,"valid center",(fabs(center[0]-1.5)GetLength()-sqrt(155.0))GetAttributes(); + MacroTest(strm,indent,"attributes exist",attributes!=0); + MacroTest(strm,indent,"empty attributes",attributes->IsEmpty()); + MacroTest(strm,indent,"empty attributes",attributes->GetNumberOfAttributes()==0); + MacroTest(strm,indent,"empty attributes",attributes->GetNumberOfComponents()==0); + MacroTest(strm,indent,"empty attributes",attributes->GetMaxNumberOfComponents()==0); + +#if 0 + strm<<"NewBoundaryIterator() start"<NewBoundaryIterator(-1,0); + MacroTest(strm,indent,"empty boundary iterator -1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,0); + MacroTest(strm,indent,"empty boundary iterator 0,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,0); + MacroTest(strm,indent,"empty boundary iterator 1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,0); + MacroTest(strm,indent,"empty boundary iterator 2,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,0); + MacroTest(strm,indent,"empty boundary iterator 3,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(-1,1); + MacroTest(strm,indent,"empty boundary iterator -1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,1); + MacroTest(strm,indent,"empty boundary iterator 0,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,1); + MacroTest(strm,indent,"empty boundary iterator 1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,1); + MacroTest(strm,indent,"empty boundary iterator 2,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,1); + MacroTest(strm,indent,"empty boundary iterator 3,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,true",it->IsAtEnd()); + it->Delete(); + strm<<"NewBoundaryIterator() end"<Delete(); + + strm<<"Delete the vtkBridgeDataSet"<Delete(); + strm<<"vtkBridgeDataSet deleted"<Delete(); + strm<<"vtkUnstructuredGrid deleted"<InsertNextPoint(0,0,0); // 0 + pts->InsertNextPoint(1,-1,0); // 1 + pts->InsertNextPoint(1,1,0); // 2 + pts->InsertNextPoint(0.5,0,1); // 3 + + pts->InsertNextPoint(2,-1,0); // 4 + pts->InsertNextPoint(3,0,0); // 5 + pts->InsertNextPoint(2,1,0); // 6 + + pts->InsertNextPoint(4,0,0); // 7 + pts->InsertNextPoint(5,0,0); // 8 + + pts->InsertNextPoint(6,0,0); // 9 + + pts->InsertNextPoint(10,0,0); // 10 0 + pts->InsertNextPoint(11,-1,0); // 11 1,4 + pts->InsertNextPoint(11,1,0); // 12 2,6 + pts->InsertNextPoint(10.5,0,1); // 13 + + pts->InsertNextPoint(12,0,0); // 14 // 5,7 + + pts->InsertNextPoint(13,0,0); // 15 // 8,9 + + pts->InsertNextPoint(14,0,0); // extra point + + + strm<<"Add points to the vtkUnstructuredGrid"<SetPoints(pts); + strm<<"Points added to the vtkUnstructuredGrid"<GetPointIds()->SetId(0,0); + tetra->GetPointIds()->SetId(1,1); + tetra->GetPointIds()->SetId(2,2); + tetra->GetPointIds()->SetId(3,3); + + g->InsertNextCell(tetra->GetCellType(),tetra->GetPointIds()); + tetra->Delete(); + + vtkTriangle *triangle=vtkTriangle::New(); + triangle->GetPointIds()->SetId(0,4); + triangle->GetPointIds()->SetId(1,5); + triangle->GetPointIds()->SetId(2,6); + + g->InsertNextCell(triangle->GetCellType(),triangle->GetPointIds()); + triangle->Delete(); + + vtkLine *line=vtkLine::New(); + line->GetPointIds()->SetId(0,7); + line->GetPointIds()->SetId(1,8); + + g->InsertNextCell(line->GetCellType(),line->GetPointIds()); + line->Delete(); + + vtkVertex *vertex=vtkVertex::New(); + vertex->GetPointIds()->SetId(0,9); + + g->InsertNextCell(vertex->GetCellType(),vertex->GetPointIds()); + vertex->Delete(); + + tetra=vtkTetra::New(); + tetra->GetPointIds()->SetId(0,10); + tetra->GetPointIds()->SetId(1,11); + tetra->GetPointIds()->SetId(2,12); + tetra->GetPointIds()->SetId(3,13); + + g->InsertNextCell(tetra->GetCellType(),tetra->GetPointIds()); + tetra->Delete(); + + triangle=vtkTriangle::New(); + triangle->GetPointIds()->SetId(0,11); + triangle->GetPointIds()->SetId(1,14); + triangle->GetPointIds()->SetId(2,12); + + g->InsertNextCell(triangle->GetCellType(),triangle->GetPointIds()); + triangle->Delete(); + + line=vtkLine::New(); + line->GetPointIds()->SetId(0,14); + line->GetPointIds()->SetId(1,15); + + g->InsertNextCell(line->GetCellType(),line->GetPointIds()); + line->Delete(); + + vertex=vtkVertex::New(); + vertex->GetPointIds()->SetId(0,15); + + g->InsertNextCell(vertex->GetCellType(),vertex->GetPointIds()); + vertex->Delete(); + + strm<<"Create a vtkBridgeDataSet"<SetDataSet(g); + strm<<"vtkBridgeDataSet initialized with the unstructured grid"<GetNumberOfPoints()==17); + MacroTest(strm,indent,"number of cells -1",ds->GetNumberOfCells(-1)==8); + MacroTest(strm,indent,"number of cells 0",ds->GetNumberOfCells(0)==2); + MacroTest(strm,indent,"number of cells 1",ds->GetNumberOfCells(1)==2); + MacroTest(strm,indent,"number of cells 2",ds->GetNumberOfCells(2)==2); + MacroTest(strm,indent,"number of cells 3",ds->GetNumberOfCells(3)==2); + MacroTest(strm,indent,"cell dimension",ds->GetCellDimension()==-1); + + strm<<"GetCellTypes() start"<GetCellTypes(types); + MacroTest(strm,indent,"cell types",types->GetNumberOfTypes()==4); + types->Delete(); + strm<<"GetCellTypes() end"<NewCellIterator(itNum); + ost=new vtkOStrStreamWrapper; + (*ost)<<"empty cell iterator "<str(); + MacroTest(strm,indent,cstring,it!=0); + delete[] cstring; + delete ost; + it->Begin(); + i=0; + count=ds->GetNumberOfCells(itNum); + while(istr(); + MacroTest(strm,indent,cstring,!it->IsAtEnd()); + delete[] cstring; + delete ost; + ++i; + cab=it->GetCell(); + MacroTest(strm,indent,"cell at iterator position is set",cab!=0); + it->Next(); + } + ost=new vtkOStrStreamWrapper; + (*ost)<<"Finished cell iterator "<str(); + MacroTest(strm,indent,cstring,it->IsAtEnd()); + delete[] cstring; + delete ost; + it->Delete(); + ++itNum; + } + strm<<"NewCellIterator() end"<NewPointIterator(); + MacroTest(strm,indent,"point iterator exists",pit!=0); + pit->Begin(); + + i=0; + count=ds->GetNumberOfPoints(); + while(iIsAtEnd()); + pit->GetPosition(x); + pts->GetPoint(i,y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + MacroTest(strm,indent,"point iterator id",pit->GetId()==i); + ++i; + pit->Next(); + } + pit->Delete(); + strm<<"NewPointIterator() end"<NewCellIterator(-1); + it->Begin(); + count=0; + pit=ds->NewPointIterator(); + int count2=0; + while(!it->IsAtEnd()) + { + cab=it->GetCell(); + cab->GetPointIterator(pit); + pit->Begin(); + switch(count) + { + case 0: // tetra + count2=0; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"point iterator id",pit->GetId()==count2); + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + case 1: // triangle + count2=4; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"point iterator id",pit->GetId()==count2); + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + case 2: // line + count2=7; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"point iterator id",pit->GetId()==count2); + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + case 3: // vertex + count2=9; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"point iterator id",pit->GetId()==count2); + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + case 4: // tetra + count2=10; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"point iterator id",pit->GetId()==count2); + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + case 5: // triangle + count2=0; + while(!pit->IsAtEnd()) + { + switch(count2) + { + case 0: + MacroTest(strm,indent,"point iterator id",pit->GetId()==11); + break; + case 1: + MacroTest(strm,indent,"point iterator id",pit->GetId()==14); + break; + case 2: + MacroTest(strm,indent,"point iterator id",pit->GetId()==12); + break; + default: + MacroTest(strm,indent,"impossible case",0); + break; + } + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + case 6: // line + count2=14; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"point iterator id",pit->GetId()==count2); + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + case 7: // vertex + count2=15; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"point iterator id",pit->GetId()==count2); + pit->GetPosition(x); + pts->GetPoint(pit->GetId(),y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + pit->Next(); + + count2++; + } + break; + default: + MacroTest(strm,indent,"impossible case",0); + break; + } + ++count; + it->Next(); + } + pit->Delete(); + it->Delete(); + strm<<" cell::GetPointIterator() end"<GetBounds(); + MacroTest(strm,indent,"volatile bounds exist",b!=0); + + strm<<"bounds=("<GetBounds(bounds); + MacroTest(strm,indent,"valid bounds",(bounds[0]==0)&&(bounds[1]==14)&&(bounds[2]==-1)&&(bounds[3]==1)&&(bounds[4]==0)&&(bounds[5]==1)); + + c=ds->GetCenter(); + MacroTest(strm,indent,"volatile center exists",c!=0); + MacroTest(strm,indent,"volatile center",(fabs(c[0]-7)GetCenter(center); + MacroTest(strm,indent,"valid center",(fabs(center[0]-7)GetLength()-sqrt(201.0))GetAttributes(); + MacroTest(strm,indent,"attributes exist",attributes!=0); + MacroTest(strm,indent,"empty attributes",attributes->IsEmpty()); + MacroTest(strm,indent,"empty attributes",attributes->GetNumberOfAttributes()==0); + MacroTest(strm,indent,"empty attributes",attributes->GetNumberOfComponents()==0); + MacroTest(strm,indent,"empty attributes",attributes->GetMaxNumberOfComponents()==0); + + strm<<"vtkBridgeCell::GetBoundaryIterator() test start"<NewCellIterator(-1); + MacroTest(strm,indent,"cell iterator on all data set cells exists" ,it!=0); + + it->Begin(); + + vtkGenericCellIterator *boundaries=ds->NewCellIterator(-1); // just for creation + MacroTest(strm,indent,"boundaries exists" ,boundaries!=0); + + i=0; + count=ds->GetNumberOfCells(-1); + + vtkGenericAdaptorCell *cab2; + + while(iIsAtEnd()); + cab=it->GetCell(); + dim=cab->GetDimension(); + + int currentDim=dim-1; + + while(currentDim>=-1) + { + cab->GetBoundaryIterator(boundaries,currentDim); + boundaries->Begin(); + while(!boundaries->IsAtEnd()) + { + cab2=boundaries->GetCell(); + MacroTest(strm,indent,"the cell at iterator position is set",cab2!=0); + boundaries->Next(); + } + --currentDim; + } + ++i; + it->Next(); + } + boundaries->Delete(); + it->Delete(); + + + strm<<"vtkBridgeCell::GetBoundaryIterator() test end"<NewBoundaryIterator(-1,0); + MacroTest(strm,indent,"empty boundary iterator -1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,0); + MacroTest(strm,indent,"empty boundary iterator 0,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,0); + MacroTest(strm,indent,"empty boundary iterator 1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,0); + MacroTest(strm,indent,"empty boundary iterator 2,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,0); + MacroTest(strm,indent,"empty boundary iterator 3,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(-1,1); + MacroTest(strm,indent,"empty boundary iterator -1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,1); + MacroTest(strm,indent,"empty boundary iterator 0,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,1); + MacroTest(strm,indent,"empty boundary iterator 1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,1); + MacroTest(strm,indent,"empty boundary iterator 2,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,1); + MacroTest(strm,indent,"empty boundary iterator 3,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,true",it->IsAtEnd()); + it->Delete(); + strm<<"NewBoundaryIterator() end"<Delete(); + + strm<<"Delete the vtkBridgeDataSet"<Delete(); + strm<<"vtkBridgeDataSet deleted"<Delete(); + strm<<"vtkUnstructuredGrid deleted"<InsertNextPoint(0,0,0); // 0 + pts->InsertNextPoint(1,-1,0); // 1 + pts->InsertNextPoint(1,1,0); // 2 + pts->InsertNextPoint(0.5,0,1); // 3 + + pts->InsertNextPoint(2,-1,0); // 4 + pts->InsertNextPoint(3,0,0); // 5 + pts->InsertNextPoint(2,1,0); // 6 + + pts->InsertNextPoint(4,0,0); // 7 + pts->InsertNextPoint(5,0,0); // 8 + + pts->InsertNextPoint(6,0,0); // 9 + + pts->InsertNextPoint(10,0,0); // 10 0 + pts->InsertNextPoint(11,-1,0); // 11 1,4 + pts->InsertNextPoint(11,1,0); // 12 2,6 + pts->InsertNextPoint(10.5,0,1); // 13 + + pts->InsertNextPoint(12,0,0); // 14 // 5,7 + + pts->InsertNextPoint(13,0,0); // 15 // 8,9 + + pts->InsertNextPoint(14,0,0); // extra point + + + strm<<"Add points to the vtkUnstructuredGrid"<SetPoints(pts); + strm<<"Points added to the vtkUnstructuredGrid"<GetPointIds()->SetId(0,0); + tetra->GetPointIds()->SetId(1,1); + tetra->GetPointIds()->SetId(2,2); + tetra->GetPointIds()->SetId(3,3); + + g->InsertNextCell(tetra->GetCellType(),tetra->GetPointIds()); + tetra->Delete(); + + vtkTriangle *triangle=vtkTriangle::New(); + triangle->GetPointIds()->SetId(0,4); + triangle->GetPointIds()->SetId(1,5); + triangle->GetPointIds()->SetId(2,6); + + g->InsertNextCell(triangle->GetCellType(),triangle->GetPointIds()); + triangle->Delete(); + + vtkLine *line=vtkLine::New(); + line->GetPointIds()->SetId(0,7); + line->GetPointIds()->SetId(1,8); + + g->InsertNextCell(line->GetCellType(),line->GetPointIds()); + line->Delete(); + + vtkVertex *vertex=vtkVertex::New(); + vertex->GetPointIds()->SetId(0,9); + + g->InsertNextCell(vertex->GetCellType(),vertex->GetPointIds()); + vertex->Delete(); + + tetra=vtkTetra::New(); + tetra->GetPointIds()->SetId(0,10); + tetra->GetPointIds()->SetId(1,11); + tetra->GetPointIds()->SetId(2,12); + tetra->GetPointIds()->SetId(3,13); + + g->InsertNextCell(tetra->GetCellType(),tetra->GetPointIds()); + tetra->Delete(); + + triangle=vtkTriangle::New(); + triangle->GetPointIds()->SetId(0,11); + triangle->GetPointIds()->SetId(1,14); + triangle->GetPointIds()->SetId(2,12); + + g->InsertNextCell(triangle->GetCellType(),triangle->GetPointIds()); + triangle->Delete(); + + line=vtkLine::New(); + line->GetPointIds()->SetId(0,14); + line->GetPointIds()->SetId(1,15); + + g->InsertNextCell(line->GetCellType(),line->GetPointIds()); + line->Delete(); + + vertex=vtkVertex::New(); + vertex->GetPointIds()->SetId(0,15); + + g->InsertNextCell(vertex->GetCellType(),vertex->GetPointIds()); + vertex->Delete(); + + strm<<"Add point data to the vtkUnstructuredGrid"<InsertNextValue(m+100); + ++m; + } + + assert(g->GetPointData()!=0); + g->GetPointData()->SetScalars(attrib); + attrib->Delete(); + attrib=0; + strm<<"Point data added to the vtkUnstructuredGrid"<SetDataSet(g); + strm<<"vtkBridgeDataSet initialized with the unstructured grid"<GetNumberOfPoints()==17); + MacroTest(strm,indent,"number of cells -1",ds->GetNumberOfCells(-1)==8); + MacroTest(strm,indent,"number of cells 0",ds->GetNumberOfCells(0)==2); + MacroTest(strm,indent,"number of cells 1",ds->GetNumberOfCells(1)==2); + MacroTest(strm,indent,"number of cells 2",ds->GetNumberOfCells(2)==2); + MacroTest(strm,indent,"number of cells 3",ds->GetNumberOfCells(3)==2); + MacroTest(strm,indent,"cell dimension",ds->GetCellDimension()==-1); + + strm<<"GetCellTypes() start"<GetCellTypes(types); + MacroTest(strm,indent,"cell types",types->GetNumberOfTypes()==4); + types->Delete(); + strm<<"GetCellTypes() end"<NewCellIterator(itNum); + ost=new vtkOStrStreamWrapper; + (*ost)<<"empty cell iterator "<str(); + MacroTest(strm,indent,cstring,it!=0); + delete[] cstring; + delete ost; + it->Begin(); + i=0; + count=ds->GetNumberOfCells(itNum); + while(istr(); + MacroTest(strm,indent,cstring,!it->IsAtEnd()); + delete[] cstring; + delete ost; + ++i; + cab=it->GetCell(); + MacroTest(strm,indent,"cell at current position is set",cab!=0); + it->Next(); + } + ost=new vtkOStrStreamWrapper; + (*ost)<<"Finished cell iterator "<str(); + MacroTest(strm,indent,cstring,it->IsAtEnd()); + delete[] cstring; + delete ost; + it->Delete(); + ++itNum; + } + strm<<"NewCellIterator() end"<NewPointIterator(); + MacroTest(strm,indent,"point iterator exists",pit!=0); + pit->Begin(); + + i=0; + count=ds->GetNumberOfPoints(); + while(iIsAtEnd()); + pit->GetPosition(x); + pts->GetPoint(i,y); + MacroTest(strm,indent,"point iterator position",(x[0]==y[0])&&(x[1]==y[1])&&(x[2]==y[2])); + MacroTest(strm,indent,"point iterator id",pit->GetId()==i); + ++i; + pit->Next(); + } + pit->Delete(); + strm<<"NewPointIterator() end"<GetBounds(); + MacroTest(strm,indent,"volatile bounds exist",b!=0); + + strm<<"bounds=("<GetBounds(bounds); + MacroTest(strm,indent,"valid bounds",(bounds[0]==0)&&(bounds[1]==14)&&(bounds[2]==-1)&&(bounds[3]==1)&&(bounds[4]==0)&&(bounds[5]==1)); + + c=ds->GetCenter(); + MacroTest(strm,indent,"volatile center exists",c!=0); + MacroTest(strm,indent,"volatile center",(fabs(c[0]-7)GetCenter(center); + MacroTest(strm,indent,"valid center",(fabs(center[0]-7)GetLength()-sqrt(201.0))GetAttributes(); + MacroTest(strm,indent,"attributes exist",attributes!=0); + MacroTest(strm,indent,"not empty attributes",!attributes->IsEmpty()); + MacroTest(strm,indent,"one attribute",attributes->GetNumberOfAttributes()==1); + MacroTest(strm,indent,"one scalar attribute",attributes->GetNumberOfComponents()==1); + MacroTest(strm,indent,"one scalar attribute",attributes->GetMaxNumberOfComponents()==1); + + vtkGenericAttribute *attribute=0; + attribute=attributes->GetAttribute(0); + MacroTest(strm,indent,"attribute exists",attribute!=0); + + MacroTest(strm,indent,"attribute name does not exist",attribute->GetName()==0); + + + int attribId; + attribId=attributes->FindAttribute(""); + MacroTest(strm,indent,"attribute not found",attribId==-1); + + g->GetPointData()->GetScalars()->SetName("pressure"); + attribId=attributes->FindAttribute("pressure"); + strm<<"attribId="<GetName()!=0); + MacroTest(strm,indent,"valid attribute name",strcmp(attribute->GetName(),"pressure")==0); + + MacroTest(strm,indent,"attribute components",attribute->GetNumberOfComponents()==1); + MacroTest(strm,indent,"attribute centering",attribute->GetCentering()==vtkPointCentered); + MacroTest(strm,indent,"attribute type",attribute->GetComponentType()==VTK_DOUBLE); + MacroTest(strm,indent,"attribute size",attribute->GetSize()==17); + + double *range=attribute->GetRange(0); + double myRange[2]; + attribute->GetRange(0,myRange); + + MacroTest(strm,indent,"attribute component lower boundary",range[0]==100); + MacroTest(strm,indent,"attribute component upper boundary",range[1]==116); + MacroTest(strm,indent,"attribute component lower boundary",myRange[0]==100); + MacroTest(strm,indent,"attribute component upper boundary",myRange[1]==116); + + MacroTest(strm,indent,"attribute max norm",fabs(attribute->GetMaxNorm()-116)<0.0001); + + + + + strm<<"vtkBridgeCell::GetBoundaryIterator() test start"<NewCellIterator(-1); + MacroTest(strm,indent,"cell iterator on all data set cells exists" ,it!=0); + + it->Begin(); + + vtkGenericCellIterator *boundaries=ds->NewCellIterator(-1); // just for creation + MacroTest(strm,indent,"boundaries exists" ,boundaries!=0); + + i=0; + count=ds->GetNumberOfCells(-1); + + vtkGenericAdaptorCell *cab2; + + while(iIsAtEnd()); + cab=it->GetCell(); + dim=cab->GetDimension(); + + int currentDim=dim-1; + + while(currentDim>=-1) + { + cab->GetBoundaryIterator(boundaries,currentDim); + boundaries->Begin(); + while(!boundaries->IsAtEnd()) + { + cab2=boundaries->GetCell(); + MacroTest(strm,indent,"the cell at iterator position is set",cab2!=0); + boundaries->Next(); + } + --currentDim; + } + ++i; + it->Next(); + } + boundaries->Delete(); + it->Delete(); + + + strm<<"vtkBridgeCell::GetBoundaryIterator() test end"<IsAtEnd() + // \post result_exists: result!=0 + // \post valid_result: sizeof(result)==GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + + strm<<"GetTuple() on cell iterator start"<NewCellIterator(-1); + + // tetra1 + it->Begin(); + + double *tuples=attribute->GetTuple(it); + double myTuples[4]; + + MacroTest(strm,indent,"tetra1, pt0",tuples[0]==100); + MacroTest(strm,indent,"tetra1, pt1",tuples[1]==101); + MacroTest(strm,indent,"tetra1, pt2",tuples[2]==102); + MacroTest(strm,indent,"tetra1, pt3",tuples[3]==103); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"tetra1, pt0",myTuples[0]==100); + MacroTest(strm,indent,"tetra1, pt1",myTuples[1]==101); + MacroTest(strm,indent,"tetra1, pt2",myTuples[2]==102); + MacroTest(strm,indent,"tetra1, pt3",myTuples[3]==103); + + // triangle1 + it->Next(); + + tuples=attribute->GetTuple(it); + + MacroTest(strm,indent,"tri1, pt0",tuples[0]==104); + MacroTest(strm,indent,"tri1, pt1",tuples[1]==105); + MacroTest(strm,indent,"tri1, pt2",tuples[2]==106); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"tri1, pt0",myTuples[0]==104); + MacroTest(strm,indent,"tri1, pt1",myTuples[1]==105); + MacroTest(strm,indent,"tri1, pt2",myTuples[2]==106); + + // line1 + it->Next(); + + tuples=attribute->GetTuple(it); + + MacroTest(strm,indent,"line1, pt0",tuples[0]==107); + MacroTest(strm,indent,"line1, pt1",tuples[1]==108); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"line1, pt0",myTuples[0]==107); + MacroTest(strm,indent,"line1, pt1",myTuples[1]==108); + + // vertex1 + it->Next(); + + tuples=attribute->GetTuple(it); + + MacroTest(strm,indent,"vertex1, pt0",tuples[0]==109); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"vertex1, pt0",myTuples[0]==109); + + + // tetra2 + it->Next(); + + tuples=attribute->GetTuple(it); + + MacroTest(strm,indent,"tetra2, pt0",tuples[0]==110); + MacroTest(strm,indent,"tetra2, pt1",tuples[1]==111); + MacroTest(strm,indent,"tetra2, pt2",tuples[2]==112); + MacroTest(strm,indent,"tetra2, pt3",tuples[3]==113); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"tetra2, pt0",myTuples[0]==110); + MacroTest(strm,indent,"tetra2, pt1",myTuples[1]==111); + MacroTest(strm,indent,"tetra2, pt2",myTuples[2]==112); + MacroTest(strm,indent,"tetra2, pt3",myTuples[3]==113); + + // triangle2 + it->Next(); + + tuples=attribute->GetTuple(it); + + MacroTest(strm,indent,"tri2, pt0",tuples[0]==111); + MacroTest(strm,indent,"tri2, pt1",tuples[1]==114); + MacroTest(strm,indent,"tri2, pt2",tuples[2]==112); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"tri2, pt0",myTuples[0]==111); + MacroTest(strm,indent,"tri2, pt1",myTuples[1]==114); + MacroTest(strm,indent,"tri2, pt2",myTuples[2]==112); + + // line1 + it->Next(); + + tuples=attribute->GetTuple(it); + + MacroTest(strm,indent,"line2, pt0",tuples[0]==114); + MacroTest(strm,indent,"line2, pt1",tuples[1]==115); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"line2, pt0",myTuples[0]==114); + MacroTest(strm,indent,"line2, pt1",myTuples[1]==115); + + // vertex2 + it->Next(); + + tuples=attribute->GetTuple(it); + + MacroTest(strm,indent,"vertex2, pt0",tuples[0]==115); + + attribute->GetTuple(it,myTuples); + MacroTest(strm,indent,"vertex2, pt0",myTuples[0]==115); + + it->Delete(); + strm<<"GetTuple() on cell iterator end"<NewPointIterator(); + pit->Begin(); + m=100; + while(!pit->IsAtEnd()) + { + tuples=attribute->GetTuple(pit); + MacroTest(strm,indent,"valid point tuple",tuples[0]==m); + attribute->GetTuple(pit,myTuples); + MacroTest(strm,indent,"valid point tuple",myTuples[0]==m); + pit->Next(); + ++m; + } + + pit->Delete(); + strm<<"GetTuple() on point iterator end"<NewCellIterator(-1); + + // tetra1 + it->Begin(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"tetra1, pt0",myTuples[0]==100); + MacroTest(strm,indent,"tetra1, pt1",myTuples[1]==101); + MacroTest(strm,indent,"tetra1, pt2",myTuples[2]==102); + MacroTest(strm,indent,"tetra1, pt3",myTuples[3]==103); + + // triangle1 + it->Next(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"tri1, pt0",myTuples[0]==104); + MacroTest(strm,indent,"tri1, pt1",myTuples[1]==105); + MacroTest(strm,indent,"tri1, pt2",myTuples[2]==106); + + // line1 + it->Next(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"line1, pt0",myTuples[0]==107); + MacroTest(strm,indent,"line1, pt1",myTuples[1]==108); + + // vertex1 + it->Next(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"vertex1, pt0",myTuples[0]==109); + + + // tetra2 + it->Next(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"tetra2, pt0",myTuples[0]==110); + MacroTest(strm,indent,"tetra2, pt1",myTuples[1]==111); + MacroTest(strm,indent,"tetra2, pt2",myTuples[2]==112); + MacroTest(strm,indent,"tetra2, pt3",myTuples[3]==113); + + // triangle2 + it->Next(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"tri2, pt0",myTuples[0]==111); + MacroTest(strm,indent,"tri2, pt1",myTuples[1]==114); + MacroTest(strm,indent,"tri2, pt2",myTuples[2]==112); + + // line1 + it->Next(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"line2, pt0",myTuples[0]==114); + MacroTest(strm,indent,"line2, pt1",myTuples[1]==115); + + // vertex2 + it->Next(); + + attribute->GetComponent(0,it,myTuples); + MacroTest(strm,indent,"vertex2, pt0",myTuples[0]==115); + + it->Delete(); + strm<<"GetComponent() on cell iterator end"<NewPointIterator(); + pit->Begin(); + m=100; + while(!pit->IsAtEnd()) + { + MacroTest(strm,indent,"valid point tuple",attribute->GetComponent(0,pit)==m); + pit->Next(); + ++m; + } + + pit->Delete(); + strm<<"GetComponent() on point iterator end"<NewCellIterator(-1); + + // tetra1 + it->Begin(); + + double pcoords[3]; + + pcoords[0]=0; + pcoords[1]=0; + pcoords[2]=0; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation p0",myTuples[0]==100); + + pcoords[0]=1; + pcoords[1]=0; + pcoords[2]=0; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation p1",myTuples[0]==101); + + pcoords[0]=0; + pcoords[1]=1; + pcoords[2]=0; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation p2",myTuples[0]==102); + + pcoords[0]=0; + pcoords[1]=0; + pcoords[2]=1; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation p3",myTuples[0]==103); + + pcoords[0]=0.5; + pcoords[1]=0; + pcoords[2]=0; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation mid p0p1",myTuples[0]==100.5); + + pcoords[0]=0; + pcoords[1]=0.5; + pcoords[2]=0; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation mid p0p2",myTuples[0]==101); + + pcoords[0]=0; + pcoords[1]=0; + pcoords[2]=0.5; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation mid p0p3",myTuples[0]==101.5); + + pcoords[0]=0.5; + pcoords[1]=0.5; + pcoords[2]=0; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation mid p1p2",myTuples[0]==101.5); + + pcoords[0]=0.5; + pcoords[1]=0; + pcoords[2]=0.5; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation mid p1p3",myTuples[0]==102); + + pcoords[0]=0; + pcoords[1]=0.5; + pcoords[2]=0.5; + it->GetCell()->InterpolateTuple(attribute,pcoords,myTuples); + MacroTest(strm,indent,"valid interpolation mid p2p3",myTuples[0]==102.5); + + it->Delete(); + strm<<"InterpolateTuple() end"<NewBoundaryIterator(-1,0); + MacroTest(strm,indent,"empty boundary iterator -1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,0); + MacroTest(strm,indent,"empty boundary iterator 0,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,0); + MacroTest(strm,indent,"empty boundary iterator 1,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,0); + MacroTest(strm,indent,"empty boundary iterator 2,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,0); + MacroTest(strm,indent,"empty boundary iterator 3,false exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,false",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(-1,1); + MacroTest(strm,indent,"empty boundary iterator -1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty boundary iterator -1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(0,1); + MacroTest(strm,indent,"empty boundary iterator 0,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 0,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(1,1); + MacroTest(strm,indent,"empty boundary iterator 1,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 1,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(2,1); + MacroTest(strm,indent,"empty boundary iterator 2,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 2,true",it->IsAtEnd()); + it->Delete(); + it=ds->NewBoundaryIterator(3,1); + MacroTest(strm,indent,"empty boundary iterator 3,true exists",it!=0); + it->Begin(); + MacroTest(strm,indent,"empty cell iterator 3,true",it->IsAtEnd()); + it->Delete(); + strm<<"NewBoundaryIterator() end"<Delete(); + + strm<<"Delete the vtkBridgeDataSet"<Delete(); + strm<<"vtkBridgeDataSet deleted"<Delete(); + strm<<"vtkUnstructuredGrid deleted"< + +vtkCxxRevisionMacro(vtkBridgeAttribute, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkBridgeAttribute); + +void vtkBridgeAttribute::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +// Description: +// Name of the attribute. (e.g. "velocity") +// \post result_may_not_exist: result!=0 || result==0 +const char *vtkBridgeAttribute::GetName() +{ + return this->Data->GetArray(this->AttributeNumber)->GetName(); +} + +//----------------------------------------------------------------------------- +// Description: +// Dimension of the attribute. (1 for scalar, 3 for velocity) +// \post positive_result: result>=0 +int vtkBridgeAttribute::GetNumberOfComponents() +{ + int result=this->Data->GetArray(this->AttributeNumber)->GetNumberOfComponents(); + assert("post: positive_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Is the attribute centered either on points, cells or boundaries? +// \post valid_result: (result==vtkPointCentered) || +// (result==vtkCellCentered) || (result==vtkBoundaryCentered) +int vtkBridgeAttribute::GetCentering() +{ + int result; + if(this->Pd!=0) + { + result=vtkPointCentered; + } + else + { + result=vtkCellCentered; + } + assert("post: valid_result" && (result==vtkPointCentered) || (result==vtkCellCentered) || (result==vtkBoundaryCentered)); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Type of the attribute: scalar, vector, normal, texture coordinate, tensor +// \post valid_result: (result==vtkDataSetAttributes::SCALARS) +// ||(result==vtkDataSetAttributes::VECTORS) +// ||(result==vtkDataSetAttributes::NORMALS) +// ||(result==vtkDataSetAttributes::TCOORDS) +// ||(result==vtkDataSetAttributes::TENSORS) +int vtkBridgeAttribute::GetType() +{ + int result=this->Data->IsArrayAnAttribute(this->AttributeNumber); + if(result==-1) + { + switch(this->GetNumberOfComponents()) + { + case 1: + result=vtkDataSetAttributes::SCALARS; + break; + case 3: + result=vtkDataSetAttributes::VECTORS; + break; + case 9: + result=vtkDataSetAttributes::TENSORS; + break; + default: + assert("check: unknown attribute type" && 0); + break; + } + } + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Type of the components of the attribute: int, float, double +// \post valid_result: (result==VTK_BIT) ||(result==VTK_CHAR) +// ||(result==VTK_UNSIGNED_CHAR) ||(result==VTK_SHORT) +// ||(result==VTK_UNSIGNED_SHORT)||(result==VTK_INT) +// ||(result==VTK_UNSIGNED_INT) ||(result==VTK_LONG) +// ||(result==VTK_UNSIGNED_LONG) ||(result==VTK_FLOAT) +// ||(result==VTK_DOUBLE) ||(result==VTK_ID_TYPE) +int vtkBridgeAttribute::GetComponentType() +{ + return this->Data->GetArray(this->AttributeNumber)->GetDataType(); +} + +//----------------------------------------------------------------------------- +// Description: +// Number of tuples. +// \post valid_result: result>=0 +vtkIdType vtkBridgeAttribute::GetSize() +{ + vtkIdType result=this->Data->GetArray(this->AttributeNumber)->GetNumberOfTuples(); + assert("post: valid_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Size in kilobytes taken by the attribute. +unsigned long vtkBridgeAttribute::GetActualMemorySize() +{ + return this->Data->GetArray(this->AttributeNumber)->GetActualMemorySize(); +} + +//----------------------------------------------------------------------------- +// Description: +// Range of the attribute component `component'. It returns double, even if +// GetType()==VTK_INT. +// NOT THREAD SAFE +// \pre valid_component: (component>=-1)&&(component=-1)&&(componentGetNumberOfComponents())); + double *result=this->Data->GetArray(this->AttributeNumber)->GetRange(component); + assert("post: result_exists" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Range of the attribute component `component'. +// THREAD SAFE +// \pre valid_component: (component>=-1)&&(component=-1)&&(componentGetNumberOfComponents())); + this->Data->GetArray(this->AttributeNumber)->GetRange(range,component); +} + +//----------------------------------------------------------------------------- +// Description: +// Return the maximum euclidean norm for the tuples. +// \post positive_result: result>=0 +double vtkBridgeAttribute::GetMaxNorm() +{ + double result=this->Data->GetArray(this->AttributeNumber)->GetMaxNorm(); + assert("post: positive_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Attribute at all points of cell `c'. +// \pre c_exists: c!=0 +// \pre c_valid: !c->IsAtEnd() +// \post result_exists: result!=0 +// \post valid_result: sizeof(result)==GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() +double *vtkBridgeAttribute::GetTuple(vtkGenericAdaptorCell *c) +{ + assert("pre: c_exists" && c!=0); + + this->AllocateInternalTuple(c->GetNumberOfPoints()*this->GetNumberOfComponents()); + this->GetTuple(c,this->InternalTuple); + + assert("post: result_exists" && this->InternalTuple!=0); + return this->InternalTuple; +} + +//----------------------------------------------------------------------------- +// Description: +// Put attribute at all points of cell `c' in `tuple'. +// \pre c_exists: c!=0 +// \pre c_valid: !c->IsAtEnd() +// \pre tuple_exists: tuple!=0 +// \pre valid_tuple: sizeof(tuple)>=GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() +void vtkBridgeAttribute::GetTuple(vtkGenericAdaptorCell *c, double *tuple) +{ + assert("pre: c_exists" && c!=0); + assert("pre: tuple_exists" && tuple!=0); + + double *p=tuple; + int i; + int j; + int size; + vtkBridgeCell *c2=static_cast(c); + + + if(this->Pd!=0) + { + i=0; + size=c2->GetNumberOfPoints(); + while(iCell->GetPointId(i); + this->Data->GetArray(this->AttributeNumber)->GetTuple(j,p); + ++i; + p=p+this->GetNumberOfComponents(); + } + } + else + { + this->Data->GetArray(this->AttributeNumber)->GetTuple(c2->GetId(),tuple); + // duplicate: + size=c2->GetNumberOfPoints(); + i=1; + p=p+this->GetNumberOfComponents(); + while(iGetNumberOfComponents()); + p=p+this->GetNumberOfComponents(); + ++i; + } + } +} + +//----------------------------------------------------------------------------- +// Description: +// Attribute at all points of cell `c'. +// \pre c_exists: c!=0 +// \pre c_valid: !c->IsAtEnd() +// \post result_exists: result!=0 +// \post valid_result: sizeof(result)==GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() +double *vtkBridgeAttribute::GetTuple(vtkGenericCellIterator *c) +{ + assert("pre: c_exists" && c!=0); + assert("pre: c_valid" && !c->IsAtEnd()); + + return this->GetTuple(c->GetCell()); +} + +//----------------------------------------------------------------------------- +// Description: +// Put attribute at all points of cell `c' in `tuple'. +// \pre c_exists: c!=0 +// \pre c_valid: !c->IsAtEnd() +// \pre tuple_exists: tuple!=0 +// \pre valid_tuple: sizeof(tuple)>=GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() +void vtkBridgeAttribute::GetTuple(vtkGenericCellIterator *c, double *tuple) +{ + assert("pre: c_exists" && c!=0); + assert("pre: c_valid" && !c->IsAtEnd()); + assert("pre: tuple_exists" && tuple!=0); + + this->GetTuple(c->GetCell(),tuple); +} + +//----------------------------------------------------------------------------- +// Description: +// Value of the attribute at position `p'. +// \pre p_exists: p!=0 +// \pre p_valid: !p->IsAtEnd() +// \post result_exists: result!=0 +// \post valid_result_size: sizeof(result)==GetNumberOfComponents() +double *vtkBridgeAttribute::GetTuple(vtkGenericPointIterator *p) +{ + assert("pre: p_exists" && p!=0); + assert("pre: p_valid" && !p->IsAtEnd()); + + this->AllocateInternalTuple(this->GetNumberOfComponents()); + + this->Data->GetArray(this->AttributeNumber)->GetTuple(p->GetId(),this->InternalTuple); + + assert("post: result_exists" && this->InternalTuple!=0); + return this->InternalTuple; +} + +//----------------------------------------------------------------------------- +// Description: +// Put the value of the attribute at position `p' into `tuple'. +// \pre p_exists: p!=0 +// \pre p_valid: !p->IsAtEnd() +// \pre tuple_exists: tuple!=0 +// \pre valid_tuple_size: sizeof(tuple)>=GetNumberOfComponents() +void vtkBridgeAttribute::GetTuple(vtkGenericPointIterator *p, double *tuple) +{ + assert("pre: p_exists" && p!=0); + assert("pre: p_valid" && !p->IsAtEnd()); + assert("pre: tuple_exists" && tuple!=0); + this->Data->GetArray(this->AttributeNumber)->GetTuple(p->GetId(),tuple); +} + +//----------------------------------------------------------------------------- +// Description: +// Put component `i' of the attribute at all points of cell `c' in `values'. +// \pre valid_component: (i>=0) && (iIsAtEnd() +// \pre values_exist: values!=0 +// \pre valid_values: sizeof(values)>=c->GetCell()->GetNumberOfPoints() +void vtkBridgeAttribute::GetComponent(int i,vtkGenericCellIterator *c, double *values) +{ + assert("pre: c_exists" && c!=0); + assert("pre: c_valid" && !c->IsAtEnd()); + + int j; + int id; + int size; + vtkBridgeCellIterator *c2=static_cast(c); + + if(this->Pd!=0) + { + j=0; + size=c2->GetCell()->GetNumberOfPoints(); + while(j(c2->GetCell())->Cell->GetPointId(j); + values[j]=this->Data->GetArray(this->AttributeNumber)->GetComponent(id,i); + ++j; + } + } + else + { + values[0]=this->Data->GetArray(this->AttributeNumber)->GetComponent(c2->GetCell()->GetId(),i); + // duplicate: + size=c2->GetCell()->GetNumberOfPoints(); + j=1; + while(j=0) && (iIsAtEnd() +double vtkBridgeAttribute::GetComponent(int i,vtkGenericPointIterator *p) +{ + assert("pre: p_exists" && p!=0); + assert("pre: p_valid" && !p->IsAtEnd()); + // Only relevant if GetCentering()==vtkCenteringPoint? + return this->Data->GetArray(this->AttributeNumber)->GetComponent(p->GetId(),i); +} + +//----------------------------------------------------------------------------- +// Description: +// Recursive duplication of `other' in `this'. +// \pre other_exists: other!=0 +// \pre not_self: other!=this +void vtkBridgeAttribute::DeepCopy(vtkGenericAttribute *other) +{ + assert("pre: other_exists" && other!=0); + assert("pre: not_self" && other!=this); + vtkBridgeAttribute *o=static_cast(other); + + vtkSetObjectBodyMacro(Pd,vtkPointData,o->Pd); + vtkSetObjectBodyMacro(Cd,vtkCellData,o->Cd); + this->Data=o->Data; + this->AttributeNumber=o->AttributeNumber; + this->AllocateInternalTuple(this->GetNumberOfComponents()); +} + +//----------------------------------------------------------------------------- +// Description: +// Update `this' using fields of `other'. +// \pre other_exists: other!=0 +// \pre not_self: other!=this +void vtkBridgeAttribute::ShallowCopy(vtkGenericAttribute *other) +{ + assert("pre: other_exists" && other!=0); + assert("pre: not_self" && other!=this); + vtkBridgeAttribute *o=static_cast(other); + + vtkSetObjectBodyMacro(Pd,vtkPointData,o->Pd); + vtkSetObjectBodyMacro(Cd,vtkCellData,o->Cd); + this->Data=o->Data; + this->AttributeNumber=o->AttributeNumber; + this->AllocateInternalTuple(this->GetNumberOfComponents()); +} + +//----------------------------------------------------------------------------- +// Description: +// Set the current attribute to be centered on points with attribute `i' of +// `d'. +// \pre d_exists: d!=0 +// \pre valid_range: (i>=0) && (iGetNumberOfArrays()) +void vtkBridgeAttribute::InitWithPointData(vtkPointData *d, + int i) +{ + assert("pre: d_exists" && d!=0); + assert("pre: valid_range" && (i>=0) && (iGetNumberOfArrays())); + vtkSetObjectBodyMacro(Cd,vtkCellData,0); + vtkSetObjectBodyMacro(Pd,vtkPointData,d); + this->Data=d; + this->AttributeNumber=i; + this->AllocateInternalTuple(this->GetNumberOfComponents()); +} + +//----------------------------------------------------------------------------- +// Description: +// Set the current attribute to be centered on cells with attribute `i' of `d'. +// \pre d_exists: d!=0 +// \pre valid_range: (i>=0) && (iGetNumberOfArrays()) +void vtkBridgeAttribute::InitWithCellData(vtkCellData *d, + int i) +{ + assert("pre: d_exists" && d!=0); + assert("pre: valid_range" && (i>=0) && (iGetNumberOfArrays())); + vtkSetObjectBodyMacro(Pd,vtkPointData,0); + vtkSetObjectBodyMacro(Cd,vtkCellData,d); + this->Data=d; + this->AttributeNumber=i; + this->AllocateInternalTuple(this->GetNumberOfComponents()); +} + +//----------------------------------------------------------------------------- +// Description: +// Default constructor: empty attribute, not valid +vtkBridgeAttribute::vtkBridgeAttribute() +{ + this->Pd=0; + this->Cd=0; + this->Data=0; + this->AttributeNumber=0; + this->InternalTuple=0; + this->InternalTupleCapacity=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Destructor. +vtkBridgeAttribute::~vtkBridgeAttribute() +{ + if(this->Pd!=0) + { + this->Pd->Delete(); + } + else + { + if(this->Cd!=0) + { + this->Cd->Delete(); + } + } + if(this->InternalTuple!=0) + { + delete[] this->InternalTuple; + } +} + +//----------------------------------------------------------------------------- +// Description: +// If size>InternalTupleCapacity, allocate enough memory. +// \pre positive_size: size>0 +void vtkBridgeAttribute::AllocateInternalTuple(int size) +{ + // size=this->GetNumberOfComponents() + assert("pre: positive_size" && size>0); + + if(this->InternalTuple==0) + { + this->InternalTupleCapacity = size; + this->InternalTuple = new double[this->InternalTupleCapacity]; + } + else + { + if(InternalTupleCapacityInternalTupleCapacity = size; + delete [] this->InternalTuple; + this->InternalTuple = new double[this->InternalTupleCapacity]; + } + } +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeAttribute.h b/GenericFiltering/Testing/Cxx/vtkBridgeAttribute.h new file mode 100644 index 0000000..fa4efea --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeAttribute.h @@ -0,0 +1,225 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeAttribute.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeAttribute - Implementation of vtkGenericAttribute. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericAttribute, vtkBridgeDataSet + + +#ifndef __vtkBridgeAttribute_h +#define __vtkBridgeAttribute_h + +#include "vtkBridgeExport.h" +#include "vtkGenericAttribute.h" + +class vtkPointData; +class vtkCellData; +class vtkDataSetAttributes; + +class VTK_BRIDGE_EXPORT vtkBridgeAttribute : public vtkGenericAttribute +{ + public: + static vtkBridgeAttribute *New(); + vtkTypeRevisionMacro(vtkBridgeAttribute,vtkGenericAttribute); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Name of the attribute. (e.g. "velocity") + // \post result_may_not_exist: result!=0 || result==0 + const char *GetName(); + + // Description: + // Dimension of the attribute. (1 for scalar, 3 for velocity) + // \post positive_result: result>=0 + int GetNumberOfComponents(); + + // Description: + // Is the attribute centered either on points, cells or boundaries? + // \post valid_result: (result==vtkCenteringPoints) || + // (result==vtkCenteringCells) || (result==vtkCenteringBoundaries) + int GetCentering(); + + // Description: + // Type of the attribute: scalar, vector, normal, texture coordinate, tensor + // \post valid_result: (result==vtkDataSetAttributes::SCALARS) + // ||(result==vtkDataSetAttributes::VECTORS) + // ||(result==vtkDataSetAttributes::NORMALS) + // ||(result==vtkDataSetAttributes::TCOORDS) + // ||(result==vtkDataSetAttributes::TENSORS) + int GetType(); + + // Description: + // Type of the components of the attribute: int, float, double + // \post valid_result: (result==VTK_BIT) ||(result==VTK_CHAR) + // ||(result==VTK_UNSIGNED_CHAR) ||(result==VTK_SHORT) + // ||(result==VTK_UNSIGNED_SHORT)||(result==VTK_INT) + // ||(result==VTK_UNSIGNED_INT) ||(result==VTK_LONG) + // ||(result==VTK_UNSIGNED_LONG) ||(result==VTK_FLOAT) + // ||(result==VTK_DOUBLE) ||(result==VTK_ID_TYPE) + int GetComponentType(); + + // Description: + // Number of tuples. + // \post valid_result: result>=0 + vtkIdType GetSize(); + + // Description: + // Size in kilobytes taken by the attribute. + unsigned long GetActualMemorySize(); + + // Description: + // Range of the attribute component `component'. It returns double, even if + // GetType()==VTK_INT. + // NOT THREAD SAFE + // \pre valid_component: (component>=0)&&(component=0)&&(component=0 + double GetMaxNorm(); + + // Description: + // Attribute at all points of cell `c'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \post result_exists: result!=0 + // \post valid_result: sizeof(result)==GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + virtual double *GetTuple(vtkGenericAdaptorCell *c); + + // Description: + // Put attribute at all points of cell `c' in `tuple'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \pre tuple_exists: tuple!=0 + // \pre valid_tuple: sizeof(tuple)>=GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + virtual void GetTuple(vtkGenericAdaptorCell *c, double *tuple); + + // Description: + // Attribute at all points of cell `c'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \post result_exists: result!=0 + // \post valid_result: sizeof(result)==GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + double *GetTuple(vtkGenericCellIterator *c); + + // Description: + // Put attribute at all points of cell `c' in `tuple'. + // \pre c_exists: c!=0 + // \pre c_valid: !c->IsAtEnd() + // \pre tuple_exists: tuple!=0 + // \pre valid_tuple: sizeof(tuple)>=GetNumberOfComponents()*c->GetCell()->GetNumberOfPoints() + void GetTuple(vtkGenericCellIterator *c, double *tuple); + + // Description: + // Value of the attribute at position `p'. + // \pre p_exists: p!=0 + // \pre p_valid: !p->IsAtEnd() + // \post result_exists: result!=0 + // \post valid_result_size: sizeof(result)==GetNumberOfComponents() + double *GetTuple(vtkGenericPointIterator *p); + + // Description: + // Put the value of the attribute at position `p' into `tuple'. + // \pre p_exists: p!=0 + // \pre p_valid: !p->IsAtEnd() + // \pre tuple_exists: tuple!=0 + // \pre valid_tuple_size: sizeof(tuple)>=GetNumberOfComponents() + void GetTuple(vtkGenericPointIterator *p, double *tuple); + + // Description: + // Put component `i' of the attribute at all points of cell `c' in `values'. + // \pre valid_component: (i>=0) && (iIsAtEnd() + // \pre values_exist: values!=0 + // \pre valid_values: sizeof(values)>=c->GetCell()->GetNumberOfPoints() + void GetComponent(int i,vtkGenericCellIterator *c, double *values); + + // Description: + // Value of the component `i' of the attribute at position `p'. + // \pre valid_component: (i>=0) && (iIsAtEnd() + double GetComponent(int i,vtkGenericPointIterator *p); + + // Description: + // Recursive duplication of `other' in `this'. + // \pre other_exists: other!=0 + // \pre not_self: other!=this + void DeepCopy(vtkGenericAttribute *other); + + // Description: + // Update `this' using fields of `other'. + // \pre other_exists: other!=0 + // \pre not_self: other!=this + void ShallowCopy(vtkGenericAttribute *other); + + // Description: + // Set the current attribute to be centered on points with attribute `i' of + // `d'. + // \pre d_exists: d!=0 + // \pre valid_range: (i>=0) && (iGetNumberOfArrays()) + void InitWithPointData(vtkPointData *d, + int i); + + // Description: + // Set the current attribute to be centered on cells with attribute `i' of + // `d'. + // \pre d_exists: d!=0 + // \pre valid_range: (i>=0) && (iGetNumberOfArrays()) + void InitWithCellData(vtkCellData *d, + int i); + +protected: + // Description: + // Default constructor: empty attribute, not valid + vtkBridgeAttribute(); + // Description: + // Destructor. + virtual ~vtkBridgeAttribute(); + + // Description: + // If size>InternalTupleCapacity, allocate enough memory. + // \pre positive_size: size>0 + void AllocateInternalTuple(int size); + + friend class vtkBridgeCell; + + // only one of them is non-null at a time. + vtkPointData *Pd; + vtkCellData *Cd; + vtkDataSetAttributes *Data; // always not-null, equal to either on Pd or Cd + int AttributeNumber; + + double *InternalTuple; // used by vtkBridgeCell + int InternalTupleCapacity; + +private: + vtkBridgeAttribute(const vtkBridgeAttribute&); // Not implemented + void operator=(const vtkBridgeAttribute&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCell.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeCell.cxx new file mode 100644 index 0000000..5600a30 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCell.cxx @@ -0,0 +1,1483 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCell - Implementation of vtkGenericAdaptorCell +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericAdaptorCell, vtkBridgeDataSet + + +#include "vtkBridgeCell.h" + +#include + +#include "vtkBridgeCellIterator.h" +#include "vtkObjectFactory.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkBridgeAttribute.h" +#include "vtkContourValues.h" +#include "vtkPoints.h" +#include "vtkCellArray.h" +#include "vtkDataSetAttributes.h" +#include "vtkBridgePointIterator.h" + +// All that stuff is for InterpolationFunction() + +#include "vtkEmptyCell.h" +#include "vtkVertex.h" +#include "vtkPolyVertex.h" +#include "vtkLine.h" +#include "vtkPolyLine.h" +#include "vtkTriangle.h" +#include "vtkTriangleStrip.h" +#include "vtkQuad.h" +#include "vtkPixel.h" +#include "vtkPolygon.h" +#include "vtkTetra.h" +#include "vtkHexahedron.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" +#include "vtkPyramid.h" + +#include "vtkQuadraticEdge.h" +#include "vtkQuadraticTriangle.h" +#include "vtkQuadraticQuad.h" +#include "vtkQuadraticTetra.h" +#include "vtkQuadraticHexahedron.h" +#include "vtkConvexPointSet.h" + +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) +# include "vtkPentagonalPrism.h" +# include "vtkHexagonalPrism.h" +# include "vtkQuadraticWedge.h" +# include "vtkQuadraticPyramid.h" +#endif + + +vtkCxxRevisionMacro(vtkBridgeCell, "$Revision: 1.13 $"); + +vtkStandardNewMacro(vtkBridgeCell); + +//----------------------------------------------------------------------------- +void vtkBridgeCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +// Description: +// Unique identification number of the cell over the whole +// data set. This unique key may not be contiguous. +vtkIdType vtkBridgeCell::GetId() +{ + return this->Id; +} + +//----------------------------------------------------------------------------- +// Description: +// Does `this' a cell of a dataset? (otherwise, it is a boundary cell) +int vtkBridgeCell::IsInDataSet() +{ + return this->BoolIsInDataSet; +} + +//----------------------------------------------------------------------------- +// Description: +// Type of the current cell. +// \post (result==VTK_HIGHER_ORDER_EDGE)|| +// (result==VTK_HIGHER_ORDER_TRIANGLE)|| +// (result==VTK_HIGHER_ORDER_TETRAHEDRON) +int vtkBridgeCell::GetType() +{ + int result=0; + switch(this->Cell->GetCellType()) + { + case VTK_TRIANGLE: + case VTK_QUADRATIC_TRIANGLE: + result=VTK_HIGHER_ORDER_TRIANGLE; + break; + case VTK_QUAD: + case VTK_QUADRATIC_QUAD: + result=VTK_HIGHER_ORDER_QUAD; + break; + case VTK_TETRA: + case VTK_QUADRATIC_TETRA: + result=VTK_HIGHER_ORDER_TETRAHEDRON; + break; + case VTK_VOXEL: + case VTK_HEXAHEDRON: + case VTK_QUADRATIC_HEXAHEDRON: + result=VTK_HIGHER_ORDER_HEXAHEDRON; + break; + case VTK_WEDGE: + case VTK_QUADRATIC_WEDGE: + result=VTK_HIGHER_ORDER_WEDGE; + break; + case VTK_PYRAMID: + case VTK_QUADRATIC_PYRAMID: + result=VTK_HIGHER_ORDER_PYRAMID; + break; +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) + case VTK_PENTAGONAL_PRISM: + assert("check: TODO" && 0); + break; + case VTK_HEXAGONAL_PRISM: + assert("check: TODO" && 0); + break; +#endif + default: + assert("check: impossible case" && 0); + break; + } + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Topological dimension of the current cell. +// \post valid_result: result>=0 && result<=3 +int vtkBridgeCell::GetDimension() +{ + int result=this->Cell->GetCellDimension(); + assert("post: valid_result" && (result>=0)&&(result<=3)); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Interpolation order of the geometry. +// \post positive_result: result>=0 +int vtkBridgeCell::GetGeometryOrder() +{ + int result; + if(this->Cell->IsLinear()) + { + result=1; + } + else + { + result=2; // GetOrder() is missing in vtkCell... + } + assert("post: positive_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Does the cell have no higher-order interpolation for geometry? +// \post definition: result==(GetGeometryOrder()==1) +int vtkBridgeCell::IsGeometryLinear() +{ + int result=this->Cell->IsLinear(); + assert("post: definition" && result==(GetGeometryOrder()==1)); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Interpolation order of attribute `a' on the cell (may differ by cell). +// \pre a_exists: a!=0 +// \post positive_result: result>=0 +int vtkBridgeCell::GetAttributeOrder(vtkGenericAttribute *vtkNotUsed(a)) +{ + int result=this->GetGeometryOrder(); + assert("post: positive_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Does the attribute `a' have no higher-order interpolation for the cell? +// \pre a_exists: a!=0 +// \post definition: result==(GetAttributeOrder()==1) +int vtkBridgeCell::IsAttributeLinear(vtkGenericAttribute *a) +{ + (void)a; // The attribute order is the order of the geometry. + int result=this->IsGeometryLinear(); + assert("post: definition" && result==(GetAttributeOrder(a)==1)); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Is the cell primary (i.e. not composite) ? +int vtkBridgeCell::IsPrimary() +{ + return this->Cell->IsPrimaryCell(); +} + +//----------------------------------------------------------------------------- +// Description: +// Number of points that compose the cell. +// \post positive_result: result>=0 +int vtkBridgeCell::GetNumberOfPoints() +{ + int result=this->Cell->GetNumberOfPoints(); + assert("post: positive_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Number of boundaries of dimension `dim' (or all dimensions less than +// GetDimension() if -1) of the cell. +// \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dim=0 +int vtkBridgeCell::GetNumberOfBoundaries(int dim) +{ + assert("pre: valid_dim_range" && ((dim==-1) ||((dim>=0)&&(dimGetDimension()>1) ) + { + result += this->Cell->GetNumberOfPoints(); + if(!this->Cell->IsLinear()) + { // Old cell API treats mid-edge nodes as vertices; subtract those out: + result -= this->Cell->GetNumberOfEdges(); + } + } + if( ((dim==-1) && (this->GetDimension()>1)) || (dim==1) ) + { + result=result+this->Cell->GetNumberOfEdges(); + } + if( ((dim==-1) && (this->GetDimension()>2)) || (dim==2) ) + { + result=result+this->Cell->GetNumberOfFaces(); + } + + assert("post: positive_result" && result>=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Accumulated number of DOF nodes of the current cell. A DOF node is +// a component of cell with a given topological dimension. e.g.: a triangle +// has 7 DOF: 1 face, 3 edges, 3 vertices. An hexahedron has 27 DOF: +// 1 region, 6 faces, 12 edges, 8 vertices. +// \post valid_result: result==GetNumberOfBoundaries(-1)+1 +int vtkBridgeCell::GetNumberOfDOFNodes() +{ + return this->GetNumberOfBoundaries(-1)+1; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the points of cell into `it'. +// \pre it_exists: it!=0 +void vtkBridgeCell::GetPointIterator(vtkGenericPointIterator *it) +{ + assert("pre: it_exists" && it!=0); + static_cast(it)->InitWithCell(this); +} + +//----------------------------------------------------------------------------- +// Description: +// Create an empty cell iterator. +// \post result_exists: result!=0 +vtkGenericCellIterator *vtkBridgeCell::NewCellIterator() +{ + vtkGenericCellIterator *result=vtkBridgeCellIterator::New(); + assert("post: result_exists" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Return in `boundaries' the cells of dimension `dim' (or all dimensions +// less than GetDimension() if -1) that are part of the boundary of the cell. +// \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dim=0)&&(dim(boundaries)->InitWithCellBoundaries(this,dim); +} + +//----------------------------------------------------------------------------- +// Description: +// Number of cells (dimension>boundary->GetDimension()) of the dataset +// that share the boundary `boundary' of `this'. +// `this' IS NOT INCLUDED. +// \pre boundary_exists: boundary!=0 +// \pre real_boundary: !boundary->IsInDataSet() +// \pre cell_of_the_dataset: IsInDataSet() +// \pre boundary: HasBoundary(boundary) +// \post positive_result: result>=0 +int vtkBridgeCell::CountNeighbors(vtkGenericAdaptorCell *boundary) +{ + assert("pre: boundary_exists" && boundary!=0); + assert("pre: real_boundary" && !boundary->IsInDataSet()); + assert("pre: cell_of_the_dataset" && IsInDataSet()); + + vtkIdList *cells=vtkIdList::New(); + vtkBridgeCell *b=static_cast(boundary); + vtkIdList *pts=b->Cell->GetPointIds(); + this->DataSet->Implementation->GetCellNeighbors(this->Id,pts,cells); + int result=cells->GetNumberOfIds(); + cells->Delete(); + + assert("post: positive_result" && result>=0); + + return result; +} + +//----------------------------------------------------------------------------- +// \pre large_enough: GetDimension()>=2 +// \pre right_size: sizeof(sharing)==GetNumberOfBoundaries(1); +void vtkBridgeCell::CountEdgeNeighbors(int *sharing) +{ + assert("pre: large_enough" && this->GetDimension()>=2); + + vtkIdType c=this->Cell->GetNumberOfEdges(); + vtkIdList *cells=vtkIdList::New(); + vtkIdType i=0; + vtkCell *edge; + vtkIdList *pts; + + while(iCell->GetEdge(i); // edge is deleted automatically by this->Cell + pts=edge->GetPointIds(); + this->DataSet->Implementation->GetCellNeighbors(this->Id,pts,cells); + sharing[i]=cells->GetNumberOfIds(); + ++i; + } + cells->Delete(); +} + +//----------------------------------------------------------------------------- +// Description: +// Put into `neighbors' the cells (dimension>boundary->GetDimension()) +// of the dataset that share the boundary `boundary' of `this'. +// `this' IS NOT INCLUDED. +// \pre boundary_exists: boundary!=0 +// \pre real_boundary: !boundary->IsInDataSet() +// \pre cell_of_the_dataset: IsInDataSet() +// \pre boundary: HasBoundary(boundary) +// \pre neighbors_exist: neighbors!=0 +void vtkBridgeCell::GetNeighbors(vtkGenericAdaptorCell *boundary, + vtkGenericCellIterator *neighbors) +{ + assert("pre: boundary_exists" && boundary!=0); + assert("pre: real_boundary" && !boundary->IsInDataSet()); + assert("pre: cell_of_the_dataset" && IsInDataSet()); + assert("pre: neighbors_exist" && neighbors!=0); + + vtkIdList *cells=vtkIdList::New(); + vtkIdList *pts=static_cast(boundary)->Cell->GetPointIds(); + this->DataSet->Implementation->GetCellNeighbors(this->Id,pts,cells); + + static_cast(neighbors)->InitWithCells(cells,this->DataSet); + + cells->Delete(); +} + +//----------------------------------------------------------------------------- +// Description: +// Compute the closest boundary of the current sub-cell `subId' for point +// `pcoord' (in parametric coordinates) in `boundary', and return whether +// the point is inside the cell or not. `boundary' is of dimension +// GetDimension()-1. +// \pre positive_subId: subId>=0 +int vtkBridgeCell::FindClosestBoundary(int subId, + double pcoords[3], + vtkGenericCellIterator* &boundary) +{ + assert("pre: positive_subId" && subId>=0); + + vtkIdList *pts=vtkIdList::New(); + int result=this->Cell->CellBoundary(subId,pcoords,pts); + static_cast(boundary)->InitWithPoints(this->Cell->Points,pts,this->GetDimension()-1,0); // id of the boundary always 0? + pts->Delete(); + + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Is `x' inside the current cell? It also evaluate parametric coordinates +// `pcoords', sub-cell id `subId' (0 means primary cell), distance squared +// to the sub-cell in `dist2' and closest corner point `closestPoint'. +// `dist2' and `closestPoint' are not evaluated if `closestPoint'==0. +// If a numerical error occurred, -1 is returned and all other results +// should be ignored. +// \post valid_result: result==-1 || result==0 || result==1 +// \post positive_distance: result!=-1 implies (closestPoint!=0 implies +// dist2>=0) +int vtkBridgeCell::EvaluatePosition(double x[3], + double *closestPoint, + int &subId, + double pcoords[3], + double &dist2) +{ + this->AllocateWeights(); + int result=this->Cell->EvaluatePosition(x,closestPoint,subId,pcoords,dist2, + this->Weights); + + if(result) + { + // clamp pcoords + int i=0; + while(i<3) + { + if(pcoords[i]<0) + { + pcoords[i]=0; + } + else if(pcoords[i]>1) + { + pcoords[i]=1; + } + ++i; + } + } + + assert("post: valid_result" && result==-1 || result==0 || result==1); + assert("post: positive_distance" && (!(result!=-1) || (!(closestPoint!=0)||dist2>=0))); // A=>B: !A || B + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Determine global coordinates `x' from sub-cell `subId' and parametric +// coordinates `pcoords' in the cell. +// \pre positive_subId: subId>=0 +// \pre clamped_pcoords: (0<=pcoords[0])&&(pcoords[0]<=1)&&(0<=pcoords[1]) +// &&(pcoords[1]<=1)&&(0<=pcoords[2])&&(pcoords[2]<=1) +void vtkBridgeCell::EvaluateLocation(int subId, + double pcoords[3], + double x[3]) +{ + assert("pre: positive_subId" && subId>=0); + assert("pre: clamped_pcoords" && (0<=pcoords[0])&&(pcoords[0]<=1) + &&(0<=pcoords[1])&&(pcoords[1]<=1)&&(0<=pcoords[2]) + &&(pcoords[2]<=1)); + + this->AllocateWeights(); + this->Cell->EvaluateLocation(subId,pcoords,x,this->Weights); +} + +//----------------------------------------------------------------------------- +// Description: +// Interpolate the attribute `a' at local position `pcoords' of the cell into +// `val'. +// \pre a_exists: a!=0 +// \pre a_is_point_centered: a->GetCentering()==vtkPointCentered +// \pre clamped_point: pcoords[0]>=0 && pcoords[0]<=1 && pcoords[1]>=0 && +// pcoords[1]<=1 && pcoords[2]>=0 && pcoords[2]<=1 +// \pre val_exists: val!=0 +// \pre valid_size: sizeof(val)==a->GetNumberOfComponents() +void vtkBridgeCell::InterpolateTuple(vtkGenericAttribute *a, double pcoords[3], + double *val) +{ + assert("pre: a_exists" && a!=0); + assert("pre: a_is_point_centered" && a->GetCentering()==vtkPointCentered); + assert("pre: clamped_point" && (pcoords[0]>=0 && pcoords[0]<=1 + && pcoords[1]>=0 && pcoords[1]<=1 && pcoords[2]>=0 + && pcoords[2]<=1)); + assert("pre: val_exists" && val!=0); + + vtkBridgeAttribute *ba=static_cast(a); + + int pt; + int component; + int ptCount; + int componentCount; + + componentCount=a->GetNumberOfComponents(); + ptCount=this->GetNumberOfPoints(); + + if(a->GetCentering()==vtkPointCentered) + { + this->AllocateWeights(); + this->InterpolationFunctions(pcoords); + + pt=0; + component=0; + while(componentData->GetArray(ba->AttributeNumber)->GetTuple(this->Cell->GetPointId(pt),ba->InternalTuple); + component=0; + while(componentInternalTuple[component]*this->Weights[pt]; + ++component; + } + ++pt; + } + } + else // cell centered + { + // not need to interpolate + ba->Data->GetArray(ba->AttributeNumber)->GetTuple(this->GetId(),val); + } +} + +//----------------------------------------------------------------------------- +// Description: +// Interpolate the whole collection of attributes `c' at local position +// `pcoords' of the cell into `val'. Only point centered attributes are +// taken into account. +// \pre c_exists: c!=0 +// \pre clamped_point: pcoords[0]>=0 && pcoords[0]<=1 && pcoords[1]>=0 && +// pcoords[1]<=1 && pcoords[2]>=0 && pcoords[2]<=1 +// \pre val_exists: val!=0 +// \pre valid_size: sizeof(val)==c->GetNumberOfPointCenteredComponents() +void vtkBridgeCell::InterpolateTuple(vtkGenericAttributeCollection *c, + double pcoords[3], + double *val) +{ + assert("pre: c_exists" && c!=0); + assert("pre: clamped_point" && (pcoords[0]>=0 && pcoords[0]<=1 + && pcoords[1]>=0 && pcoords[1]<=1 && pcoords[2]>=0 + && pcoords[2]<=1)); + assert("pre: val_exists" && val!=0); + +/// assert("check: used!" && 0); + + double *p=val; + int i=0; + int count=c->GetNumberOfAttributes(); + while(iGetAttribute(i)->GetCentering()==vtkPointCentered) + { + this->InterpolateTuple(c->GetAttribute(i),pcoords,p); + p=p+c->GetAttribute(i)->GetNumberOfComponents(); + } + ++i; + } +} + #if 0 +//----------------------------------------------------------------------------- +// Description: +// Generate a contour (contouring primitives) for each `values' or with +// respect to an implicit function `f'. Contouring +// is performed on the scalar attribute (`attributes->GetActiveAttribute()', +// `attributes->GetActiveComponent()'). +// Contouring interpolates the +// `attributes->GetNumberOfattributesToInterpolate()' attributes +// `attributes->GetAttributesToInterpolate()'. +// `locator', `verts', `lines', `polys', `outPd' and `outCd' are cumulative +// data arrays over cell iterations: they store the result of each call +// to Contour(): +// - `locator' is points list that merges points as they are inserted (i.e., +// prevents duplicates). +// - `verts' is an array of generated vertices +// - `lines' is an array of generated lines +// - `polys' is an array of generated polygons +// - `outPd' is an array of interpolated point data along the edge (if +// not-NULL) +// - `outCd' is an array of copied cell data of the current cell (if +// not-NULL) +// Note: the CopyAllocate() method must be invoked on both the output cell +// and point data. +// +// NOTE: `vtkGenericAttributeCollection *attributes' will be replaced by a +// `vtkInformation'. +// +// \pre values_exist: (values!=0 && f==0) || (values==0 && f!=0) +// \pre attributes_exist: attributes!=0 +// \pre locator_exists: locator!=0 +// \pre verts_exist: verts!=0 +// \pre lines_exist: lines!=0 +// \pre polys_exist: polys!=0 +void vtkBridgeCell::Contour(vtkContourValues *values, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *outPd, + vtkCellData *outCd) +{ + int i=0; + int c=0; + vtkGenericAttribute *a=0; + int comp=0; + + vtkDoubleArray *cellScalars=vtkDoubleArray::New(); + double *buffer=new double[this->GetNumberOfPoints()]; + cellScalars->SetArray(buffer,this->GetNumberOfPoints(),0); + + vtkPointData *inPd=0; + vtkCellData *inCd=0; + +// if(attributes->GetNumberOfAttributesToInterpolate()>0) +// { + inPd=this->DataSet->Implementation->GetPointData(); + inCd=this->DataSet->Implementation->GetCellData(); +// } + + // init cellScalars + a=attributes->GetAttribute(attributes->GetActiveAttribute()); + comp=attributes->GetActiveComponent(); + + a->GetComponent(comp,this->InternalIterator,buffer); + + if(values!=0) // values mode + { + i=0; + c=values->GetNumberOfContours(); + while(iCell->Contour(values->GetValue(i),cellScalars,locator,verts,lines, + polys,inPd,outPd,inCd,this->Id,outCd); + ++i; + } + } + else // implicit function mode + { + // not supported: do nothing, silently ignored. + (void)f; + } + + cellScalars->Delete(); // buffer is deleting automatically +} +#endif +#if 0 +slkvjbdfkjvbdsflkvbj +//----------------------------------------------------------------------------- +// Description: +// Cut (or clip) the current cell with respect to the contour defined by the +// `value' or the implicit function `f' of the scalar attribute +// (`attributes->GetActiveAttribute()',`attributes->GetActiveComponent()'). +// If `f' exists, `value' is not used. The output is the part +// of the current cell which is inside the contour. +// The output is a set of zero, one or more cells of the same topological +// dimension as the current cell. Normally, cell points whose scalar value +// is greater than "value" are considered inside. If `insideOut' is on, this +// is reversed. +// Clipping interpolates the +// `attributes->GetNumberOfattributesToInterpolate()' attributes +// `attributes->GetAttributesToInterpolate()'. +// `locator', `connectivity', `outPd' and `outCd' are cumulative +// data arrays over cell iterations: they store the result of each call +// to Clip(): +// - `locator' is points list that merges points as they are inserted (i.e., +// prevents duplicates). +// - `connectivity' is an array of generated cells +// - `outPd' is an array of interpolated point data along the edge (if +// not-NULL) +// - `outCd' is an array of copied cell data of the current cell (if +// not-NULL) +// Note: the CopyAllocate() method must be invoked on both the output cell +// and point data. +// Also, if the output cell data is +// non-NULL, the cell data from the clipped cell is passed to the generated +// contouring primitives. (Note: the CopyAllocate() method must be invoked on +// both the output cell and point data.) +// +// NOTE: `vtkGenericAttributeCollection *attributes' will be replaced by a +// `vtkInformation'. +// +// \pre attributes_exist: attributes!=0 +// \pre locator_exists: locator!=0 +// \pre connectivity_exists: connectivity!=0 +void vtkBridgeCell::Clip(double value, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *vtkNotUsed(tess), + int insideOut, + vtkPointLocator *locator, + vtkCellArray *connectivity, + vtkPointData *outPd, + vtkCellData *outCd) +{ + vtkGenericAttribute *a=0; + int comp=0; + + vtkDoubleArray *cellScalars=vtkDoubleArray::New(); + double *buffer=new double[this->GetNumberOfPoints()]; + cellScalars->SetArray(buffer,this->GetNumberOfPoints(),0); + + vtkPointData *inPd=0; + vtkCellData *inCd=0; + + if(attributes->GetNumberOfAttributesToInterpolate()>0) + { + inPd=this->DataSet->Implementation->GetPointData(); + inCd=this->DataSet->Implementation->GetCellData(); + } + + // init cellScalars + a=attributes->GetAttribute(attributes->GetActiveAttribute()); + comp=attributes->GetActiveComponent(); + + a->GetComponent(comp,this->InternalIterator,buffer); + + if(f==0) // values mode + { + this->Cell->Clip(value,cellScalars,locator,connectivity,inPd,outPd, + inCd,this->Id,outCd,insideOut); + } + else // implicit function mode + { + // not supported: do nothing, silently ignored. + } + cellScalars->Delete(); // buffer is deleting automatically +} +#endif +//----------------------------------------------------------------------------- +// Description: +// Is there an intersection between the current cell and the ray (`p1',`p2') +// according to a tolerance `tol'? If true, `x' is the global intersection, +// `t' is the parametric coordinate for the line, `pcoords' are the +// parametric coordinates for cell. `subId' is the sub-cell where +// the intersection occurs. +// \pre positive_tolerance: tol>0 +int vtkBridgeCell::IntersectWithLine(double p1[3], + double p2[3], + double tol, + double &t, + double x[3], + double pcoords[3], + int &subId) +{ + return this->Cell->IntersectWithLine(p1,p2,tol,t,x,pcoords,subId); +} + +//----------------------------------------------------------------------------- +// Description: +// Compute derivatives `derivs' of the attribute `attribute' (from its +// values at the corner points of the cell) given sub-cell `subId' (0 means +// primary cell) and parametric coordinates `pcoords'. +// Derivatives are in the x-y-z coordinate directions for each data value. +// \pre positive_subId: subId>=0 +// \pre clamped_pcoords: (0<=pcoords[0])&&(pcoords[0]<=1)&&(0<=pcoords[1]) +// &&(pcoords[1]<=1)&&(0<=pcoords[2])%%(pcoords[2]<=1) +// \pre attribute_exists: attribute!=0 +// \pre derivs_exists: derivs!=0 +// \pre valid_size: sizeof(derivs)>=attribute->GetNumberOfComponents()*3 +void vtkBridgeCell::Derivatives(int subId, + double pcoords[3], + vtkGenericAttribute *attribute, + double *derivs) +{ + double *tuples=new double[attribute->GetNumberOfComponents()*this->GetNumberOfPoints()]; + attribute->GetTuple(this->InternalIterator,tuples); + this->Cell->Derivatives(subId,pcoords,tuples, + attribute->GetNumberOfComponents(),derivs); + delete [] tuples; +} + +//----------------------------------------------------------------------------- +// Description: +// Compute the bounding box of the current cell in `bounds' in global +// coordinates. +// THREAD SAFE +void vtkBridgeCell::GetBounds(double bounds[6]) +{ + this->Cell->GetBounds(bounds); +} + +//----------------------------------------------------------------------------- +// Description: +// Return the bounding box of the current cell in global coordinates. +// NOT THREAD SAFE +// \post result_exists: result!=0 +// \post valid_size: sizeof(result)>=6 +double *vtkBridgeCell::GetBounds() +{ + return this->Cell->GetBounds(); +} + +//----------------------------------------------------------------------------- +// Description: +// Bounding box diagonal squared of the current cell. +// \post positive_result: result>=0 +double vtkBridgeCell::GetLength2() +{ + return this->Cell->GetLength2(); +} + +//----------------------------------------------------------------------------- +// Description: +// Center of the current cell in parametric coordinates `pcoords'. +// If the current cell is a composite, the return value is the sub-cell id +// that the center is in. +// \post valid_result: (result>=0) && (IsPrimary() implies result==0) +int vtkBridgeCell::GetParametricCenter(double pcoords[3]) +{ + return this->Cell->GetParametricCenter(pcoords); +} + +//----------------------------------------------------------------------------- +// Description: +// Distance of the parametric coordinate `pcoords' to the current cell. +// If inside the cell, a distance of zero is returned. This is used during +// picking to get the correct cell picked. (The tolerance will occasionally +// allow cells to be picked who are not really intersected "inside" the +// cell.) +// \post positive_result: result>=0 +double vtkBridgeCell::GetParametricDistance(double pcoords[3]) +{ + return this->Cell->GetParametricDistance(pcoords); +} + +//----------------------------------------------------------------------------- +// Description: +// Return a contiguous array of parametric coordinates of the points defining +// the current cell. In other words, (px,py,pz, px,py,pz, etc..) The +// coordinates are ordered consistent with the definition of the point +// ordering for the cell. Note that 3D parametric coordinates are returned +// no matter what the topological dimension of the cell. It includes the DOF +// nodes. +// \post valid_result_exists: ((IsPrimary()) && (result!=0)) || +// ((!IsPrimary()) && (result==0)) +// result!=0 implies sizeof(result)==GetNumberOfPoints() +double *vtkBridgeCell::GetParametricCoords() +{ + return this->Cell->GetParametricCoords(); +} +#if 0 +//----------------------------------------------------------------------------- +// Description: +// Tessellate the cell if it is not linear or if at least one attribute of +// `attributes' is not linear. The output are linear cells of the same +// dimension than than cell. If the cell is linear and all attributes are +// linear, the output is just a copy of the current cell. +// `points', `cellArray', `pd' and `cd' are cumulative output data arrays +// over cell iterations: they store the result of each call to Tessellate(). +// \pre attributes_exist: attributes!=0 +// \pre points_exist: points!=0 +// \pre cellArray_exists: cellArray!=0 +// \pre pd_exist: pd!=0 +// \pre cd_exists: cd!=0 +void vtkBridgeCell::Tessellate(vtkGenericAttributeCollection *attributes, + vtkPoints *points, vtkCellArray* cellArray, + vtkPointData *pd, vtkCellData* cd) +{ + (void)pd; + (void)cd; + + int i=0; + int j=0; + int c=0; + vtkIdList *ptIds=0; + vtkIdList *buffer=0; + vtkPoints *pts=0; + vtkCell *gc=0; + vtkGenericAttribute *a=0; + double pcoords[3]; + double *values=new double[attributes->GetMaxNumberOfComponents()]; + int dim=this->GetDimension(); + + if(this->IsGeometryLinear()) + { + // geometry: points + c=this->GetNumberOfPoints(); + i=0; + while(iInsertNextPoint(this->Cell->GetPoints()->GetPoint(i)); + ++i; + } + // geometry: cell + gc=this->Cell->NewInstance(); + gc->DeepCopy(this->Cell); + cellArray->InsertNextCell(gc); + gc->Delete(); + + // copy attributes + c=attributes->GetNumberOfAttributes(); + i=0; + while(iGetAttribute(i); + if (a->GetCentering()==vtkCenteringCells) + { + // pcoords is not used when centering is on cells. + this->InterpolateTuple(a,pcoords,values); + assert("check: TODO" && 0); + //cd->; + } + ++i; + } + } + else + { + // geometry: points + ptIds=vtkIdList::New(); + buffer=vtkIdList::New(); + pts=vtkPoints::New(); + this->Cell->Triangulate(0,ptIds,pts); + + c=pts->GetNumberOfPoints(); + i=0; + while(iInsertNextPoint(pts->GetPoint(i)); + ++i; + } + + // geometry: cells + c=ptIds->GetNumberOfIds(); + i=0; + j=0; + buffer->Reset(); + while(iInsertNextId(ptIds->GetId(i)); + ++i; + ++j; + if (j>dim) + { + cellArray->InsertNextCell(buffer); + j=0; + buffer->Reset(); + } + } + + // interpolate attributes + ptIds->Delete(); + buffer->Delete(); + pts->Delete(); + } + +} +#endif +// For the internals of the tesselation algorithm (the hash table in particular) +// Is the face `faceId' of the current cell on a exterior boundary of the +// dataset or not? +// \pre 3d: GetDimension()==3 +//----------------------------------------------------------------------------- +int vtkBridgeCell::IsFaceOnBoundary(vtkIdType faceId) +{ + assert("pre: 3d" && this->GetDimension()==3); + + // result=CountNeighbors(boundary(faceId))==0; + + vtkCell *face=this->Cell->GetFace(faceId); + vtkIdList *cells=vtkIdList::New(); // expensive + this->DataSet->Implementation->GetCellNeighbors(this->Id,face->GetPointIds(),cells); + + int result=cells->GetNumberOfIds()==0; + cells->Delete(); // expensive +#if 0 + if(this->GetType()==VTK_QUADRATIC_TETRA) + { + if(result) + { + cout<<"************************************************ boundary"<GetDimension()==2); +// assert("check: TODO" && 0); + return 1; +} + +//----------------------------------------------------------------------------- +// Description: +// Put into `id' the list of ids the point of the cell. +// \pre id_exists: id!=0 +// \pre valid_size: sizeof(id)==GetNumberOfPoints(); +void vtkBridgeCell::GetPointIds(vtkIdType *id) +{ + vtkIdType i=0; + vtkIdList *l=this->Cell->GetPointIds(); + vtkIdType c=this->GetNumberOfBoundaries(0); + while(iGetId(i); + ++i; + } +} +#if 0 +//----------------------------------------------------------------------------- +void vtkBridgeCell::TriangulateFace(vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + int index, + vtkPoints *pts, vtkCellArray *cellArray, + vtkPointData *pd, + vtkCellData *cd ) +{ + (void)attributes; + (void)tess; + (void)index; + (void)pts; + (void)cellArray; + (void)pd; + (void)cd; + assert("check: TODO" && 0); +} +#endif + +//----------------------------------------------------------------------------- +// Description: +// Return the ids of the vertices defining face `faceId'. +// \pre is_3d: this->GetDimension()==3 +// \pre valid_faceId_range: faceId>=0 && faceIdGetNumberOfBoundaries(2) +// \post result_exists: result!=0 +// \post valid_size: sizeof(result)>=GetNumberOfVerticesOnFace(faceId) +int *vtkBridgeCell::GetFaceArray(int faceId) +{ + assert("pre: is_3d" && this->GetDimension()==3); + assert("pre: valid_faceId_range" && faceId>=0 && faceIdGetNumberOfBoundaries(2)); + + int *result=0; + + switch(this->GetType()) + { + case VTK_HIGHER_ORDER_TETRAHEDRON: + result=vtkTetra::GetFaceArray(faceId); + break; + case VTK_HIGHER_ORDER_HEXAHEDRON: + if(this->Cell->GetCellType()==VTK_VOXEL) + { + result=vtkVoxel::GetFaceArray(faceId); + } + else + { + result=vtkHexahedron::GetFaceArray(faceId); + } + break; + case VTK_HIGHER_ORDER_WEDGE: + result=vtkWedge::GetFaceArray(faceId); + break; + case VTK_HIGHER_ORDER_PYRAMID: + result=vtkPyramid::GetFaceArray(faceId); + break; +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) + case VTK_PENTAGONAL_PRISM: + assert("check: TODO" && 0); + break; + case VTK_HEXAGONAL_PRISM: + assert("check: TODO" && 0); + break; +#endif + default: + assert("check: impossible case" && 0); + break; + } + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Return the number of vertices defining face `faceId' +// \pre is_3d: this->GetDimension()==3 +// \pre valid_faceId_range: faceId>=0 && faceIdGetNumberOfBoundaries(2) +// \post positive_result: && result>0 +int vtkBridgeCell::GetNumberOfVerticesOnFace(int faceId) +{ + assert("pre: is_3d" && this->GetDimension()==3); + assert("pre: valid_faceId_range" && faceId>=0 && faceIdGetNumberOfBoundaries(2)); + + int result; + + switch(this->GetType()) + { + case VTK_HIGHER_ORDER_TETRAHEDRON: + result=3; + break; + case VTK_HIGHER_ORDER_HEXAHEDRON: + result=4; + break; + case VTK_HIGHER_ORDER_WEDGE: + if(faceId<=1) + { + result=3; + } + else + { + result=4; + } + break; + case VTK_HIGHER_ORDER_PYRAMID: + if(faceId==0) + { + result=4; + } + else + { + result=3; + } + break; +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) +#if 0 // TODO + case VTK_PENTAGONAL_PRISM: + if(faceId<=1) + { + result=4; + } + else + { + result=3; + } + break; + case VTK_HEXAGONAL_PRISM: + if(faceId<=1) + { + result=6; + } + else + { + result=4; + } + break; +#endif +#endif + default: + assert("check: impossible case" && 0); + result=0; // just to fix warning of some compilers + break; + } + + assert("post: positive_result" && result>0); + return result; +} + +// copy/paste of vtkTriangle.cxx +static int triangleEdges[3][2] = { {0,1}, {1,2}, {2,0} }; +static int quadEdges[4][2] = { {0,1}, {1,2}, {3,2}, {0,3} }; + +//----------------------------------------------------------------------------- +// Description: +// Return the ids of the vertices defining edge `edgeId'. +// \pre valid_dimension: this->GetDimension()>=2 +// \pre valid_edgeId_range: edgeId>=0 && edgeIdGetNumberOfBoundaries(1) +// \post result_exists: result!=0 +// \post valid_size: sizeof(result)==2 +int *vtkBridgeCell::GetEdgeArray(int edgeId) +{ + assert("pre: valid_dimension" && this->GetDimension()>=2); + assert("pre: valid_faceId_range" && edgeId>=0 && edgeIdGetNumberOfBoundaries(1)); + + int *result; + + switch(this->GetType()) + { + case VTK_HIGHER_ORDER_TRIANGLE: + result=triangleEdges[edgeId]; + break; + case VTK_HIGHER_ORDER_QUAD: + result=quadEdges[edgeId]; + break; + case VTK_HIGHER_ORDER_TETRAHEDRON: + result=vtkTetra::GetEdgeArray(edgeId); + break; + case VTK_HIGHER_ORDER_HEXAHEDRON: + if(this->Cell->GetCellType()==VTK_VOXEL) + { + result=vtkVoxel::GetEdgeArray(edgeId); + } + else + { + result=vtkHexahedron::GetEdgeArray(edgeId); + } + break; + case VTK_HIGHER_ORDER_WEDGE: + result=vtkWedge::GetEdgeArray(edgeId); + break; + case VTK_HIGHER_ORDER_PYRAMID: + result=vtkPyramid::GetEdgeArray(edgeId); + break; +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) + case VTK_PENTAGONAL_PRISM: + assert("check: TODO" && 0); + result=0; // just to fix warning of some compilers + break; + case VTK_HEXAGONAL_PRISM: + assert("check: TODO" && 0); + result=0; // just to fix warning of some compilers + break; +#endif + default: + assert("check: impossible case" && 0); + result=0; // just to fix warning of some compilers + break; + } + + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally for the Bridge. +// Initialize the cell from a dataset `ds' and `cellid'. +// \pre ds_exists: ds!=0 +// \pre valid_cellid: (cellid>=0) && (cellidGetNumberOfCells()) +void vtkBridgeCell::Init(vtkBridgeDataSet *ds, + vtkIdType cellid) +{ + assert("pre: ds_exists" && ds!=0); + assert("pre: valid_cellid" && (cellid>=0) + && (cellidGetNumberOfCells())); + + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,ds); + vtkCell *tmp=ds->Implementation->GetCell(cellid); + vtkSetObjectBodyMacro(Cell,vtkCell,tmp); + this->Id=cellid; + this->BoolIsInDataSet=1; + if(this->InternalIterator==0) + { + this->InternalIterator=vtkBridgeCellIterator::New(); + } + this->InternalIterator->InitWithOneCell(this); + + this->InternalIterator->Begin(); +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally for the Bridge. +// Initialize the cell from a cell `c' and an `id'. +// \pre c_exists: c!=0 +void vtkBridgeCell::InitWithCell(vtkCell *c, + vtkIdType id) +{ + assert("pre: c_exists" && c!=0); + + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); + this->Id=id; + + // warning: do directly vtkSetObjectBodyMacro(Cell,vtkCell,c->NewInstance()) + // add memory leak because the text "c->NewInstance()" is copied several + // time in the macro... + + if(this->Cell!=0) + { + this->Cell->Delete(); + } + this->Cell=c->NewInstance(); + + this->Cell->DeepCopy(c); + this->BoolIsInDataSet=0; + + if(this->InternalIterator==0) + { + this->InternalIterator=vtkBridgeCellIterator::New(); + } + this->InternalIterator->InitWithOneCell(this); + this->InternalIterator->Begin(); +} + +//----------------------------------------------------------------------------- +// Description: +// Recursive copy of `other' into `this'. +// \pre other_exists: other!=0 +// \pre other_differ: this!=other +void vtkBridgeCell::DeepCopy(vtkBridgeCell *other) +{ + assert("pre: other_exists" && other!=0); + assert("pre: other_differ" && this!=other); + + vtkCell *tmp; + + if(this->InternalIterator==0) + { + this->InternalIterator=vtkBridgeCellIterator::New(); + } + this->Id=other->Id; + this->BoolIsInDataSet=other->BoolIsInDataSet; + if(other->BoolIsInDataSet) + { + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,other->DataSet); + tmp=this->DataSet->Implementation->GetCell(this->Id); + vtkSetObjectBodyMacro(Cell,vtkCell,tmp); + this->InternalIterator->InitWithOneCell(this); + this->InternalIterator->Begin(); + } + else + { + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); + tmp=other->Cell->NewInstance(); + vtkSetObjectBodyMacro(Cell,vtkCell,tmp); + this->Cell->Delete(); // because newinstance+macro=2 ref + this->Cell->DeepCopy(other->Cell); + this->InternalIterator->InitWithOneCell(this); + this->InternalIterator->Begin(); + } + this->Modified(); +} + +//----------------------------------------------------------------------------- +vtkBridgeCell::vtkBridgeCell() +{ + this->DataSet=0; + this->InternalIterator=0; // we cannot create the cell iterator here + // because we will have an infinite recursion: a cell creates a + // celliterator which creates a cell, which creates a celliterator ... + this->Cell=0; + this->BoolIsInDataSet=0; + this->Id=-1000; + + this->Weights=0; + this->WeightsCapacity=0; +// this->DebugOn(); +} + +//----------------------------------------------------------------------------- +vtkBridgeCell::~vtkBridgeCell() +{ + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); + vtkSetObjectBodyMacro(InternalIterator,vtkBridgeCellIterator,0); + vtkSetObjectBodyMacro(Cell,vtkCell,0); + + if(this->Weights!=0) + { + delete[] this->Weights; + this->Weights=0; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Allocate an array for the weights, only if it does not exist yet or if +// the capacity is too small. +void vtkBridgeCell::AllocateWeights() +{ + if((this->Weights!=0)&&(this->WeightsCapacityGetNumberOfPoints())) + { + delete[] this->Weights; + this->Weights=0; + } + if(this->Weights==0) + { + this->Weights=new double[this->GetNumberOfPoints()]; + this->WeightsCapacity=this->GetNumberOfPoints(); + } +} + +//----------------------------------------------------------------------------- +// Description: +// Compute the weights for parametric coordinates `pcoords'. +void vtkBridgeCell::InterpolationFunctions(double pcoords[3]) +{ + // Thanks to the stupid idea to make InterpolationFunctions static in all + // cells, here is a huge switch >:-( + +#if !(VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4)) + double rm=0; + double sm=0; +#endif + + switch(this->Cell->GetCellType()) + { + case VTK_EMPTY_CELL: + // I dont know what do with that + break; + case VTK_VERTEX: + vtkVertex::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_POLY_VERTEX: + // I dont know what do with that + break; + case VTK_LINE: + vtkLine::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_POLY_LINE: + vtkLine::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_TRIANGLE: +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) + vtkTriangle::InterpolationFunctions(pcoords,this->Weights); +#else + rm = 1. - pcoords[0]; + sm = 1. - pcoords[1]; + this->Weights[0]=rm*sm; + this->Weights[1]=pcoords[0] * sm; + this->Weights[1]=rm * pcoords[1]; +#endif + break; + case VTK_TRIANGLE_STRIP: + // I dont know what do with that + break; + case VTK_POLYGON: + static_cast(this->Cell)->ComputeWeights(pcoords,this->Weights); + break; + case VTK_PIXEL: + vtkPixel::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUAD: + vtkQuad::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_TETRA: + vtkTetra::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_VOXEL: + vtkVoxel::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_HEXAHEDRON: + vtkHexahedron::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_WEDGE: + vtkWedge::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_PYRAMID: + vtkPyramid::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUADRATIC_EDGE: + vtkQuadraticEdge::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUADRATIC_TRIANGLE: + vtkQuadraticTriangle::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUADRATIC_QUAD: + vtkQuadraticQuad::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUADRATIC_TETRA: + vtkQuadraticTetra::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUADRATIC_HEXAHEDRON: + vtkQuadraticHexahedron::InterpolationFunctions(pcoords,this->Weights); + break; +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) + case VTK_PENTAGONAL_PRISM: + vtkPentagonalPrism::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_HEXAGONAL_PRISM: + vtkHexagonalPrism::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUADRATIC_WEDGE: + vtkQuadraticWedge::InterpolationFunctions(pcoords,this->Weights); + break; + case VTK_QUADRATIC_PYRAMID: + vtkQuadraticPyramid::InterpolationFunctions(pcoords,this->Weights); + break; +#endif + case VTK_CONVEX_POINT_SET: + // I dont know what do with that + break; + } +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCell.h b/GenericFiltering/Testing/Cxx/vtkBridgeCell.h new file mode 100644 index 0000000..26ee6b9 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCell.h @@ -0,0 +1,497 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCell - Implementation of vtkGenericAdaptorCell +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericAdaptorCell, vtkBridgeDataSet + +#ifndef __vtkBridgeCell_h +#define __vtkBridgeCell_h + +#include "vtkBridgeExport.h" +#include "vtkGenericAdaptorCell.h" + +class vtkCell; +class vtkBridgeDataSet; +class vtkBridgeCellIterator; + +class VTK_BRIDGE_EXPORT vtkBridgeCell : public vtkGenericAdaptorCell +{ +public: + static vtkBridgeCell *New(); + vtkTypeRevisionMacro(vtkBridgeCell,vtkGenericAdaptorCell); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Unique identification number of the cell over the whole + // data set. This unique key may not be contiguous. + virtual vtkIdType GetId(); + + // Description: + // Does `this' a cell of a dataset? (otherwise, it is a boundary cell) + virtual int IsInDataSet(); + + // Description: + // Type of the current cell. + // \post (result==VTK_HIGHER_ORDER_EDGE)|| + // (result==VTK_HIGHER_ORDER_TRIANGLE)|| + // (result==VTK_HIGHER_ORDER_TETRAHEDRON) + virtual int GetType(); + + // Description: + // Topological dimension of the current cell. + // \post valid_result: result>=0 && result<=3 + virtual int GetDimension(); + + // Description: + // Interpolation order of the geometry. + // \post positive_result: result>=0 + virtual int GetGeometryOrder(); + + // Description: + // Does the cell have no higher-order interpolation for geometry? + // \post definition: result==(GetGeometryOrder()==1) + int IsGeometryLinear(); + + // Description: + // Interpolation order of attribute `a' on the cell (may differ by cell). + // \pre a_exists: a!=0 + // \post positive_result: result>=0 + virtual int GetAttributeOrder(vtkGenericAttribute *a); + + // Description: + // Does the attribute `a' have no higher-order interpolation for the cell? + // \pre a_exists: a!=0 + // \post definition: result==(GetAttributeOrder()==1) + int IsAttributeLinear(vtkGenericAttribute *a); + + // Description: + // Is the cell primary (i.e. not composite) ? + virtual int IsPrimary(); + + // Description: + // Number of points that compose the cell. + // \post positive_result: result>=0 + virtual int GetNumberOfPoints(); + + // Description: + // Return the number of boundaries of dimension `dim' (or all dimensions + // greater than 0 and less than GetDimension() if -1) of the cell. + // When \a dim is -1, the number of vertices is not included in the + // count because vertices are a special case: a vertex will have + // at most a single field value associated with it; DOF nodes may have + // an arbitrary number of field values associated with them. + // \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dim=0 + virtual int GetNumberOfBoundaries(int dim=-1); + + // Description: + // Accumulated number of DOF nodes of the current cell. A DOF node is + // a component of cell with a given topological dimension. e.g.: a triangle + // has 4 DOF: 1 face and 3 edges. An hexahedron has 19 DOF: + // 1 region, 6 faces, and 12 edges. + // + // The number of vertices is not included in the + // count because vertices are a special case: a vertex will have + // at most a single field value associated with it; DOF nodes may have + // an arbitrary number of field values associated with them. + // \post valid_result: result==GetNumberOfBoundaries(-1)+1 + virtual int GetNumberOfDOFNodes(); + + // Description: + // Return the points of cell into `it'. + // \pre it_exists: it!=0 + virtual void GetPointIterator(vtkGenericPointIterator *it); + + // Description: + // Create an empty cell iterator. + // \post result_exists: result!=0 + virtual vtkGenericCellIterator *NewCellIterator(); + + // Description: + // Return in `boundaries' the cells of dimension `dim' (or all dimensions + // less than GetDimension() if -1) that are part of the boundary of the cell. + // \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dimboundary->GetDimension()) of the dataset + // that share the boundary `boundary' of `this'. + // `this' IS NOT INCLUDED. + // \pre boundary_exists: boundary!=0 + // \pre real_boundary: !boundary->IsInDataSet() + // \pre cell_of_the_dataset: IsInDataSet() + // \pre boundary: HasBoundary(boundary) + // \post positive_result: result>=0 + virtual int CountNeighbors(vtkGenericAdaptorCell *boundary); + void CountEdgeNeighbors( int* sharing ); + + // Description: + // Put into `neighbors' the cells (dimension>boundary->GetDimension()) + // of the dataset that share the boundary `boundary' of `this'. + // `this' IS NOT INCLUDED. + // \pre boundary_exists: boundary!=0 + // \pre real_boundary: !boundary->IsInDataSet() + // \pre cell_of_the_dataset: IsInDataSet() + // \pre boundary: HasBoundary(boundary) + // \pre neighbors_exist: neighbors!=0 + virtual void GetNeighbors(vtkGenericAdaptorCell *boundary, + vtkGenericCellIterator *neighbors); + + // Description: + // Compute the closest boundary of the current sub-cell `subId' for point + // `pcoord' (in parametric coordinates) in `boundary', and return whether + // the point is inside the cell or not. `boundary' is of dimension + // GetDimension()-1. + // \pre positive_subId: subId>=0 + virtual int FindClosestBoundary(int subId, + double pcoords[3], + vtkGenericCellIterator* &boundary); + + // Description: + // Is `x' inside the current cell? It also evaluate parametric coordinates + // `pcoords', sub-cell id `subId' (0 means primary cell), distance squared + // to the sub-cell in `dist2' and closest corner point `closestPoint'. + // `dist2' and `closestPoint' are not evaluated if `closestPoint'==0. + // If a numerical error occurred, -1 is returned and all other results + // should be ignored. + // \post valid_result: result==-1 || result==0 || result==1 + // \post positive_distance: result!=-1 implies (closestPoint!=0 implies + // dist2>=0) + virtual int EvaluatePosition(double x[3], + double *closestPoint, + int &subId, + double pcoords[3], + double &dist2); + +// Description: + // Determine global coordinates `x' from sub-cell `subId' and parametric + // coordinates `pcoords' in the cell. + // \pre positive_subId: subId>=0 + // \pre clamped_pcoords: (0<=pcoords[0])&&(pcoords[0]<=1)&&(0<=pcoords[1]) + // &&(pcoords[1]<=1)&&(0<=pcoords[2])&&(pcoords[2]<=1) + virtual void EvaluateLocation(int subId, + double pcoords[3], + double x[3]); + + // Description: + // Interpolate the attribute `a' at local position `pcoords' of the cell into + // `val'. + // \pre a_exists: a!=0 + // \pre a_is_point_centered: a->GetCentering()==vtkPointCentered + // \pre clamped_point: pcoords[0]>=0 && pcoords[0]<=1 && pcoords[1]>=0 && + // pcoords[1]<=1 && pcoords[2]>=0 && pcoords[2]<=1 + // \pre val_exists: val!=0 + // \pre valid_size: sizeof(val)==a->GetNumberOfComponents() + virtual void InterpolateTuple(vtkGenericAttribute *a, double pcoords[3], + double *val); + + // Description: + // Interpolate the whole collection of attributes `c' at local position + // `pcoords' of the cell into `val'. Only point centered attributes are + // taken into account. + // \pre c_exists: c!=0 + // \pre clamped_point: pcoords[0]>=0 && pcoords[0]<=1 && pcoords[1]>=0 && + // pcoords[1]<=1 && pcoords[2]>=0 && pcoords[2]<=1 + // \pre val_exists: val!=0 + // \pre valid_size: sizeof(val)==c->GetNumberOfPointCenteredComponents() + virtual void InterpolateTuple(vtkGenericAttributeCollection *c, double pcoords[3], + double *val); +#if 0 + // Description: + // Generate a contour (contouring primitives) for each `values' or with + // respect to an implicit function `f'. Contouring + // is performed on the scalar attribute (`attributes->GetActiveAttribute()', + // `attributes->GetActiveComponent()'). + // Contouring interpolates the + // `attributes->GetNumberOfattributesToInterpolate()' attributes + // `attributes->GetAttributesToInterpolate()'. + // `locator', `verts', `lines', `polys', `outPd' and `outCd' are cumulative + // data arrays over cell iterations: they store the result of each call + // to Contour(): + // - `locator' is points list that merges points as they are inserted (i.e., + // prevents duplicates). + // - `verts' is an array of generated vertices + // - `lines' is an array of generated lines + // - `polys' is an array of generated polygons + // - `outPd' is an array of interpolated point data along the edge (if + // not-NULL) + // - `outCd' is an array of copied cell data of the current cell (if + // not-NULL) + // Note: the CopyAllocate() method must be invoked on both the output cell + // and point data. + // + // NOTE: `vtkGenericAttributeCollection *attributes' will be replaced by a + // `vtkInformation'. + // + // \pre values_exist: (values!=0 && f==0) || (values==0 && f!=0) + // \pre attributes_exist: attributes!=0 + // \pre locator_exists: locator!=0 + // \pre verts_exist: verts!=0 + // \pre lines_exist: lines!=0 + // \pre polys_exist: polys!=0 + virtual void Contour(vtkContourValues *values, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkCellArray *lines, + vtkCellArray *polys, + vtkPointData *outPd, + vtkCellData *outCd); +#endif +#if 0 + // Description: + // Cut (or clip) the current cell with respect to the contour defined by the + // `value' or the implicit function `f' of the scalar attribute + // (`attributes->GetActiveAttribute()',`attributes->GetActiveComponent()'). + // If `f' exists, `value' is not used. The output is the part + // of the current cell which is inside the contour. + // The output is a set of zero, one or more cells of the same topological + // dimension as the current cell. Normally, cell points whose scalar value + // is greater than "value" are considered inside. If `insideOut' is on, this + // is reversed. + // Clipping interpolates the + // `attributes->GetNumberOfattributesToInterpolate()' attributes + // `attributes->GetAttributesToInterpolate()'. + // `locator', `connectivity', `outPd' and `outCd' are cumulative + // data arrays over cell iterations: they store the result of each call + // to Clip(): + // - `locator' is points list that merges points as they are inserted (i.e., + // prevents duplicates). + // - `connectivity' is an array of generated cells + // - `outPd' is an array of interpolated point data along the edge (if + // not-NULL) + // - `outCd' is an array of copied cell data of the current cell (if + // not-NULL) + // Note: the CopyAllocate() method must be invoked on both the output cell + // and point data. + // Also, if the output cell data is + // non-NULL, the cell data from the clipped cell is passed to the generated + // contouring primitives. (Note: the CopyAllocate() method must be invoked on + // both the output cell and point data.) + // + // NOTE: `vtkGenericAttributeCollection *attributes' will be replaced by a + // `vtkInformation'. + // + // \pre attributes_exist: attributes!=0 + // \pre tess_exists: tess!=0 + // \pre locator_exists: locator!=0 + // \pre connectivity_exists: connectivity!=0 + virtual void Clip(double value, + vtkImplicitFunction *f, + vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + int insideOut, + vtkPointLocator *locator, + vtkCellArray *connectivity, + vtkPointData *outPd, + vtkCellData *outCd); +#endif + // Description: + // Is there an intersection between the current cell and the ray (`p1',`p2') + // according to a tolerance `tol'? If true, `x' is the global intersection, + // `t' is the parametric coordinate for the line, `pcoords' are the + // parametric coordinates for cell. `subId' is the sub-cell where + // the intersection occurs. + // \pre positive_tolerance: tol>0 + virtual int IntersectWithLine(double p1[3], + double p2[3], + double tol, + double &t, + double x[3], + double pcoords[3], + int &subId); + + // Description: + // Compute derivatives `derivs' of the attribute `attribute' (from its + // values at the corner points of the cell) given sub-cell `subId' (0 means + // primary cell) and parametric coordinates `pcoords'. + // Derivatives are in the x-y-z coordinate directions for each data value. + // \pre positive_subId: subId>=0 + // \pre clamped_pcoords: (0<=pcoords[0])&&(pcoords[0]<=1)&&(0<=pcoords[1]) + // &&(pcoords[1]<=1)&&(0<=pcoords[2])%%(pcoords[2]<=1) + // \pre attribute_exists: attribute!=0 + // \pre derivs_exists: derivs!=0 + // \pre valid_size: sizeof(derivs)>=attribute->GetNumberOfComponents()*3 + virtual void Derivatives(int subId, + double pcoords[3], + vtkGenericAttribute *attribute, + double *derivs); + + // Description: + // Compute the bounding box of the current cell in `bounds' in global + // coordinates. + // THREAD SAFE + virtual void GetBounds(double bounds[6]); + + // Description: + // Return the bounding box of the current cell in global coordinates. + // NOT THREAD SAFE + // \post result_exists: result!=0 + // \post valid_size: sizeof(result)>=6 + virtual double *GetBounds(); + + // Description: + // Bounding box diagonal squared of the current cell. + // \post positive_result: result>=0 + virtual double GetLength2(); + + // Description: + // Center of the current cell in parametric coordinates `pcoords'. + // If the current cell is a composite, the return value is the sub-cell id + // that the center is in. + // \post valid_result: (result>=0) && (IsPrimary() implies result==0) + virtual int GetParametricCenter(double pcoords[3]); + + // Description: + // Distance of the parametric coordinate `pcoords' to the current cell. + // If inside the cell, a distance of zero is returned. This is used during + // picking to get the correct cell picked. (The tolerance will occasionally + // allow cells to be picked who are not really intersected "inside" the + // cell.) + // \post positive_result: result>=0 + virtual double GetParametricDistance(double pcoords[3]); + + // Description: + // Return a contiguous array of parametric coordinates of the points defining + // the current cell. In other words, (px,py,pz, px,py,pz, etc..) The + // coordinates are ordered consistent with the definition of the point + // ordering for the cell. Note that 3D parametric coordinates are returned + // no matter what the topological dimension of the cell. It includes the DOF + // nodes. + // \post valid_result_exists: ((IsPrimary()) && (result!=0)) || + // ((!IsPrimary()) && (result==0)) + // result!=0 implies sizeof(result)==GetNumberOfPoints() + virtual double *GetParametricCoords(); +#if 0 + // Description: + // Tessellate the cell if it is not linear or if at least one attribute of + // `attributes' is not linear. The output are linear cells of the same + // dimension than than cell. If the cell is linear and all attributes are + // linear, the output is just a copy of the current cell. + // `points', `cellArray', `pd' and `cd' are cumulative output data arrays + // over cell iterations: they store the result of each call to Tessellate(). + // \pre attributes_exist: attributes!=0 + // \pre points_exist: points!=0 + // \pre cellArray_exists: cellArray!=0 + // \pre pd_exist: pd!=0 + // \pre cd_exists: cd!=0 + virtual void Tessellate(vtkGenericAttributeCollection *attributes, + vtkPoints *points, vtkCellArray* cellArray, + vtkPointData *pd, vtkCellData* cd); +#endif + // For the internals of the tesselation algorithm (the hash table in particular) + virtual int IsFaceOnBoundary(vtkIdType faceId); + virtual int IsOnBoundary(); + + // Description: + // Put into `id' the list of ids the point of the cell. + // \pre id_exists: id!=0 + // \pre valid_size: sizeof(id)==GetNumberOfPoints(); + virtual void GetPointIds(vtkIdType *id); +#if 0 + virtual void TriangulateFace(vtkGenericAttributeCollection *attributes, + vtkGenericCellTessellator *tess, + int index, + vtkPoints *pts, vtkCellArray *cellArray, + vtkPointData *pd, + vtkCellData *cd ); +#endif + + // Description: + // Return the ids of the vertices defining face `faceId'. + // \pre is_3d: this->GetDimension()==3 + // \pre valid_faceId_range: faceId>=0 && faceIdGetNumberOfBoundaries(2) + // \post result_exists: result!=0 + // \post valid_size: sizeof(result)>=GetNumberOfVerticesOnFace(faceId) + int *GetFaceArray(int faceId); + + // Description: + // Return the number of vertices defining face `faceId' + // \pre is_3d: this->GetDimension()==3 + // \pre valid_faceId_range: faceId>=0 && faceIdGetNumberOfBoundaries(2) + // \post positive_result: && result>0 + int GetNumberOfVerticesOnFace(int faceId); + + // Description: + // Return the ids of the vertices defining edge `edgeId'. + // \pre valid_dimension: this->GetDimension()>=2 + // \pre valid_edgeId_range: edgeId>=0 && edgeIdGetNumberOfBoundaries(1) + // \post result_exists: result!=0 + // \post valid_size: sizeof(result)==2 + int *GetEdgeArray(int edgeId); + + // Description: + // Used internally for the Bridge. + // Initialize the cell from a dataset `ds' and `cellid'. + // \pre ds_exists: ds!=0 + // \pre valid_cellid: (cellid>=0) && (cellidGetNumberOfCells()) + void Init(vtkBridgeDataSet *ds, + vtkIdType cellid); + + // Description: + // Used internally for the Bridge. + // Initialize the cell from a cell `c' and an `id'. + // \pre c_exists: c!=0 + void InitWithCell(vtkCell *c, + vtkIdType id); + + // Description: + // Recursive copy of `other' into `this'. + // \pre other_exists: other!=0 + // \pre other_differ: this!=other + void DeepCopy(vtkBridgeCell *other); + +protected: + vtkBridgeCell(); + virtual ~vtkBridgeCell(); + + // Description: + // Allocate an array for the weights, only if it does not exist yet or if + // the capacity is too small. + void AllocateWeights(); + + // Description: + // Compute the weights for parametric coordinates `pcoords'. + void InterpolationFunctions(double pcoords[3]); + + friend class vtkBridgeDataSet; + friend class vtkBridgeAttribute; + friend class vtkBridgeCellIterator; + friend class vtkBridgeCellIteratorOnDataSet; + friend class vtkBridgeCellIteratorOne; + friend class vtkBridgeCellIteratorOnCellBoundaries; + friend class vtkBridgePointIteratorOnCell; + + vtkCell *Cell; + vtkBridgeDataSet *DataSet; + vtkIdType Id; // what does it mean for boundary cells? + int BoolIsInDataSet; + vtkBridgeCellIterator *InternalIterator; // used in Contour + + double *Weights; // interpolation functions + int WeightsCapacity; + +private: + vtkBridgeCell(const vtkBridgeCell&); // Not implemented. + void operator=(const vtkBridgeCell&); // Not implemented. +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIterator.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeCellIterator.cxx new file mode 100644 index 0000000..139efcd --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIterator.cxx @@ -0,0 +1,255 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIterator - Implementation of vtkGenericCellIterator. +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericCellIterator, vtkBridgeDataSet + +#include "vtkBridgeCellIterator.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeCell.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" +#include "vtkIdList.h" + +#include "vtkBridgeCellIteratorOnDataSet.h" +#include "vtkBridgeCellIteratorOne.h" +#include "vtkBridgeCellIteratorOnCellBoundaries.h" +#include "vtkBridgeCellIteratorOnCellList.h" + +vtkCxxRevisionMacro(vtkBridgeCellIterator, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkBridgeCellIterator); + +//----------------------------------------------------------------------------- +void vtkBridgeCellIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIterator::vtkBridgeCellIterator() +{ +// this->DebugOn(); + this->CurrentIterator=0; + this->IteratorOnDataSet=vtkBridgeCellIteratorOnDataSet::New(); + this->IteratorOneCell=vtkBridgeCellIteratorOne::New(); + this->IteratorOnCellBoundaries=vtkBridgeCellIteratorOnCellBoundaries::New(); + this->IteratorOnCellList=vtkBridgeCellIteratorOnCellList::New(); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIterator::~vtkBridgeCellIterator() +{ + this->IteratorOnDataSet->Delete(); + this->IteratorOneCell->Delete(); + this->IteratorOnCellBoundaries->Delete(); + this->IteratorOnCellList->Delete(); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgeCellIterator::Begin() +{ + if(this->CurrentIterator!=0) + { + this->CurrentIterator->Begin(); + } +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no cell at iterator position? (exit condition). +int vtkBridgeCellIterator::IsAtEnd() +{ + int result=1; + + if(this->CurrentIterator!=0) + { + result=this->CurrentIterator->IsAtEnd(); + } + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Create an empty cell. +// \post result_exists: result!=0 +vtkGenericAdaptorCell *vtkBridgeCellIterator::NewCell() +{ + vtkGenericAdaptorCell *result=vtkBridgeCell::New(); + assert("post: result_exists" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position +// \pre not_at_end: !IsAtEnd() +// \pre c_exists: c!=0 +// THREAD SAFE +void vtkBridgeCellIterator::GetCell(vtkGenericAdaptorCell *c) +{ + assert("pre: not_at_end" && !IsAtEnd()); + assert("pre: c_exists" && c!=0); + + this->CurrentIterator->GetCell(c); +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position. +// NOT THREAD SAFE +// \pre not_at_end: !IsAtEnd() +// \post result_exits: result!=0 +vtkGenericAdaptorCell *vtkBridgeCellIterator::GetCell() +{ + assert("pre: not_at_end" && !IsAtEnd()); + vtkGenericAdaptorCell *result=this->CurrentIterator->GetCell( ); + assert("post: result_exits" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_at_end: !IsAtEnd() +void vtkBridgeCellIterator::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + this->CurrentIterator->Next(); +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate over cells of `ds' of some dimension `dim'. +// \pre ds_exists: ds!=0 +// \pre valid_dim_range: (dim>=-1) && (dim<=3) +void vtkBridgeCellIterator::InitWithDataSet(vtkBridgeDataSet *ds, + int dim) +{ + assert("pre: ds_exists" && ds!=0); + assert("pre: valid_dim_range" && (dim>=-1) && (dim<=3)); + + this->IteratorOnDataSet->InitWithDataSet(ds,dim); + this->CurrentIterator=this->IteratorOnDataSet; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate over boundary cells of `ds' of some dimension `dim'. +// \pre ds_exists: ds!=0 +// \pre valid_dim_range: (dim>=-1) && (dim<=3) +void vtkBridgeCellIterator::InitWithDataSetBoundaries(vtkBridgeDataSet *ds, + int dim, + int exterior_only) +{ + assert("pre: ds_exists" && ds!=0); + assert("pre: valid_dim_range" && (dim>=-1) && (dim<=3)); + + (void)ds; + (void)dim; + (void)exterior_only; + + assert("check: TODO" && 0); +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate on one cell `id' of `ds'. +// \pre ds_exists: ds!=0 +// \pre valid_id: (id>=0)&&(id<=ds->GetNumberOfCells()) +void vtkBridgeCellIterator::InitWithOneCell(vtkBridgeDataSet *ds, + vtkIdType cellid) +{ + assert("pre: ds_exists" && ds!=0); + assert("pre: valid_id" && (cellid>=0)&&(cellid<=ds->GetNumberOfCells())); + + this->IteratorOneCell->InitWithOneCell(ds,cellid); + this->CurrentIterator=this->IteratorOneCell; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on one cell `c'. +// \pre c_exists: c!=0 +void vtkBridgeCellIterator::InitWithOneCell(vtkBridgeCell *c) +{ + assert("pre: c_exists" && c!=0); + this->IteratorOneCell->InitWithOneCell(c); + this->CurrentIterator=this->IteratorOneCell; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on boundary cells of a cell. +// \pre cell_exists: cell!=0 +// \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dimGetDimension())) +void vtkBridgeCellIterator::InitWithCellBoundaries(vtkBridgeCell *cell, + int dim) +{ + assert("pre: cell_exists" && cell!=0); + assert("pre: valid_dim_range" && ((dim==-1) || ((dim>=0)&&(dimGetDimension())))); + this->IteratorOnCellBoundaries->InitWithCellBoundaries(cell,dim); + this->CurrentIterator=this->IteratorOnCellBoundaries; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on neighbors defined by `cells' over the dataset `ds'. +// \pre cells_exist: cells!=0 +// \pre ds_exists: ds!=0 +void vtkBridgeCellIterator::InitWithCells(vtkIdList *cells, + vtkBridgeDataSet *ds) +{ + assert("pre: cells_exist" && cells!=0); + assert("pre: ds_exists" && ds!=0); + + this->IteratorOnCellList->InitWithCells(cells,ds); + this->CurrentIterator=this->IteratorOnCellList; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on a boundary cell (defined by its points `pts' with coordinates +// `coords', dimension `dim' and unique id `cellid') of a cell. +// \pre coords_exist: coords!=0 +// \pre pts_exist: pts!=0 +// \pre valid_dim: dim>=0 && dim<=2 +// \pre valid_points: pts->GetNumberOfIds()>dim +void vtkBridgeCellIterator::InitWithPoints(vtkPoints *coords, + vtkIdList *pts, + int dim, + vtkIdType cellid) +{ + assert("pre: coords_exist" && coords!=0); + assert("pre: pts_exist" && pts!=0); + assert("pre: valid_dim" && dim>=0 && dim<=2); + assert("pre: valid_points" && pts->GetNumberOfIds()>dim); + + this->IteratorOneCell->InitWithPoints(coords,pts,dim,cellid); + this->CurrentIterator=this->IteratorOneCell; +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIterator.h b/GenericFiltering/Testing/Cxx/vtkBridgeCellIterator.h new file mode 100644 index 0000000..e52adf0 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIterator.h @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIterator - Implementation of vtkGenericCellIterator. +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericCellIterator, vtkBridgeDataSet + +#ifndef __vtkBridgeCellIterator_h +#define __vtkBridgeCellIterator_h + +#include "vtkBridgeExport.h" +#include "vtkGenericCellIterator.h" + +class vtkBridgeCell; +class vtkBridgeDataSet; +class vtkBridgeCell; +class vtkIdList; +class vtkBridgeDataSet; +class vtkPoints; + +class vtkBridgeCellIteratorStrategy; +class vtkBridgeCellIteratorOnDataSet; +class vtkBridgeCellIteratorOne; +class vtkBridgeCellIteratorOnCellBoundaries; +class vtkBridgeCellIteratorOnCellList; + +class VTK_BRIDGE_EXPORT vtkBridgeCellIterator : public vtkGenericCellIterator +{ +public: + static vtkBridgeCellIterator *New(); + vtkTypeRevisionMacro(vtkBridgeCellIterator,vtkGenericCellIterator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no cell at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Create an empty cell. + // \post result_exists: result!=0 + vtkGenericAdaptorCell *NewCell(); + + // Description: + // Cell at current position + // \pre not_at_end: !IsAtEnd() + // \pre c_exists: c!=0 + // THREAD SAFE + void GetCell(vtkGenericAdaptorCell *c); + + // Description: + // Cell at current position. + // NOT THREAD SAFE + // \pre not_at_end: !IsAtEnd() + // \post result_exits: result!=0 + vtkGenericAdaptorCell *GetCell(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_at_end: !IsAtEnd() + void Next(); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate over cells of `ds' of some dimension `dim'. + // \pre ds_exists: ds!=0 + // \pre valid_dim_range: (dim>=-1) && (dim<=3) + void InitWithDataSet(vtkBridgeDataSet *ds, + int dim); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate over boundary cells of `ds' of some dimension `dim'. + // \pre ds_exists: ds!=0 + // \pre valid_dim_range: (dim>=-1) && (dim<=3) + void InitWithDataSetBoundaries(vtkBridgeDataSet *ds, + int dim, + int exterior_only); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate on one cell `id' of `ds'. + // \pre ds_exists: ds!=0 + // \pre valid_id: (id>=0)&&(id<=ds->GetNumberOfCells()) + void InitWithOneCell(vtkBridgeDataSet *ds, + vtkIdType cellid); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on one cell `c'. + // \pre c_exists: c!=0 + void InitWithOneCell(vtkBridgeCell *c); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on boundary cells of a cell. + // \pre cell_exists: cell!=0 + // \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dimGetDimension())) + void InitWithCellBoundaries(vtkBridgeCell *cell, + int dim); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on neighbors defined by `cells' over the dataset `ds'. + // \pre cells_exist: cells!=0 + // \pre ds_exists: ds!=0 + void InitWithCells(vtkIdList *cells, + vtkBridgeDataSet *ds); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on a boundary cell (defined by its points `pts' with coordinates + // `coords', dimension `dim' and unique id `cellid') of a cell. + // \pre coords_exist: coords!=0 + // \pre pts_exist: pts!=0 + // \pre valid_dim: dim>=0 && dim<=2 + // \pre valid_points: pts->GetNumberOfIds()>dim + void InitWithPoints(vtkPoints *coords, + vtkIdList *pts, + int dim, + vtkIdType cellid); + +protected: + vtkBridgeCellIterator(); + virtual ~vtkBridgeCellIterator(); + + vtkBridgeCellIteratorStrategy *CurrentIterator; + vtkBridgeCellIteratorOnDataSet *IteratorOnDataSet; + vtkBridgeCellIteratorOne *IteratorOneCell; + vtkBridgeCellIteratorOnCellBoundaries * IteratorOnCellBoundaries; + vtkBridgeCellIteratorOnCellList *IteratorOnCellList; + + vtkBridgeDataSet *DataSet; // the structure on which the objet iterates. + vtkIdType Id; // the id at current position. + int OneCell; // Is in one cell mode? + vtkIdType Size; // size of the structure. + vtkBridgeCell *Cell; // cell at current position. + +private: + vtkBridgeCellIterator(const vtkBridgeCellIterator&); // Not implemented + void operator=(const vtkBridgeCellIterator&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellBoundaries.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellBoundaries.cxx new file mode 100644 index 0000000..1a6497c --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellBoundaries.cxx @@ -0,0 +1,273 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOnCellBoundaries.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOnCellBoundaries - Iterate over cells of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#include "vtkBridgeCellIteratorOnCellBoundaries.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeCell.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" +#include "vtkCell.h" +#include "vtkVertex.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkBridgeCellIteratorOnCellBoundaries, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkBridgeCellIteratorOnCellBoundaries); + +//----------------------------------------------------------------------------- +void vtkBridgeCellIteratorOnCellBoundaries::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOnCellBoundaries::vtkBridgeCellIteratorOnCellBoundaries() +{ + this->DataSetCell=0; + this->Cell=vtkBridgeCell::New(); + this->Id=0; +// this->DebugOn(); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOnCellBoundaries::~vtkBridgeCellIteratorOnCellBoundaries() +{ + // warn: this class does not own this->DataSetCell, do never delete it. + this->Cell->Delete(); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgeCellIteratorOnCellBoundaries::Begin() +{ + this->Id=0; // first id of the current dimension + if(this->NumberOfFaces>0) + { + this->Dim=2; + } + else + { + if(this->NumberOfEdges>0) + { + this->Dim=1; + } + else + { + if(this->NumberOfVertices>0) + { + this->Dim=0; + } + else + { + this->Dim=-1; // is at end + } + } + } +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no cell at iterator position? (exit condition). +int vtkBridgeCellIteratorOnCellBoundaries::IsAtEnd() +{ + return this->Dim==-1; +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position +// \pre not_at_end: !IsAtEnd() +// \pre c_exists: c!=0 +// THREAD SAFE +void vtkBridgeCellIteratorOnCellBoundaries::GetCell(vtkGenericAdaptorCell *c) +{ + assert("pre: not_at_end" && !IsAtEnd()); + assert("pre: c_exists" && c!=0); + + vtkBridgeCell *c2=static_cast(c); + + vtkCell *vc=0; + + switch(this->Dim) + { + case 2: + vc=this->DataSetCell->Cell->GetFace(this->Id); + break; + case 1: + vc=this->DataSetCell->Cell->GetEdge(this->Id); + break; + case 0: + vc=vtkVertex::New(); + vc->Points->InsertNextPoint(this->DataSetCell->Cell->Points->GetPoint(this->Id)); + vc->PointIds->InsertNextId(0); + break; + default: + assert("check: impossible case" && 0); + break; + } + + c2->InitWithCell(vc,this->Id); // this->Id unique? + if(this->Dim==0) + { + vc->Delete(); + } +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position. +// NOT THREAD SAFE +// \pre not_at_end: !IsAtEnd() +// \post result_exits: result!=0 +vtkGenericAdaptorCell *vtkBridgeCellIteratorOnCellBoundaries::GetCell() +{ + assert("pre: not_at_end" && !IsAtEnd()); + + vtkCell *vc=0; + + switch(this->Dim) + { + case 2: + vc=this->DataSetCell->Cell->GetFace(this->Id); + break; + case 1: + vc=this->DataSetCell->Cell->GetEdge(this->Id); + break; + case 0: + vc=vtkVertex::New(); + vc->Points->InsertNextPoint(this->DataSetCell->Cell->Points->GetPoint(this->Id)); + vc->PointIds->InsertNextId(0); + break; + default: + assert("check: impossible case" && 0); + break; + } + + this->Cell->InitWithCell(vc,this->Id); // this->Id unique? + if(this->Dim==0) + { + vc->Delete(); + } + vtkGenericAdaptorCell *result=this->Cell; + + assert("post: result_exits" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_at_end: !IsAtEnd() +void vtkBridgeCellIteratorOnCellBoundaries::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + + int atEndOfDimension=0; + + this->Id++; // next id of the current dimension + + switch(this->Dim) + { + case 2: + atEndOfDimension=Id>=this->NumberOfFaces; + break; + case 1: + atEndOfDimension=Id>=this->NumberOfEdges; + break; + case 0: + atEndOfDimension=Id>=this->NumberOfVertices; + break; + default: + assert("check: impossible case" && 0); + break; + } + + if(atEndOfDimension) + { + this->Id=0; // first id of the next dimension + this->Dim--; + + if(this->Dim==1) + { + if(this->NumberOfEdges==0) + { + if(this->NumberOfVertices==0) + { + this->Dim=-1; + } + else + { + this->Dim=0; + } + } + } + else + { + if(this->NumberOfVertices==0) + { + this->Dim=-1; + } + } + } +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on boundary cells of a cell. +// \pre cell_exists: cell!=0 +// \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dimGetDimension())) +void vtkBridgeCellIteratorOnCellBoundaries::InitWithCellBoundaries(vtkBridgeCell *cell, + int dim) +{ + assert("pre: cell_exists" && cell!=0); + assert("pre: valid_dim_range" && ((dim==-1) || ((dim>=0)&&(dimGetDimension())))); + + this->DataSetCell=cell; + + if(((dim==-1)&&(2GetDimension()))||(dim==2)) // faces + { + this->NumberOfFaces=this->DataSetCell->Cell->GetNumberOfFaces(); + } + else + { + this->NumberOfFaces=0; + } + + if(((dim==-1)&&(1GetDimension()))||(dim==1)) // edges + { + this->NumberOfEdges=this->DataSetCell->Cell->GetNumberOfEdges(); + } + else + { + this->NumberOfEdges=0; + } + + if((dim==-1)||(dim==0)) // vertices + { + this->NumberOfVertices=this->DataSetCell->Cell->GetNumberOfPoints(); + } + else + { + this->NumberOfVertices=0; + } +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellBoundaries.h b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellBoundaries.h new file mode 100644 index 0000000..1ada3c8 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellBoundaries.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOnCellBoundaries.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOnCellBoundaries - Iterate over cells of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#ifndef __vtkBridgeCellIteratorOnCellBoundaries_h +#define __vtkBridgeCellIteratorOnCellBoundaries_h + +#include "vtkBridgeCellIteratorStrategy.h" + +class vtkBridgeCell; +class vtkBridgeDataSet; +class vtkBridgeCell; +class vtkIdList; + +class VTK_BRIDGE_EXPORT vtkBridgeCellIteratorOnCellBoundaries : public vtkBridgeCellIteratorStrategy +{ +public: + static vtkBridgeCellIteratorOnCellBoundaries *New(); + vtkTypeRevisionMacro(vtkBridgeCellIteratorOnCellBoundaries, + vtkBridgeCellIteratorStrategy); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no cell at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Cell at current position + // \pre not_at_end: !IsAtEnd() + // \pre c_exists: c!=0 + // THREAD SAFE + void GetCell(vtkGenericAdaptorCell *c); + + // Description: + // Cell at current position. + // NOT THREAD SAFE + // \pre not_at_end: !IsAtEnd() + // \post result_exits: result!=0 + vtkGenericAdaptorCell *GetCell(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_at_end: !IsAtEnd() + void Next(); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on boundary cells of a cell. + // \pre cell_exists: cell!=0 + // \pre valid_dim_range: (dim==-1) || ((dim>=0)&&(dimGetDimension())) + void InitWithCellBoundaries(vtkBridgeCell *cell, + int dim); + +protected: + vtkBridgeCellIteratorOnCellBoundaries(); + virtual ~vtkBridgeCellIteratorOnCellBoundaries(); + + int Dim; // Dimension of cells over which to iterate (-1 to 3) + + vtkBridgeCell *DataSetCell; // the structure on which the objet iterates. + vtkIdType Id; // the id at current position. + vtkBridgeCell *Cell; // cell at current position. + vtkIdType NumberOfFaces; + vtkIdType NumberOfEdges; + vtkIdType NumberOfVertices; +private: + vtkBridgeCellIteratorOnCellBoundaries(const vtkBridgeCellIteratorOnCellBoundaries&); // Not implemented + void operator=(const vtkBridgeCellIteratorOnCellBoundaries&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellList.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellList.cxx new file mode 100644 index 0000000..2b0479f --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellList.cxx @@ -0,0 +1,142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOnCellList.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOnCellList - Iterate over cells of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#include "vtkBridgeCellIteratorOnCellList.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeCell.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" +#include "vtkCell.h" +#include "vtkVertex.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkBridgeCellIteratorOnCellList, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkBridgeCellIteratorOnCellList); + +//----------------------------------------------------------------------------- +void vtkBridgeCellIteratorOnCellList::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOnCellList::vtkBridgeCellIteratorOnCellList() +{ + this->DataSet=0; + this->Cells=0; + this->Cell=vtkBridgeCell::New(); + this->Id=0; +// this->DebugOn(); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOnCellList::~vtkBridgeCellIteratorOnCellList() +{ + if(this->DataSet!=0) + { + this->DataSet->Delete(); + this->DataSet=0; + } + + if(this->Cells!=0) + { + this->Cells->Delete(); + this->Cells=0; + } + + this->Cell->Delete(); + this->Cell=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgeCellIteratorOnCellList::Begin() +{ + this->Id=0; // first id of the current dimension +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no cell at iterator position? (exit condition). +int vtkBridgeCellIteratorOnCellList::IsAtEnd() +{ + return this->Id>=this->Cells->GetNumberOfIds(); +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position +// \pre not_at_end: !IsAtEnd() +// \pre c_exists: c!=0 +// THREAD SAFE +void vtkBridgeCellIteratorOnCellList::GetCell(vtkGenericAdaptorCell *c) +{ + assert("pre: not_at_end" && !IsAtEnd()); + assert("pre: c_exists" && c!=0); + + vtkBridgeCell *c2=static_cast(c); + c2->Init(this->DataSet,this->Cells->GetId(this->Id)); +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position. +// NOT THREAD SAFE +// \pre not_at_end: !IsAtEnd() +// \post result_exits: result!=0 +vtkGenericAdaptorCell *vtkBridgeCellIteratorOnCellList::GetCell() +{ + assert("pre: not_at_end" && !IsAtEnd()); + + this->Cell->Init(this->DataSet,this->Cells->GetId(this->Id)); + vtkGenericAdaptorCell *result=this->Cell; + + assert("post: result_exits" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_at_end: !IsAtEnd() +void vtkBridgeCellIteratorOnCellList::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + this->Id++; // next id of the current dimension +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on neighbors defined by `cells' over the dataset `ds'. +// \pre cells_exist: cells!=0 +// \pre ds_exists: ds!=0 +void vtkBridgeCellIteratorOnCellList::InitWithCells(vtkIdList *cells, + vtkBridgeDataSet *ds) +{ + assert("pre: cells_exist" && cells!=0); + assert("pre: ds_exists" && ds!=0); + + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,ds); + vtkSetObjectBodyMacro(Cells,vtkIdList,cells); +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellList.h b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellList.h new file mode 100644 index 0000000..b36b8d5 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnCellList.h @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOnCellList.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOnCellList - Iterate over cells of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#ifndef __vtkBridgeCellIteratorOnCellList_h +#define __vtkBridgeCellIteratorOnCellList_h + +#include "vtkBridgeCellIteratorStrategy.h" + +class vtkBridgeCell; +class vtkIdList; +class vtkBridgeDataSet; + +class VTK_BRIDGE_EXPORT vtkBridgeCellIteratorOnCellList : public vtkBridgeCellIteratorStrategy +{ +public: + static vtkBridgeCellIteratorOnCellList *New(); + vtkTypeRevisionMacro(vtkBridgeCellIteratorOnCellList, + vtkBridgeCellIteratorStrategy); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no cell at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Cell at current position + // \pre not_at_end: !IsAtEnd() + // \pre c_exists: c!=0 + // THREAD SAFE + void GetCell(vtkGenericAdaptorCell *c); + + // Description: + // Cell at current position. + // NOT THREAD SAFE + // \pre not_at_end: !IsAtEnd() + // \post result_exits: result!=0 + vtkGenericAdaptorCell *GetCell(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_at_end: !IsAtEnd() + void Next(); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on neighbors defined by `cells' over the dataset `ds'. + // \pre cells_exist: cells!=0 + // \pre ds_exists: ds!=0 + void InitWithCells(vtkIdList *cells, + vtkBridgeDataSet *ds); + +protected: + vtkBridgeCellIteratorOnCellList(); + virtual ~vtkBridgeCellIteratorOnCellList(); + + vtkIdList *Cells; // cells traversed by the iterator. + vtkBridgeDataSet *DataSet; + vtkIdType Id; // the id at current position. + vtkBridgeCell *Cell; // cell at current position. + +private: + vtkBridgeCellIteratorOnCellList(const vtkBridgeCellIteratorOnCellList&); // Not implemented + void operator=(const vtkBridgeCellIteratorOnCellList&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnDataSet.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnDataSet.cxx new file mode 100644 index 0000000..38ff348 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnDataSet.cxx @@ -0,0 +1,155 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOnDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOnDataSet - Iterate over cells of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#include "vtkBridgeCellIteratorOnDataSet.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeCell.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" +#include "vtkCell.h" + +vtkCxxRevisionMacro(vtkBridgeCellIteratorOnDataSet, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkBridgeCellIteratorOnDataSet); + +//----------------------------------------------------------------------------- +void vtkBridgeCellIteratorOnDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOnDataSet::vtkBridgeCellIteratorOnDataSet() +{ + this->DataSet=0; + this->Cell=vtkBridgeCell::New(); + this->Id=0; + this->Size=0; +// this->DebugOn(); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOnDataSet::~vtkBridgeCellIteratorOnDataSet() +{ + if(this->DataSet!=0) + { + this->DataSet->Delete(); + this->DataSet=0; + } + this->Cell->Delete(); + this->Cell=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgeCellIteratorOnDataSet::Begin() +{ + this->Id=-1; + this->Next(); // skip cells of other dimensions +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no cell at iterator position? (exit condition). +int vtkBridgeCellIteratorOnDataSet::IsAtEnd() +{ + return (this->Id>=this->Size); +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position +// \pre not_at_end: !IsAtEnd() +// \pre c_exists: c!=0 +// THREAD SAFE +void vtkBridgeCellIteratorOnDataSet::GetCell(vtkGenericAdaptorCell *c) +{ + assert("pre: not_at_end" && !IsAtEnd()); + assert("pre: c_exists" && c!=0); + + vtkBridgeCell *c2=static_cast(c); + c2->Init(this->DataSet,this->Id); +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position. +// NOT THREAD SAFE +// \pre not_at_end: !IsAtEnd() +// \post result_exits: result!=0 +vtkGenericAdaptorCell *vtkBridgeCellIteratorOnDataSet::GetCell() +{ + assert("pre: not_at_end" && !IsAtEnd()); + + this->Cell->Init(this->DataSet,this->Id); + vtkGenericAdaptorCell *result=this->Cell; + + assert("post: result_exits" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_at_end: !IsAtEnd() +void vtkBridgeCellIteratorOnDataSet::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + + vtkIdType size=this->Size; + vtkCell *c; + int found; + + this->Id++; + + if(this->Dim>=0) // skip cells of other dimensions than this->Dim + { + found=0; + while( (this->IdDataSet->Implementation->GetCell(this->Id); + found=c->GetCellDimension()==this->Dim; + this->Id++; + } + if(found) + { + this->Id--; + } + } +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate over cells of `ds' of some dimension `dim'. +// \pre ds_exists: ds!=0 +// \pre valid_dim_range: (dim>=-1) && (dim<=3) +void vtkBridgeCellIteratorOnDataSet::InitWithDataSet(vtkBridgeDataSet *ds, + int dim) +{ + assert("pre: ds_exists" && ds!=0); + assert("pre: valid_dim_range" && (dim>=-1) && (dim<=3)); + + this->Dim=dim; + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,ds); + this->Size=ds->GetNumberOfCells(); + this->Id=this->Size; // at end +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnDataSet.h b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnDataSet.h new file mode 100644 index 0000000..42505d4 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOnDataSet.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOnDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOnDataSet - Iterate over cells of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#ifndef __vtkBridgeCellIteratorOnDataSet_h +#define __vtkBridgeCellIteratorOnDataSet_h + +#include "vtkBridgeCellIteratorStrategy.h" + +class vtkBridgeCell; +class vtkBridgeDataSet; +class vtkBridgeCell; +class vtkIdList; + +class VTK_BRIDGE_EXPORT vtkBridgeCellIteratorOnDataSet : public vtkBridgeCellIteratorStrategy +{ +public: + static vtkBridgeCellIteratorOnDataSet *New(); + vtkTypeRevisionMacro(vtkBridgeCellIteratorOnDataSet, + vtkBridgeCellIteratorStrategy); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no cell at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Cell at current position + // \pre not_at_end: !IsAtEnd() + // \pre c_exists: c!=0 + // THREAD SAFE + void GetCell(vtkGenericAdaptorCell *c); + + // Description: + // Cell at current position. + // NOT THREAD SAFE + // \pre not_at_end: !IsAtEnd() + // \post result_exits: result!=0 + vtkGenericAdaptorCell *GetCell(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_at_end: !IsAtEnd() + void Next(); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate over cells of `ds' of some dimension `dim'. + // \pre ds_exists: ds!=0 + // \pre valid_dim_range: (dim>=-1) && (dim<=3) + void InitWithDataSet(vtkBridgeDataSet *ds, + int dim); + +protected: + vtkBridgeCellIteratorOnDataSet(); + virtual ~vtkBridgeCellIteratorOnDataSet(); + + int Dim; // Dimension of cells over which to iterate (-1 to 3) + + vtkBridgeDataSet *DataSet; // the structure on which the objet iterates. + vtkIdType Id; // the id at current position. + vtkIdType Size; // size of the structure. + vtkBridgeCell *Cell; // cell at current position. + +private: + vtkBridgeCellIteratorOnDataSet(const vtkBridgeCellIteratorOnDataSet&); // Not implemented + void operator=(const vtkBridgeCellIteratorOnDataSet&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOne.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOne.cxx new file mode 100644 index 0000000..ac2284e --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOne.cxx @@ -0,0 +1,279 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOne.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOne - Iterate over cells of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#include "vtkBridgeCellIteratorOne.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeCell.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" + +#include "vtkTriangle.h" +#include "vtkPolygon.h" +#include "vtkLine.h" +#include "vtkPolyLine.h" +#include "vtkVertex.h" +#include "vtkPolyVertex.h" + +vtkCxxRevisionMacro(vtkBridgeCellIteratorOne, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkBridgeCellIteratorOne); + +//----------------------------------------------------------------------------- +void vtkBridgeCellIteratorOne::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOne::vtkBridgeCellIteratorOne() +{ + this->DataSet=0; + this->InternalCell=0; + this->Cell=0; + this->Id=0; + this->cIsAtEnd=0; +// this->DebugOn(); +} + +//----------------------------------------------------------------------------- +vtkBridgeCellIteratorOne::~vtkBridgeCellIteratorOne() +{ + if((this->Cell!=0)&&((this->DataSet!=0)||(this->InternalCell!=0))) + { + // dataset mode or points mode + this->Cell->Delete(); + this->Cell=0; + } + if(this->DataSet!=0) + { + this->DataSet->Delete(); + this->DataSet=0; + } + + if(this->InternalCell!=0) + { + this->InternalCell->Delete(); + this->InternalCell=0; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgeCellIteratorOne::Begin() +{ + this->cIsAtEnd=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no cell at iterator position? (exit condition). +int vtkBridgeCellIteratorOne::IsAtEnd() +{ + return this->cIsAtEnd; +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position +// \pre not_at_end: !IsAtEnd() +// \pre c_exists: c!=0 +// THREAD SAFE +void vtkBridgeCellIteratorOne::GetCell(vtkGenericAdaptorCell *c) +{ + assert("pre: not_at_end" && !this->IsAtEnd()); + assert("pre: c_exists" && c!=0); + + vtkBridgeCell *c2=static_cast(c); + if(this->DataSet!=0) + { + c2->Init(this->DataSet,this->Id); + } + else + { + if(this->InternalCell!=0) + { + c2->InitWithCell(this->InternalCell,this->Id); + } + else + { + c2->DeepCopy(this->Cell); + } + } +} + +//----------------------------------------------------------------------------- +// Description: +// Cell at current position. +// NOT THREAD SAFE +// \pre not_at_end: !IsAtEnd() +// \post result_exits: result!=0 +vtkGenericAdaptorCell *vtkBridgeCellIteratorOne::GetCell() +{ + assert("pre: not_at_end" && !this->IsAtEnd()); + + vtkGenericAdaptorCell *result=this->Cell; + + assert("post: result_exits" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_at_end: !IsAtEnd() +void vtkBridgeCellIteratorOne::Next() +{ + assert("pre: not_off" && !this->IsAtEnd()); + + this->cIsAtEnd=1; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate on one cell `id' of `ds'. +// \pre ds_exists: ds!=0 +// \pre valid_id: (id>=0)&&(id<=ds->GetNumberOfCells()) +void vtkBridgeCellIteratorOne::InitWithOneCell(vtkBridgeDataSet *ds, + vtkIdType cellid) +{ + assert("pre: ds_exists" && ds!=0); + assert("pre: valid_id" && ((cellid>=0)&&(cellid<=ds->GetNumberOfCells()))); + + if((this->Cell!=0)&&(this->DataSet==0)&&(this->InternalCell==0)) + { + // previous mode was InitWithOneCell(vtkBridgeCell *c) +// this->Cell->Delete(); + this->Cell=0; + } + + if(this->Cell==0) + { + // first init or previous mode was InitWithOneCell(vtkBridgeCell *c) + this->Cell=vtkBridgeCell::New(); + } + + vtkSetObjectBodyMacro(InternalCell,vtkCell,0); + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,ds); + this->Id=cellid; + this->cIsAtEnd=1; + this->Cell->Init(this->DataSet,this->Id); +} +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on one cell `c'. +// \pre c_exists: c!=0 +void vtkBridgeCellIteratorOne::InitWithOneCell(vtkBridgeCell *c) +{ + assert("pre: c_exists" && c!=0); + + if((this->Cell!=0)&&((this->DataSet!=0)||(this->InternalCell!=0))) + { + // dataset mode or points mode + this->Cell->Delete(); + } + vtkSetObjectBodyMacro(InternalCell,vtkCell,0); + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); + + this->Cell=c; // no register to prevent reference cycle with vtkBridgeCell + this->Id=c->GetId(); + this->cIsAtEnd=1; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeCell. +// Iterate on a boundary cell (defined by its points `pts' with coordinates +// `coords', dimension `dim' and unique id `cellid') of a cell. +// \pre coords_exist: coords!=0 +// \pre pts_exist: pts!=0 +// \pre valid_dim: dim>=0 && dim<=2 +// \pre valid_points: pts->GetNumberOfIds()>dim +void vtkBridgeCellIteratorOne::InitWithPoints(vtkPoints *coords, + vtkIdList *pts, + int dim, + vtkIdType cellid) +{ + assert("pre: coords_exist" && coords!=0); + assert("pre: pts_exist" && pts!=0); + assert("pre: valid_dim" && dim>=0 && dim<=2); + assert("pre: valid_points" && pts->GetNumberOfIds()>dim); + + + if((this->DataSet==0)&&(this->InternalCell==0)) + { + // previous mode was InitWithOneCell(vtkBridgeCell *c) +// this->Cell->Delete(); + this->Cell=0; + } + + if(this->Cell==0) + { + // first init or previous mode was InitWithOneCell(vtkBridgeCell *c) + this->Cell=vtkBridgeCell::New(); + } + + vtkCell *cell=0; + + switch(dim) + { + case 2: + if (pts->GetNumberOfIds()==3) + { + cell=vtkTriangle::New(); + } + else + { + cell=vtkPolygon::New(); + } + break; + case 1: + // line or polyline + if(pts->GetNumberOfIds()==2) + { + cell=vtkLine::New(); + } + else + { + cell=vtkPolyLine::New(); + } + break; + case 0: + // vertex polyvertex + if(pts->GetNumberOfIds()==1) + { + cell=vtkVertex::New(); + } + else + { + cell=vtkPolyVertex::New(); + } + break; + } + cell->Points=coords; + cell->PointIds=pts; + vtkSetObjectBodyMacro(InternalCell,vtkCell,cell); + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); + this->Id=cellid; + this->cIsAtEnd=1; + this->Cell->InitWithCell(this->InternalCell,this->Id); +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOne.h b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOne.h new file mode 100644 index 0000000..61e4b46 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorOne.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorOne.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorOne - Iterate over one cell only of a dataset. +// .SECTION See Also +// vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorStrategy + +#ifndef __vtkBridgeCellIteratorOne_h +#define __vtkBridgeCellIteratorOne_h + +#include "vtkBridgeCellIteratorStrategy.h" + +class vtkBridgeCell; +class vtkBridgeDataSet; +class vtkBridgeCell; +class vtkIdList; +class vtkPoints; +class vtkCell; + +class VTK_BRIDGE_EXPORT vtkBridgeCellIteratorOne : public vtkBridgeCellIteratorStrategy +{ +public: + static vtkBridgeCellIteratorOne *New(); + vtkTypeRevisionMacro(vtkBridgeCellIteratorOne, + vtkBridgeCellIteratorStrategy); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no cell at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Cell at current position + // \pre not_at_end: !IsAtEnd() + // \pre c_exists: c!=0 + // THREAD SAFE + void GetCell(vtkGenericAdaptorCell *c); + + // Description: + // Cell at current position. + // NOT THREAD SAFE + // \pre not_at_end: !IsAtEnd() + // \post result_exits: result!=0 + vtkGenericAdaptorCell *GetCell(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_at_end: !IsAtEnd() + void Next(); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate on one cell `id' of `ds'. + // \pre ds_exists: ds!=0 + // \pre valid_id: (id>=0)&&(id<=ds->GetNumberOfCells()) + void InitWithOneCell(vtkBridgeDataSet *ds, + vtkIdType cellid); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on one cell `c'. + // \pre c_exists: c!=0 + void InitWithOneCell(vtkBridgeCell *c); + + // Description: + // Used internally by vtkBridgeCell. + // Iterate on a boundary cell (defined by its points `pts' with coordinates + // `coords', dimension `dim' and unique id `cellid') of a cell. + // \pre coords_exist: coords!=0 + // \pre pts_exist: pts!=0 + // \pre valid_dim: dim>=0 && dim<=2 + // \pre valid_points: pts->GetNumberOfIds()>dim + void InitWithPoints(vtkPoints *coords, + vtkIdList *pts, + int dim, + vtkIdType cellid); + +protected: + vtkBridgeCellIteratorOne(); + virtual ~vtkBridgeCellIteratorOne(); + + int cIsAtEnd; + vtkBridgeDataSet *DataSet; // the structure on which the objet iterates. + vtkIdType Id; // the id at current position. + vtkBridgeCell *Cell; // cell at current position. + vtkCell *InternalCell; + +private: + vtkBridgeCellIteratorOne(const vtkBridgeCellIteratorOne&); // Not implemented + void operator=(const vtkBridgeCellIteratorOne&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorStrategy.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorStrategy.cxx new file mode 100644 index 0000000..c4c8235 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorStrategy.cxx @@ -0,0 +1,46 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorStrategy.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorStrategy - Interface used by vtkBridgeCellIterator +// vtkBridgeCellIterator has different behaviors depending on the way it is +// initialized. vtkBridgeCellIteratorStrategy is the interface for one of those +// behaviors. Concrete classes are vtkBridgeCellIteratorOnDataSet, +// vtkBridgeCellIteratorOnDataSetBoundaries, +// vtkBridgeCellIteratorOnCellBoundaries, +// vtkBridgeCellIteratorOnCellNeighbors, +// .SECTION See Also +// vtkCellIterator, vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorOnDataSet, vtkBridgeCellIteratorOnDataSetBoundaries, vtkBridgeCellIteratorOnCellBoundaries, vtkBridgeCellIteratorOnCellNeighbors + +#include "vtkBridgeCellIteratorStrategy.h" + +#include + +vtkCxxRevisionMacro(vtkBridgeCellIteratorStrategy, "$Revision: 1.1 $"); + +//----------------------------------------------------------------------------- +void vtkBridgeCellIteratorStrategy::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +// Description: +// Create an empty cell. NOT USED +// \post result_exists: result!=0 +vtkGenericAdaptorCell *vtkBridgeCellIteratorStrategy::NewCell() +{ + assert("check: should not be called: see vtkBridgeCellIterator::NewCell()" + &&0); + return 0; +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorStrategy.h b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorStrategy.h new file mode 100644 index 0000000..05d5baa --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeCellIteratorStrategy.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeCellIteratorStrategy.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeCellIteratorStrategy - Interface used by vtkBridgeCellIterator +// vtkBridgeCellIterator has different behaviors depending on the way it is +// initialized. vtkBridgeCellIteratorStrategy is the interface for one of those +// behaviors. Concrete classes are vtkBridgeCellIteratorOnDataSet, +// vtkBridgeCellIteratorOnDataSetBoundaries, +// vtkBridgeCellIteratorOnCellBoundaries, +// vtkBridgeCellIteratorOnCellNeighbors, +// .SECTION See Also +// vtkGenericCellIterator, vtkBridgeCellIterator, vtkBridgeDataSet, vtkBridgeCellIteratorOnDataSet, vtkBridgeCellIteratorOnDataSetBoundaries, vtkBridgeCellIteratorOnCellBoundaries, vtkBridgeCellIteratorOnCellNeighbors + +#ifndef __vtkBridgeCellIteratorStrategy_h +#define __vtkBridgeCellIteratorStrategy_h + +#include "vtkBridgeExport.h" +#include "vtkGenericCellIterator.h" + +class vtkBridgeCell; +class vtkBridgeDataSet; +class vtkBridgeCell; +class vtkIdList; + +class VTK_BRIDGE_EXPORT vtkBridgeCellIteratorStrategy : public vtkGenericCellIterator +{ +public: + vtkTypeRevisionMacro(vtkBridgeCellIteratorStrategy,vtkGenericCellIterator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create an empty cell. NOT USED + // \post result_exists: result!=0 + vtkGenericAdaptorCell *NewCell(); + +protected: + vtkBridgeCellIteratorStrategy() {} + virtual ~vtkBridgeCellIteratorStrategy() {} + +private: + vtkBridgeCellIteratorStrategy(const vtkBridgeCellIteratorStrategy&); // Not implemented + void operator=(const vtkBridgeCellIteratorStrategy&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeDataSet.cxx b/GenericFiltering/Testing/Cxx/vtkBridgeDataSet.cxx new file mode 100644 index 0000000..6539007 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeDataSet.cxx @@ -0,0 +1,518 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeDataSet - Implementation of vtkGenericDataSet. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. + +#include "vtkBridgeDataSet.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkDataSet.h" +#include "vtkCellTypes.h" +#include "vtkCell.h" +#include "vtkBridgeCellIterator.h" +#include "vtkBridgePointIterator.h" +#include "vtkBridgeCell.h" +#include "vtkGenericCell.h" +#include "vtkMath.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkBridgeAttribute.h" +#include "vtkGenericCellTessellator.h" +#include "vtkGenericEdgeTable.h" +#include "vtkSimpleCellTessellator.h" + +vtkCxxRevisionMacro(vtkBridgeDataSet, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkBridgeDataSet); + +//---------------------------------------------------------------------------- +// Default constructor. +vtkBridgeDataSet::vtkBridgeDataSet( ) +{ + this->Implementation = 0; + this->Types=vtkCellTypes::New(); + this->Tessellator=vtkSimpleCellTessellator::New(); +} + +//---------------------------------------------------------------------------- +vtkBridgeDataSet::~vtkBridgeDataSet( ) +{ + if(this->Implementation!=0) + { + this->Implementation->Delete(); + } + this->Types->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkBridgeDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "implementation: "; + if(this->Implementation==0) + { + os << 0 << endl; + } + else + { + os << endl; + this->Implementation->PrintSelf(os,indent.GetNextIndent()); + } +} + +//---------------------------------------------------------------------------- +// Description: +// Set the dataset that will be manipulated through the adaptor interface. +// \pre ds_exists: ds!=0 +void vtkBridgeDataSet::SetDataSet(vtkDataSet *ds) +{ + int i; + int c; + vtkPointData *pd; + vtkCellData *cd; + vtkBridgeAttribute *a; + + vtkSetObjectBodyMacro(Implementation,vtkDataSet,ds); + // refresh the attribute collection + this->Attributes->Reset(); + if(ds!=0) + { + // point data + pd=ds->GetPointData(); + c=pd->GetNumberOfArrays(); + i=0; + while(iInitWithPointData(pd,i); + this->Attributes->InsertNextAttribute(a); + a->Delete(); + ++i; + } + // same thing for cell data. + cd=ds->GetCellData(); + c=cd->GetNumberOfArrays(); + i=0; + while(iInitWithCellData(cd,i); + this->Attributes->InsertNextAttribute(a); + a->Delete(); + ++i; + } + this->Tessellator->Initialize(this); + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Description: +// Number of points composing the dataset. See NewPointIterator for more +// details. +// \post positive_result: result>=0 +vtkIdType vtkBridgeDataSet::GetNumberOfPoints() +{ + vtkIdType result=0; + if(this->Implementation!=0) + { + result=Implementation->GetNumberOfPoints(); + } + assert("post: positive_result" && result>=0); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Compute the number of cells for each dimension and the list of types of +// cells. +// \pre implementation_exists: this->Implementation!=0 +void vtkBridgeDataSet::ComputeNumberOfCellsAndTypes() +{ + unsigned char type; + vtkIdType cellId; + vtkIdType numCells; + vtkCell *c; + + if ( this->GetMTime() > this->ComputeNumberOfCellsTime ) // cache is obsolete + { + numCells=this->GetNumberOfCells(); + this->NumberOf0DCells=0; + this->NumberOf1DCells=0; + this->NumberOf2DCells=0; + this->NumberOf3DCells=0; + + this->Types->Reset(); + + if(this->Implementation!=0) + { + cellId=0; + while(cellIdImplementation->GetCell(cellId); + switch(c->GetCellDimension()) + { + case 0: + this->NumberOf0DCells++; + break; + case 1: + this->NumberOf1DCells++; + break; + case 2: + this->NumberOf2DCells++; + break; + case 3: + this->NumberOf3DCells++; + break; + } + type=c->GetCellType(); + if(!Types->IsType(type)) + { + Types->InsertNextType(type); + } + cellId++; + } + } + + this->ComputeNumberOfCellsTime.Modified(); // cache is up-to-date + assert("check: positive_dim0" && this->NumberOf0DCells>=0); + assert("check: valid_dim0" && this->NumberOf0DCells<=numCells); + assert("check: positive_dim1" && this->NumberOf1DCells>=0); + assert("check: valid_dim1" && this->NumberOf1DCells<=numCells); + assert("check: positive_dim2" && this->NumberOf2DCells>=0); + assert("check: valid_dim2" && this->NumberOf2DCells<=numCells); + assert("check: positive_dim3" && this->NumberOf3DCells>=0); + assert("check: valid_dim3" && this->NumberOf3DCells<=numCells); + } +} + +//---------------------------------------------------------------------------- +// Description: +// Number of cells that explicitly define the dataset. See NewCellIterator +// for more details. +// \pre valid_dim_range: (dim>=-1) && (dim<=3) +// \post positive_result: result>=0 +vtkIdType vtkBridgeDataSet::GetNumberOfCells(int dim) +{ + assert("pre: valid_dim_range" && (dim>=-1) && (dim<=3)); + + vtkIdType result=0; + if(this->Implementation!=0) + { + if(dim==-1) + { + result=this->Implementation->GetNumberOfCells(); + } + else + { + ComputeNumberOfCellsAndTypes(); + switch(dim) + { + case 0: + result=this->NumberOf0DCells; + break; + case 1: + result=this->NumberOf1DCells; + break; + case 2: + result=this->NumberOf2DCells; + break; + case 3: + result=this->NumberOf3DCells; + break; + } + } + } + + assert("post: positive_result" && result>=0); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Return -1 if the dataset is explicitly defined by cells of several +// dimensions or if there is no cell. If the dataset is explicitly defined by +// cells of a unique dimension, return this dimension. +// \post valid_range: (result>=-1) && (result<=3) +int vtkBridgeDataSet::GetCellDimension() +{ + int result=0; + int accu=0; + + this->ComputeNumberOfCellsAndTypes(); + + if(this->NumberOf0DCells!=0) + { + accu++; + result=0; + } + if(this->NumberOf1DCells!=0) + { + accu++; + result=1; + } + if(this->NumberOf2DCells!=0) + { + accu++; + result=2; + } + if(this->NumberOf3DCells!=0) + { + accu++; + result=3; + } + if(accu!=1) // no cells at all or several dimensions + { + result=-1; + } + assert("post: valid_range" && (result>=-1) && (result<=3)); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Get a list of types of cells in a dataset. The list consists of an array +// of types (not necessarily in any order), with a single entry per type. +// For example a dataset 5 triangles, 3 lines, and 100 hexahedra would +// result a list of three entries, corresponding to the types VTK_TRIANGLE, +// VTK_LINE, and VTK_HEXAHEDRON. +// THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND +// THE DATASET IS NOT MODIFIED +// \pre types_exist: types!=0 +void vtkBridgeDataSet::GetCellTypes(vtkCellTypes *types) +{ + assert("pre: types_exist" && types!=0); + + int i; + int c; + this->ComputeNumberOfCellsAndTypes(); + + // copy from `this->Types' to `types'. + types->Reset(); + c=this->Types->GetNumberOfTypes(); + i=0; + while(iInsertNextType(this->Types->GetCellType(i)); + ++i; + } +} + +//---------------------------------------------------------------------------- +// Description: +// Cells of dimension `dim' (or all dimensions if -1) that explicitly define +// the dataset. For instance, it will return only tetrahedra if the mesh is +// defined by tetrahedra. If the mesh is composed of two parts, one with +// tetrahedra and another part with triangles, it will return both, but will +// not return edges and vertices. +// \pre valid_dim_range: (dim>=-1) && (dim<=3) +// \post result_exists: result!=0 +vtkGenericCellIterator *vtkBridgeDataSet::NewCellIterator(int dim) +{ + assert("pre: valid_dim_range" && (dim>=-1) && (dim<=3)); + + vtkBridgeCellIterator *result=vtkBridgeCellIterator::New(); + result->InitWithDataSet(this,dim); // vtkBridgeCellIteratorOnDataSetCells + + assert("post: result_exists" && result!=0); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Boundaries of dimension `dim' (or all dimensions if -1) of the dataset. +// If `exteriorOnly' is true, only the exterior boundaries of the dataset +// will be returned, otherwise it will return exterior and interior +// boundaries. +// \pre valid_dim_range: (dim>=-1) && (dim<=2) +// \post result_exists: result!=0 +vtkGenericCellIterator *vtkBridgeDataSet::NewBoundaryIterator(int dim, + int exteriorOnly) +{ + assert("pre: valid_dim_range" && (dim>=-1) && (dim<=2)); + + vtkBridgeCellIterator *result=vtkBridgeCellIterator::New(); + result->InitWithDataSetBoundaries(this,dim,exteriorOnly); //vtkBridgeCellIteratorOnDataSetBoundaries(dim,exterior_only); + + assert("post: result_exists" && result!=0); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Points composing the dataset; they can be on a vertex or isolated. +// \post result_exists: result!=0 +vtkGenericPointIterator *vtkBridgeDataSet::NewPointIterator() +{ + vtkBridgePointIterator *result=vtkBridgePointIterator::New(); + result->InitWithDataSet(this); + assert("post: result_exists" && result!=0); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Estimated size needed after tessellation (or special operation) +vtkIdType vtkBridgeDataSet::GetEstimatedSize() +{ + return this->GetNumberOfPoints()*this->GetNumberOfCells(); +} + +//---------------------------------------------------------------------------- +// Description: +// Locate closest cell to position `x' (global coordinates) with respect to +// a tolerance squared `tol2' and an initial guess `cell' (if valid). The +// result consists in the `cell', the `subId' of the sub-cell (0 if primary +// cell), the parametric coordinates `pcoord' of the position. It returns +// whether the position is inside the cell or not. Tolerance is used to +// control how close the point is to be considered "in" the cell. +// THIS METHOD IS NOT THREAD SAFE. +// \pre not_empty: GetNumberOfCells()>0 +// \pre cell_exists: cell!=0 +// \pre positive_tolerance: tol2>0 +// \post clamped_pcoords: result implies (0<=pcoords[0]<=1 && ) + +int vtkBridgeDataSet::FindCell(double x[3], + vtkGenericCellIterator* &cell, + double tol2, + int &subId, + double pcoords[3]) +{ + assert("pre: not_empty" && GetNumberOfCells()>0); + assert("pre: cell_exists" && cell!=0); + assert("pre: positive_tolerance" && tol2>0); + + vtkIdType cellid; + vtkBridgeCell *c; + vtkBridgeCellIterator *it=static_cast(cell); + vtkCell *c2; + + double *ignoredWeights=new double[this->Implementation->GetMaxCellSize()]; + + if(cell->IsAtEnd()) + { + cellid=this->Implementation->FindCell(x,0,0,tol2,subId,pcoords, + ignoredWeights); + } + else + { + c=static_cast(cell->GetCell()); + c2=c->Cell; // bridge + cellid=c->GetId(); // adaptor + cellid=this->Implementation->FindCell(x,c2,cellid,tol2,subId,pcoords, + ignoredWeights); + } + delete [] ignoredWeights; + if(cellid>=0) + { + it->InitWithOneCell(this,cellid); // at end + it->Begin(); + // clamp: + int i=0; + while(i<3) + { + if(pcoords[i]<0) + { + pcoords[i]=0; + } + else if(pcoords[i]>1) + { + pcoords[i]=1; + } + ++i; + } + } + + // A=>B: !A || B + // result => clamped pcoords + assert("post: clamped_pcoords" && ((cellid<0)||(pcoords[0]>=0 + && pcoords[0]<=1 + && pcoords[1]>=0 + && pcoords[1]<=1 + && pcoords[2]>=0 + && pcoords[2]<=1))); + + return cellid>=0; // bool +} + +//---------------------------------------------------------------------------- +// Description: +// Locate closest point `p' to position `x' (global coordinates) +// \pre not_empty: GetNumberOfPoints()>0 +// \pre p_exists: p!=0 +void vtkBridgeDataSet::FindPoint(double x[3], + vtkGenericPointIterator *p) +{ + assert("pre: not_empty" && GetNumberOfPoints()>0); + assert("pre: p_exists" && p!=0); + vtkBridgePointIterator *bp=static_cast(p); + + if(this->Implementation!=0) + { + vtkIdType pt=this->Implementation->FindPoint(x); + bp->InitWithOnePoint(this,pt); + } + else + { + bp->InitWithOnePoint(this,-1); + } +} + +//---------------------------------------------------------------------------- +// Description: +// Datasets are composite objects and need to check each part for MTime. +unsigned long int vtkBridgeDataSet::GetMTime() +{ + unsigned long result; + unsigned long mtime; + + result = vtkGenericDataSet::GetMTime(); + + if(this->Implementation!=0) + { + mtime = this->Implementation->GetMTime(); + result = ( mtime > result ? mtime : result ); + } + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Compute the geometry bounding box. +void vtkBridgeDataSet::ComputeBounds() +{ + double *bounds; + + if ( this->GetMTime() > this->ComputeTime ) + { + if(this->Implementation!=0) + { + this->Implementation->ComputeBounds(); + this->ComputeTime.Modified(); + bounds=this->Implementation->GetBounds(); + memcpy(this->Bounds,bounds,sizeof(double)*6); + } + else + { + vtkMath::UninitializeBounds(this->Bounds); + } + this->ComputeTime.Modified(); + } +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeDataSet.h b/GenericFiltering/Testing/Cxx/vtkBridgeDataSet.h new file mode 100644 index 0000000..feeba48 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeDataSet.h @@ -0,0 +1,167 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeDataSet - Implementation of vtkGenericDataSet. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. + +#ifndef __vtkBridgeDataSet_h +#define __vtkBridgeDataSet_h + +#include "vtkBridgeExport.h" +#include "vtkGenericDataSet.h" + +class vtkDataSet; + +class VTK_BRIDGE_EXPORT vtkBridgeDataSet : public vtkGenericDataSet +{ +public: + static vtkBridgeDataSet *New(); + vtkTypeRevisionMacro(vtkBridgeDataSet,vtkGenericDataSet); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the dataset that will be manipulated through the adaptor interface. + // \pre ds_exists: ds!=0 + void SetDataSet(vtkDataSet *ds); + // Description: + // Number of points composing the dataset. See NewPointIterator for more + // details. + // \post positive_result: result>=0 + vtkIdType GetNumberOfPoints(); + + // Description: + // Number of cells that explicitly define the dataset. See NewCellIterator + // for more details. + // \pre valid_dim_range: (dim>=-1) && (dim<=3) + // \post positive_result: result>=0 + vtkIdType GetNumberOfCells(int dim=-1); + + // Description: + // Return -1 if the dataset is explicitly defined by cells of several + // dimensions or if there is no cell. If the dataset is explicitly defined by + // cells of a unique + // dimension, return this dimension. + // \post valid_range: (result>=-1) && (result<=3) + int GetCellDimension(); + + // Description: + // Get a list of types of cells in a dataset. The list consists of an array + // of types (not necessarily in any order), with a single entry per type. + // For example a dataset 5 triangles, 3 lines, and 100 hexahedra would + // result a list of three entries, corresponding to the types VTK_TRIANGLE, + // VTK_LINE, and VTK_HEXAHEDRON. + // THIS METHOD IS THREAD SAFE IF FIRST CALLED FROM A SINGLE THREAD AND + // THE DATASET IS NOT MODIFIED + // \pre types_exist: types!=0 + void GetCellTypes(vtkCellTypes *types); + + // Description: + // Cells of dimension `dim' (or all dimensions if -1) that explicitly define + // the dataset. For instance, it will return only tetrahedra if the mesh is + // defined by tetrahedra. If the mesh is composed of two parts, one with + // tetrahedra and another part with triangles, it will return both, but will + // not return edges and vertices. + // \pre valid_dim_range: (dim>=-1) && (dim<=3) + // \post result_exists: result!=0 + vtkGenericCellIterator *NewCellIterator(int dim=-1); + + // Description: + // Boundaries of dimension `dim' (or all dimensions if -1) of the dataset. + // If `exteriorOnly' is true, only the exterior boundaries of the dataset + // will be returned, otherwise it will return exterior and interior + // boundaries. + // \pre valid_dim_range: (dim>=-1) && (dim<=2) + // \post result_exists: result!=0 + vtkGenericCellIterator *NewBoundaryIterator(int dim=-1, + int exteriorOnly=0); + + // Description: + // Points composing the dataset; they can be on a vertex or isolated. + // \post result_exists: result!=0 + vtkGenericPointIterator *NewPointIterator(); + + + // Description: + // Estimated size needed after tessellation (or special operation) + vtkIdType GetEstimatedSize(); + + // Description: + // Locate closest cell to position `x' (global coordinates) with respect to + // a tolerance squared `tol2' and an initial guess `cell' (if valid). The + // result consists in the `cell', the `subId' of the sub-cell (0 if primary + // cell), the parametric coordinates `pcoord' of the position. It returns + // whether the position is inside the cell or not. Tolerance is used to + // control how close the point is to be considered "in" the cell. + // THIS METHOD IS NOT THREAD SAFE. + // \pre not_empty: GetNumberOfCells()>0 + // \pre cell_exists: cell!=0 + // \pre positive_tolerance: tol2>0 + int FindCell(double x[3], + vtkGenericCellIterator* &cell, + double tol2, + int &subId, + double pcoords[3]); + + // Description: + // Locate closest point `p' to position `x' (global coordinates) + // \pre not_empty: GetNumberOfPoints()>0 + // \pre p_exists: p!=0 + void FindPoint(double x[3], + vtkGenericPointIterator *p); + + // Description: + // Datasets are composite objects and need to check each part for MTime. + unsigned long int GetMTime(); + + // Description: + // Compute the geometry bounding box. + void ComputeBounds(); + +protected: + // Constructor with default bounds (0,1, 0,1, 0,1). + vtkBridgeDataSet(); + virtual ~vtkBridgeDataSet(); + + //BTX + friend class vtkBridgeCell; + friend class vtkBridgeCellIterator; + friend class vtkBridgeCellIteratorOnDataSet; + friend class vtkBridgeCellIteratorOne; + friend class vtkBridgePointIterator; + friend class vtkBridgePointIteratorOnCell; + friend class vtkBridgePointIteratorOnDataSet; + friend class vtkBridgePointIteratorOne; + //ETX + + // Description: + // Compute the number of cells for each dimension and the list of types of + // cells. + void ComputeNumberOfCellsAndTypes(); + + vtkDataSet *Implementation; + vtkIdType NumberOf0DCells; + vtkIdType NumberOf1DCells; + vtkIdType NumberOf2DCells; + vtkIdType NumberOf3DCells; + vtkCellTypes *Types; + vtkTimeStamp ComputeNumberOfCellsTime; // for number of cells and cell types + +private: + vtkBridgeDataSet(const vtkBridgeDataSet&); // Not implemented. + void operator=(const vtkBridgeDataSet&); // Not implemented. +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgeExport.h b/GenericFiltering/Testing/Cxx/vtkBridgeExport.h new file mode 100644 index 0000000..dd2431f --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgeExport.h @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgeExport.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgeExport - manage Windows system differences +// .SECTION Description +// The vtkBridgeExport captures some system differences between Unix and +// Windows operating systems. + +#ifndef __vtkBridgeExport_h +#define __vtkBridgeExport_h + +#include "vtkSystemIncludes.h" + +#if 1 +# define VTK_BRIDGE_EXPORT +#else + +#if defined(WIN32) && defined(VTK_BUILD_SHARED_LIBS) + + #if defined(vtkBridge_EXPORTS) + #define VTK_BRIDGE_EXPORT __declspec( dllexport ) + #else + #define VTK_BRIDGE_EXPORT __declspec( dllimport ) + #endif +#else + #define VTK_BRIDGE_EXPORT +#endif + +#endif //#if 1 + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIterator.cxx b/GenericFiltering/Testing/Cxx/vtkBridgePointIterator.cxx new file mode 100644 index 0000000..9b086d4 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIterator.cxx @@ -0,0 +1,176 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIterator - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#include "vtkBridgePointIterator.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" + +#include "vtkBridgePointIteratorOnDataSet.h" +#include "vtkBridgePointIteratorOne.h" +#include "vtkBridgePointIteratorOnCell.h" + +vtkCxxRevisionMacro(vtkBridgePointIterator, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkBridgePointIterator); + +//----------------------------------------------------------------------------- +// Description: +// Default constructor. +vtkBridgePointIterator::vtkBridgePointIterator() +{ + this->CurrentIterator=0; + this->IteratorOnDataSet=vtkBridgePointIteratorOnDataSet::New(); + this->IteratorOne=vtkBridgePointIteratorOne::New(); + this->IteratorOnCell=vtkBridgePointIteratorOnCell::New(); +} + +//----------------------------------------------------------------------------- +// Description: +// Destructor. +vtkBridgePointIterator::~vtkBridgePointIterator() +{ + this->IteratorOnDataSet->Delete(); + this->IteratorOne->Delete(); + this->IteratorOnCell->Delete(); +} + +//----------------------------------------------------------------------------- +void vtkBridgePointIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgePointIterator::Begin() +{ + if(this->CurrentIterator!=0) + { + this->CurrentIterator->Begin(); + } +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no point at iterator position? (exit condition). +int vtkBridgePointIterator::IsAtEnd() +{ + int result=1; + + if(this->CurrentIterator!=0) + { + result=this->CurrentIterator->IsAtEnd(); + } + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_off: !IsAtEnd() +void vtkBridgePointIterator::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + this->CurrentIterator->Next(); +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \post result_exists: result!=0 +double *vtkBridgePointIterator::GetPosition() +{ + assert("pre: not_off" && !IsAtEnd()); + + double *result=this->CurrentIterator->GetPosition(); + + assert("post: result_exists" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \pre x_exists: x!=0 +void vtkBridgePointIterator::GetPosition(double x[3]) +{ + assert("pre: not_off" && !IsAtEnd()); + assert("pre: x_exists" && x!=0); + this->CurrentIterator->GetPosition(x); +} + +//----------------------------------------------------------------------------- +// Description: +// Unique identifier for the point, could be non-contiguous +// \pre not_off: !IsAtEnd() +vtkIdType vtkBridgePointIterator::GetId() +{ + assert("pre: not_off" && !IsAtEnd()); + + return this->CurrentIterator->GetId(); +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate over points of `ds'. +// \pre ds_exists: ds!=0 +void vtkBridgePointIterator::InitWithDataSet(vtkBridgeDataSet *ds) +{ + assert("pre: ds_exists" && ds!=0); + + this->IteratorOnDataSet->InitWithDataSet(ds); + this->CurrentIterator=this->IteratorOnDataSet; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate over one point of identifier `id' on dataset `ds'. +// \pre ds_can_be_null: ds!=0 || ds==0 +// \pre valid_id: vtkImplies(ds!=0,(id>=0)&&(id<=ds->GetNumberOfCells())) +void vtkBridgePointIterator::InitWithOnePoint(vtkBridgeDataSet *ds, + vtkIdType id) +{ + assert("pre: valid_id" && + ((!ds!=0)|| ((id>=0)&&(id<=ds->GetNumberOfCells())))); // A=>B: !A||B + + this->IteratorOne->InitWithOnePoint(ds,id); + this->CurrentIterator=this->IteratorOne; +} + +//----------------------------------------------------------------------------- +// Description: +// The iterator will iterate over the point of a cell +// \pre cell_exists: cell!=0 +void vtkBridgePointIterator::InitWithCell(vtkBridgeCell *cell) +{ + assert("pre: cell_exists" && cell!=0); + + this->IteratorOnCell->InitWithCell(cell); + this->CurrentIterator=this->IteratorOnCell; +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIterator.h b/GenericFiltering/Testing/Cxx/vtkBridgePointIterator.h new file mode 100644 index 0000000..fbee7a0 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIterator.h @@ -0,0 +1,110 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIterator - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#ifndef __vtkBridgePointIterator_h +#define __vtkBridgePointIterator_h + +#include "vtkBridgeExport.h" +#include "vtkGenericPointIterator.h" + +class vtkBridgeDataSet; +class vtkBridgeCell; +class vtkBridgePointIteratorOnDataSet; +class vtkBridgePointIteratorOne; +class vtkBridgePointIteratorOnCell; + + +class VTK_BRIDGE_EXPORT vtkBridgePointIterator : public vtkGenericPointIterator +{ +public: + static vtkBridgePointIterator *New(); + vtkTypeRevisionMacro(vtkBridgePointIterator,vtkGenericPointIterator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no point at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_off: !IsAtEnd() + void Next(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \post result_exists: result!=0 + double *GetPosition(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \pre x_exists: x!=0 + void GetPosition(double x[3]); + + // Description: + // Unique identifier for the point, could be non-contiguous + // \pre not_off: !IsAtEnd() + vtkIdType GetId(); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate over points of `ds'. + // \pre ds_exists: ds!=0 + void InitWithDataSet(vtkBridgeDataSet *ds); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate over one point of identifier `id' on dataset `ds'. + // \pre ds_can_be_null: ds!=0 || ds==0 + // \pre valid_id: vtkImplies(ds!=0,(id>=0)&&(id<=ds->GetNumberOfCells())) + void InitWithOnePoint(vtkBridgeDataSet *ds, + vtkIdType id); + + // Description: + // The iterator will iterate over the point of a cell + // \pre cell_exists: cell!=0 + void InitWithCell(vtkBridgeCell *cell); + +protected: + // Description: + // Default constructor. + vtkBridgePointIterator(); + + // Description: + // Destructor. + virtual ~vtkBridgePointIterator(); + + vtkGenericPointIterator *CurrentIterator; + vtkBridgePointIteratorOnDataSet *IteratorOnDataSet; + vtkBridgePointIteratorOne *IteratorOne; + vtkBridgePointIteratorOnCell *IteratorOnCell; + +private: + vtkBridgePointIterator(const vtkBridgePointIterator&); // Not implemented + void operator=(const vtkBridgePointIterator&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnCell.cxx b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnCell.cxx new file mode 100644 index 0000000..80adfa7 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnCell.cxx @@ -0,0 +1,137 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIteratorOnCell.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIteratorOnCell - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#include "vtkBridgePointIteratorOnCell.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" +#include "vtkIdList.h" +#include "vtkBridgeCell.h" +#include "vtkCell.h" + +vtkCxxRevisionMacro(vtkBridgePointIteratorOnCell, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkBridgePointIteratorOnCell); + +//----------------------------------------------------------------------------- +// Description: +// Default constructor. +vtkBridgePointIteratorOnCell::vtkBridgePointIteratorOnCell() +{ + this->DataSet=0; + this->Cursor=0; + this->PtIds=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Destructor. +vtkBridgePointIteratorOnCell::~vtkBridgePointIteratorOnCell() +{ + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); +} + +//----------------------------------------------------------------------------- +void vtkBridgePointIteratorOnCell::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgePointIteratorOnCell::Begin() +{ + if(this->PtIds!=0) + { + this->Cursor=0; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no point at iterator position? (exit condition). +int vtkBridgePointIteratorOnCell::IsAtEnd() +{ + return (this->PtIds==0)||(this->Cursor>=this->PtIds->GetNumberOfIds()); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_off: !IsAtEnd() +void vtkBridgePointIteratorOnCell::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + this->Cursor++; +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \post result_exists: result!=0 +double *vtkBridgePointIteratorOnCell::GetPosition() +{ + assert("pre: not_off" && !IsAtEnd()); + + double *result=this->DataSet->Implementation->GetPoint(this->PtIds->GetId(this->Cursor)); + + assert("post: result_exists" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \pre x_exists: x!=0 +void vtkBridgePointIteratorOnCell::GetPosition(double x[3]) +{ + assert("pre: not_off" && !IsAtEnd()); + assert("pre: x_exists" && x!=0); + this->DataSet->Implementation->GetPoint(this->PtIds->GetId(this->Cursor),x); +} + +//----------------------------------------------------------------------------- +// Description: +// Unique identifier for the point, could be non-contiguous +// \pre not_off: !IsAtEnd() +vtkIdType vtkBridgePointIteratorOnCell::GetId() +{ + assert("pre: not_off" && !IsAtEnd()); + + return this->PtIds->GetId(this->Cursor); +} + +//----------------------------------------------------------------------------- +// Description: +// The iterator will iterate over the point of a cell +// \pre cell_exists: cell!=0 +void vtkBridgePointIteratorOnCell::InitWithCell(vtkBridgeCell *cell) +{ + assert("pre: cell_exists" && cell!=0); + + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,cell->DataSet); + this->PtIds = cell->Cell->GetPointIds(); +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnCell.h b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnCell.h new file mode 100644 index 0000000..ee97336 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnCell.h @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIteratorOnCell.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIterator - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#ifndef __vtkBridgePointIteratorOnCell_h +#define __vtkBridgePointIteratorOnCell_h + +#include "vtkBridgeExport.h" +#include "vtkGenericPointIterator.h" + +class vtkBridgeDataSet; +class vtkBridgeCell; +class vtkIdList; + +class VTK_BRIDGE_EXPORT vtkBridgePointIteratorOnCell : public vtkGenericPointIterator +{ +public: + static vtkBridgePointIteratorOnCell *New(); + vtkTypeRevisionMacro(vtkBridgePointIteratorOnCell,vtkGenericPointIterator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no point at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_off: !IsAtEnd() + void Next(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \post result_exists: result!=0 + double *GetPosition(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \pre x_exists: x!=0 + void GetPosition(double x[3]); + + // Description: + // Unique identifier for the point, could be non-contiguous + // \pre not_off: !IsAtEnd() + vtkIdType GetId(); + + // Description: + // The iterator will iterate over the point of a cell + // \pre cell_exists: cell!=0 + void InitWithCell(vtkBridgeCell *cell); + +protected: + // Description: + // Default constructor. + vtkBridgePointIteratorOnCell(); + + // Description: + // Destructor. + virtual ~vtkBridgePointIteratorOnCell(); + + vtkBridgeDataSet *DataSet; // the structure on which the objet iterates. + vtkIdType Cursor; // current position + + vtkIdList *PtIds; // list of points of the cell + +private: + vtkBridgePointIteratorOnCell(const vtkBridgePointIteratorOnCell&); // Not implemented + void operator=(const vtkBridgePointIteratorOnCell&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnDataSet.cxx b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnDataSet.cxx new file mode 100644 index 0000000..72aae67 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnDataSet.cxx @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIteratorOnDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIteratorOnDataSet - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#include "vtkBridgePointIteratorOnDataSet.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" + +vtkCxxRevisionMacro(vtkBridgePointIteratorOnDataSet, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkBridgePointIteratorOnDataSet); + +//----------------------------------------------------------------------------- +// Description: +// Default constructor. +vtkBridgePointIteratorOnDataSet::vtkBridgePointIteratorOnDataSet() +{ + this->DataSet=0; + this->Size=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Destructor. +vtkBridgePointIteratorOnDataSet::~vtkBridgePointIteratorOnDataSet() +{ + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); +} + +//----------------------------------------------------------------------------- +void vtkBridgePointIteratorOnDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgePointIteratorOnDataSet::Begin() +{ + this->Id=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no point at iterator position? (exit condition). +int vtkBridgePointIteratorOnDataSet::IsAtEnd() +{ + return (this->Id<0) || (this->Id>=this->Size); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_off: !IsAtEnd() +void vtkBridgePointIteratorOnDataSet::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + this->Id++; +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \post result_exists: result!=0 +double *vtkBridgePointIteratorOnDataSet::GetPosition() +{ + assert("pre: not_off" && !IsAtEnd()); + + double *result=this->DataSet->Implementation->GetPoint(this->Id); + + assert("post: result_exists" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \pre x_exists: x!=0 +void vtkBridgePointIteratorOnDataSet::GetPosition(double x[3]) +{ + assert("pre: not_off" && !IsAtEnd()); + assert("pre: x_exists" && x!=0); + this->DataSet->Implementation->GetPoint(this->Id,x); +} + +//----------------------------------------------------------------------------- +// Description: +// Unique identifier for the point, could be non-contiguous +// \pre not_off: !IsAtEnd() +vtkIdType vtkBridgePointIteratorOnDataSet::GetId() +{ + assert("pre: not_off" && !IsAtEnd()); + + return this->Id; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate over points of `ds'. +// \pre ds_exists: ds!=0 +void vtkBridgePointIteratorOnDataSet::InitWithDataSet(vtkBridgeDataSet *ds) +{ + assert("pre: ds_exists" && ds!=0); + + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,ds); + this->Size=ds->GetNumberOfPoints(); +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnDataSet.h b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnDataSet.h new file mode 100644 index 0000000..dda674e --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOnDataSet.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIteratorOnDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIteratorOnDataSet - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#ifndef __vtkBridgePointIteratorOnDataSet_h +#define __vtkBridgePointIteratorOnDataSet_h + +#include "vtkBridgeExport.h" +#include "vtkGenericPointIterator.h" + +class vtkBridgeDataSet; + +class VTK_BRIDGE_EXPORT vtkBridgePointIteratorOnDataSet : public vtkGenericPointIterator +{ +public: + static vtkBridgePointIteratorOnDataSet *New(); + vtkTypeRevisionMacro(vtkBridgePointIteratorOnDataSet,vtkGenericPointIterator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no point at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_off: !IsAtEnd() + void Next(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \post result_exists: result!=0 + double *GetPosition(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \pre x_exists: x!=0 + void GetPosition(double x[3]); + + // Description: + // Unique identifier for the point, could be non-contiguous + // \pre not_off: !IsAtEnd() + vtkIdType GetId(); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate over points of `ds'. + // \pre ds_exists: ds!=0 + void InitWithDataSet(vtkBridgeDataSet *ds); + +protected: + // Description: + // Default constructor. + vtkBridgePointIteratorOnDataSet(); + + // Description: + // Destructor. + virtual ~vtkBridgePointIteratorOnDataSet(); + + vtkBridgeDataSet *DataSet; // the structure on which the objet iterates. + vtkIdType Id; // the id at current position. + int Size; // size of the structure. + +private: + vtkBridgePointIteratorOnDataSet(const vtkBridgePointIteratorOnDataSet&); // Not implemented + void operator=(const vtkBridgePointIteratorOnDataSet&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOne.cxx b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOne.cxx new file mode 100644 index 0000000..73f3b0d --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOne.cxx @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIteratorOne.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIteratorOne - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#include "vtkBridgePointIteratorOne.h" + +#include + +#include "vtkObjectFactory.h" +#include "vtkBridgeDataSet.h" +#include "vtkDataSet.h" + +vtkCxxRevisionMacro(vtkBridgePointIteratorOne, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkBridgePointIteratorOne); + +//----------------------------------------------------------------------------- +// Description: +// Default constructor. +vtkBridgePointIteratorOne::vtkBridgePointIteratorOne() +{ + this->DataSet=0; + this->cIsAtEnd=1; +} + +//----------------------------------------------------------------------------- +// Description: +// Destructor. +vtkBridgePointIteratorOne::~vtkBridgePointIteratorOne() +{ + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,0); +} + +//----------------------------------------------------------------------------- +void vtkBridgePointIteratorOne::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to first position if any (loop initialization). +void vtkBridgePointIteratorOne::Begin() +{ + this->cIsAtEnd=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Is there no point at iterator position? (exit condition). +int vtkBridgePointIteratorOne::IsAtEnd() +{ + return this->cIsAtEnd; +} + +//----------------------------------------------------------------------------- +// Description: +// Move iterator to next position. (loop progression). +// \pre not_off: !IsAtEnd() +void vtkBridgePointIteratorOne::Next() +{ + assert("pre: not_off" && !IsAtEnd()); + this->cIsAtEnd=1; +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \post result_exists: result!=0 +double *vtkBridgePointIteratorOne::GetPosition() +{ + assert("pre: not_off" && !IsAtEnd()); + + double *result=this->DataSet->Implementation->GetPoint(this->Id); + + assert("post: result_exists" && result!=0); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Point at iterator position. +// \pre not_off: !IsAtEnd() +// \pre x_exists: x!=0 +void vtkBridgePointIteratorOne::GetPosition(double x[3]) +{ + assert("pre: not_off" && !IsAtEnd()); + assert("pre: x_exists" && x!=0); + this->DataSet->Implementation->GetPoint(this->Id,x); +} + +//----------------------------------------------------------------------------- +// Description: +// Unique identifier for the point, could be non-contiguous +// \pre not_off: !IsAtEnd() +vtkIdType vtkBridgePointIteratorOne::GetId() +{ + assert("pre: not_off" && !IsAtEnd()); + + return this->Id; +} + +//----------------------------------------------------------------------------- +// Description: +// Used internally by vtkBridgeDataSet. +// Iterate over one point of identifier `id' on dataset `ds'. +// \pre ds_can_be_null: ds!=0 || ds==0 +// \pre valid_id: vtkImplies(ds!=0,(id>=0)&&(id<=ds->GetNumberOfCells())) +void vtkBridgePointIteratorOne::InitWithOnePoint(vtkBridgeDataSet *ds, + vtkIdType id) +{ + assert("pre: valid_id" && + ((!ds!=0)|| ((id>=0)&&(id<=ds->GetNumberOfCells())))); // A=>B: !A||B + + vtkSetObjectBodyMacro(DataSet,vtkBridgeDataSet,ds); + this->Id=id; +} diff --git a/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOne.h b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOne.h new file mode 100644 index 0000000..6a5cb85 --- /dev/null +++ b/GenericFiltering/Testing/Cxx/vtkBridgePointIteratorOne.h @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBridgePointIteratorOne.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBridgePointIteratorOne - Implementation of vtkGenericPointIterator. +// .SECTION Description +// It is just an example that show how to implement the Generic. It is also +// used for testing and evaluating the Generic. +// .SECTION See Also +// vtkGenericPointIterator, vtkBridgeDataSet + +#ifndef __vtkBridgePointIteratorOne_h +#define __vtkBridgePointIteratorOne_h + +#include "vtkBridgeExport.h" +#include "vtkGenericPointIterator.h" + +class vtkBridgeDataSet; + +class VTK_BRIDGE_EXPORT vtkBridgePointIteratorOne : public vtkGenericPointIterator +{ +public: + static vtkBridgePointIteratorOne *New(); + vtkTypeRevisionMacro(vtkBridgePointIteratorOne,vtkGenericPointIterator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move iterator to first position if any (loop initialization). + void Begin(); + + // Description: + // Is there no point at iterator position? (exit condition). + int IsAtEnd(); + + // Description: + // Move iterator to next position. (loop progression). + // \pre not_off: !IsAtEnd() + void Next(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \post result_exists: result!=0 + double *GetPosition(); + + // Description: + // Point at iterator position. + // \pre not_off: !IsAtEnd() + // \pre x_exists: x!=0 + void GetPosition(double x[3]); + + // Description: + // Unique identifier for the point, could be non-contiguous + // \pre not_off: !IsAtEnd() + vtkIdType GetId(); + + // Description: + // Used internally by vtkBridgeDataSet. + // Iterate over one point of identifier `id' on dataset `ds'. + // \pre ds_can_be_null: ds!=0 || ds==0 + // \pre valid_id: vtkImplies(ds!=0,(id>=0)&&(id<=ds->GetNumberOfCells())) + void InitWithOnePoint(vtkBridgeDataSet *ds, + vtkIdType id); + +protected: + // Description: + // Default constructor. + vtkBridgePointIteratorOne(); + + // Description: + // Destructor. + virtual ~vtkBridgePointIteratorOne(); + + vtkBridgeDataSet *DataSet; // the structure on which the objet iterates. + vtkIdType Id; // the id at current position. + int cIsAtEnd; + +private: + vtkBridgePointIteratorOne(const vtkBridgePointIteratorOne&); // Not implemented + void operator=(const vtkBridgePointIteratorOne&); // Not implemented +}; + +#endif diff --git a/GenericFiltering/Testing/Tcl/CMakeLists.txt b/GenericFiltering/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..1587c7a --- /dev/null +++ b/GenericFiltering/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,9 @@ +ADD_TEST(PrintSelf-GenericFiltering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/GenericFiltering) + +ADD_TEST(TestSetObjectMacro-GenericFiltering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/GenericFiltering/vtk\\\\*.h" + "vtkSetObjectMacro" + ) diff --git a/GenericFiltering/vtkGenericClip.cxx b/GenericFiltering/vtkGenericClip.cxx new file mode 100644 index 0000000..4fec023 --- /dev/null +++ b/GenericFiltering/vtkGenericClip.cxx @@ -0,0 +1,465 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericClip.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericClip.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCell.h" +#include "vtkImageData.h" +#include "vtkImplicitFunction.h" +#include "vtkIdTypeArray.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkGenericDataSet.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericPointIterator.h" +#include "vtkGenericCellTessellator.h" +#include "vtkExecutive.h" + +#include + +vtkCxxRevisionMacro(vtkGenericClip, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkGenericClip); +vtkCxxSetObjectMacro(vtkGenericClip,ClipFunction,vtkImplicitFunction); + +//---------------------------------------------------------------------------- +// Construct with user-specified implicit function; InsideOut turned off; value +// set to 0.0; and generate clip scalars turned off. +vtkGenericClip::vtkGenericClip(vtkImplicitFunction *cf) +{ + this->ClipFunction = cf; + this->InsideOut = 0; + this->Locator = NULL; + this->Value = 0.0; + this->GenerateClipScalars = 0; + + this->GenerateClippedOutput = 0; + this->MergeTolerance = 0.01; + + this->SetNumberOfOutputPorts(2); + vtkUnstructuredGrid *output2 = vtkUnstructuredGrid::New(); + this->GetExecutive()->SetOutputData(1, output2); + output2->Delete(); + + this->InputScalarsSelection = NULL; + + this->internalPD=vtkPointData::New(); + this->secondaryPD=vtkPointData::New(); + this->secondaryCD=vtkCellData::New(); +} + +//---------------------------------------------------------------------------- +vtkGenericClip::~vtkGenericClip() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + this->SetClipFunction(NULL); + this->SetInputScalarsSelection(NULL); + this->internalPD->Delete(); + this->secondaryPD->Delete(); + this->secondaryCD->Delete(); +} + +//---------------------------------------------------------------------------- +// Do not say we have two outputs unless we are generating the clipped output. +int vtkGenericClip::GetNumberOfOutputs() +{ + if (this->GenerateClippedOutput) + { + return 2; + } + return 1; +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If Clip functions is modified, +// then this object is modified as well. +unsigned long vtkGenericClip::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->ClipFunction != NULL ) + { + time = this->ClipFunction->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid *vtkGenericClip::GetClippedOutput() +{ + if (!this->GenerateClippedOutput) + { + return NULL; + } + return vtkUnstructuredGrid::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + + +//---------------------------------------------------------------------------- +// +// Clip through data generating surface. +// +int vtkGenericClip::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if(input==0) + { + return 1; + } + + vtkUnstructuredGrid *clippedOutput = this->GetClippedOutput(); + + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *outCD[2]; + vtkIdType npts=0; + vtkIdType *pts; + int cellType = 0; + int j; + vtkIdType estimatedSize; + vtkUnsignedCharArray *types[2]; + vtkIdTypeArray *locs[2]; + int numOutputs = 1; + vtkGenericAdaptorCell *cell; + + vtkDebugMacro(<< "Clipping dataset"); + + // Initialize self; create output objects + // + if ( numPts < 1 ) + { + vtkErrorMacro(<<"No data to clip"); + return 1; + } + + if ( !this->ClipFunction && this->GenerateClipScalars ) + { + vtkErrorMacro(<<"Cannot generate clip scalars if no clip function defined"); + return 1; + } + + // allocate the output and associated helper classes + estimatedSize = numCells; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + vtkPoints *newPoints = vtkPoints::New(); + newPoints->Allocate(numPts,numPts/2); + + vtkCellArray *conn[2]; + conn[0] = vtkCellArray::New(); + conn[0]->Allocate(estimatedSize,estimatedSize/2); + conn[0]->InitTraversal(); + types[0] = vtkUnsignedCharArray::New(); + types[0]->Allocate(estimatedSize,estimatedSize/2); + locs[0] = vtkIdTypeArray::New(); + locs[0]->Allocate(estimatedSize,estimatedSize/2); + + if(this->GenerateClippedOutput) + { + numOutputs = 2; + conn[1] = vtkCellArray::New(); + conn[1]->Allocate(estimatedSize,estimatedSize/2); + conn[1]->InitTraversal(); + types[1] = vtkUnsignedCharArray::New(); + types[1]->Allocate(estimatedSize,estimatedSize/2); + locs[1] = vtkIdTypeArray::New(); + locs[1]->Allocate(estimatedSize,estimatedSize/2); + } + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPoints, input->GetBounds()); + + // prepare the output attributes + vtkGenericAttributeCollection *attributes=input->GetAttributes(); + vtkGenericAttribute *attribute; + vtkDataArray *attributeArray; + + int c=attributes->GetNumberOfAttributes(); + vtkDataSetAttributes *secondaryAttributes; + + int attributeType; + + vtkIdType i=0; + while(iGetAttribute(i); + attributeType=attribute->GetType(); + if(attribute->GetCentering()==vtkPointCentered) + { + secondaryAttributes=this->secondaryPD; + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + this->internalPD->AddArray(attributeArray); + attributeArray->Delete(); + if(this->internalPD->GetAttribute(attributeType)==0) + { + this->internalPD->SetActiveAttribute(this->internalPD->GetNumberOfArrays()-1,attributeType); + } + } + else // vtkCellCentered + { + secondaryAttributes=this->secondaryCD; + } + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + secondaryAttributes->AddArray(attributeArray); + attributeArray->Delete(); + + if(secondaryAttributes->GetAttribute(attributeType)==0) + { + secondaryAttributes->SetActiveAttribute(secondaryAttributes->GetNumberOfArrays()-1, + attributeType); + } + ++i; + } + outPD->InterpolateAllocate(this->secondaryPD,estimatedSize,estimatedSize/2); + + outCD[0] = output->GetCellData(); + outCD[0]->CopyAllocate(this->secondaryCD,estimatedSize,estimatedSize/2); + if ( this->GenerateClippedOutput ) + { + outCD[1] = clippedOutput->GetCellData(); + outCD[1]->CopyAllocate(this->secondaryCD,estimatedSize,estimatedSize/2); + } + + //vtkGenericPointIterator *pointIt = input->GetPoints(); + vtkGenericCellIterator *cellIt = input->NewCellIterator(); //explicit cell could be 2D or 3D + + //Process all cells and clip each in turn + // + int abort=0; + vtkIdType updateTime = numCells/20 + 1; // update roughly every 5% + + int num[2]; num[0]=num[1]=0; + int numNew[2]; numNew[0]=numNew[1]=0; + vtkIdType cellId; + + + input->GetTessellator()->InitErrorMetrics(input); + + for (cellId = 0, cellIt->Begin(); !cellIt->IsAtEnd() && !abort; cellId++, cellIt->Next()) + { + cell = cellIt->GetCell(); + if ( !(cellId % updateTime) ) + { + this->UpdateProgress((double)cellId / numCells); + abort = this->GetAbortExecute(); + } + + // perform the clipping + + cell->Clip(this->Value, this->ClipFunction, input->GetAttributes(), + input->GetTessellator(),this->InsideOut,this->Locator,conn[0], + outPD,outCD[0],this->internalPD,this->secondaryPD, + this->secondaryCD); + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + + if ( this->GenerateClippedOutput ) + { + cell->Clip(this->Value, this->ClipFunction, input->GetAttributes(), + input->GetTessellator(),this->InsideOut,this->Locator,conn[1], + outPD,outCD[1],this->internalPD,this->secondaryPD, + this->secondaryCD); + + numNew[1] = conn[1]->GetNumberOfCells() - num[1]; + num[1] = conn[1]->GetNumberOfCells(); + } + + for (i=0; iInsertNextValue(conn[i]->GetTraversalLocation()); + conn[i]->GetNextCell(npts,pts); + + //For each new cell added, got to set the type of the cell + switch ( cell->GetDimension() ) + { + case 0: //points are generated-------------------------------- + cellType = (npts > 1 ? VTK_POLY_VERTEX : VTK_VERTEX); + break; + + case 1: //lines are generated--------------------------------- + cellType = (npts > 2 ? VTK_POLY_LINE : VTK_LINE); + break; + + case 2: //polygons are generated------------------------------ + cellType = (npts == 3 ? VTK_TRIANGLE : + (npts == 4 ? VTK_QUAD : VTK_POLYGON)); + break; + + case 3: //tetrahedra or wedges are generated------------------ + cellType = (npts == 4 ? VTK_TETRA : VTK_WEDGE); + break; + } //switch + + types[i]->InsertNextValue(cellType); + } //for each new cell + } //for both outputs + } //for each cell + cellIt->Delete(); + + output->SetPoints(newPoints); + output->SetCells(types[0], locs[0], conn[0]); + conn[0]->Delete(); + types[0]->Delete(); + locs[0]->Delete(); + + if ( this->GenerateClippedOutput ) + { + clippedOutput->SetPoints(newPoints); + clippedOutput->SetCells(types[1], locs[1], conn[1]); + conn[1]->Delete(); + types[1]->Delete(); + locs[1]->Delete(); + } + + newPoints->Delete(); + this->Locator->Initialize();//release any extra memory + output->Squeeze(); + return 1; +} + +//---------------------------------------------------------------------------- +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkGenericClip::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator) + { + return; + } + + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + if ( locator ) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkGenericClip::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkGenericClip::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Merge Tolerance: " << this->MergeTolerance << "\n"; + if ( this->ClipFunction ) + { + os << indent << "Clip Function: " << this->ClipFunction << "\n"; + } + else + { + os << indent << "Clip Function: (none)\n"; + } + os << indent << "InsideOut: " << (this->InsideOut ? "On\n" : "Off\n"); + os << indent << "Value: " << this->Value << "\n"; + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + os << indent << "Generate Clip Scalars: " + << (this->GenerateClipScalars ? "On\n" : "Off\n"); + + os << indent << "Generate Clipped Output: " + << (this->GenerateClippedOutput ? "On\n" : "Off\n"); + + if (this->InputScalarsSelection) + { + os << indent << "InputScalarsSelection: " + << this->InputScalarsSelection << endl; + } +} +//---------------------------------------------------------------------------- +int vtkGenericClip::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + return 1; +} diff --git a/GenericFiltering/vtkGenericClip.h b/GenericFiltering/vtkGenericClip.h new file mode 100644 index 0000000..847c820 --- /dev/null +++ b/GenericFiltering/vtkGenericClip.h @@ -0,0 +1,186 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericClip.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericClip - clip any dataset with an implicit function or scalar data +// .SECTION Description +// vtkGenericClip is a filter that any type of dataset using either +// any subclass of vtkImplicitFunction, or the input scalar +// data. Clipping means that it actually "cuts" through the cells of +// the dataset, returning everything inside of the specified implicit +// function (or greater than the scalar value) including "pieces" of +// a cell. (Compare this with vtkExtractGeometry, which pulls out +// entire, uncut cells.) The output of this filter is an unstructured +// grid. +// +// To use this filter, you must decide if you will be clipping with an +// implicit function, or whether you will be using the input scalar +// data. If you want to clip with an implicit function, you must: +// 1) define an implicit function +// 2) set it with the SetClipFunction method +// 3) apply the GenerateClipScalarsOn method +// If a ClipFunction is not specified, or GenerateClipScalars is off +// (the default), then the input's scalar data will be used to clip +// the polydata. +// +// You can also specify a scalar value, which is used to decide what is +// inside and outside of the implicit function. You can also reverse the +// sense of what inside/outside is by setting the InsideOut instance +// variable. (The clipping algorithm proceeds by computing an implicit +// function value or using the input scalar data for each point in the +// dataset. This is compared to the scalar value to determine +// inside/outside.) +// +// This filter can be configured to compute a second output. The +// second output is the part of the cell that is clipped away. Set the +// GenerateClippedData boolean on if you wish to access this output data. +// +// This filter has been implemented to operate on generic datasets, rather +// than the typical vtkDataSet (and subclasses). vtkGenericDataSet is a more +// complex cousin of vtkDataSet, typically consisting of nonlinear, +// higher-order cells. To process this type of data, generic cells are +// automatically tessellated into linear cells prior to isocontouring. + +// .SECTION See Also +// vtkClipDataSet vtkClipPolyData vtkClipVolume vtkImplicitFunction +// vtkGenericDataSet + +#ifndef __vtkGenericClip_h +#define __vtkGenericClip_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkImplicitFunction; + +class vtkPointLocator; +class vtkPointData; +class vtkCellData; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericClip : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGenericClip,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with user-specified implicit function; InsideOut turned off; + // value set to 0.0; and generate clip scalars turned off. + static vtkGenericClip *New(); + + // Description: + // Set the clipping value of the implicit function (if clipping with + // implicit function) or scalar value (if clipping with + // scalars). The default value is 0.0. + vtkSetMacro(Value,double); + vtkGetMacro(Value,double); + + // Description: + // Set/Get the InsideOut flag. When off, a vertex is considered + // inside the implicit function if its value is greater than the + // Value ivar. When InsideOutside is turned on, a vertex is + // considered inside the implicit function if its implicit function + // value is less than or equal to the Value ivar. InsideOut is off + // by default. + vtkSetMacro(InsideOut,int); + vtkGetMacro(InsideOut,int); + vtkBooleanMacro(InsideOut,int); + + // Description + // Specify the implicit function with which to perform the + // clipping. If you do not define an implicit function, + // then the selected input scalar data will be used for clipping. + virtual void SetClipFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ClipFunction,vtkImplicitFunction); + + // Description: + // If this flag is enabled, then the output scalar values will be + // interpolated from the implicit function values, and not the + // input scalar data. If you enable this flag but do not provide an + // implicit function an error will be reported. + vtkSetMacro(GenerateClipScalars,int); + vtkGetMacro(GenerateClipScalars,int); + vtkBooleanMacro(GenerateClipScalars,int); + + // Description: + // Control whether a second output is generated. The second output + // contains the polygonal data that's been clipped away. + vtkSetMacro(GenerateClippedOutput,int); + vtkGetMacro(GenerateClippedOutput,int); + vtkBooleanMacro(GenerateClippedOutput,int); + + // Description: + // Set the tolerance for merging clip intersection points that are near + // the vertices of cells. This tolerance is used to prevent the generation + // of degenerate primitives. Note that only 3D cells actually use this + // instance variable. + vtkSetClampMacro(MergeTolerance,double,0.0001,0.25); + vtkGetMacro(MergeTolerance,double); + + // Description: + // Return the Clipped output. + vtkUnstructuredGrid *GetClippedOutput(); + virtual int GetNumberOfOutputs(); + + // Description: + // Specify a spatial locator for merging points. By default, an + // instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. The + // locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // Return the mtime also considering the locator and clip function. + unsigned long GetMTime(); + + // Description: + // If you want to clip by an arbitrary array, then set its name here. + // By default this in NULL and the filter will use the active scalar array. + vtkGetStringMacro(InputScalarsSelection); + void SelectInputScalars(const char *fieldName) + {this->SetInputScalarsSelection(fieldName);} + +protected: + vtkGenericClip(vtkImplicitFunction *cf=NULL); + ~vtkGenericClip(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int FillInputPortInformation(int, vtkInformation*); + + vtkImplicitFunction *ClipFunction; + + vtkPointLocator *Locator; + int InsideOut; + double Value; + int GenerateClipScalars; + + int GenerateClippedOutput; + double MergeTolerance; + + char *InputScalarsSelection; + vtkSetStringMacro(InputScalarsSelection); + + // Used internal by vtkGenericAdaptorCell::Clip() + vtkPointData *internalPD; + vtkPointData *secondaryPD; + vtkCellData *secondaryCD; + +private: + vtkGenericClip(const vtkGenericClip&); // Not implemented. + void operator=(const vtkGenericClip&); // Not implemented. +}; + +#endif diff --git a/GenericFiltering/vtkGenericContourFilter.cxx b/GenericFiltering/vtkGenericContourFilter.cxx new file mode 100644 index 0000000..a36d45f --- /dev/null +++ b/GenericFiltering/vtkGenericContourFilter.cxx @@ -0,0 +1,409 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericContourFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericContourFilter.h" +#include "vtkCell.h" +#include "vtkLine.h" +#include "vtkCellArray.h" +#include "vtkMergePoints.h" +#include "vtkContourValues.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkTimerLog.h" +#include "vtkUnstructuredGrid.h" +#include "vtkContourGrid.h" +#include "vtkDoubleArray.h" +#include "vtkPointData.h" +#include "vtkGenericCellIterator.h" +#include "vtkCellData.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkPolyData.h" +#include "vtkGenericDataSet.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericCellTessellator.h" + +vtkCxxRevisionMacro(vtkGenericContourFilter, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkGenericContourFilter); + +// Construct object with initial range (0,1) and single contour value +// of 0.0. +vtkGenericContourFilter::vtkGenericContourFilter() +{ + this->ContourValues = vtkContourValues::New(); + + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->Locator = NULL; + + this->InputScalarsSelection = NULL; + + this->internalPD=vtkPointData::New(); + this->secondaryPD=vtkPointData::New(); + this->secondaryCD=vtkCellData::New(); +} + +vtkGenericContourFilter::~vtkGenericContourFilter() +{ + this->ContourValues->Delete(); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + this->SetInputScalarsSelection(NULL); + this->internalPD->Delete(); + this->secondaryPD->Delete(); + this->secondaryCD->Delete(); +} + +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkGenericContourFilter::GetMTime() +{ + unsigned long mTime = this->Superclass::GetMTime(); + unsigned long time; + + if (this->ContourValues) + { + time = this->ContourValues->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if (this->Locator) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + // mTime should also take into account the fact that tesselator is view + // dependant + + return mTime; +} + +//----------------------------------------------------------------------------- +// General contouring filter. Handles arbitrary input. +int vtkGenericContourFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<< "Executing contour filter"); + + if(input==0) + { + vtkErrorMacro("No input specified"); + return 1; + } + vtkPointData *outPd = output->GetPointData(); + vtkCellData *outCd = output->GetCellData(); + + // Create objects to hold output of contour operation. First estimate + // allocation size. + vtkIdType numCells=input->GetNumberOfCells(); + vtkIdType estimatedSize=input->GetEstimatedSize(); + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + vtkPoints *newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + vtkCellArray *newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize,estimatedSize); + vtkCellArray *newLines = vtkCellArray::New(); + newLines->Allocate(estimatedSize,estimatedSize); + vtkCellArray *newPolys = vtkCellArray::New(); + newPolys->Allocate(estimatedSize,estimatedSize); + + output->Allocate(numCells); + + // locator used to merge potentially duplicate points + if(this->Locator==0) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion(newPts,input->GetBounds(),estimatedSize); + + // prepare the output attributes + vtkGenericAttributeCollection *attributes=input->GetAttributes(); + vtkGenericAttribute *attribute; + vtkDataArray *attributeArray; + + int c=attributes->GetNumberOfAttributes(); + vtkDataSetAttributes *secondaryAttributes; + + int attributeType; + + vtkIdType i=0; + while(iGetAttribute(i); + attributeType=attribute->GetType(); + if(attribute->GetCentering()==vtkPointCentered) + { + secondaryAttributes=this->secondaryPD; + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + this->internalPD->AddArray(attributeArray); + attributeArray->Delete(); + if(this->internalPD->GetAttribute(attributeType)==0) + { + this->internalPD->SetActiveAttribute(this->internalPD->GetNumberOfArrays()-1,attributeType); + } + } + else // vtkCellCentered + { + secondaryAttributes=this->secondaryCD; + } + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + secondaryAttributes->AddArray(attributeArray); + attributeArray->Delete(); + + if(secondaryAttributes->GetAttribute(attributeType)==0) + { + secondaryAttributes->SetActiveAttribute(secondaryAttributes->GetNumberOfArrays()-1, + attributeType); + } + ++i; + } + + outPd->InterpolateAllocate(this->secondaryPD,estimatedSize,estimatedSize); + outCd->CopyAllocate(this->secondaryCD,estimatedSize,estimatedSize); + + + vtkGenericAdaptorCell *cell; + + //----------- Begin of contouring algorithm --------------------// + vtkGenericCellIterator *cellIt = input->NewCellIterator(); + + if(this->InputScalarsSelection!=0) + { + int attrib=input->GetAttributes()->FindAttribute(this->InputScalarsSelection); + if(attrib!=-1) + { + vtkGenericAttribute *a=input->GetAttributes()->GetAttribute(attrib); + if(a->GetNumberOfComponents()==1) + { + input->GetAttributes()->SetActiveAttribute(attrib,0); + } + } + } + + + vtkIdType updateCount = numCells/20 + 1; // update roughly every 5% + vtkIdType count = 0; + int abortExecute=0; + + input->GetTessellator()->InitErrorMetrics(input); + + for(cellIt->Begin(); !cellIt->IsAtEnd() && !abortExecute; cellIt->Next()) + { + if ( !(count % updateCount) ) + { + this->UpdateProgress((double)count / numCells); + abortExecute = this->GetAbortExecute(); + } + + cell = cellIt->GetCell(); + cell->Contour(this->ContourValues, NULL, input->GetAttributes(), + input->GetTessellator(), + this->Locator, newVerts, newLines, newPolys, outPd, outCd, + this->internalPD,this->secondaryPD,this->secondaryCD); + ++count; + } // for each cell + cellIt->Delete(); + + vtkDebugMacro(<<"Created: " + << newPts->GetNumberOfPoints() << " points, " + << newVerts->GetNumberOfCells() << " verts, " + << newLines->GetNumberOfCells() << " lines, " + << newPolys->GetNumberOfCells() << " triangles"); + + //----------- End of contouring algorithm ----------------------// + + // Update ourselves. Because we don't know up front how many verts, lines, + // polys we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newVerts->GetNumberOfCells()>0) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if (newLines->GetNumberOfCells()>0) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if (newPolys->GetNumberOfCells()>0) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + this->Locator->Initialize();//releases leftover memory + output->Squeeze(); + return 1; +} + + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkGenericContourFilter::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkGenericContourFilter::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +void vtkGenericContourFilter::SelectInputScalars(const char *fieldName) +{ + this->SetInputScalarsSelection(fieldName); +} + +void vtkGenericContourFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->InputScalarsSelection) + { + os << indent << "InputScalarsSelection: " + << this->InputScalarsSelection << endl; + } + + os << indent << "Compute Gradients: " + << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Normals: " + << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " + << (this->ComputeScalars ? "On\n" : "Off\n"); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value);} + +// Description: +// Get the ith contour value. +double vtkGenericContourFilter::GetValue(int i) +{return this->ContourValues->GetValue(i);} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +double *vtkGenericContourFilter::GetValues() +{return this->ContourValues->GetValues();} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +void vtkGenericContourFilter::GetValues(double *contourValues) +{this->ContourValues->GetValues(contourValues);} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +void vtkGenericContourFilter::SetNumberOfContours(int number) +{this->ContourValues->SetNumberOfContours(number);} + +// Description: +// Get the number of contours in the list of contour values. +int vtkGenericContourFilter::GetNumberOfContours() +{return this->ContourValues->GetNumberOfContours();} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +void vtkGenericContourFilter::GenerateValues(int numContours, double range[2]) +{this->ContourValues->GenerateValues(numContours, range);} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +void vtkGenericContourFilter::GenerateValues(int numContours, double + rangeStart, double rangeEnd) +{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + +//---------------------------------------------------------------------------- +int vtkGenericContourFilter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + return 1; +} diff --git a/GenericFiltering/vtkGenericContourFilter.h b/GenericFiltering/vtkGenericContourFilter.h new file mode 100644 index 0000000..468cfe0 --- /dev/null +++ b/GenericFiltering/vtkGenericContourFilter.h @@ -0,0 +1,161 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericContourFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericContourFilter - generate isocontours from input dataset +// .SECTION Description +// vtkGenericContourFilter is a filter that takes as input any (generic) +// dataset and generates on output isosurfaces and/or isolines. The exact +// form of the output depends upon the dimensionality of the input data. +// Data consisting of 3D cells will generate isosurfaces, data consisting of +// 2D cells will generate isolines, and data with 1D or 0D cells will +// generate isopoints. Combinations of output type are possible if the input +// dimension is mixed. +// +// To use this filter you must specify one or more contour values. +// You can either use the method SetValue() to specify each contour +// value, or use GenerateValues() to generate a series of evenly +// spaced contours. It is also possible to accelerate the operation of +// this filter (at the cost of extra memory) by using a +// vtkScalarTree. A scalar tree is used to quickly locate cells that +// contain a contour surface. This is especially effective if multiple +// contours are being extracted. If you want to use a scalar tree, +// invoke the method UseScalarTreeOn(). +// +// This filter has been implemented to operate on generic datasets, rather +// than the typical vtkDataSet (and subclasses). vtkGenericDataSet is a more +// complex cousin of vtkDataSet, typically consisting of nonlinear, +// higher-order cells. To process this type of data, generic cells are +// automatically tessellated into linear cells prior to isocontouring. + +// .SECTION Caveats +// For unstructured data or structured grids, normals and gradients +// are not computed. Use vtkPolyDataNormals to compute the surface +// normals. + +// .SECTION See Also +// vtkContourFilter vtkGenericDataSet + +#ifndef __vtkGenericContourFilter_h +#define __vtkGenericContourFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkContourValues; +class vtkPointLocator; +class vtkPointData; +class vtkCellData; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericContourFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGenericContourFilter, + vtkPolyDataAlgorithm); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with initial range (0,1) and single contour value + // of 0.0. + static vtkGenericContourFilter *New(); + + //BTX + typedef double PointType[3]; // Arbitrary definition of a point + //ETX + + // Description: + // Methods to set / get contour values. + void SetValue(int i, float value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Description: + // Modified GetMTime Because we delegate to vtkContourValues + unsigned long GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Set / get a spatial locator for merging points. By default, + // an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is + // specified. The locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // If you want to contour by an arbitrary scalar attribute, then set its + // name here. + // By default this in NULL and the filter will use the active scalar array. + vtkGetStringMacro(InputScalarsSelection); + virtual void SelectInputScalars(const char *fieldName); + +protected: + vtkGenericContourFilter(); + ~vtkGenericContourFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int FillInputPortInformation(int, vtkInformation*); + + vtkContourValues *ContourValues; + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkPointLocator *Locator; + + char *InputScalarsSelection; + vtkSetStringMacro(InputScalarsSelection); + + // Used internal by vtkGenericAdaptorCell::Contour() + vtkPointData *internalPD; + vtkPointData *secondaryPD; + vtkCellData *secondaryCD; + +private: + vtkGenericContourFilter(const vtkGenericContourFilter&); // Not implemented. + void operator=(const vtkGenericContourFilter&); // Not implemented. +}; +#endif diff --git a/GenericFiltering/vtkGenericCutter.cxx b/GenericFiltering/vtkGenericCutter.cxx new file mode 100644 index 0000000..fe240d7 --- /dev/null +++ b/GenericFiltering/vtkGenericCutter.cxx @@ -0,0 +1,423 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCutter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericCutter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkContourValues.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCell.h" +#include "vtkImplicitFunction.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkUnstructuredGrid.h" +#include "vtkPoints.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericPointIterator.h" +#include "vtkGenericDataSet.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericCellTessellator.h" + +#include + +vtkCxxRevisionMacro(vtkGenericCutter, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkGenericCutter); +vtkCxxSetObjectMacro(vtkGenericCutter,CutFunction,vtkImplicitFunction); + +//---------------------------------------------------------------------------- +// Construct with user-specified implicit function; initial value of 0.0; and +// generating cut scalars turned off. +// +vtkGenericCutter::vtkGenericCutter(vtkImplicitFunction *cf) +{ + this->ContourValues = vtkContourValues::New(); + this->CutFunction = cf; + this->GenerateCutScalars = 0; + this->Locator = NULL; + + this->internalPD=vtkPointData::New(); + this->secondaryPD=vtkPointData::New(); + this->secondaryCD=vtkCellData::New(); +} + +//---------------------------------------------------------------------------- +vtkGenericCutter::~vtkGenericCutter() +{ + this->ContourValues->Delete(); + this->SetCutFunction(NULL); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + this->internalPD->Delete(); + this->secondaryPD->Delete(); + this->secondaryCD->Delete(); +} + +//---------------------------------------------------------------------------- +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value); +} + +// Description: +// Get the ith contour value. +double vtkGenericCutter::GetValue(int i) +{ + return this->ContourValues->GetValue(i); +} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +double *vtkGenericCutter::GetValues() +{ + return this->ContourValues->GetValues(); +} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +void vtkGenericCutter::GetValues(double *contourValues) +{ + this->ContourValues->GetValues(contourValues); +} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +void vtkGenericCutter::SetNumberOfContours(int number) +{ + this->ContourValues->SetNumberOfContours(number); +} + +// Description: +// Get the number of contours in the list of contour values. +int vtkGenericCutter::GetNumberOfContours() +{ + return this->ContourValues->GetNumberOfContours(); +} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +void vtkGenericCutter::GenerateValues(int numContours, double range[2]) +{ + this->ContourValues->GenerateValues(numContours, range); +} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +void vtkGenericCutter::GenerateValues(int numContours, double rangeStart, + double rangeEnd) +{ + this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd); +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If cut functions is modified, +// or contour values modified, then this object is modified as well. +// +unsigned long vtkGenericCutter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long contourValuesMTime=this->ContourValues->GetMTime(); + unsigned long time; + + mTime = ( contourValuesMTime > mTime ? contourValuesMTime : mTime ); + + if ( this->CutFunction != NULL ) + { + time = this->CutFunction->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +// Cut through data generating surface. +// +int vtkGenericCutter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<< "Executing cutter"); + + if (input==0) + { + vtkErrorMacro("No input specified"); + return 1; + } + + if (this->CutFunction==0) + { + vtkErrorMacro("No cut function specified"); + return 1; + } + + if ( input->GetNumberOfPoints()<1 ) + { + vtkErrorMacro("Input data set is empty"); + return 1; + } + + vtkPointData *outPd = output->GetPointData(); + vtkCellData *outCd = output->GetCellData(); + + // Create objects to hold output of contour operation + // + vtkIdType numCells=input->GetNumberOfCells(); + int numContours = this->ContourValues->GetNumberOfContours(); + + vtkIdType estimatedSize = (vtkIdType) pow ((double) numCells, .75) * numContours; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + vtkPoints *newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + vtkCellArray *newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize,estimatedSize); + vtkCellArray *newLines = vtkCellArray::New(); + newLines->Allocate(estimatedSize,estimatedSize); + vtkCellArray *newPolys = vtkCellArray::New(); + newPolys->Allocate(estimatedSize,estimatedSize); + + output->Allocate(numCells); + + // locator used to merge potentially duplicate points + if(this->Locator==0) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion(newPts,input->GetBounds(),estimatedSize); + + // prepare the output attributes + vtkGenericAttributeCollection *attributes=input->GetAttributes(); + vtkGenericAttribute *attribute; + vtkDataArray *attributeArray; + + int c=attributes->GetNumberOfAttributes(); + vtkDataSetAttributes *secondaryAttributes; + + int attributeType; + + vtkIdType i=0; + while(iGetAttribute(i); + attributeType=attribute->GetType(); + if(attribute->GetCentering()==vtkPointCentered) + { + secondaryAttributes=this->secondaryPD; + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + this->internalPD->AddArray(attributeArray); + attributeArray->Delete(); + if(this->internalPD->GetAttribute(attributeType)==0) + { + this->internalPD->SetActiveAttribute(this->internalPD->GetNumberOfArrays()-1,attributeType); + } + } + else // vtkCellCentered + { + secondaryAttributes=this->secondaryCD; + } + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + secondaryAttributes->AddArray(attributeArray); + attributeArray->Delete(); + + if(secondaryAttributes->GetAttribute(attributeType)==0) + { + secondaryAttributes->SetActiveAttribute(secondaryAttributes->GetNumberOfArrays()-1, + attributeType); + } + ++i; + } + + outPd->InterpolateAllocate(this->secondaryPD,estimatedSize,estimatedSize); + outCd->CopyAllocate(this->secondaryCD,estimatedSize,estimatedSize); + + + vtkGenericAdaptorCell *cell; + + //----------- Begin of contouring algorithm --------------------// + vtkGenericCellIterator *cellIt = input->NewCellIterator(); + + + vtkIdType updateCount = numCells/20 + 1; // update roughly every 5% + vtkIdType count = 0; + int abortExecute=0; + + input->GetTessellator()->InitErrorMetrics(input); + + for(cellIt->Begin(); !cellIt->IsAtEnd() && !abortExecute; cellIt->Next()) + { + if ( !(count % updateCount) ) + { + this->UpdateProgress((double)count / numCells); + abortExecute = this->GetAbortExecute(); + } + + cell = cellIt->GetCell(); + cell->Contour(this->ContourValues, this->CutFunction, input->GetAttributes(), + input->GetTessellator(), + this->Locator, newVerts, newLines, newPolys, outPd, outCd, + this->internalPD,this->secondaryPD,this->secondaryCD); + ++count; + } // for each cell + cellIt->Delete(); + + vtkDebugMacro(<<"Created: " + << newPts->GetNumberOfPoints() << " points, " + << newVerts->GetNumberOfCells() << " verts, " + << newLines->GetNumberOfCells() << " lines, " + << newPolys->GetNumberOfCells() << " triangles"); + + //----------- End of contouring algorithm ----------------------// + + // Update ourselves. Because we don't know up front how many verts, lines, + // polys we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newVerts->GetNumberOfCells()>0) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if (newLines->GetNumberOfCells()>0) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if (newPolys->GetNumberOfCells()>0) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + this->Locator->Initialize();//releases leftover memory + output->Squeeze(); + return 1; +} + +//---------------------------------------------------------------------------- +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkGenericCutter::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkGenericCutter::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkGenericCutter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cut Function: " << this->CutFunction << "\n"; + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Generate Cut Scalars: " + << (this->GenerateCutScalars ? "On\n" : "Off\n"); +} +//---------------------------------------------------------------------------- +int vtkGenericCutter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + return 1; +} diff --git a/GenericFiltering/vtkGenericCutter.h b/GenericFiltering/vtkGenericCutter.h new file mode 100644 index 0000000..15fbbf2 --- /dev/null +++ b/GenericFiltering/vtkGenericCutter.h @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericCutter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericCutter - cut a vtkGenericDataSet with an implicit function or scalar data +// .SECTION Description +// vtkGenericCutter is a filter to cut through data using any subclass of +// vtkImplicitFunction. That is, a polygonal surface is created +// corresponding to the implicit function F(x,y,z) = value(s), where +// you can specify one or more values used to cut with. +// +// In VTK, cutting means reducing a cell of dimension N to a cut surface +// of dimension N-1. For example, a tetrahedron when cut by a plane (i.e., +// vtkPlane implicit function) will generate triangles. (In comparison, +// clipping takes a N dimensional cell and creates N dimension primitives.) +// +// vtkGenericCutter is generally used to "slice-through" a dataset, generating +// a surface that can be visualized. It is also possible to use +// vtkGenericCutter to do a form of volume rendering. vtkGenericCutter does +// this by generating multiple cut surfaces (usually planes) which are ordered +// (and rendered) from back-to-front. The surfaces are set translucent to give +// a volumetric rendering effect. +// +// This filter has been implemented to operate on generic datasets, rather +// than the typical vtkDataSet (and subclasses). vtkGenericDataSet is a more +// complex cousin of vtkDataSet, typically consisting of nonlinear, +// higher-order cells. To process this type of data, generic cells are +// automatically tessellated into linear cells prior to isocontouring. + + +// .SECTION See Also +// vtkCutter vtkImplicitFunction vtkClipPolyData vtkGenericDataSet + +#ifndef __vtkGenericCutter_h +#define __vtkGenericCutter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkContourValues; + +class vtkImplicitFunction; +class vtkPointLocator; +class vtkPointData; +class vtkCellData; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericCutter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGenericCutter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with user-specified implicit function; initial value of 0.0; and + // generating cut scalars turned off. + static vtkGenericCutter *New(); + + // Description: + // Set a particular contour value at contour number i. The index i ranges + // between 0<=iinternalPD=vtkPointData::New(); + this->KeepCellIds = 1; + + this->Merging = 1; + this->Locator = NULL; +} + +//---------------------------------------------------------------------------- +vtkGenericDataSetTessellator::~vtkGenericDataSetTessellator() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + this->internalPD->Delete(); +} + +//---------------------------------------------------------------------------- +// +int vtkGenericDataSetTessellator::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<< "Executing vtkGenericDataSetTessellator..."); + +// vtkGenericDataSet *input = this->GetInput(); +// vtkUnstructuredGrid *output = this->GetOutput(); + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkGenericAdaptorCell *cell; + vtkIdType numInserted=0, numNew, i; + vtkIdType npts, *pts; + int abortExecute=0; + + // Copy original points and point data + vtkPoints *newPts = vtkPoints::New(); + newPts->Allocate(2*numPts,numPts); + + // loop over region + vtkUnsignedCharArray *types = vtkUnsignedCharArray::New(); + types->Allocate(numCells); + vtkIdTypeArray *locs = vtkIdTypeArray::New(); + locs->Allocate(numCells); + vtkCellArray *conn = vtkCellArray::New(); + conn->Allocate(numCells); + + + // prepare the output attributes + vtkGenericAttributeCollection *attributes=input->GetAttributes(); + vtkGenericAttribute *attribute; + vtkDataArray *attributeArray; + + int c=attributes->GetNumberOfAttributes(); + vtkDataSetAttributes *dsAttributes; + + int attributeType; + + i=0; + while(iGetAttribute(i); + attributeType=attribute->GetType(); + if(attribute->GetCentering()==vtkPointCentered) + { + dsAttributes=outputPD; + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + this->internalPD->AddArray(attributeArray); + attributeArray->Delete(); + if(this->internalPD->GetAttribute(attributeType)==0) + { + this->internalPD->SetActiveAttribute(this->internalPD->GetNumberOfArrays()-1,attributeType); + } + } + else // vtkCellCentered + { + dsAttributes=outputCD; + } + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + dsAttributes->AddArray(attributeArray); + attributeArray->Delete(); + + if(dsAttributes->GetAttribute(attributeType)==0) + { + dsAttributes->SetActiveAttribute(dsAttributes->GetNumberOfArrays()-1,attributeType); + } + ++i; + } + + vtkIdTypeArray *cellIdArray=0; + + if(this->KeepCellIds) + { + cellIdArray=vtkIdTypeArray::New(); + cellIdArray->SetName("OriginalIds"); + } + + vtkGenericCellIterator *cellIt = input->NewCellIterator(); + vtkIdType updateCount = numCells/20 + 1; // update roughly every 5% + vtkIdType count = 0; + + input->GetTessellator()->InitErrorMetrics(input); + + vtkPointLocator *locator=0; + if ( this->Merging ) + { + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + locator=this->Locator; + } + + for(cellIt->Begin(); !cellIt->IsAtEnd() && !abortExecute; cellIt->Next(), count++) + { + if ( !(count % updateCount) ) + { + this->UpdateProgress((double)count / numCells); + abortExecute = this->GetAbortExecute(); + } + + cell = cellIt->GetCell(); + cell->Tessellate(input->GetAttributes(), input->GetTessellator(), + newPts, locator, conn, this->internalPD,outputPD, + outputCD,types); + numNew = conn->GetNumberOfCells() - numInserted; + numInserted = conn->GetNumberOfCells(); + + vtkIdType cellId=cell->GetId(); + + if(this->KeepCellIds) + { + for(i=0;iInsertNextValue(cellId); + } + } + + for (i=0; i < numNew; i++) + { + locs->InsertNextValue(conn->GetTraversalLocation()); + conn->GetNextCell(npts,pts); //side effect updates traversal location + } //insert each new cell + } //for all cells + cellIt->Delete(); + + // Send to the output + if(this->KeepCellIds) + { + outputCD->AddArray(cellIdArray); + cellIdArray->Delete(); + } + + output->SetPoints(newPts); + output->SetCells(types, locs, conn); + + if (!this->Merging && this->Locator) + { + this->Locator->Initialize(); + } + + vtkDebugMacro(<<"Subdivided " << numCells << " cells to produce " + << conn->GetNumberOfCells() << "new cells"); + + newPts->Delete(); + types->Delete(); + locs->Delete(); + conn->Delete(); + + output->Squeeze(); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericDataSetTessellator::FillInputPortInformation( + int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkGenericDataSetTessellator::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetTessellator::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +//---------------------------------------------------------------------------- +void vtkGenericDataSetTessellator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "keep cells ids="; + if(this->KeepCellIds) + { + os << "true" << endl; + } + else + { + os << "false" << endl; + } + + os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n"); + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +unsigned long int vtkGenericDataSetTessellator::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} diff --git a/GenericFiltering/vtkGenericDataSetTessellator.h b/GenericFiltering/vtkGenericDataSetTessellator.h new file mode 100644 index 0000000..380db04 --- /dev/null +++ b/GenericFiltering/vtkGenericDataSetTessellator.h @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericDataSetTessellator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericDataSetTessellator - tessellates generic, higher-order datasets into linear cells +// .SECTION Description + +// vtkGenericDataSetTessellator is a filter that subdivides a +// vtkGenericDataSet into linear elements (i.e., linear VTK +// cells). Tetrahedra are produced from 3D cells; triangles from 2D cells; +// and lines from 1D cells. The subdivision process depends on the cell +// tessellator associated with the input generic dataset, and its associated +// error metric. (These can be specified by the user if necessary.) +// +// This filter is typically used to convert a higher-order, complex dataset +// represented vtkGenericDataSet into a conventional vtkDataSet that can +// be operated on by linear VTK graphics filters. + +// .SECTION See Also +// vtkGenericDataSetTessellator vtkGenericCellTessellator +// vtkGenericSubdivisionErrorMetric + + +#ifndef __vtkGenericDataSetTessellator_h +#define __vtkGenericDataSetTessellator_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkPointData; +class vtkPointLocator; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericDataSetTessellator : public vtkUnstructuredGridAlgorithm +{ +public: + // Description: + // Standard VTK methods. + static vtkGenericDataSetTessellator *New(); + vtkTypeRevisionMacro(vtkGenericDataSetTessellator, + vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Turn on/off generation of a cell centered attribute with ids of the + // original cells (as an input cell is tessellated into several linear + // cells). + // The name of the data array is "OriginalIds". It is true by default. + vtkSetMacro(KeepCellIds, int); + vtkGetMacro(KeepCellIds, int); + vtkBooleanMacro(KeepCellIds, int); + + + // Description: + // Turn on/off merging of coincident points. Note that is merging is + // on, points with different point attributes (e.g., normals) are merged, + // which may cause rendering artifacts. + vtkSetMacro(Merging,int); + vtkGetMacro(Merging,int); + vtkBooleanMacro(Merging,int); + + // Description: + // Set / get a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + + // Description: + // Return the MTime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkGenericDataSetTessellator(); + ~vtkGenericDataSetTessellator(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int FillInputPortInformation(int, vtkInformation*); + + // See Set/Get KeepCellIds() for explanations. + int KeepCellIds; + + // Used internal by vtkGenericAdaptorCell::Tessellate() + vtkPointData *internalPD; + + int Merging; + vtkPointLocator *Locator; + +private: + vtkGenericDataSetTessellator(const vtkGenericDataSetTessellator&); // Not implemented. + void operator=(const vtkGenericDataSetTessellator&); // Not implemented. +}; + +#endif diff --git a/GenericFiltering/vtkGenericGeometryFilter.cxx b/GenericFiltering/vtkGenericGeometryFilter.cxx new file mode 100644 index 0000000..7c96c93 --- /dev/null +++ b/GenericFiltering/vtkGenericGeometryFilter.cxx @@ -0,0 +1,514 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericGeometryFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkHexahedron.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPyramid.h" +#include "vtkStructuredGrid.h" +#include "vtkTetra.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericDataSet.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericCellTessellator.h" + +vtkCxxRevisionMacro(vtkGenericGeometryFilter, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkGenericGeometryFilter); + +//---------------------------------------------------------------------------- +// Construct with all types of clipping turned off. +vtkGenericGeometryFilter::vtkGenericGeometryFilter() +{ + this->PointMinimum = 0; + this->PointMaximum = VTK_LARGE_ID; + + this->CellMinimum = 0; + this->CellMaximum = VTK_LARGE_ID; + + this->Extent[0] = VTK_DOUBLE_MIN; + this->Extent[1] = VTK_DOUBLE_MAX; + this->Extent[2] = VTK_DOUBLE_MIN; + this->Extent[3] = VTK_DOUBLE_MAX; + this->Extent[4] = VTK_DOUBLE_MIN; + this->Extent[5] = VTK_DOUBLE_MAX; + + this->PointClipping = 0; + this->CellClipping = 0; + this->ExtentClipping = 0; + + this->Merging = 1; + this->Locator = NULL; + this->internalPD=vtkPointData::New(); +} +//---------------------------------------------------------------------------- +vtkGenericGeometryFilter::~vtkGenericGeometryFilter() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + this->internalPD->Delete(); +} + +//---------------------------------------------------------------------------- +// Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. +void vtkGenericGeometryFilter::SetExtent(double xMin, double xMax, double yMin, + double yMax, double zMin, double zMax) +{ + double extent[6]; + + extent[0] = xMin; + extent[1] = xMax; + extent[2] = yMin; + extent[3] = yMax; + extent[4] = zMin; + extent[5] = zMax; + + this->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +// Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. +void vtkGenericGeometryFilter::SetExtent(double extent[6]) +{ + int i; + + if ( extent[0] != this->Extent[0] || extent[1] != this->Extent[1] || + extent[2] != this->Extent[2] || extent[3] != this->Extent[3] || + extent[4] != this->Extent[4] || extent[5] != this->Extent[5] ) + { + this->Modified(); + for (i=0; i<3; i++) + { + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + this->Extent[2*i] = extent[2*i]; + this->Extent[2*i+1] = extent[2*i+1]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkGenericGeometryFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId; + int i, j; +// vtkGenericDataSet *input= this->GetInput(); + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + char *cellVis; + vtkGenericAdaptorCell *cell; + double x[3]={0,0,0}; + //vtkIdList *ptIds; + vtkIdType ptIds[4]; + + vtkIdType ptId; + //int npts; + //vtkIdType pt=0; + int allVisible; +// vtkPolyData *output = this->GetOutput(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + + if (numCells == 0) + { + vtkErrorMacro(<<"No data to clip"); + return 1; + } + + vtkDebugMacro(<<"Executing geometry filter"); + + if ( (!this->CellClipping) && (!this->PointClipping) && + (!this->ExtentClipping) ) + { + allVisible = 1; + cellVis = NULL; + } + else + { + allVisible = 0; + cellVis = new char[numCells]; + } + + vtkGenericCellIterator *cellIt = input->NewCellIterator(); + // Mark cells as being visible or not + // + if ( ! allVisible ) + { + for (cellIt->Begin(); !cellIt->IsAtEnd(); cellIt->Next()) + { + cell = cellIt->GetCell(); + cellId = cell->GetId(); + if ( this->CellClipping && cellId < this->CellMinimum || + cellId > this->CellMaximum ) + { + cellVis[cellId] = 0; + } + else + { + //ptIds = cell->GetPointIds(); + cell->GetPointIds( ptIds ); + for (i=0; i < cell->GetNumberOfPoints(); i++) + { + ptId = ptIds[i]; + //input->GetPoint(ptId, x); + + if ( (this->PointClipping && (ptId < this->PointMinimum || + ptId > this->PointMaximum) ) || + (this->ExtentClipping && + (x[0] < this->Extent[0] || x[0] > this->Extent[1] || + x[1] < this->Extent[2] || x[1] > this->Extent[3] || + x[2] < this->Extent[4] || x[2] > this->Extent[5] )) ) + { + cellVis[cellId] = 0; + break; + } + } + if ( i >= cell->GetNumberOfPoints() ) + { + cellVis[cellId] = 1; + } + } + } + } + + // Allocate + // + vtkIdType estimatedSize = input->GetEstimatedSize(); + estimatedSize = (estimatedSize / 1024 + 1 )* 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + output->Allocate(numCells); + + vtkPoints *newPts = vtkPoints::New(); +//FB vtkDoubleArray *newScalars = vtkDoubleArray::New(); + vtkCellArray *cellArray = vtkCellArray::New(); + + newPts->Allocate(estimatedSize,numPts); +//FB newScalars->Allocate(estimatedSize, 5*numPts); + cellArray->Allocate(numCells); + + + // prepare the output attributes + vtkGenericAttributeCollection *attributes=input->GetAttributes(); + vtkGenericAttribute *attribute; + vtkDataArray *attributeArray; + + int c=attributes->GetNumberOfAttributes(); + vtkDataSetAttributes *dsAttributes; + + int attributeType; + + i=0; + while(iGetAttribute(i); + attributeType=attribute->GetType(); + if(attribute->GetCentering()==vtkPointCentered) + { + dsAttributes=outputPD; + + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + this->internalPD->AddArray(attributeArray); + attributeArray->Delete(); + if(this->internalPD->GetAttribute(attributeType)==0) + { + this->internalPD->SetActiveAttribute(this->internalPD->GetNumberOfArrays()-1,attributeType); + } + } + else // vtkCellCentered + { + dsAttributes=outputCD; + } + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + dsAttributes->AddArray(attributeArray); + attributeArray->Delete(); + + if(dsAttributes->GetAttribute(attributeType)==0) + { + dsAttributes->SetActiveAttribute(dsAttributes->GetNumberOfArrays()-1,attributeType); + } + ++i; + } + + vtkPointLocator *locator=0; + if ( this->Merging ) + { + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + locator=this->Locator; + } + + // Traverse cells to extract geometry + // + int abort=0; + vtkIdType progressInterval = numCells/20 + 1; + + vtkIdList *faceList = vtkIdList::New(); + faceList->SetNumberOfIds(3); + + input->GetTessellator()->InitErrorMetrics(input); + + for (cellId = 0, cellIt->Begin(); !cellIt->IsAtEnd() && !abort; + cellIt->Next(), cellId++) + { + cell = cellIt->GetCell(); + //Progress and abort method support + if ( !(cellId % progressInterval) ) + { + vtkDebugMacro(<<"Process cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + abort = this->GetAbortExecute(); + } + + if ( allVisible || cellVis[cellId] ) + { + switch ( cell->GetDimension() ) + { + // create new points and then cell + case 0: case 1: + vtkErrorMacro( "Cell not handled yet" ); + break; + case 2: + if ( cell->IsOnBoundary() ) + { + cell->Tessellate(input->GetAttributes(), input->GetTessellator(), + newPts, locator,cellArray, this->internalPD, + outputPD, outputCD,0); //newScalars ); + } + break; + case 3: +// int numFaces = cell->GetNumberOfFaces(); + int numFaces = cell->GetNumberOfBoundaries(2); + for (j=0; j < numFaces; j++) + { + if ( cell->IsFaceOnBoundary(j) ) + { + cell->TriangulateFace(input->GetAttributes(), + input->GetTessellator(), + j, newPts, locator, cellArray, + this->internalPD,outputPD, outputCD ); + } + } + break; + + } //switch + } //if visible + } //for all cells + cellIt->Delete(); + vtkDebugMacro(<<"Extracted " << newPts->GetNumberOfPoints() << " points," + << output->GetNumberOfCells() << " cells."); + + // Update ourselves and release memory + // + output->SetPoints(newPts); + output->SetPolys(cellArray); +//FB newScalars->SetNumberOfTuples( newPts->GetNumberOfPoints() ); +//FB outputPD->SetScalars(newScalars); + + cellArray->Delete(); + newPts->Delete(); +//FB newScalars->Delete(); + faceList->Delete(); + + //free storage + if (!this->Merging && this->Locator) + { + this->Locator->Initialize(); + } + output->Squeeze(); + + if ( cellVis ) + { + delete [] cellVis; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericGeometryFilter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkGenericGeometryFilter::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkGenericGeometryFilter::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +//---------------------------------------------------------------------------- +void vtkGenericGeometryFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Point Minimum : " << this->PointMinimum << "\n"; + os << indent << "Point Maximum : " << this->PointMaximum << "\n"; + + os << indent << "Cell Minimum : " << this->CellMinimum << "\n"; + os << indent << "Cell Maximum : " << this->CellMaximum << "\n"; + + os << indent << "Extent: \n"; + os << indent << " Xmin,Xmax: (" << this->Extent[0] << ", " << this->Extent[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->Extent[2] << ", " << this->Extent[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->Extent[4] << ", " << this->Extent[5] << ")\n"; + + os << indent << "PointClipping: " << (this->PointClipping ? "On\n" : "Off\n"); + os << indent << "CellClipping: " << (this->CellClipping ? "On\n" : "Off\n"); + os << indent << "ExtentClipping: " << (this->ExtentClipping ? "On\n" : "Off\n"); + + os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n"); + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +unsigned long int vtkGenericGeometryFilter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} + +//---------------------------------------------------------------------------- +int vtkGenericGeometryFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info objects +// vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces; + + if (this->GetInput() == NULL) + { + vtkErrorMacro("No Input"); + return 1; + } + + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + piece = output->GetUpdatePiece(); + numPieces = output->GetUpdateNumberOfPieces(); + + this->GetInput()->SetUpdateExtent(piece, numPieces, 0); + + this->GetInput()->RequestExactExtentOn(); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericGeometryFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info objects +// vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); +// vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if (this->GetInput() == NULL) + { + vtkErrorMacro("No Input"); + return 1; + } + return 1; +} diff --git a/GenericFiltering/vtkGenericGeometryFilter.h b/GenericFiltering/vtkGenericGeometryFilter.h new file mode 100644 index 0000000..df3ef76 --- /dev/null +++ b/GenericFiltering/vtkGenericGeometryFilter.h @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericGeometryFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericGeometryFilter - extract geometry from data (or convert data to polygonal type) +// .SECTION Description +// vtkGenericGeometryFilter is a general-purpose filter to extract geometry (and +// associated data) from any type of dataset. Geometry is obtained as +// follows: all 0D, 1D, and 2D cells are extracted. All 2D faces that are +// used by only one 3D cell (i.e., boundary faces) are extracted. It also is +// possible to specify conditions on point ids, cell ids, and on +// bounding box (referred to as "Extent") to control the extraction process. +// +// This filter also may be used to convert any type of data to polygonal +// type. The conversion process may be less than satisfactory for some 3D +// datasets. For example, this filter will extract the outer surface of a +// volume or structured grid dataset. (For structured data you may want to +// use vtkImageDataGeometryFilter, vtkStructuredGridGeometryFilter, +// vtkExtractUnstructuredGrid, vtkRectilinearGridGeometryFilter, or +// vtkExtractVOI.) + +// .SECTION Caveats +// When vtkGenericGeometryFilter extracts cells (or boundaries of cells) it +// will (by default) merge duplicate vertices. This may cause problems +// in some cases. For example, if you've run vtkPolyDataNormals to +// generate normals, which may split meshes and create duplicate +// vertices, vtkGenericGeometryFilter will merge these points back +// together. Turn merging off to prevent this from occurring. + +// .SECTION See Also +// vtkImageDataGeometryFilter vtkStructuredGridGeometryFilter +// vtkExtractGeometry vtkExtractVOI + +#ifndef __vtkGenericGeometryFilter_h +#define __vtkGenericGeometryFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPointLocator; +class vtkPointData; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericGeometryFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkGenericGeometryFilter *New(); + vtkTypeRevisionMacro(vtkGenericGeometryFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Turn on/off selection of geometry by point id. + vtkSetMacro(PointClipping,int); + vtkGetMacro(PointClipping,int); + vtkBooleanMacro(PointClipping,int); + + // Description: + // Turn on/off selection of geometry by cell id. + vtkSetMacro(CellClipping,int); + vtkGetMacro(CellClipping,int); + vtkBooleanMacro(CellClipping,int); + + // Description: + // Turn on/off selection of geometry via bounding box. + vtkSetMacro(ExtentClipping,int); + vtkGetMacro(ExtentClipping,int); + vtkBooleanMacro(ExtentClipping,int); + + // Description: + // Specify the minimum point id for point id selection. + vtkSetClampMacro(PointMinimum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(PointMinimum,vtkIdType); + + // Description: + // Specify the maximum point id for point id selection. + vtkSetClampMacro(PointMaximum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(PointMaximum,vtkIdType); + + // Description: + // Specify the minimum cell id for point id selection. + vtkSetClampMacro(CellMinimum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(CellMinimum,vtkIdType); + + // Description: + // Specify the maximum cell id for point id selection. + vtkSetClampMacro(CellMaximum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(CellMaximum,vtkIdType); + + // Description: + // Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. + void SetExtent(double xMin, double xMax, double yMin, double yMax, + double zMin, double zMax); + + // Description: + // Set / get a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. + void SetExtent(double extent[6]); + double *GetExtent() { return this->Extent;}; + + // Description: + // Turn on/off merging of coincident points. Note that is merging is + // on, points with different point attributes (e.g., normals) are merged, + // which may cause rendering artifacts. + vtkSetMacro(Merging,int); + vtkGetMacro(Merging,int); + vtkBooleanMacro(Merging,int); + + // Description: + // Set / get a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + + // Description: + // Return the MTime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkGenericGeometryFilter(); + ~vtkGenericGeometryFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void PolyDataExecute(); //special cases for performance + void UnstructuredGridExecute(); + void StructuredGridExecute(); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int FillInputPortInformation(int, vtkInformation*); + + vtkIdType PointMaximum; + vtkIdType PointMinimum; + vtkIdType CellMinimum; + vtkIdType CellMaximum; + double Extent[6]; + int PointClipping; + int CellClipping; + int ExtentClipping; + + int Merging; + vtkPointLocator *Locator; + + // Used internal by vtkGenericAdaptorCell::Tessellate() + vtkPointData *internalPD; + +private: + vtkGenericGeometryFilter(const vtkGenericGeometryFilter&); // Not implemented. + void operator=(const vtkGenericGeometryFilter&); // Not implemented. +}; + +#endif + + diff --git a/GenericFiltering/vtkGenericGlyph3DFilter.cxx b/GenericFiltering/vtkGenericGlyph3DFilter.cxx new file mode 100644 index 0000000..a3f7d73 --- /dev/null +++ b/GenericFiltering/vtkGenericGlyph3DFilter.cxx @@ -0,0 +1,891 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkGenericGlyph3DFilter.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericGlyph3DFilter.h" + +#include "vtkGenericDataSet.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericPointIterator.h" +//#include "vtkGenericCell.h" + +#include "vtkCell.h" +#include "vtkDoubleArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkGenericGlyph3DFilter, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkGenericGlyph3DFilter); + +// Construct object with scaling on, scaling mode is by scalar value, +// scale factor = 1.0, the range is (0,1), orient geometry is on, and +// orientation is by vector. Clamping and indexing are turned off. No +// initial sources are defined. +vtkGenericGlyph3DFilter::vtkGenericGlyph3DFilter() +{ + this->Scaling = 1; + this->ColorMode = VTK_COLOR_BY_SCALE; + this->ScaleMode = VTK_SCALE_BY_SCALAR; + this->ScaleFactor = 1.0; + this->Range[0] = 0.0; + this->Range[1] = 1.0; + this->Orient = 1; + this->VectorMode = VTK_USE_VECTOR; + this->Clamping = 0; + this->IndexMode = VTK_INDEXING_OFF; +// this->NumberOfRequiredInputs = 1; + this->GeneratePointIds = 0; + this->PointIdsName = NULL; + this->SetPointIdsName("InputPointIds"); + this->InputScalarsSelection = NULL; + this->InputVectorsSelection = NULL; + this->InputNormalsSelection = NULL; + this->SetNumberOfInputPorts(2); +} + +vtkGenericGlyph3DFilter::~vtkGenericGlyph3DFilter() +{ + if (this->PointIdsName) + { + delete []PointIdsName; + } + this->SetInputScalarsSelection(NULL); + this->SetInputVectorsSelection(NULL); + this->SetInputNormalsSelection(NULL); +} + +int vtkGenericGlyph3DFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + + + vtkPointData *pd = NULL; + // vtkDataArray *inScalars; + // vtkDataArray *inVectors; + // vtkDataArray *inNormals; + vtkDataArray *sourceNormals = NULL; + vtkGenericAttribute *inScalars=0; + vtkGenericAttribute *inVectors=0; + vtkGenericAttribute *inNormals=0; + // vtkGenericAttribute *sourceNormals=0; + + int requestedGhostLevel=0; + unsigned char* inGhostLevels=0; + + vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i; + int index; + vtkPoints *sourcePts = NULL; + vtkPoints *newPts; + vtkDataArray *newScalars=NULL; + vtkDataArray *newVectors=NULL; + vtkDataArray *newNormals=NULL; + double x[3], v[3], vNew[3], s = 0.0, vMag = 0.0, value; + vtkTransform *trans; + vtkCell *cell; + vtkIdList *cellPts; + int npts; + vtkIdList *pts; + vtkIdType ptIncr, cellId; + int haveVectors, haveNormals; + double scalex,scaley,scalez, den; + vtkPointData *outputPD = output->GetPointData(); +// vtkGenericDataSet *input = this->GetInput(); + int numberOfSources = this->GetNumberOfInputConnections(1); + vtkPolyData *defaultSource = NULL; + vtkIdTypeArray *pointIds=0; + + vtkGenericAttributeCollection *attributes=0; + int attrib=-1; + + vtkDebugMacro(<<"Generating glyphs"); + + if (!input) + { + vtkErrorMacro(<<"No input"); + return 1; + } + + attributes = input->GetAttributes(); + if((attributes==0) || (attributes->IsEmpty())) + { + vtkDebugMacro("No attributes, nothing to do."); + return 1; + } + if (this->InputScalarsSelection!=0) + { + attrib=attributes->FindAttribute(this->InputScalarsSelection); + if(attrib!=-1) + { + inScalars = attributes->GetAttribute(attrib); + if(inScalars->GetNumberOfComponents()!=1) + { + inScalars=0; + vtkDebugMacro("The attribute is not a scalar."); + } + } + else + { + vtkDebugMacro("No scalar attribute."); + } + } + if (this->InputVectorsSelection!=0) + { + vtkDebugMacro("this->InputVectorsSelection!=0"); + attrib=attributes->FindAttribute(this->InputVectorsSelection); + vtkDebugMacro("inVectors just set"); + if(attrib!=-1) + { + inVectors = attributes->GetAttribute(attrib); + if(inVectors->GetNumberOfComponents()!=3) + { + inVectors=0; + vtkDebugMacro("The attribute is not a vector."); + } + else + { + vtkDebugMacro("The attribute is a vector."); + } + } + else + { + vtkDebugMacro("No vector attribute."); + } + } + else + { + vtkDebugMacro("No input vector selection."); + } + + if (this->InputNormalsSelection!=0) + { + attrib = attributes->FindAttribute(this->InputNormalsSelection); + if(attrib!=-1) + { + inNormals = attributes->GetAttribute(attrib); + if(inNormals->GetNumberOfComponents()!=3) + { + inNormals=0; + vtkDebugMacro("The attribute is not a normal vector."); + } + } + else + { + vtkDebugMacro("No normal attribute."); + } + } + + // pd = input->GetPointData(); + // inScalars = pd->GetScalars(this->InputScalarsSelection); + // inVectors = pd->GetVectors(this->InputVectorsSelection); + // inNormals = pd->GetNormals(this->InputNormalsSelection); + + // guru concurrency section +#if 0 + vtkDataArray* temp = 0; + if (pd) + { + temp = pd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + requestedGhostLevel = output->GetUpdateGhostLevel(); +#endif + + numPts = input->GetNumberOfPoints(); + if (numPts < 1) + { + vtkDebugMacro(<<"No points to glyph!"); + return 1; + } + else + { + pts = vtkIdList::New(); + pts->Allocate(VTK_CELL_SIZE); + trans=vtkTransform::New(); + } + + // Check input for consistency + // + if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) + { + den = 1.0; + } + if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF && + ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) || + (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) ) + { + haveVectors = 1; + } + else + { + haveVectors = 0; + } + + if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inScalars) || + (this->IndexMode == VTK_INDEXING_BY_VECTOR && + ((!inVectors && this->VectorMode == VTK_USE_VECTOR) || + (!inNormals && this->VectorMode == VTK_USE_NORMAL))) ) + { + if ( this->GetSource(0) == NULL ) + { + vtkErrorMacro(<<"Indexing on but don't have data to index with"); + pts->Delete(); + trans->Delete(); + return 1; + } + else + { + vtkWarningMacro(<<"Turning indexing off: no data to index with"); + this->IndexMode = VTK_INDEXING_OFF; + } + } + + // Allocate storage for output PolyData + // + outputPD->CopyVectorsOff(); + outputPD->CopyNormalsOff(); + + if (!this->GetSource(0)) + { + defaultSource = vtkPolyData::New(); + defaultSource->Allocate(); + vtkPoints *defaultPoints = vtkPoints::New(); + defaultPoints->Allocate(6); + defaultPoints->InsertNextPoint(0, 0, 0); + defaultPoints->InsertNextPoint(1, 0, 0); + vtkIdType defaultPointIds[2]; + defaultPointIds[0] = 0; + defaultPointIds[1] = 1; + defaultSource->SetPoints(defaultPoints); + defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds); + defaultSource->SetUpdateExtent(0, 1, 0); + this->SetSource(defaultSource); + defaultSource->Delete(); + defaultSource = NULL; + defaultPoints->Delete(); + defaultPoints = NULL; + } + + if ( this->IndexMode != VTK_INDEXING_OFF ) + { + pd = NULL; + haveNormals = 1; + for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++) + { + if ( this->GetSource(i) != NULL ) + { + if (this->GetSource(i)->GetNumberOfPoints() > numSourcePts) + { + numSourcePts = this->GetSource(i)->GetNumberOfPoints(); + } + if (this->GetSource(i)->GetNumberOfCells() > numSourceCells) + { + numSourceCells = this->GetSource(i)->GetNumberOfCells(); + } + if ( !(sourceNormals = this->GetSource(i)->GetPointData()->GetNormals()) ) + { + haveNormals = 0; + } + } + } + } + else + { + sourcePts = this->GetSource(0)->GetPoints(); + numSourcePts = sourcePts->GetNumberOfPoints(); + numSourceCells = this->GetSource(0)->GetNumberOfCells(); + + sourceNormals = this->GetSource(0)->GetPointData()->GetNormals(); + if ( sourceNormals ) + { + haveNormals = 1; + } + else + { + haveNormals = 0; + } + + // Prepare to copy output. + // pd = input->GetPointData(); + // outputPD->CopyAllocate(pd,numPts*numSourcePts); // AddArray ? + } + + newPts = vtkPoints::New(); + newPts->Allocate(numPts*numSourcePts); + if ( this->GeneratePointIds ) + { + pointIds = vtkIdTypeArray::New(); + pointIds->SetName(this->PointIdsName); + pointIds->Allocate(numPts*numSourcePts); + outputPD->AddArray(pointIds); + } + if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inScalars ) + { + // newScalars = inScalars->NewInstance(); + newScalars=vtkDoubleArray::New(); + newScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + newScalars->Allocate(inScalars->GetNumberOfComponents()*numPts*numSourcePts); + newScalars->SetName(inScalars->GetName()); + } + else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inScalars) + { + newScalars = vtkDoubleArray::New(); + newScalars->Allocate(numPts*numSourcePts); + newScalars->SetName("GlyphScale"); + if (this->ScaleMode== VTK_SCALE_BY_SCALAR) + { + newScalars->SetName(inScalars->GetName()); + } + } + else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors) + { + newScalars = vtkDoubleArray::New(); + newScalars->Allocate(numPts*numSourcePts); + newScalars->SetName("VectorMagnitude"); + } + if ( haveVectors ) + { + newVectors = vtkDoubleArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(3*numPts*numSourcePts); + newVectors->SetName("GlyphVector"); + } + if ( haveNormals ) + { + newNormals = vtkDoubleArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts*numSourcePts); + newNormals->SetName("Normals"); + } + + // Setting up for calls to PolyData::InsertNextCell() + if (this->IndexMode != VTK_INDEXING_OFF ) + { + output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells); + } + else + { + output->Allocate(this->GetSource(0),3*numPts*numSourceCells,numPts*numSourceCells); + } + + // Traverse all Input points, transforming Source points and copying + // point attributes. + // + ptIncr=0; + inPtId=0; // used only for the progress information + +// vtkGenericAdaptorCell *acell=0; +// vtkCellIterator *it=input->NewVertexIterator(); + vtkGenericPointIterator *it=input->NewPointIterator(); + it->Begin(); + while(!it->IsAtEnd()) + { + scalex = scaley = scalez = 1.0; + if ( ! (inPtId % 10000) ) + { + this->UpdateProgress ((double)inPtId/numPts); + if (this->GetAbortExecute()) + { + break; + } + } + +// acell=it->GetCell(); + // Get the scalar and vector data + if ( inScalars ) + { + inScalars->GetTuple(it,&s); + // s = inScalars->GetComponent(inPtId, 0); + if ( this->ScaleMode == VTK_SCALE_BY_SCALAR || + this->ScaleMode == VTK_DATA_SCALING_OFF ) + { + scalex = scaley = scalez = s; + } + } + + if ( haveVectors ) + { + if ( this->VectorMode == VTK_USE_NORMAL ) + { + // inNormals->GetTuple(inPtId, v); + inNormals->GetTuple(it,v); + } + else + { + inVectors->GetTuple(it,v); + // inVectors->GetTuple(inPtId, v); + } + vMag = vtkMath::Norm(v); + if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS ) + { + scalex = v[0]; + scaley = v[1]; + scalez = v[2]; + } + else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) + { + scalex = scaley = scalez = vMag; + } + } + + // Clamp data scale if enabled + if ( this->Clamping ) + { + scalex = (scalex < this->Range[0] ? this->Range[0] : + (scalex > this->Range[1] ? this->Range[1] : scalex)); + scalex = (scalex - this->Range[0]) / den; + scaley = (scaley < this->Range[0] ? this->Range[0] : + (scaley > this->Range[1] ? this->Range[1] : scaley)); + scaley = (scaley - this->Range[0]) / den; + scalez = (scalez < this->Range[0] ? this->Range[0] : + (scalez > this->Range[1] ? this->Range[1] : scalez)); + scalez = (scalez - this->Range[0]) / den; + } + + // Compute index into table of glyphs + if ( this->IndexMode == VTK_INDEXING_OFF ) + { + index = 0; + } + else + { + if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) + { + value = s; + } + else + { + value = vMag; + } + + index = (int) ((double)(value - this->Range[0]) * numberOfSources / den); + index = (index < 0 ? 0 : + (index >= numberOfSources ? (numberOfSources-1) : index)); + + if ( this->GetSource(index) != NULL ) + { + sourcePts = this->GetSource(index)->GetPoints(); + sourceNormals = this->GetSource(index)->GetPointData()->GetNormals(); + numSourcePts = sourcePts->GetNumberOfPoints(); + numSourceCells = this->GetSource(index)->GetNumberOfCells(); + } + } + + // Make sure we're not indexing into empty glyph + if ( this->GetSource(index) == NULL ) + { + continue; + } + + // Check ghost points. + // If we are processing a piece, we do not want to duplicate + // glyphs on the borders. The corrct check here is: + // ghostLevel > 0. I am leaving this over glyphing here because + // it make a nice example (sphereGhost.tcl) to show the + // point ghost levels with the glyph filter. I am not certain + // of the usefullness of point ghost levels over 1, but I will have + // to think about it. + if (inGhostLevels && inGhostLevels[inPtId] > requestedGhostLevel) + { + continue; + } + + // Now begin copying/transforming glyph + trans->Identity(); + + // Copy all topology (transformation independent) + for (cellId=0; cellId < numSourceCells; cellId++) + { + cell = this->GetSource(index)->GetCell(cellId); + cellPts = cell->GetPointIds(); + npts = cellPts->GetNumberOfIds(); + for (pts->Reset(), i=0; i < npts; i++) + { + pts->InsertId(i,cellPts->GetId(i) + ptIncr); + } + output->InsertNextCell(cell->GetCellType(),pts); + } + + // translate Source to Input point + // input->GetPoint(inPtId, x); + it->GetPosition(x); + trans->Translate(x[0], x[1], x[2]); + + if ( haveVectors ) + { + // Copy Input vector + for (i=0; i < numSourcePts; i++) + { + newVectors->InsertTuple(i+ptIncr, v); + } + if (this->Orient && (vMag > 0.0)) + { + // if there is no y or z component + if ( v[1] == 0.0 && v[2] == 0.0 ) + { + if (v[0] < 0) //just flip x if we need to + { + trans->RotateWXYZ(180.0,0,1,0); + } + } + else + { + vNew[0] = (v[0]+vMag) / 2.0; + vNew[1] = v[1] / 2.0; + vNew[2] = v[2] / 2.0; + trans->RotateWXYZ((double)180.0,vNew[0],vNew[1],vNew[2]); + } + } + } + + // determine scale factor from scalars if appropriate + if ( inScalars ) + { + // Copy scalar value + if (this->ColorMode == VTK_COLOR_BY_SCALE) + { + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez + } + } + else if (this->ColorMode == VTK_COLOR_BY_SCALAR) + { + for (i=0; i < numSourcePts; i++) + { + // outputPD->CopyTuple(inScalars, newScalars, inPtId, ptIncr+i); + newScalars->InsertTuple(i+ptIncr, &s); + } + } + } + if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR) + { + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(i+ptIncr, &vMag); + } + } + + // scale data if appropriate + if ( this->Scaling ) + { + if ( this->ScaleMode == VTK_DATA_SCALING_OFF ) + { + scalex = scaley = scalez = this->ScaleFactor; + } + else + { + scalex *= this->ScaleFactor; + scaley *= this->ScaleFactor; + scalez *= this->ScaleFactor; + } + + if ( scalex == 0.0 ) + { + scalex = 1.0e-10; + } + if ( scaley == 0.0 ) + { + scaley = 1.0e-10; + } + if ( scalez == 0.0 ) + { + scalez = 1.0e-10; + } + trans->Scale(scalex,scaley,scalez); + } + + // multiply points and normals by resulting matrix + trans->TransformPoints(sourcePts,newPts); + + if ( haveNormals ) + { + trans->TransformNormals(sourceNormals,newNormals); + } + + // Copy point data from source (if possible): WRONG to from source but + // from input. + if ( pd ) + { + for (i=0; i < numSourcePts; i++) + { + outputPD->CopyData(pd,inPtId,ptIncr+i); + } + } + + // If point ids are to be generated, do it here + if ( this->GeneratePointIds ) + { + for (i=0; i < numSourcePts; i++) + { + pointIds->InsertNextValue(inPtId); + } + } + it->Next(); + ptIncr += numSourcePts; + inPtId++; + } + it->Delete(); + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newScalars) + { + int idx = outputPD->AddArray(newScalars); + outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + if (newVectors) + { + outputPD->SetVectors(newVectors); + newVectors->Delete(); + } + + if (newNormals) + { + outputPD->SetNormals(newNormals); + newNormals->Delete(); + } + + output->Squeeze(); + trans->Delete(); + pts->Delete(); + return 1; +} + +//---------------------------------------------------------------------------- +// Since indexing determines size of outputs, EstimatedWholeMemorySize is +// truly an estimate. Ignore Indexing (although for a best estimate we +// should average the size of the sources instead of using 0). +int vtkGenericGlyph3DFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info objects +// vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); +// vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if (this->GetInput() == NULL) + { + vtkErrorMacro("Missing input"); + return 1; + } + return 1; +} + +// Specify a source object at a specified table location. +void vtkGenericGlyph3DFilter::SetSource(int id, vtkPolyData *pd) +{ + if (id < 0) + { + vtkErrorMacro("Bad index " << id << " for source."); + return; + } + + int numConnections = this->GetNumberOfInputConnections(1); + vtkAlgorithmOutput *algOutput = 0; + if (pd) + { + algOutput = pd->GetProducerPort(); + } + else + { + vtkErrorMacro("Cannot set NULL source."); + return; + } + + if (id < numConnections) + { + if (algOutput) + { + this->SetNthInputConnection(1, id, algOutput); + } + } + else if (id == numConnections && algOutput) + { + this->AddInputConnection(1, algOutput); + } +} + +// Get a pointer to a source object at a specified table location. +vtkPolyData *vtkGenericGlyph3DFilter::GetSource(int id) +{ + if ( id < 0 || id >= this->GetNumberOfInputConnections(1) ) + { + return NULL; + } + else + { + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(1, id)); + } +} + +void vtkGenericGlyph3DFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Generate Point Ids " + << (this->GeneratePointIds ? "On\n" : "Off\n"); + + os << indent << "PointIdsName: " << (this->PointIdsName ? this->PointIdsName + : "(none)") << "\n"; + + os << indent << "Color Mode: " << this->GetColorModeAsString() << endl; + + if ( this->GetNumberOfInputConnections(1) < 2 ) + { + if ( this->GetSource(0) != NULL ) + { + os << indent << "Source: (" << this->GetSource(0) << ")\n"; + } + else + { + os << indent << "Source: (none)\n"; + } + } + else + { + os << indent << "A table of " << this->GetNumberOfInputConnections(1) << " glyphs has been defined\n"; + } + + os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n"); + + os << indent << "Scale Mode: "; + if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ) + { + os << "Scale by scalar\n"; + } + else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) + { + os << "Scale by vector\n"; + } + else + { + os << "Data scaling is turned off\n"; + } + + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; + os << indent << "Clamping: " << (this->Clamping ? "On\n" : "Off\n"); + os << indent << "Range: (" << this->Range[0] << ", " << this->Range[1] << ")\n"; + os << indent << "Orient: " << (this->Orient ? "On\n" : "Off\n"); + os << indent << "Orient Mode: " << (this->VectorMode == VTK_USE_VECTOR ? + "Orient by vector\n" : "Orient by normal\n"); + os << indent << "Index Mode: "; + if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) + { + os << "Index by scalar value\n"; + } + else if ( this->IndexMode == VTK_INDEXING_BY_VECTOR ) + { + os << "Index by vector value\n"; + } + else + { + os << "Indexing off\n"; + } + os << indent << "InputScalarsSelection: " + << (this->InputScalarsSelection ? this->InputScalarsSelection : "(none)") << "\n"; + os << indent << "InputVectorsSelection: " + << (this->InputVectorsSelection ? this->InputVectorsSelection : "(none)") << "\n"; + os << indent << "InputNormalsSelection: " + << (this->InputNormalsSelection ? this->InputNormalsSelection : "(none)") << "\n"; +} + +int vtkGenericGlyph3DFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + + + if (sourceInfo) + { + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericGlyph3DFilter +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + } + else + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + } + return 1; +} diff --git a/GenericFiltering/vtkGenericGlyph3DFilter.h b/GenericFiltering/vtkGenericGlyph3DFilter.h new file mode 100644 index 0000000..e722226 --- /dev/null +++ b/GenericFiltering/vtkGenericGlyph3DFilter.h @@ -0,0 +1,336 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericGlyph3DFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericGlyph3DFilter - copy oriented and scaled glyph geometry to every input point +// .SECTION Description +// vtkGenericGlyph3DFilter is a filter that copies a geometric representation (called +// a glyph) to every point in the input dataset. The glyph is defined with +// polygonal data from a source filter input. The glyph may be oriented +// along the input vectors or normals, and it may be scaled according to +// scalar data or vector magnitude. More than one glyph may be used by +// creating a table of source objects, each defining a different glyph. If a +// table of glyphs is defined, then the table can be indexed into by using +// either scalar value or vector magnitude. +// +// To use this object you'll have to provide an input dataset and a source +// to define the glyph. Then decide whether you want to scale the glyph and +// how to scale the glyph (using scalar value or vector magnitude). Next +// decide whether you want to orient the glyph, and whether to use the +// vector data or normal data to orient it. Finally, decide whether to use a +// table of glyphs, or just a single glyph. If you use a table of glyphs, +// you'll have to decide whether to index into it with scalar value or with +// vector magnitude. +// +// .SECTION Caveats +// Contrary to vtkGlyph3D, the only way to specify which attributes will be +// used for scaling, coloring and orienting is through SelectInputScalars(), +// SelectInputVectors() and SelectInputNormals(). +// +// The scaling of the glyphs is controlled by the ScaleFactor ivar multiplied +// by the scalar value at each point (if VTK_SCALE_BY_SCALAR is set), or +// multiplied by the vector magnitude (if VTK_SCALE_BY_VECTOR is set), +// Alternatively (if VTK_SCALE_BY_VECTORCOMPONENTS is set), the scaling +// may be specified for x,y,z using the vector components. The +// scale factor can be further controlled by enabling clamping using the +// Clamping ivar. If clamping is enabled, the scale is normalized by the +// Range ivar, and then multiplied by the scale factor. The normalization +// process includes clamping the scale value between (0,1). +// +// Typically this object operates on input data with scalar and/or vector +// data. However, scalar and/or vector aren't necessary, and it can be used +// to copy data from a single source to each point. In this case the scale +// factor can be used to uniformly scale the glyphs. +// +// The object uses "vector" data to scale glyphs, orient glyphs, and/or index +// into a table of glyphs. You can choose to use either the vector or normal +// data at each input point. Use the method SetVectorModeToUseVector() to use +// the vector input data, and SetVectorModeToUseNormal() to use the +// normal input data. +// +// If you do use a table of glyphs, make sure to set the Range ivar to make +// sure the index into the glyph table is computed correctly. +// +// You can turn off scaling of the glyphs completely by using the Scaling +// ivar. You can also turn off scaling due to data (either vector or scalar) +// by using the SetScaleModeToDataScalingOff() method. + +// .SECTION See Also +// vtkTensorGlyph + +#ifndef __vtkGenericGlyph3DFilter_h +#define __vtkGenericGlyph3DFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_SCALE_BY_SCALAR 0 +#define VTK_SCALE_BY_VECTOR 1 +#define VTK_SCALE_BY_VECTORCOMPONENTS 2 +#define VTK_DATA_SCALING_OFF 3 + +#define VTK_COLOR_BY_SCALE 0 +#define VTK_COLOR_BY_SCALAR 1 +#define VTK_COLOR_BY_VECTOR 2 + +#define VTK_USE_VECTOR 0 +#define VTK_USE_NORMAL 1 +#define VTK_VECTOR_ROTATION_OFF 2 + +#define VTK_INDEXING_OFF 0 +#define VTK_INDEXING_BY_SCALAR 1 +#define VTK_INDEXING_BY_VECTOR 2 + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericGlyph3DFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGenericGlyph3DFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct object with scaling on, scaling mode is by scalar value, + // scale factor = 1.0, the range is (0,1), orient geometry is on, and + // orientation is by vector. Clamping and indexing are turned off. No + // initial sources are defined. + static vtkGenericGlyph3DFilter *New(); + + // Description: + // Set the source to use for he glyph. + void SetSource(vtkPolyData *pd) {this->SetSource(0,pd);}; + + // Description: + // Specify a source object at a specified table location. + void SetSource(int id, vtkPolyData *pd); + + // Description: + // Get a pointer to a source object at a specified table location. + vtkPolyData *GetSource(int id=0); + + // Description: + // Turn on/off scaling of source geometry. + vtkSetMacro(Scaling,int); + vtkBooleanMacro(Scaling,int); + vtkGetMacro(Scaling,int); + + // Description: + // Either scale by scalar or by vector/normal magnitude. + vtkSetMacro(ScaleMode,int); + vtkGetMacro(ScaleMode,int); + void SetScaleModeToScaleByScalar() + {this->SetScaleMode(VTK_SCALE_BY_SCALAR);}; + void SetScaleModeToScaleByVector() + {this->SetScaleMode(VTK_SCALE_BY_VECTOR);}; + void SetScaleModeToScaleByVectorComponents() + {this->SetScaleMode(VTK_SCALE_BY_VECTORCOMPONENTS);}; + void SetScaleModeToDataScalingOff() + {this->SetScaleMode(VTK_DATA_SCALING_OFF);}; + const char *GetScaleModeAsString(); + + // Description: + // Either color by scale, scalar or by vector/normal magnitude. + vtkSetMacro(ColorMode,int); + vtkGetMacro(ColorMode,int); + void SetColorModeToColorByScale() + {this->SetColorMode(VTK_COLOR_BY_SCALE);}; + void SetColorModeToColorByScalar() + {this->SetColorMode(VTK_COLOR_BY_SCALAR);}; + void SetColorModeToColorByVector() + {this->SetColorMode(VTK_COLOR_BY_VECTOR);}; + const char *GetColorModeAsString(); + + // Description: + // Specify scale factor to scale object by. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Specify range to map scalar values into. + vtkSetVector2Macro(Range,double); + vtkGetVectorMacro(Range,double,2); + + // Description: + // Turn on/off orienting of input geometry along vector/normal. + vtkSetMacro(Orient,int); + vtkBooleanMacro(Orient,int); + vtkGetMacro(Orient,int); + + // Description: + // Turn on/off clamping of "scalar" values to range. (Scalar value may be + // vector magnitude if ScaleByVector() is enabled.) + vtkSetMacro(Clamping,int); + vtkBooleanMacro(Clamping,int); + vtkGetMacro(Clamping,int); + + // Description: + // Specify whether to use vector or normal to perform vector operations. + vtkSetMacro(VectorMode,int); + vtkGetMacro(VectorMode,int); + void SetVectorModeToUseVector() {this->SetVectorMode(VTK_USE_VECTOR);}; + void SetVectorModeToUseNormal() {this->SetVectorMode(VTK_USE_NORMAL);}; + void SetVectorModeToVectorRotationOff() + {this->SetVectorMode(VTK_VECTOR_ROTATION_OFF);}; + const char *GetVectorModeAsString(); + + // Description: + // Index into table of sources by scalar, by vector/normal magnitude, or + // no indexing. If indexing is turned off, then the first source glyph in + // the table of glyphs is used. + vtkSetMacro(IndexMode,int); + vtkGetMacro(IndexMode,int); + void SetIndexModeToScalar() {this->SetIndexMode(VTK_INDEXING_BY_SCALAR);}; + void SetIndexModeToVector() {this->SetIndexMode(VTK_INDEXING_BY_VECTOR);}; + void SetIndexModeToOff() {this->SetIndexMode(VTK_INDEXING_OFF);}; + const char *GetIndexModeAsString(); + + // Description: + // Enable/disable the generation of point ids as part of the output. The + // point ids are the id of the input generating point. The point ids are + // stored in the output point field data and named "InputPointIds". Point + // generation is useful for debugging and pick operations. + vtkSetMacro(GeneratePointIds,int); + vtkGetMacro(GeneratePointIds,int); + vtkBooleanMacro(GeneratePointIds,int); + + // Description: + // Set/Get the name of the PointIds array if generated. By default the Ids + // are named "InputPointIds", but this can be changed with this function. + vtkSetStringMacro(PointIdsName); + vtkGetStringMacro(PointIdsName); + + // Description: + // If you want to use an arbitrary scalars array, then set its name here. + // By default this in NULL and the filter will use the active scalar array. + vtkGetStringMacro(InputScalarsSelection); + void SelectInputScalars(const char *fieldName) + {this->SetInputScalarsSelection(fieldName);} + + // Description: + // If you want to use an arbitrary vectors array, then set its name here. + // By default this in NULL and the filter will use the active vector array. + vtkGetStringMacro(InputVectorsSelection); + void SelectInputVectors(const char *fieldName) + {this->SetInputVectorsSelection(fieldName);} + + // Description: + // If you want to use an arbitrary normals array, then set its name here. + // By default this in NULL and the filter will use the active normal array. + vtkGetStringMacro(InputNormalsSelection); + void SelectInputNormals(const char *fieldName) + {this->SetInputNormalsSelection(fieldName);} + +protected: + vtkGenericGlyph3DFilter(); + ~vtkGenericGlyph3DFilter(); + + int FillInputPortInformation(int, vtkInformation*); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + vtkPolyData **Source; // Geometry to copy to each point + int Scaling; // Determine whether scaling of geometry is performed + int ScaleMode; // Scale by scalar value or vector magnitude + int ColorMode; // new scalars based on scale, scalar or vector + double ScaleFactor; // Scale factor to use to scale geometry + double Range[2]; // Range to use to perform scalar scaling + int Orient; // boolean controls whether to "orient" data + int VectorMode; // Orient/scale via normal or via vector data + int Clamping; // whether to clamp scale factor + int IndexMode; // what to use to index into glyph table + int GeneratePointIds; // produce input points ids for each output point + char *PointIdsName; + + char *InputScalarsSelection; + char *InputVectorsSelection; + char *InputNormalsSelection; + vtkSetStringMacro(InputScalarsSelection); + vtkSetStringMacro(InputVectorsSelection); + vtkSetStringMacro(InputNormalsSelection); + +private: + vtkGenericGlyph3DFilter(const vtkGenericGlyph3DFilter&); // Not implemented. + void operator=(const vtkGenericGlyph3DFilter&); // Not implemented. +}; + +// Description: +// Return the method of scaling as a descriptive character string. +inline const char *vtkGenericGlyph3DFilter::GetScaleModeAsString(void) +{ + if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ) + { + return "ScaleByScalar"; + } + else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) + { + return "ScaleByVector"; + } + else + { + return "DataScalingOff"; + } +} + +// Description: +// Return the method of coloring as a descriptive character string. +inline const char *vtkGenericGlyph3DFilter::GetColorModeAsString(void) +{ + if ( this->ColorMode == VTK_COLOR_BY_SCALAR ) + { + return "ColorByScalar"; + } + else if ( this->ColorMode == VTK_COLOR_BY_VECTOR ) + { + return "ColorByVector"; + } + else + { + return "ColorByScale"; + } +} + +// Description: +// Return the vector mode as a character string. +inline const char *vtkGenericGlyph3DFilter::GetVectorModeAsString(void) +{ + if ( this->VectorMode == VTK_USE_VECTOR) + { + return "UseVector"; + } + else if ( this->VectorMode == VTK_USE_NORMAL) + { + return "UseNormal"; + } + else + { + return "VectorRotationOff"; + } +} + +// Description: +// Return the index mode as a character string. +inline const char *vtkGenericGlyph3DFilter::GetIndexModeAsString(void) +{ + if ( this->IndexMode == VTK_INDEXING_OFF) + { + return "IndexingOff"; + } + else if ( this->IndexMode == VTK_INDEXING_BY_SCALAR) + { + return "IndexingByScalar"; + } + else + { + return "IndexingByVector"; + } +} + +#endif diff --git a/GenericFiltering/vtkGenericOutlineFilter.cxx b/GenericFiltering/vtkGenericOutlineFilter.cxx new file mode 100644 index 0000000..1de22f8 --- /dev/null +++ b/GenericFiltering/vtkGenericOutlineFilter.cxx @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericOutlineFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericOutlineFilter.h" + +#include "vtkGenericDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineSource.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkGenericOutlineFilter, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkGenericOutlineFilter); + +vtkGenericOutlineFilter::vtkGenericOutlineFilter () +{ + this->OutlineSource = vtkOutlineSource::New(); +} + +vtkGenericOutlineFilter::~vtkGenericOutlineFilter () +{ + if (this->OutlineSource != NULL) + { + this->OutlineSource->Delete (); + this->OutlineSource = NULL; + } +} + +int vtkGenericOutlineFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + +// vtkPolyData *output = this->GetOutput(); + + vtkDebugMacro(<< "Creating dataset outline"); + + // + // Let OutlineSource do all the work + // + + this->OutlineSource->SetBounds(input->GetBounds()); + this->OutlineSource->Update(); + + output->CopyStructure(this->OutlineSource->GetOutput()); + return 1; +} + + +int vtkGenericOutlineFilter::RequestInformation( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects +// vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); +// vtkInformation *outInfo = outputVector->GetInformationObject(0); + + + vtkDebugMacro(<< "Creating dataset outline"); + + // + // Let OutlineSource do all the work + // + + int result=this->Superclass::RequestInformation(request,inputVector, + outputVector); + + this->OutlineSource->UpdateInformation(); + + return result; +} + +//---------------------------------------------------------------------------- +int vtkGenericOutlineFilter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + return 1; +} diff --git a/GenericFiltering/vtkGenericOutlineFilter.h b/GenericFiltering/vtkGenericOutlineFilter.h new file mode 100644 index 0000000..181c8c3 --- /dev/null +++ b/GenericFiltering/vtkGenericOutlineFilter.h @@ -0,0 +1,50 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericOutlineFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericOutlineFilter - create wireframe outline for arbitrary +// generic data set +// .SECTION Description +// vtkGenericOutlineFilter is a filter that generates a wireframe outline of +// any generic data set. The outline consists of the twelve edges of the +// generic dataset bounding box. + +#ifndef __vtkGenericOutlineFilter_h +#define __vtkGenericOutlineFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkOutlineSource; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericOutlineFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkGenericOutlineFilter *New(); + vtkTypeRevisionMacro(vtkGenericOutlineFilter,vtkPolyDataAlgorithm); + +protected: + vtkGenericOutlineFilter(); + ~vtkGenericOutlineFilter(); + + vtkOutlineSource *OutlineSource; + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int FillInputPortInformation(int, vtkInformation*); + +private: + vtkGenericOutlineFilter(const vtkGenericOutlineFilter&); // Not implemented. + void operator=(const vtkGenericOutlineFilter&); // Not implemented. +}; + +#endif diff --git a/GenericFiltering/vtkGenericProbeFilter.cxx b/GenericFiltering/vtkGenericProbeFilter.cxx new file mode 100644 index 0000000..953d20a --- /dev/null +++ b/GenericFiltering/vtkGenericProbeFilter.cxx @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericProbeFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericProbeFilter.h" + +#include "vtkCell.h" +#include "vtkIdTypeArray.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkGenericDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCellIterator.h" +#include "vtkGenericAdaptorCell.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAttributeCollection.h" + +vtkCxxRevisionMacro(vtkGenericProbeFilter, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkGenericProbeFilter); + +//---------------------------------------------------------------------------- +vtkGenericProbeFilter::vtkGenericProbeFilter() +{ + this->ValidPoints = vtkIdTypeArray::New(); +} + +//---------------------------------------------------------------------------- +vtkGenericProbeFilter::~vtkGenericProbeFilter() +{ + this->ValidPoints->Delete(); + this->ValidPoints = NULL; +} + + +//---------------------------------------------------------------------------- +void vtkGenericProbeFilter::SetSource(vtkGenericDataSet *input) +{ + this->vtkProcessObject::SetNthInput(1, input); +} + +//---------------------------------------------------------------------------- +vtkGenericDataSet *vtkGenericProbeFilter::GetSource() +{ + if (this->NumberOfInputs < 2) + { + return NULL; + } + + return (vtkGenericDataSet *)(this->Inputs[1]); +} + + +//---------------------------------------------------------------------------- +void vtkGenericProbeFilter::Execute() +{ + vtkIdType ptId, numPts; + double x[3], tol2; +// vtkCell *cell; + vtkPointData *outPD; + int subId; + vtkGenericDataSet *source = this->GetSource(); + vtkDataSet *input = this->GetInput(); + vtkDataSet *output= this->GetOutput(); + double pcoords[3], *weights; + double fastweights[256]; + + vtkDebugMacro(<<"Probing data"); + + if (source == NULL) + { + vtkErrorMacro (<< "Source is NULL."); + return; + } + +// pd = source->GetPointData(); + //pd = NULL; + //int size = input->GetNumberOfPoints(); + + // lets use a stack allocated array if possible for performance reasons + int mcs = 255; //source->GetMaxCellSize(); //FIXME + if (mcs<=256) + { + weights = fastweights; + } + else + { + weights = new double[mcs]; + } + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + numPts = input->GetNumberOfPoints(); + this->ValidPoints->Allocate(numPts); + + // Allocate storage for output PointData + // + outPD = output->GetPointData(); + //outPD->InterpolateAllocate(pd, size, size); + vtkDoubleArray *foobar = vtkDoubleArray::New(); + outPD->SetScalars( foobar ); + + // Use tolerance as a function of size of source data + // +// tol2 = source->GetLength(); + tol2 = 1000; //FIXME + tol2 = tol2 ? tol2*tol2 / 1000.0 : 0.001; + + // Loop over all input points, interpolating source data + // + int abort=0; + // Need to use source to create a cellIt since this class is virtual + vtkGenericCellIterator *cellIt = source->NewCellIterator(); + + vtkIdType progressInterval=numPts/20 + 1; + for (ptId=0; ptId < numPts && !abort; ptId++) + { + if ( !(ptId % progressInterval) ) + { + this->UpdateProgress((double)ptId/numPts); + abort = GetAbortExecute(); + } + + // Get the xyz coordinate of the point in the input dataset + input->GetPoint(ptId, x); + + // Find the cell that contains xyz and get it + if(source->FindCell(x,cellIt,tol2,subId,pcoords)) + { + // Interpolate the point data + vtkGenericAdaptorCell *cellProbe = cellIt->GetCell(); + double s[3]; // FIXME: should be double *s=new double[source->GetAttributes()->GetNumberOfComponents()] + //cellProbe->EvaluateShapeFunction(x,s); + //source->GetAttributes()->EvaluateTuple(cellProbe, x,s); + cellProbe->InterpolateTuple(source->GetAttributes(), x,s); + foobar->InsertTuple( ptId, s); + this->ValidPoints->InsertNextValue(ptId); + } + else + { + outPD->NullPoint(ptId); + } + } + cellIt->Delete(); + + // BUG FIX: JB. + // Output gets setup from input, but when output is imagedata, scalartype + // depends on source scalartype not input scalartype + if (output->IsA("vtkImageData")) + { + vtkImageData *out = (vtkImageData*)output; + vtkDataArray *s = outPD->GetScalars(); + out->SetScalarType(s->GetDataType()); + out->SetNumberOfScalarComponents(s->GetNumberOfComponents()); + } + if (mcs>256) + { + delete [] weights; + } +} + + +//---------------------------------------------------------------------------- +void vtkGenericProbeFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkGenericDataSet *source = this->GetSource(); + + this->Superclass::PrintSelf(os,indent); + + os << indent << "Source: " << source << "\n"; + os << indent << "ValidPoints: " << this->ValidPoints << "\n"; +} diff --git a/GenericFiltering/vtkGenericProbeFilter.h b/GenericFiltering/vtkGenericProbeFilter.h new file mode 100644 index 0000000..bd6c295 --- /dev/null +++ b/GenericFiltering/vtkGenericProbeFilter.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericProbeFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericProbeFilter - sample data values at specified point locations +// .SECTION Description +// vtkGenericProbeFilter is a filter that computes point attributes (e.g., scalars, +// vectors, etc.) at specified point positions. The filter has two inputs: +// the Input and Source. The Input geometric structure is passed through the +// filter. The point attributes are computed at the Input point positions +// by interpolating into the source data. For example, we can compute data +// values on a plane (plane specified as Input) from a volume (Source). +// +// This filter can be used to resample data, or convert one dataset form into +// another. For example, a generic dataset can be probed with a volume +// (three-dimensional vtkImageData), and then volume rendering techniques can +// be used to visualize the results. Another example: a line or curve can be +// used to probe data to produce x-y plots along that line or curve. +// +// This filter has been implemented to operate on generic datasets, rather +// than the typical vtkDataSet (and subclasses). vtkGenericDataSet is a more +// complex cousin of vtkDataSet, typically consisting of nonlinear, +// higher-order cells. To process this type of data, generic cells are +// automatically tessellated into linear cells prior to isocontouring. + +// .SECTION See Also +// vtkGenericProbeFilter vtkProbeFilter vtkGenericDataSet + + +#ifndef __vtkGenericProbeFilter_h +#define __vtkGenericProbeFilter_h + +#include "vtkDataSetToDataSetFilter.h" + +class vtkIdTypeArray; +class vtkGenericDataSet; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericProbeFilter : public vtkDataSetToDataSetFilter +{ +public: + static vtkGenericProbeFilter *New(); + vtkTypeRevisionMacro(vtkGenericProbeFilter,vtkDataSetToDataSetFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the point locations used to probe input. A generic dataset + // type is assumed. + void SetSource(vtkGenericDataSet *source); + vtkGenericDataSet *GetSource(); + + // Description: + // Get the list of point ids in the output that contain attribute data + // interpolated from the source. + vtkGetObjectMacro(ValidPoints, vtkIdTypeArray); + +protected: + vtkGenericProbeFilter(); + ~vtkGenericProbeFilter(); + + virtual void Execute(); + + vtkIdTypeArray *ValidPoints; + +private: + vtkGenericProbeFilter(const vtkGenericProbeFilter&); // Not implemented. + void operator=(const vtkGenericProbeFilter&); // Not implemented. +}; + +#endif diff --git a/GenericFiltering/vtkGenericStreamTracer.cxx b/GenericFiltering/vtkGenericStreamTracer.cxx new file mode 100644 index 0000000..d643c27 --- /dev/null +++ b/GenericFiltering/vtkGenericStreamTracer.cxx @@ -0,0 +1,1433 @@ +/*========================================================================= + + Program: Visualization Toolkits + Module: $RCSfile: vtkGenericStreamTracer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericStreamTracer.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkGenericInterpolatedVelocityField.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyLine.h" +#include "vtkRungeKutta2.h" +#include "vtkRungeKutta4.h" +#include "vtkRungeKutta45.h" +#include "vtkGenericDataSet.h" +#include "vtkGenericAttributeCollection.h" +#include "vtkGenericAttribute.h" +#include "vtkGenericAdaptorCell.h" +#include + +#include "vtkInformation.h" +#include "vtkExecutive.h" // for GetExecutive() +#include "vtkInformationVector.h" + +vtkCxxRevisionMacro(vtkGenericStreamTracer, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkGenericStreamTracer); +vtkCxxSetObjectMacro(vtkGenericStreamTracer,Integrator,vtkInitialValueProblemSolver); +vtkCxxSetObjectMacro(vtkGenericStreamTracer,InterpolatorPrototype,vtkGenericInterpolatedVelocityField); + +const double vtkGenericStreamTracer::EPSILON = 1.0E-12; + +//----------------------------------------------------------------------------- +vtkGenericStreamTracer::vtkGenericStreamTracer() +{ + this->SetNumberOfInputPorts(2); + + this->Integrator = vtkRungeKutta2::New(); + this->IntegrationDirection = FORWARD; + for(int i=0; i<3; i++) + { + this->StartPosition[i] = 0.0; + } + this->MaximumPropagation.Unit = LENGTH_UNIT; + this->MaximumPropagation.Interval = 1.0; + + this->MinimumIntegrationStep.Unit = CELL_LENGTH_UNIT; + this->MinimumIntegrationStep.Interval = 1.0E-2; + + this->MaximumIntegrationStep.Unit = CELL_LENGTH_UNIT; + this->MaximumIntegrationStep.Interval = 1.0; + + this->InitialIntegrationStep.Unit = CELL_LENGTH_UNIT; + this->InitialIntegrationStep.Interval = 0.5; + + this->MaximumError = 1.0e-6; + + this->MaximumNumberOfSteps = 2000; + + this->TerminalSpeed = EPSILON; + + this->ComputeVorticity = 1; + this->RotationScale = 1.0; + + this->InputVectorsSelection = 0; + + this->LastUsedTimeStep = 0.0; + + this->GenerateNormalsInIntegrate = 1; + + this->InterpolatorPrototype = 0; +} + +//----------------------------------------------------------------------------- +vtkGenericStreamTracer::~vtkGenericStreamTracer() +{ + this->SetIntegrator(0); + this->SetInputVectorsSelection(0); + this->SetInterpolatorPrototype(0); +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetSource(vtkDataSet *source) +{ + this->SetInputConnection(1, source->GetProducerPort()); +} + +//----------------------------------------------------------------------------- +vtkDataSet *vtkGenericStreamTracer::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) // because the port is optional + { + return 0; + } + return static_cast(this->GetExecutive()->GetInputData(1, 0)); +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::AddInput(vtkGenericDataSet* input) +{ + this->Superclass::AddInput(input); +} + + +//---------------------------------------------------------------------------- +int vtkGenericStreamTracer +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + if(port==1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(),1); + } + else + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet"); + } + return 1; +} + + +//----------------------------------------------------------------------------- +int vtkGenericStreamTracer::GetIntegratorType() +{ + if (!this->Integrator) + { + return NONE; + } + if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta2")) + { + return RUNGE_KUTTA2; + } + if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta4")) + { + return RUNGE_KUTTA4; + } + if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta45")) + { + return RUNGE_KUTTA45; + } + return UNKNOWN; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetIntegratorType(int type) +{ + vtkInitialValueProblemSolver* ivp=0; + switch (type) + { + case RUNGE_KUTTA2: + ivp = vtkRungeKutta2::New(); + break; + case RUNGE_KUTTA4: + ivp = vtkRungeKutta4::New(); + break; + case RUNGE_KUTTA45: + ivp = vtkRungeKutta45::New(); + break; + default: + vtkWarningMacro("Unrecognized integrator type. Keeping old one."); + break; + } + if (ivp) + { + this->SetIntegrator(ivp); + ivp->Delete(); + } +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetIntervalInformation( + int unit, + vtkGenericStreamTracer::IntervalInformation& currentValues) +{ + if ( unit == currentValues.Unit ) + { + return; + } + + if ( (unit < TIME_UNIT) || (unit > CELL_LENGTH_UNIT) ) + { + vtkWarningMacro("Unrecognized unit. Using TIME_UNIT instead."); + currentValues.Unit = TIME_UNIT; + } + else + { + currentValues.Unit = unit; + } + + this->Modified(); +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetIntervalInformation( + int unit, + double interval, vtkGenericStreamTracer::IntervalInformation& currentValues) +{ + if ( (unit == currentValues.Unit) && (interval == currentValues.Interval) ) + { + return; + } + + this->SetIntervalInformation(unit, currentValues); + + currentValues.Interval = interval; + this->Modified(); +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMaximumPropagation(int unit, double max) +{ + this->SetIntervalInformation(unit, max, this->MaximumPropagation); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMaximumPropagation( double max) +{ + if ( max == this->MaximumPropagation.Interval ) + { + return; + } + this->MaximumPropagation.Interval = max; + this->Modified(); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMaximumPropagationUnit(int unit) +{ + this->SetIntervalInformation(unit, this->MaximumPropagation); +} +//----------------------------------------------------------------------------- +int vtkGenericStreamTracer::GetMaximumPropagationUnit() +{ + return this->MaximumPropagation.Unit; +} +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::GetMaximumPropagation() +{ + return this->MaximumPropagation.Interval; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMinimumIntegrationStep(int unit, double step) +{ + this->SetIntervalInformation(unit, step, this->MinimumIntegrationStep); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMinimumIntegrationStepUnit(int unit) +{ + this->SetIntervalInformation(unit, this->MinimumIntegrationStep); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMinimumIntegrationStep(double step) +{ + if ( step == this->MinimumIntegrationStep.Interval ) + { + return; + } + this->MinimumIntegrationStep.Interval = step; + this->Modified(); +} +//----------------------------------------------------------------------------- +int vtkGenericStreamTracer::GetMinimumIntegrationStepUnit() +{ + return this->MinimumIntegrationStep.Unit; +} +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::GetMinimumIntegrationStep() +{ + return this->MinimumIntegrationStep.Interval; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMaximumIntegrationStep(int unit, double step) +{ + this->SetIntervalInformation(unit, step, this->MaximumIntegrationStep); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMaximumIntegrationStepUnit(int unit) +{ + this->SetIntervalInformation(unit, this->MaximumIntegrationStep); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetMaximumIntegrationStep(double step) +{ + if ( step == this->MaximumIntegrationStep.Interval ) + { + return; + } + this->MaximumIntegrationStep.Interval = step; + this->Modified(); +} +//----------------------------------------------------------------------------- +int vtkGenericStreamTracer::GetMaximumIntegrationStepUnit() +{ + return this->MaximumIntegrationStep.Unit; +} +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::GetMaximumIntegrationStep() +{ + return this->MaximumIntegrationStep.Interval; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetInitialIntegrationStep(int unit, double step) +{ + this->SetIntervalInformation(unit, step, this->InitialIntegrationStep); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetInitialIntegrationStepUnit(int unit) +{ + this->SetIntervalInformation(unit, this->InitialIntegrationStep); +} +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::SetInitialIntegrationStep(double step) +{ + if ( step == this->InitialIntegrationStep.Interval ) + { + return; + } + this->InitialIntegrationStep.Interval = step; + this->Modified(); +} +//----------------------------------------------------------------------------- +int vtkGenericStreamTracer::GetInitialIntegrationStepUnit() +{ + return this->InitialIntegrationStep.Unit; +} +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::GetInitialIntegrationStep() +{ + return this->InitialIntegrationStep.Interval; +} + +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::ConvertToTime( + vtkGenericStreamTracer::IntervalInformation& interval, + double cellLength, + double speed) +{ + double retVal = 0.0; + switch (interval.Unit) + { + case TIME_UNIT: + retVal = interval.Interval; + break; + case LENGTH_UNIT: + retVal = interval.Interval/speed; + break; + case CELL_LENGTH_UNIT: + retVal = interval.Interval*cellLength/speed; + break; + } + return retVal; +} + +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::ConvertToLength( + vtkGenericStreamTracer::IntervalInformation& interval, + double cellLength, + double speed) +{ + double retVal = 0.0; + switch (interval.Unit) + { + case TIME_UNIT: + retVal = interval.Interval * speed; + break; + case LENGTH_UNIT: + retVal = interval.Interval; + break; + case CELL_LENGTH_UNIT: + retVal = interval.Interval*cellLength; + break; + } + return retVal; +} + +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::ConvertToCellLength( + vtkGenericStreamTracer::IntervalInformation& interval, + double cellLength, + double speed) +{ + double retVal = 0.0; + switch (interval.Unit) + { + case TIME_UNIT: + retVal = (interval.Interval * speed)/cellLength; + break; + case LENGTH_UNIT: + retVal = interval.Interval/cellLength; + break; + case CELL_LENGTH_UNIT: + retVal = interval.Interval; + break; + } + return retVal; +} + +//----------------------------------------------------------------------------- +double vtkGenericStreamTracer::ConvertToUnit( + vtkGenericStreamTracer::IntervalInformation& interval, + int unit, + double cellLength, + double speed) +{ + double retVal = 0.0; + switch (unit) + { + case TIME_UNIT: + retVal = ConvertToTime(interval, cellLength, speed); + break; + case LENGTH_UNIT: + retVal = ConvertToLength(interval, cellLength, speed); + break; + case CELL_LENGTH_UNIT: + retVal = ConvertToCellLength(interval, cellLength, speed); + break; + } + return retVal; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::ConvertIntervals(double& step, + double& minStep, + double& maxStep, + int direction, + double cellLength, + double speed) +{ + step = direction * this->ConvertToTime( + this->InitialIntegrationStep, cellLength, speed); + if ( this->MinimumIntegrationStep.Interval <= 0.0 ) + { + minStep = step; + } + else + { + minStep = this->ConvertToTime(this->MinimumIntegrationStep, cellLength, + speed); + } + if ( this->MaximumIntegrationStep.Interval <= 0.0 ) + { + maxStep = step; + } + else + { + maxStep = this->ConvertToTime(this->MaximumIntegrationStep,cellLength, + speed); + } +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::CalculateVorticity(vtkGenericAdaptorCell* cell, + double pcoords[3], + vtkGenericAttribute *attribute, + double vorticity[3]) +{ + assert("pre: attribute_exists" && attribute!=0); + assert("pre: point_centered_attribute" && attribute->GetCentering()==vtkPointCentered); + assert("pre: vector_attribute" && attribute->GetType()==vtkDataSetAttributes::VECTORS); + + double derivs[9]; + cell->Derivatives(0,pcoords,attribute,derivs); + + vorticity[0] = derivs[7] - derivs[5]; + vorticity[1] = derivs[2] - derivs[6]; + vorticity[2] = derivs[3] - derivs[1]; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::InitializeSeeds( + vtkDataArray*& seeds, + vtkIdList*& seedIds, + vtkIntArray*& integrationDirections) +{ + vtkDataSet* source = this->GetSource(); + seedIds = vtkIdList::New(); + integrationDirections = vtkIntArray::New(); + seeds=0; + + if (source) + { + int i; + vtkIdType numSeeds = source->GetNumberOfPoints(); + if (numSeeds > 0) + { + // For now, one thread will do all + + if (this->IntegrationDirection == BOTH) + { + seedIds->SetNumberOfIds(2*numSeeds); + for (i=0; iSetId(i, i); + seedIds->SetId(numSeeds + i, i); + } + } + else + { + seedIds->SetNumberOfIds(numSeeds); + for (i=0; iSetId(i, i); + } + } + // Check if the source is a PointSet + vtkPointSet* seedPts = vtkPointSet::SafeDownCast(source); + if (seedPts) + { + // If it is, use it's points as source + vtkDataArray* orgSeeds = seedPts->GetPoints()->GetData(); + seeds = orgSeeds->NewInstance(); + seeds->DeepCopy(orgSeeds); + } + else + { + // Else, create a seed source + seeds = vtkDoubleArray::New(); + seeds->SetNumberOfComponents(3); + seeds->SetNumberOfTuples(numSeeds); + for (i=0; iSetTuple(i, source->GetPoint(i)); + } + } + } + } + else + { + seeds = vtkDoubleArray::New(); + seeds->SetNumberOfComponents(3); + seeds->InsertNextTuple(this->StartPosition); + seedIds->InsertNextId(0); + if (this->IntegrationDirection == BOTH) + { + seedIds->InsertNextId(0); + } + } + + if (seeds) + { + vtkIdType i; + vtkIdType numSeeds = seeds->GetNumberOfTuples(); + if (this->IntegrationDirection == BOTH) + { + for(i=0; iInsertNextValue(FORWARD); + } + for(i=0; iInsertNextValue(BACKWARD); + } + } + else + { + for(i=0; iInsertNextValue(this->IntegrationDirection); + } + } + } +} + +//----------------------------------------------------------------------------- +int vtkGenericStreamTracer::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and output + vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray* seeds = 0; + vtkIdList* seedIds = 0; + vtkIntArray* integrationDirections = 0; + this->InitializeSeeds(seeds, seedIds, integrationDirections); + + if (seeds) + { + double lastPoint[3]; + vtkGenericInterpolatedVelocityField* func; + if (this->CheckInputs(func, inputVector) != VTK_OK) + { + vtkDebugMacro("No appropriate inputs have been found. Can not execute."); + func->Delete(); + seeds->Delete(); + integrationDirections->Delete(); + seedIds->Delete(); + return 1; + } + this->Integrate(input, + output, + seeds, + seedIds, + integrationDirections, + lastPoint, + func); + func->Delete(); + seeds->Delete(); + } + + integrationDirections->Delete(); + seedIds->Delete(); + return 1; +} + +//----------------------------------------------------------------------------- +int vtkGenericStreamTracer::CheckInputs( + vtkGenericInterpolatedVelocityField*& func, + vtkInformationVector **inputVector + ) +{ + // Set the function set to be integrated + if (!this->InterpolatorPrototype) + { + func = vtkGenericInterpolatedVelocityField::New(); + } + else + { + func = this->InterpolatorPrototype->NewInstance(); + func->CopyParameters(this->InterpolatorPrototype); + } + func->SelectVectors(this->InputVectorsSelection); + + // Add all the inputs ( except source, of course ) which + // have the appropriate vectors and compute the maximum + // cell size. + int numInputs = 0; + int numInputConnections = this->GetNumberOfInputConnections(0); + for (int i = 0; i < numInputConnections; i++) + { + vtkInformation *info = inputVector[0]->GetInformationObject(i); + vtkGenericDataSet* inp=0; + + if(info!=0) + { + inp = vtkGenericDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + } + if(inp!=0) + { + int attrib; + int attributeFound; + if(this->InputVectorsSelection!=0) + { + attrib=inp->GetAttributes()->FindAttribute(this->InputVectorsSelection); + + attributeFound=attrib>=0; + if(attributeFound) + { + attributeFound=(inp->GetAttributes()->GetAttribute(attrib)->GetType()==vtkDataSetAttributes::VECTORS)&&(inp->GetAttributes()->GetAttribute(attrib)->GetCentering()==vtkPointCentered); + } + } + else + { + // Find the first attribute, point centered and with vector type. + attrib=0; + attributeFound=0; + int c=inp->GetAttributes()->GetNumberOfAttributes(); + while(attribGetAttributes()->GetAttribute(attrib)->GetType()==vtkDataSetAttributes::VECTORS)&&(inp->GetAttributes()->GetAttribute(attrib)->GetCentering()==vtkPointCentered); + ++attrib; + } + if(attributeFound) + { + --attrib; + this->SetInputVectorsSelection(inp->GetAttributes()->GetAttribute(attrib)->GetName()); + } + } + if (!attributeFound) + { + vtkDebugMacro("Input " << i << "does not contain a velocity vector."); + continue; + } + func->AddDataSet(inp); + numInputs++; + } + } + if ( numInputs == 0 ) + { + vtkDebugMacro("No appropriate inputs have been found. Can not execute."); + return VTK_ERROR; + } + return VTK_OK; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::Integrate( + vtkGenericDataSet *input0, + vtkPolyData* output, + vtkDataArray* seedSource, + vtkIdList* seedIds, + vtkIntArray* integrationDirections, + double lastPoint[3], + vtkGenericInterpolatedVelocityField* func) +{ + int i; + vtkIdType numLines = seedIds->GetNumberOfIds(); + + // Useful pointers + vtkDataSetAttributes* outputPD = output->GetPointData(); + vtkDataSetAttributes* outputCD = output->GetCellData(); + vtkGenericDataSet* input; + vtkGenericAttribute* inVectors; + + int direction=1; + + if (this->GetIntegrator() == 0) + { + vtkErrorMacro("No integrator is specified."); + return; + } + + // Used in GetCell() +// vtkGenericCell* cell = vtkGenericCell::New(); + vtkGenericAdaptorCell *cell=0; + + // Create a new integrator, the type is the same as Integrator + vtkInitialValueProblemSolver* integrator = + this->GetIntegrator()->NewInstance(); + integrator->SetFunctionSet(func); + + // Since we do not know what the total number of points + // will be, we do not allocate any. This is important for + // cases where a lot of streamers are used at once. If we + // were to allocate any points here, potentially, we can + // waste a lot of memory if a lot of streamers are used. + // Always insert the first point + vtkPoints* outputPoints = vtkPoints::New(); + vtkCellArray* outputLines = vtkCellArray::New(); + + // We will keep track of time in this array + vtkDoubleArray* time = vtkDoubleArray::New(); + time->SetName("IntegrationTime"); + + // This array explains why the integration stopped + vtkIntArray* retVals = vtkIntArray::New(); + retVals->SetName("ReasonForTermination"); + + vtkDoubleArray* vorticity = 0; + vtkDoubleArray* rotation = 0; + vtkDoubleArray* angularVel = 0; + if (this->ComputeVorticity) + { + vorticity = vtkDoubleArray::New(); + vorticity->SetName("Vorticity"); + vorticity->SetNumberOfComponents(3); + + rotation = vtkDoubleArray::New(); + rotation->SetName("Rotation"); + + angularVel = vtkDoubleArray::New(); + angularVel->SetName("AngularVelocity"); + } + + // We will interpolate all point attributes of the input on + // each point of the output (unless they are turned off) + // Note that we are using only the first input, if there are more + // than one, the attributes have to match. + + // prepare the output attributes + vtkGenericAttributeCollection *attributes=input0->GetAttributes(); + vtkGenericAttribute *attribute; + vtkDataArray *attributeArray; + + int c=attributes->GetNumberOfAttributes(); + int attributeType; + + // Only point centered attributes will be interpolated. + // Cell centered attributes are not ignored and not copied in output: + // is a missing part in vtkStreamTracer? Need to ask to the Berk. + i=0; + while(iGetAttribute(i); + attributeType=attribute->GetType(); + if(attribute->GetCentering()==vtkPointCentered) + { + attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType()); + attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents()); + attributeArray->SetName(attribute->GetName()); + outputPD->AddArray(attributeArray); + attributeArray->Delete(); + + if(outputPD->GetAttribute(attributeType)==0) + { + outputPD->SetActiveAttribute(outputPD->GetNumberOfArrays()-1, + attributeType); + } + } + ++i; + } + double *values=new double[outputPD->GetNumberOfComponents()]; // point centered attributes at some point. + + + // Note: It is an overestimation to have the estimate the same number of + // output points and input points. We sill have to squeeze at end. + + vtkIdType numPtsTotal=0; + double velocity[3]; + + int shouldAbort = 0; + + for(int currentLine = 0; currentLine < numLines; currentLine++) + { + + double progress = static_cast(currentLine)/numLines; + this->UpdateProgress(progress); + + switch (integrationDirections->GetValue(currentLine)) + { + case FORWARD: + direction = 1; + break; + case BACKWARD: + direction = -1; + break; + } + + // temporary variables used in the integration + double point1[3], point2[3], pcoords[3], vort[3], omega; + vtkIdType index, numPts=0; + + // Clear the last cell to avoid starting a search from + // the last point in the streamline + func->ClearLastCell(); + + + // Initial point + seedSource->GetTuple(seedIds->GetId(currentLine), point1); + memcpy(point2, point1, 3*sizeof(double)); + if (!func->FunctionValues(point1, velocity)) + { + continue; + } + + numPts++; + numPtsTotal++; + vtkIdType nextPoint = outputPoints->InsertNextPoint(point1); + time->InsertNextValue(0.0); + + // We will always pass a time step to the integrator. + // If the user specifies a step size with another unit, we will + // have to convert it to time. + IntervalInformation delT; + delT.Unit = TIME_UNIT; + delT.Interval = 0; + IntervalInformation aStep; + aStep.Unit = this->MaximumPropagation.Unit; + double propagation = 0.0, step, minStep=0, maxStep=0; + double stepTaken, accumTime=0; + double speed; + double cellLength; + int retVal=OUT_OF_TIME, tmp; + + // Make sure we use the dataset found + // by the vtkGenericInterpolatedVelocityField + input = func->GetLastDataSet(); + + inVectors=input->GetAttributes()->GetAttribute(input->GetAttributes()->FindAttribute(this->InputVectorsSelection)); + + // Convert intervals to time unit + cell=func->GetLastCell(); + cellLength = sqrt(static_cast(cell->GetLength2())); + speed = vtkMath::Norm(velocity); + + // Never call conversion methods if speed == 0 + if (speed != 0.0) + { + this->ConvertIntervals(delT.Interval, minStep, maxStep, direction, + cellLength, speed); + } + + // Interpolate all point attributes on first point + func->GetLastLocalCoordinates(pcoords); + cell->InterpolateTuple(input->GetAttributes(),pcoords, + values); + + double *p=values; + vtkDataArray *dataArray; + c=outputPD->GetNumberOfArrays(); + int j=0; + while(jGetArray(j); + dataArray->InsertTuple(nextPoint,p); + ++j; + p=p+dataArray->GetNumberOfComponents(); + } + + // Compute vorticity if required + // This can be used later for streamribbon generation. + if (this->ComputeVorticity) + { + // Here, we're assuming a linear cell by only taken values at + // corner points. there should be a subdivision step here instead. + // What is the criterium to stop the subdivision? + // Note: the original vtkStreamTracer is taking cell points, it means + // that for the quadratic cell, the standard stream tracer is more + // accurate than this one! + vtkGenericStreamTracer::CalculateVorticity(cell, pcoords, inVectors, + vort); + + vorticity->InsertNextTuple(vort); + // rotation + // local rotation = vorticity . unit tangent ( i.e. velocity/speed ) + if (speed != 0.0) + { + omega = vtkMath::Dot(vort, velocity); + omega /= speed; + omega *= this->RotationScale; + } + else + { + omega = 0.0; + } + angularVel->InsertNextValue(omega); + rotation->InsertNextValue(0.0); + } + + vtkIdType numSteps = 0; + double error = 0; + // Integrate until the maximum propagation length is reached, + // maximum number of steps is reached or until a boundary is encountered. + // Begin Integration + while ( propagation < this->MaximumPropagation.Interval ) + { + + if (numSteps > this->MaximumNumberOfSteps) + { + retVal = OUT_OF_STEPS; + break; + } + + if ( numSteps++ % 1000 == 1 ) + { + progress = + (currentLine + propagation / this->MaximumPropagation.Interval) / + numLines ; + this->UpdateProgress(progress); + + if (this->GetAbortExecute()) + { + shouldAbort = 1; + break; + } + } + + // Never call conversion methods if speed == 0 + if ( (speed == 0) || (speed <= this->TerminalSpeed) ) + { + retVal = STAGNATION; + break; + } + + // If, with the next step, propagation will be larger than + // max, reduce it so that it is (approximately) equal to max. + aStep.Interval = fabs(this->ConvertToUnit(delT, + this->MaximumPropagation.Unit, + cellLength, speed)); + if ( (propagation + aStep.Interval) > + this->MaximumPropagation.Interval ) + { + aStep.Interval = this->MaximumPropagation.Interval - propagation; + if (delT.Interval >= 0) + { + delT.Interval = this->ConvertToTime(aStep, cellLength, speed); + } + else + { + delT.Interval = -1.0 * this->ConvertToTime(aStep, cellLength, speed); + } + maxStep = delT.Interval; + } + this->LastUsedTimeStep = delT.Interval; + + // Calculate the next step using the integrator provided + // Break if the next point is out of bounds. + if ((tmp= + integrator->ComputeNextStep(point1, point2, 0, delT.Interval, + stepTaken, minStep, maxStep, + this->MaximumError, error)) != 0) + { + retVal = tmp; + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + + accumTime += stepTaken; + // Calculate propagation (using the same units as MaximumPropagation + propagation += fabs(this->ConvertToUnit(delT, + this->MaximumPropagation.Unit, + cellLength, speed)); + + + // This is the next starting point + for(i=0; i<3; i++) + { + point1[i] = point2[i]; + } + + // Interpolate the velocity at the next point + if ( !func->FunctionValues(point2, velocity) ) + { + retVal = OUT_OF_DOMAIN; + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + + // Make sure we use the dataset found by the vtkInterpolatedVelocityField + input = func->GetLastDataSet(); + + inVectors=input->GetAttributes()->GetAttribute(input->GetAttributes()->FindAttribute(this->InputVectorsSelection)); + + + // Point is valid. Insert it. + numPts++; + numPtsTotal++; + nextPoint = outputPoints->InsertNextPoint(point1); + time->InsertNextValue(accumTime); + + // Calculate cell length and speed to be used in unit conversions + cell=func->GetLastCell(); + cellLength = sqrt(static_cast(cell->GetLength2())); + + speed = vtkMath::Norm(velocity); + + // Interpolate all point attributes on current point + func->GetLastLocalCoordinates(pcoords); + cell->InterpolateTuple(input->GetAttributes(),pcoords, + values); + + p=values; + c=outputPD->GetNumberOfArrays(); + j=0; + while(jGetArray(j); + dataArray->InsertTuple(nextPoint,p); + ++j; + p=p+dataArray->GetNumberOfComponents(); + } + + // Compute vorticity if required + // This can be used later for streamribbon generation. + if (this->ComputeVorticity) + { + vtkGenericStreamTracer::CalculateVorticity(cell, pcoords, inVectors, + vort); + + vorticity->InsertNextTuple(vort); + // rotation + // angular velocity = vorticity . unit tangent ( i.e. velocity/speed ) + // rotation = sum ( angular velocity * delT ) + omega = vtkMath::Dot(vort, velocity); + omega /= speed; + omega *= this->RotationScale; + index = angularVel->InsertNextValue(omega); + rotation->InsertNextValue(rotation->GetValue(index-1) + + (angularVel->GetValue(index-1) + omega)/2 * + (accumTime - time->GetValue(index-1))); + } + + // Never call conversion methods if speed == 0 + if ( (speed == 0) || (speed <= this->TerminalSpeed) ) + { + retVal = STAGNATION; + break; + } + + // Convert all intervals to time + this->ConvertIntervals(step, minStep, maxStep, direction, + cellLength, speed); + + + // If the solver is adaptive and the next time step (delT.Interval) + // that the solver wants to use is smaller than minStep or larger + // than maxStep, re-adjust it. This has to be done every step + // because minStep and maxStep can change depending on the cell + // size (unless it is specified in time units) + if (integrator->IsAdaptive()) + { + if (fabs(delT.Interval) < fabs(minStep)) + { + delT.Interval = fabs(minStep) * delT.Interval/fabs(delT.Interval); + } + else if (fabs(delT.Interval) > fabs(maxStep)) + { + delT.Interval = fabs(maxStep) * delT.Interval/fabs(delT.Interval); + } + } + else + { + delT.Interval = step; + } + + // End Integration + } + + if (shouldAbort) + { + break; + } + + if (numPts > 1) + { + outputLines->InsertNextCell(numPts); + for (i=numPtsTotal-numPts; iInsertCellPoint(i); + } + retVals->InsertNextValue(retVal); + } + } + + if (!shouldAbort) + { + // Create the output polyline + output->SetPoints(outputPoints); + outputPD->AddArray(time); + if (vorticity) + { + outputPD->AddArray(vorticity); + outputPD->AddArray(rotation); + outputPD->AddArray(angularVel); + } + + vtkIdType numPts = outputPoints->GetNumberOfPoints(); + if ( numPts > 1 ) + { + // Assign geometry and attributes + output->SetLines(outputLines); + if (this->GenerateNormalsInIntegrate) + { + this->GenerateNormals(output, 0); + } + + outputCD->AddArray(retVals); + } + } + + if (vorticity) + { + vorticity->Delete(); + rotation->Delete(); + angularVel->Delete(); + } + + + retVals->Delete(); + + outputPoints->Delete(); + outputLines->Delete(); + + time->Delete(); + + + integrator->Delete(); + + delete[] values; + + output->Squeeze(); + return; +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::GenerateNormals(vtkPolyData* output, + double* firstNormal) +{ + // Useful pointers + vtkDataSetAttributes* outputPD = output->GetPointData(); + + vtkPoints* outputPoints = output->GetPoints(); + vtkCellArray* outputLines = output->GetLines(); + + vtkDataArray* rotation = outputPD->GetArray("Rotation"); + + vtkIdType numPts = outputPoints->GetNumberOfPoints(); + if ( numPts > 1 ) + { + if (this->ComputeVorticity) + { + vtkPolyLine* lineNormalGenerator = vtkPolyLine::New(); + vtkDoubleArray* normals = vtkDoubleArray::New(); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(numPts); + + lineNormalGenerator->GenerateSlidingNormals(outputPoints, + outputLines, + normals, + firstNormal); + lineNormalGenerator->Delete(); + + int i, j; + double normal[3], local1[3], local2[3], theta, costheta, sintheta, length; + double velocity[3]; + normals->SetName("Normals"); + vtkDataArray* newVectors = + outputPD->GetVectors(this->InputVectorsSelection); + for(i=0; iGetTuple(i, normal); + if (newVectors == NULL) + { // This should never happen. + vtkErrorMacro("Could not find output array."); + return; + } + newVectors->GetTuple(i, velocity); + // obtain two unit orthogonal vectors on the plane perpendicular to + // the streamline + for(j=0; j<3; j++) { local1[j] = normal[j]; } + length = vtkMath::Normalize(local1); + vtkMath::Cross(local1, velocity, local2); + vtkMath::Normalize(local2); + // Rotate the normal with theta + rotation->GetTuple(i, &theta); + costheta = cos(theta); + sintheta = sin(theta); + for(j=0; j<3; j++) + { + normal[j] = length* (costheta*local1[j] + sintheta*local2[j]); + } + normals->SetTuple(i, normal); + } + outputPD->AddArray(normals); + outputPD->SetActiveAttribute("Normals", vtkDataSetAttributes::VECTORS); + normals->Delete(); + } + } +} + + +//----------------------------------------------------------------------------- +// This is used by sub-classes in certain situations. It +// does a lot less (for example, does not compute attributes) +// than Integrate. +void vtkGenericStreamTracer::SimpleIntegrate( + double seed[3], + double lastPoint[3], + double delt, + vtkGenericInterpolatedVelocityField* func) +{ + vtkIdType numSteps = 0; + vtkIdType maxSteps = 20; + double error = 0; + double stepTaken; + double point1[3], point2[3]; + double velocity[3]; + double speed; + + (void)seed; // Seed is not used + + memcpy(point1, lastPoint, 3*sizeof(double)); + + // Create a new integrator, the type is the same as Integrator + vtkInitialValueProblemSolver* integrator = + this->GetIntegrator()->NewInstance(); + integrator->SetFunctionSet(func); + + while ( 1 ) + { + + if (numSteps++ > maxSteps) + { + break; + } + + // Calculate the next step using the integrator provided + // Break if the next point is out of bounds. + if (integrator->ComputeNextStep(point1, point2, 0, delt, + stepTaken, 0, 0, 0, error) != 0) + { + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + + + // This is the next starting point + for(int i=0; i<3; i++) + { + point1[i] = point2[i]; + } + + // Interpolate the velocity at the next point + if ( !func->FunctionValues(point2, velocity) ) + { + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + + speed = vtkMath::Norm(velocity); + + // Never call conversion methods if speed == 0 + if ( (speed == 0) || (speed <= this->TerminalSpeed) ) + { + break; + } + + memcpy(point1, point2, 3*sizeof(double)); + // End Integration + } + + integrator->Delete(); +} + +//----------------------------------------------------------------------------- +void vtkGenericStreamTracer::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Start position: " + << this->StartPosition[0] << " " + << this->StartPosition[1] << " " + << this->StartPosition[2] << endl; + os << indent << "Terminal speed: " << this->TerminalSpeed << endl; + os << indent << "Maximum propagation: " << this->MaximumPropagation.Interval + << " unit: "; + switch (this->MaximumPropagation.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Min. integration step: " + << this->MinimumIntegrationStep.Interval + << " unit: "; + switch (this->MinimumIntegrationStep.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Max. integration step: " + << this->MaximumIntegrationStep.Interval + << " unit: "; + switch (this->MaximumIntegrationStep.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Initial integration step: " + << this->InitialIntegrationStep.Interval + << " unit: "; + switch (this->InitialIntegrationStep.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Integration direction: "; + switch (this->IntegrationDirection) + { + case FORWARD: + os << "forward."; + break; + case BACKWARD: + os << "backward."; + break; + } + os << endl; + + os << indent << "Integrator: " << this->Integrator << endl; + os << indent << "Maximum error: " << this->MaximumError << endl; + os << indent << "Max. number of steps: " << this->MaximumNumberOfSteps + << endl; + os << indent << "Vorticity computation: " + << (this->ComputeVorticity ? " On" : " Off") << endl; + os << indent << "Rotation scale: " << this->RotationScale << endl; + + if (this->InputVectorsSelection) + { + os << indent << "InputVectorsSelection: " << this->InputVectorsSelection; + } +} diff --git a/GenericFiltering/vtkGenericStreamTracer.h b/GenericFiltering/vtkGenericStreamTracer.h new file mode 100644 index 0000000..0520694 --- /dev/null +++ b/GenericFiltering/vtkGenericStreamTracer.h @@ -0,0 +1,401 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericStreamTracer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericStreamTracer - Streamline generator +// .SECTION Description +// vtkGenericStreamTracer is a filter that integrates a vector field to +// generate streamlines. The integration is performed using the provided +// integrator. The default is second order Runge-Kutta. +// +// vtkGenericStreamTracer generate polylines as output. Each cell (polyline) +// corresponds to one streamline. The values associated with each streamline +// are stored in the cell data whereas the values associated with points +// are stored in point data. +// +// Note that vtkGenericStreamTracer can integrate both forward and backward. +// The length of the streamline is controlled by specifying either +// a maximum value in the units of length, cell length or elapsed time +// (the elapsed time is the time each particle would have traveled if +// flow were steady). Otherwise, the integration terminates after exiting +// the dataset or if the particle speed is reduced to a value less than +// the terminal speed or when a maximum number of steps is reached. +// The reason for the termination is stored in a cell array named +// ReasonForTermination. +// +// The quality of integration can be controlled by setting integration +// step (InitialIntegrationStep) and in the case of adaptive solvers +// the maximum error, the minimum integration step and the maximum +// integration step. All of these can have units of length, cell length +// or elapsed time. +// +// The integration time, vorticity, rotation and angular velocity +// are stored in point arrays named "IntegrationTime", "Vorticity", +// "Rotation" and "AngularVelocity" respectively (vorticity, rotation +// and angular velocity are computed only when ComputeVorticity is on). +// All point attributes in the source data set are interpolated on the +// new streamline points. +// +// vtkGenericStreamTracer integrates through any type of dataset. As a result, +// if the dataset contains 2D cells such as polygons or triangles, the +// integration is constrained to lie on the surface defined by the 2D cells. +// +// The starting point of traces may be defined in two different ways. +// Starting from global x-y-z "position" allows you to start a single trace +// at a specified x-y-z coordinate. If you specify a source object, +// a trace will be generated for each point in the source that is +// inside the dataset. +// +// .SECTION See Also +// vtkRibbonFilter vtkRuledSurfaceFilter vtkInitialValueProblemSolver +// vtkRungeKutta2 vtkRungeKutta4 vtkRungeKutta45 + +#ifndef __vtkGenericStreamTracer_h +#define __vtkGenericStreamTracer_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkInitialValueProblemSolver.h" // Needed for constants + +class vtkDataArray; +class vtkGenericAdaptorCell; +class vtkIdList; +class vtkIntArray; +class vtkGenericInterpolatedVelocityField; +class vtkDataSet; +class vtkGenericAttribute; +class vtkGenericDataSet; + +class VTK_GENERIC_FILTERING_EXPORT vtkGenericStreamTracer : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGenericStreamTracer,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object to start from position (0,0,0), integrate forward, + // terminal speed 1.0E-12, vorticity computation on, integration + // step length 0.5 (unit cell length), maximum number of steps 2000, + // using 2nd order Runge Kutta and maximum propagation 1.0 (unit length). + static vtkGenericStreamTracer *New(); + + // Description: + // Specify the start of the streamline in the global coordinate + // system. Search must be performed to find initial cell to start + // integration from. + vtkSetVector3Macro(StartPosition, double); + vtkGetVector3Macro(StartPosition, double); + + // Description: + // Specify the source object used to generate starting points. + void SetSource(vtkDataSet *source); + vtkDataSet *GetSource(); + +//BTX +#if VTK_MAJOR_VERSION>4 || (VTK_MAJOR_VERSION==4 && VTK_MINOR_VERSION>4) + int FillInputPortInformation(int port, vtkInformation* info); +#endif + + enum Units + { + TIME_UNIT, + LENGTH_UNIT, + CELL_LENGTH_UNIT + }; + + enum Solvers + { + RUNGE_KUTTA2, + RUNGE_KUTTA4, + RUNGE_KUTTA45, + NONE, + UNKNOWN + }; + + enum ReasonForTermination + { + OUT_OF_DOMAIN = vtkInitialValueProblemSolver::OUT_OF_DOMAIN, + NOT_INITIALIZED = vtkInitialValueProblemSolver::NOT_INITIALIZED , + UNEXPECTED_VALUE = vtkInitialValueProblemSolver::UNEXPECTED_VALUE, + OUT_OF_TIME = 4, + OUT_OF_STEPS = 5, + STAGNATION = 6 + }; +//ETX + + // Description: + // Set/get the integrator type to be used in the stream line + // calculation. The object passed is not actually used but + // is cloned with NewInstance in the process of integration + // (prototype pattern). The default is 2nd order Runge Kutta. + // The integrator can also be changed using SetIntegratorType. + // The recognized solvers are: + // RUNGE_KUTTA2 = 0 + // RUNGE_KUTTA4 = 1 + // RUNGE_KUTTA45 = 2 + void SetIntegrator(vtkInitialValueProblemSolver *); + vtkGetObjectMacro ( Integrator, vtkInitialValueProblemSolver ); + void SetIntegratorType(int type); + int GetIntegratorType(); + void SetIntegratorTypeToRungeKutta2() + {this->SetIntegratorType(RUNGE_KUTTA2);}; + void SetIntegratorTypeToRungeKutta4() + {this->SetIntegratorType(RUNGE_KUTTA4);}; + void SetIntegratorTypeToRungeKutta45() + {this->SetIntegratorType(RUNGE_KUTTA45);}; + + // Description: + // Specify the maximum length of the streamlines expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + void SetMaximumPropagation(int unit, double max); + void SetMaximumPropagation(double max); + void SetMaximumPropagationUnit(int unit); + int GetMaximumPropagationUnit(); + double GetMaximumPropagation(); + void SetMaximumPropagationUnitToTimeUnit() + {this->SetMaximumPropagationUnit(TIME_UNIT);}; + void SetMaximumPropagationUnitToLengthUnit() + {this->SetMaximumPropagationUnit(LENGTH_UNIT);}; + void SetMaximumPropagationUnitToCellLengthUnit() + {this->SetMaximumPropagationUnit(CELL_LENGTH_UNIT);}; + + // Description: + // Specify the minimum step used in the integration expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + // Only valid when using adaptive integrators. + void SetMinimumIntegrationStep(int unit, double step); + void SetMinimumIntegrationStepUnit(int unit); + void SetMinimumIntegrationStep(double step); + int GetMinimumIntegrationStepUnit(); + double GetMinimumIntegrationStep(); + void SetMinimumIntegrationStepUnitToTimeUnit() + {this->SetMinimumIntegrationStepUnit(TIME_UNIT);}; + void SetMinimumIntegrationStepUnitToLengthUnit() + {this->SetMinimumIntegrationStepUnit(LENGTH_UNIT);}; + void SetMinimumIntegrationStepUnitToCellLengthUnit() + {this->SetMinimumIntegrationStepUnit(CELL_LENGTH_UNIT);}; + + // Description: + // Specify the maximum step used in the integration expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + // Only valid when using adaptive integrators. + void SetMaximumIntegrationStep(int unit, double step); + void SetMaximumIntegrationStepUnit(int unit); + void SetMaximumIntegrationStep(double step); + int GetMaximumIntegrationStepUnit(); + double GetMaximumIntegrationStep(); + void SetMaximumIntegrationStepUnitToTimeUnit() + {this->SetMaximumIntegrationStepUnit(TIME_UNIT);}; + void SetMaximumIntegrationStepUnitToLengthUnit() + {this->SetMaximumIntegrationStepUnit(LENGTH_UNIT);}; + void SetMaximumIntegrationStepUnitToCellLengthUnit() + {this->SetMaximumIntegrationStepUnit(CELL_LENGTH_UNIT);}; + + // Description: + // Specify the initial step used in the integration expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + // If the integrator is not adaptive, this is the actual + // step used. + void SetInitialIntegrationStep(int unit, double step); + void SetInitialIntegrationStepUnit(int unit); + void SetInitialIntegrationStep(double step); + int GetInitialIntegrationStepUnit(); + double GetInitialIntegrationStep(); + void SetInitialIntegrationStepUnitToTimeUnit() + {this->SetInitialIntegrationStepUnit(TIME_UNIT);}; + void SetInitialIntegrationStepUnitToLengthUnit() + {this->SetInitialIntegrationStepUnit(LENGTH_UNIT);}; + void SetInitialIntegrationStepUnitToCellLengthUnit() + {this->SetInitialIntegrationStepUnit(CELL_LENGTH_UNIT);}; + + // Description + // Specify the maximum error in the integration. This value + // is passed to the integrator. Therefore, it's meaning depends + // on the integrator used. + vtkSetMacro(MaximumError, double); + vtkGetMacro(MaximumError, double); + + // Description + // Specify the maximum number of steps used in the integration. + vtkSetMacro(MaximumNumberOfSteps, vtkIdType); + vtkGetMacro(MaximumNumberOfSteps, vtkIdType); + + // Description + // If at any point, the speed is below this value, the integration + // is terminated. + vtkSetMacro(TerminalSpeed, double); + vtkGetMacro(TerminalSpeed, double); + +//BTX + enum + { + FORWARD, + BACKWARD, + BOTH + }; +//ETX + + // Description: + // Specify whether the streamtrace will be generated in the + // upstream or downstream direction. + vtkSetClampMacro(IntegrationDirection, int, FORWARD, BOTH); + vtkGetMacro(IntegrationDirection, int); + void SetIntegrationDirectionToForward() + {this->SetIntegrationDirection(FORWARD);}; + void SetIntegrationDirectionToBackward() + {this->SetIntegrationDirection(BACKWARD);}; + void SetIntegrationDirectionToBoth() + {this->SetIntegrationDirection(BOTH);}; + + // Description + // Turn on/off calculation of vorticity at streamline points + // (necessary for generating proper streamribbons using the + // vtkRibbonFilter. + vtkSetMacro(ComputeVorticity, int); + vtkGetMacro(ComputeVorticity, int); + vtkBooleanMacro(ComputeVorticity, int); + + // Description + // This can be used to scale the rate with which the streamribbons + // twist. The default is 1. + vtkSetMacro(RotationScale, double); + vtkGetMacro(RotationScale, double); + + // Description: + // If you want to generate traces using an arbitrary vector array, + // then set its name here. By default this in NULL and the filter will + // use the active vector array. + vtkGetStringMacro(InputVectorsSelection); + void SelectInputVectors(const char *fieldName) + {this->SetInputVectorsSelection(fieldName);} + + // Description: + // Add a dataset to the list inputs + void AddInput(vtkGenericDataSet *in); + + // Description: + void SetInterpolatorPrototype(vtkGenericInterpolatedVelocityField* ivf); + +protected: + + vtkGenericStreamTracer(); + ~vtkGenericStreamTracer(); + + // hide the superclass' AddInput() from the user and the compiler + void AddInput(vtkDataObject *) + { vtkErrorMacro( << "AddInput() must be called with a vtkGenericDataSet not a vtkDataObject."); }; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // Description: + // Compute the vorticity at point `pcoords' in cell `cell' for the + // vector attribute `attribute'. + // \pre attribute_exists: attribute!=0 + // \pre point_centered_attribute: attribute->GetCentering()==vtkPointCentered + // \pre vector_attribute: attribute->GetType()==vtkDataSetAttributes::VECTORS); + void CalculateVorticity(vtkGenericAdaptorCell* cell, + double pcoords[3], + vtkGenericAttribute *attribute, + double vorticity[3]); + + void Integrate(vtkGenericDataSet *input0, + vtkPolyData* output, + vtkDataArray* seedSource, + vtkIdList* seedIds, + vtkIntArray* integrationDirections, + double lastPoint[3], + vtkGenericInterpolatedVelocityField* func); + void SimpleIntegrate(double seed[3], + double lastPoint[3], + double delt, + vtkGenericInterpolatedVelocityField* func); + int CheckInputs(vtkGenericInterpolatedVelocityField*& func, + vtkInformationVector **inputVector); + void GenerateNormals(vtkPolyData* output, double* firstNormal); + + int GenerateNormalsInIntegrate; + + vtkSetStringMacro(InputVectorsSelection); + char *InputVectorsSelection; + + + // starting from global x-y-z position + double StartPosition[3]; + + static const double EPSILON; + double TerminalSpeed; + + double LastUsedTimeStep; + +//BTX + struct IntervalInformation + { + double Interval; + int Unit; + }; + + IntervalInformation MaximumPropagation; + IntervalInformation MinimumIntegrationStep; + IntervalInformation MaximumIntegrationStep; + IntervalInformation InitialIntegrationStep; + + void SetIntervalInformation(int unit, double interval, + IntervalInformation& currentValues); + void SetIntervalInformation(int unit,IntervalInformation& currentValues); + static double ConvertToTime(IntervalInformation& interval, + double cellLength, double speed); + static double ConvertToLength(IntervalInformation& interval, + double cellLength, double speed); + static double ConvertToCellLength(IntervalInformation& interval, + double cellLength, double speed); + static double ConvertToUnit(IntervalInformation& interval, int unit, + double cellLength, double speed); + void ConvertIntervals(double& step, double& minStep, double& maxStep, + int direction, double cellLength, double speed); +//ETX + + void InitializeSeeds(vtkDataArray*& seeds, + vtkIdList*& seedIds, + vtkIntArray*& integrationDirections); + + int IntegrationDirection; + + // Prototype showing the integrator type to be set by the user. + vtkInitialValueProblemSolver* Integrator; + + double MaximumError; + vtkIdType MaximumNumberOfSteps; + + int ComputeVorticity; + double RotationScale; + + vtkGenericInterpolatedVelocityField* InterpolatorPrototype; + +private: + vtkGenericStreamTracer(const vtkGenericStreamTracer&); // Not implemented. + void operator=(const vtkGenericStreamTracer&); // Not implemented. +}; + +#endif diff --git a/Graphics/CMakeLists.txt b/Graphics/CMakeLists.txt new file mode 100644 index 0000000..e021415 --- /dev/null +++ b/Graphics/CMakeLists.txt @@ -0,0 +1,225 @@ +SET(KIT Graphics) +SET(UKIT GRAPHICS) +SET(KIT_TCL_LIBS vtkFilteringTCL) +SET(KIT_PYTHON_LIBS vtkFilteringPythonD) +SET(KIT_JAVA_LIBS vtkFilteringJava) +SET(KIT_LIBS vtkFiltering) + + +SET( Kit_SRCS +vtkAppendFilter.cxx +vtkAppendPolyData.cxx +vtkApproximatingSubdivisionFilter.cxx +vtkArrayCalculator.cxx +vtkArrowSource.cxx +vtkAssignAttribute.cxx +vtkAttributeDataToFieldDataFilter.cxx +vtkAxes.cxx +vtkBandedPolyDataContourFilter.cxx +vtkBlankStructuredGrid.cxx +vtkBlankStructuredGridWithImage.cxx +vtkBoxClipDataSet.cxx +vtkBrownianPoints.cxx +vtkButterflySubdivisionFilter.cxx +vtkButtonSource.cxx +vtkBSPCuts.cxx +vtkBSPIntersections.cxx +vtkCellCenterDepthSort.cxx +vtkCellCenters.cxx +vtkCellDataToPointData.cxx +vtkCellDerivatives.cxx +vtkCleanPolyData.cxx +vtkClipDataSet.cxx +vtkClipPolyData.cxx +vtkClipVolume.cxx +vtkConeSource.cxx +vtkConnectivityFilter.cxx +vtkContourFilter.cxx +vtkContourGrid.cxx +vtkCubeSource.cxx +vtkCursor3D.cxx +vtkCutter.cxx +vtkCurvatures.cxx +vtkCylinderSource.cxx +vtkDashedStreamLine.cxx +vtkDataObjectToDataSetFilter.cxx +vtkDataSetSurfaceFilter.cxx +vtkDataSetToDataObjectFilter.cxx +vtkDataSetTriangleFilter.cxx +vtkDecimatePro.cxx +vtkDelaunay2D.cxx +vtkDelaunay3D.cxx +vtkDicer.cxx +vtkDiscreteMarchingCubes.cxx +vtkDiskSource.cxx +vtkEdgePoints.cxx +vtkElevationFilter.cxx +vtkEllipticalButtonSource.cxx +vtkExtractCells.cxx +vtkExtractDataOverTime.cxx +vtkExtractEdges.cxx +vtkExtractGeometry.cxx +vtkExtractGrid.cxx +vtkExtractPolyDataGeometry.cxx +vtkExtractRectilinearGrid.cxx +vtkExtractTensorComponents.cxx +vtkExtractUnstructuredGrid.cxx +vtkExtractVectorComponents.cxx +vtkFeatureEdges.cxx +vtkFieldDataToAttributeDataFilter.cxx +vtkGeometryFilter.cxx +vtkGlyph2D.cxx +vtkGlyph3D.cxx +vtkGlyphSource2D.cxx +vtkGraphLayoutFilter.cxx +vtkGridSynchronizedTemplates3D.cxx +vtkHierarchicalDataSetGeometryFilter.cxx +vtkHedgeHog.cxx +vtkHierarchicalDataExtractDataSets.cxx +vtkHierarchicalDataExtractLevel.cxx +vtkHierarchicalDataLevelFilter.cxx +vtkHull.cxx +vtkHyperStreamline.cxx +vtkIdFilter.cxx +vtkImageDataGeometryFilter.cxx +vtkImageMarchingCubes.cxx +vtkImplicitTextureCoords.cxx +vtkInterpolateDataSetAttributes.cxx +vtkInterpolatingSubdivisionFilter.cxx +vtkKdNode.cxx +vtkKdTree.cxx +vtkLineSource.cxx +vtkLinearExtrusionFilter.cxx +vtkLinearSubdivisionFilter.cxx +vtkLinkEdgels.cxx +vtkLoopSubdivisionFilter.cxx +vtkMarchingContourFilter.cxx +vtkMarchingCubes.cxx +vtkMarchingSquares.cxx +vtkMaskFields.cxx +vtkMaskPoints.cxx +vtkMaskPolyData.cxx +vtkMassProperties.cxx +vtkMergeDataObjectFilter.cxx +vtkMergeCells.cxx +vtkMergeFields.cxx +vtkMergeFilter.cxx +vtkMeshQuality.cxx +vtkModelMetadata.cxx +vtkOBBDicer.cxx +vtkOBBTree.cxx +vtkOutlineCornerFilter.cxx +vtkOutlineCornerSource.cxx +vtkOutlineFilter.cxx +vtkOutlineSource.cxx +vtkParametricFunctionSource.cxx +vtkPlaneSource.cxx +vtkPlanesIntersection.cxx +vtkPlatonicSolidSource.cxx +vtkPointDataToCellData.cxx +vtkPointsProjectedHull.cxx +vtkPointSource.cxx +vtkPolyDataConnectivityFilter.cxx +vtkPolyDataNormals.cxx +vtkPolyDataStreamer.cxx +vtkProbeFilter.cxx +vtkProgrammableAttributeDataFilter.cxx +vtkProgrammableDataObjectSource.cxx +vtkProgrammableFilter.cxx +vtkProgrammableGlyphFilter.cxx +vtkProgrammableSource.cxx +vtkProjectedTexture.cxx +vtkQuadricClustering.cxx +vtkQuadricDecimation.cxx +vtkQuantizePolyDataPoints.cxx +vtkRearrangeFields.cxx +vtkRectangularButtonSource.cxx +vtkRectilinearGridClip.cxx +vtkRectilinearGridGeometryFilter.cxx +vtkRectilinearGridToTetrahedra.cxx +vtkRectilinearSynchronizedTemplates.cxx +vtkRecursiveDividingCubes.cxx +vtkReflectionFilter.cxx +vtkRegularPolygonSource.cxx +vtkReverseSense.cxx +vtkRibbonFilter.cxx +vtkRotationalExtrusionFilter.cxx +vtkRotationFilter.cxx +vtkRuledSurfaceFilter.cxx +vtkSelectPolyData.cxx +vtkShrinkFilter.cxx +vtkShrinkPolyData.cxx +vtkSimpleElevationFilter.cxx +vtkSliceCubes.cxx +vtkSmoothPolyDataFilter.cxx +vtkSortDataArray.cxx +vtkSpatialRepresentationFilter.cxx +vtkSpherePuzzle.cxx +vtkSpherePuzzleArrows.cxx +vtkSphereSource.cxx +vtkSplineFilter.cxx +vtkSplitField.cxx +vtkStreamLine.cxx +vtkStreamPoints.cxx +vtkStreamTracer.cxx +vtkStreamer.cxx +vtkStripper.cxx +vtkStructuredGridClip.cxx +vtkStructuredGridGeometryFilter.cxx +vtkStructuredGridOutlineFilter.cxx +vtkStructuredPointsGeometryFilter.cxx +vtkSubPixelPositionEdgels.cxx +vtkSubdivideTetra.cxx +vtkSuperquadricSource.cxx +vtkSynchronizedTemplates2D.cxx +vtkSynchronizedTemplates3D.cxx +vtkSynchronizedTemplatesCutter3D.cxx +vtkTensorGlyph.cxx +vtkTextSource.cxx +vtkTextureMapToCylinder.cxx +vtkTextureMapToPlane.cxx +vtkTextureMapToSphere.cxx +vtkTexturedSphereSource.cxx +vtkThreshold.cxx +vtkThresholdPoints.cxx +vtkThresholdTextureCoords.cxx +vtkTransformFilter.cxx +vtkTransformPolyDataFilter.cxx +vtkTransformTextureCoords.cxx +vtkTriangleFilter.cxx +vtkTriangularTCoords.cxx +vtkTubeFilter.cxx +vtkVectorDot.cxx +vtkVectorNorm.cxx +vtkVisibilitySort.cxx +vtkVoxelContoursToSurfaceFilter.cxx +vtkWarpLens.cxx +vtkWarpScalar.cxx +vtkWarpTo.cxx +vtkWarpVector.cxx +vtkWindowedSincPolyDataFilter.cxx +) + +SET_SOURCE_FILES_PROPERTIES( +vtkApproximatingSubdivisionFilter +vtkButtonSource +vtkDicer +vtkInterpolatingSubdivisionFilter +vtkStreamer +vtkVisibilitySort.cxx +ABSTRACT +) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- diff --git a/Graphics/Testing/CMakeLists.txt b/Graphics/Testing/CMakeLists.txt new file mode 100644 index 0000000..cf93748 --- /dev/null +++ b/Graphics/Testing/CMakeLists.txt @@ -0,0 +1,25 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Graphics ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Graphics" + VTK_GRAPHICS_EXPORT + vtkButterflySubdivisionFilter.h + vtkLinearSubdivisionFilter.h + vtkLoopSubdivisionFilter.h + vtkOutlineFilter.h + vtkProgrammableFilter.h + vtkProgrammableSource.h + vtkStructuredGridOutlineFilter.h + vtkStructuredPointsGeometryFilter.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/Graphics/Testing/Cxx/BoxClipPolyData.cxx b/Graphics/Testing/Cxx/BoxClipPolyData.cxx new file mode 100644 index 0000000..ef20407 --- /dev/null +++ b/Graphics/Testing/Cxx/BoxClipPolyData.cxx @@ -0,0 +1,315 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: BoxClipPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkActor.h" +#include "vtkBoxClipDataSet.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCutter.h" +#include "vtkDataSetSurfaceFilter.h" +#include "vtkDoubleArray.h" +#include "vtkPlane.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkSphereSource.h" +#include "vtkUnstructuredGrid.h" + +#include "vtkRegressionTestImage.h" + +#include "vtkSmartPointer.h" +#define VTK_CREATE(type, var) \ + vtkSmartPointer var = vtkSmartPointer::New() + +const double minpoint1[] = { -1.00002, -0.50002, -0.50002 }; +const double maxpoint1[] = { -0.0511337, 0.5, 0.5 }; + +const double minpoint2[] = { -1.0, -1.0, -1.0 }; +const double maxpoint2[] = { 1.0, 1.0, 1.0 }; + +const double minusx[] = { -1.0, 0.0, 0.0 }; +const double minusy[] = { 0.0, -1.0, 0.0 }; +const double minusz[] = { 0.0, 0.0, -1.0 }; +const double plusx[] = { 1.0, 0.0, 0.0 }; +const double plusy[] = { 0.0, 1.0, 0.0 }; +const double plusz[] = { 0.0, 0.0, 1.0 }; + +const int numTriangles = 6; +const int numTrianglePoints = numTriangles*3*3; +static double trianglePointData[numTrianglePoints] = { + -2.0, -1.0, 0.0, + 0.0, -1.0, 0.0, + -1.0, -0.5, 0.0, + + 0.0, -1.0, 0.0, + 2.0, -1.0, 0.0, + 1.0, -0.5, 0.0, + + -1.0, 0.25, 0.0, + -2.0, -0.25, 0.0, + 0.0, -0.25, 0.0, + + 1.0, 0.25, 0.0, + 0.0, -0.25, 0.0, + 2.0, -0.25, 0.0, + + 0.0, 0.5, 0.0, + -1.0, 1.0, 0.0, + -2.0, 0.5, 0.0, + + 2.0, 0.5, 0.0, + 1.0, 1.0, 0.0, + 0.0, 0.5, 0.0 +}; + +//----------------------------------------------------------------------------- + +const int numPolySets = 4; + +static void TestPolyData(vtkPolyData *data, int num, vtkRenderWindow *renwin, + const double minBoxPoint[3], + const double maxBoxPoint[3]) +{ + // Set up test of normal box. + VTK_CREATE(vtkBoxClipDataSet, clipper1); + clipper1->SetInput(data); + clipper1->GenerateClippedOutputOff(); + clipper1->SetBoxClip(minBoxPoint[0], maxBoxPoint[0], + minBoxPoint[1], maxBoxPoint[1], + minBoxPoint[2], maxBoxPoint[2]); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface1); + surface1->SetInputConnection(0, clipper1->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper1); + mapper1->SetInputConnection(0, surface1->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor1); + actor1->SetMapper(mapper1); + actor1->GetProperty()->SetPointSize(3.0f); + + VTK_CREATE(vtkRenderer, renderer1); + renderer1->AddActor(actor1); + renderer1->SetBackground(0.0, 0.5, 0.5); + renderer1->SetViewport(0.0, (double)num/numPolySets, + 0.25, (double)(num+1)/numPolySets); + renwin->AddRenderer(renderer1); + + // Set up test of normal box with generation of clipped output. + VTK_CREATE(vtkBoxClipDataSet, clipper2); + clipper2->SetInput(data); + clipper2->GenerateClippedOutputOn(); + clipper2->SetBoxClip(minBoxPoint[0], maxBoxPoint[0], + minBoxPoint[1], maxBoxPoint[1], + minBoxPoint[2], maxBoxPoint[2]); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface2_1); + surface2_1->SetInputConnection(0, clipper2->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper2_1); + mapper2_1->SetInputConnection(0, surface2_1->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor2_1); + actor2_1->SetMapper(mapper2_1); + actor2_1->GetProperty()->SetPointSize(3.0f); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface2_2); + surface2_2->SetInput(clipper2->GetClippedOutput()); + + VTK_CREATE(vtkPolyDataMapper, mapper2_2); + mapper2_2->SetInputConnection(0, surface2_2->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor2_2); + actor2_2->SetMapper(mapper2_2); + actor2_2->GetProperty()->SetColor(1.0, 0.5, 0.5); + actor2_2->GetProperty()->SetPointSize(3.0f); + + VTK_CREATE(vtkRenderer, renderer2); + renderer2->AddActor(actor2_1); + renderer2->AddActor(actor2_2); + renderer2->SetBackground(0.0, 0.5, 0.5); + renderer2->SetViewport(0.25, (double)num/numPolySets, + 0.5, (double)(num+1)/numPolySets); + renwin->AddRenderer(renderer2); + + // Set up test of an oriented box. + VTK_CREATE(vtkBoxClipDataSet, clipper3); + clipper3->SetInput(data); + clipper3->GenerateClippedOutputOff(); + clipper3->SetBoxClip(minusx, minBoxPoint, + minusy, minBoxPoint, + minusz, minBoxPoint, + plusx, maxBoxPoint, + plusy, maxBoxPoint, + plusz, maxBoxPoint); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface3); + surface3->SetInputConnection(0, clipper3->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper3); + mapper3->SetInputConnection(0, surface3->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor3); + actor3->SetMapper(mapper3); + actor3->GetProperty()->SetPointSize(3.0f); + + VTK_CREATE(vtkRenderer, renderer3); + renderer3->AddActor(actor3); + renderer3->SetBackground(0.0, 0.5, 0.5); + renderer3->SetViewport(0.5, (double)num/numPolySets, + 0.75, (double)(num+1)/numPolySets); + renwin->AddRenderer(renderer3); + + // Set up test of an oriented box with generation of clipped output. + VTK_CREATE(vtkBoxClipDataSet, clipper4); + clipper4->SetInput(data); + clipper4->GenerateClippedOutputOn(); + clipper4->SetBoxClip(minusx, minBoxPoint, + minusy, minBoxPoint, + minusz, minBoxPoint, + plusx, maxBoxPoint, + plusy, maxBoxPoint, + plusz, maxBoxPoint); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface4_1); + surface4_1->SetInputConnection(0, clipper4->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper4_1); + mapper4_1->SetInputConnection(0, surface4_1->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor4_1); + actor4_1->SetMapper(mapper4_1); + actor4_1->GetProperty()->SetPointSize(3.0f); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface4_2); + surface4_2->SetInput(clipper4->GetClippedOutput()); + + VTK_CREATE(vtkPolyDataMapper, mapper4_2); + mapper4_2->SetInputConnection(0, surface4_2->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor4_2); + actor4_2->SetMapper(mapper4_2); + actor4_2->GetProperty()->SetColor(1.0, 0.5, 0.5); + actor4_2->GetProperty()->SetPointSize(3.0f); + + VTK_CREATE(vtkRenderer, renderer4); + renderer4->AddActor(actor4_1); + renderer4->AddActor(actor4_2); + renderer4->SetBackground(0.0, 0.5, 0.5); + renderer4->SetViewport(0.75, (double)num/numPolySets, + 1.0, (double)(num+1)/numPolySets); + renwin->AddRenderer(renderer4); +} + +//----------------------------------------------------------------------------- + +int BoxClipPolyData(int argc, char *argv[]) +{ + vtkIdType i; + + // The render window. + VTK_CREATE(vtkRenderWindow, renwin); + renwin->SetSize(640, 640); + + VTK_CREATE(vtkRenderWindowInteractor, iren); + iren->SetRenderWindow(renwin); + + // Test polygons on a sphere + VTK_CREATE(vtkSphereSource, sphere); + sphere->Update(); + + TestPolyData(sphere->GetOutput(), 0, renwin, minpoint1, maxpoint1); + + // Test a triangle with points right on the box. + VTK_CREATE(vtkDoubleArray, trianglePointsArray); + trianglePointsArray->SetArray(trianglePointData, numTrianglePoints, 1); + trianglePointsArray->SetNumberOfComponents(3); + trianglePointsArray->SetNumberOfTuples(numTriangles*3); + + VTK_CREATE(vtkPoints, trianglePoints); + trianglePoints->SetData(trianglePointsArray); + + VTK_CREATE(vtkDoubleArray, triangleNormals); + triangleNormals->SetName("Normals"); + triangleNormals->SetNumberOfComponents(3); + triangleNormals->SetNumberOfTuples(numTriangles); + + VTK_CREATE(vtkCellArray, triangleCells); + triangleCells->Allocate(numTriangles*4); + + for (i = 0; i < numTriangles; i++) + { + triangleNormals->SetTuple3(i, 0.0, 0.0, 1.0); + + vtkIdType pts[3]; + pts[0] = i*3+0; pts[1] = i*3+1; pts[2] = i*3+2; + triangleCells->InsertNextCell(3, pts); + } + + VTK_CREATE(vtkPolyData, triangles); + triangles->SetPoints(trianglePoints); + triangles->SetPolys(triangleCells); + triangles->GetCellData()->SetNormals(triangleNormals); + + TestPolyData(triangles, 1, renwin, minpoint2, maxpoint2); + + // Test lines. + VTK_CREATE(vtkPolyData, sphereNoNormals); + sphereNoNormals->CopyStructure(sphere->GetOutput()); + + VTK_CREATE(vtkPlane, plane); + plane->SetOrigin(0.0, 0.0, 0.0); + plane->SetNormal(0.0, 0.0, 1.0); + + VTK_CREATE(vtkCutter, cutter); + cutter->SetInput(sphereNoNormals); + cutter->SetCutFunction(plane); + cutter->Update(); + + TestPolyData(cutter->GetOutput(), 2, renwin, minpoint1, maxpoint1); + + // Test verts. + VTK_CREATE(vtkPolyData, verts); + vtkPoints *vertsPoints = sphereNoNormals->GetPoints(); + verts->SetPoints(vertsPoints); + + VTK_CREATE(vtkCellArray, vertsCells); + vertsCells->Allocate(2*vertsPoints->GetNumberOfPoints()); + for (i = 0; i < vertsPoints->GetNumberOfPoints(); i++) + { + vertsCells->InsertNextCell(1, &i); + } + verts->SetVerts(vertsCells); + + TestPolyData(verts, 3, renwin, minpoint1, maxpoint1); + + // Run the regression test. + renwin->Render(); + int retVal = vtkRegressionTestImage(renwin); + if (retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + return 0; + } + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/BoxClipTetrahedra.cxx b/Graphics/Testing/Cxx/BoxClipTetrahedra.cxx new file mode 100644 index 0000000..a61c3d4 --- /dev/null +++ b/Graphics/Testing/Cxx/BoxClipTetrahedra.cxx @@ -0,0 +1,400 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: BoxClipTetrahedra.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// This test exercises several ways a plane may clip a tetrahedra. One of the +// things tested is the "winding" of the tetrahedra. There are two rotationally +// independent ways to specify a tetrahedra: +// +// v3 v3 +// /|\ /|\ // +// / | \ / | \ // +// / | \ / | \ // +// v2/_ _|_ _\v1 v1/_ _|_ _\v2 // +// \ | / \ | / // +// \ | / \ | / // +// \ | / \ | / // +// \|/ \|/ // +// v0 v0 // +// +// I'm calling these rotationally independent vertex specifications windings for +// short. VTK expects the winding on the left. We will test to make sure the +// winding on the right does not occur. + +#include "vtkActor.h" +#include "vtkBoxClipDataSet.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkDataSetSurfaceFilter.h" +#include "vtkDoubleArray.h" +#include "vtkMath.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGrid.h" + +#include "vtkRegressionTestImage.h" + +#include "vtkSmartPointer.h" +#define VTK_CREATE(type, var) \ + vtkSmartPointer var = vtkSmartPointer::New() + +static double tetrahedraPoints[4*3] = { + 1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, + 0.0, 1.0, 0.5 +}; + +// All possible cell connectivites with the correct winding. +static vtkIdType tetrahedra[12][4] = { + { 0, 1, 2, 3 }, + { 2, 0, 1, 3 }, + { 1, 2, 0, 3 }, + + { 0, 3, 1, 2 }, + { 1, 0, 3, 2 }, + { 3, 1, 0, 2 }, + + { 0, 2, 3, 1 }, + { 3, 0, 2, 1 }, + { 2, 3, 0, 1 }, + + { 1, 3, 2, 0 }, + { 2, 1, 3, 0 }, + { 3, 2, 1, 0 } +}; + +static double minusx[] = { -1.0, 0.0, 0.0 }; +static double minusy[] = { 0.0, -1.0, 0.0 }; +static double minusz[] = { 0.0, 0.0, -1.0 }; +static double plusx[] = { 1.0, 0.0, 0.0 }; +static double plusy[] = { 0.0, 1.0, 0.0 }; +static double plusz[] = { 0.0, 0.0, 1.0 }; + +static int NUM_CLIP_BOXES = 8; + +class BadWinding +{ +public: + BadWinding(vtkUnstructuredGrid *data) { + this->Data = data; + this->Data->Register(NULL); + } + ~BadWinding() { + this->Data->UnRegister(NULL); + } + BadWinding(const BadWinding &bw) { + this->Data = bw.Data; + this->Data->Register(NULL); + } + void operator=(const BadWinding &bw) { + this->Data->UnRegister(NULL); + this->Data = bw.Data; + this->Data->Register(NULL); + } + + vtkUnstructuredGrid *Data; +}; + + +static void CheckWinding(vtkUnstructuredGrid *data) +{ + data->Update(); + + vtkPoints *points = data->GetPoints(); + + vtkCellArray *cells = data->GetCells(); + cells->InitTraversal(); + + vtkIdType npts, *pts; + while (cells->GetNextCell(npts, pts)) + { + if (npts != 4) + { + cout << "Weird. I got something that is not a tetrahedra." << endl; + continue; + } + + double p0[3], p1[3], p2[3], p3[3]; + points->GetPoint(pts[0], p0); + points->GetPoint(pts[1], p1); + points->GetPoint(pts[2], p2); + points->GetPoint(pts[3], p3); + + // If the winding is correct, the normal to triangle p0,p1,p2 should point + // towards p3. + double v0[3], v1[3]; + v0[0] = p1[0] - p0[0]; v0[1] = p1[1] - p0[1]; v0[2] = p1[2] - p0[2]; + v1[0] = p2[0] - p0[0]; v1[1] = p2[1] - p0[1]; v1[2] = p2[2] - p0[2]; + + double n[3]; + vtkMath::Cross(v0, v1, n); + + double d[3]; + d[0] = p3[0] - p0[0]; d[1] = p3[1] - p0[1]; d[2] = p3[2] - p0[2]; + + if (vtkMath::Dot(n, d) < 0) + { + throw BadWinding(data); + } + } +} + +static vtkSmartPointer MakeTetrahedron(int num) +{ + VTK_CREATE(vtkDoubleArray, pointArray); + pointArray->SetArray(tetrahedraPoints, 4*3, 1); + pointArray->SetNumberOfComponents(3); + pointArray->SetNumberOfTuples(4); + + VTK_CREATE(vtkPoints, points); + points->SetData(pointArray); + + VTK_CREATE(vtkUnstructuredGrid, ugrid); + ugrid->SetPoints(points); + ugrid->InsertNextCell(VTK_TETRA, 4, tetrahedra[num]); + + return ugrid; +} + +static void PlaceRenderer(vtkRenderer *renderer, int boxnum, int tetnum, + int boxtype) +{ + renderer->SetViewport(tetnum/24.0 + 0.5*(boxtype%2), + 1.0 - ( (double)boxnum/NUM_CLIP_BOXES + + (double)(boxtype/2 + 1)/(2*NUM_CLIP_BOXES) ), + (tetnum + 1)/24.0 + 0.5*(boxtype%2), + 1.0 - ( (double)boxnum/NUM_CLIP_BOXES + + (double)(boxtype/2)/(2*NUM_CLIP_BOXES) )); +} + +static void TestBox(vtkRenderWindow *renwin, int boxnum, + double minx, double maxx, + double miny, double maxy, + double minz, double maxz) +{ + int i; + + // Add tests for axis oriented box and no clipped output. + for (i = 0; i < 12; i++) + { + vtkSmartPointer input = MakeTetrahedron(i); + CheckWinding(input); + + VTK_CREATE(vtkBoxClipDataSet, clipper); + clipper->SetInput(input); + clipper->GenerateClippedOutputOff(); + clipper->SetBoxClip(minx, maxx, miny, maxy, minz, maxz); + clipper->Update(); + CheckWinding(clipper->GetOutput()); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface); + surface->SetInputConnection(0, clipper->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper); + mapper->SetInputConnection(0, surface->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor); + actor->SetMapper(mapper); + + VTK_CREATE(vtkRenderer, renderer); + renderer->AddActor(actor); + renderer->SetBackground(0.0, 0.5, 0.5); + PlaceRenderer(renderer, boxnum, i, 0); + renderer->ResetCamera(); + renwin->AddRenderer(renderer); + + vtkCamera *camera = renderer->GetActiveCamera(); + camera->Azimuth(25.0); + camera->Elevation(-25.0); + } + + // Add tests for axis oriented box and clipped output. + for (i = 0; i < 12; i++) + { + vtkSmartPointer input = MakeTetrahedron(i); + CheckWinding(input); + + VTK_CREATE(vtkBoxClipDataSet, clipper); + clipper->SetInput(input); + clipper->GenerateClippedOutputOn(); + clipper->SetBoxClip(minx, maxx, miny, maxy, minz, maxz); + clipper->Update(); + CheckWinding(clipper->GetOutput()); + CheckWinding(clipper->GetClippedOutput()); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface1); + surface1->SetInputConnection(0, clipper->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper1); + mapper1->SetInputConnection(0, surface1->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor1); + actor1->SetMapper(mapper1); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface2); + surface2->SetInput(clipper->GetClippedOutput()); + + VTK_CREATE(vtkPolyDataMapper, mapper2); + mapper2->SetInputConnection(0, surface2->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor2); + actor2->SetMapper(mapper2); + actor2->GetProperty()->SetColor(1.0, 0.5, 0.5); + + VTK_CREATE(vtkRenderer, renderer); + renderer->AddActor(actor1); + renderer->AddActor(actor2); + renderer->SetBackground(0.0, 0.5, 0.5); + PlaceRenderer(renderer, boxnum, i, 1); + renderer->ResetCamera(); + renwin->AddRenderer(renderer); + + vtkCamera *camera = renderer->GetActiveCamera(); + camera->Azimuth(25.0); + camera->Elevation(-25.0); + } + + double minpoint[3], maxpoint[3]; + minpoint[0] = minx; minpoint[1] = miny; minpoint[2] = minz; + maxpoint[0] = maxx; maxpoint[1] = maxy; maxpoint[2] = maxz; + + // Add tests for arbitrarily oriented box and no clipped output. + for (i = 0; i < 12; i++) + { + vtkSmartPointer input = MakeTetrahedron(i); + CheckWinding(input); + + VTK_CREATE(vtkBoxClipDataSet, clipper); + clipper->SetInput(input); + clipper->GenerateClippedOutputOff(); + clipper->SetBoxClip(minusx, minpoint, minusy, minpoint, minusz, minpoint, + plusx, maxpoint, plusy, maxpoint, plusz, maxpoint); + clipper->Update(); + CheckWinding(clipper->GetOutput()); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface); + surface->SetInputConnection(0, clipper->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper); + mapper->SetInputConnection(0, surface->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor); + actor->SetMapper(mapper); + + VTK_CREATE(vtkRenderer, renderer); + renderer->AddActor(actor); + renderer->SetBackground(0.0, 0.5, 0.5); + PlaceRenderer(renderer, boxnum, i, 2); + renderer->ResetCamera(); + renwin->AddRenderer(renderer); + + vtkCamera *camera = renderer->GetActiveCamera(); + camera->Azimuth(25.0); + camera->Elevation(-25.0); + } + + // Add tests for arbitrarily oriented box and clipped output. + for (i = 0; i < 12; i++) + { + vtkSmartPointer input = MakeTetrahedron(i); + CheckWinding(input); + + VTK_CREATE(vtkBoxClipDataSet, clipper); + clipper->SetInput(input); + clipper->GenerateClippedOutputOn(); + clipper->SetBoxClip(minusx, minpoint, minusy, minpoint, minusz, minpoint, + plusx, maxpoint, plusy, maxpoint, plusz, maxpoint); + clipper->Update(); + CheckWinding(clipper->GetOutput()); + CheckWinding(clipper->GetClippedOutput()); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface1); + surface1->SetInputConnection(0, clipper->GetOutputPort(0)); + + VTK_CREATE(vtkPolyDataMapper, mapper1); + mapper1->SetInputConnection(0, surface1->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor1); + actor1->SetMapper(mapper1); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface2); + surface2->SetInput(clipper->GetClippedOutput()); + + VTK_CREATE(vtkPolyDataMapper, mapper2); + mapper2->SetInputConnection(0, surface2->GetOutputPort(0)); + + VTK_CREATE(vtkActor, actor2); + actor2->SetMapper(mapper2); + actor2->GetProperty()->SetColor(1.0, 0.5, 0.5); + + VTK_CREATE(vtkRenderer, renderer); + renderer->AddActor(actor1); + renderer->AddActor(actor2); + renderer->SetBackground(0.0, 0.5, 0.5); + PlaceRenderer(renderer, boxnum, i, 3); + renderer->ResetCamera(); + renwin->AddRenderer(renderer); + + vtkCamera *camera = renderer->GetActiveCamera(); + camera->Azimuth(25.0); + camera->Elevation(-25.0); + } +} + + +int BoxClipTetrahedra(int argc, char *argv[]) +{ + VTK_CREATE(vtkRenderWindow, renwin); + renwin->SetSize(960, 640); + + VTK_CREATE(vtkRenderWindowInteractor, iren); + iren->SetRenderWindow(renwin); + + try + { + TestBox(renwin, 0, 0.15, 2.0, -2.0, 2.0, -2.0, 2.0); + TestBox(renwin, 1, -2.0, 0.15, -2.0, 2.0, -2.0, 2.0); + TestBox(renwin, 2, -2.0, 2.0, -2.0, 2.0, -2.0, 0.4); + TestBox(renwin, 3, -2.0, 2.0, -2.0, 2.0, 0.4, 2.0); + TestBox(renwin, 4, -2.0, 2.0, -2.0, 2.0, -2.0, 0.5); + TestBox(renwin, 5, -2.0, 2.0, -2.0, 2.0, 0.5, 2.0); + TestBox(renwin, 6, -2.0, 0.0, -2.0, 2.0, -2.0, 2.0); + TestBox(renwin, 7, 0.0, 2.0, -2.0, 2.0, -2.0, 2.0); + } + catch (BadWinding bw) + { + cout << "Encountered a bad winding. Aborting test." << endl; + return 1; + } + + // Run the regression test. + renwin->Render(); + int retVal = vtkRegressionTestImage(renwin); + if (retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + return 0; + } + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/BoxClipTriangulate.cxx b/Graphics/Testing/Cxx/BoxClipTriangulate.cxx new file mode 100644 index 0000000..5038537 --- /dev/null +++ b/Graphics/Testing/Cxx/BoxClipTriangulate.cxx @@ -0,0 +1,371 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: BoxClipTriangulate.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// This test makes sure that vtkBoxClipDataSet correctly triangulates all cell +// types. + +#include "vtkBoxClipDataSet.h" +#include "vtkCellArray.h" +#include "vtkDataSetSurfaceFilter.h" +#include "vtkDoubleArray.h" +#include "vtkMath.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkTriangle.h" +#include "vtkUnstructuredGrid.h" + +#include "vtkExtractEdges.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" + +#include "vtkSmartPointer.h" +#define VTK_CREATE(type, var) \ + vtkSmartPointer var = vtkSmartPointer::New() + +#include + +#include + +const int NumPoints = 13; +const double PointData[NumPoints*3] = { + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0, + 1.0, 1.0, 0.0, + 2.0, 0.0, 0.0, + 2.0, 1.0, 0.0, + + 0.0, 0.0, 1.0, + 0.0, 1.0, 1.0, + 1.0, 0.0, 1.0, + 1.0, 1.0, 1.0, + 2.0, 0.0, 1.0, + 2.0, 1.0, 1.0, + 2.0, 0.5, 1.0 +}; + + +const vtkIdType NumTriStripCells = 1; +const vtkIdType TriStripCells[] = { + 6, 1, 0, 3, 2, 5, 4 +}; + +const vtkIdType NumQuadCells = 2; +const vtkIdType QuadCells[] = { + 4, 0, 2, 3, 1, + 4, 2, 4, 5, 3 +}; + +const vtkIdType NumPixelCells = 2; +const vtkIdType PixelCells[] = { + 4, 0, 2, 1, 3, + 4, 2, 4, 3, 5 +}; + +const vtkIdType NumPolyCells = 3; +const vtkIdType PolyCells[] = { + 4, 0, 2, 3, 1, + 3, 2, 4, 5, + 5, 6, 8, 12, 9, 7 +}; + + +const vtkIdType NumHexCells = 2; +const vtkIdType HexCells[] = { + 8, 6, 8, 2, 0, 7, 9, 3, 1, + 8, 4, 2, 8, 10, 5, 3, 9, 11 +}; +const vtkIdType NumExpectedHexSurfacePolys = 20; + +const vtkIdType NumVoxelCells = 2; +const vtkIdType VoxelCells[] = { + 8, 0, 2, 1, 3, 6, 8, 7, 9, + 8, 10, 8, 11, 9, 4, 2, 5, 3 +}; +const vtkIdType NumExpectedVoxelSurfacePolys = 20; + +const vtkIdType NumWedgeCells = 4; +const vtkIdType WedgeCells[] = { + 6, 0, 1, 2, 6, 7, 8, + 6, 7, 8, 9, 1, 2, 3, + 6, 8, 11, 9, 2, 5, 3, + 6, 2, 5, 4, 8, 11, 10 +}; +const vtkIdType NumExpectedWedgeSurfacePolys = 20; + +const vtkIdType NumPyramidCells = 2; +const vtkIdType PyramidCells[] = { + 5, 8, 9, 3, 2, 0, + 5, 2, 3, 9, 8, 12 +}; +const vtkIdType NumExpectedPyramidSurfacePolys = 8; + +class BoxClipTriangulateFailed { }; + +//----------------------------------------------------------------------------- + +static void CheckWinding(vtkUnstructuredGrid *data) +{ + data->Update(); + + vtkPoints *points = data->GetPoints(); + + vtkCellArray *cells = data->GetCells(); + cells->InitTraversal(); + + vtkIdType npts, *pts; + while (cells->GetNextCell(npts, pts)) + { + if (npts != 4) + { + cout << "Weird. I got something that is not a tetrahedra." << endl; + continue; + } + + double p0[3], p1[3], p2[3], p3[3]; + points->GetPoint(pts[0], p0); + points->GetPoint(pts[1], p1); + points->GetPoint(pts[2], p2); + points->GetPoint(pts[3], p3); + + // If the winding is correct, the normal to triangle p0,p1,p2 should point + // towards p3. + double v0[3], v1[3]; + v0[0] = p1[0] - p0[0]; v0[1] = p1[1] - p0[1]; v0[2] = p1[2] - p0[2]; + v1[0] = p2[0] - p0[0]; v1[1] = p2[1] - p0[1]; v1[2] = p2[2] - p0[2]; + + double n[3]; + vtkMath::Cross(v0, v1, n); + + double d[3]; + d[0] = p3[0] - p0[0]; d[1] = p3[1] - p0[1]; d[2] = p3[2] - p0[2]; + + if (vtkMath::Dot(n, d) < 0) + { + cout << "Found a tetrahedra with bad winding." << endl; + throw BoxClipTriangulateFailed(); + } + } +} + +//----------------------------------------------------------------------------- + +static vtkSmartPointer BuildInput(int type, + vtkIdType numcells, + const vtkIdType *cells) +{ + vtkIdType i; + + VTK_CREATE(vtkUnstructuredGrid, input); + + // Randomly shuffle the points to possibly test various tessellations. + // Make a map from original point orderings to new point orderings. + vtkstd::vector idMap; + vtkstd::vector idsLeft; + + for (i = 0; i < NumPoints; i++) + { + idsLeft.push_back(i); + } + + while (!idsLeft.empty()) + { + vtkIdType next + = vtkMath::Round(vtkMath::Random(-0.49, idsLeft.size() - 0.51)); + vtkstd::vector::iterator nextp = idsLeft.begin() + next; + idMap.push_back(*nextp); + idsLeft.erase(nextp, nextp + 1); + } + + // Build shuffled points. + VTK_CREATE(vtkPoints, points); + points->SetNumberOfPoints(NumPoints); + for (i = 0; i < NumPoints; i++) + { + points->SetPoint(idMap[i], PointData + 3*i); + } + input->SetPoints(points); + + // Add the cells with indices properly mapped. + VTK_CREATE(vtkIdList, ptIds); + const vtkIdType *c = cells; + for (i = 0; i < numcells; i++) + { + vtkIdType npts = *c; c++; + ptIds->Initialize(); + for (vtkIdType j = 0; j < npts; j++) + { + ptIds->InsertNextId(idMap[*c]); + c++; + } + input->InsertNextCell(type, ptIds); + } + + return input; +} + +//----------------------------------------------------------------------------- + +static void Check2DPrimitive(int type, vtkIdType numcells, + const vtkIdType *cells) +{ + vtkSmartPointer input + = BuildInput(type, numcells, cells); + + VTK_CREATE(vtkBoxClipDataSet, clipper); + clipper->SetInput(input); + // Clip nothing. + clipper->SetBoxClip(0.0, 2.0, 0.0, 1.0, 0.0, 1.0); + clipper->Update(); + + vtkUnstructuredGrid *output = clipper->GetOutput(); + + if (output->GetNumberOfCells() < 1) + { + cout << "Output has no cells!" << endl; + throw BoxClipTriangulateFailed(); + } + + // Check to make sure all the normals point in the z direction. + vtkCellArray *outCells = output->GetCells(); + outCells->InitTraversal(); + vtkIdType npts, *pts; + while (outCells->GetNextCell(npts, pts)) + { + if (npts != 3) + { + cout << "Got a primitive that is not a triangle!" << endl; + throw BoxClipTriangulateFailed(); + } + + double n[3]; + vtkTriangle::ComputeNormal(output->GetPoints(), npts, pts, n); + if ((n[0] > 0.1) || (n[1] > 0.1) || (n[2] < 0.9)) + { + cout << "Primitive is facing the wrong way!" << endl; + throw BoxClipTriangulateFailed(); + } + } +} + +//----------------------------------------------------------------------------- + +static void Check3DPrimitive(int type, vtkIdType numcells, + const vtkIdType *cells, vtkIdType numSurfacePolys) +{ + vtkSmartPointer input + = BuildInput(type, numcells, cells); + + VTK_CREATE(vtkBoxClipDataSet, clipper); + clipper->SetInput(input); + // Clip nothing. + clipper->SetBoxClip(0.0, 2.0, 0.0, 1.0, 0.0, 1.0); + clipper->Update(); + + vtkUnstructuredGrid *output = clipper->GetOutput(); + + if (output->GetNumberOfCells() < 1) + { + cout << "Output has no cells!" << endl; + throw BoxClipTriangulateFailed(); + } + +#if 0 + VTK_CREATE(vtkExtractEdges, edges); + edges->SetInput(output); + VTK_CREATE(vtkPolyDataMapper, mapper); + mapper->SetInputConnection(0, edges->GetOutputPort(0)); + VTK_CREATE(vtkActor, actor); + actor->SetMapper(mapper); + VTK_CREATE(vtkRenderer, renderer); + renderer->AddActor(actor); + VTK_CREATE(vtkRenderWindow, renwin); + renwin->AddRenderer(renderer); + VTK_CREATE(vtkRenderWindowInteractor, iren); + iren->SetRenderWindow(renwin); + renwin->Render(); + iren->Start(); +#endif + + CheckWinding(output); + + VTK_CREATE(vtkDataSetSurfaceFilter, surface); + surface->SetInput(output); + surface->Update(); + + if (surface->GetOutput()->GetNumberOfCells() != numSurfacePolys) + { + cout << "Expected " << numSurfacePolys << " triangles on the surface, got " + << surface->GetOutput()->GetNumberOfCells() << endl; + throw BoxClipTriangulateFailed(); + } +} + +//----------------------------------------------------------------------------- + +int BoxClipTriangulate(int, char *[]) +{ + long seed = time(NULL); + cout << "Random seed = " << seed << endl; + vtkMath::RandomSeed(seed); + vtkMath::Random(); + vtkMath::Random(); + vtkMath::Random(); + + try + { + cout << "Checking triangle strip." << endl; + Check2DPrimitive(VTK_TRIANGLE_STRIP, NumTriStripCells, TriStripCells); + + cout << "Checking quadrilaterals." << endl; + Check2DPrimitive(VTK_QUAD, NumQuadCells, QuadCells); + + cout << "Checking pixels." << endl; + Check2DPrimitive(VTK_PIXEL, NumPixelCells, PixelCells); + + cout << "Checking polygons." << endl; + Check2DPrimitive(VTK_POLYGON, NumPolyCells, PolyCells); + + cout << "Checking hexahedrons." << endl; + Check3DPrimitive(VTK_HEXAHEDRON, NumHexCells, HexCells, + NumExpectedHexSurfacePolys); + + cout << "Checking voxels." << endl; + Check3DPrimitive(VTK_VOXEL, NumVoxelCells, VoxelCells, + NumExpectedVoxelSurfacePolys); + + cout << "Checking wedges." << endl; + Check3DPrimitive(VTK_WEDGE, NumWedgeCells, WedgeCells, + NumExpectedWedgeSurfacePolys); + + cout << "Checking pyramids." << endl; + Check3DPrimitive(VTK_PYRAMID, NumPyramidCells, PyramidCells, + NumExpectedPyramidSurfacePolys); + } + catch (BoxClipTriangulateFailed) + { + return 1; + } + + return 0; +} diff --git a/Graphics/Testing/Cxx/CMakeLists.txt b/Graphics/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..61ec4f3 --- /dev/null +++ b/Graphics/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,46 @@ +# if we have rendering add the following tests +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + SET(KIT Graphics) + # add tests that do not require data + SET(MyTests + Mace.cxx + expCos.cxx + BoxClipTriangulate.cxx + CellLocator.cxx + PointLocator.cxx + FrustumClip.cxx + RGrid.cxx + TestSortDataArray.cxx + ) + IF (VTK_DATA_ROOT) + # add tests that require data + SET(MyTests ${MyTests} + BoxClipPolyData.cxx + BoxClipTetrahedra.cxx + MeshQuality.cxx + TestHierarchicalBoxPipeline.cxx + TestMultiBlock.cxx + ) + ENDIF (VTK_DATA_ROOT) + CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx ${MyTests} + EXTRA_INCLUDE vtkTestDriver.h) + ADD_EXECUTABLE(${KIT}CxxTests ${Tests} + vtkTestHierarchicalDataReader.cxx) + TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkRendering vtkIO) + SET (TestsToRun ${Tests}) + REMOVE (TestsToRun ${KIT}CxxTests.cxx) + + # + # Add all the executables + FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + IF (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName} + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/${KIT}/${TName}.png) + ELSE (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) + ENDIF (VTK_DATA_ROOT) + ENDFOREACH (test) +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) diff --git a/Graphics/Testing/Cxx/CellLocator.cxx b/Graphics/Testing/Cxx/CellLocator.cxx new file mode 100644 index 0000000..9f4027a --- /dev/null +++ b/Graphics/Testing/Cxx/CellLocator.cxx @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: CellLocator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCellLocator.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" + +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +int CellLocator( int argc, char *argv[] ) +{ + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(8); sphere->SetPhiResolution(8); + sphere->SetRadius(1.0); + sphere->Update(); + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + vtkActor *sphereActor = vtkActor::New(); + sphereActor->SetMapper(sphereMapper); + + vtkSphereSource *spot = vtkSphereSource::New(); + spot->SetPhiResolution(6); + spot->SetThetaResolution(6); + spot->SetRadius(0.1); + + vtkPolyDataMapper *spotMapper = vtkPolyDataMapper::New(); + spotMapper->SetInputConnection(spot->GetOutputPort()); + + // Build a locator + vtkCellLocator *cellLocator = vtkCellLocator::New(); + cellLocator->SetDataSet(sphere->GetOutput()); + cellLocator->BuildLocator(); + + // Intersect with line + double p1[] = {2.0, 1.0, 3.0}; + double p2[] = {0.0, 0.0, 0.0}; + double t, ptline[3], pcoords[3]; + int subId; + cellLocator->IntersectWithLine(p1, p2, 0.001, t, ptline, pcoords, subId); + + vtkActor *intersectLineActor = vtkActor::New(); + intersectLineActor->SetMapper(spotMapper); + intersectLineActor->SetPosition(ptline[0],ptline[1],ptline[2]); + intersectLineActor->GetProperty()->SetColor(1.0, 0.0, 0.0); + + // Find closest point + vtkIdType cellId; + double dist; + p1[0] = -2.4; p1[1] = -0.9; + cellLocator->FindClosestPoint(p1, ptline, cellId, subId, dist); + vtkActor *closestPointActor = vtkActor::New(); + closestPointActor->SetMapper(spotMapper); + closestPointActor->SetPosition(ptline[0],ptline[1],ptline[2]); + closestPointActor->GetProperty()->SetColor(0.0, 1.0, 0.0); + + // Find closest point within radius + float radius = 5.0; + p1[0] = .2; p1[1] = 1.0; p1[2] = 1.0; + cellLocator->FindClosestPointWithinRadius(p1, radius, ptline, cellId, subId, dist); + vtkActor *closestPointActor2 = vtkActor::New(); + closestPointActor2->SetMapper(spotMapper); + closestPointActor2->SetPosition(ptline[0],ptline[1],ptline[2]); + closestPointActor2->GetProperty()->SetColor(0.0, 1.0, 0.0); + + renderer->AddActor(sphereActor); + renderer->AddActor(intersectLineActor); + renderer->AddActor(closestPointActor); + renderer->AddActor(closestPointActor2); + renderer->SetBackground(1,1,1); + renWin->SetSize(300,300); + + // interact with data + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + sphere->Delete(); + sphereMapper->Delete(); + sphereActor->Delete(); + spot->Delete(); + spotMapper->Delete(); + intersectLineActor->Delete(); + closestPointActor->Delete(); + closestPointActor2->Delete(); + cellLocator->FreeSearchStructure(); + cellLocator->Delete(); + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/FrustumClip.cxx b/Graphics/Testing/Cxx/FrustumClip.cxx new file mode 100644 index 0000000..bbc5f07 --- /dev/null +++ b/Graphics/Testing/Cxx/FrustumClip.cxx @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: FrustumClip.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkClipPolyData.h" +#include "vtkDebugLeaks.h" +#include "vtkPlanes.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" + +// Generate a sphere. Create a view frustum looking at the sphere +// Clip anything inside the frustum, then back away and view result + +int FrustumClip( int argc, char *argv[] ) +{ + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(36); + sphere->SetPhiResolution(18); + sphere->SetRadius(1); + + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection( sphere->GetOutputPort()); + + vtkActor *sphereActor = vtkActor::New(); + sphereActor->SetMapper(sphereMapper); + + renderer->AddActor(sphereActor); + renderer->SetBackground(1,1,1); + renWin->SetSize(400,300); + + vtkCamera *camera = renderer->GetActiveCamera(); + camera->SetPosition(1.5, 0.0, 0.0); + renderer->ResetCameraClippingRange(); + + // Display once with camera in position 1 + // Ensures clipping planes are initialized (camera matrix really). + renWin->Render(); + + // Now get the camera frustum and then move the camera away to see the + // clipped away stuff + double aspect=400.0/300.0, planeequations[24]; + camera->GetFrustumPlanes(aspect, planeequations); + + vtkPlanes *implictplanes = vtkPlanes::New(); + // TODO cleanup + double ped[24]; + int i; + for (i = 0; i < 24; ++i) + { + ped[i] = planeequations[i]; + } + implictplanes->SetFrustumPlanes(ped); + + vtkClipPolyData *clipper = vtkClipPolyData::New(); + clipper->SetInputConnection(sphere->GetOutputPort()); + clipper->SetClipFunction(implictplanes); + clipper->SetGenerateClipScalars(1); + clipper->SetInsideOut(0); + sphereMapper->SetInputConnection( clipper->GetOutputPort()); + + camera->SetPosition(-4.0, 0.25, 0.25); + renderer->ResetCameraClippingRange(); + + sphereActor->GetProperty()->SetColor(0.0,0.0,0.0); + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + // Clean up + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + sphere->Delete(); + sphereMapper->Delete(); + sphereActor->Delete(); + implictplanes->Delete(); + clipper->Delete(); + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/Mace.cxx b/Graphics/Testing/Cxx/Mace.cxx new file mode 100644 index 0000000..a11948d --- /dev/null +++ b/Graphics/Testing/Cxx/Mace.cxx @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Mace.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkConeSource.h" +#include "vtkDebugLeaks.h" +#include "vtkGlyph3D.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" + +int Mace( int argc, char *argv[] ) +{ + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(8); sphere->SetPhiResolution(8); + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + vtkActor *sphereActor = vtkActor::New(); + sphereActor->SetMapper(sphereMapper); + + vtkConeSource *cone = vtkConeSource::New(); + cone->SetResolution(6); + + vtkGlyph3D *glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(sphere->GetOutputPort()); + glyph->SetSourceConnection(cone->GetOutputPort()); + glyph->SetVectorModeToUseNormal(); + glyph->SetScaleModeToScaleByVector(); + glyph->SetScaleFactor(0.25); + + vtkPolyDataMapper *spikeMapper = vtkPolyDataMapper::New(); + spikeMapper->SetInputConnection(glyph->GetOutputPort()); + + vtkActor *spikeActor = vtkActor::New(); + spikeActor->SetMapper(spikeMapper); + + renderer->AddActor(sphereActor); + renderer->AddActor(spikeActor); + renderer->SetBackground(1,1,1); + renWin->SetSize(300,300); + + // interact with data + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + // Clean up + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + sphere->Delete(); + sphereMapper->Delete(); + sphereActor->Delete(); + cone->Delete(); + glyph->Delete(); + spikeMapper->Delete(); + spikeActor->Delete(); + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/MeshQuality.cxx b/Graphics/Testing/Cxx/MeshQuality.cxx new file mode 100644 index 0000000..6a4f9c7 --- /dev/null +++ b/Graphics/Testing/Cxx/MeshQuality.cxx @@ -0,0 +1,179 @@ +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkMeshQuality.h" + +#include "vtkDebugLeaks.h" +#include "vtkTestUtilities.h" +#include "vtkUnstructuredGrid.h" +#include "vtkUnstructuredGridReader.h" +#include "vtkFieldData.h" + +int DumpQualityStats( vtkMeshQuality* iq, const char *arrayname ) +{ + double avg = iq->GetOutput()->GetFieldData()->GetArray( arrayname )->GetComponent( 0, 1 ); + + cout << " range: " + << iq->GetOutput()->GetFieldData()->GetArray( arrayname )->GetComponent( 0, 0 ) + << " - " + << iq->GetOutput()->GetFieldData()->GetArray( arrayname )->GetComponent( 0, 2 ) + << endl; + cout << " average: " << avg + << " , standard deviation: " + << sqrt(fabs(iq->GetOutput()->GetFieldData()->GetArray( arrayname )->GetComponent( 0, 3 ) - avg * avg)) + << endl; + + return 0; +} + +int MeshQuality( int argc, char* argv[] ) +{ + vtkUnstructuredGridReader* mr = vtkUnstructuredGridReader::New(); + vtkUnstructuredGrid* ug; + vtkMeshQuality* iq = vtkMeshQuality::New(); + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/uGridEx.vtk"); + + mr->SetFileName( fname ); + mr->Update(); + + ug = mr->GetOutput(); + iq->SetInput( ug ); + + if ( ug->GetNumberOfCells() ) + { + cout << endl; + cout << "Triangle quality of mesh" << endl; + cout << mr->GetFileName() + << endl; + + iq->SetTriangleQualityMeasureToEdgeRatio(); + iq->Update(); + cout << " Edge Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Triangle Quality" ); + + iq->SetTriangleQualityMeasureToAspectRatio(); + iq->Update(); + cout << " Aspect Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Triangle Quality" ); + + iq->SetTriangleQualityMeasureToRadiusRatio(); + iq->Update(); + cout << " Radius Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Triangle Quality" ); + + iq->SetTriangleQualityMeasureToFrobeniusNorm(); + iq->Update(); + cout << " Frobenius Norm:" + << endl; + DumpQualityStats( iq, "Mesh Triangle Quality" ); + + iq->SetTriangleQualityMeasureToMinAngle(); + iq->Update(); + cout << " Minimal Angle:" + << endl; + DumpQualityStats( iq, "Mesh Triangle Quality" ); + + cout << endl; + cout << "Quadrilatedral quality of mesh" << endl; + cout << mr->GetFileName() + << endl; + + iq->SetQuadQualityMeasureToEdgeRatio(); + iq->Update(); + cout << " Edge Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Quadrilateral Quality" ); + + iq->SetQuadQualityMeasureToAspectRatio(); + iq->Update(); + cout << " Aspect Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Quadrilateral Quality" ); + + iq->SetQuadQualityMeasureToRadiusRatio(); + iq->Update(); + cout << " Radius Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Quadrilateral Quality" ); + + iq->SetQuadQualityMeasureToMedFrobeniusNorm(); + iq->Update(); + cout << " Average Frobenius Norm:" + << endl; + DumpQualityStats( iq, "Mesh Quadrilateral Quality" ); + + iq->SetQuadQualityMeasureToMaxFrobeniusNorm(); + iq->Update(); + cout << " Maximal Frobenius Norm:" + << endl; + DumpQualityStats( iq, "Mesh Quadrilateral Quality" ); + + iq->SetQuadQualityMeasureToMinAngle(); + iq->Update(); + cout << " Minimal Angle:" + << endl; + DumpQualityStats( iq, "Mesh Quadrilateral Quality" ); + + cout << endl; + cout << "Tetrahedral quality of mesh" << endl; + cout << mr->GetFileName() + << endl; + + iq->SetTetQualityMeasureToEdgeRatio(); + iq->Update(); + cout << " Edge Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Tetrahedron Quality" ); + + iq->SetTetQualityMeasureToAspectRatio(); + iq->Update(); + cout << " Aspect Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Tetrahedron Quality" ); + + iq->SetTetQualityMeasureToRadiusRatio(); + iq->Update(); + cout << " Radius Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Tetrahedron Quality" ); + + iq->SetTetQualityMeasureToFrobeniusNorm(); + iq->Update(); + cout << " Frobenius Norm:" + << endl; + DumpQualityStats( iq, "Mesh Tetrahedron Quality" ); + + iq->SetTetQualityMeasureToMinAngle(); + iq->Update(); + cout << " Minimal Dihedral Angle:" + << endl; + DumpQualityStats( iq, "Mesh Tetrahedron Quality" ); + cout << endl; + + cout << "Hexahedral quality of mesh" << endl; + cout << mr->GetFileName() + << endl; + + iq->SetHexQualityMeasureToEdgeRatio(); + iq->Update(); + cout << " Edge Ratio:" + << endl; + DumpQualityStats( iq, "Mesh Hexahedron Quality" ); + cout << endl; + } + + iq->Delete(); + mr->Delete(); + delete [] fname; + + return 0; +} diff --git a/Graphics/Testing/Cxx/PointLocator.cxx b/Graphics/Testing/Cxx/PointLocator.cxx new file mode 100644 index 0000000..6617461 --- /dev/null +++ b/Graphics/Testing/Cxx/PointLocator.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: PointLocator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkPointLocator.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" + +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +int PointLocator( int argc, char *argv[] ) +{ + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(8); sphere->SetPhiResolution(8); + sphere->SetRadius(1.0); + sphere->Update(); + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInputConnection(sphere->GetOutputPort()); + vtkActor *sphereActor = vtkActor::New(); + sphereActor->SetMapper(sphereMapper); + + vtkSphereSource *spot = vtkSphereSource::New(); + spot->SetPhiResolution(6); + spot->SetThetaResolution(6); + spot->SetRadius(0.1); + + vtkPolyDataMapper *spotMapper = vtkPolyDataMapper::New(); + spotMapper->SetInputConnection(spot->GetOutputPort()); + + // Build a locator + vtkPointLocator *pointLocator = vtkPointLocator::New(); + pointLocator->SetDataSet(sphere->GetOutput()); + pointLocator->BuildLocator(); + + // + double p1[] = {2.0, 1.0, 3.0}; + + // Find closest point + vtkIdType ptId; + double dist; + p1[0] = 0.1; p1[1] = -0.2; p1[2] = 0.2; + ptId = pointLocator->FindClosestPoint(p1); + vtkActor *closestPointActor = vtkActor::New(); + closestPointActor->SetMapper(spotMapper); + // TODO cleanupo + closestPointActor->SetPosition( + sphere->GetOutput()->GetPoints()->GetPoint(ptId)[0], + sphere->GetOutput()->GetPoints()->GetPoint(ptId)[1], + sphere->GetOutput()->GetPoints()->GetPoint(ptId)[2]); + closestPointActor->GetProperty()->SetColor(0.0, 1.0, 0.0); + + // Find closest point within radius + float radius = 5.0; + p1[0] = .2; p1[1] = 1.0; p1[2] = 1.0; + ptId = pointLocator->FindClosestPointWithinRadius(radius, p1, dist); + vtkActor *closestPointActor2 = vtkActor::New(); + closestPointActor2->SetMapper(spotMapper); + // TODO cleanup + closestPointActor2->SetPosition( + sphere->GetOutput()->GetPoints()->GetPoint(ptId)[0], + sphere->GetOutput()->GetPoints()->GetPoint(ptId)[1], + sphere->GetOutput()->GetPoints()->GetPoint(ptId)[2]); + closestPointActor2->GetProperty()->SetColor(0.0, 1.0, 0.0); + + renderer->AddActor(sphereActor); + renderer->AddActor(closestPointActor); + renderer->AddActor(closestPointActor2); + renderer->SetBackground(1,1,1); + renWin->SetSize(300,300); + + // interact with data + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + sphere->Delete(); + sphereMapper->Delete(); + sphereActor->Delete(); + spot->Delete(); + spotMapper->Delete(); + closestPointActor->Delete(); + closestPointActor2->Delete(); + pointLocator->FreeSearchStructure(); + pointLocator->Delete(); + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/RGrid.cxx b/Graphics/Testing/Cxx/RGrid.cxx new file mode 100644 index 0000000..021ec94 --- /dev/null +++ b/Graphics/Testing/Cxx/RGrid.cxx @@ -0,0 +1,121 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: RGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkFloatArray.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRectilinearGrid.h" +#include "vtkRectilinearGridGeometryFilter.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" + +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +int RGrid( int argc, char *argv[] ) +{ + int i; + static float x[47]={-1.22396, -1.17188, -1.11979, -1.06771, -1.01562, -0.963542, + -0.911458, -0.859375, -0.807292, -0.755208, -0.703125, -0.651042, + -0.598958, -0.546875, -0.494792, -0.442708, -0.390625, -0.338542, + -0.286458, -0.234375, -0.182292, -0.130209, -0.078125, -0.026042, + 0.0260415, 0.078125, 0.130208, 0.182291, 0.234375, 0.286458, + 0.338542, 0.390625, 0.442708, 0.494792, 0.546875, 0.598958, + 0.651042, 0.703125, 0.755208, 0.807292, 0.859375, 0.911458, + 0.963542, 1.01562, 1.06771, 1.11979, 1.17188}; + static float y[33]={-1.25, -1.17188, -1.09375, -1.01562, -0.9375, -0.859375, + -0.78125, -0.703125, -0.625, -0.546875, -0.46875, -0.390625, + -0.3125, -0.234375, -0.15625, -0.078125, 0, 0.078125, + 0.15625, 0.234375, 0.3125, 0.390625, 0.46875, 0.546875, + 0.625, 0.703125, 0.78125, 0.859375, 0.9375, 1.01562, + 1.09375, 1.17188, 1.25}; + static float z[44]={0, 0.1, 0.2, 0.3, 0.4, 0.5, + 0.6, 0.7, 0.75, 0.8, 0.9, 1, + 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, + 1.7, 1.75, 1.8, 1.9, 2, 2.1, + 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, + 2.75, 2.8, 2.9, 3, 3.1, 3.2, + 3.3, 3.4, 3.5, 3.6, 3.7, 3.75, + 3.8, 3.9}; + + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkFloatArray *xCoords = vtkFloatArray::New(); + for (i=0; i<47; i++) xCoords->InsertNextValue(x[i]); + + vtkFloatArray *yCoords = vtkFloatArray::New(); + for (i=0; i<33; i++) yCoords->InsertNextValue(y[i]); + + vtkFloatArray *zCoords = vtkFloatArray::New(); + for (i=0; i<44; i++) zCoords->InsertNextValue(z[i]); + + vtkRectilinearGrid *rgrid = vtkRectilinearGrid::New(); + rgrid->SetDimensions(47,33,44); + rgrid->SetXCoordinates(xCoords); + rgrid->SetYCoordinates(yCoords); + rgrid->SetZCoordinates(zCoords); + + vtkRectilinearGridGeometryFilter *plane = vtkRectilinearGridGeometryFilter::New(); + plane->SetInput(rgrid); + plane->SetExtent(0,46, 16,16, 0,43); + + vtkPolyDataMapper *rgridMapper = vtkPolyDataMapper::New(); + rgridMapper->SetInputConnection(plane->GetOutputPort()); + + vtkActor *wireActor = vtkActor::New(); + wireActor->SetMapper(rgridMapper); + wireActor->GetProperty()->SetRepresentationToWireframe(); + wireActor->GetProperty()->SetColor(0,0,0); + + renderer->AddActor(wireActor); + renderer->SetBackground(1,1,1); + renderer->ResetCamera(); + renderer->GetActiveCamera()->Elevation(60.0); + renderer->GetActiveCamera()->Azimuth(30.0); + renderer->GetActiveCamera()->Zoom(1.0); + + renWin->SetSize(300,300); + + // interact with data + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + xCoords->Delete(); + yCoords->Delete(); + zCoords->Delete(); + rgrid->Delete(); + rgridMapper->Delete(); + plane->Delete(); + wireActor->Delete(); + + return !retVal; + +} diff --git a/Graphics/Testing/Cxx/TestHierarchicalBoxPipeline.cxx b/Graphics/Testing/Cxx/TestHierarchicalBoxPipeline.cxx new file mode 100644 index 0000000..cbe3efa --- /dev/null +++ b/Graphics/Testing/Cxx/TestHierarchicalBoxPipeline.cxx @@ -0,0 +1,144 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestHierarchicalBoxPipeline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how hierarchical box (uniform rectilinear) +// AMR datasets can be processed using the new vtkHierarchicalBoxDataSet class. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +#include "vtkCamera.h" +#include "vtkCellDataToPointData.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkContourFilter.h" +#include "vtkDebugLeaks.h" +#include "vtkHierarchicalDataExtractLevel.h" +#include "vtkHierarchicalDataSetGeometryFilter.h" +#include "vtkOutlineCornerFilter.h" +#include "vtkHierarchicalPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkShrinkPolyData.h" +#include "vtkTestHierarchicalDataReader.h" +#include "vtkTestUtilities.h" + +int TestHierarchicalBoxPipeline(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *ren = vtkRenderer::New(); + vtkCamera* cam = ren->GetActiveCamera(); + cam->SetPosition(-5.1828, 5.89733, 8.97969); + cam->SetFocalPoint(14.6491, -2.08677, -8.92362); + cam->SetViewUp(0.210794, 0.95813, -0.193784); + + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + char* cfname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/chombo3d/chombo3d"); + + vtkTestHierarchicalDataReader* reader = vtkTestHierarchicalDataReader::New(); + reader->SetFileName(cfname); + delete[] cfname; + + // geometry filter + vtkHierarchicalDataSetGeometryFilter* geom = + vtkHierarchicalDataSetGeometryFilter::New(); + geom->SetInputConnection(0, reader->GetOutputPort(0)); + + vtkShrinkPolyData* shrink = vtkShrinkPolyData::New(); + shrink->SetShrinkFactor(0.5); + shrink->SetInputConnection(0, geom->GetOutputPort(0)); + + // Rendering objects + vtkHierarchicalPolyDataMapper* shMapper = vtkHierarchicalPolyDataMapper::New(); + shMapper->SetInputConnection(0, shrink->GetOutputPort(0)); + vtkActor* shActor = vtkActor::New(); + shActor->SetMapper(shMapper); + shActor->GetProperty()->SetColor(0, 0, 1); + ren->AddActor(shActor); + + // corner outline + vtkOutlineCornerFilter* ocf = vtkOutlineCornerFilter::New(); + ocf->SetInputConnection(0, reader->GetOutputPort(0)); + + // Rendering objects + // This one is actually just a vtkPolyData so it doesn't need a hierarchical + // mapper, but we use this one to test hierarchical mapper with polydata input + vtkHierarchicalPolyDataMapper* ocMapper = vtkHierarchicalPolyDataMapper::New(); + ocMapper->SetInputConnection(0, ocf->GetOutputPort(0)); + vtkActor* ocActor = vtkActor::New(); + ocActor->SetMapper(ocMapper); + ocActor->GetProperty()->SetColor(1, 0, 0); + ren->AddActor(ocActor); + + // cell 2 point and contour + vtkHierarchicalDataExtractLevel* el = vtkHierarchicalDataExtractLevel::New(); + el->SetInputConnection(0, reader->GetOutputPort(0)); + el->SetLevelRange(2,2); + + vtkCellDataToPointData* c2p = vtkCellDataToPointData::New(); + c2p->SetInputConnection(0, el->GetOutputPort(0)); + + vtkContourFilter* contour = vtkContourFilter::New(); + contour->SetInputConnection(0, c2p->GetOutputPort(0)); + contour->SetValue(0, -0.013); + contour->SetInputArrayToProcess( + 0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,"phi"); + + // Rendering objects + vtkHierarchicalPolyDataMapper* contMapper = vtkHierarchicalPolyDataMapper::New(); + contMapper->SetInputConnection(0, contour->GetOutputPort(0)); + vtkActor* contActor = vtkActor::New(); + contActor->SetMapper(contMapper); + contActor->GetProperty()->SetColor(1, 0, 0); + ren->AddActor(contActor); + + // Standard testing code. + ocf->Delete(); + ocMapper->Delete(); + ocActor->Delete(); + c2p->Delete(); + contour->Delete(); + contMapper->Delete(); + contActor->Delete(); + ren->SetBackground(1,1,1); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + el->Delete(); + geom->Delete(); + shMapper->Delete(); + shActor->Delete(); + ren->Delete(); + renWin->Delete(); + iren->Delete(); + reader->Delete(); + shrink->Delete(); + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/TestMultiBlock.cxx b/Graphics/Testing/Cxx/TestMultiBlock.cxx new file mode 100644 index 0000000..b2dfcbe --- /dev/null +++ b/Graphics/Testing/Cxx/TestMultiBlock.cxx @@ -0,0 +1,155 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestMultiBlock.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates how hierarchical box (uniform rectilinear) +// AMR datasets can be processed using the new vtkHierarchicalBoxDataSet class. +// +// The command line arguments are: +// -I => run in interactive mode; unless this is used, the program will +// not allow interaction and exit +// -D => path to the data; the data should be in /Data/ + +#include "vtkCamera.h" +#include "vtkCellDataToPointData.h" +#include "vtkContourFilter.h" +#include "vtkDebugLeaks.h" +#include "vtkHierarchicalDataExtractDataSets.h" +#include "vtkHierarchicalDataSetGeometryFilter.h" +#include "vtkMultiBlockPLOT3DReader.h" +#include "vtkOutlineCornerFilter.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkShrinkPolyData.h" +#include "vtkTestUtilities.h" + +int TestMultiBlock(int argc, char* argv[]) +{ + // Standard rendering classes + vtkRenderer *ren = vtkRenderer::New(); + vtkCamera* cam = ren->GetActiveCamera(); + cam->SetPosition(-5.1828, 5.89733, 8.97969); + cam->SetFocalPoint(14.6491, -2.08677, -8.92362); + cam->SetViewUp(0.210794, 0.95813, -0.193784); + + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + char* xyzname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/mbwavelet_ascii.xyz"); + char* qname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/mbwavelet_ascii.q"); + + vtkMultiBlockPLOT3DReader* reader = vtkMultiBlockPLOT3DReader::New(); + reader->SetXYZFileName(xyzname); + reader->SetQFileName(qname); + reader->SetMultiGrid(1); + reader->SetBinaryFile(0); + delete[] xyzname; + delete[] qname; + + // geometry filter + vtkHierarchicalDataSetGeometryFilter* geom = + vtkHierarchicalDataSetGeometryFilter::New(); + geom->SetInputConnection(0, reader->GetOutputPort(0)); + + vtkShrinkPolyData* shrink = vtkShrinkPolyData::New(); + shrink->SetShrinkFactor(0.2); + shrink->SetInputConnection(0, geom->GetOutputPort(0)); + + // Rendering objects + vtkPolyDataMapper* shMapper = vtkPolyDataMapper::New(); + shMapper->SetInputConnection(0, shrink->GetOutputPort(0)); + vtkActor* shActor = vtkActor::New(); + shActor->SetMapper(shMapper); + shActor->GetProperty()->SetColor(0, 0, 1); + ren->AddActor(shActor); + + // corner outline + vtkOutlineCornerFilter* ocf = vtkOutlineCornerFilter::New(); + ocf->SetInputConnection(0, reader->GetOutputPort(0)); + + // geometry filter + vtkHierarchicalDataSetGeometryFilter* geom2 = + vtkHierarchicalDataSetGeometryFilter::New(); + geom2->SetInputConnection(0, ocf->GetOutputPort(0)); + + // Rendering objects + vtkPolyDataMapper* ocMapper = vtkPolyDataMapper::New(); + ocMapper->SetInputConnection(0, geom2->GetOutputPort(0)); + vtkActor* ocActor = vtkActor::New(); + ocActor->SetMapper(ocMapper); + ocActor->GetProperty()->SetColor(1, 0, 0); + ren->AddActor(ocActor); + + // extract a block + vtkHierarchicalDataExtractDataSets* eds = + vtkHierarchicalDataExtractDataSets::New(); + eds->SetInputConnection(0, reader->GetOutputPort(0)); + eds->AddDataSet(0, 1); + + // contour + vtkContourFilter* contour = vtkContourFilter::New(); + contour->SetInputConnection(0, eds->GetOutputPort(0)); + contour->SetValue(0, 149); + + // geometry filter + vtkHierarchicalDataSetGeometryFilter* geom3 = + vtkHierarchicalDataSetGeometryFilter::New(); + geom3->SetInputConnection(0, contour->GetOutputPort(0)); + + // Rendering objects + vtkPolyDataMapper* contMapper = vtkPolyDataMapper::New(); + contMapper->SetInputConnection(0, geom3->GetOutputPort(0)); + vtkActor* contActor = vtkActor::New(); + contActor->SetMapper(contMapper); + contActor->GetProperty()->SetColor(1, 0, 0); + ren->AddActor(contActor); + + // Standard testing code. + eds->Delete(); + ocf->Delete(); + geom2->Delete(); + ocMapper->Delete(); + ocActor->Delete(); + contour->Delete(); + geom3->Delete(); + contMapper->Delete(); + contActor->Delete(); + ren->SetBackground(1,1,1); + renWin->SetSize(300,300); + renWin->Render(); + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Cleanup + geom->Delete(); + shMapper->Delete(); + shActor->Delete(); + ren->Delete(); + renWin->Delete(); + iren->Delete(); + reader->Delete(); + shrink->Delete(); + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/TestSortDataArray.cxx b/Graphics/Testing/Cxx/TestSortDataArray.cxx new file mode 100644 index 0000000..6234817 --- /dev/null +++ b/Graphics/Testing/Cxx/TestSortDataArray.cxx @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestSortDataArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ +// -*- c++ -*- ******************************************************* + +#include "vtkSortDataArray.h" +#include "vtkIntArray.h" +#include "vtkMath.h" +#include "vtkTimerLog.h" + +#define ARRAY_SIZE (2*1024*1024) +// #define ARRAY_SIZE 128 + +int TestSortDataArray(int, char *[]) +{ + vtkIdType i; + vtkTimerLog *timer = vtkTimerLog::New(); + + cout << "Building array" << endl; + vtkIntArray *keys = vtkIntArray::New(); + keys->SetNumberOfComponents(1); + keys->SetNumberOfTuples(ARRAY_SIZE); + for (i = 0; i < ARRAY_SIZE; i++) + { + keys->SetComponent(i, 0, (int)vtkMath::Random(0, ARRAY_SIZE*4)); + } + + cout << "Sorting array" << endl; + timer->StartTimer(); + vtkSortDataArray::Sort(keys); + timer->StopTimer(); + + cout << "Time to sort array: " << timer->GetElapsedTime() << " sec" << endl; + + for (i = 0; i < ARRAY_SIZE-1; i++) + { + if (keys->GetComponent(i, 0) > keys->GetComponent(i+1, 0)) + { + cout << "Array not properly sorted!" << endl; + break; + } + } + cout << "Array consistency check finished\n" << endl; + + cout << "Sorting sorted array" << endl; + timer->StartTimer(); + vtkSortDataArray::Sort(keys); + timer->StopTimer(); + + cout << "Time to sort array: " << timer->GetElapsedTime() << " sec" << endl; + + for (i = 0; i < ARRAY_SIZE-1; i++) + { + if (keys->GetComponent(i, 0) > keys->GetComponent(i+1, 0)) + { + cout << "Array not properly sorted!" << endl; + break; + } + } + cout << "Array consistency check finished\n" << endl; + + cout << "Building key/value arrays\n" << endl; + vtkIntArray *values = vtkIntArray::New(); + values->SetNumberOfComponents(2); + values->SetNumberOfTuples(ARRAY_SIZE); + for (i = 0; i < ARRAY_SIZE; i++) + { + keys->SetComponent(i, 0, (int)vtkMath::Random(0, ARRAY_SIZE*4)); + values->SetComponent(i, 0, i); + values->SetComponent(i, 1, (int)vtkMath::Random(0, ARRAY_SIZE*4)); + } + vtkIntArray *saveKeys = vtkIntArray::New(); + saveKeys->DeepCopy(keys); + vtkIntArray *saveValues = vtkIntArray::New(); + saveValues->DeepCopy(values); + + cout << "Sorting arrays" << endl; + timer->StartTimer(); + vtkSortDataArray::Sort(keys, values); + timer->StopTimer(); + + cout << "Time to sort array: " << timer->GetElapsedTime() << " sec" << endl; + + for (i = 0; i < ARRAY_SIZE-1; i++) + { + int lookup = (int)values->GetComponent(i, 0); + if (keys->GetComponent(i, 0) > keys->GetComponent(i+1, 0)) + { + cout << "Array not properly sorted!" << endl; + break; + } + if (keys->GetComponent(i, 0) != saveKeys->GetComponent(lookup, 0)) + { + cout << "Values array not consistent with keys array!" << endl; + break; + } + if (values->GetComponent(i, 1) != saveValues->GetComponent(lookup, 1)) + { + cout << "Values array not consistent with keys array!" << endl; + break; + } + } + cout << "Array consistency check finished\n" << endl; + + cout << "Sorting sorted arrays" << endl; + timer->StartTimer(); + vtkSortDataArray::Sort(keys, values); + timer->StopTimer(); + + cout << "Time to sort array: " << timer->GetElapsedTime() << " sec" << endl; + + for (i = 0; i < ARRAY_SIZE-1; i++) + { + int lookup = (int)values->GetComponent(i, 0); + if (keys->GetComponent(i, 0) > keys->GetComponent(i+1, 0)) + { + cout << "Array not properly sorted!" << endl; + break; + } + if (keys->GetComponent(i, 0) != saveKeys->GetComponent(lookup, 0)) + { + cout << "Values array not consistent with keys array!" << endl; + break; + } + if (values->GetComponent(i, 1) != saveValues->GetComponent(lookup, 1)) + { + cout << "Values array not consistent with keys array!" << endl; + break; + } + } + cout << "Array consistency check finished\n" << endl; + + timer->Delete(); + keys->Delete(); + values->Delete(); + saveKeys->Delete(); + saveValues->Delete(); + + return 0; +} diff --git a/Graphics/Testing/Cxx/expCos.cxx b/Graphics/Testing/Cxx/expCos.cxx new file mode 100644 index 0000000..68593ef --- /dev/null +++ b/Graphics/Testing/Cxx/expCos.cxx @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: expCos.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// +// Brute force computation of Bessel functions. Might be better to create a +// filter (or source) object. Might also consider vtkSampleFunction. + +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkDataSetMapper.h" +#include "vtkDebugLeaks.h" +#include "vtkFloatArray.h" +#include "vtkPlaneSource.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkTransformPolyDataFilter.h" +#include "vtkWarpScalar.h" + +int expCos( int argc, char *argv[] ) +{ + int i, numPts; + double x[3]; + double r, deriv; + + vtkRenderer *ren = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // create plane to warp + vtkPlaneSource *plane = vtkPlaneSource::New(); + plane->SetResolution (300,300); + + vtkTransform *transform = vtkTransform::New(); + transform->Scale(10.0,10.0,1.0); + + vtkTransformPolyDataFilter *transF = vtkTransformPolyDataFilter::New(); + transF->SetInputConnection(plane->GetOutputPort()); + transF->SetTransform(transform); + transF->Update(); + + // compute Bessel function and derivatives. This portion could be + // encapsulated into source or filter object. + // + vtkPolyData *input = transF->GetOutput(); + numPts = input->GetNumberOfPoints(); + + vtkPoints *newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + + vtkFloatArray *derivs = vtkFloatArray::New(); + derivs->SetNumberOfTuples(numPts); + + vtkPolyData *bessel = vtkPolyData::New(); + bessel->CopyStructure(input); + bessel->SetPoints(newPts); + bessel->GetPointData()->SetScalars(derivs); + + for (i=0; iGetPoint(i,x); + r = sqrt((double)x[0]*x[0] + x[1]*x[1]); + x[2] = exp(-r) * cos (10.0*r); + newPts->SetPoint(i,x); + deriv = -exp(-r) * (cos(10.0*r) + 10.0*sin(10.0*r)); + derivs->SetValue(i,deriv); + } + newPts->Delete(); //reference counting - it's ok + derivs->Delete(); + + // warp plane + vtkWarpScalar *warp = vtkWarpScalar::New(); + warp->SetInput(bessel); + warp->XYPlaneOn(); + warp->SetScaleFactor(0.5); + + // mapper and actor + vtkDataSetMapper *mapper = vtkDataSetMapper::New(); + mapper->SetInputConnection(warp->GetOutputPort()); + double tmp[2]; + bessel->GetScalarRange(tmp); + mapper->SetScalarRange(tmp[0],tmp[1]); + + vtkActor *carpet = vtkActor::New(); + carpet->SetMapper(mapper); + + // assign our actor to the renderer + ren->AddActor(carpet); + ren->SetBackground(1,1,1); + renWin->SetSize(300,300); + + // draw the resulting scene + ren->ResetCamera(); + ren->GetActiveCamera()->Zoom(1.4); + ren->GetActiveCamera()->Elevation(-55); + ren->GetActiveCamera()->Azimuth(25); + ren->ResetCameraClippingRange(); + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + ren->Delete(); + renWin->Delete(); + iren->Delete(); + plane->Delete(); + transform->Delete(); + transF->Delete(); + bessel->Delete(); + warp->Delete(); + mapper->Delete(); + carpet->Delete(); + + return !retVal; +} diff --git a/Graphics/Testing/Cxx/vtkTestHierarchicalDataReader.cxx b/Graphics/Testing/Cxx/vtkTestHierarchicalDataReader.cxx new file mode 100644 index 0000000..bcd0164 --- /dev/null +++ b/Graphics/Testing/Cxx/vtkTestHierarchicalDataReader.cxx @@ -0,0 +1,360 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkTestHierarchicalDataReader.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTestHierarchicalDataReader.h" + +#include "vtkAMRBox.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkExecutive.h" +#include "vtkHierarchicalBoxDataSet.h" +#include "vtkHierarchicalDataInformation.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationDoubleVectorKey.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkUniformGrid.h" +#include "vtkXMLImageDataReader.h" + +vtkCxxRevisionMacro(vtkTestHierarchicalDataReader, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkTestHierarchicalDataReader); + +vtkTestHierarchicalDataReader::vtkTestHierarchicalDataReader() +{ + this->FileName = 0; + + this->SetNumberOfInputPorts(0); +} + +vtkTestHierarchicalDataReader::~vtkTestHierarchicalDataReader() +{ + this->SetFileName(0); +} + +// Provide information about the dataset: +// * Number of levels +// * Number of boxes / level +// * AMRBox (extent) of each box +int vtkTestHierarchicalDataReader::RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if (!this->Superclass::RequestInformation(request, inputVector, outputVector)) + { + return 0; + } + + const int numLevels = 3; + int numBlocks[numLevels] = { 1, 1, 14 }; + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::New(); + compInfo->SetNumberOfLevels(numLevels); + int i; + for (i=0; iSetNumberOfDataSets(i, numBlocks[i]); + } + + vtkInformation* info = outputVector->GetInformationObject(0); + info->Set( + vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION(), compInfo); + + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1); + + vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New(); + + for (i=0; i<16; i++) + { + // Here we load the 16 separate files (each containing + // an image dataset -uniform rectilinear grid-) + char* fstr = this->GetBlockFileName(i); + reader->SetFileName(fstr); + + reader->UpdateInformation(); + + delete[] fstr; + + // Each sub-dataset in a vtkHierarchicalBoxDataSet has an associated + // vtkAMRBox. This is similar to extent but is stored externally + // since it is possible to have sub-dataset nodes with NULL + // vtkUniformGrid pointers. + vtkAMRBox box; + + // This is a hack (do not do this at home). Normally, the + // region (box) information should be available in the file. + // In this case, since there is no such information available, + // we obtain it by looking at each image data's extent. + // -- begin hack + int extent[6]; + double spacing[3]; + double origin[3]; + + vtkInformation* outInfo = reader->GetExecutive()->GetOutputInformation(0); + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + outInfo->Get(vtkDataObject::SPACING(), spacing); + outInfo->Get(vtkDataObject::ORIGIN(), origin); + + int j; + for (j=0; j<3; j++) + { + int num = static_cast(floor(origin[j]/spacing[j] + 0.5)); + box.LoCorner[j] = num + extent[2*j]; + box.HiCorner[j] = num + extent[2*j+1] - 1; + } + + int level; + int dsindex; + + this->GetBlockIdx(i, level, dsindex); + + vtkInformation* subInfo = compInfo->GetInformation(level, dsindex); + subInfo->Set(vtkHierarchicalBoxDataSet::BOX(), + box.LoCorner[0], box.LoCorner[1], box.LoCorner[2], + box.HiCorner[0], box.HiCorner[1], box.HiCorner[2]); + } + + reader->Delete(); + compInfo->Delete(); + + return 1; +} + +int vtkTestHierarchicalDataReader::SetUpdateBlocks( + vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + + if (!info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) || + !info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())) + { + vtkErrorMacro("Expected information not found. " + "Cannot provide update extent."); + return 0; + } + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::SafeDownCast( + info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + + if (!compInfo) + { + vtkErrorMacro("Expected information not found. " + "Cannot provide update extent."); + return 0; + } + + vtkHierarchicalDataInformation* updateInfo = + vtkHierarchicalDataInformation::New(); + info->Set( + vtkCompositeDataPipeline::UPDATE_BLOCKS(), updateInfo); + updateInfo->SetNumberOfLevels(compInfo->GetNumberOfLevels()); + + unsigned int updatePiece = static_cast( + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + unsigned int updateNumPieces = static_cast( + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + + unsigned int numLevels = updateInfo->GetNumberOfLevels(); + for (unsigned int j=0; jSetNumberOfDataSets(j, compInfo->GetNumberOfDataSets(j)); + unsigned int numBlocks = updateInfo->GetNumberOfDataSets(j); + unsigned int numBlocksPerPiece = 1; + if (updateNumPieces < numBlocks) + { + numBlocksPerPiece = numBlocks / updateNumPieces; + } + unsigned int minBlock = numBlocksPerPiece*updatePiece; + unsigned int maxBlock = numBlocksPerPiece*(updatePiece+1); + if (updatePiece == updateNumPieces - 1) + { + maxBlock = numBlocks; + } + for (unsigned int i=minBlock; iGetInformation(j, i); + blockInfo->Set(vtkCompositeDataPipeline::MARKED_FOR_UPDATE(), 1); + } + } + updateInfo->Delete(); + return 1; +} + +int vtkTestHierarchicalDataReader::RequestData( + vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector) +{ + int i; + + if (!this->FileName) + { + return 0; + } + + vtkInformation* info = outputVector->GetInformationObject(0); + + vtkDataObject* doOutput = + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkHierarchicalBoxDataSet* hb = + vtkHierarchicalBoxDataSet::SafeDownCast(doOutput); + if (!hb) + { + return 0; + } + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::SafeDownCast( + info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + + hb->SetHierarchicalDataInformation(compInfo); + + // Since there is no AMR reader avaible yet, we will load a + // collection of VTK files and create our own vtkHierarchicalBoxDataSet. + // To create the files, I loaded a Chombo file with an experimental + // Chombo reader and wrote the datasets separately. + vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New(); + + for (i=0; i<16; i++) + { + // Here we load the 16 separate files (each containing + // an image dataset -uniform rectilinear grid-) + char* fstr = this->GetBlockFileName(i); + reader->SetFileName(fstr); + + // We have to update since we are working without a VTK pipeline. + // This will read the file and the output of the reader will be + // a valid image data. + reader->Update(); + delete[] fstr; + + // We now create a vtkUniformGrid. This is essentially a simple + // vtkImageData (not a sub-class though) with blanking. Since + // VTK readers do not know vtkUniformGrid, we simply create our + // own by copying from the image data. + vtkUniformGrid* ug = vtkUniformGrid::New(); + ug->ShallowCopy(reader->GetOutput()); + + int level; + int dsindex; + + this->GetBlockIdx(i, level, dsindex); + + // Given the level, index and box, add the sub-dataset to + // hierarchical dataset. + hb->SetDataSet(level, dsindex, ug); + + ug->Delete(); + } + reader->Delete(); + + // I hard-coded the refinement ratios. These should normally + // be available in the file. + hb->SetRefinementRatio(0, 2); + hb->SetRefinementRatio(1, 2); + + // This call generates visibility (blanking) arrays that mask + // regions of lower level datasets that overlap with regions + // of higher level datasets (it is assumed that, when available, + // higher level information should always be used instead of + // lower level information) + hb->GenerateVisibilityArrays(); + + return 1; +} + +void vtkTestHierarchicalDataReader::GetBlockIdx( + int blockId, int& level, int& dsindex) +{ + // Similarly, the level of each sub-dataset is normally + // available in the file. Since this is not the case, I + // hard-coded this into the example program. + // Level 0 = { 0 }, Level 1 = { 1 }, + // Level 2 = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } + if (blockId == 0) + { + level = 0; + dsindex = 0; + } + else if (blockId == 1) + { + level = 1; + dsindex = 0; + } + else + { + level = 2; + dsindex = blockId-2; + } +} + +char* vtkTestHierarchicalDataReader::GetBlockFileName(int blockId) +{ + size_t len = strlen(this->FileName); + size_t pos; + + // Search from the tail end of the filename until we + // find a '.' indicating an extension, or we find a + // path separator or the beginning of the string. + for (pos=len-1; pos!=0; --pos) + { + if (this->FileName[pos] == '.') + { + break; + } + + if (1==pos || this->FileName[pos] == '/') + { + // No extension on this->FileName; use the whole + // thing as the base name + pos= len; + break; + } + } + + char* fname = new char[pos+1]; + strncpy(fname, this->FileName, pos); + fname[pos] = '\0'; + + // Here we load the 16 separate files (each containing + // an image dataset -uniform rectilinear grid-) + char* fstr = new char [strlen(fname) + + strlen(".vti") + 10]; + sprintf(fstr,"%s_%i.vti",fname, blockId); + delete[] fname; + + return fstr; +} + +int vtkTestHierarchicalDataReader::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject"); + info->Set(vtkCompositeDataPipeline::COMPOSITE_DATA_TYPE_NAME(), + "vtkHierarchicalBoxDataSet"); + return 1; +} + +void vtkTestHierarchicalDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " << + (this->FileName ? this->FileName : "(none)") << "\n"; +} + diff --git a/Graphics/Testing/Cxx/vtkTestHierarchicalDataReader.h b/Graphics/Testing/Cxx/vtkTestHierarchicalDataReader.h new file mode 100644 index 0000000..2c1c466 --- /dev/null +++ b/Graphics/Testing/Cxx/vtkTestHierarchicalDataReader.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTestHierarchicalDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTestHierarchicalDataReader - reader used in testing +// .SECTION Description +// This reader uses the xml reader and puts together one AMR dataset +// using hard-coded values. + +#ifndef __vtkTestHierarchicalDataReader_h +#define __vtkTestHierarchicalDataReader_h + +#include "vtkHierarchicalDataSetAlgorithm.h" + +class vtkTestHierarchicalDataReader : public vtkHierarchicalDataSetAlgorithm +{ +public: + static vtkTestHierarchicalDataReader *New(); + vtkTypeRevisionMacro(vtkTestHierarchicalDataReader,vtkHierarchicalDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the file prefix. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkTestHierarchicalDataReader(); + ~vtkTestHierarchicalDataReader(); + + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int SetUpdateBlocks(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + char* GetBlockFileName(int blockId); + void GetBlockIdx(int blockId, int& level, int& dsindex); + + char* FileName; + + virtual int FillOutputPortInformation(int port, vtkInformation* info); + +private: + vtkTestHierarchicalDataReader(const vtkTestHierarchicalDataReader&); // Not implemented. + void operator=(const vtkTestHierarchicalDataReader&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/Testing/Python/CMakeLists.txt b/Graphics/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..a0127f2 --- /dev/null +++ b/Graphics/Testing/Python/CMakeLists.txt @@ -0,0 +1,261 @@ +INCLUDE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake) +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_PYTHON_EXE) + SET(tests) + + IF (VTK_DATA_ROOT) + # Older tests + FOREACH ( tfile + cameraWarpedCone + glyphComb + streamComb + tubeComb + streamSurface + streamSurface2 + ) + ADD_TEST(${tfile}Python-image ${VTK_PYTHON_EXE} + ${VTK_SOURCE_DIR}/Graphics/Testing/Python/${tfile}.py + -D ${VTK_DATA_ROOT} + -V Baseline/Graphics/${tfile}.png + -A ${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py + -A ${LIBRARY_OUTPUT_PATH}) + ENDFOREACH( tfile ) + + # Add test converted from Tcl + SET( tests ${tests} + AutomaticPlaneGeneration + Canny + CellDataToPointData + Delaunay2D + Delaunay2DAlpha + Delaunay2DTransform + Delaunay3D + Disk + EnSight6Elements + EnSight6OfficeBin + EnSightBlow1ASCII + EnSightBlow1Bin + EnSightBlow2ASCII + EnSightBlow2Bin + EnSightBlow3Bin + EnSightBlow4Bin + EnSightBlow5ASCII + EnSightCompound + EnSightGoldElements + EnSightIronProtASCII + EnSightIronProtBin + EnSightMandelbrot + EnSightOfficeASCII + EnSightOfficeBin + EnSightRectGridASCII + EnSightRectGridBin + EnSightSelectArrays + ExtractEdgesQuadraticCells + ExtractTensors + Hyper + HyperScalarBar + KlineBottle + LineIntersectQuadraticCells + MatrixToTransform + MultidimensionalSolution + NoLightGeneration + OBBCylinder + OSCone + PolyDataMapperAllPolygons + PolyDataMapperAllWireframe + QuadricDecimation + StreamPolyData + TenEllip + TestBandedContourFilter + TestBoxFunction + TestButtonSource + TestCameraInterpolator + TestCellDerivs + TestCurvatures + TestDiscreteMarchingCubes + TestGraphLayoutFilter + TestGridSynchronizedTemplates3D + TestImageMarchingCubes + TestMarchingSquares + TestMultiBlockStreamer + TestParametricFunctions + #TestPlatonicSolids -- uses eval to expand list + TestQuadricClustering + TestRectilinearGridToTetrahedra + TestRectilinearSynchronizedTemplates + TestRegularPolygonSource + TestRibbonAndTube + TestRotate + TestRuledSurface + TestRuledSurface2 + TestSpherePuzzle + TestSpherePuzzleArrows + TestSplineFilter + TestStructuredGrid + TestSynchronizedTemplates2D + TestSynchronizedTemplates3D + TestTransformInterpolator + TestTriangleFilter + TransformConcatenation + TransformCoverage + TransformPolyData + blankGrid + capCow + capSphere + clipArt + clipComb + clipImage + clipQuadraticCells + clipVolume + clipVolume2 + clipVolume3 + combStreamers + combStreamers2 + coneResolution + constrainedDelaunay + #contour2DAll -- complex use of string eval. + #contour3DAll -- complex use of string eval. + contourCells + contourQuadraticCells + contoursToSurface + cowHair + cowHair2 + createBFont + cursor3D + cutLoop + cylMap + cylindrical + dataSetSurfaceFilter + #deciPlane -- complex use of string eval + dicer + dispPlot + edgePoints + eleState + extractPolyData + extractRectGrid + extractUGrid + extractVectors + extrudeCopyCD + fieldToPolyData + fieldToRGrid + fieldToSGrid + fieldToUGrid + financialField + genHead + geomFilter + glyph2D + headBone + hull + iceCream + #imageMCAll -- sunstitution in method call. + mcubes + mergeFilter + motor + multipleComponentContour + multipleIso + nacaBinary + officeStreamPoints + polyConn + probeComb + progGlyphs + progGlyphsBySource + #quadricCut -- switch case + rectGrid + recursiveDC + reverseNormals + scalarColors + scalarConn + schwarz + shepards + #skinOrder -- sources a script. + smoothCyl + smoothCyl2 + smoothMeshOnMesh + socbal + #spatialRepAll -- complex string substitutions + spherical + splitVectors + stereoDresdenMace + streamTracer + stripF + subDivideTetra + subPixelPositionMin + subdividePointData + #sync3dAll -- substitution in method call. + teapotHulls + testDataSetTriangleFilter + testDataSetTriangleFilter2 + testHexaPenta + testReflect + textureThreshold + triangularTCoords + triangularTexture + warplens + ) + + # Newer tests using vtk.test.Testing. + FOREACH ( tfile + TestTensorGlyph + TestTextureGlyph + ) + ADD_TEST(${tfile}Python-image ${VTK_PYTHON_EXE} + ${VTK_SOURCE_DIR}/Graphics/Testing/Python/${tfile}.py + -D ${VTK_DATA_ROOT} + -B ${VTK_DATA_ROOT}/Baseline/Graphics) + ENDFOREACH( tfile ) + ELSE (VTK_DATA_ROOT) + # Add test converted from Tcl + SET(tests ${tests} + capSphere + CellDataToPointData + clipVolume + clipVolume2 + clipVolume3 + coneResolution + constrainedDelaunay + contourCells + contoursToSurface + cutLoop + Delaunay2D + Delaunay2DAlpha + Delaunay2DTransform + Disk + extractPolyData + glyph2D + Hyper + KlineBottle + MatrixToTransform + OBBCylinder + progGlyphs + progGlyphsBySource + quadricCut + scalarConn + schwarz + shepards + smoothCyl + smoothCyl2 + subdividePointData + subDivideTetra + TestBoxFunction + TestGraphLayoutFilter + testQuadricDecimation + triangularTCoords + triangularTexture + warplens + TestGraphLayoutFilter + TransformConcatenation + TransformCoverage + TransformPolyData + ) + ENDIF (VTK_DATA_ROOT) + + CONVERT_TCL_TEST_TO_PY ( + tests + Graphics) + ENDIF (VTK_PYTHON_EXE) +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + diff --git a/Graphics/Testing/Python/TestTensorGlyph.py b/Graphics/Testing/Python/TestTensorGlyph.py new file mode 100644 index 0000000..954bf6a --- /dev/null +++ b/Graphics/Testing/Python/TestTensorGlyph.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +# Run this test like so: +# vtkpython TestTensorGlyph.py -D $VTK_DATA_ROOT \ +# -B $VTK_DATA_ROOT/Baseline/Graphics/ + +import os +import vtk +from vtk.test import Testing + +class SimpleGlyph: + """A simple class used to test vtkTensorGlyph.""" + def __init__(self, reader): + self.reader = reader + sg = self.src_glyph = vtk.vtkSphereSource() + sg.SetRadius(0.5) + sg.SetCenter(0.5, 0.0, 0.0) + g = self.glyph = vtk.vtkTensorGlyph() + g.SetInputConnection(self.reader.GetOutputPort()) + g.SetSource(self.src_glyph.GetOutput()) + g.SetScaleFactor(0.25) + + # The normals are needed to generate the right colors and if + # not used some of the glyphs are black. + self.normals = vtk.vtkPolyDataNormals() + self.normals.SetInputConnection(g.GetOutputPort()) + self.map = vtk.vtkPolyDataMapper() + self.map.SetInputConnection(self.normals.GetOutputPort()) + self.act = vtk.vtkActor() + self.act.SetMapper(self.map) + + # An outline. + self.of = vtk.vtkOutlineFilter() + self.of.SetInputConnection(self.reader.GetOutputPort()) + self.out_map = vtk.vtkPolyDataMapper() + self.out_map.SetInputConnection(self.of.GetOutputPort()) + self.out_act = vtk.vtkActor() + self.out_act.SetMapper(self.out_map) + + def GetActors(self): + return self.act, self.out_act + + def Update(self): + self.glyph.Update() + s = self.glyph.GetOutput().GetPointData().GetScalars() + if s: + self.map.SetScalarRange(s.GetRange()) + + def SetPosition(self, pos): + self.act.SetPosition(pos) + self.out_act.SetPosition(pos) + + +class TestTensorGlyph(Testing.vtkTest): + def testGlyphs(self): + "Test if the glyphs are created nicely." + reader = vtk.vtkDataSetReader() + data_file = os.path.join(Testing.VTK_DATA_ROOT, "Data", + "tensors.vtk") + reader.SetFileName(data_file) + + g1 = SimpleGlyph(reader) + g1.glyph.ColorGlyphsOff() + g1.Update() + + g2 = SimpleGlyph(reader) + g2.glyph.ExtractEigenvaluesOff() + g2.Update() + g2.SetPosition((2.0, 0.0, 0.0)) + + g3 = SimpleGlyph(reader) + g3.glyph.SetColorModeToEigenvalues() + g3.glyph.ThreeGlyphsOn() + g3.Update() + g3.SetPosition((0.0, 2.0, 0.0)) + + g4 = SimpleGlyph(reader) + g4.glyph.SetColorModeToEigenvalues() + g4.glyph.ThreeGlyphsOn() + g4.glyph.SymmetricOn() + g4.Update() + g4.SetPosition((2.0, 2.0, 0.0)) + + ren = vtk.vtkRenderer() + for i in (g1, g2, g3, g4): + for j in i.GetActors(): + ren.AddActor(j) + + ren.ResetCamera(); + cam = ren.GetActiveCamera() + cam.Azimuth(-20) + cam.Elevation(20) + cam.Zoom(1.5) + + ren.SetBackground(0.5, 0.5, 0.5) + renWin = vtk.vtkRenderWindow() + renWin.AddRenderer(ren) + renWin.Render() + + img_file = "TestTensorGlyph.png" + Testing.compareImage(renWin, Testing.getAbsImagePath(img_file)) + Testing.interact() + + def testParse(self): + "Test if vtkTensorGlyph is parseable" + tg = vtk.vtkTensorGlyph() + self._testParse(tg) + + def testGetSet(self): + "Testing Get/Set methods of vtkTensorGlyph" + tg = vtk.vtkTensorGlyph() + self._testGetSet(tg) + + def testParse(self): + "Testing Boolean methods of vtkTensorGlyph" + tg = vtk.vtkTensorGlyph() + self._testBoolean(tg) + + +if __name__ == "__main__": + Testing.main([(TestTensorGlyph, 'test')]) diff --git a/Graphics/Testing/Python/TestTextureGlyph.py b/Graphics/Testing/Python/TestTextureGlyph.py new file mode 100644 index 0000000..746ce30 --- /dev/null +++ b/Graphics/Testing/Python/TestTextureGlyph.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python + +# Run this test like so: +# $ vtkpython TestTextureGlyph.py -D $VTK_DATA_ROOT \ +# -B $VTK_DATA_ROOT/Baseline/Graphics/ +# +# $ vtkpython TestTextureGlyph.py --help +# provides more details on other options. + +import os +import os.path +import vtk +from vtk.test import Testing + +class TestTextureGlyph(Testing.vtkTest): + def testGlyphs(self): + """Test if texturing of the glyphs works correctly.""" + # The Glyph + cs = vtk.vtkCubeSource() + cs.SetXLength(2.0); cs.SetYLength(1.0); cs.SetZLength(0.5) + + # Create input point data. + pts = vtk.vtkPoints() + pts.InsertPoint(0, (1,1,1)) + pts.InsertPoint(1, (0,0,0)) + pts.InsertPoint(2, (-1,-1,-1)) + polys = vtk.vtkCellArray() + polys.InsertNextCell(1) + polys.InsertCellPoint(0) + polys.InsertNextCell(1) + polys.InsertCellPoint(1) + polys.InsertNextCell(1) + polys.InsertCellPoint(2) + pd = vtk.vtkPolyData() + pd.SetPoints(pts) + pd.SetPolys(polys) + + # Orient the glyphs as per vectors. + vec = vtk.vtkFloatArray() + vec.SetNumberOfComponents(3) + vec.InsertTuple3(0, 1, 0, 0) + vec.InsertTuple3(1, 0, 1, 0) + vec.InsertTuple3(2, 0, 0, 1) + pd.GetPointData().SetVectors(vec) + + # The glyph filter. + g = vtk.vtkGlyph3D() + g.SetScaleModeToDataScalingOff() + g.SetVectorModeToUseVector() + g.SetInput(pd) + g.SetSource(cs.GetOutput()) + + m = vtk.vtkPolyDataMapper() + m.SetInputConnection(g.GetOutputPort()) + a = vtk.vtkActor() + a.SetMapper(m) + + # The texture. + img_file = os.path.join(Testing.VTK_DATA_ROOT, "Data", + "masonry.bmp") + img_r = vtk.vtkBMPReader() + img_r.SetFileName(img_file) + t = vtk.vtkTexture() + t.SetInputConnection(img_r.GetOutputPort()) + t.InterpolateOn() + a.SetTexture(t) + + # Renderer, RenderWindow etc. + ren = vtk.vtkRenderer() + ren.SetBackground(0.5, 0.5, 0.5) + ren.AddActor(a) + + ren.ResetCamera(); + cam = ren.GetActiveCamera() + cam.Azimuth(-90) + cam.Zoom(1.4) + + renWin = vtk.vtkRenderWindow() + renWin.AddRenderer(ren) + rwi = vtk.vtkRenderWindowInteractor() + rwi.SetRenderWindow(renWin) + rwi.Initialize() + rwi.Render() + + # Compare the images and test. + img_file = "TestTextureGlyph.png" + Testing.compareImage(renWin, Testing.getAbsImagePath(img_file)) + # Interact if necessary. + if Testing.isInteractive(): + rwi.Start() + +if __name__ == "__main__": + Testing.main([(TestTextureGlyph, 'test')]) + diff --git a/Graphics/Testing/Python/cameraWarpedCone.py b/Graphics/Testing/Python/cameraWarpedCone.py new file mode 100644 index 0000000..8dbce75 --- /dev/null +++ b/Graphics/Testing/Python/cameraWarpedCone.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +import sys + +for i in range(0, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +from vtk.util.misc import vtkRegressionTestImage + +# create a rendering window and renderer +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer(ren) +renWin.SetSize(300,300) + +# create an actor and give it cone geometry +cone = vtk.vtkConeSource() +cone.SetResolution(8) +coneMapper = vtk.vtkPolyDataMapper() +coneMapper.SetInputConnection(cone.GetOutputPort()) +coneActor = vtk.vtkActor() +coneActor.SetMapper(coneMapper) + +# create a transform and distort the camera using it +mat = vtk.vtkMatrix4x4() +mat.SetElement(0,0,0.5) +mat.SetElement(0,1,0) +mat.SetElement(0,2,0) +mat.SetElement(0,3,0) +mat.SetElement(1,0,0) +mat.SetElement(1,1,1) +mat.SetElement(1,2,0) +mat.SetElement(1,3,0) +mat.SetElement(2,0,0) +mat.SetElement(2,1,0) +mat.SetElement(2,2,1) +mat.SetElement(2,3,0) +mat.SetElement(3,0,0) +mat.SetElement(3,1,0) +mat.SetElement(3,2,0) +mat.SetElement(3,3,1) + +trans = vtk.vtkTransform() +trans.SetMatrix(mat) + +# assign our actor to the renderer +ren.AddActor(coneActor) + +ren.ResetCamera(); +ren.GetActiveCamera().SetUserTransform(trans); + +renWin.Render() +retVal = vtkRegressionTestImage(renWin) + +sys.exit( not retVal ) diff --git a/Graphics/Testing/Python/glyphComb.py b/Graphics/Testing/Python/glyphComb.py new file mode 100644 index 0000000..89b030a --- /dev/null +++ b/Graphics/Testing/Python/glyphComb.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import sys + +for i in range(0, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +from vtk.util.misc import vtkRegressionTestImage, vtkGetDataRoot + +# create planes +# Create the RenderWindow, Renderer +# +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren ) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# create pipeline +# +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName( vtkGetDataRoot() + '/Data/combxyz.bin' ) +pl3d.SetQFileName( vtkGetDataRoot() + '/Data/combq.bin' ) +pl3d.SetScalarFunctionNumber( 100 ) +pl3d.SetVectorFunctionNumber( 202 ) +pl3d.Update() + +eg = vtk.vtkExtractGrid() +eg.SetInputConnection(pl3d.GetOutputPort()) +eg.SetSampleRate(4,4,4) + +gs = vtk.vtkGlyphSource2D() +gs.SetGlyphTypeToThickArrow() +gs.SetScale( 1 ) +gs.FilledOff() +gs.CrossOff() + +glyph = vtk.vtkGlyph3D() +glyph.SetInputConnection(eg.GetOutputPort()) +glyph.SetSource(gs.GetOutput()) +glyph.SetScaleFactor( 0.75 ) + +mapper = vtk.vtkPolyDataMapper() +mapper.SetInputConnection(glyph.GetOutputPort()) + +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +ren.AddActor(actor) + +cam=ren.GetActiveCamera() +cam.SetClippingRange( 3.95297, 50 ) +cam.SetFocalPoint( 8.88908, 0.595038, 29.3342 ) +cam.SetPosition( -12.3332, 31.7479, 41.2387 ) +cam.SetViewUp( 0.060772, -0.319905, 0.945498 ) + +renWin.Render() +retVal = vtkRegressionTestImage(renWin) +sys.exit( not retVal ) diff --git a/Graphics/Testing/Python/meshQuality.py b/Graphics/Testing/Python/meshQuality.py new file mode 100644 index 0000000..32c245f --- /dev/null +++ b/Graphics/Testing/Python/meshQuality.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +import sys + +for i in range(0, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +from vtk.util.misc import vtkGetDataRoot + +filename = vtkGetDataRoot() + '/Data/tetraMesh.vtk' + +reader = vtk.vtkUnstructuredGridReader() +reader.SetFileName(filename) + +a = vtk.vtkMeshQuality() +a.SetInputConnection(reader.GetOutputPort()) +a.VolumeOn() +a.RatioOn() +a.Update() + + +mesh = a.GetOutput().GetFieldData().GetScalars() + +for i in range(mesh.GetNumberOfTuples()): + print mesh.GetTuple2(i) + +sys.exit(0) diff --git a/Graphics/Testing/Python/streamComb.py b/Graphics/Testing/Python/streamComb.py new file mode 100644 index 0000000..960eb5c --- /dev/null +++ b/Graphics/Testing/Python/streamComb.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +import sys + +for i in range(0, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +from vtk.util.misc import vtkRegressionTestImage, vtkGetDataRoot + +# create planes +# Create the RenderWindow, Renderer +# +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren ) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# create pipeline +# +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName( vtkGetDataRoot() + '/Data/combxyz.bin' ) +pl3d.SetQFileName( vtkGetDataRoot() + '/Data/combq.bin' ) +pl3d.SetScalarFunctionNumber( 100 ) +pl3d.SetVectorFunctionNumber( 202 ) +pl3d.Update() + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) + +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +seeds = vtk.vtkLineSource() +seeds.SetPoint1(15, -5, 32) +seeds.SetPoint2(15, 5, 32) +seeds.SetResolution(10) + +sl = vtk.vtkStreamLine() +sl.SetInputConnection(pl3d.GetOutputPort()) +sl.SetSource(seeds.GetOutput()) +sl.SetMaximumPropagationTime(0.1) +sl.SetIntegrationStepLength(0.1) +sl.SetIntegrationDirectionToIntegrateBothDirections() +sl.SetStepLength(0.001) + +mapper = vtk.vtkPolyDataMapper() +mapper.SetInputConnection(sl.GetOutputPort()) + +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +mmapper = vtk.vtkPolyDataMapper() +mmapper.SetInputConnection(seeds.GetOutputPort()) +mactor = vtk.vtkActor() +mactor.SetMapper(mmapper) +ren.AddActor(mactor) + +ren.AddActor(actor) +ren.AddActor(outlineActor) + +cam=ren.GetActiveCamera() +cam.SetClippingRange( 3.95297, 50 ) +cam.SetFocalPoint( 8.88908, 0.595038, 29.3342 ) +cam.SetPosition( -12.3332, 31.7479, 41.2387 ) +cam.SetViewUp( 0.060772, -0.319905, 0.945498 ) + +renWin.Render() +retVal = vtkRegressionTestImage(renWin) +sys.exit( not retVal ) + diff --git a/Graphics/Testing/Python/streamSurface.py b/Graphics/Testing/Python/streamSurface.py new file mode 100644 index 0000000..29daa19 --- /dev/null +++ b/Graphics/Testing/Python/streamSurface.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python + +import sys + +for i in range(0, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +from vtk.util.misc import vtkRegressionTestImage, vtkGetDataRoot + +# create planes +# Create the RenderWindow, Renderer +# +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren ) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# create pipeline +# +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName( vtkGetDataRoot() + '/Data/combxyz.bin' ) +pl3d.SetQFileName( vtkGetDataRoot() + '/Data/combq.bin' ) +pl3d.SetScalarFunctionNumber( 100 ) +pl3d.SetVectorFunctionNumber( 202 ) +pl3d.Update() + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) + +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +seeds = vtk.vtkLineSource() +seeds.SetPoint1(15, -5, 32) +seeds.SetPoint2(15, 5, 32) +seeds.SetResolution(10) + +integ = vtk.vtkRungeKutta4() + +sl = vtk.vtkStreamLine() +sl.SetIntegrator(integ) +sl.SetInputConnection(pl3d.GetOutputPort()) +sl.SetSource(seeds.GetOutput()) +sl.SetMaximumPropagationTime(0.1) +sl.SetIntegrationStepLength(0.1) +sl.SetIntegrationDirectionToBackward() +sl.SetStepLength(0.001) + +scalarSurface = vtk.vtkRuledSurfaceFilter () +scalarSurface.SetInputConnection(sl.GetOutputPort()) +scalarSurface.SetOffset(0) +scalarSurface.SetOnRatio(2) +scalarSurface.PassLinesOn() +scalarSurface.SetRuledModeToPointWalk() +scalarSurface.SetDistanceFactor(30) + +mapper = vtk.vtkPolyDataMapper() +mapper.SetInputConnection(scalarSurface.GetOutputPort()) + +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +mmapper = vtk.vtkPolyDataMapper() +mmapper.SetInputConnection(seeds.GetOutputPort()) +mactor = vtk.vtkActor() +mactor.SetMapper(mmapper) +ren.AddActor(mactor) + +ren.AddActor(actor) +ren.AddActor(outlineActor) + +cam=ren.GetActiveCamera() +cam.SetClippingRange( 3.95297, 50 ) +cam.SetFocalPoint( 8.88908, 0.595038, 29.3342 ) +cam.SetPosition( -12.3332, 31.7479, 41.2387 ) +cam.SetViewUp( 0.060772, -0.319905, 0.945498 ) + +renWin.Render() +retVal = vtkRegressionTestImage(renWin) +sys.exit( not retVal ) + diff --git a/Graphics/Testing/Python/streamSurface2.py b/Graphics/Testing/Python/streamSurface2.py new file mode 100644 index 0000000..b431f48 --- /dev/null +++ b/Graphics/Testing/Python/streamSurface2.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +import sys + +for i in range(0, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +from vtk.util.misc import vtkRegressionTestImage, vtkGetDataRoot + +# create planes +# Create the RenderWindow, Renderer +# +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren ) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# create pipeline +# +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName( vtkGetDataRoot() + '/Data/combxyz.bin' ) +pl3d.SetQFileName( vtkGetDataRoot() + '/Data/combq.bin' ) +pl3d.SetScalarFunctionNumber( 100 ) +pl3d.SetVectorFunctionNumber( 202 ) +pl3d.Update() + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) + +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +seeds = vtk.vtkLineSource() +seeds.SetPoint1(15, -5, 32) +seeds.SetPoint2(15, 5, 32) +seeds.SetResolution(10) + +integ = vtk.vtkRungeKutta4() + +sl = vtk.vtkStreamLine() +sl.SetIntegrator(integ) +sl.SetInputConnection(pl3d.GetOutputPort()) +sl.SetSource(seeds.GetOutput()) +sl.SetMaximumPropagationTime(0.1) +sl.SetIntegrationStepLength(0.1) +sl.SetIntegrationDirectionToBackward() +sl.SetStepLength(0.001) + +scalarSurface = vtk.vtkRuledSurfaceFilter () +scalarSurface.SetInputConnection(sl.GetOutputPort()) +scalarSurface.SetOffset(0) +scalarSurface.SetOnRatio(2) +scalarSurface.PassLinesOn() +scalarSurface.SetRuledModeToResample() +scalarSurface.SetResolution(100,1) +scalarSurface.SetDistanceFactor(30) + +mapper = vtk.vtkPolyDataMapper() +mapper.SetInputConnection(scalarSurface.GetOutputPort()) + +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +mmapper = vtk.vtkPolyDataMapper() +mmapper.SetInputConnection(seeds.GetOutputPort()) +mactor = vtk.vtkActor() +mactor.SetMapper(mmapper) +ren.AddActor(mactor) + +ren.AddActor(actor) +ren.AddActor(outlineActor) + +cam=ren.GetActiveCamera() +cam.SetClippingRange( 3.95297, 50 ) +cam.SetFocalPoint( 8.88908, 0.595038, 29.3342 ) +cam.SetPosition( -12.3332, 31.7479, 41.2387 ) +cam.SetViewUp( 0.060772, -0.319905, 0.945498 ) + +renWin.Render() +retVal = vtkRegressionTestImage(renWin) +sys.exit( not retVal ) + diff --git a/Graphics/Testing/Python/tubeComb.py b/Graphics/Testing/Python/tubeComb.py new file mode 100644 index 0000000..98c9e42 --- /dev/null +++ b/Graphics/Testing/Python/tubeComb.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +import sys + +for i in range(0, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +from vtk.util.misc import vtkRegressionTestImage, vtkGetDataRoot + +# create planes +# Create the RenderWindow, Renderer +# +ren = vtk.vtkRenderer() +renWin = vtk.vtkRenderWindow() +renWin.AddRenderer( ren ) + +iren = vtk.vtkRenderWindowInteractor() +iren.SetRenderWindow(renWin) + +# create pipeline +# +pl3d = vtk.vtkPLOT3DReader() +pl3d.SetXYZFileName( vtkGetDataRoot() + '/Data/combxyz.bin' ) +pl3d.SetQFileName( vtkGetDataRoot() + '/Data/combq.bin' ) +pl3d.SetScalarFunctionNumber( 100 ) +pl3d.SetVectorFunctionNumber( 202 ) +pl3d.Update() + +outline = vtk.vtkStructuredGridOutlineFilter() +outline.SetInputConnection(pl3d.GetOutputPort()) + +outlineMapper = vtk.vtkPolyDataMapper() +outlineMapper.SetInputConnection(outline.GetOutputPort()) + +outlineActor = vtk.vtkActor() +outlineActor.SetMapper(outlineMapper) + +seeds = vtk.vtkLineSource() +seeds.SetPoint1(15, -5, 32) +seeds.SetPoint2(15, 5, 32) +seeds.SetResolution(10) + +integ = vtk.vtkRungeKutta4() + +sl = vtk.vtkStreamLine() +sl.SetIntegrator(integ) +sl.SetInputConnection(pl3d.GetOutputPort()) +sl.SetSource(seeds.GetOutput()) +sl.SetMaximumPropagationTime(0.1) +sl.SetIntegrationStepLength(0.1) +sl.SetIntegrationDirectionToBackward() +sl.SetStepLength(0.001) + +tube = vtk.vtkTubeFilter() +tube.SetInputConnection(sl.GetOutputPort()) +tube.SetRadius(0.1) + +mapper = vtk.vtkPolyDataMapper() +mapper.SetInputConnection(tube.GetOutputPort()) + +actor = vtk.vtkActor() +actor.SetMapper(mapper) + +mmapper = vtk.vtkPolyDataMapper() +mmapper.SetInputConnection(seeds.GetOutputPort()) +mactor = vtk.vtkActor() +mactor.SetMapper(mmapper) +ren.AddActor(mactor) + +ren.AddActor(actor) +ren.AddActor(outlineActor) + +cam=ren.GetActiveCamera() +cam.SetClippingRange( 3.95297, 50 ) +cam.SetFocalPoint( 8.88908, 0.595038, 29.3342 ) +cam.SetPosition( -12.3332, 31.7479, 41.2387 ) +cam.SetViewUp( 0.060772, -0.319905, 0.945498 ) + +renWin.Render() +retVal = vtkRegressionTestImage(renWin) +sys.exit( not retVal ) + diff --git a/Graphics/Testing/Tcl/AutomaticPlaneGeneration.tcl b/Graphics/Testing/Tcl/AutomaticPlaneGeneration.tcl new file mode 100644 index 0000000..cae59de --- /dev/null +++ b/Graphics/Testing/Tcl/AutomaticPlaneGeneration.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPlaneSource aPlane + aPlane SetCenter -100 -100 -100 + aPlane SetOrigin -100 -100 -100 + aPlane SetPoint1 -90 -100 -100 + aPlane SetPoint2 -100 -90 -100 + aPlane SetNormal 0 -1 1 + +vtkPNMReader imageIn + imageIn SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +vtkTexture texture + texture SetInputConnection [imageIn GetOutputPort] + +vtkTextureMapToPlane texturePlane + texturePlane SetInputConnection [aPlane GetOutputPort] + texturePlane AutomaticPlaneGenerationOn + +vtkPolyDataMapper planeMapper + planeMapper SetInputConnection [texturePlane GetOutputPort] + +vtkActor texturedPlane + texturedPlane SetMapper planeMapper + texturedPlane SetTexture texture + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor texturedPlane +#ren1 SetBackground 1 1 1 +renWin SetSize 200 200 +renWin Render + +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/CMakeLists.txt b/Graphics/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..3e26072 --- /dev/null +++ b/Graphics/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,268 @@ +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + + IF (VTK_USE_MANGLED_MESA) + ADD_TEST(MesaCone-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Graphics/Testing/Tcl/MesaCone.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Graphics/MesaCone.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDIF (VTK_USE_MANGLED_MESA) + + FOREACH ( tfile + AutomaticPlaneGeneration + Canny + CellDataToPointData + Delaunay2D + Delaunay2DAlpha + Delaunay2DTransform + Delaunay3D + Disk + EnSight6Elements + EnSight6OfficeBin + EnSightBlow1ASCII + EnSightBlow1Bin + EnSightBlow2ASCII + EnSightBlow2Bin + EnSightBlow3Bin + EnSightBlow4Bin + EnSightBlow5ASCII + EnSightCompound + EnSightGoldElements + EnSightIronProtASCII + EnSightIronProtBin + EnSightMandelbrot + EnSightOfficeASCII + EnSightOfficeBin + EnSightRectGridASCII + EnSightRectGridBin + EnSightSelectArrays + ExtractEdgesQuadraticCells + ExtractTensors + Hyper + HyperScalarBar + KlineBottle + LineIntersectQuadraticCells + MatrixToTransform + MultidimensionalSolution + NoLightGeneration + OBBCylinder + OSCone + PolyDataMapperAllPolygons + PolyDataMapperAllWireframe + QuadricDecimation + StreamPolyData + TenEllip + TestBandedContourFilter + TestBoxFunction + TestButtonSource + TestCameraInterpolator + TestCellDerivs + TestCurvatures + TestDiscreteMarchingCubes + TestGraphLayoutFilter + TestGridSynchronizedTemplates3D + TestImageMarchingCubes + TestMarchingSquares + TestMultiBlockStreamer + TestParametricFunctions + TestPlatonicSolids + TestQuadricClustering + TestRectilinearGridToTetrahedra + TestRectilinearSynchronizedTemplates + TestRegularPolygonSource + TestRibbonAndTube + TestRotate + TestRuledSurface + TestRuledSurface2 + TestSpherePuzzle + TestSpherePuzzleArrows + TestSplineFilter + TestStructuredGrid + TestSynchronizedTemplates2D + TestSynchronizedTemplates3D + TestTransformInterpolator + TestTriangleFilter + TransformConcatenation + TransformCoverage + TransformPolyData + blankGrid + capCow + capSphere + clipArt + clipComb + clipImage + clipQuadraticCells + clipVolume + clipVolume2 + clipVolume3 + combStreamers + combStreamers2 + coneResolution + constrainedDelaunay + contour2DAll + contour3DAll + contourCells + contourQuadraticCells + contoursToSurface + cowHair + cowHair2 + createBFont + cursor3D + cutLoop + cylMap + cylindrical + dataSetSurfaceFilter + deciPlane + dicer + dispPlot + edgePoints + eleState + extractPolyData + extractRectGrid + extractUGrid + extractVectors + extrudeCopyCD + fieldToPolyData + fieldToRGrid + fieldToSGrid + fieldToUGrid + financialField + genHead + geomFilter + glyph2D + headBone + hull + iceCream + imageMCAll + mcubes + mergeFilter + motor + multipleComponentContour + multipleIso + nacaBinary + officeStreamPoints + polyConn + probe + probeComb + progGlyphs + progGlyphsBySource + quadricCut + rectGrid + recursiveDC + reverseNormals + scalarColors + scalarConn + schwarz + shepards + skinOrder + smoothCyl + smoothCyl2 + smoothMeshOnMesh + socbal + spatialRepAll + spherical + splitVectors + stereoDresdenMace + streamTracer + stripF + subDivideTetra + subPixelPositionMin + subdividePointData + sync3dAll + teapotHulls + testDataSetTriangleFilter + testDataSetTriangleFilter2 + testHexaPenta + testReflect + textureThreshold + triangularTCoords + triangularTexture + warplens + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Graphics/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Graphics/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH ( tfile ) + + # + # If we do not have the data, still run the tests that we can + # + ELSE (VTK_DATA_ROOT) + IF (VTK_USE_MANGLED_MESA) + ADD_TEST(MesaCone ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Graphics/Testing/Tcl/MesaCone.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDIF (VTK_USE_MANGLED_MESA) + + FOREACH ( tfile + capSphere + CellDataToPointData + clipVolume + clipVolume2 + clipVolume3 + coneResolution + constrainedDelaunay + contourCells + contoursToSurface + cutLoop + Delaunay2D + Delaunay2DAlpha + Delaunay2DTransform + Disk + extractPolyData + glyph2D + Hyper + KlineBottle + MatrixToTransform + OBBCylinder + progGlyphs + progGlyphsBySource + quadricCut + scalarConn + schwarz + shepards + smoothCyl + smoothCyl2 + subdividePointData + subDivideTetra + TestBoxFunction + TestGraphLayoutFilter + testQuadricDecimation + triangularTCoords + triangularTexture + warplens + TestGraphLayoutFilter + TransformConcatenation + TransformCoverage + TransformPolyData + ) + ADD_TEST(${tfile} ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Graphics/Testing/Tcl/${tfile}.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH ( tfile ) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + +ADD_TEST(PrintSelf-Graphics ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Graphics) + +ADD_TEST(TestSetObjectMacro-Graphics ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Graphics/vtk\\\\*.h" + "vtkSetObjectMacro" + ) diff --git a/Graphics/Testing/Tcl/Canny.tcl b/Graphics/Testing/Tcl/Canny.tcl new file mode 100644 index 0000000..0a02d30 --- /dev/null +++ b/Graphics/Testing/Tcl/Canny.tcl @@ -0,0 +1,104 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# load in the texture map +# +vtkPNMReader imageIn +imageIn SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +vtkImageLuminance il +il SetInputConnection [imageIn GetOutputPort] + +vtkImageCast ic +ic SetOutputScalarTypeToFloat +ic SetInputConnection [il GetOutputPort] + +# smooth the image +vtkImageGaussianSmooth gs +gs SetInputConnection [ic GetOutputPort] +gs SetDimensionality 2 +gs SetRadiusFactors 1 1 0 + +# gradient the image +vtkImageGradient imgGradient; +imgGradient SetInputConnection [gs GetOutputPort]; +imgGradient SetDimensionality 2 + +vtkImageMagnitude imgMagnitude +imgMagnitude SetInputConnection [imgGradient GetOutputPort] + +# non maximum suppression +vtkImageNonMaximumSuppression nonMax; +nonMax SetMagnitudeInput [imgMagnitude GetOutput]; +nonMax SetVectorInput [imgGradient GetOutput]; +nonMax SetDimensionality 2 + +vtkImageConstantPad pad +pad SetInputConnection [imgGradient GetOutputPort] +pad SetOutputNumberOfScalarComponents 3 +pad SetConstant 0 + +vtkImageToStructuredPoints i2sp1 +i2sp1 SetInputConnection [nonMax GetOutputPort] +i2sp1 SetVectorInput [pad GetOutput] + +# link edgles +vtkLinkEdgels imgLink; +imgLink SetInputConnection [i2sp1 GetOutputPort]; +imgLink SetGradientThreshold 2; + +# threshold links +vtkThreshold thresholdEdgels; +thresholdEdgels SetInputConnection [imgLink GetOutputPort]; +thresholdEdgels ThresholdByUpper 10; +thresholdEdgels AllScalarsOff + +vtkGeometryFilter gf +gf SetInputConnection [thresholdEdgels GetOutputPort] + +vtkImageToStructuredPoints i2sp +i2sp SetInputConnection [imgMagnitude GetOutputPort] +i2sp SetVectorInput [pad GetOutput] + +# subpixel them +vtkSubPixelPositionEdgels spe; +spe SetInputConnection [gf GetOutputPort]; +spe SetGradMaps [i2sp GetOutput]; + +vtkStripper strip +strip SetInputConnection [spe GetOutputPort] + +vtkPolyDataMapper dsm +dsm SetInputConnection [strip GetOutputPort] +dsm ScalarVisibilityOff + +vtkActor planeActor +planeActor SetMapper dsm +[planeActor GetProperty] SetAmbient 1.0 +[planeActor GetProperty] SetDiffuse 0.0 + +# Add the actors to the renderer, set the background and size +ren1 AddActor planeActor +renWin SetSize 600 300 + +# render the image +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render +[ren1 GetActiveCamera] Zoom 2.8 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + diff --git a/Graphics/Testing/Tcl/CellDataToPointData.tcl b/Graphics/Testing/Tcl/CellDataToPointData.tcl new file mode 100644 index 0000000..522b89b --- /dev/null +++ b/Graphics/Testing/Tcl/CellDataToPointData.tcl @@ -0,0 +1,59 @@ +package require vtk +package require vtkinteraction + + +# cell scalars to point scalars +# get the interactor ui + +# Create the RenderWindow, Renderer and RenderWindowInteractor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a 2*2 cell/3*3 pt structuredgrid +vtkPoints points + points InsertNextPoint -1 1 0 + points InsertNextPoint 0 1 0 + points InsertNextPoint 1 1 0 + points InsertNextPoint -1 0 0 + points InsertNextPoint 0 0 0 + points InsertNextPoint 1 0 0 + points InsertNextPoint -1 -1 0 + points InsertNextPoint 0 -1 0 + points InsertNextPoint 1 -1 0 + +vtkFloatArray faceColors + faceColors InsertNextValue 0 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 2 + +vtkStructuredGrid sgrid + sgrid SetDimensions 3 3 1 + sgrid SetPoints points + [sgrid GetCellData] SetScalars faceColors + +vtkCellDataToPointData Cell2Point + Cell2Point SetInput sgrid + Cell2Point PassCellDataOn + +vtkDataSetMapper mapper + mapper SetInput [Cell2Point GetStructuredGridOutput] + mapper SetScalarModeToUsePointData + mapper SetScalarRange 0 2 + +vtkActor actor + actor SetMapper mapper + +# Add the actors to the renderer, set the background and size +ren1 AddActor actor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 256 256 + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + diff --git a/Graphics/Testing/Tcl/Delaunay2D.tcl b/Graphics/Testing/Tcl/Delaunay2D.tcl new file mode 100644 index 0000000..9093e38 --- /dev/null +++ b/Graphics/Testing/Tcl/Delaunay2D.tcl @@ -0,0 +1,56 @@ +package require vtk + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create some points +# +vtkMath math +vtkPoints points +for {set i 0} {$i<1000} {incr i 1} { + eval points InsertPoint $i [math Random 0 1] [math Random 0 1] 0.0 +} + +vtkPolyData profile + profile SetPoints points + +# triangulate them +# +vtkDelaunay2D del1 + del1 SetInput profile + del1 BoundingTriangulationOn + del1 SetTolerance 0.001 + del1 SetAlpha 0.0 + del1 Update + +vtkShrinkPolyData shrink + shrink SetInputConnection [del1 GetOutputPort] + +vtkPolyDataMapper map + map SetInputConnection [shrink GetOutputPort] + +vtkActor triangulation + triangulation SetMapper map + [triangulation GetProperty] SetColor 1 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor triangulation +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +renWin Render + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.5 + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/Delaunay2DAlpha.tcl b/Graphics/Testing/Tcl/Delaunay2DAlpha.tcl new file mode 100644 index 0000000..bd3f19f --- /dev/null +++ b/Graphics/Testing/Tcl/Delaunay2DAlpha.tcl @@ -0,0 +1,55 @@ +package require vtk + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create some points +# +vtkMath math +vtkPoints points +for {set i 0} {$i<100} {incr i 1} { + eval points InsertPoint $i [math Random 0 1] [math Random 0 1] 0.0 +} + +vtkPolyData profile + profile SetPoints points + +# triangulate them +# +vtkDelaunay2D del1 + del1 SetInput profile + del1 SetTolerance 0.001 + del1 SetAlpha 0.1 + del1 Update + +vtkShrinkPolyData shrink + shrink SetInputConnection [del1 GetOutputPort] + +vtkPolyDataMapper map + map SetInputConnection [shrink GetOutputPort] + +vtkActor triangulation + triangulation SetMapper map + [triangulation GetProperty] SetColor 1 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor triangulation +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +renWin Render + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.5 + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/Delaunay2DTransform.tcl b/Graphics/Testing/Tcl/Delaunay2DTransform.tcl new file mode 100644 index 0000000..5ed1643 --- /dev/null +++ b/Graphics/Testing/Tcl/Delaunay2DTransform.tcl @@ -0,0 +1,80 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create some points on a sphere such that the data is not in the form +# of z = f(x,y) +# + +vtkMath math1 +vtkPoints points +vtkFloatArray vectors +vectors SetNumberOfComponents 3 +for {set i 0} {$i<100} {incr i 1} { + set theta [math1 Random 0.31415 2.8] + set phi [math1 Random 0.31415 2.8] + eval points InsertPoint $i [expr cos($theta)*sin($phi)] [expr sin($theta)*sin($phi)] [expr cos($phi)] + eval vectors InsertTuple3 $i [expr cos($theta)*sin($phi)] [expr sin($theta)*sin($phi)] [expr cos($phi)] +} + +vtkPolyData profile + profile SetPoints points + [profile GetPointData] SetVectors vectors + +# build a transform that rotates this data into z = f(x,y) +# +vtkTransform transform +transform RotateX 90 + + +# triangulate the data using the specified transform +# +vtkDelaunay2D del1 + del1 SetInput profile + del1 SetTransform transform + del1 BoundingTriangulationOff + del1 SetTolerance 0.001 + del1 SetAlpha 0.0 + + +vtkShrinkPolyData shrink + shrink SetInputConnection [del1 GetOutputPort] + +vtkPolyDataMapper map + map SetInputConnection [shrink GetOutputPort] + +vtkActor triangulation + triangulation SetMapper map + [triangulation GetProperty] SetColor 1 0 0 + [triangulation GetProperty] BackfaceCullingOn + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor triangulation +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +renWin Render + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.5 +$cam1 Azimuth 90 +$cam1 Elevation 30 +$cam1 Azimuth -60 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/Delaunay3D.tcl b/Graphics/Testing/Tcl/Delaunay3D.tcl new file mode 100644 index 0000000..dacbf4d --- /dev/null +++ b/Graphics/Testing/Tcl/Delaunay3D.tcl @@ -0,0 +1,62 @@ +package require vtk +package require vtkinteraction + +# create some random points in the unit cube centered at (.5,.5,.5) +# +vtkMath math +vtkPoints points +for {set i 0} {$i<25} {incr i 1} { + eval points InsertPoint $i [math Random 0 1] [math Random 0 1] [math Random 0 1] +} + +vtkPolyData profile + profile SetPoints points + +# triangulate them +# +vtkDelaunay3D del1 + del1 SetInput profile + del1 BoundingTriangulationOn + del1 SetTolerance 0.01 + del1 SetAlpha 0.2 + del1 BoundingTriangulationOff + +vtkShrinkFilter shrink + shrink SetInputConnection [del1 GetOutputPort] + shrink SetShrinkFactor 0.9 + +vtkDataSetMapper map + map SetInputConnection [shrink GetOutputPort] + +vtkActor triangulation + triangulation SetMapper map + [triangulation GetProperty] SetColor 1 0 0 + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor triangulation +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 +renWin Render + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.5 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/Disk.tcl b/Graphics/Testing/Tcl/Disk.tcl new file mode 100644 index 0000000..625aff7 --- /dev/null +++ b/Graphics/Testing/Tcl/Disk.tcl @@ -0,0 +1,40 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkDiskSource disk + disk SetInnerRadius 1.0 + disk SetOuterRadius 2.0 + disk SetRadialResolution 1 + disk SetCircumferentialResolution 20 + +vtkPolyDataMapper diskMapper + diskMapper SetInputConnection [disk GetOutputPort] +vtkActor diskActor + diskActor SetMapper diskMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor diskActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 200 200 + +# Get handles to some useful objects +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +renWin Render + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/EnSight6Elements.tcl b/Graphics/Testing/Tcl/EnSight6Elements.tcl new file mode 100644 index 0000000..f0fb074 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSight6Elements.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin StereoCapableWindowOn +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkGenericEnSightReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/elements6.case" + reader Update + +vtkGeometryFilter geom + geom SetInputConnection [reader GetOutputPort] + +vtkArrayCalculator calc + calc SetInputConnection [geom GetOutputPort] + calc SetAttributeModeToUsePointData + calc SetFunction "pointCVectors_r . pointCVectors_i + pointScalars" + calc AddScalarArrayName "pointScalars" 0 + calc AddVectorArrayName "pointCVectors_r" 0 1 2 + calc AddVectorArrayName "pointCVectors_i" 0 1 2 + calc SetResultArrayName "test" + +vtkPolyDataMapper mapper + mapper SetInputConnection [calc GetOutputPort] + mapper SetColorModeToMapScalars + mapper SetScalarModeToUsePointFieldData + mapper ColorByArrayComponent "test" 0 + mapper SetScalarRange 0 36000 + +vtkActor actor + actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSight6OfficeBin.tcl b/Graphics/Testing/Tcl/EnSight6OfficeBin.tcl new file mode 100644 index 0000000..fe20f10 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSight6OfficeBin.tcl @@ -0,0 +1,60 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkGenericEnSightReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/office6_bin.case" + reader Update;#force a read to occur + +# to add coverage for vtkMultiPartExtentTranslator +vtkMultiPartExtentTranslator translator +[reader GetOutput] SetExtentTranslator translator + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Create source for streamtubes +vtkStreamPoints streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition 0.1 2.1 0.5 + streamer SetMaximumPropagationTime 500 + streamer SetTimeIncrement 0.5 + streamer SetIntegrationDirectionToForward + +vtkConeSource cone + cone SetResolution 8 +vtkGlyph3D cones + cones SetInputConnection [streamer GetOutputPort] + cones SetSource [cone GetOutput] + cones SetScaleFactor 0.9 + cones SetScaleModeToScaleByVector +vtkPolyDataMapper mapCones + mapCones SetInputConnection [cones GetOutputPort] + eval mapCones SetScalarRange [[reader GetOutput] GetScalarRange] +vtkActor conesActor + conesActor SetMapper mapCones + +ren1 AddActor outlineActor +ren1 AddActor conesActor + +ren1 SetBackground 0.4 0.4 0.5 + +renWin SetSize 300 300 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightBlow1ASCII.tcl b/Graphics/Testing/Tcl/EnSightBlow1ASCII.tcl new file mode 100644 index 0000000..d8707e5 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightBlow1ASCII.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow1_ascii.case" +reader SetTimeValue 1 +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetColorModeToMapScalars +mapper SetScalarModeToUsePointFieldData +mapper ColorByArrayComponent "displacement" 0 +mapper SetScalarRange 0 2.08 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightBlow1Bin.tcl b/Graphics/Testing/Tcl/EnSightBlow1Bin.tcl new file mode 100644 index 0000000..87e2d75 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightBlow1Bin.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow1_bin.case" +reader SetTimeValue 1 +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetColorModeToMapScalars +mapper SetScalarModeToUsePointFieldData +mapper ColorByArrayComponent "displacement" 0 +mapper SetScalarRange 0 2.08 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightBlow2ASCII.tcl b/Graphics/Testing/Tcl/EnSightBlow2ASCII.tcl new file mode 100644 index 0000000..b3464d6 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightBlow2ASCII.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow2_ascii.case" +reader SetTimeValue 1 +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetColorModeToMapScalars +mapper SetScalarModeToUsePointFieldData +mapper ColorByArrayComponent "displacement" 0 +mapper SetScalarRange 0 2.08 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightBlow2Bin.tcl b/Graphics/Testing/Tcl/EnSightBlow2Bin.tcl new file mode 100644 index 0000000..b54b4d5 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightBlow2Bin.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow2_bin.case" +reader SetTimeValue 1 +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetColorModeToMapScalars +mapper SetScalarModeToUsePointFieldData +mapper ColorByArrayComponent "displacement" 0 +mapper SetScalarRange 0 2.08 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightBlow3Bin.tcl b/Graphics/Testing/Tcl/EnSightBlow3Bin.tcl new file mode 100644 index 0000000..e3312ec --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightBlow3Bin.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow3_bin.case" +reader SetTimeValue 1 +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetColorModeToMapScalars +mapper SetScalarModeToUsePointFieldData +mapper ColorByArrayComponent "displacement" 0 +mapper SetScalarRange 0 2.08 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightBlow4Bin.tcl b/Graphics/Testing/Tcl/EnSightBlow4Bin.tcl new file mode 100644 index 0000000..c60ff27 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightBlow4Bin.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow4_bin.case" +reader SetTimeValue 1.0 +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetColorModeToMapScalars +mapper SetScalarModeToUsePointFieldData +mapper ColorByArrayComponent "displacement" 0 +mapper SetScalarRange 0 2.08 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightBlow5ASCII.tcl b/Graphics/Testing/Tcl/EnSightBlow5ASCII.tcl new file mode 100644 index 0000000..51ac36b --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightBlow5ASCII.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow5_ascii.case" +reader SetTimeValue 1 +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetColorModeToMapScalars +mapper SetScalarModeToUsePointFieldData +mapper ColorByArrayComponent "displacement" 0 +mapper SetScalarRange 0 2.08 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightCompound.tcl b/Graphics/Testing/Tcl/EnSightCompound.tcl new file mode 100644 index 0000000..5221fca --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightCompound.tcl @@ -0,0 +1,50 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin StereoCapableWindowOn +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkEnSightMasterServerReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/elements.sos" + reader SetCurrentPiece 0 + reader Update + +vtkGeometryFilter geom0 + geom0 SetInputConnection [reader GetOutputPort] +vtkGeometryFilter geom1 + geom1 SetInput [reader GetOutput 1] + +vtkPolyDataMapper mapper0 + mapper0 SetInputConnection [geom0 GetOutputPort] + mapper0 SetColorModeToMapScalars + mapper0 SetScalarModeToUsePointFieldData + mapper0 ColorByArrayComponent "pointScalars" 0 + mapper0 SetScalarRange 0 112 +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [geom1 GetOutputPort] + mapper1 SetColorModeToMapScalars + mapper1 SetScalarModeToUsePointFieldData + mapper1 ColorByArrayComponent "pointScalars" 0 + mapper1 SetScalarRange 0 112 + +vtkActor actor0 + actor0 SetMapper mapper0 +vtkActor actor1 + actor1 SetMapper mapper1 + +# assign our actor to the renderer +ren1 AddActor actor0 +ren1 AddActor actor1 + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightGoldElements.tcl b/Graphics/Testing/Tcl/EnSightGoldElements.tcl new file mode 100644 index 0000000..e4b490d --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightGoldElements.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin StereoCapableWindowOn +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkGenericEnSightReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/elements.case" + reader Update + +vtkGeometryFilter geom0 + geom0 SetInputConnection [reader GetOutputPort] +vtkGeometryFilter geom1 + geom1 SetInput [reader GetOutput 1] + +vtkPolyDataMapper mapper0 + mapper0 SetInputConnection [geom0 GetOutputPort] + mapper0 SetColorModeToMapScalars + mapper0 SetScalarModeToUsePointFieldData + mapper0 ColorByArrayComponent "pointScalars" 0 + mapper0 SetScalarRange 0 112 +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [geom1 GetOutputPort] + mapper1 SetColorModeToMapScalars + mapper1 SetScalarModeToUsePointFieldData + mapper1 ColorByArrayComponent "pointScalars" 0 + mapper1 SetScalarRange 0 112 + +vtkActor actor0 + actor0 SetMapper mapper0 +vtkActor actor1 + actor1 SetMapper mapper1 + +# assign our actor to the renderer +ren1 AddActor actor0 +ren1 AddActor actor1 + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightIronProtASCII.tcl b/Graphics/Testing/Tcl/EnSightIronProtASCII.tcl new file mode 100644 index 0000000..5dd6e22 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightIronProtASCII.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 +ren1 SetBackground 0 0 0 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# camera parameters +set camera [ren1 GetActiveCamera] +$camera SetPosition -54.8012 109.471 231.412 +$camera SetFocalPoint 33 33 33 +$camera SetViewUp 0.157687 0.942832 -0.293604 +$camera SetViewAngle 30 +$camera SetClippingRange 124.221 363.827 + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/ironProt_ascii.case" +reader Update + +vtkContourFilter Contour0 +Contour0 SetInputConnection [reader GetOutputPort] +Contour0 SetValue 0 200 +Contour0 SetComputeScalars 1 + +vtkPolyDataMapper mapper +mapper SetInputConnection [Contour0 GetOutputPort] +mapper SetImmediateModeRendering 1 +mapper SetScalarRange 0 1 +mapper SetScalarVisibility 1 + +vtkActor actor +actor SetMapper mapper +[actor GetProperty] SetRepresentationToSurface +[actor GetProperty] SetInterpolationToGouraud +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/EnSightIronProtBin.tcl b/Graphics/Testing/Tcl/EnSightIronProtBin.tcl new file mode 100644 index 0000000..8854f10 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightIronProtBin.tcl @@ -0,0 +1,49 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 +ren1 SetBackground 0 0 0 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 300 300 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# camera parameters +set camera [ren1 GetActiveCamera] +$camera SetPosition -54.8012 109.471 231.412 +$camera SetFocalPoint 33 33 33 +$camera SetViewUp 0.157687 0.942832 -0.293604 +$camera SetViewAngle 30 +$camera SetClippingRange 124.221 363.827 + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/ironProt_bin.case" +reader Update + +vtkContourFilter Contour0 +Contour0 SetInputConnection [reader GetOutputPort] +Contour0 SetValue 0 200 +Contour0 SetComputeScalars 1 + +vtkPolyDataMapper mapper +mapper SetInputConnection [Contour0 GetOutputPort] +mapper SetImmediateModeRendering 1 +mapper SetScalarRange 0 1 +mapper SetScalarVisibility 1 + +vtkActor actor +actor SetMapper mapper +[actor GetProperty] SetRepresentationToSurface +[actor GetProperty] SetInterpolationToGouraud +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/EnSightMandelbrot.tcl b/Graphics/Testing/Tcl/EnSightMandelbrot.tcl new file mode 100644 index 0000000..218945e --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightMandelbrot.tcl @@ -0,0 +1,80 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin StereoCapableWindowOn +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkEnSightMasterServerReader reader1 + reader1 SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/mandelbrot.sos" + reader1 SetCurrentPiece 0 + reader1 Update + +vtkGeometryFilter geom0 + geom0 SetInputConnection [reader1 GetOutputPort] +vtkGeometryFilter geom1 + geom1 SetInput [reader1 GetOutput 1] + +vtkPolyDataMapper mapper0 + mapper0 SetInputConnection [geom0 GetOutputPort] + mapper0 SetColorModeToMapScalars + mapper0 SetScalarModeToUsePointFieldData + mapper0 ColorByArrayComponent "Iterations" 0 + mapper0 SetScalarRange 0 112 +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [geom1 GetOutputPort] + mapper1 SetColorModeToMapScalars + mapper1 SetScalarModeToUsePointFieldData + mapper1 ColorByArrayComponent "Iterations" 0 + mapper1 SetScalarRange 0 112 + +vtkActor actor0 + actor0 SetMapper mapper0 +vtkActor actor1 + actor1 SetMapper mapper1 + +vtkEnSightMasterServerReader reader2 + reader2 SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/mandelbrot.sos" + reader2 SetCurrentPiece 1 + reader2 Update + +vtkGeometryFilter geom2 + geom2 SetInputConnection [reader2 GetOutputPort] +vtkGeometryFilter geom3 + geom3 SetInput [reader2 GetOutput 1] + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [geom2 GetOutputPort] + mapper2 SetColorModeToMapScalars + mapper2 SetScalarModeToUsePointFieldData + mapper2 ColorByArrayComponent "Iterations" 0 + mapper2 SetScalarRange 0 112 +vtkPolyDataMapper mapper3 + mapper3 SetInputConnection [geom3 GetOutputPort] + mapper3 SetColorModeToMapScalars + mapper3 SetScalarModeToUsePointFieldData + mapper3 ColorByArrayComponent "Iterations" 0 + mapper3 SetScalarRange 0 112 + +vtkActor actor2 + actor2 SetMapper mapper2 +vtkActor actor3 + actor3 SetMapper mapper3 + +# assign our actor to the renderer +ren1 AddActor actor0 +ren1 AddActor actor1 +ren1 AddActor actor2 +ren1 AddActor actor3 + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightOfficeASCII.tcl b/Graphics/Testing/Tcl/EnSightOfficeASCII.tcl new file mode 100644 index 0000000..1edd222 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightOfficeASCII.tcl @@ -0,0 +1,60 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkGenericEnSightReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/office_ascii.case" + reader Update;#force a read to occur + +# to add coverage for vtkMultiPartExtentTranslator +vtkMultiPartExtentTranslator translator +[reader GetOutput] SetExtentTranslator translator + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Create source for streamtubes +vtkStreamPoints streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition 0.1 2.1 0.5 + streamer SetMaximumPropagationTime 500 + streamer SetTimeIncrement 0.5 + streamer SetIntegrationDirectionToForward + +vtkConeSource cone + cone SetResolution 8 +vtkGlyph3D cones + cones SetInputConnection [streamer GetOutputPort] + cones SetSource [cone GetOutput] + cones SetScaleFactor 0.9 + cones SetScaleModeToScaleByVector +vtkPolyDataMapper mapCones + mapCones SetInputConnection [cones GetOutputPort] + eval mapCones SetScalarRange [[reader GetOutput] GetScalarRange] +vtkActor conesActor + conesActor SetMapper mapCones + +ren1 AddActor outlineActor +ren1 AddActor conesActor + +ren1 SetBackground 0.4 0.4 0.5 + +renWin SetSize 300 300 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightOfficeBin.tcl b/Graphics/Testing/Tcl/EnSightOfficeBin.tcl new file mode 100644 index 0000000..32555ef --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightOfficeBin.tcl @@ -0,0 +1,60 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkGenericEnSightReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/office_bin.case" + reader Update;#force a read to occur + +# to add coverage for vtkMultiPartExtentTranslator +vtkMultiPartExtentTranslator translator +[reader GetOutput] SetExtentTranslator translator + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Create source for streamtubes +vtkStreamPoints streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition 0.1 2.1 0.5 + streamer SetMaximumPropagationTime 500 + streamer SetTimeIncrement 0.5 + streamer SetIntegrationDirectionToForward + +vtkConeSource cone + cone SetResolution 8 +vtkGlyph3D cones + cones SetInputConnection [streamer GetOutputPort] + cones SetSource [cone GetOutput] + cones SetScaleFactor 0.9 + cones SetScaleModeToScaleByVector +vtkPolyDataMapper mapCones + mapCones SetInputConnection [cones GetOutputPort] + eval mapCones SetScalarRange [[reader GetOutput] GetScalarRange] +vtkActor conesActor + conesActor SetMapper mapCones + +ren1 AddActor outlineActor +ren1 AddActor conesActor + +ren1 SetBackground 0.4 0.4 0.5 + +renWin SetSize 300 300 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . + diff --git a/Graphics/Testing/Tcl/EnSightRectGridASCII.tcl b/Graphics/Testing/Tcl/EnSightRectGridASCII.tcl new file mode 100644 index 0000000..2984a69 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightRectGridASCII.tcl @@ -0,0 +1,120 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +set VTK_VARY_RADIUS_BY_VECTOR 2 + +# create pipeline +# +vtkGenericEnSightReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/RectGrid_ascii.case" + reader Update +vtkCastToConcrete toRectilinearGrid + toRectilinearGrid SetInputConnection [reader GetOutputPort] +vtkRectilinearGridGeometryFilter plane + plane SetInput [toRectilinearGrid GetRectilinearGridOutput] + plane SetExtent 0 100 0 100 15 15 +vtkTriangleFilter tri + tri SetInputConnection [plane GetOutputPort] +vtkWarpVector warper + warper SetInputConnection [tri GetOutputPort] + warper SetScaleFactor 0.05 +vtkDataSetMapper planeMapper + planeMapper SetInputConnection [warper GetOutputPort] + planeMapper SetScalarRange 0.197813 0.710419 +vtkActor planeActor + planeActor SetMapper planeMapper + +vtkPlane cutPlane + eval cutPlane SetOrigin [[reader GetOutput] GetCenter] + cutPlane SetNormal 1 0 0 +vtkCutter planeCut + planeCut SetInput [toRectilinearGrid GetRectilinearGridOutput] + planeCut SetCutFunction cutPlane +vtkDataSetMapper cutMapper + cutMapper SetInputConnection [planeCut GetOutputPort] + eval cutMapper SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor cutActor + cutActor SetMapper cutMapper + +vtkContourFilter iso + iso SetInput [toRectilinearGrid GetRectilinearGridOutput] + iso SetValue 0 0.7 +vtkPolyDataNormals normals + normals SetInputConnection [iso GetOutputPort] + normals SetFeatureAngle 45 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOff +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $bisque + eval [isoActor GetProperty] SetRepresentationToWireframe + +vtkStreamLine streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition -1.2 -0.1 1.3 + streamer SetMaximumPropagationTime 500 + streamer SetStepLength 0.05 + streamer SetIntegrationStepLength 0.05 + streamer SetIntegrationDirectionToIntegrateBothDirections + +vtkTubeFilter streamTube + streamTube SetInputConnection [streamer GetOutputPort] + streamTube SetRadius 0.025 + streamTube SetNumberOfSides 6 + streamTube SetVaryRadius $VTK_VARY_RADIUS_BY_VECTOR +vtkPolyDataMapper mapStreamTube + mapStreamTube SetInputConnection [streamTube GetOutputPort] + eval mapStreamTube SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor streamTubeActor + streamTubeActor SetMapper mapStreamTube + [streamTubeActor GetProperty] BackfaceCullingOn + +vtkOutlineFilter outline + outline SetInput [toRectilinearGrid GetRectilinearGridOutput] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor $black + +# Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor cutActor +ren1 AddActor isoActor +ren1 AddActor streamTubeActor + +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.76213 10.712 + $cam1 SetFocalPoint -0.0842503 -0.136905 0.610234 + $cam1 SetPosition 2.53813 2.2678 -5.22172 + $cam1 SetViewUp -0.241047 0.930635 0.275343 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/EnSightRectGridBin.tcl b/Graphics/Testing/Tcl/EnSightRectGridBin.tcl new file mode 100644 index 0000000..3a0ea15 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightRectGridBin.tcl @@ -0,0 +1,120 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +set VTK_VARY_RADIUS_BY_VECTOR 2 + +# create pipeline +# +vtkGenericEnSightReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/RectGrid_bin.case" + reader Update +vtkCastToConcrete toRectilinearGrid + toRectilinearGrid SetInputConnection [reader GetOutputPort] +vtkRectilinearGridGeometryFilter plane + plane SetInput [toRectilinearGrid GetRectilinearGridOutput] + plane SetExtent 0 100 0 100 15 15 +vtkTriangleFilter tri + tri SetInputConnection [plane GetOutputPort] +vtkWarpVector warper + warper SetInputConnection [tri GetOutputPort] + warper SetScaleFactor 0.05 +vtkDataSetMapper planeMapper + planeMapper SetInputConnection [warper GetOutputPort] + planeMapper SetScalarRange 0.197813 0.710419 +vtkActor planeActor + planeActor SetMapper planeMapper + +vtkPlane cutPlane + eval cutPlane SetOrigin [[reader GetOutput] GetCenter] + cutPlane SetNormal 1 0 0 +vtkCutter planeCut + planeCut SetInput [toRectilinearGrid GetRectilinearGridOutput] + planeCut SetCutFunction cutPlane +vtkDataSetMapper cutMapper + cutMapper SetInputConnection [planeCut GetOutputPort] + eval cutMapper SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor cutActor + cutActor SetMapper cutMapper + +vtkContourFilter iso + iso SetInput [toRectilinearGrid GetRectilinearGridOutput] + iso SetValue 0 0.7 +vtkPolyDataNormals normals + normals SetInputConnection [iso GetOutputPort] + normals SetFeatureAngle 45 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOff +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $bisque + eval [isoActor GetProperty] SetRepresentationToWireframe + +vtkStreamLine streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition -1.2 -0.1 1.3 + streamer SetMaximumPropagationTime 500 + streamer SetStepLength 0.05 + streamer SetIntegrationStepLength 0.05 + streamer SetIntegrationDirectionToIntegrateBothDirections + +vtkTubeFilter streamTube + streamTube SetInputConnection [streamer GetOutputPort] + streamTube SetRadius 0.025 + streamTube SetNumberOfSides 6 + streamTube SetVaryRadius $VTK_VARY_RADIUS_BY_VECTOR +vtkPolyDataMapper mapStreamTube + mapStreamTube SetInputConnection [streamTube GetOutputPort] + eval mapStreamTube SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor streamTubeActor + streamTubeActor SetMapper mapStreamTube + [streamTubeActor GetProperty] BackfaceCullingOn + +vtkOutlineFilter outline + outline SetInput [toRectilinearGrid GetRectilinearGridOutput] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor $black + +# Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor cutActor +ren1 AddActor isoActor +ren1 AddActor streamTubeActor + +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.76213 10.712 + $cam1 SetFocalPoint -0.0842503 -0.136905 0.610234 + $cam1 SetPosition 2.53813 2.2678 -5.22172 + $cam1 SetViewUp -0.241047 0.930635 0.275343 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/EnSightSelectArrays.tcl b/Graphics/Testing/Tcl/EnSightSelectArrays.tcl new file mode 100644 index 0000000..0fcb262 --- /dev/null +++ b/Graphics/Testing/Tcl/EnSightSelectArrays.tcl @@ -0,0 +1,52 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin StereoCapableWindowOn + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkGenericEnSightReader reader +reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/blow1_ascii.case" +reader SetTimeValue 1 +reader ReadAllVariablesOff + +reader SetPointArrayStatus "displacement" 1 +reader SetCellArrayStatus "thickness" 1 +reader SetCellArrayStatus "displacement" 1 + +reader Update + +vtkGeometryFilter geom +geom SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [geom GetOutputPort] +mapper SetScalarRange 0.5 1.0 + +vtkActor actor +actor SetMapper mapper + +# assign our actor to the renderer +ren1 AddActor actor + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +[ren1 GetActiveCamera] SetPosition 99.3932 17.6571 -22.6071 +[ren1 GetActiveCamera] SetFocalPoint 3.5 12 1.5 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.239617 -0.01054 0.97081 +ren1 ResetCameraClippingRange + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/ExtractEdgesQuadraticCells.tcl b/Graphics/Testing/Tcl/ExtractEdgesQuadraticCells.tcl new file mode 100644 index 0000000..354cfb2 --- /dev/null +++ b/Graphics/Testing/Tcl/ExtractEdgesQuadraticCells.tcl @@ -0,0 +1,355 @@ +package require vtk +package require vtkinteraction + +# Create 2D and 3D quadratic cells and extract their edges + +# Quadratic triangle +vtkPoints triPoints + triPoints SetNumberOfPoints 6 + triPoints InsertPoint 0 2.0 0.0 0.0 + triPoints InsertPoint 1 3.0 0.0 0.0 + triPoints InsertPoint 2 2.5 0.8 0.0 + triPoints InsertPoint 3 2.5 0.0 0.0 + triPoints InsertPoint 4 2.75 0.4 0.0 + triPoints InsertPoint 5 2.25 0.4 0.0 +vtkFloatArray triScalars + triScalars SetNumberOfTuples 6 + triScalars InsertValue 0 0.0 + triScalars InsertValue 1 0.0 + triScalars InsertValue 2 0.0 + triScalars InsertValue 3 1.0 + triScalars InsertValue 4 1.0 + triScalars InsertValue 5 0.0 +vtkQuadraticTriangle aTri + [aTri GetPointIds] SetId 0 0 + [aTri GetPointIds] SetId 1 1 + [aTri GetPointIds] SetId 2 2 + [aTri GetPointIds] SetId 3 3 + [aTri GetPointIds] SetId 4 4 + [aTri GetPointIds] SetId 5 5 +vtkUnstructuredGrid aTriGrid + aTriGrid Allocate 1 1 + aTriGrid InsertNextCell [aTri GetCellType] [aTri GetPointIds] + aTriGrid SetPoints triPoints + [aTriGrid GetPointData] SetScalars triScalars + +# Quadratic quadrilateral +vtkPoints quadPoints + quadPoints SetNumberOfPoints 8 + quadPoints InsertPoint 0 4.0 0.0 0.0 + quadPoints InsertPoint 1 5.0 0.0 0.0 + quadPoints InsertPoint 2 5.0 1.0 0.0 + quadPoints InsertPoint 3 4.0 1.0 0.0 + quadPoints InsertPoint 4 4.5 0.0 0.0 + quadPoints InsertPoint 5 5.0 0.5 0.0 + quadPoints InsertPoint 6 4.5 1.0 0.0 + quadPoints InsertPoint 7 4.0 0.5 0.0 +vtkFloatArray quadScalars + quadScalars SetNumberOfTuples 8 + quadScalars InsertValue 0 0.0 + quadScalars InsertValue 1 0.0 + quadScalars InsertValue 2 1.0 + quadScalars InsertValue 3 1.0 + quadScalars InsertValue 4 1.0 + quadScalars InsertValue 5 0.0 + quadScalars InsertValue 6 0.0 + quadScalars InsertValue 7 0.0 +vtkQuadraticQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + [aQuad GetPointIds] SetId 4 4 + [aQuad GetPointIds] SetId 5 5 + [aQuad GetPointIds] SetId 6 6 + [aQuad GetPointIds] SetId 7 7 +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + [aQuadGrid GetPointData] SetScalars quadScalars + +# Quadratic tetrahedron +vtkPoints tetPoints + tetPoints SetNumberOfPoints 10 + tetPoints InsertPoint 0 6.0 0.0 0.0 + tetPoints InsertPoint 1 7.0 0.0 0.0 + tetPoints InsertPoint 2 6.5 0.8 0.0 + tetPoints InsertPoint 3 6.5 0.4 1.0 + tetPoints InsertPoint 4 6.5 0.0 0.0 + tetPoints InsertPoint 5 6.75 0.4 0.0 + tetPoints InsertPoint 6 6.25 0.4 0.0 + tetPoints InsertPoint 7 6.25 0.2 0.5 + tetPoints InsertPoint 8 6.75 0.2 0.5 + tetPoints InsertPoint 9 6.50 0.6 0.5 +vtkFloatArray tetScalars + tetScalars SetNumberOfTuples 10 + tetScalars InsertValue 0 1.0 + tetScalars InsertValue 1 1.0 + tetScalars InsertValue 2 1.0 + tetScalars InsertValue 3 1.0 + tetScalars InsertValue 4 0.0 + tetScalars InsertValue 5 0.0 + tetScalars InsertValue 6 0.0 + tetScalars InsertValue 7 0.0 + tetScalars InsertValue 8 0.0 + tetScalars InsertValue 9 0.0 +vtkQuadraticTetra aTet + [aTet GetPointIds] SetId 0 0 + [aTet GetPointIds] SetId 1 1 + [aTet GetPointIds] SetId 2 2 + [aTet GetPointIds] SetId 3 3 + [aTet GetPointIds] SetId 4 4 + [aTet GetPointIds] SetId 5 5 + [aTet GetPointIds] SetId 6 6 + [aTet GetPointIds] SetId 7 7 + [aTet GetPointIds] SetId 8 8 + [aTet GetPointIds] SetId 9 9 +vtkUnstructuredGrid aTetGrid + aTetGrid Allocate 1 1 + aTetGrid InsertNextCell [aTet GetCellType] [aTet GetPointIds] + aTetGrid SetPoints tetPoints + [aTetGrid GetPointData] SetScalars tetScalars + +# Quadratic hexahedron +vtkPoints hexPoints + hexPoints SetNumberOfPoints 20 + hexPoints InsertPoint 0 8 0 0 + hexPoints InsertPoint 1 9 0 0 + hexPoints InsertPoint 2 9 1 0 + hexPoints InsertPoint 3 8 1 0 + hexPoints InsertPoint 4 8 0 1 + hexPoints InsertPoint 5 9 0 1 + hexPoints InsertPoint 6 9 1 1 + hexPoints InsertPoint 7 8 1 1 + hexPoints InsertPoint 8 8.5 0 0 + hexPoints InsertPoint 9 9 0.5 0 + hexPoints InsertPoint 10 8.5 1 0 + hexPoints InsertPoint 11 8 0.5 0 + hexPoints InsertPoint 12 8.5 0 1 + hexPoints InsertPoint 13 9 0.5 1 + hexPoints InsertPoint 14 8.5 1 1 + hexPoints InsertPoint 15 8 0.5 1 + hexPoints InsertPoint 16 8 0 0.5 + hexPoints InsertPoint 17 9 0 0.5 + hexPoints InsertPoint 18 9 1 0.5 + hexPoints InsertPoint 19 8 1 0.5 +vtkFloatArray hexScalars + hexScalars SetNumberOfTuples 20 + hexScalars InsertValue 0 1.0 + hexScalars InsertValue 1 1.0 + hexScalars InsertValue 2 1.0 + hexScalars InsertValue 3 1.0 + hexScalars InsertValue 4 1.0 + hexScalars InsertValue 5 1.0 + hexScalars InsertValue 6 1.0 + hexScalars InsertValue 7 1.0 + hexScalars InsertValue 8 0.0 + hexScalars InsertValue 9 0.0 + hexScalars InsertValue 10 0.0 + hexScalars InsertValue 11 0.0 + hexScalars InsertValue 12 0.0 + hexScalars InsertValue 13 0.0 + hexScalars InsertValue 14 0.0 + hexScalars InsertValue 15 0.0 + hexScalars InsertValue 16 0.0 + hexScalars InsertValue 17 0.0 + hexScalars InsertValue 18 0.0 + hexScalars InsertValue 19 0.0 +vtkQuadraticHexahedron aHex + [aHex GetPointIds] SetId 0 0 + [aHex GetPointIds] SetId 1 1 + [aHex GetPointIds] SetId 2 2 + [aHex GetPointIds] SetId 3 3 + [aHex GetPointIds] SetId 4 4 + [aHex GetPointIds] SetId 5 5 + [aHex GetPointIds] SetId 6 6 + [aHex GetPointIds] SetId 7 7 + [aHex GetPointIds] SetId 8 8 + [aHex GetPointIds] SetId 9 9 + [aHex GetPointIds] SetId 10 10 + [aHex GetPointIds] SetId 11 11 + [aHex GetPointIds] SetId 12 12 + [aHex GetPointIds] SetId 13 13 + [aHex GetPointIds] SetId 14 14 + [aHex GetPointIds] SetId 15 15 + [aHex GetPointIds] SetId 16 16 + [aHex GetPointIds] SetId 17 17 + [aHex GetPointIds] SetId 18 18 + [aHex GetPointIds] SetId 19 19 +vtkUnstructuredGrid aHexGrid + aHexGrid Allocate 1 1 + aHexGrid InsertNextCell [aHex GetCellType] [aHex GetPointIds] + aHexGrid SetPoints hexPoints + [aHexGrid GetPointData] SetScalars hexScalars + +# Quadratic wedge +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 15 + wedgePoints InsertPoint 0 10 0 0 + wedgePoints InsertPoint 1 11 0 0 + wedgePoints InsertPoint 2 10 1 0 + wedgePoints InsertPoint 3 10 0 1 + wedgePoints InsertPoint 4 11 0 1 + wedgePoints InsertPoint 5 10 1 1 + wedgePoints InsertPoint 6 10.5 0 0 + wedgePoints InsertPoint 7 10.5 0.5 0 + wedgePoints InsertPoint 8 10 0.5 0 + wedgePoints InsertPoint 9 10.5 0 1 + wedgePoints InsertPoint 10 10.5 0.5 1 + wedgePoints InsertPoint 11 10 0.5 1 + wedgePoints InsertPoint 12 10 0 0.5 + wedgePoints InsertPoint 13 11 0 0.5 + wedgePoints InsertPoint 14 10 1 0.5 +vtkFloatArray wedgeScalars + wedgeScalars SetNumberOfTuples 15 + wedgeScalars InsertValue 0 1.0 + wedgeScalars InsertValue 1 1.0 + wedgeScalars InsertValue 2 1.0 + wedgeScalars InsertValue 3 1.0 + wedgeScalars InsertValue 4 1.0 + wedgeScalars InsertValue 5 1.0 + wedgeScalars InsertValue 6 0.0 + wedgeScalars InsertValue 7 0.0 + wedgeScalars InsertValue 8 0.0 + wedgeScalars InsertValue 9 0.0 + wedgeScalars InsertValue 10 0.0 + wedgeScalars InsertValue 11 0.0 + wedgeScalars InsertValue 12 0.0 + wedgeScalars InsertValue 13 0.0 + wedgeScalars InsertValue 14 0.0 +vtkQuadraticWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + [aWedge GetPointIds] SetId 6 6 + [aWedge GetPointIds] SetId 7 7 + [aWedge GetPointIds] SetId 8 8 + [aWedge GetPointIds] SetId 9 9 + [aWedge GetPointIds] SetId 10 10 + [aWedge GetPointIds] SetId 11 11 + [aWedge GetPointIds] SetId 12 12 + [aWedge GetPointIds] SetId 13 13 + [aWedge GetPointIds] SetId 14 14 + #aWedge DebugOn + +#puts aWedge + +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + [aWedgeGrid GetPointData] SetScalars wedgeScalars + +# Quadratic pyramid +vtkPoints pyraPoints + pyraPoints SetNumberOfPoints 13 + pyraPoints InsertPoint 0 12 0 0 + pyraPoints InsertPoint 1 13 0 0 + pyraPoints InsertPoint 2 13 1 0 + pyraPoints InsertPoint 3 12 1 0 + pyraPoints InsertPoint 4 12 0 1 + pyraPoints InsertPoint 5 12.5 0 0 + pyraPoints InsertPoint 6 13 0.5 0 + pyraPoints InsertPoint 7 12.5 1 0 + pyraPoints InsertPoint 8 12 0.5 0 + pyraPoints InsertPoint 9 12 0 0.5 + pyraPoints InsertPoint 10 12.5 0 0.5 + pyraPoints InsertPoint 11 12.5 0.5 0.5 + pyraPoints InsertPoint 12 12 0.5 0.5 +vtkFloatArray pyraScalars + pyraScalars SetNumberOfTuples 13 + pyraScalars InsertValue 0 1.0 + pyraScalars InsertValue 1 1.0 + pyraScalars InsertValue 2 1.0 + pyraScalars InsertValue 3 1.0 + pyraScalars InsertValue 4 1.0 + pyraScalars InsertValue 5 1.0 + pyraScalars InsertValue 6 0.0 + pyraScalars InsertValue 7 0.0 + pyraScalars InsertValue 8 0.0 + pyraScalars InsertValue 9 0.0 + pyraScalars InsertValue 10 0.0 + pyraScalars InsertValue 11 0.0 + pyraScalars InsertValue 12 0.0 +vtkQuadraticPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + [aPyramid GetPointIds] SetId 5 5 + [aPyramid GetPointIds] SetId 6 6 + [aPyramid GetPointIds] SetId 7 7 + [aPyramid GetPointIds] SetId 8 8 + [aPyramid GetPointIds] SetId 9 9 + [aPyramid GetPointIds] SetId 10 10 + [aPyramid GetPointIds] SetId 11 11 + [aPyramid GetPointIds] SetId 12 12 + #aPyramid DebugOn + +#puts aPyramid + +vtkUnstructuredGrid aPyraGrid + aPyraGrid Allocate 1 1 + aPyraGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyraGrid SetPoints pyraPoints + [aPyraGrid GetPointData] SetScalars pyraScalars + +#vtkUnstructuredGridWriter writer +# writer SetInput aWedgeGrid +# writer SetFileName foo.vtk +# writer Write + +# Append the quadratic cells together +vtkAppendFilter appendF + appendF AddInput aTriGrid + appendF AddInput aQuadGrid + appendF AddInput aTetGrid + appendF AddInput aHexGrid + appendF AddInput aWedgeGrid + appendF AddInput aPyraGrid + +# Extract the edges +vtkExtractEdges extract + extract SetInputConnection [appendF GetOutputPort] + +vtkShrinkPolyData shrink + shrink SetInputConnection [extract GetOutputPort] + shrink SetShrinkFactor 0.90 + +vtkDataSetMapper aMapper + aMapper SetInputConnection [shrink GetOutputPort] + #aMapper ScalarVisibilityOff + +vtkActor aActor + aActor SetMapper aMapper + [aActor GetProperty] SetRepresentationToWireframe + [aActor GetProperty] SetAmbient 1.0 + +# Create the rendering related stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground .1 .2 .3 +renWin SetSize 400 150 + +# specify properties +ren1 AddActor aActor +renWin Render +[ren1 GetActiveCamera] Dolly 3.0 +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/ExtractTensors.tcl b/Graphics/Testing/Tcl/ExtractTensors.tcl new file mode 100644 index 0000000..43d435c --- /dev/null +++ b/Graphics/Testing/Tcl/ExtractTensors.tcl @@ -0,0 +1,107 @@ +package require vtk +package require vtkinteraction + +# create tensor ellipsoids + +# Create the RenderWindow, Renderer and interactive renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPointLoad ptLoad + ptLoad SetLoadValue 100.0 + ptLoad SetSampleDimensions 30 30 30 + ptLoad ComputeEffectiveStressOn + ptLoad SetModelBounds -10 10 -10 10 -10 10 + +vtkExtractTensorComponents extractTensor + extractTensor SetInputConnection [ptLoad GetOutputPort] + extractTensor ScalarIsEffectiveStress + extractTensor ScalarIsComponent + extractTensor ExtractScalarsOn + extractTensor ExtractVectorsOn + extractTensor ExtractNormalsOff + extractTensor ExtractTCoordsOn + +vtkContourFilter contour + contour SetInputConnection [extractTensor GetOutputPort] + contour SetValue 0 0 + +vtkProbeFilter probe + probe SetInputConnection [contour GetOutputPort] + probe SetSource [ptLoad GetOutput] + +vtkLoopSubdivisionFilter su + su SetInputConnection [probe GetOutputPort] + su SetNumberOfSubdivisions 1 + +vtkPolyDataMapper s1Mapper + s1Mapper SetInputConnection [probe GetOutputPort] +# s1Mapper SetInputConnection [su GetOutputPort] + +vtkActor s1Actor + s1Actor SetMapper s1Mapper + +# +# plane for context +# +vtkImageDataGeometryFilter g + g SetInputConnection [ptLoad GetOutputPort] + g SetExtent 0 100 0 100 0 0 + g Update;#for scalar range + +vtkPolyDataMapper gm + gm SetInputConnection [g GetOutputPort] + eval gm SetScalarRange [[g GetOutput] GetScalarRange] +vtkActor ga + ga SetMapper gm + + eval s1Mapper SetScalarRange [[g GetOutput] GetScalarRange] +# +# Create outline around data +# +vtkOutlineFilter outline + outline SetInputConnection [ptLoad GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 +# +# Create cone indicating application of load +# +vtkConeSource coneSrc + coneSrc SetRadius .5 + coneSrc SetHeight 2 +vtkPolyDataMapper coneMap + coneMap SetInputConnection [coneSrc GetOutputPort] +vtkActor coneActor + coneActor SetMapper coneMap; + coneActor SetPosition 0 0 11 + coneActor RotateY 90 + eval [coneActor GetProperty] SetColor 1 0 0 + +vtkCamera camera + camera SetFocalPoint 0.113766 -1.13665 -1.01919 + camera SetPosition -29.4886 -63.1488 26.5807 + camera SetViewAngle 24.4617 + camera SetViewUp 0.17138 0.331163 0.927879 + camera SetClippingRange 1 100 + +ren1 AddActor s1Actor +ren1 AddActor outlineActor +ren1 AddActor coneActor +ren1 AddActor ga +ren1 SetBackground 1.0 1.0 1.0 +ren1 SetActiveCamera camera + +renWin SetSize 300 300 +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/Hyper.tcl b/Graphics/Testing/Tcl/Hyper.tcl new file mode 100644 index 0000000..36ff68a --- /dev/null +++ b/Graphics/Testing/Tcl/Hyper.tcl @@ -0,0 +1,186 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and interactive renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +set VTK_INTEGRATE_BOTH_DIRECTIONS 2 + +# +# generate tensors +vtkPointLoad ptLoad + ptLoad SetLoadValue 100.0 + ptLoad SetSampleDimensions 20 20 20 + ptLoad ComputeEffectiveStressOn + ptLoad SetModelBounds -10 10 -10 10 -10 10 + + + +# +# If the current directory is writable, then test the witers +# +if {[catch {set channel [open "test.tmp" "w"]}] == 0 } { + close $channel + file delete -force "test.tmp" + + vtkDataSetWriter wSP + wSP SetInputConnection [ptLoad GetOutputPort] + wSP SetFileName "wSP.vtk" + wSP SetTensorsName "pointload" + wSP SetScalarsName "effective_stress" + wSP Write + + vtkDataSetReader rSP + rSP SetFileName "wSP.vtk" + rSP SetTensorsName "pointload" + rSP SetScalarsName "effective_stress" + rSP Update + + set input [rSP GetOutput] + + file delete -force "wSP.vtk" +} else { + set input [ptLoad GetOutput] +} + +# Generate hyperstreamlines +vtkHyperStreamline s1 +s1 SetInput $input +s1 SetStartPosition 9 9 -9 +s1 IntegrateMinorEigenvector +s1 SetMaximumPropagationDistance 18.0 +s1 SetIntegrationStepLength 0.1 +s1 SetStepLength 0.01 +s1 SetRadius 0.25 +s1 SetNumberOfSides 18 +s1 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS +s1 Update + +# Map hyperstreamlines +vtkLogLookupTable lut + lut SetHueRange .6667 0.0 +vtkPolyDataMapper s1Mapper + s1Mapper SetInputConnection [s1 GetOutputPort] + s1Mapper SetLookupTable lut + ptLoad Update;#force update for scalar range + eval s1Mapper SetScalarRange [[ptLoad GetOutput] GetScalarRange] +vtkActor s1Actor + s1Actor SetMapper s1Mapper + +vtkHyperStreamline s2 + s2 SetInput $input + s2 SetStartPosition -9 -9 -9 + s2 IntegrateMinorEigenvector + s2 SetMaximumPropagationDistance 18.0 + s2 SetIntegrationStepLength 0.1 + s2 SetStepLength 0.01 + s2 SetRadius 0.25 + s2 SetNumberOfSides 18 + s2 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS + s2 Update +vtkPolyDataMapper s2Mapper + s2Mapper SetInputConnection [s2 GetOutputPort] + s2Mapper SetLookupTable lut + eval s2Mapper SetScalarRange [$input GetScalarRange] +vtkActor s2Actor + s2Actor SetMapper s2Mapper + +vtkHyperStreamline s3 + s3 SetInput $input + s3 SetStartPosition 9 -9 -9 + s3 IntegrateMinorEigenvector + s3 SetMaximumPropagationDistance 18.0 + s3 SetIntegrationStepLength 0.1 + s3 SetStepLength 0.01 + s3 SetRadius 0.25 + s3 SetNumberOfSides 18 + s3 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS + s3 Update +vtkPolyDataMapper s3Mapper + s3Mapper SetInputConnection [s3 GetOutputPort] + s3Mapper SetLookupTable lut + eval s3Mapper SetScalarRange [$input GetScalarRange] +vtkActor s3Actor + s3Actor SetMapper s3Mapper + +vtkHyperStreamline s4 + s4 SetInput $input + s4 SetStartPosition -9 9 -9 + s4 IntegrateMinorEigenvector + s4 SetMaximumPropagationDistance 18.0 + s4 SetIntegrationStepLength 0.1 + s4 SetStepLength 0.01 + s4 SetRadius 0.25 + s4 SetNumberOfSides 18 + s4 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS + s4 Update +vtkPolyDataMapper s4Mapper + s4Mapper SetInputConnection [s4 GetOutputPort] + s4Mapper SetLookupTable lut + eval s4Mapper SetScalarRange [$input GetScalarRange] +vtkActor s4Actor + s4Actor SetMapper s4Mapper + +# plane for context +# +vtkImageDataGeometryFilter g + g SetInput $input + g SetExtent 0 100 0 100 0 0 + g Update;#for scalar range +vtkPolyDataMapper gm + gm SetInputConnection [g GetOutputPort] + eval gm SetScalarRange [[g GetOutput] GetScalarRange] +vtkActor ga + ga SetMapper gm + +# Create outline around data +# +vtkOutlineFilter outline + outline SetInput $input +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# Create cone indicating application of load +# +vtkConeSource coneSrc + coneSrc SetRadius .5 + coneSrc SetHeight 2 +vtkPolyDataMapper coneMap + coneMap SetInputConnection [coneSrc GetOutputPort] +vtkActor coneActor + coneActor SetMapper coneMap; + coneActor SetPosition 0 0 11 + coneActor RotateY 90 + eval [coneActor GetProperty] SetColor 1 0 0 + +vtkCamera camera + camera SetFocalPoint 0.113766 -1.13665 -1.01919 + camera SetPosition -29.4886 -63.1488 26.5807 + camera SetViewAngle 24.4617 + camera SetViewUp 0.17138 0.331163 0.927879 + camera SetClippingRange 1 100 + +ren1 AddActor s1Actor +ren1 AddActor s2Actor +ren1 AddActor s3Actor +ren1 AddActor s4Actor +ren1 AddActor outlineActor +ren1 AddActor coneActor +ren1 AddActor ga +ren1 SetBackground 1.0 1.0 1.0 +ren1 SetActiveCamera camera + +renWin SetSize 300 300 +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/HyperScalarBar.tcl b/Graphics/Testing/Tcl/HyperScalarBar.tcl new file mode 100644 index 0000000..4a06fe5 --- /dev/null +++ b/Graphics/Testing/Tcl/HyperScalarBar.tcl @@ -0,0 +1,172 @@ +# Test the scalar bar actor using a logarithmic lookup table +# +package require vtk +package require vtkinteraction + +set VTK_INTEGRATE_BOTH_DIRECTIONS 2 + +# +# generate tensors +vtkPointLoad ptLoad + ptLoad SetLoadValue 100.0 + ptLoad SetSampleDimensions 20 20 20 + ptLoad ComputeEffectiveStressOn + ptLoad SetModelBounds -10 10 -10 10 -10 10 + +# Generate hyperstreamlines +vtkHyperStreamline s1 + s1 SetInputConnection [ptLoad GetOutputPort] + s1 SetStartPosition 9 9 -9 + s1 IntegrateMinorEigenvector + s1 SetMaximumPropagationDistance 18.0 + s1 SetIntegrationStepLength 0.1 + s1 SetStepLength 0.01 + s1 SetRadius 0.25 + s1 SetNumberOfSides 18 + s1 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS + s1 Update + +# Map hyperstreamlines +vtkLogLookupTable lut + lut SetHueRange .6667 0.0 +vtkScalarBarActor scalarBar + scalarBar SetLookupTable lut + scalarBar SetTitle "Stress" + [scalarBar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport + [scalarBar GetPositionCoordinate] SetValue 0.1 0.05 + scalarBar SetOrientationToVertical + scalarBar SetWidth 0.1 + scalarBar SetHeight 0.9 + scalarBar SetPosition 0.01 0.1 + scalarBar SetLabelFormat "%-#6.3f" + [scalarBar GetLabelTextProperty] SetColor 1 0 0 + [scalarBar GetTitleTextProperty] SetColor 1 0 0 +vtkPolyDataMapper s1Mapper + s1Mapper SetInputConnection [s1 GetOutputPort] + s1Mapper SetLookupTable lut + ptLoad Update;#force update for scalar range + eval s1Mapper SetScalarRange [[ptLoad GetOutput] GetScalarRange] +vtkActor s1Actor + s1Actor SetMapper s1Mapper + +vtkHyperStreamline s2 + s2 SetInputConnection [ptLoad GetOutputPort] + s2 SetStartPosition -9 -9 -9 + s2 IntegrateMinorEigenvector + s2 SetMaximumPropagationDistance 18.0 + s2 SetIntegrationStepLength 0.1 + s2 SetStepLength 0.01 + s2 SetRadius 0.25 + s2 SetNumberOfSides 18 + s2 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS + s2 Update +vtkPolyDataMapper s2Mapper + s2Mapper SetInputConnection [s2 GetOutputPort] + s2Mapper SetLookupTable lut + eval s2Mapper SetScalarRange [[ptLoad GetOutput] GetScalarRange] +vtkActor s2Actor + s2Actor SetMapper s2Mapper + +vtkHyperStreamline s3 + s3 SetInputConnection [ptLoad GetOutputPort] + s3 SetStartPosition 9 -9 -9 + s3 IntegrateMinorEigenvector + s3 SetMaximumPropagationDistance 18.0 + s3 SetIntegrationStepLength 0.1 + s3 SetStepLength 0.01 + s3 SetRadius 0.25 + s3 SetNumberOfSides 18 + s3 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS + s3 Update +vtkPolyDataMapper s3Mapper + s3Mapper SetInputConnection [s3 GetOutputPort] + s3Mapper SetLookupTable lut + eval s3Mapper SetScalarRange [[ptLoad GetOutput] GetScalarRange] +vtkActor s3Actor + s3Actor SetMapper s3Mapper + +vtkHyperStreamline s4 + s4 SetInputConnection [ptLoad GetOutputPort] + s4 SetStartPosition -9 9 -9 + s4 IntegrateMinorEigenvector + s4 SetMaximumPropagationDistance 18.0 + s4 SetIntegrationStepLength 0.1 + s4 SetStepLength 0.01 + s4 SetRadius 0.25 + s4 SetNumberOfSides 18 + s4 SetIntegrationDirection $VTK_INTEGRATE_BOTH_DIRECTIONS + s4 Update +vtkPolyDataMapper s4Mapper + s4Mapper SetInputConnection [s4 GetOutputPort] + s4Mapper SetLookupTable lut + eval s4Mapper SetScalarRange [[ptLoad GetOutput] GetScalarRange] +vtkActor s4Actor + s4Actor SetMapper s4Mapper + +# plane for context +# +vtkImageDataGeometryFilter g + g SetInputConnection [ptLoad GetOutputPort] + g SetExtent 0 100 0 100 0 0 + g Update;#for scalar range +vtkPolyDataMapper gm + gm SetInputConnection [g GetOutputPort] + eval gm SetScalarRange [[g GetOutput] GetScalarRange] +vtkActor ga + ga SetMapper gm + +# Create outline around data +# +vtkOutlineFilter outline + outline SetInputConnection [ptLoad GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# Create cone indicating application of load +# +vtkConeSource coneSrc + coneSrc SetRadius .5 + coneSrc SetHeight 2 +vtkPolyDataMapper coneMap + coneMap SetInputConnection [coneSrc GetOutputPort] +vtkActor coneActor + coneActor SetMapper coneMap; + coneActor SetPosition 0 0 11 + coneActor RotateY 90 + eval [coneActor GetProperty] SetColor 1 0 0 + +# Create the rendering infrastructure +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkCamera camera + camera SetFocalPoint 0.113766 -1.13665 -1.01919 + camera SetPosition -29.4886 -63.1488 26.5807 + camera SetViewAngle 24.4617 + camera SetViewUp 0.17138 0.331163 0.927879 + camera SetClippingRange 1 100 + +ren1 AddActor2D scalarBar +ren1 AddActor s1Actor +ren1 AddActor s2Actor +ren1 AddActor s3Actor +ren1 AddActor s4Actor +ren1 AddActor outlineActor +ren1 AddActor coneActor +ren1 AddActor ga +ren1 SetBackground 1.0 1.0 1.0 +ren1 SetActiveCamera camera + +renWin SetSize 300 300 +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/KlineBottle.tcl b/Graphics/Testing/Tcl/KlineBottle.tcl new file mode 100644 index 0000000..8957fb7 --- /dev/null +++ b/Graphics/Testing/Tcl/KlineBottle.tcl @@ -0,0 +1,360 @@ +package require vtk +package require vtkinteraction + +vtkPoints points +points InsertNextPoint 0 -16 0 +points InsertNextPoint 0 0 -14 +points InsertNextPoint 0 0 14 +points InsertNextPoint 14 0 0 +points InsertNextPoint 10 20 -10 +points InsertNextPoint 10 20 10 +points InsertNextPoint 10 -20 -10 +points InsertNextPoint 10 -20 10 +points InsertNextPoint -10 -20 -10 +points InsertNextPoint -10 -20 10 +points InsertNextPoint -10 20 -10 +points InsertNextPoint -10 20 10 +points InsertNextPoint -2 27 0 +points InsertNextPoint 0 27 2 +points InsertNextPoint 0 27 -2 +points InsertNextPoint 2 27 0 +points InsertNextPoint -14 4 -1 +points InsertNextPoint -14 3 0 +points InsertNextPoint -14 5 0 +points InsertNextPoint -14 4 1 +points InsertNextPoint -1 38 -2 +points InsertNextPoint -1 38 2 +points InsertNextPoint 2 35 -2 +points InsertNextPoint 2 35 2 +points InsertNextPoint 17 42 0 +points InsertNextPoint 15 40 2 +points InsertNextPoint 15 39 -2 +points InsertNextPoint 13 37 0 +points InsertNextPoint 19 -2 -2 +points InsertNextPoint 19 -2 2 +points InsertNextPoint 15 2 -2 +points InsertNextPoint 15 2 2 + +vtkCellArray faces +faces InsertNextCell 3 +faces InsertCellPoint 3 +faces InsertCellPoint 4 +faces InsertCellPoint 5 +faces InsertNextCell 3 +faces InsertCellPoint 3 +faces InsertCellPoint 5 +faces InsertCellPoint 7 +faces InsertNextCell 3 +faces InsertCellPoint 3 +faces InsertCellPoint 7 +faces InsertCellPoint 6 +faces InsertNextCell 3 +faces InsertCellPoint 3 +faces InsertCellPoint 6 +faces InsertCellPoint 4 +faces InsertNextCell 3 +faces InsertCellPoint 0 +faces InsertCellPoint 6 +faces InsertCellPoint 7 +faces InsertNextCell 3 +faces InsertCellPoint 0 +faces InsertCellPoint 7 +faces InsertCellPoint 9 +faces InsertNextCell 3 +faces InsertCellPoint 0 +faces InsertCellPoint 9 +faces InsertCellPoint 8 +faces InsertNextCell 3 +faces InsertCellPoint 0 +faces InsertCellPoint 8 +faces InsertCellPoint 6 +faces InsertNextCell 3 +faces InsertCellPoint 1 +faces InsertCellPoint 4 +faces InsertCellPoint 6 +faces InsertNextCell 3 +faces InsertCellPoint 1 +faces InsertCellPoint 6 +faces InsertCellPoint 8 +faces InsertNextCell 3 +faces InsertCellPoint 1 +faces InsertCellPoint 8 +faces InsertCellPoint 10 +faces InsertNextCell 3 +faces InsertCellPoint 1 +faces InsertCellPoint 10 +faces InsertCellPoint 4 +faces InsertNextCell 3 +faces InsertCellPoint 2 +faces InsertCellPoint 11 +faces InsertCellPoint 9 +faces InsertNextCell 3 +faces InsertCellPoint 2 +faces InsertCellPoint 9 +faces InsertCellPoint 7 +faces InsertNextCell 3 +faces InsertCellPoint 2 +faces InsertCellPoint 7 +faces InsertCellPoint 5 +faces InsertNextCell 3 +faces InsertCellPoint 2 +faces InsertCellPoint 5 +faces InsertCellPoint 11 +faces InsertNextCell 3 +faces InsertCellPoint 4 +faces InsertCellPoint 15 +faces InsertCellPoint 5 +faces InsertNextCell 3 +faces InsertCellPoint 4 +faces InsertCellPoint 14 +faces InsertCellPoint 15 +faces InsertNextCell 3 +faces InsertCellPoint 5 +faces InsertCellPoint 13 +faces InsertCellPoint 11 +faces InsertNextCell 3 +faces InsertCellPoint 5 +faces InsertCellPoint 15 +faces InsertCellPoint 13 +faces InsertNextCell 3 +faces InsertCellPoint 11 +faces InsertCellPoint 12 +faces InsertCellPoint 10 +faces InsertNextCell 3 +faces InsertCellPoint 11 +faces InsertCellPoint 13 +faces InsertCellPoint 12 +faces InsertNextCell 3 +faces InsertCellPoint 10 +faces InsertCellPoint 14 +faces InsertCellPoint 4 +faces InsertNextCell 3 +faces InsertCellPoint 10 +faces InsertCellPoint 12 +faces InsertCellPoint 14 +faces InsertNextCell 3 +faces InsertCellPoint 8 +faces InsertCellPoint 17 +faces InsertCellPoint 16 +faces InsertNextCell 3 +faces InsertCellPoint 8 +faces InsertCellPoint 9 +faces InsertCellPoint 17 +faces InsertNextCell 3 +faces InsertCellPoint 9 +faces InsertCellPoint 19 +faces InsertCellPoint 17 +faces InsertNextCell 3 +faces InsertCellPoint 9 +faces InsertCellPoint 11 +faces InsertCellPoint 19 +faces InsertNextCell 3 +faces InsertCellPoint 11 +faces InsertCellPoint 18 +faces InsertCellPoint 19 +faces InsertNextCell 3 +faces InsertCellPoint 11 +faces InsertCellPoint 10 +faces InsertCellPoint 18 +faces InsertNextCell 3 +faces InsertCellPoint 10 +faces InsertCellPoint 16 +faces InsertCellPoint 18 +faces InsertNextCell 3 +faces InsertCellPoint 10 +faces InsertCellPoint 8 +faces InsertCellPoint 16 +faces InsertNextCell 3 +faces InsertCellPoint 13 +faces InsertCellPoint 21 +faces InsertCellPoint 12 +faces InsertNextCell 3 +faces InsertCellPoint 12 +faces InsertCellPoint 21 +faces InsertCellPoint 20 +faces InsertNextCell 3 +faces InsertCellPoint 12 +faces InsertCellPoint 20 +faces InsertCellPoint 14 +faces InsertNextCell 3 +faces InsertCellPoint 14 +faces InsertCellPoint 20 +faces InsertCellPoint 22 +faces InsertNextCell 3 +faces InsertCellPoint 14 +faces InsertCellPoint 22 +faces InsertCellPoint 15 +faces InsertNextCell 3 +faces InsertCellPoint 15 +faces InsertCellPoint 22 +faces InsertCellPoint 23 +faces InsertNextCell 3 +faces InsertCellPoint 15 +faces InsertCellPoint 23 +faces InsertCellPoint 13 +faces InsertNextCell 3 +faces InsertCellPoint 13 +faces InsertCellPoint 23 +faces InsertCellPoint 21 +faces InsertNextCell 3 +faces InsertCellPoint 21 +faces InsertCellPoint 25 +faces InsertCellPoint 24 +faces InsertNextCell 3 +faces InsertCellPoint 21 +faces InsertCellPoint 24 +faces InsertCellPoint 20 +faces InsertNextCell 3 +faces InsertCellPoint 20 +faces InsertCellPoint 24 +faces InsertCellPoint 26 +faces InsertNextCell 3 +faces InsertCellPoint 20 +faces InsertCellPoint 26 +faces InsertCellPoint 22 +faces InsertNextCell 3 +faces InsertCellPoint 22 +faces InsertCellPoint 26 +faces InsertCellPoint 27 +faces InsertNextCell 3 +faces InsertCellPoint 22 +faces InsertCellPoint 27 +faces InsertCellPoint 23 +faces InsertNextCell 3 +faces InsertCellPoint 23 +faces InsertCellPoint 27 +faces InsertCellPoint 25 +faces InsertNextCell 3 +faces InsertCellPoint 23 +faces InsertCellPoint 25 +faces InsertCellPoint 21 +faces InsertNextCell 3 +faces InsertCellPoint 25 +faces InsertCellPoint 29 +faces InsertCellPoint 24 +faces InsertNextCell 3 +faces InsertCellPoint 24 +faces InsertCellPoint 29 +faces InsertCellPoint 28 +faces InsertNextCell 3 +faces InsertCellPoint 24 +faces InsertCellPoint 28 +faces InsertCellPoint 26 +faces InsertNextCell 3 +faces InsertCellPoint 26 +faces InsertCellPoint 28 +faces InsertCellPoint 30 +faces InsertNextCell 3 +faces InsertCellPoint 26 +faces InsertCellPoint 30 +faces InsertCellPoint 27 +faces InsertNextCell 3 +faces InsertCellPoint 27 +faces InsertCellPoint 30 +faces InsertCellPoint 31 +faces InsertNextCell 3 +faces InsertCellPoint 27 +faces InsertCellPoint 31 +faces InsertCellPoint 25 +faces InsertNextCell 3 +faces InsertCellPoint 25 +faces InsertCellPoint 31 +faces InsertCellPoint 29 +faces InsertNextCell 3 +faces InsertCellPoint 29 +faces InsertCellPoint 19 +faces InsertCellPoint 17 +faces InsertNextCell 3 +faces InsertCellPoint 29 +faces InsertCellPoint 17 +faces InsertCellPoint 28 +faces InsertNextCell 3 +faces InsertCellPoint 28 +faces InsertCellPoint 17 +faces InsertCellPoint 16 +faces InsertNextCell 3 +faces InsertCellPoint 28 +faces InsertCellPoint 16 +faces InsertCellPoint 30 +faces InsertNextCell 3 +faces InsertCellPoint 30 +faces InsertCellPoint 16 +faces InsertCellPoint 18 +faces InsertNextCell 3 +faces InsertCellPoint 30 +faces InsertCellPoint 18 +faces InsertCellPoint 31 +faces InsertNextCell 3 +faces InsertCellPoint 31 +faces InsertCellPoint 18 +faces InsertCellPoint 19 +faces InsertNextCell 3 +faces InsertCellPoint 31 +faces InsertCellPoint 19 +faces InsertCellPoint 29 + + +vtkPolyData model + model SetPolys faces + model SetPoints points + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +#vtkButterflySubdivisionFilter subdivide +vtkLoopSubdivisionFilter subdivide + subdivide SetInput model + subdivide SetNumberOfSubdivisions 4 + +vtkDataSetMapper mapper + mapper SetInputConnection [subdivide GetOutputPort] + +vtkLODActor rose + rose SetMapper mapper + +vtkFeatureEdges fe + fe SetInputConnection [subdivide GetOutputPort] + fe SetFeatureAngle 100 + +vtkPolyDataMapper feMapper + feMapper SetInputConnection [fe GetOutputPort] + +vtkActor edges + edges SetMapper feMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor rose +#ren1 AddActor edges +vtkProperty backP + backP SetDiffuseColor 1 1 .3 +rose SetBackfaceProperty backP + +[rose GetProperty] SetDiffuseColor 1 .4 .3 +[rose GetProperty] SetSpecular .4 +[rose GetProperty] SetDiffuse .8 +[rose GetProperty] SetSpecularPower 40 + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 4.5 +$cam1 Azimuth -90 +ren1 ResetCameraClippingRange +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/LineIntersectQuadraticCells.tcl b/Graphics/Testing/Tcl/LineIntersectQuadraticCells.tcl new file mode 100644 index 0000000..58b3144 --- /dev/null +++ b/Graphics/Testing/Tcl/LineIntersectQuadraticCells.tcl @@ -0,0 +1,502 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Contour every quadratic cell type + +# Create a scene with one of each cell type. +# QuadraticEdge +vtkPoints edgePoints + edgePoints SetNumberOfPoints 3 + edgePoints InsertPoint 0 0 0 0 + edgePoints InsertPoint 1 1.0 0 0 + edgePoints InsertPoint 2 0.5 0.25 0 +vtkFloatArray edgeScalars + edgeScalars SetNumberOfTuples 3 + edgeScalars InsertValue 0 0.0 + edgeScalars InsertValue 1 0.0 + edgeScalars InsertValue 2 0.9 +vtkQuadraticEdge aEdge + [aEdge GetPointIds] SetId 0 0 + [aEdge GetPointIds] SetId 1 1 + [aEdge GetPointIds] SetId 2 2 +vtkUnstructuredGrid aEdgeGrid + aEdgeGrid Allocate 1 1 + aEdgeGrid InsertNextCell [aEdge GetCellType] [aEdge GetPointIds] + aEdgeGrid SetPoints edgePoints + [aEdgeGrid GetPointData] SetScalars edgeScalars +vtkDataSetMapper aEdgeMapper + aEdgeMapper SetInput aEdgeGrid + aEdgeMapper ScalarVisibilityOff +vtkActor aEdgeActor + aEdgeActor SetMapper aEdgeMapper + [aEdgeActor GetProperty] SetRepresentationToWireframe + [aEdgeActor GetProperty] SetAmbient 1.0 + +# Quadratic triangle +vtkPoints triPoints + triPoints SetNumberOfPoints 6 + triPoints InsertPoint 0 0.0 0.0 0.0 + triPoints InsertPoint 1 1.0 0.0 0.0 + triPoints InsertPoint 2 0.5 0.8 0.0 + triPoints InsertPoint 3 0.5 0.0 0.0 + triPoints InsertPoint 4 0.75 0.4 0.0 + triPoints InsertPoint 5 0.25 0.4 0.0 +vtkFloatArray triScalars + triScalars SetNumberOfTuples 6 + triScalars InsertValue 0 0.0 + triScalars InsertValue 1 0.0 + triScalars InsertValue 2 0.0 + triScalars InsertValue 3 1.0 + triScalars InsertValue 4 0.0 + triScalars InsertValue 5 0.0 +vtkQuadraticTriangle aTri + [aTri GetPointIds] SetId 0 0 + [aTri GetPointIds] SetId 1 1 + [aTri GetPointIds] SetId 2 2 + [aTri GetPointIds] SetId 3 3 + [aTri GetPointIds] SetId 4 4 + [aTri GetPointIds] SetId 5 5 +vtkUnstructuredGrid aTriGrid + aTriGrid Allocate 1 1 + aTriGrid InsertNextCell [aTri GetCellType] [aTri GetPointIds] + aTriGrid SetPoints triPoints + [aTriGrid GetPointData] SetScalars triScalars +vtkDataSetMapper aTriMapper + aTriMapper SetInput aTriGrid + aTriMapper ScalarVisibilityOff +vtkActor aTriActor + aTriActor SetMapper aTriMapper + [aTriActor GetProperty] SetRepresentationToWireframe + [aTriActor GetProperty] SetAmbient 1.0 + +# Quadratic quadrilateral +vtkPoints quadPoints + quadPoints SetNumberOfPoints 8 + quadPoints InsertPoint 0 0.0 0.0 0.0 + quadPoints InsertPoint 1 1.0 0.0 0.0 + quadPoints InsertPoint 2 1.0 1.0 0.0 + quadPoints InsertPoint 3 0.0 1.0 0.0 + quadPoints InsertPoint 4 0.5 0.0 0.0 + quadPoints InsertPoint 5 1.0 0.5 0.0 + quadPoints InsertPoint 6 0.5 1.0 0.0 + quadPoints InsertPoint 7 0.0 0.5 0.0 +vtkFloatArray quadScalars + quadScalars SetNumberOfTuples 8 + quadScalars InsertValue 0 0.0 + quadScalars InsertValue 1 0.0 + quadScalars InsertValue 2 1.0 + quadScalars InsertValue 3 1.0 + quadScalars InsertValue 4 1.0 + quadScalars InsertValue 5 0.0 + quadScalars InsertValue 6 0.0 + quadScalars InsertValue 7 0.0 +vtkQuadraticQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + [aQuad GetPointIds] SetId 4 4 + [aQuad GetPointIds] SetId 5 5 + [aQuad GetPointIds] SetId 6 6 + [aQuad GetPointIds] SetId 7 7 +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + [aQuadGrid GetPointData] SetScalars quadScalars +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid + aQuadMapper ScalarVisibilityOff +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + [aQuadActor GetProperty] SetRepresentationToWireframe + [aQuadActor GetProperty] SetAmbient 1.0 + +# Quadratic tetrahedron +vtkPoints tetPoints + tetPoints SetNumberOfPoints 10 + tetPoints InsertPoint 0 0.0 0.0 0.0 + tetPoints InsertPoint 1 1.0 0.0 0.0 + tetPoints InsertPoint 2 0.5 0.8 0.0 + tetPoints InsertPoint 3 0.5 0.4 1.0 + tetPoints InsertPoint 4 0.5 0.0 0.0 + tetPoints InsertPoint 5 0.75 0.4 0.0 + tetPoints InsertPoint 6 0.25 0.4 0.0 + tetPoints InsertPoint 7 0.25 0.2 0.5 + tetPoints InsertPoint 8 0.75 0.2 0.5 + tetPoints InsertPoint 9 0.50 0.6 0.5 +vtkFloatArray tetScalars + tetScalars SetNumberOfTuples 10 + tetScalars InsertValue 0 1.0 + tetScalars InsertValue 1 1.0 + tetScalars InsertValue 2 1.0 + tetScalars InsertValue 3 1.0 + tetScalars InsertValue 4 0.0 + tetScalars InsertValue 5 0.0 + tetScalars InsertValue 6 0.0 + tetScalars InsertValue 7 0.0 + tetScalars InsertValue 8 0.0 + tetScalars InsertValue 9 0.0 +vtkQuadraticTetra aTet + [aTet GetPointIds] SetId 0 0 + [aTet GetPointIds] SetId 1 1 + [aTet GetPointIds] SetId 2 2 + [aTet GetPointIds] SetId 3 3 + [aTet GetPointIds] SetId 4 4 + [aTet GetPointIds] SetId 5 5 + [aTet GetPointIds] SetId 6 6 + [aTet GetPointIds] SetId 7 7 + [aTet GetPointIds] SetId 8 8 + [aTet GetPointIds] SetId 9 9 +vtkUnstructuredGrid aTetGrid + aTetGrid Allocate 1 1 + aTetGrid InsertNextCell [aTet GetCellType] [aTet GetPointIds] + aTetGrid SetPoints tetPoints + [aTetGrid GetPointData] SetScalars tetScalars +vtkDataSetMapper aTetMapper + aTetMapper SetInput aTetGrid + aTetMapper ScalarVisibilityOff +vtkActor aTetActor + aTetActor SetMapper aTetMapper + [aTetActor GetProperty] SetRepresentationToWireframe + [aTetActor GetProperty] SetAmbient 1.0 + +# Quadratic hexahedron +vtkPoints hexPoints + hexPoints SetNumberOfPoints 20 + hexPoints InsertPoint 0 0 0 0 + hexPoints InsertPoint 1 1 0 0 + hexPoints InsertPoint 2 1 1 0 + hexPoints InsertPoint 3 0 1 0 + hexPoints InsertPoint 4 0 0 1 + hexPoints InsertPoint 5 1 0 1 + hexPoints InsertPoint 6 1 1 1 + hexPoints InsertPoint 7 0 1 1 + hexPoints InsertPoint 8 0.5 0 0 + hexPoints InsertPoint 9 1 0.5 0 + hexPoints InsertPoint 10 0.5 1 0 + hexPoints InsertPoint 11 0 0.5 0 + hexPoints InsertPoint 12 0.5 0 1 + hexPoints InsertPoint 13 1 0.5 1 + hexPoints InsertPoint 14 0.5 1 1 + hexPoints InsertPoint 15 0 0.5 1 + hexPoints InsertPoint 16 0 0 0.5 + hexPoints InsertPoint 17 1 0 0.5 + hexPoints InsertPoint 18 1 1 0.5 + hexPoints InsertPoint 19 0 1 0.5 +vtkFloatArray hexScalars + hexScalars SetNumberOfTuples 20 + hexScalars InsertValue 0 1.0 + hexScalars InsertValue 1 1.0 + hexScalars InsertValue 2 1.0 + hexScalars InsertValue 3 1.0 + hexScalars InsertValue 4 1.0 + hexScalars InsertValue 5 1.0 + hexScalars InsertValue 6 1.0 + hexScalars InsertValue 7 1.0 + hexScalars InsertValue 8 0.0 + hexScalars InsertValue 9 0.0 + hexScalars InsertValue 10 0.0 + hexScalars InsertValue 11 0.0 + hexScalars InsertValue 12 0.0 + hexScalars InsertValue 13 0.0 + hexScalars InsertValue 14 0.0 + hexScalars InsertValue 15 0.0 + hexScalars InsertValue 16 0.0 + hexScalars InsertValue 17 0.0 + hexScalars InsertValue 18 0.0 + hexScalars InsertValue 19 0.0 +vtkQuadraticHexahedron aHex + [aHex GetPointIds] SetId 0 0 + [aHex GetPointIds] SetId 1 1 + [aHex GetPointIds] SetId 2 2 + [aHex GetPointIds] SetId 3 3 + [aHex GetPointIds] SetId 4 4 + [aHex GetPointIds] SetId 5 5 + [aHex GetPointIds] SetId 6 6 + [aHex GetPointIds] SetId 7 7 + [aHex GetPointIds] SetId 8 8 + [aHex GetPointIds] SetId 9 9 + [aHex GetPointIds] SetId 10 10 + [aHex GetPointIds] SetId 11 11 + [aHex GetPointIds] SetId 12 12 + [aHex GetPointIds] SetId 13 13 + [aHex GetPointIds] SetId 14 14 + [aHex GetPointIds] SetId 15 15 + [aHex GetPointIds] SetId 16 16 + [aHex GetPointIds] SetId 17 17 + [aHex GetPointIds] SetId 18 18 + [aHex GetPointIds] SetId 19 19 +vtkUnstructuredGrid aHexGrid + aHexGrid Allocate 1 1 + aHexGrid InsertNextCell [aHex GetCellType] [aHex GetPointIds] + aHexGrid SetPoints hexPoints + [aHexGrid GetPointData] SetScalars hexScalars +vtkDataSetMapper aHexMapper + aHexMapper SetInput aHexGrid + aHexMapper ScalarVisibilityOff +vtkActor aHexActor + aHexActor SetMapper aHexMapper + [aHexActor GetProperty] SetRepresentationToWireframe + [aHexActor GetProperty] SetAmbient 1.0 + +# Quadratic wedge +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 15 + wedgePoints InsertPoint 0 0 0 0 + wedgePoints InsertPoint 1 1 0 0 + wedgePoints InsertPoint 2 0 1 0 + wedgePoints InsertPoint 3 0 0 1 + wedgePoints InsertPoint 4 1 0 1 + wedgePoints InsertPoint 5 0 1 1 + wedgePoints InsertPoint 6 0.5 0 0 + wedgePoints InsertPoint 7 0.5 0.5 0 + wedgePoints InsertPoint 8 0 0.5 0 + wedgePoints InsertPoint 9 0.5 0 1 + wedgePoints InsertPoint 10 0.5 0.5 1 + wedgePoints InsertPoint 11 0 0.5 1 + wedgePoints InsertPoint 12 0 0 0.5 + wedgePoints InsertPoint 13 1 0 0.5 + wedgePoints InsertPoint 14 0 1 0.5 +vtkFloatArray wedgeScalars + wedgeScalars SetNumberOfTuples 15 + wedgeScalars InsertValue 0 1.0 + wedgeScalars InsertValue 1 1.0 + wedgeScalars InsertValue 2 1.0 + wedgeScalars InsertValue 3 1.0 + wedgeScalars InsertValue 4 1.0 + wedgeScalars InsertValue 5 1.0 + wedgeScalars InsertValue 6 1.0 + wedgeScalars InsertValue 7 1.0 + wedgeScalars InsertValue 8 0.0 + wedgeScalars InsertValue 9 0.0 + wedgeScalars InsertValue 10 0.0 + wedgeScalars InsertValue 11 0.0 + wedgeScalars InsertValue 12 0.0 + wedgeScalars InsertValue 13 0.0 + wedgeScalars InsertValue 14 0.0 +vtkQuadraticWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + [aWedge GetPointIds] SetId 6 6 + [aWedge GetPointIds] SetId 7 7 + [aWedge GetPointIds] SetId 8 8 + [aWedge GetPointIds] SetId 9 9 + [aWedge GetPointIds] SetId 10 10 + [aWedge GetPointIds] SetId 11 11 + [aWedge GetPointIds] SetId 12 12 + [aWedge GetPointIds] SetId 13 13 + [aWedge GetPointIds] SetId 14 14 +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + [aWedgeGrid GetPointData] SetScalars wedgeScalars +vtkClipDataSet wedgeContours + wedgeContours SetInput aWedgeGrid + wedgeContours SetValue 0.5 +vtkDataSetMapper aWedgeContourMapper + aWedgeContourMapper SetInputConnection [wedgeContours GetOutputPort] + aWedgeContourMapper ScalarVisibilityOff +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeGrid + aWedgeMapper ScalarVisibilityOff +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + [aWedgeActor GetProperty] SetRepresentationToWireframe + [aWedgeActor GetProperty] SetAmbient 1.0 +vtkActor aWedgeContourActor + aWedgeContourActor SetMapper aWedgeContourMapper + [aWedgeContourActor GetProperty] SetAmbient 1.0 + +# Quadratic pyramid +vtkPoints pyraPoints + pyraPoints SetNumberOfPoints 13 + pyraPoints InsertPoint 0 0 0 0 + pyraPoints InsertPoint 1 1 0 0 + pyraPoints InsertPoint 2 1 1 0 + pyraPoints InsertPoint 3 0 1 0 + pyraPoints InsertPoint 4 0 0 1 + pyraPoints InsertPoint 5 0.5 0 0 + pyraPoints InsertPoint 6 1 0.5 0 + pyraPoints InsertPoint 7 0.5 1 0 + pyraPoints InsertPoint 8 0 0.5 0 + pyraPoints InsertPoint 9 0 0 0.5 + pyraPoints InsertPoint 10 0.5 0 0.5 + pyraPoints InsertPoint 11 0.5 0.5 0.5 + pyraPoints InsertPoint 12 0 0.5 0.5 +vtkFloatArray pyraScalars + pyraScalars SetNumberOfTuples 13 + pyraScalars InsertValue 0 1.0 + pyraScalars InsertValue 1 1.0 + pyraScalars InsertValue 2 1.0 + pyraScalars InsertValue 3 1.0 + pyraScalars InsertValue 4 1.0 + pyraScalars InsertValue 5 1.0 + pyraScalars InsertValue 6 1.0 + pyraScalars InsertValue 7 1.0 + pyraScalars InsertValue 8 0.0 + pyraScalars InsertValue 9 0.0 + pyraScalars InsertValue 10 0.0 + pyraScalars InsertValue 11 0.0 + pyraScalars InsertValue 12 0.0 +vtkQuadraticPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + [aPyramid GetPointIds] SetId 5 5 + [aPyramid GetPointIds] SetId 6 6 + [aPyramid GetPointIds] SetId 7 7 + [aPyramid GetPointIds] SetId 8 8 + [aPyramid GetPointIds] SetId 9 9 + [aPyramid GetPointIds] SetId 10 10 + [aPyramid GetPointIds] SetId 11 11 + [aPyramid GetPointIds] SetId 12 12 +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyraPoints + [aPyramidGrid GetPointData] SetScalars pyraScalars +vtkClipDataSet pyraContours + pyraContours SetInput aPyramidGrid + pyraContours SetValue 0.5 +vtkDataSetMapper aPyramidContourMapper + aPyramidContourMapper SetInputConnection [pyraContours GetOutputPort] + aPyramidContourMapper ScalarVisibilityOff +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid + aPyramidMapper ScalarVisibilityOff +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + [aPyramidActor GetProperty] SetRepresentationToWireframe + [aPyramidActor GetProperty] SetAmbient 1.0 +vtkActor aPyramidContourActor + aPyramidContourActor SetMapper aPyramidContourMapper + [aPyramidContourActor GetProperty] SetAmbient 1.0 + +# Create the rendering related stuff. +# Since some of our actors are a single vertex, we need to remove all +# cullers so the single vertex actors will render +vtkRenderer ren1 +[ren1 GetCullers] RemoveAllItems + +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground .1 .2 .3 +renWin SetSize 400 200 + +# specify properties +ren1 AddActor aEdgeActor +ren1 AddActor aTriActor +ren1 AddActor aQuadActor +ren1 AddActor aTetActor +ren1 AddActor aHexActor +ren1 AddActor aWedgeActor +ren1 AddActor aPyramidActor + +# places everyone!! +aTriActor AddPosition 2 0 0 +aQuadActor AddPosition 4 0 0 +aTetActor AddPosition 6 0 0 +aHexActor AddPosition 8 0 0 +aWedgeActor AddPosition 10 0 0 +aPyramidActor AddPosition 12 0 0 + +BuildBackdrop -1 15 -1 4 -1 2 .1 +ren1 AddActor base +[base GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor left +[left GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor back +[back GetProperty] SetDiffuseColor .2 .2 .2 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 2.5 +ren1 ResetCameraClippingRange + +renWin Render + +# create a little scorecard above each of the cells. These are displayed +# if a ray cast hits the cell, otherwise they are not shown. +vtkPlaneSource pm + pm SetXResolution 1 + pm SetYResolution 1 +vtkPolyDataMapper pmapper + pmapper SetInputConnection [pm GetOutputPort] + +# now try intersecting rays with the cell +vtkCellPicker cellPicker + +vtkActor edgeCheck + edgeCheck SetMapper pmapper + edgeCheck AddPosition 0.5 2.5 0 +cellPicker Pick 87 71 0 ren1 +if {[cellPicker GetCellId] != "-1" } { + ren1 AddActor edgeCheck +} + +vtkActor triCheck + triCheck SetMapper pmapper + triCheck AddPosition 2.5 2.5 0 +cellPicker Pick 139 72 0 ren1 +if {[cellPicker GetCellId] != "-1" } { + ren1 AddActor triCheck +} + +vtkActor quadCheck + quadCheck SetMapper pmapper + quadCheck AddPosition 4.5 2.5 0 +cellPicker Pick 192 78 0 ren1 +if {[cellPicker GetCellId] != "-1" } { + ren1 AddActor quadCheck +} + +vtkActor tetCheck + tetCheck SetMapper pmapper + tetCheck AddPosition 6.5 2.5 0 +cellPicker Pick 233 70 0 ren1 +if {[cellPicker GetCellId] != "-1" } { + ren1 AddActor tetCheck +} + +vtkActor hexCheck + hexCheck SetMapper pmapper + hexCheck AddPosition 8.5 2.5 0 +cellPicker Pick 287 80 0 ren1 +if {[cellPicker GetCellId] != "-1" } { + ren1 AddActor hexCheck +} + +vtkActor wedgeCheck + wedgeCheck SetMapper pmapper + wedgeCheck AddPosition 10.5 2.5 0 +cellPicker Pick 287 80 0 ren1 +if {[cellPicker GetCellId] != "-1" } { + ren1 AddActor wedgeCheck +} + +vtkActor pyraCheck + pyraCheck SetMapper pmapper + pyraCheck AddPosition 12.5 2.5 0 +cellPicker Pick 287 80 0 ren1 +if {[cellPicker GetCellId] != "-1" } { + ren1 AddActor pyraCheck +} + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/MatrixToTransform.tcl b/Graphics/Testing/Tcl/MatrixToTransform.tcl new file mode 100644 index 0000000..11b2b2e --- /dev/null +++ b/Graphics/Testing/Tcl/MatrixToTransform.tcl @@ -0,0 +1,254 @@ +package require vtk + +# This example demonstrates how to use a matrix in place of a transfrom +# via vtkMatrixToLinearTransform and vtkMatrixToHomogeneousTransform. + + +# create a rendering window +vtkRenderWindow renWin +renWin SetSize 600 300 + +# set up first set of polydata +vtkPlaneSource p1 +p1 SetOrigin 0.5 0.508 -0.5 +p1 SetPoint1 -0.5 0.508 -0.5 +p1 SetPoint2 0.5 0.508 0.5 +p1 SetXResolution 5 +p1 SetYResolution 5 + +vtkPlaneSource p2 +p2 SetOrigin -0.508 0.5 -0.5 +p2 SetPoint1 -0.508 -0.5 -0.5 +p2 SetPoint2 -0.508 0.5 0.5 +p2 SetXResolution 5 +p2 SetYResolution 5 + +vtkPlaneSource p3 +p3 SetOrigin -0.5 -0.508 -0.5 +p3 SetPoint1 0.5 -0.508 -0.5 +p3 SetPoint2 -0.5 -0.508 0.5 +p3 SetXResolution 5 +p3 SetYResolution 5 + +vtkPlaneSource p4 +p4 SetOrigin 0.508 -0.5 -0.5 +p4 SetPoint1 0.508 0.5 -0.5 +p4 SetPoint2 0.508 -0.5 0.5 +p4 SetXResolution 5 +p4 SetYResolution 5 + +vtkPlaneSource p5 +p5 SetOrigin 0.5 0.5 -0.508 +p5 SetPoint1 0.5 -0.5 -0.508 +p5 SetPoint2 -0.5 0.5 -0.508 +p5 SetXResolution 5 +p5 SetYResolution 5 + +vtkPlaneSource p6 +p6 SetOrigin 0.5 0.5 0.508 +p6 SetPoint1 -0.5 0.5 0.508 +p6 SetPoint2 0.5 -0.5 0.508 +p6 SetXResolution 5 +p6 SetYResolution 5 + +# append together +vtkAppendPolyData ap +ap AddInput [p1 GetOutput] +ap AddInput [p2 GetOutput] +ap AddInput [p3 GetOutput] +ap AddInput [p4 GetOutput] +ap AddInput [p5 GetOutput] +ap AddInput [p6 GetOutput] + +#-------------------------- +# linear transform matrix +vtkMatrixToLinearTransform t1 +vtkMatrix4x4 m1 +t1 SetInput m1 + +m1 SetElement 0 0 1.127631 +m1 SetElement 0 1 0.205212 +m1 SetElement 0 2 -0.355438 +m1 SetElement 1 0 0.000000 +m1 SetElement 1 1 0.692820 +m1 SetElement 1 2 0.400000 +m1 SetElement 2 0 0.200000 +m1 SetElement 2 1 -0.469846 +m1 SetElement 2 2 0.813798 + +vtkTransformPolyDataFilter f11 +f11 SetInputConnection [ap GetOutputPort] +f11 SetTransform t1 + +vtkDataSetMapper m11 +m11 SetInputConnection [f11 GetOutputPort] + +vtkActor a11 +a11 SetMapper m11 +[a11 GetProperty] SetColor 1 0 0 +[a11 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren11 +ren11 SetViewport 0.0 0.5 0.25 1.0 +ren11 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren11 AddActor a11 +renWin AddRenderer ren11 + +# inverse identity transform +vtkTransformPolyDataFilter f12 +f12 SetInputConnection [ap GetOutputPort] +f12 SetTransform [t1 GetInverse] + +vtkDataSetMapper m12 +m12 SetInputConnection [f12 GetOutputPort] + +vtkActor a12 +a12 SetMapper m12 +[a12 GetProperty] SetColor 0.9 0.9 0 +[a12 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren12 +ren12 SetViewport 0.0 0.0 0.25 0.5 +ren12 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren12 AddActor a12 +renWin AddRenderer ren12 + + +#-------------------------- +# perspective transform matrix +vtkMatrix4x4 m2 +m2 SetElement 3 0 -0.11 +m2 SetElement 3 1 0.3 +m2 SetElement 3 2 0.2 + +vtkMatrixToHomogeneousTransform t2 +t2 SetInput m2 + +vtkTransformPolyDataFilter f21 +f21 SetInputConnection [ap GetOutputPort] +f21 SetTransform t2 + +vtkDataSetMapper m21 +m21 SetInputConnection [f21 GetOutputPort] + +vtkActor a21 +a21 SetMapper m21 +[a21 GetProperty] SetColor 1 0 0 +[a21 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren21 +ren21 SetViewport 0.25 0.5 0.50 1.0 +ren21 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren21 AddActor a21 +renWin AddRenderer ren21 + +# inverse linear transform +vtkTransformPolyDataFilter f22 +f22 SetInputConnection [ap GetOutputPort] +f22 SetTransform [t2 GetInverse] + +vtkDataSetMapper m22 +m22 SetInputConnection [f22 GetOutputPort] + +vtkActor a22 +a22 SetMapper m22 +[a22 GetProperty] SetColor 0.9 0.9 0 +[a22 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren22 +ren22 SetViewport 0.25 0.0 0.50 0.5 +ren22 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren22 AddActor a22 +renWin AddRenderer ren22 + + +#-------------------------- +# linear concatenation - should end up with identity here +vtkTransform t3 +t3 Concatenate t1 +t3 Concatenate [t1 GetInverse] + +vtkTransformPolyDataFilter f31 +f31 SetInputConnection [ap GetOutputPort] +f31 SetTransform t3 + +vtkDataSetMapper m31 +m31 SetInputConnection [f31 GetOutputPort] + +vtkActor a31 +a31 SetMapper m31 +[a31 GetProperty] SetColor 1 0 0 +[a31 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren31 +ren31 SetViewport 0.50 0.5 0.75 1.0 +ren31 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren31 AddActor a31 +renWin AddRenderer ren31 + +# inverse linear transform +vtkTransformPolyDataFilter f32 +f32 SetInputConnection [ap GetOutputPort] +f32 SetTransform [t3 GetInverse] + +vtkDataSetMapper m32 +m32 SetInputConnection [f32 GetOutputPort] + +vtkActor a32 +a32 SetMapper m32 +[a32 GetProperty] SetColor 0.9 0.9 0 +[a32 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren32 +ren32 SetViewport 0.5 0.0 0.75 0.5 +ren32 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren32 AddActor a32 +renWin AddRenderer ren32 + + +#-------------------------- +# perspective transform concatenation +vtkPerspectiveTransform t4 +t4 Concatenate t1 +t4 Concatenate t2 +t4 Concatenate t3 + +vtkTransformPolyDataFilter f41 +f41 SetInputConnection [ap GetOutputPort] +f41 SetTransform t4 + +vtkDataSetMapper m41 +m41 SetInputConnection [f41 GetOutputPort] + +vtkActor a41 +a41 SetMapper m41 +[a41 GetProperty] SetColor 1 0 0 +[a41 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren41 +ren41 SetViewport 0.75 0.5 1.0 1.0 +ren41 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren41 AddActor a41 +renWin AddRenderer ren41 + +# inverse of transform concatenation +vtkTransformPolyDataFilter f42 +f42 SetInputConnection [ap GetOutputPort] +f42 SetTransform [t4 GetInverse] + +vtkDataSetMapper m42 +m42 SetInputConnection [f42 GetOutputPort] + +vtkActor a42 +a42 SetMapper m42 +[a42 GetProperty] SetColor 0.9 0.9 0 +[a42 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren42 +ren42 SetViewport 0.75 0.0 1.0 0.5 +ren42 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren42 AddActor a42 +renWin AddRenderer ren42 +renWin Render + + diff --git a/Graphics/Testing/Tcl/MesaCone.tcl b/Graphics/Testing/Tcl/MesaCone.tcl new file mode 100644 index 0000000..3373379 --- /dev/null +++ b/Graphics/Testing/Tcl/MesaCone.tcl @@ -0,0 +1,28 @@ +package require vtk +package require vtkinteraction + +vtkXMesaRenderWindow renWin + +vtkMesaRenderer ren +renWin AddRenderer ren + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkConeSource cone + +vtkMesaPolyDataMapper mp +mp SetInputConnection [cone GetOutputPort] + +vtkMesaActor actor +actor SetMapper mp + +ren AddActor actor + +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/MultidimensionalSolution.tcl b/Graphics/Testing/Tcl/MultidimensionalSolution.tcl new file mode 100644 index 0000000..1a500a0 --- /dev/null +++ b/Graphics/Testing/Tcl/MultidimensionalSolution.tcl @@ -0,0 +1,207 @@ +# +# The dataset read by this exercise ("combVectors.vtk") has field data +# associated with the pointdata, namely two vector fields. In this exercise, +# you will convert both sets of field data into attribute data. Mappers only +# process attribute data, not field data. So we must convert the field data to +# attribute data in order to display it. (You'll need to determine the "names" +# of the two vector fields in the field data.) +# +# If there is time remaining, you might consider adding a programmable filter +# to convert the two sets of vectors into a single scalar field, representing +# the angle between the two vector fields. +# +# You will most likely use vtkFieldDataToAttributeDataFilter, vtkHedgeHog, +# and vtkProgrammableAttributeDataFilter. +# +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# + +# get the pressure gradient vector field +vtkPLOT3DReader pl3d_gradient + pl3d_gradient SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d_gradient SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d_gradient SetScalarFunctionNumber 100 + pl3d_gradient SetVectorFunctionNumber 210 + pl3d_gradient Update + +# get the velocity vector field +vtkPLOT3DReader pl3d_velocity + pl3d_velocity SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d_velocity SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d_velocity SetScalarFunctionNumber 100 + pl3d_velocity SetVectorFunctionNumber 200 + pl3d_velocity Update + + +# contour the scalar fields +vtkContourFilter contour +contour SetInputConnection [pl3d_gradient GetOutputPort] +contour SetValue 0 0.225 + +# probe the vector fields to get data at the contour surface +vtkProbeFilter probe_gradient +probe_gradient SetInputConnection [contour GetOutputPort] +probe_gradient SetSource [pl3d_gradient GetOutput] + +vtkProbeFilter probe_velocity +probe_velocity SetInputConnection [contour GetOutputPort] +probe_velocity SetSource [pl3d_velocity GetOutput] + + +# +# To display the vector fields, we use vtkHedgeHog to create lines. +# +vtkHedgeHog velocity +velocity SetInputConnection [probe_velocity GetOutputPort] +velocity SetScaleFactor 0.0015 + +vtkHedgeHog pressureGradient +pressureGradient SetInputConnection [probe_gradient GetOutputPort] +pressureGradient SetScaleFactor 0.00002 + + +proc ExecuteDot {} { + # proc for ProgrammableAttributeDataFilter. Note the use of "double()" + # in the calculations. This protects us from Tcl using ints and + # overflowing. + + set inputs [dotProduct GetInputList] + set input0 [$inputs GetDataSet 0] + set input1 [$inputs GetDataSet 1] + set numPts [$input0 GetNumberOfPoints] + + set vectors0 [[$input0 GetPointData] GetVectors] + set vectors1 [[$input1 GetPointData] GetVectors] + + vtkFloatArray scalars + + for {set i 0} {$i < $numPts} {incr i} { + set v0 [$vectors0 GetTuple3 $i] + set v1 [$vectors1 GetTuple3 $i] + + set v0x [lindex $v0 0] + set v0y [lindex $v0 1] + set v0z [lindex $v0 2] + + set v1x [lindex $v1 0] + set v1y [lindex $v1 1] + set v1z [lindex $v1 2] + + set l0 [expr double($v0x)*double($v0x) + double($v0y)*double($v0y) \ + + double($v0z)*double($v0z)] + set l1 [expr double($v1x)*double($v1x) + double($v1y)*double($v1y) \ + + double($v1z)*double($v1z)] + + set l0 [expr sqrt(double($l0))] + set l1 [expr sqrt(double($l1))] + + if {$l0 > 0.0 && $l1 > 0.0} { + set d [expr (double($v0x)*double($v1x) + double($v0y)*double($v1y)\ + + double($v0z)*double($v1z))/($l0*$l1)] + } else { + set d 0.0 + } + + scalars InsertValue $i $d + } + + [[dotProduct GetOutput] GetPointData] SetScalars scalars + + scalars Delete +} + +# +# We use the ProgrammableAttributeDataFilter to compute the cosine +# of the angle between the two vector fields (i.e. the dot product +# normalized by the product of the vector lengths). +# +# +vtkProgrammableAttributeDataFilter dotProduct +dotProduct SetInputConnection [probe_velocity GetOutputPort] +dotProduct AddInput [probe_velocity GetOutput] +dotProduct AddInput [probe_gradient GetOutput] +dotProduct SetExecuteMethod ExecuteDot + +# +# Create the mappers and actors. Note the call to GetPolyDataOutput when +# setting up the mapper for the ProgrammableAttributeDataFilter +# +vtkPolyDataMapper velocityMapper + velocityMapper SetInputConnection [velocity GetOutputPort] + velocityMapper ScalarVisibilityOff + +vtkLODActor velocityActor + velocityActor SetMapper velocityMapper + velocityActor SetNumberOfCloudPoints 1000 + eval [velocityActor GetProperty] SetColor 1 0 0 + +vtkPolyDataMapper pressureGradientMapper + pressureGradientMapper SetInputConnection [pressureGradient GetOutputPort] + pressureGradientMapper ScalarVisibilityOff + +vtkLODActor pressureGradientActor + pressureGradientActor SetMapper pressureGradientMapper + pressureGradientActor SetNumberOfCloudPoints 1000 + eval [pressureGradientActor GetProperty] SetColor 0 1 0 + +vtkPolyDataMapper dotMapper + dotMapper SetInput [dotProduct GetPolyDataOutput] + dotMapper SetScalarRange -1 1 + +vtkLODActor dotActor + dotActor SetMapper dotMapper + dotActor SetNumberOfCloudPoints 1000 + +# +# The PLOT3DReader is used to draw the outline of the original dataset. +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor velocityActor +ren1 AddActor pressureGradientActor +ren1 AddActor dotActor +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +#ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition -21.6807 -22.6387 35.9759 +$cam1 SetViewUp -0.0158865 0.293715 0.955761 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render +renWin SetWindowName "Multidimensional Visualization Exercise" + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/NoLightGeneration.tcl b/Graphics/Testing/Tcl/NoLightGeneration.tcl new file mode 100644 index 0000000..8414d4a --- /dev/null +++ b/Graphics/Testing/Tcl/NoLightGeneration.tcl @@ -0,0 +1,72 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 + ren1 AutomaticLightCreationOff +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create cones of varying resolution +vtkConeSource cone0 + cone0 SetResolution 0 +vtkConeSource cone1 + cone1 SetResolution 1 +vtkConeSource cone2 + cone2 SetResolution 2 +vtkConeSource cone8 + cone8 SetResolution 8 + cone8 SetDirection 0 0 10 + cone8 SetCenter 5 0 0 + +vtkPolyDataMapper cone0Mapper + cone0Mapper SetInputConnection [cone0 GetOutputPort] +vtkActor cone0Actor + cone0Actor SetMapper cone0Mapper + +vtkPolyDataMapper cone1Mapper + cone1Mapper SetInputConnection [cone1 GetOutputPort] +vtkActor cone1Actor + cone1Actor SetMapper cone1Mapper + +vtkPolyDataMapper cone2Mapper + cone2Mapper SetInputConnection [cone2 GetOutputPort] +vtkActor cone2Actor + cone2Actor SetMapper cone2Mapper + +vtkPolyDataMapper cone8Mapper + cone8Mapper SetInputConnection [cone8 GetOutputPort] +vtkActor cone8Actor + cone8Actor SetMapper cone8Mapper + +# assign our actor to the renderer +ren1 AddActor cone0Actor +ren1 AddActor cone1Actor +ren1 AddActor cone2Actor +ren1 AddActor cone8Actor +ren1 SetBackground .5 .5 .5 +ren1 ResetCamera +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.3 +ren1 ResetCameraClippingRange + +renWin SetSize 301 91 +cone0Actor SetPosition -1.5 0 0 +cone1Actor SetPosition -.5 0 0 +cone2Actor SetPosition .5 0 0 +cone8Actor SetPosition 1.5 0 0 + +[cone0Actor GetProperty] SetDiffuseColor 1 0 0 +[cone1Actor GetProperty] SetDiffuseColor 0 1 0 +[cone8Actor GetProperty] BackfaceCullingOn +[cone8Actor GetProperty] SetDiffuseColor 0 0 1 + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/OBBCylinder.tcl b/Graphics/Testing/Tcl/OBBCylinder.tcl new file mode 100644 index 0000000..98a94e9 --- /dev/null +++ b/Graphics/Testing/Tcl/OBBCylinder.tcl @@ -0,0 +1,69 @@ +package require vtk +package require vtkinteraction + +vtkCylinderSource cylinder +cylinder SetHeight 1 +cylinder SetRadius 4 +cylinder SetResolution 100 +cylinder CappingOff + +vtkTransform foo +foo RotateX 20 +foo RotateY 10 +foo RotateZ 27 +foo Scale 1 .7 .3 + +vtkTransformPolyDataFilter transPD +transPD SetInputConnection [cylinder GetOutputPort] +transPD SetTransform foo + +vtkPolyDataMapper dataMapper + dataMapper SetInputConnection [transPD GetOutputPort] +vtkActor model + model SetMapper dataMapper + [model GetProperty] SetColor 1 0 0 + + +vtkOBBTree obb + obb SetMaxLevel 10 + obb SetNumberOfCellsPerBucket 5 + obb AutomaticOff + +vtkSpatialRepresentationFilter boxes + boxes SetInputConnection [transPD GetOutputPort] + boxes SetSpatialRepresentation obb +vtkExtractEdges boxEdges + boxEdges SetInput [ boxes GetOutput ] +vtkPolyDataMapper boxMapper + boxMapper SetInputConnection [boxEdges GetOutputPort] + boxMapper SetResolveCoincidentTopology 1 +vtkActor boxActor + boxActor SetMapper boxMapper + [boxActor GetProperty] SetAmbient 1 + [boxActor GetProperty] SetDiffuse 0 + [boxActor GetProperty] SetRepresentationToWireframe + + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor model +ren1 AddActor boxActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/OSCone.tcl b/Graphics/Testing/Tcl/OSCone.tcl new file mode 100644 index 0000000..f564b5b --- /dev/null +++ b/Graphics/Testing/Tcl/OSCone.tcl @@ -0,0 +1,23 @@ +package require vtk +package require vtkinteraction + +vtkRenderWindow renWin +renWin OffScreenRenderingOn + +vtkRenderer ren +renWin AddRenderer ren + +vtkConeSource cone + +vtkPolyDataMapper mp +mp SetInputConnection [cone GetOutputPort] + +vtkActor actor +actor SetMapper mp + +ren AddActor actor + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/PolyDataMapperAllPolygons.tcl b/Graphics/Testing/Tcl/PolyDataMapperAllPolygons.tcl new file mode 100644 index 0000000..0676d99 --- /dev/null +++ b/Graphics/Testing/Tcl/PolyDataMapperAllPolygons.tcl @@ -0,0 +1,133 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkBMPReader bmpReader + bmpReader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" +vtkTexture texture + texture SetInputConnection [bmpReader GetOutputPort] + +vtkPoints triangleStripPoints + triangleStripPoints SetNumberOfPoints 5 + triangleStripPoints InsertPoint 0 0 1 0 + triangleStripPoints InsertPoint 1 0 0 .5 + triangleStripPoints InsertPoint 2 1 1 .3 + triangleStripPoints InsertPoint 3 1 0 .6 + triangleStripPoints InsertPoint 4 2 1 .1 + +vtkFloatArray triangleStripTCoords + triangleStripTCoords SetNumberOfComponents 2 + triangleStripTCoords SetNumberOfTuples 5 + triangleStripTCoords InsertTuple2 0 0 1 + triangleStripTCoords InsertTuple2 1 0 0 + triangleStripTCoords InsertTuple2 2 .5 1 + triangleStripTCoords InsertTuple2 3 .5 0 + triangleStripTCoords InsertTuple2 4 1 1 + +vtkFloatArray triangleStripPointScalars + triangleStripPointScalars SetNumberOfTuples 5 + triangleStripPointScalars InsertValue 0 1 + triangleStripPointScalars InsertValue 1 0 + triangleStripPointScalars InsertValue 2 0 + triangleStripPointScalars InsertValue 3 0 + triangleStripPointScalars InsertValue 4 0 + +vtkFloatArray triangleStripCellScalars + triangleStripCellScalars SetNumberOfTuples 1 + triangleStripCellScalars InsertValue 0 1 + +vtkFloatArray triangleStripPointNormals + triangleStripPointNormals SetNumberOfComponents 3 + triangleStripPointNormals SetNumberOfTuples 5 + triangleStripPointNormals InsertTuple3 0 0 0 1 + triangleStripPointNormals InsertTuple3 1 0 1 0 + triangleStripPointNormals InsertTuple3 2 0 1 1 + triangleStripPointNormals InsertTuple3 3 1 0 0 + triangleStripPointNormals InsertTuple3 4 1 0 1 + +vtkFloatArray triangleStripCellNormals + triangleStripCellNormals SetNumberOfComponents 3 + triangleStripCellNormals SetNumberOfTuples 1 + triangleStripCellNormals InsertTuple3 0 0 0 1 + +vtkTriangleStrip aTriangleStrip + [aTriangleStrip GetPointIds] SetNumberOfIds 5 + [aTriangleStrip GetPointIds] SetId 0 0 + [aTriangleStrip GetPointIds] SetId 1 1 + [aTriangleStrip GetPointIds] SetId 2 2 + [aTriangleStrip GetPointIds] SetId 3 3 + [aTriangleStrip GetPointIds] SetId 4 4 + +vtkLookupTable lut + lut SetNumberOfColors 5 + lut SetTableValue 0 0 0 1 1 + lut SetTableValue 1 0 1 0 1 + lut SetTableValue 2 0 1 1 1 + lut SetTableValue 3 1 0 0 1 + lut SetTableValue 4 1 0 1 1 + +set masks "0 1 2 3 4 5 6 7 10 11 14 15 16 18 20 22 26 30" +set i 0; set j 0 ; set k 0 +set types "strip triangle" +foreach type $types { + foreach mask $masks { + vtkUnstructuredGrid grid$i + grid$i Allocate 1 1 + grid$i InsertNextCell [aTriangleStrip GetCellType] [aTriangleStrip GetPointIds] + grid$i SetPoints triangleStripPoints + vtkGeometryFilter geometry$i + geometry$i SetInput grid$i + vtkTriangleFilter triangles$i + triangles$i SetInputConnection [geometry$i GetOutputPort] + vtkPolyDataMapper mapper$i + if {$type == "strip"} {mapper$i SetInputConnection [geometry$i GetOutputPort]} + if {$type == "triangle"} {mapper$i SetInputConnection [triangles$i GetOutputPort]} + mapper$i SetLookupTable lut + mapper$i SetScalarRange 0 4 + vtkActor actor$i + actor$i SetMapper mapper$i + + if {[expr $mask & 1] != 0} { + [grid$i GetPointData] SetNormals triangleStripPointNormals + } + if {[expr $mask & 2] != 0} { + [grid$i GetPointData] SetScalars triangleStripPointScalars + mapper$i SetScalarModeToUsePointData + } + if {[expr $mask & 4] != 0} { + [grid$i GetPointData] SetTCoords triangleStripTCoords + actor$i SetTexture texture + } + if {[expr $mask & 8] != 0} { + [grid$i GetCellData] SetScalars triangleStripCellScalars + mapper$i SetScalarModeToUseCellData + } + if {[expr $mask & 16] != 0} { + [grid$i GetCellData] SetNormals triangleStripCellNormals + } + actor$i AddPosition [expr $j * 2] [expr $k * 2] 0 + ren1 AddActor actor$i + incr j + if {$j >= 6} {set j 0; incr k}; + incr i + } +} +renWin SetSize 480 480 +ren1 SetBackground .7 .3 .1 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/PolyDataMapperAllWireframe.tcl b/Graphics/Testing/Tcl/PolyDataMapperAllWireframe.tcl new file mode 100644 index 0000000..b7cf93d --- /dev/null +++ b/Graphics/Testing/Tcl/PolyDataMapperAllWireframe.tcl @@ -0,0 +1,134 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkBMPReader pnmReader + pnmReader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" +vtkTexture texture + texture SetInputConnection [pnmReader GetOutputPort] + +vtkPoints triangleStripPoints + triangleStripPoints SetNumberOfPoints 5 + triangleStripPoints InsertPoint 0 0 1 0 + triangleStripPoints InsertPoint 1 0 0 .5 + triangleStripPoints InsertPoint 2 1 1 .3 + triangleStripPoints InsertPoint 3 1 0 .6 + triangleStripPoints InsertPoint 4 2 1 .1 + +vtkFloatArray triangleStripTCoords + triangleStripTCoords SetNumberOfComponents 2 + triangleStripTCoords SetNumberOfTuples 5 + triangleStripTCoords InsertTuple2 0 0 1 + triangleStripTCoords InsertTuple2 1 0 0 + triangleStripTCoords InsertTuple2 2 .5 1 + triangleStripTCoords InsertTuple2 3 .5 0 + triangleStripTCoords InsertTuple2 4 1 1 + +vtkFloatArray triangleStripPointScalars + triangleStripPointScalars SetNumberOfTuples 5 + triangleStripPointScalars InsertValue 0 1 + triangleStripPointScalars InsertValue 1 0 + triangleStripPointScalars InsertValue 2 0 + triangleStripPointScalars InsertValue 3 0 + triangleStripPointScalars InsertValue 4 0 + +vtkFloatArray triangleStripCellScalars + triangleStripCellScalars SetNumberOfTuples 1 + triangleStripCellScalars InsertValue 0 1 + +vtkFloatArray triangleStripPointNormals + triangleStripPointNormals SetNumberOfComponents 3 + triangleStripPointNormals SetNumberOfTuples 5 + triangleStripPointNormals InsertTuple3 0 0 0 1 + triangleStripPointNormals InsertTuple3 1 0 1 0 + triangleStripPointNormals InsertTuple3 2 0 1 1 + triangleStripPointNormals InsertTuple3 3 1 0 0 + triangleStripPointNormals InsertTuple3 4 1 0 1 + +vtkFloatArray triangleStripCellNormals + triangleStripCellNormals SetNumberOfComponents 3 + triangleStripCellNormals SetNumberOfTuples 1 + triangleStripCellNormals InsertTuple3 0 1 1 1 + +vtkTriangleStrip aTriangleStrip + [aTriangleStrip GetPointIds] SetNumberOfIds 5 + [aTriangleStrip GetPointIds] SetId 0 0 + [aTriangleStrip GetPointIds] SetId 1 1 + [aTriangleStrip GetPointIds] SetId 2 2 + [aTriangleStrip GetPointIds] SetId 3 3 + [aTriangleStrip GetPointIds] SetId 4 4 + +vtkLookupTable lut + lut SetNumberOfColors 5 + lut SetTableValue 0 0 0 1 1 + lut SetTableValue 1 0 1 0 1 + lut SetTableValue 2 0 1 1 1 + lut SetTableValue 3 1 0 0 1 + lut SetTableValue 4 1 0 1 1 + +set masks "0 1 2 3 4 5 6 7 10 11 14 15 16 18 20 22 26 30" +set i 0; set j 0 ; set k 0 +set types "strip triangle" +foreach type $types { + foreach mask $masks { + vtkUnstructuredGrid grid$i + grid$i Allocate 1 1 + grid$i InsertNextCell [aTriangleStrip GetCellType] [aTriangleStrip GetPointIds] + grid$i SetPoints triangleStripPoints + vtkGeometryFilter geometry$i + geometry$i SetInput grid$i + vtkTriangleFilter triangles$i + triangles$i SetInputConnection [geometry$i GetOutputPort] + vtkPolyDataMapper mapper$i + if {$type == "strip"} {mapper$i SetInputConnection [geometry$i GetOutputPort]} + if {$type == "triangle"} {mapper$i SetInputConnection [triangles$i GetOutputPort]} + mapper$i SetLookupTable lut + mapper$i SetScalarRange 0 4 + vtkActor actor$i + actor$i SetMapper mapper$i + + if {[expr $mask & 1] != 0} { + [grid$i GetPointData] SetNormals triangleStripPointNormals + } + if {[expr $mask & 2] != 0} { + [grid$i GetPointData] SetScalars triangleStripPointScalars + mapper$i SetScalarModeToUsePointData + } + if {[expr $mask & 4] != 0} { + [grid$i GetPointData] SetTCoords triangleStripTCoords + actor$i SetTexture texture + } + if {[expr $mask & 8] != 0} { + [grid$i GetCellData] SetScalars triangleStripCellScalars + mapper$i SetScalarModeToUseCellData + } + if {[expr $mask & 16] != 0} { + [grid$i GetCellData] SetNormals triangleStripCellNormals + } + actor$i AddPosition [expr $j * 2] [expr $k * 2] 0 + ren1 AddActor actor$i + [actor$i GetProperty] SetRepresentationToWireframe + incr j + if {$j >= 6} {set j 0; incr k}; + incr i + } +} +renWin SetSize 480 480 +ren1 SetBackground .7 .3 .1 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + +set threshold 15 + diff --git a/Graphics/Testing/Tcl/QuadricDecimation.tcl b/Graphics/Testing/Tcl/QuadricDecimation.tcl new file mode 100644 index 0000000..6c9122a --- /dev/null +++ b/Graphics/Testing/Tcl/QuadricDecimation.tcl @@ -0,0 +1,82 @@ +package require vtk +package require vtkinteraction + +# pipeline stuff +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +vtkGeometryFilter gf + gf SetInputConnection [pl3d GetOutputPort] +vtkTriangleFilter tf + tf SetInputConnection [gf GetOutputPort] +vtkPolyDataMapper gMapper + gMapper SetInputConnection [gf GetOutputPort] + eval gMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor gActor + gActor SetMapper gMapper + +# Don't look at attributes +vtkQuadricDecimation mesh + mesh SetInputConnection [tf GetOutputPort] + mesh SetTargetReduction .90 + mesh AttributeErrorMetricOn + +vtkPolyDataMapper mapper + mapper SetInputConnection [mesh GetOutputPort] + +vtkActor actor + actor SetMapper mapper + +# This time worry about attributes +vtkQuadricDecimation mesh2 + mesh2 SetInputConnection [tf GetOutputPort] + mesh2 SetTargetReduction .90 + mesh2 AttributeErrorMetricOff + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [mesh2 GetOutputPort] + +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 AddPosition 0 12 0 + +# Create rendering instances +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Set up the camera parameters +# +vtkCamera camera + camera SetPosition 19.34 6.128 -11.96 + camera SetFocalPoint 8.25451 6.0 29.77 + camera SetViewUp 0.9664 0.00605 0.256883 + camera SetViewAngle 30 + camera SetClippingRange 26 64 + +ren1 SetActiveCamera camera + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 AddActor actor2 + +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +set threshold 50 diff --git a/Graphics/Testing/Tcl/SliceOrder.tcl b/Graphics/Testing/Tcl/SliceOrder.tcl new file mode 100644 index 0000000..68c7623 --- /dev/null +++ b/Graphics/Testing/Tcl/SliceOrder.tcl @@ -0,0 +1,67 @@ +# +# these transformations permute medical image data to maintain proper orientation +# regardless of the acqusition order. After applying these transforms with +# vtkTransformFilter, a view up of 0,-1,0 will result in the body part +# facing the viewer. +# NOTE: some transformations have a -1 scale factor for one of the components. +# To ensure proper polygon orientation and normal direction, you must +# apply the vtkPolyDataNormals filter. +# +# Naming: +# si - superior to inferior (top to bottom) +# is - inferior to superior (bottom to top) +# ap - anterior to posterior (front to back) +# pa - posterior to anterior (back to front) +# lr - left to right +# rl - right to left +# +vtkTransform si + si SetMatrix 1 0 0 0 0 0 1 0 0 -1 0 0 0 0 0 1 + +vtkTransform is + is SetMatrix 1 0 0 0 0 0 -1 0 0 -1 0 0 0 0 0 1 + +vtkTransform ap + ap Scale 1 -1 1 + +vtkTransform pa + pa Scale 1 -1 -1 + +vtkTransform lr + lr SetMatrix 0 0 -1 0 0 -1 0 0 1 0 0 0 0 0 0 1 + +vtkTransform rl + rl SetMatrix 0 0 1 0 0 -1 0 0 1 0 0 0 0 0 0 1 + +# +# the previous transforms assume radiological views of the slices (viewed from the feet). other +# modalities such as physical sectioning may view from the head. these transforms modify the original +# with a 180 rotation about y +# +vtkTransform hf + hf SetMatrix -1 0 0 0 0 1 0 0 0 0 -1 0 0 0 0 1 + +vtkTransform hfsi + hfsi Concatenate [hf GetMatrix] + hfsi Concatenate [si GetMatrix] + +vtkTransform hfis + hfis Concatenate [hf GetMatrix] + hfis Concatenate [is GetMatrix] + +vtkTransform hfap + hfap Concatenate [hf GetMatrix] + hfap Concatenate [ap GetMatrix] + +vtkTransform hfpa + hfpa Concatenate [hf GetMatrix] + hfpa Concatenate [pa GetMatrix] + +vtkTransform hflr + hflr Concatenate [hf GetMatrix] + hflr Concatenate [lr GetMatrix] + +vtkTransform hfrl + hfrl Concatenate [hf GetMatrix] + hfrl Concatenate [rl GetMatrix] + diff --git a/Graphics/Testing/Tcl/StreamPolyData.tcl b/Graphics/Testing/Tcl/StreamPolyData.tcl new file mode 100644 index 0000000..675f03f --- /dev/null +++ b/Graphics/Testing/Tcl/StreamPolyData.tcl @@ -0,0 +1,93 @@ +package require vtk +package require vtktesting + +set NUMBER_OF_PIECES 5 + +# Generate implicit model of a sphere +# + +# Create renderer stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline that handles ghost cells + +vtkSphereSource sphere + sphere SetRadius 3 + sphere SetPhiResolution 100 + sphere SetThetaResolution 150 + # sphere AddObserver StartEvent {tk_messageBox -message "Executing with piece [[sphere GetOutput] GetUpdatePiece]"} + +# Just playing with an alternative that is not currently used. +proc NotUsed {} { + # This filter actually spoils the example because it asks for the whole input. + # The only reason it is here is because sphere complains it cannot generate ghost cells. + vtkExtractPolyDataPiece piece + piece SetInputConnection [sphere GetOutputPort] + # purposely put seams in here. + piece CreateGhostCellsOff + + # purposely put seams in here. + vtkPolyDataNormals pdn + pdn SetInputConnection [piece GetOutputPort] +} + +# Just playing with an alternative that is not currently used. +vtkDecimatePro deci + deci SetInputConnection [sphere GetOutputPort] + # this did not remove seams as I thought it would + deci BoundaryVertexDeletionOff + #deci PreserveTopologyOn + +# Since quadric Clustering does not handle borders properly yet, +# the pieces will have dramatic "eams" +vtkQuadricClustering q + q SetInputConnection [sphere GetOutputPort] + q SetNumberOfXDivisions 5 + q SetNumberOfYDivisions 5 + q SetNumberOfZDivisions 10 + q UseInputPointsOn + +vtkPolyDataStreamer streamer + #streamer SetInputConnection [deci GetOutputPort] + streamer SetInputConnection [q GetOutputPort] + #streamer SetInputConnection [pdn GetOutputPort] + streamer SetNumberOfStreamDivisions $NUMBER_OF_PIECES + + + +vtkPolyDataMapper mapper + mapper SetInputConnection [streamer GetOutputPort] + mapper ScalarVisibilityOff + mapper SetPiece 0 + mapper SetNumberOfPieces 2 + mapper ImmediateModeRenderingOn + +vtkActor actor + actor SetMapper mapper + eval [actor GetProperty] SetColor $english_red + + + +# Add the actors to the renderer, set the background and size +# + +[ren1 GetActiveCamera] SetPosition 5 5 10 +[ren1 GetActiveCamera] SetFocalPoint 0 0 0 +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TenEllip.tcl b/Graphics/Testing/Tcl/TenEllip.tcl new file mode 100644 index 0000000..68c33e6 --- /dev/null +++ b/Graphics/Testing/Tcl/TenEllip.tcl @@ -0,0 +1,97 @@ +package require vtk +package require vtkinteraction + +# create tensor ellipsoids +# Create the RenderWindow, Renderer and interactive renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# +# Create tensor ellipsoids +# +# generate tensors +vtkPointLoad ptLoad + ptLoad SetLoadValue 100.0 + ptLoad SetSampleDimensions 6 6 6 + ptLoad ComputeEffectiveStressOn + ptLoad SetModelBounds -10 10 -10 10 -10 10 + +# extract plane of data +vtkImageDataGeometryFilter plane + plane SetInputConnection [ptLoad GetOutputPort] + plane SetExtent 2 2 0 99 0 99 + +# Generate ellipsoids +vtkSphereSource sphere + sphere SetThetaResolution 8 + sphere SetPhiResolution 8 +vtkTensorGlyph ellipsoids + ellipsoids SetInputConnection [ptLoad GetOutputPort] + ellipsoids SetSourceConnection [sphere GetOutputPort] + ellipsoids SetScaleFactor 10 + ellipsoids ClampScalingOn + +vtkPolyDataNormals ellipNormals + ellipNormals SetInputConnection [ellipsoids GetOutputPort] + +# Map contour +vtkLogLookupTable lut + lut SetHueRange .6667 0.0 +vtkPolyDataMapper ellipMapper + ellipMapper SetInputConnection [ellipNormals GetOutputPort] + ellipMapper SetLookupTable lut + plane Update;#force update for scalar range + eval ellipMapper SetScalarRange [[plane GetOutput] GetScalarRange] + +vtkActor ellipActor + ellipActor SetMapper ellipMapper +# +# Create outline around data +# +vtkOutlineFilter outline + outline SetInputConnection [ptLoad GetOutputPort] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# +# Create cone indicating application of load +# +vtkConeSource coneSrc + coneSrc SetRadius .5 + coneSrc SetHeight 2 +vtkPolyDataMapper coneMap + coneMap SetInputConnection [coneSrc GetOutputPort] +vtkActor coneActor + coneActor SetMapper coneMap; + coneActor SetPosition 0 0 11 + coneActor RotateY 90 + eval [coneActor GetProperty] SetColor 1 0 0 + +vtkCamera camera + camera SetFocalPoint 0.113766 -1.13665 -1.01919 + camera SetPosition -29.4886 -63.1488 26.5807 + camera SetViewAngle 24.4617 + camera SetViewUp 0.17138 0.331163 0.927879 + camera SetClippingRange 1 100 + +ren1 AddActor ellipActor +ren1 AddActor outlineActor +ren1 AddActor coneActor +ren1 SetBackground 1.0 1.0 1.0 +ren1 SetActiveCamera camera + +renWin SetSize 400 400 +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestBandedContourFilter.tcl b/Graphics/Testing/Tcl/TestBandedContourFilter.tcl new file mode 100644 index 0000000..37bdbc1 --- /dev/null +++ b/Graphics/Testing/Tcl/TestBandedContourFilter.tcl @@ -0,0 +1,166 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Manually create cells of various types: vertex, polyvertex, line, +# polyline, triangle, quad, pentagon, and triangle strip. +vtkPoints pts + pts InsertPoint 0 0 0 0 + pts InsertPoint 1 0 1 0 + pts InsertPoint 2 0 2 0 + pts InsertPoint 3 1 0 0 + pts InsertPoint 4 1 1 0 + pts InsertPoint 5 1 2 0 + pts InsertPoint 6 2 0 0 + pts InsertPoint 7 2 2 0 + pts InsertPoint 8 3 0 0 + pts InsertPoint 9 3 1 0 + pts InsertPoint 10 3 2 0 + pts InsertPoint 11 4 0 0 + pts InsertPoint 12 6 0 0 + pts InsertPoint 13 5 2 0 + pts InsertPoint 14 7 0 0 + pts InsertPoint 15 9 0 0 + pts InsertPoint 16 7 2 0 + pts InsertPoint 17 9 2 0 + pts InsertPoint 18 10 0 0 + pts InsertPoint 19 12 0 0 + pts InsertPoint 20 10 1 0 + pts InsertPoint 21 12 1 0 + pts InsertPoint 22 10 2 0 + pts InsertPoint 23 12 2 0 + pts InsertPoint 24 10 3 0 + pts InsertPoint 25 12 3 0 + +vtkCellArray verts + verts InsertNextCell 1 + verts InsertCellPoint 0 + verts InsertNextCell 1 + verts InsertCellPoint 1 + verts InsertNextCell 1 + verts InsertCellPoint 2 + verts InsertNextCell 3 + verts InsertCellPoint 3 + verts InsertCellPoint 4 + verts InsertCellPoint 5 + +vtkCellArray lines + lines InsertNextCell 2 + lines InsertCellPoint 6 + lines InsertCellPoint 7 + lines InsertNextCell 3 + lines InsertCellPoint 8 + lines InsertCellPoint 9 + lines InsertCellPoint 10 + +vtkCellArray polys + polys InsertNextCell 4 + polys InsertCellPoint 14 + polys InsertCellPoint 15 + polys InsertCellPoint 17 + polys InsertCellPoint 16 + polys InsertNextCell 3 + polys InsertCellPoint 11 + polys InsertCellPoint 12 + polys InsertCellPoint 13 + +vtkCellArray strips + strips InsertNextCell 8 + strips InsertCellPoint 19 + strips InsertCellPoint 18 + strips InsertCellPoint 21 + strips InsertCellPoint 20 + strips InsertCellPoint 23 + strips InsertCellPoint 22 + strips InsertCellPoint 25 + strips InsertCellPoint 24 + +vtkFloatArray scalars + scalars SetNumberOfTuples 26 + scalars SetTuple1 0 0 + scalars SetTuple1 1 50 + scalars SetTuple1 2 100 + scalars SetTuple1 3 0 + scalars SetTuple1 4 50 + scalars SetTuple1 5 100 + scalars SetTuple1 6 10 + scalars SetTuple1 7 90 + scalars SetTuple1 8 10 + scalars SetTuple1 9 50 + scalars SetTuple1 10 90 + scalars SetTuple1 11 10 + scalars SetTuple1 12 40 + scalars SetTuple1 13 100 + scalars SetTuple1 14 0 + scalars SetTuple1 15 60 + scalars SetTuple1 16 40 + scalars SetTuple1 17 100 + scalars SetTuple1 18 0 + scalars SetTuple1 19 25 + scalars SetTuple1 20 25 + scalars SetTuple1 21 50 + scalars SetTuple1 22 50 + scalars SetTuple1 23 75 + scalars SetTuple1 24 75 + scalars SetTuple1 25 100 + +vtkPolyData polyData + polyData SetPoints pts + polyData SetVerts verts + polyData SetLines lines + polyData SetPolys polys + polyData SetStrips strips + [polyData GetPointData] SetScalars scalars + +vtkBandedPolyDataContourFilter bf + bf SetInput polyData + bf GenerateValues 3 25 75 +vtkPolyDataMapper mapper + mapper SetInputConnection [bf GetOutputPort] + mapper SetScalarModeToUseCellData + mapper SetScalarRange 0 4 +vtkActor actor + actor SetMapper mapper + +vtkIdFilter ids + ids SetInputConnection [bf GetOutputPort] + ids PointIdsOn + ids CellIdsOn + ids FieldDataOn +vtkLabeledDataMapper ldm + ldm SetInputConnection [ids GetOutputPort] + ldm SetLabelFormat "%g" + ldm SetLabelModeToLabelFieldData +vtkActor2D pointLabels + pointLabels SetMapper ldm + + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +#ren1 AddActor2D pointLabels #for debugging only + + +ren1 SetBackground 0 0 0 +renWin SetSize 300 80 +renWin Render +[ren1 GetActiveCamera] Zoom 3 +renWin Render +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TestBoxFunction.tcl b/Graphics/Testing/Tcl/TestBoxFunction.tcl new file mode 100644 index 0000000..765421e --- /dev/null +++ b/Graphics/Testing/Tcl/TestBoxFunction.tcl @@ -0,0 +1,65 @@ +package require vtk +package require vtkinteraction + +vtkBox box + box SetXMin 0 2 4 + box SetXMax 2 4 6 + +vtkSampleFunction sample + sample SetSampleDimensions 30 30 30 + sample SetImplicitFunction box + sample SetModelBounds 0 1.5 1 5 2 8 + sample ComputeNormalsOn + +vtkContourFilter contours + contours SetInputConnection [sample GetOutputPort] + contours GenerateValues 5 -0.5 1.5 + +vtkPolyDataWriter w +w SetInputConnection [contours GetOutputPort] +w SetFileName "junk.vtk" +#w Write + +vtkPolyDataMapper contMapper + contMapper SetInputConnection [contours GetOutputPort] + contMapper SetScalarRange -0.5 1.5 + +vtkActor contActor + contActor SetMapper contMapper + +# We'll put a simple outline around the data. +vtkOutlineFilter outline + outline SetInputConnection [sample GetOutputPort] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# The usual rendering stuff. +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 500 500 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 1 1 1 +ren1 AddActor contActor +ren1 AddActor outlineActor + +vtkCamera camera +camera SetClippingRange 6.31875 20.689 +camera SetFocalPoint 0.75 3 5 +camera SetPosition 9.07114 -4.10065 -1.38712 +camera SetViewAngle 30 +camera SetViewUp -0.580577 -0.802756 0.13606 + +ren1 SetActiveCamera camera + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestButtonSource.tcl b/Graphics/Testing/Tcl/TestButtonSource.tcl new file mode 100644 index 0000000..3e2f7bf --- /dev/null +++ b/Graphics/Testing/Tcl/TestButtonSource.tcl @@ -0,0 +1,101 @@ +# Test the button source +package require vtk +package require vtkinteraction + +# The image to map on the button +vtkJPEGReader r + r SetFileName "$VTK_DATA_ROOT/Data/beach.jpg" + r Update +vtkTexture t + t SetInputConnection [r GetOutputPort] +set dims [[r GetOutput] GetDimensions] +set d1 [lindex $dims 0] +set d2 [lindex $dims 1] + +# The first elliptical button +vtkEllipticalButtonSource bs + bs SetWidth 2 + bs SetHeight 1 + bs SetDepth 0.2 + bs SetCircumferentialResolution 64 + bs SetRadialRatio 1.1 + bs SetShoulderResolution 8 + bs SetTextureResolution 4 + bs TwoSidedOn +vtkPolyDataMapper bMapper + bMapper SetInputConnection [bs GetOutputPort] +vtkActor b1 + b1 SetMapper bMapper + b1 SetTexture t + +# The second elliptical button +vtkEllipticalButtonSource bs2 + bs2 SetWidth 2 + bs2 SetHeight 1 + bs2 SetDepth 0.2 + bs2 SetCircumferentialResolution 64 + bs2 SetRadialRatio 1.1 + bs2 SetShoulderResolution 8 + bs2 SetTextureResolution 4 + bs2 TwoSidedOn + bs2 SetCenter 2 0 0 + bs2 SetTextureStyleToFitImage + bs2 SetTextureDimensions $d1 $d2 +vtkPolyDataMapper b2Mapper + b2Mapper SetInputConnection [bs2 GetOutputPort] +vtkActor b2 + b2 SetMapper b2Mapper + b2 SetTexture t + +# The third rectangular button +vtkRectangularButtonSource bs3 + bs3 SetWidth 1.5 + bs3 SetHeight 0.75 + bs3 SetDepth 0.2 + bs3 TwoSidedOn + bs3 SetCenter 0 1 0 + bs3 SetTextureDimensions $d1 $d2 +vtkPolyDataMapper b3Mapper + b3Mapper SetInputConnection [bs3 GetOutputPort] +vtkActor b3 + b3 SetMapper b3Mapper + b3 SetTexture t + +# The fourth rectangular button +vtkRectangularButtonSource bs4 + bs4 SetWidth 1.5 + bs4 SetHeight 0.75 + bs4 SetDepth 0.2 + bs4 TwoSidedOn + bs4 SetCenter 2 1 0 + bs4 SetTextureStyleToFitImage + bs4 SetTextureDimensions $d1 $d2 +vtkPolyDataMapper b4Mapper + b4Mapper SetInputConnection [bs4 GetOutputPort] +vtkActor b4 + b4 SetMapper b4Mapper + b4 SetTexture t + +# Create the RenderWindow, Renderer and Interactive Renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor b1 +ren1 AddActor b2 +ren1 AddActor b3 +ren1 AddActor b4 +ren1 SetBackground 0 0 0 + +renWin SetSize 250 150 +renWin Render +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestCameraInterpolator.tcl b/Graphics/Testing/Tcl/TestCameraInterpolator.tcl new file mode 100644 index 0000000..c319806 --- /dev/null +++ b/Graphics/Testing/Tcl/TestCameraInterpolator.tcl @@ -0,0 +1,120 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +vtkLookupTable lut + lut SetHueRange 0.6 0 + lut SetSaturationRange 1.0 0 + lut SetValueRange 0.5 1.0 + +# Read the data: a height field results +vtkDEMReader demReader + demReader SetFileName "$VTK_DATA_ROOT/Data/SainteHelens.dem" + demReader Update + +set lo [lindex [[demReader GetOutput] GetScalarRange] 0] +set hi [lindex [[demReader GetOutput] GetScalarRange] 1] + +vtkImageDataGeometryFilter surface + surface SetInputConnection [demReader GetOutputPort] + +vtkWarpScalar warp + warp SetInputConnection [surface GetOutputPort] + warp SetScaleFactor 1 + warp UseNormalOn + warp SetNormal 0 0 1 + +vtkPolyDataNormals normals + normals SetInput [warp GetPolyDataOutput] + normals SetFeatureAngle 60 + normals SplittingOff + +vtkPolyDataMapper demMapper + demMapper SetInputConnection [normals GetOutputPort] + eval demMapper SetScalarRange $lo $hi + demMapper SetLookupTable lut + +vtkLODActor demActor + demActor SetMapper demMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor demActor + +ren1 SetBackground 0 0 0 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +vtkCamera view1 +view1 SetClippingRange 30972.2 35983.7 +view1 SetFocalPoint 562835 5.11498e+006 2294.5 +view1 SetPosition 562835 5.11498e+006 35449.9 +view1 SetViewAngle 30 +view1 SetViewUp 0 1 0 + +vtkCamera view2 +view2 SetClippingRange 9013.43 13470.4 +view2 SetFocalPoint 562835 5.11498e+006 2294.5 +view2 SetPosition 562835 5.11498e+006 13269.4 +view2 SetViewAngle 30 +view2 SetViewUp 0 1 0 + +vtkCamera view3 +view3 SetClippingRange 4081.2 13866.4 +view3 SetFocalPoint 562853 5.11586e+006 2450.05 +view3 SetPosition 562853 5.1144e+006 10726.6 +view3 SetViewAngle 30 +view3 SetViewUp 0 0.984808 0.173648 + +vtkCamera view4 +view4 SetClippingRange 14.0481 14048.1 +view4 SetFocalPoint 562880 5.11652e+006 2733.15 +view4 SetPosition 562974 5.11462e+006 6419.98 +view4 SetViewAngle 30 +view4 SetViewUp 0.0047047 0.888364 0.459116 + +vtkCamera view5 +view5 SetClippingRange 14.411 14411 +view5 SetFocalPoint 562910 5.11674e+006 3027.15 +view5 SetPosition 562414 5.11568e+006 3419.87 +view5 SetViewAngle 30 +view5 SetViewUp -0.0301976 0.359864 0.932516 + +vtkCameraInterpolator interpolator +interpolator SetInterpolationTypeToSpline +interpolator AddCamera 0 view1 +interpolator AddCamera 5 view2 +interpolator AddCamera 7.5 view3 +interpolator AddCamera 9.0 view4 +interpolator AddCamera 11.0 view5 + +vtkCamera camera +ren1 SetActiveCamera camera +proc animate {} { + set numSteps 500 + set min [interpolator GetMinimumT] + set max [interpolator GetMaximumT] + for {set i 0} {$i <= $numSteps} {incr i} { + set t [expr double($i) * ($max - $min) / double($numSteps)] + interpolator InterpolateCamera $t camera + renWin Render + } +} +interpolator InterpolateCamera 8.2 camera +#animate diff --git a/Graphics/Testing/Tcl/TestCellDerivs.tcl b/Graphics/Testing/Tcl/TestCellDerivs.tcl new file mode 100644 index 0000000..de88691 --- /dev/null +++ b/Graphics/Testing/Tcl/TestCellDerivs.tcl @@ -0,0 +1,653 @@ +package require vtk +package require vtkinteraction + +# Demonstrates vtkCellDerivatives for all cell types +# + +# get the interactor ui + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a scene with one of each cell type +# Voxel +vtkPoints voxelPoints + voxelPoints SetNumberOfPoints 8 + voxelPoints InsertPoint 0 0 0 0 + voxelPoints InsertPoint 1 1 0 0 + voxelPoints InsertPoint 2 0 1 0 + voxelPoints InsertPoint 3 1 1 0 + voxelPoints InsertPoint 4 0 0 1 + voxelPoints InsertPoint 5 1 0 1 + voxelPoints InsertPoint 6 0 1 1 + voxelPoints InsertPoint 7 1 1 1 + +vtkVoxel aVoxel + [aVoxel GetPointIds] SetId 0 0 + [aVoxel GetPointIds] SetId 1 1 + [aVoxel GetPointIds] SetId 2 2 + [aVoxel GetPointIds] SetId 3 3 + [aVoxel GetPointIds] SetId 4 4 + [aVoxel GetPointIds] SetId 5 5 + [aVoxel GetPointIds] SetId 6 6 + [aVoxel GetPointIds] SetId 7 7 + + +vtkUnstructuredGrid aVoxelGrid + aVoxelGrid Allocate 1 1 + aVoxelGrid InsertNextCell [aVoxel GetCellType] [aVoxel GetPointIds] + aVoxelGrid SetPoints voxelPoints + +vtkDataSetMapper aVoxelMapper +aVoxelMapper SetInput aVoxelGrid + +vtkActor aVoxelActor + aVoxelActor SetMapper aVoxelMapper + [aVoxelActor GetProperty] BackfaceCullingOn + +# Hexahedron + +vtkPoints hexahedronPoints + hexahedronPoints SetNumberOfPoints 8 + hexahedronPoints InsertPoint 0 0 0 0 + hexahedronPoints InsertPoint 1 1 0 0 + hexahedronPoints InsertPoint 2 1 1 0 + hexahedronPoints InsertPoint 3 0 1 0 + hexahedronPoints InsertPoint 4 0 0 1 + hexahedronPoints InsertPoint 5 1 0 1 + hexahedronPoints InsertPoint 6 1 1 1 + hexahedronPoints InsertPoint 7 0 1 1 + +vtkHexahedron aHexahedron + [aHexahedron GetPointIds] SetId 0 0 + [aHexahedron GetPointIds] SetId 1 1 + [aHexahedron GetPointIds] SetId 2 2 + [aHexahedron GetPointIds] SetId 3 3 + [aHexahedron GetPointIds] SetId 4 4 + [aHexahedron GetPointIds] SetId 5 5 + [aHexahedron GetPointIds] SetId 6 6 + [aHexahedron GetPointIds] SetId 7 7 + + +vtkUnstructuredGrid aHexahedronGrid + aHexahedronGrid Allocate 1 1 + aHexahedronGrid InsertNextCell [aHexahedron GetCellType] [aHexahedron GetPointIds] + aHexahedronGrid SetPoints hexahedronPoints + +vtkDataSetMapper aHexahedronMapper + aHexahedronMapper SetInput aHexahedronGrid + +vtkActor aHexahedronActor + aHexahedronActor SetMapper aHexahedronMapper + aHexahedronActor AddPosition 2 0 0 + [aHexahedronActor GetProperty] BackfaceCullingOn + +# Tetra + +vtkPoints tetraPoints + tetraPoints SetNumberOfPoints 4 + tetraPoints InsertPoint 0 0 0 0 + tetraPoints InsertPoint 1 1 0 0 + tetraPoints InsertPoint 2 0 1 0 + tetraPoints InsertPoint 3 1 1 1 + +vtkTetra aTetra + [aTetra GetPointIds] SetId 0 0 + [aTetra GetPointIds] SetId 1 1 + [aTetra GetPointIds] SetId 2 2 + [aTetra GetPointIds] SetId 3 3 + + +vtkUnstructuredGrid aTetraGrid + aTetraGrid Allocate 1 1 + aTetraGrid InsertNextCell [aTetra GetCellType] [aTetra GetPointIds] + aTetraGrid SetPoints tetraPoints + +vtkDataSetMapper aTetraMapper + aTetraMapper SetInput aTetraGrid + +vtkActor aTetraActor + aTetraActor SetMapper aTetraMapper + aTetraActor AddPosition 4 0 0 + [aTetraActor GetProperty] BackfaceCullingOn + +# Wedge + +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 6 + wedgePoints InsertPoint 0 0 1 0 + wedgePoints InsertPoint 1 0 0 0 + wedgePoints InsertPoint 2 0 .5 .5 + wedgePoints InsertPoint 3 1 1 0 + wedgePoints InsertPoint 4 1 0 0 + wedgePoints InsertPoint 5 1 .5 .5 + +vtkWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + + +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeGrid + +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + aWedgeActor AddPosition 6 0 0 + [aWedgeActor GetProperty] BackfaceCullingOn + +# Pyramid + +vtkPoints pyramidPoints + pyramidPoints SetNumberOfPoints 5 + pyramidPoints InsertPoint 0 0 0 0 + pyramidPoints InsertPoint 1 1 0 0 + pyramidPoints InsertPoint 2 1 1 0 + pyramidPoints InsertPoint 3 0 1 0 + pyramidPoints InsertPoint 4 .5 .5 1 + +vtkPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + + +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyramidPoints + +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid + +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + aPyramidActor AddPosition 8 0 0 + [aPyramidActor GetProperty] BackfaceCullingOn + +# Pixel + +vtkPoints pixelPoints + pixelPoints SetNumberOfPoints 4 + pixelPoints InsertPoint 0 0 0 0 + pixelPoints InsertPoint 1 1 0 0 + pixelPoints InsertPoint 2 0 1 0 + pixelPoints InsertPoint 3 1 1 0 + +vtkPixel aPixel + [aPixel GetPointIds] SetId 0 0 + [aPixel GetPointIds] SetId 1 1 + [aPixel GetPointIds] SetId 2 2 + [aPixel GetPointIds] SetId 3 3 + + +vtkUnstructuredGrid aPixelGrid + aPixelGrid Allocate 1 1 + aPixelGrid InsertNextCell [aPixel GetCellType] [aPixel GetPointIds] + aPixelGrid SetPoints pixelPoints + +vtkDataSetMapper aPixelMapper + aPixelMapper SetInput aPixelGrid + +vtkActor aPixelActor + aPixelActor SetMapper aPixelMapper + aPixelActor AddPosition 0 0 2 + [aPixelActor GetProperty] BackfaceCullingOn + +# Quad + +vtkPoints quadPoints + quadPoints SetNumberOfPoints 4 + quadPoints InsertPoint 0 0 0 0 + quadPoints InsertPoint 1 1 0 0 + quadPoints InsertPoint 2 1 1 0 + quadPoints InsertPoint 3 0 1 0 + +vtkQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + + +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid + +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + aQuadActor AddPosition 2 0 2 + [aQuadActor GetProperty] BackfaceCullingOn + +# Triangle + +vtkPoints trianglePoints + trianglePoints SetNumberOfPoints 3 + trianglePoints InsertPoint 0 0 0 0 + trianglePoints InsertPoint 1 1 0 0 + trianglePoints InsertPoint 2 .5 .5 0 + +vtkFloatArray triangleTCoords + triangleTCoords SetNumberOfComponents 2 + triangleTCoords SetNumberOfTuples 3 + triangleTCoords InsertTuple2 0 1 1 + triangleTCoords InsertTuple2 1 2 2 + triangleTCoords InsertTuple2 2 3 3 + +vtkTriangle aTriangle + [aTriangle GetPointIds] SetId 0 0 + [aTriangle GetPointIds] SetId 1 1 + [aTriangle GetPointIds] SetId 2 2 + + +vtkUnstructuredGrid aTriangleGrid + aTriangleGrid Allocate 1 1 + aTriangleGrid InsertNextCell [aTriangle GetCellType] [aTriangle GetPointIds] + aTriangleGrid SetPoints trianglePoints + [aTriangleGrid GetPointData] SetTCoords triangleTCoords + +vtkDataSetMapper aTriangleMapper + aTriangleMapper SetInput aTriangleGrid + +vtkActor aTriangleActor + aTriangleActor SetMapper aTriangleMapper + aTriangleActor AddPosition 4 0 2 + [aTriangleActor GetProperty] BackfaceCullingOn + +# Polygon + +vtkPoints polygonPoints + polygonPoints SetNumberOfPoints 4 + polygonPoints InsertPoint 0 0 0 0 + polygonPoints InsertPoint 1 1 0 0 + polygonPoints InsertPoint 2 1 1 0 + polygonPoints InsertPoint 3 0 1 0 + +vtkPolygon aPolygon + [aPolygon GetPointIds] SetNumberOfIds 4 + [aPolygon GetPointIds] SetId 0 0 + [aPolygon GetPointIds] SetId 1 1 + [aPolygon GetPointIds] SetId 2 2 + [aPolygon GetPointIds] SetId 3 3 + + +vtkUnstructuredGrid aPolygonGrid + aPolygonGrid Allocate 1 1 + aPolygonGrid InsertNextCell [aPolygon GetCellType] [aPolygon GetPointIds] + aPolygonGrid SetPoints polygonPoints + +vtkDataSetMapper aPolygonMapper + aPolygonMapper SetInput aPolygonGrid + +vtkActor aPolygonActor + aPolygonActor SetMapper aPolygonMapper + aPolygonActor AddPosition 6 0 2 + [aPolygonActor GetProperty] BackfaceCullingOn + +# Triangle strip + +vtkPoints triangleStripPoints + triangleStripPoints SetNumberOfPoints 5 + triangleStripPoints InsertPoint 0 0 1 0 + triangleStripPoints InsertPoint 1 0 0 0 + triangleStripPoints InsertPoint 2 1 1 0 + triangleStripPoints InsertPoint 3 1 0 0 + triangleStripPoints InsertPoint 4 2 1 0 + +vtkFloatArray triangleStripTCoords + triangleStripTCoords SetNumberOfComponents 2 + triangleStripTCoords SetNumberOfTuples 3 + triangleStripTCoords InsertTuple2 0 1 1 + triangleStripTCoords InsertTuple2 1 2 2 + triangleStripTCoords InsertTuple2 2 3 3 + triangleStripTCoords InsertTuple2 3 4 4 + triangleStripTCoords InsertTuple2 4 5 5 + +vtkTriangleStrip aTriangleStrip + [aTriangleStrip GetPointIds] SetNumberOfIds 5 + [aTriangleStrip GetPointIds] SetId 0 0 + [aTriangleStrip GetPointIds] SetId 1 1 + [aTriangleStrip GetPointIds] SetId 2 2 + [aTriangleStrip GetPointIds] SetId 3 3 + [aTriangleStrip GetPointIds] SetId 4 4 + + +vtkUnstructuredGrid aTriangleStripGrid + aTriangleStripGrid Allocate 1 1 + aTriangleStripGrid InsertNextCell [aTriangleStrip GetCellType] [aTriangleStrip GetPointIds] + aTriangleStripGrid SetPoints triangleStripPoints + [aTriangleStripGrid GetPointData] SetTCoords triangleStripTCoords + +vtkDataSetMapper aTriangleStripMapper + aTriangleStripMapper SetInput aTriangleStripGrid + +vtkActor aTriangleStripActor + aTriangleStripActor SetMapper aTriangleStripMapper + aTriangleStripActor AddPosition 8 0 2 + [aTriangleStripActor GetProperty] BackfaceCullingOn + +# Line + +vtkPoints linePoints + linePoints SetNumberOfPoints 2 + linePoints InsertPoint 0 0 0 0 + linePoints InsertPoint 1 1 1 0 + +vtkLine aLine + [aLine GetPointIds] SetId 0 0 + [aLine GetPointIds] SetId 1 1 + + +vtkUnstructuredGrid aLineGrid + aLineGrid Allocate 1 1 + aLineGrid InsertNextCell [aLine GetCellType] [aLine GetPointIds] + aLineGrid SetPoints linePoints + +vtkDataSetMapper aLineMapper + aLineMapper SetInput aLineGrid + +vtkActor aLineActor + aLineActor SetMapper aLineMapper + aLineActor AddPosition 0 0 4 + [aLineActor GetProperty] BackfaceCullingOn + +# Polyline + +vtkPoints polyLinePoints + polyLinePoints SetNumberOfPoints 3 + polyLinePoints InsertPoint 0 0 0 0 + polyLinePoints InsertPoint 1 1 1 0 + polyLinePoints InsertPoint 2 1 0 0 + +vtkPolyLine aPolyLine + [aPolyLine GetPointIds] SetNumberOfIds 3 + [aPolyLine GetPointIds] SetId 0 0 + [aPolyLine GetPointIds] SetId 1 1 + [aPolyLine GetPointIds] SetId 2 2 + + +vtkUnstructuredGrid aPolyLineGrid + aPolyLineGrid Allocate 1 1 + aPolyLineGrid InsertNextCell [aPolyLine GetCellType] [aPolyLine GetPointIds] + aPolyLineGrid SetPoints polyLinePoints + +vtkDataSetMapper aPolyLineMapper + aPolyLineMapper SetInput aPolyLineGrid + +vtkActor aPolyLineActor + aPolyLineActor SetMapper aPolyLineMapper + aPolyLineActor AddPosition 2 0 4 + [aPolyLineActor GetProperty] BackfaceCullingOn + +# Vertex + +vtkPoints vertexPoints + vertexPoints SetNumberOfPoints 1 + vertexPoints InsertPoint 0 0 0 0 + +vtkVertex aVertex + [aVertex GetPointIds] SetId 0 0 + + +vtkUnstructuredGrid aVertexGrid + aVertexGrid Allocate 1 1 + aVertexGrid InsertNextCell [aVertex GetCellType] [aVertex GetPointIds] + aVertexGrid SetPoints vertexPoints + +vtkDataSetMapper aVertexMapper + aVertexMapper SetInput aVertexGrid + +vtkActor aVertexActor + aVertexActor SetMapper aVertexMapper + aVertexActor AddPosition 0 0 6 + [aVertexActor GetProperty] BackfaceCullingOn + +# Polyvertex + +vtkPoints polyVertexPoints + polyVertexPoints SetNumberOfPoints 3 + polyVertexPoints InsertPoint 0 0 0 0 + polyVertexPoints InsertPoint 1 1 0 0 + polyVertexPoints InsertPoint 2 1 1 0 + +vtkPolyVertex aPolyVertex + [aPolyVertex GetPointIds] SetNumberOfIds 3 + [aPolyVertex GetPointIds] SetId 0 0 + [aPolyVertex GetPointIds] SetId 1 1 + [aPolyVertex GetPointIds] SetId 2 2 + + +vtkUnstructuredGrid aPolyVertexGrid + aPolyVertexGrid Allocate 1 1 + aPolyVertexGrid InsertNextCell [aPolyVertex GetCellType] [aPolyVertex GetPointIds] + aPolyVertexGrid SetPoints polyVertexPoints + +vtkDataSetMapper aPolyVertexMapper + aPolyVertexMapper SetInput aPolyVertexGrid + +vtkActor aPolyVertexActor + aPolyVertexActor SetMapper aPolyVertexMapper + aPolyVertexActor AddPosition 2 0 6 + [aPolyVertexActor GetProperty] BackfaceCullingOn + + +# Pentagonal prism + +vtkPoints pentaPoints + pentaPoints SetNumberOfPoints 10 + pentaPoints InsertPoint 0 0.25 0.0 0.0 + pentaPoints InsertPoint 1 0.75 0.0 0.0 + pentaPoints InsertPoint 2 1.0 0.5 0.0 + pentaPoints InsertPoint 3 0.5 1.0 0.0 + pentaPoints InsertPoint 4 0.0 0.5 0.0 + pentaPoints InsertPoint 5 0.25 0.0 1.0 + pentaPoints InsertPoint 6 0.75 0.0 1.0 + pentaPoints InsertPoint 7 1.0 0.5 1.0 + pentaPoints InsertPoint 8 0.5 1.0 1.0 + pentaPoints InsertPoint 9 0.0 0.5 1.0 + +vtkPentagonalPrism aPenta + [aPenta GetPointIds] SetId 0 0 + [aPenta GetPointIds] SetId 1 1 + [aPenta GetPointIds] SetId 2 2 + [aPenta GetPointIds] SetId 3 3 + [aPenta GetPointIds] SetId 4 4 + [aPenta GetPointIds] SetId 5 5 + [aPenta GetPointIds] SetId 6 6 + [aPenta GetPointIds] SetId 7 7 + [aPenta GetPointIds] SetId 8 8 + [aPenta GetPointIds] SetId 9 9 + + +vtkUnstructuredGrid aPentaGrid + aPentaGrid Allocate 1 1 + aPentaGrid InsertNextCell [aPenta GetCellType] [aPenta GetPointIds] + aPentaGrid SetPoints pentaPoints + +vtkDataSetMapper aPentaMapper + aPentaMapper SetInput aPentaGrid + +vtkActor aPentaActor + aPentaActor SetMapper aPentaMapper + aPentaActor AddPosition 10 0 0 + [aPentaActor GetProperty] BackfaceCullingOn + +# Hexagonal prism + +vtkPoints hexaPoints + hexaPoints SetNumberOfPoints 12 + hexaPoints InsertPoint 0 0.0 0.0 0.0 + hexaPoints InsertPoint 1 0.5 0.0 0.0 + hexaPoints InsertPoint 2 1.0 0.5 0.0 + hexaPoints InsertPoint 3 1.0 1.0 0.0 + hexaPoints InsertPoint 4 0.5 1.0 0.0 + hexaPoints InsertPoint 5 0.0 0.5 0.0 + hexaPoints InsertPoint 6 0.0 0.0 1.0 + hexaPoints InsertPoint 7 0.5 0.0 1.0 + hexaPoints InsertPoint 8 1.0 0.5 1.0 + hexaPoints InsertPoint 9 1.0 1.0 1.0 + hexaPoints InsertPoint 10 0.5 1.0 1.0 + hexaPoints InsertPoint 11 0.0 0.5 1.0 + +vtkHexagonalPrism aHexa + [aHexa GetPointIds] SetId 0 0 + [aHexa GetPointIds] SetId 1 1 + [aHexa GetPointIds] SetId 2 2 + [aHexa GetPointIds] SetId 3 3 + [aHexa GetPointIds] SetId 4 4 + [aHexa GetPointIds] SetId 5 5 + [aHexa GetPointIds] SetId 6 6 + [aHexa GetPointIds] SetId 7 7 + [aHexa GetPointIds] SetId 8 8 + [aHexa GetPointIds] SetId 9 9 + [aHexa GetPointIds] SetId 10 10 + [aHexa GetPointIds] SetId 11 11 + + +vtkUnstructuredGrid aHexaGrid + aHexaGrid Allocate 1 1 + aHexaGrid InsertNextCell [aHexa GetCellType] [aHexa GetPointIds] + aHexaGrid SetPoints hexaPoints + +vtkDataSetMapper aHexaMapper + aHexaMapper SetInput aHexaGrid + +vtkActor aHexaActor + aHexaActor SetMapper aHexaMapper + aHexaActor AddPosition 12 0 0 + [aHexaActor GetProperty] BackfaceCullingOn + + +ren1 SetBackground 1 1 1 + +ren1 AddActor aVoxelActor; [aVoxelActor GetProperty] SetDiffuseColor 1 0 0 +ren1 AddActor aHexahedronActor; [aHexahedronActor GetProperty] SetDiffuseColor 1 1 0 +ren1 AddActor aTetraActor; [aTetraActor GetProperty] SetDiffuseColor 0 1 0 +ren1 AddActor aWedgeActor; [aWedgeActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aPyramidActor; [aPyramidActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aPixelActor; [aPixelActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aQuadActor; [aQuadActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aTriangleActor; [aTriangleActor GetProperty] SetDiffuseColor .3 1 .5 +ren1 AddActor aPolygonActor; [aPolygonActor GetProperty] SetDiffuseColor 1 .4 .5 +ren1 AddActor aTriangleStripActor; [aTriangleStripActor GetProperty] SetDiffuseColor .3 .7 1 +ren1 AddActor aLineActor; [aLineActor GetProperty] SetDiffuseColor .2 1 1 +ren1 AddActor aPolyLineActor; [aPolyLineActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aVertexActor; [aVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPolyVertexActor; [aPolyVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPentaActor; [aPentaActor GetProperty] SetDiffuseColor 1 1 0 +ren1 AddActor aHexaActor; [aHexaActor GetProperty] SetDiffuseColor 1 1 0 + +# +# get the cell center of each type and put a glyph there +# +vtkSphereSource ball + ball SetRadius .2 + +foreach cell "aVoxel aHexahedron aWedge aPyramid aTetra aPixel aQuad aTriangle aPolygon \ +aTriangleStrip aLine aPolyLine aVertex aPolyVertex aPenta aHexa" { + vtkFloatArray ${cell}Scalars + set N [${cell}Grid GetNumberOfPoints ] + vtkFloatArray ${cell}Scalar + ${cell}Scalar SetNumberOfTuples $N + ${cell}Scalar SetNumberOfComponents 1 + for {set i 0} {$i < $N} {incr i 1} { + ${cell}Scalar SetValue $i 0} + ${cell}Scalar SetValue 0 4 + + [${cell}Grid GetPointData] SetScalars ${cell}Scalar + + } + +# write to the temp directory if possible, otherwise use . +set dir "." +if {[info commands "rtTester"] == "rtTester"} { + set dir [rtTester GetTempDirectory] +} + + +foreach cell "aVoxel aHexahedron aWedge aPyramid aTetra aQuad aTriangle aTriangleStrip aLine \ +aPolyLine aVertex aPolyVertex aPixel aPolygon aPenta aHexa" { + + vtkCellDerivatives ${cell}derivs + ${cell}derivs SetInput ${cell}Grid + ${cell}derivs SetVectorModeToComputeGradient + + set FileName $dir + append FileName $cell + append FileName ".vtk" + + # make sure the directory is writeable first + if {[catch {set channel [open "$dir/test.tmp" "w"]}] == 0 } { + close $channel + file delete -force "$dir/test.tmp" + + vtkUnstructuredGridWriter ${cell}Writer + ${cell}Writer SetInputConnection [${cell}derivs GetOutputPort] + ${cell}Writer SetFileName $FileName + ${cell}Writer Write + # delete the file + file delete -force $FileName + } + + vtkCellCenters ${cell}Centers + ${cell}Centers SetInputConnection [${cell}derivs GetOutputPort] + ${cell}Centers VertexCellsOn + + vtkHedgeHog ${cell}hog + ${cell}hog SetInputConnection [${cell}Centers GetOutputPort] + + vtkPolyDataMapper ${cell}mapHog + ${cell}mapHog SetInputConnection [${cell}hog GetOutputPort] + ${cell}mapHog SetScalarModeToUseCellData + ${cell}mapHog ScalarVisibilityOff + vtkActor ${cell}hogActor + ${cell}hogActor SetMapper ${cell}mapHog + [${cell}hogActor GetProperty] SetColor 0 1 0 + + vtkGlyph3D ${cell}Glyph3D + ${cell}Glyph3D SetInputConnection [${cell}Centers GetOutputPort] + ${cell}Glyph3D SetSource [ball GetOutput] + vtkPolyDataMapper ${cell}CentersMapper + ${cell}CentersMapper SetInputConnection [${cell}Glyph3D GetOutputPort] + vtkActor ${cell}CentersActor + ${cell}CentersActor SetMapper ${cell}CentersMapper + eval ${cell}hogActor SetPosition [${cell}Actor GetPosition] + ren1 AddActor ${cell}hogActor + [${cell}hogActor GetProperty] SetRepresentationToWireframe +} + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Dolly 3.0 +ren1 ResetCameraClippingRange + +renWin SetSize 300 150 +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + + + diff --git a/Graphics/Testing/Tcl/TestConvexPointSet.tcl b/Graphics/Testing/Tcl/TestConvexPointSet.tcl new file mode 100644 index 0000000..80bde6e --- /dev/null +++ b/Graphics/Testing/Tcl/TestConvexPointSet.tcl @@ -0,0 +1,112 @@ +package require vtk +package require vtkinteraction + +# create points in the configuration of an octant with one 2:1 face +# +vtkPoints points +vtkConvexPointSet aConvex +points InsertPoint 0 0 0 0 +points InsertPoint 1 1 0 0 +points InsertPoint 2 1 1 0 +points InsertPoint 3 0 1 0 +points InsertPoint 4 0 0 1 +points InsertPoint 5 1 0 1 +points InsertPoint 6 1 1 1 +points InsertPoint 7 0 1 1 +points InsertPoint 8 0.5 0 0 +points InsertPoint 9 1 0.5 0 +points InsertPoint 10 0.5 1 0 +points InsertPoint 11 0 0.5 0 +points InsertPoint 12 0.5 0.5 0 +for {set i 0} {$i<13} {incr i 1} { + [aConvex GetPointIds] InsertId $i $i +} + +vtkUnstructuredGrid aConvexGrid + aConvexGrid Allocate 1 1 + aConvexGrid InsertNextCell [aConvex GetCellType] [aConvex GetPointIds] + aConvexGrid SetPoints points + +# Display the cell +vtkDataSetMapper dsm + dsm SetInput aConvexGrid +vtkActor a + a SetMapper dsm + eval [a GetProperty] SetColor 0 1 0 + +# Contour and clip the cell with elevation scalars +vtkElevationFilter ele + ele SetInput aConvexGrid + ele SetLowPoint -1 -1 -1 + ele SetHighPoint 1 1 1 + ele SetScalarRange -1 1 + +# Clip +# +vtkClipDataSet clip + clip SetInputConnection [ele GetOutputPort] + clip SetValue 0.5 +vtkDataSetSurfaceFilter g + g SetInputConnection [clip GetOutputPort] +vtkPolyDataMapper map + map SetInputConnection [g GetOutputPort] + map ScalarVisibilityOff +vtkActor clipActor + clipActor SetMapper map + [clipActor GetProperty] SetColor 1 0 0 + clipActor AddPosition 2 0 0 + +# Contour +# +vtkContourFilter contour + contour SetInputConnection [ele GetOutputPort] + contour SetValue 0 0.5 +vtkDataSetSurfaceFilter g2 + g2 SetInputConnection [contour GetOutputPort] +vtkPolyDataMapper map2 + map2 SetInputConnection [g2 GetOutputPort] + map2 ScalarVisibilityOff +vtkActor contourActor + contourActor SetMapper map2 + [contourActor GetProperty] SetColor 1 0 0 + contourActor AddPosition 1 2 0 + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor a +ren1 AddActor clipActor +ren1 AddActor contourActor + +ren1 SetBackground 1 1 1 +renWin SetSize 250 150 + +vtkCamera aCam + aCam SetFocalPoint 1.38705 1.37031 0.639901 + aCam SetPosition 1.89458 -5.07106 -4.17439 + aCam SetViewUp 0.00355726 0.598843 -0.800858 + aCam SetClippingRange 4.82121 12.1805 +ren1 SetActiveCamera aCam + +renWin Render + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.5 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/TestCurvatures.tcl b/Graphics/Testing/Tcl/TestCurvatures.tcl new file mode 100644 index 0000000..e196777 --- /dev/null +++ b/Graphics/Testing/Tcl/TestCurvatures.tcl @@ -0,0 +1,108 @@ +package require vtk +package require vtkinteraction + +# Create renderer stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Pipeline stuff +# +vtkSuperquadricSource torus + torus SetCenter 0.0 0.0 0.0 + torus SetScale 1.0 1.0 1.0 + torus SetPhiResolution 64 + torus SetThetaResolution 64 + torus SetPhiRoundness 1.0 + torus SetThetaRoundness 1.0 + torus SetThickness 0.5 + torus SetSize 0.5 + torus SetToroidal 1 + +# The quadric is made of strips, so pass it through a triangle filter as +# the curvature filter only operates on polys +vtkTriangleFilter tri + tri SetInputConnection [torus GetOutputPort] + +# The quadric has nasty discontinuities from the way the edges are generated +# so let's pass it though a CleanPolyDataFilter and merge any points which +# are coincident, or very close + +vtkCleanPolyData cleaner + cleaner SetInputConnection [tri GetOutputPort] + cleaner SetTolerance 0.005 + +vtkCurvatures curve1 + curve1 SetInputConnection [cleaner GetOutputPort] + curve1 SetCurvatureTypeToGaussian + +vtkCurvatures curve2 + curve2 SetInputConnection [cleaner GetOutputPort] + curve2 SetCurvatureTypeToMean + +vtkLookupTable lut1 + lut1 SetNumberOfColors 256 + lut1 SetHueRange 0.15 1.0 + lut1 SetSaturationRange 1.0 1.0 + lut1 SetValueRange 1.0 1.0 + lut1 SetAlphaRange 1.0 1.0 + lut1 SetRange -20 20 + +vtkLookupTable lut2 + lut2 SetNumberOfColors 256 + lut2 SetHueRange 0.15 1.0 + lut2 SetSaturationRange 1.0 1.0 + lut2 SetValueRange 1.0 1.0 + lut2 SetAlphaRange 1.0 1.0 + lut2 SetRange 0 4 + +vtkPolyDataMapper cmapper1 + cmapper1 SetInputConnection [curve1 GetOutputPort] + cmapper1 SetLookupTable lut1 + cmapper1 SetUseLookupTableScalarRange 1 + +vtkPolyDataMapper cmapper2 + cmapper2 SetInputConnection [curve2 GetOutputPort] + cmapper2 SetLookupTable lut2 + cmapper2 SetUseLookupTableScalarRange 1 + +vtkActor cActor1 + cActor1 SetMapper cmapper1 + cActor1 SetPosition -0.5 0.0 0.0 + +vtkActor cActor2 + cActor2 SetMapper cmapper2 + cActor2 SetPosition 0.5 0.0 0.0 + +# Add the actors to the renderer +# +ren1 AddActor cActor1 +ren1 AddActor cActor2 + +ren1 SetBackground 0.5 0.5 0.5 +renWin SetSize 300 200 + +vtkCamera camera +ren1 SetActiveCamera camera + +camera SetPosition 0.0 2.0 2.1 +camera SetFocalPoint 0.0 0.0 0.0 +camera SetViewAngle 30 + +ren1 ResetCameraClippingRange + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + +renWin Render diff --git a/Graphics/Testing/Tcl/TestDiscreteMarchingCubes.tcl b/Graphics/Testing/Tcl/TestDiscreteMarchingCubes.tcl new file mode 100644 index 0000000..8a228e3 --- /dev/null +++ b/Graphics/Testing/Tcl/TestDiscreteMarchingCubes.tcl @@ -0,0 +1,96 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Generate some random colors +proc MakeColors {lut n } { + catch {vtkMath math} + $lut SetNumberOfColors $n + $lut SetTableRange 0 [expr $n-1] + $lut SetScaleToLinear + $lut Build + $lut SetTableValue 0 0 0 0 1 + math RandomSeed 5071 + for {set i 1} {$i < $n } {incr i} { + $lut SetTableValue $i [math Random .2 1] [math Random .2 1] [math Random .2 1] 1 + } +} + +vtkLookupTable lut +MakeColors lut 256 + + + +set n 20 +set radius 10 + +# This has been moved outside the loop so that the code can be correctly +# translated to python +catch {vtkImageData blobImage} +for {set i 0} {$i < $n} {incr i} { + catch {vtkSphere sphere} + sphere SetRadius $radius + set max [expr 50 - $radius] + sphere SetCenter [expr int ( [math Random -$max $max] ) ] [expr int ( [math Random -$max $max] ) ] [expr int ( [math Random -$max $max] ) ] + + catch {vtkSampleFunction sampler} + sampler SetImplicitFunction sphere + sampler SetOutputScalarTypeToFloat + sampler SetSampleDimensions 51 51 51 + sampler SetModelBounds -50 50 -50 50 -50 50 + + catch {vtkImageThreshold thres} + thres SetInputConnection [sampler GetOutputPort] + thres ThresholdByLower [expr $radius * $radius] + thres ReplaceInOn + thres ReplaceOutOn + thres SetInValue [expr $i + 1] + thres SetOutValue 0 + thres Update + + if {$i == 0} { + blobImage DeepCopy [thres GetOutput] + } + + catch {vtkImageMathematics maxValue} + maxValue SetInput 0 blobImage + maxValue SetInput 1 [thres GetOutput] + maxValue SetOperationToMax + maxValue Modified + maxValue Update + + blobImage DeepCopy [maxValue GetOutput] +} + +vtkDiscreteMarchingCubes discrete + discrete SetInput blobImage + discrete GenerateValues $n 1 $n + +vtkPolyDataMapper mapper + mapper SetInputConnection [discrete GetOutputPort] + mapper SetLookupTable lut + mapper SetScalarRange 0 [lut GetNumberOfColors] + +vtkActor actor + actor SetMapper mapper + +ren1 AddActor actor + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TestGraphLayoutFilter.tcl b/Graphics/Testing/Tcl/TestGraphLayoutFilter.tcl new file mode 100644 index 0000000..6c3fedc --- /dev/null +++ b/Graphics/Testing/Tcl/TestGraphLayoutFilter.tcl @@ -0,0 +1,121 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create a simple graph (it's jittered from optimum) +vtkPoints pts +pts SetNumberOfPoints 10 +pts SetPoint 0 -0.5 1.0 -0.3 +pts SetPoint 1 -3.0 0.1 0.2 +pts SetPoint 2 0.0 0.0 0.0 +pts SetPoint 3 1.2 -0.1 -0.2 +pts SetPoint 4 0.2 -3.0 0.2 +pts SetPoint 5 -4.2 -5.5 0.7 +pts SetPoint 6 1.2 -7.3 -0.6 +pts SetPoint 7 4.2 -5.5 0.7 +pts SetPoint 8 0.0 0.0 -0.4 +pts SetPoint 9 0.0 0.0 0.8 + +vtkCellArray lines +lines InsertNextCell 4 +lines InsertCellPoint 0 +lines InsertCellPoint 2 +lines InsertCellPoint 4 +lines InsertCellPoint 6 +lines InsertNextCell 2 +lines InsertCellPoint 1 +lines InsertCellPoint 2 +lines InsertNextCell 2 +lines InsertCellPoint 2 +lines InsertCellPoint 3 +lines InsertNextCell 2 +lines InsertCellPoint 5 +lines InsertCellPoint 6 +lines InsertNextCell 2 +lines InsertCellPoint 6 +lines InsertCellPoint 7 +lines InsertNextCell 2 +lines InsertCellPoint 2 +lines InsertCellPoint 8 +lines InsertNextCell 2 +lines InsertCellPoint 2 +lines InsertCellPoint 9 + +vtkPolyData pd +pd SetPoints pts +pd SetLines lines + +vtkGraphLayoutFilter layout2D + layout2D SetInput pd + layout2D SetMaxNumberOfIterations 100 + layout2D ThreeDimensionalLayoutOff + layout2D AutomaticBoundsComputationOff + layout2D SetGraphBounds -2.0 0.0 -1.0 1.0 -1.0 1.0 + +vtkGraphLayoutFilter layout3D + layout3D SetInput pd + layout3D SetMaxNumberOfIterations 100 + layout3D ThreeDimensionalLayoutOn + layout3D AutomaticBoundsComputationOff + layout3D SetGraphBounds 0.0 2.0 -1.0 1.0 -1.0 1.0 + +vtkAppendPolyData apf + apf AddInput [layout2D GetOutput] + apf AddInput [layout3D GetOutput] + +vtkTubeFilter tubes + tubes SetInputConnection [apf GetOutputPort] + tubes SetRadius 0.01 + tubes SetNumberOfSides 6 +vtkPolyDataMapper mapEdges + mapEdges SetInputConnection [tubes GetOutputPort] +vtkActor edgeActor + edgeActor SetMapper mapEdges + eval [edgeActor GetProperty] SetColor $peacock + [edgeActor GetProperty] SetSpecularColor 1 1 1 + [edgeActor GetProperty] SetSpecular 0.3 + [edgeActor GetProperty] SetSpecularPower 20 + [edgeActor GetProperty] SetAmbient 0.2 + [edgeActor GetProperty] SetDiffuse 0.8 + +vtkSphereSource ball + ball SetRadius 0.025 + ball SetThetaResolution 12 + ball SetPhiResolution 12 +vtkGlyph3D balls + balls SetInputConnection [apf GetOutputPort] + balls SetSource [ball GetOutput] +vtkPolyDataMapper mapBalls + mapBalls SetInputConnection [balls GetOutputPort] +vtkActor ballActor + ballActor SetMapper mapBalls + eval [ballActor GetProperty] SetColor $hot_pink + [ballActor GetProperty] SetSpecularColor 1 1 1 + [ballActor GetProperty] SetSpecular 0.3 + [ballActor GetProperty] SetSpecularPower 20 + [ballActor GetProperty] SetAmbient 0.2 + [ballActor GetProperty] SetDiffuse 0.8 + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor edgeActor +ren1 AddActor ballActor + +ren1 SetBackground 1 1 1 +renWin SetSize 400 250 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.55085 6.01004 + $cam1 SetFocalPoint 0.0427 -0.0149608 0.0 + $cam1 SetPosition 0.0427 -0.0149608 4.63462 + $cam1 SetViewUp 0 1 0 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestGridSynchronizedTemplates3D.tcl b/Graphics/Testing/Tcl/TestGridSynchronizedTemplates3D.tcl new file mode 100644 index 0000000..18b242f --- /dev/null +++ b/Graphics/Testing/Tcl/TestGridSynchronizedTemplates3D.tcl @@ -0,0 +1,77 @@ +package require vtk +package require vtkinteraction + +# cut data +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +set range [[[[pl3d GetOutput] GetPointData] GetScalars] GetRange] +set min [lindex $range 0] +set max [lindex $range 1] +set value [expr ($min + $max) / 2.0] + +#vtkGridSynchronizedTemplates3D cf +vtkContourFilter cf + cf SetInputConnection [pl3d GetOutputPort] + cf SetValue 0 $value + #cf ComputeNormalsOff + +vtkPolyDataMapper cfMapper + cfMapper ImmediateModeRenderingOn + cfMapper SetInputConnection [cf GetOutputPort] + eval cfMapper SetScalarRange \ + [[[[pl3d GetOutput] GetPointData] GetScalars] GetRange] +vtkActor cfActor + cfActor SetMapper cfMapper + +#outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +## Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor cfActor +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# loop over surfaces +for {set i 0} {$i < 17} {incr i} { + cf SetValue 0 [expr $min + ($i/16.0)*($max - $min)] + renWin Render +} + +cf SetValue 0 [expr $min + (0.2)*($max - $min)] +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/TestImageMarchingCubes.tcl b/Graphics/Testing/Tcl/TestImageMarchingCubes.tcl new file mode 100644 index 0000000..f1a7e58 --- /dev/null +++ b/Graphics/Testing/Tcl/TestImageMarchingCubes.tcl @@ -0,0 +1,67 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + v16 Update + +vtkImageMarchingCubes iso + iso SetInputConnection [v16 GetOutputPort] + iso SetValue 0 1150 + iso SetInputMemoryLimit 1000 + +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [iso GetOutputPort] + isoMapper ScalarVisibilityOff + isoMapper ImmediateModeRenderingOn + +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $antique_white + +vtkOutlineFilter outline + outline SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 0.2 0.3 0.4 +renWin SetSize 200 200 +ren1 ResetCamera +[ren1 GetActiveCamera] Elevation 90 +[ren1 GetActiveCamera] SetViewUp 0 0 -1 +[ren1 GetActiveCamera] Azimuth 180 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TestMarchingSquares.tcl b/Graphics/Testing/Tcl/TestMarchingSquares.tcl new file mode 100644 index 0000000..2ecefac --- /dev/null +++ b/Graphics/Testing/Tcl/TestMarchingSquares.tcl @@ -0,0 +1,92 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + v16 Update + +vtkMergePoints myLocator + +vtkMarchingSquares isoXY + isoXY SetInputConnection [v16 GetOutputPort] + isoXY GenerateValues 2 600 1200 + isoXY SetImageRange 0 32 32 63 45 45 + isoXY SetLocator myLocator + +vtkPolyDataMapper isoXYMapper + isoXYMapper SetInputConnection [isoXY GetOutputPort] + isoXYMapper SetScalarRange 600 1200 + +vtkActor isoXYActor + isoXYActor SetMapper isoXYMapper + +vtkMarchingSquares isoYZ + isoYZ SetInputConnection [v16 GetOutputPort] + isoYZ GenerateValues 2 600 1200 + isoYZ SetImageRange 32 32 32 63 46 92 + +vtkPolyDataMapper isoYZMapper + isoYZMapper SetInputConnection [isoYZ GetOutputPort] + isoYZMapper SetScalarRange 600 1200 + +vtkActor isoYZActor + isoYZActor SetMapper isoYZMapper + +vtkMarchingSquares isoXZ + isoXZ SetInputConnection [v16 GetOutputPort] + isoXZ GenerateValues 2 600 1200 + isoXZ SetImageRange 0 32 32 32 0 46 + +vtkPolyDataMapper isoXZMapper + isoXZMapper SetInputConnection [isoXZ GetOutputPort] + isoXZMapper SetScalarRange 600 1200 + +vtkActor isoXZActor + isoXZActor SetMapper isoXZMapper + +vtkOutlineFilter outline + outline SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoXYActor +ren1 AddActor isoYZActor +ren1 AddActor isoXZActor +ren1 SetBackground 0.9 .9 .9 +renWin SetSize 200 200 +[ren1 GetActiveCamera] SetPosition 324.368 284.266 -19.3293 +[ren1 GetActiveCamera] SetFocalPoint 73.5683 120.903 70.7309 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp -0.304692 -0.0563843 -0.950781 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TestMultiBlockStreamer.tcl b/Graphics/Testing/Tcl/TestMultiBlockStreamer.tcl new file mode 100644 index 0000000..e3a12cc --- /dev/null +++ b/Graphics/Testing/Tcl/TestMultiBlockStreamer.tcl @@ -0,0 +1,128 @@ +package require vtk +package require vtkinteraction +vtkRenderer Ren1 +Ren1 SetBackground 0.33 0.35 0.43 + +vtkRenderWindow renWin +renWin AddRenderer Ren1 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkPLOT3DReader Plot3D0 +Plot3D0 SetFileName "$VTK_DATA_ROOT/Data/combxyz.bin" +Plot3D0 SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" +Plot3D0 SetBinaryFile 1 +Plot3D0 SetMultiGrid 0 +Plot3D0 SetHasByteCount 0 +Plot3D0 SetIBlanking 0 +Plot3D0 SetTwoDimensionalGeometry 0 +Plot3D0 SetForceRead 0 +Plot3D0 SetByteOrder 0 + +vtkStructuredGridOutlineFilter Geometry5 +Geometry5 SetInputConnection [Plot3D0 GetOutputPort] + +vtkPolyDataMapper Mapper5 +Mapper5 SetInputConnection [Geometry5 GetOutputPort] +Mapper5 SetImmediateModeRendering 1 +Mapper5 UseLookupTableScalarRangeOn +Mapper5 SetScalarVisibility 0 +Mapper5 SetScalarModeToDefault + +vtkActor Actor5 +Actor5 SetMapper Mapper5 +[Actor5 GetProperty] SetRepresentationToSurface +[Actor5 GetProperty] SetInterpolationToGouraud +[Actor5 GetProperty] SetAmbient 0.15 +[Actor5 GetProperty] SetDiffuse 0.85 +[Actor5 GetProperty] SetSpecular 0.1 +[Actor5 GetProperty] SetSpecularPower 100 +[Actor5 GetProperty] SetSpecularColor 1 1 1 + +[Actor5 GetProperty] SetColor 1 1 1 +Ren1 AddActor Actor5 + +vtkExtractGrid ExtractGrid0 +ExtractGrid0 SetInputConnection [Plot3D0 GetOutputPort] +ExtractGrid0 SetVOI 0 14 0 32 0 24 +ExtractGrid0 SetSampleRate 1 1 1 +ExtractGrid0 SetIncludeBoundary 0 + +vtkExtractGrid ExtractGrid1 +ExtractGrid1 SetInputConnection [Plot3D0 GetOutputPort] +ExtractGrid1 SetVOI 14 29 0 32 0 24 +ExtractGrid1 SetSampleRate 1 1 1 +ExtractGrid1 SetIncludeBoundary 0 + +vtkExtractGrid ExtractGrid2 +ExtractGrid2 SetInputConnection [Plot3D0 GetOutputPort] +ExtractGrid2 SetVOI 29 56 0 32 0 24 +ExtractGrid2 SetSampleRate 1 1 1 +ExtractGrid2 SetIncludeBoundary 0 + +vtkLineSource LineSourceWidget0 +LineSourceWidget0 SetPoint1 3.05638 -3.00497 28.2211 +LineSourceWidget0 SetPoint2 3.05638 3.95916 28.2211 +LineSourceWidget0 SetResolution 20 + +vtkStreamTracer Stream0 +Stream0 AddInput [ExtractGrid0 GetOutput] +Stream0 SetSource [LineSourceWidget0 GetOutput] +Stream0 AddInput [ExtractGrid1 GetOutput] +Stream0 AddInput [ExtractGrid2 GetOutput] +Stream0 SetMaximumPropagationUnit 1 +Stream0 SetMaximumPropagation 20 +Stream0 SetInitialIntegrationStepUnit 2 +Stream0 SetInitialIntegrationStep 0.5 +Stream0 SetIntegrationDirection 0 +Stream0 SetIntegratorType 0 +Stream0 SetMaximumNumberOfSteps 2000 +Stream0 SetTerminalSpeed 1e-12 + +vtkAssignAttribute aa +aa SetInputConnection [Stream0 GetOutputPort] +aa Assign "Normals" "NORMALS" "POINT_DATA" + +vtkRibbonFilter Ribbon0 +Ribbon0 SetInputConnection [aa GetOutputPort] +Ribbon0 SetWidth 0.1 +Ribbon0 SetAngle 0 +Ribbon0 SetDefaultNormal 0 0 1 +Ribbon0 SetVaryWidth 0 + +vtkLookupTable LookupTable1 +LookupTable1 SetNumberOfTableValues 256 +LookupTable1 SetHueRange 0 0.66667 +LookupTable1 SetSaturationRange 1 1 +LookupTable1 SetValueRange 1 1 +LookupTable1 SetTableRange 0.197813 0.710419 +LookupTable1 SetVectorComponent 0 +LookupTable1 Build + +vtkPolyDataMapper Mapper10 +Mapper10 SetInputConnection [Ribbon0 GetOutputPort] +Mapper10 SetImmediateModeRendering 1 +Mapper10 UseLookupTableScalarRangeOn +Mapper10 SetScalarVisibility 1 +Mapper10 SetScalarModeToUsePointFieldData +Mapper10 SelectColorArray "Density" +Mapper10 SetLookupTable LookupTable1 + +vtkActor Actor10 +Actor10 SetMapper Mapper10 +[Actor10 GetProperty] SetRepresentationToSurface +[Actor10 GetProperty] SetInterpolationToGouraud +[Actor10 GetProperty] SetAmbient 0.15 +[Actor10 GetProperty] SetDiffuse 0.85 +[Actor10 GetProperty] SetSpecular 0 +[Actor10 GetProperty] SetSpecularPower 1 +[Actor10 GetProperty] SetSpecularColor 1 1 1 +Ren1 AddActor Actor10 + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestParametricFunctions.tcl b/Graphics/Testing/Tcl/TestParametricFunctions.tcl new file mode 100644 index 0000000..2e63e51 --- /dev/null +++ b/Graphics/Testing/Tcl/TestParametricFunctions.tcl @@ -0,0 +1,550 @@ +# ------------------------------------------------------------ +# Purpose: Test the paraemtric functions. +# ------------------------------------------------------------ + +# ------------------------------------------------------------ +# Call the VTK Tcl packages to make available all VTK commands +# ------------------------------------------------------------ +package require vtk +package require vtkinteraction + +# ------------------------------------------------------------ +# Get a texture +# ------------------------------------------------------------ +vtkJPEGReader textureReader + textureReader SetFileName "$VTK_DATA_ROOT/Data/beach.jpg" +vtkTexture texture + texture SetInputConnection [textureReader GetOutputPort] + +# ------------------------------------------------------------ +# For each parametric surface: +# 1) Create it +# 2) Assign mappers and actors +# 3) Position ths object +# 5) Add a label +# ------------------------------------------------------------ + +# ------------------------------------------------------------ +# Create a torus +# ------------------------------------------------------------ +vtkParametricTorus torus +vtkParametricFunctionSource torusSource + torusSource SetParametricFunction torus + torusSource SetScalarModeToPhase + +vtkPolyDataMapper torusMapper + torusMapper SetInputConnection [torusSource GetOutputPort] + torusMapper SetScalarRange 0 360 + +vtkActor torusActor + torusActor SetMapper torusMapper + torusActor SetPosition 0 12 0 + +vtkTextMapper torusTextMapper + torusTextMapper SetInput "Torus" + [torusTextMapper GetTextProperty] SetJustificationToCentered + [torusTextMapper GetTextProperty] SetVerticalJustificationToCentered + [torusTextMapper GetTextProperty] SetColor 1 0 0 + [torusTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D torusTextActor + torusTextActor SetMapper torusTextMapper + [torusTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [torusTextActor GetPositionCoordinate] SetValue 0 9.5 0 + +# ------------------------------------------------------------ +# Create a klein bottle +# ------------------------------------------------------------ +vtkParametricKlein klein +vtkParametricFunctionSource kleinSource + kleinSource SetParametricFunction klein + kleinSource SetScalarModeToU0V0 + +vtkPolyDataMapper kleinMapper + kleinMapper SetInputConnection [kleinSource GetOutputPort] + kleinMapper SetScalarRange 0 3 + +vtkActor kleinActor + kleinActor SetMapper kleinMapper + kleinActor SetPosition 8 10.5 0 + +vtkTextMapper kleinTextMapper + kleinTextMapper SetInput "Klein" + [kleinTextMapper GetTextProperty] SetJustificationToCentered + [kleinTextMapper GetTextProperty] SetVerticalJustificationToCentered + [kleinTextMapper GetTextProperty] SetColor 1 0 0 + [kleinTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D kleinTextActor + kleinTextActor SetMapper kleinTextMapper + [kleinTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [kleinTextActor GetPositionCoordinate] SetValue 8 9.5 0 + +# ------------------------------------------------------------ +# Create a Figure-8 Klein +# ------------------------------------------------------------ +vtkParametricFigure8Klein klein2 +vtkParametricFunctionSource klein2Source + klein2Source SetParametricFunction klein2 + klein2Source GenerateTextureCoordinatesOn + +vtkPolyDataMapper klein2Mapper + klein2Mapper SetInputConnection [klein2Source GetOutputPort] + klein2Mapper SetScalarRange 0 3 + +vtkActor klein2Actor + klein2Actor SetMapper klein2Mapper + klein2Actor SetPosition 16 12 0 + klein2Actor SetTexture texture + + +vtkTextMapper fig8KleinTextMapper + fig8KleinTextMapper SetInput "Fig-8 Klein" + [fig8KleinTextMapper GetTextProperty] SetJustificationToCentered + [fig8KleinTextMapper GetTextProperty] SetVerticalJustificationToCentered + [fig8KleinTextMapper GetTextProperty] SetColor 1 0 0 + [fig8KleinTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D fig8KleinTextActor + fig8KleinTextActor SetMapper fig8KleinTextMapper + [fig8KleinTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [fig8KleinTextActor GetPositionCoordinate] SetValue 16 9.5 0 + +# ------------------------------------------------------------ +# Create a mobius strip +# ------------------------------------------------------------ +vtkParametricMobius mobius +vtkParametricFunctionSource mobiusSource + mobiusSource SetParametricFunction mobius + mobiusSource GenerateTextureCoordinatesOn + +vtkPolyDataMapper mobiusMapper + mobiusMapper SetInputConnection [mobiusSource GetOutputPort] + +vtkActor mobiusActor + mobiusActor SetMapper mobiusMapper + mobiusActor RotateX 45 + mobiusActor SetPosition 24 12 0 + mobiusActor SetTexture texture + +vtkTextMapper mobiusTextMapper + mobiusTextMapper SetInput "Mobius" + [mobiusTextMapper GetTextProperty] SetJustificationToCentered + [mobiusTextMapper GetTextProperty] SetVerticalJustificationToCentered + [mobiusTextMapper GetTextProperty] SetColor 1 0 0 + [mobiusTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D mobiusTextActor + mobiusTextActor SetMapper mobiusTextMapper + [mobiusTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [mobiusTextActor GetPositionCoordinate] SetValue 24 9.5 0 + +# ------------------------------------------------------------ +# Create a super toroid +# ------------------------------------------------------------ +vtkParametricSuperToroid toroid +toroid SetN1 2 +toroid SetN2 3 +vtkParametricFunctionSource toroidSource + toroidSource SetParametricFunction toroid + toroidSource SetScalarModeToU + +vtkPolyDataMapper toroidMapper + toroidMapper SetInputConnection [toroidSource GetOutputPort] + toroidMapper SetScalarRange 0 6.28 + +vtkActor toroidActor + toroidActor SetMapper toroidMapper + toroidActor SetPosition 0 4 0 + +vtkTextMapper superToroidTextMapper + superToroidTextMapper SetInput "Super Toroid" + [superToroidTextMapper GetTextProperty] SetJustificationToCentered + [superToroidTextMapper GetTextProperty] SetVerticalJustificationToCentered + [superToroidTextMapper GetTextProperty] SetColor 1 0 0 + [superToroidTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D superToroidTextActor + superToroidTextActor SetMapper superToroidTextMapper + [superToroidTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [superToroidTextActor GetPositionCoordinate] SetValue 0 1.5 0 + +# ------------------------------------------------------------ +# Create a super ellipsoid +# ------------------------------------------------------------ +vtkParametricSuperEllipsoid superEllipsoid +superEllipsoid SetXRadius 1.25 +superEllipsoid SetYRadius 1.5 +superEllipsoid SetZRadius 1.0 +superEllipsoid SetN1 1.1 +superEllipsoid SetN2 1.75 +vtkParametricFunctionSource superEllipsoidSource + superEllipsoidSource SetParametricFunction superEllipsoid + superEllipsoidSource SetScalarModeToV + +vtkPolyDataMapper superEllipsoidMapper + superEllipsoidMapper SetInputConnection [superEllipsoidSource GetOutputPort] + superEllipsoidMapper SetScalarRange 0 3.14 + +vtkActor superEllipsoidActor + superEllipsoidActor SetMapper superEllipsoidMapper + superEllipsoidActor SetPosition 8 4 0 + +vtkTextMapper superEllipsoidTextMapper + superEllipsoidTextMapper SetInput "Super Ellipsoid" + [superEllipsoidTextMapper GetTextProperty] SetJustificationToCentered + [superEllipsoidTextMapper GetTextProperty] SetVerticalJustificationToCentered + [superEllipsoidTextMapper GetTextProperty] SetColor 1 0 0 + [superEllipsoidTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D superEllipsoidTextActor + superEllipsoidTextActor SetMapper superEllipsoidTextMapper + [superEllipsoidTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [superEllipsoidTextActor GetPositionCoordinate] SetValue 8 1.5 0 + +# ------------------------------------------------------------ +# Create an open 1D spline +# ------------------------------------------------------------ +vtkMath math +vtkPoints inputPoints +for {set i 0} {$i < 10} {incr i 1} { + set x [math Random -1 1] + set y [math Random -1 1] + set z [math Random -1 1] + inputPoints InsertPoint $i $x $y $z +} +vtkParametricSpline spline + spline SetPoints inputPoints + spline ClosedOff +vtkParametricFunctionSource splineSource + splineSource SetParametricFunction spline + +vtkPolyDataMapper splineMapper + splineMapper SetInputConnection [splineSource GetOutputPort] + +vtkActor splineActor + splineActor SetMapper splineMapper + splineActor SetPosition 16 4 0 + [splineActor GetProperty] SetColor 0 0 0 + +vtkTextMapper splineTextMapper + splineTextMapper SetInput "Open Spline" + [splineTextMapper GetTextProperty] SetJustificationToCentered + [splineTextMapper GetTextProperty] SetVerticalJustificationToCentered + [splineTextMapper GetTextProperty] SetColor 1 0 0 + [splineTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D splineTextActor + splineTextActor SetMapper splineTextMapper + [splineTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [splineTextActor GetPositionCoordinate] SetValue 16 1.5 0 + +# ------------------------------------------------------------ +# Create a closed 1D spline +# ------------------------------------------------------------ +vtkParametricSpline spline2 + spline2 SetPoints inputPoints + spline2 ClosedOn +vtkParametricFunctionSource spline2Source + spline2Source SetParametricFunction spline2 + +vtkPolyDataMapper spline2Mapper + spline2Mapper SetInputConnection [spline2Source GetOutputPort] + +vtkActor spline2Actor + spline2Actor SetMapper spline2Mapper + spline2Actor SetPosition 24 4 0 + [spline2Actor GetProperty] SetColor 0 0 0 + +vtkTextMapper spline2TextMapper + spline2TextMapper SetInput "Closed Spline" + [spline2TextMapper GetTextProperty] SetJustificationToCentered + [spline2TextMapper GetTextProperty] SetVerticalJustificationToCentered + [spline2TextMapper GetTextProperty] SetColor 1 0 0 + [spline2TextMapper GetTextProperty] SetFontSize 14 +vtkActor2D spline2TextActor + spline2TextActor SetMapper spline2TextMapper + [spline2TextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [spline2TextActor GetPositionCoordinate] SetValue 24 1.5 0 + +# ------------------------------------------------------------ +# Create a spiral conic +# ------------------------------------------------------------ +vtkParametricConicSpiral sconic + sconic SetA 0.8 + sconic SetB 2.5 + sconic SetC 0.4 +vtkParametricFunctionSource sconicSource + sconicSource SetParametricFunction sconic + sconicSource SetScalarModeToDistance + +vtkPolyDataMapper sconicMapper + sconicMapper SetInputConnection [sconicSource GetOutputPort] +vtkActor sconicActor + sconicActor SetMapper sconicMapper + sconicMapper SetScalarRange 0 9 + sconicActor SetPosition 0 -4 0 + sconicActor SetScale 1.2 1.2 1.2 + +vtkTextMapper sconicTextMapper + sconicTextMapper SetInput "Spiral Conic" + [sconicTextMapper GetTextProperty] SetJustificationToCentered + [sconicTextMapper GetTextProperty] SetVerticalJustificationToCentered + [sconicTextMapper GetTextProperty] SetColor 1 0 0 + [sconicTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D sconicTextActor + sconicTextActor SetMapper sconicTextMapper + [sconicTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [sconicTextActor GetPositionCoordinate] SetValue 0 -6.5 0 + +# ------------------------------------------------------------ +# Create Boy's surface +# ------------------------------------------------------------ +vtkParametricBoy boy +vtkParametricFunctionSource boySource + boySource SetParametricFunction boy + boySource SetScalarModeToModulus + +vtkPolyDataMapper boyMapper + boyMapper SetInputConnection [boySource GetOutputPort] + boyMapper SetScalarRange 0 2 +vtkActor boyActor + boyActor SetMapper boyMapper + boyActor SetPosition 8 -4 0 + boyActor SetScale 1.5 1.5 1.5 + +vtkTextMapper boyTextMapper + boyTextMapper SetInput "Boy" + [boyTextMapper GetTextProperty] SetJustificationToCentered + [boyTextMapper GetTextProperty] SetVerticalJustificationToCentered + [boyTextMapper GetTextProperty] SetColor 1 0 0 + [boyTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D boyTextActor + boyTextActor SetMapper boyTextMapper + [boyTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [boyTextActor GetPositionCoordinate] SetValue 8 -6.5 0 + +# ------------------------------------------------------------ +# Create a cross cap +# ------------------------------------------------------------ +vtkParametricCrossCap crossCap +vtkParametricFunctionSource crossCapSource + crossCapSource SetParametricFunction crossCap + crossCapSource SetScalarModeToY + +vtkPolyDataMapper crossCapMapper + crossCapMapper SetInputConnection [crossCapSource GetOutputPort] +vtkActor crossCapActor + crossCapActor SetMapper crossCapMapper + crossCapActor RotateX 65 + crossCapActor SetPosition 16 -4 0 + crossCapActor SetScale 1.5 1.5 1.5 + +vtkTextMapper crossCapTextMapper + crossCapTextMapper SetInput "Cross Cap" + [crossCapTextMapper GetTextProperty] SetJustificationToCentered + [crossCapTextMapper GetTextProperty] SetVerticalJustificationToCentered + [crossCapTextMapper GetTextProperty] SetColor 1 0 0 + [crossCapTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D crossCapTextActor + crossCapTextActor SetMapper crossCapTextMapper + [crossCapTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [crossCapTextActor GetPositionCoordinate] SetValue 16 -6.5 0 + +# ------------------------------------------------------------ +# Create Dini's surface +# ------------------------------------------------------------ +vtkParametricDini dini +vtkParametricFunctionSource diniSource + diniSource SetScalarModeToDistance + diniSource SetParametricFunction dini + +vtkPolyDataMapper diniMapper + diniMapper SetInputConnection [diniSource GetOutputPort] + +vtkActor diniActor + diniActor SetMapper diniMapper + diniActor RotateX -90 + diniActor SetPosition 24 -3 0 + diniActor SetScale 1.5 1.5 0.5 + +vtkTextMapper diniTextMapper + diniTextMapper SetInput "Dini" + [diniTextMapper GetTextProperty] SetJustificationToCentered + [diniTextMapper GetTextProperty] SetVerticalJustificationToCentered + [diniTextMapper GetTextProperty] SetColor 1 0 0 + [diniTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D diniTextActor + diniTextActor SetMapper diniTextMapper + [diniTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [diniTextActor GetPositionCoordinate] SetValue 24 -6.5 0 + +# ------------------------------------------------------------ +# Create Enneper's surface +# ------------------------------------------------------------ +vtkParametricEnneper enneper +vtkParametricFunctionSource enneperSource + enneperSource SetParametricFunction enneper + enneperSource SetScalarModeToQuadrant + +vtkPolyDataMapper enneperMapper + enneperMapper SetInputConnection [enneperSource GetOutputPort] + enneperMapper SetScalarRange 1 4 + +vtkActor enneperActor + enneperActor SetMapper enneperMapper + enneperActor SetPosition 0 -12 0 + enneperActor SetScale 0.25 0.25 0.25 + +vtkTextMapper enneperTextMapper + enneperTextMapper SetInput "Enneper" + [enneperTextMapper GetTextProperty] SetJustificationToCentered + [enneperTextMapper GetTextProperty] SetVerticalJustificationToCentered + [enneperTextMapper GetTextProperty] SetColor 1 0 0 + [enneperTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D enneperTextActor + enneperTextActor SetMapper enneperTextMapper + [enneperTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [enneperTextActor GetPositionCoordinate] SetValue 0 -14.5 0 + +# ------------------------------------------------------------ +# Create an ellipsoidal surface +# ------------------------------------------------------------ +vtkParametricEllipsoid ellipsoid + ellipsoid SetXRadius 1 + ellipsoid SetYRadius 0.75 + ellipsoid SetZRadius 0.5 +vtkParametricFunctionSource ellipsoidSource + ellipsoidSource SetParametricFunction ellipsoid + ellipsoidSource SetScalarModeToZ + +vtkPolyDataMapper ellipsoidMapper + ellipsoidMapper SetInputConnection [ellipsoidSource GetOutputPort] + ellipsoidMapper SetScalarRange -0.5 0.5 + +vtkActor ellipsoidActor + ellipsoidActor SetMapper ellipsoidMapper + ellipsoidActor SetPosition 8 -12 0 + ellipsoidActor SetScale 1.5 1.5 1.5 + +vtkTextMapper ellipsoidTextMapper + ellipsoidTextMapper SetInput "Ellipsoid" + [ellipsoidTextMapper GetTextProperty] SetJustificationToCentered + [ellipsoidTextMapper GetTextProperty] SetVerticalJustificationToCentered + [ellipsoidTextMapper GetTextProperty] SetColor 1 0 0 + [ellipsoidTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D ellipsoidTextActor + ellipsoidTextActor SetMapper ellipsoidTextMapper + [ellipsoidTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [ellipsoidTextActor GetPositionCoordinate] SetValue 8 -14.5 0 + +# ------------------------------------------------------------ +# Create an surface with random hills on it. +# Note that for testing, we will disable the +# random generation of the surfaces. This is +# because random number generators do not +# return the same result on different operating +# systems. +# ------------------------------------------------------------ +vtkParametricRandomHills randomHills + randomHills AllowRandomGenerationOff + randomHills GenerateTheHills +vtkParametricFunctionSource randomHillsSource + randomHillsSource SetParametricFunction randomHills + randomHillsSource GenerateTextureCoordinatesOn + +vtkPolyDataMapper randomHillsMapper + randomHillsMapper SetInputConnection [randomHillsSource GetOutputPort] + +vtkActor randomHillsActor + randomHillsActor SetMapper randomHillsMapper + randomHillsActor SetPosition 16 -14 0 + randomHillsActor SetScale 0.2 0.2 0.2 + randomHillsActor SetTexture texture + +vtkTextMapper randomHillsTextMapper + randomHillsTextMapper SetInput "Random Hills" + [randomHillsTextMapper GetTextProperty] SetJustificationToCentered + [randomHillsTextMapper GetTextProperty] SetVerticalJustificationToCentered + [randomHillsTextMapper GetTextProperty] SetColor 1 0 0 + [randomHillsTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D randomHillsTextActor + randomHillsTextActor SetMapper randomHillsTextMapper + [randomHillsTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [randomHillsTextActor GetPositionCoordinate] SetValue 16 -14.5 0 + +# ------------------------------------------------------------ +# Create an Steiner's Roman Surface. +# ------------------------------------------------------------ +vtkParametricRoman roman + roman SetRadius 1.5 +vtkParametricFunctionSource romanSource + romanSource SetParametricFunction roman + romanSource SetScalarModeToX + +vtkPolyDataMapper romanMapper + romanMapper SetInputConnection [romanSource GetOutputPort] + +vtkActor romanActor + romanActor SetMapper romanMapper + romanActor SetPosition 24 -12 0 + +vtkTextMapper romanTextMapper + romanTextMapper SetInput "Roman" + [romanTextMapper GetTextProperty] SetJustificationToCentered + [romanTextMapper GetTextProperty] SetVerticalJustificationToCentered + [romanTextMapper GetTextProperty] SetColor 1 0 0 + [romanTextMapper GetTextProperty] SetFontSize 14 +vtkActor2D romanTextActor + romanTextActor SetMapper romanTextMapper + [romanTextActor GetPositionCoordinate] SetCoordinateSystemToWorld + [romanTextActor GetPositionCoordinate] SetValue 24 -14.5 0 + +# ------------------------------------------------------------ +# Create the RenderWindow, Renderer and both Actors +# ------------------------------------------------------------ +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# add actors +ren1 AddViewProp torusActor +ren1 AddViewProp kleinActor +ren1 AddViewProp klein2Actor +ren1 AddViewProp toroidActor +ren1 AddViewProp superEllipsoidActor +ren1 AddViewProp mobiusActor +ren1 AddViewProp splineActor +ren1 AddViewProp spline2Actor +ren1 AddViewProp sconicActor +ren1 AddViewProp boyActor +ren1 AddViewProp crossCapActor +ren1 AddViewProp diniActor +ren1 AddViewProp enneperActor +ren1 AddViewProp ellipsoidActor +ren1 AddViewProp randomHillsActor +ren1 AddViewProp romanActor +#add text actors +ren1 AddViewProp torusTextActor +ren1 AddViewProp kleinTextActor +ren1 AddViewProp fig8KleinTextActor +ren1 AddViewProp mobiusTextActor +ren1 AddViewProp superToroidTextActor +ren1 AddViewProp superEllipsoidTextActor +ren1 AddViewProp splineTextActor +ren1 AddViewProp spline2TextActor +ren1 AddViewProp sconicTextActor +ren1 AddViewProp boyTextActor +ren1 AddViewProp crossCapTextActor +ren1 AddViewProp diniTextActor +ren1 AddViewProp enneperTextActor +ren1 AddViewProp ellipsoidTextActor +ren1 AddViewProp randomHillsTextActor +ren1 AddViewProp romanTextActor + +ren1 SetBackground 0.7 0.8 1 +renWin SetSize 500 500 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.3 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TestPlatonicSolids.tcl b/Graphics/Testing/Tcl/TestPlatonicSolids.tcl new file mode 100644 index 0000000..aa9a283 --- /dev/null +++ b/Graphics/Testing/Tcl/TestPlatonicSolids.tcl @@ -0,0 +1,117 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create five instances of vtkPlatonicSolidSource +# corresponding to each of the five Platonic solids. +# +vtkPlatonicSolidSource tet + tet SetSolidTypeToTetrahedron +vtkPolyDataMapper tetMapper + tetMapper SetInputConnection [tet GetOutputPort] +vtkActor tetActor + tetActor SetMapper tetMapper + +vtkPlatonicSolidSource cube + cube SetSolidTypeToCube +vtkPolyDataMapper cubeMapper + cubeMapper SetInputConnection [cube GetOutputPort] +vtkActor cubeActor + cubeActor SetMapper cubeMapper + cubeActor AddPosition 2.0 0 0 + +vtkPlatonicSolidSource oct + oct SetSolidTypeToOctahedron +vtkPolyDataMapper octMapper + octMapper SetInputConnection [oct GetOutputPort] +vtkActor octActor + octActor SetMapper octMapper + octActor AddPosition 4.0 0 0 + +vtkPlatonicSolidSource icosa + icosa SetSolidTypeToIcosahedron +vtkPolyDataMapper icosaMapper + icosaMapper SetInputConnection [icosa GetOutputPort] +vtkActor icosaActor + icosaActor SetMapper icosaMapper + icosaActor AddPosition 6.0 0 0 + +vtkPlatonicSolidSource dode + dode SetSolidTypeToDodecahedron +vtkPolyDataMapper dodeMapper + dodeMapper SetInputConnection [dode GetOutputPort] +vtkActor dodeActor + dodeActor SetMapper dodeMapper + dodeActor AddPosition 8.0 0 0 + +# Create rendering stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor tetActor +ren1 AddActor cubeActor +ren1 AddActor octActor +ren1 AddActor icosaActor +ren1 AddActor dodeActor + +# Create a lookup table with colors for each face +# +vtkMath math +vtkLookupTable lut + lut SetNumberOfColors 20 + lut Build + lut SetTableValue 0 1 0 0 1 + lut SetTableValue 1 0 1 0 1 + lut SetTableValue 2 1 1 0 1 + lut SetTableValue 3 0 0 1 1 + lut SetTableValue 4 1 0 1 1 + lut SetTableValue 5 0 1 1 1 + eval lut SetTableValue 6 $spring_green 1.0 + eval lut SetTableValue 7 $lavender 1.0 + eval lut SetTableValue 8 $mint_cream 1.0 + eval lut SetTableValue 9 $violet 1.0 + eval lut SetTableValue 10 $ivory_black 1.0 + eval lut SetTableValue 11 $coral 1.0 + eval lut SetTableValue 12 $pink 1.0 + eval lut SetTableValue 13 $salmon 1.0 + eval lut SetTableValue 14 $sepia 1.0 + eval lut SetTableValue 15 $carrot 1.0 + eval lut SetTableValue 16 $gold 1.0 + eval lut SetTableValue 17 $forest_green 1.0 + eval lut SetTableValue 18 $turquoise 1.0 + eval lut SetTableValue 19 $plum 1.0 + +lut SetTableRange 0 19 +tetMapper SetLookupTable lut +tetMapper SetScalarRange 0 19 +cubeMapper SetLookupTable lut +cubeMapper SetScalarRange 0 19 +octMapper SetLookupTable lut +octMapper SetScalarRange 0 19 +icosaMapper SetLookupTable lut +icosaMapper SetScalarRange 0 19 +dodeMapper SetLookupTable lut +dodeMapper SetScalarRange 0 19 + +set cam [ren1 GetActiveCamera] +$cam SetPosition 3.89696 7.20771 1.44123 +$cam SetFocalPoint 3.96132 0 0 +$cam SetViewUp -0.0079335 0.196002 -0.980571 +$cam SetClippingRange 5.42814 9.78848 + +ren1 SetBackground 0 0 0 +renWin SetSize 400 150 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestQuadricClustering.tcl b/Graphics/Testing/Tcl/TestQuadricClustering.tcl new file mode 100644 index 0000000..266529e --- /dev/null +++ b/Graphics/Testing/Tcl/TestQuadricClustering.tcl @@ -0,0 +1,78 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Generate implicit model of a sphere +# + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# pipeline stuff +# + +vtkSphereSource sphere + sphere SetPhiResolution 150 + sphere SetThetaResolution 150 + +vtkPoints pts + pts InsertNextPoint 0 0 0 + pts InsertNextPoint 1 0 0 + pts InsertNextPoint 0 1 0 + pts InsertNextPoint 0 0 1 + +vtkCellArray tris + tris InsertNextCell 3 + tris InsertCellPoint 0 + tris InsertCellPoint 1 + tris InsertCellPoint 2 + tris InsertNextCell 3 + tris InsertCellPoint 0 + tris InsertCellPoint 2 + tris InsertCellPoint 3 + tris InsertNextCell 3 + tris InsertCellPoint 0 + tris InsertCellPoint 3 + tris InsertCellPoint 1 + tris InsertNextCell 3 + tris InsertCellPoint 1 + tris InsertCellPoint 2 + tris InsertCellPoint 3 + +vtkPolyData polys + polys SetPoints pts + polys SetPolys tris + +vtkQuadricClustering mesh + mesh SetInputConnection [sphere GetOutputPort] + mesh SetNumberOfXDivisions 10 + mesh SetNumberOfYDivisions 10 + mesh SetNumberOfZDivisions 10 + +vtkPolyDataMapper mapper + mapper SetInputConnection [mesh GetOutputPort] +vtkActor actor + actor SetMapper mapper +eval [actor GetProperty] SetDiffuseColor $tomato +[actor GetProperty] SetDiffuse .8 +[actor GetProperty] SetSpecular .4 +[actor GetProperty] SetSpecularPower 30 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground 1 1 1 + +renWin SetSize 300 300 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestRectilinearGridToTetrahedra.tcl b/Graphics/Testing/Tcl/TestRectilinearGridToTetrahedra.tcl new file mode 100644 index 0000000..7fd882d --- /dev/null +++ b/Graphics/Testing/Tcl/TestRectilinearGridToTetrahedra.tcl @@ -0,0 +1,97 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +### SetUp the pipeline + +vtkRectilinearGridToTetrahedra FormMesh + FormMesh SetInput 4 2 2 1 1 1 0.001 + FormMesh RememberVoxelIdOn +vtkExtractEdges TetraEdges + TetraEdges SetInputConnection [FormMesh GetOutputPort] +vtkTubeFilter tubes + tubes SetInputConnection [TetraEdges GetOutputPort] + tubes SetRadius 0.05 + tubes SetNumberOfSides 6 + +### Run the pipeline 3 times, with different conversions to TetMesh + +vtkPolyData Tubes1 + FormMesh SetTetraPerCellTo5 + tubes Update + Tubes1 DeepCopy [tubes GetOutput] +vtkPolyData Tubes2 + FormMesh SetTetraPerCellTo6 + tubes Update + Tubes2 DeepCopy [tubes GetOutput] +vtkPolyData Tubes3 + FormMesh SetTetraPerCellTo12 + tubes Update + Tubes3 DeepCopy [tubes GetOutput] + +### Run the pipeline once more, this time converting some cells to +### 5 and some data to 12 TetMesh + +### Determine which cells are which +vtkIntArray DivTypes + set numCell [[FormMesh GetInput] GetNumberOfCells] + DivTypes SetNumberOfValues $numCell + for {set i 0} {$i<$numCell} {incr i 1} { + DivTypes SetValue $i [expr 5 + (7* ( $i % 4))] + } + +### Finish this pipeline +vtkPolyData Tubes4 + FormMesh SetTetraPerCellTo5And12 + [[FormMesh GetInput] GetCellData] SetScalars DivTypes + tubes Update + Tubes4 DeepCopy [tubes GetOutput] + +### Finish the 4 pipelines +for {set i 1} {$i<5} {incr i 1} { + vtkPolyDataMapper mapEdges$i + mapEdges$i SetInput Tubes$i + vtkActor edgeActor$i + edgeActor$i SetMapper mapEdges$i + eval [edgeActor$i GetProperty] SetColor $peacock + [edgeActor$i GetProperty] SetSpecularColor 1 1 1 + [edgeActor$i GetProperty] SetSpecular 0.3 + [edgeActor$i GetProperty] SetSpecularPower 20 + [edgeActor$i GetProperty] SetAmbient 0.2 + [edgeActor$i GetProperty] SetDiffuse 0.8 + vtkRenderer ren$i + ren$i AddActor edgeActor$i + ren$i SetBackground 0 0 0 + ren$i ResetCamera + [ren$i GetActiveCamera] Zoom 1 + [ren$i GetActiveCamera] SetPosition 1.73906 12.7987 -0.257808 + [ren$i GetActiveCamera] SetViewUp 0.992444 0.00890284 -0.122379 + [ren$i GetActiveCamera] SetClippingRange 9.36398 15.0496 +} + +# Create graphics objects +# Create the rendering window, renderer, and interactive renderer +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin AddRenderer ren3 + renWin AddRenderer ren4 + renWin SetSize 600 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size + +ren1 SetViewport .75 0 1 1 +ren2 SetViewport .50 0 .75 1 +ren3 SetViewport .25 0 .50 1 +ren4 SetViewport 0 0 .25 1 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestRectilinearSynchronizedTemplates.tcl b/Graphics/Testing/Tcl/TestRectilinearSynchronizedTemplates.tcl new file mode 100644 index 0000000..1996e8b --- /dev/null +++ b/Graphics/Testing/Tcl/TestRectilinearSynchronizedTemplates.tcl @@ -0,0 +1,45 @@ +package require vtk +package require vtkinteraction + +# create pipeline - rectilinear grid +# +vtkRectilinearGridReader rgridReader +rgridReader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" +rgridReader Update + +vtkRectilinearSynchronizedTemplates contour +contour SetInputConnection [rgridReader GetOutputPort] +contour SetValue 0 1 +contour ComputeScalarsOff +contour ComputeNormalsOn +contour ComputeGradientsOn + +vtkPolyDataMapper cMapper +cMapper SetInputConnection [contour GetOutputPort] + +vtkActor cActor +cActor SetMapper cMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 200 200 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +ren1 AddActor cActor + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TestRegularPolygonSource.tcl b/Graphics/Testing/Tcl/TestRegularPolygonSource.tcl new file mode 100644 index 0000000..6194e09 --- /dev/null +++ b/Graphics/Testing/Tcl/TestRegularPolygonSource.tcl @@ -0,0 +1,61 @@ +package require vtk +package require vtkinteraction + +# Create two polygon sources, one a closed polyline, one a polygon +# +vtkRegularPolygonSource polyline +polyline SetCenter 1 1 1 +polyline SetRadius 1 +polyline SetNumberOfSides 12 +polyline SetNormal 1 2 3 +polyline GeneratePolylineOn +polyline GeneratePolygonOff + +vtkPolyDataMapper polylineMapper +polylineMapper SetInputConnection [polyline GetOutputPort] + +vtkActor polylineActor +polylineActor SetMapper polylineMapper +[polylineActor GetProperty] SetColor 0 1 0 +[polylineActor GetProperty] SetAmbient 1 + + +vtkRegularPolygonSource polygon +polygon SetCenter 3 1 1 +polygon SetRadius 1 +polygon SetNumberOfSides 12 +polygon SetNormal 1 2 3 +polygon GeneratePolylineOff +polygon GeneratePolygonOn + +vtkPolyDataMapper polygonMapper +polygonMapper SetInputConnection [polygon GetOutputPort] + +vtkActor polygonActor +polygonActor SetMapper polygonMapper +[polygonActor GetProperty] SetColor 1 0 0 +[polygonActor GetProperty] SetAmbient 1 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create room profile# Add the actors to the renderer, set the background and size +# +ren1 AddActor polylineActor +ren1 AddActor polygonActor + +ren1 SetBackground 0 0 0 +renWin SetSize 200 200 +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/TestRibbonAndTube.tcl b/Graphics/Testing/Tcl/TestRibbonAndTube.tcl new file mode 100644 index 0000000..34b4c8d --- /dev/null +++ b/Graphics/Testing/Tcl/TestRibbonAndTube.tcl @@ -0,0 +1,74 @@ +package require vtk +package require vtkinteraction + +# create pipeline +# +vtkPolyDataReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/vtk.vtk" + +# Read a ruler texture +vtkPNGReader r + r SetFileName "$VTK_DATA_ROOT/Data/ruler.png" +vtkTexture atext + atext SetInputConnection [r GetOutputPort] + atext InterpolateOn + +# produce some ribbons +vtkRibbonFilter ribbon + ribbon SetInputConnection [reader GetOutputPort] + ribbon SetWidth 0.1 + ribbon SetGenerateTCoordsToUseLength + ribbon SetTextureLength 1.0 + ribbon UseDefaultNormalOn + ribbon SetDefaultNormal 0 0 1 +vtkPolyDataMapper ribbonMapper + ribbonMapper SetInputConnection [ribbon GetOutputPort] +vtkActor ribbonActor + ribbonActor SetMapper ribbonMapper + eval [ribbonActor GetProperty] SetColor 1 1 0 + ribbonActor SetTexture atext + +# produce some tubes +vtkTubeFilter tuber + tuber SetInputConnection [reader GetOutputPort] + tuber SetRadius 0.1 + tuber SetNumberOfSides 12 + tuber SetGenerateTCoordsToUseLength + tuber SetTextureLength 0.5 + tuber CappingOn +vtkPolyDataMapper tubeMapper + tubeMapper SetInputConnection [tuber GetOutputPort] +vtkActor tubeActor + tubeActor SetMapper tubeMapper + eval [tubeActor GetProperty] SetColor 1 1 0 + tubeActor SetTexture atext + tubeActor AddPosition 5 0 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor ribbonActor +ren1 AddActor tubeActor + +ren1 SetBackground 1 1 1 +renWin SetSize 900 350 +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 4 + +# render the image +# +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +set threshold 15 \ No newline at end of file diff --git a/Graphics/Testing/Tcl/TestRotate.tcl b/Graphics/Testing/Tcl/TestRotate.tcl new file mode 100644 index 0000000..236184f --- /dev/null +++ b/Graphics/Testing/Tcl/TestRotate.tcl @@ -0,0 +1,38 @@ +package require vtk +package require vtkinteraction + +vtkConeSource cone +cone SetRadius 0.05 +cone SetHeight 0.25 +cone SetResolution 256 +cone SetCenter 0.15 0.0 0.15 + +vtkRotationFilter rotate +rotate SetInputConnection [cone GetOutputPort] +rotate SetAxisToZ +rotate SetCenter 0.0 0.0 0.0 +rotate SetAngle 45 +rotate SetNumberOfCopies 7 +rotate CopyInputOn + +vtkDataSetMapper mapper +mapper SetInputConnection [rotate GetOutputPort] + +vtkActor actor +actor SetMapper mapper + +vtkRenderer ren1 +ren1 AddActor actor + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 512 512 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +renWin Render + +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestRuledSurface.tcl b/Graphics/Testing/Tcl/TestRuledSurface.tcl new file mode 100644 index 0000000..96f06d1 --- /dev/null +++ b/Graphics/Testing/Tcl/TestRuledSurface.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create room profile +# +vtkPoints points + points InsertPoint 0 0 0 0 + points InsertPoint 1 1 0 0 + points InsertPoint 2 1 1 0 + points InsertPoint 3 2 1 0 + +vtkCellArray lines + lines InsertNextCell 4;#number of points + lines InsertCellPoint 0 + lines InsertCellPoint 1 + lines InsertCellPoint 2 + lines InsertCellPoint 3 + +vtkPolyData profile + profile SetPoints points + profile SetLines lines + +vtkTransform xfm + xfm Translate 0 0 8 + xfm RotateZ 90 + +vtkTransformPolyDataFilter xfmPd + xfmPd SetInput profile + xfmPd SetTransform xfm + +vtkAppendPolyData appendPD + appendPD AddInput profile + appendPD AddInput [xfmPd GetOutput] + +# extrude profile to make wall +# +vtkRuledSurfaceFilter extrude + extrude SetInputConnection [appendPD GetOutputPort] + extrude SetResolution 51 51 + extrude SetRuledModeToResample + +vtkPolyDataMapper map + map SetInputConnection [extrude GetOutputPort] + +vtkActor wall + wall SetMapper map + [wall GetProperty] SetColor 0.3800 0.7000 0.1600 + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor wall +ren1 SetBackground 1 1 1 + +renWin SetSize 200 200 + +[ren1 GetActiveCamera] SetPosition 12.9841 -1.81551 8.82706 +[ren1 GetActiveCamera] SetFocalPoint 0.5 1 4 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.128644 -0.675064 -0.726456 +[ren1 GetActiveCamera] SetClippingRange 7.59758 21.3643 + +renWin Render +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/TestRuledSurface2.tcl b/Graphics/Testing/Tcl/TestRuledSurface2.tcl new file mode 100644 index 0000000..09e9788 --- /dev/null +++ b/Graphics/Testing/Tcl/TestRuledSurface2.tcl @@ -0,0 +1,73 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkSphereSource sphere + sphere SetPhiResolution 15 + sphere SetThetaResolution 30 + +vtkPlane plane + plane SetNormal 1 0 0 + +vtkCutter cut + cut SetInputConnection [sphere GetOutputPort] + cut SetCutFunction plane + cut GenerateCutScalarsOn + +vtkStripper strip + strip SetInputConnection [cut GetOutputPort] + +vtkPoints points + points InsertPoint 0 1 0 0 + +vtkCellArray lines + lines InsertNextCell 2;#number of points + lines InsertCellPoint 0 + lines InsertCellPoint 0 + +vtkPolyData tip + tip SetPoints points + tip SetLines lines + +vtkAppendPolyData appendPD + appendPD AddInput [strip GetOutput] + appendPD AddInput tip + +# extrude profile to make coverage +# +vtkRuledSurfaceFilter extrude + extrude SetInputConnection [appendPD GetOutputPort] + extrude SetRuledModeToPointWalk + +vtkCleanPolyData clean + clean SetInputConnection [extrude GetOutputPort] + clean ConvertPolysToLinesOff + +vtkPolyDataMapper mapper + mapper SetInputConnection [clean GetOutputPort] + mapper ScalarVisibilityOff + +vtkActor actor + actor SetMapper mapper + [actor GetProperty] SetOpacity .4 + +ren1 AddActor actor +renWin SetSize 200 200 + +renWin Render +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/TestSpherePuzzle.tcl b/Graphics/Testing/Tcl/TestSpherePuzzle.tcl new file mode 100644 index 0000000..5c476e9 --- /dev/null +++ b/Graphics/Testing/Tcl/TestSpherePuzzle.tcl @@ -0,0 +1,105 @@ +package require vtk +package require vtkinteraction + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +vtkRenderWindow renWin + +# create a rendering window and renderer +vtkRenderer ren1 + renWin AddRenderer ren1 + renWin SetSize 400 400 + +vtkSpherePuzzle puzzle +vtkPolyDataMapper mapper + mapper SetInputConnection [puzzle GetOutputPort] +vtkActor actor + actor SetMapper mapper + +vtkSpherePuzzleArrows arrows +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [arrows GetOutputPort] +vtkActor actor2 + actor2 SetMapper mapper2 + + + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 AddActor actor2 + +ren1 SetBackground 0.1 0.2 0.4 + + +set LastVal -1 +proc MotionCallback {x y} { + global LastVal + + # Compute display point from Tk display point. + set WindowY 400 + set y [expr $WindowY - $y] + set z [ren1 GetZ $x $y] + + ren1 SetDisplayPoint $x $y $z + ren1 DisplayToWorld + set pt [ren1 GetWorldPoint] + + #tk_messageBox -message "$pt" + set x [lindex $pt 0] + set y [lindex $pt 1] + set z [lindex $pt 2] + + set val [puzzle SetPoint $x $y $z] + if {$val != $LastVal} { + renWin Render + set LastVal $val + } +} + + +proc ButtonCallback {x y} { + + # Compute display point from Tk display point. + set WindowY 400 + set y [expr $WindowY - $y] + set z [ren1 GetZ $x $y] + + ren1 SetDisplayPoint $x $y $z + ren1 DisplayToWorld + set pt [ren1 GetWorldPoint] + + #tk_messageBox -message "$pt" + set x [lindex $pt 0] + set y [lindex $pt 1] + set z [lindex $pt 2] + + # Had to move away from mose events (sgi RT problems) + for { set i 0} {$i <= 100} {set i [expr $i + 5]} { + puzzle SetPoint $x $y $z + puzzle MovePoint $i + renWin Render + } + + +} + +renWin Render + +set cam [ren1 GetActiveCamera] +$cam Elevation -40 +update + + + + +puzzle MoveHorizontal 0 100 0 +puzzle MoveHorizontal 1 100 1 +puzzle MoveHorizontal 2 100 0 +puzzle MoveVertical 2 100 0 +puzzle MoveVertical 1 100 0 + + +renWin Render diff --git a/Graphics/Testing/Tcl/TestSpherePuzzleArrows.tcl b/Graphics/Testing/Tcl/TestSpherePuzzleArrows.tcl new file mode 100644 index 0000000..5b7bff7 --- /dev/null +++ b/Graphics/Testing/Tcl/TestSpherePuzzleArrows.tcl @@ -0,0 +1,99 @@ +package require vtk +package require vtkinteraction + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +vtkRenderWindow renWin + +# create a rendering window and renderer +vtkRenderer ren1 + renWin AddRenderer ren1 + renWin SetSize 400 400 + + +vtkSpherePuzzle puzzle +vtkPolyDataMapper mapper + mapper SetInputConnection [puzzle GetOutputPort] +vtkActor actor + actor SetMapper mapper + +vtkSpherePuzzleArrows arrows +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [arrows GetOutputPort] +vtkActor actor2 + actor2 SetMapper mapper2 + + + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 AddActor actor2 + +ren1 SetBackground 0.1 0.2 0.4 + + +set LastVal -1 +proc MotionCallback {x y} { + global LastVal + + # Compute display point from Tk display point. + set WindowY 400 + set y [expr $WindowY - $y] + set z [ren1 GetZ $x $y] + + ren1 SetDisplayPoint $x $y $z + ren1 DisplayToWorld + set pt [ren1 GetWorldPoint] + + #tk_messageBox -message "$pt" + set x [lindex $pt 0] + set y [lindex $pt 1] + set z [lindex $pt 2] + + set val [puzzle SetPoint $x $y $z] + if {$val != $LastVal} { + renWin Render + set LastVal $val + } +} + + +proc ButtonCallback {x y} { + + # Compute display point from Tk display point. + set WindowY 400 + set y [expr $WindowY - $y] + set z [ren1 GetZ $x $y] + + ren1 SetDisplayPoint $x $y $z + ren1 DisplayToWorld + set pt [ren1 GetWorldPoint] + + #tk_messageBox -message "$pt" + set x [lindex $pt 0] + set y [lindex $pt 1] + set z [lindex $pt 2] + + for { set i 0} {$i <= 100} {set i [expr $i + 5]} { + puzzle SetPoint $x $y $z + puzzle MovePoint $i + renWin Render + } +} + +renWin Render + +set cam [ren1 GetActiveCamera] +$cam Elevation -40 +update + +ButtonCallback 261 272 +arrows SetPermutation puzzle +renWin Render + + + + diff --git a/Graphics/Testing/Tcl/TestSplineFilter.tcl b/Graphics/Testing/Tcl/TestSplineFilter.tcl new file mode 100644 index 0000000..f0cf437 --- /dev/null +++ b/Graphics/Testing/Tcl/TestSplineFilter.tcl @@ -0,0 +1,92 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +vtkPlaneSource ps + ps SetXResolution 4 + ps SetYResolution 4 + ps SetOrigin 2 -2 26 + ps SetPoint1 2 2 26 + ps SetPoint2 2 -2 32 +vtkPolyDataMapper psMapper + psMapper SetInputConnection [ps GetOutputPort] +vtkActor psActor + psActor SetMapper psMapper + [psActor GetProperty] SetRepresentationToWireframe + +vtkRungeKutta4 rk4 + +vtkStreamLine streamer + streamer SetInputConnection [pl3d GetOutputPort] + streamer SetSource [ps GetOutput] + streamer SetMaximumPropagationTime 100 + streamer SetIntegrationStepLength .2 + streamer SetStepLength .001 + streamer SetNumberOfThreads 1 + streamer SetIntegrationDirectionToForward + streamer VorticityOn + streamer SetIntegrator rk4 +vtkSplineFilter sf + sf SetInputConnection [streamer GetOutputPort] + sf SetSubdivideToLength + sf SetLength 0.15 +vtkRibbonFilter rf + rf SetInputConnection [sf GetOutputPort] + rf SetWidth 0.1 + rf SetWidthFactor 5 +vtkPolyDataMapper streamMapper + streamMapper SetInputConnection [rf GetOutputPort] + eval streamMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor streamline + streamline SetMapper streamMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor psActor +ren1 AddActor outlineActor +ren1 AddActor streamline + +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# for testing +set threshold 15 diff --git a/Graphics/Testing/Tcl/TestStructuredGrid.tcl b/Graphics/Testing/Tcl/TestStructuredGrid.tcl new file mode 100644 index 0000000..6c2a417 --- /dev/null +++ b/Graphics/Testing/Tcl/TestStructuredGrid.tcl @@ -0,0 +1,250 @@ +package require vtk +package require vtkinteraction + +# Remove cullers so single vertex will render +vtkRenderer ren1 + [ren1 GetCullers] RemoveAllItems +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkGenericCell cell +vtkIdList ptIds + +# 0D +vtkPoints ZeroDPts +ZeroDPts SetNumberOfPoints 1 +ZeroDPts SetPoint 0 0 0 0 + +vtkStructuredGrid ZeroDGrid +ZeroDGrid SetDimensions 1 1 1 +ZeroDGrid SetPoints ZeroDPts +ZeroDGrid GetCell 0 +ZeroDGrid GetCell 0 cell +ZeroDGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter ZeroDGeom +ZeroDGeom SetInput ZeroDGrid +ZeroDGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper ZeroDMapper +ZeroDMapper SetInputConnection [ZeroDGeom GetOutputPort] + +vtkActor ZeroDActor +ZeroDActor SetMapper ZeroDMapper +ZeroDActor SetPosition 0 0 0 + +ren1 AddActor ZeroDActor + +# 1D - X +vtkPoints XPts +XPts SetNumberOfPoints 2 +XPts SetPoint 0 0 0 0 +XPts SetPoint 1 1 0 0 + +vtkStructuredGrid XGrid +XGrid SetDimensions 2 1 1 +XGrid SetPoints XPts +XGrid GetCell 0 +XGrid GetCell 0 cell +XGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter XGeom +XGeom SetInput XGrid +XGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper XMapper +XMapper SetInputConnection [XGeom GetOutputPort] + +vtkActor XActor +XActor SetMapper XMapper +XActor SetPosition 2 0 0 + +ren1 AddActor XActor + +# 1D - Y +vtkPoints YPts +YPts SetNumberOfPoints 2 +YPts SetPoint 0 0 0 0 +YPts SetPoint 1 0 1 0 + +vtkStructuredGrid YGrid +YGrid SetDimensions 1 2 1 +YGrid SetPoints YPts +YGrid GetCell 0 +YGrid GetCell 0 cell +YGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter YGeom +YGeom SetInput YGrid +YGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper YMapper +YMapper SetInputConnection [YGeom GetOutputPort] + +vtkActor YActor +YActor SetMapper YMapper +YActor SetPosition 4 0 0 + +ren1 AddActor YActor + + +# 1D - Z +vtkPoints ZPts +ZPts SetNumberOfPoints 2 +ZPts SetPoint 0 0 0 0 +ZPts SetPoint 1 0 0 1 + +vtkStructuredGrid ZGrid +ZGrid SetDimensions 1 1 2 +ZGrid SetPoints ZPts +ZGrid GetCell 0 +ZGrid GetCell 0 cell +ZGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter ZGeom +ZGeom SetInput ZGrid +ZGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper ZMapper +ZMapper SetInputConnection [ZGeom GetOutputPort] + +vtkActor ZActor +ZActor SetMapper ZMapper +ZActor SetPosition 6 0 0 + +ren1 AddActor ZActor + +# 2D - XY +vtkPoints XYPts +XYPts SetNumberOfPoints 4 +XYPts SetPoint 0 0 0 0 +XYPts SetPoint 1 1 0 0 +XYPts SetPoint 2 0 1 0 +XYPts SetPoint 3 1 1 0 + +vtkStructuredGrid XYGrid +XYGrid SetDimensions 2 2 1 +XYGrid SetPoints XYPts +XYGrid GetCell 0 +XYGrid GetCell 0 cell +XYGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter XYGeom +XYGeom SetInput XYGrid +XYGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper XYMapper +XYMapper SetInputConnection [XYGeom GetOutputPort] + +vtkActor XYActor +XYActor SetMapper XYMapper +XYActor SetPosition 0 2 0 + +ren1 AddActor XYActor + +# 2D - YZ +vtkPoints YZPts +YZPts SetNumberOfPoints 4 +YZPts SetPoint 0 0 0 0 +YZPts SetPoint 1 0 1 0 +YZPts SetPoint 2 0 0 1 +YZPts SetPoint 3 0 1 1 + +vtkStructuredGrid YZGrid +YZGrid SetDimensions 1 2 2 +YZGrid SetPoints YZPts +YZGrid GetCell 0 +YZGrid GetCell 0 cell +YZGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter YZGeom +YZGeom SetInput YZGrid +YZGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper YZMapper +YZMapper SetInputConnection [YZGeom GetOutputPort] + +vtkActor YZActor +YZActor SetMapper YZMapper +YZActor SetPosition 2 2 0 + +ren1 AddActor YZActor + +# 2D - XZ +vtkPoints XZPts +XZPts SetNumberOfPoints 4 +XZPts SetPoint 0 0 0 0 +XZPts SetPoint 1 1 0 0 +XZPts SetPoint 2 0 0 1 +XZPts SetPoint 3 1 0 1 + +vtkStructuredGrid XZGrid +XZGrid SetDimensions 2 1 2 +XZGrid SetPoints XZPts +XZGrid GetCell 0 +XZGrid GetCell 0 cell +XZGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter XZGeom +XZGeom SetInput XZGrid +XZGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper XZMapper +XZMapper SetInputConnection [XZGeom GetOutputPort] + +vtkActor XZActor +XZActor SetMapper XZMapper +XZActor SetPosition 4 2 0 + +ren1 AddActor XZActor + +# 3D +vtkPoints XYZPts +XYZPts SetNumberOfPoints 8 +XYZPts SetPoint 0 0 0 0 +XYZPts SetPoint 1 1 0 0 +XYZPts SetPoint 2 0 1 0 +XYZPts SetPoint 3 1 1 0 +XYZPts SetPoint 4 0 0 1 +XYZPts SetPoint 5 1 0 1 +XYZPts SetPoint 6 0 1 1 +XYZPts SetPoint 7 1 1 1 + +vtkStructuredGrid XYZGrid +XYZGrid SetDimensions 2 2 2 +XYZGrid SetPoints XYZPts +XYZGrid GetCell 0 +XYZGrid GetCell 0 cell +XYZGrid GetCellPoints 0 ptIds + +vtkStructuredGridGeometryFilter XYZGeom +XYZGeom SetInput XYZGrid +XYZGeom SetExtent 0 2 0 2 0 2 + +vtkPolyDataMapper XYZMapper +XYZMapper SetInputConnection [XYZGeom GetOutputPort] + +vtkActor XYZActor +XYZActor SetMapper XYZMapper +XYZActor SetPosition 6 2 0 + +ren1 AddActor XYZActor + +# render the image +# +renWin SetSize 300 150 +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 2.27407 14.9819 + $cam1 SetFocalPoint 3.1957 1.74012 0.176603 + $cam1 SetPosition -0.380779 6.13894 5.59404 + $cam1 SetViewUp 0.137568 0.811424 -0.568037 + +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TestSynchronizedTemplates2D.tcl b/Graphics/Testing/Tcl/TestSynchronizedTemplates2D.tcl new file mode 100644 index 0000000..1361c0e --- /dev/null +++ b/Graphics/Testing/Tcl/TestSynchronizedTemplates2D.tcl @@ -0,0 +1,51 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkContourFilter iso + iso SetInputConnection [reader GetOutputPort] + iso GenerateValues 12 500 1150 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [iso GetOutputPort] + isoMapper ScalarVisibilityOff +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor 0 0 0 + +vtkOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper +set outlineProp [outlineActor GetProperty] +#eval $outlineProp SetColor 0 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 0.8 0.8 1 +renWin SetSize 400 400 + +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.3 + +iren Initialize + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/TestSynchronizedTemplates3D.tcl b/Graphics/Testing/Tcl/TestSynchronizedTemplates3D.tcl new file mode 100644 index 0000000..2c5ed90 --- /dev/null +++ b/Graphics/Testing/Tcl/TestSynchronizedTemplates3D.tcl @@ -0,0 +1,57 @@ +package require vtk +package require vtkinteraction + +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +# write isosurface to file +#vtkSynchronizedTemplates3D stemp +vtkContourFilter stemp + stemp SetInputConnection [reader GetOutputPort] + stemp SetValue 0 1150 + stemp Update + + +vtkPolyDataMapper mapper + mapper SetInputConnection [stemp GetOutputPort] + mapper ScalarVisibilityOff + +vtkActor head + head SetMapper mapper + eval [head GetProperty] SetColor 1 0.7 0.6 + +# Create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor head +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 +eval ren1 SetBackground 0.5 0.5 0.6 + +[ren1 GetActiveCamera] SetPosition 99.8847 537.926 15 +[ren1 GetActiveCamera] SetFocalPoint 99.8847 109.81 15 +[ren1 GetActiveCamera] SetViewAngle 20 +[ren1 GetActiveCamera] SetViewUp 0 0 -1 + +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/TestTransformInterpolator.tcl b/Graphics/Testing/Tcl/TestTransformInterpolator.tcl new file mode 100644 index 0000000..80af7ce --- /dev/null +++ b/Graphics/Testing/Tcl/TestTransformInterpolator.tcl @@ -0,0 +1,204 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# create two boxes and interpolate between them +# +vtkPoints pts + pts InsertNextPoint -1 -1 -1 + pts InsertNextPoint 1 -1 -1 + pts InsertNextPoint 1 1 -1 + pts InsertNextPoint -1 1 -1 + pts InsertNextPoint -1 -1 1 + pts InsertNextPoint 1 -1 1 + pts InsertNextPoint 1 1 1 + pts InsertNextPoint -1 1 1 +vtkCellArray faces + faces InsertNextCell 4 + faces InsertCellPoint 0 + faces InsertCellPoint 3 + faces InsertCellPoint 2 + faces InsertCellPoint 1 + faces InsertNextCell 4 + faces InsertCellPoint 4 + faces InsertCellPoint 5 + faces InsertCellPoint 6 + faces InsertCellPoint 7 + faces InsertNextCell 4 + faces InsertCellPoint 0 + faces InsertCellPoint 1 + faces InsertCellPoint 5 + faces InsertCellPoint 4 + faces InsertNextCell 4 + faces InsertCellPoint 1 + faces InsertCellPoint 2 + faces InsertCellPoint 6 + faces InsertCellPoint 5 + faces InsertNextCell 4 + faces InsertCellPoint 2 + faces InsertCellPoint 3 + faces InsertCellPoint 7 + faces InsertCellPoint 6 + faces InsertNextCell 4 + faces InsertCellPoint 3 + faces InsertCellPoint 0 + faces InsertCellPoint 4 + faces InsertCellPoint 7 +vtkUnsignedCharArray faceColors + faceColors SetNumberOfComponents 3 + faceColors SetNumberOfTuples 3 + faceColors InsertComponent 0 0 255 + faceColors InsertComponent 0 1 0 + faceColors InsertComponent 0 2 0 + faceColors InsertComponent 1 0 0 + faceColors InsertComponent 1 1 255 + faceColors InsertComponent 1 2 0 + faceColors InsertComponent 2 0 255 + faceColors InsertComponent 2 1 255 + faceColors InsertComponent 2 2 0 + faceColors InsertComponent 3 0 0 + faceColors InsertComponent 3 1 0 + faceColors InsertComponent 3 2 255 + faceColors InsertComponent 4 0 255 + faceColors InsertComponent 4 1 0 + faceColors InsertComponent 4 2 255 + faceColors InsertComponent 5 0 0 + faceColors InsertComponent 5 1 255 + faceColors InsertComponent 5 2 255 + +vtkPolyData cube + cube SetPoints pts + cube SetPolys faces + [cube GetCellData] SetScalars faceColors + +vtkTransform t1 + t1 Translate 1 2 3 + t1 RotateX 15 + t1 Scale 4 2 1 +vtkTransformPolyDataFilter tpdf1 + tpdf1 SetInput cube + tpdf1 SetTransform t1 +vtkPolyDataMapper cube1Mapper + cube1Mapper SetInputConnection [tpdf1 GetOutputPort] +vtkActor cube1 + cube1 SetMapper cube1Mapper + +vtkTransform t2 + t2 Translate 5 10 15 + t2 RotateX 22.5 + t2 RotateY 15 + t2 RotateZ 85 + t2 Scale 1 2 4 +vtkTransformPolyDataFilter tpdf2 + tpdf2 SetInput cube + tpdf2 SetTransform t2 +vtkPolyDataMapper cube2Mapper + cube2Mapper SetInputConnection [tpdf2 GetOutputPort] +vtkActor cube2 + cube2 SetMapper cube2Mapper + +vtkTransform t3 + t3 Translate 5 -10 15 + t3 RotateX 13 + t3 RotateY 72 + t3 RotateZ -15 + t3 Scale 2 4 1 +vtkTransformPolyDataFilter tpdf3 + tpdf3 SetInput cube + tpdf3 SetTransform t3 +vtkPolyDataMapper cube3Mapper + cube3Mapper SetInputConnection [tpdf3 GetOutputPort] +vtkActor cube3 + cube3 SetMapper cube3Mapper + +vtkTransform t4 + t4 Translate 10 -5 5 + t4 RotateX 66 + t4 RotateY 19 + t4 RotateZ 24 + t4 Scale 2 .5 1 +vtkTransformPolyDataFilter tpdf4 + tpdf4 SetInput cube + tpdf4 SetTransform t4 +vtkPolyDataMapper cube4Mapper + cube4Mapper SetInputConnection [tpdf4 GetOutputPort] +vtkActor cube4 + cube4 SetMapper cube4Mapper + +# Interpolate the transformation +vtkPolyDataMapper cubeMapper + cubeMapper SetInput cube +vtkActor cubeActor + cubeActor SetMapper cubeMapper + +# Interpolate some transformations, test along the way +vtkTransformInterpolator interpolator +#interpolator SetInterpolationTypeToLinear +interpolator SetInterpolationTypeToSpline +interpolator AddTransform 0.0 cube1 +interpolator AddTransform 8.0 cube2 +interpolator AddTransform 18.2 cube3 +interpolator AddTransform 24.4 cube4 +interpolator Initialize +#puts [interpolator GetNumberOfTransforms] +interpolator AddTransform 0.0 t1 +interpolator AddTransform 8.0 t2 +interpolator AddTransform 18.2 t3 +interpolator AddTransform 24.4 t4 +#puts [interpolator GetNumberOfTransforms] + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cube1 +ren1 AddActor cube2 +ren1 AddActor cube3 +ren1 AddActor cube4 +ren1 AddActor cubeActor + +ren1 SetBackground 0 0 0 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +vtkCamera camera +camera SetClippingRange 31.2977 81.697 +camera SetFocalPoint 3.0991 -2.00445 9.78648 +camera SetPosition -44.8481 -25.871 10.0645 +camera SetViewAngle 30 +camera SetViewUp -0.0356378 0.0599728 -0.997564 + +ren1 SetActiveCamera camera + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +vtkTransform xform +proc animate {} { + set numSteps 250 + set min [interpolator GetMinimumT] + set max [interpolator GetMaximumT] + for {set i 0} {$i <= $numSteps} {incr i} { + set t [expr double($i) * ($max - $min) / double($numSteps)] + interpolator InterpolateTransform $t xform + cubeActor SetUserMatrix [xform GetMatrix] + renWin Render + } +} +interpolator InterpolateTransform 13.2 xform +cubeActor SetUserMatrix [xform GetMatrix] +renWin Render +#animate + + diff --git a/Graphics/Testing/Tcl/TestTriangleFilter.tcl b/Graphics/Testing/Tcl/TestTriangleFilter.tcl new file mode 100644 index 0000000..f42291d --- /dev/null +++ b/Graphics/Testing/Tcl/TestTriangleFilter.tcl @@ -0,0 +1,112 @@ +package require vtk +package require vtkinteraction + +vtkPoints pts +pts SetNumberOfPoints 22 +pts SetPoint 0 0 0 0 +pts SetPoint 1 1 0 0 +pts SetPoint 2 2 0 0 +pts SetPoint 3 3 0 0 +pts SetPoint 4 4 0 0 +pts SetPoint 5 5 0 0 +pts SetPoint 6 6 0 0 +pts SetPoint 7 7 0 0 +pts SetPoint 8 8 0 0 +pts SetPoint 9 9 0 0 +pts SetPoint 10 1 1 0 +pts SetPoint 11 2 1 0 +pts SetPoint 12 3 1 0 +pts SetPoint 13 4 1 0 +pts SetPoint 14 6 1 0 +pts SetPoint 15 8 1 0 +pts SetPoint 16 9 1 0 +pts SetPoint 17 3 2 0 +pts SetPoint 18 6 2 0 +pts SetPoint 19 7 2 0 +pts SetPoint 20 8 2 0 +pts SetPoint 21 9 2 0 + +vtkPolyData pd +pd SetPoints pts +vtkCellArray verts +verts InsertNextCell 1 +verts InsertCellPoint 0 +verts InsertNextCell 2 +verts InsertCellPoint 1 +verts InsertCellPoint 10 +pd SetVerts verts + +vtkCellArray lines +lines InsertNextCell 2 +lines InsertCellPoint 2 +lines InsertCellPoint 11 +lines InsertNextCell 3 +lines InsertCellPoint 3 +lines InsertCellPoint 12 +lines InsertCellPoint 17 +pd SetLines lines + +vtkCellArray polys +polys InsertNextCell 3 +polys InsertCellPoint 4 +polys InsertCellPoint 5 +polys InsertCellPoint 13 +polys InsertNextCell 5 +polys InsertCellPoint 6 +polys InsertCellPoint 7 +polys InsertCellPoint 19 +polys InsertCellPoint 18 +polys InsertCellPoint 14 +pd SetPolys polys + +vtkCellArray strips +strips InsertNextCell 6 +strips InsertCellPoint 8 +strips InsertCellPoint 9 +strips InsertCellPoint 15 +strips InsertCellPoint 16 +strips InsertCellPoint 20 +strips InsertCellPoint 21 +pd SetStrips strips + +vtkUnsignedCharArray colors +colors SetNumberOfComponents 4 +colors SetNumberOfTuples 7 +colors SetTuple4 0 255 0 0 255 +colors SetTuple4 1 0 255 0 255 +colors SetTuple4 2 0 0 255 255 +colors SetTuple4 3 255 255 0 255 +colors SetTuple4 4 255 0 255 255 +colors SetTuple4 5 0 255 0 255 +colors SetTuple4 6 0 255 255 255 +[pd GetCellData] SetScalars colors + +vtkTriangleFilter tf +tf SetInput pd + +vtkPolyDataMapper mapper +mapper SetInputConnection [tf GetOutputPort] + +vtkActor actor +actor SetMapper mapper + +# Create the RenderWindow, Renderer and interactive renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor actor +ren1 SetBackground 1 1 1 + +renWin SetSize 300 150 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 2.5 +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/TransformConcatenation.tcl b/Graphics/Testing/Tcl/TransformConcatenation.tcl new file mode 100644 index 0000000..b5b709d --- /dev/null +++ b/Graphics/Testing/Tcl/TransformConcatenation.tcl @@ -0,0 +1,114 @@ +package require vtk + +# This example demonstrates how to set up flexible joints using +# the transformation pipeline and vtkTransformPolyDataFilter. + + +# create a rendering window and renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + +# set up first set of polydata +vtkCylinderSource c1 +c1 SetHeight 1.6 +c1 SetRadius 0.2 +c1 SetCenter 0 0.8 0 + +vtkTransform t1 + +vtkTransformPolyDataFilter f1 +f1 SetInputConnection [c1 GetOutputPort] +f1 SetTransform t1 + +vtkDataSetMapper m1 +m1 SetInputConnection [f1 GetOutputPort] + +vtkActor a1 +a1 SetMapper m1 +[a1 GetProperty] SetColor 1 0 0 + + +# set up second set, at a relative transform to the first +vtkCylinderSource c2 +c2 SetHeight 1.6 +c2 SetRadius 0.15 +c2 SetCenter 0 0.8 0 + +# relative rotation for first joint +vtkTransform joint1 + +# set input to initial transform +vtkTransform t2 +t2 SetInput t1 +t2 Translate 0 1.6 0 +t2 Concatenate joint1 + +vtkTransformPolyDataFilter f2 +f2 SetInputConnection [c2 GetOutputPort] +f2 SetTransform t2 + +vtkDataSetMapper m2 +m2 SetInputConnection [f2 GetOutputPort] + +vtkActor a2 +a2 SetMapper m2 +[a2 GetProperty] SetColor 0.0 0.7 1.0 + + +# set up third set, at a relative transform to the second +vtkCylinderSource c3 +c3 SetHeight 0.5 +c3 SetRadius 0.1 +c3 SetCenter 0 0.25 0 + +# relative rotation +vtkTransform joint2 + +# set input to previous transform +vtkTransform t3 +t3 SetInput t2 +t3 Translate 0 1.6 0 +t3 Concatenate joint2 + +vtkTransformPolyDataFilter f3 +f3 SetInputConnection [c3 GetOutputPort] +f3 SetTransform t3 + +vtkDataSetMapper m3 +m3 SetInputConnection [f3 GetOutputPort] + +vtkActor a3 +a3 SetMapper m3 +[a3 GetProperty] SetColor 0.9 0.9 0 + + +# add actors to renderer +ren1 AddActor a1 +ren1 AddActor a2 +ren1 AddActor a3 + +# set clipping range +ren1 ResetCamera -1 1 -0.1 2 -3 3 + +# set angles for first joint +set phi2 70 +set theta2 85 + +# set angles for second joint +set phi3 50 +set theta3 90 + +joint1 Identity +joint1 RotateY $phi2 +joint1 RotateX $theta2 + +joint2 Identity +joint2 RotateY $phi3 +joint2 RotateX $theta3 + +renWin Render + + + + diff --git a/Graphics/Testing/Tcl/TransformCoverage.tcl b/Graphics/Testing/Tcl/TransformCoverage.tcl new file mode 100644 index 0000000..dd86123 --- /dev/null +++ b/Graphics/Testing/Tcl/TransformCoverage.tcl @@ -0,0 +1,293 @@ +package require vtk + +# this test covers a lot of the code in vtkAbstractTransform that +# is not covered elsewhere + +# create a rendering window +vtkRenderWindow renWin +renWin SetSize 600 300 + +# set up first set of polydata +vtkPlaneSource p1 +p1 SetOrigin 0.5 0.508 -0.5 +p1 SetPoint1 -0.5 0.508 -0.5 +p1 SetPoint2 0.5 0.508 0.5 +p1 SetXResolution 5 +p1 SetYResolution 5 + +vtkPlaneSource p2 +p2 SetOrigin -0.508 0.5 -0.5 +p2 SetPoint1 -0.508 -0.5 -0.5 +p2 SetPoint2 -0.508 0.5 0.5 +p2 SetXResolution 5 +p2 SetYResolution 5 + +vtkPlaneSource p3 +p3 SetOrigin -0.5 -0.508 -0.5 +p3 SetPoint1 0.5 -0.508 -0.5 +p3 SetPoint2 -0.5 -0.508 0.5 +p3 SetXResolution 5 +p3 SetYResolution 5 + +vtkPlaneSource p4 +p4 SetOrigin 0.508 -0.5 -0.5 +p4 SetPoint1 0.508 0.5 -0.5 +p4 SetPoint2 0.508 -0.5 0.5 +p4 SetXResolution 5 +p4 SetYResolution 5 + +vtkPlaneSource p5 +p5 SetOrigin 0.5 0.5 -0.508 +p5 SetPoint1 0.5 -0.5 -0.508 +p5 SetPoint2 -0.5 0.5 -0.508 +p5 SetXResolution 5 +p5 SetYResolution 5 + +vtkPlaneSource p6 +p6 SetOrigin 0.5 0.5 0.508 +p6 SetPoint1 -0.5 0.5 0.508 +p6 SetPoint2 0.5 -0.5 0.508 +p6 SetXResolution 5 +p6 SetYResolution 5 + +# append together +vtkAppendPolyData ap +ap AddInput [p1 GetOutput] +ap AddInput [p2 GetOutput] +ap AddInput [p3 GetOutput] +ap AddInput [p4 GetOutput] +ap AddInput [p5 GetOutput] +ap AddInput [p6 GetOutput] + +#-------------------------- +vtkTransform tLinear +vtkPerspectiveTransform tPerspective +vtkGeneralTransform tGeneral + +# set up a linear transformation +tLinear Scale 1.2 1.0 0.8 +tLinear RotateX 30 +tLinear RotateY 10 +tLinear RotateZ 80 +tLinear Translate 0.2 0.3 -0.1 + +# set up a perspective transform +tPerspective SetInput tLinear +tPerspective SetInput [tLinear GetInverse] +tPerspective Scale 2 2 2 +# these should cancel +tPerspective AdjustViewport -0.5 0.5 -0.5 0.5 -1 1 -1 1 +tPerspective AdjustViewport -1 1 -1 1 -0.5 0.5 -0.5 0.5 +# test shear transformation +tPerspective Shear 0.2 0.3 0.0 + +# the following 6 operations cancel out +tPerspective RotateWXYZ 30 1 1 1 +tPerspective RotateWXYZ -30 1 1 1 +tPerspective Scale 2 2 2 +tPerspective Scale 0.5 0.5 0.5 +tPerspective Translate 10 0.1 0.3 +tPerspective Translate -10 -0.1 -0.3 + +tPerspective Concatenate tLinear +# test push and pop +tPerspective Push +tPerspective RotateX 30 +tPerspective RotateY 10 +tPerspective RotateZ 80 +tPerspective Translate 0.1 -0.2 0.0 + +# test copy of transforms +set tNew [tPerspective MakeTransform] +$tNew DeepCopy tPerspective + +tPerspective Pop + +# test general transform +tGeneral SetInput tLinear +tGeneral SetInput tPerspective +tGeneral PostMultiply +tGeneral Concatenate $tNew +tGeneral Concatenate [$tNew GetInverse] +tGeneral PreMultiply + +# the following 6 operations cancel out +tGeneral RotateWXYZ 30 1 1 1 +tGeneral RotateWXYZ -30 1 1 1 +tGeneral Scale 2 2 2 +tGeneral Scale 0.5 0.5 0.5 +tGeneral Translate 10 0.1 0.3 +tGeneral Translate -10 -0.1 -0.3 + +#-------------------------- +# identity transform + +vtkTransformPolyDataFilter f11 +f11 SetInputConnection [ap GetOutputPort] +f11 SetTransform tLinear + +vtkDataSetMapper m11 +m11 SetInputConnection [f11 GetOutputPort] + +vtkActor a11 +a11 SetMapper m11 +[a11 GetProperty] SetColor 1 0 0 +[a11 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren11 +ren11 SetViewport 0.0 0.5 0.25 1.0 +ren11 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren11 AddActor a11 +renWin AddRenderer ren11 + +# inverse identity transform +vtkTransformPolyDataFilter f12 +f12 SetInputConnection [ap GetOutputPort] +f12 SetTransform [tLinear GetInverse] + +vtkDataSetMapper m12 +m12 SetInputConnection [f12 GetOutputPort] + +vtkActor a12 +a12 SetMapper m12 +[a12 GetProperty] SetColor 0.9 0.9 0 +[a12 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren12 +ren12 SetViewport 0.0 0.0 0.25 0.5 +ren12 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren12 AddActor a12 +renWin AddRenderer ren12 + + +#-------------------------- +# linear transform +vtkTransformPolyDataFilter f21 +f21 SetInputConnection [ap GetOutputPort] +f21 SetTransform tPerspective + +vtkDataSetMapper m21 +m21 SetInputConnection [f21 GetOutputPort] + +vtkActor a21 +a21 SetMapper m21 +[a21 GetProperty] SetColor 1 0 0 +[a21 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren21 +ren21 SetViewport 0.25 0.5 0.50 1.0 +ren21 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren21 AddActor a21 +renWin AddRenderer ren21 + +# inverse linear transform +vtkTransformPolyDataFilter f22 +f22 SetInputConnection [ap GetOutputPort] +f22 SetTransform [tPerspective GetInverse] + +vtkDataSetMapper m22 +m22 SetInputConnection [f22 GetOutputPort] + +vtkActor a22 +a22 SetMapper m22 +[a22 GetProperty] SetColor 0.9 0.9 0 +[a22 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren22 +ren22 SetViewport 0.25 0.0 0.50 0.5 +ren22 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren22 AddActor a22 +renWin AddRenderer ren22 + + +#-------------------------- +# perspective transform +vtkMatrix4x4 matrix +matrix SetElement 3 0 0.1 +matrix SetElement 3 1 0.2 +matrix SetElement 3 2 0.5 + +vtkTransformPolyDataFilter f31 +f31 SetInputConnection [ap GetOutputPort] +f31 SetTransform $tNew + +vtkDataSetMapper m31 +m31 SetInputConnection [f31 GetOutputPort] + +vtkActor a31 +a31 SetMapper m31 +[a31 GetProperty] SetColor 1 0 0 +[a31 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren31 +ren31 SetViewport 0.50 0.5 0.75 1.0 +ren31 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren31 AddActor a31 +renWin AddRenderer ren31 + +# inverse linear transform +vtkTransformPolyDataFilter f32 +f32 SetInputConnection [ap GetOutputPort] +f32 SetTransform [$tNew GetInverse] + +vtkDataSetMapper m32 +m32 SetInputConnection [f32 GetOutputPort] + +vtkActor a32 +a32 SetMapper m32 +[a32 GetProperty] SetColor 0.9 0.9 0 +[a32 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren32 +ren32 SetViewport 0.5 0.0 0.75 0.5 +ren32 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren32 AddActor a32 +renWin AddRenderer ren32 + + +#-------------------------- +# perspective transform concatenation +vtkTransformPolyDataFilter f41 +f41 SetInputConnection [ap GetOutputPort] +f41 SetTransform tGeneral + +vtkDataSetMapper m41 +m41 SetInputConnection [f41 GetOutputPort] + +vtkActor a41 +a41 SetMapper m41 +[a41 GetProperty] SetColor 1 0 0 +[a41 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren41 +ren41 SetViewport 0.75 0.5 1.0 1.0 +ren41 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren41 AddActor a41 +renWin AddRenderer ren41 + +# inverse linear transform +vtkTransformPolyDataFilter f42 +f42 SetInputConnection [ap GetOutputPort] +f42 SetTransform [tGeneral GetInverse] + +vtkDataSetMapper m42 +m42 SetInputConnection [f42 GetOutputPort] + +vtkActor a42 +a42 SetMapper m42 +[a42 GetProperty] SetColor 0.9 0.9 0 +[a42 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren42 +ren42 SetViewport 0.75 0.0 1.0 0.5 +ren42 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren42 AddActor a42 +renWin AddRenderer ren42 + + +renWin Render + +# free what we did a MakeTransform on +$tNew UnRegister {} + + diff --git a/Graphics/Testing/Tcl/TransformPolyData.tcl b/Graphics/Testing/Tcl/TransformPolyData.tcl new file mode 100644 index 0000000..d23a359 --- /dev/null +++ b/Graphics/Testing/Tcl/TransformPolyData.tcl @@ -0,0 +1,242 @@ +package require vtk + +# create a rendering window +vtkRenderWindow renWin +renWin SetSize 600 300 + +# set up first set of polydata +vtkPlaneSource p1 +p1 SetOrigin 0.5 0.508 -0.5 +p1 SetPoint1 -0.5 0.508 -0.5 +p1 SetPoint2 0.5 0.508 0.5 +p1 SetXResolution 5 +p1 SetYResolution 5 + +vtkPlaneSource p2 +p2 SetOrigin -0.508 0.5 -0.5 +p2 SetPoint1 -0.508 -0.5 -0.5 +p2 SetPoint2 -0.508 0.5 0.5 +p2 SetXResolution 5 +p2 SetYResolution 5 + +vtkPlaneSource p3 +p3 SetOrigin -0.5 -0.508 -0.5 +p3 SetPoint1 0.5 -0.508 -0.5 +p3 SetPoint2 -0.5 -0.508 0.5 +p3 SetXResolution 5 +p3 SetYResolution 5 + +vtkPlaneSource p4 +p4 SetOrigin 0.508 -0.5 -0.5 +p4 SetPoint1 0.508 0.5 -0.5 +p4 SetPoint2 0.508 -0.5 0.5 +p4 SetXResolution 5 +p4 SetYResolution 5 + +vtkPlaneSource p5 +p5 SetOrigin 0.5 0.5 -0.508 +p5 SetPoint1 0.5 -0.5 -0.508 +p5 SetPoint2 -0.5 0.5 -0.508 +p5 SetXResolution 5 +p5 SetYResolution 5 + +vtkPlaneSource p6 +p6 SetOrigin 0.5 0.5 0.508 +p6 SetPoint1 -0.5 0.5 0.508 +p6 SetPoint2 0.5 -0.5 0.508 +p6 SetXResolution 5 +p6 SetYResolution 5 + +# append together +vtkAppendPolyData ap +ap AddInput [p1 GetOutput] +ap AddInput [p2 GetOutput] +ap AddInput [p3 GetOutput] +ap AddInput [p4 GetOutput] +ap AddInput [p5 GetOutput] +ap AddInput [p6 GetOutput] + +#-------------------------- +# identity transform +vtkIdentityTransform t1 + +vtkTransformPolyDataFilter f11 +f11 SetInputConnection [ap GetOutputPort] +f11 SetTransform t1 + +vtkDataSetMapper m11 +m11 SetInputConnection [f11 GetOutputPort] + +vtkActor a11 +a11 SetMapper m11 +[a11 GetProperty] SetColor 1 0 0 +[a11 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren11 +ren11 SetViewport 0.0 0.5 0.25 1.0 +ren11 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren11 AddActor a11 +renWin AddRenderer ren11 + +# inverse identity transform +vtkTransformPolyDataFilter f12 +f12 SetInputConnection [ap GetOutputPort] +f12 SetTransform [t1 GetInverse] + +vtkDataSetMapper m12 +m12 SetInputConnection [f12 GetOutputPort] + +vtkActor a12 +a12 SetMapper m12 +[a12 GetProperty] SetColor 0.9 0.9 0 +[a12 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren12 +ren12 SetViewport 0.0 0.0 0.25 0.5 +ren12 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren12 AddActor a12 +renWin AddRenderer ren12 + + +#-------------------------- +# linear transform +vtkTransform t2 +t2 RotateX 50 +t2 RotateY 30 +t2 Translate 0.2 0.1 -0.15 + +vtkTransformPolyDataFilter f21 +f21 SetInputConnection [ap GetOutputPort] +f21 SetTransform t2 + +vtkDataSetMapper m21 +m21 SetInputConnection [f21 GetOutputPort] + +vtkActor a21 +a21 SetMapper m21 +[a21 GetProperty] SetColor 1 0 0 +[a21 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren21 +ren21 SetViewport 0.25 0.5 0.50 1.0 +ren21 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren21 AddActor a21 +renWin AddRenderer ren21 + +# inverse linear transform +vtkTransformPolyDataFilter f22 +f22 SetInputConnection [ap GetOutputPort] +f22 SetTransform [t2 GetInverse] + +vtkDataSetMapper m22 +m22 SetInputConnection [f22 GetOutputPort] + +vtkActor a22 +a22 SetMapper m22 +[a22 GetProperty] SetColor 0.9 0.9 0 +[a22 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren22 +ren22 SetViewport 0.25 0.0 0.50 0.5 +ren22 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren22 AddActor a22 +renWin AddRenderer ren22 + + +#-------------------------- +# perspective transform +vtkMatrix4x4 matrix +matrix SetElement 3 0 0.1 +matrix SetElement 3 1 0.2 +matrix SetElement 3 2 0.5 + +vtkPerspectiveTransform t3 +t3 SetMatrix matrix + +vtkTransformPolyDataFilter f31 +f31 SetInputConnection [ap GetOutputPort] +f31 SetTransform t3 + +vtkDataSetMapper m31 +m31 SetInputConnection [f31 GetOutputPort] + +vtkActor a31 +a31 SetMapper m31 +[a31 GetProperty] SetColor 1 0 0 +[a31 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren31 +ren31 SetViewport 0.50 0.5 0.75 1.0 +ren31 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren31 AddActor a31 +renWin AddRenderer ren31 + +# inverse linear transform +vtkTransformPolyDataFilter f32 +f32 SetInputConnection [ap GetOutputPort] +f32 SetTransform [t3 GetInverse] + +vtkDataSetMapper m32 +m32 SetInputConnection [f32 GetOutputPort] + +vtkActor a32 +a32 SetMapper m32 +[a32 GetProperty] SetColor 0.9 0.9 0 +[a32 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren32 +ren32 SetViewport 0.5 0.0 0.75 0.5 +ren32 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren32 AddActor a32 +renWin AddRenderer ren32 + + +#-------------------------- +# perspective transform concatenation +vtkPerspectiveTransform t4 +t4 Concatenate t1 +t4 Concatenate t2 +t4 Concatenate t3 + +vtkTransformPolyDataFilter f41 +f41 SetInputConnection [ap GetOutputPort] +f41 SetTransform t4 + +vtkDataSetMapper m41 +m41 SetInputConnection [f41 GetOutputPort] + +vtkActor a41 +a41 SetMapper m41 +[a41 GetProperty] SetColor 1 0 0 +[a41 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren41 +ren41 SetViewport 0.75 0.5 1.0 1.0 +ren41 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren41 AddActor a41 +renWin AddRenderer ren41 + +# inverse linear transform +vtkTransformPolyDataFilter f42 +f42 SetInputConnection [ap GetOutputPort] +f42 SetTransform [t4 GetInverse] + +vtkDataSetMapper m42 +m42 SetInputConnection [f42 GetOutputPort] + +vtkActor a42 +a42 SetMapper m42 +[a42 GetProperty] SetColor 0.9 0.9 0 +[a42 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren42 +ren42 SetViewport 0.75 0.0 1.0 0.5 +ren42 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren42 AddActor a42 +renWin AddRenderer ren42 + + +renWin Render + + + diff --git a/Graphics/Testing/Tcl/blankGrid.tcl b/Graphics/Testing/Tcl/blankGrid.tcl new file mode 100644 index 0000000..340b99f --- /dev/null +++ b/Graphics/Testing/Tcl/blankGrid.tcl @@ -0,0 +1,151 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Demonstrate how to use structured grid blanking with an image. There are two +# techniques demonstrated: one uses an image to perform the blanking; +# the other uses scalar values to do the same thing. Both images should +# be identical. +# + +# get the interactor ui + +# create pipeline - start by extracting a single plane from the grid +# + +vtkPLOT3DReader pl3d +pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" +pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" +pl3d SetScalarFunctionNumber 100 +pl3d SetVectorFunctionNumber 202 + +vtkExtractGrid plane +plane SetInputConnection [pl3d GetOutputPort] +plane SetVOI 0 57 0 33 0 0 +plane Update + +# Create some data to use for the (image) blanking +# +vtkImageData blankImage +blankImage SetScalarTypeToUnsignedChar +blankImage SetDimensions 57 33 1 +blankImage AllocateScalars +[[blankImage GetPointData] GetScalars] SetName "blankScalars" + +set blanking [[blankImage GetPointData] GetScalars] +set numBlanks [expr 57*33] +for {set i 0} {$i<$numBlanks} {incr i} { + $blanking SetComponent $i 0 1 +} + +# Manually blank out areas corresponding to dilution holes +$blanking SetComponent 318 0 0 +$blanking SetComponent 945 0 0 +$blanking SetComponent 1572 0 0 +$blanking SetComponent 641 0 0 +$blanking SetComponent 1553 0 0 + +# The first blanking technique uses the image to set the blanking values +# +vtkBlankStructuredGridWithImage blankIt +blankIt SetInputConnection [plane GetOutputPort] +blankIt SetBlankingInput blankImage + +vtkStructuredGridGeometryFilter blankedPlane +blankedPlane SetInputConnection [blankIt GetOutputPort] +blankedPlane SetExtent 0 100 0 100 0 0 + +vtkPolyDataMapper planeMapper +planeMapper SetInputConnection [blankedPlane GetOutputPort] +planeMapper SetScalarRange 0.197813 0.710419 + +vtkActor planeActor +planeActor SetMapper planeMapper + +# The second blanking technique uses grid data values to create the blanking. +# Here we borrow the image data and threshold on that. +# +vtkStructuredGrid anotherGrid +anotherGrid CopyStructure [plane GetOutput] +[anotherGrid GetPointData] SetScalars [[blankImage GetPointData] GetScalars] + +vtkBlankStructuredGrid blankGrid +blankGrid SetInput anotherGrid +blankGrid SetArrayName "blankScalars" +blankGrid SetMinBlankingValue -0.5 +blankGrid SetMaxBlankingValue 0.5 + +vtkStructuredGridGeometryFilter blankedPlane2 +blankedPlane2 SetInputConnection [blankGrid GetOutputPort] +blankedPlane2 SetExtent 0 100 0 100 0 0 + +vtkPolyDataMapper planeMapper2 +planeMapper2 SetInputConnection [blankedPlane2 GetOutputPort] +planeMapper2 SetScalarRange 0.197813 0.710419 + +vtkActor planeActor2 +planeActor2 SetMapper planeMapper2 + +# An outline around the data +# +vtkStructuredGridOutlineFilter outline +outline SetInputConnection [pl3d GetOutputPort] + +vtkPolyDataMapper outlineMapper +outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor +outlineActor SetMapper outlineMapper +eval [outlineActor GetProperty] SetColor $black + +vtkPolyDataMapper outlineMapper2 +outlineMapper2 SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor2 +outlineActor2 SetMapper outlineMapper2 +eval [outlineActor2 GetProperty] SetColor $black + +# create planes +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +ren1 SetViewport 0 0 0.5 1 + +vtkRenderer ren2 +ren2 SetViewport 0.5 0 1 1 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin AddRenderer ren2 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren2 AddActor outlineActor2 +ren2 AddActor planeActor2 + +ren1 SetBackground 1 1 1 +ren2 SetBackground 1 1 1 + +renWin SetSize 500 250 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 8.88908 0.595038 29.3342 +$cam1 SetPosition -12.3332 31.7479 41.2387 +$cam1 SetViewUp 0.060772 -0.319905 0.945498 +ren2 SetActiveCamera [ren1 GetActiveCamera] + +# render the image +# +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/capCow.tcl b/Graphics/Testing/Tcl/capCow.tcl new file mode 100644 index 0000000..b08c720 --- /dev/null +++ b/Graphics/Testing/Tcl/capCow.tcl @@ -0,0 +1,106 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# +# Demonstrate the use of clipping and capping on polyhedral data. Also shows how to +# use triangle filter to triangulate loops. +# + +# create pipeline +# +# Read the polygonal data and generate vertex normals +vtkBYUReader cow + cow SetGeometryFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.g" +vtkPolyDataNormals cowNormals + cowNormals SetInputConnection [cow GetOutputPort] + +# Define a clip plane to clip the cow in half +vtkPlane plane + plane SetOrigin 0.25 0 0 + plane SetNormal -1 -1 0 +vtkClipPolyData clipper + clipper SetInputConnection [cowNormals GetOutputPort] + clipper SetClipFunction plane + clipper GenerateClipScalarsOn + clipper GenerateClippedOutputOn + clipper SetValue 0.5 +vtkPolyDataMapper clipMapper + clipMapper SetInputConnection [clipper GetOutputPort] + clipMapper ScalarVisibilityOff +vtkProperty backProp + eval backProp SetDiffuseColor $tomato +vtkActor clipActor + clipActor SetMapper clipMapper + eval [clipActor GetProperty] SetColor $peacock + clipActor SetBackfaceProperty backProp + +# Create polygons outlining clipped areas and triangulate them to generate cut surface +vtkCutter cutEdges; #Generate cut lines + cutEdges SetInputConnection [cowNormals GetOutputPort] + cutEdges SetCutFunction plane + cutEdges GenerateCutScalarsOn + cutEdges SetValue 0 0.5 +vtkStripper cutStrips; #Forms loops (closed polylines) from cutter + cutStrips SetInputConnection [cutEdges GetOutputPort] + cutStrips Update +vtkPolyData cutPoly; #This trick defines polygons as polyline loop + cutPoly SetPoints [[cutStrips GetOutput] GetPoints] + cutPoly SetPolys [[cutStrips GetOutput] GetLines] +vtkTriangleFilter cutTriangles; #Triangulates the polygons to create cut surface + cutTriangles SetInput cutPoly +vtkPolyDataMapper cutMapper + cutMapper SetInput cutPoly + cutMapper SetInputConnection [cutTriangles GetOutputPort] +vtkActor cutActor + cutActor SetMapper cutMapper + eval [cutActor GetProperty] SetColor $peacock + +# Create the rest of the cow in wireframe +vtkPolyDataMapper restMapper + restMapper SetInput [clipper GetClippedOutput] + restMapper ScalarVisibilityOff +vtkActor restActor + restActor SetMapper restMapper + [restActor GetProperty] SetRepresentationToWireframe + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor clipActor +ren1 AddActor cutActor +ren1 AddActor restActor +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCameraClippingRange + +renWin SetSize 300 300 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + +# Lets you move the cut plane back and forth +proc Cut {v} { + clipper SetValue $v + cutEdges SetValue 0 $v + cutStrips Update + cutPoly SetPoints [[cutStrips GetOutput] GetPoints] + cutPoly SetPolys [[cutStrips GetOutput] GetLines] + cutMapper Update + renWin Render +} diff --git a/Graphics/Testing/Tcl/capSphere.tcl b/Graphics/Testing/Tcl/capSphere.tcl new file mode 100644 index 0000000..72264a6 --- /dev/null +++ b/Graphics/Testing/Tcl/capSphere.tcl @@ -0,0 +1,90 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# +# Demonstrate the use of clipping and capping on polyhedral data +# + +# create a sphere and clip it +# +vtkSphereSource sphere + sphere SetRadius 1 + sphere SetPhiResolution 10 + sphere SetThetaResolution 10 +vtkPlane plane + plane SetOrigin 0 0 0 + plane SetNormal -1 -1 0 +vtkClipPolyData clipper + clipper SetInputConnection [sphere GetOutputPort] + clipper SetClipFunction plane + clipper GenerateClipScalarsOn + clipper GenerateClippedOutputOn + clipper SetValue 0 +vtkPolyDataMapper clipMapper + clipMapper SetInputConnection [clipper GetOutputPort] + clipMapper ScalarVisibilityOff + +vtkProperty backProp + eval backProp SetDiffuseColor $tomato +vtkActor clipActor + clipActor SetMapper clipMapper + eval [clipActor GetProperty] SetColor $peacock + clipActor SetBackfaceProperty backProp + +# now extract feature edges +vtkFeatureEdges boundaryEdges + boundaryEdges SetInputConnection [clipper GetOutputPort] + boundaryEdges BoundaryEdgesOn + boundaryEdges FeatureEdgesOff + boundaryEdges NonManifoldEdgesOff + +vtkCleanPolyData boundaryClean + boundaryClean SetInputConnection [boundaryEdges GetOutputPort] + +vtkStripper boundaryStrips + boundaryStrips SetInputConnection [boundaryClean GetOutputPort] + boundaryStrips Update + +vtkPolyData boundaryPoly + boundaryPoly SetPoints [[boundaryStrips GetOutput] GetPoints] + boundaryPoly SetPolys [[boundaryStrips GetOutput] GetLines] + +vtkTriangleFilter boundaryTriangles + boundaryTriangles SetInput boundaryPoly + +vtkPolyDataMapper boundaryMapper +boundaryMapper SetInputConnection [boundaryTriangles GetOutputPort] + +vtkActor boundaryActor + boundaryActor SetMapper boundaryMapper + eval [boundaryActor GetProperty] SetColor $banana + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor clipActor +ren1 AddActor boundaryActor +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +renWin SetSize 300 300 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/clipArt.tcl b/Graphics/Testing/Tcl/clipArt.tcl new file mode 100644 index 0000000..6554e2a --- /dev/null +++ b/Graphics/Testing/Tcl/clipArt.tcl @@ -0,0 +1,156 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkTIFFReader imageIn + imageIn SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + imageIn ReleaseDataFlagOff + imageIn Update + +proc PowerOfTwo {amt} { + set pow 0 + incr amt -1 + while {1} { + set amt [expr $amt >> 1] + incr pow + if {$amt <= 0} {return [expr 1 << $pow];} + } +} + +set orgX [expr [lindex [[imageIn GetOutput] GetWholeExtent] 1] - [lindex [[imageIn GetOutput] GetWholeExtent] 0] + 1] +set orgY [expr [lindex [[imageIn GetOutput] GetWholeExtent] 3] - [lindex [[imageIn GetOutput] GetWholeExtent] 2] + 1] +set padX [PowerOfTwo $orgX] +set padY [PowerOfTwo $orgY] + +vtkImageConstantPad imagePowerOf2 + imagePowerOf2 SetInputConnection [imageIn GetOutputPort] + imagePowerOf2 SetOutputWholeExtent 0 [expr $padX - 1] 0 [expr $padY - 1] 0 0 + +vtkImageRGBToHSV toHSV + toHSV SetInputConnection [imageIn GetOutputPort] + toHSV ReleaseDataFlagOff + +vtkImageExtractComponents extractImage + extractImage SetInputConnection [toHSV GetOutputPort] + extractImage SetComponents 2 + extractImage ReleaseDataFlagOff + +vtkImageThreshold threshold1 + threshold1 SetInputConnection [extractImage GetOutputPort] + threshold1 ThresholdByUpper 230 + threshold1 SetInValue 255 + threshold1 SetOutValue 0 + threshold1 Update + + +set extent [[threshold1 GetOutput] GetWholeExtent] + +vtkImageSeedConnectivity connect + connect SetInputConnection [threshold1 GetOutputPort] + connect SetInputConnectValue 255 + connect SetOutputConnectedValue 255 + connect SetOutputUnconnectedValue 0 + connect AddSeed [lindex $extent 0] [lindex $extent 2] + connect AddSeed [lindex $extent 1] [lindex $extent 2] + connect AddSeed [lindex $extent 1] [lindex $extent 3] + connect AddSeed [lindex $extent 0] [lindex $extent 3] + +vtkImageGaussianSmooth smooth + smooth SetDimensionality 2 + smooth SetStandardDeviation 1 1 + smooth SetInputConnection [connect GetOutputPort] + +vtkImageShrink3D shrink + shrink SetInputConnection [smooth GetOutputPort] + shrink SetShrinkFactors 2 2 1 + shrink AveragingOn + +vtkImageDataGeometryFilter geometry + geometry SetInputConnection [shrink GetOutputPort] + +vtkTextureMapToPlane geometryTexture + geometryTexture SetInputConnection [geometry GetOutputPort] + geometryTexture SetOrigin 0 0 0 + geometryTexture SetPoint1 [expr $padX - 1] 0 0 + geometryTexture SetPoint2 0 [expr $padY - 1] 0 + +vtkCastToConcrete geometryPD + geometryPD SetInputConnection [geometryTexture GetOutputPort] + +vtkClipPolyData clip + clip SetInput [geometryPD GetPolyDataOutput] + clip SetValue 5.5 + clip GenerateClipScalarsOff + clip InsideOutOff + clip InsideOutOn + [[clip GetOutput] GetPointData] CopyScalarsOff + clip Update + +vtkTriangleFilter triangles + triangles SetInputConnection [clip GetOutputPort] + +vtkDecimatePro decimate + decimate SetInputConnection [triangles GetOutputPort] + decimate BoundaryVertexDeletionOn + decimate SetDegree 25 + decimate PreserveTopologyOn + +vtkLinearExtrusionFilter extrude + extrude SetInputConnection [decimate GetOutputPort] + extrude SetExtrusionType 2 + extrude SetScaleFactor -20 + +vtkPolyDataNormals normals + normals SetInputConnection [extrude GetOutputPort] + normals SetFeatureAngle 80 + +vtkStripper strip + strip SetInputConnection [extrude GetOutputPort] + +vtkPolyDataMapper map + map SetInputConnection [strip GetOutputPort] + map SetInputConnection [normals GetOutputPort] + map ScalarVisibilityOff + +vtkTexture imageTexture + imageTexture InterpolateOn + imageTexture SetInputConnection [imagePowerOf2 GetOutputPort] + +vtkActor clipart + clipart SetMapper map + clipart SetTexture imageTexture + +ren1 AddActor clipart +[clipart GetProperty] SetDiffuseColor 1 1 1 +[clipart GetProperty] SetSpecular .5 +[clipart GetProperty] SetSpecularPower 30 +[clipart GetProperty] SetDiffuse .9 + +ren1 ResetCamera +set camera [ren1 GetActiveCamera] +$camera Azimuth 30 +$camera Elevation -30 +$camera Dolly 1.5 +ren1 ResetCameraClippingRange + +ren1 SetBackground 0.2 0.3 0.4 +renWin SetSize 320 256 +iren Initialize + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/clipComb.tcl b/Graphics/Testing/Tcl/clipComb.tcl new file mode 100644 index 0000000..782d2c7 --- /dev/null +++ b/Graphics/Testing/Tcl/clipComb.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# create a crazy implicit function +set center [[pl3d GetOutput] GetCenter] +vtkSphere sphere + eval sphere SetCenter $center + sphere SetRadius 2.0 +vtkSphere sphere2 + sphere2 SetCenter [expr [lindex $center 0] + 4.0] [lindex $center 1] \ + [lindex $center 2] + sphere2 SetRadius 4.0 +vtkImplicitBoolean bool + bool SetOperationTypeToUnion + bool AddFunction sphere + bool AddFunction sphere2 + +# clip the structured grid to produce a tetrahedral mesh +vtkClipDataSet clip + clip SetInputConnection [pl3d GetOutputPort] + clip SetClipFunction bool + clip InsideOutOn + +vtkGeometryFilter gf + gf SetInputConnection [clip GetOutputPort] +vtkPolyDataMapper clipMapper + clipMapper SetInputConnection [gf GetOutputPort] +vtkActor clipActor + clipActor SetMapper clipMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor clipActor +ren1 AddActor outlineActor + +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 8.88908 0.595038 29.3342 +$cam1 SetPosition -12.3332 31.7479 41.2387 +$cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/clipImage.tcl b/Graphics/Testing/Tcl/clipImage.tcl new file mode 100644 index 0000000..9f70896 --- /dev/null +++ b/Graphics/Testing/Tcl/clipImage.tcl @@ -0,0 +1,59 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# create pipeline +# +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 45 45 + v16 SetDataSpacing 3.2 3.2 1.5 + v16 Update + +# do the pixel clipping +vtkClipDataSet clip + clip SetInputConnection [v16 GetOutputPort] + clip SetValue 1000 +vtkDataSetMapper clipMapper + clipMapper SetInputConnection [clip GetOutputPort] + clipMapper ScalarVisibilityOff +vtkActor clipActor + clipActor SetMapper clipMapper + +# put an outline around the data +vtkOutlineFilter outline + outline SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor clipActor + +ren1 SetBackground 0 0 0 +renWin SetSize 200 200 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/clipQuadraticCells.tcl b/Graphics/Testing/Tcl/clipQuadraticCells.tcl new file mode 100644 index 0000000..c4393dd --- /dev/null +++ b/Graphics/Testing/Tcl/clipQuadraticCells.tcl @@ -0,0 +1,507 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Contour every quadratic cell type + +# Create a scene with one of each cell type. +# QuadraticEdge +vtkPoints edgePoints + edgePoints SetNumberOfPoints 3 + edgePoints InsertPoint 0 0 0 0 + edgePoints InsertPoint 1 1.0 0 0 + edgePoints InsertPoint 2 0.5 0.25 0 +vtkFloatArray edgeScalars + edgeScalars SetNumberOfTuples 3 + edgeScalars InsertValue 0 0.0 + edgeScalars InsertValue 1 0.0 + edgeScalars InsertValue 2 0.9 +vtkQuadraticEdge aEdge + [aEdge GetPointIds] SetId 0 0 + [aEdge GetPointIds] SetId 1 1 + [aEdge GetPointIds] SetId 2 2 +vtkUnstructuredGrid aEdgeGrid + aEdgeGrid Allocate 1 1 + aEdgeGrid InsertNextCell [aEdge GetCellType] [aEdge GetPointIds] + aEdgeGrid SetPoints edgePoints + [aEdgeGrid GetPointData] SetScalars edgeScalars +vtkClipDataSet edgeContours + edgeContours SetInput aEdgeGrid + edgeContours SetValue 0.5 +vtkDataSetMapper aEdgeContourMapper + aEdgeContourMapper SetInputConnection [edgeContours GetOutputPort] + aEdgeContourMapper ScalarVisibilityOff +vtkDataSetMapper aEdgeMapper + aEdgeMapper SetInput aEdgeGrid + aEdgeMapper ScalarVisibilityOff +vtkActor aEdgeActor + aEdgeActor SetMapper aEdgeMapper + [aEdgeActor GetProperty] SetRepresentationToWireframe + [aEdgeActor GetProperty] SetAmbient 1.0 +vtkActor aEdgeContourActor + aEdgeContourActor SetMapper aEdgeContourMapper + [aEdgeContourActor GetProperty] BackfaceCullingOn + [aEdgeContourActor GetProperty] SetAmbient 1.0 + +# Quadratic triangle +vtkPoints triPoints + triPoints SetNumberOfPoints 6 + triPoints InsertPoint 0 0.0 0.0 0.0 + triPoints InsertPoint 1 1.0 0.0 0.0 + triPoints InsertPoint 2 0.5 0.8 0.0 + triPoints InsertPoint 3 0.5 0.0 0.0 + triPoints InsertPoint 4 0.75 0.4 0.0 + triPoints InsertPoint 5 0.25 0.4 0.0 +vtkFloatArray triScalars + triScalars SetNumberOfTuples 6 + triScalars InsertValue 0 0.0 + triScalars InsertValue 1 0.0 + triScalars InsertValue 2 0.0 + triScalars InsertValue 3 1.0 + triScalars InsertValue 4 0.0 + triScalars InsertValue 5 0.0 +vtkQuadraticTriangle aTri + [aTri GetPointIds] SetId 0 0 + [aTri GetPointIds] SetId 1 1 + [aTri GetPointIds] SetId 2 2 + [aTri GetPointIds] SetId 3 3 + [aTri GetPointIds] SetId 4 4 + [aTri GetPointIds] SetId 5 5 +vtkUnstructuredGrid aTriGrid + aTriGrid Allocate 1 1 + aTriGrid InsertNextCell [aTri GetCellType] [aTri GetPointIds] + aTriGrid SetPoints triPoints + [aTriGrid GetPointData] SetScalars triScalars +vtkClipDataSet triContours + triContours SetInput aTriGrid + triContours SetValue 0.5 +vtkDataSetMapper aTriContourMapper + aTriContourMapper SetInputConnection [triContours GetOutputPort] + aTriContourMapper ScalarVisibilityOff +vtkDataSetMapper aTriMapper + aTriMapper SetInput aTriGrid + aTriMapper ScalarVisibilityOff +vtkActor aTriActor + aTriActor SetMapper aTriMapper + [aTriActor GetProperty] SetRepresentationToWireframe + [aTriActor GetProperty] SetAmbient 1.0 +vtkActor aTriContourActor + aTriContourActor SetMapper aTriContourMapper + [aTriContourActor GetProperty] BackfaceCullingOn + [aTriContourActor GetProperty] SetAmbient 1.0 + +# Quadratic quadrilateral +vtkPoints quadPoints + quadPoints SetNumberOfPoints 8 + quadPoints InsertPoint 0 0.0 0.0 0.0 + quadPoints InsertPoint 1 1.0 0.0 0.0 + quadPoints InsertPoint 2 1.0 1.0 0.0 + quadPoints InsertPoint 3 0.0 1.0 0.0 + quadPoints InsertPoint 4 0.5 0.0 0.0 + quadPoints InsertPoint 5 1.0 0.5 0.0 + quadPoints InsertPoint 6 0.5 1.0 0.0 + quadPoints InsertPoint 7 0.0 0.5 0.0 +vtkFloatArray quadScalars + quadScalars SetNumberOfTuples 8 + quadScalars InsertValue 0 0.0 + quadScalars InsertValue 1 0.0 + quadScalars InsertValue 2 1.0 + quadScalars InsertValue 3 1.0 + quadScalars InsertValue 4 1.0 + quadScalars InsertValue 5 0.0 + quadScalars InsertValue 6 0.0 + quadScalars InsertValue 7 0.0 +vtkQuadraticQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + [aQuad GetPointIds] SetId 4 4 + [aQuad GetPointIds] SetId 5 5 + [aQuad GetPointIds] SetId 6 6 + [aQuad GetPointIds] SetId 7 7 +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + [aQuadGrid GetPointData] SetScalars quadScalars +vtkClipDataSet quadContours + quadContours SetInput aQuadGrid + quadContours SetValue 0.5 +vtkDataSetMapper aQuadContourMapper + aQuadContourMapper SetInputConnection [quadContours GetOutputPort] + aQuadContourMapper ScalarVisibilityOff +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid + aQuadMapper ScalarVisibilityOff +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + [aQuadActor GetProperty] SetRepresentationToWireframe + [aQuadActor GetProperty] SetAmbient 1.0 +vtkActor aQuadContourActor + aQuadContourActor SetMapper aQuadContourMapper + [aQuadContourActor GetProperty] BackfaceCullingOn + [aQuadContourActor GetProperty] SetAmbient 1.0 + +# Quadratic tetrahedron +vtkPoints tetPoints + tetPoints SetNumberOfPoints 10 + tetPoints InsertPoint 0 0.0 0.0 0.0 + tetPoints InsertPoint 1 1.0 0.0 0.0 + tetPoints InsertPoint 2 0.5 0.8 0.0 + tetPoints InsertPoint 3 0.5 0.4 1.0 + tetPoints InsertPoint 4 0.5 0.0 0.0 + tetPoints InsertPoint 5 0.75 0.4 0.0 + tetPoints InsertPoint 6 0.25 0.4 0.0 + tetPoints InsertPoint 7 0.25 0.2 0.5 + tetPoints InsertPoint 8 0.75 0.2 0.5 + tetPoints InsertPoint 9 0.50 0.6 0.5 +vtkFloatArray tetScalars + tetScalars SetNumberOfTuples 10 + tetScalars InsertValue 0 1.0 + tetScalars InsertValue 1 1.0 + tetScalars InsertValue 2 1.0 + tetScalars InsertValue 3 1.0 + tetScalars InsertValue 4 0.0 + tetScalars InsertValue 5 0.0 + tetScalars InsertValue 6 0.0 + tetScalars InsertValue 7 0.0 + tetScalars InsertValue 8 0.0 + tetScalars InsertValue 9 0.0 +vtkQuadraticTetra aTet + [aTet GetPointIds] SetId 0 0 + [aTet GetPointIds] SetId 1 1 + [aTet GetPointIds] SetId 2 2 + [aTet GetPointIds] SetId 3 3 + [aTet GetPointIds] SetId 4 4 + [aTet GetPointIds] SetId 5 5 + [aTet GetPointIds] SetId 6 6 + [aTet GetPointIds] SetId 7 7 + [aTet GetPointIds] SetId 8 8 + [aTet GetPointIds] SetId 9 9 +vtkUnstructuredGrid aTetGrid + aTetGrid Allocate 1 1 + aTetGrid InsertNextCell [aTet GetCellType] [aTet GetPointIds] + aTetGrid SetPoints tetPoints + [aTetGrid GetPointData] SetScalars tetScalars +vtkClipDataSet tetContours + tetContours SetInput aTetGrid + tetContours SetValue 0.5 +vtkDataSetMapper aTetContourMapper + aTetContourMapper SetInputConnection [tetContours GetOutputPort] + aTetContourMapper ScalarVisibilityOff +vtkDataSetMapper aTetMapper + aTetMapper SetInput aTetGrid + aTetMapper ScalarVisibilityOff +vtkActor aTetActor + aTetActor SetMapper aTetMapper + [aTetActor GetProperty] SetRepresentationToWireframe + [aTetActor GetProperty] SetAmbient 1.0 +vtkActor aTetContourActor + aTetContourActor SetMapper aTetContourMapper + [aTetContourActor GetProperty] SetAmbient 1.0 + +# Quadratic hexahedron +vtkPoints hexPoints + hexPoints SetNumberOfPoints 20 + hexPoints InsertPoint 0 0 0 0 + hexPoints InsertPoint 1 1 0 0 + hexPoints InsertPoint 2 1 1 0 + hexPoints InsertPoint 3 0 1 0 + hexPoints InsertPoint 4 0 0 1 + hexPoints InsertPoint 5 1 0 1 + hexPoints InsertPoint 6 1 1 1 + hexPoints InsertPoint 7 0 1 1 + hexPoints InsertPoint 8 0.5 0 0 + hexPoints InsertPoint 9 1 0.5 0 + hexPoints InsertPoint 10 0.5 1 0 + hexPoints InsertPoint 11 0 0.5 0 + hexPoints InsertPoint 12 0.5 0 1 + hexPoints InsertPoint 13 1 0.5 1 + hexPoints InsertPoint 14 0.5 1 1 + hexPoints InsertPoint 15 0 0.5 1 + hexPoints InsertPoint 16 0 0 0.5 + hexPoints InsertPoint 17 1 0 0.5 + hexPoints InsertPoint 18 1 1 0.5 + hexPoints InsertPoint 19 0 1 0.5 +vtkFloatArray hexScalars + hexScalars SetNumberOfTuples 20 + hexScalars InsertValue 0 1.0 + hexScalars InsertValue 1 1.0 + hexScalars InsertValue 2 1.0 + hexScalars InsertValue 3 1.0 + hexScalars InsertValue 4 1.0 + hexScalars InsertValue 5 1.0 + hexScalars InsertValue 6 1.0 + hexScalars InsertValue 7 1.0 + hexScalars InsertValue 8 0.0 + hexScalars InsertValue 9 0.0 + hexScalars InsertValue 10 0.0 + hexScalars InsertValue 11 0.0 + hexScalars InsertValue 12 0.0 + hexScalars InsertValue 13 0.0 + hexScalars InsertValue 14 0.0 + hexScalars InsertValue 15 0.0 + hexScalars InsertValue 16 0.0 + hexScalars InsertValue 17 0.0 + hexScalars InsertValue 18 0.0 + hexScalars InsertValue 19 0.0 +vtkQuadraticHexahedron aHex + [aHex GetPointIds] SetId 0 0 + [aHex GetPointIds] SetId 1 1 + [aHex GetPointIds] SetId 2 2 + [aHex GetPointIds] SetId 3 3 + [aHex GetPointIds] SetId 4 4 + [aHex GetPointIds] SetId 5 5 + [aHex GetPointIds] SetId 6 6 + [aHex GetPointIds] SetId 7 7 + [aHex GetPointIds] SetId 8 8 + [aHex GetPointIds] SetId 9 9 + [aHex GetPointIds] SetId 10 10 + [aHex GetPointIds] SetId 11 11 + [aHex GetPointIds] SetId 12 12 + [aHex GetPointIds] SetId 13 13 + [aHex GetPointIds] SetId 14 14 + [aHex GetPointIds] SetId 15 15 + [aHex GetPointIds] SetId 16 16 + [aHex GetPointIds] SetId 17 17 + [aHex GetPointIds] SetId 18 18 + [aHex GetPointIds] SetId 19 19 +vtkUnstructuredGrid aHexGrid + aHexGrid Allocate 1 1 + aHexGrid InsertNextCell [aHex GetCellType] [aHex GetPointIds] + aHexGrid SetPoints hexPoints + [aHexGrid GetPointData] SetScalars hexScalars +vtkClipDataSet hexContours + hexContours SetInput aHexGrid + hexContours SetValue 0.5 +vtkDataSetMapper aHexContourMapper + aHexContourMapper SetInputConnection [hexContours GetOutputPort] + aHexContourMapper ScalarVisibilityOff +vtkDataSetMapper aHexMapper + aHexMapper SetInput aHexGrid + aHexMapper ScalarVisibilityOff +vtkActor aHexActor + aHexActor SetMapper aHexMapper + [aHexActor GetProperty] SetRepresentationToWireframe + [aHexActor GetProperty] SetAmbient 1.0 +vtkActor aHexContourActor + aHexContourActor SetMapper aHexContourMapper + [aHexContourActor GetProperty] SetAmbient 1.0 + +aHex GetEdge 110 +#aHex GetFace 11 + +# Quadratic wedge +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 15 + wedgePoints InsertPoint 0 0 0 0 + wedgePoints InsertPoint 1 1 0 0 + wedgePoints InsertPoint 2 0 1 0 + wedgePoints InsertPoint 3 0 0 1 + wedgePoints InsertPoint 4 1 0 1 + wedgePoints InsertPoint 5 0 1 1 + wedgePoints InsertPoint 6 0.5 0 0 + wedgePoints InsertPoint 7 0.5 0.5 0 + wedgePoints InsertPoint 8 0 0.5 0 + wedgePoints InsertPoint 9 0.5 0 1 + wedgePoints InsertPoint 10 0.5 0.5 1 + wedgePoints InsertPoint 11 0 0.5 1 + wedgePoints InsertPoint 12 0 0 0.5 + wedgePoints InsertPoint 13 1 0 0.5 + wedgePoints InsertPoint 14 0 1 0.5 +vtkFloatArray wedgeScalars + wedgeScalars SetNumberOfTuples 15 + wedgeScalars InsertValue 0 1.0 + wedgeScalars InsertValue 1 1.0 + wedgeScalars InsertValue 2 1.0 + wedgeScalars InsertValue 3 1.0 + wedgeScalars InsertValue 4 1.0 + wedgeScalars InsertValue 5 1.0 + wedgeScalars InsertValue 6 0.0 + wedgeScalars InsertValue 7 0.0 + wedgeScalars InsertValue 8 0.0 + wedgeScalars InsertValue 9 0.0 + wedgeScalars InsertValue 10 0.0 + wedgeScalars InsertValue 11 0.0 + wedgeScalars InsertValue 12 0.0 + wedgeScalars InsertValue 13 0.0 + wedgeScalars InsertValue 14 0.0 +vtkQuadraticWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + [aWedge GetPointIds] SetId 6 6 + [aWedge GetPointIds] SetId 7 7 + [aWedge GetPointIds] SetId 8 8 + [aWedge GetPointIds] SetId 9 9 + [aWedge GetPointIds] SetId 10 10 + [aWedge GetPointIds] SetId 11 11 + [aWedge GetPointIds] SetId 12 12 + [aWedge GetPointIds] SetId 13 13 + [aWedge GetPointIds] SetId 14 14 +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + [aWedgeGrid GetPointData] SetScalars wedgeScalars +vtkClipDataSet wedgeContours + wedgeContours SetInput aWedgeGrid + wedgeContours SetValue 0.5 +vtkDataSetMapper aWedgeContourMapper + aWedgeContourMapper SetInputConnection [wedgeContours GetOutputPort] + #aWedgeContourMapper ScalarVisibilityOff +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeGrid + #aWedgeMapper ScalarVisibilityOff +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + [aWedgeActor GetProperty] SetRepresentationToWireframe + [aWedgeActor GetProperty] SetAmbient 1.0 +vtkActor aWedgeContourActor + aWedgeContourActor SetMapper aWedgeContourMapper + [aWedgeContourActor GetProperty] SetAmbient 1.0 + +# Quadratic pyramid +vtkPoints pyraPoints + pyraPoints SetNumberOfPoints 13 + pyraPoints InsertPoint 0 0 0 0 + pyraPoints InsertPoint 1 1 0 0 + pyraPoints InsertPoint 2 1 1 0 + pyraPoints InsertPoint 3 0 1 0 + pyraPoints InsertPoint 4 0 0 1 + pyraPoints InsertPoint 5 0.5 0 0 + pyraPoints InsertPoint 6 1 0.5 0 + pyraPoints InsertPoint 7 0.5 1 0 + pyraPoints InsertPoint 8 0 0.5 0 + pyraPoints InsertPoint 9 0 0 0.5 + pyraPoints InsertPoint 10 0.5 0 0.5 + pyraPoints InsertPoint 11 0.5 0.5 0.5 + pyraPoints InsertPoint 12 0 0.5 0.5 +vtkFloatArray pyraScalars + pyraScalars SetNumberOfTuples 13 + pyraScalars InsertValue 0 1.0 + pyraScalars InsertValue 1 1.0 + pyraScalars InsertValue 2 1.0 + pyraScalars InsertValue 3 1.0 + pyraScalars InsertValue 4 1.0 + pyraScalars InsertValue 5 0.0 + pyraScalars InsertValue 6 0.0 + pyraScalars InsertValue 7 0.0 + pyraScalars InsertValue 8 0.0 + pyraScalars InsertValue 9 0.0 + pyraScalars InsertValue 10 0.0 + pyraScalars InsertValue 11 0.0 + pyraScalars InsertValue 12 0.0 +vtkQuadraticPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + [aPyramid GetPointIds] SetId 5 5 + [aPyramid GetPointIds] SetId 6 6 + [aPyramid GetPointIds] SetId 7 7 + [aPyramid GetPointIds] SetId 8 8 + [aPyramid GetPointIds] SetId 9 9 + [aPyramid GetPointIds] SetId 10 10 + [aPyramid GetPointIds] SetId 11 11 + [aPyramid GetPointIds] SetId 12 12 +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyraPoints + [aPyramidGrid GetPointData] SetScalars pyraScalars +vtkClipDataSet pyraContours + pyraContours SetInput aPyramidGrid + pyraContours SetValue 0.5 +vtkDataSetMapper aPyramidContourMapper + aPyramidContourMapper SetInputConnection [pyraContours GetOutputPort] + #aPyramidContourMapper ScalarVisibilityOff +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid + #aPyramidMapper ScalarVisibilityOff +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + [aPyramidActor GetProperty] SetRepresentationToWireframe + [aPyramidActor GetProperty] SetAmbient 1.0 +vtkActor aPyramidContourActor + aPyramidContourActor SetMapper aPyramidContourMapper + [aPyramidContourActor GetProperty] SetAmbient 1.0 + +# Create the rendering related stuff. +# Since some of our actors are a single vertex, we need to remove all +# cullers so the single vertex actors will render +vtkRenderer ren1 +[ren1 GetCullers] RemoveAllItems + +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground .1 .2 .3 +renWin SetSize 400 200 + +# specify properties +ren1 AddActor aEdgeActor +ren1 AddActor aEdgeContourActor + +ren1 AddActor aTriActor +ren1 AddActor aTriContourActor + +ren1 AddActor aQuadActor +ren1 AddActor aQuadContourActor + +ren1 AddActor aTetActor +ren1 AddActor aTetContourActor + +ren1 AddActor aHexActor +ren1 AddActor aHexContourActor + +ren1 AddActor aWedgeActor +ren1 AddActor aWedgeContourActor + +ren1 AddActor aPyramidActor +ren1 AddActor aPyramidContourActor + +# places everyone!! +aEdgeContourActor AddPosition 0 2 0 +aTriActor AddPosition 2 0 0 +aTriContourActor AddPosition 2 2 0 +aQuadActor AddPosition 4 0 0 +aQuadContourActor AddPosition 4 2 0 +aTetActor AddPosition 6 0 0 +aTetContourActor AddPosition 6 2 0 +aHexActor AddPosition 8 0 0 +aHexContourActor AddPosition 8 2 0 +aWedgeActor AddPosition 10 0 0 +aWedgeContourActor AddPosition 10 2 0 +aPyramidActor AddPosition 12 0 0 +aPyramidContourActor AddPosition 12 2 0 + +BuildBackdrop -1 15 -1 4 -1 2 .1 + +ren1 AddActor base +[base GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor left +[left GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor back +[back GetProperty] SetDiffuseColor .2 .2 .2 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 2.5 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/clipVolume.tcl b/Graphics/Testing/Tcl/clipVolume.tcl new file mode 100644 index 0000000..4cde94d --- /dev/null +++ b/Graphics/Testing/Tcl/clipVolume.tcl @@ -0,0 +1,57 @@ +package require vtk +package require vtkinteraction + +# Example demonstrates how to generate a 3D tetrahedra mesh from a volume +# + + +# Quadric definition +vtkQuadric quadric + quadric SetCoefficients .5 1 .2 0 .1 0 0 .2 0 0 + +vtkSampleFunction sample + sample SetSampleDimensions 20 20 20 + sample SetImplicitFunction quadric + sample ComputeNormalsOff + +# Generate tetrahedral mesh +vtkClipVolume clip + clip SetInputConnection [sample GetOutputPort] + clip SetValue 1.0 + clip GenerateClippedOutputOff + +vtkDataSetMapper clipMapper + clipMapper SetInputConnection [clip GetOutputPort] + clipMapper ScalarVisibilityOff + +vtkActor clipActor + clipActor SetMapper clipMapper + [clipActor GetProperty] SetColor .8 .4 .4 + +# Create outline +vtkOutlineFilter outline + outline SetInput [clip GetInput] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# Define graphics objects +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 1 1 1 +ren1 AddActor clipActor +ren1 AddActor outlineActor + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + + +wm withdraw . diff --git a/Graphics/Testing/Tcl/clipVolume2.tcl b/Graphics/Testing/Tcl/clipVolume2.tcl new file mode 100644 index 0000000..ae59817 --- /dev/null +++ b/Graphics/Testing/Tcl/clipVolume2.tcl @@ -0,0 +1,67 @@ +package require vtk +package require vtkinteraction + +# Example demonstrates how to generate a 3D tetrahedra mesh from a volume. This example +# differs from clipVolume.tcl in that the mesh is generated within a range of contour values. +# + +# Quadric definition +vtkQuadric quadric + quadric SetCoefficients .5 1 .2 0 .1 0 0 .2 0 0 + +vtkSampleFunction sample + sample SetSampleDimensions 20 20 20 + sample SetImplicitFunction quadric + sample ComputeNormalsOff + +# Program a bandpass filter to clip a range of data. What we do is transform the +# scalars so that values lying betweeen (minRange,maxRange) are >= 0.0; all +# others are < 0.0, +vtkImplicitDataSet dataset + dataset SetDataSet [sample GetOutput] +vtkImplicitWindowFunction window + window SetImplicitFunction dataset + window SetWindowRange 0.5 1.0 + +# Generate tetrahedral mesh +vtkClipVolume clip + clip SetInputConnection [sample GetOutputPort] + clip SetClipFunction window + clip SetValue 0.0 + clip GenerateClippedOutputOff + +vtkDataSetMapper clipMapper + clipMapper SetInputConnection [clip GetOutputPort] + clipMapper ScalarVisibilityOff + +vtkActor clipActor + clipActor SetMapper clipMapper + [clipActor GetProperty] SetColor .8 .4 .4 + +# Create outline +vtkOutlineFilter outline + outline SetInput [clip GetInput] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# Define graphics objects +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 1 1 1 +ren1 AddActor clipActor +ren1 AddActor outlineActor + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + + +wm withdraw . diff --git a/Graphics/Testing/Tcl/clipVolume3.tcl b/Graphics/Testing/Tcl/clipVolume3.tcl new file mode 100644 index 0000000..12d6b99 --- /dev/null +++ b/Graphics/Testing/Tcl/clipVolume3.tcl @@ -0,0 +1,75 @@ +package require vtk +package require vtkinteraction + +# Example demonstrates how to generate a 3D tetrahedra mesh from a +# volume. This example differs from the previous clipVolume.tcl examples +# in that it uses the slower ordered triangulator and generates clip scalars. + + +# Quadric definition +vtkQuadric quadric + quadric SetCoefficients .5 1 .2 0 .1 0 0 .2 0 0 + +vtkSampleFunction sample + sample SetSampleDimensions 20 20 20 + sample SetImplicitFunction quadric + sample ComputeNormalsOff + sample Update + +# Program a bandpass filter to clip a range of data. What we do is transform the +# scalars so that values lying betweeen (minRange,maxRange) are >= 0.0; all +# others are < 0.0, +vtkImplicitDataSet dataset + dataset SetDataSet [sample GetOutput] +vtkImplicitWindowFunction window + window SetImplicitFunction dataset + window SetWindowRange 0.5 1.0 + +# Generate tetrahedral mesh +vtkClipVolume clip + clip SetInputConnection [sample GetOutputPort] + clip SetClipFunction window + clip SetValue 0.0 + clip GenerateClippedOutputOff + clip Mixed3DCellGenerationOff + +vtkGeometryFilter gf +# gf SetInput [clip GetClippedOutput] + gf SetInputConnection [clip GetOutputPort] + +vtkPolyDataMapper clipMapper + clipMapper SetInputConnection [gf GetOutputPort] + clipMapper ScalarVisibilityOn + eval clipMapper SetScalarRange 0 2 + +vtkActor clipActor + clipActor SetMapper clipMapper + [clipActor GetProperty] SetColor .8 .4 .4 + +# Create outline +vtkOutlineFilter outline + outline SetInput [clip GetInput] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# Define graphics objects +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 1 1 1 +ren1 AddActor clipActor +ren1 AddActor outlineActor + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + + +wm withdraw . diff --git a/Graphics/Testing/Tcl/combStreamers.tcl b/Graphics/Testing/Tcl/combStreamers.tcl new file mode 100644 index 0000000..59740dc --- /dev/null +++ b/Graphics/Testing/Tcl/combStreamers.tcl @@ -0,0 +1,88 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +vtkPlaneSource ps + ps SetXResolution 4 + ps SetYResolution 4 + ps SetOrigin 2 -2 26 + ps SetPoint1 2 2 26 + ps SetPoint2 2 -2 32 +vtkPolyDataMapper psMapper + psMapper SetInputConnection [ps GetOutputPort] +vtkActor psActor + psActor SetMapper psMapper + [psActor GetProperty] SetRepresentationToWireframe + +vtkRungeKutta4 rk4 + +vtkStreamLine streamer + streamer SetInputConnection [pl3d GetOutputPort] + streamer SetSource [ps GetOutput] + streamer SetMaximumPropagationTime 100 + streamer SetIntegrationStepLength .2 + streamer SetStepLength .001 + streamer SetNumberOfThreads 1 + streamer SetIntegrationDirectionToForward + streamer VorticityOn + streamer SetIntegrator rk4 +vtkRibbonFilter rf + rf SetInputConnection [streamer GetOutputPort] + rf SetWidth 0.1 + rf SetWidthFactor 5 +vtkPolyDataMapper streamMapper + streamMapper SetInputConnection [rf GetOutputPort] + eval streamMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor streamline + streamline SetMapper streamMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor psActor +ren1 AddActor outlineActor +ren1 AddActor streamline + +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# for testing +set threshold 15 diff --git a/Graphics/Testing/Tcl/combStreamers2.tcl b/Graphics/Testing/Tcl/combStreamers2.tcl new file mode 100644 index 0000000..99b0b80 --- /dev/null +++ b/Graphics/Testing/Tcl/combStreamers2.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +vtkPlaneSource ps + ps SetXResolution 4 + ps SetYResolution 4 + ps SetOrigin 2 -2 26 + ps SetPoint1 2 2 26 + ps SetPoint2 2 -2 32 +vtkPolyDataMapper psMapper + psMapper SetInputConnection [ps GetOutputPort] +vtkActor psActor + psActor SetMapper psMapper + [psActor GetProperty] SetRepresentationToWireframe + +vtkDashedStreamLine streamer + streamer SetInputConnection [pl3d GetOutputPort] + streamer SetSource [ps GetOutput] + streamer SetMaximumPropagationTime 100 + streamer SetIntegrationStepLength .2 + streamer SetStepLength .001 + streamer SetNumberOfThreads 1 + streamer SetIntegrationDirectionToForward +vtkPolyDataMapper streamMapper + streamMapper SetInputConnection [streamer GetOutputPort] + eval streamMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor streamline + streamline SetMapper streamMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor psActor +ren1 AddActor outlineActor +ren1 AddActor streamline + +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/coneResolution.tcl b/Graphics/Testing/Tcl/coneResolution.tcl new file mode 100644 index 0000000..f8558fa --- /dev/null +++ b/Graphics/Testing/Tcl/coneResolution.tcl @@ -0,0 +1,69 @@ +package require vtk +package require vtkinteraction + +# create a rendering window and renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create cones of varying resolution +vtkConeSource cone0 + cone0 SetResolution 0 +vtkConeSource cone1 + cone1 SetResolution 1 +vtkConeSource cone2 + cone2 SetResolution 2 +vtkConeSource cone8 + cone8 SetResolution 8 + +vtkPolyDataMapper cone0Mapper + cone0Mapper SetInputConnection [cone0 GetOutputPort] +vtkActor cone0Actor + cone0Actor SetMapper cone0Mapper + +vtkPolyDataMapper cone1Mapper + cone1Mapper SetInputConnection [cone1 GetOutputPort] +vtkActor cone1Actor + cone1Actor SetMapper cone1Mapper + +vtkPolyDataMapper cone2Mapper + cone2Mapper SetInputConnection [cone2 GetOutputPort] +vtkActor cone2Actor + cone2Actor SetMapper cone2Mapper + +vtkPolyDataMapper cone8Mapper + cone8Mapper SetInputConnection [cone8 GetOutputPort] +vtkActor cone8Actor + cone8Actor SetMapper cone8Mapper + +# assign our actor to the renderer +ren1 AddActor cone0Actor +ren1 AddActor cone1Actor +ren1 AddActor cone2Actor +ren1 AddActor cone8Actor +ren1 SetBackground .5 .5 .5 +ren1 ResetCamera +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.3 +ren1 ResetCameraClippingRange + +renWin SetSize 301 91 +cone0Actor SetPosition -1.5 0 0 +cone1Actor SetPosition -.5 0 0 +cone2Actor SetPosition .5 0 0 +cone8Actor SetPosition 1.5 0 0 + +[cone0Actor GetProperty] SetDiffuseColor 1 0 0 +[cone1Actor GetProperty] SetDiffuseColor 0 1 0 +[cone8Actor GetProperty] BackfaceCullingOn +[cone8Actor GetProperty] SetDiffuseColor 0 0 1 + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/constrainedDelaunay.tcl b/Graphics/Testing/Tcl/constrainedDelaunay.tcl new file mode 100644 index 0000000..a27ff90 --- /dev/null +++ b/Graphics/Testing/Tcl/constrainedDelaunay.tcl @@ -0,0 +1,149 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create a constrained Delaunay triangulation (i.e., edges and polygons defined) + +# Generate the input points and constrained edges/polygons +# +vtkPoints points + points InsertPoint 0 1 4 0 + points InsertPoint 1 3 4 0 + points InsertPoint 2 7 4 0 + points InsertPoint 3 11 4 0 + points InsertPoint 4 13 4 0 + points InsertPoint 5 13 8 0 + points InsertPoint 6 13 12 0 + points InsertPoint 7 10 12 0 + points InsertPoint 8 7 12 0 + points InsertPoint 9 4 12 0 + points InsertPoint 10 1 12 0 + points InsertPoint 11 1 8 0 + points InsertPoint 12 3.5 5 0 + points InsertPoint 13 4.5 5 0 + points InsertPoint 14 5.5 8 0 + points InsertPoint 15 6.5 8 0 + points InsertPoint 16 6.5 5 0 + points InsertPoint 17 7.5 5 0 + points InsertPoint 18 7.5 8 0 + points InsertPoint 19 9 8 0 + points InsertPoint 20 9 5 0 + points InsertPoint 21 10 5 0 + points InsertPoint 22 10 7 0 + points InsertPoint 23 11 5 0 + points InsertPoint 24 12 5 0 + points InsertPoint 25 10.5 8 0 + points InsertPoint 26 12 11 0 + points InsertPoint 27 11 11 0 + points InsertPoint 28 10 9 0 + points InsertPoint 29 10 11 0 + points InsertPoint 30 9 11 0 + points InsertPoint 31 9 9 0 + points InsertPoint 32 7.5 9 0 + points InsertPoint 33 7.5 11 0 + points InsertPoint 34 6.5 11 0 + points InsertPoint 35 6.5 9 0 + points InsertPoint 36 5 9 0 + points InsertPoint 37 4 6 0 + points InsertPoint 38 3 9 0 + points InsertPoint 39 2 9 0 +vtkCellArray polys + polys InsertNextCell 12 + polys InsertCellPoint 0 + polys InsertCellPoint 1 + polys InsertCellPoint 2 + polys InsertCellPoint 3 + polys InsertCellPoint 4 + polys InsertCellPoint 5 + polys InsertCellPoint 6 + polys InsertCellPoint 7 + polys InsertCellPoint 8 + polys InsertCellPoint 9 + polys InsertCellPoint 10 + polys InsertCellPoint 11 + polys InsertNextCell 28 + polys InsertCellPoint 39 + polys InsertCellPoint 38 + polys InsertCellPoint 37 + polys InsertCellPoint 36 + polys InsertCellPoint 35 + polys InsertCellPoint 34 + polys InsertCellPoint 33 + polys InsertCellPoint 32 + polys InsertCellPoint 31 + polys InsertCellPoint 30 + polys InsertCellPoint 29 + polys InsertCellPoint 28 + polys InsertCellPoint 27 + polys InsertCellPoint 26 + polys InsertCellPoint 25 + polys InsertCellPoint 24 + polys InsertCellPoint 23 + polys InsertCellPoint 22 + polys InsertCellPoint 21 + polys InsertCellPoint 20 + polys InsertCellPoint 19 + polys InsertCellPoint 18 + polys InsertCellPoint 17 + polys InsertCellPoint 16 + polys InsertCellPoint 15 + polys InsertCellPoint 14 + polys InsertCellPoint 13 + polys InsertCellPoint 12 + +vtkPolyData polyData + polyData SetPoints points + polyData SetPolys polys + +# triangulate them +# +vtkDelaunay2D del1 + del1 SetInput polyData + del1 SetSource polyData +vtkPolyDataMapper mapMesh + mapMesh SetInputConnection [del1 GetOutputPort] +vtkActor meshActor + meshActor SetMapper mapMesh + +# tubes around mesh +vtkExtractEdges extract + extract SetInputConnection [del1 GetOutputPort] +vtkTubeFilter tubes + tubes SetInputConnection [extract GetOutputPort] + tubes SetRadius 0.1 + tubes SetNumberOfSides 6 +vtkPolyDataMapper mapEdges + mapEdges SetInputConnection [tubes GetOutputPort] +vtkActor edgeActor + edgeActor SetMapper mapEdges + eval [edgeActor GetProperty] SetColor $peacock + [edgeActor GetProperty] SetSpecularColor 1 1 1 + [edgeActor GetProperty] SetSpecular 0.3 + [edgeActor GetProperty] SetSpecularPower 20 + [edgeActor GetProperty] SetAmbient 0.2 + [edgeActor GetProperty] SetDiffuse 0.8 + +# Create graphics objects +# Create the rendering window, renderer, and interactive renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor meshActor +ren1 AddActor edgeActor +ren1 ResetCamera +ren1 SetBackground 0 0 0 +renWin SetSize 450 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +[ren1 GetActiveCamera] Zoom 2 +iren Initialize + + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/contour2DAll.tcl b/Graphics/Testing/Tcl/contour2DAll.tcl new file mode 100644 index 0000000..886cf1f --- /dev/null +++ b/Graphics/Testing/Tcl/contour2DAll.tcl @@ -0,0 +1,72 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkSLCReader slc + slc SetFileName "$VTK_DATA_ROOT/Data/nut.slc" + +set types "Char UnsignedChar Short UnsignedShort Int UnsignedInt Long UnsignedLong Float Double" +set i 3 +foreach vtkType $types { + vtkImageClip clip$vtkType + clip$vtkType SetInputConnection [slc GetOutputPort] + clip$vtkType SetOutputWholeExtent -1000 1000 -1000 1000 $i $i + incr i 2 + vtkImageCast castTo$vtkType + castTo$vtkType SetOutputScalarTypeTo$vtkType + castTo$vtkType SetInputConnection [clip$vtkType GetOutputPort] + castTo$vtkType ClampOverflowOn + + vtkContourFilter iso$vtkType + iso$vtkType SetInputConnection [castTo$vtkType GetOutputPort] + iso$vtkType GenerateValues 1 30 30 + + vtkPolyDataMapper iso${vtkType}Mapper + iso${vtkType}Mapper SetInputConnection [iso$vtkType GetOutputPort] + iso${vtkType}Mapper SetColorModeToMapScalars + + vtkActor iso${vtkType}Actor + iso${vtkType}Actor SetMapper iso${vtkType}Mapper + ren1 AddActor iso${vtkType}Actor +} + +vtkOutlineFilter outline + outline SetInputConnection [slc GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 ResetCamera +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Azimuth 20 +[ren1 GetActiveCamera] Zoom 1.5 +ren1 ResetCameraClippingRange + +ren1 SetBackground 0.9 .9 .9 +renWin SetSize 200 200 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/contour3DAll.tcl b/Graphics/Testing/Tcl/contour3DAll.tcl new file mode 100644 index 0000000..ce33abd --- /dev/null +++ b/Graphics/Testing/Tcl/contour3DAll.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkStructuredPointsReader slc + slc SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +set colors "$flesh $banana $grey $pink $carrot $gainsboro $tomato $gold $thistle $chocolate" +set types "UnsignedChar Char Short UnsignedShort Int UnsignedInt Long UnsignedLong Float Double" +set i 1 +set c 0 +foreach vtkType $types { + vtkImageClip clip$vtkType + clip$vtkType SetInputConnection [slc GetOutputPort] + clip$vtkType SetOutputWholeExtent -1000 1000 -1000 1000 $i [expr $i + 5] + incr i 5 + vtkImageCast castTo$vtkType + castTo$vtkType SetOutputScalarTypeTo$vtkType + castTo$vtkType SetInputConnection [clip$vtkType GetOutputPort] + castTo$vtkType ClampOverflowOn + + vtkContourFilter iso$vtkType + iso$vtkType SetInputConnection [castTo$vtkType GetOutputPort] + iso$vtkType GenerateValues 1 30 30 + iso$vtkType ComputeScalarsOff + iso$vtkType ComputeGradientsOff + + vtkPolyDataMapper iso${vtkType}Mapper + iso${vtkType}Mapper SetInputConnection [iso$vtkType GetOutputPort] + iso${vtkType}Mapper ImmediateModeRenderingOn + + vtkActor iso${vtkType}Actor + iso${vtkType}Actor SetMapper iso${vtkType}Mapper + [iso${vtkType}Actor GetProperty] SetDiffuseColor [lindex $colors $c] [lindex $colors [expr $c + 1]] [lindex $colors [expr $c + 2]] + [iso${vtkType}Actor GetProperty] SetSpecularPower 30 + [iso${vtkType}Actor GetProperty] SetDiffuse .7 + [iso${vtkType}Actor GetProperty] SetSpecular .5 + incr c 3 + ren1 AddActor iso${vtkType}Actor +} + +vtkOutlineFilter outline + outline SetInputConnection [slc GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 SetBackground 0.9 .9 .9 +ren1 ResetCamera +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Azimuth 20 +[ren1 GetActiveCamera] Zoom 1.5 +ren1 ResetCameraClippingRange + +renWin SetSize 400 400 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/contourCells.tcl b/Graphics/Testing/Tcl/contourCells.tcl new file mode 100644 index 0000000..8f99987 --- /dev/null +++ b/Graphics/Testing/Tcl/contourCells.tcl @@ -0,0 +1,979 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Contour every cell type + + +# Since some of our actors are a single vertex, we need to remove all +# cullers so the single vertex actors will render +vtkRenderer ren1 +[ren1 GetCullers] RemoveAllItems + +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a scene with one of each cell type +# Voxel + +vtkPoints voxelPoints + voxelPoints SetNumberOfPoints 8 + voxelPoints InsertPoint 0 0 0 0 + voxelPoints InsertPoint 1 1 0 0 + voxelPoints InsertPoint 2 0 1 0 + voxelPoints InsertPoint 3 1 1 0 + voxelPoints InsertPoint 4 0 0 1 + voxelPoints InsertPoint 5 1 0 1 + voxelPoints InsertPoint 6 0 1 1 + voxelPoints InsertPoint 7 1 1 1 + +vtkFloatArray voxelScalars + voxelScalars SetNumberOfTuples 8 + voxelScalars InsertValue 0 0 + voxelScalars InsertValue 1 1 + voxelScalars InsertValue 2 0 + voxelScalars InsertValue 3 0 + voxelScalars InsertValue 4 0 + voxelScalars InsertValue 5 0 + voxelScalars InsertValue 6 0 + voxelScalars InsertValue 7 0 + +vtkVoxel aVoxel + [aVoxel GetPointIds] SetId 0 0 + [aVoxel GetPointIds] SetId 1 1 + [aVoxel GetPointIds] SetId 2 2 + [aVoxel GetPointIds] SetId 3 3 + [aVoxel GetPointIds] SetId 4 4 + [aVoxel GetPointIds] SetId 5 5 + [aVoxel GetPointIds] SetId 6 6 + [aVoxel GetPointIds] SetId 7 7 + + +vtkUnstructuredGrid aVoxelGrid + aVoxelGrid Allocate 1 1 + aVoxelGrid InsertNextCell [aVoxel GetCellType] [aVoxel GetPointIds] + aVoxelGrid SetPoints voxelPoints + [aVoxelGrid GetPointData] SetScalars voxelScalars + +vtkContourFilter voxelContours + voxelContours SetInput aVoxelGrid + voxelContours SetValue 0 .5 + +vtkDataSetMapper aVoxelContourMapper + aVoxelContourMapper SetInputConnection [voxelContours GetOutputPort] + aVoxelContourMapper ScalarVisibilityOff + +vtkDataSetMapper aVoxelMapper + aVoxelMapper SetInput aVoxelGrid + aVoxelMapper ScalarVisibilityOff + +vtkActor aVoxelActor + aVoxelActor SetMapper aVoxelMapper + [aVoxelActor GetProperty] SetRepresentationToWireframe + +vtkActor aVoxelContourActor + aVoxelContourActor SetMapper aVoxelContourMapper + [aVoxelContourActor GetProperty] BackfaceCullingOn + +# Hexahedron + +vtkPoints hexahedronPoints + hexahedronPoints SetNumberOfPoints 8 + hexahedronPoints InsertPoint 0 0 0 0 + hexahedronPoints InsertPoint 1 1 0 0 + hexahedronPoints InsertPoint 2 1 1 0 + hexahedronPoints InsertPoint 3 0 1 0 + hexahedronPoints InsertPoint 4 0 0 1 + hexahedronPoints InsertPoint 5 1 0 1 + hexahedronPoints InsertPoint 6 1 1 1 + hexahedronPoints InsertPoint 7 0 1 1 + +vtkFloatArray hexahedronScalars + hexahedronScalars SetNumberOfTuples 8 + hexahedronScalars InsertValue 0 0 + hexahedronScalars InsertValue 1 1 + hexahedronScalars InsertValue 2 0 + hexahedronScalars InsertValue 3 0 + hexahedronScalars InsertValue 4 0 + hexahedronScalars InsertValue 5 0 + hexahedronScalars InsertValue 6 0 + hexahedronScalars InsertValue 7 0 + +vtkHexahedron aHexahedron + [aHexahedron GetPointIds] SetId 0 0 + [aHexahedron GetPointIds] SetId 1 1 + [aHexahedron GetPointIds] SetId 2 2 + [aHexahedron GetPointIds] SetId 3 3 + [aHexahedron GetPointIds] SetId 4 4 + [aHexahedron GetPointIds] SetId 5 5 + [aHexahedron GetPointIds] SetId 6 6 + [aHexahedron GetPointIds] SetId 7 7 + + +vtkUnstructuredGrid aHexahedronGrid + aHexahedronGrid Allocate 1 1 + aHexahedronGrid InsertNextCell [aHexahedron GetCellType] [aHexahedron GetPointIds] + aHexahedronGrid SetPoints hexahedronPoints + [aHexahedronGrid GetPointData] SetScalars hexahedronScalars + +vtkContourFilter hexahedronContours + hexahedronContours SetInput aHexahedronGrid + hexahedronContours SetValue 0 .5 + +vtkDataSetMapper aHexahedronContourMapper + aHexahedronContourMapper SetInputConnection [hexahedronContours GetOutputPort] + aHexahedronContourMapper ScalarVisibilityOff + +vtkDataSetMapper aHexahedronMapper + aHexahedronMapper SetInput aHexahedronGrid + aHexahedronMapper ScalarVisibilityOff + +vtkActor aHexahedronActor + aHexahedronActor SetMapper aHexahedronMapper + [aHexahedronActor GetProperty] BackfaceCullingOn + [aHexahedronActor GetProperty] SetRepresentationToWireframe + +vtkActor aHexahedronContourActor + aHexahedronContourActor SetMapper aHexahedronContourMapper + [aHexahedronContourActor GetProperty] BackfaceCullingOn + +# Tetra + +vtkPoints tetraPoints + tetraPoints SetNumberOfPoints 4 + tetraPoints InsertPoint 0 0 0 0 + tetraPoints InsertPoint 1 1 0 0 + tetraPoints InsertPoint 2 .5 1 0 + tetraPoints InsertPoint 3 .5 .5 1 + +vtkFloatArray tetraScalars + tetraScalars SetNumberOfTuples 4 + tetraScalars InsertValue 0 1 + tetraScalars InsertValue 1 0 + tetraScalars InsertValue 2 0 + tetraScalars InsertValue 3 0 + +vtkTetra aTetra + [aTetra GetPointIds] SetId 0 0 + [aTetra GetPointIds] SetId 1 1 + [aTetra GetPointIds] SetId 2 2 + [aTetra GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aTetraGrid + aTetraGrid Allocate 1 1 + aTetraGrid InsertNextCell [aTetra GetCellType] [aTetra GetPointIds] + aTetraGrid SetPoints tetraPoints + [aTetraGrid GetPointData] SetScalars tetraScalars + +vtkContourFilter tetraContours + tetraContours SetInput aTetraGrid + tetraContours SetValue 0 .5 + +vtkDataSetMapper aTetraContourMapper + aTetraContourMapper SetInputConnection [tetraContours GetOutputPort] + aTetraContourMapper ScalarVisibilityOff + +vtkDataSetMapper aTetraMapper + aTetraMapper SetInput aTetraGrid + aTetraMapper ScalarVisibilityOff + +vtkActor aTetraContourActor + aTetraContourActor SetMapper aTetraContourMapper + +vtkActor aTetraActor + aTetraActor SetMapper aTetraMapper + [aTetraActor GetProperty] SetRepresentationToWireframe + +# Wedge + +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 6 + wedgePoints InsertPoint 0 0 1 0 + wedgePoints InsertPoint 1 0 0 0 + wedgePoints InsertPoint 2 0 .5 .5 + wedgePoints InsertPoint 3 1 1 0 + wedgePoints InsertPoint 4 1 0 0 + wedgePoints InsertPoint 5 1 .5 .5 + +vtkFloatArray wedgeScalars + wedgeScalars SetNumberOfTuples 6 + wedgeScalars InsertValue 0 1 + wedgeScalars InsertValue 1 1 + wedgeScalars InsertValue 2 0 + wedgeScalars InsertValue 3 1 + wedgeScalars InsertValue 4 1 + wedgeScalars InsertValue 5 0 + +vtkWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + + +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + [aWedgeGrid GetPointData] SetScalars wedgeScalars + +vtkContourFilter wedgeContours + wedgeContours SetInput aWedgeGrid + wedgeContours SetValue 0 .5 + +vtkDataSetMapper aWedgeContourMapper + aWedgeContourMapper SetInputConnection [wedgeContours GetOutputPort] + aWedgeContourMapper ScalarVisibilityOff + +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeGrid + aWedgeMapper ScalarVisibilityOff + +vtkActor aWedgeContourActor + aWedgeContourActor SetMapper aWedgeContourMapper + +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + [aWedgeActor GetProperty] SetRepresentationToWireframe + +# Pyramid + +vtkPoints pyramidPoints + pyramidPoints SetNumberOfPoints 5 + pyramidPoints InsertPoint 0 0 0 0 + pyramidPoints InsertPoint 1 1 0 0 + pyramidPoints InsertPoint 2 1 1 0 + pyramidPoints InsertPoint 3 0 1 0 + pyramidPoints InsertPoint 4 .5 .5 1 + +vtkFloatArray pyramidScalars + pyramidScalars SetNumberOfTuples 5 + pyramidScalars InsertValue 0 1 + pyramidScalars InsertValue 1 1 + pyramidScalars InsertValue 2 1 + pyramidScalars InsertValue 3 1 + pyramidScalars InsertValue 4 0 + +vtkPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + + +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyramidPoints + [aPyramidGrid GetPointData] SetScalars pyramidScalars + +vtkContourFilter pyramidContours + pyramidContours SetInput aPyramidGrid + pyramidContours SetValue 0 .5 + +vtkDataSetMapper aPyramidContourMapper + aPyramidContourMapper SetInputConnection [pyramidContours GetOutputPort] + aPyramidContourMapper ScalarVisibilityOff + +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid + aPyramidMapper ScalarVisibilityOff + +vtkActor aPyramidContourActor + aPyramidContourActor SetMapper aPyramidContourMapper + +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + [aPyramidActor GetProperty] SetRepresentationToWireframe + +# Pixel + +vtkPoints pixelPoints + pixelPoints SetNumberOfPoints 4 + pixelPoints InsertPoint 0 0 0 0 + pixelPoints InsertPoint 1 1 0 0 + pixelPoints InsertPoint 2 0 1 0 + pixelPoints InsertPoint 3 1 1 0 + +vtkFloatArray pixelScalars + pixelScalars SetNumberOfTuples 4 + pixelScalars InsertValue 0 1 + pixelScalars InsertValue 1 0 + pixelScalars InsertValue 2 0 + pixelScalars InsertValue 3 0 + +vtkPixel aPixel + [aPixel GetPointIds] SetId 0 0 + [aPixel GetPointIds] SetId 1 1 + [aPixel GetPointIds] SetId 2 2 + [aPixel GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aPixelGrid + aPixelGrid Allocate 1 1 + aPixelGrid InsertNextCell [aPixel GetCellType] [aPixel GetPointIds] + aPixelGrid SetPoints pixelPoints + [aPixelGrid GetPointData] SetScalars pixelScalars + +vtkContourFilter pixelContours + pixelContours SetInput aPixelGrid + pixelContours SetValue 0 .5 + +vtkDataSetMapper aPixelContourMapper + aPixelContourMapper SetInputConnection [pixelContours GetOutputPort] + aPixelContourMapper ScalarVisibilityOff + +vtkDataSetMapper aPixelMapper + aPixelMapper SetInput aPixelGrid + aPixelMapper ScalarVisibilityOff + +vtkActor aPixelContourActor + aPixelContourActor SetMapper aPixelContourMapper + +vtkActor aPixelActor + aPixelActor SetMapper aPixelMapper + [aPixelActor GetProperty] BackfaceCullingOn + [aPixelActor GetProperty] SetRepresentationToWireframe + +# Quad + +vtkPoints quadPoints + quadPoints SetNumberOfPoints 4 + quadPoints InsertPoint 0 0 0 0 + quadPoints InsertPoint 1 1 0 0 + quadPoints InsertPoint 2 1 1 0 + quadPoints InsertPoint 3 0 1 0 + +vtkFloatArray quadScalars + quadScalars SetNumberOfTuples 4 + quadScalars InsertValue 0 1 + quadScalars InsertValue 1 0 + quadScalars InsertValue 2 0 + quadScalars InsertValue 3 0 + +vtkQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + [aQuadGrid GetPointData] SetScalars quadScalars + +vtkContourFilter quadContours + quadContours SetInput aQuadGrid + quadContours SetValue 0 .5 + +vtkDataSetMapper aQuadContourMapper + aQuadContourMapper SetInputConnection [quadContours GetOutputPort] + aQuadContourMapper ScalarVisibilityOff + +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid + aQuadMapper ScalarVisibilityOff + +vtkActor aQuadContourActor + aQuadContourActor SetMapper aQuadContourMapper + +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + [aQuadActor GetProperty] BackfaceCullingOn + [aQuadActor GetProperty] SetRepresentationToWireframe + +# Triangle + +vtkPoints trianglePoints + trianglePoints SetNumberOfPoints 3 + trianglePoints InsertPoint 0 0 0 0 + trianglePoints InsertPoint 1 1 0 0 + trianglePoints InsertPoint 2 .5 .5 0 + +vtkFloatArray triangleScalars + triangleScalars SetNumberOfTuples 3 + triangleScalars InsertValue 0 1 + triangleScalars InsertValue 1 0 + triangleScalars InsertValue 2 0 + +vtkTriangle aTriangle + [aTriangle GetPointIds] SetId 0 0 + [aTriangle GetPointIds] SetId 1 1 + [aTriangle GetPointIds] SetId 2 2 + +vtkUnstructuredGrid aTriangleGrid + aTriangleGrid Allocate 1 1 + aTriangleGrid InsertNextCell [aTriangle GetCellType] [aTriangle GetPointIds] + aTriangleGrid SetPoints trianglePoints + [aTriangleGrid GetPointData] SetScalars triangleScalars + +vtkContourFilter triangleContours + triangleContours SetInput aTriangleGrid + triangleContours SetValue 0 .5 + +vtkDataSetMapper aTriangleContourMapper + aTriangleContourMapper SetInputConnection [triangleContours GetOutputPort] + aTriangleContourMapper ScalarVisibilityOff + +vtkActor aTriangleContourActor + aTriangleContourActor SetMapper aTriangleContourMapper + +vtkDataSetMapper aTriangleMapper + aTriangleMapper SetInput aTriangleGrid + aTriangleMapper ScalarVisibilityOff + +vtkActor aTriangleActor + aTriangleActor SetMapper aTriangleMapper + [aTriangleActor GetProperty] BackfaceCullingOn + [aTriangleActor GetProperty] SetRepresentationToWireframe + +# Polygon + +vtkPoints polygonPoints + polygonPoints SetNumberOfPoints 4 + polygonPoints InsertPoint 0 0 0 0 + polygonPoints InsertPoint 1 1 0 0 + polygonPoints InsertPoint 2 1 1 0 + polygonPoints InsertPoint 3 0 1 0 + +vtkFloatArray polygonScalars + polygonScalars SetNumberOfTuples 4 + polygonScalars InsertValue 0 1 + polygonScalars InsertValue 1 0 + polygonScalars InsertValue 2 0 + polygonScalars InsertValue 3 0 + +vtkPolygon aPolygon + [aPolygon GetPointIds] SetNumberOfIds 4 + [aPolygon GetPointIds] SetId 0 0 + [aPolygon GetPointIds] SetId 1 1 + [aPolygon GetPointIds] SetId 2 2 + [aPolygon GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aPolygonGrid + aPolygonGrid Allocate 1 1 + aPolygonGrid InsertNextCell [aPolygon GetCellType] [aPolygon GetPointIds] + aPolygonGrid SetPoints polygonPoints + [aPolygonGrid GetPointData] SetScalars polygonScalars + +vtkContourFilter polygonContours + polygonContours SetInput aPolygonGrid + polygonContours SetValue 0 .5 + +vtkDataSetMapper aPolygonContourMapper + aPolygonContourMapper SetInputConnection [polygonContours GetOutputPort] + aPolygonContourMapper ScalarVisibilityOff + +vtkDataSetMapper aPolygonMapper + aPolygonMapper SetInput aPolygonGrid + aPolygonMapper ScalarVisibilityOff + +vtkActor aPolygonContourActor + aPolygonContourActor SetMapper aPolygonContourMapper + +vtkActor aPolygonActor + aPolygonActor SetMapper aPolygonMapper + [aPolygonActor GetProperty] BackfaceCullingOn + [aPolygonActor GetProperty] SetRepresentationToWireframe + +# Triangle strip + +vtkPoints triangleStripPoints + triangleStripPoints SetNumberOfPoints 5 + triangleStripPoints InsertPoint 0 0 1 0 + triangleStripPoints InsertPoint 1 0 0 0 + triangleStripPoints InsertPoint 2 1 1 0 + triangleStripPoints InsertPoint 3 1 0 0 + triangleStripPoints InsertPoint 4 2 1 0 + +vtkFloatArray triangleStripScalars + triangleStripScalars SetNumberOfTuples 5 + triangleStripScalars InsertValue 0 1 + triangleStripScalars InsertValue 1 0 + triangleStripScalars InsertValue 2 0 + triangleStripScalars InsertValue 3 0 + triangleStripScalars InsertValue 4 0 + +vtkTriangleStrip aTriangleStrip + [aTriangleStrip GetPointIds] SetNumberOfIds 5 + [aTriangleStrip GetPointIds] SetId 0 0 + [aTriangleStrip GetPointIds] SetId 1 1 + [aTriangleStrip GetPointIds] SetId 2 2 + [aTriangleStrip GetPointIds] SetId 3 3 + [aTriangleStrip GetPointIds] SetId 4 4 + +vtkUnstructuredGrid aTriangleStripGrid + aTriangleStripGrid Allocate 1 1 + aTriangleStripGrid InsertNextCell [aTriangleStrip GetCellType] [aTriangleStrip GetPointIds] + aTriangleStripGrid SetPoints triangleStripPoints + [aTriangleStripGrid GetPointData] SetScalars triangleStripScalars + +vtkDataSetMapper aTriangleStripMapper + aTriangleStripMapper SetInput aTriangleStripGrid + aTriangleStripMapper ScalarVisibilityOff + +vtkContourFilter triangleStripContours + triangleStripContours SetInput aTriangleStripGrid + triangleStripContours SetValue 0 .5 + +vtkDataSetMapper aTriangleStripContourMapper + aTriangleStripContourMapper SetInputConnection [triangleStripContours GetOutputPort] + aTriangleStripContourMapper ScalarVisibilityOff + +vtkActor aTriangleStripContourActor + aTriangleStripContourActor SetMapper aTriangleStripContourMapper + +vtkActor aTriangleStripActor + aTriangleStripActor SetMapper aTriangleStripMapper + [aTriangleStripActor GetProperty] BackfaceCullingOn + [aTriangleStripActor GetProperty] SetRepresentationToWireframe + +# Line + +vtkPoints linePoints + linePoints SetNumberOfPoints 2 + linePoints InsertPoint 0 0 0 0 + linePoints InsertPoint 1 1 1 0 + +vtkFloatArray lineScalars + lineScalars SetNumberOfTuples 2 + lineScalars InsertValue 0 1 + lineScalars InsertValue 1 0 + +vtkLine aLine + [aLine GetPointIds] SetId 0 0 + [aLine GetPointIds] SetId 1 1 + +vtkUnstructuredGrid aLineGrid + aLineGrid Allocate 1 1 + aLineGrid InsertNextCell [aLine GetCellType] [aLine GetPointIds] + aLineGrid SetPoints linePoints + [aLineGrid GetPointData] SetScalars lineScalars + +vtkContourFilter lineContours + lineContours SetInput aLineGrid + lineContours SetValue 0 .5 + +vtkDataSetMapper aLineContourMapper + aLineContourMapper SetInputConnection [lineContours GetOutputPort] + aLineContourMapper ScalarVisibilityOff + +vtkActor aLineContourActor + aLineContourActor SetMapper aLineContourMapper + +vtkDataSetMapper aLineMapper + aLineMapper SetInput aLineGrid + aLineMapper ScalarVisibilityOff + +vtkActor aLineActor + aLineActor SetMapper aLineMapper + [aLineActor GetProperty] BackfaceCullingOn + [aLineActor GetProperty] SetRepresentationToWireframe + +# Polyline + +vtkPoints polyLinePoints + polyLinePoints SetNumberOfPoints 3 + polyLinePoints InsertPoint 0 0 0 0 + polyLinePoints InsertPoint 1 1 1 0 + polyLinePoints InsertPoint 2 1 0 0 + +vtkFloatArray polyLineScalars + polyLineScalars SetNumberOfTuples 3 + polyLineScalars InsertValue 0 1 + polyLineScalars InsertValue 1 0 + polyLineScalars InsertValue 2 0 + +vtkPolyLine aPolyLine + [aPolyLine GetPointIds] SetNumberOfIds 3 + [aPolyLine GetPointIds] SetId 0 0 + [aPolyLine GetPointIds] SetId 1 1 + [aPolyLine GetPointIds] SetId 2 2 + +vtkUnstructuredGrid aPolyLineGrid + aPolyLineGrid Allocate 1 1 + aPolyLineGrid InsertNextCell [aPolyLine GetCellType] [aPolyLine GetPointIds] + aPolyLineGrid SetPoints polyLinePoints + [aPolyLineGrid GetPointData] SetScalars polyLineScalars + +vtkContourFilter polyLineContours + polyLineContours SetInput aPolyLineGrid + polyLineContours SetValue 0 .5 + +vtkDataSetMapper aPolyLineContourMapper + aPolyLineContourMapper SetInputConnection [polyLineContours GetOutputPort] + aPolyLineContourMapper ScalarVisibilityOff + +vtkActor aPolyLineContourActor + aPolyLineContourActor SetMapper aPolyLineContourMapper + +vtkDataSetMapper aPolyLineMapper + aPolyLineMapper SetInput aPolyLineGrid + aPolyLineMapper ScalarVisibilityOff + +vtkActor aPolyLineActor + aPolyLineActor SetMapper aPolyLineMapper + [aPolyLineActor GetProperty] BackfaceCullingOn + [aPolyLineActor GetProperty] SetRepresentationToWireframe + +# Vertex + +vtkPoints vertexPoints + vertexPoints SetNumberOfPoints 1 + vertexPoints InsertPoint 0 0 0 0 + +vtkFloatArray vertexScalars + vertexScalars SetNumberOfTuples 1 + vertexScalars InsertValue 0 1 + +vtkVertex aVertex + [aVertex GetPointIds] SetId 0 0 + +vtkUnstructuredGrid aVertexGrid + aVertexGrid Allocate 1 1 + aVertexGrid InsertNextCell [aVertex GetCellType] [aVertex GetPointIds] + aVertexGrid SetPoints vertexPoints + [aVertexGrid GetPointData] SetScalars vertexScalars + +vtkContourFilter vertexContours + vertexContours SetInput aVertexGrid + vertexContours SetValue 0 1 + +vtkDataSetMapper aVertexContourMapper + aVertexContourMapper SetInputConnection [vertexContours GetOutputPort] + aVertexContourMapper ScalarVisibilityOff + +vtkActor aVertexContourActor + aVertexContourActor SetMapper aVertexContourMapper + [aVertexContourActor GetProperty] SetRepresentationToWireframe + +vtkDataSetMapper aVertexMapper + aVertexMapper SetInput aVertexGrid + aVertexMapper ScalarVisibilityOff + +vtkActor aVertexActor + aVertexActor SetMapper aVertexMapper + [aVertexActor GetProperty] BackfaceCullingOn + +# Poly Vertex + +vtkPoints polyVertexPoints + polyVertexPoints SetNumberOfPoints 3 + polyVertexPoints InsertPoint 0 0 0 0 + polyVertexPoints InsertPoint 1 1 0 0 + polyVertexPoints InsertPoint 2 1 1 0 + +vtkFloatArray polyVertexScalars + polyVertexScalars SetNumberOfTuples 3 + polyVertexScalars InsertValue 0 1 + polyVertexScalars InsertValue 1 0 + polyVertexScalars InsertValue 2 0 + +vtkPolyVertex aPolyVertex + [aPolyVertex GetPointIds] SetNumberOfIds 3 + [aPolyVertex GetPointIds] SetId 0 0 + [aPolyVertex GetPointIds] SetId 1 1 + [aPolyVertex GetPointIds] SetId 2 2 + +vtkUnstructuredGrid aPolyVertexGrid + aPolyVertexGrid Allocate 1 1 + aPolyVertexGrid InsertNextCell [aPolyVertex GetCellType] [aPolyVertex GetPointIds] + aPolyVertexGrid SetPoints polyVertexPoints + [aPolyVertexGrid GetPointData] SetScalars polyVertexScalars + +vtkContourFilter polyVertexContours + polyVertexContours SetInput aPolyVertexGrid + polyVertexContours SetValue 0 0 + +vtkDataSetMapper aPolyVertexContourMapper + aPolyVertexContourMapper SetInputConnection [polyVertexContours GetOutputPort] + aPolyVertexContourMapper ScalarVisibilityOff + +vtkActor aPolyVertexContourActor + aPolyVertexContourActor SetMapper aPolyVertexContourMapper + [aPolyVertexContourActor GetProperty] SetRepresentationToWireframe + +vtkDataSetMapper aPolyVertexMapper + aPolyVertexMapper SetInput aPolyVertexGrid + aPolyVertexMapper ScalarVisibilityOff + +vtkActor aPolyVertexActor + aPolyVertexActor SetMapper aPolyVertexMapper + +# Pentagonal prism + +vtkPoints pentaPoints + pentaPoints SetNumberOfPoints 10 + pentaPoints InsertPoint 0 0.25 0.0 0.0 + pentaPoints InsertPoint 1 0.75 0.0 0.0 + pentaPoints InsertPoint 2 1.0 0.5 0.0 + pentaPoints InsertPoint 3 0.5 1.0 0.0 + pentaPoints InsertPoint 4 0.0 0.5 0.0 + pentaPoints InsertPoint 5 0.25 0.0 1.0 + pentaPoints InsertPoint 6 0.75 0.0 1.0 + pentaPoints InsertPoint 7 1.0 0.5 1.0 + pentaPoints InsertPoint 8 0.5 1.0 1.0 + pentaPoints InsertPoint 9 0.0 0.5 1.0 + +vtkFloatArray pentaScalars + pentaScalars SetNumberOfTuples 10 + pentaScalars InsertValue 0 0 + pentaScalars InsertValue 1 0 + pentaScalars InsertValue 2 0 + pentaScalars InsertValue 3 0 + pentaScalars InsertValue 4 0 + pentaScalars InsertValue 5 1 + pentaScalars InsertValue 6 1 + pentaScalars InsertValue 7 1 + pentaScalars InsertValue 8 1 + pentaScalars InsertValue 9 1 + +vtkPentagonalPrism aPenta + [aPenta GetPointIds] SetId 0 0 + [aPenta GetPointIds] SetId 1 1 + [aPenta GetPointIds] SetId 2 2 + [aPenta GetPointIds] SetId 3 3 + [aPenta GetPointIds] SetId 4 4 + [aPenta GetPointIds] SetId 5 5 + [aPenta GetPointIds] SetId 6 6 + [aPenta GetPointIds] SetId 7 7 + [aPenta GetPointIds] SetId 8 8 + [aPenta GetPointIds] SetId 9 9 + + +vtkUnstructuredGrid aPentaGrid + aPentaGrid Allocate 1 1 + aPentaGrid InsertNextCell [aPenta GetCellType] [aPenta GetPointIds] + aPentaGrid SetPoints pentaPoints + [aPentaGrid GetPointData] SetScalars pentaScalars + +vtkContourFilter pentaContours + pentaContours SetInput aPentaGrid + pentaContours SetValue 0 .5 + +vtkDataSetMapper aPentaContourMapper + aPentaContourMapper SetInputConnection [pentaContours GetOutputPort] + aPentaContourMapper ScalarVisibilityOff + +vtkDataSetMapper aPentaMapper + aPentaMapper SetInput aPentaGrid + aPentaMapper ScalarVisibilityOff + +vtkActor aPentaActor + aPentaActor SetMapper aPentaMapper + [aPentaActor GetProperty] BackfaceCullingOn + [aPentaActor GetProperty] SetRepresentationToWireframe + +vtkActor aPentaContourActor + aPentaContourActor SetMapper aPentaContourMapper + [aPentaContourActor GetProperty] BackfaceCullingOn + + +# Hexagonal prism + +vtkPoints hexaPoints + hexaPoints SetNumberOfPoints 12 + hexaPoints InsertPoint 0 0.0 0.0 0.0 + hexaPoints InsertPoint 1 0.5 0.0 0.0 + hexaPoints InsertPoint 2 1.0 0.5 0.0 + hexaPoints InsertPoint 3 1.0 1.0 0.0 + hexaPoints InsertPoint 4 0.5 1.0 0.0 + hexaPoints InsertPoint 5 0.0 0.5 0.0 + hexaPoints InsertPoint 6 0.0 0.0 1.0 + hexaPoints InsertPoint 7 0.5 0.0 1.0 + hexaPoints InsertPoint 8 1.0 0.5 1.0 + hexaPoints InsertPoint 9 1.0 1.0 1.0 + hexaPoints InsertPoint 10 0.5 1.0 1.0 + hexaPoints InsertPoint 11 0.0 0.5 1.0 + +vtkFloatArray hexaScalars + hexaScalars SetNumberOfTuples 12 + hexaScalars InsertValue 0 0 + hexaScalars InsertValue 1 0 + hexaScalars InsertValue 2 0 + hexaScalars InsertValue 3 0 + hexaScalars InsertValue 4 0 + hexaScalars InsertValue 5 0 + hexaScalars InsertValue 6 1 + hexaScalars InsertValue 7 1 + hexaScalars InsertValue 8 1 + hexaScalars InsertValue 9 1 + hexaScalars InsertValue 10 1 + hexaScalars InsertValue 11 1 + +vtkHexagonalPrism aHexa + [aHexa GetPointIds] SetId 0 0 + [aHexa GetPointIds] SetId 1 1 + [aHexa GetPointIds] SetId 2 2 + [aHexa GetPointIds] SetId 3 3 + [aHexa GetPointIds] SetId 4 4 + [aHexa GetPointIds] SetId 5 5 + [aHexa GetPointIds] SetId 6 6 + [aHexa GetPointIds] SetId 7 7 + [aHexa GetPointIds] SetId 8 8 + [aHexa GetPointIds] SetId 9 9 + [aHexa GetPointIds] SetId 10 10 + [aHexa GetPointIds] SetId 11 11 + + +vtkUnstructuredGrid aHexaGrid + aHexaGrid Allocate 1 1 + aHexaGrid InsertNextCell [aHexa GetCellType] [aHexa GetPointIds] + aHexaGrid SetPoints hexaPoints + [aHexaGrid GetPointData] SetScalars hexaScalars + +vtkContourFilter hexaContours + hexaContours SetInput aHexaGrid + hexaContours SetValue 0 .5 + +vtkDataSetMapper aHexaContourMapper + aHexaContourMapper SetInputConnection [hexaContours GetOutputPort] + aHexaContourMapper ScalarVisibilityOff + +vtkDataSetMapper aHexaMapper + aHexaMapper SetInput aHexaGrid + aHexaMapper ScalarVisibilityOff + +vtkActor aHexaActor + aHexaActor SetMapper aHexaMapper + [aHexaActor GetProperty] BackfaceCullingOn + [aHexaActor GetProperty] SetRepresentationToWireframe + +vtkActor aHexaContourActor + aHexaContourActor SetMapper aHexaContourMapper + [aHexaContourActor GetProperty] BackfaceCullingOn + + + +ren1 SetBackground .1 .2 .3 +renWin SetSize 400 400 + +ren1 AddActor aVoxelActor; [aVoxelActor GetProperty] SetDiffuseColor 1 0 0 +ren1 AddActor aVoxelContourActor; [aVoxelContourActor GetProperty] SetDiffuseColor 1 0 0 + +ren1 AddActor aHexahedronActor; [aHexahedronActor GetProperty] SetDiffuseColor 1 1 0 +ren1 AddActor aHexahedronContourActor; [aHexahedronContourActor GetProperty] SetDiffuseColor 1 1 0 + +ren1 AddActor aTetraActor; [aTetraActor GetProperty] SetDiffuseColor 0 1 0 +ren1 AddActor aTetraContourActor; [aTetraContourActor GetProperty] SetDiffuseColor 0 1 0 + +ren1 AddActor aWedgeActor; [aWedgeActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aWedgeContourActor; [aWedgeContourActor GetProperty] SetDiffuseColor 0 1 1 + +ren1 AddActor aPyramidActor; [aPyramidActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aPyramidContourActor; [aPyramidContourActor GetProperty] SetDiffuseColor 1 0 1 + +ren1 AddActor aPixelActor; [aPixelActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aPixelContourActor; [aPixelContourActor GetProperty] SetDiffuseColor 0 1 1 + +ren1 AddActor aQuadActor; [aQuadActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aQuadContourActor; [aQuadContourActor GetProperty] SetDiffuseColor 1 0 1 + +ren1 AddActor aTriangleActor; [aTriangleActor GetProperty] SetDiffuseColor .3 1 .5 +ren1 AddActor aTriangleContourActor; [aTriangleContourActor GetProperty] SetDiffuseColor .3 1 .5 + +ren1 AddActor aPolygonActor; [aPolygonActor GetProperty] SetDiffuseColor 1 .4 .5 +ren1 AddActor aPolygonContourActor; [aPolygonContourActor GetProperty] SetDiffuseColor 1 .4 .5 + +ren1 AddActor aTriangleStripActor; [aTriangleStripActor GetProperty] SetDiffuseColor .3 .7 1 +ren1 AddActor aTriangleStripContourActor; [aTriangleStripContourActor GetProperty] SetDiffuseColor .3 .7 1 + +ren1 AddActor aLineActor; [aLineActor GetProperty] SetDiffuseColor .2 1 1 +ren1 AddActor aLineContourActor; [aLineContourActor GetProperty] SetDiffuseColor .2 1 1 + +ren1 AddActor aPolyLineActor; [aPolyLineActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPolyLineContourActor; [aPolyLineContourActor GetProperty] SetDiffuseColor 1 1 1 + +ren1 AddActor aVertexActor; [aVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aVertexContourActor; [aVertexContourActor GetProperty] SetDiffuseColor 1 1 1 + +ren1 AddActor aPolyVertexActor; [aPolyVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPolyVertexContourActor; [aPolyVertexContourActor GetProperty] SetDiffuseColor 1 1 1 + +ren1 AddActor aPentaActor; [aPentaActor GetProperty] SetDiffuseColor .2 .4 .7 +ren1 AddActor aPentaContourActor; [aPentaContourActor GetProperty] SetDiffuseColor .2 .4 .7 + +ren1 AddActor aHexaActor; [aHexaActor GetProperty] SetDiffuseColor .7 .5 1 +ren1 AddActor aHexaContourActor; [aHexaContourActor GetProperty] SetDiffuseColor .7 .5 1 + +# places everyone!! +aVoxelContourActor AddPosition 0 0 0 +aVoxelContourActor AddPosition 0 2 0 +aHexahedronContourActor AddPosition 2 0 0 +aHexahedronContourActor AddPosition 0 2 0 +aHexahedronActor AddPosition 2 0 0 +aTetraContourActor AddPosition 4 0 0 +aTetraContourActor AddPosition 0 2 0 +aTetraActor AddPosition 4 0 0 +aWedgeContourActor AddPosition 6 0 0 +aWedgeContourActor AddPosition 0 2 0 +aWedgeActor AddPosition 6 0 0 +aPyramidContourActor AddPosition 8 0 0 +aPyramidContourActor AddPosition 0 2 0 +aPyramidActor AddPosition 8 0 0 + +aPixelContourActor AddPosition 0 4 0 +aPixelContourActor AddPosition 0 2 0 +aPixelActor AddPosition 0 4 0 +aQuadContourActor AddPosition 2 4 0 +aQuadContourActor AddPosition 0 2 0 +aQuadActor AddPosition 2 4 0 +aTriangleContourActor AddPosition 4 4 0 +aTriangleContourActor AddPosition 0 2 0 +aTriangleActor AddPosition 4 4 0 +aPolygonContourActor AddPosition 6 4 0 +aPolygonContourActor AddPosition 0 2 0 +aPolygonActor AddPosition 6 4 0 +aTriangleStripContourActor AddPosition 8 4 0 +aTriangleStripContourActor AddPosition 0 2 0 +aTriangleStripActor AddPosition 8 4 0 + +aLineContourActor AddPosition 0 8 0 +aLineContourActor AddPosition 0 2 0 +aLineActor AddPosition 0 8 0 +aPolyLineContourActor AddPosition 2 8 0 +aPolyLineContourActor AddPosition 0 2 0 +aPolyLineActor AddPosition 2 8 0 + +aVertexContourActor AddPosition 0 12 0 +aVertexContourActor AddPosition 0 2 0 +aVertexActor AddPosition 0 12 0 +aPolyVertexContourActor AddPosition 2 12 0 +aPolyVertexContourActor AddPosition 0 2 0 +aPolyVertexActor AddPosition 2 12 0 + +aPentaContourActor AddPosition 4 8 0 +aPentaContourActor AddPosition 0 2 0 +aPentaActor AddPosition 4 8 0 +aHexaContourActor AddPosition 6 8 0 +aHexaContourActor AddPosition 0 2 0 +aHexaActor AddPosition 6 8 0 + + +BuildBackdrop -1 11 -1 16 -1 2 .1 + +ren1 AddActor base +[base GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor left +[left GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor back +[back GetProperty] SetDiffuseColor .2 .2 .2 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/contourQuadraticCells.tcl b/Graphics/Testing/Tcl/contourQuadraticCells.tcl new file mode 100644 index 0000000..03508ae --- /dev/null +++ b/Graphics/Testing/Tcl/contourQuadraticCells.tcl @@ -0,0 +1,504 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Contour every quadratic cell type + +# Create a scene with one of each cell type. +# QuadraticEdge +vtkPoints edgePoints + edgePoints SetNumberOfPoints 3 + edgePoints InsertPoint 0 0 0 0 + edgePoints InsertPoint 1 1.0 0 0 + edgePoints InsertPoint 2 0.5 0.25 0 +vtkFloatArray edgeScalars + edgeScalars SetNumberOfTuples 3 + edgeScalars InsertValue 0 0.0 + edgeScalars InsertValue 1 0.0 + edgeScalars InsertValue 2 0.9 +vtkQuadraticEdge aEdge + [aEdge GetPointIds] SetId 0 0 + [aEdge GetPointIds] SetId 1 1 + [aEdge GetPointIds] SetId 2 2 +vtkUnstructuredGrid aEdgeGrid + aEdgeGrid Allocate 1 1 + aEdgeGrid InsertNextCell [aEdge GetCellType] [aEdge GetPointIds] + aEdgeGrid SetPoints edgePoints + [aEdgeGrid GetPointData] SetScalars edgeScalars +vtkContourFilter edgeContours + edgeContours SetInput aEdgeGrid + edgeContours SetValue 0 0.5 +vtkDataSetMapper aEdgeContourMapper + aEdgeContourMapper SetInputConnection [edgeContours GetOutputPort] + aEdgeContourMapper ScalarVisibilityOff +vtkDataSetMapper aEdgeMapper + aEdgeMapper SetInput aEdgeGrid + aEdgeMapper ScalarVisibilityOff +vtkActor aEdgeActor + aEdgeActor SetMapper aEdgeMapper + [aEdgeActor GetProperty] SetRepresentationToWireframe + [aEdgeActor GetProperty] SetAmbient 1.0 +vtkActor aEdgeContourActor + aEdgeContourActor SetMapper aEdgeContourMapper + [aEdgeContourActor GetProperty] BackfaceCullingOn + [aEdgeContourActor GetProperty] SetAmbient 1.0 + +# Quadratic triangle +vtkPoints triPoints + triPoints SetNumberOfPoints 6 + triPoints InsertPoint 0 0.0 0.0 0.0 + triPoints InsertPoint 1 1.0 0.0 0.0 + triPoints InsertPoint 2 0.5 0.8 0.0 + triPoints InsertPoint 3 0.5 0.0 0.0 + triPoints InsertPoint 4 0.75 0.4 0.0 + triPoints InsertPoint 5 0.25 0.4 0.0 +vtkFloatArray triScalars + triScalars SetNumberOfTuples 6 + triScalars InsertValue 0 0.0 + triScalars InsertValue 1 0.0 + triScalars InsertValue 2 0.0 + triScalars InsertValue 3 1.0 + triScalars InsertValue 4 0.0 + triScalars InsertValue 5 0.0 +vtkQuadraticTriangle aTri + [aTri GetPointIds] SetId 0 0 + [aTri GetPointIds] SetId 1 1 + [aTri GetPointIds] SetId 2 2 + [aTri GetPointIds] SetId 3 3 + [aTri GetPointIds] SetId 4 4 + [aTri GetPointIds] SetId 5 5 +vtkUnstructuredGrid aTriGrid + aTriGrid Allocate 1 1 + aTriGrid InsertNextCell [aTri GetCellType] [aTri GetPointIds] + aTriGrid SetPoints triPoints + [aTriGrid GetPointData] SetScalars triScalars +vtkContourFilter triContours + triContours SetInput aTriGrid + triContours SetValue 0 0.5 +vtkDataSetMapper aTriContourMapper + aTriContourMapper SetInputConnection [triContours GetOutputPort] + aTriContourMapper ScalarVisibilityOff +vtkDataSetMapper aTriMapper + aTriMapper SetInput aTriGrid + aTriMapper ScalarVisibilityOff +vtkActor aTriActor + aTriActor SetMapper aTriMapper + [aTriActor GetProperty] SetRepresentationToWireframe + [aTriActor GetProperty] SetAmbient 1.0 +vtkActor aTriContourActor + aTriContourActor SetMapper aTriContourMapper + [aTriContourActor GetProperty] BackfaceCullingOn + [aTriContourActor GetProperty] SetAmbient 1.0 + +# Quadratic quadrilateral +vtkPoints quadPoints + quadPoints SetNumberOfPoints 8 + quadPoints InsertPoint 0 0.0 0.0 0.0 + quadPoints InsertPoint 1 1.0 0.0 0.0 + quadPoints InsertPoint 2 1.0 1.0 0.0 + quadPoints InsertPoint 3 0.0 1.0 0.0 + quadPoints InsertPoint 4 0.5 0.0 0.0 + quadPoints InsertPoint 5 1.0 0.5 0.0 + quadPoints InsertPoint 6 0.5 1.0 0.0 + quadPoints InsertPoint 7 0.0 0.5 0.0 +vtkFloatArray quadScalars + quadScalars SetNumberOfTuples 8 + quadScalars InsertValue 0 0.0 + quadScalars InsertValue 1 0.0 + quadScalars InsertValue 2 1.0 + quadScalars InsertValue 3 1.0 + quadScalars InsertValue 4 1.0 + quadScalars InsertValue 5 0.0 + quadScalars InsertValue 6 0.0 + quadScalars InsertValue 7 0.0 +vtkQuadraticQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + [aQuad GetPointIds] SetId 4 4 + [aQuad GetPointIds] SetId 5 5 + [aQuad GetPointIds] SetId 6 6 + [aQuad GetPointIds] SetId 7 7 +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + [aQuadGrid GetPointData] SetScalars quadScalars +vtkContourFilter quadContours + quadContours SetInput aQuadGrid + quadContours SetValue 0 0.5 +vtkDataSetMapper aQuadContourMapper + aQuadContourMapper SetInputConnection [quadContours GetOutputPort] + aQuadContourMapper ScalarVisibilityOff +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid + aQuadMapper ScalarVisibilityOff +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + [aQuadActor GetProperty] SetRepresentationToWireframe + [aQuadActor GetProperty] SetAmbient 1.0 +vtkActor aQuadContourActor + aQuadContourActor SetMapper aQuadContourMapper + [aQuadContourActor GetProperty] BackfaceCullingOn + [aQuadContourActor GetProperty] SetAmbient 1.0 + +# Quadratic tetrahedron +vtkPoints tetPoints + tetPoints SetNumberOfPoints 10 + tetPoints InsertPoint 0 0.0 0.0 0.0 + tetPoints InsertPoint 1 1.0 0.0 0.0 + tetPoints InsertPoint 2 0.5 0.8 0.0 + tetPoints InsertPoint 3 0.5 0.4 1.0 + tetPoints InsertPoint 4 0.5 0.0 0.0 + tetPoints InsertPoint 5 0.75 0.4 0.0 + tetPoints InsertPoint 6 0.25 0.4 0.0 + tetPoints InsertPoint 7 0.25 0.2 0.5 + tetPoints InsertPoint 8 0.75 0.2 0.5 + tetPoints InsertPoint 9 0.50 0.6 0.5 +vtkFloatArray tetScalars + tetScalars SetNumberOfTuples 10 + tetScalars InsertValue 0 1.0 + tetScalars InsertValue 1 1.0 + tetScalars InsertValue 2 1.0 + tetScalars InsertValue 3 1.0 + tetScalars InsertValue 4 0.0 + tetScalars InsertValue 5 0.0 + tetScalars InsertValue 6 0.0 + tetScalars InsertValue 7 0.0 + tetScalars InsertValue 8 0.0 + tetScalars InsertValue 9 0.0 +vtkQuadraticTetra aTet + [aTet GetPointIds] SetId 0 0 + [aTet GetPointIds] SetId 1 1 + [aTet GetPointIds] SetId 2 2 + [aTet GetPointIds] SetId 3 3 + [aTet GetPointIds] SetId 4 4 + [aTet GetPointIds] SetId 5 5 + [aTet GetPointIds] SetId 6 6 + [aTet GetPointIds] SetId 7 7 + [aTet GetPointIds] SetId 8 8 + [aTet GetPointIds] SetId 9 9 +vtkUnstructuredGrid aTetGrid + aTetGrid Allocate 1 1 + aTetGrid InsertNextCell [aTet GetCellType] [aTet GetPointIds] + aTetGrid SetPoints tetPoints + [aTetGrid GetPointData] SetScalars tetScalars +vtkContourFilter tetContours + tetContours SetInput aTetGrid + tetContours SetValue 0 0.5 +vtkDataSetMapper aTetContourMapper + aTetContourMapper SetInputConnection [tetContours GetOutputPort] + aTetContourMapper ScalarVisibilityOff +vtkDataSetMapper aTetMapper + aTetMapper SetInput aTetGrid + aTetMapper ScalarVisibilityOff +vtkActor aTetActor + aTetActor SetMapper aTetMapper + [aTetActor GetProperty] SetRepresentationToWireframe + [aTetActor GetProperty] SetAmbient 1.0 +vtkActor aTetContourActor + aTetContourActor SetMapper aTetContourMapper + [aTetContourActor GetProperty] SetAmbient 1.0 + +# Quadratic hexahedron +vtkPoints hexPoints + hexPoints SetNumberOfPoints 20 + hexPoints InsertPoint 0 0 0 0 + hexPoints InsertPoint 1 1 0 0 + hexPoints InsertPoint 2 1 1 0 + hexPoints InsertPoint 3 0 1 0 + hexPoints InsertPoint 4 0 0 1 + hexPoints InsertPoint 5 1 0 1 + hexPoints InsertPoint 6 1 1 1 + hexPoints InsertPoint 7 0 1 1 + hexPoints InsertPoint 8 0.5 0 0 + hexPoints InsertPoint 9 1 0.5 0 + hexPoints InsertPoint 10 0.5 1 0 + hexPoints InsertPoint 11 0 0.5 0 + hexPoints InsertPoint 12 0.5 0 1 + hexPoints InsertPoint 13 1 0.5 1 + hexPoints InsertPoint 14 0.5 1 1 + hexPoints InsertPoint 15 0 0.5 1 + hexPoints InsertPoint 16 0 0 0.5 + hexPoints InsertPoint 17 1 0 0.5 + hexPoints InsertPoint 18 1 1 0.5 + hexPoints InsertPoint 19 0 1 0.5 +vtkFloatArray hexScalars + hexScalars SetNumberOfTuples 20 + hexScalars InsertValue 0 1.0 + hexScalars InsertValue 1 1.0 + hexScalars InsertValue 2 1.0 + hexScalars InsertValue 3 1.0 + hexScalars InsertValue 4 1.0 + hexScalars InsertValue 5 1.0 + hexScalars InsertValue 6 1.0 + hexScalars InsertValue 7 1.0 + hexScalars InsertValue 8 0.0 + hexScalars InsertValue 9 0.0 + hexScalars InsertValue 10 0.0 + hexScalars InsertValue 11 0.0 + hexScalars InsertValue 12 0.0 + hexScalars InsertValue 13 0.0 + hexScalars InsertValue 14 0.0 + hexScalars InsertValue 15 0.0 + hexScalars InsertValue 16 0.0 + hexScalars InsertValue 17 0.0 + hexScalars InsertValue 18 0.0 + hexScalars InsertValue 19 0.0 +vtkQuadraticHexahedron aHex + [aHex GetPointIds] SetId 0 0 + [aHex GetPointIds] SetId 1 1 + [aHex GetPointIds] SetId 2 2 + [aHex GetPointIds] SetId 3 3 + [aHex GetPointIds] SetId 4 4 + [aHex GetPointIds] SetId 5 5 + [aHex GetPointIds] SetId 6 6 + [aHex GetPointIds] SetId 7 7 + [aHex GetPointIds] SetId 8 8 + [aHex GetPointIds] SetId 9 9 + [aHex GetPointIds] SetId 10 10 + [aHex GetPointIds] SetId 11 11 + [aHex GetPointIds] SetId 12 12 + [aHex GetPointIds] SetId 13 13 + [aHex GetPointIds] SetId 14 14 + [aHex GetPointIds] SetId 15 15 + [aHex GetPointIds] SetId 16 16 + [aHex GetPointIds] SetId 17 17 + [aHex GetPointIds] SetId 18 18 + [aHex GetPointIds] SetId 19 19 +vtkUnstructuredGrid aHexGrid + aHexGrid Allocate 1 1 + aHexGrid InsertNextCell [aHex GetCellType] [aHex GetPointIds] + aHexGrid SetPoints hexPoints + [aHexGrid GetPointData] SetScalars hexScalars +vtkContourFilter hexContours + hexContours SetInput aHexGrid + hexContours SetValue 0 0.5 +vtkDataSetMapper aHexContourMapper + aHexContourMapper SetInputConnection [hexContours GetOutputPort] + aHexContourMapper ScalarVisibilityOff +vtkDataSetMapper aHexMapper + aHexMapper SetInput aHexGrid + aHexMapper ScalarVisibilityOff +vtkActor aHexActor + aHexActor SetMapper aHexMapper + [aHexActor GetProperty] SetRepresentationToWireframe + [aHexActor GetProperty] SetAmbient 1.0 +vtkActor aHexContourActor + aHexContourActor SetMapper aHexContourMapper + [aHexContourActor GetProperty] SetAmbient 1.0 + +# Quadratic wedge +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 15 + wedgePoints InsertPoint 0 0 0 0 + wedgePoints InsertPoint 1 1 0 0 + wedgePoints InsertPoint 2 0 1 0 + wedgePoints InsertPoint 3 0 0 1 + wedgePoints InsertPoint 4 1 0 1 + wedgePoints InsertPoint 5 0 1 1 + wedgePoints InsertPoint 6 0.5 0 0 + wedgePoints InsertPoint 7 0.5 0.5 0 + wedgePoints InsertPoint 8 0 0.5 0 + wedgePoints InsertPoint 9 0.5 0 1 + wedgePoints InsertPoint 10 0.5 0.5 1 + wedgePoints InsertPoint 11 0 0.5 1 + wedgePoints InsertPoint 12 0 0 0.5 + wedgePoints InsertPoint 13 1 0 0.5 + wedgePoints InsertPoint 14 0 1 0.5 +vtkFloatArray wedgeScalars + wedgeScalars SetNumberOfTuples 15 + wedgeScalars InsertValue 0 1.0 + wedgeScalars InsertValue 1 1.0 + wedgeScalars InsertValue 2 1.0 + wedgeScalars InsertValue 3 1.0 + wedgeScalars InsertValue 4 1.0 + wedgeScalars InsertValue 5 1.0 + wedgeScalars InsertValue 6 0.0 + wedgeScalars InsertValue 7 0.0 + wedgeScalars InsertValue 8 0.0 + wedgeScalars InsertValue 9 0.0 + wedgeScalars InsertValue 10 0.0 + wedgeScalars InsertValue 11 0.0 + wedgeScalars InsertValue 12 0.0 + wedgeScalars InsertValue 13 0.0 + wedgeScalars InsertValue 14 0.0 +vtkQuadraticWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + [aWedge GetPointIds] SetId 6 6 + [aWedge GetPointIds] SetId 7 7 + [aWedge GetPointIds] SetId 8 8 + [aWedge GetPointIds] SetId 9 9 + [aWedge GetPointIds] SetId 10 10 + [aWedge GetPointIds] SetId 11 11 + [aWedge GetPointIds] SetId 12 12 + [aWedge GetPointIds] SetId 13 13 + [aWedge GetPointIds] SetId 14 14 +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + [aWedgeGrid GetPointData] SetScalars wedgeScalars +vtkContourFilter wedgeContours + wedgeContours SetInput aWedgeGrid + wedgeContours SetValue 0 0.5 +vtkDataSetMapper aWedgeContourMapper + aWedgeContourMapper SetInputConnection [wedgeContours GetOutputPort] + aWedgeContourMapper ScalarVisibilityOff +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeGrid + aWedgeMapper ScalarVisibilityOff +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + [aWedgeActor GetProperty] SetRepresentationToWireframe + [aWedgeActor GetProperty] SetAmbient 1.0 +vtkActor aWedgeContourActor + aWedgeContourActor SetMapper aWedgeContourMapper + [aWedgeContourActor GetProperty] SetAmbient 1.0 + +# Quadratic pyramid +vtkPoints pyraPoints + pyraPoints SetNumberOfPoints 13 + pyraPoints InsertPoint 0 0 0 0 + pyraPoints InsertPoint 1 1 0 0 + pyraPoints InsertPoint 2 1 1 0 + pyraPoints InsertPoint 3 0 1 0 + pyraPoints InsertPoint 4 0 0 1 + pyraPoints InsertPoint 5 0.5 0 0 + pyraPoints InsertPoint 6 1 0.5 0 + pyraPoints InsertPoint 7 0.5 1 0 + pyraPoints InsertPoint 8 0 0.5 0 + pyraPoints InsertPoint 9 0 0 0.5 + pyraPoints InsertPoint 10 0.5 0 0.5 + pyraPoints InsertPoint 11 0.5 0.5 0.5 + pyraPoints InsertPoint 12 0 0.5 0.5 +vtkFloatArray pyraScalars + pyraScalars SetNumberOfTuples 13 + pyraScalars InsertValue 0 1.0 + pyraScalars InsertValue 1 1.0 + pyraScalars InsertValue 2 1.0 + pyraScalars InsertValue 3 1.0 + pyraScalars InsertValue 4 1.0 + pyraScalars InsertValue 5 0.0 + pyraScalars InsertValue 6 0.0 + pyraScalars InsertValue 7 0.0 + pyraScalars InsertValue 8 0.0 + pyraScalars InsertValue 9 0.0 + pyraScalars InsertValue 10 0.0 + pyraScalars InsertValue 11 0.0 + pyraScalars InsertValue 12 0.0 +vtkQuadraticPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + [aPyramid GetPointIds] SetId 5 5 + [aPyramid GetPointIds] SetId 6 6 + [aPyramid GetPointIds] SetId 7 7 + [aPyramid GetPointIds] SetId 8 8 + [aPyramid GetPointIds] SetId 9 9 + [aPyramid GetPointIds] SetId 10 10 + [aPyramid GetPointIds] SetId 11 11 + [aPyramid GetPointIds] SetId 12 12 +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyraPoints + [aPyramidGrid GetPointData] SetScalars pyraScalars +vtkContourFilter pyraContours + pyraContours SetInput aPyramidGrid + pyraContours SetValue 0 0.5 +vtkDataSetMapper aPyramidContourMapper + aPyramidContourMapper SetInputConnection [pyraContours GetOutputPort] + aPyramidContourMapper ScalarVisibilityOff +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid + aPyramidMapper ScalarVisibilityOff +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + [aPyramidActor GetProperty] SetRepresentationToWireframe + [aPyramidActor GetProperty] SetAmbient 1.0 +vtkActor aPyramidContourActor + aPyramidContourActor SetMapper aPyramidContourMapper + [aPyramidContourActor GetProperty] SetAmbient 1.0 + +# Create the rendering related stuff. +# Since some of our actors are a single vertex, we need to remove all +# cullers so the single vertex actors will render +vtkRenderer ren1 +[ren1 GetCullers] RemoveAllItems + +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground .1 .2 .3 +renWin SetSize 400 200 + +# specify properties +ren1 AddActor aEdgeActor +ren1 AddActor aEdgeContourActor + +ren1 AddActor aTriActor +ren1 AddActor aTriContourActor + +ren1 AddActor aQuadActor +ren1 AddActor aQuadContourActor + +ren1 AddActor aTetActor +ren1 AddActor aTetContourActor + +ren1 AddActor aHexActor +ren1 AddActor aHexContourActor + +ren1 AddActor aWedgeActor +ren1 AddActor aWedgeContourActor + +ren1 AddActor aPyramidActor +ren1 AddActor aPyramidContourActor + +# places everyone!! +aEdgeContourActor AddPosition 0 2 0 +aTriActor AddPosition 2 0 0 +aTriContourActor AddPosition 2 2 0 +aQuadActor AddPosition 4 0 0 +aQuadContourActor AddPosition 4 2 0 +aTetActor AddPosition 6 0 0 +aTetContourActor AddPosition 6 2 0 +aHexActor AddPosition 8 0 0 +aHexContourActor AddPosition 8 2 0 +aWedgeActor AddPosition 10 0 0 +aWedgeContourActor AddPosition 10 2 0 +aPyramidActor AddPosition 12 0 0 +aPyramidContourActor AddPosition 12 2 0 + +BuildBackdrop -1 15 -1 4 -1 2 .1 + +ren1 AddActor base +[base GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor left +[left GetProperty] SetDiffuseColor .2 .2 .2 +ren1 AddActor back +[back GetProperty] SetDiffuseColor .2 .2 .2 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 2.5 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/contoursToSurface.tcl b/Graphics/Testing/Tcl/contoursToSurface.tcl new file mode 100644 index 0000000..cfaf939 --- /dev/null +++ b/Graphics/Testing/Tcl/contoursToSurface.tcl @@ -0,0 +1,148 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# +# Create the data +# + +vtkPoints points +vtkCellArray polys + +set i 0 + +for { set z -5 } { $z < 30 } { incr z } { + for { set xtraX 0 } { $xtraX < 90 } { incr xtraX 30 } { + for { set xtraY 0 } { $xtraY < 90 } { incr xtraY 30 } { + + set x -10 + set y -10 + + set x [expr $x + $xtraX] + set y [expr $y + $xtraY] + + if { [expr $z % 12] == 0 } { incr x 1; } + if { [expr $z % 12] == 1 } { incr x 2 } + if { [expr $z % 12] == 2 } { incr x 3 } + if { [expr $z % 12] == 3 } { incr x 3; incr y 1 } + if { [expr $z % 12] == 4 } { incr x 3; incr y 2 } + if { [expr $z % 12] == 5 } { incr x 3; incr y 3 } + if { [expr $z % 12] == 6 } { incr x 2; incr y 3 } + if { [expr $z % 12] == 7 } { incr x 1; incr y 3 } + if { [expr $z % 12] == 8 } { incr y 3 } + if { [expr $z % 12] == 9 } { incr y 2 } + if { [expr $z % 12] == 10 } { incr y 1 } + + if { [expr ($xtraX != 30 && $xtraY != 30) || ($xtraX == $xtraY)] } { + polys InsertNextCell 4 + points InsertPoint $i [expr $x + 0] [expr $y + 0] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 20] [expr $y + 0] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 20] [expr $y + 20] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 0] [expr $y + 20] $z + polys InsertCellPoint $i + incr i + + polys InsertNextCell 4 + points InsertPoint $i [expr $x + 4] [expr $y + 4] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 16] [expr $y + 4] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 16] [expr $y + 16] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 4] [expr $y + 16] $z + polys InsertCellPoint $i + incr i + } + + if { [expr $xtraX != 30 || $xtraY != 30]} { + polys InsertNextCell 4 + points InsertPoint $i [expr $x + 8] [expr $y + 8] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 12] [expr $y + 8] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 12] [expr $y + 12] $z + polys InsertCellPoint $i + incr i + points InsertPoint $i [expr $x + 8] [expr $y + 12] $z + polys InsertCellPoint $i + incr i + } + } + } +} + +# +# Create a representation of the contours used as input +# + +vtkPolyData contours + contours SetPoints points + contours SetPolys polys + +vtkPolyDataMapper contourMapper + contourMapper SetInput contours + +vtkActor contourActor + contourActor SetMapper contourMapper + [contourActor GetProperty] SetColor 1 0 0 + [contourActor GetProperty] SetAmbient 1 + [contourActor GetProperty] SetDiffuse 0 + [contourActor GetProperty] SetRepresentationToWireframe + + +ren1 AddViewProp contourActor + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 10 +[ren1 GetActiveCamera] Elevation 30 +ren1 ResetCameraClippingRange + +renWin SetSize 300 300 +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# +# Create the contour to surface filter +# + +vtkVoxelContoursToSurfaceFilter f +f SetInput contours +f SetMemoryLimitInBytes 100000 + +vtkPolyDataMapper m +m SetInputConnection [f GetOutputPort] +m ScalarVisibilityOff +m ImmediateModeRenderingOn + +vtkActor a +a SetMapper m + +ren1 AddViewProp a +contourActor VisibilityOff + +ren1 SetBackground .1 .2 .4 + +renWin Render diff --git a/Graphics/Testing/Tcl/cowHair.tcl b/Graphics/Testing/Tcl/cowHair.tcl new file mode 100644 index 0000000..98f021c --- /dev/null +++ b/Graphics/Testing/Tcl/cowHair.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkOBJReader wavefront + wavefront SetFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.obj" + wavefront Update + +vtkConeSource cone + cone SetResolution 6 + cone SetRadius .1 + +vtkTransform transform + transform Translate 0.5 0.0 0.0 + +vtkTransformPolyDataFilter transformF + transformF SetInputConnection [cone GetOutputPort] + transformF SetTransform transform + +# we just clean the normals for efficiency (keep down number of cones) +vtkCleanPolyData clean + clean SetInputConnection [wavefront GetOutputPort] + +vtkHedgeHog glyph + glyph SetInputConnection [clean GetOutputPort] + glyph SetVectorModeToUseNormal + glyph SetScaleFactor 0.4 + +vtkPolyDataMapper hairMapper + hairMapper SetInputConnection [glyph GetOutputPort] + +vtkActor hair + hair SetMapper hairMapper + +vtkPolyDataMapper cowMapper + cowMapper SetInputConnection [wavefront GetOutputPort] + +vtkActor cow + cow SetMapper cowMapper + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cow +ren1 AddActor hair +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 2 +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +ren1 ResetCameraClippingRange + +eval [hair GetProperty] SetDiffuseColor $saddle_brown +eval [hair GetProperty] SetAmbientColor $thistle +eval [hair GetProperty] SetAmbient .3 +eval [cow GetProperty] SetDiffuseColor $beige + + +renWin SetSize 320 240 +ren1 SetBackground .1 .2 .4 + +iren Initialize +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/cowHair2.tcl b/Graphics/Testing/Tcl/cowHair2.tcl new file mode 100644 index 0000000..222edb9 --- /dev/null +++ b/Graphics/Testing/Tcl/cowHair2.tcl @@ -0,0 +1,81 @@ +# This differs from cowHair because it checks the "MergingOff" feature +# of vtkCleanPolyData....it should give the same result. +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkOBJReader wavefront + wavefront SetFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.obj" + wavefront Update + +vtkConeSource cone + cone SetResolution 6 + cone SetRadius .1 + +vtkTransform transform + transform Translate 0.5 0.0 0.0 + +vtkTransformPolyDataFilter transformF + transformF SetInputConnection [cone GetOutputPort] + transformF SetTransform transform + +# we just clean the normals for efficiency (keep down number of cones) +vtkCleanPolyData clean + clean SetInputConnection [wavefront GetOutputPort] + clean PointMergingOff + +vtkHedgeHog glyph + glyph SetInputConnection [clean GetOutputPort] + glyph SetVectorModeToUseNormal + glyph SetScaleFactor 0.4 + +vtkPolyDataMapper hairMapper + hairMapper SetInputConnection [glyph GetOutputPort] + +vtkActor hair + hair SetMapper hairMapper + +vtkPolyDataMapper cowMapper + cowMapper SetInputConnection [wavefront GetOutputPort] + +vtkActor cow + cow SetMapper cowMapper + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cow +ren1 AddActor hair +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 2 +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +ren1 ResetCameraClippingRange + +eval [hair GetProperty] SetDiffuseColor $saddle_brown +eval [hair GetProperty] SetAmbientColor $thistle +eval [hair GetProperty] SetAmbient .3 +eval [cow GetProperty] SetDiffuseColor $beige + +renWin SetSize 320 240 +ren1 SetBackground .1 .2 .4 + +iren Initialize +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/createBFont.tcl b/Graphics/Testing/Tcl/createBFont.tcl new file mode 100644 index 0000000..d5686c5 --- /dev/null +++ b/Graphics/Testing/Tcl/createBFont.tcl @@ -0,0 +1,57 @@ +package require vtk +package require vtkinteraction + +# Now create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPNMReader imageIn + imageIn SetFileName "$VTK_DATA_ROOT/Data/B.pgm" + +vtkImageGaussianSmooth gaussian + eval gaussian SetStandardDeviations 2 2 + gaussian SetDimensionality 2 + gaussian SetRadiusFactors 1 1 + gaussian SetInputConnection [imageIn GetOutputPort] + +vtkImageDataGeometryFilter geometry + geometry SetInputConnection [gaussian GetOutputPort] + +vtkClipPolyData aClipper + aClipper SetInputConnection [geometry GetOutputPort] + aClipper SetValue 127.5 + aClipper GenerateClipScalarsOff + aClipper InsideOutOn + [[aClipper GetOutput] GetPointData] CopyScalarsOff + aClipper Update + +vtkPolyDataMapper mapper + mapper SetInputConnection [aClipper GetOutputPort] + mapper ScalarVisibilityOff + +vtkActor letter + letter SetMapper mapper + +ren1 AddActor letter + [letter GetProperty] SetDiffuseColor 0 0 0 + [letter GetProperty] SetRepresentationToWireframe + +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +renWin SetSize 320 320 +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# render the image +# +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/cursor3D.tcl b/Graphics/Testing/Tcl/cursor3D.tcl new file mode 100644 index 0000000..a06d457 --- /dev/null +++ b/Graphics/Testing/Tcl/cursor3D.tcl @@ -0,0 +1,78 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + + # read data +vtkPLOT3DReader reader + reader SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + reader SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + reader SetScalarFunctionNumber 110 + reader Update + + # create outline +vtkStructuredGridOutlineFilter outlineF + outlineF SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outlineF GetOutputPort] +vtkActor outline + outline SetMapper outlineMapper + [outline GetProperty] SetColor 0 0 0 + + # create cursor +vtkCursor3D cursor + eval cursor SetModelBounds [[reader GetOutput] GetBounds] + eval cursor SetFocalPoint [[reader GetOutput] GetCenter] + cursor AllOff + cursor AxesOn + cursor OutlineOn + cursor XShadowsOn + cursor YShadowsOn + cursor ZShadowsOn +vtkPolyDataMapper cursorMapper + cursorMapper SetInputConnection [cursor GetOutputPort] +vtkActor cursorActor + cursorActor SetMapper cursorMapper + [cursorActor GetProperty] SetColor 1 0 0 + + # create probe +vtkProbeFilter probe + probe SetInput [cursor GetFocus] + probe SetSource [reader GetOutput] + + # create a cone geometry for glyph +vtkConeSource cone + cone SetResolution 16 + cone SetRadius 0.25 + + # create glyph +vtkGlyph3D glyph + glyph SetInputConnection [probe GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseVector + glyph SetScaleModeToScaleByScalar + glyph SetScaleFactor .0002 +vtkPolyDataMapper glyphMapper + glyphMapper SetInputConnection [glyph GetOutputPort] +vtkActor glyphActor + glyphActor SetMapper glyphMapper + +ren1 AddActor outline +ren1 AddActor cursorActor +ren1 AddActor glyphActor +ren1 SetBackground 1.0 1.0 1.0 +renWin SetSize 200 200 +ren1 ResetCamera +[ren1 GetActiveCamera] Elevation 60 +ren1 ResetCameraClippingRange +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/cutLoop.tcl b/Graphics/Testing/Tcl/cutLoop.tcl new file mode 100644 index 0000000..91a121d --- /dev/null +++ b/Graphics/Testing/Tcl/cutLoop.tcl @@ -0,0 +1,93 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Define loop to clip with +# +vtkPoints selectionPoints + selectionPoints InsertPoint 0 -0.16553 0.135971 0.451972 + selectionPoints InsertPoint 1 -0.0880123 -0.134952 0.4747 + selectionPoints InsertPoint 2 0.00292618 -0.134604 0.482459 + selectionPoints InsertPoint 3 0.0641941 0.067112 0.490947 + selectionPoints InsertPoint 4 0.15577 0.0734765 0.469245 + selectionPoints InsertPoint 5 0.166667 -0.129217 0.454622 + selectionPoints InsertPoint 6 0.241259 -0.123363 0.420581 + selectionPoints InsertPoint 7 0.240334 0.0727106 0.432555 + selectionPoints InsertPoint 8 0.308529 0.0844311 0.384357 + selectionPoints InsertPoint 9 0.32672 -0.121674 0.359187 + selectionPoints InsertPoint 10 0.380721 -0.117342 0.302527 + selectionPoints InsertPoint 11 0.387804 0.0455074 0.312375 + selectionPoints InsertPoint 12 0.43943 -0.111673 0.211707 + selectionPoints InsertPoint 13 0.470984 -0.0801913 0.147919 + selectionPoints InsertPoint 14 0.436777 0.0688872 0.233021 + selectionPoints InsertPoint 15 0.44874 0.188852 0.109882 + selectionPoints InsertPoint 16 0.391352 0.254285 0.176943 + selectionPoints InsertPoint 17 0.373274 0.154162 0.294296 + selectionPoints InsertPoint 18 0.274659 0.311654 0.276609 + selectionPoints InsertPoint 19 0.206068 0.31396 0.329702 + selectionPoints InsertPoint 20 0.263789 0.174982 0.387308 + selectionPoints InsertPoint 21 0.213034 0.175485 0.417142 + selectionPoints InsertPoint 22 0.169113 0.261974 0.390286 + selectionPoints InsertPoint 23 0.102552 0.25997 0.414814 + selectionPoints InsertPoint 24 0.131512 0.161254 0.454705 + selectionPoints InsertPoint 25 0.000192443 0.156264 0.475307 + selectionPoints InsertPoint 26 -0.0392091 0.000251724 0.499943 + selectionPoints InsertPoint 27 -0.096161 0.159646 0.46438 + +vtkSphereSource sphere + sphere SetPhiResolution 50 + sphere SetThetaResolution 100 + sphere SetStartPhi 0 + sphere SetEndPhi 90 +vtkSelectPolyData loop + loop SetInputConnection [sphere GetOutputPort] + loop SetLoop selectionPoints + loop GenerateSelectionScalarsOn + loop SetSelectionModeToSmallestRegion; #negative scalars inside +vtkClipPolyData clip; #clips out positive region + clip SetInputConnection [loop GetOutputPort] +vtkPolyDataMapper clipMapper + clipMapper SetInputConnection [clip GetOutputPort] +vtkLODActor clipActor + clipActor SetMapper clipMapper + +vtkSelectPolyData loop2 + loop2 SetInputConnection [sphere GetOutputPort] + loop2 SetLoop selectionPoints + loop2 SetSelectionModeToSmallestRegion +vtkPolyDataMapper selectMapper + selectMapper SetInputConnection [loop2 GetOutputPort] +vtkLODActor selectActor + selectActor SetMapper selectMapper + selectActor AddPosition 1 0 0 + eval [selectActor GetProperty] SetColor $peacock + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor clipActor +ren1 AddActor selectActor +ren1 SetBackground .1 .2 .4 + +renWin SetSize 500 250 +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 0.236644 11.8322 +$cam1 SetFocalPoint 0.542809 -0.0166201 0.183931 +$cam1 SetPosition 1.65945 0.364443 2.29141 +$cam1 SetViewUp -0.0746604 0.986933 -0.14279 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/cylMap.tcl b/Graphics/Testing/Tcl/cylMap.tcl new file mode 100644 index 0000000..ec247de --- /dev/null +++ b/Graphics/Testing/Tcl/cylMap.tcl @@ -0,0 +1,62 @@ +package require vtk + +# Generate texture coordinates on a "random" sphere. + +# create some random points in a sphere +# +vtkPointSource sphere + sphere SetNumberOfPoints 25 + +# triangulate the points +# +vtkDelaunay3D del1 + del1 SetInputConnection [sphere GetOutputPort] + del1 SetTolerance 0.01 + +# texture map the sphere (using cylindrical coordinate system) +# +vtkTextureMapToCylinder tmapper + tmapper SetInputConnection [del1 GetOutputPort] + tmapper PreventSeamOn + +vtkTransformTextureCoords xform + xform SetInputConnection [tmapper GetOutputPort] + xform SetScale 4 4 1 + +vtkDataSetMapper mapper + mapper SetInputConnection [xform GetOutputPort] + +# load in the texture map and assign to actor +# +vtkBMPReader bmpReader + bmpReader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" +vtkTexture atext + atext SetInputConnection [bmpReader GetOutputPort] + atext InterpolateOn +vtkActor triangulation + triangulation SetMapper mapper + triangulation SetTexture atext + +# Create rendering stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor triangulation +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +renWin Render + +# render the image +# +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/cylindrical.tcl b/Graphics/Testing/Tcl/cylindrical.tcl new file mode 100644 index 0000000..3e9c672 --- /dev/null +++ b/Graphics/Testing/Tcl/cylindrical.tcl @@ -0,0 +1,72 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# avoid the singularity at the Z axis using 0.0001 radian offset +vtkPlaneSource plane + plane SetOrigin 1.0 0.0 -1.0 + plane SetPoint1 1.0 6.28318530719 -1.0 + plane SetPoint2 1.0 0.0 1.0 + plane SetXResolution 19 + plane SetYResolution 9 + +vtkCylindricalTransform transform + +vtkTransformPolyDataFilter tpoly + tpoly SetInputConnection [plane GetOutputPort] + tpoly SetTransform transform + +vtkTransformPolyDataFilter tpoly2 + tpoly2 SetInputConnection [tpoly GetOutputPort] + tpoly2 SetTransform [transform GetInverse] + +# also cover the inverse transformation by going back and forth +vtkTransformPolyDataFilter tpoly3 + tpoly3 SetInputConnection [tpoly2 GetOutputPort] + tpoly3 SetTransform transform + +vtkDataSetMapper mapper + mapper SetInputConnection [tpoly3 GetOutputPort] + +vtkPNMReader earth + earth SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +vtkTexture texture + texture SetInputConnection [earth GetOutputPort] + texture InterpolateOn + +vtkActor world + world SetMapper mapper + world SetTexture texture + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor world +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 +[ren1 GetActiveCamera] SetPosition 8 -10 6 +[ren1 GetActiveCamera] SetFocalPoint 0 0 0 +[ren1 GetActiveCamera] SetViewAngle 15 +[ren1 GetActiveCamera] SetViewUp 0.0 0.0 1.0 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +ren1 ResetCameraClippingRange + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/dataSetSurfaceFilter.tcl b/Graphics/Testing/Tcl/dataSetSurfaceFilter.tcl new file mode 100644 index 0000000..5aa58e3 --- /dev/null +++ b/Graphics/Testing/Tcl/dataSetSurfaceFilter.tcl @@ -0,0 +1,132 @@ +package require vtk +package require vtkinteraction + +# create pipeline - structured grid +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +vtkDataSetSurfaceFilter gf + gf SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper gMapper + gMapper SetInputConnection [gf GetOutputPort] + eval gMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor gActor + gActor SetMapper gMapper +vtkDataSetSurfaceFilter gf2 + gf2 SetInputConnection [pl3d GetOutputPort] + gf2 UseStripsOn +vtkPolyDataMapper g2Mapper + g2Mapper SetInputConnection [gf2 GetOutputPort] + eval g2Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g2Actor + g2Actor SetMapper g2Mapper + g2Actor AddPosition 0 15 0 + +# create pipeline - poly data +# +vtkDataSetSurfaceFilter gf3 + gf3 SetInputConnection [gf GetOutputPort] +vtkPolyDataMapper g3Mapper + g3Mapper SetInputConnection [gf3 GetOutputPort] + eval g3Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g3Actor + g3Actor SetMapper g3Mapper + g3Actor AddPosition 0 0 15 +vtkDataSetSurfaceFilter gf4 + gf4 SetInputConnection [gf2 GetOutputPort] + gf4 UseStripsOn +vtkPolyDataMapper g4Mapper + g4Mapper SetInputConnection [gf4 GetOutputPort] + eval g4Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g4Actor + g4Actor SetMapper g4Mapper + g4Actor AddPosition 0 15 15 + +# create pipeline - unstructured grid +# +vtkSphere s + eval s SetCenter [[pl3d GetOutput] GetCenter] + s SetRadius 100.0; #everything +vtkExtractGeometry eg + eg SetInputConnection [pl3d GetOutputPort] + eg SetImplicitFunction s +vtkDataSetSurfaceFilter gf5 + gf5 SetInputConnection [eg GetOutputPort] +vtkPolyDataMapper g5Mapper + g5Mapper SetInputConnection [gf5 GetOutputPort] + eval g5Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g5Actor + g5Actor SetMapper g5Mapper + g5Actor AddPosition 0 0 30 +vtkDataSetSurfaceFilter gf6 + gf6 SetInputConnection [eg GetOutputPort] + gf6 UseStripsOn +vtkPolyDataMapper g6Mapper + g6Mapper SetInputConnection [gf6 GetOutputPort] + eval g6Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g6Actor + g6Actor SetMapper g6Mapper + g6Actor AddPosition 0 15 30 + +# create pipeline - rectilinear grid +# +vtkRectilinearGridReader rgridReader + rgridReader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" + rgridReader Update +vtkDataSetSurfaceFilter gf7 + gf7 SetInputConnection [rgridReader GetOutputPort] +vtkPolyDataMapper g7Mapper + g7Mapper SetInputConnection [gf7 GetOutputPort] + eval g7Mapper SetScalarRange [[rgridReader GetOutput] GetScalarRange] +vtkActor g7Actor + g7Actor SetMapper g7Mapper + g7Actor SetScale 3 3 3 +vtkDataSetSurfaceFilter gf8 + gf8 SetInputConnection [rgridReader GetOutputPort] + gf8 UseStripsOn +vtkPolyDataMapper g8Mapper + g8Mapper SetInputConnection [gf8 GetOutputPort] + eval g8Mapper SetScalarRange [[rgridReader GetOutput] GetScalarRange] +vtkActor g8Actor + g8Actor SetMapper g8Mapper + g8Actor SetScale 3 3 3 + g8Actor AddPosition 0 15 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor gActor +ren1 AddActor g2Actor +ren1 AddActor g3Actor +ren1 AddActor g4Actor +ren1 AddActor g5Actor +ren1 AddActor g6Actor +ren1 AddActor g7Actor +ren1 AddActor g8Actor +renWin SetSize 340 550 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 84 174 +$cam1 SetFocalPoint 5.22824 6.09412 35.9813 +$cam1 SetPosition 100.052 62.875 102.818 +$cam1 SetViewUp -0.307455 -0.464269 0.830617 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/deciFranFace.tcl b/Graphics/Testing/Tcl/deciFranFace.tcl new file mode 100644 index 0000000..b936050 --- /dev/null +++ b/Graphics/Testing/Tcl/deciFranFace.tcl @@ -0,0 +1,91 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderer ren3 +vtkRenderer ren4 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin AddRenderer ren3 + renWin AddRenderer ren4 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPNGReader pnm1 + pnm1 SetFileName "$VTK_DATA_ROOT/Data/fran_cut.png" + +vtkTexture atext + atext SetInputConnection [pnm1 GetOutputPort] + atext InterpolateOn + +# create a cyberware source +# +vtkPolyDataReader fran + fran SetFileName "$VTK_DATA_ROOT/Data/fran_cut.vtk" + +set topologies "On Off" +set accumulates "On Off" +foreach topology $topologies { + foreach accumulate $accumulates { + vtkDecimatePro deci$topology$accumulate + deci$topology$accumulate SetInputConnection [fran GetOutputPort] + deci$topology$accumulate SetTargetReduction .95 + deci$topology$accumulate PreserveTopology$topology + deci$topology$accumulate AccumulateError$accumulate + vtkPolyDataMapper mapper$topology$accumulate + mapper$topology$accumulate SetInputConnection [deci$topology$accumulate GetOutputPort] + vtkActor fran$topology$accumulate + fran$topology$accumulate SetMapper mapper$topology$accumulate + fran$topology$accumulate SetTexture atext + } +} + +# Add the actors to the renderer, set the background and size +# +ren1 SetViewport 0 .5 .5 1 +ren2 SetViewport .5 .5 1 1 +ren3 SetViewport 0 0 .5 .5 +ren4 SetViewport .5 0 1 .5 + +ren1 AddActor franOnOn +ren2 AddActor franOnOff +ren3 AddActor franOffOn +ren4 AddActor franOffOff + +vtkCamera camera +ren1 SetActiveCamera camera +ren2 SetActiveCamera camera +ren3 SetActiveCamera camera +ren4 SetActiveCamera camera + +[ren1 GetActiveCamera] SetPosition 0.314753 -0.0699988 -0.264225 +[ren1 GetActiveCamera] SetFocalPoint 0.00188636 -0.136847 -5.84226e-09 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0 1 0 + +ren1 ResetCameraClippingRange +ren2 ResetCameraClippingRange +ren3 ResetCameraClippingRange +ren4 ResetCameraClippingRange + +ren1 SetBackground 1 1 1 +ren2 SetBackground 1 1 1 +ren3 SetBackground 1 1 1 +ren4 SetBackground 1 1 1 + +renWin SetSize 500 500 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/deciPlane.tcl b/Graphics/Testing/Tcl/deciPlane.tcl new file mode 100644 index 0000000..2378c54 --- /dev/null +++ b/Graphics/Testing/Tcl/deciPlane.tcl @@ -0,0 +1,125 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderer ren3 +vtkRenderer ren4 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin AddRenderer ren3 + renWin AddRenderer ren4 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create the data -- a plane with a couple of bumps +# +vtkPlaneSource plane + plane SetXResolution 10 + plane SetYResolution 10 + +vtkTriangleFilter tf + tf SetInputConnection [plane GetOutputPort] + +# This filter modifies the point coordinates in a couple of spots +# +vtkProgrammableFilter adjustPoints + adjustPoints SetInputConnection [tf GetOutputPort] + adjustPoints SetExecuteMethod adjustPointsProc + +# The SetExecuteMethod takes a Tcl proc as an argument +# In here is where all the processing is done. +# +proc adjustPointsProc {} { + set input [adjustPoints GetPolyDataInput] + set inPts [$input GetPoints] + set numPts [$input GetNumberOfPoints] + vtkPoints newPts + newPts SetNumberOfPoints $numPts + + for {set i 0} {$i < $numPts} {incr i} { + eval newPts SetPoint $i [$inPts GetPoint $i] + } + + set pt [$inPts GetPoint 17] + newPts SetPoint 17 [lindex $pt 0] [lindex $pt 1] 0.25 + + set pt [$inPts GetPoint 50] + newPts SetPoint 50 [lindex $pt 0] [lindex $pt 1] 1.0 + + set pt [$inPts GetPoint 77] + newPts SetPoint 77 [lindex $pt 0] [lindex $pt 1] 0.125 + + [adjustPoints GetPolyDataOutput] CopyStructure $input + [adjustPoints GetPolyDataOutput] SetPoints newPts + + newPts Delete; #reference counting - it's ok +} + +# Now remove the extreme peak in the center +vtkGeometryFilter gf + gf SetInput [adjustPoints GetPolyDataOutput] + gf ExtentClippingOn + gf SetExtent -100 100 -100 100 -1 0.9 + +# Create a table of decimation conditions +# +set boundaryVertexDeletion "On Off" +set accumulates "On Off" +foreach topology $boundaryVertexDeletion { + foreach accumulate $accumulates { + vtkDecimatePro deci$topology$accumulate + deci$topology$accumulate SetInputConnection [gf GetOutputPort] + deci$topology$accumulate SetTargetReduction .95 + deci$topology$accumulate BoundaryVertexDeletion$topology + deci$topology$accumulate AccumulateError$accumulate + vtkPolyDataMapper mapper$topology$accumulate + mapper$topology$accumulate SetInputConnection [deci$topology$accumulate GetOutputPort] + vtkActor plane$topology$accumulate + plane$topology$accumulate SetMapper mapper$topology$accumulate + } +} + +# Add the actors to the renderer, set the background and size +# +ren1 SetViewport 0 .5 .5 1 +ren2 SetViewport .5 .5 1 1 +ren3 SetViewport 0 0 .5 .5 +ren4 SetViewport .5 0 1 .5 + +ren1 AddActor planeOnOn +ren2 AddActor planeOnOff +ren3 AddActor planeOffOn +ren4 AddActor planeOffOff + +vtkCamera camera +ren1 SetActiveCamera camera +ren2 SetActiveCamera camera +ren3 SetActiveCamera camera +ren4 SetActiveCamera camera + +[ren1 GetActiveCamera] SetPosition -0.128224 0.611836 2.31297 +[ren1 GetActiveCamera] SetFocalPoint 0 0 0.125 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.162675 0.952658 -0.256864 + +ren1 SetBackground 0 0 0 +ren2 SetBackground 0 0 0 +ren3 SetBackground 0 0 0 +ren4 SetBackground 0 0 0 + +renWin SetSize 500 500 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/dicer.tcl b/Graphics/Testing/Tcl/dicer.tcl new file mode 100644 index 0000000..a887c08 --- /dev/null +++ b/Graphics/Testing/Tcl/dicer.tcl @@ -0,0 +1,51 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkSTLReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/42400-IDGH.stl" +vtkOBBDicer dicer + dicer SetInputConnection [reader GetOutputPort] + dicer SetNumberOfPointsPerPiece 1000 + dicer Update +vtkDataSetMapper isoMapper + isoMapper SetInputConnection [dicer GetOutputPort] + isoMapper SetScalarRange 0 [dicer GetNumberOfActualPieces] +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor 0.7 0.3 0.3 + +vtkOutlineCornerFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 +eval ren1 SetBackground 0.5 0.5 0.6 + +# render the image +# +renWin Render + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/dispPlot.tcl b/Graphics/Testing/Tcl/dispPlot.tcl new file mode 100644 index 0000000..0468bd4 --- /dev/null +++ b/Graphics/Testing/Tcl/dispPlot.tcl @@ -0,0 +1,59 @@ +package require vtk +package require vtkinteraction + +# this is a tcl version of plate vibration + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read a vtk file +# +vtkPolyDataReader plate + plate SetFileName "$VTK_DATA_ROOT/Data/plate.vtk" + plate SetVectorsName "mode8" +vtkWarpVector warp + warp SetInputConnection [plate GetOutputPort] + warp SetScaleFactor 0.5 +vtkPolyDataNormals normals + normals SetInputConnection [warp GetOutputPort] +vtkVectorDot color + color SetInputConnection [normals GetOutputPort] +vtkLookupTable lut + lut SetNumberOfColors 256 + lut Build + for {set i 0} {$i<128} {incr i 1} { + eval lut SetTableValue $i [expr (128.0-$i)/128.0] [expr (128.0-$i)/128.0] [expr (128.0-$i)/128.0] 1 + } + for {set i 128} {$i<256} {incr i 1} { + eval lut SetTableValue $i [expr ($i-128.0)/128.0] [expr ($i-128.0)/128.0] [expr ($i-128.0)/128.0] 1 + } + +vtkDataSetMapper plateMapper + plateMapper SetInputConnection [color GetOutputPort] + plateMapper SetLookupTable lut + plateMapper SetScalarRange -1 1 +vtkActor plateActor + plateActor SetMapper plateMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor plateActor +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 + +[ren1 GetActiveCamera] SetPosition 13.3991 14.0764 9.97787 +[ren1 GetActiveCamera] SetFocalPoint 1.50437 0.481517 4.52992 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp -0.120861 0.458556 -0.880408 +[ren1 GetActiveCamera] SetClippingRange 12.5724 26.8374 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/edgePoints.tcl b/Graphics/Testing/Tcl/edgePoints.tcl new file mode 100644 index 0000000..550ea2c --- /dev/null +++ b/Graphics/Testing/Tcl/edgePoints.tcl @@ -0,0 +1,58 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# create pipeline +# reader reads slices +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetDataSpacing 3.2 3.2 1.5 + v16 SetImageRange 30 50 + v16 SetDataMask 0x7fff + +# create points on edges +vtkEdgePoints edgePoints + edgePoints SetInputConnection [v16 GetOutputPort] + edgePoints SetValue 1150 + +# +vtkDataSetMapper mapper + mapper SetInputConnection [edgePoints GetOutputPort] + mapper ImmediateModeRenderingOn + mapper ScalarVisibilityOff + +vtkActor head + head SetMapper mapper + eval [head GetProperty] SetColor $raw_sienna + +# Create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor head +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +eval ren1 SetBackground $slate_grey +[ren1 GetActiveCamera] SetPosition 99.8847 537.86 22.4716 +[ren1 GetActiveCamera] SetFocalPoint 99.8847 109.81 15 +[ren1 GetActiveCamera] SetViewAngle 20 +[ren1 GetActiveCamera] SetViewUp 0 -1 0 + +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/eleState.tcl b/Graphics/Testing/Tcl/eleState.tcl new file mode 100644 index 0000000..10585c7 --- /dev/null +++ b/Graphics/Testing/Tcl/eleState.tcl @@ -0,0 +1,65 @@ +package require vtk +package require vtkinteraction + +# This example demonstrates the use of the linear extrusion filter and +# the USA state outline vtk dataset. It also tests the triangulation filter. + +# get the interactor ui + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline - read data +# +vtkPolyDataReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/usa.vtk" + +# okay, now create some extrusion filters with actors for each US state +vtkMath math +for {set i 0} {$i < 51} {incr i} { + vtkGeometryFilter extractCell$i + extractCell$i SetInputConnection [reader GetOutputPort] + extractCell$i CellClippingOn + extractCell$i SetCellMinimum $i + extractCell$i SetCellMaximum $i + vtkTriangleFilter tf$i + tf$i SetInputConnection [extractCell$i GetOutputPort] + vtkLinearExtrusionFilter extrude$i + extrude$i SetInputConnection [tf$i GetOutputPort] + extrude$i SetExtrusionType 1 + extrude$i SetVector 0 0 1 + extrude$i CappingOn + extrude$i SetScaleFactor [math Random 1 10] + vtkPolyDataMapper mapper$i + mapper$i SetInputConnection [extrude$i GetOutputPort] + vtkActor actor$i + actor$i SetMapper mapper$i + [actor$i GetProperty] SetColor [math Random 0 1] \ + [math Random 0 1] [math Random 0 1] + + ren1 AddActor actor$i +} + +ren1 SetBackground 1 1 1 +renWin SetSize 500 250 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 10.2299 511.497 +$cam1 SetPosition -119.669 -25.5502 79.0198 +$cam1 SetFocalPoint -115.96 41.6709 1.99546 +$cam1 SetViewUp -0.0013035 0.753456 0.657497 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/extractPolyData.tcl b/Graphics/Testing/Tcl/extractPolyData.tcl new file mode 100644 index 0000000..5f84030 --- /dev/null +++ b/Graphics/Testing/Tcl/extractPolyData.tcl @@ -0,0 +1,60 @@ +package require vtk +package require vtkinteraction + +# Demonstrate how to extract polygonal cells with an implicit function +# get the interactor ui + +# create a sphere source and actor +# +vtkSphereSource sphere + sphere SetThetaResolution 8 + sphere SetPhiResolution 16 + sphere SetRadius 1.5 + +# Extraction stuff +vtkTransform t + t RotateX 90 +vtkCylinder cylfunc + cylfunc SetRadius 0.5 + cylfunc SetTransform t +vtkExtractPolyDataGeometry extract + extract SetInputConnection [sphere GetOutputPort] + extract SetImplicitFunction cylfunc + extract ExtractBoundaryCellsOn + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [extract GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetWindowName "vtk - extractPolyData" +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor sphereActor + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/extractRectGrid.tcl b/Graphics/Testing/Tcl/extractRectGrid.tcl new file mode 100644 index 0000000..f04d5c8 --- /dev/null +++ b/Graphics/Testing/Tcl/extractRectGrid.tcl @@ -0,0 +1,76 @@ +package require vtk +package require vtkinteraction + +# create pipeline - rectilinear grid +# +vtkRectilinearGridReader rgridReader + rgridReader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" +vtkOutlineFilter outline + outline SetInputConnection [rgridReader GetOutputPort] +vtkPolyDataMapper mapper + mapper SetInputConnection [outline GetOutputPort] +vtkActor actor + actor SetMapper mapper + +rgridReader Update + +vtkExtractRectilinearGrid extract1 + extract1 SetInputConnection [rgridReader GetOutputPort] + #extract1 SetVOI 0 46 0 32 0 10 + extract1 SetVOI 23 40 16 30 9 9 + extract1 SetSampleRate 2 2 1 + extract1 IncludeBoundaryOn + extract1 Update +vtkDataSetSurfaceFilter surf1 + surf1 SetInputConnection [extract1 GetOutputPort] +vtkTriangleFilter tris + tris SetInputConnection [surf1 GetOutputPort] +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [tris GetOutputPort] + eval mapper1 SetScalarRange [[extract1 GetOutput] GetScalarRange] +vtkActor actor1 + actor1 SetMapper mapper1 + +# write out a rect grid +# write to the temp directory if possible, otherwise use . +set dir "." +if {[info commands "rtTester"] == "rtTester"} { + set dir [rtTester GetTempDirectory] +} + +# make sure the directory is writeable first +if {[catch {set channel [open "$dir/test.tmp" "w"]}] == 0 } { + close $channel + file delete -force "$dir/test.tmp" + + vtkRectilinearGridWriter rectWriter + rectWriter SetInputConnection [extract1 GetOutputPort] + rectWriter SetFileName "$dir/rect.tmp" + rectWriter Write + # delete the file + file delete -force "$dir/rect.tmp" +} + + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +#ren1 AddActor actor +ren1 AddActor actor1 +renWin SetSize 340 400 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/extractUGrid.tcl b/Graphics/Testing/Tcl/extractUGrid.tcl new file mode 100644 index 0000000..d60f5e2 --- /dev/null +++ b/Graphics/Testing/Tcl/extractUGrid.tcl @@ -0,0 +1,73 @@ +package require vtk + +# create reader and warp data with vectors +vtkDataSetReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/blow.vtk" + reader SetScalarsName "thickness9" + reader SetVectorsName "displacement9" +vtkCastToConcrete castToUnstructuredGrid + castToUnstructuredGrid SetInputConnection [reader GetOutputPort] +vtkWarpVector warp + warp SetInput [castToUnstructuredGrid GetUnstructuredGridOutput] + +# extract mold from mesh using connectivity +vtkConnectivityFilter connect + connect SetInputConnection [warp GetOutputPort] + connect SetExtractionModeToSpecifiedRegions + connect AddSpecifiedRegion 0 + connect AddSpecifiedRegion 1 +vtkDataSetMapper moldMapper + moldMapper SetInputConnection [reader GetOutputPort] + moldMapper ScalarVisibilityOff +vtkActor moldActor + moldActor SetMapper moldMapper + [moldActor GetProperty] SetColor .2 .2 .2 + [moldActor GetProperty] SetRepresentationToWireframe + +# extract parison from mesh using connectivity +vtkConnectivityFilter connect2 + connect2 SetInputConnection [warp GetOutputPort] + connect2 SetExtractionModeToSpecifiedRegions + connect2 AddSpecifiedRegion 2 +vtkExtractUnstructuredGrid extractGrid + extractGrid SetInputConnection [connect2 GetOutputPort] + extractGrid CellClippingOn + extractGrid SetCellMinimum 0 + extractGrid SetCellMaximum 23 +vtkGeometryFilter parison + parison SetInputConnection [extractGrid GetOutputPort] +vtkPolyDataNormals normals2 + normals2 SetInputConnection [parison GetOutputPort] + normals2 SetFeatureAngle 60 +vtkLookupTable lut + lut SetHueRange 0.0 0.66667 +vtkPolyDataMapper parisonMapper + parisonMapper SetInputConnection [normals2 GetOutputPort] + parisonMapper SetLookupTable lut + parisonMapper SetScalarRange 0.12 1.0 +vtkActor parisonActor + parisonActor SetMapper parisonMapper + +# graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor parisonActor +ren1 AddActor moldActor +ren1 SetBackground 1 1 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 60 +[ren1 GetActiveCamera] Roll -90 +[ren1 GetActiveCamera] Dolly 2 +ren1 ResetCameraClippingRange +renWin SetSize 500 375 +iren Initialize + + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/extractVectors.tcl b/Graphics/Testing/Tcl/extractVectors.tcl new file mode 100644 index 0000000..23a2f00 --- /dev/null +++ b/Graphics/Testing/Tcl/extractVectors.tcl @@ -0,0 +1,102 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +vtkExtractVectorComponents vx + vx SetInputConnection [pl3d GetOutputPort] +vtkContourFilter isoVx + isoVx SetInput [vx GetVxComponent] + isoVx SetValue 0 .38 +vtkPolyDataNormals normalsVx + normalsVx SetInputConnection [isoVx GetOutputPort] + normalsVx SetFeatureAngle 45 +vtkPolyDataMapper isoVxMapper + isoVxMapper SetInputConnection [normalsVx GetOutputPort] + isoVxMapper ScalarVisibilityOff + isoVxMapper ImmediateModeRenderingOn +vtkActor isoVxActor + isoVxActor SetMapper isoVxMapper + eval [isoVxActor GetProperty] SetColor 1 0.7 0.6 + +vtkExtractVectorComponents vy + vy SetInputConnection [pl3d GetOutputPort] +vtkContourFilter isoVy + isoVy SetInput [vy GetVyComponent] + isoVy SetValue 0 .38 +vtkPolyDataNormals normalsVy + normalsVy SetInputConnection [isoVy GetOutputPort] + normalsVy SetFeatureAngle 45 +vtkPolyDataMapper isoVyMapper + isoVyMapper SetInputConnection [normalsVy GetOutputPort] + isoVyMapper ScalarVisibilityOff + isoVyMapper ImmediateModeRenderingOn +vtkActor isoVyActor + isoVyActor SetMapper isoVyMapper + eval [isoVyActor GetProperty] SetColor 0.7 1 0.6 + +vtkExtractVectorComponents vz + vz SetInputConnection [pl3d GetOutputPort] +vtkContourFilter isoVz + isoVz SetInput [vz GetVzComponent] + isoVz SetValue 0 .38 +vtkPolyDataNormals normalsVz + normalsVz SetInputConnection [isoVz GetOutputPort] + normalsVz SetFeatureAngle 45 +vtkPolyDataMapper isoVzMapper + isoVzMapper SetInputConnection [normalsVz GetOutputPort] + isoVzMapper ScalarVisibilityOff + isoVzMapper ImmediateModeRenderingOn +vtkActor isoVzActor + isoVzActor SetMapper isoVzMapper + eval [isoVzActor GetProperty] SetColor 0.4 0.5 1 + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoVxActor +isoVxActor AddPosition 0 12 0 +ren1 AddActor isoVyActor +ren1 AddActor isoVzActor +isoVzActor AddPosition 0 -12 0 +ren1 SetBackground .8 .8 .8 +renWin SetSize 321 321 + +[ren1 GetActiveCamera] SetPosition -63.3093 -1.55444 64.3922 +[ren1 GetActiveCamera] SetFocalPoint 8.255 0.0499763 29.7631 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0 0 1 +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/extrudeCopyCD.tcl b/Graphics/Testing/Tcl/extrudeCopyCD.tcl new file mode 100644 index 0000000..b72504d --- /dev/null +++ b/Graphics/Testing/Tcl/extrudeCopyCD.tcl @@ -0,0 +1,101 @@ +package require vtk +package require vtkinteraction + +vtkVectorText disk + disk SetText "o" + +vtkTransform t + t Translate 1.1 0 0 +vtkTransformFilter tf + tf SetTransform t + tf SetInputConnection [disk GetOutputPort] +vtkStripper strips + strips SetInputConnection [tf GetOutputPort] + +vtkAppendPolyData app + app AddInput [disk GetOutput] + app AddInput [strips GetOutput] + app Update + +set model [app GetOutput] + +vtkLinearExtrusionFilter extrude + extrude SetInput $model + +# create random cell scalars for the model before extrusion. + +vtkMath rn + rn RandomSeed 1230 +vtkUnsignedCharArray cellColors + cellColors SetNumberOfComponents 3 + cellColors SetNumberOfTuples [$model GetNumberOfCells] +for { set i 0 } { $i < [$model GetNumberOfCells] } { incr i } { + cellColors InsertComponent $i 0 [rn Random 100 255] + cellColors InsertComponent $i 1 [rn Random 100 255] + cellColors InsertComponent $i 2 [rn Random 100 255] +} + +[$model GetCellData] SetScalars cellColors + + + +# Lets test the arrow source instead of creating another test. +vtkArrowSource arrow1 +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [arrow1 GetOutputPort] +vtkActor actor1 + actor1 SetMapper mapper1 + actor1 SetPosition 0 -0.2 1 + +vtkArrowSource arrow2 + arrow2 SetShaftResolution 2 + arrow2 SetTipResolution 1 +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [arrow2 GetOutputPort] +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetPosition 1 -0.2 1 + + + + + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPolyDataMapper mapper + mapper SetInputConnection [extrude GetOutputPort] + +vtkActor actor + actor SetMapper mapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 AddActor actor1 +ren1 AddActor actor2 + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set cam1 [ren1 GetActiveCamera] +$cam1 Azimuth 20 +$cam1 Elevation 40 +ren1 ResetCamera +$cam1 Zoom 1.5 + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/fieldToPolyData.tcl b/Graphics/Testing/Tcl/fieldToPolyData.tcl new file mode 100644 index 0000000..938a3b5 --- /dev/null +++ b/Graphics/Testing/Tcl/fieldToPolyData.tcl @@ -0,0 +1,73 @@ +package require vtk +package require vtkinteraction + +# This example demonstrates the reading of a field and conversion to PolyData +# The output should be the same as polyEx.tcl. + +# get the interactor ui + +# Create a reader and write out the field +vtkPolyDataReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/polyEx.vtk" +vtkDataSetToDataObjectFilter ds2do + ds2do SetInputConnection [reader GetOutputPort] +if {[catch {set channel [open "PolyField.vtk" "w"]}] == 0 } { + close $channel + vtkDataObjectWriter writer + writer SetInputConnection [ds2do GetOutputPort] + writer SetFileName "PolyField.vtk" + writer Write + +# create pipeline +# +vtkDataObjectReader dor + dor SetFileName "PolyField.vtk" +vtkDataObjectToDataSetFilter do2ds + do2ds SetInputConnection [dor GetOutputPort] + do2ds SetDataSetTypeToPolyData + do2ds SetPointComponent 0 "Points" 0 + do2ds SetPointComponent 1 "Points" 1 + do2ds SetPointComponent 2 "Points" 2 + do2ds SetPolysComponent "Polys" 0 +vtkFieldDataToAttributeDataFilter fd2ad + fd2ad SetInput [do2ds GetPolyDataOutput] + fd2ad SetInputFieldToDataObjectField + fd2ad SetOutputAttributeDataToPointData + fd2ad SetScalarComponent 0 "my_scalars" 0 + +vtkPolyDataMapper mapper + mapper SetInput [fd2ad GetPolyDataOutput] + eval mapper SetScalarRange [[fd2ad GetOutput] GetScalarRange] +vtkActor actor + actor SetMapper mapper + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange .348 17.43 +$cam1 SetPosition 2.92 2.62 -0.836 +$cam1 SetViewUp -0.436 -0.067 -0.897 +$cam1 Azimuth 90 +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +if {[info commands "rtExMath"] != ""} { + file delete -force "PolyField.vtk" +} +} +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/fieldToRGrid.tcl b/Graphics/Testing/Tcl/fieldToRGrid.tcl new file mode 100644 index 0000000..fa64a34 --- /dev/null +++ b/Graphics/Testing/Tcl/fieldToRGrid.tcl @@ -0,0 +1,153 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +## Generate a rectilinear grid from a field. +## + +# get the interactor ui + +# Create a reader and write out the field +vtkDataSetReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" +vtkDataSetToDataObjectFilter ds2do + ds2do SetInputConnection [reader GetOutputPort] +if {[catch {set channel [open "RGridField.vtk" "w"]}] == 0 } { + close $channel +vtkDataObjectWriter writer + writer SetInputConnection [ds2do GetOutputPort] + writer SetFileName "RGridField.vtk" + writer Write + +# Read the field +# +vtkDataObjectReader dor + dor SetFileName "RGridField.vtk" +vtkDataObjectToDataSetFilter do2ds + do2ds SetInputConnection [dor GetOutputPort] + do2ds SetDataSetTypeToRectilinearGrid + do2ds SetDimensionsComponent "Dimensions" 0 + do2ds SetPointComponent 0 "XCoordinates" 0 + do2ds SetPointComponent 1 "YCoordinates" 0 + do2ds SetPointComponent 2 "ZCoordinates" 0 +vtkFieldDataToAttributeDataFilter fd2ad + fd2ad SetInput [do2ds GetRectilinearGridOutput] + fd2ad SetInputFieldToDataObjectField + fd2ad SetOutputAttributeDataToPointData + fd2ad SetVectorComponent 0 "vectors" 0 + fd2ad SetVectorComponent 1 "vectors" 1 + fd2ad SetVectorComponent 2 "vectors" 2 + fd2ad SetScalarComponent 0 "scalars" 0 + fd2ad Update + +# create pipeline +# +vtkRectilinearGridGeometryFilter plane + plane SetInput [fd2ad GetRectilinearGridOutput] + plane SetExtent 0 100 0 100 15 15 +vtkWarpVector warper + warper SetInputConnection [plane GetOutputPort] + warper SetScaleFactor 0.05 +vtkDataSetMapper planeMapper + planeMapper SetInputConnection [warper GetOutputPort] + planeMapper SetScalarRange 0.197813 0.710419 +vtkActor planeActor + planeActor SetMapper planeMapper + +vtkPlane cutPlane + eval cutPlane SetOrigin [[fd2ad GetOutput] GetCenter] + cutPlane SetNormal 1 0 0 +vtkCutter planeCut + planeCut SetInput [fd2ad GetRectilinearGridOutput] + planeCut SetCutFunction cutPlane +vtkDataSetMapper cutMapper + cutMapper SetInputConnection [planeCut GetOutputPort] + eval cutMapper SetScalarRange \ + [[[[fd2ad GetOutput] GetPointData] GetScalars] GetRange] +vtkActor cutActor + cutActor SetMapper cutMapper + +vtkContourFilter iso + iso SetInput [fd2ad GetRectilinearGridOutput] + iso SetValue 0 0.7 +vtkPolyDataNormals normals + normals SetInputConnection [iso GetOutputPort] + normals SetFeatureAngle 45 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOff +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $bisque + eval [isoActor GetProperty] SetRepresentationToWireframe + +vtkStreamLine streamer + streamer SetInputConnection [fd2ad GetOutputPort] + streamer SetStartPosition -1.2 -0.1 1.3 + streamer SetMaximumPropagationTime 500 + streamer SetStepLength 0.05 + streamer SetIntegrationStepLength 0.05 + streamer SetIntegrationDirectionToIntegrateBothDirections + +vtkTubeFilter streamTube + streamTube SetInputConnection [streamer GetOutputPort] + streamTube SetRadius 0.025 + streamTube SetNumberOfSides 6 + streamTube SetVaryRadiusToVaryRadiusByVector +vtkPolyDataMapper mapStreamTube + mapStreamTube SetInputConnection [streamTube GetOutputPort] + eval mapStreamTube SetScalarRange \ + [[[[fd2ad GetOutput] GetPointData] GetScalars] GetRange] +vtkActor streamTubeActor + streamTubeActor SetMapper mapStreamTube + [streamTubeActor GetProperty] BackfaceCullingOn + +vtkOutlineFilter outline + outline SetInput [fd2ad GetRectilinearGridOutput] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor $black + +# Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor cutActor +ren1 AddActor isoActor +ren1 AddActor streamTubeActor + +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 + +[ren1 GetActiveCamera] SetPosition 0.0390893 0.184813 -3.94026 +[ren1 GetActiveCamera] SetFocalPoint -0.00578326 0 0.701967 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.00850257 0.999169 0.0398605 +[ren1 GetActiveCamera] SetClippingRange 3.08127 6.62716 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +if {[info commands "rtExMath"] != ""} { + file delete -force "RGridField.vtk" +} +} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/fieldToSGrid.tcl b/Graphics/Testing/Tcl/fieldToSGrid.tcl new file mode 100644 index 0000000..648f5d5 --- /dev/null +++ b/Graphics/Testing/Tcl/fieldToSGrid.tcl @@ -0,0 +1,118 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Demonstrate the generation of a structured grid from field data. The output +# should be similar to combIso.tcl. +# +# NOTE: This test only works if the current directory is writable +# + +if {[catch {set channel [open "test.tmp" "w"]}] == 0 } { + close $channel + file delete -force "test.tmp" + +# get the interactor ui + +# Create a reader and write out the field +vtkPLOT3DReader comb + comb SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + comb SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + comb SetScalarFunctionNumber 100 + +vtkStructuredGridWriter wsg + wsg SetInputConnection [comb GetOutputPort] + wsg SetFileTypeToBinary + wsg SetFileName "combsg.vtk" + wsg Write + +vtkStructuredGridReader pl3d + pl3d SetFileName "combsg.vtk" + +vtkDataSetToDataObjectFilter ds2do + ds2do SetInputConnection [pl3d GetOutputPort] + +vtkDataObjectWriter writer + writer SetInputConnection [ds2do GetOutputPort] + writer SetFileName "SGridField.vtk" + writer Write + +# read the field +vtkDataObjectReader dor + dor SetFileName "SGridField.vtk" +vtkDataObjectToDataSetFilter do2ds + do2ds SetInputConnection [dor GetOutputPort] + do2ds SetDataSetTypeToStructuredGrid + do2ds SetDimensionsComponent "Dimensions" 0 + do2ds SetPointComponent 0 "Points" 0 + do2ds SetPointComponent 1 "Points" 1 + do2ds SetPointComponent 2 "Points" 2 +vtkFieldDataToAttributeDataFilter fd2ad + fd2ad SetInput [do2ds GetStructuredGridOutput] + fd2ad SetInputFieldToDataObjectField + fd2ad SetOutputAttributeDataToPointData + fd2ad SetVectorComponent 0 "Momentum" 0 + fd2ad SetVectorComponent 1 "Momentum" 1 + fd2ad SetVectorComponent 2 "Momentum" 2 + fd2ad SetScalarComponent 0 "Density" 0 + +# create pipeline +# +vtkContourFilter iso + iso SetInputConnection [fd2ad GetOutputPort] + iso SetValue 0 .38 +vtkPolyDataNormals normals + normals SetInputConnection [iso GetOutputPort] + normals SetFeatureAngle 45 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOff +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $bisque + +vtkStructuredGridOutlineFilter outline + outline SetInput [fd2ad GetStructuredGridOutput] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 +ren1 SetBackground 0.1 0.2 0.4 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# +# cleanup + file delete -force "combsg.vtk" + file delete -force "SGridField.vtk" + +# prevent the tk window from showing up then start the event loop +wm withdraw . +} + + diff --git a/Graphics/Testing/Tcl/fieldToUGrid.tcl b/Graphics/Testing/Tcl/fieldToUGrid.tcl new file mode 100644 index 0000000..0011b3d --- /dev/null +++ b/Graphics/Testing/Tcl/fieldToUGrid.tcl @@ -0,0 +1,118 @@ +package require vtk +package require vtkinteraction + +# Read a field representing unstructured grid and display it (similar to blow.tcl) + +# create a reader and write out field daya +vtkUnstructuredGridReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/blow.vtk" + reader SetScalarsName "thickness9" + reader SetVectorsName "displacement9" +vtkDataSetToDataObjectFilter ds2do + ds2do SetInputConnection [reader GetOutputPort] + +# we must be able to write here +if {[catch {set channel [open "UGridField.vtk" "w"]}] == 0 } { + close $channel + +vtkDataObjectWriter write + write SetInputConnection [ds2do GetOutputPort] + write SetFileName "UGridField.vtk" + write Write + +# Read the field and convert to unstructured grid. +vtkDataObjectReader dor + dor SetFileName "UGridField.vtk" +vtkDataObjectToDataSetFilter do2ds + do2ds SetInputConnection [dor GetOutputPort] + do2ds SetDataSetTypeToUnstructuredGrid + do2ds SetPointComponent 0 "Points" 0 + do2ds SetPointComponent 1 "Points" 1 + do2ds SetPointComponent 2 "Points" 2 + do2ds SetCellTypeComponent "CellTypes" 0 + do2ds SetCellConnectivityComponent "Cells" 0 +vtkFieldDataToAttributeDataFilter fd2ad + fd2ad SetInput [do2ds GetUnstructuredGridOutput] + fd2ad SetInputFieldToDataObjectField + fd2ad SetOutputAttributeDataToPointData + fd2ad SetVectorComponent 0 "displacement9" 0 + fd2ad SetVectorComponent 1 "displacement9" 1 + fd2ad SetVectorComponent 2 "displacement9" 2 + fd2ad SetScalarComponent 0 "thickness9" 0 + +# Now start visualizing +vtkWarpVector warp + warp SetInput [fd2ad GetUnstructuredGridOutput] + +# extract mold from mesh using connectivity +vtkConnectivityFilter connect + connect SetInputConnection [warp GetOutputPort] + connect SetExtractionModeToSpecifiedRegions + connect AddSpecifiedRegion 0 + connect AddSpecifiedRegion 1 +vtkDataSetMapper moldMapper + moldMapper SetInputConnection [connect GetOutputPort] + moldMapper ScalarVisibilityOff +vtkActor moldActor + moldActor SetMapper moldMapper + [moldActor GetProperty] SetColor .2 .2 .2 + [moldActor GetProperty] SetRepresentationToWireframe + +# extract parison from mesh using connectivity +vtkConnectivityFilter connect2 + connect2 SetInputConnection [warp GetOutputPort] + connect2 SetExtractionModeToSpecifiedRegions + connect2 AddSpecifiedRegion 2 +vtkGeometryFilter parison + parison SetInputConnection [connect2 GetOutputPort] +vtkPolyDataNormals normals2 + normals2 SetInputConnection [parison GetOutputPort] + normals2 SetFeatureAngle 60 +vtkLookupTable lut + lut SetHueRange 0.0 0.66667 +vtkPolyDataMapper parisonMapper + parisonMapper SetInputConnection [normals2 GetOutputPort] + parisonMapper SetLookupTable lut + parisonMapper SetScalarRange 0.12 1.0 +vtkActor parisonActor + parisonActor SetMapper parisonMapper + +vtkContourFilter cf + cf SetInputConnection [connect2 GetOutputPort] + cf SetValue 0 .5 +vtkPolyDataMapper contourMapper + contourMapper SetInputConnection [cf GetOutputPort] +vtkActor contours + contours SetMapper contourMapper + +# Create graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor moldActor +ren1 AddActor parisonActor +ren1 AddActor contours +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 60 +[ren1 GetActiveCamera] Roll -90 +[ren1 GetActiveCamera] Dolly 2 +ren1 ResetCameraClippingRange +ren1 SetBackground 1 1 1 +renWin SetSize 375 200 + +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} +if {[info commands "rtExMath"] != ""} { + file delete -force "UGridField.vtk" +} +} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/financialField.tcl b/Graphics/Testing/Tcl/financialField.tcl new file mode 100644 index 0000000..4c86578 --- /dev/null +++ b/Graphics/Testing/Tcl/financialField.tcl @@ -0,0 +1,149 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +set size 3187;#maximum number possible +#set size 100;#maximum number possible +set xAxis "INTEREST_RATE" +set yAxis "MONTHLY_PAYMENT" +set zAxis "MONTHLY_INCOME" +set scalar "TIME_LATE" + +# extract data from field as a polydata (just points), then extract scalars +vtkDataObjectReader fdr + fdr SetFileName "$VTK_DATA_ROOT/Data/financial.vtk" +vtkDataObjectToDataSetFilter do2ds + do2ds SetInputConnection [fdr GetOutputPort] + do2ds SetDataSetTypeToPolyData + #format: component#, arrayname, arraycomp, minArrayId, maxArrayId, normalize + do2ds DefaultNormalizeOn + do2ds SetPointComponent 0 $xAxis 0 + do2ds SetPointComponent 1 $yAxis 0 0 $size 1 + do2ds SetPointComponent 2 $zAxis 0 + do2ds Update +vtkFieldDataToAttributeDataFilter fd2ad + fd2ad SetInputConnection [do2ds GetOutputPort] + fd2ad SetInputFieldToDataObjectField + fd2ad SetOutputAttributeDataToPointData + fd2ad DefaultNormalizeOn + fd2ad SetScalarComponent 0 $scalar 0 + +# construct pipeline for original population +vtkGaussianSplatter popSplatter + popSplatter SetInputConnection [fd2ad GetOutputPort] + popSplatter SetSampleDimensions 50 50 50 + popSplatter SetRadius 0.05 + popSplatter ScalarWarpingOff +vtkMarchingContourFilter popSurface + popSurface SetInputConnection [popSplatter GetOutputPort] + popSurface SetValue 0 0.01 +vtkPolyDataMapper popMapper + popMapper SetInputConnection [popSurface GetOutputPort] + popMapper ScalarVisibilityOff +vtkActor popActor + popActor SetMapper popMapper + [popActor GetProperty] SetOpacity 0.3 + [popActor GetProperty] SetColor .9 .9 .9 + +# construct pipeline for delinquent population +vtkGaussianSplatter lateSplatter + lateSplatter SetInputConnection [fd2ad GetOutputPort] + lateSplatter SetSampleDimensions 50 50 50 + lateSplatter SetRadius 0.05 + lateSplatter SetScaleFactor 0.05 +vtkMarchingContourFilter lateSurface + lateSurface SetInputConnection [lateSplatter GetOutputPort] + lateSurface SetValue 0 0.01 +vtkPolyDataMapper lateMapper + lateMapper SetInputConnection [lateSurface GetOutputPort] + lateMapper ScalarVisibilityOff +vtkActor lateActor + lateActor SetMapper lateMapper + [lateActor GetProperty] SetColor 1.0 0.0 0.0 + +# create axes +popSplatter Update +set bounds [[popSplatter GetOutput] GetBounds] +vtkAxes axes + axes SetOrigin [lindex $bounds 0] [lindex $bounds 2] [lindex $bounds 4] + axes SetScaleFactor [expr [[popSplatter GetOutput] GetLength]/5.0] +vtkTubeFilter axesTubes + axesTubes SetInputConnection [axes GetOutputPort] + axesTubes SetRadius [expr [axes GetScaleFactor]/25.0] + axesTubes SetNumberOfSides 6 +vtkPolyDataMapper axesMapper + axesMapper SetInputConnection [axesTubes GetOutputPort] +vtkActor axesActor + axesActor SetMapper axesMapper + +# label the axes +vtkVectorText XText + XText SetText $xAxis +vtkPolyDataMapper XTextMapper + XTextMapper SetInputConnection [XText GetOutputPort] +vtkFollower XActor + XActor SetMapper XTextMapper + XActor SetScale 0.02 .02 .02 + XActor SetPosition 0.35 -0.05 -0.05 + [XActor GetProperty] SetColor 0 0 0 + +vtkVectorText YText + YText SetText $yAxis +vtkPolyDataMapper YTextMapper + YTextMapper SetInputConnection [YText GetOutputPort] +vtkFollower YActor + YActor SetMapper YTextMapper + YActor SetScale 0.02 .02 .02 + YActor SetPosition -0.05 0.35 -0.05 + [YActor GetProperty] SetColor 0 0 0 + +vtkVectorText ZText + ZText SetText $zAxis +vtkPolyDataMapper ZTextMapper + ZTextMapper SetInputConnection [ZText GetOutputPort] +vtkFollower ZActor + ZActor SetMapper ZTextMapper + ZActor SetScale 0.02 .02 .02 + ZActor SetPosition -0.05 -0.05 0.35 + [ZActor GetProperty] SetColor 0 0 0 + +# Graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetWindowName "vtk - Field Data" +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor axesActor +ren1 AddActor lateActor +ren1 AddActor XActor +ren1 AddActor YActor +ren1 AddActor ZActor +ren1 AddActor popActor;#it's last because its translucent +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +vtkCamera camera + camera SetClippingRange .274 13.72 + camera SetFocalPoint 0.433816 0.333131 0.449 + camera SetPosition -1.96987 1.15145 1.49053 + camera SetViewUp 0.378927 0.911821 0.158107 +ren1 SetActiveCamera camera +XActor SetCamera camera +YActor SetCamera camera +ZActor SetCamera camera + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/genHead.tcl b/Graphics/Testing/Tcl/genHead.tcl new file mode 100644 index 0000000..53ffc11 --- /dev/null +++ b/Graphics/Testing/Tcl/genHead.tcl @@ -0,0 +1,70 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +if {[catch {set channel [open "fullHead.tri" "w"]}] == 0 } { + close $channel + file delete -force "fullHead.tri" + file delete -force "fullHead.lim" +# reader reads slices +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetDataSpacing 3.2 3.2 1.5 + v16 SetImageRange 30 50 + v16 SetDataMask 0x7fff + +# write isosurface to file +vtkSliceCubes mcubes + mcubes SetReader v16 + mcubes SetValue 1150 + mcubes SetFileName "fullHead.tri" + mcubes SetLimitsFileName "fullHead.lim" + mcubes Update + +# read from file +vtkMCubesReader reader +reader SetFileName "fullHead.tri" +reader SetLimitsFileName "fullHead.lim" + +vtkPolyDataMapper mapper + mapper SetInputConnection [reader GetOutputPort] + +vtkActor head + head SetMapper mapper + eval [head GetProperty] SetColor $raw_sienna + +# Create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor head +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +eval ren1 SetBackground $slate_grey +[ren1 GetActiveCamera] SetPosition 99.8847 537.926 15 +[ren1 GetActiveCamera] SetFocalPoint 99.8847 109.81 15 +[ren1 GetActiveCamera] SetViewAngle 20 +[ren1 GetActiveCamera] SetViewUp 0 0 -1 + +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + file delete -force "fullHead.tri" + file delete -force "fullHead.lim" +} diff --git a/Graphics/Testing/Tcl/geomFilter.tcl b/Graphics/Testing/Tcl/geomFilter.tcl new file mode 100644 index 0000000..8850231 --- /dev/null +++ b/Graphics/Testing/Tcl/geomFilter.tcl @@ -0,0 +1,155 @@ +package require vtk + +# create pipeline - structured grid +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +vtkGeometryFilter gf + gf SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper gMapper + gMapper SetInputConnection [gf GetOutputPort] + eval gMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor gActor + gActor SetMapper gMapper +vtkGeometryFilter gf2 + gf2 SetInputConnection [pl3d GetOutputPort] + gf2 ExtentClippingOn + gf2 SetExtent 10 17 -6 6 23 37 + gf2 PointClippingOn + gf2 SetPointMinimum 0 + gf2 SetPointMaximum 10000 + gf2 CellClippingOn + gf2 SetCellMinimum 0 + gf2 SetCellMaximum 7500 +vtkPolyDataMapper g2Mapper + g2Mapper SetInputConnection [gf2 GetOutputPort] + eval g2Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g2Actor + g2Actor SetMapper g2Mapper + g2Actor AddPosition 0 15 0 + +# create pipeline - poly data +# +vtkGeometryFilter gf3 + gf3 SetInputConnection [gf GetOutputPort] +vtkPolyDataMapper g3Mapper + g3Mapper SetInputConnection [gf3 GetOutputPort] + eval g3Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g3Actor + g3Actor SetMapper g3Mapper + g3Actor AddPosition 0 0 15 +vtkGeometryFilter gf4 + gf4 SetInputConnection [gf2 GetOutputPort] + gf4 ExtentClippingOn + gf4 SetExtent 10 17 -6 6 23 37 + gf4 PointClippingOn + gf4 SetPointMinimum 0 + gf4 SetPointMaximum 10000 + gf4 CellClippingOn + gf4 SetCellMinimum 0 + gf4 SetCellMaximum 7500 +vtkPolyDataMapper g4Mapper + g4Mapper SetInputConnection [gf4 GetOutputPort] + eval g4Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g4Actor + g4Actor SetMapper g4Mapper + g4Actor AddPosition 0 15 15 + +# create pipeline - unstructured grid +# +vtkSphere s + eval s SetCenter [[pl3d GetOutput] GetCenter] + s SetRadius 100.0; #everything +vtkExtractGeometry eg + eg SetInputConnection [pl3d GetOutputPort] + eg SetImplicitFunction s +vtkGeometryFilter gf5 + gf5 SetInputConnection [eg GetOutputPort] +vtkPolyDataMapper g5Mapper + g5Mapper SetInputConnection [gf5 GetOutputPort] + eval g5Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g5Actor + g5Actor SetMapper g5Mapper + g5Actor AddPosition 0 0 30 +vtkGeometryFilter gf6 + gf6 SetInputConnection [eg GetOutputPort] + gf6 ExtentClippingOn + gf6 SetExtent 10 17 -6 6 23 37 + gf6 PointClippingOn + gf6 SetPointMinimum 0 + gf6 SetPointMaximum 10000 + gf6 CellClippingOn + gf6 SetCellMinimum 0 + gf6 SetCellMaximum 7500 +vtkPolyDataMapper g6Mapper + g6Mapper SetInputConnection [gf6 GetOutputPort] + eval g6Mapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor g6Actor + g6Actor SetMapper g6Mapper + g6Actor AddPosition 0 15 30 + +# create pipeline - rectilinear grid +# +vtkRectilinearGridReader rgridReader + rgridReader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" + rgridReader Update +vtkGeometryFilter gf7 + gf7 SetInputConnection [rgridReader GetOutputPort] +vtkPolyDataMapper g7Mapper + g7Mapper SetInputConnection [gf7 GetOutputPort] + eval g7Mapper SetScalarRange [[rgridReader GetOutput] GetScalarRange] +vtkActor g7Actor + g7Actor SetMapper g7Mapper + g7Actor SetScale 3 3 3 +vtkGeometryFilter gf8 + gf8 SetInputConnection [rgridReader GetOutputPort] + gf8 ExtentClippingOn + gf8 SetExtent 0 1 -2 2 0 4 + gf8 PointClippingOn + gf8 SetPointMinimum 0 + gf8 SetPointMaximum 10000 + gf8 CellClippingOn + gf8 SetCellMinimum 0 + gf8 SetCellMaximum 7500 +vtkPolyDataMapper g8Mapper + g8Mapper SetInputConnection [gf8 GetOutputPort] + eval g8Mapper SetScalarRange [[rgridReader GetOutput] GetScalarRange] +vtkActor g8Actor + g8Actor SetMapper g8Mapper + g8Actor SetScale 3 3 3 + g8Actor AddPosition 0 15 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor gActor +ren1 AddActor g2Actor +ren1 AddActor g3Actor +ren1 AddActor g4Actor +ren1 AddActor g5Actor +ren1 AddActor g6Actor +ren1 AddActor g7Actor +ren1 AddActor g8Actor +renWin SetSize 340 550 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 84 174 +$cam1 SetFocalPoint 5.22824 6.09412 35.9813 +$cam1 SetPosition 100.052 62.875 102.818 +$cam1 SetViewUp -0.307455 -0.464269 0.830617 +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/glyph2D.tcl b/Graphics/Testing/Tcl/glyph2D.tcl new file mode 100644 index 0000000..50271b7 --- /dev/null +++ b/Graphics/Testing/Tcl/glyph2D.tcl @@ -0,0 +1,102 @@ +package require vtk +package require vtkinteraction + +# Create some random points, scalars, and vectors to glyph +# +vtkPolyData pd +vtkPoints pts +vtkFloatArray scalars +vtkFloatArray vectors +vectors SetNumberOfComponents 3 + +pd SetPoints pts + [pd GetPointData] SetScalars scalars + [pd GetPointData] SetVectors vectors + +vtkMath math +set size 500 +for {set i 0} {$i < 100} {incr i} { + pts InsertNextPoint [math Random 0 [expr $size - 1]] \ + [math Random 0 [expr $size - 1]] 0.0 + scalars InsertNextValue [math Random 0.0 5] + vectors InsertNextTuple3 [math Random -1 1] [math Random -1 1] 0.0 +} + +vtkGlyphSource2D gs + gs SetGlyphTypeToCircle + gs SetScale 20 + gs FilledOff + gs CrossOn +vtkGlyphSource2D gs1 + gs1 SetGlyphTypeToTriangle + gs1 SetScale 20 + gs1 FilledOff + gs1 CrossOn +vtkGlyphSource2D gs2 + gs2 SetGlyphTypeToSquare + gs2 SetScale 20 + gs2 FilledOff + gs2 CrossOn +vtkGlyphSource2D gs3 + gs3 SetGlyphTypeToDiamond + gs3 SetScale 20 + gs3 FilledOff + gs3 CrossOn +vtkGlyphSource2D gs4 + gs4 SetGlyphTypeToDiamond + gs4 SetScale 20 + gs4 FilledOn + gs4 DashOn + gs4 CrossOff +vtkGlyphSource2D gs5 + gs5 SetGlyphTypeToThickArrow + gs5 SetScale 20 + gs5 FilledOn + gs5 CrossOff + +# Create a table of glyphs +vtkGlyph2D glypher + glypher SetInput pd + glypher SetSource 0 [gs GetOutput] + glypher SetSource 1 [gs1 GetOutput] + glypher SetSource 2 [gs2 GetOutput] + glypher SetSource 3 [gs3 GetOutput] + glypher SetSource 4 [gs4 GetOutput] + glypher SetSource 5 [gs5 GetOutput] + glypher SetIndexModeToScalar + glypher SetRange 0 5 + glypher SetScaleModeToDataScalingOff + +vtkPolyDataMapper2D mapper + mapper SetInputConnection [glypher GetOutputPort] + mapper SetScalarRange 0 5 + +vtkActor2D glyphActor + glyphActor SetMapper mapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor glyphActor +ren1 SetBackground 1 1 1 + +renWin SetSize $size $size +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/headBone.tcl b/Graphics/Testing/Tcl/headBone.tcl new file mode 100644 index 0000000..79aae80 --- /dev/null +++ b/Graphics/Testing/Tcl/headBone.tcl @@ -0,0 +1,88 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +vtkLight lgt + +# create pipeline +# +vtkMergePoints locator + locator SetDivisions 32 32 46 + locator RetainCellListsOff + locator SetNumberOfPointsPerBucket 2 + locator AutomaticOff + +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + +vtkMarchingCubes iso + iso SetInputConnection [v16 GetOutputPort] + iso SetValue 0 1150 + iso ComputeGradientsOn + iso ComputeScalarsOff + iso SetLocator locator + +vtkVectorNorm gradient + gradient SetInputConnection [iso GetOutputPort] + +vtkDataSetMapper isoMapper + isoMapper SetInputConnection [gradient GetOutputPort] + isoMapper ScalarVisibilityOn + isoMapper SetScalarRange 0 1200 + isoMapper ImmediateModeRenderingOn + +vtkActor isoActor + isoActor SetMapper isoMapper +set isoProp [isoActor GetProperty] +eval $isoProp SetColor $antique_white + +vtkOutlineFilter outline + outline SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper +set outlineProp [outlineActor GetProperty] +#eval $outlineProp SetColor 0 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 1 1 1 +ren1 AddLight lgt +renWin SetSize 250 250 +ren1 SetBackground 0.1 0.2 0.4 + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Elevation 90 +$cam1 SetViewUp 0 0 -1 +$cam1 Zoom 1.5 +eval lgt SetPosition [$cam1 GetPosition] +eval lgt SetFocalPoint [$cam1 GetFocalPoint] + +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/hull.tcl b/Graphics/Testing/Tcl/hull.tcl new file mode 100644 index 0000000..309eae7 --- /dev/null +++ b/Graphics/Testing/Tcl/hull.tcl @@ -0,0 +1,72 @@ +package require vtk +package require vtkinteraction + + +# Generate random planes to form a convex polyhedron. +# Create a polyhedral representation of the planes. + +# get the interactor ui + + +# create some points laying between 1<=r<5 (r is radius) +# the points also have normals pointing away from the origin. +# +vtkMath mathObj +vtkPoints points +vtkFloatArray normals +normals SetNumberOfComponents 3 +for {set i 0} {$i<100} {incr i 1} { + set radius 1.0 + set theta [mathObj Random 0 360] + set phi [mathObj Random 0 180] + + set x [expr $radius*sin($phi)*cos($theta)] + set y [expr $radius*sin($phi)*sin($theta)] + set z [expr $radius*cos($phi)] + + eval points InsertPoint $i $x $y $z + eval normals InsertTuple3 $i $x $y $z +} + +vtkPlanes planes + planes SetPoints points + planes SetNormals normals + +vtkSphereSource ss +vtkHull hull + hull SetPlanes planes + +vtkPolyData pd + hull GenerateHull pd -20 20 -20 20 -20 20 + +# triangulate them +# +vtkPolyDataMapper mapHull + mapHull SetInput pd +vtkActor hullActor + hullActor SetMapper mapHull + +# Create graphics objects +# Create the rendering window, renderer, and interactive renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor hullActor +renWin SetSize 250 250 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +iren Initialize + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/iceCream.tcl b/Graphics/Testing/Tcl/iceCream.tcl new file mode 100644 index 0000000..2a34b36 --- /dev/null +++ b/Graphics/Testing/Tcl/iceCream.tcl @@ -0,0 +1,89 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create implicit function primitives +vtkCone cone + cone SetAngle 20 +vtkPlane vertPlane + vertPlane SetOrigin .1 0 0 + vertPlane SetNormal -1 0 0 +vtkPlane basePlane + basePlane SetOrigin 1.2 0 0 + basePlane SetNormal 1 0 0 +vtkSphere iceCream + iceCream SetCenter 1.333 0 0 + iceCream SetRadius 0.5 +vtkSphere bite + bite SetCenter 1.5 0 0.5 + bite SetRadius 0.25 + +# combine primitives to build ice-cream cone +vtkImplicitBoolean theCone + theCone SetOperationTypeToIntersection + theCone AddFunction cone + theCone AddFunction vertPlane + theCone AddFunction basePlane + +vtkImplicitBoolean theCream + theCream SetOperationTypeToDifference + theCream AddFunction iceCream + theCream AddFunction bite + +# iso-surface to create geometry +vtkSampleFunction theConeSample + theConeSample SetImplicitFunction theCone + theConeSample SetModelBounds -1 1.5 -1.25 1.25 -1.25 1.25 + theConeSample SetSampleDimensions 60 60 60 + theConeSample ComputeNormalsOff +vtkMarchingContourFilter theConeSurface + theConeSurface SetInputConnection [theConeSample GetOutputPort] + theConeSurface SetValue 0 0.0 +vtkPolyDataMapper coneMapper + coneMapper SetInputConnection [theConeSurface GetOutputPort] + coneMapper ScalarVisibilityOff +vtkActor coneActor + coneActor SetMapper coneMapper + eval [coneActor GetProperty] SetColor $chocolate + +# iso-surface to create geometry +vtkSampleFunction theCreamSample + theCreamSample SetImplicitFunction theCream + theCreamSample SetModelBounds 0 2.5 -1.25 1.25 -1.25 1.25 + theCreamSample SetSampleDimensions 60 60 60 + theCreamSample ComputeNormalsOff +vtkMarchingContourFilter theCreamSurface + theCreamSurface SetInputConnection [theCreamSample GetOutputPort] + theCreamSurface SetValue 0 0.0 +vtkPolyDataMapper creamMapper + creamMapper SetInputConnection [theCreamSurface GetOutputPort] + creamMapper ScalarVisibilityOff +vtkActor creamActor + creamActor SetMapper creamMapper + eval [creamActor GetProperty] SetColor $mint + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor coneActor +ren1 AddActor creamActor +ren1 SetBackground 1 1 1 +renWin SetSize 250 250 +ren1 ResetCamera +[ren1 GetActiveCamera] Roll 90 +[ren1 GetActiveCamera] Dolly 1.5 +ren1 ResetCameraClippingRange +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/imageMCAll.tcl b/Graphics/Testing/Tcl/imageMCAll.tcl new file mode 100644 index 0000000..63538c0 --- /dev/null +++ b/Graphics/Testing/Tcl/imageMCAll.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkStructuredPointsReader slc + slc SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +set colors "$flesh $banana $grey $pink $carrot $gainsboro $tomato $gold $thistle $chocolate" +set types "UnsignedChar Char Short UnsignedShort Int UnsignedInt Long UnsignedLong Float Double" +set i 1 +set c 0 +foreach vtkType $types { + vtkImageClip clip$vtkType + clip$vtkType SetInputConnection [slc GetOutputPort] + clip$vtkType SetOutputWholeExtent -1000 1000 -1000 1000 $i [expr $i + 5] + incr i 5 + vtkImageCast castTo$vtkType + castTo$vtkType SetOutputScalarTypeTo$vtkType + castTo$vtkType SetInputConnection [clip$vtkType GetOutputPort] + castTo$vtkType ClampOverflowOn + + vtkMarchingContourFilter iso$vtkType + iso$vtkType SetInputConnection [castTo$vtkType GetOutputPort] + iso$vtkType GenerateValues 1 30 30 + + vtkPolyDataMapper iso${vtkType}Mapper + iso${vtkType}Mapper SetInputConnection [iso$vtkType GetOutputPort] + iso${vtkType}Mapper ScalarVisibilityOff + + vtkActor iso${vtkType}Actor + iso${vtkType}Actor SetMapper iso${vtkType}Mapper + [iso${vtkType}Actor GetProperty] SetDiffuseColor [lindex $colors $c] [lindex $colors [expr $c + 1]] [lindex $colors [expr $c + 2]] + [iso${vtkType}Actor GetProperty] SetSpecularPower 30 + [iso${vtkType}Actor GetProperty] SetDiffuse .7 + [iso${vtkType}Actor GetProperty] SetSpecular .5 + incr c 3 + ren1 AddActor iso${vtkType}Actor +} + +vtkOutlineFilter outline + outline SetInputConnection [slc GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 SetBackground 0.9 .9 .9 +ren1 ResetCamera +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Azimuth 20 +[ren1 GetActiveCamera] Zoom 1.5 +ren1 ResetCameraClippingRange + +renWin SetSize 400 400 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/mcubes.tcl b/Graphics/Testing/Tcl/mcubes.tcl new file mode 100644 index 0000000..4597532 --- /dev/null +++ b/Graphics/Testing/Tcl/mcubes.tcl @@ -0,0 +1,66 @@ +package require vtk +package require vtkinteraction +package require vtktesting + + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 + v16 Update + +vtkMarchingContourFilter iso + iso SetInputConnection [v16 GetOutputPort] + iso SetValue 0 1125 + +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [iso GetOutputPort] + isoMapper ScalarVisibilityOff + +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $antique_white + +vtkOutlineFilter outline + outline SetInputConnection [v16 GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 0.2 0.3 0.4 +renWin SetSize 200 200 +ren1 ResetCamera +[ren1 GetActiveCamera] Elevation 90 +[ren1 GetActiveCamera] SetViewUp 0 0 -1 +[ren1 GetActiveCamera] Dolly 1.5 + + +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/mergeFilter.tcl b/Graphics/Testing/Tcl/mergeFilter.tcl new file mode 100644 index 0000000..a903558 --- /dev/null +++ b/Graphics/Testing/Tcl/mergeFilter.tcl @@ -0,0 +1,107 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 110 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +vtkLineSource probeLine + probeLine SetPoint1 1 1 29 + probeLine SetPoint2 16.5 5 31.7693 + probeLine SetResolution 500 + +vtkProbeFilter probe + probe SetInputConnection [probeLine GetOutputPort] + probe SetSource [pl3d GetOutput] + +vtkTubeFilter probeTube + probeTube SetInput [probe GetPolyDataOutput] + probeTube SetNumberOfSides 5 + probeTube SetRadius .05 + +vtkPolyDataMapper probeMapper + probeMapper SetInputConnection [probeTube GetOutputPort] + eval probeMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] + +vtkActor probeActor + probeActor SetMapper probeMapper + +vtkLineSource displayLine + displayLine SetPoint1 0 0 0 + displayLine SetPoint2 1 0 0 + displayLine SetResolution [probeLine GetResolution] + +vtkMergeFilter displayMerge + displayMerge SetGeometry [displayLine GetOutput] + displayMerge SetScalars [probe GetPolyDataOutput] + +vtkWarpScalar displayWarp + displayWarp SetInput [displayMerge GetPolyDataOutput] + displayWarp SetNormal 0 1 0 + displayWarp SetScaleFactor .000001 + +vtkPolyDataMapper displayMapper + displayMapper SetInput [displayWarp GetPolyDataOutput] +eval displayMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] + +vtkActor displayActor + displayActor SetMapper displayMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +ren1 AddActor outlineActor +ren1 AddActor probeActor +ren1 SetBackground 1 1 1 +ren1 SetViewport 0 .25 1 1 + +ren2 AddActor displayActor +ren2 SetBackground 0 0 0 +ren2 SetViewport 0 0 1 .25 + +renWin SetSize 300 300 + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 8.88908 0.595038 29.3342 +$cam1 SetPosition 9.9 -26 41 +$cam1 SetViewUp 0.060772 -0.319905 0.945498 + +ren2 ResetCamera +set cam2 [ren2 GetActiveCamera] +$cam2 ParallelProjectionOn +$cam2 SetParallelScale .15 + +iren Initialize + + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/motor.tcl b/Graphics/Testing/Tcl/motor.tcl new file mode 100644 index 0000000..cd9a1b4 --- /dev/null +++ b/Graphics/Testing/Tcl/motor.tcl @@ -0,0 +1,147 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create cutting planes +vtkPlanes planes +vtkPoints points +vtkFloatArray norms +norms SetNumberOfComponents 3 + +points InsertPoint 0 0.0 0.0 0.0 +norms InsertTuple3 0 0.0 0.0 1.0; +points InsertPoint 1 0.0 0.0 0.0 +norms InsertTuple3 1 -1.0 0.0 0.0; + +planes SetPoints points +planes SetNormals norms + +# texture +vtkStructuredPointsReader texReader + texReader SetFileName "$VTK_DATA_ROOT/Data/texThres2.vtk" +vtkTexture texture + texture SetInputConnection [texReader GetOutputPort] + texture InterpolateOff + texture RepeatOff + +# read motor parts...each part colored separately +# +vtkBYUReader byu + byu SetGeometryFileName "$VTK_DATA_ROOT/Data/motor.g" + byu SetPartNumber 1 +vtkPolyDataNormals normals + normals SetInputConnection [byu GetOutputPort] +vtkImplicitTextureCoords tex1 + tex1 SetInputConnection [normals GetOutputPort] + tex1 SetRFunction planes +# tex1 FlipTextureOn +vtkDataSetMapper byuMapper + byuMapper SetInputConnection [tex1 GetOutputPort] +vtkActor byuActor + byuActor SetMapper byuMapper + byuActor SetTexture texture + eval [byuActor GetProperty] SetColor $cold_grey + +vtkBYUReader byu2 + byu2 SetGeometryFileName "$VTK_DATA_ROOT/Data/motor.g" + byu2 SetPartNumber 2 +vtkPolyDataNormals normals2 + normals2 SetInputConnection [byu2 GetOutputPort] +vtkImplicitTextureCoords tex2 + tex2 SetInputConnection [normals2 GetOutputPort] + tex2 SetRFunction planes +# tex2 FlipTextureOn +vtkDataSetMapper byuMapper2 + byuMapper2 SetInputConnection [tex2 GetOutputPort] +vtkActor byuActor2 + byuActor2 SetMapper byuMapper2 + byuActor2 SetTexture texture + eval [byuActor2 GetProperty] SetColor $peacock + +vtkBYUReader byu3 + byu3 SetGeometryFileName "$VTK_DATA_ROOT/Data/motor.g" + byu3 SetPartNumber 3 + +vtkTriangleFilter triangle3 + triangle3 SetInputConnection [byu3 GetOutputPort] + +vtkPolyDataNormals normals3 + normals3 SetInputConnection [triangle3 GetOutputPort] +vtkImplicitTextureCoords tex3 + tex3 SetInputConnection [normals3 GetOutputPort] + tex3 SetRFunction planes +# tex3 FlipTextureOn +vtkDataSetMapper byuMapper3 + byuMapper3 SetInputConnection [tex3 GetOutputPort] +vtkActor byuActor3 + byuActor3 SetMapper byuMapper3 + byuActor3 SetTexture texture + eval [byuActor3 GetProperty] SetColor $raw_sienna + +vtkBYUReader byu4 + byu4 SetGeometryFileName "$VTK_DATA_ROOT/Data/motor.g" + byu4 SetPartNumber 4 +vtkPolyDataNormals normals4 + normals4 SetInputConnection [byu4 GetOutputPort] +vtkImplicitTextureCoords tex4 + tex4 SetInputConnection [normals4 GetOutputPort] + tex4 SetRFunction planes +# tex4 FlipTextureOn +vtkDataSetMapper byuMapper4 + byuMapper4 SetInputConnection [tex4 GetOutputPort] +vtkActor byuActor4 + byuActor4 SetMapper byuMapper4 + byuActor4 SetTexture texture + eval [byuActor4 GetProperty] SetColor $banana + +vtkBYUReader byu5 + byu5 SetGeometryFileName "$VTK_DATA_ROOT/Data/motor.g" + byu5 SetPartNumber 5 +vtkPolyDataNormals normals5 + normals5 SetInputConnection [byu5 GetOutputPort] +vtkImplicitTextureCoords tex5 + tex5 SetInputConnection [normals5 GetOutputPort] + tex5 SetRFunction planes +# tex5 FlipTextureOn +vtkDataSetMapper byuMapper5 + byuMapper5 SetInputConnection [tex5 GetOutputPort] +vtkActor byuActor5 + byuActor5 SetMapper byuMapper5 + byuActor5 SetTexture texture + eval [byuActor5 GetProperty] SetColor $peach_puff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor byuActor +ren1 AddActor byuActor2 +ren1 AddActor byuActor3 +byuActor3 VisibilityOff +ren1 AddActor byuActor4 +ren1 AddActor byuActor5 +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 + +vtkCamera camera + camera SetFocalPoint 0.0286334 0.0362996 0.0379685 + camera SetPosition 1.37067 1.08629 -1.30349 + camera SetViewAngle 17.673 + camera SetClippingRange 1 10 + camera SetViewUp -0.376306 -0.5085 -0.774482 + +ren1 SetActiveCamera camera + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/multipleComponentContour.tcl b/Graphics/Testing/Tcl/multipleComponentContour.tcl new file mode 100644 index 0000000..abfc6cc --- /dev/null +++ b/Graphics/Testing/Tcl/multipleComponentContour.tcl @@ -0,0 +1,75 @@ +package require vtk +package require vtkinteraction + +# get the interactor ui + +## Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkImageGaussianSource gs1 + gs1 SetWholeExtent 0 31 0 31 0 31 + gs1 SetCenter 10 16 16 + gs1 SetMaximum 1000 + gs1 SetStandardDeviation 7 + +vtkImageGaussianSource gs2 + gs2 SetWholeExtent 0 31 0 31 0 31 + gs2 SetCenter 22 16 16 + gs2 SetMaximum 1000 + gs2 SetStandardDeviation 7 + +vtkImageAppendComponents iac + iac AddInput [gs1 GetOutput] + iac AddInput [gs2 GetOutput] + +vtkContourFilter cf1 + cf1 SetInputConnection [iac GetOutputPort] + cf1 SetValue 0 500 + cf1 SetArrayComponent 0 + +vtkContourFilter cf2 + cf2 SetInputConnection [iac GetOutputPort] + cf2 SetValue 0 500 + cf2 SetArrayComponent 1 + +vtkPolyDataMapper mapper1 +mapper1 SetInputConnection [cf1 GetOutputPort] +mapper1 SetImmediateModeRendering 1 +mapper1 SetScalarRange 0 1 +mapper1 SetScalarVisibility 0 +mapper1 Update + +vtkPolyDataMapper mapper2 +mapper2 SetInputConnection [cf2 GetOutputPort] +mapper2 SetImmediateModeRendering 1 +mapper2 SetScalarRange 0 1 +mapper2 SetScalarVisibility 0 + +vtkActor actor1 +actor1 SetMapper mapper1 +[actor1 GetProperty] SetColor 1 1 1 +ren1 AddActor actor1 + +vtkActor actor2 +actor2 SetMapper mapper2 +[actor2 GetProperty] SetColor 1 0 0 +ren1 AddActor actor2 + +# Add the actors to the renderer, set the background and size +# +ren1 SetBackground .3 .3 .3 +renWin SetSize 400 400 + +# enable user interface interactor +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/multipleIso.tcl b/Graphics/Testing/Tcl/multipleIso.tcl new file mode 100644 index 0000000..85acb6f --- /dev/null +++ b/Graphics/Testing/Tcl/multipleIso.tcl @@ -0,0 +1,73 @@ +package require vtk +package require vtkinteraction + +# get the interactor ui + +## Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +set range [[[[pl3d GetOutput] GetPointData] GetScalars] GetRange] +set min [lindex $range 0] +set max [lindex $range 1] +set value [expr ($min + $max) / 2.0] + +vtkContourFilter cf + cf SetInputConnection [pl3d GetOutputPort] + cf SetValue 0 $value + cf UseScalarTreeOn + +set numberOfContours 5 +set epsilon [expr double($max - $min) / double($numberOfContours * 10)] +set min [expr $min + $epsilon] +set max [expr $max - $epsilon] + +for {set i 1} { $i <= $numberOfContours } {incr i} { + cf SetValue 0 [expr $min + (($i - 1) / double($numberOfContours - 1) )*($max - $min)] + cf Update + vtkPolyData pd$i + pd$i CopyStructure [cf GetOutput] + [pd$i GetPointData] DeepCopy [[cf GetOutput] GetPointData] + vtkPolyDataMapper mapper$i + mapper$i SetInput pd$i + eval mapper$i SetScalarRange \ + [[[[pl3d GetOutput] GetPointData] GetScalars] GetRange] + vtkActor actor$i + actor$i AddPosition 0 [expr $i * 12] 0 + actor$i SetMapper mapper$i + ren1 AddActor actor$i +} + +# Add the actors to the renderer, set the background and size +# +ren1 SetBackground .3 .3 .3 +renWin SetSize 450 150 + +set cam1 [ren1 GetActiveCamera] +[ren1 GetActiveCamera] SetPosition -36.3762 32.3855 51.3652 +[ren1 GetActiveCamera] SetFocalPoint 8.255 33.3861 29.7687 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0 0 1 +ren1 ResetCameraClippingRange + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/nacaBinary.tcl b/Graphics/Testing/Tcl/nacaBinary.tcl new file mode 100644 index 0000000..8b81869 --- /dev/null +++ b/Graphics/Testing/Tcl/nacaBinary.tcl @@ -0,0 +1,53 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkEnSightGoldBinaryReader reader + reader SetCaseFileName "$VTK_DATA_ROOT/Data/EnSight/naca.bin.case" + reader SetTimeValue 3 + reader Update + + +vtkLookupTable lut + lut SetHueRange 0.667 0.0 + lut SetTableRange 0.636 1.34 + + +vtkDataSetMapper blockMapper0 + blockMapper0 SetInput [reader GetOutput 0] +vtkActor blockActor0 + blockActor0 SetMapper blockMapper0 + +vtkDataSetMapper blockMapper1 + blockMapper1 SetInput [reader GetOutput 1] +vtkActor blockActor1 + blockActor1 SetMapper blockMapper1 + + +vtkDataSetMapper blockMapper2 + blockMapper2 SetInput [reader GetOutput 2] +vtkActor blockActor2 + blockActor2 SetMapper blockMapper2 + + +ren1 AddActor blockActor0 +ren1 AddActor blockActor1 +ren1 AddActor blockActor2 + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 SetFocalPoint 0 0 0 +$cam1 ParallelProjectionOff +$cam1 Zoom 70 +$cam1 SetViewAngle 1.0 + + +renWin SetSize 400 400 +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} +wm withdraw . diff --git a/Graphics/Testing/Tcl/officeStreamPoints.tcl b/Graphics/Testing/Tcl/officeStreamPoints.tcl new file mode 100644 index 0000000..25a2fdd --- /dev/null +++ b/Graphics/Testing/Tcl/officeStreamPoints.tcl @@ -0,0 +1,284 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkStructuredGridReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/office.binary.vtk" + reader Update;#force a read to occur + +# to add coverage for vtkMultiPartExtentTranslator +vtkMultiPartExtentTranslator translator +[reader GetOutput] SetExtentTranslator translator + +set length [[reader GetOutput] GetLength] + +set maxVelocity \ + [[[[reader GetOutput] GetPointData] GetVectors] GetMaxNorm] +set maxTime [expr 35.0 * $length / $maxVelocity] + +vtkStructuredGridGeometryFilter table1 + table1 SetInputConnection [reader GetOutputPort] + table1 SetExtent 11 15 7 9 8 8 +vtkPolyDataMapper mapTable1 + mapTable1 SetInputConnection [table1 GetOutputPort] + mapTable1 ScalarVisibilityOff +vtkActor table1Actor + table1Actor SetMapper mapTable1 + [table1Actor GetProperty] SetColor .59 .427 .392 + +vtkStructuredGridGeometryFilter table2 + table2 SetInputConnection [reader GetOutputPort] + table2 SetExtent 11 15 10 12 8 8 +vtkPolyDataMapper mapTable2 + mapTable2 SetInputConnection [table2 GetOutputPort] + mapTable2 ScalarVisibilityOff +vtkActor table2Actor + table2Actor SetMapper mapTable2 + [table2Actor GetProperty] SetColor .59 .427 .392 + +vtkStructuredGridGeometryFilter FilingCabinet1 + FilingCabinet1 SetInputConnection [reader GetOutputPort] + FilingCabinet1 SetExtent 15 15 7 9 0 8 +vtkPolyDataMapper mapFilingCabinet1 + mapFilingCabinet1 SetInputConnection [FilingCabinet1 GetOutputPort] + mapFilingCabinet1 ScalarVisibilityOff +vtkActor FilingCabinet1Actor + FilingCabinet1Actor SetMapper mapFilingCabinet1 + [FilingCabinet1Actor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter FilingCabinet2 + FilingCabinet2 SetInputConnection [reader GetOutputPort] + FilingCabinet2 SetExtent 15 15 10 12 0 8 +vtkPolyDataMapper mapFilingCabinet2 + mapFilingCabinet2 SetInputConnection [FilingCabinet2 GetOutputPort] + mapFilingCabinet2 ScalarVisibilityOff +vtkActor FilingCabinet2Actor + FilingCabinet2Actor SetMapper mapFilingCabinet2 + [FilingCabinet2Actor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Top + bookshelf1Top SetInputConnection [reader GetOutputPort] + bookshelf1Top SetExtent 13 13 0 4 0 11 +vtkPolyDataMapper mapBookshelf1Top + mapBookshelf1Top SetInputConnection [bookshelf1Top GetOutputPort] + mapBookshelf1Top ScalarVisibilityOff +vtkActor bookshelf1TopActor + bookshelf1TopActor SetMapper mapBookshelf1Top + [bookshelf1TopActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Bottom + bookshelf1Bottom SetInputConnection [reader GetOutputPort] + bookshelf1Bottom SetExtent 20 20 0 4 0 11 +vtkPolyDataMapper mapBookshelf1Bottom + mapBookshelf1Bottom SetInputConnection [bookshelf1Bottom GetOutputPort] + mapBookshelf1Bottom ScalarVisibilityOff +vtkActor bookshelf1BottomActor + bookshelf1BottomActor SetMapper mapBookshelf1Bottom + [bookshelf1BottomActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Front + bookshelf1Front SetInputConnection [reader GetOutputPort] + bookshelf1Front SetExtent 13 20 0 0 0 11 +vtkPolyDataMapper mapBookshelf1Front + mapBookshelf1Front SetInputConnection [bookshelf1Front GetOutputPort] + mapBookshelf1Front ScalarVisibilityOff +vtkActor bookshelf1FrontActor + bookshelf1FrontActor SetMapper mapBookshelf1Front + [bookshelf1FrontActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1Back + bookshelf1Back SetInputConnection [reader GetOutputPort] + bookshelf1Back SetExtent 13 20 4 4 0 11 +vtkPolyDataMapper mapBookshelf1Back + mapBookshelf1Back SetInputConnection [bookshelf1Back GetOutputPort] + mapBookshelf1Back ScalarVisibilityOff +vtkActor bookshelf1BackActor + bookshelf1BackActor SetMapper mapBookshelf1Back + [bookshelf1BackActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1LHS + bookshelf1LHS SetInputConnection [reader GetOutputPort] + bookshelf1LHS SetExtent 13 20 0 4 0 0 +vtkPolyDataMapper mapBookshelf1LHS + mapBookshelf1LHS SetInputConnection [bookshelf1LHS GetOutputPort] + mapBookshelf1LHS ScalarVisibilityOff +vtkActor bookshelf1LHSActor + bookshelf1LHSActor SetMapper mapBookshelf1LHS + [bookshelf1LHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf1RHS + bookshelf1RHS SetInputConnection [reader GetOutputPort] + bookshelf1RHS SetExtent 13 20 0 4 11 11 +vtkPolyDataMapper mapBookshelf1RHS + mapBookshelf1RHS SetInputConnection [bookshelf1RHS GetOutputPort] + mapBookshelf1RHS ScalarVisibilityOff +vtkActor bookshelf1RHSActor + bookshelf1RHSActor SetMapper mapBookshelf1RHS + [bookshelf1RHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Top + bookshelf2Top SetInputConnection [reader GetOutputPort] + bookshelf2Top SetExtent 13 13 15 19 0 11 +vtkPolyDataMapper mapBookshelf2Top + mapBookshelf2Top SetInputConnection [bookshelf2Top GetOutputPort] + mapBookshelf2Top ScalarVisibilityOff +vtkActor bookshelf2TopActor + bookshelf2TopActor SetMapper mapBookshelf2Top + [bookshelf2TopActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Bottom + bookshelf2Bottom SetInputConnection [reader GetOutputPort] + bookshelf2Bottom SetExtent 20 20 15 19 0 11 +vtkPolyDataMapper mapBookshelf2Bottom + mapBookshelf2Bottom SetInputConnection [bookshelf2Bottom GetOutputPort] + mapBookshelf2Bottom ScalarVisibilityOff +vtkActor bookshelf2BottomActor + bookshelf2BottomActor SetMapper mapBookshelf2Bottom + [bookshelf2BottomActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Front + bookshelf2Front SetInputConnection [reader GetOutputPort] + bookshelf2Front SetExtent 13 20 15 15 0 11 +vtkPolyDataMapper mapBookshelf2Front + mapBookshelf2Front SetInputConnection [bookshelf2Front GetOutputPort] + mapBookshelf2Front ScalarVisibilityOff +vtkActor bookshelf2FrontActor + bookshelf2FrontActor SetMapper mapBookshelf2Front + [bookshelf2FrontActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2Back + bookshelf2Back SetInputConnection [reader GetOutputPort] + bookshelf2Back SetExtent 13 20 19 19 0 11 +vtkPolyDataMapper mapBookshelf2Back + mapBookshelf2Back SetInputConnection [bookshelf2Back GetOutputPort] + mapBookshelf2Back ScalarVisibilityOff +vtkActor bookshelf2BackActor + bookshelf2BackActor SetMapper mapBookshelf2Back + [bookshelf2BackActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2LHS + bookshelf2LHS SetInputConnection [reader GetOutputPort] + bookshelf2LHS SetExtent 13 20 15 19 0 0 +vtkPolyDataMapper mapBookshelf2LHS + mapBookshelf2LHS SetInputConnection [bookshelf2LHS GetOutputPort] + mapBookshelf2LHS ScalarVisibilityOff +vtkActor bookshelf2LHSActor + bookshelf2LHSActor SetMapper mapBookshelf2LHS + [bookshelf2LHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter bookshelf2RHS + bookshelf2RHS SetInputConnection [reader GetOutputPort] + bookshelf2RHS SetExtent 13 20 15 19 11 11 +vtkPolyDataMapper mapBookshelf2RHS + mapBookshelf2RHS SetInputConnection [bookshelf2RHS GetOutputPort] + mapBookshelf2RHS ScalarVisibilityOff +vtkActor bookshelf2RHSActor + bookshelf2RHSActor SetMapper mapBookshelf2RHS + [bookshelf2RHSActor GetProperty] SetColor .8 .8 .6 + +vtkStructuredGridGeometryFilter window + window SetInputConnection [reader GetOutputPort] + window SetExtent 20 20 6 13 10 13 +vtkPolyDataMapper mapWindow + mapWindow SetInputConnection [window GetOutputPort] + mapWindow ScalarVisibilityOff +vtkActor windowActor + windowActor SetMapper mapWindow + [windowActor GetProperty] SetColor .3 .3 .5 + +vtkStructuredGridGeometryFilter outlet + outlet SetInputConnection [reader GetOutputPort] + outlet SetExtent 0 0 9 10 14 16 +vtkPolyDataMapper mapOutlet + mapOutlet SetInputConnection [outlet GetOutputPort] + mapOutlet ScalarVisibilityOff +vtkActor outletActor + outletActor SetMapper mapOutlet + [outletActor GetProperty] SetColor 0 0 0 + +vtkStructuredGridGeometryFilter inlet + inlet SetInputConnection [reader GetOutputPort] + inlet SetExtent 0 0 9 10 0 6 +vtkPolyDataMapper mapInlet + mapInlet SetInputConnection [inlet GetOutputPort] + mapInlet ScalarVisibilityOff +vtkActor inletActor + inletActor SetMapper mapInlet + [inletActor GetProperty] SetColor 0 0 0 + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Create source for streamtubes +vtkStreamPoints streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition 0.1 2.1 0.5 + streamer SetMaximumPropagationTime 500 + streamer SetTimeIncrement 0.5 + streamer SetIntegrationDirectionToForward + +vtkConeSource cone + cone SetResolution 8 +vtkGlyph3D cones + cones SetInputConnection [streamer GetOutputPort] + cones SetSource [cone GetOutput] + cones SetScaleFactor 0.5 + cones SetScaleModeToScaleByVector +vtkPolyDataMapper mapCones + mapCones SetInputConnection [cones GetOutputPort] + eval mapCones SetScalarRange [[reader GetOutput] GetScalarRange] +vtkActor conesActor + conesActor SetMapper mapCones + +ren1 AddActor table1Actor +ren1 AddActor table2Actor +ren1 AddActor FilingCabinet1Actor +ren1 AddActor FilingCabinet2Actor +ren1 AddActor bookshelf1TopActor +ren1 AddActor bookshelf1BottomActor +ren1 AddActor bookshelf1FrontActor +ren1 AddActor bookshelf1BackActor +ren1 AddActor bookshelf1LHSActor +ren1 AddActor bookshelf1RHSActor +ren1 AddActor bookshelf2TopActor +ren1 AddActor bookshelf2BottomActor +ren1 AddActor bookshelf2FrontActor +ren1 AddActor bookshelf2BackActor +ren1 AddActor bookshelf2LHSActor +ren1 AddActor bookshelf2RHSActor +ren1 AddActor windowActor +ren1 AddActor outletActor +ren1 AddActor inletActor +ren1 AddActor outlineActor +ren1 AddActor conesActor + +ren1 SetBackground 0.4 0.4 0.5 + +vtkCamera aCamera + aCamera SetClippingRange 0.7724 39 + aCamera SetFocalPoint 1.14798 3.08416 2.47187 + aCamera SetPosition -2.64683 -3.55525 3.55848 + aCamera SetViewUp 0.0511273 0.132773 0.989827 + aCamera SetViewAngle 15.5033 + +ren1 SetActiveCamera aCamera + +renWin SetSize 500 300 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . + diff --git a/Graphics/Testing/Tcl/polyConn.tcl b/Graphics/Testing/Tcl/polyConn.tcl new file mode 100644 index 0000000..25b2c45 --- /dev/null +++ b/Graphics/Testing/Tcl/polyConn.tcl @@ -0,0 +1,71 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# planes to connect +vtkStructuredGridGeometryFilter plane1 + plane1 SetInputConnection [pl3d GetOutputPort] + plane1 SetExtent 20 20 0 100 0 100 +vtkPolyDataConnectivityFilter conn + conn SetInputConnection [plane1 GetOutputPort] + conn ScalarConnectivityOn + conn SetScalarRange 0.19 0.25 +vtkPolyDataMapper plane1Map + plane1Map SetInputConnection [conn GetOutputPort] + eval plane1Map SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor plane1Actor + plane1Actor SetMapper plane1Map + [plane1Actor GetProperty] SetOpacity 0.999 + +# outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + set outlineProp [outlineActor GetProperty] + eval $outlineProp SetColor 0 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor plane1Actor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 + +vtkCamera cam1 + cam1 SetClippingRange 14.29 63.53 + cam1 SetFocalPoint 8.58522 1.58266 30.6486 + cam1 SetPosition 37.6808 -20.1298 35.4016 + cam1 SetViewAngle 30 + cam1 SetViewUp -0.0566235 0.140504 0.98846 +ren1 SetActiveCamera cam1 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/probe.tcl b/Graphics/Testing/Tcl/probe.tcl new file mode 100644 index 0000000..2703daf --- /dev/null +++ b/Graphics/Testing/Tcl/probe.tcl @@ -0,0 +1,80 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# cut data +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update +vtkPlane plane + eval plane SetOrigin [[pl3d GetOutput] GetCenter] + plane SetNormal -0.287 0 0.9579 +vtkCutter planeCut + planeCut SetInputConnection [pl3d GetOutputPort] + planeCut SetCutFunction plane +vtkProbeFilter probe + probe SetInputConnection [planeCut GetOutputPort] + probe SetSourceConnection [pl3d GetOutputPort] +vtkDataSetMapper cutMapper + cutMapper SetInputConnection [probe GetOutputPort] + eval cutMapper SetScalarRange \ + [[[[pl3d GetOutput] GetPointData] GetScalars] GetRange] +vtkActor cutActor + cutActor SetMapper cutMapper + +#extract plane +vtkStructuredGridGeometryFilter compPlane + compPlane SetInputConnection [pl3d GetOutputPort] + compPlane SetExtent 0 100 0 100 9 9 +vtkPolyDataMapper planeMapper + planeMapper SetInputConnection [compPlane GetOutputPort] + planeMapper ScalarVisibilityOff +vtkActor planeActor + planeActor SetMapper planeMapper + [planeActor GetProperty] SetRepresentationToWireframe + [planeActor GetProperty] SetColor 0 0 0 + +#outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper +set outlineProp [outlineActor GetProperty] +eval $outlineProp SetColor 0 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor cutActor +ren1 SetBackground 1 1 1 +renWin SetSize 400 300 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 11.1034 59.5328 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition -2.95748 -26.7271 44.5309 +$cam1 SetViewUp 0.0184785 0.479657 0.877262 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/probeComb.tcl b/Graphics/Testing/Tcl/probeComb.tcl new file mode 100644 index 0000000..52c266d --- /dev/null +++ b/Graphics/Testing/Tcl/probeComb.tcl @@ -0,0 +1,116 @@ +package require vtk +package require vtkinteraction + +# create planes +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +vtkPlaneSource plane + plane SetResolution 50 50 +vtkTransform transP1 + transP1 Translate 3.7 0.0 28.37 + transP1 Scale 5 5 5 + transP1 RotateY 90 +vtkTransformPolyDataFilter tpd1 + tpd1 SetInputConnection [plane GetOutputPort] + tpd1 SetTransform transP1 +vtkOutlineFilter outTpd1 + outTpd1 SetInputConnection [tpd1 GetOutputPort] +vtkPolyDataMapper mapTpd1 + mapTpd1 SetInputConnection [outTpd1 GetOutputPort] +vtkActor tpd1Actor + tpd1Actor SetMapper mapTpd1 + [tpd1Actor GetProperty] SetColor 0 0 0 + +vtkTransform transP2 + transP2 Translate 9.2 0.0 31.20 + transP2 Scale 5 5 5 + transP2 RotateY 90 +vtkTransformPolyDataFilter tpd2 + tpd2 SetInputConnection [plane GetOutputPort] + tpd2 SetTransform transP2 +vtkOutlineFilter outTpd2 + outTpd2 SetInputConnection [tpd2 GetOutputPort] +vtkPolyDataMapper mapTpd2 + mapTpd2 SetInputConnection [outTpd2 GetOutputPort] +vtkActor tpd2Actor + tpd2Actor SetMapper mapTpd2 + [tpd2Actor GetProperty] SetColor 0 0 0 + +vtkTransform transP3 + transP3 Translate 13.27 0.0 33.30 + transP3 Scale 5 5 5 + transP3 RotateY 90 +vtkTransformPolyDataFilter tpd3 + tpd3 SetInputConnection [plane GetOutputPort] + tpd3 SetTransform transP3 +vtkOutlineFilter outTpd3 + outTpd3 SetInputConnection [tpd3 GetOutputPort] +vtkPolyDataMapper mapTpd3 + mapTpd3 SetInputConnection [outTpd3 GetOutputPort] +vtkActor tpd3Actor + tpd3Actor SetMapper mapTpd3 + [tpd3Actor GetProperty] SetColor 0 0 0 + +vtkAppendPolyData appendF + appendF AddInput [tpd1 GetOutput] + appendF AddInput [tpd2 GetOutput] + appendF AddInput [tpd3 GetOutput] + +vtkProbeFilter probe + probe SetInputConnection [appendF GetOutputPort] + probe SetSource [pl3d GetOutput] + +vtkContourFilter contour + contour SetInputConnection [probe GetOutputPort] + eval contour GenerateValues 50 [[pl3d GetOutput] GetScalarRange] + +vtkPolyDataMapper contourMapper + contourMapper SetInputConnection [contour GetOutputPort] + eval contourMapper SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor planeActor + planeActor SetMapper contourMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor tpd1Actor +ren1 AddActor tpd2Actor +ren1 AddActor tpd3Actor +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 8.88908 0.595038 29.3342 +$cam1 SetPosition -12.3332 31.7479 41.2387 +$cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/progGlyphs.tcl b/Graphics/Testing/Tcl/progGlyphs.tcl new file mode 100644 index 0000000..564d963 --- /dev/null +++ b/Graphics/Testing/Tcl/progGlyphs.tcl @@ -0,0 +1,70 @@ +package require vtk +package require vtkinteraction + +set res 6 +vtkPlaneSource plane + plane SetResolution $res $res +vtkElevationFilter colors + colors SetInputConnection [plane GetOutputPort] + colors SetLowPoint -0.25 -0.25 -0.25 + colors SetHighPoint 0.25 0.25 0.25 +vtkPolyDataMapper planeMapper + planeMapper SetInput [colors GetPolyDataOutput] +vtkActor planeActor + planeActor SetMapper planeMapper + [planeActor GetProperty] SetRepresentationToWireframe + +# procedure for generating glyphs +proc Glyph {} { + global res + set ptId [glypher GetPointId] + set pd [glypher GetPointData] + set xyz [glypher GetPoint] + set x [lindex $xyz 0] + set y [lindex $xyz 1] + set length [[glypher GetInput 0] GetLength] + set scale [expr $length / (2.0*$res)] + + squad SetScale $scale $scale $scale + eval squad SetCenter $xyz + squad SetPhiRoundness [expr abs($x)*5.0] + squad SetThetaRoundness [expr abs($y)*5.0] +} + +# create simple poly data so we can apply glyph +vtkSuperquadricSource squad +vtkProgrammableGlyphFilter glypher + glypher SetInputConnection [colors GetOutputPort] + glypher SetSource [squad GetOutput] + glypher SetGlyphMethod Glyph +vtkPolyDataMapper glyphMapper + glyphMapper SetInputConnection [glypher GetOutputPort] +vtkActor glyphActor + glyphActor SetMapper glyphMapper + + + +# Create the rendering stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor planeActor +ren1 AddActor glyphActor +ren1 SetBackground 1 1 1 +renWin SetSize 450 450 +renWin Render +[ren1 GetActiveCamera] Zoom 1.5 + +# Get handles to some useful objects +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/progGlyphsBySource.tcl b/Graphics/Testing/Tcl/progGlyphsBySource.tcl new file mode 100644 index 0000000..9d1ba5d --- /dev/null +++ b/Graphics/Testing/Tcl/progGlyphsBySource.tcl @@ -0,0 +1,93 @@ +package require vtk +package require vtkinteraction + +set res 6 +vtkPlaneSource plane + plane SetResolution $res $res +vtkElevationFilter colors + colors SetInputConnection [plane GetOutputPort] + colors SetLowPoint -0.25 -0.25 -0.25 + colors SetHighPoint 0.25 0.25 0.25 +vtkPolyDataMapper planeMapper + planeMapper SetInput [colors GetPolyDataOutput] +vtkActor planeActor + planeActor SetMapper planeMapper + [planeActor GetProperty] SetRepresentationToWireframe + +# create simple poly data so we can apply glyph +vtkSuperquadricSource squad + +vtkElevationFilter squadColors + squadColors SetInputConnection [squad GetOutputPort] + squadColors SetLowPoint -0.25 -0.25 -0.25 + squadColors SetHighPoint 0.25 0.25 0.25 +vtkCastToConcrete squadCaster + squadCaster SetInputConnection [squadColors GetOutputPort] +vtkTransform squadTransform +vtkTransformPolyDataFilter transformSquad + transformSquad SetInput [squadColors GetPolyDataOutput] + transformSquad SetTransform squadTransform + +# procedure for generating glyphs +proc Glyph {} { + global res + set ptId [glypher GetPointId] + set pd [glypher GetPointData] + set xyz [glypher GetPoint] + set x [lindex $xyz 0] + set y [lindex $xyz 1] + set length [[glypher GetInput 0] GetLength] + set scale [expr $length / (2.0*$res)] + + squadTransform Identity + if { $x == $y } { + squad ToroidalOn + eval squadTransform Translate $xyz + squadTransform RotateX 90 + } else { + eval squadTransform Translate $xyz + squad ToroidalOff + } + squadTransform Scale $scale $scale $scale + + squad SetPhiRoundness [expr abs($x)*5.0] + squad SetThetaRoundness [expr abs($y)*5.0] +} + +vtkProgrammableGlyphFilter glypher + glypher SetInputConnection [colors GetOutputPort] + glypher SetSource [transformSquad GetOutput] + glypher SetGlyphMethod Glyph + glypher SetColorModeToColorBySource + +vtkPolyDataMapper glyphMapper + glyphMapper SetInputConnection [glypher GetOutputPort] +vtkActor glyphActor + glyphActor SetMapper glyphMapper + + + +# Create the rendering stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor planeActor +ren1 AddActor glyphActor +ren1 SetBackground 1 1 1 +renWin SetSize 450 450 +renWin Render +[ren1 GetActiveCamera] Zoom 1.3 + +# Get handles to some useful objects +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/quadricCut.tcl b/Graphics/Testing/Tcl/quadricCut.tcl new file mode 100644 index 0000000..4aa9370 --- /dev/null +++ b/Graphics/Testing/Tcl/quadricCut.tcl @@ -0,0 +1,286 @@ +package require vtk +package require vtkinteraction + +set solidTexture "255 255" +set clearTexture "255 0" +set edgeTexture "0 255" + +proc makeBooleanTexture {caseNumber resolution thickness} { + global solidTexture clearTexture edgeTexture + vtkBooleanTexture booleanTexture$caseNumber + + booleanTexture$caseNumber SetXSize $resolution + booleanTexture$caseNumber SetYSize $resolution + booleanTexture$caseNumber SetThickness $thickness + + switch $caseNumber { + 0 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $solidTexture + eval booleanTexture$caseNumber SetOnIn $solidTexture + eval booleanTexture$caseNumber SetOnOut $solidTexture + eval booleanTexture$caseNumber SetInOn $solidTexture + eval booleanTexture$caseNumber SetOutOn $solidTexture + } + + 1 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $solidTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $solidTexture + } + + 2 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $solidTexture + eval booleanTexture$caseNumber SetInOn $solidTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + 3 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $clearTexture + eval booleanTexture$caseNumber SetOnOut $solidTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + 4 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $solidTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $solidTexture + } + + 5 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $clearTexture + eval booleanTexture$caseNumber SetOutOn $solidTexture + } + + 6 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + 7 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutOut $solidTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $clearTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $clearTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + 8 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $solidTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $solidTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + 9 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + 10 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $solidTexture + eval booleanTexture$caseNumber SetOutOn $clearTexture + } + + 11 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetInOut $solidTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $clearTexture + eval booleanTexture$caseNumber SetOnOut $edgeTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $clearTexture + } + + 12 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $solidTexture + eval booleanTexture$caseNumber SetOnOut $clearTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + 13 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutIn $solidTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $clearTexture + eval booleanTexture$caseNumber SetInOn $clearTexture + eval booleanTexture$caseNumber SetOutOn $edgeTexture + } + + + 14 { + eval booleanTexture$caseNumber SetInIn $solidTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $edgeTexture + eval booleanTexture$caseNumber SetOnIn $edgeTexture + eval booleanTexture$caseNumber SetOnOut $clearTexture + eval booleanTexture$caseNumber SetInOn $edgeTexture + eval booleanTexture$caseNumber SetOutOn $clearTexture + } + + 15 { + eval booleanTexture$caseNumber SetInIn $clearTexture + eval booleanTexture$caseNumber SetInOut $clearTexture + eval booleanTexture$caseNumber SetOutIn $clearTexture + eval booleanTexture$caseNumber SetOutOut $clearTexture + eval booleanTexture$caseNumber SetOnOn $clearTexture + eval booleanTexture$caseNumber SetOnIn $clearTexture + eval booleanTexture$caseNumber SetOnOut $clearTexture + eval booleanTexture$caseNumber SetInOn $clearTexture + eval booleanTexture$caseNumber SetOutOn $clearTexture + } + } + return booleanTexture$caseNumber +} + +set positions(0) "-4 4 0" +set positions(1) "-2 4 0" +set positions(2) "0 4 0" +set positions(3) "2 4 0" +set positions(4) "-4 2 0" +set positions(5) "-2 2 0" +set positions(6) "0 2 0" +set positions(7) "2 2 0" +set positions(8) "-4 0 0" +set positions(9) "-2 0 0" +set positions(10) "0 0 0" +set positions(11) "2 0 0" +set positions(12) "-4 -2 0" +set positions(13) "-2 -2 0" +set positions(14) "0 -2 0" +set positions(15) "2 -2 0" + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + + # define two elliptical cylinders +vtkQuadric quadric1 + quadric1 SetCoefficients 1 2 0 0 0 0 0 0 0 -.07 + +vtkQuadric quadric2 + quadric2 SetCoefficients 2 1 0 0 0 0 0 0 0 -.07 + + # create a sphere for all to use +vtkSphereSource aSphere + aSphere SetPhiResolution 50 + aSphere SetThetaResolution 50 + + # create texture coordianates for all +vtkImplicitTextureCoords tcoords + tcoords SetInputConnection [aSphere GetOutputPort] + tcoords SetRFunction quadric1 + tcoords SetSFunction quadric2 + +vtkDataSetMapper aMapper + aMapper SetInputConnection [tcoords GetOutputPort] + + # create a mapper, sphere and texture map for each case +for {set i 0} {$i < 16} {incr i} { + vtkTexture aTexture$i + aTexture$i SetInput [[eval makeBooleanTexture $i 256 1] GetOutput] + aTexture$i InterpolateOff + aTexture$i RepeatOff + vtkActor anActor$i + anActor$i SetMapper aMapper + anActor$i SetTexture aTexture$i + eval anActor$i SetPosition $positions($i) + anActor$i SetScale 2.0 2.0 2.0 + ren1 AddActor anActor$i + } + +ren1 SetBackground 0.4392 0.5020 0.5647 +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.4 +renWin SetSize 500 500 + +# interact with data +renWin Render + +#renWin SetFileName "quadricCut.tcl.ppm" +#renWin SaveImageAsPPM + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/rectGrid.tcl b/Graphics/Testing/Tcl/rectGrid.tcl new file mode 100644 index 0000000..fd2057a --- /dev/null +++ b/Graphics/Testing/Tcl/rectGrid.tcl @@ -0,0 +1,118 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +set VTK_VARY_RADIUS_BY_VECTOR 2 + +# create pipeline +# +vtkDataSetReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" + reader Update +vtkCastToConcrete toRectilinearGrid + toRectilinearGrid SetInputConnection [reader GetOutputPort] +vtkRectilinearGridGeometryFilter plane + plane SetInput [toRectilinearGrid GetRectilinearGridOutput] + plane SetExtent 0 100 0 100 15 15 +vtkWarpVector warper + warper SetInputConnection [plane GetOutputPort] + warper SetScaleFactor 0.05 +vtkDataSetMapper planeMapper + planeMapper SetInputConnection [warper GetOutputPort] + planeMapper SetScalarRange 0.197813 0.710419 +vtkActor planeActor + planeActor SetMapper planeMapper + +vtkPlane cutPlane + eval cutPlane SetOrigin [[reader GetOutput] GetCenter] + cutPlane SetNormal 1 0 0 +vtkCutter planeCut + planeCut SetInput [toRectilinearGrid GetRectilinearGridOutput] + planeCut SetCutFunction cutPlane +vtkDataSetMapper cutMapper + cutMapper SetInputConnection [planeCut GetOutputPort] + eval cutMapper SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor cutActor + cutActor SetMapper cutMapper + +vtkContourFilter iso + iso SetInput [toRectilinearGrid GetRectilinearGridOutput] + iso SetValue 0 0.7 +vtkPolyDataNormals normals + normals SetInputConnection [iso GetOutputPort] + normals SetFeatureAngle 45 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOff +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $bisque + eval [isoActor GetProperty] SetRepresentationToWireframe + +vtkStreamLine streamer + streamer SetInputConnection [reader GetOutputPort] + streamer SetStartPosition -1.2 -0.1 1.3 + streamer SetMaximumPropagationTime 500 + streamer SetStepLength 0.05 + streamer SetIntegrationStepLength 0.05 + streamer SetIntegrationDirectionToIntegrateBothDirections + +vtkTubeFilter streamTube + streamTube SetInputConnection [streamer GetOutputPort] + streamTube SetRadius 0.025 + streamTube SetNumberOfSides 6 + streamTube SetVaryRadius $VTK_VARY_RADIUS_BY_VECTOR +vtkPolyDataMapper mapStreamTube + mapStreamTube SetInputConnection [streamTube GetOutputPort] + eval mapStreamTube SetScalarRange \ + [[[[reader GetOutput] GetPointData] GetScalars] GetRange] +vtkActor streamTubeActor + streamTubeActor SetMapper mapStreamTube + [streamTubeActor GetProperty] BackfaceCullingOn + +vtkOutlineFilter outline + outline SetInput [toRectilinearGrid GetRectilinearGridOutput] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor $black + +# Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor planeActor +ren1 AddActor cutActor +ren1 AddActor isoActor +ren1 AddActor streamTubeActor + +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.76213 10.712 + $cam1 SetFocalPoint -0.0842503 -0.136905 0.610234 + $cam1 SetPosition 2.53813 2.2678 -5.22172 + $cam1 SetViewUp -0.241047 0.930635 0.275343 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/recursiveDC.tcl b/Graphics/Testing/Tcl/recursiveDC.tcl new file mode 100644 index 0000000..9f6c214 --- /dev/null +++ b/Graphics/Testing/Tcl/recursiveDC.tcl @@ -0,0 +1,60 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkStructuredPointsReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" +vtkRecursiveDividingCubes iso + iso SetInputConnection [reader GetOutputPort] + iso SetValue 128 + iso SetDistance .5 + iso SetIncrement 2 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [iso GetOutputPort] + isoMapper ScalarVisibilityOff + isoMapper ImmediateModeRenderingOn +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $bisque + +vtkOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor $black + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +renWin SetSize 250 250 +ren1 SetBackground 0.1 0.2 0.4 + +vtkCamera cam1 + cam1 SetClippingRange 19.1589 957.946 + cam1 SetFocalPoint 33.7014 26.706 30.5867 + cam1 SetPosition 150.841 89.374 -107.462 + cam1 SetViewUp -0.190015 0.944614 0.267578 + cam1 Dolly 3 +ren1 SetActiveCamera cam1 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/reverseNormals.tcl b/Graphics/Testing/Tcl/reverseNormals.tcl new file mode 100644 index 0000000..18d8f81 --- /dev/null +++ b/Graphics/Testing/Tcl/reverseNormals.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Now create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkOBJReader cowReader + cowReader SetFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.obj" + +vtkPlane plane + plane SetNormal 1 0 0 + +vtkClipPolyData cowClipper + cowClipper SetInputConnection [cowReader GetOutputPort] + cowClipper SetClipFunction plane + +vtkPolyDataNormals cellNormals + cellNormals SetInputConnection [cowClipper GetOutputPort] + cellNormals ComputePointNormalsOn + cellNormals ComputeCellNormalsOn + +vtkTransform reflect + reflect Scale -1 1 1 + +vtkTransformPolyDataFilter cowReflect + cowReflect SetTransform reflect + cowReflect SetInputConnection [cellNormals GetOutputPort] + +vtkReverseSense cowReverse + cowReverse SetInputConnection [cowReflect GetOutputPort] + cowReverse ReverseNormalsOn + cowReverse ReverseCellsOff + +vtkPolyDataMapper reflectedMapper + reflectedMapper SetInputConnection [cowReverse GetOutputPort] + +vtkActor reflected + reflected SetMapper reflectedMapper +eval [reflected GetProperty] SetDiffuseColor $flesh +[reflected GetProperty] SetDiffuse .8 +[reflected GetProperty] SetSpecular .5 +[reflected GetProperty] SetSpecularPower 30 +[reflected GetProperty] FrontfaceCullingOn + +ren1 AddActor reflected + +vtkPolyDataMapper cowMapper + cowMapper SetInputConnection [cowClipper GetOutputPort] + +vtkActor cow + cow SetMapper cowMapper + +ren1 AddActor cow + +ren1 SetBackground .1 .2 .4 +renWin SetSize 320 240 +ren1 ResetCamera +[ren1 GetActiveCamera] SetViewUp 0 1 0 +[ren1 GetActiveCamera] Azimuth 180 +[ren1 GetActiveCamera] Dolly 1.75 +ren1 ResetCameraClippingRange + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/scalarColors.tcl b/Graphics/Testing/Tcl/scalarColors.tcl new file mode 100644 index 0000000..92fefc9 --- /dev/null +++ b/Graphics/Testing/Tcl/scalarColors.tcl @@ -0,0 +1,100 @@ +package require vtk +package require vtkinteraction + +# Color points with scalars + +# get the interactor ui + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create some points with scalars + +vtkUnsignedCharArray colors + colors SetName "Colors" + colors SetNumberOfComponents 3 + colors SetNumberOfTuples 3 + colors InsertComponent 0 0 255 + colors InsertComponent 0 1 99 + colors InsertComponent 0 2 71 + + colors InsertComponent 1 0 125 + colors InsertComponent 1 1 255 + colors InsertComponent 1 2 0 + + colors InsertComponent 2 0 226 + colors InsertComponent 2 1 207 + colors InsertComponent 2 2 87 + +vtkUnsignedCharArray sizes + sizes SetName "Sizes" + sizes SetNumberOfComponents 1 + sizes SetNumberOfTuples 3 + sizes SetValue 0 1 + sizes SetValue 1 2 + sizes SetValue 2 3 + +vtkPoints polyVertexPoints + polyVertexPoints SetNumberOfPoints 3 + polyVertexPoints InsertPoint 0 0.0 0.0 0.0 + polyVertexPoints InsertPoint 1 2.5 0.0 0.0 + polyVertexPoints InsertPoint 2 5.0 0.0 0.0 + +vtkPolyVertex aPolyVertex + [aPolyVertex GetPointIds] SetNumberOfIds 3 + [aPolyVertex GetPointIds] SetId 0 0 + [aPolyVertex GetPointIds] SetId 1 1 + [aPolyVertex GetPointIds] SetId 2 2 + +vtkUnstructuredGrid aPolyVertexGrid + aPolyVertexGrid Allocate 1 1 + aPolyVertexGrid InsertNextCell [aPolyVertex GetCellType] [aPolyVertex GetPointIds] + aPolyVertexGrid SetPoints polyVertexPoints + [aPolyVertexGrid GetPointData] SetScalars sizes + [aPolyVertexGrid GetPointData] AddArray colors + +vtkSphereSource sphere + sphere SetRadius 1.0 + +vtkGlyph3D glyphs + glyphs ScalingOn + glyphs SetColorModeToColorByScalar + glyphs SetScaleModeToScaleByScalar + glyphs SetScaleFactor 1 + glyphs SetInput aPolyVertexGrid + glyphs SetSource [sphere GetOutput] + glyphs SetInputArrayToProcess 0 0 0 0 "Sizes" + glyphs SetInputArrayToProcess 3 0 0 0 "Colors" + +#puts [ glyphs GetScaleModeAsString] + +vtkDataSetMapper glyphsMapper + glyphsMapper SetInputConnection [glyphs GetOutputPort] + +vtkActor glyphsActor + glyphsActor SetMapper glyphsMapper + [glyphsActor GetProperty] BackfaceCullingOn + + +ren1 SetBackground .1 .2 .4 + +ren1 AddActor glyphsActor; [glyphsActor GetProperty] SetDiffuseColor 1 1 1 + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Dolly 1.25 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/scalarConn.tcl b/Graphics/Testing/Tcl/scalarConn.tcl new file mode 100644 index 0000000..390c273 --- /dev/null +++ b/Graphics/Testing/Tcl/scalarConn.tcl @@ -0,0 +1,68 @@ +package require vtk +package require vtkinteraction + +# Quadric definition +vtkQuadric quadric + quadric SetCoefficients .5 1 .2 0 .1 0 0 .2 0 0 + +vtkSampleFunction sample + sample SetSampleDimensions 30 30 30 + sample SetImplicitFunction quadric + sample Update + #sample Print + sample ComputeNormalsOff + +# Extract cells that contains isosurface of interest +vtkConnectivityFilter conn + conn SetInputConnection [sample GetOutputPort] + conn ScalarConnectivityOn + conn SetScalarRange 0.6 0.6 + conn SetExtractionModeToCellSeededRegions + conn AddSeed 105 + +# Create a surface +vtkContourFilter contours + contours SetInputConnection [conn GetOutputPort] +# contours SetInputConnection [sample GetOutputPort] + contours GenerateValues 5 0.0 1.2 + +vtkDataSetMapper contMapper +# contMapper SetInputConnection [contours GetOutputPort] + contMapper SetInputConnection [conn GetOutputPort] + contMapper SetScalarRange 0.0 1.2 + +vtkActor contActor + contActor SetMapper contMapper + +# Create outline +vtkOutlineFilter outline + outline SetInputConnection [sample GetOutputPort] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor 0 0 0 + +# Graphics +# create a window to render into +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + +# create a renderer + +# interactiver renderer catches mouse events (optional) +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 1 1 1 +ren1 AddActor contActor +ren1 AddActor outlineActor +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.4 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . diff --git a/Graphics/Testing/Tcl/schwarz.tcl b/Graphics/Testing/Tcl/schwarz.tcl new file mode 100644 index 0000000..c2ee560 --- /dev/null +++ b/Graphics/Testing/Tcl/schwarz.tcl @@ -0,0 +1,279 @@ +package require vtk +package require vtkinteraction + +vtkPoints points + points InsertNextPoint 2 4 0 + points InsertNextPoint 2.6 2.6 0 + points InsertNextPoint 4 2 0 + points InsertNextPoint 1.4 4 1.4 + points InsertNextPoint 2 3 1 + points InsertNextPoint 3 2 1 + points InsertNextPoint 4 1.4 1.4 + points InsertNextPoint 0 4 2 + points InsertNextPoint 1 3 2 + points InsertNextPoint 2 2 2 + points InsertNextPoint 3 1 2 + points InsertNextPoint 4 0 2 + points InsertNextPoint 0 2.6 2.6 + points InsertNextPoint 1 2 3 + points InsertNextPoint 2 1 3 + points InsertNextPoint 2.6 0 2.6 + points InsertNextPoint 0 2 4 + points InsertNextPoint 1.4 1.4 4 + points InsertNextPoint 2 0 4 + +vtkCellArray faces + faces InsertNextCell 3 + faces InsertCellPoint 0 + faces InsertCellPoint 3 + faces InsertCellPoint 4 + faces InsertNextCell 3 + faces InsertCellPoint 0 + faces InsertCellPoint 4 + faces InsertCellPoint 1 + faces InsertNextCell 3 + faces InsertCellPoint 1 + faces InsertCellPoint 4 + faces InsertCellPoint 5 + faces InsertNextCell 3 + faces InsertCellPoint 1 + faces InsertCellPoint 5 + faces InsertCellPoint 2 + faces InsertNextCell 3 + faces InsertCellPoint 2 + faces InsertCellPoint 5 + faces InsertCellPoint 6 + faces InsertNextCell 3 + faces InsertCellPoint 3 + faces InsertCellPoint 7 + faces InsertCellPoint 8 + faces InsertNextCell 3 + faces InsertCellPoint 3 + faces InsertCellPoint 8 + faces InsertCellPoint 4 + faces InsertNextCell 3 + faces InsertCellPoint 4 + faces InsertCellPoint 8 + faces InsertCellPoint 9 + faces InsertNextCell 3 + faces InsertCellPoint 4 + faces InsertCellPoint 9 + faces InsertCellPoint 5 + faces InsertNextCell 3 + faces InsertCellPoint 5 + faces InsertCellPoint 9 + faces InsertCellPoint 10 + faces InsertNextCell 3 + faces InsertCellPoint 5 + faces InsertCellPoint 10 + faces InsertCellPoint 6 + faces InsertNextCell 3 + faces InsertCellPoint 6 + faces InsertCellPoint 10 + faces InsertCellPoint 11 + faces InsertNextCell 3 + faces InsertCellPoint 7 + faces InsertCellPoint 12 + faces InsertCellPoint 8 + faces InsertNextCell 3 + faces InsertCellPoint 8 + faces InsertCellPoint 12 + faces InsertCellPoint 13 + faces InsertNextCell 3 + faces InsertCellPoint 8 + faces InsertCellPoint 13 + faces InsertCellPoint 9 + faces InsertNextCell 3 + faces InsertCellPoint 9 + faces InsertCellPoint 13 + faces InsertCellPoint 14 + faces InsertNextCell 3 + faces InsertCellPoint 9 + faces InsertCellPoint 14 + faces InsertCellPoint 10 + faces InsertNextCell 3 + faces InsertCellPoint 10 + faces InsertCellPoint 14 + faces InsertCellPoint 15 + faces InsertNextCell 3 + faces InsertCellPoint 10 + faces InsertCellPoint 15 + faces InsertCellPoint 11 + faces InsertNextCell 3 + faces InsertCellPoint 12 + faces InsertCellPoint 16 + faces InsertCellPoint 13 + faces InsertNextCell 3 + faces InsertCellPoint 13 + faces InsertCellPoint 16 + faces InsertCellPoint 17 + faces InsertNextCell 3 + faces InsertCellPoint 13 + faces InsertCellPoint 17 + faces InsertCellPoint 14 + faces InsertNextCell 3 + faces InsertCellPoint 14 + faces InsertCellPoint 17 + faces InsertCellPoint 18 + faces InsertNextCell 3 + faces InsertCellPoint 14 + faces InsertCellPoint 18 + faces InsertCellPoint 15 + +vtkPolyData model + model SetPolys faces + model SetPoints points + +vtkMath rn + +vtkUnsignedCharArray cellColors + cellColors SetNumberOfComponents 3 + cellColors SetNumberOfTuples [model GetNumberOfCells] +for { set i 0 } { $i < [model GetNumberOfCells] } { incr i } { + cellColors InsertComponent $i 0 [rn Random 100 255] + cellColors InsertComponent $i 1 [rn Random 100 255] + cellColors InsertComponent $i 2 [rn Random 100 255] +} + +[model GetCellData] SetScalars cellColors + +vtkTransform t0 + t0 Identity +vtkTransformPolyDataFilter tf0 + tf0 SetTransform t0 + tf0 SetInput model + +vtkTransform t1 + t1 Identity + t1 RotateZ 90 +vtkTransformPolyDataFilter tf1 + tf1 SetTransform t1 + tf1 SetInput model + +vtkTransform t2 + t2 Identity + t2 RotateZ 180 +vtkTransformPolyDataFilter tf2 + tf2 SetTransform t2 + tf2 SetInput model + +vtkTransform t3 + t3 Identity + t3 RotateZ 270 +vtkTransformPolyDataFilter tf3 + tf3 SetTransform t3 + tf3 SetInput model + +vtkAppendPolyData af + af AddInput [tf0 GetOutput] + af AddInput [tf1 GetOutput] + af AddInput [tf2 GetOutput] + af AddInput [tf3 GetOutput] + +vtkTransform t4 + t4 Identity + t4 RotateX 180 +vtkTransformPolyDataFilter tf4 + tf4 SetTransform t4 + tf4 SetInputConnection [af GetOutputPort] + +vtkAppendPolyData af2 + af2 AddInput [af GetOutput] + af2 AddInput [tf4 GetOutput] + +vtkTransform t5 + t5 Identity + t5 Translate 0 0 -8 +vtkTransformPolyDataFilter tf5 + tf5 SetTransform t5 + tf5 SetInputConnection [af2 GetOutputPort] + +vtkAppendPolyData af3 + af3 AddInput [af2 GetOutput] + af3 AddInput [tf5 GetOutput] + +vtkTransform t6 + t6 Identity + t6 Translate 0 -8 0 +vtkTransformPolyDataFilter tf6 + tf6 SetTransform t6 + tf6 SetInputConnection [af3 GetOutputPort] + +vtkAppendPolyData af4 + af4 AddInput [af3 GetOutput] + af4 AddInput [tf6 GetOutput] + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkCleanPolyData clean + clean SetTolerance .001 + clean SetInput model + clean SetInputConnection [af2 GetOutputPort] + clean SetInputConnection [af3 GetOutputPort] + clean SetInputConnection [af4 GetOutputPort] + +vtkButterflySubdivisionFilter subdivide + subdivide SetInputConnection [clean GetOutputPort] + subdivide SetNumberOfSubdivisions 3 + +vtkDataSetMapper mapper + mapper SetInputConnection [subdivide GetOutputPort] + +vtkActor surface + surface SetMapper mapper + +vtkFeatureEdges fe + fe SetInputConnection [subdivide GetOutputPort] + fe SetFeatureAngle 100 + +vtkStripper feStripper + feStripper SetInputConnection [fe GetOutputPort] + +vtkTubeFilter feTubes + feTubes SetInputConnection [feStripper GetOutputPort] + feTubes SetRadius .1 + +vtkPolyDataMapper feMapper + feMapper SetInputConnection [feTubes GetOutputPort] + +vtkActor edges + edges SetMapper feMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor surface +ren1 AddActor edges +vtkProperty backP + backP SetDiffuseColor 1 1 .3 +surface SetBackfaceProperty backP + +[edges GetProperty] SetDiffuseColor .2 .2 .2 +[surface GetProperty] SetDiffuseColor 1 .4 .3 +[surface GetProperty] SetSpecular .4 +[surface GetProperty] SetDiffuse .8 +[surface GetProperty] SetSpecularPower 40 + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Azimuth 90 +ren1 ResetCamera +$cam1 Zoom 1.5 +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/shepards.tcl b/Graphics/Testing/Tcl/shepards.tcl new file mode 100644 index 0000000..6308ecf --- /dev/null +++ b/Graphics/Testing/Tcl/shepards.tcl @@ -0,0 +1,71 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create some points +# +vtkMath math +vtkPoints points +for {set i 0} {$i<50} {incr i 1} { + eval points InsertPoint $i [math Random 0 1] [math Random 0 1] [math Random 0 1] +} + +vtkFloatArray scalars +for {set i 0} {$i<50} {incr i 1} { + eval scalars InsertValue $i [math Random 0 1] +} + +vtkPolyData profile + profile SetPoints points + [profile GetPointData] SetScalars scalars + +# triangulate them +# +vtkShepardMethod shepard + shepard SetInput profile + shepard SetModelBounds 0 1 0 1 .1 .5 +# shepard SetMaximumDistance .1 + shepard SetNullValue 1 + shepard SetSampleDimensions 20 20 20 + shepard Update + +vtkDataSetMapper map + map SetInputConnection [shepard GetOutputPort] + +vtkActor block + block SetMapper map + [block GetProperty] SetColor 1 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor block +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Azimuth 160 +$cam1 Elevation 30 +$cam1 Zoom 1.5 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +set threshold 15 + diff --git a/Graphics/Testing/Tcl/skinOrder.tcl b/Graphics/Testing/Tcl/skinOrder.tcl new file mode 100644 index 0000000..3e4571f --- /dev/null +++ b/Graphics/Testing/Tcl/skinOrder.tcl @@ -0,0 +1,76 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +source [file join [file dirname [info script]] SliceOrder.tcl] + +# Create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +set RESOLUTION 64 +set START_SLICE 50 +set END_SLICE 60 +set PIXEL_SIZE 3.2 +set centerX [expr ( $RESOLUTION / 2 )] +set centerY [expr ( $RESOLUTION / 2 )] +set centerZ [expr ( $END_SLICE - $START_SLICE ) / 2] +set endX [expr ( $RESOLUTION - 1 ) ] +set endY [expr ( $RESOLUTION - 1 ) ] +set endZ [expr ( $END_SLICE - 1 ) ] +set origin [expr ( $RESOLUTION / 2.0 ) * $PIXEL_SIZE * -1.0] + +vtkMath math + +set orders "ap pa si is lr rl" + +foreach order $orders { + vtkVolume16Reader reader$order + eval reader$order SetDataDimensions $RESOLUTION $RESOLUTION + reader$order SetFilePrefix $VTK_DATA_ROOT/Data/headsq/quarter + reader$order SetDataSpacing $PIXEL_SIZE $PIXEL_SIZE 1.5 + reader$order SetDataOrigin $origin $origin 1.5 + reader$order SetImageRange $START_SLICE $END_SLICE + reader$order SetTransform $order + reader$order SetHeaderSize 0 + reader$order SetDataMask 0x7fff; + reader$order SetDataByteOrderToLittleEndian + [reader$order GetOutput] ReleaseDataFlagOn + + vtkContourFilter iso$order + iso$order SetInputConnection [reader$order GetOutputPort] + iso$order SetValue 0 550.5 + iso$order ComputeScalarsOff + iso$order ReleaseDataFlagOn + + vtkPolyDataMapper mapper$order + mapper$order SetInputConnection [iso$order GetOutputPort] + mapper$order ImmediateModeRenderingOn + + vtkActor actor$order + actor$order SetMapper mapper$order + [actor$order GetProperty] SetDiffuseColor [math Random .5 1] [math Random .5 1] [math Random .5 1] + + ren1 AddActor actor$order +} + +renWin SetSize 300 300 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 210 +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +ren1 SetBackground .8 .8 .8 +iren Initialize; + +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract}; + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/smoothCyl.tcl b/Graphics/Testing/Tcl/smoothCyl.tcl new file mode 100644 index 0000000..9861eb3 --- /dev/null +++ b/Graphics/Testing/Tcl/smoothCyl.tcl @@ -0,0 +1,86 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a semi-cylinder +# +vtkLineSource line + line SetPoint1 0 1 0 + line SetPoint2 0 1 2 + line SetResolution 10 + +vtkRotationalExtrusionFilter lineSweeper + lineSweeper SetResolution 20 + lineSweeper SetInputConnection [line GetOutputPort] + lineSweeper SetAngle 270 + +vtkBrownianPoints bump + bump SetInputConnection [lineSweeper GetOutputPort] + +vtkWarpVector warp + warp SetInput [bump GetPolyDataOutput] + warp SetScaleFactor .2 + +vtkSmoothPolyDataFilter smooth + smooth SetInput [warp GetPolyDataOutput] + smooth SetNumberOfIterations 50 + smooth BoundarySmoothingOn + smooth SetFeatureAngle 120 + smooth SetEdgeAngle 90 + smooth SetRelaxationFactor .025 + +vtkPolyDataNormals normals + normals SetInputConnection [smooth GetOutputPort] + +vtkPolyDataMapper cylMapper + cylMapper SetInputConnection [normals GetOutputPort] + +vtkActor cylActor + cylActor SetMapper cylMapper + eval [cylActor GetProperty] SetInterpolationToGouraud + eval [cylActor GetProperty] SetInterpolationToFlat + eval [cylActor GetProperty] SetColor $beige + +vtkPolyDataMapper originalMapper + originalMapper SetInput [bump GetPolyDataOutput] + +vtkActor originalActor + originalActor SetMapper originalMapper + eval [originalActor GetProperty] SetInterpolationToFlat + eval [cylActor GetProperty] SetColor $tomato + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cylActor +#ren1 AddActor originalActor +ren1 SetBackground 1 1 1 +renWin SetSize 200 300 + +vtkCamera camera + camera SetClippingRange 0.576398 28.8199 + camera SetFocalPoint 0.0463079 -0.0356571 1.01993 + camera SetPosition -2.47044 2.39516 -3.56066 + camera SetViewUp 0.607296 -0.513537 -0.606195 +ren1 SetActiveCamera camera + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + diff --git a/Graphics/Testing/Tcl/smoothCyl2.tcl b/Graphics/Testing/Tcl/smoothCyl2.tcl new file mode 100644 index 0000000..a2181fb --- /dev/null +++ b/Graphics/Testing/Tcl/smoothCyl2.tcl @@ -0,0 +1,86 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a semi-cylinder +# +vtkLineSource line + line SetPoint1 0 1 0 + line SetPoint2 0 1 2 + line SetResolution 10 + +vtkRotationalExtrusionFilter lineSweeper + lineSweeper SetResolution 20 + lineSweeper SetInputConnection [line GetOutputPort] + lineSweeper SetAngle 270 + +vtkBrownianPoints bump + bump SetInputConnection [lineSweeper GetOutputPort] + +vtkWarpVector warp + warp SetInput [bump GetPolyDataOutput] + warp SetScaleFactor .2 + +vtkWindowedSincPolyDataFilter smooth + smooth SetInput [warp GetPolyDataOutput] + smooth SetNumberOfIterations 20 + smooth BoundarySmoothingOn + smooth SetFeatureAngle 120 + smooth SetEdgeAngle 90 + smooth SetPassBand 0.1 + +vtkPolyDataNormals normals + normals SetInputConnection [smooth GetOutputPort] + +vtkPolyDataMapper cylMapper + cylMapper SetInputConnection [normals GetOutputPort] + +vtkActor cylActor + cylActor SetMapper cylMapper + eval [cylActor GetProperty] SetInterpolationToGouraud + eval [cylActor GetProperty] SetInterpolationToFlat + eval [cylActor GetProperty] SetColor $beige + +vtkPolyDataMapper originalMapper + originalMapper SetInput [bump GetPolyDataOutput] + +vtkActor originalActor + originalActor SetMapper originalMapper + eval [originalActor GetProperty] SetInterpolationToFlat + eval [cylActor GetProperty] SetColor $tomato + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cylActor +#ren1 AddActor originalActor +ren1 SetBackground 1 1 1 +renWin SetSize 200 300 + +vtkCamera camera + camera SetClippingRange 0.576398 28.8199 + camera SetFocalPoint 0.0463079 -0.0356571 1.01993 + camera SetPosition -2.47044 2.39516 -3.56066 + camera SetViewUp 0.607296 -0.513537 -0.606195 +ren1 SetActiveCamera camera + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + diff --git a/Graphics/Testing/Tcl/smoothMeshOnMesh.tcl b/Graphics/Testing/Tcl/smoothMeshOnMesh.tcl new file mode 100644 index 0000000..1fa5f9e --- /dev/null +++ b/Graphics/Testing/Tcl/smoothMeshOnMesh.tcl @@ -0,0 +1,3569 @@ +package require vtk + +# this scripts reads in a surface, projects a mesh on the surface, and then +# smooths the mesh on the surface. In case you're wondering, it's fran's nose. + +# get the interactor ui + +# Read some data from a Cyberware scanner +# +vtkPolyDataReader cyber + cyber SetFileName "$VTK_DATA_ROOT/Data/fran_cut.vtk" + +# Create a patch by manual enumeration +vtkPoints pts +pts InsertNextPoint 0.0898212 -0.141201 -0.0543264 +pts InsertNextPoint 0.0899667 -0.140847 -0.0571981 +pts InsertNextPoint 0.0900662 -0.140508 -0.0600019 +pts InsertNextPoint 0.0898179 -0.140253 -0.0625551 +pts InsertNextPoint 0.0894205 -0.140035 -0.0649932 +pts InsertNextPoint 0.0894354 -0.139726 -0.0676513 +pts InsertNextPoint 0.0896324 -0.13938 -0.0703804 +pts InsertNextPoint 0.0896831 -0.139071 -0.0729911 +pts InsertNextPoint 0.0896528 -0.138783 -0.0755255 +pts InsertNextPoint 0.0890329 -0.138628 -0.07772 +pts InsertNextPoint 0.0880441 -0.138554 -0.079713 +pts InsertNextPoint 0.0869966 -0.138493 -0.0816747 +pts InsertNextPoint 0.0962548 -0.13623 -0.0886322 +pts InsertNextPoint 0.0996361 -0.135246 -0.092541 +pts InsertNextPoint 0.0826716 -0.13856 -0.0870153 +pts InsertNextPoint 0.0805636 -0.138719 -0.088519 +pts InsertNextPoint 0.0783242 -0.138903 -0.0899932 +pts InsertNextPoint 0.0758828 -0.139124 -0.0914127 +pts InsertNextPoint 0.0731464 -0.139402 -0.092747 +pts InsertNextPoint 0.0698455 -0.13979 -0.0939008 +pts InsertNextPoint 0.0658686 -0.140308 -0.0948519 +pts InsertNextPoint 0.0618506 -0.140826 -0.0958585 +pts InsertNextPoint 0.0580382 -0.141295 -0.0970088 +pts InsertNextPoint 0.0542195 -0.141758 -0.0982213 +pts InsertNextPoint 0.0517424 -0.14195 -0.0999432 +pts InsertNextPoint 0.0895673 -0.139582 -0.0543633 +pts InsertNextPoint 0.0896713 -0.139247 -0.0571809 +pts InsertNextPoint 0.0895717 -0.13896 -0.0598337 +pts InsertNextPoint 0.0891913 -0.138739 -0.0622839 +pts InsertNextPoint 0.0888944 -0.138501 -0.0647627 +pts InsertNextPoint 0.0890423 -0.138171 -0.0674778 +pts InsertNextPoint 0.0893555 -0.137809 -0.0702511 +pts InsertNextPoint 0.0896202 -0.137462 -0.0729575 +pts InsertNextPoint 0.0898311 -0.13713 -0.0755968 +pts InsertNextPoint 0.0901588 -0.136778 -0.078262 +pts InsertNextPoint 0.0958704 -0.135311 -0.0836493 +pts InsertNextPoint 0.102495 -0.133677 -0.0893072 +pts InsertNextPoint 0.102998 -0.133321 -0.0917862 +pts InsertNextPoint 0.10191 -0.133291 -0.0934747 +pts InsertNextPoint 0.100414 -0.133344 -0.0949797 +pts InsertNextPoint 0.0981196 -0.133555 -0.096143 +pts InsertNextPoint 0.0787119 -0.137165 -0.0899321 +pts InsertNextPoint 0.0760138 -0.137423 -0.0912127 +pts InsertNextPoint 0.0729729 -0.137744 -0.0923948 +pts InsertNextPoint 0.0696326 -0.138117 -0.0935077 +pts InsertNextPoint 0.0655273 -0.138632 -0.0943834 +pts InsertNextPoint 0.0619417 -0.139038 -0.095525 +pts InsertNextPoint 0.0581265 -0.139482 -0.0966439 +pts InsertNextPoint 0.0550065 -0.139787 -0.0980677 +pts InsertNextPoint 0.0524524 -0.13998 -0.0997275 +pts InsertNextPoint 0.0892589 -0.137975 -0.0543643 +pts InsertNextPoint 0.0892436 -0.137673 -0.0570789 +pts InsertNextPoint 0.0890252 -0.137418 -0.0596333 +pts InsertNextPoint 0.0885402 -0.137221 -0.0619982 +pts InsertNextPoint 0.0883384 -0.136968 -0.0645147 +pts InsertNextPoint 0.0886129 -0.136619 -0.0672834 +pts InsertNextPoint 0.0891757 -0.136215 -0.0701771 +pts InsertNextPoint 0.089491 -0.135867 -0.0728871 +pts InsertNextPoint 0.0902239 -0.135439 -0.0757843 +pts InsertNextPoint 0.0952174 -0.134163 -0.0808767 +pts InsertNextPoint 0.10257 -0.132436 -0.0870141 +pts InsertNextPoint 0.10505 -0.131695 -0.0904905 +pts InsertNextPoint 0.104427 -0.131573 -0.0923661 +pts InsertNextPoint 0.10324 -0.131562 -0.0939661 +pts InsertNextPoint 0.101982 -0.131564 -0.0955403 +pts InsertNextPoint 0.10033 -0.13164 -0.0969469 +pts InsertNextPoint 0.0970554 -0.132022 -0.097667 +pts InsertNextPoint 0.0763884 -0.135679 -0.091116 +pts InsertNextPoint 0.0728229 -0.136078 -0.0920519 +pts InsertNextPoint 0.0693026 -0.136462 -0.0930676 +pts InsertNextPoint 0.065117 -0.136962 -0.0938874 +pts InsertNextPoint 0.061751 -0.137304 -0.095087 +pts InsertNextPoint 0.0584943 -0.13762 -0.0963801 +pts InsertNextPoint 0.0556668 -0.137852 -0.0978732 +pts InsertNextPoint 0.0531444 -0.138026 -0.0995086 +pts InsertNextPoint 0.0889303 -0.13637 -0.0543522 +pts InsertNextPoint 0.0887258 -0.136113 -0.0569194 +pts InsertNextPoint 0.0884949 -0.135865 -0.0594436 +pts InsertNextPoint 0.0880983 -0.135654 -0.0618411 +pts InsertNextPoint 0.0879921 -0.135386 -0.0643923 +pts InsertNextPoint 0.0882446 -0.135051 -0.0671246 +pts InsertNextPoint 0.0886638 -0.134687 -0.0699141 +pts InsertNextPoint 0.0893645 -0.134273 -0.0728182 +pts InsertNextPoint 0.0934928 -0.133203 -0.0775275 +pts InsertNextPoint 0.101566 -0.131394 -0.0841743 +pts InsertNextPoint 0.10542 -0.130413 -0.0884076 +pts InsertNextPoint 0.105793 -0.130102 -0.0907705 +pts InsertNextPoint 0.105129 -0.129989 -0.0925939 +pts InsertNextPoint 0.104082 -0.129948 -0.0942287 +pts InsertNextPoint 0.102808 -0.129949 -0.0957624 +pts InsertNextPoint 0.101434 -0.129966 -0.0972601 +pts InsertNextPoint 0.09965 -0.130057 -0.0985905 +pts InsertNextPoint 0.0946529 -0.130724 -0.098584 +pts InsertNextPoint 0.0729091 -0.134368 -0.0918056 +pts InsertNextPoint 0.0690177 -0.134794 -0.0926445 +pts InsertNextPoint 0.0648858 -0.135255 -0.0934591 +pts InsertNextPoint 0.0616261 -0.135555 -0.094673 +pts InsertNextPoint 0.0588847 -0.13576 -0.0961258 +pts InsertNextPoint 0.0561992 -0.135951 -0.0976364 +pts InsertNextPoint 0.0537512 -0.136097 -0.0992637 +pts InsertNextPoint 0.0887181 -0.13474 -0.0544167 +pts InsertNextPoint 0.0883955 -0.134512 -0.0568807 +pts InsertNextPoint 0.0881582 -0.13427 -0.0593756 +pts InsertNextPoint 0.0876732 -0.134078 -0.0616947 +pts InsertNextPoint 0.0875346 -0.133822 -0.0642036 +pts InsertNextPoint 0.0880362 -0.133448 -0.0670592 +pts InsertNextPoint 0.0883204 -0.13312 -0.0697472 +pts InsertNextPoint 0.0904604 -0.132452 -0.0734275 +pts InsertNextPoint 0.100819 -0.130282 -0.0814667 +pts InsertNextPoint 0.104537 -0.129357 -0.0856942 +pts InsertNextPoint 0.106004 -0.128853 -0.0886386 +pts InsertNextPoint 0.106138 -0.128596 -0.0908521 +pts InsertNextPoint 0.105576 -0.128465 -0.0926982 +pts InsertNextPoint 0.104573 -0.128413 -0.094326 +pts InsertNextPoint 0.103314 -0.128406 -0.0958379 +pts InsertNextPoint 0.102022 -0.128403 -0.0973437 +pts InsertNextPoint 0.100317 -0.128471 -0.098679 +pts InsertNextPoint 0.0978606 -0.128665 -0.0997148 +pts InsertNextPoint 0.0915907 -0.129503 -0.0992178 +pts InsertNextPoint 0.0689604 -0.133084 -0.0923117 +pts InsertNextPoint 0.064735 -0.13353 -0.0930614 +pts InsertNextPoint 0.0615331 -0.133799 -0.0942706 +pts InsertNextPoint 0.0589916 -0.133953 -0.0957698 +pts InsertNextPoint 0.0566751 -0.134067 -0.0973817 +pts InsertNextPoint 0.0543147 -0.134185 -0.0990064 +pts InsertNextPoint 0.0885913 -0.133094 -0.0545371 +pts InsertNextPoint 0.0882526 -0.132873 -0.056962 +pts InsertNextPoint 0.0877571 -0.132683 -0.0592676 +pts InsertNextPoint 0.0872004 -0.132507 -0.0615193 +pts InsertNextPoint 0.0872035 -0.13223 -0.0640906 +pts InsertNextPoint 0.0877778 -0.131855 -0.0669647 +pts InsertNextPoint 0.0966322 -0.130011 -0.074501 +pts InsertNextPoint 0.101132 -0.128966 -0.0793491 +pts InsertNextPoint 0.103162 -0.128367 -0.0827118 +pts InsertNextPoint 0.105295 -0.12776 -0.0860482 +pts InsertNextPoint 0.106134 -0.127384 -0.0886371 +pts InsertNextPoint 0.106268 -0.127133 -0.0908265 +pts InsertNextPoint 0.105833 -0.126982 -0.0927112 +pts InsertNextPoint 0.104782 -0.126935 -0.0942906 +pts InsertNextPoint 0.103545 -0.126919 -0.0957877 +pts InsertNextPoint 0.102274 -0.126907 -0.0972781 +pts InsertNextPoint 0.100614 -0.126958 -0.0986071 +pts InsertNextPoint 0.0985164 -0.127078 -0.0997685 +pts InsertNextPoint 0.0944886 -0.127506 -0.100161 +pts InsertNextPoint 0.0871121 -0.128462 -0.0992849 +pts InsertNextPoint 0.0647841 -0.131772 -0.092741 +pts InsertNextPoint 0.0616161 -0.132013 -0.0939343 +pts InsertNextPoint 0.0589983 -0.132164 -0.0953776 +pts InsertNextPoint 0.0568177 -0.132243 -0.0970109 +pts InsertNextPoint 0.0547602 -0.132301 -0.098711 +pts InsertNextPoint 0.0885342 -0.131438 -0.0547028 +pts InsertNextPoint 0.0880497 -0.131246 -0.0570049 +pts InsertNextPoint 0.087496 -0.131069 -0.0592473 +pts InsertNextPoint 0.0887446 -0.130581 -0.062575 +pts InsertNextPoint 0.0956884 -0.129122 -0.0692327 +pts InsertNextPoint 0.0975384 -0.128554 -0.0727027 +pts InsertNextPoint 0.0993698 -0.127997 -0.076084 +pts InsertNextPoint 0.101319 -0.127428 -0.0794544 +pts InsertNextPoint 0.10332 -0.12686 -0.082774 +pts InsertNextPoint 0.10522 -0.126316 -0.0859625 +pts InsertNextPoint 0.105997 -0.125963 -0.0884982 +pts InsertNextPoint 0.106162 -0.125713 -0.0906827 +pts InsertNextPoint 0.105705 -0.125567 -0.0925359 +pts InsertNextPoint 0.104638 -0.125518 -0.094087 +pts InsertNextPoint 0.103442 -0.125489 -0.0955831 +pts InsertNextPoint 0.1022 -0.125467 -0.0970657 +pts InsertNextPoint 0.100628 -0.125495 -0.0984116 +pts InsertNextPoint 0.0985777 -0.125595 -0.0995704 +pts InsertNextPoint 0.0950356 -0.125919 -0.100138 +pts InsertNextPoint 0.0890071 -0.126613 -0.0997667 +pts InsertNextPoint 0.0822873 -0.127397 -0.0992456 +pts InsertNextPoint 0.0616611 -0.130235 -0.0935839 +pts InsertNextPoint 0.0590303 -0.130371 -0.0949946 +pts InsertNextPoint 0.0570259 -0.130412 -0.0966639 +pts InsertNextPoint 0.0553267 -0.130406 -0.0984591 +pts InsertNextPoint 0.0883465 -0.129807 -0.054783 +pts InsertNextPoint 0.0879283 -0.129606 -0.0570999 +pts InsertNextPoint 0.087219 -0.129456 -0.0592172 +pts InsertNextPoint 0.0944916 -0.127998 -0.0661902 +pts InsertNextPoint 0.0965781 -0.127407 -0.0698429 +pts InsertNextPoint 0.0979208 -0.126945 -0.072978 +pts InsertNextPoint 0.0993564 -0.126474 -0.0761028 +pts InsertNextPoint 0.101101 -0.125961 -0.0793343 +pts InsertNextPoint 0.102995 -0.125433 -0.0825754 +pts InsertNextPoint 0.104877 -0.124914 -0.0857354 +pts InsertNextPoint 0.1057 -0.124565 -0.0882767 +pts InsertNextPoint 0.105786 -0.124334 -0.0904033 +pts InsertNextPoint 0.105247 -0.124201 -0.0921987 +pts InsertNextPoint 0.104196 -0.124145 -0.0937416 +pts InsertNextPoint 0.103122 -0.124092 -0.0952776 +pts InsertNextPoint 0.101967 -0.124051 -0.0967813 +pts InsertNextPoint 0.100469 -0.124059 -0.0981404 +pts InsertNextPoint 0.09849 -0.124135 -0.0993087 +pts InsertNextPoint 0.09527 -0.124387 -0.0999862 +pts InsertNextPoint 0.0888882 -0.125084 -0.0994401 +pts InsertNextPoint 0.0833452 -0.125649 -0.099351 +pts InsertNextPoint 0.0775917 -0.126232 -0.0992881 +pts InsertNextPoint 0.0592747 -0.12855 -0.0946904 +pts InsertNextPoint 0.0573001 -0.128575 -0.0963413 +pts InsertNextPoint 0.0558052 -0.128533 -0.098179 +pts InsertNextPoint 0.0883754 -0.128142 -0.055004 +pts InsertNextPoint 0.0877421 -0.127978 -0.0571533 +pts InsertNextPoint 0.0892883 -0.127475 -0.0606485 +pts InsertNextPoint 0.0956621 -0.126232 -0.0670114 +pts InsertNextPoint 0.096559 -0.12585 -0.0699114 +pts InsertNextPoint 0.0975451 -0.12546 -0.0728122 +pts InsertNextPoint 0.0985432 -0.125074 -0.0756673 +pts InsertNextPoint 0.100126 -0.124606 -0.0787949 +pts InsertNextPoint 0.102546 -0.12402 -0.0823091 +pts InsertNextPoint 0.104363 -0.123532 -0.0854175 +pts InsertNextPoint 0.105313 -0.123178 -0.0880087 +pts InsertNextPoint 0.105321 -0.122963 -0.0900789 +pts InsertNextPoint 0.104784 -0.122829 -0.0918591 +pts InsertNextPoint 0.103798 -0.122759 -0.0934161 +pts InsertNextPoint 0.102638 -0.122713 -0.0948947 +pts InsertNextPoint 0.10151 -0.122662 -0.096395 +pts InsertNextPoint 0.100085 -0.122651 -0.0977698 +pts InsertNextPoint 0.0981897 -0.122703 -0.0989557 +pts InsertNextPoint 0.0950281 -0.122924 -0.0996365 +pts InsertNextPoint 0.0871054 -0.123776 -0.0984377 +pts InsertNextPoint 0.0821806 -0.124214 -0.0985836 +pts InsertNextPoint 0.0776877 -0.124586 -0.098986 +pts InsertNextPoint 0.0594417 -0.126742 -0.0943582 +pts InsertNextPoint 0.0576309 -0.126735 -0.0960403 +pts InsertNextPoint 0.056527 -0.126636 -0.0979857 +pts InsertNextPoint 0.0883342 -0.126492 -0.055179 +pts InsertNextPoint 0.0875258 -0.126355 -0.0571875 +pts InsertNextPoint 0.0912843 -0.125547 -0.0620307 +pts InsertNextPoint 0.0951903 -0.12473 -0.066832 +pts InsertNextPoint 0.0960468 -0.124368 -0.0696865 +pts InsertNextPoint 0.0965605 -0.124059 -0.0722926 +pts InsertNextPoint 0.0972562 -0.123729 -0.0749629 +pts InsertNextPoint 0.0988733 -0.123274 -0.078101 +pts InsertNextPoint 0.10106 -0.122746 -0.081481 +pts InsertNextPoint 0.103964 -0.122128 -0.0851606 +pts InsertNextPoint 0.104718 -0.121813 -0.0876328 +pts InsertNextPoint 0.104736 -0.121602 -0.0896932 +pts InsertNextPoint 0.104086 -0.121482 -0.0914032 +pts InsertNextPoint 0.103133 -0.121403 -0.0929626 +pts InsertNextPoint 0.102034 -0.121343 -0.0944555 +pts InsertNextPoint 0.100863 -0.121291 -0.0959213 +pts InsertNextPoint 0.099489 -0.121265 -0.0973044 +pts InsertNextPoint 0.097493 -0.121318 -0.0984312 +pts InsertNextPoint 0.0939277 -0.121566 -0.0989264 +pts InsertNextPoint 0.0848718 -0.122495 -0.0972463 +pts InsertNextPoint 0.0805925 -0.122812 -0.0976446 +pts InsertNextPoint 0.0762928 -0.123125 -0.0981108 +pts InsertNextPoint 0.0598456 -0.124909 -0.0941152 +pts InsertNextPoint 0.058236 -0.124868 -0.0958399 +pts InsertNextPoint 0.0572795 -0.124747 -0.0978062 +pts InsertNextPoint 0.0884305 -0.124826 -0.0554427 +pts InsertNextPoint 0.0877166 -0.124675 -0.0574802 +pts InsertNextPoint 0.0914562 -0.12391 -0.0622761 +pts InsertNextPoint 0.0945191 -0.123251 -0.0665317 +pts InsertNextPoint 0.0949038 -0.122964 -0.069087 +pts InsertNextPoint 0.0954918 -0.122655 -0.0717246 +pts InsertNextPoint 0.0960524 -0.122352 -0.0743061 +pts InsertNextPoint 0.0975213 -0.121935 -0.0773522 +pts InsertNextPoint 0.0996491 -0.121438 -0.0806935 +pts InsertNextPoint 0.103362 -0.120745 -0.0847955 +pts InsertNextPoint 0.104032 -0.120452 -0.0872099 +pts InsertNextPoint 0.104048 -0.120245 -0.0892555 +pts InsertNextPoint 0.103483 -0.120112 -0.0909934 +pts InsertNextPoint 0.10254 -0.120027 -0.0925425 +pts InsertNextPoint 0.10156 -0.119947 -0.0940762 +pts InsertNextPoint 0.100276 -0.119903 -0.095474 +pts InsertNextPoint 0.0988374 -0.119877 -0.0968131 +pts InsertNextPoint 0.0967143 -0.11993 -0.0978696 +pts InsertNextPoint 0.0925188 -0.120225 -0.0980835 +pts InsertNextPoint 0.0824897 -0.121192 -0.0959872 +pts InsertNextPoint 0.0784544 -0.121447 -0.0964817 +pts InsertNextPoint 0.0728627 -0.121872 -0.096444 +pts InsertNextPoint 0.0605779 -0.123045 -0.093997 +pts InsertNextPoint 0.0590068 -0.122992 -0.0957022 +pts InsertNextPoint 0.0582441 -0.122848 -0.0977047 +pts InsertNextPoint 0.0886002 -0.123157 -0.0557533 +pts InsertNextPoint 0.088019 -0.122988 -0.057843 +pts InsertNextPoint 0.0896799 -0.122531 -0.0613123 +pts InsertNextPoint 0.0926237 -0.121918 -0.0654889 +pts InsertNextPoint 0.0934978 -0.121577 -0.0683323 +pts InsertNextPoint 0.0934952 -0.121349 -0.0706185 +pts InsertNextPoint 0.0943033 -0.121024 -0.0733401 +pts InsertNextPoint 0.0952207 -0.12069 -0.0760772 +pts InsertNextPoint 0.098867 -0.120031 -0.0802462 +pts InsertNextPoint 0.102457 -0.11939 -0.0842706 +pts InsertNextPoint 0.10342 -0.119071 -0.0868246 +pts InsertNextPoint 0.103372 -0.118875 -0.0888228 +pts InsertNextPoint 0.10289 -0.118732 -0.0905877 +pts InsertNextPoint 0.102055 -0.11863 -0.0921735 +pts InsertNextPoint 0.100962 -0.118558 -0.0936377 +pts InsertNextPoint 0.0996979 -0.118504 -0.0950296 +pts InsertNextPoint 0.0980846 -0.118489 -0.0962752 +pts InsertNextPoint 0.0958862 -0.118536 -0.0972846 +pts InsertNextPoint 0.0902128 -0.118959 -0.0968581 +pts InsertNextPoint 0.0800089 -0.11986 -0.0946802 +pts InsertNextPoint 0.0756185 -0.12012 -0.095033 +pts InsertNextPoint 0.0654384 -0.120983 -0.0932143 +pts InsertNextPoint 0.0616571 -0.121158 -0.0940124 +pts InsertNextPoint 0.0599775 -0.121108 -0.0956409 +pts InsertNextPoint 0.0591664 -0.120969 -0.0975922 +pts InsertNextPoint 0.0889457 -0.121473 -0.0561767 +pts InsertNextPoint 0.0881444 -0.121332 -0.0580927 +pts InsertNextPoint 0.0880075 -0.121111 -0.0604153 +pts InsertNextPoint 0.0900535 -0.120634 -0.0640391 +pts InsertNextPoint 0.0905522 -0.120347 -0.0666654 +pts InsertNextPoint 0.0907897 -0.120093 -0.0691021 +pts InsertNextPoint 0.0925286 -0.11967 -0.0723601 +pts InsertNextPoint 0.0941482 -0.119268 -0.0754835 +pts InsertNextPoint 0.0982613 -0.118592 -0.0798945 +pts InsertNextPoint 0.101635 -0.118011 -0.0837882 +pts InsertNextPoint 0.102551 -0.11771 -0.0863057 +pts InsertNextPoint 0.102647 -0.117501 -0.0883651 +pts InsertNextPoint 0.102326 -0.11734 -0.0901958 +pts InsertNextPoint 0.101605 -0.117223 -0.091821 +pts InsertNextPoint 0.100564 -0.117139 -0.0932925 +pts InsertNextPoint 0.0992053 -0.117088 -0.0946232 +pts InsertNextPoint 0.0974141 -0.11708 -0.0957724 +pts InsertNextPoint 0.0948733 -0.117146 -0.0966172 +pts InsertNextPoint 0.0878169 -0.117662 -0.0955882 +pts InsertNextPoint 0.0774655 -0.118491 -0.0933398 +pts InsertNextPoint 0.0724544 -0.118776 -0.0934432 +pts InsertNextPoint 0.0655845 -0.119232 -0.0929109 +pts InsertNextPoint 0.0626006 -0.119302 -0.0939805 +pts InsertNextPoint 0.0610374 -0.119233 -0.0956161 +pts InsertNextPoint 0.0599403 -0.119119 -0.0974303 +pts InsertNextPoint 0.0890914 -0.119822 -0.0564699 +pts InsertNextPoint 0.0881962 -0.11969 -0.0582952 +pts InsertNextPoint 0.0877971 -0.119502 -0.0604254 +pts InsertNextPoint 0.087792 -0.119274 -0.0627792 +pts InsertNextPoint 0.0886635 -0.118953 -0.0656275 +pts InsertNextPoint 0.0895523 -0.118634 -0.0684388 +pts InsertNextPoint 0.091024 -0.118259 -0.0715338 +pts InsertNextPoint 0.0934527 -0.117789 -0.0750989 +pts InsertNextPoint 0.0979718 -0.117113 -0.0797141 +pts InsertNextPoint 0.100749 -0.116626 -0.0832721 +pts InsertNextPoint 0.101765 -0.116326 -0.0858295 +pts InsertNextPoint 0.101945 -0.116114 -0.0879181 +pts InsertNextPoint 0.10174 -0.115942 -0.089792 +pts InsertNextPoint 0.101075 -0.115816 -0.0914288 +pts InsertNextPoint 0.100073 -0.115723 -0.0929029 +pts InsertNextPoint 0.098635 -0.115671 -0.0941801 +pts InsertNextPoint 0.0967003 -0.115665 -0.0952488 +pts InsertNextPoint 0.0938784 -0.115738 -0.0959551 +pts InsertNextPoint 0.0855002 -0.116317 -0.094345 +pts InsertNextPoint 0.0763311 -0.116952 -0.0925745 +pts InsertNextPoint 0.0710751 -0.117218 -0.0925617 +pts InsertNextPoint 0.0661254 -0.117448 -0.0927628 +pts InsertNextPoint 0.0634995 -0.117466 -0.0939351 +pts InsertNextPoint 0.0619461 -0.117388 -0.0955397 +pts InsertNextPoint 0.0605929 -0.117292 -0.097228 +pts InsertNextPoint 0.0890592 -0.118197 -0.0566475 +pts InsertNextPoint 0.0882458 -0.118053 -0.0584958 +pts InsertNextPoint 0.0875824 -0.117894 -0.0604329 +pts InsertNextPoint 0.0874223 -0.117686 -0.0626667 +pts InsertNextPoint 0.0877951 -0.117426 -0.0651956 +pts InsertNextPoint 0.0888083 -0.117108 -0.0680621 +pts InsertNextPoint 0.0903993 -0.116738 -0.0712069 +pts InsertNextPoint 0.0933385 -0.116246 -0.0750368 +pts InsertNextPoint 0.0972461 -0.115671 -0.0792971 +pts InsertNextPoint 0.0996133 -0.115251 -0.0826233 +pts InsertNextPoint 0.100921 -0.114936 -0.0853224 +pts InsertNextPoint 0.101156 -0.114724 -0.0874263 +pts InsertNextPoint 0.100916 -0.114556 -0.08927 +pts InsertNextPoint 0.100342 -0.11442 -0.090938 +pts InsertNextPoint 0.0994054 -0.114315 -0.0924289 +pts InsertNextPoint 0.0980113 -0.11425 -0.0937114 +pts InsertNextPoint 0.0958238 -0.114252 -0.0946505 +pts InsertNextPoint 0.0925364 -0.114343 -0.0951386 +pts InsertNextPoint 0.0836062 -0.114898 -0.0932755 +pts InsertNextPoint 0.0761611 -0.115314 -0.0922063 +pts InsertNextPoint 0.0708212 -0.115545 -0.0921308 +pts InsertNextPoint 0.0667141 -0.115669 -0.0926354 +pts InsertNextPoint 0.0642784 -0.115655 -0.0938472 +pts InsertNextPoint 0.0624853 -0.115588 -0.0953292 +pts InsertNextPoint 0.0606927 -0.115519 -0.0968284 +pts InsertNextPoint 0.0888599 -0.11659 -0.0567173 +pts InsertNextPoint 0.0882013 -0.116429 -0.0586367 +pts InsertNextPoint 0.0872944 -0.116292 -0.0603951 +pts InsertNextPoint 0.0868801 -0.11611 -0.0624501 +pts InsertNextPoint 0.0872886 -0.115855 -0.0649786 +pts InsertNextPoint 0.0881464 -0.115564 -0.0677333 +pts InsertNextPoint 0.0898868 -0.115199 -0.0709439 +pts InsertNextPoint 0.0924604 -0.114768 -0.074551 +pts InsertNextPoint 0.0961746 -0.114248 -0.0786922 +pts InsertNextPoint 0.0984617 -0.113859 -0.0819653 +pts InsertNextPoint 0.100087 -0.113532 -0.0848202 +pts InsertNextPoint 0.100338 -0.113324 -0.0869192 +pts InsertNextPoint 0.100094 -0.113157 -0.0887478 +pts InsertNextPoint 0.0995495 -0.113016 -0.0904174 +pts InsertNextPoint 0.0985852 -0.112909 -0.0918818 +pts InsertNextPoint 0.0969324 -0.112855 -0.0930317 +pts InsertNextPoint 0.0945455 -0.112856 -0.0938696 +pts InsertNextPoint 0.0901107 -0.113007 -0.0938434 +pts InsertNextPoint 0.081019 -0.113498 -0.0919041 +pts InsertNextPoint 0.0759758 -0.113674 -0.0918312 +pts InsertNextPoint 0.0704773 -0.113876 -0.0916625 +pts InsertNextPoint 0.0668396 -0.113934 -0.092327 +pts InsertNextPoint 0.0643551 -0.113907 -0.093492 +pts InsertNextPoint 0.0621302 -0.113858 -0.094786 +pts InsertNextPoint 0.06008 -0.113795 -0.0961697 +pts InsertNextPoint 0.0882938 -0.115016 -0.0565514 +pts InsertNextPoint 0.0879397 -0.114828 -0.0586406 +pts InsertNextPoint 0.087037 -0.114686 -0.0603763 +pts InsertNextPoint 0.0864387 -0.11452 -0.0622949 +pts InsertNextPoint 0.0864531 -0.114305 -0.0645673 +pts InsertNextPoint 0.0874847 -0.114011 -0.067405 +pts InsertNextPoint 0.0890558 -0.113679 -0.0705003 +pts InsertNextPoint 0.0918449 -0.113258 -0.0742108 +pts InsertNextPoint 0.0952927 -0.112795 -0.07819 +pts InsertNextPoint 0.0972979 -0.11245 -0.0813002 +pts InsertNextPoint 0.0987547 -0.112153 -0.0840582 +pts InsertNextPoint 0.0993609 -0.111923 -0.0863307 +pts InsertNextPoint 0.0992112 -0.11175 -0.0881948 +pts InsertNextPoint 0.0986349 -0.111609 -0.0898365 +pts InsertNextPoint 0.0976817 -0.111496 -0.0912939 +pts InsertNextPoint 0.0960021 -0.111432 -0.0924184 +pts InsertNextPoint 0.0934462 -0.111426 -0.0931665 +pts InsertNextPoint 0.0884574 -0.111578 -0.0928817 +pts InsertNextPoint 0.0796282 -0.111975 -0.0910388 +pts InsertNextPoint 0.0744007 -0.112123 -0.0908742 +pts InsertNextPoint 0.0693799 -0.112248 -0.0908859 +pts InsertNextPoint 0.066155 -0.112253 -0.0916973 +pts InsertNextPoint 0.0632416 -0.112234 -0.0926768 +pts InsertNextPoint 0.060733 -0.112186 -0.0938492 +pts InsertNextPoint 0.0586257 -0.112111 -0.0952002 +pts InsertNextPoint 0.0871203 -0.113482 -0.055997 +pts InsertNextPoint 0.0870465 -0.113273 -0.0582477 +pts InsertNextPoint 0.0863129 -0.113114 -0.0600703 +pts InsertNextPoint 0.0855783 -0.112956 -0.0618872 +pts InsertNextPoint 0.0854363 -0.112756 -0.0640494 +pts InsertNextPoint 0.0862355 -0.112491 -0.0667369 +pts InsertNextPoint 0.0877491 -0.112179 -0.0697875 +pts InsertNextPoint 0.09066 -0.111778 -0.0735548 +pts InsertNextPoint 0.0938534 -0.111365 -0.077385 +pts InsertNextPoint 0.0959943 -0.111032 -0.0805603 +pts InsertNextPoint 0.0972028 -0.110766 -0.0831814 +pts InsertNextPoint 0.0982906 -0.110512 -0.0856937 +pts InsertNextPoint 0.0982302 -0.110335 -0.0875917 +pts InsertNextPoint 0.0976649 -0.110191 -0.0892272 +pts InsertNextPoint 0.096652 -0.110075 -0.0906446 +pts InsertNextPoint 0.0948284 -0.110008 -0.0916906 +pts InsertNextPoint 0.0923762 -0.109976 -0.0924741 +pts InsertNextPoint 0.0871852 -0.110099 -0.092084 +pts InsertNextPoint 0.0770207 -0.110498 -0.0896458 +pts InsertNextPoint 0.0708414 -0.110655 -0.0890791 +pts InsertNextPoint 0.0674992 -0.110645 -0.089785 +pts InsertNextPoint 0.0637733 -0.110651 -0.0903882 +pts InsertNextPoint 0.0611852 -0.110591 -0.091491 +pts InsertNextPoint 0.0591087 -0.110501 -0.0928208 +pts InsertNextPoint 0.0571082 -0.110406 -0.0942012 +pts InsertNextPoint 0.0860098 -0.111927 -0.0554849 +pts InsertNextPoint 0.0856644 -0.111738 -0.0575493 +pts InsertNextPoint 0.0848174 -0.111583 -0.0592906 +pts InsertNextPoint 0.0838904 -0.111434 -0.0609816 +pts InsertNextPoint 0.084211 -0.111205 -0.0634091 +pts InsertNextPoint 0.0849887 -0.110951 -0.0660709 +pts InsertNextPoint 0.0862012 -0.110675 -0.0689383 +pts InsertNextPoint 0.0897738 -0.110261 -0.0730645 +pts InsertNextPoint 0.0922552 -0.109922 -0.0764933 +pts InsertNextPoint 0.0946147 -0.109597 -0.0797794 +pts InsertNextPoint 0.0962195 -0.109321 -0.082599 +pts InsertNextPoint 0.0968494 -0.109105 -0.084867 +pts InsertNextPoint 0.0969284 -0.108922 -0.0868279 +pts InsertNextPoint 0.09651 -0.108767 -0.0885267 +pts InsertNextPoint 0.0955002 -0.108645 -0.0899355 +pts InsertNextPoint 0.0939411 -0.10855 -0.0910933 +pts InsertNextPoint 0.0912255 -0.108512 -0.0917427 +pts InsertNextPoint 0.0868029 -0.108555 -0.0916769 +pts InsertNextPoint 0.0747477 -0.108961 -0.0883899 +pts InsertNextPoint 0.0695532 -0.109019 -0.0882303 +pts InsertNextPoint 0.0663324 -0.108977 -0.0889714 +pts InsertNextPoint 0.0626822 -0.10895 -0.0895878 +pts InsertNextPoint 0.0600727 -0.108872 -0.090666 +pts InsertNextPoint 0.0575584 -0.108786 -0.0918141 +pts InsertNextPoint 0.0553563 -0.108684 -0.093109 +pts InsertNextPoint 0.0851261 -0.110342 -0.0551197 +pts InsertNextPoint 0.0847313 -0.110156 -0.0571345 +pts InsertNextPoint 0.0839991 -0.10999 -0.0589289 +pts InsertNextPoint 0.0833032 -0.109823 -0.0607405 +pts InsertNextPoint 0.0837508 -0.109594 -0.0632213 +pts InsertNextPoint 0.0844621 -0.109354 -0.0658219 +pts InsertNextPoint 0.085617 -0.109095 -0.0686354 +pts InsertNextPoint 0.088544 -0.108749 -0.0723836 +pts InsertNextPoint 0.0913291 -0.108419 -0.0759663 +pts InsertNextPoint 0.093603 -0.108121 -0.0791933 +pts InsertNextPoint 0.0954715 -0.10785 -0.0821383 +pts InsertNextPoint 0.095835 -0.107654 -0.0842561 +pts InsertNextPoint 0.0959382 -0.107473 -0.0862176 +pts InsertNextPoint 0.095529 -0.107317 -0.0879091 +pts InsertNextPoint 0.0946462 -0.107182 -0.0893661 +pts InsertNextPoint 0.0931271 -0.107075 -0.0905284 +pts InsertNextPoint 0.0906307 -0.107007 -0.0912613 +pts InsertNextPoint 0.0861782 -0.107015 -0.0911614 +pts InsertNextPoint 0.0728955 -0.107369 -0.08731 +pts InsertNextPoint 0.0692164 -0.107324 -0.0877801 +pts InsertNextPoint 0.0658602 -0.107263 -0.0884407 +pts InsertNextPoint 0.0619263 -0.107218 -0.0889185 +pts InsertNextPoint 0.0591189 -0.107127 -0.0898991 +pts InsertNextPoint 0.0565055 -0.107026 -0.0909912 +pts InsertNextPoint 0.053631 -0.106931 -0.0920192 +pts InsertNextPoint 0.0844463 -0.108736 -0.054886 +pts InsertNextPoint 0.083948 -0.108554 -0.0568146 +pts InsertNextPoint 0.0834465 -0.108374 -0.0587312 +pts InsertNextPoint 0.0827588 -0.108204 -0.0605257 +pts InsertNextPoint 0.0830176 -0.107991 -0.0628728 +pts InsertNextPoint 0.0841279 -0.107742 -0.0656843 +pts InsertNextPoint 0.084953 -0.107511 -0.0682874 +pts InsertNextPoint 0.0874022 -0.107214 -0.0717515 +pts InsertNextPoint 0.0904351 -0.106901 -0.0754566 +pts InsertNextPoint 0.0930288 -0.106613 -0.0788395 +pts InsertNextPoint 0.0946685 -0.10637 -0.0816484 +pts InsertNextPoint 0.0949646 -0.106182 -0.0837175 +pts InsertNextPoint 0.0949355 -0.106009 -0.0855998 +pts InsertNextPoint 0.0944449 -0.105855 -0.0872397 +pts InsertNextPoint 0.0935671 -0.105714 -0.0886878 +pts InsertNextPoint 0.0921416 -0.105592 -0.0898818 +pts InsertNextPoint 0.0895416 -0.105508 -0.0905534 +pts InsertNextPoint 0.0858686 -0.105455 -0.0907846 +pts InsertNextPoint 0.072294 -0.105706 -0.0867688 +pts InsertNextPoint 0.0689791 -0.105621 -0.0873712 +pts InsertNextPoint 0.0654259 -0.10554 -0.0879241 +pts InsertNextPoint 0.0611841 -0.105473 -0.0882521 +pts InsertNextPoint 0.0578746 -0.105374 -0.089014 +pts InsertNextPoint 0.0550534 -0.105258 -0.0900107 +pts InsertNextPoint 0.0526628 -0.105128 -0.0912055 +pts InsertNextPoint 0.0838226 -0.107119 -0.0546889 +pts InsertNextPoint 0.0831948 -0.106941 -0.0565147 +pts InsertNextPoint 0.0827575 -0.106757 -0.0584503 +pts InsertNextPoint 0.0821759 -0.106579 -0.0602881 +pts InsertNextPoint 0.0823385 -0.106375 -0.0625566 +pts InsertNextPoint 0.0834905 -0.106138 -0.0653718 +pts InsertNextPoint 0.0843416 -0.105916 -0.0679694 +pts InsertNextPoint 0.0860984 -0.105667 -0.0710297 +pts InsertNextPoint 0.0896156 -0.105367 -0.074987 +pts InsertNextPoint 0.0926124 -0.105092 -0.0785694 +pts InsertNextPoint 0.093825 -0.104878 -0.0811369 +pts InsertNextPoint 0.0941736 -0.104694 -0.0832187 +pts InsertNextPoint 0.0939176 -0.10453 -0.0849732 +pts InsertNextPoint 0.0933511 -0.104375 -0.086564 +pts InsertNextPoint 0.0924957 -0.104228 -0.0880113 +pts InsertNextPoint 0.0910169 -0.104097 -0.0891682 +pts InsertNextPoint 0.088859 -0.103982 -0.0900288 +pts InsertNextPoint 0.0852585 -0.103897 -0.0902729 +pts InsertNextPoint 0.0719664 -0.104027 -0.0863454 +pts InsertNextPoint 0.0686316 -0.103917 -0.0869147 +pts InsertNextPoint 0.0647459 -0.103815 -0.087304 +pts InsertNextPoint 0.0602624 -0.103719 -0.0875101 +pts InsertNextPoint 0.0562658 -0.103607 -0.0879798 +pts InsertNextPoint 0.0544143 -0.103451 -0.0893385 +pts InsertNextPoint 0.0530892 -0.103285 -0.090913 +pts InsertNextPoint 0.0832507 -0.105493 -0.0545257 +pts InsertNextPoint 0.0824988 -0.105317 -0.0562514 +pts InsertNextPoint 0.0820648 -0.105131 -0.058168 +pts InsertNextPoint 0.0815269 -0.10495 -0.0600113 +pts InsertNextPoint 0.081673 -0.104751 -0.062249 +pts InsertNextPoint 0.0825249 -0.104535 -0.06487 +pts InsertNextPoint 0.0833271 -0.104324 -0.0674233 +pts InsertNextPoint 0.0858362 -0.104074 -0.0708855 +pts InsertNextPoint 0.0896779 -0.1038 -0.0749966 +pts InsertNextPoint 0.0908493 -0.103595 -0.0775821 +pts InsertNextPoint 0.0929675 -0.103375 -0.0806174 +pts InsertNextPoint 0.0931055 -0.1032 -0.0825775 +pts InsertNextPoint 0.0928628 -0.103035 -0.0843269 +pts InsertNextPoint 0.0923395 -0.102876 -0.0859268 +pts InsertNextPoint 0.0914122 -0.102725 -0.0873272 +pts InsertNextPoint 0.0898335 -0.102585 -0.0884249 +pts InsertNextPoint 0.0876505 -0.102453 -0.0892618 +pts InsertNextPoint 0.0840349 -0.102339 -0.089485 +pts InsertNextPoint 0.0717453 -0.102341 -0.0859679 +pts InsertNextPoint 0.068159 -0.102209 -0.0864036 +pts InsertNextPoint 0.0638112 -0.102081 -0.0865752 +pts InsertNextPoint 0.0591184 -0.101951 -0.0866743 +pts InsertNextPoint 0.0557334 -0.101801 -0.087368 +pts InsertNextPoint 0.0546243 -0.101625 -0.0889934 +pts InsertNextPoint 0.0537662 -0.101446 -0.090717 +pts InsertNextPoint 0.0820141 -0.103876 -0.0539414 +pts InsertNextPoint 0.0818125 -0.103683 -0.055995 +pts InsertNextPoint 0.0813016 -0.103498 -0.0578433 +pts InsertNextPoint 0.0807344 -0.103316 -0.0596491 +pts InsertNextPoint 0.0809305 -0.103119 -0.0618964 +pts InsertNextPoint 0.0818695 -0.102912 -0.0645477 +pts InsertNextPoint 0.0825983 -0.102711 -0.0670392 +pts InsertNextPoint 0.0846148 -0.102494 -0.0702093 +pts InsertNextPoint 0.0875215 -0.102269 -0.0738 +pts InsertNextPoint 0.0901664 -0.102056 -0.0771693 +pts InsertNextPoint 0.0919021 -0.10186 -0.0799888 +pts InsertNextPoint 0.0920518 -0.101689 -0.0819427 +pts InsertNextPoint 0.091724 -0.101524 -0.0836371 +pts InsertNextPoint 0.0911694 -0.101363 -0.0852104 +pts InsertNextPoint 0.0902245 -0.101206 -0.0865911 +pts InsertNextPoint 0.088777 -0.101052 -0.0877388 +pts InsertNextPoint 0.086709 -0.100902 -0.0886146 +pts InsertNextPoint 0.0831344 -0.100758 -0.0888391 +pts InsertNextPoint 0.0712353 -0.100654 -0.0854629 +pts InsertNextPoint 0.0672884 -0.100495 -0.0857204 +pts InsertNextPoint 0.06249 -0.100334 -0.0856813 +pts InsertNextPoint 0.0571388 -0.100167 -0.0854921 +pts InsertNextPoint 0.0558877 -0.0999847 -0.0870288 +pts InsertNextPoint 0.0551029 -0.0998017 -0.0887539 +pts InsertNextPoint 0.0544511 -0.0996189 -0.0905269 +pts InsertNextPoint 0.0808777 -0.10224 -0.0534229 +pts InsertNextPoint 0.0803915 -0.102051 -0.0552826 +pts InsertNextPoint 0.0804125 -0.101857 -0.0574427 +pts InsertNextPoint 0.0799982 -0.10167 -0.0593213 +pts InsertNextPoint 0.0801642 -0.101478 -0.0615304 +pts InsertNextPoint 0.0809996 -0.101282 -0.064102 +pts InsertNextPoint 0.0817187 -0.10109 -0.06657 +pts InsertNextPoint 0.0841565 -0.10089 -0.0699564 +pts InsertNextPoint 0.0863255 -0.100698 -0.0731251 +pts InsertNextPoint 0.0889732 -0.100509 -0.0764842 +pts InsertNextPoint 0.0909597 -0.100329 -0.0794237 +pts InsertNextPoint 0.0909888 -0.100161 -0.081302 +pts InsertNextPoint 0.0907195 -0.099995 -0.0830133 +pts InsertNextPoint 0.0901659 -0.0998305 -0.084574 +pts InsertNextPoint 0.0891033 -0.0996666 -0.0858849 +pts InsertNextPoint 0.0875981 -0.0995019 -0.0869929 +pts InsertNextPoint 0.0851347 -0.0993344 -0.0876739 +pts InsertNextPoint 0.0817109 -0.0991617 -0.0879553 +pts InsertNextPoint 0.0704428 -0.0989584 -0.0848322 +pts InsertNextPoint 0.0661582 -0.0987658 -0.0849228 +pts InsertNextPoint 0.060547 -0.0985605 -0.0845212 +pts InsertNextPoint 0.057211 -0.0983605 -0.0851471 +pts InsertNextPoint 0.0562477 -0.0981724 -0.086773 +pts InsertNextPoint 0.0554538 -0.0979856 -0.0884662 +pts InsertNextPoint 0.0546043 -0.0977985 -0.0901359 + +vtkCellArray ca +ca InsertNextCell 4 +ca InsertCellPoint 0 +ca InsertCellPoint 1 +ca InsertCellPoint 26 +ca InsertCellPoint 25 +ca InsertNextCell 4 +ca InsertCellPoint 1 +ca InsertCellPoint 2 +ca InsertCellPoint 27 +ca InsertCellPoint 26 +ca InsertNextCell 4 +ca InsertCellPoint 2 +ca InsertCellPoint 3 +ca InsertCellPoint 28 +ca InsertCellPoint 27 +ca InsertNextCell 4 +ca InsertCellPoint 3 +ca InsertCellPoint 4 +ca InsertCellPoint 29 +ca InsertCellPoint 28 +ca InsertNextCell 4 +ca InsertCellPoint 4 +ca InsertCellPoint 5 +ca InsertCellPoint 30 +ca InsertCellPoint 29 +ca InsertNextCell 4 +ca InsertCellPoint 5 +ca InsertCellPoint 6 +ca InsertCellPoint 31 +ca InsertCellPoint 30 +ca InsertNextCell 4 +ca InsertCellPoint 6 +ca InsertCellPoint 7 +ca InsertCellPoint 32 +ca InsertCellPoint 31 +ca InsertNextCell 4 +ca InsertCellPoint 7 +ca InsertCellPoint 8 +ca InsertCellPoint 33 +ca InsertCellPoint 32 +ca InsertNextCell 4 +ca InsertCellPoint 8 +ca InsertCellPoint 9 +ca InsertCellPoint 34 +ca InsertCellPoint 33 +ca InsertNextCell 4 +ca InsertCellPoint 9 +ca InsertCellPoint 10 +ca InsertCellPoint 35 +ca InsertCellPoint 34 +ca InsertNextCell 4 +ca InsertCellPoint 10 +ca InsertCellPoint 11 +ca InsertCellPoint 36 +ca InsertCellPoint 35 +ca InsertNextCell 4 +ca InsertCellPoint 11 +ca InsertCellPoint 12 +ca InsertCellPoint 37 +ca InsertCellPoint 36 +ca InsertNextCell 4 +ca InsertCellPoint 12 +ca InsertCellPoint 13 +ca InsertCellPoint 38 +ca InsertCellPoint 37 +ca InsertNextCell 4 +ca InsertCellPoint 13 +ca InsertCellPoint 14 +ca InsertCellPoint 39 +ca InsertCellPoint 38 +ca InsertNextCell 4 +ca InsertCellPoint 14 +ca InsertCellPoint 15 +ca InsertCellPoint 40 +ca InsertCellPoint 39 +ca InsertNextCell 4 +ca InsertCellPoint 15 +ca InsertCellPoint 16 +ca InsertCellPoint 41 +ca InsertCellPoint 40 +ca InsertNextCell 4 +ca InsertCellPoint 16 +ca InsertCellPoint 17 +ca InsertCellPoint 42 +ca InsertCellPoint 41 +ca InsertNextCell 4 +ca InsertCellPoint 17 +ca InsertCellPoint 18 +ca InsertCellPoint 43 +ca InsertCellPoint 42 +ca InsertNextCell 4 +ca InsertCellPoint 18 +ca InsertCellPoint 19 +ca InsertCellPoint 44 +ca InsertCellPoint 43 +ca InsertNextCell 4 +ca InsertCellPoint 19 +ca InsertCellPoint 20 +ca InsertCellPoint 45 +ca InsertCellPoint 44 +ca InsertNextCell 4 +ca InsertCellPoint 20 +ca InsertCellPoint 21 +ca InsertCellPoint 46 +ca InsertCellPoint 45 +ca InsertNextCell 4 +ca InsertCellPoint 21 +ca InsertCellPoint 22 +ca InsertCellPoint 47 +ca InsertCellPoint 46 +ca InsertNextCell 4 +ca InsertCellPoint 22 +ca InsertCellPoint 23 +ca InsertCellPoint 48 +ca InsertCellPoint 47 +ca InsertNextCell 4 +ca InsertCellPoint 23 +ca InsertCellPoint 24 +ca InsertCellPoint 49 +ca InsertCellPoint 48 +ca InsertNextCell 4 +ca InsertCellPoint 25 +ca InsertCellPoint 26 +ca InsertCellPoint 51 +ca InsertCellPoint 50 +ca InsertNextCell 4 +ca InsertCellPoint 26 +ca InsertCellPoint 27 +ca InsertCellPoint 52 +ca InsertCellPoint 51 +ca InsertNextCell 4 +ca InsertCellPoint 27 +ca InsertCellPoint 28 +ca InsertCellPoint 53 +ca InsertCellPoint 52 +ca InsertNextCell 4 +ca InsertCellPoint 28 +ca InsertCellPoint 29 +ca InsertCellPoint 54 +ca InsertCellPoint 53 +ca InsertNextCell 4 +ca InsertCellPoint 29 +ca InsertCellPoint 30 +ca InsertCellPoint 55 +ca InsertCellPoint 54 +ca InsertNextCell 4 +ca InsertCellPoint 30 +ca InsertCellPoint 31 +ca InsertCellPoint 56 +ca InsertCellPoint 55 +ca InsertNextCell 4 +ca InsertCellPoint 31 +ca InsertCellPoint 32 +ca InsertCellPoint 57 +ca InsertCellPoint 56 +ca InsertNextCell 4 +ca InsertCellPoint 32 +ca InsertCellPoint 33 +ca InsertCellPoint 58 +ca InsertCellPoint 57 +ca InsertNextCell 4 +ca InsertCellPoint 33 +ca InsertCellPoint 34 +ca InsertCellPoint 59 +ca InsertCellPoint 58 +ca InsertNextCell 4 +ca InsertCellPoint 34 +ca InsertCellPoint 35 +ca InsertCellPoint 60 +ca InsertCellPoint 59 +ca InsertNextCell 4 +ca InsertCellPoint 35 +ca InsertCellPoint 36 +ca InsertCellPoint 61 +ca InsertCellPoint 60 +ca InsertNextCell 4 +ca InsertCellPoint 36 +ca InsertCellPoint 37 +ca InsertCellPoint 62 +ca InsertCellPoint 61 +ca InsertNextCell 4 +ca InsertCellPoint 37 +ca InsertCellPoint 38 +ca InsertCellPoint 63 +ca InsertCellPoint 62 +ca InsertNextCell 4 +ca InsertCellPoint 38 +ca InsertCellPoint 39 +ca InsertCellPoint 64 +ca InsertCellPoint 63 +ca InsertNextCell 4 +ca InsertCellPoint 39 +ca InsertCellPoint 40 +ca InsertCellPoint 65 +ca InsertCellPoint 64 +ca InsertNextCell 4 +ca InsertCellPoint 40 +ca InsertCellPoint 41 +ca InsertCellPoint 66 +ca InsertCellPoint 65 +ca InsertNextCell 4 +ca InsertCellPoint 41 +ca InsertCellPoint 42 +ca InsertCellPoint 67 +ca InsertCellPoint 66 +ca InsertNextCell 4 +ca InsertCellPoint 42 +ca InsertCellPoint 43 +ca InsertCellPoint 68 +ca InsertCellPoint 67 +ca InsertNextCell 4 +ca InsertCellPoint 43 +ca InsertCellPoint 44 +ca InsertCellPoint 69 +ca InsertCellPoint 68 +ca InsertNextCell 4 +ca InsertCellPoint 44 +ca InsertCellPoint 45 +ca InsertCellPoint 70 +ca InsertCellPoint 69 +ca InsertNextCell 4 +ca InsertCellPoint 45 +ca InsertCellPoint 46 +ca InsertCellPoint 71 +ca InsertCellPoint 70 +ca InsertNextCell 4 +ca InsertCellPoint 46 +ca InsertCellPoint 47 +ca InsertCellPoint 72 +ca InsertCellPoint 71 +ca InsertNextCell 4 +ca InsertCellPoint 47 +ca InsertCellPoint 48 +ca InsertCellPoint 73 +ca InsertCellPoint 72 +ca InsertNextCell 4 +ca InsertCellPoint 48 +ca InsertCellPoint 49 +ca InsertCellPoint 74 +ca InsertCellPoint 73 +ca InsertNextCell 4 +ca InsertCellPoint 50 +ca InsertCellPoint 51 +ca InsertCellPoint 76 +ca InsertCellPoint 75 +ca InsertNextCell 4 +ca InsertCellPoint 51 +ca InsertCellPoint 52 +ca InsertCellPoint 77 +ca InsertCellPoint 76 +ca InsertNextCell 4 +ca InsertCellPoint 52 +ca InsertCellPoint 53 +ca InsertCellPoint 78 +ca InsertCellPoint 77 +ca InsertNextCell 4 +ca InsertCellPoint 53 +ca InsertCellPoint 54 +ca InsertCellPoint 79 +ca InsertCellPoint 78 +ca InsertNextCell 4 +ca InsertCellPoint 54 +ca InsertCellPoint 55 +ca InsertCellPoint 80 +ca InsertCellPoint 79 +ca InsertNextCell 4 +ca InsertCellPoint 55 +ca InsertCellPoint 56 +ca InsertCellPoint 81 +ca InsertCellPoint 80 +ca InsertNextCell 4 +ca InsertCellPoint 56 +ca InsertCellPoint 57 +ca InsertCellPoint 82 +ca InsertCellPoint 81 +ca InsertNextCell 4 +ca InsertCellPoint 57 +ca InsertCellPoint 58 +ca InsertCellPoint 83 +ca InsertCellPoint 82 +ca InsertNextCell 4 +ca InsertCellPoint 58 +ca InsertCellPoint 59 +ca InsertCellPoint 84 +ca InsertCellPoint 83 +ca InsertNextCell 4 +ca InsertCellPoint 59 +ca InsertCellPoint 60 +ca InsertCellPoint 85 +ca InsertCellPoint 84 +ca InsertNextCell 4 +ca InsertCellPoint 60 +ca InsertCellPoint 61 +ca InsertCellPoint 86 +ca InsertCellPoint 85 +ca InsertNextCell 4 +ca InsertCellPoint 61 +ca InsertCellPoint 62 +ca InsertCellPoint 87 +ca InsertCellPoint 86 +ca InsertNextCell 4 +ca InsertCellPoint 62 +ca InsertCellPoint 63 +ca InsertCellPoint 88 +ca InsertCellPoint 87 +ca InsertNextCell 4 +ca InsertCellPoint 63 +ca InsertCellPoint 64 +ca InsertCellPoint 89 +ca InsertCellPoint 88 +ca InsertNextCell 4 +ca InsertCellPoint 64 +ca InsertCellPoint 65 +ca InsertCellPoint 90 +ca InsertCellPoint 89 +ca InsertNextCell 4 +ca InsertCellPoint 65 +ca InsertCellPoint 66 +ca InsertCellPoint 91 +ca InsertCellPoint 90 +ca InsertNextCell 4 +ca InsertCellPoint 66 +ca InsertCellPoint 67 +ca InsertCellPoint 92 +ca InsertCellPoint 91 +ca InsertNextCell 4 +ca InsertCellPoint 67 +ca InsertCellPoint 68 +ca InsertCellPoint 93 +ca InsertCellPoint 92 +ca InsertNextCell 4 +ca InsertCellPoint 68 +ca InsertCellPoint 69 +ca InsertCellPoint 94 +ca InsertCellPoint 93 +ca InsertNextCell 4 +ca InsertCellPoint 69 +ca InsertCellPoint 70 +ca InsertCellPoint 95 +ca InsertCellPoint 94 +ca InsertNextCell 4 +ca InsertCellPoint 70 +ca InsertCellPoint 71 +ca InsertCellPoint 96 +ca InsertCellPoint 95 +ca InsertNextCell 4 +ca InsertCellPoint 71 +ca InsertCellPoint 72 +ca InsertCellPoint 97 +ca InsertCellPoint 96 +ca InsertNextCell 4 +ca InsertCellPoint 72 +ca InsertCellPoint 73 +ca InsertCellPoint 98 +ca InsertCellPoint 97 +ca InsertNextCell 4 +ca InsertCellPoint 73 +ca InsertCellPoint 74 +ca InsertCellPoint 99 +ca InsertCellPoint 98 +ca InsertNextCell 4 +ca InsertCellPoint 75 +ca InsertCellPoint 76 +ca InsertCellPoint 101 +ca InsertCellPoint 100 +ca InsertNextCell 4 +ca InsertCellPoint 76 +ca InsertCellPoint 77 +ca InsertCellPoint 102 +ca InsertCellPoint 101 +ca InsertNextCell 4 +ca InsertCellPoint 77 +ca InsertCellPoint 78 +ca InsertCellPoint 103 +ca InsertCellPoint 102 +ca InsertNextCell 4 +ca InsertCellPoint 78 +ca InsertCellPoint 79 +ca InsertCellPoint 104 +ca InsertCellPoint 103 +ca InsertNextCell 4 +ca InsertCellPoint 79 +ca InsertCellPoint 80 +ca InsertCellPoint 105 +ca InsertCellPoint 104 +ca InsertNextCell 4 +ca InsertCellPoint 80 +ca InsertCellPoint 81 +ca InsertCellPoint 106 +ca InsertCellPoint 105 +ca InsertNextCell 4 +ca InsertCellPoint 81 +ca InsertCellPoint 82 +ca InsertCellPoint 107 +ca InsertCellPoint 106 +ca InsertNextCell 4 +ca InsertCellPoint 82 +ca InsertCellPoint 83 +ca InsertCellPoint 108 +ca InsertCellPoint 107 +ca InsertNextCell 4 +ca InsertCellPoint 83 +ca InsertCellPoint 84 +ca InsertCellPoint 109 +ca InsertCellPoint 108 +ca InsertNextCell 4 +ca InsertCellPoint 84 +ca InsertCellPoint 85 +ca InsertCellPoint 110 +ca InsertCellPoint 109 +ca InsertNextCell 4 +ca InsertCellPoint 85 +ca InsertCellPoint 86 +ca InsertCellPoint 111 +ca InsertCellPoint 110 +ca InsertNextCell 4 +ca InsertCellPoint 86 +ca InsertCellPoint 87 +ca InsertCellPoint 112 +ca InsertCellPoint 111 +ca InsertNextCell 4 +ca InsertCellPoint 87 +ca InsertCellPoint 88 +ca InsertCellPoint 113 +ca InsertCellPoint 112 +ca InsertNextCell 4 +ca InsertCellPoint 88 +ca InsertCellPoint 89 +ca InsertCellPoint 114 +ca InsertCellPoint 113 +ca InsertNextCell 4 +ca InsertCellPoint 89 +ca InsertCellPoint 90 +ca InsertCellPoint 115 +ca InsertCellPoint 114 +ca InsertNextCell 4 +ca InsertCellPoint 90 +ca InsertCellPoint 91 +ca InsertCellPoint 116 +ca InsertCellPoint 115 +ca InsertNextCell 4 +ca InsertCellPoint 91 +ca InsertCellPoint 92 +ca InsertCellPoint 117 +ca InsertCellPoint 116 +ca InsertNextCell 4 +ca InsertCellPoint 92 +ca InsertCellPoint 93 +ca InsertCellPoint 118 +ca InsertCellPoint 117 +ca InsertNextCell 4 +ca InsertCellPoint 93 +ca InsertCellPoint 94 +ca InsertCellPoint 119 +ca InsertCellPoint 118 +ca InsertNextCell 4 +ca InsertCellPoint 94 +ca InsertCellPoint 95 +ca InsertCellPoint 120 +ca InsertCellPoint 119 +ca InsertNextCell 4 +ca InsertCellPoint 95 +ca InsertCellPoint 96 +ca InsertCellPoint 121 +ca InsertCellPoint 120 +ca InsertNextCell 4 +ca InsertCellPoint 96 +ca InsertCellPoint 97 +ca InsertCellPoint 122 +ca InsertCellPoint 121 +ca InsertNextCell 4 +ca InsertCellPoint 97 +ca InsertCellPoint 98 +ca InsertCellPoint 123 +ca InsertCellPoint 122 +ca InsertNextCell 4 +ca InsertCellPoint 98 +ca InsertCellPoint 99 +ca InsertCellPoint 124 +ca InsertCellPoint 123 +ca InsertNextCell 4 +ca InsertCellPoint 100 +ca InsertCellPoint 101 +ca InsertCellPoint 126 +ca InsertCellPoint 125 +ca InsertNextCell 4 +ca InsertCellPoint 101 +ca InsertCellPoint 102 +ca InsertCellPoint 127 +ca InsertCellPoint 126 +ca InsertNextCell 4 +ca InsertCellPoint 102 +ca InsertCellPoint 103 +ca InsertCellPoint 128 +ca InsertCellPoint 127 +ca InsertNextCell 4 +ca InsertCellPoint 103 +ca InsertCellPoint 104 +ca InsertCellPoint 129 +ca InsertCellPoint 128 +ca InsertNextCell 4 +ca InsertCellPoint 104 +ca InsertCellPoint 105 +ca InsertCellPoint 130 +ca InsertCellPoint 129 +ca InsertNextCell 4 +ca InsertCellPoint 105 +ca InsertCellPoint 106 +ca InsertCellPoint 131 +ca InsertCellPoint 130 +ca InsertNextCell 4 +ca InsertCellPoint 106 +ca InsertCellPoint 107 +ca InsertCellPoint 132 +ca InsertCellPoint 131 +ca InsertNextCell 4 +ca InsertCellPoint 107 +ca InsertCellPoint 108 +ca InsertCellPoint 133 +ca InsertCellPoint 132 +ca InsertNextCell 4 +ca InsertCellPoint 108 +ca InsertCellPoint 109 +ca InsertCellPoint 134 +ca InsertCellPoint 133 +ca InsertNextCell 4 +ca InsertCellPoint 109 +ca InsertCellPoint 110 +ca InsertCellPoint 135 +ca InsertCellPoint 134 +ca InsertNextCell 4 +ca InsertCellPoint 110 +ca InsertCellPoint 111 +ca InsertCellPoint 136 +ca InsertCellPoint 135 +ca InsertNextCell 4 +ca InsertCellPoint 111 +ca InsertCellPoint 112 +ca InsertCellPoint 137 +ca InsertCellPoint 136 +ca InsertNextCell 4 +ca InsertCellPoint 112 +ca InsertCellPoint 113 +ca InsertCellPoint 138 +ca InsertCellPoint 137 +ca InsertNextCell 4 +ca InsertCellPoint 113 +ca InsertCellPoint 114 +ca InsertCellPoint 139 +ca InsertCellPoint 138 +ca InsertNextCell 4 +ca InsertCellPoint 114 +ca InsertCellPoint 115 +ca InsertCellPoint 140 +ca InsertCellPoint 139 +ca InsertNextCell 4 +ca InsertCellPoint 115 +ca InsertCellPoint 116 +ca InsertCellPoint 141 +ca InsertCellPoint 140 +ca InsertNextCell 4 +ca InsertCellPoint 116 +ca InsertCellPoint 117 +ca InsertCellPoint 142 +ca InsertCellPoint 141 +ca InsertNextCell 4 +ca InsertCellPoint 117 +ca InsertCellPoint 118 +ca InsertCellPoint 143 +ca InsertCellPoint 142 +ca InsertNextCell 4 +ca InsertCellPoint 118 +ca InsertCellPoint 119 +ca InsertCellPoint 144 +ca InsertCellPoint 143 +ca InsertNextCell 4 +ca InsertCellPoint 119 +ca InsertCellPoint 120 +ca InsertCellPoint 145 +ca InsertCellPoint 144 +ca InsertNextCell 4 +ca InsertCellPoint 120 +ca InsertCellPoint 121 +ca InsertCellPoint 146 +ca InsertCellPoint 145 +ca InsertNextCell 4 +ca InsertCellPoint 121 +ca InsertCellPoint 122 +ca InsertCellPoint 147 +ca InsertCellPoint 146 +ca InsertNextCell 4 +ca InsertCellPoint 122 +ca InsertCellPoint 123 +ca InsertCellPoint 148 +ca InsertCellPoint 147 +ca InsertNextCell 4 +ca InsertCellPoint 123 +ca InsertCellPoint 124 +ca InsertCellPoint 149 +ca InsertCellPoint 148 +ca InsertNextCell 4 +ca InsertCellPoint 125 +ca InsertCellPoint 126 +ca InsertCellPoint 151 +ca InsertCellPoint 150 +ca InsertNextCell 4 +ca InsertCellPoint 126 +ca InsertCellPoint 127 +ca InsertCellPoint 152 +ca InsertCellPoint 151 +ca InsertNextCell 4 +ca InsertCellPoint 127 +ca InsertCellPoint 128 +ca InsertCellPoint 153 +ca InsertCellPoint 152 +ca InsertNextCell 4 +ca InsertCellPoint 128 +ca InsertCellPoint 129 +ca InsertCellPoint 154 +ca InsertCellPoint 153 +ca InsertNextCell 4 +ca InsertCellPoint 129 +ca InsertCellPoint 130 +ca InsertCellPoint 155 +ca InsertCellPoint 154 +ca InsertNextCell 4 +ca InsertCellPoint 130 +ca InsertCellPoint 131 +ca InsertCellPoint 156 +ca InsertCellPoint 155 +ca InsertNextCell 4 +ca InsertCellPoint 131 +ca InsertCellPoint 132 +ca InsertCellPoint 157 +ca InsertCellPoint 156 +ca InsertNextCell 4 +ca InsertCellPoint 132 +ca InsertCellPoint 133 +ca InsertCellPoint 158 +ca InsertCellPoint 157 +ca InsertNextCell 4 +ca InsertCellPoint 133 +ca InsertCellPoint 134 +ca InsertCellPoint 159 +ca InsertCellPoint 158 +ca InsertNextCell 4 +ca InsertCellPoint 134 +ca InsertCellPoint 135 +ca InsertCellPoint 160 +ca InsertCellPoint 159 +ca InsertNextCell 4 +ca InsertCellPoint 135 +ca InsertCellPoint 136 +ca InsertCellPoint 161 +ca InsertCellPoint 160 +ca InsertNextCell 4 +ca InsertCellPoint 136 +ca InsertCellPoint 137 +ca InsertCellPoint 162 +ca InsertCellPoint 161 +ca InsertNextCell 4 +ca InsertCellPoint 137 +ca InsertCellPoint 138 +ca InsertCellPoint 163 +ca InsertCellPoint 162 +ca InsertNextCell 4 +ca InsertCellPoint 138 +ca InsertCellPoint 139 +ca InsertCellPoint 164 +ca InsertCellPoint 163 +ca InsertNextCell 4 +ca InsertCellPoint 139 +ca InsertCellPoint 140 +ca InsertCellPoint 165 +ca InsertCellPoint 164 +ca InsertNextCell 4 +ca InsertCellPoint 140 +ca InsertCellPoint 141 +ca InsertCellPoint 166 +ca InsertCellPoint 165 +ca InsertNextCell 4 +ca InsertCellPoint 141 +ca InsertCellPoint 142 +ca InsertCellPoint 167 +ca InsertCellPoint 166 +ca InsertNextCell 4 +ca InsertCellPoint 142 +ca InsertCellPoint 143 +ca InsertCellPoint 168 +ca InsertCellPoint 167 +ca InsertNextCell 4 +ca InsertCellPoint 143 +ca InsertCellPoint 144 +ca InsertCellPoint 169 +ca InsertCellPoint 168 +ca InsertNextCell 4 +ca InsertCellPoint 144 +ca InsertCellPoint 145 +ca InsertCellPoint 170 +ca InsertCellPoint 169 +ca InsertNextCell 4 +ca InsertCellPoint 145 +ca InsertCellPoint 146 +ca InsertCellPoint 171 +ca InsertCellPoint 170 +ca InsertNextCell 4 +ca InsertCellPoint 146 +ca InsertCellPoint 147 +ca InsertCellPoint 172 +ca InsertCellPoint 171 +ca InsertNextCell 4 +ca InsertCellPoint 147 +ca InsertCellPoint 148 +ca InsertCellPoint 173 +ca InsertCellPoint 172 +ca InsertNextCell 4 +ca InsertCellPoint 148 +ca InsertCellPoint 149 +ca InsertCellPoint 174 +ca InsertCellPoint 173 +ca InsertNextCell 4 +ca InsertCellPoint 150 +ca InsertCellPoint 151 +ca InsertCellPoint 176 +ca InsertCellPoint 175 +ca InsertNextCell 4 +ca InsertCellPoint 151 +ca InsertCellPoint 152 +ca InsertCellPoint 177 +ca InsertCellPoint 176 +ca InsertNextCell 4 +ca InsertCellPoint 152 +ca InsertCellPoint 153 +ca InsertCellPoint 178 +ca InsertCellPoint 177 +ca InsertNextCell 4 +ca InsertCellPoint 153 +ca InsertCellPoint 154 +ca InsertCellPoint 179 +ca InsertCellPoint 178 +ca InsertNextCell 4 +ca InsertCellPoint 154 +ca InsertCellPoint 155 +ca InsertCellPoint 180 +ca InsertCellPoint 179 +ca InsertNextCell 4 +ca InsertCellPoint 155 +ca InsertCellPoint 156 +ca InsertCellPoint 181 +ca InsertCellPoint 180 +ca InsertNextCell 4 +ca InsertCellPoint 156 +ca InsertCellPoint 157 +ca InsertCellPoint 182 +ca InsertCellPoint 181 +ca InsertNextCell 4 +ca InsertCellPoint 157 +ca InsertCellPoint 158 +ca InsertCellPoint 183 +ca InsertCellPoint 182 +ca InsertNextCell 4 +ca InsertCellPoint 158 +ca InsertCellPoint 159 +ca InsertCellPoint 184 +ca InsertCellPoint 183 +ca InsertNextCell 4 +ca InsertCellPoint 159 +ca InsertCellPoint 160 +ca InsertCellPoint 185 +ca InsertCellPoint 184 +ca InsertNextCell 4 +ca InsertCellPoint 160 +ca InsertCellPoint 161 +ca InsertCellPoint 186 +ca InsertCellPoint 185 +ca InsertNextCell 4 +ca InsertCellPoint 161 +ca InsertCellPoint 162 +ca InsertCellPoint 187 +ca InsertCellPoint 186 +ca InsertNextCell 4 +ca InsertCellPoint 162 +ca InsertCellPoint 163 +ca InsertCellPoint 188 +ca InsertCellPoint 187 +ca InsertNextCell 4 +ca InsertCellPoint 163 +ca InsertCellPoint 164 +ca InsertCellPoint 189 +ca InsertCellPoint 188 +ca InsertNextCell 4 +ca InsertCellPoint 164 +ca InsertCellPoint 165 +ca InsertCellPoint 190 +ca InsertCellPoint 189 +ca InsertNextCell 4 +ca InsertCellPoint 165 +ca InsertCellPoint 166 +ca InsertCellPoint 191 +ca InsertCellPoint 190 +ca InsertNextCell 4 +ca InsertCellPoint 166 +ca InsertCellPoint 167 +ca InsertCellPoint 192 +ca InsertCellPoint 191 +ca InsertNextCell 4 +ca InsertCellPoint 167 +ca InsertCellPoint 168 +ca InsertCellPoint 193 +ca InsertCellPoint 192 +ca InsertNextCell 4 +ca InsertCellPoint 168 +ca InsertCellPoint 169 +ca InsertCellPoint 194 +ca InsertCellPoint 193 +ca InsertNextCell 4 +ca InsertCellPoint 169 +ca InsertCellPoint 170 +ca InsertCellPoint 195 +ca InsertCellPoint 194 +ca InsertNextCell 4 +ca InsertCellPoint 170 +ca InsertCellPoint 171 +ca InsertCellPoint 196 +ca InsertCellPoint 195 +ca InsertNextCell 4 +ca InsertCellPoint 171 +ca InsertCellPoint 172 +ca InsertCellPoint 197 +ca InsertCellPoint 196 +ca InsertNextCell 4 +ca InsertCellPoint 172 +ca InsertCellPoint 173 +ca InsertCellPoint 198 +ca InsertCellPoint 197 +ca InsertNextCell 4 +ca InsertCellPoint 173 +ca InsertCellPoint 174 +ca InsertCellPoint 199 +ca InsertCellPoint 198 +ca InsertNextCell 4 +ca InsertCellPoint 175 +ca InsertCellPoint 176 +ca InsertCellPoint 201 +ca InsertCellPoint 200 +ca InsertNextCell 4 +ca InsertCellPoint 176 +ca InsertCellPoint 177 +ca InsertCellPoint 202 +ca InsertCellPoint 201 +ca InsertNextCell 4 +ca InsertCellPoint 177 +ca InsertCellPoint 178 +ca InsertCellPoint 203 +ca InsertCellPoint 202 +ca InsertNextCell 4 +ca InsertCellPoint 178 +ca InsertCellPoint 179 +ca InsertCellPoint 204 +ca InsertCellPoint 203 +ca InsertNextCell 4 +ca InsertCellPoint 179 +ca InsertCellPoint 180 +ca InsertCellPoint 205 +ca InsertCellPoint 204 +ca InsertNextCell 4 +ca InsertCellPoint 180 +ca InsertCellPoint 181 +ca InsertCellPoint 206 +ca InsertCellPoint 205 +ca InsertNextCell 4 +ca InsertCellPoint 181 +ca InsertCellPoint 182 +ca InsertCellPoint 207 +ca InsertCellPoint 206 +ca InsertNextCell 4 +ca InsertCellPoint 182 +ca InsertCellPoint 183 +ca InsertCellPoint 208 +ca InsertCellPoint 207 +ca InsertNextCell 4 +ca InsertCellPoint 183 +ca InsertCellPoint 184 +ca InsertCellPoint 209 +ca InsertCellPoint 208 +ca InsertNextCell 4 +ca InsertCellPoint 184 +ca InsertCellPoint 185 +ca InsertCellPoint 210 +ca InsertCellPoint 209 +ca InsertNextCell 4 +ca InsertCellPoint 185 +ca InsertCellPoint 186 +ca InsertCellPoint 211 +ca InsertCellPoint 210 +ca InsertNextCell 4 +ca InsertCellPoint 186 +ca InsertCellPoint 187 +ca InsertCellPoint 212 +ca InsertCellPoint 211 +ca InsertNextCell 4 +ca InsertCellPoint 187 +ca InsertCellPoint 188 +ca InsertCellPoint 213 +ca InsertCellPoint 212 +ca InsertNextCell 4 +ca InsertCellPoint 188 +ca InsertCellPoint 189 +ca InsertCellPoint 214 +ca InsertCellPoint 213 +ca InsertNextCell 4 +ca InsertCellPoint 189 +ca InsertCellPoint 190 +ca InsertCellPoint 215 +ca InsertCellPoint 214 +ca InsertNextCell 4 +ca InsertCellPoint 190 +ca InsertCellPoint 191 +ca InsertCellPoint 216 +ca InsertCellPoint 215 +ca InsertNextCell 4 +ca InsertCellPoint 191 +ca InsertCellPoint 192 +ca InsertCellPoint 217 +ca InsertCellPoint 216 +ca InsertNextCell 4 +ca InsertCellPoint 192 +ca InsertCellPoint 193 +ca InsertCellPoint 218 +ca InsertCellPoint 217 +ca InsertNextCell 4 +ca InsertCellPoint 193 +ca InsertCellPoint 194 +ca InsertCellPoint 219 +ca InsertCellPoint 218 +ca InsertNextCell 4 +ca InsertCellPoint 194 +ca InsertCellPoint 195 +ca InsertCellPoint 220 +ca InsertCellPoint 219 +ca InsertNextCell 4 +ca InsertCellPoint 195 +ca InsertCellPoint 196 +ca InsertCellPoint 221 +ca InsertCellPoint 220 +ca InsertNextCell 4 +ca InsertCellPoint 196 +ca InsertCellPoint 197 +ca InsertCellPoint 222 +ca InsertCellPoint 221 +ca InsertNextCell 4 +ca InsertCellPoint 197 +ca InsertCellPoint 198 +ca InsertCellPoint 223 +ca InsertCellPoint 222 +ca InsertNextCell 4 +ca InsertCellPoint 198 +ca InsertCellPoint 199 +ca InsertCellPoint 224 +ca InsertCellPoint 223 +ca InsertNextCell 4 +ca InsertCellPoint 200 +ca InsertCellPoint 201 +ca InsertCellPoint 226 +ca InsertCellPoint 225 +ca InsertNextCell 4 +ca InsertCellPoint 201 +ca InsertCellPoint 202 +ca InsertCellPoint 227 +ca InsertCellPoint 226 +ca InsertNextCell 4 +ca InsertCellPoint 202 +ca InsertCellPoint 203 +ca InsertCellPoint 228 +ca InsertCellPoint 227 +ca InsertNextCell 4 +ca InsertCellPoint 203 +ca InsertCellPoint 204 +ca InsertCellPoint 229 +ca InsertCellPoint 228 +ca InsertNextCell 4 +ca InsertCellPoint 204 +ca InsertCellPoint 205 +ca InsertCellPoint 230 +ca InsertCellPoint 229 +ca InsertNextCell 4 +ca InsertCellPoint 205 +ca InsertCellPoint 206 +ca InsertCellPoint 231 +ca InsertCellPoint 230 +ca InsertNextCell 4 +ca InsertCellPoint 206 +ca InsertCellPoint 207 +ca InsertCellPoint 232 +ca InsertCellPoint 231 +ca InsertNextCell 4 +ca InsertCellPoint 207 +ca InsertCellPoint 208 +ca InsertCellPoint 233 +ca InsertCellPoint 232 +ca InsertNextCell 4 +ca InsertCellPoint 208 +ca InsertCellPoint 209 +ca InsertCellPoint 234 +ca InsertCellPoint 233 +ca InsertNextCell 4 +ca InsertCellPoint 209 +ca InsertCellPoint 210 +ca InsertCellPoint 235 +ca InsertCellPoint 234 +ca InsertNextCell 4 +ca InsertCellPoint 210 +ca InsertCellPoint 211 +ca InsertCellPoint 236 +ca InsertCellPoint 235 +ca InsertNextCell 4 +ca InsertCellPoint 211 +ca InsertCellPoint 212 +ca InsertCellPoint 237 +ca InsertCellPoint 236 +ca InsertNextCell 4 +ca InsertCellPoint 212 +ca InsertCellPoint 213 +ca InsertCellPoint 238 +ca InsertCellPoint 237 +ca InsertNextCell 4 +ca InsertCellPoint 213 +ca InsertCellPoint 214 +ca InsertCellPoint 239 +ca InsertCellPoint 238 +ca InsertNextCell 4 +ca InsertCellPoint 214 +ca InsertCellPoint 215 +ca InsertCellPoint 240 +ca InsertCellPoint 239 +ca InsertNextCell 4 +ca InsertCellPoint 215 +ca InsertCellPoint 216 +ca InsertCellPoint 241 +ca InsertCellPoint 240 +ca InsertNextCell 4 +ca InsertCellPoint 216 +ca InsertCellPoint 217 +ca InsertCellPoint 242 +ca InsertCellPoint 241 +ca InsertNextCell 4 +ca InsertCellPoint 217 +ca InsertCellPoint 218 +ca InsertCellPoint 243 +ca InsertCellPoint 242 +ca InsertNextCell 4 +ca InsertCellPoint 218 +ca InsertCellPoint 219 +ca InsertCellPoint 244 +ca InsertCellPoint 243 +ca InsertNextCell 4 +ca InsertCellPoint 219 +ca InsertCellPoint 220 +ca InsertCellPoint 245 +ca InsertCellPoint 244 +ca InsertNextCell 4 +ca InsertCellPoint 220 +ca InsertCellPoint 221 +ca InsertCellPoint 246 +ca InsertCellPoint 245 +ca InsertNextCell 4 +ca InsertCellPoint 221 +ca InsertCellPoint 222 +ca InsertCellPoint 247 +ca InsertCellPoint 246 +ca InsertNextCell 4 +ca InsertCellPoint 222 +ca InsertCellPoint 223 +ca InsertCellPoint 248 +ca InsertCellPoint 247 +ca InsertNextCell 4 +ca InsertCellPoint 223 +ca InsertCellPoint 224 +ca InsertCellPoint 249 +ca InsertCellPoint 248 +ca InsertNextCell 4 +ca InsertCellPoint 225 +ca InsertCellPoint 226 +ca InsertCellPoint 251 +ca InsertCellPoint 250 +ca InsertNextCell 4 +ca InsertCellPoint 226 +ca InsertCellPoint 227 +ca InsertCellPoint 252 +ca InsertCellPoint 251 +ca InsertNextCell 4 +ca InsertCellPoint 227 +ca InsertCellPoint 228 +ca InsertCellPoint 253 +ca InsertCellPoint 252 +ca InsertNextCell 4 +ca InsertCellPoint 228 +ca InsertCellPoint 229 +ca InsertCellPoint 254 +ca InsertCellPoint 253 +ca InsertNextCell 4 +ca InsertCellPoint 229 +ca InsertCellPoint 230 +ca InsertCellPoint 255 +ca InsertCellPoint 254 +ca InsertNextCell 4 +ca InsertCellPoint 230 +ca InsertCellPoint 231 +ca InsertCellPoint 256 +ca InsertCellPoint 255 +ca InsertNextCell 4 +ca InsertCellPoint 231 +ca InsertCellPoint 232 +ca InsertCellPoint 257 +ca InsertCellPoint 256 +ca InsertNextCell 4 +ca InsertCellPoint 232 +ca InsertCellPoint 233 +ca InsertCellPoint 258 +ca InsertCellPoint 257 +ca InsertNextCell 4 +ca InsertCellPoint 233 +ca InsertCellPoint 234 +ca InsertCellPoint 259 +ca InsertCellPoint 258 +ca InsertNextCell 4 +ca InsertCellPoint 234 +ca InsertCellPoint 235 +ca InsertCellPoint 260 +ca InsertCellPoint 259 +ca InsertNextCell 4 +ca InsertCellPoint 235 +ca InsertCellPoint 236 +ca InsertCellPoint 261 +ca InsertCellPoint 260 +ca InsertNextCell 4 +ca InsertCellPoint 236 +ca InsertCellPoint 237 +ca InsertCellPoint 262 +ca InsertCellPoint 261 +ca InsertNextCell 4 +ca InsertCellPoint 237 +ca InsertCellPoint 238 +ca InsertCellPoint 263 +ca InsertCellPoint 262 +ca InsertNextCell 4 +ca InsertCellPoint 238 +ca InsertCellPoint 239 +ca InsertCellPoint 264 +ca InsertCellPoint 263 +ca InsertNextCell 4 +ca InsertCellPoint 239 +ca InsertCellPoint 240 +ca InsertCellPoint 265 +ca InsertCellPoint 264 +ca InsertNextCell 4 +ca InsertCellPoint 240 +ca InsertCellPoint 241 +ca InsertCellPoint 266 +ca InsertCellPoint 265 +ca InsertNextCell 4 +ca InsertCellPoint 241 +ca InsertCellPoint 242 +ca InsertCellPoint 267 +ca InsertCellPoint 266 +ca InsertNextCell 4 +ca InsertCellPoint 242 +ca InsertCellPoint 243 +ca InsertCellPoint 268 +ca InsertCellPoint 267 +ca InsertNextCell 4 +ca InsertCellPoint 243 +ca InsertCellPoint 244 +ca InsertCellPoint 269 +ca InsertCellPoint 268 +ca InsertNextCell 4 +ca InsertCellPoint 244 +ca InsertCellPoint 245 +ca InsertCellPoint 270 +ca InsertCellPoint 269 +ca InsertNextCell 4 +ca InsertCellPoint 245 +ca InsertCellPoint 246 +ca InsertCellPoint 271 +ca InsertCellPoint 270 +ca InsertNextCell 4 +ca InsertCellPoint 246 +ca InsertCellPoint 247 +ca InsertCellPoint 272 +ca InsertCellPoint 271 +ca InsertNextCell 4 +ca InsertCellPoint 247 +ca InsertCellPoint 248 +ca InsertCellPoint 273 +ca InsertCellPoint 272 +ca InsertNextCell 4 +ca InsertCellPoint 248 +ca InsertCellPoint 249 +ca InsertCellPoint 274 +ca InsertCellPoint 273 +ca InsertNextCell 4 +ca InsertCellPoint 250 +ca InsertCellPoint 251 +ca InsertCellPoint 276 +ca InsertCellPoint 275 +ca InsertNextCell 4 +ca InsertCellPoint 251 +ca InsertCellPoint 252 +ca InsertCellPoint 277 +ca InsertCellPoint 276 +ca InsertNextCell 4 +ca InsertCellPoint 252 +ca InsertCellPoint 253 +ca InsertCellPoint 278 +ca InsertCellPoint 277 +ca InsertNextCell 4 +ca InsertCellPoint 253 +ca InsertCellPoint 254 +ca InsertCellPoint 279 +ca InsertCellPoint 278 +ca InsertNextCell 4 +ca InsertCellPoint 254 +ca InsertCellPoint 255 +ca InsertCellPoint 280 +ca InsertCellPoint 279 +ca InsertNextCell 4 +ca InsertCellPoint 255 +ca InsertCellPoint 256 +ca InsertCellPoint 281 +ca InsertCellPoint 280 +ca InsertNextCell 4 +ca InsertCellPoint 256 +ca InsertCellPoint 257 +ca InsertCellPoint 282 +ca InsertCellPoint 281 +ca InsertNextCell 4 +ca InsertCellPoint 257 +ca InsertCellPoint 258 +ca InsertCellPoint 283 +ca InsertCellPoint 282 +ca InsertNextCell 4 +ca InsertCellPoint 258 +ca InsertCellPoint 259 +ca InsertCellPoint 284 +ca InsertCellPoint 283 +ca InsertNextCell 4 +ca InsertCellPoint 259 +ca InsertCellPoint 260 +ca InsertCellPoint 285 +ca InsertCellPoint 284 +ca InsertNextCell 4 +ca InsertCellPoint 260 +ca InsertCellPoint 261 +ca InsertCellPoint 286 +ca InsertCellPoint 285 +ca InsertNextCell 4 +ca InsertCellPoint 261 +ca InsertCellPoint 262 +ca InsertCellPoint 287 +ca InsertCellPoint 286 +ca InsertNextCell 4 +ca InsertCellPoint 262 +ca InsertCellPoint 263 +ca InsertCellPoint 288 +ca InsertCellPoint 287 +ca InsertNextCell 4 +ca InsertCellPoint 263 +ca InsertCellPoint 264 +ca InsertCellPoint 289 +ca InsertCellPoint 288 +ca InsertNextCell 4 +ca InsertCellPoint 264 +ca InsertCellPoint 265 +ca InsertCellPoint 290 +ca InsertCellPoint 289 +ca InsertNextCell 4 +ca InsertCellPoint 265 +ca InsertCellPoint 266 +ca InsertCellPoint 291 +ca InsertCellPoint 290 +ca InsertNextCell 4 +ca InsertCellPoint 266 +ca InsertCellPoint 267 +ca InsertCellPoint 292 +ca InsertCellPoint 291 +ca InsertNextCell 4 +ca InsertCellPoint 267 +ca InsertCellPoint 268 +ca InsertCellPoint 293 +ca InsertCellPoint 292 +ca InsertNextCell 4 +ca InsertCellPoint 268 +ca InsertCellPoint 269 +ca InsertCellPoint 294 +ca InsertCellPoint 293 +ca InsertNextCell 4 +ca InsertCellPoint 269 +ca InsertCellPoint 270 +ca InsertCellPoint 295 +ca InsertCellPoint 294 +ca InsertNextCell 4 +ca InsertCellPoint 270 +ca InsertCellPoint 271 +ca InsertCellPoint 296 +ca InsertCellPoint 295 +ca InsertNextCell 4 +ca InsertCellPoint 271 +ca InsertCellPoint 272 +ca InsertCellPoint 297 +ca InsertCellPoint 296 +ca InsertNextCell 4 +ca InsertCellPoint 272 +ca InsertCellPoint 273 +ca InsertCellPoint 298 +ca InsertCellPoint 297 +ca InsertNextCell 4 +ca InsertCellPoint 273 +ca InsertCellPoint 274 +ca InsertCellPoint 299 +ca InsertCellPoint 298 +ca InsertNextCell 4 +ca InsertCellPoint 275 +ca InsertCellPoint 276 +ca InsertCellPoint 301 +ca InsertCellPoint 300 +ca InsertNextCell 4 +ca InsertCellPoint 276 +ca InsertCellPoint 277 +ca InsertCellPoint 302 +ca InsertCellPoint 301 +ca InsertNextCell 4 +ca InsertCellPoint 277 +ca InsertCellPoint 278 +ca InsertCellPoint 303 +ca InsertCellPoint 302 +ca InsertNextCell 4 +ca InsertCellPoint 278 +ca InsertCellPoint 279 +ca InsertCellPoint 304 +ca InsertCellPoint 303 +ca InsertNextCell 4 +ca InsertCellPoint 279 +ca InsertCellPoint 280 +ca InsertCellPoint 305 +ca InsertCellPoint 304 +ca InsertNextCell 4 +ca InsertCellPoint 280 +ca InsertCellPoint 281 +ca InsertCellPoint 306 +ca InsertCellPoint 305 +ca InsertNextCell 4 +ca InsertCellPoint 281 +ca InsertCellPoint 282 +ca InsertCellPoint 307 +ca InsertCellPoint 306 +ca InsertNextCell 4 +ca InsertCellPoint 282 +ca InsertCellPoint 283 +ca InsertCellPoint 308 +ca InsertCellPoint 307 +ca InsertNextCell 4 +ca InsertCellPoint 283 +ca InsertCellPoint 284 +ca InsertCellPoint 309 +ca InsertCellPoint 308 +ca InsertNextCell 4 +ca InsertCellPoint 284 +ca InsertCellPoint 285 +ca InsertCellPoint 310 +ca InsertCellPoint 309 +ca InsertNextCell 4 +ca InsertCellPoint 285 +ca InsertCellPoint 286 +ca InsertCellPoint 311 +ca InsertCellPoint 310 +ca InsertNextCell 4 +ca InsertCellPoint 286 +ca InsertCellPoint 287 +ca InsertCellPoint 312 +ca InsertCellPoint 311 +ca InsertNextCell 4 +ca InsertCellPoint 287 +ca InsertCellPoint 288 +ca InsertCellPoint 313 +ca InsertCellPoint 312 +ca InsertNextCell 4 +ca InsertCellPoint 288 +ca InsertCellPoint 289 +ca InsertCellPoint 314 +ca InsertCellPoint 313 +ca InsertNextCell 4 +ca InsertCellPoint 289 +ca InsertCellPoint 290 +ca InsertCellPoint 315 +ca InsertCellPoint 314 +ca InsertNextCell 4 +ca InsertCellPoint 290 +ca InsertCellPoint 291 +ca InsertCellPoint 316 +ca InsertCellPoint 315 +ca InsertNextCell 4 +ca InsertCellPoint 291 +ca InsertCellPoint 292 +ca InsertCellPoint 317 +ca InsertCellPoint 316 +ca InsertNextCell 4 +ca InsertCellPoint 292 +ca InsertCellPoint 293 +ca InsertCellPoint 318 +ca InsertCellPoint 317 +ca InsertNextCell 4 +ca InsertCellPoint 293 +ca InsertCellPoint 294 +ca InsertCellPoint 319 +ca InsertCellPoint 318 +ca InsertNextCell 4 +ca InsertCellPoint 294 +ca InsertCellPoint 295 +ca InsertCellPoint 320 +ca InsertCellPoint 319 +ca InsertNextCell 4 +ca InsertCellPoint 295 +ca InsertCellPoint 296 +ca InsertCellPoint 321 +ca InsertCellPoint 320 +ca InsertNextCell 4 +ca InsertCellPoint 296 +ca InsertCellPoint 297 +ca InsertCellPoint 322 +ca InsertCellPoint 321 +ca InsertNextCell 4 +ca InsertCellPoint 297 +ca InsertCellPoint 298 +ca InsertCellPoint 323 +ca InsertCellPoint 322 +ca InsertNextCell 4 +ca InsertCellPoint 298 +ca InsertCellPoint 299 +ca InsertCellPoint 324 +ca InsertCellPoint 323 +ca InsertNextCell 4 +ca InsertCellPoint 300 +ca InsertCellPoint 301 +ca InsertCellPoint 326 +ca InsertCellPoint 325 +ca InsertNextCell 4 +ca InsertCellPoint 301 +ca InsertCellPoint 302 +ca InsertCellPoint 327 +ca InsertCellPoint 326 +ca InsertNextCell 4 +ca InsertCellPoint 302 +ca InsertCellPoint 303 +ca InsertCellPoint 328 +ca InsertCellPoint 327 +ca InsertNextCell 4 +ca InsertCellPoint 303 +ca InsertCellPoint 304 +ca InsertCellPoint 329 +ca InsertCellPoint 328 +ca InsertNextCell 4 +ca InsertCellPoint 304 +ca InsertCellPoint 305 +ca InsertCellPoint 330 +ca InsertCellPoint 329 +ca InsertNextCell 4 +ca InsertCellPoint 305 +ca InsertCellPoint 306 +ca InsertCellPoint 331 +ca InsertCellPoint 330 +ca InsertNextCell 4 +ca InsertCellPoint 306 +ca InsertCellPoint 307 +ca InsertCellPoint 332 +ca InsertCellPoint 331 +ca InsertNextCell 4 +ca InsertCellPoint 307 +ca InsertCellPoint 308 +ca InsertCellPoint 333 +ca InsertCellPoint 332 +ca InsertNextCell 4 +ca InsertCellPoint 308 +ca InsertCellPoint 309 +ca InsertCellPoint 334 +ca InsertCellPoint 333 +ca InsertNextCell 4 +ca InsertCellPoint 309 +ca InsertCellPoint 310 +ca InsertCellPoint 335 +ca InsertCellPoint 334 +ca InsertNextCell 4 +ca InsertCellPoint 310 +ca InsertCellPoint 311 +ca InsertCellPoint 336 +ca InsertCellPoint 335 +ca InsertNextCell 4 +ca InsertCellPoint 311 +ca InsertCellPoint 312 +ca InsertCellPoint 337 +ca InsertCellPoint 336 +ca InsertNextCell 4 +ca InsertCellPoint 312 +ca InsertCellPoint 313 +ca InsertCellPoint 338 +ca InsertCellPoint 337 +ca InsertNextCell 4 +ca InsertCellPoint 313 +ca InsertCellPoint 314 +ca InsertCellPoint 339 +ca InsertCellPoint 338 +ca InsertNextCell 4 +ca InsertCellPoint 314 +ca InsertCellPoint 315 +ca InsertCellPoint 340 +ca InsertCellPoint 339 +ca InsertNextCell 4 +ca InsertCellPoint 315 +ca InsertCellPoint 316 +ca InsertCellPoint 341 +ca InsertCellPoint 340 +ca InsertNextCell 4 +ca InsertCellPoint 316 +ca InsertCellPoint 317 +ca InsertCellPoint 342 +ca InsertCellPoint 341 +ca InsertNextCell 4 +ca InsertCellPoint 317 +ca InsertCellPoint 318 +ca InsertCellPoint 343 +ca InsertCellPoint 342 +ca InsertNextCell 4 +ca InsertCellPoint 318 +ca InsertCellPoint 319 +ca InsertCellPoint 344 +ca InsertCellPoint 343 +ca InsertNextCell 4 +ca InsertCellPoint 319 +ca InsertCellPoint 320 +ca InsertCellPoint 345 +ca InsertCellPoint 344 +ca InsertNextCell 4 +ca InsertCellPoint 320 +ca InsertCellPoint 321 +ca InsertCellPoint 346 +ca InsertCellPoint 345 +ca InsertNextCell 4 +ca InsertCellPoint 321 +ca InsertCellPoint 322 +ca InsertCellPoint 347 +ca InsertCellPoint 346 +ca InsertNextCell 4 +ca InsertCellPoint 322 +ca InsertCellPoint 323 +ca InsertCellPoint 348 +ca InsertCellPoint 347 +ca InsertNextCell 4 +ca InsertCellPoint 323 +ca InsertCellPoint 324 +ca InsertCellPoint 349 +ca InsertCellPoint 348 +ca InsertNextCell 4 +ca InsertCellPoint 325 +ca InsertCellPoint 326 +ca InsertCellPoint 351 +ca InsertCellPoint 350 +ca InsertNextCell 4 +ca InsertCellPoint 326 +ca InsertCellPoint 327 +ca InsertCellPoint 352 +ca InsertCellPoint 351 +ca InsertNextCell 4 +ca InsertCellPoint 327 +ca InsertCellPoint 328 +ca InsertCellPoint 353 +ca InsertCellPoint 352 +ca InsertNextCell 4 +ca InsertCellPoint 328 +ca InsertCellPoint 329 +ca InsertCellPoint 354 +ca InsertCellPoint 353 +ca InsertNextCell 4 +ca InsertCellPoint 329 +ca InsertCellPoint 330 +ca InsertCellPoint 355 +ca InsertCellPoint 354 +ca InsertNextCell 4 +ca InsertCellPoint 330 +ca InsertCellPoint 331 +ca InsertCellPoint 356 +ca InsertCellPoint 355 +ca InsertNextCell 4 +ca InsertCellPoint 331 +ca InsertCellPoint 332 +ca InsertCellPoint 357 +ca InsertCellPoint 356 +ca InsertNextCell 4 +ca InsertCellPoint 332 +ca InsertCellPoint 333 +ca InsertCellPoint 358 +ca InsertCellPoint 357 +ca InsertNextCell 4 +ca InsertCellPoint 333 +ca InsertCellPoint 334 +ca InsertCellPoint 359 +ca InsertCellPoint 358 +ca InsertNextCell 4 +ca InsertCellPoint 334 +ca InsertCellPoint 335 +ca InsertCellPoint 360 +ca InsertCellPoint 359 +ca InsertNextCell 4 +ca InsertCellPoint 335 +ca InsertCellPoint 336 +ca InsertCellPoint 361 +ca InsertCellPoint 360 +ca InsertNextCell 4 +ca InsertCellPoint 336 +ca InsertCellPoint 337 +ca InsertCellPoint 362 +ca InsertCellPoint 361 +ca InsertNextCell 4 +ca InsertCellPoint 337 +ca InsertCellPoint 338 +ca InsertCellPoint 363 +ca InsertCellPoint 362 +ca InsertNextCell 4 +ca InsertCellPoint 338 +ca InsertCellPoint 339 +ca InsertCellPoint 364 +ca InsertCellPoint 363 +ca InsertNextCell 4 +ca InsertCellPoint 339 +ca InsertCellPoint 340 +ca InsertCellPoint 365 +ca InsertCellPoint 364 +ca InsertNextCell 4 +ca InsertCellPoint 340 +ca InsertCellPoint 341 +ca InsertCellPoint 366 +ca InsertCellPoint 365 +ca InsertNextCell 4 +ca InsertCellPoint 341 +ca InsertCellPoint 342 +ca InsertCellPoint 367 +ca InsertCellPoint 366 +ca InsertNextCell 4 +ca InsertCellPoint 342 +ca InsertCellPoint 343 +ca InsertCellPoint 368 +ca InsertCellPoint 367 +ca InsertNextCell 4 +ca InsertCellPoint 343 +ca InsertCellPoint 344 +ca InsertCellPoint 369 +ca InsertCellPoint 368 +ca InsertNextCell 4 +ca InsertCellPoint 344 +ca InsertCellPoint 345 +ca InsertCellPoint 370 +ca InsertCellPoint 369 +ca InsertNextCell 4 +ca InsertCellPoint 345 +ca InsertCellPoint 346 +ca InsertCellPoint 371 +ca InsertCellPoint 370 +ca InsertNextCell 4 +ca InsertCellPoint 346 +ca InsertCellPoint 347 +ca InsertCellPoint 372 +ca InsertCellPoint 371 +ca InsertNextCell 4 +ca InsertCellPoint 347 +ca InsertCellPoint 348 +ca InsertCellPoint 373 +ca InsertCellPoint 372 +ca InsertNextCell 4 +ca InsertCellPoint 348 +ca InsertCellPoint 349 +ca InsertCellPoint 374 +ca InsertCellPoint 373 +ca InsertNextCell 4 +ca InsertCellPoint 350 +ca InsertCellPoint 351 +ca InsertCellPoint 376 +ca InsertCellPoint 375 +ca InsertNextCell 4 +ca InsertCellPoint 351 +ca InsertCellPoint 352 +ca InsertCellPoint 377 +ca InsertCellPoint 376 +ca InsertNextCell 4 +ca InsertCellPoint 352 +ca InsertCellPoint 353 +ca InsertCellPoint 378 +ca InsertCellPoint 377 +ca InsertNextCell 4 +ca InsertCellPoint 353 +ca InsertCellPoint 354 +ca InsertCellPoint 379 +ca InsertCellPoint 378 +ca InsertNextCell 4 +ca InsertCellPoint 354 +ca InsertCellPoint 355 +ca InsertCellPoint 380 +ca InsertCellPoint 379 +ca InsertNextCell 4 +ca InsertCellPoint 355 +ca InsertCellPoint 356 +ca InsertCellPoint 381 +ca InsertCellPoint 380 +ca InsertNextCell 4 +ca InsertCellPoint 356 +ca InsertCellPoint 357 +ca InsertCellPoint 382 +ca InsertCellPoint 381 +ca InsertNextCell 4 +ca InsertCellPoint 357 +ca InsertCellPoint 358 +ca InsertCellPoint 383 +ca InsertCellPoint 382 +ca InsertNextCell 4 +ca InsertCellPoint 358 +ca InsertCellPoint 359 +ca InsertCellPoint 384 +ca InsertCellPoint 383 +ca InsertNextCell 4 +ca InsertCellPoint 359 +ca InsertCellPoint 360 +ca InsertCellPoint 385 +ca InsertCellPoint 384 +ca InsertNextCell 4 +ca InsertCellPoint 360 +ca InsertCellPoint 361 +ca InsertCellPoint 386 +ca InsertCellPoint 385 +ca InsertNextCell 4 +ca InsertCellPoint 361 +ca InsertCellPoint 362 +ca InsertCellPoint 387 +ca InsertCellPoint 386 +ca InsertNextCell 4 +ca InsertCellPoint 362 +ca InsertCellPoint 363 +ca InsertCellPoint 388 +ca InsertCellPoint 387 +ca InsertNextCell 4 +ca InsertCellPoint 363 +ca InsertCellPoint 364 +ca InsertCellPoint 389 +ca InsertCellPoint 388 +ca InsertNextCell 4 +ca InsertCellPoint 364 +ca InsertCellPoint 365 +ca InsertCellPoint 390 +ca InsertCellPoint 389 +ca InsertNextCell 4 +ca InsertCellPoint 365 +ca InsertCellPoint 366 +ca InsertCellPoint 391 +ca InsertCellPoint 390 +ca InsertNextCell 4 +ca InsertCellPoint 366 +ca InsertCellPoint 367 +ca InsertCellPoint 392 +ca InsertCellPoint 391 +ca InsertNextCell 4 +ca InsertCellPoint 367 +ca InsertCellPoint 368 +ca InsertCellPoint 393 +ca InsertCellPoint 392 +ca InsertNextCell 4 +ca InsertCellPoint 368 +ca InsertCellPoint 369 +ca InsertCellPoint 394 +ca InsertCellPoint 393 +ca InsertNextCell 4 +ca InsertCellPoint 369 +ca InsertCellPoint 370 +ca InsertCellPoint 395 +ca InsertCellPoint 394 +ca InsertNextCell 4 +ca InsertCellPoint 370 +ca InsertCellPoint 371 +ca InsertCellPoint 396 +ca InsertCellPoint 395 +ca InsertNextCell 4 +ca InsertCellPoint 371 +ca InsertCellPoint 372 +ca InsertCellPoint 397 +ca InsertCellPoint 396 +ca InsertNextCell 4 +ca InsertCellPoint 372 +ca InsertCellPoint 373 +ca InsertCellPoint 398 +ca InsertCellPoint 397 +ca InsertNextCell 4 +ca InsertCellPoint 373 +ca InsertCellPoint 374 +ca InsertCellPoint 399 +ca InsertCellPoint 398 +ca InsertNextCell 4 +ca InsertCellPoint 375 +ca InsertCellPoint 376 +ca InsertCellPoint 401 +ca InsertCellPoint 400 +ca InsertNextCell 4 +ca InsertCellPoint 376 +ca InsertCellPoint 377 +ca InsertCellPoint 402 +ca InsertCellPoint 401 +ca InsertNextCell 4 +ca InsertCellPoint 377 +ca InsertCellPoint 378 +ca InsertCellPoint 403 +ca InsertCellPoint 402 +ca InsertNextCell 4 +ca InsertCellPoint 378 +ca InsertCellPoint 379 +ca InsertCellPoint 404 +ca InsertCellPoint 403 +ca InsertNextCell 4 +ca InsertCellPoint 379 +ca InsertCellPoint 380 +ca InsertCellPoint 405 +ca InsertCellPoint 404 +ca InsertNextCell 4 +ca InsertCellPoint 380 +ca InsertCellPoint 381 +ca InsertCellPoint 406 +ca InsertCellPoint 405 +ca InsertNextCell 4 +ca InsertCellPoint 381 +ca InsertCellPoint 382 +ca InsertCellPoint 407 +ca InsertCellPoint 406 +ca InsertNextCell 4 +ca InsertCellPoint 382 +ca InsertCellPoint 383 +ca InsertCellPoint 408 +ca InsertCellPoint 407 +ca InsertNextCell 4 +ca InsertCellPoint 383 +ca InsertCellPoint 384 +ca InsertCellPoint 409 +ca InsertCellPoint 408 +ca InsertNextCell 4 +ca InsertCellPoint 384 +ca InsertCellPoint 385 +ca InsertCellPoint 410 +ca InsertCellPoint 409 +ca InsertNextCell 4 +ca InsertCellPoint 385 +ca InsertCellPoint 386 +ca InsertCellPoint 411 +ca InsertCellPoint 410 +ca InsertNextCell 4 +ca InsertCellPoint 386 +ca InsertCellPoint 387 +ca InsertCellPoint 412 +ca InsertCellPoint 411 +ca InsertNextCell 4 +ca InsertCellPoint 387 +ca InsertCellPoint 388 +ca InsertCellPoint 413 +ca InsertCellPoint 412 +ca InsertNextCell 4 +ca InsertCellPoint 388 +ca InsertCellPoint 389 +ca InsertCellPoint 414 +ca InsertCellPoint 413 +ca InsertNextCell 4 +ca InsertCellPoint 389 +ca InsertCellPoint 390 +ca InsertCellPoint 415 +ca InsertCellPoint 414 +ca InsertNextCell 4 +ca InsertCellPoint 390 +ca InsertCellPoint 391 +ca InsertCellPoint 416 +ca InsertCellPoint 415 +ca InsertNextCell 4 +ca InsertCellPoint 391 +ca InsertCellPoint 392 +ca InsertCellPoint 417 +ca InsertCellPoint 416 +ca InsertNextCell 4 +ca InsertCellPoint 392 +ca InsertCellPoint 393 +ca InsertCellPoint 418 +ca InsertCellPoint 417 +ca InsertNextCell 4 +ca InsertCellPoint 393 +ca InsertCellPoint 394 +ca InsertCellPoint 419 +ca InsertCellPoint 418 +ca InsertNextCell 4 +ca InsertCellPoint 394 +ca InsertCellPoint 395 +ca InsertCellPoint 420 +ca InsertCellPoint 419 +ca InsertNextCell 4 +ca InsertCellPoint 395 +ca InsertCellPoint 396 +ca InsertCellPoint 421 +ca InsertCellPoint 420 +ca InsertNextCell 4 +ca InsertCellPoint 396 +ca InsertCellPoint 397 +ca InsertCellPoint 422 +ca InsertCellPoint 421 +ca InsertNextCell 4 +ca InsertCellPoint 397 +ca InsertCellPoint 398 +ca InsertCellPoint 423 +ca InsertCellPoint 422 +ca InsertNextCell 4 +ca InsertCellPoint 398 +ca InsertCellPoint 399 +ca InsertCellPoint 424 +ca InsertCellPoint 423 +ca InsertNextCell 4 +ca InsertCellPoint 400 +ca InsertCellPoint 401 +ca InsertCellPoint 426 +ca InsertCellPoint 425 +ca InsertNextCell 4 +ca InsertCellPoint 401 +ca InsertCellPoint 402 +ca InsertCellPoint 427 +ca InsertCellPoint 426 +ca InsertNextCell 4 +ca InsertCellPoint 402 +ca InsertCellPoint 403 +ca InsertCellPoint 428 +ca InsertCellPoint 427 +ca InsertNextCell 4 +ca InsertCellPoint 403 +ca InsertCellPoint 404 +ca InsertCellPoint 429 +ca InsertCellPoint 428 +ca InsertNextCell 4 +ca InsertCellPoint 404 +ca InsertCellPoint 405 +ca InsertCellPoint 430 +ca InsertCellPoint 429 +ca InsertNextCell 4 +ca InsertCellPoint 405 +ca InsertCellPoint 406 +ca InsertCellPoint 431 +ca InsertCellPoint 430 +ca InsertNextCell 4 +ca InsertCellPoint 406 +ca InsertCellPoint 407 +ca InsertCellPoint 432 +ca InsertCellPoint 431 +ca InsertNextCell 4 +ca InsertCellPoint 407 +ca InsertCellPoint 408 +ca InsertCellPoint 433 +ca InsertCellPoint 432 +ca InsertNextCell 4 +ca InsertCellPoint 408 +ca InsertCellPoint 409 +ca InsertCellPoint 434 +ca InsertCellPoint 433 +ca InsertNextCell 4 +ca InsertCellPoint 409 +ca InsertCellPoint 410 +ca InsertCellPoint 435 +ca InsertCellPoint 434 +ca InsertNextCell 4 +ca InsertCellPoint 410 +ca InsertCellPoint 411 +ca InsertCellPoint 436 +ca InsertCellPoint 435 +ca InsertNextCell 4 +ca InsertCellPoint 411 +ca InsertCellPoint 412 +ca InsertCellPoint 437 +ca InsertCellPoint 436 +ca InsertNextCell 4 +ca InsertCellPoint 412 +ca InsertCellPoint 413 +ca InsertCellPoint 438 +ca InsertCellPoint 437 +ca InsertNextCell 4 +ca InsertCellPoint 413 +ca InsertCellPoint 414 +ca InsertCellPoint 439 +ca InsertCellPoint 438 +ca InsertNextCell 4 +ca InsertCellPoint 414 +ca InsertCellPoint 415 +ca InsertCellPoint 440 +ca InsertCellPoint 439 +ca InsertNextCell 4 +ca InsertCellPoint 415 +ca InsertCellPoint 416 +ca InsertCellPoint 441 +ca InsertCellPoint 440 +ca InsertNextCell 4 +ca InsertCellPoint 416 +ca InsertCellPoint 417 +ca InsertCellPoint 442 +ca InsertCellPoint 441 +ca InsertNextCell 4 +ca InsertCellPoint 417 +ca InsertCellPoint 418 +ca InsertCellPoint 443 +ca InsertCellPoint 442 +ca InsertNextCell 4 +ca InsertCellPoint 418 +ca InsertCellPoint 419 +ca InsertCellPoint 444 +ca InsertCellPoint 443 +ca InsertNextCell 4 +ca InsertCellPoint 419 +ca InsertCellPoint 420 +ca InsertCellPoint 445 +ca InsertCellPoint 444 +ca InsertNextCell 4 +ca InsertCellPoint 420 +ca InsertCellPoint 421 +ca InsertCellPoint 446 +ca InsertCellPoint 445 +ca InsertNextCell 4 +ca InsertCellPoint 421 +ca InsertCellPoint 422 +ca InsertCellPoint 447 +ca InsertCellPoint 446 +ca InsertNextCell 4 +ca InsertCellPoint 422 +ca InsertCellPoint 423 +ca InsertCellPoint 448 +ca InsertCellPoint 447 +ca InsertNextCell 4 +ca InsertCellPoint 423 +ca InsertCellPoint 424 +ca InsertCellPoint 449 +ca InsertCellPoint 448 +ca InsertNextCell 4 +ca InsertCellPoint 425 +ca InsertCellPoint 426 +ca InsertCellPoint 451 +ca InsertCellPoint 450 +ca InsertNextCell 4 +ca InsertCellPoint 426 +ca InsertCellPoint 427 +ca InsertCellPoint 452 +ca InsertCellPoint 451 +ca InsertNextCell 4 +ca InsertCellPoint 427 +ca InsertCellPoint 428 +ca InsertCellPoint 453 +ca InsertCellPoint 452 +ca InsertNextCell 4 +ca InsertCellPoint 428 +ca InsertCellPoint 429 +ca InsertCellPoint 454 +ca InsertCellPoint 453 +ca InsertNextCell 4 +ca InsertCellPoint 429 +ca InsertCellPoint 430 +ca InsertCellPoint 455 +ca InsertCellPoint 454 +ca InsertNextCell 4 +ca InsertCellPoint 430 +ca InsertCellPoint 431 +ca InsertCellPoint 456 +ca InsertCellPoint 455 +ca InsertNextCell 4 +ca InsertCellPoint 431 +ca InsertCellPoint 432 +ca InsertCellPoint 457 +ca InsertCellPoint 456 +ca InsertNextCell 4 +ca InsertCellPoint 432 +ca InsertCellPoint 433 +ca InsertCellPoint 458 +ca InsertCellPoint 457 +ca InsertNextCell 4 +ca InsertCellPoint 433 +ca InsertCellPoint 434 +ca InsertCellPoint 459 +ca InsertCellPoint 458 +ca InsertNextCell 4 +ca InsertCellPoint 434 +ca InsertCellPoint 435 +ca InsertCellPoint 460 +ca InsertCellPoint 459 +ca InsertNextCell 4 +ca InsertCellPoint 435 +ca InsertCellPoint 436 +ca InsertCellPoint 461 +ca InsertCellPoint 460 +ca InsertNextCell 4 +ca InsertCellPoint 436 +ca InsertCellPoint 437 +ca InsertCellPoint 462 +ca InsertCellPoint 461 +ca InsertNextCell 4 +ca InsertCellPoint 437 +ca InsertCellPoint 438 +ca InsertCellPoint 463 +ca InsertCellPoint 462 +ca InsertNextCell 4 +ca InsertCellPoint 438 +ca InsertCellPoint 439 +ca InsertCellPoint 464 +ca InsertCellPoint 463 +ca InsertNextCell 4 +ca InsertCellPoint 439 +ca InsertCellPoint 440 +ca InsertCellPoint 465 +ca InsertCellPoint 464 +ca InsertNextCell 4 +ca InsertCellPoint 440 +ca InsertCellPoint 441 +ca InsertCellPoint 466 +ca InsertCellPoint 465 +ca InsertNextCell 4 +ca InsertCellPoint 441 +ca InsertCellPoint 442 +ca InsertCellPoint 467 +ca InsertCellPoint 466 +ca InsertNextCell 4 +ca InsertCellPoint 442 +ca InsertCellPoint 443 +ca InsertCellPoint 468 +ca InsertCellPoint 467 +ca InsertNextCell 4 +ca InsertCellPoint 443 +ca InsertCellPoint 444 +ca InsertCellPoint 469 +ca InsertCellPoint 468 +ca InsertNextCell 4 +ca InsertCellPoint 444 +ca InsertCellPoint 445 +ca InsertCellPoint 470 +ca InsertCellPoint 469 +ca InsertNextCell 4 +ca InsertCellPoint 445 +ca InsertCellPoint 446 +ca InsertCellPoint 471 +ca InsertCellPoint 470 +ca InsertNextCell 4 +ca InsertCellPoint 446 +ca InsertCellPoint 447 +ca InsertCellPoint 472 +ca InsertCellPoint 471 +ca InsertNextCell 4 +ca InsertCellPoint 447 +ca InsertCellPoint 448 +ca InsertCellPoint 473 +ca InsertCellPoint 472 +ca InsertNextCell 4 +ca InsertCellPoint 448 +ca InsertCellPoint 449 +ca InsertCellPoint 474 +ca InsertCellPoint 473 +ca InsertNextCell 4 +ca InsertCellPoint 450 +ca InsertCellPoint 451 +ca InsertCellPoint 476 +ca InsertCellPoint 475 +ca InsertNextCell 4 +ca InsertCellPoint 451 +ca InsertCellPoint 452 +ca InsertCellPoint 477 +ca InsertCellPoint 476 +ca InsertNextCell 4 +ca InsertCellPoint 452 +ca InsertCellPoint 453 +ca InsertCellPoint 478 +ca InsertCellPoint 477 +ca InsertNextCell 4 +ca InsertCellPoint 453 +ca InsertCellPoint 454 +ca InsertCellPoint 479 +ca InsertCellPoint 478 +ca InsertNextCell 4 +ca InsertCellPoint 454 +ca InsertCellPoint 455 +ca InsertCellPoint 480 +ca InsertCellPoint 479 +ca InsertNextCell 4 +ca InsertCellPoint 455 +ca InsertCellPoint 456 +ca InsertCellPoint 481 +ca InsertCellPoint 480 +ca InsertNextCell 4 +ca InsertCellPoint 456 +ca InsertCellPoint 457 +ca InsertCellPoint 482 +ca InsertCellPoint 481 +ca InsertNextCell 4 +ca InsertCellPoint 457 +ca InsertCellPoint 458 +ca InsertCellPoint 483 +ca InsertCellPoint 482 +ca InsertNextCell 4 +ca InsertCellPoint 458 +ca InsertCellPoint 459 +ca InsertCellPoint 484 +ca InsertCellPoint 483 +ca InsertNextCell 4 +ca InsertCellPoint 459 +ca InsertCellPoint 460 +ca InsertCellPoint 485 +ca InsertCellPoint 484 +ca InsertNextCell 4 +ca InsertCellPoint 460 +ca InsertCellPoint 461 +ca InsertCellPoint 486 +ca InsertCellPoint 485 +ca InsertNextCell 4 +ca InsertCellPoint 461 +ca InsertCellPoint 462 +ca InsertCellPoint 487 +ca InsertCellPoint 486 +ca InsertNextCell 4 +ca InsertCellPoint 462 +ca InsertCellPoint 463 +ca InsertCellPoint 488 +ca InsertCellPoint 487 +ca InsertNextCell 4 +ca InsertCellPoint 463 +ca InsertCellPoint 464 +ca InsertCellPoint 489 +ca InsertCellPoint 488 +ca InsertNextCell 4 +ca InsertCellPoint 464 +ca InsertCellPoint 465 +ca InsertCellPoint 490 +ca InsertCellPoint 489 +ca InsertNextCell 4 +ca InsertCellPoint 465 +ca InsertCellPoint 466 +ca InsertCellPoint 491 +ca InsertCellPoint 490 +ca InsertNextCell 4 +ca InsertCellPoint 466 +ca InsertCellPoint 467 +ca InsertCellPoint 492 +ca InsertCellPoint 491 +ca InsertNextCell 4 +ca InsertCellPoint 467 +ca InsertCellPoint 468 +ca InsertCellPoint 493 +ca InsertCellPoint 492 +ca InsertNextCell 4 +ca InsertCellPoint 468 +ca InsertCellPoint 469 +ca InsertCellPoint 494 +ca InsertCellPoint 493 +ca InsertNextCell 4 +ca InsertCellPoint 469 +ca InsertCellPoint 470 +ca InsertCellPoint 495 +ca InsertCellPoint 494 +ca InsertNextCell 4 +ca InsertCellPoint 470 +ca InsertCellPoint 471 +ca InsertCellPoint 496 +ca InsertCellPoint 495 +ca InsertNextCell 4 +ca InsertCellPoint 471 +ca InsertCellPoint 472 +ca InsertCellPoint 497 +ca InsertCellPoint 496 +ca InsertNextCell 4 +ca InsertCellPoint 472 +ca InsertCellPoint 473 +ca InsertCellPoint 498 +ca InsertCellPoint 497 +ca InsertNextCell 4 +ca InsertCellPoint 473 +ca InsertCellPoint 474 +ca InsertCellPoint 499 +ca InsertCellPoint 498 +ca InsertNextCell 4 +ca InsertCellPoint 475 +ca InsertCellPoint 476 +ca InsertCellPoint 501 +ca InsertCellPoint 500 +ca InsertNextCell 4 +ca InsertCellPoint 476 +ca InsertCellPoint 477 +ca InsertCellPoint 502 +ca InsertCellPoint 501 +ca InsertNextCell 4 +ca InsertCellPoint 477 +ca InsertCellPoint 478 +ca InsertCellPoint 503 +ca InsertCellPoint 502 +ca InsertNextCell 4 +ca InsertCellPoint 478 +ca InsertCellPoint 479 +ca InsertCellPoint 504 +ca InsertCellPoint 503 +ca InsertNextCell 4 +ca InsertCellPoint 479 +ca InsertCellPoint 480 +ca InsertCellPoint 505 +ca InsertCellPoint 504 +ca InsertNextCell 4 +ca InsertCellPoint 480 +ca InsertCellPoint 481 +ca InsertCellPoint 506 +ca InsertCellPoint 505 +ca InsertNextCell 4 +ca InsertCellPoint 481 +ca InsertCellPoint 482 +ca InsertCellPoint 507 +ca InsertCellPoint 506 +ca InsertNextCell 4 +ca InsertCellPoint 482 +ca InsertCellPoint 483 +ca InsertCellPoint 508 +ca InsertCellPoint 507 +ca InsertNextCell 4 +ca InsertCellPoint 483 +ca InsertCellPoint 484 +ca InsertCellPoint 509 +ca InsertCellPoint 508 +ca InsertNextCell 4 +ca InsertCellPoint 484 +ca InsertCellPoint 485 +ca InsertCellPoint 510 +ca InsertCellPoint 509 +ca InsertNextCell 4 +ca InsertCellPoint 485 +ca InsertCellPoint 486 +ca InsertCellPoint 511 +ca InsertCellPoint 510 +ca InsertNextCell 4 +ca InsertCellPoint 486 +ca InsertCellPoint 487 +ca InsertCellPoint 512 +ca InsertCellPoint 511 +ca InsertNextCell 4 +ca InsertCellPoint 487 +ca InsertCellPoint 488 +ca InsertCellPoint 513 +ca InsertCellPoint 512 +ca InsertNextCell 4 +ca InsertCellPoint 488 +ca InsertCellPoint 489 +ca InsertCellPoint 514 +ca InsertCellPoint 513 +ca InsertNextCell 4 +ca InsertCellPoint 489 +ca InsertCellPoint 490 +ca InsertCellPoint 515 +ca InsertCellPoint 514 +ca InsertNextCell 4 +ca InsertCellPoint 490 +ca InsertCellPoint 491 +ca InsertCellPoint 516 +ca InsertCellPoint 515 +ca InsertNextCell 4 +ca InsertCellPoint 491 +ca InsertCellPoint 492 +ca InsertCellPoint 517 +ca InsertCellPoint 516 +ca InsertNextCell 4 +ca InsertCellPoint 492 +ca InsertCellPoint 493 +ca InsertCellPoint 518 +ca InsertCellPoint 517 +ca InsertNextCell 4 +ca InsertCellPoint 493 +ca InsertCellPoint 494 +ca InsertCellPoint 519 +ca InsertCellPoint 518 +ca InsertNextCell 4 +ca InsertCellPoint 494 +ca InsertCellPoint 495 +ca InsertCellPoint 520 +ca InsertCellPoint 519 +ca InsertNextCell 4 +ca InsertCellPoint 495 +ca InsertCellPoint 496 +ca InsertCellPoint 521 +ca InsertCellPoint 520 +ca InsertNextCell 4 +ca InsertCellPoint 496 +ca InsertCellPoint 497 +ca InsertCellPoint 522 +ca InsertCellPoint 521 +ca InsertNextCell 4 +ca InsertCellPoint 497 +ca InsertCellPoint 498 +ca InsertCellPoint 523 +ca InsertCellPoint 522 +ca InsertNextCell 4 +ca InsertCellPoint 498 +ca InsertCellPoint 499 +ca InsertCellPoint 524 +ca InsertCellPoint 523 +ca InsertNextCell 4 +ca InsertCellPoint 500 +ca InsertCellPoint 501 +ca InsertCellPoint 526 +ca InsertCellPoint 525 +ca InsertNextCell 4 +ca InsertCellPoint 501 +ca InsertCellPoint 502 +ca InsertCellPoint 527 +ca InsertCellPoint 526 +ca InsertNextCell 4 +ca InsertCellPoint 502 +ca InsertCellPoint 503 +ca InsertCellPoint 528 +ca InsertCellPoint 527 +ca InsertNextCell 4 +ca InsertCellPoint 503 +ca InsertCellPoint 504 +ca InsertCellPoint 529 +ca InsertCellPoint 528 +ca InsertNextCell 4 +ca InsertCellPoint 504 +ca InsertCellPoint 505 +ca InsertCellPoint 530 +ca InsertCellPoint 529 +ca InsertNextCell 4 +ca InsertCellPoint 505 +ca InsertCellPoint 506 +ca InsertCellPoint 531 +ca InsertCellPoint 530 +ca InsertNextCell 4 +ca InsertCellPoint 506 +ca InsertCellPoint 507 +ca InsertCellPoint 532 +ca InsertCellPoint 531 +ca InsertNextCell 4 +ca InsertCellPoint 507 +ca InsertCellPoint 508 +ca InsertCellPoint 533 +ca InsertCellPoint 532 +ca InsertNextCell 4 +ca InsertCellPoint 508 +ca InsertCellPoint 509 +ca InsertCellPoint 534 +ca InsertCellPoint 533 +ca InsertNextCell 4 +ca InsertCellPoint 509 +ca InsertCellPoint 510 +ca InsertCellPoint 535 +ca InsertCellPoint 534 +ca InsertNextCell 4 +ca InsertCellPoint 510 +ca InsertCellPoint 511 +ca InsertCellPoint 536 +ca InsertCellPoint 535 +ca InsertNextCell 4 +ca InsertCellPoint 511 +ca InsertCellPoint 512 +ca InsertCellPoint 537 +ca InsertCellPoint 536 +ca InsertNextCell 4 +ca InsertCellPoint 512 +ca InsertCellPoint 513 +ca InsertCellPoint 538 +ca InsertCellPoint 537 +ca InsertNextCell 4 +ca InsertCellPoint 513 +ca InsertCellPoint 514 +ca InsertCellPoint 539 +ca InsertCellPoint 538 +ca InsertNextCell 4 +ca InsertCellPoint 514 +ca InsertCellPoint 515 +ca InsertCellPoint 540 +ca InsertCellPoint 539 +ca InsertNextCell 4 +ca InsertCellPoint 515 +ca InsertCellPoint 516 +ca InsertCellPoint 541 +ca InsertCellPoint 540 +ca InsertNextCell 4 +ca InsertCellPoint 516 +ca InsertCellPoint 517 +ca InsertCellPoint 542 +ca InsertCellPoint 541 +ca InsertNextCell 4 +ca InsertCellPoint 517 +ca InsertCellPoint 518 +ca InsertCellPoint 543 +ca InsertCellPoint 542 +ca InsertNextCell 4 +ca InsertCellPoint 518 +ca InsertCellPoint 519 +ca InsertCellPoint 544 +ca InsertCellPoint 543 +ca InsertNextCell 4 +ca InsertCellPoint 519 +ca InsertCellPoint 520 +ca InsertCellPoint 545 +ca InsertCellPoint 544 +ca InsertNextCell 4 +ca InsertCellPoint 520 +ca InsertCellPoint 521 +ca InsertCellPoint 546 +ca InsertCellPoint 545 +ca InsertNextCell 4 +ca InsertCellPoint 521 +ca InsertCellPoint 522 +ca InsertCellPoint 547 +ca InsertCellPoint 546 +ca InsertNextCell 4 +ca InsertCellPoint 522 +ca InsertCellPoint 523 +ca InsertCellPoint 548 +ca InsertCellPoint 547 +ca InsertNextCell 4 +ca InsertCellPoint 523 +ca InsertCellPoint 524 +ca InsertCellPoint 549 +ca InsertCellPoint 548 +ca InsertNextCell 4 +ca InsertCellPoint 525 +ca InsertCellPoint 526 +ca InsertCellPoint 551 +ca InsertCellPoint 550 +ca InsertNextCell 4 +ca InsertCellPoint 526 +ca InsertCellPoint 527 +ca InsertCellPoint 552 +ca InsertCellPoint 551 +ca InsertNextCell 4 +ca InsertCellPoint 527 +ca InsertCellPoint 528 +ca InsertCellPoint 553 +ca InsertCellPoint 552 +ca InsertNextCell 4 +ca InsertCellPoint 528 +ca InsertCellPoint 529 +ca InsertCellPoint 554 +ca InsertCellPoint 553 +ca InsertNextCell 4 +ca InsertCellPoint 529 +ca InsertCellPoint 530 +ca InsertCellPoint 555 +ca InsertCellPoint 554 +ca InsertNextCell 4 +ca InsertCellPoint 530 +ca InsertCellPoint 531 +ca InsertCellPoint 556 +ca InsertCellPoint 555 +ca InsertNextCell 4 +ca InsertCellPoint 531 +ca InsertCellPoint 532 +ca InsertCellPoint 557 +ca InsertCellPoint 556 +ca InsertNextCell 4 +ca InsertCellPoint 532 +ca InsertCellPoint 533 +ca InsertCellPoint 558 +ca InsertCellPoint 557 +ca InsertNextCell 4 +ca InsertCellPoint 533 +ca InsertCellPoint 534 +ca InsertCellPoint 559 +ca InsertCellPoint 558 +ca InsertNextCell 4 +ca InsertCellPoint 534 +ca InsertCellPoint 535 +ca InsertCellPoint 560 +ca InsertCellPoint 559 +ca InsertNextCell 4 +ca InsertCellPoint 535 +ca InsertCellPoint 536 +ca InsertCellPoint 561 +ca InsertCellPoint 560 +ca InsertNextCell 4 +ca InsertCellPoint 536 +ca InsertCellPoint 537 +ca InsertCellPoint 562 +ca InsertCellPoint 561 +ca InsertNextCell 4 +ca InsertCellPoint 537 +ca InsertCellPoint 538 +ca InsertCellPoint 563 +ca InsertCellPoint 562 +ca InsertNextCell 4 +ca InsertCellPoint 538 +ca InsertCellPoint 539 +ca InsertCellPoint 564 +ca InsertCellPoint 563 +ca InsertNextCell 4 +ca InsertCellPoint 539 +ca InsertCellPoint 540 +ca InsertCellPoint 565 +ca InsertCellPoint 564 +ca InsertNextCell 4 +ca InsertCellPoint 540 +ca InsertCellPoint 541 +ca InsertCellPoint 566 +ca InsertCellPoint 565 +ca InsertNextCell 4 +ca InsertCellPoint 541 +ca InsertCellPoint 542 +ca InsertCellPoint 567 +ca InsertCellPoint 566 +ca InsertNextCell 4 +ca InsertCellPoint 542 +ca InsertCellPoint 543 +ca InsertCellPoint 568 +ca InsertCellPoint 567 +ca InsertNextCell 4 +ca InsertCellPoint 543 +ca InsertCellPoint 544 +ca InsertCellPoint 569 +ca InsertCellPoint 568 +ca InsertNextCell 4 +ca InsertCellPoint 544 +ca InsertCellPoint 545 +ca InsertCellPoint 570 +ca InsertCellPoint 569 +ca InsertNextCell 4 +ca InsertCellPoint 545 +ca InsertCellPoint 546 +ca InsertCellPoint 571 +ca InsertCellPoint 570 +ca InsertNextCell 4 +ca InsertCellPoint 546 +ca InsertCellPoint 547 +ca InsertCellPoint 572 +ca InsertCellPoint 571 +ca InsertNextCell 4 +ca InsertCellPoint 547 +ca InsertCellPoint 548 +ca InsertCellPoint 573 +ca InsertCellPoint 572 +ca InsertNextCell 4 +ca InsertCellPoint 548 +ca InsertCellPoint 549 +ca InsertCellPoint 574 +ca InsertCellPoint 573 +ca InsertNextCell 4 +ca InsertCellPoint 550 +ca InsertCellPoint 551 +ca InsertCellPoint 576 +ca InsertCellPoint 575 +ca InsertNextCell 4 +ca InsertCellPoint 551 +ca InsertCellPoint 552 +ca InsertCellPoint 577 +ca InsertCellPoint 576 +ca InsertNextCell 4 +ca InsertCellPoint 552 +ca InsertCellPoint 553 +ca InsertCellPoint 578 +ca InsertCellPoint 577 +ca InsertNextCell 4 +ca InsertCellPoint 553 +ca InsertCellPoint 554 +ca InsertCellPoint 579 +ca InsertCellPoint 578 +ca InsertNextCell 4 +ca InsertCellPoint 554 +ca InsertCellPoint 555 +ca InsertCellPoint 580 +ca InsertCellPoint 579 +ca InsertNextCell 4 +ca InsertCellPoint 555 +ca InsertCellPoint 556 +ca InsertCellPoint 581 +ca InsertCellPoint 580 +ca InsertNextCell 4 +ca InsertCellPoint 556 +ca InsertCellPoint 557 +ca InsertCellPoint 582 +ca InsertCellPoint 581 +ca InsertNextCell 4 +ca InsertCellPoint 557 +ca InsertCellPoint 558 +ca InsertCellPoint 583 +ca InsertCellPoint 582 +ca InsertNextCell 4 +ca InsertCellPoint 558 +ca InsertCellPoint 559 +ca InsertCellPoint 584 +ca InsertCellPoint 583 +ca InsertNextCell 4 +ca InsertCellPoint 559 +ca InsertCellPoint 560 +ca InsertCellPoint 585 +ca InsertCellPoint 584 +ca InsertNextCell 4 +ca InsertCellPoint 560 +ca InsertCellPoint 561 +ca InsertCellPoint 586 +ca InsertCellPoint 585 +ca InsertNextCell 4 +ca InsertCellPoint 561 +ca InsertCellPoint 562 +ca InsertCellPoint 587 +ca InsertCellPoint 586 +ca InsertNextCell 4 +ca InsertCellPoint 562 +ca InsertCellPoint 563 +ca InsertCellPoint 588 +ca InsertCellPoint 587 +ca InsertNextCell 4 +ca InsertCellPoint 563 +ca InsertCellPoint 564 +ca InsertCellPoint 589 +ca InsertCellPoint 588 +ca InsertNextCell 4 +ca InsertCellPoint 564 +ca InsertCellPoint 565 +ca InsertCellPoint 590 +ca InsertCellPoint 589 +ca InsertNextCell 4 +ca InsertCellPoint 565 +ca InsertCellPoint 566 +ca InsertCellPoint 591 +ca InsertCellPoint 590 +ca InsertNextCell 4 +ca InsertCellPoint 566 +ca InsertCellPoint 567 +ca InsertCellPoint 592 +ca InsertCellPoint 591 +ca InsertNextCell 4 +ca InsertCellPoint 567 +ca InsertCellPoint 568 +ca InsertCellPoint 593 +ca InsertCellPoint 592 +ca InsertNextCell 4 +ca InsertCellPoint 568 +ca InsertCellPoint 569 +ca InsertCellPoint 594 +ca InsertCellPoint 593 +ca InsertNextCell 4 +ca InsertCellPoint 569 +ca InsertCellPoint 570 +ca InsertCellPoint 595 +ca InsertCellPoint 594 +ca InsertNextCell 4 +ca InsertCellPoint 570 +ca InsertCellPoint 571 +ca InsertCellPoint 596 +ca InsertCellPoint 595 +ca InsertNextCell 4 +ca InsertCellPoint 571 +ca InsertCellPoint 572 +ca InsertCellPoint 597 +ca InsertCellPoint 596 +ca InsertNextCell 4 +ca InsertCellPoint 572 +ca InsertCellPoint 573 +ca InsertCellPoint 598 +ca InsertCellPoint 597 +ca InsertNextCell 4 +ca InsertCellPoint 573 +ca InsertCellPoint 574 +ca InsertCellPoint 599 +ca InsertCellPoint 598 +ca InsertNextCell 4 +ca InsertCellPoint 575 +ca InsertCellPoint 576 +ca InsertCellPoint 601 +ca InsertCellPoint 600 +ca InsertNextCell 4 +ca InsertCellPoint 576 +ca InsertCellPoint 577 +ca InsertCellPoint 602 +ca InsertCellPoint 601 +ca InsertNextCell 4 +ca InsertCellPoint 577 +ca InsertCellPoint 578 +ca InsertCellPoint 603 +ca InsertCellPoint 602 +ca InsertNextCell 4 +ca InsertCellPoint 578 +ca InsertCellPoint 579 +ca InsertCellPoint 604 +ca InsertCellPoint 603 +ca InsertNextCell 4 +ca InsertCellPoint 579 +ca InsertCellPoint 580 +ca InsertCellPoint 605 +ca InsertCellPoint 604 +ca InsertNextCell 4 +ca InsertCellPoint 580 +ca InsertCellPoint 581 +ca InsertCellPoint 606 +ca InsertCellPoint 605 +ca InsertNextCell 4 +ca InsertCellPoint 581 +ca InsertCellPoint 582 +ca InsertCellPoint 607 +ca InsertCellPoint 606 +ca InsertNextCell 4 +ca InsertCellPoint 582 +ca InsertCellPoint 583 +ca InsertCellPoint 608 +ca InsertCellPoint 607 +ca InsertNextCell 4 +ca InsertCellPoint 583 +ca InsertCellPoint 584 +ca InsertCellPoint 609 +ca InsertCellPoint 608 +ca InsertNextCell 4 +ca InsertCellPoint 584 +ca InsertCellPoint 585 +ca InsertCellPoint 610 +ca InsertCellPoint 609 +ca InsertNextCell 4 +ca InsertCellPoint 585 +ca InsertCellPoint 586 +ca InsertCellPoint 611 +ca InsertCellPoint 610 +ca InsertNextCell 4 +ca InsertCellPoint 586 +ca InsertCellPoint 587 +ca InsertCellPoint 612 +ca InsertCellPoint 611 +ca InsertNextCell 4 +ca InsertCellPoint 587 +ca InsertCellPoint 588 +ca InsertCellPoint 613 +ca InsertCellPoint 612 +ca InsertNextCell 4 +ca InsertCellPoint 588 +ca InsertCellPoint 589 +ca InsertCellPoint 614 +ca InsertCellPoint 613 +ca InsertNextCell 4 +ca InsertCellPoint 589 +ca InsertCellPoint 590 +ca InsertCellPoint 615 +ca InsertCellPoint 614 +ca InsertNextCell 4 +ca InsertCellPoint 590 +ca InsertCellPoint 591 +ca InsertCellPoint 616 +ca InsertCellPoint 615 +ca InsertNextCell 4 +ca InsertCellPoint 591 +ca InsertCellPoint 592 +ca InsertCellPoint 617 +ca InsertCellPoint 616 +ca InsertNextCell 4 +ca InsertCellPoint 592 +ca InsertCellPoint 593 +ca InsertCellPoint 618 +ca InsertCellPoint 617 +ca InsertNextCell 4 +ca InsertCellPoint 593 +ca InsertCellPoint 594 +ca InsertCellPoint 619 +ca InsertCellPoint 618 +ca InsertNextCell 4 +ca InsertCellPoint 594 +ca InsertCellPoint 595 +ca InsertCellPoint 620 +ca InsertCellPoint 619 +ca InsertNextCell 4 +ca InsertCellPoint 595 +ca InsertCellPoint 596 +ca InsertCellPoint 621 +ca InsertCellPoint 620 +ca InsertNextCell 4 +ca InsertCellPoint 596 +ca InsertCellPoint 597 +ca InsertCellPoint 622 +ca InsertCellPoint 621 +ca InsertNextCell 4 +ca InsertCellPoint 597 +ca InsertCellPoint 598 +ca InsertCellPoint 623 +ca InsertCellPoint 622 +ca InsertNextCell 4 +ca InsertCellPoint 598 +ca InsertCellPoint 599 +ca InsertCellPoint 624 +ca InsertCellPoint 623 + +vtkPolyData patch + patch SetPoints pts + patch SetPolys ca +vtkTriangleFilter tf + tf SetInput patch +vtkSmoothPolyDataFilter smooth + smooth SetInputConnection [tf GetOutputPort] + smooth SetSource [cyber GetOutput] + smooth SetNumberOfIterations 50 +vtkPolyDataMapper patchMapper + patchMapper SetInputConnection [smooth GetOutputPort] +vtkProperty back + back SetDiffuseColor 1.0 1.0 0.0 +vtkActor patchActor + patchActor SetMapper patchMapper + eval [patchActor GetProperty] SetColor 0.0 1.0 0.0 + patchActor SetBackfaceProperty back + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor patchActor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 + +vtkCamera cam1 + cam1 SetClippingRange 0.0475572 2.37786 + cam1 SetFocalPoint 0.052665 -0.129454 -0.0573973 + cam1 SetPosition 0.327637 -0.116299 -0.256418 + cam1 SetViewUp -0.0225386 0.999137 0.034901 + cam1 Zoom 2 +ren1 SetActiveCamera cam1 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/socbal.tcl b/Graphics/Testing/Tcl/socbal.tcl new file mode 100644 index 0000000..3d6778b --- /dev/null +++ b/Graphics/Testing/Tcl/socbal.tcl @@ -0,0 +1,445 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a soccer ball +# +vtkPoints points +# first point repeated because polygons were 1-offset +points InsertNextPoint 0.348012 0 0.93749 +points InsertNextPoint 0.348012 0 0.93749 +points InsertNextPoint 0.107542 0.330979 0.93749 +points InsertNextPoint -0.281548 0.204556 0.93749 +points InsertNextPoint -0.281548 -0.204556 0.93749 +points InsertNextPoint 0.107542 -0.330979 0.93749 +points InsertNextPoint 0.694318 0 0.719669 +points InsertNextPoint 0.799191 -0.327801 0.502204 +points InsertNextPoint 0.965027 -0.20654 0.154057 +points InsertNextPoint 0.965027 0.20654 0.154057 +points InsertNextPoint 0.799191 0.327801 0.502204 +points InsertNextPoint 0.214556 0.660335 0.719669 +points InsertNextPoint 0.558721 0.65878 0.502204 +points InsertNextPoint 0.494641 0.853971 0.154057 +points InsertNextPoint 0.101778 0.981619 0.154057 +points InsertNextPoint -0.0647933 0.861372 0.502204 +points InsertNextPoint -0.561715 0.40811 0.719669 +points InsertNextPoint -0.453883 0.734949 0.502204 +points InsertNextPoint -0.659322 0.734323 0.154057 +points InsertNextPoint -0.902124 0.400134 0.154057 +points InsertNextPoint -0.839236 0.204556 0.502204 +points InsertNextPoint -0.561715 -0.40811 0.719669 +points InsertNextPoint -0.839236 -0.204556 0.502204 +points InsertNextPoint -0.902124 -0.400134 0.154057 +points InsertNextPoint -0.659322 -0.734323 0.154057 +points InsertNextPoint -0.453883 -0.734949 0.502204 +points InsertNextPoint 0.214556 -0.660335 0.719669 +points InsertNextPoint -0.0647933 -0.861372 0.502204 +points InsertNextPoint 0.101778 -0.981619 0.154057 +points InsertNextPoint 0.494641 -0.853971 0.154057 +points InsertNextPoint 0.558721 -0.65878 0.502204 +points InsertNextPoint 0.902124 0.400134 -0.154057 +points InsertNextPoint 0.839236 0.204556 -0.502204 +points InsertNextPoint 0.561715 0.40811 -0.719669 +points InsertNextPoint 0.453883 0.734949 -0.502204 +points InsertNextPoint 0.659322 0.734323 -0.154057 +points InsertNextPoint -0.101778 0.981619 -0.154057 +points InsertNextPoint 0.0647933 0.861372 -0.502204 +points InsertNextPoint -0.214556 0.660335 -0.719669 +points InsertNextPoint -0.558721 0.65878 -0.502204 +points InsertNextPoint -0.494641 0.853971 -0.154057 +points InsertNextPoint -0.965027 0.20654 -0.154057 +points InsertNextPoint -0.799191 0.327801 -0.502204 +points InsertNextPoint -0.694318 0 -0.719669 +points InsertNextPoint -0.799191 -0.327801 -0.502204 +points InsertNextPoint -0.965027 -0.20654 -0.154057 +points InsertNextPoint -0.494641 -0.853971 -0.154057 +points InsertNextPoint -0.558721 -0.65878 -0.502204 +points InsertNextPoint -0.214556 -0.660335 -0.719669 +points InsertNextPoint 0.0647933 -0.861372 -0.502204 +points InsertNextPoint -0.101778 -0.981619 -0.154057 +points InsertNextPoint 0.659322 -0.734323 -0.154057 +points InsertNextPoint 0.453883 -0.734949 -0.502204 +points InsertNextPoint 0.561715 -0.40811 -0.719669 +points InsertNextPoint 0.839236 -0.204556 -0.502204 +points InsertNextPoint 0.902124 -0.400134 -0.154057 +points InsertNextPoint 0.281548 -0.204556 -0.93749 +points InsertNextPoint -0.107542 -0.330979 -0.93749 +points InsertNextPoint -0.348012 0 -0.93749 +points InsertNextPoint -0.107542 0.330979 -0.93749 +points InsertNextPoint 0.281548 0.204556 -0.93749 + +vtkCellArray faces +faces InsertNextCell 5 +faces InsertCellPoint 5 +faces InsertCellPoint 4 +faces InsertCellPoint 3 +faces InsertCellPoint 2 +faces InsertCellPoint 1 +faces InsertNextCell 5 +faces InsertCellPoint 10 +faces InsertCellPoint 9 +faces InsertCellPoint 8 +faces InsertCellPoint 7 +faces InsertCellPoint 6 +faces InsertNextCell 5 +faces InsertCellPoint 15 +faces InsertCellPoint 14 +faces InsertCellPoint 13 +faces InsertCellPoint 12 +faces InsertCellPoint 11 +faces InsertNextCell 5 +faces InsertCellPoint 20 +faces InsertCellPoint 19 +faces InsertCellPoint 18 +faces InsertCellPoint 17 +faces InsertCellPoint 16 +faces InsertNextCell 5 +faces InsertCellPoint 25 +faces InsertCellPoint 24 +faces InsertCellPoint 23 +faces InsertCellPoint 22 +faces InsertCellPoint 21 +faces InsertNextCell 5 +faces InsertCellPoint 30 +faces InsertCellPoint 29 +faces InsertCellPoint 28 +faces InsertCellPoint 27 +faces InsertCellPoint 26 +faces InsertNextCell 5 +faces InsertCellPoint 35 +faces InsertCellPoint 34 +faces InsertCellPoint 33 +faces InsertCellPoint 32 +faces InsertCellPoint 31 +faces InsertNextCell 5 +faces InsertCellPoint 40 +faces InsertCellPoint 39 +faces InsertCellPoint 38 +faces InsertCellPoint 37 +faces InsertCellPoint 36 +faces InsertNextCell 5 +faces InsertCellPoint 45 +faces InsertCellPoint 44 +faces InsertCellPoint 43 +faces InsertCellPoint 42 +faces InsertCellPoint 41 +faces InsertNextCell 5 +faces InsertCellPoint 50 +faces InsertCellPoint 49 +faces InsertCellPoint 48 +faces InsertCellPoint 47 +faces InsertCellPoint 46 +faces InsertNextCell 5 +faces InsertCellPoint 55 +faces InsertCellPoint 54 +faces InsertCellPoint 53 +faces InsertCellPoint 52 +faces InsertCellPoint 51 +faces InsertNextCell 5 +faces InsertCellPoint 60 +faces InsertCellPoint 59 +faces InsertCellPoint 58 +faces InsertCellPoint 57 +faces InsertCellPoint 56 +faces InsertNextCell 6 +faces InsertCellPoint 2 +faces InsertCellPoint 11 +faces InsertCellPoint 12 +faces InsertCellPoint 10 +faces InsertCellPoint 6 +faces InsertCellPoint 1 +faces InsertNextCell 6 +faces InsertCellPoint 3 +faces InsertCellPoint 16 +faces InsertCellPoint 17 +faces InsertCellPoint 15 +faces InsertCellPoint 11 +faces InsertCellPoint 2 +faces InsertNextCell 6 +faces InsertCellPoint 4 +faces InsertCellPoint 21 +faces InsertCellPoint 22 +faces InsertCellPoint 20 +faces InsertCellPoint 16 +faces InsertCellPoint 3 +faces InsertNextCell 6 +faces InsertCellPoint 5 +faces InsertCellPoint 26 +faces InsertCellPoint 27 +faces InsertCellPoint 25 +faces InsertCellPoint 21 +faces InsertCellPoint 4 +faces InsertNextCell 6 +faces InsertCellPoint 1 +faces InsertCellPoint 6 +faces InsertCellPoint 7 +faces InsertCellPoint 30 +faces InsertCellPoint 26 +faces InsertCellPoint 5 +faces InsertNextCell 6 +faces InsertCellPoint 12 +faces InsertCellPoint 13 +faces InsertCellPoint 35 +faces InsertCellPoint 31 +faces InsertCellPoint 9 +faces InsertCellPoint 10 +faces InsertNextCell 6 +faces InsertCellPoint 17 +faces InsertCellPoint 18 +faces InsertCellPoint 40 +faces InsertCellPoint 36 +faces InsertCellPoint 14 +faces InsertCellPoint 15 +faces InsertNextCell 6 +faces InsertCellPoint 22 +faces InsertCellPoint 23 +faces InsertCellPoint 45 +faces InsertCellPoint 41 +faces InsertCellPoint 19 +faces InsertCellPoint 20 +faces InsertNextCell 6 +faces InsertCellPoint 27 +faces InsertCellPoint 28 +faces InsertCellPoint 50 +faces InsertCellPoint 46 +faces InsertCellPoint 24 +faces InsertCellPoint 25 +faces InsertNextCell 6 +faces InsertCellPoint 7 +faces InsertCellPoint 8 +faces InsertCellPoint 55 +faces InsertCellPoint 51 +faces InsertCellPoint 29 +faces InsertCellPoint 30 +faces InsertNextCell 6 +faces InsertCellPoint 9 +faces InsertCellPoint 31 +faces InsertCellPoint 32 +faces InsertCellPoint 54 +faces InsertCellPoint 55 +faces InsertCellPoint 8 +faces InsertNextCell 6 +faces InsertCellPoint 14 +faces InsertCellPoint 36 +faces InsertCellPoint 37 +faces InsertCellPoint 34 +faces InsertCellPoint 35 +faces InsertCellPoint 13 +faces InsertNextCell 6 +faces InsertCellPoint 19 +faces InsertCellPoint 41 +faces InsertCellPoint 42 +faces InsertCellPoint 39 +faces InsertCellPoint 40 +faces InsertCellPoint 18 +faces InsertNextCell 6 +faces InsertCellPoint 24 +faces InsertCellPoint 46 +faces InsertCellPoint 47 +faces InsertCellPoint 44 +faces InsertCellPoint 45 +faces InsertCellPoint 23 +faces InsertNextCell 6 +faces InsertCellPoint 29 +faces InsertCellPoint 51 +faces InsertCellPoint 52 +faces InsertCellPoint 49 +faces InsertCellPoint 50 +faces InsertCellPoint 28 +faces InsertNextCell 6 +faces InsertCellPoint 32 +faces InsertCellPoint 33 +faces InsertCellPoint 60 +faces InsertCellPoint 56 +faces InsertCellPoint 53 +faces InsertCellPoint 54 +faces InsertNextCell 6 +faces InsertCellPoint 37 +faces InsertCellPoint 38 +faces InsertCellPoint 59 +faces InsertCellPoint 60 +faces InsertCellPoint 33 +faces InsertCellPoint 34 +faces InsertNextCell 6 +faces InsertCellPoint 42 +faces InsertCellPoint 43 +faces InsertCellPoint 58 +faces InsertCellPoint 59 +faces InsertCellPoint 38 +faces InsertCellPoint 39 +faces InsertNextCell 6 +faces InsertCellPoint 47 +faces InsertCellPoint 48 +faces InsertCellPoint 57 +faces InsertCellPoint 58 +faces InsertCellPoint 43 +faces InsertCellPoint 44 +faces InsertNextCell 6 +faces InsertCellPoint 52 +faces InsertCellPoint 53 +faces InsertCellPoint 56 +faces InsertCellPoint 57 +faces InsertCellPoint 48 +faces InsertCellPoint 49 + +vtkFloatArray faceColors + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 1 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + faceColors InsertNextValue 2 + +vtkFloatArray vertexColors + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + vertexColors InsertNextValue 2 + +vtkPolyData model + model SetPolys faces + model SetPoints points + [model GetCellData] SetScalars faceColors + [model GetPointData] SetScalars vertexColors + +vtkTextureMapToSphere ballTC + ballTC SetInput model + +vtkLookupTable lut + lut SetNumberOfColors 3 + lut Build + lut SetTableValue 0 0 0 0 0 + lut SetTableValue 1 1 .3 .3 1 + lut SetTableValue 2 .8 .8 .9 1 + +vtkDataSetMapper mapper + mapper SetInputConnection [ballTC GetOutputPort] + mapper SetScalarModeToUseCellData + mapper SetLookupTable lut + mapper SetScalarRange 0 2 + +vtkPNMReader earth + earth SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +vtkTexture texture +texture SetInputConnection [earth GetOutputPort] + +vtkActor soccerBall + soccerBall SetMapper mapper + soccerBall SetTexture texture + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor soccerBall +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 +[ren1 GetActiveCamera] SetPosition 4.19682 4.65178 6.23545 +[ren1 GetActiveCamera] SetFocalPoint 0 0 0 +[ren1 GetActiveCamera] SetViewAngle 21.4286 +[ren1 GetActiveCamera] SetViewUp 0.451577 -0.833646 0.317981 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +ren1 ResetCameraClippingRange + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/spatialRepAll.tcl b/Graphics/Testing/Tcl/spatialRepAll.tcl new file mode 100644 index 0000000..d196a26 --- /dev/null +++ b/Graphics/Testing/Tcl/spatialRepAll.tcl @@ -0,0 +1,59 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkSTLReader asource + asource SetFileName "$VTK_DATA_ROOT/Data/42400-IDGH.stl" +vtkPolyDataMapper dataMapper + dataMapper SetInput [asource GetOutput] +vtkActor model + model SetMapper dataMapper + [model GetProperty] SetColor 1 0 0 + model VisibilityOn + +set locators "vtkPointLocator vtkCellLocator vtkOBBTree" +set i 1 +foreach locator $locators { +$locator locator$i + locator$i AutomaticOff + locator$i SetMaxLevel 3 +vtkSpatialRepresentationFilter boxes$i + boxes$i SetInput [asource GetOutput] + boxes$i SetSpatialRepresentation locator$i +vtkPolyDataMapper boxMapper$i + boxMapper$i SetInput [boxes$i GetOutput] +vtkActor boxActor$i + boxActor$i SetMapper boxMapper$i + boxActor$i AddPosition [expr $i * 15] 0 0 + ren1 AddActor boxActor$i + incr i +#} + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor model +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 400 160 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +vtkCamera camera + camera SetPosition 148.579 136.352 214.961 + camera SetFocalPoint 151.889 86.3178 223.333 + camera SetViewAngle 30 + camera SetViewUp 0 0 -1 + camera SetClippingRange 1 100 +ren1 SetActiveCamera camera +renWin Render +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Graphics/Testing/Tcl/spherical.tcl b/Graphics/Testing/Tcl/spherical.tcl new file mode 100644 index 0000000..ffa8770 --- /dev/null +++ b/Graphics/Testing/Tcl/spherical.tcl @@ -0,0 +1,72 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# avoid the singularity at the Z axis using 0.0001 radian offset +vtkPlaneSource plane + plane SetOrigin 1.0 [expr 3.14159265359 - 0.0001] 0.0 + plane SetPoint1 1.0 [expr 3.14159265359 - 0.0001] 6.28318530719 + plane SetPoint2 1.0 0.0001 0.0 + plane SetXResolution 19 + plane SetYResolution 9 + +vtkSphericalTransform transform + +vtkTransformPolyDataFilter tpoly + tpoly SetInputConnection [plane GetOutputPort] + tpoly SetTransform transform + +# also cover the inverse transformation by going back and forth +vtkTransformPolyDataFilter tpoly2 + tpoly2 SetInputConnection [tpoly GetOutputPort] + tpoly2 SetTransform [transform GetInverse] + +vtkTransformPolyDataFilter tpoly3 + tpoly3 SetInputConnection [tpoly2 GetOutputPort] + tpoly3 SetTransform transform + +vtkDataSetMapper mapper + mapper SetInputConnection [tpoly3 GetOutputPort] + +vtkPNMReader earth + earth SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +vtkTexture texture + texture SetInputConnection [earth GetOutputPort] + texture InterpolateOn + +vtkActor world + world SetMapper mapper + world SetTexture texture + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor world +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 +[ren1 GetActiveCamera] SetPosition 8 -10 6 +[ren1 GetActiveCamera] SetFocalPoint 0 0 0 +[ren1 GetActiveCamera] SetViewAngle 15 +[ren1 GetActiveCamera] SetViewUp 0.0 0.0 1.0 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +ren1 ResetCameraClippingRange + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/splitVectors.tcl b/Graphics/Testing/Tcl/splitVectors.tcl new file mode 100644 index 0000000..d02724b --- /dev/null +++ b/Graphics/Testing/Tcl/splitVectors.tcl @@ -0,0 +1,152 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +vtkSplitField sf + sf SetInputConnection [pl3d GetOutputPort] + sf SetInputField "VECTORS" "POINT_DATA" + sf Split 0 "vx" + sf Split 1 "vy" + sf Split 2 "vz" + +sf Print + +vtkAssignAttribute aax + aax SetInputConnection [sf GetOutputPort] + aax Assign "vx" "SCALARS" "POINT_DATA" +vtkContourFilter isoVx + isoVx SetInputConnection [aax GetOutputPort] + isoVx SetValue 0 .38 +vtkPolyDataNormals normalsVx + normalsVx SetInputConnection [isoVx GetOutputPort] + normalsVx SetFeatureAngle 45 +vtkPolyDataMapper isoVxMapper + isoVxMapper SetInputConnection [normalsVx GetOutputPort] + isoVxMapper ScalarVisibilityOff + isoVxMapper ImmediateModeRenderingOn +vtkActor isoVxActor + isoVxActor SetMapper isoVxMapper + eval [isoVxActor GetProperty] SetColor 1 0.7 0.6 + +vtkAssignAttribute aay + aay SetInputConnection [sf GetOutputPort] + aay Assign "vy" "SCALARS" "POINT_DATA" +vtkContourFilter isoVy + isoVy SetInputConnection [aay GetOutputPort] + isoVy SetValue 0 .38 +vtkPolyDataNormals normalsVy + normalsVy SetInputConnection [isoVy GetOutputPort] + normalsVy SetFeatureAngle 45 +vtkPolyDataMapper isoVyMapper + isoVyMapper SetInputConnection [normalsVy GetOutputPort] + isoVyMapper ScalarVisibilityOff + isoVyMapper ImmediateModeRenderingOn +vtkActor isoVyActor + isoVyActor SetMapper isoVyMapper + eval [isoVyActor GetProperty] SetColor 0.7 1 0.6 + +vtkAssignAttribute aaz + aaz SetInputConnection [sf GetOutputPort] + aaz Assign "vz" "SCALARS" "POINT_DATA" +vtkContourFilter isoVz + isoVz SetInputConnection [aaz GetOutputPort] + isoVz SetValue 0 .38 +vtkPolyDataNormals normalsVz + normalsVz SetInputConnection [isoVz GetOutputPort] + normalsVz SetFeatureAngle 45 +vtkPolyDataMapper isoVzMapper + isoVzMapper SetInputConnection [normalsVz GetOutputPort] + isoVzMapper ScalarVisibilityOff + isoVzMapper ImmediateModeRenderingOn +vtkActor isoVzActor + isoVzActor SetMapper isoVzMapper + eval [isoVzActor GetProperty] SetColor 0.4 0.5 1 + +vtkMergeFields mf + mf SetInputConnection [sf GetOutputPort] + mf SetOutputField "merged" "POINT_DATA" + mf SetNumberOfComponents 3 + mf Merge 0 "vy" 0 + mf Merge 1 "vz" 0 + mf Merge 2 "vx" 0 + +mf Print + +vtkAssignAttribute aa + aa SetInputConnection [mf GetOutputPort] + aa Assign "merged" "SCALARS" "POINT_DATA" +vtkAssignAttribute aa2 + aa2 SetInputConnection [aa GetOutputPort] + aa2 Assign "SCALARS" "VECTORS" "POINT_DATA" +vtkStreamLine sl + sl SetInputConnection [aa2 GetOutputPort] + sl SetStartPosition 2 -2 26 + sl SetMaximumPropagationTime 40 + sl SetIntegrationStepLength 0.2 + sl SetIntegrationDirectionToForward + sl SetStepLength 0.001 +vtkRibbonFilter rf + rf SetInputConnection [sl GetOutputPort] + rf SetWidth 1.0 + rf SetWidthFactor 5 +vtkPolyDataMapper slMapper + slMapper SetInputConnection [rf GetOutputPort] + slMapper ImmediateModeRenderingOn +vtkActor slActor + slActor SetMapper slMapper + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor isoVxActor +isoVxActor AddPosition 0 12 0 +ren1 AddActor isoVyActor +ren1 AddActor isoVzActor +isoVzActor AddPosition 0 -12 0 +ren1 AddActor slActor +slActor AddPosition 0 24 0 +ren1 AddActor outlineActor +outlineActor AddPosition 0 24 0 +ren1 SetBackground .8 .8 .8 +renWin SetSize 321 321 + +[ren1 GetActiveCamera] SetPosition -20.3093 20.55444 64.3922 +[ren1 GetActiveCamera] SetFocalPoint 8.255 0.0499763 29.7631 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0 0 1 +[ren1 GetActiveCamera] Dolly 0.4 +ren1 ResetCameraClippingRange + + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/stereoDresdenMace.tcl b/Graphics/Testing/Tcl/stereoDresdenMace.tcl new file mode 100644 index 0000000..f320e6a --- /dev/null +++ b/Graphics/Testing/Tcl/stereoDresdenMace.tcl @@ -0,0 +1,71 @@ +package require vtk + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin StereoCapableWindowOn + renWin SetWindowName "vtk - Mace" +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +renWin SetStereoTypeToDresden +renWin StereoRenderOn + +# create a sphere source and actor +# +vtkSphereSource sphere + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +# create the spikes using a cone source and the sphere source +# +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] +vtkLODActor spikeActor + spikeActor SetMapper spikeMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor sphereActor +ren1 AddActor spikeActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +iren Initialize + +# default arguments added so that the protoype matches +# as required in Python when the test is translated. +proc TkCheckAbort { { a 0 } { b 0 } } { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" TkCheckAbort + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + +vtkMatrix4x4 mat +spikeActor SetUserMatrix mat + +renWin Render diff --git a/Graphics/Testing/Tcl/streamTracer.tcl b/Graphics/Testing/Tcl/streamTracer.tcl new file mode 100644 index 0000000..31e1bea --- /dev/null +++ b/Graphics/Testing/Tcl/streamTracer.tcl @@ -0,0 +1,70 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin +renWin AddRenderer ren1 +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +# read data +# +vtkStructuredGridReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/office.binary.vtk" +reader Update;#force a read to occur + +vtkStructuredGridOutlineFilter outline +outline SetInputConnection [reader GetOutputPort] +vtkPolyDataMapper mapOutline +mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor +outlineActor SetMapper mapOutline +[outlineActor GetProperty] SetColor 0 0 0 + +vtkRungeKutta45 rk + +# Create source for streamtubes +vtkStreamTracer streamer +streamer SetInputConnection [reader GetOutputPort] +streamer SetStartPosition 0.1 2.1 0.5 +streamer SetMaximumPropagation 0 500 +streamer SetMinimumIntegrationStep 1 0.1 +streamer SetMaximumIntegrationStep 1 1.0 +streamer SetInitialIntegrationStep 2 0.2 +streamer SetIntegrationDirection 0 +streamer SetIntegrator rk +streamer SetRotationScale 0.5 +streamer SetMaximumError 1.0e-8 + +vtkAssignAttribute aa +aa SetInputConnection [streamer GetOutputPort] +aa Assign "Normals" "NORMALS" "POINT_DATA" + +vtkRibbonFilter rf1 +rf1 SetInputConnection [aa GetOutputPort] +rf1 SetWidth 0.1 +rf1 VaryWidthOff + +vtkPolyDataMapper mapStream +mapStream SetInputConnection [rf1 GetOutputPort] +eval mapStream SetScalarRange [[reader GetOutput] GetScalarRange] +vtkActor streamActor +streamActor SetMapper mapStream + +ren1 AddActor outlineActor +ren1 AddActor streamActor + +ren1 SetBackground 0.4 0.4 0.5 + +set cam [ren1 GetActiveCamera] +$cam SetPosition -2.35599 -3.35001 4.59236 +$cam SetFocalPoint 2.255 2.255 1.28413 +$cam SetViewUp 0.311311 0.279912 0.908149 +$cam SetClippingRange 1.12294 16.6226 + +renWin SetSize 300 200 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# interact with data +wm withdraw . diff --git a/Graphics/Testing/Tcl/stripF.tcl b/Graphics/Testing/Tcl/stripF.tcl new file mode 100644 index 0000000..92fd70f --- /dev/null +++ b/Graphics/Testing/Tcl/stripF.tcl @@ -0,0 +1,50 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a cyberware source +# +vtkPolyDataReader cyber + cyber SetFileName "$VTK_DATA_ROOT/Data/fran_cut.vtk" +vtkPolyDataNormals normals;#enable this for cool effect + normals SetInputConnection [cyber GetOutputPort] + normals FlipNormalsOn +vtkStripper stripper + stripper SetInputConnection [cyber GetOutputPort] +vtkMaskPolyData mask + mask SetInputConnection [stripper GetOutputPort] + mask SetOnRatio 2 +vtkPolyDataMapper cyberMapper + cyberMapper SetInputConnection [mask GetOutputPort] +vtkActor cyberActor + cyberActor SetMapper cyberMapper + [cyberActor GetProperty] SetColor 1.0 0.49 0.25 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cyberActor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +#ren1 SetBackground 0.1 0.2 0.4 +ren1 SetBackground 1 1 1 + +# render the image +# +vtkCamera cam1 + cam1 SetFocalPoint 0.0520703 -0.128547 -0.0581083 + cam1 SetPosition 0.419653 -0.120916 -0.321626 + cam1 SetViewAngle 21.4286 + cam1 SetViewUp -0.0136986 0.999858 0.00984497 +ren1 SetActiveCamera cam1 +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/subDivideTetra.tcl b/Graphics/Testing/Tcl/subDivideTetra.tcl new file mode 100644 index 0000000..0a1d888 --- /dev/null +++ b/Graphics/Testing/Tcl/subDivideTetra.tcl @@ -0,0 +1,62 @@ +package require vtk +package require vtkinteraction + +vtkPoints tetraPoints + tetraPoints SetNumberOfPoints 4 + tetraPoints InsertPoint 0 0 0 0 + tetraPoints InsertPoint 1 1 0 0 + tetraPoints InsertPoint 2 .5 1 0 + tetraPoints InsertPoint 3 .5 .5 1 + +vtkTetra aTetra + [aTetra GetPointIds] SetId 0 0 + [aTetra GetPointIds] SetId 1 1 + [aTetra GetPointIds] SetId 2 2 + [aTetra GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aTetraGrid + aTetraGrid Allocate 1 1 + aTetraGrid InsertNextCell [aTetra GetCellType] [aTetra GetPointIds] + aTetraGrid SetPoints tetraPoints + +vtkSubdivideTetra sub + sub SetInput aTetraGrid + +vtkShrinkFilter shrinker + shrinker SetInputConnection [sub GetOutputPort] + +vtkDataSetMapper mapper + mapper SetInputConnection [shrinker GetOutputPort] + +vtkActor actor + actor SetMapper mapper + [actor GetProperty] SetColor 0.7400 0.9900 0.7900 + +# define graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor actor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 0.183196 9.15979 +$cam1 SetFocalPoint 0.579471 0.462507 0.283392 +$cam1 SetPosition -1.04453 0.345281 -0.556222 +$cam1 SetViewUp 0.197321 0.843578 -0.499441 +ren1 ResetCameraClippingRange + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/subPixelPositionMin.tcl b/Graphics/Testing/Tcl/subPixelPositionMin.tcl new file mode 100644 index 0000000..4aa9969 --- /dev/null +++ b/Graphics/Testing/Tcl/subPixelPositionMin.tcl @@ -0,0 +1,74 @@ +package require vtk + +# Test sub pixel positioning (A round about way of getting an iso surface.) +# See cubed sphere for the surface before sub pixel poisitioning. + +vtkSphere sphere + sphere SetCenter 1 1 1 + sphere SetRadius 0.9 + +vtkSampleFunction sample + sample SetImplicitFunction sphere + sample SetModelBounds 0 2 0 2 0 2 + sample SetSampleDimensions 30 30 30 + sample ComputeNormalsOff + + +vtkThreshold threshold1 + threshold1 SetInputConnection [sample GetOutputPort] + threshold1 ThresholdByLower 0.001 + +vtkGeometryFilter geometry + geometry SetInputConnection [threshold1 GetOutputPort] + +vtkImageGradient grad +grad SetDimensionality 3 +grad SetInputConnection [sample GetOutputPort] + +vtkImageMathematics mult +mult SetOperationToMultiply +mult SetInput1 [sample GetOutput] +mult SetInput2 [sample GetOutput] + +vtkImageToStructuredPoints itosp +itosp SetInputConnection [mult GetOutputPort] +itosp SetVectorInput [grad GetOutput] + +vtkSubPixelPositionEdgels sub +sub SetInputConnection [geometry GetOutputPort] +sub SetGradMaps [itosp GetOutput] + + +vtkDataSetMapper mapper + mapper SetInputConnection [sub GetOutputPort] + +vtkActor actor + actor SetMapper mapper + +# Create renderer stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 20 +[ren1 GetActiveCamera] Elevation 30 +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 450 450 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +iren Initialize + + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/subdividePointData.tcl b/Graphics/Testing/Tcl/subdividePointData.tcl new file mode 100644 index 0000000..144a0d4 --- /dev/null +++ b/Graphics/Testing/Tcl/subdividePointData.tcl @@ -0,0 +1,115 @@ +package require vtk +package require vtkinteraction + +# +# Test butterfly subdivision of point data +# + + + + +vtkSphereSource sphere + sphere SetPhiResolution 11 + sphere SetThetaResolution 11 + +vtkElevationFilter colorIt + colorIt SetInputConnection [sphere GetOutputPort] + colorIt SetLowPoint 0 0 -.5 + colorIt SetHighPoint 0 0 .5 + +vtkButterflySubdivisionFilter butterfly + butterfly SetInput [colorIt GetPolyDataOutput] + butterfly SetNumberOfSubdivisions 3 + +vtkLookupTable lut + lut SetNumberOfColors 256 + lut Build + +vtkPolyDataMapper mapper + mapper SetInputConnection [butterfly GetOutputPort] + mapper SetLookupTable lut + +vtkActor actor + actor SetMapper mapper + +vtkLinearSubdivisionFilter linear + linear SetInput [colorIt GetPolyDataOutput] + linear SetNumberOfSubdivisions 3 + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [linear GetOutputPort] + mapper2 SetLookupTable lut + +vtkActor actor2 + actor2 SetMapper mapper2 + +vtkPolyDataMapper mapper3 + mapper3 SetInputConnection [colorIt GetOutputPort] + mapper3 SetLookupTable lut + +vtkActor actor3 + actor3 SetMapper mapper3 + +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderer ren3 + +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin AddRenderer ren3 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor actor +ren1 SetBackground 1 1 1 + +ren2 AddActor actor2 +ren2 SetBackground 1 1 1 + +ren3 AddActor actor3 +ren3 SetBackground 1 1 1 + +renWin SetSize 600 200 +vtkCamera aCamera + aCamera Azimuth 70 +vtkLight aLight +eval aLight SetPosition [aCamera GetPosition] +eval aLight SetFocalPoint [aCamera GetFocalPoint] + +ren1 SetActiveCamera aCamera +ren1 AddLight aLight +ren1 ResetCamera +aCamera Dolly 1.4 +ren1 ResetCameraClippingRange + +ren2 SetActiveCamera aCamera +ren2 AddLight aLight + +ren3 SetActiveCamera aCamera +ren3 AddLight aLight + +ren3 SetViewport 0 0 .33 1 +ren2 SetViewport .33 0 .67 1 +ren1 SetViewport .67 0 1 1 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +proc flat {} { + [actor GetProperty] SetInterpolationToFlat + [actor2 GetProperty] SetInterpolationToFlat + [actor3 GetProperty] SetInterpolationToFlat + renWin Render +} + +proc smooth {} { + [actor GetProperty] SetInterpolationToGouraud + [actor2 GetProperty] SetInterpolationToGouraud + [actor3 GetProperty] SetInterpolationToGouraud + renWin Render +} + + +wm withdraw . diff --git a/Graphics/Testing/Tcl/sync3dAll.tcl b/Graphics/Testing/Tcl/sync3dAll.tcl new file mode 100644 index 0000000..e2797f1 --- /dev/null +++ b/Graphics/Testing/Tcl/sync3dAll.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkStructuredPointsReader slc + slc SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +set colors "$flesh $banana $grey $pink $carrot $gainsboro $tomato $gold $thistle $chocolate" +set types "UnsignedChar Char Short UnsignedShort Int UnsignedInt Long UnsignedLong Float Double" +set i 1 +set c 0 +foreach vtkType $types { + vtkImageClip clip$vtkType + clip$vtkType SetInputConnection [slc GetOutputPort] + clip$vtkType SetOutputWholeExtent -1000 1000 -1000 1000 $i [expr $i + 5] + incr i 5 + vtkImageCast castTo$vtkType + castTo$vtkType SetOutputScalarTypeTo$vtkType + castTo$vtkType SetInputConnection [clip$vtkType GetOutputPort] + castTo$vtkType ClampOverflowOn + + vtkSynchronizedTemplates3D iso$vtkType + iso$vtkType SetInputConnection [castTo$vtkType GetOutputPort] + iso$vtkType GenerateValues 1 30 30 + + vtkPolyDataMapper iso${vtkType}Mapper + iso${vtkType}Mapper SetInputConnection [iso$vtkType GetOutputPort] + iso${vtkType}Mapper ScalarVisibilityOff + + vtkActor iso${vtkType}Actor + iso${vtkType}Actor SetMapper iso${vtkType}Mapper + [iso${vtkType}Actor GetProperty] SetDiffuseColor [lindex $colors $c] [lindex $colors [expr $c + 1]] [lindex $colors [expr $c + 2]] + [iso${vtkType}Actor GetProperty] SetSpecularPower 30 + [iso${vtkType}Actor GetProperty] SetDiffuse .7 + [iso${vtkType}Actor GetProperty] SetSpecular .5 + incr c 3 + ren1 AddActor iso${vtkType}Actor +} + +vtkOutlineFilter outline + outline SetInputConnection [slc GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + outlineActor VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 SetBackground 0.9 .9 .9 +ren1 ResetCamera +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Azimuth 20 +[ren1 GetActiveCamera] Zoom 1.5 +ren1 ResetCameraClippingRange + +renWin SetSize 400 400 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Graphics/Testing/Tcl/teapotHulls.tcl b/Graphics/Testing/Tcl/teapotHulls.tcl new file mode 100644 index 0000000..f53c900 --- /dev/null +++ b/Graphics/Testing/Tcl/teapotHulls.tcl @@ -0,0 +1,75 @@ +package require vtk + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkBYUReader byuReader + byuReader SetGeometryFileName "$VTK_DATA_ROOT/Data/teapot.g" + +vtkPolyDataMapper byuMapper + byuMapper SetInputConnection [byuReader GetOutputPort] + +for { set i 0 } { $i < 9 } { incr i } { + vtkActor byuActor${i} + byuActor${i} SetMapper byuMapper + ren1 AddActor byuActor${i} + + vtkHull hull${i} + hull${i} SetInputConnection [byuReader GetOutputPort] + + vtkPolyDataMapper hullMapper${i} + hullMapper${i} SetInputConnection [hull${i} GetOutputPort] + + vtkActor hullActor${i} + hullActor${i} SetMapper hullMapper${i} + [hullActor${i} GetProperty] SetColor 1 0 0 + [hullActor${i} GetProperty] SetAmbient 0.2 + [hullActor${i} GetProperty] SetDiffuse 0.8 + [hullActor${i} GetProperty] SetRepresentationToWireframe + + ren1 AddActor hullActor${i} +} + +byuReader Update + +set diagonal [byuActor0 GetLength] +set i 0 +for { set j -1 } { $j < 2 } { incr j } { + for { set k -1 } { $k < 2 } { incr k } { + byuActor${i} AddPosition [expr $k * $diagonal] [expr $j * $diagonal] 0 + hullActor${i} AddPosition [expr $k * $diagonal] [expr $j * $diagonal] 0 + incr i + } +} + +hull0 AddCubeFacePlanes +hull1 AddCubeEdgePlanes +hull2 AddCubeVertexPlanes +hull3 AddCubeFacePlanes +hull3 AddCubeEdgePlanes +hull3 AddCubeVertexPlanes +hull4 AddRecursiveSpherePlanes 0 +hull5 AddRecursiveSpherePlanes 1 +hull6 AddRecursiveSpherePlanes 2 +hull7 AddRecursiveSpherePlanes 3 +hull8 AddRecursiveSpherePlanes 4 + +# Add the actors to the renderer, set the background and size +# +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 500 500 + +iren Initialize +renWin Render +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# for testing +set threshold 15 diff --git a/Graphics/Testing/Tcl/testDataSetTriangleFilter.tcl b/Graphics/Testing/Tcl/testDataSetTriangleFilter.tcl new file mode 100644 index 0000000..a7b9e78 --- /dev/null +++ b/Graphics/Testing/Tcl/testDataSetTriangleFilter.tcl @@ -0,0 +1,86 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +set PIECE 0 +set NUMBER_OF_PIECES 8 + +vtkImageReader reader + reader SetDataByteOrderToLittleEndian + reader SetDataExtent 0 63 0 63 1 64 + reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + reader SetDataMask 0x7fff + reader SetDataSpacing 1.6 1.6 1.5 + +vtkImageClip clipper + clipper SetInputConnection [reader GetOutputPort] + clipper SetOutputWholeExtent 30 36 30 36 30 36 + +vtkImageClip clipper2 + clipper2 SetInputConnection [reader GetOutputPort] + clipper2 SetOutputWholeExtent 30 36 30 36 30 36 + +vtkDataSetTriangleFilter tris + tris SetInputConnection [clipper GetOutputPort] + +vtkDataSetTriangleFilter tris2 + tris2 SetInputConnection [clipper2 GetOutputPort] + +vtkGeometryFilter geom + geom SetInputConnection [tris GetOutputPort] + +vtkExtractEdges edges + edges SetInputConnection [tris2 GetOutputPort] + +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [geom GetOutputPort] + mapper1 ScalarVisibilityOn + mapper1 SetScalarRange 0 1200 + mapper1 SetPiece $PIECE + mapper1 SetNumberOfPieces $NUMBER_OF_PIECES + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [edges GetOutputPort] + mapper2 SetPiece $PIECE + mapper2 SetNumberOfPieces $NUMBER_OF_PIECES + +vtkActor actor1 + actor1 SetMapper mapper1 + +vtkActor actor2 + actor2 SetMapper mapper2 + +# add the actor to the renderer; set the size +# +ren1 AddActor actor1 +ren1 AddActor actor2 +renWin SetSize 450 450 +ren1 SetBackground 1 1 1 + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + + + + + diff --git a/Graphics/Testing/Tcl/testDataSetTriangleFilter2.tcl b/Graphics/Testing/Tcl/testDataSetTriangleFilter2.tcl new file mode 100644 index 0000000..dbf963b --- /dev/null +++ b/Graphics/Testing/Tcl/testDataSetTriangleFilter2.tcl @@ -0,0 +1,59 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkDataSetReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/uGridEx.vtk" + +vtkDataSetTriangleFilter tris + tris SetInputConnection [reader GetOutputPort] + +vtkShrinkFilter shrink + shrink SetInputConnection [tris GetOutputPort] + shrink SetShrinkFactor .8 + +vtkDataSetMapper mapper + mapper SetInputConnection [shrink GetOutputPort] + mapper SetScalarRange 0 26 +vtkActor actor + actor SetMapper mapper + +# add the actor to the renderer; set the size +# +ren1 AddActor actor +renWin SetSize 350 350 +ren1 SetBackground 1 1 1 + +[ren1 GetActiveCamera] SetPosition -4.01115 6.03964 10.5393 +[ren1 GetActiveCamera] SetFocalPoint 1 0.525 3.025 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp 0.114284 0.835731 -0.537115 +[ren1 GetActiveCamera] SetClippingRange 4.83787 17.8392 + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + + + + + diff --git a/Graphics/Testing/Tcl/testHexaPenta.tcl b/Graphics/Testing/Tcl/testHexaPenta.tcl new file mode 100644 index 0000000..8d639e8 --- /dev/null +++ b/Graphics/Testing/Tcl/testHexaPenta.tcl @@ -0,0 +1,90 @@ +package require vtk +package require vtkinteraction + +# read the football dataset: +# + +vtkUnstructuredGridReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/PentaHexa.vtk" + reader Update + +# Clip +# +vtkPlane plane + plane SetNormal 1 1 0 +vtkClipDataSet clip + clip SetInputConnection [reader GetOutputPort] + clip SetClipFunction plane + clip GenerateClipScalarsOn +vtkDataSetSurfaceFilter g + g SetInputConnection [clip GetOutputPort] +vtkPolyDataMapper map + map SetInputConnection [g GetOutputPort] +vtkActor clipActor + clipActor SetMapper map + +# Contour +# +vtkContourFilter contour + contour SetInputConnection [reader GetOutputPort] + contour SetValue 0 0.125 + contour SetValue 1 0.25 + contour SetValue 2 0.5 + contour SetValue 3 0.75 + contour SetValue 4 1.0 +vtkDataSetSurfaceFilter g2 + g2 SetInputConnection [contour GetOutputPort] +vtkPolyDataMapper map2 + map2 SetInputConnection [g2 GetOutputPort] + map2 ScalarVisibilityOff +vtkActor contourActor + contourActor SetMapper map2 + [contourActor GetProperty] SetColor 1 0 0 + [contourActor GetProperty] SetRepresentationToWireframe + + +# Triangulate +vtkDataSetTriangleFilter tris + tris SetInputConnection [reader GetOutputPort] + +vtkShrinkFilter shrink + shrink SetInputConnection [tris GetOutputPort] + shrink SetShrinkFactor .8 + +vtkDataSetMapper map3 + map3 SetInputConnection [shrink GetOutputPort] + map3 SetScalarRange 0 26 + +vtkActor triActor + triActor SetMapper map3 + triActor AddPosition 2 0 0 + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor clipActor +ren1 AddActor contourActor +ren1 AddActor triActor + +ren1 SetBackground 1 1 1 + +renWin Render + +# render the image +# +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/testQuadricDecimation.tcl b/Graphics/Testing/Tcl/testQuadricDecimation.tcl new file mode 100644 index 0000000..4d960a9 --- /dev/null +++ b/Graphics/Testing/Tcl/testQuadricDecimation.tcl @@ -0,0 +1,72 @@ +package require vtk +package require vtkinteraction + +# Create renderer stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# pipeline stuff +# + +vtkSphereSource sphere + sphere SetPhiResolution 5 + sphere SetThetaResolution 5 + sphere SetRadius 1 + +vtkTransform xform + xform Scale 1 2 3 + xform RotateWXYZ 32 3 1 2 + xform Scale 2 5 4 + +vtkTransformFilter xformFilter + xformFilter SetInputConnection [sphere GetOutputPort] + xformFilter SetTransform xform + +vtkElevationFilter el + el SetInputConnection [xformFilter GetOutputPort] + el SetLowPoint 0 0 0 + el SetHighPoint 0 0 1 + +vtkQuadricDecimation mesh + mesh SetInputConnection [el GetOutputPort] + mesh SetTargetReduction .60 + mesh AttributeErrorMetricOn + +vtkPolyDataMapper mapper + mapper SetInputConnection [mesh GetOutputPort] + +vtkActor actor + actor SetMapper mapper + +# Set up the camera parameters +# +vtkCamera camera + camera SetPosition -58.3274 -.948032 17.7715 + camera SetFocalPoint -.172376 .389125 -.100301 + camera SetViewUp -.0374429 .998186 -.0471559 + camera SetViewAngle 30 + camera SetClippingRange 48.8511 76.1099 + +ren1 SetActiveCamera camera + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + +renWin Render diff --git a/Graphics/Testing/Tcl/testReflect.tcl b/Graphics/Testing/Tcl/testReflect.tcl new file mode 100644 index 0000000..c40c2d1 --- /dev/null +++ b/Graphics/Testing/Tcl/testReflect.tcl @@ -0,0 +1,38 @@ +package require vtk +package require vtkinteraction + +vtkConeSource cone + +vtkReflectionFilter reflect +reflect SetInputConnection [cone GetOutputPort] +reflect SetPlaneToXMax + +vtkReflectionFilter reflect2 +reflect2 SetInputConnection [reflect GetOutputPort] +reflect2 SetPlaneToYMax + +vtkReflectionFilter reflect3 +reflect3 SetInputConnection [reflect2 GetOutputPort] +reflect3 SetPlaneToZMax + +vtkDataSetMapper mapper +mapper SetInputConnection [reflect3 GetOutputPort] + +vtkActor actor +actor SetMapper mapper + +vtkRenderer ren1 +ren1 AddActor actor + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 200 200 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +renWin Render + +wm withdraw . \ No newline at end of file diff --git a/Graphics/Testing/Tcl/textureThreshold.tcl b/Graphics/Testing/Tcl/textureThreshold.tcl new file mode 100644 index 0000000..bc4d2be --- /dev/null +++ b/Graphics/Testing/Tcl/textureThreshold.tcl @@ -0,0 +1,134 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/bluntfinxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/bluntfinq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# wall +# +vtkStructuredGridGeometryFilter wall + wall SetInputConnection [pl3d GetOutputPort] + wall SetExtent 0 100 0 0 0 100 +vtkPolyDataMapper wallMap + wallMap SetInputConnection [wall GetOutputPort] + wallMap ScalarVisibilityOff +vtkActor wallActor + wallActor SetMapper wallMap + eval [wallActor GetProperty] SetColor 0.8 0.8 0.8 + +# fin +# +vtkStructuredGridGeometryFilter fin + fin SetInputConnection [pl3d GetOutputPort] + fin SetExtent 0 100 0 100 0 0 +vtkPolyDataMapper finMap + finMap SetInputConnection [fin GetOutputPort] + finMap ScalarVisibilityOff +vtkActor finActor + finActor SetMapper finMap + eval [finActor GetProperty] SetColor 0.8 0.8 0.8 + +# planes to threshold +vtkStructuredPointsReader tmap + tmap SetFileName "$VTK_DATA_ROOT/Data/texThres2.vtk" +vtkTexture texture + texture SetInputConnection [tmap GetOutputPort] + texture InterpolateOff + texture RepeatOff + +vtkStructuredGridGeometryFilter plane1 + plane1 SetInputConnection [pl3d GetOutputPort] + plane1 SetExtent 10 10 0 100 0 100 +vtkThresholdTextureCoords thresh1 + thresh1 SetInputConnection [plane1 GetOutputPort] + thresh1 ThresholdByUpper 1.5 +vtkDataSetMapper plane1Map + plane1Map SetInputConnection [thresh1 GetOutputPort] + eval plane1Map SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor plane1Actor + plane1Actor SetMapper plane1Map + plane1Actor SetTexture texture +[plane1Actor GetProperty] SetOpacity 0.999 + +vtkStructuredGridGeometryFilter plane2 + plane2 SetInputConnection [pl3d GetOutputPort] + plane2 SetExtent 30 30 0 100 0 100 +vtkThresholdTextureCoords thresh2 + thresh2 SetInputConnection [plane2 GetOutputPort] + thresh2 ThresholdByLower 1.5 +vtkDataSetMapper plane2Map + plane2Map SetInputConnection [thresh2 GetOutputPort] + eval plane2Map SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor plane2Actor + plane2Actor SetMapper plane2Map + plane2Actor SetTexture texture + [plane2Actor GetProperty] SetOpacity 0.999 + +vtkStructuredGridGeometryFilter plane3 + plane3 SetInputConnection [pl3d GetOutputPort] + plane3 SetExtent 35 35 0 100 0 100 +vtkThresholdTextureCoords thresh3 + thresh3 SetInputConnection [plane3 GetOutputPort] + thresh3 ThresholdBetween 1.5 1.8 +vtkDataSetMapper plane3Map + plane3Map SetInputConnection [thresh3 GetOutputPort] + eval plane3Map SetScalarRange [[pl3d GetOutput] GetScalarRange] +vtkActor plane3Actor + plane3Actor SetMapper plane3Map + plane3Actor SetTexture texture + [plane3Actor GetProperty] SetOpacity 0.999 + +# outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + set outlineProp [outlineActor GetProperty] + eval $outlineProp SetColor 0 0 0 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor wallActor +ren1 AddActor finActor +ren1 AddActor plane1Actor +ren1 AddActor plane2Actor +ren1 AddActor plane3Actor +ren1 SetBackground 1 1 1 +renWin SetSize 256 256 + +vtkCamera cam1 + cam1 SetClippingRange 1.51176 75.5879 + cam1 SetFocalPoint 2.33749 2.96739 3.61023 + cam1 SetPosition 10.8787 5.27346 15.8687 + cam1 SetViewAngle 30 + cam1 SetViewUp -0.0610856 0.987798 -0.143262 +ren1 SetActiveCamera cam1 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Graphics/Testing/Tcl/triangularTCoords.tcl b/Graphics/Testing/Tcl/triangularTCoords.tcl new file mode 100644 index 0000000..b172c6f --- /dev/null +++ b/Graphics/Testing/Tcl/triangularTCoords.tcl @@ -0,0 +1,65 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + + +vtkTriangularTexture aTriangularTexture + aTriangularTexture SetTexturePattern 2 + aTriangularTexture SetScaleFactor 1.3 + aTriangularTexture SetXSize 64 + aTriangularTexture SetYSize 64 + +vtkSphereSource aSphere + aSphere SetThetaResolution 20 + aSphere SetPhiResolution 20 + +vtkTriangularTCoords tCoords + tCoords SetInputConnection [aSphere GetOutputPort] + +vtkPolyDataMapper triangleMapper + triangleMapper SetInputConnection [tCoords GetOutputPort] + +vtkTexture aTexture + aTexture SetInputConnection [aTriangularTexture GetOutputPort] + aTexture InterpolateOn + +vtkActor texturedActor + texturedActor SetMapper triangleMapper + texturedActor SetTexture aTexture + [texturedActor GetProperty] BackfaceCullingOn + eval [texturedActor GetProperty] SetDiffuseColor $banana + eval [texturedActor GetProperty] SetSpecular .4 + eval [texturedActor GetProperty] SetSpecularPower 40 + +vtkCubeSource aCube + aCube SetXLength .5 + aCube SetYLength .5 + +vtkPolyDataMapper aCubeMapper + aCubeMapper SetInputConnection [aCube GetOutputPort] + +vtkActor cubeActor + cubeActor SetMapper aCubeMapper + eval [cubeActor GetProperty] SetDiffuseColor $tomato + +eval ren1 SetBackground $slate_grey +ren1 AddActor cubeActor +ren1 AddActor texturedActor +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/triangularTexture.tcl b/Graphics/Testing/Tcl/triangularTexture.tcl new file mode 100644 index 0000000..40e6b94 --- /dev/null +++ b/Graphics/Testing/Tcl/triangularTexture.tcl @@ -0,0 +1,77 @@ +package require vtk +package require vtkinteraction +# +# create a triangular texture +# + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + + +vtkTriangularTexture aTriangularTexture + aTriangularTexture SetTexturePattern 1 + aTriangularTexture SetXSize 32 + aTriangularTexture SetYSize 32 + +vtkPoints points + points InsertPoint 0 0.0 0.0 0.0 + points InsertPoint 1 1.0 0.0 0.0 + points InsertPoint 2 .5 1.0 0.0 + points InsertPoint 3 1.0 0.0 0.0 + points InsertPoint 4 0.0 0.0 0.0 + points InsertPoint 5 .5 -1.0 .5 + +vtkFloatArray tCoords + tCoords SetNumberOfComponents 2 + tCoords InsertTuple2 0 0.0 0.0 + tCoords InsertTuple2 1 1.0 0.0 + tCoords InsertTuple2 2 .5 .86602540378443864676 + tCoords InsertTuple2 3 0.0 0.0 + tCoords InsertTuple2 4 1.0 0.0 + tCoords InsertTuple2 5 .5 .86602540378443864676 + +vtkPointData pointData + pointData SetTCoords tCoords + +vtkCellArray triangles + triangles InsertNextCell 3 + triangles InsertCellPoint 0 + triangles InsertCellPoint 1 + triangles InsertCellPoint 2 + triangles InsertNextCell 3 + triangles InsertCellPoint 3 + triangles InsertCellPoint 4 + triangles InsertCellPoint 5 + +vtkPolyData triangle + triangle SetPolys triangles + triangle SetPoints points + [triangle GetPointData] SetTCoords tCoords + +vtkPolyDataMapper triangleMapper + triangleMapper SetInput triangle + +vtkTexture aTexture + aTexture SetInputConnection [aTriangularTexture GetOutputPort] + +vtkActor triangleActor + triangleActor SetMapper triangleMapper + triangleActor SetTexture aTexture + +ren1 SetBackground .3 .7 .2 +ren1 AddActor triangleActor +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Graphics/Testing/Tcl/warplens.tcl b/Graphics/Testing/Tcl/warplens.tcl new file mode 100644 index 0000000..f8b7a87 --- /dev/null +++ b/Graphics/Testing/Tcl/warplens.tcl @@ -0,0 +1,67 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# load in the texture map +# +vtkPNGReader pngReader +pngReader SetFileName "$VTK_DATA_ROOT/Data/camscene.png" +pngReader Update + +set xWidth [lindex [[pngReader GetOutput] GetDimensions] 0] +set yHeight [lindex [[pngReader GetOutput] GetDimensions] 1] + +vtkGeometryFilter gf +gf SetInputConnection [pngReader GetOutputPort] + +vtkWarpLens wl +wl SetInputConnection [gf GetOutputPort] + +wl SetPrincipalPoint 2.4507 1.7733 +wl SetFormatWidth 4.792 +wl SetFormatHeight 3.6 +wl SetImageWidth $xWidth +wl SetImageHeight $yHeight +wl SetK1 0.01307 +wl SetK2 0.0003102 +wl SetP1 1.953e-005 +wl SetP2 -9.655e-005 + +vtkTriangleFilter tf +tf SetInput [wl GetPolyDataOutput] + +vtkStripper strip +strip SetInputConnection [tf GetOutputPort] +strip SetMaximumLength 250 + +vtkPolyDataMapper dsm +dsm SetInputConnection [strip GetOutputPort] + +vtkActor planeActor +planeActor SetMapper dsm + +# Add the actors to the renderer, set the background and size +ren1 AddActor planeActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render +[ren1 GetActiveCamera] Zoom 1.4 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + diff --git a/Graphics/vtkAppendFilter.cxx b/Graphics/vtkAppendFilter.cxx new file mode 100644 index 0000000..0149423 --- /dev/null +++ b/Graphics/vtkAppendFilter.cxx @@ -0,0 +1,282 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAppendFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAppendFilter.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkDataSetAttributes.h" +#include "vtkDataSetCollection.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkAppendFilter, "$Revision: 1.73 $"); +vtkStandardNewMacro(vtkAppendFilter); + +//---------------------------------------------------------------------------- +vtkAppendFilter::vtkAppendFilter() +{ + this->InputList = NULL; +} + +//---------------------------------------------------------------------------- +vtkAppendFilter::~vtkAppendFilter() +{ + if (this->InputList != NULL) + { + this->InputList->Delete(); + this->InputList = NULL; + } +} + +//---------------------------------------------------------------------------- +vtkDataSet *vtkAppendFilter::GetInput(int idx) +{ + if (idx >= this->GetNumberOfInputConnections(0) || idx < 0) + { + return NULL; + } + + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(0, idx)); +} + +//---------------------------------------------------------------------------- +// Remove a dataset from the list of data to append. +void vtkAppendFilter::RemoveInput(vtkDataSet *ds) +{ + vtkAlgorithmOutput *algOutput = 0; + if (ds) + { + algOutput = ds->GetProducerPort(); + } + + this->RemoveInputConnection(0, algOutput); +} + +//---------------------------------------------------------------------------- +vtkDataSetCollection *vtkAppendFilter::GetInputList() +{ + int idx; + + if (this->InputList) + { + this->InputList->Delete(); + } + this->InputList = vtkDataSetCollection::New(); + + for (idx = 0; idx < this->GetNumberOfInputConnections(0); ++idx) + { + if (this->GetInput(idx)) + { + this->InputList->AddItem((vtkDataSet*)(this->GetInput(idx))); + } + } + + return this->InputList; +} + +//---------------------------------------------------------------------------- +// Append data sets into single unstructured grid +int vtkAppendFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the output info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells, ptOffset; + int tenth, count, abort=0; + float decimal; + vtkPoints *newPts; + vtkPointData *pd; + vtkCellData *cd; + vtkIdList *ptIds, *newPtIds; + int i, idx; + vtkDataSet *ds; + vtkIdType ptId, cellId, newCellId; + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + int numInputs = this->GetNumberOfInputConnections(0); + + vtkDebugMacro(<<"Appending data together"); + + // Loop over all data sets, checking to see what data is common to + // all inputs. Note that data is common if 1) it is the same attribute + // type (scalar, vector, etc.), 2) it is the same native type (int, + // float, etc.), and 3) if a data array in a field, if it has the same name. + count = 0; + decimal = 0.0; + + numPts = 0; + numCells = 0; + + vtkDataSetAttributes::FieldList ptList(numInputs); + vtkDataSetAttributes::FieldList cellList(numInputs); + int firstPD=1; + int firstCD=1; + vtkInformation *inInfo = 0; + for (idx = 0; idx < numInputs; ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + ds = 0; + if (inInfo) + { + ds = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + } + if (ds != NULL) + { + if ( ds->GetNumberOfPoints() <= 0 && ds->GetNumberOfCells() <= 0 ) + { + continue; //no input, just skip + } + + numPts += ds->GetNumberOfPoints(); + numCells += ds->GetNumberOfCells(); + + pd = ds->GetPointData(); + if ( firstPD ) + { + ptList.InitializeFieldList(pd); + firstPD = 0; + } + else + { + ptList.IntersectFieldList(pd); + } + + cd = ds->GetCellData(); + if ( firstCD ) + { + cellList.InitializeFieldList(cd); + firstCD = 0; + } + else + { + cellList.IntersectFieldList(cd); + } + }//if non-empty dataset + }//for all inputs + + if ( numPts < 1) + { + vtkDebugMacro(<<"No data to append!"); + return 1; + } + + // Now can allocate memory + output->Allocate(numCells); //allocate storage for geometry/topology + outputPD->CopyAllocate(ptList,numPts); + outputCD->CopyAllocate(cellList,numCells); + + newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + ptIds = vtkIdList::New(); ptIds->Allocate(VTK_CELL_SIZE); + newPtIds = vtkIdList::New(); newPtIds->Allocate(VTK_CELL_SIZE); + + // Append each input dataset together + // + tenth = (numPts + numCells)/10 + 1; + ptOffset=0; + int inputCount = 0; // Since empty inputs are not in the list. + for (idx = 0; idx < numInputs && !abort; ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + ds = 0; + if (inInfo) + { + ds = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + } + if ( ds != NULL && + (ds->GetNumberOfPoints() > 0 || ds->GetNumberOfCells() > 0) ) + { + numPts = ds->GetNumberOfPoints(); + numCells = ds->GetNumberOfCells(); + pd = ds->GetPointData(); + + // copy points and point data + for (ptId=0; ptId < numPts && !abort; ptId++) + { + newPts->SetPoint(ptId+ptOffset,ds->GetPoint(ptId)); + outputPD->CopyData(ptList,pd,inputCount,ptId,ptId+ptOffset); + + // Update progress + count++; + if ( !(count % tenth) ) + { + decimal += 0.1; + this->UpdateProgress (decimal); + abort = this->GetAbortExecute(); + } + } + + cd = ds->GetCellData(); + // copy cell and cell data + for (cellId=0; cellId < numCells && !abort; cellId++) + { + ds->GetCellPoints(cellId, ptIds); + newPtIds->Reset (); + for (i=0; i < ptIds->GetNumberOfIds(); i++) + { + newPtIds->InsertId(i,ptIds->GetId(i)+ptOffset); + } + newCellId = output->InsertNextCell(ds->GetCellType(cellId),newPtIds); + outputCD->CopyData(cellList,cd,inputCount,cellId,newCellId); + + // Update progress + count++; + if ( !(count % tenth) ) + { + decimal += 0.1; + this->UpdateProgress (decimal); + abort = this->GetAbortExecute(); + } + } + ptOffset+=numPts; + ++inputCount; + } + } + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + ptIds->Delete(); + newPtIds->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkAppendFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkAppendFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkAppendFilter.h b/Graphics/vtkAppendFilter.h new file mode 100644 index 0000000..cdf88e5 --- /dev/null +++ b/Graphics/vtkAppendFilter.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAppendFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAppendFilter - appends one or more datasets together into a single unstructured grid +// .SECTION Description +// vtkAppendFilter is a filter that appends one of more datasets into a single +// unstructured grid. All geometry is extracted and appended, but point +// attributes (i.e., scalars, vectors, normals, field data, etc.) are extracted +// and appended only if all datasets have the point attributes available. +// (For example, if one dataset has scalars but another does not, scalars will +// not be appended.) + +// .SECTION See Also +// vtkAppendPolyData + +#ifndef __vtkAppendFilter_h +#define __vtkAppendFilter_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkDataSetCollection; + +class VTK_GRAPHICS_EXPORT vtkAppendFilter : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkAppendFilter *New(); + + vtkTypeRevisionMacro(vtkAppendFilter,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get any input of this filter. +//BTX + vtkDataSet *GetInput(int idx); + vtkDataSet *GetInput() + {return this->GetInput( 0 );} +//ETX + + // Description: + // Remove a dataset from the list of data to append. + void RemoveInput(vtkDataSet *in); + + // Description: + // Returns a copy of the input array. Modifications to this list + // will not be reflected in the actual inputs. + vtkDataSetCollection *GetInputList(); + +protected: + vtkAppendFilter(); + ~vtkAppendFilter(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + // list of data sets to append together. + // Here as a convenience. It is a copy of the input array. + vtkDataSetCollection *InputList; + +private: + vtkAppendFilter(const vtkAppendFilter&); // Not implemented. + void operator=(const vtkAppendFilter&); // Not implemented. +}; + + +#endif + + diff --git a/Graphics/vtkAppendPolyData.cxx b/Graphics/vtkAppendPolyData.cxx new file mode 100644 index 0000000..6a94e2a --- /dev/null +++ b/Graphics/vtkAppendPolyData.cxx @@ -0,0 +1,740 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAppendPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAppendPolyData.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDataSetAttributes.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkAppendPolyData, "$Revision: 1.98 $"); +vtkStandardNewMacro(vtkAppendPolyData); + +//---------------------------------------------------------------------------- +vtkAppendPolyData::vtkAppendPolyData() +{ + this->ParallelStreaming = 0; + this->UserManagedInputs = 0; +} + +//---------------------------------------------------------------------------- +vtkAppendPolyData::~vtkAppendPolyData() +{ +} + +//---------------------------------------------------------------------------- +// Add a dataset to the list of data to append. +void vtkAppendPolyData::AddInput(vtkPolyData *ds) +{ + if (this->UserManagedInputs) + { + vtkErrorMacro(<< + "AddInput is not supported if UserManagedInputs is true"); + return; + } + this->Superclass::AddInput(ds); +} + +//---------------------------------------------------------------------------- +// Remove a dataset from the list of data to append. +void vtkAppendPolyData::RemoveInput(vtkPolyData *ds) +{ + if (this->UserManagedInputs) + { + vtkErrorMacro(<< + "RemoveInput is not supported if UserManagedInputs is true"); + return; + } + + vtkAlgorithmOutput *algOutput = 0; + if (ds) + { + algOutput = ds->GetProducerPort(); + } + + this->RemoveInputConnection(0, algOutput); +} + +//---------------------------------------------------------------------------- +// make ProcessObject function visible +// should only be used when UserManagedInputs is true. +void vtkAppendPolyData::SetNumberOfInputs(int num) +{ + if (!this->UserManagedInputs) + { + vtkErrorMacro(<< + "SetNumberOfInputs is not supported if UserManagedInputs is false"); + return; + } + + // Ask the superclass to set the number of connections. + this->SetNumberOfInputConnections(0, num); +} + +//---------------------------------------------------------------------------- +// Set Nth input, should only be used when UserManagedInputs is true. +void vtkAppendPolyData::SetInputByNumber(int num, vtkPolyData *input) +{ + if (!this->UserManagedInputs) + { + vtkErrorMacro(<< + "SetInputByNumber is not supported if UserManagedInputs is false"); + return; + } + + // Ask the superclass to connect the input. + this->SetNthInputConnection(0, num, input? input->GetProducerPort() : 0); +} + +//---------------------------------------------------------------------------- +// This method is much too long, and has to be broken up! +// Append data sets into single polygonal data set. +int vtkAppendPolyData::RequestData(vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int idx; + vtkPolyData *ds; + vtkPoints *inPts; + vtkPoints *newPts; + vtkCellArray *inVerts, *newVerts; + vtkCellArray *inLines, *newLines; + vtkCellArray *inPolys, *newPolys; + vtkIdType sizePolys, numPolys; + vtkCellArray *inStrips, *newStrips; + vtkIdType numPts, numCells; + vtkPointData *inPD = NULL; + vtkCellData *inCD = NULL; + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkDataArray *newPtScalars = NULL; + vtkDataArray *newPtVectors = NULL; + vtkDataArray *newPtNormals = NULL; + vtkDataArray *newPtTCoords = NULL; + vtkDataArray *newPtTensors = NULL; + int i; + vtkIdType *pts = 0; + vtkIdType *pPolys; + vtkIdType npts = 0; + vtkIdType ptId, cellId; + + vtkDebugMacro(<<"Appending polydata"); + + // loop over all data sets, checking to see what point data is available. + numPts = 0; + numCells = 0; + sizePolys = numPolys = 0; + + int countPD=0; + int countCD=0; + + int numInputs = this->GetNumberOfInputConnections(0); + vtkInformation *inInfo; + + // These Field lists are very picky. Count the number of non empty inputs + // so we can initialize them properly. + for (idx = 0; idx < numInputs; ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + if (ds != NULL) + { + if ( ds->GetNumberOfPoints() > 0) + { + ++countPD; + } + if (ds->GetNumberOfCells() > 0 ) + { + ++countCD; + } // for a data set that has cells + } // for a non NULL input + } // for each input + + // These are used to determine which fields are available for appending + vtkDataSetAttributes::FieldList ptList(countPD); + vtkDataSetAttributes::FieldList cellList(countCD); + + countPD = countCD = 0; + for (idx = 0; idx < numInputs; ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + if (ds != NULL) + { + // Skip points and cells if there are no points. Empty inputs may have no arrays. + if ( ds->GetNumberOfPoints() > 0) + { + numPts += ds->GetNumberOfPoints(); + // Take intersection of available point data fields. + inPD = ds->GetPointData(); + if ( countPD == 0 ) + { + ptList.InitializeFieldList(inPD); + } + else + { + ptList.IntersectFieldList(inPD); + } + ++countPD; + } // for a data set that has points + + // Although we cannot have cells without points ... let's not nest. + if (ds->GetNumberOfCells() > 0 ) + { + // keep track of the size of the poly cell array + if (ds->GetPolys()) + { + numPolys += ds->GetPolys()->GetNumberOfCells(); + sizePolys += ds->GetPolys()->GetNumberOfConnectivityEntries(); + } + numCells += ds->GetNumberOfCells(); + + inCD = ds->GetCellData(); + if ( countCD == 0 ) + { + cellList.InitializeFieldList(inCD); + } + else + { + cellList.IntersectFieldList(inCD); + } + ++countCD; + } // for a data set that has cells + } // for a non NULL input + } // for each input + + if ( numPts < 1 || numCells < 1 ) + { + vtkDebugMacro(<<"No data to append!"); + return 1; + } + this->UpdateProgress(0.10); + + // Examine the points and check if they're the same type. If not, + // use highest (double probably), otherwise the type of the first + // array (float no doubt). Depends on defs in vtkSetGet.h - Warning. + int ttype, firstType=1, AllSame=1; + int pointtype = 0; + + // Keep track of types for fast point append + for (idx = 0; idx < numInputs; ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + if (ds != NULL && ds->GetNumberOfPoints()>0) + { + if ( firstType ) + { + firstType = 0; + pointtype = ds->GetPoints()->GetData()->GetDataType(); + } + ttype = ds->GetPoints()->GetData()->GetDataType(); + + if ( ttype != pointtype ) + { + AllSame = 0; + vtkDebugMacro(<<"Different point data types"); + } + pointtype = pointtype > ttype ? pointtype : ttype; + } + } + + // Allocate geometry/topology + newPts = vtkPoints::New(pointtype); + newPts->SetNumberOfPoints(numPts); + + newVerts = vtkCellArray::New(); + newVerts->Allocate(numCells*4); + + newLines = vtkCellArray::New(); + newLines->Allocate(numCells*4); + + newStrips = vtkCellArray::New(); + newStrips->Allocate(numCells*4); + + newPolys = vtkCellArray::New(); + pPolys = newPolys->WritePointer(numPolys, sizePolys); + + // These are created manually for faster execution + // Uses the properties of the last input + if ( ptList.IsAttributePresent(vtkDataSetAttributes::SCALARS) > -1 ) + { + outputPD->CopyScalarsOff(); + newPtScalars = inPD->GetScalars()->NewInstance(); + newPtScalars->SetNumberOfComponents(inPD->GetScalars()->GetNumberOfComponents()); + newPtScalars->SetName(inPD->GetScalars()->GetName()); + newPtScalars->SetNumberOfTuples(numPts); + } + if ( ptList.IsAttributePresent(vtkDataSetAttributes::VECTORS) > -1 ) + { + outputPD->CopyVectorsOff(); + newPtVectors = inPD->GetVectors()->NewInstance(); + newPtVectors->SetNumberOfComponents(inPD->GetVectors()->GetNumberOfComponents()); + newPtVectors->SetName(inPD->GetVectors()->GetName()); + newPtVectors->SetNumberOfTuples(numPts); + } + if ( ptList.IsAttributePresent(vtkDataSetAttributes::TENSORS) > -1 ) + { + outputPD->CopyTensorsOff(); + newPtTensors = inPD->GetTensors()->NewInstance(); + newPtTensors->SetNumberOfComponents(inPD->GetTensors()->GetNumberOfComponents()); + newPtTensors->SetName(inPD->GetTensors()->GetName()); + newPtTensors->SetNumberOfTuples(numPts); + } + if ( ptList.IsAttributePresent(vtkDataSetAttributes::NORMALS) > -1 ) + { + outputPD->CopyNormalsOff(); + newPtNormals = inPD->GetNormals()->NewInstance(); + newPtNormals->SetNumberOfComponents(inPD->GetNormals()->GetNumberOfComponents()); + newPtNormals->SetName(inPD->GetNormals()->GetName()); + newPtNormals->SetNumberOfTuples(numPts); + } + if ( ptList.IsAttributePresent(vtkDataSetAttributes::TCOORDS) > -1 ) + { + outputPD->CopyTCoordsOff(); + newPtTCoords = inPD->GetTCoords()->NewInstance(); + newPtTCoords->SetNumberOfComponents(inPD->GetTCoords()->GetNumberOfComponents()); + newPtTCoords->SetName(inPD->GetTCoords()->GetName()); + newPtTCoords->SetNumberOfTuples(numPts); + } + + // Allocate the point and cell data + outputPD->CopyAllocate(ptList,numPts); + outputCD->CopyAllocate(cellList,numCells); + + // loop over all input sets + vtkIdType ptOffset = 0; + vtkIdType cellOffset = 0; + countPD = countCD = 0; + for (idx = 0; idx < numInputs; ++idx) + { + this->UpdateProgress(0.2 + 0.8*idx/numInputs); + inInfo = inputVector[0]->GetInformationObject(idx); + ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + // this check is not necessary, but I'll put it in anyway + if (ds != NULL) + { + numPts = ds->GetNumberOfPoints(); + numCells = ds->GetNumberOfCells(); + if ( numPts <= 0 && numCells <= 0 ) + { + continue; //no input, just skip + } + + inPD = ds->GetPointData(); + inCD = ds->GetCellData(); + + inPts = ds->GetPoints(); + inVerts = ds->GetVerts(); + inLines = ds->GetLines(); + inPolys = ds->GetPolys(); + inStrips = ds->GetStrips(); + + if (ds->GetNumberOfPoints() > 0) + { + // copy points directly + if (AllSame) + { + this->AppendData(newPts->GetData(), + inPts->GetData(), ptOffset); + } + else + { + this->AppendDifferentPoints(newPts->GetData(), + inPts->GetData(), ptOffset); + } + // copy scalars directly + if (newPtScalars) + { + this->AppendData(newPtScalars,inPD->GetScalars(), ptOffset); + } + // copy normals directly + if (newPtNormals) + { + this->AppendData(newPtNormals, inPD->GetNormals(), ptOffset); + } + // copy vectors directly + if (newPtVectors) + { + this->AppendData(newPtVectors, inPD->GetVectors(), ptOffset); + } + // copy tcoords directly + if (newPtTCoords) + { + this->AppendData(newPtTCoords, inPD->GetTCoords() , ptOffset); + } + // copy tensors directly + if (newPtTensors) + { + this->AppendData(newPtTensors, inPD->GetTensors(), ptOffset); + } + // append the remainder of the field data + for (ptId=0; ptId < numPts; ptId++) + { + outputPD->CopyData(ptList,inPD,countPD,ptId,ptId+ptOffset); + } + ++countPD; + } + + if (ds->GetNumberOfCells() > 0) + { + // cell data could be made efficient like the point data, + // but I will wait on that. + // copy cell data + for (cellId=0; cellId < numCells; cellId++) + { + outputCD->CopyData(cellList,inCD,countCD,cellId,cellId+cellOffset); + } + ++countCD; + + // copy the cells + pPolys = this->AppendCells(pPolys, inPolys, ptOffset); + + // These other cell arrays could be made efficient like polys ... + for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); ) + { + newVerts->InsertNextCell(npts); + for (i=0; i < npts; i++) + { + newVerts->InsertCellPoint(pts[i]+ptOffset); + } + } + + for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); ) + { + newLines->InsertNextCell(npts); + for (i=0; i < npts; i++) + { + newLines->InsertCellPoint(pts[i]+ptOffset); + } + } + + for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + newStrips->InsertNextCell(npts); + for (i=0; i < npts; i++) + { + newStrips->InsertCellPoint(pts[i]+ptOffset); + } + } + } + ptOffset += numPts; + cellOffset += numCells; + } + } + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newPtScalars) + { + output->GetPointData()->SetScalars(newPtScalars); + newPtScalars->Delete(); + } + if (newPtNormals) + { + output->GetPointData()->SetNormals(newPtNormals); + newPtNormals->Delete(); + } + if (newPtVectors) + { + output->GetPointData()->SetVectors(newPtVectors); + newPtVectors->Delete(); + } + if (newPtTCoords) + { + output->GetPointData()->SetTCoords(newPtTCoords); + newPtTCoords->Delete(); + } + if (newPtTensors) + { + output->GetPointData()->SetTensors(newPtTensors); + newPtTensors->Delete(); + } + + if ( newVerts->GetNumberOfCells() > 0 ) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if ( newLines->GetNumberOfCells() > 0 ) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if ( newPolys->GetNumberOfCells() > 0 ) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + if ( newStrips->GetNumberOfCells() > 0 ) + { + output->SetStrips(newStrips); + } + newStrips->Delete(); + + // When all optimizations are complete, this squeeze will be unecessary. + // (But it does not seem to cost much.) + output->Squeeze(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkAppendPolyData::RequestUpdateExtent(vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the output info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces, ghostLevel; + int idx; + + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + // make sure piece is valid + if (piece < 0 || piece >= numPieces) + { + return 0; + } + + int numInputs = this->GetNumberOfInputConnections(0); + if (this->ParallelStreaming) + { + piece = piece * numInputs; + numPieces = numPieces * numInputs; + } + + vtkInformation *inInfo; + // just copy the Update extent as default behavior. + for (idx = 0; idx < numInputs; ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + if (inInfo) + { + if (this->ParallelStreaming) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + piece + idx); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel); + } + else + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + piece); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel); + } + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +vtkPolyData *vtkAppendPolyData::GetInput(int idx) +{ + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(0, idx)); +} + +//---------------------------------------------------------------------------- +void vtkAppendPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << "ParallelStreaming:" << (this->ParallelStreaming?"On":"Off") << endl; + os << "UserManagedInputs:" << (this->UserManagedInputs?"On":"Off") << endl; +} + +//---------------------------------------------------------------------------- +template +size_t vtkAppendPolyDataGetTypeSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +void vtkAppendPolyData::AppendData(vtkDataArray *dest, vtkDataArray *src, + vtkIdType offset) +{ + void *pSrc, *pDest; + vtkIdType length; + + // sanity checks + if (src->GetDataType() != dest->GetDataType()) + { + vtkErrorMacro("Data type mismatch."); + return; + } + if (src->GetNumberOfComponents() != dest->GetNumberOfComponents()) + { + vtkErrorMacro("NumberOfComponents mismatch."); + return; + } + if (src->GetNumberOfTuples() + offset > dest->GetNumberOfTuples()) + { + vtkErrorMacro("Destination not big enough"); + return; + } + + // convert from tuples to components. + offset *= src->GetNumberOfComponents(); + length = src->GetMaxId() + 1; + + switch (src->GetDataType()) + { + vtkTemplateMacro( + length *= vtkAppendPolyDataGetTypeSize(static_cast(0)) + ); + default: + vtkErrorMacro("Unknown data type " << src->GetDataType()); + } + + pSrc = src->GetVoidPointer(0); + pDest = dest->GetVoidPointer(offset); + + memcpy(pDest, pSrc, length); +} + +//---------------------------------------------------------------------------- +void vtkAppendPolyData::AppendDifferentPoints(vtkDataArray *dest, + vtkDataArray *src, + vtkIdType offset) +{ + float *fSrc; + double *dSrc, *dDest; + vtkIdType p; + + if (src->GetNumberOfTuples() + offset > dest->GetNumberOfTuples()) + { + vtkErrorMacro("Destination not big enough"); + return; + } + + vtkIdType vals = src->GetMaxId()+1; + switch (dest->GetDataType()) + { + // + // Dest is FLOAT - if sources are not all same type, dest ought to + // be double. (assuming float and double are the only choices) + // + case VTK_FLOAT: + vtkErrorMacro("Dest type should be double? " + << dest->GetDataType()); + break; + // + // Dest is DOUBLE - sources may be mixed float/double combinations + // + + case VTK_DOUBLE: + dDest = (double*)(dest->GetVoidPointer(offset*src->GetNumberOfComponents())); + // + switch (src->GetDataType()) + { + case VTK_FLOAT: + fSrc = (float*)(src->GetVoidPointer(0)); + for (p=0; pGetVoidPointer(0)); + memcpy(dDest, dSrc, vals*sizeof(double)); + break; + default: + vtkErrorMacro("Unknown data type " << dest->GetDataType()); + } + break; + // + default: + vtkErrorMacro("Unknown data type " << dest->GetDataType()); + } + +} + + +//---------------------------------------------------------------------------- +// returns the next pointer in dest +vtkIdType *vtkAppendPolyData::AppendCells(vtkIdType *pDest, vtkCellArray *src, + vtkIdType offset) +{ + vtkIdType *pSrc, *end, *pNum; + + if (src == NULL) + { + return pDest; + } + + pSrc = (vtkIdType*)(src->GetPointer()); + end = pSrc + src->GetNumberOfConnectivityEntries(); + pNum = pSrc; + + while (pSrc < end) + { + if (pSrc == pNum) + { + // move cell pointer to next cell + pNum += 1+*pSrc; + // copy the number of cells + *pDest++ = *pSrc++; + } + else + { + // offset the point index + *pDest++ = offset + *pSrc++; + } + } + + return pDest; +} + +//---------------------------------------------------------------------------- +int vtkAppendPolyData::FillInputPortInformation(int port, vtkInformation *info) +{ + if (!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return 1; +} diff --git a/Graphics/vtkAppendPolyData.h b/Graphics/vtkAppendPolyData.h new file mode 100644 index 0000000..cca31e3 --- /dev/null +++ b/Graphics/vtkAppendPolyData.h @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAppendPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAppendPolyData - appends one or more polygonal datasets together +// .SECTION Description +// +// vtkAppendPolyData is a filter that appends one of more polygonal datasets +// into a single polygonal dataset. All geometry is extracted and appended, +// but point and cell attributes (i.e., scalars, vectors, normals) are +// extracted and appended only if all datasets have the point and/or cell +// attributes available. (For example, if one dataset has point scalars but +// another does not, point scalars will not be appended.) + +// .SECTION See Also +// vtkAppendFilter + +#ifndef __vtkAppendPolyData_h +#define __vtkAppendPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkDataArray; +class vtkPoints; +class vtkPolyData; + +class VTK_GRAPHICS_EXPORT vtkAppendPolyData : public vtkPolyDataAlgorithm +{ +public: + static vtkAppendPolyData *New(); + + vtkTypeRevisionMacro(vtkAppendPolyData,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // UserManagedInputs allows the user to set inputs by number instead of + // using the AddInput/RemoveInput functions. Calls to + // SetNumberOfInputs/SetInputByNumber should not be mixed with calls + // to AddInput/RemoveInput. By default, UserManagedInputs is false. + vtkSetMacro(UserManagedInputs,int); + vtkGetMacro(UserManagedInputs,int); + vtkBooleanMacro(UserManagedInputs,int); + + // Description: + // Add a dataset to the list of data to append. Should not be + // used when UserManagedInputs is true, use SetInputByNumber instead. + void AddInput(vtkPolyData *); + + // Description: + // Remove a dataset from the list of data to append. Should not be + // used when UserManagedInputs is true, use SetInputByNumber (NULL) instead. + void RemoveInput(vtkPolyData *); + + // Description: + // Get any input of this filter. +//BTX + vtkPolyData *GetInput(int idx); + vtkPolyData *GetInput() { return this->GetInput( 0 ); }; +//ETX + + // Description: + // Directly set(allocate) number of inputs, should only be used + // when UserManagedInputs is true. + void SetNumberOfInputs(int num); + + // Set Nth input, should only be used when UserManagedInputs is true. + void SetInputByNumber(int num, vtkPolyData *input); + + // Description: + // ParallelStreaming is for a particular application. + // It causes this filter to ask for a different piece + // from each of its inputs. If all the inputs are the same, + // then the output of this append filter is the whole dataset + // pieced back together. Duplicate points are create + // along the seams. The purpose of this feature is to get + // data parallelism at a course scale. Each of the inputs + // can be generated in a different process at the same time. + vtkSetMacro(ParallelStreaming, int); + vtkGetMacro(ParallelStreaming, int); + vtkBooleanMacro(ParallelStreaming, int); + +protected: + vtkAppendPolyData(); + ~vtkAppendPolyData(); + + // Flag for selecting parallel streaming behavior + int ParallelStreaming; + + // Usual data generation method + virtual int RequestData(vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int, vtkInformation *); + + // An efficient way to append data/cells. + void AppendData(vtkDataArray *dest, vtkDataArray *src, vtkIdType offset); + void AppendDifferentPoints(vtkDataArray *dest, vtkDataArray *src, + vtkIdType offset); + vtkIdType *AppendCells(vtkIdType *pDest, vtkCellArray *src, + vtkIdType offset); + + private: + // hide the superclass' AddInput() from the user and the compiler + void AddInput(vtkDataObject *) + { vtkErrorMacro( << "AddInput() must be called with a vtkPolyData not a vtkDataObject."); }; + + int UserManagedInputs; + +private: + vtkAppendPolyData(const vtkAppendPolyData&); // Not implemented. + void operator=(const vtkAppendPolyData&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkApproximatingSubdivisionFilter.cxx b/Graphics/vtkApproximatingSubdivisionFilter.cxx new file mode 100644 index 0000000..fc5cd49 --- /dev/null +++ b/Graphics/vtkApproximatingSubdivisionFilter.cxx @@ -0,0 +1,283 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkApproximatingSubdivisionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkApproximatingSubdivisionFilter.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkEdgeTable.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkApproximatingSubdivisionFilter, "$Revision: 1.30 $"); + +// Construct object with number of subdivisions set to 1. +vtkApproximatingSubdivisionFilter::vtkApproximatingSubdivisionFilter() +{ + this->NumberOfSubdivisions = 1; +} + +int vtkApproximatingSubdivisionFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numCells, numPts; + int level; + vtkPoints *outputPts; + + vtkCellArray *outputPolys; + vtkPointData *outputPD; + vtkCellData *outputCD; + vtkIntArray *edgeData; + + vtkDebugMacro(<< "Generating subdivision surface using approximating scheme"); + numPts=input->GetNumberOfPoints(); + numCells=input->GetNumberOfCells(); + + if (numPts < 1 || numCells < 1) + { + vtkErrorMacro(<<"No data to approximate!"); + return 1; + } + + // + // Initialize and check input + // + + vtkPolyData *inputDS = vtkPolyData::New(); + inputDS->CopyStructure (input); + inputDS->GetPointData()->PassData(input->GetPointData()); + inputDS->GetCellData()->PassData(input->GetCellData()); + + int abort=0; + for (level = 0; level < this->NumberOfSubdivisions && !abort; level++) + { + this->UpdateProgress((double)(level+1)/this->NumberOfSubdivisions); + abort = this->GetAbortExecute(); + + // Generate topology for the input dataset + inputDS->BuildLinks(); + + numCells = inputDS->GetNumberOfCells (); + numPts = inputDS->GetNumberOfPoints(); + + // The points for the subdivisions will + // include even points (computed from old points) and + // odd points (inserted on edges) + outputPts = vtkPoints::New(); + outputPts->Allocate (numPts); + + // Copy pointdata structure from input + outputPD = vtkPointData::New(); + outputPD->CopyAllocate(inputDS->GetPointData(),2*inputDS->GetNumberOfPoints()); + + // Copy celldata structure from input + outputCD = vtkCellData::New(); + outputCD->CopyAllocate(inputDS->GetCellData(),4*numCells); + + // Create triangles + outputPolys = vtkCellArray::New(); + outputPolys->Allocate(outputPolys->EstimateSize(4*numCells,3)); + + // Create an array to hold new location indices + edgeData = vtkIntArray::New(); + edgeData->SetNumberOfComponents(3); + edgeData->SetNumberOfTuples(numCells); + + this->GenerateSubdivisionPoints (inputDS, edgeData, outputPts, outputPD); + this->GenerateSubdivisionCells (inputDS, edgeData, outputPolys, outputCD); + + // start the next iteration with the input set to the output we just created + edgeData->Delete(); + inputDS->Delete(); + inputDS = vtkPolyData::New(); + inputDS->SetPoints(outputPts); outputPts->Delete(); + inputDS->SetPolys(outputPolys); outputPolys->Delete(); + inputDS->GetPointData()->PassData(outputPD); outputPD->Delete(); + inputDS->GetCellData()->PassData(outputCD); outputCD->Delete(); + inputDS->Squeeze(); + } // each level + + // Get rid of ghost cells if we have to. + unsigned char* ghostLevels=0; + + vtkCellData* cd = inputDS->GetCellData(); + if (cd) + { + vtkDataArray* temp = cd->GetArray("vtkGhostLevels"); + if (temp) + { + ghostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + } + int updateGhostLevel = output->GetUpdateGhostLevel(); + + output->SetPoints(inputDS->GetPoints()); + output->SetPolys(inputDS->GetPolys()); + output->GetPointData()->PassData(inputDS->GetPointData()); + output->GetCellData()->PassData(inputDS->GetCellData()); + + if (input->GetGhostLevel() > updateGhostLevel && ghostLevels != NULL) + { + output->RemoveGhostCells(updateGhostLevel+1); + } + + inputDS->Delete(); + + return 1; +} + +int vtkApproximatingSubdivisionFilter::FindEdge (vtkPolyData *mesh, + vtkIdType cellId, + vtkIdType p1, vtkIdType p2, + vtkIntArray *edgeData, + vtkIdList *cellIds) +{ + + int edgeId = 0; + vtkIdType currentCellId = 0; + vtkIdType i; + int numEdges; + vtkIdType tp1, tp2; + vtkCell *cell; + + // get all the cells that use the edge (except for cellId) + mesh->GetCellEdgeNeighbors (cellId, p1, p2, cellIds); + + // find the edge that has the point we are looking for + for ( i=0; i < cellIds->GetNumberOfIds(); i++) + { + currentCellId = cellIds->GetId(i); + cell = mesh->GetCell(currentCellId); + numEdges = cell->GetNumberOfEdges(); + tp1 = cell->GetPointId(2); + tp2 = cell->GetPointId(0); + for (edgeId=0; edgeId < numEdges; edgeId++) + { + if ( (tp1 == p1 && tp2 == p2) || + (tp2 == p1 && tp1 == p2)) + { + break; + } + tp1 = tp2; + tp2 = cell->GetPointId(edgeId + 1); + } + } + // found the edge, return the stored value + return (int) edgeData->GetComponent(currentCellId,edgeId); +} + +vtkIdType vtkApproximatingSubdivisionFilter::InterpolatePosition ( + vtkPoints *inputPts, vtkPoints *outputPts, + vtkIdList *stencil, double *weights) +{ + double xx[3], x[3]; + vtkIdType i; + int j; + + for (j = 0; j < 3; j++) + { + x[j] = 0.0; + } + + for (i = 0; i < stencil->GetNumberOfIds(); i++) + { + inputPts->GetPoint(stencil->GetId(i), xx); + for (j = 0; j < 3; j++) + { + x[j] += xx[j] * weights[i]; + } + } + return outputPts->InsertNextPoint (x); +} + + +void vtkApproximatingSubdivisionFilter::GenerateSubdivisionCells ( + vtkPolyData *inputDS, vtkIntArray *edgeData, vtkCellArray *outputPolys, + vtkCellData *outputCD) +{ + vtkIdType numCells = inputDS->GetNumberOfCells(); + vtkIdType cellId, newId, id; + vtkIdType npts; + vtkIdType *pts; + double edgePts[3]; + vtkIdType newCellPts[3]; + vtkCellData *inputCD = inputDS->GetCellData(); + + // Now create new cells from existing points and generated edge points + for (cellId=0; cellId < numCells; cellId++) + { + if ( inputDS->GetCellType(cellId) != VTK_TRIANGLE ) + { + continue; + } + // get the original point ids and the ids stored as edge data + inputDS->GetCellPoints(cellId, npts, pts); + edgeData->GetTuple(cellId, edgePts); + + id = 0; + newCellPts[id++] = pts[0]; + newCellPts[id++] = (int) edgePts[1]; + newCellPts[id++] = (int) edgePts[0]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + + id = 0; + newCellPts[id++] = (int) edgePts[1]; + newCellPts[id++] = pts[1]; + newCellPts[id++] = (int) edgePts[2]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + + id = 0; + newCellPts[id++] = (int) edgePts[2]; + newCellPts[id++] = pts[2]; + newCellPts[id++] = (int) edgePts[0]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + + id = 0; + newCellPts[id++] = (int) edgePts[1]; + newCellPts[id++] = (int) edgePts[2]; + newCellPts[id++] = (int) edgePts[0]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + } +} + +void vtkApproximatingSubdivisionFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of subdivisions: " + << this->NumberOfSubdivisions << endl; +} + + diff --git a/Graphics/vtkApproximatingSubdivisionFilter.h b/Graphics/vtkApproximatingSubdivisionFilter.h new file mode 100644 index 0000000..daa0b3f --- /dev/null +++ b/Graphics/vtkApproximatingSubdivisionFilter.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkApproximatingSubdivisionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkApproximatingSubdivisionFilter - generate a subdivision surface using an Approximating Scheme +// .SECTION Description +// vtkApproximatingSubdivisionFilter is an abstract class that defines +// the protocol for Approximating subdivision surface filters. + +// .SECTION Thanks +// This work was supported by PHS Research Grant No. 1 P41 RR13218-01 +// from the National Center for Research Resources. + +#ifndef __vtkApproximatingSubdivisionFilter_h +#define __vtkApproximatingSubdivisionFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkCellData; +class vtkIdList; +class vtkIntArray; +class vtkPoints; +class vtkPointData; + +class VTK_GRAPHICS_EXPORT vtkApproximatingSubdivisionFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkApproximatingSubdivisionFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/get the number of subdivisions. + vtkSetMacro(NumberOfSubdivisions,int); + vtkGetMacro(NumberOfSubdivisions,int); + +protected: + vtkApproximatingSubdivisionFilter(); + ~vtkApproximatingSubdivisionFilter() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual void GenerateSubdivisionPoints (vtkPolyData *inputDS, + vtkIntArray *edgeData, + vtkPoints *outputPts, + vtkPointData *outputPD) = 0; + void GenerateSubdivisionCells (vtkPolyData *inputDS, vtkIntArray *edgeData, + vtkCellArray *outputPolys, + vtkCellData *outputCD); + int FindEdge (vtkPolyData *mesh, vtkIdType cellId, vtkIdType p1, + vtkIdType p2, vtkIntArray *edgeData, vtkIdList *cellIds); + vtkIdType InterpolatePosition (vtkPoints *inputPts, vtkPoints *outputPts, + vtkIdList *stencil, double *weights); + int NumberOfSubdivisions; +private: + vtkApproximatingSubdivisionFilter(const vtkApproximatingSubdivisionFilter&); // Not implemented. + void operator=(const vtkApproximatingSubdivisionFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkArrayCalculator.cxx b/Graphics/vtkArrayCalculator.cxx new file mode 100644 index 0000000..e1c273e --- /dev/null +++ b/Graphics/vtkArrayCalculator.cxx @@ -0,0 +1,820 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkArrayCalculator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkArrayCalculator.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkFieldData.h" +#include "vtkFunctionParser.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkArrayCalculator, "$Revision: 1.31 $"); +vtkStandardNewMacro(vtkArrayCalculator); + +vtkArrayCalculator::vtkArrayCalculator() +{ + this->FunctionParser = vtkFunctionParser::New(); + + this->Function = NULL; + this->ResultArrayName = NULL; + this->SetResultArrayName("resultArray"); + this->ScalarArrayNames = NULL; + this->VectorArrayNames = NULL; + this->ScalarVariableNames = NULL; + this->VectorVariableNames = NULL; + this->NumberOfScalarArrays = 0; + this->NumberOfVectorArrays = 0; + this->AttributeMode = VTK_ATTRIBUTE_MODE_DEFAULT; + this->SelectedScalarComponents = NULL; + this->SelectedVectorComponents = NULL; + + this->ReplaceInvalidValues = 0; + this->ReplacementValue = 0.0; +} + +vtkArrayCalculator::~vtkArrayCalculator() +{ + int i; + + this->FunctionParser->Delete(); + this->FunctionParser = NULL; + + if (this->Function) + { + delete [] this->Function; + this->Function = NULL; + } + + if (this->ResultArrayName) + { + delete [] this->ResultArrayName; + this->ResultArrayName = NULL; + } + + if (this->ScalarArrayNames) + { + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + delete [] this->ScalarArrayNames[i]; + this->ScalarArrayNames[i] = NULL; + } + delete [] this->ScalarArrayNames; + this->ScalarArrayNames = NULL; + } + + if (this->VectorArrayNames) + { + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + delete [] this->VectorArrayNames[i]; + this->VectorArrayNames[i] = NULL; + } + delete [] this->VectorArrayNames; + this->VectorArrayNames = NULL; + } + + if (this->ScalarVariableNames) + { + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + delete [] this->ScalarVariableNames[i]; + this->ScalarVariableNames[i] = NULL; + } + delete [] this->ScalarVariableNames; + this->ScalarVariableNames = NULL; + } + + if (this->VectorVariableNames) + { + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + delete [] this->VectorVariableNames[i]; + this->VectorVariableNames[i] = NULL; + } + delete [] this->VectorVariableNames; + this->VectorVariableNames = NULL; + } + + if (this->SelectedScalarComponents) + { + delete [] this->SelectedScalarComponents; + this->SelectedScalarComponents = NULL; + } + + if (this->SelectedVectorComponents) + { + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + delete [] this->SelectedVectorComponents[i]; + this->SelectedVectorComponents[i] = NULL; + } + delete [] this->SelectedVectorComponents; + this->SelectedVectorComponents = NULL; + } +} + +void vtkArrayCalculator::SetResultArrayName(const char* name) +{ + if (name == NULL || *name == '\0') + { + vtkErrorMacro("The result array must have a name."); + return; + } + if (this->ResultArrayName != NULL && strcmp(this->ResultArrayName, name) == 0) + { + return; + } + this->Modified(); + if (this->ResultArrayName) + { + delete [] this->ResultArrayName; + this->ResultArrayName = NULL; + } + this->ResultArrayName = new char [strlen(name)+1]; + strcpy(this->ResultArrayName, name); +} + +int vtkArrayCalculator::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int resultType; // 0 for scalar, 1 for vector + int attributeDataType; // 0 for point data, 1 for cell data + vtkIdType i; + int j; + + vtkPointData* inPD = input->GetPointData(); + vtkCellData* inCD = input->GetCellData(); + vtkFieldData* inFD; + vtkDataArray* currentArray; + vtkDoubleArray* resultArray; + vtkIdType numTuples; + double scalarResult[1]; + + this->FunctionParser->SetReplaceInvalidValues(this->ReplaceInvalidValues); + this->FunctionParser->SetReplacementValue(this->ReplacementValue); + + if (this->AttributeMode == VTK_ATTRIBUTE_MODE_DEFAULT) + { + inFD = inPD; + attributeDataType = 0; + numTuples = input->GetNumberOfPoints(); + } + else if (this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_POINT_DATA) + { + inFD = inPD; + attributeDataType = 0; + numTuples = input->GetNumberOfPoints(); + } + else + { + inFD = inCD; + attributeDataType = 1; + numTuples = input->GetNumberOfCells(); + } + + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + currentArray = inFD->GetArray(this->ScalarArrayNames[i]); + if (currentArray) + { + if (currentArray->GetNumberOfComponents() > + this->SelectedScalarComponents[i]) + { + this->FunctionParser-> + SetScalarVariableValue(this->ScalarVariableNames[i], + currentArray->GetComponent(0, this->SelectedScalarComponents[i])); + } + else + { + vtkErrorMacro("Array " << this->ScalarArrayNames[i] + << " does not contain the selected component."); + return 1; + } + } + else + { + vtkErrorMacro("Invalid array name: " << this->ScalarArrayNames[i]); + return 1; + } + } + + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + currentArray = inFD->GetArray(this->VectorArrayNames[i]); + if (currentArray) + { + if ((currentArray->GetNumberOfComponents() > + this->SelectedVectorComponents[i][0]) && + (currentArray->GetNumberOfComponents() > + this->SelectedVectorComponents[i][1]) && + (currentArray->GetNumberOfComponents() > + this->SelectedVectorComponents[i][2])) + { + this->FunctionParser-> + SetVectorVariableValue(this->VectorVariableNames[i], + currentArray->GetComponent(0, this->SelectedVectorComponents[i][0]), + currentArray->GetComponent(0, this->SelectedVectorComponents[i][1]), + currentArray->GetComponent(0, this->SelectedVectorComponents[i][2])); + } + else + { + vtkErrorMacro("Array " << this->VectorArrayNames[i] + << " does not contain one of the selected components."); + return 1; + } + } + else + { + vtkErrorMacro("Invalid array name: " << this->VectorArrayNames[i]); + return 1; + } + } + + if (this->FunctionParser->IsScalarResult()) + { + resultType = 0; + } + else if (this->FunctionParser->IsVectorResult()) + { + resultType = 1; + } + else + { + // Error occurred in vtkFunctionParser. + return 1; + } + + resultArray = vtkDoubleArray::New(); + if (resultType == 0) + { + resultArray->SetNumberOfComponents(1); + resultArray->SetNumberOfTuples(numTuples); + scalarResult[0] = this->FunctionParser->GetScalarResult(); + resultArray->SetTuple(0, scalarResult); + } + else + { + resultArray->Allocate(numTuples * 3); + resultArray->SetNumberOfComponents(3); + resultArray->SetNumberOfTuples(numTuples); + resultArray->SetTuple(0, this->FunctionParser->GetVectorResult()); + } + + for (i = 1; i < numTuples; i++) + { + for (j = 0; j < this->NumberOfScalarArrays; j++) + { + currentArray = inFD->GetArray(this->ScalarArrayNames[j]); + this->FunctionParser-> + SetScalarVariableValue(j, currentArray->GetComponent(i, this->SelectedScalarComponents[j])); + } + for (j = 0; j < this->NumberOfVectorArrays; j++) + { + currentArray = inFD->GetArray(this->VectorArrayNames[j]); + this->FunctionParser-> + SetVectorVariableValue(j, currentArray->GetComponent(i, this->SelectedVectorComponents[j][0]), + currentArray->GetComponent(i, this->SelectedVectorComponents[j][1]), + currentArray->GetComponent(i, this->SelectedVectorComponents[j][2])); + } + if (resultType == 0) + { + scalarResult[0] = this->FunctionParser->GetScalarResult(); + resultArray->SetTuple(i, scalarResult); + } + else + { + resultArray->SetTuple(i, this->FunctionParser->GetVectorResult()); + } + } + + output->CopyStructure(input); + output->GetPointData()->PassData(inPD); + output->GetCellData()->PassData(inCD); + + resultArray->SetName(this->ResultArrayName); + if (attributeDataType == 0) + { + output->GetPointData()->AddArray(resultArray); + if (resultType == 0) + { + output->GetPointData()->SetActiveScalars(this->ResultArrayName); + } + else + { + output->GetPointData()->SetActiveVectors(this->ResultArrayName); + } + } + else + { + output->GetCellData()->AddArray(resultArray); + if (resultType == 0) + { + output->GetCellData()->SetActiveScalars(this->ResultArrayName); + } + else + { + output->GetCellData()->SetActiveVectors(this->ResultArrayName); + } + } + + resultArray->Delete(); + + return 1; +} + +void vtkArrayCalculator::SetFunction(const char* function) +{ + if (this->Function && function && + strcmp(this->Function, function) == 0) + { + return; + } + + this->Modified(); + + if (this->Function) + { + delete [] this->Function; + this->Function = NULL; + } + + if (function) + { + this->Function = new char[strlen(function)+1]; + strcpy(this->Function, function); + this->FunctionParser->SetFunction(this->Function); + } +} + +void vtkArrayCalculator::AddScalarArrayName(const char* arrayName, + int component) +{ + if (!arrayName) + { + return; + } + + int i; + char** arrayNames = new char *[this->NumberOfScalarArrays]; + char** varNames = new char *[this->NumberOfScalarArrays]; + int* tempComponents = new int[this->NumberOfScalarArrays]; + + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + arrayNames[i] = new char[strlen(this->ScalarArrayNames[i]) + 1]; + strcpy(arrayNames[i], this->ScalarArrayNames[i]); + delete [] this->ScalarArrayNames[i]; + this->ScalarArrayNames[i] = NULL; + varNames[i] = new char[strlen(this->ScalarArrayNames[i]) + 1]; + strcpy(varNames[i], this->ScalarVariableNames[i]); + delete [] this->ScalarVariableNames[i]; + this->ScalarVariableNames[i] = NULL; + tempComponents[i] = this->SelectedScalarComponents[i]; + } + if (this->ScalarArrayNames) + { + delete [] this->ScalarArrayNames; + this->ScalarArrayNames = NULL; + } + if (this->ScalarVariableNames) + { + delete [] this->ScalarVariableNames; + this->ScalarVariableNames = NULL; + } + if (this->SelectedScalarComponents) + { + delete [] this->SelectedScalarComponents; + this->SelectedScalarComponents = NULL; + } + + this->ScalarArrayNames = new char *[this->NumberOfScalarArrays + 1]; + this->ScalarVariableNames = new char *[this->NumberOfScalarArrays + 1]; + this->SelectedScalarComponents = new int[this->NumberOfScalarArrays + 1]; + + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + this->ScalarArrayNames[i] = new char[strlen(arrayNames[i]) + 1]; + strcpy(this->ScalarArrayNames[i], arrayNames[i]); + delete [] arrayNames[i]; + arrayNames[i] = NULL; + this->ScalarVariableNames[i] = new char[strlen(varNames[i]) + 1]; + strcpy(this->ScalarVariableNames[i], varNames[i]); + delete [] varNames[i]; + varNames[i] = NULL; + this->SelectedScalarComponents[i] = tempComponents[i]; + } + delete [] arrayNames; + delete [] varNames; + delete [] tempComponents; + + this->ScalarArrayNames[i] = new char[strlen(arrayName) + 1]; + strcpy(this->ScalarArrayNames[i], arrayName); + this->ScalarVariableNames[i] = new char[strlen(arrayName) + 1]; + strcpy(this->ScalarVariableNames[i], arrayName); + this->SelectedScalarComponents[i] = component; + + this->NumberOfScalarArrays++; +} + +void vtkArrayCalculator::AddVectorArrayName(const char* arrayName, + int component0, int component1, + int component2) +{ + if (!arrayName) + { + return; + } + + int i; + char** arrayNames = new char *[this->NumberOfVectorArrays]; + char** varNames = new char *[this->NumberOfVectorArrays]; + int** tempComponents = new int *[this->NumberOfVectorArrays]; + + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + arrayNames[i] = new char[strlen(this->VectorArrayNames[i]) + 1]; + strcpy(arrayNames[i], this->VectorArrayNames[i]); + delete [] this->VectorArrayNames[i]; + this->VectorArrayNames[i] = NULL; + varNames[i] = new char[strlen(this->VectorVariableNames[i]) + 1]; + strcpy(varNames[i], this->VectorVariableNames[i]); + delete [] this->VectorVariableNames[i]; + this->VectorVariableNames[i] = NULL; + tempComponents[i] = new int[3]; + tempComponents[i][0] = this->SelectedVectorComponents[i][0]; + tempComponents[i][1] = this->SelectedVectorComponents[i][1]; + tempComponents[i][2] = this->SelectedVectorComponents[i][2]; + delete [] this->SelectedVectorComponents[i]; + this->SelectedVectorComponents[i] = NULL; + } + + if (this->VectorArrayNames) + { + delete [] this->VectorArrayNames; + this->VectorArrayNames = NULL; + } + if (this->VectorVariableNames) + { + delete [] this->VectorVariableNames; + this->VectorVariableNames = NULL; + } + if (this->SelectedVectorComponents) + { + delete [] this->SelectedVectorComponents; + this->SelectedVectorComponents = NULL; + } + + this->VectorArrayNames = new char *[this->NumberOfVectorArrays + 1]; + this->VectorVariableNames = new char *[this->NumberOfVectorArrays + 1]; + this->SelectedVectorComponents = new int *[this->NumberOfVectorArrays + 1]; + + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + this->VectorArrayNames[i] = new char[strlen(arrayNames[i]) + 1]; + strcpy(this->VectorArrayNames[i], arrayNames[i]); + delete [] arrayNames[i]; + arrayNames[i] = NULL; + this->VectorVariableNames[i] = new char[strlen(varNames[i]) + 1]; + strcpy(this->VectorVariableNames[i], varNames[i]); + delete [] varNames[i]; + varNames[i] = NULL; + this->SelectedVectorComponents[i] = new int[3]; + this->SelectedVectorComponents[i][0] = component0; + this->SelectedVectorComponents[i][1] = component1; + this->SelectedVectorComponents[i][2] = component2; + delete [] tempComponents[i]; + tempComponents[i] = NULL; + } + delete [] arrayNames; + delete [] varNames; + delete [] tempComponents; + + this->VectorArrayNames[i] = new char[strlen(arrayName) + 1]; + strcpy(this->VectorArrayNames[i], arrayName); + this->VectorVariableNames[i] = new char[strlen(arrayName) + 1]; + strcpy(this->VectorVariableNames[i], arrayName); + this->SelectedVectorComponents[i] = new int[3]; + this->SelectedVectorComponents[i][0] = component0; + this->SelectedVectorComponents[i][1] = component1; + this->SelectedVectorComponents[i][2] = component2; + + this->NumberOfVectorArrays++; +} + +void vtkArrayCalculator::AddScalarVariable(const char* variableName, + const char* arrayName, + int component) +{ + if (!arrayName) + { + return; + } + + int i; + char** arrayNames = new char *[this->NumberOfScalarArrays]; + char** varNames = new char *[this->NumberOfScalarArrays]; + int* tempComponents = new int[this->NumberOfScalarArrays]; + + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + arrayNames[i] = new char[strlen(this->ScalarArrayNames[i]) + 1]; + strcpy(arrayNames[i], this->ScalarArrayNames[i]); + delete [] this->ScalarArrayNames[i]; + this->ScalarArrayNames[i] = NULL; + varNames[i] = new char[strlen(this->ScalarVariableNames[i]) + 1]; + strcpy(varNames[i], this->ScalarVariableNames[i]); + delete [] this->ScalarVariableNames[i]; + this->ScalarVariableNames[i] = NULL; + tempComponents[i] = this->SelectedScalarComponents[i]; + } + if (this->ScalarArrayNames) + { + delete [] this->ScalarArrayNames; + this->ScalarArrayNames = NULL; + } + if (this->ScalarVariableNames) + { + delete [] this->ScalarVariableNames; + this->ScalarVariableNames = NULL; + } + if (this->SelectedScalarComponents) + { + delete [] this->SelectedScalarComponents; + this->SelectedScalarComponents = NULL; + } + + this->ScalarArrayNames = new char *[this->NumberOfScalarArrays + 1]; + this->ScalarVariableNames = new char *[this->NumberOfScalarArrays + 1]; + this->SelectedScalarComponents = new int[this->NumberOfScalarArrays + 1]; + + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + this->ScalarArrayNames[i] = new char[strlen(arrayNames[i]) + 1]; + strcpy(this->ScalarArrayNames[i], arrayNames[i]); + delete [] arrayNames[i]; + arrayNames[i] = NULL; + this->ScalarVariableNames[i] = new char[strlen(varNames[i]) + 1]; + strcpy(this->ScalarVariableNames[i], varNames[i]); + delete [] varNames[i]; + varNames[i] = NULL; + this->SelectedScalarComponents[i] = tempComponents[i]; + } + delete [] arrayNames; + delete [] varNames; + delete [] tempComponents; + + this->ScalarArrayNames[i] = new char[strlen(arrayName) + 1]; + strcpy(this->ScalarArrayNames[i], arrayName); + this->ScalarVariableNames[i] = new char[strlen(variableName) + 1]; + strcpy(this->ScalarVariableNames[i], variableName); + this->SelectedScalarComponents[i] = component; + + this->NumberOfScalarArrays++; +} + +void vtkArrayCalculator::AddVectorVariable(const char* variableName, + const char* arrayName, + int component0, int component1, + int component2) +{ + if (!arrayName) + { + return; + } + + int i; + char** arrayNames = new char *[this->NumberOfVectorArrays]; + char** varNames = new char *[this->NumberOfVectorArrays]; + int** tempComponents = new int *[this->NumberOfVectorArrays]; + + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + arrayNames[i] = new char[strlen(this->VectorArrayNames[i]) + 1]; + strcpy(arrayNames[i], this->VectorArrayNames[i]); + delete [] this->VectorArrayNames[i]; + this->VectorArrayNames[i] = NULL; + varNames[i] = new char[strlen(this->VectorVariableNames[i]) + 1]; + strcpy(varNames[i], this->VectorVariableNames[i]); + delete [] this->VectorVariableNames[i]; + this->VectorVariableNames[i] = NULL; + tempComponents[i] = new int[3]; + tempComponents[i][0] = this->SelectedVectorComponents[i][0]; + tempComponents[i][1] = this->SelectedVectorComponents[i][1]; + tempComponents[i][2] = this->SelectedVectorComponents[i][2]; + delete [] this->SelectedVectorComponents[i]; + this->SelectedVectorComponents[i] = NULL; + } + + if (this->VectorArrayNames) + { + delete [] this->VectorArrayNames; + this->VectorArrayNames = NULL; + } + if (this->VectorVariableNames) + { + delete [] this->VectorVariableNames; + this->VectorVariableNames = NULL; + } + if (this->SelectedVectorComponents) + { + delete [] this->SelectedVectorComponents; + this->SelectedVectorComponents = NULL; + } + + this->VectorArrayNames = new char *[this->NumberOfVectorArrays + 1]; + this->VectorVariableNames = new char *[this->NumberOfVectorArrays + 1]; + this->SelectedVectorComponents = new int *[this->NumberOfVectorArrays + 1]; + + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + this->VectorArrayNames[i] = new char[strlen(arrayNames[i]) + 1]; + strcpy(this->VectorArrayNames[i], arrayNames[i]); + delete [] arrayNames[i]; + arrayNames[i] = NULL; + this->VectorVariableNames[i] = new char[strlen(varNames[i]) + 1]; + strcpy(this->VectorVariableNames[i], varNames[i]); + delete [] varNames[i]; + varNames[i] = NULL; + this->SelectedVectorComponents[i] = new int[3]; + this->SelectedVectorComponents[i][0] = tempComponents[i][0]; + this->SelectedVectorComponents[i][1] = tempComponents[i][1]; + this->SelectedVectorComponents[i][2] = tempComponents[i][2]; + delete [] tempComponents[i]; + tempComponents[i] = NULL; + } + delete [] arrayNames; + delete [] varNames; + delete [] tempComponents; + + this->VectorArrayNames[i] = new char[strlen(arrayName) + 1]; + strcpy(this->VectorArrayNames[i], arrayName); + this->VectorVariableNames[i] = new char[strlen(variableName) + 1]; + strcpy(this->VectorVariableNames[i], variableName); + this->SelectedVectorComponents[i] = new int[3]; + this->SelectedVectorComponents[i][0] = component0; + this->SelectedVectorComponents[i][1] = component1; + this->SelectedVectorComponents[i][2] = component2; + + this->NumberOfVectorArrays++; +} + +const char* vtkArrayCalculator::GetAttributeModeAsString() +{ + if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_DEFAULT ) + { + return "Default"; + } + else if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else + { + return "UseCellData"; + } +} + +void vtkArrayCalculator::RemoveAllVariables() +{ + int i; + + for (i = 0; i < this->NumberOfScalarArrays; i++) + { + delete [] this->ScalarArrayNames[i]; + this->ScalarArrayNames[i] = NULL; + delete [] this->ScalarVariableNames[i]; + this->ScalarVariableNames[i] = NULL; + } + if (this->NumberOfScalarArrays > 0) + { + delete [] this->ScalarArrayNames; + this->ScalarArrayNames = NULL; + delete [] this->ScalarVariableNames; + this->ScalarVariableNames = NULL; + delete [] this->SelectedScalarComponents; + this->SelectedScalarComponents = NULL; + } + this->NumberOfScalarArrays = 0; + + for (i = 0; i < this->NumberOfVectorArrays; i++) + { + delete [] this->VectorArrayNames[i]; + this->VectorArrayNames[i] = NULL; + delete [] this->VectorVariableNames[i]; + this->VectorVariableNames[i] = NULL; + delete [] this->SelectedVectorComponents[i]; + this->SelectedVectorComponents[i] = NULL; + } + if (this->NumberOfVectorArrays > 0) + { + delete [] this->VectorArrayNames; + this->VectorArrayNames = NULL; + delete [] this->VectorVariableNames; + this->VectorVariableNames = NULL; + delete [] this->SelectedVectorComponents; + this->SelectedVectorComponents = NULL; + } + this->NumberOfVectorArrays = 0; + + this->FunctionParser->RemoveAllVariables(); +} + +char* vtkArrayCalculator::GetScalarArrayName(int i) +{ + if (i < this->NumberOfScalarArrays) + { + return this->ScalarArrayNames[i]; + } + return NULL; +} + +char* vtkArrayCalculator::GetVectorArrayName(int i) +{ + if (i < this->NumberOfVectorArrays) + { + return this->VectorArrayNames[i]; + } + return NULL; +} + +char* vtkArrayCalculator::GetScalarVariableName(int i) +{ + if (i < this->NumberOfScalarArrays) + { + return this->ScalarVariableNames[i]; + } + return NULL; +} + +char* vtkArrayCalculator::GetVectorVariableName(int i) +{ + if (i < this->NumberOfVectorArrays) + { + return this->VectorVariableNames[i]; + } + return NULL; +} + +int vtkArrayCalculator::GetSelectedScalarComponent(int i) +{ + if (i < this->NumberOfScalarArrays) + { + return this->SelectedScalarComponents[i]; + } + return -1; +} + +int* vtkArrayCalculator::GetSelectedVectorComponents(int i) +{ + if (i < this->NumberOfVectorArrays) + { + return this->SelectedVectorComponents[i]; + } + return NULL; +} + +void vtkArrayCalculator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Function: " + << (this->Function ? this->Function : "(none)") << endl; + os << indent << "Result Array Name: " + << (this->ResultArrayName ? this->ResultArrayName : "(none)") << endl; + os << indent << "Attribute Mode: " << this->GetAttributeModeAsString() << endl; + os << indent << "Number Of Scalar Arrays: " << this->NumberOfScalarArrays + << endl; + os << indent << "Number Of Vector Arrays: " << this->NumberOfVectorArrays + << endl; + os << indent << "Replace Invalid Values: " + << (this->ReplaceInvalidValues ? "On" : "Off") << endl; + os << indent << "Replacement Value: " << this->ReplacementValue << endl; +} diff --git a/Graphics/vtkArrayCalculator.h b/Graphics/vtkArrayCalculator.h new file mode 100644 index 0000000..53dc0ab --- /dev/null +++ b/Graphics/vtkArrayCalculator.h @@ -0,0 +1,182 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkArrayCalculator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkArrayCalculator - perform mathematical operations on data in field data arrays +// .SECTION Description +// vtkArrayCalculator performs operations on vectors or scalars in field +// data arrays. It uses vtkFunctionParser to do the parsing and to +// evaluate the function for each entry in the input arrays. The arrays +// used in a given function must be all in point data or all in cell data. +// The resulting array will be stored as a field data array. The result +// array can either be stored in a new array or it can overwrite an existing +// array. +// +// The functions that this array calculator understands is: +//
+// standard operations: + - * / ^ .
+// access vector components: iHat, jHat, kHat
+// abs
+// acos
+// asin
+// atan
+// ceil
+// cos
+// cosh
+// exp
+// floor
+// log
+// mag
+// min
+// max
+// norm
+// sign
+// sin
+// sinh
+// sqrt
+// tan
+// tanh
+// 
+// Note that some of these operations work on scalars, some on vectors, and some on +// both (e.g., you can multiply a scalar times a vector). The operations are performed +// tuple-wise (i.e., tuple-by-tuple). The user must specify which arrays to use as +// vectors and/or scalars, and the name of the output data array. +// +// .SECTION See Also +// vtkFunctionParser + +#ifndef __vtkArrayCalculator_h +#define __vtkArrayCalculator_h + +#include "vtkDataSetAlgorithm.h" + +class vtkFunctionParser; + +#define VTK_ATTRIBUTE_MODE_DEFAULT 0 +#define VTK_ATTRIBUTE_MODE_USE_POINT_DATA 1 +#define VTK_ATTRIBUTE_MODE_USE_CELL_DATA 2 + +class VTK_GRAPHICS_EXPORT vtkArrayCalculator : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkArrayCalculator,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkArrayCalculator *New(); + + // Description: + // Set/Get the function to be evaluated. + void SetFunction(const char* function); + vtkGetStringMacro(Function); + + // Description: + // Add an array name to the list of arrays used in the function and specify + // which components of the array to use in evaluating the function. The + // array name must match the name in the function. Use AddScalarVariable or + // AddVectorVariable to use a variable name different from the array name. + void AddScalarArrayName(const char* arrayName, int component = 0); + void AddVectorArrayName(const char* arrayName, int component0 = 0, + int component1 = 1, int component2 = 2); + + // Description: + // Add a variable name, a corresponding array name, and which components of + // the array to use. + void AddScalarVariable(const char* variableName, const char* arrayName, + int component = 0); + void AddVectorVariable(const char* variableName, const char* arrayName, + int component0 = 0, int component1 = 1, + int component2 = 2); + + // Description: + // Set the name of the array in which to store the result of + // evaluating this function. If this is the name of an existing array, + // that array will be overwritten. Otherwise a new array will be + // created with the specified name. + void SetResultArrayName(const char* name); + vtkGetStringMacro(ResultArrayName); + + // Description: + // Control whether the filter operates on point data or cell data. + // By default (AttributeModeToDefault), the filter uses point + // data. Alternatively you can explicitly set the filter to use point data + // (AttributeModeToUsePointData) or cell data (AttributeModeToUseCellData). + vtkSetMacro(AttributeMode,int); + vtkGetMacro(AttributeMode,int); + void SetAttributeModeToDefault() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_DEFAULT);}; + void SetAttributeModeToUsePointData() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_POINT_DATA);}; + void SetAttributeModeToUseCellData() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_CELL_DATA);}; + const char *GetAttributeModeAsString(); + + // Description: + // Remove all the variable names and their associated array names. + void RemoveAllVariables(); + + // Description: + // Methods to get information about the current variables. + char** GetScalarArrayNames() { return this->ScalarArrayNames; } + char* GetScalarArrayName(int i); + char** GetVectorArrayNames() { return this->VectorArrayNames; } + char* GetVectorArrayName(int i); + char** GetScalarVariableNames() { return this->ScalarVariableNames; } + char* GetScalarVariableName(int i); + char** GetVectorVariableNames() { return this->VectorVariableNames; } + char* GetVectorVariableName(int i); + int* GetSelectedScalarComponents() { return this->SelectedScalarComponents; } + int GetSelectedScalarComponent(int i); + int** GetSelectedVectorComponents() { return this->SelectedVectorComponents;} + int* GetSelectedVectorComponents(int i); + vtkGetMacro(NumberOfScalarArrays, int); + vtkGetMacro(NumberOfVectorArrays, int); + + // Description: + // When ReplaceInvalidValues is on, all invalid values (such as + // sqrt(-2), note that function parser does not handle complex + // numbers) will be replaced by ReplacementValue. Otherwise an + // error will be reported + vtkSetMacro(ReplaceInvalidValues,int); + vtkGetMacro(ReplaceInvalidValues,int); + vtkBooleanMacro(ReplaceInvalidValues,int); + vtkSetMacro(ReplacementValue,double); + vtkGetMacro(ReplacementValue,double); + +protected: + vtkArrayCalculator(); + ~vtkArrayCalculator(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char* Function; + char* ResultArrayName; + char** ScalarArrayNames; + char** VectorArrayNames; + char** ScalarVariableNames; + char** VectorVariableNames; + int NumberOfScalarArrays; + int NumberOfVectorArrays; + int AttributeMode; + int* SelectedScalarComponents; + int** SelectedVectorComponents; + vtkFunctionParser* FunctionParser; + + int ReplaceInvalidValues; + double ReplacementValue; + +private: + vtkArrayCalculator(const vtkArrayCalculator&); // Not implemented. + void operator=(const vtkArrayCalculator&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkArrowSource.cxx b/Graphics/vtkArrowSource.cxx new file mode 100644 index 0000000..8ea2b94 --- /dev/null +++ b/Graphics/vtkArrowSource.cxx @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkArrowSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkArrowSource.h" + +#include "vtkAppendPolyData.h" +#include "vtkConeSource.h" +#include "vtkCylinderSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" +#include "vtkTransformFilter.h" + +vtkCxxRevisionMacro(vtkArrowSource, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkArrowSource); + +vtkArrowSource::vtkArrowSource() +{ + this->TipResolution = 6; + this->TipRadius = 0.1; + this->TipLength = 0.35; + this->ShaftResolution = 6; + this->ShaftRadius = 0.03; + + this->SetNumberOfInputPorts(0); +} + +int vtkArrowSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int piece, numPieces, ghostLevel; + vtkCylinderSource *cyl = vtkCylinderSource::New(); + vtkTransform *trans0 = vtkTransform::New(); + vtkTransformFilter *tf0 = vtkTransformFilter::New(); + vtkConeSource *cone = vtkConeSource::New(); + vtkTransform *trans1 = vtkTransform::New(); + vtkTransformFilter *tf1 = vtkTransformFilter::New(); + vtkAppendPolyData *append = vtkAppendPolyData::New(); + + piece = output->GetUpdatePiece(); + numPieces = output->GetUpdateNumberOfPieces(); + ghostLevel = output->GetUpdateGhostLevel(); + + cyl->SetResolution(this->ShaftResolution); + cyl->SetRadius(this->ShaftRadius); + cyl->SetHeight(1.0 - this->TipLength); + cyl->SetCenter(0, (1.0-this->TipLength)*0.5, 0.0); + cyl->CappingOn(); + + trans0->RotateZ(-90.0); + tf0->SetTransform(trans0); + tf0->SetInput(cyl->GetOutput()); + + cone->SetResolution(this->TipResolution); + cone->SetHeight(this->TipLength); + cone->SetRadius(this->TipRadius); + + trans1->Translate(1.0-this->TipLength*0.5, 0.0, 0.0); + tf1->SetTransform(trans1); + tf1->SetInput(cone->GetOutput()); + + append->AddInput(tf0->GetPolyDataOutput()); + append->AddInput(tf1->GetPolyDataOutput()); + + if (output->GetUpdatePiece() == 0 && numPieces > 0) + { + append->Update(); + output->ShallowCopy(append->GetOutput()); + } + output->SetUpdatePiece(piece); + output->SetUpdateNumberOfPieces(numPieces); + output->SetUpdateGhostLevel(ghostLevel); + + cone->Delete(); + trans0->Delete(); + tf0->Delete(); + cyl->Delete(); + trans1->Delete(); + tf1->Delete(); + append->Delete(); + + return 1; +} + +void vtkArrowSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "TipResolution: " << this->TipResolution << "\n"; + os << indent << "TipRadius: " << this->TipRadius << "\n"; + os << indent << "TipLength: " << this->TipLength << "\n"; + + os << indent << "ShaftResolution: " << this->ShaftResolution << "\n"; + os << indent << "ShaftRadius: " << this->ShaftRadius << "\n"; +} diff --git a/Graphics/vtkArrowSource.h b/Graphics/vtkArrowSource.h new file mode 100644 index 0000000..c05004f --- /dev/null +++ b/Graphics/vtkArrowSource.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkArrowSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkArrowSource - Appends a cylinder to a cone to form an arrow. +// .SECTION Description +// vtkArrowSource was intended to be used as the source for a glyph. +// The shaft base is always at (0,0,0). The arrow tip is always at (1,0,0). +// The resolution of the cone and shaft can be set and default to 6. +// The radius of the cone and shaft can be set and default to 0.03 and 0.1. +// The length of the tip can also be set, and defaults to 0.35. + + +#ifndef __vtkArrowSource_h +#define __vtkArrowSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkArrowSource : public vtkPolyDataAlgorithm +{ +public: + // Description + // Construct cone with angle of 45 degrees. + static vtkArrowSource *New(); + + vtkTypeRevisionMacro(vtkArrowSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the length, and radius of the tip. They default to 0.35 and 0.1 + vtkSetClampMacro(TipLength,double,0.0,1.0); + vtkGetMacro(TipLength,double); + vtkSetClampMacro(TipRadius,double,0.0,10.0); + vtkGetMacro(TipRadius,double); + + // Description: + // Set the resolution of the tip. The tip behaves the same as a cone. + // Resoultion 1 gives a single triangle, 2 gives two crossed triangles. + vtkSetClampMacro(TipResolution,int,1,128); + vtkGetMacro(TipResolution,int); + + // Description: + // Set the radius of the shaft. Defaults to 0.03. + vtkSetClampMacro(ShaftRadius,double,0.0,5.0); + vtkGetMacro(ShaftRadius,double); + + // Description: + // Set the resolution of the shaft. 2 gives a rectangle. + // I would like to extend the cone to produce a line, + // but this is not an option now. + vtkSetClampMacro(ShaftResolution,int,0,128); + vtkGetMacro(ShaftResolution,int); + +protected: + vtkArrowSource(); + ~vtkArrowSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int TipResolution; + double TipLength; + double TipRadius; + + int ShaftResolution; + double ShaftRadius; + +private: + vtkArrowSource(const vtkArrowSource&); // Not implemented. + void operator=(const vtkArrowSource&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkAssignAttribute.cxx b/Graphics/vtkAssignAttribute.cxx new file mode 100644 index 0000000..4bd50be --- /dev/null +++ b/Graphics/vtkAssignAttribute.cxx @@ -0,0 +1,292 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssignAttribute.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAssignAttribute.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDataSetAttributes.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkAssignAttribute, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkAssignAttribute); + +char vtkAssignAttribute::AttributeLocationNames[2][12] += { "POINT_DATA", + "CELL_DATA" }; + +char vtkAssignAttribute::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10] += { "SCALARS", + "VECTORS", + "NORMALS", + "TCOORDS", + "TENSORS" }; + +vtkAssignAttribute::vtkAssignAttribute() +{ + this->FieldName = 0; + this->AttributeLocation = -1; + this->AttributeType = -1; + this->InputAttributeType = -1; + this->FieldType = -1; +} + +vtkAssignAttribute::~vtkAssignAttribute() +{ + delete[] this->FieldName; + this->FieldName = 0; +} + +void vtkAssignAttribute::Assign(const char* fieldName, int attributeType, + int attributeLoc) +{ + if (!fieldName) + { + return; + } + + if ( (attributeType < 0) || + (attributeType > vtkDataSetAttributes::NUM_ATTRIBUTES) ) + { + vtkErrorMacro("Wrong attribute type."); + return; + } + + if ( (attributeLoc != vtkAssignAttribute::POINT_DATA) && + (attributeLoc != vtkAssignAttribute::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return; + } + + this->Modified(); + delete[] this->FieldName; + this->FieldName = new char[strlen(fieldName)+1]; + strcpy(this->FieldName, fieldName); + + this->AttributeType = attributeType; + this->AttributeLocation = attributeLoc; + this->FieldType = vtkAssignAttribute::NAME; +} + +void vtkAssignAttribute::Assign(int inputAttributeType, int attributeType, + int attributeLoc) +{ + if ( (attributeType < 0) || + (attributeType > vtkDataSetAttributes::NUM_ATTRIBUTES) || + (inputAttributeType < 0) || + (inputAttributeType > vtkDataSetAttributes::NUM_ATTRIBUTES)) + { + vtkErrorMacro("Wrong attribute type."); + return; + } + + if ( (attributeLoc != vtkAssignAttribute::POINT_DATA) && + (attributeLoc != vtkAssignAttribute::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return; + } + + this->Modified(); + this->AttributeType = attributeType; + this->InputAttributeType = inputAttributeType; + this->AttributeLocation = attributeLoc; + this->FieldType = vtkAssignAttribute::ATTRIBUTE; +} + +void vtkAssignAttribute::Assign(const char* name, + const char* attributeType, + const char* attributeLoc) +{ + if (!name || !attributeType || !attributeLoc) + { + return; + } + + int numAttr = vtkDataSetAttributes::NUM_ATTRIBUTES; + int numAttributeLocs = 2; + int i; + + // Convert strings to ints and call the appropriate Assign() + int inputAttributeType=-1; + for(i=0; iAssign(name, attrType, loc); + } + else + { + this->Assign(inputAttributeType, attrType, loc); + } +} + +int vtkAssignAttribute::RequestInformation(vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if ((this->AttributeType != -1) && + (this->AttributeLocation != -1) && (this->FieldType != -1)) + { + int fieldAssociation = this->AttributeLocation == POINT_DATA ? + vtkDataObject::FIELD_ASSOCIATION_POINTS : vtkDataObject::FIELD_ASSOCIATION_CELLS; + if (this->FieldType == vtkAssignAttribute::NAME && this->FieldName) + { + vtkDataObject::SetActiveAttribute(outInfo, fieldAssociation, + this->FieldName, this->AttributeType); + } + else if (this->FieldType == vtkAssignAttribute::ATTRIBUTE && + this->InputAttributeType != -1) + { + vtkInformation *inputAttributeInfo = vtkDataObject::GetActiveFieldInformation( + inInfo, fieldAssociation, this->InputAttributeType); + if (inputAttributeInfo) // do we have an active field of requested type + { + vtkDataObject::SetActiveAttribute(outInfo, fieldAssociation, + inputAttributeInfo->Get( vtkDataObject::FIELD_NAME() ), + this->AttributeType); + } + } + } + + return 1; +} + + +int vtkAssignAttribute::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // This has to be here because it initialized all field datas. + output->CopyStructure( input ); + + if ( output->GetFieldData() && input->GetFieldData() ) + { + output->GetFieldData()->PassData( input->GetFieldData() ); + } + output->GetPointData()->PassData( input->GetPointData() ); + output->GetCellData()->PassData( input->GetCellData() ); + + if ((this->AttributeType != -1) && + (this->AttributeLocation != -1) && (this->FieldType != -1)) + { + vtkDataSetAttributes* ods=0; + // Get the appropriate output DataSetAttributes + switch (this->AttributeLocation) + { + case vtkAssignAttribute::POINT_DATA: + ods = output->GetPointData(); + break; + case vtkAssignAttribute::CELL_DATA: + ods = output->GetCellData(); + break; + } + if (this->FieldType == vtkAssignAttribute::NAME && this->FieldName) + { + ods->SetActiveAttribute(this->FieldName, this->AttributeType); + } + else if (this->FieldType == vtkAssignAttribute::ATTRIBUTE && + (this->InputAttributeType != -1)) + { + // If labeling an attribute as another attribute, we + // need to get it's index and call SetActiveAttribute() + // with that index + //int attributeIndices[vtkDataSetAttributes::NUM_ATTRIBUTES]; + //ods->GetAttributeIndices(attributeIndices); + // if (attributeIndices[this->InputAttributeType] != -1) + vtkDataArray *oda = ods->GetAttribute(this->InputAttributeType); + if (oda) + { + ods->SetActiveAttribute(oda->GetName(),this->AttributeType); + } + } + } + + return 1; +} + +void vtkAssignAttribute::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Field name: "; + if (this->FieldName) + { + os << this->FieldName << endl; + } + else + { + os << "(none)" << endl; + } + os << indent << "Field type: " << this->FieldType << endl; + os << indent << "Attribute type: " << this->AttributeType << endl; + os << indent << "Input attribute type: " << this->InputAttributeType + << endl; + os << indent << "Attribute location: " << this->AttributeLocation << endl; +} diff --git a/Graphics/vtkAssignAttribute.h b/Graphics/vtkAssignAttribute.h new file mode 100644 index 0000000..21d2998 --- /dev/null +++ b/Graphics/vtkAssignAttribute.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssignAttribute.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAssignAttribute - Labels a field as an attribute +// .SECTION Description +// vtkAssignAttribute is use to label a field (vtkDataArray) as an attribute. +// A field name or an attribute to labeled can be specified. For example: +// @verbatim +// aa->Assign("foo", vtkDataSetAttributes::SCALARS, +// vtkAssignAttribute::POINT_DATA); +// @endverbatim +// tells vtkAssignAttribute to make the array in the point data called +// "foo" the active scalars. On the other hand, +// @verbatim +// aa->Assign(vtkDataSetAttributes::VECTORS, vtkDataSetAttributes::SCALARS, +// vtkAssignAttribute::POINT_DATA); +// @endverbatim +// tells vtkAssignAttribute to make the active vectors also the active +// scalars. The same can be done more easily from Tcl by using the Assign() +// method which takes strings: +// @verbatim +// aa Assign "foo" SCALARS POINT_DATA +// or +// aa Assign SCALARS VECTORS POINT_DATA +// +// AttributeTypes: SCALARS, VECTORS, NORMALS, TCOORDS, TENSORS +// Attribute locations: POINT_DATA, CELL_DATA +// @endverbatim + +// .SECTION Caveats +// When using Tcl, Java, Python or Visual Basic bindings, the array name +// can not be one of the AttributeTypes when calling Assign() which takes +// strings as arguments. The Tcl (Java etc.) command will +// always assume the string corresponds to an attribute type when +// the argument is one of the AttributeTypes. In this situation, +// use the Assign() which takes enums. + +// .SECTION See Also +// vtkFieldData vtkDataSet vtkDataObjectToDataSetFilter +// vtkDataSetAttributes vtkDataArray vtkRearrangeFields +// vtkSplitField vtkMergeFields + +#ifndef __vtkAssignAttribute_h +#define __vtkAssignAttribute_h + +#include "vtkDataSetAlgorithm.h" + +#include "vtkDataSetAttributes.h" // Needed for NUM_ATTRIBUTES + +class vtkFieldData; + +class VTK_GRAPHICS_EXPORT vtkAssignAttribute : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkAssignAttribute,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a new vtkAssignAttribute. + static vtkAssignAttribute *New(); + + // Description: + // Label an attribute as another attribute. + void Assign(int inputAttributeType, int attributeType, int attributeLoc); + + // Description: + // Label an array as an attribute. + void Assign(const char* fieldName, int attributeType, int attributeLoc); + + // Description: + // Helper method used by other language bindings. Allows the caller to + // specify arguments as strings instead of enums. + void Assign(const char* name, const char* attributeType, + const char* attributeLoc); + + +//BTX + enum AttributeLocation + { + POINT_DATA=0, + CELL_DATA=1 + }; +//ETX + +protected: + +//BTX + enum FieldType + { + NAME, + ATTRIBUTE + }; +//ETX + + vtkAssignAttribute(); + virtual ~vtkAssignAttribute(); + + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char* FieldName; + int FieldType; + int AttributeType; + int InputAttributeType; + int AttributeLocation; + + static char AttributeLocationNames[2][12]; + static char AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10]; +private: + vtkAssignAttribute(const vtkAssignAttribute&); // Not implemented. + void operator=(const vtkAssignAttribute&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkAttributeDataToFieldDataFilter.cxx b/Graphics/vtkAttributeDataToFieldDataFilter.cxx new file mode 100644 index 0000000..5feea11 --- /dev/null +++ b/Graphics/vtkAttributeDataToFieldDataFilter.cxx @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAttributeDataToFieldDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAttributeDataToFieldDataFilter.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkAttributeDataToFieldDataFilter, "$Revision: 1.18 $"); +vtkStandardNewMacro(vtkAttributeDataToFieldDataFilter); + +// Instantiate object. +vtkAttributeDataToFieldDataFilter::vtkAttributeDataToFieldDataFilter() +{ + this->PassAttributeData = 1; +} + +int vtkAttributeDataToFieldDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->CopyStructure( input ); + output->GetPointData()->PassData( input->GetPointData() ); + output->GetCellData()->PassData( input->GetCellData() ); + + return 1; +} + +void vtkAttributeDataToFieldDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Pass Attribute Data: " << (this->PassAttributeData ? "On\n" : "Off\n"); +} + diff --git a/Graphics/vtkAttributeDataToFieldDataFilter.h b/Graphics/vtkAttributeDataToFieldDataFilter.h new file mode 100644 index 0000000..87d1b1e --- /dev/null +++ b/Graphics/vtkAttributeDataToFieldDataFilter.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAttributeDataToFieldDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAttributeDataToFieldDataFilter - map attribute data to field data +// .SECTION Description +// vtkAttributeDataToFieldDataFilter is a class that maps attribute data into +// field data. Since this filter is a subclass of vtkDataSetAlgorithm, +// the output dataset (whose structure is the same as the input dataset), +// will contain the field data that is generated. The filter will convert +// point and cell attribute data to field data and assign it as point and +// cell field data, replacing any point or field data that was there +// previously. By default, the original non-field point and cell attribute +// data will be passed to the output of the filter, although you can shut +// this behavior down. + +// .SECTION Caveats +// Reference counting the underlying data arrays is used to create the field +// data. Therefore, no extra memory is utilized. +// +// The original field data (if any) associated with the point and cell +// attribute data is placed into the generated fields along with the scalars, +// vectors, etc. + +// .SECTION See Also +// vtkFieldData vtkDataObject vtkDataSet vtkFieldDataToAttributeDataFilter + +#ifndef __vtkAttributeDataToFieldDataFilter_h +#define __vtkAttributeDataToFieldDataFilter_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkAttributeDataToFieldDataFilter : public vtkDataSetAlgorithm +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkAttributeDataToFieldDataFilter,vtkDataSetAlgorithm); + + // Description: + // Construct this object. + static vtkAttributeDataToFieldDataFilter *New(); + + // Description: + // Turn on/off the passing of point and cell non-field attribute data to the + // output of the filter. + vtkSetMacro(PassAttributeData,int); + vtkGetMacro(PassAttributeData,int); + vtkBooleanMacro(PassAttributeData,int); + +protected: + vtkAttributeDataToFieldDataFilter(); + ~vtkAttributeDataToFieldDataFilter() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); //generate output data + + int PassAttributeData; +private: + vtkAttributeDataToFieldDataFilter(const vtkAttributeDataToFieldDataFilter&); // Not implemented. + void operator=(const vtkAttributeDataToFieldDataFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkAxes.cxx b/Graphics/vtkAxes.cxx new file mode 100644 index 0000000..b75c81a --- /dev/null +++ b/Graphics/vtkAxes.cxx @@ -0,0 +1,187 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAxes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAxes.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkAxes, "$Revision: 1.44 $"); +vtkStandardNewMacro(vtkAxes); + +// Construct with origin=(0,0,0) and scale factor=1. +vtkAxes::vtkAxes() +{ + this->Origin[0] = 0.0; + this->Origin[1] = 0.0; + this->Origin[2] = 0.0; + + this->ScaleFactor = 1.0; + + this->Symmetric = 0; + this->ComputeNormals = 1; + + this->SetNumberOfInputPorts(0); +} + +int vtkAxes::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int numPts=6, numLines=3; + vtkPoints *newPts; + vtkCellArray *newLines; + vtkFloatArray *newScalars; + vtkFloatArray *newNormals; + double x[3], n[3]; + vtkIdType ptIds[2]; + + vtkDebugMacro(<<"Creating x-y-z axes"); + + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(numLines,2)); + newScalars = vtkFloatArray::New(); + newScalars->Allocate(numPts); + newScalars->SetName("Axes"); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(numPts); + newNormals->SetName("Normals"); + +// +// Create axes +// + x[0] = this->Origin[0]; + x[1] = this->Origin[1]; + x[2] = this->Origin[2]; + if (this->Symmetric) + { + x[0] = this->Origin[0] - this->ScaleFactor; + } + n[0] = 0.0; n[1] = 1.0; n[2] = 0.0; + ptIds[0] = newPts->InsertNextPoint(x); + newScalars->InsertNextValue(0.0); + newNormals->InsertNextTuple(n); + + x[0] = this->Origin[0] + this->ScaleFactor; + x[1] = this->Origin[1]; + x[2] = this->Origin[2]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + newScalars->InsertNextValue(0.0); + newNormals->InsertNextTuple(n); + + x[0] = this->Origin[0]; + x[1] = this->Origin[1]; + x[2] = this->Origin[2]; + if (this->Symmetric) + { + x[1] = this->Origin[1] - this->ScaleFactor; + } + n[0] = 0.0; n[1] = 0.0; n[2] = 1.0; + ptIds[0] = newPts->InsertNextPoint(x); + newScalars->InsertNextValue(0.25); + newNormals->InsertNextTuple(n); + + x[0] = this->Origin[0]; + x[1] = this->Origin[1] + this->ScaleFactor; + x[2] = this->Origin[2]; + ptIds[1] = newPts->InsertNextPoint(x); + newScalars->InsertNextValue(0.25); + newNormals->InsertNextTuple(n); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->Origin[0]; + x[1] = this->Origin[1]; + x[2] = this->Origin[2]; + if (this->Symmetric) + { + x[2] = this->Origin[2] - this->ScaleFactor; + } + n[0] = 1.0; n[1] = 0.0; n[2] = 0.0; + ptIds[0] = newPts->InsertNextPoint(x); + newScalars->InsertNextValue(0.5); + newNormals->InsertNextTuple(n); + + x[0] = this->Origin[0]; + x[1] = this->Origin[1]; + x[2] = this->Origin[2] + this->ScaleFactor; + ptIds[1] = newPts->InsertNextPoint(x); + newScalars->InsertNextValue(0.5); + newNormals->InsertNextTuple(n); + newLines->InsertNextCell(2,ptIds); + + // + // Update our output and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + output->GetPointData()->SetScalars(newScalars); + newScalars->Delete(); + + if (this->ComputeNormals) + { + output->GetPointData()->SetNormals(newNormals); + } + newNormals->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +// This source does not know how to generate pieces yet. +int vtkAxes::ComputeDivisionExtents(vtkDataObject *vtkNotUsed(output), + int idx, int numDivisions) +{ + if (idx == 0 && numDivisions == 1) + { + // I will give you the whole thing + return 1; + } + else + { + // I have nothing to give you for this piece. + return 0; + } +} + +void vtkAxes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Origin: (" << this->Origin[0] << ", " + << this->Origin[1] << ", " + << this->Origin[2] << ")\n"; + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; + os << indent << "Symmetric: " << this->Symmetric << "\n"; + os << indent << "ComputeNormals: " << this->ComputeNormals << "\n"; +} diff --git a/Graphics/vtkAxes.h b/Graphics/vtkAxes.h new file mode 100644 index 0000000..6538940 --- /dev/null +++ b/Graphics/vtkAxes.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAxes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAxes - create an x-y-z axes +// .SECTION Description +// vtkAxes creates three lines that form an x-y-z axes. The origin of the +// axes is user specified (0,0,0 is default), and the size is specified with +// a scale factor. Three scalar values are generated for the three lines and +// can be used (via color map) to indicate a particular coordinate axis. + +#ifndef __vtkAxes_h +#define __vtkAxes_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkAxes : public vtkPolyDataAlgorithm +{ +public: + static vtkAxes *New(); + + vtkTypeRevisionMacro(vtkAxes,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the origin of the axes. + vtkSetVector3Macro(Origin,double); + vtkGetVectorMacro(Origin,double,3); + + // Description: + // Set the scale factor of the axes. Used to control size. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // If Symetric is on, the the axis continue to negative values. + vtkSetMacro(Symmetric,int); + vtkGetMacro(Symmetric,int); + vtkBooleanMacro(Symmetric,int); + + // Description: + // Option for computing normals. By default they are computed. + vtkSetMacro(ComputeNormals, int); + vtkGetMacro(ComputeNormals, int); + vtkBooleanMacro(ComputeNormals, int); + +protected: + vtkAxes(); + ~vtkAxes() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + // This source does not know how to generate pieces yet. + int ComputeDivisionExtents(vtkDataObject *output, + int idx, int numDivisions); + + double Origin[3]; + double ScaleFactor; + + int Symmetric; + int ComputeNormals; +private: + vtkAxes(const vtkAxes&); // Not implemented. + void operator=(const vtkAxes&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkBSPCuts.cxx b/Graphics/vtkBSPCuts.cxx new file mode 100644 index 0000000..649e16d --- /dev/null +++ b/Graphics/vtkBSPCuts.cxx @@ -0,0 +1,487 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBSPCuts.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkBSPCuts.h" +#include "vtkKdNode.h" +#include "vtkKdTree.h" +#include "vtkObjectFactory.h" + +#ifdef _MSC_VER +#pragma warning ( disable : 4100 ) +#endif + +vtkCxxRevisionMacro(vtkBSPCuts, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkBSPCuts); + +//---------------------------------------------------------------------------- +vtkBSPCuts::vtkBSPCuts() +{ + this->Top = NULL; + this->NumberOfCuts = 0; + this->Dim = NULL; + this->Coord = NULL; + this->Lower = NULL; + this->Upper = NULL; + this->LowerDataCoord = NULL; + this->UpperDataCoord = NULL; + this->Npoints = NULL; +} + +//---------------------------------------------------------------------------- +vtkBSPCuts::~vtkBSPCuts() +{ + if (this->Top) + { + vtkBSPCuts::DeleteAllDescendants(this->Top); + this->Top->Delete(); + } + + this->ResetArrays(); +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::ResetArrays() +{ + if (this->Dim) + { + delete [] this->Dim; + this->Dim = NULL; + } + if (this->Coord) + { + delete [] this->Coord; + this->Coord = NULL; + } + if (this->Lower) + { + delete [] this->Lower; + this->Lower = NULL; + } + if (this->Upper) + { + delete [] this->Upper; + this->Upper = NULL; + } + if (this->LowerDataCoord) + { + delete [] this->LowerDataCoord; + this->LowerDataCoord = NULL; + } + if (this->UpperDataCoord) + { + delete [] this->UpperDataCoord; + this->UpperDataCoord = NULL; + } + if (this->Npoints) + { + delete [] this->Npoints; + this->Npoints = NULL; + } + + this->NumberOfCuts = 0; +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::AllocateArrays(int nNodes) +{ + this->Dim = new int [nNodes]; + this->Coord = new double [nNodes]; + this->Lower = new int [nNodes]; + this->Upper = new int [nNodes]; + this->LowerDataCoord = new double [nNodes]; + this->UpperDataCoord = new double [nNodes]; + this->Npoints = new int [nNodes]; +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::DeleteAllDescendants(vtkKdNode *nd) +{ + vtkKdNode *left = nd->GetLeft(); + vtkKdNode *right = nd->GetRight(); + + if (left && left->GetLeft()) + { + vtkBSPCuts::DeleteAllDescendants(left); + } + + if (right && right->GetLeft()) + { + vtkBSPCuts::DeleteAllDescendants(right); + } + + if (left && right) + { + nd->DeleteChildNodes(); // undo AddChildNodes + left->Delete(); // undo vtkKdNode::New() + right->Delete(); + } +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::CreateCuts(vtkKdNode *kd) +{ + // Given a tree of vtkKdNodes, create the arrays that describe this + // spatial partitioning. + + kd->GetBounds(this->Bounds); + + // preallocate vectors + + this->ResetArrays(); + + int nNodes = vtkBSPCuts::CountNodes(kd); + + this->AllocateArrays(nNodes); + + // convert kd node tree to vector form + + this->NumberOfCuts = this->WriteArray(kd, 0); + + // keep a copy of vtkKdNode tree + + if (this->Top) + { + vtkBSPCuts::DeleteAllDescendants(this->Top); + this->Top->Delete(); + this->Top = NULL; + } + + this->Top = vtkKdTree::CopyTree(kd); +} +//---------------------------------------------------------------------------- +int vtkBSPCuts::CountNodes(vtkKdNode *kd) +{ + int leftCount=0; + int rightCount=0; + + if (kd->GetLeft()) + { + leftCount = vtkBSPCuts::CountNodes(kd->GetLeft()); + rightCount = vtkBSPCuts::CountNodes(kd->GetRight()); + } + + return leftCount + rightCount + 1; +} +//---------------------------------------------------------------------------- +int vtkBSPCuts::WriteArray(vtkKdNode *kd, int loc) +{ + int nextloc = loc + 1; + + int dim = kd->GetDim(); // 0 (X), 1 (Y), 2 (Z) + + this->Npoints[loc] = kd->GetNumberOfPoints(); + + if (kd->GetLeft()) + { + this->Dim[loc] = dim; + + vtkKdNode *left = kd->GetLeft(); + vtkKdNode *right = kd->GetRight(); + + this->Coord[loc] = left->GetMaxBounds()[dim]; + this->LowerDataCoord[loc] = left->GetMaxDataBounds()[dim]; + this->UpperDataCoord[loc] = right->GetMinDataBounds()[dim]; + + int locleft = loc + 1; + + int locright = this->WriteArray(left, locleft); + + nextloc = this->WriteArray(right, locright); + + this->Lower[loc] = locleft; + this->Upper[loc] = locright; + } + else + { + this->Dim[loc] = -1; + this->Coord[loc] = 0.0; + this->LowerDataCoord[loc] = 0.0; + this->UpperDataCoord[loc] = 0.0; + this->Lower[loc] = kd->GetID() * -1; // partition ID + this->Upper[loc] = kd->GetID() * -1; + } + + return nextloc; // next available array location +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::CreateCuts(double *bnds, int ncuts, int *dim, double *coord, + int *lower, int *upper, + double *lowerDataCoord, double *upperDataCoord, + int *npoints) +{ + // Keep a copy of these arrays + + vtkBSPCuts::ResetArrays(); + vtkBSPCuts::AllocateArrays(ncuts); + + for (int i=0; i<6; i++) + { + this->Bounds[i] = bnds[i]; + } + + this->NumberOfCuts = ncuts; + + memcpy(this->Dim, dim, sizeof(int) * ncuts); + memcpy(this->Coord, coord, sizeof(double) * ncuts); + memcpy(this->Lower, lower, sizeof(int) * ncuts); + memcpy(this->Upper, upper, sizeof(int) * ncuts); + + if (lowerDataCoord) + { + memcpy(this->LowerDataCoord, lowerDataCoord, sizeof(double) * ncuts); + } + else + { + delete [] this->LowerDataCoord; + this->LowerDataCoord = NULL; + } + + if (upperDataCoord) + { + memcpy(this->UpperDataCoord, upperDataCoord, sizeof(double) * ncuts); + } + else + { + delete [] this->UpperDataCoord; + this->UpperDataCoord = NULL; + } + + if (npoints) + { + memcpy(this->Npoints, npoints, sizeof(int) * ncuts); + } + else + { + delete [] this->Npoints; + this->Npoints = NULL; + } + + // Now build tree from arrays + + if (this->Top) + { + vtkBSPCuts::DeleteAllDescendants(this->Top); + this->Top->Delete(); + this->Top = NULL; + } + + this->Top = vtkKdNode::New(); + this->Top->SetBounds(bnds[0], bnds[1],bnds[2],bnds[3],bnds[4],bnds[5]); + this->Top->SetDataBounds(bnds[0], bnds[1],bnds[2],bnds[3],bnds[4],bnds[5]); + + this->BuildTree(this->Top, 0); + + vtkBSPCuts::SetMinMaxId(this->Top); +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::BuildTree(vtkKdNode *kd, int idx) +{ + int dim = this->Dim[idx]; + + if (this->Npoints) + { + kd->SetNumberOfPoints(this->Npoints[idx]); + } + + if (this->Lower[idx] > 0) + { + vtkKdNode *left = vtkKdNode::New(); + vtkKdNode *right = vtkKdNode::New(); + + kd->SetDim(dim); + + double b2[6]; + double db2[6]; + + kd->GetBounds(b2); + kd->GetDataBounds(db2); + + b2[dim*2 + 1] = this->Coord[idx]; // new upper bound for lower half + + if (this->LowerDataCoord) + { + db2[dim*2 + 1] = this->LowerDataCoord[idx]; + } + else + { + db2[dim*2 + 1] = this->Coord[idx]; + } + + left->SetBounds(b2[0],b2[1],b2[2],b2[3],b2[4],b2[5]); + left->SetDataBounds(db2[0],db2[1],db2[2],db2[3],db2[4],db2[5]); + + kd->GetBounds(b2); + kd->GetDataBounds(db2); + + b2[dim*2] = this->Coord[idx]; // new lower bound for upper half + + if (this->UpperDataCoord) + { + db2[dim*2] = this->UpperDataCoord[idx]; + } + else + { + db2[dim*2] = this->Coord[idx]; + } + + right->SetBounds(b2[0],b2[1],b2[2],b2[3],b2[4],b2[5]); + right->SetDataBounds(db2[0],db2[1],db2[2],db2[3],db2[4],db2[5]); + + kd->AddChildNodes(left, right); + + this->BuildTree(left, this->Lower[idx]); + this->BuildTree(right, this->Upper[idx]); + } + else + { + kd->SetID(this->Lower[idx] * -1); // partition ID of leaf node + } +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::SetMinMaxId(vtkKdNode *kd) +{ + if (kd->GetLeft()) + { + vtkBSPCuts::SetMinMaxId(kd->GetLeft()); + vtkBSPCuts::SetMinMaxId(kd->GetRight()); + } + else + { + kd->SetMinID(kd->GetID()); + kd->SetMaxID(kd->GetID()); + return; + } + + int min1 = kd->GetLeft()->GetMinID(); + int max1 = kd->GetLeft()->GetMaxID(); + int min2 = kd->GetRight()->GetMinID(); + int max2 = kd->GetRight()->GetMaxID(); + + kd->SetMinID( (min1 < min2) ? min1 : min2); + kd->SetMaxID( (max1 > max2) ? max1 : max2); +} + +//---------------------------------------------------------------------------- +int vtkBSPCuts::GetArrays(int len, + int *dim, double *coord, int *lower, int *upper, + double *lowerDataCoord, double *upperDataCoord, int *npoints) +{ + int l = (len < this->NumberOfCuts) ? len : this->NumberOfCuts; + + if (l < 1) return 1; + + if (dim) + { + memcpy(dim, this->Dim, l * sizeof(int)); + } + if (coord) + { + memcpy(coord, this->Coord, l * sizeof(double)); + } + if (lower) + { + memcpy(lower, this->Lower, l * sizeof(int)); + } + if (upper) + { + memcpy(upper, this->Upper, l * sizeof(int)); + } + + if (lowerDataCoord && this->LowerDataCoord) + { + memcpy(lowerDataCoord, this->LowerDataCoord, l * sizeof(double)); + } + if (upperDataCoord && this->UpperDataCoord) + { + memcpy(upperDataCoord, this->UpperDataCoord, l * sizeof(double)); + } + if (npoints && this->Npoints) + { + memcpy(npoints, this->Npoints, l * sizeof(int)); + } + + return 0; +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::PrintArrays() +{ + int i; + if (this->NumberOfCuts == 0) + { + return; + } + + cout << "xmin: " << this->Bounds[0] << " xmax: " << this->Bounds[1] << endl ; + cout << "ymin: " << this->Bounds[2] << " ymax: " << this->Bounds[3] << endl; + cout << "zmin: " << this->Bounds[4] << " zmax: " << this->Bounds[5] << endl; + + cout << "index / dimension / coordinate / lower region / upper region" << endl; + + for (i=0; iNumberOfCuts; i++) + { + cout << i << " / " << this->Dim[i] << " / " << this->Coord[i]; + cout << " / " << this->Lower[i] << " / " << this->Upper[i] << endl; + } + + if (this->LowerDataCoord) + { + cout << "index / lower data bdry / upper data bdry / data points" << endl; + + for (i=0; iNumberOfCuts; i++) + { + cout << i << " / " << this->LowerDataCoord[i] << " / " << this->UpperDataCoord[i]; + cout << " / " << this->Npoints[i] << endl; + } + } +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::PrintTree() +{ + if (this->Top == NULL) + { + return; + } + + vtkBSPCuts::_PrintTree(this->Top, 0); +} +//---------------------------------------------------------------------------- +void vtkBSPCuts::_PrintTree(vtkKdNode *kd, int depth) +{ + kd->PrintNode(depth); + + if (kd->GetLeft()) + { + vtkBSPCuts::_PrintTree(kd->GetLeft(),depth+1); + vtkBSPCuts::_PrintTree(kd->GetRight(),depth+1); + } +} + +//---------------------------------------------------------------------------- + +void vtkBSPCuts::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Top: " << this->Top << endl; + os << indent << "NumberOfCuts: " << this->NumberOfCuts << endl; + os << indent << "Dim: " << this->Dim << endl; + os << indent << "Coord: " << this->Coord << endl; + os << indent << "Lower: " << this->Lower << endl; + os << indent << "Upper: " << this->Upper << endl; + os << indent << "LowerDataCoord: " << this->LowerDataCoord << endl; + os << indent << "UpperDataCoord: " << this->UpperDataCoord << endl; + os << indent << "Npoints: " << this->Npoints << endl; +} diff --git a/Graphics/vtkBSPCuts.h b/Graphics/vtkBSPCuts.h new file mode 100644 index 0000000..9c26400 --- /dev/null +++ b/Graphics/vtkBSPCuts.h @@ -0,0 +1,137 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBSPCuts.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkBSPCuts - This class represents an axis-aligned Binary Spatial +// Partitioning of a 3D space. +// +// .SECTION Description +// This class converts between the vtkKdTree +// representation of a tree of vtkKdNodes (used by vtkDistributedDataFilter) +// and a compact array representation that might be provided by a +// graph partitioning library like Zoltan. Such a representation +// could be used in message passing. +// +// .SECTION See Also +// vtkKdTree vtkKdNode vtkDistributedDataFilter + +#ifndef __vtkBSPCuts_h +#define __vtkBSPCuts_h + +#include "vtkObject.h" + +class vtkKdNode; + +class VTK_GRAPHICS_EXPORT vtkBSPCuts : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkBSPCuts, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkBSPCuts *New(); + + // Description: + // Initialize the cuts with arrays of information. This type of + // information would be obtained from a graph partitioning software + // package like Zoltan. + // + // bounds - the bounds (xmin, xmax, ymin, ymax, zmin, zmax) of the + // space being partitioned + // ncuts - the number cuts, also the size of the following arrays + // dim - the dimension along which the cut is made (x/y/z - 0/1/2) + // coord - the location of the cut along the axis + // lower - array index for the lower region bounded by the cut + // upper - array index for the upper region bounded by the cut + // lowerDataCoord - optional upper bound of the data in the lower region + // upperDataCoord - optional lower bound of the data in the upper region + // npoints - optional number of points in the spatial region + + void CreateCuts(double *bounds, + int ncuts, int *dim, double *coord, + int *lower, int *upper, + double *lowerDataCoord, double *upperDataCoord, + int *npoints); + + // Description: + // Initialize the cuts from a tree of vtkKdNode's + + void CreateCuts(vtkKdNode *kd); + + // Description: + // Return a tree of vtkKdNode's representing the cuts specified + // in this object. This is our copy, don't delete it. + + vtkKdNode *GetKdNodeTree(){return this->Top;} + + // Description: + // Get the number of cuts in the partitioning, which also the size of + // the arrays in the array representation of the partitioning. + + vtkGetMacro(NumberOfCuts, int); + + // Description: + // Get the arrays representing the cuts in the partitioning. + + int GetArrays(int len, int *dim, double *coord, int *lower, int *upper, + double *lowerDataCoord, double *upperDataCoord, int *npoints); + + void PrintTree(); + void PrintArrays(); + +protected: + + vtkBSPCuts(); + ~vtkBSPCuts(); + +private: + + static void DeleteAllDescendants(vtkKdNode *kd); + + static int CountNodes(vtkKdNode *kd); + static void SetMinMaxId(vtkKdNode *kd); + static void _PrintTree(vtkKdNode *kd, int depth); + + void BuildTree(vtkKdNode *kd, int idx); + int WriteArray(vtkKdNode *kd, int loc); + + void ResetArrays(); + void AllocateArrays(int size); + + vtkKdNode *Top; + + // required cut information + + int NumberOfCuts;// number of cuts, also length of each array + int *Dim; // dimension (x/y/z - 0/1/2) where cut occurs + double *Coord; // location of cut along axis + int *Lower; // location in arrays of left (lower) child info + int *Upper; // location in arrays of right (lower) child info + + // optional cut information + + double *LowerDataCoord; // coordinate of uppermost data in lower half + double *UpperDataCoord; // coordinate of lowermost data in upper half + int *Npoints; // number of data values in partition + + double Bounds[6]; + + vtkBSPCuts(const vtkBSPCuts&); // Not implemented + void operator=(const vtkBSPCuts&); // Not implemented +}; + +#endif diff --git a/Graphics/vtkBSPIntersections.cxx b/Graphics/vtkBSPIntersections.cxx new file mode 100644 index 0000000..2205501 --- /dev/null +++ b/Graphics/vtkBSPIntersections.cxx @@ -0,0 +1,522 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBSPIntersections.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkBSPIntersections.h" +#include "vtkBSPCuts.h" +#include "vtkKdNode.h" +#include "vtkObjectFactory.h" +#include "vtkCell.h" +#include "vtkPoints.h" + +#include + +vtkCxxRevisionMacro(vtkBSPIntersections, "$Revision: 1.2 $"); + +vtkStandardNewMacro(vtkBSPIntersections); + +#define REGIONCHECK(err) \ +if (this->BuildRegionList()) \ + { \ + return err; \ + } + +#define REGIONIDCHECK_RETURNERR(id, err) \ +if (this->BuildRegionList()) \ + { \ + return err; \ + } \ +if ((id < 0) || (id >= this->NumberOfRegions)) \ + { \ + vtkErrorMacro(<< "Invalid region ID"); \ + return err; \ + } + +#define REGIONIDCHECK(id) \ +if (this->BuildRegionList()) \ + { \ + return; \ + } \ +if ((id < 0) || (id >= this->NumberOfRegions)) \ + { \ + vtkErrorMacro(<< "Invalid region ID"); \ + return; \ + } + +//---------------------------------------------------------------------------- + +vtkCxxSetObjectMacro(vtkBSPIntersections, Cuts, vtkBSPCuts) + +//---------------------------------------------------------------------------- + +// Don't use vtkSetMacro or vtkBooleanMacro on these. They will +// update the Mtime, which is incorrect. + +void vtkBSPIntersections::SetComputeIntersectionsUsingDataBounds(int c) +{ + this->ComputeIntersectionsUsingDataBounds = (c != 0); +} + +void vtkBSPIntersections::ComputeIntersectionsUsingDataBoundsOn() +{ + this->ComputeIntersectionsUsingDataBounds = 1; +} + +void vtkBSPIntersections::ComputeIntersectionsUsingDataBoundsOff() +{ + this->ComputeIntersectionsUsingDataBounds = 0; +} + +//---------------------------------------------------------------------------- +vtkBSPIntersections::vtkBSPIntersections() +{ + this->Cuts = NULL; + this->NumberOfRegions = 0; + this->RegionList = NULL; + this->ComputeIntersectionsUsingDataBounds = 0; +} + +//---------------------------------------------------------------------------- +vtkBSPIntersections::~vtkBSPIntersections() +{ + this->SetCuts(NULL); + if (this->RegionList) + { + delete [] this->RegionList; + } +} +//---------------------------------------------------------------------------- +int vtkBSPIntersections::BuildRegionList() +{ + if ((this->RegionList != NULL) && + (this->RegionListBuildTime > this->GetMTime())) + { + return 0; + } + + if (this->RegionList) + { + delete [] this->RegionList; + this->RegionList = NULL; + } + + vtkKdNode *top = NULL; + if (this->Cuts) + { + top = this->Cuts->GetKdNodeTree(); + } + + if (!top) + { + return 1; + } + + this->NumberOfRegions = vtkBSPIntersections::NumberOfLeafNodes(top); + + if (this->NumberOfRegions < 1) + { + vtkErrorMacro(<< "vtkBSPIntersections::BuildRegionList no cuts in vtkBSPCut object"); + return 1; + } + + this->RegionList = new vtkKdNode * [this->NumberOfRegions]; + + if (!this->RegionList) + { + vtkErrorMacro(<< "vtkBSPIntersections::BuildRegionList memory allocation"); + return 1; + } + + int fail = this->SelfRegister(top); + + if (fail) + { + vtkErrorMacro(<< "vtkBSPIntersections::BuildRegionList bad ids in vtkBSPCut object"); + return 1; + } + + int min=0; + int max=0; + + vtkBSPIntersections::SetIDRanges(top, min, max); + + this->RegionListBuildTime.Modified(); + + return 0; +} +//---------------------------------------------------------------------------- +int vtkBSPIntersections::SelfRegister(vtkKdNode *kd) +{ + int fail = 0; + + if (kd->GetLeft() == NULL) + { + int id = kd->GetID(); + + if ((id < 0) || (id >= this->NumberOfRegions)) + { + return 1; + } + this->RegionList[id] = kd; + } + else + { + fail = this->SelfRegister(kd->GetLeft()); + + if (!fail) + { + fail = this->SelfRegister(kd->GetRight()); + } + } + + return fail; +} +//---------------------------------------------------------------------------- +int vtkBSPIntersections::NumberOfLeafNodes(vtkKdNode *kd) +{ + int nLeafNodes=1; + + if (kd->GetLeft() != NULL) + { + int numLeft = vtkBSPIntersections::NumberOfLeafNodes(kd->GetLeft()); + int numRight = vtkBSPIntersections::NumberOfLeafNodes(kd->GetRight()); + + nLeafNodes = numLeft + numRight; + } + + return nLeafNodes; +} +//---------------------------------------------------------------------------- +void vtkBSPIntersections::SetIDRanges(vtkKdNode *kd, int &min, int &max) +{ + int tempMin=0; + int tempMax=0; + + if (kd->GetLeft() == NULL) + { + min = kd->GetID(); + max = kd->GetID(); + } + else + { + vtkBSPIntersections::SetIDRanges(kd->GetLeft(), min, max); + vtkBSPIntersections::SetIDRanges(kd->GetRight(), tempMin, tempMax); + max = (tempMax > max) ? tempMax : max; + min = (tempMin < min) ? tempMin : min; + } + + kd->SetMinID(min); + kd->SetMaxID(max); +} +//---------------------------------------------------------------------------- +int vtkBSPIntersections::GetBounds(double *bounds) +{ + REGIONCHECK(1); + + this->Cuts->GetKdNodeTree()->GetBounds(bounds); + + return 0; +} +//---------------------------------------------------------------------------- +int vtkBSPIntersections::GetNumberOfRegions() +{ + REGIONCHECK(0) + + return this->NumberOfRegions; +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::GetRegionBounds(int regionID, double bounds[6]) +{ + REGIONIDCHECK_RETURNERR(regionID, 1) + + vtkKdNode *node = this->RegionList[regionID]; + + node->GetBounds(bounds); + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::GetRegionDataBounds(int regionID, double bounds[6]) +{ + REGIONIDCHECK_RETURNERR(regionID, 1) + + vtkKdNode *node = this->RegionList[regionID]; + + node->GetDataBounds(bounds); + + return 0; +} + +//---------------------------------------------------------------------------- +// Query functions ---------------------------------------------------- +// K-d Trees are particularly efficient with region intersection +// queries, like finding all regions that intersect a view frustum +// +// Intersection with axis-aligned box---------------------------------- +// + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::IntersectsBox(int regionId, double *x) +{ + return this->IntersectsBox(regionId, x[0], x[1], x[2], x[3], x[4], x[5]); +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::IntersectsBox(int regionId, double x0, double x1, + double y0, double y1, double z0, double z1) +{ + REGIONIDCHECK_RETURNERR(regionId, 0); + + vtkKdNode *node = this->RegionList[regionId]; + + return node->IntersectsBox(x0, x1, y0, y1, z0, z1, + this->ComputeIntersectionsUsingDataBounds); +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::IntersectsBox(int *ids, int len, double *x) +{ + return this->IntersectsBox(ids, len, x[0], x[1], x[2], x[3], x[4], x[5]); +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::IntersectsBox(int *ids, int len, + double x0, double x1, + double y0, double y1, double z0, double z1) +{ + REGIONCHECK(0); + + int nnodes = 0; + + if (len > 0) + { + nnodes = this->_IntersectsBox(this->Cuts->GetKdNodeTree(), ids, len, + x0, x1, y0, y1, z0, z1); + } + return nnodes; +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::_IntersectsBox(vtkKdNode *node, int *ids, int len, + double x0, double x1, + double y0, double y1, double z0, double z1) +{ + int result, nnodes1, nnodes2, listlen; + int *idlist; + + result = node->IntersectsBox(x0, x1, y0, y1, z0, z1, + this->ComputeIntersectionsUsingDataBounds); + + if (!result) + { + return 0; + } + + if (node->GetLeft() == NULL) + { + ids[0] = node->GetID(); + return 1; + } + + nnodes1 = _IntersectsBox(node->GetLeft(), ids, len, x0, x1, y0, y1, z0, z1); + + idlist = ids + nnodes1; + listlen = len - nnodes1; + + if (listlen > 0) + { + nnodes2 = _IntersectsBox(node->GetRight(), idlist, listlen, x0, x1, y0, y1, z0, z1); + } + else + { + nnodes2 = 0; + } + + return (nnodes1 + nnodes2); +} + +//---------------------------------------------------------------------------- +// Intersection with a sphere--------------------------------------- +// +int vtkBSPIntersections::IntersectsSphere2(int regionId, double x, double y, double z, + double rSquared) +{ + REGIONIDCHECK_RETURNERR(regionId, 0); + + vtkKdNode *node = this->RegionList[regionId]; + + return node->IntersectsSphere2(x, y, z, rSquared, + this->ComputeIntersectionsUsingDataBounds); +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::IntersectsSphere2(int *ids, int len, + double x, double y, double z, double rSquared) +{ + REGIONCHECK(0) + + int nnodes = 0; + + if (len > 0) + { + nnodes = this->_IntersectsSphere2(this->Cuts->GetKdNodeTree(), + ids, len, x, y, z, rSquared); + } + return nnodes; +} + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::_IntersectsSphere2(vtkKdNode *node, int *ids, int len, + double x, double y, double z, double rSquared) +{ + int result, nnodes1, nnodes2, listlen; + int *idlist; + + result = node->IntersectsSphere2(x, y, z, rSquared, + this->ComputeIntersectionsUsingDataBounds); + + if (!result) + { + return 0; + } + + if (node->GetLeft() == NULL) + { + ids[0] = node->GetID(); + return 1; + } + + nnodes1 = _IntersectsSphere2(node->GetLeft(), ids, len, x, y, z, rSquared); + + idlist = ids + nnodes1; + listlen = len - nnodes1; + + if (listlen > 0) + { + nnodes2 = _IntersectsSphere2(node->GetRight(), idlist, listlen, x, y, z, rSquared); + } + else + { + nnodes2 = 0; + } + + return (nnodes1 + nnodes2); +} + +//---------------------------------------------------------------------------- +// Intersection with arbitrary vtkCell ----------------------------- +// + +//---------------------------------------------------------------------------- +int vtkBSPIntersections::IntersectsCell(int regionId, vtkCell *cell, int cellRegion) +{ + REGIONIDCHECK_RETURNERR(regionId, 0); + + vtkKdNode *node = this->RegionList[regionId]; + + return node->IntersectsCell(cell, this->ComputeIntersectionsUsingDataBounds, + cellRegion); +} +//---------------------------------------------------------------------------- +void vtkBSPIntersections::SetCellBounds(vtkCell *cell, double *bounds) +{ + vtkPoints *pts = cell->GetPoints(); + pts->Modified(); // VTK bug - so bounds will be re-calculated + pts->GetBounds(bounds); +} +//---------------------------------------------------------------------------- +int vtkBSPIntersections::IntersectsCell(int *ids, int len, vtkCell *cell, int cellRegion) +{ + REGIONCHECK(0) + + vtkBSPIntersections::SetCellBounds(cell, this->CellBoundsCache); + + return this->_IntersectsCell(this->Cuts->GetKdNodeTree(), ids, len, cell, cellRegion); +} +//---------------------------------------------------------------------------- +int vtkBSPIntersections::_IntersectsCell(vtkKdNode *node, int *ids, int len, + vtkCell *cell, int cellRegion) +{ + int result, nnodes1, nnodes2, listlen, intersects; + int *idlist; + + intersects = node->IntersectsCell(cell, + this->ComputeIntersectionsUsingDataBounds, + cellRegion, this->CellBoundsCache); + + if (intersects) + { + if (node->GetLeft()) + { + nnodes1 = this->_IntersectsCell(node->GetLeft(), ids, len, cell, + cellRegion); + + idlist = ids + nnodes1; + listlen = len - nnodes1; + + if (listlen > 0) + { + nnodes2 = this->_IntersectsCell(node->GetRight(), idlist, listlen, cell, + cellRegion); + } + else + { + nnodes2 = 0; + } + + result = nnodes1 + nnodes2; + } + else + { + ids[0] = node->GetID(); // leaf node (spatial region) + + result = 1; + } + } + else + { + result = 0; + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkBSPIntersections::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cuts: "; + if( this->Cuts ) + { + this->Cuts->PrintSelf(os << endl, indent.GetNextIndent() ); + } + else + { + os << "(none)" << endl; + } + os << indent << "NumberOfRegions: " << this->NumberOfRegions << endl; + os << indent << "RegionList: " << this->RegionList << endl; + os << indent << "RegionListBuildTime: " << this->RegionListBuildTime << endl; + os << indent << "ComputeIntersectionsUsingDataBounds: " << this->ComputeIntersectionsUsingDataBounds << endl; + double *d = this->CellBoundsCache; + os << indent << "CellBoundsCache " << d[0] << " " << d[1] << " " << d[2] << " " << d[3] << " " << d[4] << " " << d[5] << " " << endl; +} diff --git a/Graphics/vtkBSPIntersections.h b/Graphics/vtkBSPIntersections.h new file mode 100644 index 0000000..a8e9f66 --- /dev/null +++ b/Graphics/vtkBSPIntersections.h @@ -0,0 +1,191 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBSPIntersections.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkBSPIntersections - Perform calculations (mostly intersection +// calculations) on regions of a 3D binary spatial partitioning. +// +// .SECTION Description +// Given an axis aligned binary spatial partitioning described by a +// vtkBSPCuts object, perform intersection queries on various +// geometric entities with regions of the spatial partitioning. +// +// .SECTION See Also +// vtkBSPCuts vtkKdTree + +#ifndef __vtkBSPIntersections_h +#define __vtkBSPIntersections_h + +#include "vtkObject.h" + +class vtkTimeStamp; +class vtkCell; +class vtkKdNode; +class vtkBSPCuts; + +class VTK_GRAPHICS_EXPORT vtkBSPIntersections : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkBSPIntersections, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkBSPIntersections *New(); + + // Description: + // Define the binary spatial partitioning. + + void SetCuts(vtkBSPCuts *cuts); + vtkGetObjectMacro(Cuts, vtkBSPCuts); + + // Description: + // Get the bounds of the whole space (xmin, xmax, ymin, ymax, zmin, zmax) + // Return 0 if OK, 1 on error. + + int GetBounds(double *bounds); + + // Description: + // The number of regions in the binary spatial partitioning + + int GetNumberOfRegions(); + + // Description: + // Get the spatial bounds of a particular region + // Return 0 if OK, 1 on error. + + int GetRegionBounds(int regionID, double bounds[6]); + + // Description: + // Get the bounds of the data within the k-d tree region, possibly + // smaller than the bounds of the region. + // Return 0 if OK, 1 on error. + + int GetRegionDataBounds(int regionID, double bounds[6]); + + // Description: + // Determine whether a region of the spatial decomposition + // intersects an axis aligned box. + int IntersectsBox(int regionId, double *x); + int IntersectsBox(int regionId, double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax); + + // Description: + // Compute a list of the Ids of all regions that + // intersect the specified axis aligned box. + // Returns: the number of ids in the list. + int IntersectsBox(int *ids, int len, double *x); + int IntersectsBox(int *ids, int len, double x0, double x1, + double y0, double y1, double z0, double z1); + + // Description: + // Determine whether a region of the spatial decomposition + // intersects a sphere, given the center of the sphere + // and the square of it's radius. + int IntersectsSphere2(int regionId, + double x, double y, double z, double rSquared); + + // Description: + // Compute a list of the Ids of all regions that + // intersect the specified sphere. The sphere is given + // by it's center and the square of it's radius. + // Returns: the number of ids in the list. + int IntersectsSphere2(int *ids, int len, + double x, double y, double z, double rSquared); + + // Description: + // Determine whether a region of the spatial decomposition + // intersects the given cell. If you already + // know the region that the cell centroid lies in, provide + // that as the last argument to make the computation quicker. + int IntersectsCell(int regionId, vtkCell *cell, int cellRegion=-1); + + // Description: + // Compute a list of the Ids of all regions that + // intersect the given cell. If you alrady + // know the region that the cell centroid lies in, provide + // that as the last argument to make the computation quicker. + // Returns the number of regions the cell intersects. + int IntersectsCell(int *ids, int len, vtkCell *cell, int cellRegion=-1); + + // Description: + // When computing the intersection of k-d tree regions with other + // objects, we use the spatial bounds of the region. To use the + // tighter bound of the bounding box of the data within the region, + // set this variable ON. (Specifying data bounds in the vtkBSPCuts + // object is optional. If data bounds were not specified, this + // option has no meaning.) + + vtkGetMacro(ComputeIntersectionsUsingDataBounds, int); + void SetComputeIntersectionsUsingDataBounds(int c); + void ComputeIntersectionsUsingDataBoundsOn(); + void ComputeIntersectionsUsingDataBoundsOff(); + +protected: + + vtkBSPIntersections(); + ~vtkBSPIntersections(); + + vtkGetMacro(RegionListBuildTime, unsigned long); + + int BuildRegionList(); + + vtkKdNode **GetRegionList(){return this->RegionList;} + + double CellBoundsCache[6]; // to speed cell intersection queries + +//BTX + enum { + XDIM = 0, // don't change these values + YDIM = 1, + ZDIM = 2 + }; +//ETX + +private: + + static int NumberOfLeafNodes(vtkKdNode *kd); + static void SetIDRanges(vtkKdNode *kd, int &min, int &max); + + int SelfRegister(vtkKdNode *kd); + + static void SetCellBounds(vtkCell *cell, double *bounds); + + int _IntersectsBox(vtkKdNode *node, int *ids, int len, + double x0, double x1, + double y0, double y1, + double z0, double z1); + + int _IntersectsSphere2(vtkKdNode *node, int *ids, int len, + double x, double y, double z, double rSquared); + + int _IntersectsCell(vtkKdNode *node, int *ids, int len, + vtkCell *cell, int cellRegion=-1); + + vtkBSPCuts *Cuts; + + int NumberOfRegions; + vtkKdNode **RegionList; + + vtkTimeStamp RegionListBuildTime; + + int ComputeIntersectionsUsingDataBounds; + + vtkBSPIntersections(const vtkBSPIntersections&); // Not implemented + void operator=(const vtkBSPIntersections&); // Not implemented +}; +#endif diff --git a/Graphics/vtkBandedPolyDataContourFilter.cxx b/Graphics/vtkBandedPolyDataContourFilter.cxx new file mode 100644 index 0000000..aa85c9e --- /dev/null +++ b/Graphics/vtkBandedPolyDataContourFilter.cxx @@ -0,0 +1,820 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBandedPolyDataContourFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBandedPolyDataContourFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkEdgeTable.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkTriangleStrip.h" +#include "vtkDoubleArray.h" + +#include + +vtkCxxRevisionMacro(vtkBandedPolyDataContourFilter, "$Revision: 1.54 $"); +vtkStandardNewMacro(vtkBandedPolyDataContourFilter); + +// Construct object. +vtkBandedPolyDataContourFilter::vtkBandedPolyDataContourFilter() +{ + this->ContourValues = vtkContourValues::New(); + this->Clipping = 0; + this->ScalarMode = VTK_SCALAR_MODE_INDEX; + + this->SetNumberOfOutputPorts(2); + + vtkPolyData *output2 = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(1, output2); + output2->Delete(); + this->ClipTolerance = FLT_EPSILON; + this->GenerateContourEdges = 0; +} + +vtkBandedPolyDataContourFilter::~vtkBandedPolyDataContourFilter() +{ + this->ContourValues->Delete(); +} + +int vtkBandedPolyDataContourFilter::ComputeScalarIndex(double val) +{ + + for (int i=0; i < (this->NumberOfClipValues-1); i++) + { + if ( val >= this->ClipValues[i] && val < this->ClipValues[i+1] ) + { + return i; + } + } + return this->NumberOfClipValues - 1; + +} + +int vtkBandedPolyDataContourFilter::IsContourValue(double val) +{ + int i; + + // Check to see whether a vertex is an intersection point. + for ( i=0; i < this->NumberOfClipValues; i++) + { + if ( val == this->ClipValues[i] ) + { + return 1; + } + } + return 0; +} + +// Return a flag that indicates that the ordering of vertices along the +// edge is not from v1->v2, where v1 < v2. +int vtkBandedPolyDataContourFilter::ClipEdge(int v1, int v2, + vtkPoints *newPts, + vtkDataArray *inScalars, + vtkDoubleArray *outScalars, + vtkPointData *inPD, + vtkPointData *outPD) +{ + double x[3], t, sNew; + double x1[3], x2[3]; + int ptId; + int reverse = (v1 < v2 ? 0 : 1); + + newPts->GetPoint(v1, x1); + newPts->GetPoint(v2, x2); + + double s1 = inScalars->GetTuple1(v1); + double s2 = inScalars->GetTuple1(v2); + + if ( s1 <= s2 ) + { + int idx1 = this->ComputeScalarIndex(s1); + int idx2 = this->ComputeScalarIndex(s2); + + for (int i=1; i < (idx2-idx1+1); i++) + { + t = (this->ClipValues[idx1+i] - s1) / (s2 - s1); + x[0] = x1[0] + t*(x2[0]-x1[0]); + x[1] = x1[1] + t*(x2[1]-x1[1]); + x[2] = x1[2] + t*(x2[2]-x1[2]); + ptId = newPts->InsertNextPoint(x); + outPD->InterpolateEdge(inPD,ptId,v1,v2,t); + // We cannot use directly s1 + t*(s2-s1) as is causes rounding error + sNew = this->ClipValues[idx1+i]; + outScalars->InsertTuple1(ptId,sNew); + } + return reverse; + } + else + { + int idx1 = this->ComputeScalarIndex(s1); + int idx2 = this->ComputeScalarIndex(s2); + + for (int i=1; i < (idx1-idx2+1); i++) + { + t = (this->ClipValues[idx2+i] - s1) / (s2 - s1); + x[0] = x1[0] + t*(x2[0]-x1[0]); + x[1] = x1[1] + t*(x2[1]-x1[1]); + x[2] = x1[2] + t*(x2[2]-x1[2]); + ptId = newPts->InsertNextPoint(x); + outPD->InterpolateEdge(inPD,ptId,v1,v2,t); + // We cannot use directly s1 + t*(s2-s1) as is causes rounding error + sNew = this->ClipValues[idx2+i]; + outScalars->InsertTuple1(ptId,sNew); + } + return ((reverse+1) % 2); + } +} + + +extern "C" { +int vtkCompareClipValues(const void *val1, const void *val2) +{ + if ( *((double*)val1) < *((double*)val2) ) + { + return (-1); + } + else if ( *((double*)val1) > *((double*)val2) ) + { + return (1); + } + else + { + return (0); + } +} +} + +inline int vtkBandedPolyDataContourFilter::InsertCell(vtkCellArray *cells, + int npts, vtkIdType *pts, + int cellId, double s, + vtkFloatArray *newS) +{ + + int idx = this->ComputeScalarIndex(s+this->ClipTolerance); + + if ( !this->Clipping || + idx >= this->ClipIndex[0] && idx < this->ClipIndex[1] ) + { + cells->InsertNextCell(npts,pts); + + if ( this->ScalarMode == VTK_SCALAR_MODE_INDEX ) + { + newS->InsertTuple1(cellId++,idx); + } + else + { + newS->InsertTuple1(cellId++,this->ClipValues[idx]); + } + } + return cellId; +} + + +// Create filled contours for polydata +int vtkBandedPolyDataContourFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd = input->GetPointData(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *outCD = output->GetCellData(); + vtkPoints *inPts = input->GetPoints(); + vtkDataArray *inScalars = pd->GetScalars(); + int abort=0; + vtkPoints *newPts; + int i, j, idx=0; + vtkIdType npts = 0; + vtkIdType cellId=0; + vtkIdType *pts = 0; + int numEdgePts, numNewPts, maxCellSize; + vtkIdType v, vR, *intPts; + int intsIdx, reverse; + vtkIdType intLoc; + vtkIdType numIntPts, intsInc; + vtkIdType numPts, numCells, estimatedSize; + + vtkDebugMacro(<<"Executing banded contour filter"); + + // Check input + // + + numCells = input->GetNumberOfCells(); + if ( !inPts || (numPts=inPts->GetNumberOfPoints()) < 1 || + !inScalars || numCells < 1 ) + { + vtkErrorMacro(<<"No input data!"); + return 1; + } + + // Set up supplemental data structures for processing edge/generating + // intersections. First we sort the contour values into an ascending + // list of clip values including the extreme min/max values. + this->NumberOfClipValues = this->ContourValues->GetNumberOfContours() + 2; + this->ClipValues = new double[this->NumberOfClipValues]; + double range[2]; + inScalars->GetRange(range); + + // base clip tolerance on overall input scalar range + this->ClipTolerance = FLT_EPSILON*(range[1] - range[0]); + + this->ClipValues[0] = + (range[0]ContourValues->GetValue(0))? + (range[0]): + (this->ContourValues->GetValue(0)); + + this->ClipValues[this->NumberOfClipValues - 1] = + (range[1]>this->ContourValues->GetValue(this->NumberOfClipValues-2-1))? + (range[1]): + (this->ContourValues->GetValue(this->NumberOfClipValues-2-1)); + + for ( i=1; iNumberOfClipValues-1; i++) + { + this->ClipValues[i] = this->ContourValues->GetValue(i-1); + } + + qsort((void *)this->ClipValues, this->NumberOfClipValues, sizeof(double), + vtkCompareClipValues); + + // toss out values which are too close together, currently within FLT_EPSILON% + // of each other based on full scalar range, but could define temporary based + // on percentage of scalar range... + for ( i=0; i<(this->NumberOfClipValues-1); i++) + { + if ( (this->ClipValues[i] + this->ClipTolerance) >= this->ClipValues[i+1] ) + { + for (j=i+1; j<(this->NumberOfClipValues-2); j++) + { + this->ClipValues[j] = this->ClipValues[j+1]; + } + this->NumberOfClipValues--; + } + } + + this->ClipIndex[0] = + this->ComputeScalarIndex(this->ContourValues->GetValue(0)); + this->ClipIndex[1] = this->ComputeScalarIndex( + this->ContourValues->GetValue(this->ContourValues->GetNumberOfContours()-1)); + + // + // Estimate allocation size, stolen from vtkContourGrid... + // + estimatedSize = (vtkIdType) pow ((double) numCells, .9); + estimatedSize *= this->NumberOfClipValues; + estimatedSize = estimatedSize / 1024 * 1024; // multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + // The original set of points and point data are copied. Later on + // intersection points due to clipping will be created. + newPts = vtkPoints::New(); + + // Note: since we use the output scalars in the execution of the algorithm, + // the output point scalars MUST BE double or bad things happen due to + // numerical precision issues. + newPts->Allocate(estimatedSize,estimatedSize); + outPD->CopyScalarsOff(); + outPD->InterpolateAllocate(pd,3*numPts,numPts); + vtkDoubleArray *outScalars = vtkDoubleArray::New(); + outScalars->Allocate(3*numPts,numPts); + outPD->SetScalars(outScalars); + + for (i=0; iInsertPoint(i,inPts->GetPoint(i)); + outPD->CopyData(pd, i, i); + outScalars->InsertTuple1(i, inScalars->GetTuple1(i)); + } + + // These are the new cell scalars + vtkFloatArray *newScalars = vtkFloatArray::New(); + newScalars->Allocate(numCells*5,numCells); + newScalars->SetName("Scalars"); + + // Used to keep track of intersections + vtkEdgeTable *edgeTable = vtkEdgeTable::New(); + vtkCellArray *intList = vtkCellArray::New(); //intersection point ids + + // All vertices are filled and passed through; poly-vertices are broken + // into single vertices. Cell data per vertex is set. + // + if ( input->GetVerts()->GetNumberOfCells() > 0 ) + { + vtkCellArray *verts = input->GetVerts(); + vtkCellArray *newVerts = vtkCellArray::New(); + newVerts->Allocate(verts->GetSize()); + for ( verts->InitTraversal(); verts->GetNextCell(npts,pts) && !abort; + abort=this->GetAbortExecute() ) + { + for (i=0; iInsertNextCell(1,pts+i); + idx = this->ComputeScalarIndex(inScalars->GetTuple1(pts[i])); + newScalars->InsertTuple1(cellId++,idx); + } + } + output->SetVerts(newVerts); + newVerts->Delete(); + } + this->UpdateProgress(0.05); + + // Lines are chopped into line segments. + // + if ( input->GetLines()->GetNumberOfCells() > 0 ) + { + vtkCellArray *lines = input->GetLines(); + + maxCellSize = lines->GetMaxCellSize(); + maxCellSize *= (1 + this->NumberOfClipValues); + + vtkIdType *fullLine = new vtkIdType [maxCellSize]; + vtkCellArray *newLines = vtkCellArray::New(); + newLines->Allocate(lines->GetSize()); + edgeTable->InitEdgeInsertion(numPts,1); //store attributes on edge + + //start by generating intersection points + for ( lines->InitTraversal(); lines->GetNextCell(npts,pts) && !abort; + abort=this->GetAbortExecute() ) + { + for (i=0; i<(npts-1); i++) + { + numNewPts = newPts->GetNumberOfPoints(); + reverse = this->ClipEdge(pts[i],pts[i+1],newPts,inScalars,outScalars, + pd,outPD); + numEdgePts = newPts->GetNumberOfPoints() - numNewPts; + if ( numEdgePts > 0 ) //there is an intersection + { + if ( !reverse ) + { + for (j=0; jInsertNextCell(numEdgePts,fullLine); + edgeTable->InsertEdge(pts[i],pts[i+1], //associate ints with edge + intList->GetInsertLocation(numEdgePts)); + } + else //no intersection points along the edge + { + edgeTable->InsertEdge(pts[i],pts[i+1],-1); //-1 means no points + } + }//for all line segments in this line + } + + //now create line segments + for ( lines->InitTraversal(); lines->GetNextCell(npts,pts) && !abort; + abort=this->GetAbortExecute() ) + { + for (i=0; i<(npts-1); i++) + { + v = pts[i]; + vR = pts[i+1]; + + newLines->InsertNextCell(2); + + newScalars->InsertTuple1(cellId++, + this->ComputeScalarIndex(outScalars->GetTuple1(v))); + newLines->InsertCellPoint(v); + + if ( (intLoc=edgeTable->IsEdge(v,vR)) != -1 ) + { + intList->GetCell(intLoc,numIntPts,intPts); + if ( v < vR ) {intsIdx = 0; intsInc=1;} //order of the edge + else {intsIdx=numIntPts-1; intsInc=(-1);} + + for ( ; intsIdx >= 0 && intsIdx < numIntPts; intsIdx += intsInc ) + { + newLines->InsertCellPoint(intPts[intsIdx]); + newLines->InsertNextCell(2); + + newScalars->InsertTuple1(cellId++, this->ComputeScalarIndex( + outScalars->GetTuple1(intPts[intsIdx]))); + newLines->InsertCellPoint(intPts[intsIdx]); + } + } + newLines->InsertCellPoint(vR); + } + } + + delete [] fullLine; + + output->SetLines(newLines); + newLines->Delete(); + } + this->UpdateProgress(0.1); + + // Polygons are assumed convex and chopped into filled, convex polygons. + // Triangle strips are treated similarly. + // + int numPolys = input->GetPolys()->GetNumberOfCells(); + int numStrips = input->GetStrips()->GetNumberOfCells(); + if ( numPolys > 0 || numStrips > 0 ) + { + // Set up processing. We are going to store an ordered list of + // intersections along each edge (ordered from smallest point id + // to largest). These will later be connected into convex polygons + // which represent a filled region in the cell. + // + edgeTable->InitEdgeInsertion(numPts,1); //store attributes on edge + intList->Reset(); + + vtkCellArray *polys = input->GetPolys(); + vtkCellArray *tmpPolys = NULL; + + // If contour edges requested, set things up. + vtkCellArray *contourEdges=0; + if ( this->GenerateContourEdges ) + { + contourEdges = vtkCellArray::New(); + contourEdges->Allocate(numCells); + this->GetContourEdgesOutput()->SetLines(contourEdges); + contourEdges->Delete(); + this->GetContourEdgesOutput()->SetPoints(newPts); + } + + // Set up structures for processing polygons + maxCellSize = polys->GetMaxCellSize(); + if( maxCellSize == 0 ) + { + maxCellSize = input->GetStrips()->GetMaxCellSize(); + } + maxCellSize *= (1 + this->NumberOfClipValues); + + vtkIdType *newPolygon = new vtkIdType [maxCellSize]; + double *s = new double [maxCellSize]; //scalars at vertices + int *isContourValue = new int [maxCellSize]; + int *isOriginalVertex = new int [maxCellSize]; + vtkIdType *fullPoly = new vtkIdType [maxCellSize]; + + // Lump strips and polygons together. + // Decompose strips into triangles. + if ( numStrips > 0 ) + { + vtkCellArray *strips = input->GetStrips(); + tmpPolys = vtkCellArray::New(); + if ( numPolys > 0 ) + { + tmpPolys->DeepCopy(polys); + } + else + { + tmpPolys->Allocate(polys->EstimateSize(numStrips,5)); + } + for ( strips->InitTraversal(); strips->GetNextCell(npts,pts); ) + { + vtkTriangleStrip::DecomposeStrip(npts, pts, tmpPolys); + } + polys = tmpPolys; + } + + // Process polygons to produce edge intersections.------------------------ + // + numPolys = polys->GetNumberOfCells(); + vtkIdType updateCount = numPolys/20 + 1; + vtkIdType count=0; + for ( polys->InitTraversal(); polys->GetNextCell(npts,pts) && !abort; + abort=this->GetAbortExecute() ) + { + if ( ! (++count % updateCount) ) + { + this->UpdateProgress(0.1 + 0.45*((double)count/numPolys)); + } + + for (i=0; iIsEdge(v,vR) == -1 ) + { + numNewPts = newPts->GetNumberOfPoints(); + reverse = this->ClipEdge(v,vR,newPts,inScalars,outScalars,pd,outPD); + numEdgePts = newPts->GetNumberOfPoints() - numNewPts; + if ( numEdgePts > 0 ) + { + if ( !reverse ) + { + for (j=0; jInsertNextCell(numEdgePts,fullPoly); + edgeTable->InsertEdge(v,vR, //associate ints with edge + intList->GetInsertLocation(numEdgePts)); + } + else //no intersection points along the edge + { + edgeTable->InsertEdge(v,vR,-1); //-1 means no points + } + }//if edge not processed yet + } + }//for all polygons + + // Process polygons to produce output triangles------------------------ + // + vtkCellArray *newPolys = vtkCellArray::New(); + newPolys->Allocate(polys->GetSize()); + int intersectionPoint; + int mL, mR, m2L, m2R; + int numPointsToAdd, numLeftPointsToAdd, numRightPointsToAdd; + int numPolyPoints, numFullPts; + count = 0; + for ( polys->InitTraversal(); polys->GetNextCell(npts,pts) && !abort; + abort=this->GetAbortExecute() ) + { + if ( ! (++count % updateCount) ) + { + this->UpdateProgress(0.55 + 0.45*((double)count/numPolys)); + } + + //Create a new polygon that includes all the points including the + //intersection vertices. This hugely simplifies the logic of the + //code. + for ( intersectionPoint=0, numFullPts=0, i=0; iGetTuple1(v); + isContourValue[numFullPts] = this->IsContourValue(s[numFullPts]); + isOriginalVertex[numFullPts] = 1; + fullPoly[numFullPts++] = v; + + //see whether intersection points need to be added. + if ( (intLoc=edgeTable->IsEdge(v,vR)) != -1 ) + { + intersectionPoint = 1; + intList->GetCell(intLoc,numIntPts,intPts); + if ( v < vR ) {intsIdx = 0; intsInc=1;} //order of the edge + else {intsIdx=numIntPts-1; intsInc=(-1);} + for ( ; intsIdx >= 0 && intsIdx < numIntPts; intsIdx += intsInc ) + { + s[numFullPts] = outScalars->GetTuple1(intPts[intsIdx]); + isContourValue[numFullPts] = 1; + isOriginalVertex[numFullPts] = 0; + fullPoly[numFullPts++] = intPts[intsIdx]; + } + } + } //for all points and edges + + //Very important: have to find the right starting vertex. The vertex + //needs to be one where the contour values increase in both directions. + //Really should check whether the vertex is convex. + double minValue=VTK_DOUBLE_MAX; + for ( i=0; iInsertCell(newPolys,npts,pts,cellId,s[idx],newScalars); + continue; + } + + //Produce contour edges if requested + if ( this->GenerateContourEdges ) + { + for (i=0; i < numFullPts; i++) + { + if ( isContourValue[i] && isContourValue[(i+1)%numFullPts] && + s[i] == s[(i+1)%numFullPts] ) + { + contourEdges->InsertNextCell(2); + contourEdges->InsertCellPoint(fullPoly[i]); + contourEdges->InsertCellPoint(fullPoly[(i+1)%numFullPts]); + } + } + } + + //Find the first intersection points in the polygons starting + //from this vertex and build a polygon. + numPointsToAdd = 1; + for ( mR=idx, intersectionPoint=0; !intersectionPoint; ) + { + numPointsToAdd++; + mR = (mR + 1) % numFullPts; + if ( isContourValue[mR] && s[mR] != s[idx] ) intersectionPoint = 1; + } + for ( mL=idx, intersectionPoint=0; !intersectionPoint; ) + { + numPointsToAdd++; + mL = (mL + numFullPts - 1) % numFullPts; + if ( isContourValue[mL] && s[mL] != s[idx] ) intersectionPoint = 1; + } + for ( numPolyPoints=0, i=0; i= 3) + { + cellId = this->InsertCell(newPolys,numPolyPoints,newPolygon, + cellId,s[idx],newScalars); + } + if ( this->GenerateContourEdges ) + { + contourEdges->InsertNextCell(2); + contourEdges->InsertCellPoint(fullPoly[mR]); + contourEdges->InsertCellPoint(fullPoly[mL]); + } + + //We've got an edge (mL,mR) that marks the edge of the region not yet + //clipped. We move this edge forward from intersection point to + //intersection point. + m2R = mR; + m2L = mL; + while ( m2R != m2L ) + { + numPointsToAdd = (mL > mR ? mL-mR+1 : numFullPts-(mR-mL)+1); + if ( numPointsToAdd == 3 ) + {//just a triangle left + for (i=0; iInsertCell(newPolys,numPointsToAdd,newPolygon, + cellId,s[mR],newScalars); + if ( this->GenerateContourEdges ) + { + contourEdges->InsertNextCell(2); + contourEdges->InsertCellPoint(fullPoly[mR]); + contourEdges->InsertCellPoint(fullPoly[mL]); + } + break; + } + else //find the next intersection points + { + numLeftPointsToAdd = 0; + numRightPointsToAdd = 0; + for ( intersectionPoint=0; + !intersectionPoint && ((m2R+1)%numFullPts) != m2L; ) + { + numRightPointsToAdd++; + m2R = (m2R + 1) % numFullPts; + if ( isContourValue[m2R] ) intersectionPoint = 1; + } + for ( intersectionPoint=0; + !intersectionPoint && ((m2L+numFullPts-1)%numFullPts) != m2R; ) + { + numLeftPointsToAdd++; + m2L = (m2L + numFullPts - 1) % numFullPts; + if ( isContourValue[m2L] ) intersectionPoint = 1; + } + + //specify the polygon vertices. From m2L to mL, then mR to m2R. + for ( numPolyPoints=0, i=0; iInsertCell(newPolys,numPolyPoints,newPolygon, + cellId,s[mR],newScalars); + if ( this->GenerateContourEdges ) + { + contourEdges->InsertNextCell(2); + contourEdges->InsertCellPoint(fullPoly[mR]); + contourEdges->InsertCellPoint(fullPoly[mL]); + } + mL = m2L; + mR = m2R; + }//add a polygon + }//while still removing polygons + }//for all polygons + + delete [] s; + delete [] newPolygon; + delete [] isContourValue; + delete [] isOriginalVertex; + delete [] fullPoly; + outScalars->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + if ( tmpPolys ) {tmpPolys->Delete(); } + }//for all polygons (and strips) in input + + vtkDebugMacro(<<"Created " << cellId << " total cells\n"); + vtkDebugMacro(<<"Created " << output->GetVerts()->GetNumberOfCells() + << " verts\n"); + vtkDebugMacro(<<"Created " << output->GetLines()->GetNumberOfCells() + << " lines\n"); + vtkDebugMacro(<<"Created " << output->GetPolys()->GetNumberOfCells() + << " polys\n"); + vtkDebugMacro(<<"Created " << output->GetStrips()->GetNumberOfCells() + << " strips\n"); + + // Update ourselves and release temporary memory + // + delete [] this->ClipValues; + intList->Delete(); + edgeTable->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + + int arrayIdx = outCD->AddArray(newScalars); + outCD->SetActiveAttribute(arrayIdx, vtkDataSetAttributes::SCALARS); + + newScalars->Delete(); + + output->Squeeze(); + + return 1; +} + +vtkPolyData *vtkBandedPolyDataContourFilter::GetContourEdgesOutput() +{ + if (this->GetNumberOfOutputPorts() < 2) + { + return NULL; + } + + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + +unsigned long int vtkBandedPolyDataContourFilter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + time = this->ContourValues->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + + return mTime; +} + +void vtkBandedPolyDataContourFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Generate Contour Edges: " + << (this->GenerateContourEdges ? "On\n" : "Off\n"); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Clipping: " << (this->Clipping ? "On\n" : "Off\n"); + + os << indent << "Scalar Mode: "; + if ( this->ScalarMode == VTK_SCALAR_MODE_INDEX ) + { + os << "INDEX\n"; + } + else + { + os << "VALUE\n"; + } +} diff --git a/Graphics/vtkBandedPolyDataContourFilter.h b/Graphics/vtkBandedPolyDataContourFilter.h new file mode 100644 index 0000000..c88a0ce --- /dev/null +++ b/Graphics/vtkBandedPolyDataContourFilter.h @@ -0,0 +1,204 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBandedPolyDataContourFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBandedPolyDataContourFilter - generate filled contours for vtkPolyData +// .SECTION Description +// vtkBandedPolyDataContourFilter is a filter that takes as input vtkPolyData +// and produces as output filled contours (also represented as vtkPolyData). +// Filled contours are bands of cells that all have the same cell scalar +// value, and can therefore be colored the same. The method is also referred +// to as filled contour generation. +// +// To use this filter you must specify one or more contour values. You can +// either use the method SetValue() to specify each contour value, or use +// GenerateValues() to generate a series of evenly spaced contours. Each +// contour value divides (or clips) the data into two pieces, values below +// the contour value, and values above it. The scalar values of each +// band correspond to the specified contour value. Note that if the first and +// last contour values are not the minimum/maximum contour range, then two +// extra contour values are added corresponding to the minimum and maximum +// range values. These extra contour bands can be prevented from being output +// by turning clipping on. +// +// .SECTION See Also +// vtkClipDataSet vtkClipPolyData vtkClipVolume vtkContourFilter +// +#ifndef __vtkBandedPolyDataContourFilter_h +#define __vtkBandedPolyDataContourFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for inline methods + +class vtkPoints; +class vtkCellArray; +class vtkPointData; +class vtkDataArray; +class vtkFloatArray; +class vtkDoubleArray; + +#define VTK_SCALAR_MODE_INDEX 0 +#define VTK_SCALAR_MODE_VALUE 1 + +class VTK_GRAPHICS_EXPORT vtkBandedPolyDataContourFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkBandedPolyDataContourFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with no contours defined. + static vtkBandedPolyDataContourFilter *New(); + + // Description: + // Methods to set / get contour values. A single value at a time can be + // set with SetValue(). Multiple contour values can be set with + // GenerateValues(). Note that GenerateValues() generates n values + // inclusive of the start and end range values. + void SetValue(int i, double value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Description: + // Indicate whether to clip outside the range specified by the user. + // (The range is contour value[0] to contour value[numContours-1].) + // Clipping means all cells outside of the range specified are not + // sent to the output. + vtkSetMacro(Clipping,int); + vtkGetMacro(Clipping,int); + vtkBooleanMacro(Clipping,int); + + // Description: + // Control whether the cell scalars are output as an integer index or + // a scalar value. If an index, the index refers to the bands produced + // by the clipping range. If a value, then a scalar value which is a + // value between clip values is used. + vtkSetClampMacro(ScalarMode,int,VTK_SCALAR_MODE_INDEX,VTK_SCALAR_MODE_VALUE); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToIndex() + {this->SetScalarMode(VTK_SCALAR_MODE_INDEX);} + void SetScalarModeToValue() + {this->SetScalarMode(VTK_SCALAR_MODE_VALUE);} + + // Description: + // Turn on/off a flag to control whether contour edges are generated. + // Contour edges are the edges between bands. If enabled, they are + // generated from polygons/triangle strips and placed into the second + // output (the ContourEdgesOutput). + vtkSetMacro(GenerateContourEdges,int); + vtkGetMacro(GenerateContourEdges,int); + vtkBooleanMacro(GenerateContourEdges,int); + + // Description: + // Get the second output which contains the edges dividing the contour + // bands. This output is empty unless GenerateContourEdges is enabled. + vtkPolyData *GetContourEdgesOutput(); + + // Description: + // Overload GetMTime because we delegate to vtkContourValues so its + // modified time must be taken into account. + unsigned long GetMTime(); + +protected: + vtkBandedPolyDataContourFilter(); + ~vtkBandedPolyDataContourFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int ComputeScalarIndex(double); + int IsContourValue(double val); + int ClipEdge(int v1, int v2, vtkPoints *pts, vtkDataArray *inScalars, + vtkDoubleArray *outScalars, + vtkPointData *inPD, vtkPointData *outPD); + int InsertCell(vtkCellArray *cells, int npts, vtkIdType *pts, + int cellId, double s, vtkFloatArray *newS); + + // data members + vtkContourValues *ContourValues; + + int Clipping; + int ScalarMode; + + // sorted and cleaned contour values + double *ClipValues; + int NumberOfClipValues; + int ClipIndex[2]; //indices outside of this range (inclusive) are clipped + double ClipTolerance; //used to clean up numerical problems + + //the second output + int GenerateContourEdges; + +private: + vtkBandedPolyDataContourFilter(const vtkBandedPolyDataContourFilter&); // Not implemented. + void operator=(const vtkBandedPolyDataContourFilter&); // Not implemented. +}; + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value);} + +// Description: +// Get the ith contour value. +inline double vtkBandedPolyDataContourFilter::GetValue(int i) + {return this->ContourValues->GetValue(i);} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +inline double *vtkBandedPolyDataContourFilter::GetValues() + {return this->ContourValues->GetValues();} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +inline void vtkBandedPolyDataContourFilter::GetValues(double *contourValues) + {this->ContourValues->GetValues(contourValues);} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +inline void vtkBandedPolyDataContourFilter::SetNumberOfContours(int number) + {this->ContourValues->SetNumberOfContours(number);} + +// Description: +// Get the number of contours in the list of contour values. +inline int vtkBandedPolyDataContourFilter::GetNumberOfContours() + {return this->ContourValues->GetNumberOfContours();} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkBandedPolyDataContourFilter::GenerateValues(int numContours, + double range[2]) + {this->ContourValues->GenerateValues(numContours, range);} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkBandedPolyDataContourFilter::GenerateValues(int numContours, + double rangeStart, + double rangeEnd) + {this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + +#endif diff --git a/Graphics/vtkBlankStructuredGrid.cxx b/Graphics/vtkBlankStructuredGrid.cxx new file mode 100644 index 0000000..78dc404 --- /dev/null +++ b/Graphics/vtkBlankStructuredGrid.cxx @@ -0,0 +1,165 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBlankStructuredGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBlankStructuredGrid.h" + +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStructuredGrid.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkBlankStructuredGrid, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkBlankStructuredGrid); + +// Construct object to extract all of the input data. +vtkBlankStructuredGrid::vtkBlankStructuredGrid() +{ + this->MinBlankingValue = VTK_LARGE_FLOAT; + this->MaxBlankingValue = VTK_LARGE_FLOAT; + this->ArrayName = NULL; + this->ArrayId = -1; + this->Component = 0; +} + +vtkBlankStructuredGrid::~vtkBlankStructuredGrid() +{ + if ( this->ArrayName ) + { + delete [] this->ArrayName; + this->ArrayName = NULL; + } +} + + +template +void vtkBlankStructuredGridExecute(vtkBlankStructuredGrid *vtkNotUsed(self), + T *dptr, int numPts, int numComp, + int comp, double min, double max, + vtkUnsignedCharArray *blanking) +{ + T compValue; + dptr += comp; + + for ( int ptId=0; ptId < numPts; ptId++, dptr+=numComp) + { + compValue = *dptr; + if ( compValue >= min && compValue <= max ) + { + blanking->SetValue(ptId,0); //make it invisible + } + else + { + blanking->SetValue(ptId,1); + } + } +} + + +int vtkBlankStructuredGrid::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(); + vtkCellData *cd=input->GetCellData(); + vtkPointData *outPD=output->GetPointData(); + vtkCellData *outCD=output->GetCellData(); + int numPts = input->GetNumberOfPoints(); + vtkDataArray *dataArray=NULL; + int numComp; + + vtkDebugMacro(<< "Blanking Grid"); + + // Pass input to output + // + output->CopyStructure(input); + outPD->PassData(pd); + outCD->PassData(cd); + + // Get the appropriate data array + // + if ( this->ArrayName != NULL ) + { + dataArray = pd->GetArray(this->ArrayName); + } + else if ( this->ArrayId >= 0 ) + { + dataArray = pd->GetArray(this->ArrayId); + } + + if ( !dataArray || + (numComp=dataArray->GetNumberOfComponents()) <= this->Component ) + { + vtkWarningMacro(<<"Data array not found"); + return 1; + } + void *dptr = dataArray->GetVoidPointer(0); + + // Loop over the data array setting anything within the data range specified + // to be blanked. + // + vtkUnsignedCharArray *blanking = vtkUnsignedCharArray::New(); + blanking->SetNumberOfValues(numPts); + + // call templated function + switch (dataArray->GetDataType()) + { + vtkTemplateMacro( + vtkBlankStructuredGridExecute(this, (VTK_TT *)(dptr), numPts, + numComp, this->Component, + this->MinBlankingValue, + this->MaxBlankingValue, blanking)); + default: + break; + } + + // Clean up and get out + output->SetPointVisibilityArray(blanking); + blanking->Delete(); + + return 1; +} + + +void vtkBlankStructuredGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Min Blanking Value: " << this->MinBlankingValue << "\n"; + os << indent << "Max Blanking Value: " << this->MaxBlankingValue << "\n"; + os << indent << "Array Name: "; + if ( this->ArrayName ) + { + os << this->ArrayName << "\n"; + } + else + { + os << "(none)\n"; + } + os << indent << "Array ID: " << this->ArrayId << "\n"; + os << indent << "Component: " << this->Component << "\n"; +} diff --git a/Graphics/vtkBlankStructuredGrid.h b/Graphics/vtkBlankStructuredGrid.h new file mode 100644 index 0000000..d144b7c --- /dev/null +++ b/Graphics/vtkBlankStructuredGrid.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBlankStructuredGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBlankStructuredGrid - translate point attribute data into a blanking field + +// .SECTION Description +// vtkBlankStructuredGrid is a filter that sets the blanking field in a +// vtkStructuredGrid dataset. The blanking field is set by examining a +// specified point attribute data array (e.g., scalars) and converting +// values in the data array to either a "1" (visible) or "0" (blanked) value +// in the blanking array. The values to be blanked are specified by giving +// a min/max range. All data values in the data array indicated and laying +// within the range specified (inclusive on both ends) are translated to +// a "off" blanking value. + +// .SECTION See Also +// vtkStructuredGrid + +#ifndef __vtkBlankStructuredGrid_h +#define __vtkBlankStructuredGrid_h + +#include "vtkStructuredGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkBlankStructuredGrid : public vtkStructuredGridAlgorithm +{ +public: + static vtkBlankStructuredGrid *New(); + vtkTypeRevisionMacro(vtkBlankStructuredGrid,vtkStructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the lower data value in the data array specified which will be + // converted into a "blank" (or off) value in the blanking array. + vtkSetMacro(MinBlankingValue,double); + vtkGetMacro(MinBlankingValue,double); + + // Description: + // Specify the upper data value in the data array specified which will be + // converted into a "blank" (or off) value in the blanking array. + vtkSetMacro(MaxBlankingValue,double); + vtkGetMacro(MaxBlankingValue,double); + + // Description: + // Specify the data array name to use to generate the blanking + // field. Alternatively, you can specify the array id. (If both are set, + // the array name takes precedence.) + vtkSetStringMacro(ArrayName); + vtkGetStringMacro(ArrayName); + + // Description: + // Specify the data array id to use to generate the blanking + // field. Alternatively, you can specify the array name. (If both are set, + // the array name takes precedence.) + vtkSetMacro(ArrayId,int); + vtkGetMacro(ArrayId,int); + + // Description: + // Specify the component in the data array to use to generate the blanking + // field. + vtkSetClampMacro(Component,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(Component,int); + +protected: + vtkBlankStructuredGrid(); + ~vtkBlankStructuredGrid(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double MinBlankingValue; + double MaxBlankingValue; + char *ArrayName; + int ArrayId; + int Component; + +private: + vtkBlankStructuredGrid(const vtkBlankStructuredGrid&); // Not implemented. + void operator=(const vtkBlankStructuredGrid&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkBlankStructuredGridWithImage.cxx b/Graphics/vtkBlankStructuredGridWithImage.cxx new file mode 100644 index 0000000..0745e12 --- /dev/null +++ b/Graphics/vtkBlankStructuredGridWithImage.cxx @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBlankStructuredGridWithImage.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBlankStructuredGridWithImage.h" + +#include "vtkCellData.h" +#include "vtkExecutive.h" +#include "vtkFieldData.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStructuredGrid.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkBlankStructuredGridWithImage, "$Revision: 1.12 $"); +vtkStandardNewMacro(vtkBlankStructuredGridWithImage); + +//---------------------------------------------------------------------------- +vtkBlankStructuredGridWithImage::vtkBlankStructuredGridWithImage() +{ + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +vtkBlankStructuredGridWithImage::~vtkBlankStructuredGridWithImage() +{ +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkBlankStructuredGridWithImage::SetBlankingInput(vtkImageData *input) +{ + this->SetInput(1, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkImageData *vtkBlankStructuredGridWithImage::GetBlankingInput() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +int vtkBlankStructuredGridWithImage::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *imageInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkStructuredGrid *grid = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *image = vtkImageData::SafeDownCast( + imageInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int gridDims[3], imageDims[3]; + + vtkDebugMacro(<< "Adding image blanking"); + + // Perform error checking + grid->GetDimensions(gridDims); + image->GetDimensions(imageDims); + if ( gridDims[0] != imageDims[0] || gridDims[1] != imageDims[1] || + gridDims[2] != imageDims[2] ) + { + vtkErrorMacro("Blanking dimensions must be identical with grid dimensions. " + "Blanking dimensions are " << imageDims[0] << " " + << imageDims[1] << " " << imageDims[2] + << ". Grid dimensions are " << gridDims[0] << " " + << gridDims[1] << " " << gridDims[2] << "."); + return 1; + } + + if ( image->GetScalarType() != VTK_UNSIGNED_CHAR || + image->GetNumberOfScalarComponents() != 1 ) + { + vtkErrorMacro(<<"This filter requires unsigned char images with one component"); + return 1; + } + + // Get the image, set it as the blanking array. + unsigned char *data = (unsigned char *)image->GetScalarPointer(); + vtkUnsignedCharArray *dataArray = vtkUnsignedCharArray::New(); + dataArray->SetArray(data, gridDims[0]*gridDims[1]*gridDims[2], 1); + + output->CopyStructure(grid); + output->GetPointData()->PassData(grid->GetPointData()); + output->GetCellData()->PassData(grid->GetCellData()); + output->SetPointVisibilityArray(dataArray); + + dataArray->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkBlankStructuredGridWithImage::FillInputPortInformation( + int port, vtkInformation *info) +{ + if (port == 0) + { + return this->Superclass::FillInputPortInformation(port, info); + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkBlankStructuredGridWithImage::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkBlankStructuredGridWithImage.h b/Graphics/vtkBlankStructuredGridWithImage.h new file mode 100644 index 0000000..0e45389 --- /dev/null +++ b/Graphics/vtkBlankStructuredGridWithImage.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBlankStructuredGridWithImage.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBlankStructuredGridWithImage - blank a structured grid with an image +// .SECTION Description +// This filter can be used to set the blanking in a structured grid with +// an image. The filter takes two inputs: the structured grid to blank, +// and the image used to set the blanking. Make sure that the dimensions of +// both the image and the structured grid are identical. +// +// Note that the image is interpreted as follows: zero values indicate that +// the structured grid point is blanked; non-zero values indicate that the +// structured grid point is visible. The blanking data must be unsigned char. + +// .SECTION See Also +// vtkStructuredGrid + +#ifndef __vtkBlankStructuredGridWithImage_h +#define __vtkBlankStructuredGridWithImage_h + +#include "vtkStructuredGridAlgorithm.h" + +class vtkImageData; + +class VTK_GRAPHICS_EXPORT vtkBlankStructuredGridWithImage : public vtkStructuredGridAlgorithm +{ +public: + static vtkBlankStructuredGridWithImage *New(); + vtkTypeRevisionMacro(vtkBlankStructuredGridWithImage,vtkStructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the input image used to perform the blanking. + void SetBlankingInput(vtkImageData *input); + vtkImageData *GetBlankingInput(); + +protected: + vtkBlankStructuredGridWithImage(); + ~vtkBlankStructuredGridWithImage(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkBlankStructuredGridWithImage(const vtkBlankStructuredGridWithImage&); // Not implemented. + void operator=(const vtkBlankStructuredGridWithImage&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkBoxClipDataSet.cxx b/Graphics/vtkBoxClipDataSet.cxx new file mode 100644 index 0000000..acef711 --- /dev/null +++ b/Graphics/vtkBoxClipDataSet.cxx @@ -0,0 +1,6414 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBoxClipDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ +#include "vtkBoxClipDataSet.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkGenericCell.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkIdList.h" + +#include + +vtkCxxRevisionMacro(vtkBoxClipDataSet, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkBoxClipDataSet); + +//---------------------------------------------------------------------------- +vtkBoxClipDataSet::vtkBoxClipDataSet() +{ + this->Locator = NULL; + this->GenerateClipScalars = 0; + + this->GenerateClippedOutput = 0; + //this->MergeTolerance = 0.01; + + this->SetNumberOfOutputPorts(2); + vtkUnstructuredGrid *output2 = vtkUnstructuredGrid::New(); + this->GetExecutive()->SetOutputData(1, output2); + output2->Delete(); + + this->Orientation = 1; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//---------------------------------------------------------------------------- +vtkBoxClipDataSet::~vtkBoxClipDataSet() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +//---------------------------------------------------------------------------- +// Do not say we have two outputs unless we are generating the clipped output. +int vtkBoxClipDataSet::GetNumberOfOutputs() +{ + if (this->GenerateClippedOutput) + { + return 2; + } + return 1; +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If Clip functions is modified, +// then this object is modified as well. +unsigned long vtkBoxClipDataSet::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid *vtkBoxClipDataSet::GetClippedOutput() +{ + if (this->GetNumberOfOutputPorts() < 2) + { + return NULL; + } + + return vtkUnstructuredGrid::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + +//---------------------------------------------------------------------------- +// +// Clip by box +// +int vtkBoxClipDataSet::RequestData(vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkUnstructuredGrid *clippedOutput = this->GetClippedOutput(); + + vtkIdType i; + vtkIdType npts; + vtkIdType *pts; + vtkIdType estimatedSize; + vtkIdType newCellId; + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + vtkPointData *inPD=input->GetPointData(), *outPD = output->GetPointData(); + vtkCellData *inCD=input->GetCellData(); + vtkCellData *outCD[2]; + vtkPoints *newPoints; + vtkPoints *cellPts; + vtkIdTypeArray *locs[2]; + vtkDebugMacro( << "Clip by Box\n" ); + vtkUnsignedCharArray *types[2]; + + int j; + int cellType = 0; + int numOutputs = 1; + int inputObjectType = input->GetDataObjectType(); + + // if we have volumes + if (inputObjectType == VTK_STRUCTURED_POINTS || + inputObjectType == VTK_IMAGE_DATA) + { + int dimension; + int *dims = vtkImageData::SafeDownCast(input)->GetDimensions(); + for (dimension=3, i=0; i<3; i++) + { + if ( dims[i] <= 1 ) + { + dimension--; + } + } + } + + // Initialize self; create output objects + // + if ( numPts < 1 ) + { + vtkDebugMacro(<<"No data to clip"); + return 1; + } + + // allocate the output and associated helper classes + estimatedSize = numCells; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + vtkCellArray *conn[2]; + conn[0] = vtkCellArray::New(); + conn[0]->Allocate(estimatedSize,estimatedSize/2); + conn[0]->InitTraversal(); + types[0] = vtkUnsignedCharArray::New(); + types[0]->Allocate(estimatedSize,estimatedSize/2); + locs[0] = vtkIdTypeArray::New(); + locs[0]->Allocate(estimatedSize,estimatedSize/2); + + if ( this->GenerateClippedOutput ) + { + numOutputs = 2; + conn[1] = vtkCellArray::New(); + conn[1]->Allocate(estimatedSize,estimatedSize/2); + conn[1]->InitTraversal(); + types[1] = vtkUnsignedCharArray::New(); + types[1]->Allocate(estimatedSize,estimatedSize/2); + locs[1] = vtkIdTypeArray::New(); + locs[1]->Allocate(estimatedSize,estimatedSize/2); + } + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts,numPts/2); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPoints, input->GetBounds()); + + + vtkDataArray *scalars = this->GetInputArrayToProcess(0,inputVector); + if ( !this->GenerateClipScalars && !scalars) + { + outPD->CopyScalarsOff(); + } + else + { + outPD->CopyScalarsOn(); + } + outPD->InterpolateAllocate(inPD,estimatedSize,estimatedSize/2); + outCD[0] = output->GetCellData(); + outCD[0]->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + if ( this->GenerateClippedOutput ) + { + outCD[1] = clippedOutput->GetCellData(); + outCD[1]->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + } + + //Process all cells and clip each in turn + + vtkIdType updateTime = numCells/20 + 1; // update roughly every 5% + vtkGenericCell *cell = vtkGenericCell::New(); + vtkIdType cellId; + + int abort = 0; + int num[2]; + int numNew[2]; + + num[0] = num[1] = 0; + numNew[0] = numNew[1] = 0; + + unsigned int orientation = this->GetOrientation(); //Test if there is a transformation + + //clock_t init_tmp = clock(); + for (cellId=0; cellId < numCells && !abort; cellId++) + { + if ( !(cellId % updateTime) ) + { + this->UpdateProgress((float)cellId / numCells); + abort = this->GetAbortExecute(); + } + + input->GetCell(cellId,cell); + cellPts = cell->GetPoints(); + npts = cellPts->GetNumberOfPoints(); + + if (this->GenerateClippedOutput) + { + if((cell->GetCellDimension())==3 ) + { + if (orientation) + { + this->ClipHexahedronInOut(newPoints,cell,this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + else + { + this->ClipBoxInOut(newPoints,cell, this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + numNew[1] = conn[1]->GetNumberOfCells() - num[1]; + num[0] = conn[0]->GetNumberOfCells(); + num[1] = conn[1]->GetNumberOfCells(); + } + else if((cell->GetCellDimension())==2 ) + { + if (orientation) + { + this->ClipHexahedronInOut2D(newPoints,cell,this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + else + { + this->ClipBoxInOut2D(newPoints,cell, this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + numNew[1] = conn[1]->GetNumberOfCells() - num[1]; + num[0] = conn[0]->GetNumberOfCells(); + num[1] = conn[1]->GetNumberOfCells(); + } + else if (cell->GetCellDimension() == 1) + { + if (orientation) + { + this->ClipHexahedronInOut1D(newPoints,cell, this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + else + { + this->ClipBoxInOut1D(newPoints,cell, this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + numNew[1] = conn[1]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + num[1] = conn[1]->GetNumberOfCells(); + } + else if (cell->GetCellDimension() == 0) + { + if (orientation) + { + this->ClipHexahedronInOut0D(cell, this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + else + { + this->ClipBoxInOut0D(cell, this->Locator, conn, + inPD, outPD, inCD, cellId, outCD); + } + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + numNew[1] = conn[1]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + num[1] = conn[1]->GetNumberOfCells(); + } + else + { + vtkErrorMacro(<< "Do not support cells of dimension " + << cell->GetCellDimension()); + } + } + else + { + if((cell->GetCellDimension())==3 ) + { + if (orientation) + { + this->ClipHexahedron(newPoints,cell,this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + else + { + this->ClipBox(newPoints,cell, this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + } + else if((cell->GetCellDimension())==2 ) + { + if (orientation) + { + this->ClipHexahedron2D(newPoints,cell,this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + else + { + this->ClipBox2D(newPoints,cell, this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + } + else if (cell->GetCellDimension() == 1) + { + if (orientation) + { + this->ClipHexahedron1D(newPoints,cell, this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + else + { + this->ClipBox1D(newPoints,cell, this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + } + else if (cell->GetCellDimension() == 0) + { + if (orientation) + { + this->ClipHexahedron0D(cell, this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + else + { + this->ClipBox0D(cell, this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0]); + } + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + } + else + { + vtkErrorMacro(<< "Do not support cells of dimension " + << cell->GetCellDimension()); + } + } + + for (i=0 ; iInsertNextValue(conn[i]->GetTraversalLocation()); + conn[i]->GetNextCell(npts,pts); + + //For each new cell added, got to set the type of the cell + switch ( cell->GetCellDimension() ) + { + case 0: //points are generated------------------------------- + cellType = (npts > 1 ? VTK_POLY_VERTEX : VTK_VERTEX); + break; + + case 1: //lines are generated---------------------------------- + cellType = (npts > 2 ? VTK_POLY_LINE : VTK_LINE); + break; + + case 2: //polygons are generated------------------------------ + cellType = (npts == 3 ? VTK_TRIANGLE : + (npts == 4 ? VTK_QUAD : VTK_POLYGON)); + break; + + case 3: //tetrahedra are generated------------------------------ + cellType = VTK_TETRA; + break; + } //switch + + newCellId = types[i]->InsertNextValue(cellType); + outCD[i]->CopyData(inCD, cellId, newCellId); + } //for each new cell + } // for both outputs + } //for each cell + + cell->Delete(); + + output->SetPoints(newPoints); + output->SetCells(types[0], locs[0], conn[0]); + + conn[0]->Delete(); + types[0]->Delete(); + locs[0]->Delete(); + + if ( this->GenerateClippedOutput ) + { + clippedOutput->SetPoints(newPoints); + clippedOutput->SetCells(types[1], locs[1], conn[1]); + conn[1]->Delete(); + types[1]->Delete(); + locs[1]->Delete(); + } + newPoints->Delete(); + this->Locator->Initialize();//release any extra memory + output->Squeeze(); + + return 1; +} + +//---------------------------------------------------------------------------- +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkBoxClipDataSet::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator) + { + return; + } + + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + if ( locator ) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkBoxClipDataSet::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +//---------------------------------------------------------------------------- +// Set the box for clipping +// for each plane, specify the normal and one vertex on the plane. +// +void vtkBoxClipDataSet::SetBoxClip(const double *n0, const double *o0, + const double *n1, const double *o1, + const double *n2, const double *o2, + const double *n3, const double *o3, + const double *n4, const double *o4, + const double *n5, const double *o5) +{ + int i; + + for ( i=0;i<3;i++) + { + this->PlaneNormal[0][i] = n0[i]; + this->PlanePoint[0][i] = o0[i]; + } + for ( i=0;i<3;i++) + { + this->PlaneNormal[1][i] = n1[i]; + this->PlanePoint[1][i] = o1[i]; + } + for ( i=0;i<3;i++) + { + this->PlaneNormal[2][i] = n2[i]; + this->PlanePoint[2][i] = o2[i]; + } + for ( i=0;i<3;i++) + { + this->PlaneNormal[3][i] = n3[i]; + this->PlanePoint[3][i] = o3[i]; + } + for ( i=0;i<3;i++) + { + this->PlaneNormal[4][i] = n4[i]; + this->PlanePoint[4][i] = o4[i]; + } + for ( i=0;i<3;i++) + { + this->PlaneNormal[5][i] = n5[i]; + this->PlanePoint[5][i] = o5[i]; + } +} + +//---------------------------------------------------------------------------- +// Specify the bounding box for clipping + +void vtkBoxClipDataSet::SetBoxClip(double xmin,double xmax, + double ymin,double ymax, + double zmin,double zmax) +{ + this->SetOrientation(0); + this->BoundBoxClip[0][0] = xmin; + this->BoundBoxClip[0][1] = xmax; + this->BoundBoxClip[1][0] = ymin; + this->BoundBoxClip[1][1] = ymax; + this->BoundBoxClip[2][0] = zmin; + this->BoundBoxClip[2][1] = zmax; +} + +//---------------------------------------------------------------------------- +int vtkBoxClipDataSet::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkBoxClipDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + //os << indent << "Merge Tolerance: " << this->MergeTolerance << "\n"; + os << indent << "Orientation: " << this->Orientation << "\n"; + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + os << indent << "Generate Clipped Output: " + << (this->GenerateClippedOutput ? "Yes\n" : "Off\n"); + os << indent << "Generate Clip Scalars: " + << (this->GenerateClipScalars ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +// CellGrid: Subdivide cells in consistent tetrahedra. +// Case : Voxel(11) or Hexahedron(12). +// +// MinEdgF search the smallest vertex index in linear order of a face(4 vertices) +// +void vtkBoxClipDataSet::MinEdgeF(const unsigned int *id_v, + const vtkIdType *cellIds, + unsigned int *edgF) +{ + + int i; + unsigned int id; + int ids; + int min_f; + + ids = 0; + id = id_v[0]; //Face index + min_f = cellIds[id_v[0]]; + + for(i=1; i<4; i++) + { + if(min_f > cellIds[id_v[i]]) + { + min_f = cellIds[id_v[i]]; + id = id_v[i]; + ids= i; + } + } + + switch(ids) + { + case 0: + if(id < id_v[2]) + { + edgF[0] = id; + edgF[1] = id_v[2]; + } + else + { + edgF[0] = id_v[2]; + edgF[1] = id; + } + break; + case 1: + if(id < id_v[3]) + { + edgF[0] = id; + edgF[1] = id_v[3]; + } + else + { + edgF[0] = id_v[3]; + edgF[1] = id; + } + break; + case 2: + if(id < id_v[0]) + { + edgF[0] = id; + edgF[1] = id_v[0]; + } + else + { + edgF[0] = id_v[0]; + edgF[1] = id; + } + break; + case 3: + if(id < id_v[1]) + { + edgF[0] = id; + edgF[1] = id_v[1]; + } + else + { + edgF[0] = id_v[1]; + edgF[1] = id; + } + break; + } +} + +//---------------------------------------------------------------------------- +// CellGrid: Subdivide cells in consistent tetrahedra. +// +// Case : Voxel or Hexahedron: +// if ( subdivide voxel in 6 tetrahedra) +// voxel : 2 wedges (*) +// else +// voxel : 5 tetrahedra +// +// Case : Wedge (*) +// +// ------------------------------------------------ +// +//(*) WedgeToTetra: subdivide one wedge in 3 tetrahedra +// +// wedge : 1 tetrahedron + 1 pyramid = 3 tetrahedra. +// +void vtkBoxClipDataSet::WedgeToTetra(const vtkIdType *wedgeId, + const vtkIdType *cellIds, + vtkCellArray *newCellArray) +{ + int i; + int id; + vtkIdType xmin; + vtkIdType tab[4]; + vtkIdType tabpyram[5]; + + const vtkIdType vwedge[6][4]={ {0, 4, 3, 5}, {1, 4, 3, 5}, {2, 4, 3, 5}, + {3, 0, 1, 2}, {4, 0, 1, 2}, {5, 0, 1, 2} }; + + // the table 'vwedge' set 6 possibilities of the smallest index + // + // v5 + // /\ . + // v3 /..\ v4 + // / / + // v2/\ / + // v0/__\/v1 + // if(v0 index ) is the smallest index: + // wedge is subdivided in: + // 1 tetrahedron-> vwedge[0]: {v0,v4,v3,v5} + // and 1 pyramid -> vert[0] : {v1,v2,v5,v4,v0} + // + + id = 0; + xmin = cellIds[wedgeId[0]]; + for(i=1;i<6;i++) + { + if(xmin > cellIds[wedgeId[i]]) + { + xmin = cellIds[wedgeId[i]];// the smallest global index + id = i; // local index + } + } + for (i =0;i<4;i++) + { + tab[i] = wedgeId[vwedge[id][i]]; + } + newCellArray->InsertNextCell(4,tab); + + // Pyramid :create 2 tetrahedra + const vtkIdType vert[6][5]={ {1, 2, 5, 4, 0}, {2, 0, 3, 5, 1}, + {3, 0, 1, 4, 2}, {1, 2, 5, 4, 3}, + {2, 0, 3, 5, 4}, {3, 0, 1, 4, 5} }; + for(i=0;i<5;i++) + { + tabpyram[i] = wedgeId[vert[id][i]]; + } + this->PyramidToTetra(tabpyram,cellIds,newCellArray); +} + +//---------------------------------------------------------------------------- +// CellGrid: Subdivide cells in consistent tetrahedra. +// +// PyramidToTetra :Subdivide the pyramid in consistent tetrahedra. +// Pyramid : 2 tetrahedra. +// +void vtkBoxClipDataSet::PyramidToTetra(const vtkIdType *pyramId, + const vtkIdType *cellIds, + vtkCellArray *newCellArray) +{ + vtkIdType xmin; + unsigned int i,j,idpy; + vtkIdType tab[4]; + + // the table 'vpy' set 3 possibilities of the smallest index + // vertices{v0,v1,v2,v3,v4}. {v0,v1,v2,v3} is a square face of pyramid + // + // v4 + // ^ + // + // + // v3 _ _ __ _ v2 + // / / + // v0/_ _ _ _ _/v1 + // + // if(v0 index ) is the smallest index: + // the pyramid is subdivided in: + // 2 tetrahedra-> vpy[0]: {v0,v1,v2,v4} + // vpy[1]: {v0,v2,v3,v4} + // + const vtkIdType vpy[8][4] ={{0,1,2,4},{0,2,3,4},{1,2,3,4},{1,3,0,4}, + {2,3,0,4},{2,0,1,4},{3,0,1,4},{3,1,2,4}}; + + xmin = cellIds[pyramId[0]]; + idpy = 0; + for(i=1;i<4;i++) + { + if(xmin > cellIds[pyramId[i]]) + { + xmin = cellIds[pyramId[i]]; // global index + idpy = i; // local index + } + } + for(j = 0; j < 4 ; j++) + { + tab[j] = pyramId[vpy[2*idpy][j]]; + } + newCellArray->InsertNextCell(4,tab); + + for(j = 0; j < 4 ; j++) + { + tab[j] = pyramId[vpy[2*idpy+1][j]]; + } + newCellArray->InsertNextCell(4,tab); +} + + +//---------------------------------------------------------------------------- +//Tetra Grid : Subdivide cells in consistent tetrahedra. +// For each cell, search the smallest global index. +// +// Case Tetrahedron(10): Just insert this cell in the newCellArray +// +// Case Voxel(11) or Hexahedron(12): +// - for each face: looking for the diagonal edge with the smallest index +// - 2 possibilities: subdivide a cell in 5 or 6 tetrahedra +// +// (I)Case 6 tetrahedra: +// - 6 possibilities: subdivide de cell in 2 wedges: +// (1) diagonal edges (v0,v5),(v2,v7) +// vwedge[0]={0,5,4,2,7,6}, +// vwedge[1]={0,1,5,2,3,7}, +// (2) diagonal edges (v4,v7),(v0,v3) +// vwedge[2]={4,7,6,0,3,2}, +// vwedge[3]={4,5,7,0,1,3}, +// (3) diagonal edges (v0,v6),(v1,v7) +// vwedge[4]= {1,7,5,0,6,4}, +// vwedge[5]{1,3,7,0,2,6}, +// subdivide de cell in 2 wedges: +// (4) diagonal edges (v1,v2),(v5,v6) +// vwedge[6]={4,5,6,0,1,2}, +// vwedge[7]={6,5,7,2,1,3}, +// (5) diagonal edges (v2,v4),(v3,v5) +// vwedge[8]={3,7,5,2,6,4}, +// vwedge[9]={1,3,5,0,2,4}, +// (6) diagonal edges (v1,v4),(v3,v6) +// vwedge[10]={0,1,4,2,3,6} +// vwedge[11]={1,5,4,3,7,6} +// v6 _ _ __ _ v7 +// /| /| VOXEL +// v4/_|_ _ _ _/ | opposite vertex of v0 is v7 and vice-versa +// | | v5| | diagonal edges Edg_f[i] +// |v2 _ _ _ |_| v3 +// |/ |/ +// v0/_ _ _ _ _|/v1 +// +// +// (II)Case 5 tetrahedra: +// - search the smallest vertex vi +// - verify if the opposite vertices of vi do not belong to any diagonal edges Edg_f +// - 2 possibilites: create 5 tetraedra +// - if vi is ( 0 or 3 or 5 or 6) +// vtetra[]={v0,v5,v3,v6},{v0,v4,v5,v6},{v0,v1,v3,v5},{v5,v3,v6,v7},{v0,v3,v2,v6}}; +// - if vi is ( 1 or 2 or 4 or 7) +// vtetra[]={v1,v2,v4,v7},{v0,v1,v2,v4},{v1,v4,v5,v7},{v1,v3,v2,v7},{v2,v6,v4,v7}}; +// Case Wedge (13): +// the table 'vwedge' set 6 possibilities of the smallest index +// +// v5 +// /\ . +// v3 /..\ v4 +// / / +// v2/\ / +// v0/__\/v1 +// +// if(v0 index ) is the smallest index: +// wedge is subdivided in: +// 1 tetrahedron-> vwedge[0]: {v0,v4,v3,v5} +// and 1 pyramid-> vert[0] : {v1,v2,v5,v4,v0} +// +// Case Pyramid (14): +// the table 'vpy' set 3 possibilities of the smallest index +// vertices{v0,v1,v2,v3,v4}. {v0,v1,v2,v3} is a square face of pyramid +// +// v4 (opposite vertex of face with 4 vertices) +// ^ +// +// +// v3 _ _ __ _ v2 +// / / +// v0/_ _ _ _ _/v1 +// +// if(v0 index ) is the smallest index: +// the pyramid is subdivided in: +// 2 tetrahedra-> vpyram[0]: {v0,v1,v2,v4} +// vpyram[1]: {v0,v2,v3,v4} +// +// +//---------------------------------------------------------------------------- +void vtkBoxClipDataSet::CellGrid(vtkIdType typeobj, vtkIdType npts, + const vtkIdType *cellIds, + vtkCellArray *newCellArray) +{ + vtkIdType tab[4]; + vtkIdType tabp[5]; + vtkIdType ptstriangle = 3; + vtkIdType ptstetra = 4; + vtkIdType xmin; + vtkIdType idt; + int i,j; + unsigned int id =0; + unsigned int idpy =0; + + unsigned int Edg_f[6][2]; //edge selected of each face + unsigned int idv[4]; + + unsigned int idopos; + unsigned int numbertetra; + + const vtkIdType triPassThrough[3] = {0, 1, 2}; + vtkIdType tri[3]; + vtkIdType line[2]; + + switch(typeobj) + { + case VTK_VERTEX: + case VTK_POLY_VERTEX: + for (idt = 0; idt < npts; idt++) + { + newCellArray->InsertNextCell(1, &idt); + } + break; + + case VTK_LINE: + case VTK_POLY_LINE: + for (idt = 0; idt < npts-1; idt++) + { + line[0] = idt; + line[1] = idt+1; + newCellArray->InsertNextCell(2, line); + } + break; + + case VTK_TRIANGLE: // 5 + case VTK_QUADRATIC_TRIANGLE: + newCellArray->InsertNextCell(ptstriangle, triPassThrough); + break; + + case VTK_TRIANGLE_STRIP: // 6 + for (idt=0 ; idt < npts-2; idt++) + { + if (idt%2 == 0) + { + tri[0] = idt; + tri[1] = idt+1; + tri[2] = idt+2; + } + else + { + tri[0] = idt; + tri[1] = idt+2; + tri[2] = idt+1; + } + newCellArray->InsertNextCell(3,tri); + } + break; + + case VTK_POLYGON: // 7 (Convex case) + tri[0] = 0; + for (idt=2 ; idt < npts; idt++) + { + tri[1] = idt-1; + tri[2] = idt; + newCellArray->InsertNextCell(3,tri); + } + break; + + case VTK_PIXEL: // 8 + { + const vtkIdType vtrip[2][3] = {{0,1,3},{0,3,2}}; + newCellArray->InsertNextCell(3,vtrip[0]); + newCellArray->InsertNextCell(3,vtrip[1]); + } + break; + + case VTK_QUAD: // 9 + case VTK_QUADRATIC_QUAD: + + { + const vtkIdType vtriq[2][3] = {{0,1,2},{0,2,3}}; + newCellArray->InsertNextCell(3,vtriq[0]); + newCellArray->InsertNextCell(3,vtriq[1]); + } + break; + + case VTK_TETRA: // 10 + case VTK_QUADRATIC_TETRA: + { + const vtkIdType tetra[4]={0,1,2,3}; + newCellArray->InsertNextCell(ptstetra,tetra); + } + break; + + case VTK_VOXEL: // 11 + // each face: search edge with smallest global index + // face 0 (0,1,5,4) + idv[0]= 0; + idv[1]= 1; + idv[2]= 5; + idv[3]= 4; + this->MinEdgeF(idv,cellIds,Edg_f[0]); + + // face 1 (0,1,3,2) + idv[0]= 0; + idv[1]= 1; + idv[2]= 3; + idv[3]= 2; + this->MinEdgeF(idv,cellIds,Edg_f[1]); + // face 2 (0,2,6,4) + idv[0]= 0; + idv[1]= 2; + idv[2]= 6; + idv[3]= 4; + this->MinEdgeF(idv,cellIds,Edg_f[2]); + // face 3 (4,5,7,6) + idv[0]= 4; + idv[1]= 5; + idv[2]= 7; + idv[3]= 6; + this->MinEdgeF(idv,cellIds,Edg_f[3]); + // face 4 (2,3,7,6) + idv[0]= 2; + idv[1]= 3; + idv[2]= 7; + idv[3]= 6; + this->MinEdgeF(idv,cellIds,Edg_f[4]); + // face 5 (1,3,7,5) + idv[0]= 1; + idv[1]= 3; + idv[2]= 7; + idv[3]= 5; + this->MinEdgeF(idv,cellIds,Edg_f[5]); + + //search the smallest global index of voxel + xmin = cellIds[0]; + id = 0; + for(i=1;i<8;i++) + { + if(xmin > cellIds[i]) + { + xmin = cellIds[i];// the smallest global index + id = i; // local index + } + } + //two cases: + idopos = 7 - id; + numbertetra = 5; + for(i=0;i<6;i++) + { + j=0; + if (idopos == Edg_f[i][j]) + { + numbertetra = 6; + break; + } + j=1; + if (idopos == Edg_f[i][j]) + { + numbertetra = 6; + break; + } + } + + if(numbertetra == 5) + { + // case 1: create 5 tetraedra + if((id == 0)||(id == 3)||(id == 5)||(id == 6)) + { + const vtkIdType vtetra[5][4]={{0,5,3,6},{0,4,5,6}, + {0,1,3,5},{5,3,6,7},{0,3,2,6}}; + for(i=0; i<5; i++) + { + newCellArray->InsertNextCell(4,vtetra[i]); + } + } + else + { + const vtkIdType vtetra[5][4]={{1,2,4,7},{0,1,2,4}, + {1,4,5,7},{1,3,2,7},{2,6,4,7}}; + + for(i=0; i<5; i++) + { + newCellArray->InsertNextCell(4,vtetra[i]); + } + } + } + else + { + //case 2: create 2 wedges-> 6 tetrahedra + const vtkIdType vwedge[12][6]={{0,5,4,2,7,6},{0,1,5,2,3,7}, + {4,7,6,0,3,2},{4,5,7,0,1,3}, + {1,7,5,0,6,4},{1,3,7,0,2,6}, + {4,5,6,0,1,2},{6,5,7,2,1,3}, + {3,7,5,2,6,4},{1,3,5,0,2,4}, + {0,1,4,2,3,6},{1,5,4,3,7,6}}; + unsigned int edgeId = 10*Edg_f[i][0]+ Edg_f[i][1]; + switch(edgeId) + { + case 5: // edge(v0,v5):10*0 + 5 + case 27: // edge(v2,v7):10*2 + 7 + this->WedgeToTetra(vwedge[0],cellIds,newCellArray); + this->WedgeToTetra(vwedge[1],cellIds,newCellArray); + break; + case 3: // edge(v0,v2) + case 47: // edge(v4,v6) + this->WedgeToTetra(vwedge[2],cellIds,newCellArray); + this->WedgeToTetra(vwedge[3],cellIds,newCellArray); + break; + case 6: + case 17: + this->WedgeToTetra(vwedge[4],cellIds,newCellArray); + this->WedgeToTetra(vwedge[5],cellIds,newCellArray); + break; + case 12: + case 56: + this->WedgeToTetra(vwedge[6],cellIds,newCellArray); + this->WedgeToTetra(vwedge[7],cellIds,newCellArray); + break; + case 24: + case 35: + this->WedgeToTetra(vwedge[8],cellIds,newCellArray); + this->WedgeToTetra(vwedge[9],cellIds,newCellArray); + break; + case 14: + case 36: + this->WedgeToTetra(vwedge[10],cellIds,newCellArray); + this->WedgeToTetra(vwedge[11],cellIds,newCellArray); + break; + } + } + break; + + case VTK_HEXAHEDRON: // 12 + case VTK_QUADRATIC_HEXAHEDRON: + { + // each face: search edge with smallest global index + // face 0 (0,1,5,4) + idv[0]= 0; + idv[1]= 1; + idv[2]= 5; + idv[3]= 4; + this->MinEdgeF(idv,cellIds,Edg_f[0]); + + // face 1 (0,1,2,3) + idv[0]= 0; + idv[1]= 1; + idv[2]= 2; + idv[3]= 3; + this->MinEdgeF(idv,cellIds,Edg_f[1]); + // face 2 (0,3,7,4) + idv[0]= 0; + idv[1]= 3; + idv[2]= 7; + idv[3]= 4; + this->MinEdgeF(idv,cellIds,Edg_f[2]); + // face 3 (4,5,6,7) + idv[0]= 4; + idv[1]= 5; + idv[2]= 6; + idv[3]= 7; + this->MinEdgeF(idv,cellIds,Edg_f[3]); + // face 4 (3,2,6,7) + idv[0]= 3; + idv[1]= 2; + idv[2]= 6; + idv[3]= 7; + this->MinEdgeF(idv,cellIds,Edg_f[4]); + // face 5 (1,2,6,5) + idv[0]= 1; + idv[1]= 2; + idv[2]= 6; + idv[3]= 5; + this->MinEdgeF(idv,cellIds,Edg_f[5]); + + //search the smallest global index of voxel + xmin = cellIds[0]; + id = 0; + for(i=1;i<8;i++) + { + if(xmin > cellIds[i]) + { + xmin = cellIds[i];// the smallest global index + id = i; // local index + } + } + + //two cases: + const unsigned int tabopos[8] = {6,7,4,5,2,3,0,1}; + idopos = tabopos[id]; + numbertetra = 5; + for(i=0;i<6;i++) + { + j = 0; + if (idopos == Edg_f[i][j]) + { + numbertetra = 6; + break; + } + j=1; + if (idopos == Edg_f[i][j]) + { + numbertetra = 6; + break; + } + } + + if(numbertetra == 5) + { + // case 1: create 5 tetraedra + if((id == 0)||(id == 2)||(id == 5)||(id == 7)) + { + const vtkIdType vtetra[5][4]={{0,5,2,7},{0,4,5,7}, + {0,1,2,5},{5,2,7,6},{0,2,3,7}}; + for(i=0; i<5; i++) + { + newCellArray->InsertNextCell(4,vtetra[i]); + } + } + else + { + const vtkIdType vtetra[5][4]={{1,3,4,6},{0,1,3,4}, + {1,4,5,6},{1,2,3,6},{3,7,4,6}}; + + for(i=0; i<5; i++) + { + newCellArray->InsertNextCell(4,vtetra[i]); + } + } + } + else + { + //case 2: create 2 wedges-> 6 tetrahedra + const vtkIdType vwedge[12][6]={{0,5,4,3,6,7},{0,1,5,3,2,6}, + {4,6,7,0,2,3},{4,5,6,0,1,2}, + {1,6,5,0,7,4},{1,2,6,0,3,7}, + {4,5,7,0,1,3},{7,5,6,3,1,2}, + {2,6,5,3,7,4},{1,2,5,0,3,4}, + {0,1,4,3,2,7},{1,5,4,2,6,7}}; + unsigned int edgeId = 10*Edg_f[i][0]+ Edg_f[i][1]; + + switch(edgeId) + { + case 5: // edge(v0,v5):10*0 + 5 + case 36: // edge(v3,v6):10*3 + 6 + this->WedgeToTetra(vwedge[0],cellIds,newCellArray); + this->WedgeToTetra(vwedge[1],cellIds,newCellArray); + break; + case 2: // edge(v0,v2) + case 46: // edge(v4,v6) + this->WedgeToTetra(vwedge[2],cellIds,newCellArray); + this->WedgeToTetra(vwedge[3],cellIds,newCellArray); + break; + case 7: + case 16: + this->WedgeToTetra(vwedge[4],cellIds,newCellArray); + this->WedgeToTetra(vwedge[5],cellIds,newCellArray); + break; + case 13: + case 57: + this->WedgeToTetra(vwedge[6],cellIds,newCellArray); + this->WedgeToTetra(vwedge[7],cellIds,newCellArray); + break; + case 34: + case 25: + this->WedgeToTetra(vwedge[8],cellIds,newCellArray); + this->WedgeToTetra(vwedge[9],cellIds,newCellArray); + break; + case 14: + case 27: + this->WedgeToTetra(vwedge[10],cellIds,newCellArray); + this->WedgeToTetra(vwedge[11],cellIds,newCellArray); + break; + } + } + } + break; + + case VTK_WEDGE: + case VTK_QUADRATIC_WEDGE: + if(npts == 6) //create 3 tetrahedra + { + //first tetrahedron + const vtkIdType vwedge[6][4]={{0,4,3,5},{1,4,3,5},{2,4,3,5}, + {3,0,1,2},{4,0,1,2},{5,0,1,2}}; + xmin = cellIds[0]; + id = 0; + for(i=1;i<6;i++) + { + if(xmin > cellIds[i]) + { + xmin = cellIds[i]; // the smallest global index + id = i; // local index + } + } + newCellArray->InsertNextCell(4, vwedge[id]); + + //Pyramid :create 2 tetrahedra + + const vtkIdType vert[6][5]={{1,2,5,4,0},{2,0,3,5,1},{3,0,1,4,2}, + {1,2,5,4,3},{2,0,3,5,4},{3,0,1,4,5}}; + const vtkIdType vpy[8][4] ={{0,1,2,4},{0,2,3,4},{1,2,3,4},{1,3,0,4}, + {2,3,0,4},{2,0,1,4},{3,0,1,4},{3,1,2,4}}; + xmin = cellIds[vert[id][0]]; + tabp[0] = vert[id][0]; + idpy = 0; + for(i=1;i<4;i++) + { + tabp[i] = vert[id][i]; + if(xmin > cellIds[vert[id][i]]) + { + xmin = cellIds[vert[id][i]]; // global index + idpy = i; // local index + } + } + tabp[4] = vert[id][4]; + for(j = 0; j < 4 ; j++) + { + tab[j] = tabp[vpy[2*idpy][j]]; + } + newCellArray->InsertNextCell(4,tab); + + for(j = 0; j < 4 ; j++) + { + tab[j] = tabp[vpy[2*idpy+1][j]]; + } + newCellArray->InsertNextCell(4,tab); + + } + else + { + vtkErrorMacro( << " This cell is not a wedge\n" ); + return; + } + break; + + case VTK_PYRAMID: //Create 2 tetrahedra + case VTK_QUADRATIC_PYRAMID: + if(npts == 5) + { + //note: the first element vpyram[][0] is the smallest index of pyramid + const vtkIdType vpyram[8][4]={{0,1,2,4},{0,2,3,4},{1,2,3,4},{1,3,0,4}, + {2,3,0,4},{2,0,1,4},{3,0,1,4},{3,1,2,4}}; + xmin = cellIds[0]; + id = 0; + for(i=1;i<4;i++) + { + if(xmin > cellIds[i]) + { + xmin = cellIds[i]; // the smallest global index of square face + id = i; // local index + } + } + newCellArray->InsertNextCell(4,vpyram[2*id]); + newCellArray->InsertNextCell(4,vpyram[2*id+1]); + } + else + { + vtkErrorMacro( << " This cell is not a pyramid\n" ); + return; + } + break; + } +} + +//---------------------------------------------------------------------------- +// The new cell created in intersection between tetrahedron and plane +// are tetrahedron or wedges or pyramides. +// +// CreateTetra is used to subdivide wedges and pyramids in tetrahedron. The +// proper vertex ordering for wedges and pyramids can be found in "The +// Visualization Toolkit." In the third edition, they are in Figure 5-2 on page +// 115 in section 5.4 ("Cell Types") in the "Basic Data Representation" chapter. +// +void vtkBoxClipDataSet::CreateTetra(vtkIdType npts, const vtkIdType *cellIds, + vtkCellArray *newCellArray) +{ + vtkIdType tabp[5]; + vtkIdType tab[3][4]; + + unsigned int i,j; + unsigned int id =0; + unsigned int idpy; + + vtkIdType xmin; + + if (npts == 6) + { + //VTK_WEDGE: Create 3 tetrahedra + //first tetrahedron + const vtkIdType vwedge[6][4]={{0,4,3,5},{1,4,3,5},{2,4,3,5}, + {3,0,1,2},{4,0,1,2},{5,0,1,2}}; + xmin = cellIds[0]; + id = 0; + for(i=1;i<6;i++) + { + if(xmin > cellIds[i]) + { + xmin = cellIds[i];// the smallest global index + id = i; // local index + } + } + for(j = 0; j < 4 ; j++) + { + tab[0][j] = cellIds[vwedge[id][j]]; + } + newCellArray->InsertNextCell(4,tab[0]); + + //Pyramid: create 2 tetrahedra + + const vtkIdType vert[6][5]= {{1,2,5,4,0},{2,0,3,5,1},{3,0,1,4,2}, + {1,2,5,4,3},{2,0,3,5,4},{3,0,1,4,5}}; + const vtkIdType vpy[8][4] = {{0,1,2,4},{0,2,3,4},{1,2,3,4},{1,3,0,4}, + {2,3,0,4},{2,0,1,4},{3,0,1,4},{3,1,2,4}}; + xmin = cellIds[vert[id][0]]; + tabp[0] = vert[id][0]; + idpy = 0; + for(i=1;i<4;i++) + { + tabp[i] = vert[id][i]; + if(xmin > cellIds[vert[id][i]]) + { + xmin = cellIds[vert[id][i]]; // global index + idpy = i; // local index + } + } + tabp[4] = vert[id][4]; + for(j = 0; j < 4 ; j++) + { + tab[1][j] = cellIds[tabp[vpy[2*idpy][j]]]; + } + newCellArray->InsertNextCell(4,tab[1]); + + for(j = 0; j < 4 ; j++) + { + tab[2][j] = cellIds[tabp[vpy[2*idpy+1][j]]]; + } + newCellArray->InsertNextCell(4,tab[2]); + } + else + { + //VTK_PYRAMID: Create 2 tetrahedra + //The first element in each set is the smallest index of pyramid + const vtkIdType vpyram[8][4]={{0,1,2,4},{0,2,3,4},{1,2,3,4},{1,3,0,4}, + {2,3,0,4},{2,0,1,4},{3,0,1,4},{3,1,2,4}}; + xmin = cellIds[0]; + id = 0; + for(i=1;i<4;i++) + { + if(xmin > cellIds[i]) + { + xmin = cellIds[i]; // the smallest global index of face with 4 vertices + id = i; // local index + } + } + for(j = 0; j < 4 ; j++) + { + tab[0][j] = cellIds[vpyram[2*id][j]]; + } + newCellArray->InsertNextCell(4,tab[0]); + + for(j = 0; j < 4 ; j++) + { + tab[1][j] = cellIds[vpyram[2*id+1][j]]; + } + newCellArray->InsertNextCell(4,tab[1]); + } +} + +//---------------------------------------------------------------------------- +// Clip each cell of an unstructured grid. +// +//---------------------------------------------------------------------------- +//(1) How decide when the cell is NOT outside +// +// Explaining with an example in 2D. +// Look at 9 region in the picture and the triangle represented there. +// v0,v1,v2 are vertices of triangle T. +// +// | | +// 1 | 2 | 3 +// _ _ _ _ _ _ _ _ _ _ _ _ _ _ ymax +// | | v1 +// 4 | 5 |/\ 6 +// | / \ . +// _ _ _ _ _ _ _ _ _ /| _ \_ _ _ymin +// | v2/_|_ _ \v0 +// 7 | 8 | 9 +// xmin xmax +// +// set test={1,1,1,1} (one test for each plane: test={xmin,xmax,ymin,ymax} ) +// for each vertex, if the test is true set 0 in the test table: +// vO > xmin ?, v0 < xmax ?, v0 > ymin ?, v0 < ymax ? +// In the example: test={0,1,1,0} +// v1 > xmin ?, v1 < xmax ?, v1 > ymin ?, v1 < ymax ? +// In the example: test={0,1,0,0} +// v2 > xmin ?, v2 < xmax ?, v2 > ymin ?, v2 < ymax ? +// In the Example: test={0,0,0,0} -> triangle is NOT outside. +// +// +// In general, look at the possibilities of each region +// +// (1,0,0,1) | (0,0,0,1) | (0,1,0,1) +// - - - - - - - - - - - - - - - - - - +// (1,0,0,0) | (0,0,0,0) | (0,1,0,0) +// - - - - - - - - - - - - - - - - - - +// (1,0,1,0) | (0,0,1,0) | (0,1,1,0) +// +// In the case above we have:(v0,v1,v2) +// (1,1,1,1)->(0,1,1,0)->(0,1,0,0)->(0,0,0,0) +// +// If you have one vertex in region 5, this triangle is NOT outside +// The triangle IS outside if (v0,v1,v2) are in region like +// (1,2,3): (1,0,0,1)->(0,0,0,1)->(0,0,0,1) +// (1,4,7): (1,0,0,1)->(1,0,0,0)->(1,0,0,0) +// (7,8,9): (1,0,1,0)->(0,0,1,0)->(0,0,1,0) +// (9,6,3): (0,1,1,0)->(0,1,0,0)->(0,1,0,0) +// +// Note that if the triangle T is on the region 5, T is NOT outside +// In fact, T is inside +// +// You can extend this idea to 3D. +// +// Note: xmin = this->BoundBoxClip[0][0], xmax= this->BoundBoxClip[0][1],... +// +//---------------------------------------------------------------------------- +// (2) Intersection between Tetrahedron and Plane: +// Description: +// vertices of tetrahedron {v0,v1,v2,v3} +// edge e1 : (v0,v1), edge e2 : (v1,v2) +// edge e3 : (v2,v0), edge e4 : (v0,v3) +// edge e5 : (v1,v3), edge e6 : (v2,v3) +// +// interseting points p0, pi, ... +// +// Note: The algorithm search intersection +// points with these edge order. +// +// v3 v3 +// e6/|\ e5 | +// / | \ e2 | +// v2/_ |_ \ v1 v2 - - -v1 |e4 +// \ | / | +// e3\ | /e1 | +// \|/ | +// v0 v0 +// +// (a) Intersecting 4 edges: see tab4[] +// -> create: 2 wedges +// -> 3 cases +// ------------------------------------------ +// case 1246: +// if (plane intersecting edges {e1,e2,e4,e6}) +// then p0 belongs to e1, p1 belongs to e2, +// p2 belongs to e4, p3 belongs to e6. +// +// v3 +// | v3 +// | / +// v1 v2 - *- -v1 | * p3 +// / p1 * p2 / +// *p0 | v2/ +// / | +// v0 v0 +// (e1) (e2) (e4) (e6) +// +// So, there are two wedges: +// {p0,v1,p1,p2,v3,p3} {p2,v0,p0,p3,v2,p1} +// +// Note: if e1 and e2 are intersected by plane, +// and the plane intersects 4 edges, +// the edge e5 could not be intersected +// (skew lines, do not create a planar face) +// neither the edge e3((e1,e2,e3) is a face) +// +// ------------------------------------------ +// case 2345: +// if (plane intersecting edges {e2,e3,e4,e5}) +// The two wedges are: +// {p3,v3,p2,p0,v2,p1}, {p1,v0,p2,p0,v1,p3} +// +// ------------------------------------------ +// case 1356: +// if (plane intersecting edges {e1,e3,e5,e6}) +// The two wedges are: +// {p0,v0,p1,p2,v3,p3}, {p0,v1,p2,p1,v2,p3} +// +// ----------------------------------------- +// +// (b) Intersecting 3 edges: tab3[] +// ->create: 1 tetrahedron + 1 wedge +// -> 4 cases +// ------------------------------------------ +// case 134: +// if (plane intersecting edges {e1,e3,e4}) +// then p0 belongs to e1, p1 belongs to e3, +// p2 belongs to e4. +// +// v3 +// | +// | +// v2 *p2 v1 +// \ | / +// p1* | *p0 +// \|/ +// v0 +// +// +// So, there are: +// 1 tetrahedron {v0,p0,p2,p1) +// and 1 wedge: {p0,p2,p1,v1,v3,v2}: tab3[0] +// +// Note:(a)if e1 and e3 are intersected by plane, +// and the plane intersects 3 edges, +// the edges e5 could not be intersected, +// if so, e6 be intersected too and the +// plane intersect 4 edges. +// (b) tetrahedron vertices: +// Use the first three indices of tab3: +// {v0,p(0),p(2),p(1)} +// +// ------------------------------------------ +// case 125: +// if (plane intersecting edges {e1,e2,e5}) +// There are : +// 1 tetrahedron: {v1,p0,p2,p1} +// 1 wedge : {p0,p2,p1,v0,v3,v2}, +// ------------------------------------------ +// case 236: +// if (plane intersecting edges {e2,e3,e6}) +// There are : +// 1 tetrahedron: {v2,p0,p1,p2} +// 1 wedge : {p0,p1,p2,v1,v0,v3}, +// ------------------------------------------ +// case 456: +// if (plane intersecting edges {e4,e5,e6}) +// There are : +// 1 tetrahedron: {v3,p0,p1,p2} +// 1 wedge : {p0,p1,p2,v0,v1,v2}, +// ------------------------------------------ +// +// (c) Intersecting 2 edges and 1 vertex: tab2[] +// -> create: 1 tetrahedron + 1 pyramid +// -> 12 cases +// ------------------------------------------ +// case 12: v3 indexes:{0,0,1,2,3}, +// * 0 1 2 3 4 +// e6/ | \ e5 +// / |p1\ tetrahedron: indices(*,4,1,2) +// v2/_ _|_*_\ v1 +// \ | / +// e3\ |p0* +// \ | /e1 +// v0 +// +// if (plane intersecting edges {e1,e2} +// and one vertex) +// There are +// 1 tetrahedron: {v1,v3,p0,p1} +// 1 pyramid : {v0,p0,p1,v2,v3}, +// +// Note: if e1 and e2 are intersected by plane, +// and the plane intersects 2 edges, +// then the vertex is v3. +// ------------------------------------------ +// +// case 13: indexes{2,1,0,1,3} +// Intersecting edges {e1,e3} +// Intersectinf vertes v3, +// +// 1 tetrahedron: {v0,v3,p1,p0} +// 1 pyramid : {v2,p1,p0,v1,v3}, +// ------------------------------------------ +// all cases see tab2[] +// ------------------------------------------ +// (d) Intersecting 1 edges and 2 vertices: tab1[] +// -> create: 2 tetrahedra +// -> 6 cases +// +// - edge e1, vertices {v2,v3}(e6) +// +// v3 +// * tetrahedra: {p0,v2,v3,v1},{p0,v3,v2,v0} +// e6/ | \ e5 +// / | \ . +// v2 *_ _|_ _\ v1 +// \ | / +// e3\ |p0* +// \ | /e1 +// v0 +// - other cases see tab1[] +//---------------------------------------------------------------------------- +// +void vtkBoxClipDataSet::ClipBox(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytetra = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[4]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType tab_id[6]; + vtkIdType ptstetra = 4; + + vtkIdType i,j; + unsigned int allInside; + unsigned int idcellnew; + unsigned int cutInd; + + vtkIdType edges[6][2] = { {0,1}, {1,2}, {2,0}, + {0,3}, {1,3}, {2,3} }; /* Edges Tetrahedron */ + double value,deltaScalar; + double t; + double *p1, *p2; + double x[3], v[3]; + double v_tetra[4][3]; + + for (i=0; iGetId(i); + } + + // Convert all volume cells to tetrahedra + this->CellGrid(cellType,npts,cellptId,arraytetra); + unsigned int totalnewtetra = arraytetra->GetNumberOfCells(); + unsigned int idtetranew; + + for (idtetranew = 0 ; idtetranew < totalnewtetra; idtetranew++) + { + arraytetra->GetNextCell(ptstetra,v_id); + + for (allInside=1, i=0; i<4; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (!(((v[0] >= this->BoundBoxClip[0][0])&&(v[0] <= this->BoundBoxClip[0][1]) && + (v[1] >= this->BoundBoxClip[1][0])&&(v[1] <= this->BoundBoxClip[1][1])&& + (v[2] >= this->BoundBoxClip[2][0])&&(v[2] <= this->BoundBoxClip[2][1])))) + { + //outside,its type might change later (nearby intersection) + allInside = 0; + } + }//for all points of the tetrahedron. + + // Test Outside: see(1) + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<4; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (v[0] > this->BoundBoxClip[0][0]) + { + test[0] = 0; + } + if (v[0] < this->BoundBoxClip[0][1]) + { + test[1] = 0; + } + if (v[1] > this->BoundBoxClip[1][0]) + { + test[2] = 0; + } + if (v[1] < this->BoundBoxClip[1][1]) + { + test[3] = 0; + } + if (v[2] > this->BoundBoxClip[2][0]) + { + test[4] = 0; + } + if (v[2] < this->BoundBoxClip[2][1]) + { + test[5] = 0; + } + + }//for all points of the cell. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + continue; // Tetrahedron is outside. + } + }//if not all inside. + + for (i=0; i<4; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + // Currently all points are injected because of the possibility + // of intersection point merging. + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + + }//for all points of the tetrahedron. + + if ( allInside ) + { + // Tetrahedron inside. + vtkIdType newCellId = tets->InsertNextCell(4,iid); + outCD->CopyData(inCD,cellId,newCellId); + continue; + } + + double *pedg1,*pedg2; + + + // Tetrahedron Intersection Cases + const unsigned int tab4[6][6] = { {1,1,0,3,3,2}, + {2,0,0,3,2,1}, + {3,3,2,0,2,1}, + {1,0,2,0,1,3}, + {0,0,1,2,3,3}, + {0,1,2,1,2,3}}; + const unsigned int tab3[4][6] = { {0,2,1,1,3,2}, + {0,1,2,0,2,3}, + {0,1,2,1,0,3}, + {0,1,2,0,1,2}}; + const unsigned int tab2[12][5] = { {0,0,1,2,3}, + {2,1,0,1,3}, + {1,0,1,0,3}, + {2,0,1,3,0}, + {3,1,0,1,0}, + {1,0,1,2,0}, + {3,1,0,2,1}, + {2,1,0,0,1}, + {0,0,1,3,1}, + {1,0,1,3,2}, + {3,1,0,0,2}, + {0,0,1,1,2}}; + const unsigned int tab1[12][3] = { {2,3,1}, + {3,2,0}, + {3,0,1}, + {0,3,2}, + {1,3,0}, + {3,1,2}, + {2,1,0}, + {1,2,3}, + {2,0,3}, + {0,2,1}, + {0,1,3}, + {1,0,2}}; + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkIdType newCellId = cellarray->InsertNextCell(4,iid); + unsigned int planes; + + // Test Cell intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + // The index of the dimension of the cut plane (x == 0, y == 1, z == 2). + cutInd = planes/2; + + // The plane is always parallel to unitary cube. + value = this->BoundBoxClip[cutInd][planes%2]; + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + int edgeNum; + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + unsigned int i0,i1; + vtkIdType p_id[4]; + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_tetra[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_tetra[1]); + newPoints->GetPoint(v_id[2],v_tetra[2]); + newPoints->GetPoint(v_id[3],v_tetra[3]); + + for (edgeNum=0; edgeNum < 6; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_tetra[verts[0]]; + p2 = v_tetra[verts[1]]; + + if ( (p1[cutInd] <= value && value <= p2[cutInd]) || + (p2[cutInd] <= value && value <= p1[cutInd]) ) + { + deltaScalar = p2[cutInd] - p1[cutInd]; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + (value - pedg1[cutInd]) / deltaScalar ); + + if ( t == 0.0 || t == 1.0 ) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + num_inter++; + }//if edge intersects value + }//for all edges + + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0; i<4; i++) + { + if (((v_tetra[i][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[i][cutInd] > value) && ((planes % 2) == 1))) + + // If only one vertex is ouside, so the tetrahedron is outside + // because there is not intersection. + { + outside = 1; + break; + } + } + if(outside == 0) + { + // else it is possible intersection if other plane + newCellId = newcellArray->InsertNextCell(4,v_id); + } + continue; + } + switch(num_inter) + { + case 4: // We have two wedges + switch(edges_inter) + { + case 1246: + i0 = 0; + break; + case 2345: + i0 = 2; + break; + case 1356: + i0 = 4; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + + if (((v_tetra[3][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[3][cutInd] > value) && ((planes % 2) == 1))) + { + + // The v_tetra[3] is outside box, so the first wedge is outside + + tab_id[0] = p_id[tab4[i0+1][0]]; + // ps: v_tetra[3] is always in first wedge (see tab) + + tab_id[1] = v_id[tab4[i0+1][1]]; + tab_id[2] = p_id[tab4[i0+1][2]]; + tab_id[3] = p_id[tab4[i0+1][3]]; + tab_id[4] = v_id[tab4[i0+1][4]]; + tab_id[5] = p_id[tab4[i0+1][5]]; + this->CreateTetra(6,tab_id,newcellArray); + } + else + { + tab_id[0] = p_id[tab4[i0][0]]; + tab_id[1] = v_id[tab4[i0][1]]; + tab_id[2] = p_id[tab4[i0][2]]; + tab_id[3] = p_id[tab4[i0][3]]; + tab_id[4] = v_id[tab4[i0][4]]; + tab_id[5] = p_id[tab4[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + } + break; + case 3: // We have one tetrahedron and one wedge + // i0 gets the vertex on the tetrahedron. + switch(edges_inter) + { + case 134: + i0 = 0; + break; + case 125: + i0 = 1; + break; + case 236: + i0 = 2; + break; + case 456: + i0 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + + if (((v_tetra[i0][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[i0][cutInd] > value) && ((planes % 2) == 1))) + { + + // Isolate vertex is outside box, so the tetrahedron is outside + tab_id[0] = p_id[tab3[i0][0]]; + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[tab3[i0][3]]; + tab_id[4] = v_id[tab3[i0][4]]; + tab_id[5] = v_id[tab3[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + } + else + { + tab_id[0] = p_id[tab3[i0][0]]; + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[i0]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + break; + + case 2: // We have one tetrahedron and one pyramid + switch(edges_inter) // i1 = vertex of the tetrahedron + { + case 12: + i0 = 0; i1 = 1; + break; + case 13: + i0 = 1; i1 = 0; + break; + case 23: + i0 = 2; i1 = 2; + break; + case 25: + i0 = 3; i1 = 1; + break; + case 26: + i0 = 4; i1 = 2; + break; + case 56: + i0 = 5; i1 = 3; + break; + case 34: + i0 = 6; i1 = 0; + break; + case 46: + i0 = 7; i1 = 3; + break; + case 36: + i0 = 8; i1 = 2; + break; + case 14: + i0 = 9; i1 = 0; + break; + case 15: + i0 = 10; i1 = 1; + break; + case 45: + i0 = 11; i1 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_tetra[i1][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[i1][cutInd] > value) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + tab_id[0] = v_id[tab2[i0][0]]; + tab_id[1] = p_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = v_id[tab2[i0][3]]; + tab_id[4] = v_id[tab2[i0][4]]; + this->CreateTetra(5,tab_id,newcellArray); + } + else + { + tab_id[0] = v_id[i1]; + tab_id[1] = v_id[tab2[i0][4]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = p_id[tab2[i0][1]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + break; + + case 1: // We have two tetrahedron. + if ((edges_inter > 6) || (edges_inter < 1)) + { + vtkErrorMacro( << "Intersection not found: Num_inter = " + << num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_tetra[tab1[2*edges_inter-1][2]][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[tab1[2*edges_inter-1][2]][cutInd] > value) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + tab_id[0] = p_id[0]; + tab_id[1] = v_id[tab1[2*edges_inter-2][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-2][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-2][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = p_id[0]; + tab_id[1] = v_id[tab1[2*edges_inter-1][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-1][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-1][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + break; + } + } // for all new cells + + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets->InsertNextCell(npts,v_id); + outCD->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + } + arraytetra->Delete(); +} + +//---------------------------------------------------------------------------- +// ClipHexahedron: Box is like hexahedron. +// +// The difference between ClipBox and ClipHexahedron is the outside test. +// The ClipHexahedron use plane equation to decide who is outside. +// +void vtkBoxClipDataSet::ClipHexahedron(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType idcellnew; + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytetra = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[4]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType tab_id[6]; + vtkIdType ptstetra = 4; + + vtkIdType i,j; + unsigned int allInside, k; + unsigned int planes; + + vtkIdType edges[6][2] = { {0,1}, {1,2}, {2,0}, + {0,3}, {1,3}, {2,3} }; /* Edges Tetrahedron */ + double deltaScalar; + double t; + double *p1, *p2; + double v[3], x[3]; + double p[6]; + double v_tetra[4][3]; + + for (i=0; iGetId(i); + } + + this->CellGrid(cellType,npts,cellptId,arraytetra); // Convert all volume cells to tetrahedra + + unsigned int totalnewtetra = arraytetra->GetNumberOfCells(); + unsigned int idtetranew; + + for (idtetranew = 0 ; idtetranew < totalnewtetra; idtetranew++) + { + arraytetra->GetNextCell(ptstetra,v_id); + + for (allInside=1, i=0; i<4; i++) + { + cellPts->GetPoint(v_id[i],v); + + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0])+ + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]); + } + + if (!((p[0] <= 0) && (p[1] <= 0) && + (p[2] <= 0) && (p[3] <= 0) && + (p[4] <= 0) && (p[5] <= 0))) + { + allInside = 0; + } + }//for all points of the cell. + + // Test Outside + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<4; i++) + { + cellPts->GetPoint(v_id[i],v); + + // Use plane equation + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0])+ + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]); + } + + + for(k=0;k<3;k++) + { + if (p[2*k] < 0) + { + test[2*k] = 0; + } + if (p[2*k+1] < 0) + { + test[2*k+1] = 0; + } + } + + }//for all points of the cell. + + if (!allInside && ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1))) + { + continue; // Tetrahedron is outside. + } + + for (i=0; i<4; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + // Currently all points are injected because of the possibility + // of intersection point merging. + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + }//for all points of the tetrahedron. + + if ( allInside ) + { + vtkIdType newCellId = tets->InsertNextCell(4,iid); // Tetrahedron inside. + outCD->CopyData(inCD,cellId,newCellId); + continue; + } + + double *pedg1,*pedg2; + + // Tetrahedron Intersection Cases + const unsigned int tab4[6][6] = { {1,1,0,3,3,2}, + {2,0,0,3,2,1}, + {3,3,2,0,2,1}, + {1,0,2,0,1,3}, + {0,0,1,2,3,3}, + {0,1,2,1,2,3}}; + const unsigned int tab3[4][6] = { {0,2,1,1,3,2}, + {0,1,2,0,2,3}, + {0,1,2,1,0,3}, + {0,1,2,0,1,2}}; + const unsigned int tab2[12][5] = { {0,0,1,2,3}, + {2,1,0,1,3}, + {1,0,1,0,3}, + {2,0,1,3,0}, + {3,1,0,1,0}, + {1,0,1,2,0}, + {3,1,0,2,1}, + {2,1,0,0,1}, + {0,0,1,3,1}, + {1,0,1,3,2}, + {3,1,0,0,2}, + {0,0,1,1,2}}; + const unsigned int tab1[12][3] = { {2,3,1}, + {3,2,0}, + {3,0,1}, + {0,3,2}, + {1,3,0}, + {3,1,2}, + {2,1,0}, + {1,2,3}, + {2,0,3}, + {0,2,1}, + {0,1,3}, + {1,0,2}}; + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkIdType newCellId = cellarray->InsertNextCell(4,iid); + + // Test Cell intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + vtkIdType totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int i0,i1; + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + vtkIdType p_id[4]; + + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_tetra[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_tetra[1]); + newPoints->GetPoint(v_id[2],v_tetra[2]); + newPoints->GetPoint(v_id[3],v_tetra[3]); + + p[0] = this->PlaneNormal[planes][0]*(v_tetra[0][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[0][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[0][2] - this->PlanePoint[planes][2]); + p[1] = this->PlaneNormal[planes][0]*(v_tetra[1][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[1][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[1][2] - this->PlanePoint[planes][2]); + p[2] = this->PlaneNormal[planes][0]*(v_tetra[2][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[2][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[2][2] - this->PlanePoint[planes][2]); + p[3] = this->PlaneNormal[planes][0]*(v_tetra[3][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[3][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[3][2] - this->PlanePoint[planes][2]); + + for (int edgeNum=0; edgeNum < 6; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_tetra[verts[0]]; + p2 = v_tetra[verts[1]]; + double s1 = p[verts[0]]; + double s2 = p[verts[1]]; + if ( (s1 * s2) <=0) + { + deltaScalar = s2 - s1; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + t = s1; s1 = s2; s2 = t; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : ( - s1) / deltaScalar ); + + if ( t == 0.0 ) + { + continue; + } + else if ( t == 1.0 ) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + + num_inter++; + }//if edge intersects value + }//for all edges + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0;i<4;i++) + { + if (p[i] > 0) + { + // If only one vertex is ouside, so the tetrahedron is outside + // because there is not intersection. + // some vertex could be on plane, so you need to test all vertex + + outside = 1; + break; + } + } + if (outside == 0) + { + // else it is possible intersection if other plane + + newCellId = newcellArray->InsertNextCell(4,v_id); + } + continue; + } + switch(num_inter) + { + case 4: // We have two wedges + switch(edges_inter) + { + case 1246: + i0 = 0; + break; + case 2345: + i0 = 2; + break; + case 1356: + i0 = 4; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + + if (((p[3] > 0) && ((planes % 2) == 0)) || + ((p[3] > 0) && ((planes % 2) == 1))) + { + // The v_tetra[3] is outside box, so the first wedge is outside + // ps: v_tetra[3] is always in first wedge (see tab) + + tab_id[0] = p_id[tab4[i0+1][0]]; + tab_id[1] = v_id[tab4[i0+1][1]]; + tab_id[2] = p_id[tab4[i0+1][2]]; + tab_id[3] = p_id[tab4[i0+1][3]]; + tab_id[4] = v_id[tab4[i0+1][4]]; + tab_id[5] = p_id[tab4[i0+1][5]]; + this->CreateTetra(6,tab_id,newcellArray); + } + else + { + tab_id[0] = p_id[tab4[i0][0]]; + tab_id[1] = v_id[tab4[i0][1]]; + tab_id[2] = p_id[tab4[i0][2]]; + tab_id[3] = p_id[tab4[i0][3]]; + tab_id[4] = v_id[tab4[i0][4]]; + tab_id[5] = p_id[tab4[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + } + break; + case 3: // We have one tetrahedron and one wedge + switch(edges_inter) + { + case 134: + i0 = 0; + break; + case 125: + i0 = 1; + break; + case 236: + i0 = 2; + break; + case 456: + i0 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + + if (((p[i0] > 0) && ((planes % 2) == 0)) || + ((p[i0] > 0) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + + tab_id[0] = p_id[tab3[i0][0]]; + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[tab3[i0][3]]; + tab_id[4] = v_id[tab3[i0][4]]; + tab_id[5] = v_id[tab3[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + } + else + { + tab_id[0] = p_id[tab3[i0][0]]; + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[i0]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + break; + case 2: // We have one tetrahedron and one pyramid + switch(edges_inter) // i1 = vertex of the tetrahedron + { + case 12: + i0 = 0; i1 = 1; + break; + case 13: + i0 = 1; i1 = 0; + break; + case 23: + i0 = 2; i1 = 2; + break; + case 25: + i0 = 3; i1 = 1; + break; + case 26: + i0 = 4; i1 = 2; + break; + case 56: + i0 = 5; i1 = 3; + break; + case 34: + i0 = 6; i1 = 0; + break; + case 46: + i0 = 7; i1 = 3; + break; + case 36: + i0 = 8; i1 = 2; + break; + case 14: + i0 = 9; i1 = 0; + break; + case 15: + i0 = 10; i1 = 1; + break; + case 45: + i0 = 11; i1 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((p[i1] > 0) && ((planes % 2) == 0)) || + ((p[i1] > 0) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + + tab_id[0] = v_id[tab2[i0][0]]; + tab_id[1] = p_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = v_id[tab2[i0][3]]; + tab_id[4] = v_id[tab2[i0][4]]; + this->CreateTetra(5,tab_id,newcellArray); + } + else + { + tab_id[0] = v_id[i1]; + tab_id[1] = v_id[tab2[i0][4]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = p_id[tab2[i0][1]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + break; + case 1: // We have two tetrahedron. + if ((edges_inter > 6) || (edges_inter < 1)) + { + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((p[tab1[2*edges_inter-1][2]] > 0) && ((planes % 2) == 0)) || + ((p[tab1[2*edges_inter-1][2]] > 0) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + tab_id[0] = p_id[0]; + tab_id[1] = v_id[tab1[2*edges_inter-2][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-2][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-2][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = p_id[0]; + tab_id[1] = v_id[tab1[2*edges_inter-1][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-1][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-1][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + } + break; + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + vtkIdType totalnewcells = cellarray->GetNumberOfCells(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets->InsertNextCell(npts,v_id); + outCD->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + } + arraytetra->Delete(); +} +//---------------------------------------------------------------------------- +// ClipBoxInOut +// +// The difference between ClipBox and ClipBoxInOut is the outputs. +// The ClipBoxInOut generate both outputs: inside and outside the clip box. +// +void vtkBoxClipDataSet::ClipBoxInOut(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytetra = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[4]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType ptIdout[4]; + vtkIdType tab_id[6]; + vtkIdType ptstetra = 4; + + int i,j; + int allInside; + int cutInd; + + unsigned int planes; + unsigned int idcellnew; + unsigned int idtetranew; + + vtkIdType edges[6][2] = { {0,1}, {1,2}, {2,0}, + {0,3}, {1,3}, {2,3} }; /* Edges Tetrahedron */ + double value,deltaScalar; + double t; + double v[3], x[3]; + double v_tetra[4][3]; + double *p1, *p2; + + for (i=0; iGetId(i); + } + + // Convert all volume cells to tetrahedra + this->CellGrid(cellType,npts,cellptId,arraytetra); + unsigned int totalnewtetra = arraytetra->GetNumberOfCells(); + + for (idtetranew = 0 ; idtetranew < totalnewtetra; idtetranew++) + { + arraytetra->GetNextCell(ptstetra,v_id); + + for (allInside=1, i=0; i<4; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (!(((v[0] >= this->BoundBoxClip[0][0])&&(v[0] <= this->BoundBoxClip[0][1]) && + (v[1] >= this->BoundBoxClip[1][0])&&(v[1] <= this->BoundBoxClip[1][1])&& + (v[2] >= this->BoundBoxClip[2][0])&&(v[2] <= this->BoundBoxClip[2][1])))) + { + //outside,its type might change later (nearby intersection) + allInside = 0; + } + }//for all points of the cell. + + // Test Outside: see(1) + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<4; i++) + { + ptIdout[i] = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v_tetra[i]); + + if (v_tetra[i][0] > this->BoundBoxClip[0][0]) + { + test[0] = 0; + } + if (v_tetra[i][0] < this->BoundBoxClip[0][1]) + { + test[1] = 0; + } + if (v_tetra[i][1] > this->BoundBoxClip[1][0]) + { + test[2] = 0; + } + if (v_tetra[i][1] < this->BoundBoxClip[1][1]) + { + test[3] = 0; + } + if (v_tetra[i][2] > this->BoundBoxClip[2][0]) + { + test[4] = 0; + } + if (v_tetra[i][2] < this->BoundBoxClip[2][1]) + { + test[5] = 0; + } + }//for all points of the cell. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + for (i=0; i<4; i++) + { + if ( locator->InsertUniquePoint(v_tetra[i], iid[i]) ) + { + outPD->CopyData(inPD,ptIdout[i], iid[i]); + } + } + int newCellId = tets[1]->InsertNextCell(4,iid); + outCD[1]->CopyData(inCD,cellId,newCellId); + continue; // Tetrahedron is outside. + } + }//if not allinside. + + for (i=0; i<4; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + // Currently all points are injected because of the possibility + // of intersection point merging. + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + + }//for all points of the tetrahedron. + + if ( allInside ) + { + // Tetrahedron inside. + int newCellId = tets[0]->InsertNextCell(4,iid); + outCD[0]->CopyData(inCD,cellId,newCellId); + continue; + } + + double *pedg1,*pedg2; + + // Tetrahedron Intersection Cases + const unsigned int tab4[6][6] = { {1,1,0,3,3,2}, + {2,0,0,3,2,1}, + {3,3,2,0,2,1}, + {1,0,2,0,1,3}, + {0,0,1,2,3,3}, + {0,1,2,1,2,3}}; + const unsigned int tab3[4][6] = { {0,2,1,1,3,2}, + {0,1,2,0,2,3}, + {0,1,2,1,0,3}, + {0,1,2,0,1,2}}; + const unsigned int tab2[12][5] = { {0,0,1,2,3}, + {2,1,0,1,3}, + {1,0,1,0,3}, + {2,0,1,3,0}, + {3,1,0,1,0}, + {1,0,1,2,0}, + {3,1,0,2,1}, + {2,1,0,0,1}, + {0,0,1,3,1}, + {1,0,1,3,2}, + {3,1,0,0,2}, + {0,0,1,1,2}}; + const unsigned int tab1[12][3] = { {2,3,1}, + {3,2,0}, + {3,0,1}, + {0,3,2}, + {1,3,0}, + {3,1,2}, + {2,1,0}, + {1,2,3}, + {2,0,3}, + {0,2,1}, + {0,1,3}, + {1,0,2}}; + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkCellArray *cellarrayout = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(4,iid); + + // Test Cell intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + // The index of the dimension of the cut plane (x == 0, y == 1, z == 2). + cutInd = planes/2; + + value = this->BoundBoxClip[cutInd][planes%2]; // The plane is always parallel to unitary cube. + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + unsigned int i0,i1; + vtkIdType p_id[4]; + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_tetra[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_tetra[1]); + newPoints->GetPoint(v_id[2],v_tetra[2]); + newPoints->GetPoint(v_id[3],v_tetra[3]); + for (int edgeNum=0; edgeNum < 6; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_tetra[verts[0]]; + p2 = v_tetra[verts[1]]; + + if ( (p1[cutInd] <= value && value <= p2[cutInd]) || + (p2[cutInd] <= value && value <= p1[cutInd]) ) + { + deltaScalar = p2[cutInd] - p1[cutInd]; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + (value - pedg1[cutInd]) / deltaScalar ); + + if ( t == 0.0 ) + { + continue; + } + else if ( t == 1.0 ) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + + num_inter++; + }//if edge intersects value + }//for all edges + + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0; i<4; i++) + { + if (((v_tetra[i][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[i][cutInd] > value) && ((planes % 2) == 1))) + { + // If only one vertex is ouside, so the tetrahedron is outside + // because there is not intersection. + outside = 1; + break; + } + } + if(outside == 0) + { + // else it is possible intersection if other plane + newCellId = newcellArray->InsertNextCell(4,v_id); + } + else + { + newCellId = tets[1]->InsertNextCell(4,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + continue; + } + switch(num_inter) + { + case 4: // We have two wedges + switch(edges_inter) + { + case 1246: + i0 = 0; + break; + case 2345: + i0 = 2; + break; + case 1356: + i0 = 4; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_tetra[3][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[3][cutInd] > value) && ((planes % 2) == 1))) + { + // The v_tetra[3] is outside box, so + // the first wedge is outside + // ps: v_tetra[3] is always in first wedge (see tab) + + tab_id[0] = p_id[tab4[i0+1][0]]; // Inside + tab_id[1] = v_id[tab4[i0+1][1]]; + tab_id[2] = p_id[tab4[i0+1][2]]; + tab_id[3] = p_id[tab4[i0+1][3]]; + tab_id[4] = v_id[tab4[i0+1][4]]; + tab_id[5] = p_id[tab4[i0+1][5]]; + this->CreateTetra(6,tab_id,newcellArray); + + tab_id[0] = p_id[tab4[i0][0]]; // Outside + tab_id[1] = v_id[tab4[i0][1]]; + tab_id[2] = p_id[tab4[i0][2]]; + tab_id[3] = p_id[tab4[i0][3]]; + tab_id[4] = v_id[tab4[i0][4]]; + tab_id[5] = p_id[tab4[i0][5]]; + this->CreateTetra(6,tab_id,cellarrayout); + } + else + { + tab_id[0] = p_id[tab4[i0][0]]; // Inside + tab_id[1] = v_id[tab4[i0][1]]; + tab_id[2] = p_id[tab4[i0][2]]; + tab_id[3] = p_id[tab4[i0][3]]; + tab_id[4] = v_id[tab4[i0][4]]; + tab_id[5] = p_id[tab4[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + + tab_id[0] = p_id[tab4[i0+1][0]]; // Outside + tab_id[1] = v_id[tab4[i0+1][1]]; + tab_id[2] = p_id[tab4[i0+1][2]]; + tab_id[3] = p_id[tab4[i0+1][3]]; + tab_id[4] = v_id[tab4[i0+1][4]]; + tab_id[5] = p_id[tab4[i0+1][5]]; + this->CreateTetra(6,tab_id,cellarrayout); + } + break; + case 3: // We have one tetrahedron and one wedge + switch(edges_inter) + { + case 134: + i0 = 0; + break; + case 125: + i0 = 1; + break; + case 236: + i0 = 2; + break; + case 456: + i0 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_tetra[i0][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[i0][cutInd] > value) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so/ the tetrahedron is outside + tab_id[0] = p_id[tab3[i0][0]]; // Inside + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[tab3[i0][3]]; + tab_id[4] = v_id[tab3[i0][4]]; + tab_id[5] = v_id[tab3[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + + tab_id[0] = p_id[tab3[i0][0]]; // Outside + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[i0]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = p_id[tab3[i0][0]]; + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; // Inside + tab_id[3] = v_id[i0]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = p_id[tab3[i0][0]]; // Outside + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[tab3[i0][3]]; + tab_id[4] = v_id[tab3[i0][4]]; + tab_id[5] = v_id[tab3[i0][5]]; + this->CreateTetra(6,tab_id,cellarrayout); + } + break; + case 2: // We have one tetrahedron and one pyramid + switch(edges_inter) // i1 = vertex of the tetrahedron + { + case 12: + i0 = 0; i1 = 1; + break; + case 13: + i0 = 1; i1 = 0; + break; + case 23: + i0 = 2; i1 = 2; + break; + case 25: + i0 = 3; i1 = 1; + break; + case 26: + i0 = 4; i1 = 2; + break; + case 56: + i0 = 5; i1 = 3; + break; + case 34: + i0 = 6; i1 = 0; + break; + case 46: + i0 = 7; i1 = 3; + break; + case 36: + i0 = 8; i1 = 2; + break; + case 14: + i0 = 9; i1 = 0; + break; + case 15: + i0 = 10; i1 = 1; + break; + case 45: + i0 = 11; i1 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_tetra[i1][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[i1][cutInd] > value) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + tab_id[0] = v_id[tab2[i0][0]]; // Inside + tab_id[1] = p_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = v_id[tab2[i0][3]]; + tab_id[4] = v_id[tab2[i0][4]]; + this->CreateTetra(5,tab_id,newcellArray); + + tab_id[0] = v_id[i1]; // Outside + tab_id[1] = v_id[tab2[i0][4]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = p_id[tab2[i0][1]]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = v_id[i1]; // Inside + tab_id[1] = v_id[tab2[i0][4]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = p_id[tab2[i0][1]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = v_id[tab2[i0][0]]; // Outside + tab_id[1] = p_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = v_id[tab2[i0][3]]; + tab_id[4] = v_id[tab2[i0][4]]; + this->CreateTetra(5,tab_id,cellarrayout); + } + break; + case 1: // We have two tetrahedron. + if ((edges_inter > 6) || (edges_inter < 1)) + { + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_tetra[tab1[2*edges_inter-1][2]][cutInd] < value) && ((planes % 2) == 0)) || + ((v_tetra[tab1[2*edges_inter-1][2]][cutInd] > value) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + + tab_id[0] = p_id[0]; // Inside + tab_id[1] = v_id[tab1[2*edges_inter-2][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-2][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-2][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = p_id[0]; // Outside + tab_id[1] = v_id[tab1[2*edges_inter-1][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-1][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-1][2]]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = p_id[0]; // Inside + tab_id[1] = v_id[tab1[2*edges_inter-1][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-1][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-1][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = p_id[0]; // Outside + tab_id[1] = v_id[tab1[2*edges_inter-2][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-2][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-2][2]]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + break; + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); // Inside + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets[0]->InsertNextCell(npts,v_id); + outCD[0]->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + + totalnewcells = cellarrayout->GetNumberOfCells(); // Outside + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarrayout->GetNextCell(npts,v_id); + newCellId = tets[1]->InsertNextCell(npts,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + cellarrayout->Delete(); + } + arraytetra->Delete(); +} + + +//---------------------------------------------------------------------------- +// ClipHexahedronInOut +// +// The difference between ClipHexahedron and ClipHexahedronInOut is the outputs. +// The ClipHexahedronInOut generate both outputs: inside and outside the clip hexahedron. +// +void vtkBoxClipDataSet::ClipHexahedronInOut(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytetra = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[4]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType ptIdout[4]; + vtkIdType tab_id[6]; + vtkIdType ptstetra = 4; + + int i,j,k; + int allInside; + + vtkIdType edges[6][2] = { {0,1}, {1,2}, {2,0}, + {0,3}, {1,3}, {2,3} }; /* Edges Tetrahedron */ + double deltaScalar; + double p[6], t; + double v_tetra[4][3]; + double v[3], x[3]; + double *p1, *p2; + + unsigned int idtetranew; + unsigned int idcellnew; + unsigned int planes; + + for (i=0; iGetId(i); + } + + this->CellGrid(cellType,npts,cellptId,arraytetra); // Convert all volume cells to tetrahedra + + unsigned int totalnewtetra = arraytetra->GetNumberOfCells(); + for (idtetranew = 0 ; idtetranew < totalnewtetra; idtetranew++) + { + arraytetra->GetNextCell(ptstetra,v_id); + + for (allInside=1, i=0; i<4; i++) + { + cellPts->GetPoint(v_id[i],v); + + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]); + } + + if (!((p[0] <= 0) && (p[1] <= 0) && + (p[2] <= 0) && (p[3] <= 0) && + (p[4] <= 0) && (p[5] <= 0))) + { + allInside = 0; + } + }//for all points of the tetrahedron. + + // Test Outside + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<4; i++) + { + ptIdout[i] = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v_tetra[i]); + + // Use plane equation + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v_tetra[i][0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v_tetra[i][1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v_tetra[i][2] - this->PlanePoint[k][2]); + } + + + for(k=0;k<3;k++) + { + if (p[2*k] < 0) + { + test[2*k] = 0; + } + if (p[2*k+1] < 0) + { + test[2*k+1] = 0; + } + } + + }//for all points of the cell. + + if (!allInside && ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1))) + { + for (i=0; i<4; i++) + { + if ( locator->InsertUniquePoint(v_tetra[i], iid[i]) ) + { + outPD->CopyData(inPD,ptIdout[i], iid[i]); + } + } + int newCellId = tets[1]->InsertNextCell(4,iid); + outCD[1]->CopyData(inCD,cellId,newCellId); + continue; // Tetrahedron is outside. + } + + for (i=0; i<4; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + // Currently all points are injected because of the possibility + // of intersection point merging. + + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + + }//for all points of the tetrahedron. + + if ( allInside ) + { + int newCellId = tets[0]->InsertNextCell(4,iid); // Tetrahedron inside. + outCD[0]->CopyData(inCD,cellId,newCellId); + continue; + } + + //float *pc1 , *pc2; + double *pedg1,*pedg2; + + // Tetrahedron Intersection Cases + const unsigned int tab4[6][6] = { {1,1,0,3,3,2}, + {2,0,0,3,2,1}, + {3,3,2,0,2,1}, + {1,0,2,0,1,3}, + {0,0,1,2,3,3}, + {0,1,2,1,2,3}}; + const unsigned int tab3[4][6] = { {0,2,1,1,3,2}, + {0,1,2,0,2,3}, + {0,1,2,1,0,3}, + {0,1,2,0,1,2}}; + const unsigned int tab2[12][5] = { {0,0,1,2,3}, + {2,1,0,1,3}, + {1,0,1,0,3}, + {2,0,1,3,0}, + {3,1,0,1,0}, + {1,0,1,2,0}, + {3,1,0,2,1}, + {2,1,0,0,1}, + {0,0,1,3,1}, + {1,0,1,3,2}, + {3,1,0,0,2}, + {0,0,1,1,2}}; + const unsigned int tab1[12][3] = { {2,3,1}, + {3,2,0}, + {3,0,1}, + {0,3,2}, + {1,3,0}, + {3,1,2}, + {2,1,0}, + {1,2,3}, + {2,0,3}, + {0,2,1}, + {0,1,3}, + {1,0,2}}; + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkCellArray *cellarrayout = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(4,iid); + + // Test Cell intersection with each plane of box + // FIXME: there is no difference in the for loop (planes has no influence!) + for (planes = 0; planes < 6; planes++) + { + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int i0,i1; + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + vtkIdType p_id[4]; + + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_tetra[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_tetra[1]); + newPoints->GetPoint(v_id[2],v_tetra[2]); + newPoints->GetPoint(v_id[3],v_tetra[3]); + + p[0] = this->PlaneNormal[planes][0]*(v_tetra[0][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[0][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[0][2] - this->PlanePoint[planes][2]); + p[1] = this->PlaneNormal[planes][0]*(v_tetra[1][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[1][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[1][2] - this->PlanePoint[planes][2]); + p[2] = this->PlaneNormal[planes][0]*(v_tetra[2][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[2][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[2][2] - this->PlanePoint[planes][2]); + p[3] = this->PlaneNormal[planes][0]*(v_tetra[3][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_tetra[3][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_tetra[3][2] - this->PlanePoint[planes][2]); + + for (int edgeNum=0; edgeNum < 6; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_tetra[verts[0]]; + p2 = v_tetra[verts[1]]; + double s1 = p[verts[0]]; + double s2 = p[verts[1]]; + if ( (s1 * s2) <=0) + { + deltaScalar = s2 - s1; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + t = s1; s1 = s2; s2 = t; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : + ( - s1) / deltaScalar ); + + if ( t == 0.0 || t == 1.0 ) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + + num_inter++; + }//if edge intersects value + }//for all edges + + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0;i<4;i++) + { + if (p[i] > 0) + { // If only one vertex is ouside, so the tetrahedron is outside + outside = 1; // because there is not intersection. + break; // some vertex could be on plane, so you need to test all vertex + } + } + if (outside == 0) + { + // else it is possible intersection if other plane + newCellId = newcellArray->InsertNextCell(4,v_id); + } + else + { + newCellId = tets[1]->InsertNextCell(4,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + continue; + } + + switch(num_inter) + { + case 4: // We have two wedges + switch(edges_inter) + { + case 1246: + i0 = 0; + break; + case 2345: + i0 = 2; + break; + case 1356: + i0 = 4; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((p[3] > 0) && ((planes % 2) == 0)) || + ((p[3] > 0) && ((planes % 2) == 1))) + { + // The v_tetra[3] is outside box, so the first wedge is outside + // ps: v_tetra[3] is always in first wedge (see tab) + + tab_id[0] = p_id[tab4[i0+1][0]]; // Inside + tab_id[1] = v_id[tab4[i0+1][1]]; + tab_id[2] = p_id[tab4[i0+1][2]]; + tab_id[3] = p_id[tab4[i0+1][3]]; + tab_id[4] = v_id[tab4[i0+1][4]]; + tab_id[5] = p_id[tab4[i0+1][5]]; + this->CreateTetra(6,tab_id,newcellArray); + + tab_id[0] = p_id[tab4[i0][0]]; // Outside + tab_id[1] = v_id[tab4[i0][1]]; + tab_id[2] = p_id[tab4[i0][2]]; + tab_id[3] = p_id[tab4[i0][3]]; + tab_id[4] = v_id[tab4[i0][4]]; + tab_id[5] = p_id[tab4[i0][5]]; + this->CreateTetra(6,tab_id,cellarrayout); + } + else + { + tab_id[0] = p_id[tab4[i0][0]]; // Inside + tab_id[1] = v_id[tab4[i0][1]]; + tab_id[2] = p_id[tab4[i0][2]]; + tab_id[3] = p_id[tab4[i0][3]]; + tab_id[4] = v_id[tab4[i0][4]]; + tab_id[5] = p_id[tab4[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + + tab_id[0] = p_id[tab4[i0+1][0]]; // Outside + tab_id[1] = v_id[tab4[i0+1][1]]; + tab_id[2] = p_id[tab4[i0+1][2]]; + tab_id[3] = p_id[tab4[i0+1][3]]; + tab_id[4] = v_id[tab4[i0+1][4]]; + tab_id[5] = p_id[tab4[i0+1][5]]; + this->CreateTetra(6,tab_id,cellarrayout); + } + + break; + case 3: // We have one tetrahedron and one wedge + switch(edges_inter) + { + case 134: + i0 = 0; + break; + case 125: + i0 = 1; + break; + case 236: + i0 = 2; + break; + case 456: + i0 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((p[i0] > 0) && ((planes % 2) == 0)) || // Isolate vertex is outside box, so + ((p[i0] > 0) && ((planes % 2) == 1))) // the tetrahedron is outside + { + tab_id[0] = p_id[tab3[i0][0]]; // Inside + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[tab3[i0][3]]; + tab_id[4] = v_id[tab3[i0][4]]; + tab_id[5] = v_id[tab3[i0][5]]; + this->CreateTetra(6,tab_id,newcellArray); + + tab_id[0] = p_id[tab3[i0][0]]; // Outside + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[i0]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = p_id[tab3[i0][0]]; // Inside + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[i0]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = p_id[tab3[i0][0]]; // Outside + tab_id[1] = p_id[tab3[i0][1]]; + tab_id[2] = p_id[tab3[i0][2]]; + tab_id[3] = v_id[tab3[i0][3]]; + tab_id[4] = v_id[tab3[i0][4]]; + tab_id[5] = v_id[tab3[i0][5]]; + this->CreateTetra(6,tab_id,cellarrayout); + } + break; + case 2: // We have one tetrahedron and one pyramid + switch(edges_inter) // i1 = vertex of the tetrahedron + { + case 12: + i0 = 0; i1 = 1; + break; + case 13: + i0 = 1; i1 = 0; + break; + case 23: + i0 = 2; i1 = 2; + break; + case 25: + i0 = 3; i1 = 1; + break; + case 26: + i0 = 4; i1 = 2; + break; + case 56: + i0 = 5; i1 = 3; + break; + case 34: + i0 = 6; i1 = 0; + break; + case 46: + i0 = 7; i1 = 3; + break; + case 36: + i0 = 8; i1 = 2; + break; + case 14: + i0 = 9; i1 = 0; + break; + case 15: + i0 = 10; i1 = 1; + break; + case 45: + i0 = 11; i1 = 3; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = %" << edges_inter ); + continue; + } + + if (((p[i1] > 0) && ((planes % 2) == 0)) || // Isolate vertex is outside box, so + ((p[i1] > 0) && ((planes % 2) == 1))) // the tetrahedron is outside + { + tab_id[0] = v_id[tab2[i0][0]]; // Inside + tab_id[1] = p_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = v_id[tab2[i0][3]]; + tab_id[4] = v_id[tab2[i0][4]]; + this->CreateTetra(5,tab_id,newcellArray); + + tab_id[0] = v_id[i1]; // Outside + tab_id[1] = v_id[tab2[i0][4]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = p_id[tab2[i0][1]]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = v_id[i1]; // Inside + tab_id[1] = v_id[tab2[i0][4]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = p_id[tab2[i0][1]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = v_id[tab2[i0][0]]; // Outside + tab_id[1] = p_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + tab_id[3] = v_id[tab2[i0][3]]; + tab_id[4] = v_id[tab2[i0][4]]; + this->CreateTetra(5,tab_id,cellarrayout); + } + break; + case 1: // We have two tetrahedron. + if ((edges_inter > 6) || (edges_inter < 1)) + { + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((p[tab1[2*edges_inter-1][2]] > 0) && ((planes % 2) == 0)) || + ((p[tab1[2*edges_inter-1][2]] > 0) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the tetrahedron is outside + tab_id[0] = p_id[0]; // Inside + tab_id[1] = v_id[tab1[2*edges_inter-2][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-2][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-2][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = p_id[0]; // Outside + tab_id[1] = v_id[tab1[2*edges_inter-1][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-1][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-1][2]]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + else + { + tab_id[0] = p_id[0]; // Inside + tab_id[1] = v_id[tab1[2*edges_inter-1][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-1][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-1][2]]; + newCellId = newcellArray->InsertNextCell(4,tab_id); + + tab_id[0] = p_id[0]; // Outside + tab_id[1] = v_id[tab1[2*edges_inter-2][0]]; + tab_id[2] = v_id[tab1[2*edges_inter-2][1]]; + tab_id[3] = v_id[tab1[2*edges_inter-2][2]]; + newCellId = cellarrayout->InsertNextCell(4,tab_id); + } + break; + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); // Inside + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets[0]->InsertNextCell(npts,v_id); + outCD[0]->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + + totalnewcells = cellarrayout->GetNumberOfCells(); // Outside + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarrayout->GetNextCell(npts,v_id); + newCellId = tets[1]->InsertNextCell(npts,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + cellarrayout->Delete(); + } + arraytetra->Delete(); +} + +//------------------------------------------------------- + +//------------------------------------------------------- +void vtkBoxClipDataSet::ClipBox2D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytriangle = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[3]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType tab_id[6]; + vtkIdType ptstriangle = 3; + + int i,j; + unsigned int allInside; + unsigned int planes; + unsigned int cutInd; + + vtkIdType edges[3][2] = { {0,1}, {1,2}, {2,0}}; /* Edges Triangle*/ + double value,deltaScalar; + double t, *p1, *p2; + double v[3],x[3]; + double v_triangle[3][3]; + + for (i=0; iGetId(i); + } + + // Convert all 2d cells to triangle + this->CellGrid(cellType,npts,cellptId,arraytriangle); + + unsigned int totalnewtriangle= arraytriangle->GetNumberOfCells(); + unsigned int idtrianglenew; + + for (idtrianglenew = 0 ; idtrianglenew < totalnewtriangle; idtrianglenew++) + { + arraytriangle->GetNextCell(ptstriangle,v_id); + + for (allInside=1, i=0; i<3; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (!(((v[0] >= this->BoundBoxClip[0][0])&&(v[0] <= this->BoundBoxClip[0][1]) && + (v[1] >= this->BoundBoxClip[1][0])&&(v[1] <= this->BoundBoxClip[1][1])&& + (v[2] >= this->BoundBoxClip[2][0])&&(v[2] <= this->BoundBoxClip[2][1])))) + { + //outside,its type might change later (nearby intersection) + allInside = 0; + } + } + + // Test Outside: + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<3; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (v[0] > this->BoundBoxClip[0][0]) + { + test[0] = 0; + } + if (v[0] < this->BoundBoxClip[0][1]) + { + test[1] = 0; + } + if (v[1] > this->BoundBoxClip[1][0]) + { + test[2] = 0; + } + if (v[1] < this->BoundBoxClip[1][1]) + { + test[3] = 0; + } + if (v[2] > this->BoundBoxClip[2][0]) + { + test[4] = 0; + } + if (v[2] < this->BoundBoxClip[2][1]) + { + test[5] = 0; + } + }//for all points of the triangle. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + continue; // Triangle is outside. + } + } + + for (i=0; i<3; i++) + { + // Currently all points are injected because of the possibility + // of intersection point merging. + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + + }//for all points of the triangle. + + if ( allInside ) + { + // Triangle inside. + int newCellId = tets->InsertNextCell(3,iid); + outCD->CopyData(inCD,cellId,newCellId); + continue; + } + + //float *pc1 , *pc2; + double *pedg1,*pedg2; + + // Triangle intersection cases + + unsigned int tab2[3][4] = { {1,2,1,0}, + {2,0,0,1}, + {0,1,0,1}}; + unsigned int tab1[3][2] = { {2,1}, + {0,2}, + {1,0}}; + + vtkCellArray *cellarray = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(3,iid); + unsigned int idcellnew; + + // Test triangle intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + // The index of the dimension of the cut plane (x == 0, y == 1, z == 2). + cutInd = planes/2; + + // The plane is always parallel to unitary cube. + value = this->BoundBoxClip[cutInd][planes%2]; + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + unsigned int i0; + vtkIdType p_id[3]; + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_triangle[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_triangle[1]); + newPoints->GetPoint(v_id[2],v_triangle[2]); + for (int edgeNum=0; edgeNum < 3; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_triangle[verts[0]]; + p2 = v_triangle[verts[1]]; + + if ( (p1[cutInd] <= value && value <= p2[cutInd]) || + (p2[cutInd] <= value && value <= p1[cutInd]) ) + { + deltaScalar = p2[cutInd] - p1[cutInd]; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : (value - pedg1[cutInd]) / deltaScalar ); + + if ( t == 0.0 || t == 1.0 ) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + + num_inter++; + }//if edge intersects value + }//for all edges + + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0; i<3; i++) + { + if (((v_triangle[i][cutInd] < value) && ((planes % 2) == 0)) || + // If only one vertex is ouside, so the triangle is outside + ((v_triangle[i][cutInd] > value) && ((planes % 2) == 1))) // because there is not intersection. + { + outside = 1; + break; + } + } + if(outside == 0) + { + // else it is possible intersection if other plane + newCellId = newcellArray->InsertNextCell(3,v_id); + } + continue; + } + switch(num_inter) + { + case 2: // We have one quad and one triangle + switch(edges_inter) + { + case 12: + i0 = 1; + break; + case 23: + i0 = 2; + break; + case 13: + i0 = 0; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_triangle[i0][cutInd] < value) && ((planes % 2) == 0)) || + ((v_triangle[i0][cutInd] > value) && ((planes % 2) == 1))) + { + // The v_triangle[i0] is outside box, so + // The Quad is inside: two triangles: (v0,v1,p0) and (p0,p1,v1) + tab_id[0] = v_id[tab2[i0][0]]; + tab_id[1] = v_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + tab_id[0] = p_id[tab2[i0][2]]; + tab_id[1] = p_id[tab2[i0][3]]; + tab_id[2] = v_id[tab2[i0][0]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + else + { + // The Triangle is inside: (v0,p0,p1) + // The correct winding of the new triangle depends on where the + // plane intersected the original triangle. + switch (edges_inter) + { + case 12: + case 23: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[1]; + tab_id[2] = p_id[0]; + break; + case 13: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[0]; + tab_id[2] = p_id[1]; + break; + } + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + break; + + case 1: // We have two triangles + switch(edges_inter) + { + case 1: + i0 = 0; + break; + case 2: + i0 = 1; + break; + case 3: + i0 = 2; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_triangle[i0][cutInd] < value) && ((planes % 2) == 0)) || + ((v_triangle[i0][cutInd] > value) && ((planes % 2) == 1))) + { + // Test one of the vertices vertex i0 is outside + tab_id[0] = v_id[tab1[i0][1]]; + tab_id[1] = v_id[tab1[i0][0]]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + else + { + tab_id[0] = v_id[tab1[i0][0]]; + tab_id[1] = v_id[i0]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + break; + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets->InsertNextCell(npts,v_id); + outCD->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + } + arraytriangle->Delete(); +} +//------------------------------------------------------- + +void vtkBoxClipDataSet::ClipBoxInOut2D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytriangle = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[3]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType ptIdout[4]; + vtkIdType tab_id[6]; + vtkIdType ptstriangle = 3; + + int i,j; + unsigned int allInside; + unsigned int cutInd; + unsigned int planes; + unsigned int idcellnew; + + vtkIdType edges[3][2] = { {0,1}, {1,2}, {2,0}}; /* Edges Triangle */ + double value,deltaScalar; + double t, *p1, *p2; + double v[3],x[3]; + double v_triangle[3][3]; + + for (i=0; iGetId(i); + } + + // Convert all 2D cells to triangle + this->CellGrid(cellType,npts,cellptId,arraytriangle); + unsigned int totalnewtriangle = arraytriangle->GetNumberOfCells(); + unsigned int idtrianglenew; + + for (idtrianglenew = 0 ; idtrianglenew < totalnewtriangle; idtrianglenew++) + { + arraytriangle->GetNextCell(ptstriangle,v_id); + + for (allInside=1, i=0; i<3; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (!(((v[0] >= this->BoundBoxClip[0][0])&&(v[0] <= this->BoundBoxClip[0][1]) && + (v[1] >= this->BoundBoxClip[1][0])&&(v[1] <= this->BoundBoxClip[1][1])&& + (v[2] >= this->BoundBoxClip[2][0])&&(v[2] <= this->BoundBoxClip[2][1])))) + { + //outside,its type might change later (nearby intersection) + allInside = 0; + } + }//for all points of the cell. + + // Test Outside: see(1) + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<3; i++) + { + ptIdout[i] = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v_triangle[i]); + + if (v_triangle[i][0] > this->BoundBoxClip[0][0]) + { + test[0] = 0; + } + if (v_triangle[i][0] < this->BoundBoxClip[0][1]) + { + test[1] = 0; + } + if (v_triangle[i][1] > this->BoundBoxClip[1][0]) + { + test[2] = 0; + } + if (v_triangle[i][1] < this->BoundBoxClip[1][1]) + { + test[3] = 0; + } + if (v_triangle[i][2] > this->BoundBoxClip[2][0]) + { + test[4] = 0; + } + if (v_triangle[i][2] < this->BoundBoxClip[2][1]) + { + test[5] = 0; + } + + }//for all points of the cell. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + for (i=0; i<3; i++) + { + if ( locator->InsertUniquePoint(v_triangle[i], iid[i]) ) + { + outPD->CopyData(inPD,ptIdout[i], iid[i]); + } + } + + int newCellId = tets[1]->InsertNextCell(3,iid); + outCD[1]->CopyData(inCD,cellId,newCellId); + continue; // Triangle is outside. + } + }//if not allInside. + + for (i=0; i<3; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + // Currently all points are injected because of the possibility + // of intersection point merging. + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + }//for all points of the triangle. + + if ( allInside ) + { + // Triangle inside. + int newCellId = tets[0]->InsertNextCell(3,iid); + outCD[0]->CopyData(inCD,cellId,newCellId); + continue; + } + + //float *pc1 , *pc2; + double *pedg1,*pedg2; + + // Triangle intersection cases + + unsigned int tab2[3][4] = { {1,2,1,0}, + {2,0,0,1}, + {0,1,0,1}}; + unsigned int tab1[3][2] = { {2,1}, + {0,2}, + {1,0}}; + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkCellArray *cellarrayout = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(3,iid); + + // Test Cell intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + // The index of the dimension of the cut plane (x == 0, y == 1, z == 2). + cutInd = planes/2; + + // The plane is always parallel to unitary cube. + value = this->BoundBoxClip[cutInd][planes%2]; + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + unsigned int i0; + vtkIdType p_id[3]; + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_triangle[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_triangle[1]); + newPoints->GetPoint(v_id[2],v_triangle[2]); + for (int edgeNum=0; edgeNum < 3; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_triangle[verts[0]]; + p2 = v_triangle[verts[1]]; + + if ( (p1[cutInd] <= value && value <= p2[cutInd]) || + (p2[cutInd] <= value && value <= p1[cutInd]) ) + { + deltaScalar = p2[cutInd] - p1[cutInd]; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : (value - pedg1[cutInd]) / deltaScalar ); + + if ( t == 0.0 ) + { + continue; + } + else if ( t == 1.0 ) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + + num_inter++; + }//if edge intersects value + }//for all edges + + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0; i<3; i++) + { + if (((v_triangle[i][cutInd] < value) && ((planes % 2) == 0)) || + ((v_triangle[i][cutInd] > value) && ((planes % 2) == 1))) + { + // If only one vertex is ouside, so the triangle is outside + // because there is not intersection. + outside = 1; + break; + } + } + if(outside == 0) + { + // else it is possible intersection if other plane + newCellId = newcellArray->InsertNextCell(3,v_id); + } + else + { + newCellId = tets[1]->InsertNextCell(3,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + continue; + } + switch(num_inter) + { + case 2: // We have one quad and one triangle + // i0 gets the index of the triangle point that lies alone on + // one side of the plane. + switch(edges_inter) + { + case 12: + i0 = 1; + break; + case 23: + i0 = 2; + break; + case 13: + i0 = 0; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_triangle[i0][cutInd] < value) && ((planes % 2) == 0)) || + ((v_triangle[i0][cutInd] > value) && ((planes % 2) == 1))) + { + // The v_triangle[i0] is outside box, so + + tab_id[0] = v_id[tab2[i0][0]]; // Quad Inside + tab_id[1] = v_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + tab_id[0] = p_id[tab2[i0][2]]; + tab_id[1] = p_id[tab2[i0][3]]; + tab_id[2] = v_id[tab2[i0][0]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + + switch (edges_inter) // Triangle Outside + { + case 12: + case 23: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[1]; + tab_id[2] = p_id[0]; + break; + case 13: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[0]; + tab_id[2] = p_id[1]; + break; + } + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + else + { + // The Triangle is inside: (v0,p0,p1) + switch (edges_inter) + { + case 12: + case 23: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[1]; + tab_id[2] = p_id[0]; + break; + case 13: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[0]; + tab_id[2] = p_id[1]; + break; + } + newCellId = newcellArray->InsertNextCell(3,tab_id); + + tab_id[0] = v_id[tab2[i0][0]]; // Quad is Outside + tab_id[1] = v_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + tab_id[0] = p_id[tab2[i0][2]]; + tab_id[1] = p_id[tab2[i0][3]]; + tab_id[2] = v_id[tab2[i0][0]]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + break; + + case 1: // We have two triangles + switch(edges_inter) + { + case 1: + i0 = 0; + break; + case 2: + i0 = 1; + break; + case 3: + i0 = 2; + break; + default: + vtkErrorMacro( << "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter ); + continue; + } + if (((v_triangle[i0][cutInd] < value) && ((planes % 2) == 0)) || + ((v_triangle[i0][cutInd] > value) && ((planes % 2) == 1))) + { + // Test one of the vertices vertex i0 is outside + + tab_id[0] = v_id[tab1[i0][1]]; // Inside + tab_id[1] = v_id[tab1[i0][0]]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + + tab_id[0] = v_id[tab1[i0][0]]; // Outside + tab_id[1] = v_id[i0]; + tab_id[2] = p_id[0]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + else + { + tab_id[0] = v_id[tab1[i0][0]]; // Inside + tab_id[1] = v_id[i0]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + + tab_id[0] = v_id[tab1[i0][1]]; // Outside + tab_id[1] = v_id[tab1[i0][0]]; + tab_id[2] = p_id[0]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + break; + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); // Inside + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets[0]->InsertNextCell(npts,v_id); + outCD[0]->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + + totalnewcells = cellarrayout->GetNumberOfCells(); // Outside + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarrayout->GetNextCell(npts,v_id); + newCellId = tets[1]->InsertNextCell(npts,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + cellarrayout->Delete(); + } + arraytriangle->Delete(); +} + +//------------------------------------------------------- + +void vtkBoxClipDataSet::ClipHexahedron2D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytriangle = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[3]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType tab_id[6]; + vtkIdType ptstriangle = 3; + + int i,j,k; + unsigned int allInside; + unsigned int idtrianglenew; + unsigned int idcellnew; + unsigned int planes; + + vtkIdType edges[3][2] = { {0,1}, {1,2}, {2,0}}; + double deltaScalar; + double t, *p1, *p2; + double v[3],x[3]; + double p[6]; + double v_triangle[3][3]; + + for (i=0; iGetId(i); + } + + this->CellGrid(cellType,npts,cellptId,arraytriangle); // Convert all volume cells to triangle + + unsigned int totalnewtriangle = arraytriangle->GetNumberOfCells(); + for (idtrianglenew = 0 ; idtrianglenew < totalnewtriangle; idtrianglenew++) + { + arraytriangle->GetNextCell(ptstriangle,v_id); + + for (allInside=1, i=0; i<3; i++) + { + cellPts->GetPoint(v_id[i],v); + + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0])+ + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]); + } + + if (!((p[0] <= 0) && (p[1] <= 0) && + (p[2] <= 0) && (p[3] <= 0) && + (p[4] <= 0) && (p[5] <= 0))) + { + allInside = 0; + } + }//for all points of the triangle. + + // Test Outside + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<3; i++) + { + cellPts->GetPoint(v_id[i],v); + + // Use plane equation + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0])+ + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]); + } + + for(k=0;k<3;k++) + { + if (p[2*k] < 0) + { + test[2*k] = 0; + } + if (p[2*k+1] < 0) + { + test[2*k+1] = 0; + } + } + }//for all points of the cell. + + if (!allInside && ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1))) + { + continue; // Triangle is outside. + } + + for (i=0; i<3; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + // Currently all points are injected because of the possibility + // of intersection point merging. + + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + }//for all points of the triangle. + + if ( allInside ) + { + int newCellId = tets->InsertNextCell(3,iid); // Triangle inside. + outCD->CopyData(inCD,cellId,newCellId); + continue; + } + + //float *pc1 , *pc2; + double *pedg1,*pedg2; + + unsigned int tab2[3][4] = { {1,2,1,0}, + {2,0,0,1}, + {0,1,0,1}}; + unsigned int tab1[3][2] = { {2,1}, + {0,2}, + {1,0}}; + + vtkCellArray *cellarray = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(3,iid); + + // Test Cell intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int i0; + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + vtkIdType p_id[3]; + + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_triangle[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_triangle[1]); + newPoints->GetPoint(v_id[2],v_triangle[2]); + + p[0] = this->PlaneNormal[planes][0]*(v_triangle[0][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_triangle[0][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_triangle[0][2] - this->PlanePoint[planes][2]); + p[1] = this->PlaneNormal[planes][0]*(v_triangle[1][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_triangle[1][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_triangle[1][2] - this->PlanePoint[planes][2]); + p[2] = this->PlaneNormal[planes][0]*(v_triangle[2][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_triangle[2][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_triangle[2][2] - this->PlanePoint[planes][2]); + + for (int edgeNum=0; edgeNum < 3; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_triangle[verts[0]]; + p2 = v_triangle[verts[1]]; + double s1 = p[verts[0]]; + double s2 = p[verts[1]]; + if ( (s1 * s2) <=0) + { + deltaScalar = s2 - s1; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + t = s1; s1 = s2; s2 = t; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : ( - s1) / deltaScalar ); + + if ( t == 0.0 || t == 1.0 ) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + + num_inter++; + }//if edge intersects value + }//for all edges + + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0;i<3;i++) + { + if (p[i] > 0) // If only one vertex is ouside, so the triangle is outside + { + outside = 1; // because there is not intersection. + break; // some vertex could be on plane, so you need to test all vertex + } + } + if (outside == 0) + { + // else it is possible intersection if other plane + newCellId = newcellArray->InsertNextCell(3,v_id); + } + continue; + } + switch(num_inter) + { + case 2: // We have one quad and one triangle + // i0 gets the index of the triangle point that lies alone on + // one side of the plane. + switch(edges_inter) + { + case 12: + i0 = 1; + break; + case 23: + i0 = 2; + break; + case 13: + i0 = 0; + break; + default: + vtkErrorMacro(<< "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter); + continue; + } + if (((p[i0] > 0) && ((planes % 2) == 0)) || // The v_triangle[3] is outside box, so + ((p[i0] > 0) && ((planes % 2) == 1))) // the first wedge is outside + { + // The v_triangle[3] is outside box, so the quad is outside + // The Quad is inside: two triangles: (v0,v1,p0) and (p0,p1,v1) + tab_id[0] = v_id[tab2[i0][0]]; + tab_id[1] = v_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + tab_id[0] = p_id[tab2[i0][2]]; + tab_id[1] = p_id[tab2[i0][3]]; + tab_id[2] = v_id[tab2[i0][0]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + else + { + // The Triangle is inside: (v0,p0,p1) + // The correct winding of the new triangle depends on where the + // plane intersected the original triangle. + switch (edges_inter) + { + case 12: + case 23: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[1]; + tab_id[2] = p_id[0]; + break; + case 13: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[0]; + tab_id[2] = p_id[1]; + break; + } + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + break; + + case 1: // We have two triangles + switch(edges_inter) + { + case 1: + i0 = 0; + break; + case 2: + i0 = 1; + break; + case 3: + i0 = 2; + break; + default: + vtkErrorMacro(<< "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter); + continue; + } + if (((p[i0] > 0) && ((planes % 2) == 0)) || + ((p[i0] > 0) && ((planes % 2) == 1))) + { + // Isolate vertex is outside box, so the triangle is outside + tab_id[0] = v_id[tab1[i0][1]]; + tab_id[1] = v_id[tab1[i0][0]]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + else + { + tab_id[0] = v_id[tab1[i0][0]]; + tab_id[1] = v_id[i0]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + } + break; + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets->InsertNextCell(npts,v_id); + outCD->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + } + arraytriangle->Delete(); +} + +//------------------------------------------------------- + +void vtkBoxClipDataSet::ClipHexahedronInOut2D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **tets, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arraytriangle = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[3]; + vtkIdType *v_id = NULL; + vtkIdType *verts, v1, v2; + vtkIdType ptId; + vtkIdType ptIdout[3]; + vtkIdType tab_id[6]; + vtkIdType ptstriangle = 3; + + int i,j, k; + unsigned int allInside; + unsigned int idtrianglenew; + unsigned int idcellnew; + unsigned int planes; + + vtkIdType edges[3][2] = { {0,1}, {1,2}, {2,0}}; /* Edges Triangle */ + double deltaScalar; + double t, *p1, *p2; + double v[3],x[3]; + double p[6]; + double v_triangle[3][3]; + + for (i=0; iGetId(i); + } + + // Convert all polygon cells to triangles + this->CellGrid(cellType,npts,cellptId,arraytriangle); + + unsigned int totalnewtriangle = arraytriangle->GetNumberOfCells(); + for (idtrianglenew = 0 ; idtrianglenew < totalnewtriangle; idtrianglenew++) + { + arraytriangle->GetNextCell(ptstriangle,v_id); + + for (allInside=1, i=0; i<3; i++) + { + cellPts->GetPoint(v_id[i],v); + + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0])+ + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]); + } + + if (!((p[0] <= 0) && (p[1] <= 0) && + (p[2] <= 0) && (p[3] <= 0) && + (p[4] <= 0) && (p[5] <= 0))) + { + allInside = 0; + } + }//for all points of the trianglehedron. + + // Test Outside + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<3; i++) + { + ptIdout[i] = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v_triangle[i]); + + // Use plane equation + for(k=0;k<6;k++) + { + p[k] = this->PlaneNormal[k][0]*(v_triangle[i][0] - this->PlanePoint[k][0])+ + this->PlaneNormal[k][1]*(v_triangle[i][1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v_triangle[i][2] - this->PlanePoint[k][2]); + } + + for(k=0;k<3;k++) + { + if (p[2*k] < 0) + { + test[2*k] = 0; + } + if (p[2*k+1] < 0) + { + test[2*k+1] = 0; + } + } + }//for all points of the cell. + + if (!allInside && ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1))) + { + for (i=0; i<3; i++) + { + if ( locator->InsertUniquePoint(v_triangle[i], iid[i]) ) + { + outPD->CopyData(inPD,ptIdout[i], iid[i]); + } + } + + int newCellId = tets[1]->InsertNextCell(3,iid); + outCD[1]->CopyData(inCD,cellId,newCellId); + continue; // Triangle is outside. + } + + for (i=0; i<3; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + // Currently all points are injected because of the possibility + // of intersection point merging. + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + + }//for all points of the trianglehedron. + + if ( allInside ) + { + int newCellId = tets[0]->InsertNextCell(3,iid); // Tetrahedron inside. + outCD[0]->CopyData(inCD,cellId,newCellId); + continue; + } + + double *pedg1,*pedg2; + + unsigned int tab2[3][4] = { {1, 2, 1, 0}, + {2, 0, 0, 1}, + {0, 1, 0, 1} }; + unsigned int tab1[3][2] = { {2, 1}, + {0, 2}, + {1, 0} }; + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkCellArray *cellarrayout = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(3,iid); + + // Test Cell intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + unsigned int i0; + unsigned int num_inter = 0; + unsigned int edges_inter = 0; + vtkIdType p_id[3]; + + cellarray->GetNextCell(npts,v_id); + + newPoints->GetPoint(v_id[0],v_triangle[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1],v_triangle[1]); + newPoints->GetPoint(v_id[2],v_triangle[2]); + + p[0] = this->PlaneNormal[planes][0]*(v_triangle[0][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_triangle[0][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_triangle[0][2] - this->PlanePoint[planes][2]); + p[1] = this->PlaneNormal[planes][0]*(v_triangle[1][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_triangle[1][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_triangle[1][2] - this->PlanePoint[planes][2]); + p[2] = this->PlaneNormal[planes][0]*(v_triangle[2][0] - this->PlanePoint[planes][0]) + + this->PlaneNormal[planes][1]*(v_triangle[2][1] - this->PlanePoint[planes][1]) + + this->PlaneNormal[planes][2]*(v_triangle[2][2] - this->PlanePoint[planes][2]); + + for (int edgeNum=0; edgeNum < 3; edgeNum++) + { + verts = edges[edgeNum]; + + p1 = v_triangle[verts[0]]; + p2 = v_triangle[verts[1]]; + double s1 = p[verts[0]]; + double s2 = p[verts[1]]; + if ( (s1 * s2) <=0) + { + deltaScalar = s2 - s1; + + if (deltaScalar > 0) + { + pedg1 = p1; pedg2 = p2; + v1 = verts[0]; v2 = verts[1]; + } + else + { + pedg1 = p2; pedg2 = p1; + v1 = verts[1]; v2 = verts[0]; + deltaScalar = -deltaScalar; + t = s1; s1 = s2; s2 = t; + } + + // linear interpolation + t = ( deltaScalar == 0.0 ? 0.0 : ( - s1) / deltaScalar ); + + if ( t == 0.0 || t == 1.0) + { + continue; + } + + for (j=0; j<3; j++) + { + x[j] = pedg1[j] + t*(pedg2[j] - pedg1[j]); + } + + // Incorporate point into output and interpolate edge data as necessary + edges_inter = edges_inter * 10 + (edgeNum+1); + + if ( locator->InsertUniquePoint(x, p_id[num_inter]) ) + { + outPD->InterpolateEdge(inPD, p_id[num_inter], cellIds->GetId(v1), + cellIds->GetId(v2), t); + } + + num_inter++; + }//if edge intersects value + }//for all edges + + if (num_inter == 0) + { + unsigned int outside = 0; + for(i=0;i<3;i++) + { + if (p[i] > 0) // If only one vertex is ouside, so the trianglehedron is outside + { + outside = 1; // because there is not intersection. + break; // some vertex could be on plane, so you need to test all vertex + } + } + if (outside == 0) + { + // else it is possible intersection if other plane + newCellId = newcellArray->InsertNextCell(3,v_id); + } + else + { + newCellId = tets[1]->InsertNextCell(3,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + continue; + } + switch(num_inter) + { + case 2: // We have one quad and one triangle + switch(edges_inter) + { + case 12: + i0 = 1; + break; + case 23: + i0 = 2; + break; + case 13: + i0 = 0; + break; + default: + vtkErrorMacro(<< "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter); + continue; + } + + if (((p[i0] > 0) && ((planes % 2) == 0)) || // The v_triangle[3] is outside box, so + ((p[i0] > 0) && ((planes % 2) == 1))) // the first wedge is outside + { + // The Quad is inside: two triangles: (v0,v1,p0) and (p0,p1,v1) + tab_id[0] = v_id[tab2[i0][0]]; + tab_id[1] = v_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + tab_id[0] = p_id[tab2[i0][2]]; + tab_id[1] = p_id[tab2[i0][3]]; + tab_id[2] = v_id[tab2[i0][0]]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + + + switch (edges_inter) // Triangle Outside + { + case 12: + case 23: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[1]; + tab_id[2] = p_id[0]; + break; + case 13: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[0]; + tab_id[2] = p_id[1]; + break; + } + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + else + { + // The Triangle is inside: (v0,p0,p1) + switch (edges_inter) + { + case 12: + case 23: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[1]; + tab_id[2] = p_id[0]; + break; + case 13: + tab_id[0] = v_id[i0]; + tab_id[1] = p_id[0]; + tab_id[2] = p_id[1]; + break; + } + newCellId = newcellArray->InsertNextCell(3,tab_id); + + // The Quad is outside: two triangles: (v0,v1,p0) and (p0,p1,v1) + tab_id[0] = v_id[tab2[i0][0]]; + tab_id[1] = v_id[tab2[i0][1]]; + tab_id[2] = p_id[tab2[i0][2]]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + tab_id[0] = p_id[tab2[i0][2]]; + tab_id[1] = p_id[tab2[i0][3]]; + tab_id[2] = v_id[tab2[i0][0]]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + break; + + case 1: // We have two triangles + switch(edges_inter) + { + case 1: + i0 = 0; + break; + case 2: + i0 = 1; + break; + case 3: + i0 = 2; + break; + default: + vtkErrorMacro(<< "Intersection not found: Num_inter = " << + num_inter << " Edges_inter = " << edges_inter); + continue; + } + if (((p[i0] > 0) && ((planes % 2) == 0)) || // Isolate vertex is outside box, so + ((p[i0] > 0) && ((planes % 2) == 1))) // the triangle is outside + { + tab_id[0] = v_id[tab1[i0][1]]; // Inside + tab_id[1] = v_id[tab1[i0][0]]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + + tab_id[0] = v_id[tab1[i0][0]]; // Outside + tab_id[1] = v_id[i0]; + tab_id[2] = p_id[0]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + else + { + tab_id[0] = v_id[tab1[i0][0]]; // Inside + tab_id[1] = v_id[i0]; + tab_id[2] = p_id[0]; + newCellId = newcellArray->InsertNextCell(3,tab_id); + + tab_id[0] = v_id[tab1[i0][1]]; // Outside + tab_id[1] = v_id[tab1[i0][0]]; + tab_id[2] = p_id[0]; + newCellId = cellarrayout->InsertNextCell(3,tab_id); + } + break; + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } //for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); // Inside + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = tets[0]->InsertNextCell(npts,v_id); + outCD[0]->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + + totalnewcells = cellarrayout->GetNumberOfCells(); // Outside + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarrayout->GetNextCell(npts,v_id); + newCellId = tets[1]->InsertNextCell(npts,v_id); + outCD[1]->CopyData(inCD,cellId,newCellId); + } + cellarrayout->Delete(); + } + arraytriangle->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipBox1D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *lines, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayline = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[2]; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType tab_id[2]; + vtkIdType ptsline = 2; + + int i,j; + unsigned int allInside; + unsigned int planes; + unsigned int cutInd; + + double value; + double t; + double v[3],x[3]; + double v_line[2][3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 1d cells to single line. + this->CellGrid(cellType, npts, cellptId, arrayline); + + unsigned int totalnewline = arrayline->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewline; idlinenew++) + { + arrayline->GetNextCell(ptsline, v_id); + + for (allInside=1, i=0; i<2; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (!( (v[0] >= this->BoundBoxClip[0][0]) + && (v[0] <= this->BoundBoxClip[0][1]) + && (v[1] >= this->BoundBoxClip[1][0]) + && (v[1] <= this->BoundBoxClip[1][1]) + && (v[2] >= this->BoundBoxClip[2][0]) + && (v[2] <= this->BoundBoxClip[2][1]) )) + { + //outside + allInside = 0; + } + } + + // Test Outside: + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<2; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (v[0] > this->BoundBoxClip[0][0]) + { + test[0] = 0; + } + if (v[0] < this->BoundBoxClip[0][1]) + { + test[1] = 0; + } + if (v[1] > this->BoundBoxClip[1][0]) + { + test[2] = 0; + } + if (v[1] < this->BoundBoxClip[1][1]) + { + test[3] = 0; + } + if (v[2] > this->BoundBoxClip[2][0]) + { + test[4] = 0; + } + if (v[2] < this->BoundBoxClip[2][1]) + { + test[5] = 0; + } + }//for all points of the line. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + continue; // Line is outside. + } + }//if not allInside + + for (i=0; i<2; i++) + { + // Currently all points are injected because of the possibility + // of intersection point merging. + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + }//for all points of the triangle. + + if ( allInside ) + { + // Triangle inside. + int newCellId = lines->InsertNextCell(2,iid); + outCD->CopyData(inCD,cellId,newCellId); + continue; + } + + vtkCellArray *cellarray = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(2,iid); + unsigned int idcellnew; + + // Test triangle intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + // The index of the dimension of the cut plane (x == 0, y == 1, z == 2). + cutInd = planes/2; + + // The plane is always parallel to unitary cube. + value = this->BoundBoxClip[cutInd][planes%2]; + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + vtkIdType p_id; + cellarray->GetNextCell(npts, v_id); + + newPoints->GetPoint(v_id[0], v_line[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1], v_line[1]); + + // Check to see if line is inside plane. + if ( ( (planes%2 == 0) + && (v_line[0][cutInd] >= value) + && (v_line[1][cutInd] >= value) ) + || ( (planes%2 == 1) + && (v_line[0][cutInd] <= value) + && (v_line[1][cutInd] <= value) ) ) + { + newCellId = newcellArray->InsertNextCell(2, v_id); + continue; + } + + // Check to see if line is outside plane. + if ( ( (planes%2 == 0) + && (v_line[0][cutInd] <= value) + && (v_line[1][cutInd] <= value) ) + || ( (planes%2 == 1) + && (v_line[0][cutInd] >= value) + && (v_line[1][cutInd] >= value) ) ) + { + continue; + } + + // If we are here, the plane intersects the line segment. + t = (value - v_line[0][cutInd])/(v_line[1][cutInd] - v_line[0][cutInd]); + for (j = 0; j < 3; j++) + { + x[j] = (v_line[1][j] - v_line[0][j])*t + v_line[0][j]; + } + + // Incorporate point into output and interpolate edge data as + // necessary. + if (locator->InsertUniquePoint(x, p_id)) + { + outPD->InterpolateEdge(inPD, p_id, cellIds->GetId(0), + cellIds->GetId(1), t); + } + + // Add the clipped line to the output. + if ( ((planes%2 == 0) && (v_line[0][cutInd] >= value)) + || ((planes%2 == 1) && (v_line[0][cutInd] <= value)) ) + { + // First point of line is inside. + tab_id[0] = v_id[0]; + tab_id[1] = p_id; + newcellArray->InsertNextCell(2, tab_id); + } + else + { + // Second point of line is inside. + tab_id[0] = p_id; + tab_id[1] = v_id[1]; + newcellArray->InsertNextCell(2, tab_id); + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } // for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = lines->InsertNextCell(npts,v_id); + outCD->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + } + arrayline->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipBoxInOut1D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **lines, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayline = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[2]; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType tab_id[2]; + vtkIdType ptsline = 2; + + int i,j; + unsigned int allInside; + unsigned int planes; + unsigned int cutInd; + + double value; + double t; + double v[3],x[3]; + double v_line[2][3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 1d cells to single line. + this->CellGrid(cellType, npts, cellptId, arrayline); + + unsigned int totalnewline = arrayline->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewline; idlinenew++) + { + arrayline->GetNextCell(ptsline, v_id); + + for (allInside=1, i=0; i<2; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + if (!( (v[0] >= this->BoundBoxClip[0][0]) + && (v[0] <= this->BoundBoxClip[0][1]) + && (v[1] >= this->BoundBoxClip[1][0]) + && (v[1] <= this->BoundBoxClip[1][1]) + && (v[2] >= this->BoundBoxClip[2][0]) + && (v[2] <= this->BoundBoxClip[2][1]) )) + { + //outside + allInside = 0; + } + + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD, ptId, iid[i]); + } + } + + // Test Outside: + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<2; i++) + { + cellPts->GetPoint(v_id[i],v); + + if (v[0] > this->BoundBoxClip[0][0]) + { + test[0] = 0; + } + if (v[0] < this->BoundBoxClip[0][1]) + { + test[1] = 0; + } + if (v[1] > this->BoundBoxClip[1][0]) + { + test[2] = 0; + } + if (v[1] < this->BoundBoxClip[1][1]) + { + test[3] = 0; + } + if (v[2] > this->BoundBoxClip[2][0]) + { + test[4] = 0; + } + if (v[2] < this->BoundBoxClip[2][1]) + { + test[5] = 0; + } + }//for all points of the line. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + int newCellId = lines[1]->InsertNextCell(2, iid); + outCD[1]->CopyData(inCD, cellId, newCellId); + continue; // Line is outside. + } + }//if not allInside + + if ( allInside ) + { + // Triangle inside. + int newCellId = lines[0]->InsertNextCell(2,iid); + outCD[0]->CopyData(inCD,cellId,newCellId); + continue; + } + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkCellArray *cellarrayout = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(2,iid); + unsigned int idcellnew; + + // Test triangle intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + // The index of the dimension of the cut plane (x == 0, y == 1, z == 2). + cutInd = planes/2; + + // The plane is always parallel to unitary cube. + value = this->BoundBoxClip[cutInd][planes%2]; + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + vtkIdType p_id; + cellarray->GetNextCell(npts, v_id); + + newPoints->GetPoint(v_id[0], v_line[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1], v_line[1]); + + // Check to see if line is inside plane. + if ( ( (planes%2 == 0) + && (v_line[0][cutInd] >= value) + && (v_line[1][cutInd] >= value) ) + || ( (planes%2 == 1) + && (v_line[0][cutInd] <= value) + && (v_line[1][cutInd] <= value) ) ) + { + newCellId = newcellArray->InsertNextCell(2, v_id); + continue; + } + + // Check to see if line is outside plane. + if ( ( (planes%2 == 0) + && (v_line[0][cutInd] <= value) + && (v_line[1][cutInd] <= value) ) + || ( (planes%2 == 1) + && (v_line[0][cutInd] >= value) + && (v_line[1][cutInd] >= value) ) ) + { + newCellId = lines[1]->InsertNextCell(2, v_id); + outCD[1]->CopyData(inCD, cellId, newCellId); + continue; + } + + // If we are here, the plane intersects the line segment. + t = (value - v_line[0][cutInd])/(v_line[1][cutInd] - v_line[0][cutInd]); + for (j = 0; j < 3; j++) + { + x[j] = (v_line[1][j] - v_line[0][j])*t + v_line[0][j]; + } + + // Incorporate point into output and interpolate edge data as + // necessary. + if (locator->InsertUniquePoint(x, p_id)) + { + outPD->InterpolateEdge(inPD, p_id, cellIds->GetId(0), + cellIds->GetId(1), t); + } + + // Add the clipped line to the output. + if ( ((planes%2 == 0) && (v_line[0][cutInd] >= value)) + || ((planes%2 == 1) && (v_line[0][cutInd] <= value)) ) + { + // First point of line is inside. + tab_id[0] = v_id[0]; + tab_id[1] = p_id; + newcellArray->InsertNextCell(2, tab_id); + + // Second point of line is outside. + tab_id[0] = p_id; + tab_id[1] = v_id[1]; + cellarrayout->InsertNextCell(2, tab_id); + } + else + { + // Second point of line is inside. + tab_id[0] = p_id; + tab_id[1] = v_id[1]; + newcellArray->InsertNextCell(2, tab_id); + + // First point of line is outside. + tab_id[0] = v_id[0]; + tab_id[1] = p_id; + cellarrayout->InsertNextCell(2, tab_id); + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } // for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); // Inside + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts, v_id); + newCellId = lines[0]->InsertNextCell(npts, v_id); + outCD[0]->CopyData(inCD, cellId, newCellId); + } + cellarray->Delete(); + + totalnewcells = cellarrayout->GetNumberOfCells(); // Outside + for (idcellnew = 0; idcellnew < totalnewcells; idcellnew++) + { + cellarrayout->GetNextCell(npts, v_id); + newCellId = lines[1]->InsertNextCell(npts, v_id); + outCD[1]->CopyData(inCD, cellId, newCellId); + } + cellarrayout->Delete(); + } + arrayline->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipHexahedron1D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *lines, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayline = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[2]; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType tab_id[2]; + vtkIdType ptsline = 2; + + int i,j; + unsigned int allInside; + unsigned int planes; + + double values[2]; + double t; + double v[3],x[3]; + double v_line[2][3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 1d cells to single line. + this->CellGrid(cellType, npts, cellptId, arrayline); + + unsigned int totalnewline = arrayline->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewline; idlinenew++) + { + arrayline->GetNextCell(ptsline, v_id); + + for (allInside=1, i=0; i<2; i++) + { + cellPts->GetPoint(v_id[i],v); + + for (int k = 0; k < 6; k++) + { + values[0] = ( this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2])); + if (values[0] > 0) + { + //outside + allInside = 0; + } + } + } + + // Test Outside: + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<2; i++) + { + cellPts->GetPoint(v_id[i],v); + + // Use plane equation. + for (int k = 0; k < 6; k++) + { + values[0] + = ( this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]) ); + if (values[0] < 0) + { + test[k] = 0; + } + }//for all planes of the hexahedron. + }//for all points of the line. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + continue; // Line is outside. + } + }//if not allInside + + for (i=0; i<2; i++) + { + // Currently all points are injected because of the possibility + // of intersection point merging. + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD,ptId, iid[i]); + } + }//for all points of the triangle. + + if ( allInside ) + { + // Triangle inside. + int newCellId = lines->InsertNextCell(2,iid); + outCD->CopyData(inCD,cellId,newCellId); + continue; + } + + vtkCellArray *cellarray = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(2,iid); + unsigned int idcellnew; + + // Test triangle intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + vtkIdType p_id; + cellarray->GetNextCell(npts, v_id); + + newPoints->GetPoint(v_id[0], v_line[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1], v_line[1]); + + const double *planeNormal = this->PlaneNormal[planes]; + const double *planePoint = this->PlanePoint[planes]; + values[0] = ( planeNormal[0]*(v_line[0][0] - planePoint[0]) + + planeNormal[1]*(v_line[0][1] - planePoint[1]) + + planeNormal[2]*(v_line[0][2] - planePoint[2])); + values[1] = ( planeNormal[0]*(v_line[1][0] - planePoint[0]) + + planeNormal[1]*(v_line[1][1] - planePoint[1]) + + planeNormal[2]*(v_line[1][2] - planePoint[2])); + + // Check to see if line is inside plane. + if ((values[0] <= 0) && (values[1] <= 0)) + { + newCellId = newcellArray->InsertNextCell(2, v_id); + continue; + } + + // Check to see if line is outside plane. + if ((values[0] >= 0) && (values[1] >= 0)) + { + continue; + } + + // If we are here, the plane intersects the line segment. + t = values[0]/(values[0] - values[1]); + for (j = 0; j < 3; j++) + { + x[j] = (v_line[1][j] - v_line[0][j])*t + v_line[0][j]; + } + + // Incorporate point into output and interpolate edge data as + // necessary. + if (locator->InsertUniquePoint(x, p_id)) + { + outPD->InterpolateEdge(inPD, p_id, cellIds->GetId(0), + cellIds->GetId(1), t); + } + + // Add the clipped line to the output. + if (values[0] <= 0) + { + // First point of line is inside. + tab_id[0] = v_id[0]; + tab_id[1] = p_id; + newcellArray->InsertNextCell(2, tab_id); + } + else + { + // Second point of line is inside. + tab_id[0] = p_id; + tab_id[1] = v_id[1]; + newcellArray->InsertNextCell(2, tab_id); + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } // for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts,v_id); + newCellId = lines->InsertNextCell(npts,v_id); + outCD->CopyData(inCD,cellId,newCellId); + } + cellarray->Delete(); + } + arrayline->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipHexahedronInOut1D(vtkPoints *newPoints, + vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **lines, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayline = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid[2]; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType tab_id[2]; + vtkIdType ptsline = 2; + + int i,j; + unsigned int allInside; + unsigned int planes; + + double values[2]; + double t; + double v[3],x[3]; + double v_line[2][3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 1d cells to single line. + this->CellGrid(cellType, npts, cellptId, arrayline); + + unsigned int totalnewline = arrayline->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewline; idlinenew++) + { + arrayline->GetNextCell(ptsline, v_id); + + for (allInside=1, i=0; i<2; i++) + { + ptId = cellIds->GetId(v_id[i]); + cellPts->GetPoint(v_id[i],v); + + for (int k = 0; k < 6; k++) + { + values[0] = ( this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2])); + if (values[0] > 0) + { + //outside + allInside = 0; + } + } + + if ( locator->InsertUniquePoint(v, iid[i]) ) + { + outPD->CopyData(inPD, ptId, iid[i]); + } + } + + // Test Outside: + if (!allInside) + { + unsigned int test[6] = {1,1,1,1,1,1}; + for (i=0; i<2; i++) + { + cellPts->GetPoint(v_id[i],v); + + // Use plane equation. + for (int k = 0; k < 6; k++) + { + values[0] + = ( this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]) ); + if (values[0] < 0) + { + test[k] = 0; + } + }//for all planes of the hexahedron. + }//for all points of the line. + + if ((test[0] == 1)|| (test[1] == 1) || + (test[2] == 1)|| (test[3] == 1) || + (test[4] == 1)|| (test[5] == 1)) + { + int newCellId = lines[1]->InsertNextCell(2, iid); + outCD[1]->CopyData(inCD, cellId, newCellId); + continue; // Line is outside. + } + }//if not allInside + + if ( allInside ) + { + // Triangle inside. + int newCellId = lines[0]->InsertNextCell(2,iid); + outCD[0]->CopyData(inCD,cellId,newCellId); + continue; + } + + vtkCellArray *cellarray = vtkCellArray::New(); + vtkCellArray *cellarrayout = vtkCellArray::New(); + int newCellId = cellarray->InsertNextCell(2,iid); + unsigned int idcellnew; + + // Test triangle intersection with each plane of box + for (planes = 0; planes < 6; planes++) + { + unsigned int totalnewcells = cellarray->GetNumberOfCells(); + vtkCellArray *newcellArray = vtkCellArray::New(); + + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + vtkIdType p_id; + cellarray->GetNextCell(npts, v_id); + + newPoints->GetPoint(v_id[0], v_line[0]); //coord (x,y,z) + newPoints->GetPoint(v_id[1], v_line[1]); + + const double *planeNormal = this->PlaneNormal[planes]; + const double *planePoint = this->PlanePoint[planes]; + values[0] = ( planeNormal[0]*(v_line[0][0] - planePoint[0]) + + planeNormal[1]*(v_line[0][1] - planePoint[1]) + + planeNormal[2]*(v_line[0][2] - planePoint[2])); + values[1] = ( planeNormal[0]*(v_line[1][0] - planePoint[0]) + + planeNormal[1]*(v_line[1][1] - planePoint[1]) + + planeNormal[2]*(v_line[1][2] - planePoint[2])); + + // Check to see if line is inside plane. + if ((values[0] <= 0) && (values[1] <= 0)) + { + newCellId = newcellArray->InsertNextCell(2, v_id); + continue; + } + + // Check to see if line is outside plane. + if ((values[0] >= 0) && (values[1] >= 0)) + { + newCellId = lines[1]->InsertNextCell(2, v_id); + outCD[1]->CopyData(inCD, cellId, newCellId); + continue; + } + + // If we are here, the plane intersects the line segment. + t = values[0]/(values[0] - values[1]); + for (j = 0; j < 3; j++) + { + x[j] = (v_line[1][j] - v_line[0][j])*t + v_line[0][j]; + } + + // Incorporate point into output and interpolate edge data as + // necessary. + if (locator->InsertUniquePoint(x, p_id)) + { + outPD->InterpolateEdge(inPD, p_id, cellIds->GetId(0), + cellIds->GetId(1), t); + } + + // Add the clipped line to the output. + if (values[0] <= 0) + { + // First point of line is inside. + tab_id[0] = v_id[0]; + tab_id[1] = p_id; + newcellArray->InsertNextCell(2, tab_id); + + // Second point of line is outside. + tab_id[0] = p_id; + tab_id[1] = v_id[1]; + cellarrayout->InsertNextCell(2, tab_id); + } + else + { + // Second point of line is inside. + tab_id[0] = p_id; + tab_id[1] = v_id[1]; + newcellArray->InsertNextCell(2, tab_id); + + // First point of line is outside. + tab_id[0] = v_id[0]; + tab_id[1] = p_id; + cellarrayout->InsertNextCell(2, tab_id); + } + } // for all new cells + cellarray->Delete(); + cellarray = newcellArray; + } // for all planes + + unsigned int totalnewcells = cellarray->GetNumberOfCells(); // Inside + for (idcellnew = 0 ; idcellnew < totalnewcells; idcellnew++) + { + cellarray->GetNextCell(npts, v_id); + newCellId = lines[0]->InsertNextCell(npts, v_id); + outCD[0]->CopyData(inCD, cellId, newCellId); + } + cellarray->Delete(); + + totalnewcells = cellarrayout->GetNumberOfCells(); // Outside + for (idcellnew = 0; idcellnew < totalnewcells; idcellnew++) + { + cellarrayout->GetNextCell(npts, v_id); + newCellId = lines[1]->InsertNextCell(npts, v_id); + outCD[1]->CopyData(inCD, cellId, newCellId); + } + cellarrayout->Delete(); + } + arrayline->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipBox0D(vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayvert = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType ptsvert = 1; + + int i; + + double v[3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 0d cells to single vert. + this->CellGrid(cellType, npts, cellptId, arrayvert); + + unsigned int totalnewvert = arrayvert->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewvert; idlinenew++) + { + arrayvert->GetNextCell(ptsvert, v_id); + + // Clipping verts is easy. Either it is inside the box or it isn't. + cellPts->GetPoint(v_id[0], v); + if ( (v[0] >= this->BoundBoxClip[0][0]) + && (v[0] <= this->BoundBoxClip[0][1]) + && (v[1] >= this->BoundBoxClip[1][0]) + && (v[1] <= this->BoundBoxClip[1][1]) + && (v[2] >= this->BoundBoxClip[2][0]) + && (v[2] <= this->BoundBoxClip[2][1]) ) + { + // Vert is inside. + ptId = cellIds->GetId(v_id[0]); + if (locator->InsertUniquePoint(v, iid)) + { + outPD->CopyData(inPD, ptId, iid); + } + + int newCellId = verts->InsertNextCell(1, &iid); + outCD->CopyData(inCD, cellId, newCellId); + } + } + arrayvert->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipBoxInOut0D(vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **verts, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayvert = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType ptsvert = 1; + + int i; + + double v[3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 0d cells to single vert. + this->CellGrid(cellType, npts, cellptId, arrayvert); + + unsigned int totalnewvert = arrayvert->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewvert; idlinenew++) + { + arrayvert->GetNextCell(ptsvert, v_id); + + // One way or another, we are adding the point. + ptId = cellIds->GetId(v_id[0]); + cellPts->GetPoint(v_id[0], v); + + if (locator->InsertUniquePoint(v, iid)) + { + outPD->CopyData(inPD, ptId, iid); + } + + // Clipping verts is easy. Either it is inside the box or it isn't. + if ( (v[0] >= this->BoundBoxClip[0][0]) + && (v[0] <= this->BoundBoxClip[0][1]) + && (v[1] >= this->BoundBoxClip[1][0]) + && (v[1] <= this->BoundBoxClip[1][1]) + && (v[2] >= this->BoundBoxClip[2][0]) + && (v[2] <= this->BoundBoxClip[2][1]) ) + { + // Vert is inside. + int newCellId = verts[0]->InsertNextCell(1, &iid); + outCD[0]->CopyData(inCD, cellId, newCellId); + } + else + { + // Vert is outside. + int newCellId = verts[1]->InsertNextCell(1, &iid); + outCD[1]->CopyData(inCD, cellId, newCellId); + } + } + arrayvert->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipHexahedron0D(vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray *verts, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData *outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayvert = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType ptsvert = 1; + + int i; + + double v[3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 0d cells to single vert. + this->CellGrid(cellType, npts, cellptId, arrayvert); + + unsigned int totalnewvert = arrayvert->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewvert; idlinenew++) + { + arrayvert->GetNextCell(ptsvert, v_id); + + // Clipping verts is easy. Either it is inside the hexahedron or it isn't. + cellPts->GetPoint(v_id[0], v); + int inside = 1; + + for (int k = 0; k < 6; k++) + { + double value + = ( this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]) ); + if (value > 0) + { + inside = 0; + } + } + + if (inside) + { + // Vert is inside. + ptId = cellIds->GetId(v_id[0]); + if (locator->InsertUniquePoint(v, iid)) + { + outPD->CopyData(inPD, ptId, iid); + } + + int newCellId = verts->InsertNextCell(1, &iid); + outCD->CopyData(inCD, cellId, newCellId); + } + } + arrayvert->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkBoxClipDataSet::ClipHexahedronInOut0D(vtkGenericCell *cell, + vtkPointLocator *locator, + vtkCellArray **verts, + vtkPointData *inPD, + vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, + vtkCellData **outCD) +{ + vtkIdType cellType = cell->GetCellType(); + vtkIdList *cellIds = cell->GetPointIds(); + vtkCellArray *arrayvert = vtkCellArray::New(); + vtkPoints *cellPts = cell->GetPoints(); + vtkIdType npts = cellPts->GetNumberOfPoints(); + vtkIdType cellptId[VTK_CELL_SIZE]; + vtkIdType iid; + vtkIdType *v_id = NULL; + vtkIdType ptId; + vtkIdType ptsvert = 1; + + int i; + + double v[3]; + + for (i = 0; i < npts; i++) + { + cellptId[i] = cellIds->GetId(i); + } + + // Convert all 0d cells to single vert. + this->CellGrid(cellType, npts, cellptId, arrayvert); + + unsigned int totalnewvert = arrayvert->GetNumberOfCells(); + for (unsigned int idlinenew = 0; idlinenew < totalnewvert; idlinenew++) + { + arrayvert->GetNextCell(ptsvert, v_id); + + // One way or another, we are adding the point. + ptId = cellIds->GetId(v_id[0]); + cellPts->GetPoint(v_id[0], v); + + if (locator->InsertUniquePoint(v, iid)) + { + outPD->CopyData(inPD, ptId, iid); + } + + int inside = 1; + for (int k = 0; k < 6; k++) + { + double value + = ( this->PlaneNormal[k][0]*(v[0] - this->PlanePoint[k][0]) + + this->PlaneNormal[k][1]*(v[1] - this->PlanePoint[k][1]) + + this->PlaneNormal[k][2]*(v[2] - this->PlanePoint[k][2]) ); + if (value > 0) + { + inside = 0; + } + } + + // Clipping verts is easy. Either it is inside the box or it isn't. + if (inside) + { + // Vert is inside. + int newCellId = verts[0]->InsertNextCell(1, &iid); + outCD[0]->CopyData(inCD, cellId, newCellId); + } + else + { + // Vert is outside. + int newCellId = verts[1]->InsertNextCell(1, &iid); + outCD[1]->CopyData(inCD, cellId, newCellId); + } + } + arrayvert->Delete(); +} diff --git a/Graphics/vtkBoxClipDataSet.h b/Graphics/vtkBoxClipDataSet.h new file mode 100644 index 0000000..e9579a9 --- /dev/null +++ b/Graphics/vtkBoxClipDataSet.h @@ -0,0 +1,239 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBoxClipDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkBoxClipDataSet - clip an unstructured grid +// +// .SECTION Description +// Clipping means that is actually 'cuts' through the cells of the dataset, +// returning tetrahedral cells inside of the box. +// The output of this filter is an unstructured grid. +// +// This filter can be configured to compute a second output. The +// second output is the part of the cell that is clipped away. Set the +// GenerateClippedData boolean on if you wish to access this output data. +// +// The vtkBoxClipDataSet will triangulate all types of 3D cells (i.e, create tetrahedra). +// This is necessary to preserve compatibility across face neighbors. +// +// To use this filter,you can decide if you will be clipping with a box or a hexahedral box. +// 1) Set orientation +// if(SetOrientation(0)): box (parallel with coordinate axis) +// SetBoxClip(xmin,xmax,ymin,ymax,zmin,zmax) +// if(SetOrientation(1)): hexahedral box (Default) +// SetBoxClip(n[0],o[0],n[1],o[1],n[2],o[2],n[3],o[3],n[4],o[4],n[5],o[5]) +// PlaneNormal[] normal of each plane +// PlanePoint[] point on the plane +// 2) Apply the GenerateClipScalarsOn() +// 3) Execute clipping Update(); + +#ifndef __vtkBoxClipDataSet_h +#define __vtkBoxClipDataSet_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkGenericCell; +class vtkCell3D; +class vtkDataArray; +class vtkCellArray; +class vtkPointData; +class vtkCellData; +class vtkPoints; +class vtkIdList; +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkBoxClipDataSet : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkBoxClipDataSet,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Constructor of the clipping box. + static vtkBoxClipDataSet *New(); + + // Description + // Specify the Box with which to perform the clipping. + // If the box is not parallel to axis, you need to especify + // normal vector of each plane and a point on the plane. + void SetBoxClip(double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax); + void SetBoxClip(const double *n0, const double *o0, + const double *n1, const double *o1, + const double *n2, const double *o2, + const double *n3, const double *o3, + const double *n4, const double *o4, + const double *n5, const double *o5); + + + // Description: + // If this flag is enabled, then the output scalar values will be + // interpolated, and not the input scalar data. + vtkSetMacro(GenerateClipScalars,int); + vtkGetMacro(GenerateClipScalars,int); + vtkBooleanMacro(GenerateClipScalars,int); + + // Description: + // Control whether a second output is generated. The second output + // contains the polygonal data that's been clipped away. + vtkSetMacro(GenerateClippedOutput,int); + vtkGetMacro(GenerateClippedOutput,int); + vtkBooleanMacro(GenerateClippedOutput,int); + + // Description: + // Set the tolerance for merging clip intersection points that are near + // the vertices of cells. This tolerance is used to prevent the generation + // of degenerate primitives. Note that only 3D cells actually use this + // instance variable. + //vtkSetClampMacro(MergeTolerance,double,0.0001,0.25); + //vtkGetMacro(MergeTolerance,double); + + // Description: + // Return the Clipped output. + vtkUnstructuredGrid *GetClippedOutput(); + virtual int GetNumberOfOutputs(); + + // Description: + // Specify a spatial locator for merging points. By default, an + // instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. The + // locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // Return the mtime also considering the locator. + unsigned long GetMTime(); + + vtkGetMacro(Orientation,unsigned int); + vtkSetMacro(Orientation,unsigned int); + + void MinEdgeF(const unsigned int *id_v, const vtkIdType *cellIds, + unsigned int *edgF ); + void PyramidToTetra(const vtkIdType *pyramId, const vtkIdType *cellIds, + vtkCellArray *newCellArray); + void WedgeToTetra(const vtkIdType *wedgeId, const vtkIdType *cellIds, + vtkCellArray *newCellArray); + void CellGrid(vtkIdType typeobj, vtkIdType npts, const vtkIdType *cellIds, + vtkCellArray *newCellArray); + void CreateTetra(vtkIdType npts, const vtkIdType *cellIds, + vtkCellArray *newCellArray); + void ClipBox(vtkPoints *newPoints,vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *tets,vtkPointData *inPD, + vtkPointData *outPD,vtkCellData *inCD,vtkIdType cellId, + vtkCellData *outCD); + void ClipHexahedron(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData *outCD); + void ClipBoxInOut(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData **outCD); + void ClipHexahedronInOut(vtkPoints *newPoints,vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, + vtkCellData **outCD); + + void ClipBox2D(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *tets, + vtkPointData *inPD, vtkPointData *outPD, vtkCellData *inCD, + vtkIdType cellId, vtkCellData *outCD); + void ClipBoxInOut2D(vtkPoints *newPoints,vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData **outCD); + void ClipHexahedron2D(vtkPoints *newPoints,vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, + vtkCellData *outCD); + void ClipHexahedronInOut2D(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **tets, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD,vtkIdType cellId, + vtkCellData **outCD); + + void ClipBox1D(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *lines, + vtkPointData *inPD, vtkPointData *outPD, vtkCellData *inCD, + vtkIdType cellId, vtkCellData *outCD); + void ClipBoxInOut1D(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **lines, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData **outCD); + void ClipHexahedron1D(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *lines, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, + vtkCellData *outCD); + void ClipHexahedronInOut1D(vtkPoints *newPoints, vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **lines, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, + vtkCellData **outCD); + + void ClipBox0D(vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *verts, + vtkPointData *inPD, vtkPointData *outPD, vtkCellData *inCD, + vtkIdType cellId, vtkCellData *outCD); + void ClipBoxInOut0D(vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **verts, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, vtkCellData **outCD); + void ClipHexahedron0D(vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray *verts, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, vtkCellData *outCD); + void ClipHexahedronInOut0D(vtkGenericCell *cell, + vtkPointLocator *locator, vtkCellArray **verts, + vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, + vtkIdType cellId, vtkCellData **outCD); +protected: + vtkBoxClipDataSet(); + ~vtkBoxClipDataSet(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkPointLocator *Locator; + int GenerateClipScalars; + + int GenerateClippedOutput; + + //double MergeTolerance; + + double BoundBoxClip[3][2]; + unsigned int Orientation; + double PlaneNormal[6][3]; //normal of each plane + double PlanePoint[6][3]; //point on the plane + +private: + vtkBoxClipDataSet(const vtkBoxClipDataSet&); // Not implemented. + void operator=(const vtkBoxClipDataSet&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkBrownianPoints.cxx b/Graphics/vtkBrownianPoints.cxx new file mode 100644 index 0000000..ce4a0f6 --- /dev/null +++ b/Graphics/vtkBrownianPoints.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBrownianPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBrownianPoints.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkBrownianPoints, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkBrownianPoints); + +vtkBrownianPoints::vtkBrownianPoints() +{ + this->MinimumSpeed = 0.0; + this->MaximumSpeed = 1.0; +} + +int vtkBrownianPoints::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType i, numPts; + int j; + vtkFloatArray *newVectors; + double v[3], norm, speed; + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + vtkDebugMacro(<< "Executing Brownian filter"); + + if ( ((numPts=input->GetNumberOfPoints()) < 1) ) + { + vtkDebugMacro(<< "No input!\n"); + return 1; + } + + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->SetNumberOfTuples(numPts); + newVectors->SetName("BrownianVectors"); + + // Check consistency of minumum and maximum speed + // + if ( this->MinimumSpeed > this->MaximumSpeed ) + { + vtkErrorMacro(<< " Minimum speed > maximum speed; reset to (0,1)."); + this->MinimumSpeed = 0.0; + this->MaximumSpeed = 1.0; + } + + int tenth = numPts/10 + 1; + for (i=0; iUpdateProgress ((double)i/numPts); + if (this->GetAbortExecute()) + { + break; + } + } + + speed = vtkMath::Random(this->MinimumSpeed,this->MaximumSpeed); + if ( speed != 0.0 ) + { + for (j=0; j<3; j++) + { + v[j] = vtkMath::Random(-1.0,1.0); + } + norm = vtkMath::Norm(v); + for (j=0; j<3; j++) + { + v[j] *= (speed / norm); + } + } + else + { + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; + } + + newVectors->SetTuple(i,v); + } + + // Update ourselves + // + output->GetPointData()->CopyVectorsOff(); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + output->GetFieldData()->PassData(input->GetFieldData()); + + output->GetPointData()->SetVectors(newVectors); + newVectors->Delete(); + + return 1; +} + +void vtkBrownianPoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Minimum Speed: " << this->MinimumSpeed << "\n"; + os << indent << "Maximum Speed: " << this->MaximumSpeed << "\n"; +} diff --git a/Graphics/vtkBrownianPoints.h b/Graphics/vtkBrownianPoints.h new file mode 100644 index 0000000..e77ec42 --- /dev/null +++ b/Graphics/vtkBrownianPoints.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBrownianPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBrownianPoints - assign random vector to points +// .SECTION Description +// vtkBrownianPoints is a filter object that assigns a random vector (i.e., +// magnitude and direction) to each point. The minimum and maximum speed +// values can be controlled by the user. + +#ifndef __vtkBrownianPoints_h +#define __vtkBrownianPoints_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkBrownianPoints : public vtkDataSetAlgorithm +{ +public: + // Description: + // Create instance with minimum speed 0.0, maximum speed 1.0. + static vtkBrownianPoints *New(); + + vtkTypeRevisionMacro(vtkBrownianPoints,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the minimum speed value. + vtkSetClampMacro(MinimumSpeed,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(MinimumSpeed,double); + + // Description: + // Set the maximum speed value. + vtkSetClampMacro(MaximumSpeed,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(MaximumSpeed,double); + +protected: + vtkBrownianPoints(); + ~vtkBrownianPoints() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double MinimumSpeed; + double MaximumSpeed; +private: + vtkBrownianPoints(const vtkBrownianPoints&); // Not implemented. + void operator=(const vtkBrownianPoints&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkButterflySubdivisionFilter.cxx b/Graphics/vtkButterflySubdivisionFilter.cxx new file mode 100644 index 0000000..e6ff639 --- /dev/null +++ b/Graphics/vtkButterflySubdivisionFilter.cxx @@ -0,0 +1,491 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkButterflySubdivisionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkButterflySubdivisionFilter.h" + +#include "vtkCellArray.h" +#include "vtkEdgeTable.h" +#include "vtkIdList.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkButterflySubdivisionFilter, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkButterflySubdivisionFilter); + +static double butterflyWeights[8] = + {.5, .5, .125, .125, -.0625, -.0625, -.0625, -.0625}; + +void vtkButterflySubdivisionFilter::GenerateSubdivisionPoints( + vtkPolyData *inputDS, vtkIntArray *edgeData, vtkPoints *outputPts, + vtkPointData *outputPD) +{ + double *weights, *weights1, *weights2; + vtkIdType *pts = 0; + vtkIdType cellId, newId, i, j; + int edgeId; + vtkIdType npts = 0; + vtkIdType p1, p2; + int valence1, valence2; + vtkCellArray *inputPolys=inputDS->GetPolys(); + vtkEdgeTable *edgeTable; + vtkIdList *cellIds = vtkIdList::New(); + vtkIdList *p1CellIds = vtkIdList::New(); + vtkIdList *p2CellIds = vtkIdList::New(); + vtkIdList *stencil = vtkIdList::New(); + vtkIdList *stencil1 = vtkIdList::New(); + vtkIdList *stencil2 = vtkIdList::New(); + vtkPoints *inputPts=inputDS->GetPoints(); + vtkPointData *inputPD=inputDS->GetPointData(); + + weights = new double[256]; + weights1 = new double[256]; + weights2 = new double[256]; + + // Create an edge table to keep track of which edges we've processed + edgeTable = vtkEdgeTable::New(); + edgeTable->InitEdgeInsertion(inputDS->GetNumberOfPoints()); + + // Generate new points for subdivisions surface + for (cellId=0, inputPolys->InitTraversal(); + inputPolys->GetNextCell(npts, pts); cellId++) + { + if ( inputDS->GetCellType(cellId) != VTK_TRIANGLE ) + { + continue; + } + + p1 = pts[2]; + p2 = pts[0]; + + for (edgeId=0; edgeId < 3; edgeId++) + { + // Do we need to create a point on this edge? + if (edgeTable->IsEdge (p1, p2) == -1) + { + outputPD->CopyData (inputPD, p1, p1); + outputPD->CopyData (inputPD, p2, p2); + edgeTable->InsertEdge (p1, p2); + + inputDS->GetCellEdgeNeighbors (-1, p1, p2, cellIds); + // If this is a boundary edge. we need to use a special subdivision rule + if (cellIds->GetNumberOfIds() == 1) + { + // Compute new POsition and PointData using the same subdivision scheme + this->GenerateBoundaryStencil (p1, p2, + inputDS, stencil, weights); + } // boundary edge + else + { + // find the valence of the two points + inputDS->GetPointCells (p1, p1CellIds); + valence1 = p1CellIds->GetNumberOfIds(); + inputDS->GetPointCells (p2, p2CellIds); + valence2 = p2CellIds->GetNumberOfIds(); + + if (valence1 == 6 && valence2 == 6) + { + this->GenerateButterflyStencil (p1, p2, + inputDS, stencil, weights); + } + else if (valence1 == 6 && valence2 != 6) + { + this->GenerateLoopStencil (p2, p1, + inputDS, stencil, weights); + } + else if (valence1 != 6 && valence2 == 6) + { + this->GenerateLoopStencil (p1, p2, + inputDS, stencil, weights); + } + else + { + // Edge connects two extraordinary vertices + this->GenerateLoopStencil (p2, p1, + inputDS, stencil1, weights1); + this->GenerateLoopStencil (p1, p2, + inputDS, stencil2, weights2); + // combine the two stencils and halve the weights + vtkIdType total = stencil1->GetNumberOfIds() + + stencil2->GetNumberOfIds(); + stencil->SetNumberOfIds (total); + + j = 0; + for (i = 0; i < stencil1->GetNumberOfIds(); i++) + { + stencil->InsertId(j, stencil1->GetId(i)); + weights[j++] = weights1[i] * .5; + } + for (i = 0; i < stencil2->GetNumberOfIds(); i++) + { + stencil->InsertId(j, stencil2->GetId(i)); + weights[j++] = weights2[i] * .5; + } + } + } + newId = this->InterpolatePosition (inputPts, outputPts, stencil, weights); + outputPD->InterpolatePoint (inputPD, newId, stencil, weights); + } + else // we have already created a point on this edge. find it + { + newId = this->FindEdge (inputDS, cellId, p1, p2, edgeData, cellIds); + } + edgeData->InsertComponent(cellId,edgeId,newId); + p1 = p2; + if (edgeId < 2) + { + p2 = pts[edgeId + 1]; + } + } // each interior edge + } // each cell + + // cleanup + delete [] weights; delete [] weights1; delete [] weights2; + edgeTable->Delete(); + stencil->Delete (); stencil1->Delete (); stencil2->Delete (); + cellIds->Delete(); + p1CellIds->Delete(); + p2CellIds->Delete(); +} + +void vtkButterflySubdivisionFilter::GenerateLoopStencil( + vtkIdType p1, vtkIdType p2, vtkPolyData *polys, vtkIdList *stencilIds, + double *weights) +{ + vtkIdList *cellIds = vtkIdList::New(); + vtkCell *cell; + int j; + vtkIdType startCell, nextCell, tp2, p; + int shift[255]; + int processed = 0; + int boundary = 0; + + // Find another cell with this edge (we assume there is just one) + polys->GetCellEdgeNeighbors (-1, p1, p2, cellIds); + startCell = cellIds->GetId(0); + + stencilIds->Reset(); + stencilIds->InsertNextId (p2); + shift[0] = 0; + + // Walk around the loop and get cells + nextCell = cellIds->GetId(1); + tp2 = p2; + while (nextCell != startCell) + { + cell = polys->GetCell(nextCell); + p = -1; + for (int i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != tp2) + { + break; + } + } + tp2 = p; + stencilIds->InsertNextId (tp2); + processed++; + shift[processed] = processed; + polys->GetCellEdgeNeighbors (nextCell, p1, tp2, cellIds); + if (cellIds->GetNumberOfIds() != 1) + { + boundary = 1; + break; + } + nextCell = cellIds->GetId(0); + } + + // If p1 or p2 is on the boundary, use the butterfly stencil with reflected vertices. + if (boundary) + { + this->GenerateButterflyStencil (p1, p2, + polys, stencilIds, weights); + cellIds->Delete(); + return; + } + + // Generate weights +#define VTK_PI 3.14159265358979 + int K = stencilIds->GetNumberOfIds(); + if (K >= 5) + { + for (j = 0; j < K; j++) + { + weights[j] = (.25 + cos (2.0 * VTK_PI * (double) shift[j] / (double) K) + + .5 * cos (4.0 * VTK_PI * (double) shift[j] / (double) K)) / (double) K; + } + } + else if (K == 4) + { + static double weights4[4] = {3.0/8.0, 0.0, -1.0/8.0, 0.0}; + weights[0] = weights4[abs(shift[0])]; + weights[1] = weights4[abs(shift[1])]; + weights[2] = weights4[abs(shift[2])]; + weights[3] = weights4[abs(shift[3])]; + } + else if (K == 3) + { + static double weights3[3] = {5.0/12.0, -1.0/12.0, -1.0/12.0}; + weights[0] = weights3[abs(shift[0])]; + weights[1] = weights3[abs(shift[1])]; + weights[2] = weights3[abs(shift[2])]; + } + else + { // K == 2. p1 must be on a boundary edge, + cell = polys->GetCell(startCell); + p = -1; + for (int i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p2) + { + break; + } + } + p2 = p; + stencilIds->InsertNextId (p2); + weights[0] = 5.0 / 12.0; + weights[1] = -1.0 / 12.0; + weights[2] = -1.0 / 12.0; + } + // add in the extraordinary vertex + weights[stencilIds->GetNumberOfIds()] = .75; + stencilIds->InsertNextId (p1); + + cellIds->Delete(); +} + +void vtkButterflySubdivisionFilter::GenerateBoundaryStencil( + vtkIdType p1, vtkIdType p2, vtkPolyData *polys, vtkIdList *stencilIds, + double *weights) +{ + vtkIdList *cellIds = vtkIdList::New(); + vtkIdType *cells; + unsigned short ncells; + vtkIdType *pts; + vtkIdType npts; + int i, j; + vtkIdType p0, p3; + + // find a boundary edge that uses p1 other than the one containing p2 + polys->GetPointCells (p1, ncells, cells); + p0 = -1; + for (i = 0; i < ncells && p0 == -1; i++) + { + polys->GetCellPoints (cells[i], npts, pts); + for (j = 0; j < npts; j++) + { + if (pts[j] == p1 || pts[j] == p2) + { + continue; + } + polys->GetCellEdgeNeighbors (-1, p1, pts[j], cellIds); + if (cellIds->GetNumberOfIds() == 1) + { + p0 = pts[j]; + break; + } + } + } + // find a boundary edge that uses p2 other than the one containing p1 + polys->GetPointCells (p2, ncells, cells); + p3 = -1; + for (i = 0; i < ncells && p3 == -1; i++) + { + polys->GetCellPoints (cells[i], npts, pts); + for (j = 0; j < npts; j++) + { + if (pts[j] == p1 || pts[j] == p2 || pts[j] == p0) + { + continue; + } + polys->GetCellEdgeNeighbors (-1, p2, pts[j], cellIds); + if (cellIds->GetNumberOfIds() == 1) + { + p3 = pts[j]; + break; + } + } + } + stencilIds->SetNumberOfIds (4); + stencilIds->SetId (0, p0); + stencilIds->SetId (1, p1); + stencilIds->SetId (2, p2); + stencilIds->SetId (3, p3); + weights[0] = -.0625; + weights[1] = .5625; + weights[2] = .5625; + weights[3] = -.0625; + + cellIds->Delete(); +} + +void vtkButterflySubdivisionFilter::GenerateButterflyStencil ( + vtkIdType p1, vtkIdType p2, vtkPolyData *polys, vtkIdList *stencilIds, + double *weights) +{ + vtkIdList *cellIds = vtkIdList::New(); + vtkCell *cell; + int i; + vtkIdType cell0, cell1; + vtkIdType p, p3, p4, p5, p6, p7, p8; + + polys->GetCellEdgeNeighbors (-1, p1, p2, cellIds); + cell0 = cellIds->GetId(0); + cell1 = cellIds->GetId(1); + + cell = polys->GetCell(cell0); + p3 = -1; + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p2) + { + p3 = p; + break; + } + } + cell = polys->GetCell(cell1); + p4 = -1; + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p2) + { + p4 = p; + break; + } + } + + polys->GetCellEdgeNeighbors (cell0, p1, p3, cellIds); + p5 = -1; + if (cellIds->GetNumberOfIds() > 0) + { + cell = polys->GetCell(cellIds->GetId(0)); + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p3) + { + p5 = p; + break; + } + } + } + + polys->GetCellEdgeNeighbors (cell0, p2, p3, cellIds); + p6 = -1; + if (cellIds->GetNumberOfIds() > 0) + { + cell = polys->GetCell(cellIds->GetId(0)); + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p2 && cell->GetPointId(i) != p3) + { + p6 = p; + break; + } + } + } + + polys->GetCellEdgeNeighbors (cell1, p1, p4, cellIds); + p7 = -1; + if (cellIds->GetNumberOfIds() > 0) + { + cell = polys->GetCell(cellIds->GetId(0)); + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p4) + { + p7 = p; + break; + } + } + } + + p8 = -1; + polys->GetCellEdgeNeighbors (cell1, p2, p4, cellIds); + if (cellIds->GetNumberOfIds() > 0) + { + cell = polys->GetCell(cellIds->GetId(0)); + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p2 && cell->GetPointId(i) != p4) + { + p8= p; + break; + } + } + } + + stencilIds->SetNumberOfIds (8); + stencilIds->SetId(0, p1); + stencilIds->SetId(1, p2); + stencilIds->SetId(2, p3); + stencilIds->SetId(3, p4); + if (p5 != -1) + { + stencilIds->SetId(4, p5); + } + else if (p4 != -1) + { + stencilIds->SetId(4, p4); + } + else + { + vtkWarningMacro (<< "bad p5, p4 " << p5 << ", " << p4); + } + + if (p6 != -1) + { + stencilIds->SetId(5, p6); + } + else if (p4 != -1) + { + stencilIds->SetId(5, p4); + } + else + { + vtkWarningMacro (<< "bad p5, p4 " << p5 << ", " << p4); + } + + if (p7 != -1) + { + stencilIds->SetId(6, p7); + } + else if (p3 != -1) + { + stencilIds->SetId(6, p3); + } + else + { + vtkWarningMacro (<< "bad p7, p3 " << p7 << ", " << p3); + } + + if (p8 != -1) + { + stencilIds->SetId(7, p8); + } + else if (p3 != -1) + { + stencilIds->SetId(7, p3); + } + else + { + vtkWarningMacro (<< "bad p7, p8 " << p7 << ", " << p3); + } + + + for (i = 0; i < stencilIds->GetNumberOfIds (); i++) + { + weights[i] = butterflyWeights[i]; + } + cellIds->Delete(); +} diff --git a/Graphics/vtkButterflySubdivisionFilter.h b/Graphics/vtkButterflySubdivisionFilter.h new file mode 100644 index 0000000..f29edc9 --- /dev/null +++ b/Graphics/vtkButterflySubdivisionFilter.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkButterflySubdivisionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkButterflySubdivisionFilter - generate a subdivision surface using the Butterfly Scheme +// .SECTION Description +// vtkButterflySubdivisionFilter is an interpolating subdivision scheme +// that creates four new triangles for each triangle in the mesh. The +// user can specify the NumberOfSubdivisions. This filter implements the +// 8-point butterfly scheme described in: Zorin, D., Schroder, P., and +// Sweldens, W., "Interpolating Subdivisions for Meshes with Arbitrary +// Topology," Computer Graphics Proceedings, Annual Conference Series, +// 1996, ACM SIGGRAPH, pp.189-192. This scheme improves previous +// butterfly subdivisions with special treatment of vertices with valence +// other than 6. +// +// Currently, the filter only operates on triangles. Users should use the +// vtkTriangleFilter to triangulate meshes that contain polygons or +// triangle strips. +// +// The filter interpolates point data using the same scheme. New +// triangles created at a subdivision step will have the cell data of +// their parent cell. + +// .SECTION Thanks +// This work was supported by PHS Research Grant No. 1 P41 RR13218-01 +// from the National Center for Research Resources. + +// .SECTION See Also +// vtkInterpolatingSubdivisionFilter vtkLinearSubdivisionFilter + +#ifndef __vtkButterflySubdivisionFilter_h +#define __vtkButterflySubdivisionFilter_h + +#include "vtkInterpolatingSubdivisionFilter.h" + +class vtkCellArray; +class vtkIdList; +class vtkIntArray; + +class VTK_GRAPHICS_EXPORT vtkButterflySubdivisionFilter : public vtkInterpolatingSubdivisionFilter +{ +public: + // Description: + // Construct object with NumberOfSubdivisions set to 1. + static vtkButterflySubdivisionFilter *New(); + vtkTypeRevisionMacro(vtkButterflySubdivisionFilter,vtkInterpolatingSubdivisionFilter); + +protected: + vtkButterflySubdivisionFilter () {}; + ~vtkButterflySubdivisionFilter () {}; + +private: + void GenerateSubdivisionPoints(vtkPolyData *inputDS, vtkIntArray *edgeData, + vtkPoints *outputPts, vtkPointData *outputPD); + void GenerateButterflyStencil(vtkIdType p1, vtkIdType p2, vtkPolyData *polys, + vtkIdList *stencilIds, double *weights); + void GenerateLoopStencil(vtkIdType p1, vtkIdType p2, vtkPolyData *polys, + vtkIdList *stencilIds, double *weights); + void GenerateBoundaryStencil(vtkIdType p1, vtkIdType p2, vtkPolyData *polys, + vtkIdList *stencilIds, double *weights); + +private: + vtkButterflySubdivisionFilter(const vtkButterflySubdivisionFilter&); // Not implemented. + void operator=(const vtkButterflySubdivisionFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkButtonSource.cxx b/Graphics/vtkButtonSource.cxx new file mode 100644 index 0000000..503ccc5 --- /dev/null +++ b/Graphics/vtkButtonSource.cxx @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkButtonSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkButtonSource.h" + +vtkCxxRevisionMacro(vtkButtonSource, "$Revision: 1.12 $"); + +// Construct +vtkButtonSource::vtkButtonSource() +{ + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + this->ShoulderTextureCoordinate[0] = 0.0; + this->ShoulderTextureCoordinate[1] = 0.0; + this->TextureStyle = VTK_TEXTURE_STYLE_PROPORTIONAL; + this->TextureDimensions[0] = 100; + this->TextureDimensions[1] = 100; + this->TwoSided = 0; + + this->SetNumberOfInputPorts(0); +} + +void vtkButtonSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << ")\n"; + + os << indent << "Shoulder Texture Coordinate: (" + << this->ShoulderTextureCoordinate[0] << ", " + << this->ShoulderTextureCoordinate[1] << ")\n"; + + os << indent << "Texture Style: "; + if ( this->TextureStyle == VTK_TEXTURE_STYLE_FIT_IMAGE ) + { + os << "Fit\n"; + } + else + { + os << "Proportional\n"; + } + + os << indent << "Texture Dimensions: (" + << this->TextureDimensions[0] << ", " + << this->TextureDimensions[1] << ")\n"; + + os << indent << "Two Sided: " + << (this->TwoSided ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkButtonSource.h b/Graphics/vtkButtonSource.h new file mode 100644 index 0000000..b681da2 --- /dev/null +++ b/Graphics/vtkButtonSource.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkButtonSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkButtonSource - abstract class for creating various button types +// .SECTION Description +// vtkButtonSource is an abstract class that defines an API for creating +// "button-like" objects in VTK. A button is a geometry with a rectangular +// region that can be textured. The button is divided into two regions: the +// texture region and the shoulder region. The points in both regions are +// assigned texture coordinates. The texture region has texture coordinates +// consistent with the image to be placed on it. All points in the shoulder +// regions are assigned a texture coordinate specified by the user. In this +// way the shoulder region can be colored by the texture. +// +// Creating a vtkButtonSource requires specifying its center point. +// (Subclasses have other attributes that must be set to control +// the shape of the button.) You must also specify how to control +// the shape of the texture region; i.e., wheter to size the +// texture region proportional to the texture dimensions or whether +// to size the texture region proportional to the button. Also, buttons +// can be created single sided are mirrored to create two-sided buttons. + +// .SECTION See Also +// vtkEllipticalButtonSource vtkRectangularButtonSource + +// .SECTION Caveats +// The button is defined in the x-y plane. Use vtkTransformPolyDataFilter +// or vtkGlyph3D to orient the button in a different direction. + + +#ifndef __vtkButtonSource_h +#define __vtkButtonSource_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_TEXTURE_STYLE_FIT_IMAGE 0 +#define VTK_TEXTURE_STYLE_PROPORTIONAL 1 + +class VTK_GRAPHICS_EXPORT vtkButtonSource : public vtkPolyDataAlgorithm +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkButtonSource,vtkPolyDataAlgorithm); + + // Description: + // Specify a point defining the origin (center) of the button. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set/Get the style of the texture region: whether to size it + // according to the x-y dimensions of the texture, or whether to make + // the texture region proportional to the width/height of the button. + vtkSetClampMacro(TextureStyle,int,VTK_TEXTURE_STYLE_FIT_IMAGE, + VTK_TEXTURE_STYLE_PROPORTIONAL); + vtkGetMacro(TextureStyle,int); + void SetTextureStyleToFitImage() + {this->SetTextureStyle(VTK_TEXTURE_STYLE_FIT_IMAGE);} + void SetTextureStyleToProportional() + {this->SetTextureStyle(VTK_TEXTURE_STYLE_PROPORTIONAL);} + + // Description: + // Set/get the texture dimension. This needs to be set if the texture + // style is set to fit the image. + vtkSetVector2Macro(TextureDimensions,int); + vtkGetVector2Macro(TextureDimensions,int); + + // Description: + // Set/Get the default texture coordinate to set the shoulder region to. + vtkSetVector2Macro(ShoulderTextureCoordinate,double); + vtkGetVector2Macro(ShoulderTextureCoordinate,double); + + // Description: + // Indicate whether the button is single or double sided. A double sided + // button can be viewed from two sides...it looks sort of like a "pill." + // A single-sided button is meant to viewed from a single side; it looks + // like a "clam-shell." + vtkSetMacro(TwoSided,int); + vtkGetMacro(TwoSided,int); + vtkBooleanMacro(TwoSided,int); + +protected: + vtkButtonSource(); + ~vtkButtonSource() {} + + double Center[3]; + double ShoulderTextureCoordinate[2]; + int TextureStyle; + int TextureDimensions[2]; + int TwoSided; + +private: + vtkButtonSource(const vtkButtonSource&); // Not implemented. + void operator=(const vtkButtonSource&); // Not implemented. + +}; + +#endif + + diff --git a/Graphics/vtkCellCenterDepthSort.cxx b/Graphics/vtkCellCenterDepthSort.cxx new file mode 100644 index 0000000..45e910f --- /dev/null +++ b/Graphics/vtkCellCenterDepthSort.cxx @@ -0,0 +1,251 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellCenterDepthSort.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ +#include "vtkCellCenterDepthSort.h" + +#include "vtkObjectFactory.h" +#include "vtkIdTypeArray.h" +#include "vtkDataSet.h" +#include "vtkCamera.h" +#include "vtkMatrix4x4.h" +#include "vtkFloatArray.h" +#include "vtkCell.h" +#include "vtkMath.h" +#include "vtkSortDataArray.h" + +#include +#include +#include + +//----------------------------------------------------------------------------- + +typedef vtkstd::pair vtkIdPair; + +class vtkCellCenterDepthSortStack +{ +public: + vtkstd::stack Stack; +}; + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkCellCenterDepthSort, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkCellCenterDepthSort); + +vtkCellCenterDepthSort::vtkCellCenterDepthSort() +{ + this->SortedCells = vtkIdTypeArray::New(); + this->SortedCells->SetNumberOfComponents(1); + this->SortedCellPartition = vtkIdTypeArray::New(); + this->SortedCells->SetNumberOfComponents(1); + + this->CellCenters = vtkFloatArray::New(); + this->CellCenters->SetNumberOfComponents(3); + this->CellDepths = vtkFloatArray::New(); + this->CellDepths->SetNumberOfComponents(1); + this->CellPartitionDepths = vtkFloatArray::New(); + this->CellPartitionDepths->SetNumberOfComponents(1); + + this->ToSort = new vtkCellCenterDepthSortStack; +} + +vtkCellCenterDepthSort::~vtkCellCenterDepthSort() +{ + this->SortedCells->Delete(); + this->SortedCellPartition->Delete(); + this->CellCenters->Delete(); + this->CellDepths->Delete(); + this->CellPartitionDepths->Delete(); + + delete this->ToSort; +} + +void vtkCellCenterDepthSort::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +float *vtkCellCenterDepthSort::ComputeProjectionVector() +{ + vtkDebugMacro("ComputeProjectionVector"); + + if (this->Camera == NULL) + { + vtkErrorMacro("Must set camera before sorting cells."); + static float v[3] = { 0.0, 0.0, 0.0}; + return v; + } + + double focalPoint[4]; + double position[4]; + + this->Camera->GetFocalPoint(focalPoint); focalPoint[3] = 1.0; + this->Camera->GetPosition(position); position[3] = 1.0; + + this->InverseModelTransform->MultiplyPoint(focalPoint, focalPoint); + this->InverseModelTransform->MultiplyPoint(position, position); + + static float vector[3]; + if (this->Direction == vtkVisibilitySort::BACK_TO_FRONT) + { + // Sort back to front. + vector[0] = position[0] - focalPoint[0]; + vector[1] = position[1] - focalPoint[1]; + vector[2] = position[2] - focalPoint[2]; + } + else + { + // Sort front to back. + vector[0] = focalPoint[0] - position[0]; + vector[1] = focalPoint[1] - position[1]; + vector[2] = focalPoint[2] - position[2]; + } + + vtkDebugMacro("Returning: " << vector[0] << ", " << vector[1] << ", " + << vector[2]); + + return vector; +} + +void vtkCellCenterDepthSort::ComputeCellCenters() +{ + vtkIdType numcells = this->Input->GetNumberOfCells(); + this->CellCenters->SetNumberOfTuples(numcells); + + float *center = this->CellCenters->GetPointer(0); + double dcenter[3]; + double *weights = new double[this->Input->GetMaxCellSize()]; //Dummy array. + + for (vtkIdType i = 0; i < numcells; i++) + { + vtkCell *cell = this->Input->GetCell(i); + double pcenter[3]; + int subId; + subId = cell->GetParametricCenter(pcenter); + cell->EvaluateLocation(subId, pcenter, dcenter, weights); + center[0] = dcenter[0]; center[1] = dcenter[1]; center[2] = dcenter[2]; + center += 3; + } + + delete[] weights; +} + +void vtkCellCenterDepthSort::ComputeDepths() +{ + float *vector = this->ComputeProjectionVector(); + vtkIdType numcells = this->Input->GetNumberOfCells(); + + float *center = this->CellCenters->GetPointer(0); + float *depth = this->CellDepths->GetPointer(0); + for (vtkIdType i = 0; i < numcells; i++) + { + *(depth++) = vtkMath::Dot(center, vector); + center += 3; + } +} + +void vtkCellCenterDepthSort::InitTraversal() +{ + vtkDebugMacro("InitTraversal"); + + vtkIdType numcells = this->Input->GetNumberOfCells(); + + if ( (this->LastSortTime < this->Input->GetMTime()) + || (this->LastSortTime < this->MTime) ) + { + vtkDebugMacro("Building cell centers array."); + + // Data may have changed. Recompute cell centers. + this->ComputeCellCenters(); + this->CellDepths->SetNumberOfTuples(numcells); + this->SortedCells->SetNumberOfTuples(numcells); + } + + vtkDebugMacro("Filling SortedCells to initial values."); + vtkIdType *id = this->SortedCells->GetPointer(0); + for (vtkIdType i = 0; i < numcells; i++) + { + *(id++) = i; + } + + vtkDebugMacro("Calculating depths."); + this->ComputeDepths(); + + while (!this->ToSort->Stack.empty()) this->ToSort->Stack.pop(); + this->ToSort->Stack.push(vtkIdPair(0, numcells)); + + this->LastSortTime.Modified(); +} + +vtkIdTypeArray *vtkCellCenterDepthSort::GetNextCells() +{ + if (this->ToSort->Stack.empty()) + { + // Already sorted and returned everything. + return NULL; + } + + vtkIdType *cellIds = this->SortedCells->GetPointer(0); + float *cellDepths = this->CellDepths->GetPointer(0); + vtkIdPair partition; + + partition = this->ToSort->Stack.top(); this->ToSort->Stack.pop(); + while (partition.second - partition.first > this->MaxCellsReturned) + { + vtkIdType left = partition.first; + vtkIdType right = partition.second - 1; + float pivot = cellDepths[(vtkIdType)vtkMath::Random(left, right)]; + while (left <= right) + { + while ((left <= right) && (cellDepths[left] < pivot)) left++; + while ((left <= right) && (cellDepths[right] > pivot)) right--; + + if (left > right) break; + + vtkstd::swap(cellIds[left], cellIds[right]); + vtkstd::swap(cellDepths[left], cellDepths[right]); + + left++; right--; + } + + this->ToSort->Stack.push(vtkIdPair(left, partition.second)); + partition.second = left; + } + + if (partition.second <= partition.first) + { + // Got a partition of zero size. Just recurse to get the next one. + return this->GetNextCells(); + } + + vtkIdType firstcell = partition.first; + vtkIdType numcells = partition.second - partition.first; + + this->SortedCellPartition->SetArray(cellIds + firstcell, numcells, 1); + this->SortedCellPartition->SetNumberOfTuples(numcells); + this->CellPartitionDepths->SetArray(cellDepths + firstcell, numcells, 1); + this->CellPartitionDepths->SetNumberOfTuples(numcells); + + vtkSortDataArray::Sort(this->CellPartitionDepths, this->SortedCellPartition); + return this->SortedCellPartition; +} diff --git a/Graphics/vtkCellCenterDepthSort.h b/Graphics/vtkCellCenterDepthSort.h new file mode 100644 index 0000000..8957bc0 --- /dev/null +++ b/Graphics/vtkCellCenterDepthSort.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellCenterDepthSort.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkCellCenterDepthSort - A simple implementation of vtkCellDepthSort. +// +// .SECTION Description +// vtkCellCenterDepthSort is a simple and fast implementation of depth +// sort, but it only provides approximate results. The sorting algorithm +// finds the centroids of all the cells. It then performs the dot product +// of the centroids against a vector pointing in the direction of the +// camera transformed into object space. It then performs an ordinary sort +// on the result. +// + +#ifndef __vtkCellCenterDepthSort_h +#define __vtkCellCenterDepthSort_h + +#include "vtkVisibilitySort.h" + +class vtkFloatArray; + +class vtkCellCenterDepthSortStack; + +class VTK_GRAPHICS_EXPORT vtkCellCenterDepthSort : public vtkVisibilitySort +{ +public: + vtkTypeRevisionMacro(vtkCellCenterDepthSort, vtkVisibilitySort); + virtual void PrintSelf(ostream &os, vtkIndent indent); + static vtkCellCenterDepthSort *New(); + + virtual void InitTraversal(); + virtual vtkIdTypeArray *GetNextCells(); + +protected: + vtkCellCenterDepthSort(); + virtual ~vtkCellCenterDepthSort(); + + vtkIdTypeArray *SortedCells; + vtkIdTypeArray *SortedCellPartition; + + vtkFloatArray *CellCenters; + vtkFloatArray *CellDepths; + vtkFloatArray *CellPartitionDepths; + + virtual float *ComputeProjectionVector(); + virtual void ComputeCellCenters(); + virtual void ComputeDepths(); + +private: + vtkCellCenterDepthSortStack *ToSort; + + vtkCellCenterDepthSort(const vtkCellCenterDepthSort &); // Not implemented. + void operator=(const vtkCellCenterDepthSort &); // Not implemented. +}; + +#endif //__vtkCellCenterDepthSort_h + diff --git a/Graphics/vtkCellCenters.cxx b/Graphics/vtkCellCenters.cxx new file mode 100644 index 0000000..e5d8cbc --- /dev/null +++ b/Graphics/vtkCellCenters.cxx @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellCenters.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellCenters.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkCellArray.h" + +vtkCxxRevisionMacro(vtkCellCenters, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkCellCenters); + +// Construct object with vertex cell generation turned off. +vtkCellCenters::vtkCellCenters() +{ + this->VertexCells = 0; +} + +// Generate points +int vtkCellCenters::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, numCells; + int subId; + vtkCellData *inCD; + vtkPointData *outPD; + vtkPoints *newPts; + vtkCell *cell; + double x[3], pcoords[3]; + double *weights; + + inCD=input->GetCellData(); + outPD=output->GetPointData(); + + if ( (numCells = input->GetNumberOfCells()) < 1 ) + { + vtkWarningMacro(<<"No cells to generate center points for"); + return 1; + } + + newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numCells); + weights = new double [input->GetMaxCellSize()]; + + int abort=0; + vtkIdType progressInterval = numCells/10 + 1; + int hasEmptyCells = 0; + for (cellId=0; cellId < numCells && !abort; cellId++) + { + if ( ! (cellId % progressInterval) ) + { + vtkDebugMacro(<<"Processing #" << cellId); + this->UpdateProgress (0.5*cellId/numCells); + abort = this->GetAbortExecute(); + } + + cell = input->GetCell(cellId); + if (cell->GetCellType() != VTK_EMPTY_CELL) + { + subId = cell->GetParametricCenter(pcoords); + cell->EvaluateLocation(subId, pcoords, x, weights); + newPts->SetPoint(cellId,x); + } + else + { + hasEmptyCells = 1; + } + } + + if ( this->VertexCells ) + { + vtkIdType pts[1]; + vtkCellData *outCD=output->GetCellData(); + vtkCellArray *verts = vtkCellArray::New(); + verts->Allocate(verts->EstimateSize(1,numCells),1); + + for (cellId=0; cellId < numCells && !abort; cellId++) + { + if ( ! (cellId % progressInterval) ) + { + vtkDebugMacro(<<"Processing #" << cellId); + this->UpdateProgress (0.5+0.5*cellId/numCells); + abort = this->GetAbortExecute(); + } + + cell = input->GetCell(cellId); + if (cell->GetCellType() != VTK_EMPTY_CELL) + { + pts[0] = cellId; + verts->InsertNextCell(1,pts); + } + } + + output->SetVerts(verts); + verts->Delete(); + if (!hasEmptyCells) + { + outCD->PassData(inCD); //only if verts are generated + } + } + + // clean up and update output + output->SetPoints(newPts); + newPts->Delete(); + + if (!hasEmptyCells) + { + outPD->PassData(inCD); //because number of points = number of cells + } + if (weights) + { + delete [] weights; + } + + return 1; +} + +int vtkCellCenters::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkCellCenters::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Vertex Cells: " << (this->VertexCells ? "On\n" : "Off\n"); +} + diff --git a/Graphics/vtkCellCenters.h b/Graphics/vtkCellCenters.h new file mode 100644 index 0000000..56205c7 --- /dev/null +++ b/Graphics/vtkCellCenters.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellCenters.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellCenters - generate points at center of cells +// .SECTION Description +// vtkCellCenters is a filter that takes as input any dataset and +// generates on output points at the center of the cells in the dataset. +// These points can be used for placing glyphs (vtkGlyph3D) or labeling +// (vtkLabeledDataMapper). (The center is the parametric center of the +// cell, not necessarily the geometric or bounding box center.) The cell +// attributes will be associated with the points on output. +// +// .SECTION Caveats +// You can choose to generate just points or points and vertex cells. +// Vertex cells are drawn during rendering; points are not. Use the ivar +// VertexCells to generate cells. + +// .SECTION See Also +// vtkGlyph3D vtkLabeledDataMapper + +#ifndef __vtkCellCenters_h +#define __vtkCellCenters_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkCellCenters : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkCellCenters,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with vertex cell generation turned off. + static vtkCellCenters *New(); + + // Description: + // Enable/disable the generation of vertex cells. + vtkSetMacro(VertexCells,int); + vtkGetMacro(VertexCells,int); + vtkBooleanMacro(VertexCells,int); + +protected: + vtkCellCenters(); + ~vtkCellCenters() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int VertexCells; +private: + vtkCellCenters(const vtkCellCenters&); // Not implemented. + void operator=(const vtkCellCenters&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkCellDataToPointData.cxx b/Graphics/vtkCellDataToPointData.cxx new file mode 100644 index 0000000..daa7aa5 --- /dev/null +++ b/Graphics/vtkCellDataToPointData.cxx @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellDataToPointData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellDataToPointData.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkCellDataToPointData, "$Revision: 1.31 $"); +vtkStandardNewMacro(vtkCellDataToPointData); + +//---------------------------------------------------------------------------- +// Instantiate object so that cell data is not passed to output. +vtkCellDataToPointData::vtkCellDataToPointData() +{ + this->PassCellData = 0; +} + +#define VTK_MAX_CELLS_PER_POINT 4096 + +//---------------------------------------------------------------------------- +int vtkCellDataToPointData::RequestData( + vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, ptId; + vtkIdType numCells, numPts; + vtkCellData *inPD=input->GetCellData(); + vtkPointData *outPD=output->GetPointData(); + vtkIdList *cellIds; + double weight; + double *weights; + + vtkDebugMacro(<<"Mapping cell data to point data"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + cellIds = vtkIdList::New(); + cellIds->Allocate(VTK_MAX_CELLS_PER_POINT); + + if ( (numPts=input->GetNumberOfPoints()) < 1 ) + { + vtkDebugMacro(<<"No input point data!"); + cellIds->Delete(); + return 1; + } + weights = new double[VTK_MAX_CELLS_PER_POINT]; + + // Pass the point data first. The fields and attributes + // which also exist in the cell data of the input will + // be over-written during CopyAllocate + output->GetPointData()->PassData(input->GetPointData()); + + // notice that inPD and outPD are vtkCellData and vtkPointData; respectively. + // It's weird, but it works. + outPD->CopyAllocate(inPD,numPts); + + int abort=0; + vtkIdType progressInterval=numPts/20 + 1; + for (ptId=0; ptId < numPts && !abort; ptId++) + { + if ( !(ptId % progressInterval) ) + { + this->UpdateProgress((double)ptId/numPts); + abort = GetAbortExecute(); + } + + input->GetPointCells(ptId, cellIds); + numCells = cellIds->GetNumberOfIds(); + if ( numCells > 0 ) + { + weight = 1.0 / numCells; + for (cellId=0; cellId < numCells; cellId++) + { + weights[cellId] = weight; + } + outPD->InterpolatePoint(inPD, ptId, cellIds, weights); + } + else + { + outPD->NullPoint(ptId); + } + } + + if ( this->PassCellData ) + { + output->GetCellData()->PassData(input->GetCellData()); + } + + cellIds->Delete(); + delete [] weights; + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkCellDataToPointData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Pass Cell Data: " << (this->PassCellData ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkCellDataToPointData.h b/Graphics/vtkCellDataToPointData.h new file mode 100644 index 0000000..14d54ce --- /dev/null +++ b/Graphics/vtkCellDataToPointData.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellDataToPointData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellDataToPointData - map cell data to point data +// .SECTION Description +// vtkCellDataToPointData is a filter that transforms cell data (i.e., data +// specified per cell) into point data (i.e., data specified at cell +// points). The method of transformation is based on averaging the data +// values of all cells using a particular point. Optionally, the input cell +// data can be passed through to the output as well. + +// .SECTION Caveats +// This filter is an abstract filter, that is, the output is an abstract type +// (i.e., vtkDataSet). Use the convenience methods (e.g., +// vtkGetPolyDataOutput(), GetStructuredPointsOutput(), etc.) to get the type +// of output you want. + +// .SECTION See Also +// vtkPointData vtkCellData vtkPointDataToCellData + + +#ifndef __vtkCellDataToPointData_h +#define __vtkCellDataToPointData_h + +#include "vtkDataSetAlgorithm.h" + +class vtkDataSet; + +class VTK_GRAPHICS_EXPORT vtkCellDataToPointData : public vtkDataSetAlgorithm +{ +public: + static vtkCellDataToPointData *New(); + vtkTypeRevisionMacro(vtkCellDataToPointData,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Control whether the input cell data is to be passed to the output. If + // on, then the input cell data is passed through to the output; otherwise, + // only generated point data is placed into the output. + vtkSetMacro(PassCellData,int); + vtkGetMacro(PassCellData,int); + vtkBooleanMacro(PassCellData,int); + +protected: + vtkCellDataToPointData(); + ~vtkCellDataToPointData() {}; + + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + int PassCellData; +private: + vtkCellDataToPointData(const vtkCellDataToPointData&); // Not implemented. + void operator=(const vtkCellDataToPointData&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkCellDerivatives.cxx b/Graphics/vtkCellDerivatives.cxx new file mode 100644 index 0000000..7859551 --- /dev/null +++ b/Graphics/vtkCellDerivatives.cxx @@ -0,0 +1,253 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellDerivatives.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellDerivatives.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkTensor.h" + +#include + +vtkCxxRevisionMacro(vtkCellDerivatives, "$Revision: 1.27 $"); +vtkStandardNewMacro(vtkCellDerivatives); + +vtkCellDerivatives::vtkCellDerivatives() +{ + this->VectorMode = VTK_VECTOR_MODE_COMPUTE_GRADIENT; + this->TensorMode = VTK_TENSOR_MODE_COMPUTE_GRADIENT; +} + +int vtkCellDerivatives::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + vtkDataArray *inScalars=pd->GetScalars(); + vtkDataArray *inVectors=pd->GetVectors(); + vtkDoubleArray *outVectors=NULL; + vtkDoubleArray *outTensors=NULL; + vtkIdType numCells=input->GetNumberOfCells(); + int computeScalarDerivs=1, computeVectorDerivs=1, subId; + + // Initialize + vtkDebugMacro(<<"Computing cell derivatives"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + // Check input + if ( numCells < 1 ) + { + vtkErrorMacro("No cells to generate derivatives from"); + return 1; + } + + // Figure out what to compute + if ( !inScalars || this->VectorMode == VTK_VECTOR_MODE_PASS_VECTORS ) + { + computeScalarDerivs = 0; + } + else + { + if ( this->VectorMode == VTK_VECTOR_MODE_COMPUTE_VORTICITY ) + { + computeScalarDerivs = 0; + } + outVectors = vtkDoubleArray::New(); + outVectors->SetNumberOfComponents(3); + outVectors->SetNumberOfTuples(numCells); + outVectors->SetName("Vorticity"); + outCD->SetVectors(outVectors); + outVectors->Delete(); //okay reference counted + outCD->CopyVectorsOff(); + } + + if ( !inVectors || (this->TensorMode == VTK_TENSOR_MODE_PASS_TENSORS && + this->VectorMode != VTK_VECTOR_MODE_COMPUTE_VORTICITY) ) + { + computeVectorDerivs = 0; + } + else + { + outTensors = vtkDoubleArray::New(); + outTensors->SetNumberOfComponents(9); + outTensors->SetNumberOfTuples(numCells); + outTensors->SetName("Tensors"); + outCD->SetTensors(outTensors); + outTensors->Delete(); //okay reference counted + outCD->CopyTensorsOff(); + } + + // If just passing data forget the loop + if ( computeScalarDerivs || computeVectorDerivs ) + { + double pcoords[3], derivs[9], w[3], *scalars, *vectors; + vtkGenericCell *cell = vtkGenericCell::New(); + vtkIdType cellId; + vtkDoubleArray *cellScalars=vtkDoubleArray::New(); + if ( computeScalarDerivs ) + { + cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + cellScalars->Allocate(cellScalars->GetNumberOfComponents()*VTK_CELL_SIZE); + cellScalars->SetName("Scalars"); + } + vtkDoubleArray *cellVectors=vtkDoubleArray::New(); + cellVectors->SetNumberOfComponents(3); + cellVectors->Allocate(3*VTK_CELL_SIZE); + cellVectors->SetName("Vectors"); + vtkTensor* tens = vtkTensor::New(); + + // Loop over all cells computing derivatives + vtkIdType progressInterval = numCells/20 + 1; + for (cellId=0; cellId < numCells; cellId++) + { + if ( ! (cellId % progressInterval) ) + { + vtkDebugMacro(<<"Computing cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + } + + input->GetCell(cellId, cell); + subId = cell->GetParametricCenter(pcoords); + + if ( computeScalarDerivs ) + { + inScalars->GetTuples(cell->PointIds, cellScalars); + scalars = cellScalars->GetPointer(0); + cell->Derivatives(subId, pcoords, scalars, 1, derivs); + outVectors->SetTuple(cellId, derivs); + } + + if ( computeVectorDerivs ) + { + inVectors->GetTuples(cell->PointIds, cellVectors); + vectors = cellVectors->GetPointer(0); + cell->Derivatives(0, pcoords, vectors, 3, derivs); + + // Insert appropriate tensor + if ( this->TensorMode == VTK_TENSOR_MODE_COMPUTE_GRADIENT) + { + tens->SetComponent(0,0, derivs[0]); + tens->SetComponent(0,1, derivs[1]); + tens->SetComponent(0,2, derivs[2]); + tens->SetComponent(1,0, derivs[3]); + tens->SetComponent(1,1, derivs[4]); + tens->SetComponent(1,2, derivs[5]); + tens->SetComponent(2,0, derivs[6]); + tens->SetComponent(2,1, derivs[7]); + tens->SetComponent(2,2, derivs[8]); + + outTensors->InsertTuple(cellId, tens->T); + } + else // this->TensorMode == VTK_TENSOR_MODE_COMPUTE_STRAIN + { + tens->SetComponent(0,0, derivs[0]); + tens->SetComponent(0,1, 0.5*(derivs[1]+derivs[3])); + tens->SetComponent(0,2, 0.5*(derivs[2]+derivs[6])); + tens->SetComponent(1,0, 0.5*(derivs[1]+derivs[3])); + tens->SetComponent(1,1, derivs[4]); + tens->SetComponent(1,2, 0.5*(derivs[5]+derivs[7])); + tens->SetComponent(2,0, 0.5*(derivs[2]+derivs[6])); + tens->SetComponent(2,1, 0.5*(derivs[5]+derivs[7])); + tens->SetComponent(2,2, derivs[8]); + + outTensors->InsertTuple(cellId, tens->T); + } + + if ( this->VectorMode == VTK_VECTOR_MODE_COMPUTE_VORTICITY ) + { + w[0] = derivs[7] - derivs[5]; + w[1] = derivs[2] - derivs[6]; + w[2] = derivs[3] - derivs[1]; + outVectors->SetTuple(cellId, w); + } + } + }//for all cells + + cell->Delete(); + cellScalars->Delete(); + cellVectors->Delete(); + tens->Delete(); + }//if something to compute + + // Pass appropriate data through to output + outPD->PassData(pd); + outCD->PassData(cd); + + return 1; +} + +const char *vtkCellDerivatives::GetVectorModeAsString(void) +{ + if ( this->VectorMode == VTK_VECTOR_MODE_PASS_VECTORS ) + { + return "PassVectors"; + } + else if ( this->VectorMode == VTK_VECTOR_MODE_COMPUTE_GRADIENT ) + { + return "ComputeGradient"; + } + else //VTK_VECTOR_MODE_COMPUTE_VORTICITY + { + return "ComputeVorticity"; + } +} + +const char *vtkCellDerivatives::GetTensorModeAsString(void) +{ + if ( this->TensorMode == VTK_TENSOR_MODE_PASS_TENSORS ) + { + return "PassTensors"; + } + else if ( this->TensorMode == VTK_TENSOR_MODE_COMPUTE_GRADIENT ) + { + return "ComputeGradient"; + } + else //VTK_TENSOR_MODE_COMPUTE_STRAIN + { + return "ComputeVorticity"; + } +} + +void vtkCellDerivatives::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Vector Mode: " << this->GetVectorModeAsString() + << endl; + + os << indent << "Tensor Mode: " << this->GetTensorModeAsString() + << endl; +} + diff --git a/Graphics/vtkCellDerivatives.h b/Graphics/vtkCellDerivatives.h new file mode 100644 index 0000000..667c0a8 --- /dev/null +++ b/Graphics/vtkCellDerivatives.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellDerivatives.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellDerivatives - compute derivatives of scalars and vectors +// .SECTION Description +// vtkCellDerivatives is a filter that computes derivatives of scalars +// and vectors at the center of cells. You can choose to generate +// different output including the scalar gradient (a vector), computed +// tensor vorticity (a vector), gradient of input vectors (a tensor), +// and strain matrix of the input vectors (a tensor); or you may +// choose to pass data through to the output. +// +// Note that it is assumed that on input scalars and vector point data +// is available, which are then used to generate cell vectors and tensors. +// (The interpolation functions of the cells are used to compute the +// derivatives which is why point data is required.) + +// .SECTION Caveats +// The computed derivatives are cell attribute data; you can convert them to +// point attribute data by using the vtkCellDataToPointData filter. +// Note that, due to the interpolation function used (obtained using +// 1/r**2 normalized sum), the derivatives calculated for polygons +// with more than 4 vertices are inaccurate in most cases. +// +// The point data is passed through the filter to the output. + +// .SECTION See Also +// vtkVectorNorm + +#ifndef __vtkCellDerivatives_h +#define __vtkCellDerivatives_h + +#include "vtkDataSetAlgorithm.h" + +#define VTK_VECTOR_MODE_PASS_VECTORS 0 +#define VTK_VECTOR_MODE_COMPUTE_GRADIENT 1 +#define VTK_VECTOR_MODE_COMPUTE_VORTICITY 2 + +#define VTK_TENSOR_MODE_PASS_TENSORS 0 +#define VTK_TENSOR_MODE_COMPUTE_GRADIENT 1 +#define VTK_TENSOR_MODE_COMPUTE_STRAIN 2 + +class VTK_GRAPHICS_EXPORT vtkCellDerivatives : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkCellDerivatives,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct to compute the gradient of the scalars and vectors. + static vtkCellDerivatives *New(); + + // Description: + // Control how the filter works to generate vector cell data. You + // can choose to pass the input cell vectors, compute the gradient + // of the input scalars, or extract the vorticity of the computed + // vector gradient tensor. By default (VectorModeToComputeGradient), + // the filter will take the gradient of the input scalar data. + vtkSetMacro(VectorMode,int); + vtkGetMacro(VectorMode,int); + void SetVectorModeToPassVectors() + {this->SetVectorMode(VTK_VECTOR_MODE_PASS_VECTORS);}; + void SetVectorModeToComputeGradient() + {this->SetVectorMode(VTK_VECTOR_MODE_COMPUTE_GRADIENT);}; + void SetVectorModeToComputeVorticity() + {this->SetVectorMode(VTK_VECTOR_MODE_COMPUTE_VORTICITY);}; + const char *GetVectorModeAsString(); + + // Description: + // Control how the filter works to generate tensor cell data. You can + // choose to pass the input cell tensors, compute the gradient of + // the input vectors, or compute the strain tensor of the vector gradient + // tensor. By default (TensorModeToComputeGradient), the filter will + // take the gradient of the vector data to construct a tensor. + vtkSetMacro(TensorMode,int); + vtkGetMacro(TensorMode,int); + void SetTensorModeToPassTensors() + {this->SetTensorMode(VTK_TENSOR_MODE_PASS_TENSORS);}; + void SetTensorModeToComputeGradient() + {this->SetTensorMode(VTK_TENSOR_MODE_COMPUTE_GRADIENT);}; + void SetTensorModeToComputeStrain() + {this->SetTensorMode(VTK_TENSOR_MODE_COMPUTE_STRAIN);}; + const char *GetTensorModeAsString(); + +protected: + vtkCellDerivatives(); + ~vtkCellDerivatives() {}; + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int VectorMode; + int TensorMode; +private: + vtkCellDerivatives(const vtkCellDerivatives&); // Not implemented. + void operator=(const vtkCellDerivatives&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkCleanPolyData.cxx b/Graphics/vtkCleanPolyData.cxx new file mode 100644 index 0000000..7103798 --- /dev/null +++ b/Graphics/vtkCleanPolyData.cxx @@ -0,0 +1,724 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCleanPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCleanPolyData.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkCleanPolyData, "$Revision: 1.77 $"); +vtkStandardNewMacro(vtkCleanPolyData); + +//--------------------------------------------------------------------------- +// Construct object with initial Tolerance of 0.0 +vtkCleanPolyData::vtkCleanPolyData() +{ + this->PointMerging = 1; + this->ToleranceIsAbsolute = 0; + this->Tolerance = 0.0; + this->AbsoluteTolerance = 1.0; + this->ConvertPolysToLines = 1; + this->ConvertLinesToPoints = 1; + this->ConvertStripsToPolys = 1; + this->Locator = NULL; + this->PieceInvariant = 1; +} + +//-------------------------------------------------------------------------- +vtkCleanPolyData::~vtkCleanPolyData() +{ + this->ReleaseLocator(); +} + +//-------------------------------------------------------------------------- +void vtkCleanPolyData::OperateOnPoint(double in[3], double out[3]) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +//-------------------------------------------------------------------------- +void vtkCleanPolyData::OperateOnBounds(double in[6], double out[6]) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out[4] = in[4]; + out[5] = in[5]; +} + +//-------------------------------------------------------------------------- +int vtkCleanPolyData::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if (this->PieceInvariant) + { + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + 1); + } + else + { + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + } + + return 1; +} + +//-------------------------------------------------------------------------- +int vtkCleanPolyData::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if (this->PieceInvariant) + { + // Although piece > 1 is handled by superclass, we should be thorough. + if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) == 0) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + } + else + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), -1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 0); + } + } + else + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + } + + return 1; +} + +//-------------------------------------------------------------------------- +int vtkCleanPolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts = input->GetPoints(); + vtkIdType numPts = input->GetNumberOfPoints(); + + vtkDebugMacro(<<"Beginning PolyData clean"); + if ( (numPts<1) || (inPts == NULL ) ) + { + vtkDebugMacro(<<"No data to Operate On!"); + return 1; + } + vtkIdType *updatedPts = new vtkIdType[input->GetMaxCellSize()]; + + vtkIdType numNewPts; + vtkIdType numUsedPts=0; + vtkPoints *newPts = vtkPoints::New(); + newPts->Allocate(numPts); + + // we'll be needing these + vtkIdType inCellID, newId; + int i; + vtkIdType ptId; + vtkIdType npts = 0; + vtkIdType *pts = 0; + double x[3]; + double newx[3]; + vtkIdType *pointMap=0; //used if no merging + + vtkCellArray *inVerts = input->GetVerts(), *newVerts = NULL; + vtkCellArray *inLines = input->GetLines(), *newLines = NULL; + vtkCellArray *inPolys = input->GetPolys(), *newPolys = NULL; + vtkCellArray *inStrips = input->GetStrips(), *newStrips = NULL; + + vtkPointData *inputPD = input->GetPointData(); + vtkCellData *inputCD = input->GetCellData(); + + // We must be careful to 'operate' on the bounds of the locator so + // that all inserted points lie inside it + if ( this->PointMerging ) + { + this->CreateDefaultLocator(input); + if (this->ToleranceIsAbsolute) + { + this->Locator->SetTolerance(this->AbsoluteTolerance); + } + else + { + this->Locator->SetTolerance(this->Tolerance*input->GetLength()); + } + double originalbounds[6], mappedbounds[6]; + input->GetBounds(originalbounds); + this->OperateOnBounds(originalbounds,mappedbounds); + this->Locator->InitPointInsertion(newPts, mappedbounds); + } + else + { + pointMap = new vtkIdType [numPts]; + for (i=0; i < numPts; i++) + { + pointMap[i] = -1; //initialize unused + } + } + + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + outputPD->CopyAllocate(inputPD); + outputCD->CopyAllocate(inputCD); + + // Celldata needs to be copied correctly. If a poly is converted to + // a line, or a line to a point, then using a CellCounter will not + // do, as the cells should be ordered verts, lines, polys, + // strips. We need to maintain seperate cell data lists so we can + // copy them all correctly. Tedious but easy to implement. We can + // use outputCD for vertex cell data, then add the rest at the end. + vtkCellData *outLineData = NULL; + vtkCellData *outPolyData = NULL; + vtkCellData *outStrpData = NULL; + vtkIdType vertIDcounter = 0, lineIDcounter = 0; + vtkIdType polyIDcounter = 0, strpIDcounter = 0; + + // Begin to adjust topology. + // + // Vertices are renumbered and we remove duplicates + inCellID = 0; + if ( !this->GetAbortExecute() && inVerts->GetNumberOfCells() > 0 ) + { + newVerts = vtkCellArray::New(); + newVerts->Allocate(inVerts->GetSize()); + + vtkDebugMacro(<<"Starting Verts "<InitTraversal(); inVerts->GetNextCell(npts,pts); + inCellID++) + { + for ( numNewPts=0, i=0; i < npts; i++ ) + { + inPts->GetPoint(pts[i],x); + this->OperateOnPoint(x, newx); + if ( ! this->PointMerging ) + { + if ( (ptId=pointMap[pts[i]]) == -1 ) + { + pointMap[pts[i]] = ptId = numUsedPts++; + newPts->SetPoint(ptId,newx); + outputPD->CopyData(inputPD,pts[i],ptId); + } + } + else if ( this->Locator->InsertUniquePoint(newx, ptId) ) + { + outputPD->CopyData(inputPD,pts[i],ptId); + } + updatedPts[numNewPts++] = ptId; + }//for all points of vertex cell + + if ( numNewPts > 0 ) + { + newId = newVerts->InsertNextCell(numNewPts,updatedPts); + outputCD->CopyData(inputCD, inCellID, newId); + if ( vertIDcounter != newId) + { + vtkErrorMacro(<<"Vertex ID fault in vertex test"); + } + vertIDcounter++; + } + } + } + this->UpdateProgress(0.25); + + // lines reduced to one point are eliminated or made into verts + if ( !this->GetAbortExecute() && inLines->GetNumberOfCells() > 0 ) + { + newLines = vtkCellArray::New(); + newLines->Allocate(inLines->GetSize()); + outLineData = vtkCellData::New(); + outLineData->CopyAllocate(inputCD); + // + vtkDebugMacro(<<"Starting Lines "<InitTraversal(); inLines->GetNextCell(npts,pts); inCellID++) + { + for ( numNewPts=0, i=0; iGetPoint(pts[i],x); + this->OperateOnPoint(x, newx); + if ( ! this->PointMerging ) + { + if ( (ptId=pointMap[pts[i]]) == -1 ) + { + pointMap[pts[i]] = ptId = numUsedPts++; + newPts->SetPoint(ptId,newx); + outputPD->CopyData(inputPD,pts[i],ptId); + } + } + else if ( this->Locator->InsertUniquePoint(newx, ptId) ) + { + outputPD->CopyData(inputPD,pts[i],ptId); + } + if ( i == 0 || ptId != updatedPts[numNewPts-1] ) + { + updatedPts[numNewPts++] = ptId; + } + }//for all cell points + if ( (numNewPts>1) || !this->ConvertLinesToPoints ) + { + newId = newLines->InsertNextCell(numNewPts,updatedPts); + outLineData->CopyData(inputCD, inCellID, newId); + if (lineIDcounter!=newId) + { + vtkErrorMacro(<<"Line ID fault in line test"); + } + lineIDcounter++; + } + else if ( numNewPts==1 ) + { + if (!newVerts) + { + newVerts = vtkCellArray::New(); + newVerts->Allocate(5); + } + newId = newVerts->InsertNextCell(numNewPts,updatedPts); + outputCD->CopyData(inputCD, inCellID, newId); + if (vertIDcounter!=newId) + { + vtkErrorMacro(<<"Vertex ID fault in line test"); + } + vertIDcounter++; + } + } + vtkDebugMacro(<<"Removed " + << inLines->GetNumberOfCells() - newLines->GetNumberOfCells() + << " lines"); + } + this->UpdateProgress(0.50); + + // polygons reduced to two points or less are either eliminated + // or converted to lines or points if enabled + if ( !this->GetAbortExecute() && inPolys->GetNumberOfCells() > 0 ) + { + newPolys = vtkCellArray::New(); + newPolys->Allocate(inPolys->GetSize()); + outPolyData = vtkCellData::New(); + outPolyData->CopyAllocate(inputCD); + + vtkDebugMacro(<<"Starting Polys "<InitTraversal(); inPolys->GetNextCell(npts,pts); inCellID++) + { + for ( numNewPts=0, i=0; iGetPoint(pts[i],x); + this->OperateOnPoint(x, newx); + if ( ! this->PointMerging ) + { + if ( (ptId=pointMap[pts[i]]) == -1 ) + { + pointMap[pts[i]] = ptId = numUsedPts++; + newPts->SetPoint(ptId,newx); + outputPD->CopyData(inputPD,pts[i],ptId); + } + } + else if ( this->Locator->InsertUniquePoint(newx, ptId) ) + { + outputPD->CopyData(inputPD,pts[i],ptId); + } + if ( i == 0 || ptId != updatedPts[numNewPts-1] ) + { + updatedPts[numNewPts++] = ptId; + } + } //for points in cell + if ( numNewPts>2 && updatedPts[0] == updatedPts[numNewPts-1] ) + { + numNewPts--; + } + if ( (numNewPts > 2) || !this->ConvertPolysToLines ) + { + newId = newPolys->InsertNextCell(numNewPts,updatedPts); + outPolyData->CopyData(inputCD, inCellID, newId); + if (polyIDcounter!=newId) + { + vtkErrorMacro(<<"Poly ID fault in poly test"); + } + polyIDcounter++; + } + else if ( (numNewPts==2) || !this->ConvertLinesToPoints ) + { + if (!newLines) + { + newLines = vtkCellArray::New(); + newLines->Allocate(5); + outLineData = vtkCellData::New(); + outLineData->CopyAllocate(inputCD); + } + newId = newLines->InsertNextCell(numNewPts,updatedPts); + outLineData->CopyData(inputCD, inCellID, newId); + if (lineIDcounter!=newId) + { + vtkErrorMacro(<<"Line ID fault in poly test"); + } + lineIDcounter++; + } + else if ( numNewPts==1 ) + { + if (!newVerts) + { + newVerts = vtkCellArray::New(); + newVerts->Allocate(5); + } + newId = newVerts->InsertNextCell(numNewPts,updatedPts); + outputCD->CopyData(inputCD, inCellID, newId); + if (vertIDcounter!=newId) + { + vtkErrorMacro(<<"Vertex ID fault in poly test"); + } + vertIDcounter++; + } + } + vtkDebugMacro(<<"Removed " + << inPolys->GetNumberOfCells() - newPolys->GetNumberOfCells() + << " polys"); + } + this->UpdateProgress(0.75); + + // triangle strips can reduced to polys/lines/points etc + if ( !this->GetAbortExecute() && inStrips->GetNumberOfCells() > 0 ) + { + newStrips = vtkCellArray::New(); + newStrips->Allocate(inStrips->GetSize()); + outStrpData = vtkCellData::New(); + outStrpData->CopyAllocate(inputCD); + + for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); + inCellID++) + { + for ( numNewPts=0, i=0; i < npts; i++ ) + { + inPts->GetPoint(pts[i],x); + this->OperateOnPoint(x, newx); + if ( ! this->PointMerging ) + { + if ( (ptId=pointMap[pts[i]]) == -1 ) + { + pointMap[pts[i]] = ptId = numUsedPts++; + newPts->SetPoint(ptId,newx); + outputPD->CopyData(inputPD,pts[i],ptId); + } + } + else if ( this->Locator->InsertUniquePoint(newx, ptId) ) + { + outputPD->CopyData(inputPD,pts[i],ptId); + } + if ( i == 0 || ptId != updatedPts[numNewPts-1] ) + { + updatedPts[numNewPts++] = ptId; + } + } + if ( (numNewPts > 3) || !this->ConvertStripsToPolys ) + { + newId = newStrips->InsertNextCell(numNewPts,updatedPts); + outStrpData->CopyData(inputCD, inCellID, newId); + if (strpIDcounter!=newId) + { + vtkErrorMacro(<<"Strip ID fault in strip test"); + } + strpIDcounter++; + } + else if ( (numNewPts==3) || !this->ConvertPolysToLines ) + { + if (!newPolys) + { + newPolys = vtkCellArray::New(); + newPolys->Allocate(5); + outPolyData = vtkCellData::New(); + outPolyData->CopyAllocate(inputCD); + } + newId = newPolys->InsertNextCell(numNewPts,updatedPts); + outPolyData->CopyData(inputCD, inCellID, newId); + if (polyIDcounter!=newId) + { + vtkErrorMacro(<<"Poly ID fault in strip test"); + } + polyIDcounter++; + } + else if ( (numNewPts==2) || !this->ConvertLinesToPoints ) + { + if (!newLines) + { + newLines = vtkCellArray::New(); + newLines->Allocate(5); + outLineData = vtkCellData::New(); + outLineData->CopyAllocate(inputCD); + } + newId = newLines->InsertNextCell(numNewPts,updatedPts); + outLineData->CopyData(inputCD, inCellID, newId); + if (lineIDcounter!=newId) + { + vtkErrorMacro(<<"Line ID fault in strip test"); + } + lineIDcounter++; + } + else if ( numNewPts==1 ) + { + if (!newVerts) + { + newVerts = vtkCellArray::New(); + newVerts->Allocate(5); + } + newId = newVerts->InsertNextCell(numNewPts,updatedPts); + outputCD->CopyData(inputCD, inCellID, newId); + if (vertIDcounter!=newId) + { + vtkErrorMacro(<<"Vertex ID fault in strip test"); + } + vertIDcounter++; + } + } + vtkDebugMacro(<<"Removed " + << inStrips->GetNumberOfCells() - newStrips->GetNumberOfCells() + << " strips"); + } + + vtkDebugMacro(<<"Removed " + << numPts - newPts->GetNumberOfPoints() << " points"); + + // Update ourselves and release memory + // + delete [] updatedPts; + if ( this->PointMerging ) + { + this->Locator->Initialize(); //release memory. + } + else + { + newPts->SetNumberOfPoints(numUsedPts); + delete [] pointMap; + } + + // Now transfer all CellData from Lines/Polys/Strips into final + // Cell data output + int CombinedCellID = vertIDcounter; + if (newLines) + { + for (i=0; iCopyData(outLineData, i, CombinedCellID); + } + outLineData->Delete(); + } + if (newPolys) + { + for (i=0; iCopyData(outPolyData, i, CombinedCellID); + } + outPolyData->Delete(); + } + if (newStrips) + { + for (i=0; iCopyData(outStrpData, i, CombinedCellID); + } + outStrpData->Delete(); + } + + output->SetPoints(newPts); + newPts->Squeeze(); + newPts->Delete(); + if (newVerts) + { + newVerts->Squeeze(); + output->SetVerts(newVerts); + newVerts->Delete(); + } + if (newLines) + { + newLines->Squeeze(); + output->SetLines(newLines); + newLines->Delete(); + } + if (newPolys) + { + newPolys->Squeeze(); + output->SetPolys(newPolys); + newPolys->Delete(); + } + if (newStrips) + { + newStrips->Squeeze(); + output->SetStrips(newStrips); + newStrips->Delete(); + } + + return 1; +} + +//------------------------------------------------------------------------ +// Specify a spatial locator for speeding the search process. By +// default an instance of vtkLocator is used. +void vtkCleanPolyData::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +//-------------------------------------------------------------------------- +// Method manages creation of locators. It takes into account the potential +// change of tolerance (zero to non-zero). +void vtkCleanPolyData::CreateDefaultLocator(vtkPolyData *input) +{ + double tol; + if (this->ToleranceIsAbsolute) + { + tol = this->AbsoluteTolerance; + } + else + { + if (input) + { + tol = this->Tolerance*input->GetLength(); + } + else + { + tol = this->Tolerance; + } + } + + if ( this->Locator == NULL) + { + if (tol==0.0) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } + else + { + this->Locator = vtkPointLocator::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } + } + else + { + // check that the tolerance wasn't changed from zero to non-zero + if ((tol>0.0) && (this->GetLocator()->GetTolerance()==0.0)) + { + this->ReleaseLocator(); + this->Locator = vtkPointLocator::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } + } +} + +//-------------------------------------------------------------------------- +void vtkCleanPolyData::ReleaseLocator(void) +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +//-------------------------------------------------------------------------- +void vtkCleanPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Point Merging: " + << (this->PointMerging ? "On\n" : "Off\n"); + os << indent << "ToleranceIsAbsolute: " + << (this->ToleranceIsAbsolute ? "On\n" : "Off\n"); + os << indent << "Tolerance: " + << (this->Tolerance ? "On\n" : "Off\n"); + os << indent << "AbsoluteTolerance: " + << (this->AbsoluteTolerance ? "On\n" : "Off\n"); + os << indent << "ConvertPolysToLines: " + << (this->ConvertPolysToLines ? "On\n" : "Off\n"); + os << indent << "ConvertLinesToPoints: " + << (this->ConvertLinesToPoints ? "On\n" : "Off\n"); + os << indent << "ConvertStripsToPolys: " + << (this->ConvertStripsToPolys ? "On\n" : "Off\n"); + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + os << indent << "PieceInvariant: " + << (this->PieceInvariant ? "On\n" : "Off\n"); +} + +//-------------------------------------------------------------------------- +unsigned long int vtkCleanPolyData::GetMTime() +{ + unsigned long mTime=this->vtkObject::GetMTime(); + unsigned long time; + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} diff --git a/Graphics/vtkCleanPolyData.h b/Graphics/vtkCleanPolyData.h new file mode 100644 index 0000000..c8dffb8 --- /dev/null +++ b/Graphics/vtkCleanPolyData.h @@ -0,0 +1,175 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCleanPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCleanPolyData - merge duplicate points, and/or remove unused points and/or remove degenerate cells +// .SECTION Description +// vtkCleanPolyData is a filter that takes polygonal data as input and +// generates polygonal data as output. vtkCleanPolyData can merge duplicate +// points (within specified tolerance and if enabled), eliminate points +// that are not used, and if enabled, transform degenerate cells into +// appropriate forms (for example, a triangle is converted into a line +// if two points of triangle are merged). +// +// Conversion of degenerate cells is controlled by the flags +// ConvertLinesToPoints, ConvertPolysToLines, ConvertStripsToPolys which act +// cumulatively such that a degenerate strip may become a poly. +// The full set is +// Line with 1 points -> Vert (if ConvertLinesToPoints) +// Poly with 2 points -> Line (if ConvertPolysToLines) +// Poly with 1 points -> Vert (if ConvertPolysToLines && ConvertLinesToPoints) +// Strp with 3 points -> Poly (if ConvertStripsToPolys) +// Strp with 2 points -> Line (if ConvertStripsToPolys && ConvertPolysToLines) +// Strp with 1 points -> Vert (if ConvertStripsToPolys && ConvertPolysToLines +// && ConvertLinesToPoints) +// +// If tolerance is specified precisely=0.0, then vtkCleanPolyData will use +// the vtkMergePoints object to merge points (which is faster). Otherwise the +// slower vtkPointLocator is used. Before inserting points into the point +// locator, this class calls a function OperateOnPoint which can be used (in +// subclasses) to further refine the cleaning process. See +// vtkQuantizePolyDataPoints. +// +// Note that merging of points can be disabled. In this case, a point locator +// will not be used, and points that are not used by any cells will be +// eliminated, but never merged. + +// .SECTION Caveats +// Merging points can alter topology, including introducing non-manifold +// forms. The tolerance should be chosen carefully to avoid these problems. +// Subclasses should handle OperateOnBounds as well as OperateOnPoint +// to ensure that the locator is correctly initialized (i.e. all modified +// points must lie inside modified bounds). +// +// .SECTION See Also +// vtkQuantizePolyDataPoints + +#ifndef __vtkCleanPolyData_h +#define __vtkCleanPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkCleanPolyData : public vtkPolyDataAlgorithm +{ +public: + static vtkCleanPolyData *New(); + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkCleanPolyData,vtkPolyDataAlgorithm); + + // Description: + // By default ToleranceIsAbsolute is false and Tolerance is + // a fraction of Bounding box diagonal, if true, AbsoluteTolerance is + // used when adding points to locator (merging) + vtkSetMacro(ToleranceIsAbsolute,int); + vtkBooleanMacro(ToleranceIsAbsolute,int); + vtkGetMacro(ToleranceIsAbsolute,int); + + // Description: + // Specify tolerance in terms of fraction of bounding box length. + vtkSetClampMacro(Tolerance,double,0.0,1.0); + vtkGetMacro(Tolerance,double); + + // Description: + // Specify tolerance in absolute terms + vtkSetClampMacro(AbsoluteTolerance,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(AbsoluteTolerance,double); + + // Description: + // Turn on/off conversion of degenerate lines to points + vtkSetMacro(ConvertLinesToPoints,int); + vtkBooleanMacro(ConvertLinesToPoints,int); + vtkGetMacro(ConvertLinesToPoints,int); + + // Description: + // Turn on/off conversion of degenerate polys to lines + vtkSetMacro(ConvertPolysToLines,int); + vtkBooleanMacro(ConvertPolysToLines,int); + vtkGetMacro(ConvertPolysToLines,int); + + // Description: + // Turn on/off conversion of degenerate strips to polys + vtkSetMacro(ConvertStripsToPolys,int); + vtkBooleanMacro(ConvertStripsToPolys,int); + vtkGetMacro(ConvertStripsToPolys,int); + + // Description: + // Set/Get a boolean value that controls whether point merging is + // performed. If on, a locator will be used, and points laying within + // the appropriate tolerance may be merged. If off, points are never + // merged. By default, merging is on. + vtkSetMacro(PointMerging,int); + vtkGetMacro(PointMerging,int); + vtkBooleanMacro(PointMerging,int); + + // Description: + // Set/Get a spatial locator for speeding the search process. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(vtkPolyData *input = 0); + + // Description: + // Release locator + void ReleaseLocator(void); + + // Description: + // Get the MTime of this object also considering the locator. + unsigned long int GetMTime(); + + // Description: + // Perform operation on a point + virtual void OperateOnPoint(double in[3], double out[3]); + + // Description: + // Perform operation on bounds + virtual void OperateOnBounds(double in[6], double out[6]); + + // This filter is difficult to stream. + // To get invariant results, the whole input must be processed at once. + // This flag allows the user to select whether strict piece invariance + // is required. By default it is on. When off, the filter can stream, + // but results may change. + vtkSetMacro(PieceInvariant, int); + vtkGetMacro(PieceInvariant, int); + vtkBooleanMacro(PieceInvariant, int); + +protected: + vtkCleanPolyData(); + ~vtkCleanPolyData(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int PointMerging; + double Tolerance; + double AbsoluteTolerance; + int ConvertLinesToPoints; + int ConvertPolysToLines; + int ConvertStripsToPolys; + int ToleranceIsAbsolute; + vtkPointLocator *Locator; + + int PieceInvariant; +private: + vtkCleanPolyData(const vtkCleanPolyData&); // Not implemented. + void operator=(const vtkCleanPolyData&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkClipDataSet.cxx b/Graphics/vtkClipDataSet.cxx new file mode 100644 index 0000000..832d02a --- /dev/null +++ b/Graphics/vtkClipDataSet.cxx @@ -0,0 +1,498 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkClipDataSet.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkClipDataSet.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkClipVolume.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkGenericCell.h" +#include "vtkImageData.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" + +#include + +vtkCxxRevisionMacro(vtkClipDataSet, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkClipDataSet); +vtkCxxSetObjectMacro(vtkClipDataSet,ClipFunction,vtkImplicitFunction); + +//---------------------------------------------------------------------------- +// Construct with user-specified implicit function; InsideOut turned off; value +// set to 0.0; and generate clip scalars turned off. +vtkClipDataSet::vtkClipDataSet(vtkImplicitFunction *cf) +{ + this->ClipFunction = cf; + this->InsideOut = 0; + this->Locator = NULL; + this->Value = 0.0; + this->GenerateClipScalars = 0; + + this->GenerateClippedOutput = 0; + this->MergeTolerance = 0.01; + + this->SetNumberOfOutputPorts(2); + vtkUnstructuredGrid *output2 = vtkUnstructuredGrid::New(); + this->GetExecutive()->SetOutputData(1, output2); + output2->Delete(); + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//---------------------------------------------------------------------------- +vtkClipDataSet::~vtkClipDataSet() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + this->SetClipFunction(NULL); +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If Clip functions is modified, +// then this object is modified as well. +unsigned long vtkClipDataSet::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->ClipFunction != NULL ) + { + time = this->ClipFunction->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +vtkUnstructuredGrid *vtkClipDataSet::GetClippedOutput() +{ + if (!this->GenerateClippedOutput) + { + return NULL; + } + return vtkUnstructuredGrid::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + +//---------------------------------------------------------------------------- +// +// Clip through data generating surface. +// +int vtkClipDataSet::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkUnstructuredGrid *clippedOutput = this->GetClippedOutput(); + + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + vtkPointData *inPD=input->GetPointData(), *outPD = output->GetPointData(); + vtkCellData *inCD=input->GetCellData(); + vtkCellData *outCD[2]; + vtkPoints *newPoints; + vtkFloatArray *cellScalars; + vtkDataArray *clipScalars; + vtkPoints *cellPts; + vtkIdList *cellIds; + double s; + vtkIdType npts; + vtkIdType *pts; + int cellType = 0; + vtkIdType i; + int j; + vtkIdType estimatedSize; + vtkUnsignedCharArray *types[2]; + types[0] = types[1] = 0; + vtkIdTypeArray *locs[2]; + locs[0] = locs[1] = 0; + int numOutputs = 1; + + vtkDebugMacro(<< "Clipping dataset"); + + int inputObjectType = input->GetDataObjectType(); + + // if we have volumes + if (inputObjectType == VTK_STRUCTURED_POINTS || + inputObjectType == VTK_IMAGE_DATA) + { + int dimension; + int *dims = vtkImageData::SafeDownCast(input)->GetDimensions(); + for (dimension=3, i=0; i<3; i++) + { + if ( dims[i] <= 1 ) + { + dimension--; + } + } + if ( dimension >= 3 ) + { + this->ClipVolume(input, output); + return 1; + } + } + + // Initialize self; create output objects + // + if ( numPts < 1 ) + { + vtkDebugMacro(<<"No data to clip"); + return 1; + } + + if ( !this->ClipFunction && this->GenerateClipScalars ) + { + vtkErrorMacro(<<"Cannot generate clip scalars if no clip function defined"); + return 1; + } + + // allocate the output and associated helper classes + estimatedSize = numCells; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + cellScalars = vtkFloatArray::New(); + cellScalars->Allocate(VTK_CELL_SIZE); + vtkCellArray *conn[2]; + conn[0] = conn[1] = 0; + conn[0] = vtkCellArray::New(); + conn[0]->Allocate(estimatedSize,estimatedSize/2); + conn[0]->InitTraversal(); + types[0] = vtkUnsignedCharArray::New(); + types[0]->Allocate(estimatedSize,estimatedSize/2); + locs[0] = vtkIdTypeArray::New(); + locs[0]->Allocate(estimatedSize,estimatedSize/2); + if ( this->GenerateClippedOutput ) + { + numOutputs = 2; + conn[1] = vtkCellArray::New(); + conn[1]->Allocate(estimatedSize,estimatedSize/2); + conn[1]->InitTraversal(); + types[1] = vtkUnsignedCharArray::New(); + types[1]->Allocate(estimatedSize,estimatedSize/2); + locs[1] = vtkIdTypeArray::New(); + locs[1]->Allocate(estimatedSize,estimatedSize/2); + } + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts,numPts/2); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPoints, input->GetBounds()); + + // Determine whether we're clipping with input scalars or a clip function + // and do necessary setup. + if ( this->ClipFunction ) + { + vtkFloatArray *tmpScalars = vtkFloatArray::New(); + tmpScalars->SetNumberOfTuples(numPts); + tmpScalars->SetName("ClipDataSetScalars"); + inPD = vtkPointData::New(); + inPD->ShallowCopy(input->GetPointData());//copies original + if ( this->GenerateClipScalars ) + { + inPD->SetScalars(tmpScalars); + } + for ( i=0; i < numPts; i++ ) + { + s = this->ClipFunction->FunctionValue(input->GetPoint(i)); + tmpScalars->SetTuple1(i,s); + } + clipScalars = tmpScalars; + } + else //using input scalars + { + clipScalars = this->GetInputArrayToProcess(0,inputVector); + if ( !clipScalars ) + { + for ( i=0; i<2; i++ ) + { + if (conn[i]) + { + conn[i]->Delete(); + } + if (types[i]) + { + types[i]->Delete(); + } + if (locs[i]) + { + locs[i]->Delete(); + } + } + cellScalars->Delete(); + newPoints->Delete(); + vtkErrorMacro(<<"Cannot clip without clip function or input scalars"); + return 1; + } + } + + if ( !this->GenerateClipScalars && !this->GetInputArrayToProcess(0,inputVector)) + { + outPD->CopyScalarsOff(); + } + else + { + outPD->CopyScalarsOn(); + } + outPD->InterpolateAllocate(inPD,estimatedSize,estimatedSize/2); + outCD[0] = output->GetCellData(); + outCD[0]->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + if ( this->GenerateClippedOutput ) + { + outCD[1] = clippedOutput->GetCellData(); + outCD[1]->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + } + + //Process all cells and clip each in turn + // + int abort=0; + vtkIdType updateTime = numCells/20 + 1; // update roughly every 5% + vtkGenericCell *cell = vtkGenericCell::New(); + int num[2]; num[0]=num[1]=0; + int numNew[2]; numNew[0]=numNew[1]=0; + for (vtkIdType cellId=0; cellId < numCells && !abort; cellId++) + { + if ( !(cellId % updateTime) ) + { + this->UpdateProgress((double)cellId / numCells); + abort = this->GetAbortExecute(); + } + + input->GetCell(cellId,cell); + cellPts = cell->GetPoints(); + cellIds = cell->GetPointIds(); + npts = cellPts->GetNumberOfPoints(); + + // evaluate implicit cutting function + for ( i=0; i < npts; i++ ) + { + s = clipScalars->GetComponent(cellIds->GetId(i), 0); + cellScalars->InsertTuple(i, &s); + } + + // perform the clipping + cell->Clip(this->Value, cellScalars, this->Locator, conn[0], + inPD, outPD, inCD, cellId, outCD[0], this->InsideOut); + numNew[0] = conn[0]->GetNumberOfCells() - num[0]; + num[0] = conn[0]->GetNumberOfCells(); + + if ( this->GenerateClippedOutput ) + { + cell->Clip(this->Value, cellScalars, this->Locator, conn[1], + inPD, outPD, inCD, cellId, outCD[1], !this->InsideOut); + numNew[1] = conn[1]->GetNumberOfCells() - num[1]; + num[1] = conn[1]->GetNumberOfCells(); + } + + for (i=0; iInsertNextValue(conn[i]->GetTraversalLocation()); + conn[i]->GetNextCell(npts,pts); + + //For each new cell added, got to set the type of the cell + switch ( cell->GetCellDimension() ) + { + case 0: //points are generated-------------------------------- + cellType = (npts > 1 ? VTK_POLY_VERTEX : VTK_VERTEX); + break; + + case 1: //lines are generated--------------------------------- + cellType = (npts > 2 ? VTK_POLY_LINE : VTK_LINE); + break; + + case 2: //polygons are generated------------------------------ + cellType = (npts == 3 ? VTK_TRIANGLE : + (npts == 4 ? VTK_QUAD : VTK_POLYGON)); + break; + + case 3: //tetrahedra or wedges are generated------------------ + cellType = (npts == 4 ? VTK_TETRA : VTK_WEDGE); + break; + } //switch + + types[i]->InsertNextValue(cellType); + } //for each new cell + } //for both outputs + } //for each cell + + cell->Delete(); + cellScalars->Delete(); + + if ( this->ClipFunction ) + { + clipScalars->Delete(); + inPD->Delete(); + } + + output->SetPoints(newPoints); + output->SetCells(types[0], locs[0], conn[0]); + conn[0]->Delete(); + types[0]->Delete(); + locs[0]->Delete(); + + if ( this->GenerateClippedOutput ) + { + clippedOutput->SetPoints(newPoints); + clippedOutput->SetCells(types[1], locs[1], conn[1]); + conn[1]->Delete(); + types[1]->Delete(); + locs[1]->Delete(); + } + + newPoints->Delete(); + this->Locator->Initialize();//release any extra memory + output->Squeeze(); + + return 1; +} + +//---------------------------------------------------------------------------- +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkClipDataSet::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator) + { + return; + } + + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + if ( locator ) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkClipDataSet::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkClipDataSet::ClipVolume(vtkDataSet *input, vtkUnstructuredGrid *output) +{ + vtkClipVolume *clipVolume = vtkClipVolume::New(); + + // We cannot set the input directly. This messes up the partitioning. + // output->UpdateNumberOfPieces gets set to 1. + vtkImageData* tmp = vtkImageData::New(); + tmp->ShallowCopy(vtkImageData::SafeDownCast(input)); + + clipVolume->SetInput(tmp); + clipVolume->SetValue(this->Value); + clipVolume->SetInsideOut(this->InsideOut); + clipVolume->SetClipFunction(this->ClipFunction); + clipVolume->SetGenerateClipScalars(this->GenerateClipScalars); + clipVolume->SetGenerateClippedOutput(this->GenerateClippedOutput); + clipVolume->SetMergeTolerance(this->MergeTolerance); + clipVolume->SetDebug(this->Debug); + clipVolume->Update(); + vtkUnstructuredGrid *clipOutput = clipVolume->GetOutput(); + + output->CopyStructure(clipOutput); + output->GetPointData()->ShallowCopy(clipOutput->GetPointData()); + output->GetCellData()->ShallowCopy(clipOutput->GetCellData()); + clipVolume->Delete(); + tmp->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkClipDataSet::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkClipDataSet::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Merge Tolerance: " << this->MergeTolerance << "\n"; + if ( this->ClipFunction ) + { + os << indent << "Clip Function: " << this->ClipFunction << "\n"; + } + else + { + os << indent << "Clip Function: (none)\n"; + } + os << indent << "InsideOut: " << (this->InsideOut ? "On\n" : "Off\n"); + os << indent << "Value: " << this->Value << "\n"; + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + os << indent << "Generate Clip Scalars: " + << (this->GenerateClipScalars ? "On\n" : "Off\n"); + + os << indent << "Generate Clipped Output: " + << (this->GenerateClippedOutput ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkClipDataSet.h b/Graphics/vtkClipDataSet.h new file mode 100644 index 0000000..1dbc629 --- /dev/null +++ b/Graphics/vtkClipDataSet.h @@ -0,0 +1,169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkClipDataSet.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkClipDataSet - clip any dataset with user-specified implicit function or input scalar data +// .SECTION Description +// vtkClipDataSet is a filter that clips any type of dataset using either +// any subclass of vtkImplicitFunction, or the input scalar +// data. Clipping means that it actually "cuts" through the cells of +// the dataset, returning everything inside of the specified implicit +// function (or greater than the scalar value) including "pieces" of +// a cell. (Compare this with vtkExtractGeometry, which pulls out +// entire, uncut cells.) The output of this filter is an unstructured +// grid. +// +// To use this filter, you must decide if you will be clipping with an +// implicit function, or whether you will be using the input scalar +// data. If you want to clip with an implicit function, you must: +// 1) define an implicit function +// 2) set it with the SetClipFunction method +// 3) apply the GenerateClipScalarsOn method +// If a ClipFunction is not specified, or GenerateClipScalars is off +// (the default), then the input's scalar data will be used to clip +// the polydata. +// +// You can also specify a scalar value, which is used to decide what is +// inside and outside of the implicit function. You can also reverse the +// sense of what inside/outside is by setting the InsideOut instance +// variable. (The clipping algorithm proceeds by computing an implicit +// function value or using the input scalar data for each point in the +// dataset. This is compared to the scalar value to determine +// inside/outside.) +// +// This filter can be configured to compute a second output. The +// second output is the part of the cell that is clipped away. Set the +// GenerateClippedData boolean on if you wish to access this output data. + +// .SECTION Caveats +// vtkClipDataSet will triangulate all types of 3D cells (i.e., create +// tetrahedra). This is true even if the cell is not actually cut. This +// is necessary to preserve compatibility across face neighbors. 2D cells +// will only be triangulated if the cutting function passes through them. + +// .SECTION See Also +// vtkImplicitFunction vtkCutter vtkClipVolume vtkClipPolyData + +#ifndef __vtkClipDataSet_h +#define __vtkClipDataSet_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkImplicitFunction; + +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkClipDataSet : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkClipDataSet,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with user-specified implicit function; InsideOut turned off; + // value set to 0.0; and generate clip scalars turned off. + static vtkClipDataSet *New(); + + // Description: + // Set the clipping value of the implicit function (if clipping with + // implicit function) or scalar value (if clipping with + // scalars). The default value is 0.0. + vtkSetMacro(Value,double); + vtkGetMacro(Value,double); + + // Description: + // Set/Get the InsideOut flag. When off, a vertex is considered + // inside the implicit function if its value is greater than the + // Value ivar. When InsideOutside is turned on, a vertex is + // considered inside the implicit function if its implicit function + // value is less than or equal to the Value ivar. InsideOut is off + // by default. + vtkSetMacro(InsideOut,int); + vtkGetMacro(InsideOut,int); + vtkBooleanMacro(InsideOut,int); + + // Description + // Specify the implicit function with which to perform the + // clipping. If you do not define an implicit function, + // then the selected input scalar data will be used for clipping. + virtual void SetClipFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ClipFunction,vtkImplicitFunction); + + // Description: + // If this flag is enabled, then the output scalar values will be + // interpolated from the implicit function values, and not the + // input scalar data. If you enable this flag but do not provide an + // implicit function an error will be reported. + vtkSetMacro(GenerateClipScalars,int); + vtkGetMacro(GenerateClipScalars,int); + vtkBooleanMacro(GenerateClipScalars,int); + + // Description: + // Control whether a second output is generated. The second output + // contains the polygonal data that's been clipped away. + vtkSetMacro(GenerateClippedOutput,int); + vtkGetMacro(GenerateClippedOutput,int); + vtkBooleanMacro(GenerateClippedOutput,int); + + // Description: + // Set the tolerance for merging clip intersection points that are near + // the vertices of cells. This tolerance is used to prevent the generation + // of degenerate primitives. Note that only 3D cells actually use this + // instance variable. + vtkSetClampMacro(MergeTolerance,double,0.0001,0.25); + vtkGetMacro(MergeTolerance,double); + + // Description: + // Return the Clipped output. + vtkUnstructuredGrid *GetClippedOutput(); + + // Description: + // Specify a spatial locator for merging points. By default, an + // instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. The + // locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // Return the mtime also considering the locator and clip function. + unsigned long GetMTime(); + +protected: + vtkClipDataSet(vtkImplicitFunction *cf=NULL); + ~vtkClipDataSet(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + vtkImplicitFunction *ClipFunction; + + vtkPointLocator *Locator; + int InsideOut; + double Value; + int GenerateClipScalars; + + int GenerateClippedOutput; + double MergeTolerance; + + //helper functions + void ClipVolume(vtkDataSet *input, vtkUnstructuredGrid *output); + +private: + vtkClipDataSet(const vtkClipDataSet&); // Not implemented. + void operator=(const vtkClipDataSet&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkClipPolyData.cxx b/Graphics/vtkClipPolyData.cxx new file mode 100644 index 0000000..cd81bd7 --- /dev/null +++ b/Graphics/vtkClipPolyData.cxx @@ -0,0 +1,427 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkClipPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkClipPolyData.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkGenericCell.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkTriangle.h" + +#include + +vtkCxxRevisionMacro(vtkClipPolyData, "$Revision: 1.56.10.1 $"); +vtkStandardNewMacro(vtkClipPolyData); +vtkCxxSetObjectMacro(vtkClipPolyData,ClipFunction,vtkImplicitFunction); + +//---------------------------------------------------------------------------- +// Construct with user-specified implicit function; InsideOut turned off; value +// set to 0.0; and generate clip scalars turned off. +vtkClipPolyData::vtkClipPolyData(vtkImplicitFunction *cf) +{ + this->ClipFunction = cf; + this->InsideOut = 0; + this->Locator = NULL; + this->Value = 0.0; + this->GenerateClipScalars = 0; + + this->SetNumberOfOutputPorts(2); + + this->GenerateClippedOutput = 0; + vtkPolyData *output2 = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(1, output2); + output2->Delete(); +} + +//---------------------------------------------------------------------------- +vtkClipPolyData::~vtkClipPolyData() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + this->SetClipFunction(NULL); +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If Clip functions is modified, +// then this object is modified as well. +unsigned long vtkClipPolyData::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->ClipFunction != NULL ) + { + time = this->ClipFunction->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +vtkPolyData *vtkClipPolyData::GetClippedOutput() +{ + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + + +//---------------------------------------------------------------------------- +// +// Clip through data generating surface. +// +int vtkClipPolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, i, updateTime; + vtkPoints *cellPts; + vtkDataArray *clipScalars; + vtkFloatArray *cellScalars; + vtkGenericCell *cell; + vtkCellArray *newVerts, *newLines, *newPolys, *connList=NULL; + vtkCellArray *clippedVerts=NULL, *clippedLines=NULL; + vtkCellArray *clippedPolys=NULL, *clippedList=NULL; + vtkPoints *newPoints; + vtkIdList *cellIds; + double s; + vtkIdType estimatedSize, numCells=input->GetNumberOfCells(); + vtkIdType numPts=input->GetNumberOfPoints(); + vtkPoints *inPts=input->GetPoints(); + int numberOfPoints; + vtkPointData *inPD=input->GetPointData(), *outPD = output->GetPointData(); + vtkCellData *inCD=input->GetCellData(), *outCD = output->GetCellData(); + vtkCellData *outClippedCD = NULL; + + vtkDebugMacro(<< "Clipping polygonal data"); + + // Initialize self; create output objects + // + if ( numPts < 1 || inPts == NULL ) + { + vtkDebugMacro(<<"No data to clip"); + return 1; + } + + if ( !this->ClipFunction && this->GenerateClipScalars ) + { + vtkErrorMacro(<<"Cannot generate clip scalars if no clip function defined"); + return 1; + } + + // Create objects to hold output of clip operation + // + estimatedSize = numCells; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts,numPts/2); + newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize,estimatedSize/2); + newLines = vtkCellArray::New(); + newLines->Allocate(estimatedSize,estimatedSize/2); + newPolys = vtkCellArray::New(); + newPolys->Allocate(estimatedSize,estimatedSize/2); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPoints, input->GetBounds()); + + // Determine whether we're clipping with input scalars or a clip function + // and to necessary setup. + if ( this->ClipFunction ) + { + vtkFloatArray *tmpScalars = vtkFloatArray::New(); + tmpScalars->SetNumberOfTuples(numPts); + inPD = vtkPointData::New(); + inPD->ShallowCopy(input->GetPointData());//copies original + if ( this->GenerateClipScalars ) + { + inPD->SetScalars(tmpScalars); + } + for ( i=0; i < numPts; i++ ) + { + s = this->ClipFunction->FunctionValue(inPts->GetPoint(i)); + tmpScalars->SetComponent(i,0,s); + } + clipScalars = tmpScalars; + } + else //using input scalars + { + clipScalars = inPD->GetScalars(); + if ( !clipScalars ) + { + vtkErrorMacro(<<"Cannot clip without clip function or input scalars"); + return 1; + } + } + + if ( !this->GenerateClipScalars && !input->GetPointData()->GetScalars()) + { + outPD->CopyScalarsOff(); + } + else + { + outPD->CopyScalarsOn(); + } + outPD->InterpolateAllocate(inPD,estimatedSize,estimatedSize/2); + outCD->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + + // If generating second output, setup clipped output + if ( this->GenerateClippedOutput ) + { + this->GetClippedOutput()->Initialize(); + outClippedCD = this->GetClippedOutput()->GetCellData(); + outClippedCD->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + clippedVerts = vtkCellArray::New(); + clippedVerts->Allocate(estimatedSize,estimatedSize/2); + clippedLines = vtkCellArray::New(); + clippedLines->Allocate(estimatedSize,estimatedSize/2); + clippedPolys = vtkCellArray::New(); + clippedPolys->Allocate(estimatedSize,estimatedSize/2); + } + + cellScalars = vtkFloatArray::New(); + cellScalars->Allocate(VTK_CELL_SIZE); + + // perform clipping on cells + int abort=0; + updateTime = numCells/20 + 1; // update roughly every 5% + cell = vtkGenericCell::New(); + for (cellId=0; cellId < numCells && !abort; cellId++) + { + input->GetCell(cellId,cell); + cellPts = cell->GetPoints(); + cellIds = cell->GetPointIds(); + numberOfPoints = cellPts->GetNumberOfPoints(); + + // evaluate implicit cutting function + for ( i=0; i < numberOfPoints; i++ ) + { + s = clipScalars->GetComponent(cellIds->GetId(i),0); + cellScalars->InsertTuple(i, &s); + } + + switch ( cell->GetCellDimension() ) + { + case 0: //points are generated------------------------------- + connList = newVerts; + clippedList = clippedVerts; + break; + + case 1: //lines are generated---------------------------------- + connList = newLines; + clippedList = clippedLines; + break; + + case 2: //triangles are generated------------------------------ + connList = newPolys; + clippedList = clippedPolys; + break; + + } //switch + + cell->Clip(this->Value, cellScalars, this->Locator, connList, + inPD, outPD, inCD, cellId, outCD, this->InsideOut); + + if ( this->GenerateClippedOutput ) + { + cell->Clip(this->Value, cellScalars, this->Locator, clippedList, + inPD, outPD, inCD, cellId, outClippedCD, !this->InsideOut); + } + + if ( !(cellId % updateTime) ) + { + this->UpdateProgress((double)cellId / numCells); + abort = this->GetAbortExecute(); + } + } //for each cell + cell->Delete(); + + vtkDebugMacro(<<"Created: " + << newPoints->GetNumberOfPoints() << " points, " + << newVerts->GetNumberOfCells() << " verts, " + << newLines->GetNumberOfCells() << " lines, " + << newPolys->GetNumberOfCells() << " polys"); + + if ( this->GenerateClippedOutput ) + { + vtkDebugMacro(<<"Created (clipped output): " + << clippedVerts->GetNumberOfCells() << " verts, " + << clippedLines->GetNumberOfCells() << " lines, " + << clippedPolys->GetNumberOfCells() << " triangles"); + } + + // Update ourselves. Because we don't know upfront how many verts, lines, + // polys we've created, take care to reclaim memory. + // + if ( this->ClipFunction ) + { + clipScalars->Delete(); + inPD->Delete(); + } + + if (newVerts->GetNumberOfCells()) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if (newLines->GetNumberOfCells()) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if (newPolys->GetNumberOfCells()) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + if ( this->GenerateClippedOutput ) + { + this->GetClippedOutput()->SetPoints(newPoints); + + if (clippedVerts->GetNumberOfCells()) + { + this->GetClippedOutput()->SetVerts(clippedVerts); + } + clippedVerts->Delete(); + + if (clippedLines->GetNumberOfCells()) + { + this->GetClippedOutput()->SetLines(clippedLines); + } + clippedLines->Delete(); + + if (clippedPolys->GetNumberOfCells()) + { + this->GetClippedOutput()->SetPolys(clippedPolys); + } + clippedPolys->Delete(); + + this->GetClippedOutput()->GetPointData()->PassData(outPD); + this->GetClippedOutput()->Squeeze(); + } + + output->SetPoints(newPoints); + newPoints->Delete(); + cellScalars->Delete(); + + this->Locator->Initialize();//release any extra memory + output->Squeeze(); + + return 1; +} + + +//---------------------------------------------------------------------------- +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkClipPolyData::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator) + { + return; + } + + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + if ( locator ) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkClipPolyData::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + + +//---------------------------------------------------------------------------- +void vtkClipPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->ClipFunction ) + { + os << indent << "Clip Function: " << this->ClipFunction << "\n"; + } + else + { + os << indent << "Clip Function: (none)\n"; + } + os << indent << "InsideOut: " << (this->InsideOut ? "On\n" : "Off\n"); + os << indent << "Value: " << this->Value << "\n"; + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + os << indent << "Generate Clip Scalars: " << (this->GenerateClipScalars ? "On\n" : "Off\n"); + + os << indent << "Generate Clipped Output: " << (this->GenerateClippedOutput ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkClipPolyData.h b/Graphics/vtkClipPolyData.h new file mode 100644 index 0000000..f556748 --- /dev/null +++ b/Graphics/vtkClipPolyData.h @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkClipPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkClipPolyData - clip polygonal data with user-specified implicit function or input scalar data +// .SECTION Description +// vtkClipPolyData is a filter that clips polygonal data using either +// any subclass of vtkImplicitFunction, or the input scalar +// data. Clipping means that it actually "cuts" through the cells of +// the dataset, returning everything inside of the specified implicit +// function (or greater than the scalar value) including "pieces" of +// a cell. (Compare this with vtkExtractGeometry, which pulls out +// entire, uncut cells.) The output of this filter is polygonal data. +// +// To use this filter, you must decide if you will be clipping with an +// implicit function, or whether you will be using the input scalar +// data. If you want to clip with an implicit function, you must: +// 1) define an implicit function +// 2) set it with the SetClipFunction method +// 3) apply the GenerateClipScalarsOn method +// If a ClipFunction is not specified, or GenerateClipScalars is off +// (the default), then the input's scalar data will be used to clip +// the polydata. +// +// You can also specify a scalar value, which is used to +// decide what is inside and outside of the implicit function. You can +// also reverse the sense of what inside/outside is by setting the +// InsideOut instance variable. (The cutting algorithm proceeds by +// computing an implicit function value or using the input scalar data +// for each point in the dataset. This is compared to the scalar value +// to determine inside/outside.) +// +// This filter can be configured to compute a second output. The +// second output is the polygonal data that is clipped away. Set the +// GenerateClippedData boolean on if you wish to access this output data. + +// .SECTION Caveats +// In order to cut all types of cells in polygonal data, vtkClipPolyData +// triangulates some cells, and then cuts the resulting simplices +// (i.e., points, lines, and triangles). This means that the resulting +// output may consist of different cell types than the input data. + +// .SECTION See Also +// vtkImplicitFunction vtkCutter vtkClipVolume + +#ifndef __vtkClipPolyData_h +#define __vtkClipPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkImplicitFunction; +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkClipPolyData : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkClipPolyData,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with user-specified implicit function; InsideOut turned off; + // value set to 0.0; and generate clip scalars turned off. + static vtkClipPolyData *New(); + + // Description: + // Set the clipping value of the implicit function (if clipping with + // implicit function) or scalar value (if clipping with + // scalars). The default value is 0.0. + vtkSetMacro(Value,double); + vtkGetMacro(Value,double); + + // Description: + // Set/Get the InsideOut flag. When off, a vertex is considered + // inside the implicit function if its value is greater than the + // Value ivar. When InsideOutside is turned on, a vertex is + // considered inside the implicit function if its implicit function + // value is less than or equal to the Value ivar. InsideOut is off + // by default. + vtkSetMacro(InsideOut,int); + vtkGetMacro(InsideOut,int); + vtkBooleanMacro(InsideOut,int); + + // Description + // Specify the implicit function with which to perform the + // clipping. If you do not define an implicit function, then the input + // scalar data will be used for clipping. + virtual void SetClipFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ClipFunction,vtkImplicitFunction); + + // Description: + // If this flag is enabled, then the output scalar values will be + // interpolated from the implicit function values, and not the + // input scalar data. If you enable this flag but do not provide an + // implicit function an error will be reported. + vtkSetMacro(GenerateClipScalars,int); + vtkGetMacro(GenerateClipScalars,int); + vtkBooleanMacro(GenerateClipScalars,int); + + // Description: + // Control whether a second output is generated. The second output + // contains the polygonal data that's been clipped away. + vtkSetMacro(GenerateClippedOutput,int); + vtkGetMacro(GenerateClippedOutput,int); + vtkBooleanMacro(GenerateClippedOutput,int); + + // Description: + // Return the Clipped output. + vtkPolyData *GetClippedOutput(); + + // Description: + // Return the output port (a vtkAlgorithmOutput) of the clipped output. + vtkAlgorithmOutput* GetClippedOutputPort() + { + return this->GetOutputPort(1); + } + + // Description: + // Specify a spatial locator for merging points. By default, an + // instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. The + // locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // Return the mtime also considering the locator and clip function. + unsigned long GetMTime(); + +protected: + vtkClipPolyData(vtkImplicitFunction *cf=NULL); + ~vtkClipPolyData(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + vtkImplicitFunction *ClipFunction; + + vtkPointLocator *Locator; + int InsideOut; + double Value; + int GenerateClipScalars; + + int GenerateClippedOutput; +private: + vtkClipPolyData(const vtkClipPolyData&); // Not implemented. + void operator=(const vtkClipPolyData&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkClipVolume.cxx b/Graphics/vtkClipVolume.cxx new file mode 100644 index 0000000..1f3ce39 --- /dev/null +++ b/Graphics/vtkClipVolume.cxx @@ -0,0 +1,723 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkClipVolume.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkClipVolume.h" + +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkGarbageCollector.h" +#include "vtkImageData.h" +#include "vtkImplicitFunction.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkExecutive.h" +#include "vtkObjectFactory.h" +#include "vtkOrderedTriangulator.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" +#include "vtkVoxel.h" +#include "vtkGenericCell.h" +#include "vtkTetra.h" +#include "vtkCellArray.h" +#include "vtkIdTypeArray.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkClipVolume, "$Revision: 1.71 $"); +vtkStandardNewMacro(vtkClipVolume); +vtkCxxSetObjectMacro(vtkClipVolume,ClipFunction,vtkImplicitFunction); + +// Construct with user-specified implicit function; InsideOut turned off; value +// set to 0.0; and generate clip scalars turned off. The merge tolerance is set +// to 0.01. +vtkClipVolume::vtkClipVolume(vtkImplicitFunction *cf) +{ + this->ClipFunction = cf; + this->InsideOut = 0; + this->Locator = NULL; + this->Value = 0.0; + this->GenerateClipScalars = 0; + this->Mixed3DCellGeneration = 1; + + this->GenerateClippedOutput = 0; + this->MergeTolerance = 0.01; + + this->Triangulator = vtkOrderedTriangulator::New(); + this->Triangulator->PreSortedOn(); + + // optional clipped output + this->SetNumberOfOutputPorts(2); + vtkUnstructuredGrid *output2 = vtkUnstructuredGrid::New(); + this->GetExecutive()->SetOutputData(1, output2); + output2->Delete(); +} + +vtkClipVolume::~vtkClipVolume() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + this->Triangulator->Delete(); + this->SetClipFunction(NULL); +} + +vtkUnstructuredGrid *vtkClipVolume::GetClippedOutput() +{ + return vtkUnstructuredGrid::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + +// Overload standard modified time function. If Clip functions is modified, +// then this object is modified as well. +unsigned long vtkClipVolume::GetMTime() +{ + unsigned long mTime, time; + + mTime=this->Superclass::GetMTime(); + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->ClipFunction != NULL ) + { + time = this->ClipFunction->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +// +// Clip through volume generating tetrahedra +// +int vtkClipVolume::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkUnstructuredGrid *clippedOutput = this->GetClippedOutput(); + vtkCellArray *outputConn; + vtkIdTypeArray *outputLoc; + vtkUnsignedCharArray *outputTypes; + vtkIdType cellId, newCellId, i; + int j, k, flip; + vtkPoints *cellPts; + vtkDataArray *clipScalars; + vtkFloatArray *cellScalars; + vtkPoints *newPoints; + vtkIdList *cellIds; + double value, s, x[3], origin[3], spacing[3]; + vtkIdType estimatedSize, numCells=input->GetNumberOfCells(); + vtkIdType numPts=input->GetNumberOfPoints(); + vtkPointData *inPD=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *inCD=input->GetCellData(), *outCD=output->GetCellData(); + vtkCellData *clippedCD=clippedOutput->GetCellData(); + vtkCellData *outputCD; + int dims[3], dimension, numICells, numJCells, numKCells, sliceSize; + int extOffset; + int above, below; + vtkIdList *tetraIds; + vtkPoints *tetraPts; + int ii, jj, id, ntetra; + vtkIdType pts[4], npts, *dpts, *outputCount; + + vtkDebugMacro(<< "Clipping volume"); + + // Initialize self; create output objects + // + input->GetDimensions(dims); + input->GetOrigin(origin); + input->GetSpacing(spacing); + + extOffset = + input->GetExtent()[0] + input->GetExtent()[2] + input->GetExtent()[4]; + + for (dimension=3, i=0; i<3; i++) + { + if ( dims[i] <= 1 ) + { + dimension--; + } + } + if ( dimension < 3 ) + { + vtkErrorMacro("This filter only clips 3D volume data"); + return 1; + } + + if ( !this->ClipFunction && this->GenerateClipScalars ) + { + vtkErrorMacro(<<"Cannot generate clip scalars without clip function"); + return 1; + } + + // Create objects to hold output of clip operation + // + estimatedSize = numCells; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPoints = vtkPoints::New(); + newPoints->Allocate(estimatedSize/2,estimatedSize/2); + this->NumberOfCells = 0; + this->Connectivity = vtkCellArray::New(); + this->Connectivity->Allocate(estimatedSize*2); //allocate storage for cells + this->Locations = vtkIdTypeArray::New(); + this->Locations->Allocate(estimatedSize); + this->Types = vtkUnsignedCharArray::New(); + this->Types->Allocate(estimatedSize); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPoints, input->GetBounds()); + + // Determine whether we're clipping with input scalars or a clip function + // and do necessary setup. + if ( this->ClipFunction ) + { + vtkFloatArray *tmpScalars = vtkFloatArray::New(); + tmpScalars->Allocate(numPts); + inPD = vtkPointData::New(); + inPD->ShallowCopy(input->GetPointData()); + if ( this->GenerateClipScalars ) + { + inPD->SetScalars(tmpScalars); + } + for ( i=0; i < numPts; i++ ) + { + s = this->ClipFunction->FunctionValue(input->GetPoint(i)); + tmpScalars->InsertTuple(i,&s); + } + clipScalars = tmpScalars; + } + else //using input scalars + { + clipScalars = inPD->GetScalars(); + if ( !clipScalars ) + { + vtkErrorMacro(<<"Cannot clip without clip function or input scalars"); + return 1; + } + } + + if ( !this->GenerateClipScalars && !input->GetPointData()->GetScalars()) + { + outPD->CopyScalarsOff(); + } + else + { + outPD->CopyScalarsOn(); + } + outPD->InterpolateAllocate(inPD,estimatedSize,estimatedSize/2); + outCD->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + clippedCD->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + + // If generating second output, setup clipped output + if ( this->GenerateClippedOutput ) + { + this->NumberOfClippedCells = 0; + this->ClippedConnectivity = vtkCellArray::New(); + this->ClippedConnectivity->Allocate(estimatedSize); //storage for cells + this->ClippedLocations = vtkIdTypeArray::New(); + this->ClippedLocations->Allocate(estimatedSize); + this->ClippedTypes = vtkUnsignedCharArray::New(); + this->ClippedTypes->Allocate(estimatedSize); + } + + // perform clipping on voxels - compute approriate numbers + value = this->Value; + numICells = dims[0] - 1; + numJCells = dims[1] - 1; + numKCells = dims[2] - 1; + sliceSize = numICells * numJCells; + + tetraIds = vtkIdList::New(); tetraIds->Allocate(20); + cellScalars = vtkFloatArray::New(); cellScalars->Allocate(8); + tetraPts = vtkPoints::New(); tetraPts->Allocate(20); + vtkGenericCell *cell=vtkGenericCell::New(); + vtkTetra *clipTetra = vtkTetra::New(); + + // Interior voxels (i.e., inside the clip region) are tetrahedralized using + // 5 tetrahedra. This requires swapping the face diagonals on alternating + // voxels to insure compatibility. Loop over i-j-k directions so that we + // can control the direction of face diagonals on voxels (i.e., the flip + // variable). The flip variable also controls the generation of tetrahedra + // in boundary voxels in ClipTets() and the ordered Delaunay triangulation + // used in ClipVoxel(). + int abort=0; + for ( k=0; k < numKCells && !abort; k++) + { + // Check for progress and abort on every z-slice + this->UpdateProgress((double)k / numKCells); + abort = this->GetAbortExecute(); + for ( j=0; j < numJCells; j++) + { + for ( i=0; i < numICells; i++ ) + { + flip = (extOffset+i+j+k) & 0x1; + cellId = i + j*numICells + k*sliceSize; + + input->GetCell(cellId,cell); + if ( cell->GetCellType() == VTK_EMPTY_CELL ) + { + continue; + } + cellPts = cell->GetPoints(); + cellIds = cell->GetPointIds(); + + // gather scalar values for the cell and keep + for ( above=below=0, ii=0; ii < 8; ii++ ) + { + s = clipScalars->GetComponent(cellIds->GetId(ii),0); + cellScalars->SetComponent(ii, 0, s); + if ( s >= value ) + { + above = 1; + } + else if ( s < value ) + { + below = 1; + } + } + + // take into account inside/out flag + if ( this->InsideOut ) + { + above = !above; + below = !below; + } + + // See whether voxel is fully inside or outside and triangulate + // according to the flup variable. + if ( (above && !below) || + (this->GenerateClippedOutput && (below && !above)) ) + { + cell->Triangulate(flip, tetraIds, tetraPts); + ntetra = tetraPts->GetNumberOfPoints() / 4; + + if (above && !below) + { + outputConn = this->Connectivity; + outputLoc = this->Locations; + outputTypes = this->Types; + outputCount = &this->NumberOfCells; + outputCD = outCD; + } + else + { + outputConn = this->ClippedConnectivity; + outputLoc = this->ClippedLocations; + outputTypes = this->ClippedTypes; + outputCount = &this->NumberOfClippedCells; + outputCD = clippedCD; + } + + for (ii=0; iiGetPoint(id+jj, x); + if ( this->Locator->InsertUniquePoint(x, pts[jj]) ) + { + outPD->CopyData(inPD,tetraIds->GetId(id+jj),pts[jj]); + } + } + newCellId = outputConn->InsertNextCell(4,pts); + (*outputCount)++; + outputLoc->InsertNextValue(outputConn->GetTraversalLocation()); + outputConn->GetNextCell(npts,dpts); //updates traversal location + outputTypes->InsertNextValue( VTK_TETRA ); + outputCD->CopyData(inCD,cellId,newCellId); + }//for each tetra produced by triangulation + } + + else if (above == below ) // clipped voxel, have to triangulate + { + if ( this->Mixed3DCellGeneration ) //use vtkTetra clipping templates + { + cell->Triangulate(flip, tetraIds, tetraPts); + this->ClipTets(value, clipTetra, clipScalars, cellScalars, + tetraIds, tetraPts, inPD, outPD, + inCD, cellId, outCD, clippedCD, this->InsideOut); + } + else //use vtkOrderedTriangulator to produce tetrahedra + { + this->ClipVoxel(value, cellScalars, flip, origin, spacing, + cellIds, cellPts, inPD, outPD, + inCD, cellId, outCD, clippedCD); + } + } // using ordered triangulator + }// for i + }// for j + }// for k + + // Create the output + output->SetPoints(newPoints); + output->SetCells(this->Types,this->Locations,this->Connectivity); + this->Types->Delete(); + this->Locations->Delete(); + this->Connectivity->Delete(); + output->Squeeze(); + vtkDebugMacro(<<"Created: " + << newPoints->GetNumberOfPoints() << " points, " + << output->GetNumberOfCells() << " tetra" ); + + if ( this->GenerateClippedOutput ) + { + clippedOutput->SetPoints(newPoints); + clippedOutput->SetCells(this->ClippedTypes,this->ClippedLocations, + this->ClippedConnectivity); + this->ClippedTypes->Delete(); + this->ClippedLocations->Delete(); + this->ClippedConnectivity->Delete(); + clippedOutput->GetPointData()->PassData(outPD); + clippedOutput->Squeeze(); + vtkDebugMacro(<<"Created (clipped output): " + << clippedOutput->GetNumberOfCells() << " tetra"); + } + + // Update ourselves. Because we don't know upfront how many cells + // we've created, take care to reclaim memory. + // + if ( this->ClipFunction ) + { + clipScalars->Delete(); + inPD->Delete(); + } + + // Clean up + newPoints->Delete(); + cell->Delete(); + tetraIds->Delete(); + tetraPts->Delete(); + cellScalars->Delete(); + clipTetra->Delete(); + + this->Locator->Initialize();//release any extra memory + + return 1; +} + + +// Method to triangulate and clip voxel using vtkTetra::Clip() method. +// This produces a mixed mesh of tetrahedra and wedges but it is faster +// than using the ordered triangulator. It works by using the usual +// alternating five tetrahedra template per voxel, and then using the +// vtkTetra::Clip() method to produce the output. +// +void vtkClipVolume::ClipTets(double value, vtkTetra *clipTetra, + vtkDataArray *clipScalars, + vtkDataArray *cellScalars, vtkIdList *tetraIds, + vtkPoints *tetraPts, vtkPointData *inPD, + vtkPointData *outPD, vtkCellData *inCD, + vtkIdType cellId, vtkCellData *outCD, + vtkCellData *clippedCD, int insideOut) +{ + // Tessellate this cell as if it were inside + vtkIdType ntetra = tetraPts->GetNumberOfPoints() / 4; + int i, id, j, k, numNew; + vtkIdType npts=0, *pts; + + // Clip each tetrahedron + for (i=0; iPointIds->SetId(j,tetraIds->GetId(id+j)); + clipTetra->Points->SetPoint(j,tetraPts->GetPoint(id+j)); + cellScalars-> + SetComponent(j,0,clipScalars->GetComponent(tetraIds->GetId(id+j),0)); + } + clipTetra->Clip(value, cellScalars, this->Locator, this->Connectivity, + inPD, outPD, inCD, cellId, outCD, insideOut); + numNew = this->Connectivity->GetNumberOfCells() - this->NumberOfCells; + this->NumberOfCells = this->Connectivity->GetNumberOfCells(); + for (k=0; kLocations-> + InsertNextValue(this->Connectivity->GetTraversalLocation()); + this->Connectivity->GetNextCell(npts,pts); + this->Types->InsertNextValue((npts==4?VTK_TETRA:VTK_WEDGE)); + } + + if ( this->GenerateClippedOutput ) + { + clipTetra->Clip(value, cellScalars, this->Locator, + this->ClippedConnectivity, inPD, outPD, + inCD, cellId, clippedCD, !insideOut); + numNew = this->ClippedConnectivity->GetNumberOfCells() - + this->NumberOfClippedCells; + this->NumberOfClippedCells = + this->ClippedConnectivity->GetNumberOfCells(); + for (k=0; kClippedLocations->InsertNextValue( + this->ClippedConnectivity->GetTraversalLocation() ); + this->ClippedConnectivity->GetNextCell(npts,pts); + this->ClippedTypes->InsertNextValue((npts==4?VTK_TETRA:VTK_WEDGE)); + } + } + } +} + +// Method to triangulate and clip voxel using ordered Delaunay +// triangulation to produce tetrahedra. Voxel is initially triangulated +// using 8 voxel corner points inserted in order (to control direction +// of face diagonals). Then edge intersection points are injected into the +// triangulation. The ordering controls the orientation of any face +// diagonals. +void vtkClipVolume::ClipVoxel(double value, vtkDataArray *cellScalars, + int flip, double vtkNotUsed(origin)[3], + double spacing[3], vtkIdList *cellIds, + vtkPoints *cellPts, vtkPointData *inPD, + vtkPointData *outPD, vtkCellData *inCD, + vtkIdType cellId, vtkCellData *outCD, + vtkCellData *clippedCD) +{ + double x[3], s1, s2, t, voxelOrigin[3]; + double bounds[6], p1[3], p2[3]; + int i, k, edgeNum, numPts, numNew; + vtkIdType id, ptId, npts, *pts; + static int edges[12][2] = { {0,1}, {2,3}, {4,5}, {6,7}, + {0,2}, {1,3}, {4,6}, {5,7}, + {0,4}, {1,5}, {2,6}, {3,7}}; + static int order[2][8] = { {0,3,5,6,1,2,4,7}, + {1,2,4,7,0,3,5,6}};//injection order based on flip + + // compute bounds for voxel and initialize + cellPts->GetPoint(0,voxelOrigin); + for (i=0; i<3; i++) + { + bounds[2*i] = voxelOrigin[i]; + bounds[2*i+1] = voxelOrigin[i] + spacing[i]; + } + + // Initialize Delaunay insertion process with voxel triangulation. + // No more than 20 points (8 corners + 12 edges) may be inserted. + this->Triangulator->InitTriangulation(bounds,20); + + // Inject ordered voxel corner points into triangulation. Recall + // that the PreSortedOn() flag was set in the triangulator. + int type; + vtkIdType internalId[8]; //used to merge points if nearby edge intersection + for (numPts=0; numPts<8; numPts++) + { + ptId = order[flip][numPts]; + + // Currently all points are injected because of the possibility + // of intersection point merging. + s1 = cellScalars->GetComponent(ptId,0); + if ( (s1 >= value && !this->InsideOut) || (s1 < value && this->InsideOut) ) + { + type = 0; //inside + } + else + { + //type 1 is "outside"; type 4 is don't insert + type = (this->GenerateClippedOutput ? 1 : 4); + } + + cellPts->GetPoint(ptId, x); + if ( this->Locator->InsertUniquePoint(x, id) ) + { + outPD->CopyData(inPD, cellIds->GetId(ptId), id); + } + internalId[ptId] = this->Triangulator->InsertPoint(id, x, x, type); + }//for eight voxel corner points + + // For each edge intersection point, insert into triangulation. Edge + // intersections come from clipping value. Have to be careful of + // intersections near exisiting points (causes bad Delaunay behavior). + for (edgeNum=0; edgeNum < 12; edgeNum++) + { + s1 = cellScalars->GetComponent(edges[edgeNum][0],0); + s2 = cellScalars->GetComponent(edges[edgeNum][1],0); + + if ( (s1 < value && s2 >= value) || (s1 >= value && s2 < value) ) + { + + t = (value - s1) / (s2 - s1); + + // Check to see whether near the intersection is near a voxel corner. + // If so,have to merge requiring a change of type to type=boundary. + if ( t < this->MergeTolerance ) + { + this->Triangulator->UpdatePointType(internalId[edges[edgeNum][0]], 2); + continue; + } + else if (t > (1.0 - this->MergeTolerance) ) + { + this->Triangulator->UpdatePointType(internalId[edges[edgeNum][1]], 2); + continue; + } + + // generate edge intersection point + cellPts->GetPoint(edges[edgeNum][0],p1); + cellPts->GetPoint(edges[edgeNum][1],p2); + for (i=0; i<3; i++) + { + x[i] = p1[i] + t * (p2[i] - p1[i]); + } + + // Incorporate point into output and interpolate edge data as necessary + if ( this->Locator->InsertUniquePoint(x, ptId) ) + { + outPD->InterpolateEdge(inPD, ptId, cellIds->GetId(edges[edgeNum][0]), + cellIds->GetId(edges[edgeNum][1]), t); + } + + //Insert into Delaunay triangulation + this->Triangulator->InsertPoint(ptId,x,x,2); + + }//if edge intersects value + }//for all edges + + // triangulate the points + this->Triangulator->Triangulate(); + + // Add the triangulation to the mesh + vtkIdType newCellId; + this->Triangulator->AddTetras(0,this->Connectivity); + numNew = this->Connectivity->GetNumberOfCells() - this->NumberOfCells; + this->NumberOfCells = this->Connectivity->GetNumberOfCells(); + for (k=0; kLocations-> + InsertNextValue(this->Connectivity->GetTraversalLocation()); + this->Connectivity->GetNextCell(npts,pts); //updates traversal location + this->Types->InsertNextValue(VTK_TETRA); + outCD->CopyData(inCD,cellId,newCellId); + } + + if ( this->GenerateClippedOutput ) + { + this->Triangulator->AddTetras(1,this->ClippedConnectivity); + numNew = this->ClippedConnectivity->GetNumberOfCells() - + this->NumberOfClippedCells; + this->NumberOfClippedCells = this->ClippedConnectivity->GetNumberOfCells(); + for (k=0; kClippedLocations-> + InsertNextValue(this->ClippedConnectivity->GetTraversalLocation()); + this->ClippedConnectivity->GetNextCell(npts,pts); + this->ClippedTypes->InsertNextValue(VTK_TETRA); + clippedCD->CopyData(inCD,cellId,newCellId); + } + } +} + + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkClipVolume::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + if (locator) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +void vtkClipVolume::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +int vtkClipVolume::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkClipVolume::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->ClipFunction ) + { + os << indent << "Clip Function: " << this->ClipFunction << "\n"; + } + else + { + os << indent << "Clip Function: (none)\n"; + } + os << indent << "InsideOut: " << (this->InsideOut ? "On\n" : "Off\n"); + os << indent << "Value: " << this->Value << "\n"; + os << indent << "Merge Tolerance: " << this->MergeTolerance << "\n"; + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + os << indent << "Generate Clip Scalars: " + << (this->GenerateClipScalars ? "On\n" : "Off\n"); + + os << indent << "Generate Clipped Output: " + << (this->GenerateClippedOutput ? "On\n" : "Off\n"); + + os << indent << "Mixed 3D Cell Type: " + << (this->Mixed3DCellGeneration ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +void vtkClipVolume::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->ClipFunction, "ClipFunction"); +} diff --git a/Graphics/vtkClipVolume.h b/Graphics/vtkClipVolume.h new file mode 100644 index 0000000..97f0629 --- /dev/null +++ b/Graphics/vtkClipVolume.h @@ -0,0 +1,213 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkClipVolume.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkClipVolume - clip volume data with user-specified implicit function or input scalar data +// .SECTION Description +// vtkClipVolume is a filter that clips volume data (i.e., vtkImageData) +// using either: any subclass of vtkImplicitFunction or the input scalar +// data. The clipping operation cuts through the cells of the +// dataset--converting 3D image data into a 3D unstructured grid--returning +// everything inside of the specified implicit function (or greater than the +// scalar value). During the clipping the filter will produce pieces of a +// cell. (Compare this with vtkExtractGeometry or vtkGeometryFilter, which +// produces entire, uncut cells.) The output of this filter is a 3D +// unstructured grid (e.g., tetrahedra or other 3D cell types). +// +// To use this filter, you must decide if you will be clipping with an +// implicit function, or whether you will be using the input scalar data. If +// you want to clip with an implicit function, you must first define and then +// set the implicit function with the SetClipFunction() method. Otherwise, +// you must make sure input scalar data is available. You can also specify a +// scalar value, which is used to decide what is inside and outside of the +// implicit function. You can also reverse the sense of what inside/outside +// is by setting the InsideOut instance variable. (The cutting algorithm +// proceeds by computing an implicit function value or using the input scalar +// data for each point in the dataset. This is compared to the scalar value +// to determine inside/outside.) +// +// This filter can be configured to compute a second output. The +// second output is the portion of the volume that is clipped away. Set the +// GenerateClippedData boolean on if you wish to access this output data. +// +// The filter will produce an unstructured grid of entirely tetrahedra or a +// mixed grid of tetrahedra and other 3D cell types (e.g., wedges). Control +// this behavior by setting the Mixed3DCellGeneration. By default the +// Mixed3DCellGeneration is on and a combination of cell types will be +// produced. Note that producing mixed cell types is a faster than producing +// only tetrahedra. + +// .SECTION Caveats +// This filter is designed to function with 3D structured points. Clipping +// 2D images should be done by converting the image to polygonal data +// and using vtkClipPolyData, + +// .SECTION See Also +// vtkImplicitFunction vtkClipPolyData vtkGeometryFilter vtkExtractGeometry + +#ifndef __vtkClipVolume_h +#define __vtkClipVolume_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkCellData; +class vtkDataArray; +class vtkIdList; +class vtkImplicitFunction; +class vtkMergePoints; +class vtkOrderedTriangulator; +class vtkPointData; +class vtkPointLocator; +class vtkPoints; +class vtkUnstructuredGrid; +class vtkCell; +class vtkTetra; +class vtkCellArray; +class vtkIdTypeArray; +class vtkUnsignedCharArray; + +class VTK_GRAPHICS_EXPORT vtkClipVolume : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkClipVolume,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with user-specified implicit function; InsideOut turned off; + // value set to 0.0; and generate clip scalars turned off. + static vtkClipVolume *New(); + + // Description: + // Set the clipping value of the implicit function (if clipping with + // implicit function) or scalar value (if clipping with scalars). The + // default value is 0.0. + vtkSetMacro(Value,double); + vtkGetMacro(Value,double); + + // Description: + // Set/Get the InsideOut flag. When off, a vertex is considered inside the + // implicit function if its value is greater than the Value ivar. When + // InsideOutside is turned on, a vertex is considered inside the implicit + // function if its implicit function value is less than or equal to the + // Value ivar. InsideOut is off by default. + vtkSetMacro(InsideOut,int); + vtkGetMacro(InsideOut,int); + vtkBooleanMacro(InsideOut,int); + + // Description + // Specify the implicit function with which to perform the clipping. If you + // do not define an implicit function, then the input scalar data will be + // used for clipping. + virtual void SetClipFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ClipFunction,vtkImplicitFunction); + + // Description: + // If this flag is enabled, then the output scalar values will be + // interpolated from the implicit function values, and not the + // input scalar data. If you enable this flag but do not provide an + // implicit function an error will be reported. + vtkSetMacro(GenerateClipScalars,int); + vtkGetMacro(GenerateClipScalars,int); + vtkBooleanMacro(GenerateClipScalars,int); + + // Description: + // Control whether a second output is generated. The second output + // contains the unstructured grid that's been clipped away. + vtkSetMacro(GenerateClippedOutput,int); + vtkGetMacro(GenerateClippedOutput,int); + vtkBooleanMacro(GenerateClippedOutput,int); + + // Description: + // Return the clipped output. + vtkUnstructuredGrid *GetClippedOutput(); + + // Description: + // Control whether the filter produces a mix of 3D cell types on output, or + // whether the output cells are all tetrahedra. By default, a mixed set of + // cells (e.g., tetrahedra and wedges) is produced. (Note: mixed type + // generation is faster and less overall data is generated.) + vtkSetMacro(Mixed3DCellGeneration,int); + vtkGetMacro(Mixed3DCellGeneration,int); + vtkBooleanMacro(Mixed3DCellGeneration,int); + + // Description: + // Set the tolerance for merging clip intersection points that are near + // the corners of voxels. This tolerance is used to prevent the generation + // of degenerate tetrahedra. + vtkSetClampMacro(MergeTolerance,double,0.0001,0.25); + vtkGetMacro(MergeTolerance,double); + + // Description: + // Set / Get a spatial locator for merging points. By default, + // an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. The + // locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // Return the mtime also considering the locator and clip function. + unsigned long int GetMTime(); + +protected: + vtkClipVolume(vtkImplicitFunction *cf=NULL); + ~vtkClipVolume(); + + virtual void ReportReferences(vtkGarbageCollector*); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + void ClipTets(double value, vtkTetra *clipTetra, vtkDataArray *clipScalars, + vtkDataArray *cellScalars, vtkIdList *tetraIds, + vtkPoints *tetraPts, vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData *outCD, + vtkCellData *clippedCD, int insideOut); + void ClipVoxel(double value, vtkDataArray *cellScalars, int flip, + double origin[3], double spacing[3], vtkIdList *cellIds, + vtkPoints *cellPts, vtkPointData *inPD, vtkPointData *outPD, + vtkCellData *inCD, vtkIdType cellId, vtkCellData *outCD, + vtkCellData *clippedCD); + + vtkImplicitFunction *ClipFunction; + vtkPointLocator *Locator; + int InsideOut; + double Value; + int GenerateClipScalars; + double MergeTolerance; + int Mixed3DCellGeneration; + int GenerateClippedOutput; + vtkUnstructuredGrid *ClippedOutput; + +private: + vtkOrderedTriangulator *Triangulator; + + // Used temporarily to pass data around + vtkIdType NumberOfCells; + vtkCellArray *Connectivity; + vtkUnsignedCharArray *Types; + vtkIdTypeArray *Locations; + vtkIdType NumberOfClippedCells; + vtkCellArray *ClippedConnectivity; + vtkUnsignedCharArray *ClippedTypes; + vtkIdTypeArray *ClippedLocations; + +private: + vtkClipVolume(const vtkClipVolume&); // Not implemented. + void operator=(const vtkClipVolume&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkConeSource.cxx b/Graphics/vtkConeSource.cxx new file mode 100644 index 0000000..213a3ba --- /dev/null +++ b/Graphics/vtkConeSource.cxx @@ -0,0 +1,329 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkConeSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkConeSource.h" + +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" +#include "vtkCellArray.h" + +#include + +vtkCxxRevisionMacro(vtkConeSource, "$Revision: 1.73 $"); +vtkStandardNewMacro(vtkConeSource); + +//---------------------------------------------------------------------------- +// Construct with default resolution 6, height 1.0, radius 0.5, and capping +// on. +vtkConeSource::vtkConeSource(int res) +{ + res = (res < 0 ? 0 : res); + this->Resolution = res; + this->Height = 1.0; + this->Radius = 0.5; + this->Capping = 1; + + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; + + this->Direction[0] = 1.0; + this->Direction[1] = 0.0; + this->Direction[2] = 0.0; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +int vtkConeSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + double angle; + int numLines, numPolys, numPts; + double x[3], xbot; + int i; + vtkIdType pts[VTK_CELL_SIZE]; + vtkPoints *newPoints; + vtkCellArray *newLines=0; + vtkCellArray *newPolys=0; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + // for streaming + int piece; + int numPieces; + int maxPieces; + int start, end; + int createBottom; + + piece = output->GetUpdatePiece(); + if (piece >= this->Resolution && !(piece == 0 && this->Resolution == 0)) + { + return 1; + } + numPieces = output->GetUpdateNumberOfPieces(); + maxPieces = this->Resolution != 0 ? this->Resolution : 1; + if (numPieces > maxPieces) + { + numPieces = maxPieces; + } + if (piece >= maxPieces) + { + // Super class should do this for us, + // but I put this condition in any way. + return 1; + } + start = maxPieces * piece / numPieces; + end = (maxPieces * (piece+1) / numPieces) - 1; + createBottom = (this->Capping && (start == 0)); + + vtkDebugMacro("ConeSource Executing"); + + if ( this->Resolution ) + { + angle = 2.0*3.141592654/this->Resolution; + } + else + { + angle = 0.0; + } + + // Set things up; allocate memory + // + switch ( this->Resolution ) + { + case 0: + numPts = 2; + numLines = 1; + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(numLines,numPts)); + break; + + case 1: case 2: + numPts = 2*this->Resolution + 1; + numPolys = this->Resolution; + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys,3)); + break; + + default: + if (createBottom) + { + // piece 0 has cap. + numPts = this->Resolution + 1; + numPolys = end - start + 2; + } + else + { + numPts = end - start + 3; + numPolys = end - start + 2; + } + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys,this->Resolution)); + break; + } + newPoints = vtkPoints::New(); + newPoints->SetDataTypeToFloat(); //used later during transformation + newPoints->Allocate(numPts); + + // Create cone + // + x[0] = this->Height / 2.0; // zero-centered + x[1] = 0.0; + x[2] = 0.0; + pts[0] = newPoints->InsertNextPoint(x); + + xbot = -this->Height / 2.0; + + switch (this->Resolution) + { + case 0: + x[0] = xbot; + x[1] = 0.0; + x[2] = 0.0; + pts[1] = newPoints->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + break; + + case 2: // fall through this case to use the code in case 1 + x[0] = xbot; + x[1] = 0.0; + x[2] = -this->Radius; + pts[1] = newPoints->InsertNextPoint(x); + x[0] = xbot; + x[1] = 0.0; + x[2] = this->Radius; + pts[2] = newPoints->InsertNextPoint(x); + newPolys->InsertNextCell(3,pts); + + case 1: + x[0] = xbot; + x[1] = -this->Radius; + x[2] = 0.0; + pts[1] = newPoints->InsertNextPoint(x); + x[0] = xbot; + x[1] = this->Radius; + x[2] = 0.0; + pts[2] = newPoints->InsertNextPoint(x); + newPolys->InsertNextCell(3,pts); + break; + + default: // General case: create Resolution triangles and single cap + // create the bottom. + if ( createBottom ) + { + for (i=0; i < this->Resolution; i++) + { + x[0] = xbot; + x[1] = this->Radius * cos ((double)i*angle); + x[2] = this->Radius * sin ((double)i*angle); + // Reverse the order + pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x); + } + newPolys->InsertNextCell(this->Resolution,pts); + } + + pts[0] = 0; + if ( ! createBottom) + { + // we need to create the points also + x[0] = xbot; + x[1] = this->Radius * cos ((double)start*angle); + x[2] = this->Radius * sin ((double)start*angle); + pts[1] = newPoints->InsertNextPoint(x); + for (i = start; i <= end; ++i) + { + x[1] = this->Radius * cos ((double)(i+1)*angle); + x[2] = this->Radius * sin ((double)(i+1)*angle); + pts[2] = newPoints->InsertNextPoint(x); + newPolys->InsertNextCell(3,pts); + pts[1] = pts[2]; + } + } + else + { + // bottom and points have already been created. + for (i=start; i <= end; i++) + { + pts[1] = i+1; + pts[2] = i+2; + if (pts[2] > this->Resolution) + { + pts[2] = 1; + } + newPolys->InsertNextCell(3,pts); + } + } // createBottom + + } //switch + + // A non-default origin and/or direction requires transformation + // + if ( this->Center[0] != 0.0 || this->Center[1] != 0.0 || + this->Center[2] != 0.0 || this->Direction[0] != 1.0 || + this->Direction[1] != 0.0 || this->Direction[2] != 0.0 ) + { + vtkTransform *t = vtkTransform::New(); + t->Translate(this->Center[0], this->Center[1], this->Center[2]); + double vMag = vtkMath::Norm(this->Direction); + if ( this->Direction[0] < 0.0 && + this->Direction[1] == 0.0 && + this->Direction[2] == 0.0 ) + { + // just flip x + t->RotateWXYZ(180.0,0,1,0); + } + else + { + t->RotateWXYZ((double)180.0, (this->Direction[0]+vMag)/2.0, + this->Direction[1]/2.0, this->Direction[2]/2.0); + } + float *ipts = ((vtkFloatArray *)newPoints->GetData())->GetPointer(0); + for (i=0; iTransformPoint(ipts,ipts); + } + + t->Delete(); + } + + // Update ourselves + // + output->SetPoints(newPoints); + newPoints->Delete(); + + if ( newPolys ) + { + newPolys->Squeeze(); // we may have estimated size; reclaim some space + output->SetPolys(newPolys); + newPolys->Delete(); + } + else + { + output->SetLines(newLines); + newLines->Delete(); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkConeSource::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkConeSource::SetAngle(double angle) +{ + this->SetRadius (this->Height * tan ((double) angle*vtkMath::DegreesToRadians())); +} + +//---------------------------------------------------------------------------- +double vtkConeSource::GetAngle() +{ + return atan2 (this->Radius, this->Height) / vtkMath::DegreesToRadians(); +} + +//---------------------------------------------------------------------------- +void vtkConeSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Resolution: " << this->Resolution << "\n"; + os << indent << "Height: " << this->Height << "\n"; + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << ")\n"; + os << indent << "Direction: (" << this->Direction[0] << ", " + << this->Direction[1] << ", " << this->Direction[2] << ")\n"; +} diff --git a/Graphics/vtkConeSource.h b/Graphics/vtkConeSource.h new file mode 100644 index 0000000..1de9ca2 --- /dev/null +++ b/Graphics/vtkConeSource.h @@ -0,0 +1,107 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkConeSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkConeSource - generate polygonal cone +// .SECTION Description +// vtkConeSource creates a cone centered at a specified point and pointing in +// a specified direction. (By default, the center is the origin and the +// direction is the x-axis.) Depending upon the resolution of this object, +// different representations are created. If resolution=0 a line is created; +// if resolution=1, a single triangle is created; if resolution=2, two +// crossed triangles are created. For resolution > 2, a 3D cone (with +// resolution number of sides) is created. It also is possible to control +// whether the bottom of the cone is capped with a (resolution-sided) +// polygon, and to specify the height and radius of the cone. + +#ifndef __vtkConeSource_h +#define __vtkConeSource_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkCell.h" // Needed for VTK_CELL_SIZE + +class VTK_GRAPHICS_EXPORT vtkConeSource : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkConeSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with default resolution 6, height 1.0, radius 0.5, and + // capping on. The cone is centered at the origin and points down + // the x-axis. + static vtkConeSource *New(); + + // Description: + // Set the height of the cone. This is the height along the cone in + // its specified direction. + vtkSetClampMacro(Height,double,0.0,VTK_DOUBLE_MAX) + vtkGetMacro(Height,double); + + // Description: + // Set the base radius of the cone. + vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX) + vtkGetMacro(Radius,double); + + // Description: + // Set the number of facets used to represent the cone. + vtkSetClampMacro(Resolution,int,0,VTK_CELL_SIZE) + vtkGetMacro(Resolution,int); + + // Description: + // Set the center of the cone. The default is 0,0,0. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set the orientation vector of the cone. The vector does not have + // to be normalized. The cone will point in the Direction specified. + // The default is (1,0,0). + vtkSetVector3Macro(Direction,double); + vtkGetVectorMacro(Direction,double,3); + + // Description: + // Set the angle of the cone. As a side effect, the angle plus height sets + // the base radius of the cone. + void SetAngle (double angle); + double GetAngle (); + + // Description: + // Turn on/off whether to cap the base of the cone with a polygon. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + +protected: + vtkConeSource(int res=6); + ~vtkConeSource() {} + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Height; + double Radius; + int Resolution; + int Capping; + double Center[3]; + double Direction[3]; + +private: + vtkConeSource(const vtkConeSource&); // Not implemented. + void operator=(const vtkConeSource&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkConnectivityFilter.cxx b/Graphics/vtkConnectivityFilter.cxx new file mode 100644 index 0000000..689b90b --- /dev/null +++ b/Graphics/vtkConnectivityFilter.cxx @@ -0,0 +1,526 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkConnectivityFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkConnectivityFilter.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkConnectivityFilter, "$Revision: 1.72 $"); +vtkStandardNewMacro(vtkConnectivityFilter); + +// Construct with default extraction mode to extract largest regions. +vtkConnectivityFilter::vtkConnectivityFilter() +{ + this->RegionSizes = vtkIntArray::New(); + this->ExtractionMode = VTK_EXTRACT_LARGEST_REGION; + this->ColorRegions = 0; + + this->ScalarConnectivity = 0; + this->ScalarRange[0] = 0.0; + this->ScalarRange[1] = 1.0; + + this->ClosestPoint[0] = this->ClosestPoint[1] = this->ClosestPoint[2] = 0.0; + + this->CellScalars = vtkFloatArray::New(); + this->CellScalars->Allocate(8); + + this->NeighborCellPointIds = vtkIdList::New(); + this->NeighborCellPointIds->Allocate(8); + + this->Seeds = vtkIdList::New(); + this->SpecifiedRegionIds = vtkIdList::New(); +} + +vtkConnectivityFilter::~vtkConnectivityFilter() +{ + this->RegionSizes->Delete(); + this->CellScalars->Delete(); + this->NeighborCellPointIds->Delete(); + this->Seeds->Delete(); + this->SpecifiedRegionIds->Delete(); +} + +int vtkConnectivityFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells, cellId, newCellId, i, j, pt; + vtkPoints *newPts; + int id; + int maxCellsInRegion; + int largestRegionId = 0; + vtkPointData *pd=input->GetPointData(), *outputPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outputCD=output->GetCellData(); + + vtkDebugMacro(<<"Executing connectivity filter."); + + // Check input/allocate storage + // + numCells=input->GetNumberOfCells(); + if ( (numPts=input->GetNumberOfPoints()) < 1 || numCells < 1 ) + { + vtkDebugMacro(<<"No data to connect!"); + return 1; + } + output->Allocate(numCells,numCells); + + // See whether to consider scalar connectivity + // + this->InScalars = input->GetPointData()->GetScalars(); + if ( !this->ScalarConnectivity ) + { + this->InScalars = NULL; + } + else + { + if ( this->ScalarRange[1] < this->ScalarRange[0] ) + { + this->ScalarRange[1] = this->ScalarRange[0]; + } + } + + // Initialize. Keep track of points and cells visited. + // + this->RegionSizes->Reset(); + this->Visited = new vtkIdType[numCells]; + for ( i=0; i < numCells; i++ ) + { + this->Visited[i] = -1; + } + this->PointMap = new vtkIdType[numPts]; + for ( i=0; i < numPts; i++ ) + { + this->PointMap[i] = -1; + } + + this->NewScalars = vtkFloatArray::New(); + this->NewScalars->SetNumberOfTuples(numPts); + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + + // Traverse all cells marking those visited. Each new search + // starts a new connected region. Connected region grows + // using a connected wave propagation. + // + this->Wave = vtkIdList::New(); + this->Wave->Allocate(numPts/4+1,numPts); + this->Wave2 = vtkIdList::New(); + this->Wave2->Allocate(numPts/4+1,numPts); + + this->PointNumber = 0; + this->RegionNumber = 0; + maxCellsInRegion = 0; + + this->CellIds = vtkIdList::New(); + this->CellIds->Allocate(8, VTK_CELL_SIZE); + this->PointIds = vtkIdList::New(); + this->PointIds->Allocate(8, VTK_CELL_SIZE); + + if ( this->ExtractionMode != VTK_EXTRACT_POINT_SEEDED_REGIONS && + this->ExtractionMode != VTK_EXTRACT_CELL_SEEDED_REGIONS && + this->ExtractionMode != VTK_EXTRACT_CLOSEST_POINT_REGION ) + { //visit all cells marking with region number + for (cellId=0; cellId < numCells; cellId++) + { + if ( cellId && !(cellId % 5000) ) + { + this->UpdateProgress (0.1 + 0.8*cellId/numCells); + } + + if ( this->Visited[cellId] < 0 ) + { + this->NumCellsInRegion = 0; + this->Wave->InsertNextId(cellId); + this->TraverseAndMark (input); + + if ( this->NumCellsInRegion > maxCellsInRegion ) + { + maxCellsInRegion = this->NumCellsInRegion; + largestRegionId = this->RegionNumber; + } + + this->RegionSizes->InsertValue(this->RegionNumber++, + this->NumCellsInRegion); + this->Wave->Reset(); + this->Wave2->Reset(); + } + } + } + else // regions have been seeded, everything considered in same region + { + this->NumCellsInRegion = 0; + + if ( this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS ) + { + for (i=0; i < this->Seeds->GetNumberOfIds(); i++) + { + pt = this->Seeds->GetId(i); + if ( pt >= 0 ) + { + input->GetPointCells(pt,this->CellIds); + for (j=0; j < this->CellIds->GetNumberOfIds(); j++) + { + this->Wave->InsertNextId(this->CellIds->GetId(j)); + } + } + } + } + else if ( this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS ) + { + for (i=0; i < this->Seeds->GetNumberOfIds(); i++) + { + cellId = this->Seeds->GetId(i); + if ( cellId >= 0 ) + { + this->Wave->InsertNextId(cellId); + } + } + } + else if ( this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION ) + {//loop over points, find closest one + double minDist2, dist2, x[3]; + vtkIdType minId = 0; + for (minDist2=VTK_DOUBLE_MAX, i=0; iGetPoint(i,x); + dist2 = vtkMath::Distance2BetweenPoints(x,this->ClosestPoint); + if ( dist2 < minDist2 ) + { + minId = i; + minDist2 = dist2; + } + } + input->GetPointCells(minId,this->CellIds); + for (j=0; j < this->CellIds->GetNumberOfIds(); j++) + { + this->Wave->InsertNextId(this->CellIds->GetId(j)); + } + } + this->UpdateProgress (0.5); + + //mark all seeded regions + this->TraverseAndMark (input); + this->RegionSizes->InsertValue(this->RegionNumber,this->NumCellsInRegion); + this->UpdateProgress (0.9); + } + + vtkDebugMacro (<<"Extracted " << this->RegionNumber << " region(s)"); + this->Wave->Delete(); + this->Wave2->Delete(); + + // Now that points and cells have been marked, traverse these lists pulling + // everything that has been visited. + // + //Pass through point data that has been visited + outputPD->CopyAllocate(pd); + outputCD->CopyAllocate(cd); + + for (i=0; i < numPts; i++) + { + if ( this->PointMap[i] > -1 ) + { + newPts->InsertPoint(this->PointMap[i],input->GetPoint(i)); + outputPD->CopyData(pd,i,this->PointMap[i]); + } + } + + // if coloring regions; send down new scalar data + if ( this->ColorRegions ) + { + int idx = outputPD->AddArray(this->NewScalars); + outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + } + this->NewScalars->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + + // Create output cells + // + if ( this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS || + this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS || + this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION || + this->ExtractionMode == VTK_EXTRACT_ALL_REGIONS) + { // extract any cell that's been visited + for (cellId=0; cellId < numCells; cellId++) + { + if ( this->Visited[cellId] >= 0 ) + { + input->GetCellPoints(cellId, this->PointIds); + for (i=0; i < this->PointIds->GetNumberOfIds(); i++) + { + id = this->PointMap[this->PointIds->GetId(i)]; + this->PointIds->InsertId(i,id); + } + newCellId = output->InsertNextCell(input->GetCellType(cellId), + this->PointIds); + outputCD->CopyData(cd,cellId,newCellId); + } + } + } + else if ( this->ExtractionMode == VTK_EXTRACT_SPECIFIED_REGIONS ) + { + for (cellId=0; cellId < numCells; cellId++) + { + int inReg, regionId; + if ( (regionId=this->Visited[cellId]) >= 0 ) + { + for (inReg=0,i=0; iSpecifiedRegionIds->GetNumberOfIds(); i++) + { + if ( regionId == this->SpecifiedRegionIds->GetId(i) ) + { + inReg = 1; + break; + } + } + if ( inReg ) + { + input->GetCellPoints(cellId, this->PointIds); + for (i=0; i < this->PointIds->GetNumberOfIds(); i++) + { + id = this->PointMap[this->PointIds->GetId(i)]; + this->PointIds->InsertId(i,id); + } + newCellId =output->InsertNextCell(input->GetCellType(cellId), + this->PointIds); + outputCD->CopyData(cd,cellId,newCellId); + } + } + } + } + else //extract largest region + { + for (cellId=0; cellId < numCells; cellId++) + { + if ( this->Visited[cellId] == largestRegionId ) + { + input->GetCellPoints(cellId, this->PointIds); + for (i=0; i < this->PointIds->GetNumberOfIds(); i++) + { + id = this->PointMap[this->PointIds->GetId(i)]; + this->PointIds->InsertId(i,id); + } + newCellId = output->InsertNextCell(input->GetCellType(cellId), + this->PointIds); + outputCD->CopyData(cd,cellId,newCellId); + } + } + } + + delete [] this->Visited; + delete [] this->PointMap; + this->PointIds->Delete(); + this->CellIds->Delete(); + output->Squeeze(); + vtkDataArray* outScalars = 0; + if (this->ColorRegions && (outScalars=output->GetPointData()->GetScalars())) + { + outScalars->Resize(output->GetNumberOfPoints()); + } + + int num = this->GetNumberOfExtractedRegions(); + int count = 0; + + for (int ii = 0; ii < num; ii++) + { + count += this->RegionSizes->GetValue (ii); + } + vtkDebugMacro (<< "Total # of cells accounted for: " << count); + vtkDebugMacro (<< "Extracted " << output->GetNumberOfCells() << " cells"); + + return 1; +} + + +// Mark current cell as visited and assign region number. Note: +// traversal occurs across shared vertices. +// +void vtkConnectivityFilter::TraverseAndMark (vtkDataSet *input) +{ + int i, j, k, cellId, numIds, ptId, numPts, numCells; + vtkIdList *tmpWave; + + while ( (numIds=this->Wave->GetNumberOfIds()) > 0 ) + { + for ( i=0; i < numIds; i++ ) + { + cellId = this->Wave->GetId(i); + if ( this->Visited[cellId] < 0 ) + { + this->Visited[cellId] = this->RegionNumber; + this->NumCellsInRegion++; + input->GetCellPoints(cellId, this->PointIds); + + numPts = this->PointIds->GetNumberOfIds(); + for (j=0; j < numPts; j++) + { + if ( this->PointMap[ptId=this->PointIds->GetId(j)] < 0 ) + { + this->PointMap[ptId] = this->PointNumber++; + this->NewScalars->SetComponent(this->PointMap[ptId], 0, + this->RegionNumber); + } + + input->GetPointCells(ptId,this->CellIds); + + // check connectivity criterion (geometric + scalar) + numCells = this->CellIds->GetNumberOfIds(); + for (k=0; k < numCells; k++) + { + cellId = this->CellIds->GetId(k); + if ( this->InScalars ) + { + int numScalars, ii; + double s, range[2]; + + input->GetCellPoints(cellId, this->NeighborCellPointIds); + numScalars = this->NeighborCellPointIds->GetNumberOfIds(); + this->CellScalars->SetNumberOfComponents(this->InScalars->GetNumberOfComponents()); + this->CellScalars->SetNumberOfTuples(numScalars); + this->InScalars->GetTuples(this->NeighborCellPointIds, + this->CellScalars); + range[0] = VTK_DOUBLE_MAX; range[1] = -VTK_DOUBLE_MAX; + for (ii=0; ii < numScalars; ii++) + { + s = this->CellScalars->GetComponent(ii,0); + if ( s < range[0] ) + { + range[0] = s; + } + if ( s > range[1] ) + { + range[1] = s; + } + } + if ( range[1] >= this->ScalarRange[0] && + range[0] <= this->ScalarRange[1] ) + { + this->Wave2->InsertNextId(cellId); + } + } + else + { + this->Wave2->InsertNextId(cellId); + } + }//for all cells using this point + }//for all points of this cell + }//if cell not yet visited + }//for all cells in this wave + + tmpWave = this->Wave; + this->Wave = this->Wave2; + this->Wave2 = tmpWave; + tmpWave->Reset(); + } //while wave is not empty + + return; +} + +// Obtain the number of connected regions. +int vtkConnectivityFilter::GetNumberOfExtractedRegions() +{ + return this->RegionSizes->GetMaxId() + 1; +} + +// Initialize list of point ids/cell ids used to seed regions. +void vtkConnectivityFilter::InitializeSeedList() +{ + this->Modified(); + this->Seeds->Reset(); +} + +// Add a seed id (point or cell id). Note: ids are 0-offset. +void vtkConnectivityFilter::AddSeed(vtkIdType id) +{ + this->Modified(); + this->Seeds->InsertNextId(id); +} + +// Delete a seed id (point or cell id). Note: ids are 0-offset. +void vtkConnectivityFilter::DeleteSeed(vtkIdType id) +{ + this->Modified(); + this->Seeds->DeleteId(id); +} + +// Initialize list of region ids to extract. +void vtkConnectivityFilter::InitializeSpecifiedRegionList() +{ + this->Modified(); + this->SpecifiedRegionIds->Reset(); +} + +// Add a region id to extract. Note: ids are 0-offset. +void vtkConnectivityFilter::AddSpecifiedRegion(int id) +{ + this->Modified(); + this->SpecifiedRegionIds->InsertNextId(id); +} + +// Delete a region id to extract. Note: ids are 0-offset. +void vtkConnectivityFilter::DeleteSpecifiedRegion(int id) +{ + this->Modified(); + this->SpecifiedRegionIds->DeleteId(id); +} + +int vtkConnectivityFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkConnectivityFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Extraction Mode: "; + os << this->GetExtractionModeAsString() << "\n"; + + os << indent << "Closest Point: (" << this->ClosestPoint[0] << ", " + << this->ClosestPoint[1] << ", " << this->ClosestPoint[2] << ")\n"; + + os << indent << "Color Regions: " << (this->ColorRegions ? "On\n" : "Off\n"); + + os << indent << "Scalar Connectivity: " + << (this->ScalarConnectivity ? "On\n" : "Off\n"); + + double *range = this->GetScalarRange(); + os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n"; +} + diff --git a/Graphics/vtkConnectivityFilter.h b/Graphics/vtkConnectivityFilter.h new file mode 100644 index 0000000..78dd9da --- /dev/null +++ b/Graphics/vtkConnectivityFilter.h @@ -0,0 +1,219 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkConnectivityFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkConnectivityFilter - extract data based on geometric connectivity +// .SECTION Description +// vtkConnectivityFilter is a filter that extracts cells that share common +// points and/or meet other connectivity criterion. (Cells that share +// vertices and meet other connectivity criterion such as scalar range are +// known as a region.) The filter works in one of six ways: 1) extract the +// largest connected region in the dataset; 2) extract specified region +// numbers; 3) extract all regions sharing specified point ids; 4) extract +// all regions sharing specified cell ids; 5) extract the region closest to +// the specified point; or 6) extract all regions (used to color the data by +// region). +// +// vtkConnectivityFilter is generalized to handle any type of input dataset. +// It generates output data of type vtkUnstructuredGrid. If you know that +// your input type is vtkPolyData, you may wish to use +// vtkPolyDataConnectivityFilter. +// +// The behavior of vtkConnectivityFilter can be modified by turning on the +// boolean ivar ScalarConnectivity. If this flag is on, the connectivity +// algorithm is modified so that cells are considered connected only if 1) +// they are geometrically connected (share a point) and 2) the scalar values +// of one of the cell's points falls in the scalar range specified. This use +// of ScalarConnectivity is particularly useful for volume datasets: it can +// be used as a simple "connected segmentation" algorithm. For example, by +// using a seed voxel (i.e., cell) on a known anatomical structure, +// connectivity will pull out all voxels "containing" the anatomical +// structure. These voxels can then be contoured or processed by other +// visualization filters. + +// .SECTION See Also +// vtkPolyDataConnectivityFilter + +#ifndef __vtkConnectivityFilter_h +#define __vtkConnectivityFilter_h + +#include "vtkUnstructuredGridAlgorithm.h" + +#define VTK_EXTRACT_POINT_SEEDED_REGIONS 1 +#define VTK_EXTRACT_CELL_SEEDED_REGIONS 2 +#define VTK_EXTRACT_SPECIFIED_REGIONS 3 +#define VTK_EXTRACT_LARGEST_REGION 4 +#define VTK_EXTRACT_ALL_REGIONS 5 +#define VTK_EXTRACT_CLOSEST_POINT_REGION 6 + +class vtkDataArray; +class vtkFloatArray; +class vtkIdList; +class vtkIntArray; + +class VTK_GRAPHICS_EXPORT vtkConnectivityFilter : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkConnectivityFilter,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with default extraction mode to extract largest regions. + static vtkConnectivityFilter *New(); + + // Description: + // Turn on/off connectivity based on scalar value. If on, cells are connected + // only if they share points AND one of the cells scalar values falls in the + // scalar range specified. + vtkSetMacro(ScalarConnectivity,int); + vtkGetMacro(ScalarConnectivity,int); + vtkBooleanMacro(ScalarConnectivity,int); + + // Description: + // Set the scalar range to use to extract cells based on scalar connectivity. + vtkSetVector2Macro(ScalarRange,double); + vtkGetVector2Macro(ScalarRange,double); + + // Description: + // Control the extraction of connected surfaces. + vtkSetClampMacro(ExtractionMode,int, + VTK_EXTRACT_POINT_SEEDED_REGIONS,VTK_EXTRACT_CLOSEST_POINT_REGION); + vtkGetMacro(ExtractionMode,int); + void SetExtractionModeToPointSeededRegions() + {this->SetExtractionMode(VTK_EXTRACT_POINT_SEEDED_REGIONS);}; + void SetExtractionModeToCellSeededRegions() + {this->SetExtractionMode(VTK_EXTRACT_CELL_SEEDED_REGIONS);}; + void SetExtractionModeToLargestRegion() + {this->SetExtractionMode(VTK_EXTRACT_LARGEST_REGION);}; + void SetExtractionModeToSpecifiedRegions() + {this->SetExtractionMode(VTK_EXTRACT_SPECIFIED_REGIONS);}; + void SetExtractionModeToClosestPointRegion() + {this->SetExtractionMode(VTK_EXTRACT_CLOSEST_POINT_REGION);}; + void SetExtractionModeToAllRegions() + {this->SetExtractionMode(VTK_EXTRACT_ALL_REGIONS);}; + const char *GetExtractionModeAsString(); + + // Description: + // Initialize list of point ids/cell ids used to seed regions. + void InitializeSeedList(); + + // Description: + // Add a seed id (point or cell id). Note: ids are 0-offset. + void AddSeed(vtkIdType id); + + // Description: + // Delete a seed id (point or cell id). Note: ids are 0-offset. + void DeleteSeed(vtkIdType id); + + // Description: + // Initialize list of region ids to extract. + void InitializeSpecifiedRegionList(); + + // Description: + // Add a region id to extract. Note: ids are 0-offset. + void AddSpecifiedRegion(int id); + + // Description: + // Delete a region id to extract. Note: ids are 0-offset. + void DeleteSpecifiedRegion(int id); + + // Description: + // Use to specify x-y-z point coordinates when extracting the region + // closest to a specified point. + vtkSetVector3Macro(ClosestPoint,double); + vtkGetVectorMacro(ClosestPoint,double,3); + + // Description: + // Obtain the number of connected regions. + int GetNumberOfExtractedRegions(); + + // Description: + // Turn on/off the coloring of connected regions. + vtkSetMacro(ColorRegions,int); + vtkGetMacro(ColorRegions,int); + vtkBooleanMacro(ColorRegions,int); + +protected: + vtkConnectivityFilter(); + ~vtkConnectivityFilter(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int ColorRegions; //boolean turns on/off scalar gen for separate regions + int ExtractionMode; //how to extract regions + vtkIdList *Seeds; //id's of points or cells used to seed regions + vtkIdList *SpecifiedRegionIds; //regions specified for extraction + vtkIntArray *RegionSizes; //size (in cells) of each region extracted + + double ClosestPoint[3]; + + int ScalarConnectivity; + double ScalarRange[2]; + + void TraverseAndMark(vtkDataSet *input); + +private: + // used to support algorithm execution + vtkFloatArray *CellScalars; + vtkIdList *NeighborCellPointIds; + vtkIdType *Visited; + vtkIdType *PointMap; + vtkFloatArray *NewScalars; + int RegionNumber; + vtkIdType PointNumber; + int NumCellsInRegion; + vtkDataArray *InScalars; + vtkIdList *Wave; + vtkIdList *Wave2; + vtkIdList *PointIds; + vtkIdList *CellIds; +private: + vtkConnectivityFilter(const vtkConnectivityFilter&); // Not implemented. + void operator=(const vtkConnectivityFilter&); // Not implemented. +}; + +// Description: +// Return the method of extraction as a string. +inline const char *vtkConnectivityFilter::GetExtractionModeAsString(void) +{ + if ( this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS ) + { + return "ExtractPointSeededRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS ) + { + return "ExtractCellSeededRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_SPECIFIED_REGIONS ) + { + return "ExtractSpecifiedRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_ALL_REGIONS ) + { + return "ExtractAllRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION ) + { + return "ExtractClosestPointRegion"; + } + else + { + return "ExtractLargestRegion"; + } +} + +#endif + + diff --git a/Graphics/vtkContourFilter.cxx b/Graphics/vtkContourFilter.cxx new file mode 100644 index 0000000..cf3021b --- /dev/null +++ b/Graphics/vtkContourFilter.cxx @@ -0,0 +1,656 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkContourFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkContourFilter.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkContourGrid.h" +#include "vtkContourValues.h" +#include "vtkCutter.h" +#include "vtkGarbageCollector.h" +#include "vtkGenericCell.h" +#include "vtkGridSynchronizedTemplates3D.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkRectilinearSynchronizedTemplates.h" +#include "vtkSimpleScalarTree.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkSynchronizedTemplates2D.h" +#include "vtkSynchronizedTemplates3D.h" +#include "vtkTimerLog.h" +#include "vtkUniformGrid.h" +#include "vtkUnstructuredGrid.h" + +#include + +vtkCxxRevisionMacro(vtkContourFilter, "$Revision: 1.125 $"); +vtkStandardNewMacro(vtkContourFilter); +vtkCxxSetObjectMacro(vtkContourFilter,ScalarTree,vtkScalarTree); + +// Construct object with initial range (0,1) and single contour value +// of 0.0. +vtkContourFilter::vtkContourFilter() +{ + this->ContourValues = vtkContourValues::New(); + + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->Locator = NULL; + + this->UseScalarTree = 0; + this->ScalarTree = NULL; + + this->SynchronizedTemplates2D = vtkSynchronizedTemplates2D::New(); + this->SynchronizedTemplates3D = vtkSynchronizedTemplates3D::New(); + this->GridSynchronizedTemplates = vtkGridSynchronizedTemplates3D::New(); + this->RectilinearSynchronizedTemplates = vtkRectilinearSynchronizedTemplates::New(); + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +vtkContourFilter::~vtkContourFilter() +{ + this->ContourValues->Delete(); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( this->ScalarTree ) + { + this->ScalarTree->Delete(); + this->ScalarTree = 0; + } + this->SynchronizedTemplates2D->Delete(); + this->SynchronizedTemplates3D->Delete(); + this->GridSynchronizedTemplates->Delete(); + this->RectilinearSynchronizedTemplates->Delete(); +} + +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkContourFilter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if (this->ContourValues) + { + time = this->ContourValues->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if (this->Locator) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +int vtkContourFilter::RequestUpdateExtent(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = + vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + + vtkInformation *fInfo = + vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); + int sType = VTK_DOUBLE; + if (fInfo) + { + sType = fInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()); + } + + // handle 2D images + int i; + if (vtkImageData::SafeDownCast(input) && sType != VTK_BIT && + !vtkUniformGrid::SafeDownCast(input)) + { + int dim = 3; + int *uExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + if (uExt[0] == uExt[1]) + { + --dim; + } + if (uExt[2] == uExt[3]) + { + --dim; + } + if (uExt[4] == uExt[5]) + { + --dim; + } + + if ( dim == 2 ) + { + this->SynchronizedTemplates2D->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->SynchronizedTemplates2D->SetValue(i,values[i]); + } + this->SynchronizedTemplates2D->SetComputeScalars(this->ComputeScalars); + return this->SynchronizedTemplates2D-> + ProcessRequest(request,inputVector,outputVector); + } + else if (dim == 3) + { + this->SynchronizedTemplates3D->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->SynchronizedTemplates3D->SetValue(i,values[i]); + } + this->SynchronizedTemplates3D->SetComputeNormals(this->ComputeNormals); + this->SynchronizedTemplates3D->SetComputeGradients(this->ComputeGradients); + this->SynchronizedTemplates3D->SetComputeScalars(this->ComputeScalars); + return this->SynchronizedTemplates3D-> + ProcessRequest(request,inputVector,outputVector); + } + } //if image data + + // handle 3D RGrids + if (vtkRectilinearGrid::SafeDownCast(input) && sType != VTK_BIT) + { + int *uExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + // if 3D + if (uExt[0] < uExt[1] && uExt[2] < uExt[3] && uExt[4] < uExt[5]) + { + this->RectilinearSynchronizedTemplates->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->RectilinearSynchronizedTemplates->SetValue(i,values[i]); + } + this->RectilinearSynchronizedTemplates->SetComputeNormals(this->ComputeNormals); + this->RectilinearSynchronizedTemplates->SetComputeGradients(this->ComputeGradients); + this->RectilinearSynchronizedTemplates->SetComputeScalars(this->ComputeScalars); + return this->RectilinearSynchronizedTemplates-> + ProcessRequest(request,inputVector,outputVector); + } + } //if 3D RGrid + + // handle 3D SGrids + if (vtkStructuredGrid::SafeDownCast(input) && sType != VTK_BIT) + { + int *uExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + // if 3D + if (uExt[0] < uExt[1] && uExt[2] < uExt[3] && uExt[4] < uExt[5]) + { + this->GridSynchronizedTemplates->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->GridSynchronizedTemplates->SetValue(i,values[i]); + } + this->GridSynchronizedTemplates->SetComputeNormals(this->ComputeNormals); + this->GridSynchronizedTemplates->SetComputeGradients(this->ComputeGradients); + this->GridSynchronizedTemplates->SetComputeScalars(this->ComputeScalars); + return this->GridSynchronizedTemplates-> + ProcessRequest(request,inputVector,outputVector); + } + } //if 3D SGrid + + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + return 1; +} + +// General contouring filter. Handles arbitrary input. +// +int vtkContourFilter::RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the input + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + if (!input) + { + return 0; + } + + // get the contours + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + int i; + + // is there data to process? + if (!this->GetInputArrayToProcess(0, inputVector)) + { + return 1; + } + + int sType = this->GetInputArrayToProcess(0, inputVector)->GetDataType(); + + // handle 2D images + if (vtkImageData::SafeDownCast(input) && sType != VTK_BIT && + !vtkUniformGrid::SafeDownCast(input)) + { + int dim = 3; + int *uExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + if (uExt[0] == uExt[1]) + { + --dim; + } + if (uExt[2] == uExt[3]) + { + --dim; + } + if (uExt[4] == uExt[5]) + { + --dim; + } + + if ( dim == 2 ) + { + this->SynchronizedTemplates2D->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->SynchronizedTemplates2D->SetValue(i,values[i]); + } + this->SynchronizedTemplates2D-> + SetInputArrayToProcess(0,this->GetInputArrayInformation(0)); + return + this->SynchronizedTemplates2D->ProcessRequest(request,inputVector,outputVector); + } + else if ( dim == 3 ) + { + this->SynchronizedTemplates3D->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->SynchronizedTemplates3D->SetValue(i,values[i]); + } + this->SynchronizedTemplates3D->SetComputeNormals(this->ComputeNormals); + this->SynchronizedTemplates3D->SetComputeGradients(this->ComputeGradients); + this->SynchronizedTemplates3D->SetComputeScalars(this->ComputeScalars); + this->SynchronizedTemplates3D-> + SetInputArrayToProcess(0,this->GetInputArrayInformation(0)); + return + this->SynchronizedTemplates3D->ProcessRequest(request,inputVector,outputVector); + } + } //if image data + + // handle 3D RGrids + if (vtkRectilinearGrid::SafeDownCast(input) && sType != VTK_BIT) + { + int *uExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + // if 3D + if (uExt[0] < uExt[1] && uExt[2] < uExt[3] && uExt[4] < uExt[5]) + { + this->RectilinearSynchronizedTemplates->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->RectilinearSynchronizedTemplates->SetValue(i,values[i]); + } + this->RectilinearSynchronizedTemplates->SetComputeNormals(this->ComputeNormals); + this->RectilinearSynchronizedTemplates->SetComputeGradients(this->ComputeGradients); + this->RectilinearSynchronizedTemplates->SetComputeScalars(this->ComputeScalars); + this->RectilinearSynchronizedTemplates-> + SetInputArrayToProcess(0,this->GetInputArrayInformation(0)); + return this->RectilinearSynchronizedTemplates-> + ProcessRequest(request,inputVector,outputVector); + } + } // if 3D Rgrid + + // handle 3D SGrids + if (vtkStructuredGrid::SafeDownCast(input) && sType != VTK_BIT) + { + int *uExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + // if 3D + if (uExt[0] < uExt[1] && uExt[2] < uExt[3] && uExt[4] < uExt[5]) + { + this->GridSynchronizedTemplates->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + this->GridSynchronizedTemplates->SetValue(i,values[i]); + } + this->GridSynchronizedTemplates->SetComputeNormals(this->ComputeNormals); + this->GridSynchronizedTemplates->SetComputeGradients(this->ComputeGradients); + this->GridSynchronizedTemplates->SetComputeScalars(this->ComputeScalars); + this->GridSynchronizedTemplates-> + SetInputArrayToProcess(0,this->GetInputArrayInformation(0)); + return this->GridSynchronizedTemplates-> + ProcessRequest(request,inputVector,outputVector); + } + } //if 3D SGrid + + vtkIdType cellId; + int abortExecute=0; + vtkIdList *cellPts; + vtkDataArray *inScalars; + vtkCellArray *newVerts, *newLines, *newPolys; + vtkPoints *newPts; + vtkIdType numCells, estimatedSize; + vtkDataArray *cellScalars; + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + if (!output) {return 0;} + + + vtkPointData *inPd=input->GetPointData(), *outPd=output->GetPointData(); + vtkCellData *inCd=input->GetCellData(), *outCd=output->GetCellData(); + + vtkDebugMacro(<< "Executing contour filter"); + if (input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID) + { + vtkDebugMacro(<< "Processing unstructured grid"); + vtkContourGrid *cgrid; + + cgrid = vtkContourGrid::New(); + cgrid->SetInput((vtkUnstructuredGrid *)input); + for (i = 0; i < numContours; i++) + { + cgrid->SetValue(i, values[i]); + } + cgrid->GetOutput()->SetUpdateExtent(output->GetUpdatePiece(), + output->GetUpdateNumberOfPieces(), + output->GetUpdateGhostLevel()); + cgrid->SetInputArrayToProcess(0,this->GetInputArrayInformation(0)); + cgrid->Update(); + output->ShallowCopy(cgrid->GetOutput()); + cgrid->SetInput(0); + cgrid->Delete(); + } //if type VTK_UNSTRUCTURED_GRID + else + { + numCells = input->GetNumberOfCells(); + inScalars = this->GetInputArrayToProcess(0,inputVector); + if ( ! inScalars || numCells < 1 ) + { + vtkDebugMacro(<<"No data to contour"); + return 1; + } + + // Create objects to hold output of contour operation. First estimate + // allocation size. + // + estimatedSize = (vtkIdType) pow ((double) numCells, .75); + estimatedSize *= numContours; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize,estimatedSize); + newLines = vtkCellArray::New(); + newLines->Allocate(estimatedSize,estimatedSize); + newPolys = vtkCellArray::New(); + newPolys->Allocate(estimatedSize,estimatedSize); + cellScalars = inScalars->NewInstance(); + cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + cellScalars->Allocate(cellScalars->GetNumberOfComponents()*VTK_CELL_SIZE); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, + input->GetBounds(),estimatedSize); + + // interpolate data along edge + // if we did not ask for scalars to be computed, don't copy them + if (!this->ComputeScalars) + { + outPd->CopyScalarsOff(); + } + outPd->InterpolateAllocate(inPd,estimatedSize,estimatedSize); + outCd->CopyAllocate(inCd,estimatedSize,estimatedSize); + + // If enabled, build a scalar tree to accelerate search + // + if ( !this->UseScalarTree ) + { + vtkGenericCell *cell = vtkGenericCell::New(); + // Three passes over the cells to process lower dimensional cells first. + // For poly data output cells need to be added in the order: + // verts, lines and then polys, or cell data gets mixed up. + // A better solution is to have an unstructured grid output. + // I create a table that maps cell type to cell dimensionality, + // because I need a fast way to get cell dimensionality. + // This assumes GetCell is slow and GetCellType is fast. + // I do not like hard coding a list of cell types here, + // but I do not want to add GetCellDimension(vtkIdType cellId) + // to the vtkDataSet API. Since I anticipate that the output + // will change to vtkUnstructuredGrid. This temporary solution + // is acceptable. + // + int cellType; + unsigned char cellTypeDimensions[VTK_NUMBER_OF_CELL_TYPES]; + vtkCutter::GetCellTypeDimensions(cellTypeDimensions); + int dimensionality; + // We skip 0d cells (points), because they cannot be cut (generate no data). + for (dimensionality = 1; dimensionality <= 3; ++dimensionality) + { + // Loop over all cells; get scalar values for all cell points + // and process each cell. + // + for (cellId=0; cellId < numCells && !abortExecute; cellId++) + { + // I assume that "GetCellType" is fast. + cellType = input->GetCellType(cellId); + if (cellType >= VTK_NUMBER_OF_CELL_TYPES) + { // Protect against new cell types added. + vtkErrorMacro("Unknown cell type " << cellType); + continue; + } + if (cellTypeDimensions[cellType] != dimensionality) + { + continue; + } + input->GetCell(cellId,cell); + cellPts = cell->GetPointIds(); + inScalars->GetTuples(cellPts,cellScalars); + + if (dimensionality == 3 && ! (cellId % 5000) ) + { + vtkDebugMacro(<<"Contouring #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + abortExecute = this->GetAbortExecute(); + } + + for (i=0; i < numContours; i++) + { + cell->Contour(values[i], cellScalars, this->Locator, + newVerts, newLines, newPolys, inPd, outPd, + inCd, cellId, outCd); + + } // for all contour values + } // for all cells + } // for all dimensions + cell->Delete(); + } //if using scalar tree + else + { + vtkCell *cell; + if ( this->ScalarTree == NULL ) + { + this->ScalarTree = vtkSimpleScalarTree::New(); + } + this->ScalarTree->SetDataSet(input); + // Note: This will have problems when input contains 2D and 3D cells. + // CellData will get scrabled because of the implicit ordering of + // verts, lines and polys in vtkPolyData. The solution + // is to convert this filter to create unstructured grid. + // + // Loop over all contour values. Then for each contour value, + // loop over all cells. + // + for (i=0; i < numContours; i++) + { + for ( this->ScalarTree->InitTraversal(values[i]); + (cell=this->ScalarTree->GetNextCell(cellId,cellPts,cellScalars)) != NULL; ) + { + cell->Contour(values[i], cellScalars, this->Locator, + newVerts, newLines, newPolys, inPd, outPd, + inCd, cellId, outCd); + + } //for all cells + } //for all contour values + } //using scalar tree + + vtkDebugMacro(<<"Created: " + << newPts->GetNumberOfPoints() << " points, " + << newVerts->GetNumberOfCells() << " verts, " + << newLines->GetNumberOfCells() << " lines, " + << newPolys->GetNumberOfCells() << " triangles"); + + // Update ourselves. Because we don't know up front how many verts, lines, + // polys we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + cellScalars->Delete(); + + if (newVerts->GetNumberOfCells()) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if (newLines->GetNumberOfCells()) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if (newPolys->GetNumberOfCells()) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + this->Locator->Initialize();//releases leftover memory + output->Squeeze(); + } //else if not vtkUnstructuredGrid + + return 1; +} + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkContourFilter::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkContourFilter::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +void vtkContourFilter::SetArrayComponent( int comp ) +{ + this->SynchronizedTemplates2D->SetArrayComponent( comp ); + this->SynchronizedTemplates3D->SetArrayComponent( comp ); + this->RectilinearSynchronizedTemplates->SetArrayComponent( comp ); +} + +int vtkContourFilter::GetArrayComponent() +{ + return( this->SynchronizedTemplates2D->GetArrayComponent() ); +} + +int vtkContourFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkContourFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Compute Gradients: " + << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Normals: " + << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " + << (this->ComputeScalars ? "On\n" : "Off\n"); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Use Scalar Tree: " + << (this->UseScalarTree ? "On\n" : "Off\n"); + if ( this->ScalarTree ) + { + os << indent << "Scalar Tree: " << this->ScalarTree << "\n"; + } + else + { + os << indent << "Scalar Tree: (none)\n"; + } + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkContourFilter::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->ScalarTree, "ScalarTree"); +} diff --git a/Graphics/vtkContourFilter.h b/Graphics/vtkContourFilter.h new file mode 100644 index 0000000..e5ff7ba --- /dev/null +++ b/Graphics/vtkContourFilter.h @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkContourFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkContourFilter - generate isosurfaces/isolines from scalar values +// .SECTION Description +// vtkContourFilter is a filter that takes as input any dataset and +// generates on output isosurfaces and/or isolines. The exact form +// of the output depends upon the dimensionality of the input data. +// Data consisting of 3D cells will generate isosurfaces, data +// consisting of 2D cells will generate isolines, and data with 1D +// or 0D cells will generate isopoints. Combinations of output type +// are possible if the input dimension is mixed. +// +// To use this filter you must specify one or more contour values. +// You can either use the method SetValue() to specify each contour +// value, or use GenerateValues() to generate a series of evenly +// spaced contours. It is also possible to accelerate the operation of +// this filter (at the cost of extra memory) by using a +// vtkScalarTree. A scalar tree is used to quickly locate cells that +// contain a contour surface. This is especially effective if multiple +// contours are being extracted. If you want to use a scalar tree, +// invoke the method UseScalarTreeOn(). + +// .SECTION Caveats +// For unstructured data or structured grids, normals and gradients +// are not computed. Use vtkPolyDataNormals to compute the surface +// normals. + +// .SECTION See Also +// vtkMarchingContourFilter vtkKitwareContourFilter +// vtkMarchingCubes vtkSliceCubes vtkDividingCubes vtkMarchingSquares +// vtkImageMarchingCubes + +#ifndef __vtkContourFilter_h +#define __vtkContourFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for inline methods + +class vtkPointLocator; +class vtkScalarTree; +class vtkSynchronizedTemplates2D; +class vtkSynchronizedTemplates3D; +class vtkGridSynchronizedTemplates3D; +class vtkRectilinearSynchronizedTemplates; + +class VTK_GRAPHICS_EXPORT vtkContourFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkContourFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with initial range (0,1) and single contour value + // of 0.0. + static vtkContourFilter *New(); + + // Description: + // Methods to set / get contour values. + void SetValue(int i, double value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Description: + // Modified GetMTime Because we delegate to vtkContourValues + unsigned long GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Enable the use of a scalar tree to accelerate contour extraction. + vtkSetMacro(UseScalarTree,int); + vtkGetMacro(UseScalarTree,int); + vtkBooleanMacro(UseScalarTree,int); + + // Description: + // Enable the use of a scalar tree to accelerate contour extraction. + virtual void SetScalarTree(vtkScalarTree*); + vtkGetObjectMacro(ScalarTree,vtkScalarTree); + + // Description: + // Set / get a spatial locator for merging points. By default, + // an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is + // specified. The locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // Set/get which component of the scalar array to contour on; defaults to 0. + // Currently this feature only works if the input is a vtkImageData. + void SetArrayComponent( int ); + int GetArrayComponent(); + +protected: + vtkContourFilter(); + ~vtkContourFilter(); + + virtual void ReportReferences(vtkGarbageCollector*); + + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkContourValues *ContourValues; + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkPointLocator *Locator; + int UseScalarTree; + vtkScalarTree *ScalarTree; + + vtkSynchronizedTemplates2D *SynchronizedTemplates2D; + vtkSynchronizedTemplates3D *SynchronizedTemplates3D; + vtkGridSynchronizedTemplates3D *GridSynchronizedTemplates; + vtkRectilinearSynchronizedTemplates *RectilinearSynchronizedTemplates; + +private: + vtkContourFilter(const vtkContourFilter&); // Not implemented. + void operator=(const vtkContourFilter&); // Not implemented. +}; + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value);} + +// Description: +// Get the ith contour value. +inline double vtkContourFilter::GetValue(int i) +{return this->ContourValues->GetValue(i);} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +inline double *vtkContourFilter::GetValues() +{return this->ContourValues->GetValues();} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +inline void vtkContourFilter::GetValues(double *contourValues) +{this->ContourValues->GetValues(contourValues);} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +inline void vtkContourFilter::SetNumberOfContours(int number) +{this->ContourValues->SetNumberOfContours(number);} + +// Description: +// Get the number of contours in the list of contour values. +inline int vtkContourFilter::GetNumberOfContours() +{return this->ContourValues->GetNumberOfContours();} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkContourFilter::GenerateValues(int numContours, double range[2]) +{this->ContourValues->GenerateValues(numContours, range);} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkContourFilter::GenerateValues(int numContours, double + rangeStart, double rangeEnd) +{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + +#endif + + diff --git a/Graphics/vtkContourGrid.cxx b/Graphics/vtkContourGrid.cxx new file mode 100644 index 0000000..36d7a84 --- /dev/null +++ b/Graphics/vtkContourGrid.cxx @@ -0,0 +1,439 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkContourGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkContourGrid.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkContourValues.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkSimpleScalarTree.h" +#include "vtkUnstructuredGrid.h" +#include "vtkCutter.h" + +#include + +vtkCxxRevisionMacro(vtkContourGrid, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkContourGrid); + +// Construct object with initial range (0,1) and single contour value +// of 0.0. +vtkContourGrid::vtkContourGrid() +{ + this->ContourValues = vtkContourValues::New(); + + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->Locator = NULL; + + this->UseScalarTree = 0; + this->ScalarTree = NULL; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +vtkContourGrid::~vtkContourGrid() +{ + this->ContourValues->Delete(); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( this->ScalarTree ) + { + this->ScalarTree->Delete(); + } +} + +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkContourGrid::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if (this->ContourValues) + { + time = this->ContourValues->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if (this->Locator) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +template +void vtkContourGridExecute(vtkContourGrid *self, vtkDataSet *input, + vtkPolyData *output, + vtkDataArray *inScalars, T *scalarArrayPtr, + int numContours, double *values, + int computeScalars, + int useScalarTree,vtkScalarTree *&scalarTree) +{ + vtkIdType cellId, i; + int abortExecute=0; + vtkPointLocator *locator = self->GetLocator(); + vtkIdList *cellPts; + vtkCell *cell; + double range[2]; + vtkCellArray *newVerts, *newLines, *newPolys; + vtkPoints *newPts; + vtkIdType numCells, estimatedSize; + vtkPointData *inPd=input->GetPointData(), *outPd=output->GetPointData(); + vtkCellData *inCd=input->GetCellData(), *outCd=output->GetCellData(); + vtkDataArray *cellScalars; + vtkUnstructuredGrid *grid = (vtkUnstructuredGrid *)input; + //In this case, we know that the input is an unstructured grid. + vtkIdType numPoints, cellArrayIt = 0; + int needCell = 0; + vtkIdType *cellArrayPtr; + T tempScalar; + + numCells = input->GetNumberOfCells(); + + // + // Create objects to hold output of contour operation. First estimate + // allocation size. + // + estimatedSize = (vtkIdType) pow ((double) numCells, .75); + estimatedSize *= numContours; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize,estimatedSize); + newLines = vtkCellArray::New(); + newLines->Allocate(estimatedSize,estimatedSize); + newPolys = vtkCellArray::New(); + newPolys->Allocate(estimatedSize,estimatedSize); + cellScalars = inScalars->NewInstance(); + cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + cellScalars->Allocate(VTK_CELL_SIZE*inScalars->GetNumberOfComponents()); + + // locator used to merge potentially duplicate points + locator->InitPointInsertion (newPts, input->GetBounds(),estimatedSize); + + // interpolate data along edge + // if we did not ask for scalars to be computed, don't copy them + if (!computeScalars) + { + outPd->CopyScalarsOff(); + } + outPd->InterpolateAllocate(inPd,estimatedSize,estimatedSize); + outCd->CopyAllocate(inCd,estimatedSize,estimatedSize); + + // If enabled, build a scalar tree to accelerate search + // + if ( !useScalarTree ) + { + // Three passes over the cells to process lower dimensional cells first. + // For poly data output cells need to be added in the order: + // verts, lines and then polys, or cell data gets mixed up. + // A better solution is to have an unstructured grid output. + // I create a table that maps cell type to cell dimensionality, + // because I need a fast way to get cell dimensionality. + // This assumes GetCell is slow and GetCellType is fast. + // I do not like hard coding a list of cell types here, + // but I do not want to add GetCellDimension(vtkIdType cellId) + // to the vtkDataSet API. Since I anticipate that the output + // will change to vtkUnstructuredGrid. This temporary solution + // is acceptable. + // + int cellType; + unsigned char cellTypeDimensions[VTK_NUMBER_OF_CELL_TYPES]; + vtkCutter::GetCellTypeDimensions(cellTypeDimensions); + int dimensionality; + // We skip 0d cells (points), because they cannot be cut (generate no data). + for (dimensionality = 1; dimensionality <= 3; ++dimensionality) + { + // Loop over all cells; get scalar values for all cell points + // and process each cell. + // + cellArrayIt = 0; + cellArrayPtr = grid->GetCells()->GetPointer(); + for (cellId=0; cellId < numCells && !abortExecute; cellId++) + { + numPoints = cellArrayPtr[cellArrayIt]; + // I assume that "GetCellType" is fast. + cellType = input->GetCellType(cellId); + if (cellType >= VTK_NUMBER_OF_CELL_TYPES) + { // Protect against new cell types added. + vtkGenericWarningMacro("Unknown cell type " << cellType); + cellArrayIt += 1+numPoints; + continue; + } + if (cellTypeDimensions[cellType] != dimensionality) + { + cellArrayIt += 1+numPoints; + continue; + } + cellArrayIt++; + + //find min and max values in scalar data + range[0] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + range[1] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + cellArrayIt++; + + for (i = 1; i < numPoints; i++) + { + tempScalar = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + cellArrayIt++; + if (tempScalar <= range[0]) + { + range[0] = tempScalar; + } //if tempScalar <= min range value + if (tempScalar >= range[1]) + { + range[1] = tempScalar; + } //if tempScalar >= max range value + } // for all points in this cell + + if (dimensionality == 3 && ! (cellId % 5000) ) + { + self->UpdateProgress ((double)cellId/numCells); + if (self->GetAbortExecute()) + { + abortExecute = 1; + break; + } + } + + for (i = 0; i < numContours; i++) + { + if ((values[i] >= range[0]) && (values[i] <= range[1])) + { + needCell = 1; + } // if contour value in range for this cell + } // end for numContours + + if (needCell) + { + cell = input->GetCell(cellId); + cellPts = cell->GetPointIds(); + inScalars->GetTuples(cellPts,cellScalars); + + for (i=0; i < numContours; i++) + { + if ((values[i] >= range[0]) && (values[i] <= range[1])) + { + cell->Contour(values[i], cellScalars, locator, + newVerts, newLines, newPolys, inPd, outPd, + inCd, cellId, outCd); + } // if contour value in range of values for this cell + } // for all contour values + } // if contour goes through this cell + needCell = 0; + } // for all cells + } // For all dimensions. + } //if using scalar tree + else + { + // Note: This will have problems when input contains 2D and 3D cells. + // CellData will get scrabled because of the implicit ordering of + // verts, lines and polys in vtkPolyData. The solution + // is to convert this filter to create unstructured grid. + // + if ( scalarTree == NULL ) + { + scalarTree = vtkSimpleScalarTree::New(); + } + scalarTree->SetDataSet(input); + // + // Loop over all contour values. Then for each contour value, + // loop over all cells. + // + for (i=0; i < numContours; i++) + { + for ( scalarTree->InitTraversal(values[i]); + (cell=scalarTree->GetNextCell(cellId,cellPts,cellScalars)) != NULL; ) + { + cell->Contour(values[i], cellScalars, locator, + newVerts, newLines, newPolys, inPd, outPd, + inCd, cellId, outCd); + //don't want to call Contour any more than necessary + } //for all cells + } //for all contour values + } //using scalar tree + + // + // Update ourselves. Because we don't know up front how many verts, lines, + // polys we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + cellScalars->Delete(); + + if (newVerts->GetNumberOfCells()) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if (newLines->GetNumberOfCells()) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if (newPolys->GetNumberOfCells()) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + locator->Initialize();//releases leftover memory + output->Squeeze(); +} + +// +// Contouring filter for unstructured grids. +// +int vtkContourGrid::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *inScalars; + void *scalarArrayPtr; + vtkIdType numCells; + int numContours = this->ContourValues->GetNumberOfContours(); + double *values = this->ContourValues->GetValues(); + int computeScalars = this->ComputeScalars; + int useScalarTree = this->UseScalarTree; + vtkScalarTree *&scalarTree = this->ScalarTree; + + vtkDebugMacro(<< "Executing contour filter"); + + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + + numCells = input->GetNumberOfCells(); + inScalars = this->GetInputArrayToProcess(0,inputVector); + if ( ! inScalars || numCells < 1 ) + { + vtkDebugMacro(<<"No data to contour"); + return 1; + } + + scalarArrayPtr = inScalars->GetVoidPointer(0); + + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + vtkContourGridExecute( this, input, output, inScalars, + (VTK_TT *)(scalarArrayPtr), numContours, values, + computeScalars, useScalarTree, + scalarTree)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 1; + } + + return 1; +} + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkContourGrid::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkContourGrid::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +int vtkContourGrid::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + +void vtkContourGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Compute Gradients: " + << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Normals: " + << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " + << (this->ComputeScalars ? "On\n" : "Off\n"); + os << indent << "Use Scalar Tree: " + << (this->UseScalarTree ? "On\n" : "Off\n"); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/Graphics/vtkContourGrid.h b/Graphics/vtkContourGrid.h new file mode 100644 index 0000000..7b38bfc --- /dev/null +++ b/Graphics/vtkContourGrid.h @@ -0,0 +1,199 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkContourGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkContourGrid - generate isosurfaces/isolines from scalar values (specialized for unstructured grids) +// .SECTION Description +// vtkContourGrid is a filter that takes as input datasets of type +// vtkUnstructuredGrid and generates on output isosurfaces and/or +// isolines. The exact form of the output depends upon the dimensionality of +// the input data. Data consisting of 3D cells will generate isosurfaces, +// data consisting of 2D cells will generate isolines, and data with 1D or 0D +// cells will generate isopoints. Combinations of output type are possible if +// the input dimension is mixed. +// +// To use this filter you must specify one or more contour values. +// You can either use the method SetValue() to specify each contour +// value, or use GenerateValues() to generate a series of evenly +// spaced contours. It is also possible to accelerate the operation of +// this filter (at the cost of extra memory) by using a +// vtkScalarTree. A scalar tree is used to quickly locate cells that +// contain a contour surface. This is especially effective if multiple +// contours are being extracted. If you want to use a scalar tree, +// invoke the method UseScalarTreeOn(). +// + +// .SECTION Caveats +// For unstructured data or structured grids, normals and gradients +// are not computed. Use vtkPolyDataNormals to compute the surface +// normals of the resulting isosurface. + +// .SECTION See Also +// vtkMarchingContourFilter vtkKitwareContourFilter +// vtkMarchingCubes vtkSliceCubes vtkDividingCubes vtkMarchingSquares +// vtkImageMarchingCubes + +#ifndef __vtkContourGrid_h +#define __vtkContourGrid_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for inline methods + +class vtkEdgeTable; +class vtkPointLocator; +class vtkScalarTree; + +class VTK_GRAPHICS_EXPORT vtkContourGrid : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkContourGrid,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with initial range (0,1) and single contour value + // of 0.0. + static vtkContourGrid *New(); + + // Description: + // Methods to set / get contour values. + void SetValue(int i, double value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Description: + // Modified GetMTime Because we delegate to vtkContourValues + unsigned long GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Enable the use of a scalar tree to accelerate contour extraction. + vtkSetMacro(UseScalarTree,int); + vtkGetMacro(UseScalarTree,int); + vtkBooleanMacro(UseScalarTree,int); + + // Description: + // Set / get a spatial locator for merging points. By default, + // an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is + // specified. The locator is used to merge coincident points. + void CreateDefaultLocator(); + +protected: + vtkContourGrid(); + ~vtkContourGrid(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkContourValues *ContourValues; + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkPointLocator *Locator; + int UseScalarTree; + vtkScalarTree *ScalarTree; + vtkEdgeTable *EdgeTable; + +private: + vtkContourGrid(const vtkContourGrid&); // Not implemented. + void operator=(const vtkContourGrid&); // Not implemented. +}; + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value);} + +// Description: +// Get the ith contour value. +inline double vtkContourGrid::GetValue(int i) +{return this->ContourValues->GetValue(i);} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +inline double *vtkContourGrid::GetValues() +{return this->ContourValues->GetValues();} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +inline void vtkContourGrid::GetValues(double *contourValues) +{this->ContourValues->GetValues(contourValues);} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +inline void vtkContourGrid::SetNumberOfContours(int number) +{this->ContourValues->SetNumberOfContours(number);} + +// Description: +// Get the number of contours in the list of contour values. +inline int vtkContourGrid::GetNumberOfContours() +{return this->ContourValues->GetNumberOfContours();} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkContourGrid::GenerateValues(int numContours, double range[2]) +{this->ContourValues->GenerateValues(numContours, range);} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkContourGrid::GenerateValues(int numContours, double + rangeStart, double rangeEnd) +{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + +#endif + + diff --git a/Graphics/vtkCubeSource.cxx b/Graphics/vtkCubeSource.cxx new file mode 100644 index 0000000..8d81cf4 --- /dev/null +++ b/Graphics/vtkCubeSource.cxx @@ -0,0 +1,204 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCubeSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCubeSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +#include + +vtkCxxRevisionMacro(vtkCubeSource, "$Revision: 1.53 $"); +vtkStandardNewMacro(vtkCubeSource); + +vtkCubeSource::vtkCubeSource(double xL, double yL, double zL) +{ + this->XLength = fabs(xL); + this->YLength = fabs(yL); + this->ZLength = fabs(zL); + + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; + + this->SetNumberOfInputPorts(0); +} + +int vtkCubeSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double x[3], n[3], tc[3]; + int numPolys=6, numPts=24; + int i, j, k; + vtkIdType pts[4]; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkFloatArray *newTCoords; // CCS 7/27/98 Added for Texture Mapping + vtkCellArray *newPolys; + +// +// Set things up; allocate memory +// + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(numPts); + newNormals->SetName("Normals"); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(numPts); + newTCoords->SetName("TCoords"); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys,4)); +// +// Generate points and normals +// + + for (x[0]=this->Center[0]-this->XLength/2.0, n[0]=(-1.0), n[1]=n[2]=0.0, i=0; + i<2; i++, x[0]+=this->XLength, n[0]+=2.0) + { + for (x[1]=this->Center[1]-this->YLength/2.0, j=0; j<2; + j++, x[1]+=this->YLength) + { + tc[1] = x[1] + 0.5; + for (x[2]=this->Center[2]-this->ZLength/2.0, k=0; k<2; + k++, x[2]+=this->ZLength) + { + tc[0] = (x[2] + 0.5) * ( 1 - 2*i ); + newPoints->InsertNextPoint(x); + newTCoords->InsertNextTuple(tc); + newNormals->InsertNextTuple(n); + } + } + } + pts[0] = 0; pts[1] = 1; pts[2] = 3; pts[3] = 2; + newPolys->InsertNextCell(4,pts); + pts[0] = 4; pts[1] = 6; pts[2] = 7; pts[3] = 5; + newPolys->InsertNextCell(4,pts); + + for (x[1]=this->Center[1]-this->YLength/2.0, n[1]=(-1.0), n[0]=n[2]=0.0, i=0; + i<2; i++, x[1]+=this->YLength, n[1]+=2.0) + { + for (x[0]=this->Center[0]-this->XLength/2.0, j=0; j<2; + j++, x[0]+=this->XLength) + { + tc[0] = ( x[0] + 0.5 ) * ( 2*i - 1 ); + for (x[2]=this->Center[2]-this->ZLength/2.0, k=0; k<2; + k++, x[2]+=this->ZLength) + { + tc[1] = ( x[2] + 0.5 ) * -1; + newPoints->InsertNextPoint(x); + newTCoords->InsertNextTuple(tc); + newNormals->InsertNextTuple(n); + } + } + } + pts[0] = 8; pts[1] = 10; pts[2] = 11; pts[3] = 9; + newPolys->InsertNextCell(4,pts); + pts[0] = 12; pts[1] = 13; pts[2] = 15; pts[3] = 14; + newPolys->InsertNextCell(4,pts); + + for (x[2]=this->Center[2]-this->ZLength/2.0, n[2]=(-1.0), n[0]=n[1]=0.0, i=0; + i<2; i++, x[2]+=this->ZLength, n[2]+=2.0) + { + for (x[1]=this->Center[1]-this->YLength/2.0, j=0; j<2; + j++, x[1]+=this->YLength) + { + tc[1] = x[1] + 0.5; + for (x[0]=this->Center[0]-this->XLength/2.0, k=0; k<2; + k++, x[0]+=this->XLength) + { + tc[0] = ( x[0] + 0.5 ) * ( 2*i - 1 ); + newPoints->InsertNextPoint(x); + newTCoords->InsertNextTuple(tc); + newNormals->InsertNextTuple(n); + } + } + } + pts[0] = 16; pts[1] = 18; pts[2] = 19; pts[3] = 17; + newPolys->InsertNextCell(4,pts); + pts[0] = 20; pts[1] = 21; pts[2] = 23; pts[3] = 22; + newPolys->InsertNextCell(4,pts); +// +// Update ourselves and release memory +// + output->SetPoints(newPoints); + newPoints->Delete(); + + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + newPolys->Squeeze(); // since we've estimated size; reclaim some space + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +// Convenience method allows creation of cube by specifying bounding box. +void vtkCubeSource::SetBounds(double xMin, double xMax, + double yMin, double yMax, + double zMin, double zMax) +{ + double bounds[6]; + bounds[0] = xMin; + bounds[1] = xMax; + bounds[2] = yMin; + bounds[3] = yMax; + bounds[4] = zMin; + bounds[5] = zMax; + this->SetBounds (bounds); +} + +void vtkCubeSource::SetBounds(double bounds[6]) +{ + this->SetXLength(bounds[1]-bounds[0]); + this->SetYLength(bounds[3]-bounds[2]); + this->SetZLength(bounds[5]-bounds[4]); + + this->SetCenter((bounds[1]+bounds[0])/2.0, (bounds[3]+bounds[2])/2.0, + (bounds[5]+bounds[4])/2.0); +} + +void vtkCubeSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "X Length: " << this->XLength << "\n"; + os << indent << "Y Length: " << this->YLength << "\n"; + os << indent << "Z Length: " << this->ZLength << "\n"; + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << ")\n"; +} diff --git a/Graphics/vtkCubeSource.h b/Graphics/vtkCubeSource.h new file mode 100644 index 0000000..d10d985 --- /dev/null +++ b/Graphics/vtkCubeSource.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCubeSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCubeSource - create a polygonal representation of a cube +// .SECTION Description +// vtkCubeSource creates a cube centered at origin. The cube is represented +// with four-sided polygons. It is possible to specify the length, width, +// and height of the cube independently. + +#ifndef __vtkCubeSource_h +#define __vtkCubeSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkCubeSource : public vtkPolyDataAlgorithm +{ +public: + static vtkCubeSource *New(); + vtkTypeRevisionMacro(vtkCubeSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the length of the cube in the x-direction. + vtkSetClampMacro(XLength,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(XLength,double); + + // Description: + // Set the length of the cube in the y-direction. + vtkSetClampMacro(YLength,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(YLength,double); + + // Description: + // Set the length of the cube in the z-direction. + vtkSetClampMacro(ZLength,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(ZLength,double); + + // Description: + // Set the center of the cube. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Convenience method allows creation of cube by specifying bounding box. + void SetBounds(double xMin, double xMax, + double yMin, double yMax, + double zMin, double zMax); + void SetBounds(double bounds[6]); + +protected: + vtkCubeSource(double xL=1.0, double yL=1.0, double zL=1.0); + ~vtkCubeSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double XLength; + double YLength; + double ZLength; + double Center[3]; +private: + vtkCubeSource(const vtkCubeSource&); // Not implemented. + void operator=(const vtkCubeSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkCursor3D.cxx b/Graphics/vtkCursor3D.cxx new file mode 100644 index 0000000..c1c2b82 --- /dev/null +++ b/Graphics/vtkCursor3D.cxx @@ -0,0 +1,517 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCursor3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCursor3D.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +#include + +vtkCxxRevisionMacro(vtkCursor3D, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkCursor3D); + +// Construct with model bounds = (-1,1,-1,1,-1,1), focal point = (0,0,0), +// all parts of cursor visible, and wrapping off. +vtkCursor3D::vtkCursor3D() +{ + vtkPoints *pts; + + this->Focus = vtkPolyData::New(); + pts = vtkPoints::New(); + pts->Allocate(1); + pts->vtkPoints::InsertPoint(0, 0.0, 0.0, 0.0); + this->Focus->SetPoints(pts); + pts->Delete(); + + this->ModelBounds[0] = -1.0; + this->ModelBounds[1] = 1.0; + this->ModelBounds[2] = -1.0; + this->ModelBounds[3] = 1.0; + this->ModelBounds[4] = -1.0; + this->ModelBounds[5] = 1.0; + + this->FocalPoint[0] = 0.0; + this->FocalPoint[1] = 0.0; + this->FocalPoint[2] = 0.0; + + this->Outline = 1; + this->Axes = 1; + this->XShadows = 1; + this->YShadows = 1; + this->ZShadows = 1; + this->Wrap = 0; + this->TranslationMode = 0; + + this->SetNumberOfInputPorts(0); +} + +vtkCursor3D::~vtkCursor3D() +{ + this->Focus->Delete(); +} + +int vtkCursor3D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int i; + int numPts=0, numLines=0; + vtkPoints *newPts; + vtkCellArray *newLines; + double x[3]; + vtkIdType ptIds[2]; + + // Check bounding box and origin + // + if ( this->Wrap ) + { + for (i=0; i<3; i++) + { + this->FocalPoint[i] = this->ModelBounds[2*i] + + fmod((double)(this->FocalPoint[i]-this->ModelBounds[2*i]), + (double)(this->ModelBounds[2*i+1]-this->ModelBounds[2*i])); + } + } + else + { + for (i=0; i<3; i++) + { + if ( this->FocalPoint[i] < this->ModelBounds[2*i] ) + { + this->FocalPoint[i] = this->ModelBounds[2*i]; + } + if ( this->FocalPoint[i] > this->ModelBounds[2*i+1] ) + { + this->FocalPoint[i] = this->ModelBounds[2*i+1]; + } + } + } + + // Allocate storage + // + if (this->Axes) + { + numPts += 6; + numLines += 3; + } + + if (this->Outline) + { + numPts += 8; + numLines += 12; + } + + if (this->XShadows) + { + numPts += 8; + numLines += 4; + } + + if (this->YShadows) + { + numPts += 8; + numLines += 4; + } + + if (this->ZShadows) + { + numPts += 8; + numLines += 4; + } + + if ( numPts ) + { + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(numLines,2)); + } + else + { + return 1; + } + + // Create axes + // + if ( this->Axes ) + { + x[0] = this->ModelBounds[0]; + x[1] = this->FocalPoint[1]; + x[2] = this->FocalPoint[2]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[1]; + x[1] = this->FocalPoint[1]; + x[2] = this->FocalPoint[2]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->FocalPoint[0]; + x[1] = this->ModelBounds[2]; + x[2] = this->FocalPoint[2]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->FocalPoint[0]; + x[1] = this->ModelBounds[3]; + x[2] = this->FocalPoint[2]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->FocalPoint[0]; + x[1] = this->FocalPoint[1]; + x[2] = this->ModelBounds[4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->FocalPoint[0]; + x[1] = this->FocalPoint[1]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + } + + // Create outline + // + if ( this->Outline ) + { + // First triad + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[4]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[4]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + // Second triad + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[5]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[4]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + // Fill in remaining lines + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[4]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[4]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[5]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + } + + // Create x-shadows + // + if ( this->XShadows ) + { + for (i=0; i<2; i++) + { + x[0] = this->ModelBounds[i]; + x[1] = this->ModelBounds[2]; + x[2] = this->FocalPoint[2]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[i]; + x[1] = this->ModelBounds[3]; + x[2] = this->FocalPoint[2]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->ModelBounds[i]; + x[1] = this->FocalPoint[1]; + x[2] = this->ModelBounds[4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[i]; + x[1] = this->FocalPoint[1]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + } + } + + // Create y-shadows + // + if ( this->YShadows ) + { + for (i=0; i<2; i++) + { + x[0] = this->ModelBounds[0]; + x[1] = this->ModelBounds[i+2]; + x[2] = this->FocalPoint[2]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[1]; + x[1] = this->ModelBounds[i+2]; + x[2] = this->FocalPoint[2]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->FocalPoint[0]; + x[1] = this->ModelBounds[i+2]; + x[2] = this->ModelBounds[4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->FocalPoint[0]; + x[1] = this->ModelBounds[i+2]; + x[2] = this->ModelBounds[5]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + } + } + + // Create z-shadows + // + if ( this->ZShadows ) + { + for (i=0; i<2; i++) + { + x[0] = this->ModelBounds[0]; + x[1] = this->FocalPoint[1]; + x[2] = this->ModelBounds[i+4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->ModelBounds[1]; + x[1] = this->FocalPoint[1]; + x[2] = this->ModelBounds[i+4]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + + x[0] = this->FocalPoint[0]; + x[1] = this->ModelBounds[2]; + x[2] = this->ModelBounds[i+4]; + ptIds[0] = newPts->InsertNextPoint(x); + + x[0] = this->FocalPoint[0]; + x[1] = this->ModelBounds[3]; + x[2] = this->ModelBounds[i+4]; + ptIds[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,ptIds); + } + } + + // Update ourselves and release memory + // + this->Focus->GetPoints()->SetPoint(0,this->FocalPoint); + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +// Set the boundary of the 3D cursor. +void vtkCursor3D::SetModelBounds(double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax) +{ + if ( xmin != this->ModelBounds[0] || xmax != this->ModelBounds[1] || + ymin != this->ModelBounds[2] || ymax != this->ModelBounds[3] || + zmin != this->ModelBounds[4] || zmax != this->ModelBounds[5] ) + { + this->Modified(); + + this->ModelBounds[0] = xmin; this->ModelBounds[1] = xmax; + this->ModelBounds[2] = ymin; this->ModelBounds[3] = ymax; + this->ModelBounds[4] = zmin; this->ModelBounds[5] = zmax; + + for (int i=0; i<3; i++) + { + if ( this->ModelBounds[2*i] > this->ModelBounds[2*i+1] ) + { + this->ModelBounds[2*i] = this->ModelBounds[2*i+1]; + } + } + } +} + +void vtkCursor3D::SetFocalPoint(double x[3]) +{ + if ( x[0] == this->FocalPoint[0] && x[1] == this->FocalPoint[1] && + x[2] == this->FocalPoint[2] ) + { + return; + } + + this->Modified(); + + double v[3]; + for (int i=0; i<3; i++) + { + v[i] = x[i] - this->FocalPoint[i]; + this->FocalPoint[i] = x[i]; + + if ( this->TranslationMode ) + { + this->ModelBounds[2*i] += v[i]; + this->ModelBounds[2*i+1] += v[i]; + } + else if ( this->Wrap ) //wrap + { + this->FocalPoint[i] = this->ModelBounds[2*i] + + fmod((double)(this->FocalPoint[i]-this->ModelBounds[2*i]), + (double)(this->ModelBounds[2*i+1]-this->ModelBounds[2*i])); + } + else //clamp + { + if ( x[i] < this->ModelBounds[2*i] ) + { + this->FocalPoint[i] = this->ModelBounds[2*i]; + } + if ( x[i] > this->ModelBounds[2*i+1] ) + { + this->FocalPoint[i] = this->ModelBounds[2*i+1]; + } + } + } +} + +void vtkCursor3D::SetModelBounds(double bounds[6]) +{ + this->SetModelBounds(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], + bounds[5]); +} + +// Turn every part of the 3D cursor on. +void vtkCursor3D::AllOn() +{ + this->OutlineOn(); + this->AxesOn(); + this->XShadowsOn(); + this->YShadowsOn(); + this->ZShadowsOn(); +} + +// Turn every part of the 3D cursor off. +void vtkCursor3D::AllOff() +{ + this->OutlineOff(); + this->AxesOff(); + this->XShadowsOff(); + this->YShadowsOff(); + this->ZShadowsOff(); +} + +void vtkCursor3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ModelBounds: \n"; + os << indent << " Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n"; + + os << indent << "Focal Point: (" << this->FocalPoint[0] << ", " + << this->FocalPoint[1] << ", " + << this->FocalPoint[2] << ")\n"; + + os << indent << "Outline: " << (this->Outline ? "On\n" : "Off\n"); + os << indent << "Axes: " << (this->Axes ? "On\n" : "Off\n"); + os << indent << "XShadows: " << (this->XShadows ? "On\n" : "Off\n"); + os << indent << "YShadows: " << (this->YShadows ? "On\n" : "Off\n"); + os << indent << "ZShadows: " << (this->ZShadows ? "On\n" : "Off\n"); + os << indent << "Wrap: " << (this->Wrap ? "On\n" : "Off\n"); + os << indent << "Translation Mode: " + << (this->TranslationMode ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkCursor3D.h b/Graphics/vtkCursor3D.h new file mode 100644 index 0000000..ffcd44c --- /dev/null +++ b/Graphics/vtkCursor3D.h @@ -0,0 +1,142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCursor3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCursor3D - generate a 3D cursor representation +// .SECTION Description +// vtkCursor3D is an object that generates a 3D representation of a cursor. +// The cursor consists of a wireframe bounding box, three intersecting +// axes lines that meet at the cursor focus, and "shadows" or projections +// of the axes against the sides of the bounding box. Each of these +// components can be turned on/off. +// +// This filter generates two output datasets. The first (Output) is just the +// geometric representation of the cursor. The second (Focus) is a single +// point at the focal point. + +#ifndef __vtkCursor3D_h +#define __vtkCursor3D_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkCursor3D : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkCursor3D,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with model bounds = (-1,1,-1,1,-1,1), focal point = (0,0,0), + // all parts of cursor visible, and wrapping off. + static vtkCursor3D *New(); + + // Description: + // Set / get the boundary of the 3D cursor. + void SetModelBounds(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax); + void SetModelBounds(double bounds[6]); + vtkGetVectorMacro(ModelBounds,double,6); + + // Description: + // Set/Get the position of cursor focus. If translation mode is on, + // then the entire cursor (including bounding box, cursor, and shadows) + // is translated. Otherwise, the focal point will either be clamped to the + // bounding box, or wrapped, if Wrap is on. (Note: this behavior requires + // that the bounding box is set prior to the focal point.) + void SetFocalPoint(double x[3]); + void SetFocalPoint(double x, double y, double z) + { + double xyz[3]; + xyz[0] = x; xyz[1] = y; xyz[2] = z; + this->SetFocalPoint(xyz); + } + vtkGetVectorMacro(FocalPoint,double,3); + + // Description: + // Turn on/off the wireframe bounding box. + vtkSetMacro(Outline,int); + vtkGetMacro(Outline,int); + vtkBooleanMacro(Outline,int); + + // Description: + // Turn on/off the wireframe axes. + vtkSetMacro(Axes,int); + vtkGetMacro(Axes,int); + vtkBooleanMacro(Axes,int); + + // Description: + // Turn on/off the wireframe x-shadows. + vtkSetMacro(XShadows,int); + vtkGetMacro(XShadows,int); + vtkBooleanMacro(XShadows,int); + + // Description: + // Turn on/off the wireframe y-shadows. + vtkSetMacro(YShadows,int); + vtkGetMacro(YShadows,int); + vtkBooleanMacro(YShadows,int); + + // Description: + // Turn on/off the wireframe z-shadows. + vtkSetMacro(ZShadows,int); + vtkGetMacro(ZShadows,int); + vtkBooleanMacro(ZShadows,int); + + // Description: + // Enable/disable the translation mode. If on, changes in cursor position + // cause the entire widget to translate along with the cursor. + // By default, translation mode is off. + vtkSetMacro(TranslationMode,int); + vtkGetMacro(TranslationMode,int); + vtkBooleanMacro(TranslationMode,int); + + // Description: + // Turn on/off cursor wrapping. If the cursor focus moves outside the + // specified bounds, the cursor will either be restrained against the + // nearest "wall" (Wrap=off), or it will wrap around (Wrap=on). + vtkSetMacro(Wrap,int); + vtkGetMacro(Wrap,int); + vtkBooleanMacro(Wrap,int); + + // Description: + // Get the focus for this filter. + vtkPolyData *GetFocus() {return (vtkPolyData *)this->Focus;}; + + // Description: + // Turn every part of the 3D cursor on or off. + void AllOn(); + void AllOff(); + +protected: + vtkCursor3D(); + ~vtkCursor3D(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkPolyData *Focus; + double ModelBounds[6]; + double FocalPoint[3]; + int Outline; + int Axes; + int XShadows; + int YShadows; + int ZShadows; + int TranslationMode; + int Wrap; + +private: + vtkCursor3D(const vtkCursor3D&); // Not implemented. + void operator=(const vtkCursor3D&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkCurvatures.cxx b/Graphics/vtkCurvatures.cxx new file mode 100644 index 0000000..6ba58fd --- /dev/null +++ b/Graphics/vtkCurvatures.cxx @@ -0,0 +1,463 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCurvatures.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCurvatures.h" + +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataNormals.h" +#include "vtkPolygon.h" +#include "vtkTensor.h" +#include "vtkTriangle.h" + +vtkCxxRevisionMacro(vtkCurvatures, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkCurvatures); + +//------------------------------------------------------------------------------ +#if VTK3 +vtkCurvatures* vtkCurvatures::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkObjectFactory::CreateInstance("vtkCurvatures"); + if(ret) + { + return (vtkCurvatures*)ret; + } + // If the factory was unable to create the object, then create it here. + return new vtkCurvatures; +} +#endif +//-------------------------------------------------------// +vtkCurvatures::vtkCurvatures() +{ + this->CurvatureType = VTK_CURVATURE_GAUSS; + this->InvertMeanCurvature = 0; +} +//-------------------------------------------------------// +void vtkCurvatures::GetMeanCurvature(vtkPolyData *mesh) +{ + vtkDebugMacro("Start vtkCurvatures::GetMeanCurvature"); + + // Empty array check + if (mesh->GetNumberOfPolys()==0 || mesh->GetNumberOfPoints()==0) + { + vtkErrorMacro("No points/cells to operate on"); + return; + } + + int numPts = mesh->GetNumberOfPoints(); + + // vtkData + vtkIdList* vertices, *vertices_n, *neighbours; + + vtkTriangle* facet; + vtkTriangle* neighbour; + // create-allocate + vertices = vtkIdList::New(); + vertices_n = vtkIdList::New(); + neighbours = vtkIdList::New(); + facet = vtkTriangle::New(); + neighbour = vtkTriangle::New(); + vtkDoubleArray* meanCurvature = vtkDoubleArray::New(); + meanCurvature->SetName("Mean_Curvature"); + meanCurvature->SetNumberOfComponents(1); + meanCurvature->SetNumberOfTuples(numPts); + // Get the array so we can write to it directly + double *meanCurvatureData = meanCurvature->GetPointer(0); + // data + int v, v_l, v_r, v_o, f, F, n, nv;// n short for neighbor + + // create-allocate + double n_f[3]; // normal of facet (could be stored for later?) + double n_n[3]; // normal of edge + double t[3]; // to store the cross product of n_f n_n + double ore[3]; // origin of e + double end[3]; // end of e + double oth[3]; // third vertex necessary for comp of n + double vn0[3]; + double vn1[3]; // vertices for computation of neighbour's n + double vn2[3]; + double e[3]; // edge (oriented) + + double cs, sn; // cs: cos; sn sin + double angle, length, Af, Hf; // temporary store + + mesh->BuildLinks(); + //data init + f = 0; + F = mesh->GetNumberOfCells(); + // init, preallocate the mean curvature + int* num_neighb = new int[numPts]; + for (v = 0; v < numPts; v++) + { + meanCurvatureData[v] = 0.0; + num_neighb[v] = 0; + } + + // main loop + vtkDebugMacro(<<"Main loop: loop over facets such that id > id of neighb"); + vtkDebugMacro(<<"so that every edge comes only once"); + // + for (f = 0; f < F; f++) + { + mesh->GetCellPoints(f,vertices); + nv = vertices->GetNumberOfIds(); + + for (v = 0; v < nv; v++) + { + // get neighbour + v_l = vertices->GetId(v); + v_r = vertices->GetId((v+1) % nv); + v_o = vertices->GetId((v+2) % nv); + mesh->GetCellEdgeNeighbors(f,v_l,v_r,neighbours); + + // compute only if there is really ONE neighbour + // AND meanCurvature has not been computed yet! + // (ensured by n > f) + if (neighbours->GetNumberOfIds() == 1 && (n = neighbours->GetId(0)) > f) + { + // find 3 corners of f: in order! + mesh->GetPoint(v_l,ore); + mesh->GetPoint(v_r,end); + mesh->GetPoint(v_o,oth); + // compute normal of f + facet->ComputeNormal(ore,end,oth,n_f); + // compute common edge + e[0] = end[0]; e[1] = end[1]; e[2] = end[2]; + e[0] -= ore[0]; e[1] -= ore[1]; e[2] -= ore[2]; + length = double(vtkMath::Normalize(e)); + Af = double(facet->TriangleArea(ore,end,oth)); + // find 3 corners of n: in order! + mesh->GetCellPoints(n,vertices_n); + mesh->GetPoint(vertices_n->GetId(0),vn0); + mesh->GetPoint(vertices_n->GetId(1),vn1); + mesh->GetPoint(vertices_n->GetId(2),vn2); + Af += double(facet->TriangleArea(vn0,vn1,vn2)); + // compute normal of n + neighbour->ComputeNormal(vn0,vn1,vn2,n_n); + // the cosine is n_f * n_n + cs = double(vtkMath::Dot(n_f,n_n)); + // the sin is (n_f x n_n) * e + vtkMath::Cross(n_f,n_n,t); + sn = double(vtkMath::Dot(t,e)); + // signed angle in [-pi,pi] + if (sn!=0.0 || cs!=0.0) + { + angle = atan2(sn,cs); + Hf = length*angle; + } + else + { + Hf = 0.0; + } + // add weighted Hf to scalar at v_l and v_r + if (Af!=0.0) + { + (Hf /= Af) *=3.0; + } + meanCurvatureData[v_l] += Hf; + meanCurvatureData[v_r] += Hf; + num_neighb[v_l] += 1; + num_neighb[v_r] += 1; + } + } + } + + // put curvature in vtkArray + for (v = 0; v < numPts; v++) + { + if (num_neighb[v]>0) + { + Hf = 0.5*meanCurvatureData[v]/(double)num_neighb[v]; + if (this->InvertMeanCurvature) + { + meanCurvatureData[v] = -Hf; + } + else + { + meanCurvatureData[v] = Hf; + } + } + else + { + meanCurvatureData[v] = 0.0; + } + } + + mesh->GetPointData()->AddArray(meanCurvature); + mesh->GetPointData()->SetActiveScalars("Mean_Curvature"); + + vtkDebugMacro("Set Values of Mean Curvature: Done"); + // clean + vertices ->Delete(); + vertices_n->Delete(); + neighbours->Delete(); + facet ->Delete(); + neighbour ->Delete(); + + if (meanCurvature) meanCurvature->Delete(); + if (num_neighb) delete [] num_neighb; +}; +//-------------------------------------------- +#define CLAMP_MACRO(v) ((v)<(-1) ? (-1) : (v) > (1) ? (1) : v) +void vtkCurvatures::GetGaussCurvature(vtkPolyData *output) +{ + vtkDebugMacro("Start vtkCurvatures::GetGaussCurvature()"); + // vtk data + vtkCellArray* facets = output->GetPolys(); + + // Empty array check + if (output->GetNumberOfPolys()==0 || output->GetNumberOfPoints()==0) + { + vtkErrorMacro("No points/cells to operate on"); + return; + } + + vtkTriangle* facet = vtkTriangle::New(); + + // other data + vtkIdType Nv = output->GetNumberOfPoints(); + + double* K = new double[Nv]; + double* dA = new double[Nv]; + double pi2 = 2.0*vtkMath::Pi(); + for (int k = 0; k < Nv; k++) + { + K[k] = pi2; + dA[k] = 0.0; + } + + double v0[3], v1[3], v2[3], e0[3], e1[3], e2[3]; + + double A, alpha0, alpha1, alpha2; + + vtkIdType f, *vert=0; + facets->InitTraversal(); + while (facets->GetNextCell(f,vert)) + { + output->GetPoint(vert[0],v0); + output->GetPoint(vert[1],v1); + output->GetPoint(vert[2],v2); + // edges + e0[0] = v1[0] ; e0[1] = v1[1] ; e0[2] = v1[2] ; + e0[0] -= v0[0]; e0[1] -= v0[1]; e0[2] -= v0[2]; + + e1[0] = v2[0] ; e1[1] = v2[1] ; e1[2] = v2[2] ; + e1[0] -= v1[0]; e1[1] -= v1[1]; e1[2] -= v1[2]; + + e2[0] = v0[0] ; e2[1] = v0[1] ; e2[2] = v0[2] ; + e2[0] -= v2[0]; e2[1] -= v2[1]; e2[2] -= v2[2]; + + // normalise + vtkMath::Normalize(e0); vtkMath::Normalize(e1); vtkMath::Normalize(e2); + // angles + // I get lots of acos domain errors so clamp the value to +/-1 as the + // normalize function can return 1.000000001 etc (I think) + double ac1 = vtkMath::Dot(e1,e2); + double ac2 = vtkMath::Dot(e2,e0); + double ac3 = vtkMath::Dot(e0,e1); + alpha0 = acos(-CLAMP_MACRO(ac1)); + alpha1 = acos(-CLAMP_MACRO(ac2)); + alpha2 = acos(-CLAMP_MACRO(ac3)); + + // surf. area + A = double(facet->TriangleArea(v0,v1,v2)); + // UPDATE + dA[vert[0]] += A; + dA[vert[1]] += A; + dA[vert[2]] += A; + K[vert[0]] -= alpha1; + K[vert[1]] -= alpha2; + K[vert[2]] -= alpha0; + } + + int numPts = output->GetNumberOfPoints(); + // put curvature in vtkArray + vtkDoubleArray* gaussCurvature = vtkDoubleArray::New(); + gaussCurvature->SetName("Gauss_Curvature"); + gaussCurvature->SetNumberOfComponents(1); + gaussCurvature->SetNumberOfTuples(numPts); + double *gaussCurvatureData = gaussCurvature->GetPointer(0); + + for (int v = 0; v < Nv; v++) + { + if (dA[v]>0.0) + { + gaussCurvatureData[v] = 3.0*K[v]/dA[v]; + } + else + { + gaussCurvatureData[v] = 0.0; + } + } + + output->GetPointData()->AddArray(gaussCurvature); + output->GetPointData()->SetActiveScalars("Gauss_Curvature"); + + vtkDebugMacro("Set Values of Gauss Curvature: Done"); + /*******************************************************/ + if (facet) facet->Delete(); + if (K) delete [] K; + if (dA) delete [] dA; + if (gaussCurvature) gaussCurvature->Delete(); + /*******************************************************/ +}; + +void vtkCurvatures::GetMaximumCurvature(vtkPolyData *input,vtkPolyData *output) +{ + this->GetGaussCurvature(output); + this->GetMeanCurvature(output); + + vtkIdType numPts = input->GetNumberOfPoints(); + + vtkDoubleArray *maximumCurvature = vtkDoubleArray::New(); + maximumCurvature->SetNumberOfComponents(1); + maximumCurvature->SetNumberOfTuples(numPts); + maximumCurvature->SetName("Maximum_Curvature"); + output->GetPointData()->AddArray(maximumCurvature); + output->GetPointData()->SetActiveScalars("Maximum_Curvature"); + maximumCurvature->Delete(); + + vtkDoubleArray *gauss = (vtkDoubleArray *)output->GetPointData()->GetArray("Gauss_Curvature"); + vtkDoubleArray *mean = (vtkDoubleArray *)output->GetPointData()->GetArray("Mean_Curvature"); + double k, h, k_max,tmp; + + for (vtkIdType i = 0; iGetComponent(i,0); + h = mean->GetComponent(i,0); + tmp = h*h - k; + if (tmp >= 0) + { + k_max = h + sqrt(tmp); + } + else + { + vtkDebugMacro(<< "Maximum Curvature undefined at point: " << i); + // k_max can be any real number. Undefined points will be indistinguishable + // from points that actually have a k_max == 0 + k_max = 0; + } + maximumCurvature->SetComponent(i, 0, k_max); + } +} + +void vtkCurvatures::GetMinimumCurvature(vtkPolyData *input,vtkPolyData *output) +{ + this->GetGaussCurvature(output); + this->GetMeanCurvature(output); + + vtkIdType numPts = input->GetNumberOfPoints(); + + vtkDoubleArray *minimumCurvature = vtkDoubleArray::New(); + minimumCurvature->SetNumberOfComponents(1); + minimumCurvature->SetNumberOfTuples(numPts); + minimumCurvature->SetName("Minimum_Curvature"); + output->GetPointData()->AddArray(minimumCurvature); + output->GetPointData()->SetActiveScalars("Minimum_Curvature"); + minimumCurvature->Delete(); + + vtkDoubleArray *gauss = (vtkDoubleArray *)output->GetPointData()->GetArray("Gauss_Curvature"); + vtkDoubleArray *mean = (vtkDoubleArray *)output->GetPointData()->GetArray("Mean_Curvature"); + double k, h, k_min,tmp; + + for (vtkIdType i = 0; iGetComponent(i,0); + h = mean->GetComponent(i,0); + tmp = h*h - k; + if (tmp >= 0) + { + k_min = h - sqrt(tmp); + } + else + { + vtkDebugMacro(<< "Minimum Curvature undefined at point: " << i); + // k_min can be any real number. Undefined points will be indistinguishable + // from points that actually have a k_min == 0 + k_min = 0; + } + minimumCurvature->SetComponent(i, 0, k_min); + } +} + +//------------------------------------------------------- +int vtkCurvatures::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Null input check + if (!input) + { + return 0; + } + + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetFieldData()->PassData(input->GetFieldData()); + + //-------------------------------------------------------// + // Set Curvatures as PointData Scalars // + //-------------------------------------------------------// + + if ( this->CurvatureType == VTK_CURVATURE_GAUSS ) + { + this->GetGaussCurvature(output); + } + else if ( this->CurvatureType == VTK_CURVATURE_MEAN ) + { + this->GetMeanCurvature(output); + } + else if ( this->CurvatureType == VTK_CURVATURE_MAXIMUM ) + { + this->GetMaximumCurvature(input, output); + } + else if ( this->CurvatureType == VTK_CURVATURE_MINIMUM ) + { + this->GetMinimumCurvature(input, output); + } + else + { + vtkErrorMacro("Only Gauss, Mean, Max, and Min Curvature type available"); + return 1; + } + + return 1; +} +/*-------------------------------------------------------*/ +void vtkCurvatures::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "CurvatureType: " << this->CurvatureType << "\n"; + os << indent << "InvertMeanCurvature: " << this->InvertMeanCurvature << "\n"; +} diff --git a/Graphics/vtkCurvatures.h b/Graphics/vtkCurvatures.h new file mode 100644 index 0000000..b8d4041 --- /dev/null +++ b/Graphics/vtkCurvatures.h @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCurvatures.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCurvatures - compute curvatures (Gauss and mean) of a Polydata object +// .SECTION Description +// vtkCurvatures takes a polydata input and computes the curvature of the +// mesh at each point. Four possible methods of computation are available : +// +// Gauss Curvature +// discrete Gauss curvature (K) computation, +// \f$K(vertex v) = 2*PI-\sum_{facet neighbs f of v} (angle_f at v)\f$ +// The contribution of every facet is for the moment weighted by \f$Area(facet)/3\f$ +// The units of Gaussian Curvature are \f$[1/m^2]\f$ +// +// Mean Curvature +// \f$H(vertex v) = average over edges neighbs e of H(e)\f$ +// \f$H(edge e) = length(e)*dihedral_angle(e)\f$ +// NB: dihedral_angle is the ORIENTED angle between -PI and PI, +// this means that the surface is assumed to be orientable +// the computation creates the orientation +// The units of Mean Curvature are [1/m] +// +// Maximum (\f$k_max\f$) and Minimum (\f$k_min\f$) Principal Curvatures +// \f$k_max = H + sqrt(H^2 - K)\f$ +// \f$k_min = H - sqrt(H^2 - K)\f$ +// Excepting spherical and planar surfaces which have equal principal curvatures, +// the curvature at a point on a surface varies with the direction one "sets off" +// from the point. For all directions, the curvature will pass through two extrema: +// a minimum (\f$k_min\f$) and a maximum (\f$k_max\f$) which occur at mutually orthogonal +// directions to each other. +// +// NB. The sign of the Gauss curvature is a geometric ivariant, it should be +ve +// when the surface looks like a sphere, -ve when it looks like a saddle, +// however, the sign of the Mean curvature is not, it depends on the +// convention for normals - This code assumes that normals point outwards (ie +// from the surface of a sphere outwards). If a given mesh produces curvatures +// of opposite senses then the flag InvertMeanCurvature can be set and the +// Curvature reported by the Mean calculation will be inverted. +// +// .SECTION Thanks +// Philip Batchelor philipp.batchelor@kcl.ac.uk for creating and contributing +// the class and Andrew Maclean a.maclean@acfr.usyd.edu.au for cleanups and +// fixes. Thanks also to Goodwin Lawlor for contributing patch to calculate +// principal curvatures + +// +// .SECTION See Also +// + +#ifndef __vtkCurvatures_h +#define __vtkCurvatures_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_CURVATURE_GAUSS 0 +#define VTK_CURVATURE_MEAN 1 +#define VTK_CURVATURE_MAXIMUM 2 +#define VTK_CURVATURE_MINIMUM 3 + +class VTK_GRAPHICS_EXPORT vtkCurvatures : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkCurvatures,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with curvature type set to Gauss + static vtkCurvatures *New(); + + // Description: + // Set/Get Curvature type + // VTK_CURVATURE_GAUSS: Gaussian curvature, stored as + // DataArray "Gauss_Curvature" + // VTK_CURVATURE_MEAN : Mean curvature, stored as + // DataArray "Mean_Curvature" + vtkSetMacro(CurvatureType,int); + vtkGetMacro(CurvatureType,int); + void SetCurvatureTypeToGaussian() + { this->SetCurvatureType(VTK_CURVATURE_GAUSS); } + void SetCurvatureTypeToMean() + { this->SetCurvatureType(VTK_CURVATURE_MEAN); } + void SetCurvatureTypeToMaximum() + { this->SetCurvatureType(VTK_CURVATURE_MAXIMUM); } + void SetCurvatureTypeToMinimum() + { this->SetCurvatureType(VTK_CURVATURE_MINIMUM); } + + // Description: + // Set/Get the flag which inverts the mean curvature calculation for + // meshes with inward pointing normals (default false) + vtkSetMacro(InvertMeanCurvature,int); + vtkGetMacro(InvertMeanCurvature,int); + vtkBooleanMacro(InvertMeanCurvature,int); +protected: + vtkCurvatures(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // Description: + // discrete Gauss curvature (K) computation, + // cf http://www-ipg.umds.ac.uk/p.batchelor/curvatures/curvatures.html + void GetGaussCurvature(vtkPolyData *output); + + // discrete Mean curvature (H) computation, + // cf http://www-ipg.umds.ac.uk/p.batchelor/curvatures/curvatures.html + void GetMeanCurvature(vtkPolyData *output); + + //Description: + // Maximum principal curvature \f$k_max = H + sqrt(H^2 -K)\f$ + void GetMaximumCurvature(vtkPolyData *input, vtkPolyData *output); + + //Description: + // Minimum principal curvature \f$k_min = H - sqrt(H^2 -K)\f$ + void GetMinimumCurvature(vtkPolyData *input, vtkPolyData *output); + + + // Vars + int CurvatureType; + int InvertMeanCurvature; + +private: + vtkCurvatures(const vtkCurvatures&); // Not implemented. + void operator=(const vtkCurvatures&); // Not implemented. + +}; + +#endif + + diff --git a/Graphics/vtkCutter.cxx b/Graphics/vtkCutter.cxx new file mode 100644 index 0000000..f73d767 --- /dev/null +++ b/Graphics/vtkCutter.cxx @@ -0,0 +1,999 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCutter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCutter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkContourValues.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkGenericCell.h" +#include "vtkGridSynchronizedTemplates3D.h" +#include "vtkImageData.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkRectilinearSynchronizedTemplates.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkSynchronizedTemplates3D.h" +#include "vtkSynchronizedTemplatesCutter3D.h" +#include "vtkUnstructuredGrid.h" + +#include + +vtkCxxRevisionMacro(vtkCutter, "$Revision: 1.85 $"); +vtkStandardNewMacro(vtkCutter); +vtkCxxSetObjectMacro(vtkCutter,CutFunction,vtkImplicitFunction); + +// Construct with user-specified implicit function; initial value of 0.0; and +// generating cut scalars turned off. +vtkCutter::vtkCutter(vtkImplicitFunction *cf) +{ + this->ContourValues = vtkContourValues::New(); + this->SortBy = VTK_SORT_BY_VALUE; + this->CutFunction = cf; + this->GenerateCutScalars = 0; + this->Locator = NULL; + + this->SynchronizedTemplates3D = vtkSynchronizedTemplates3D::New(); + this->SynchronizedTemplatesCutter3D = vtkSynchronizedTemplatesCutter3D::New(); + this->GridSynchronizedTemplates = vtkGridSynchronizedTemplates3D::New(); + this->RectilinearSynchronizedTemplates = vtkRectilinearSynchronizedTemplates::New(); +} + +vtkCutter::~vtkCutter() +{ + this->ContourValues->Delete(); + this->SetCutFunction(NULL); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + this->SynchronizedTemplates3D->Delete(); + this->SynchronizedTemplatesCutter3D->Delete(); + this->GridSynchronizedTemplates->Delete(); + this->RectilinearSynchronizedTemplates->Delete(); +} + +// Overload standard modified time function. If cut functions is modified, +// or contour values modified, then this object is modified as well. +unsigned long vtkCutter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long contourValuesMTime=this->ContourValues->GetMTime(); + unsigned long time; + + mTime = ( contourValuesMTime > mTime ? contourValuesMTime : mTime ); + + if ( this->CutFunction != NULL ) + { + time = this->CutFunction->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +void vtkCutter::StructuredPointsCutter(vtkDataSet *dataSetInput, + vtkPolyData *thisOutput, + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkImageData *input = vtkImageData::SafeDownCast(dataSetInput); + vtkPolyData *output; + vtkIdType numPts = input->GetNumberOfPoints(); + + if (numPts < 1) + { + return; + } + + int numContours = this->GetNumberOfContours(); + + // for one contour we use the SyncTempCutter which is faster and has a + // smaller memory footprint + if (numContours == 1) + { + this->SynchronizedTemplatesCutter3D->SetCutFunction(this->CutFunction); + this->SynchronizedTemplatesCutter3D->SetValue(0, this->GetValue(0)); + this->SynchronizedTemplatesCutter3D->ProcessRequest(request,inputVector,outputVector); + return; + } + + // otherwise compute scalar data then contour + vtkFloatArray *cutScalars = vtkFloatArray::New(); + cutScalars->SetNumberOfTuples(numPts); + cutScalars->SetName("cutScalars"); + + vtkImageData *contourData = vtkImageData::New(); + contourData->ShallowCopy(input); + if (this->GenerateCutScalars) + { + contourData->GetPointData()->SetScalars(cutScalars); + } + else + { + contourData->GetPointData()->AddArray(cutScalars); + } + + int i,j,k; + double scalar; + double x[3]; + int *ext = input->GetExtent(); + double *origin = input->GetOrigin(); + double *spacing = input->GetSpacing(); + int count = 0; + for (k = ext[4]; k <= ext[5]; ++k) + { + x[2] = origin[2] + spacing[2]*k; + for (j = ext[2]; j <= ext[3]; ++j) + { + x[1] = origin[1] + spacing[1]*j; + for (i = ext[0]; i <= ext[1]; i++) + { + x[0] = origin[0] + spacing[0]*i; + scalar = this->CutFunction->FunctionValue(x); + cutScalars->SetComponent(count, 0, scalar); + count++; + } + } + } + + this->SynchronizedTemplates3D->SetInput(contourData); + this->SynchronizedTemplates3D-> + SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,"cutScalars"); + for (i = 0; i < numContours; i++) + { + this->SynchronizedTemplates3D->SetValue(i, this->GetValue(i)); + } + this->SynchronizedTemplates3D->ComputeScalarsOff(); + this->SynchronizedTemplates3D->ComputeNormalsOff(); + output = this->SynchronizedTemplates3D->GetOutput(); + this->SynchronizedTemplates3D->Update(); + output->Register(this); + + thisOutput->CopyStructure(output); + thisOutput->GetPointData()->ShallowCopy(output->GetPointData()); + thisOutput->GetCellData()->ShallowCopy(output->GetCellData()); + output->UnRegister(this); + + cutScalars->Delete(); + contourData->Delete(); +} + +void vtkCutter::StructuredGridCutter(vtkDataSet *dataSetInput, + vtkPolyData *thisOutput) +{ + vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast(dataSetInput); + vtkPolyData *output; + vtkIdType numPts = input->GetNumberOfPoints(); + + if (numPts < 1) + { + return; + } + + vtkFloatArray *cutScalars = vtkFloatArray::New(); + cutScalars->SetNumberOfTuples(numPts); + cutScalars->SetName("cutScalars"); + + vtkStructuredGrid *contourData = vtkStructuredGrid::New(); + contourData->ShallowCopy(input); + if (this->GenerateCutScalars) + { + contourData->GetPointData()->SetScalars(cutScalars); + } + else + { + contourData->GetPointData()->AddArray(cutScalars); + } + + int i; + double scalar; + for (i = 0; i < numPts; i++) + { + scalar = this->CutFunction->FunctionValue(input->GetPoint(i)); + cutScalars->SetComponent(i, 0, scalar); + } + int numContours = this->GetNumberOfContours(); + + this->GridSynchronizedTemplates->SetInput(contourData); + this->GridSynchronizedTemplates-> + SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,"cutScalars"); + for (i = 0; i < numContours; i++) + { + this->GridSynchronizedTemplates->SetValue(i, this->GetValue(i)); + } + this->GridSynchronizedTemplates->ComputeScalarsOff(); + this->GridSynchronizedTemplates->ComputeNormalsOff(); + output = this->GridSynchronizedTemplates->GetOutput(); + this->GridSynchronizedTemplates->Update(); + output->Register(this); + + thisOutput->ShallowCopy(output); + output->UnRegister(this); + + cutScalars->Delete(); + contourData->Delete(); +} + +void vtkCutter::RectilinearGridCutter(vtkDataSet *dataSetInput, + vtkPolyData *thisOutput) +{ + vtkRectilinearGrid *input = vtkRectilinearGrid::SafeDownCast(dataSetInput); + vtkPolyData *output; + vtkIdType numPts = input->GetNumberOfPoints(); + + if (numPts < 1) + { + return; + } + + vtkFloatArray *cutScalars = vtkFloatArray::New(); + cutScalars->SetNumberOfTuples(numPts); + cutScalars->SetName("cutScalars"); + + vtkRectilinearGrid *contourData = vtkRectilinearGrid::New(); + contourData->ShallowCopy(input); + if (this->GenerateCutScalars) + { + contourData->GetPointData()->SetScalars(cutScalars); + } + else + { + contourData->GetPointData()->AddArray(cutScalars); + } + + int i; + double scalar; + for (i = 0; i < numPts; i++) + { + scalar = this->CutFunction->FunctionValue(input->GetPoint(i)); + cutScalars->SetComponent(i, 0, scalar); + } + int numContours = this->GetNumberOfContours(); + + this->RectilinearSynchronizedTemplates->SetInput(contourData); + this->RectilinearSynchronizedTemplates-> + SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,"cutScalars"); + for (i = 0; i < numContours; i++) + { + this->RectilinearSynchronizedTemplates->SetValue(i, this->GetValue(i)); + } + this->RectilinearSynchronizedTemplates->ComputeScalarsOff(); + this->RectilinearSynchronizedTemplates->ComputeNormalsOff(); + output = this->RectilinearSynchronizedTemplates->GetOutput(); + this->RectilinearSynchronizedTemplates->Update(); + output->Register(this); + + thisOutput->ShallowCopy(output); + output->UnRegister(this); + + cutScalars->Delete(); + contourData->Delete(); +} + +// Cut through data generating surface. +// +int vtkCutter::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<< "Executing cutter"); + + if (!this->CutFunction) + { + vtkErrorMacro("No cut function specified"); + return 0; + } + + if ( input->GetNumberOfPoints() < 1 ) + { + return 1; + } + + if (input->GetDataObjectType() == VTK_STRUCTURED_POINTS || + input->GetDataObjectType() == VTK_IMAGE_DATA) + { + if ( input->GetCell(0) && input->GetCell(0)->GetCellDimension() >= 3 ) + { + this->StructuredPointsCutter(input, output, request, inputVector, outputVector); + return 1; + } + } + if (input->GetDataObjectType() == VTK_STRUCTURED_GRID) + { + if (input->GetCell(0)) + { + int dim = input->GetCell(0)->GetCellDimension(); + // only do 3D structured grids (to be extended in the future) + if (dim >= 3) + { + this->StructuredGridCutter(input, output); + return 1; + } + } + } + if (input->GetDataObjectType() == VTK_RECTILINEAR_GRID) + { + int dim = ((vtkRectilinearGrid*)input)->GetDataDimension(); + if ( dim == 3 ) + { + this->RectilinearGridCutter(input, output); + return 1; + } + } + + if (input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID) + { + vtkDebugMacro(<< "Executing Unstructured Grid Cutter"); + this->UnstructuredGridCutter(input, output); + } + else + { + vtkDebugMacro(<< "Executing DataSet Cutter"); + this->DataSetCutter(input, output); + } + + return 1; +} + +void vtkCutter::GetCellTypeDimensions(unsigned char* cellTypeDimensions) +{ + // Assume most cells will be 3d. + memset(cellTypeDimensions, 3, VTK_NUMBER_OF_CELL_TYPES); + cellTypeDimensions[VTK_EMPTY_CELL] = 0; + cellTypeDimensions[VTK_VERTEX] = 0; + cellTypeDimensions[VTK_POLY_VERTEX] = 0; + cellTypeDimensions[VTK_LINE] = 1; + cellTypeDimensions[VTK_POLY_LINE] = 1; + cellTypeDimensions[VTK_QUADRATIC_EDGE] = 1; + cellTypeDimensions[VTK_PARAMETRIC_CURVE] = 1; + cellTypeDimensions[VTK_HIGHER_ORDER_EDGE] = 1; + cellTypeDimensions[VTK_TRIANGLE] = 2; + cellTypeDimensions[VTK_TRIANGLE_STRIP] = 2; + cellTypeDimensions[VTK_POLYGON] = 2; + cellTypeDimensions[VTK_PIXEL] = 2; + cellTypeDimensions[VTK_QUAD] = 2; + cellTypeDimensions[VTK_QUADRATIC_TRIANGLE] = 2; + cellTypeDimensions[VTK_QUADRATIC_QUAD] = 2; + cellTypeDimensions[VTK_PARAMETRIC_SURFACE] = 2; + cellTypeDimensions[VTK_PARAMETRIC_TRI_SURFACE] = 2; + cellTypeDimensions[VTK_PARAMETRIC_QUAD_SURFACE] = 2; + cellTypeDimensions[VTK_HIGHER_ORDER_TRIANGLE] = 2; + cellTypeDimensions[VTK_HIGHER_ORDER_QUAD] = 2; + cellTypeDimensions[VTK_HIGHER_ORDER_POLYGON] = 2; +} + + +void vtkCutter::DataSetCutter(vtkDataSet *input, vtkPolyData *output) +{ + vtkIdType cellId, i; + int iter; + vtkPoints *cellPts; + vtkDoubleArray *cellScalars; + vtkGenericCell *cell; + vtkCellArray *newVerts, *newLines, *newPolys; + vtkPoints *newPoints; + vtkDoubleArray *cutScalars; + double value, s; + vtkIdType estimatedSize, numCells=input->GetNumberOfCells(); + vtkIdType numPts=input->GetNumberOfPoints(); + int numCellPts; + vtkPointData *inPD, *outPD; + vtkCellData *inCD=input->GetCellData(), *outCD=output->GetCellData(); + vtkIdList *cellIds; + int numContours=this->ContourValues->GetNumberOfContours(); + int abortExecute=0; + + cellScalars=vtkDoubleArray::New(); + + // Create objects to hold output of contour operation + // + estimatedSize = (vtkIdType) pow ((double) numCells, .75) * numContours; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPoints = vtkPoints::New(); + newPoints->Allocate(estimatedSize,estimatedSize/2); + newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize,estimatedSize/2); + newLines = vtkCellArray::New(); + newLines->Allocate(estimatedSize,estimatedSize/2); + newPolys = vtkCellArray::New(); + newPolys->Allocate(estimatedSize,estimatedSize/2); + cutScalars = vtkDoubleArray::New(); + cutScalars->SetNumberOfTuples(numPts); + + // Interpolate data along edge. If generating cut scalars, do necessary setup + if ( this->GenerateCutScalars ) + { + inPD = vtkPointData::New(); + inPD->ShallowCopy(input->GetPointData());//copies original attributes + inPD->SetScalars(cutScalars); + } + else + { + inPD = input->GetPointData(); + } + outPD = output->GetPointData(); + outPD->InterpolateAllocate(inPD,estimatedSize,estimatedSize/2); + outCD->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPoints, input->GetBounds()); + + // Loop over all points evaluating scalar function at each point + // + for ( i=0; i < numPts; i++ ) + { + s = this->CutFunction->FunctionValue(input->GetPoint(i)); + cutScalars->SetComponent(i,0,s); + } + + // Compute some information for progress methods + // + cell = vtkGenericCell::New(); + vtkIdType numCuts = numContours*numCells; + vtkIdType progressInterval = numCuts/20 + 1; + int cut=0; + + if ( this->SortBy == VTK_SORT_BY_CELL ) + { + // Loop over all contour values. Then for each contour value, + // loop over all cells. + // + // This is going to have a problem if the input has 2D and 3D cells. + // I am fixing a bug where cell data is scrambled becauses with + // vtkPolyData output, verts and lines have lower cell ids than triangles. + for (iter=0; iter < numContours && !abortExecute; iter++) + { + // Loop over all cells; get scalar values for all cell points + // and process each cell. + // + for (cellId=0; cellId < numCells && !abortExecute; cellId++) + { + if ( !(++cut % progressInterval) ) + { + vtkDebugMacro(<<"Cutting #" << cut); + this->UpdateProgress ((double)cut/numCuts); + abortExecute = this->GetAbortExecute(); + } + + input->GetCell(cellId,cell); + cellPts = cell->GetPoints(); + cellIds = cell->GetPointIds(); + + numCellPts = cellPts->GetNumberOfPoints(); + cellScalars->SetNumberOfTuples(numCellPts); + for (i=0; i < numCellPts; i++) + { + s = cutScalars->GetComponent(cellIds->GetId(i),0); + cellScalars->SetTuple(i,&s); + } + + value = this->ContourValues->GetValue(iter); + cell->Contour(value, cellScalars, this->Locator, + newVerts, newLines, newPolys, inPD, outPD, + inCD, cellId, outCD); + + } // for all cells + } // for all contour values + } // sort by cell + + else // VTK_SORT_BY_VALUE: + { + // Three passes over the cells to process lower dimensional cells first. + // For poly data output cells need to be added in the order: + // verts, lines and then polys, or cell data gets mixed up. + // A better solution is to have an unstructured grid output. + // I create a table that maps cell type to cell dimensionality, + // because I need a fast way to get cell dimensionality. + // This assumes GetCell is slow and GetCellType is fast. + // I do not like hard coding a list of cell types here, + // but I do not want to add GetCellDimension(vtkIdType cellId) + // to the vtkDataSet API. Since I anticipate that the output + // will change to vtkUnstructuredGrid. This temporary solution + // is acceptable. + // + int cellType; + unsigned char cellTypeDimensions[VTK_NUMBER_OF_CELL_TYPES]; + vtkCutter::GetCellTypeDimensions(cellTypeDimensions); + int dimensionality; + // We skip 0d cells (points), because they cannot be cut (generate no data). + for (dimensionality = 1; dimensionality <= 3; ++dimensionality) + { + // Loop over all cells; get scalar values for all cell points + // and process each cell. + // + for (cellId=0; cellId < numCells && !abortExecute; cellId++) + { + // I assume that "GetCellType" is fast. + cellType = input->GetCellType(cellId); + if (cellType >= VTK_NUMBER_OF_CELL_TYPES) + { // Protect against new cell types added. + vtkErrorMacro("Unknown cell type " << cellType); + continue; + } + if (cellTypeDimensions[cellType] != dimensionality) + { + continue; + } + input->GetCell(cellId,cell); + cellPts = cell->GetPoints(); + cellIds = cell->GetPointIds(); + + numCellPts = cellPts->GetNumberOfPoints(); + cellScalars->SetNumberOfTuples(numCellPts); + for (i=0; i < numCellPts; i++) + { + s = cutScalars->GetComponent(cellIds->GetId(i),0); + cellScalars->SetTuple(i,&s); + } + + // Loop over all contour values. + for (iter=0; iter < numContours && !abortExecute; iter++) + { + if (dimensionality == 3 && !(++cut % progressInterval) ) + { + vtkDebugMacro(<<"Cutting #" << cut); + this->UpdateProgress ((double)cut/numCuts); + abortExecute = this->GetAbortExecute(); + } + value = this->ContourValues->GetValue(iter); + cell->Contour(value, cellScalars, this->Locator, + newVerts, newLines, newPolys, inPD, outPD, + inCD, cellId, outCD); + + } // for all contour values + } // for all cells + } // for all dimensions. + } // sort by value + + // Update ourselves. Because we don't know upfront how many verts, lines, + // polys we've created, take care to reclaim memory. + // + cell->Delete(); + cellScalars->Delete(); + cutScalars->Delete(); + + if ( this->GenerateCutScalars ) + { + inPD->Delete(); + } + + output->SetPoints(newPoints); + newPoints->Delete(); + + if (newVerts->GetNumberOfCells()) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if (newLines->GetNumberOfCells()) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if (newPolys->GetNumberOfCells()) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + this->Locator->Initialize();//release any extra memory + output->Squeeze(); +} + +void vtkCutter::UnstructuredGridCutter(vtkDataSet *input, vtkPolyData *output) +{ + vtkIdType cellId, i; + int iter; + vtkDoubleArray *cellScalars; + vtkCellArray *newVerts, *newLines, *newPolys; + vtkPoints *newPoints; + vtkDoubleArray *cutScalars; + double value, s; + vtkIdType estimatedSize, numCells=input->GetNumberOfCells(); + vtkIdType numPts=input->GetNumberOfPoints(); + vtkIdType cellArrayIt = 0; + int numCellPts; + vtkPointData *inPD, *outPD; + vtkCellData *inCD=input->GetCellData(), *outCD=output->GetCellData(); + vtkIdList *cellIds; + int numContours = this->ContourValues->GetNumberOfContours(); + int abortExecute = 0; + + double range[2]; + + // Create objects to hold output of contour operation + // + estimatedSize = (vtkIdType) pow ((double) numCells, .75) * numContours; + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPoints = vtkPoints::New(); + newPoints->Allocate(estimatedSize,estimatedSize/2); + newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize,estimatedSize/2); + newLines = vtkCellArray::New(); + newLines->Allocate(estimatedSize,estimatedSize/2); + newPolys = vtkCellArray::New(); + newPolys->Allocate(estimatedSize,estimatedSize/2); + cutScalars = vtkDoubleArray::New(); + cutScalars->SetNumberOfTuples(numPts); + + // Interpolate data along edge. If generating cut scalars, do necessary setup + if ( this->GenerateCutScalars ) + { + inPD = vtkPointData::New(); + inPD->ShallowCopy(input->GetPointData());//copies original attributes + inPD->SetScalars(cutScalars); + } + else + { + inPD = input->GetPointData(); + } + outPD = output->GetPointData(); + outPD->InterpolateAllocate(inPD,estimatedSize,estimatedSize/2); + outCD->CopyAllocate(inCD,estimatedSize,estimatedSize/2); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPoints, input->GetBounds()); + + // Loop over all points evaluating scalar function at each point + // + for ( i=0; i < numPts; i++ ) + { + s = this->CutFunction->FunctionValue(input->GetPoint(i)); + cutScalars->SetComponent(i,0,s); + } + + // Compute some information for progress methods + // + vtkIdType numCuts = numContours*numCells; + vtkIdType progressInterval = numCuts/20 + 1; + int cut=0; + + vtkUnstructuredGrid *grid = (vtkUnstructuredGrid *)input; + vtkIdType *cellArrayPtr = grid->GetCells()->GetPointer(); + double *scalarArrayPtr = cutScalars->GetPointer(0); + double tempScalar; + cellScalars = cutScalars->NewInstance(); + cellScalars->SetNumberOfComponents(cutScalars->GetNumberOfComponents()); + cellScalars->Allocate(VTK_CELL_SIZE*cutScalars->GetNumberOfComponents()); + + if ( this->SortBy == VTK_SORT_BY_CELL ) + { + // Loop over all contour values. Then for each contour value, + // loop over all cells. + // + for (iter=0; iter < numContours && !abortExecute; iter++) + { + // Loop over all cells; get scalar values for all cell points + // and process each cell. + // + for (cellId=0; cellId < numCells && !abortExecute; cellId++) + { + if ( !(++cut % progressInterval) ) + { + vtkDebugMacro(<<"Cutting #" << cut); + this->UpdateProgress ((double)cut/numCuts); + abortExecute = this->GetAbortExecute(); + } + + numCellPts = cellArrayPtr[cellArrayIt]; + cellArrayIt++; + + //find min and max values in scalar data + range[0] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + range[1] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + cellArrayIt++; + + for (i = 1; i < numCellPts; i++) + { + tempScalar = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + cellArrayIt++; + if (tempScalar <= range[0]) + { + range[0] = tempScalar; + } //if tempScalar <= min range value + if (tempScalar >= range[1]) + { + range[1] = tempScalar; + } //if tempScalar >= max range value + } // for all points in this cell + + int needCell = 0; + double val = this->ContourValues->GetValue(iter); + if (val >= range[0] && val <= range[1]) + { + needCell = 1; + } + + if (needCell) + { + vtkCell *cell = input->GetCell(cellId); + cellIds = cell->GetPointIds(); + cutScalars->GetTuples(cellIds,cellScalars); + // Loop over all contour values. + for (iter=0; iter < numContours && !abortExecute; iter++) + { + if ( !(++cut % progressInterval) ) + { + vtkDebugMacro(<<"Cutting #" << cut); + this->UpdateProgress ((double)cut/numCuts); + abortExecute = this->GetAbortExecute(); + } + value = this->ContourValues->GetValue(iter); + + cell->Contour(value, cellScalars, this->Locator, + newVerts, newLines, newPolys, inPD, outPD, + inCD, cellId, outCD); + } + } + + } // for all cells + } // for all contour values + } // sort by cell + + else // SORT_BY_VALUE: + { + // Three passes over the cells to process lower dimensional cells first. + // For poly data output cells need to be added in the order: + // verts, lines and then polys, or cell data gets mixed up. + // A better solution is to have an unstructured grid output. + // I create a table that maps cell type to cell dimensionality, + // because I need a fast way to get cell dimensionality. + // This assumes GetCell is slow and GetCellType is fast. + // I do not like hard coding a list of cell types here, + // but I do not want to add GetCellDimension(vtkIdType cellId) + // to the vtkDataSet API. Since I anticipate that the output + // will change to vtkUnstructuredGrid. This temporary solution + // is acceptable. + // + int cellType; + unsigned char cellTypeDimensions[VTK_NUMBER_OF_CELL_TYPES]; + vtkCutter::GetCellTypeDimensions(cellTypeDimensions); + int dimensionality; + // We skip 0d cells (points), because they cannot be cut (generate no data). + for (dimensionality = 1; dimensionality <= 3; ++dimensionality) + { + // Loop over all cells; get scalar values for all cell points + // and process each cell. + // + cellArrayIt = 0; + for (cellId=0; cellId < numCells && !abortExecute; cellId++) + { + numCellPts = cellArrayPtr[cellArrayIt]; + // I assume that "GetCellType" is fast. + cellType = input->GetCellType(cellId); + if (cellType >= VTK_NUMBER_OF_CELL_TYPES) + { // Protect against new cell types added. + vtkErrorMacro("Unknown cell type " << cellType); + cellArrayIt += 1+numCellPts; + continue; + } + if (cellTypeDimensions[cellType] != dimensionality) + { + cellArrayIt += 1+numCellPts; + continue; + } + cellArrayIt++; + + //find min and max values in scalar data + range[0] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + range[1] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + cellArrayIt++; + + for (i = 1; i < numCellPts; i++) + { + tempScalar = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; + cellArrayIt++; + if (tempScalar <= range[0]) + { + range[0] = tempScalar; + } //if tempScalar <= min range value + if (tempScalar >= range[1]) + { + range[1] = tempScalar; + } //if tempScalar >= max range value + } // for all points in this cell + + int needCell = 0; + for (int cont = 0; cont < numContours; ++cont) + { + double val = this->ContourValues->GetValue(cont); + if (val >= range[0] && val <= range[1]) + { + needCell = 1; + break; + } + } + + if (needCell) + { + vtkCell *cell = input->GetCell(cellId); + cellIds = cell->GetPointIds(); + cutScalars->GetTuples(cellIds,cellScalars); + // Loop over all contour values. + for (iter=0; iter < numContours && !abortExecute; iter++) + { + if (dimensionality == 3 && !(++cut % progressInterval) ) + { + vtkDebugMacro(<<"Cutting #" << cut); + this->UpdateProgress ((double)cut/numCuts); + abortExecute = this->GetAbortExecute(); + } + value = this->ContourValues->GetValue(iter); + + cell->Contour(value, cellScalars, this->Locator, + newVerts, newLines, newPolys, inPD, outPD, + inCD, cellId, outCD); + } // for all contour values + + } // if need cell + } // for all cells + } // for all dimensions (1,2,3). + } // sort by value + + // Update ourselves. Because we don't know upfront how many verts, lines, + // polys we've created, take care to reclaim memory. + // + cellScalars->Delete(); + cutScalars->Delete(); + + if ( this->GenerateCutScalars ) + { + inPD->Delete(); + } + + output->SetPoints(newPoints); + newPoints->Delete(); + + if (newVerts->GetNumberOfCells()) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + + if (newLines->GetNumberOfCells()) + { + output->SetLines(newLines); + } + newLines->Delete(); + + if (newPolys->GetNumberOfCells()) + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + this->Locator->Initialize();//release any extra memory + output->Squeeze(); +} + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkCutter::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkCutter::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +int vtkCutter::RequestUpdateExtent( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + return 1; +} + +int vtkCutter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkCutter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cut Function: " << this->CutFunction << "\n"; + + os << indent << "Sort By: " << this->GetSortByAsString() << "\n"; + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Generate Cut Scalars: " + << (this->GenerateCutScalars ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkCutter.h b/Graphics/vtkCutter.h new file mode 100644 index 0000000..4071114 --- /dev/null +++ b/Graphics/vtkCutter.h @@ -0,0 +1,222 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCutter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCutter - Cut vtkDataSet with user-specified implicit function +// .SECTION Description +// vtkCutter is a filter to cut through data using any subclass of +// vtkImplicitFunction. That is, a polygonal surface is created +// corresponding to the implicit function F(x,y,z) = value(s), where +// you can specify one or more values used to cut with. +// +// In VTK, cutting means reducing a cell of dimension N to a cut surface +// of dimension N-1. For example, a tetrahedron when cut by a plane (i.e., +// vtkPlane implicit function) will generate triangles. (In comparison, +// clipping takes a N dimensional cell and creates N dimension primitives.) +// +// vtkCutter is generally used to "slice-through" a dataset, generating +// a surface that can be visualized. It is also possible to use vtkCutter +// to do a form of volume rendering. vtkCutter does this by generating +// multiple cut surfaces (usually planes) which are ordered (and rendered) +// from back-to-front. The surfaces are set translucent to give a +// volumetric rendering effect. +// +// Note that data can be cut using either 1) the scalar values associated +// with the dataset or 2) an implicit function associated with this class. +// By default, if an implicit function is set it is used to clip the data +// set, otherwise the dataset scalars are used to perform the clipping. + +// .SECTION See Also +// vtkImplicitFunction vtkClipPolyData + +#ifndef __vtkCutter_h +#define __vtkCutter_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for inline methods + +#define VTK_SORT_BY_VALUE 0 +#define VTK_SORT_BY_CELL 1 +// This does not really belong here, ut it is for a temporary +// fix until this filter can be converted to geernate unstructured grids. +#define VTK_NUMBER_OF_CELL_TYPES 68 + +class vtkImplicitFunction; +class vtkPointLocator; +class vtkSynchronizedTemplates3D; +class vtkSynchronizedTemplatesCutter3D; +class vtkGridSynchronizedTemplates3D; +class vtkRectilinearSynchronizedTemplates; + +class VTK_GRAPHICS_EXPORT vtkCutter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkCutter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with user-specified implicit function; initial value of 0.0; and + // generating cut scalars turned off. + static vtkCutter *New(); + + // Description: + // Set a particular contour value at contour number i. The index i ranges + // between 0<=iContourValues->SetValue(i,value);} + + // Description: + // Get the ith contour value. + double GetValue(int i) + {return this->ContourValues->GetValue(i);} + + // Description: + // Get a pointer to an array of contour values. There will be + // GetNumberOfContours() values in the list. + double *GetValues() + {return this->ContourValues->GetValues();} + + // Description: + // Fill a supplied list with contour values. There will be + // GetNumberOfContours() values in the list. Make sure you allocate + // enough memory to hold the list. + void GetValues(double *contourValues) + {this->ContourValues->GetValues(contourValues);} + + // Description: + // Set the number of contours to place into the list. You only really + // need to use this method to reduce list size. The method SetValue() + // will automatically increase list size as needed. + void SetNumberOfContours(int number) + {this->ContourValues->SetNumberOfContours(number);} + + // Description: + // Get the number of contours in the list of contour values. + int GetNumberOfContours() + {return this->ContourValues->GetNumberOfContours();} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double range[2]) + {this->ContourValues->GenerateValues(numContours, range);} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double rangeStart, double rangeEnd) + {this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + // Description: + // Override GetMTime because we delegate to vtkContourValues and refer to + // vtkImplicitFunction. + unsigned long GetMTime(); + + // Description + // Specify the implicit function to perform the cutting. + virtual void SetCutFunction(vtkImplicitFunction*); + vtkGetObjectMacro(CutFunction,vtkImplicitFunction); + + // Description: + // If this flag is enabled, then the output scalar values will be + // interpolated from the implicit function values, and not the input scalar + // data. + vtkSetMacro(GenerateCutScalars,int); + vtkGetMacro(GenerateCutScalars,int); + vtkBooleanMacro(GenerateCutScalars,int); + + // Description: + // Specify a spatial locator for merging points. By default, + // an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Set the sorting order for the generated polydata. There are two + // possibilities: + // Sort by value = 0 - This is the most efficient sort. For each cell, + // all contour values are processed. This is the default. + // Sort by cell = 1 - For each contour value, all cells are processed. + // This order should be used if the extracted polygons must be rendered + // in a back-to-front or front-to-back order. This is very problem + // dependent. + // For most applications, the default order is fine (and faster). + // + // Sort by cell is going to have a problem if the input has 2D and 3D cells. + // Cell data will be scrambled becauses with + // vtkPolyData output, verts and lines have lower cell ids than triangles. + vtkSetClampMacro(SortBy,int,VTK_SORT_BY_VALUE,VTK_SORT_BY_CELL); + vtkGetMacro(SortBy,int); + void SetSortByToSortByValue() + {this->SetSortBy(VTK_SORT_BY_VALUE);} + void SetSortByToSortByCell() + {this->SetSortBy(VTK_SORT_BY_CELL);} + const char *GetSortByAsString(); + + // Description: + // Create default locator. Used to create one when none is specified. The + // locator is used to merge coincident points. + void CreateDefaultLocator(); + + // Description: + // Normally I would put this in a different class, but since + // This is a temporary fix until we convert this class and contour filter + // to generate unstructured grid output instead of poly data, I am leaving it here. + static void GetCellTypeDimensions(unsigned char* cellTypeDimensions); + +protected: + vtkCutter(vtkImplicitFunction *cf=NULL); + ~vtkCutter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + void UnstructuredGridCutter(vtkDataSet *input, vtkPolyData *output); + void DataSetCutter(vtkDataSet *input, vtkPolyData *output); + void StructuredPointsCutter(vtkDataSet *, vtkPolyData *, + vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + void StructuredGridCutter(vtkDataSet *, vtkPolyData *); + void RectilinearGridCutter(vtkDataSet *, vtkPolyData *); + vtkImplicitFunction *CutFunction; + + vtkSynchronizedTemplates3D *SynchronizedTemplates3D; + vtkSynchronizedTemplatesCutter3D *SynchronizedTemplatesCutter3D; + vtkGridSynchronizedTemplates3D *GridSynchronizedTemplates; + vtkRectilinearSynchronizedTemplates *RectilinearSynchronizedTemplates; + + vtkPointLocator *Locator; + int SortBy; + vtkContourValues *ContourValues; + int GenerateCutScalars; +private: + vtkCutter(const vtkCutter&); // Not implemented. + void operator=(const vtkCutter&); // Not implemented. +}; + +// Description: +// Return the sorting procedure as a descriptive character string. +inline const char *vtkCutter::GetSortByAsString(void) +{ + if ( this->SortBy == VTK_SORT_BY_VALUE ) + { + return "SortByValue"; + } + else + { + return "SortByCell"; + } +} + +#endif diff --git a/Graphics/vtkCylinderSource.cxx b/Graphics/vtkCylinderSource.cxx new file mode 100644 index 0000000..668d3af --- /dev/null +++ b/Graphics/vtkCylinderSource.cxx @@ -0,0 +1,217 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCylinderSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCylinderSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +#include + +vtkCxxRevisionMacro(vtkCylinderSource, "$Revision: 1.54 $"); +vtkStandardNewMacro(vtkCylinderSource); + +vtkCylinderSource::vtkCylinderSource (int res) +{ + this->Resolution = res; + this->Height = 1.0; + this->Radius = 0.5; + this->Capping = 1; + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + + this->SetNumberOfInputPorts(0); +} + +int vtkCylinderSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double angle= 2.0*3.141592654/this->Resolution; + int numPolys, numPts; + double xbot[3], tcbot[2], nbot[3]; + double xtop[3], tctop[2], ntop[3]; + double *center = this->Center; + int i, idx; + vtkIdType pts[VTK_CELL_SIZE]; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkFloatArray *newTCoords; + vtkCellArray *newPolys; + +// +// Set things up; allocate memory +// + + if ( this->Capping ) + { + numPts = 4*this->Resolution; + numPolys = this->Resolution + 2; + } + else + { + numPts = 2*this->Resolution; + numPolys = this->Resolution; + } + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(numPts); + newNormals->SetName("Normals"); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(numPts); + newTCoords->SetName("TCoords"); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys,this->Resolution)); +// +// Generate points and point data for sides +// + for (i=0; iResolution; i++) + { + // x coordinate + nbot[0] = ntop[0] = cos((double)i*angle); + xbot[0] = (nbot[0] * this->Radius) + center[0]; + xtop[0] = (ntop[0] * this->Radius) + center[0]; + tcbot[0] = tctop[0] = fabs(2.0*i/this->Resolution - 1.0); + + // y coordinate + xbot[1] = 0.5 * this->Height + center[1]; + xtop[1] = -0.5 * this->Height + center[1]; + nbot[1] = ntop[1] = 0.0; + tcbot[1] = 0.0; + tctop[1] = 1.0; + + // z coordinate + nbot[2] = ntop[2] = -sin((double)i*angle); + xbot[2] = (nbot[2] * this->Radius) + center[2]; + xtop[2] = (ntop[2] * this->Radius) + center[2]; + + idx = 2*i; + newPoints->InsertPoint(idx,xbot); + newPoints->InsertPoint(idx+1,xtop); + newTCoords->InsertTuple(idx,tcbot); + newTCoords->InsertTuple(idx+1,tctop); + newNormals->InsertTuple(idx,nbot); + newNormals->InsertTuple(idx+1,ntop); + } +// +// Generate polygons for sides +// + for (i=0; iResolution; i++) + { + pts[0] = 2*i; + pts[1] = pts[0] + 1; + pts[2] = (pts[1] + 2) % (2*this->Resolution); + pts[3] = pts[2] - 1; + newPolys->InsertNextCell(4,pts); + } +// +// Generate points and point data for top/bottom polygons +// + if ( this->Capping ) + { + for (i=0; iResolution; i++) + { + // x coordinate + xbot[0] = xtop[0] = this->Radius * cos((double)i*angle); + nbot[0] = ntop[0] = 0.0; + tcbot[0] = tctop[0] = xbot[0]; + xbot[0] += center[0]; xtop[0] += center[0]; + + // y coordinate + xbot[1] = 0.5 * this->Height; + xtop[1] = -0.5 * this->Height; + nbot[1] = 1.0; + ntop[1] = -1.0; + xbot[1] += center[1]; xtop[1] += center[1]; + + // z coordinate + xbot[2] = xtop[2] = -this->Radius * sin((double)i*angle); + tcbot[1] = tctop[1] = xbot[2]; + xbot[2] += center[2]; xtop[2] += center[2]; + nbot[2] = 0.0; + ntop[2] = 0.0; + + idx = 2*this->Resolution; + newPoints->InsertPoint(idx+i,xbot); + newTCoords->InsertTuple(idx+i,tcbot); + newNormals->InsertTuple(idx+i,nbot); + + idx = 3*this->Resolution; + newPoints->InsertPoint(idx+this->Resolution-i-1,xtop); + newTCoords->InsertTuple(idx+this->Resolution-i-1,tctop); + newNormals->InsertTuple(idx+this->Resolution-i-1,ntop); + } +// +// Generate polygons for top/bottom polygons +// + for (i=0; iResolution; i++) + { + pts[i] = 2*this->Resolution + i; + } + newPolys->InsertNextCell(this->Resolution,pts); + for (i=0; iResolution; i++) + { + pts[i] = 3*this->Resolution + i; + } + newPolys->InsertNextCell(this->Resolution,pts); + + } // if capping +// +// Update ourselves and release memory +// + output->SetPoints(newPoints); + newPoints->Delete(); + + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + newPolys->Squeeze(); // since we've estimated size; reclaim some space + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +void vtkCylinderSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Resolution: " << this->Resolution << "\n"; + os << indent << "Height: " << this->Height << "\n"; + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << " )\n"; + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkCylinderSource.h b/Graphics/vtkCylinderSource.h new file mode 100644 index 0000000..458cc71 --- /dev/null +++ b/Graphics/vtkCylinderSource.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCylinderSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCylinderSource - generate a cylinder centered at origin +// .SECTION Description +// vtkCylinderSource creates a polygonal cylinder centered at Center; +// The axis of the cylinder is aligned along the global y-axis. +// The height and radius of the cylinder can be specified, as well as the +// number of sides. It is also possible to control whether the cylinder is +// open-ended or capped. + +#ifndef __vtkCylinderSource_h +#define __vtkCylinderSource_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkCell.h" // Needed for VTK_CELL_SIZE + +class VTK_GRAPHICS_EXPORT vtkCylinderSource : public vtkPolyDataAlgorithm +{ +public: + static vtkCylinderSource *New(); + vtkTypeRevisionMacro(vtkCylinderSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the height of the cylinder. + vtkSetClampMacro(Height,double,0.0,VTK_DOUBLE_MAX) + vtkGetMacro(Height,double); + + // Description: + // Set the radius of the cylinder. + vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX) + vtkGetMacro(Radius,double); + + // Description: + // Set/Get cylinder center + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set the number of facets used to define cylinder. + vtkSetClampMacro(Resolution,int,2,VTK_CELL_SIZE) + vtkGetMacro(Resolution,int); + + // Description: + // Turn on/off whether to cap cylinder with polygons. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + +protected: + vtkCylinderSource(int res=6); + ~vtkCylinderSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double Height; + double Radius; + double Center[3]; + int Resolution; + int Capping; + +private: + vtkCylinderSource(const vtkCylinderSource&); // Not implemented. + void operator=(const vtkCylinderSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkDashedStreamLine.cxx b/Graphics/vtkDashedStreamLine.cxx new file mode 100644 index 0000000..2fc59f7 --- /dev/null +++ b/Graphics/vtkDashedStreamLine.cxx @@ -0,0 +1,198 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDashedStreamLine.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDashedStreamLine.h" + +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkDashedStreamLine, "$Revision: 1.44 $"); +vtkStandardNewMacro(vtkDashedStreamLine); + +vtkDashedStreamLine::vtkDashedStreamLine() +{ + this->DashFactor = 0.75; +} + +int vtkDashedStreamLine::RequestData(vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + + vtkStreamer::StreamPoint *sPrev, *sPtr; + vtkPoints *newPts; + vtkFloatArray *newVectors; + vtkFloatArray *newScalars=NULL; + vtkCellArray *newLines; + int i, ptId, j; + vtkIdType pts[2]; + double tOffset, x[3], v[3], r, xPrev[3], vPrev[3], scalarPrev; + double s = 0; + double xEnd[3], vEnd[3], sEnd; + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *source = 0; + if (sourceInfo) + { + source = vtkDataSet::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + } + + this->SavePointInterval = this->StepLength; + this->vtkStreamer::Integrate(input, source); + if ( this->NumberOfStreamers <= 0 ) + { + return 1; + } + // + // Convert streamer into lines. Lines may be dashed. + // + newPts = vtkPoints::New(); + newPts->Allocate(1000); + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(1000); + if ( input->GetPointData()->GetScalars() || this->SpeedScalars ) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(1000); + } + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(2*this->NumberOfStreamers,VTK_CELL_SIZE)); + // + // Loop over all streamers generating points + // + for (ptId=0; ptId < this->NumberOfStreamers; ptId++) + { + if ( this->Streamers[ptId].GetNumberOfPoints() < 2 ) + { + continue; + } + sPrev = this->Streamers[ptId].GetStreamPoint(0); + sPtr = this->Streamers[ptId].GetStreamPoint(1); + for (j=0; j<3; j++) + { + xPrev[j] = sPrev->x[j]; + vPrev[j] = sPrev->v[j]; + } + scalarPrev = sPrev->s; + + if ( this->Streamers[ptId].GetNumberOfPoints() == 2 && sPtr->cellId < 0 ) + { + continue; + } + + tOffset = sPrev->t; + + for ( i=1; + i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0; + i++, sPrev=sPtr, sPtr=this->Streamers[ptId].GetStreamPoint(i) ) + { +// +// Search for end of dash...create end of one dash, beginning of next +// + while ( tOffset >= sPrev->t && tOffset < sPtr->t ) + { + r = (tOffset - sPrev->t) / (sPtr->t - sPrev->t); + + for (j=0; j<3; j++) + { + x[j] = sPrev->x[j] + r * (sPtr->x[j] - sPrev->x[j]); + v[j] = sPrev->v[j] + r * (sPtr->v[j] - sPrev->v[j]); + xEnd[j] = xPrev[j] + this->DashFactor * (x[j] - xPrev[j]); + vEnd[j] = vPrev[j] + this->DashFactor * (v[j] - vPrev[j]); + } + + // create this dash + pts[0] = newPts->InsertNextPoint(x); + newVectors->InsertTuple(pts[0],v); + + pts[1] = newPts->InsertNextPoint(xEnd); + newVectors->InsertTuple(pts[1],vEnd); + + if ( newScalars ) + { + s = sPrev->s + r * (sPtr->s - sPrev->s); + newScalars->InsertTuple(pts[0],&s); + sEnd = scalarPrev + this->DashFactor * (s - scalarPrev); + newScalars->InsertTuple(pts[1],&sEnd); + } + + newLines->InsertNextCell(2,pts); + + for (j=0; j<3; j++) + { + xPrev[j] = x[j]; + vPrev[j] = v[j]; + } + if ( newScalars ) + { + scalarPrev = s; + } + tOffset += this->StepLength; + + } // while + } //for this streamer + } //for all streamers +// +// Update ourselves and release memory +// + vtkDebugMacro(<<"Created " << newPts->GetNumberOfPoints() << " points, " + << newLines->GetNumberOfCells() << " lines"); + + output->SetPoints(newPts); + newPts->Delete(); + + output->GetPointData()->SetVectors(newVectors); + newVectors->Delete(); + + if ( newScalars ) + { + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, + vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + output->SetLines(newLines); + newLines->Delete(); + + // Delete the streamers since they are no longer needed + delete[] this->Streamers; + this->Streamers = 0; + this->NumberOfStreamers = 0; + + output->Squeeze(); + + return 1; +} + +void vtkDashedStreamLine::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Dash Factor: " << this->DashFactor << " <<\n"; + +} diff --git a/Graphics/vtkDashedStreamLine.h b/Graphics/vtkDashedStreamLine.h new file mode 100644 index 0000000..20999a2 --- /dev/null +++ b/Graphics/vtkDashedStreamLine.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDashedStreamLine.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDashedStreamLine - generate constant-time dashed streamline in arbitrary dataset +// .SECTION Description +// vtkDashedStreamLine is a filter that generates a "dashed" streamline for +// an arbitrary dataset. The streamline consists of a series of dashes, each +// of which represents (approximately) a constant time increment. Thus, in the +// resulting visual representation, relatively long dashes represent areas of +// high velocity, and small dashes represent areas of low velocity. +// +// vtkDashedStreamLine introduces the instance variable DashFactor. +// DashFactor interacts with its superclass' instance variable StepLength to +// create the dashes. DashFactor is the percentage of the StepLength line +// segment that is visible. Thus, if the DashFactor=0.75, the dashes will be +// "three-quarters on" and "one-quarter off". + +// .SECTION See Also +// vtkStreamer vtkStreamLine vtkStreamPoints + +#ifndef __vtkDashedStreamLine_h +#define __vtkDashedStreamLine_h + +#include "vtkStreamLine.h" + +class VTK_GRAPHICS_EXPORT vtkDashedStreamLine : public vtkStreamLine +{ +public: + static vtkDashedStreamLine *New(); + vtkTypeRevisionMacro(vtkDashedStreamLine,vtkStreamLine); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // For each dash, specify the fraction of the dash that is "on". A factor + // of 1.0 will result in a continuous line, a factor of 0.5 will result in + // dashed that are half on and half off. + vtkSetClampMacro(DashFactor,double,0.01,1.0); + vtkGetMacro(DashFactor,double); + +protected: + vtkDashedStreamLine(); + ~vtkDashedStreamLine() {}; + + // Convert streamer array into vtkPolyData + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // the fraction of on versus off in dash + double DashFactor; + +private: + vtkDashedStreamLine(const vtkDashedStreamLine&); // Not implemented. + void operator=(const vtkDashedStreamLine&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkDataObjectToDataSetFilter.cxx b/Graphics/vtkDataObjectToDataSetFilter.cxx new file mode 100644 index 0000000..6e819e8 --- /dev/null +++ b/Graphics/vtkDataObjectToDataSetFilter.cxx @@ -0,0 +1,1521 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectToDataSetFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataObjectToDataSetFilter.h" + +#include "vtkFieldData.h" +#include "vtkFieldDataToAttributeDataFilter.h" +#include "vtkPolyData.h" +#include "vtkStructuredPoints.h" +#include "vtkStructuredGrid.h" +#include "vtkRectilinearGrid.h" +#include "vtkUnstructuredGrid.h" +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDataObjectToDataSetFilter, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkDataObjectToDataSetFilter); + +//---------------------------------------------------------------------------- +// Instantiate object with no input and no defined output. +vtkDataObjectToDataSetFilter::vtkDataObjectToDataSetFilter() +{ + int i; + this->Updating = 0; + + this->DataSetType = VTK_POLY_DATA; + vtkPolyData *output = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(0,output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); + + for (i=0; i < 3; i++) + { + this->PointArrays[i] = NULL; + this->PointArrayComponents[i] = -1; //uninitialized + this->PointComponentRange[i][0] = this->PointComponentRange[i][1] = -1; + this->PointNormalize[i] = 1; //yes, normalize + } + + this->VertsArray = NULL; + this->VertsArrayComponent = -1; + this->VertsComponentRange[0] = this->VertsComponentRange[1] = -1; + + this->LinesArray = NULL; + this->LinesArrayComponent = -1; + this->LinesComponentRange[0] = this->LinesComponentRange[1] = -1; + + this->PolysArray = NULL; + this->PolysArrayComponent = -1; + this->PolysComponentRange[0] = this->PolysComponentRange[1] = -1; + + this->StripsArray = NULL; + this->StripsArrayComponent = -1; + this->StripsComponentRange[0] = this->StripsComponentRange[1] = -1; + + this->CellTypeArray = NULL; + this->CellTypeArrayComponent = -1; + this->CellTypeComponentRange[0] = this->CellTypeComponentRange[1] = -1; + + this->CellConnectivityArray = NULL; + this->CellConnectivityArrayComponent = -1; + this->CellConnectivityComponentRange[0] = + this->CellConnectivityComponentRange[1] = -1; + + this->DefaultNormalize = 0; + + this->DimensionsArray = NULL;; //the name of the array + this->DimensionsArrayComponent = -1; + this->DimensionsComponentRange[0] = this->DimensionsComponentRange[1] = -1; + + this->SpacingArray = NULL;; //the name of the array + this->SpacingArrayComponent = -1; + this->SpacingComponentRange[0] = this->SpacingComponentRange[1] = -1; + + this->OriginArray = NULL;; //the name of the array + this->OriginArrayComponent = -1; + this->OriginComponentRange[0] = this->OriginComponentRange[1] = -1; + + this->Dimensions[0] = this->Dimensions[1] = this->Dimensions[2] = 0; + this->Spacing[0] = this->Spacing[1] = this->Spacing[2] = 0.0; + this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.0; +} + +//---------------------------------------------------------------------------- +vtkDataObjectToDataSetFilter::~vtkDataObjectToDataSetFilter() +{ + int i; + + for (i=0; i<3; i++) + { + if ( this->PointArrays[i] != NULL ) + { + delete [] this->PointArrays[i]; + } + } + if ( this->VertsArray != NULL ) + { + delete [] this->VertsArray; + } + if ( this->LinesArray != NULL ) + { + delete [] this->LinesArray; + } + if ( this->PolysArray != NULL ) + { + delete [] this->PolysArray; + } + if ( this->StripsArray != NULL ) + { + delete [] this->StripsArray; + } + if ( this->CellTypeArray != NULL ) + { + delete [] this->CellTypeArray; + } + if ( this->CellConnectivityArray != NULL ) + { + delete [] this->CellConnectivityArray; + } + if ( this->DimensionsArray != NULL ) + { + delete [] this->DimensionsArray; + } + if ( this->SpacingArray != NULL ) + { + delete [] this->SpacingArray; + } + if ( this->OriginArray != NULL ) + { + delete [] this->OriginArray; + } +} + +void vtkDataObjectToDataSetFilter::SetDataSetType(int dt) +{ + if (dt == this->DataSetType) + { + return; + } + + vtkDataSet *output; + switch (dt) + { + case VTK_POLY_DATA: + output = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(0,output); + output->Delete(); + break; + case VTK_STRUCTURED_GRID: + output = vtkStructuredGrid::New(); + this->GetExecutive()->SetOutputData(0,output); + output->Delete(); + break; + case VTK_STRUCTURED_POINTS: + output = vtkStructuredPoints::New(); + this->GetExecutive()->SetOutputData(0,output); + output->Delete(); + break; + case VTK_UNSTRUCTURED_GRID: + output = vtkUnstructuredGrid::New(); + this->GetExecutive()->SetOutputData(0,output); + output->Delete(); + break; + case VTK_RECTILINEAR_GRID: + output = vtkRectilinearGrid::New(); + this->GetExecutive()->SetOutputData(0,output); + output->Delete(); + break; + default: + vtkWarningMacro("unknown type in SetDataSetType"); + } + this->DataSetType = dt; + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkDataObject *vtkDataObjectToDataSetFilter::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return NULL; + } + + return this->GetExecutive()->GetInputData(0, 0); +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkDataObject *input = inInfo->Get(vtkDataObject::DATA_OBJECT()); + + switch (this->DataSetType) + { + case VTK_POLY_DATA: + break; + + case VTK_STRUCTURED_POINTS: + // We need the array to get the dimensions + input->Update(); + this->ConstructDimensions(input); + this->ConstructSpacing(input); + this->ConstructOrigin(input); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, this->Dimensions[0]-1, 0, this->Dimensions[1]-1, + 0, this->Dimensions[2]-1); + outInfo->Set(vtkDataObject::ORIGIN(), this->Origin, 3); + outInfo->Set(vtkDataObject::SPACING(), this->Spacing, 3); + break; + + case VTK_STRUCTURED_GRID: + // We need the array to get the dimensions + input->Update(); + this->ConstructDimensions(input); + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, this->Dimensions[0]-1, 0, this->Dimensions[1]-1, + 0, this->Dimensions[2]-1); + break; + + case VTK_RECTILINEAR_GRID: + // We need the array to get the dimensions + input->Update(); + this->ConstructDimensions(input); + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, this->Dimensions[0]-1, 0, this->Dimensions[1]-1, + 0, this->Dimensions[2]-1); + break; + + case VTK_UNSTRUCTURED_GRID: + break; + + default: + vtkErrorMacro(<<"Unsupported dataset type!"); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataObject *input = inInfo->Get(vtkDataObject::DATA_OBJECT()); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType npts; + + vtkDebugMacro(<<"Generating dataset from field data"); + + switch (this->DataSetType) + { + case VTK_POLY_DATA: + if ( (npts=this->ConstructPoints(input, + vtkPolyData::SafeDownCast(output))) ) + { + this->ConstructCells(input, vtkPolyData::SafeDownCast(output)); + } + else + { + vtkErrorMacro(<<"Couldn't create any points"); + } + break; + + case VTK_STRUCTURED_POINTS: + { + this->ConstructDimensions(input); + this->ConstructSpacing(input); + this->ConstructOrigin(input); + vtkStructuredPoints *sp = vtkStructuredPoints::SafeDownCast(output); + sp->SetDimensions(this->Dimensions); + sp->SetOrigin(this->Origin); + sp->SetSpacing(this->Spacing); + break; + } + + case VTK_STRUCTURED_GRID: + if ( (npts=this->ConstructPoints(input, + this->GetStructuredGridOutput())) ) + { + this->ConstructDimensions(input); + if ( npts == (this->Dimensions[0] * this->Dimensions[1] * + this->Dimensions[2]) ) + { + vtkStructuredGrid *sg = vtkStructuredGrid::SafeDownCast(output); + sg->SetDimensions(this->Dimensions); + } + else + { + vtkErrorMacro(<<"Number of points don't match dimensions"); + } + } + break; + + case VTK_RECTILINEAR_GRID: + if ( (npts=this->ConstructPoints(input, + this->GetRectilinearGridOutput())) ) + { + this->ConstructDimensions(input); + if ( npts == (this->Dimensions[0] * this->Dimensions[1] * + this->Dimensions[2]) ) + { + vtkRectilinearGrid *rg = vtkRectilinearGrid::SafeDownCast(output); + rg->SetDimensions(this->Dimensions); + } + else + { + vtkErrorMacro(<<"Number of points don't match dimensions"); + } + } + break; + + case VTK_UNSTRUCTURED_GRID: + if ( this->ConstructPoints(input, + vtkUnstructuredGrid::SafeDownCast(output)) ) + { + this->ConstructCells(input, vtkUnstructuredGrid::SafeDownCast(output)); + } + else + { + vtkErrorMacro(<<"Couldn't create any points"); + } + break; + + default: + vtkErrorMacro(<<"Unsupported dataset type!"); + } + + vtkFieldData *inFD = input->GetFieldData(); + vtkFieldData *outFD = output->GetFieldData(); + outFD->CopyAllOn(); + outFD->PassData(inFD); + + return 1; +} + +// Get the output as vtkPolyData. +vtkPolyData *vtkDataObjectToDataSetFilter::GetPolyDataOutput() +{ + return vtkPolyData::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +vtkDataSet *vtkDataObjectToDataSetFilter::GetOutput() +{ + if (this->GetNumberOfOutputPorts() < 1) + { + return NULL; + } + + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetOutputData(0)); +} + +// Get the output as vtkStructuredPoints. +vtkStructuredPoints *vtkDataObjectToDataSetFilter::GetStructuredPointsOutput() +{ + return vtkStructuredPoints::SafeDownCast(this->GetOutput()); +} + +// Get the output as vtkStructuredGrid. +vtkStructuredGrid *vtkDataObjectToDataSetFilter::GetStructuredGridOutput() +{ + return vtkStructuredGrid::SafeDownCast(this->GetOutput()); +} + +// Get the output as vtkUnstructuredGrid. +vtkUnstructuredGrid *vtkDataObjectToDataSetFilter::GetUnstructuredGridOutput() +{ + return vtkUnstructuredGrid::SafeDownCast(this->GetOutput()); +} + +// Get the output as vtkRectilinearGrid. +vtkRectilinearGrid *vtkDataObjectToDataSetFilter::GetRectilinearGridOutput() +{ + return vtkRectilinearGrid::SafeDownCast(this->GetOutput()); +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Data Set Type: "; + if ( this->DataSetType == VTK_POLY_DATA ) + { + os << "vtkPolyData\n"; + } + else if ( this->DataSetType == VTK_STRUCTURED_POINTS ) + { + os << "vtkStructuredPoints\n"; + } + else if ( this->DataSetType == VTK_STRUCTURED_GRID ) + { + os << "vtkStructuredGrid\n"; + } + else if ( this->DataSetType == VTK_RECTILINEAR_GRID ) + { + os << "vtkRectilinearGrid\n"; + } + else // if ( this->DataSetType == VTK_UNSTRUCTURED_GRID ) + { + os << "vtkUnstructuredGrid\n"; + } + + os << indent << "Dimensions: (" << this->Dimensions[0] << ", " + << this->Dimensions[1] << ", " + << this->Dimensions[2] << ")\n"; + + os << indent << "Spacing: (" << this->Spacing[0] << ", " + << this->Spacing[1] << ", " + << this->Spacing[2] << ")\n"; + + os << indent << "Origin: (" << this->Origin[0] << ", " + << this->Origin[1] << ", " + << this->Origin[2] << ")\n"; + + os << indent << "Default Normalize: " + << (this->DefaultNormalize ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +// Stuff related to points -------------------------------------------- +// +void vtkDataObjectToDataSetFilter::SetPointComponent(int comp, + char *arrayName, + int arrayComp, + int min, int max, + int normalize) +{ + if ( comp < 0 || comp > 2 ) + { + vtkErrorMacro(<<"Point component must be between (0,2)"); + return; + } + + vtkFieldDataToAttributeDataFilter::SetArrayName( + this, this->PointArrays[comp], arrayName); + if ( this->PointArrayComponents[comp] != arrayComp ) + { + this->PointArrayComponents[comp] = arrayComp; + this->Modified(); + } + if ( this->PointComponentRange[comp][0] != min ) + { + this->PointComponentRange[comp][0] = min; + this->Modified(); + } + if ( this->PointComponentRange[comp][1] != max ) + { + this->PointComponentRange[comp][1] = max; + this->Modified(); + } + if ( this->PointNormalize[comp] != normalize ) + { + this->PointNormalize[comp] = normalize; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +const char *vtkDataObjectToDataSetFilter::GetPointComponentArrayName(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->PointArrays[comp]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetPointComponentArrayComponent(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->PointArrayComponents[comp]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetPointComponentMinRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->PointComponentRange[comp][0]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetPointComponentMaxRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->PointComponentRange[comp][1]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetPointComponentNormailzeFlag(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->PointNormalize[comp]; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkDataObjectToDataSetFilter::ConstructPoints(vtkDataObject *input, + vtkPointSet *ps) +{ + int i, updated=0; + vtkDataArray *fieldArray[3]; + vtkIdType npts; + vtkFieldData *fd=input->GetFieldData(); + + for ( i=0; i < 3; i++ ) + { + fieldArray[i] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->PointArrays[i], + this->PointArrayComponents[i]); + + if ( fieldArray[i] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested"); + return 0; + } + updated |= vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray[i], + this->PointComponentRange[i]); + } + + npts = this->PointComponentRange[0][1] - this->PointComponentRange[0][0] + 1; + if ( npts != (this->PointComponentRange[1][1] - + this->PointComponentRange[1][0] + 1) || + npts != (this->PointComponentRange[2][1] - + this->PointComponentRange[2][0] + 1) ) + { + vtkErrorMacro(<<"Number of point components not consistent"); + return 0; + } + + // Try using the arrays directly if possible; otherwise copy data + vtkPoints *newPts = vtkPoints::New(); + if ( fieldArray[0]->GetNumberOfComponents() == 3 && + fieldArray[0] == fieldArray[1] && fieldArray[1] == fieldArray[2] && + fieldArray[0]->GetNumberOfTuples() == npts && + !this->PointNormalize[0] && !this->PointNormalize[1] && + !this->PointNormalize[2] ) + { + newPts->SetData(fieldArray[0]); + } + else //have to copy data into created array + { + newPts->SetDataType( + vtkFieldDataToAttributeDataFilter::GetComponentsType(3, fieldArray)); + newPts->SetNumberOfPoints(npts); + + for ( i=0; i < 3; i++ ) + { + if ( vtkFieldDataToAttributeDataFilter::ConstructArray( + newPts->GetData(), i, fieldArray[i], this->PointArrayComponents[i], + this->PointComponentRange[i][0], + this->PointComponentRange[i][1], + this->PointNormalize[i]) == 0 ) + { + newPts->Delete(); + return 0; + } + } + } + + ps->SetPoints(newPts); + newPts->Delete(); + if ( updated ) //reset for next execution pass + { + for (i=0; i < 3; i++) + { + this->PointComponentRange[i][0] = this->PointComponentRange[i][1] = -1; + } + } + + return npts; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkDataObjectToDataSetFilter::ConstructPoints(vtkDataObject *input, + vtkRectilinearGrid *rg) +{ + int i, nXpts, nYpts, nZpts, updated=0; + vtkIdType npts; + vtkDataArray *fieldArray[3]; + vtkFieldData *fd=input->GetFieldData(); + + for ( i=0; i < 3; i++ ) + { + fieldArray[i] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->PointArrays[i], + this->PointArrayComponents[i]); + + if ( fieldArray[i] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested"); + return 0; + } + } + + for (i=0; i<3; i++) + { + updated |= vtkFieldDataToAttributeDataFilter::UpdateComponentRange(fieldArray[i], + this->PointComponentRange[i]); + } + + nXpts = this->PointComponentRange[0][1] - this->PointComponentRange[0][0] + 1; + nYpts = this->PointComponentRange[1][1] - this->PointComponentRange[1][0] + 1; + nZpts = this->PointComponentRange[2][1] - this->PointComponentRange[2][0] + 1; + npts = nXpts * nYpts * nZpts; + + // Create the coordinate arrays + vtkDataArray *XPts; + vtkDataArray *YPts; + vtkDataArray *ZPts; + + // Decide whether to use the field array or whether to copy data + // First look at the x-coordinates + if ( fieldArray[0]->GetNumberOfComponents() == 1 && + fieldArray[0]->GetNumberOfTuples() == nXpts && + !this->PointNormalize[0] ) + { + XPts = fieldArray[0]; + XPts->Register(this); + } + else //have to copy data into created array + { + XPts = vtkDataArray::CreateDataArray( + vtkFieldDataToAttributeDataFilter::GetComponentsType(1, fieldArray)); + XPts->SetNumberOfComponents(1); + XPts->SetNumberOfTuples(nXpts); + + if ( vtkFieldDataToAttributeDataFilter::ConstructArray( + XPts, 0, fieldArray[0], this->PointArrayComponents[0], + this->PointComponentRange[0][0], + this->PointComponentRange[0][1], + this->PointNormalize[0]) == 0 ) + { + XPts->Delete(); + return 0; + } + } + + // Look at the y-coordinates + if ( fieldArray[1]->GetNumberOfComponents() == 1 && + fieldArray[1]->GetNumberOfTuples() == nYpts && + !this->PointNormalize[1] ) + { + YPts = fieldArray[1]; + YPts->Register(this); + } + else //have to copy data into created array + { + YPts = vtkDataArray::CreateDataArray( + vtkFieldDataToAttributeDataFilter::GetComponentsType(1, fieldArray+1)); + YPts->SetNumberOfComponents(1); + YPts->SetNumberOfTuples(nYpts); + + if ( vtkFieldDataToAttributeDataFilter::ConstructArray( + YPts, 0, fieldArray[1], this->PointArrayComponents[1], + this->PointComponentRange[1][0], + this->PointComponentRange[1][1], + this->PointNormalize[1]) == 0 ) + { + XPts->Delete(); YPts->Delete(); + return 0; + } + } + + // Look at the z-coordinates + if ( fieldArray[2]->GetNumberOfComponents() == 1 && + fieldArray[2]->GetNumberOfTuples() == nZpts && + !this->PointNormalize[2] ) + { + ZPts = fieldArray[2]; + ZPts->Register(this); + } + else //have to copy data into created array + { + ZPts = vtkDataArray::CreateDataArray( + vtkFieldDataToAttributeDataFilter::GetComponentsType(1, fieldArray+2)); + ZPts->SetNumberOfComponents(1); + ZPts->SetNumberOfTuples(nZpts); + + if ( vtkFieldDataToAttributeDataFilter::ConstructArray( + ZPts, 0, fieldArray[2], this->PointArrayComponents[2], + this->PointComponentRange[2][0], + this->PointComponentRange[2][1], + this->PointNormalize[2]) == 0 ) + { + XPts->Delete(); YPts->Delete(); ZPts->Delete(); + return 0; + } + } + + rg->SetXCoordinates(XPts); + rg->SetYCoordinates(YPts); + rg->SetZCoordinates(ZPts); + XPts->Delete(); YPts->Delete(); ZPts->Delete(); + + if ( updated ) //reset for next execution pass + { + for (i=0; i < 3; i++) + { + this->PointComponentRange[i][0] = this->PointComponentRange[i][1] = -1; + } + } + + return npts; +} + +//---------------------------------------------------------------------------- +// Stuff related to vtkPolyData -------------------------------------------- +// +void vtkDataObjectToDataSetFilter::SetVertsComponent(char *arrayName, + int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName( + this, this->VertsArray, arrayName); + if ( this->VertsArrayComponent != arrayComp ) + { + this->VertsArrayComponent = arrayComp; + this->Modified(); + } + if ( this->VertsComponentRange[0] != min ) + { + this->VertsComponentRange[0] = min; + this->Modified(); + } + if ( this->VertsComponentRange[1] != max ) + { + this->VertsComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +const char *vtkDataObjectToDataSetFilter::GetVertsComponentArrayName() +{ + return this->VertsArray; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetVertsComponentArrayComponent() +{ + return this->VertsArrayComponent; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetVertsComponentMinRange() +{ + return this->VertsComponentRange[0]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetVertsComponentMaxRange() +{ + return this->VertsComponentRange[1]; +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::SetLinesComponent(char *arrayName, + int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName( + this, this->LinesArray, arrayName); + if ( this->LinesArrayComponent != arrayComp ) + { + this->LinesArrayComponent = arrayComp; + this->Modified(); + } + if ( this->LinesComponentRange[0] != min ) + { + this->LinesComponentRange[0] = min; + this->Modified(); + } + if ( this->LinesComponentRange[1] != max ) + { + this->LinesComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +const char *vtkDataObjectToDataSetFilter::GetLinesComponentArrayName() +{ + return this->LinesArray; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetLinesComponentArrayComponent() +{ + return this->LinesArrayComponent; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetLinesComponentMinRange() +{ + return this->LinesComponentRange[0]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetLinesComponentMaxRange() +{ + return this->LinesComponentRange[1]; +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::SetPolysComponent(char *arrayName, + int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName( + this, this->PolysArray, arrayName); + if ( this->PolysArrayComponent != arrayComp ) + { + this->PolysArrayComponent = arrayComp; + this->Modified(); + } + if ( this->PolysComponentRange[0] != min ) + { + this->PolysComponentRange[0] = min; + this->Modified(); + } + if ( this->PolysComponentRange[1] != max ) + { + this->PolysComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +const char *vtkDataObjectToDataSetFilter::GetPolysComponentArrayName() +{ + return this->PolysArray; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetPolysComponentArrayComponent() +{ + return this->PolysArrayComponent; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetPolysComponentMinRange() +{ + return this->PolysComponentRange[0]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetPolysComponentMaxRange() +{ + return this->PolysComponentRange[1]; +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::SetStripsComponent(char *arrayName, + int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName( + this, this->StripsArray, arrayName); + if ( this->StripsArrayComponent != arrayComp ) + { + this->StripsArrayComponent = arrayComp; + this->Modified(); + } + if ( this->StripsComponentRange[0] != min ) + { + this->StripsComponentRange[0] = min; + this->Modified(); + } + if ( this->StripsComponentRange[1] != max ) + { + this->StripsComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +const char *vtkDataObjectToDataSetFilter::GetStripsComponentArrayName() +{ + return this->StripsArray; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetStripsComponentArrayComponent() +{ + return this->StripsArrayComponent; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetStripsComponentMinRange() +{ + return this->StripsComponentRange[0]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetStripsComponentMaxRange() +{ + return this->StripsComponentRange[1]; +} + +//---------------------------------------------------------------------------- +// Stuff related to vtkUnstructuredGrid -------------------------------------- +void vtkDataObjectToDataSetFilter::SetCellTypeComponent(char *arrayName, int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName( + this, this->CellTypeArray, arrayName); + if ( this->CellTypeArrayComponent != arrayComp ) + { + this->CellTypeArrayComponent = arrayComp; + this->Modified(); + } + if ( this->CellTypeComponentRange[0] != min ) + { + this->CellTypeComponentRange[0] = min; + this->Modified(); + } + if ( this->CellTypeComponentRange[1] != max ) + { + this->CellTypeComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +const char *vtkDataObjectToDataSetFilter::GetCellTypeComponentArrayName() +{ + return this->CellTypeArray; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetCellTypeComponentArrayComponent() +{ + return this->CellTypeArrayComponent; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetCellTypeComponentMinRange() +{ + return this->CellTypeComponentRange[0]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetCellTypeComponentMaxRange() +{ + return this->CellTypeComponentRange[1]; +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::SetCellConnectivityComponent( + char *arrayName, int arrayComp, int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName( + this, this->CellConnectivityArray, arrayName); + if ( this->CellConnectivityArrayComponent != arrayComp ) + { + this->CellConnectivityArrayComponent = arrayComp; + this->Modified(); + } + if ( this->CellConnectivityComponentRange[0] != min ) + { + this->CellConnectivityComponentRange[0] = min; + this->Modified(); + } + if ( this->CellConnectivityComponentRange[1] != max ) + { + this->CellConnectivityComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +const char * +vtkDataObjectToDataSetFilter::GetCellConnectivityComponentArrayName() +{ + return this->CellConnectivityArray; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetCellConnectivityComponentArrayComponent() +{ + return this->CellConnectivityArrayComponent; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetCellConnectivityComponentMinRange() +{ + return this->CellConnectivityComponentRange[0]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::GetCellConnectivityComponentMaxRange() +{ + return this->CellConnectivityComponentRange[1]; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::ConstructCells(vtkDataObject *input, + vtkPolyData *pd) +{ + vtkIdType ncells=0; + vtkDataArray *fieldArray[4]; + vtkFieldData *fd=input->GetFieldData(); + + fieldArray[0] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->VertsArray, this->VertsArrayComponent); + if ( this->VertsArray && fieldArray[0] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for vertices"); + return 0; + } + + fieldArray[1] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->LinesArray, this->LinesArrayComponent); + if ( this->LinesArray && fieldArray[1] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for lines"); + return 0; + } + + fieldArray[2] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->PolysArray, this->PolysArrayComponent); + if ( this->PolysArray && fieldArray[2] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for polygons"); + return 0; + } + + fieldArray[3] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->StripsArray, this->StripsArrayComponent); + if ( this->StripsArray && fieldArray[3] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for triangle strips"); + return 0; + } + + if ( fieldArray[0] ) + { + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray[0], this->VertsComponentRange); + vtkCellArray *verts = this->ConstructCellArray( + fieldArray[0], this->VertsArrayComponent, + this->VertsComponentRange); + if ( verts != NULL ) + { + pd->SetVerts(verts); + ncells += verts->GetNumberOfCells(); + verts->Delete(); + } + this->VertsComponentRange[0] = this->VertsComponentRange[1] = -1; + } + + if ( fieldArray[1] ) + { + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray[1], this->LinesComponentRange); + vtkCellArray *lines = this->ConstructCellArray( + fieldArray[1], this->LinesArrayComponent, this->LinesComponentRange); + if ( lines != NULL ) + { + pd->SetLines(lines); + ncells += lines->GetNumberOfCells(); + lines->Delete(); + } + this->LinesComponentRange[0] = this->LinesComponentRange[1] = -1; + } + + if ( fieldArray[2] ) + { + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray[2], this->PolysComponentRange); + vtkCellArray *polys = this->ConstructCellArray( + fieldArray[2], this->PolysArrayComponent, + this->PolysComponentRange); + if ( polys != NULL ) + { + pd->SetPolys(polys); + ncells += polys->GetNumberOfCells(); + polys->Delete(); + } + this->PolysComponentRange[0] = this->PolysComponentRange[1] = -1; + } + + if ( fieldArray[3] ) + { + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray[3], this->StripsComponentRange); + vtkCellArray *triStrips = this->ConstructCellArray(fieldArray[3], + this->StripsArrayComponent, this->StripsComponentRange); + if ( triStrips != NULL ) + { + pd->SetStrips(triStrips); + ncells += triStrips->GetNumberOfCells(); + triStrips->Delete(); + } + this->StripsComponentRange[0] = this->StripsComponentRange[1] = -1; + } + + return ncells; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::ConstructCells(vtkDataObject *input, + vtkUnstructuredGrid *ug) +{ + int i, *types, typesAllocated=0; + vtkDataArray *fieldArray[2]; + int ncells; + vtkFieldData *fd=input->GetFieldData(); + + fieldArray[0] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->CellTypeArray, + this->CellTypeArrayComponent); + + if ( fieldArray[0] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for cell types"); + return 0; + } + + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray[0], + this->CellTypeComponentRange); + ncells = this->CellTypeComponentRange[1] - + this->CellTypeComponentRange[0] + 1; + + fieldArray[1] = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, + this->CellConnectivityArray, + this->CellConnectivityArrayComponent); + if ( fieldArray[1] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for cell connectivity"); + return 0; + } + + // Okay, let's piece it together + if ( fieldArray[0] ) //cell types defined + { + // first we create the integer array of types + vtkDataArray *da=fieldArray[0]; + + if ( da->GetDataType() == VTK_INT && da->GetNumberOfComponents() == 1 && + this->CellTypeArrayComponent == 0 && + this->CellTypeComponentRange[0] == 0 && + this->CellTypeComponentRange[1] == da->GetMaxId() ) + { + types = ((vtkIntArray *)da)->GetPointer(0); + } + // Otherwise, we'll copy the data by inserting it into a vtkCellArray + else + { + typesAllocated = 1; + types = new int[ncells]; + for (i=this->CellTypeComponentRange[0]; + i <= this->CellTypeComponentRange[1]; i++) + { + types[i] = (int) da->GetComponent(i,this->CellTypeArrayComponent); + } + } + this->CellTypeComponentRange[0] = this->CellTypeComponentRange[1] = -1; + + // create connectivity + if ( fieldArray[1] ) //cell connectivity defined + { + vtkFieldDataToAttributeDataFilter::UpdateComponentRange(fieldArray[1], + this->CellConnectivityComponentRange); + vtkCellArray *carray = this->ConstructCellArray( + fieldArray[1], + this->CellConnectivityArrayComponent, + this->CellConnectivityComponentRange); + if ( carray != NULL ) //insert into unstructured grid + { + ug->SetCells(types,carray); + carray->Delete(); + } + this->CellConnectivityComponentRange[0] + = this->CellConnectivityComponentRange[1] = -1; + } + if ( typesAllocated ) + { + delete [] types; + } + } + + return ncells; +} + +//---------------------------------------------------------------------------- +vtkCellArray *vtkDataObjectToDataSetFilter::ConstructCellArray(vtkDataArray *da, int comp, vtkIdType compRange[2]) +{ + int j, min, max, numComp=da->GetNumberOfComponents(); + vtkCellArray *carray; + vtkIdType npts, ncells, i; + + min = 0; + max = da->GetMaxId(); + + if ( comp < 0 || comp >= numComp ) + { + vtkErrorMacro(<<"Bad component specification"); + return NULL; + } + + carray = vtkCellArray::New(); + + // If the data type is vtkIdType, and the number of components is 1, then + // we can directly use the data array without copying it. We just have to + // figure out how many cells we have. + if ( da->GetDataType() == VTK_ID_TYPE && da->GetNumberOfComponents() == 1 + && comp == 0 && compRange[0] == 0 && compRange[1] == max ) + { + vtkIdTypeArray *ia = (vtkIdTypeArray *)da; + for (ncells=i=0; iGetMaxId(); i+=(npts+1)) + { + ncells++; + npts = ia->GetValue(i); + } + carray->SetCells(ncells,ia); + } + // Otherwise, we'll copy the data by inserting it into a vtkCellArray + else + { + for (i=min; iGetComponent(i,comp); + if ( npts <= 0 ) + { + vtkErrorMacro(<<"Error constructing cell array"); + carray->Delete(); + return NULL; + } + else + { + carray->InsertNextCell(npts); + for (j=1; j<=npts; j++) + { + carray->InsertCellPoint((int)da->GetComponent(i+j,comp)); + } + } + } + } + + return carray; +} + +//---------------------------------------------------------------------------- +// Alternative methods for Dimensions, Spacing, and Origin ------------------- +// +void vtkDataObjectToDataSetFilter::SetDimensionsComponent(char *arrayName, + int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName(this, this->DimensionsArray, + arrayName); + if ( this->DimensionsArrayComponent != arrayComp ) + { + this->DimensionsArrayComponent = arrayComp; + this->Modified(); + } + if ( this->DimensionsComponentRange[0] != min ) + { + this->DimensionsComponentRange[0] = min; + this->Modified(); + } + if ( this->DimensionsComponentRange[1] != max ) + { + this->DimensionsComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::SetSpacingComponent(char *arrayName, + int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName(this, this->SpacingArray, + arrayName); + if ( this->SpacingArrayComponent != arrayComp ) + { + this->SpacingArrayComponent = arrayComp; + this->Modified(); + } + if ( this->SpacingComponentRange[0] != min ) + { + this->SpacingComponentRange[0] = min; + this->Modified(); + } + if ( this->SpacingComponentRange[1] != max ) + { + this->SpacingComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::SetOriginComponent(char *arrayName, + int arrayComp, + int min, int max) +{ + vtkFieldDataToAttributeDataFilter::SetArrayName(this, this->OriginArray, + arrayName); + if ( this->OriginArrayComponent != arrayComp ) + { + this->OriginArrayComponent = arrayComp; + this->Modified(); + } + if ( this->OriginComponentRange[0] != min ) + { + this->OriginComponentRange[0] = min; + this->Modified(); + } + if ( this->OriginComponentRange[1] != max ) + { + this->OriginComponentRange[1] = max; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::ConstructDimensions(vtkDataObject *input) +{ + if ( this->DimensionsArray == NULL || this->DimensionsArrayComponent < 0 ) + { + return; //assume dimensions have been set + } + else + { + vtkFieldData *fd=input->GetFieldData(); + vtkDataArray *fieldArray + = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->DimensionsArray, this->DimensionsArrayComponent); + if ( fieldArray == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for dimensions"); + return; + } + + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray, this->DimensionsComponentRange); + + for (int i=0; i<3; i++) + { + this->Dimensions[i] = (int)(fieldArray->GetComponent( + this->DimensionsComponentRange[0]+i, + this->DimensionsArrayComponent)); + } + } + + this->DimensionsComponentRange[0] = this->DimensionsComponentRange[1] = -1; +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::ConstructSpacing(vtkDataObject *input) +{ + if ( this->SpacingArray == NULL || this->SpacingArrayComponent < 0 ) + { + return; //assume Spacing have been set + } + else + { + vtkFieldData *fd=input->GetFieldData(); + vtkDataArray *fieldArray + = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->SpacingArray, this->SpacingArrayComponent); + if ( fieldArray == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for Spacing"); + return; + } + + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray, this->SpacingComponentRange); + + for (int i=0; i<3; i++) + { + this->Spacing[i] = fieldArray->GetComponent( + this->SpacingComponentRange[0]+i, + this->SpacingArrayComponent); + } + } + this->SpacingComponentRange[0] = this->SpacingComponentRange[1] = -1; +} + +//---------------------------------------------------------------------------- +vtkDataSet *vtkDataObjectToDataSetFilter::GetOutput(int idx) +{ + return vtkDataSet::SafeDownCast(this->GetExecutive()->GetOutputData(idx)); +} + +//---------------------------------------------------------------------------- +void vtkDataObjectToDataSetFilter::ConstructOrigin(vtkDataObject *input) +{ + if ( this->OriginArray == NULL || this->OriginArrayComponent < 0 ) + { + return; //assume Origin have been set + } + else + { + vtkFieldData *fd=input->GetFieldData(); + vtkDataArray *fieldArray + = vtkFieldDataToAttributeDataFilter::GetFieldArray( + fd, this->OriginArray, this->OriginArrayComponent); + if ( fieldArray == NULL ) + { + vtkErrorMacro(<<"Can't find array requested for Origin"); + return; + } + + vtkFieldDataToAttributeDataFilter::UpdateComponentRange( + fieldArray, + this->OriginComponentRange); + + for (int i=0; i<3; i++) + { + this->Origin[i] = fieldArray->GetComponent( + this->OriginComponentRange[0]+i, + this->OriginArrayComponent); + } + } + + this->OriginComponentRange[0] = this->OriginComponentRange[1] = -1; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::FillInputPortInformation(int, + vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataObjectToDataSetFilter::RequestDataObject( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + if (!output || (output->GetDataObjectType() != this->DataSetType)) + { + switch (this->DataSetType) + { + case VTK_POLY_DATA: + output = vtkPolyData::New(); + break; + case VTK_STRUCTURED_GRID: + output = vtkStructuredGrid::New(); + break; + case VTK_STRUCTURED_POINTS: + output = vtkStructuredPoints::New(); + break; + case VTK_UNSTRUCTURED_GRID: + output = vtkUnstructuredGrid::New(); + break; + case VTK_RECTILINEAR_GRID: + output = vtkRectilinearGrid::New(); + break; + default: + vtkWarningMacro("unknown DataSetType"); + } + if (output) + { + output->SetPipelineInformation(outInfo); + output->Delete(); + this->GetOutputPortInformation(0)->Set( + vtkDataObject::DATA_EXTENT_TYPE(), output->GetExtentType()); + } + } + return 1; +} diff --git a/Graphics/vtkDataObjectToDataSetFilter.h b/Graphics/vtkDataObjectToDataSetFilter.h new file mode 100644 index 0000000..1ef2413 --- /dev/null +++ b/Graphics/vtkDataObjectToDataSetFilter.h @@ -0,0 +1,326 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectToDataSetFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataObjectToDataSetFilter - map field data to concrete dataset +// .SECTION Description +// vtkDataObjectToDataSetFilter is an class that maps a data object (i.e., a field) +// into a concrete dataset, i.e., gives structure to the field by defining a +// geometry and topology. +// +// To use this filter you associate components in the input field data with +// portions of the output dataset. (A component is an array of values from +// the field.) For example, you would specify x-y-z points by assigning +// components from the field for the x, then y, then z values of the points. +// You may also have to specify component ranges (for each z-y-z) to make +// sure that the number of x, y, and z values is the same. Also, you may +// want to normalize the components which helps distribute the data +// uniformly. Once you've setup the filter to combine all the pieces of +// data into a specified dataset (the geometry, topology, point and cell +// data attributes), the various output methods (e.g., GetPolyData()) are +// used to retrieve the final product. +// +// This filter is often used in conjunction with +// vtkFieldDataToAttributeDataFilter. vtkFieldDataToAttributeDataFilter +// takes field data and transforms it into attribute data (e.g., point and +// cell data attributes such as scalars and vectors). To do this, use this +// filter which constructs a concrete dataset and passes the input data +// object field data to its output. and then use +// vtkFieldDataToAttributeDataFilter to generate the attribute data associated +// with the dataset. + +// .SECTION Caveats +// Make sure that the data you extract is consistent. That is, if you have N +// points, extract N x, y, and z components. Also, all the information +// necessary to define a dataset must be given. For example, vtkPolyData +// requires points at a minimum; vtkStructuredPoints requires setting the +// dimensions; vtkStructuredGrid requires defining points and dimensions; +// vtkUnstructuredGrid requires setting points; and vtkRectilinearGrid +// requires that you define the x, y, and z-coordinate arrays (by specifying +// points) as well as the dimensions. +// +// If you wish to create a dataset of just points (i.e., unstructured points +// dataset), create vtkPolyData consisting of points. There will be no cells +// in such a dataset. + +// .SECTION See Also +// vtkDataObject vtkFieldData vtkDataSet vtkPolyData vtkStructuredPoints +// vtkStructuredGrid vtkUnstructuredGrid vtkRectilinearGrid +// vtkDataSetAttributes vtkDataArray + +#ifndef __vtkDataObjectToDataSetFilter_h +#define __vtkDataObjectToDataSetFilter_h + +#include "vtkDataSetAlgorithm.h" + +class vtkCellArray; +class vtkDataArray; +class vtkDataSet; +class vtkPointSet; +class vtkPolyData; +class vtkRectilinearGrid; +class vtkStructuredGrid; +class vtkStructuredPoints; +class vtkUnstructuredGrid; + +class VTK_GRAPHICS_EXPORT vtkDataObjectToDataSetFilter : public vtkDataSetAlgorithm +{ +public: + static vtkDataObjectToDataSetFilter *New(); + vtkTypeRevisionMacro(vtkDataObjectToDataSetFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the input to the filter. + vtkDataObject *GetInput(); + + // Description: + // Control what type of data is generated for output. + void SetDataSetType(int); + vtkGetMacro(DataSetType,int); + void SetDataSetTypeToPolyData() { + this->SetDataSetType(VTK_POLY_DATA);}; + void SetDataSetTypeToStructuredPoints() { + this->SetDataSetType(VTK_STRUCTURED_POINTS);}; + void SetDataSetTypeToStructuredGrid() { + this->SetDataSetType(VTK_STRUCTURED_GRID);}; + void SetDataSetTypeToRectilinearGrid() { + this->SetDataSetType(VTK_RECTILINEAR_GRID);}; + void SetDataSetTypeToUnstructuredGrid() { + this->SetDataSetType(VTK_UNSTRUCTURED_GRID);}; + + // Description: + // Get the output in different forms. The particular method invoked + // should be consistent with the SetDataSetType() method. (Note: + // GetOutput() will always return a type consistent with + // SetDataSetType(). Also, GetOutput() will return NULL if the filter + // aborted due to inconsistent data.) + vtkDataSet *GetOutput(); + vtkDataSet *GetOutput(int idx); + vtkPolyData *GetPolyDataOutput(); + vtkStructuredPoints *GetStructuredPointsOutput(); + vtkStructuredGrid *GetStructuredGridOutput(); + vtkUnstructuredGrid *GetUnstructuredGridOutput(); + vtkRectilinearGrid *GetRectilinearGridOutput(); + + // Description: + // Define the component of the field to be used for the x, y, and z values + // of the points. Note that the parameter comp must lie between (0,2) and + // refers to the x-y-z (i.e., 0,1,2) components of the points. To define + // the field component to use you can specify an array name and the + // component in that array. The (min,max) values are the range of data in + // the component you wish to extract. (This method should be used for + // vtkPolyData, vtkUnstructuredGrid, vtkStructuredGrid, and + // vtkRectilinearGrid.) A convenience method, SetPointComponent(),is also + // provided which does not require setting the (min,max) component range or + // the normalize flag (normalize is set to DefaulatNormalize value). + void SetPointComponent(int comp, char *arrayName, int arrayComp, + int min, int max, int normalize); + void SetPointComponent(int comp, char *arrayName, int arrayComp) + {this->SetPointComponent(comp, arrayName, arrayComp, -1, -1, this->DefaultNormalize);}; + const char *GetPointComponentArrayName(int comp); + int GetPointComponentArrayComponent(int comp); + int GetPointComponentMinRange(int comp); + int GetPointComponentMaxRange(int comp); + int GetPointComponentNormailzeFlag(int comp); + + // Description: + // Define cell connectivity when creating vtkPolyData. You can define + // vertices, lines, polygons, and/or triangle strips via these methods. + // These methods are similar to those for defining points, except + // that no normalization of the data is possible. Basically, you need to + // define an array of values that (for each cell) includes the number of + // points per cell, and then the cell connectivity. (This is the vtk file + // format described in in the textbook or User's Guide.) + void SetVertsComponent(char *arrayName, int arrayComp, int min, int max); + void SetVertsComponent(char *arrayName, int arrayComp) + {this->SetVertsComponent(arrayName, arrayComp, -1, -1);}; + const char *GetVertsComponentArrayName(); + int GetVertsComponentArrayComponent(); + int GetVertsComponentMinRange(); + int GetVertsComponentMaxRange(); + void SetLinesComponent(char *arrayName, int arrayComp, int min, int max); + void SetLinesComponent(char *arrayName, int arrayComp) + {this->SetLinesComponent(arrayName, arrayComp, -1, -1);}; + const char *GetLinesComponentArrayName(); + int GetLinesComponentArrayComponent(); + int GetLinesComponentMinRange(); + int GetLinesComponentMaxRange(); + void SetPolysComponent(char *arrayName, int arrayComp, int min, int max); + void SetPolysComponent(char *arrayName, int arrayComp) + {this->SetPolysComponent(arrayName, arrayComp, -1, -1);}; + const char *GetPolysComponentArrayName(); + int GetPolysComponentArrayComponent(); + int GetPolysComponentMinRange(); + int GetPolysComponentMaxRange(); + void SetStripsComponent(char *arrayName, int arrayComp, int min, int max); + void SetStripsComponent(char *arrayName, int arrayComp) + {this->SetStripsComponent(arrayName, arrayComp, -1, -1);}; + const char *GetStripsComponentArrayName(); + int GetStripsComponentArrayComponent(); + int GetStripsComponentMinRange(); + int GetStripsComponentMaxRange(); + + // Description: + // Define cell types and cell connectivity when creating unstructured grid + // data. These methods are similar to those for defining points, except + // that no normalization of the data is possible. Basically, you need to + // define an array of cell types (an integer value per cell), and another + // array consisting (for each cell) of a number of points per cell, and + // then the cell connectivity. (This is the vtk file format described in + // in the textbook or User's Guide.) + void SetCellTypeComponent(char *arrayName, int arrayComp, + int min, int max); + void SetCellTypeComponent(char *arrayName, int arrayComp) + {this->SetCellTypeComponent(arrayName, arrayComp, -1, -1);}; + const char *GetCellTypeComponentArrayName(); + int GetCellTypeComponentArrayComponent(); + int GetCellTypeComponentMinRange(); + int GetCellTypeComponentMaxRange(); + void SetCellConnectivityComponent(char *arrayName, int arrayComp, + int min, int max); + void SetCellConnectivityComponent(char *arrayName, int arrayComp) + {this->SetCellConnectivityComponent(arrayName, arrayComp, -1, -1);}; + const char *GetCellConnectivityComponentArrayName(); + int GetCellConnectivityComponentArrayComponent(); + int GetCellConnectivityComponentMinRange(); + int GetCellConnectivityComponentMaxRange(); + + // Description: + // Set the default Normalize() flag for those methods setting a default + // Normalize value (e.g., SetPointComponent). + vtkSetMacro(DefaultNormalize,int); + vtkGetMacro(DefaultNormalize,int); + vtkBooleanMacro(DefaultNormalize,int); + + // Decription: + // Specify the dimensions to use if generating a dataset that requires + // dimensions specification (vtkStructuredPoints, vtkStructuredGrid, + // vtkRectilinearGrid). + vtkSetVector3Macro(Dimensions,int); + vtkGetVectorMacro(Dimensions,int,3); + + // Decription: + // Specify the origin to use if generating a dataset whose origin + // can be set (i.e., a vtkStructuredPoints dataset). + vtkSetVector3Macro(Origin,double); + vtkGetVectorMacro(Origin,double,3); + + // Decription: + // Specify the spacing to use if generating a dataset whose spacing + // can be set (i.e., a vtkStructuredPoints dataset). + vtkSetVector3Macro(Spacing,double); + vtkGetVectorMacro(Spacing,double,3); + + // Decription: + // Alternative methods to specify the dimensions, spacing, and origin for those + // datasets requiring this information. You need to specify the name of an array; + // the component of the array, and the range of the array (min,max). These methods + // will override the information given by the previous methods. + void SetDimensionsComponent(char *arrayName, int arrayComp, int min, int max); + void SetDimensionsComponent(char *arrayName, int arrayComp) + {this->SetDimensionsComponent(arrayName, arrayComp, -1, -1);}; + void SetSpacingComponent(char *arrayName, int arrayComp, int min, int max); + void SetSpacingComponent(char *arrayName, int arrayComp) + {this->SetSpacingComponent(arrayName, arrayComp, -1, -1);}; + void SetOriginComponent(char *arrayName, int arrayComp, int min, int max); + void SetOriginComponent(char *arrayName, int arrayComp) + {this->SetOriginComponent(arrayName, arrayComp, -1, -1);}; + +protected: + vtkDataObjectToDataSetFilter(); + ~vtkDataObjectToDataSetFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); //generate output data + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + virtual int RequestDataObject(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + char Updating; + + // control flags used to generate the output dataset + int DataSetType; //the type of dataset to generate + + // Support definition of points + char *PointArrays[3]; //the name of the arrays + int PointArrayComponents[3]; //the array components used for x-y-z + vtkIdType PointComponentRange[3][2]; //the range of the components to use + int PointNormalize[3]; //flags control normalization + + // These define cells for vtkPolyData + char *VertsArray; //the name of the array + int VertsArrayComponent; //the array component + vtkIdType VertsComponentRange[2]; //the range of the components to use + + char *LinesArray; //the name of the array + int LinesArrayComponent; //the array component used for cell types + vtkIdType LinesComponentRange[2]; //the range of the components to use + + char *PolysArray; //the name of the array + int PolysArrayComponent; //the array component + vtkIdType PolysComponentRange[2]; //the range of the components to use + + char *StripsArray; //the name of the array + int StripsArrayComponent; //the array component + vtkIdType StripsComponentRange[2]; //the range of the components to use + + // Used to define vtkUnstructuredGrid datasets + char *CellTypeArray; //the name of the array + int CellTypeArrayComponent; //the array component used for cell types + vtkIdType CellTypeComponentRange[2]; //the range of the components to use + + char *CellConnectivityArray; //the name of the array + int CellConnectivityArrayComponent; //the array components used for cell connectivity + vtkIdType CellConnectivityComponentRange[2]; //the range of the components to use + + // helper methods (and attributes) to construct datasets + void SetArrayName(char* &name, char *newName); + vtkIdType ConstructPoints(vtkDataObject *input, vtkPointSet *ps); + vtkIdType ConstructPoints(vtkDataObject *input, vtkRectilinearGrid *rg); + int ConstructCells(vtkDataObject *input, vtkPolyData *pd); + int ConstructCells(vtkDataObject *input, vtkUnstructuredGrid *ug); + vtkCellArray *ConstructCellArray(vtkDataArray *da, int comp, + vtkIdType compRange[2]); + + // Default value for normalization + int DefaultNormalize; + + // Couple of different ways to specify dimensions, spacing, and origin. + int Dimensions[3]; + double Origin[3]; + double Spacing[3]; + + char *DimensionsArray; //the name of the array + int DimensionsArrayComponent; //the component of the array used for dimensions + vtkIdType DimensionsComponentRange[2]; //the ComponentRange of the array for the dimensions + + char *OriginArray; //the name of the array + int OriginArrayComponent; //the component of the array used for Origins + vtkIdType OriginComponentRange[2]; //the ComponentRange of the array for the Origins + + char *SpacingArray; //the name of the array + int SpacingArrayComponent; //the component of the array used for Spacings + vtkIdType SpacingComponentRange[2]; //the ComponentRange of the array for the Spacings + + void ConstructDimensions(vtkDataObject *input); + void ConstructSpacing(vtkDataObject *input); + void ConstructOrigin(vtkDataObject *input); + +private: + vtkDataObjectToDataSetFilter(const vtkDataObjectToDataSetFilter&); // Not implemented. + void operator=(const vtkDataObjectToDataSetFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkDataSetSurfaceFilter.cxx b/Graphics/vtkDataSetSurfaceFilter.cxx new file mode 100644 index 0000000..38f0af6 --- /dev/null +++ b/Graphics/vtkDataSetSurfaceFilter.cxx @@ -0,0 +1,1617 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetSurfaceFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetSurfaceFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkHexahedron.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPyramid.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkUniformGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGridGeometryFilter.h" +#include "vtkStructuredPoints.h" +#include "vtkTetra.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" + +// Helper structure for hashing faces. +struct vtkFastGeomQuadStruct +{ + vtkIdType p0; + vtkIdType p1; + vtkIdType p2; + vtkIdType p3; + vtkIdType p4; + vtkIdType p5; + vtkIdType SourceId; + struct vtkFastGeomQuadStruct *Next; +}; + +vtkCxxRevisionMacro(vtkDataSetSurfaceFilter, "$Revision: 1.49 $"); +vtkStandardNewMacro(vtkDataSetSurfaceFilter); + +//---------------------------------------------------------------------------- +vtkDataSetSurfaceFilter::vtkDataSetSurfaceFilter() +{ + this->QuadHash = NULL; + this->PointMap = NULL; + this->QuadHashLength = 0; + this->UseStrips = 0; + this->NumberOfNewCells = 0; + + // Quad allocation stuff. + this->FastGeomQuadArrayLength = 0; + this->NumberOfFastGeomQuadArrays = 0; + this->FastGeomQuadArrays = NULL; + this->NextArrayIndex = 0; + this->NextQuadIndex = 0; + + this->PieceInvariant = 0; +} + +//---------------------------------------------------------------------------- +vtkDataSetSurfaceFilter::~vtkDataSetSurfaceFilter() +{ + if (this->QuadHash) + { + this->DeleteQuadHash(); + } +} + +//---------------------------------------------------------------------------- +int vtkDataSetSurfaceFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numCells = input->GetNumberOfCells(); + int *ext; + + if (input->CheckAttributes()) + { + return 1; + } + + if (numCells == 0) + { + return 1; + } + + switch (input->GetDataObjectType()) + { + case VTK_UNSTRUCTURED_GRID: + { + if (!this->UnstructuredGridExecute(input, output)) + { + return 1; + } + output->CheckAttributes(); + return 1; + } + case VTK_RECTILINEAR_GRID: + { + vtkRectilinearGrid *grid = vtkRectilinearGrid::SafeDownCast(input); + ext = grid->GetExtent(); + return this->StructuredExecute(grid, output, ext, inInfo); + } + case VTK_STRUCTURED_GRID: + { + vtkStructuredGrid *grid = vtkStructuredGrid::SafeDownCast(input); + ext = grid->GetExtent(); + return this->StructuredExecute(grid, output, ext, inInfo); + } + case VTK_UNIFORM_GRID: + { + vtkUniformGrid *grid = vtkUniformGrid::SafeDownCast(input); + ext = grid->GetExtent(); + return this->StructuredExecute(grid, output, ext, inInfo); + } + case VTK_STRUCTURED_POINTS: + { + vtkStructuredPoints *image = vtkStructuredPoints::SafeDownCast(input); + ext = image->GetExtent(); + return this->StructuredExecute(image, output, ext, inInfo); + } + case VTK_IMAGE_DATA: + { + vtkImageData *image = vtkImageData::SafeDownCast(input); + ext = image->GetExtent(); + return this->StructuredExecute(image, output, ext, inInfo); + } + case VTK_POLY_DATA: + { + vtkPolyData *inPd = vtkPolyData::SafeDownCast(input); + output->ShallowCopy(inPd); + return 1; + } + default: + return this->DataSetExecute(input, output); + } +} + +//---------------------------------------------------------------------------- +// It is a pain that structured data sets do not share a common super class +// other than data set, and data set does not allow access to extent! +int vtkDataSetSurfaceFilter::StructuredExecute(vtkDataSet *input, + vtkPolyData *output, + int *ext, + vtkInformation *inInfo) +{ + int *wholeExt; + vtkIdType numPoints, cellArraySize; + vtkCellArray *outStrips; + vtkCellArray *outPolys; + vtkPoints *outPoints; + + // Cell Array Size is a pretty good estimate. + // Does not consider direction of strip. + + wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + // Lets figure out how many cells and points we are going to have. + // It may be overkill comptuing the exact amount, but we can do it, so ... + cellArraySize = numPoints = 0; + // xMin face + if (ext[0] == wholeExt[0] && ext[2] != ext[3] && ext[4] != ext[5] && ext[0] != ext[1]) + { + cellArraySize += 2*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + } + // xMax face + if (ext[1] == wholeExt[1] && ext[2] != ext[3] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + } + // yMin face + if (ext[2] == wholeExt[2] && ext[0] != ext[1] && ext[4] != ext[5] && ext[2] != ext[3]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + } + // yMax face + if (ext[3] == wholeExt[3] && ext[0] != ext[1] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + } + // zMin face + if (ext[4] == wholeExt[4] && ext[0] != ext[1] && ext[2] != ext[3] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + } + // zMax face + if (ext[5] == wholeExt[5] && ext[0] != ext[1] && ext[2] != ext[3]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + } + + if (this->UseStrips) + { + outStrips = vtkCellArray::New(); + outStrips->Allocate(cellArraySize); + output->SetStrips(outStrips); + outStrips->Delete(); + } + else + { + outPolys = vtkCellArray::New(); + outPolys->Allocate(cellArraySize); + output->SetPolys(outPolys); + outPolys->Delete(); + } + outPoints = vtkPoints::New(); + outPoints->Allocate(numPoints); + output->SetPoints(outPoints); + outPoints->Delete(); + + // Allocate attributes for copying. + output->GetPointData()->CopyAllocate(input->GetPointData()); + output->GetCellData()->CopyAllocate(input->GetCellData()); + + if (this->UseStrips) + { + // xMin face + this->ExecuteFaceStrips(input, output, 0, ext, 0,1,2, inInfo); + // xMax face + this->ExecuteFaceStrips(input, output, 1, ext, 0,2,1, inInfo); + // yMin face + this->ExecuteFaceStrips(input, output, 0, ext, 1,2,0, inInfo); + // yMax face + this->ExecuteFaceStrips(input, output, 1, ext, 1,0,2, inInfo); + // zMin face + this->ExecuteFaceStrips(input, output, 0, ext, 2,0,1, inInfo); + // zMax face + this->ExecuteFaceStrips(input, output, 1, ext, 2,1,0, inInfo); + } + else + { + // xMin face + this->ExecuteFaceQuads(input, output, 0, ext, 0,1,2, inInfo); + // xMax face + this->ExecuteFaceQuads(input, output, 1, ext, 0,2,1, inInfo); + // yMin face + this->ExecuteFaceQuads(input, output, 0, ext, 1,2,0, inInfo); + // yMax face + this->ExecuteFaceQuads(input, output, 1, ext, 1,0,2, inInfo); + // zMin face + this->ExecuteFaceQuads(input, output, 0, ext, 2,0,1, inInfo); + // zMax face + this->ExecuteFaceQuads(input, output, 1, ext, 2,1,0, inInfo); + } + output->Squeeze(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::ExecuteFaceStrips(vtkDataSet *input, + vtkPolyData *output, + int maxFlag, int *ext, + int aAxis, int bAxis, int cAxis, + vtkInformation *inInfo) +{ + vtkPoints *outPts; + vtkCellArray *outStrips; + vtkPointData *inPD, *outPD; + int *wholeExt; + int pInc[3]; + int qInc[3]; + int cOutInc; + double pt[3]; + vtkIdType inStartPtId; + vtkIdType outStartPtId; + vtkIdType outPtId; + vtkIdType inId, outId; + int ib, ic; + int aA2, bA2, cA2; + int rotatedFlag; + vtkIdType *stripArray; + vtkIdType stripArrayIdx; + + outPts = output->GetPoints(); + outPD = output->GetPointData(); + inPD = input->GetPointData(); + + wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + pInc[0] = 1; + pInc[1] = (ext[1]-ext[0]+1); + pInc[2] = (ext[3]-ext[2]+1) * pInc[1]; + // quad increments (cell incraments, but cInc could be confused with c axis). + qInc[0] = 1; + qInc[1] = ext[1]-ext[0]; + qInc[2] = (ext[3]-ext[2]) * qInc[1]; + + // Tempoprary variables to avoid many multiplications. + aA2 = aAxis * 2; + bA2 = bAxis * 2; + cA2 = cAxis * 2; + + // We might as well put the test for this face here. + if (ext[bA2] == ext[bA2+1] || ext[cA2] == ext[cA2+1]) + { + return; + } + if (maxFlag) + { // max faces have a slightly different condition to avoid coincident faces. + if (ext[aA2] == ext[aA2+1] || ext[aA2+1] < wholeExt[aA2+1]) + { + return; + } + } + else + { + if (ext[aA2] > wholeExt[aA2]) + { + return; + } + } + + // Lets rotate the image to make b the longest axis. + // This will make the tri strips longer. + rotatedFlag = 0; + if (ext[bA2+1]-ext[bA2] < ext[cA2+1]-ext[cA2]) + { + int tmp; + rotatedFlag = 1; + tmp = cAxis; + cAxis = bAxis; + bAxis = tmp; + bA2 = bAxis * 2; + cA2 = cAxis * 2; + } + + // Assuming no ghost cells ... + inStartPtId = 0; + if (maxFlag) + { + inStartPtId = pInc[aAxis]*(ext[aA2+1]-ext[aA2]); + } + + outStartPtId = outPts->GetNumberOfPoints(); + // Make the points for this face. + for (ic = ext[cA2]; ic <= ext[cA2+1]; ++ic) + { + for (ib = ext[bA2]; ib <= ext[bA2+1]; ++ib) + { + inId = inStartPtId + (ib-ext[bA2])*pInc[bAxis] + + (ic-ext[cA2])*pInc[cAxis]; + input->GetPoint(inId, pt); + outId = outPts->InsertNextPoint(pt); + // Copy point data. + outPD->CopyData(inPD,inId,outId); + } + } + + // Do the cells. + cOutInc = ext[bA2+1] - ext[bA2] + 1; + + // Tri Strips (no cell data ...). + // Allocate the temporary array user to create the tri strips. + stripArray = new vtkIdType[2*(ext[bA2+1]-ext[bA2]+1)]; + // Make the cells for this face. + outStrips = output->GetStrips(); + for (ic = ext[cA2]; ic < ext[cA2+1]; ++ic) + { + // Fill in the array describing the strips. + stripArrayIdx = 0; + outPtId = outStartPtId + (ic-ext[cA2])*cOutInc; + if (rotatedFlag) + { + for (ib = ext[bA2]; ib <= ext[bA2+1]; ++ib) + { + stripArray[stripArrayIdx++] = outPtId+cOutInc; + stripArray[stripArrayIdx++] = outPtId; + ++outPtId; + } + } + else + { // Faster to justto dupicate the inner most loop. + for (ib = ext[bA2]; ib <= ext[bA2+1]; ++ib) + { + stripArray[stripArrayIdx++] = outPtId; + stripArray[stripArrayIdx++] = outPtId+cOutInc; + ++outPtId; + } + } + outStrips->InsertNextCell(stripArrayIdx, stripArray); + } + delete [] stripArray; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::ExecuteFaceQuads(vtkDataSet *input, + vtkPolyData *output, + int maxFlag, int *ext, + int aAxis, int bAxis, int cAxis, + vtkInformation *inInfo) +{ + vtkPoints *outPts; + vtkCellArray *outPolys; + vtkPointData *inPD, *outPD; + vtkCellData *inCD, *outCD; + int *wholeExt; + int pInc[3]; + int qInc[3]; + int cOutInc; + double pt[3]; + vtkIdType inStartPtId; + vtkIdType inStartCellId; + vtkIdType outStartPtId; + vtkIdType outPtId; + vtkIdType inId, outId; + int ib, ic; + int aA2, bA2, cA2; + + outPts = output->GetPoints(); + outPD = output->GetPointData(); + inPD = input->GetPointData(); + outCD = output->GetCellData(); + inCD = input->GetCellData(); + + wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + pInc[0] = 1; + pInc[1] = (ext[1]-ext[0]+1); + pInc[2] = (ext[3]-ext[2]+1) * pInc[1]; + // quad increments (cell incraments, but cInc could be confused with c axis). + qInc[0] = 1; + qInc[1] = ext[1]-ext[0]; + // The conditions are for when we have one or more degenerate axes (2d or 1d cells). + if (qInc[1] == 0) + { + qInc[1] = 1; + } + qInc[2] = (ext[3]-ext[2]) * qInc[1]; + if (qInc[2] == 0) + { + qInc[2] = qInc[1]; + } + + // Temporary variables to avoid many multiplications. + aA2 = aAxis * 2; + bA2 = bAxis * 2; + cA2 = cAxis * 2; + + // We might as well put the test for this face here. + if (ext[bA2] == ext[bA2+1] || ext[cA2] == ext[cA2+1]) + { + return; + } + if (maxFlag) + { + if (ext[aA2+1] < wholeExt[aA2+1]) + { + return; + } + } + else + { // min faces have a slightly different condition to avoid coincident faces. + if (ext[aA2] == ext[aA2+1] || ext[aA2] > wholeExt[aA2]) + { + return; + } + } + + // Assuming no ghost cells ... + inStartPtId = inStartCellId = 0; + // I put this confusing conditional to fix a regression test. + // If we are creating a maximum face, then we indeed have to offset the input cell Ids. + // However, vtkGeometryFilter created a 2d image as a max face, but the cells are copied + // as a min face (no offset). Hence maxFlag = 1 and there should be no offset. + if (maxFlag && ext[aA2] < ext[1+aA2]) + { + inStartPtId = pInc[aAxis]*(ext[aA2+1]-ext[aA2]); + inStartCellId = qInc[aAxis]*(ext[aA2+1]-ext[aA2]-1); + } + + outStartPtId = outPts->GetNumberOfPoints(); + // Make the points for this face. + for (ic = ext[cA2]; ic <= ext[cA2+1]; ++ic) + { + for (ib = ext[bA2]; ib <= ext[bA2+1]; ++ib) + { + inId = inStartPtId + (ib-ext[bA2])*pInc[bAxis] + + (ic-ext[cA2])*pInc[cAxis]; + input->GetPoint(inId, pt); + outId = outPts->InsertNextPoint(pt); + // Copy point data. + outPD->CopyData(inPD,inId,outId); + } + } + + // Do the cells. + cOutInc = ext[bA2+1] - ext[bA2] + 1; + + outPolys = output->GetPolys(); + + // Old method for creating quads (needed for cell data.). + for (ic = ext[cA2]; ic < ext[cA2+1]; ++ic) + { + for (ib = ext[bA2]; ib < ext[bA2+1]; ++ib) + { + outPtId = outStartPtId + (ib-ext[bA2]) + (ic-ext[cA2])*cOutInc; + inId = inStartCellId + (ib-ext[bA2])*qInc[bAxis] + (ic-ext[cA2])*qInc[cAxis]; + + outId = outPolys->InsertNextCell(4); + outPolys->InsertCellPoint(outPtId); + outPolys->InsertCellPoint(outPtId+cOutInc); + outPolys->InsertCellPoint(outPtId+cOutInc+1); + outPolys->InsertCellPoint(outPtId+1); + // Copy cell data. + outCD->CopyData(inCD,inId,outId); + } + } +} + +//---------------------------------------------------------------------------- +int vtkDataSetSurfaceFilter::DataSetExecute(vtkDataSet *input, + vtkPolyData *output) +{ + vtkIdType cellId, newCellId; + int i, j; + vtkIdType numPts=input->GetNumberOfPoints(); + vtkIdType numCells=input->GetNumberOfCells(); + vtkGenericCell *cell; + vtkCell *face; + double x[3]; + vtkIdList *cellIds; + vtkIdList *pts; + vtkPoints *newPts; + vtkIdType ptId, pt; + int npts; + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + + if (numCells == 0) + { + return 1; + } + + cellIds = vtkIdList::New(); + pts = vtkIdList::New(); + + vtkDebugMacro(<<"Executing geometry filter"); + + cell = vtkGenericCell::New(); + + // Allocate + // + newPts = vtkPoints::New(); + newPts->Allocate(numPts,numPts/2); + output->Allocate(4*numCells,numCells/2); + outputPD->CopyAllocate(pd,numPts,numPts/2); + outputCD->CopyAllocate(cd,numCells,numCells/2); + + // Traverse cells to extract geometry + // + int abort=0; + vtkIdType progressInterval = numCells/20 + 1; + + for(cellId=0; cellId < numCells && !abort; cellId++) + { + //Progress and abort method support + if ( !(cellId % progressInterval) ) + { + vtkDebugMacro(<<"Process cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + abort = this->GetAbortExecute(); + } + + input->GetCell(cellId,cell); + switch (cell->GetCellDimension()) + { + // create new points and then cell + case 0: case 1: case 2: + + npts = cell->GetNumberOfPoints(); + pts->Reset(); + for ( i=0; i < npts; i++) + { + ptId = cell->GetPointId(i); + input->GetPoint(ptId, x); + pt = newPts->InsertNextPoint(x); + outputPD->CopyData(pd,ptId,pt); + pts->InsertId(i,pt); + } + newCellId = output->InsertNextCell(cell->GetCellType(), pts); + outputCD->CopyData(cd,cellId,newCellId); + break; + case 3: + for (j=0; j < cell->GetNumberOfFaces(); j++) + { + face = cell->GetFace(j); + input->GetCellNeighbors(cellId, face->PointIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0) + { + npts = face->GetNumberOfPoints(); + pts->Reset(); + for ( i=0; i < npts; i++) + { + ptId = face->GetPointId(i); + input->GetPoint(ptId, x); + pt = newPts->InsertNextPoint(x); + outputPD->CopyData(pd,ptId,pt); + pts->InsertId(i,pt); + } + newCellId = output->InsertNextCell(face->GetCellType(), pts); + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + } //switch + } //for all cells + + vtkDebugMacro(<<"Extracted " << newPts->GetNumberOfPoints() << " points," + << output->GetNumberOfCells() << " cells."); + + // Update ourselves and release memory + // + cell->Delete(); + output->SetPoints(newPts); + newPts->Delete(); + + //free storage + output->Squeeze(); + + cellIds->Delete(); + pts->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataSetSurfaceFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces, ghostLevels; + + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevels = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + if (numPieces > 1 && this->PieceInvariant) + { + // The special execute for structured data handle boundaries internally. + // PolyData does not need any ghost levels. + vtkDataObject* dobj = inInfo->Get(vtkDataObject::DATA_OBJECT()); + if (dobj && !strcmp(dobj->GetClassName(), "vtkUnstructuredGrid")) + { // Processing does nothing fo ghost levels yet so ... + // Be careful to set output ghost level value one less than default + // when they are implemented. I had trouble with multiple executes. + ++ghostLevels; + } + } + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevels); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataSetSurfaceFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->UseStrips) + { + os << indent << "UseStripsOn\n"; + } + else + { + os << indent << "UseStripsOff\n"; + } + + os << indent << "PieceInvariant: " << this->PieceInvariant << endl; +} + +//======================================================================== +// Tris are now degenerate quads so we only need one hash table. +// We might want to change the method names from QuadHash to just Hash. + + + +//---------------------------------------------------------------------------- +int vtkDataSetSurfaceFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput, + vtkPolyData *output) +{ + vtkCellArray *newVerts; + vtkCellArray *newLines; + vtkCellArray *newPolys; + vtkPoints *newPts; + vtkIdType *ids; + int progressCount; + vtkIdType cellId; + int i, j; + vtkIdType *cellPointer; + int cellType; + vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast(dataSetInput); + vtkIdType numPts=input->GetNumberOfPoints(); + vtkIdType numCells=input->GetNumberOfCells(); + vtkGenericCell *cell; + int numFacePts, numCellPts; + vtkIdType inPtId, outPtId; + vtkPointData *inputPD = input->GetPointData(); + vtkCellData *inputCD = input->GetCellData(); + vtkCellData *cd = input->GetCellData(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkIdType outPts[6]; + vtkFastGeomQuad *q; + unsigned char* cellTypes = input->GetCellTypesArray()->GetPointer(0); + + // These are for the default case/ + vtkIdList *pts; + vtkPoints *coords; + vtkCell *face; + int flag2D = 0; + + pts = vtkIdList::New(); + coords = vtkPoints::New(); + cell = vtkGenericCell::New(); + + this->NumberOfNewCells = 0; + this->InitializeQuadHash(numPts); + + // Allocate + // + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + newPolys = vtkCellArray::New(); + newPolys->Allocate(4*numCells,numCells/2); + newVerts = vtkCellArray::New(); + newLines = vtkCellArray::New(); + + outputPD->CopyAllocate(inputPD, numPts, numPts/2); + outputCD->CopyAllocate(inputCD, numCells, numCells/2); + + + // First insert all points. Points have to come first in poly data. + cellPointer = input->GetCells()->GetPointer(); + for(cellId=0; cellId < numCells; cellId++) + { + // Direct access to cells. + cellType = cellTypes[cellId]; + numCellPts = cellPointer[0]; + ids = cellPointer+1; + // Move to the next cell. + cellPointer += (1 + *cellPointer); + + // A couple of common cases to see if things go faster. + if (cellType == VTK_VERTEX || cellType == VTK_POLY_VERTEX) + { + newVerts->InsertNextCell(numCellPts); + for (i = 0; i < numCellPts; ++i) + { + inPtId = ids[i]; + outPtId = this->GetOutputPointId(inPtId, input, newPts, outputPD); + newVerts->InsertCellPoint(outPtId); + } + outputCD->CopyData(cd, cellId, this->NumberOfNewCells++); + } + } + + // Traverse cells to extract geometry + // + progressCount = 0; + int abort=0; + vtkIdType progressInterval = numCells/20 + 1; + + // First insert all points lines in output and 3D geometry in hash. + // Save 2D geometry for second pass. + // initialize the pointer to the cells for fast traversal. + cellPointer = input->GetCells()->GetPointer(); + for(cellId=0; cellId < numCells && !abort; cellId++) + { + //Progress and abort method support + if ( progressCount >= progressInterval ) + { + vtkDebugMacro(<<"Process cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + abort = this->GetAbortExecute(); + progressCount = 0; + } + progressCount++; + + // Direct access to cells. + cellType = cellTypes[cellId]; + numCellPts = cellPointer[0]; + ids = cellPointer+1; + // Move to the next cell. + cellPointer += (1 + *cellPointer); + + // A couple of common cases to see if things go faster. + if (cellType == VTK_VERTEX || cellType == VTK_POLY_VERTEX) + { + // Do nothing. This case was handled in the provious loop. + } + else if (cellType == VTK_LINE || cellType == VTK_POLY_LINE) + { + newLines->InsertNextCell(numCellPts); + for (i = 0; i < numCellPts; ++i) + { + inPtId = ids[i]; + outPtId = this->GetOutputPointId(inPtId, input, newPts, outputPD); + newLines->InsertCellPoint(outPtId); + } + outputCD->CopyData(cd, cellId, this->NumberOfNewCells++); + } + else if (cellType == VTK_HEXAHEDRON) + { + this->InsertQuadInHash(ids[0], ids[1], ids[5], ids[4], cellId); + this->InsertQuadInHash(ids[0], ids[3], ids[2], ids[1], cellId); + this->InsertQuadInHash(ids[0], ids[4], ids[7], ids[3], cellId); + this->InsertQuadInHash(ids[1], ids[2], ids[6], ids[5], cellId); + this->InsertQuadInHash(ids[2], ids[3], ids[7], ids[6], cellId); + this->InsertQuadInHash(ids[4], ids[5], ids[6], ids[7], cellId); + } + else if (cellType == VTK_VOXEL) + { + this->InsertQuadInHash(ids[0], ids[1], ids[5], ids[4], cellId); + this->InsertQuadInHash(ids[0], ids[2], ids[3], ids[1], cellId); + this->InsertQuadInHash(ids[0], ids[4], ids[6], ids[2], cellId); + this->InsertQuadInHash(ids[1], ids[3], ids[7], ids[5], cellId); + this->InsertQuadInHash(ids[2], ids[6], ids[7], ids[3], cellId); + this->InsertQuadInHash(ids[4], ids[5], ids[7], ids[6], cellId); + } + else if (cellType == VTK_TETRA) + { + this->InsertTriInHash(ids[0], ids[1], ids[3], cellId); + this->InsertTriInHash(ids[0], ids[2], ids[1], cellId); + this->InsertTriInHash(ids[0], ids[3], ids[2], cellId); + this->InsertTriInHash(ids[1], ids[2], ids[3], cellId); + } + else if (cellType == VTK_PENTAGONAL_PRISM) + { + // The quads : + this->InsertQuadInHash (ids[0], ids[1], ids[6], ids[5], cellId); + this->InsertQuadInHash (ids[1], ids[2], ids[7], ids[6], cellId); + this->InsertQuadInHash (ids[2], ids[3], ids[8], ids[7], cellId); + this->InsertQuadInHash (ids[3], ids[4], ids[9], ids[8], cellId); + this->InsertQuadInHash (ids[4], ids[0], ids[5], ids[9], cellId); + this->InsertPentaInHash(ids[0], ids[1], ids[2], ids[3], ids[4], cellId); + this->InsertPentaInHash(ids[5], ids[6], ids[7], ids[8], ids[9], cellId); + } + else if (cellType == VTK_HEXAGONAL_PRISM) + { + // The quads : + this->InsertQuadInHash(ids[0], ids[1], ids[7], ids[6], cellId); + this->InsertQuadInHash(ids[1], ids[2], ids[8], ids[7], cellId); + this->InsertQuadInHash(ids[2], ids[3], ids[9], ids[8], cellId); + this->InsertQuadInHash(ids[3], ids[4], ids[10], ids[9], cellId); + this->InsertQuadInHash(ids[4], ids[5], ids[11], ids[10], cellId); + this->InsertQuadInHash(ids[5], ids[0], ids[6], ids[11], cellId); + this->InsertHexInHash (ids[0], ids[1], ids[2], ids[3], ids[4], ids[5], cellId); + this->InsertHexInHash (ids[6], ids[7], ids[8], ids[9], ids[10], ids[11], cellId); + } + else if (cellType == VTK_PIXEL || cellType == VTK_QUAD || + cellType == VTK_TRIANGLE || cellType == VTK_POLYGON || + cellType == VTK_TRIANGLE_STRIP || + cellType == VTK_QUADRATIC_TRIANGLE || + cellType == VTK_QUADRATIC_QUAD ) + { // save 2D cells for second pass + flag2D = 1; + } + else + // Default way of getting faces. Differentiates between linear + // and higher order cells. + { + input->GetCell(cellId,cell); + if ( cell->IsLinear() ) + { + if (cell->GetCellDimension() == 3) + { + int numFaces = cell->GetNumberOfFaces(); + for (j=0; j < numFaces; j++) + { + face = cell->GetFace(j); + numFacePts = face->GetNumberOfPoints(); + if (numFacePts == 4) + { + this->InsertQuadInHash(face->PointIds->GetId(0), + face->PointIds->GetId(1), + face->PointIds->GetId(2), + face->PointIds->GetId(3), cellId); + } + else if (numFacePts == 3) + { + this->InsertTriInHash(face->PointIds->GetId(0), + face->PointIds->GetId(1), + face->PointIds->GetId(2), cellId); + } + else + { + vtkWarningMacro(<< "I cannot deal with faces with " << numFacePts + << " points."); + } + } // for all cell faces + } // if 3D + else + { + vtkDebugMacro("Missing cell type."); + } + } // a linear cell type + + else //process nonlinear cells via triangulation + { + if ( cell->GetCellDimension() == 1 ) + { + cell->Triangulate(0,pts,coords); + for (i=0; i < pts->GetNumberOfIds(); i+=2) + { + newLines->InsertNextCell(2); + inPtId = pts->GetId(i); + outputCD->CopyData( cd, cellId, this->NumberOfNewCells++ ); + outPtId = this->GetOutputPointId(inPtId, input, newPts, outputPD); + newLines->InsertCellPoint(outPtId); + inPtId = pts->GetId(i+1); + outPtId = this->GetOutputPointId(inPtId, input, newPts, outputPD); + newLines->InsertCellPoint(outPtId); + } + } + else if ( cell->GetCellDimension() == 2 ) + { + vtkWarningMacro(<< "2-D nonlinear cells must be processed with all other 2-D cells."); + } + else //3D nonlinear cell + { + vtkIdList *cellIds = vtkIdList::New(); + int numFaces = cell->GetNumberOfFaces(); + for (j=0; j < numFaces; j++) + { + face = cell->GetFace(j); + input->GetCellNeighbors(cellId, face->PointIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0) + { + // FIXME: Face could not be consistent. vtkOrderedTriangulator is a better option + face->Triangulate(0,pts,coords); + for (i=0; i < pts->GetNumberOfIds(); i+=3) + { + this->InsertTriInHash(pts->GetId(i), pts->GetId(i+1), + pts->GetId(i+2), cellId); + } + } + } + cellIds->Delete(); + } //3d cell + } //nonlinear cell + } // Cell type else. + } // for all cells. + + // It would be possible to add these (except for polygons with 5+ sides) + // to the hashes. Alternatively, the higher order 2d cells could be handled + // in the following loop. + + // Now insert 2DCells. Because of poly datas (cell data) ordering, + // the 2D cells have to come after points and lines. + // initialize the pointer to the cells for fast traversal. + cellPointer = input->GetCells()->GetPointer(); + for(cellId=0; cellId < numCells && !abort && flag2D; cellId++) + { + // Direct acces to cells. + cellType = input->GetCellType(cellId); + numCellPts = cellPointer[0]; + ids = cellPointer+1; + // Move to the next cell. + cellPointer += (1 + *cellPointer); + + // A couple of common cases to see if things go faster. + if (cellType == VTK_PIXEL) + { // Do we really want to insert the 2D cells into a hash? + pts->Reset(); + pts->InsertId(0, this->GetOutputPointId(ids[0], input, newPts, outputPD)); + pts->InsertId(1, this->GetOutputPointId(ids[1], input, newPts, outputPD)); + pts->InsertId(2, this->GetOutputPointId(ids[3], input, newPts, outputPD)); + pts->InsertId(3, this->GetOutputPointId(ids[2], input, newPts, outputPD)); + newPolys->InsertNextCell(pts); + outputCD->CopyData(cd, cellId, this->NumberOfNewCells++); + } + else if (cellType == VTK_POLYGON || cellType == VTK_TRIANGLE || cellType == VTK_QUAD) + { + pts->Reset(); + for ( i=0; i < numCellPts; i++) + { + inPtId = ids[i]; + outPtId = this->GetOutputPointId(inPtId, input, newPts, outputPD); + pts->InsertId(i, outPtId); + } + newPolys->InsertNextCell(pts); + outputCD->CopyData(cd, cellId, this->NumberOfNewCells++); + } + else if (cellType == VTK_TRIANGLE_STRIP) + { + // Change strips to triangles so we do not have to worry about order. + int toggle = 0; + vtkIdType ptIds[3]; + // This check is not really necessary. It was put here because of another (now fixed) bug. + if (numCellPts > 1) + { + ptIds[0] = this->GetOutputPointId(ids[0], input, newPts, outputPD); + ptIds[1] = this->GetOutputPointId(ids[1], input, newPts, outputPD); + for (i = 2; i < numCellPts; ++i) + { + ptIds[2] = this->GetOutputPointId(ids[i], input, newPts, outputPD); + newPolys->InsertNextCell(3, ptIds); + outputCD->CopyData(cd, cellId, this->NumberOfNewCells++); + ptIds[toggle] = ptIds[2]; + toggle = !toggle; + } + } + } + else if ( cellType == VTK_QUADRATIC_TRIANGLE || cellType == VTK_QUADRATIC_QUAD ) + { + input->GetCell( cellId, cell ); + cell->Triangulate( 0, pts, coords ); + for ( i=0; i < pts->GetNumberOfIds(); i+=3 ) + { + outPts[0] = this->GetOutputPointId( pts->GetId(i), input, newPts, outputPD ); + outPts[1] = this->GetOutputPointId( pts->GetId(i+1), input, newPts, outputPD ); + outPts[2] = this->GetOutputPointId( pts->GetId(i+2), input, newPts, outputPD ); + newPolys->InsertNextCell( 3, outPts ); + outputCD->CopyData(cd, cellId, this->NumberOfNewCells++); + } + } + } // for all cells. + + + // Now transfer geometry from hash to output (only triangles and quads). + this->InitQuadHashTraversal(); + while ( (q = this->GetNextVisibleQuadFromHash()) ) + { + // If Tri or Quad: + if( q->p4 == -1 && q->p5 == -1) + { + if ( q->p0 == q->p3) + { + outPts[0] = this->GetOutputPointId(q->p0, input, newPts, outputPD); + outPts[1] = this->GetOutputPointId(q->p1, input, newPts, outputPD); + outPts[2] = this->GetOutputPointId(q->p2, input, newPts, outputPD); + newPolys->InsertNextCell(3, outPts); + outputCD->CopyData(inputCD, q->SourceId, this->NumberOfNewCells++); + } + else + { + outPts[0] = this->GetOutputPointId(q->p0, input, newPts, outputPD); + outPts[1] = this->GetOutputPointId(q->p1, input, newPts, outputPD); + outPts[2] = this->GetOutputPointId(q->p2, input, newPts, outputPD); + outPts[3] = this->GetOutputPointId(q->p3, input, newPts, outputPD); + newPolys->InsertNextCell(4, outPts); + outputCD->CopyData(inputCD, q->SourceId, this->NumberOfNewCells++); + } + } + else // Penta or Hex + { + if( q->p4 != -1 && q->p5 == -1) + { + outPts[0] = this->GetOutputPointId(q->p0, input, newPts, outputPD); + outPts[1] = this->GetOutputPointId(q->p1, input, newPts, outputPD); + outPts[2] = this->GetOutputPointId(q->p2, input, newPts, outputPD); + outPts[3] = this->GetOutputPointId(q->p3, input, newPts, outputPD); + outPts[4] = this->GetOutputPointId(q->p4, input, newPts, outputPD); + newPolys->InsertNextCell(5, outPts); + outputCD->CopyData(inputCD, q->SourceId, this->NumberOfNewCells++); + } + else + { + outPts[0] = this->GetOutputPointId(q->p0, input, newPts, outputPD); + outPts[1] = this->GetOutputPointId(q->p1, input, newPts, outputPD); + outPts[2] = this->GetOutputPointId(q->p2, input, newPts, outputPD); + outPts[3] = this->GetOutputPointId(q->p3, input, newPts, outputPD); + outPts[4] = this->GetOutputPointId(q->p4, input, newPts, outputPD); + outPts[5] = this->GetOutputPointId(q->p5, input, newPts, outputPD); + newPolys->InsertNextCell(6, outPts); + outputCD->CopyData(inputCD, q->SourceId, this->NumberOfNewCells++); + } + } + } + + // Update ourselves and release memory + // + cell->Delete(); + coords->Delete(); + pts->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + output->SetPolys(newPolys); + newPolys->Delete(); + if (newVerts->GetNumberOfCells() > 0) + { + output->SetVerts(newVerts); + } + newVerts->Delete(); + newVerts = NULL; + if (newLines->GetNumberOfCells() > 0) + { + output->SetLines(newLines); + } + newLines->Delete(); + + //free storage + output->Squeeze(); + + int ghostLevels = output->GetUpdateGhostLevel(); + if (this->PieceInvariant) + { + output->RemoveGhostCells(ghostLevels+1); + } + + this->DeleteQuadHash(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::InitializeQuadHash(vtkIdType numPoints) +{ + vtkIdType i; + + if (this->QuadHash) + { + this->DeleteQuadHash(); + } + + // Prepare our special quad allocator (for efficiency). + this->InitFastGeomQuadAllocation(numPoints); + + this->QuadHash = new vtkFastGeomQuad*[numPoints]; + this->QuadHashLength = numPoints; + this->PointMap = new vtkIdType[numPoints]; + for (i = 0; i < numPoints; ++i) + { + this->QuadHash[i] = NULL; + this->PointMap[i] = -1; + } +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::DeleteQuadHash() +{ + vtkIdType i; + + this->DeleteAllFastGeomQuads(); + + for (i = 0; i < this->QuadHashLength; ++i) + { + this->QuadHash[i] = NULL; + } + + delete [] this->QuadHash; + this->QuadHash = NULL; + this->QuadHashLength = 0; + delete [] this->PointMap; + this->PointMap = NULL; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::InsertQuadInHash(vtkIdType a, vtkIdType b, + vtkIdType c, vtkIdType d, + vtkIdType sourceId) +{ + int tmp; + vtkFastGeomQuad *quad, **end; + + // Reorder to get smallest id in a. + if (b < a && b < c && b < d) + { + tmp = a; + a = b; + b = c; + c = d; + d = tmp; + } + else if (c < a && c < b && c < d) + { + tmp = a; + a = c; + c = tmp; + tmp = b; + b = d; + d = tmp; + } + else if (d < a && d < b && d < c) + { + tmp = a; + a = d; + d = c; + c = b; + b = tmp; + } + + // Look for existing quad in the hash; + end = this->QuadHash + a; + quad = *end; + while (quad) + { + end = &(quad->Next); + // a has to match in this bin. + // c should be independant of point order. + if (c == quad->p2) + { + // Check boh orders for b and d. + if ((b == quad->p1 && d == quad->p3) || (b == quad->p3 && d == quad->p1)) + { + // We have a match. + quad->SourceId = -1; + // That is all we need to do. Hide any quad shared by two or more cells. + return; + } + } + quad = *end; + } + + // Create a new quad and add it to the hash. + quad = this->NewFastGeomQuad(); + quad->Next = NULL; + quad->SourceId = sourceId; + quad->p0 = a; + quad->p1 = b; + quad->p2 = c; + quad->p3 = d; + quad->p4 = -1; + quad->p5 = -1; + *end = quad; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::InsertTriInHash(vtkIdType a, vtkIdType b, + vtkIdType c, vtkIdType sourceId) +{ + int tmp; + vtkFastGeomQuad *quad, **end; + + // Reorder to get smallest id in a. + if (b < a && b < c) + { + tmp = a; + a = b; + b = c; + c = tmp; + } + else if (c < a && c < b) + { + tmp = a; + a = c; + c = b; + b = tmp; + } + // We can't put the second smnallest in b because it might change the order + // of the verticies in the final triangle. + + // Look for existing tri in the hash; + end = this->QuadHash + a; + quad = *end; + while (quad) + { + end = &(quad->Next); + // a has to match in this bin. + if (quad->p0 == quad->p3) + { + if ((b == quad->p1 && c == quad->p2) || (b == quad->p2 && c == quad->p1)) + { + // We have a match. + quad->SourceId = -1; + // That is all we need to do. Hide any tri shared by two or more cells. + return; + } + } + quad = *end; + } + + // Create a new quad and add it to the hash. + quad = this->NewFastGeomQuad(); + quad->Next = NULL; + quad->SourceId = sourceId; + quad->p0 = a; + quad->p1 = b; + quad->p2 = c; + quad->p3 = a; + quad->p4 = -1; + quad->p5 = -1; + *end = quad; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::InsertPentaInHash(vtkIdType a, vtkIdType b, + vtkIdType c, vtkIdType d, + vtkIdType e, vtkIdType sourceId) +{ + int idxmin = 0; + vtkIdType min = a; + vtkFastGeomQuad *quad, **end; + + // Copy in an array + vtkIdType tab[5] = {a, b, c, d, e}; + + // Reorder to get smallest id in a. + for(int i=0;i<5;i++) + { + if( tab[i] < min ) + { + min = tab[i]; + idxmin = i; + } + } + a = tab[idxmin]; + b = tab[(idxmin+1)%5]; + c = tab[(idxmin+2)%5]; + d = tab[(idxmin+3)%5]; + e = tab[(idxmin+4)%5]; + + // Look for existing hex in the hash; + end = this->QuadHash + a; + quad = *end; + while (quad) + { + end = &(quad->Next); + // a has to match in this bin. + if (quad->p5 == -1) + { + if ((b == quad->p1 && c == quad->p2 && d == quad->p3 && e == quad->p4) + || (b == quad->p4 && c == quad->p3 && d == quad->p2 && e == quad->p1)) + { + // We have a match. + quad->SourceId = -1; + // That is all we need to do. Hide any tri shared by two or more cells. + return; + } + } + quad = *end; + } + + // Create a new quad and add it to the hash. + quad = this->NewFastGeomQuad(); + quad->Next = NULL; + quad->SourceId = sourceId; + quad->p0 = a; + quad->p1 = b; + quad->p2 = c; + quad->p3 = d; + quad->p4 = e; + quad->p5 = -1; + *end = quad; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::InsertHexInHash(vtkIdType a, vtkIdType b, + vtkIdType c, vtkIdType d, + vtkIdType e, vtkIdType f, + vtkIdType sourceId) +{ + int idxmin = 0; + vtkIdType min = a; + vtkFastGeomQuad *quad, **end; + + // Copy in an array + vtkIdType tab[6] = {a, b, c, d, e, f}; + + // Reorder to get smallest id in a. + for(int i=0;i<6;i++) + { + if( tab[i] < min ) + { + min = tab[i]; + idxmin = i; + } + } + a = tab[idxmin]; + b = tab[(idxmin+1)%6]; + c = tab[(idxmin+2)%6]; + d = tab[(idxmin+3)%6]; + e = tab[(idxmin+4)%6]; + f = tab[(idxmin+5)%6]; + + // Look for existing hex in the hash; + end = this->QuadHash + a; + quad = *end; + while (quad) + { + end = &(quad->Next); + // a has to match in this bin. + // d should be independant of point order. + if (d == quad->p3) + { + if ((b == quad->p1 && c == quad->p2 && e == quad->p4 && f == quad->p5) + || (b == quad->p5 && c == quad->p4 && e == quad->p2 && f == quad->p1)) + { + // We have a match. + quad->SourceId = -1; + // That is all we need to do. Hide any tri shared by two or more cells. + return; + } + } + quad = *end; + } + + // Create a new quad and add it to the hash. + quad = this->NewFastGeomQuad(); + quad->Next = NULL; + quad->SourceId = sourceId; + quad->p0 = a; + quad->p1 = b; + quad->p2 = c; + quad->p3 = d; + quad->p4 = e; + quad->p5 = f; + *end = quad; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::InitFastGeomQuadAllocation(int numberOfCells) +{ + int idx; + + this->DeleteAllFastGeomQuads(); + // Allocate 100 pointers to arrays. + // This should be plenty (unless we have riangle strips) ... + this->NumberOfFastGeomQuadArrays = 100; + this->FastGeomQuadArrays = new vtkFastGeomQuad*[100]; + // Initalize all to NULL; + for (idx = 0; idx < 100; ++idx) + { + this->FastGeomQuadArrays[idx] = NULL; + } + // Set pointer to the begining. + this->NextArrayIndex = 0; + this->NextQuadIndex = 0; + + // Lets keep the chunk size relatively small. + if (numberOfCells < 100) + { + this->FastGeomQuadArrayLength = 50; + } + else + { + this->FastGeomQuadArrayLength = numberOfCells / 2; + } +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::DeleteAllFastGeomQuads() +{ + int idx; + + for (idx = 0; idx < this->NumberOfFastGeomQuadArrays; ++idx) + { + if (this->FastGeomQuadArrays[idx]) + { + delete [] this->FastGeomQuadArrays[idx]; + this->FastGeomQuadArrays[idx] = NULL; + } + } + if (this->FastGeomQuadArrays) + { + delete [] this->FastGeomQuadArrays; + this->FastGeomQuadArrays = NULL; + } + this->FastGeomQuadArrayLength = 0; + this->NumberOfFastGeomQuadArrays = 0; + this->NextArrayIndex = 0; + this->NextQuadIndex = 0; +} + +//---------------------------------------------------------------------------- +vtkFastGeomQuad* vtkDataSetSurfaceFilter::NewFastGeomQuad() +{ + if (this->FastGeomQuadArrayLength == 0) + { + vtkErrorMacro("Face hash allocation has not been initialized."); + return NULL; + } + + // Although this should not happen often, check first. + if (this->NextArrayIndex >= this->NumberOfFastGeomQuadArrays) + { + int idx, num; + vtkFastGeomQuad** newArrays; + num = this->FastGeomQuadArrayLength * 2; + newArrays = new vtkFastGeomQuad*[num]; + for (idx = 0; idx < num; ++idx) + { + newArrays[idx] = NULL; + if (idx < this->NumberOfFastGeomQuadArrays) + { + newArrays[idx] = this->FastGeomQuadArrays[idx]; + } + } + delete [] this->FastGeomQuadArrays; + this->FastGeomQuadArrays = newArrays; + this->FastGeomQuadArrayLength = num; + } + + // Next: allocate a new array if necessary. + if (this->FastGeomQuadArrays[this->NextArrayIndex] == NULL) + { + // We are allocating a whole bunch at a time to avoid + // allocation of many small pieces of memory. + this->FastGeomQuadArrays[this->NextArrayIndex] + = new vtkFastGeomQuad[this->FastGeomQuadArrayLength]; + } + + vtkFastGeomQuad* q = (this->FastGeomQuadArrays[this->NextArrayIndex]) + this->NextQuadIndex; + + // Move to the next quad. + ++(this->NextQuadIndex); + if (this->NextQuadIndex >= this->FastGeomQuadArrayLength) + { + ++(this->NextArrayIndex); + this->NextQuadIndex = 0; + } + + return q; +} + +//---------------------------------------------------------------------------- +void vtkDataSetSurfaceFilter::InitQuadHashTraversal() +{ + this->QuadHashTraversalIndex = 0; + this->QuadHashTraversal = this->QuadHash[0]; +} + +//---------------------------------------------------------------------------- +vtkFastGeomQuad *vtkDataSetSurfaceFilter::GetNextVisibleQuadFromHash() +{ + vtkFastGeomQuad *quad; + + quad = this->QuadHashTraversal; + + // Move till traversal until we have a quad to return. + // Note: the current traversal has not been returned yet. + while (quad == NULL || quad->SourceId == -1) + { + if (quad) + { // The quad must be hidden. Move to the next. + quad = quad->Next; + } + else + { // must be the end of the linked list. Move to the next bin. + this->QuadHashTraversalIndex += 1; + if ( this->QuadHashTraversalIndex >= this->QuadHashLength) + { // There are no more bins. + this->QuadHashTraversal = NULL; + return NULL; + } + quad = this->QuadHash[this->QuadHashTraversalIndex]; + } + } + + // Now we have a quad to return. Set the traversal to the next entry. + this->QuadHashTraversal = quad->Next; + + return quad; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkDataSetSurfaceFilter::GetOutputPointId(vtkIdType inPtId, + vtkDataSet *input, + vtkPoints *outPts, + vtkPointData *outPD) +{ + vtkIdType outPtId; + + outPtId = this->PointMap[inPtId]; + if (outPtId == -1) + { + outPtId = outPts->InsertNextPoint(input->GetPoint(inPtId)); + outPD->CopyData(input->GetPointData(), inPtId, outPtId); + this->PointMap[inPtId] = outPtId; + } + + return outPtId; +} diff --git a/Graphics/vtkDataSetSurfaceFilter.h b/Graphics/vtkDataSetSurfaceFilter.h new file mode 100644 index 0000000..be695ae --- /dev/null +++ b/Graphics/vtkDataSetSurfaceFilter.h @@ -0,0 +1,132 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetSurfaceFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetSurfaceFilter - Extracts outer (polygonal) surface. +// .SECTION Description +// vtkDataSetSurfaceFilter is a faster version of vtkGeometry filter, but it +// does not have an option to select bounds. It may use more memory than +// vtkGeometryFilter. It only has one option: whether to use triangle strips +// when the input type is structured. + +// .SECTION See Also +// vtkGeometryFilter vtkStructuredGridGeometryFilter. + +#ifndef __vtkDataSetSurfaceFilter_h +#define __vtkDataSetSurfaceFilter_h + +#include "vtkPolyDataAlgorithm.h" + + +class vtkPointData; +class vtkPoints; +//BTX +struct vtkFastGeomQuadStruct; +typedef struct vtkFastGeomQuadStruct vtkFastGeomQuad; +//ETX + +class VTK_GRAPHICS_EXPORT vtkDataSetSurfaceFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkDataSetSurfaceFilter *New(); + vtkTypeRevisionMacro(vtkDataSetSurfaceFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // When input is structured data, this flag will generate faces with + // triangle strips. This should render faster and use less memory, but no + // cell data is copied. By default, UseStrips is Off. + vtkSetMacro(UseStrips, int); + vtkGetMacro(UseStrips, int); + vtkBooleanMacro(UseStrips, int); + + // Description: + // If PieceInvariant is true, vtkDataSetSurfaceFilter requests + // 1 ghost level from input in order to remove internal surface + // that are between processes. False by default. + vtkSetMacro(PieceInvariant, int); + vtkGetMacro(PieceInvariant, int); + +protected: + vtkDataSetSurfaceFilter(); + ~vtkDataSetSurfaceFilter(); + + int UseStrips; + + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + int StructuredExecute(vtkDataSet *input, vtkPolyData *output, int *ext, + vtkInformation *inInfo); + int UnstructuredGridExecute(vtkDataSet *input, vtkPolyData *output); + int DataSetExecute(vtkDataSet *input, vtkPolyData *output); + + // Helper methods. + void ExecuteFaceStrips(vtkDataSet *input, vtkPolyData *output, + int maxFlag, int *ext, + int aAxis, int bAxis, int cAxis, + vtkInformation *inInfo); + void ExecuteFaceQuads(vtkDataSet *input, vtkPolyData *output, + int maxFlag, int *ext, + int aAxis, int bAxis, int cAxis, + vtkInformation *inInfo); + + void InitializeQuadHash(vtkIdType numPoints); + void DeleteQuadHash(); + void InsertQuadInHash(vtkIdType a, vtkIdType b, vtkIdType c, vtkIdType d, + vtkIdType sourceId); + void InsertTriInHash(vtkIdType a, vtkIdType b, vtkIdType c, + vtkIdType sourceId); + void InsertPentaInHash(vtkIdType a, vtkIdType b, + vtkIdType c, vtkIdType d, + vtkIdType e, + vtkIdType sourceId); + void InsertHexInHash(vtkIdType a, vtkIdType b, + vtkIdType c, vtkIdType d, + vtkIdType e, vtkIdType f, + vtkIdType sourceId); + void InitQuadHashTraversal(); + vtkFastGeomQuad *GetNextVisibleQuadFromHash(); + + vtkFastGeomQuad **QuadHash; + vtkIdType QuadHashLength; + vtkFastGeomQuad *QuadHashTraversal; + vtkIdType QuadHashTraversalIndex; + + vtkIdType *PointMap; + vtkIdType GetOutputPointId(vtkIdType inPtId, vtkDataSet *input, + vtkPoints *outPts, vtkPointData *outPD); + + vtkIdType NumberOfNewCells; + + // Better memory allocation for faces (hash) + void InitFastGeomQuadAllocation(int numberOfCells); + vtkFastGeomQuad* NewFastGeomQuad(); + void DeleteAllFastGeomQuads(); + // ----- + int FastGeomQuadArrayLength; + int NumberOfFastGeomQuadArrays; + vtkFastGeomQuad** FastGeomQuadArrays; + // These indexes allow us to find the next available face. + int NextArrayIndex; + int NextQuadIndex; + + int PieceInvariant; + +private: + vtkDataSetSurfaceFilter(const vtkDataSetSurfaceFilter&); // Not implemented. + void operator=(const vtkDataSetSurfaceFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkDataSetToDataObjectFilter.cxx b/Graphics/vtkDataSetToDataObjectFilter.cxx new file mode 100644 index 0000000..87fd73f --- /dev/null +++ b/Graphics/vtkDataSetToDataObjectFilter.cxx @@ -0,0 +1,339 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToDataObjectFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetToDataObjectFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkDataSetToDataObjectFilter, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkDataSetToDataObjectFilter); + +//---------------------------------------------------------------------------- +// Instantiate object. +vtkDataSetToDataObjectFilter::vtkDataSetToDataObjectFilter() +{ + this->Geometry = 1; + this->Topology = 1; + this->PointData = 1; + this->CellData = 1; + this->FieldData = 1; +} + +vtkDataSetToDataObjectFilter::~vtkDataSetToDataObjectFilter() +{ +} + +//---------------------------------------------------------------------------- +int vtkDataSetToDataObjectFilter::RequestData( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataObject *output = outInfo->Get(vtkDataObject::DATA_OBJECT()); + vtkFieldData *fd=vtkFieldData::New(); + vtkPoints *pts; + vtkDataArray *da; + int i; + + vtkDebugMacro(<<"Generating field data from data set"); + + if ( this->Geometry) + { + if ( input->GetDataObjectType() == VTK_POLY_DATA ) + { + pts = ((vtkPolyData *)input)->GetPoints(); + if (pts) + { + da = pts->GetData(); + da->SetName("Points"); + fd->AddArray( da ); + } + } + + else if ( input->GetDataObjectType() == VTK_STRUCTURED_POINTS ) + { + vtkStructuredPoints *spts=(vtkStructuredPoints *)input; + + vtkFloatArray *origin=vtkFloatArray::New(); + origin->SetNumberOfValues(3); + double org[3]; + spts->GetOrigin(org); + origin->SetValue(0, org[0]); + origin->SetValue(1, org[1]); + origin->SetValue(2, org[2]); + origin->SetName("Origin"); + fd->AddArray(origin); + origin->Delete(); + + vtkFloatArray *spacing=vtkFloatArray::New(); + spacing->SetNumberOfValues(3); + double sp[3]; + spts->GetSpacing(sp); + spacing->SetValue(0, sp[0]); + spacing->SetValue(1, sp[1]); + spacing->SetValue(2, sp[2]); + spacing->SetName("Spacing"); + fd->AddArray(spacing); + spacing->Delete(); + } + + else if ( input->GetDataObjectType() == VTK_STRUCTURED_GRID ) + { + pts = ((vtkPolyData *)input)->GetPoints(); + if (pts) + { + da = pts->GetData(); + da->SetName("Points"); + fd->AddArray( da ); + } + } + + else if ( input->GetDataObjectType() == VTK_RECTILINEAR_GRID ) + { + vtkRectilinearGrid *rgrid=(vtkRectilinearGrid *)input; + da = rgrid->GetXCoordinates(); + if (da != NULL) + { + da->SetName("XCoordinates"); + fd->AddArray( da ); + } + da = rgrid->GetYCoordinates(); + if (da != NULL) + { + da->SetName("YCoordinates"); + fd->AddArray( da ); + } + da = rgrid->GetZCoordinates(); + if (da != NULL) + { + da->SetName("ZCoordinates"); + fd->AddArray( da ); + } + } + + else if ( input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID ) + { + pts = ((vtkPolyData *)input)->GetPoints(); + if (pts) + { + da = pts->GetData(); + da->SetName("Points"); + fd->AddArray( da ); + } + } + + else + { + vtkErrorMacro(<<"Unsupported dataset type!"); + fd->Delete(); + return 1; + } + } + + if (this->Topology) + { + if ( input->GetDataObjectType() == VTK_POLY_DATA ) + { + vtkPolyData *pd=(vtkPolyData *)input; + vtkCellArray *ca; + if ( pd->GetVerts()->GetNumberOfCells() > 0 ) + { + ca = pd->GetVerts(); + ca->GetData()->SetName("Verts"); + fd->AddArray( ca->GetData() ); + } + if ( pd->GetLines()->GetNumberOfCells() > 0 ) + { + ca = pd->GetLines(); + ca->GetData()->SetName("Lines"); + fd->AddArray( ca->GetData() ); + } + if ( pd->GetPolys()->GetNumberOfCells() > 0 ) + { + ca = pd->GetPolys(); + ca->GetData()->SetName("Polys"); + fd->AddArray( ca->GetData() ); + } + if ( pd->GetStrips()->GetNumberOfCells() > 0 ) + { + ca = pd->GetStrips(); + ca->GetData()->SetName("Strips"); + fd->AddArray( ca->GetData() ); + } + } + + else if ( input->GetDataObjectType() == VTK_STRUCTURED_POINTS ) + { + vtkIntArray *dimensions=vtkIntArray::New(); + dimensions->SetNumberOfValues(3); + int dims[3]; + ((vtkStructuredPoints *)input)->GetDimensions(dims); + dimensions->SetValue(0, dims[0]); + dimensions->SetValue(1, dims[1]); + dimensions->SetValue(2, dims[2]); + dimensions->SetName("Dimensions"); + fd->AddArray( dimensions ); + dimensions->Delete(); + } + + else if ( input->GetDataObjectType() == VTK_STRUCTURED_GRID ) + { + vtkIntArray *dimensions=vtkIntArray::New(); + dimensions->SetNumberOfValues(3); + int dims[3]; + ((vtkStructuredGrid *)input)->GetDimensions(dims); + dimensions->SetValue(0, dims[0]); + dimensions->SetValue(1, dims[1]); + dimensions->SetValue(2, dims[2]); + dimensions->SetName("Dimensions"); + fd->AddArray( dimensions ); + dimensions->Delete(); + } + + else if ( input->GetDataObjectType() == VTK_RECTILINEAR_GRID ) + { + vtkIntArray *dimensions=vtkIntArray::New(); + dimensions->SetNumberOfValues(3); + int dims[3]; + ((vtkRectilinearGrid *)input)->GetDimensions(dims); + dimensions->SetValue(0, dims[0]); + dimensions->SetValue(1, dims[1]); + dimensions->SetValue(2, dims[2]); + dimensions->SetName("Dimensions"); + fd->AddArray( dimensions ); + dimensions->Delete(); + } + + else if ( input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID ) + { + vtkCellArray *ca=((vtkUnstructuredGrid *)input)->GetCells(); + if ( ca != NULL && ca->GetNumberOfCells() > 0 ) + { + ca->GetData()->SetName("Cells"); + fd->AddArray( ca->GetData() ); + + vtkIdType numCells=input->GetNumberOfCells(); + vtkIntArray *types=vtkIntArray::New(); + types->SetNumberOfValues(numCells); + for (i=0; iSetValue(i, input->GetCellType(i)); + } + types->SetName("CellTypes"); + fd->AddArray( types ); + types->Delete(); + } + } + + else + { + vtkErrorMacro(<<"Unsupported dataset type!"); + fd->Delete(); + return 1; + } + } + + vtkFieldData* fieldData; + + if (this->FieldData) + { + fieldData = input->GetFieldData(); + + for (i=0; iGetNumberOfArrays(); i++) + { + fd->AddArray(fieldData->GetArray(i)); + } + } + + if (this->PointData) + { + fieldData = input->GetPointData(); + + for (i=0; iGetNumberOfArrays(); i++) + { + fd->AddArray(fieldData->GetArray(i)); + } + } + + if (this->CellData) + { + fieldData = input->GetCellData(); + + for (i=0; iGetNumberOfArrays(); i++) + { + fd->AddArray(fieldData->GetArray(i)); + } + } + + output->SetFieldData(fd); + fd->Delete(); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataSetToDataObjectFilter::RequestUpdateExtent( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDataSetToDataObjectFilter::FillInputPortInformation(int port, + vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetToDataObjectFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Geometry: " << (this->Geometry ? "On\n" : "Off\n"); + os << indent << "Topology: " << (this->Topology ? "On\n" : "Off\n"); + os << indent << "Field Data: " << (this->FieldData ? "On\n" : "Off\n"); + os << indent << "Point Data: " << (this->PointData ? "On\n" : "Off\n"); + os << indent << "Cell Data: " << (this->CellData ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkDataSetToDataObjectFilter.h b/Graphics/vtkDataSetToDataObjectFilter.h new file mode 100644 index 0000000..7c54a8a --- /dev/null +++ b/Graphics/vtkDataSetToDataObjectFilter.h @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetToDataObjectFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetToDataObjectFilter - map dataset into data object (i.e., a field) +// .SECTION Description +// vtkDataSetToDataObjectFilter is an class that transforms a dataset into +// data object (i.e., a field). The field will have labeled data arrays +// corresponding to the topology, geometry, field data, and point and cell +// attribute data. +// +// You can control what portions of the dataset are converted into the +// output data object's field data. The instance variables Geometry, +// Topology, FieldData, PointData, and CellData are flags that control +// whether the dataset's geometry (e.g., points, spacing, origin); +// topology (e.g., cell connectivity, dimensions); the field data +// associated with the dataset's superclass data object; the dataset's +// point data attributes; and the dataset's cell data attributes. (Note: +// the data attributes include scalars, vectors, tensors, normals, texture +// coordinates, and field data.) +// +// The names used to create the field data are as follows. For vtkPolyData, +// "Points", "Verts", "Lines", "Polys", and "Strips". For vtkUnstructuredGrid, +// "Cells" and "CellTypes". For vtkStructuredPoints, "Dimensions", "Spacing", +// and "Origin". For vtkStructuredGrid, "Points" and "Dimensions". For +// vtkRectilinearGrid, "XCoordinates", "YCoordinates", and "ZCoordinates". +// for point attribute data, "PointScalars", "PointVectors", etc. For cell +// attribute data, "CellScalars", "CellVectors", etc. Field data arrays retain +// their original name. + +// .SECTION See Also +// vtkDataObject vtkFieldData vtkDataObjectToDataSetFilter + +#ifndef __vtkDataSetToDataObjectFilter_h +#define __vtkDataSetToDataObjectFilter_h + +#include "vtkDataObjectAlgorithm.h" + +class vtkDataSet; + +class VTK_GRAPHICS_EXPORT vtkDataSetToDataObjectFilter : public vtkDataObjectAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkDataSetToDataObjectFilter,vtkDataObjectAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the object to transform all data into a data object. + static vtkDataSetToDataObjectFilter *New(); + + // Description: + // Turn on/off the conversion of dataset geometry to a data object. + vtkSetMacro(Geometry,int); + vtkGetMacro(Geometry,int); + vtkBooleanMacro(Geometry,int); + + // Description: + // Turn on/off the conversion of dataset topology to a data object. + vtkSetMacro(Topology,int); + vtkGetMacro(Topology,int); + vtkBooleanMacro(Topology,int); + + // Description: + // Turn on/off the conversion of dataset field data to a data object. + vtkSetMacro(FieldData,int); + vtkGetMacro(FieldData,int); + vtkBooleanMacro(FieldData,int); + + // Description: + // Turn on/off the conversion of dataset point data to a data object. + vtkSetMacro(PointData,int); + vtkGetMacro(PointData,int); + vtkBooleanMacro(PointData,int); + + // Description: + // Turn on/off the conversion of dataset cell data to a data object. + vtkSetMacro(CellData,int); + vtkGetMacro(CellData,int); + vtkBooleanMacro(CellData,int); + +protected: + vtkDataSetToDataObjectFilter(); + ~vtkDataSetToDataObjectFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); //generate output data + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + virtual int FillInputPortInformation(int, vtkInformation*); + + int Geometry; + int Topology; + int PointData; + int CellData; + int FieldData; + +private: + vtkDataSetToDataObjectFilter(const vtkDataSetToDataObjectFilter&); // Not implemented. + void operator=(const vtkDataSetToDataObjectFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkDataSetTriangleFilter.cxx b/Graphics/vtkDataSetTriangleFilter.cxx new file mode 100644 index 0000000..22e3e4a --- /dev/null +++ b/Graphics/vtkDataSetTriangleFilter.cxx @@ -0,0 +1,322 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetTriangleFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetTriangleFilter.h" + +#include "vtkCellData.h" +#include "vtkCellType.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkOrderedTriangulator.h" +#include "vtkPointData.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkRectilinearGrid.h" + +vtkCxxRevisionMacro(vtkDataSetTriangleFilter, "$Revision: 1.24 $"); +vtkStandardNewMacro(vtkDataSetTriangleFilter); + +vtkDataSetTriangleFilter::vtkDataSetTriangleFilter() +{ + this->Triangulator = vtkOrderedTriangulator::New(); + this->Triangulator->PreSortedOff(); + this->Triangulator->UseTemplatesOn(); +} + +vtkDataSetTriangleFilter::~vtkDataSetTriangleFilter() +{ + this->Triangulator->Delete(); + this->Triangulator = NULL; +} + +int vtkDataSetTriangleFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (input->IsA("vtkStructuredPoints") || + input->IsA("vtkStructuredGrid") || + input->IsA("vtkImageData") || + input->IsA("vtkRectilinearGrid")) + { + this->StructuredExecute(input, output); + } + else + { + this->UnstructuredExecute(input, output); + } + + vtkDebugMacro(<<"Produced " << this->GetOutput()->GetNumberOfCells() << " cells"); + + return 1; +} + +void vtkDataSetTriangleFilter::StructuredExecute(vtkDataSet *input, + vtkUnstructuredGrid *output) +{ + int dimensions[3], i, j, k, l, m; + vtkIdType newCellId, inId; + vtkGenericCell *cell = vtkGenericCell::New(); + vtkCellData *inCD = input->GetCellData(); + vtkCellData *outCD = output->GetCellData(); + vtkPoints *cellPts = vtkPoints::New(); + vtkPoints *newPoints = vtkPoints::New(); + vtkIdList *cellPtIds = vtkIdList::New(); + int numSimplices, numPts, dim, type; + vtkIdType pts[4], num; + + // Create an array of points. This does an explicit creation + // of each point. + num = input->GetNumberOfPoints(); + newPoints->SetNumberOfPoints(num); + for (i = 0; i < num; ++i) + { + newPoints->SetPoint(i,input->GetPoint(i)); + } + + outCD->CopyAllocate(inCD,input->GetNumberOfCells()*5); + output->Allocate(input->GetNumberOfCells()*5); + + if (input->IsA("vtkStructuredPoints")) + { + static_cast(input)->GetDimensions(dimensions); + } + else if (input->IsA("vtkStructuredGrid")) + { + static_cast(input)->GetDimensions(dimensions); + } + else if (input->IsA("vtkImageData")) + { + static_cast(input)->GetDimensions(dimensions); + } + else if (input->IsA("vtkRectilinearGrid")) + { + static_cast(input)->GetDimensions(dimensions); + } + + dimensions[0] = dimensions[0] - 1; + dimensions[1] = dimensions[1] - 1; + dimensions[2] = dimensions[2] - 1; + + vtkIdType numSlices = ( dimensions[2] > 0 ? dimensions[2] : 1 ); + int abort=0; + for (k = 0; k < numSlices && !abort; k++) + { + this->UpdateProgress((double)k / numSlices); + abort = this->GetAbortExecute(); + + for (j = 0; j < dimensions[1]; j++) + { + for (i = 0; i < dimensions[0]; i++) + { + inId = i+(j+(k*dimensions[1]))*dimensions[0]; + input->GetCell(inId, cell); + if ((i+j+k)%2 == 0) + { + cell->Triangulate(0, cellPtIds, cellPts); + } + else + { + cell->Triangulate(1, cellPtIds, cellPts); + } + + dim = cell->GetCellDimension() + 1; + + numPts = cellPtIds->GetNumberOfIds(); + numSimplices = numPts / dim; + type = 0; + switch (dim) + { + case 1: + type = VTK_VERTEX; break; + case 2: + type = VTK_LINE; break; + case 3: + type = VTK_TRIANGLE; break; + case 4: + type = VTK_TETRA; break; + } + for (l = 0; l < numSimplices; l++ ) + { + for (m = 0; m < dim; m++) + { + pts[m] = cellPtIds->GetId(dim*l+m); + } + // copy cell data + newCellId = output->InsertNextCell(type, dim, pts); + outCD->CopyData(inCD, inId, newCellId); + }//for all simplices + }//i dimension + }//j dimension + }//k dimension + + // Update output + output->SetPoints(newPoints); + output->GetPointData()->PassData(input->GetPointData()); + output->Squeeze(); + + cell->Delete(); + newPoints->Delete(); + cellPts->Delete(); + cellPtIds->Delete(); +} + +// 3D cells use the ordered triangulator. The ordered triangulator is used +// to create templates on the fly. Once the templates are created then they +// are used to produce the final triangulation. +// +void vtkDataSetTriangleFilter::UnstructuredExecute(vtkDataSet *dataSetInput, + vtkUnstructuredGrid *output) +{ + vtkPointSet *input = (vtkPointSet*) dataSetInput; //has to be + vtkIdType numCells = input->GetNumberOfCells(); + vtkGenericCell *cell; + vtkIdType newCellId, j; + int k; + vtkCellData *inCD=input->GetCellData(); + vtkCellData *outCD=output->GetCellData(); + vtkPoints *cellPts; + vtkIdList *cellPtIds; + vtkIdType ptId, numTets, ncells; + int numPts, type; + int numSimplices, dim; + vtkIdType pts[4]; + double x[3]; + + if (numCells == 0) + { + return; + } + + cell = vtkGenericCell::New(); + cellPts = vtkPoints::New(); + cellPtIds = vtkIdList::New(); + + // Create an array of points + outCD->CopyAllocate(inCD,input->GetNumberOfCells()*5); + output->Allocate(input->GetNumberOfCells()*5); + + // Points are passed through + output->SetPoints(input->GetPoints()); + output->GetPointData()->PassData(input->GetPointData()); + + int abort=0; + vtkIdType updateTime = numCells/20 + 1; // update roughly every 5% + for (vtkIdType cellId=0; cellId < numCells && !abort; cellId++) + { + if ( !(cellId % updateTime) ) + { + this->UpdateProgress((double)cellId / numCells); + abort = this->GetAbortExecute(); + } + + input->GetCell(cellId, cell); + dim = cell->GetCellDimension(); + + if ( dim == 3 ) //use ordered triangulation + { + numPts = cell->GetNumberOfPoints(); + double *p, *pPtr=cell->GetParametricCoords(); + this->Triangulator->InitTriangulation(0.0,1.0, 0.0,1.0, 0.0,1.0, numPts); + for (p=pPtr, j=0; jPointIds->GetId(j); + cell->Points->GetPoint(j, x); + this->Triangulator->InsertPoint(ptId, x, p, 0); + }//for all cell points + if ( cell->IsPrimaryCell() ) //use templates if topology is fixed + { + int numEdges=cell->GetNumberOfEdges(); + this->Triangulator->TemplateTriangulate(cell->GetCellType(), + numPts,numEdges); + } + else //use ordered triangulator + { + this->Triangulator->Triangulate(); + } + + ncells = output->GetNumberOfCells(); + numTets = this->Triangulator->AddTetras(0,output); + + for (j=0; j < numTets; j++) + { + outCD->CopyData(inCD, cellId, ncells+j); + } + } + + else //2D or lower dimension + { + dim++; + cell->Triangulate(0, cellPtIds, cellPts); + numPts = cellPtIds->GetNumberOfIds(); + + numSimplices = numPts / dim; + type = 0; + switch (dim) + { + case 1: + type = VTK_VERTEX; break; + case 2: + type = VTK_LINE; break; + case 3: + type = VTK_TRIANGLE; break; + } + + for ( j=0; j < numSimplices; j++ ) + { + for (k=0; kGetId(dim*j+k); + } + // copy cell data + newCellId = output->InsertNextCell(type, dim, pts); + outCD->CopyData(inCD, cellId, newCellId); + } + } //if 2D or less cell + } //for all cells + + // Update output + output->Squeeze(); + + cellPts->Delete(); + cellPtIds->Delete(); + cell->Delete(); +} + +int vtkDataSetTriangleFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkDataSetTriangleFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Graphics/vtkDataSetTriangleFilter.h b/Graphics/vtkDataSetTriangleFilter.h new file mode 100644 index 0000000..d99ffc1 --- /dev/null +++ b/Graphics/vtkDataSetTriangleFilter.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetTriangleFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetTriangleFilter - triangulate any type of dataset +// .SECTION Description +// vtkDataSetTriangleFilter generates n-dimensional simplices from any input +// dataset. That is, 3D cells are converted to tetrahedral meshes, 2D cells +// to triangles, and so on. The triangulation is guaranteed to be compatible. +// +// This filter uses simple 1D and 2D triangulation techniques for cells +// that are of topological dimension 2 or less. For 3D cells--due to the +// issue of face compatibility across quadrilateral faces (which way to +// orient the diagonal?)--a fancier ordered Delaunay triangulation is used. +// This approach produces templates on the fly for triangulating the +// cells. The templates are then used to do the actual triangulation. +// +// .SECTION See Also +// vtkOrderedTriangulator vtkTriangleFilter + +#ifndef __vtkDataSetTriangleFilter_h +#define __vtkDataSetTriangleFilter_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkOrderedTriangulator; + +class VTK_GRAPHICS_EXPORT vtkDataSetTriangleFilter : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkDataSetTriangleFilter *New(); + vtkTypeRevisionMacro(vtkDataSetTriangleFilter,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkDataSetTriangleFilter(); + ~vtkDataSetTriangleFilter(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + // Used to triangulate 3D cells + vtkOrderedTriangulator *Triangulator; + + // Different execute methods depending on whether input is structured or not + void StructuredExecute(vtkDataSet *, vtkUnstructuredGrid *); + void UnstructuredExecute(vtkDataSet *, vtkUnstructuredGrid *); + +private: + vtkDataSetTriangleFilter(const vtkDataSetTriangleFilter&); // Not implemented. + void operator=(const vtkDataSetTriangleFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkDecimatePro.cxx b/Graphics/vtkDecimatePro.cxx new file mode 100644 index 0000000..b907cf4 --- /dev/null +++ b/Graphics/vtkDecimatePro.cxx @@ -0,0 +1,1719 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDecimatePro.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDecimatePro.h" + +#include "vtkDoubleArray.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPolyData.h" +#include "vtkPriorityQueue.h" +#include "vtkTriangle.h" +#include "vtkCellArray.h" +#include "vtkPointData.h" +#include "vtkCellData.h" + +vtkCxxRevisionMacro(vtkDecimatePro, "$Revision: 1.79 $"); +vtkStandardNewMacro(vtkDecimatePro); + +#define VTK_TOLERANCE 1.0e-05 +#define VTK_MAX_TRIS_PER_VERTEX VTK_CELL_SIZE +#define VTK_RECYCLE_VERTEX VTK_DOUBLE_MAX + +#define VTK_SIMPLE_VERTEX 1 +#define VTK_BOUNDARY_VERTEX 2 +#define VTK_INTERIOR_EDGE_VERTEX 3 +#define VTK_CORNER_VERTEX 4 +#define VTK_CRACK_TIP_VERTEX 5 +#define VTK_EDGE_END_VERTEX 6 +#define VTK_NON_MANIFOLD_VERTEX 7 +#define VTK_DEGENERATE_VERTEX 8 +#define VTK_HIGH_DEGREE_VERTEX 9 + +#define VTK_STATE_UNSPLIT 0 +#define VTK_STATE_SPLIT 1 +#define VTK_STATE_SPLIT_ALL 2 + +// Helper functions +static double ComputeSimpleError(double x[3], double normal[3], double point[3]); +static double ComputeEdgeError(double x[3], double x1[3], double x2[3]); +static double ComputeSingleTriangleError(double x[3], double x1[3], double x2[3]); + + +// Create object with specified reduction of 90% and feature angle of +// 15 degrees. Edge splitting is on, defer splitting is on, and the +// split angle is 75 degrees. Topology preservation is off, delete +// boundary vertices is on, and the maximum error is set to +// VTK_DOUBLE_MAX. The inflection point ratio is 10 and the vertex +// degree is 25. Error accumulation is turned off. +vtkDecimatePro::vtkDecimatePro() +{ + this->Neighbors = vtkIdList::New(); + this->Neighbors->Allocate(VTK_MAX_TRIS_PER_VERTEX); + this->V = new vtkDecimatePro::VertexArray(VTK_MAX_TRIS_PER_VERTEX+1); + this->T = new vtkDecimatePro::TriArray(VTK_MAX_TRIS_PER_VERTEX+1); + this->EdgeLengths = vtkPriorityQueue::New(); + this->EdgeLengths->Allocate(VTK_MAX_TRIS_PER_VERTEX); + + this->InflectionPoints = vtkDoubleArray::New(); + this->TargetReduction = 0.90; + this->FeatureAngle = 15.0; + this->PreserveTopology = 0; + this->MaximumError = VTK_DOUBLE_MAX; + this->AbsoluteError = VTK_DOUBLE_MAX; + this->ErrorIsAbsolute = 0; + this->AccumulateError = 0; + this->SplitAngle = 75.0; + this->Splitting = 1; + this->PreSplitMesh = 0; + this->Degree = 25; + this->BoundaryVertexDeletion = 1; + this->InflectionPointRatio = 10.0; + + this->Queue = NULL; + this->VertexError = NULL; + + this->Mesh = NULL; +} + +vtkDecimatePro::~vtkDecimatePro() +{ + this->InflectionPoints->Delete(); + if ( this->Queue ) + { + this->Queue->Delete(); + } + if ( this->VertexError ) + { + this->VertexError->Delete(); + } + this->Neighbors->Delete(); + this->EdgeLengths->Delete(); + delete this->V; + delete this->T; +} + +// +// Reduce triangles in mesh by specified reduction factor. +// +int vtkDecimatePro::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType i, ptId, numPts, numTris, collapseId; + vtkPoints *inPts; + vtkPoints *newPts; + vtkCellArray *inPolys; + vtkCellArray *newPolys; + double error, previousError=0.0, reduction; + int type; + vtkIdType *pts, npts, totalEliminated, numRecycles, numPops; + unsigned short int ncells; + vtkIdType pt1, pt2, cellId, fedges[2]; + vtkIdType *cells; + vtkIdList *CollapseTris; + double max, *bounds; + if (!input) + { + vtkErrorMacro(<<"No input!"); + return 1; + } + vtkPointData *outputPD=output->GetPointData(); + vtkPointData *inPD=input->GetPointData(); + vtkPointData *meshPD=0; + vtkIdType *map, numNewPts, totalPts; + vtkIdType newCellPts[3]; + int abortExecute=0; + + vtkDebugMacro(<<"Executing progressive decimation..."); + + // Check input + this->NumberOfRemainingTris = numTris = input->GetNumberOfPolys(); + if ( ((numPts=input->GetNumberOfPoints()) < 1 || numTris < 1) && + (this->TargetReduction > 0.0) ) + { + vtkErrorMacro(<<"No data to decimate!"); + return 1; + } + + // Initialize + bounds = input->GetBounds(); + for (max=0.0, i=0; i<3; i++) + { + max = ((bounds[2*i+1]-bounds[2*i]) > max ? + (bounds[2*i+1]-bounds[2*i]) : max); + } + if (!this->ErrorIsAbsolute) + { + this->Error = (this->MaximumError >= VTK_DOUBLE_MAX ? + VTK_DOUBLE_MAX : this->MaximumError * max); + } + else + { + this->Error = (this->AbsoluteError >= VTK_DOUBLE_MAX ? + VTK_DOUBLE_MAX : this->AbsoluteError); + } + this->Tolerance = VTK_TOLERANCE * input->GetLength(); + this->CosAngle = + cos ((double) vtkMath::DegreesToRadians() * this->FeatureAngle); + this->Split = ( this->Splitting && !this->PreserveTopology ); + this->VertexDegree = this->Degree; + this->TheSplitAngle = this->SplitAngle; + this->SplitState = VTK_STATE_UNSPLIT; + + // Lets check to make sure there are only triangles in the input. + vtkIdType *pPolys; + pPolys = input->GetPolys()->GetPointer(); + for (i = 0; i < numTris; ++i) + { + if (*pPolys != 3) + { + vtkErrorMacro("DecimatePro does not accept polygons that are not triangles."); + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + return 1; + } + pPolys += 4; + } + + // Build cell data structure. Need to copy triangle connectivity data + // so we can modify it. + if ( this->TargetReduction > 0.0 ) + { + inPts = input->GetPoints(); + inPolys = input->GetPolys(); + + // this static should be eliminated + if (this->Mesh != NULL) {this->Mesh->Delete(); this->Mesh = NULL;} + this->Mesh = vtkPolyData::New(); + + newPts = vtkPoints::New(); newPts->SetNumberOfPoints(numPts); + newPts->DeepCopy(inPts); + this->Mesh->SetPoints(newPts); + newPts->Delete(); //registered by Mesh and preserved + + newPolys = vtkCellArray::New(); + newPolys->DeepCopy(inPolys); + this->Mesh->SetPolys(newPolys); + newPolys->Delete(); //registered by Mesh and preserved + + meshPD = this->Mesh->GetPointData(); + meshPD->DeepCopy(inPD); + meshPD->CopyAllocate(meshPD, input->GetNumberOfPoints()); + + this->Mesh->BuildLinks(); + } + else + { + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + //vtkWarningMacro(<<"Reduction == 0: passing data through unchanged"); + return 1; + } + + // Initialize data structures: priority queue and errors. + this->InitializeQueue(numPts); + + if ( this->AccumulateError ) + { + this->VertexError = vtkDoubleArray::New(); + this->VertexError->Allocate(numPts,((vtkIdType)0.25*numPts)); + for (i=0; iVertexError->SetValue(i, 0.0); + } + } + + // If not deferring splitting and splitting on, we'll start off by + // splitting the mesh. This has side effect of inserting vertices. + this->NumCollapses = this->NumMerges = 0; + if ( this->Split && this->PreSplitMesh ) + { + vtkDebugMacro(<<"Pre-splitting mesh"); + this->SplitState = VTK_STATE_SPLIT; + this->SplitMesh(); + } + + // Start by traversing all vertices. For each vertex, evaluate the + // local topology/geometry. (Some vertex splitting may be + // necessary to resolve non-manifold geometry or to split edges.) + // Then evaluate the local error for the vertex. The vertex is then + // inserted into the priority queue. + npts = this->Mesh->GetNumberOfPoints(); + for ( ptId=0; ptId < npts && !abortExecute ; ptId++ ) + { + if ( ! (ptId % 10000) ) + { + vtkDebugMacro(<<"Inserting vertex #" << ptId); + this->UpdateProgress (0.25*ptId/npts);//25% spent inserting + abortExecute = this->GetAbortExecute(); + } + this->Insert(ptId); + } + this->UpdateProgress (0.25);//25% spent inserting + + CollapseTris = vtkIdList::New(); + CollapseTris->Allocate(100,100); + + // While the priority queue is not empty, retrieve the top vertex from the + // queue and attempt to delete it by performing an edge collapse. This + // in turn will cause modification to the surrounding vertices. For each + // surrounding vertex, evaluate the error and re-insert into the queue. + // (While this is happening we keep track of operations on the data - + // this forms the core of the progressive mesh representation.) + for ( totalEliminated=0, reduction=0.0, numRecycles=0, numPops=0; + reduction < this->TargetReduction && (ptId = this->Pop(error)) >= 0 && !abortExecute; + numPops++) + { + if ( numPops && !(numPops % 5000) ) + { + vtkDebugMacro(<<"Deleting vertex #" << numPops); + this->UpdateProgress (0.25 + 0.75*(reduction/this->TargetReduction)); + abortExecute = this->GetAbortExecute(); + } + + this->Mesh->GetPoint(ptId,this->X); + this->Mesh->GetPointCells(ptId,ncells,cells); + + if ( ncells > 0 ) + { + type = this->EvaluateVertex(ptId, ncells, cells, fedges); + + // FindSplit finds the edge to collapse - and if it fails, we + // split the vertex. + collapseId = this->FindSplit (type, fedges, pt1, pt2, CollapseTris); + + if ( collapseId >= 0 ) + { + if ( this->AccumulateError ) + { + this->DistributeError(error); + } + + totalEliminated += this->CollapseEdge(type, ptId, collapseId, pt1, pt2, + CollapseTris); + + reduction = (double) totalEliminated / numTris; + this->NumberOfRemainingTris = numTris - totalEliminated; + + //see whether we've found inflection + if ( numPops == 0 || (previousError == 0.0 && error != 0.0) || + (previousError != 0.0 && + fabs(error/previousError) > this->InflectionPointRatio) ) + { + this->InflectionPoints->InsertNextValue(numPops); + } + previousError = error; + } + + else //Couldn't delete the vertex, so we'll re-insert it for splitting + { + numRecycles++; + this->Insert(ptId,VTK_RECYCLE_VERTEX); + } + + }//if cells attached + }//while queue not empty and reduction not satisfied + + CollapseTris->Delete(); + + totalPts = this->Mesh->GetNumberOfPoints(); + vtkDebugMacro(<<"\n\tReduction " << reduction << " (" << numTris << " to " + << numTris - totalEliminated << " triangles)" + <<"\n\tPerformed " << numPops << " vertex pops" + <<"\n\tFound " << this->GetNumberOfInflectionPoints() + <<" inflection points" + <<"\n\tPerformed " << totalPts - numPts << " vertex splits" + <<"\n\tPerformed " << this->NumCollapses << " edge collapses" + <<"\n\tPerformed " << this->NumMerges << " vertex merges" + <<"\n\tRecycled " << numRecycles << " points" + <<"\n\tAdded " << totalPts - numPts << " points (" + << numPts << " to " << totalPts << " points)"); + + // + // Create output and release memory + // + vtkDebugMacro (<<"Creating output..."); + this->DeleteQueue(); + + // Grab the points that are left; copy point data. Remember that splitting + // data may have added new points. + map = new vtkIdType[totalPts]; + for (i=0; i < totalPts; i++) + { + map[i] = -1; + } + numNewPts = 0; + for (ptId=0; ptId < totalPts; ptId++) + { + this->Mesh->GetPointCells(ptId,ncells,cells); + if ( ncells > 0 ) + { + map[ptId] = numNewPts++; + } + } + + outputPD->CopyAllocate(meshPD,numNewPts); + + // Copy points in place + for (ptId=0; ptId < totalPts; ptId++) + { + if ( map[ptId] > -1 ) + { + newPts->SetPoint(map[ptId],newPts->GetPoint(ptId)); + outputPD->CopyData(meshPD,ptId,map[ptId]); + } + } + + newPts->SetNumberOfPoints(numNewPts); + newPts->Squeeze(); + + // Now renumber connectivity + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(3,numTris-totalEliminated)); + + for (cellId=0; cellId < numTris; cellId++) + { + if ( this->Mesh->GetCellType(cellId) == VTK_TRIANGLE ) // non-null element + { + this->Mesh->GetCellPoints(cellId, npts, pts); + for (i=0; i < 3; i++) + { + newCellPts[i] = map[pts[i]]; + } + newPolys->InsertNextCell(npts,newCellPts); + } + } + + delete [] map; + output->SetPoints(newPts); + output->SetPolys(newPolys); + if (this->Mesh != NULL) {this->Mesh->Delete(); this->Mesh = NULL;} + newPolys->Delete(); + + return 1; +} + +// +// Computes error to edge (distance squared) +// +static double ComputeEdgeError(double x[3], double x1[3], double x2[3]) +{ + double projDist = vtkLine::DistanceToLine(x, x1, x2); + double edgeLength = vtkMath::Distance2BetweenPoints(x1,x2); + + return (projDist < edgeLength ? projDist : edgeLength); +} + +// +// Computes triangle area +// +static double ComputeSingleTriangleError(double x[3], double x1[3], double x2[3]) +{ + return vtkTriangle::TriangleArea(x, x1, x2); +} + +// +// Computes error to a cycle of triangles...the average plane (normal and +// point) have been already computed. (Returns distance squared.) +// +static double ComputeSimpleError(double x[3], double normal[3], double point[3]) +{ + double dist = vtkPlane::DistanceToPlane(x, normal, point); + return dist * dist; +} + +// +// Split the mesh along sharp edges - separates the mesh into pieces. +// +void vtkDecimatePro::SplitMesh() +{ + vtkIdType ptId, fedges[2]; + int type; + vtkIdType *cells; + unsigned short int ncells; + + this->CosAngle = cos ((double) vtkMath::DegreesToRadians() * this->SplitAngle); + for ( ptId=0; ptId < this->Mesh->GetNumberOfPoints(); ptId++ ) + { + this->Mesh->GetPoint(ptId,this->X); + this->Mesh->GetPointCells(ptId,ncells,cells); + + if ( ncells > 0 && + ((type=this->EvaluateVertex(ptId,ncells,cells,fedges)) == VTK_CORNER_VERTEX || + type == VTK_INTERIOR_EDGE_VERTEX || + type == VTK_NON_MANIFOLD_VERTEX) ) + { + this->SplitVertex(ptId, type, ncells, cells, 0); + } + } +} + +#define VTK_FEATURE_ANGLE(tri1,tri2) \ + vtkMath::Dot(this->T->Array[tri1].n, this->T->Array[tri2].n) +// +// Evalute the local topology/geometry of a vertex. This is a two-pass +// process: first topology is examined, and then the geometry. +// +int vtkDecimatePro::EvaluateVertex(vtkIdType ptId, unsigned short int numTris, + vtkIdType *tris, vtkIdType fedges[2]) +{ + vtkIdType numNei, numFEdges; + vtkIdType numVerts; + vtkDecimatePro::LocalTri t; + vtkDecimatePro::LocalVertex sn; + vtkIdType startVertex, nextVertex, numNormals; + int i, j, vtype; + vtkIdType *verts; + double *x1, *x2, *normal; + double v1[3], v2[3], center[3]; + // + // The first step is to evaluate topology. + // + + // Check cases with high vertex degree + // + if ( numTris >= this->VertexDegree ) + { + return VTK_HIGH_DEGREE_VERTEX; + } + + // From the adjacency structure we can find the triangles that use the + // vertex. Traverse this structure, gathering all the surrounding vertices + // into an ordered list. + // + this->V->Reset(); + this->T->Reset(); + + sn.FAngle = 0.0; + + t.area = 0.0; + t.n[0] = t.n[1] = t.n[2] = 0.0; + t.verts[0] = -1; // Marks the fact that this poly hasn't been replaced + t.verts[1] = -1; + t.verts[2] = -1; + // + // Find the starting edge. Do it very carefully do make sure + // ordering is consistent + // (e.g., polygons ordering/normals remains consistent) + // + this->Mesh->GetCellPoints(*tris,numVerts,verts); // get starting point + for (i=0; i<3; i++) + { + if (verts[i] == ptId) + { + break; + } + } + sn.id = startVertex = verts[(i+1)%3]; + this->Mesh->GetPoint(sn.id, sn.x); //grab coordinates here to save GetPoint() calls + + this->V->InsertNextVertex(sn); + + nextVertex = -1; // initialize + this->Neighbors->Reset(); + this->Neighbors->InsertId(0,*tris); + numNei = 1; + // + // Traverse the edge neighbors and see whether a cycle can be + // completed. Also have to keep track of orientation of faces for + // computing normals. + // + while ( this->T->MaxId < numTris && numNei == 1 && nextVertex != startVertex) + { + t.id = this->Neighbors->GetId(0); + this->T->InsertNextTriangle(t); + + this->Mesh->GetCellPoints(t.id,numVerts,verts); + + for (j=0; j<3; j++) + { + if (verts[j] != sn.id && verts[j] != ptId) + { + nextVertex = verts[j]; + break; + } + } + sn.id = nextVertex; + this->Mesh->GetPoint(sn.id, sn.x); + this->V->InsertNextVertex(sn); + + this->Mesh->GetCellEdgeNeighbors(t.id, ptId, nextVertex, this->Neighbors); + numNei = this->Neighbors->GetNumberOfIds(); + } + // + // See whether we've run around the loop, hit a boundary, or hit a + // complex spot. + // + if ( nextVertex == startVertex && numNei == 1 ) + { + if ( this->T->GetNumberOfTriangles() != numTris ) //touching non-manifold + { + vtype = VTK_NON_MANIFOLD_VERTEX; + } + else //remove last vertex addition + { + this->V->MaxId -= 1; + vtype = VTK_SIMPLE_VERTEX; + } + } + // + // Check for non-manifold cases + // + else if ( numNei > 1 || this->T->GetNumberOfTriangles() > numTris ) + { + vtype = VTK_NON_MANIFOLD_VERTEX; + } + // + // Boundary loop - but (luckily) completed semi-cycle + // + else if ( numNei == 0 && this->T->GetNumberOfTriangles() == numTris ) + { + this->V->Array[0].FAngle = -1.0; // using cosine of -180 degrees + this->V->Array[this->V->MaxId].FAngle = -1.0; + vtype = VTK_BOUNDARY_VERTEX; + } + // + // Hit a boundary but didn't complete semi-cycle. Gotta go back + // around the other way. Just reset the starting point and go + // back the other way. + // + else + { + t = this->T->GetTriangle(this->T->MaxId); + + this->V->Reset(); + this->T->Reset(); + + startVertex = sn.id = nextVertex; + this->Mesh->GetPoint(sn.id, sn.x); + this->V->InsertNextVertex(sn); + + nextVertex = -1; + this->Neighbors->Reset(); + this->Neighbors->InsertId(0,t.id); + numNei = 1; + // + // Now move from boundary edge around the other way. + // + while ( this->T->MaxId < numTris && numNei == 1 && nextVertex != startVertex) + { + t.id = this->Neighbors->GetId(0); + this->T->InsertNextTriangle(t); + + this->Mesh->GetCellPoints(t.id,numVerts,verts); + + for (j=0; j<3; j++) + { + if (verts[j] != sn.id && verts[j] != ptId) + { + nextVertex = verts[j]; + break; + } + } + + sn.id = nextVertex; + this->Mesh->GetPoint(sn.id, sn.x); + this->V->InsertNextVertex(sn); + + this->Mesh->GetCellEdgeNeighbors(t.id, ptId, nextVertex, this->Neighbors); + numNei = this->Neighbors->GetNumberOfIds(); + } + // + // Make sure that there are only two boundaries (i.e., not non-manifold) + // + if ( this->T->GetNumberOfTriangles() == numTris ) + { + // + // Because we've reversed order of loop, need to rearrange the order + // of the vertices and polygons to preserve consistent polygons + // ordering / normal orientation. + // + numVerts = this->V->GetNumberOfVertices(); + for (i=0; i<(numVerts/2); i++) + { + sn.id = this->V->Array[i].id; + this->V->Array[i].id = this->V->Array[numVerts-i-1].id; + this->V->Array[numVerts-i-1].id = sn.id; + for (j=0; j<3; j++) + { + sn.x[j] = this->V->Array[i].x[j]; + this->V->Array[i].x[j] = this->V->Array[numVerts-i-1].x[j]; + this->V->Array[numVerts-i-1].x[j] = sn.x[j]; + } + } + + numTris = this->T->GetNumberOfTriangles(); + for (i=0; i<(numTris/2); i++) + { + t.id = this->T->Array[i].id; + this->T->Array[i].id = this->T->Array[numTris-i-1].id; + this->T->Array[numTris-i-1].id = t.id; + } + + this->V->Array[0].FAngle = -1.0; + this->V->Array[this->V->MaxId].FAngle = -1.0; + vtype = VTK_BOUNDARY_VERTEX; + } + else // non-manifold + { + vtype = VTK_NON_MANIFOLD_VERTEX; + } + } + // + // If at this point, the vertex is either simple or boundary. Here we do + // a geometric evaluation to find feature edges, if any, and then a + // final classification. + // + + // + // Traverse all polygons and generate normals and areas + // + x2 = this->V->Array[0].x; + for (i=0; i<3; i++) + { + v2[i] = x2[i] - this->X[i]; + } + + this->LoopArea=0.0; + this->Normal[0] = this->Normal[1] = this->Normal[2] = 0.0; + this->Pt[0] = this->Pt[1] = this->Pt[2] = 0.0; + numNormals=0; + + for (i=0; i < this->T->GetNumberOfTriangles(); i++) + { + normal = this->T->Array[i].n; + x1 = x2; + x2 = this->V->Array[i+1].x; + + for (j=0; j<3; j++) + { + v1[j] = v2[j]; + v2[j] = x2[j] - this->X[j]; + } + + this->T->Array[i].area = vtkTriangle::TriangleArea (this->X, x1, x2); + vtkTriangle::TriangleCenter (this->X, x1, x2, center); + this->LoopArea += this->T->Array[i].area; + + vtkMath::Cross (v1, v2, normal); + // + // Get normals. If null, then normal make no contribution to loop. + // The center of the loop is the center of gravity. + // + if ( vtkMath::Normalize(normal) != 0.0 ) + { + numNormals++; + for (j=0; j<3; j++) + { + this->Normal[j] += this->T->Array[i].area * normal[j]; + this->Pt[j] += this->T->Array[i].area * center[j]; + } + } + } + // + // Compute "average" plane normal and plane center. Use an area + // averaged normal calulation + // + if ( !numNormals || this->LoopArea == 0.0 ) + { + return VTK_DEGENERATE_VERTEX; + } + + for (j=0; j<3; j++) + { + this->Normal[j] /= this->LoopArea; + this->Pt[j] /= this->LoopArea; + } + if ( vtkMath::Normalize(this->Normal) == 0.0 ) + { + return VTK_DEGENERATE_VERTEX; + } + // + // Now run through polygons again generating feature angles. (Note + // that if an edge is on the boundary its feature angle has already + // been set to 180.) Also need to keep track whether any feature + // angles exceed the current value. + // + if ( vtype == VTK_BOUNDARY_VERTEX ) + { + numFEdges = 2; + fedges[0] = 0; + fedges[1] = this->V->MaxId; + } + else + { + numFEdges = 0; + } + // + // Compare to cosine of feature angle to avoid cosine extraction + // + if ( vtype == VTK_SIMPLE_VERTEX ) // first edge + { + if ( (this->V->Array[0].FAngle = VTK_FEATURE_ANGLE(0,this->T->MaxId)) <= this->CosAngle ) + { + fedges[numFEdges++] = 0; + } + } + + for (i=0; i < this->T->MaxId; i++) + { + if ( (this->V->Array[i+1].FAngle = VTK_FEATURE_ANGLE(i,i+1)) <= this->CosAngle ) + { + if ( numFEdges >= 2 ) + { + numFEdges++; + } + else + { + fedges[numFEdges++] = i + 1; + } + } + } + // + // Final classification + // + if ( vtype == VTK_SIMPLE_VERTEX && numFEdges > 0 ) + { + if ( numFEdges == 1 ) + { + vtype = VTK_EDGE_END_VERTEX; + } + else if ( numFEdges == 2 ) + { + vtype = VTK_INTERIOR_EDGE_VERTEX; + } + else + { + vtype = VTK_CORNER_VERTEX; + } + } + else if ( vtype == VTK_BOUNDARY_VERTEX ) + { + if ( numFEdges != 2 ) + { + vtype = VTK_CORNER_VERTEX; + } + else + {//see whether this is the tip of a crack + if ( this->V->Array[fedges[0]].x[0] == this->V->Array[fedges[1]].x[0] && + this->V->Array[fedges[0]].x[1] == this->V->Array[fedges[1]].x[1] && + this->V->Array[fedges[0]].x[2] == this->V->Array[fedges[1]].x[2]) + { + vtype = VTK_CRACK_TIP_VERTEX; + } + } + } + + return vtype; +} + +// +// Split the vertex by modifying topological connections. +// +void vtkDecimatePro::SplitVertex(vtkIdType ptId, int type, + unsigned short int numTris, vtkIdType *tris, + int insert) +{ + vtkIdType id, fedge1, fedge2, i, j; + vtkIdType tri, veryFirst; + int numSplitTris; + vtkIdType *verts, nverts; + double error; + vtkIdType startTri, p[2]; + int maxGroupSize; + vtkPointData* meshPD = this->Mesh->GetPointData(); + + // + // On an interior edge split along the edge + // + if ( type == VTK_INTERIOR_EDGE_VERTEX ) //when edge splitting is on + { + // Half of loop is left connected to current vertex. Second half is + // split away. + for ( i=0; i < numTris; i++ ) // find first feature edge + { + if ( this->V->Array[i].FAngle <= this->CosAngle ) + { + break; + } + } + fedge1 = i; + for ( i++, numSplitTris=1; this->V->Array[i].FAngle > this->CosAngle; i++ ) + { + numSplitTris++; + } + + fedge2 = i; + + // Now split region + id = this->Mesh->InsertNextLinkedPoint(this->X,numSplitTris); + meshPD->CopyData(meshPD, ptId, id); + for ( i=fedge1; i < fedge2; i++ ) + { //disconnect from existing vertex + tri = this->T->Array[i].id; + this->Mesh->RemoveReferenceToCell(ptId, tri); + this->Mesh->AddReferenceToCell(id, tri); + this->Mesh->ReplaceCellPoint(tri, ptId, id); + } + + // Compute error and insert the two vertices (old + split) + error = ComputeEdgeError(this->X, this->V->Array[fedge1].x, this->V->Array[fedge2].x); + if ( this->AccumulateError ) + { + this->VertexError->InsertValue(id, this->VertexError->GetValue(ptId)); + } + + if ( insert ) + { + this->Insert(ptId,error); + this->Insert(id,error); + } + } + + // + // Break corners into separate pieces (along feature edges) + // + else if ( type == VTK_CORNER_VERTEX ) + { + // The first piece is left connected to vertex. Just find first + // feature/boundary edge. If on boundary, skip boundary piece. + for ( i=0; i <= this->V->MaxId; i++ ) // find first feature edge + { + if ( this->V->Array[i].FAngle <= this->CosAngle && this->V->Array[i].FAngle != -1.0 ) + { + break; + } + } + for ( veryFirst = fedge1 = i; fedge1 < this->V->MaxId; i = fedge1 = fedge2 ) + { + for (i++, numSplitTris=1; + i <= this->V->MaxId && this->V->Array[i].FAngle > this->CosAngle; i++) + { + numSplitTris++; + } + + if ( (fedge2 = i) > this->V->MaxId ) + { + continue; //must be part of first region + } + + // Now split region + id = this->Mesh->InsertNextLinkedPoint(this->X,numSplitTris); + meshPD->CopyData(meshPD, ptId, id); + + for ( j=fedge1; j < fedge2; j++ ) + { //disconnect from existing vertex + tri = this->T->Array[j].id; + this->Mesh->RemoveReferenceToCell(ptId, tri); + this->Mesh->AddReferenceToCell(id, tri); + this->Mesh->ReplaceCellPoint(tri, ptId, id); + } + + // Compute error for the vertex and insert + error = ComputeEdgeError(this->X, this->V->Array[fedge1].x, this->V->Array[fedge2].x); + if ( this->AccumulateError ) + { + this->VertexError->InsertValue(id, this->VertexError->GetValue(ptId)); + } + + if ( insert ) + { + this->Insert(id,error); + } + } + + // don't forget to compute error for old vertex, and insert into queue + if ( this->V->Array[0].FAngle == -1.0 ) + { + error = ComputeEdgeError(this->X, this->V->Array[0].x, this->V->Array[veryFirst].x); + } + else + { + error = ComputeEdgeError(this->X, this->V->Array[veryFirst].x, this->V->Array[fedge1].x); + } + + if ( insert ) + { + this->Insert(ptId,error); + } + } + + // Default case just splits off triangle(s) that form manifold groups. + // Note: this code also handles high-degree vertices. + else + { + vtkIdList *triangles = vtkIdList::New(); + vtkIdList *cellIds = vtkIdList::New(); + vtkIdList *group = vtkIdList::New(); + + triangles->Allocate(VTK_MAX_TRIS_PER_VERTEX); + cellIds->Allocate(5,10); + group->Allocate(VTK_MAX_TRIS_PER_VERTEX); + + //changes in group size control how to split loop + if ( numTris <= 1 ) + { + triangles->Delete(); + cellIds->Delete(); + group->Delete(); + return; //prevents infinite recursion + } + maxGroupSize = ( numTris < this->VertexDegree ? numTris : (this->VertexDegree - 1)); + + if ( type == VTK_NON_MANIFOLD_VERTEX || type == VTK_HIGH_DEGREE_VERTEX ) + { + ; //use maxGroupSize + } + else + { + maxGroupSize /= 2; //prevents infinite recursion + } + + for ( i=0; i < numTris; i++ ) + { + triangles->InsertId(i,tris[i]); + } + + // now group into manifold pieces + for ( i=0; triangles->GetNumberOfIds() > 0; i++ ) + { + group->Reset(); + startTri = triangles->GetId(0); + group->InsertId(0,startTri); + triangles->DeleteId(startTri); + this->Mesh->GetCellPoints(startTri,nverts,verts); + p[0] = ( verts[0] != ptId ? verts[0] : verts[1] ); + p[1] = ( verts[1] != ptId && verts[1] != p[0] ? verts[1] : verts[2] ); + + //grab manifold group - j index is the forward/backward direction around vertex + for ( j=0; j < 2; j++ ) + { + for ( tri=startTri; p[j] >= 0; ) + { + this->Mesh->GetCellEdgeNeighbors(tri, ptId, p[j], cellIds); + if ( cellIds->GetNumberOfIds() == 1 && + triangles->IsId((tri=cellIds->GetId(0))) > -1 && + group->GetNumberOfIds() < maxGroupSize ) + { + group->InsertNextId(tri); + triangles->DeleteId(tri); + this->Mesh->GetCellPoints(tri,nverts,verts); + if ( verts[0] != ptId && verts[0] != p[j] ) + { + p[j] = verts[0]; + } + else if ( verts[1] != ptId && verts[1] != p[j] ) + { + p[j] = verts[1]; + } + else + { + p[j] = verts[2]; + } + } + else + { + p[j] = -1; + } + } + }//for both directions + + // reconnect group into manifold chunk (first group is left attached) + if ( i != 0 ) + { + id = this->Mesh->InsertNextLinkedPoint(this->X,group->GetNumberOfIds()); + meshPD->CopyData(meshPD, ptId, id); + + for ( j=0; j < group->GetNumberOfIds(); j++ ) + { + tri = group->GetId(j); + this->Mesh->RemoveReferenceToCell(ptId, tri); + this->Mesh->AddReferenceToCell(id, tri); + this->Mesh->ReplaceCellPoint(tri, ptId, id); + } + if ( this->AccumulateError ) + { + this->VertexError->InsertValue(id, this->VertexError->GetValue(ptId)); + } + if ( insert ) + { + this->Insert(id); + } + }//if not first group + }//for all groups + //Don't forget to reinsert original vertex + if ( insert ) + { + this->Insert(ptId); + } + + triangles->Delete(); + cellIds->Delete(); + group->Delete(); + } + + return; +} + + +// +// Find a way to split this loop. If -1 is returned, then we have a real +// bad situation and we'll split the vertex. +// +vtkIdType vtkDecimatePro::FindSplit (int type, vtkIdType fedges[2], + vtkIdType& pt1, vtkIdType& pt2, + vtkIdList *CollapseTris) +{ + vtkIdType i, maxI; + double dist2, e2dist2; + vtkIdType numVerts=this->V->MaxId+1; + + pt2 = -1; + CollapseTris->SetNumberOfIds(2); + this->EdgeLengths->Reset(); + + switch (type) + { + case VTK_SIMPLE_VERTEX: + case VTK_EDGE_END_VERTEX: + case VTK_INTERIOR_EDGE_VERTEX: + if ( type == VTK_INTERIOR_EDGE_VERTEX ) + { + dist2 = vtkMath::Distance2BetweenPoints(this->X, + this->V->Array[fedges[0]].x); + this->EdgeLengths->Insert(dist2,fedges[0]); + + dist2 = vtkMath::Distance2BetweenPoints(this->X, + this->V->Array[fedges[1]].x); + this->EdgeLengths->Insert(dist2,fedges[1]); + } + else // Compute the edge lengths + { + for ( i=0; i < numVerts; i++ ) + { + dist2 = vtkMath::Distance2BetweenPoints(this->X, + this->V->Array[i].x); + this->EdgeLengths->Insert(dist2,i); + } + } + + // See whether the collapse is okay + while ( (maxI = this->EdgeLengths->Pop(0, dist2)) >= 0 ) + { + if ( this->IsValidSplit(maxI) ) + { + break; + } + } + + if ( maxI >= 0 ) + { + CollapseTris->SetId(0,this->T->Array[maxI].id); + if ( maxI == 0 ) + { + pt1 = this->V->Array[1].id; + pt2 = this->V->Array[this->V->MaxId].id; + CollapseTris->SetId(1,this->T->Array[this->T->MaxId].id); + } + else + { + pt1 = this->V->Array[(maxI+1)%numVerts].id; + pt2 = this->V->Array[maxI-1].id; + CollapseTris->SetId(1,this->T->Array[maxI-1].id); + } + + return this->V->Array[maxI].id; + } + break; + + case VTK_BOUNDARY_VERTEX: //-------------------------------------------- + CollapseTris->SetNumberOfIds(1); + // Compute the edge lengths + dist2 = vtkMath::Distance2BetweenPoints(this->X, this->V->Array[0].x); + e2dist2 = vtkMath::Distance2BetweenPoints(this->X,this->V->Array[this->V->MaxId].x); + + maxI = -1; + if ( dist2 <= e2dist2 ) + { + if ( this->IsValidSplit(0) ) + { + maxI = 0; + } + else if ( this->IsValidSplit(this->V->MaxId) ) + { + maxI = this->V->MaxId; + } + } + else + { + if ( this->IsValidSplit(this->V->MaxId) ) + { + maxI = this->V->MaxId; + } + else if ( this->IsValidSplit(0) ) + { + maxI = 0; + } + } + + if ( maxI >= 0 ) + { + if ( maxI == 0 ) + { + CollapseTris->SetId(0,this->T->Array[0].id); + pt1 = this->V->Array[1].id; + return this->V->Array[0].id; + } + else + { + CollapseTris->SetId(0,this->T->Array[this->T->MaxId].id); + pt1 = this->V->Array[this->V->MaxId-1].id; + return this->V->Array[this->V->MaxId].id; + } + } + break; + + case VTK_CRACK_TIP_VERTEX: //------------------------------------------- + this->V->MaxId--; + if ( this->IsValidSplit(0) ) + { + CollapseTris->SetId(0,this->T->Array[0].id); + pt1 = this->V->Array[1].id; + pt2 = this->V->Array[this->V->MaxId].id; + CollapseTris->SetId(1,this->T->Array[this->T->MaxId].id); + return this->V->Array[0].id; + } + else + { + this->V->MaxId++; + } + break; + + case VTK_DEGENERATE_VERTEX: //------------------------------------------- + // Collapse to the first edge + CollapseTris->SetId(0,this->T->Array[0].id); + pt1 = this->V->Array[1].id; + if ( this->T->MaxId > 0 ) //more than one triangle + { + if ( this->T->MaxId == this->V->MaxId ) //a complete cycle + { + CollapseTris->SetId(1,this->T->Array[this->T->MaxId].id); + pt2 = this->V->Array[this->V->MaxId].id; + } + else + { + CollapseTris->SetNumberOfIds(1); + } + } + else + { + CollapseTris->SetNumberOfIds(1); + } + return this->V->Array[0].id; + + default: + ; + } + + return -1; +} + +// +// Determine whether the loop can be split at the vertex indicated +// +int vtkDecimatePro::IsValidSplit(int index) +{ + vtkIdType fedges[2]; + int i, sign; + vtkIdType nverts=this->V->MaxId+1, j; + double *x, val, sPt[3], v21[3], sN[3]; + vtkIdType l1[VTK_MAX_TRIS_PER_VERTEX], l2[VTK_MAX_TRIS_PER_VERTEX]; + vtkIdType n1, n2; + + // For a edge collapse to be valid, all edges to that vertex must + // divide the loop cleanly. + fedges[0] = index; + for ( j=0; j < (nverts-3); j++ ) + { + fedges[1] = (index + 2 + j) % nverts; + this->SplitLoop (fedges, n1, l1, n2, l2); + + // Create splitting plane. Splitting plane is parallel to the loop + // plane normal and contains the splitting vertices fedges[0] and fedges[1]. + for (i=0; i<3; i++) + { + sPt[i] = this->V->Array[fedges[0]].x[i]; + v21[i] = this->V->Array[fedges[1]].x[i] - sPt[i]; + } + + vtkMath::Cross (v21,this->Normal,sN); + if ( vtkMath::Normalize(sN) == 0.0 ) + { + return 0; + } + + for (sign=0, i=0; i < n1; i++) // first loop + { + if ( !(l1[i] == fedges[0] || l1[i] == fedges[1]) ) + { + x = this->V->Array[l1[i]].x; + val = vtkPlane::Evaluate(sN,sPt,x); + if ( ((double) fabs((double)val)) < this->Tolerance ) + { + return 0; + } + + if ( !sign ) + { + sign = (val > this->Tolerance ? 1 : -1); + } + else if ( sign != (val > 0 ? 1 : -1) ) + { + return 0; + } + } + } + + sign *= -1; + for (i=0; i < n2; i++) // second loop + { + if ( !(l2[i] == fedges[0] || l2[i] == fedges[1]) ) + { + x = this->V->Array[l2[i]].x; + val = vtkPlane::Evaluate(sN,sPt,x); + if ( ((double) fabs((double)val)) < this->Tolerance ) + { + return 0; + } + if ( !sign ) + { + sign = (val > this->Tolerance ? 1 : -1); + } + else if ( sign != (val > 0 ? 1 : -1) ) + { + return 0; + } + } + } + }// Check all splits + return 1; +} + +// +// Creates two loops from splitting plane provided +// +void vtkDecimatePro::SplitLoop(vtkIdType fedges[2], vtkIdType& n1, + vtkIdType *l1, vtkIdType& n2, vtkIdType *l2) +{ + vtkIdType i; + vtkIdType *loop; + vtkIdType *count; + + n1 = n2 = 0; + loop = l1; + count = &n1; + + for (i=0; i <= this->V->MaxId; i++) + { + loop[(*count)++] = i; + if ( i == fedges[0] || i == fedges[1] ) + { + loop = (loop == l1 ? l2 : l1); + count = (count == &n1 ? &n2 : &n1); + loop[(*count)++] = i; + } + } +} + +// Collapse the point to the specified vertex. Distribute the error +// and update neighborhood vertices. +int vtkDecimatePro::CollapseEdge(int type, vtkIdType ptId, + vtkIdType collapseId, vtkIdType pt1, + vtkIdType pt2, vtkIdList *CollapseTris) +{ + vtkIdType i, numDeleted=CollapseTris->GetNumberOfIds(); + vtkIdType ntris=this->T->MaxId+1; + vtkIdType nverts=this->V->MaxId+1; + vtkIdType tri[2]; + vtkIdType verts[VTK_MAX_TRIS_PER_VERTEX+1]; + + this->NumCollapses++; + for ( i=0; i < numDeleted; i++ ) + { + tri[i] = CollapseTris->GetId(i); + } + + // type == VTK_CRACK_TIP_VERTEX || type == VTK_SIMPLE_VERTEX + if ( numDeleted == 2 ) + { + if ( type == VTK_CRACK_TIP_VERTEX ) //got to seal the crack first + { + this->NumMerges++; + this->Mesh->RemoveReferenceToCell(this->V->Array[this->V->MaxId+1].id, tri[1]); + this->Mesh->ReplaceCellPoint(tri[1],this->V->Array[this->V->MaxId+1].id, collapseId); + } + + // delete two triangles + this->Mesh->RemoveReferenceToCell(pt1, tri[0]); + this->Mesh->RemoveReferenceToCell(pt2, tri[1]); + this->Mesh->RemoveReferenceToCell(collapseId, tri[0]); + this->Mesh->RemoveReferenceToCell(collapseId, tri[1]); + this->Mesh->DeletePoint(ptId); + this->Mesh->DeleteCell(tri[0]); this->Mesh->DeleteCell(tri[1]); + + // update topology to reflect new attachments + this->Mesh->ResizeCellList(collapseId, ntris-2); + for ( i=0; i < ntris; i++ ) + { + if ( this->T->Array[i].id != tri[0] && this->T->Array[i].id != tri[1] ) + { + this->Mesh->AddReferenceToCell(collapseId, this->T->Array[i].id); + this->Mesh->ReplaceCellPoint(this->T->Array[i].id,ptId,collapseId); + } + } + }//if interior vertex + + else // if ( numDeleted == 1 ) e.g., VTK_BOUNDARY_VERTEX + { + // delete one triangle + this->Mesh->RemoveReferenceToCell(pt1, tri[0]); + this->Mesh->RemoveReferenceToCell(collapseId, tri[0]); + this->Mesh->DeletePoint(ptId); + this->Mesh->DeleteCell(tri[0]); + + // update topology to reflect new attachments + if ( ntris > 1 ) + { + this->Mesh->ResizeCellList(collapseId, ntris-1); + for ( i=0; i < ntris; i++ ) + { + if ( this->T->Array[i].id != tri[0] ) + { + this->Mesh->AddReferenceToCell(collapseId, this->T->Array[i].id); + this->Mesh->ReplaceCellPoint(this->T->Array[i].id,ptId,collapseId); + } + } + } + } //else boundary vertex + + // Update surrounding vertices. Need to copy verts first because the V/T + // arrays might change as points are being reinserted. + // + for ( i=0; i < nverts; i++ ) + { + verts[i] = this->V->Array[i].id; + } + for ( i=0; i < nverts; i++ ) + { + this->DeleteId(verts[i]); + this->Insert(verts[i]); + } + + return numDeleted; +} + +// Get a list of inflection points. These are double values 0 < r <= 1.0 +// corresponding to reduction level, and there are a total of +// NumberOfInflectionPoints() values. You must provide an array (of +// the correct size) into which the inflection points are written. +void vtkDecimatePro::GetInflectionPoints(double *inflectionPoints) +{ + vtkIdType i; + + for (i=0; i < this->GetNumberOfInflectionPoints(); i++) + { + inflectionPoints[i] = this->InflectionPoints->GetValue(i); + } +} + +// Get a list of inflection points. These are double values 0 < r <= 1.0 +// corresponding to reduction level, and there are a total of +// NumberOfInflectionPoints() values. You must provide an array (of +// the correct size) into which the inflection points are written. +// This method returns a pointer to a list of inflection points. +double *vtkDecimatePro::GetInflectionPoints() +{ + return this->InflectionPoints->GetPointer(0); +} + +// Get the number of inflection points. Only returns a valid value +// after the filter has executed. +vtkIdType vtkDecimatePro::GetNumberOfInflectionPoints() +{ + return this->InflectionPoints->GetMaxId()+1; +} + +// +// The following are private functions used to manage the priority +// queue of vertices. +// + +void vtkDecimatePro::InitializeQueue(vtkIdType numPts) +{ + if ( !this->PreserveTopology && this->Splitting ) + { + numPts = (vtkIdType) ((double)numPts*1.25); + } + + this->Queue = vtkPriorityQueue::New(); + this->Queue->Allocate(numPts, (vtkIdType)((double)0.25*numPts)); +} + +int vtkDecimatePro::Pop(double &error) +{ + vtkIdType ptId; + + // Try returning what's in queue + if ( (ptId = this->Queue->Pop(0, error)) >= 0 ) + { + if ( error > this->Error ) + { + this->Queue->Reset(); + } + else + { + return ptId; + } + } + + // See whether anything's left and split/re-insert if allowed + if ( this->NumberOfRemainingTris > 0 && this->Split && + this->SplitState == VTK_STATE_UNSPLIT ) + { + vtkDebugMacro(<<"Splitting this->Mesh"); + + this->SplitState = VTK_STATE_SPLIT; + this->SplitMesh(); + this->CosAngle = cos ((double) vtkMath::DegreesToRadians() * this->SplitAngle); + + // Now that things are split, insert the vertices. (Have to do this + // otherwise error calculation is incorrect.) + for ( ptId=0; ptId < this->Mesh->GetNumberOfPoints(); ptId++ ) + { + this->Insert(ptId); + } + + if ( (ptId = this->Queue->Pop(0, error)) >= 0 ) + { + if ( error > this->Error ) + { + this->Queue->Reset(); + } + else + { + return ptId; + } + } + } + + // If here, then this->Mesh splitting hasn't helped or is exhausted. Run thru + // vertices and split them as necessary no matter what. + if ( this->NumberOfRemainingTris > 0 && this->Split && this->SplitState != VTK_STATE_SPLIT_ALL ) + { + vtkDebugMacro(<<"Final splitting attempt"); + + this->SplitState = VTK_STATE_SPLIT_ALL; + for ( ptId=0; ptId < this->Mesh->GetNumberOfPoints(); ptId++ ) + { + this->Insert(ptId); + } + + if ( (ptId = this->Queue->Pop(0, error)) >= 0 ) + { + if ( error > this->Error ) + { + this->Queue->Reset(); + } + else + { + return ptId; + } + } + } + + //every possible point has been processed + return -1; +} + +// Computes error and inserts point into priority queue. +void vtkDecimatePro::Insert(vtkIdType ptId, double error) +{ + int type, simpleType; + vtkIdType *cells; + vtkIdType fedges[2]; + unsigned short int ncells; + + // on value of error, we need to compute it or just insert the point + if ( error < -this->Tolerance ) + { + this->Mesh->GetPoint(ptId,this->X); + this->Mesh->GetPointCells(ptId,ncells,cells); + + if ( ncells > 0 ) + { + simpleType = 0; + type = this->EvaluateVertex(ptId, ncells, cells, fedges); + + // Compute error for simple types - split vertex handles others + if ( type == VTK_SIMPLE_VERTEX || type == VTK_EDGE_END_VERTEX || + type == VTK_CRACK_TIP_VERTEX ) + { + simpleType = 1; + error = ComputeSimpleError(this->X,this->Normal,this->Pt); + } + + else if ( (type == VTK_INTERIOR_EDGE_VERTEX) || + (type == VTK_BOUNDARY_VERTEX && this->BoundaryVertexDeletion) ) + { + simpleType = 1; + if ( ncells == 1 ) //compute better error for single triangle + { + error = ComputeSingleTriangleError(this->X,this->V->Array[0].x, + this->V->Array[1].x); + } + else + { + error = ComputeEdgeError(this->X, this->V->Array[fedges[0]].x, + this->V->Array[fedges[1]].x); + } + } + + if ( simpleType ) + { + if ( this->AccumulateError ) + { + error += this->VertexError->GetValue(ptId); + } + this->Queue->Insert(error,ptId); + } + + // Type is complex so we break it up (if splitting allowed). A + // side-effect of splitting a vertex is that it inserts it and any + // new vertices into queue. + else if ( this->SplitState == VTK_STATE_SPLIT && type != VTK_DEGENERATE_VERTEX ) + { + this->SplitVertex(ptId, type, ncells, cells, 1); + } //not a simple type + + } //if cells attached to vertex + } //need to compute the error + + // If point is being recycled, see whether we want to split it + else if ( error >= VTK_RECYCLE_VERTEX ) + { + //see whether to split it, otherwise it isn't inserted yet + if ( this->SplitState == VTK_STATE_SPLIT_ALL ) + { + this->Mesh->GetPoint(ptId,this->X); + this->Mesh->GetPointCells(ptId,ncells,cells); + if ( ncells > 0 ) + { + type = this->EvaluateVertex(ptId, ncells, cells, fedges); + this->SplitVertex(ptId, type, ncells, cells, 1); + } + } + } + + // Sometimes the error is computed for us so we insert it appropriately + else + { + if ( this->AccumulateError ) + { + error += this->VertexError->GetValue(ptId); + } + this->Queue->Insert(error,ptId); + } +} + +// Compute the error of the point to the new triangulated surface +void vtkDecimatePro::DistributeError(double error) +{ + vtkIdType i; + vtkIdType nverts=this->V->MaxId+1; + double previousError; + + for (i=0; i < nverts; i++) + { + previousError = this->VertexError->GetValue(this->V->Array[i].id); + this->VertexError->SetValue(this->V->Array[i].id, previousError+error); + } +} +void vtkDecimatePro::DeleteQueue() +{ + if (this->Queue) + { + this->Queue->Delete(); + } + this->Queue=NULL; +} + +double vtkDecimatePro::DeleteId(vtkIdType id) +{ + return this->Queue->DeleteId(id); +} + +void vtkDecimatePro::Reset() +{ + this->Queue->Reset(); +} + +void vtkDecimatePro::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Target Reduction: " << this->TargetReduction << "\n"; + os << indent << "Feature Angle: " << this->FeatureAngle << "\n"; + + os << indent << "Splitting: " << (this->Splitting ? "On\n" : "Off\n"); + os << indent << "Split Angle: " << this->SplitAngle << "\n"; + os << indent << "Pre-Split Mesh: " + << (this->PreSplitMesh ? "On\n" : "Off\n"); + + os << indent << "Degree: " << this->Degree << "\n"; + + os << indent << "Preserve Topology: " + << (this->PreserveTopology ? "On\n" : "Off\n"); + os << indent << "Maximum Error: " << this->MaximumError << "\n"; + os << indent << "Accumulate Error: " + << (this->AccumulateError ? "On\n" : "Off\n"); + os << indent << "Error is Absolute: " + << (this->ErrorIsAbsolute ? "On\n" : "Off\n"); + os << indent << "Absolute Error: " << this->AbsoluteError << "\n"; + + os << indent << "Boundary Vertex Deletion: " + << (this->BoundaryVertexDeletion ? "On\n" : "Off\n"); + + os << indent << "Inflection Point Ratio: " + << this->InflectionPointRatio << "\n"; + os << indent << "Number Of Inflection Points: " + << this->GetNumberOfInflectionPoints() << "\n"; +} diff --git a/Graphics/vtkDecimatePro.h b/Graphics/vtkDecimatePro.h new file mode 100644 index 0000000..29414df --- /dev/null +++ b/Graphics/vtkDecimatePro.h @@ -0,0 +1,381 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDecimatePro.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDecimatePro - reduce the number of triangles in a mesh +// .SECTION Description +// vtkDecimatePro is a filter to reduce the number of triangles in a triangle +// mesh, forming a good approximation to the original geometry. The input to +// vtkDecimatePro is a vtkPolyData object, and only triangles are treated. If +// you desire to decimate polygonal meshes, first triangulate the polygons +// with vtkTriangleFilter object. +// +// The implementation of vtkDecimatePro is similar to the algorithm +// originally described in "Decimation of Triangle Meshes", Proc Siggraph +// `92, with three major differences. First, this algorithm does not +// necessarily preserve the topology of the mesh. Second, it is guaranteed to +// give the a mesh reduction factor specified by the user (as long as certain +// constraints are not set - see Caveats). Third, it is set up generate +// progressive meshes, that is a stream of operations that can be easily +// transmitted and incrementally updated (see Hugues Hoppe's Siggraph '96 +// paper on progressive meshes). +// +// The algorithm proceeds as follows. Each vertex in the mesh is classified +// and inserted into a priority queue. The priority is based on the error to +// delete the vertex and retriangulate the hole. Vertices that cannot be +// deleted or triangulated (at this point in the algorithm) are +// skipped. Then, each vertex in the priority queue is processed (i.e., +// deleted followed by hole triangulation using edge collapse). This +// continues until the priority queue is empty. Next, all remaining vertices +// are processed, and the mesh is split into separate pieces along sharp +// edges or at non-manifold attachment points and reinserted into the +// priority queue. Again, the priority queue is processed until empty. If +// the desired reduction is still not achieved, the remaining vertices are +// split as necessary (in a recursive fashion) so that it is possible to +// eliminate every triangle as necessary. +// +// To use this object, at a minimum you need to specify the ivar +// TargetReduction. The algorithm is guaranteed to generate a reduced mesh +// at this level as long as the following four conditions are met: 1) +// topology modification is allowed (i.e., the ivar PreserveTopology is off); +// 2) mesh splitting is enabled (i.e., the ivar Splitting is on); 3) the +// algorithm is allowed to modify the boundary of the mesh (i.e., the ivar +// BoundaryVertexDeletion is on); and 4) the maximum allowable error (i.e., +// the ivar MaximumError) is set to VTK_DOUBLE_MAX. Other important +// parameters to adjust include the FeatureAngle and SplitAngle ivars, since +// these can impact the quality of the final mesh. Also, you can set the +// ivar AccumulateError to force incremental error update and distribution +// to surrounding vertices as each vertex is deleted. The accumulated error +// is a conservative global error bounds and decimation error, but requires +// additional memory and time to compute. + +// .SECTION Caveats +// To guarantee a given level of reduction, the ivar PreserveTopology must +// be off; the ivar Splitting is on; the ivar BoundaryVertexDeletion is on; +// and the ivar MaximumError is set to VTK_DOUBLE_MAX. +// +// If PreserveTopology is off, and SplitEdges is off; the mesh topology may +// be modified by closing holes. +// +// Once mesh splitting begins, the feature angle is set to the split angle. + +// .SECTION See Also +// vtkDecimate vtkQuadricClustering vtkQuadricDecimation + + +#ifndef __vtkDecimatePro_h +#define __vtkDecimatePro_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkCell.h" // Needed for VTK_CELL_SIZE + +class vtkDoubleArray; +class vtkPriorityQueue; + +class VTK_GRAPHICS_EXPORT vtkDecimatePro : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkDecimatePro,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create object with specified reduction of 90% and feature angle of + // 15 degrees. Edge splitting is on, defer splitting is on, and the + // split angle is 75 degrees. Topology preservation is off, delete + // boundary vertices is on, and the maximum error is set to + // VTK_DOUBLE_MAX. The inflection point ratio is 10 and the vertex + // degree is 25. Error accumulation is turned off. + static vtkDecimatePro *New(); + + // Description: + // Specify the desired reduction in the total number of polygons (e.g., if + // TargetReduction is set to 0.9, this filter will try to reduce the data set + // to 10% of its original size). Because of various constraints, this level of + // reduction may not be realized. If you want to guarantee a particular + // reduction, you must turn off PreserveTopology, turn on SplitEdges and + // BoundaryVertexDeletion, and set the MaximumError to VTK_DOUBLE_MAX (these + // ivars are initialized this way when the object is instantiated). + vtkSetClampMacro(TargetReduction,double,0.0,1.0); + vtkGetMacro(TargetReduction,double); + + // Description: + // Turn on/off whether to preserve the topology of the original mesh. If + // on, mesh splitting and hole elimination will not occur. This may limit + // the maximum reduction that may be achieved. + vtkSetMacro(PreserveTopology,int); + vtkGetMacro(PreserveTopology,int); + vtkBooleanMacro(PreserveTopology,int); + + // Description: + // Specify the mesh feature angle. This angle is used to define what + // an edge is (i.e., if the surface normal between two adjacent triangles + // is >= FeatureAngle, an edge exists). + vtkSetClampMacro(FeatureAngle,double,0.0,180.0); + vtkGetMacro(FeatureAngle,double); + + // Description: + // Turn on/off the splitting of the mesh at corners, along edges, at + // non-manifold points, or anywhere else a split is required. Turning + // splitting off will better preserve the original topology of the + // mesh, but you may not obtain the requested reduction. + vtkSetMacro(Splitting,int); + vtkGetMacro(Splitting,int); + vtkBooleanMacro(Splitting,int); + + // Description: + // Specify the mesh split angle. This angle is used to control the splitting + // of the mesh. A split line exists when the surface normals between + // two edge connected triangles are >= SplitAngle. + vtkSetClampMacro(SplitAngle,double,0.0,180.0); + vtkGetMacro(SplitAngle,double); + + // Description: + // In some cases you may wish to split the mesh prior to algorithm + // execution. This separates the mesh into semi-planar patches, which are + // disconnected from each other. This can give superior results in some + // cases. If the ivar PreSplitMesh ivar is enabled, the mesh is split with + // the specified SplitAngle. Otherwise mesh splitting is deferred as long + // as possible. + vtkSetMacro(PreSplitMesh,int); + vtkGetMacro(PreSplitMesh,int); + vtkBooleanMacro(PreSplitMesh,int); + + // Description: + // Set the largest decimation error that is allowed during the decimation + // process. This may limit the maximum reduction that may be achieved. The + // maximum error is specified as a fraction of the maximum length of + // the input data bounding box. + vtkSetClampMacro(MaximumError,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(MaximumError,double); + + // Description: + // The computed error can either be computed directly from the mesh + // or the error may be accumulated as the mesh is modified. If the error + // is accumulated, then it represents a global error bounds, and the ivar + // MaximumError becomes a global bounds on mesh error. Accumulating the + // error requires extra memory proportional to the number of vertices in + // the mesh. If AccumulateError is off, then the error is not accumulated. + vtkSetMacro(AccumulateError,int); + vtkGetMacro(AccumulateError,int); + vtkBooleanMacro(AccumulateError,int); + + // Description: + // The MaximumError is normally defined as a fraction of the dataset bounding + // diagonal. By setting ErrorIsAbsolute to 1, the error is instead defined + // as that specified by AbsoluteError. By default ErrorIsAbsolute=0. + vtkSetMacro(ErrorIsAbsolute,int); + vtkGetMacro(ErrorIsAbsolute,int); + + // Description: + // Same as MaximumError, but to be used when ErrorIsAbsolute is 1 + vtkSetClampMacro(AbsoluteError,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(AbsoluteError,double); + + // Description: + // Turn on/off the deletion of vertices on the boundary of a mesh. This + // may limit the maximum reduction that may be achieved. + vtkSetMacro(BoundaryVertexDeletion,int); + vtkGetMacro(BoundaryVertexDeletion,int); + vtkBooleanMacro(BoundaryVertexDeletion,int); + + // Description: + // If the number of triangles connected to a vertex exceeds "Degree", then + // the vertex will be split. (NOTE: the complexity of the triangulation + // algorithm is proportional to Degree^2. Setting degree small can improve + // the performance of the algorithm.) + vtkSetClampMacro(Degree,int,25,VTK_CELL_SIZE); + vtkGetMacro(Degree,int); + + // Description: + // Specify the inflection point ratio. An inflection point occurs + // when the ratio of reduction error between two iterations is greater + // than or equal to the InflectionPointRatio. + vtkSetClampMacro(InflectionPointRatio,double,1.001,VTK_DOUBLE_MAX); + vtkGetMacro(InflectionPointRatio,double); + + + // Description: + // Get the number of inflection points. Only returns a valid value after + // the filter has executed. The values in the list are mesh reduction + // values at each inflection point. Note: the first inflection point always + // occurs right before non-planar triangles are decimated (i.e., as the + // error becomes non-zero). + vtkIdType GetNumberOfInflectionPoints(); + + // Description: + // Get a list of inflection points. These are double values 0 < r <= 1.0 + // corresponding to reduction level, and there are a total of + // NumberOfInflectionPoints() values. You must provide an array (of + // the correct size) into which the inflection points are written. + void GetInflectionPoints(double *inflectionPoints); + + // Description: + // Get a list of inflection points. These are double values 0 < r <= 1.0 + // corresponding to reduction level, and there are a total of + // NumberOfInflectionPoints() values. You must provide an array (of + // the correct size) into which the inflection points are written. + // This method returns a pointer to a list of inflection points. + double *GetInflectionPoints(); + +protected: + vtkDecimatePro(); + ~vtkDecimatePro(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double TargetReduction; + double FeatureAngle; + double MaximumError; + double AbsoluteError; + int ErrorIsAbsolute; + int AccumulateError; + double SplitAngle; + int Splitting; + int PreSplitMesh; + int BoundaryVertexDeletion; + int PreserveTopology; + int Degree; + double InflectionPointRatio; + vtkDoubleArray *InflectionPoints; + + // to replace a static object + vtkIdList *Neighbors; + vtkPriorityQueue *EdgeLengths; + + void SplitMesh(); + int EvaluateVertex(vtkIdType ptId, unsigned short int numTris, + vtkIdType *tris, vtkIdType fedges[2]); + vtkIdType FindSplit(int type, vtkIdType fedges[2], vtkIdType& pt1, + vtkIdType& pt2, vtkIdList *CollapseTris); + int IsValidSplit(int index); + void SplitLoop(vtkIdType fedges[2], vtkIdType& n1, vtkIdType *l1, + vtkIdType& n2, vtkIdType *l2); + void SplitVertex(vtkIdType ptId,int type, unsigned short int numTris, + vtkIdType *tris, int insert); + int CollapseEdge(int type, vtkIdType ptId, vtkIdType collapseId, + vtkIdType pt1, vtkIdType pt2, vtkIdList *CollapseTris); + void DistributeError(double error); + + // + // Special classes for manipulating data + // + //BTX - begin tcl exclude + // + // Special structures for building loops + class LocalVertex + { + public: + vtkIdType id; + double x[3]; + double FAngle; + }; + typedef LocalVertex *LocalVertexPtr; + + class LocalTri + { + public: + vtkIdType id; + double area; + double n[3]; + vtkIdType verts[3]; + }; + typedef LocalTri *LocalTriPtr; + + class VertexArray; + friend class VertexArray; + class VertexArray { //;prevent man page generation + public: + VertexArray(const vtkIdType sz) + {this->MaxId = -1; this->Array = new LocalVertex[sz];}; + ~VertexArray() + { + if (this->Array) + { + delete [] this->Array; + } + }; + vtkIdType GetNumberOfVertices() {return this->MaxId + 1;}; + void InsertNextVertex(LocalVertex& v) + {this->MaxId++; this->Array[this->MaxId] = v;}; + LocalVertex& GetVertex(vtkIdType i) {return this->Array[i];}; + void Reset() {this->MaxId = -1;}; + + LocalVertex *Array; // pointer to data + vtkIdType MaxId; // maximum index inserted thus far + }; + + class TriArray; + friend class TriArray; + class TriArray { //;prevent man page generation + public: + TriArray(const vtkIdType sz) + {this->MaxId = -1; this->Array = new LocalTri[sz];}; + ~TriArray() + { + if (this->Array) + { + delete [] this->Array; + } + }; + vtkIdType GetNumberOfTriangles() {return this->MaxId + 1;}; + void InsertNextTriangle(LocalTri& t) + {this->MaxId++; this->Array[this->MaxId] = t;}; + LocalTri& GetTriangle(vtkIdType i) {return this->Array[i];}; + void Reset() {this->MaxId = -1;}; + + LocalTri *Array; // pointer to data + vtkIdType MaxId; // maximum index inserted thus far + }; + //ETX - end tcl exclude + // + +private: + void InitializeQueue(vtkIdType numPts); + void DeleteQueue(); + void Insert(vtkIdType id, double error= -1.0); + int Pop(double &error); + double DeleteId(vtkIdType id); + void Reset(); + + vtkPriorityQueue *Queue; + vtkDoubleArray *VertexError; + + VertexArray *V; + TriArray *T; + + // Use to be static variables used by object + vtkPolyData *Mesh; //operate on this data structure + double Pt[3]; //least squares plane point + double Normal[3]; //least squares plane normal + double LoopArea; //the total area of all triangles in a loop + double CosAngle; //Cosine of dihedral angle + double Tolerance; //Intersection tolerance + double X[3]; //coordinates of current point + int NumCollapses; //Number of times edge collapses occur + int NumMerges; //Number of times vertex merges occur + int Split; //Controls whether and when vertex splitting occurs + int VertexDegree; //Maximum number of triangles that can use a vertex + vtkIdType NumberOfRemainingTris; //Number of triangles left in the mesh + double TheSplitAngle; //Split angle + int SplitState; //State of the splitting process + double Error; //Maximum allowable surface error + +private: + vtkDecimatePro(const vtkDecimatePro&); // Not implemented. + void operator=(const vtkDecimatePro&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkDelaunay2D.cxx b/Graphics/vtkDelaunay2D.cxx new file mode 100644 index 0000000..e8645df --- /dev/null +++ b/Graphics/vtkDelaunay2D.cxx @@ -0,0 +1,1277 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDelaunay2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDelaunay2D.h" + +#include "vtkAbstractTransform.h" +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTriangle.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkDelaunay2D, "$Revision: 1.68.10.1 $"); +vtkStandardNewMacro(vtkDelaunay2D); +vtkCxxSetObjectMacro(vtkDelaunay2D,Transform,vtkAbstractTransform); + +// Construct object with Alpha = 0.0; Tolerance = 0.00001; Offset = 1.25; +// BoundingTriangulation turned off. +vtkDelaunay2D::vtkDelaunay2D() +{ + this->Alpha = 0.0; + this->Tolerance = 0.00001; + this->BoundingTriangulation = 0; + this->Offset = 1.0; + this->Transform = NULL; + this->ProjectionPlaneMode = VTK_DELAUNAY_XY_PLANE; + + // optional 2nd input + this->SetNumberOfInputPorts(2); +} + +vtkDelaunay2D::~vtkDelaunay2D() +{ + if (this->Transform) + { + this->Transform->UnRegister(this); + } +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. Old style. +void vtkDelaunay2D::SetSource(vtkPolyData *input) +{ + this->Superclass::SetInput(1, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. New style. +void vtkDelaunay2D::SetSourceConnection(vtkAlgorithmOutput *algOutput) +{ + this->Superclass::SetInputConnection(1, algOutput); +} + +vtkPolyData *vtkDelaunay2D::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +// Determine whether point x is inside of circumcircle of triangle +// defined by points (x1, x2, x3). Returns non-zero if inside circle. +// (Note that z-component is ignored.) +int vtkDelaunay2D::InCircle (double x[3], double x1[3], double x2[3], + double x3[3]) +{ + double radius2, center[2], dist2; + + radius2 = vtkTriangle::Circumcircle(x1,x2,x3,center); + + // check if inside/outside circumcircle + dist2 = (x[0]-center[0]) * (x[0]-center[0]) + + (x[1]-center[1]) * (x[1]-center[1]); + + if ( dist2 < (0.999999999999*radius2) ) + { + return 1; + } + else + { + return 0; + } +} + +#define VTK_DEL2D_TOLERANCE 1.0e-014 + +// Recursive method to locate triangle containing point. Starts with arbitrary +// triangle (tri) and "walks" towards it. Influenced by some of Guibas and +// Stolfi's work. Returns id of enclosing triangle, or -1 if no triangle +// found. Also, the array nei[3] is used to communicate info about points +// that lie on triangle edges: nei[0] is neighboring triangle id, and nei[1] +// and nei[2] are the vertices defining the edge. +vtkIdType vtkDelaunay2D::FindTriangle(double x[3], vtkIdType ptIds[3], + vtkIdType tri, double tol, + vtkIdType nei[3], vtkIdList *neighbors) +{ + int i, j, ir, ic, inside, i2, i3; + vtkIdType *pts, npts, newNei; + double p[3][3], n[2], vp[2], vx[2], dp, minProj; + + // get local triangle info + this->Mesh->GetCellPoints(tri,npts,pts); + for (i=0; i<3; i++) + { + ptIds[i] = pts[i]; + this->GetPoint(ptIds[i], p[i]); + } + + // Randomization (of find edge neighbora) avoids walking in + // circles in certain weird cases + srand(tri); + ir = rand() % 3; + // evaluate in/out of each edge + for (inside=1, minProj=0.0, ic=0; ic<3; ic++) + { + i = (ir+ic) % 3; + i2 = (i+1) % 3; + i3 = (i+2) % 3; + + // create a 2D edge normal to define a "half-space"; evaluate points (i.e., + // candiate point and other triangle vertex not on this edge). + n[0] = -(p[i2][1] - p[i][1]); + n[1] = p[i2][0] - p[i][0]; + vtkMath::Normalize2D(n); + + // compute local vectors + for (j=0; j<2; j++) + { + vp[j] = p[i3][j] - p[i][j]; + vx[j] = x[j] - p[i][j]; + } + + //check for duplicate point + vtkMath::Normalize2D(vp); + if ( vtkMath::Normalize2D(vx) <= tol ) + { + this->NumberOfDuplicatePoints++; + return -1; + } + + // see if two points are in opposite half spaces + dp = vtkMath::Dot2D(n,vx) * (vtkMath::Dot2D(n,vp) < 0 ? -1.0 : 1.0); + if ( dp < VTK_DEL2D_TOLERANCE ) + { + if ( dp < minProj ) //track edge most orthogonal to point direction + { + inside = 0; + nei[1] = ptIds[i]; + nei[2] = ptIds[i2]; + minProj = dp; + } + }//outside this edge + }//for each edge + + if ( inside ) // all edges have tested positive + { + nei[0] = (-1); + return tri; + } + + else if ( !inside && (fabs(minProj) < VTK_DEL2D_TOLERANCE) ) // on edge + { + this->Mesh->GetCellEdgeNeighbors(tri,nei[1],nei[2],neighbors); + nei[0] = neighbors->GetId(0); + return tri; + } + + else //walk towards point + { + this->Mesh->GetCellEdgeNeighbors(tri,nei[1],nei[2],neighbors); + if ( (newNei=neighbors->GetId(0)) == nei[0] ) + { + this->NumberOfDegeneracies++; + return -1; + } + else + { + nei[0] = tri; + return this->FindTriangle(x,ptIds,newNei,tol,nei,neighbors); + } + } +} + +#undef VTK_DEL2D_TOLERANCE + +// Recursive method checks whether edge is Delaunay, and if not, swaps edge. +// Continues until all edges are Delaunay. Points p1 and p2 form the edge in +// question; x is the coordinates of the inserted point; tri is the current +// triangle id. +void vtkDelaunay2D::CheckEdge(vtkIdType ptId, double x[3], vtkIdType p1, + vtkIdType p2, vtkIdType tri) +{ + int i; + vtkIdType *pts, npts, numNei, nei, p3; + double x1[3], x2[3], x3[3]; + vtkIdList *neighbors; + vtkIdType swapTri[3]; + + this->GetPoint(p1,x1); + this->GetPoint(p2,x2); + + neighbors = vtkIdList::New(); + neighbors->Allocate(2); + + this->Mesh->GetCellEdgeNeighbors(tri,p1,p2,neighbors); + numNei = neighbors->GetNumberOfIds(); + + if ( numNei > 0 ) //i.e., not a boundary edge + { + // get neighbor info including opposite point + nei = neighbors->GetId(0); + this->Mesh->GetCellPoints(nei, npts, pts); + for (i=0; i<2; i++) + { + if ( pts[i] != p1 && pts[i] != p2 ) + { + break; + } + } + p3 = pts[i]; + this->GetPoint(p3,x3); + + // see whether point is in circumcircle + if ( this->InCircle (x3, x, x1, x2) ) + {// swap diagonal + this->Mesh->RemoveReferenceToCell(p1,tri); + this->Mesh->RemoveReferenceToCell(p2,nei); + this->Mesh->ResizeCellList(ptId,1); + this->Mesh->AddReferenceToCell(ptId,nei); + this->Mesh->ResizeCellList(p3,1); + this->Mesh->AddReferenceToCell(p3,tri); + + swapTri[0] = ptId; swapTri[1] = p3; swapTri[2] = p2; + this->Mesh->ReplaceCell(tri,3,swapTri); + + swapTri[0] = ptId; swapTri[1] = p1; swapTri[2] = p3; + this->Mesh->ReplaceCell(nei,3,swapTri); + + // two new edges become suspect + this->CheckEdge(ptId, x, p3, p2, tri); + this->CheckEdge(ptId, x, p1, p3, nei); + + }//in circle + }//interior edge + + neighbors->Delete(); +} + +// 2D Delaunay triangulation. Steps are as follows: +// 1. For each point +// 2. Find triangle point is in +// 3. Create 3 triangles from each edge of triangle that point is in +// 4. Recursively evaluate Delaunay criterion for each edge neighbor +// 5. If criterion not satisfied; swap diagonal +// +int vtkDelaunay2D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *source = 0; + if (sourceInfo) + { + source = + vtkPolyData::SafeDownCast(sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + } + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPoints, i; + vtkIdType numTriangles = 0; + vtkIdType ptId, tri[4], nei[3]; + vtkIdType p1 = 0; + vtkIdType p2 = 0; + vtkPoints *inPoints; + vtkPoints *points; + vtkPoints *tPoints = NULL; + vtkCellArray *triangles; + int ncells; + vtkIdType nodes[4][3], *neiPts; + vtkIdType *triPts = 0; + vtkIdType numNeiPts; + vtkIdType npts = 0; + vtkIdType pts[3]; + vtkIdList *neighbors, *cells; + double center[3], radius, tol, x[3]; + int *triUse = NULL; + double *bounds; + + vtkDebugMacro(<<"Generating 2D Delaunay triangulation"); + + if (this->Transform && this->BoundingTriangulation) + { + vtkWarningMacro(<<"Bounding triangulation cannot be used when an input transform is specified. Output will not contain bounding triangulation."); + } + + if (this->ProjectionPlaneMode == VTK_BEST_FITTING_PLANE && this->BoundingTriangulation) + { + vtkWarningMacro(<<"Bounding triangulation cannot be used when the best fitting plane option is on. Output will not contain bounding triangulation."); + } + + // Initialize; check input + // + if ( (inPoints=input->GetPoints()) == NULL ) + { + vtkErrorMacro("<GetNumberOfPoints()) <= 2 ) + { + vtkErrorMacro("<Allocate(2); + cells = vtkIdList::New(); cells->Allocate(64); + + this->NumberOfDuplicatePoints = 0; + this->NumberOfDegeneracies = 0; + + this->Mesh = vtkPolyData::New(); + + + // If the user specified a transform, apply it to the input data. + // + // Only the input points are transformed. We do not bother + // transforming the source points (if specified). The reason is + // that only the topology of the Source is used during the constrain + // operation. The point ids in the Source topology are assumed to + // reference points in the input. So, when an input transform is + // used, only the input points are transformed. We do not bother + // with transforming the Source points since they are never + // referenced. + if (this->Transform) + { + tPoints = vtkPoints::New(); + this->Transform->TransformPoints(inPoints, tPoints); + } + else + { + // If the user asked this filter to compute the best fitting plane, + // proceed to compute the plane and generate a transform that will + // map the input points into that plane. + if(this->ProjectionPlaneMode == VTK_BEST_FITTING_PLANE) + { + this->SetTransform( this->ComputeBestFittingPlane(input) ); + tPoints = vtkPoints::New(); + this->Transform->TransformPoints(inPoints, tPoints); + } + } + + // Create initial bounding triangulation. Have to create bounding points. + // Initialize mesh structure. + // + points = vtkPoints::New(); + // This will copy doubles to doubles if the input is double. + points->SetDataTypeToDouble(); + points->SetNumberOfPoints(numPoints); + if (!this->Transform) + { + points->DeepCopy(inPoints); + } + else + { + points->DeepCopy(tPoints); + tPoints->Delete(); + tPoints = NULL; + } + + bounds = points->GetBounds(); + center[0] = (bounds[0]+bounds[1])/2.0; + center[1] = (bounds[2]+bounds[3])/2.0; + center[2] = (bounds[4]+bounds[5])/2.0; + tol = input->GetLength(); + radius = this->Offset * tol; + tol *= this->Tolerance; + + for (ptId=0; ptId<8; ptId++) + { + x[0] = center[0] + + radius*cos((double)(45.0*ptId)*vtkMath::DegreesToRadians()); + x[1] = center[1] + + radius*sin((double)(45.0*ptId)*vtkMath::DegreesToRadians()); + x[2] = center[2]; + points->InsertPoint(numPoints+ptId,x); + } + // We do this for speed accessing points + this->Points = ((vtkDoubleArray *)points->GetData())->GetPointer(0); + + triangles = vtkCellArray::New(); + triangles->Allocate(triangles->EstimateSize(2*numPoints,3)); + + //create bounding triangles (there are six) + pts[0] = numPoints; pts[1] = numPoints + 1; pts[2] = numPoints + 2; + triangles->InsertNextCell(3,pts); + pts[0] = numPoints + 2; pts[1] = numPoints + 3; pts[2] = numPoints + 4; + triangles->InsertNextCell(3,pts); + pts[0] = numPoints + 4; pts[1] = numPoints + 5; pts[2] = numPoints + 6; + triangles->InsertNextCell(3,pts); + pts[0] = numPoints + 6; pts[1] = numPoints + 7; pts[2] = numPoints + 0; + triangles->InsertNextCell(3,pts); + pts[0] = numPoints + 0; pts[1] = numPoints + 2; pts[2] = numPoints + 6; + triangles->InsertNextCell(3,pts); + pts[0] = numPoints + 2; pts[1] = numPoints + 4; pts[2] = numPoints + 6; + triangles->InsertNextCell(3,pts); + tri[0] = 0; + + this->Mesh->SetPoints(points); + this->Mesh->SetPolys(triangles); + this->Mesh->BuildLinks(); //build cell structure + + // For each point; find triangle containing point. Then evaluate three + // neighboring triangles for Delaunay criterion. Triangles that do not + // satisfy criterion have their edges swapped. This continues recursively + // until all triangles have been shown to be Delaunay. + // + for (ptId=0; ptId < numPoints; ptId++) + { + this->GetPoint(ptId,x); + nei[0] = (-1); //where we are coming from...nowhere initially + + if ( (tri[0] = this->FindTriangle(x,pts,tri[0],tol,nei,neighbors)) >= 0 ) + { + if ( nei[0] < 0 ) //in triangle + { + //delete this triangle; create three new triangles + //first triangle is replaced with one of the new ones + nodes[0][0] = ptId; nodes[0][1] = pts[0]; nodes[0][2] = pts[1]; + this->Mesh->RemoveReferenceToCell(pts[2], tri[0]); + this->Mesh->ReplaceCell(tri[0], 3, nodes[0]); + this->Mesh->ResizeCellList(ptId,1); + this->Mesh->AddReferenceToCell(ptId,tri[0]); + + //create two new triangles + nodes[1][0] = ptId; nodes[1][1] = pts[1]; nodes[1][2] = pts[2]; + tri[1] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[1]); + + nodes[2][0] = ptId; nodes[2][1] = pts[2]; nodes[2][2] = pts[0]; + tri[2] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[2]); + + // Check edge neighbors for Delaunay criterion. If not satisfied, flip + // edge diagonal. (This is done recursively.) + this->CheckEdge(ptId, x, pts[0], pts[1], tri[0]); + this->CheckEdge(ptId, x, pts[1], pts[2], tri[1]); + this->CheckEdge(ptId, x, pts[2], pts[0], tri[2]); + } + + else // on triangle edge + { + //update cell list + this->Mesh->GetCellPoints(nei[0],numNeiPts,neiPts); + for (i=0; i<3; i++) + { + if ( neiPts[i] != nei[1] && neiPts[i] != nei[2] ) + { + p1 = neiPts[i]; + } + if ( pts[i] != nei[1] && pts[i] != nei[2] ) + { + p2 = pts[i]; + } + } + this->Mesh->ResizeCellList(p1,1); + this->Mesh->ResizeCellList(p2,1); + + //replace two triangles + this->Mesh->RemoveReferenceToCell(nei[2],tri[0]); + this->Mesh->RemoveReferenceToCell(nei[2],nei[0]); + nodes[0][0] = ptId; nodes[0][1] = p2; nodes[0][2] = nei[1]; + this->Mesh->ReplaceCell(tri[0], 3, nodes[0]); + nodes[1][0] = ptId; nodes[1][1] = p1; nodes[1][2] = nei[1]; + this->Mesh->ReplaceCell(nei[0], 3, nodes[1]); + this->Mesh->ResizeCellList(ptId, 2); + this->Mesh->AddReferenceToCell(ptId,tri[0]); + this->Mesh->AddReferenceToCell(ptId,nei[0]); + + tri[1] = nei[0]; + + //create two new triangles + nodes[2][0] = ptId; nodes[2][1] = p2; nodes[2][2] = nei[2]; + tri[2] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[2]); + + nodes[3][0] = ptId; nodes[3][1] = p1; nodes[3][2] = nei[2]; + tri[3] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[3]); + + // Check edge neighbors for Delaunay criterion. + for ( i=0; i<4; i++ ) + { + this->CheckEdge (ptId, x, nodes[i][1], nodes[i][2], tri[i]); + } + } + }//if triangle found + + else + { + tri[0] = 0; //no triangle found + } + + if ( ! (ptId % 1000) ) + { + vtkDebugMacro(<<"point #" << ptId); + this->UpdateProgress ((double)ptId/numPoints); + if (this->GetAbortExecute()) + { + break; + } + } + + }//for all points + + vtkDebugMacro(<<"Triangulated " << numPoints <<" points, " + << this->NumberOfDuplicatePoints + << " of which were duplicates"); + + if ( this->NumberOfDegeneracies > 0 ) + { + vtkDebugMacro(<< this->NumberOfDegeneracies + << " degenerate triangles encountered, mesh quality suspect"); + } + + // Finish up by recovering the boundary, or deleting all triangles connected + // to the bounding triangulation points or not satisfying alpha criterion, + if ( !this->BoundingTriangulation || this->Alpha > 0.0 || source ) + { + numTriangles = this->Mesh->GetNumberOfCells(); + if ( source ) + { + triUse = this->RecoverBoundary(source); + } + else + { + triUse = new int[numTriangles]; + for (i=0; iBoundingTriangulation ) + { + for (ptId=numPoints; ptId < (numPoints+8); ptId++) + { + this->Mesh->GetPointCells(ptId, cells); + ncells = cells->GetNumberOfIds(); + for (i=0; i < ncells; i++) + { + triUse[cells->GetId(i)] = 0; //mark as deleted + } + } + } + + // If non-zero alpha value, then figure out which parts of mesh are + // contained within alpha radius. + // + if ( this->Alpha > 0.0 ) + { + double alpha2 = this->Alpha * this->Alpha; + double x1[3], x2[3], x3[3]; + double xx1[3], xx2[3], xx3[3]; + vtkIdType cellId, numNei, ap1, ap2, neighbor; + + vtkCellArray *alphaVerts = vtkCellArray::New(); + alphaVerts->Allocate(numPoints); + vtkCellArray *alphaLines = vtkCellArray::New(); + alphaLines->Allocate(numPoints); + + char *pointUse = new char[numPoints+8]; + for (ptId=0; ptId < (numPoints+8); ptId++) + { + pointUse[ptId] = 0; + } + + //traverse all triangles; evaluating Delaunay criterion + for (i=0; i < numTriangles; i++) + { + if ( triUse[i] == 1 ) + { + this->Mesh->GetCellPoints(i, npts, triPts); + + // if any point is one of the bounding points that was added + // at the beginning of the algorithm, then grab the points + // from the variable "points" (this list has the boundary + // points and the original points have been transformed by the + // input transform). if none of the points are bounding points, + // then grab the points from the variable "inPoints" so the alpha + // criterion is applied in the nontransformed space. + if (triPts[0]GetPoint(triPts[0],x1); + inPoints->GetPoint(triPts[1],x2); + inPoints->GetPoint(triPts[2],x3); + } + else + { + points->GetPoint(triPts[0],x1); + points->GetPoint(triPts[1],x2); + points->GetPoint(triPts[2],x3); + } + + // evaluate the alpha criterion in 3D + vtkTriangle::ProjectTo2D(x1, x2, x3, xx1, xx2, xx3); + if ( vtkTriangle::Circumcircle(xx1,xx2,xx3,center) > alpha2 ) + { + triUse[i] = 0; + } + else + { + for (int j=0; j<3; j++) + { + pointUse[triPts[j]] = 1; + } + } + }//if non-deleted triangle + }//for all triangles + + //traverse all edges see whether we need to create some + for (cellId=0, triangles->InitTraversal(); + triangles->GetNextCell(npts,triPts); cellId++) + { + if ( ! triUse[cellId] ) + { + for (i=0; i < npts; i++) + { + ap1 = triPts[i]; + ap2 = triPts[(i+1)%npts]; + + if (this->BoundingTriangulation || (ap1Mesh->GetCellEdgeNeighbors(cellId,ap1,ap2,neighbors); + numNei = neighbors->GetNumberOfIds(); + + if ( numNei < 1 || ((neighbor=neighbors->GetId(0)) > cellId + && !triUse[neighbor]) ) + {//see whether edge is shorter than Alpha + + // same argument as above, if one is a boundary point, get + // it using this->GetPoint() which are transformed points. if + // neither of the points are boundary points, get the from + // inPoints (untransformed points) so alpha comparison done + // untransformed space + if (ap1 < numPoints && ap2 < numPoints) + { + inPoints->GetPoint(ap1,x1); + inPoints->GetPoint(ap2,x2); + } + else + { + this->GetPoint(ap1,x1); + this->GetPoint(ap2,x2); + } + if ( (vtkMath::Distance2BetweenPoints(x1,x2)*0.25) <= alpha2 ) + { + pointUse[ap1] = 1; pointUse[ap2] = 1; + pts[0] = ap1; + pts[1] = ap2; + alphaLines->InsertNextCell(2,pts); + }//if passed test + }//test edge + }//if valid edge + }//for all edges of this triangle + }//if triangle not output + }//for all triangles + + //traverse all points, create vertices if none used + for (ptId=0; ptId<(numPoints+8); ptId++) + { + if ( !pointUse[ptId] + && (ptId < numPoints || this->BoundingTriangulation) ) + { + pts[0] = ptId; + alphaVerts->InsertNextCell(1,pts); + } + } + + // update output + delete [] pointUse; + output->SetVerts(alphaVerts); + alphaVerts->Delete(); + output->SetLines(alphaLines); + alphaLines->Delete(); + } + + // Update output; free up supporting data structures. + // + if ( this->BoundingTriangulation && !this->Transform) + { + output->SetPoints(points); + } + else + { + output->SetPoints(inPoints); + output->GetPointData()->PassData(input->GetPointData()); + } + + if ( this->Alpha <= 0.0 && this->BoundingTriangulation && !source ) + { + output->SetPolys(triangles); + } + else + { + vtkCellArray *alphaTriangles = vtkCellArray::New(); + alphaTriangles->Allocate(numTriangles); + vtkIdType *alphaTriPts; + + for (i=0; iMesh->GetCellPoints(i,npts,alphaTriPts); + alphaTriangles->InsertNextCell(3,alphaTriPts); + } + } + output->SetPolys(alphaTriangles); + alphaTriangles->Delete(); + delete [] triUse; + } + + points->Delete(); + triangles->Delete(); + this->Mesh->Delete(); + neighbors->Delete(); + cells->Delete(); + + // If the best fitting option was ON, then the current transform + // is the one that was computed internally. We must now destroy it. + if( this->ProjectionPlaneMode == VTK_BEST_FITTING_PLANE ) + { + if (this->Transform) + { + this->Transform->UnRegister(this); + this->Transform = NULL; + } + } + + output->Squeeze(); + + return 1; +} + +// Methods used to recover edges. Uses lines and polygons to determine boundary +// and inside/outside. +// +// Only the topology of the Source is used during the constrain operation. +// The point ids in the Source topology are assumed to reference points +// in the input. So, when an input transform is used, only the input points +// are transformed. We do not bother with transforming the Source points +// since they are never referenced. +int *vtkDelaunay2D::RecoverBoundary(vtkPolyData *source) +{ + vtkCellArray *lines=source->GetLines(); + vtkCellArray *polys=source->GetPolys(); + vtkIdType *pts = 0; + vtkIdType npts = 0; + vtkIdType i, p1, p2; + int *triUse; + + // Recover the edges of the mesh + for ( lines->InitTraversal(); lines->GetNextCell(npts,pts); ) + { + for (i=0; i<(npts-1); i++) + { + p1 = pts[i]; + p2 = pts[i+1]; + if ( ! this->Mesh->IsEdge(p1,p2) ) + { + this->RecoverEdge(p1, p2); + } + } + } + + // Recover the enclosed regions (polygons) of the mesh + for ( polys->InitTraversal(); polys->GetNextCell(npts,pts); ) + { + for (i=0; iMesh->IsEdge(p1,p2) ) + { + this->RecoverEdge(p1, p2); + } + } + } + + // Generate inside/outside marks on mesh + int numTriangles = this->Mesh->GetNumberOfCells(); + triUse = new int[numTriangles]; + for (i=0; iFillPolygons(polys, triUse); + + return triUse; +} + +// Method attempts to recover an edge by retriangulating mesh around the edge. +// What we do is identify a "submesh" of triangles that includes the edge to recover. +// Then we split the submesh in two with the recovered edge, and triangulate each of +// the two halves. If any part of this fails, we leave things alone. +int vtkDelaunay2D::RecoverEdge(vtkIdType p1, vtkIdType p2) +{ + vtkIdType cellId = 0; + int i, j, k; + double p1X[3], p2X[3], xyNormal[3], splitNormal[3], p21[3]; + double x1[3], x2[3], sepNormal[3], v21[3]; + int ncells, v1=0, v2=0, signX1=0, signX2, signP1, signP2; + vtkIdType *pts, *leftTris, *rightTris, npts, numRightTris, numLeftTris; + int success=0; + + vtkIdList *cells=vtkIdList::New(); cells->Allocate(64); + vtkIdList *tris=vtkIdList::New(); tris->Allocate(64); + vtkPolygon *rightPoly=vtkPolygon::New(); + vtkPolygon *leftPoly=vtkPolygon::New(); + vtkIdList *leftChain=leftPoly->GetPointIds(); + vtkIdList *rightChain=rightPoly->GetPointIds(); + vtkPoints *leftChainX=leftPoly->GetPoints(); + vtkPoints *rightChainX=rightPoly->GetPoints(); + vtkIdList *neis=vtkIdList::New(); neis->Allocate(4); + vtkIdList *rightPtIds=vtkIdList::New(); rightPtIds->Allocate(64); + vtkIdList *leftPtIds=vtkIdList::New(); leftPtIds->Allocate(64); + vtkPoints *rightTriPts=vtkPoints::New(); rightTriPts->Allocate(64); + vtkPoints *leftTriPts=vtkPoints::New(); leftTriPts->Allocate(64); + + // Compute a split plane along (p1,p2) and parallel to the z-axis. + // + this->GetPoint(p1,p1X); p1X[2] = 0.0; //split plane point + this->GetPoint(p2,p2X); p2X[2] = 0.0; //split plane point + xyNormal[0] = xyNormal[1] = 0.0; xyNormal[2] = 1.0; + for (i=0; i<3; i++ ) + { + p21[i] = p2X[i] - p1X[i]; //working in x-y plane + } + + vtkMath::Cross (p21,xyNormal,splitNormal); + if ( vtkMath::Normalize(splitNormal) == 0.0 ) + {//Usually means coincident points + goto FAILURE; + } + + // Identify a triangle connected to the point p1 containing a portion of the edge. + // + this->Mesh->GetPointCells(p1, cells); + ncells = cells->GetNumberOfIds(); + for (i=0; i < ncells; i++) + { + cellId = cells->GetId(i); + this->Mesh->GetCellPoints(cellId, npts, pts); + for (j=0; j<3; j++) + { + if ( pts[j] == p1 ) + { + break; + } + } + v1 = pts[(j+1)%3]; + v2 = pts[(j+2)%3]; + this->GetPoint(v1,x1); x1[2] = 0.0; + this->GetPoint(v2,x2); x2[2] = 0.0; + signX1 = (vtkPlane::Evaluate(splitNormal, p1X, x1) > 0.0 ? 1 : -1); + signX2 = (vtkPlane::Evaluate(splitNormal, p1X, x2) > 0.0 ? 1 : -1); + if ( signX1 != signX2 ) //points of triangle on either side of edge + { + // determine if edge separates p1 from p2 - then we've found triangle + v21[0] = x2[0] - x1[0]; //working in x-y plane + v21[1] = x2[1] - x1[1]; + v21[2] = 0.0; + + vtkMath::Cross (v21,xyNormal,sepNormal); + if ( vtkMath::Normalize(sepNormal) == 0.0 ) + { //bad mesh + goto FAILURE; + } + + signP1 = (vtkPlane::Evaluate(sepNormal, x1, p1X) > 0.0 ? 1 : -1); + signP2 = (vtkPlane::Evaluate(sepNormal, x1, p2X) > 0.0 ? 1 : -1); + if ( signP1 != signP2 ) //is a separation line + { + break; + } + } + } //for all cells + + if ( i >= ncells ) + {//something is really screwed up + goto FAILURE; + } + + // We found initial triangle; begin to track triangles containing edge. Also, + // the triangle defines the beginning of two "chains" which form a boundary of + // enclosing triangles around the edge. Create the two chains (from p1 to p2). + // (The chains are actually defining two polygons on either side of the edge.) + // + tris->InsertId(0, cellId); + rightChain->InsertId(0, p1); rightChainX->InsertPoint(0, p1X); + leftChain->InsertId(0, p1); leftChainX->InsertPoint(0, p1X); + if ( signX1 > 0 ) + { + rightChain->InsertId(1, v1); rightChainX->InsertPoint(1, x1); + leftChain->InsertId(1, v2); leftChainX->InsertPoint(1, x2); + } + else + { + leftChain->InsertId(1, v1); leftChainX->InsertPoint(1, x1); + rightChain->InsertId(1, v2); rightChainX->InsertPoint(1, x2); + } + + // Walk along triangles (edge neighbors) towards point p2. + while ( v1 != p2 ) + { + this->Mesh->GetCellEdgeNeighbors(cellId, v1, v2, neis); + if ( neis->GetNumberOfIds() != 1 ) + {//Mesh is folded or degenerate + goto FAILURE; + } + cellId = neis->GetId(0); + tris->InsertNextId(cellId); + this->Mesh->GetCellPoints(cellId, npts, pts); + for (j=0; j<3; j++) + { + if ( pts[j] != v1 && pts[j] != v2 ) + {//found point opposite current edge (v1,v2) + if ( pts[j] == p2 ) + { + v1 = p2; //this will cause the walk to stop + rightChain->InsertNextId(p2); rightChainX->InsertNextPoint(p2X); + leftChain->InsertNextId(p2); leftChainX->InsertNextPoint(p2X); + } + else + {//keep walking + this->GetPoint(pts[j], x1); x1[2] = 0.0; + if ( vtkPlane::Evaluate(splitNormal, p1X, x1) > 0.0 ) + { + v1 = pts[j]; + rightChain->InsertNextId(v1); rightChainX->InsertNextPoint(x1); + } + else + { + v2 = pts[j]; + leftChain->InsertNextId(v2); leftChainX->InsertNextPoint(x1); + } + } + break; + }//else found opposite point + }//for all points in triangle + }//while walking + + // Now that the to chains are formed, each chain forms a polygon (along with + // the edge (p1,p2)) that requires triangulation. If we can successfully + // triangulate the two polygons, we will delete the triangles contained within + // the chains and replace them with the new triangulation. + // + success = 1; + success &= (rightPoly->Triangulate(0, rightPtIds, rightTriPts)); + numRightTris = rightPtIds->GetNumberOfIds() / 3; + + success &= (leftPoly->Triangulate(0, leftPtIds, leftTriPts)); + numLeftTris = leftPtIds->GetNumberOfIds() / 3; + + if ( ! success ) + {//polygons on either side of edge are poorly shaped + goto FAILURE; + } + + // Okay, delete the old triangles and replace them with new ones. There should be + // the same number of new triangles as old ones. + leftTris = leftPtIds->GetPointer(0); + for ( j=i=0; iGetId(j); + this->Mesh->RemoveCellReference(cellId); + for (k=0; k<3; k++) + {//allocate new space for cell lists + this->Mesh->ResizeCellList(leftTris[k],1); + } + this->Mesh->ReplaceLinkedCell(cellId, 3, leftTris); + } + + rightTris = rightPtIds->GetPointer(0); + for ( i=0; iGetId(j); + this->Mesh->RemoveCellReference(cellId); + for (k=0; k<3; k++) + {//allocate new space for cell lists + this->Mesh->ResizeCellList(rightTris[k],1); + } + this->Mesh->ReplaceLinkedCell(cellId, 3, rightTris); + } + + FAILURE: + tris->Delete(); cells->Delete(); + leftPoly->Delete(); rightPoly->Delete(); neis->Delete(); + rightPtIds->Delete(); leftPtIds->Delete(); + rightTriPts->Delete(); leftTriPts->Delete(); + return success; +} + +void vtkDelaunay2D::FillPolygons(vtkCellArray *polys, int *triUse) +{ + vtkIdType p1, p2, j, kk; + int i, k; + vtkIdType *pts = 0; + vtkIdType *triPts; + vtkIdType npts = 0; + vtkIdType numPts; + static double xyNormal[3]={0.0,0.0,1.0}; + double negDir[3], x21[3], x1[3], x2[3], x[3]; + vtkIdList *neis=vtkIdList::New(); + vtkIdType cellId, numNeis; + vtkIdList *currentFront = vtkIdList::New(), *tmpFront; + vtkIdList *nextFront = vtkIdList::New(); + vtkIdType numCellsInFront, neiId; + vtkIdType numTriangles=this->Mesh->GetNumberOfCells(); + + // Loop over edges of polygon, marking triangles on "outside" of polygon as outside. + // Then perform a fill. + for ( polys->InitTraversal(); polys->GetNextCell(npts,pts); ) + { + currentFront->Reset(); + for (i=0; iMesh->IsEdge(p1,p2) ) + { + vtkWarningMacro(<<"Edge not recovered, polygon fill suspect"); + } + else //Mark the "outside" triangles + { + neis->Reset(); + this->GetPoint(p1,x1); + this->GetPoint(p2,x2); + for (j=0; j<3; j++) + { + x21[j] = x2[j] - x1[j]; + } + vtkMath::Cross (x21,xyNormal,negDir); + this->Mesh->GetCellEdgeNeighbors(-1, p1, p2, neis); //get both triangles + numNeis = neis->GetNumberOfIds(); + for (j=0; jGetId(j); + this->Mesh->GetCellPoints(cellId, numPts, triPts); + for (k=0; k<3; k++) + { + if ( triPts[k] != p1 && triPts[k] != p2 ) + { + break; + } + } + this->GetPoint(triPts[k],x); x[2] = 0.0; + if ( vtkPlane::Evaluate(negDir, x1, x) > 0.0 ) + { + triUse[cellId] = 0; + currentFront->InsertNextId(cellId); + } + else + { + triUse[cellId] = -1; + } + } + }//edge was recovered + }//for all edges in polygon + + // Okay, now perform a fill operation (filling "outside" values). + // + while ( (numCellsInFront = currentFront->GetNumberOfIds()) > 0 ) + { + for (j=0; j < numCellsInFront; j++) + { + cellId = currentFront->GetId(j); + + this->Mesh->GetCellPoints(cellId, numPts, triPts); + for (k=0; k<3; k++) + { + p1 = triPts[k]; + p2 = triPts[(k+1)%3]; + + this->Mesh->GetCellEdgeNeighbors(cellId, p1, p2, neis); + numNeis = neis->GetNumberOfIds(); + for (kk=0; kkGetId(kk); + if ( triUse[neiId] == 1 ) //0 is what we're filling with + { + triUse[neiId] = 0; + nextFront->InsertNextId(neiId); + } + }//mark all neigbors + }//for all edges of cell + } //all cells in front + + tmpFront = currentFront; + currentFront = nextFront; + nextFront = tmpFront; + nextFront->Reset(); + } //while still advancing + + }//for all polygons + + //convert all unvisited to inside + for (i=0; iDelete(); + nextFront->Delete(); + neis->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkDelaunay2D::FillInputPortInformation(int port, vtkInformation* info) +{ + if (port == 0) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPointSet"); + } + else if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + return 1; +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform * vtkDelaunay2D::ComputeBestFittingPlane( + vtkPointSet *input) +{ + vtkIdType numPts=input->GetNumberOfPoints(); + double m[9], v[3], x[3]; + vtkIdType ptId; + int i; + double *c1, *c2, *c3, det; + double normal[3]; + double origin[3]; + + const double tolerance = 1.0e-03; + + // This code was taken from the vtkTextureMapToPlane class + // and slightly modified. + // + for (i=0; i<3; i++) + { + normal[i] = 0.0; + } + + // Compute least squares approximation. + // Compute 3x3 least squares matrix + v[0] = v[1] = v[2] = 0.0; + for (i=0; i<9; i++) + { + m[i] = 0.0; + } + + for (ptId=0; ptId < numPts; ptId++) + { + input->GetPoint(ptId, x); + + v[0] += x[0]*x[2]; + v[1] += x[1]*x[2]; + v[2] += x[2]; + + m[0] += x[0]*x[0]; + m[1] += x[0]*x[1]; + m[2] += x[0]; + + m[3] += x[0]*x[1]; + m[4] += x[1]*x[1]; + m[5] += x[1]; + + m[6] += x[0]; + m[7] += x[1]; + } + m[8] = numPts; + + origin[0] = m[2] / numPts; + origin[1] = m[5] / numPts; + origin[2] = v[2] / numPts; + + // Solve linear system using Kramers rule + // + c1 = m; c2 = m+3; c3 = m+6; + if ( (det = vtkMath::Determinant3x3 (c1,c2,c3)) > tolerance ) + { + normal[0] = vtkMath::Determinant3x3 (v,c2,c3) / det; + normal[1] = vtkMath::Determinant3x3 (c1,v,c3) / det; + normal[2] = -1.0; // because of the formulation + } + + vtkTransform * transform = vtkTransform::New(); + + // Set the new Z axis as the normal to the best fitting + // plane. + double zaxis[3]; + zaxis[0] = 0; + zaxis[1] = 0; + zaxis[2] = 1; + + double rotationAxis[3]; + + vtkMath::Normalize(normal); + vtkMath::Cross(normal,zaxis,rotationAxis); + vtkMath::Normalize(rotationAxis); + + const double rotationAngle = + 180.0*acos(vtkMath::Dot(zaxis,normal))/3.1415926; + + transform->PreMultiply(); + transform->Identity(); + + transform->RotateWXYZ(rotationAngle, + rotationAxis[0], rotationAxis[1], rotationAxis[2]); + + // Set the center of mass as the origin of coordinates + transform->Translate( -origin[0], -origin[1], -origin[2] ); + + return transform; +} + +//---------------------------------------------------------------------------- +void vtkDelaunay2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Alpha: " << this->Alpha << "\n"; + os << indent << "ProjectionPlaneMode: " + << ((this->ProjectionPlaneMode == VTK_BEST_FITTING_PLANE)? "Best Fitting Plane" : "XY Plane") << "\n"; + os << indent << "Transform: " << (this->Transform ? "specified" : "none") << "\n"; + os << indent << "Tolerance: " << this->Tolerance << "\n"; + os << indent << "Offset: " << this->Offset << "\n"; + os << indent << "Bounding Triangulation: " + << (this->BoundingTriangulation ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkDelaunay2D.h b/Graphics/vtkDelaunay2D.h new file mode 100644 index 0000000..b7db1dd --- /dev/null +++ b/Graphics/vtkDelaunay2D.h @@ -0,0 +1,269 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDelaunay2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDelaunay2D - create 2D Delaunay triangulation of input points +// .SECTION Description +// vtkDelaunay2D is a filter that constructs a 2D Delaunay triangulation from +// a list of input points. These points may be represented by any dataset of +// type vtkPointSet and subclasses. The output of the filter is a polygonal +// dataset. Usually the output is a triangle mesh, but if a non-zero alpha +// distance value is specified (called the "alpha" value), then only +// triangles, edges, and vertices lying within the alpha radius are +// output. In other words, non-zero alpha values may result in arbitrary +// combinations of triangles, lines, and vertices. (The notion of alpha value +// is derived from Edelsbrunner's work on "alpha shapes".) Also, it is +// possible to generate "constrained triangulations" using this filter. +// A constrained triangulation is one where edges and loops (i.e., polygons) +// can be defined and the triangulation will preserve them (read on for +// more information). +// +// The 2D Delaunay triangulation is defined as the triangulation that +// satisfies the Delaunay criterion for n-dimensional simplexes (in this case +// n=2 and the simplexes are triangles). This criterion states that a +// circumsphere of each simplex in a triangulation contains only the n+1 +// defining points of the simplex. (See "The Visualization Toolkit" text +// for more information.) In two dimensions, this translates into an optimal +// triangulation. That is, the maximum interior angle of any triangle is less +// than or equal to that of any possible triangulation. +// +// Delaunay triangulations are used to build topological structures +// from unorganized (or unstructured) points. The input to this filter +// is a list of points specified in 3D, even though the triangulation +// is 2D. Thus the triangulation is constructed in the x-y plane, and +// the z coordinate is ignored (although carried through to the +// output). If you desire to triangulate in a different plane, you +// can use the vtkTransformFilter to transform the points into and +// out of the x-y plane or you can specify a transform to the Delaunay2D +// directly. In the latter case, the input points are transformed, the +// transformed points are triangulated, and the output will use the +// triangulated topology for the original (non-transformed) points. This +// avoids transforming the data back as would be required when using the +// vtkTransformFilter method. Specifying a transform directly also allows +// any transform to be used: rigid, non-rigid, non-invertible, etc. +// +// If an input transform is used, then alpha values are applied (for the +// most part) in the original data space. The exception is when +// BoundingTriangulation is on. In this case, alpha values are applied in +// the original data space unless a cell uses a bounding vertex. +// +// The Delaunay triangulation can be numerically sensitive in some cases. To +// prevent problems, try to avoid injecting points that will result in +// triangles with bad aspect ratios (1000:1 or greater). In practice this +// means inserting points that are "widely dispersed", and enables smooth +// transition of triangle sizes throughout the mesh. (You may even want to +// add extra points to create a better point distribution.) If numerical +// problems are present, you will see a warning message to this effect at +// the end of the triangulation process. +// +// To create constrained meshes, you must define an additional +// input. This input is an instance of vtkPolyData which contains +// lines, polylines, and/or polygons that define constrained edges and +// loops. Only the topology of (lines and polygons) from this second +// input are used. The topology is assumed to reference points in the +// input point set (the one to be triangulated). In other words, the +// lines and polygons use point ids from the first input point +// set. Lines and polylines found in the input will be mesh edges in +// the output. Polygons define a loop with inside and outside +// regions. The inside of the polygon is determined by using the +// right-hand-rule, i.e., looking down the z-axis a polygon should be +// ordered counter-clockwise. Holes in a polygon should be ordered +// clockwise. If you choose to create a constrained triangulation, the +// final mesh may not satisfy the Delaunay criterion. (Noted: the +// lines/polygon edges must not intersect when projected onto the 2D +// plane. It may not be possible to recover all edges due to not +// enough points in the triangulation, or poorly defined edges +// (coincident or excessively long). The form of the lines or +// polygons is a list of point ids that correspond to the input point +// ids used to generate the triangulation.) +// +// If an input transform is used, constraints are defined in the +// "transformed" space. So when the right hand rule is used for a +// polygon constraint, that operation is applied using the transformed +// points. Since the input transform can be any transformation (rigid +// or non-rigid), care must be taken in constructing constraints when +// an input transform is used. + +// .SECTION Caveats +// Points arranged on a regular lattice (termed degenerate cases) can be +// triangulated in more than one way (at least according to the Delaunay +// criterion). The choice of triangulation (as implemented by +// this algorithm) depends on the order of the input points. The first three +// points will form a triangle; other degenerate points will not break +// this triangle. +// +// Points that are coincident (or nearly so) may be discarded by the algorithm. +// This is because the Delaunay triangulation requires unique input points. +// You can control the definition of coincidence with the "Tolerance" instance +// variable. +// +// The output of the Delaunay triangulation is supposedly a convex hull. In +// certain cases this implementation may not generate the convex hull. This +// behavior can be controlled by the Offset instance variable. Offset is a +// multiplier used to control the size of the initial triangulation. The +// larger the offset value, the more likely you will generate a convex hull; +// but the more likely you are to see numerical problems. + +// .SECTION See Also +// vtkDelaunay3D vtkTransformFilter vtkGaussianSplatter + +#ifndef __vtkDelaunay2D_h +#define __vtkDelaunay2D_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkAbstractTransform; +class vtkCellArray; +class vtkIdList; +class vtkPointSet; + +#define VTK_DELAUNAY_XY_PLANE 0 +#define VTK_SET_TRANSFORM_PLANE 1 +#define VTK_BEST_FITTING_PLANE 2 + +class VTK_GRAPHICS_EXPORT vtkDelaunay2D : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkDelaunay2D,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with Alpha = 0.0; Tolerance = 0.001; Offset = 1.25; + // BoundingTriangulation turned off. + static vtkDelaunay2D *New(); + + // Description: + // Specify the source object used to specify constrained edges and loops. + // (This is optional.) If set, and lines/polygons are defined, a constrained + // triangulation is created. The lines/polygons are assumed to reference + // points in the input point set (i.e. point ids are identical in the + // input and source). + // Old style. See SetSourceConnection. + void SetSource(vtkPolyData *); + + // Description: + // Specify the source object used to specify constrained edges and loops. + // (This is optional.) If set, and lines/polygons are defined, a constrained + // triangulation is created. The lines/polygons are assumed to reference + // points in the input point set (i.e. point ids are identical in the + // input and source). + // New style. This method is equivalent to SetInputConnection(1, algOutput). + void SetSourceConnection(vtkAlgorithmOutput *algOutput); + + // Description: + // Get a pointer to the source object. + vtkPolyData *GetSource(); + + // Description: + // Specify alpha (or distance) value to control output of this filter. + // For a non-zero alpha value, only edges or triangles contained within + // a sphere centered at mesh vertices will be output. Otherwise, only + // triangles will be output. + vtkSetClampMacro(Alpha,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Alpha,double); + + // Description: + // Specify a tolerance to control discarding of closely spaced points. + // This tolerance is specified as a fraction of the diagonal length of + // the bounding box of the points. + vtkSetClampMacro(Tolerance,double,0.0,1.0); + vtkGetMacro(Tolerance,double); + + // Description: + // Specify a multiplier to control the size of the initial, bounding + // Delaunay triangulation. + vtkSetClampMacro(Offset,double,0.75,VTK_DOUBLE_MAX); + vtkGetMacro(Offset,double); + + // Description: + // Boolean controls whether bounding triangulation points (and associated + // triangles) are included in the output. (These are introduced as an + // initial triangulation to begin the triangulation process. This feature + // is nice for debugging output.) + vtkSetMacro(BoundingTriangulation,int); + vtkGetMacro(BoundingTriangulation,int); + vtkBooleanMacro(BoundingTriangulation,int); + + // Description: + // Set / get the transform which is applied to points to generate a + // 2D problem. This maps a 3D dataset into a 2D dataset where + // triangulation can be done on the XY plane. The points are + // transformed and triangulated. The topology of triangulated + // points is used as the output topology. The output points are the + // original (untransformed) points. The transform can be any + // subclass of vtkAbstractTransform (thus it does not need to be a + // linear or invertible transform). + virtual void SetTransform(vtkAbstractTransform*); + vtkGetObjectMacro(Transform, vtkAbstractTransform); + + // Description: + // Define + vtkSetClampMacro(ProjectionPlaneMode,int, + VTK_DELAUNAY_XY_PLANE,VTK_BEST_FITTING_PLANE); + vtkGetMacro(ProjectionPlaneMode,int); + +protected: + vtkDelaunay2D(); + ~vtkDelaunay2D(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkAbstractTransform * ComputeBestFittingPlane(vtkPointSet *input); + + double Alpha; + double Tolerance; + int BoundingTriangulation; + double Offset; + + vtkAbstractTransform *Transform; + + int ProjectionPlaneMode; //selects the plane in 3D where the Delaunay triangulation will be computed. + +private: + vtkPolyData *Mesh; //the created mesh + double *Points; //the raw points in double precision + void SetPoint(vtkIdType id, double *x) + {vtkIdType idx=3*id; + this->Points[idx] = x[0]; + this->Points[idx+1] = x[1]; + this->Points[idx+2] = x[2]; + } + + void GetPoint(vtkIdType id, double x[3]) + {double *ptr = this->Points + 3*id; + x[0] = *ptr++; + x[1] = *ptr++; + x[2] = *ptr; + } + + int NumberOfDuplicatePoints; + int NumberOfDegeneracies; + + int *RecoverBoundary(vtkPolyData *source); + int RecoverEdge(vtkIdType p1, vtkIdType p2); + void FillPolygons(vtkCellArray *polys, int *triUse); + + int InCircle (double x[3], double x1[3], double x2[3], double x3[3]); + vtkIdType FindTriangle(double x[3], vtkIdType ptIds[3], vtkIdType tri, + double tol, vtkIdType nei[3], vtkIdList *neighbors); + void CheckEdge(vtkIdType ptId, double x[3], vtkIdType p1, vtkIdType p2, + vtkIdType tri); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkDelaunay2D(const vtkDelaunay2D&); // Not implemented. + void operator=(const vtkDelaunay2D&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkDelaunay3D.cxx b/Graphics/vtkDelaunay3D.cxx new file mode 100644 index 0000000..9503295 --- /dev/null +++ b/Graphics/vtkDelaunay3D.cxx @@ -0,0 +1,1058 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDelaunay3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDelaunay3D.h" + +#include "vtkEdgeTable.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPolyData.h" +#include "vtkTetra.h" +#include "vtkTriangle.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkDelaunay3D, "$Revision: 1.73 $"); +vtkStandardNewMacro(vtkDelaunay3D); + +// Structure used to represent sphere around tetrahedron +// +typedef struct _vtkDelaunayTetra +{ + double r2; + double center[3]; +} +vtkDelaunayTetra; + +// Special classes for manipulating tetra array +// +class vtkTetraArray { //;prevent man page generation +public: + vtkTetraArray(vtkIdType sz, vtkIdType extend); + ~vtkTetraArray() + { + if (this->Array) + { + delete [] this->Array; + } + }; + vtkDelaunayTetra *GetTetra(vtkIdType tetraId) + { return this->Array + tetraId;}; + void InsertTetra(vtkIdType tetraId, double r2, double center[3]); + vtkDelaunayTetra *Resize(vtkIdType sz); //reallocates data + +protected: + vtkDelaunayTetra *Array; // pointer to data + vtkIdType MaxId; // maximum index inserted thus far + vtkIdType Size; // allocated size of data + vtkIdType Extend; // grow array by this amount +}; + +vtkTetraArray::vtkTetraArray(vtkIdType sz, vtkIdType extend) +{ + this->MaxId = -1; + this->Array = new vtkDelaunayTetra[sz]; + this->Size = sz; + this->Extend = extend; +} + +void vtkTetraArray::InsertTetra(vtkIdType id, double r2, double center[3]) +{ + if ( id >= this->Size ) + { + this->Resize(id+1); + } + this->Array[id].r2 = r2; + this->Array[id].center[0] = center[0]; + this->Array[id].center[1] = center[1]; + this->Array[id].center[2] = center[2]; + if ( id > this->MaxId ) + { + this->MaxId = id; + } +} + +vtkDelaunayTetra *vtkTetraArray::Resize(vtkIdType sz) +{ + vtkDelaunayTetra *newArray; + vtkIdType newSize; + + if ( sz > this->Size ) + { + newSize = this->Size + this->Extend*(((sz-this->Size)/this->Extend)+1); + } + else if (sz == this->Size) + { + return this->Array; + } + else + { + newSize = sz; + } + + if ( (newArray = new vtkDelaunayTetra[newSize]) == NULL ) + { + vtkGenericWarningMacro(<< "Cannot allocate memory\n"); + return 0; + } + + if (this->Array) + { + memcpy(newArray, this->Array, + (sz < this->Size ? sz : this->Size) * sizeof(vtkDelaunayTetra)); + delete [] this->Array; + } + + this->Size = newSize; + this->Array = newArray; + + return this->Array; +} + + +// vtkDelaunay3D methods +// + +// Construct object with Alpha = 0.0; Tolerance = 0.001; Offset = 2.5; +// BoundingTriangulation turned off. +vtkDelaunay3D::vtkDelaunay3D() +{ + this->Alpha = 0.0; + this->Tolerance = 0.001; + this->BoundingTriangulation = 0; + this->Offset = 2.5; + this->Locator = NULL; + this->TetraArray = NULL; + + // added for performance + this->Tetras = vtkIdList::New(); + this->Tetras->Allocate(5); + this->Faces = vtkIdList::New(); + this->Faces->Allocate(15); + this->CheckedTetras = vtkIdList::New(); + this->CheckedTetras->Allocate(25); +} + +vtkDelaunay3D::~vtkDelaunay3D() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( this->TetraArray ) + { + delete this->TetraArray; + } + this->Tetras->Delete(); + this->Faces->Delete(); + this->CheckedTetras->Delete(); +} +// special method for performance +static int GetTetraFaceNeighbor(vtkUnstructuredGrid *Mesh, vtkIdType tetraId, + vtkIdType p1, vtkIdType p2, vtkIdType p3, + vtkIdType& nei); + +// Find all faces that enclose a point. (Enclosure means not satifying +// Delaunay criterion.) This method works in two distinct parts. First, the +// tetrahedra containing the point are found (there may be more than one if +// the point falls on an edge or face). Next, face neighbors of these points +// are visited to see whether they satisfy the Delaunay criterion. Face +// neighbors are visited repeatedly until no more tetrahedron are found. +// Enclosing tetras are returned in the tetras list; the enclosing faces +// are returned in the faces list. +vtkIdType vtkDelaunay3D::FindEnclosingFaces(double x[3], + vtkUnstructuredGrid *Mesh, + vtkIdList *tetras, + vtkIdList *faces, + vtkPointLocator *locator) +{ + vtkIdType tetraId, i, numTetras; + int j, insertFace; + vtkIdType p1, p2, p3, nei; + int hasNei; + vtkIdType *tetraPts, npts; + vtkIdType closestPoint; + double xd[3]; xd[0]=x[0]; xd[1]=x[1]; xd[2]=x[2]; + + // Start off by finding closest point and tetras that use the point. + // This will serve as the starting point to determine an enclosing + // tetrahedron. (We just need a starting point + if ( locator->IsInsertedPoint(x) >= 0 ) + { + this->NumberOfDuplicatePoints++; + return 0; + } + + closestPoint = locator->FindClosestInsertedPoint(x); + vtkCellLinks *links = Mesh->GetCellLinks(); + int numCells = links->GetNcells(closestPoint); + vtkIdType *cells = links->GetCells(closestPoint); + if ( numCells <= 0 ) //shouldn't happen + { + this->NumberOfDegeneracies++; + return 0; + } + else + { + tetraId = cells[0]; + } + + // Okay, walk towards the containing tetrahedron + tetraId = this->FindTetra(Mesh,xd,tetraId,0); + if ( tetraId < 0 ) + { + this->NumberOfDegeneracies++; + return 0; + } + + // Initialize the list of tetras who contain the point according + // to the Delaunay criterion. + tetras->InsertNextId(tetraId); //means that point is in this tetra + + // Okay, check neighbors for Delaunay criterion. Purpose is to find + // list of enclosing faces and deleted tetras. + numTetras = tetras->GetNumberOfIds(); + for (this->CheckedTetras->Reset(), i=0; i < numTetras; i++) + { + this->CheckedTetras->InsertId(i,tetras->GetId(i)); + } + + p1 = 0; + p2 = 0; + p3 = 0; + for (i=0; i < numTetras; i++) + { + tetraId = tetras->GetId(i); + Mesh->GetCellPoints(tetraId,npts,tetraPts); + for (j=0; j < 4; j++) + { + insertFace = 0; + // Make sure to arrange these points so that they're in + // counterclockwise order when viewed from the center of the + // cell + switch (j) + { + case 0: // face 0: points 0, 1, 2 + p1 = tetraPts[0]; p2 = tetraPts[1]; p3 = tetraPts[2]; break; + case 1: // face 1: points 1, 2, 3 (must flip order!) + p1 = tetraPts[1]; p2 = tetraPts[3]; p3 = tetraPts[2]; break; + case 2: // face 2: points 2, 3, 0 + p1 = tetraPts[2]; p2 = tetraPts[3]; p3 = tetraPts[0]; break; + case 3: // face 3: points 3, 0, 1 (must flip order!) + p1 = tetraPts[3]; p2 = tetraPts[1]; p3 = tetraPts[0]; break; + } + + hasNei = GetTetraFaceNeighbor(Mesh, tetraId, p1, p2, p3, nei); + + //if a boundary face or an enclosing face + if ( !hasNei ) //a boundary face + { + insertFace = 1; + } + else + { + if ( this->CheckedTetras->IsId(nei) == -1 ) //if not checked + { + if ( this->InSphere(xd,nei) ) //if point inside circumsphere + { + numTetras++; + tetras->InsertNextId(nei); //delete this tetra + } + else + { + insertFace = 1; //this is a boundary face + } + this->CheckedTetras->InsertNextId(nei); //okay, we've checked it + } + else + { + if ( tetras->IsId(nei) == -1 ) //if checked but not deleted + { + insertFace = 1; //a boundary face + } + } + } + + if ( insertFace ) + { + faces->InsertNextId(p1); + faces->InsertNextId(p2); + faces->InsertNextId(p3); + } + + }//for each tetra face + }//for all deleted tetras + + // Okay, let's delete the tetras and prepare the data structure + for (i=0; i < tetras->GetNumberOfIds(); i++) + { + tetraId = tetras->GetId(i); + Mesh->GetCellPoints(tetraId, npts, tetraPts); + for (j=0; j<4; j++) + { + this->References[tetraPts[j]]--; + Mesh->RemoveReferenceToCell(tetraPts[j],tetraId); + } + } + + return (faces->GetNumberOfIds() / 3); +} + +int vtkDelaunay3D::FindTetra(vtkUnstructuredGrid *Mesh, double x[3], + vtkIdType tetraId, int depth) +{ + double p[4][3]; + double b[4]; + vtkTetra *tetra; + int neg = 0; + int j, numNeg; + double negValue; + + // prevent aimless wandering and death by recursion + if ( depth > 200 ) + { + return -1; + } + + tetra = (vtkTetra *)Mesh->GetCell(tetraId); + for ( j=0; j < 4; j++ ) //load the points + { + tetra->Points->GetPoint(j,p[j]); + } + + vtkTetra::BarycentricCoords(x, p[0], p[1], p[2], p[3], b); + + // find the most negative face + for ( negValue=VTK_DOUBLE_MAX, numNeg=j=0; j<4; j++ ) + { + if ( b[j] < 0.0 ) + { + numNeg++; + if ( b[j] < negValue ) + { + negValue = b[j]; + neg = j; + } + } + } + + // if no negatives, then inside this tetra + if ( numNeg <= 0 ) + { + return tetraId; + } + + // okay, march towards the most negative direction + int p1 = 0, p2 = 0, p3 = 0; + switch (neg) + { + case 0: + p1 = tetra->PointIds->GetId(1); + p2 = tetra->PointIds->GetId(2); + p3 = tetra->PointIds->GetId(3); + break; + case 1: + p1 = tetra->PointIds->GetId(0); + p2 = tetra->PointIds->GetId(2); + p3 = tetra->PointIds->GetId(3); + break; + case 2: + p1 = tetra->PointIds->GetId(0); + p2 = tetra->PointIds->GetId(1); + p3 = tetra->PointIds->GetId(3); + break; + case 3: + p1 = tetra->PointIds->GetId(0); + p2 = tetra->PointIds->GetId(1); + p3 = tetra->PointIds->GetId(2); + break; + } + vtkIdType nei; + if ( GetTetraFaceNeighbor(Mesh, tetraId, p1, p2, p3, nei) ) + { + return this->FindTetra(Mesh, x, nei, ++depth); + } + else + { + return -1; + } +} + + +// 3D Delaunay triangulation. Steps are as follows: +// 1. For each point +// 2. Find tetrahedron point is in +// 3. Repeatedly visit face neighbors and evaluate Delaunay criterion +// 4. Gather list of faces forming boundary of insertion polyhedron +// 5. Make sure that faces/point combination forms good tetrahedron +// 6. Create tetrahedron from each point/face combination +// +int vtkDelaunay3D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPoints, numTetras, i; + vtkIdType ptId; + vtkPoints *inPoints; + vtkPoints *points; + vtkUnstructuredGrid *Mesh; + double x[3]; + vtkIdType npts; + vtkIdType *tetraPts, pts[4]; + vtkIdList *cells, *holeTetras; + double center[3], tol; + char *tetraUse; + + vtkDebugMacro(<<"Generating 3D Delaunay triangulation"); + + // Initialize; check input + // + if ( (inPoints=input->GetPoints()) == NULL ) + { + vtkErrorMacro("<Allocate(64); + holeTetras = vtkIdList::New(); + holeTetras->Allocate(12); + + numPoints = inPoints->GetNumberOfPoints(); + + // Create initial bounding triangulation. Have to create bounding points. + // Initialize mesh structure. + input->GetCenter(center); + tol = input->GetLength(); + Mesh = this->InitPointInsertion(center, this->Offset*tol, + numPoints, points); + + // Insert each point into triangulation. Points lying "inside" + // of tetra cause tetra to be deleted, leaving a void with bounding + // faces. Combination of point and each face is used to form new + // tetrahedra. + for (ptId=0; ptId < numPoints; ptId++) + { + inPoints->GetPoint(ptId,x); + + this->InsertPoint(Mesh, points, ptId, x, holeTetras); + + if ( ! (ptId % 250) ) + { + vtkDebugMacro(<<"point #" << ptId); + this->UpdateProgress ((double)ptId/numPoints); + if (this->GetAbortExecute()) + { + break; + } + } + + }//for all points + + this->EndPointInsertion(); + + vtkDebugMacro(<<"Triangulated " << numPoints <<" points, " + << this->NumberOfDuplicatePoints << " of which were duplicates"); + + if ( this->NumberOfDegeneracies > 0 ) + { + vtkWarningMacro(<< this->NumberOfDegeneracies + << " degenerate triangles encountered, mesh quality suspect"); + } + + // Send appropriate portions of triangulation to output + // + output->Allocate(5*numPoints); + numTetras = Mesh->GetNumberOfCells(); + tetraUse = new char[numTetras]; + + for (i=0; i < numTetras; i++) + { + tetraUse[i] = 2; //mark as non-deleted + } + for (i=0; i < holeTetras->GetNumberOfIds(); i++) + { + tetraUse[holeTetras->GetId(i)] = 0; //mark as deleted + } + + //if boundary triangulation not desired, delete tetras connected to + // boundary points + if ( ! this->BoundingTriangulation ) + { + for (ptId=numPoints; ptId < (numPoints+6); ptId++) + { + Mesh->GetPointCells(ptId, cells); + for (i=0; i < cells->GetNumberOfIds(); i++) + { + tetraUse[cells->GetId(i)] = 0; //mark as deleted + } + } + } + + // If non-zero alpha value, then figure out which parts of mesh are + // contained within alpha radius. + // + if ( this->Alpha > 0.0 ) + { + double alpha2 = this->Alpha * this->Alpha; + vtkEdgeTable *edges; + char *pointUse = new char[numPoints+6]; + vtkIdType p1, p2, p3, nei; + int hasNei, j, k; + double x1[3], x2[3], x3[3]; + vtkDelaunayTetra *tetra; + static int edge[6][2] = {{0,1},{1,2},{2,0},{0,3},{1,3},{2,3}}; + + edges = vtkEdgeTable::New(); + edges->InitEdgeInsertion(numPoints+6); + + for (ptId=0; ptId < (numPoints+6); ptId++) + { + pointUse[ptId] = 0; + } + + //traverse all tetras, checking against alpha radius + for (i=0; i < numTetras; i++) + { + //check tetras + if ( tetraUse[i] == 2 ) //if not deleted + { + tetra = this->TetraArray->GetTetra(i); + if ( tetra->r2 > alpha2 ) + { + tetraUse[i] = 1; //mark as visited and discarded + } + else + { + Mesh->GetCellPoints(i, npts, tetraPts); + for (j=0; j<4; j++) + { + pointUse[tetraPts[j]] = 1; + } + for (j=0; j<6; j++) + { + p1 = tetraPts[edge[j][0]]; + p2 = tetraPts[edge[j][1]]; + if ( edges->IsEdge(p1,p2) == -1 ) + { + edges->InsertEdge(p1,p2); + } + } + } + }//if non-deleted tetra + }//for all tetras + + //traverse tetras again, this time examining faces + //used tetras have already been output, so we look at those that haven't + for (i=0; i < numTetras; i++) + { + if ( tetraUse[i] == 1 ) //if visited and discarded + { + Mesh->GetCellPoints(i, npts, tetraPts); + for (j=0; j < 4; j++) + { + p1 = tetraPts[j]; + p2 = tetraPts[(j+1)%4]; + p3 = tetraPts[(j+2)%4]; + + //make sure face is okay to create + if ( this->BoundingTriangulation || + (p1 < numPoints && p2 < numPoints && p3 < numPoints) ) + { + hasNei = GetTetraFaceNeighbor(Mesh, i, p1,p2,p3, nei); + + if ( !hasNei || ( nei > i && tetraUse[nei]!=2 ) ) + { + double dx1[3], dx2[3], dx3[3], dv1[3], dv2[3], dv3[3], dcenter[3]; + points->GetPoint(p1,x1); dx1[0]=x1[0]; dx1[1]=x1[1]; dx1[2]=x1[2]; + points->GetPoint(p2,x2); dx2[0]=x2[0]; dx2[1]=x2[1]; dx2[2]=x2[2]; + points->GetPoint(p3,x3); dx3[0]=x3[0]; dx3[1]=x3[1]; dx3[2]=x3[2]; + vtkTriangle::ProjectTo2D(dx1,dx2,dx3,dv1,dv2,dv3); + if ( vtkTriangle::Circumcircle(dv1,dv2,dv3,dcenter) <= alpha2 ) + { + pts[0] = p1; + pts[1] = p2; + pts[2] = p3; + output->InsertNextCell(VTK_TRIANGLE,3,pts); + if ( edges->IsEdge(p1,p2) == -1 ) + { + edges->InsertEdge(p1,p2); + } + if ( edges->IsEdge(p2,p3) == -1 ) + { + edges->InsertEdge(p2,p3); + } + if ( edges->IsEdge(p3,p1) == -1 ) + { + edges->InsertEdge(p3,p1); + } + for (k=0; k<3; k++) + { + pointUse[pts[k]] = 1; + } + } + }//if candidate face + }//if not boundary face or boundary faces requested + }//if tetra isn't being output + }//if tetra not output + }//for all tetras + + //traverse tetras again, this time examining edges + for (i=0; i < numTetras; i++) + { + if ( tetraUse[i] == 1 ) //one means visited and discarded + { + Mesh->GetCellPoints(i, npts, tetraPts); + + for (j=0; j < 6; j++) + { + p1 = tetraPts[edge[j][0]]; + p2 = tetraPts[edge[j][1]]; + + if ((this->BoundingTriangulation || + (p1 < numPoints && p2 < numPoints)) + && (edges->IsEdge(p1,p2) == -1) ) + { + points->GetPoint(p1,x1); + points->GetPoint(p2,x2); + if ( (vtkMath::Distance2BetweenPoints(x1,x2)*0.25) <= alpha2 ) + { + edges->InsertEdge(p1,p2); + pts[0] = p1; + pts[1] = p2; + output->InsertNextCell(VTK_LINE,2,pts); + pointUse[p1] = 1; pointUse[p2] = 1; + } + }//if edge a candidate + }//for all edges of tetra + }//if tetra not output + }//for all tetras + + //traverse all points, create vertices if none used + for (ptId=0; ptId<(numPoints+6); ptId++) + { + if (!pointUse[ptId] && (ptId < numPoints || this->BoundingTriangulation)) + { + pts[0] = ptId; + output->InsertNextCell(VTK_VERTEX,1,pts); + } + } + + // update output + delete [] pointUse; + edges->Delete(); + } + + // Update output; free up supporting data structures. + // + if ( this->BoundingTriangulation ) + { + output->SetPoints(points); + } + else + { + output->SetPoints(inPoints); + output->GetPointData()->PassData(input->GetPointData()); + } + + for (i=0; iGetCellPoints(i,npts,tetraPts); + output->InsertNextCell(VTK_TETRA,4,tetraPts); + } + } + vtkDebugMacro(<<"Generated " << output->GetNumberOfPoints() << " points and " + << output->GetNumberOfCells() << " tetrahedra"); + + delete [] tetraUse; + cells->Delete(); + holeTetras->Delete(); + + Mesh->Delete(); + + output->Squeeze(); + + return 1; +} + +// This is a helper method used with InsertPoint() to create +// tetrahedronalizations of points. Its purpose is construct an initial +// Delaunay triangulation into which to inject other points. You must +// specify the center of a cubical bounding box and its length, as well +// as the numer of points to insert. The method returns a pointer to +// an unstructured grid. Use this pointer to manipulate the mesh as +// necessary. You must delete (with Delete()) the mesh when done. +// Note: This initialization method places points forming bounding octahedron +// at the end of the Mesh's point list. That is, InsertPoint() assumes that +// you will be inserting points between (0,numPtsToInsert-1). +vtkUnstructuredGrid *vtkDelaunay3D::InitPointInsertion(double center[3], + double length, vtkIdType numPtsToInsert, vtkPoints* &points) +{ + double x[3], bounds[6]; + vtkIdType tetraId; + vtkIdType pts[4]; + vtkUnstructuredGrid *Mesh=vtkUnstructuredGrid::New(); + + this->NumberOfDuplicatePoints = 0; + this->NumberOfDegeneracies = 0; + + points = vtkPoints::New(); + points->Allocate(numPtsToInsert+6); + + if ( length <= 0.0 ) + { + length = 1.0; + } + bounds[0] = center[0] - length; bounds[1] = center[0] + length; + bounds[2] = center[1] - length; bounds[3] = center[1] + length; + bounds[4] = center[2] - length; bounds[5] = center[2] + length; + + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion(points,bounds); + + //create bounding octahedron: 6 points & 4 tetra + x[0] = center[0] - length; + x[1] = center[1]; + x[2] = center[2]; + this->Locator->InsertPoint(numPtsToInsert,x); + + x[0] = center[0] + length; + x[1] = center[1]; + x[2] = center[2]; + this->Locator->InsertPoint(numPtsToInsert+1,x); + + x[0] = center[0]; + x[1] = center[1] - length; + x[2] = center[2]; + this->Locator->InsertPoint(numPtsToInsert+2,x); + + x[0] = center[0]; + x[1] = center[1] + length; + x[2] = center[2]; + this->Locator->InsertPoint(numPtsToInsert+3,x); + + x[0] = center[0]; + x[1] = center[1]; + x[2] = center[2] - length; + this->Locator->InsertPoint(numPtsToInsert+4,x); + + x[0] = center[0]; + x[1] = center[1]; + x[2] = center[2] + length; + this->Locator->InsertPoint(numPtsToInsert+5,x); + + Mesh->Allocate(5*numPtsToInsert); + + if (this->TetraArray) + { + delete this->TetraArray; + } + + this->TetraArray = new vtkTetraArray(5*numPtsToInsert,numPtsToInsert); + + //create bounding tetras (there are four) + pts[0] = numPtsToInsert + 4; pts[1] = numPtsToInsert + 5; + pts[2] = numPtsToInsert; pts[3] = numPtsToInsert + 2; + tetraId = Mesh->InsertNextCell(VTK_TETRA,4,pts); + this->InsertTetra(Mesh,points,tetraId); + + pts[0] = numPtsToInsert + 4; pts[1] = numPtsToInsert + 5; + pts[2] = numPtsToInsert + 2; pts[3] = numPtsToInsert + 1; + tetraId = Mesh->InsertNextCell(VTK_TETRA,4,pts); + this->InsertTetra(Mesh,points,tetraId); + + pts[0] = numPtsToInsert + 4; pts[1] = numPtsToInsert + 5; + pts[2] = numPtsToInsert + 1; pts[3] = numPtsToInsert + 3; + tetraId = Mesh->InsertNextCell(VTK_TETRA,4,pts); + this->InsertTetra(Mesh,points,tetraId); + + pts[0] = numPtsToInsert + 4; pts[1] = numPtsToInsert + 5; + pts[2] = numPtsToInsert + 3; pts[3] = numPtsToInsert; + tetraId = Mesh->InsertNextCell(VTK_TETRA,4,pts); + this->InsertTetra(Mesh,points,tetraId); + + Mesh->SetPoints(points); + points->Delete(); + Mesh->BuildLinks(); + + // Keep track of change in references to points + this->References = new int [numPtsToInsert+6]; + memset(this->References, 0, (numPtsToInsert+6)*sizeof(int)); + + return Mesh; +} + +// This is a helper method used with InitPointInsertion() to create +// tetrahedronalizations of points. Its purpose is to inject point at +// coordinates specified into tetrahedronalization. The point id is an index +// into the list of points in the mesh structure. (See +// vtkDelaunay3D::InitPointInsertion() for more information.) When you have +// completed inserting points, traverse the mesh structure to extract desired +// tetrahedra (or tetra faces and edges). The holeTetras id list lists all the +// tetrahedra that are deleted (invalid) in the mesh structure. +void vtkDelaunay3D::InsertPoint(vtkUnstructuredGrid *Mesh, vtkPoints *points, + vtkIdType ptId, double x[3], + vtkIdList *holeTetras) +{ + vtkIdType tetraId, numFaces; + int i; + vtkIdType nodes[4]; + vtkIdType tetraNum, numTetras; + + this->Tetras->Reset(); + this->Faces->Reset(); + + // Find faces containing point. (Faces are found by deleting + // one or more tetrahedra "containing" point.) Tetrahedron contain point + // when they satisfy Delaunay criterion. (More than one tetra may contain + // a point if the point is on or near an edge or face.) For each face, + // create a tetrahedron. (The locator helps speed search of points + // in tetras.) + if ( (numFaces=this->FindEnclosingFaces(x, Mesh, this->Tetras, + this->Faces, this->Locator)) > 0 ) + { + this->Locator->InsertPoint(ptId,x); //point is part of mesh now + numTetras = this->Tetras->GetNumberOfIds(); + + // create new tetra for each face + for (tetraNum=0; tetraNum < numFaces; tetraNum++) + { + // Define tetrahedron. The order of the points matters: points + // 0, 1, and 2 must appear in counterclockwise order when seen + // from point 3. When we get here, point ptId is inside the + // tetrahedron whose faces we're considering and we've + // guaranteed that the 3 points in this face are + // counterclockwise wrt the new point. That lets us create a + // new tetrahedron with the right ordering. + nodes[0] = this->Faces->GetId(3*tetraNum); + nodes[1] = this->Faces->GetId(3*tetraNum+1); + nodes[2] = this->Faces->GetId(3*tetraNum+2); + nodes[3] = ptId; + + //either replace previously deleted tetra or create new one + if ( tetraNum < numTetras ) + { + tetraId = this->Tetras->GetId(tetraNum); + Mesh->ReplaceCell(tetraId, 4, nodes); + } + else + { + tetraId = Mesh->InsertNextCell(VTK_TETRA,4,nodes); + } + + // Update data structures + for (i=0; i<4; i++) + { + if ( this->References[nodes[i]] >= 0 ) + { + Mesh->ResizeCellList(nodes[i],5); + this->References[nodes[i]] -= 5; + } + this->References[nodes[i]]++; + Mesh->AddReferenceToCell(nodes[i],tetraId); + } + + this->InsertTetra(Mesh, points, tetraId); + + }//for each face + + // Sometimes there are more tetras deleted than created. These + // have to be accounted for because they leave a "hole" in the + // data structure. Keep track of them here...mark them deleted later. + for (tetraNum = numFaces; tetraNum < numTetras; tetraNum++ ) + { + holeTetras->InsertNextId(this->Tetras->GetId(tetraNum)); + } + }//if enclosing faces found +} + + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkDelaunay3D::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +void vtkDelaunay3D::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkPointLocator::New(); + this->Locator->SetDivisions(25,25,25); + } +} + +// See whether point is in sphere of tetrahedron +int vtkDelaunay3D::InSphere(double x[3], vtkIdType tetraId) +{ + double dist2; + vtkDelaunayTetra *tetra = this->TetraArray->GetTetra(tetraId); + + // check if inside/outside circumcircle + dist2 = (x[0] - tetra->center[0]) * (x[0] - tetra->center[0]) + + (x[1] - tetra->center[1]) * (x[1] - tetra->center[1]) + + (x[2] - tetra->center[2]) * (x[2] - tetra->center[2]); + + if ( dist2 < (0.9999999999L * tetra->r2) ) + { + return 1; + } + else + { + return 0; + } +} + +// Compute circumsphere and place into array of tetras +void vtkDelaunay3D::InsertTetra(vtkUnstructuredGrid *Mesh, vtkPoints *points, + vtkIdType tetraId) +{ + double dx1[3], dx2[3], dx3[3], dx4[3], radius2, center[3]; + vtkIdType *pts, npts; + + Mesh->GetCellPoints(tetraId, npts, pts); + points->GetPoint(pts[0], dx1); + points->GetPoint(pts[1], dx2); + points->GetPoint(pts[2], dx3); + points->GetPoint(pts[3], dx4); + + radius2 = vtkTetra::Circumsphere(dx1,dx2,dx3,dx4,center); + this->TetraArray->InsertTetra(tetraId, radius2, center); +} + +void vtkDelaunay3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Alpha: " << this->Alpha << "\n"; + os << indent << "Tolerance: " << this->Tolerance << "\n"; + os << indent << "Offset: " << this->Offset << "\n"; + os << indent << "Bounding Triangulation: " + << (this->BoundingTriangulation ? "On\n" : "Off\n"); + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +void vtkDelaunay3D::EndPointInsertion() +{ + if (this->References) + { + delete [] this->References; + this->References = NULL; + } +} + +unsigned long int vtkDelaunay3D::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} + +static int GetTetraFaceNeighbor(vtkUnstructuredGrid *Mesh, vtkIdType tetraId, + vtkIdType p1, vtkIdType p2, vtkIdType p3, + vtkIdType& nei) +{ + // gather necessary information + vtkCellLinks *links = Mesh->GetCellLinks(); + int numCells = links->GetNcells(p1); + vtkIdType *cells = links->GetCells(p1); + int i; + vtkIdType *pts, npts; + + //perform set operation + for (i=0; i < numCells; i++) + { + if ( cells[i] != tetraId ) + { + Mesh->GetCellPoints(cells[i],npts,pts); + if ( (p2 == pts[0] || p2 == pts[1] || p2 == pts[2] || p2 == pts[3]) && + (p3 == pts[0] || p3 == pts[1] || p3 == pts[2] || p3 == pts[3]) ) + { + nei = cells[i]; + break; + } + }//if not referring tetra + }//for all candidate cells + + if ( i < numCells ) + { + return 1; + } + else + { + return 0; //there is no neighbor + } +} + +//---------------------------------------------------------------------------- +int vtkDelaunay3D::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPointSet"); + return 1; +} diff --git a/Graphics/vtkDelaunay3D.h b/Graphics/vtkDelaunay3D.h new file mode 100644 index 0000000..254752d --- /dev/null +++ b/Graphics/vtkDelaunay3D.h @@ -0,0 +1,230 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDelaunay3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDelaunay3D - create 3D Delaunay triangulation of input points +// .SECTION Description +// vtkDelaunay3D is a filter that constructs a 3D Delaunay +// triangulation from a list of input points. These points may be +// represented by any dataset of type vtkPointSet and subclasses. The +// output of the filter is an unstructured grid dataset. Usually the +// output is a tetrahedral mesh, but if a non-zero alpha distance +// value is specified (called the "alpha" value), then only tetrahedra, +// triangles, edges, and vertices lying within the alpha radius are +// output. In other words, non-zero alpha values may result in arbitrary +// combinations of tetrahedra, triangles, lines, and vertices. (The notion +// of alpha value is derived from Edelsbrunner's work on "alpha shapes".) +// +// The 3D Delaunay triangulation is defined as the triangulation that +// satisfies the Delaunay criterion for n-dimensional simplexes (in +// this case n=3 and the simplexes are tetrahedra). This criterion +// states that a circumsphere of each simplex in a triangulation +// contains only the n+1 defining points of the simplex. (See text for +// more information.) While in two dimensions this translates into an +// "optimal" triangulation, this is not true in 3D, since a measurement +// for optimality in 3D is not agreed on. +// +// Delaunay triangulations are used to build topological structures +// from unorganized (or unstructured) points. The input to this filter +// is a list of points specified in 3D. (If you wish to create 2D +// triangulations see vtkDelaunay2D.) The output is an unstructured grid. +// +// The Delaunay triangulation can be numerically sensitive. To prevent +// problems, try to avoid injecting points that will result in +// triangles with bad aspect ratios (1000:1 or greater). In practice +// this means inserting points that are "widely dispersed", and +// enables smooth transition of triangle sizes throughout the +// mesh. (You may even want to add extra points to create a better +// point distribution.) If numerical problems are present, you will +// see a warning message to this effect at the end of the +// triangulation process. + +// .SECTION Caveats +// Points arranged on a regular lattice (termed degenerate cases) can be +// triangulated in more than one way (at least according to the Delaunay +// criterion). The choice of triangulation (as implemented by +// this algorithm) depends on the order of the input points. The first four +// points will form a tetrahedron; other degenerate points (relative to this +// initial tetrahedron) will not break it. +// +// Points that are coincident (or nearly so) may be discarded by the +// algorithm. This is because the Delaunay triangulation requires +// unique input points. You can control the definition of coincidence +// with the "Tolerance" instance variable. +// +// The output of the Delaunay triangulation is supposedly a convex hull. In +// certain cases this implementation may not generate the convex hull. This +// behavior can be controlled by the Offset instance variable. Offset is a +// multiplier used to control the size of the initial triangulation. The +// larger the offset value, the more likely you will generate a convex hull; +// and the more likely you are to see numerical problems. +// +// The implementation of this algorithm varies from the 2D Delaunay +// algorithm (i.e., vtkDelaunay2D) in an important way. When points are +// injected into the triangulation, the search for the enclosing tetrahedron +// is quite different. In the 3D case, the closest previously inserted point +// point is found, and then the connected tetrahedra are searched to find +// the containing one. (In 2D, a "walk" towards the enclosing triangle is +// performed.) If the triangulation is Delaunay, then an enclosing tetrahedron +// will be found. However, in degenerate cases an enclosing tetrahedron may +// not be found and the point will be rejected. + +// .SECTION See Also +// vtkDelaunay2D vtkGaussianSplatter vtkUnstructuredGrid + +#ifndef __vtkDelaunay3D_h +#define __vtkDelaunay3D_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkIdList; +class vtkPointLocator; +class vtkPointSet; +class vtkPoints; +class vtkTetraArray; + +class VTK_GRAPHICS_EXPORT vtkDelaunay3D : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkDelaunay3D,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with Alpha = 0.0; Tolerance = 0.001; Offset = 2.5; + // BoundingTriangulation turned off. + static vtkDelaunay3D *New(); + + // Description: + // Specify alpha (or distance) value to control output of this filter. + // For a non-zero alpha value, only edges, faces, or tetra contained + // within the circumsphere (of radius alpha) will be output. Otherwise, + // only tetrahedra will be output. + vtkSetClampMacro(Alpha,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Alpha,double); + + // Description: + // Specify a tolerance to control discarding of closely spaced points. + // This tolerance is specified as a fraction of the diagonal length of + // the bounding box of the points. + vtkSetClampMacro(Tolerance,double,0.0,1.0); + vtkGetMacro(Tolerance,double); + + // Description: + // Specify a multiplier to control the size of the initial, bounding + // Delaunay triangulation. + vtkSetClampMacro(Offset,double,2.5,VTK_DOUBLE_MAX); + vtkGetMacro(Offset,double); + + // Description: + // Boolean controls whether bounding triangulation points (and associated + // triangles) are included in the output. (These are introduced as an + // initial triangulation to begin the triangulation process. This feature + // is nice for debugging output.) + vtkSetMacro(BoundingTriangulation,int); + vtkGetMacro(BoundingTriangulation,int); + vtkBooleanMacro(BoundingTriangulation,int); + + // Description: + // Set / get a spatial locator for merging points. By default, + // an instance of vtkPointLocator is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. The + // locator is used to eliminate "coincident" points. + void CreateDefaultLocator(); + + // Description: + // This is a helper method used with InsertPoint() to create + // tetrahedronalizations of points. Its purpose is construct an initial + // Delaunay triangulation into which to inject other points. You must + // specify the center of a cubical bounding box and its length, as well + // as the number of points to insert. The method returns a pointer to + // an unstructured grid. Use this pointer to manipulate the mesh as + // necessary. You must delete (with Delete()) the mesh when done. + // Note: This initialization method places points forming bounding octahedron + // at the end of the Mesh's point list. That is, InsertPoint() assumes that + // you will be inserting points between (0,numPtsToInsert-1). + vtkUnstructuredGrid *InitPointInsertion(double center[3], double length, + vtkIdType numPts, vtkPoints* &pts); + + // Description: + // This is a helper method used with InitPointInsertion() to create + // tetrahedronalizations of points. Its purpose is to inject point at + // coordinates specified into tetrahedronalization. The point id is an index + // into the list of points in the mesh structure. (See + // vtkDelaunay3D::InitPointInsertion() for more information.) When you have + // completed inserting points, traverse the mesh structure to extract desired + // tetrahedra (or tetra faces and edges).The holeTetras id list lists all the + // tetrahedra that are deleted (invalid) in the mesh structure. + void InsertPoint(vtkUnstructuredGrid *Mesh, vtkPoints *points, + vtkIdType id, double x[3], vtkIdList *holeTetras); + + // Description: + // Invoke this method after all points have been inserted. The purpose of + // the method is to clean up internal data structures. Note that the + // (vtkUnstructuredGrid *)Mesh returned from InitPointInsertion() is NOT + // deleted, you still are responsible for cleaning that up. + void EndPointInsertion(); + + // Description: + // Return the MTime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkDelaunay3D(); + ~vtkDelaunay3D(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Alpha; + double Tolerance; + int BoundingTriangulation; + double Offset; + + vtkPointLocator *Locator; //help locate points faster + + vtkTetraArray *TetraArray; //used to keep track of circumspheres/neighbors + int FindTetra(vtkUnstructuredGrid *Mesh, double x[3], vtkIdType tetId, + int depth); + int InSphere(double x[3], vtkIdType tetraId); + void InsertTetra(vtkUnstructuredGrid *Mesh, vtkPoints *pts, + vtkIdType tetraId); + + int NumberOfDuplicatePoints; //keep track of bad data + int NumberOfDegeneracies; + + // Keep track of number of references to points to avoid new/delete calls + int *References; + + vtkIdType FindEnclosingFaces(double x[3], vtkUnstructuredGrid *Mesh, + vtkIdList *tetras, vtkIdList *faces, + vtkPointLocator *Locator); + + virtual int FillInputPortInformation(int, vtkInformation*); +private: //members added for performance + vtkIdList *Tetras; //used in InsertPoint + vtkIdList *Faces; //used in InsertPoint + vtkIdList *BoundaryPts; //used by InsertPoint + vtkIdList *CheckedTetras; //used by InsertPoint + vtkIdList *NeiTetras; //used by InsertPoint + +private: + vtkDelaunay3D(const vtkDelaunay3D&); // Not implemented. + void operator=(const vtkDelaunay3D&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkDicer.cxx b/Graphics/vtkDicer.cxx new file mode 100644 index 0000000..211cc3b --- /dev/null +++ b/Graphics/vtkDicer.cxx @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDicer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDicer.h" + +#include "vtkDataSet.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkDicer, "$Revision: 1.33 $"); + +// Instantiate object. +vtkDicer::vtkDicer() +{ + this->NumberOfPointsPerPiece = 5000; + this->NumberOfPieces = 10; + this->MemoryLimit = 50000; //50 MBytes + this->NumberOfActualPieces = 0; + this->FieldData = 0; + this->DiceMode = VTK_DICE_MODE_NUMBER_OF_POINTS; +} + +// This method unifies the measures used to define piece size. Call this +// in the subclass Execute() method. +void vtkDicer::UpdatePieceMeasures(vtkDataSet *input) +{ + int numPts = input->GetNumberOfPoints(); + unsigned long memSize = input->GetActualMemorySize(); + + if ( this->DiceMode == VTK_DICE_MODE_NUMBER_OF_POINTS ) + { + this->NumberOfPieces = (int) ceil((double)numPts/this->NumberOfPointsPerPiece); + this->MemoryLimit = (unsigned long) ceil((double)memSize/this->NumberOfPieces); + } + + else if ( this->DiceMode == VTK_DICE_MODE_SPECIFIED_NUMBER ) + { + this->NumberOfPointsPerPiece = (int) ceil((double)numPts/this->NumberOfPieces); + this->MemoryLimit = (unsigned long) ceil((double)memSize/this->NumberOfPieces); + } + + else //this->DiceMode == VTK_DICE_MODE_MEMORY_LIMIT + { + this->NumberOfPieces = (int) ceil((double)memSize/this->MemoryLimit); + this->NumberOfPointsPerPiece = (int) ceil((double)numPts/this->NumberOfPieces); + } +} + +void vtkDicer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of Points per Piece: " + << this->NumberOfPointsPerPiece << "\n"; + + os << indent << "Number of Pieces: " + << this->NumberOfPieces << "\n"; + + os << indent << "Memory Limit: " + << this->MemoryLimit << "\n"; + + os << indent << "Number of Actual Pieces: " + << this->NumberOfActualPieces << "\n"; + + os << indent << "Field Data: " << (this->FieldData ? "On\n" : "Off\n"); + + if ( this->DiceMode == VTK_DICE_MODE_NUMBER_OF_POINTS ) + { + os << indent << "Dice Mode: Number Of Points\n"; + } + else if ( this->DiceMode == VTK_DICE_MODE_SPECIFIED_NUMBER ) + { + os << indent << "Dice Mode: Specified Number\n"; + } + else + { + os << indent << "Dice Mode: Memory Limit\n"; + } +} diff --git a/Graphics/vtkDicer.h b/Graphics/vtkDicer.h new file mode 100644 index 0000000..75e77e8 --- /dev/null +++ b/Graphics/vtkDicer.h @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDicer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDicer - abstract superclass to divide dataset into pieces +// .SECTION Description +// Subclasses of vtkDicer divides the input dataset into separate +// pieces. These pieces can then be operated on by other filters +// (e.g., vtkThreshold). One application is to break very large +// polygonal models into pieces and performing viewing and occlusion +// culling on the pieces. Multiple pieces can also be streamed through +// the visualization pipeline. +// +// To use this filter, you must specify the execution mode of the +// filter; i.e., set the way that the piece size is controlled (do +// this by setting the DiceMode ivar). The filter does not change the +// geometry or topology of the input dataset, rather it generates +// integer numbers that indicate which piece a particular point +// belongs to (i.e., it modifies the point and cell attribute +// data). The integer number can be placed into the output scalar +// data, or the output field data. + +// .SECTION Caveats +// The number of pieces generated may not equal the specified number +// of pieces. Use the method GetNumberOfActualPieces() after filter +// execution to get the actual number of pieces generated. + +// .SECTION See Also +// vtkOBBDicer vtkConnectedDicer vtkSpatialDicer + +#ifndef __vtkDicer_h +#define __vtkDicer_h + +#include "vtkDataSetAlgorithm.h" + +#define VTK_DICE_MODE_NUMBER_OF_POINTS 0 +#define VTK_DICE_MODE_SPECIFIED_NUMBER 1 +#define VTK_DICE_MODE_MEMORY_LIMIT 2 + +class VTK_GRAPHICS_EXPORT vtkDicer : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkDicer,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the flag which controls whether to generate point scalar + // data or point field data. If this flag is off, scalar data is + // generated. Otherwise, field data is generated. Note that the + // generated the data are integer numbers indicating which piece a + // particular point belongs to. + vtkSetMacro(FieldData,int); + vtkGetMacro(FieldData,int); + vtkBooleanMacro(FieldData,int); + + // Description: + // Specify the method to determine how many pieces the data should be + // broken into. By default, the number of points per piece is used. + vtkSetClampMacro(DiceMode,int,VTK_DICE_MODE_NUMBER_OF_POINTS,VTK_DICE_MODE_MEMORY_LIMIT); + vtkGetMacro(DiceMode,int); + void SetDiceModeToNumberOfPointsPerPiece() + {this->SetDiceMode(VTK_DICE_MODE_NUMBER_OF_POINTS);}; + void SetDiceModeToSpecifiedNumberOfPieces() + {this->SetDiceMode(VTK_DICE_MODE_SPECIFIED_NUMBER);}; + void SetDiceModeToMemoryLimitPerPiece() + {this->SetDiceMode(VTK_DICE_MODE_MEMORY_LIMIT);}; + + // Description: + // Use the following method after the filter has updated to + // determine the actual number of pieces the data was separated + // into. + vtkGetMacro(NumberOfActualPieces,int); + + // Description: + // Control piece size based on the maximum number of points per piece. + // (This ivar has effect only when the DiceMode is set to + // SetDiceModeToNumberOfPoints().) + vtkSetClampMacro(NumberOfPointsPerPiece,int,1000,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfPointsPerPiece,int); + + // Description: + // Set/Get the number of pieces the object is to be separated into. + // (This ivar has effect only when the DiceMode is set to + // SetDiceModeToSpecifiedNumber()). Note that the ivar + // NumberOfPieces is a target - depending on the particulars of the + // data, more or less number of pieces than the target value may be + // created. + vtkSetClampMacro(NumberOfPieces,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfPieces,int); + + // Description: + // Control piece size based on a memory limit. (This ivar has + // effect only when the DiceMode is set to + // SetDiceModeToMemoryLimit()). The memory limit should be set in + // kilobytes. + vtkSetClampMacro(MemoryLimit,unsigned long,100,VTK_LARGE_INTEGER); + vtkGetMacro(MemoryLimit,unsigned long); + +protected: + vtkDicer(); + ~vtkDicer() {}; + + virtual void UpdatePieceMeasures(vtkDataSet *input); + + int NumberOfPointsPerPiece; + int NumberOfPieces; + unsigned long MemoryLimit; + int NumberOfActualPieces; + int FieldData; + int DiceMode; + +private: + vtkDicer(const vtkDicer&); // Not implemented. + void operator=(const vtkDicer&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkDiscreteMarchingCubes.cxx b/Graphics/vtkDiscreteMarchingCubes.cxx new file mode 100644 index 0000000..77e027f --- /dev/null +++ b/Graphics/vtkDiscreteMarchingCubes.cxx @@ -0,0 +1,398 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDiscreteMarchingCubes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkDiscreteMarchingCubes.h" + +#include "vtkCellArray.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMarchingCubesCases.h" +#include "vtkMath.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkCellData.h" +#include "vtkShortArray.h" +#include "vtkStructuredPoints.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#ifndef vtkFloatingPointType +#define vtkFloatingPointType float +#endif + +vtkCxxRevisionMacro(vtkDiscreteMarchingCubes, "$Revision: 1.1.6.1 $"); +vtkStandardNewMacro(vtkDiscreteMarchingCubes); + +// Description: +// Construct object with initial range (0,1) and single contour value +// of 0.0. ComputeNormals is off, ComputeGradients is off and ComputeScalars is on. +vtkDiscreteMarchingCubes::vtkDiscreteMarchingCubes() +{ + this->ComputeNormals = 0; + this->ComputeGradients = 0; + this->ComputeScalars = 1; +} + +vtkDiscreteMarchingCubes::~vtkDiscreteMarchingCubes() +{ +} + + +// +// Contouring filter specialized for volumes and "short int" data values. +// +template +void vtkDiscreteMarchingCubesComputeGradient( + vtkDiscreteMarchingCubes *self,T *scalars, int dims[3], + vtkFloatingPointType origin[3], vtkFloatingPointType Spacing[3], + vtkPointLocator *locator, + vtkDataArray *newCellScalars, + vtkCellArray *newPolys, vtkFloatingPointType *values, + int numValues) +{ + vtkFloatingPointType s[8], value; + int i, j, k, sliceSize; + static int CASE_MASK[8] = {1,2,4,8,16,32,64,128}; + vtkMarchingCubesTriangleCases *triCase, *triCases; + EDGE_LIST *edge; + int contNum, jOffset, kOffset, idx, ii, index, *vert; + vtkIdType ptIds[3]; + int extent[6]; + int ComputeScalars = newCellScalars != NULL; + vtkFloatingPointType t, *x1, *x2, x[3], min, max; + vtkFloatingPointType pts[8][3], xp, yp, zp; + static int edges[12][2] = { {0,1}, {1,2}, {3,2}, {0,3}, + {4,5}, {5,6}, {7,6}, {4,7}, + {0,4}, {1,5}, {3,7}, {2,6}}; + + vtkInformation *inInfo = self->GetExecutive()->GetInputInformation(0, 0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + + triCases = vtkMarchingCubesTriangleCases::GetCases(); + +// +// Get min/max contour values +// + if ( numValues < 1 ) + { + return; + } + for ( min=max=values[0], i=1; i < numValues; i++) + { + if ( values[i] < min ) + { + min = values[i]; + } + if ( values[i] > max ) + { + max = values[i]; + } + } +// +// Traverse all voxel cells, generating triangles +// using marching cubes algorithm. +// + sliceSize = dims[0] * dims[1]; + for ( k=0; k < (dims[2]-1); k++) + { + self->UpdateProgress ((vtkFloatingPointType) k / ((vtkFloatingPointType) dims[2] - 1)); + if (self->GetAbortExecute()) + { + break; + } + kOffset = k*sliceSize; + pts[0][2] = origin[2] + (k+extent[4])*Spacing[2]; + zp = pts[0][2] + Spacing[2]; + for ( j=0; j < (dims[1]-1); j++) + { + jOffset = j*dims[0]; + pts[0][1] = origin[1] + (j+extent[2])*Spacing[1]; + yp = pts[0][1] + Spacing[1]; + for ( i=0; i < (dims[0]-1); i++) + { + //get scalar values + idx = i + jOffset + kOffset; + s[0] = scalars[idx]; + s[1] = scalars[idx+1]; + s[2] = scalars[idx+1 + dims[0]]; + s[3] = scalars[idx + dims[0]]; + s[4] = scalars[idx + sliceSize]; + s[5] = scalars[idx+1 + sliceSize]; + s[6] = scalars[idx+1 + dims[0] + sliceSize]; + s[7] = scalars[idx + dims[0] + sliceSize]; + + if ( (s[0] < min && s[1] < min && s[2] < min && s[3] < min && + s[4] < min && s[5] < min && s[6] < min && s[7] < min) || + (s[0] > max && s[1] > max && s[2] > max && s[3] > max && + s[4] > max && s[5] > max && s[6] > max && s[7] > max) ) + { + continue; // no contours possible + } + + //create voxel points + pts[0][0] = origin[0] + (i+extent[0])*Spacing[0]; + xp = pts[0][0] + Spacing[0]; + + pts[1][0] = xp; + pts[1][1] = pts[0][1]; + pts[1][2] = pts[0][2]; + + pts[2][0] = xp; + pts[2][1] = yp; + pts[2][2] = pts[0][2]; + + pts[3][0] = pts[0][0]; + pts[3][1] = yp; + pts[3][2] = pts[0][2]; + + pts[4][0] = pts[0][0]; + pts[4][1] = pts[0][1]; + pts[4][2] = zp; + + pts[5][0] = xp; + pts[5][1] = pts[0][1]; + pts[5][2] = zp; + + pts[6][0] = xp; + pts[6][1] = yp; + pts[6][2] = zp; + + pts[7][0] = pts[0][0]; + pts[7][1] = yp; + pts[7][2] = zp; + + for (contNum=0; contNum < numValues; contNum++) + { + value = values[contNum]; + // Build the case table + for ( ii=0, index = 0; ii < 8; ii++) + { + // for discrete marching cubes, we are looking for an + // exact match of a scalar at a vertex to a value + if ( s[ii] == value ) + { + index |= CASE_MASK[ii]; + } + } + if ( index == 0 || index == 255 ) //no surface + { + continue; + } + + triCase = triCases+ index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (ii=0; ii<3; ii++) //insert triangle + { + vert = edges[edge[ii]]; + // for discrete marching cubes, the interpolation point + // is always 0.5. + t = 0.5; + x1 = pts[vert[0]]; + x2 = pts[vert[1]]; + x[0] = x1[0] + t * (x2[0] - x1[0]); + x[1] = x1[1] + t * (x2[1] - x1[1]); + x[2] = x1[2] + t * (x2[2] - x1[2]); + + // add point + locator->InsertUniquePoint(x, ptIds[ii]); + } + // check for degenerate triangle + if ( ptIds[0] != ptIds[1] && + ptIds[0] != ptIds[2] && + ptIds[1] != ptIds[2] ) + { + newPolys->InsertNextCell(3,ptIds); + // Note that DiscreteMarchingCubes stores the scalar + // data in the cells. It does not use the point data + // since cells from different labeled segments may use + // the same point. + if (ComputeScalars) + { + newCellScalars->InsertNextTuple(&value); + } + } + }//for each triangle + }//for all contours + }//for i + }//for j + }//for k +} + +// +// Contouring filter specialized for volumes and "short int" data values. +// +int vtkDiscreteMarchingCubes::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkPoints *newPts; + vtkCellArray *newPolys; + vtkFloatArray *newCellScalars; + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointData *pd; + vtkDataArray *inScalars; + int dims[3], extent[6]; + int estimatedSize; + vtkFloatingPointType Spacing[3], origin[3]; + vtkFloatingPointType bounds[6]; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int numContours=this->ContourValues->GetNumberOfContours(); + vtkFloatingPointType *values=this->ContourValues->GetValues(); + + vtkDebugMacro(<< "Executing marching cubes"); + +// +// Initialize and check input +// + pd=input->GetPointData(); + if (pd ==NULL) + { + vtkErrorMacro(<<"PointData is NULL"); + return 1; + } + inScalars=pd->GetScalars(); + if ( inScalars == NULL ) + { + vtkErrorMacro(<<"Scalars must be defined for contouring"); + return 1; + } + + if ( input->GetDataDimension() != 3 ) + { + vtkErrorMacro(<<"Cannot contour data of dimension != 3"); + return 1; + } + input->GetDimensions(dims); + input->GetOrigin(origin); + input->GetSpacing(Spacing); + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + + // estimate the number of points from the volume dimensions + estimatedSize = (int) pow ((vtkFloatingPointType) (dims[0] * dims[1] * dims[2]), .75); + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + vtkDebugMacro(<< "Estimated allocation size is " << estimatedSize); + newPts = vtkPoints::New(); newPts->Allocate(estimatedSize,estimatedSize/2); + // compute bounds for merging points + for ( int i=0; i<3; i++) + { + bounds[2*i] = origin[i] + extent[2*i] * Spacing[i]; + bounds[2*i+1] = origin[i] + extent[2*i+1] * Spacing[i]; + } + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, bounds, estimatedSize); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(estimatedSize,3)); + + if (this->ComputeScalars) + { + newCellScalars = vtkFloatArray::New(); + newCellScalars->Allocate(estimatedSize,3); + } + else + { + newCellScalars = NULL; + } + + if (inScalars->GetNumberOfComponents() == 1 ) + { + void* scalars = inScalars->GetVoidPointer(0); + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + vtkDiscreteMarchingCubesComputeGradient(this, + static_cast(scalars), + dims, origin, Spacing, + this->Locator, newCellScalars, + newPolys, values, numContours) + ); + } //switch + } + + else //multiple components - have to convert + { + int dataSize = dims[0] * dims[1] * dims[2]; + vtkDoubleArray *image=vtkDoubleArray::New(); + image->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + image->SetNumberOfTuples(image->GetNumberOfComponents()*dataSize); + inScalars->GetTuples(0,dataSize,image); + + double *scalars = image->GetPointer(0); + vtkDiscreteMarchingCubesComputeGradient(this, + scalars, + dims, + origin, + Spacing, + this->Locator, + newCellScalars, + newPolys, + values, + numContours); + image->Delete(); + } + + vtkDebugMacro(<<"Created: " + << newPts->GetNumberOfPoints() << " points, " + << newPolys->GetNumberOfCells() << " triangles"); + // + // Update ourselves. Because we don't know up front how many triangles + // we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + if (newCellScalars) + { + output->GetCellData()->SetScalars(newCellScalars); + newCellScalars->Delete(); + } + output->Squeeze(); + if (this->Locator) + { + this->Locator->Initialize(); //free storage + } + + return 1; +} diff --git a/Graphics/vtkDiscreteMarchingCubes.h b/Graphics/vtkDiscreteMarchingCubes.h new file mode 100644 index 0000000..7023208 --- /dev/null +++ b/Graphics/vtkDiscreteMarchingCubes.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDiscreteMarchingCubes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +// .SECTION Thanks +// Jim Miller at GE Research implemented the original version of this +// filter. +// This work was supported by PHS Research Grant No. 1 P41 RR13218-01 +// from the National Center for Research Resources and supported by a +// grant from the DARPA, executed by the U.S. Army Medical Research +// and Materiel Command/TATRC Cooperative Agreement, +// Contract # W81XWH-04-2-0012. + +=========================================================================*/ +// .NAME vtkDiscreteMarchingCubes - generate object boundaries from +// labelled volumes +// .SECTION Description vtkDiscreteMarchingCubes is a filter that +// takes as input a volume (e.g., 3D structured point set) of +// segmentation labels and generates on output one or more +// models representing the boundaries between the specified label and +// the adjacent structures. One or more label values must be specified to +// generate the models. The boundary positions are always defined to +// be half-way between adjacent voxels. This filter works best with +// integral scalar values. +// If ComputeScalars is on (the default), each output cell will have +// cell data that corresponds to the scalar value (segmentation label) +// of the corresponding cube. Note that this differs from vtkMarchingCubes, +// which stores the scalar value as point data. The rationale for this +// difference is that cell vertices may be shared between multiple +// cells. This also means that the resultant polydata may be +// non-manifold (cell faces may be coincident). To further process the +// polydata, users should either: 1) extract cells that have a common +// scalar value using vtkThreshold, or 2) process the data with +// filters that can handle non-manifold polydata +// (e.g. vtkWindowedSincPolyDataFilter). +// Also note, Normals and Gradients are not computed. +// .SECTION Caveats +// This filter is specialized to volumes. If you are interested in +// contouring other types of data, use the general vtkContourFilter. If you +// want to contour an image (i.e., a volume slice), use vtkMarchingSquares. +// .SECTION See Also +// vtkContourFilter vtkSliceCubes vtkMarchingSquares vtkDividingCubes + +#ifndef __vtkDiscreteMarchingCubes_h +#define __vtkDiscreteMarchingCubes_h + +#include "vtkMarchingCubes.h" + +class VTK_GRAPHICS_EXPORT vtkDiscreteMarchingCubes : public vtkMarchingCubes +{ +public: + static vtkDiscreteMarchingCubes *New(); + vtkTypeRevisionMacro(vtkDiscreteMarchingCubes,vtkMarchingCubes); + +protected: + vtkDiscreteMarchingCubes(); + ~vtkDiscreteMarchingCubes(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + +private: + vtkDiscreteMarchingCubes(const vtkDiscreteMarchingCubes&); // Not implemented. + void operator=(const vtkDiscreteMarchingCubes&); // Not implemented. + +}; + +#endif + + diff --git a/Graphics/vtkDiskSource.cxx b/Graphics/vtkDiskSource.cxx new file mode 100644 index 0000000..0630c63 --- /dev/null +++ b/Graphics/vtkDiskSource.cxx @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDiskSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDiskSource.h" + +#include "vtkCellArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkDiskSource, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkDiskSource); + +vtkDiskSource::vtkDiskSource() +{ + this->InnerRadius = 0.25; + this->OuterRadius = 0.5; + this->RadialResolution = 1; + this->CircumferentialResolution = 6; + + this->SetNumberOfInputPorts(0); +} + +int vtkDiskSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPolys, numPts; + double x[3]; + int i, j; + vtkIdType pts[4]; + double theta, deltaRadius; + double cosTheta, sinTheta; + vtkPoints *newPoints; + vtkCellArray *newPolys; + + // Set things up; allocate memory + // + numPts = (this->RadialResolution + 1) * + (this->CircumferentialResolution + 1); + numPolys = this->RadialResolution * this->CircumferentialResolution; + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys,4)); + + // Create disk + // + theta = 2.0 * vtkMath::Pi() / ((double)this->CircumferentialResolution); + deltaRadius = (this->OuterRadius - this->InnerRadius) / + ((double)this->RadialResolution); + + for (i=0; i < this->CircumferentialResolution; i++) + { + cosTheta = cos((double)i*theta); + sinTheta = sin((double)i*theta); + for (j=0; j <= this->RadialResolution; j++) + { + x[0] = (this->InnerRadius + j*deltaRadius) * cosTheta; + x[1] = (this->InnerRadius + j*deltaRadius) * sinTheta; + x[2] = 0.0; + newPoints->InsertNextPoint(x); + } + } + + // Create connectivity + // + for (i=0; i < this->CircumferentialResolution; i++) + { + for (j=0; j < this->RadialResolution; j++) + { + pts[0] = i*(this->RadialResolution+1) + j; + pts[1] = pts[0] + 1; + if ( i < (this->CircumferentialResolution-1) ) + { + pts[2] = pts[1] + this->RadialResolution + 1; + } + else + { + pts[2] = j + 1; + } + pts[3] = pts[2] - 1; + newPolys->InsertNextCell(4,pts); + } + } + + // Update ourselves and release memory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +void vtkDiskSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "InnerRadius: " << this->InnerRadius << "\n"; + os << indent << "OuterRadius: " << this->OuterRadius << "\n"; + os << indent << "RadialResolution: " << this->RadialResolution << "\n"; + os << indent << "CircumferentialResolution: " << this->CircumferentialResolution << "\n"; +} diff --git a/Graphics/vtkDiskSource.h b/Graphics/vtkDiskSource.h new file mode 100644 index 0000000..2f42c12 --- /dev/null +++ b/Graphics/vtkDiskSource.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDiskSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDiskSource - create a disk with hole in center +// .SECTION Description +// vtkDiskSource creates a polygonal disk with a hole in the center. The +// disk has zero height. The user can specify the inner and outer radius +// of the disk, and the radial and circumferential resolution of the +// polygonal representation. +// .SECTION See Also +// vtkLinearExtrusionFilter + +#ifndef __vtkDiskSource_h +#define __vtkDiskSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkDiskSource : public vtkPolyDataAlgorithm +{ +public: + static vtkDiskSource *New(); + vtkTypeRevisionMacro(vtkDiskSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify inner radius of hole in disc. + vtkSetClampMacro(InnerRadius,double,0.0,VTK_DOUBLE_MAX) + vtkGetMacro(InnerRadius,double); + + // Description: + // Specify outer radius of disc. + vtkSetClampMacro(OuterRadius,double,0.0,VTK_DOUBLE_MAX) + vtkGetMacro(OuterRadius,double); + + // Description: + // Set the number of points in radius direction. + vtkSetClampMacro(RadialResolution,int,1,VTK_LARGE_INTEGER) + vtkGetMacro(RadialResolution,int); + + // Description: + // Set the number of points in circumferential direction. + vtkSetClampMacro(CircumferentialResolution,int,3,VTK_LARGE_INTEGER) + vtkGetMacro(CircumferentialResolution,int); + +protected: + vtkDiskSource(); + ~vtkDiskSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double InnerRadius; + double OuterRadius; + int RadialResolution; + int CircumferentialResolution; + +private: + vtkDiskSource(const vtkDiskSource&); // Not implemented. + void operator=(const vtkDiskSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkEdgePoints.cxx b/Graphics/vtkEdgePoints.cxx new file mode 100644 index 0000000..e91ad3a --- /dev/null +++ b/Graphics/vtkEdgePoints.cxx @@ -0,0 +1,241 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEdgePoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEdgePoints.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkEdgePoints, "$Revision: 1.57 $"); +vtkStandardNewMacro(vtkEdgePoints); + +// Construct object with contour value of 0.0. +vtkEdgePoints::vtkEdgePoints() +{ + this->Value = 0.0; + this->Locator = vtkMergePoints::New(); +} + +vtkEdgePoints::~vtkEdgePoints() +{ + this->Locator->Delete(); + this->Locator = NULL; +} + +// +// General filter: handles arbitrary input. +// +int vtkEdgePoints::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *inScalars; + vtkPoints *newPts; + vtkCellArray *newVerts; + vtkIdType cellId, ptId, edgeId, newCellId; + int above, below, i, numEdges; + vtkCell *edge; + double range[2]; + double s0, s1, x0[3], x1[3], x[3], t; + double e0Scalar, deltaScalar; + int e0, e1; + vtkIdType p1, p2; + vtkIdType pts[1]; + vtkIdType numCells, estimatedSize; + vtkDataArray *cellScalars; + vtkPointData *inPd=input->GetPointData(), *outPd=output->GetPointData(); + vtkCellData *inCd=input->GetCellData(), *outCd=output->GetCellData(); + + vtkDebugMacro(<< "Generating edge points"); + + // Initialize and check input + // + if ( ! (inScalars = input->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"No scalar data to contour"); + return 1; + } + + inScalars->GetRange(range,0); + if ( this->Value < range[0] || this->Value > range[1] ) + { + vtkWarningMacro(<<"Value lies outside of scalar range"); + return 1; + } + + numCells = input->GetNumberOfCells(); + estimatedSize = (vtkIdType) (numCells * .75); + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize, estimatedSize/2); + newVerts = vtkCellArray::New(); + newVerts->Allocate(estimatedSize, estimatedSize/2); + cellScalars = inScalars->NewInstance(); + cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + cellScalars->Allocate(VTK_CELL_SIZE*inScalars->GetNumberOfComponents()); + + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + + // interpolate data along edge; copy cell data + outPd->InterpolateAllocate(inPd,5000,10000); + outCd->CopyAllocate(inCd,5000,10000); + + // Traverse all edges. Since edges are not explicitly represented, use a + // trick: traverse all cells and obtain cell edges and then cell edge + // neighbors. If cell id < all edge neigbors ids, then this edge has not + // yet been visited and is processed. + // + int abort=0; + vtkIdType progressInterval = numCells/20 + 1; + vtkGenericCell *cell = vtkGenericCell::New(); + for (cellId=0; cellId < numCells && !abort; cellId++) + { + if ( ! (cellId % progressInterval) ) + { + vtkDebugMacro(<<"Processing #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + abort = this->GetAbortExecute(); + } + + input->GetCell(cellId,cell); + inScalars->GetTuples(cell->PointIds, cellScalars); + + // loop over cell points to check if cell straddles isosurface value + for ( above=below=0, ptId=0; ptId < cell->GetNumberOfPoints(); ptId++ ) + { + if ( cellScalars->GetComponent(ptId,0) >= this->Value ) + { + above = 1; + } + else if ( cellScalars->GetComponent(ptId,0) < this->Value ) + { + below = 1; + } + } + + if ( above && below ) //contour passes through cell + { + if ( cell->GetCellDimension() < 2 ) //only points can be generated + { + cell->Contour(this->Value, cellScalars, this->Locator, newVerts, + NULL, NULL, inPd, outPd, inCd, cellId, outCd); + } + + else // + { + numEdges = cell->GetNumberOfEdges(); + for (edgeId=0; edgeId < numEdges; edgeId++) + { + edge = cell->GetEdge(edgeId); + inScalars->GetTuples(edge->PointIds, cellScalars); + + s0 = cellScalars->GetComponent(0,0); + s1 = cellScalars->GetComponent(1,0); + if ( (s0 < this->Value && s1 >= this->Value) || + (s0 >= this->Value && s1 < this->Value) ) + { + //ordering intersection direction avoids numerical problems + deltaScalar = s1 - s0; + if (deltaScalar > 0) + { + e0 = 0; e1 = 1; + e0Scalar = s0; + } + else + { + e0 = 1; e1 = 0; + e0Scalar = s1; + deltaScalar = -deltaScalar; + } + + t = (this->Value - e0Scalar) / deltaScalar; + + edge->Points->GetPoint(e0,x0); + edge->Points->GetPoint(e1,x1); + + for (i=0; i<3; i++) + { + x[i] = x0[i] + t * (x1[i] - x0[i]); + } + if ( this->Locator->InsertUniquePoint(x, pts[0]) ) + { + newCellId = newVerts->InsertNextCell(1,pts); + outCd->CopyData(inCd,cellId,newCellId); + p1 = edge->PointIds->GetId(e0); + p2 = edge->PointIds->GetId(e1); + outPd->InterpolateEdge(inPd,pts[0],p1,p2,t); + } //if point not created before + } //if edge straddles contour value + } //for each edge + } //dimension 2 and higher + } //above and below + } //for all cells + cell->Delete(); + + vtkDebugMacro(<<"Created: " << newPts->GetNumberOfPoints() << " points"); + + // Update ourselves. Because we don't know up front how many verts we've + // created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetVerts(newVerts); + newVerts->Delete(); + + this->Locator->Initialize();//free up any extra memory + output->Squeeze(); + + cellScalars->Delete(); + + return 1; +} + +int vtkEdgePoints::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkEdgePoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Contour Value: " << this->Value << "\n"; +} diff --git a/Graphics/vtkEdgePoints.h b/Graphics/vtkEdgePoints.h new file mode 100644 index 0000000..584795a --- /dev/null +++ b/Graphics/vtkEdgePoints.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEdgePoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEdgePoints - generate points on isosurface +// .SECTION Description +// vtkEdgePoints is a filter that takes as input any dataset and +// generates for output a set of points that lie on an isosurface. The +// points are created by interpolation along cells edges whose end-points are +// below and above the contour value. +// .SECTION Caveats +// vtkEdgePoints can be considered a "poor man's" dividing cubes algorithm +// (see vtkDividingCubes). Points are generated only on the edges of cells, +// not in the interior, and at lower density than dividing cubes. However, it +// is more general than dividing cubes since it treats any type of dataset. + +#ifndef __vtkEdgePoints_h +#define __vtkEdgePoints_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkMergePoints; + +class VTK_GRAPHICS_EXPORT vtkEdgePoints : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkEdgePoints,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with contour value of 0.0. + static vtkEdgePoints *New(); + + // Description: + // Set/get the contour value. + vtkSetMacro(Value,double); + vtkGetMacro(Value,double); + +protected: + vtkEdgePoints(); + ~vtkEdgePoints(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + double Value; + vtkMergePoints *Locator; +private: + vtkEdgePoints(const vtkEdgePoints&); // Not implemented. + void operator=(const vtkEdgePoints&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkElevationFilter.cxx b/Graphics/vtkElevationFilter.cxx new file mode 100644 index 0000000..00bf525 --- /dev/null +++ b/Graphics/vtkElevationFilter.cxx @@ -0,0 +1,145 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkElevationFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkElevationFilter.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkSmartPointer.h" + +vtkCxxRevisionMacro(vtkElevationFilter, "$Revision: 1.57.10.1 $"); +vtkStandardNewMacro(vtkElevationFilter); + +//---------------------------------------------------------------------------- +vtkElevationFilter::vtkElevationFilter() +{ + this->LowPoint[0] = 0.0; + this->LowPoint[1] = 0.0; + this->LowPoint[2] = 0.0; + + this->HighPoint[0] = 0.0; + this->HighPoint[1] = 0.0; + this->HighPoint[2] = 1.0; + + this->ScalarRange[0] = 0.0; + this->ScalarRange[1] = 1.0; +} + +//---------------------------------------------------------------------------- +vtkElevationFilter::~vtkElevationFilter() +{ +} + +//---------------------------------------------------------------------------- +void vtkElevationFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Low Point: (" + << this->LowPoint[0] << ", " + << this->LowPoint[1] << ", " + << this->LowPoint[2] << ")\n"; + os << indent << "High Point: (" + << this->HighPoint[0] << ", " + << this->HighPoint[1] << ", " + << this->HighPoint[2] << ")\n"; + os << indent << "Scalar Range: (" + << this->ScalarRange[0] << ", " + << this->ScalarRange[1] << ")\n"; +} + +//---------------------------------------------------------------------------- +int vtkElevationFilter::RequestData(vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // Get the input and output data objects. + vtkDataSet* input = vtkDataSet::GetData(inputVector[0]); + vtkDataSet* output = vtkDataSet::GetData(outputVector); + + // Check the size of the input. + vtkIdType numPts = input->GetNumberOfPoints(); + if(numPts < 1) + { + vtkDebugMacro("No input!"); + return 1; + } + + // Allocate space for the elevation scalar data. + vtkSmartPointer newScalars = + vtkSmartPointer::New(); + newScalars->SetNumberOfTuples(numPts); + + // Set up 1D parametric system and make sure it is valid. + double diffVector[3] = + { this->HighPoint[0] - this->LowPoint[0], + this->HighPoint[1] - this->LowPoint[1], + this->HighPoint[2] - this->LowPoint[2] }; + double length2 = vtkMath::Dot(diffVector, diffVector); + if(length2 <= 0) + { + vtkErrorMacro("Bad vector, using (0,0,1)."); + diffVector[0] = 0; + diffVector[1] = 0; + diffVector[2] = 1; + length2 = 1.0; + } + + // Support progress and abort. + vtkIdType tenth = (numPts >= 10? numPts/10 : 1); + double numPtsInv = 1.0/numPts; + int abort = 0; + + // Compute parametric coordinate and map into scalar range. + double diffScalar = this->ScalarRange[1] - this->ScalarRange[0]; + vtkDebugMacro("Generating elevation scalars!"); + for(vtkIdType i=0; i < numPts && !abort; ++i) + { + // Periodically update progress and check for an abort request. + if(i % tenth == 0) + { + this->UpdateProgress((i+1)*numPtsInv); + abort = this->GetAbortExecute(); + } + + // Project this input point into the 1D system. + double x[3]; + input->GetPoint(i, x); + double v[3] = { x[0] - this->LowPoint[0], + x[1] - this->LowPoint[1], + x[2] - this->LowPoint[2] }; + double s = vtkMath::Dot(v, diffVector) / length2; + s = (s < 0.0 ? 0.0 : s > 1.0 ? 1.0 : s); + + // Store the resulting scalar value. + newScalars->SetValue(i, this->ScalarRange[0] + s*diffScalar); + } + + // Copy all the input geometry and data to the output. + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + // Add the new scalars array to the output. + newScalars->SetName("Elevation"); + output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveScalars("Elevation"); + + return 1; +} diff --git a/Graphics/vtkElevationFilter.h b/Graphics/vtkElevationFilter.h new file mode 100644 index 0000000..6b1e04a --- /dev/null +++ b/Graphics/vtkElevationFilter.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkElevationFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkElevationFilter - generate scalars along a specified direction +// .SECTION Description +// vtkElevationFilter is a filter to generate scalar values from a +// dataset. The scalar values lie within a user specified range, and +// are generated by computing a projection of each dataset point onto +// a line. The line can be oriented arbitrarily. A typical example is +// to generate scalars based on elevation or height above a plane. + +#ifndef __vtkElevationFilter_h +#define __vtkElevationFilter_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkElevationFilter : public vtkDataSetAlgorithm +{ +public: + static vtkElevationFilter* New(); + vtkTypeRevisionMacro(vtkElevationFilter, vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Define one end of the line (small scalar values). Default is + // (0,0,0). + vtkSetVector3Macro(LowPoint,double); + vtkGetVectorMacro(LowPoint,double,3); + + // Description: + // Define other end of the line (large scalar values). Default is + // (0,0,1). + vtkSetVector3Macro(HighPoint,double); + vtkGetVectorMacro(HighPoint,double,3); + + // Description: + // Specify range to map scalars into. Default is [0, 1]. + vtkSetVector2Macro(ScalarRange,double); + vtkGetVectorMacro(ScalarRange,double,2); + +protected: + vtkElevationFilter(); + ~vtkElevationFilter(); + + int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + double LowPoint[3]; + double HighPoint[3]; + double ScalarRange[2]; +private: + vtkElevationFilter(const vtkElevationFilter&); // Not implemented. + void operator=(const vtkElevationFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkEllipticalButtonSource.cxx b/Graphics/vtkEllipticalButtonSource.cxx new file mode 100644 index 0000000..7463017 --- /dev/null +++ b/Graphics/vtkEllipticalButtonSource.cxx @@ -0,0 +1,436 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEllipticalButtonSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEllipticalButtonSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkEllipticalButtonSource, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkEllipticalButtonSource); + +// Construct +vtkEllipticalButtonSource::vtkEllipticalButtonSource() +{ + this->Width = 0.5; + this->Height = 0.5; + this->Depth = 0.05; + + this->CircumferentialResolution = 4; + this->TextureResolution = 2; + this->ShoulderResolution = 2; + + this->RadialRatio = 1.1; +} + +int vtkEllipticalButtonSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int i, j; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Generating elliptical button"); + + // Check input + if ( this->Width <= 0.0 || this->Height <= 0.0 ) + { + vtkErrorMacro(<<"Button must have non-zero height and width"); + return 1; + } + + // Create the button in several steps. First, create the button in + // the x-y plane, this requires creating the texture region and then + // the shoulder region. After this, the z-depth is created. And if + // it is a two-sided button, then a mirror reflection of the button + // in the negative z-direction is created. + int numPts = 1 + this->CircumferentialResolution * + (this->TextureResolution + this->ShoulderResolution + 1); + if ( this->TwoSided ) { numPts *= 2; } + + vtkPoints *newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + + vtkFloatArray *normals = vtkFloatArray::New(); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(numPts); + + vtkFloatArray *tcoords = vtkFloatArray::New(); + tcoords->SetNumberOfComponents(2); + tcoords->SetNumberOfTuples(numPts); + + vtkCellArray *newPolys = vtkCellArray::New(); + newPolys->Allocate(this->CircumferentialResolution* + (this->TextureResolution*this->ShoulderResolution)); + + // Create the texture region. -------------------------------------------- + // Start by determining the resolution in the width and height directions. + // Setup the ellipsoid. + double x[3], x0[3], x1[3], x2[3], x3[3], n[3]; + this->A = this->Width / 2.0; + this->A2 = this->A * this->A; + this->B = this->Height / 2.0; + this->B2 = this->B*this->B; + this->C = this->Depth; + this->C2 = this->C*this->C; + + double xP[3], dX, dY; + if ( this->TextureStyle == VTK_TEXTURE_STYLE_FIT_IMAGE ) + { + dX = (double)this->TextureDimensions[0]; + dY = (double)this->TextureDimensions[1]; + } + else + { + dX = this->A; + dY = this->B; + } + int hRes = ((int)ceil(this->CircumferentialResolution * (dY/(dY+dX)))) / 2; + hRes = (hRes <= 0 ? 1 : hRes); + int wRes = (this->CircumferentialResolution - 2*hRes) / 2; + + // Create the center point + newPts->SetPoint(0,this->Center[0],this->Center[1], + this->Center[2]+this->Depth); + normals->SetTuple3(0, 0.0,0.0,1.0); + tcoords->SetTuple2(0, 0.5, 0.5); + + // Set up for points interior to the texture + int offset = 1 + (this->TextureResolution-1)*this->CircumferentialResolution; + + // Determine the lower-left corner of the texture region + double xe, ye; + double a = this->A/this->RadialRatio; + double b = this->B/this->RadialRatio; + this->IntersectEllipseWithLine(a*a,b*b,dX,dY,xe,ye); + + x0[0] = this->Center[0] - xe; + x0[1] = this->Center[1] - ye; + x0[2] = this->ComputeDepth(1,x0[0],x0[1],n); + newPts->SetPoint(offset, x0); + normals->SetTuple(offset, n); + tcoords->SetTuple2(offset, 0.0, 0.0); + + // Create the lower right point + x1[0] = this->Center[0] + xe; + x1[1] = this->Center[1] - ye; + x1[2] = this->ComputeDepth(1,x1[0],x1[1],n); + newPts->SetPoint(offset + wRes, x1); + normals->SetTuple(offset + wRes, n); + tcoords->SetTuple2(offset + wRes, 1.0, 0.0); + + // Create the upper right point + x2[0] = this->Center[0] + xe; + x2[1] = this->Center[1] + ye; + x2[2] = this->ComputeDepth(1,x2[0],x2[1],n); + newPts->SetPoint(offset + wRes + hRes, x2); + normals->SetTuple(offset + wRes + hRes, n); + tcoords->SetTuple2(offset + wRes + hRes, 1.0, 1.0); + + // Create the upper left point + x3[0] = this->Center[0] - xe; + x3[1] = this->Center[1] + ye; + x3[2] = this->ComputeDepth(1,x3[0],x3[1],n); + newPts->SetPoint(offset + 2*wRes + hRes, x3); + normals->SetTuple(offset + 2*wRes + hRes, n); + tcoords->SetTuple2(offset + 2*wRes + hRes, 0.0, 1.0); + + // Okay, now fill in the points along the edges + double t; + for (i=1; i < wRes; i++) //x0 -> x1 + { + t = (double)i/wRes; + x[0] = x0[0] + t * (x1[0]-x0[0]); + x[1] = x0[1]; + x[2] = this->ComputeDepth(1,x[0],x[1],n); + newPts->SetPoint(offset+i,x); + normals->SetTuple(offset+i,n); + tcoords->SetTuple2(offset+i, t,0.0); + } + for (i=1; i < hRes; i++) //x1 -> x2 + { + t = (double)i/hRes; + x[0] = x1[0]; + x[1] = x1[1] + t * (x2[1]-x1[1]); + x[2] = this->ComputeDepth(1,x[0],x[1],n); + newPts->SetPoint(offset+wRes+i,x); + normals->SetTuple(offset+wRes+i,n); + tcoords->SetTuple2(offset+wRes+i, 1.0,t); + } + for (i=1; i < wRes; i++) //x2 -> x3 + { + t = (double)i/wRes; + x[0] = x2[0] + t * (x3[0]-x2[0]); + x[1] = x2[1]; + x[2] = this->ComputeDepth(1,x[0],x[1],n); + newPts->SetPoint(offset+wRes+hRes+i,x); + normals->SetTuple(offset+wRes+hRes+i,n); + tcoords->SetTuple2(offset+wRes+hRes+i, (1.0-t),1.0); + } + for (i=1; i < hRes; i++) //x3 -> x0 + { + t = (double)i/hRes; + x[0] = x3[0]; + x[1] = x3[1] + t * (x0[1]-x3[1]); + x[2] = this->ComputeDepth(1,x[0],x[1],n); + newPts->SetPoint(offset+2*wRes+hRes+i,x); + normals->SetTuple(offset+2*wRes+hRes+i,n); + tcoords->SetTuple2(offset+2*wRes+hRes+i, 0.0,(1.0-t)); + } + + // Fill in the inside of the texture region + vtkIdType pts[3]; + pts[0] = 0; + for (i=0; i<(this->CircumferentialResolution-1); i++) + { + pts[1] = i + 1; + pts[2] = i + 2; + newPolys->InsertNextCell(3,pts); + } + pts[1] = this->CircumferentialResolution; + pts[2] = 1; + newPolys->InsertNextCell(3,pts); + + if ( this->TextureResolution >= 1 ) + { + this->InterpolateCurve(1, newPts, this->CircumferentialResolution, + normals, tcoords, this->TextureResolution, + 0, 0, offset, 1, 1, 1); + this->CreatePolygons(newPolys, this->CircumferentialResolution, + this->TextureResolution-1, 1); + } + + // Create the shoulder region. -------------------------------------------- + // Start by duplicating points around the texture region. These are + // copied to avoid texture interpolation pollution. + int c1Start = offset + this->CircumferentialResolution; + for ( i=0; i < this->CircumferentialResolution; i++) + { + newPts->SetPoint(c1Start+i, newPts->GetPoint(offset+i)); + normals->SetTuple(c1Start+i, normals->GetTuple(offset+i)); + tcoords->SetTuple(c1Start+i, this->ShoulderTextureCoordinate); + } + + // Now create points around the perimeter of the button. The locations + // of the points (i.e., angles) are taken from the texture region. + int c2Start = offset + (this->ShoulderResolution+1) * + this->CircumferentialResolution; + for ( i=0; i < this->CircumferentialResolution; i++) + { + //compute the angle + newPts->GetPoint(offset+i, xP); + dX = xP[0] - this->Center[0]; + dY = xP[1] - this->Center[1]; + + this->IntersectEllipseWithLine(this->A2,this->B2,dX,dY,xe,ye); + + x[0] = this->Center[0] + xe; + x[1] = this->Center[1] + ye; + x[2] = this->ComputeDepth(0,x[0],x[1],n); + newPts->SetPoint(c2Start+i, x); + normals->SetTuple(c2Start+i, n); + tcoords->SetTuple(c2Start+i, this->ShoulderTextureCoordinate); + } + + // Interpolate points between the curves. Create polygons. + this->InterpolateCurve(0, newPts, this->CircumferentialResolution, + normals, tcoords, this->ShoulderResolution, + c1Start, 1, c2Start, 1, + c1Start+this->CircumferentialResolution, 1); + this->CreatePolygons(newPolys, this->CircumferentialResolution, + this->ShoulderResolution, c1Start); + + // Create the other side of the button if requested. + if ( this->TwoSided > 0.0 ) + { + //do the points + numPts /= 2; + for (i=0; iGetPoint(i, x); + x[0] = -(x[0]-this->Center[0]) + this->Center[0]; + x[2] = -(x[2]-this->Center[2]) + this->Center[2]; + newPts->SetPoint(i+numPts, x); + normals->GetTuple(i, x); + x[0] = -x[0]; + x[2] = -x[2]; + normals->SetTuple(i+numPts, x); + tcoords->SetTuple(i+numPts, tcoords->GetTuple(i)); + } + //do the polygons + vtkIdType *ipts = 0; + vtkIdType opts[4]; + + vtkIdType npts = 0; + int numPolys=newPolys->GetNumberOfCells(); + for ( j=0, newPolys->InitTraversal(); j < numPolys; j++ ) + { + newPolys->GetNextCell(npts,ipts); + for (i=0; iInsertNextCell(npts,opts); + } + } + + // Clean up and get out + output->SetPoints(newPts); + output->GetPointData()->SetNormals(normals); + output->GetPointData()->SetTCoords(tcoords); + output->SetPolys(newPolys); + + newPts->Delete(); + tcoords->Delete(); + normals->Delete(); + newPolys->Delete(); + + return 1; +} + +void vtkEllipticalButtonSource::InterpolateCurve(int inTextureRegion, + vtkPoints *newPts, int numPts, + vtkFloatArray *normals, + vtkFloatArray *tcoords, int res, + int c1StartPt, int c1Incr, + int c2StartPt, int c2Incr, + int startPt, int incr) +{ + int i, j, idx; + double x0[3], x1[3], tc0[3], tc1[3], t, x[3], tc[2], n[3]; + + //walk around the curves interpolating new points between them + for ( i=0; i < numPts; + i++, c1StartPt+=c1Incr, c2StartPt+=c2Incr, startPt+=incr) + { + newPts->GetPoint(c1StartPt, x0); + newPts->GetPoint(c2StartPt, x1); + tcoords->GetTuple(c1StartPt, tc0); + tcoords->GetTuple(c2StartPt, tc1); + + //do the interpolations along this radius + for ( j=1; j < res; j++ ) + { + idx = startPt+(j-1)*numPts; + t = (double)j / res; + x[0] = x0[0] + t * (x1[0] - x0[0]); + x[1] = x0[1] + t * (x1[1] - x0[1]); + x[2] = this->ComputeDepth(inTextureRegion,x[0],x[1],n); + newPts->SetPoint(idx, x); + normals->SetTuple(idx, n); + tc[0] = tc0[0] + t * (tc1[0] - tc0[0]); + tc[1] = tc0[1] + t * (tc1[1] - tc0[1]); + tcoords->SetTuple(idx, tc); + } + }//for all points +} + +void vtkEllipticalButtonSource::CreatePolygons(vtkCellArray *newPolys, int num, int res, + int startIdx) +{ + int i, j; + vtkIdType idx, pts[4]; + + for (i=0; i < res; i++, startIdx+=num) + { + idx = startIdx; + for (j=0; j < num; j++, idx++) + { + pts[0] = idx; + pts[1] = idx + num; + if ( j == (num-1) ) + { + pts[2] = startIdx + num; + pts[3] = startIdx; + } + else + { + pts[2] = idx + num + 1; + pts[3] = idx + 1; + } + newPolys->InsertNextCell(4,pts); + } + } +} + +void vtkEllipticalButtonSource::IntersectEllipseWithLine(double a2, double b2, double dX, + double dY, double& xe, double& ye) +{ + double m; + + if ( fabs(dY) <= fabs(dX) ) + { + m = dY/dX; + xe = sqrt( a2*b2/(b2 + m*m*a2) ); + if ( dX < 0.0 ) xe = -xe; + ye = m*xe; + } + else + { + m = dX/dY; + ye = sqrt( a2*b2/(m*m*b2 + a2) ); + if ( dY < 0.0 ) ye = -ye; + xe = m*ye; + } +} + +double vtkEllipticalButtonSource::ComputeDepth(int vtkNotUsed(inTextureRegion), + double x, double y, double n[3]) +{ + double z; + + x -= this->Center[0]; + y -= this->Center[1]; + z = 1.0 - (x*x)/this->A2 - (y*y)/this->B2; + + if ( z < 0.0 ) n[2] = z = 0.0; + else n[2] = z = this->Depth * sqrt(z); + + n[0] = 2.0*x / this->A2; + n[1] = 2.0*y / this->B2; + n[2] = 2.0*z / this->C2; + + vtkMath::Normalize(n); + + return (z + this->Center[2]); +} + +void vtkEllipticalButtonSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Width: " << this->Width << "\n"; + os << indent << "Height: " << this->Height << "\n"; + os << indent << "Depth: " << this->Depth << "\n"; + + os << indent << "Circumferential Resolution: " + << this->CircumferentialResolution << "\n"; + os << indent << "Texture Resolution: " << this->TextureResolution << "\n"; + os << indent << "Shoulder Resolution: " << this->ShoulderResolution << "\n"; + + os << indent << "Radial Ratio: " << this->RadialRatio << "\n"; + +} diff --git a/Graphics/vtkEllipticalButtonSource.h b/Graphics/vtkEllipticalButtonSource.h new file mode 100644 index 0000000..caadc6a --- /dev/null +++ b/Graphics/vtkEllipticalButtonSource.h @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEllipticalButtonSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEllipticalButtonSource - create a ellipsoidal-shaped button +// .SECTION Description +// vtkEllipticalButtonSource creates a ellipsoidal shaped button with +// texture coordinates suitable for application of a texture map. This +// provides a way to make nice looking 3D buttons. The buttons are +// represented as vtkPolyData that includes texture coordinates and +// normals. The button lies in the x-y plane. +// +// To use this class you must define the major and minor axes lengths of an +// ellipsoid (expressed as width (x), height (y) and depth (z)). The button +// has a rectangular mesh region in the center with texture coordinates that +// range smoothly from (0,1). (This flat region is called the texture +// region.) The outer, curved portion of the button (called the shoulder) has +// texture coordinates set to a user specified value (by default (0,0). +// (This results in coloring the button curve the same color as the (s,t) +// location of the texture map.) The resolution in the radial direction, the +// texture region, and the shoulder region must also be set. The button can +// be moved by specifying an origin. + +#ifndef __vtkEllipticalButtonSource_h +#define __vtkEllipticalButtonSource_h + +#include "vtkButtonSource.h" + +class vtkCellArray; +class vtkFloatArray; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkEllipticalButtonSource : public vtkButtonSource +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkEllipticalButtonSource,vtkButtonSource); + + // Description: + // Construct a circular button with depth 10% of its height. + static vtkEllipticalButtonSource *New(); + + // Description: + // Set/Get the width of the button (the x-ellipsoid axis length * 2). + vtkSetClampMacro(Width,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Width,double); + + // Description: + // Set/Get the height of the button (the y-ellipsoid axis length * 2). + vtkSetClampMacro(Height,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Height,double); + + // Description: + // Set/Get the depth of the button (the z-eliipsoid axis length). + vtkSetClampMacro(Depth,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Depth,double); + + // Description: + // Specify the resolution of the button in the circumferential direction. + vtkSetClampMacro(CircumferentialResolution,int,4,VTK_LARGE_INTEGER); + vtkGetMacro(CircumferentialResolution,int); + + // Description: + // Specify the resolution of the texture in the radial direction in the + // texture region. + vtkSetClampMacro(TextureResolution,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(TextureResolution,int); + + // Description: + // Specify the resolution of the texture in the radial direction in the + // shoulder region. + vtkSetClampMacro(ShoulderResolution,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(ShoulderResolution,int); + + // Description: + // Set/Get the radial ratio. This is the measure of the radius of the + // outer ellipsoid to the inner ellipsoid of the button. The outer + // ellipsoid is the boundary of the button defined by the height and + // width. The inner ellipsoid circumscribes the texture region. Larger + // RadialRatio's cause the button to be more rounded (and the texture + // region to be smaller); smaller ratios produce sharply curved shoulders + // with a larger texture region. + vtkSetClampMacro(RadialRatio,double,1.0,VTK_DOUBLE_MAX); + vtkGetMacro(RadialRatio,double); + +protected: + vtkEllipticalButtonSource(); + ~vtkEllipticalButtonSource() {} + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Width; + double Height; + double Depth; + int CircumferentialResolution; + int TextureResolution; + int ShoulderResolution; + double RadialRatio; + +private: + vtkEllipticalButtonSource(const vtkEllipticalButtonSource&); // Not implemented. + void operator=(const vtkEllipticalButtonSource&); // Not implemented. + + //internal variable related to axes of ellipsoid + double A; + double A2; + double B; + double B2; + double C; + double C2; + + double ComputeDepth(int inTextureRegion, double x, double y, double n[3]); + void InterpolateCurve(int inTextureRegion, vtkPoints *newPts, int numPts, + vtkFloatArray *normals, vtkFloatArray *tcoords, + int res, int c1StartPoint,int c1Incr, + int c2StartPoint,int s2Incr, int startPoint,int incr); + void CreatePolygons(vtkCellArray *newPolys, int num, int res, int startIdx); + void IntersectEllipseWithLine(double a2, double b2, double dX, double dY, + double& xe, double& ye); + + +}; + +#endif + + diff --git a/Graphics/vtkExtractCells.cxx b/Graphics/vtkExtractCells.cxx new file mode 100644 index 0000000..27ef685 --- /dev/null +++ b/Graphics/vtkExtractCells.cxx @@ -0,0 +1,608 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractCells.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkExtractCells.h" + +#include "vtkCellArray.h" +#include "vtkIntArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkModelMetadata.h" +#include "vtkCell.h" +#include "vtkPoints.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkIntArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkExtractCells, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkExtractCells); + +#include +#include + +class vtkExtractCellsSTLCloak +{ +public: + vtkstd::set IdTypeSet; +}; + +vtkExtractCells::vtkExtractCells() +{ + this->SubSetUGridCellArraySize = 0; + this->InputIsUgrid = 0; + this->CellList = new vtkExtractCellsSTLCloak; +} +vtkExtractCells::~vtkExtractCells() +{ + this->SetCellList(NULL); +} + +void vtkExtractCells::SetCellList(vtkIdList *l) +{ + delete this->CellList; + this->CellList = new vtkExtractCellsSTLCloak; + + if (l != NULL) + { + this->AddCellList(l); + } +} +void vtkExtractCells::AddCellList(vtkIdList *l) +{ + if (l == NULL) + { + return; + } + + vtkIdType ncells = l->GetNumberOfIds(); + + if (ncells == 0) + { + return; + } + + for (int i=0; iCellList->IdTypeSet.insert(l->GetId(i)); + } + + this->Modified(); + + return; +} +void vtkExtractCells::AddCellRange(vtkIdType from, vtkIdType to) +{ + if (to < from) return; + + for (vtkIdType id=from; id <= to; id++) + { + this->CellList->IdTypeSet.insert(id); + } + + this->Modified(); + + return; +} +int vtkExtractCells::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + this->InputIsUgrid = + ((vtkUnstructuredGrid::SafeDownCast(input)) != NULL); + + vtkModelMetadata *extractMetadata = this->ExtractMetadata(input); + + int numCellsInput = input->GetNumberOfCells(); + + int numCells = this->CellList->IdTypeSet.size(); + + if (numCells == numCellsInput) + { + #if 0 + this->Copy(input, output); + + if (extractMetadata) + { + vtkModelMetadata::RemoveMetadata((vtkDataSet *)output); + extractMetadata->Pack(output); + extractMetadata->Delete(); + } + return; + #else + // The Copy method seems to have a bug, causing codes using ExtractCells to die + #endif + } + + vtkPointData *PD = input->GetPointData(); + vtkCellData *CD = input->GetCellData(); + + if (numCells == 0) + { + // set up a ugrid with same data arrays as input, but + // no points, cells or data. + + output->Allocate(1); + + output->GetPointData()->CopyAllocate(PD, VTK_CELL_SIZE); + output->GetCellData()->CopyAllocate(CD, 1); + + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(0); + + output->SetPoints(pts); + + pts->Delete(); + + if (extractMetadata) + { + vtkModelMetadata::RemoveMetadata((vtkDataSet *)output); + extractMetadata->Pack(output); + extractMetadata->Delete(); + } + + return 1; + } + vtkPointData *newPD = output->GetPointData(); + vtkCellData *newCD = output->GetCellData(); + + vtkIdList *ptIdMap = reMapPointIds(input); + + vtkIdType numPoints = ptIdMap->GetNumberOfIds(); + + newPD->CopyAllocate(PD, numPoints); + + newCD->CopyAllocate(CD, numCells); + + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(numPoints); + + for (vtkIdType newId =0; newIdGetId(newId); + + pts->SetPoint(newId, input->GetPoint(oldId)); + + newPD->CopyData(PD, oldId, newId); + } + + output->SetPoints(pts); + pts->Delete(); + + if (this->InputIsUgrid) + { + this->CopyCellsUnstructuredGrid(ptIdMap, input, output); + } + else + { + this->CopyCellsDataSet(ptIdMap, input, output); + } + + ptIdMap->Delete(); + + output->Squeeze(); + + if (extractMetadata) + { + vtkModelMetadata::RemoveMetadata((vtkDataSet *)output); + extractMetadata->Pack(output); + extractMetadata->Delete(); + } + + return 1; +} +vtkModelMetadata *vtkExtractCells::ExtractMetadata(vtkDataSet *input) +{ + vtkModelMetadata *extractedMD = NULL; + int numCells = this->CellList->IdTypeSet.size(); + + if (vtkModelMetadata::HasMetadata(input)) + { + if (numCells == input->GetNumberOfCells()) + { + extractedMD = vtkModelMetadata::New(); + extractedMD->Unpack(input, 0); + } + else + { + vtkDataArray *c = input->GetCellData()->GetArray("GlobalElementId"); + vtkDataArray *p = input->GetPointData()->GetArray("GlobalNodeId"); + + if (c && p) + { + vtkIntArray *cgids = vtkIntArray::SafeDownCast(c); + + if (cgids) + { + int *cids = cgids->GetPointer(0); + + vtkIntArray *gids = vtkIntArray::New(); + gids->SetNumberOfValues(numCells); + + int next = 0; + vtkstd::set::iterator cellPtr; + + for (cellPtr = this->CellList->IdTypeSet.begin(); + cellPtr != this->CellList->IdTypeSet.end(); + ++cellPtr) + { + gids->SetValue(next++, cids[*cellPtr]); // global cell IDs + } + + vtkModelMetadata *mmd = vtkModelMetadata::New(); + mmd->Unpack(input, 0); + + extractedMD = mmd->ExtractModelMetadata(gids, + input, "GlobalElementId", "GlobalNodeId"); + + gids->Delete(); + mmd->Delete(); + } + else + { + vtkWarningMacro(<< + "vtkExtractCells: metadata lost, GlobalElementId array is not a vtkIntArray"); + } + } + else + { + vtkWarningMacro(<< + "vtkExtractCells: metadata lost, no GlobalElementId or GlobalNodeId array"); + } + } + } + + return extractedMD; +} + +void vtkExtractCells::Copy(vtkDataSet *input, vtkUnstructuredGrid *output) +{ + int i; + + if (this->InputIsUgrid) + { + output->DeepCopy(vtkUnstructuredGrid::SafeDownCast(input)); + return; + } + + int numCells = input->GetNumberOfCells(); + + vtkPointData *PD = input->GetPointData(); + vtkCellData *CD = input->GetCellData(); + + vtkPointData *newPD = output->GetPointData(); + vtkCellData *newCD = output->GetCellData(); + + int numPoints = input->GetNumberOfPoints(); + + output->Allocate(numCells); + + newPD->CopyAllocate(PD, numPoints); + + newCD->CopyAllocate(CD, numCells); + + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(numPoints); + + for (i=0; iSetPoint(i, input->GetPoint(i)); + } + newPD->DeepCopy(PD); + + output->SetPoints(pts); + + pts->Delete(); + + vtkIdList *cellPoints = vtkIdList::New(); + + for (vtkIdType cellId=0; cellId < numCells; cellId++) + { + input->GetCellPoints(cellId, cellPoints); + + output->InsertNextCell(input->GetCellType(cellId), cellPoints); + } + newCD->DeepCopy(CD); + + cellPoints->Delete(); + + output->Squeeze(); + + return; +} +vtkIdType vtkExtractCells::findInSortedList(vtkIdList *idList, vtkIdType id) +{ + vtkIdType numids = idList->GetNumberOfIds(); + + if (numids < 8) return idList->IsId(id); + + int L, R, M; + L=0; + R=numids-1; + + vtkIdType *ids = idList->GetPointer(0); + + int loc = -1; + + while (R > L) + { + if (R == L+1) + { + if (ids[R] == id) + { + loc = R; + } + else if (ids[L] == id) + { + loc = L; + } + break; + } + + M = (R + L) / 2; + + if (ids[M] > id) + { + R = M; + continue; + } + else if (ids[M] < id) + { + L = M; + continue; + } + else + { + loc = M; + break; + } + } + return loc; +} +vtkIdList *vtkExtractCells::reMapPointIds(vtkDataSet *grid) +{ + int totalPoints = grid->GetNumberOfPoints(); + + char *temp = new char [totalPoints]; + + if (!temp) + { + vtkErrorMacro(<< "vtkExtractCells::reMapPointIds memory allocation"); + return NULL; + } + memset(temp, 0, totalPoints); + + int numberOfIds = 0; + int i; + vtkIdType id; + vtkIdList *ptIds = vtkIdList::New(); + vtkstd::set::iterator cellPtr; + + if (!this->InputIsUgrid) + { + for (cellPtr = this->CellList->IdTypeSet.begin(); + cellPtr != this->CellList->IdTypeSet.end(); + ++cellPtr) + { + grid->GetCellPoints(*cellPtr, ptIds); + + vtkIdType nIds = ptIds->GetNumberOfIds(); + + vtkIdType *ptId = ptIds->GetPointer(0); + + for (i=0; iSubSetUGridCellArraySize = 0; + + vtkIdType *cellArray = ugrid->GetCells()->GetPointer(); + vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0); + + this->SubSetUGridCellArraySize = 0; + vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId(); + + for (cellPtr = this->CellList->IdTypeSet.begin(); + cellPtr != this->CellList->IdTypeSet.end(); + ++cellPtr) + { + if (*cellPtr > maxid) continue; + + int loc = locs[*cellPtr]; + + vtkIdType nIds = cellArray[loc++]; + + this->SubSetUGridCellArraySize += (1 + nIds); + + for (i=0; iSetNumberOfIds(numberOfIds); + int next=0; + + for (id=0; idSetId(next++, id); + } + + delete [] temp; + + return ptIds; +} +void vtkExtractCells::CopyCellsDataSet(vtkIdList *ptMap, vtkDataSet *input, + vtkUnstructuredGrid *output) +{ + output->Allocate(this->CellList->IdTypeSet.size()); + + vtkCellData *oldCD = input->GetCellData(); + vtkCellData *newCD = output->GetCellData(); + + vtkIdList *cellPoints = vtkIdList::New(); + + vtkstd::set::iterator cellPtr; + + for (cellPtr = this->CellList->IdTypeSet.begin(); + cellPtr != this->CellList->IdTypeSet.end(); + ++cellPtr) + { + vtkIdType cellId = *cellPtr; + + input->GetCellPoints(cellId, cellPoints); + + for (int i=0; i < cellPoints->GetNumberOfIds(); i++) + { + vtkIdType oldId = cellPoints->GetId(i); + + vtkIdType newId = vtkExtractCells::findInSortedList(ptMap, oldId); + + cellPoints->SetId(i, newId); + } + int newId = output->InsertNextCell(input->GetCellType(cellId), cellPoints); + + newCD->CopyData(oldCD, cellId, newId); + } + + cellPoints->Delete(); + + return; +} +void vtkExtractCells::CopyCellsUnstructuredGrid(vtkIdList *ptMap, + vtkDataSet *input, + vtkUnstructuredGrid *output) +{ + vtkUnstructuredGrid *ugrid = vtkUnstructuredGrid::SafeDownCast(input); + + if (ugrid == NULL) + { + this->CopyCellsDataSet(ptMap, input, output); + return; + } + + vtkCellData *oldCD = input->GetCellData(); + vtkCellData *newCD = output->GetCellData(); + + int numCells = this->CellList->IdTypeSet.size(); + + vtkCellArray *cellArray = vtkCellArray::New(); // output + vtkIdTypeArray *newcells = vtkIdTypeArray::New(); + newcells->SetNumberOfValues(this->SubSetUGridCellArraySize); + cellArray->SetCells(numCells, newcells); + int cellArrayIdx = 0; + + vtkIdTypeArray *locationArray = vtkIdTypeArray::New(); + locationArray->SetNumberOfValues(numCells); + + vtkUnsignedCharArray *typeArray = vtkUnsignedCharArray::New(); + typeArray->SetNumberOfValues(numCells); + + int nextCellId = 0; + + vtkstd::set::iterator cellPtr; // input + vtkIdType *cells = ugrid->GetCells()->GetPointer(); + vtkIdType maxid = ugrid->GetCellLocationsArray()->GetMaxId(); + vtkIdType *locs = ugrid->GetCellLocationsArray()->GetPointer(0); + vtkUnsignedCharArray *types = ugrid->GetCellTypesArray(); + + for (cellPtr = this->CellList->IdTypeSet.begin(); + cellPtr != this->CellList->IdTypeSet.end(); + ++cellPtr) + { + if (*cellPtr > maxid) continue; + + int oldCellId = *cellPtr; + + int loc = locs[oldCellId]; + int size = (int)cells[loc]; + vtkIdType *pts = cells + loc + 1; + unsigned char type = types->GetValue(oldCellId); + + locationArray->SetValue(nextCellId, cellArrayIdx); + typeArray->SetValue(nextCellId, type); + + newcells->SetValue(cellArrayIdx++, size); + + for (int i=0; iSetValue(cellArrayIdx++, newId); + } + + newCD->CopyData(oldCD, oldCellId, nextCellId); + + nextCellId++; + } + + output->SetCells(typeArray, locationArray, cellArray); + + typeArray->Delete(); + locationArray->Delete(); + newcells->Delete(); + cellArray->Delete(); + + return; +} + +int vtkExtractCells::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkExtractCells::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Graphics/vtkExtractCells.h b/Graphics/vtkExtractCells.h new file mode 100644 index 0000000..b6c13e4 --- /dev/null +++ b/Graphics/vtkExtractCells.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractCells.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkExtractCells - subset a vtkDataSet to create a vtkUnstructuredGrid +// +// .SECTION Description +// Given a vtkDataSet and a list of cell Ids, create a vtkUnstructuredGrid +// composed of these cells. If the cell list is empty when vtkExtractCells +// executes, it will set up the ugrid, point and cell arrays, with no points, +// cells or data. + +#ifndef __vtkExtractCells_h +#define __vtkExtractCells_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkIdList; +class vtkExtractCellsSTLCloak; +class vtkModelMetadata; + +class VTK_GRAPHICS_EXPORT vtkExtractCells : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkExtractCells, vtkUnstructuredGridAlgorithm); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + static vtkExtractCells *New(); + + // Description: + // Set the list of cell IDs that the output vtkUnstructuredGrid + // will be composed of. Replaces any other cell ID list supplied + // so far. (Set to NULL to free memory used by cell list.) + + void SetCellList(vtkIdList *l); + + // Description: + // Add the supplied list of cell IDs to those that will be included + // in the output vtkUnstructuredGrid. + + void AddCellList(vtkIdList *l); + + // Description: + // Add this range of cell IDs to those that will be included + // in the output vtkUnstructuredGrid. + + void AddCellRange(vtkIdType from, vtkIdType to); + +protected: + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkExtractCells(); + ~vtkExtractCells(); + +private: + + void Copy(vtkDataSet *input, vtkUnstructuredGrid *output); + static vtkIdType findInSortedList(vtkIdList *idList, vtkIdType id); + vtkIdList *reMapPointIds(vtkDataSet *grid); + + vtkModelMetadata *ExtractMetadata(vtkDataSet *input); + + void CopyCellsDataSet(vtkIdList *ptMap, vtkDataSet *input, + vtkUnstructuredGrid *output); + void CopyCellsUnstructuredGrid(vtkIdList *ptMap, vtkDataSet *input, + vtkUnstructuredGrid *output); + + vtkExtractCellsSTLCloak *CellList; + + int SubSetUGridCellArraySize; + char InputIsUgrid; + + vtkExtractCells(const vtkExtractCells&); // Not implemented + void operator=(const vtkExtractCells&); // Not implemented +}; + +#endif diff --git a/Graphics/vtkExtractDataOverTime.cxx b/Graphics/vtkExtractDataOverTime.cxx new file mode 100644 index 0000000..47980d2 --- /dev/null +++ b/Graphics/vtkExtractDataOverTime.cxx @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractDataOverTime.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractDataOverTime.h" + +#include "vtkPointSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkDoubleArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkExtractDataOverTime, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkExtractDataOverTime); + +//---------------------------------------------------------------------------- +vtkExtractDataOverTime::vtkExtractDataOverTime() +{ + this->NumberOfTimeSteps = 0; + this->CurrentTimeIndex = 0; + this->PointIndex = 0; + +} + +//---------------------------------------------------------------------------- +void vtkExtractDataOverTime::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Point Index: " << this->PointIndex << endl; + os << indent << "NumberOfTimeSteps: " << this->NumberOfTimeSteps << endl; +} + + +//---------------------------------------------------------------------------- +int vtkExtractDataOverTime::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + if ( outInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()) ) + { + this->NumberOfTimeSteps = + outInfo->Length( vtkStreamingDemandDrivenPipeline::TIME_STEPS() ); + } + else + { + this->NumberOfTimeSteps = 0; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkExtractDataOverTime::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + else if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + // get the requested update extent + inputVector[0]->GetInformationObject(0)->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_TIME_INDEX(), this->CurrentTimeIndex ); + + return 1; + } + + // generate the data + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + if (this->NumberOfTimeSteps == 0) + { + vtkErrorMacro("No Time steps in input time data!"); + return 0; + } + + // get the output data object + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkPointSet *output = + vtkPointSet::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // and input data object + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkPointSet *input = + vtkPointSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // is this the first request + if (!this->CurrentTimeIndex) + { + // Tell the pipeline to start looping. + request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); + this->AllocateOutputData(input, output); + } + + // extract the actual data + output->GetPoints()->SetPoint( this->CurrentTimeIndex, + input->GetPoints()->GetPoint(this->PointIndex) ); + output->GetPointData()->CopyData(input->GetPointData(), this->PointIndex, + this->CurrentTimeIndex); + if (input->GetPointData()->GetArray("Time")) + { + output->GetPointData()->GetArray("TimeData")->SetTuple1( + this->CurrentTimeIndex, + input->GetInformation()->Get(vtkDataObject::DATA_TIME()) ); + } + else + { + output->GetPointData()->GetArray("Time")->SetTuple1( + this->CurrentTimeIndex, + input->GetInformation()->Get(vtkDataObject::DATA_TIME()) ); + } + + + // increment the time index + this->CurrentTimeIndex++; + if (this->CurrentTimeIndex == this->NumberOfTimeSteps) + { + // Tell the pipeline to stop looping. + request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); + this->CurrentTimeIndex = 0; + } + + return 1; + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkExtractDataOverTime::AllocateOutputData(vtkPointSet *input, vtkPointSet *output) +{ + // by default vtkPointSetAlgorithm::RequestDataObject already + // created an output of the same type as the input + if (!output) + { + vtkErrorMacro("Output not created as expected!"); + return 0; + } + + // 1st the points + vtkPoints *points = output->GetPoints(); + if (!points) + { + points = vtkPoints::New(); + output->SetPoints( points ); + points->Delete(); + } + points->SetNumberOfPoints( this->NumberOfTimeSteps ); + + // now the point data + output->GetPointData()->CopyAllocate(input->GetPointData(), this->NumberOfTimeSteps); + + // and finally add an array to hold the time at each step + vtkDoubleArray *timeArray = vtkDoubleArray::New(); + timeArray->SetNumberOfComponents(1); + timeArray->SetNumberOfTuples(this->NumberOfTimeSteps); + if (input->GetPointData()->GetArray("Time")) + { + timeArray->SetName("TimeData"); + } + else + { + timeArray->SetName("Time"); + } + output->GetPointData()->AddArray(timeArray); + timeArray->Delete(); + + return 1; +} + + diff --git a/Graphics/vtkExtractDataOverTime.h b/Graphics/vtkExtractDataOverTime.h new file mode 100644 index 0000000..dac89fe --- /dev/null +++ b/Graphics/vtkExtractDataOverTime.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractDataOverTime.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractDataOverTime - extract point data from a time sequence for +// a specified point id. +// .SECTION Description +// This filter extracts the point data from a time sequence and specified index +// and creates an output of the same type as the input but with Points +// containing "number of time steps" points; the point and PointData +// corresponding to the PointIndex are extracted at each time step and added to +// the output. A PointData array is added called "Time" (or "TimeData" if +// there is already an array called "Time"), which is the time at each index. + +#ifndef __vtkExtractDataOverTime_h +#define __vtkExtractDataOverTime_h + +#include "vtkPointSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkExtractDataOverTime : public vtkPointSetAlgorithm +{ +public: + static vtkExtractDataOverTime *New(); + vtkTypeRevisionMacro(vtkExtractDataOverTime,vtkPointSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Index of point to extract at each time step + vtkSetMacro(PointIndex,int); + vtkGetMacro(PointIndex,int); + + // Description: + // Get the number of time steps + vtkGetMacro(NumberOfTimeSteps,int); + +protected: + vtkExtractDataOverTime(); + ~vtkExtractDataOverTime() {}; + + int RequestInformation( vtkInformation *request, + vtkInformationVector **inputVector, vtkInformationVector *outputVector); + + int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + int AllocateOutputData(vtkPointSet *input, vtkPointSet *output); + + int PointIndex; + int CurrentTimeIndex; + int NumberOfTimeSteps; + +private: + vtkExtractDataOverTime(const vtkExtractDataOverTime&); // Not implemented. + void operator=(const vtkExtractDataOverTime&); // Not implemented. +}; + +#endif + + + diff --git a/Graphics/vtkExtractEdges.cxx b/Graphics/vtkExtractEdges.cxx new file mode 100644 index 0000000..da786cb --- /dev/null +++ b/Graphics/vtkExtractEdges.cxx @@ -0,0 +1,270 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractEdges.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractEdges.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkEdgeTable.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkExtractEdges, "$Revision: 1.53 $"); +vtkStandardNewMacro(vtkExtractEdges); + +// Construct object. +vtkExtractEdges::vtkExtractEdges() +{ + this->Locator = NULL; +} + +vtkExtractEdges::~vtkExtractEdges() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +// Generate feature edges for mesh +int vtkExtractEdges::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *newPts; + vtkCellArray *newLines; + vtkIdType numCells, cellNum, numPts, newId; + int edgeNum, numEdgePts, numCellEdges; + int i, abort = 0; + vtkIdType pts[2]; + vtkIdType pt1 = 0, pt2; + double x[3]; + vtkEdgeTable *edgeTable; + vtkGenericCell *cell; + vtkCell *edge; + vtkPointData *pd, *outPD; + vtkCellData *cd, *outCD; + + vtkDebugMacro(<<"Executing edge extractor"); + + // Check input + // + numPts=input->GetNumberOfPoints(); + if ( (numCells=input->GetNumberOfCells()) < 1 || numPts < 1 ) + { + return 1; + } + + // Set up processing + // + edgeTable = vtkEdgeTable::New(); + edgeTable->InitEdgeInsertion(numPts); + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + newLines = vtkCellArray::New(); + newLines->EstimateSize(numPts*4,2); + + pd = input->GetPointData(); + outPD = output->GetPointData(); + outPD->CopyAllocate(pd,numPts); + + cd = input->GetCellData(); + outCD = output->GetCellData(); + outCD->CopyAllocate(cd,numCells); + + cell = vtkGenericCell::New(); + vtkIdList *edgeIds, *HEedgeIds=vtkIdList::New(); + vtkPoints *edgePts, *HEedgePts=vtkPoints::New(); + + // Get our locator for merging points + // + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + + // Loop over all cells, extracting non-visited edges. + // + int tenth = numCells/10 + 1; + for (cellNum=0; cellNum < numCells && !abort; cellNum++ ) + { + if ( ! (cellNum % tenth) ) //manage progress reports / early abort + { + this->UpdateProgress ((double)cellNum / numCells); + abort = this->GetAbortExecute(); + } + + input->GetCell(cellNum,cell); + numCellEdges = cell->GetNumberOfEdges(); + for (edgeNum=0; edgeNum < numCellEdges; edgeNum++ ) + { + edge = cell->GetEdge(edgeNum); + numEdgePts = edge->GetNumberOfPoints(); + + // Tessellate higher-order edges + if ( ! edge->IsLinear() ) + { + edge->Triangulate(0, HEedgeIds, HEedgePts); + edgeIds = HEedgeIds; + edgePts = HEedgePts; + + for ( i=0; i < (edgeIds->GetNumberOfIds()/2); i++ ) + { + pt1 = edgeIds->GetId(2*i); + pt2 = edgeIds->GetId(2*i+1); + edgePts->GetPoint(2*i, x); + if ( this->Locator->InsertUniquePoint(x, pts[0]) ) + { + outPD->CopyData (pd,pt1,pts[0]); + } + edgePts->GetPoint(2*i+1, x); + if ( this->Locator->InsertUniquePoint(x, pts[1]) ) + { + outPD->CopyData (pd,pt2,pts[1]); + } + if ( edgeTable->IsEdge(pt1,pt2) == -1 ) + { + edgeTable->InsertEdge(pt1, pt2); + newId = newLines->InsertNextCell(2,pts); + outCD->CopyData(cd, cellNum, newId); + } + } + } //if non-linear edge + + else // linear edges + { + edgeIds = edge->PointIds; + edgePts = edge->Points; + + for ( i=0; i < numEdgePts; i++, pt1=pt2, pts[0]=pts[1] ) + { + pt2 = edgeIds->GetId(i); + edgePts->GetPoint(i, x); + if ( this->Locator->InsertUniquePoint(x, pts[1]) ) + { + outPD->CopyData (pd,pt2,pts[1]); + } + if ( i > 0 && edgeTable->IsEdge(pt1,pt2) == -1 ) + { + edgeTable->InsertEdge(pt1, pt2); + newId = newLines->InsertNextCell(2,pts); + outCD->CopyData(cd, cellNum, newId); + } + }//if linear edge + } + }//for all edges of cell + }//for all cells + + vtkDebugMacro(<<"Created " << newLines->GetNumberOfCells() << " edges"); + + // Update ourselves. + // + HEedgeIds->Delete(); + HEedgePts->Delete(); + edgeTable->Delete(); + cell->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + output->Squeeze(); + + return 1; +} + +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkExtractEdges::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkExtractEdges::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + vtkMergePoints *locator = vtkMergePoints::New(); + this->SetLocator(locator); + locator->Delete(); + } +} + +int vtkExtractEdges::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkExtractEdges::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +unsigned long int vtkExtractEdges::GetMTime() +{ + unsigned long mTime=this-> Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} diff --git a/Graphics/vtkExtractEdges.h b/Graphics/vtkExtractEdges.h new file mode 100644 index 0000000..cd86b9e --- /dev/null +++ b/Graphics/vtkExtractEdges.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractEdges.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractEdges - extract cell edges from any type of data +// .SECTION Description +// vtkExtractEdges is a filter to extract edges from a dataset. Edges +// are extracted as lines or polylines. + +// .SECTION See Also +// vtkFeatureEdges + +#ifndef __vtkExtractEdges_h +#define __vtkExtractEdges_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkExtractEdges : public vtkPolyDataAlgorithm +{ +public: + static vtkExtractEdges *New(); + vtkTypeRevisionMacro(vtkExtractEdges,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + + // Description: + // Return MTime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkExtractEdges(); + ~vtkExtractEdges(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkPointLocator *Locator; +private: + vtkExtractEdges(const vtkExtractEdges&); // Not implemented. + void operator=(const vtkExtractEdges&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkExtractGeometry.cxx b/Graphics/vtkExtractGeometry.cxx new file mode 100644 index 0000000..3dfeb81 --- /dev/null +++ b/Graphics/vtkExtractGeometry.cxx @@ -0,0 +1,293 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractGeometry.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractGeometry.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkExtractGeometry, "$Revision: 1.57 $"); +vtkStandardNewMacro(vtkExtractGeometry); +vtkCxxSetObjectMacro(vtkExtractGeometry,ImplicitFunction,vtkImplicitFunction); + +// Construct object with ExtractInside turned on. +vtkExtractGeometry::vtkExtractGeometry(vtkImplicitFunction *f) +{ + this->ImplicitFunction = f; + if (this->ImplicitFunction) + { + this->ImplicitFunction->Register(this); + } + + this->ExtractInside = 1; + this->ExtractBoundaryCells = 0; + this->ExtractOnlyBoundaryCells = 0; +} + +vtkExtractGeometry::~vtkExtractGeometry() +{ + this->SetImplicitFunction(NULL); +} + +// Overload standard modified time function. If implicit function is modified, +// then this object is modified as well. +unsigned long vtkExtractGeometry::GetMTime() +{ + unsigned long mTime=this->MTime.GetMTime(); + unsigned long impFuncMTime; + + if ( this->ImplicitFunction != NULL ) + { + impFuncMTime = this->ImplicitFunction->GetMTime(); + mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime ); + } + + return mTime; +} + +int vtkExtractGeometry::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType ptId, numPts, numCells, i, cellId, newCellId, newId, *pointMap; + vtkIdList *cellPts; + vtkCell *cell; + int numCellPts; + double x[3]; + double multiplier; + vtkPoints *newPts; + vtkIdList *newCellPts; + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + int npts; + + vtkDebugMacro(<< "Extracting geometry"); + + if ( ! this->ImplicitFunction ) + { + vtkErrorMacro(<<"No implicit function specified"); + return 1; + } + + newCellPts = vtkIdList::New(); + newCellPts->Allocate(VTK_CELL_SIZE); + + if ( this->ExtractInside ) + { + multiplier = 1.0; + } + else + { + multiplier = -1.0; + } + + // Loop over all points determining whether they are inside the + // implicit function. Copy the points and point data if they are. + // + numPts = input->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + pointMap = new vtkIdType[numPts]; // maps old point ids into new + for (i=0; i < numPts; i++) + { + pointMap[i] = -1; + } + + output->Allocate(numCells/4); //allocate storage for geometry/topology + newPts = vtkPoints::New(); + newPts->Allocate(numPts/4,numPts); + outputPD->CopyAllocate(pd); + outputCD->CopyAllocate(cd); + vtkFloatArray *newScalars = NULL; + + if ( ! this->ExtractBoundaryCells ) + { + for ( ptId=0; ptId < numPts; ptId++ ) + { + input->GetPoint(ptId, x); + if ( (this->ImplicitFunction->FunctionValue(x)*multiplier) < 0.0 ) + { + newId = newPts->InsertNextPoint(x); + pointMap[ptId] = newId; + outputPD->CopyData(pd,ptId,newId); + } + } + } + else + { + // To extract boundary cells, we have to create supplemental information + double val; + newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfValues(numPts); + + for (ptId=0; ptId < numPts; ptId++ ) + { + input->GetPoint(ptId, x); + val = this->ImplicitFunction->FunctionValue(x) * multiplier; + newScalars->SetValue(ptId, val); + if ( val < 0.0 ) + { + newId = newPts->InsertNextPoint(x); + pointMap[ptId] = newId; + outputPD->CopyData(pd,ptId,newId); + } + } + } + + // Now loop over all cells to see whether they are inside implicit + // function (or on boundary if ExtractBoundaryCells is on). + // + for (cellId=0; cellId < numCells; cellId++) + { + cell = input->GetCell(cellId); + cellPts = cell->GetPointIds(); + numCellPts = cell->GetNumberOfPoints(); + + newCellPts->Reset(); + if ( ! this->ExtractBoundaryCells ) //requires less work + { + for ( npts=0, i=0; i < numCellPts; i++, npts++) + { + ptId = cellPts->GetId(i); + if ( pointMap[ptId] < 0 ) + { + break; //this cell won't be inserted + } + else + { + newCellPts->InsertId(i,pointMap[ptId]); + } + } + } //if don't want to extract boundary cells + + else //want boundary cells + { + for ( npts=0, i=0; i < numCellPts; i++ ) + { + ptId = cellPts->GetId(i); + if ( newScalars->GetValue(ptId) <= 0.0 ) + { + npts++; + } + } + int extraction_condition = 0; + if ( this->ExtractOnlyBoundaryCells ) + { + if ( ( npts > 0 ) && ( npts != numCellPts ) ) + { + extraction_condition = 1; + } + } + else + { + if ( npts > 0 ) + { + extraction_condition = 1; + } + } + if ( extraction_condition ) + { + for ( i=0; i < numCellPts; i++ ) + { + ptId = cellPts->GetId(i); + if ( pointMap[ptId] < 0 ) + { + input->GetPoint(ptId, x); + newId = newPts->InsertNextPoint(x); + pointMap[ptId] = newId; + outputPD->CopyData(pd,ptId,newId); + } + newCellPts->InsertId(i,pointMap[ptId]); + } + }//a boundary or interior cell + }//if mapping boundary cells + + int extraction_condition = 0; + if ( this->ExtractOnlyBoundaryCells ) + { + if ( npts != numCellPts && (this->ExtractBoundaryCells && npts > 0) ) + { + extraction_condition = 1; + } + } + else + { + if ( npts >= numCellPts || (this->ExtractBoundaryCells && npts > 0) ) + { + extraction_condition = 1; + } + } + if ( extraction_condition ) + { + newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts); + outputCD->CopyData(cd,cellId,newCellId); + } + }//for all cells + + // Update ourselves and release memory + // + delete [] pointMap; + newCellPts->Delete(); + output->SetPoints(newPts); + newPts->Delete(); + + if ( this->ExtractBoundaryCells ) + { + newScalars->Delete(); + } + + output->Squeeze(); + + return 1; +} + +int vtkExtractGeometry::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkExtractGeometry::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Implicit Function: " + << (void *)this->ImplicitFunction << "\n"; + os << indent << "Extract Inside: " + << (this->ExtractInside ? "On\n" : "Off\n"); + os << indent << "Extract Boundary Cells: " + << (this->ExtractBoundaryCells ? "On\n" : "Off\n"); + os << indent << "Extract Only Boundary Cells: " + << (this->ExtractOnlyBoundaryCells ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkExtractGeometry.h b/Graphics/vtkExtractGeometry.h new file mode 100644 index 0000000..a2a1063 --- /dev/null +++ b/Graphics/vtkExtractGeometry.h @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractGeometry.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractGeometry - extract cells that lie either entirely inside or outside of a specified implicit function + +// .SECTION Description +// vtkExtractGeometry extracts from its input dataset all cells that are either +// completely inside or outside of a specified implicit function. Any type of +// dataset can be input to this filter. On output the filter generates an +// unstructured grid. +// +// To use this filter you must specify an implicit function. You must also +// specify whethter to extract cells lying inside or outside of the implicit +// function. (The inside of an implicit function is the negative values +// region.) An option exists to extract cells that are neither inside or +// outside (i.e., boundary). +// +// A more efficient version of this filter is available for vtkPolyData input. +// See vtkExtractPolyDataGeometry. + +// .SECTION See Also +// vtkExtractPolyDataGeometry vtkGeometryFilter vtkExtractVOI + +#ifndef __vtkExtractGeometry_h +#define __vtkExtractGeometry_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkImplicitFunction; + +class VTK_GRAPHICS_EXPORT vtkExtractGeometry : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkExtractGeometry,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with ExtractInside turned on. + static vtkExtractGeometry *New(); + + // Description: + // Return the MTime taking into account changes to the implicit function + unsigned long GetMTime(); + + // Description: + // Specify the implicit function for inside/outside checks. + virtual void SetImplicitFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ImplicitFunction,vtkImplicitFunction); + + // Description: + // Boolean controls whether to extract cells that are inside of implicit + // function (ExtractInside == 1) or outside of implicit function + // (ExtractInside == 0). + vtkSetMacro(ExtractInside,int); + vtkGetMacro(ExtractInside,int); + vtkBooleanMacro(ExtractInside,int); + + // Description: + // Boolean controls whether to extract cells that are partially inside. + // By default, ExtractBoundaryCells is off. + vtkSetMacro(ExtractBoundaryCells,int); + vtkGetMacro(ExtractBoundaryCells,int); + vtkBooleanMacro(ExtractBoundaryCells,int); + vtkSetMacro(ExtractOnlyBoundaryCells,int); + vtkGetMacro(ExtractOnlyBoundaryCells,int); + vtkBooleanMacro(ExtractOnlyBoundaryCells,int); + +protected: + vtkExtractGeometry(vtkImplicitFunction *f=NULL); + ~vtkExtractGeometry(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkImplicitFunction *ImplicitFunction; + int ExtractInside; + int ExtractBoundaryCells; + int ExtractOnlyBoundaryCells; + +private: + vtkExtractGeometry(const vtkExtractGeometry&); // Not implemented. + void operator=(const vtkExtractGeometry&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkExtractGrid.cxx b/Graphics/vtkExtractGrid.cxx new file mode 100644 index 0000000..8f47178 --- /dev/null +++ b/Graphics/vtkExtractGrid.cxx @@ -0,0 +1,422 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractGrid.h" + +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" + +vtkCxxRevisionMacro(vtkExtractGrid, "$Revision: 1.44 $"); +vtkStandardNewMacro(vtkExtractGrid); + +// Construct object to extract all of the input data. +vtkExtractGrid::vtkExtractGrid() +{ + this->VOI[0] = this->VOI[2] = this->VOI[4] = 0; + this->VOI[1] = this->VOI[3] = this->VOI[5] = VTK_LARGE_INTEGER; + + this->SampleRate[0] = this->SampleRate[1] = this->SampleRate[2] = 1; + + this->IncludeBoundary = 0; +} + +int vtkExtractGrid::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int i, ext[6], voi[6]; + int *inWholeExt, *outWholeExt, *updateExt; + int rate[3]; + + inWholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + outWholeExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + updateExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + for (i = 0; i < 3; ++i) + { + rate[i] = this->SampleRate[i]; + if (rate[i] < 1) + { + rate[i] = 1; + } + } + + // Once again, clip the VOI with the input whole extent. + for (i = 0; i < 3; ++i) + { + voi[i*2] = this->VOI[2*i]; + if (voi[2*i] < inWholeExt[2*i]) + { + voi[2*i] = inWholeExt[2*i]; + } + voi[i*2+1] = this->VOI[2*i+1]; + if (voi[2*i+1] > inWholeExt[2*i+1]) + { + voi[2*i+1] = inWholeExt[2*i+1]; + } + } + + ext[0] = voi[0] + (updateExt[0]-outWholeExt[0])*rate[0]; + ext[1] = voi[0] + (updateExt[1]-outWholeExt[0])*rate[0]; + if (ext[1] > voi[1]) + { // This handles the IncludeBoundary condition. + ext[1] = voi[1]; + } + ext[2] = voi[2] + (updateExt[2]-outWholeExt[2])*rate[1]; + ext[3] = voi[2] + (updateExt[3]-outWholeExt[2])*rate[1]; + if (ext[3] > voi[3]) + { // This handles the IncludeBoundary condition. + ext[3] = voi[3]; + } + ext[4] = voi[4] + (updateExt[4]-outWholeExt[4])*rate[2]; + ext[5] = voi[4] + (updateExt[5]-outWholeExt[4])*rate[2]; + if (ext[5] > voi[5]) + { // This handles the IncludeBoundary condition. + ext[5] = voi[5]; + } + + // I do not think we need this extra check, but it cannot hurt. + if (ext[0] < inWholeExt[0]) + { + ext[0] = inWholeExt[0]; + } + if (ext[1] > inWholeExt[1]) + { + ext[1] = inWholeExt[1]; + } + + if (ext[2] < inWholeExt[2]) + { + ext[2] = inWholeExt[2]; + } + if (ext[3] > inWholeExt[3]) + { + ext[3] = inWholeExt[3]; + } + + if (ext[4] < inWholeExt[4]) + { + ext[4] = inWholeExt[4]; + } + if (ext[5] > inWholeExt[5]) + { + ext[5] = inWholeExt[5]; + } + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + // We can handle anything. + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 0); + + return 1; +} + +int vtkExtractGrid::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int i, outDims[3], voi[6], wholeExtent[6]; + int mins[3]; + int rate[3]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + + // Copy because we need to take union of voi and whole extent. + for ( i=0; i < 6; i++ ) + { + voi[i] = this->VOI[i]; + } + + for ( i=0; i < 3; i++ ) + { + // Empty request. + if (voi[2*i+1] < voi[2*i] || voi[2*i+1] < wholeExtent[2*i] || + voi[2*i] > wholeExtent[2*i+1]) + { + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0,-1,0,-1,0,-1); + return 1; + } + + // Make sure VOI is in the whole extent. + if ( voi[2*i+1] > wholeExtent[2*i+1] ) + { + voi[2*i+1] = wholeExtent[2*i+1]; + } + else if ( voi[2*i+1] < wholeExtent[2*i] ) + { + voi[2*i+1] = wholeExtent[2*i]; + } + if ( voi[2*i] > wholeExtent[2*i+1] ) + { + voi[2*i] = wholeExtent[2*i+1]; + } + else if ( voi[2*i] < wholeExtent[2*i] ) + { + voi[2*i] = wholeExtent[2*i]; + } + + if ( (rate[i] = this->SampleRate[i]) < 1 ) + { + rate[i] = 1; + } + + outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1; + if ( outDims[i] < 1 ) + { + outDims[i] = 1; + } + // We might as well make this work for negative extents. + mins[i] = (int)(floor((float)voi[2*i] / (float)rate[i])); + } + + // Adjust the output dimensions if the boundaries are to be + // included and the sample rate is not 1. + if ( this->IncludeBoundary && + (rate[0] != 1 || rate[1] != 1 || rate[2] != 1) ) + { + int diff; + for (i=0; i<3; i++) + { + if ( ((diff=voi[2*i+1]-voi[2*i]) > 0) && rate[i] != 1 && + ((diff % rate[i]) != 0) ) + { + outDims[i]++; + } + } + } + + // Set the whole extent of the output + wholeExtent[0] = mins[0]; + wholeExtent[1] = mins[0] + outDims[0] - 1; + wholeExtent[2] = mins[1]; + wholeExtent[3] = mins[1] + outDims[1] - 1; + wholeExtent[4] = mins[2]; + wholeExtent[5] = mins[2] + outDims[2] - 1; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + wholeExtent, 6); + + return 1; +} + +int vtkExtractGrid::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(); + vtkCellData *cd=input->GetCellData(); + vtkPointData *outPD=output->GetPointData(); + vtkCellData *outCD=output->GetCellData(); + int i, j, k, uExt[6], voi[6]; + int *inExt; + int *inWholeExt; + int iIn, jIn, kIn; + int outSize, jOffset, kOffset, rate[3]; + vtkIdType idx, newIdx, newCellId; + vtkPoints *newPts, *inPts; + int inInc1, inInc2; + // Function to convert output index to input index f(i) = Rate*I + shift + int shift[3]; + + vtkDebugMacro(<< "Extracting Grid"); + + inPts = input->GetPoints(); + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExt); + inExt = input->GetExtent(); + inInc1 = (inExt[1]-inExt[0]+1); + inInc2 = inInc1*(inExt[3]-inExt[2]+1); + + for (i = 0; i < 3; ++i) + { + if ( (rate[i] = this->SampleRate[i]) < 1 ) + { + rate[i] = 1; + } + } + + // Clip the VOI by the input whole extent + inWholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + for (i = 0; i < 3; ++i) + { + voi[i*2] = this->VOI[2*i]; + if (voi[2*i] < inWholeExt[2*i]) + { + voi[2*i] = inWholeExt[2*i]; + } + voi[i*2+1] = this->VOI[2*i+1]; + if (voi[2*i+1] > inWholeExt[2*i+1]) + { + voi[2*i+1] = inWholeExt[2*i+1]; + } + } + + // Compute the shift. + // The shift is necessary because the starting VOI may not be on stride boundary. + // We need to duplicate the computation done in + // ExecuteInformtation for the output whole extent. + // Use shift as temporary variable (output mins). + shift[0] = (int)(floor( (float)(voi[0])/(float)(rate[0]) )); + shift[1] = (int)(floor( (float)(voi[2])/(float)(rate[1]) )); + shift[2] = (int)(floor( (float)(voi[4])/(float)(rate[2]) )); + // Take the different between the output and input mins (in input coordinates). + shift[0] = voi[0] - (shift[0]*rate[0]); + shift[1] = voi[2] - (shift[1]*rate[1]); + shift[2] = voi[4] - (shift[2]*rate[2]); + + output->SetExtent(uExt); + + // If output same as input, just pass data through + if ( uExt[0] <= inExt[0] && uExt[1] >= inExt[1] && + uExt[2] <= inExt[2] && uExt[3] >= inExt[3] && + uExt[4] <= inExt[4] && uExt[5] >= inExt[5] && + rate[0] == 1 && rate[1] == 1 && rate[2] == 1) + { + output->SetPoints(inPts); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + vtkDebugMacro(<<"Passed data through bacause input and output are the same"); + return 1; + } + + // Allocate necessary objects + // + outSize = (uExt[1]-uExt[0]+1)*(uExt[3]-uExt[2]+1)*(uExt[5]-uExt[4]+1); + newPts = inPts->NewInstance(); + newPts->SetDataType(inPts->GetDataType()); + newPts->SetNumberOfPoints(outSize); + outPD->CopyAllocate(pd,outSize,outSize); + outCD->CopyAllocate(cd,outSize,outSize); + + // Traverse input data and copy point attributes to output + // iIn,jIn,kIn are in input grid coordinates. + newIdx = 0; + for ( k=uExt[4]; k <= uExt[5]; ++k) + { // Convert out coords to in coords. + kIn = shift[2] + (k*rate[2]); + if (kIn > voi[5]) + { // This handles the IncludeBoundaryOn condition. + kIn = voi[5]; + } + kOffset = (kIn-inExt[4]) * inInc2; + for ( j=uExt[2]; j <= uExt[3]; ++j) + { // Convert out coords to in coords. + jIn = shift[1] + (j*rate[1]); + if (jIn > voi[3]) + { // This handles the IncludeBoundaryOn condition. + jIn = voi[3]; + } + jOffset = (jIn-inExt[2]) * inInc1; + for ( i=uExt[0]; i <= uExt[1]; ++i) + { // Convert out coords to in coords. + iIn = shift[0] + (i*rate[0]); + if (iIn > voi[1]) + { // This handles the IncludeBoundaryOn condition. + iIn = voi[1]; + } + idx = (iIn-inExt[0]) + jOffset + kOffset; + newPts->SetPoint(newIdx,inPts->GetPoint(idx)); + outPD->CopyData(pd, idx, newIdx++); + } + } + } + + // Traverse input data and copy cell attributes to output + // + newCellId = 0; + inInc1 = (inExt[1]-inExt[0]); + inInc2 = inInc1*(inExt[3]-inExt[2]); + // This will take care of 2D and 1D cells. + // Each loop has to excute at least once. + if (uExt[4] == uExt[5]) + { + uExt[5] = uExt[5] + 1; + } + if (uExt[2] == uExt[3]) + { + uExt[3] = uExt[3] + 1; + } + if (uExt[0] == uExt[1]) + { + uExt[1] = uExt[1] + 1; + } + // No need to consider IncludeBoundary for cell data. + for ( k=uExt[4]; k < uExt[5]; ++k ) + { // Convert out coords to in coords. + kIn = shift[2] + (k*rate[2]); + kOffset = (kIn-inExt[4]) * inInc2; + for ( j=uExt[2]; j < uExt[3]; ++j ) + { // Convert out coords to in coords. + jIn = shift[1] + (j*rate[1]); + jOffset = (jIn-inExt[2]) * inInc1; + for ( i=uExt[0]; i < uExt[1]; ++i ) + { + iIn = shift[0] + (i*rate[0]); + idx = (iIn-inExt[0]) + jOffset + kOffset; + outCD->CopyData(cd, idx, newCellId++); + } + } + } + + output->SetPoints(newPts); + newPts->Delete(); + + return 1; +} + +void vtkExtractGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "VOI: \n"; + os << indent << " Imin,Imax: (" << this->VOI[0] << ", " + << this->VOI[1] << ")\n"; + os << indent << " Jmin,Jmax: (" << this->VOI[2] << ", " + << this->VOI[3] << ")\n"; + os << indent << " Kmin,Kmax: (" << this->VOI[4] << ", " + << this->VOI[5] << ")\n"; + + os << indent << "Sample Rate: (" << this->SampleRate[0] << ", " + << this->SampleRate[1] << ", " + << this->SampleRate[2] << ")\n"; + + os << indent << "Include Boundary: " + << (this->IncludeBoundary ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkExtractGrid.h b/Graphics/vtkExtractGrid.h new file mode 100644 index 0000000..dbc0964 --- /dev/null +++ b/Graphics/vtkExtractGrid.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractGrid - select piece (e.g., volume of interest) and/or subsample structured grid dataset + +// .SECTION Description +// vtkExtractGrid is a filter that selects a portion of an input structured +// grid dataset, or subsamples an input dataset. (The selected portion of +// interested is referred to as the Volume Of Interest, or VOI.) The output of +// this filter is a structured grid dataset. The filter treats input data of +// any topological dimension (i.e., point, line, image, or volume) and can +// generate output data of any topological dimension. +// +// To use this filter set the VOI ivar which are i-j-k min/max indices that +// specify a rectangular region in the data. (Note that these are 0-offset.) +// You can also specify a sampling rate to subsample the data. +// +// Typical applications of this filter are to extract a plane from a grid for +// contouring, subsampling large grids to reduce data size, or extracting +// regions of a grid with interesting data. + +// .SECTION See Also +// vtkGeometryFilter vtkExtractGeometry vtkExtractVOI +// vtkStructuredGridGeometryFilter + +#ifndef __vtkExtractGrid_h +#define __vtkExtractGrid_h + +#include "vtkStructuredGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkExtractGrid : public vtkStructuredGridAlgorithm +{ +public: + static vtkExtractGrid *New(); + vtkTypeRevisionMacro(vtkExtractGrid,vtkStructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify i-j-k (min,max) pairs to extract. The resulting structured grid + // dataset can be of any topological dimension (i.e., point, line, plane, + // or 3D grid). + vtkSetVector6Macro(VOI,int); + vtkGetVectorMacro(VOI,int,6); + + // Description: + // Set the sampling rate in the i, j, and k directions. If the rate is > 1, + // then the resulting VOI will be subsampled representation of the input. + // For example, if the SampleRate=(2,2,2), every other point will be + // selected, resulting in a volume 1/8th the original size. + vtkSetVector3Macro(SampleRate, int); + vtkGetVectorMacro(SampleRate, int, 3); + + // Description: + // Control whether to enforce that the "boundary" of the grid is output in + // the subsampling process. (This ivar only has effect when the SampleRate + // in any direction is not equal to 1.) When this ivar IncludeBoundary is + // on, the subsampling will always include the boundary of the grid even + // though the sample rate is not an even multiple of the grid + // dimensions. (By default IncludeBoundary is off.) + vtkSetMacro(IncludeBoundary,int); + vtkGetMacro(IncludeBoundary,int); + vtkBooleanMacro(IncludeBoundary,int); + +protected: + vtkExtractGrid(); + ~vtkExtractGrid() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int VOI[6]; + int SampleRate[3]; + int IncludeBoundary; + +private: + vtkExtractGrid(const vtkExtractGrid&); // Not implemented. + void operator=(const vtkExtractGrid&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkExtractPolyDataGeometry.cxx b/Graphics/vtkExtractPolyDataGeometry.cxx new file mode 100644 index 0000000..113a6b7 --- /dev/null +++ b/Graphics/vtkExtractPolyDataGeometry.cxx @@ -0,0 +1,290 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractPolyDataGeometry.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractPolyDataGeometry.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkExtractPolyDataGeometry, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkExtractPolyDataGeometry); +vtkCxxSetObjectMacro(vtkExtractPolyDataGeometry, + ImplicitFunction,vtkImplicitFunction); + +// Construct object with ExtractInside turned on. +vtkExtractPolyDataGeometry::vtkExtractPolyDataGeometry(vtkImplicitFunction *f) +{ + this->ImplicitFunction = f; + if (this->ImplicitFunction) + { + this->ImplicitFunction->Register(this); + } + + this->ExtractInside = 1; + this->ExtractBoundaryCells = 0; +} + +vtkExtractPolyDataGeometry::~vtkExtractPolyDataGeometry() +{ + this->SetImplicitFunction(NULL); +} + +// Overload standard modified time function. If implicit function is modified, +// then this object is modified as well. +unsigned long vtkExtractPolyDataGeometry::GetMTime() +{ + unsigned long mTime=this->MTime.GetMTime(); + unsigned long impFuncMTime; + + if ( this->ImplicitFunction != NULL ) + { + impFuncMTime = this->ImplicitFunction->GetMTime(); + mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime ); + } + + return mTime; +} + +int vtkExtractPolyDataGeometry::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkPoints *inPts=input->GetPoints(); + vtkIdType numPts, i, cellId = -1, newId; + float multiplier; + vtkCellArray *inVerts=NULL, *inLines=NULL, *inPolys=NULL, *inStrips=NULL; + vtkCellArray *newVerts=NULL, *newLines=NULL, *newPolys=NULL, *newStrips=NULL; + + vtkDebugMacro(<< "Extracting poly data geometry"); + + if ( ! this->ImplicitFunction ) + { + vtkErrorMacro(<<"No implicit function specified"); + return 1; + } + + numPts = input->GetNumberOfPoints(); + + if ( this->ExtractInside ) + { + multiplier = 1.0; + } + else + { + multiplier = -1.0; + } + + // Use a templated function to access the points. The points are + // passed through, but scalar values are generated. + vtkFloatArray *newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfValues(numPts); + + for (int ptId=0; ptId < numPts; ptId++ ) + { + newScalars->SetValue(ptId, this->ImplicitFunction-> + FunctionValue(inPts->GetPoint(ptId))*multiplier); + } + + output->SetPoints(inPts); + outputPD->PassData(pd); + + // Now loop over all cells to see whether they are inside the implicit + // function. Copy if they are. Note: there is an awful hack here, that + // can result in bugs. The cellId is assumed to be arranged starting + // with the verts, then lines, then polys, then strips. + // + int numIn; + vtkIdType npts = 0; + vtkIdType *pts = 0; + if ( input->GetNumberOfVerts() ) + { + inVerts = input->GetVerts(); + newVerts = vtkCellArray::New(); + newVerts->Allocate(inVerts->GetSize()); + } + if ( input->GetNumberOfLines() ) + { + inLines = input->GetLines(); + newLines = vtkCellArray::New(); + newLines->Allocate(inLines->GetSize()); + } + if ( input->GetNumberOfPolys() ) + { + inPolys = input->GetPolys(); + newPolys = vtkCellArray::New(); + newPolys->Allocate(inPolys->GetSize()); + } + if ( input->GetNumberOfStrips() ) + { + inStrips = input->GetStrips(); + newStrips = vtkCellArray::New(); + newStrips->Allocate(inStrips->GetSize()); + } + + // verts + if ( newVerts && !this->GetAbortExecute() ) + { + for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); ) + { + for (numIn=0, i=0; iGetValue(pts[i]) <= 0.0 ) + { + numIn++; + } + } + if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) ) + { + newId = newVerts->InsertNextCell(npts,pts); + outputCD->CopyData(cd, cellId, newId); + } + cellId++; + } + } + this->UpdateProgress (0.6); + + // lines + if ( newLines && !this->GetAbortExecute() ) + { + for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); ) + { + for (numIn=0, i=0; iGetValue(pts[i]) <= 0.0 ) + { + numIn++; + } + } + if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) ) + { + newId = newLines->InsertNextCell(npts,pts); + outputCD->CopyData(cd, cellId, newId); + } + cellId++; + } + } + this->UpdateProgress (0.75); + + // polys + if ( newPolys && !this->GetAbortExecute() ) + { + for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + for (numIn=0, i=0; iGetValue(pts[i]) <= 0.0 ) + { + numIn++; + } + } + if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) ) + { + newId = newPolys->InsertNextCell(npts,pts); + outputCD->CopyData(cd, cellId, newId); + } + cellId++; + } + } + this->UpdateProgress (0.90); + + // strips + if ( newStrips && !this->GetAbortExecute() ) + { + for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + for (numIn=0, i=0; iGetValue(pts[i]) <= 0.0 ) + { + numIn++; + } + } + if ( (numIn == npts) || (this->ExtractBoundaryCells && numIn > 0) ) + { + newId = newStrips->InsertNextCell(npts,pts); + outputCD->CopyData(cd, cellId, newId); + } + cellId++; + } + } + this->UpdateProgress (1.0); + + // Update ourselves and release memory + // + newScalars->Delete(); + + if ( newVerts ) + { + output->SetVerts(newVerts); + newVerts->Delete(); + } + if ( newLines ) + { + output->SetLines(newLines); + newLines->Delete(); + } + if ( newPolys ) + { + output->SetPolys(newPolys); + newPolys->Delete(); + } + if ( newStrips ) + { + output->SetStrips(newStrips); + newStrips->Delete(); + } + + return 1; +} + +void vtkExtractPolyDataGeometry::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->ImplicitFunction) + { + os << indent << "Implicit Function: " + << (void *)this->ImplicitFunction << "\n"; + } + else + { + os << indent << "Implicit Function: (null)\n"; + } + os << indent << "Extract Inside: " + << (this->ExtractInside ? "On\n" : "Off\n"); + os << indent << "Extract Boundary Cells: " + << (this->ExtractBoundaryCells ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkExtractPolyDataGeometry.h b/Graphics/vtkExtractPolyDataGeometry.h new file mode 100644 index 0000000..59ad3b7 --- /dev/null +++ b/Graphics/vtkExtractPolyDataGeometry.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractPolyDataGeometry.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractPolyDataGeometry - extract vtkPolyData cells that lies either entirely inside or outside of a specified implicit function + +// .SECTION Description +// vtkExtractPolyDataGeometry extracts from its input vtkPolyData all cells +// that are either completely inside or outside of a specified implicit +// function. This filter is specialized to vtkPolyData. On output the +// filter generates vtkPolyData. +// +// To use this filter you must specify an implicit function. You must also +// specify whether to extract cells lying inside or outside of the implicit +// function. (The inside of an implicit function is the negative values +// region.) An option exists to extract cells that are neither inside nor +// outside (i.e., boundary). +// +// A more general version of this filter is available for arbitrary +// vtkDataSet input (see vtkExtractGeometry). + +// .SECTION See Also +// vtkExtractGeometry vtkClipPolyData + +#ifndef __vtkExtractPolyDataGeometry_h +#define __vtkExtractPolyDataGeometry_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkImplicitFunction; + +class VTK_GRAPHICS_EXPORT vtkExtractPolyDataGeometry : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkExtractPolyDataGeometry,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with ExtractInside turned on. + static vtkExtractPolyDataGeometry *New(); + + // Description: + // Return the MTime taking into account changes to the implicit function + unsigned long GetMTime(); + + // Description: + // Specify the implicit function for inside/outside checks. + virtual void SetImplicitFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ImplicitFunction,vtkImplicitFunction); + + // Description: + // Boolean controls whether to extract cells that are inside of implicit + // function (ExtractInside == 1) or outside of implicit function + // (ExtractInside == 0). + vtkSetMacro(ExtractInside,int); + vtkGetMacro(ExtractInside,int); + vtkBooleanMacro(ExtractInside,int); + + // Description: + // Boolean controls whether to extract cells that are partially inside. + // By default, ExtractBoundaryCells is off. + vtkSetMacro(ExtractBoundaryCells,int); + vtkGetMacro(ExtractBoundaryCells,int); + vtkBooleanMacro(ExtractBoundaryCells,int); + +protected: + vtkExtractPolyDataGeometry(vtkImplicitFunction *f=NULL); + ~vtkExtractPolyDataGeometry(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkImplicitFunction *ImplicitFunction; + int ExtractInside; + int ExtractBoundaryCells; +private: + vtkExtractPolyDataGeometry(const vtkExtractPolyDataGeometry&); // Not implemented. + void operator=(const vtkExtractPolyDataGeometry&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkExtractRectilinearGrid.cxx b/Graphics/vtkExtractRectilinearGrid.cxx new file mode 100644 index 0000000..3366a70 --- /dev/null +++ b/Graphics/vtkExtractRectilinearGrid.cxx @@ -0,0 +1,470 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractRectilinearGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractRectilinearGrid.h" + +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkExtractRectilinearGrid, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkExtractRectilinearGrid); + +// Construct object to extract all of the input data. +vtkExtractRectilinearGrid::vtkExtractRectilinearGrid() +{ + this->VOI[0] = this->VOI[2] = this->VOI[4] = 0; + this->VOI[1] = this->VOI[3] = this->VOI[5] = VTK_LARGE_INTEGER; + + this->SampleRate[0] = this->SampleRate[1] = this->SampleRate[2] = 1; + + this->IncludeBoundary = 0; +} + +//---------------------------------------------------------------------------- +int vtkExtractRectilinearGrid::RequestUpdateExtent( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int i, ext[6], voi[6]; + int *inWholeExt, *outWholeExt, *updateExt; + int rate[3]; + + + inWholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + outWholeExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + updateExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + for (i = 0; i < 3; ++i) + { + rate[i] = this->SampleRate[i]; + if (rate[i] < 1) + { + rate[i] = 1; + } + } + + // Once again, clip the VOI with the input whole extent. + for (i = 0; i < 3; ++i) + { + voi[i*2] = this->VOI[2*i]; + if (voi[2*i] < inWholeExt[2*i]) + { + voi[2*i] = inWholeExt[2*i]; + } + voi[i*2+1] = this->VOI[2*i+1]; + if (voi[2*i+1] > inWholeExt[2*i+1]) + { + voi[2*i+1] = inWholeExt[2*i+1]; + } + } + + ext[0] = voi[0] + (updateExt[0]-outWholeExt[0])*rate[0]; + ext[1] = voi[0] + (updateExt[1]-outWholeExt[0])*rate[0]; + if (ext[1] > voi[1]) + { // This handles the IncludeBoundary condition. + ext[1] = voi[1]; + } + ext[2] = voi[2] + (updateExt[2]-outWholeExt[2])*rate[1]; + ext[3] = voi[2] + (updateExt[3]-outWholeExt[2])*rate[1]; + if (ext[3] > voi[3]) + { // This handles the IncludeBoundary condition. + ext[3] = voi[3]; + } + ext[4] = voi[4] + (updateExt[4]-outWholeExt[4])*rate[2]; + ext[5] = voi[4] + (updateExt[5]-outWholeExt[4])*rate[2]; + if (ext[5] > voi[5]) + { // This handles the IncludeBoundary condition. + ext[5] = voi[5]; + } + + // I do not think we need this extra check, but it cannot hurt. + if (ext[0] < inWholeExt[0]) + { + ext[0] = inWholeExt[0]; + } + if (ext[1] > inWholeExt[1]) + { + ext[1] = inWholeExt[1]; + } + + if (ext[2] < inWholeExt[2]) + { + ext[2] = inWholeExt[2]; + } + if (ext[3] > inWholeExt[3]) + { + ext[3] = inWholeExt[3]; + } + + if (ext[4] < inWholeExt[4]) + { + ext[4] = inWholeExt[4]; + } + if (ext[5] > inWholeExt[5]) + { + ext[5] = inWholeExt[5]; + } + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + // We can handle anything. + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 0); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkExtractRectilinearGrid::RequestInformation( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int i, outDims[3], voi[6]; + int inWholeExtent[6], outWholeExtent[6]; + int mins[3]; + int rate[3]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inWholeExtent); + + // Copy because we need to take union of voi and whole extent. + for ( i=0; i < 6; i++ ) + { + voi[i] = this->VOI[i]; + } + + for ( i=0; i < 3; i++ ) + { + // Empty request. + if (voi[2*i+1] < voi[2*i] || voi[2*i+1] < inWholeExtent[2*i] || + voi[2*i] > inWholeExtent[2*i+1]) + { + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0,-1,0,-1,0,-1); + return 1; + } + + // Make sure VOI is in the whole extent. + if ( voi[2*i+1] > inWholeExtent[2*i+1] ) + { + voi[2*i+1] = inWholeExtent[2*i+1]; + } + else if ( voi[2*i+1] < inWholeExtent[2*i] ) + { + voi[2*i+1] = inWholeExtent[2*i]; + } + if ( voi[2*i] > inWholeExtent[2*i+1] ) + { + voi[2*i] = inWholeExtent[2*i+1]; + } + else if ( voi[2*i] < inWholeExtent[2*i] ) + { + voi[2*i] = inWholeExtent[2*i]; + } + + if ( (rate[i] = this->SampleRate[i]) < 1 ) + { + rate[i] = 1; + } + + outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1; + if ( outDims[i] < 1 ) + { + outDims[i] = 1; + } + // We might as well make this work for negative extents. + mins[i] = (int)(floor((float)voi[2*i] / (float)rate[i])); + } + + // Adjust the output dimensions if the boundaries are to be + // included and the sample rate is not 1. + if ( this->IncludeBoundary && + (rate[0] != 1 || rate[1] != 1 || rate[2] != 1) ) + { + int diff; + for (i=0; i<3; i++) + { + if ( ((diff=voi[2*i+1]-voi[2*i]) > 0) && rate[i] != 1 && + ((diff % rate[i]) != 0) ) + { + outDims[i]++; + } + } + } + + // Set the whole extent of the output + outWholeExtent[0] = mins[0]; + outWholeExtent[1] = mins[0] + outDims[0] - 1; + outWholeExtent[2] = mins[1]; + outWholeExtent[3] = mins[1] + outDims[1] - 1; + outWholeExtent[4] = mins[2]; + outWholeExtent[5] = mins[2] + outDims[2] - 1; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + outWholeExtent, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkExtractRectilinearGrid::RequestData( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkRectilinearGrid *input= vtkRectilinearGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointData *pd=input->GetPointData(); + vtkCellData *cd=input->GetCellData(); + vtkRectilinearGrid *output= vtkRectilinearGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointData *outPD=output->GetPointData(); + vtkCellData *outCD=output->GetCellData(); + int uExt[6], voi[6]; + int *inExt, *outWholeExt; + vtkIdType i, j, k; + vtkIdType iIn, jIn, kIn; + int outSize, jOffset, kOffset, rate[3]; + vtkIdType idx, newIdx, newCellId; + int inInc1, inInc2; + int *inWholeExt; + + vtkDebugMacro(<< "Extracting Grid"); + + inWholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + outWholeExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExt); + inExt = input->GetExtent(); + inInc1 = (inExt[1]-inExt[0]+1); + inInc2 = inInc1*(inExt[3]-inExt[2]+1); + + for (i = 0; i < 3; ++i) + { + if ( (rate[i] = this->SampleRate[i]) < 1 ) + { + rate[i] = 1; + } + } + + // Clip the VOI by the input extent + for (i = 0; i < 3; ++i) + { + voi[i*2] = this->VOI[2*i]; + if (voi[2*i] < inWholeExt[2*i]) + { + voi[2*i] = inWholeExt[2*i]; + } + voi[i*2+1] = this->VOI[2*i+1]; + if (voi[2*i+1] > inWholeExt[2*i+1]) + { + voi[2*i+1] = inWholeExt[2*i+1]; + } + } + + output->SetExtent(uExt); + + // If output same as input, just pass data through + if ( uExt[0] <= inExt[0] && uExt[1] >= inExt[1] && + uExt[2] <= inExt[2] && uExt[3] >= inExt[3] && + uExt[4] <= inExt[4] && uExt[5] >= inExt[5] && + rate[0] == 1 && rate[1] == 1 && rate[2] == 1) + { + output->SetXCoordinates(input->GetXCoordinates()); + output->SetYCoordinates(input->GetYCoordinates()); + output->SetZCoordinates(input->GetZCoordinates()); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + vtkDebugMacro(<<"Passed data through bacause input and output are the same"); + return 1; + } + + // Allocate necessary objects + // + outSize = (uExt[1]-uExt[0]+1)*(uExt[3]-uExt[2]+1)*(uExt[5]-uExt[4]+1); + outPD->CopyAllocate(pd,outSize,outSize); + outCD->CopyAllocate(cd,outSize,outSize); + + // Setup the new "geometry" + vtkDataArray *inCoords; + vtkFloatArray *outCoords; + // X + inCoords = input->GetXCoordinates(); + if (inCoords->GetNumberOfComponents() > 1) + { + vtkWarningMacro("Multiple componenet axis coordinate."); + } + outCoords = vtkFloatArray::New(); + outCoords->Allocate(uExt[1]-uExt[0]+1); + outCoords->Allocate(uExt[1]-uExt[0]+1); + outCoords->SetNumberOfTuples(uExt[1]-uExt[0]+1); + for ( k=uExt[0]; k <= uExt[1]; ++k) + { // Convert out coords to in coords. + kIn = voi[0] + ((k-outWholeExt[0])*rate[0]); + if (kIn > voi[1]) + { // This handles the IncludeBoundaryOn condition. + kIn = voi[1]; + } + outCoords->SetValue(k-uExt[0], inCoords->GetComponent(kIn-inExt[0], 0)); + } + output->SetXCoordinates(outCoords); + outCoords->Delete(); + outCoords = NULL; + // Y + inCoords = input->GetYCoordinates(); + if (inCoords->GetNumberOfComponents() > 1) + { + vtkWarningMacro("Multiple componenet axis coordinate."); + } + outCoords = vtkFloatArray::New(); + outCoords->Allocate(uExt[3]-uExt[2]+1); + outCoords->SetNumberOfTuples(uExt[3]-uExt[2]+1); + for ( k=uExt[2]; k <= uExt[3]; ++k) + { // Convert out coords to in coords. + kIn = voi[2] + ((k-outWholeExt[2])*rate[1]); + if (kIn > voi[3]) + { // This handles the IncludeBoundaryOn condition. + kIn = voi[3]; + } + outCoords->SetValue(k-uExt[2], inCoords->GetComponent(kIn-inExt[2], 0)); + } + output->SetYCoordinates(outCoords); + outCoords->Delete(); + // Z + inCoords = input->GetZCoordinates(); + if (inCoords->GetNumberOfComponents() > 1) + { + vtkWarningMacro("Multiple componenet axis coordinate."); + } + outCoords = vtkFloatArray::New(); + outCoords->Allocate(uExt[5]-uExt[4]+1); + outCoords->SetNumberOfTuples(uExt[5]-uExt[4]+1); + for ( k=uExt[4]; k <= uExt[5]; ++k) + { // Convert out coords to in coords. + kIn = voi[4] + ((k-outWholeExt[4])*rate[2]); + if (kIn > voi[5]) + { // This handles the IncludeBoundaryOn condition. + kIn = voi[5]; + } + outCoords->SetValue(k-uExt[4], inCoords->GetComponent(kIn-inExt[4], 0)); + } + output->SetZCoordinates(outCoords); + outCoords->Delete(); + + // Traverse input data and copy point attributes to output + // iIn,jIn,kIn are in input grid coordinates. + newIdx = 0; + for ( k=uExt[4]; k <= uExt[5]; ++k) + { // Convert out coords to in coords. + kIn = voi[4] + ((k-outWholeExt[4])*rate[2]); + if (kIn > voi[5]) + { // This handles the IncludeBoundaryOn condition. + kIn = voi[5]; + } + kOffset = (kIn-inExt[4]) * inInc2; + for ( j=uExt[2]; j <= uExt[3]; ++j) + { // Convert out coords to in coords. + jIn = voi[2] + ((j-outWholeExt[2])*rate[1]); + if (jIn > voi[3]) + { // This handles the IncludeBoundaryOn condition. + jIn = voi[3]; + } + jOffset = (jIn-inExt[2]) * inInc1; + for ( i=uExt[0]; i <= uExt[1]; ++i) + { // Convert out coords to in coords. + iIn = voi[0] + ((i-outWholeExt[0])*rate[0]); + if (iIn > voi[1]) + { // This handles the IncludeBoundaryOn condition. + iIn = voi[1]; + } + idx = (iIn-inExt[0]) + jOffset + kOffset; + //newPts->SetPoint(newIdx,inPts->GetPoint(idx)); + outPD->CopyData(pd, idx, newIdx++); + } + } + } + + // Traverse input data and copy cell attributes to output + // + newCellId = 0; + inInc1 = (inExt[1]-inExt[0]); + inInc2 = inInc1*(inExt[3]-inExt[2]); + // This will take care of 2D and 1D cells. + // Each loop has to excute at least once. + if (uExt[4] == uExt[5]) + { + uExt[5] = uExt[5] + 1; + } + if (uExt[2] == uExt[3]) + { + uExt[3] = uExt[3] + 1; + } + if (uExt[0] == uExt[1]) + { + uExt[1] = uExt[1] + 1; + } + // No need to consider IncludeBoundary for cell data. + for ( k=uExt[4]; k < uExt[5]; ++k ) + { // Convert out coords to in coords. + kIn = voi[4] + ((k-outWholeExt[4])*rate[2]); + kOffset = (kIn-inExt[4]) * inInc2; + for ( j=uExt[2]; j < uExt[3]; ++j ) + { // Convert out coords to in coords. + jIn = voi[2] + ((j-outWholeExt[2])*rate[1]); + jOffset = (jIn-inExt[2]) * inInc1; + for ( i=uExt[0]; i < uExt[1]; ++i ) + { + iIn = voi[0] + ((i-outWholeExt[0])*rate[0]); + idx = (iIn-inExt[0]) + jOffset + kOffset; + outCD->CopyData(cd, idx, newCellId++); + } + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkExtractRectilinearGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "VOI: \n"; + os << indent << " Imin,Imax: (" << this->VOI[0] << ", " + << this->VOI[1] << ")\n"; + os << indent << " Jmin,Jmax: (" << this->VOI[2] << ", " + << this->VOI[3] << ")\n"; + os << indent << " Kmin,Kmax: (" << this->VOI[4] << ", " + << this->VOI[5] << ")\n"; + + os << indent << "Sample Rate: (" << this->SampleRate[0] << ", " + << this->SampleRate[1] << ", " + << this->SampleRate[2] << ")\n"; + + os << indent << "Include Boundary: " + << (this->IncludeBoundary ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkExtractRectilinearGrid.h b/Graphics/vtkExtractRectilinearGrid.h new file mode 100644 index 0000000..52254e1 --- /dev/null +++ b/Graphics/vtkExtractRectilinearGrid.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractRectilinearGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractRectilinearGrid - Extract a sub grid (VOI) from the structured rectilinear dataset. +// .SECTION Description +// vtkExtractRectilinearGrid rounds out the set of filters that extract +// a subgrid out of a larger structured data set. RIght now, this filter +// only supports extracting a VOI. In the future, it might support +// strides like the vtkExtract grid filter. + +// .SECTION See Also +// vtkExtractGrid vtkImageClip vtkGeometryFilter vtkExtractGeometry vtkExtractVOI +// vtkStructuredGridGeometryFilter + +#ifndef __vtkExtractRectilinearGrid_h +#define __vtkExtractRectilinearGrid_h + +#include "vtkRectilinearGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkExtractRectilinearGrid : public vtkRectilinearGridAlgorithm +{ +public: + static vtkExtractRectilinearGrid *New(); + vtkTypeRevisionMacro(vtkExtractRectilinearGrid,vtkRectilinearGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify i-j-k (min,max) pairs to extract. The resulting structured grid + // dataset can be of any topological dimension (i.e., point, line, plane, + // or 3D grid). + vtkSetVector6Macro(VOI,int); + vtkGetVectorMacro(VOI,int,6); + + // Description: + // Set the sampling rate in the i, j, and k directions. If the rate is > 1, + // then the resulting VOI will be subsampled representation of the input. + // For example, if the SampleRate=(2,2,2), every other point will be + // selected, resulting in a volume 1/8th the original size. + vtkSetVector3Macro(SampleRate, int); + vtkGetVectorMacro(SampleRate, int, 3); + + // Description: + // Control whether to enforce that the "boundary" of the grid is output in + // the subsampling process. (This ivar only has effect when the SampleRate + // in any direction is not equal to 1.) When this ivar IncludeBoundary is + // on, the subsampling will always include the boundary of the grid even + // though the sample rate is not an even multiple of the grid + // dimensions. (By default IncludeBoundary is off.) + vtkSetMacro(IncludeBoundary,int); + vtkGetMacro(IncludeBoundary,int); + vtkBooleanMacro(IncludeBoundary,int); + +protected: + vtkExtractRectilinearGrid(); + ~vtkExtractRectilinearGrid() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int VOI[6]; + int SampleRate[3]; + int IncludeBoundary; + +private: + vtkExtractRectilinearGrid(const vtkExtractRectilinearGrid&); // Not implemented. + void operator=(const vtkExtractRectilinearGrid&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkExtractTensorComponents.cxx b/Graphics/vtkExtractTensorComponents.cxx new file mode 100644 index 0000000..523291b --- /dev/null +++ b/Graphics/vtkExtractTensorComponents.cxx @@ -0,0 +1,295 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractTensorComponents.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractTensorComponents.h" + +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkExtractTensorComponents, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkExtractTensorComponents); + +//--------------------------------------------------------------------------- +// Construct object to extract nothing and to not pass tensor data +// through the pipeline. +vtkExtractTensorComponents::vtkExtractTensorComponents() +{ + this->PassTensorsToOutput = 0; + + this->ExtractScalars = 0; + this->ExtractVectors = 0; + this->ExtractNormals = 0; + this->ExtractTCoords = 0; + + this->ScalarMode = VTK_EXTRACT_COMPONENT; + this->ScalarComponents[0] = this->ScalarComponents[1] = 0; + + this->VectorComponents[0] = 0; this->VectorComponents[1] = 0; + this->VectorComponents[2] = 1; this->VectorComponents[3] = 0; + this->VectorComponents[4] = 2; this->VectorComponents[5] = 0; + + this->NormalizeNormals = 1; + this->NormalComponents[0] = 0; this->NormalComponents[1] = 1; + this->NormalComponents[2] = 1; this->NormalComponents[3] = 1; + this->NormalComponents[4] = 2; this->NormalComponents[5] = 1; + + this->NumberOfTCoords = 2; + this->TCoordComponents[0] = 0; this->TCoordComponents[1] = 2; + this->TCoordComponents[2] = 1; this->TCoordComponents[3] = 2; + this->TCoordComponents[4] = 2; this->TCoordComponents[5] = 2; +} + +//--------------------------------------------------------------------------- +// Extract data from tensors. +// +int vtkExtractTensorComponents::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *inTensors; + double tensor[9]; + vtkPointData *pd = input->GetPointData(); + vtkPointData *outPD = output->GetPointData(); + double s = 0.0; + double v[3]; + vtkFloatArray *newScalars=NULL; + vtkFloatArray *newVectors=NULL; + vtkFloatArray *newNormals=NULL; + vtkFloatArray *newTCoords=NULL; + vtkIdType ptId, numPts; + double sx, sy, sz, txy, tyz, txz; + + // Initialize + // + vtkDebugMacro(<<"Extracting vector components!"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + inTensors = pd->GetTensors(); + numPts = input->GetNumberOfPoints(); + + if ( !inTensors || numPts < 1 ) + { + vtkErrorMacro(<<"No data to extract!"); + return 1; + } + + if ( !this->ExtractScalars && !this->ExtractVectors && + !this->ExtractNormals && !this->ExtractTCoords ) + { + vtkWarningMacro(<<"No data is being extracted"); + } + + outPD->CopyAllOn(); + if ( !this->PassTensorsToOutput ) + { + outPD->CopyTensorsOff(); + } + if ( this->ExtractScalars ) + { + outPD->CopyScalarsOff(); + newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfTuples(numPts); + } + if ( this->ExtractVectors ) + { + outPD->CopyVectorsOff(); + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->SetNumberOfTuples(numPts); + } + if ( this->ExtractNormals ) + { + outPD->CopyNormalsOff(); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->SetNumberOfTuples(numPts); + } + if ( this->ExtractTCoords ) + { + outPD->CopyTCoordsOff(); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->SetNumberOfTuples(numPts); + } + outPD->PassData(pd); + + // Loop over all points extracting components of tensor + // + for (ptId=0; ptId < numPts; ptId++) + { + inTensors->GetTuple(ptId, tensor); + + if ( this->ExtractScalars ) + { + if ( this->ScalarMode == VTK_EXTRACT_EFFECTIVE_STRESS ) + { + sx = tensor[0]; + sy = tensor[4]; + sz = tensor[8]; + txy = tensor[3]; + tyz = tensor[7]; + txz = tensor[6]; + + s = sqrt (0.16666667 * ((sx-sy)*(sx-sy) + (sy-sz)*(sy-sz) + + (sz-sx)*(sz-sx) + + 6.0*(txy*txy + tyz*tyz + txz*txz))); + } + + else if ( this->ScalarMode == VTK_EXTRACT_COMPONENT ) + { + s = tensor[this->ScalarComponents[0]+3*this->ScalarComponents[1]]; + } + + else //VTK_EXTRACT_EFFECTIVE_DETERMINANT + { + s = tensor[0]*tensor[4]*tensor[8]- + tensor[0]*tensor[5]*tensor[7]- + tensor[1]*tensor[3]*tensor[8]+ + tensor[1]*tensor[5]*tensor[6]+ + tensor[2]*tensor[3]*tensor[7]- + tensor[2]*tensor[4]*tensor[6]; + } + newScalars->SetTuple(ptId, &s); + }//if extract scalars + + if ( this->ExtractVectors ) + { + v[0] = tensor[this->VectorComponents[0]+3*this->VectorComponents[1]]; + v[1] = tensor[this->VectorComponents[2]+3*this->VectorComponents[3]]; + v[2] = tensor[this->VectorComponents[4]+3*this->VectorComponents[5]]; + newVectors->SetTuple(ptId, v); + } + + if ( this->ExtractNormals ) + { + v[0] = tensor[this->NormalComponents[0]+3*this->NormalComponents[1]]; + v[1] = tensor[this->NormalComponents[2]+3*this->NormalComponents[3]]; + v[2] = tensor[this->NormalComponents[4]+3*this->NormalComponents[5]]; + newNormals->SetTuple(ptId, v); + } + + if ( this->ExtractTCoords ) + { + for ( int i=0; i < this->NumberOfTCoords; i++ ) + { + v[i] = tensor[this->TCoordComponents[2*i]+3* + this->TCoordComponents[2*i+1]]; + } + newTCoords->SetTuple(ptId, v); + } + + }//for all points + + // Send data to output + // + if ( this->ExtractScalars ) + { + int idx = outPD->AddArray(newScalars); + outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + if ( this->ExtractVectors ) + { + outPD->SetVectors(newVectors); + newVectors->Delete(); + } + if ( this->ExtractNormals ) + { + outPD->SetNormals(newNormals); + newNormals->Delete(); + } + if ( this->ExtractTCoords ) + { + outPD->SetTCoords(newTCoords); + newTCoords->Delete(); + } + + return 1; +} + +//--------------------------------------------------------------------------- +void vtkExtractTensorComponents::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Pass Tensors To Output: " << (this->PassTensorsToOutput ? "On\n" : "Off\n"); + + os << indent << "Extract Scalars: " << (this->ExtractScalars ? "On\n" : "Off\n"); + + os << indent << "Scalar Extraction Mode: "; + + if ( this->ScalarMode == VTK_EXTRACT_COMPONENT ) + { + os << "VTK_EXTRACT_COMPONENT\n"; + } + else if ( this->ScalarMode == VTK_EXTRACT_EFFECTIVE_STRESS ) + { + os << "VTK_EXTRACT_EFFECTIVE_STRESS\n"; + } + else + { + os << "VTK_EXTRACT_DETERMINANT\n"; + } + + os << indent << "Scalar Components: \n"; + os << indent << " (row,column): (" + << this->ScalarComponents[0] << ", " << this->ScalarComponents[1] << ")\n"; + + os << indent << "Extract Vectors: " << (this->ExtractVectors ? "On\n" : "Off\n"); + os << indent << "Vector Components: \n"; + os << indent << " (row,column)0: (" + << this->VectorComponents[0] << ", " << this->VectorComponents[1] << ")\n"; + os << indent << " (row,column)1: (" + << this->VectorComponents[2] << ", " << this->VectorComponents[3] << ")\n"; + os << indent << " (row,column)2: (" + << this->VectorComponents[4] << ", " << this->VectorComponents[5] << ")\n"; + + os << indent << "Extract Normals: " << (this->ExtractNormals ? "On\n" : "Off\n"); + os << indent << "Normalize Normals: " << (this->NormalizeNormals ? "On\n" : "Off\n"); + os << indent << "Normal Components: \n"; + os << indent << " (row,column)0: (" + << this->NormalComponents[0] << ", " << this->NormalComponents[1] << ")\n"; + os << indent << " (row,column)1: (" + << this->NormalComponents[2] << ", " << this->NormalComponents[3] << ")\n"; + os << indent << " (row,column)2: (" + << this->NormalComponents[4] << ", " << this->NormalComponents[5] << ")\n"; + + os << indent << "Extract TCoords: " << (this->ExtractTCoords ? "On\n" : "Off\n"); + os << indent << "Number Of TCoords: (" << this->NumberOfTCoords << ")\n"; + os << indent << "TCoord Components: \n"; + os << indent << " (row,column)0: (" + << this->TCoordComponents[0] << ", " << this->TCoordComponents[1] << ")\n"; + os << indent << " (row,column)1: (" + << this->TCoordComponents[2] << ", " << this->TCoordComponents[3] << ")\n"; + os << indent << " (row,column)2: (" + << this->TCoordComponents[4] << ", " << this->TCoordComponents[5] << ")\n"; +} diff --git a/Graphics/vtkExtractTensorComponents.h b/Graphics/vtkExtractTensorComponents.h new file mode 100644 index 0000000..3a99094 --- /dev/null +++ b/Graphics/vtkExtractTensorComponents.h @@ -0,0 +1,177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractTensorComponents.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractTensorComponents - extract parts of tensor and create a scalar, vector, normal, or texture coordinates. +// .SECTION Description +// vtkExtractTensorComponents is a filter that extracts components of +// a tensor to create a scalar, vector, normal, or texture coords. For +// example, if the tensor contains components of stress, then you +// could extract the normal stress in the x-direction as a scalar +// (i.e., tensor component (0,0). +// +// To use this filter, you must set some boolean flags to control +// which data is extracted from the tensors, and whether you want to +// pass the tensor data through to the output. Also, you must specify +// the tensor component(s) for each type of data you want to +// extract. The tensor component(s) is(are) specified using matrix notation +// into a 3x3 matrix. That is, use the (row,column) address to specify +// a particular tensor component; and if the data you are extracting +// requires more than one component, use a list of addresses. (Note +// that the addresses are 0-offset -> (0,0) specifies upper left +// corner of the tensor.) +// +// There are two optional methods to extract scalar data. You can +// extract the determinant of the tensor, or you can extract the +// effective stress of the tensor. These require that the ivar +// ExtractScalars is on, and the appropriate scalar extraction mode is +// set. + +#ifndef __vtkExtractTensorComponents_h +#define __vtkExtractTensorComponents_h + +#include "vtkDataSetAlgorithm.h" + +#define VTK_EXTRACT_COMPONENT 0 +#define VTK_EXTRACT_EFFECTIVE_STRESS 1 +#define VTK_EXTRACT_DETERMINANT 2 + +class VTK_GRAPHICS_EXPORT vtkExtractTensorComponents : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkExtractTensorComponents,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object to extract nothing and to not pass tensor data + // through the pipeline. + static vtkExtractTensorComponents *New(); + + // Description: + // Boolean controls whether tensor data is passed through to output. + vtkSetMacro(PassTensorsToOutput,int); + vtkGetMacro(PassTensorsToOutput,int); + vtkBooleanMacro(PassTensorsToOutput,int); + + // Description: + // Boolean controls whether scalar data is extracted from tensor. + vtkSetMacro(ExtractScalars,int); + vtkGetMacro(ExtractScalars,int); + vtkBooleanMacro(ExtractScalars,int); + + // Description: + // Specify the (row,column) tensor component to extract as a scalar. + vtkSetVector2Macro(ScalarComponents,int); + vtkGetVectorMacro(ScalarComponents,int,2); + + // Description: + // Specify how to extract the scalar. You can extract it as one of + // the components of the tensor, as effective stress, or as the + // determinant of the tensor. If you extract a component make sure + // that you set the ScalarComponents ivar. + vtkSetMacro(ScalarMode,int); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToComponent() + {this->SetScalarMode(VTK_EXTRACT_COMPONENT);}; + void SetScalarModeToEffectiveStress() + {this->SetScalarMode(VTK_EXTRACT_EFFECTIVE_STRESS);}; + void SetScalarModeToDeterminant() + {this->SetScalarMode(VTK_EXTRACT_DETERMINANT);}; + void ScalarIsComponent() + {this->SetScalarMode(VTK_EXTRACT_COMPONENT);}; + void ScalarIsEffectiveStress() + {this->SetScalarMode(VTK_EXTRACT_EFFECTIVE_STRESS);}; + void ScalarIsDeterminant() + {this->SetScalarMode(VTK_EXTRACT_DETERMINANT);}; + + // Description: + // Boolean controls whether vector data is extracted from tensor. + vtkSetMacro(ExtractVectors,int); + vtkGetMacro(ExtractVectors,int); + vtkBooleanMacro(ExtractVectors,int); + + // Description: + // Specify the ((row,column)0,(row,column)1,(row,column)2) tensor + // components to extract as a vector. + vtkSetVector6Macro(VectorComponents,int); + vtkGetVectorMacro(VectorComponents,int,6); + + + // Description: + // Boolean controls whether normal data is extracted from tensor. + vtkSetMacro(ExtractNormals,int); + vtkGetMacro(ExtractNormals,int); + vtkBooleanMacro(ExtractNormals,int); + + // Description: + // Boolean controls whether normal vector is converted to unit normal + // after extraction. + vtkSetMacro(NormalizeNormals,int); + vtkGetMacro(NormalizeNormals,int); + vtkBooleanMacro(NormalizeNormals,int); + + // Description: + // Specify the ((row,column)0,(row,column)1,(row,column)2) tensor + // components to extract as a vector. + vtkSetVector6Macro(NormalComponents,int); + vtkGetVectorMacro(NormalComponents,int,6); + + // Description: + // Boolean controls whether texture coordinates are extracted from tensor. + vtkSetMacro(ExtractTCoords,int); + vtkGetMacro(ExtractTCoords,int); + vtkBooleanMacro(ExtractTCoords,int); + + // Description: + // Set the dimension of the texture coordinates to extract. + vtkSetClampMacro(NumberOfTCoords,int,1,3); + vtkGetMacro(NumberOfTCoords,int); + + // Description: + // Specify the ((row,column)0,(row,column)1,(row,column)2) tensor + // components to extract as a vector. Up to NumberOfTCoords + // components are extracted. + vtkSetVector6Macro(TCoordComponents,int); + vtkGetVectorMacro(TCoordComponents,int,6); + +protected: + vtkExtractTensorComponents(); + ~vtkExtractTensorComponents() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int PassTensorsToOutput; + + int ExtractScalars; + int ExtractVectors; + int ExtractNormals; + int ExtractTCoords; + + int ScalarMode; + int ScalarComponents[2]; + + int VectorComponents[6]; + + int NormalizeNormals; + int NormalComponents[6]; + + int NumberOfTCoords; + int TCoordComponents[6]; + +private: + vtkExtractTensorComponents(const vtkExtractTensorComponents&); // Not implemented. + void operator=(const vtkExtractTensorComponents&); // Not implemented. +}; + +#endif + diff --git a/Graphics/vtkExtractUnstructuredGrid.cxx b/Graphics/vtkExtractUnstructuredGrid.cxx new file mode 100644 index 0000000..1ae9a3a --- /dev/null +++ b/Graphics/vtkExtractUnstructuredGrid.cxx @@ -0,0 +1,349 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractUnstructuredGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractUnstructuredGrid.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkExtractUnstructuredGrid, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkExtractUnstructuredGrid); + +// Construct with all types of clipping turned off. +vtkExtractUnstructuredGrid::vtkExtractUnstructuredGrid() +{ + this->PointMinimum = 0; + this->PointMaximum = VTK_LARGE_ID; + + this->CellMinimum = 0; + this->CellMaximum = VTK_LARGE_ID; + + this->Extent[0] = -VTK_DOUBLE_MAX; + this->Extent[1] = VTK_DOUBLE_MAX; + this->Extent[2] = -VTK_DOUBLE_MAX; + this->Extent[3] = VTK_DOUBLE_MAX; + this->Extent[4] = -VTK_DOUBLE_MAX; + this->Extent[5] = VTK_DOUBLE_MAX; + + this->PointClipping = 0; + this->CellClipping = 0; + this->ExtentClipping = 0; + + this->Merging = 0; + this->Locator = NULL; +} + +// Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. +void vtkExtractUnstructuredGrid::SetExtent(double xMin,double xMax, double yMin, + double yMax, double zMin, double zMax) +{ + double extent[6]; + + extent[0] = xMin; + extent[1] = xMax; + extent[2] = yMin; + extent[3] = yMax; + extent[4] = zMin; + extent[5] = zMax; + + this->SetExtent(extent); +} + +// Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. +void vtkExtractUnstructuredGrid::SetExtent(double extent[6]) +{ + int i; + + if ( extent[0] != this->Extent[0] || extent[1] != this->Extent[1] || + extent[2] != this->Extent[2] || extent[3] != this->Extent[3] || + extent[4] != this->Extent[4] || extent[5] != this->Extent[5] ) + { + this->ExtentClippingOn(); + for (i=0; i<3; i++) + { + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + this->Extent[2*i] = extent[2*i]; + this->Extent[2*i+1] = extent[2*i+1]; + } + } +} + +// Extract cells and pass points and point data through. Also handles +// cell data. +int vtkExtractUnstructuredGrid::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, i, newCellId; + vtkIdType newPtId; + vtkIdType numPts=input->GetNumberOfPoints(); + vtkIdType numCells=input->GetNumberOfCells(); + vtkPoints *inPts=input->GetPoints(), *newPts; + char *cellVis; + vtkCell *cell; + double x[3]; + vtkIdList *ptIds; + vtkIdList *cellIds; + vtkIdType ptId; + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + int allVisible, numIds; + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkIdType *pointMap = NULL; + + vtkDebugMacro(<<"Executing extraction filter"); + + if ( numPts < 1 || numCells < 1 || !inPts ) + { + vtkDebugMacro(<<"No data to extract!"); + return 1; + } + cellIds=vtkIdList::New(); + + if ( (!this->CellClipping) && (!this->PointClipping) && + (!this->ExtentClipping) ) + { + allVisible = 1; + cellVis = NULL; + } + else + { + allVisible = 0; + cellVis = new char[numCells]; + } + + // Mark cells as being visible or not + if ( ! allVisible ) + { + for(cellId=0; cellId < numCells; cellId++) + { + if ( this->CellClipping && cellId < this->CellMinimum || + cellId > this->CellMaximum ) + { + cellVis[cellId] = 0; + } + else + { + cell = input->GetCell(cellId); + ptIds = cell->GetPointIds(); + numIds = ptIds->GetNumberOfIds(); + for (i=0; i < numIds; i++) + { + ptId = ptIds->GetId(i); + input->GetPoint(ptId, x); + + if ( (this->PointClipping && (ptId < this->PointMinimum || + ptId > this->PointMaximum) ) || + (this->ExtentClipping && + (x[0] < this->Extent[0] || x[0] > this->Extent[1] || + x[1] < this->Extent[2] || x[1] > this->Extent[3] || + x[2] < this->Extent[4] || x[2] > this->Extent[5] )) ) + { + cellVis[cellId] = 0; + break; + } + } + if ( i >= numIds ) + { + cellVis[cellId] = 1; + } + } + } + } + + // Allocate + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + output->Allocate(numCells); + outputPD->CopyAllocate(pd,numPts,numPts/2); + outputCD->CopyAllocate(cd,numCells,numCells/2); + + if ( this->Merging ) + { + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + } + else + { + pointMap = new vtkIdType[numPts]; + for (i=0; iGetCell(cellId); + numIds = cell->PointIds->GetNumberOfIds(); + cellIds->Reset(); + if ( this->Merging ) + { + for (i=0; i < numIds; i++) + { + ptId = cell->PointIds->GetId(i); + input->GetPoint(ptId, x); + if ( this->Locator->InsertUniquePoint(x, newPtId) ) + { + outputPD->CopyData(pd,ptId,newPtId); + } + cellIds->InsertNextId(newPtId); + } + }//merging coincident points + else + { + for (i=0; i < numIds; i++) + { + ptId = cell->PointIds->GetId(i); + if ( pointMap[ptId] < 0 ) + { + pointMap[ptId] = newPtId + = newPts->InsertNextPoint(inPts->GetPoint(ptId)); + outputPD->CopyData(pd, ptId, newPtId); + } + cellIds->InsertNextId(pointMap[ptId]); + } + }//keeping original point list + + newCellId = output->InsertNextCell(input->GetCellType(cellId), cellIds); + outputCD->CopyData(cd, cellId, newCellId); + + } //if cell is visible + } //for all cells + + // Update ourselves and release memory + output->SetPoints(newPts); + newPts->Delete(); + + vtkDebugMacro(<<"Extracted " << output->GetNumberOfPoints() << " points," + << output->GetNumberOfCells() << " cells."); + + if ( this->Merging && this->Locator ) + { + this->Locator->Initialize(); + } + else + { + delete [] pointMap; + } + output->Squeeze(); + + if ( cellVis ) + { + delete [] cellVis; + } + cellIds->Delete(); + + return 1; +} + +unsigned long int vtkExtractUnstructuredGrid::GetMTime() +{ + unsigned long mTime= this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} + +void vtkExtractUnstructuredGrid::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkExtractUnstructuredGrid::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkExtractUnstructuredGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Point Minimum : " << this->PointMinimum << "\n"; + os << indent << "Point Maximum : " << this->PointMaximum << "\n"; + + os << indent << "Cell Minimum : " << this->CellMinimum << "\n"; + os << indent << "Cell Maximum : " << this->CellMaximum << "\n"; + + os << indent << "Extent: \n"; + os << indent << " Xmin,Xmax: (" << this->Extent[0] << ", " << this->Extent[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->Extent[2] << ", " << this->Extent[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->Extent[4] << ", " << this->Extent[5] << ")\n"; + + os << indent << "PointClipping: " << (this->PointClipping ? "On\n" : "Off\n"); + os << indent << "CellClipping: " << (this->CellClipping ? "On\n" : "Off\n"); + os << indent << "ExtentClipping: " << (this->ExtentClipping ? "On\n" : "Off\n"); + + os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n"); + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/Graphics/vtkExtractUnstructuredGrid.h b/Graphics/vtkExtractUnstructuredGrid.h new file mode 100644 index 0000000..82093d1 --- /dev/null +++ b/Graphics/vtkExtractUnstructuredGrid.h @@ -0,0 +1,147 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractUnstructuredGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractUnstructuredGrid - extract subset of unstructured grid geometry +// .SECTION Description +// vtkExtractUnstructuredGrid is a general-purpose filter to +// extract geometry (and associated data) from an unstructured grid +// dataset. The extraction process is controlled by specifying a range +// of point ids, cell ids, or a bounding box (referred to as "Extent"). +// Those cells lying within these regions are sent to the output. +// The user has the choice of merging coincident points (Merging is on) +// or using the original point set (Merging is off). + +// .SECTION Caveats +// If merging is off, the input points are copied through to the +// output. This means unused points may be present in the output data. +// If merging is on, then coincident points with different point attribute +// values are merged. + +// .SECTION See Also +// vtkImageDataGeometryFilter vtkStructuredGridGeometryFilter +// vtkRectilinearGridGeometryFilter +// vtkExtractGeometry vtkExtractVOI + +#ifndef __vtkExtractUnstructuredGrid_h +#define __vtkExtractUnstructuredGrid_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkExtractUnstructuredGrid : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkExtractUnstructuredGrid,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with all types of clipping turned off. + static vtkExtractUnstructuredGrid *New(); + + // Description: + // Turn on/off selection of geometry by point id. + vtkSetMacro(PointClipping,int); + vtkGetMacro(PointClipping,int); + vtkBooleanMacro(PointClipping,int); + + // Description: + // Turn on/off selection of geometry by cell id. + vtkSetMacro(CellClipping,int); + vtkGetMacro(CellClipping,int); + vtkBooleanMacro(CellClipping,int); + + // Description: + // Turn on/off selection of geometry via bounding box. + vtkSetMacro(ExtentClipping,int); + vtkGetMacro(ExtentClipping,int); + vtkBooleanMacro(ExtentClipping,int); + + // Description: + // Specify the minimum point id for point id selection. + vtkSetClampMacro(PointMinimum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(PointMinimum,vtkIdType); + + // Description: + // Specify the maximum point id for point id selection. + vtkSetClampMacro(PointMaximum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(PointMaximum,vtkIdType); + + // Description: + // Specify the minimum cell id for point id selection. + vtkSetClampMacro(CellMinimum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(CellMinimum,vtkIdType); + + // Description: + // Specify the maximum cell id for point id selection. + vtkSetClampMacro(CellMaximum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(CellMaximum,vtkIdType); + + // Description: + // Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. + void SetExtent(double xMin, double xMax, double yMin, double yMax, + double zMin, double zMax); + + // Description: + // Set / get a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. + void SetExtent(double extent[6]); + double *GetExtent() { return this->Extent;}; + + // Description: + // Turn on/off merging of coincident points. Note that is merging is + // on, points with different point attributes (e.g., normals) are merged, + // which may cause rendering artifacts. + vtkSetMacro(Merging,int); + vtkGetMacro(Merging,int); + vtkBooleanMacro(Merging,int); + + // Description: + // Set / get a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + + // Description: + // Return the MTime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkExtractUnstructuredGrid(); + ~vtkExtractUnstructuredGrid() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkIdType PointMinimum; + vtkIdType PointMaximum; + vtkIdType CellMinimum; + vtkIdType CellMaximum; + double Extent[6]; + int PointClipping; + int CellClipping; + int ExtentClipping; + + int Merging; + vtkPointLocator *Locator; +private: + vtkExtractUnstructuredGrid(const vtkExtractUnstructuredGrid&); // Not implemented. + void operator=(const vtkExtractUnstructuredGrid&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkExtractVectorComponents.cxx b/Graphics/vtkExtractVectorComponents.cxx new file mode 100644 index 0000000..f0fdcc6 --- /dev/null +++ b/Graphics/vtkExtractVectorComponents.cxx @@ -0,0 +1,315 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractVectorComponents.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractVectorComponents.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDataObject.h" +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkExtractVectorComponents, "$Revision: 1.51 $"); +vtkStandardNewMacro(vtkExtractVectorComponents); + +vtkExtractVectorComponents::vtkExtractVectorComponents() +{ + this->ExtractToFieldData = 0; + this->SetNumberOfOutputPorts(3); + this->OutputsInitialized = 0; +} + +vtkExtractVectorComponents::~vtkExtractVectorComponents() +{ +} + +// Get the output dataset representing velocity x-component. If output is NULL +// then input hasn't been set, which is necessary for abstract objects. (Note: +// this method returns the same information as the GetOutput() method with an +// index of 0.) +vtkDataSet *vtkExtractVectorComponents::GetVxComponent() +{ + return this->GetOutput(0); +} + +// Get the output dataset representing velocity y-component. If output is NULL +// then input hasn't been set, which is necessary for abstract objects. (Note: +// this method returns the same information as the GetOutput() method with an +// index of 1.) +vtkDataSet *vtkExtractVectorComponents::GetVyComponent() +{ + return this->GetOutput(1); +} + +// Get the output dataset representing velocity z-component. If output is NULL +// then input hasn't been set, which is necessary for abstract objects. (Note: +// this method returns the same information as the GetOutput() method with an +// index of 2.) +vtkDataSet *vtkExtractVectorComponents::GetVzComponent() +{ + return this->GetOutput(2); +} + +// Specify the input data or filter. +void vtkExtractVectorComponents::SetInput(vtkDataSet *input) +{ + if (this->GetNumberOfInputConnections(0) > 0 && this->GetInput(0) == input ) + { + return; + } + + this->Superclass::SetInput(0, input); + + if ( input == NULL ) + { + return; + } + + vtkDataSet *output; + if ( ! this->OutputsInitialized ) + { + output = input->NewInstance(); + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + output = input->NewInstance(); + this->GetExecutive()->SetOutputData(1, output); + output->Delete(); + output = input->NewInstance(); + this->GetExecutive()->SetOutputData(2, output); + output->Delete(); + this->OutputsInitialized = 1; + return; + } + + // since the input has changed we might need to create a new output + // It seems that output 0 is the correct type as a result of the call to + // the superclass's SetInput. Check the type of output 1 instead. + if (strcmp(this->GetOutput(1)->GetClassName(),input->GetClassName())) + { + output = input->NewInstance(); + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + output = input->NewInstance(); + this->GetExecutive()->SetOutputData(1, output); + output->Delete(); + output = input->NewInstance(); + this->GetExecutive()->SetOutputData(2, output); + output->Delete(); + vtkWarningMacro(<<" a new output had to be created since the input type changed."); + } +} + +template +void vtkExtractComponents(int numVectors, T* vectors, T* vx, T* vy, T* vz) +{ + for (int i=0; iGetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int numVectors = 0, numVectorsc = 0; + vtkDataArray *vectors, *vectorsc; + vtkDataArray *vx, *vy, *vz; + vtkDataArray *vxc, *vyc, *vzc; + vtkPointData *pd, *outVx, *outVy=0, *outVz=0; + vtkCellData *cd, *outVxc, *outVyc=0, *outVzc=0; + + vtkDebugMacro(<<"Extracting vector components..."); + + // taken out of previous update method. + output->CopyStructure(input); + if (!this->ExtractToFieldData) + { + this->GetVyComponent()->CopyStructure(input); + this->GetVzComponent()->CopyStructure(input); + } + + pd = input->GetPointData(); + cd = input->GetCellData(); + outVx = output->GetPointData(); + outVxc = output->GetCellData(); + if (!this->ExtractToFieldData) + { + outVy = this->GetVyComponent()->GetPointData(); + outVz = this->GetVzComponent()->GetPointData(); + outVyc = this->GetVyComponent()->GetCellData(); + outVzc = this->GetVzComponent()->GetCellData(); + } + + vectors = pd->GetVectors(); + vectorsc = cd->GetVectors(); + if ( (vectors == NULL || + ((numVectors = vectors->GetNumberOfTuples()) < 1) ) && + (vectorsc == NULL || + ((numVectorsc = vectorsc->GetNumberOfTuples()) < 1))) + { + vtkErrorMacro(<<"No vector data to extract!"); + return 1; + } + + const char* name; + if (vectors) + { + name = vectors->GetName(); + } + else if (vectorsc) + { + name = vectorsc->GetName(); + } + else + { + name = 0; + } + + char* newName; + if (name) + { + newName = new char[strlen(name)+10]; + } + else + { + newName = new char[10]; + name = ""; + } + + if (vectors) + { + vx = vtkDataArray::CreateDataArray(vectors->GetDataType()); + vx->SetNumberOfTuples(numVectors); + sprintf(newName, "%s-x", name); + vx->SetName(newName); + vy = vtkDataArray::CreateDataArray(vectors->GetDataType()); + vy->SetNumberOfTuples(numVectors); + sprintf(newName, "%s-y", name); + vy->SetName(newName); + vz = vtkDataArray::CreateDataArray(vectors->GetDataType()); + vz->SetNumberOfTuples(numVectors); + sprintf(newName, "%s-z", name); + vz->SetName(newName); + + switch (vectors->GetDataType()) + { + vtkTemplateMacro( + vtkExtractComponents(numVectors, + (VTK_TT *)vectors->GetVoidPointer(0), + (VTK_TT *)vx->GetVoidPointer(0), + (VTK_TT *)vy->GetVoidPointer(0), + (VTK_TT *)vz->GetVoidPointer(0))); + } + + outVx->PassData(pd); + outVx->AddArray(vx); + outVx->SetActiveScalars(vx->GetName()); + vx->Delete(); + + if (this->ExtractToFieldData) + { + outVx->AddArray(vy); + outVx->AddArray(vz); + } + else + { + outVy->PassData(pd); + outVy->AddArray(vy); + outVy->SetActiveScalars(vy->GetName()); + + outVz->PassData(pd); + outVz->AddArray(vz); + outVz->SetActiveScalars(vz->GetName()); + } + vy->Delete(); + vz->Delete(); + } + + if (vectorsc) + { + vxc = vtkDataArray::CreateDataArray(vectorsc->GetDataType()); + vxc->SetNumberOfTuples(numVectorsc); + sprintf(newName, "%s-x", name); + vxc->SetName(newName); + vyc = vtkDataArray::CreateDataArray(vectorsc->GetDataType()); + vyc->SetNumberOfTuples(numVectorsc); + sprintf(newName, "%s-y", name); + vyc->SetName(newName); + vzc = vtkDataArray::CreateDataArray(vectorsc->GetDataType()); + vzc->SetNumberOfTuples(numVectorsc); + sprintf(newName, "%s-z", name); + vzc->SetName(newName); + + switch (vectorsc->GetDataType()) + { + vtkTemplateMacro( + vtkExtractComponents( numVectorsc, + (VTK_TT *)vectorsc->GetVoidPointer(0), + (VTK_TT *)vxc->GetVoidPointer(0), + (VTK_TT *)vyc->GetVoidPointer(0), + (VTK_TT *)vzc->GetVoidPointer(0))); + } + + outVxc->PassData(cd); + outVxc->AddArray(vxc); + outVxc->SetActiveScalars(vxc->GetName()); + vxc->Delete(); + + if (this->ExtractToFieldData) + { + outVxc->AddArray(vyc); + outVxc->AddArray(vzc); + } + else + { + outVyc->PassData(cd); + outVyc->AddArray(vyc); + outVyc->SetActiveScalars(vyc->GetName()); + + outVzc->PassData(cd); + outVzc->AddArray(vzc); + outVzc->SetActiveScalars(vzc->GetName()); + } + vyc->Delete(); + vzc->Delete(); + } + delete[] newName; + + return 1; +} + +void vtkExtractVectorComponents::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ExtractToFieldData: " << this->ExtractToFieldData << endl; +} diff --git a/Graphics/vtkExtractVectorComponents.h b/Graphics/vtkExtractVectorComponents.h new file mode 100644 index 0000000..4f0eb05 --- /dev/null +++ b/Graphics/vtkExtractVectorComponents.h @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractVectorComponents.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractVectorComponents - extract components of vector as separate scalars +// .SECTION Description +// vtkExtractVectorComponents is a filter that extracts vector components as +// separate scalars. This is accomplished by creating three different outputs. +// Each output is the same as the input, except that the scalar values will be +// one of the three components of the vector. These can be found in the +// VxComponent, VyComponent, and VzComponent. +// Alternatively, if the ExtractToFieldData flag is set, the filter will +// put all the components in the field data. The first component will be +// the scalar and the others will be non-attribute arrays. + +// .SECTION Caveats +// This filter is unusual in that it creates multiple outputs. +// If you use the GetOutput() method, you will be retrieving the x vector +// component. + +#ifndef __vtkExtractVectorComponents_h +#define __vtkExtractVectorComponents_h + +#include "vtkDataSetAlgorithm.h" + +class vtkDataSet; + +class VTK_GRAPHICS_EXPORT vtkExtractVectorComponents : public vtkDataSetAlgorithm +{ +public: + static vtkExtractVectorComponents *New(); + vtkTypeRevisionMacro(vtkExtractVectorComponents,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the input data or filter. + virtual void SetInput(vtkDataSet *input); + + // Description: + // Get the output dataset representing velocity x-component. If output is + // NULL then input hasn't been set, which is necessary for abstract + // objects. (Note: this method returns the same information as the + // GetOutput() method with an index of 0.) + vtkDataSet *GetVxComponent(); + + // Description: + // Get the output dataset representing velocity y-component. If output is + // NULL then input hasn't been set, which is necessary for abstract + // objects. (Note: this method returns the same information as the + // GetOutput() method with an index of 1.) + // Note that if ExtractToFieldData is true, this output will be empty. + vtkDataSet *GetVyComponent(); + + // Description: + // Get the output dataset representing velocity z-component. If output is + // NULL then input hasn't been set, which is necessary for abstract + // objects. (Note: this method returns the same information as the + // GetOutput() method with an index of 2.) + // Note that if ExtractToFieldData is true, this output will be empty. + vtkDataSet *GetVzComponent(); + + // Description: + // Determines whether the vector components will be put + // in separate outputs or in the first output's field data + vtkSetMacro(ExtractToFieldData, int); + vtkGetMacro(ExtractToFieldData, int); + vtkBooleanMacro(ExtractToFieldData, int); + +protected: + vtkExtractVectorComponents(); + ~vtkExtractVectorComponents(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int ExtractToFieldData; + int OutputsInitialized; +private: + vtkExtractVectorComponents(const vtkExtractVectorComponents&); // Not implemented. + void operator=(const vtkExtractVectorComponents&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkFeatureEdges.cxx b/Graphics/vtkFeatureEdges.cxx new file mode 100644 index 0000000..ab8e0e7 --- /dev/null +++ b/Graphics/vtkFeatureEdges.cxx @@ -0,0 +1,451 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFeatureEdges.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFeatureEdges.h" + +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTriangleStrip.h" +#include "vtkUnsignedCharArray.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkFeatureEdges, "$Revision: 1.72 $"); +vtkStandardNewMacro(vtkFeatureEdges); + +// Construct object with feature angle = 30; all types of edges, except +// manifold edges, are extracted and colored. +vtkFeatureEdges::vtkFeatureEdges() +{ + this->FeatureAngle = 30.0; + this->BoundaryEdges = 1; + this->FeatureEdges = 1; + this->NonManifoldEdges = 1; + this->ManifoldEdges = 0; + this->Coloring = 1; + this->Locator = NULL; +} + +vtkFeatureEdges::~vtkFeatureEdges() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +// Generate feature edges for mesh +int vtkFeatureEdges::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts; + vtkPoints *newPts; + vtkFloatArray *newScalars = NULL; + vtkCellArray *newLines; + vtkPolyData *Mesh; + int i; + vtkIdType j, numNei, cellId; + vtkIdType numBEdges, numNonManifoldEdges, numFedges, numManifoldEdges; + double scalar, n[3], x1[3], x2[3]; + double cosAngle = 0; + vtkIdType lineIds[2]; + vtkIdType npts = 0; + vtkIdType *pts = 0; + vtkCellArray *inPolys, *inStrips, *newPolys; + vtkFloatArray *polyNormals = NULL; + vtkIdType numPts, numCells, numPolys, numStrips, nei; + vtkIdList *neighbors; + vtkIdType p1, p2, newId; + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + unsigned char* ghostLevels=0; + unsigned char updateLevel = (unsigned char)(output->GetUpdateGhostLevel()); + + vtkDebugMacro(<<"Executing feature edges"); + + vtkDataArray* temp = 0; + if (cd) + { + temp = cd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + ghostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + // Check input + // + inPts=input->GetPoints(); + numCells = input->GetNumberOfCells(); + numPolys = input->GetNumberOfPolys(); + numStrips = input->GetNumberOfStrips(); + if ( (numPts=input->GetNumberOfPoints()) < 1 || !inPts || + (numPolys < 1 && numStrips < 1) ) + { + vtkDebugMacro(<<"No input data!"); + return 1; + } + + if ( !this->BoundaryEdges && !this->NonManifoldEdges && + !this->FeatureEdges && !this->ManifoldEdges ) + { + vtkDebugMacro(<<"All edge types turned off!"); + } + + // Build cell structure. Might have to triangulate the strips. + Mesh = vtkPolyData::New(); + Mesh->SetPoints(inPts); + inPolys=input->GetPolys(); + if ( numStrips > 0 ) + { + newPolys = vtkCellArray::New(); + if ( numPolys > 0 ) + { + newPolys->DeepCopy(inPolys); + } + else + { + newPolys->Allocate(newPolys->EstimateSize(numStrips,5)); + } + inStrips = input->GetStrips(); + for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + vtkTriangleStrip::DecomposeStrip(npts, pts, newPolys); + } + Mesh->SetPolys(newPolys); + newPolys->Delete(); + } + else + { + newPolys = inPolys; + Mesh->SetPolys(newPolys); + } + Mesh->BuildLinks(); + + // Allocate storage for lines/points (arbitrary allocation sizes) + // + newPts = vtkPoints::New(); + newPts->Allocate(numPts/10,numPts); + newLines = vtkCellArray::New(); + newLines->Allocate(numPts/10); + if ( this->Coloring ) + { + newScalars = vtkFloatArray::New(); + newScalars->SetName("Edge Types"); + newScalars->Allocate(numCells/10,numCells); + } + + outPD->CopyAllocate(pd, numPts); + outCD->CopyAllocate(cd, numCells); + + // Get our locator for merging points + // + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + + // Loop over all polygons generating boundary, non-manifold, + // and feature edges + // + if ( this->FeatureEdges ) + { + polyNormals = vtkFloatArray::New(); + polyNormals->SetNumberOfComponents(3); + polyNormals->Allocate(3*newPolys->GetNumberOfCells()); + + for (cellId=0, newPolys->InitTraversal(); newPolys->GetNextCell(npts,pts); + cellId++) + { + vtkPolygon::ComputeNormal(inPts,npts,pts,n); + polyNormals->InsertTuple(cellId,n); + } + + cosAngle = cos ((double) vtkMath::DegreesToRadians() * this->FeatureAngle); + } + + neighbors = vtkIdList::New(); + neighbors->Allocate(VTK_CELL_SIZE); + + int abort=0; + vtkIdType progressInterval=numCells/20+1; + + numBEdges = numNonManifoldEdges = numFedges = numManifoldEdges = 0; + for (cellId=0, newPolys->InitTraversal(); + newPolys->GetNextCell(npts,pts) && !abort; cellId++) + { + if ( ! (cellId % progressInterval) ) //manage progress / early abort + { + this->UpdateProgress ((double)cellId / numCells); + abort = this->GetAbortExecute(); + } + + for (i=0; i < npts; i++) + { + p1 = pts[i]; + p2 = pts[(i+1)%npts]; + + Mesh->GetCellEdgeNeighbors(cellId,p1,p2, neighbors); + numNei = neighbors->GetNumberOfIds(); + + if ( this->BoundaryEdges && numNei < 1 ) + { + if (ghostLevels && ghostLevels[cellId] > updateLevel) + { + continue; + } + else + { + numBEdges++; + scalar = 0.0; + } + } + + else if ( this->NonManifoldEdges && numNei > 1 ) + { + // check to make sure that this edge hasn't been created before + for (j=0; j < numNei; j++) + { + if ( neighbors->GetId(j) < cellId ) + { + break; + } + } + if ( j >= numNei ) + { + if (ghostLevels && ghostLevels[cellId] > updateLevel) + { + continue; + } + else + { + numNonManifoldEdges++; + scalar = 0.222222; + } + } + else + { + continue; + } + } + else if ( this->FeatureEdges && + numNei == 1 && (nei=neighbors->GetId(0)) > cellId ) + { + double neiTuple[3]; + double cellTuple[3]; + polyNormals->GetTuple(nei, neiTuple); + polyNormals->GetTuple(cellId, cellTuple); + if ( vtkMath::Dot(neiTuple, cellTuple) <= cosAngle ) + { + if (ghostLevels && ghostLevels[cellId] > updateLevel) + { + continue; + } + else + { + numFedges++; + scalar = 0.444444; + } + } + else + { + continue; + } + } + else if ( this->ManifoldEdges && + numNei == 1 && neighbors->GetId(0) > cellId ) + { + if (ghostLevels && ghostLevels[cellId] > updateLevel) + { + continue; + } + else + { + numManifoldEdges++; + scalar = 0.666667; + } + } + else + { + continue; + } + + // Add edge to output + Mesh->GetPoint(p1, x1); + Mesh->GetPoint(p2, x2); + + if ( this->Locator->InsertUniquePoint(x1, lineIds[0]) ) + { + outPD->CopyData (pd,p1,lineIds[0]); + } + + if ( this->Locator->InsertUniquePoint(x2, lineIds[1]) ) + { + outPD->CopyData (pd,p2,lineIds[1]); + } + + newId = newLines->InsertNextCell(2,lineIds); + outCD->CopyData (cd,cellId,newId); + if ( this->Coloring ) + { + newScalars->InsertTuple(newId, &scalar); + } + } + } + + vtkDebugMacro(<<"Created " << numBEdges << " boundary edges, " + << numNonManifoldEdges << " non-manifold edges, " + << numFedges << " feature edges, " + << numManifoldEdges << " manifold edges"); + + // Update ourselves. + // + if ( this->FeatureEdges ) + { + polyNormals->Delete(); + } + + Mesh->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + neighbors->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + if ( this->Coloring ) + { + int idx = outCD->AddArray(newScalars); + outCD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + return 1; +} + +void vtkFeatureEdges::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkFeatureEdges::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +unsigned long int vtkFeatureEdges::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} + +int vtkFeatureEdges::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int numPieces, ghostLevel; + + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevel = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + if (numPieces > 1) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel + 1); + } + + return 1; +} + +void vtkFeatureEdges::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Feature Angle: " << this->FeatureAngle << "\n"; + os << indent << "Boundary Edges: " << (this->BoundaryEdges ? "On\n" : "Off\n"); + os << indent << "Feature Edges: " << (this->FeatureEdges ? "On\n" : "Off\n"); + os << indent << "Non-Manifold Edges: " << (this->NonManifoldEdges ? "On\n" : "Off\n"); + os << indent << "Manifold Edges: " << (this->ManifoldEdges ? "On\n" : "Off\n"); + os << indent << "Coloring: " << (this->Coloring ? "On\n" : "Off\n"); + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/Graphics/vtkFeatureEdges.h b/Graphics/vtkFeatureEdges.h new file mode 100644 index 0000000..54cc2e0 --- /dev/null +++ b/Graphics/vtkFeatureEdges.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFeatureEdges.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFeatureEdges - extract boundary, non-manifold, and/or sharp edges from polygonal data +// .SECTION Description +// vtkFeatureEdges is a filter to extract special types of edges from +// input polygonal data. These edges are either 1) boundary (used by +// one polygon) or a line cell; 2) non-manifold (used by three or more +// polygons); 3) feature edges (edges used by two triangles and whose +// dihedral angle > FeatureAngle); or 4) manifold edges (edges used by +// exactly two polygons). These edges may be extracted in any +// combination. Edges may also be "colored" (i.e., scalar values assigned) +// based on edge type. The cell coloring is assigned to the cell data of +// the extracted edges. + +// .SECTION Caveats +// To see the coloring of the liens you may have to set the ScalarMode +// instance variable of the mapper to SetScalarModeToUseCellData(). (This +// is only a problem if there are point data scalars.) + +// .SECTION See Also +// vtkExtractEdges + +#ifndef __vtkFeatureEdges_h +#define __vtkFeatureEdges_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkFeatureEdges : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkFeatureEdges,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with feature angle = 30; all types of edges extracted + // and colored. + static vtkFeatureEdges *New(); + + // Description: + // Turn on/off the extraction of boundary edges. + vtkSetMacro(BoundaryEdges,int); + vtkGetMacro(BoundaryEdges,int); + vtkBooleanMacro(BoundaryEdges,int); + + // Description: + // Turn on/off the extraction of feature edges. + vtkSetMacro(FeatureEdges,int); + vtkGetMacro(FeatureEdges,int); + vtkBooleanMacro(FeatureEdges,int); + + // Description: + // Specify the feature angle for extracting feature edges. + vtkSetClampMacro(FeatureAngle,double,0.0,180.0); + vtkGetMacro(FeatureAngle,double); + + // Description: + // Turn on/off the extraction of non-manifold edges. + vtkSetMacro(NonManifoldEdges,int); + vtkGetMacro(NonManifoldEdges,int); + vtkBooleanMacro(NonManifoldEdges,int); + + // Description: + // Turn on/off the extraction of manifold edges. + vtkSetMacro(ManifoldEdges,int); + vtkGetMacro(ManifoldEdges,int); + vtkBooleanMacro(ManifoldEdges,int); + + // Description: + // Turn on/off the coloring of edges by type. + vtkSetMacro(Coloring,int); + vtkGetMacro(Coloring,int); + vtkBooleanMacro(Coloring,int); + + // Description: + // Set / get a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + + // Description: + // Return MTime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkFeatureEdges(); + ~vtkFeatureEdges(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double FeatureAngle; + int BoundaryEdges; + int FeatureEdges; + int NonManifoldEdges; + int ManifoldEdges; + int Coloring; + vtkPointLocator *Locator; +private: + vtkFeatureEdges(const vtkFeatureEdges&); // Not implemented. + void operator=(const vtkFeatureEdges&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkFieldDataToAttributeDataFilter.cxx b/Graphics/vtkFieldDataToAttributeDataFilter.cxx new file mode 100644 index 0000000..ab266e5 --- /dev/null +++ b/Graphics/vtkFieldDataToAttributeDataFilter.cxx @@ -0,0 +1,1187 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFieldDataToAttributeDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFieldDataToAttributeDataFilter.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkFieldDataToAttributeDataFilter, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkFieldDataToAttributeDataFilter); + +// Instantiate object with no input and no defined output. +vtkFieldDataToAttributeDataFilter::vtkFieldDataToAttributeDataFilter() +{ + int i; + + this->InputField = VTK_DATA_OBJECT_FIELD; + this->OutputAttributeData = VTK_POINT_DATA; + this->DefaultNormalize = 0; + + this->NumberOfScalarComponents = 0; + for (i=0; i < 4; i++) + { + this->ScalarArrays[i] = NULL; + this->ScalarArrayComponents[i] = -1; //uninitialized + this->ScalarComponentRange[i][0] = this->ScalarComponentRange[i][1] = -1; + this->ScalarNormalize[i] = 1; //yes, normalize + } + + for (i=0; i < 3; i++) + { + this->VectorArrays[i] = NULL; + this->VectorArrayComponents[i] = -1; //uninitialized + this->VectorComponentRange[i][0] = this->VectorComponentRange[i][1] = -1; + this->VectorNormalize[i] = 1; //yes, normalize + } + + for (i=0; i < 3; i++) + { + this->NormalArrays[i] = NULL; + this->NormalArrayComponents[i] = -1; //uninitialized + this->NormalComponentRange[i][0] = this->NormalComponentRange[i][1] = -1; + this->NormalNormalize[i] = 1; //yes, normalize + } + + this->NumberOfTCoordComponents = 0; + for (i=0; i < 3; i++) + { + this->TCoordArrays[i] = NULL; + this->TCoordArrayComponents[i] = -1; //uninitialized + this->TCoordComponentRange[i][0] = this->TCoordComponentRange[i][1] = -1; + this->TCoordNormalize[i] = 1; //yes, normalize + } + + for (i=0; i < 9; i++) + { + this->TensorArrays[i] = NULL; + this->TensorArrayComponents[i] = -1; //uninitialized + this->TensorComponentRange[i][0] = this->TensorComponentRange[i][1] = -1; + this->TensorNormalize[i] = 1; //yes, normalize + } +} + +vtkFieldDataToAttributeDataFilter::~vtkFieldDataToAttributeDataFilter() +{ + int i; + + for (i=0; i<4; i++) + { + if ( this->ScalarArrays[i] != NULL ) + { + delete [] this->ScalarArrays[i]; + } + } + + for (i=0; i<3; i++) + { + if ( this->VectorArrays[i] != NULL ) + { + delete [] this->VectorArrays[i]; + } + } + + for (i=0; i<3; i++) + { + if ( this->NormalArrays[i] != NULL ) + { + delete [] this->NormalArrays[i]; + } + } + + for (i=0; i<3; i++) + { + if ( this->TCoordArrays[i] != NULL ) + { + delete [] this->TCoordArrays[i]; + } + } + + for (i=0; i<9; i++) + { + if ( this->TensorArrays[i] != NULL ) + { + delete [] this->TensorArrays[i]; + } + } + +} + +// Stuff related to filter interface------------------------------------------ +// +int vtkFieldDataToAttributeDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType num; + vtkDataSetAttributes *attr; + vtkFieldData *fd; + vtkDebugMacro(<<"Generating attribute data from field data"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + // Pass here so that the attributes/fields can be over-written later + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + if ( this->OutputAttributeData == VTK_CELL_DATA ) + { + attr = output->GetCellData(); + num = input->GetNumberOfCells(); + } + else + { + attr = output->GetPointData(); + num = input->GetNumberOfPoints(); + } + + if ( num < 1 ) + { + vtkDebugMacro(<<"No input points/cells to create attribute data for"); + return 1; + } + + fd = NULL; + if ( this->InputField == VTK_DATA_OBJECT_FIELD ) + { + fd = input->GetFieldData(); + } + else if ( this->InputField == VTK_POINT_DATA_FIELD ) + { + fd = input->GetPointData(); + } + else if ( this->InputField == VTK_CELL_DATA_FIELD ) + { + fd = input->GetCellData(); + } + if ( fd == NULL ) + { + vtkErrorMacro(<<"No field data available"); + return 1; + } + + this->ConstructScalars(num, fd, attr, this->ScalarComponentRange, + this->ScalarArrays, this->ScalarArrayComponents, + this->ScalarNormalize,this->NumberOfScalarComponents); + this->ConstructVectors(num, fd, attr, this->VectorComponentRange, + this->VectorArrays, this->VectorArrayComponents, + this->VectorNormalize); + this->ConstructTensors(num, fd, attr, this->TensorComponentRange, + this->TensorArrays, this->TensorArrayComponents, + this->TensorNormalize); + this->ConstructTCoords(num, fd, attr, this->TCoordComponentRange, + this->TCoordArrays, this->TCoordArrayComponents, + this->TCoordNormalize,this->NumberOfTCoordComponents); + this->ConstructNormals(num, fd, attr, this->NormalComponentRange, + this->NormalArrays, this->NormalArrayComponents, + this->NormalNormalize); + this->ConstructFieldData(num, attr); + + return 1; +} + +void vtkFieldDataToAttributeDataFilter::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Input Field: "; + if ( this->InputField == VTK_DATA_OBJECT_FIELD ) + { + os << "DataObjectField\n"; + } + else if ( this->InputField == VTK_POINT_DATA_FIELD ) + { + os << "PointDataField\n"; + } + else //if ( this->InputField == VTK_CELL_DATA_FIELD ) + { + os << "CellDataField\n"; + } + + os << indent << "Default Normalize: " + << (this->DefaultNormalize ? "On\n" : "Off\n"); + + os << indent << "Output Attribute Data: "; + if ( this->OutputAttributeData == VTK_CELL_DATA ) + { + os << "CellData\n"; + } + else //if ( this->OutputAttributeData == VTK_POINT_DATA ) + { + os << "PointData\n"; + } +} + +// Stuff related to scalars -------------------------------------------- +// +void vtkFieldDataToAttributeDataFilter::SetScalarComponent(int comp, const char *arrayName, + int arrayComp, int min, int max, int normalize) +{ + if ( comp < 0 || comp > 3 ) + { + vtkErrorMacro(<<"Scalar component must be between (0,3)"); + return; + } + + if ( comp >= this->NumberOfScalarComponents ) + { + this->NumberOfScalarComponents = comp + 1; + } + this->SetArrayName(this, this->ScalarArrays[comp], arrayName); + if ( this->ScalarArrayComponents[comp] != arrayComp ) + { + this->ScalarArrayComponents[comp] = arrayComp; + this->Modified(); + } + if ( this->ScalarComponentRange[comp][0] != min ) + { + this->ScalarComponentRange[comp][0] = min; + this->Modified(); + } + if ( this->ScalarComponentRange[comp][1] != max ) + { + this->ScalarComponentRange[comp][1] = max; + this->Modified(); + } + if ( this->ScalarNormalize[comp] != normalize ) + { + this->ScalarNormalize[comp] = normalize; + this->Modified(); + } +} + +const char *vtkFieldDataToAttributeDataFilter::GetScalarComponentArrayName(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 3 ? 3 : comp)); + return this->ScalarArrays[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetScalarComponentArrayComponent(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 3 ? 3 : comp)); + return this->ScalarArrayComponents[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetScalarComponentMinRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 3 ? 3 : comp)); + return this->ScalarComponentRange[comp][0]; +} + +int vtkFieldDataToAttributeDataFilter::GetScalarComponentMaxRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 3 ? 3 : comp)); + return this->ScalarComponentRange[comp][1]; +} + +int vtkFieldDataToAttributeDataFilter::GetScalarComponentNormalizeFlag(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 3 ? 3 : comp)); + return this->ScalarNormalize[comp]; +} + +void vtkFieldDataToAttributeDataFilter::ConstructScalars(int num, vtkFieldData *fd, + vtkDataSetAttributes *attr, + vtkIdType componentRange[4][2], + char *arrays[4], int arrayComp[4], + int normalize[4], int numComp) +{ + int i, normalizeAny, updated=0; + vtkDataArray *fieldArray[4]; + + if ( numComp < 1 ) + { + return; + } + for (i=0; iGetFieldArray(fd, arrays[i], arrayComp[i]); + + if ( fieldArray[i] == NULL ) + { + vtkErrorMacro(<<"Can't find array/component requested"); + return; + } + } + + for (normalizeAny=i=0; i < numComp; i++) + { + updated |= this->UpdateComponentRange(fieldArray[i], componentRange[i]); + if ( num != (componentRange[i][1] - componentRange[i][0] + 1) ) + { + vtkErrorMacro(<<"Number of scalars not consistent"); + return; + } + normalizeAny |= normalize[i]; + } + + vtkDataArray *newScalars; + for (i=1; i < numComp; i++) //see whether all the data is from the same array + { + if ( fieldArray[i] != fieldArray[i-1] ) + { + break; + } + } + + // see whether we can reuse the data array from the field + if ( i >= numComp && fieldArray[0]->GetNumberOfComponents() == numComp && + fieldArray[0]->GetNumberOfTuples() == num && !normalizeAny ) + { + newScalars = fieldArray[0]; + newScalars->Register(0); + } + else //have to copy data into created array + { + newScalars = vtkDataArray::CreateDataArray(this->GetComponentsType(numComp, + fieldArray)); + newScalars->SetNumberOfTuples(num); + + for ( i=0; i < numComp; i++ ) + { + if ( this->ConstructArray(newScalars, i, fieldArray[i], arrayComp[i], + componentRange[i][0], componentRange[i][1], + normalize[i]) == 0 ) + { + newScalars->Delete(); + return; + } + } + } + + attr->SetScalars(newScalars); + newScalars->Delete(); + if ( updated ) //reset for next execution pass + { + for (i=0; i < numComp; i++) + { + componentRange[i][0] = componentRange[i][1] = -1; + } + } +} + +// Stuff related to vectors -------------------------------------------- +// +void vtkFieldDataToAttributeDataFilter::SetVectorComponent(int comp, const char *arrayName, + int arrayComp, int min, int max, int normalize) +{ + if ( comp < 0 || comp > 2 ) + { + vtkErrorMacro(<<"Vector component must be between (0,2)"); + return; + } + + this->SetArrayName(this, this->VectorArrays[comp], arrayName); + if ( this->VectorArrayComponents[comp] != arrayComp ) + { + this->VectorArrayComponents[comp] = arrayComp; + this->Modified(); + } + if ( this->VectorComponentRange[comp][0] != min ) + { + this->VectorComponentRange[comp][0] = min; + this->Modified(); + } + if ( this->VectorComponentRange[comp][1] != max ) + { + this->VectorComponentRange[comp][1] = max; + this->Modified(); + } + if ( this->VectorNormalize[comp] != normalize ) + { + this->VectorNormalize[comp] = normalize; + this->Modified(); + } +} + +const char *vtkFieldDataToAttributeDataFilter::GetVectorComponentArrayName(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->VectorArrays[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetVectorComponentArrayComponent(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->VectorArrayComponents[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetVectorComponentMinRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->VectorComponentRange[comp][0]; +} + +int vtkFieldDataToAttributeDataFilter::GetVectorComponentMaxRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->VectorComponentRange[comp][1]; +} + +int vtkFieldDataToAttributeDataFilter::GetVectorComponentNormalizeFlag(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->VectorNormalize[comp]; +} + +void vtkFieldDataToAttributeDataFilter::ConstructVectors(int num, vtkFieldData *fd, + vtkDataSetAttributes *attr, + vtkIdType componentRange[3][2], + char *arrays[3], + int arrayComp[3], int normalize[3]) +{ + int i, updated; + vtkDataArray *fieldArray[3]; + + for (i=0; i<3; i++) + { + if ( arrays[i] == NULL ) + { + return; + } + } + + for ( i=0; i < 3; i++ ) + { + fieldArray[i] = this->GetFieldArray(fd, arrays[i], arrayComp[i]); + + if ( fieldArray[i] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested"); + return; + } + } + + updated = this->UpdateComponentRange(fieldArray[0], componentRange[0]); + updated |= this->UpdateComponentRange(fieldArray[1], componentRange[1]); + updated |= this->UpdateComponentRange(fieldArray[2], componentRange[2]); + + if ( num != (componentRange[0][1] - componentRange[0][0] + 1) || + num != (componentRange[1][1] - componentRange[1][0] + 1) || + num != (componentRange[2][1] - componentRange[2][0] + 1) ) + { + vtkErrorMacro(<<"Number of vectors not consistent"); + return; + } + + vtkDataArray *newVectors; + if ( fieldArray[0]->GetNumberOfComponents() == 3 && + fieldArray[0] == fieldArray[1] && fieldArray[1] == fieldArray[2] && + fieldArray[0]->GetNumberOfTuples() == num && + !normalize[0] && !normalize[1] && !normalize[2] ) + { + newVectors = fieldArray[0]; + newVectors->Register(0); + } + else //have to copy data into created array + { + newVectors = vtkDataArray::CreateDataArray(this->GetComponentsType(3,fieldArray)); + newVectors->SetNumberOfComponents(3); + newVectors->SetNumberOfTuples(num); + + for ( i=0; i < 3; i++ ) + { + if ( this->ConstructArray(newVectors, i, fieldArray[i], arrayComp[i], + componentRange[i][0], componentRange[i][1], + normalize[i]) == 0 ) + { + newVectors->Delete(); + return; + } + } + } + + attr->SetVectors(newVectors); + newVectors->Delete(); + if ( updated ) //reset for next execution pass + { + for (i=0; i < 3; i++) + { + componentRange[i][0] = componentRange[i][1] = -1; + } + } +} + + +// Stuff related to normals -------------------------------------------- +// +void vtkFieldDataToAttributeDataFilter::SetNormalComponent(int comp, const char *arrayName, + int arrayComp, int min, int max, int normalize) +{ + if ( comp < 0 || comp > 2 ) + { + vtkErrorMacro(<<"Normal component must be between (0,2)"); + return; + } + + this->SetArrayName(this, this->NormalArrays[comp], arrayName); + if ( this->NormalArrayComponents[comp] != arrayComp ) + { + this->NormalArrayComponents[comp] = arrayComp; + this->Modified(); + } + if ( this->NormalComponentRange[comp][0] != min ) + { + this->NormalComponentRange[comp][0] = min; + this->Modified(); + } + if ( this->NormalComponentRange[comp][1] != max ) + { + this->NormalComponentRange[comp][1] = max; + this->Modified(); + } + if ( this->NormalNormalize[comp] != normalize ) + { + this->NormalNormalize[comp] = normalize; + this->Modified(); + } +} + +const char *vtkFieldDataToAttributeDataFilter::GetNormalComponentArrayName(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->NormalArrays[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetNormalComponentArrayComponent(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->NormalArrayComponents[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetNormalComponentMinRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->NormalComponentRange[comp][0]; +} + +int vtkFieldDataToAttributeDataFilter::GetNormalComponentMaxRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->NormalComponentRange[comp][1]; +} + +int vtkFieldDataToAttributeDataFilter::GetNormalComponentNormalizeFlag(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->NormalNormalize[comp]; +} + +void vtkFieldDataToAttributeDataFilter::ConstructNormals(int num, vtkFieldData *fd, + vtkDataSetAttributes *attr, + vtkIdType componentRange[3][2], + char *arrays[3], int arrayComp[3], + int normalize[3]) +{ + int i, updated; + vtkDataArray *fieldArray[3]; + + for (i=0; i<3; i++) + { + if ( arrays[i] == NULL ) + { + return; + } + } + + for ( i=0; i < 3; i++ ) + { + fieldArray[i] = this->GetFieldArray(fd, arrays[i], arrayComp[i]); + + if ( fieldArray[i] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested"); + return; + } + } + + updated = this->UpdateComponentRange(fieldArray[0], componentRange[0]); + updated |= this->UpdateComponentRange(fieldArray[1], componentRange[1]); + updated |= this->UpdateComponentRange(fieldArray[2], componentRange[2]); + + if ( num != (componentRange[0][1] - componentRange[0][0] + 1) || + num != (componentRange[1][1] - componentRange[1][0] + 1) || + num != (componentRange[2][1] - componentRange[2][0] + 1) ) + { + vtkErrorMacro(<<"Number of normals not consistent"); + return; + } + + vtkDataArray *newNormals; + if ( fieldArray[0]->GetNumberOfComponents() == 3 && + fieldArray[0] == fieldArray[1] && fieldArray[1] == fieldArray[2] && + fieldArray[0]->GetNumberOfTuples() == num && + !normalize[0] && !normalize[1] && !normalize[2] ) + { + newNormals = fieldArray[0]; + newNormals->Register(0); + } + else //have to copy data into created array + { + newNormals = vtkDataArray::CreateDataArray(this->GetComponentsType(3, fieldArray)); + newNormals->SetNumberOfComponents(3); + newNormals->SetNumberOfTuples(num); + + for ( i=0; i < 3; i++ ) + { + if ( this->ConstructArray(newNormals, i, fieldArray[i], arrayComp[i], + componentRange[i][0], componentRange[i][1], + normalize[i]) == 0 ) + { + newNormals->Delete(); + return; + } + } + } + + attr->SetNormals(newNormals); + newNormals->Delete(); + if ( updated ) //reset for next execution pass + { + for (i=0; i < 3; i++) + { + componentRange[i][0] = componentRange[i][1] = -1; + } + } +} + +// Stuff related to texture coords -------------------------------------------- +// +void vtkFieldDataToAttributeDataFilter::SetTCoordComponent(int comp, const char *arrayName, + int arrayComp, int min, int max, int normalize) +{ + if ( comp < 0 || comp > 2 ) + { + vtkErrorMacro(<<"TCoord component must be between (0,2)"); + return; + } + + if ( comp >= this->NumberOfTCoordComponents ) + { + this->NumberOfTCoordComponents = comp + 1; + } + this->SetArrayName(this, this->TCoordArrays[comp], arrayName); + if ( this->TCoordArrayComponents[comp] != arrayComp ) + { + this->TCoordArrayComponents[comp] = arrayComp; + this->Modified(); + } + if ( this->TCoordComponentRange[comp][0] != min ) + { + this->TCoordComponentRange[comp][0] = min; + this->Modified(); + } + if ( this->TCoordComponentRange[comp][1] != max ) + { + this->TCoordComponentRange[comp][1] = max; + this->Modified(); + } + if ( this->TCoordNormalize[comp] != normalize ) + { + this->TCoordNormalize[comp] = normalize; + this->Modified(); + } +} + +const char *vtkFieldDataToAttributeDataFilter::GetTCoordComponentArrayName(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->TCoordArrays[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetTCoordComponentArrayComponent(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->TCoordArrayComponents[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetTCoordComponentMinRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->TCoordComponentRange[comp][0]; +} + +int vtkFieldDataToAttributeDataFilter::GetTCoordComponentMaxRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->TCoordComponentRange[comp][1]; +} + +int vtkFieldDataToAttributeDataFilter::GetTCoordComponentNormalizeFlag(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 2 ? 2 : comp)); + return this->TCoordNormalize[comp]; +} + +void vtkFieldDataToAttributeDataFilter::ConstructTCoords(int num, vtkFieldData *fd, + vtkDataSetAttributes *attr, + vtkIdType componentRange[3][2], + char *arrays[3], int arrayComp[3], + int normalize[3], int numComp) +{ + int i, normalizeAny, updated=0; + vtkDataArray *fieldArray[3]; + + if ( numComp < 1 ) + { + return; + } + for (i=0; iGetFieldArray(fd, arrays[i], arrayComp[i]); + + if ( fieldArray[i] == NULL ) + { + vtkErrorMacro(<<"Can't find array/component requested"); + return; + } + normalizeAny |= normalize[i]; + } + + for (i=0; i < numComp; i++) + { + updated |= this->UpdateComponentRange(fieldArray[i], componentRange[i]); + if ( num != (componentRange[i][1] - componentRange[i][0] + 1) ) + { + vtkErrorMacro(<<"Number of texture coords not consistent"); + return; + } + } + + vtkDataArray *newTCoords; + for (i=1; i < numComp; i++) //see whether all the data is from the same array + { + if ( fieldArray[i] != fieldArray[i-1] ) + { + break; + } + } + + // see whether we can reuse the data array from the field + if ( i >= numComp && fieldArray[0]->GetNumberOfComponents() == numComp && + fieldArray[0]->GetNumberOfTuples() == num && !normalizeAny ) + { + newTCoords = fieldArray[0]; + newTCoords->Register(0); + } + else //have to copy data into created array + { + newTCoords = vtkDataArray::CreateDataArray(this->GetComponentsType(numComp, fieldArray)); + newTCoords->SetNumberOfComponents(numComp); + newTCoords->SetNumberOfTuples(num); + + for ( i=0; i < numComp; i++ ) + { + if ( this->ConstructArray(newTCoords, i, fieldArray[i], arrayComp[i], + componentRange[i][0], componentRange[i][1], + normalize[i]) == 0 ) + { + newTCoords->Delete(); + return; + } + } + } + + attr->SetTCoords(newTCoords); + newTCoords->Delete(); + if ( updated ) //reset for next execution pass + { + for (i=0; i < numComp; i++) + { + componentRange[i][0] = componentRange[i][1] = -1; + } + } +} + +// Stuff related to tensors -------------------------------------------- +// +void vtkFieldDataToAttributeDataFilter::SetTensorComponent(int comp, const char *arrayName, + int arrayComp, int min, int max, int normalize) +{ + if ( comp < 0 || comp > 8 ) + { + vtkErrorMacro(<<"Tensor component must be between (0,8)"); + return; + } + + this->SetArrayName(this, this->TensorArrays[comp], arrayName); + if ( this->TensorArrayComponents[comp] != arrayComp ) + { + this->TensorArrayComponents[comp] = arrayComp; + this->Modified(); + } + if ( this->TensorComponentRange[comp][0] != min ) + { + this->TensorComponentRange[comp][0] = min; + this->Modified(); + } + if ( this->TensorComponentRange[comp][1] != max ) + { + this->TensorComponentRange[comp][1] = max; + this->Modified(); + } + if ( this->TensorNormalize[comp] != normalize ) + { + this->TensorNormalize[comp] = normalize; + this->Modified(); + } +} + +const char *vtkFieldDataToAttributeDataFilter::GetTensorComponentArrayName(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 8 ? 8 : comp)); + return this->TensorArrays[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetTensorComponentArrayComponent(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 8 ? 8 : comp)); + return this->TensorArrayComponents[comp]; +} + +int vtkFieldDataToAttributeDataFilter::GetTensorComponentMinRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 8 ? 8 : comp)); + return this->TensorComponentRange[comp][0]; +} + +int vtkFieldDataToAttributeDataFilter::GetTensorComponentMaxRange(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 8 ? 8 : comp)); + return this->TensorComponentRange[comp][1]; +} + +int vtkFieldDataToAttributeDataFilter::GetTensorComponentNormalizeFlag(int comp) +{ + comp = (comp < 0 ? 0 : (comp > 8 ? 8 : comp)); + return this->TensorNormalize[comp]; +} + +void vtkFieldDataToAttributeDataFilter::ConstructTensors(int num, vtkFieldData *fd, + vtkDataSetAttributes *attr, + vtkIdType componentRange[9][2], + char *arrays[9], int arrayComp[9], + int normalize[9]) +{ + int i, normalizeAny, updated=0; + vtkDataArray *fieldArray[9]; + + for (i=0; i<9; i++) + { + if ( arrays[i] == NULL ) + { + return; + } + } + + for ( i=0; i < 9; i++ ) + { + fieldArray[i] = this->GetFieldArray(fd, arrays[i], arrayComp[i]); + + if ( fieldArray[i] == NULL ) + { + vtkErrorMacro(<<"Can't find array requested"); + return; + } + } + + for (normalizeAny=i=0; i < 9; i++) + { + updated |= this->UpdateComponentRange(fieldArray[i], componentRange[i]); + if ( num != (componentRange[i][1] - componentRange[i][0] + 1) ) + { + vtkErrorMacro(<<"Number of tensors not consistent"); + return; + } + normalizeAny |= normalize[i]; + } + + vtkDataArray *newTensors; + for (i=1; i < 9; i++) //see whether all the data is from the same array + { + if ( fieldArray[i] != fieldArray[i-1] ) + { + break; + } + } + + // see whether we can reuse the data array from the field + if ( i >= 9 && fieldArray[0]->GetNumberOfComponents() == 9 && + fieldArray[0]->GetNumberOfTuples() == num && !normalizeAny ) + { + newTensors = fieldArray[0]; + newTensors->Register(0); + } + else //have to copy data into created array + { + newTensors = vtkDataArray::CreateDataArray(this->GetComponentsType(9, fieldArray)); + newTensors->SetNumberOfComponents(9); + newTensors->SetNumberOfTuples(num); + + for ( i=0; i < 9; i++ ) + { + if ( this->ConstructArray(newTensors, i, fieldArray[i], arrayComp[i], + componentRange[i][0], componentRange[i][1], + normalize[i]) == 0 ) + { + newTensors->Delete(); + return; + } + } + } + + attr->SetTensors(newTensors); + newTensors->Delete(); + if ( updated ) //reset for next execution pass + { + for (i=0; i < 9; i++) + { + componentRange[i][0] = componentRange[i][1] = -1; + } + } +} + +// Stuff related to fields -------------------------------------------- +// +void +vtkFieldDataToAttributeDataFilter::ConstructFieldData(int vtkNotUsed(num), + vtkDataSetAttributes *vtkNotUsed(attr)) +{ +} + +// Stuff related to helper methods --------------------------------------- +// +int vtkFieldDataToAttributeDataFilter::ConstructArray(vtkDataArray *da, + int comp, + vtkDataArray *fieldArray, + int fieldComp, + vtkIdType min, + vtkIdType max, + int normalize) +{ + vtkIdType i, n=max-min+1; + float minValue=VTK_LARGE_FLOAT; + float maxValue= -VTK_LARGE_FLOAT; + float compRange, compValue; + + if ( fieldComp >= fieldArray->GetNumberOfComponents() ) + { + vtkGenericWarningMacro(<<"Trying to access component out of range"); + return 0; + } + + for (i=0; i < n; i++) + { + compValue = fieldArray->GetComponent(min+i, fieldComp); + if ( compValue < minValue ) + { + minValue = compValue; + } + if ( compValue > maxValue ) + { + maxValue = compValue; + } + da->SetComponent(i, comp, compValue); + } + + if ( normalize ) + { + compRange = maxValue - minValue; + if ( compRange != 0.0 ) + { + for (i=0; i < n; i++) + { + compValue = da->GetComponent(i, comp); + compValue = (compValue - minValue) / compRange; + da->SetComponent(i, comp, compValue); + } + } + } + + return 1; +} + +int vtkFieldDataToAttributeDataFilter::GetComponentsType(int numComp, vtkDataArray **arrays) +{ + int type, mostComplexType=VTK_VOID; + + for (int i=0; i < numComp; i++) + { + type = arrays[i]->GetDataType(); + if ( type > mostComplexType ) + { + mostComplexType = type; + } + } + + return mostComplexType; +} + +vtkDataArray *vtkFieldDataToAttributeDataFilter::GetFieldArray(vtkFieldData *fd, + char *name, int comp) +{ + vtkDataArray *da = NULL; + int numComp; + int found=0; + + if ( name != NULL ) + { + vtkDataSetAttributes* dsa; + if ((dsa=vtkDataSetAttributes::SafeDownCast(fd))) + { + found=1; + if(!strcmp("PointScalars", name) || !strcmp("CellScalars", name)) + { + da = dsa->GetScalars(); + } + else if(!strcmp("PointVectors", name) || !strcmp("CellVectors", name)) + { + da = dsa->GetVectors(); + } + else if(!strcmp("PointTensors", name) || !strcmp("CellTensors", name)) + { + da = dsa->GetTensors(); + } + else if(!strcmp("PointNormals", name) || !strcmp("CellNormals", name)) + { + da = dsa->GetNormals(); + } + else if(!strcmp("PointTCoords", name) || !strcmp("CellTCoords", name)) + { + da = dsa->GetTCoords(); + } + else + { + found=0; + } + } + if (!found || !da) + { + da = fd->GetArray(name); + } + + if ( da == NULL ) + { + return NULL; + } + numComp = da->GetNumberOfComponents(); + if ( comp < 0 || comp >= numComp ) + { + return NULL; + } + else + { + return da; + } + } + + return NULL; +} + +void vtkFieldDataToAttributeDataFilter::SetArrayName(vtkObject *self, char* &name, const char *newName) +{ + if ( name && newName && (!strcmp(name,newName))) + { + return; + } + if (name) + { + delete [] name; + } + if (newName) + { + name = new char[strlen(newName)+1]; + strcpy(name,newName); + } + else + { + name = NULL; + } + self->Modified(); +} + +int vtkFieldDataToAttributeDataFilter::UpdateComponentRange(vtkDataArray *da, + vtkIdType compRange[2]) +{ + if ( compRange[0] == -1 ) + { + compRange[0] = 0; + compRange[1] = da->GetNumberOfTuples() - 1; + return 1; + } + else + { + return 0; + } +} + + +//---------------------------------------------------------------------------- +int vtkFieldDataToAttributeDataFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()), + 6); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT())); + return 1; +} diff --git a/Graphics/vtkFieldDataToAttributeDataFilter.h b/Graphics/vtkFieldDataToAttributeDataFilter.h new file mode 100644 index 0000000..42c2914 --- /dev/null +++ b/Graphics/vtkFieldDataToAttributeDataFilter.h @@ -0,0 +1,296 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFieldDataToAttributeDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFieldDataToAttributeDataFilter - map field data to dataset attribute data +// .SECTION Description +// vtkFieldDataToAttributeDataFilter is a class that maps field data into +// dataset attributes. The input to this filter is any type of dataset and +// the output is the same dataset (geometry/topology) with new attribute data +// (attribute data is passed through if not replaced during filter +// execution). +// +// To use this filter you must specify which field data from the input +// dataset to use. There are three possibilities: the cell field data, the +// point field data, or the field data associated with the data object +// superclass. Then you specify which attribute data to create: either cell +// attribute data or point attribute data. Finally, you must define how to +// construct the various attribute data types (e.g., scalars, vectors, +// normals, etc.) from the arrays and the components of the arrays from the +// field data. This is done by associating components in the input field with +// components making up the attribute data. For example, you would specify a +// scalar with three components (RGB) by assigning components from the field +// for the R, then G, then B values of the scalars. You may also have to +// specify component ranges (for each R-G-B) to make sure that the number of +// R, G, and B values is the same. Also, you may want to normalize the +// components which helps distribute the data uniformly. +// +// This filter is often used in conjunction with +// vtkDataObjectToDataSetFilter. vtkDataObjectToDataSetFilter filter +// generates dataset topology and geometry and passes its input field data +// along to its output. Then this filter is used to generate the attribute +// data to go along with the dataset. + +// .SECTION Caveats +// Make sure that the data you extract is consistent. That is, if you have N +// points, extract N point attributes (scalars, vectors, etc.). + +// .SECTION See Also +// vtkFieldData vtkDataSet vtkDataObjectToDataSetFilter +// vtkDataSetAttributes vtkDataArray + +#ifndef __vtkFieldDataToAttributeDataFilter_h +#define __vtkFieldDataToAttributeDataFilter_h + +#include "vtkDataSetAlgorithm.h" + +#define VTK_DATA_OBJECT_FIELD 0 +#define VTK_POINT_DATA_FIELD 1 +#define VTK_CELL_DATA_FIELD 2 + +#define VTK_CELL_DATA 0 +#define VTK_POINT_DATA 1 + +class vtkDataArray; +class vtkDataSetAttributes; +class vtkFieldData; + +class VTK_GRAPHICS_EXPORT vtkFieldDataToAttributeDataFilter : public vtkDataSetAlgorithm +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkFieldDataToAttributeDataFilter,vtkDataSetAlgorithm); + + // Description: + // Construct object with input field set to the data object field, and the + // output attribute data set to generate point data. + static vtkFieldDataToAttributeDataFilter *New(); + + // Description: + // Specify which field data to use to generate the output attribute + // data. There are three choices: the field data associated with the + // vtkDataObject superclass; the point field attribute data; and the cell + // field attribute data. + vtkSetMacro(InputField,int); + vtkGetMacro(InputField,int); + void SetInputFieldToDataObjectField() + {this->SetInputField(VTK_DATA_OBJECT_FIELD);}; + void SetInputFieldToPointDataField() + {this->SetInputField(VTK_POINT_DATA_FIELD);}; + void SetInputFieldToCellDataField() + {this->SetInputField(VTK_CELL_DATA_FIELD);}; + + // Description: + // Specify which attribute data to output: point or cell data attributes. + vtkSetMacro(OutputAttributeData,int); + vtkGetMacro(OutputAttributeData,int); + void SetOutputAttributeDataToCellData() + {this->SetOutputAttributeData(VTK_CELL_DATA);}; + void SetOutputAttributeDataToPointData() + {this->SetOutputAttributeData(VTK_POINT_DATA);}; + + // Description: + // Define the component(s) of the field to be used for the scalar + // components. Note that the parameter comp must lie between (0,4). To + // define the field component to use you specify an array name and the + // component in that array. The (min,max) values are the range of data in + // the component you wish to extract. + void SetScalarComponent(int comp, const char *arrayName, int arrayComp, + int min, int max, int normalize); + void SetScalarComponent(int comp, const char *arrayName, int arrayComp) + {this->SetScalarComponent(comp, arrayName, arrayComp, -1, -1, this->DefaultNormalize);}; + const char *GetScalarComponentArrayName(int comp); + int GetScalarComponentArrayComponent(int comp); + int GetScalarComponentMinRange(int comp); + int GetScalarComponentMaxRange(int comp); + int GetScalarComponentNormalizeFlag(int comp); + + // Description: + // Define the component(s) of the field to be used for the vector + // components. Note that the parameter comp must lie between (0,3). To + // define the field component to use you specify an array name and the + // component in that array. The (min,max) values are the range of data in + // the component you wish to extract. + void SetVectorComponent(int comp, const char *arrayName, int arrayComp, + int min, int max, int normalize); + void SetVectorComponent(int comp, const char *arrayName, int arrayComp) + {this->SetVectorComponent(comp, arrayName, arrayComp, -1, -1, this->DefaultNormalize);}; + const char *GetVectorComponentArrayName(int comp); + int GetVectorComponentArrayComponent(int comp); + int GetVectorComponentMinRange(int comp); + int GetVectorComponentMaxRange(int comp); + int GetVectorComponentNormalizeFlag(int comp); + + // Description: + // Define the component(s) of the field to be used for the normal + // components. Note that the parameter comp must lie between (0,3). To + // define the field component to use you specify an array name and the + // component in that array. The (min,max) values are the range of data in + // the component you wish to extract. + void SetNormalComponent(int comp, const char *arrayName, int arrayComp, + int min, int max, int normalize); + void SetNormalComponent(int comp, const char *arrayName, int arrayComp) + {this->SetNormalComponent(comp, arrayName, arrayComp, -1, -1, this->DefaultNormalize);}; + const char *GetNormalComponentArrayName(int comp); + int GetNormalComponentArrayComponent(int comp); + int GetNormalComponentMinRange(int comp); + int GetNormalComponentMaxRange(int comp); + int GetNormalComponentNormalizeFlag(int comp); + + // Description: + // Define the components of the field to be used for the tensor + // components. Note that the parameter comp must lie between (0,9). To + // define the field component to use you specify an array name and the + // component in that array. The (min,max) values are the range of data in + // the component you wish to extract. + void SetTensorComponent(int comp, const char *arrayName, int arrayComp, + int min, int max, int normalize); + void SetTensorComponent(int comp, const char *arrayName, int arrayComp) + {this->SetTensorComponent(comp, arrayName, arrayComp, -1, -1, this->DefaultNormalize);}; + const char *GetTensorComponentArrayName(int comp); + int GetTensorComponentArrayComponent(int comp); + int GetTensorComponentMinRange(int comp); + int GetTensorComponentMaxRange(int comp); + int GetTensorComponentNormalizeFlag(int comp); + + // Description: + // Define the components of the field to be used for the cell texture coord + // components. Note that the parameter comp must lie between (0,9). To + // define the field component to use you specify an array name and the + // component in that array. The (min,max) values are the range of data in + // the component you wish to extract. + void SetTCoordComponent(int comp, const char *arrayName, int arrayComp, + int min, int max, int normalize); + void SetTCoordComponent(int comp, const char *arrayName, int arrayComp) + {this->SetTCoordComponent(comp, arrayName, arrayComp, -1, -1, this->DefaultNormalize);}; + const char *GetTCoordComponentArrayName(int comp); + int GetTCoordComponentArrayComponent(int comp); + int GetTCoordComponentMinRange(int comp); + int GetTCoordComponentMaxRange(int comp); + int GetTCoordComponentNormalizeFlag(int comp); + + // Description: + // Set the default Normalize() flag for those methods setting a default + // Normalize value (e.g., SetScalarComponents). + vtkSetMacro(DefaultNormalize,int); + vtkGetMacro(DefaultNormalize,int); + vtkBooleanMacro(DefaultNormalize,int); + + // Helper functions, made public to support other classes + + // Description: + // Given an array of names of arrays in field data, return the common type + // for these arrays. For example, if a vector is constructed of the three + // type (char,int,float), the return type is float. + static int GetComponentsType(int numComp, vtkDataArray **arrays); + + // Description: + // Construct a portion of a data array (the comp portion) from another data + // array and its component. The variables min and max control the range of + // the data to use from the other data array; normalize is a flag that when + // set will normalize the data between (0,1). + static int ConstructArray(vtkDataArray *da, int comp, vtkDataArray *frray, + int fieldComp, vtkIdType min, vtkIdType max, + int normalize); + + // Description: + // Return an array of a particular name from field data and do error checking. + static vtkDataArray *GetFieldArray(vtkFieldData *fd, char *name, int comp); + + // Description: + // Specify an array name for one of the components. + static void SetArrayName(vtkObject *self, char* &name, const char *newName); + +//BTX + // Description: + // Update the maximum and minimum component range values. Returns a flag + // indicating whether the range was updated. + static int UpdateComponentRange(vtkDataArray *da, vtkIdType compRange[2]); +//ETX + + // Description: + // If output does not need exact extent, the I do not either. + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +protected: + vtkFieldDataToAttributeDataFilter(); + ~vtkFieldDataToAttributeDataFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); //generate output data + + int InputField; + int OutputAttributeData; + + int NumberOfScalarComponents; //the number of components to fill-in + char *ScalarArrays[4]; //the name of the arrays used to construct the scalar + int ScalarArrayComponents[4]; //the components of the arrays used to construct + vtkIdType ScalarComponentRange[4][2]; //the range of the components to use + int ScalarNormalize[4]; //flags control normalization + + char *VectorArrays[3]; //the name of the arrays used to construct the vectors + int VectorArrayComponents[3]; //the components of the arrays used to construct + vtkIdType VectorComponentRange[3][2]; //the range of the components to use + int VectorNormalize[3]; //flags control normalization + + char *GhostLevelArray; //the name of the array used to construct the ghost levels + int GhostLevelArrayComponent; //the component of the array used to construct + vtkIdType GhostLevelComponentRange[2]; //the range of the components to use + int GhostLevelNormalize; //flags control normalization + + char *NormalArrays[3]; //the name of the arrays used to construct the normals + int NormalArrayComponents[3]; //the components of the arrays used to construct + vtkIdType NormalComponentRange[3][2]; //the range of the components to use + int NormalNormalize[3]; //flags control normalization + + char *TensorArrays[9]; //the name of the arrays used to construct the tensors + int TensorArrayComponents[9]; //the components of the arrays used to construct + vtkIdType TensorComponentRange[9][2]; //the range of the components to use + int TensorNormalize[9]; //flags control normalization + + int NumberOfTCoordComponents; //the number of components to fill-in + char *TCoordArrays[3]; //the name of the arrays used to construct the tcoords + int TCoordArrayComponents[3]; //the components of the arrays used to construct + vtkIdType TCoordComponentRange[3][2]; //the range of the components to use + int TCoordNormalize[3]; //flags control normalization + + int DefaultNormalize; + + void ConstructScalars(int num, vtkFieldData *fd, vtkDataSetAttributes *attr, + vtkIdType componentRange[4][2], char *arrays[4], + int arrayComponents[4], int normalize[4], int numComp); + void ConstructVectors(int num, vtkFieldData *fd, vtkDataSetAttributes *attr, + vtkIdType componentRange[3][2], char *arrays[3], + int arrayComponents[3], int normalize[3]); + void ConstructGhostLevels(int num, vtkFieldData *fd, + vtkDataSetAttributes *attr, + vtkIdType componentRange[2], + char *array, int arrayComponent, int normalize); + void ConstructNormals(int num, vtkFieldData *fd, vtkDataSetAttributes *attr, + vtkIdType componentRange[3][2], char *arrays[3], + int arrayComponents[3], int normalize[3]); + void ConstructTCoords(int num, vtkFieldData *fd, vtkDataSetAttributes *attr, + vtkIdType componentRange[3][2], char *arrays[3], + int arrayComponents[3], int normalize[3], int numComp); + void ConstructTensors(int num, vtkFieldData *fd, vtkDataSetAttributes *attr, + vtkIdType componentRange[9][2], char *arrays[9], + int arrayComponents[9], int normalize[9]); + void ConstructFieldData(int num, vtkDataSetAttributes *attr); + +private: + vtkFieldDataToAttributeDataFilter(const vtkFieldDataToAttributeDataFilter&); // Not implemented. + void operator=(const vtkFieldDataToAttributeDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkGeometryFilter.cxx b/Graphics/vtkGeometryFilter.cxx new file mode 100644 index 0000000..c11e7f9 --- /dev/null +++ b/Graphics/vtkGeometryFilter.cxx @@ -0,0 +1,1278 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGeometryFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkHexagonalPrism.h" +#include "vtkHexahedron.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPyramid.h" +#include "vtkPentagonalPrism.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkTetra.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkVoxel.h" +#include "vtkWedge.h" + +vtkCxxRevisionMacro(vtkGeometryFilter, "$Revision: 1.101 $"); +vtkStandardNewMacro(vtkGeometryFilter); + +// Construct with all types of clipping turned off. +vtkGeometryFilter::vtkGeometryFilter() +{ + this->PointMinimum = 0; + this->PointMaximum = VTK_LARGE_ID; + + this->CellMinimum = 0; + this->CellMaximum = VTK_LARGE_ID; + + this->Extent[0] = -VTK_DOUBLE_MAX; + this->Extent[1] = VTK_DOUBLE_MAX; + this->Extent[2] = -VTK_DOUBLE_MAX; + this->Extent[3] = VTK_DOUBLE_MAX; + this->Extent[4] = -VTK_DOUBLE_MAX; + this->Extent[5] = VTK_DOUBLE_MAX; + + this->PointClipping = 0; + this->CellClipping = 0; + this->ExtentClipping = 0; + + this->Merging = 1; + this->Locator = NULL; +} + +vtkGeometryFilter::~vtkGeometryFilter() +{ + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +// Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. +void vtkGeometryFilter::SetExtent(double xMin, double xMax, double yMin, + double yMax, double zMin, double zMax) +{ + double extent[6]; + + extent[0] = xMin; + extent[1] = xMax; + extent[2] = yMin; + extent[3] = yMax; + extent[4] = zMin; + extent[5] = zMax; + + this->SetExtent(extent); +} + +// Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. +void vtkGeometryFilter::SetExtent(double extent[6]) +{ + int i; + + if ( extent[0] != this->Extent[0] || extent[1] != this->Extent[1] || + extent[2] != this->Extent[2] || extent[3] != this->Extent[3] || + extent[4] != this->Extent[4] || extent[5] != this->Extent[5] ) + { + this->Modified(); + for (i=0; i<3; i++) + { + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + this->Extent[2*i] = extent[2*i]; + this->Extent[2*i+1] = extent[2*i+1]; + } + } +} + +int vtkGeometryFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, newCellId; + int i, j; + vtkIdType numPts=input->GetNumberOfPoints(); + vtkIdType numCells=input->GetNumberOfCells(); + char *cellVis; + vtkGenericCell *cell; + vtkCell *face; + double x[3]; + vtkIdList *ptIds; + vtkIdList *cellIds; + vtkIdList *pts; + vtkPoints *newPts; + vtkIdType ptId; + int npts; + vtkIdType pt=0; + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + int allVisible; + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + // ghost cell stuff + unsigned char updateLevel = (unsigned char)(output->GetUpdateGhostLevel()); + unsigned char *cellGhostLevels = NULL; + + if (numCells == 0) + { + return 1; + } + + switch (input->GetDataObjectType()) + { + case VTK_POLY_DATA: + this->PolyDataExecute(input, output, outInfo); + return 1; + case VTK_UNSTRUCTURED_GRID: + this->UnstructuredGridExecute(input, output, outInfo); + return 1; + case VTK_STRUCTURED_GRID: + this->StructuredGridExecute(input, output, outInfo); + return 1; + } + + vtkDataArray* temp = 0; + if (cd) + { + temp = cd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + cellGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + cellIds = vtkIdList::New(); + pts = vtkIdList::New(); + + vtkDebugMacro(<<"Executing geometry filter"); + + cell = vtkGenericCell::New(); + + if ( (!this->CellClipping) && (!this->PointClipping) && + (!this->ExtentClipping) ) + { + allVisible = 1; + cellVis = NULL; + } + else + { + allVisible = 0; + cellVis = new char[numCells]; + } + + // Mark cells as being visible or not + // + if ( ! allVisible ) + { + for(cellId=0; cellId < numCells; cellId++) + { + if ( this->CellClipping && cellId < this->CellMinimum || + cellId > this->CellMaximum ) + { + cellVis[cellId] = 0; + } + else + { + input->GetCell(cellId,cell); + ptIds = cell->GetPointIds(); + for (i=0; i < ptIds->GetNumberOfIds(); i++) + { + ptId = ptIds->GetId(i); + input->GetPoint(ptId, x); + + if ( (this->PointClipping && (ptId < this->PointMinimum || + ptId > this->PointMaximum) ) || + (this->ExtentClipping && + (x[0] < this->Extent[0] || x[0] > this->Extent[1] || + x[1] < this->Extent[2] || x[1] > this->Extent[3] || + x[2] < this->Extent[4] || x[2] > this->Extent[5] )) ) + { + cellVis[cellId] = 0; + break; + } + } + if ( i >= ptIds->GetNumberOfIds() ) + { + cellVis[cellId] = 1; + } + } + } + } + + // Allocate + // + newPts = vtkPoints::New(); + newPts->Allocate(numPts,numPts/2); + output->Allocate(4*numCells,numCells/2); + outputPD->CopyAllocate(pd,numPts,numPts/2); + outputCD->CopyAllocate(cd,numCells,numCells/2); + + if ( this->Merging ) + { + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + } + + // Traverse cells to extract geometry + // + int abort=0; + vtkIdType progressInterval = numCells/20 + 1; + for(cellId=0; cellId < numCells && !abort; cellId++) + { + //Progress and abort method support + if ( !(cellId % progressInterval) ) + { + vtkDebugMacro(<<"Process cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + abort = this->GetAbortExecute(); + } + + // Handle ghost cells here. Another option was used cellVis array. + if (cellGhostLevels && cellGhostLevels[cellId] > updateLevel) + { // Do not create surfaces in outer ghost cells. + continue; + } + + if ( allVisible || cellVis[cellId] ) + { + input->GetCell(cellId,cell); + if (cell->GetCellType() != VTK_EMPTY_CELL) + { + switch (cell->GetCellDimension()) + { + // create new points and then cell + case 0: case 1: case 2: + + npts = cell->GetNumberOfPoints(); + pts->Reset(); + for ( i=0; i < npts; i++) + { + ptId = cell->GetPointId(i); + input->GetPoint(ptId, x); + + if ( this->Merging && this->Locator->InsertUniquePoint(x, pt) ) + { + outputPD->CopyData(pd,ptId,pt); + } + else if (!this->Merging) + { + pt = newPts->InsertNextPoint(x); + outputPD->CopyData(pd,ptId,pt); + } + pts->InsertId(i,pt); + } + newCellId = output->InsertNextCell(cell->GetCellType(), pts); + outputCD->CopyData(cd,cellId,newCellId); + break; + + case 3: + int numFaces = cell->GetNumberOfFaces(); + for (j=0; j < numFaces; j++) + { + face = cell->GetFace(j); + input->GetCellNeighbors(cellId, face->PointIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + npts = face->GetNumberOfPoints(); + pts->Reset(); + for ( i=0; i < npts; i++) + { + ptId = face->GetPointId(i); + input->GetPoint(ptId, x); + if (this->Merging && this->Locator->InsertUniquePoint(x, pt) ) + { + outputPD->CopyData(pd,ptId,pt); + } + else if (!this->Merging) + { + pt = newPts->InsertNextPoint(x); + outputPD->CopyData(pd,ptId,pt); + } + pts->InsertId(i,pt); + } + newCellId = output->InsertNextCell(face->GetCellType(), pts); + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + } //switch + } + } //if visible + } //for all cells + + vtkDebugMacro(<<"Extracted " << newPts->GetNumberOfPoints() << " points," + << output->GetNumberOfCells() << " cells."); + + // Update ourselves and release memory + // + cell->Delete(); + output->SetPoints(newPts); + newPts->Delete(); + + //free storage + if (!this->Merging && this->Locator) + { + this->Locator->Initialize(); + } + output->Squeeze(); + + cellIds->Delete(); + pts->Delete(); + if ( cellVis ) + { + delete [] cellVis; + } + + return 1; +} + +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkGeometryFilter::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkGeometryFilter::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +int vtkGeometryFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkGeometryFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Point Minimum : " << this->PointMinimum << "\n"; + os << indent << "Point Maximum : " << this->PointMaximum << "\n"; + + os << indent << "Cell Minimum : " << this->CellMinimum << "\n"; + os << indent << "Cell Maximum : " << this->CellMaximum << "\n"; + + os << indent << "Extent: \n"; + os << indent << " Xmin,Xmax: (" << this->Extent[0] << ", " << this->Extent[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->Extent[2] << ", " << this->Extent[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->Extent[4] << ", " << this->Extent[5] << ")\n"; + + os << indent << "PointClipping: " << (this->PointClipping ? "On\n" : "Off\n"); + os << indent << "CellClipping: " << (this->CellClipping ? "On\n" : "Off\n"); + os << indent << "ExtentClipping: " << (this->ExtentClipping ? "On\n" : "Off\n"); + + os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n"); + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +unsigned long int vtkGeometryFilter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} + +void vtkGeometryFilter::PolyDataExecute(vtkDataSet *dataSetInput, + vtkPolyData *output, + vtkInformation *outInfo) +{ + vtkPolyData *input= (vtkPolyData *)dataSetInput; + vtkIdType cellId; + int i; + int allVisible; + vtkIdType npts; + vtkIdType *pts; + vtkPoints *p = input->GetPoints(); + vtkIdType numCells=input->GetNumberOfCells(); + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkIdType newCellId, ptId; + int visible, type; + double x[3]; + // ghost cell stuff + unsigned char updateLevel = (unsigned char) + (outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + unsigned char *cellGhostLevels = 0; + + vtkDebugMacro(<<"Executing geometry filter for poly data input"); + + vtkDataArray* temp = 0; + if (cd) + { + temp = cd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + cellGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + if ( (!this->CellClipping) && (!this->PointClipping) && + (!this->ExtentClipping) ) + { + allVisible = 1; + } + else + { + allVisible = 0; + } + + if ( allVisible ) //just pass input to output + { + output->CopyStructure(input); + outputPD->PassData(pd); + outputCD->PassData(cd); + return; + } + + // Always pass point data + output->SetPoints(p); + outputPD->PassData(pd); + + // Allocate + // + output->Allocate(numCells); + outputCD->CopyAllocate(cd,numCells,numCells/2); + input->BuildCells(); //needed for GetCellPoints() + + vtkIdType progressInterval = numCells/20 + 1; + for(cellId=0; cellId < numCells; cellId++) + { + //Progress and abort method support + if ( !(cellId % progressInterval) ) + { + vtkDebugMacro(<<"Process cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + } + + // Handle ghost cells here. Another option was used cellVis array. + if (cellGhostLevels && cellGhostLevels[cellId] > updateLevel) + { // Do not create surfaces in outer ghost cells. + continue; + } + + input->GetCellPoints(cellId,npts,pts); + visible = 1; + if ( !allVisible ) + { + if ( this->CellClipping && cellId < this->CellMinimum || + cellId > this->CellMaximum ) + { + visible = 0; + } + else + { + for (i=0; i < npts; i++) + { + ptId = pts[i]; + input->GetPoint(ptId, x); + + if ( (this->PointClipping && (ptId < this->PointMinimum || + ptId > this->PointMaximum) ) || + (this->ExtentClipping && + (x[0] < this->Extent[0] || x[0] > this->Extent[1] || + x[1] < this->Extent[2] || x[1] > this->Extent[3] || + x[2] < this->Extent[4] || x[2] > this->Extent[5] )) ) + { + visible = 0; + break; + } + } + } + } + + // now if visible extract geometry + if (allVisible || visible) + { + type = input->GetCellType(cellId); + newCellId = output->InsertNextCell(type,npts,pts); + outputCD->CopyData(cd,cellId,newCellId); + } //if visible + } //for all cells + + // Update ourselves and release memory + // + output->Squeeze(); + + vtkDebugMacro(<<"Extracted " << output->GetNumberOfPoints() << " points," + << output->GetNumberOfCells() << " cells."); +} + +void vtkGeometryFilter::UnstructuredGridExecute(vtkDataSet *dataSetInput, + vtkPolyData *output, + vtkInformation *outInfo) +{ + vtkUnstructuredGrid *input= (vtkUnstructuredGrid *)dataSetInput; + vtkCellArray *Connectivity = input->GetCells(); + if (Connectivity == NULL) + { + return; + } + vtkIdType cellId; + int i; + int allVisible; + vtkIdType npts = 0; + vtkIdType *pts = 0; + vtkPoints *p = input->GetPoints(); + vtkIdType numCells=input->GetNumberOfCells(); + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkCellArray *Verts, *Lines, *Polys, *Strips; + vtkIdList *cellIds, *faceIds; + char *cellVis; + vtkIdType newCellId; + int faceId, *faceVerts, numFacePts; + double x[3]; + int PixelConvert[4]; + // ghost cell stuff + unsigned char updateLevel = (unsigned char) + (outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + unsigned char *cellGhostLevels = 0; + + PixelConvert[0] = 0; + PixelConvert[1] = 1; + PixelConvert[2] = 3; + PixelConvert[3] = 2; + + vtkDebugMacro(<<"Executing geometry filter for unstructured grid input"); + + vtkDataArray* temp = 0; + if (cd) + { + temp = cd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + cellGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + // Check input + if ( Connectivity == NULL ) + { + vtkDebugMacro(<<"Nothing to extract"); + return; + } + + // Determine nature of what we have to do + cellIds = vtkIdList::New(); + faceIds = vtkIdList::New(); + if ( (!this->CellClipping) && (!this->PointClipping) && + (!this->ExtentClipping) ) + { + allVisible = 1; + cellVis = NULL; + } + else + { + allVisible = 0; + cellVis = new char[numCells]; + } + + // Just pass points through, never merge + output->SetPoints(input->GetPoints()); + outputPD->PassData(pd); + + outputCD->CopyAllocate(cd,numCells,numCells/2); + + Verts = vtkCellArray::New(); + Verts->Allocate(numCells/4+1,numCells); + Lines = vtkCellArray::New(); + Lines->Allocate(numCells/4+1,numCells); + Polys = vtkCellArray::New(); + Polys->Allocate(numCells/4+1,numCells); + Strips = vtkCellArray::New(); + Strips->Allocate(numCells/4+1,numCells); + + // Loop over the cells determining what's visible + if (!allVisible) + { + for (cellId=0, Connectivity->InitTraversal(); + Connectivity->GetNextCell(npts,pts); + cellId++) + { + cellVis[cellId] = 1; + if ( this->CellClipping && cellId < this->CellMinimum || + cellId > this->CellMaximum ) + { + cellVis[cellId] = 0; + } + else + { + for (i=0; i < npts; i++) + { + p->GetPoint(pts[i], x); + if ( (this->PointClipping && (pts[i] < this->PointMinimum || + pts[i] > this->PointMaximum) ) || + (this->ExtentClipping && + (x[0] < this->Extent[0] || x[0] > this->Extent[1] || + x[1] < this->Extent[2] || x[1] > this->Extent[3] || + x[2] < this->Extent[4] || x[2] > this->Extent[5] )) ) + { + cellVis[cellId] = 0; + break; + }//point/extent clipping + }//for each point + }//if point clipping needs checking + }//for all cells + }//if not all visible + + // Loop over all cells now that visibility is known + // (Have to compute visibility first for 3D cell boundarys) + int progressInterval = numCells/20 + 1; + for (cellId=0, Connectivity->InitTraversal(); + Connectivity->GetNextCell(npts,pts); + cellId++) + { + //Progress and abort method support + if ( !(cellId % progressInterval) ) + { + vtkDebugMacro(<<"Process cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + } + + // Handle ghost cells here. Another option was used cellVis array. + if (cellGhostLevels && cellGhostLevels[cellId] > updateLevel) + { // Do not create surfaces in outer ghost cells. + continue; + } + + if (allVisible || cellVis[cellId]) //now if visible extract geometry + { + //special code for nonlinear cells - rarely occurs, so right now it + //is slow. + switch (input->GetCellType(cellId)) + { + case VTK_EMPTY_CELL: + break; + + case VTK_VERTEX: + case VTK_POLY_VERTEX: + newCellId = Verts->InsertNextCell(npts,pts); + outputCD->CopyData(cd,cellId,newCellId); + break; + + case VTK_LINE: + case VTK_POLY_LINE: + newCellId = Lines->InsertNextCell(npts,pts); + outputCD->CopyData(cd,cellId,newCellId); + break; + + case VTK_TRIANGLE: + case VTK_QUAD: + case VTK_POLYGON: + newCellId = Polys->InsertNextCell(npts,pts); + outputCD->CopyData(cd,cellId,newCellId); + break; + + case VTK_TRIANGLE_STRIP: + newCellId = Strips->InsertNextCell(npts,pts); + outputCD->CopyData(cd,cellId,newCellId); + break; + + case VTK_PIXEL: + newCellId = Polys->InsertNextCell(npts); + for ( i=0; i < npts; i++) + { + Polys->InsertCellPoint(pts[PixelConvert[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + break; + + case VTK_TETRA: + for (faceId = 0; faceId < 4; faceId++) + { + faceIds->Reset(); + faceVerts = vtkTetra::GetFaceArray(faceId); + faceIds->InsertNextId(pts[faceVerts[0]]); + faceIds->InsertNextId(pts[faceVerts[1]]); + faceIds->InsertNextId(pts[faceVerts[2]]); + numFacePts = 3; + input->GetCellNeighbors(cellId, faceIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = Polys->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + Polys->InsertCellPoint(pts[faceVerts[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + case VTK_VOXEL: + for (faceId = 0; faceId < 6; faceId++) + { + faceIds->Reset(); + faceVerts = vtkVoxel::GetFaceArray(faceId); + faceIds->InsertNextId(pts[faceVerts[0]]); + faceIds->InsertNextId(pts[faceVerts[1]]); + faceIds->InsertNextId(pts[faceVerts[2]]); + faceIds->InsertNextId(pts[faceVerts[3]]); + numFacePts = 4; + input->GetCellNeighbors(cellId, faceIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = Polys->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + Polys->InsertCellPoint(pts[faceVerts[PixelConvert[i]]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + case VTK_HEXAHEDRON: + for (faceId = 0; faceId < 6; faceId++) + { + faceIds->Reset(); + faceVerts = vtkHexahedron::GetFaceArray(faceId); + faceIds->InsertNextId(pts[faceVerts[0]]); + faceIds->InsertNextId(pts[faceVerts[1]]); + faceIds->InsertNextId(pts[faceVerts[2]]); + faceIds->InsertNextId(pts[faceVerts[3]]); + numFacePts = 4; + input->GetCellNeighbors(cellId, faceIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = Polys->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + Polys->InsertCellPoint(pts[faceVerts[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + case VTK_WEDGE: + for (faceId = 0; faceId < 5; faceId++) + { + faceIds->Reset(); + faceVerts = vtkWedge::GetFaceArray(faceId); + faceIds->InsertNextId(pts[faceVerts[0]]); + faceIds->InsertNextId(pts[faceVerts[1]]); + faceIds->InsertNextId(pts[faceVerts[2]]); + numFacePts = 3; + if (faceVerts[3] >= 0) + { + faceIds->InsertNextId(pts[faceVerts[3]]); + numFacePts = 4; + } + input->GetCellNeighbors(cellId, faceIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = Polys->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + Polys->InsertCellPoint(pts[faceVerts[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + case VTK_PYRAMID: + for (faceId = 0; faceId < 5; faceId++) + { + faceIds->Reset(); + faceVerts = vtkPyramid::GetFaceArray(faceId); + faceIds->InsertNextId(pts[faceVerts[0]]); + faceIds->InsertNextId(pts[faceVerts[1]]); + faceIds->InsertNextId(pts[faceVerts[2]]); + numFacePts = 3; + if (faceVerts[3] >= 0) + { + faceIds->InsertNextId(pts[faceVerts[3]]); + numFacePts = 4; + } + input->GetCellNeighbors(cellId, faceIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = Polys->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + Polys->InsertCellPoint(pts[faceVerts[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + case VTK_PENTAGONAL_PRISM: + for (faceId = 0; faceId < 7; faceId++) + { + faceIds->Reset(); + faceVerts = vtkPentagonalPrism::GetFaceArray(faceId); + faceIds->InsertNextId(pts[faceVerts[0]]); + faceIds->InsertNextId(pts[faceVerts[1]]); + faceIds->InsertNextId(pts[faceVerts[2]]); + faceIds->InsertNextId(pts[faceVerts[3]]); + numFacePts = 4; + if (faceVerts[4] >= 0) + { + faceIds->InsertNextId(pts[faceVerts[4]]); + numFacePts = 5; + } + input->GetCellNeighbors(cellId, faceIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = Polys->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + Polys->InsertCellPoint(pts[faceVerts[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + case VTK_HEXAGONAL_PRISM: + for (faceId = 0; faceId < 8; faceId++) + { + faceIds->Reset(); + faceVerts = vtkHexagonalPrism::GetFaceArray(faceId); + faceIds->InsertNextId(pts[faceVerts[0]]); + faceIds->InsertNextId(pts[faceVerts[1]]); + faceIds->InsertNextId(pts[faceVerts[2]]); + faceIds->InsertNextId(pts[faceVerts[3]]); + numFacePts = 4; + if (faceVerts[4] >= 0) + { + faceIds->InsertNextId(pts[faceVerts[4]]); + faceIds->InsertNextId(pts[faceVerts[5]]); + numFacePts = 6; + } + input->GetCellNeighbors(cellId, faceIds, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = Polys->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + Polys->InsertCellPoint(pts[faceVerts[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + //Quadratic cells + case VTK_QUADRATIC_EDGE: + case VTK_QUADRATIC_TRIANGLE: + case VTK_QUADRATIC_QUAD: + case VTK_QUADRATIC_TETRA: + case VTK_QUADRATIC_HEXAHEDRON: + case VTK_QUADRATIC_WEDGE: + case VTK_QUADRATIC_PYRAMID: + { + vtkGenericCell *cell = vtkGenericCell::New(); + input->GetCell(cellId,cell); + vtkIdList *ipts = vtkIdList::New(); + vtkPoints *coords = vtkPoints::New(); + vtkIdList *icellIds = vtkIdList::New(); + vtkIdType inewCellId; + + if ( cell->GetCellDimension() == 1 ) + { + cell->Triangulate(0,ipts,coords); + for (i=0; i < ipts->GetNumberOfIds(); i+=2) + { + inewCellId = Lines->InsertNextCell(2); + Lines->InsertCellPoint(ipts->GetId(i)); + Lines->InsertCellPoint(ipts->GetId(i+1)); + outputCD->CopyData(cd,cellId,inewCellId); + } + } + else if ( cell->GetCellDimension() == 2 ) + { + cell->Triangulate(0,ipts,coords); + for (i=0; i < ipts->GetNumberOfIds(); i+=3) + { + inewCellId = Polys->InsertNextCell(3); + Polys->InsertCellPoint(ipts->GetId(i)); + Polys->InsertCellPoint(ipts->GetId(i+1)); + Polys->InsertCellPoint(ipts->GetId(i+2)); + outputCD->CopyData(cd,cellId,inewCellId); + } + } + else //3D nonlinear cell + { + vtkCell *face; + for (int j=0; j < cell->GetNumberOfFaces(); j++) + { + face = cell->GetFace(j); + input->GetCellNeighbors(cellId, face->PointIds, icellIds); + if ( icellIds->GetNumberOfIds() <= 0) + { + face->Triangulate(0,ipts,coords); + for (i=0; i < ipts->GetNumberOfIds(); i+=3) + { + inewCellId = Polys->InsertNextCell(3); + Polys->InsertCellPoint(ipts->GetId(i)); + Polys->InsertCellPoint(ipts->GetId(i+1)); + Polys->InsertCellPoint(ipts->GetId(i+2)); + outputCD->CopyData(cd,cellId,inewCellId); + } + } + } + } //3d cell + icellIds->Delete(); + coords->Delete(); + ipts->Delete(); + cell->Delete(); + } + break; //done with quadratic cells + + } //switch + } //if visible + } //for all cells + + // Update ourselves and release memory + // + output->SetVerts(Verts); + Verts->Delete(); + output->SetLines(Lines); + Lines->Delete(); + output->SetPolys(Polys); + Polys->Delete(); + output->SetStrips(Strips); + Strips->Delete(); + + output->Squeeze(); + + vtkDebugMacro(<<"Extracted " << input->GetNumberOfPoints() << " points," + << output->GetNumberOfCells() << " cells."); + + cellIds->Delete(); + faceIds->Delete(); + if ( cellVis ) + { + delete [] cellVis; + } +} + +void vtkGeometryFilter::StructuredGridExecute(vtkDataSet *dataSetInput, + vtkPolyData *output, + vtkInformation *outInfo) +{ + vtkIdType cellId, newCellId; + int i; + vtkStructuredGrid *input=(vtkStructuredGrid *)dataSetInput; + vtkIdType numCells=input->GetNumberOfCells(); + char *cellVis; + vtkGenericCell *cell; + double x[3]; + vtkIdList *ptIds; + vtkIdList *cellIds; + vtkIdList *pts; + vtkIdType ptId; + int *faceVerts, faceId, numFacePts; + vtkIdType *facePts; + vtkPointData *pd = input->GetPointData(); + vtkCellData *cd = input->GetCellData(); + int allVisible; + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkCellArray *cells; + // ghost cell stuff + unsigned char updateLevel = (unsigned char) + (outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + unsigned char *cellGhostLevels = 0; + + cellIds = vtkIdList::New(); + pts = vtkIdList::New(); + + vtkDebugMacro(<<"Executing geometry filter with structured grid input"); + + cell = vtkGenericCell::New(); + + vtkDataArray* temp = 0; + if (cd) + { + temp = cd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + cellGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + if ( (!this->CellClipping) && (!this->PointClipping) && + (!this->ExtentClipping) ) + { + allVisible = 1; + cellVis = NULL; + } + else + { + allVisible = 0; + cellVis = new char[numCells]; + } + + // Mark cells as being visible or not + // + if ( ! allVisible ) + { + for(cellId=0; cellId < numCells; cellId++) + { + cellVis[cellId] = 1; + if ( this->CellClipping && cellId < this->CellMinimum || + cellId > this->CellMaximum ) + { + cellVis[cellId] = 0; + } + else + { + input->GetCell(cellId,cell); + ptIds = cell->GetPointIds(); + for (i=0; i < ptIds->GetNumberOfIds(); i++) + { + ptId = ptIds->GetId(i); + input->GetPoint(ptId, x); + + if ( (this->PointClipping && (ptId < this->PointMinimum || + ptId > this->PointMaximum) ) || + (this->ExtentClipping && + (x[0] < this->Extent[0] || x[0] > this->Extent[1] || + x[1] < this->Extent[2] || x[1] > this->Extent[3] || + x[2] < this->Extent[4] || x[2] > this->Extent[5] )) ) + { + cellVis[cellId] = 0; + break; + } + } + } + } + } + + // Allocate - points are never merged + // + output->SetPoints(input->GetPoints()); + outputPD->PassData(pd); + outputCD->CopyAllocate(cd,numCells,numCells/2); + + cells = vtkCellArray::New(); + cells->Allocate(numCells,numCells/2); + + // Traverse cells to extract geometry + // + vtkIdType progressInterval = numCells/20 + 1; + for(cellId=0; cellId < numCells; cellId++) + { + //Progress and abort method support + if ( !(cellId % progressInterval) ) + { + vtkDebugMacro(<<"Process cell #" << cellId); + this->UpdateProgress ((double)cellId/numCells); + } + + // Handle ghost cells here. Another option was used cellVis array. + if (cellGhostLevels && cellGhostLevels[cellId] > updateLevel) + { // Do not create surfaces in outer ghost cells. + continue; + } + + if ( (allVisible || cellVis[cellId])) + { + input->GetCell(cellId,cell); + switch (cell->GetCellDimension()) + { + // create new points and then cell + case 0: case 1: case 2: + newCellId = cells->InsertNextCell(cell); + outputCD->CopyData(cd,cellId,newCellId); + break; + + case 3: //must be hexahedron + facePts = cell->GetPointIds()->GetPointer(0); + for (faceId = 0; faceId < 6; faceId++) + { + pts->Reset(); + faceVerts = vtkHexahedron::GetFaceArray(faceId); + pts->InsertNextId(facePts[faceVerts[0]]); + pts->InsertNextId(facePts[faceVerts[1]]); + pts->InsertNextId(facePts[faceVerts[2]]); + pts->InsertNextId(facePts[faceVerts[3]]); + numFacePts = 4; + input->GetCellNeighbors(cellId, pts, cellIds); + if ( cellIds->GetNumberOfIds() <= 0 || + (!allVisible && !cellVis[cellIds->GetId(0)]) ) + { + newCellId = cells->InsertNextCell(numFacePts); + for ( i=0; i < numFacePts; i++) + { + cells->InsertCellPoint(facePts[faceVerts[i]]); + } + outputCD->CopyData(cd,cellId,newCellId); + } + } + break; + + } //switch + } //if visible + } //for all cells + + switch (input->GetDataDimension()) + { + case 0: + output->SetVerts(cells); + break; + case 1: + output->SetLines(cells); + break; + case 2: case 3: + output->SetPolys(cells); + } + + vtkDebugMacro(<<"Extracted " << output->GetNumberOfPoints() << " points," + << output->GetNumberOfCells() << " cells."); + + // Update ourselves and release memory + // + cells->Delete(); + cell->Delete(); + output->Squeeze(); + cellIds->Delete(); + pts->Delete(); + if ( cellVis ) + { + delete [] cellVis; + } +} + +int vtkGeometryFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces, ghostLevels; + + piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevels = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + if (numPieces > 1) + { + ++ghostLevels; + } + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevels); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + + return 1; +} diff --git a/Graphics/vtkGeometryFilter.h b/Graphics/vtkGeometryFilter.h new file mode 100644 index 0000000..052a7f8 --- /dev/null +++ b/Graphics/vtkGeometryFilter.h @@ -0,0 +1,159 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGeometryFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGeometryFilter - extract geometry from data (or convert data to polygonal type) +// .SECTION Description +// vtkGeometryFilter is a general-purpose filter to extract geometry (and +// associated data) from any type of dataset. Geometry is obtained as +// follows: all 0D, 1D, and 2D cells are extracted. All 2D faces that are +// used by only one 3D cell (i.e., boundary faces) are extracted. It also is +// possible to specify conditions on point ids, cell ids, and on +// bounding box (referred to as "Extent") to control the extraction process. +// +// This filter also may be used to convert any type of data to polygonal +// type. The conversion process may be less than satisfactory for some 3D +// datasets. For example, this filter will extract the outer surface of a +// volume or structured grid dataset. (For structured data you may want to +// use vtkImageDataGeometryFilter, vtkStructuredGridGeometryFilter, +// vtkExtractUnstructuredGrid, vtkRectilinearGridGeometryFilter, or +// vtkExtractVOI.) + +// .SECTION Caveats +// When vtkGeometryFilter extracts cells (or boundaries of cells) it +// will (by default) merge duplicate vertices. This may cause problems +// in some cases. For example, if you've run vtkPolyDataNormals to +// generate normals, which may split meshes and create duplicate +// vertices, vtkGeometryFilter will merge these points back +// together. Turn merging off to prevent this from occurring. + +// .SECTION See Also +// vtkImageDataGeometryFilter vtkStructuredGridGeometryFilter +// vtkExtractGeometry vtkExtractVOI + +#ifndef __vtkGeometryFilter_h +#define __vtkGeometryFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkGeometryFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkGeometryFilter *New(); + vtkTypeRevisionMacro(vtkGeometryFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Turn on/off selection of geometry by point id. + vtkSetMacro(PointClipping,int); + vtkGetMacro(PointClipping,int); + vtkBooleanMacro(PointClipping,int); + + // Description: + // Turn on/off selection of geometry by cell id. + vtkSetMacro(CellClipping,int); + vtkGetMacro(CellClipping,int); + vtkBooleanMacro(CellClipping,int); + + // Description: + // Turn on/off selection of geometry via bounding box. + vtkSetMacro(ExtentClipping,int); + vtkGetMacro(ExtentClipping,int); + vtkBooleanMacro(ExtentClipping,int); + + // Description: + // Specify the minimum point id for point id selection. + vtkSetClampMacro(PointMinimum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(PointMinimum,vtkIdType); + + // Description: + // Specify the maximum point id for point id selection. + vtkSetClampMacro(PointMaximum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(PointMaximum,vtkIdType); + + // Description: + // Specify the minimum cell id for point id selection. + vtkSetClampMacro(CellMinimum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(CellMinimum,vtkIdType); + + // Description: + // Specify the maximum cell id for point id selection. + vtkSetClampMacro(CellMaximum,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(CellMaximum,vtkIdType); + + // Description: + // Specify a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. + void SetExtent(double xMin, double xMax, double yMin, double yMax, + double zMin, double zMax); + + // Description: + // Set / get a (xmin,xmax, ymin,ymax, zmin,zmax) bounding box to clip data. + void SetExtent(double extent[6]); + double *GetExtent() { return this->Extent;}; + + // Description: + // Turn on/off merging of coincident points. Note that is merging is + // on, points with different point attributes (e.g., normals) are merged, + // which may cause rendering artifacts. + vtkSetMacro(Merging,int); + vtkGetMacro(Merging,int); + vtkBooleanMacro(Merging,int); + + // Description: + // Set / get a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + + // Description: + // Return the MTime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkGeometryFilter(); + ~vtkGeometryFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + //special cases for performance + void PolyDataExecute(vtkDataSet *, vtkPolyData *, vtkInformation *); + void UnstructuredGridExecute(vtkDataSet *, vtkPolyData *, vtkInformation *); + void StructuredGridExecute(vtkDataSet *, vtkPolyData *, vtkInformation *); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkIdType PointMaximum; + vtkIdType PointMinimum; + vtkIdType CellMinimum; + vtkIdType CellMaximum; + double Extent[6]; + int PointClipping; + int CellClipping; + int ExtentClipping; + + int Merging; + vtkPointLocator *Locator; +private: + vtkGeometryFilter(const vtkGeometryFilter&); // Not implemented. + void operator=(const vtkGeometryFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkGlyph2D.cxx b/Graphics/vtkGlyph2D.cxx new file mode 100644 index 0000000..6166b58 --- /dev/null +++ b/Graphics/vtkGlyph2D.cxx @@ -0,0 +1,471 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGlyph2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGlyph2D.h" + +#include "vtkCell.h" +#include "vtkDoubleArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkGlyph2D, "$Revision: 1.25 $"); +vtkStandardNewMacro(vtkGlyph2D); + +int vtkGlyph2D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkPointData *pd; + vtkDataArray *inScalars; + vtkDataArray *inVectors; + unsigned char* inGhostLevels = 0; + vtkDataArray *inNormals, *sourceNormals = NULL; + vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i; + int index; + vtkPoints *sourcePts = NULL; + vtkPoints *newPts; + vtkDataArray *newScalars=NULL; + vtkDataArray *newVectors=NULL; + vtkDataArray *newNormals=NULL; + double x[3], v[3], s = 0.0, vMag = 0.0, value, theta; + vtkTransform *trans = vtkTransform::New(); + vtkCell *cell; + vtkIdList *cellPts; + int npts; + vtkIdList *pts; + vtkIdType ptIncr, cellId; + int haveVectors, haveNormals; + double scalex,scaley, den; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointData *outputPD = output->GetPointData(); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + int numberOfSources = this->GetNumberOfInputConnections(1); + vtkPolyData *source = 0; + + vtkDebugMacro(<<"Generating 2D glyphs"); + + pts = vtkIdList::New(); + pts->Allocate(VTK_CELL_SIZE); + + pd = input->GetPointData(); + + inScalars = this->GetInputArrayToProcess(0,inputVector); + inVectors = this->GetInputArrayToProcess(1,inputVector); + inNormals = this->GetInputArrayToProcess(2,inputVector); + + vtkDataArray* temp = 0; + if (pd) + { + temp = pd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + numPts = input->GetNumberOfPoints(); + if (numPts < 1) + { + vtkDebugMacro(<<"No points to glyph!"); + pts->Delete(); + trans->Delete(); + return 1; + } + + // Check input for consistency + // + if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) + { + den = 1.0; + } + if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF && + ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) || + (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) ) + { + haveVectors = 1; + } + else + { + haveVectors = 0; + } + + if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inScalars) || + (this->IndexMode == VTK_INDEXING_BY_VECTOR && + ((!inVectors && this->VectorMode == VTK_USE_VECTOR) || + (!inNormals && this->VectorMode == VTK_USE_NORMAL))) ) + { + if ( this->GetSource(0, inputVector[1]) == NULL ) + { + vtkErrorMacro(<<"Indexing on but don't have data to index with"); + pts->Delete(); + trans->Delete(); + return 1; + } + else + { + vtkWarningMacro(<<"Turning indexing off: no data to index with"); + this->IndexMode = VTK_INDEXING_OFF; + } + } + + // Allocate storage for output PolyData + // + outputPD->CopyVectorsOff(); + outputPD->CopyNormalsOff(); + if ( this->IndexMode != VTK_INDEXING_OFF ) + { + pd = NULL; + //numSourcePts = numSourceCells = 0; + haveNormals = 1; + for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++) + { + source = this->GetSource(i, inputVector[1]); + if ( source != NULL ) + { + numSourcePts += source->GetNumberOfPoints(); + numSourceCells += source->GetNumberOfCells(); + sourceNormals = source->GetPointData()->GetNormals(); + if ( !sourceNormals ) + { + haveNormals = 0; + } + } + } + } + else + { + source = this->GetSource(0, inputVector[1]); + sourcePts = source->GetPoints(); + numSourcePts = sourcePts->GetNumberOfPoints(); + numSourceCells = source->GetNumberOfCells(); + + sourceNormals = source->GetPointData()->GetNormals(); + if ( sourceNormals ) + { + haveNormals = 1; + } + else + { + haveNormals = 0; + } + + // Prepare to copy output. + pd = source->GetPointData(); + outputPD->CopyAllocate(pd,numPts*numSourcePts); + } + + newPts = vtkPoints::New(); + newPts->Allocate(numPts*numSourcePts); + if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inScalars ) + { + newScalars = inScalars->NewInstance(); + newScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + newScalars->Allocate(inScalars->GetNumberOfComponents()*numPts*numSourcePts); + } + else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inScalars) + { + newScalars = vtkDoubleArray::New(); + newScalars->Allocate(numPts*numSourcePts); + newScalars->SetName("GlyphScale"); + } + else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors) + { + newScalars = vtkDoubleArray::New(); + newScalars->Allocate(numPts*numSourcePts); + newScalars->SetName("VectorMagnitude"); + } + if ( haveVectors ) + { + newVectors = vtkDoubleArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(3*numPts*numSourcePts); + newVectors->SetName("GlyphVector"); + } + if ( haveNormals ) + { + newNormals = vtkDoubleArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts*numSourcePts); + newNormals->SetName("Normals"); + } + + // Setting up for calls to PolyData::InsertNextCell() + if (this->IndexMode != VTK_INDEXING_OFF ) + { + output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells); + } + else + { + output->Allocate(this->GetSource(0, inputVector[1]), + 3*numPts*numSourceCells, numPts*numSourceCells); + } + + // Traverse all Input points, transforming Source points and copying + // point attributes. + // + ptIncr=0; + for (inPtId=0; inPtId < numPts; inPtId++) + { + scalex = scaley = 1.0; + if ( ! (inPtId % 10000) ) + { + this->UpdateProgress ((double)inPtId/numPts); + if (this->GetAbortExecute()) + { + break; + } + } + + // Get the scalar and vector data + if ( inScalars ) + { + s = inScalars->GetComponent(inPtId, 0); + if ( this->ScaleMode == VTK_SCALE_BY_SCALAR || + this->ScaleMode == VTK_DATA_SCALING_OFF ) + { + scalex = scaley = s; + } + } + + if ( haveVectors ) + { + if ( this->VectorMode == VTK_USE_NORMAL ) + { + inNormals->GetTuple(inPtId, v); + } + else + { + inVectors->GetTuple(inPtId, v); + } + vMag = vtkMath::Norm(v); + if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS ) + { + scalex = v[0]; + scaley = v[1]; + } + else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) + { + scalex = scaley = vMag; + } + } + + // Clamp data scale if enabled + if ( this->Clamping ) + { + scalex = (scalex < this->Range[0] ? this->Range[0] : + (scalex > this->Range[1] ? this->Range[1] : scalex)); + scalex = (scalex - this->Range[0]) / den; + scaley = (scaley < this->Range[0] ? this->Range[0] : + (scaley > this->Range[1] ? this->Range[1] : scaley)); + scaley = (scaley - this->Range[0]) / den; + } + + // Compute index into table of glyphs + if ( this->IndexMode == VTK_INDEXING_OFF ) + { + index = 0; + } + else + { + if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) + { + value = s; + } + else + { + value = vMag; + } + + index = (int) ((double)(value - this->Range[0]) * numberOfSources / den); + index = (index < 0 ? 0 : + (index >= numberOfSources ? (numberOfSources-1) : index)); + + source = this->GetSource(index, inputVector[1]); + if ( source != NULL ) + { + sourcePts = source->GetPoints(); + sourceNormals = source->GetPointData()->GetNormals(); + numSourcePts = sourcePts->GetNumberOfPoints(); + numSourceCells = source->GetNumberOfCells(); + } + } + + // Make sure we're not indexing into empty glyph + if ( this->GetSource(index, inputVector[1]) == NULL ) + { + continue; + } + + // Check ghost points. + if (inGhostLevels && inGhostLevels[inPtId] > 0) + { + continue; + } + + // Now begin copying/transforming glyph + trans->Identity(); + + // Copy all topology (transformation independent) + for (cellId=0; cellId < numSourceCells; cellId++) + { + cell = this->GetSource(index, inputVector[1])->GetCell(cellId); + cellPts = cell->GetPointIds(); + npts = cellPts->GetNumberOfIds(); + for (pts->Reset(), i=0; i < npts; i++) + { + pts->InsertId(i,cellPts->GetId(i) + ptIncr); + } + output->InsertNextCell(cell->GetCellType(),pts); + } + + // translate Source to Input point + input->GetPoint(inPtId, x); + trans->Translate(x[0], x[1], 0.0); + + if ( haveVectors ) + { + // Copy Input vector + for (i=0; i < numSourcePts; i++) + { + newVectors->InsertTuple(i+ptIncr, v); + } + if (this->Orient && (vMag > 0.0)) + { + theta = atan2(v[1],v[0])/vtkMath::DegreesToRadians(); + trans->RotateWXYZ(theta, 0.0, 0.0, 1.0); + } + } + + // determine scale factor from scalars if appropriate + if ( inScalars ) + { + // Copy scalar value + if (this->ColorMode == VTK_COLOR_BY_SCALE) + { + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(i+ptIncr, &scalex); + } + } + else if (this->ColorMode == VTK_COLOR_BY_SCALAR) + { + for (i=0; i < numSourcePts; i++) + { + outputPD->CopyTuple(inScalars, newScalars, inPtId, ptIncr+i); + } + } + } + if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR) + { + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(i+ptIncr, &vMag); + } + } + + // scale data if appropriate + if ( this->Scaling ) + { + if ( this->ScaleMode == VTK_DATA_SCALING_OFF ) + { + scalex = scaley = this->ScaleFactor; + } + else + { + scalex *= this->ScaleFactor; + scaley *= this->ScaleFactor; + } + + if ( scalex == 0.0 ) + { + scalex = 1.0e-10; + } + if ( scaley == 0.0 ) + { + scaley = 1.0e-10; + } + trans->Scale(scalex,scaley,1.0); + } + + // multiply points and normals by resulting matrix + trans->TransformPoints(sourcePts,newPts); + + if ( haveNormals ) + { + trans->TransformNormals(sourceNormals,newNormals); + } + + // Copy point data from source (if possible) + if ( pd ) + { + for (i=0; i < numSourcePts; i++) + { + outputPD->CopyData(pd,i,ptIncr+i); + } + } + ptIncr += numSourcePts; + } + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newScalars) + { + outputPD->AddArray(newScalars); + outputPD->SetActiveScalars(newScalars->GetName()); + newScalars->Delete(); + } + + if (newVectors) + { + outputPD->SetVectors(newVectors); + newVectors->Delete(); + } + + if (newNormals) + { + outputPD->SetNormals(newNormals); + newNormals->Delete(); + } + + output->Squeeze(); + trans->Delete(); + pts->Delete(); + + return 1; +} + +void vtkGlyph2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkGlyph2D.h b/Graphics/vtkGlyph2D.h new file mode 100644 index 0000000..b5a291f --- /dev/null +++ b/Graphics/vtkGlyph2D.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGlyph2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGlyph2D - copy oriented and scaled glyph geometry to every input point (2D specialization) +// .SECTION Description +// This subclass of vtkGlyph3D is a specialization to 2D. Transformations +// (i.e., translation, scaling, and rotation) are constrained to the plane. +// For example, rotations due to a vector are computed from the x-y +// coordinates of the vector only, and are assumed to occur around the +// z-axis. (See vtkGlyph3D for documentation on the interface to this +// class.) +// +// .SECTION See Also +// vtkTensorGlyph vtkGlyph3D vtkProgrammableGlyphFilter + +#ifndef __vtkGlyph2D_h +#define __vtkGlyph2D_h + +#include "vtkGlyph3D.h" + +class VTK_GRAPHICS_EXPORT vtkGlyph2D : public vtkGlyph3D +{ +public: + vtkTypeRevisionMacro(vtkGlyph2D,vtkGlyph3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct object with scaling on, scaling mode is by scalar value, + // scale factor = 1.0, the range is (0,1), orient geometry is on, and + // orientation is by vector. Clamping and indexing are turned off. No + // initial sources are defined. + static vtkGlyph2D *New(); + +protected: + vtkGlyph2D() {}; + ~vtkGlyph2D() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkGlyph2D(const vtkGlyph2D&); // Not implemented. + void operator=(const vtkGlyph2D&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkGlyph3D.cxx b/Graphics/vtkGlyph3D.cxx new file mode 100644 index 0000000..cf5cd72 --- /dev/null +++ b/Graphics/vtkGlyph3D.cxx @@ -0,0 +1,846 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGlyph3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGlyph3D.h" + +#include "vtkCell.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTransform.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkGlyph3D, "$Revision: 1.123.4.1 $"); +vtkStandardNewMacro(vtkGlyph3D); + +//---------------------------------------------------------------------------- +// Construct object with scaling on, scaling mode is by scalar value, +// scale factor = 1.0, the range is (0,1), orient geometry is on, and +// orientation is by vector. Clamping and indexing are turned off. No +// initial sources are defined. +vtkGlyph3D::vtkGlyph3D() +{ + this->Scaling = 1; + this->ColorMode = VTK_COLOR_BY_SCALE; + this->ScaleMode = VTK_SCALE_BY_SCALAR; + this->ScaleFactor = 1.0; + this->Range[0] = 0.0; + this->Range[1] = 1.0; + this->Orient = 1; + this->VectorMode = VTK_USE_VECTOR; + this->Clamping = 0; + this->IndexMode = VTK_INDEXING_OFF; + this->GeneratePointIds = 0; + this->PointIdsName = NULL; + this->SetPointIdsName("InputPointIds"); + this->SetNumberOfInputPorts(2); + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); + // by default process active point vectors + this->SetInputArrayToProcess(1,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::VECTORS); + // by default process active point normals + this->SetInputArrayToProcess(2,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::NORMALS); + // by default process active point scalars + this->SetInputArrayToProcess(3,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//---------------------------------------------------------------------------- +vtkGlyph3D::~vtkGlyph3D() +{ + if (this->PointIdsName) + { + delete []PointIdsName; + } +} + +//---------------------------------------------------------------------------- +int vtkGlyph3D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd; + vtkDataArray *inSScalars; // Scalars for Scaling + vtkDataArray *inCScalars; // Scalars for Coloring + vtkDataArray *inVectors; + int requestedGhostLevel; + unsigned char* inGhostLevels=0; + vtkDataArray *inNormals, *sourceNormals = NULL; + vtkDataArray *sourceTCoords = NULL; + vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i; + int index; + vtkPoints *sourcePts = NULL; + vtkPoints *newPts; + vtkDataArray *newScalars=NULL; + vtkDataArray *newVectors=NULL; + vtkDataArray *newNormals=NULL; + vtkDataArray *newTCoords = NULL; + double x[3], v[3], vNew[3], s = 0.0, vMag = 0.0, value, tc[3]; + vtkTransform *trans = vtkTransform::New(); + vtkCell *cell; + vtkIdList *cellPts; + int npts; + vtkIdList *pts; + vtkIdType ptIncr, cellId; + int haveVectors, haveNormals, haveTCoords = 0; + double scalex,scaley,scalez, den; + vtkPointData *outputPD = output->GetPointData(); + int numberOfSources = this->GetNumberOfInputConnections(1); + vtkPolyData *defaultSource = NULL; + vtkIdTypeArray *pointIds=0; + vtkPolyData *source = 0; + + vtkDebugMacro(<<"Generating glyphs"); + + pts = vtkIdList::New(); + pts->Allocate(VTK_CELL_SIZE); + + pd = input->GetPointData(); + inSScalars = this->GetInputArrayToProcess(0,inputVector); + inVectors = this->GetInputArrayToProcess(1,inputVector); + inNormals = this->GetInputArrayToProcess(2,inputVector); + inCScalars = this->GetInputArrayToProcess(3,inputVector); + if (inCScalars == NULL) + { + inCScalars = inSScalars; + } + + vtkDataArray* temp = 0; + if (pd) + { + temp = pd->GetArray("vtkGhostLevels"); + } + if ( (!temp) || (temp->GetDataType() != VTK_UNSIGNED_CHAR) + || (temp->GetNumberOfComponents() != 1)) + { + vtkDebugMacro("No appropriate ghost levels field available."); + } + else + { + inGhostLevels = ((vtkUnsignedCharArray*)temp)->GetPointer(0); + } + + requestedGhostLevel = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + numPts = input->GetNumberOfPoints(); + if (numPts < 1) + { + vtkDebugMacro(<<"No points to glyph!"); + pts->Delete(); + trans->Delete(); + return 1; + } + + // Check input for consistency + // + if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) + { + den = 1.0; + } + if ( this->VectorMode != VTK_VECTOR_ROTATION_OFF && + ((this->VectorMode == VTK_USE_VECTOR && inVectors != NULL) || + (this->VectorMode == VTK_USE_NORMAL && inNormals != NULL)) ) + { + haveVectors = 1; + } + else + { + haveVectors = 0; + } + + if ( (this->IndexMode == VTK_INDEXING_BY_SCALAR && !inSScalars) || + (this->IndexMode == VTK_INDEXING_BY_VECTOR && + ((!inVectors && this->VectorMode == VTK_USE_VECTOR) || + (!inNormals && this->VectorMode == VTK_USE_NORMAL))) ) + { + if ( this->GetSource(0, inputVector[1]) == NULL ) + { + vtkErrorMacro(<<"Indexing on but don't have data to index with"); + pts->Delete(); + trans->Delete(); + return 1; + } + else + { + vtkWarningMacro(<<"Turning indexing off: no data to index with"); + this->IndexMode = VTK_INDEXING_OFF; + } + } + + // Allocate storage for output PolyData + // + outputPD->CopyVectorsOff(); + outputPD->CopyNormalsOff(); + outputPD->CopyTCoordsOff(); + + if (!this->GetSource(0, inputVector[1])) + { + defaultSource = vtkPolyData::New(); + defaultSource->Allocate(); + vtkPoints *defaultPoints = vtkPoints::New(); + defaultPoints->Allocate(6); + defaultPoints->InsertNextPoint(0, 0, 0); + defaultPoints->InsertNextPoint(1, 0, 0); + vtkIdType defaultPointIds[2]; + defaultPointIds[0] = 0; + defaultPointIds[1] = 1; + defaultSource->SetPoints(defaultPoints); + defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds); + defaultSource->SetUpdateExtent(0, 1, 0); + this->SetSource(defaultSource); + defaultSource->Delete(); + defaultSource = NULL; + defaultPoints->Delete(); + defaultPoints = NULL; + } + + if ( this->IndexMode != VTK_INDEXING_OFF ) + { + pd = NULL; + haveNormals = 1; + for (numSourcePts=numSourceCells=i=0; i < numberOfSources; i++) + { + source = this->GetSource(i, inputVector[1]); + if ( source != NULL ) + { + if (source->GetNumberOfPoints() > numSourcePts) + { + numSourcePts = source->GetNumberOfPoints(); + } + if (source->GetNumberOfCells() > numSourceCells) + { + numSourceCells = source->GetNumberOfCells(); + } + if ( !(sourceNormals = source->GetPointData()->GetNormals()) ) + { + haveNormals = 0; + } + } + } + } + else + { + source = this->GetSource(0, inputVector[1]); + sourcePts = source->GetPoints(); + numSourcePts = sourcePts->GetNumberOfPoints(); + numSourceCells = source->GetNumberOfCells(); + + sourceNormals = source->GetPointData()->GetNormals(); + if ( sourceNormals ) + { + haveNormals = 1; + } + else + { + haveNormals = 0; + } + + sourceTCoords = source->GetPointData()->GetTCoords(); + if (sourceTCoords) + { + haveTCoords = 1; + } + else + { + haveTCoords = 0; + } + + // Prepare to copy output. + pd = input->GetPointData(); + outputPD->CopyAllocate(pd,numPts*numSourcePts); + } + + newPts = vtkPoints::New(); + newPts->Allocate(numPts*numSourcePts); + if ( this->GeneratePointIds ) + { + pointIds = vtkIdTypeArray::New(); + pointIds->SetName(this->PointIdsName); + pointIds->Allocate(numPts*numSourcePts); + outputPD->AddArray(pointIds); + pointIds->Delete(); + } + if ( this->ColorMode == VTK_COLOR_BY_SCALAR && inCScalars ) + { + newScalars = inCScalars->NewInstance(); + newScalars->SetNumberOfComponents(inCScalars->GetNumberOfComponents()); + newScalars->Allocate(inCScalars->GetNumberOfComponents()*numPts*numSourcePts); + newScalars->SetName(inCScalars->GetName()); + } + else if ( (this->ColorMode == VTK_COLOR_BY_SCALE) && inSScalars) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(numPts*numSourcePts); + newScalars->SetName("GlyphScale"); + if (this->ScaleMode == VTK_SCALE_BY_SCALAR) + { + newScalars->SetName(inSScalars->GetName()); + } + } + else if ( (this->ColorMode == VTK_COLOR_BY_VECTOR) && haveVectors) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(numPts*numSourcePts); + newScalars->SetName("VectorMagnitude"); + } + if ( haveVectors ) + { + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(3*numPts*numSourcePts); + newVectors->SetName("GlyphVector"); + } + if ( haveNormals ) + { + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts*numSourcePts); + newNormals->SetName("Normals"); + } + if (haveTCoords) + { + newTCoords = vtkFloatArray::New(); + int numComps = sourceTCoords->GetNumberOfComponents(); + newTCoords->SetNumberOfComponents(numComps); + newTCoords->Allocate(numComps*numPts*numSourcePts); + newTCoords->SetName("TCoords"); + } + + // Setting up for calls to PolyData::InsertNextCell() + if (this->IndexMode != VTK_INDEXING_OFF ) + { + output->Allocate(3*numPts*numSourceCells,numPts*numSourceCells); + } + else + { + output->Allocate(this->GetSource(0, inputVector[1]), + 3*numPts*numSourceCells, numPts*numSourceCells); + } + + // Traverse all Input points, transforming Source points and copying + // point attributes. + // + ptIncr=0; + for (inPtId=0; inPtId < numPts; inPtId++) + { + scalex = scaley = scalez = 1.0; + if ( ! (inPtId % 10000) ) + { + this->UpdateProgress ((double)inPtId/numPts); + if (this->GetAbortExecute()) + { + break; + } + } + + // Get the scalar and vector data + if ( inSScalars ) + { + s = inSScalars->GetComponent(inPtId, 0); + if ( this->ScaleMode == VTK_SCALE_BY_SCALAR || + this->ScaleMode == VTK_DATA_SCALING_OFF ) + { + scalex = scaley = scalez = s; + } + } + + if ( haveVectors ) + { + if ( this->VectorMode == VTK_USE_NORMAL ) + { + inNormals->GetTuple(inPtId, v); + } + else + { + inVectors->GetTuple(inPtId, v); + } + vMag = vtkMath::Norm(v); + if ( this->ScaleMode == VTK_SCALE_BY_VECTORCOMPONENTS ) + { + scalex = v[0]; + scaley = v[1]; + scalez = v[2]; + } + else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) + { + scalex = scaley = scalez = vMag; + } + } + + // Clamp data scale if enabled + if ( this->Clamping ) + { + scalex = (scalex < this->Range[0] ? this->Range[0] : + (scalex > this->Range[1] ? this->Range[1] : scalex)); + scalex = (scalex - this->Range[0]) / den; + scaley = (scaley < this->Range[0] ? this->Range[0] : + (scaley > this->Range[1] ? this->Range[1] : scaley)); + scaley = (scaley - this->Range[0]) / den; + scalez = (scalez < this->Range[0] ? this->Range[0] : + (scalez > this->Range[1] ? this->Range[1] : scalez)); + scalez = (scalez - this->Range[0]) / den; + } + + // Compute index into table of glyphs + if ( this->IndexMode == VTK_INDEXING_OFF ) + { + index = 0; + } + else + { + if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) + { + value = s; + } + else + { + value = vMag; + } + + index = (int) ((double)(value - this->Range[0]) * numberOfSources / den); + index = (index < 0 ? 0 : + (index >= numberOfSources ? (numberOfSources-1) : index)); + + source = this->GetSource(index, inputVector[1]); + if ( source != NULL ) + { + sourcePts = source->GetPoints(); + sourceNormals = source->GetPointData()->GetNormals(); + numSourcePts = sourcePts->GetNumberOfPoints(); + numSourceCells = source->GetNumberOfCells(); + } + } + + // Make sure we're not indexing into empty glyph + if ( this->GetSource(index, inputVector[1]) == NULL ) + { + continue; + } + + // Check ghost points. + // If we are processing a piece, we do not want to duplicate + // glyphs on the borders. The corrct check here is: + // ghostLevel > 0. I am leaving this over glyphing here because + // it make a nice example (sphereGhost.tcl) to show the + // point ghost levels with the glyph filter. I am not certain + // of the usefullness of point ghost levels over 1, but I will have + // to think about it. + if (inGhostLevels && inGhostLevels[inPtId] > requestedGhostLevel) + { + continue; + } + + if (!this->IsPointVisible(input, inPtId)) + { + continue; + } + + // Now begin copying/transforming glyph + trans->Identity(); + + // Copy all topology (transformation independent) + for (cellId=0; cellId < numSourceCells; cellId++) + { + cell = this->GetSource(index, inputVector[1])->GetCell(cellId); + cellPts = cell->GetPointIds(); + npts = cellPts->GetNumberOfIds(); + for (pts->Reset(), i=0; i < npts; i++) + { + pts->InsertId(i,cellPts->GetId(i) + ptIncr); + } + output->InsertNextCell(cell->GetCellType(),pts); + } + + // translate Source to Input point + input->GetPoint(inPtId, x); + trans->Translate(x[0], x[1], x[2]); + + if ( haveVectors ) + { + // Copy Input vector + for (i=0; i < numSourcePts; i++) + { + newVectors->InsertTuple(i+ptIncr, v); + } + if (this->Orient && (vMag > 0.0)) + { + // if there is no y or z component + if ( v[1] == 0.0 && v[2] == 0.0 ) + { + if (v[0] < 0) //just flip x if we need to + { + trans->RotateWXYZ(180.0,0,1,0); + } + } + else + { + vNew[0] = (v[0]+vMag) / 2.0; + vNew[1] = v[1] / 2.0; + vNew[2] = v[2] / 2.0; + trans->RotateWXYZ((double)180.0,vNew[0],vNew[1],vNew[2]); + } + } + } + + if (haveTCoords) + { + for (i = 0; i < numSourcePts; i++) + { + sourceTCoords->GetTuple(i, tc); + newTCoords->InsertTuple(i+ptIncr, tc); + } + } + + // determine scale factor from scalars if appropriate + // Copy scalar value + if (inSScalars && (this->ColorMode == VTK_COLOR_BY_SCALE)) + { + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(i+ptIncr, &scalex); // = scaley = scalez + } + } + else if (inCScalars && (this->ColorMode == VTK_COLOR_BY_SCALAR)) + { + for (i=0; i < numSourcePts; i++) + { + outputPD->CopyTuple(inCScalars, newScalars, inPtId, ptIncr+i); + } + } + if (haveVectors && this->ColorMode == VTK_COLOR_BY_VECTOR) + { + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(i+ptIncr, &vMag); + } + } + + // scale data if appropriate + if ( this->Scaling ) + { + if ( this->ScaleMode == VTK_DATA_SCALING_OFF ) + { + scalex = scaley = scalez = this->ScaleFactor; + } + else + { + scalex *= this->ScaleFactor; + scaley *= this->ScaleFactor; + scalez *= this->ScaleFactor; + } + + if ( scalex == 0.0 ) + { + scalex = 1.0e-10; + } + if ( scaley == 0.0 ) + { + scaley = 1.0e-10; + } + if ( scalez == 0.0 ) + { + scalez = 1.0e-10; + } + trans->Scale(scalex,scaley,scalez); + } + + // multiply points and normals by resulting matrix + trans->TransformPoints(sourcePts,newPts); + + if ( haveNormals ) + { + trans->TransformNormals(sourceNormals,newNormals); + } + + // Copy point data from source (if possible) + if ( pd ) + { + for (i=0; i < numSourcePts; i++) + { + outputPD->CopyData(pd,inPtId,ptIncr+i); + } + } + + // If point ids are to be generated, do it here + if ( this->GeneratePointIds ) + { + for (i=0; i < numSourcePts; i++) + { + pointIds->InsertNextValue(inPtId); + } + } + + ptIncr += numSourcePts; + } + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newScalars) + { + int idx = outputPD->AddArray(newScalars); + outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + if (newVectors) + { + outputPD->SetVectors(newVectors); + newVectors->Delete(); + } + + if (newNormals) + { + outputPD->SetNormals(newNormals); + newNormals->Delete(); + } + + if (newTCoords) + { + outputPD->SetTCoords(newTCoords); + newTCoords->Delete(); + } + + output->Squeeze(); + trans->Delete(); + pts->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +// Specify a source object at a specified table location. +void vtkGlyph3D::SetSourceConnection(int id, vtkAlgorithmOutput* algOutput) +{ + if (id < 0) + { + vtkErrorMacro("Bad index " << id << " for source."); + return; + } + + int numConnections = this->GetNumberOfInputConnections(1); + if (id < numConnections) + { + this->SetNthInputConnection(1, id, algOutput); + } + else if (id == numConnections && algOutput) + { + this->AddInputConnection(1, algOutput); + } + else if (algOutput) + { + vtkWarningMacro("The source id provided is larger than the maximum " + "source id, using " << numConnections << " instead."); + this->AddInputConnection(1, algOutput); + } +} + +//---------------------------------------------------------------------------- +// Specify a source object at a specified table location. +void vtkGlyph3D::SetSource(int id, vtkPolyData *pd) +{ + if (id < 0) + { + vtkErrorMacro("Bad index " << id << " for source."); + return; + } + + int numConnections = this->GetNumberOfInputConnections(1); + vtkAlgorithmOutput *algOutput = 0; + if (pd) + { + algOutput = pd->GetProducerPort(); + } + else + { + vtkErrorMacro("Cannot set NULL source."); + return; + } + + if (id < numConnections) + { + if (algOutput) + { + this->SetNthInputConnection(1, id, algOutput); + } + } + else if (id == numConnections && algOutput) + { + this->AddInputConnection(1, algOutput); + } +} + +//---------------------------------------------------------------------------- +// Get a pointer to a source object at a specified table location. +vtkPolyData *vtkGlyph3D::GetSource(int id) +{ + if ( id < 0 || id >= this->GetNumberOfInputConnections(1) ) + { + return NULL; + } + + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(1, id)); +} + +//---------------------------------------------------------------------------- +void vtkGlyph3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Generate Point Ids " + << (this->GeneratePointIds ? "On\n" : "Off\n"); + + os << indent << "PointIdsName: " << (this->PointIdsName ? this->PointIdsName + : "(none)") << "\n"; + + os << indent << "Color Mode: " << this->GetColorModeAsString() << endl; + + if ( this->GetNumberOfInputConnections(1) < 2 ) + { + if ( this->GetSource(0) != NULL ) + { + os << indent << "Source: (" << this->GetSource(0) << ")\n"; + } + else + { + os << indent << "Source: (none)\n"; + } + } + else + { + os << indent << "A table of " << this->GetNumberOfInputConnections(1) << " glyphs has been defined\n"; + } + + os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n"); + + os << indent << "Scale Mode: "; + if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ) + { + os << "Scale by scalar\n"; + } + else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) + { + os << "Scale by vector\n"; + } + else + { + os << "Data scaling is turned off\n"; + } + + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; + os << indent << "Clamping: " << (this->Clamping ? "On\n" : "Off\n"); + os << indent << "Range: (" << this->Range[0] << ", " << this->Range[1] << ")\n"; + os << indent << "Orient: " << (this->Orient ? "On\n" : "Off\n"); + os << indent << "Orient Mode: " << (this->VectorMode == VTK_USE_VECTOR ? + "Orient by vector\n" : "Orient by normal\n"); + os << indent << "Index Mode: "; + if ( this->IndexMode == VTK_INDEXING_BY_SCALAR ) + { + os << "Index by scalar value\n"; + } + else if ( this->IndexMode == VTK_INDEXING_BY_VECTOR ) + { + os << "Index by vector value\n"; + } + else + { + os << "Indexing off\n"; + } +} + +int vtkGlyph3D::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if (sourceInfo) + { + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + + return 1; +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkGlyph3D::GetSource(int idx, vtkInformationVector *sourceInfo) +{ + vtkInformation *info = sourceInfo->GetInformationObject(idx); + if (!info) + { + return NULL; + } + return vtkPolyData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT())); +} + +//---------------------------------------------------------------------------- +int vtkGlyph3D::FillInputPortInformation(int port, vtkInformation *info) +{ + if (port == 0) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; + } + else if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; + } + return 0; +} diff --git a/Graphics/vtkGlyph3D.h b/Graphics/vtkGlyph3D.h new file mode 100644 index 0000000..6d5d8cd --- /dev/null +++ b/Graphics/vtkGlyph3D.h @@ -0,0 +1,328 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGlyph3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGlyph3D - copy oriented and scaled glyph geometry to every input point +// .SECTION Description +// vtkGlyph3D is a filter that copies a geometric representation (called +// a glyph) to every point in the input dataset. The glyph is defined with +// polygonal data from a source filter input. The glyph may be oriented +// along the input vectors or normals, and it may be scaled according to +// scalar data or vector magnitude. More than one glyph may be used by +// creating a table of source objects, each defining a different glyph. If a +// table of glyphs is defined, then the table can be indexed into by using +// either scalar value or vector magnitude. +// +// To use this object you'll have to provide an input dataset and a source +// to define the glyph. Then decide whether you want to scale the glyph and +// how to scale the glyph (using scalar value or vector magnitude). Next +// decide whether you want to orient the glyph, and whether to use the +// vector data or normal data to orient it. Finally, decide whether to use a +// table of glyphs, or just a single glyph. If you use a table of glyphs, +// you'll have to decide whether to index into it with scalar value or with +// vector magnitude. +// +// .SECTION Caveats +// The scaling of the glyphs is controlled by the ScaleFactor ivar multiplied +// by the scalar value at each point (if VTK_SCALE_BY_SCALAR is set), or +// multiplied by the vector magnitude (if VTK_SCALE_BY_VECTOR is set), +// Alternatively (if VTK_SCALE_BY_VECTORCOMPONENTS is set), the scaling +// may be specified for x,y,z using the vector components. The +// scale factor can be further controlled by enabling clamping using the +// Clamping ivar. If clamping is enabled, the scale is normalized by the +// Range ivar, and then multiplied by the scale factor. The normalization +// process includes clamping the scale value between (0,1). +// +// Typically this object operates on input data with scalar and/or vector +// data. However, scalar and/or vector aren't necessary, and it can be used +// to copy data from a single source to each point. In this case the scale +// factor can be used to uniformly scale the glyphs. +// +// The object uses "vector" data to scale glyphs, orient glyphs, and/or index +// into a table of glyphs. You can choose to use either the vector or normal +// data at each input point. Use the method SetVectorModeToUseVector() to use +// the vector input data, and SetVectorModeToUseNormal() to use the +// normal input data. +// +// If you do use a table of glyphs, make sure to set the Range ivar to make +// sure the index into the glyph table is computed correctly. +// +// You can turn off scaling of the glyphs completely by using the Scaling +// ivar. You can also turn off scaling due to data (either vector or scalar) +// by using the SetScaleModeToDataScalingOff() method. +// +// You can set what arrays to use for the scalars, vectors, normals, and +// color scalars by using the SetInputArrayToProcess methods in +// vtkAlgorithm. The first array is scalars, the next vectors, the next +// normals and finally color scalars. + +// .SECTION See Also +// vtkTensorGlyph + +#ifndef __vtkGlyph3D_h +#define __vtkGlyph3D_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_SCALE_BY_SCALAR 0 +#define VTK_SCALE_BY_VECTOR 1 +#define VTK_SCALE_BY_VECTORCOMPONENTS 2 +#define VTK_DATA_SCALING_OFF 3 + +#define VTK_COLOR_BY_SCALE 0 +#define VTK_COLOR_BY_SCALAR 1 +#define VTK_COLOR_BY_VECTOR 2 + +#define VTK_USE_VECTOR 0 +#define VTK_USE_NORMAL 1 +#define VTK_VECTOR_ROTATION_OFF 2 + +#define VTK_INDEXING_OFF 0 +#define VTK_INDEXING_BY_SCALAR 1 +#define VTK_INDEXING_BY_VECTOR 2 + +class VTK_GRAPHICS_EXPORT vtkGlyph3D : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGlyph3D,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct object with scaling on, scaling mode is by scalar value, + // scale factor = 1.0, the range is (0,1), orient geometry is on, and + // orientation is by vector. Clamping and indexing are turned off. No + // initial sources are defined. + static vtkGlyph3D *New(); + + // Description: + // Set the source to use for he glyph. Old style. See SetSourceConnection. + void SetSource(vtkPolyData *pd) {this->SetSource(0,pd);}; + + // Description: + // Specify a source object at a specified table location. + // Old style. See SetSourceConnection. + void SetSource(int id, vtkPolyData *pd); + + // Description: + // Specify a source object at a specified table location. New style. + // Source connection is stored in port 1. This method is equivalent + // to SetInputConnection(1, id, outputPort). + void SetSourceConnection(int id, vtkAlgorithmOutput* algOutput); + void SetSourceConnection(vtkAlgorithmOutput* algOutput) + { + this->SetSourceConnection(0, algOutput); + } + + // Description: + // Get a pointer to a source object at a specified table location. + vtkPolyData *GetSource(int id=0); + + // Description: + // Turn on/off scaling of source geometry. + vtkSetMacro(Scaling,int); + vtkBooleanMacro(Scaling,int); + vtkGetMacro(Scaling,int); + + // Description: + // Either scale by scalar or by vector/normal magnitude. + vtkSetMacro(ScaleMode,int); + vtkGetMacro(ScaleMode,int); + void SetScaleModeToScaleByScalar() + {this->SetScaleMode(VTK_SCALE_BY_SCALAR);}; + void SetScaleModeToScaleByVector() + {this->SetScaleMode(VTK_SCALE_BY_VECTOR);}; + void SetScaleModeToScaleByVectorComponents() + {this->SetScaleMode(VTK_SCALE_BY_VECTORCOMPONENTS);}; + void SetScaleModeToDataScalingOff() + {this->SetScaleMode(VTK_DATA_SCALING_OFF);}; + const char *GetScaleModeAsString(); + + // Description: + // Either color by scale, scalar or by vector/normal magnitude. + vtkSetMacro(ColorMode,int); + vtkGetMacro(ColorMode,int); + void SetColorModeToColorByScale() + {this->SetColorMode(VTK_COLOR_BY_SCALE);}; + void SetColorModeToColorByScalar() + {this->SetColorMode(VTK_COLOR_BY_SCALAR);}; + void SetColorModeToColorByVector() + {this->SetColorMode(VTK_COLOR_BY_VECTOR);}; + const char *GetColorModeAsString(); + + // Description: + // Specify scale factor to scale object by. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Specify range to map scalar values into. + vtkSetVector2Macro(Range,double); + vtkGetVectorMacro(Range,double,2); + + // Description: + // Turn on/off orienting of input geometry along vector/normal. + vtkSetMacro(Orient,int); + vtkBooleanMacro(Orient,int); + vtkGetMacro(Orient,int); + + // Description: + // Turn on/off clamping of "scalar" values to range. (Scalar value may be + // vector magnitude if ScaleByVector() is enabled.) + vtkSetMacro(Clamping,int); + vtkBooleanMacro(Clamping,int); + vtkGetMacro(Clamping,int); + + // Description: + // Specify whether to use vector or normal to perform vector operations. + vtkSetMacro(VectorMode,int); + vtkGetMacro(VectorMode,int); + void SetVectorModeToUseVector() {this->SetVectorMode(VTK_USE_VECTOR);}; + void SetVectorModeToUseNormal() {this->SetVectorMode(VTK_USE_NORMAL);}; + void SetVectorModeToVectorRotationOff() + {this->SetVectorMode(VTK_VECTOR_ROTATION_OFF);}; + const char *GetVectorModeAsString(); + + // Description: + // Index into table of sources by scalar, by vector/normal magnitude, or + // no indexing. If indexing is turned off, then the first source glyph in + // the table of glyphs is used. Note that indexing mode will only use the + // InputScalarsSelection array and not the InputColorScalarsSelection + // as the scalar source if an array is specified. + vtkSetMacro(IndexMode,int); + vtkGetMacro(IndexMode,int); + void SetIndexModeToScalar() {this->SetIndexMode(VTK_INDEXING_BY_SCALAR);}; + void SetIndexModeToVector() {this->SetIndexMode(VTK_INDEXING_BY_VECTOR);}; + void SetIndexModeToOff() {this->SetIndexMode(VTK_INDEXING_OFF);}; + const char *GetIndexModeAsString(); + + // Description: + // Enable/disable the generation of point ids as part of the output. The + // point ids are the id of the input generating point. The point ids are + // stored in the output point field data and named "InputPointIds". Point + // generation is useful for debugging and pick operations. + vtkSetMacro(GeneratePointIds,int); + vtkGetMacro(GeneratePointIds,int); + vtkBooleanMacro(GeneratePointIds,int); + + // Description: + // Set/Get the name of the PointIds array if generated. By default the Ids + // are named "InputPointIds", but this can be changed with this function. + vtkSetStringMacro(PointIdsName); + vtkGetStringMacro(PointIdsName); + + // Description: + // This can be overwritten by subclass to return 0 when a point is + // blanked. Default implementation is to always return 1; + virtual int IsPointVisible(vtkDataSet*, vtkIdType) {return 1;}; + +protected: + vtkGlyph3D(); + ~vtkGlyph3D(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int, vtkInformation *); + + vtkPolyData* GetSource(int idx, vtkInformationVector *sourceInfo); + + vtkPolyData **Source; // Geometry to copy to each point + int Scaling; // Determine whether scaling of geometry is performed + int ScaleMode; // Scale by scalar value or vector magnitude + int ColorMode; // new scalars based on scale, scalar or vector + double ScaleFactor; // Scale factor to use to scale geometry + double Range[2]; // Range to use to perform scalar scaling + int Orient; // boolean controls whether to "orient" data + int VectorMode; // Orient/scale via normal or via vector data + int Clamping; // whether to clamp scale factor + int IndexMode; // what to use to index into glyph table + int GeneratePointIds; // produce input points ids for each output point + char *PointIdsName; + +private: + vtkGlyph3D(const vtkGlyph3D&); // Not implemented. + void operator=(const vtkGlyph3D&); // Not implemented. +}; + +// Description: +// Return the method of scaling as a descriptive character string. +inline const char *vtkGlyph3D::GetScaleModeAsString(void) +{ + if ( this->ScaleMode == VTK_SCALE_BY_SCALAR ) + { + return "ScaleByScalar"; + } + else if ( this->ScaleMode == VTK_SCALE_BY_VECTOR ) + { + return "ScaleByVector"; + } + else + { + return "DataScalingOff"; + } +} + +// Description: +// Return the method of coloring as a descriptive character string. +inline const char *vtkGlyph3D::GetColorModeAsString(void) +{ + if ( this->ColorMode == VTK_COLOR_BY_SCALAR ) + { + return "ColorByScalar"; + } + else if ( this->ColorMode == VTK_COLOR_BY_VECTOR ) + { + return "ColorByVector"; + } + else + { + return "ColorByScale"; + } +} + +// Description: +// Return the vector mode as a character string. +inline const char *vtkGlyph3D::GetVectorModeAsString(void) +{ + if ( this->VectorMode == VTK_USE_VECTOR) + { + return "UseVector"; + } + else if ( this->VectorMode == VTK_USE_NORMAL) + { + return "UseNormal"; + } + else + { + return "VectorRotationOff"; + } +} + +// Description: +// Return the index mode as a character string. +inline const char *vtkGlyph3D::GetIndexModeAsString(void) +{ + if ( this->IndexMode == VTK_INDEXING_OFF) + { + return "IndexingOff"; + } + else if ( this->IndexMode == VTK_INDEXING_BY_SCALAR) + { + return "IndexingByScalar"; + } + else + { + return "IndexingByVector"; + } +} + +#endif diff --git a/Graphics/vtkGlyphSource2D.cxx b/Graphics/vtkGlyphSource2D.cxx new file mode 100644 index 0000000..56abcd4 --- /dev/null +++ b/Graphics/vtkGlyphSource2D.cxx @@ -0,0 +1,572 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGlyphSource2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGlyphSource2D.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkGlyphSource2D, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkGlyphSource2D); + +//---------------------------------------------------------------------------- +vtkGlyphSource2D::vtkGlyphSource2D() +{ + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; + this->Scale = 1.0; + this->Scale2 = 1.5; + this->Color[0] = 1.0; + this->Color[1] = 1.0; + this->Color[2] = 1.0; + this->Filled = 1; + this->Cross = 0; + this->Dash = 0; + this->RotationAngle = 0.0; + this->GlyphType = VTK_VERTEX_GLYPH; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +int vtkGlyphSource2D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + //Allocate storage + vtkPoints *pts = vtkPoints::New(); + pts->Allocate(6,6); + vtkCellArray *verts = vtkCellArray::New(); + verts->Allocate(verts->EstimateSize(1,1),1); + vtkCellArray *lines = vtkCellArray::New(); + lines->Allocate(lines->EstimateSize(4,2),2); + vtkCellArray *polys = vtkCellArray::New(); + polys->Allocate(polys->EstimateSize(1,4),4); + vtkUnsignedCharArray *colors = vtkUnsignedCharArray::New(); + colors->SetNumberOfComponents(3); + colors->Allocate(2,2); + + this->ConvertColor(); + + //Special options + if ( this->Dash ) + { + int filled = this->Filled; + this->Filled = 0; + this->CreateDash(pts,lines,polys,colors,this->Scale2); + this->Filled = filled; + } + if ( this->Cross ) + { + int filled = this->Filled; + this->Filled = 0; + this->CreateCross(pts,lines,polys,colors,this->Scale2); + this->Filled = filled; + } + + //Call the right function + switch (this->GlyphType) + { + case VTK_NO_GLYPH: + break; + case VTK_VERTEX_GLYPH: + this->CreateVertex(pts,verts,colors); + break; + case VTK_DASH_GLYPH: + this->CreateDash(pts,lines,polys,colors,this->Scale); + break; + case VTK_CROSS_GLYPH: + this->CreateCross(pts,lines,polys,colors,this->Scale); + break; + case VTK_THICKCROSS_GLYPH: + this->CreateThickCross(pts,lines,polys,colors); + break; + case VTK_TRIANGLE_GLYPH: + this->CreateTriangle(pts,lines,polys,colors); + break; + case VTK_SQUARE_GLYPH: + this->CreateSquare(pts,lines,polys,colors); + break; + case VTK_CIRCLE_GLYPH: + this->CreateCircle(pts,lines,polys,colors); + break; + case VTK_DIAMOND_GLYPH: + this->CreateDiamond(pts,lines,polys,colors); + break; + case VTK_ARROW_GLYPH: + this->CreateArrow(pts,lines,polys,colors); + break; + case VTK_THICKARROW_GLYPH: + this->CreateThickArrow(pts,lines,polys,colors); + break; + case VTK_HOOKEDARROW_GLYPH: + this->CreateHookedArrow(pts,lines,polys,colors); + break; + } + + this->TransformGlyph(pts); + + //Clean up + output->SetPoints(pts); + pts->Delete(); + + output->SetVerts(verts); + verts->Delete(); + + output->SetLines(lines); + lines->Delete(); + + output->SetPolys(polys); + polys->Delete(); + + output->GetCellData()->SetScalars(colors); + colors->Delete(); + + return 1; +} + +void vtkGlyphSource2D::ConvertColor() +{ + this->RGB[0] = (unsigned char) (255.0 * this->Color[0]); + this->RGB[1] = (unsigned char) (255.0 * this->Color[1]); + this->RGB[2] = (unsigned char) (255.0 * this->Color[2]); +} + +void vtkGlyphSource2D::TransformGlyph(vtkPoints *pts) +{ + double x[3]; + int i; + int numPts=pts->GetNumberOfPoints(); + + if ( this->RotationAngle == 0.0 ) + { + for (i=0; iGetPoint(i,x); + x[0] = this->Center[0] + this->Scale * x[0]; + x[1] = this->Center[1] + this->Scale * x[1]; + pts->SetPoint(i,x); + } + } + else + { + double angle = this->RotationAngle * vtkMath::DegreesToRadians(); + double xt; + for (i=0; iGetPoint(i,x); + xt = x[0]*cos(angle) - x[1]*sin(angle); + x[1] = x[0]*sin(angle) + x[1]*cos(angle); + x[0] = xt; + x[0] = this->Center[0] + this->Scale * x[0]; + x[1] = this->Center[1] + this->Scale * x[1]; + pts->SetPoint(i,x); + } + } +} + +void vtkGlyphSource2D::CreateVertex(vtkPoints *pts, vtkCellArray *verts, + vtkUnsignedCharArray *colors) +{ + vtkIdType ptIds[1]; + ptIds[0] = pts->InsertNextPoint(0.0,0.0,0.0); + verts->InsertNextCell(1,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); +} + +void vtkGlyphSource2D::CreateCross(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors, + double scale) +{ + vtkIdType ptIds[4]; + + if ( this->Filled ) + { + this->CreateThickCross(pts,lines,polys,colors); + } + else + { + ptIds[0] = pts->InsertNextPoint(-0.5*scale, 0.0, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5*scale, 0.0, 0.0); + lines->InsertNextCell(2,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + ptIds[0] = pts->InsertNextPoint(0.0, -0.5*scale, 0.0); + ptIds[1] = pts->InsertNextPoint(0.0, 0.5*scale, 0.0); + lines->InsertNextCell(2,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } +} + +void vtkGlyphSource2D::CreateThickCross(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + if ( this->Filled ) + { + vtkIdType ptIds[4]; + ptIds[0] = pts->InsertNextPoint(-0.5, -0.1, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, -0.1, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.5, 0.1, 0.0); + ptIds[3] = pts->InsertNextPoint(-0.5, 0.1, 0.0); + polys->InsertNextCell(4,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + ptIds[0] = pts->InsertNextPoint(-0.1, -0.5, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.1, -0.5, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.1, 0.5, 0.0); + ptIds[3] = pts->InsertNextPoint(-0.1, 0.5, 0.0); + polys->InsertNextCell(4,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } + else + { + vtkIdType ptIds[13]; + ptIds[0] = pts->InsertNextPoint(-0.5, -0.1, 0.0); + ptIds[1] = pts->InsertNextPoint(-0.1, -0.1, 0.0); + ptIds[2] = pts->InsertNextPoint(-0.1, -0.5, 0.0); + ptIds[3] = pts->InsertNextPoint( 0.1, -0.5, 0.0); + ptIds[4] = pts->InsertNextPoint( 0.1, -0.1, 0.0); + ptIds[5] = pts->InsertNextPoint( 0.5, -0.1, 0.0); + ptIds[6] = pts->InsertNextPoint( 0.5, 0.1, 0.0); + ptIds[7] = pts->InsertNextPoint( 0.1, 0.1, 0.0); + ptIds[8] = pts->InsertNextPoint( 0.1, 0.5, 0.0); + ptIds[9] = pts->InsertNextPoint(-0.1, 0.5, 0.0); + ptIds[10] = pts->InsertNextPoint(-0.1, 0.1, 0.0); + ptIds[11] = pts->InsertNextPoint(-0.5, 0.1, 0.0); + ptIds[12] = ptIds[0]; + lines->InsertNextCell(13,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } +} + +void vtkGlyphSource2D::CreateTriangle(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + vtkIdType ptIds[4]; + + ptIds[0] = pts->InsertNextPoint(-0.375, -0.25, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.0, 0.5, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.375, -0.25, 0.0); + + if ( this->Filled ) + { + polys->InsertNextCell(3,ptIds); + } + else + { + ptIds[3] = ptIds[0]; + lines->InsertNextCell(4,ptIds); + } + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); +} + +void vtkGlyphSource2D::CreateSquare(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + vtkIdType ptIds[5]; + + ptIds[0] = pts->InsertNextPoint(-0.5, -0.5, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, -0.5, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.5, 0.5, 0.0); + ptIds[3] = pts->InsertNextPoint(-0.5, 0.5, 0.0); + + if ( this->Filled ) + { + polys->InsertNextCell(4,ptIds); + } + else + { + ptIds[4] = ptIds[0]; + lines->InsertNextCell(5,ptIds); + } + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); +} + +void vtkGlyphSource2D::CreateCircle(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + vtkIdType ptIds[9]; + double x[3], theta; + + // generate eight points in a circle + x[2] = 0.0; + theta = 2.0 * vtkMath::Pi() / 8.0; + for (int i=0; i<8; i++) + { + x[0] = 0.5 * cos((double)i*theta); + x[1] = 0.5 * sin((double)i*theta); + ptIds[i] = pts->InsertNextPoint(x); + } + + if ( this->Filled ) + { + polys->InsertNextCell(8,ptIds); + } + else + { + ptIds[8] = ptIds[0]; + lines->InsertNextCell(9,ptIds); + } + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); +} + +void vtkGlyphSource2D::CreateDiamond(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + vtkIdType ptIds[5]; + + ptIds[0] = pts->InsertNextPoint( 0.0, -0.5, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, 0.0, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.0, 0.5, 0.0); + ptIds[3] = pts->InsertNextPoint(-0.5, 0.0, 0.0); + + if ( this->Filled ) + { + polys->InsertNextCell(4,ptIds); + } + else + { + ptIds[4] = ptIds[0]; + lines->InsertNextCell(5,ptIds); + } + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); +} + +void vtkGlyphSource2D::CreateArrow(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + if ( this->Filled ) //create two convex polygons + { + this->CreateThickArrow(pts,lines,polys,colors); + } + else + { + //stem + vtkIdType ptIds[3]; + ptIds[0] = pts->InsertNextPoint( -0.5, 0.0, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, 0.0, 0.0); + lines->InsertNextCell(2,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + + //arrow head + ptIds[0] = pts->InsertNextPoint( 0.2, -0.1, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, 0.0, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.2, 0.1, 0.0); + lines->InsertNextCell(3,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } +} + +void vtkGlyphSource2D::CreateThickArrow(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + vtkIdType ptIds[8]; + + ptIds[0] = pts->InsertNextPoint( -0.5, -0.1, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.1, -0.1, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.1, -0.2, 0.0); + ptIds[3] = pts->InsertNextPoint( 0.5, 0.0, 0.0); + ptIds[4] = pts->InsertNextPoint( 0.1, 0.2, 0.0); + ptIds[5] = pts->InsertNextPoint( 0.1, 0.1, 0.0); + ptIds[6] = pts->InsertNextPoint( -0.5, 0.1, 0.0); + + if ( this->Filled ) //create two convex polygons + { + polys->InsertNextCell(4); + polys->InsertCellPoint(ptIds[0]); + polys->InsertCellPoint(ptIds[1]); + polys->InsertCellPoint(ptIds[5]); + polys->InsertCellPoint(ptIds[6]); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + + polys->InsertNextCell(5,ptIds+1); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } + else + { + ptIds[7] = ptIds[0]; + lines->InsertNextCell(8,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } +} + +void vtkGlyphSource2D::CreateHookedArrow(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors) +{ + if ( this->Filled ) + { + //create two convex polygons + vtkIdType ptIds[4]; + ptIds[0] = pts->InsertNextPoint( -0.5, -0.1, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.1, -0.1, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.1, 0.075, 0.0); + ptIds[3] = pts->InsertNextPoint( -0.5, 0.075, 0.0); + polys->InsertNextCell(4,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + + ptIds[0] = pts->InsertNextPoint( 0.1, -0.1, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, -0.1, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.1, 0.2, 0.0); + polys->InsertNextCell(3,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } + else + { + vtkIdType ptIds[3]; + ptIds[0] = pts->InsertNextPoint( -0.5, 0.0, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, 0.0, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.2, 0.1, 0.0); + lines->InsertNextCell(3,ptIds); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + } +} + +void vtkGlyphSource2D::CreateDash(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors, + double scale) +{ + vtkIdType ptIds[5]; + ptIds[0] = pts->InsertNextPoint(-0.5, -0.1, 0.0); + ptIds[1] = pts->InsertNextPoint( 0.5, -0.1, 0.0); + ptIds[2] = pts->InsertNextPoint( 0.5, 0.1, 0.0); + ptIds[3] = pts->InsertNextPoint(-0.5, 0.1, 0.0); + + if ( this->Filled ) + { + polys->InsertNextCell(4,ptIds); + } + else + { + vtkIdType ptIds2D[2]; + ptIds2D[0] = pts->InsertNextPoint(-0.5*scale, 0.0, 0.0); + ptIds2D[1] = pts->InsertNextPoint( 0.5*scale, 0.0, 0.0); + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); + lines->InsertNextCell(2,ptIds2D); + } + colors->InsertNextValue(this->RGB[0]); + colors->InsertNextValue(this->RGB[1]); + colors->InsertNextValue(this->RGB[2]); +} + +//---------------------------------------------------------------------------- +void vtkGlyphSource2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << ")\n"; + + os << indent << "Scale: " << this->Scale << "\n"; + os << indent << "Scale2: " << this->Scale2 << "\n"; + os << indent << "Rotation Angle: " << this->RotationAngle << "\n"; + + os << indent << "Color: (" << this->Color[0] << ", " + << this->Color[1] << ", " << this->Color[2] << ")\n"; + + os << indent << "Filled: " << (this->Filled ? "On\n" : "Off\n"); + os << indent << "Dash: " << (this->Dash ? "On\n" : "Off\n"); + os << indent << "Cross: " << (this->Cross ? "On\n" : "Off\n"); + + os << indent << "Glyph Type"; + switch (this->GlyphType) + { + case VTK_NO_GLYPH: + os << "No Glyph\n"; + break; + case VTK_VERTEX_GLYPH: + os << "Vertex\n"; + break; + case VTK_DASH_GLYPH: + os << "Dash\n"; + break; + case VTK_CROSS_GLYPH: + os << "Cross\n"; + break; + case VTK_THICKCROSS_GLYPH: + os << "Cross\n"; + break; + case VTK_TRIANGLE_GLYPH: + os << "Triangle\n"; + break; + case VTK_SQUARE_GLYPH: + os << "Square\n"; + break; + case VTK_CIRCLE_GLYPH: + os << "Circle\n"; + break; + case VTK_DIAMOND_GLYPH: + os << "Diamond\n"; + break; + case VTK_ARROW_GLYPH: + os << "Arrow\n"; + break; + case VTK_THICKARROW_GLYPH: + os << "Arrow\n"; + break; + case VTK_HOOKEDARROW_GLYPH: + os << "Hooked Arrow\n"; + break; + } +} diff --git a/Graphics/vtkGlyphSource2D.h b/Graphics/vtkGlyphSource2D.h new file mode 100644 index 0000000..fb7f77e --- /dev/null +++ b/Graphics/vtkGlyphSource2D.h @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGlyphSource2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGlyphSource2D - create 2D glyphs represented by vtkPolyData +// .SECTION Description +// vtkGlyphSource2D can generate a family of 2D glyphs each of which lies +// in the x-y plane (i.e., the z-coordinate is zero). The class is a helper +// class to be used with vtkGlyph2D and vtkXYPlotActor. +// +// To use this class, specify the glyph type to use and its +// attributes. Attributes include its position (i.e., center point), scale, +// color, and whether the symbol is filled or not (a polygon or closed line +// sequence). You can also put a short line through the glyph running from -x +// to +x (the glyph looks like it's on a line), or a cross. + +#ifndef __vtkGlyphSource2D_h +#define __vtkGlyphSource2D_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_NO_GLYPH 0 +#define VTK_VERTEX_GLYPH 1 +#define VTK_DASH_GLYPH 2 +#define VTK_CROSS_GLYPH 3 +#define VTK_THICKCROSS_GLYPH 4 +#define VTK_TRIANGLE_GLYPH 5 +#define VTK_SQUARE_GLYPH 6 +#define VTK_CIRCLE_GLYPH 7 +#define VTK_DIAMOND_GLYPH 8 +#define VTK_ARROW_GLYPH 9 +#define VTK_THICKARROW_GLYPH 10 +#define VTK_HOOKEDARROW_GLYPH 11 + +class vtkPoints; +class vtkUnsignedCharArray; +class vtkCellArray; + +class VTK_GRAPHICS_EXPORT vtkGlyphSource2D : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGlyphSource2D,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct a vertex glyph centered at the origin, scale 1.0, white in + // color, filled, with line segment passing through the point. + static vtkGlyphSource2D *New(); + + // Description: + // Set the center of the glyph. By default the center is (0,0,0). + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set the scale of the glyph. Note that the glyphs are designed + // to fit in the (1,1) rectangle. + vtkSetClampMacro(Scale,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Scale,double); + + // Description: + // Set the scale of optional portions of the glyph (e.g., the + // dash and cross is DashOn() and CrossOn()). + vtkSetClampMacro(Scale2,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Scale2,double); + + // Description: + // Set the color of the glyph. The default color is white. + vtkSetVector3Macro(Color,double); + vtkGetVectorMacro(Color,double,3); + + // Description: + // Specify whether the glyph is filled (a polygon) or not (a + // closed polygon defined by line segments). This only applies + // to 2D closed glyphs. + vtkSetMacro(Filled,int); + vtkGetMacro(Filled,int); + vtkBooleanMacro(Filled,int); + + // Description: + // Specify whether a short line segment is drawn through the + // glyph. (This is in addition to the glyph. If the glyph type + // is set to "Dash" there is no need to enable this flag.) + vtkSetMacro(Dash,int); + vtkGetMacro(Dash,int); + vtkBooleanMacro(Dash,int); + + // Description: + // Specify whether a cross is drawn as part of the glyph. (This + // is in addition to the glyph. If the glyph type is set to + // "Cross" there is no need to enable this flag.) + vtkSetMacro(Cross,int); + vtkGetMacro(Cross,int); + vtkBooleanMacro(Cross,int); + + // Description: + // Specify an angle (in degrees) to rotate the glyph around + // the z-axis. Using this ivar, it is possible to generate + // rotated glyphs (e.g., crosses, arrows, etc.) + vtkSetMacro(RotationAngle,double); + vtkGetMacro(RotationAngle,double); + + // Description: + // Specify the type of glyph to generate. + vtkSetClampMacro(GlyphType,int,VTK_NO_GLYPH,VTK_HOOKEDARROW_GLYPH); + vtkGetMacro(GlyphType,int); + void SetGlyphTypeToNone() {this->SetGlyphType(VTK_NO_GLYPH);} + void SetGlyphTypeToVertex() {this->SetGlyphType(VTK_VERTEX_GLYPH);} + void SetGlyphTypeToDash() {this->SetGlyphType(VTK_DASH_GLYPH);} + void SetGlyphTypeToCross() {this->SetGlyphType(VTK_CROSS_GLYPH);} + void SetGlyphTypeToThickCross() {this->SetGlyphType(VTK_THICKCROSS_GLYPH);} + void SetGlyphTypeToTriangle() {this->SetGlyphType(VTK_TRIANGLE_GLYPH);} + void SetGlyphTypeToSquare() {this->SetGlyphType(VTK_SQUARE_GLYPH);} + void SetGlyphTypeToCircle() {this->SetGlyphType(VTK_CIRCLE_GLYPH);} + void SetGlyphTypeToDiamond() {this->SetGlyphType(VTK_DIAMOND_GLYPH);} + void SetGlyphTypeToArrow() {this->SetGlyphType(VTK_ARROW_GLYPH);} + void SetGlyphTypeToThickArrow() {this->SetGlyphType(VTK_THICKARROW_GLYPH);} + void SetGlyphTypeToHookedArrow() {this->SetGlyphType(VTK_HOOKEDARROW_GLYPH);} + +protected: + vtkGlyphSource2D(); + ~vtkGlyphSource2D() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Center[3]; + double Scale; + double Scale2; + double Color[3]; + int Filled; + int Dash; + int Cross; + int GlyphType; + double RotationAngle; + + void TransformGlyph(vtkPoints *pts); + void ConvertColor(); + unsigned char RGB[3]; + + void CreateVertex(vtkPoints *pts, vtkCellArray *verts, + vtkUnsignedCharArray *colors); + void CreateDash(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors, double scale); + void CreateCross(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors, double scale); + void CreateThickCross(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + void CreateTriangle(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + void CreateSquare(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + void CreateCircle(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + void CreateDiamond(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + void CreateArrow(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + void CreateThickArrow(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + void CreateHookedArrow(vtkPoints *pts, vtkCellArray *lines, + vtkCellArray *polys, vtkUnsignedCharArray *colors); + +private: + vtkGlyphSource2D(const vtkGlyphSource2D&); // Not implemented. + void operator=(const vtkGlyphSource2D&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkGraphLayoutFilter.cxx b/Graphics/vtkGraphLayoutFilter.cxx new file mode 100644 index 0000000..bcfaea0 --- /dev/null +++ b/Graphics/vtkGraphLayoutFilter.cxx @@ -0,0 +1,298 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGraphLayoutFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGraphLayoutFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkGraphLayoutFilter, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkGraphLayoutFilter); + +vtkGraphLayoutFilter::vtkGraphLayoutFilter() +{ + this->GraphBounds[0] = this->GraphBounds[2] = this->GraphBounds[4] = -0.5; + this->GraphBounds[1] = this->GraphBounds[3] = this->GraphBounds[5] = 0.5; + this->MaxNumberOfIterations = 50; + this->CoolDownRate = 10.0; + this->AutomaticBoundsComputation = 1; + this->ThreeDimensionalLayout = 1; +} + +// A vertex contains a position and a displacement. +typedef struct _vtkLayoutVertex +{ + double x[3]; + double d[3]; +} vtkLayoutVertex; + +// An edge consists of two vertices joined together. +// This struct acts as a "pointer" to those two vertices. +typedef struct _vtkLayoutEdge +{ + int t; + int u; +} vtkLayoutEdge; + +// Cool-down function. +static inline double CoolDown(double t, double r) +{ + return t-(t/r); +} + +static inline double forceAttract(double x, double k) +{ + return (x * x) / k; +} + +static inline double forceRepulse(double x, double k) +{ + if (x != 0.0) + { + return k * k / x; + } + else + { + return VTK_DOUBLE_MAX; + } +} + +int vtkGraphLayoutFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *pts = input->GetPoints(); + vtkCellArray *lines = input->GetLines(); + int numLines = lines->GetNumberOfCells(); //Number of lines/edges. + int numPts = input->GetNumberOfPoints(); //Number of points/vertices. + double diff[3], len; //The difference vector. + int i, j, l; //Iteration variables. + vtkIdType npts = 0; + vtkIdType *cellPts = 0; + double fa, fr, minimum; + + vtkDebugMacro(<<"Drawing graph"); + + if ( numPts <= 0 || numLines <= 0) + { + vtkErrorMacro(<<"No input"); + return 1; + } + + // Generate bounds automatically if necessary. It's the same + // as the input bounds. + if ( this->AutomaticBoundsComputation ) + { + pts->GetBounds(this->GraphBounds); + } + + for (i=0; i<3; i++) + { + if ( this->GraphBounds[2*i+1] <= this->GraphBounds[2*i] ) + { + this->GraphBounds[2*i+1] = this->GraphBounds[2*i] + 1; + } + } + + // Allocate memory for structures. Break polylines into line segments. + numLines=0; + for (i=0, lines->InitTraversal(); lines->GetNextCell(npts, cellPts); i++) + { + numLines += npts - 1; + } + + vtkLayoutVertex *v = new vtkLayoutVertex [numPts]; + vtkLayoutEdge *e = new vtkLayoutEdge [numLines]; + + // Get the points, either x,y,0 or x,y,z + for (i=0; iGetPoint(i,v[i].x); + if ( ! this->ThreeDimensionalLayout ) + { + v[i].x[2] = 0; + } + } + + // Get the edges + numLines=0; + for (i=0, lines->InitTraversal(); lines->GetNextCell(npts, cellPts); i++) + { + for (j=0; jGraphBounds[1] - this->GraphBounds[0]) * + (this->GraphBounds[3] - this->GraphBounds[2]) * + (this->GraphBounds[5] - this->GraphBounds[4]); + double temp = sqrt( (this->GraphBounds[1]-this->GraphBounds[0])* + (this->GraphBounds[1]-this->GraphBounds[0]) + + (this->GraphBounds[3]-this->GraphBounds[2])* + (this->GraphBounds[3]-this->GraphBounds[2]) + + (this->GraphBounds[5]-this->GraphBounds[4])* + (this->GraphBounds[5]-this->GraphBounds[4]) ); + // The optimal distance between vertices. + double k = pow((double)volume/numPts,0.33333); + + // Begin iterations. + double norm; + for(i=0; iMaxNumberOfIterations; i++) + { + // Calculate the repulsive forces. + for(j=0; jCoolDownRate); + } + + // Get the bounds of the graph and scale and translate to + // bring them within the bounds specified. + vtkPoints *newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + for (i=0; iSetPoint(i,v[i].x); + } + double bounds[6], sf[3], x[3], xNew[3]; + double center[3], graphCenter[3]; + newPts->GetBounds(bounds); + for (i=0; i<3; i++) + { + if ( (len=(bounds[2*i+1] - bounds[2*i])) == 0.0 ) + { + len = 1.0; + } + sf[i] = (this->GraphBounds[2*i+1] - this->GraphBounds[2*i]) / len; + center[i] = (bounds[2*i+1] + bounds[2*i])/2.0; + graphCenter[i] = (this->GraphBounds[2*i+1] + this->GraphBounds[2*i])/2.0; + } + + double scale = sf[0]; + scale = (scale < sf[1] ? scale : sf[1]); + scale = (scale < sf[2] ? scale : sf[2]); + + for (i=0; iGetPoint(i, x); + for (j=0; j<3; j++) + { + xNew[j] = graphCenter[j] + scale*(x[j]-center[j]); + } + newPts->SetPoint(i,xNew); + } + + // Send the data to output. + output->SetPoints(newPts); + output->SetLines(lines); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + // Clean up. + newPts->Delete(); + delete [] v; + delete [] e; + + return 1; +} + +void vtkGraphLayoutFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "AutomaticBoundsComputation: " + << (this->AutomaticBoundsComputation ? "On\n" : "Off\n"); + + os << indent << "GraphBounds: \n"; + os << indent << " Xmin,Xmax: (" << this->GraphBounds[0] << ", " + << this->GraphBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->GraphBounds[2] << ", " + << this->GraphBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->GraphBounds[4] << ", " + << this->GraphBounds[5] << ")\n"; + + os << indent << "MaxNumberOfIterations: " + << this->MaxNumberOfIterations << endl; + + os << indent << "CoolDownRate: " + << this->CoolDownRate << endl; + + os << indent << "Three Dimensional Layout: " + << (this->ThreeDimensionalLayout ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkGraphLayoutFilter.h b/Graphics/vtkGraphLayoutFilter.h new file mode 100644 index 0000000..916e84e --- /dev/null +++ b/Graphics/vtkGraphLayoutFilter.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGraphLayoutFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGraphLayoutFilter - nice layout of undirected graphs in 3D +// .SECTION Description +// vtkGraphLayoutFilter will reposition a network of nodes, connected by +// lines or polylines, into a more pleasing arrangement. The class +// implements a simple force-directed placement algorithm +// (Fruchterman & Reingold "Graph Drawing by Force-directed Placement" +// Software-Practice and Experience 21(11) 1991). +// +// The input to the filter is a vtkPolyData representing the undirected +// graphs. A graph is represented by a set of polylines and/or lines. +// The output is also a vtkPolyData, where the point positions have been +// modified. To use the filter, specify whether you wish the layout to +// occur in 2D or 3D; the bounds in which the graph should lie (note that you +// can just use automatic bounds computation); and modify the cool down +// rate (controls the final process of simulated annealing). + +#ifndef __vtkGraphLayoutFilter_h +#define __vtkGraphLayoutFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkGraphLayoutFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkGraphLayoutFilter *New(); + + vtkTypeRevisionMacro(vtkGraphLayoutFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / get the region in space in which to place the final graph. + // The GraphBounds only affects the results if AutomaticBoundsComputation + // is off. + vtkSetVector6Macro(GraphBounds,double); + vtkGetVectorMacro(GraphBounds,double,6); + + // Description: + // Turn on/off automatic graph bounds calculation. If this + // boolean is off, then the manually specified GraphBounds is used. + // If on, then the input's bounds us used as the graph bounds. + vtkSetMacro(AutomaticBoundsComputation, int); + vtkGetMacro(AutomaticBoundsComputation, int); + vtkBooleanMacro(AutomaticBoundsComputation, int); + + // Description: + // Set/Get the maximum number of iterations to be used. + // The higher this number, the more iterations through the algorithm + // is possible, and thus, the more the graph gets modified. + vtkSetClampMacro(MaxNumberOfIterations, int, 0, VTK_LARGE_INTEGER); + vtkGetMacro(MaxNumberOfIterations, int); + + // Description: + // Set/Get the Cool-down rate. + // The higher this number is, the longer it will take to "cool-down", + // and thus, the more the graph will be modified. + vtkSetClampMacro(CoolDownRate, double, 0.01, VTK_DOUBLE_MAX); + vtkGetMacro(CoolDownRate, double); + + // Turn on/off layout of graph in three dimensions. If off, graph + // layout occurs in two dimensions. By default, three dimensional + // layout is on. + vtkSetMacro(ThreeDimensionalLayout, int); + vtkGetMacro(ThreeDimensionalLayout, int); + vtkBooleanMacro(ThreeDimensionalLayout, int); + +protected: + vtkGraphLayoutFilter(); + ~vtkGraphLayoutFilter() {} + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double GraphBounds[6]; + int AutomaticBoundsComputation; //Boolean controls automatic bounds calc. + int MaxNumberOfIterations; //Maximum number of iterations. + double CoolDownRate; //Cool-down rate. Note: Higher # = Slower rate. + int ThreeDimensionalLayout; //Boolean for a third dimension. +private: + vtkGraphLayoutFilter(const vtkGraphLayoutFilter&); // Not implemented. + void operator=(const vtkGraphLayoutFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkGridSynchronizedTemplates3D.cxx b/Graphics/vtkGridSynchronizedTemplates3D.cxx new file mode 100644 index 0000000..685aa70 --- /dev/null +++ b/Graphics/vtkGridSynchronizedTemplates3D.cxx @@ -0,0 +1,963 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGridSynchronizedTemplates3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSynchronizedTemplates3D.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkExtentTranslator.h" +#include "vtkFloatArray.h" +#include "vtkGridSynchronizedTemplates3D.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include + +vtkCxxRevisionMacro(vtkGridSynchronizedTemplates3D, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkGridSynchronizedTemplates3D); + +//---------------------------------------------------------------------------- +// Description: +// Construct object with initial scalar range (0,1) and single contour value +// of 0.0. The ImageRange are set to extract the first k-plane. +vtkGridSynchronizedTemplates3D::vtkGridSynchronizedTemplates3D() +{ + this->ContourValues = vtkContourValues::New(); + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->ExecuteExtent[0] = this->ExecuteExtent[1] + = this->ExecuteExtent[2] = this->ExecuteExtent[3] + = this->ExecuteExtent[4] = this->ExecuteExtent[5] = 0; + + this->MinimumPieceSize[0] = 10; + this->MinimumPieceSize[1] = 10; + this->MinimumPieceSize[2] = 10; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//---------------------------------------------------------------------------- +vtkGridSynchronizedTemplates3D::~vtkGridSynchronizedTemplates3D() +{ + this->ContourValues->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkGridSynchronizedTemplates3D::SetInputMemoryLimit( + long vtkNotUsed(limit)) +{ + vtkErrorMacro( << "This filter no longer supports a memory limit." ); + vtkErrorMacro( << "This filter no longer initiates streaming." ); + vtkErrorMacro( << "Please use a .... after this filter to achieve similar functionality." ); +} + +//---------------------------------------------------------------------------- +// Description: +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkGridSynchronizedTemplates3D::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long mTime2=this->ContourValues->GetMTime(); + + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + return mTime; +} + +//---------------------------------------------------------------------------- +void vtkGridSynchronizedTemplates3DInitializeOutput(int *ext, + vtkStructuredGrid *input, + vtkPolyData *o, + vtkFloatArray *scalars, + vtkFloatArray *normals, + vtkFloatArray *gradients, + vtkDataArray *inScalars) +{ + vtkPoints *newPts; + vtkCellArray *newPolys; + long estimatedSize; + + estimatedSize = (int) pow ((double) + ((ext[1]-ext[0]+1)*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1)), .75); + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(estimatedSize,3)); + o->SetPoints(newPts); + newPts->Delete(); + o->SetPolys(newPolys); + newPolys->Delete(); + + o->GetPointData()->CopyAllOn(); + + // It is more efficient to just create the scalar array + // rather than redundantly interpolate the scalars. + if (input->GetPointData()->GetScalars() == inScalars) + { + o->GetPointData()->CopyScalarsOff(); + } + else + { + o->GetPointData()->CopyFieldOff(inScalars->GetName()); + } + + if (normals) + { + normals->SetNumberOfComponents(3); + normals->Allocate(3*estimatedSize,3*estimatedSize/2); + normals->SetName("Normals"); + } + if (gradients) + { + gradients->SetNumberOfComponents(3); + gradients->Allocate(3*estimatedSize,3*estimatedSize/2); + gradients->SetName("Gradients"); + } + if (scalars) + { + scalars->Allocate(estimatedSize,estimatedSize/2); + scalars->SetName("Scalars"); + } + + + // It is more efficient to just create the scalar array + o->GetPointData()->InterpolateAllocate(input->GetPointData(), + estimatedSize,estimatedSize/2); + o->GetCellData()->CopyAllocate(input->GetCellData(), + estimatedSize,estimatedSize/2); +} + +//---------------------------------------------------------------------------- +// Close to central differences for a grid as I could get. +// Given a linear gradient assumption find gradient that minimizes +// error squared for + and - (*3) neighbors). +template +void ComputeGridPointGradient(int i, int j, int k, int inExt[6], + int incY, int incZ, T *sc, PointsType* pt, + double g[3]) +{ + double N[6][3]; + double NtN[3][3], NtNi[3][3]; + double *NtN2[3], *NtNi2[3]; + double tmpDoubleArray[3]; + int tmpIntArray[3]; + double s[6], Nts[3], sum; + int count = 0; + T *s2; + PointsType *p2; + + if (i == 2 && k == 2) + { + count = 0; + } + + // x-direction + if (i > inExt[0]) + { + p2 = pt - 3; + s2 = sc - 1; + N[count][0] = p2[0] - pt[0]; + N[count][1] = p2[1] - pt[1]; + N[count][2] = p2[2] - pt[2]; + s[count] = (double)(*s2) - (double)(*sc); + ++count; + } + if (i < inExt[1]) + { + p2 = pt + 3; + s2 = sc + 1; + N[count][0] = p2[0] - pt[0]; + N[count][1] = p2[1] - pt[1]; + N[count][2] = p2[2] - pt[2]; + s[count] = (double)(*s2) - (double)(*sc); + ++count; + } + + // y-direction + if (j > inExt[2]) + { + p2 = pt - 3*incY; + s2 = sc - incY; + N[count][0] = p2[0] - pt[0]; + N[count][1] = p2[1] - pt[1]; + N[count][2] = p2[2] - pt[2]; + s[count] = (double)(*s2) - (double)(*sc); + ++count; + } + if (j < inExt[3]) + { + p2 = pt + 3*incY; + s2 = sc + incY; + N[count][0] = p2[0] - pt[0]; + N[count][1] = p2[1] - pt[1]; + N[count][2] = p2[2] - pt[2]; + s[count] = (double)(*s2) - (double)(*sc); + ++count; + } + + // z-direction + if (k > inExt[4]) + { + p2 = pt - 3*incZ; + s2 = sc - incZ; + N[count][0] = p2[0] - pt[0]; + N[count][1] = p2[1] - pt[1]; + N[count][2] = p2[2] - pt[2]; + s[count] = (double)(*s2) - (double)(*sc); + ++count; + } + if (k < inExt[5]) + { + p2 = pt + 3*incZ; + s2 = sc + incZ; + N[count][0] = p2[0] - pt[0]; + N[count][1] = p2[1] - pt[1]; + N[count][2] = p2[2] - pt[2]; + s[count] = (double)(*s2) - (double)(*sc); + ++count; + } + + // compute transpose(N)N. + // since this will be a symetric matrix, we could make the + // computation a little more efficient. + for (i = 0; i < 3; ++i) + { + for (j = 0; j < 3; ++j) + { + sum = 0.0; + for (k = 0; k < count; ++k) + { + sum += N[k][i] * N[k][j]; + } + NtN[i][j] = sum; + } + } + // compute the inverse of NtN + // We have to setup a double** for the invert matrix call (@#$%!&%$!) + NtN2[0] = &(NtN[0][0]); + NtN2[1] = &(NtN[1][0]); + NtN2[2] = &(NtN[2][0]); + NtNi2[0] = &(NtNi[0][0]); + NtNi2[1] = &(NtNi[1][0]); + NtNi2[2] = &(NtNi[2][0]); + if (vtkMath::InvertMatrix(NtN2, NtNi2, 3, tmpIntArray, tmpDoubleArray) == 0) + { + vtkGenericWarningMacro("Cannot compute gradient of grid"); + return; + } + + // compute transpose(N)s. + for (i = 0; i < 3; ++i) + { + sum = 0.0; + for (j = 0; j < count; ++j) + { + sum += N[j][i] * s[j]; + } + Nts[i] = sum; + } + + // now compute gradient + for (i = 0; i < 3; ++i) + { + sum = 0.0; + for (j = 0; j < 3; ++j) + { + sum += NtNi[j][i] * Nts[j]; + } + g[i] = sum; + } +} + +//---------------------------------------------------------------------------- +#define VTK_CSP3PA(i2,j2,k2,s,p, grad, norm) \ +if (NeedGradients) \ + { \ + if (!g0) \ + { \ + ComputeGridPointGradient(i, j, k, inExt, incY, incZ, s0, p0, n0); \ + g0 = 1; \ + } \ + ComputeGridPointGradient(i2, j2, k2, inExt, incY, incZ, s, p, n1); \ + for (jj=0; jj<3; jj++) \ + { \ + grad[jj] = n0[jj] + t * (n1[jj] - n0[jj]); \ + } \ + if (ComputeGradients) \ + { \ + newGradients->InsertNextTuple(grad); \ + } \ + if (ComputeNormals) \ + { \ + norm[0] = -grad[0]; norm[1] = -grad[1]; norm[2] = -grad[2]; \ + vtkMath::Normalize(norm); \ + newNormals->InsertNextTuple(norm); \ + } \ +} \ +if (ComputeScalars) \ +{ \ + newScalars->InsertNextTuple(&value); \ +} + +//---------------------------------------------------------------------------- +// Contouring filter specialized for images +template +void ContourGrid(vtkGridSynchronizedTemplates3D *self, + int *exExt, T *scalars, + vtkStructuredGrid *input, vtkPolyData *output, PointsType*, vtkDataArray *inScalars) +{ + int *inExt = input->GetExtent(); + int xdim = exExt[1] - exExt[0] + 1; + int ydim = exExt[3] - exExt[2] + 1; + double n0[3], n1[3]; // used in gradient macro + double *values = self->GetValues(); + int numContours = self->GetNumberOfContours(); + PointsType *inPtPtrX, *inPtPtrY, *inPtPtrZ; + PointsType *p0, *p1, *p2, *p3; + T *inPtrX, *inPtrY, *inPtrZ; + T *s0, *s1, *s2, *s3; + int XMin, XMax, YMin, YMax, ZMin, ZMax; + int incY, incZ; + PointsType* points = + static_cast(input->GetPoints()->GetData()->GetVoidPointer(0)); + double t; + int *isect1Ptr, *isect2Ptr; + vtkIdType ptIds[3]; + int *tablePtr; + int v0, v1, v2, v3; + int idx, vidx; + double value; + int i, j, k; + int zstep, yisectstep; + int offsets[12]; + int ComputeNormals = self->GetComputeNormals(); + int ComputeGradients = self->GetComputeGradients(); + int ComputeScalars = self->GetComputeScalars(); + int NeedGradients = ComputeGradients || ComputeNormals; + int jj, g0; + // We need to know the edgePointId's for interpolating attributes. + vtkIdType edgePtId, inCellId, outCellId; + vtkPointData *inPD = input->GetPointData(); + vtkCellData *inCD = input->GetCellData(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *outCD = output->GetCellData(); + // Temporary point data. + double x[3]; + double grad[3]; + double norm[3]; + // Used to be passed in as parameteters. + vtkCellArray *newPolys; + vtkPoints *newPts; + vtkFloatArray *newScalars = NULL; + vtkFloatArray *newNormals = NULL; + vtkFloatArray *newGradients = NULL; + + if (ComputeScalars) + { + newScalars = vtkFloatArray::New(); + } + if (ComputeNormals) + { + newNormals = vtkFloatArray::New(); + } + if (ComputeGradients) + { + newGradients = vtkFloatArray::New(); + } + vtkGridSynchronizedTemplates3DInitializeOutput(exExt, input, output, + newScalars, newNormals, newGradients, inScalars); + newPts = output->GetPoints(); + newPolys = output->GetPolys(); + + // this is an exploded execute extent. + XMin = exExt[0]; + XMax = exExt[1]; + YMin = exExt[2]; + YMax = exExt[3]; + ZMin = exExt[4]; + ZMax = exExt[5]; + // to skip over an x row of the input. + incY = inExt[1]-inExt[0]+1; + // to skip over an xy slice of the input. + incZ = (inExt[3]-inExt[2]+1)*incY; + + // Kens increments, probably to do with edge array + zstep = xdim*ydim; + yisectstep = xdim*3; + // compute offsets probably how to get to the edges in the edge array. + offsets[0] = -xdim*3; + offsets[1] = -xdim*3 + 1; + offsets[2] = -xdim*3 + 2; + offsets[3] = -xdim*3 + 4; + offsets[4] = -xdim*3 + 5; + offsets[5] = 0; + offsets[6] = 2; + offsets[7] = 5; + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + + // allocate storage array + int *isect1 = new int [xdim*ydim*3*2]; + // set impossible edges to -1 + for (i = 0; i < ydim; i++) + { + isect1[(i+1)*xdim*3-3] = -1; + isect1[(i+1)*xdim*3*2-3] = -1; + } + for (i = 0; i < xdim; i++) + { + isect1[((ydim-1)*xdim + i)*3 + 1] = -1; + isect1[((ydim-1)*xdim + i)*3*2 + 1] = -1; + } + + + //fprintf(stderr, "%d: -------- Extent %d, %d, %d, %d, %d, %d\n", threadId, + // exExt[0], exExt[1], exExt[2], exExt[3], exExt[4], exExt[5]); + + // for each contour + for (vidx = 0; vidx < numContours; vidx++) + { + value = values[vidx]; + // skip any slices which are overlap for computing gradients. + inPtPtrZ = points + 3*((ZMin - inExt[4]) * incZ + + (YMin - inExt[2]) * incY + + (XMin - inExt[0])); + inPtrZ = scalars + ((ZMin - inExt[4]) * incZ + + (YMin - inExt[2]) * incY + + (XMin - inExt[0])); + s2 = inPtrZ; + v2 = (*s2 < value ? 0 : 1); + + //================================================================== + for (k = ZMin; k <= ZMax; k++) + { + // swap the buffers + if (k%2) + { + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + isect1Ptr = isect1; + isect2Ptr = isect1 + xdim*ydim*3; + } + else + { + offsets[8] = (-zstep - xdim)*3; + offsets[9] = (-zstep - xdim)*3 + 1; + offsets[10] = (-zstep - xdim)*3 + 4; + offsets[11] = -zstep*3; + isect1Ptr = isect1 + xdim*ydim*3; + isect2Ptr = isect1; + } + + inPtPtrY = inPtPtrZ; + inPtrY = inPtrZ; + for (j = YMin; j <= YMax; j++) + { + // Should not impact perfomance here/ + edgePtId = (j-inExt[2])*incY + (k-inExt[4])*incZ; + // Increments are different for cells. + // Since the cells are not contoured until the second row of templates, + // subtract 1 from i,j,and k. Note: first cube is formed when i=0, j=1, and k=1. + inCellId = (XMin-inExt[0]) + (inExt[1]-inExt[0])*( (j-inExt[2]-1) + (k-inExt[4]-1)*(inExt[3]-inExt[2]) ); + + p1 = inPtPtrY; + s1 = inPtrY; + v1 = (*s1 < value ? 0 : 1); + inPtPtrX = inPtPtrY; + inPtrX = inPtrY; + // inCellId is ised to keep track of ids for copying cell attributes. + for (i = XMin; i <= XMax; i++, inCellId++) + { + p0 = p1; + s0 = s1; + v0 = v1; + // this flag keeps up from computing gradient for grid point 0 twice. + g0 = 0; + *isect2Ptr = -1; + *(isect2Ptr + 1) = -1; + *(isect2Ptr + 2) = -1; + if (i < XMax) + { + p1 = (inPtPtrX + 3); + s1 = (inPtrX + 1); + v1 = (*s1 < value ? 0 : 1); + if (v0 ^ v1) + { + // watch for degenerate points + if (*s0 == value) + { + if (i > XMin && *(isect2Ptr-3) > -1) + { + *isect2Ptr = *(isect2Ptr-3); + } + else if (j > XMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 1); + } + else if (k > ZMin && *(isect1Ptr+2) > -1) + { + *isect2Ptr = *(isect1Ptr+2); + } + } + else if (*s1 == value) + { + if (j > YMin && *(isect2Ptr - yisectstep +4) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 4); + } + else if (k > ZMin && i < XMax && *(isect1Ptr + 5) > -1) + { + *isect2Ptr = *(isect1Ptr + 5); + } + } + // if the edge has not been set yet then it is a new point + if (*isect2Ptr == -1) + { + t = (value - (double)(*s0)) / ((double)(*s1) - (double)(*s0)); + x[0] = p0[0] + t*(p1[0] - p0[0]); + x[1] = p0[1] + t*(p1[1] - p0[1]); + x[2] = p0[2] + t*(p1[2] - p0[2]); + *isect2Ptr = newPts->InsertNextPoint(x); + VTK_CSP3PA(i+1,j,k,s1,p1,grad,norm); + outPD->InterpolateEdge(inPD, *isect2Ptr, edgePtId, edgePtId+1, t); + } + } + } + if (j < YMax) + { + p2 = (inPtPtrX + incY*3); + s2 = (inPtrX + incY); + v2 = (*s2 < value ? 0 : 1); + if (v0 ^ v2) + { + // watch for degen points + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 1) = *isect2Ptr; + } + else if (i > XMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr-3); + } + else if (j > YMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr - yisectstep + 1); + } + else if (k > ZMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 1) = *(isect1Ptr+2); + } + } + else if (*s2 == value && k > ZMin && *(isect1Ptr + yisectstep + 2) > -1) + { + *(isect2Ptr+1) = *(isect1Ptr + yisectstep + 2); + } + // if the edge has not been set yet then it is a new point + if (*(isect2Ptr + 1) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s2) - (double)(*s0)); + x[0] = p0[0] + t*(p2[0] - p0[0]); + x[1] = p0[1] + t*(p2[1] - p0[1]); + x[2] = p0[2] + t*(p2[2] - p0[2]); + *(isect2Ptr + 1) = newPts->InsertNextPoint(x); + VTK_CSP3PA(i,j+1,k,s2,p2,grad,norm); + outPD->InterpolateEdge(inPD, *(isect2Ptr+1), edgePtId, + edgePtId+incY, t); + } + } + } + if (k < ZMax) + { + p3 = (inPtPtrX + incZ*3); + s3 = (inPtrX + incZ); + v3 = (*s3 < value ? 0 : 1); + if (v0 ^ v3) + { + // watch for degen points + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 2) = *isect2Ptr; + } + else if (*(isect2Ptr+1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr+1); + } + else if (i > XMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr-3); + } + else if (j > YMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr - yisectstep + 1); + } + else if (k > ZMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 2) = *(isect1Ptr+2); + } + } + if (*(isect2Ptr + 2) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s3) - (double)(*s0)); + x[0] = p0[0] + t*(p3[0] - p0[0]); + x[1] = p0[1] + t*(p3[1] - p0[1]); + x[2] = p0[2] + t*(p3[2] - p0[2]); + *(isect2Ptr + 2) = newPts->InsertNextPoint(x); + VTK_CSP3PA(i,j,k+1,s3,p3,grad,norm); + outPD->InterpolateEdge(inPD, *(isect2Ptr+2), + edgePtId, edgePtId+incZ, t); + } + } + } + + // To keep track of ids for interpolating attributes. + ++edgePtId; + + // now add any polys that need to be added + // basically look at the isect values, + // form an index and lookup the polys + if (j > YMin && i < XMax && k > ZMin) + { + idx = (v0 ? 4096 : 0); + idx = idx + (*(isect1Ptr - yisectstep) > -1 ? 2048 : 0); + idx = idx + (*(isect1Ptr -yisectstep +1) > -1 ? 1024 : 0); + idx = idx + (*(isect1Ptr -yisectstep +2) > -1 ? 512 : 0); + idx = idx + (*(isect1Ptr -yisectstep +4) > -1 ? 256 : 0); + idx = idx + (*(isect1Ptr -yisectstep +5) > -1 ? 128 : 0); + idx = idx + (*(isect1Ptr) > -1 ? 64 : 0); + idx = idx + (*(isect1Ptr + 2) > -1 ? 32 : 0); + idx = idx + (*(isect1Ptr + 5) > -1 ? 16 : 0); + idx = idx + (*(isect2Ptr -yisectstep) > -1 ? 8 : 0); + idx = idx + (*(isect2Ptr -yisectstep +1) > -1 ? 4 : 0); + idx = idx + (*(isect2Ptr -yisectstep +4) > -1 ? 2 : 0); + idx = idx + (*(isect2Ptr) > -1 ? 1 : 0); + + tablePtr = VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_2 + + VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_1[idx]; + // to protect data against multiple threads + if ( input->IsCellVisible(inCellId) ) + { + while (*tablePtr != -1) + { + ptIds[0] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[1] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[2] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + if (ptIds[0] != ptIds[1] && + ptIds[0] != ptIds[2] && + ptIds[1] != ptIds[2]) + { + outCellId = newPolys->InsertNextCell(3,ptIds); + outCD->CopyData(inCD, inCellId, outCellId); + } + } + } + } + inPtPtrX += 3; + ++inPtrX; + isect2Ptr += 3; + isect1Ptr += 3; + } + inPtPtrY += 3*incY; + inPtrY += incY; + } + inPtPtrZ += 3*incZ; + inPtrZ += incZ; + } + } + + if (newScalars) + { + newScalars->SetName(inScalars->GetName()); + idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + newScalars = NULL; + } + if (newGradients) + { + output->GetPointData()->SetVectors(newGradients); + newGradients->Delete(); + newGradients = NULL; + } + if (newNormals) + { + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + newNormals = NULL; + } + + delete [] isect1; +} + +template +void ContourGrid(vtkGridSynchronizedTemplates3D *self, + int *exExt, T *scalars, vtkStructuredGrid *input, + vtkPolyData *output, vtkDataArray *inScalars) +{ + switch(input->GetPoints()->GetData()->GetDataType()) + { + vtkTemplateMacro( + ContourGrid(self, exExt, scalars, input, output, (VTK_TT*)0, inScalars)); + } +} + +//---------------------------------------------------------------------------- +// Contouring filter specialized for images (or slices from images) +void vtkGridSynchronizedTemplates3D::ThreadedExecute(int *exExt, int , + vtkStructuredGrid *input, + vtkInformationVector **inputVector, + vtkInformation *outInfo) +{ + vtkDataArray *inScalars = this->GetInputArrayToProcess(0,inputVector); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + long dataSize; + + vtkDebugMacro(<< "Executing 3D structured contour"); + + if ( inScalars == NULL ) + { + vtkErrorMacro(<<"Scalars must be defined for contouring"); + return; + } + + if ( input->GetDataDimension() != 3 ) + { + vtkErrorMacro(<<"3D structured contours requires 3D data"); + return; + } + + // + // Check dimensionality of data and get appropriate form + // + dataSize = (exExt[1]-exExt[0]+1) * (exExt[3]-exExt[2]+1) + * (exExt[5]-exExt[4]+1); + + // + // Check data type and execute appropriate function + // + if (inScalars->GetNumberOfComponents() == 1 ) + { + void *scalars = inScalars->GetVoidPointer(0); + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + ContourGrid(this, exExt, (VTK_TT *)scalars, input, output, inScalars)); + }//switch + } + else //multiple components - have to convert + { + vtkDoubleArray *image = vtkDoubleArray::New(); + image->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + image->Allocate(dataSize*image->GetNumberOfComponents()); + inScalars->GetTuples(0,dataSize,image); + double *scalars = image->GetPointer(0); + ContourGrid(this, exExt, scalars, input, output, inScalars); + image->Delete(); + } + + // Lets set the name of the scalars here. + if (this->ComputeScalars) + { + vtkDataArray *outScalars = output->GetPointData()->GetScalars(); + outScalars->SetName(inScalars->GetName()); + } +} + +//---------------------------------------------------------------------------- +int vtkGridSynchronizedTemplates3D::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces; + int *wholeExt; + int ext[6]; + + vtkExtentTranslator *translator = vtkExtentTranslator::SafeDownCast( + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + // Get request from output + piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + // Start with the whole grid. + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext); + + // get the extent associated with the piece. + if (translator == NULL) + { + // Default behavior + if (piece != 0) + { + ext[0] = ext[2] = ext[4] = 0; + ext[1] = ext[3] = ext[5] = -1; + } + } + else + { + translator->PieceToExtentThreadSafe(piece, numPieces, 0, wholeExt, ext, + translator->GetSplitMode(),0); + } + + // As a side product of this call, ExecuteExtent is set. + // This is the region that we are really updating, although + // we may require a larger input region in order to generate + // it if normals / gradients are being computed + + this->ExecuteExtent[0] = ext[0]; + this->ExecuteExtent[1] = ext[1]; + this->ExecuteExtent[2] = ext[2]; + this->ExecuteExtent[3] = ext[3]; + this->ExecuteExtent[4] = ext[4]; + this->ExecuteExtent[5] = ext[5]; + + // expand if we need to compute gradients + if (this->ComputeGradients || this->ComputeNormals) + { + ext[0] -= 1; + if (ext[0] < wholeExt[0]) + { + ext[0] = wholeExt[0]; + } + ext[1] += 1; + if (ext[1] > wholeExt[1]) + { + ext[1] = wholeExt[1]; + } + + ext[2] -= 1; + if (ext[2] < wholeExt[2]) + { + ext[2] = wholeExt[2]; + } + ext[3] += 1; + if (ext[3] > wholeExt[3]) + { + ext[3] = wholeExt[3]; + } + + ext[4] -= 1; + if (ext[4] < wholeExt[4]) + { + ext[4] = wholeExt[4]; + } + ext[5] += 1; + if (ext[5] > wholeExt[5]) + { + ext[5] = wholeExt[5]; + } + } + + // Set the update extent of the input. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGridSynchronizedTemplates3D::FillInputPortInformation( + int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkGridSynchronizedTemplates3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Gradients: " << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " << (this->ComputeScalars ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +int vtkGridSynchronizedTemplates3D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Make sure the attributes match the geometry. + if (input->CheckAttributes()) + { + return 1; + } + + if (input->GetNumberOfPoints() == 0) + { + return 1; + } + + // just call the threaded execute directly. + this->ThreadedExecute(this->GetExecuteExtent(), 0, input, inputVector, outInfo); + + output->Squeeze(); + + return 1; +} diff --git a/Graphics/vtkGridSynchronizedTemplates3D.h b/Graphics/vtkGridSynchronizedTemplates3D.h new file mode 100644 index 0000000..c0619c5 --- /dev/null +++ b/Graphics/vtkGridSynchronizedTemplates3D.h @@ -0,0 +1,152 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGridSynchronizedTemplates3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGridSynchronizedTemplates3D - generate isosurface from structured grids + +// .SECTION Description +// vtkGridSynchronizedTemplates3D is a 3D implementation of the synchronized +// template algorithm. + +// .SECTION Caveats +// This filter is specialized to 3D grids. + +// .SECTION See Also +// vtkContourFilter vtkSynchronizedTemplates3D + +#ifndef __vtkGridSynchronizedTemplates3D_h +#define __vtkGridSynchronizedTemplates3D_h + +#include "vtkPolyDataAlgorithm.h" +#include "vtkContourValues.h" // Because it passes all the calls to it + +class vtkKitwareContourFilter; +class vtkStructuredGrid; + +class VTK_GRAPHICS_EXPORT vtkGridSynchronizedTemplates3D : public vtkPolyDataAlgorithm +{ +public: + static vtkGridSynchronizedTemplates3D *New(); + vtkTypeRevisionMacro(vtkGridSynchronizedTemplates3D,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Because we delegate to vtkContourValues + unsigned long int GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Set a particular contour value at contour number i. The index i ranges + // between 0<=iContourValues->SetValue(i,value);} + + // Description: + // Get the ith contour value. + double GetValue(int i) {return this->ContourValues->GetValue(i);} + + // Description: + // Get a pointer to an array of contour values. There will be + // GetNumberOfContours() values in the list. + double *GetValues() {return this->ContourValues->GetValues();} + + // Description: + // Fill a supplied list with contour values. There will be + // GetNumberOfContours() values in the list. Make sure you allocate + // enough memory to hold the list. + void GetValues(double *contourValues) { + this->ContourValues->GetValues(contourValues);} + + // Description: + // Set the number of contours to place into the list. You only really + // need to use this method to reduce list size. The method SetValue() + // will automatically increase list size as needed. + void SetNumberOfContours(int number) { + this->ContourValues->SetNumberOfContours(number);} + + // Description: + // Get the number of contours in the list of contour values. + int GetNumberOfContours() { + return this->ContourValues->GetNumberOfContours();} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double range[2]) { + this->ContourValues->GenerateValues(numContours, range);} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double rangeStart, double rangeEnd) + {this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + // Description: + // Needed by templated functions. + int *GetExecuteExtent() {return this->ExecuteExtent;} + void ThreadedExecute(int *exExt, int threadId, vtkStructuredGrid *input, + vtkInformationVector **inVec, + vtkInformation *outInfo); + + // Description: + // This filter will initiate streaming so that no piece requested + // from the input will be larger than this value (KiloBytes). + void SetInputMemoryLimit(long limit); + +protected: + vtkGridSynchronizedTemplates3D(); + ~vtkGridSynchronizedTemplates3D(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkContourValues *ContourValues; + + int MinimumPieceSize[3]; + int ExecuteExtent[6]; + +private: + vtkGridSynchronizedTemplates3D(const vtkGridSynchronizedTemplates3D&); // Not implemented. + void operator=(const vtkGridSynchronizedTemplates3D&); // Not implemented. +}; + + +#endif diff --git a/Graphics/vtkHedgeHog.cxx b/Graphics/vtkHedgeHog.cxx new file mode 100644 index 0000000..a2e32d2 --- /dev/null +++ b/Graphics/vtkHedgeHog.cxx @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHedgeHog.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHedgeHog.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkHedgeHog, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkHedgeHog); + +vtkHedgeHog::vtkHedgeHog() +{ + this->ScaleFactor = 1.0; + this->VectorMode = VTK_USE_VECTOR; +} + +int vtkHedgeHog::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts; + vtkPoints *newPts; + vtkPointData *pd; + vtkDataArray *inVectors; + vtkDataArray *inNormals; + vtkIdType ptId; + int i; + vtkIdType pts[2]; + vtkCellArray *newLines; + double x[3], v[3]; + double newX[3]; + vtkPointData *outputPD = output->GetPointData(); + + // Initialize + // + numPts = input->GetNumberOfPoints(); + pd = input->GetPointData(); + inVectors = pd->GetVectors(); + if ( numPts < 1 ) + { + vtkErrorMacro(<<"No input data"); + return 1; + } + if ( !inVectors && this->VectorMode == VTK_USE_VECTOR) + { + vtkErrorMacro(<<"No vectors in input data"); + return 1; + } + + inNormals = pd->GetNormals(); + if ( !inNormals && this->VectorMode == VTK_USE_NORMAL) + { + vtkErrorMacro(<<"No normals in input data"); + return 1; + } + outputPD->CopyAllocate(pd, 2*numPts); + + newPts = vtkPoints::New(); newPts->SetNumberOfPoints(2*numPts); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(numPts,2)); + + // Loop over all points, creating oriented line + // + for (ptId=0; ptId < numPts; ptId++) + { + if ( ! (ptId % 10000) ) //abort/progress + { + this->UpdateProgress ((double)ptId/numPts); + if (this->GetAbortExecute()) + { + break; + } + } + + input->GetPoint(ptId, x); + if (this->VectorMode == VTK_USE_VECTOR) + { + inVectors->GetTuple(ptId, v); + } + else + { + inNormals->GetTuple(ptId, v); + } + for (i=0; i<3; i++) + { + newX[i] = x[i] + this->ScaleFactor * v[i]; + } + + pts[0] = ptId; + pts[1] = ptId + numPts;; + + newPts->SetPoint(pts[0], x); + newPts->SetPoint(pts[1], newX); + + newLines->InsertNextCell(2,pts); + + outputPD->CopyData(pd,ptId,pts[0]); + outputPD->CopyData(pd,ptId,pts[1]); + } + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +int vtkHedgeHog::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkHedgeHog::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; + os << indent << "Orient Mode: " << (this->VectorMode == VTK_USE_VECTOR ? + "Orient by vector\n" : "Orient by normal\n"); +} diff --git a/Graphics/vtkHedgeHog.h b/Graphics/vtkHedgeHog.h new file mode 100644 index 0000000..84f8e49 --- /dev/null +++ b/Graphics/vtkHedgeHog.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHedgeHog.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHedgeHog - create oriented lines from vector data +// .SECTION Description +// vtkHedgeHog creates oriented lines from the input data set. Line +// length is controlled by vector (or normal) magnitude times scale +// factor. If VectorMode is UseNormal, normals determine the orientation +// of the lines. Lines are colored by scalar data, if available. + +#ifndef __vtkHedgeHog_h +#define __vtkHedgeHog_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_USE_VECTOR 0 +#define VTK_USE_NORMAL 1 + +class VTK_GRAPHICS_EXPORT vtkHedgeHog : public vtkPolyDataAlgorithm +{ +public: + static vtkHedgeHog *New(); + vtkTypeRevisionMacro(vtkHedgeHog,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set scale factor to control size of oriented lines. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Specify whether to use vector or normal to perform vector operations. + vtkSetMacro(VectorMode,int); + vtkGetMacro(VectorMode,int); + void SetVectorModeToUseVector() {this->SetVectorMode(VTK_USE_VECTOR);}; + void SetVectorModeToUseNormal() {this->SetVectorMode(VTK_USE_NORMAL);}; + const char *GetVectorModeAsString(); + +protected: + vtkHedgeHog(); + ~vtkHedgeHog() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + double ScaleFactor; + int VectorMode; // Orient/scale via normal or via vector data + +private: + vtkHedgeHog(const vtkHedgeHog&); // Not implemented. + void operator=(const vtkHedgeHog&); // Not implemented. +}; + +// Description: +// Return the vector mode as a character string. +inline const char *vtkHedgeHog::GetVectorModeAsString(void) +{ + if ( this->VectorMode == VTK_USE_VECTOR) + { + return "UseVector"; + } + else if ( this->VectorMode == VTK_USE_NORMAL) + { + return "UseNormal"; + } + else + { + return "Unknown"; + } +} +#endif diff --git a/Graphics/vtkHierarchicalDataExtractDataSets.cxx b/Graphics/vtkHierarchicalDataExtractDataSets.cxx new file mode 100644 index 0000000..65c6ab8 --- /dev/null +++ b/Graphics/vtkHierarchicalDataExtractDataSets.cxx @@ -0,0 +1,261 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkHierarchicalDataExtractDataSets.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataExtractDataSets.h" + +#include "vtkCompositeDataPipeline.h" +#include "vtkCompositeDataSet.h" +#include "vtkDataSet.h" +#include "vtkHierarchicalBoxDataSet.h" +#include "vtkHierarchicalDataInformation.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkUniformGrid.h" + +#include + +vtkCxxRevisionMacro(vtkHierarchicalDataExtractDataSets, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkHierarchicalDataExtractDataSets); + +struct vtkHierarchicalDataExtractDataSetsInternals +{ + typedef + vtkstd::list DataSetsTypes; + DataSetsTypes DataSets; +}; + +//---------------------------------------------------------------------------- +vtkHierarchicalDataExtractDataSets::vtkHierarchicalDataExtractDataSets() +{ + this->Internal = new vtkHierarchicalDataExtractDataSetsInternals; +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataExtractDataSets::~vtkHierarchicalDataExtractDataSets() +{ + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataExtractDataSets::AddDataSet( + unsigned int level, unsigned int idx) +{ + this->Internal->DataSets.push_back(DataSetNode(level, idx)); + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataExtractDataSets::ClearDataSetList() +{ + this->Internal->DataSets.clear(); + this->Modified(); +} + +//---------------------------------------------------------------------------- +unsigned int vtkHierarchicalDataExtractDataSets::ComputeOutputLevels( + unsigned int inputNumLevels) +{ + unsigned int numLevels = 0; + vtkHierarchicalDataExtractDataSetsInternals::DataSetsTypes::iterator it = + this->Internal->DataSets.begin(); + for (; it != this->Internal->DataSets.end(); it++) + { + DataSetNode& node = *it; + unsigned int curNumLevels = node.Level + 1; + if (curNumLevels > numLevels && curNumLevels <= inputNumLevels) + { + numLevels = curNumLevels; + } + } + return numLevels; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataExtractDataSets::RequestDataObject( + vtkInformation*, + vtkInformationVector** inputVector , + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + if (!inInfo) + { + return 0; + } + vtkCompositeDataSet *input = vtkCompositeDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + if (input) + { + vtkInformation* info = outputVector->GetInformationObject(0); + vtkCompositeDataSet *output = vtkCompositeDataSet::SafeDownCast( + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + if (!output || !output->IsA(input->GetClassName())) + { + output = input->NewInstance(); + output->SetPipelineInformation(info); + output->Delete(); + } + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataExtractDataSets::RequestInformation( + vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkHierarchicalDataInformation* inCompInfo = + vtkHierarchicalDataInformation::SafeDownCast( + inInfo->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + if (!inCompInfo) + { + vtkDebugMacro("Expected information not found. " + "Cannot provide information."); + return 1; + } + + unsigned int numInputLevels = inCompInfo->GetNumberOfLevels(); + unsigned int numOutputLevels = this->ComputeOutputLevels(numInputLevels); + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::New(); + if (numOutputLevels > 0) + { + compInfo->SetNumberOfLevels(numOutputLevels); + vtkHierarchicalDataExtractDataSetsInternals::DataSetsTypes::iterator it = + this->Internal->DataSets.begin(); + for (; it != this->Internal->DataSets.end(); it++) + { + DataSetNode& node = *it; + unsigned int numInputDataSets = + inCompInfo->GetNumberOfDataSets(node.Level); + if (node.DataSetId <= numInputDataSets) + { + if (node.DataSetId >= compInfo->GetNumberOfDataSets(node.Level)) + { + compInfo->SetNumberOfDataSets(node.Level, node.DataSetId+1); + + if (inCompInfo->HasInformation(node.Level, node.DataSetId)) + { + vtkInformation* outdInfo = + compInfo->GetInformation(node.Level, node.DataSetId); + vtkInformation* indInfo = + inCompInfo->GetInformation(node.Level, node.DataSetId); + outdInfo->Copy(indInfo); + } + } + } + } + } + + vtkInformation* outInfo = outputVector->GetInformationObject(0); + outInfo->Set( + vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION(), compInfo); + compInfo->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataExtractDataSets::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkHierarchicalDataSet *input = vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (!input) {return 0;} + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkHierarchicalDataSet *output = vtkHierarchicalDataSet::SafeDownCast( + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (!output) {return 0;} + + unsigned int numInputLevels = input->GetNumberOfLevels(); + unsigned int numOutputLevels = this->ComputeOutputLevels(numInputLevels); + + if (numOutputLevels > 0) + { + output->SetNumberOfLevels(numOutputLevels); + + vtkHierarchicalDataExtractDataSetsInternals::DataSetsTypes::iterator it = + this->Internal->DataSets.begin(); + for (; it != this->Internal->DataSets.end(); it++) + { + DataSetNode& node = *it; + unsigned int numInputDataSets = input->GetNumberOfDataSets(node.Level); + if (node.DataSetId <= numInputDataSets) + { + if (node.DataSetId >= output->GetNumberOfDataSets(node.Level)) + { + output->SetNumberOfDataSets(node.Level, node.DataSetId+1); + } + vtkDataObject* dObj = + input->GetDataSet(node.Level, node.DataSetId); + if (dObj) + { + vtkDataObject* copy = dObj->NewInstance(); + copy->ShallowCopy(dObj); + output->SetDataSet(node.Level, node.DataSetId, copy); + // Remove blanking from output datasets. + vtkUniformGrid* ug = vtkUniformGrid::SafeDownCast(copy); + if (ug) + { + ug->SetCellVisibilityArray(0); + } + output->SetDataSet(node.Level, node.DataSetId, copy); + copy->Delete(); + } + } + } + + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::SafeDownCast( + info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + + if (compInfo) + { + output->SetHierarchicalDataInformation(compInfo); + } + unsigned int numLevels = output->GetNumberOfLevels(); + + vtkHierarchicalBoxDataSet* hbds = + vtkHierarchicalBoxDataSet::SafeDownCast(output); + if (hbds) + { + vtkHierarchicalBoxDataSet* ihbds = + vtkHierarchicalBoxDataSet::SafeDownCast(input); + for (unsigned int level=0; levelSetRefinementRatio(level, ihbds->GetRefinementRatio(level)); + } + hbds->GenerateVisibilityArrays(); + } + + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataExtractDataSets::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkHierarchicalDataExtractDataSets.h b/Graphics/vtkHierarchicalDataExtractDataSets.h new file mode 100644 index 0000000..99bcc3f --- /dev/null +++ b/Graphics/vtkHierarchicalDataExtractDataSets.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataExtractDataSets.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataExtractDataSets - extract a number of datasets +// .SECTION Description +// vtkHierarchicalDataExtractDataSets extracts the user specified list +// of datasets from a hierarchical dataset. + +#ifndef __vtkHierarchicalDataExtractDataSets_h +#define __vtkHierarchicalDataExtractDataSets_h + +#include "vtkHierarchicalDataSetAlgorithm.h" + +//BTX +struct vtkHierarchicalDataExtractDataSetsInternals; +//ETX + +class VTK_GRAPHICS_EXPORT vtkHierarchicalDataExtractDataSets : public vtkHierarchicalDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkHierarchicalDataExtractDataSets,vtkHierarchicalDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkHierarchicalDataExtractDataSets *New(); + + // Description: + // Add a dataset to be extracted. + void AddDataSet(unsigned int level, unsigned int idx); + + // Description: + // Remove all entries from the list of datasets to be extracted. + void ClearDataSetList(); + +protected: + vtkHierarchicalDataExtractDataSets(); + ~vtkHierarchicalDataExtractDataSets(); + + virtual int RequestDataObject(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual int RequestInformation(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + unsigned int ComputeOutputLevels(unsigned int inputNumLevels); + +//BTX + friend struct vtkHierarchicalDataExtractDataSetsInternals; + + struct DataSetNode + { + unsigned int Level; + unsigned int DataSetId; + int Initialized; + + DataSetNode() : Initialized(0) {} + DataSetNode(unsigned int level, unsigned int dsid) : + Level(level), DataSetId(dsid), Initialized(1) {} + }; +//ETX + +private: + vtkHierarchicalDataExtractDataSetsInternals* Internal; + + vtkHierarchicalDataExtractDataSets(const vtkHierarchicalDataExtractDataSets&); // Not implemented. + void operator=(const vtkHierarchicalDataExtractDataSets&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkHierarchicalDataExtractLevel.cxx b/Graphics/vtkHierarchicalDataExtractLevel.cxx new file mode 100644 index 0000000..c8669d2 --- /dev/null +++ b/Graphics/vtkHierarchicalDataExtractLevel.cxx @@ -0,0 +1,223 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkHierarchicalDataExtractLevel.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataExtractLevel.h" + +#include "vtkCompositeDataPipeline.h" +#include "vtkCompositeDataSet.h" +#include "vtkDataSet.h" +#include "vtkHierarchicalBoxDataSet.h" +#include "vtkHierarchicalDataInformation.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkUniformGrid.h" + +vtkCxxRevisionMacro(vtkHierarchicalDataExtractLevel, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkHierarchicalDataExtractLevel); + +//---------------------------------------------------------------------------- +vtkHierarchicalDataExtractLevel::vtkHierarchicalDataExtractLevel() +{ + this->MinLevel = 0; + this->MaxLevel = 0; + + this->InputLevels[0] = 0; + this->InputLevels[1] = 0; +} + +//---------------------------------------------------------------------------- +vtkHierarchicalDataExtractLevel::~vtkHierarchicalDataExtractLevel() +{ +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataExtractLevel::RequestDataObject( + vtkInformation*, + vtkInformationVector** inputVector , + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + if (!inInfo) + { + return 0; + } + vtkCompositeDataSet *input = vtkCompositeDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + if (input) + { + vtkInformation* info = outputVector->GetInformationObject(0); + vtkCompositeDataSet *output = vtkCompositeDataSet::SafeDownCast( + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + if (!output || !output->IsA(input->GetClassName())) + { + output = input->NewInstance(); + output->SetPipelineInformation(info); + output->Delete(); + } + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataExtractLevel::RequestInformation( + vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkHierarchicalDataInformation* inCompInfo = + vtkHierarchicalDataInformation::SafeDownCast( + inInfo->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + if (!inCompInfo) + { + vtkDebugMacro("Expected information not found. " + "Cannot provide information."); + return 1; + } + + unsigned int numInputLevels = inCompInfo->GetNumberOfLevels(); + this->InputLevels[1] = numInputLevels-1; + + unsigned int numLevels; + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::New(); + if (this->MaxLevel >= numInputLevels) + { + numLevels = numInputLevels; + } + else + { + numLevels = this->MaxLevel+1; + } + compInfo->SetNumberOfLevels(numLevels); + + for (unsigned int i=0; iMinLevel || i > this->MaxLevel) + { + compInfo->SetNumberOfDataSets(i, 0); + } + else + { + compInfo->SetNumberOfDataSets(i, inCompInfo->GetNumberOfDataSets(i)); + } + unsigned int numDataSets = compInfo->GetNumberOfDataSets(i); + for (unsigned int j=0; jHasInformation(i, j)) + { + vtkInformation* outdInfo = compInfo->GetInformation(i, j); + vtkInformation* indInfo = inCompInfo->GetInformation(i, j); + outdInfo->Copy(indInfo); + } + } + } + + vtkInformation* outInfo = outputVector->GetInformationObject(0); + outInfo->Set( + vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION(), compInfo); + compInfo->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkHierarchicalDataExtractLevel::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkHierarchicalDataSet *input = vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (!input) {return 0;} + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkHierarchicalDataSet *output = vtkHierarchicalDataSet::SafeDownCast( + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (!output) {return 0;} + + output->SetNumberOfLevels(this->MaxLevel+1); + unsigned int numLevels = output->GetNumberOfLevels(); + + for (unsigned int level=0; levelMinLevel || level > this->MaxLevel) + { + output->SetNumberOfDataSets(level, 0); + continue; + } + unsigned int numDataSets = input->GetNumberOfDataSets(level); + output->SetNumberOfDataSets(level, numDataSets); + for (unsigned int dataSet=0; dataSetGetDataSet(level, dataSet)); + if (dObj) + { + vtkDataSet* copy = dObj->NewInstance(); + copy->ShallowCopy(dObj); + output->SetDataSet(level, dataSet, copy); + copy->Delete(); + } + } + } + vtkHierarchicalDataInformation* compInfo = + vtkHierarchicalDataInformation::SafeDownCast( + info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION())); + + output->SetHierarchicalDataInformation(compInfo); + + vtkHierarchicalBoxDataSet* hbds = + vtkHierarchicalBoxDataSet::SafeDownCast(output); + if (hbds) + { + vtkHierarchicalBoxDataSet* ihbds = + vtkHierarchicalBoxDataSet::SafeDownCast(input); + for (unsigned int level=0; levelSetRefinementRatio(level, ihbds->GetRefinementRatio(level)); + } + } + + // Last level should not be blanked (uniform grid only) + unsigned int numDataSets = output->GetNumberOfDataSets(numLevels-1); + for (unsigned int dataSet=0; dataSetGetDataSet(numLevels-1, dataSet)); + if (ug) + { + ug->SetCellVisibilityArray(0); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkHierarchicalDataExtractLevel::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "MinLevel:" << this->MinLevel << endl; + os << indent << "MaxLevel:" << this->MaxLevel << endl; + os << indent << "InputLevels: (" << this->InputLevels[0] << "," + << this->InputLevels[1] << ")" << endl; + +} diff --git a/Graphics/vtkHierarchicalDataExtractLevel.h b/Graphics/vtkHierarchicalDataExtractLevel.h new file mode 100644 index 0000000..191f1aa --- /dev/null +++ b/Graphics/vtkHierarchicalDataExtractLevel.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataExtractLevel.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataExtractLevel - extact levels between min and max +// .SECTION Description +// vtkHierarchicalDataExtractLevel is a filter to that extracts levels +// between user specified min and max. + +#ifndef __vtkHierarchicalDataExtractLevel_h +#define __vtkHierarchicalDataExtractLevel_h + +#include "vtkHierarchicalDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkHierarchicalDataExtractLevel : public vtkHierarchicalDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkHierarchicalDataExtractLevel,vtkHierarchicalDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkHierarchicalDataExtractLevel *New(); + + // Description: + // Minimum level to be extacted + vtkSetMacro(MinLevel, unsigned int); + vtkGetMacro(MinLevel, unsigned int); + + // Description: + // Maximum level to be extacted + vtkSetMacro(MaxLevel, unsigned int); + vtkGetMacro(MaxLevel, unsigned int); + + // Description: + // Sets the min and max levels + void SetLevelRange(unsigned int min, unsigned int max) + { + this->SetMinLevel(min); + this->SetMaxLevel(max); + } + + // Description: + // Returns input min (always 0) and max levels. + vtkGetVector2Macro(InputLevels, int); + +protected: + vtkHierarchicalDataExtractLevel(); + ~vtkHierarchicalDataExtractLevel(); + + virtual int RequestDataObject(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual int RequestInformation(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + unsigned int MinLevel; + unsigned int MaxLevel; + int InputLevels[2]; + +private: + vtkHierarchicalDataExtractLevel(const vtkHierarchicalDataExtractLevel&); // Not implemented. + void operator=(const vtkHierarchicalDataExtractLevel&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkHierarchicalDataLevelFilter.cxx b/Graphics/vtkHierarchicalDataLevelFilter.cxx new file mode 100644 index 0000000..f09e3ab --- /dev/null +++ b/Graphics/vtkHierarchicalDataLevelFilter.cxx @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataLevelFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataLevelFilter.h" + +#include "vtkCellData.h" +#include "vtkCompositeDataSet.h" +#include "vtkDataSet.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkHierarchicalDataLevelFilter, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkHierarchicalDataLevelFilter); + +// Construct object with PointIds and CellIds on; and ids being generated +// as scalars. +vtkHierarchicalDataLevelFilter::vtkHierarchicalDataLevelFilter() +{ +} + +vtkHierarchicalDataLevelFilter::~vtkHierarchicalDataLevelFilter() +{ +} + +// +// Map ids into attribute data +// +int vtkHierarchicalDataLevelFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkHierarchicalDataSet *input = vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (!input) {return 0;} + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkHierarchicalDataSet *output = vtkHierarchicalDataSet::SafeDownCast( + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (!output) {return 0;} + + unsigned int numLevels = input->GetNumberOfLevels(); + output->SetNumberOfLevels(numLevels); + + for (unsigned int level=0; levelGetNumberOfDataSets(level); + output->SetNumberOfDataSets(level, numDataSets); + for (unsigned int dataSet=0; dataSetGetDataSet(level, dataSet)); + if (dObj) + { + vtkDataSet* copy = dObj->NewInstance(); + copy->ShallowCopy(dObj); + output->SetDataSet(level, dataSet, copy); + vtkIdType numCells = copy->GetNumberOfCells(); + vtkUnsignedCharArray* cArray = vtkUnsignedCharArray::New(); + cArray->SetNumberOfTuples(numCells); + for (vtkIdType cellIdx=0; cellIdxSetValue(cellIdx, level); + } + cArray->SetName("LevelScalars"); + copy->GetCellData()->AddArray(cArray); + cArray->Delete(); + copy->Delete(); + } + } + } + + return 1; +} + +void vtkHierarchicalDataLevelFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkHierarchicalDataLevelFilter.h b/Graphics/vtkHierarchicalDataLevelFilter.h new file mode 100644 index 0000000..0f70613 --- /dev/null +++ b/Graphics/vtkHierarchicalDataLevelFilter.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataLevelFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataLevelFilter - generate scalars from levels +// .SECTION Description +// vtkHierarchicalDataLevelFilter is a filter to that generates scalars +// using hiearchical data level information. + +#ifndef __vtkHierarchicalDataLevelFilter_h +#define __vtkHierarchicalDataLevelFilter_h + +#include "vtkHierarchicalDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkHierarchicalDataLevelFilter : public vtkHierarchicalDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkHierarchicalDataLevelFilter,vtkHierarchicalDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with PointIds and CellIds on; and ids being generated + // as scalars. + static vtkHierarchicalDataLevelFilter *New(); + +protected: + vtkHierarchicalDataLevelFilter(); + ~vtkHierarchicalDataLevelFilter(); + + int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + +private: + vtkHierarchicalDataLevelFilter(const vtkHierarchicalDataLevelFilter&); // Not implemented. + void operator=(const vtkHierarchicalDataLevelFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkHierarchicalDataSetGeometryFilter.cxx b/Graphics/vtkHierarchicalDataSetGeometryFilter.cxx new file mode 100644 index 0000000..4134017 --- /dev/null +++ b/Graphics/vtkHierarchicalDataSetGeometryFilter.cxx @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataSetGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHierarchicalDataSetGeometryFilter.h" + +#include "vtkAppendPolyData.h" +#include "vtkCompositeDataIterator.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkDataSet.h" +#include "vtkGeometryFilter.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkHierarchicalDataSetGeometryFilter, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkHierarchicalDataSetGeometryFilter); + +vtkHierarchicalDataSetGeometryFilter::vtkHierarchicalDataSetGeometryFilter() +{ +} + +vtkHierarchicalDataSetGeometryFilter::~vtkHierarchicalDataSetGeometryFilter() +{ +} + +int vtkHierarchicalDataSetGeometryFilter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject"); + info->Set(vtkCompositeDataPipeline::INPUT_REQUIRED_COMPOSITE_DATA_TYPE(), + "vtkHierarchicalDataSet"); + return 1; +} + +int vtkHierarchicalDataSetGeometryFilter::ProcessRequest( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkCompositeDataPipeline::REQUEST_DATA())) + { + int retVal = this->RequestCompositeData(request, inputVector, outputVector); + return retVal; + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +int vtkHierarchicalDataSetGeometryFilter::RequestCompositeData( + vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkHierarchicalDataSet *input = vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (!input) + { + vtkErrorMacro("No input composite dataset provided."); + return 0; + } + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + if (!output) + { + vtkErrorMacro("No output polydata provided."); + return 0; + } + + vtkCompositeDataIterator* iter = input->NewIterator(); + iter->GoToFirstItem(); + vtkAppendPolyData* append = vtkAppendPolyData::New(); + while (!iter->IsDoneWithTraversal()) + { + vtkDataSet* ds = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject()); + if (ds) + { + vtkGeometryFilter* geom = vtkGeometryFilter::New(); + geom->SetInput(ds); + geom->Update(); + append->AddInput(geom->GetOutput()); + geom->Delete(); + } + iter->GoToNextItem(); + } + iter->Delete(); + append->Update(); + + output->ShallowCopy(append->GetOutput()); + + append->Delete(); + + return 1; +} + +vtkExecutive* vtkHierarchicalDataSetGeometryFilter::CreateDefaultExecutive() +{ + return vtkCompositeDataPipeline::New(); +} + +void vtkHierarchicalDataSetGeometryFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Graphics/vtkHierarchicalDataSetGeometryFilter.h b/Graphics/vtkHierarchicalDataSetGeometryFilter.h new file mode 100644 index 0000000..da3fd32 --- /dev/null +++ b/Graphics/vtkHierarchicalDataSetGeometryFilter.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalDataSetGeometryFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalDataSetGeometryFilter - extract geometry from hierarchical data +// .SECTION Description +// vtkHierarchicalDataSetGeometryFilter applies vtkGeometryFilter to all +// blocks in vtkHierarchicalDataSet. Place this filter at the end of a +// pipeline before a polydata consumer such as a polydata mapper to extract +// geometry from all blocks and append them to one polydata object. + +#ifndef __vtkHierarchicalDataSetGeometryFilter_h +#define __vtkHierarchicalDataSetGeometryFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPolyData; + +class VTK_GRAPHICS_EXPORT vtkHierarchicalDataSetGeometryFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkHierarchicalDataSetGeometryFilter *New(); + vtkTypeRevisionMacro(vtkHierarchicalDataSetGeometryFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +protected: + vtkHierarchicalDataSetGeometryFilter(); + ~vtkHierarchicalDataSetGeometryFilter(); + + virtual int FillInputPortInformation(int port, vtkInformation* info); + + // Create a default executive. + virtual vtkExecutive* CreateDefaultExecutive(); + + virtual int RequestCompositeData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +private: + vtkHierarchicalDataSetGeometryFilter(const vtkHierarchicalDataSetGeometryFilter&); // Not implemented. + void operator=(const vtkHierarchicalDataSetGeometryFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkHull.cxx b/Graphics/vtkHull.cxx new file mode 100644 index 0000000..deb5561 --- /dev/null +++ b/Graphics/vtkHull.cxx @@ -0,0 +1,845 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHull.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHull.h" + +#include "vtkCellArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPlanes.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkHull, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkHull); + +// Construct an the hull object with no planes +vtkHull::vtkHull() +{ + this->Planes = NULL; + this->PlanesStorageSize = 0; + this->NumberOfPlanes = 0; +} + +// Destructor for a hull object - remove the planes if necessary +vtkHull::~vtkHull() +{ + if ( this->Planes ) + { + delete [] this->Planes; + this->Planes = NULL; + } +} + +// Remove all planes. +void vtkHull::RemoveAllPlanes() +{ + if ( this->Planes ) + { + delete [] this->Planes; + this->Planes = NULL; + } + + this->PlanesStorageSize = 0; + this->NumberOfPlanes = 0; + this->Modified(); +} + +// Add a plane. The vector (A,B,C) is the plane normal and is from the +// plane equation Ax + By + Cz + D = 0. The normal should point outwards +// away from the center of the hull. +int vtkHull::AddPlane( double A, double B, double C ) +{ + double *tmpPointer; + int i; + double norm, dotproduct; + + // Normalize the direction, + // and make sure the vector has a length. + norm = sqrt( (double) A*A + B*B + C*C ); + if ( norm == 0.0 ) + { + vtkErrorMacro( << "Zero length vector not allowed for plane normal!" ); + return -VTK_LARGE_INTEGER; + } + A /= norm; + B /= norm; + C /= norm; + + // Check that it is at least somewhat different from the other + // planes we have so far - can't have a normalized dot product of + // nearly 1. + for ( i = 0; i < this->NumberOfPlanes; i++ ) + { + dotproduct = + A * this->Planes[i*4 + 0] + + B * this->Planes[i*4 + 1] + + C * this->Planes[i*4 + 2]; + + //If planes are parallel, we already have the plane. + //Indicate this with the appropriate return value. + if ( dotproduct > 0.99999 && dotproduct < 1.00001 ) + { + return -(i+1); + } + } + + // If adding this plane would put us over the amount of space we've + // allocated for planes, then we'll have to allocated some more space + if ( (this->NumberOfPlanes+1) >= this->PlanesStorageSize ) + { + // Hang onto the previous set of planes + tmpPointer = this->Planes; + + // Increase our storage + if ( this->PlanesStorageSize <= 0 ) + { + this->PlanesStorageSize = 100; + } + else + { + this->PlanesStorageSize *= 2; + } + this->Planes = new double [this->PlanesStorageSize * 4]; + + if ( !this->Planes ) + { + vtkErrorMacro( << "Unable to allocate space for planes" ); + this->Planes = tmpPointer; + return -VTK_LARGE_INTEGER; + } + + // Copy the planes and delete the old storage space + for ( i = 0; i < this->NumberOfPlanes*4; i++ ) + { + this->Planes[i] = tmpPointer[i]; + } + if ( tmpPointer ) + { + delete [] tmpPointer; + } + } + + // Add the plane at the end of the array. + // The fourth element doesn't actually need to be set, but it + // eliminates a purify uninitialized memory copy error if it is set + i = this->NumberOfPlanes; + this->Planes[i*4 + 0] = A; + this->Planes[i*4 + 1] = B; + this->Planes[i*4 + 2] = C; + this->Planes[i*4 + 3] = 0.0; + this->NumberOfPlanes++; + + this->Modified(); + + // Return the index to this plane so that it can be set later + return i; +} + +// Add a plane, passing the plane normal vector as a double array instead +// of three doubles. +int vtkHull::AddPlane( double plane[3] ) +{ + return this->AddPlane( plane[0], plane[1], plane[2] ); +} + +// Set a specific plane - this plane should already have been added with +// AddPlane, and the return value then used to modifiy the plane normal +// with this method. +void vtkHull::SetPlane( int i, double A, double B, double C ) +{ + double norm; + + // Make sure this is a plane that was already added + if ( i < 0 || i >= this->NumberOfPlanes ) + { + vtkErrorMacro( << "Invalid index in SetPlane" ); + return; + } + + double *plane = this->Planes + i*4; + if ( A == plane[0] && B == plane[1] && C == plane[2] ) + { + return; //no modified + } + + // Set plane that has index i. Normalize the direction, + // and make sure the vector has a length. + norm = sqrt( (double) A*A + B*B + C*C ); + if ( norm == 0.0 ) + { + vtkErrorMacro( << "Zero length vector not allowed for plane normal!" ); + return; + } + this->Planes[i*4 + 0] = A/norm; + this->Planes[i*4 + 1] = B/norm; + this->Planes[i*4 + 2] = C/norm; + + this->Modified(); +} + +// Set a specific plane (that has already been added) - passing the plane +// normal as a double array +void vtkHull::SetPlane( int i, double plane[3] ) +{ + this->SetPlane( i, plane[0], plane[1], plane[2] ); +} + +int vtkHull::AddPlane( double A, double B, double C, double D ) +{ + int i, j; + + if ( (i=this->AddPlane(A,B,C)) >= 0 ) + { + this->Planes[4*i + 3] = D; + } + else if ( i >= -this->NumberOfPlanes ) + {//pick the D that minimizes the convex set + j = -i - 1; + this->Planes[4*j + 3] = (D > this->Planes[4*j + 3] ? + D : this->Planes[4*j + 3]); + } + return i; +} + +int vtkHull::AddPlane( double plane[3], double D ) +{ + int i, j; + + if ( (i=this->AddPlane(plane[0],plane[1],plane[2])) >= 0 ) + { + this->Planes[4*i + 3] = D; + } + else if ( i >= -this->NumberOfPlanes ) + {//pick the D that minimizes the convex set + j = -i - 1; + this->Planes[4*j + 3] = (D > this->Planes[4*j + 3] ? + D : this->Planes[4*j + 3]); + } + return i; +} + +void vtkHull::SetPlane( int i, double A, double B, double C, double D ) +{ + if ( i >= 0 && i < this->NumberOfPlanes ) + { + double *plane = this->Planes + 4*i; + if ( plane[0] != A || plane[1] != B || plane[2] != C || + plane[3] != D ) + { + this->SetPlane(i, A,B,C); + plane[3] = D; + this->Modified(); + } + } +} + +void vtkHull::SetPlane( int i, double plane[3], double D ) +{ + this->SetPlane(i, plane[0], plane[1], plane[2], D); +} + +void vtkHull::SetPlanes( vtkPlanes *planes ) +{ + this->RemoveAllPlanes(); + + // Add the planes to the hull + if ( planes ) + { + int i, idx; + vtkPoints *points = planes->GetPoints(); + vtkDataArray *normals = planes->GetNormals(); + if ( points && normals ) + { + for (i=0; iGetNumberOfPlanes(); i++) + { + double point[3]; + points->GetPoint(i, point); + if ( (idx=this->AddPlane(normals->GetTuple(i))) >= 0) + { + idx *= 4; + this->Planes[idx + 3] = -(this->Planes[idx]*point[0] + + this->Planes[idx+1]*point[1] + + this->Planes[idx+2]*point[2]); + } + + else if ( idx >= -this->NumberOfPlanes ) + { //planes are parallel, take the one that minimizes the convex set + idx = -4*(idx+1); + double D = -(this->Planes[idx]*point[0] + + this->Planes[idx+1]*point[1] + + this->Planes[idx+2]*point[2]); + this->Planes[idx + 3] = (D > this->Planes[idx + 3] ? + D : this->Planes[idx + 3]); + + }//special parallel planes case + }//for all planes + }//if points and normals + }//if planes defined + + return; +} + +// Add the six planes that represent the faces on a cube +void vtkHull::AddCubeFacePlanes() +{ + this->AddPlane( 1.0, 0.0, 0.0 ); + this->AddPlane( -1.0, 0.0, 0.0 ); + this->AddPlane( 0.0, 1.0, 0.0 ); + this->AddPlane( 0.0, -1.0, 0.0 ); + this->AddPlane( 0.0, 0.0, 1.0 ); + this->AddPlane( 0.0, 0.0, -1.0 ); +} + +// Add the twelve planes that represent the edges on a cube - halfway between +// the two adjacent face planes +void vtkHull::AddCubeEdgePlanes() +{ + this->AddPlane( 1.0, 1.0, 0.0 ); + this->AddPlane( 1.0, -1.0, 0.0 ); + this->AddPlane( -1.0, 1.0, 0.0 ); + this->AddPlane( -1.0, -1.0, 0.0 ); + this->AddPlane( 1.0, 0.0, 1.0 ); + this->AddPlane( 1.0, 0.0, -1.0 ); + this->AddPlane( -1.0, 0.0, 1.0 ); + this->AddPlane( -1.0, 0.0, -1.0 ); + this->AddPlane( 0.0, 1.0, 1.0 ); + this->AddPlane( 0.0, 1.0, -1.0 ); + this->AddPlane( 0.0, -1.0, 1.0 ); + this->AddPlane( 0.0, -1.0, -1.0 ); +} + +// Add the eight planes that represent the vertices on a cube - partway +// between the three adjacent face planes. +void vtkHull::AddCubeVertexPlanes() +{ + this->AddPlane( 1.0, 1.0, 1.0 ); + this->AddPlane( 1.0, 1.0, -1.0 ); + this->AddPlane( 1.0, -1.0, 1.0 ); + this->AddPlane( 1.0, -1.0, -1.0 ); + this->AddPlane( -1.0, 1.0, 1.0 ); + this->AddPlane( -1.0, 1.0, -1.0 ); + this->AddPlane( -1.0, -1.0, 1.0 ); + this->AddPlane( -1.0, -1.0, -1.0 ); +} + +// Add the planes that represent the normals of the vertices of a +// polygonal sphere formed by recursively subdividing the triangles in +// an octahedron. Each triangle is subdivided by connecting the +// midpoints of the edges thus forming 4 smaller triangles. The level +// indicates how many subdivisions to do with a level of 0 used to add +// the 6 planes from the original octahedron, level 1 will add 18 +// planes, and so on. +void vtkHull::AddRecursiveSpherePlanes( int level ) +{ + int numTriangles; + double *points; + int *triangles; + int *validPoint; + int triCount, pointCount; + int i, j, k, loop, limit; + double midpoint[3][3]; + double midindex[3]; + int A, B, C; + + if ( level < 0 ) + { + vtkErrorMacro( << "Cannot have a level less than 0!" ); + return; + } + + if ( level > 10 ) + { + vtkErrorMacro( << "Cannot have a level greater than 10!" ); + return; + } + + numTriangles = (int)(8*pow( 4.0, (double)level )); + + // Create room for the triangles and points + // We will also need to keep track of which points are + // duplicates so keep a validPoint array for this + points = new double[3*numTriangles]; + triangles = new int[3*numTriangles]; + validPoint = new int[3*numTriangles]; + + + // Add the initial points + i = 0; + points[i++] = 0.0; points[i++] = 1.0; points[i++] = 0.0; + points[i++] = -1.0; points[i++] = 0.0; points[i++] = 0.0; + points[i++] = 0.0; points[i++] = 0.0; points[i++] = -1.0; + points[i++] = 1.0; points[i++] = 0.0; points[i++] = 0.0; + points[i++] = 0.0; points[i++] = 0.0; points[i++] = 1.0; + points[i++] = 0.0; points[i++] = -1.0; points[i++] = 0.0; + pointCount = i / 3; + + // Add the initial triangles + i = 0; + triangles[i++] = 0; triangles[i++] = 1; triangles[i++] = 2; + triangles[i++] = 0; triangles[i++] = 2; triangles[i++] = 3; + triangles[i++] = 0; triangles[i++] = 3; triangles[i++] = 4; + triangles[i++] = 0; triangles[i++] = 4; triangles[i++] = 1; + triangles[i++] = 5; triangles[i++] = 1; triangles[i++] = 2; + triangles[i++] = 5; triangles[i++] = 2; triangles[i++] = 3; + triangles[i++] = 5; triangles[i++] = 3; triangles[i++] = 4; + triangles[i++] = 5; triangles[i++] = 4; triangles[i++] = 1; + triCount = i / 3; + + // loop over the levels adding points and triangles + for ( loop = 0; loop < level; loop++ ) + { + limit = triCount; + for ( i = 0; i < limit; i++ ) + { + for ( j = 0; j < 3; j++ ) + { + A = j; + B = (j+1) % 3; + for ( k = 0; k < 3; k++ ) + { + midpoint[j][k] = ( points[3*triangles[i*3 + A] + k] + + points[3*triangles[i*3 + B] + k] ) * 0.5; + points[pointCount*3 + k] = midpoint[j][k]; + } + midindex[j] = pointCount; + pointCount++; + } + A = triangles[i*3 + 0]; + B = triangles[i*3 + 1]; + C = triangles[i*3 + 2]; + + // Add the middle triangle in place of the one we just processed + triangles[i*3 + 0] = (int)(midindex[0]); + triangles[i*3 + 1] = (int)(midindex[1]); + triangles[i*3 + 2] = (int)(midindex[2]); + + // Now add the 3 outer triangles at the end of the triangle list + triangles[triCount*3 + 0] = (int)(midindex[0]); + triangles[triCount*3 + 1] = B; + triangles[triCount*3 + 2] = (int)(midindex[1]); + triCount++; + + triangles[triCount*3 + 0] = (int)(midindex[1]); + triangles[triCount*3 + 1] = C; + triangles[triCount*3 + 2] = (int)(midindex[2]); + triCount++; + + triangles[triCount*3 + 0] = (int)(midindex[2]); + triangles[triCount*3 + 1] = A; + triangles[triCount*3 + 2] = (int)(midindex[0]); + triCount++; + } + } + + // Mark duplicate points as invalid so that we don't try to add the + // same plane twice + for ( i = 0; i < pointCount; i++ ) + { + validPoint[i] = 1; + for ( j = 0; j < i; j++ ) + { + if ( fabs((double)(points[i*3 + 0] - points[j*3 + 0])) < 0.001 && + fabs((double)(points[i*3 + 1] - points[j*3 + 1])) < 0.001 && + fabs((double)(points[i*3 + 2] - points[j*3 + 2])) < 0.001 ) + { + validPoint[i] = 0; + break; + } + } + } + for ( i = 0; i < pointCount; i++ ) + { + if ( validPoint[i] ) + { + this->AddPlane( points[i*3 + 0], points[i*3 + 1], points[i*3 + 2] ); + } + } + + delete [] points; + delete [] triangles; + delete [] validPoint; + +} + +// Create the n-sided convex hull from the input geometry according to the +// set of planes. +int vtkHull::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPoints; + vtkPoints *outPoints; + vtkCellArray *outPolys; + double *bounds = input->GetBounds(); + + // Get the number of points in the input data + numPoints = input->GetNumberOfPoints(); + + // There should be at least three points for this to work. + if ( numPoints < 3 ) + { + vtkErrorMacro( << "There must be >= 3 points in the input data!!!\n" ); + return 1; + } + + // There should be at least four planes for this to work. There will need + // to be more planes than four if any of them are parallel. + if ( this->NumberOfPlanes < 4 ) + { + vtkErrorMacro( << "There must be >= 4 planes!!!\n" ); + return 1; + } + + // Create a new set of points and polygons into which the results will + // be stored + outPoints = vtkPoints::New(); + outPolys = vtkCellArray::New(); + + // Compute the D value for each plane according to the vertices in the + // geometry + this->ComputePlaneDistances(input); + this->UpdateProgress(0.25); + + // Create a large polygon representing each plane, and clip that polygon + // against all other planes to form the polygons of the hull. + this->ClipPolygonsFromPlanes( outPoints, outPolys, bounds ); + this->UpdateProgress(0.80); + + // Set the output vertices and polygons + output->SetPoints( outPoints ); + output->SetPolys( outPolys ); + + // Delete the temporary storage + outPoints->Delete(); + outPolys->Delete(); + + return 1; +} + +// Compute the D value for each plane. This is the largest D value obtained +// by passing a plane with the specified normal through each vertex in the +// geometry. This plane will have a normal pointing in towards the center of +// the hull. +void vtkHull::ComputePlaneDistances(vtkPolyData *input) +{ + vtkIdType i; + int j; + double coord[3]; + double v; + + // Initialize all planes to the first vertex value + input->GetPoint( 0, coord ); + for ( j = 0; j < this->NumberOfPlanes; j++ ) + { + this->Planes[j*4 + 3] = -( this->Planes[j*4 + 0] * coord[0] + + this->Planes[j*4 + 1] * coord[1] + + this->Planes[j*4 + 2] * coord[2] ); + } + // For all other vertices in the geometry, check if it produces a larger + // D value for each of the planes. + for ( i = 1; i < input->GetNumberOfPoints(); i++ ) + { + input->GetPoint( i, coord ); + for ( j = 0; j < this->NumberOfPlanes; j++ ) + { + v = -( this->Planes[j*4 + 0] * coord[0] + + this->Planes[j*4 + 1] * coord[1] + + this->Planes[j*4 + 2] * coord[2] ); + // negative means further in + direction of plane + if ( v < this->Planes[j*4 + 3] ) + { + this->Planes[j*4 + 3] = v; + } + } + } +} + +// Given the set of planes, create a large polygon for each, then use all the +// other planes to clip this polygon. +void vtkHull::ClipPolygonsFromPlanes( vtkPoints *outPoints, + vtkCellArray *outPolys, + double *bounds) +{ + int i, j, k, q; + double previousD, d, crosspoint; + double *verts, *newVerts, *tmpVerts; + int vertCount, newVertCount; + vtkIdType *pnts; + + // Use two arrays to store the vertices of the polygon + verts = new double[3*(this->NumberOfPlanes+1)]; + newVerts = new double[3*(this->NumberOfPlanes+1)]; + + // We need an array to store the indices for the polygon + pnts = new vtkIdType[this->NumberOfPlanes-1]; + + // We have no vertices yet + //vertCount = 0; + + // For each plane, create a polygon (if it gets completely clipped there + // won't be a polygon) + for ( i = 0; i < this->NumberOfPlanes; i++ ) + { + // Create the initial polygon - this is a large square around the + // projected center of the object (projected onto this plane). We + // now have four vertices. + this->CreateInitialPolygon( verts, i, bounds ); + vertCount = 4; + + // Clip this polygon by each plane. + for ( j = 0; j < this->NumberOfPlanes; j++ ) + { + // Stop if we have removed too many vertices and no longer have + // a polygon + if ( vertCount <= 2 ) + { + break; + } + // Otherwise, if this is not the plane we are working on, clip + // it by this plane. + if ( i != j ) + { + // Test each pair of vertices to make sure this edge + // isn't clipped. If the d values are different, it is + // clipped - find the crossing point and add that as + // a new vertex. If the second vertex's d is greater than 0, + // then keep this vertex. + newVertCount = 0; + previousD = + this->Planes[j*4 + 0] * verts[(vertCount-1)*3 + 0] + + this->Planes[j*4 + 1] * verts[(vertCount-1)*3 + 1] + + this->Planes[j*4 + 2] * verts[(vertCount-1)*3 + 2] + + this->Planes[j*4 + 3]; + + for ( k = 0; k < vertCount; k++ ) + { + d = + this->Planes[j*4 + 0] * verts[k*3 + 0] + + this->Planes[j*4 + 1] * verts[k*3 + 1] + + this->Planes[j*4 + 2] * verts[k*3 + 2] + + this->Planes[j*4 + 3]; + + if ( (previousD < 0.0) != (d < 0.0) ) + { + if ( k > 0 ) + { + q = k - 1; + } + else + { + q = vertCount - 1; + } + + crosspoint = -previousD / (d - previousD); + newVerts[newVertCount*3 + 0] = + verts[q*3+0] + crosspoint*(verts[k*3+0] - verts[q*3+0]); + newVerts[newVertCount*3 + 1] = + verts[q*3+1] + crosspoint*(verts[k*3+1] - verts[q*3+1]); + newVerts[newVertCount*3 + 2] = + verts[q*3+2] + crosspoint*(verts[k*3+2] - verts[q*3+2]); + newVertCount++; + } + + if ( d < 0.0 ) + { + newVerts[newVertCount*3 + 0] = verts[k*3 + 0]; + newVerts[newVertCount*3 + 1] = verts[k*3 + 1]; + newVerts[newVertCount*3 + 2] = verts[k*3 + 2]; + newVertCount++; + } + + previousD = d; + } //for all vertices of this plane + tmpVerts = newVerts; + newVerts = verts; + verts = tmpVerts; + vertCount = newVertCount; + } + } //for each potentially intersecting plane + + if ( vertCount > 0 ) + { + for ( j = 0; j < vertCount; j++ ) + { + pnts[j] = outPoints->InsertNextPoint( (verts + j*3) ); + } + outPolys->InsertNextCell( vertCount, pnts ); + } + } //for each plane + + delete [] verts; + delete [] newVerts; + delete [] pnts; +} + +void vtkHull::CreateInitialPolygon( double *verts, int i, double *bounds) +{ + double center[3], d, planeCenter[3]; + double v1[3], v2[3], norm, dotProduct; + int j; + + center[0] = ( bounds[0] + bounds[1] ) * 0.5; + center[1] = ( bounds[2] + bounds[3] ) * 0.5; + center[2] = ( bounds[4] + bounds[5] ) * 0.5; + + d = + this->Planes[i*4 + 0] * center[0] + + this->Planes[i*4 + 1] * center[1] + + this->Planes[i*4 + 2] * center[2] + + this->Planes[i*4 + 3]; + + planeCenter[0] = center[0] - d * this->Planes[i*4 + 0]; + planeCenter[1] = center[1] - d * this->Planes[i*4 + 1]; + planeCenter[2] = center[2] - d * this->Planes[i*4 + 2]; + + dotProduct = 1.0; + j = i; + while (dotProduct > 0.99999 || dotProduct < -0.99999) + { + j++; + if ( j >= this->NumberOfPlanes ) + { + j = 0; + } + dotProduct = + this->Planes[i*4 + 0] * this->Planes[j*4 + 0] + + this->Planes[i*4 + 1] * this->Planes[j*4 + 1] + + this->Planes[i*4 + 2] * this->Planes[j*4 + 2]; + } + + v1[0] = + this->Planes[j*4 + 1] * this->Planes[i*4 + 2] - + this->Planes[j*4 + 2] * this->Planes[i*4 + 1]; + v1[1] = + this->Planes[j*4 + 2] * this->Planes[i*4 + 0] - + this->Planes[j*4 + 0] * this->Planes[i*4 + 2]; + v1[2] = + this->Planes[j*4 + 0] * this->Planes[i*4 + 1] - + this->Planes[j*4 + 1] * this->Planes[i*4 + 0]; + + norm = sqrt( (v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]) ); + v1[0] /= norm; + v1[1] /= norm; + v1[2] /= norm; + + v2[0] = + v1[1] * this->Planes[i*4 + 2] - + v1[2] * this->Planes[i*4 + 1]; + v2[1] = + v1[2] * this->Planes[i*4 + 0] - + v1[0] * this->Planes[i*4 + 2]; + v2[2] = + v1[0] * this->Planes[i*4 + 1] - + v1[1] * this->Planes[i*4 + 0]; + + norm = sqrt( (double) (v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]) ); + v2[0] /= norm; + v2[1] /= norm; + v2[2] /= norm; + + d = + (bounds[1] - bounds[0]) + + (bounds[3] - bounds[2]) + + (bounds[5] - bounds[4]); + + verts[0*3 + 0] = planeCenter[0] - d * v1[0] - d * v2[0]; + verts[0*3 + 1] = planeCenter[1] - d * v1[1] - d * v2[1]; + verts[0*3 + 2] = planeCenter[2] - d * v1[2] - d * v2[2]; + + verts[1*3 + 0] = planeCenter[0] - d * v1[0] + d * v2[0]; + verts[1*3 + 1] = planeCenter[1] - d * v1[1] + d * v2[1]; + verts[1*3 + 2] = planeCenter[2] - d * v1[2] + d * v2[2]; + + verts[2*3 + 0] = planeCenter[0] + d * v1[0] + d * v2[0]; + verts[2*3 + 1] = planeCenter[1] + d * v1[1] + d * v2[1]; + verts[2*3 + 2] = planeCenter[2] + d * v1[2] + d * v2[2]; + + verts[3*3 + 0] = planeCenter[0] + d * v1[0] - d * v2[0]; + verts[3*3 + 1] = planeCenter[1] + d * v1[1] - d * v2[1]; + verts[3*3 + 2] = planeCenter[2] + d * v1[2] - d * v2[2]; + +} + +void vtkHull::GenerateHull(vtkPolyData *pd, double xmin, double xmax, + double ymin, double ymax, double zmin, double zmax) +{ + double bounds[6]; + bounds[0] = xmin; bounds[1] = xmax; + bounds[2] = ymin; bounds[3] = ymax; + bounds[4] = zmin; bounds[5] = zmax; + + this->GenerateHull(pd, bounds); +} + +void vtkHull::GenerateHull(vtkPolyData *pd, double *bounds) +{ + vtkPoints *newPoints; + vtkCellArray *newPolys; + + // There should be at least four planes for this to work. There will need + // to be more planes than four if any of them are parallel. + if ( this->NumberOfPlanes < 4 ) + { + vtkErrorMacro( << "There must be >= 4 planes!!!" ); + return; + } + + // Create a new set of points and polygons into which the results will + // be stored + newPoints = vtkPoints::New(); + newPoints->Allocate(this->NumberOfPlanes*3); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(this->NumberOfPlanes,3)); + + this->ClipPolygonsFromPlanes( newPoints, newPolys, bounds ); + + pd->SetPoints(newPoints); + pd->SetPolys(newPolys); + newPoints->Delete(); + newPolys->Delete(); + + pd->Squeeze(); +} + +// Print the object +void vtkHull::PrintSelf(ostream& os, vtkIndent indent) +{ + int i; + + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Planes: " << this->NumberOfPlanes << endl; + + for ( i = 0; i < this->NumberOfPlanes; i++ ) + { + os << indent << "Plane " << i << ": " + << this->Planes[i*4] << " " + << this->Planes[i*4+1] << " " + << this->Planes[i*4+2] << " " + << this->Planes[i*4+3] << endl; + } +} diff --git a/Graphics/vtkHull.h b/Graphics/vtkHull.h new file mode 100644 index 0000000..b255c72 --- /dev/null +++ b/Graphics/vtkHull.h @@ -0,0 +1,176 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHull.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHull - produce an n-sided convex hull +// .SECTION Description +// vtkHull is a filter which will produce an n-sided convex hull given a +// set of n planes. (The convex hull bounds the input polygonal data.) +// The hull is generated by squeezing the planes towards the input +// vtkPolyData, until the planes just touch the vtkPolyData. Then, +// the resulting planes are used to generate a polyhedron (i.e., hull) +// that is represented by triangles. +// +// The n planes can be defined in a number of ways including 1) manually +// specifying each plane; 2) choosing the six face planes of the input's +// bounding box; 3) choosing the eight vertex planes of the input's +// bounding box; 4) choosing the twelve edge planes of the input's +// bounding box; and/or 5) using a recursively subdivided octahedron. +// Note that when specifying planes, the plane normals should point +// outside of the convex region. +// +// The output of this filter can be used in combination with vtkLODActor +// to represent a levels-of-detail in the LOD hierarchy. Another use of +// this class is to manually specify the planes, and then generate the +// polyhedron from the planes (without squeezing the planes towards the +// input). The method GenerateHull() is used to do this. + +#ifndef __vtkHull_h +#define __vtkHull_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkPlanes; +class vtkPoints; +class vtkPolyData; + +class VTK_GRAPHICS_EXPORT vtkHull : public vtkPolyDataAlgorithm +{ +public: + static vtkHull *New(); + vtkTypeRevisionMacro(vtkHull,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Remove all planes from the current set of planes. + void RemoveAllPlanes( void ); + + // Description: + // Add a plane to the current set of planes. It will be added at the + // end of the list, and an index that can later be used to set this + // plane's normal will be returned. The values A, B, C are from the + // plane equation Ax + By + Cz + D = 0. This vector does not have to + // have unit length (but it must have a non-zero length!). If a value + // 0 > i >= -NumberOfPlanes is returned, then the plane is parallel + // with a previously inserted plane, and |-i-1| is the index of the + // plane that was previously inserted. If a value i < -NumberOfPlanes + // is returned, then the plane normal is zero length. + int AddPlane( double A, double B, double C ); + int AddPlane( double plane[3] ); + + // Description: + // Set the normal values for plane i. This is a plane that was already + // added to the current set of planes with AddPlane(), and is now being + // modified. The values A, B, C are from the plane equation + // Ax + By + Cz + D = 0. This vector does not have to have unit length. + // Note that D is set to zero, except in the case of the method taking + // a vtkPlanes* argument, where it is set to the D value defined there. + void SetPlane( int i, double A, double B, double C ); + void SetPlane( int i, double plane[3] ); + + // Description: + // Variations of AddPlane()/SetPlane() that allow D to be set. These + // methods are used when GenerateHull() is used. + int AddPlane( double A, double B, double C, double D ); + int AddPlane( double plane[3], double D ); + void SetPlane( int i, double A, double B, double C, double D ); + void SetPlane( int i, double plane[3], double D ); + + // Description: + // Set all the planes at once using a vtkPlanes implicit function. + // This also sets the D value, so it can be used with GenerateHull(). + void SetPlanes( vtkPlanes *planes ); + + // Description: + // Get the number of planes in the current set of planes. + vtkGetMacro( NumberOfPlanes, int ); + + // Description: + // Add the 8 planes that represent the vertices of a cube - the combination + // of the three face planes connecting to a vertex - (1,1,1), (1,1,-1), + // (1,-1,1), (1,-1,1), (-1,1,1), (-1,1,-1), (-1,-1,1), (-1,-1-1). + void AddCubeVertexPlanes(); + + // Description: + // Add the 12 planes that represent the edges of a cube - halfway between + // the two connecting face planes - (1,1,0), (-1,-1,0), (-1,1,0), (1,-1,0), + // (0,1,1), (0,-1,-1), (0,1,-1), (0,-1,1), (1,0,1), (-1,0,-1), + // (1,0,-1), (-1,0,1) + void AddCubeEdgePlanes(); + + // Description: + // Add the six planes that make up the faces of a cube - (1,0,0), + // (-1, 0, 0), (0,1,0), (0,-1,0), (0,0,1), (0,0,-1) + void AddCubeFacePlanes(); + + // Description: + // Add the planes that represent the normals of the vertices of a + // polygonal sphere formed by recursively subdividing the triangles + // in an octahedron. Each triangle is subdivided by connecting the + // midpoints of the edges thus forming 4 smaller triangles. The + // level indicates how many subdivisions to do with a level of 0 + // used to add the 6 planes from the original octahedron, level 1 + // will add 18 planes, and so on. + void AddRecursiveSpherePlanes( int level ); + + // Description: + // A special method that is used to generate a polyhedron directly + // from a set of n planes. The planes that are supplied by the user + // are not squeezed towards the input data (in fact the user need + // not specify an input). To use this method, you must provide an + // instance of vtkPolyData into which the points and cells defining + // the polyhedron are placed. You must also provide a bounding box + // where you expect the resulting polyhedron to lie. This can be + // a very generous fit, it's only used to create the initial polygons + // that are eventually clipped. + void GenerateHull(vtkPolyData *pd, double *bounds); + void GenerateHull(vtkPolyData *pd, double xmin, double xmax, + double ymin, double ymax, double zmin, double zmax); + +protected: + vtkHull(); + ~vtkHull(); + + // The planes - 4 doubles per plane for A, B, C, D + double *Planes; + + // This indicates the current size (in planes - 4*sizeof(double)) of + // the this->Planes array. Planes are allocated in chunks so that the + // array does not need to be reallocated every time a new plane is added + int PlanesStorageSize; + + // The number of planes that have been added + int NumberOfPlanes; + + // Internal method used to find the position of each plane + void ComputePlaneDistances(vtkPolyData *input); + + // Internal method used to create the actual polygons from the set + // of planes + void ClipPolygonsFromPlanes( vtkPoints *points, vtkCellArray *polys, + double *bounds ); + + // Internal method used to create the initial "big" polygon from the + // plane equation. This polygon is clipped by all other planes to form + // the final polygon (or it may be clipped entirely) + void CreateInitialPolygon( double *, int, double * ); + + // The method that does it all... + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); +private: + vtkHull(const vtkHull&); // Not implemented. + void operator=(const vtkHull&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkHyperStreamline.cxx b/Graphics/vtkHyperStreamline.cxx new file mode 100644 index 0000000..834192f --- /dev/null +++ b/Graphics/vtkHyperStreamline.cxx @@ -0,0 +1,864 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHyperStreamline.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkHyperStreamline.h" + +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkHyperStreamline, "$Revision: 1.60 $"); +vtkStandardNewMacro(vtkHyperStreamline); + +// +// Special classes for manipulating data +//BTX +class vtkHyperPoint { //;prevent man page generation +public: + vtkHyperPoint(); // method sets up storage + vtkHyperPoint &operator=(const vtkHyperPoint& hp); //for resizing + + double X[3]; // position + vtkIdType CellId; // cell + int SubId; // cell sub id + double P[3]; // parametric coords in cell + double W[3]; // eigenvalues (sorted in decreasing value) + double *V[3]; // pointers to eigenvectors (also sorted) + double V0[3]; // storage for eigenvectors + double V1[3]; + double V2[3]; + double S; // scalar value + double D; // distance travelled so far +}; +//ETX + +class vtkHyperArray { //;prevent man page generation +public: + vtkHyperArray(); + ~vtkHyperArray() + { + if (this->Array) + { + delete [] this->Array; + } + }; + vtkIdType GetNumberOfPoints() {return this->MaxId + 1;}; + vtkHyperPoint *GetHyperPoint(vtkIdType i) {return this->Array + i;}; + vtkHyperPoint *InsertNextHyperPoint() + { + if ( ++this->MaxId >= this->Size ) + { + this->Resize(this->MaxId); + } + return this->Array + this->MaxId; + } + vtkHyperPoint *Resize(vtkIdType sz); //reallocates data + void Reset() {this->MaxId = -1;}; + + vtkHyperPoint *Array; // pointer to data + vtkIdType MaxId; // maximum index inserted thus far + vtkIdType Size; // allocated size of data + vtkIdType Extend; // grow array by this amount + double Direction; // integration direction +}; + +#define VTK_START_FROM_POSITION 0 +#define VTK_START_FROM_LOCATION 1 + +vtkHyperPoint::vtkHyperPoint() +{ + this->V[0] = this->V0; + this->V[1] = this->V1; + this->V[2] = this->V2; +} + +vtkHyperPoint& vtkHyperPoint::operator=(const vtkHyperPoint& hp) +{ + int i, j; + + for (i=0; i<3; i++) + { + this->X[i] = hp.X[i]; + this->P[i] = hp.P[i]; + this->W[i] = hp.W[i]; + for (j=0; j<3; j++) + { + this->V[j][i] = hp.V[j][i]; + } + } + this->CellId = hp.CellId; + this->SubId = hp.SubId; + this->S = hp.S; + this->D = hp.D; + + return *this; +} + +vtkHyperArray::vtkHyperArray() +{ + this->MaxId = -1; + this->Array = new vtkHyperPoint[1000]; + this->Size = 1000; + this->Extend = 5000; + this->Direction = VTK_INTEGRATE_FORWARD; +} + +vtkHyperPoint *vtkHyperArray::Resize(vtkIdType sz) +{ + vtkHyperPoint *newArray; + vtkIdType newSize, i; + + if (sz >= this->Size) + { + newSize = this->Size + + this->Extend*(((sz-this->Size)/this->Extend)+1); + } + else + { + newSize = sz; + } + + newArray = new vtkHyperPoint[newSize]; + + for (i=0; iArray[i]; + } + + this->Size = newSize; + delete [] this->Array; + this->Array = newArray; + + return this->Array; +} + +// Construct object with initial starting position (0,0,0); integration step +// length 0.2; step length 0.01; forward integration; terminal eigenvalue 0.0; +// number of sides 6; radius 0.5; and logarithmic scaling off. +vtkHyperStreamline::vtkHyperStreamline() +{ + this->StartFrom = VTK_START_FROM_POSITION; + this->StartPosition[0] = this->StartPosition[1] = this->StartPosition[2] = 0.0; + + this->StartCell = 0; + this->StartSubId = 0; + this->StartPCoords[0] = this->StartPCoords[1] = this->StartPCoords[2] = 0.5; + + this->Streamers = NULL; + + this->MaximumPropagationDistance = 100.0; + this->IntegrationStepLength = 0.2; + this->StepLength = 0.01; + this->IntegrationDirection = VTK_INTEGRATE_FORWARD; + this->TerminalEigenvalue = 0.0; + this->NumberOfSides = 6; + this->Radius = 0.5; + this->LogScaling = 0; + this->IntegrationEigenvector = VTK_INTEGRATE_MAJOR_EIGENVECTOR; +} + +vtkHyperStreamline::~vtkHyperStreamline() +{ + if ( this->Streamers ) + { + delete [] this->Streamers; + } +} + +// Specify the start of the hyperstreamline in the cell coordinate system. +// That is, cellId and subId (if composite cell), and parametric coordinates. +void vtkHyperStreamline::SetStartLocation(vtkIdType cellId, int subId, + double pcoords[3]) +{ + if ( cellId != this->StartCell || subId != this->StartSubId || + pcoords[0] != this->StartPCoords[0] || + pcoords[1] != this->StartPCoords[1] || + pcoords[2] != this->StartPCoords[2] ) + { + this->Modified(); + this->StartFrom = VTK_START_FROM_LOCATION; + + this->StartCell = cellId; + this->StartSubId = subId; + this->StartPCoords[0] = pcoords[0]; + this->StartPCoords[1] = pcoords[1]; + this->StartPCoords[2] = pcoords[2]; + } +} + +// Specify the start of the hyperstreamline in the cell coordinate system. +// That is, cellId and subId (if composite cell), and parametric coordinates. +void vtkHyperStreamline::SetStartLocation(vtkIdType cellId, int subId, + double r, double s, double t) +{ + double pcoords[3]; + pcoords[0] = r; + pcoords[1] = s; + pcoords[2] = t; + + this->SetStartLocation(cellId, subId, pcoords); +} + +// Get the starting location of the hyperstreamline in the cell coordinate +// system. Returns the cell that the starting point is in. +vtkIdType vtkHyperStreamline::GetStartLocation(int& subId, double pcoords[3]) +{ + subId = this->StartSubId; + pcoords[0] = this->StartPCoords[0]; + pcoords[1] = this->StartPCoords[1]; + pcoords[2] = this->StartPCoords[2]; + return this->StartCell; +} + +// Specify the start of the hyperstreamline in the global coordinate system. +// Starting from position implies that a search must be performed to find +// initial cell to start integration from. +void vtkHyperStreamline::SetStartPosition(double x[3]) +{ + if ( x[0] != this->StartPosition[0] || x[1] != this->StartPosition[1] || + x[2] != this->StartPosition[2] ) + { + this->Modified(); + this->StartFrom = VTK_START_FROM_POSITION; + + this->StartPosition[0] = x[0]; + this->StartPosition[1] = x[1]; + this->StartPosition[2] = x[2]; + } +} + +// Specify the start of the hyperstreamline in the global coordinate system. +// Starting from position implies that a search must be performed to find +// initial cell to start integration from. +void vtkHyperStreamline::SetStartPosition(double x, double y, double z) +{ + double pos[3]; + pos[0] = x; + pos[1] = y; + pos[2] = z; + + this->SetStartPosition(pos); +} + +// Get the start position of the hyperstreamline in global x-y-z coordinates. +double *vtkHyperStreamline::GetStartPosition() +{ + return this->StartPosition; +} + +// Make sure coordinate systems are consistent +static void FixVectors(double **prev, double **current, int iv, int ix, int iy) +{ + double p0[3], p1[3], p2[3]; + double v0[3], v1[3], v2[3]; + double temp[3]; + int i; + + for (i=0; i<3; i++) + { + v0[i] = current[i][iv]; + v1[i] = current[i][ix]; + v2[i] = current[i][iy]; + } + + if ( prev == NULL ) //make sure coord system is right handed + { + vtkMath::Cross(v0,v1,temp); + if ( vtkMath::Dot(v2,temp) < 0.0 ) + { + for (i=0; i<3; i++) + { + current[i][iy] *= -1.0; + } + } + } + + else //make sure vectors consistent from one point to the next + { + for (i=0; i<3; i++) + { + p0[i] = prev[i][iv]; + p1[i] = prev[i][ix]; + p2[i] = prev[i][iy]; + } + if ( vtkMath::Dot(p0,v0) < 0.0 ) + { + for (i=0; i<3; i++) + { + current[i][iv] *= -1.0; + } + } + if ( vtkMath::Dot(p1,v1) < 0.0 ) + { + for (i=0; i<3; i++) + { + current[i][ix] *= -1.0; + } + } + if ( vtkMath::Dot(p2,v2) < 0.0 ) + { + for (i=0; i<3; i++) + { + current[i][iy] *= -1.0; + } + } + } +} + +int vtkHyperStreamline::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(); + vtkDataArray *inScalars; + vtkDataArray *inTensors; + double tensor[9]; + vtkHyperPoint *sNext, *sPtr; + int i, j, k, ptId, subId, iv, ix, iy; + vtkCell *cell; + double ev[3], xNext[3]; + double d, step, dir, tol2, p[3]; + double *w; + double dist2; + double closestPoint[3]; + double *m[3], *v[3]; + double m0[3], m1[3], m2[3]; + double v0[3], v1[3], v2[3]; + vtkDataArray *cellTensors; + vtkDataArray *cellScalars; + // set up working matrices + v[0] = v0; v[1] = v1; v[2] = v2; + m[0] = m0; m[1] = m1; m[2] = m2; + + vtkDebugMacro(<<"Generating hyperstreamline(s)"); + this->NumberOfStreamers = 0; + + if ( ! (inTensors=pd->GetTensors()) ) + { + vtkErrorMacro(<<"No tensor data defined!"); + return 1; + } + w = new double[input->GetMaxCellSize()]; + + inScalars = pd->GetScalars(); + + cellTensors = vtkDataArray::CreateDataArray(inTensors->GetDataType()); + cellScalars = vtkDataArray::CreateDataArray(inScalars->GetDataType()); + int numComp; + if (inTensors) + { + numComp = inTensors->GetNumberOfComponents(); + cellTensors->SetNumberOfComponents(numComp); + cellTensors->SetNumberOfTuples(VTK_CELL_SIZE); + } + if (inScalars) + { + numComp = inScalars->GetNumberOfComponents(); + cellScalars->SetNumberOfComponents(numComp); + cellScalars->SetNumberOfTuples(VTK_CELL_SIZE); + } + + tol2 = input->GetLength() / 1000.0; + tol2 = tol2 * tol2; + iv = this->IntegrationEigenvector; + ix = (iv + 1) % 3; + iy = (iv + 2) % 3; + // + // Create starting points + // + this->NumberOfStreamers = 1; + + if ( this->IntegrationDirection == VTK_INTEGRATE_BOTH_DIRECTIONS ) + { + this->NumberOfStreamers *= 2; + } + + this->Streamers = new vtkHyperArray[this->NumberOfStreamers]; + + if ( this->StartFrom == VTK_START_FROM_POSITION ) + { + sPtr = this->Streamers[0].InsertNextHyperPoint(); + for (i=0; i<3; i++) + { + sPtr->X[i] = this->StartPosition[i]; + } + sPtr->CellId = input->FindCell(this->StartPosition, NULL, (-1), 0.0, + sPtr->SubId, sPtr->P, w); + } + + else //VTK_START_FROM_LOCATION + { + sPtr = this->Streamers[0].InsertNextHyperPoint(); + cell = input->GetCell(sPtr->CellId); + cell->EvaluateLocation(sPtr->SubId, sPtr->P, sPtr->X, w); + } + // + // Finish initializing each hyperstreamline + // + this->Streamers[0].Direction = 1.0; + sPtr = this->Streamers[0].GetHyperPoint(0); + sPtr->D = 0.0; + if ( sPtr->CellId >= 0 ) //starting point in dataset + { + cell = input->GetCell(sPtr->CellId); + cell->EvaluateLocation(sPtr->SubId, sPtr->P, xNext, w); + + inTensors->GetTuples(cell->PointIds, cellTensors); + + // interpolate tensor, compute eigenfunctions + for (j=0; j<3; j++) + { + for (i=0; i<3; i++) + { + m[i][j] = 0.0; + } + } + for (k=0; k < cell->GetNumberOfPoints(); k++) + { + cellTensors->GetTuple(k, tensor); + for (j=0; j<3; j++) + { + for (i=0; i<3; i++) + { + m[i][j] += tensor[i+3*j] * w[k]; + } + } + } + + vtkMath::Jacobi(m, sPtr->W, sPtr->V); + FixVectors(NULL, sPtr->V, iv, ix, iy); + + if ( inScalars ) + { + inScalars->GetTuples(cell->PointIds, cellScalars); + for (sPtr->S=0, i=0; i < cell->GetNumberOfPoints(); i++) + { + sPtr->S += cellScalars->GetTuple(i)[0] * w[i]; + } + } + + if ( this->IntegrationDirection == VTK_INTEGRATE_BOTH_DIRECTIONS ) + { + this->Streamers[1].Direction = -1.0; + sNext = this->Streamers[1].InsertNextHyperPoint(); + *sNext = *sPtr; + } + else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD ) + { + this->Streamers[0].Direction = -1.0; + } + } //for hyperstreamline in dataset + // + // For each hyperstreamline, integrate in appropriate direction (using RK2). + // + for (ptId=0; ptId < this->NumberOfStreamers; ptId++) + { + //get starting step + sPtr = this->Streamers[ptId].GetHyperPoint(0); + if ( sPtr->CellId < 0 ) + { + continue; + } + + dir = this->Streamers[ptId].Direction; + cell = input->GetCell(sPtr->CellId); + cell->EvaluateLocation(sPtr->SubId, sPtr->P, xNext, w); + step = this->IntegrationStepLength * sqrt((double)cell->GetLength2()); + inTensors->GetTuples(cell->PointIds, cellTensors); + if ( inScalars ) {inScalars->GetTuples(cell->PointIds, cellScalars);} + + //integrate until distance has been exceeded + while ( sPtr->CellId >= 0 && fabs(sPtr->W[0]) > this->TerminalEigenvalue && + sPtr->D < this->MaximumPropagationDistance ) + { + + //compute updated position using this step (Euler integration) + for (i=0; i<3; i++) + { + xNext[i] = sPtr->X[i] + dir * step * sPtr->V[i][iv]; + } + + //compute updated position using updated step + cell->EvaluatePosition(xNext, closestPoint, subId, p, dist2, w); + + //interpolate tensor + for (j=0; j<3; j++) + { + for (i=0; i<3; i++) + { + m[i][j] = 0.0; + } + } + for (k=0; k < cell->GetNumberOfPoints(); k++) + { + cellTensors->GetTuple(k, tensor); + for (j=0; j<3; j++) + { + for (i=0; i<3; i++) + { + m[i][j] += tensor[i+3*j] * w[k]; + } + } + } + + vtkMath::Jacobi(m, ev, v); + FixVectors(sPtr->V, v, iv, ix, iy); + + //now compute final position + for (i=0; i<3; i++) + { + xNext[i] = sPtr->X[i] + + dir * (step/2.0) * (sPtr->V[i][iv] + v[i][iv]); + } + sNext = this->Streamers[ptId].InsertNextHyperPoint(); + + if ( cell->EvaluatePosition(xNext, closestPoint, sNext->SubId, + sNext->P, dist2, w) ) + { //integration still in cell + for (i=0; i<3; i++) + { + sNext->X[i] = closestPoint[i]; + } + sNext->CellId = sPtr->CellId; + sNext->SubId = sPtr->SubId; + } + else + { //integration has passed out of cell + sNext->CellId = input->FindCell(xNext, cell, sPtr->CellId, tol2, + sNext->SubId, sNext->P, w); + if ( sNext->CellId >= 0 ) //make sure not out of dataset + { + for (i=0; i<3; i++) + { + sNext->X[i] = xNext[i]; + } + cell = input->GetCell(sNext->CellId); + inTensors->GetTuples(cell->PointIds, cellTensors); + if (inScalars){inScalars->GetTuples(cell->PointIds, cellScalars);} + step = this->IntegrationStepLength * sqrt((double)cell->GetLength2()); + } + } + + if ( sNext->CellId >= 0 ) + { + cell->EvaluateLocation(sNext->SubId, sNext->P, xNext, w); + for (j=0; j<3; j++) + { + for (i=0; i<3; i++) + { + m[i][j] = 0.0; + } + } + for (k=0; k < cell->GetNumberOfPoints(); k++) + { + cellTensors->GetTuple(k, tensor); + for (j=0; j<3; j++) + { + for (i=0; i<3; i++) + { + m[i][j] += tensor[i+3*j] * w[k]; + } + } + } + + vtkMath::Jacobi(m, sNext->W, sNext->V); + FixVectors(sPtr->V, sNext->V, iv, ix, iy); + + if ( inScalars ) + { + for (sNext->S=0.0, i=0; i < cell->GetNumberOfPoints(); i++) + { + sNext->S += cellScalars->GetTuple(i)[0] * w[i]; + } + } + d = sqrt((double)vtkMath::Distance2BetweenPoints(sPtr->X,sNext->X)); + sNext->D = sPtr->D + d; + } + + sPtr = sNext; + + }//for elapsed time + + } //for each hyperstreamline + + int retval = this->BuildTube(input, output); + + delete [] w; + cellTensors->Delete(); + cellScalars->Delete(); + + return retval; +} + +int vtkHyperStreamline::BuildTube(vtkDataSet *input, vtkPolyData *output) +{ + vtkHyperPoint *sPrev, *sPtr; + vtkPoints *newPts; + vtkFloatArray *newVectors; + vtkFloatArray *newNormals; + vtkFloatArray *newScalars=NULL; + vtkCellArray *newStrips; + vtkIdType i, npts, ptOffset=0; + int ptId, j, id, k, i1, i2; + double dOffset, x[3], v[3], s, r, r1[3], r2[3], stepLength; + double xT[3], sFactor, normal[3], w[3]; + double theta=2.0*vtkMath::Pi()/this->NumberOfSides; + vtkPointData *outPD; + int iv, ix, iy; + vtkIdType numIntPts; + // + // Initialize + // + vtkDebugMacro(<<"Creating hyperstreamline tube"); + if ( this->NumberOfStreamers <= 0 ) + { + return 0; + } + + stepLength = input->GetLength() * this->StepLength; + outPD = output->GetPointData(); + + iv = this->IntegrationEigenvector; + ix = (iv+1) % 3; + iy = (iv+2) % 3; + // + // Allocate + // + newPts = vtkPoints::New(); + newPts ->Allocate(2500); + if ( input->GetPointData()->GetScalars() ) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(2500); + } + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(7500); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(7500); + newStrips = vtkCellArray::New(); + newStrips->Allocate(newStrips->EstimateSize(3*this->NumberOfStreamers, + VTK_CELL_SIZE)); + // + // Loop over all hyperstreamlines generating points + // + for (ptId=0; ptId < this->NumberOfStreamers; ptId++) + { + if ( (numIntPts=this->Streamers[ptId].GetNumberOfPoints()) < 2 ) + { + continue; + } + sPrev = this->Streamers[ptId].GetHyperPoint(0); + sPtr = this->Streamers[ptId].GetHyperPoint(1); + + // compute scale factor + i = (sPrev->W[ix] > sPrev->W[iy] ? ix : iy); + if ( sPrev->W[i] == 0.0 ) + { + sFactor = 1.0; + } + else + { + sFactor = this->Radius / sPrev->W[i]; + } + + if ( numIntPts == 2 && sPtr->CellId < 0 ) + { + continue; + } + + dOffset = sPrev->D; + + for ( npts=0, i=1; i < numIntPts && sPtr->CellId >= 0; + i++, sPrev=sPtr, sPtr=this->Streamers[ptId].GetHyperPoint(i) ) + { + // + // Bracket steps and construct tube points + // + while ( dOffset >= sPrev->D && dOffset < sPtr->D ) + { + r = (dOffset - sPrev->D) / (sPtr->D - sPrev->D); + + for (j=0; j<3; j++) //compute point in center of tube + { + x[j] = sPrev->X[j] + r * (sPtr->X[j] - sPrev->X[j]); + v[j] = sPrev->V[j][iv] + r * (sPtr->V[j][iv] - sPrev->V[j][iv]); + r1[j] = sPrev->V[j][ix] + r * (sPtr->V[j][ix] - sPrev->V[j][ix]); + r2[j] = sPrev->V[j][iy] + r * (sPtr->V[j][iy] - sPrev->V[j][iy]); + w[j] = sPrev->W[j] + r * (sPtr->W[j] - sPrev->W[j]); + } + + // construct points around tube + for (k=0; k < this->NumberOfSides; k++) + { + for (j=0; j<3; j++) + { + normal[j] = w[ix]*r1[j]*cos((double)k*theta) + + w[iy]*r2[j]*sin((double)k*theta); + xT[j] = x[j] + sFactor * normal[j]; + } + id = newPts->InsertNextPoint(xT); + newVectors->InsertTuple(id,v); + vtkMath::Normalize(normal); + newNormals->InsertTuple(id,normal); + } + + if ( newScalars ) //add scalars around tube + { + s = sPrev->S + r * (sPtr->S - sPrev->S); + for (k=0; kNumberOfSides; k++) + { + newScalars->InsertNextTuple(&s); + } + } + + npts++; + dOffset += stepLength; + + } //while + } //for this hyperstreamline + + // + // Generate the strips for this hyperstreamline + // + for (k=0; kNumberOfSides; k++) + { + i1 = (k+1) % this->NumberOfSides; + newStrips->InsertNextCell(npts*2); + for (i=0; i < npts; i++) + { + //make sure strip definition consistent with normals + if (this->Streamers[ptId].Direction > 0.0) + { + i2 = i*this->NumberOfSides; + } + else + { + i2 = (npts - i - 1) * this->NumberOfSides; + } + newStrips->InsertCellPoint(ptOffset+i2+k); + newStrips->InsertCellPoint(ptOffset+i2+i1); + } + }//for all tube sides + + ptOffset += this->NumberOfSides*npts; + + } //for all hyperstreamlines + // + // Update ourselves + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetStrips(newStrips); + newStrips->Delete(); + + if ( newScalars ) + { + int idx = outPD->AddArray(newScalars); + outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + outPD->SetNormals(newNormals); + newNormals->Delete(); + + outPD->SetVectors(newVectors); + newVectors->Delete(); + + output->Squeeze(); + + return 1; +} + +int vtkHyperStreamline::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkHyperStreamline::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->StartFrom == VTK_START_FROM_POSITION ) + { + os << indent << "Starting Position: (" << this->StartPosition[0] << "," + << this->StartPosition[1] << ", " << this->StartPosition[2] << ")\n"; + } + else + { + os << indent << "Starting Location:\n\tCell: " << this->StartCell + << "\n\tSubId: " << this->StartSubId << "\n\tP.Coordinates: (" + << this->StartPCoords[0] << ", " + << this->StartPCoords[1] << ", " + << this->StartPCoords[2] << ")\n"; + } + + os << indent << "Maximum Propagation Distance: " + << this->MaximumPropagationDistance << "\n"; + + if ( this->IntegrationDirection == VTK_INTEGRATE_FORWARD ) + { + os << indent << "Integration Direction: FORWARD\n"; + } + else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD ) + { + os << indent << "Integration Direction: BACKWARD\n"; + } + else + { + os << indent << "Integration Direction: FORWARD & BACKWARD\n"; + } + + os << indent << "Integration Step Length: " << this->IntegrationStepLength << "\n"; + os << indent << "Step Length: " << this->StepLength << "\n"; + + os << indent << "Terminal Eigenvalue: " << this->TerminalEigenvalue << "\n"; + + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Number Of Sides: " << this->NumberOfSides << "\n"; + os << indent << "Logarithmic Scaling: " << (this->LogScaling ? "On\n" : "Off\n"); + + if ( this->IntegrationEigenvector == 0 ) + { + os << indent << "Integrate Along Major Eigenvector\n"; + } + else if ( this->IntegrationEigenvector == 1 ) + { + os << indent << "Integrate Along Medium Eigenvector\n"; + } + else + { + os << indent << "Integrate Along Minor Eigenvector\n"; + } +} diff --git a/Graphics/vtkHyperStreamline.h b/Graphics/vtkHyperStreamline.h new file mode 100644 index 0000000..50ef6ce --- /dev/null +++ b/Graphics/vtkHyperStreamline.h @@ -0,0 +1,262 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHyperStreamline.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHyperStreamline - generate hyperstreamline in arbitrary dataset +// .SECTION Description +// vtkHyperStreamline is a filter that integrates through a tensor field to +// generate a hyperstreamline. The integration is along the maximum eigenvector +// and the cross section of the hyperstreamline is defined by the two other +// eigenvectors. Thus the shape of the hyperstreamline is "tube-like", with +// the cross section being elliptical. Hyperstreamlines are used to visualize +// tensor fields. +// +// The starting point of a hyperstreamline can be defined in one of two ways. +// First, you may specify an initial position. This is a x-y-z global +// coordinate. The second option is to specify a starting location. This is +// cellId, subId, and cell parametric coordinates. +// +// The integration of the hyperstreamline occurs through the major eigenvector +// field. IntegrationStepLength controls the step length within each cell +// (i.e., this is the fraction of the cell length). The length of the +// hyperstreamline is controlled by MaximumPropagationDistance. This parameter +// is the length of the hyperstreamline in units of distance. The tube itself +// is composed of many small sub-tubes - NumberOfSides controls the number of +// sides in the tube, and StepLength controls the length of the sub-tubes. +// +// Because hyperstreamlines are often created near regions of singularities, it +// is possible to control the scaling of the tube cross section by using a +// logarithmic scale. Use LogScalingOn to turn this capability on. The Radius +// value controls the initial radius of the tube. + +// .SECTION See Also +// vtkTensorGlyph vtkStreamer + +#ifndef __vtkHyperStreamline_h +#define __vtkHyperStreamline_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_INTEGRATE_FORWARD 0 +#define VTK_INTEGRATE_BACKWARD 1 +#define VTK_INTEGRATE_BOTH_DIRECTIONS 2 + +#define VTK_INTEGRATE_MAJOR_EIGENVECTOR 0 +#define VTK_INTEGRATE_MEDIUM_EIGENVECTOR 1 +#define VTK_INTEGRATE_MINOR_EIGENVECTOR 2 + + +class vtkHyperArray; + +class VTK_GRAPHICS_EXPORT vtkHyperStreamline : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkHyperStreamline,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with initial starting position (0,0,0); integration + // step length 0.2; step length 0.01; forward integration; terminal + // eigenvalue 0.0; number of sides 6; radius 0.5; and logarithmic scaling + // off. + static vtkHyperStreamline *New(); + + // Description: + // Specify the start of the hyperstreamline in the cell coordinate system. + // That is, cellId and subId (if composite cell), and parametric coordinates. + void SetStartLocation(vtkIdType cellId, int subId, double pcoords[3]); + + // Description: + // Specify the start of the hyperstreamline in the cell coordinate system. + // That is, cellId and subId (if composite cell), and parametric coordinates. + void SetStartLocation(vtkIdType cellId, int subId, double r, double s, + double t); + + // Description: + // Get the starting location of the hyperstreamline in the cell coordinate + // system. Returns the cell that the starting point is in. + vtkIdType GetStartLocation(int& subId, double pcoords[3]); + + // Description: + // Specify the start of the hyperstreamline in the global coordinate system. + // Starting from position implies that a search must be performed to find + // initial cell to start integration from. + void SetStartPosition(double x[3]); + + // Description: + // Specify the start of the hyperstreamline in the global coordinate system. + // Starting from position implies that a search must be performed to find + // initial cell to start integration from. + void SetStartPosition(double x, double y, double z); + + // Description: + // Get the start position of the hyperstreamline in global x-y-z coordinates. + double *GetStartPosition(); + + // Description: + // Set / get the maximum length of the hyperstreamline expressed as absolute + // distance (i.e., arc length) value. + vtkSetClampMacro(MaximumPropagationDistance,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(MaximumPropagationDistance,double); + + // Description: + // Set / get the eigenvector field through which to ingrate. It is + // possible to integrate using the major, medium or minor + // eigenvector field. The major eigenvector is the eigenvector + // whose corresponding eigenvalue is closest to positive infinity. + // The minor eigenvector is the eigenvector whose corresponding + // eigenvalue is closest to negative infinity. The medium + // eigenvector is the eigenvector whose corresponding eigenvalue is + // between the major and minor eigenvalues. + vtkSetClampMacro(IntegrationEigenvector,int, + VTK_INTEGRATE_MAJOR_EIGENVECTOR, + VTK_INTEGRATE_MINOR_EIGENVECTOR); + vtkGetMacro(IntegrationEigenvector,int); + void SetIntegrationEigenvectorToMajor() + {this->SetIntegrationEigenvector(VTK_INTEGRATE_MAJOR_EIGENVECTOR);}; + void SetIntegrationEigenvectorToMedium() + {this->SetIntegrationEigenvector(VTK_INTEGRATE_MEDIUM_EIGENVECTOR);}; + void SetIntegrationEigenvectorToMinor() + {this->SetIntegrationEigenvector(VTK_INTEGRATE_MINOR_EIGENVECTOR);}; + + // Description: + // Use the major eigenvector field as the vector field through which + // to integrate. The major eigenvector is the eigenvector whose + // corresponding eigenvalue is closest to positive infinity. + void IntegrateMajorEigenvector() + {this->SetIntegrationEigenvectorToMajor();}; + + // Description: + // Use the medium eigenvector field as the vector field through which + // to integrate. The medium eigenvector is the eigenvector whose + // corresponding eigenvalue is between the major and minor + // eigenvalues. + void IntegrateMediumEigenvector() + {this->SetIntegrationEigenvectorToMedium();}; + + // Description: + // Use the minor eigenvector field as the vector field through which + // to integrate. The minor eigenvector is the eigenvector whose + // corresponding eigenvalue is closest to negative infinity. + void IntegrateMinorEigenvector() + {this->SetIntegrationEigenvectorToMinor();}; + + // Description: + // Set / get a nominal integration step size (expressed as a fraction of + // the size of each cell). + vtkSetClampMacro(IntegrationStepLength,double,0.001,0.5); + vtkGetMacro(IntegrationStepLength,double); + + // Description: + // Set / get the length of a tube segment composing the + // hyperstreamline. The length is specified as a fraction of the + // diagonal length of the input bounding box. + vtkSetClampMacro(StepLength,double,0.000001,1.0); + vtkGetMacro(StepLength,double); + + // Description: + // Specify the direction in which to integrate the hyperstreamline. + vtkSetClampMacro(IntegrationDirection,int, + VTK_INTEGRATE_FORWARD,VTK_INTEGRATE_BOTH_DIRECTIONS); + vtkGetMacro(IntegrationDirection,int); + void SetIntegrationDirectionToForward() + {this->SetIntegrationDirection(VTK_INTEGRATE_FORWARD);}; + void SetIntegrationDirectionToBackward() + {this->SetIntegrationDirection(VTK_INTEGRATE_BACKWARD);}; + void SetIntegrationDirectionToIntegrateBothDirections() + {this->SetIntegrationDirection(VTK_INTEGRATE_BOTH_DIRECTIONS);}; + + // Description: + // Set/get terminal eigenvalue. If major eigenvalue falls below this + // value, hyperstreamline terminates propagation. + vtkSetClampMacro(TerminalEigenvalue,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(TerminalEigenvalue,double); + + // Description: + // Set / get the number of sides for the hyperstreamlines. At a minimum, + // number of sides is 3. + vtkSetClampMacro(NumberOfSides,int,3,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfSides,int); + + // Description: + // Set / get the initial tube radius. This is the maximum "elliptical" + // radius at the beginning of the tube. Radius varies based on ratio of + // eigenvalues. Note that tube section is actually elliptical and may + // become a point or line in cross section in some cases. + vtkSetClampMacro(Radius,double,0.0001,VTK_DOUBLE_MAX); + vtkGetMacro(Radius,double); + + // Description: + // Turn on/off logarithmic scaling. If scaling is on, the log base 10 + // of the computed eigenvalues are used to scale the cross section radii. + vtkSetMacro(LogScaling,int); + vtkGetMacro(LogScaling,int); + vtkBooleanMacro(LogScaling,int); + +protected: + vtkHyperStreamline(); + ~vtkHyperStreamline(); + + // Integrate data + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int BuildTube(vtkDataSet *input, vtkPolyData *output); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + // Flag indicates where streamlines start from (either position or location) + int StartFrom; + + // Starting from cell location + vtkIdType StartCell; + int StartSubId; + double StartPCoords[3]; + + // starting from global x-y-z position + double StartPosition[3]; + + //array of hyperstreamlines + vtkHyperArray *Streamers; + int NumberOfStreamers; + + // length of hyperstreamline in absolute distance + double MaximumPropagationDistance; + + // integration direction + int IntegrationDirection; + + // the length (fraction of cell size) of integration steps + double IntegrationStepLength; + + // the length of the tube segments composing the hyperstreamline + double StepLength; + + // terminal propagation speed + double TerminalEigenvalue; + + // number of sides of tube + int NumberOfSides; + + // maximum radius of tube + double Radius; + + // boolean controls whether scaling is clamped + int LogScaling; + + // which eigenvector to use as integration vector field + int IntegrationEigenvector; +private: + vtkHyperStreamline(const vtkHyperStreamline&); // Not implemented. + void operator=(const vtkHyperStreamline&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkIdFilter.cxx b/Graphics/vtkIdFilter.cxx new file mode 100644 index 0000000..80012aa --- /dev/null +++ b/Graphics/vtkIdFilter.cxx @@ -0,0 +1,151 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIdFilter.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDataSet.h" +#include "vtkIdTypeArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkIdFilter, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkIdFilter); + +// Construct object with PointIds and CellIds on; and ids being generated +// as scalars. +vtkIdFilter::vtkIdFilter() +{ + this->PointIds = 1; + this->CellIds = 1; + this->FieldData = 0; + this->IdsArrayName = NULL; + this->SetIdsArrayName("vtkIdFilter_Ids"); +} + +vtkIdFilter::~vtkIdFilter() +{ + if (this->IdsArrayName) + { + delete []IdsArrayName; + } +} + +// +// Map ids into attribute data +// +int vtkIdFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells, id; + vtkIdTypeArray *ptIds; + vtkIdTypeArray *cellIds; + vtkPointData *inPD=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *inCD=input->GetCellData(), *outCD=output->GetCellData(); + + // Initialize + // + vtkDebugMacro(<<"Generating ids!"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + numPts = input->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + + // Loop over points (if requested) and generate ids + // + if ( this->PointIds && numPts > 0 ) + { + ptIds = vtkIdTypeArray::New(); + ptIds->SetNumberOfValues(numPts); + + for (id=0; id < numPts; id++) + { + ptIds->SetValue(id, id); + } + + if ( ! this->FieldData ) + { + int idx = outPD->AddArray(ptIds); + outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + outPD->CopyScalarsOff(); + } + else + { + ptIds->SetName(this->IdsArrayName); + outPD->AddArray(ptIds); + outPD->CopyFieldOff(this->IdsArrayName); + } + ptIds->Delete(); + } + + // Loop over cells (if requested) and generate ids + // + if ( this->CellIds && numCells > 0 ) + { + cellIds = vtkIdTypeArray::New(); + cellIds->SetNumberOfValues(numCells); + + for (id=0; id < numCells; id++) + { + cellIds->SetValue(id, id); + } + + if ( ! this->FieldData ) + { + int idx = outCD->AddArray(cellIds); + outCD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + outCD->CopyScalarsOff(); + } + else + { + cellIds->SetName(this->IdsArrayName); + outCD->AddArray(cellIds); + outCD->CopyFieldOff(this->IdsArrayName); + } + cellIds->Delete(); + } + + outPD->PassData(inPD); + outCD->PassData(inCD); + + return 1; +} + +void vtkIdFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Point Ids: " << (this->PointIds ? "On\n" : "Off\n"); + os << indent << "Cell Ids: " << (this->CellIds ? "On\n" : "Off\n"); + os << indent << "Field Data: " << (this->FieldData ? "On\n" : "Off\n"); + os << indent << "IdsArrayName: " << (this->IdsArrayName ? this->IdsArrayName + : "(none)") << "\n"; +} diff --git a/Graphics/vtkIdFilter.h b/Graphics/vtkIdFilter.h new file mode 100644 index 0000000..f58e7fa --- /dev/null +++ b/Graphics/vtkIdFilter.h @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIdFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIdFilter - generate scalars or field data from point and cell ids +// .SECTION Description +// vtkIdFilter is a filter to that generates scalars or field data +// using cell and point ids. That is, the point attribute data scalars +// or field data are generated from the point ids, and the cell +// attribute data scalars or field data are generated from the the +// cell ids. +// +// Typically this filter is used with vtkLabeledDataMapper (and possibly +// vtkSelectVisiblePoints) to create labels for points and cells, or labels +// for the point or cell data scalar values. + +#ifndef __vtkIdFilter_h +#define __vtkIdFilter_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkIdFilter : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkIdFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with PointIds and CellIds on; and ids being generated + // as scalars. + static vtkIdFilter *New(); + + // Description: + // Enable/disable the generation of point ids. + vtkSetMacro(PointIds,int); + vtkGetMacro(PointIds,int); + vtkBooleanMacro(PointIds,int); + + // Description: + // Enable/disable the generation of point ids. + vtkSetMacro(CellIds,int); + vtkGetMacro(CellIds,int); + vtkBooleanMacro(CellIds,int); + + // Description: + // Set/Get the flag which controls whether to generate scalar data + // or field data. If this flag is off, scalar data is generated. + // Otherwise, field data is generated. + vtkSetMacro(FieldData,int); + vtkGetMacro(FieldData,int); + vtkBooleanMacro(FieldData,int); + + // Description: + // Set/Get the name of the Ids array if generated. By default the Ids + // are named "vtkIdFilter_Ids", but this can be changed with this function. + vtkSetStringMacro(IdsArrayName); + vtkGetStringMacro(IdsArrayName); + +protected: + vtkIdFilter(); + ~vtkIdFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int PointIds; + int CellIds; + int FieldData; + char *IdsArrayName; + +private: + vtkIdFilter(const vtkIdFilter&); // Not implemented. + void operator=(const vtkIdFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkImageDataGeometryFilter.cxx b/Graphics/vtkImageDataGeometryFilter.cxx new file mode 100644 index 0000000..1e56481 --- /dev/null +++ b/Graphics/vtkImageDataGeometryFilter.cxx @@ -0,0 +1,484 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDataGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageDataGeometryFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkImageDataGeometryFilter, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkImageDataGeometryFilter); + +// Construct with initial extent of all the data +vtkImageDataGeometryFilter::vtkImageDataGeometryFilter() +{ + this->Extent[0] = 0; + this->Extent[1] = VTK_LARGE_INTEGER; + this->Extent[2] = 0; + this->Extent[3] = VTK_LARGE_INTEGER; + this->Extent[4] = 0; + this->Extent[5] = VTK_LARGE_INTEGER; + this->ThresholdCells = 0; + this->ThresholdValue = 0.0; + this->OutputTriangles = 0; +} + +int vtkImageDataGeometryFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int *dims, dimension, dir[3], diff[3]; + int i, j, k, extent[6], s, threshok; + vtkIdType idx, startIdx, startCellIdx; + vtkIdType ptIds[4], cellId, triIds[3]; + vtkPoints *newPts=0; + vtkCellArray *newVerts=0; + vtkCellArray *newLines=0; + vtkCellArray *newPolys=0; + vtkIdType totPoints, pos; + int offset[3], numPolys; + double x[3]; + vtkPointData *pd, *outPD; + vtkDataArray *pointScalars; + vtkCellData *cd, *outCD; + vtkDebugMacro(<< "Extracting structured points geometry"); + + pd = input->GetPointData(); + outPD = output->GetPointData(); + cd = input->GetCellData(); + outCD = output->GetCellData(); + pointScalars=pd->GetScalars(); +// this->PointData.CopyNormalsOff(); + dims = input->GetDimensions(); + + if (dims[0] <= 0 || dims[1] <= 0 || dims[2] <= 0) + { + return 1; + } + +// +// Based on the dimensions of the structured data, and the extent of the geometry, +// compute the combined extent plus the dimensionality of the data +// + for (dimension=3, i=0; i<3; i++) + { + extent[2*i] = this->Extent[2*i] < 0 ? 0 : this->Extent[2*i]; + extent[2*i] = this->Extent[2*i] >= dims[i] ? dims[i]-1 : this->Extent[2*i]; + extent[2*i+1] = this->Extent[2*i+1] >= dims[i] ? dims[i]-1 : this->Extent[2*i+1]; + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + if ( (extent[2*i+1] - extent[2*i]) == 0 ) + { + dimension--; + } + } +// +// Now create polygonal data based on dimension of data +// + startIdx = extent[0] + extent[2]*dims[0] + extent[4]*dims[0]*dims[1]; +// The cell index is a bit more complicated at the boundaries + if (dims[0] == 1) + { + startCellIdx = extent[0]; + } + else + { + startCellIdx = (extent[0] < dims[0] - 1) ? extent[0] + : extent[0]-1; + } + if (dims[1] == 1) + { + startCellIdx += extent[2]*(dims[0]-1); + } + else + { + startCellIdx += (extent[2] < dims[1] - 1) ? extent[2]*(dims[0]-1) + : (extent[2]-1)*(dims[0]-1); + } + if (dims[2] == 1) + { + startCellIdx += extent[4]*(dims[0]-1)*(dims[1]-1); + } + else + { + startCellIdx += (extent[4] < dims[2] - 1) ? extent[4]*(dims[0]-1)*(dims[1]-1) + : (extent[4]-1)*(dims[0]-1)*(dims[1]-1); + } + + switch (dimension) + { + default: + break; + + case 0: // --------------------- build point ----------------------- + + newPts = vtkPoints::New(); + newPts->Allocate(1); + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(1,1)); + outPD->CopyAllocate(pd,1); + outCD->CopyAllocate(cd,1); + + ptIds[0] = newPts->InsertNextPoint(input->GetPoint(startIdx)); + outPD->CopyData(pd,startIdx,ptIds[0]); + + cellId = newVerts->InsertNextCell(1,ptIds); + outCD->CopyData(cd,startIdx,cellId); + break; + + case 1: // --------------------- build line ----------------------- + + for (dir[0]=dir[1]=dir[2]=totPoints=0, i=0; i<3; i++) + { + if ( (diff[i] = extent[2*i+1] - extent[2*i]) > 0 ) + { + dir[0] = i; + totPoints = diff[i] + 1; + break; + } + } + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(totPoints-1,2)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,totPoints - 1); +// +// Load data +// + if ( dir[0] == 0 ) + { + offset[0] = 1; + } + else if (dir[0] == 1) + { + offset[0] = dims[0]; + } + else + { + offset[0] = dims[0]*dims[1]; + } + + for (i=0; iGetPoint(idx, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,idx,ptIds[0]); + } + + if ( dir[0] == 0 ) + { + offset[0] = 1; + } + else if (dir[0] == 1) + { + offset[0] = dims[0] - 1; + } + else + { + offset[0] = (dims[0] - 1) * (dims[1] - 1); + } + + for (i=0; i<(totPoints-1); i++) + { + idx = startCellIdx + i*offset[0]; + ptIds[0] = i; + ptIds[1] = i + 1; + cellId = newLines->InsertNextCell(2,ptIds); + outCD->CopyData(cd,idx,cellId); + } + break; + + case 2: // --------------------- build plane ----------------------- +// +// Create the data objects +// + for (dir[0]=dir[1]=dir[2]=idx=0,i=0; i<3; i++) + { + if ( (diff[i] = extent[2*i+1] - extent[2*i]) != 0 ) + { + dir[idx++] = i; + } + else + { + dir[2] = i; + } + } + + totPoints = (diff[dir[0]]+1) * (diff[dir[1]]+1); + numPolys = diff[dir[0]] * diff[dir[1]]; + + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newPolys = vtkCellArray::New(); + if (this->OutputTriangles) + { + newPolys->Allocate(2*newLines->EstimateSize(numPolys,3)); + } + else + { + newPolys->Allocate(newLines->EstimateSize(numPolys,4)); + } + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,numPolys); +// +// Create vertices +// + for (i=0; i<2; i++) + { + if ( dir[i] == 0 ) + { + offset[i] = 1; + } + else if ( dir[i] == 1 ) + { + offset[i] = dims[0]; + } + else if ( dir[i] == 2 ) + { + offset[i] = dims[0]*dims[1]; + } + } + + for (pos=startIdx, j=0; j < (diff[dir[1]]+1); j++) + { + for (i=0; i < (diff[dir[0]]+1); i++) + { + idx = pos + i*offset[0]; + input->GetPoint(idx, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,idx,ptIds[0]); + } + pos += offset[1]; + } + +// +// Create cells +// + for (i=0; i<2; i++) + { + if ( dir[i] == 0 ) + { + offset[i] = 1; + } + else if ( dir[i] == 1 ) + { + offset[i] = (dims[0] - 1); + } + else if ( dir[i] == 2 ) + { + offset[i] = (dims[0] - 1) * (dims[1] - 1); + } + } + + for (pos=startCellIdx, j=0; j < diff[dir[1]]; j++) + { + for (i=0; i < diff[dir[0]]; i++) + { + idx = pos + i*offset[0]; + ptIds[0] = i + j*(diff[dir[0]]+1); + ptIds[1] = ptIds[0] + 1; + ptIds[2] = ptIds[1] + diff[dir[0]] + 1; + ptIds[3] = ptIds[2] - 1; + if (this->ThresholdCells) + { + threshok = false; + for (s=0; !threshok && s<4; s++) + { + if (pointScalars->GetComponent(ptIds[s],0)>this->ThresholdValue) + { + threshok = true; + break; + } + } + if (threshok) + { + if (this->OutputTriangles) + { + triIds[0] = ptIds[0]; + triIds[1] = ptIds[2]; + triIds[2] = ptIds[3]; + cellId = newPolys->InsertNextCell(3,ptIds); + outCD->CopyData(cd,idx,cellId); + cellId = newPolys->InsertNextCell(3,triIds); + outCD->CopyData(cd,idx,cellId); + } + else + { + cellId = newPolys->InsertNextCell(4,ptIds); + outCD->CopyData(cd,idx,cellId); + } + } + } + else + { + cellId = newPolys->InsertNextCell(4,ptIds); + outCD->CopyData(cd,idx,cellId); + } + } + pos += offset[1]; + } + break; + + case 3: // ------------------- grab points in volume -------------- + +// +// Create data objects +// + for (i=0; i<3; i++) + { + diff[i] = extent[2*i+1] - extent[2*i]; + } + totPoints = (diff[0]+1) * (diff[1]+1) * (diff[2]+1); + + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(totPoints,1)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,totPoints); +// +// Create vertices and cells +// + offset[0] = dims[0]; + offset[1] = dims[0]*dims[1]; + + for (k=0; k < (diff[2]+1); k++) + { + for (j=0; j < (diff[1]+1); j++) + { + pos = startIdx + j*offset[0] + k*offset[1]; + for (i=0; i < (diff[0]+1); i++) + { + input->GetPoint(pos+i, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,pos+i,ptIds[0]); + cellId = newVerts->InsertNextCell(1,ptIds); + outCD->CopyData(cd,pos+i,cellId); + } + } + } + break; /* end this case */ + + } // switch +// +// Update self and release memory +// + if (newPts) + { + output->SetPoints(newPts); + newPts->Delete(); + } + + if (newVerts) + { + output->SetVerts(newVerts); + newVerts->Delete(); + } + + if (newLines) + { + output->SetLines(newLines); + newLines->Delete(); + } + + if (newPolys) + { + output->SetPolys(newPolys); + newPolys->Delete(); + } + + return 1; +} + +void vtkImageDataGeometryFilter::SetExtent(int iMin, int iMax, + int jMin, int jMax, + int kMin, int kMax) +{ + int extent[6]; + + extent[0] = iMin; + extent[1] = iMax; + extent[2] = jMin; + extent[3] = jMax; + extent[4] = kMin; + extent[5] = kMax; + + this->SetExtent(extent); +} + +// Specify (imin,imax, jmin,jmax, kmin,kmax) indices. +void vtkImageDataGeometryFilter::SetExtent(int extent[6]) +{ + int i; + + if ( extent[0] != this->Extent[0] || extent[1] != this->Extent[1] || + extent[2] != this->Extent[2] || extent[3] != this->Extent[3] || + extent[4] != this->Extent[4] || extent[5] != this->Extent[5] ) + { + this->Modified(); + for (i=0; i<3; i++) + { + if ( extent[2*i] < 0 ) + { + extent[2*i] = 0; + } + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + this->Extent[2*i] = extent[2*i]; + this->Extent[2*i+1] = extent[2*i+1]; + } + } +} + +int vtkImageDataGeometryFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkImageDataGeometryFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Extent: \n"; + os << indent << " Jmin,Jmax: (" << this->Extent[2] << ", " << this->Extent[3] << ")\n"; + os << indent << " Kmin,Kmax: (" << this->Extent[4] << ", " << this->Extent[5] << ")\n"; + os << indent << " Imin,Imax: (" << this->Extent[0] << ", " << this->Extent[1] << ")\n"; + os << indent << "OutputTriangles " << this->OutputTriangles << "\n"; + os << indent << "ThresholdValue " << this->ThresholdValue << "\n"; + os << indent << "ThresholdCells " << this->ThresholdCells << "\n"; +} diff --git a/Graphics/vtkImageDataGeometryFilter.h b/Graphics/vtkImageDataGeometryFilter.h new file mode 100644 index 0000000..55f941a --- /dev/null +++ b/Graphics/vtkImageDataGeometryFilter.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDataGeometryFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageDataGeometryFilter - extract geometry for structured points +// .SECTION Description +// vtkImageDataGeometryFilter is a filter that extracts geometry from a +// structured points dataset. By specifying appropriate i-j-k indices (via the +// "Extent" instance variable), it is possible to extract a point, a line, a +// plane (i.e., image), or a "volume" from dataset. (Since the output is +// of type polydata, the volume is actually a (n x m x o) region of points.) +// +// The extent specification is zero-offset. That is, the first k-plane in +// a 50x50x50 volume is given by (0,49, 0,49, 0,0). +// .SECTION Caveats +// If you don't know the dimensions of the input dataset, you can use a large +// number to specify extent (the number will be clamped appropriately). For +// example, if the dataset dimensions are 50x50x50, and you want a the fifth +// k-plane, you can use the extents (0,100, 0,100, 4,4). The 100 will +// automatically be clamped to 49. + +// .SECTION See Also +// vtkGeometryFilter vtkStructuredGridSource + +#ifndef __vtkImageDataGeometryFilter_h +#define __vtkImageDataGeometryFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkImageDataGeometryFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImageDataGeometryFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with initial extent of all the data + static vtkImageDataGeometryFilter *New(); + + // Description: + // Set / get the extent (imin,imax, jmin,jmax, kmin,kmax) indices. + void SetExtent(int extent[6]); + void SetExtent(int iMin, int iMax, int jMin, int jMax, int kMin, int kMax); + int *GetExtent() { return this->Extent;}; + + // Description: + // Set ThresholdCells to true if you wish to skip any voxel/pixels which have scalar + // values less than the specified threshold. + // Currently this functionality is only implemented for 2D imagedata + vtkSetMacro(ThresholdCells,int); + vtkGetMacro(ThresholdCells,int); + vtkBooleanMacro(ThresholdCells,int); + + // Description: + // Set ThresholdValue to the scalar value by which to threshhold cells when extracting geometry + // when ThresholdCells is true. Cells with scalar values greater than the threshold will be output. + vtkSetMacro(ThresholdValue,double); + vtkGetMacro(ThresholdValue,double); + vtkBooleanMacro(ThresholdValue,double); + + // Description: + // Set OutputTriangles to true if you wish to generate triangles instead of quads + // when extracting cells from 2D imagedata + // Currently this functionality is only implemented for 2D imagedata + vtkSetMacro(OutputTriangles,int); + vtkGetMacro(OutputTriangles,int); + vtkBooleanMacro(OutputTriangles,int); + +protected: + vtkImageDataGeometryFilter(); + ~vtkImageDataGeometryFilter() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int Extent[6]; + int ThresholdCells; + double ThresholdValue; + int OutputTriangles; + +private: + vtkImageDataGeometryFilter(const vtkImageDataGeometryFilter&); // Not implemented. + void operator=(const vtkImageDataGeometryFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkImageMarchingCubes.cxx b/Graphics/vtkImageMarchingCubes.cxx new file mode 100644 index 0000000..ade2ece --- /dev/null +++ b/Graphics/vtkImageMarchingCubes.cxx @@ -0,0 +1,823 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMarchingCubes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMarchingCubes.h" + +#include "vtkCellArray.h" +#include "vtkCommand.h" +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMarchingCubesCases.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include + +vtkCxxRevisionMacro(vtkImageMarchingCubes, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkImageMarchingCubes); + +//---------------------------------------------------------------------------- +// Description: +// Construct object with initial range (0,1) and single contour value +// of 0.0. ComputeNormal is on, ComputeGradients is off and ComputeScalars is on. +vtkImageMarchingCubes::vtkImageMarchingCubes() +{ + this->ContourValues = vtkContourValues::New(); + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->LocatorPointIds = NULL; + this->InputMemoryLimit = 10000; // 10 mega Bytes +} + +vtkImageMarchingCubes::~vtkImageMarchingCubes() +{ + this->ContourValues->Delete(); +} + +// Description: +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkImageMarchingCubes::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long contourValuesMTime=this->ContourValues->GetMTime(); + + mTime = ( contourValuesMTime > mTime ? contourValuesMTime : mTime ); + + return mTime; +} + +//---------------------------------------------------------------------------- +template +int vtkImageMarchingCubesGetTypeSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +int vtkImageMarchingCubes::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int extent[8], estimatedSize; + int temp, zMin, zMax, chunkMin, chunkMax; + int minSlicesPerChunk, chunkOverlap; + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + + vtkDebugMacro("Starting Execute Method"); + + // Gradients must be computed (but not saved) if Compute normals is on. + this->NeedGradients = this->ComputeGradients || this->ComputeNormals; + + // Determine the number of slices per request from input memory limit. + if (this->NeedGradients) + { + minSlicesPerChunk = 4; + chunkOverlap = 3; + } + else + { + minSlicesPerChunk = 2; + chunkOverlap = 1; + } + inData->UpdateInformation(); + // Each data type requires a different amount of memory. + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + temp = vtkImageMarchingCubesGetTypeSize(static_cast(0)) + ); + default: + vtkErrorMacro(<< "Could not determine input scalar type."); + return 1; + } + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + // multiply by the area of each slice + temp *= extent[1] - extent[0] + 1; + temp *= extent[3] - extent[2] + 1; + temp = temp; + // temp holds memory per image. (+1 to avoid dividing by zero) + this->NumberOfSlicesPerChunk = this->InputMemoryLimit * 1000 / (temp + 1); + if (this->NumberOfSlicesPerChunk < minSlicesPerChunk) + { + vtkWarningMacro("Execute: Need " + << minSlicesPerChunk*(temp/1000) << " KB to load " + << minSlicesPerChunk << " slices.\n"); + this->NumberOfSlicesPerChunk = minSlicesPerChunk; + } + vtkDebugMacro("Execute: NumberOfSlicesPerChunk = " + << this->NumberOfSlicesPerChunk); + this->NumberOfSlicesPerChunk -= chunkOverlap; + + // Create the points, scalars, normals and Cell arrays for the output. + // estimate the number of points from the volume dimensions + estimatedSize = (int) pow ((double) ((extent[1]-extent[0]+1) * + (extent[3]-extent[2]+1) * + (extent[5]-extent[4]+1)), 0.75); + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + vtkDebugMacro(<< "Estimated number of points/triangles: " << estimatedSize); + this->Points = vtkPoints::New(); + this->Points->Allocate(estimatedSize,estimatedSize/2); + this->Triangles = vtkCellArray::New(); + this->Triangles->Allocate(estimatedSize,estimatedSize/2); + if (this->ComputeScalars) + { + this->Scalars = vtkFloatArray::New(); + this->Scalars->Allocate(estimatedSize,estimatedSize/2); + } + if (this->ComputeNormals) + { + this->Normals = vtkFloatArray::New(); + this->Normals->SetNumberOfComponents(3); + this->Normals->Allocate(3*estimatedSize,3*estimatedSize/2); + } + if (this->ComputeGradients) + { + this->Gradients = vtkFloatArray::New(); + this->Gradients->SetNumberOfComponents(3); + this->Gradients->Allocate(3*estimatedSize,3*estimatedSize/2); + } + + // Initialize the internal point locator (edge table for oen image of cubes). + this->InitializeLocator(extent[0], extent[1], extent[2], extent[3]); + + // Loop through the chunks running marching cubes on each one + zMin = extent[4]; + zMax = extent[5]; + // to avoid warnings + chunkMax = zMin + this->NumberOfSlicesPerChunk; + for(chunkMin = zMin; chunkMin < zMax; chunkMin = chunkMax) + { + // Get the chunk from the input + chunkMax = chunkMin + this->NumberOfSlicesPerChunk; + if (chunkMax > zMax) + { + chunkMax = zMax; + } + extent[4] = chunkMin; + extent[5] = chunkMax; + // Expand if computing gradients with central differences + if (this->NeedGradients) + { + --extent[4]; + ++extent[5]; + } + // Don't go over boundary of data. + if (extent[4] < zMin) + { + extent[4] = zMin; + } + if (extent[5] > zMax) + { + extent[5] = zMax; + } + // Get the chunk from the input + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + extent, 6); + inData->Update(); + + this->InvokeEvent(vtkCommand::StartEvent,NULL); + this->March(inData, chunkMin, chunkMax, numContours, values); + if ( !this->AbortExecute ) + { + this->UpdateProgress(1.0); + } + this->InvokeEvent(vtkCommand::EndEvent,NULL); + + if (inData->ShouldIReleaseData()) + { + inData->ReleaseData(); + } + } + + // Put results in our output + vtkDebugMacro(<<"Created: " + << this->Points->GetNumberOfPoints() << " points, " + << this->Triangles->GetNumberOfCells() << " triangles"); + output->SetPoints(this->Points); + this->Points->Delete(); + this->Points = NULL; + output->SetPolys(this->Triangles); + this->Triangles->Delete(); + this->Triangles = NULL; + if (this->ComputeScalars) + { + int idx = output->GetPointData()->AddArray(this->Scalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + this->Scalars->Delete(); + this->Scalars = NULL; + } + if (this->ComputeNormals) + { + output->GetPointData()->SetNormals(this->Normals); + this->Normals->Delete(); + this->Normals = NULL; + } + + // Recover extra space. + output->Squeeze(); + + // release the locators memory + this->DeleteLocator(); + + return 1; +} + +//---------------------------------------------------------------------------- +// This method uses central differences to compute the gradient +// of a point. Note: This method assumes that max > min for all 3 axes! +// It does not consider the dataset spacing. +// b0 (b1, b2) indicates the boundary conditions for the three axes.: +// b0 = -1 => pixel is on x axis minimum of region. +// b0 = 0 => no boundary conditions +// b0 = +1 => pixel is on x axis maximum of region. +template +void vtkImageMarchingCubesComputePointGradient(T *ptr, double *g, + int inc0, int inc1, int inc2, + short b0, short b1, short b2) +{ + if (b0 < 0) + { + g[0] = (double)(ptr[inc0]) - (double)(*ptr); + } + else if (b0 > 0) + { + g[0] = (double)(*ptr) - (double)(ptr[-inc0]); + } + else + { + g[0] = (double)(ptr[inc0]) - (double)(ptr[-inc0]); + } + + if (b1 < 0) + { + g[1] = (double)(ptr[inc1]) - (double)(*ptr); + } + else if (b1 > 0) + { + g[1] = (double)(*ptr) - (double)(ptr[-inc1]); + } + else + { + g[1] = (double)(ptr[inc1]) - (double)(ptr[-inc1]); + } + + if (b2 < 0) + { + g[2] = (double)(ptr[inc2]) - (double)(*ptr); + } + else if (b2 > 0) + { + g[2] = (double)(*ptr) - (double)(ptr[-inc2]); + } + else + { + g[2] = (double)(ptr[inc2]) - (double)(ptr[-inc2]); + } +} + + +//---------------------------------------------------------------------------- +// This method interpolates verticies to make a new point. +template +int vtkImageMarchingCubesMakeNewPoint(vtkImageMarchingCubes *self, + int idx0, int idx1, int idx2, + int inc0, int inc1, int inc2, + T *ptr, int edge, + int *imageExtent, + double *spacing, double *origin, + double value) +{ + int edgeAxis = 0; + T *ptrB = NULL; + double temp, pt[3]; + + // decode the edge into starting point and axis direction + switch (edge) + { + case 0: // 0,1 + ptrB = ptr + inc0; + edgeAxis = 0; + break; + case 1: // 1,2 + ++idx0; + ptr += inc0; + ptrB = ptr + inc1; + edgeAxis = 1; + break; + case 2: // 3,2 + ++idx1; + ptr += inc1; + ptrB = ptr + inc0; + edgeAxis = 0; + break; + case 3: // 0,3 + ptrB = ptr + inc1; + edgeAxis = 1; + break; + case 4: // 4,5 + ++idx2; + ptr += inc2; + ptrB = ptr + inc0; + edgeAxis = 0; + break; + case 5: // 5,6 + ++idx0; ++idx2; + ptr += inc0 + inc2; + ptrB = ptr + inc1; + edgeAxis = 1; + break; + case 6: // 7,6 + ++idx1; ++idx2; + ptr += inc1 + inc2; + ptrB = ptr + inc0; + edgeAxis = 0; + break; + case 7: // 4,7 + ++idx2; + ptr += inc2; + ptrB = ptr + inc1; + edgeAxis = 1; + break; + case 8: // 0,4 + ptrB = ptr + inc2; + edgeAxis = 2; + break; + case 9: // 1,5 + ++idx0; + ptr += inc0; + ptrB = ptr + inc2; + edgeAxis = 2; + break; + case 10: // 3,7 + ++idx1; + ptr += inc1; + ptrB = ptr + inc2; + edgeAxis = 2; + break; + case 11: // 2,6 + ++idx0; ++idx1; + ptr += inc0 + inc1; + ptrB = ptr + inc2; + edgeAxis = 2; + break; + } + + // interpolation factor + temp = (value - *ptr) / (*ptrB - *ptr); + + // interpolate the point position + switch (edgeAxis) + { + case 0: + pt[0] = origin[0] + spacing[0] * ((double)idx0 + temp); + pt[1] = origin[1] + spacing[1] * ((double)idx1); + pt[2] = origin[2] + spacing[2] * ((double)idx2); + break; + case 1: + pt[0] = origin[0] + spacing[0] * ((double)idx0); + pt[1] = origin[1] + spacing[1] * ((double)idx1 + temp); + pt[2] = origin[2] + spacing[2] * ((double)idx2); + break; + case 2: + pt[0] = origin[0] + spacing[0] * ((double)idx0); + pt[1] = origin[1] + spacing[1] * ((double)idx1); + pt[2] = origin[2] + spacing[2] * ((double)idx2 + temp); + break; + } + + // Save the scale if we are generating scalars + if (self->ComputeScalars) + { + self->Scalars->InsertNextValue(value); + } + + // Interpolate to find normal from vectors. + if (self->NeedGradients) + { + short b0, b1, b2; + double g[3], gB[3]; + // Find boundary conditions and compute gradient (first point) + b0 = (idx0 == imageExtent[1]); + if (idx0 == imageExtent[0]) + { + b0 = -1; + } + b1 = (idx1 == imageExtent[3]); + if (idx1 == imageExtent[2]) + { + b1 = -1; + } + b2 = (idx2 == imageExtent[5]); + if (idx2 == imageExtent[4]) + { + b2 = -1; + } + vtkImageMarchingCubesComputePointGradient(ptr, g, inc0, inc1, inc2, + b0, b1, b2); + // Find boundary conditions and compute gradient (second point) + switch (edgeAxis) + { + case 0: + ++idx0; + b0 = (idx0 == imageExtent[1]); + break; + case 1: + ++idx1; + b1 = (idx1 == imageExtent[3]); + break; + case 2: + ++idx2; + b2 = (idx2 == imageExtent[5]); + break; + } + vtkImageMarchingCubesComputePointGradient(ptrB, gB, inc0, inc1, inc2, + b0, b1, b2); + // Interpolate Gradient + g[0] = (g[0] + temp * (gB[0] - g[0])) / spacing[0]; + g[1] = (g[1] + temp * (gB[1] - g[1])) / spacing[1]; + g[2] = (g[2] + temp * (gB[2] - g[2])) / spacing[2]; + if (self->ComputeGradients) + { + self->Gradients->InsertNextTuple(g); + } + if (self->ComputeNormals) + { + temp = -1.0 / sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]); + g[0] *= temp; + g[1] *= temp; + g[2] *= temp; + self->Normals->InsertNextTuple(g); + } + } + + return self->Points->InsertNextPoint(pt); +} + +//---------------------------------------------------------------------------- +// This method runs marching cubes on one cube. +template +void vtkImageMarchingCubesHandleCube(vtkImageMarchingCubes *self, + int cellX, int cellY, int cellZ, + vtkImageData *inData, + T *ptr, int numContours, double *values) +{ + vtkIdType inc0, inc1, inc2; + int valueIdx; + double value; + int cubeIndex, ii; + vtkIdType pointIds[3]; + vtkMarchingCubesTriangleCases *triCase, *triCases; + EDGE_LIST *edge; + + vtkInformation *inInfo = self->GetExecutive()->GetInputInformation(0, 0); + + triCases = vtkMarchingCubesTriangleCases::GetCases(); + + inData->GetIncrements(inc0, inc1, inc2); + for (valueIdx = 0; valueIdx < numContours; ++valueIdx) + { + value = values[valueIdx]; + // compute the case index + cubeIndex = 0; + if ((double)(ptr[0]) > value) + { + cubeIndex += 1; + } + if ((double)(ptr[inc0]) > value) + { + cubeIndex += 2; + } + if ((double)(ptr[inc0 + inc1]) > value) + { + cubeIndex += 4; + } + if ((double)(ptr[inc1]) > value) + { + cubeIndex += 8; + } + if ((double)(ptr[inc2]) > value) + { + cubeIndex += 16; + } + if ((double)(ptr[inc0 + inc2]) > value) + { + cubeIndex += 32; + } + if ((double)(ptr[inc0 + inc1 + inc2]) > value) + { + cubeIndex += 64; + } + if ((double)(ptr[inc1 + inc2]) > value) + { + cubeIndex += 128; + } + // Make sure we have trianlges + if (cubeIndex != 0 && cubeIndex != 255) + { + // Get edges. + triCase = triCases + cubeIndex; + edge = triCase->edges; + // loop over triangles + while(*edge > -1) + { + for (ii=0; ii<3; ++ii, ++edge) //insert triangle + { + // Get the index of the point + pointIds[ii] = self->GetLocatorPoint(cellX, cellY, *edge); + // If the point has not been created yet + if (pointIds[ii] == -1) + { + double *spacing = inData->GetSpacing(); + double *origin = inData->GetOrigin(); + int *extent = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + pointIds[ii] = vtkImageMarchingCubesMakeNewPoint(self, + cellX, cellY, cellZ, + inc0, inc1, inc2, + ptr, *edge, extent, + spacing, origin, value); + self->AddLocatorPoint(cellX, cellY, *edge, pointIds[ii]); + } + } + self->Triangles->InsertNextCell(3,pointIds); + }//for each triangle + } + } +} + +//---------------------------------------------------------------------------- +template +void vtkImageMarchingCubesMarch(vtkImageMarchingCubes *self, + vtkImageData *inData, T *ptr, + int chunkMin, int chunkMax, + int numContours, double *values) +{ + int idx0, idx1, idx2; + int min0, max0, min1, max1, min2, max2; + vtkIdType inc0, inc1, inc2; + T *ptr0, *ptr1, *ptr2; + unsigned long target, count; + + // avoid warnings + ptr = ptr; + + // Get information to loop through images. + inData->GetExtent(min0, max0, min1, max1, min2, max2); + ptr2 = (T *)(inData->GetScalarPointer(min0, min1, chunkMin)); + inData->GetIncrements(inc0, inc1, inc2); + + // Setup the progress reporting + target = (unsigned long)((max0-min0+1) * (max1-min1+1) / 50.0); + ++target; + count = 0; + + // Loop over all the cubes + for (idx2 = chunkMin; idx2 < chunkMax; ++idx2) + { + ptr1 = ptr2; + for (idx1 = min1; idx1 < max1; ++idx1) + { + // update progress if necessary + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + if (self->GetAbortExecute()) + { + return; + } + } + count++; + // continue with last loop + ptr0 = ptr1; + for (idx0 = min0; idx0 < max0; ++idx0) + { + // put magnitudes into the cube structure. + vtkImageMarchingCubesHandleCube(self, idx0, idx1, idx2, inData, ptr0, + numContours, values); + + ptr0 += inc0; + } + ptr1 += inc1; + } + ptr2 += inc2; + self->IncrementLocatorZ(); + } +} + + + +//---------------------------------------------------------------------------- +// This method calls the proper templade function. +void vtkImageMarchingCubes::March(vtkImageData *inData, + int chunkMin, int chunkMax, + int numContours, double *values) +{ + void *ptr = inData->GetScalarPointer(); + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMarchingCubesMarch(this, inData, static_cast(ptr), + chunkMin, chunkMax, numContours, values) + ); + default: + vtkErrorMacro(<< "Unknown output ScalarType"); + return; + } +} + + +//============================================================================ +// These method act as the point locator so verticies will be shared. +// One 2d array of cubes is stored. (z dimension is ignored). +// Points are indexed by their cube and edge. +// Shared edges are only represented once. Cubes are responsible for +// edges on their min faces. Their is an extra row and column of cubes +// to store the max edges of the last row/column of cubes, + + +//---------------------------------------------------------------------------- +// This method allocates and initializes the point array. +// One 2d array of cubes is stored. (z dimension is ignored). +void vtkImageMarchingCubes::InitializeLocator(int min0, int max0, + int min1, int max1) +{ + int idx; + int size; + + // Free old memory + if (this->LocatorPointIds) + { + delete [] this->LocatorPointIds; + } + // Extra row and column + this->LocatorDimX = (max0 - min0 + 2); + this->LocatorDimY = (max1 - min1 + 2); + this->LocatorMinX = min0; + this->LocatorMinY = min1; + // 5 non shared edges. + size = (this->LocatorDimX)*(this->LocatorDimY)*5; + this->LocatorPointIds = new int[size]; + // Initialize the array + for (idx = 0; idx < size; ++idx) + { + this->LocatorPointIds[idx] = -1; + } +} + +//---------------------------------------------------------------------------- +// This method frees the locators memory. +void vtkImageMarchingCubes::DeleteLocator() +{ + // Free old memory + if (this->LocatorPointIds) + { + delete [] this->LocatorPointIds; + this->LocatorPointIds = NULL; + } +} + +//---------------------------------------------------------------------------- +// This method moves the Z index of the locator up one slice. +void vtkImageMarchingCubes::IncrementLocatorZ() +{ + int x, y; + int *ptr; + + ptr = this->LocatorPointIds; + for (y = 0; y < this->LocatorDimY; ++y) + { + for (x = 0; x < this->LocatorDimX; ++x) + { + ptr[0] = ptr[4]; + ptr[3] = ptr[1]; + ptr[1] = ptr[2] = ptr[4] = -1; + ptr += 5; + } + } +} + +//---------------------------------------------------------------------------- +// This method adds a point to the array. Cube is the X/Y cube, +// segment is the index of the segment (same as marching cubes).(XYZ) +// (0,0,0)->(1,0,0): 0, (1,0,0)->(1,1,0): 1, +// (1,1,0)->(0,1,0): 2, (0,1,0)->(0,0,0): 3, +// (0,0,1)->(1,0,1): 4, (1,0,1)->(1,1,1): 5, +// (1,1,1)->(0,1,1): 6, (0,1,1)->(0,0,1): 7, +// (0,0,0)->(0,0,1): 8, (1,0,0)->(1,0,1): 9, +// (0,1,0)->(0,1,1): 10, (1,1,0)->(1,1,1): 11. +// Shared edges are computed internaly. (no error checking) +void vtkImageMarchingCubes::AddLocatorPoint(int cellX, int cellY, int edge, + int ptId) +{ + int *ptr; + + // Get the correct position in the array. + ptr = this->GetLocatorPointer(cellX, cellY, edge); + *ptr = ptId; +} + +//---------------------------------------------------------------------------- +// This method gets a point from the locator. +int vtkImageMarchingCubes::GetLocatorPoint(int cellX, int cellY, int edge) +{ + int *ptr; + + // Get the correct position in the array. + ptr = this->GetLocatorPointer(cellX, cellY, edge); + return *ptr; +} + +//---------------------------------------------------------------------------- +// This method returns a pointer to an ID from a cube and an edge. +int *vtkImageMarchingCubes::GetLocatorPointer(int cellX,int cellY,int edge) +{ + // Remove redundant edges (shared by more than one cube). + // Take care of shared edges + switch (edge) + { + case 9: ++cellX; edge = 8; break; + case 10: ++cellY; edge = 8; break; + case 11: ++cellX; ++cellY; edge = 8; break; + case 5: ++cellX; edge = 7; break; + case 6: ++cellY; edge = 4; break; + case 1: ++cellX; edge = 3; break; + case 2: ++cellY; edge = 0; break; + } + + // relative to min and max. + cellX -= this->LocatorMinX; + cellY -= this->LocatorMinY; + + // compute new indexes for edges (0 to 4) + // must be compatable with LocatorIncrementZ. + if (edge == 7) + { + edge = 1; + } + if (edge == 8) + { + edge = 2; + } + + // return correct pointer + return this->LocatorPointIds + edge + + (cellX + cellY * (this->LocatorDimX)) * 5; +} + +//---------------------------------------------------------------------------- +int vtkImageMarchingCubes::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageMarchingCubes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "ComputeScalars: " << this->ComputeScalars << "\n"; + os << indent << "ComputeNormals: " << this->ComputeNormals << "\n"; + os << indent << "ComputeGradients: " << this->ComputeGradients << "\n"; + + os << indent << "InputMemoryLimit: " << this->InputMemoryLimit <<"K bytes\n"; +} + diff --git a/Graphics/vtkImageMarchingCubes.h b/Graphics/vtkImageMarchingCubes.h new file mode 100644 index 0000000..a314738 --- /dev/null +++ b/Graphics/vtkImageMarchingCubes.h @@ -0,0 +1,193 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMarchingCubes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMarchingCubes - generate isosurface(s) from volume/images +// .SECTION Description +// vtkImageMarchingCubes is a filter that takes as input images (e.g., 3D +// image region) and generates on output one or more isosurfaces. +// One or more contour values must be specified to generate the isosurfaces. +// Alternatively, you can specify a min/max scalar range and the number of +// contours to generate a series of evenly spaced contour values. +// This filter can stream, so that the entire volume need not be loaded at +// once. Streaming is controlled using the instance variable +// InputMemoryLimit, which has units KBytes. + +// .SECTION Caveats +// This filter is specialized to volumes. If you are interested in +// contouring other types of data, use the general vtkContourFilter. If you +// want to contour an image (i.e., a volume slice), use vtkMarchingSquares. +// .SECTION See Also +// vtkContourFilter vtkSliceCubes vtkMarchingSquares vtkDividingCubes + + +#ifndef __vtkImageMarchingCubes_h +#define __vtkImageMarchingCubes_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for direct access to ContourValues + +class vtkCellArray; +class vtkFloatArray; +class vtkImageData; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkImageMarchingCubes : public vtkPolyDataAlgorithm +{ +public: + static vtkImageMarchingCubes *New(); + vtkTypeRevisionMacro(vtkImageMarchingCubes,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods to set contour values + void SetValue(int i, double value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Description: + // Because we delegate to vtkContourValues & refer to vtkImplicitFunction + unsigned long int GetMTime(); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars, int); + vtkGetMacro(ComputeScalars, int); + vtkBooleanMacro(ComputeScalars, int); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly expensive + // in both time and storage. If the output data will be processed by filters + // that modify topology or geometry, it may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals, int); + vtkGetMacro(ComputeNormals, int); + vtkBooleanMacro(ComputeNormals, int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is fairly expensive + // in both time and storage. Note that if ComputeNormals is on, gradients will + // have to be calculated, but will not be stored in the output dataset. + // If the output data will be processed by filters that modify topology or + // geometry, it may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients, int); + vtkGetMacro(ComputeGradients, int); + vtkBooleanMacro(ComputeGradients, int); + + // Should be protected, but the templated functions need these + int ComputeScalars; + int ComputeNormals; + int ComputeGradients; + int NeedGradients; + + vtkCellArray *Triangles; + vtkFloatArray *Scalars; + vtkPoints *Points; + vtkFloatArray *Normals; + vtkFloatArray *Gradients; + + int GetLocatorPoint(int cellX, int cellY, int edge); + void AddLocatorPoint(int cellX, int cellY, int edge, int ptId); + void IncrementLocatorZ(); + + // Description: + // The InputMemoryLimit determines the chunk size (the number of slices + // requested at each iteration). The units of this limit is KiloBytes. + // For now, only the Z axis is split. + vtkSetMacro(InputMemoryLimit, int); + vtkGetMacro(InputMemoryLimit, int); + +protected: + vtkImageMarchingCubes(); + ~vtkImageMarchingCubes(); + + int NumberOfSlicesPerChunk; + int InputMemoryLimit; + + vtkContourValues *ContourValues; + + int *LocatorPointIds; + int LocatorDimX; + int LocatorDimY; + int LocatorMinX; + int LocatorMinY; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + void March(vtkImageData *inData, int chunkMin, int chunkMax, + int numContours, double *values); + void InitializeLocator(int min0, int max0, int min1, int max1); + void DeleteLocator(); + int *GetLocatorPointer(int cellX, int cellY, int edge); + +private: + vtkImageMarchingCubes(const vtkImageMarchingCubes&); // Not implemented. + void operator=(const vtkImageMarchingCubes&); // Not implemented. +}; + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value);} + +// Description: +// Get the ith contour value. +inline double vtkImageMarchingCubes::GetValue(int i) +{return this->ContourValues->GetValue(i);} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +inline double *vtkImageMarchingCubes::GetValues() +{return this->ContourValues->GetValues();} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +inline void vtkImageMarchingCubes::GetValues(double *contourValues) +{this->ContourValues->GetValues(contourValues);} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +inline void vtkImageMarchingCubes::SetNumberOfContours(int number) +{this->ContourValues->SetNumberOfContours(number);} + +// Description: +// Get the number of contours in the list of contour values. +inline int vtkImageMarchingCubes::GetNumberOfContours() +{return this->ContourValues->GetNumberOfContours();} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkImageMarchingCubes::GenerateValues(int numContours, double range[2]) +{this->ContourValues->GenerateValues(numContours, range);} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkImageMarchingCubes::GenerateValues(int numContours, double + rangeStart, double rangeEnd) +{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + +#endif diff --git a/Graphics/vtkImplicitTextureCoords.cxx b/Graphics/vtkImplicitTextureCoords.cxx new file mode 100644 index 0000000..a4b002f --- /dev/null +++ b/Graphics/vtkImplicitTextureCoords.cxx @@ -0,0 +1,231 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitTextureCoords.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitTextureCoords.h" + +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImplicitTextureCoords, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkImplicitTextureCoords); +vtkCxxSetObjectMacro(vtkImplicitTextureCoords,SFunction,vtkImplicitFunction); +vtkCxxSetObjectMacro(vtkImplicitTextureCoords,RFunction,vtkImplicitFunction); +vtkCxxSetObjectMacro(vtkImplicitTextureCoords,TFunction,vtkImplicitFunction); + +// Create object with texture dimension=2 and no r-s-t implicit functions +// defined and FlipTexture turned off. +vtkImplicitTextureCoords::vtkImplicitTextureCoords() +{ + this->RFunction = NULL; + this->SFunction = NULL; + this->TFunction = NULL; + + this->FlipTexture = 0; +} + +vtkImplicitTextureCoords::~vtkImplicitTextureCoords() +{ + this->SetRFunction(NULL); + this->SetSFunction(NULL); + this->SetTFunction(NULL); +} + + +int vtkImplicitTextureCoords::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType ptId, numPts; + int tcoordDim; + vtkFloatArray *newTCoords; + double min[3], max[3], scale[3]; + double tCoord[3], tc[3], x[3]; + int i; + + // Initialize + // + vtkDebugMacro(<<"Generating texture coordinates from implicit functions..."); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( ((numPts=input->GetNumberOfPoints()) < 1) ) + { + vtkErrorMacro(<< "No input points!"); + return 1; + } + + if ( this->RFunction == NULL ) + { + vtkErrorMacro(<< "No implicit functions defined!"); + return 1; + } + + tcoordDim = 1; + if ( this->SFunction != NULL ) + { + tcoordDim++; + if ( this->TFunction != NULL ) + { + tcoordDim++; + } + } +// +// Allocate +// + tCoord[0] = tCoord[1] = tCoord[2] = 0.0; + + newTCoords = vtkFloatArray::New(); + if ( tcoordDim == 1 ) //force 2D map to be created + { + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*numPts); + } + else + { + newTCoords->SetNumberOfComponents(tcoordDim); + newTCoords->Allocate(tcoordDim*numPts); + } +// +// Compute implicit function values -> insert as initial texture coordinate +// + for (i=0; i<3; i++) //initialize min/max values array + { + min[i] = VTK_DOUBLE_MAX; + max[i] = -VTK_DOUBLE_MAX; + } + for (ptId=0; ptIdGetPoint(ptId, x); + tCoord[0] = this->RFunction->FunctionValue(x); + if ( this->SFunction ) + { + tCoord[1] = this->SFunction->FunctionValue(x); + } + if ( this->TFunction ) + { + tCoord[2] = this->TFunction->FunctionValue(x); + } + + for (i=0; i max[i]) + { + max[i] = tCoord[i]; + } + } + + newTCoords->InsertTuple(ptId,tCoord); + } +// +// Scale and shift texture coordinates into (0,1) range, with 0.0 implicit +// function value equal to texture coordinate value of 0.5 +// + for (i=0; i 0.0 && min[i] < 0.0 ) //have positive & negative numbers + { + if ( max[i] > (-min[i]) ) + { + scale[i] = 0.499 / max[i]; //scale into 0.5->1 + } + else + { + scale[i] = -0.499 / min[i]; //scale into 0->0.5 + } + } + else if ( max[i] > 0.0 ) //have positive numbers only + { + scale[i] = 0.499 / max[i]; //scale into 0.5->1.0 + } + else if ( min[i] < 0.0 ) //have negative numbers only + { + scale[i] = -0.499 / min[i]; //scale into 0.0->0.5 + } + } + + if ( this->FlipTexture ) + { + for (i=0; iGetTuple(ptId, tc); + for (i=0; iInsertTuple(ptId,tCoord); + } +// +// Update self +// + output->GetPointData()->CopyTCoordsOff(); + output->GetPointData()->PassData(input->GetPointData()); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + return 1; +} + +void vtkImplicitTextureCoords::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Flip Texture: " << this->FlipTexture << "\n"; + + if ( this->RFunction != NULL ) + { + if ( this->SFunction != NULL ) + { + if ( this->TFunction != NULL ) + { + os << indent << "R, S, and T Functions defined\n"; + } + } + else + { + os << indent << "R and S Functions defined\n"; + } + } + else + { + os << indent << "R Function defined\n"; + } +} diff --git a/Graphics/vtkImplicitTextureCoords.h b/Graphics/vtkImplicitTextureCoords.h new file mode 100644 index 0000000..d233404 --- /dev/null +++ b/Graphics/vtkImplicitTextureCoords.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitTextureCoords.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitTextureCoords - generate 1D, 2D, or 3D texture coordinates based on implicit function(s) +// .SECTION Description +// vtkImplicitTextureCoords is a filter to generate 1D, 2D, or 3D texture +// coordinates from one, two, or three implicit functions, respectively. +// In combinations with a vtkBooleanTexture map (or another texture map of +// your own creation), the texture coordinates can be used to highlight +//(via color or intensity) or cut (via transparency) dataset geometry without +// any complex geometric processing. (Note: the texture coordinates are +// referred to as r-s-t coordinates.) +// +// The texture coordinates are automatically normalized to lie between (0,1). +// Thus, no matter what the implicit functions evaluate to, the resulting +// texture coordinates lie between (0,1), with the zero implicit function +// value mapped to the 0.5 texture coordinates value. Depending upon the +// maximum negative/positive implicit function values, the full (0,1) range +// may not be occupied (i.e., the positive/negative ranges are mapped using +// the same scale factor). +// +// A boolean variable InvertTexture is available to flip the texture +// coordinates around 0.5 (value 1.0 becomes 0.0, 0.25->0.75). This is +// equivalent to flipping the texture map (but a whole lot easier). + +// .SECTION Caveats +// You can use the transformation capabilities of vtkImplicitFunction to +// orient, translate, and scale the implicit functions. Also, the dimension of +// the texture coordinates is implicitly defined by the number of implicit +// functions defined. + +// .SECTION See Also +// vtkImplicitFunction vtkTexture vtkBooleanTexture vtkTransformTexture + +#ifndef __vtkImplicitTextureCoords_h +#define __vtkImplicitTextureCoords_h + +#include "vtkDataSetAlgorithm.h" + +class vtkImplicitFunction; + +class VTK_GRAPHICS_EXPORT vtkImplicitTextureCoords : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImplicitTextureCoords,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create object with texture dimension=2 and no r-s-t implicit functions + // defined and FlipTexture turned off. + static vtkImplicitTextureCoords *New(); + + // Description: + // Specify an implicit function to compute the r texture coordinate. + virtual void SetRFunction(vtkImplicitFunction*); + vtkGetObjectMacro(RFunction,vtkImplicitFunction); + + // Description: + // Specify an implicit function to compute the s texture coordinate. + virtual void SetSFunction(vtkImplicitFunction*); + vtkGetObjectMacro(SFunction,vtkImplicitFunction); + + // Description: + // Specify an implicit function to compute the t texture coordinate. + virtual void SetTFunction(vtkImplicitFunction*); + vtkGetObjectMacro(TFunction,vtkImplicitFunction); + + // Description: + // If enabled, this will flip the sense of inside and outside the implicit + // function (i.e., a rotation around the r-s-t=0.5 axis). + vtkSetMacro(FlipTexture,int); + vtkGetMacro(FlipTexture,int); + vtkBooleanMacro(FlipTexture,int); + +protected: + vtkImplicitTextureCoords(); + ~vtkImplicitTextureCoords(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkImplicitFunction *RFunction; + vtkImplicitFunction *SFunction; + vtkImplicitFunction *TFunction; + int FlipTexture; +private: + vtkImplicitTextureCoords(const vtkImplicitTextureCoords&); // Not implemented. + void operator=(const vtkImplicitTextureCoords&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkInterpolateDataSetAttributes.cxx b/Graphics/vtkInterpolateDataSetAttributes.cxx new file mode 100644 index 0000000..1fcf526 --- /dev/null +++ b/Graphics/vtkInterpolateDataSetAttributes.cxx @@ -0,0 +1,252 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInterpolateDataSetAttributes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInterpolateDataSetAttributes.h" + +#include "vtkCellData.h" +#include "vtkDataSetCollection.h" +#include "vtkExecutive.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkInterpolateDataSetAttributes, "$Revision: 1.29 $"); +vtkStandardNewMacro(vtkInterpolateDataSetAttributes); + +// Create object with no input or output. +vtkInterpolateDataSetAttributes::vtkInterpolateDataSetAttributes() +{ + this->InputList = vtkDataSetCollection::New(); + + this->T = 0.0; +} + +vtkInterpolateDataSetAttributes::~vtkInterpolateDataSetAttributes() +{ + if (this->InputList) + { + this->InputList->Delete(); + this->InputList = NULL; + } +} + +vtkDataSetCollection *vtkInterpolateDataSetAttributes::GetInputList() +{ + int i; + this->InputList->RemoveAllItems(); + + for (i = 0; i < this->GetNumberOfInputConnections(0); i++) + { + this->InputList->AddItem((vtkDataSet *)this->GetExecutive()->GetInputData(0, i)); + } + return this->InputList; +} + +// Interpolate the data +int vtkInterpolateDataSetAttributes::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells, i; + int numInputs = this->GetNumberOfInputConnections(0); + int lowDS, highDS; + vtkDataSet *ds, *ds2; + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkPointData *inputPD, *input2PD; + vtkCellData *inputCD, *input2CD; + double t; + + if ( numInputs < 2 ) + { + vtkErrorMacro(<< "Need at least two inputs to interpolate!"); + return 1; + } + + vtkDebugMacro(<<"Interpolating data..."); + + // Check input and determine between which data sets the interpolation + // is to occur. + if ( this->T > (double)numInputs ) + { + vtkErrorMacro(<<"Bad interpolation parameter"); + return 1; + } + + lowDS = (int) this->T; + if ( lowDS >= (numInputs-1) ) + { + lowDS = numInputs - 2; + } + + highDS = lowDS + 1; + t = this->T - (double)lowDS; + if (t > 1.0) + { + t =1.0; + } + + vtkInformation *dsInfo = inputVector[0]->GetInformationObject(lowDS); + vtkInformation *ds2Info = inputVector[0]->GetInformationObject(highDS); + ds = vtkDataSet::SafeDownCast(dsInfo->Get(vtkDataObject::DATA_OBJECT())); + ds2 = vtkDataSet::SafeDownCast(ds2Info->Get(vtkDataObject::DATA_OBJECT())); + + numPts = ds->GetNumberOfPoints(); + numCells = ds->GetNumberOfCells(); + + if ( numPts != ds2->GetNumberOfPoints() || + numCells != ds2->GetNumberOfCells() ) + { + vtkErrorMacro(<<"Data sets not consistent!"); + return 1; + } + + output->CopyStructure(ds); + inputPD = ds->GetPointData(); + inputCD = ds->GetCellData(); + input2PD = ds2->GetPointData(); + input2CD = ds2->GetCellData(); + + // Allocate the data set attributes + outputPD->CopyAllOff(); + if ( inputPD->GetScalars() && input2PD->GetScalars() ) + { + outputPD->CopyScalarsOn(); + } + if ( inputPD->GetVectors() && input2PD->GetVectors() ) + { + outputPD->CopyVectorsOn(); + } + if ( inputPD->GetNormals() && input2PD->GetNormals() ) + { + outputPD->CopyNormalsOn(); + } + if ( inputPD->GetTCoords() && input2PD->GetTCoords() ) + { + outputPD->CopyTCoordsOn(); + } + if ( inputPD->GetTensors() && input2PD->GetTensors() ) + { + outputPD->CopyTensorsOn(); + } + // *TODO* Fix + // if ( inputPD->GetFieldData() && input2PD->GetFieldData() ) + //{ + // outputPD->CopyFieldDataOn(); + //} + outputPD->InterpolateAllocate(inputPD); + + outputCD->CopyAllOff(); + if ( inputCD->GetScalars() && input2CD->GetScalars() ) + { + outputCD->CopyScalarsOn(); + } + if ( inputCD->GetVectors() && input2CD->GetVectors() ) + { + outputCD->CopyVectorsOn(); + } + if ( inputCD->GetNormals() && input2CD->GetNormals() ) + { + outputCD->CopyNormalsOn(); + } + if ( inputCD->GetTCoords() && input2CD->GetTCoords() ) + { + outputCD->CopyTCoordsOn(); + } + if ( inputCD->GetTensors() && input2CD->GetTensors() ) + { + outputCD->CopyTensorsOn(); + } + // *TODO* Fix + //if ( inputCD->GetFieldData() && input2CD->GetFieldData() ) + //{ + // outputCD->CopyFieldDataOn(); + // } + outputCD->InterpolateAllocate(inputCD); + + + // Interpolate point data. We'll assume that it takes 50% of the time + for ( i=0; i < numPts; i++ ) + { + if ( ! (i % 10000) ) + { + this->UpdateProgress ((double)i/numPts * 0.50); + if (this->GetAbortExecute()) + { + break; + } + } + + outputPD->InterpolateTime(inputPD, input2PD, i, t); + } + + // Interpolate cell data. We'll assume that it takes 50% of the time + for ( i=0; i < numCells; i++ ) + { + if ( ! (i % 10000) ) + { + this->UpdateProgress (0.5 + (double)i/numCells * 0.50); + if (this->GetAbortExecute()) + { + break; + } + } + + outputCD->InterpolateTime(inputCD, input2CD, i, t); + } + + return 1; +} + +int vtkInterpolateDataSetAttributes::FillInputPortInformation( + int port, vtkInformation *info) +{ + if (!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return 1; +} + +void vtkInterpolateDataSetAttributes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "T: " << this->T << endl; +} + +//---------------------------------------------------------------------------- +void +vtkInterpolateDataSetAttributes +::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->InputList, "InputList"); +} diff --git a/Graphics/vtkInterpolateDataSetAttributes.h b/Graphics/vtkInterpolateDataSetAttributes.h new file mode 100644 index 0000000..1bb6012 --- /dev/null +++ b/Graphics/vtkInterpolateDataSetAttributes.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInterpolateDataSetAttributes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInterpolateDataSetAttributes - interpolate scalars, vectors, etc. and other dataset attributes +// .SECTION Description +// vtkInterpolateDataSetAttributes is a filter that interpolates data set +// attribute values between input data sets. The input to the filter +// must be datasets of the same type, same number of cells, and same +// number of points. The output of the filter is a data set of the same +// type as the input dataset and whose attribute values have been +// interpolated at the parametric value specified. +// +// The filter is used by specifying two or more input data sets (total of N), +// and a parametric value t (0 <= t <= N-1). The output will contain +// interpolated data set attributes common to all input data sets. (For +// example, if one input has scalars and vectors, and another has just +// scalars, then only scalars will be interpolated and output.) + +#ifndef __vtkInterpolateDataSetAttributes_h +#define __vtkInterpolateDataSetAttributes_h + +#include "vtkDataSetAlgorithm.h" + +class vtkDataSetCollection; + +class VTK_GRAPHICS_EXPORT vtkInterpolateDataSetAttributes : public vtkDataSetAlgorithm +{ +public: + static vtkInterpolateDataSetAttributes *New(); + vtkTypeRevisionMacro(vtkInterpolateDataSetAttributes,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the list of inputs to this filter. + vtkDataSetCollection *GetInputList(); + + // Description: + // Specify interpolation parameter t. + vtkSetClampMacro(T,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(T,double); + +protected: + vtkInterpolateDataSetAttributes(); + ~vtkInterpolateDataSetAttributes(); + + virtual void ReportReferences(vtkGarbageCollector*); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int FillInputPortInformation(int port, vtkInformation *info); + + vtkDataSetCollection *InputList; // list of data sets to interpolate + double T; // interpolation parameter + +private: + vtkInterpolateDataSetAttributes(const vtkInterpolateDataSetAttributes&); // Not implemented. + void operator=(const vtkInterpolateDataSetAttributes&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkInterpolatingSubdivisionFilter.cxx b/Graphics/vtkInterpolatingSubdivisionFilter.cxx new file mode 100644 index 0000000..e6d432b --- /dev/null +++ b/Graphics/vtkInterpolatingSubdivisionFilter.cxx @@ -0,0 +1,275 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInterpolatingSubdivisionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInterpolatingSubdivisionFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkEdgeTable.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkInterpolatingSubdivisionFilter, "$Revision: 1.27 $"); + +// Construct object with number of subdivisions set to 1. +vtkInterpolatingSubdivisionFilter::vtkInterpolatingSubdivisionFilter() +{ + this->NumberOfSubdivisions = 1; +} + +int vtkInterpolatingSubdivisionFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells; + int level; + vtkPoints *outputPts; + vtkCellArray *outputPolys; + vtkPointData *outputPD; + vtkCellData *outputCD; + vtkIntArray *edgeData; + + numPts=input->GetNumberOfPoints(); + numCells=input->GetNumberOfCells(); + + if (numPts < 1 || numCells < 1) + { + vtkDebugMacro(<<"No data to interpolate!"); + return 1; + } + + // + // Initialize and check input + // + + vtkPolyData *inputDS = vtkPolyData::New(); + inputDS->CopyStructure (input); + inputDS->GetPointData()->PassData(input->GetPointData()); + inputDS->GetCellData()->PassData(input->GetCellData()); + + // check for triangles in input; if none, stop execution + inputDS->BuildLinks(); + vtkCellArray *polys = inputDS->GetPolys(); + int hasTris = 0; + vtkIdType numCellPts = 0, *pts = 0; + polys->InitTraversal(); + + while(polys->GetNextCell(numCellPts, pts)) + { + if (numCellPts == 3) + { + if (inputDS->IsTriangle(pts[0], pts[1], pts[2])) + { + hasTris = 1; + break; + } + } + } + + if (!hasTris) + { + vtkWarningMacro( << this->GetClassName() << " only operates on triangles, but this data set has no triangles to operate on."); + inputDS->Delete(); + return 1; + } + + for (level = 0; level < this->NumberOfSubdivisions; level++) + { + // Generate topology for the input dataset + inputDS->BuildLinks(); + numCells = inputDS->GetNumberOfCells (); + + // Copy points from input. The new points will include the old points + // and points calculated by the subdivision algorithm + outputPts = vtkPoints::New(); + outputPts->GetData()->DeepCopy(inputDS->GetPoints()->GetData()); + + // Copy pointdata structure from input + outputPD = vtkPointData::New(); + outputPD->CopyAllocate(inputDS->GetPointData(), + 2*inputDS->GetNumberOfPoints()); + + // Copy celldata structure from input + outputCD = vtkCellData::New(); + outputCD->CopyAllocate(inputDS->GetCellData(),4*numCells); + + // Create triangles + outputPolys = vtkCellArray::New(); + outputPolys->Allocate(outputPolys->EstimateSize(4*numCells,3)); + + // Create an array to hold new location indices + edgeData = vtkIntArray::New(); + edgeData->SetNumberOfComponents(3); + edgeData->SetNumberOfTuples(numCells); + + this->GenerateSubdivisionPoints (inputDS, edgeData, outputPts, outputPD); + this->GenerateSubdivisionCells (inputDS, edgeData, outputPolys, outputCD); + + // start the next iteration with the input set to the output we just created + edgeData->Delete(); + inputDS->Delete(); + inputDS = vtkPolyData::New(); + inputDS->SetPoints(outputPts); outputPts->Delete(); + inputDS->SetPolys(outputPolys); outputPolys->Delete(); + inputDS->GetPointData()->PassData(outputPD); outputPD->Delete(); + inputDS->GetCellData()->PassData(outputCD); outputCD->Delete(); + inputDS->Squeeze(); + } // each level + + output->SetPoints(inputDS->GetPoints()); + output->SetPolys(inputDS->GetPolys()); + output->GetPointData()->PassData(inputDS->GetPointData()); + output->GetCellData()->PassData(inputDS->GetCellData()); + inputDS->Delete(); + + return 1; +} + +int vtkInterpolatingSubdivisionFilter::FindEdge (vtkPolyData *mesh, + vtkIdType cellId, + vtkIdType p1, vtkIdType p2, + vtkIntArray *edgeData, + vtkIdList *cellIds) +{ + int edgeId = 0; + int currentCellId = 0; + int i; + int numEdges; + vtkIdType tp1, tp2; + vtkCell *cell; + + // get all the cells that use the edge (except for cellId) + mesh->GetCellEdgeNeighbors (cellId, p1, p2, cellIds); + + // find the edge that has the point we are looking for + for ( i=0; i < cellIds->GetNumberOfIds(); i++) + { + currentCellId = cellIds->GetId(i); + cell = mesh->GetCell(currentCellId); + numEdges = cell->GetNumberOfEdges(); + tp1 = cell->GetPointId(2); + tp2 = cell->GetPointId(0); + for (edgeId=0; edgeId < numEdges; edgeId++) + { + if ( (tp1 == p1 && tp2 == p2) || + (tp2 == p1 && tp1 == p2)) + { + // found the edge, return the stored value + return (int) edgeData->GetComponent(currentCellId,edgeId); + } + tp1 = tp2; + tp2 = cell->GetPointId(edgeId + 1); + } + } + vtkErrorMacro("Edge should have been found... but couldn't find it!!"); + return 0; +} + +vtkIdType vtkInterpolatingSubdivisionFilter::InterpolatePosition ( + vtkPoints *inputPts, vtkPoints *outputPts, + vtkIdList *stencil, double *weights) +{ + double xx[3], x[3]; + int i, j; + + for (j = 0; j < 3; j++) + { + x[j] = 0.0; + } + + for (i = 0; i < stencil->GetNumberOfIds(); i++) + { + inputPts->GetPoint(stencil->GetId(i), xx); + for (j = 0; j < 3; j++) + { + x[j] += xx[j] * weights[i]; + } + } + return outputPts->InsertNextPoint (x); +} + + +void vtkInterpolatingSubdivisionFilter::GenerateSubdivisionCells (vtkPolyData *inputDS, vtkIntArray *edgeData, vtkCellArray *outputPolys, vtkCellData *outputCD) +{ + vtkIdType numCells = inputDS->GetNumberOfCells(); + vtkIdType cellId, newId; + int id; + vtkIdType npts; + vtkIdType *pts; + double edgePts[3]; + vtkIdType newCellPts[3]; + vtkCellData *inputCD = inputDS->GetCellData(); + + // Now create new cells from existing points and generated edge points + for (cellId=0; cellId < numCells; cellId++) + { + if ( inputDS->GetCellType(cellId) != VTK_TRIANGLE ) + { + continue; + } + // get the original point ids and the ids stored as cell data + inputDS->GetCellPoints(cellId, npts, pts); + edgeData->GetTuple(cellId, edgePts); + + id = 0; + newCellPts[id++] = pts[0]; + newCellPts[id++] = (int) edgePts[1]; + newCellPts[id++] = (int) edgePts[0]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + + id = 0; + newCellPts[id++] = (int) edgePts[1]; + newCellPts[id++] = pts[1]; + newCellPts[id++] = (int) edgePts[2]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + + id = 0; + newCellPts[id++] = (int) edgePts[2]; + newCellPts[id++] = pts[2]; + newCellPts[id++] = (int) edgePts[0]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + + id = 0; + newCellPts[id++] = (int) edgePts[1]; + newCellPts[id++] = (int) edgePts[2]; + newCellPts[id++] = (int) edgePts[0]; + newId = outputPolys->InsertNextCell (3, newCellPts); + outputCD->CopyData (inputCD, cellId, newId); + } +} + +void vtkInterpolatingSubdivisionFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of subdivisions: " << this->NumberOfSubdivisions << endl; +} + + diff --git a/Graphics/vtkInterpolatingSubdivisionFilter.h b/Graphics/vtkInterpolatingSubdivisionFilter.h new file mode 100644 index 0000000..b0819cc --- /dev/null +++ b/Graphics/vtkInterpolatingSubdivisionFilter.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInterpolatingSubdivisionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInterpolatingSubdivisionFilter - generate a subdivision surface using an Interpolating Scheme +// .SECTION Description +// vtkInterpolatingSubdivisionFilter is an abstract class that defines +// the protocol for interpolating subdivision surface filters. + +// .SECTION Thanks +// This work was supported by PHS Research Grant No. 1 P41 RR13218-01 +// from the National Center for Research Resources. + +// .SECTION See Also +// vtkLinearSubdivisionFilter vtkButterflySubdivisionFilter + +#ifndef __vtkInterpolatingSubdivisionFilter_h +#define __vtkInterpolatingSubdivisionFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkCellData; +class vtkIdList; +class vtkIntArray; +class vtkPointData; +class vtkPoints; +class vtkPolyData; + +class VTK_GRAPHICS_EXPORT vtkInterpolatingSubdivisionFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkInterpolatingSubdivisionFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/get the number of subdivisions. + vtkSetMacro(NumberOfSubdivisions,int); + vtkGetMacro(NumberOfSubdivisions,int); + +protected: + vtkInterpolatingSubdivisionFilter(); + ~vtkInterpolatingSubdivisionFilter() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual void GenerateSubdivisionPoints (vtkPolyData *inputDS, vtkIntArray *edgeData, vtkPoints *outputPts, vtkPointData *outputPD) = 0; + void GenerateSubdivisionCells (vtkPolyData *inputDS, vtkIntArray *edgeData, vtkCellArray *outputPolys, vtkCellData *outputCD); + int FindEdge (vtkPolyData *mesh, vtkIdType cellId, vtkIdType p1, + vtkIdType p2, vtkIntArray *edgeData, vtkIdList *cellIds); + vtkIdType InterpolatePosition (vtkPoints *inputPts, vtkPoints *outputPts, + vtkIdList *stencil, double *weights); + int NumberOfSubdivisions; + +private: + vtkInterpolatingSubdivisionFilter(const vtkInterpolatingSubdivisionFilter&); // Not implemented. + void operator=(const vtkInterpolatingSubdivisionFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkKdNode.cxx b/Graphics/vtkKdNode.cxx new file mode 100644 index 0000000..f602cf0 --- /dev/null +++ b/Graphics/vtkKdNode.cxx @@ -0,0 +1,940 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkKdNode.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkKdNode.h" +#include "vtkCell.h" +#include "vtkBox.h" +#include "vtkMath.h" +#include "vtkPoints.h" +#include "vtkPlanesIntersection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkKdNode, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkKdNode); +vtkCxxSetObjectMacro(vtkKdNode, Left, vtkKdNode); +vtkCxxSetObjectMacro(vtkKdNode, Right, vtkKdNode); +vtkCxxSetObjectMacro(vtkKdNode, Up, vtkKdNode); + +//---------------------------------------------------------------------------- +vtkKdNode::vtkKdNode() +{ + this->Up = this->Left = this->Right = NULL; + this->Dim = 3; + this->ID = -1; + this->MinID = -1; + this->MaxID = -1; + this->NumberOfPoints= 0; +} + +//---------------------------------------------------------------------------- +vtkKdNode::~vtkKdNode() +{ +} + +//---------------------------------------------------------------------------- +void vtkKdNode::SetBounds(double x1,double x2,double y1,double y2,double z1,double z2) +{ + this->Min[0] = x1; this->Max[0] = x2; + this->Min[1] = y1; this->Max[1] = y2; + this->Min[2] = z1; this->Max[2] = z2; +} +//---------------------------------------------------------------------------- +void vtkKdNode::SetMinBounds(double *b) +{ + this->Min[0] = b[0]; + this->Min[1] = b[1]; + this->Min[2] = b[2]; +} + +//---------------------------------------------------------------------------- +void vtkKdNode::SetMaxBounds(double *b) +{ + this->Max[0] = b[0]; + this->Max[1] = b[1]; + this->Max[2] = b[2]; +} + +//---------------------------------------------------------------------------- +void vtkKdNode::SetMinDataBounds(double *b) +{ + this->MinVal[0] = b[0]; + this->MinVal[1] = b[1]; + this->MinVal[2] = b[2]; +} + +//---------------------------------------------------------------------------- +void vtkKdNode::SetMaxDataBounds(double *b) +{ + this->MaxVal[0] = b[0]; + this->MaxVal[1] = b[1]; + this->MaxVal[2] = b[2]; +} + + +//---------------------------------------------------------------------------- +void vtkKdNode::GetBounds(double *b) const +{ + b[0] = this->Min[0]; b[1] = this->Max[0]; + b[2] = this->Min[1]; b[3] = this->Max[1]; + b[4] = this->Min[2]; b[5] = this->Max[2]; +} + +//---------------------------------------------------------------------------- +void vtkKdNode::SetDataBounds(double x1,double x2,double y1,double y2,double z1,double z2) +{ + this->MinVal[0] = x1; this->MaxVal[0] = x2; + this->MinVal[1] = y1; this->MaxVal[1] = y2; + this->MinVal[2] = z1; this->MaxVal[2] = z2; +} + +//---------------------------------------------------------------------------- +void vtkKdNode::SetDataBounds(float *v) +{ + int x; + double newbounds[6]; + + vtkIdType numPoints = this->GetNumberOfPoints(); + + int i; + + if (this->Up) + { + double bounds[6]; + + this->Up->GetDataBounds(bounds); + + int dim = this->Up->GetDim(); + + for (i=0; i<3; i++) + { + if (i == dim) + { + continue; + } + + newbounds[i*2] = bounds[i*2]; + newbounds[i*2+1] = bounds[i*2+1]; + } + + newbounds[dim*2] = newbounds[dim*2+1] = (double)v[dim]; + + for (i = dim+3; i< numPoints*3; i+=3) + { + if (v[i] < newbounds[dim*2]) + { + newbounds[dim*2] = (double)v[i]; + } + else if (v[i] > newbounds[dim*2+1]) + { + newbounds[dim*2+1] = (double)v[i]; + } + } + } + else + { + for (i=0; i<3; i++) + { + newbounds[i*2] = newbounds[i*2+1] = (double)v[i]; + } + + for (x = 3; x< numPoints*3; x+=3) + { + int y=x+1; + int z=x+2; + + if (v[x] < newbounds[0]) + { + newbounds[0] = (double)v[x]; + } + else if (v[x] > newbounds[1]) + { + newbounds[1] = (double)v[x]; + } + + if (v[y] < newbounds[2]) + { + newbounds[2] = (double)v[y]; + } + else if (v[y] > newbounds[3]) + { + newbounds[3] = (double)v[y]; + } + + if (v[z] < newbounds[4]) + { + newbounds[4] = (double)v[z]; + } + else if (v[z] > newbounds[5]) + { + newbounds[5] = (double)v[z]; + } + } + } + + this->SetDataBounds(newbounds[0], newbounds[1], newbounds[2], + newbounds[3], newbounds[4], newbounds[5]); +} + +//---------------------------------------------------------------------------- +void vtkKdNode::GetDataBounds(double *b) const +{ + b[0] = this->MinVal[0]; b[1] = this->MaxVal[0]; + b[2] = this->MinVal[1]; b[3] = this->MaxVal[1]; + b[4] = this->MinVal[2]; b[5] = this->MaxVal[2]; +} + +//---------------------------------------------------------------------------- +// Distance (squared) from any point anywhere to the boundary of spatial region +// +double vtkKdNode::GetDistance2ToBoundary(double x, double y, double z, + int useDataBounds=0) +{ + return this->_GetDistance2ToBoundary(x, y, z, NULL, 0, useDataBounds); +} + +//---------------------------------------------------------------------------- +// Distance (squared) from any point anywhere to the boundary of spatial region, +// and give me the point on the boundary closest to this point. +// +double vtkKdNode::GetDistance2ToBoundary(double x, double y, double z, double *p, + int useDataBounds=0) +{ + return this->_GetDistance2ToBoundary(x, y, z, p, 0, useDataBounds); +} + +//---------------------------------------------------------------------------- +// The point is inside the region, and I want the distance (squared) +// to the closest "interior" wall, one that is not an outer boundary of +// the entire space. +// + +double vtkKdNode::GetDistance2ToInnerBoundary(double x, double y, double z) +{ + return this->_GetDistance2ToBoundary(x, y, z, NULL, 1, 0); +} + +double vtkKdNode::_GetDistance2ToBoundary( + double x, double y, double z, // from this point + double *p, // set to point on boundary that is closest + int innerBoundaryOnly, // ignore boundaries on "outside" + int useDataBounds=0) // use bounds of data within region instead +{ + double minDistance, dist; + double edgePt[3]; + double cornerPt[3]; + double pt3[3]; + + double *min, *max; + + if (useDataBounds) + { + min = this->MinVal; max = this->MaxVal; // data inside region + } + else + { + min = this->Min; max = this->Max; // region itself + } + + double *outerBoundaryMin=NULL; + double *outerBoundaryMax=NULL; + + if (innerBoundaryOnly) + { + // We want the distance to the nearest inner boundary, because we are only + // interested in boundaries such that there may be points on the other + // side. This option only makes sense when the point supplied is + // inside this node (region). + + vtkKdNode *top = this; + vtkKdNode *up = this->Up; + + while(up) { top = up; up = up->Up; } + + outerBoundaryMin = (useDataBounds? top->MinVal : top->Min); + outerBoundaryMax = (useDataBounds? top->MaxVal : top->Max); + } + + double xmax = max[0]; double ymax = max[1]; double zmax = max[2]; + double xmin = min[0]; double ymin = min[1]; double zmin = min[2]; + + int xless = (x < xmin); + int xmore = (x > xmax); + int yless = (y < ymin); + int ymore = (y > ymax); + int zless = (z < zmin); + int zmore = (z > zmax); + + int withinX = !xless && !xmore; + int withinY = !yless && !ymore; + int withinZ = !zless && !zmore; + + int mindim=0; + + if (withinX && withinY && withinZ) // point is inside the box + { + if (!innerBoundaryOnly) + { + minDistance = x - xmin; + mindim = 0; + + if ((dist = xmax - x) < minDistance) + { + mindim = 1; + minDistance = dist; + } + if ((dist = y - ymin) < minDistance) + { + mindim = 2; + minDistance = dist; + } + if ((dist = ymax - y) < minDistance) + { + mindim = 3; + minDistance = dist; + } + if ((dist = z - zmin) < minDistance) + { + mindim = 4; + minDistance = dist; + } + if ((dist = zmax - z) < minDistance) + { + mindim = 5; + minDistance = dist; + } + } + else + { + int first = 1; + minDistance = VTK_LARGE_FLOAT; // Suppresses warning message. + + if ((xmin != outerBoundaryMin[0]) && + (((dist = x - xmin) < minDistance) || first)) + { + mindim = 0; + minDistance = dist; + first = 0; + } + if ((xmax != outerBoundaryMax[0]) && + (((dist = xmax - x) < minDistance) || first)) + { + mindim = 1; + minDistance = dist; + first = 0; + } + if ((ymin != outerBoundaryMin[1]) && + (((dist = y - ymin) < minDistance) || first)) + { + mindim = 2; + minDistance = dist; + first = 0; + } + if ((ymax != outerBoundaryMax[1]) && + (((dist = ymax - y) < minDistance) || first)) + { + mindim = 3; + minDistance = dist; + first = 0; + } + if ((zmin != outerBoundaryMin[2]) && + (((dist = z - zmin) < minDistance) || first)) + { + mindim = 4; + minDistance = dist; + first = 0; + } + if ((zmax != outerBoundaryMax[2]) && + (((dist = zmax - z) < minDistance) || first)) + { + mindim = 5; + minDistance = dist; + } + } + + minDistance *= minDistance; + + if (p) + { + p[0] = x; p[1] = y; p[2] = z; + + + if (mindim == 0) + { + p[0] = xmin; + } + else if (mindim == 1) + { + p[0] = xmax; + } + else if (mindim == 2) + { + p[1] = ymin; + } + else if (mindim == 3) + { + p[1] = ymax; + } + else if (mindim == 4) + { + p[2] = zmin; + } + else if (mindim == 5) + { + p[2] = zmax; + } + } + } + else if (withinX && withinY) // point projects orthogonally to a face + { + minDistance = (zless ? zmin - z : z - zmax); + minDistance *= minDistance; + + if (p) + { + p[0] = x; p[1] = y; + p[2] = (zless ? zmin : zmax); + } + } + else if (withinX && withinZ) + { + minDistance = (yless ? ymin - y : y - ymax); + minDistance *= minDistance; + + if (p) + { + p[0] = x; p[2] = z; + p[1] = (yless ? ymin : ymax); + } + } + else if (withinY && withinZ) + { + minDistance = (xless ? xmin - x : x - xmax); + minDistance *= minDistance; + + if (p) + { + p[1] = y; p[2] = z; + p[0] = (xless ? xmin: xmax); + } + } + else if (withinX || withinY || withinZ) // point is closest to an edge + { + edgePt[0] = (withinX ? x : (xless ? xmin : xmax)); + edgePt[1] = (withinY ? y : (yless ? ymin : ymax)); + edgePt[2] = (withinZ ? z : (zless ? zmin : zmax)); + + pt3[0] = x; pt3[1] = y; pt3[2] = z; + + minDistance = vtkMath::Distance2BetweenPoints(pt3, edgePt); + + if (p) + { + p[0] = edgePt[0]; p[1] = edgePt[1]; p[2] = edgePt[2]; + } + } + else // point is closest to a corner + { + cornerPt[0] = (xless ? xmin : xmax); + cornerPt[1] = (yless ? ymin : ymax); + cornerPt[2] = (zless ? zmin : zmax); + + pt3[0] = x; pt3[1] = y; pt3[2] = z; + + minDistance = vtkMath::Distance2BetweenPoints(pt3, cornerPt); + + if (p) + { + p[0] = cornerPt[0]; p[1] = cornerPt[1]; p[2] = cornerPt[2]; + } + } + + return minDistance; +} + +//---------------------------------------------------------------------------- +void vtkKdNode::AddChildNodes(vtkKdNode *left, vtkKdNode *right) +{ + this->DeleteChildNodes(); + + if (left) + { + this->SetLeft(left); + left->SetUp(this); + } + + if (right) + { + this->SetRight(right); + right->SetUp(this); + } +} + +//---------------------------------------------------------------------------- +void vtkKdNode::DeleteChildNodes() +{ + if (this->GetLeft()) + { + this->GetLeft()->SetUp(NULL); + this->SetLeft(NULL); + } + + if (this->GetRight()) + { + this->GetRight()->SetUp(NULL); + this->SetRight(NULL); + } +} +//---------------------------------------------------------------------------- +int vtkKdNode::IntersectsBox(double x0, double x1, double y0, double y1, + double z0, double z1, int useDataBounds=0) +{ + double *min, *max; + + if (useDataBounds) + { + min = this->MinVal; + max = this->MaxVal; + } + else + { + min = this->Min; + max = this->Max; + } + + if ( (min[0] >= x1) || + (max[0] < x0) || + (min[1] >= y1) || + (max[1] < y0) || + (min[2] >= z1) || + (max[2] < z0)) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +int vtkKdNode::IntersectsSphere2(double x, double y, double z, double rSquared, + int useDataBounds=0) +{ + int center = this->ContainsPoint(x, y, z, useDataBounds); + + if (center) + { + return 1; + } + + double dist2 = this->GetDistance2ToBoundary(x, y, z, useDataBounds); + + if (dist2 < rSquared) + { + return 1; + } + + return 0; +} + +//---------------------------------------------------------------------------- +int vtkKdNode::ContainsBox(double x0, double x1, double y0, double y1, + double z0, double z1, int useDataBounds=0) +{ + double *min, *max; + + if (useDataBounds) + { + min = this->MinVal; + max = this->MaxVal; + } + else + { + min = this->Min; + max = this->Max; + } + + if ( (min[0] >= x0) || + (max[0] < x1) || + (min[1] >= y0) || + (max[1] < y1) || + (min[2] >= z0) || + (max[2] < z1)) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +int vtkKdNode::ContainsPoint(double x, double y, double z, int useDataBounds=0) +{ + double *min, *max; + + if (useDataBounds) + { + min = this->MinVal; + max = this->MaxVal; + } + else + { + min = this->Min; + max = this->Max; + } + + // points on a boundary are arbitrarily assigned to the region + // for which they are on the upper boundary + + if ( (min[0] >= x) || + (max[0] < x) || + (min[1] >= y) || + (max[1] < y) || + (min[2] >= z) || + (max[2] < z)) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- +int vtkKdNode::IntersectsRegion(vtkPlanesIntersection *pi, int useDataBounds) +{ + double x0, x1, y0, y1, z0, z1; + vtkPoints *box = vtkPoints::New(); + + box->SetNumberOfPoints(8); + + double *min, *max; + + if (useDataBounds) + { + min = this->MinVal; + max = this->MaxVal; + } + else + { + min = this->Min; + max = this->Max; + } + + x0 = min[0]; x1 = max[0]; + y0 = min[1]; y1 = max[1]; + z0 = min[2]; z1 = max[2]; + + box->SetPoint(0, x1, y0, z1); + box->SetPoint(1, x1, y0, z0); + box->SetPoint(2, x1, y1, z0); + box->SetPoint(3, x1, y1, z1); + box->SetPoint(4, x0, y0, z1); + box->SetPoint(5, x0, y0, z0); + box->SetPoint(6, x0, y1, z0); + box->SetPoint(7, x0, y1, z1); + + int intersects = pi->IntersectsRegion(box); + + box->Delete(); + + return intersects; +} + +//---------------------------------------------------------------------------- +int vtkKdNode::IntersectsCell(vtkCell *cell, int useDataBounds, int cellRegion, + double *bounds) +{ + int i; + + if ((useDataBounds==0) && (cellRegion >= 0)) + { + if ( (cellRegion >= this->MinID) && (cellRegion <= this->MaxID)) + { + return 1; // the cell centroid is contained in this spatial region + } + } + + double *cellBounds = NULL; + int deleteCellBounds = (bounds == NULL); + + if (deleteCellBounds) + { + cellBounds = new double [6]; + + vtkPoints *pts = cell->GetPoints(); + pts->Modified(); // VTK bug - so bounds will be re-calculated + pts->GetBounds(cellBounds); + } + else + { + cellBounds = bounds; + } + + int intersects = -1; + int dim = cell->GetCellDimension(); + + if (!this->IntersectsBox(cellBounds[0], cellBounds[1], + cellBounds[2], cellBounds[3], + cellBounds[4], cellBounds[5], useDataBounds) ) + { + intersects = 0; // cell bounding box is outside region + } + else if ( this->ContainsBox(cellBounds[0], cellBounds[1], + cellBounds[2], cellBounds[3], + cellBounds[4], cellBounds[5], useDataBounds) ) + { + intersects = 1; // cell bounding box is completely inside region + } + else + { + // quick test - if any of the points are in this region, + // then it intersects + + vtkPoints *pts = cell->GetPoints(); + int npts = pts->GetNumberOfPoints(); + + for (i=0; i < npts ; i++) + { + double *pt = pts->GetPoint(i); + if (this->ContainsPoint(pt[0],pt[1],pt[2], useDataBounds)) + { + intersects = 1; + break; + } + } + + if ((dim == 0) && (intersects != 1)) + { + intersects = 0; // it's a point set and no points intersect + } + } + + if (intersects != -1) + { + if (deleteCellBounds) + { + delete [] cellBounds; + } + return intersects; + } + + vtkPoints *pts = cell->Points; + int npts = pts->GetNumberOfPoints(); + + // determine if cell intersects region + + intersects = 0; + + if (dim == 1) // lines + { + double *p2 = pts->GetPoint(0); + double *p1; + double dir[3], x[3], t; + + double regionBounds[6]; + + this->GetBounds(regionBounds); + + for (i=0; i < npts - 1 ; i++) + { + p1 = p2; + p2 = p1 + 3; + + dir[0] = p2[0] - p1[0]; dir[1] = p2[1] - p1[1]; dir[2] = p2[2] - p1[2]; + + char result = vtkBox::IntersectBox(regionBounds, p1, dir, x, t); + + intersects = (result != 0); + + if (intersects) + { + break; + } + } + } + else if (dim == 2) // polygons + { + double *min, *max; + + if (useDataBounds) + { + min = this->MinVal; + max = this->MaxVal; + } + else + { + min = this->Min; + max = this->Max; + } + double regionBounds[6]; + + regionBounds[0] = min[0], regionBounds[1] = max[0]; + regionBounds[2] = min[1], regionBounds[3] = max[1]; + regionBounds[4] = min[2], regionBounds[5] = max[2]; + + if (cell->GetCellType() == VTK_TRIANGLE_STRIP) + { + vtkPoints *triangle = vtkPoints::New(); + + triangle->SetNumberOfPoints(3); + + triangle->SetPoint(0, pts->GetPoint(0)); + triangle->SetPoint(1, pts->GetPoint(1)); + + int newpoint = 2; + + for (i=2; iSetPoint(newpoint, pts->GetPoint(i)); + + newpoint = (newpoint == 2) ? 0 : newpoint+1; + + intersects = + vtkPlanesIntersection::PolygonIntersectsBBox(regionBounds, triangle); + + if (intersects) + { + break; + } + } + triangle->Delete(); + } + else + { + intersects = + vtkPlanesIntersection::PolygonIntersectsBBox(regionBounds, pts); + } + } + else if (dim == 3) // 3D cells + { + vtkPlanesIntersection *pi = vtkPlanesIntersection::Convert3DCell(cell); + + intersects = this->IntersectsRegion(pi, useDataBounds); + + pi->Delete(); + } + + if (deleteCellBounds) + { + delete [] cellBounds; + } + + return intersects; +} + +//---------------------------------------------------------------------------- +void vtkKdNode::PrintNode(int depth) +{ + if ( (depth < 0) || (depth > 19)) + { + depth = 19; + } + + for (int i=0; iMin[0] << ", " << this->Max[0] << ") "; + cout << " y (" << this->Min[1] << ", " << this->Max[1] << ") "; + cout << " z (" << this->Min[2] << ", " << this->Max[2] << ") "; + cout << this->NumberOfPoints << " cells, "; + + if (this->ID > -1) + { + cout << this->ID << " (leaf node)" << endl; + } + else + { + cout << this->MinID << " - " << this->MaxID << endl; + } +} + +//---------------------------------------------------------------------------- +void vtkKdNode::PrintVerboseNode(int depth) +{ + int i; + + if ( (depth < 0) || (depth > 19)) + { + depth = 19; + } + + for (i=0; iMin[0] << ", " << this->Max[0] << ") "; + cout << " y (" << this->Min[1] << ", " << this->Max[1] << ") "; + cout << " z (" << this->Min[2] << ", " << this->Max[2] << ") " << endl; + + for (i=0; iMinVal[0] << ", " << this->MaxVal[0] << ") "; + cout << " y (" << this->MinVal[1] << ", " << this->MaxVal[1] << ") "; + cout << " z (" << this->MinVal[2] << ", " << this->MaxVal[2] << ") " << endl; + + for (i=0; iNumberOfPoints << " cells, "; + + if (this->ID == -1) + { + cout << "id range " << this->MinID << " - " << this->MaxID << ", "; + } + else + { + cout << "id " << this->ID << ", "; + } + + cout << "cut next along " << this->Dim << ", left "; + cout << (void *)this->Left << ", right "; + cout << (void *)this->Right << ", up " << (void *)this->Up << endl; +} +void vtkKdNode::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfPoints: " << this->NumberOfPoints << endl; + os << indent << "Up: " << this->Up << endl; + os << indent << "Left: " << this->Left << endl; + os << indent << "Right: " << this->Right << endl; + os << indent << "Dim: " << this->Dim << endl; + os << indent << "ID: " << this->ID << endl; + os << indent << "MinID: " << this->MinID << endl; + os << indent << "MaxID: " << this->MaxID << endl; + os << indent << "Min: " << Min[0] << " " << Min[1] << " " << Min[2] << endl; + os << indent << "Max: " << Max[0] << " " << Max[1] << " " << Max[2] << endl; + os << indent << "MinVal: " << MinVal[0] << " " << MinVal[1] << " " << MinVal[2] << endl; + os << indent << "MaxVal: " << MaxVal[0] << " " << MaxVal[1] << " " << MaxVal[2] << endl; +} diff --git a/Graphics/vtkKdNode.h b/Graphics/vtkKdNode.h new file mode 100644 index 0000000..7c3e966 --- /dev/null +++ b/Graphics/vtkKdNode.h @@ -0,0 +1,277 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkKdNode.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkKdNode - This class represents a single spatial region +// in an 3D axis aligned binary spatial partitioning. It is assumed +// the region bounds some set of points. Regions are represented +// as nodes in a binary tree. +// +// .SECTION Description +// +// .SECTION See Also +// vtkKdTree vtkOBSPCuts + +#ifndef __vtkKdNode_h +#define __vtkKdNode_h + +#include "vtkObject.h" + +class vtkCell; +class vtkPlanesIntersection; + +class VTK_GRAPHICS_EXPORT vtkKdNode : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkKdNode, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkKdNode *New(); + + // Description: + // Set/Get the dimension along which this region is divided. + // (0 - x, 1 - y, 2 - z, 3 - leaf node (default)). + + vtkSetMacro(Dim, int); + vtkGetMacro(Dim, int); + + // Description: + // Set/Get the number of points contained in this region. + + vtkSetMacro(NumberOfPoints, int); + vtkGetMacro(NumberOfPoints, int); + + // Description: + // Set/Get the bounds of the spatial region represented by this node. + // Caller allocates storage for 6-vector in GetBounds. + + void SetBounds(double x1,double x2,double y1,double y2,double z1,double z2); + void GetBounds(double *b) const; + + // Description: + // Set/Get the bounds of the points contained in this spatial region. + // This may be smaller than the bounds of the region itself. + // Caller allocates storage for 6-vector in GetDataBounds. + + void SetDataBounds(double x1,double x2,double y1,double y2,double z1,double z2); + void GetDataBounds(double *b) const; + + // Description: + // Given a pointer to NumberOfPoints points, set the DataBounds of this + // node to the bounds of these points. + + void SetDataBounds(float *v); + + // Description: + // Get a pointer to the 3 bound minima (xmin, ymin and zmin) or the + // 3 bound maxima (xmax, ymax, zmax). Don't free this pointer. + + double *GetMinBounds() {return this->Min;} + double *GetMaxBounds() {return this->Max;} + + // Description: + // Set the xmin, ymin and zmin value of the bounds of this region + + void SetMinBounds(double *mb); + + // Description: + // Set the xmax, ymax and zmax value of the bounds of this region + + void SetMaxBounds(double *mb); + + // Description: + // Get a pointer to the 3 data bound minima (xmin, ymin and zmin) or the + // 3 data bound maxima (xmax, ymax, zmax). Don't free this pointer. + + double *GetMinDataBounds() {return this->MinVal;} + double *GetMaxDataBounds() {return this->MaxVal;} + + // Description: + // Set the xmin, ymin and zmin value of the bounds of this + // data within this region + + void SetMinDataBounds(double *mb); + + // Description: + // Set the xmax, ymax and zmax value of the bounds of this + // data within this region + + void SetMaxDataBounds(double *mb); + + // Description: + // Set/Get the ID associated with the region described by this node. If + // this is not a leaf node, this value should be -1. + + vtkSetMacro(ID, int); + vtkGetMacro(ID, int); + + // Description: + // If this node is not a leaf node, there are leaf nodes below it whose + // regions represent a partitioning of this region. The IDs of these + // leaf nodes form a contigous set. Set/Get the range of the IDs of + // the leaf nodes below this node. If this is already a leaf node, these + // values should be the same as the ID. + + vtkGetMacro(MinID, int); + vtkGetMacro(MaxID, int); + vtkSetMacro(MinID, int); + vtkSetMacro(MaxID, int); + + // Description: + // Add the left and right children. + + void AddChildNodes(vtkKdNode *left, vtkKdNode *right); + + // Description: + // Delete the left and right children. + + void DeleteChildNodes(); + + // Description: + // Set/Get a pointer to the left child of this node. + + vtkGetObjectMacro(Left, vtkKdNode); + void SetLeft(vtkKdNode* left); + + // Description: + // Set/Get a pointer to the right child of this node. + + vtkGetObjectMacro(Right, vtkKdNode); + void SetRight(vtkKdNode *right); + + // Description: + // Set/Get a pointer to the parent of this node. + + vtkGetObjectMacro(Up, vtkKdNode); + void SetUp(vtkKdNode* up); + + // Description: + // Return 1 if this spatial region intersects the axis-aligned box given + // by the bounds passed in. Use the possibly smaller bounds of the points + // within the region if useDataBounds is non-zero. + + int IntersectsBox(double x1,double x2,double y1,double y2,double z1,double z2, + int useDataBounds); + + // Description: + // Return 1 if this spatial region intersects a sphere described by + // it's center and the square of it's radius. Use the possibly smaller + // bounds of the points within the region if useDataBounds is non-zero. + + int IntersectsSphere2(double x, double y, double z, double rSquared, + int useDataBounds); + + // Description: + // A vtkPlanesIntersection object represents a convex 3D region bounded + // by planes, and it is capable of computing intersections of + // boxes with itself. Return 1 if this spatial region intersects + // the spatial region described by the vtkPlanesIntersection object. + // Use the possibly smaller bounds of the points within the region + // if useDataBounds is non-zero. + + int IntersectsRegion(vtkPlanesIntersection *pi, int useDataBounds); + + // Description: + // Return 1 if the cell specified intersects this region. If you + // already know the ID of the region containing the cell's centroid, + // provide that as an argument. If you already know the bounds of the + // cell, provide that as well, in the form of xmin,xmax,ymin,ymax,zmin, + // zmax. Either of these may speed the calculation. + // Use the possibly smaller bounds of the points within the region + // if useDataBounds is non-zero. + + int IntersectsCell(vtkCell *cell, int useDataBounds, + int cellRegion=-1, double *cellBounds=NULL); + + // Description: + // Return 1 if this spatial region entirely contains a box specified + // by it's bounds. Use the possibly smaller + // bounds of the points within the region if useDataBounds is non-zero. + + int ContainsBox(double x1,double x2,double y1,double y2,double z1,double z2, + int useDataBounds); + + // Description: + // Return 1 if this spatial region entirely contains the given point. + // Use the possibly smaller bounds of the points within the region + // if useDataBounds is non-zero. + + int ContainsPoint(double x, double y, double z, int useDataBounds); + + // Description: + // Calculate the distance squared from any point to the boundary of this + // region. Use the boundary of the points within the region if useDataBounds + // is non-zero. + + double GetDistance2ToBoundary(double x, double y, double z, int useDataBounds); + + // Description: + // Calculate the distance squared from any point to the boundary of this + // region. Use the boundary of the points within the region if useDataBounds + // is non-zero. Set boundaryPt to the point on the boundary. + + double GetDistance2ToBoundary(double x, double y, double z, double *boundaryPt, + int useDataBounds); + + // Description: + // Calculate the distance from the specified point (which is required to + // be inside this spatial region) to an interior boundary. An interior + // boundary is one that is not also an boundary of the entire space + // partitioned by the tree of vtkKdNode's. + + double GetDistance2ToInnerBoundary(double x, double y, double z); + + // Description: + // For debugging purposes, print out this node. + + void PrintNode(int depth); + void PrintVerboseNode(int depth); + +protected: + + vtkKdNode(); + ~vtkKdNode(); + +private: + + double _GetDistance2ToBoundary(double x, double y, double z, double *boundaryPt, + int innerBoundaryOnly, int useDataBounds); + + double Min[3]; // spatial bounds of node + double Max[3]; // spatial bounds of node + double MinVal[3]; // spatial bounds of data within node + double MaxVal[3]; // spatial bounds of data within node + int NumberOfPoints; + + vtkKdNode *Up; + + vtkKdNode *Left; + vtkKdNode *Right; + + int Dim; + + int ID; // region id + + int MinID; + int MaxID; + + vtkKdNode(const vtkKdNode&); // Not implemented + void operator=(const vtkKdNode&); // Not implemented +}; + +#endif diff --git a/Graphics/vtkKdTree.cxx b/Graphics/vtkKdTree.cxx new file mode 100644 index 0000000..a3e6f93 --- /dev/null +++ b/Graphics/vtkKdTree.cxx @@ -0,0 +1,4233 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkKdTree.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkKdTree.h" +#include "vtkKdNode.h" +#include "vtkBSPCuts.h" +#include "vtkBSPIntersections.h" +#include "vtkObjectFactory.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkGarbageCollector.h" +#include "vtkIdList.h" +#include "vtkPolyData.h" +#include "vtkPoints.h" +#include "vtkIdTypeArray.h" +#include "vtkIntArray.h" +#include "vtkPointSet.h" +#include "vtkImageData.h" +#include "vtkUniformGrid.h" +#include "vtkRectilinearGrid.h" + +#ifdef _MSC_VER +#pragma warning ( disable : 4100 ) +#endif +#include +#include + +vtkCxxRevisionMacro(vtkKdTree, "$Revision: 1.4 $"); + +// Timing data --------------------------------------------- + +#include "vtkTimerLog.h" + +#define MSGSIZE 60 + +static char dots[MSGSIZE] = "..........................................................."; +static char msg[MSGSIZE]; + +//---------------------------------------------------------------------------- +static char * makeEntry(const char *s) +{ + memcpy(msg, dots, MSGSIZE); + int len = strlen(s); + len = (len >= MSGSIZE) ? MSGSIZE-1 : len; + + memcpy(msg, s, len); + + return msg; +} + +#define TIMER(s) \ + if (this->Timing) \ + { \ + char *s2 = makeEntry(s); \ + if (this->TimerLog == NULL){ \ + this->TimerLog = vtkTimerLog::New(); \ + } \ + this->TimerLog->MarkStartEvent(s2); \ + } + +#define TIMERDONE(s) \ + if (this->Timing){ char *s2 = makeEntry(s); this->TimerLog->MarkEndEvent(s2); } + +// Timing data --------------------------------------------- + +vtkStandardNewMacro(vtkKdTree); + +//---------------------------------------------------------------------------- +vtkKdTree::vtkKdTree() +{ + this->FudgeFactor = 0; + this->MaxWidth = 0.0; + this->MaxLevel = 20; + this->Level = 0; + + this->NumberOfRegionsOrLess = 0; + this->NumberOfRegionsOrMore = 0; + + this->ValidDirections = + (1 << vtkKdTree::XDIM) | (1 << vtkKdTree::YDIM) | (1 << vtkKdTree::ZDIM); + + this->MinCells = 100; + this->NumberOfRegions = 0; + + this->DataSets = NULL; + this->NumDataSets = 0; + + this->Top = NULL; + this->RegionList = NULL; + + this->Timing = 0; + this->TimerLog = NULL; + + this->NumDataSetsAllocated = 0; + this->IncludeRegionBoundaryCells = 0; + this->GenerateRepresentationUsingDataBounds = 0; + + this->InitializeCellLists(); + this->CellRegionList = NULL; + + this->NumberOfLocatorPoints = 0; + this->LocatorPoints = NULL; + this->LocatorIds = NULL; + this->LocatorRegionLocation = NULL; + + this->LastDataCacheSize = 0; + this->ClearLastBuildCache(); + + this->BSPCalculator = NULL; + this->Cuts = NULL; + this->UserDefinedCuts = 0; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::DeleteAllDescendants(vtkKdNode *nd) +{ + vtkKdNode *left = nd->GetLeft(); + vtkKdNode *right = nd->GetRight(); + + if (left && left->GetLeft()) + { + vtkKdTree::DeleteAllDescendants(left); + } + + if (right && right->GetLeft()) + { + vtkKdTree::DeleteAllDescendants(right); + } + + if (left && right) + { + nd->DeleteChildNodes(); // undo AddChildNodes + left->Delete(); // undo vtkKdNode::New() + right->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::InitializeCellLists() +{ + this->CellList.dataSet = NULL; + this->CellList.regionIds = NULL; + this->CellList.nRegions = 0; + this->CellList.cells = NULL; + this->CellList.boundaryCells = NULL; + this->CellList.emptyList = NULL; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::DeleteCellLists() +{ + int i; + int num = this->CellList.nRegions; + + if (this->CellList.regionIds) + { + delete [] this->CellList.regionIds; + } + + if (this->CellList.cells) + { + for (i=0; iCellList.cells[i]->Delete(); + } + + delete [] this->CellList.cells; + } + + if (this->CellList.boundaryCells) + { + for (i=0; iCellList.boundaryCells[i]->Delete(); + } + delete [] this->CellList.boundaryCells; + } + + if (this->CellList.emptyList) + { + this->CellList.emptyList->Delete(); + } + + this->InitializeCellLists(); + + return; +} + +//---------------------------------------------------------------------------- +vtkKdTree::~vtkKdTree() +{ + if (this->DataSets) + { + for (int i=0; iNumDataSetsAllocated; i++) + { + this->SetNthDataSet(i, NULL); + } + delete [] (this->DataSets); + } + + this->FreeSearchStructure(); + + this->DeleteCellLists(); + + if (this->CellRegionList) + { + delete [] this->CellRegionList; + this->CellRegionList = NULL; + } + + if (this->TimerLog) + { + this->TimerLog->Delete(); + } + + this->ClearLastBuildCache(); + + this->SetCalculator(NULL); + this->SetCuts(NULL); +} +//---------------------------------------------------------------------------- +void vtkKdTree::SetCalculator(vtkKdNode *kd) +{ + if (this->BSPCalculator) + { + this->BSPCalculator->Delete(); + this->BSPCalculator = NULL; + } + + if (!this->UserDefinedCuts) + { + this->SetCuts(NULL, 0); + } + + if (kd == NULL) + { + return; + } + + if (!this->UserDefinedCuts) + { + vtkBSPCuts *cuts = vtkBSPCuts::New(); + cuts->CreateCuts(kd); + this->SetCuts(cuts, 0); + } + + this->BSPCalculator = vtkBSPIntersections::New(); + this->BSPCalculator->SetCuts(this->Cuts); +} +//---------------------------------------------------------------------------- +void vtkKdTree::SetCuts(vtkBSPCuts *cuts) +{ + this->SetCuts(cuts, 1); +} +//---------------------------------------------------------------------------- +void vtkKdTree::SetCuts(vtkBSPCuts *cuts, int userDefined) +{ + if (userDefined != 0) + { + userDefined = 1; + } + + if ((cuts == this->Cuts) && (userDefined == this->UserDefinedCuts)) + { + return; + } + + this->Modified(); + + if (this->Cuts) + { + if (this->UserDefinedCuts) + { + this->Cuts->UnRegister(this); + } + else + { + this->Cuts->Delete(); + } + + this->Cuts = NULL; + this->UserDefinedCuts = 0; + } + + if (cuts == NULL) + { + return; + } + + this->Cuts = cuts; + this->UserDefinedCuts = userDefined; + + if (this->UserDefinedCuts) + { + this->Cuts->Register(this); + } +} +//---------------------------------------------------------------------------- +// Add and remove data sets. We don't update this->Modify() here, because +// changing the data sets doesn't necessarily require rebuilding the +// k-d tree. We only need to build a new k-d tree in BuildLocator if +// the geometry has changed, and we check for that with NewGeometry in +// BuildLocator. We Modify() for changes that definitely require a +// rebuild of the tree, like changing the depth of the k-d tree. + +void vtkKdTree::SetNthDataSet(int idx, vtkDataSet *set) +{ + if (idx < 0) + { + vtkErrorMacro(<< "vtkKdTree::SetNthDataSet invalid index"); + return; + } + + if (idx >= this->NumDataSetsAllocated) + { + int oldSize = this->NumDataSetsAllocated; + int newSize = oldSize + 4; + + vtkDataSet **tmp = this->DataSets; + this->DataSets = new vtkDataSet * [newSize]; + + if (!this->DataSets) + { + vtkErrorMacro(<<"vtkKdTree::SetDataSet memory allocation"); + return; + } + + memset(this->DataSets, 0, sizeof(vtkDataSet *) * newSize); + + if (tmp) + { + memcpy(this->DataSets, tmp, sizeof(vtkDataSet *) * oldSize); + delete [] tmp; + } + + this->NumDataSetsAllocated = newSize; + } + + if (this->DataSets[idx] == set) + { + return; + } + + if (this->DataSets[idx]) + { + this->DataSets[idx]->UnRegister(this); + this->NumDataSets--; + } + + this->DataSets[idx] = set; + + if (set) + { + this->DataSets[idx]->Register(this); + this->NumDataSets++; + } + + if (idx == 0) + { + vtkLocator::SetDataSet(set); + } +} +void vtkKdTree::SetDataSet(vtkDataSet *set) +{ + this->SetNthDataSet(0, set); +} +void vtkKdTree::AddDataSet(vtkDataSet *set) +{ + if (set == NULL) + { + return; + } + + int firstSlot = this->NumDataSetsAllocated; + + for (int i=0; i < this->NumDataSetsAllocated; i++) + { + if (this->DataSets[i] == set) + { + return; // already have it + } + if ((firstSlot == this->NumDataSetsAllocated) && (this->DataSets[i] == NULL)) + { + firstSlot = i; + } + } + + this->SetNthDataSet(firstSlot, set); +} +void vtkKdTree::RemoveDataSet(vtkDataSet *set) +{ + if (set == NULL) + { + return; + } + + int i; + int removeSet = -1; + + for (i=0; iNumDataSetsAllocated; i++) + { + if (this->DataSets[i] == set) + { + removeSet = i; + break; + } + } + if (removeSet >= 0) + { + this->RemoveDataSet(removeSet); + } + else + { + vtkErrorMacro( << "vtkKdTree::RemoveDataSet not a valid data set"); + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::RemoveDataSet(int which) +{ + if ( (which < 0) || (which >= this->NumDataSetsAllocated)) + { + vtkErrorMacro( << "vtkKdTree::RemoveDataSet not a valid data set"); + return; + } + + if (this->CellList.dataSet == this->DataSets[which]) + { + this->DeleteCellLists(); + } + + if (this->DataSets[which]) + { + this->DataSets[which]->UnRegister(this); + this->DataSets[which] = NULL; + this->NumDataSets--; + } +} +vtkDataSet *vtkKdTree::GetDataSet(int n) +{ + if ((n < 0) || + (n >= this->NumDataSets)) + { + vtkErrorMacro(<< "vtkKdTree::GetDataSet. invalid data set number"); + return NULL; + } + + int set = -1; + + for (int i=0; iNumDataSetsAllocated; i++) + { + if (this->DataSets[i]) + { + set++; + if (set == n) + { + break; + } + } + } + + if (set >= 0) + { + return this->DataSets[set]; + } + else + { + return NULL; + } +} +int vtkKdTree::GetDataSet(vtkDataSet *set) +{ + int i; + int whichSet = -1; + + for (i=0; iNumDataSetsAllocated; i++) + { + if (this->DataSets[i] == set) + { + whichSet = i; + break; + } + } + return whichSet; +} +int vtkKdTree::GetDataSetsNumberOfCells(int from, int to) +{ + int numCells = 0; + + for (int i=from; i<=to; i++) + { + if (this->DataSets[i]) + { + numCells += this->DataSets[i]->GetNumberOfCells(); + } + } + + return numCells; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::GetNumberOfCells() +{ + return this->GetDataSetsNumberOfCells(0, this->NumDataSetsAllocated - 1); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::GetBounds(double *bounds) +{ + if (this->Top) + { + this->Top->GetBounds(bounds); + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::GetRegionBounds(int regionID, double bounds[6]) +{ + if ( (regionID < 0) || (regionID >= this->NumberOfRegions)) + { + vtkErrorMacro( << "vtkKdTree::GetRegionBounds invalid region"); + return; + } + + vtkKdNode *node = this->RegionList[regionID]; + + node->GetBounds(bounds); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::GetRegionDataBounds(int regionID, double bounds[6]) +{ + if ( (regionID < 0) || (regionID >= this->NumberOfRegions)) + { + vtkErrorMacro( << "vtkKdTree::GetRegionDataBounds invalid region"); + return; + } + + vtkKdNode *node = this->RegionList[regionID]; + + node->GetDataBounds(bounds); +} + +//---------------------------------------------------------------------------- +vtkKdNode **vtkKdTree::_GetRegionsAtLevel(int level, vtkKdNode **nodes, vtkKdNode *kd) +{ + if (level > 0) + { + vtkKdNode **nodes0 = _GetRegionsAtLevel(level-1, nodes, kd->GetLeft()); + vtkKdNode **nodes1 = _GetRegionsAtLevel(level-1, nodes0, kd->GetRight()); + + return nodes1; + } + else + { + nodes[0] = kd; + return nodes+1; + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::GetRegionsAtLevel(int level, vtkKdNode **nodes) +{ + if ( (level < 0) || (level > this->Level)) + { + return; + } + + vtkKdTree::_GetRegionsAtLevel(level, nodes, this->Top); + + return; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::GetLeafNodeIds(vtkKdNode *node, vtkIntArray *ids) +{ + int id = node->GetID(); + + if (id < 0) + { + vtkKdTree::GetLeafNodeIds(node->GetLeft(), ids); + vtkKdTree::GetLeafNodeIds(node->GetRight(), ids); + } + else + { + ids->InsertNextValue(id); + } + return; +} + +//---------------------------------------------------------------------------- +float *vtkKdTree::ComputeCellCenters() +{ + vtkDataSet *allSets = NULL; + return this->ComputeCellCenters(allSets); +} + +//---------------------------------------------------------------------------- +float *vtkKdTree::ComputeCellCenters(int set) +{ + if ( (set < 0) || + (set >= this->NumDataSetsAllocated) || + (this->DataSets[set] == NULL)) + { + vtkErrorMacro(<<"vtkKdTree::ComputeCellCenters no such data set"); + return NULL; + } + return this->ComputeCellCenters(this->DataSets[set]); +} + +//---------------------------------------------------------------------------- +float *vtkKdTree::ComputeCellCenters(vtkDataSet *set) +{ + int i,j; + int totalCells; + + if (set) + { + totalCells = set->GetNumberOfCells(); + } + else + { + totalCells = this->GetNumberOfCells(); // all data sets + } + + if (totalCells == 0) + { + return NULL; + } + + float *center = new float [3 * totalCells]; + + if (!center) + { + return NULL; + } + + int maxCellSize = 0; + + if (set) + { + maxCellSize = set->GetMaxCellSize(); + } + else + { + for (i=0; iNumDataSetsAllocated; i++) + { + if (this->DataSets[i]) + { + int cellSize = this->DataSets[i]->GetMaxCellSize(); + maxCellSize = (cellSize > maxCellSize) ? cellSize : maxCellSize; + } + } + } + + double *weights = new double [maxCellSize]; + + float *cptr = center; + double dcenter[3]; + + if (set) + { + for (j=0; jComputeCellCenter(set->GetCell(j), dcenter, weights); + cptr[0] = (float)dcenter[0]; + cptr[1] = (float)dcenter[1]; + cptr[2] = (float)dcenter[2]; + cptr += 3; + } + } + else + { + for (i=0; iNumDataSetsAllocated; i++) + { + if (!this->DataSets[i]) + { + continue; + } + + vtkDataSet *iset = this->DataSets[i]; + + int nCells = iset->GetNumberOfCells(); + + for (j=0; jComputeCellCenter(iset->GetCell(j), dcenter, weights); + cptr[0] = (float)dcenter[0]; + cptr[1] = (float)dcenter[1]; + cptr[2] = (float)dcenter[2]; + cptr += 3; + } + } + } + + delete [] weights; + + return center; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::ComputeCellCenter(vtkDataSet *set, int cellId, float *center) +{ + double dcenter[3]; + + this->ComputeCellCenter(set, cellId, dcenter); + + center[0] = (float)dcenter[0]; + center[1] = (float)dcenter[1]; + center[2] = (float)dcenter[2]; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::ComputeCellCenter(vtkDataSet *set, int cellId, double *center) +{ + int setNum; + + if (set) + { + setNum = this->GetDataSet(set); + + if ( setNum < 0) + { + vtkErrorMacro(<<"vtkKdTree::ComputeCellCenter invalid data set"); + return; + } + } + else + { + setNum = 0; + set = this->DataSets[0]; + } + + if ( (cellId < 0) || (cellId >= set->GetNumberOfCells())) + { + vtkErrorMacro(<<"vtkKdTree::ComputeCellCenter invalid cell ID"); + return; + } + + double *weights = new double [set->GetMaxCellSize()]; + + this->ComputeCellCenter(set->GetCell(cellId), center, weights); + + delete [] weights; + + return; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::ComputeCellCenter(vtkCell *cell, double *center, double *weights) +{ + double pcoords[3]; + + int subId = cell->GetParametricCenter(pcoords); + + cell->EvaluateLocation(subId, pcoords, center, weights); + + return; +} + +//---------------------------------------------------------------------------- +// Build the kdtree structure based on location of cell centroids. +// +void vtkKdTree::BuildLocator() +{ + + int nCells=0; + int i; + + if ((this->Top != NULL) && + (this->BuildTime > this->GetMTime()) && + (this->NewGeometry() == 0)) + { + return; + } + + nCells = this->GetNumberOfCells(); + + if (nCells == 0) + { + vtkErrorMacro( << "vtkKdTree::BuildLocator - No cells to subdivide"); + return; + } + + vtkDebugMacro( << "Creating Kdtree" ); + + if ((this->Timing) && (this->TimerLog == NULL)) + { + this->TimerLog = vtkTimerLog::New(); + } + + TIMER("Set up to build k-d tree"); + + this->FreeSearchStructure(); + + // volume bounds - push out a little if flat + + double setBounds[6], volBounds[6]; + int first = 1; + + for (i=0; iNumDataSetsAllocated; i++) + { + if (this->DataSets[i] == NULL) + { + continue; + } + + this->DataSets[i]->Update(); + if (first) + { + this->DataSets[i]->GetBounds(volBounds); + first = 0; + } + else + { + this->DataSets[i]->GetBounds(setBounds); + if (setBounds[0] < volBounds[0]) + { + volBounds[0] = setBounds[0]; + } + if (setBounds[2] < volBounds[2]) + { + volBounds[2] = setBounds[2]; + } + if (setBounds[4] < volBounds[4]) + { + volBounds[4] = setBounds[4]; + } + if (setBounds[1] > volBounds[1]) + { + volBounds[1] = setBounds[1]; + } + if (setBounds[3] > volBounds[3]) + { + volBounds[3] = setBounds[3]; + } + if (setBounds[5] > volBounds[5]) + { + volBounds[5] = setBounds[5]; + } + } + } + + double diff[3], aLittle = 0.0; + this->MaxWidth = 0.0; + + for (i=0; i<3; i++) + { + diff[i] = volBounds[2*i+1] - volBounds[2*i]; + this->MaxWidth = static_cast( + (diff[i] > this->MaxWidth) ? diff[i] : this->MaxWidth); + } + + this->FudgeFactor = this->MaxWidth * 10e-6; + + aLittle = this->MaxWidth / 100.0; + + for (i=0; i<3; i++) + { + if (diff[i] <= 0) + { + volBounds[2*i] -= aLittle; + volBounds[2*i+1] += aLittle; + } + else // need lower bound to be strictly less than any point in decomposition + { + volBounds[2*i] -= this->FudgeFactor; + } + } + TIMERDONE("Set up to build k-d tree"); + + if (this->UserDefinedCuts) + { + // Actually, we will not compute the k-d tree. We will use a + // k-d tree provided to us. + + int fail = this->ProcessUserDefinedCuts(volBounds); + + if (fail) + { + return; + } + } + else + { + // cell centers - basis of spacial decomposition + + TIMER("Create centroid list"); + + float *ptarray = this->ComputeCellCenters(); + + TIMERDONE("Create centroid list"); + + if (!ptarray) + { + vtkErrorMacro( << "vtkKdTree::BuildLocator - insufficient memory"); + return; + } + + // create kd tree structure that balances cell centers + + vtkKdNode *kd = this->Top = vtkKdNode::New(); + + kd->SetBounds((double)volBounds[0], (double)volBounds[1], + (double)volBounds[2], (double)volBounds[3], + (double)volBounds[4], (double)volBounds[5]); + + kd->SetNumberOfPoints(nCells); + + kd->SetDataBounds((double)volBounds[0], (double)volBounds[1], + (double)volBounds[2], (double)volBounds[3], + (double)volBounds[4], (double)volBounds[5]); + + TIMER("Build tree"); + + this->DivideRegion(kd, ptarray, NULL, 0); + + TIMERDONE("Build tree"); + + // In the process of building the k-d tree regions, + // the cell centers became reordered, so no point + // in saving them, for example to build cell lists. + + delete [] ptarray; + } + + this->SetActualLevel(); + this->BuildRegionList(); + + this->UpdateBuildTime(); + + this->SetCalculator(this->Top); + + return; +} + +int vtkKdTree::ProcessUserDefinedCuts(double *minBounds) +{ + if (!this->Cuts) + { + vtkErrorMacro(<< "vtkKdTree::ProcessUserDefinedCuts - no cuts" ); + return 1; + } + // Fix the bounds for the entire partitioning. They must be at + // least as large of the bounds of all the data sets. + + vtkKdNode *kd = this->Cuts->GetKdNodeTree(); + double bounds[6]; + kd->GetBounds(bounds); + int fixBounds = 0; + + for (int j=0; j<3; j++) + { + int min = 2*j; + int max = min+1; + + if (minBounds[min] < bounds[min]) + { + bounds[min] = minBounds[min]; + fixBounds = 1; + } + if (minBounds[max] > bounds[max]) + { + bounds[max] = minBounds[max]; + fixBounds = 1; + } + } + + this->Top = vtkKdTree::CopyTree(kd); + + if (fixBounds) + { + this->SetNewBounds(bounds); + } + + // We don't really know the data bounds, so we'll just set them + // to the spatial bounds. + + vtkKdTree::SetDataBoundsToSpatialBounds(this->Top); + + // And, we don't know how many points are in each region. The number + // in the provided vtkBSPCuts object was for some other dataset. So + // we zero out those fields. + + vtkKdTree::ZeroNumberOfPoints(this->Top); + + return 0; +} +//---------------------------------------------------------------------------- +void vtkKdTree::ZeroNumberOfPoints(vtkKdNode *kd) +{ + kd->SetNumberOfPoints(0); + + if (kd->GetLeft()) + { + vtkKdTree::ZeroNumberOfPoints(kd->GetLeft()); + vtkKdTree::ZeroNumberOfPoints(kd->GetRight()); + } +} +//---------------------------------------------------------------------------- +void vtkKdTree::SetNewBounds(double *bounds) +{ + vtkKdNode *kd = this->Top; + + if (!kd) + { + return; + } + + int fixDimLeft[6], fixDimRight[6]; + int go=0; + + double kdb[6]; + kd->GetBounds(kdb); + + for (int i=0; i<3; i++) + { + int min = 2*i; + int max = 2*i + 1; + + fixDimLeft[min] = fixDimRight[min] = 0; + fixDimLeft[max] = fixDimRight[max] = 0; + + if (kdb[min] > bounds[min]) + { + kdb[min] = bounds[min]; + go = fixDimLeft[min] = fixDimRight[min] = 1; + } + if (kdb[max] < bounds[max]) + { + kdb[max] = bounds[max]; + go = fixDimLeft[max] = fixDimRight[max] = 1; + } + } + + if (go) + { + kd->SetBounds(kdb[0],kdb[1],kdb[2],kdb[3],kdb[4],kdb[5]); + + if (kd->GetLeft()) + { + int cutDim = kd->GetDim() * 2; + + fixDimLeft[cutDim + 1] = 0; + vtkKdTree::_SetNewBounds(kd->GetLeft(), bounds, fixDimLeft); + + fixDimRight[cutDim] = 0; + vtkKdTree::_SetNewBounds(kd->GetRight(), bounds, fixDimRight); + } + } +} +//---------------------------------------------------------------------------- +void vtkKdTree::_SetNewBounds(vtkKdNode *kd, double *b, int *fixDim) +{ + int go=0; + int fixDimLeft[6], fixDimRight[6]; + + double kdb[6]; + kd->GetBounds(kdb); + + for (int i=0; i<6; i++) + { + if (fixDim[i]) + { + kdb[i] = b[i]; + go = 1; + } + fixDimLeft[i] = fixDim[i]; + fixDimRight[i] = fixDim[i]; + } + + if (go) + { + kd->SetBounds(kdb[0],kdb[1],kdb[2],kdb[3],kdb[4],kdb[5]); + + if (kd->GetLeft()) + { + int cutDim = kd->GetDim() * 2; + + fixDimLeft[cutDim + 1] = 0; + vtkKdTree::_SetNewBounds(kd->GetLeft(), b, fixDimLeft); + + fixDimRight[cutDim] = 0; + vtkKdTree::_SetNewBounds(kd->GetRight(), b, fixDimRight); + } + } +} +//---------------------------------------------------------------------------- +vtkKdNode *vtkKdTree::CopyTree(vtkKdNode *kd) +{ + vtkKdNode *top = vtkKdNode::New(); + vtkKdTree::CopyKdNode(top, kd); + vtkKdTree::CopyChildNodes(top, kd); + + return top; +} +//---------------------------------------------------------------------------- +void vtkKdTree::CopyChildNodes(vtkKdNode *to, vtkKdNode *from) +{ + if (from->GetLeft()) + { + vtkKdNode *left = vtkKdNode::New(); + vtkKdNode *right = vtkKdNode::New(); + + vtkKdTree::CopyKdNode(left, from->GetLeft()); + vtkKdTree::CopyKdNode(right, from->GetRight()); + + to->AddChildNodes(left, right); + + vtkKdTree::CopyChildNodes(to->GetLeft(), from->GetLeft()); + vtkKdTree::CopyChildNodes(to->GetRight(), from->GetRight()); + } +} +//---------------------------------------------------------------------------- +void vtkKdTree::CopyKdNode(vtkKdNode *to, vtkKdNode *from) +{ + to->SetMinBounds(from->GetMinBounds()); + to->SetMaxBounds(from->GetMaxBounds()); + to->SetMinDataBounds(from->GetMinDataBounds()); + to->SetMaxDataBounds(from->GetMaxDataBounds()); + to->SetID(from->GetID()); + to->SetMinID(from->GetMinID()); + to->SetMaxID(from->GetMaxID()); + to->SetNumberOfPoints(from->GetNumberOfPoints()); + to->SetDim(from->GetDim()); +} + +//---------------------------------------------------------------------------- +int vtkKdTree::ComputeLevel(vtkKdNode *kd) +{ + if (!kd) + { + return 0; + } + + int iam = 1; + + if (kd->GetLeft() != NULL) + { + int depth1 = vtkKdTree::ComputeLevel(kd->GetLeft()); + int depth2 = vtkKdTree::ComputeLevel(kd->GetRight()); + + if (depth1 > depth2) + { + iam += depth1; + } + else + { + iam += depth2; + } + } + return iam; +} +//---------------------------------------------------------------------------- +void vtkKdTree::SetDataBoundsToSpatialBounds(vtkKdNode *kd) +{ + kd->SetMinDataBounds(kd->GetMinBounds()); + kd->SetMaxDataBounds(kd->GetMaxBounds()); + + if (kd->GetLeft()) + { + vtkKdTree::SetDataBoundsToSpatialBounds(kd->GetLeft()); + vtkKdTree::SetDataBoundsToSpatialBounds(kd->GetRight()); + } +} +//---------------------------------------------------------------------------- +int vtkKdTree::SelectCutDirection(vtkKdNode *kd) +{ + int dim=0, i; + + int xdir = 1 << vtkKdTree::XDIM; + int ydir = 1 << vtkKdTree::YDIM; + int zdir = 1 << vtkKdTree::ZDIM; + + // determine direction in which to divide this region + + if (this->ValidDirections == xdir) + { + dim = vtkKdTree::XDIM; + } + else if (this->ValidDirections == ydir) + { + dim = vtkKdTree::YDIM; + } + else if (this->ValidDirections == zdir) + { + dim = vtkKdTree::ZDIM; + } + else + { + // divide in the longest direction, for more compact regions + + double diff[3], dataBounds[6], maxdiff; + kd->GetDataBounds(dataBounds); + + for (i=0; i<3; i++) + { + diff[i] = dataBounds[i*2+1] - dataBounds[i*2]; + } + + maxdiff = -1.0; + + if ((this->ValidDirections & xdir) && (diff[vtkKdTree::XDIM] > maxdiff)) + { + dim = vtkKdTree::XDIM; + maxdiff = diff[vtkKdTree::XDIM]; + } + + if ((this->ValidDirections & ydir) && (diff[vtkKdTree::YDIM] > maxdiff)) + { + dim = vtkKdTree::YDIM; + maxdiff = diff[vtkKdTree::YDIM]; + } + + if ((this->ValidDirections & zdir) && (diff[vtkKdTree::ZDIM] > maxdiff)) + { + dim = vtkKdTree::ZDIM; + } + } + return dim; +} +//---------------------------------------------------------------------------- +int vtkKdTree::DivideTest(int size, int level) +{ + if (level >= this->MaxLevel) return 0; + + int minCells = this->GetMinCells(); + + if ((size < 2) || (minCells && (minCells > (size/2)))) return 0; + + int nRegionsNow = 1 << level; + int nRegionsNext = nRegionsNow << 1; + + if (this->NumberOfRegionsOrLess && (nRegionsNext > this->NumberOfRegionsOrLess)) return 0; + if (this->NumberOfRegionsOrMore && (nRegionsNow >= this->NumberOfRegionsOrMore)) return 0; + + return 1; +} +//---------------------------------------------------------------------------- +int vtkKdTree::DivideRegion(vtkKdNode *kd, float *c1, int *ids, int level) +{ + int ok = this->DivideTest(kd->GetNumberOfPoints(), level); + + if (!ok) + { + return 0; + } + + int maxdim = this->SelectCutDirection(kd); + + kd->SetDim(maxdim); + + int dim1 = maxdim; // best cut direction + int dim2 = -1; // other valid cut directions + int dim3 = -1; + + int otherDirections = this->ValidDirections ^ (1 << maxdim); + + if (otherDirections) + { + int x = otherDirections & (1 << vtkKdTree::XDIM); + int y = otherDirections & (1 << vtkKdTree::YDIM); + int z = otherDirections & (1 << vtkKdTree::ZDIM); + + if (x) + { + dim2 = vtkKdTree::XDIM; + + if (y) + { + dim3 = vtkKdTree::YDIM; + } + else if (z) + { + dim3 = vtkKdTree::ZDIM; + } + } + else if (y) + { + dim2 = vtkKdTree::YDIM; + + if (z) + { + dim3 = vtkKdTree::ZDIM; + } + } + else if (z) + { + dim2 = vtkKdTree::ZDIM; + } + } + + this->DoMedianFind(kd, c1, ids, dim1, dim2, dim3); + + if (kd->GetLeft() == NULL) + { + return 0; // unable to divide region further + } + + int nleft = kd->GetLeft()->GetNumberOfPoints(); + + int *leftIds = ids; + int *rightIds = ids ? ids + nleft : NULL; + + this->DivideRegion(kd->GetLeft(), c1, leftIds, level + 1); + + this->DivideRegion(kd->GetRight(), c1 + nleft*3, rightIds, level + 1); + + return 0; +} + +//---------------------------------------------------------------------------- +// Rearrange the point array. Try dim1 first. If there's a problem +// go to dim2, then dim3. +// +void vtkKdTree::DoMedianFind(vtkKdNode *kd, float *c1, int *ids, + int dim1, int dim2, int dim3) +{ + double coord; + int dim; + int midpt; + + int npoints = kd->GetNumberOfPoints(); + + int dims[3]; + + dims[0] = dim1; dims[1] = dim2; dims[2] = dim3; + + for (dim = 0; dim < 3; dim++) + { + if (dims[dim] < 0) + { + break; + } + + midpt = vtkKdTree::Select(dims[dim], c1, ids, npoints, coord); + + if (midpt == 0) + { + continue; // fatal + } + + kd->SetDim(dims[dim]); + + vtkKdTree::AddNewRegions(kd, c1, midpt, dims[dim], coord); + + break; // division is fine + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::AddNewRegions(vtkKdNode *kd, float *c1, int midpt, int dim, double coord) +{ + vtkKdNode *left = vtkKdNode::New(); + vtkKdNode *right = vtkKdNode::New(); + + int npoints = kd->GetNumberOfPoints(); + + int nleft = midpt; + int nright = npoints - midpt; + + kd->AddChildNodes(left, right); + + double bounds[6]; + kd->GetBounds(bounds); + + left->SetBounds( + bounds[0], ((dim == vtkKdTree::XDIM) ? coord : bounds[1]), + bounds[2], ((dim == vtkKdTree::YDIM) ? coord : bounds[3]), + bounds[4], ((dim == vtkKdTree::ZDIM) ? coord : bounds[5])); + + left->SetNumberOfPoints(nleft); + + right->SetBounds( + ((dim == vtkKdTree::XDIM) ? coord : bounds[0]), bounds[1], + ((dim == vtkKdTree::YDIM) ? coord : bounds[2]), bounds[3], + ((dim == vtkKdTree::ZDIM) ? coord : bounds[4]), bounds[5]); + + right->SetNumberOfPoints(nright); + + left->SetDataBounds(c1); + right->SetDataBounds(c1 + nleft*3); +} +// Use Floyd & Rivest (1975) to find the median: +// Given an array X with element indices ranging from L to R, and +// a K such that L <= K <= R, rearrange the elements such that +// X[K] contains the ith sorted element, where i = K - L + 1, and +// all the elements X[j], j < k satisfy X[j] < X[K], and all the +// elements X[j], j > k satisfy X[j] >= X[K]. + +#define Exchange(array, ids, x, y) \ + { \ + float temp[3]; \ + temp[0] = array[3*x]; \ + temp[1] = array[3*x + 1]; \ + temp[2] = array[3*x + 2]; \ + array[3*x] = array[3*y]; \ + array[3*x + 1] = array[3*y + 1]; \ + array[3*x + 2] = array[3*y + 2]; \ + array[3*y] = temp[0]; \ + array[3*y + 1] = temp[1]; \ + array[3*y + 2] = temp[2]; \ + if (ids) \ + { \ + vtkIdType tempid = ids[x]; \ + ids[x] = ids[y]; \ + ids[y] = tempid; \ + } \ +} + +#define sign(x) ((x<0) ? (-1) : (1)) +#ifndef max +#define max(x,y) ((x>y) ? (x) : (y)) +#endif +#ifndef min +#define min(x,y) ((x= c1[mid] + // + // In addition, by careful construction, there is a J <= mid + // such that + // + // All values c1[n], n < J, satisfy c1[n] < c1[mid] STRICTLY + // All values c1[n], J <= n <= mid, satisfy c1[n] = c1[mid] + // All values c1[n], mid < n <= right , satisfy c1[n] >= c1[mid] + // + // We need to roll back the "mid" value to the "J". This + // means our spatial regions are less balanced, but there + // is no ambiguity regarding which region a point belongs in. + + int midValIndex = mid*3 + dim; + + while ((mid > left) && (c1[midValIndex-3] == c1[midValIndex])) + { + mid--; + midValIndex -= 3; + } + + if (mid == left) + { + return mid; // failed to divide region + } + + float leftMax = vtkKdTree::FindMaxLeftHalf(dim, c1, mid); + + coord = ((double)c1[midValIndex] + (double)leftMax) / 2.0; + + return mid; +} + +//---------------------------------------------------------------------------- +float vtkKdTree::FindMaxLeftHalf(int dim, float *c1, int K) +{ + int i; + + float *Xcomponent = c1 + dim; + float max = Xcomponent[0]; + + for (i=3; i max) + { + max = Xcomponent[i]; + } + } + return max; +} + +//---------------------------------------------------------------------------- +// Note: The indices (L, R, X) into the point array should be vtkIdTypes rather +// than ints, but this change causes the k-d tree build time to double. +// _Select is the heart of this build, called for every sub-interval that +// is to be reordered. We will leave these as ints now. + +void vtkKdTree::_Select(int dim, float *X, int *ids, + int L, int R, int K) +{ + int N, I, J, S, SD, LL, RR; + float Z, T; + int manyTValues=0; + + while (R > L) + { + if ( R - L > 600) + { + // "Recurse on a sample of size S to get an estimate for the + // (K-L+1)-th smallest element into X[K], biased slightly so + // that the (K-L+1)-th element is expected to lie in the + // smaller set after partitioning" + + N = R - L + 1; + I = K - L + 1; + Z = static_cast(log((float)N)); + S = static_cast(.5 * exp(2*Z/3)); + SD = static_cast(.5 * sqrt(Z*S*((float)(N-S)/N)) * sign(I - N/2)); + LL = max(L, K - static_cast(I*((float)S/N)) + SD); + RR = min(R, K + static_cast((N-I) * ((float)S/N)) + SD); + _Select(dim, X, ids, LL, RR, K); + } + + float *Xcomponent = X + dim; // x, y or z component + + T = Xcomponent[K*3]; + + // "the following code partitions X[L:R] about T." + + I = L; + J = R; + + Exchange(X, ids, L, K); + + if (Xcomponent[R*3] >= T) + { + if (Xcomponent[R*3] == T) manyTValues++; + Exchange(X, ids, R, L); + } + while (I < J) + { + Exchange(X, ids, I, J); + + while (Xcomponent[(++I)*3] < T); + + while ((J>L) && (Xcomponent[(--J)*3] >= T)) + { + if (!manyTValues && (J>L) && (Xcomponent[J*3] == T)) + { + manyTValues = 1; + } + } + } + + if (Xcomponent[L*3] == T) + { + Exchange(X, ids, L, J); + } + else + { + J++; + Exchange(X, ids, J, R); + } + + if ((J < K) && manyTValues) + { + // Select has a worst case - when many of the same values + // are repeated in an array. It is bad enough that it is + // worth detecting and optimizing for. Here we're taking the + // interval of values that are >= T, and rearranging it into + // an interval of values = T followed by those > T. + + I = J; + J = R+1; + + while (I < J) + { + while ((++I < J) && (Xcomponent[I*3] == T)); + if (I == J) break; + + while ((--J > I) && (Xcomponent[J*3] > T)); + if (J == I) break; + + Exchange(X, ids, I, J); + } + + // I and J are at the first array element that is > T + // If K is within the sequence of T's, we're done, else + // move the new [L,R] interval to the sequence of values + // that are strictly greater than T. + + if (K < J) + { + J = K; + } + else + { + J = J-1; + } + } + + // "now adjust L,R so they surround the subset containing + // the (K-L+1)-th smallest element" + + if (J <= K) + { + L = J + 1; + } + if (K <= J) + { + R = J - 1; + } + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::SelfRegister(vtkKdNode *kd) +{ + if (kd->GetLeft() == NULL) + { + this->RegionList[kd->GetID()] = kd; + } + else + { + this->SelfRegister(kd->GetLeft()); + this->SelfRegister(kd->GetRight()); + } + + return; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::SelfOrder(int startId, vtkKdNode *kd) +{ + int nextId; + + if (kd->GetLeft() == NULL) + { + kd->SetID(startId); + kd->SetMaxID(startId); + kd->SetMinID(startId); + + nextId = startId + 1; + } + else + { + kd->SetID(-1); + nextId = vtkKdTree::SelfOrder(startId, kd->GetLeft()); + nextId = vtkKdTree::SelfOrder(nextId, kd->GetRight()); + + kd->SetMinID(startId); + kd->SetMaxID(nextId - 1); + } + + return nextId; +} + +void vtkKdTree::BuildRegionList() +{ + if (this->Top == NULL) + { + return; + } + + this->NumberOfRegions = vtkKdTree::SelfOrder(0, this->Top); + + this->RegionList = new vtkKdNode * [this->NumberOfRegions]; + + this->SelfRegister(this->Top); +} + +//---------------------------------------------------------------------------- +// K-d tree from points, for finding duplicate and near-by points +// +void vtkKdTree::BuildLocatorFromPoints(vtkPoints *ptArray) +{ + this->BuildLocatorFromPoints(&ptArray, 1); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::BuildLocatorFromPoints(vtkPoints **ptArrays, int numPtArrays) +{ + int ptId; + int i; + + int totalNumPoints = 0; + + for (i = 0; i < numPtArrays; i++) + { + totalNumPoints += ptArrays[i]->GetNumberOfPoints(); + } + + if (totalNumPoints < 1) + { + vtkErrorMacro(<< "vtkKdTree::BuildLocatorFromPoints - no points"); + return; + } + + if (totalNumPoints >= VTK_INT_MAX) + { + // The heart of the k-d tree build is the recursive median find in + // _Select. It rearranges point IDs along with points themselves. + // When point IDs are stored in an "int" instead of a vtkIdType, + // performance doubles. So we store point IDs in an "int" during + // the calculation. This will need to be rewritten if true 64 bit + // IDs are required. + + vtkErrorMacro(<< + "BuildLocatorFromPoints - intentional 64 bit error - time to rewrite code"); + return; + } + + vtkDebugMacro( << "Creating Kdtree" ); + + if ((this->Timing) && (this->TimerLog == NULL) ) + { + this->TimerLog = vtkTimerLog::New(); + } + + TIMER("Set up to build k-d tree"); + + this->FreeSearchStructure(); + this->ClearLastBuildCache(); + + // Fix bounds - (1) push out a little if flat + // (2) pull back the x, y and z lower bounds a little bit so that + // points are clearly "inside" the spatial region. Point p is + // "inside" region r = [r1, r2] if r1 < p <= r2. + + double bounds[6], diff[3]; + + ptArrays[0]->GetBounds(bounds); + + for (i=1; iGetBounds(tmpbounds); + + if (tmpbounds[0] < bounds[0]) + { + bounds[0] = tmpbounds[0]; + } + if (tmpbounds[2] < bounds[2]) + { + bounds[2] = tmpbounds[2]; + } + if (tmpbounds[4] < bounds[4]) + { + bounds[4] = tmpbounds[4]; + } + if (tmpbounds[1] > bounds[1]) + { + bounds[1] = tmpbounds[1]; + } + if (tmpbounds[3] > bounds[3]) + { + bounds[3] = tmpbounds[3]; + } + if (tmpbounds[5] > bounds[5]) + { + bounds[5] = tmpbounds[5]; + } + } + + this->MaxWidth = 0.0; + + for (i=0; i<3; i++) + { + diff[i] = bounds[2*i+1] - bounds[2*i]; + this->MaxWidth = (float) + ((diff[i] > this->MaxWidth) ? diff[i] : this->MaxWidth); + } + + this->FudgeFactor = this->MaxWidth * 10e-6; + + double aLittle = this->MaxWidth * 10e-2; + + for (i=0; i<3; i++) + { + if (diff[i] < aLittle) // case (1) above + { + double temp = bounds[2*i]; + bounds[2*i] = bounds[2*i+1] - aLittle; + bounds[2*i+1] = temp + aLittle; + } + else // case (2) above + { + bounds[2*i] -= this->FudgeFactor; + } + } + + // root node of k-d tree - it's the whole space + + vtkKdNode *kd = this->Top = vtkKdNode::New(); + + kd->SetBounds((double)bounds[0], (double)bounds[1], + (double)bounds[2], (double)bounds[3], + (double)bounds[4], (double)bounds[5]); + + kd->SetNumberOfPoints(totalNumPoints); + + kd->SetDataBounds((double)bounds[0], (double)bounds[1], + (double)bounds[2], (double)bounds[3], + (double)bounds[4], (double)bounds[5]); + + + this->LocatorIds = new int [totalNumPoints]; + this->LocatorPoints = new float [3 * totalNumPoints]; + + if ( !this->LocatorPoints || !this->LocatorIds) + { + this->FreeSearchStructure(); + vtkErrorMacro(<< "vtkKdTree::BuildLocatorFromPoints - memory allocation"); + return; + } + + int *ptIds = this->LocatorIds; + float *points = this->LocatorPoints; + + for (i=0, ptId = 0; iGetNumberOfPoints(); + int nvals = npoints * 3; + + int pointArrayType = ptArrays[i]->GetDataType(); + + if (pointArrayType == VTK_FLOAT) + { + vtkDataArray *da = ptArrays[i]->GetData(); + vtkFloatArray *fa = vtkFloatArray::SafeDownCast(da); + memcpy(points + ptId, fa->GetPointer(0), sizeof(float) * nvals ); + ptId += nvals; + } + else + { + // Hopefully point arrays are usually floats. This conversion will + // really slow things down. + + for (vtkIdType ii=0; iiGetPoint(ii); + + points[ptId++] = (float)pt[0]; + points[ptId++] = (float)pt[1]; + points[ptId++] = (float)pt[2]; + } + } + } + + for (ptId=0; ptIdDivideRegion(kd, points, ptIds, 0); + + this->SetActualLevel(); + this->BuildRegionList(); + + // Create a location array for the points of each region + + this->LocatorRegionLocation = new int [this->NumberOfRegions]; + + int idx = 0; + + for (int reg = 0; reg < this->NumberOfRegions; reg++) + { + this->LocatorRegionLocation[reg] = idx; + + idx += this->RegionList[reg]->GetNumberOfPoints(); + } + + this->NumberOfLocatorPoints = idx; + + this->SetCalculator(this->Top); + + TIMERDONE("Build tree"); +} + +//---------------------------------------------------------------------------- +// Query functions subsequent to BuildLocatorFromPoints, +// relating to duplicate and nearby points +// +vtkIdTypeArray *vtkKdTree::BuildMapForDuplicatePoints(float tolerance = 0.0) +{ + int i; + + if (this->LocatorPoints == NULL) + { + vtkErrorMacro(<< "vtkKdTree::BuildMapForDuplicatePoints - build locator first"); + return NULL; + } + + if ((tolerance < 0.0) || (tolerance >= this->MaxWidth)) + { + vtkErrorMacro(<< "vtkKdTree::BuildMapForDuplicatePoints - invalid tolerance"); + return NULL; + } + + TIMER("Find duplicate points"); + + int *idCount = new int [this->NumberOfRegions]; + int **uniqueFound = new int * [this->NumberOfRegions]; + + if (!idCount || !uniqueFound) + { + if (idCount) + { + delete [] idCount; + } + if (uniqueFound) + { + delete [] uniqueFound; + } + + vtkErrorMacro(<< "vtkKdTree::BuildMapForDuplicatePoints memory allocation"); + return NULL; + } + + memset(idCount, 0, sizeof(int) * this->NumberOfRegions); + + for (i=0; iNumberOfRegions; i++) + { + uniqueFound[i] = new int [this->RegionList[i]->GetNumberOfPoints()]; + + if (!uniqueFound[i]) + { + delete [] idCount; + for (int j=0; jSetNumberOfValues(this->NumberOfLocatorPoints); + + int idx = 0; + int nextRegionId = 0; + float *point = this->LocatorPoints; + + while (idx < this->NumberOfLocatorPoints) + { + // first point we have in this region + + int currentId = this->LocatorIds[idx]; + + int regionId = this->GetRegionContainingPoint(point[0],point[1],point[2]); + + if ((regionId == -1) || (regionId != nextRegionId)) + { + delete [] idCount; + for (i=0; iNumberOfRegions; i++) delete [] uniqueFound[i]; + delete [] uniqueFound; + uniqueIds->Delete(); + vtkErrorMacro(<< "vtkKdTree::BuildMapForDuplicatePoints corrupt k-d tree"); + return NULL; + } + + int duplicateFound = -1; + + if ((tolerance > 0.0) && (regionId > 0)) + { + duplicateFound = this->SearchNeighborsForDuplicate(regionId, point, + uniqueFound, idCount, tolerance, tolerance2); + } + + if (duplicateFound >= 0) + { + uniqueIds->SetValue(currentId, this->LocatorIds[duplicateFound]); + } + else + { + uniqueFound[regionId][idCount[regionId]++] = idx; + uniqueIds->SetValue(currentId, currentId); + } + + // test the other points in this region + + int numRegionPoints = this->RegionList[regionId]->GetNumberOfPoints(); + + int secondIdx = idx + 1; + int nextFirstIdx = idx + numRegionPoints; + + for (int idx2 = secondIdx ; idx2 < nextFirstIdx; idx2++) + { + point += 3; + currentId = this->LocatorIds[idx2]; + + duplicateFound = this->SearchRegionForDuplicate(point, + uniqueFound[regionId], idCount[regionId], tolerance2); + + if ((tolerance > 0.0) && (duplicateFound < 0) && (regionId > 0)) + { + duplicateFound = this->SearchNeighborsForDuplicate(regionId, point, + uniqueFound, idCount, tolerance, tolerance2); + } + + if (duplicateFound >= 0) + { + uniqueIds->SetValue(currentId, this->LocatorIds[duplicateFound]); + } + else + { + uniqueFound[regionId][idCount[regionId]++] = idx2; + uniqueIds->SetValue(currentId, currentId); + } + } + + idx = nextFirstIdx; + point += 3; + nextRegionId++; + } + + for (i=0; iNumberOfRegions; i++) + { + delete [] uniqueFound[i]; + } + delete [] uniqueFound; + delete [] idCount; + + TIMERDONE("Find duplicate points"); + + return uniqueIds; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::SearchRegionForDuplicate(float *point, int *pointsSoFar, + int len, float tolerance2) +{ + int duplicateFound = -1; + int id; + + for (id=0; id < len; id++) + { + int otherId = pointsSoFar[id]; + + float *otherPoint = this->LocatorPoints + (otherId * 3); + + float distance2 = vtkMath::Distance2BetweenPoints(point, otherPoint); + + if (distance2 <= tolerance2) + { + duplicateFound = otherId; + break; + } + } + return duplicateFound; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::SearchNeighborsForDuplicate(int regionId, float *point, + int **pointsSoFar, int *len, + float tolerance, float tolerance2) +{ + int duplicateFound = -1; + + float dist2 = + this->RegionList[regionId]->GetDistance2ToInnerBoundary(point[0],point[1],point[2]); + + if (dist2 >= tolerance2) + { + // There are no other regions with data that are within the + // tolerance distance of this point. + + return duplicateFound; + } + + // Find all regions that are within the tolerance distance of the point + + int *regionIds = new int [this->NumberOfRegions]; + + this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOn(); + +#ifdef USE_SPHERE + + // Find all regions which intersect a sphere around the point + // with radius equal to tolerance. Compute the intersection using + // the bounds of data within regions, not the bounds of the region. + + int nRegions = + this->BSPCalculator->IntersectsSphere2(regionIds, this->NumberOfRegions, + point[0], point[1], point[2], tolerance2); +#else + + // Technically, we want all regions that intersect a sphere around the + // point. But this takes much longer to compute than a box. We'll compute + // all regions that intersect a box. We may occasionally get a region + // we don't need, but that's OK. + + double box[6]; + box[0] = point[0] - tolerance; box[1] = point[0] + tolerance; + box[2] = point[1] - tolerance; box[3] = point[1] + tolerance; + box[4] = point[2] - tolerance; box[5] = point[2] + tolerance; + + int nRegions = this->BSPCalculator->IntersectsBox(regionIds, this->NumberOfRegions, box); + +#endif + + this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOff(); + + for (int reg=0; reg < nRegions; reg++) + { + if ((regionIds[reg] == regionId) || (len[reg] == 0) ) + { + continue; + } + + duplicateFound = this->SearchRegionForDuplicate(point, pointsSoFar[reg], + len[reg], tolerance2); + + if (duplicateFound) + { + break; + } + } + + delete [] regionIds; + + return duplicateFound; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::FindPoint(double x[3]) +{ + return this->FindPoint(x[0], x[1], x[2]); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::FindPoint(double x, double y, double z) +{ + if (!this->LocatorPoints) + { + vtkErrorMacro(<< "vtkKdTree::FindPoint - must build locator first"); + return -1; + } + + int regionId = this->GetRegionContainingPoint(x, y, z); + + if (regionId == -1) + { + return -1; + } + + int idx = this->LocatorRegionLocation[regionId]; + + vtkIdType ptId = -1; + + float *point = this->LocatorPoints + (idx * 3); + + float fx = (float)x; + float fy = (float)y; + float fz = (float)z; + + for (int i=0; i < this->RegionList[regionId]->GetNumberOfPoints(); i++) + { + if ( (point[0] == fx) && (point[1] == fy) && (point[2] == fz)) + { + ptId = (vtkIdType)this->LocatorIds[idx + i]; + break; + } + + point += 3; + } + + return ptId; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::FindClosestPoint(double x[3], double &dist2) +{ + vtkIdType id = this->FindClosestPoint(x[0], x[1], x[2], dist2); + + return id; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::FindClosestPoint(double x, double y, double z, double &dist2) +{ + if (!this->LocatorPoints) + { + vtkErrorMacro(<< "vtkKdTree::FindClosestPoint: must build locator first"); + return -1; + } + + double minDistance2 = 0.0; + + int closeId=-1, newCloseId=-1; + double newDistance2 = 4 * this->MaxWidth * this->MaxWidth; + + int regionId = this->GetRegionContainingPoint(x, y, z); + + if (regionId < 0) + { + // This point is not inside the space divided by the k-d tree. + // Find the point on the boundary that is closest to it. + + double pt[3]; + this->Top->GetDistance2ToBoundary(x, y, z, pt, 1); + + double *min = this->Top->GetMinBounds(); + double *max = this->Top->GetMaxBounds(); + + // GetDistance2ToBoundary will sometimes return a point *just* + // *barely* outside the bounds of the region. Move that point to + // just barely *inside* instead. + + if (pt[0] <= min[0]) + { + pt[0] = min[0] + this->FudgeFactor; + } + if (pt[1] <= min[1]) + { + pt[1] = min[1] + this->FudgeFactor; + } + if (pt[2] <= min[2]) + { + pt[2] = min[2] + this->FudgeFactor; + } + if (pt[0] >= max[0]) + { + pt[0] = max[0] - this->FudgeFactor; + } + if (pt[1] >= max[1]) + { + pt[1] = max[1] - this->FudgeFactor; + } + if (pt[2] >= max[2]) + { + pt[2] = max[2] - this->FudgeFactor; + } + + regionId = this->GetRegionContainingPoint(pt[0], pt[1], pt[2]); + + double proxyDistance; + + // XXX atwilso changed this to compute from x, y, z instead of pt + // -- computing from pt still wasn't giving the right results for + // far-away points + + closeId = this->_FindClosestPointInRegion(regionId, + x, y, z, + proxyDistance); + + double originalPoint[3], otherPoint[3]; + originalPoint[0] = x; originalPoint[1] = y; originalPoint[2] = z; + + float *closePoint = this->LocatorPoints + (closeId * 3); + otherPoint[0] = (double)closePoint[0]; + otherPoint[1] = (double)closePoint[1]; + otherPoint[2] = (double)closePoint[2]; + + minDistance2 = + vtkMath::Distance2BetweenPoints(originalPoint, otherPoint); + + // Check to see if neighboring regions have a closer point + + newCloseId = + this->FindClosestPointInSphere(x, y, z, + minDistance2, // radius + regionId, // skip this region + newDistance2); // distance to closest point + + } + else // Point is inside a k-d tree region + { + closeId = + this->_FindClosestPointInRegion(regionId, x, y, z, minDistance2); + + if (minDistance2 > 0.0) + { + float dist2ToBoundary = + this->RegionList[regionId]->GetDistance2ToInnerBoundary(x, y, z); + + if (dist2ToBoundary < minDistance2) + { + // The closest point may be in a neighboring region + + newCloseId = this->FindClosestPointInSphere(x, y, z, + minDistance2, // radius + regionId, // skip this region + newDistance2); + } + } + } + + if (newDistance2 < minDistance2 && newCloseId != -1) + { + closeId = newCloseId; + minDistance2 = newDistance2; + } + + vtkIdType closePointId = (vtkIdType)this->LocatorIds[closeId]; + + dist2 = minDistance2; + + return closePointId; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::FindClosestPointInRegion(int regionId, double *x, double &dist2) +{ + return this->FindClosestPointInRegion(regionId, x[0], x[1], x[2], dist2); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::FindClosestPointInRegion(int regionId, + double x, double y, double z, double &dist2) +{ + int localId = this->_FindClosestPointInRegion(regionId, x, y, z, dist2); + + vtkIdType originalId = -1; + + if (localId >= 0) + { + originalId = (vtkIdType)this->LocatorIds[localId]; + } + + return originalId; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::_FindClosestPointInRegion(int regionId, + double x, double y, double z, double &dist2) +{ + int minId=0; + + double minDistance2 = 4 * this->MaxWidth * this->MaxWidth; + + int idx = this->LocatorRegionLocation[regionId]; + + float *candidate = this->LocatorPoints + (idx * 3); + + for (int i=0; i < this->RegionList[regionId]->GetNumberOfPoints(); i++) + { + double dx = (x - (double)candidate[0]) * (x - (double)candidate[0]); + + if (dx < minDistance2) + { + double dxy = dx + ((y - (double)candidate[1]) * (y - (double)candidate[1])); + + if (dxy < minDistance2) + { + double dxyz = dxy + ((z - (double)candidate[2]) * (z - (double)candidate[2])); + + if (dxyz < minDistance2) + { + minId = idx + i; + minDistance2 = dxyz; + + if (dxyz == 0.0) + { + break; + } + } + } + } + + candidate += 3; + } + + dist2 = minDistance2; + + return minId; +} +int vtkKdTree::FindClosestPointInSphere(double x, double y, double z, + double radius, int skipRegion, + double &dist2) +{ + int *regionIds = new int [this->NumberOfRegions]; + + this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOn(); + + int nRegions = + this->BSPCalculator->IntersectsSphere2(regionIds, this->NumberOfRegions, x, y, z, radius); + + this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOff(); + + double minDistance2 = 4 * this->MaxWidth * this->MaxWidth; + int closeId = -1; + + for (int reg=0; reg < nRegions; reg++) + { + if (regionIds[reg] == skipRegion) + { + continue; + } + + int neighbor = regionIds[reg]; + double newDistance2; + + int newCloseId = this->_FindClosestPointInRegion(neighbor, + x, y, z, newDistance2); + + if (newDistance2 < minDistance2) + { + minDistance2 = newDistance2; + closeId = newCloseId; + } + } + + delete [] regionIds; + + dist2 = minDistance2; + return closeId; +} + +//---------------------------------------------------------------------------- +vtkIdTypeArray *vtkKdTree::GetPointsInRegion(int regionId) +{ + if ( (regionId < 0) || (regionId >= this->NumberOfRegions)) + { + vtkErrorMacro(<< "vtkKdTree::GetPointsInRegion invalid region ID"); + return NULL; + } + + if (!this->LocatorIds) + { + vtkErrorMacro(<< "vtkKdTree::GetPointsInRegion build locator first"); + return NULL; + } + + int numPoints = this->RegionList[regionId]->GetNumberOfPoints(); + int where = this->LocatorRegionLocation[regionId]; + + vtkIdTypeArray *ptIds = vtkIdTypeArray::New(); + ptIds->SetNumberOfValues(numPoints); + + int *ids = this->LocatorIds + where; + + for (int i=0; iSetValue(i, ids[i]); + } + + return ptIds; +} + +//---------------------------------------------------------------------------- +// Code to save state/time of last k-d tree build, and to +// determine if a data set's geometry has changed since the +// last build. +// +void vtkKdTree::ClearLastBuildCache() +{ + if (this->LastDataCacheSize > 0) + { + delete [] this->LastInputDataSets; + delete [] this->LastDataSetType; + delete [] this->LastInputDataInfo; + delete [] this->LastBounds; + delete [] this->LastNumCells; + delete [] this->LastNumPoints; + this->LastDataCacheSize = 0; + } + this->LastNumDataSets = 0; + this->LastInputDataSets = NULL; + this->LastDataSetType = NULL; + this->LastInputDataInfo = NULL; + this->LastBounds = NULL; + this->LastNumPoints = NULL; + this->LastNumCells = NULL; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::UpdateBuildTime() +{ + this->BuildTime.Modified(); + + // Save enough information so that next time we execute, + // we can determine whether input geometry has changed. + + if (this->NumDataSets > this->LastDataCacheSize) + { + this->ClearLastBuildCache(); + + this->LastInputDataSets = new vtkDataSet * [this->NumDataSets]; + this->LastDataSetType = new int [this->NumDataSets]; + this->LastInputDataInfo = new double [9 * this->NumDataSets]; + this->LastBounds = new double [6 * this->NumDataSets]; + this->LastNumPoints = new int [this->NumDataSets]; + this->LastNumCells = new int [this->NumDataSets]; + this->LastDataCacheSize = this->NumDataSets; + } + + this->LastNumDataSets = this->NumDataSets; + + int nextds = 0; + + for (int i=0; iNumDataSetsAllocated; i++) + { + vtkDataSet *in = this->DataSets[i]; + + if (in == NULL) + { + continue; + } + + if (nextds >= this->NumDataSets) + { + vtkErrorMacro(<< "vtkKdTree::UpdateBuildTime corrupt counts"); + return; + } + + this->LastInputDataSets[nextds] = in; + + this->LastNumPoints[nextds] = static_cast(in->GetNumberOfPoints()); + this->LastNumCells[nextds] = static_cast(in->GetNumberOfCells()); + + in->GetBounds(this->LastBounds + 6*nextds); + + int type = this->LastDataSetType[nextds] = in->GetDataObjectType(); + + if ((type == VTK_IMAGE_DATA) || (type == VTK_UNIFORM_GRID)) + { + double origin[3], spacing[3]; + int dims[3]; + + if (type == VTK_IMAGE_DATA) + { + vtkImageData *id = vtkImageData::SafeDownCast(in); + id->GetDimensions(dims); + id->GetOrigin(origin); + id->GetSpacing(spacing); + } + else + { + vtkUniformGrid *ug = vtkUniformGrid::SafeDownCast(in); + ug->GetDimensions(dims); + ug->GetOrigin(origin); + ug->GetSpacing(spacing); + } + + this->SetInputDataInfo(nextds, dims, origin, spacing); + } + + nextds++; + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::SetInputDataInfo(int i, int dims[3], double origin[3], + double spacing[3]) +{ + int idx = 9*i; + this->LastInputDataInfo[idx++] = (double)dims[0]; + this->LastInputDataInfo[idx++] = (double)dims[1]; + this->LastInputDataInfo[idx++] = (double)dims[2]; + this->LastInputDataInfo[idx++] = origin[0]; + this->LastInputDataInfo[idx++] = origin[1]; + this->LastInputDataInfo[idx++] = origin[2]; + this->LastInputDataInfo[idx++] = spacing[0]; + this->LastInputDataInfo[idx++] = spacing[1]; + this->LastInputDataInfo[idx++] = spacing[2]; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::CheckInputDataInfo(int i, int dims[3], double origin[3], + double spacing[3]) +{ + int sameValues = 1; + int idx = 9*i; + + if ((dims[0] != (int)this->LastInputDataInfo[idx]) || + (dims[1] != (int)this->LastInputDataInfo[idx+1]) || + (dims[2] != (int)this->LastInputDataInfo[idx+2]) || + (origin[0] != this->LastInputDataInfo[idx+3]) || + (origin[1] != this->LastInputDataInfo[idx+4]) || + (origin[2] != this->LastInputDataInfo[idx+5]) || + (spacing[0] != this->LastInputDataInfo[idx+6]) || + (spacing[1] != this->LastInputDataInfo[idx+7]) || + (spacing[2] != this->LastInputDataInfo[idx+8]) ) + { + sameValues = 0; + } + + return sameValues; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::NewGeometry() +{ + if (this->NumDataSets != this->LastNumDataSets) + { + return 1; + } + + vtkDataSet **tmp = new vtkDataSet * [this->NumDataSets]; + int nextds = 0; + for (int i=0; iNumDataSetsAllocated; i++) + { + if (this->DataSets[i] == NULL) + { + continue; + } + if (nextds >= this->NumDataSets) + { + vtkErrorMacro(<<"vtkKdTree::NewGeometry corrupt counts"); + return -1; + } + + tmp[nextds++] = this->DataSets[i]; + } + + int itsNew = this->NewGeometry(tmp, this->NumDataSets); + + delete [] tmp; + + return itsNew; +} +int vtkKdTree::NewGeometry(vtkDataSet **sets, int numSets) +{ + int newGeometry = 0; +#if 0 + vtkPointSet *ps = NULL; +#endif + vtkRectilinearGrid *rg = NULL; + vtkImageData *id = NULL; + vtkUniformGrid *ug = NULL; + int same=0; + int dims[3]; + double origin[3], spacing[3]; + + for (int i=0; iLastInputDataSets[i]; + int type = in->GetDataObjectType(); + + if (type != this->LastDataSetType[i]) + { + newGeometry = 1; + break; + } + + switch (type) + { + case VTK_POLY_DATA: + case VTK_UNSTRUCTURED_GRID: + case VTK_STRUCTURED_GRID: + #if 0 + // For now, vtkPExodusReader creates a whole new + // vtkUnstructuredGrid, even when just changing + // field arrays. So we'll just check bounds. + ps = vtkPointSet::SafeDownCast(in); + if (ps->GetPoints()->GetMTime() > this->BuildTime) + { + newGeometry = 1; + } + #else + if ((sets[i]->GetNumberOfPoints() != this->LastNumPoints[i]) || + (sets[i]->GetNumberOfCells() != this->LastNumCells[i]) ) + { + newGeometry = 1; + } + else + { + double b[6]; + sets[i]->GetBounds(b); + double *lastb = this->LastBounds + 6*i; + + for (int dim=0; dim<6; dim++) + { + if (*lastb++ != b[dim]) + { + newGeometry = 1; + break; + } + } + } + #endif + break; + + case VTK_RECTILINEAR_GRID: + + rg = vtkRectilinearGrid::SafeDownCast(in); + if ((rg->GetXCoordinates()->GetMTime() > this->BuildTime) || + (rg->GetYCoordinates()->GetMTime() > this->BuildTime) || + (rg->GetZCoordinates()->GetMTime() > this->BuildTime) ) + { + newGeometry = 1; + } + break; + + case VTK_IMAGE_DATA: + case VTK_STRUCTURED_POINTS: + + id = vtkImageData::SafeDownCast(in); + + id->GetDimensions(dims); + id->GetOrigin(origin); + id->GetSpacing(spacing); + + same = this->CheckInputDataInfo(i, dims, origin, spacing); + + if (!same) + { + newGeometry = 1; + } + + break; + + case VTK_UNIFORM_GRID: + + ug = vtkUniformGrid::SafeDownCast(in); + + ug->GetDimensions(dims); + ug->GetOrigin(origin); + ug->GetSpacing(spacing); + + same = this->CheckInputDataInfo(i, dims, origin, spacing); + + if (!same) + { + newGeometry = 1; + } + else if (ug->GetPointVisibilityArray()->GetMTime() > + this->BuildTime) + { + newGeometry = 1; + } + else if (ug->GetCellVisibilityArray()->GetMTime() > + this->BuildTime) + { + newGeometry = 1; + } + break; + + default: + vtkWarningMacro(<< + "vtkKdTree::NewGeometry: unanticipated type"); + + newGeometry = 1; + } + if (newGeometry) + { + break; + } + } + + return newGeometry; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::__printTree(vtkKdNode *kd, int depth, int v) +{ + if (v) + { + kd->PrintVerboseNode(depth); + } + else + { + kd->PrintNode(depth); + } + + if (kd->GetLeft()) + { + vtkKdTree::__printTree(kd->GetLeft(), depth+1, v); + } + if (kd->GetRight()) + { + vtkKdTree::__printTree(kd->GetRight(), depth+1, v); + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::_printTree(int v) +{ + vtkKdTree::__printTree(this->Top, 0, v); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::PrintRegion(int id) +{ + this->RegionList[id]->PrintNode(0); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::PrintTree() +{ + _printTree(0); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::PrintVerboseTree() +{ + _printTree(1); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::FreeSearchStructure() +{ + if (this->Top) + { + vtkKdTree::DeleteAllDescendants(this->Top); + this->Top->Delete(); + this->Top = NULL; + } + if (this->RegionList) + { + delete [] this->RegionList; + this->RegionList = NULL; + } + + this->NumberOfRegions = 0; + this->SetActualLevel(); + + this->DeleteCellLists(); + + if (this->CellRegionList) + { + delete [] this->CellRegionList; + this->CellRegionList = NULL; + } + + if (this->LocatorPoints) + { + delete [] this->LocatorPoints; + this->LocatorPoints = NULL; + } + + if (this->LocatorIds) + { + delete [] this->LocatorIds; + this->LocatorIds = NULL; + } + + if (this->LocatorRegionLocation) + { + delete [] this->LocatorRegionLocation; + this->LocatorRegionLocation = NULL; + } +} + +//---------------------------------------------------------------------------- +// build PolyData representation of all spacial regions------------ +// +void vtkKdTree::GenerateRepresentation(int level, vtkPolyData *pd) +{ + if (this->GenerateRepresentationUsingDataBounds) + { + this->GenerateRepresentationDataBounds(level, pd); + } + else + { + this->GenerateRepresentationWholeSpace(level, pd); + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::GenerateRepresentationWholeSpace(int level, vtkPolyData *pd) +{ + int i; + + vtkPoints *pts; + vtkCellArray *polys; + + if ( this->Top == NULL ) + { + vtkErrorMacro(<<"vtkKdTree::GenerateRepresentation empty tree"); + return; + } + + if ((level < 0) || (level > this->Level)) + { + level = this->Level; + } + + int npoints = 0; + int npolys = 0; + + for (i=0 ; i < level; i++) + { + int levelPolys = 1 << (i-1); + npoints += (4 * levelPolys); + npolys += levelPolys; + } + + pts = vtkPoints::New(); + pts->Allocate(npoints); + polys = vtkCellArray::New(); + polys->Allocate(npolys); + + // level 0 bounding box + + vtkIdType ids[8]; + vtkIdType idList[4]; + double x[3]; + vtkKdNode *kd = this->Top; + + double *min = kd->GetMinBounds(); + double *max = kd->GetMaxBounds(); + + x[0] = min[0]; x[1] = max[1]; x[2] = min[2]; + ids[0] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = max[1]; x[2] = min[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = max[1]; x[2] = max[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = min[0]; x[1] = max[1]; x[2] = max[2]; + ids[3] = pts->InsertNextPoint(x); + + x[0] = min[0]; x[1] = min[1]; x[2] = min[2]; + ids[4] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = min[1]; x[2] = min[2]; + ids[5] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = min[1]; x[2] = max[2]; + ids[6] = pts->InsertNextPoint(x); + + x[0] = min[0]; x[1] = min[1]; x[2] = max[2]; + ids[7] = pts->InsertNextPoint(x); + + idList[0] = ids[0]; idList[1] = ids[1]; idList[2] = ids[2]; idList[3] = ids[3]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[1]; idList[1] = ids[5]; idList[2] = ids[6]; idList[3] = ids[2]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[5]; idList[1] = ids[4]; idList[2] = ids[7]; idList[3] = ids[6]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[4]; idList[1] = ids[0]; idList[2] = ids[3]; idList[3] = ids[7]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[3]; idList[1] = ids[2]; idList[2] = ids[6]; idList[3] = ids[7]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[1]; idList[1] = ids[0]; idList[2] = ids[4]; idList[3] = ids[5]; + polys->InsertNextCell(4, idList); + + if (kd->GetLeft() && (level > 0)) + { + _generateRepresentationWholeSpace(kd, pts, polys, level-1); + } + + pd->SetPoints(pts); + pts->Delete(); + pd->SetPolys(polys); + polys->Delete(); + pd->Squeeze(); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::_generateRepresentationWholeSpace(vtkKdNode *kd, + vtkPoints *pts, + vtkCellArray *polys, + int level) +{ + int i; + double p[4][3]; + vtkIdType ids[4]; + + if ((level < 0) || (kd->GetLeft() == NULL)) + { + return; + } + + double *min = kd->GetMinBounds(); + double *max = kd->GetMaxBounds(); + double *leftmax = kd->GetLeft()->GetMaxBounds(); + + // splitting plane + + switch (kd->GetDim()) + { + case XDIM: + + p[0][0] = leftmax[0]; p[0][1] = max[1]; p[0][2] = max[2]; + p[1][0] = leftmax[0]; p[1][1] = max[1]; p[1][2] = min[2]; + p[2][0] = leftmax[0]; p[2][1] = min[1]; p[2][2] = min[2]; + p[3][0] = leftmax[0]; p[3][1] = min[1]; p[3][2] = max[2]; + + break; + + case YDIM: + + p[0][0] = min[0]; p[0][1] = leftmax[1]; p[0][2] = max[2]; + p[1][0] = min[0]; p[1][1] = leftmax[1]; p[1][2] = min[2]; + p[2][0] = max[0]; p[2][1] = leftmax[1]; p[2][2] = min[2]; + p[3][0] = max[0]; p[3][1] = leftmax[1]; p[3][2] = max[2]; + + break; + + case ZDIM: + + p[0][0] = min[0]; p[0][1] = min[1]; p[0][2] = leftmax[2]; + p[1][0] = min[0]; p[1][1] = max[1]; p[1][2] = leftmax[2]; + p[2][0] = max[0]; p[2][1] = max[1]; p[2][2] = leftmax[2]; + p[3][0] = max[0]; p[3][1] = min[1]; p[3][2] = leftmax[2]; + + break; + } + + + for (i=0; i<4; i++) ids[i] = pts->InsertNextPoint(p[i]); + + polys->InsertNextCell(4, ids); + + _generateRepresentationWholeSpace(kd->GetLeft(), pts, polys, level-1); + _generateRepresentationWholeSpace(kd->GetRight(), pts, polys, level-1); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::GenerateRepresentationDataBounds(int level, vtkPolyData *pd) +{ + int i; + vtkPoints *pts; + vtkCellArray *polys; + + if ( this->Top == NULL ) + { + vtkErrorMacro(<<"vtkKdTree::GenerateRepresentation no tree"); + return; + } + + if ((level < 0) || (level > this->Level)) + { + level = this->Level; + } + + int npoints = 0; + int npolys = 0; + + for (i=0; i < level; i++) + { + int levelBoxes= 1 << i; + npoints += (8 * levelBoxes); + npolys += (6 * levelBoxes); + } + + pts = vtkPoints::New(); + pts->Allocate(npoints); + polys = vtkCellArray::New(); + polys->Allocate(npolys); + + _generateRepresentationDataBounds(this->Top, pts, polys, level); + + pd->SetPoints(pts); + pts->Delete(); + pd->SetPolys(polys); + polys->Delete(); + pd->Squeeze(); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::_generateRepresentationDataBounds(vtkKdNode *kd, vtkPoints *pts, + vtkCellArray *polys, int level) +{ + if (level > 0) + { + if (kd->GetLeft()) + { + _generateRepresentationDataBounds(kd->GetLeft(), pts, polys, level-1); + _generateRepresentationDataBounds(kd->GetRight(), pts, polys, level-1); + } + + return; + } + vtkKdTree::AddPolys(kd, pts, polys); +} + +//---------------------------------------------------------------------------- +// PolyData rep. of all spacial regions, shrunk to data bounds------- +// +void vtkKdTree::AddPolys(vtkKdNode *kd, vtkPoints *pts, vtkCellArray *polys) +{ + vtkIdType ids[8]; + vtkIdType idList[4]; + double x[3]; + + double *min; + double *max; + + if (this->GenerateRepresentationUsingDataBounds) + { + min = kd->GetMinDataBounds(); + max = kd->GetMaxDataBounds(); + } + else + { + min = kd->GetMinBounds(); + max = kd->GetMaxBounds(); + } + + x[0] = min[0]; x[1] = max[1]; x[2] = min[2]; + ids[0] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = max[1]; x[2] = min[2]; + ids[1] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = max[1]; x[2] = max[2]; + ids[2] = pts->InsertNextPoint(x); + + x[0] = min[0]; x[1] = max[1]; x[2] = max[2]; + ids[3] = pts->InsertNextPoint(x); + + x[0] = min[0]; x[1] = min[1]; x[2] = min[2]; + ids[4] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = min[1]; x[2] = min[2]; + ids[5] = pts->InsertNextPoint(x); + + x[0] = max[0]; x[1] = min[1]; x[2] = max[2]; + ids[6] = pts->InsertNextPoint(x); + + x[0] = min[0]; x[1] = min[1]; x[2] = max[2]; + ids[7] = pts->InsertNextPoint(x); + + idList[0] = ids[0]; idList[1] = ids[1]; idList[2] = ids[2]; idList[3] = ids[3]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[1]; idList[1] = ids[5]; idList[2] = ids[6]; idList[3] = ids[2]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[5]; idList[1] = ids[4]; idList[2] = ids[7]; idList[3] = ids[6]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[4]; idList[1] = ids[0]; idList[2] = ids[3]; idList[3] = ids[7]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[3]; idList[1] = ids[2]; idList[2] = ids[6]; idList[3] = ids[7]; + polys->InsertNextCell(4, idList); + + idList[0] = ids[1]; idList[1] = ids[0]; idList[2] = ids[4]; idList[3] = ids[5]; + polys->InsertNextCell(4, idList); +} + +//---------------------------------------------------------------------------- +// PolyData representation of a list of spacial regions------------ +// +void vtkKdTree::GenerateRepresentation(int *regions, int len, vtkPolyData *pd) +{ + int i; + vtkPoints *pts; + vtkCellArray *polys; + + if ( this->Top == NULL ) + { + vtkErrorMacro(<<"vtkKdTree::GenerateRepresentation no tree"); + return; + } + + int npoints = 8 * len; + int npolys = 6 * len; + + pts = vtkPoints::New(); + pts->Allocate(npoints); + polys = vtkCellArray::New(); + polys->Allocate(npolys); + + for (i=0; i= this->NumberOfRegions)) + { + break; + } + + vtkKdTree::AddPolys(this->RegionList[regions[i]], pts, polys); + } + + pd->SetPoints(pts); + pts->Delete(); + pd->SetPolys(polys); + polys->Delete(); + pd->Squeeze(); +} + +//---------------------------------------------------------------------------- +// Cell ID lists +// +#define SORTLIST(l, lsize) vtkstd::sort(l, l + lsize) + +#define REMOVEDUPLICATES(l, lsize, newsize) \ +{ \ +int ii,jj; \ +for (ii=0, jj=0; ii 0) && (l[ii] == l[jj-1])) \ + { \ + continue; \ + } \ + if (jj != ii) \ + { \ + l[jj] = l[ii]; \ + } \ + jj++; \ +} \ +newsize = jj; \ +} + +//---------------------------------------------------------------------------- +int vtkKdTree::FoundId(vtkIntArray *idArray, int id) +{ + // This is a simple linear search, because I think it is rare that + // an id array would be provided, and if one is it should be small. + + int found = 0; + int len = idArray->GetNumberOfTuples(); + int *ids = idArray->GetPointer(0); + + for (int i=0; iContainsPoint(x, y, z, 0)) + { + return -1; + } + + if (node->GetLeft() == NULL) + { + regionId = node->GetID(); + } + else + { + regionId = vtkKdTree::findRegion(node->GetLeft(), x, y, z); + + if (regionId < 0) + { + regionId = vtkKdTree::findRegion(node->GetRight(), x, y, z); + } + } + + return regionId; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::CreateCellLists() +{ + this->CreateCellLists(this->DataSets[0], (int *)NULL, 0); + return; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::CreateCellLists(int *regionList, int listSize) +{ + this->CreateCellLists(this->DataSets[0], regionList, listSize); + return; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::CreateCellLists(int dataSet, int *regionList, int listSize) +{ + if ((dataSet < 0) || (dataSet >= NumDataSets)) + { + vtkErrorMacro(<<"vtkKdTree::CreateCellLists invalid data set"); + return; + } + + this->CreateCellLists(this->DataSets[dataSet], regionList, listSize); + return; +} + +//---------------------------------------------------------------------------- +void vtkKdTree::CreateCellLists(vtkDataSet *set, int *regionList, int listSize) +{ + int i, AllRegions; + + if ( this->GetDataSet(set) < 0) + { + vtkErrorMacro(<<"vtkKdTree::CreateCellLists invalid data set"); + return; + } + + vtkKdTree::_cellList *list = &this->CellList; + + if (list->nRegions > 0) + { + this->DeleteCellLists(); + } + + list->emptyList = vtkIdList::New(); + + list->dataSet = set; + + if ((regionList == NULL) || (listSize == 0)) + { + list->nRegions = this->NumberOfRegions; // all regions + } + else + { + list->regionIds = new int [listSize]; + + if (!list->regionIds) + { + vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation"); + return; + } + + memcpy(list->regionIds, regionList, sizeof(int) * listSize); + SORTLIST(list->regionIds, listSize); + REMOVEDUPLICATES(list->regionIds, listSize, list->nRegions); + + if (list->nRegions == this->NumberOfRegions) + { + delete [] list->regionIds; + list->regionIds = NULL; + } + } + + if (list->nRegions == this->NumberOfRegions) + { + AllRegions = 1; + } + else + { + AllRegions = 0; + } + + int *idlist = NULL; + int idListLen = 0; + + if (this->IncludeRegionBoundaryCells) + { + list->boundaryCells = new vtkIdList * [list->nRegions]; + + if (!list->boundaryCells) + { + vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation"); + return; + } + + for (i=0; inRegions; i++) + { + list->boundaryCells[i] = vtkIdList::New(); + } + idListLen = this->NumberOfRegions; + + idlist = new int [idListLen]; + } + + int *listptr = NULL; + + if (!AllRegions) + { + listptr = new int [this->NumberOfRegions]; + + if (!listptr) + { + vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation"); + return; + } + + for (i=0; iNumberOfRegions; i++) + { + listptr[i] = -1; + } + } + + list->cells = new vtkIdList * [list->nRegions]; + + if (!list->cells) + { + vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation"); + return; + } + + for (i = 0; i < list->nRegions; i++) + { + list->cells[i] = vtkIdList::New(); + + if (listptr) + { + listptr[list->regionIds[i]] = i; + } + } + + // acquire a list in cell Id order of the region Id each + // cell centroid falls in + + int *regList = this->CellRegionList; + + if (regList == NULL) + { + regList = this->AllGetRegionContainingCell(); + } + + int setNum = this->GetDataSet(set); + + if (setNum > 0) + { + int ncells = this->GetDataSetsNumberOfCells(0,setNum-1); + regList += ncells; + } + + int nCells = set->GetNumberOfCells(); + + for (int cellId=0; cellIdIncludeRegionBoundaryCells) + { + // Find all regions the cell intersects, including + // the region the cell centroid lies in. + // This can be an expensive calculation, intersections + // of a convex region with axis aligned boxes. + + int nRegions = + this->BSPCalculator->IntersectsCell(idlist, idListLen, + set->GetCell(cellId), regList[cellId]); + + if (nRegions == 1) + { + int idx = (listptr) ? listptr[idlist[0]] : idlist[0]; + + if (idx >= 0) + { + list->cells[idx]->InsertNextId(cellId); + } + } + else + { + for (int r=0; r < nRegions; r++) + { + int regionId = idlist[r]; + + int idx = (listptr) ? listptr[regionId] : regionId; + + if (idx < 0) + { + continue; + } + + if (regionId == regList[cellId]) + { + list->cells[idx]->InsertNextId(cellId); + } + else + { + list->boundaryCells[idx]->InsertNextId(cellId); + } + } + } + } + else + { + // just find the region the cell centroid lies in - easy + + int regionId = regList[cellId]; + + int idx = (listptr) ? listptr[regionId] : regionId; + + if (idx >= 0) + { + list->cells[idx]->InsertNextId(cellId); + } + } + } + + if (listptr) + { + delete [] listptr; + } + if (idlist) + { + delete [] idlist; + } +} + +//---------------------------------------------------------------------------- +vtkIdList * vtkKdTree::GetList(int regionId, vtkIdList **which) +{ + int i; + struct _cellList *list = &this->CellList; + vtkIdList *cellIds = NULL; + + if (which && (list->nRegions == this->NumberOfRegions)) + { + cellIds = which[regionId]; + } + else if (which) + { + for (i=0; i< list->nRegions; i++) + { + if (list->regionIds[i] == regionId) + { + cellIds = which[i]; + break; + } + } + } + else + { + cellIds = list->emptyList; + } + + return cellIds; +} + +//---------------------------------------------------------------------------- +vtkIdList * vtkKdTree::GetCellList(int regionID) +{ + return this->GetList(regionID, this->CellList.cells); +} + +//---------------------------------------------------------------------------- +vtkIdList * vtkKdTree::GetBoundaryCellList(int regionID) +{ + return this->GetList(regionID, this->CellList.boundaryCells); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::GetCellLists(vtkIntArray *regions, + int set, vtkIdList *inRegionCells, vtkIdList *onBoundaryCells) +{ + if ( (set < 0) || + (set >= this->NumDataSetsAllocated) || + (this->DataSets[set] == NULL)) + { + vtkErrorMacro(<<"vtkKdTree::GetCellLists no such data set"); + return 0; + } + return this->GetCellLists(regions, this->DataSets[set], + inRegionCells, onBoundaryCells); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::GetCellLists(vtkIntArray *regions, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells) +{ + return this->GetCellLists(regions, this->DataSets[0], + inRegionCells, onBoundaryCells); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkKdTree::GetCellLists(vtkIntArray *regions, vtkDataSet *set, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells) +{ + int reg, regionId; + vtkIdType cell, cellId, numCells; + vtkIdList *cellIds; + + vtkIdType totalCells = 0; + + if ( (inRegionCells == NULL) && (onBoundaryCells == NULL)) + { + return totalCells; + } + + int nregions = regions->GetNumberOfTuples(); + + if (nregions == 0) + { + return totalCells; + } + + // Do I have cell lists for all these regions? If not, build cell + // lists for all regions for this data set. + + int rebuild = 0; + + if (this->CellList.dataSet != set) + { + rebuild = 1; + } + else if (nregions > this->CellList.nRegions) + { + rebuild = 1; + } + else if ((onBoundaryCells != NULL) && (this->CellList.boundaryCells == NULL)) + { + rebuild = 1; + } + else if (this->CellList.nRegions < this->NumberOfRegions) + { + // these two lists should generally be "short" + + int *haveIds = this->CellList.regionIds; + + for (int wantReg=0; wantReg < nregions; wantReg++) + { + int wantRegion = regions->GetValue(wantReg); + int gotId = 0; + + for (int haveReg=0; haveReg < this->CellList.nRegions; haveReg++) + { + if (haveIds[haveReg] == wantRegion) + { + gotId = 1; + break; + } + } + if (!gotId) + { + rebuild = 1; + break; + } + } + } + + if (rebuild) + { + if (onBoundaryCells != NULL) + { + this->IncludeRegionBoundaryCellsOn(); + } + this->CreateCellLists(set, NULL, 0); // for all regions + } + + // OK, we have cell lists for these regions. Make lists of region + // cells and boundary cells. + + int CheckSet = (onBoundaryCells && (nregions > 1)); + + vtkstd::set ids; + vtkstd::pair::iterator, bool> idRec; + + vtkIdType totalRegionCells = 0; + vtkIdType totalBoundaryCells = 0; + + vtkIdList **inRegionList = new vtkIdList * [nregions]; + + // First the cell IDs with centroid in the regions + + for (reg = 0; reg < nregions; reg++) + { + regionId = regions->GetValue(reg); + + inRegionList[reg] = this->GetCellList(regionId); + + totalRegionCells += inRegionList[reg]->GetNumberOfIds(); + } + + if (inRegionCells) + { + inRegionCells->Initialize(); + inRegionCells->SetNumberOfIds(totalRegionCells); + } + + int nextCell = 0; + + for (reg = 0; reg < nregions; reg++) + { + cellIds = inRegionList[reg]; + + numCells = cellIds->GetNumberOfIds(); + + for (cell = 0; cell < numCells; cell++) + { + if (inRegionCells) + { + inRegionCells->SetId(nextCell++, cellIds->GetId(cell)); + } + + if (CheckSet) + { + // We have to save the ids, so we don't include + // them as boundary cells. A cell in one region + // may be a boundary cell of another region. + + ids.insert(cellIds->GetId(cell)); + } + } + } + + delete [] inRegionList; + + if (onBoundaryCells == NULL) + { + return totalRegionCells; + } + + // Now the list of all cells on the boundary of the regions, + // which do not have their centroid in one of the regions + + onBoundaryCells->Initialize(); + + for (reg = 0; reg < nregions; reg++) + { + regionId = regions->GetValue(reg); + + cellIds = this->GetBoundaryCellList(regionId); + + numCells = cellIds->GetNumberOfIds(); + + for (cell = 0; cell < numCells; cell++) + { + cellId = cellIds->GetId(cell); + + if (CheckSet) + { + // if we already included this cell because it is within + // one of the regions, or on the boundary of another, skip it + + idRec = ids.insert(cellId); + + if (idRec.second == 0) + { + continue; + } + } + + onBoundaryCells->InsertNextId(cellId); + totalBoundaryCells++; + } + + totalCells += totalBoundaryCells; + } + + return totalCells; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::GetRegionContainingCell(vtkIdType cellID) +{ + return this->GetRegionContainingCell(this->DataSets[0], cellID); +} + +//---------------------------------------------------------------------------- +int vtkKdTree::GetRegionContainingCell(int set, vtkIdType cellID) +{ + if ( (set < 0) || + (set >= this->NumDataSetsAllocated) || + (this->DataSets[set] == NULL)) + { + vtkErrorMacro(<<"vtkKdTree::GetRegionContainingCell no such data set"); + return -1; + } + return this->GetRegionContainingCell(this->DataSets[set], cellID); +} + +//---------------------------------------------------------------------------- +int vtkKdTree::GetRegionContainingCell(vtkDataSet *set, vtkIdType cellID) +{ + int regionID = -1; + + if ( this->GetDataSet(set) < 0) + { + vtkErrorMacro(<<"vtkKdTree::GetRegionContainingCell no such data set"); + return -1; + } + if ( (cellID < 0) || (cellID >= set->GetNumberOfCells())) + { + vtkErrorMacro(<<"vtkKdTree::GetRegionContainingCell bad cell ID"); + return -1; + } + + if (this->CellRegionList) + { + if (set == this->DataSets[0]) // 99.99999% of the time + { + return this->CellRegionList[cellID]; + } + + int setNum = this->GetDataSet(set); + + int offset = this->GetDataSetsNumberOfCells(0, setNum-1); + + return this->CellRegionList[offset + cellID]; + } + + float center[3]; + + this->ComputeCellCenter(set, cellID, center); + + regionID = this->GetRegionContainingPoint(center[0], center[1], center[2]); + + return regionID; +} + +//---------------------------------------------------------------------------- +int *vtkKdTree::AllGetRegionContainingCell() +{ + if (this->CellRegionList) + { + return this->CellRegionList; + } + this->CellRegionList = new int [this->GetNumberOfCells()]; + + if (!this->CellRegionList) + { + vtkErrorMacro(<<"vtkKdTree::AllGetRegionContainingCell memory allocation"); + return NULL; + } + + int *listPtr = this->CellRegionList; + + for (int set=0; set < this->NumDataSetsAllocated; set++) + { + if (this->DataSets[set] == NULL) + { + continue; + } + + int setCells = this->DataSets[set]->GetNumberOfCells(); + + float *centers = this->ComputeCellCenters(set); + + float *pt = centers; + + for (int cellId = 0; cellId < setCells; cellId++) + { + listPtr[cellId] = + this->GetRegionContainingPoint(pt[0], pt[1], pt[2]); + + pt += 3; + } + + listPtr += setCells; + + delete [] centers; + } + + return this->CellRegionList; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::GetRegionContainingPoint(double x, double y, double z) +{ + return vtkKdTree::findRegion(this->Top, x, y, z); +} +//---------------------------------------------------------------------------- +int vtkKdTree::MinimalNumberOfConvexSubRegions(vtkIntArray *regionIdList, + double **convexSubRegions) +{ + int nids = 0; + + if ((regionIdList == NULL) || + ((nids = regionIdList->GetNumberOfTuples()) == 0)) + { + vtkErrorMacro(<< + "vtkKdTree::MinimalNumberOfConvexSubRegions no regions specified"); + return 0; + } + + int i; + int *ids = regionIdList->GetPointer(0); + + if (nids == 1) + { + if ( (ids[0] < 0) || (ids[0] >= this->NumberOfRegions)) + { + vtkErrorMacro(<< + "vtkKdTree::MinimalNumberOfConvexSubRegions bad region ID"); + return 0; + } + + double *bounds = new double [6]; + + this->RegionList[ids[0]]->GetBounds(bounds); + + *convexSubRegions = bounds; + + return 1; + } + + // create a sorted list of unique region Ids + + vtkstd::set idSet; + vtkstd::set::iterator it; + + for (i=0; iTop, regions); + + double *bounds = new double [nregions * 6]; + + for (i=0; iGetBounds(bounds + (i*6)); + } + + *convexSubRegions = bounds; + + delete [] idList; + delete [] regions; + + return nregions; +} +//---------------------------------------------------------------------------- +int vtkKdTree::__ConvexSubRegions(int *ids, int len, vtkKdNode *tree, vtkKdNode **nodes) +{ + int nregions = tree->GetMaxID() - tree->GetMinID() + 1; + + if (nregions == len) + { + *nodes = tree; + return 1; + } + + if (tree->GetLeft() == NULL) + { + return 0; + } + + int min = ids[0]; + int max = ids[len-1]; + + int leftMax = tree->GetLeft()->GetMaxID(); + int rightMin = tree->GetRight()->GetMinID(); + + if (max <= leftMax) + { + return vtkKdTree::__ConvexSubRegions(ids, len, tree->GetLeft(), nodes); + } + else if (min >= rightMin) + { + return vtkKdTree::__ConvexSubRegions(ids, len, tree->GetRight(), nodes); + } + else + { + int leftIds = 1; + + for (int i=1; iGetLeft(), nodes); + + + int numNodesRight = + vtkKdTree::__ConvexSubRegions(ids + leftIds, len - leftIds, + tree->GetRight(), nodes + numNodesLeft); + + return (numNodesLeft + numNodesRight); + } +} + +//---------------------------------------------------------------------------- +int vtkKdTree::DepthOrderRegions(vtkIntArray *regionIds, + double *directionOfProjection, vtkIntArray *orderedList) +{ + int i; + + vtkIntArray *IdsOfInterest = NULL; + + if (regionIds && (regionIds->GetNumberOfTuples() > 0)) + { + // Created sorted list of unique ids + + vtkstd::set ids; + vtkstd::set::iterator it; + int nids = regionIds->GetNumberOfTuples(); + + for (i=0; iGetValue(i)); + } + + if (ids.size() < (unsigned int)this->NumberOfRegions) + { + IdsOfInterest = vtkIntArray::New(); + IdsOfInterest->SetNumberOfValues(ids.size()); + + for (it = ids.begin(), i=0; it != ids.end(); ++it, ++i) + { + IdsOfInterest->SetValue(i, *it); + } + } + } + + int size = this->_DepthOrderRegions(IdsOfInterest, + directionOfProjection, orderedList); + + if (IdsOfInterest) + { + IdsOfInterest->Delete(); + } + + return size; +} + +//---------------------------------------------------------------------------- +int vtkKdTree::DepthOrderAllRegions(double *directionOfProjection, + vtkIntArray *orderedList) +{ + return this->_DepthOrderRegions(NULL, directionOfProjection, orderedList); +} + +//---------------------------------------------------------------------------- +int vtkKdTree::_DepthOrderRegions(vtkIntArray *IdsOfInterest, + double *dir, vtkIntArray *orderedList) +{ + int nextId = 0; + + int numValues = (IdsOfInterest ? IdsOfInterest->GetNumberOfTuples() : + this->NumberOfRegions); + + orderedList->Initialize(); + orderedList->SetNumberOfValues(numValues); + + int size = + vtkKdTree::__DepthOrderRegions(this->Top, orderedList, IdsOfInterest, dir, nextId); + if (size < 0) + { + vtkErrorMacro(<<"vtkKdTree::DepthOrderRegions k-d tree structure is corrupt"); + orderedList->Initialize(); + return 0; + } + + return size; +} +//---------------------------------------------------------------------------- +int vtkKdTree::__DepthOrderRegions(vtkKdNode *node, + vtkIntArray *list, vtkIntArray *IdsOfInterest, + double *dir, int nextId) +{ + if (node->GetLeft() == NULL) + { + if (!IdsOfInterest || vtkKdTree::FoundId(IdsOfInterest, node->GetID())) + { + list->SetValue(nextId, node->GetID()); + nextId = nextId+1; + } + + return nextId; + } + + int cutPlane = node->GetDim(); + + if ((cutPlane < 0) || (cutPlane > 2)) + { + return -1; + } + + double closest = dir[cutPlane] * -1; + + vtkKdNode *closeNode = (closest < 0) ? node->GetLeft() : node->GetRight(); + vtkKdNode *farNode = (closest >= 0) ? node->GetLeft() : node->GetRight(); + + int nextNextId = vtkKdTree::__DepthOrderRegions(closeNode, list, + IdsOfInterest, dir, nextId); + + if (nextNextId == -1) + { + return -1; + } + + nextNextId = vtkKdTree::__DepthOrderRegions(farNode, list, + IdsOfInterest, dir, nextNextId); + + return nextNextId; +} + +//---------------------------------------------------------------------------- +// These requests change the boundaries of the k-d tree, so must +// update the MTime. +// +void vtkKdTree::NewPartitioningRequest(int req) +{ + if (req != this->ValidDirections) + { + this->Modified(); + this->ValidDirections = req; + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::OmitXPartitioning() +{ + this->NewPartitioningRequest((1 << vtkKdTree::YDIM) | (1 << vtkKdTree::ZDIM)); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::OmitYPartitioning() +{ + this->NewPartitioningRequest((1 << vtkKdTree::ZDIM) | (1 << vtkKdTree::XDIM)); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::OmitZPartitioning() +{ + this->NewPartitioningRequest((1 << vtkKdTree::XDIM) | (1 << vtkKdTree::YDIM)); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::OmitXYPartitioning() +{ + this->NewPartitioningRequest((1 << vtkKdTree::ZDIM)); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::OmitYZPartitioning() +{ + this->NewPartitioningRequest((1 << vtkKdTree::XDIM)); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::OmitZXPartitioning() +{ + this->NewPartitioningRequest((1 << vtkKdTree::YDIM)); +} + +//---------------------------------------------------------------------------- +void vtkKdTree::OmitNoPartitioning() +{ + int req = ((1 << vtkKdTree::XDIM)|(1 << vtkKdTree::YDIM)|(1 << vtkKdTree::ZDIM)); + this->NewPartitioningRequest(req); +} + +//--------------------------------------------------------------------------- +void vtkKdTree::PrintTiming(ostream& os, vtkIndent ) +{ + vtkTimerLog::DumpLogWithIndents(&os, (float)0.0); +} + +//--------------------------------------------------------------------------- +void vtkKdTree::ReportReferences(vtkGarbageCollector *collector) +{ + this->Superclass::ReportReferences(collector); + + for (int i = 0; i < this->NumDataSetsAllocated; i++) + { + vtkGarbageCollectorReport(collector, this->DataSets[i], "DataSets[i]"); + } +} + +//---------------------------------------------------------------------------- +void vtkKdTree::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ValidDirections: " << this->ValidDirections << endl; + os << indent << "MinCells: " << this->MinCells << endl; + os << indent << "NumberOfRegionsOrLess: " << this->NumberOfRegionsOrLess << endl; + os << indent << "NumberOfRegionsOrMore: " << this->NumberOfRegionsOrMore << endl; + + os << indent << "NumberOfRegions: " << this->NumberOfRegions << endl; + + os << indent << "DataSets: " << this->DataSets << endl; + os << indent << "NumDataSets: " << this->NumDataSets << endl; + + os << indent << "Top: " << this->Top << endl; + os << indent << "RegionList: " << this->RegionList << endl; + + os << indent << "Timing: " << this->Timing << endl; + os << indent << "TimerLog: " << this->TimerLog << endl; + + os << indent << "NumDataSetsAllocated: " << this->NumDataSetsAllocated << endl; + os << indent << "IncludeRegionBoundaryCells: "; + os << this->IncludeRegionBoundaryCells << endl; + os << indent << "GenerateRepresentationUsingDataBounds: "; + os<< this->GenerateRepresentationUsingDataBounds << endl; + + if (this->CellList.nRegions > 0) + { + os << indent << "CellList.dataSet " << this->CellList.dataSet << endl; + os << indent << "CellList.regionIds " << this->CellList.regionIds << endl; + os << indent << "CellList.nRegions " << this->CellList.nRegions << endl; + os << indent << "CellList.cells " << this->CellList.cells << endl; + os << indent << "CellList.boundaryCells " << this->CellList.boundaryCells << endl; + } + os << indent << "CellRegionList: " << this->CellRegionList << endl; + + os << indent << "LocatorPoints: " << this->LocatorPoints << endl; + os << indent << "NumberOfLocatorPoints: " << this->NumberOfLocatorPoints << endl; + os << indent << "LocatorIds: " << this->LocatorIds << endl; + os << indent << "LocatorRegionLocation: " << this->LocatorRegionLocation << endl; + + os << indent << "FudgeFactor: " << this->FudgeFactor << endl; + os << indent << "MaxWidth: " << this->MaxWidth << endl; + + os << indent << "Cuts: "; + if( this->Cuts ) + { + this->Cuts->PrintSelf(os << endl, indent.GetNextIndent() ); + } + else + { + os << "(none)" << endl; + } +} diff --git a/Graphics/vtkKdTree.h b/Graphics/vtkKdTree.h new file mode 100644 index 0000000..f7b727c --- /dev/null +++ b/Graphics/vtkKdTree.h @@ -0,0 +1,712 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkKdTree.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkKdTree - a Kd-tree spatial decomposition of a set of points +// +// .SECTION Description +// Given one or more vtkDataSets, create a load balancing +// k-d tree decomposition of the points at the center of the cells. +// Or, create a k-d tree point locator from a list of points. +// +// This class can also generate a PolyData representation of +// the boundaries of the spatial regions in the decomposition. +// +// It can sort the regions with respect to a viewing direction, +// and it can decompose a list of regions into subsets, each +// of which represent a convex spatial region (since many algorithms +// require a convex region). +// +// If the points were derived from cells, vtkKdTree +// can create a list of cell Ids for each region for each data set. +// Two lists are available - all cells with centroid in the region, +// and all cells that intersect the region but whose centroid lies +// in another region. +// +// For the purpose of removing duplicate points quickly from large +// data sets, or for finding nearby points, we added another mode for +// building the locator. BuildLocatorFromPoints will build a k-d tree +// from one or more vtkPoints objects. This can be followed by +// BuildMapForDuplicatePoints which returns a mapping from the original +// ids to a subset of the ids that is unique within a supplied +// tolerance, or you can use FindPoint and FindClosestPoint to +// locate points in the original set that the tree was built from. +// +// .SECTION See Also +// vtkLocator vtkCellLocator vtkPKdTree + +#ifndef __vtkKdTree_h +#define __vtkKdTree_h + +#include "vtkLocator.h" + +class vtkTimerLog; +class vtkIdList; +class vtkIdTypeArray; +class vtkIntArray; +class vtkPoints; +class vtkCellArray; +class vtkCell; +class vtkKdNode; +class vtkBSPCuts; +class vtkBSPIntersections; + +class VTK_GRAPHICS_EXPORT vtkKdTree : public vtkLocator +{ +public: + vtkTypeRevisionMacro(vtkKdTree, vtkLocator); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkKdTree *New(); + + // Description: + // Turn on timing of the k-d tree build + vtkBooleanMacro(Timing, int); + vtkSetMacro(Timing, int); + vtkGetMacro(Timing, int); + + // Description: + // Minimum number of cells per spatial region. Default is 100. + vtkSetMacro(MinCells, int); + vtkGetMacro(MinCells, int); + + // Description: + // Set/Get the number of spatial regions you want to get close + // to without going over. (The number of spatial regions is normally + // a power of two.) Call this before BuildLocator(). Default + // is unset. + + vtkGetMacro(NumberOfRegionsOrLess, int); + vtkSetMacro(NumberOfRegionsOrLess, int); + + // Description: + // Set/Get the number of spatial regions you want to get close + // to while having at least this many regions. (The number of + // spatial regions is normally a power of two.) Default + // is unset. + + vtkGetMacro(NumberOfRegionsOrMore, int); + vtkSetMacro(NumberOfRegionsOrMore, int); + + // Description: + // Some algorithms on k-d trees require a value that is a very + // small distance relative to the diameter of the entire space + // divided by the k-d tree. This factor is the maximum axis-aligned + // width of the space multipled by 10e-6. + + vtkGetMacro(FudgeFactor, double); + vtkSetMacro(FudgeFactor, double); + + // Description: + // Get a vtkBSPCuts object, a general object representing an axis- + // aligned spatial partitioning. Used by vtkBSPIntersections. + + vtkGetObjectMacro(Cuts, vtkBSPCuts); + + // Description: + // Normally the k-d tree is computed from the dataset(s) provided + // in SetDataSet. Alternatively, you can provide the cuts that will + // be applied by calling SetCuts. + + void SetCuts(vtkBSPCuts *cuts); + + // Description: + // Omit partitions along the X axis, yielding shafts in the X direction + void OmitXPartitioning(); + + // Description: + // Omit partitions along the Y axis, yielding shafts in the Y direction + void OmitYPartitioning(); + + // Description: + // Omit partitions along the Z axis, yielding shafts in the Z direction + void OmitZPartitioning(); + + // Description: + // Omit partitions along the X and Y axes, yielding slabs along Z + void OmitXYPartitioning(); + + // Description: + // Omit partitions along the Y and Z axes, yielding slabs along X + void OmitYZPartitioning(); + + // Description: + // Omit partitions along the Z and X axes, yielding slabs along Y + void OmitZXPartitioning(); + + // Description: + // Partition along all three axes - this is the default + void OmitNoPartitioning(); + + // Description + // This class can compute a spatial decomposition based on the + // cells in a list of one or more input data sets. + // SetDataSet sets the first data set in the list to the named set. + // SetNthDataSet sets the data set at index N to the data set named. + // RemoveData set takes either the data set itself or an index and + // removes that data set from the list of data sets. + // AddDataSet adds a data set to the list of data sets. + + void SetDataSet(vtkDataSet *set); + void SetNthDataSet(int index, vtkDataSet *set); + void RemoveDataSet(int index); + void RemoveDataSet(vtkDataSet *set); + void AddDataSet(vtkDataSet *set); + + // Description: + // Get the number of data sets included in spatial paritioning + int GetNumberOfDataSets(){return this->NumDataSets;}; + + // Description: + // Get the nth defined data set in the spatial partitioning. + // (If you used SetNthDataSet to define 0,1 and 3 and ask for + // data set 2, you get 3.) + + vtkDataSet *GetDataSet(int n); + vtkDataSet *GetDataSet(){ return this->GetDataSet(0); } + + // Description: + // Get handle for one of the data sets included in spatial paritioning. + // Handles can change after RemoveDataSet. + int GetDataSet(vtkDataSet *set); + + // Description: + // Get the spatial bounds of the entire k-d tree space. Sets + // bounds array to xmin, xmax, ymin, ymax, zmin, zmax. + void GetBounds(double *bounds); + + // Description: + // There are certain applications where you want the bounds of + // the k-d tree space to be at least as large as a specified + // box. If the k-d tree has been built, you can expand it's + // bounds with this method. If the bounds supplied are smaller + // than those computed, they will be ignored. + + void SetNewBounds(double *bounds); + + // Description: + // The number of leaf nodes of the tree, the spatial regions + vtkGetMacro(NumberOfRegions, int); + + // Description: + // Get the spatial bounds of k-d tree region + void GetRegionBounds(int regionID, double bounds[6]); + + // Description: + // Get the bounds of the data within the k-d tree region + void GetRegionDataBounds(int regionID, double bounds[6]); + + // Description: + // Print out nodes of kd tree + void PrintTree(); + void PrintVerboseTree(); + + // Description: + // Print out leaf node data for given id + void PrintRegion(int id); + + // Description: + // Create a list for each of the requested regions, listing + // the IDs of all cells whose centroid falls in the region. + // These lists are obtained with GetCellList(). + // If no DataSet is specified, the cell list is created + // for DataSet 0. If no list of requested regions is provided, + // the cell lists for all regions are created. + // + // When CreateCellLists is called again, the lists created + // on the previous call are deleted. + + void CreateCellLists(int DataSet, int *regionReqList, + int reqListSize); + void CreateCellLists(vtkDataSet *set, int *regionReqList, + int reqListSize); + void CreateCellLists(int *regionReqList, int listSize); + void CreateCellLists(); + + // Description: + // If IncludeRegionBoundaryCells is ON, + // CreateCellLists() will also create a list of cells which + // intersect a given region, but are not assigned + // to the region. These lists are obtained with + // GetBoundaryCellList(). Default is OFF. + vtkSetMacro(IncludeRegionBoundaryCells, int); + vtkGetMacro(IncludeRegionBoundaryCells, int); + vtkBooleanMacro(IncludeRegionBoundaryCells, int); + + // Description: + // Free the memory used by the cell lists. + void DeleteCellLists(); + + // Description: + // Get the cell list for a region. This returns a pointer + // to vtkKdTree's memory, so don't free it. + vtkIdList *GetCellList(int regionID); + + // Description: + // The cell list obtained with GetCellList is the list + // of all cells such that their centroid is contained in + // the spatial region. It may also be desirable to get + // a list of all cells intersecting a spatial region, + // but with centroid in some other region. This is that + // list. This list is computed in CreateCellLists() if + // and only if IncludeRegionBoundaryCells is ON. This + // returns a pointer to KdTree's memory, so don't free it. + vtkIdList *GetBoundaryCellList(int regionID); + + // Description: + // + // For a list of regions, get two cell lists. The first lists + // the IDs all cells whose centroids lie in one of the regions. + // The second lists the IDs of all cells that intersect the regions, + // but whose centroid lies in a region not on the list. + // + // The total number of cell IDs written to both lists is returned. + // Either list pointer passed in can be NULL, and it will be ignored. + // If there are multiple data sets, you must specify which data set + // you wish cell IDs for. + // + // The caller should delete these two lists when done. This method + // uses the cell lists created in CreateCellLists(). + // If the cell list for any of the requested regions does not + // exist, then this method will call CreateCellLists() to create + // cell lists for *every* region of the k-d tree. You must remember + // to DeleteCellLists() when done with all calls to this method, as + // cell lists can require a great deal of memory. + vtkIdType GetCellLists(vtkIntArray *regions, int set, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells); + vtkIdType GetCellLists(vtkIntArray *regions, vtkDataSet *set, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells); + vtkIdType GetCellLists(vtkIntArray *regions, vtkIdList *inRegionCells, + vtkIdList *onBoundaryCells); + + // Description: + // Get the id of the region containing the cell centroid. If + // no DataSet is specified, assume DataSet 0. If you need the + // region ID for every cell, use AllGetRegionContainingCell + // instead. It is more efficient. + int GetRegionContainingCell(vtkDataSet *set, vtkIdType cellID); + int GetRegionContainingCell(int set, vtkIdType cellID); + int GetRegionContainingCell(vtkIdType cellID); + + // Description: + // Get a list (in order by data set by cell id) of the + // region IDs of the region containing the centroid for + // each cell. + // This is faster than calling GetRegionContainingCell + // for each cell in the DataSet. + // vtkKdTree uses this list, so don't delete it. + int *AllGetRegionContainingCell(); + + // Description: + // Get the id of the region containing the specified location. + int GetRegionContainingPoint(double x, double y, double z); + + // Description: + // Create the k-d tree decomposition of the cells of the data set + // or data sets. Cells are assigned to k-d tree spatial regions + // based on the location of their centroids. + void BuildLocator(); + + // Description: + // Given a list of region IDs, determine the decomposition of + // these regions into the minimal number of convex subregions. Due + // to the way the k-d tree is constructed, those convex subregions + // will be axis-aligned boxes. Return the minimal number of + // such convex regions that compose the original region list. + // This call will set convexRegionBounds to point to a list + // of the bounds of these regions. Caller should free this. + // There will be six values for each convex subregion (xmin, + // xmax, ymin, ymax, zmin, zmax). If the regions in the + // regionIdList form a box already, a "1" is returned and the + // second argument contains the bounds of the box. + + int MinimalNumberOfConvexSubRegions(vtkIntArray *regionIdList, + double **convexRegionBounds); + + // Description: + // Given a direction of projection (typically obtained with + // vtkCamera::GetDirectionOfProjection()), this function + // creates a list of the k-d tree region IDs in order from + // front to back with respect to the that direction. + // The number of regions in + // the ordered list is returned. (This is not actually sorting + // the regions on their distance from the view plane, but there + // is no region on the list which blocks a region that appears + // earlier on the list.) + + int DepthOrderAllRegions(double *dop, vtkIntArray *orderedList); + + // Description: + // Given a direction of projection, and a list of k-d tree region + // IDs, this function creates an ordered list of those IDs + // in front to back order with respect to the + // camera's direction of projection. The number of regions in + // the ordered list is returned. + + int DepthOrderRegions(vtkIntArray *regionIds, double *dop, + vtkIntArray *orderedList); + + // Description: + // This is a special purpose locator that builds a k-d tree to + // find duplicate and near-by points. It builds the tree from + // one or more vtkPoints objects instead of from the cells of + // a vtkDataSet. This build would normally be followed by + // BuildMapForDuplicatePoints, FindPoint, or FindClosestPoint. + // Since this will build a normal k-d tree, all the region intersection + // queries will still work, as will most other calls except those that + // have "Cell" in the name. + // + // This method works most efficiently when the point arrays are + // float arrays. + void BuildLocatorFromPoints(vtkPoints *ptArray); + void BuildLocatorFromPoints(vtkPoints **ptArray, int numPtArrays); + + // Description: + // This call returns a mapping from the original point IDs supplied + // to BuildLocatorFromPoints to a subset of those IDs that is unique + // within the specified tolerance. + // If points 2, 5, and 12 are the same, then + // IdMap[2] = IdMap[5] = IdMap[12] = 2 (or 5 or 12). + // + // "original point IDs" - For point IDs we start at 0 for the first + // point in the first vtkPoints object, and increase by 1 for subsequent + // points and subsequent vtkPoints objects. + // + // You must have called BuildLocatorFromPoints() before calling this. + // You are responsible for deleting the returned array. + vtkIdTypeArray *BuildMapForDuplicatePoints(float tolerance); + + // Description: + // Find the Id of the point that was previously supplied + // to BuildLocatorFromPoints(). Returns -1 if the point + // was not in the original array. + vtkIdType FindPoint(double *x); + vtkIdType FindPoint(double x, double y, double z); + + // Description: + // Find the Id of the point that was previously supplied + // to BuildLocatorFromPoints() which is closest to the given point. + // Set the square of the distance between the two points. + vtkIdType FindClosestPoint(double *x, double &dist2); + vtkIdType FindClosestPoint(double x, double y, double z, double &dist2); + + // Description: + // Find the Id of the point in the given region which is + // closest to the given point. Return the ID of the point, + // and set the square of the distance of between the points. + vtkIdType FindClosestPointInRegion(int regionId, double *x, double &dist2); + vtkIdType FindClosestPointInRegion(int regionId, double x, double y, double z, + double &dist2); + + // Description: + // Get a list of the original IDs of all points in a region. You + // must have called BuildLocatorFromPoints before calling this. + vtkIdTypeArray *GetPointsInRegion(int regionId); + + // Description: + // Delete the k-d tree data structure. Also delete any + // cell lists that were computed with CreateCellLists(). + void FreeSearchStructure(); + + // Description: + // Create a polydata representation of the boundaries of + // the k-d tree regions. If level equals GetLevel(), the + // leaf nodes are represented. + void GenerateRepresentation(int level, vtkPolyData *pd); + + // Description: + // Generate a polygonal representation of a list of regions. + // Only leaf nodes have region IDs, so these will be leaf nodes. + void GenerateRepresentation(int *regionList, int len, vtkPolyData *pd); + + // Description: + // The polydata representation of the k-d tree shows the boundaries + // of the k-d tree decomposition spatial regions. The data inside + // the regions may not occupy the entire space. To draw just the + // bounds of the data in the regions, set this variable ON. + vtkBooleanMacro(GenerateRepresentationUsingDataBounds, int); + vtkSetMacro(GenerateRepresentationUsingDataBounds, int); + vtkGetMacro(GenerateRepresentationUsingDataBounds, int); + + // Description: + // Print timing of k-d tree build + virtual void PrintTiming(ostream& os, vtkIndent indent); + + // Description: + // Return 1 if the geometry of the input data sets + // has changed since the last time the k-d tree was built. + int NewGeometry(); + + // Description: + // Return 1 if the geometry of these data sets differs + // for the geometry of the last data sets used to build + // the k-d tree. + int NewGeometry(vtkDataSet **sets, int numDataSets); + + // Description: + // Create a copy of the binary tree representation of the + // k-d tree spatial partitioning provided. + + static vtkKdNode *CopyTree(vtkKdNode *kd); + +protected: + + vtkKdTree(); + ~vtkKdTree(); + + vtkBSPIntersections *BSPCalculator; + int UserDefinedCuts; + + void SetCalculator(vtkKdNode *kd); + + int ProcessUserDefinedCuts(double *bounds); + + void SetCuts(vtkBSPCuts *cuts, int userDefined); + + // Description: + // Save enough state so NewGeometry() can work, + // and update the BuildTime time stamp. + + void UpdateBuildTime(); + + // Description: + // Prior to dividing a region at level "level", of size + // "numberOfPoints", apply the tests implied by MinCells, + // NumberOfRegionsOrMore and NumberOfRegionsOrLess. Return 1 if it's + // OK to divide the region, 0 if you should not. + + int DivideTest(int numberOfPoints, int level); + +//BTX + enum { + XDIM = 0, // don't change these values + YDIM = 1, + ZDIM = 2 + }; +//ETX + + int ValidDirections; + + vtkKdNode *Top; + vtkKdNode **RegionList; // indexed by region ID + + vtkTimerLog *TimerLog; + + static void DeleteAllDescendants(vtkKdNode *nd); + + void BuildRegionList(); + virtual int SelectCutDirection(vtkKdNode *kd); + void SetActualLevel(){this->Level = vtkKdTree::ComputeLevel(this->Top);} + + // Description: + // Get back a list of the nodes at a specified level, nodes must + // be preallocated to hold 2^^(level) node structures. + + void GetRegionsAtLevel(int level, vtkKdNode **nodes); + + // Description: + // Adds to the vtkIntArray the list of region IDs of all leaf + // nodes in the given node. + + static void GetLeafNodeIds(vtkKdNode *node, vtkIntArray *ids); + + + // Description: + // Returns the total number of cells in all the data sets + + int GetNumberOfCells(); + + // Description: + // Returns the total number of cells in data set 1 through + // data set 2. + + int GetDataSetsNumberOfCells(int set1, int set2); + + // Description: + // Get or compute the center of one cell. If the DataSet is + // NULL, the first DataSet is used. This is the point used in + // determining to which spatial region the cell is assigned. + + void ComputeCellCenter(vtkDataSet *set, int cellId, float *center); + void ComputeCellCenter(vtkDataSet *set, int cellId, double *center); + + // Description: + // Compute and return a pointer to a list of all cell centers, + // in order by data set by cell Id. If a DataSet is specified + // cell centers for cells of that data only are returned. If + // no DataSet is specified, the cell centers of cells in all + // DataSets are returned. The caller should free the list of + // cell centers when done. + + float *ComputeCellCenters(); + float *ComputeCellCenters(int set); + float *ComputeCellCenters(vtkDataSet *set); + + virtual void ReportReferences(vtkGarbageCollector*); + +private: + + static void _SetNewBounds(vtkKdNode *kd, double *b, int *fixDim); + static void CopyChildNodes(vtkKdNode *to, vtkKdNode *from); + static void CopyKdNode(vtkKdNode *to, vtkKdNode *from); + static void SetDataBoundsToSpatialBounds(vtkKdNode *kd); + static void ZeroNumberOfPoints(vtkKdNode *kd); + +//BTX + int DivideRegion(vtkKdNode *kd, float *c1, int *ids, int nlevels); + + void DoMedianFind(vtkKdNode *kd, float *c1, int *ids, int d1, int d2, int d3); + + void SelfRegister(vtkKdNode *kd); + + struct _cellList{ + vtkDataSet *dataSet; // cell lists for which data set + int *regionIds; // NULL if listing all regions + int nRegions; + vtkIdList **cells; + vtkIdList **boundaryCells; + vtkIdList *emptyList; + }; +//ETX + + void InitializeCellLists(); + vtkIdList *GetList(int regionId, vtkIdList **which); + + void ComputeCellCenter(vtkCell* cell, double *center, double *weights); + + void GenerateRepresentationDataBounds(int level, vtkPolyData *pd); + void _generateRepresentationDataBounds(vtkKdNode *kd, vtkPoints *pts, + vtkCellArray *polys, int level); + + void GenerateRepresentationWholeSpace(int level, vtkPolyData *pd); + void _generateRepresentationWholeSpace(vtkKdNode *kd, vtkPoints *pts, + vtkCellArray *polys, int level); + + void AddPolys(vtkKdNode *kd, vtkPoints *pts, vtkCellArray *polys); + + void _printTree(int verbose); + + int SearchNeighborsForDuplicate(int regionId, float *point, + int **pointsSoFar, int *len, + float tolerance, float tolerance2); + + int SearchRegionForDuplicate(float *point, int *pointsSoFar, + int len, float tolerance2); + + int _FindClosestPointInRegion(int regionId, + double x, double y, double z, double &dist2); + + int FindClosestPointInSphere(double x, double y, double z, double radius, + int skipRegion, double &dist2); + + int _DepthOrderRegions(vtkIntArray *IdsOfInterest, double *dop, + vtkIntArray *orderedList); + + static int __DepthOrderRegions(vtkKdNode *node, vtkIntArray *list, + vtkIntArray *IdsOfInterest, double *dir, int nextId); + static int __ConvexSubRegions(int *ids, int len, vtkKdNode *tree, vtkKdNode **nodes); + static int FoundId(vtkIntArray *idArray, int id); + + void NewParitioningRequest(int req); + void SetInputDataInfo(int i, + int dims[3], double origin[3], double spacing[3]); + int CheckInputDataInfo(int i, + int dims[3], double origin[3], double spacing[3]); + void ClearLastBuildCache(); + +//BTX + static void __printTree(vtkKdNode *kd, int depth, int verbose); +//ETX + + static int MidValue(int dim, float *c1, int nvals, double &coord); + + static int Select(int dim, float *c1, int *ids, int nvals, double &coord); + static float FindMaxLeftHalf(int dim, float *c1, int K); + static void _Select(int dim, float *X, int *ids, int L, int R, int K); + +//BTX + static int ComputeLevel(vtkKdNode *kd); + static int SelfOrder(int id, vtkKdNode *kd); + static int findRegion(vtkKdNode *node, float x, float y, float z); + static int findRegion(vtkKdNode *node, double x, double y, double z); +//ETX + + static vtkKdNode **_GetRegionsAtLevel(int level, vtkKdNode **nodes, + vtkKdNode *kd); + + static void AddNewRegions(vtkKdNode *kd, float *c1, + int midpt, int dim, double coord); + + void NewPartitioningRequest(int req); + + int NumDataSetsAllocated; + + int NumberOfRegionsOrLess; + int NumberOfRegionsOrMore; + + int IncludeRegionBoundaryCells; + double CellBoundsCache[6]; // to optimize IntersectsCell() + + int GenerateRepresentationUsingDataBounds; + +//BTX + struct _cellList CellList; +//ETX + + // Region Ids, by data set by cell id - this list is large (one + // int per cell) but accelerates creation of cell lists + + int *CellRegionList; + + int MinCells; + int NumberOfRegions; // number of leaf nodes + + int Timing; + double FudgeFactor; // a very small distance, relative to the dataset's size + + vtkDataSet **DataSets; + int NumDataSets; + + // These instance variables are used by the special locator created + // to find duplicate points. (BuildLocatorFromPoints) + + int NumberOfLocatorPoints; + float *LocatorPoints; + int *LocatorIds; + int *LocatorRegionLocation; + + float MaxWidth; + + // These Last* values are here to save state so we can + // determine later if k-d tree must be rebuilt. + + int LastNumDataSets; + int LastDataCacheSize; + vtkDataSet **LastInputDataSets; + int *LastDataSetType; + double *LastInputDataInfo; + double *LastBounds; + int *LastNumPoints; + int *LastNumCells; + + vtkBSPCuts *Cuts; + + vtkKdTree(const vtkKdTree&); // Not implemented + void operator=(const vtkKdTree&); // Not implemented +}; +#endif diff --git a/Graphics/vtkLineSource.cxx b/Graphics/vtkLineSource.cxx new file mode 100644 index 0000000..08d0f50 --- /dev/null +++ b/Graphics/vtkLineSource.cxx @@ -0,0 +1,147 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLineSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLineSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +#include +vtkCxxRevisionMacro(vtkLineSource, "$Revision: 1.47 $"); +vtkStandardNewMacro(vtkLineSource); + +vtkLineSource::vtkLineSource(int res) +{ + this->Point1[0] = -0.5; + this->Point1[1] = 0.0; + this->Point1[2] = 0.0; + + this->Point2[0] = 0.5; + this->Point2[1] = 0.0; + this->Point2[2] = 0.0; + + this->Resolution = (res < 1 ? 1 : res); + + this->SetNumberOfInputPorts(0); +} + +int vtkLineSource::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + return 1; +} + +int vtkLineSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int numLines=this->Resolution; + int numPts=this->Resolution+1; + double x[3], tc[3], v[3]; + int i, j; + vtkPoints *newPoints; + vtkFloatArray *newTCoords; + vtkCellArray *newLines; + + if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) + { + return 1; + } + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*numPts); + + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(numLines,2)); +// +// Generate points and texture coordinates +// + for (i=0; i<3; i++) + { + v[i] = this->Point2[i] - this->Point1[i]; + } + + tc[1] = 0.0; + tc[2] = 0.0; + for (i=0; iResolution); + for (j=0; j<3; j++) + { + x[j] = this->Point1[j] + tc[0]*v[j]; + } + newPoints->InsertPoint(i,x); + newTCoords->InsertTuple(i,tc); + } +// +// Generate lines +// + newLines->InsertNextCell(numPts); + for (i=0; i < numPts; i++) + { + newLines->InsertCellPoint (i); + } +// +// Update ourselves and release memory +// + output->SetPoints(newPoints); + newPoints->Delete(); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +void vtkLineSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Resolution: " << this->Resolution << "\n"; + + os << indent << "Point 1: (" << this->Point1[0] << ", " + << this->Point1[1] << ", " + << this->Point1[2] << ")\n"; + + os << indent << "Point 2: (" << this->Point2[0] << ", " + << this->Point2[1] << ", " + << this->Point2[2] << ")\n"; +} diff --git a/Graphics/vtkLineSource.h b/Graphics/vtkLineSource.h new file mode 100644 index 0000000..b25d604 --- /dev/null +++ b/Graphics/vtkLineSource.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLineSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLineSource - create a line defined by two end points +// .SECTION Description +// vtkLineSource is a source object that creates a polyline defined by +// two endpoints. The number of segments composing the polyline is +// controlled by setting the object resolution. + +#ifndef __vtkLineSource_h +#define __vtkLineSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkLineSource : public vtkPolyDataAlgorithm +{ +public: + static vtkLineSource *New(); + vtkTypeRevisionMacro(vtkLineSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set position of first end point. + vtkSetVector3Macro(Point1,double); + vtkGetVectorMacro(Point1,double,3); + + // Description: + // Set position of other end point. + vtkSetVector3Macro(Point2,double); + vtkGetVectorMacro(Point2,double,3); + + // Description: + // Divide line into resolution number of pieces. + vtkSetClampMacro(Resolution,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(Resolution,int); + +protected: + vtkLineSource(int res=1); + ~vtkLineSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double Point1[3]; + double Point2[3]; + int Resolution; +private: + vtkLineSource(const vtkLineSource&); // Not implemented. + void operator=(const vtkLineSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkLinearExtrusionFilter.cxx b/Graphics/vtkLinearExtrusionFilter.cxx new file mode 100644 index 0000000..8b819a6 --- /dev/null +++ b/Graphics/vtkLinearExtrusionFilter.cxx @@ -0,0 +1,425 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinearExtrusionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLinearExtrusionFilter.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkLinearExtrusionFilter, "$Revision: 1.62 $"); +vtkStandardNewMacro(vtkLinearExtrusionFilter); + +// Create object with normal extrusion type, capping on, scale factor=1.0, +// vector (0,0,1), and extrusion point (0,0,0). +vtkLinearExtrusionFilter::vtkLinearExtrusionFilter() +{ + this->ExtrusionType = VTK_NORMAL_EXTRUSION; + this->Capping = 1; + this->ScaleFactor = 1.0; + this->Vector[0] = this->Vector[1] = 0.0; this->Vector[2] = 1.0; + this->ExtrusionPoint[0] = this->ExtrusionPoint[1] = this->ExtrusionPoint[2] = 0.0; +} + +double *vtkLinearExtrusionFilter::ViaNormal(double x[3], vtkIdType id, + vtkDataArray *n) +{ + static double xNew[3], normal[3]; + int i; + + n->GetTuple(id, normal); + for (i=0; i<3; i++) + { + xNew[i] = x[i] + this->ScaleFactor*normal[i]; + } + + return xNew; +} + +double *vtkLinearExtrusionFilter::ViaVector(double x[3], + vtkIdType vtkNotUsed(id), + vtkDataArray *vtkNotUsed(n)) +{ + static double xNew[3]; + int i; + + for (i=0; i<3; i++) + { + xNew[i] = x[i] + this->ScaleFactor*this->Vector[i]; + } + + return xNew; +} + +double *vtkLinearExtrusionFilter::ViaPoint(double x[3], vtkIdType vtkNotUsed(id), + vtkDataArray *vtkNotUsed(n)) +{ + static double xNew[3]; + int i; + + for (i=0; i<3; i++) + { + xNew[i] = x[i] + this->ScaleFactor*(x[i] - this->ExtrusionPoint[i]); + } + + return xNew; +} + +int vtkLinearExtrusionFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells; + vtkPointData *pd=input->GetPointData(); + vtkDataArray *inNormals=NULL; + vtkPolyData *mesh; + vtkPoints *inPts; + vtkCellArray *inVerts, *inLines, *inPolys, *inStrips; + vtkIdType inCellId, outCellId; + int numEdges, dim; + vtkIdType *pts = 0; + vtkIdType npts = 0; + vtkIdType ptId, ncells, p1, p2; + int i, j; + double x[3]; + vtkPoints *newPts; + vtkCellArray *newLines=NULL, *newPolys=NULL, *newStrips; + vtkCell *edge; + vtkIdList *cellIds, *cellPts; + vtkPointData *outputPD = output->GetPointData(); + // Here is a big pain about ordering of cells. (Copy CellData) + vtkIdList *lineIds; + vtkIdList *polyIds; + vtkIdList *stripIds; + + // Initialize / check input + // + vtkDebugMacro(<<"Linearly extruding data"); + + numPts=input->GetNumberOfPoints(); + numCells=input->GetNumberOfCells(); + + if (numPts < 1 || numCells < 1) + { + vtkErrorMacro(<<"No data to extrude!"); + return 1; + } + // + // Decide which vector to use for extrusion + // + if ( this->ExtrusionType == VTK_POINT_EXTRUSION ) + { + this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaPoint; + } + else if ( this->ExtrusionType == VTK_NORMAL_EXTRUSION && + (inNormals = pd->GetNormals()) != NULL ) + { + this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaNormal; + inNormals = pd->GetNormals(); + } + else // VTK_VECTOR_EXTRUSION + { + this->ExtrudePoint = &vtkLinearExtrusionFilter::ViaVector; + } + + // Build cell data structure. + // + mesh = vtkPolyData::New(); + inPts = input->GetPoints(); + inVerts = input->GetVerts(); + inLines = input->GetLines(); + inPolys = input->GetPolys(); + inStrips = input->GetStrips(); + mesh->SetPoints(inPts); + mesh->SetVerts(inVerts); + mesh->SetLines(inLines); + mesh->SetPolys(inPolys); + mesh->SetStrips(inStrips); + if (inPolys->GetNumberOfCells() || inStrips->GetNumberOfCells()) + { + mesh->BuildLinks(); + } + + cellIds = vtkIdList::New(); + cellIds->Allocate(VTK_CELL_SIZE); + + + // Allocate memory for output. We don't copy normals because surface geometry + // is modified. Copy all points - this is the usual requirement and it makes + // creation of skirt much easier. + // + output->GetCellData()->CopyNormalsOff(); + output->GetCellData()->CopyAllocate(input->GetCellData(), + 3*input->GetNumberOfCells()); + + outputPD->CopyNormalsOff(); + outputPD->CopyAllocate(pd,2*numPts); + newPts = vtkPoints::New(); newPts->SetNumberOfPoints(2*numPts); + if ( (ncells=inVerts->GetNumberOfCells()) > 0 ) + { + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(ncells,2)); + } + // arbitrary initial allocation size + ncells = inLines->GetNumberOfCells() + inPolys->GetNumberOfCells()/10 + + inStrips->GetNumberOfCells()/10; + ncells = (ncells < 100 ? 100 : ncells); + newStrips = vtkCellArray::New(); + newStrips->Allocate(newStrips->EstimateSize(ncells,4)); + + vtkIdType progressInterval=numPts/10+1; + int abort=0; + + // copy points + for (ptId=0; ptId < numPts; ptId++) + { + if ( ! (ptId % progressInterval) ) //manage progress / early abort + { + this->UpdateProgress (0.25*ptId/numPts); + } + + inPts->GetPoint(ptId, x); + newPts->SetPoint(ptId,x); + newPts->SetPoint(ptId+numPts, + (this->*(this->ExtrudePoint))(x,ptId,inNormals)); + outputPD->CopyData(pd,ptId,ptId); + outputPD->CopyData(pd,ptId,ptId+numPts); + } + + // We need the cellid to copy cell data. Skip points and lines. + inCellId = outCellId =0; + if (input->GetVerts()) + { + inCellId += input->GetVerts()->GetNumberOfCells(); + } + if (input->GetLines()) + { + inCellId += input->GetLines()->GetNumberOfCells(); + } + // We need to keep track of input cell ids used to generate + // output cells so that we can copy cell data at the end. + // We do not know how many lines, polys and strips we will get + // before hand. + lineIds = vtkIdList::New(); + polyIds = vtkIdList::New(); + stripIds = vtkIdList::New(); + + // If capping is on, copy 2D cells to output (plus create cap) + // + if ( this->Capping ) + { + if ( inPolys->GetNumberOfCells() > 0 ) + { + newPolys = vtkCellArray::New(); + newPolys->Allocate(inPolys->GetSize()); + for ( inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + newPolys->InsertNextCell(npts,pts); + polyIds->InsertNextId(inCellId); + newPolys->InsertNextCell(npts); + for (i=0; i < npts; i++) + { + newPolys->InsertCellPoint(pts[i] + numPts); + } + polyIds->InsertNextId(inCellId); + ++inCellId; + } + } + + if ( inStrips->GetNumberOfCells() > 0 ) + { + for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + newStrips->InsertNextCell(npts,pts); + stripIds->InsertNextId(inCellId); + newStrips->InsertNextCell(npts); + for (i=0; i < npts; i++) + { + newStrips->InsertCellPoint(pts[i] + numPts); + } + stripIds->InsertNextId(inCellId); + ++inCellId; + } + } + } + this->UpdateProgress (0.4); + + // Loop over all polygons and triangle strips searching for boundary edges. + // If boundary edge found, extrude triangle strip. + // + progressInterval=numCells/10+1; + vtkGenericCell *cell = vtkGenericCell::New(); + for ( inCellId=0; inCellId < numCells && !abort; inCellId++) + { + if ( ! (inCellId % progressInterval) ) //manage progress / early abort + { + this->UpdateProgress (0.4 + 0.6*inCellId/numCells); + abort = this->GetAbortExecute(); + } + + mesh->GetCell(inCellId,cell); + cellPts = cell->GetPointIds(); + + if ( (dim=cell->GetCellDimension()) == 0 ) //create lines from points + { + for (i=0; iGetNumberOfIds(); i++) + { + newLines->InsertNextCell(2); + ptId = cellPts->GetId(i); + newLines->InsertCellPoint(ptId); + newLines->InsertCellPoint(ptId+numPts); + lineIds->InsertNextId(inCellId); + } + } + + else if ( dim == 1 ) // create strips from lines + { + for (i=0; i < (cellPts->GetNumberOfIds()-1); i++) + { + p1 = cellPts->GetId(i); + p2 = cellPts->GetId(i+1); + newStrips->InsertNextCell(4); + newStrips->InsertCellPoint(p1); + newStrips->InsertCellPoint(p2); + newStrips->InsertCellPoint(p1+numPts); + newStrips->InsertCellPoint(p2+numPts); + stripIds->InsertNextId(inCellId); + } + } + + else if ( dim == 2 ) // create strips from boundary edges + { + numEdges = cell->GetNumberOfEdges(); + for (i=0; iGetEdge(i); + for (j=0; j<(edge->GetNumberOfPoints()-1); j++) + { + p1 = edge->PointIds->GetId(j); + p2 = edge->PointIds->GetId(j+1); + mesh->GetCellEdgeNeighbors(inCellId, p1, p2, cellIds); + + if ( cellIds->GetNumberOfIds() < 1 ) //generate strip + { + newStrips->InsertNextCell(4); + newStrips->InsertCellPoint(p1); + newStrips->InsertCellPoint(p2); + newStrips->InsertCellPoint(p1+numPts); + newStrips->InsertCellPoint(p2+numPts); + stripIds->InsertNextId(inCellId); + } + } //for each sub-edge + } //for each edge + } //for each polygon or triangle strip + } //for each cell + cell->Delete(); + + // Now Copy cell data. + outCellId = 0; + j = lineIds->GetNumberOfIds(); + for (i = 0; i < j; ++i) + { + output->GetCellData()->CopyData(input->GetCellData(), + lineIds->GetId(i),outCellId); + ++outCellId; + } + j = polyIds->GetNumberOfIds(); + for (i = 0; i < j; ++i) + { + output->GetCellData()->CopyData(input->GetCellData(), + polyIds->GetId(i),outCellId); + ++outCellId; + } + j = stripIds->GetNumberOfIds(); + for (i = 0; i < j; ++i) + { + output->GetCellData()->CopyData(input->GetCellData(), + stripIds->GetId(i),outCellId); + ++outCellId; + } + lineIds->Delete(); + stripIds->Delete(); + polyIds->Delete(); + polyIds = NULL; + + + // Send data to output and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + cellIds->Delete(); + mesh->Delete(); + + if ( newLines ) + { + output->SetLines(newLines); + newLines->Delete(); + } + + if ( newPolys ) + { + output->SetPolys(newPolys); + newPolys->Delete(); + } + + output->SetStrips(newStrips); + newStrips->Delete(); + + output->Squeeze(); + + return 1; +} + +void vtkLinearExtrusionFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->ExtrusionType == VTK_VECTOR_EXTRUSION ) + { + os << indent << "Extrusion Type: Extrude along vector\n"; + os << indent << "Vector: (" << this->Vector[0] << ", " + << this->Vector[1] << ", " << this->Vector[2] << ")\n"; + } + else if ( this->ExtrusionType == VTK_NORMAL_EXTRUSION ) + { + os << indent << "Extrusion Type: Extrude along vertex normals\n"; + } + else //POINT_EXTRUSION + { + os << indent << "Extrusion Type: Extrude towards point\n"; + os << indent << "Extrusion Point: (" << this->ExtrusionPoint[0] << ", " + << this->ExtrusionPoint[1] << ", " << this->ExtrusionPoint[2] << ")\n"; + } + + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; +} diff --git a/Graphics/vtkLinearExtrusionFilter.h b/Graphics/vtkLinearExtrusionFilter.h new file mode 100644 index 0000000..3b280c9 --- /dev/null +++ b/Graphics/vtkLinearExtrusionFilter.h @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinearExtrusionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLinearExtrusionFilter - sweep polygonal data creating a "skirt" from free edges and lines, and lines from vertices +// .SECTION Description +// vtkLinearExtrusionFilter is a modeling filter. It takes polygonal data as +// input and generates polygonal data on output. The input dataset is swept +// according to some extrusion function and creates new polygonal primitives. +// These primitives form a "skirt" or swept surface. For example, sweeping a +// line results in a quadrilateral, and sweeping a triangle creates a "wedge". +// +// There are a number of control parameters for this filter. You can +// control whether the sweep of a 2D object (i.e., polygon or triangle strip) +// is capped with the generating geometry via the "Capping" ivar. Also, you +// can extrude in the direction of a user specified vector, towards a point, +// or in the direction of vertex normals (normals must be provided - use +// vtkPolyDataNormals if necessary). The amount of extrusion is controlled by +// the "ScaleFactor" instance variable. +// +// The skirt is generated by locating certain topological features. Free +// edges (edges of polygons or triangle strips only used by one polygon or +// triangle strips) generate surfaces. This is true also of lines or +// polylines. Vertices generate lines. +// +// This filter can be used to create 3D fonts, 3D irregular bar charts, +// or to model 2 1/2D objects like punched plates. It also can be used to +// create solid objects from 2D polygonal meshes. + +// .SECTION Caveats +// Some polygonal objects have no free edges (e.g., sphere). When swept, +// this will result in two separate surfaces if capping is on, or no surface +// if capping is off. + +// .SECTION See Also +// vtkRotationalExtrusionFilter + +#ifndef __vtkLinearExtrusionFilter_h +#define __vtkLinearExtrusionFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkDataArray; + +#define VTK_VECTOR_EXTRUSION 1 +#define VTK_NORMAL_EXTRUSION 2 +#define VTK_POINT_EXTRUSION 3 + +class VTK_GRAPHICS_EXPORT vtkLinearExtrusionFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkLinearExtrusionFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create object with normal extrusion type, capping on, scale factor=1.0, + // vector (0,0,1), and extrusion point (0,0,0). + static vtkLinearExtrusionFilter *New(); + + // Description: + // Set/Get the type of extrusion. + vtkSetClampMacro(ExtrusionType,int,VTK_VECTOR_EXTRUSION,VTK_POINT_EXTRUSION); + vtkGetMacro(ExtrusionType,int); + void SetExtrusionTypeToVectorExtrusion() + {this->SetExtrusionType(VTK_VECTOR_EXTRUSION);}; + void SetExtrusionTypeToNormalExtrusion() + {this->SetExtrusionType(VTK_NORMAL_EXTRUSION);}; + void SetExtrusionTypeToPointExtrusion() + {this->SetExtrusionType(VTK_POINT_EXTRUSION);}; + + // Description: + // Turn on/off the capping of the skirt. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + + // Description: + // Set/Get extrusion scale factor, + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Set/Get extrusion vector. Only needs to be set if VectorExtrusion is + // turned on. + vtkSetVector3Macro(Vector,double); + vtkGetVectorMacro(Vector,double,3); + + // Description: + // Set/Get extrusion point. Only needs to be set if PointExtrusion is + // turned on. This is the point towards which extrusion occurs. + vtkSetVector3Macro(ExtrusionPoint,double); + vtkGetVectorMacro(ExtrusionPoint,double,3); + +protected: + vtkLinearExtrusionFilter(); + ~vtkLinearExtrusionFilter() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int ExtrusionType; + int Capping; + double ScaleFactor; + double Vector[3]; + double ExtrusionPoint[3]; + + //BTX + double *(vtkLinearExtrusionFilter::*ExtrudePoint)(double x[3], vtkIdType id, + vtkDataArray *normals); + double *ViaNormal(double x[3], vtkIdType id, vtkDataArray *normals); + double *ViaVector(double x[3], vtkIdType id, vtkDataArray *normals=0); + double *ViaPoint(double x[3], vtkIdType id, vtkDataArray *normals=0); + //ETX + +private: + vtkLinearExtrusionFilter(const vtkLinearExtrusionFilter&); // Not implemented. + void operator=(const vtkLinearExtrusionFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkLinearSubdivisionFilter.cxx b/Graphics/vtkLinearSubdivisionFilter.cxx new file mode 100644 index 0000000..a93b243 --- /dev/null +++ b/Graphics/vtkLinearSubdivisionFilter.cxx @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinearSubdivisionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLinearSubdivisionFilter.h" + +#include "vtkCellArray.h" +#include "vtkEdgeTable.h" +#include "vtkIdList.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkLinearSubdivisionFilter, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkLinearSubdivisionFilter); + +void vtkLinearSubdivisionFilter::GenerateSubdivisionPoints (vtkPolyData *inputDS, vtkIntArray *edgeData, vtkPoints *outputPts, vtkPointData *outputPD) +{ + vtkIdType *pts = 0; + int edgeId; + vtkIdType npts, cellId, newId; + vtkIdType p1, p2; + vtkCellArray *inputPolys=inputDS->GetPolys(); + vtkEdgeTable *edgeTable; + vtkIdList *cellIds = vtkIdList::New(); + vtkIdList *pointIds = vtkIdList::New(); + vtkPoints *inputPts=inputDS->GetPoints(); + vtkPointData *inputPD=inputDS->GetPointData(); + static double weights[2] = {.5, .5}; + + // Create an edge table to keep track of which edges we've processed + edgeTable = vtkEdgeTable::New(); + edgeTable->InitEdgeInsertion(inputDS->GetNumberOfPoints()); + + pointIds->SetNumberOfIds(2); + + double total = inputPolys->GetNumberOfCells(); + double curr = 0; + + // Generate new points for subdivisions surface + for (cellId=0, inputPolys->InitTraversal(); + inputPolys->GetNextCell(npts, pts); cellId++) + { + if ( inputDS->GetCellType(cellId) != VTK_TRIANGLE ) + { + continue; + } + + p1 = pts[2]; + p2 = pts[0]; + + for (edgeId=0; edgeId < 3; edgeId++) + { + outputPD->CopyData (inputPD, p1, p1); + outputPD->CopyData (inputPD, p2, p2); + + // Do we need to create a point on this edge? + if (edgeTable->IsEdge (p1, p2) == -1) + { + edgeTable->InsertEdge (p1, p2); + // Compute Position andnew PointData using the same subdivision scheme + pointIds->SetId(0,p1); + pointIds->SetId(1,p2); + newId = + this->InterpolatePosition (inputPts, outputPts, pointIds, weights); + outputPD->InterpolatePoint (inputPD, newId, pointIds, weights); + } + else // we have already created a point on this edge. find it + { + newId = this->FindEdge (inputDS, cellId, p1, p2, edgeData, cellIds); + } + edgeData->InsertComponent(cellId,edgeId,newId); + p1 = p2; + if (edgeId < 2) + { + p2 = pts[edgeId + 1]; + } + } // each edge + this->UpdateProgress(curr / total); + curr += 1; + } // each cell + + edgeTable->Delete(); + cellIds->Delete(); + pointIds->Delete(); +} + diff --git a/Graphics/vtkLinearSubdivisionFilter.h b/Graphics/vtkLinearSubdivisionFilter.h new file mode 100644 index 0000000..2527994 --- /dev/null +++ b/Graphics/vtkLinearSubdivisionFilter.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinearSubdivisionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLinearSubdivisionFilter - generate a subdivision surface using the Linear Scheme +// .SECTION Description +// vtkLinearSubdivisionFilter is a filter that generates output by +// subdividing its input polydata. Each subdivision iteration create 4 +// new triangles for each triangle in the polydata. + +// .SECTION Thanks +// This work was supported by PHS Research Grant No. 1 P41 RR13218-01 +// from the National Center for Research Resources. + +// .SECTION See Also +// vtkInterpolatingSubdivisionFilter vtkButterflySubdivisionFilter + +#ifndef __vtkLinearSubdivisionFilter_h +#define __vtkLinearSubdivisionFilter_h + +#include "vtkInterpolatingSubdivisionFilter.h" + +class vtkIntArray; +class vtkPointData; +class vtkPoints; +class vtkPolyData; + +class VTK_GRAPHICS_EXPORT vtkLinearSubdivisionFilter : public vtkInterpolatingSubdivisionFilter +{ +public: + // Description: + // Construct object with NumberOfSubdivisions set to 1. + static vtkLinearSubdivisionFilter *New(); + vtkTypeRevisionMacro(vtkLinearSubdivisionFilter,vtkInterpolatingSubdivisionFilter); + +protected: + vtkLinearSubdivisionFilter () {}; + ~vtkLinearSubdivisionFilter () {}; + + void GenerateSubdivisionPoints (vtkPolyData *inputDS, + vtkIntArray *edgeData, + vtkPoints *outputPts, + vtkPointData *outputPD); + +private: + vtkLinearSubdivisionFilter(const vtkLinearSubdivisionFilter&); // Not implemented. + void operator=(const vtkLinearSubdivisionFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkLinkEdgels.cxx b/Graphics/vtkLinkEdgels.cxx new file mode 100644 index 0000000..63b4e7d --- /dev/null +++ b/Graphics/vtkLinkEdgels.cxx @@ -0,0 +1,363 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinkEdgels.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLinkEdgels.h" + +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkLinkEdgels, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkLinkEdgels); + +// Construct instance of vtkLinkEdgels with GradientThreshold set to +// 0.1, PhiThreshold set to 90 degrees and LinkThreshold set to 90 degrees. +vtkLinkEdgels::vtkLinkEdgels() +{ + this->GradientThreshold = 0.1; + this->PhiThreshold = 90; + this->LinkThreshold = 90; +} + +int vtkLinkEdgels::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd; + vtkPoints *newPts; + vtkCellArray *newLines; + vtkDoubleArray *inScalars; + vtkDoubleArray *outScalars; + vtkDoubleArray *outVectors; + int *dimensions; + double *CurrMap, *inDataPtr; + vtkDataArray *inVectors; + int ptId; + + vtkDebugMacro(<< "Extracting structured points geometry"); + + pd = input->GetPointData(); + dimensions = input->GetDimensions(); + inScalars = vtkDoubleArray::SafeDownCast(pd->GetScalars()); + inVectors = pd->GetVectors(); + if ((input->GetNumberOfPoints()) < 2 || inScalars == NULL) + { + vtkErrorMacro(<<"No data to transform (or wrong data type)!"); + return 1; + } + + // set up the input + inDataPtr = inScalars->GetPointer(0); + + // Finally do edge following to extract the edge data from the Thin image + newPts = vtkPoints::New(); + newLines = vtkCellArray::New(); + outScalars = vtkDoubleArray::New(); + outVectors = vtkDoubleArray::New(); + outVectors->SetNumberOfComponents(3); + + vtkDebugMacro("doing edge linking\n"); + // + // Traverse all points, for each point find Gradient in the Image map. + // + for (ptId=0; ptId < dimensions[2]; ptId++) + { + CurrMap = inDataPtr + dimensions[0]*dimensions[1]*ptId; + + this->LinkEdgels(dimensions[0],dimensions[1],CurrMap, inVectors, + newLines,newPts,outScalars,outVectors,ptId); + } + + output->SetPoints(newPts); + output->SetLines(newLines); + + // Update ourselves +// outScalars->ComputeRange(); + output->GetPointData()->SetScalars(outScalars); + output->GetPointData()->SetVectors(outVectors); + + newPts->Delete(); + newLines->Delete(); + outScalars->Delete(); + outVectors->Delete(); + + return 1; +} + +// This method links the edges for one image. +void vtkLinkEdgels::LinkEdgels(int xdim, int ydim, double *image, + vtkDataArray *inVectors, + vtkCellArray *newLines, + vtkPoints *newPts, + vtkDoubleArray *outScalars, + vtkDoubleArray *outVectors, + int z) +{ + int **forward; + int **backward; + int x,y,ypos,zpos; + int currX, currY, i; + int newX, newY; + double vec[3], vec1[3], vec2[3]; + double linkThresh, phiThresh; + // these direction vectors are rotated 90 degrees + // to convert gradient direction into edgel direction + static double directions[8][2] = { + {0,1}, {-0.707, 0.707}, + {-1,0}, {-0.707, -0.707}, + {0,-1}, {0.707, -0.707}, + {1,0}, {0.707, 0.707}}; + static int xoffset[8] = {1,1,0,-1,-1,-1,0,1}; + static int yoffset[8] = {0,1,1,1,0,-1,-1,-1}; + int length, start; + int bestDirection = 0; + double error, bestError; + + forward = new int *[ydim]; + backward = new int *[ydim]; + for (i = 0; i < ydim; i++) + { + forward[i] = new int [xdim]; + backward[i] = new int [xdim]; + memset(forward[i],0,xdim*sizeof(int)); + memset(backward[i],0,xdim*sizeof(int)); + } + + zpos = z*xdim*ydim; + linkThresh = cos(this->LinkThreshold*3.1415926/180.0); + phiThresh = cos(this->PhiThreshold*3.1415926/180.0); + + // first find all forward & backwards links + for (y = 0; y < ydim; y++) + { + ypos = y*xdim; + for (x = 0; x < xdim; x++) + { + // find forward and backward neighbor for this pixel + // if its value is less than threshold then ignore it + if (image[x+ypos] < this->GradientThreshold) + { + forward[y][x] = -1; + backward[y][x] = -1; + } + else + { + // try all neighbors as forward, first try four connected + inVectors->GetTuple(x+ypos+zpos,vec1); + vtkMath::Normalize(vec1); + // first eliminate based on phi1 - alpha + bestError = 0; + for (i = 0; i < 8; i += 2) + { + // make sure it passes the linkThresh test + if ((directions[i][0]*vec1[0]+directions[i][1]*vec1[1]) >= + linkThresh) + { + // make sure we dont go off the edge and are >= GradientThresh + // and it hasn't already been set + if ((x + xoffset[i] >= 0)&&(x + xoffset[i] < xdim)&& + (y + yoffset[i] >= 0)&&(y + yoffset[i] < ydim)&& + (!backward[y+yoffset[i]][x+xoffset[i]])&& + (image[x + xoffset[i] + (y+yoffset[i])*xdim] >= + this->GradientThreshold)) + { + // satisfied the first test, now check second + inVectors->GetTuple(x + xoffset[i] + + (y + yoffset[i])*xdim + zpos,vec2); + vtkMath::Normalize(vec2); + if ((vec1[0]*vec2[0] + vec1[1]*vec2[1]) >= phiThresh) + { + // pased phi - phi test does the forward neighbor + // pass the link test + if ((directions[i][0]*vec2[0]+directions[i][1]*vec2[1]) >= + linkThresh) + { + // check against the current best solution + error = (directions[i][0]*vec2[0]+directions[i][1]*vec2[1]) + + (directions[i][0]*vec1[0]+directions[i][1]*vec1[1]) + + (vec1[0]*vec2[0] + vec1[1]*vec2[1]); + if (error > bestError) + { + bestDirection = i; + bestError = error; + } + } + } + } + } + } + if (bestError > 0) + { + forward[y][x] = (bestDirection+1); + backward[y+yoffset[bestDirection]][x+xoffset[bestDirection]] + = ((bestDirection+4)%8)+1; + } + else + { + // check the eight connected neighbors now + for (i = 1; i < 8; i += 2) + { + // make sure it passes the linkThresh test + if ((directions[i][0]*vec1[0]+directions[i][1]*vec1[1]) >= + linkThresh) + { + // make sure we dont go off the edge and are >= GradientThresh + // and it hasn't already been set + if ((x + xoffset[i] >= 0)&&(x + xoffset[i] < xdim)&& + (y + yoffset[i] >= 0)&&(y + yoffset[i] < ydim)&& + (!backward[y+yoffset[i]][x+xoffset[i]])&& + (image[x + xoffset[i] + (y+yoffset[i])*xdim] >= + this->GradientThreshold)) + { + // satisfied the first test, now check second + inVectors->GetTuple(x + xoffset[i] + + (y + yoffset[i])*xdim + zpos,vec2); + vtkMath::Normalize(vec2); + if ((vec1[0]*vec2[0] + vec1[1]*vec2[1]) >= phiThresh) + { + // pased phi - phi test does the forward neighbor + // pass the link test + if ((directions[i][0]*vec2[0]+directions[i][1]*vec2[1]) >= + linkThresh) + { + // check against the current best solution + error = (directions[i][0]*vec2[0]+directions[i][1]*vec2[1]) + + (directions[i][0]*vec1[0]+directions[i][1]*vec1[1]) + + (vec1[0]*vec2[0] + vec1[1]*vec2[1]); + if (error > bestError) + { + bestDirection = i; + bestError = error; + } + } + } + } + } + } + if (bestError > 0) + { + forward[y][x] = (bestDirection+1); + backward[y+yoffset[bestDirection]][x+xoffset[bestDirection]] + = ((bestDirection+4)%8)+1; + } + } + } + } + } + + + // now construct the chains + vec[2] = z; + for (y = 0; y < ydim; y++) + { + ypos = y*xdim; + for (x = 0; x < xdim; x++) + { + // do we have part of an edgel chain ? + // isolated edgels do not qualify + if (backward[y][x] > 0) + { + // trace back to the beginning + currX = x; + currY = y; + do + { + newX = currX + xoffset[backward[currY][currX] - 1]; + currY += yoffset[backward[currY][currX] - 1]; + currX = newX; + } + while ((currX != x || currY != y) && backward[currY][currX]); + + // now trace to the end and build the digital curve + length = 0; + start = outScalars->GetNumberOfTuples(); + newX = currX; + newY = currY; + do + { + currX = newX; + currY = newY; + outScalars->InsertNextTuple(&(image[currX + currY*xdim])); + inVectors->GetTuple(currX+currY*xdim+zpos,vec2); + vtkMath::Normalize(vec2); + outVectors->InsertNextTuple(vec2); + vec[0] = currX; + vec[1] = currY; + newPts->InsertNextPoint(vec); + length++; + + // if there is a next pixel select it + if (forward[currY][currX]) + { + newX = currX + xoffset[forward[currY][currX] - 1]; + newY = currY + yoffset[forward[currY][currX] - 1]; + } + // clear out this edgel now that were done with it + backward[newY][newX] = 0; + forward[currY][currX] = 0; + } + while ((currX != newX || currY != newY)); + + // build up the cell + newLines->InsertNextCell(length); + for (i = 0; i < length; i++) + { + newLines->InsertCellPoint(start); + start++; + } + } + } + } + + // free up the memory + for (i = 0; i < ydim; i++) + { + delete [] forward[i]; + delete [] backward[i]; + } + delete [] forward; + delete [] backward; +} + +int vtkLinkEdgels::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkLinkEdgels::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "GradientThreshold:" << this->GradientThreshold << "\n"; + os << indent << "LinkThreshold:" << this->LinkThreshold << "\n"; + os << indent << "PhiThreshold:" << this->PhiThreshold << "\n"; +} diff --git a/Graphics/vtkLinkEdgels.h b/Graphics/vtkLinkEdgels.h new file mode 100644 index 0000000..5b4d380 --- /dev/null +++ b/Graphics/vtkLinkEdgels.h @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLinkEdgels.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLinkEdgels - links edgels together to form digital curves. +// .SECTION Description +// vtkLinkEdgels links edgels into digital curves which are then stored +// as polylines. The algorithm works one pixel at a time only looking at +// its immediate neighbors. There is a GradientThreshold that can be set +// that eliminates any pixels with a smaller gradient value. This can +// be used as the lower threshold of a two value edgel thresholding. +// +// For the remaining edgels, links are first tried for the four +// connected neighbors. A successful neighbor will satisfy three +// tests. First both edgels must be above the gradient +// threshold. Second, the difference between the orientation between +// the two edgels (Alpha) and each edgels orientation (Phi) must be +// less than LinkThreshold. Third, the difference between the two +// edgels Phi values must be less than PhiThreshold. +// The most successful link is selected. The measure is simply the +// sum of the three angle differences (actually stored as the sum of +// the cosines). If none of the four connect neighbors succeeds, then +// the eight connect neighbors are examined using the same method. +// +// This filter requires gradient information so you will need to use +// a vtkImageGradient at some point prior to this filter. Typically +// a vtkNonMaximumSuppression filter is also used. vtkThresholdEdgels +// can be used to complete the two value edgel thresholding as used +// in a Canny edge detector. The vtkSubpixelPositionEdgels filter +// can also be used after this filter to adjust the edgel locations. + +// .SECTION see also +// vtkImageData vtkImageGradient vtkImageNonMaximumSuppression + +#ifndef __vtkLinkEdgels_h +#define __vtkLinkEdgels_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkDataArray; +class vtkDoubleArray; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkLinkEdgels : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkLinkEdgels,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct instance of vtkLinkEdgels with GradientThreshold set to + // 0.1, PhiThreshold set to 90 degrees and LinkThreshold set to 90 degrees. + static vtkLinkEdgels *New(); + + // Description: + // Set/Get the threshold for Phi vs. Alpha link thresholding. + vtkSetMacro(LinkThreshold,double); + vtkGetMacro(LinkThreshold,double); + + // Description: + // Set/get the threshold for Phi vs. Phi link thresholding. + vtkSetMacro(PhiThreshold,double); + vtkGetMacro(PhiThreshold,double); + + // Description: + // Set/Get the threshold for image gradient thresholding. + vtkSetMacro(GradientThreshold,double); + vtkGetMacro(GradientThreshold,double); + +protected: + vtkLinkEdgels(); + ~vtkLinkEdgels() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + void LinkEdgels(int xdim, int ydim,double *image, vtkDataArray *inVectors, + vtkCellArray *newLines, vtkPoints *newPts, + vtkDoubleArray *outScalars, vtkDoubleArray *outVectors, + int z); + double GradientThreshold; + double PhiThreshold; + double LinkThreshold; +private: + vtkLinkEdgels(const vtkLinkEdgels&); // Not implemented. + void operator=(const vtkLinkEdgels&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkLoopSubdivisionFilter.cxx b/Graphics/vtkLoopSubdivisionFilter.cxx new file mode 100644 index 0000000..482cb7b --- /dev/null +++ b/Graphics/vtkLoopSubdivisionFilter.cxx @@ -0,0 +1,369 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLoopSubdivisionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLoopSubdivisionFilter.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkEdgeTable.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkLoopSubdivisionFilter, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkLoopSubdivisionFilter); + +static double LoopWeights[4] = + {.375, .375, .125, .125}; + +void vtkLoopSubdivisionFilter::GenerateSubdivisionPoints (vtkPolyData *inputDS,vtkIntArray *edgeData, vtkPoints *outputPts, vtkPointData *outputPD) +{ + double *weights; + vtkIdType *pts = 0; + vtkIdType numPts, cellId, newId; + int edgeId; + vtkIdType npts; + vtkIdType p1, p2; + vtkCellArray *inputPolys=inputDS->GetPolys(); + vtkEdgeTable *edgeTable; + vtkIdList *cellIds = vtkIdList::New(); + vtkIdList *stencil = vtkIdList::New(); + vtkPoints *inputPts=inputDS->GetPoints(); + vtkPointData *inputPD=inputDS->GetPointData(); + + weights = new double[256]; + + // Create an edge table to keep track of which edges we've processed + edgeTable = vtkEdgeTable::New(); + edgeTable->InitEdgeInsertion(inputDS->GetNumberOfPoints()); + + // Generate even points. these are derived from the old points + numPts = inputDS->GetNumberOfPoints(); + for (vtkIdType ptId=0; ptId < numPts; ptId++) + { + this->GenerateEvenStencil (ptId, inputDS, stencil, weights); + this->InterpolatePosition (inputPts, outputPts, stencil, weights); + outputPD->InterpolatePoint (inputPD, ptId, stencil, weights); + } + + // Generate odd points. These will be inserted into the new dataset + for (cellId=0, inputPolys->InitTraversal(); + inputPolys->GetNextCell(npts, pts); cellId++) + { + if ( inputDS->GetCellType(cellId) != VTK_TRIANGLE ) + { + continue; + } + + // start with one edge + p1 = pts[2]; + p2 = pts[0]; + + for (edgeId=0; edgeId < 3; edgeId++) + { + // Do we need to create a point on this edge? + if (edgeTable->IsEdge (p1, p2) == -1) + { + edgeTable->InsertEdge (p1, p2); + inputDS->GetCellEdgeNeighbors (-1, p1, p2, cellIds); + if (cellIds->GetNumberOfIds() == 1) + { + // Compute new Position and PointData using the same subdivision scheme + stencil->SetNumberOfIds(2); + stencil->SetId(0,p1); + stencil->SetId(1,p2); + weights[0] = .5; weights[1] = .5; + } // boundary edge + else + { + this->GenerateOddStencil (p1, p2, + inputDS, stencil, weights); + } + newId = this->InterpolatePosition (inputPts, outputPts, + stencil, weights); + outputPD->InterpolatePoint (inputPD, newId, stencil, weights); + } + else // we have already created a point on this edge. find it + { + newId = this->FindEdge (inputDS, cellId, p1, p2, edgeData, cellIds); + } + edgeData->InsertComponent(cellId,edgeId,newId); + p1 = p2; + if (edgeId < 2) + { + p2 = pts[edgeId + 1]; + } + } // each interior edge + } // each cell + + // cleanup + delete [] weights; + edgeTable->Delete(); + stencil->Delete (); + cellIds->Delete(); +} + +void vtkLoopSubdivisionFilter::GenerateEvenStencil (vtkIdType p1, + vtkPolyData *polys, + vtkIdList *stencilIds, + double *weights) +{ + vtkIdList *cellIds = vtkIdList::New(); + vtkIdList *ptIds = vtkIdList::New(); + vtkCell *cell; + + int i, j; + int numCellsInLoop; + int startCell, nextCell; + vtkIdType p, p2; + vtkIdType bp1, bp2; + int K; + double beta, cosSQ; + + // Get the cells that use this point + polys->GetPointCells (p1, cellIds); + numCellsInLoop = cellIds->GetNumberOfIds(); + if (numCellsInLoop < 1) + { + vtkWarningMacro("numCellsInLoop < 1: " << numCellsInLoop); + stencilIds->Reset(); + return; + } + // Find an edge to start with that contains p1 + polys->GetCellPoints (cellIds->GetId(0), ptIds); + p2 = ptIds->GetId(0); + i = 1; + while (p1 == p2) + { + p2 = ptIds->GetId(i++); + } + polys->GetCellEdgeNeighbors (-1, p1, p2, cellIds); + + nextCell = cellIds->GetId(0); + bp2 = -1; + bp1 = p2; + if (cellIds->GetNumberOfIds() == 1) + { + startCell = -1; + } + else + { + startCell = cellIds->GetId(1); + } + + stencilIds->Reset(); + stencilIds->InsertNextId(p2); + + // walk around the loop counter-clockwise and get cells + for (j = 0; j < numCellsInLoop; j++) + { + cell = polys->GetCell(nextCell); + p = -1; + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p2) + { + break; + } + } + p2 = p; + stencilIds->InsertNextId (p2); + polys->GetCellEdgeNeighbors (nextCell, p1, p2, cellIds); + if (cellIds->GetNumberOfIds() != 1) + { + bp2 = p2; + j++; + break; + } + nextCell = cellIds->GetId(0); + } + + // now walk around the other way. this will only happen if there + // is a boundary cell left that we have not visited + nextCell = startCell; + p2 = bp1; + for (; j < numCellsInLoop && startCell != -1; j++) + { + cell = polys->GetCell(nextCell); + p = -1; + for (i = 0; i < 3; i++) + { + if ((p = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p2) + { + break; + } + } + p2 = p; + stencilIds->InsertNextId (p2); + polys->GetCellEdgeNeighbors (nextCell, p1, p2, cellIds); + if (cellIds->GetNumberOfIds() != 1) + { + bp1 = p2; + break; + } + nextCell = cellIds->GetId(0); + } + + if (bp2 != -1) // boundary edge + { + stencilIds->SetNumberOfIds(3); + stencilIds->SetId(0,bp2); + stencilIds->SetId(1,bp1); + stencilIds->SetId(2,p1); + weights[0] = .125; + weights[1] = .125; + weights[2] = .75; + } + else + { + K = stencilIds->GetNumberOfIds(); + // Remove last id. It's a duplicate of the first + K--; + if (K > 3) + { + // Generate weights +#define VTK_PI 3.14159265358979 + cosSQ = .375 + .25 * cos (2.0 * VTK_PI / (double) K); + cosSQ = cosSQ * cosSQ; + beta = (.625 - cosSQ) / (double) K; + } + else + { + beta = 3.0 / 16.0; + } + for (j = 0; j < K; j++) + { + weights[j] = beta; + } + weights[K] = 1.0 - K * beta; + stencilIds->SetId (K,p1); + } + cellIds->Delete(); + ptIds->Delete(); +} + +void vtkLoopSubdivisionFilter::GenerateOddStencil (vtkIdType p1, vtkIdType p2, + vtkPolyData *polys, + vtkIdList *stencilIds, + double *weights) +{ + vtkIdList *cellIds = vtkIdList::New(); + vtkCell *cell; + int i; + vtkIdType cell0, cell1; + vtkIdType p3=0, p4=0; + + polys->GetCellEdgeNeighbors (-1, p1, p2, cellIds); + cell0 = cellIds->GetId(0); + cell1 = cellIds->GetId(1); + + cell = polys->GetCell(cell0); + for (i = 0; i < 3; i++) + { + if ((p3 = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p2) + { + break; + } + } + cell = polys->GetCell(cell1); + for (i = 0; i < 3; i++) + { + if ((p4 = cell->GetPointId(i)) != p1 && cell->GetPointId(i) != p2) + { + break; + } + } + + stencilIds->SetNumberOfIds (4); + stencilIds->SetId(0, p1); + stencilIds->SetId(1, p2); + stencilIds->SetId(2, p3); + stencilIds->SetId(3, p4); + + for (i = 0; i < stencilIds->GetNumberOfIds (); i++) + { + weights[i] = LoopWeights[i]; + } + cellIds->Delete(); +} + +int vtkLoopSubdivisionFilter::RequestUpdateExtent( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int numPieces, ghostLevel; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if (!this->Superclass::RequestUpdateExtent(request, inputVector, + outputVector)) + { + return 0; + } + + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevel = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + if (numPieces > 1 && this->NumberOfSubdivisions > 0) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel + 1); + } + + return 1; +} + +int vtkLoopSubdivisionFilter::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkCellArray *polys = input->GetPolys(); + int hasTris = 0; + vtkIdType numPts = 0, *pts = 0; + + input->BuildLinks(); + + polys->InitTraversal(); + while (polys->GetNextCell(numPts, pts)) + { + if (numPts == 3) + { + if (input->IsTriangle(pts[0], pts[1], pts[2])) + { + hasTris = 1; + break; + } + } + } + + if (!hasTris) + { + vtkWarningMacro("vtkLoopSubdivisionFilter only operates on triangles, but this data set has no triangles to operate on.") + return 0; + } + + return this->Superclass::RequestData(request, inputVector, outputVector); +} diff --git a/Graphics/vtkLoopSubdivisionFilter.h b/Graphics/vtkLoopSubdivisionFilter.h new file mode 100644 index 0000000..fbc59e5 --- /dev/null +++ b/Graphics/vtkLoopSubdivisionFilter.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLoopSubdivisionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLoopSubdivisionFilter - generate a subdivision surface using the Loop Scheme +// .SECTION Description +// vtkLoopSubdivisionFilter is an approximating subdivision scheme that +// creates four new triangles for each triangle in the mesh. The user can +// specify the NumberOfSubdivisions. Loop's subdivision scheme is +// described in: Loop, C., "Smooth Subdivision surfaces based on +// triangles,", Masters Thesis, University of Utah, August 1987. +// For a nice summary of the technique see, Hoppe, H., et. al, +// "Piecewise Smooth Surface Reconstruction,:, Proceedings of Siggraph 94 +// (Orlando, Florida, July 24-29, 1994). In COmputer Graphics +// Proceedings, Annual COnference Series, 1994, ACM SIGGRAPH, +// pp. 295-302. +//

+// The filter only operates on triangles. Users should use the +// vtkTriangleFilter to triangulate meshes that contain polygons or +// triangle strips. +//

+// The filter approximates point data using the same scheme. New +// triangles create at a subdivision step will have the cell data of +// their parent cell. + +// .SECTION Thanks +// This work was supported by PHS Research Grant No. 1 P41 RR13218-01 +// from the National Center for Research Resources. + +// .SECTION See Also +// vtkApproximatingSubdivisionFilter + +#ifndef __vtkLoopSubdivisionFilter_h +#define __vtkLoopSubdivisionFilter_h + +#include "vtkApproximatingSubdivisionFilter.h" + +class vtkPolyData; +class vtkIntArray; +class vtkPoints; +class vtkIdList; + +class VTK_GRAPHICS_EXPORT vtkLoopSubdivisionFilter : public vtkApproximatingSubdivisionFilter +{ +public: + // Description: + // Construct object with NumberOfSubdivisions set to 1. + static vtkLoopSubdivisionFilter *New(); + vtkTypeRevisionMacro(vtkLoopSubdivisionFilter,vtkApproximatingSubdivisionFilter); + +protected: + vtkLoopSubdivisionFilter () {}; + ~vtkLoopSubdivisionFilter () {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void GenerateSubdivisionPoints (vtkPolyData *inputDS, vtkIntArray *edgeData, + vtkPoints *outputPts, + vtkPointData *outputPD); + void GenerateEvenStencil (vtkIdType p1, vtkPolyData *polys, + vtkIdList *stencilIds, double *weights); + void GenerateOddStencil (vtkIdType p1, vtkIdType p2, vtkPolyData *polys, + vtkIdList *stencilIds, double *weights); + + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkLoopSubdivisionFilter(const vtkLoopSubdivisionFilter&); // Not implemented. + void operator=(const vtkLoopSubdivisionFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkMarchingContourFilter.cxx b/Graphics/vtkMarchingContourFilter.cxx new file mode 100644 index 0000000..642a0c9 --- /dev/null +++ b/Graphics/vtkMarchingContourFilter.cxx @@ -0,0 +1,342 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingContourFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMarchingContourFilter.h" + +#include "vtkCell.h" +#include "vtkContourFilter.h" +#include "vtkContourValues.h" +#include "vtkImageMarchingCubes.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMarchingCubes.h" +#include "vtkMarchingSquares.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkScalarTree.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredPoints.h" + +#include + +vtkCxxRevisionMacro(vtkMarchingContourFilter, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkMarchingContourFilter); + +// Construct object with initial range (0,1) and single contour value +// of 0.0. +vtkMarchingContourFilter::vtkMarchingContourFilter() +{ + this->ContourValues = vtkContourValues::New(); + + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->Locator = NULL; + + this->UseScalarTree = 0; + this->ScalarTree = NULL; +} + +vtkMarchingContourFilter::~vtkMarchingContourFilter() +{ + this->ContourValues->Delete(); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( this->ScalarTree ) + { + this->ScalarTree->Delete(); + } +} + +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkMarchingContourFilter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if (this->ContourValues) + { + time = this->ContourValues->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if (this->Locator) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +// +// General contouring filter. Handles arbitrary input. +// +int vtkMarchingContourFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *inScalars; + vtkIdType numCells; + + vtkDebugMacro(<< "Executing marching contour filter"); + + numCells = input->GetNumberOfCells(); + inScalars = input->GetPointData()->GetScalars(); + if ( ! inScalars || numCells < 1 ) + { + vtkErrorMacro(<<"No data to contour"); + return 1; + } + + // If structured points, use more efficient algorithms + if ( (input->GetDataObjectType() == VTK_STRUCTURED_POINTS)) + { + if (inScalars->GetDataType() != VTK_BIT) + { + int dim = input->GetCell(0)->GetCellDimension(); + + if ( input->GetCell(0)->GetCellDimension() >= 2 ) + { + vtkDebugMacro(<< "Structured Points"); + this->StructuredPointsContour(dim, input, output); + return 1; + } + } + } + + if ( (input->GetDataObjectType() == VTK_IMAGE_DATA)) + { + if (inScalars->GetDataType() != VTK_BIT) + { + int dim = input->GetCell(0)->GetCellDimension(); + + if ( input->GetCell(0)->GetCellDimension() >= 2 ) + { + vtkDebugMacro(<< "Image"); + this->ImageContour(dim, input, output); + return 1; + } + } + } + + vtkDebugMacro(<< "Unoptimized"); + this->DataSetContour(input, output); + + return 1; +} + +void vtkMarchingContourFilter::StructuredPointsContour(int dim, + vtkDataSet *input, + vtkPolyData *thisOutput) +{ + vtkPolyData *output; + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + + if ( dim == 2 ) //marching squares + { + vtkMarchingSquares *msquares; + int i; + + msquares = vtkMarchingSquares::New(); + msquares->SetInput((vtkImageData *)input); + msquares->SetDebug(this->Debug); + msquares->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + msquares->SetValue(i,values[i]); + } + + msquares->Update(); + output = msquares->GetOutput(); + output->Register(this); + msquares->Delete(); + } + + else //marching cubes + { + vtkMarchingCubes *mcubes; + int i; + + mcubes = vtkMarchingCubes::New(); + mcubes->SetInput((vtkImageData *)input); + mcubes->SetComputeNormals (this->ComputeNormals); + mcubes->SetComputeGradients (this->ComputeGradients); + mcubes->SetComputeScalars (this->ComputeScalars); + mcubes->SetDebug(this->Debug); + mcubes->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + mcubes->SetValue(i,values[i]); + } + + mcubes->Update(); + output = mcubes->GetOutput(); + output->Register(this); + mcubes->Delete(); + } + + thisOutput->CopyStructure(output); + thisOutput->GetPointData()->ShallowCopy(output->GetPointData()); + output->UnRegister(this); +} + +void vtkMarchingContourFilter::DataSetContour(vtkDataSet *input, + vtkPolyData *output) +{ + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + + vtkContourFilter *contour = vtkContourFilter::New(); + contour->SetInput((vtkImageData *)input); + contour->SetComputeNormals (this->ComputeNormals); + contour->SetComputeGradients (this->ComputeGradients); + contour->SetComputeScalars (this->ComputeScalars); + contour->SetDebug(this->Debug); + contour->SetNumberOfContours(numContours); + for (int i=0; i < numContours; i++) + { + contour->SetValue(i,values[i]); + } + + contour->Update(); + output->ShallowCopy(contour->GetOutput()); + this->SetOutput(output); + contour->Delete(); +} + +void vtkMarchingContourFilter::ImageContour(int dim, vtkDataSet *input, + vtkPolyData *output) +{ + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + vtkPolyData *contourOutput; + + if ( dim == 2 ) //marching squares + { + vtkMarchingSquares *msquares; + int i; + + msquares = vtkMarchingSquares::New(); + msquares->SetInput((vtkImageData *)input); + msquares->SetDebug(this->Debug); + msquares->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + msquares->SetValue(i,values[i]); + } + + contourOutput = msquares->GetOutput(); + msquares->Update(); + output->ShallowCopy(contourOutput); + msquares->Delete(); + } + + else //image marching cubes + { + vtkImageMarchingCubes *mcubes; + int i; + + mcubes = vtkImageMarchingCubes::New(); + mcubes->SetInput((vtkImageData *)input); + mcubes->SetComputeNormals (this->ComputeNormals); + mcubes->SetComputeGradients (this->ComputeGradients); + mcubes->SetComputeScalars (this->ComputeScalars); + mcubes->SetDebug(this->Debug); + mcubes->SetNumberOfContours(numContours); + for (i=0; i < numContours; i++) + { + mcubes->SetValue(i,values[i]); + } + + contourOutput = mcubes->GetOutput(); + mcubes->Update(); + output->ShallowCopy(contourOutput); + mcubes->Delete(); + } +} + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkMarchingContourFilter::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkMarchingContourFilter::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +int vtkMarchingContourFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkMarchingContourFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Compute Gradients: " << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " << (this->ComputeScalars ? "On\n" : "Off\n"); + os << indent << "Use Scalar Tree: " << (this->UseScalarTree ? "On\n" : "Off\n"); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/Graphics/vtkMarchingContourFilter.h b/Graphics/vtkMarchingContourFilter.h new file mode 100644 index 0000000..f5caddd --- /dev/null +++ b/Graphics/vtkMarchingContourFilter.h @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingContourFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMarchingContourFilter - generate isosurfaces/isolines from scalar values +// .SECTION Description +// vtkMarchingContourFilter is a filter that takes as input any dataset and +// generates on output isosurfaces and/or isolines. The exact form +// of the output depends upon the dimensionality of the input data. +// Data consisting of 3D cells will generate isosurfaces, data +// consisting of 2D cells will generate isolines, and data with 1D +// or 0D cells will generate isopoints. Combinations of output type +// are possible if the input dimension is mixed. +// +// This filter will identify special dataset types (e.g., structured +// points) and use the appropriate specialized filter to process the +// data. For examples, if the input dataset type is a volume, this +// filter will create an internal vtkMarchingCubes instance and use +// it. This gives much better performance. +// +// To use this filter you must specify one or more contour values. +// You can either use the method SetValue() to specify each contour +// value, or use GenerateValues() to generate a series of evenly +// spaced contours. It is also possible to accelerate the operation of +// this filter (at the cost of extra memory) by using a +// vtkScalarTree. A scalar tree is used to quickly locate cells that +// contain a contour surface. This is especially effective if multiple +// contours are being extracted. If you want to use a scalar tree, +// invoke the method UseScalarTreeOn(). + +// .SECTION Caveats +// For unstructured data or structured grids, normals and gradients +// are not computed. This calculation will be implemented in the +// future. In the mean time, use vtkPolyDataNormals to compute the surface +// normals. + +// .SECTION See Also +// vtkMarchingCubes vtkSliceCubes vtkDividingCubes vtkMarchingSquares +// vtkImageMarchingCubes + +#ifndef __vtkMarchingContourFilter_h +#define __vtkMarchingContourFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for direct access to ContourValues + +class vtkPointLocator; +class vtkScalarTree; + +class VTK_GRAPHICS_EXPORT vtkMarchingContourFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkMarchingContourFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with initial range (0,1) and single contour value + // of 0.0. + static vtkMarchingContourFilter *New(); + + // Description: + // Methods to set / get contour values. + void SetValue(int i, double value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Description: + // Modified GetMTime Because we delegate to vtkContourValues + unsigned long GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Enable the use of a scalar tree to accelerate contour extraction. + vtkSetMacro(UseScalarTree,int); + vtkGetMacro(UseScalarTree,int); + vtkBooleanMacro(UseScalarTree,int); + + // Description: + // Set / get a spatial locator for merging points. By default, + // an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is + // specified. The locator is used to merge coincident points. + void CreateDefaultLocator(); + +protected: + vtkMarchingContourFilter(); + ~vtkMarchingContourFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkContourValues *ContourValues; + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkPointLocator *Locator; + int UseScalarTree; + vtkScalarTree *ScalarTree; + + //special contouring for structured points + void StructuredPointsContour(int dim, vtkDataSet *input, vtkPolyData *output); + //special contouring for image data + void ImageContour(int dim, vtkDataSet *input, vtkPolyData *output); + //default if not structured data + void DataSetContour(vtkDataSet *input, vtkPolyData *output); +private: + vtkMarchingContourFilter(const vtkMarchingContourFilter&); // Not implemented. + void operator=(const vtkMarchingContourFilter&); // Not implemented. +}; + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value); +} + +// Description: +// Get the ith contour value. +inline double vtkMarchingContourFilter::GetValue(int i) +{ + return this->ContourValues->GetValue(i); +} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +inline double *vtkMarchingContourFilter::GetValues() +{ + return this->ContourValues->GetValues(); +} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +inline void vtkMarchingContourFilter::GetValues(double *contourValues) +{ + this->ContourValues->GetValues(contourValues); +} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +inline void vtkMarchingContourFilter::SetNumberOfContours(int number) +{ + this->ContourValues->SetNumberOfContours(number); +} + +// Description: +// Get the number of contours in the list of contour values. +inline int vtkMarchingContourFilter::GetNumberOfContours() +{ + return this->ContourValues->GetNumberOfContours(); +} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkMarchingContourFilter::GenerateValues(int numContours, + double range[2]) +{ + this->ContourValues->GenerateValues(numContours, range); +} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkMarchingContourFilter::GenerateValues(int numContours, + double rangeStart, + double rangeEnd) +{ + this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd); +} + +#endif diff --git a/Graphics/vtkMarchingCubes.cxx b/Graphics/vtkMarchingCubes.cxx new file mode 100644 index 0000000..3634b81 --- /dev/null +++ b/Graphics/vtkMarchingCubes.cxx @@ -0,0 +1,607 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingCubes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + + +=========================================================================*/ +#include "vtkMarchingCubes.h" + +#include "vtkCellArray.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMarchingCubesCases.h" +#include "vtkMath.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkShortArray.h" +#include "vtkStructuredPoints.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkMarchingCubes, "$Revision: 1.1.6.1 $"); +vtkStandardNewMacro(vtkMarchingCubes); + +// Description: +// Construct object with initial range (0,1) and single contour value +// of 0.0. ComputeNormal is on, ComputeGradients is off and ComputeScalars is on. +vtkMarchingCubes::vtkMarchingCubes() +{ + this->ContourValues = vtkContourValues::New(); + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + this->Locator = NULL; +} + +vtkMarchingCubes::~vtkMarchingCubes() +{ + this->ContourValues->Delete(); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +// Description: +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkMarchingCubes::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long mTime2=this->ContourValues->GetMTime(); + + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + if (this->Locator) + { + mTime2=this->Locator->GetMTime(); + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + } + + return mTime; +} + +// Calculate the gradient using central difference. +// NOTE: We calculate the negative of the gradient for efficiency +template +void vtkMarchingCubesComputePointGradient(int i, int j, int k, T *s, int dims[3], + int sliceSize, double spacing[3], double n[3]) +{ + double sp, sm; + + // x-direction + if ( i == 0 ) + { + sp = s[i+1 + j*dims[0] + k*sliceSize]; + sm = s[i + j*dims[0] + k*sliceSize]; + n[0] = (sm - sp) / spacing[0]; + } + else if ( i == (dims[0]-1) ) + { + sp = s[i + j*dims[0] + k*sliceSize]; + sm = s[i-1 + j*dims[0] + k*sliceSize]; + n[0] = (sm - sp) / spacing[0]; + } + else + { + sp = s[i+1 + j*dims[0] + k*sliceSize]; + sm = s[i-1 + j*dims[0] + k*sliceSize]; + n[0] = 0.5 * (sm - sp) / spacing[0]; + } + + // y-direction + if ( j == 0 ) + { + sp = s[i + (j+1)*dims[0] + k*sliceSize]; + sm = s[i + j*dims[0] + k*sliceSize]; + n[1] = (sm - sp) / spacing[1]; + } + else if ( j == (dims[1]-1) ) + { + sp = s[i + j*dims[0] + k*sliceSize]; + sm = s[i + (j-1)*dims[0] + k*sliceSize]; + n[1] = (sm - sp) / spacing[1]; + } + else + { + sp = s[i + (j+1)*dims[0] + k*sliceSize]; + sm = s[i + (j-1)*dims[0] + k*sliceSize]; + n[1] = 0.5 * (sm - sp) / spacing[1]; + } + + // z-direction + if ( k == 0 ) + { + sp = s[i + j*dims[0] + (k+1)*sliceSize]; + sm = s[i + j*dims[0] + k*sliceSize]; + n[2] = (sm - sp) / spacing[2]; + } + else if ( k == (dims[2]-1) ) + { + sp = s[i + j*dims[0] + k*sliceSize]; + sm = s[i + j*dims[0] + (k-1)*sliceSize]; + n[2] = (sm - sp) / spacing[2]; + } + else + { + sp = s[i + j*dims[0] + (k+1)*sliceSize]; + sm = s[i + j*dims[0] + (k-1)*sliceSize]; + n[2] = 0.5 * (sm - sp) / spacing[2]; + } +} + +// +// Contouring filter specialized for volumes and "short int" data values. +// +template +void vtkMarchingCubesComputeGradient(vtkMarchingCubes *self,T *scalars, int dims[3], + double origin[3], double spacing[3], + vtkPointLocator *locator, + vtkDataArray *newScalars, + vtkDataArray *newGradients, + vtkDataArray *newNormals, + vtkCellArray *newPolys, double *values, + int numValues) +{ + double s[8], value; + int i, j, k, sliceSize; + static int CASE_MASK[8] = {1,2,4,8,16,32,64,128}; + vtkMarchingCubesTriangleCases *triCase, *triCases; + EDGE_LIST *edge; + int contNum, jOffset, kOffset, idx, ii, index, *vert; + vtkIdType ptIds[3]; + int ComputeNormals = newNormals != NULL; + int ComputeGradients = newGradients != NULL; + int ComputeScalars = newScalars != NULL; + int NeedGradients; + int extent[6]; + double t, *x1, *x2, x[3], *n1, *n2, n[3], min, max; + double pts[8][3], gradients[8][3], xp, yp, zp; + static int edges[12][2] = { {0,1}, {1,2}, {3,2}, {0,3}, + {4,5}, {5,6}, {7,6}, {4,7}, + {0,4}, {1,5}, {3,7}, {2,6}}; + + vtkInformation *inInfo = self->GetExecutive()->GetInputInformation(0, 0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + + triCases = vtkMarchingCubesTriangleCases::GetCases(); + +// +// Get min/max contour values +// + if ( numValues < 1 ) + { + return; + } + for ( min=max=values[0], i=1; i < numValues; i++) + { + if ( values[i] < min ) + { + min = values[i]; + } + if ( values[i] > max ) + { + max = values[i]; + } + } +// +// Traverse all voxel cells, generating triangles and point gradients +// using marching cubes algorithm. +// + sliceSize = dims[0] * dims[1]; + for ( k=0; k < (dims[2]-1); k++) + { + self->UpdateProgress ((double) k / ((double) dims[2] - 1)); + if (self->GetAbortExecute()) + { + break; + } + kOffset = k*sliceSize; + pts[0][2] = origin[2] + (k+extent[4]) * spacing[2]; + zp = pts[0][2] + spacing[2]; + for ( j=0; j < (dims[1]-1); j++) + { + jOffset = j*dims[0]; + pts[0][1] = origin[1] + (j+extent[2]) * spacing[1]; + yp = pts[0][1] + spacing[1]; + for ( i=0; i < (dims[0]-1); i++) + { + //get scalar values + idx = i + jOffset + kOffset; + s[0] = scalars[idx]; + s[1] = scalars[idx+1]; + s[2] = scalars[idx+1 + dims[0]]; + s[3] = scalars[idx + dims[0]]; + s[4] = scalars[idx + sliceSize]; + s[5] = scalars[idx+1 + sliceSize]; + s[6] = scalars[idx+1 + dims[0] + sliceSize]; + s[7] = scalars[idx + dims[0] + sliceSize]; + + if ( (s[0] < min && s[1] < min && s[2] < min && s[3] < min && + s[4] < min && s[5] < min && s[6] < min && s[7] < min) || + (s[0] > max && s[1] > max && s[2] > max && s[3] > max && + s[4] > max && s[5] > max && s[6] > max && s[7] > max) ) + { + continue; // no contours possible + } + + //create voxel points + pts[0][0] = origin[0] + (i+extent[0]) * spacing[0]; + xp = pts[0][0] + spacing[0]; + + pts[1][0] = xp; + pts[1][1] = pts[0][1]; + pts[1][2] = pts[0][2]; + + pts[2][0] = xp; + pts[2][1] = yp; + pts[2][2] = pts[0][2]; + + pts[3][0] = pts[0][0]; + pts[3][1] = yp; + pts[3][2] = pts[0][2]; + + pts[4][0] = pts[0][0]; + pts[4][1] = pts[0][1]; + pts[4][2] = zp; + + pts[5][0] = xp; + pts[5][1] = pts[0][1]; + pts[5][2] = zp; + + pts[6][0] = xp; + pts[6][1] = yp; + pts[6][2] = zp; + + pts[7][0] = pts[0][0]; + pts[7][1] = yp; + pts[7][2] = zp; + + NeedGradients = ComputeGradients || ComputeNormals; + + //create gradients if needed + if (NeedGradients) + { + vtkMarchingCubesComputePointGradient(i,j,k, scalars, dims, sliceSize, spacing, gradients[0]); + vtkMarchingCubesComputePointGradient(i+1,j,k, scalars, dims, sliceSize, spacing, gradients[1]); + vtkMarchingCubesComputePointGradient(i+1,j+1,k, scalars, dims, sliceSize, spacing, gradients[2]); + vtkMarchingCubesComputePointGradient(i,j+1,k, scalars, dims, sliceSize, spacing, gradients[3]); + vtkMarchingCubesComputePointGradient(i,j,k+1, scalars, dims, sliceSize, spacing, gradients[4]); + vtkMarchingCubesComputePointGradient(i+1,j,k+1, scalars, dims, sliceSize, spacing, gradients[5]); + vtkMarchingCubesComputePointGradient(i+1,j+1,k+1, scalars, dims, sliceSize, spacing, gradients[6]); + vtkMarchingCubesComputePointGradient(i,j+1,k+1, scalars, dims, sliceSize, spacing, gradients[7]); + } + for (contNum=0; contNum < numValues; contNum++) + { + value = values[contNum]; + // Build the case table + for ( ii=0, index = 0; ii < 8; ii++) + { + if ( s[ii] >= value ) + { + index |= CASE_MASK[ii]; + } + } + if ( index == 0 || index == 255 ) //no surface + { + continue; + } + + triCase = triCases+ index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (ii=0; ii<3; ii++) //insert triangle + { + vert = edges[edge[ii]]; + t = (value - s[vert[0]]) / (s[vert[1]] - s[vert[0]]); + x1 = pts[vert[0]]; + x2 = pts[vert[1]]; + x[0] = x1[0] + t * (x2[0] - x1[0]); + x[1] = x1[1] + t * (x2[1] - x1[1]); + x[2] = x1[2] + t * (x2[2] - x1[2]); + + // check for a new point + if ( locator->InsertUniquePoint(x, ptIds[ii]) ) + { + if (NeedGradients) + { + n1 = gradients[vert[0]]; + n2 = gradients[vert[1]]; + n[0] = n1[0] + t * (n2[0] - n1[0]); + n[1] = n1[1] + t * (n2[1] - n1[1]); + n[2] = n1[2] + t * (n2[2] - n1[2]); + } + if (ComputeScalars) + { + newScalars->InsertTuple(ptIds[ii],&value); + } + if (ComputeGradients) + { + newGradients->InsertTuple(ptIds[ii],n); + } + if (ComputeNormals) + { + vtkMath::Normalize(n); + newNormals->InsertTuple(ptIds[ii],n); + } + } + } + // check for degenerate triangle + if ( ptIds[0] != ptIds[1] && + ptIds[0] != ptIds[2] && + ptIds[1] != ptIds[2] ) + { + newPolys->InsertNextCell(3,ptIds); + } + }//for each triangle + }//for all contours + }//for i + }//for j + }//for k +} + +// +// Contouring filter specialized for volumes and "short int" data values. +// +int vtkMarchingCubes::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *newPts; + vtkCellArray *newPolys; + vtkFloatArray *newScalars; + vtkFloatArray *newNormals; + vtkFloatArray *newGradients; + vtkPointData *pd; + vtkDataArray *inScalars; + int dims[3], extent[6]; + int estimatedSize; + double spacing[3], origin[3]; + double bounds[6]; + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + + vtkDebugMacro(<< "Executing marching cubes"); + +// +// Initialize and check input +// + pd=input->GetPointData(); + if (pd ==NULL) + { + vtkErrorMacro(<<"PointData is NULL"); + return 1; + } + inScalars=pd->GetScalars(); + if ( inScalars == NULL ) + { + vtkErrorMacro(<<"Scalars must be defined for contouring"); + return 1; + } + + if ( input->GetDataDimension() != 3 ) + { + vtkErrorMacro(<<"Cannot contour data of dimension != 3"); + return 1; + } + input->GetDimensions(dims); + input->GetOrigin(origin); + input->GetSpacing(spacing); + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + + // estimate the number of points from the volume dimensions + estimatedSize = (int) pow ((double) (dims[0] * dims[1] * dims[2]), .75); + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + vtkDebugMacro(<< "Estimated allocation size is " << estimatedSize); + newPts = vtkPoints::New(); newPts->Allocate(estimatedSize,estimatedSize/2); + // compute bounds for merging points + for ( int i=0; i<3; i++) + { + bounds[2*i] = origin[i] + extent[2*i] * spacing[i]; + bounds[2*i+1] = origin[i] + extent[2*i+1] * spacing[i]; + } + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, bounds, estimatedSize); + + if (this->ComputeNormals) + { + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*estimatedSize,3*estimatedSize/2); + } + else + { + newNormals = NULL; + } + + if (this->ComputeGradients) + { + newGradients = vtkFloatArray::New(); + newGradients->SetNumberOfComponents(3); + newGradients->Allocate(3*estimatedSize,3*estimatedSize/2); + } + else + { + newGradients = NULL; + } + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(estimatedSize,3)); + + if (this->ComputeScalars) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(estimatedSize,estimatedSize/2); + } + else + { + newScalars = NULL; + } + + if (inScalars->GetNumberOfComponents() == 1 ) + { + void* scalars = inScalars->GetVoidPointer(0); + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + vtkMarchingCubesComputeGradient(this, static_cast(scalars), + dims,origin,spacing,this->Locator, + newScalars,newGradients, + newNormals,newPolys,values, + numContours) + ); + } //switch + } + + else //multiple components - have to convert + { + int dataSize = dims[0] * dims[1] * dims[2]; + vtkDoubleArray *image=vtkDoubleArray::New(); + image->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + image->SetNumberOfTuples(image->GetNumberOfComponents()*dataSize); + inScalars->GetTuples(0,dataSize,image); + + double *scalars = image->GetPointer(0); + vtkMarchingCubesComputeGradient(this,scalars,dims,origin,spacing,this->Locator, + newScalars,newGradients, + newNormals,newPolys,values,numContours); + image->Delete(); + } + + vtkDebugMacro(<<"Created: " + << newPts->GetNumberOfPoints() << " points, " + << newPolys->GetNumberOfCells() << " triangles"); + // + // Update ourselves. Because we don't know up front how many triangles + // we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + if (newScalars) + { + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + if (newGradients) + { + output->GetPointData()->SetVectors(newGradients); + newGradients->Delete(); + } + if (newNormals) + { + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + } + output->Squeeze(); + if (this->Locator) + { + this->Locator->Initialize(); //free storage + } + + return 1; +} + +// Description: +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkMarchingCubes::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + if (locator) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +void vtkMarchingCubes::CreateDefaultLocator() +{ + if ( this->Locator == NULL) + { + this->Locator = vtkMergePoints::New(); + } +} + +int vtkMarchingCubes::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkMarchingCubes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Gradients: " << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " << (this->ComputeScalars ? "On\n" : "Off\n"); + + if ( this->Locator ) + { + os << indent << "Locator:" << this->Locator << "\n"; + this->Locator->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/Graphics/vtkMarchingCubes.h b/Graphics/vtkMarchingCubes.h new file mode 100644 index 0000000..46ebed3 --- /dev/null +++ b/Graphics/vtkMarchingCubes.h @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingCubes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMarchingCubes - generate isosurface(s) from volume +// .SECTION Description +// vtkMarchingCubes is a filter that takes as input a volume (e.g., 3D +// structured point set) and generates on output one or more isosurfaces. +// One or more contour values must be specified to generate the isosurfaces. +// Alternatively, you can specify a min/max scalar range and the number of +// contours to generate a series of evenly spaced contour values. + +// .SECTION Caveats +// This filter is specialized to volumes. If you are interested in +// contouring other types of data, use the general vtkContourFilter. If you +// want to contour an image (i.e., a volume slice), use vtkMarchingSquares. +// .SECTION See Also +// vtkContourFilter vtkSliceCubes vtkMarchingSquares vtkDividingCubes + +#ifndef __vtkMarchingCubes_h +#define __vtkMarchingCubes_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for direct access to ContourValues + +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkMarchingCubes : public vtkPolyDataAlgorithm +{ +public: + static vtkMarchingCubes *New(); + vtkTypeRevisionMacro(vtkMarchingCubes,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Methods to set contour values + void SetValue(int i, double value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Because we delegate to vtkContourValues + unsigned long int GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Overide the default locator. Useful for changing the number of + // bins for performance or specifying a more aggressive locator. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is + // specified. The locator is used to merge coincident points. + void CreateDefaultLocator(); + +protected: + vtkMarchingCubes(); + ~vtkMarchingCubes(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkContourValues *ContourValues; + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkPointLocator *Locator; +private: + vtkMarchingCubes(const vtkMarchingCubes&); // Not implemented. + void operator=(const vtkMarchingCubes&); // Not implemented. +}; + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value);} + +// Description: +// Get the ith contour value. +inline double vtkMarchingCubes::GetValue(int i) +{return this->ContourValues->GetValue(i);} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +inline double *vtkMarchingCubes::GetValues() +{return this->ContourValues->GetValues();} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +inline void vtkMarchingCubes::GetValues(double *contourValues) +{this->ContourValues->GetValues(contourValues);} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +inline void vtkMarchingCubes::SetNumberOfContours(int number) +{this->ContourValues->SetNumberOfContours(number);} + +// Description: +// Get the number of contours in the list of contour values. +inline int vtkMarchingCubes::GetNumberOfContours() +{return this->ContourValues->GetNumberOfContours();} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkMarchingCubes::GenerateValues(int numContours, double range[2]) +{this->ContourValues->GenerateValues(numContours, range);} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkMarchingCubes::GenerateValues(int numContours, double + rangeStart, double rangeEnd) +{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + +#endif diff --git a/Graphics/vtkMarchingSquares.cxx b/Graphics/vtkMarchingSquares.cxx new file mode 100644 index 0000000..173f21a --- /dev/null +++ b/Graphics/vtkMarchingSquares.cxx @@ -0,0 +1,498 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingSquares.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMarchingSquares.h" + +#include "vtkCellArray.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMarchingSquaresCases.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkShortArray.h" +#include "vtkStructuredPoints.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include + +vtkCxxRevisionMacro(vtkMarchingSquares, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkMarchingSquares); + +// Description: +// Construct object with initial scalar range (0,1) and single contour value +// of 0.0. The ImageRange are set to extract the first k-plane. +vtkMarchingSquares::vtkMarchingSquares() +{ + this->ContourValues = vtkContourValues::New(); + + this->ImageRange[0] = 0; this->ImageRange[1] = VTK_LARGE_INTEGER; + this->ImageRange[2] = 0; this->ImageRange[3] = VTK_LARGE_INTEGER; + this->ImageRange[4] = 0; this->ImageRange[5] = 0; + + this->Locator = NULL; +} + +vtkMarchingSquares::~vtkMarchingSquares() +{ + this->ContourValues->Delete(); + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +void vtkMarchingSquares::SetImageRange(int imin, int imax, int jmin, int jmax, + int kmin, int kmax) +{ + int dim[6]; + + dim[0] = imin; + dim[1] = imax; + dim[2] = jmin; + dim[3] = jmax; + dim[4] = kmin; + dim[5] = kmax; + + this->SetImageRange(dim); +} + +// Description: +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkMarchingSquares::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long mTime2=this->ContourValues->GetMTime(); + + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + if (this->Locator) + { + mTime2=this->Locator->GetMTime(); + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + } + + return mTime; +} + +// +// Contouring filter specialized for images +// +template +void vtkContourImage(T *scalars, vtkDataArray *newScalars, int roi[6], int dir[3], + int start[2], int end[2], int offset[3], double ar[3], + double origin[3], double *values, int numValues, + vtkPointLocator *p, vtkCellArray *lines) +{ + int i, j; + vtkIdType ptIds[2]; + double t, *x1, *x2, x[3], xp, yp; + double pts[4][3], min, max; + int contNum, jOffset, idx, ii, jj, index, *vert; + static int CASE_MASK[4] = {1,2,8,4}; + vtkMarchingSquaresLineCases *lineCase, *lineCases; + static int edges[4][2] = { {0,1}, {1,3}, {2,3}, {0,2} }; + EDGE_LIST *edge; + double value, s[4]; + + lineCases = vtkMarchingSquaresLineCases::GetCases(); +// +// Get min/max contour values +// + if ( numValues < 1 ) + { + return; + } + for ( min=max=values[0], i=1; i < numValues; i++) + { + if ( values[i] < min ) + { + min = values[i]; + } + if ( values[i] > max ) + { + max = values[i]; + } + } + + //assign coordinate value to non-varying coordinate direction + x[dir[2]] = origin[dir[2]] + roi[dir[2]*2]*ar[dir[2]]; + + // Traverse all pixel cells, generating line segements using marching squares. + for ( j=roi[start[1]]; j < roi[end[1]]; j++ ) + { + + jOffset = j * offset[1]; + pts[0][dir[1]] = origin[dir[1]] + j*ar[dir[1]]; + yp = origin[dir[1]] + (j+1)*ar[dir[1]]; + + for ( i=roi[start[0]]; i < roi[end[0]]; i++) + { + //get scalar values + idx = i * offset[0] + jOffset + offset[2]; + s[0] = scalars[idx]; + s[1] = scalars[idx+offset[0]]; + s[2] = scalars[idx + offset[1]]; + s[3] = scalars[idx+offset[0] + offset[1]]; + + if ( (s[0] < min && s[1] < min && s[2] < min && s[3] < min) || + (s[0] > max && s[1] > max && s[2] > max && s[3] > max) ) + { + continue; // no contours possible + } + + //create pixel points + pts[0][dir[0]] = origin[dir[0]] + i*ar[dir[0]]; + xp = origin[dir[0]] + (i+1)*ar[dir[0]]; + + pts[1][dir[0]] = xp; + pts[1][dir[1]] = pts[0][dir[1]]; + + pts[2][dir[0]] = pts[0][dir[0]]; + pts[2][dir[1]] = yp; + + pts[3][dir[0]] = xp; + pts[3][dir[1]] = yp; + + // Loop over contours in this pixel + for (contNum=0; contNum < numValues; contNum++) + { + value = values[contNum]; + + // Build the case table + for ( ii=0, index = 0; ii < 4; ii++) + { + if ( s[ii] >= value ) + { + index |= CASE_MASK[ii]; + } + } + if ( index == 0 || index == 15 ) + { + continue; //no lines + } + + lineCase = lineCases + index; + edge = lineCase->edges; + + for ( ; edge[0] > -1; edge += 2 ) + { + for (ii=0; ii<2; ii++) //insert line + { + vert = edges[edge[ii]]; + t = (value - s[vert[0]]) / (s[vert[1]] - s[vert[0]]); + x1 = pts[vert[0]]; + x2 = pts[vert[1]]; + for (jj=0; jj<2; jj++) //only need to interpolate two values + { + x[dir[jj]] = x1[dir[jj]] + t * (x2[dir[jj]] - x1[dir[jj]]); + } + if ( p->InsertUniquePoint(x, ptIds[ii]) ) + { + newScalars->InsertComponent(ptIds[ii],0,value); + } + } + + if ( ptIds[0] != ptIds[1] ) //check for degenerate line + { + lines->InsertNextCell(2,ptIds); + } + + }//for each line + }//for all contours + }//for i + }//for j +} + +// +// Contouring filter specialized for images (or slices from images) +// +int vtkMarchingSquares::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd; + vtkPoints *newPts; + vtkCellArray *newLines; + vtkDataArray *inScalars; + vtkDataArray *newScalars = NULL; + int i, dims[3], roi[6], dataSize, dim, plane=0; + int *ext; + double origin[3], ar[3]; + int start[2], end[2], offset[3], dir[3], estimatedSize; + int numContours=this->ContourValues->GetNumberOfContours(); + double *values=this->ContourValues->GetValues(); + + vtkDebugMacro(<< "Executing marching squares"); +// +// Initialize and check input +// + pd=input->GetPointData(); + if (pd ==NULL) + { + vtkErrorMacro(<<"PointData is NULL"); + return 1; + } + inScalars=pd->GetScalars(); + if ( inScalars == NULL ) + { + vtkErrorMacro(<<"Scalars must be defined for contouring"); + return 1; + } +// +// Check dimensionality of data and get appropriate form +// + input->GetDimensions(dims); + ext = input->GetExtent(); + input->GetOrigin(origin); + input->GetSpacing(ar); + dataSize = dims[0] * dims[1] * dims[2]; + + if ( input->GetDataDimension() != 2 ) + { + for (i=0; i < 6; i++) + { + roi[i] = this->ImageRange[i]; + } + } + else + { + input->GetExtent(roi); + } + + // check the final region of interest to make sure its acceptable + for ( dim=0, i=0; i < 3; i++ ) + { + if ( roi[2*i+1] > ext[2*i+1] ) + { + roi[2*i+1] = ext[2*i+1]; + } + else if ( roi[2*i+1] < ext[2*i] ) + { + roi[2*i+1] = ext[2*i]; + } + + if ( roi[2*i] > roi[2*i+1] ) + { + roi[2*i] = roi[2*i+1]; + } + else if ( roi[2*i] < ext[2*i] ) + { + roi[2*i] = ext[2*i]; + } + + if ( (roi[2*i+1]-roi[2*i]) > 0 ) + { + dim++; + } + else + { + plane = i; + } + } + + if ( dim != 2 ) + { + vtkErrorMacro(<<"Marching squares requires 2D data"); + return 1; + } +// +// Setup indices and offsets (since can have x-y or z-plane) +// + if ( plane == 0 ) //x-plane + { + start[0] = 2; end[0] = 3; + start[1] = 4; end[1] = 5; + offset[0] = dims[0]; + offset[1] = dims[0]*dims[1]; + offset[2] = (roi[0]-ext[0]); + dir[0] = 1; dir[1] = 2; dir[2] = 0; + } + else if ( plane == 1 ) //y-plane + { + start[0] = 0; end[0] = 1; + start[1] = 4; end[1] = 5; + offset[0] = 1; + offset[1] = dims[0]*dims[1]; + offset[2] = (roi[2]-ext[2])*dims[0]; + dir[0] = 0; dir[1] = 2; dir[2] = 1; + } + else //z-plane + { + start[0] = 0; end[0] = 1; + start[1] = 2; end[1] = 3; + offset[0] = 1; + offset[1] = dims[0]; + offset[2] = (roi[4]-ext[4])*dims[0]*dims[1]; + dir[0] = 0; dir[1] = 1; dir[2] = 2; + } +// +// Allocate necessary objects +// + estimatedSize = (int) (numContours * sqrt((double)dims[0]*dims[1])); + estimatedSize = estimatedSize / 1024 * 1024; //multiple of 1024 + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(estimatedSize,2)); + + // locator used to merge potentially duplicate points + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, input->GetBounds()); + // + // Check data type and execute appropriate function + // + if (inScalars->GetNumberOfComponents() == 1 ) + { + void* scalars = inScalars->GetVoidPointer(0); + newScalars = inScalars->NewInstance(); + newScalars->Allocate(5000, 25000); + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + vtkContourImage(static_cast(scalars),newScalars, + roi,dir,start,end,offset,ar,origin, + values,numContours,this->Locator,newLines) + ); + }//switch + } + + else //multiple components - have to convert + { + vtkDoubleArray *image = vtkDoubleArray::New(); + image->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + image->SetNumberOfTuples(dataSize); + inScalars->GetTuples(0,dataSize,image); + newScalars = vtkFloatArray::New(); + newScalars->Allocate(5000,25000); + double *scalars = image->GetPointer(0); + vtkContourImage(scalars,newScalars,roi,dir,start,end,offset,ar,origin, + values,numContours,this->Locator,newLines); + image->Delete(); + } + + vtkDebugMacro(<<"Created: " + << newPts->GetNumberOfPoints() << " points, " + << newLines->GetNumberOfCells() << " lines"); + // + // Update ourselves. Because we don't know up front how many lines + // we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + + this->Locator->Initialize(); + output->Squeeze(); + + return 1; +} + +// Description: +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkMarchingSquares::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator) + { + return; + } + + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + + if ( locator ) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +void vtkMarchingSquares::CreateDefaultLocator() +{ + if ( this->Locator == NULL) + { + this->Locator = vtkMergePoints::New(); + } +} + +int vtkMarchingSquares::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkMarchingSquares::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Image Range: ( " + << this->ImageRange[0] << ", " + << this->ImageRange[1] << ", " + << this->ImageRange[2] << ", " + << this->ImageRange[3] << ", " + << this->ImageRange[4] << ", " + << this->ImageRange[5] << " )\n"; + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/Graphics/vtkMarchingSquares.h b/Graphics/vtkMarchingSquares.h new file mode 100644 index 0000000..6814b38 --- /dev/null +++ b/Graphics/vtkMarchingSquares.h @@ -0,0 +1,151 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMarchingSquares.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMarchingSquares - generate isoline(s) from structured points set +// .SECTION Description +// vtkMarchingSquares is a filter that takes as input a structured points set +// and generates on output one or more isolines. One or more contour values +// must be specified to generate the isolines. Alternatively, you can specify +// a min/max scalar range and the number of contours to generate a series of +// evenly spaced contour values. +// +// To generate contour lines the input data must be of topological dimension 2 +// (i.e., an image). If not, you can use the ImageRange ivar to select an +// image plane from an input volume. This avoids having to extract a plane first +// (using vtkExtractSubVolume). The filter deals with this by first +// trying to use the input data directly, and if not a 2D image, then uses the +// ImageRange ivar to reduce it to an image. + +// .SECTION Caveats +// This filter is specialized to images. If you are interested in +// contouring other types of data, use the general vtkContourFilter. +// .SECTION See Also +// vtkContourFilter vtkMarchingCubes vtkSliceCubes vtkDividingCubes + +#ifndef __vtkMarchingSquares_h +#define __vtkMarchingSquares_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Passes calls to vtkContourValues + +class vtkImageData; +class vtkPointLocator; + +class VTK_GRAPHICS_EXPORT vtkMarchingSquares : public vtkPolyDataAlgorithm +{ +public: + static vtkMarchingSquares *New(); + vtkTypeRevisionMacro(vtkMarchingSquares,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the i-j-k index range which define a plane on which to generate + // contour lines. Using this ivar it is possible to input a 3D volume + // directly and then generate contour lines on one of the i-j-k planes, or + // a portion of a plane. + vtkSetVectorMacro(ImageRange,int,6); + vtkGetVectorMacro(ImageRange,int,6); + void SetImageRange(int imin, int imax, int jmin, int jmax, + int kmin, int kmax); + + // Description: + // Methods to set contour values + void SetValue(int i, double value); + double GetValue(int i); + double *GetValues(); + void GetValues(double *contourValues); + void SetNumberOfContours(int number); + int GetNumberOfContours(); + void GenerateValues(int numContours, double range[2]); + void GenerateValues(int numContours, double rangeStart, double rangeEnd); + + // Description: + // Because we delegate to vtkContourValues + unsigned long int GetMTime(); + + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + // The locator is used to merge coincident points. + void CreateDefaultLocator(); + +protected: + vtkMarchingSquares(); + ~vtkMarchingSquares(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkContourValues *ContourValues; + int ImageRange[6]; + vtkPointLocator *Locator; + +private: + vtkMarchingSquares(const vtkMarchingSquares&); // Not implemented. + void operator=(const vtkMarchingSquares&); // Not implemented. +}; + +// Description: +// Set a particular contour value at contour number i. The index i ranges +// between 0<=iContourValues->SetValue(i,value);} + +// Description: +// Get the ith contour value. +inline double vtkMarchingSquares::GetValue(int i) +{return this->ContourValues->GetValue(i);} + +// Description: +// Get a pointer to an array of contour values. There will be +// GetNumberOfContours() values in the list. +inline double *vtkMarchingSquares::GetValues() +{return this->ContourValues->GetValues();} + +// Description: +// Fill a supplied list with contour values. There will be +// GetNumberOfContours() values in the list. Make sure you allocate +// enough memory to hold the list. +inline void vtkMarchingSquares::GetValues(double *contourValues) +{this->ContourValues->GetValues(contourValues);} + +// Description: +// Set the number of contours to place into the list. You only really +// need to use this method to reduce list size. The method SetValue() +// will automatically increase list size as needed. +inline void vtkMarchingSquares::SetNumberOfContours(int number) +{this->ContourValues->SetNumberOfContours(number);} + +// Description: +// Get the number of contours in the list of contour values. +inline int vtkMarchingSquares::GetNumberOfContours() +{return this->ContourValues->GetNumberOfContours();} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkMarchingSquares::GenerateValues(int numContours, double range[2]) +{this->ContourValues->GenerateValues(numContours, range);} + +// Description: +// Generate numContours equally spaced contour values between specified +// range. Contour values will include min/max range values. +inline void vtkMarchingSquares::GenerateValues(int numContours, double + rangeStart, double rangeEnd) +{this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + +#endif diff --git a/Graphics/vtkMaskFields.cxx b/Graphics/vtkMaskFields.cxx new file mode 100644 index 0000000..accd665 --- /dev/null +++ b/Graphics/vtkMaskFields.cxx @@ -0,0 +1,494 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMaskFields.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMaskFields.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDataSetAttributes.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkMaskFields, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkMaskFields); + +char vtkMaskFields::FieldLocationNames[3][12] += { "OBJECT_DATA", + "POINT_DATA", + "CELL_DATA" }; + +char vtkMaskFields::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10] += { "SCALARS", + "VECTORS", + "NORMALS", + "TCOORDS", + "TENSORS" }; + +vtkMaskFields::vtkMaskFields() +{ + + this->CopyFieldFlags = 0; + this->NumberOfFieldFlags = 0; + this->CopyAllOn(); + +} + +vtkMaskFields::~vtkMaskFields() +{ + + this->ClearFieldFlags(); + +} + +void vtkMaskFields::CopyFieldOnOff(int fieldLocation, + const char* field, int onOff) +{ + if (!field) { return; } + + int index; + // If the array is in the list, simply set IsCopied to onOff + if ((index=this->FindFlag(field, fieldLocation)) != -1) + { + this->CopyFieldFlags[index].IsCopied = onOff; + } + else + { + // We need to reallocate the list of fields + vtkMaskFields::CopyFieldFlag* newFlags = + new vtkMaskFields::CopyFieldFlag[this->NumberOfFieldFlags+1]; + // Copy old flags (pointer copy for name) + for(int i=0; iNumberOfFieldFlags; i++) + { + newFlags[i].Name = this->CopyFieldFlags[i].Name; + newFlags[i].Type = this->CopyFieldFlags[i].Type; + newFlags[i].Location = this->CopyFieldFlags[i].Location; + newFlags[i].IsCopied = this->CopyFieldFlags[i].IsCopied; + } + // Copy new flag (strcpy) + char* newName = new char[strlen(field)+1]; + strcpy(newName, field); + newFlags[this->NumberOfFieldFlags].Name = newName; + newFlags[this->NumberOfFieldFlags].Type = -1; + newFlags[this->NumberOfFieldFlags].Location = fieldLocation; + newFlags[this->NumberOfFieldFlags].IsCopied = onOff; + this->NumberOfFieldFlags++; + delete[] this->CopyFieldFlags; + this->CopyFieldFlags = newFlags; + } + this->Modified(); +} + +void vtkMaskFields::CopyAttributeOnOff(int attributeLocation, + int attributeType, int onOff) +{ + + int index; + // If the array is in the list, simply set IsCopied to onOff + if ((index=this->FindFlag(attributeType, attributeLocation)) != -1) + { + this->CopyFieldFlags[index].IsCopied = onOff; + } + else + { + // We need to reallocate the list of fields + vtkMaskFields::CopyFieldFlag* newFlags = + new vtkMaskFields::CopyFieldFlag[this->NumberOfFieldFlags+1]; + // Copy old flags (pointer copy for name) + for(int i=0; iNumberOfFieldFlags; i++) + { + newFlags[i].Name = this->CopyFieldFlags[i].Name; + newFlags[i].Type = this->CopyFieldFlags[i].Type; + newFlags[i].Location = this->CopyFieldFlags[i].Location; + newFlags[i].IsCopied = this->CopyFieldFlags[i].IsCopied; + } + // Copy new flag + newFlags[this->NumberOfFieldFlags].Name = 0; + newFlags[this->NumberOfFieldFlags].Type = attributeType; + newFlags[this->NumberOfFieldFlags].Location = attributeLocation; + newFlags[this->NumberOfFieldFlags].IsCopied = onOff; + this->NumberOfFieldFlags++; + delete[] this->CopyFieldFlags; + this->CopyFieldFlags = newFlags; + } + this->Modified(); +} + +int vtkMaskFields::GetAttributeLocation(const char* attributeLoc) +{ + int numAttributeLocs = 3; + int loc=-1; + + if (!attributeLoc) + { + return loc; + } + + for (int i=0; iGetAttributeType(attributeType); + if ( attrType == -1 ) + { + vtkErrorMacro("Target attribute type is invalid."); + return; + } + + int loc = this->GetAttributeLocation(attributeLoc); + if (loc == -1) + { + vtkErrorMacro("Target location for the attribute is invalid."); + return; + } + + this->CopyAttributeOn(loc, attrType); + +} + +void vtkMaskFields::CopyAttributeOff(const char* attributeLoc, + const char* attributeType) +{ + if (!attributeType || !attributeLoc) + { + return; + } + + // Convert strings to ints and call the appropriate CopyAttributeOn() + + int attrType = this->GetAttributeType(attributeType); + if ( attrType == -1 ) + { + vtkErrorMacro("Target attribute type is invalid."); + return; + } + + int loc = this->GetAttributeLocation(attributeLoc); + if (loc == -1) + { + vtkErrorMacro("Target location for the attribute is invalid."); + return; + } + + this->CopyAttributeOff(loc, attrType); + +} + +void vtkMaskFields::CopyFieldOn(const char* fieldLoc, + const char* name) +{ + if (!name || !fieldLoc) + { + return; + } + + // Convert strings to ints and call the appropriate CopyAttributeOn() + int loc = this->GetAttributeLocation(fieldLoc); + if (loc == -1) + { + vtkErrorMacro("Target location for the attribute is invalid."); + return; + } + + this->CopyFieldOn(loc, name); + +} + +void vtkMaskFields::CopyFieldOff(const char* fieldLoc, + const char* name) +{ + if (!name || !fieldLoc) + { + return; + } + + // Convert strings to ints and call the appropriate CopyAttributeOn() + int loc = this->GetAttributeLocation(fieldLoc); + if (loc == -1) + { + vtkErrorMacro("Target location for the attribute is invalid."); + return; + } + + this->CopyFieldOff(loc, name); + +} + +// Turn on copying of all data. +void vtkMaskFields::CopyAllOn() +{ + this->CopyFields = 1; + this->CopyAttributes = 1; + this->Modified(); +} + +// Turn off copying of all data. +void vtkMaskFields::CopyAllOff() +{ + this->CopyFields = 0; + this->CopyAttributes = 0; + this->Modified(); +} + +// Deallocate and clear the list of fields. +void vtkMaskFields::ClearFieldFlags() +{ + if (this->NumberOfFieldFlags > 0) + { + for(int i=0; iNumberOfFieldFlags; i++) + { + delete[] this->CopyFieldFlags[i].Name; + } + } + delete[] this->CopyFieldFlags; + this->CopyFieldFlags=0; + this->NumberOfFieldFlags=0; +} + +// Find if field is in CopyFieldFlags. +// If it is, it returns the index otherwise it returns -1 +int vtkMaskFields::FindFlag(const char* field, int loc) +{ + if ( !field ) return -1; + for(int i=0; iNumberOfFieldFlags; i++) + { + if (this->CopyFieldFlags[i].Name && + !strcmp(field, this->CopyFieldFlags[i].Name) && + this->CopyFieldFlags[i].Location == loc) + { + return i; + } + } + return -1; +} + +// Find if field is in CopyFieldFlags. +// If it is, it returns the index otherwise it returns -1 +int vtkMaskFields::FindFlag(int attributeType, int loc) +{ + for(int i=0; iNumberOfFieldFlags; i++) + { + if (this->CopyFieldFlags[i].Type == attributeType && + this->CopyFieldFlags[i].Location == loc) + { + return i; + } + } + return -1; +} + +// If there is no flag for this array, return -1. +// If there is one: return 0 if off, 1 if on +int vtkMaskFields::GetFlag(const char* field, int loc) +{ + int index = this->FindFlag(field, loc); + if ( index == -1 ) + { + return -1; + } + else + { + return this->CopyFieldFlags[index].IsCopied; + } +} + +// If there is no flag for this array, return -1. +// If there is one: return 0 if off, 1 if on +int vtkMaskFields::GetFlag(int arrayType, int loc) +{ + int index = this->FindFlag(arrayType, loc); + if ( index == -1 ) + { + return -1; + } + else + { + return this->CopyFieldFlags[index].IsCopied; + } +} + +int vtkMaskFields::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // This has to be here because it initializes all field data. + output->CopyStructure( input ); + + if (this->CopyFields && this->CopyAttributes) { + vtkDebugMacro("Copying both fields and attributes."); + output->GetPointData()->CopyAllOn(); + output->GetCellData()->CopyAllOn(); + + output->GetFieldData()->CopyAllOn(); + + } else if (!this->CopyFields && this->CopyAttributes) { + vtkDebugMacro("Copying only attributes."); + output->GetPointData()->CopyAllOff(); + output->GetPointData()->CopyScalarsOn(); + output->GetPointData()->CopyVectorsOn(); + output->GetPointData()->CopyTensorsOn(); + output->GetPointData()->CopyNormalsOn(); + output->GetPointData()->CopyTCoordsOn(); + + output->GetCellData()->CopyAllOff(); + output->GetCellData()->CopyScalarsOn(); + output->GetCellData()->CopyVectorsOn(); + output->GetCellData()->CopyTensorsOn(); + output->GetCellData()->CopyNormalsOn(); + output->GetCellData()->CopyTCoordsOn(); + + } else if (this->CopyFields && !this->CopyAttributes) { + vtkDebugMacro("Copying only fields."); + output->GetPointData()->CopyAllOn(); + output->GetPointData()->CopyScalarsOff(); + output->GetPointData()->CopyVectorsOff(); + output->GetPointData()->CopyTensorsOff(); + output->GetPointData()->CopyNormalsOff(); + output->GetPointData()->CopyTCoordsOff(); + + output->GetCellData()->CopyAllOn(); + output->GetCellData()->CopyScalarsOff(); + output->GetCellData()->CopyVectorsOff(); + output->GetCellData()->CopyTensorsOff(); + output->GetCellData()->CopyNormalsOff(); + output->GetCellData()->CopyTCoordsOff(); + + output->GetFieldData()->CopyAllOn(); + + } else if (!this->CopyFields && !this->CopyAttributes) { + vtkDebugMacro("Global copying off for fields and attributes."); + output->GetPointData()->CopyAllOff(); + output->GetCellData()->CopyAllOff(); + + output->GetFieldData()->CopyAllOff(); + + } + + // individual flags take precedence, so all of above will be + // overridden by individual flags... + for(int i=0; iNumberOfFieldFlags; ++i) { + + switch (this->CopyFieldFlags[i].Location) + { + case vtkMaskFields::POINT_DATA: + + if (this->CopyFieldFlags[i].Type > -1) { // attribute data + output->GetPointData()->SetCopyAttribute(this->CopyFieldFlags[i].Type,this->CopyFieldFlags[i].IsCopied); + + } else { // field data + if (this->CopyFieldFlags[i].IsCopied == 1) { + output->GetPointData()->CopyFieldOn(this->CopyFieldFlags[i].Name); + } else { + output->GetPointData()->CopyFieldOff(this->CopyFieldFlags[i].Name); + } + } + break; + case vtkMaskFields::CELL_DATA: + if (this->CopyFieldFlags[i].Type > -1) { // attribute data + output->GetCellData()->SetCopyAttribute(this->CopyFieldFlags[i].Type,this->CopyFieldFlags[i].IsCopied); + } else { // field data + if (this->CopyFieldFlags[i].IsCopied == 1) { + output->GetCellData()->CopyFieldOn(this->CopyFieldFlags[i].Name); + } else { + output->GetCellData()->CopyFieldOff(this->CopyFieldFlags[i].Name); + } + } + break; + case vtkMaskFields::OBJECT_DATA: + if (this->CopyFieldFlags[i].IsCopied == 1) { + output->GetFieldData()->CopyFieldOn(this->CopyFieldFlags[i].Name); + } else { + output->GetFieldData()->CopyFieldOff(this->CopyFieldFlags[i].Name); + } + break; + default: + vtkErrorMacro("unknown location field"); + break; + } + } + + // Pass all. + if ( output->GetFieldData() && input->GetFieldData() ) + { + output->GetFieldData()->PassData( input->GetFieldData() ); + } + output->GetPointData()->PassData( input->GetPointData() ); + output->GetCellData()->PassData( input->GetCellData() ); + + return 1; +} + +void vtkMaskFields::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of field flags: " << this->NumberOfFieldFlags << endl; + + os << indent << "CopyFields: " << this->CopyFields << endl; + + os << indent << "CopyAttributes: " << this->CopyAttributes << endl; + + +} diff --git a/Graphics/vtkMaskFields.h b/Graphics/vtkMaskFields.h new file mode 100644 index 0000000..5e5bf9a --- /dev/null +++ b/Graphics/vtkMaskFields.h @@ -0,0 +1,172 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMaskFields.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMaskFields - Allow control of which fields get passed +// to the output +// .SECTION Description +// vtkMaskFields is used to mark which fields in the input dataset +// get copied to the output. The output will contain only those fields +// marked as on by the filter. + +// .SECTION See Also +// vtkFieldData vtkDataSet vtkDataObjectToDataSetFilter +// vtkDataSetAttributes vtkDataArray vtkRearrangeFields +// vtkSplitField vtkMergeFields vtkAssignAttribute + +#ifndef __vtkMaskFields_h +#define __vtkMaskFields_h + +#include "vtkDataSetAlgorithm.h" + +#include "vtkDataSetAttributes.h" // Needed for NUM_ATTRIBUTES + +class vtkDataSet; + +class VTK_GRAPHICS_EXPORT vtkMaskFields : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkMaskFields,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a new vtkMaskFields. + static vtkMaskFields *New(); + + // Description: + // Turn on/off the copying of the field or specified by name. + // During the copying/passing, the following rules are followed for each + // array: + // 1. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 2. + // 2. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + // A field name and a location must be specified. For example: + // @verbatim + // maskFields->CopyFieldOff(vtkMaskFields::CELL_DATA, "foo"); + // @endverbatim + // causes the field "foo" on the input cell data to not get copied + // to the output. + void CopyFieldOn(int fieldLocation, const char* name) { this->CopyFieldOnOff(fieldLocation, name, 1); } + void CopyFieldOff(int fieldLocation, const char* name) { this->CopyFieldOnOff(fieldLocation, name, 0); } + + + // Description: + // Turn on/off the copying of the attribute or specified by vtkDataSetAttributes:AttributeTypes. + // During the copying/passing, the following rules are followed for each + // array: + // 1. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 2. + // 2. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + // An attribute type and a location must be specified. For example: + // @verbatim + // maskFields->CopyAttributeOff(vtkMaskFields::POINT_DATA, vtkDataSetAttributes::SCALARS); + // @endverbatim + // causes the scalars on the input point data to not get copied + // to the output. + void CopyAttributeOn(int attributeLocation, int attributeType) { this->CopyAttributeOnOff(attributeLocation, attributeType, 1); } + void CopyAttributeOff(int attributeLocation, int attributeType) { this->CopyAttributeOnOff(attributeLocation, attributeType, 0); } + + // Description: + // Convenience methods which operate on all field data or + // attribute data. More specific than CopyAllOn or CopyAllOff + void CopyFieldsOff() { this->CopyFields = 0; } + void CopyAttributesOff() { this->CopyAttributes = 0; } + + void CopyFieldsOn() { this->CopyFields = 1; } + void CopyAttributesOn() { this->CopyAttributes = 1; } + + // Description: + // Helper methods used by other language bindings. Allows the caller to + // specify arguments as strings instead of enums. + void CopyAttributeOn(const char* attributeLoc, + const char* attributeType); + void CopyAttributeOff(const char* attributeLoc, + const char* attributeType); + void CopyFieldOn(const char* fieldLoc, + const char* name); + void CopyFieldOff(const char* fieldLoc, + const char* name); + + // Description: + // Turn on copying of all data. + // During the copying/passing, the following rules are followed for each + // array: + // 1. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 2. + // 2. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + virtual void CopyAllOn(); + + // Description: + // Turn off copying of all data. + // During the copying/passing, the following rules are followed for each + // array: + // 1. If the copy flag for an array is set (on or off), it is applied + // This overrides rule 2. + // 2. If CopyAllOn is set, copy the array. + // If CopyAllOff is set, do not copy the array + virtual void CopyAllOff(); + +//BTX + enum FieldLocation + { + OBJECT_DATA=0, + POINT_DATA=1, + CELL_DATA=2 + }; +//ETX + +protected: + vtkMaskFields(); + virtual ~vtkMaskFields(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +//BTX + struct CopyFieldFlag + { + char* Name; + int Type; + int Location; + int IsCopied; + }; +//ETX + + CopyFieldFlag* CopyFieldFlags; // the names of fields not to be copied + int NumberOfFieldFlags; // the number of fields not to be copied + void CopyFieldOnOff(int fieldLocation, const char* name, int onOff); + void CopyAttributeOnOff(int attributeLocation, int attributeType, int onOff); + void ClearFieldFlags(); + int FindFlag(const char* field, int location); + int FindFlag(int arrayType, int location); + int GetFlag(const char* field, int location); + int GetFlag(int arrayType, int location); + int GetAttributeLocation(const char* loc); + int GetAttributeType(const char* type); + + int CopyFields; + int CopyAttributes; + + static char FieldLocationNames[3][12]; + static char AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10]; + +private: + vtkMaskFields(const vtkMaskFields&); // Not implemented. + void operator=(const vtkMaskFields&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkMaskPoints.cxx b/Graphics/vtkMaskPoints.cxx new file mode 100644 index 0000000..19c80f1 --- /dev/null +++ b/Graphics/vtkMaskPoints.cxx @@ -0,0 +1,187 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMaskPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMaskPoints.h" + +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkMaskPoints, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkMaskPoints); + +//---------------------------------------------------------------------------- +vtkMaskPoints::vtkMaskPoints() +{ + this->OnRatio = 2; + this->Offset = 0; + this->RandomMode = 0; + this->MaximumNumberOfPoints = VTK_LARGE_ID; + this->GenerateVertices = 0; +} + +//---------------------------------------------------------------------------- +int vtkMaskPoints::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *newPts; + vtkPointData *pd; + vtkIdType numNewPts; + double x[3]; + vtkIdType ptId, id; + vtkPointData *outputPD = output->GetPointData(); + vtkIdType numPts=input->GetNumberOfPoints(); + + // Check input + // + vtkDebugMacro(<<"Masking points"); + + if ( numPts < 1 ) + { + return 1; + } + + pd = input->GetPointData(); + id = 0; + + // Allocate space + // + numNewPts = numPts / this->OnRatio; + if (numNewPts > this->MaximumNumberOfPoints) + { + numNewPts = this->MaximumNumberOfPoints; + } + newPts = vtkPoints::New(); + newPts->Allocate(numNewPts); + outputPD->CopyAllocate(pd); + + // Traverse points and copy + // + int abort=0; + vtkIdType progressInterval=numPts/20 +1; + if ( this->RandomMode ) // retro mode + { + double cap; + + if (((double)numPts/this->OnRatio) > this->MaximumNumberOfPoints) + { + cap = 2.0*numPts/this->MaximumNumberOfPoints - 1; + } + else + { + cap = 2.0*this->OnRatio - 1; + } + + for (ptId = this->Offset; + (ptId < numPts) && (id < this->MaximumNumberOfPoints) && !abort; + ptId += (1 + (int)((double)vtkMath::Random()*cap)) ) + { + input->GetPoint(ptId, x); + id = newPts->InsertNextPoint(x); + outputPD->CopyData(pd,ptId,id); + if ( ! (id % progressInterval) ) //abort/progress + { + this->UpdateProgress (0.5*id/numPts); + abort = this->GetAbortExecute(); + } + } + } + else // a.r. mode + { + for ( ptId = this->Offset; + (ptId < numPts) && (id < (this->MaximumNumberOfPoints-1)) && !abort; + ptId += this->OnRatio ) + { + input->GetPoint(ptId, x); + id = newPts->InsertNextPoint(x); + outputPD->CopyData(pd,ptId,id); + if ( ! (id % progressInterval) ) //abort/progress + { + this->UpdateProgress (0.5*id/numPts); + abort = this->GetAbortExecute(); + } + } + } + + // Generate vertices if requested + // + if ( this->GenerateVertices ) + { + vtkCellArray *verts = vtkCellArray::New(); + verts->Allocate(verts->EstimateSize(1,id+1)); + verts->InsertNextCell(id+1); + for ( ptId=0; ptId<(id+1) && !abort; ptId++) + { + if ( ! (ptId % progressInterval) ) //abort/progress + { + this->UpdateProgress (0.5+0.5*ptId/(id+1)); + abort = this->GetAbortExecute(); + } + verts->InsertCellPoint(ptId); + } + output->SetVerts(verts); + verts->Delete(); + } + + // Update ourselves + // + output->SetPoints(newPts); + newPts->Delete(); + + output->Squeeze(); + + vtkDebugMacro(<<"Masked " << numPts << " original points to " + << id+1 << " points"); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkMaskPoints::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkMaskPoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Generate Vertices: " + << (this->GenerateVertices ? "On\n" : "Off\n"); + os << indent << "MaximumNumberOfPoints: " + << this->MaximumNumberOfPoints << "\n"; + os << indent << "On Ratio: " << this->OnRatio << "\n"; + os << indent << "Offset: " << this->Offset << "\n"; + os << indent << "Random Mode: " << (this->RandomMode ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkMaskPoints.h b/Graphics/vtkMaskPoints.h new file mode 100644 index 0000000..c590b17 --- /dev/null +++ b/Graphics/vtkMaskPoints.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMaskPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMaskPoints - selectively filter points +// .SECTION Description +// vtkMaskPoints is a filter that passes through points and point attributes +// from input dataset. (Other geometry is not passed through.) It is +// possible to mask every nth point, and to specify an initial offset +// to begin masking from. A special random mode feature enables random +// selection of points. The filter can also generate vertices (topological +// primitives) as well as points. This is useful because vertices are +// rendered while points are not. + +#ifndef __vtkMaskPoints_h +#define __vtkMaskPoints_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkMaskPoints : public vtkPolyDataAlgorithm +{ +public: + static vtkMaskPoints *New(); + vtkTypeRevisionMacro(vtkMaskPoints,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Turn on every nth point. + vtkSetClampMacro(OnRatio,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(OnRatio,int); + + // Description: + // Limit the number of points that can be passed through. + vtkSetClampMacro(MaximumNumberOfPoints,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(MaximumNumberOfPoints,vtkIdType); + + // Description: + // Start with this point. + vtkSetClampMacro(Offset,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(Offset,vtkIdType); + + // Description: + // Special flag causes randomization of point selection. If this mode is on, + // statistically every nth point (i.e., OnRatio) will be displayed. + vtkSetMacro(RandomMode,int); + vtkGetMacro(RandomMode,int); + vtkBooleanMacro(RandomMode,int); + + // Description: + // Generate output polydata vertices as well as points. A useful + // convenience method because vertices are drawn (they are topology) while + // points are not (they are geometry). By default this method is off. + vtkSetMacro(GenerateVertices,int); + vtkGetMacro(GenerateVertices,int); + vtkBooleanMacro(GenerateVertices,int); + +protected: + vtkMaskPoints(); + ~vtkMaskPoints() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int OnRatio; // every OnRatio point is on; all others are off. + vtkIdType Offset; // offset (or starting point id) + int RandomMode; // turn on/off randomization + vtkIdType MaximumNumberOfPoints; + int GenerateVertices; //generate polydata verts +private: + vtkMaskPoints(const vtkMaskPoints&); // Not implemented. + void operator=(const vtkMaskPoints&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkMaskPolyData.cxx b/Graphics/vtkMaskPolyData.cxx new file mode 100644 index 0000000..fc45859 --- /dev/null +++ b/Graphics/vtkMaskPolyData.cxx @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMaskPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMaskPolyData.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkMaskPolyData, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkMaskPolyData); + +vtkMaskPolyData::vtkMaskPolyData() +{ + this->OnRatio = 11; + this->Offset = 0; +} + +// Down sample polygonal data. Don't down sample points (that is, use the +// original points, since usually not worth it. +// +int vtkMaskPolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType id; + vtkPointData *pd; + vtkIdType numCells; + vtkIdType *pts = 0; + vtkIdType npts = 0; + int abortExecute=0; + + // Check input / pass data through + // + numCells = input->GetNumberOfCells(); + + if ( numCells < 1 ) + { + vtkErrorMacro (<<"No PolyData to mask!"); + return 1; + } + + output->Allocate(input,numCells); + input->BuildCells(); + + // Traverse topological lists and traverse + // + vtkIdType tenth = numCells/10 + 1; + for (id=this->Offset; id < numCells && !abortExecute; id+=this->OnRatio) + { + if ( ! (id % tenth) ) + { + this->UpdateProgress ((float)id/numCells); + abortExecute = this->GetAbortExecute(); + } + input->GetCellPoints(id, npts, pts); + output->InsertNextCell(input->GetCellType(id), npts, pts); + } + + // Update ourselves and release memory + // + output->SetPoints(input->GetPoints()); + pd = input->GetPointData(); + output->GetPointData()->PassData(pd); + + output->Squeeze(); + + return 1; +} + +void vtkMaskPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "On Ratio: " << this->OnRatio << "\n"; + os << indent << "Offset: " << this->Offset << "\n"; +} diff --git a/Graphics/vtkMaskPolyData.h b/Graphics/vtkMaskPolyData.h new file mode 100644 index 0000000..0027e34 --- /dev/null +++ b/Graphics/vtkMaskPolyData.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMaskPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMaskPolyData - sample subset of input polygonal data cells +// .SECTION Description +// vtkMaskPolyData is a filter that sub-samples the cells of input polygonal +// data. The user specifies every nth item, with an initial offset to begin +// sampling. + +// .SECTION See Also +// vtkMaskPoints + +#ifndef __vtkMaskPolyData_h +#define __vtkMaskPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkMaskPolyData : public vtkPolyDataAlgorithm +{ +public: + static vtkMaskPolyData *New(); + vtkTypeRevisionMacro(vtkMaskPolyData,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Turn on every nth entity (cell). + vtkSetClampMacro(OnRatio,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(OnRatio,int); + + // Description: + // Start with this entity (cell). + vtkSetClampMacro(Offset,vtkIdType,0,VTK_LARGE_ID); + vtkGetMacro(Offset,vtkIdType); + +protected: + vtkMaskPolyData(); + ~vtkMaskPolyData() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int OnRatio; // every OnRatio entity is on; all others are off. + vtkIdType Offset; // offset (or starting point id) + +private: + vtkMaskPolyData(const vtkMaskPolyData&); // Not implemented. + void operator=(const vtkMaskPolyData&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkMassProperties.cxx b/Graphics/vtkMassProperties.cxx new file mode 100644 index 0000000..47ae78d --- /dev/null +++ b/Graphics/vtkMassProperties.cxx @@ -0,0 +1,257 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMassProperties.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMassProperties.h" + +#include "vtkCell.h" +#include "vtkDataObject.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkMassProperties, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkMassProperties); + +#define VTK_CUBE_ROOT(x) \ + ((x<0.0)?(-pow((-x),0.333333333333333)):(pow((x),0.333333333333333))) + +// Constructs with initial 0 values. +vtkMassProperties::vtkMassProperties() +{ + this->SurfaceArea = 0.0; + this->Volume = 0.0; + this->VolumeX = 0.0; + this->VolumeY = 0.0; + this->VolumeZ = 0.0; + this->Kx = 0.0; + this->Ky = 0.0; + this->Kz = 0.0; + this->NormalizedShapeIndex = 0.0; + + this->SetNumberOfOutputPorts(0); +} + +// Destroy any allocated memory. +vtkMassProperties::~vtkMassProperties() +{ +} + +// Description: +// This method measures volume, surface area, and normalized shape index. +// Currently, the input is a ploydata which consists of triangles. +int vtkMassProperties::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed( outputVector )) +{ + vtkIdList *ptIds; + + vtkInformation *inInfo = + inputVector[0]->GetInformationObject(0); + + // call ExecuteData + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, numCells, numPts, numIds; + double p[3]; + + numCells=input->GetNumberOfCells(); + numPts = input->GetNumberOfPoints(); + if (numCells < 1 || numPts < 1) + { + vtkErrorMacro(<<"No data to measure...!"); + return 1; + } + + ptIds = vtkIdList::New(); + ptIds->Allocate(VTK_CELL_SIZE); + + // Traverse all cells, obtaining node coordinates. + // + double vol[3],kxyz[3]; + double munc[3],wxyz,wxy,wxz,wyz; + double area,surfacearea; + double a,b,c,s; + double x[3],y[3],z[3]; + double i[3],j[3],k[3],u[3],absu[3],length; + double ii[3],jj[3],kk[3]; + double xavg,yavg,zavg; + vtkIdType idx; + + // Initialize variables ... + // + surfacearea = 0.0; + wxyz = 0; wxy = 0.0; wxz = 0.0; wyz = 0.0; + for ( idx =0; idx < 3 ; idx++ ) + { + munc[idx] = 0.0; + vol[idx] = 0.0; + kxyz[idx] = 0.0; + } + + for (cellId=0; cellId < numCells; cellId++) + { + if ( input->GetCellType(cellId) != VTK_TRIANGLE) + { + vtkWarningMacro(<<"Input data type must be VTK_TRIANGLE not " + << input->GetCellType(cellId)); + continue; + } + input->GetCellPoints(cellId,ptIds); + numIds = ptIds->GetNumberOfIds(); + + // store current vertix (x,y,z) coordinates ... + // + for (idx=0; idx < numIds; idx++) + { + input->GetPoint(ptIds->GetId(idx), p); + x[idx] = p[0]; y[idx] = p[1]; z[idx] = p[2]; + } + + // get i j k vectors ... + // + i[0] = ( x[1] - x[0]); j[0] = (y[1] - y[0]); k[0] = (z[1] - z[0]); + i[1] = ( x[2] - x[0]); j[1] = (y[2] - y[0]); k[1] = (z[2] - z[0]); + i[2] = ( x[2] - x[1]); j[2] = (y[2] - y[1]); k[2] = (z[2] - z[1]); + + // cross product between two vectors, to determine normal vector + // + u[0] = ( j[0] * k[1] - k[0] * j[1]); + u[1] = ( k[0] * i[1] - i[0] * k[1]); + u[2] = ( i[0] * j[1] - j[0] * i[1]); + + // normalize normal vector to 1 + // + length = sqrt( u[0]*u[0] + u[1]*u[1] + u[2]*u[2]); + if ( length != 0.0) + { + u[0] /= length; + u[1] /= length; + u[2] /= length; + } + else + { + u[0] = u[1] = u[2] = 0.0; + } + + // determine max unit normal component... + // + absu[0] = fabs(u[0]); absu[1] = fabs(u[1]); absu[2] = fabs(u[2]); + + if (( absu[0] > absu[1]) && ( absu[0] > absu[2]) ) + { + munc[0]++; + } + else if (( absu[1] > absu[0]) && ( absu[1] > absu[2]) ) + { + munc[1]++; + } + else if (( absu[2] > absu[0]) && ( absu[2] > absu[1]) ) + { + munc[2]++; + } + else if (( absu[0] == absu[1])&& ( absu[0] == absu[2])) + { + wxyz++; + } + else if (( absu[0] == absu[1])&& ( absu[0] > absu[2]) ) + { + wxy++; + } + else if (( absu[0] == absu[2])&& ( absu[0] > absu[1]) ) + { + wxz++; + } + else if (( absu[1] == absu[2])&& ( absu[0] < absu[2]) ) + { + wyz++; + } + else + { + vtkErrorMacro(<<"Unpredicted situation...!"); + return 1; + } + + // This is reduced to ... + // + ii[0] = i[0] * i[0]; ii[1] = i[1] * i[1]; ii[2] = i[2] * i[2]; + jj[0] = j[0] * j[0]; jj[1] = j[1] * j[1]; jj[2] = j[2] * j[2]; + kk[0] = k[0] * k[0]; kk[1] = k[1] * k[1]; kk[2] = k[2] * k[2]; + + // area of a triangle... + // + a = sqrt(ii[1] + jj[1] + kk[1]); + b = sqrt(ii[0] + jj[0] + kk[0]); + c = sqrt(ii[2] + jj[2] + kk[2]); + s = 0.5 * (a + b + c); + area = sqrt( fabs(s*(s-a)*(s-b)*(s-c))); + surfacearea += area; + + // volume elements ... + // + zavg = (z[0] + z[1] + z[2]) / 3.0; + yavg = (y[0] + y[1] + y[2]) / 3.0; + xavg = (x[0] + x[1] + x[2]) / 3.0; + + vol[2] += (area * (double)u[2] * (double)zavg); + vol[1] += (area * (double)u[1] * (double)yavg); + vol[0] += (area * (double)u[0] * (double)xavg); + } + + // Surface Area ... + // + this->SurfaceArea = (double)surfacearea; + + // Weighting factors in Discrete Divergence theorem for volume calculation... + // + kxyz[0] = (munc[0] + (wxyz/3.0) + ((wxy+wxz)/2.0)) /(double)(numCells); + kxyz[1] = (munc[1] + (wxyz/3.0) + ((wxy+wyz)/2.0)) /(double)(numCells); + kxyz[2] = (munc[2] + (wxyz/3.0) + ((wxz+wyz)/2.0)) /(double)(numCells); + this->VolumeX = vol[0]; + this->VolumeY = vol[1]; + this->VolumeZ = vol[2]; + this->Kx = kxyz[0]; + this->Ky = kxyz[1]; + this->Kz = kxyz[2]; + this->Volume = (kxyz[0] * vol[0] + kxyz[1] * vol[1] + kxyz[2] * vol[2]); + this->Volume = fabs(this->Volume); + this->NormalizedShapeIndex = + (sqrt(surfacearea)/VTK_CUBE_ROOT(this->Volume))/2.199085233; + ptIds->Delete(); + + return 1; +} + +void vtkMassProperties::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + vtkPolyData *input = vtkPolyData::SafeDownCast(this->GetInput(0)); + if (!input) + { + return; + } + os << indent << "VolumeX: " << this->GetVolumeX () << "\n"; + os << indent << "VolumeY: " << this->GetVolumeY () << "\n"; + os << indent << "VolumeZ: " << this->GetVolumeZ () << "\n"; + os << indent << "Kx: " << this->GetKx () << "\n"; + os << indent << "Ky: " << this->GetKy () << "\n"; + os << indent << "Kz: " << this->GetKz () << "\n"; + os << indent << "Volume: " << this->GetVolume () << "\n"; + os << indent << "Surface Area: " << this->GetSurfaceArea () << "\n"; + os << indent << "Normalized Shape Index: " + << this->GetNormalizedShapeIndex () << "\n"; +} diff --git a/Graphics/vtkMassProperties.h b/Graphics/vtkMassProperties.h new file mode 100644 index 0000000..b94b911 --- /dev/null +++ b/Graphics/vtkMassProperties.h @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMassProperties.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMassProperties - estimate volume, area, shape index of triangle mesh +// .SECTION Description +// vtkMassProperties estimates the volume, the surface area, and the +// normalized shape index of a triangle mesh. The algorithm +// implemented here is based on the discrete form of the divergence +// theorem. The general assumption here is that the model is of +// closed surface. For more details see the following reference +// (Alyassin A.M. et al, "Evaluation of new algorithms for the +// interactive measurement of surface area and volume", Med Phys 21(6) +// 1994.). + +// .SECTION Caveats +// Currently only triangles are processed. Use vtkTriangleFilter to +// convert any strips or polygons to triangles. + +// .SECTION See Also +// vtkTriangleFilter + +#ifndef __vtkMassProperties_h +#define __vtkMassProperties_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkMassProperties : public vtkPolyDataAlgorithm +{ +public: + // Description: + // Constructs with initial values of zero. + static vtkMassProperties *New(); + + vtkTypeRevisionMacro(vtkMassProperties,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Compute and return the volume. + double GetVolume() {this->Update(); return this->Volume;} + + // Description: + // Compute and return the volume projected on to each axis aligned plane. + double GetVolumeX() {this->Update(); return this->VolumeX;} + double GetVolumeY() {this->Update(); return this->VolumeY;} + double GetVolumeZ() {this->Update(); return this->VolumeZ;} + + // Description: + // Compute and return the weighting factors for the maximum unit + // normal component (MUNC). + double GetKx() {this->Update(); return this->Kx;} + double GetKy() {this->Update(); return this->Ky;} + double GetKz() {this->Update(); return this->Kz;} + + // Description: + // Compute and return the area. + double GetSurfaceArea() {this->Update(); return this->SurfaceArea;} + + // Description: + // Compute and return the normalized shape index. This characterizes the + // deviation of the shape of an object from a sphere. A sphere's NSI + // is one. This number is always >= 1.0. + double GetNormalizedShapeIndex() + {this->Update(); return this->NormalizedShapeIndex;} + +protected: + vtkMassProperties(); + ~vtkMassProperties(); + + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + double SurfaceArea; + double Volume; + double VolumeX; + double VolumeY; + double VolumeZ; + double Kx; + double Ky; + double Kz; + double NormalizedShapeIndex; + vtkTimeStamp ExecuteTime; + +private: + vtkMassProperties(const vtkMassProperties&); // Not implemented. + void operator=(const vtkMassProperties&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkMergeCells.cxx b/Graphics/vtkMergeCells.cxx new file mode 100644 index 0000000..36a449a --- /dev/null +++ b/Graphics/vtkMergeCells.cxx @@ -0,0 +1,964 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeCells.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkMergeCells.h" + +#include "vtkUnstructuredGrid.h" +#include "vtkCell.h" +#include "vtkPoints.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkObjectFactory.h" +#include "vtkCellArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkObjectFactory.h" +#include "vtkIntArray.h" +#include "vtkCharArray.h" +#include "vtkLongArray.h" +#include "vtkShortArray.h" +#include "vtkIdTypeArray.h" +#include "vtkDataArray.h" +#include "vtkMergePoints.h" +#include "vtkKdTree.h" +#include "vtkModelMetadata.h" +#include +#include +#include + +vtkCxxRevisionMacro(vtkMergeCells, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkMergeCells); + +vtkCxxSetObjectMacro(vtkMergeCells, UnstructuredGrid, vtkUnstructuredGrid); + +class vtkMergeCellsSTLCloak +{ +public: + vtkstd::map IdTypeMap; +}; + +vtkMergeCells::vtkMergeCells() +{ + this->TotalNumberOfDataSets = 0; + this->TotalNumberOfCells = 0; + this->TotalNumberOfPoints = 0; + + this->NumberOfCells = 0; + this->NumberOfPoints = 0; + + this->GlobalIdArrayName = NULL; + this->GlobalCellIdArrayName = NULL; + this->PointMergeTolerance = 10e-4; + this->MergeDuplicatePoints = 1; + + this->InputIsUGrid = 0; + this->InputIsPointSet = 0; + + this->ptList = NULL; + this->cellList = NULL; + + this->UnstructuredGrid = NULL; + + this->GlobalIdMap = new vtkMergeCellsSTLCloak; + this->GlobalCellIdMap = new vtkMergeCellsSTLCloak; + + this->nextGrid = 0; +} + +vtkMergeCells::~vtkMergeCells() +{ + this->FreeLists(); + + delete this->GlobalIdMap; + delete this->GlobalCellIdMap; + + this->SetUnstructuredGrid(0); +} + +void vtkMergeCells::FreeLists() +{ + if (this->GlobalIdArrayName) + { + delete [] this->GlobalIdArrayName; + this->GlobalIdArrayName = NULL; + } + + if (this->GlobalCellIdArrayName) + { + delete [] this->GlobalCellIdArrayName; + this->GlobalCellIdArrayName = NULL; + } + + if (this->ptList) + { + delete this->ptList; + this->ptList = NULL; + } + + if (this->cellList) + { + delete this->cellList; + this->cellList = NULL; + } +} + + +int vtkMergeCells::MergeDataSet(vtkDataSet *set) +{ + vtkIdType newPtId, oldPtId, newCellId; + vtkIdType *idMap; + + vtkUnstructuredGrid *ugrid = this->UnstructuredGrid; + + if (!ugrid) + { + vtkErrorMacro(<< "SetUnstructuredGrid first"); + return -1; + } + + if (this->TotalNumberOfDataSets <= 0) + { + // TotalNumberOfCells and TotalNumberOfPoints may both be zero + // if all data sets to be merged are empty + + vtkErrorMacro(<< + "Must SetTotalNumberOfCells, SetTotalNumberOfPoints and SetTotalNumberOfDataSets (upper bounds at least)" + " before starting to MergeDataSets"); + + return -1; + } + + vtkModelMetadata *mergedMetadata = NULL; + + if (vtkModelMetadata::HasMetadata(set)) + { + mergedMetadata = vtkModelMetadata::New(); + mergedMetadata->Unpack(set, 0); + + if (vtkModelMetadata::HasMetadata(ugrid)) + { + vtkModelMetadata *gridMetadata = vtkModelMetadata::New(); + gridMetadata->Unpack(ugrid, 1); // delete md from ugrid after unpacking it + + // warning - MergeModelMetadata checks for duplicate points, but + // doesn't check for duplicate cells + + mergedMetadata->MergeModelMetadata(gridMetadata); + gridMetadata->Delete(); + } + } + + vtkPointData *pointArrays = set->GetPointData(); + vtkCellData *cellArrays = set->GetCellData(); + + // Since vtkMergeCells is to be used only on distributed vtkDataSets, + // each DataSet should have the same field arrays. However I've been + // told that the field arrays may get rearranged in the process of + // Marshalling/UnMarshalling. So we use a + // vtkDataSetAttributes::FieldList to ensure the field arrays are + // merged in the right order. + + if (ugrid->GetNumberOfCells() == 0) + { + vtkPointSet *check1 = vtkPointSet::SafeDownCast(set); + + if (check1) + { + this->InputIsPointSet = 1; + vtkUnstructuredGrid *check2 = vtkUnstructuredGrid::SafeDownCast(set); + this->InputIsUGrid = (check2 != NULL); + } + + this->StartUGrid(set); + } + else + { + this->ptList->IntersectFieldList(pointArrays); + this->cellList->IntersectFieldList(cellArrays); + } + + vtkIdType numPoints = set->GetNumberOfPoints(); + vtkIdType numCells = set->GetNumberOfCells(); + + if (numCells == 0) + { + if (mergedMetadata) + { + mergedMetadata->Pack(ugrid); + mergedMetadata->Delete(); + } + return 0; + } + + if (this->MergeDuplicatePoints) + { + if (this->GlobalIdArrayName) // faster by far + { + // Note: It has been observed that an input dataset may + // have an invalid global ID array. Using the array to + // merge points results in bad geometry. It may be + // worthwhile to do a quick sanity check when merging + // points. Downside is that will slow down this filter. + + idMap = this->MapPointsToIdsUsingGlobalIds(set); + } + else + { + idMap = this->MapPointsToIdsUsingLocator(set); + } + } + else + { + idMap = NULL; + } + + vtkIdType nextPt = (vtkIdType)this->NumberOfPoints; + + vtkPoints *pts = ugrid->GetPoints(); + + for (oldPtId=0; oldPtId < numPoints; oldPtId++) + { + if (idMap) + { + newPtId = idMap[oldPtId]; + } + else + { + newPtId = nextPt; + } + + if (newPtId == nextPt) + { + pts->SetPoint(nextPt, set->GetPoint(oldPtId)); + + ugrid->GetPointData()->CopyData(*this->ptList, + pointArrays, this->nextGrid, oldPtId, nextPt); + + nextPt++; + } + } + + pts->Modified(); // so that subsequent GetBounds will be correct + + if (this->InputIsUGrid) + { + newCellId = this->AddNewCellsUnstructuredGrid(set, idMap); + } + else + { + newCellId = this->AddNewCellsDataSet(set, idMap); + } + + if (idMap) delete [] idMap; + + this->NumberOfPoints = nextPt; + this->NumberOfCells = newCellId; + + this->nextGrid++; + + if (mergedMetadata) + { + mergedMetadata->Pack(ugrid); + mergedMetadata->Delete(); + } + + return 0; +} +vtkIdType vtkMergeCells::AddNewCellsDataSet(vtkDataSet *set, vtkIdType *idMap) +{ + vtkIdType oldCellId, id, newPtId, newCellId = 0, oldPtId; + + vtkUnstructuredGrid *ugrid = this->UnstructuredGrid; + vtkCellData *cellArrays = set->GetCellData(); + vtkIdType numCells = set->GetNumberOfCells(); + + vtkIdList *cellPoints = vtkIdList::New(); + cellPoints->Allocate(VTK_CELL_SIZE); + + vtkIdType nextCellId = 0; + + int duplicateCellTest = 0; + + if (this->GlobalCellIdArrayName) + { + int success = this->GlobalCellIdAccessStart(set); + + if (success) + { + nextCellId = this->GlobalCellIdMap->IdTypeMap.size(); + duplicateCellTest = 1; + } + } + + for (oldCellId=0; oldCellId < numCells; oldCellId++) + { + if (duplicateCellTest) + { + vtkIdType globalId = this->GlobalCellIdAccessGetId(oldCellId); + + vtkstd::pair::iterator, bool> inserted = + + this->GlobalCellIdMap->IdTypeMap.insert( + vtkstd::map::value_type(globalId, nextCellId)); + + if (inserted.second) + { + nextCellId++; + } + else + { + continue; // skip it, we already have this cell + } + } + + set->GetCellPoints(oldCellId, cellPoints); + + for (id=0; id < cellPoints->GetNumberOfIds(); id++) + { + oldPtId = cellPoints->GetId(id); + + if (idMap) + { + newPtId = idMap[oldPtId]; + } + else + { + newPtId = this->NumberOfPoints + oldPtId; + } + cellPoints->SetId(id, newPtId); + } + + newCellId = + (vtkIdType)ugrid->InsertNextCell(set->GetCellType(oldCellId), cellPoints); + + ugrid->GetCellData()->CopyData(*(this->cellList), cellArrays, + this->nextGrid, oldCellId, newCellId); + } + + cellPoints->Delete(); + + return newCellId; +} +vtkIdType vtkMergeCells::AddNewCellsUnstructuredGrid(vtkDataSet *set, + vtkIdType *idMap) +{ + vtkIdType id; + + char firstSet = 0; + + if (this->nextGrid == 0) firstSet = 1; + + vtkUnstructuredGrid *newUgrid = vtkUnstructuredGrid::SafeDownCast(set); + vtkUnstructuredGrid *Ugrid = this->UnstructuredGrid; + + // connectivity information for the new data set + + vtkCellArray *newCellArray = newUgrid->GetCells(); + vtkIdType *newCells = newCellArray->GetPointer(); + vtkIdType *newLocs = newUgrid->GetCellLocationsArray()->GetPointer(0); + unsigned char *newTypes = newUgrid->GetCellTypesArray()->GetPointer(0); + + int newNumCells = newUgrid->GetNumberOfCells(); + int newNumConnections = newCellArray->GetData()->GetNumberOfTuples(); + + // If we are checking for duplicate cells, create a list now of + // any cells in the new data set that we already have. + + vtkIdList *duplicateCellIds = NULL; + int numDuplicateCells = 0; + int numDuplicateConnections = 0; + + if (this->GlobalCellIdArrayName) + { + int success = this->GlobalCellIdAccessStart(set); + + if (success) + { + vtkIdType nextLocalId = this->GlobalCellIdMap->IdTypeMap.size(); + + duplicateCellIds = vtkIdList::New(); + + for (id = 0; id < newNumCells; id++) + { + vtkIdType globalId = this->GlobalCellIdAccessGetId(id); + + vtkstd::pair::iterator, bool> inserted = + + this->GlobalCellIdMap->IdTypeMap.insert( + vtkstd::map::value_type(globalId, nextLocalId)); + + if (inserted.second) + { + nextLocalId++; + } + else + { + duplicateCellIds->InsertNextId(id); + numDuplicateCells++; + + int npoints = newCells[newLocs[id]]; + + numDuplicateConnections += (npoints + 1); + } + } + + if (numDuplicateCells == 0) + { + duplicateCellIds->Delete(); + duplicateCellIds = NULL; + } + } + } + + // connectivity for the merged ugrid so far + + vtkCellArray *cellArray = NULL; + vtkIdType *cells = NULL; + vtkIdType *locs = NULL; + unsigned char *types = NULL; + + int numCells = 0; + int numConnections = 0; + + if (!firstSet) + { + cellArray = Ugrid->GetCells(); + cells = cellArray->GetPointer(); + locs = Ugrid->GetCellLocationsArray()->GetPointer(0); + types = Ugrid->GetCellTypesArray()->GetPointer(0);; + + numCells = Ugrid->GetNumberOfCells(); + numConnections = cellArray->GetData()->GetNumberOfTuples(); + } + + // New output grid: merging of existing and incoming grids + + // CELL ARRAY + + int totalNumCells = numCells + newNumCells - numDuplicateCells; + int totalNumConnections = + numConnections + newNumConnections - numDuplicateConnections; + + vtkIdTypeArray *mergedcells = vtkIdTypeArray::New(); + mergedcells->SetNumberOfValues(totalNumConnections); + + if (!firstSet) + { + vtkIdType *idptr = mergedcells->GetPointer(0); + memcpy(idptr, cells, sizeof(vtkIdType) * numConnections); + } + + vtkCellArray *finalCellArray = vtkCellArray::New(); + finalCellArray->SetCells(totalNumCells, mergedcells); + + // LOCATION ARRAY + + vtkIdTypeArray *locationArray = vtkIdTypeArray::New(); + locationArray->SetNumberOfValues(totalNumCells); + + vtkIdType *iptr = locationArray->GetPointer(0); // new output dataset + + if (!firstSet) + { + memcpy(iptr, locs, numCells * sizeof(vtkIdType)); // existing set + } + + // TYPE ARRAY + + vtkUnsignedCharArray *typeArray = vtkUnsignedCharArray::New(); + typeArray->SetNumberOfValues(totalNumCells); + + unsigned char *cptr = typeArray->GetPointer(0); + + if (!firstSet) + { + memcpy(cptr, types, numCells * sizeof(unsigned char)); + } + + // set up new cell data + + vtkIdType finalCellId = numCells; + vtkIdType nextCellArrayIndex = static_cast(numConnections); + vtkCellData *cellArrays = set->GetCellData(); + + vtkIdType oldPtId, finalPtId; + + int nextDuplicateCellId = 0; + + for (vtkIdType oldCellId=0; oldCellId < newNumCells; oldCellId++) + { + vtkIdType size = *newCells++; + + if (duplicateCellIds) + { + vtkIdType skipId = duplicateCellIds->GetId(nextDuplicateCellId); + + if (skipId == oldCellId) + { + newCells += size; + nextDuplicateCellId++; + continue; + } + } + + locationArray->SetValue(finalCellId, nextCellArrayIndex); + + typeArray->SetValue(finalCellId, newTypes[oldCellId]); + + mergedcells->SetValue(nextCellArrayIndex++, size); + + for (id=0; id < size; id++) + { + oldPtId = *newCells++; + + if (idMap) + { + finalPtId = idMap[oldPtId]; + } + else + { + finalPtId = this->NumberOfPoints + oldPtId; + } + + mergedcells->SetValue(nextCellArrayIndex++, finalPtId); + } + + Ugrid->GetCellData()->CopyData(*(this->cellList), cellArrays, + this->nextGrid, oldCellId, finalCellId); + + finalCellId++; + } + + Ugrid->SetCells(typeArray, locationArray, finalCellArray); + + mergedcells->Delete(); + typeArray->Delete(); + locationArray->Delete(); + finalCellArray->Delete(); + + if (duplicateCellIds) + { + duplicateCellIds->Delete(); + } + + return finalCellId; +} + +void vtkMergeCells::StartUGrid(vtkDataSet *set) +{ + vtkPointData *PD = set->GetPointData(); + vtkCellData *CD = set->GetCellData(); + + vtkUnstructuredGrid *ugrid = this->UnstructuredGrid; + + ugrid->Initialize(); + + if (!this->InputIsUGrid) + { + ugrid->Allocate(this->TotalNumberOfCells); + } + + vtkPoints *pts = vtkPoints::New(); + + // If the input has a vtkPoints object, we'll make the merged output + // grid have a vtkPoints object of the same data type. Otherwise, + // the merged output grid will have the default of points of type float. + + if (this->InputIsPointSet) + { + vtkPointSet *ps = vtkPointSet::SafeDownCast(set); + pts->SetDataType(ps->GetPoints()->GetDataType()); + } + + pts->SetNumberOfPoints(this->TotalNumberOfPoints); // allocate for upper bound + + ugrid->SetPoints(pts); + + pts->Delete(); + + // Order of field arrays may get changed when data sets are + // marshalled/sent/unmarshalled. So we need to re-index the + // field arrays before copying them using a FieldList + + this->ptList = new vtkDataSetAttributes::FieldList(this->TotalNumberOfDataSets); + this->cellList = new vtkDataSetAttributes::FieldList(this->TotalNumberOfDataSets); + + this->ptList->InitializeFieldList(PD); + this->cellList->InitializeFieldList(CD); + + ugrid->GetPointData()->CopyAllocate(*ptList, this->TotalNumberOfPoints); + ugrid->GetCellData()->CopyAllocate(*cellList, this->TotalNumberOfCells); + + return; +} + +void vtkMergeCells::Finish() +{ + this->FreeLists(); + + vtkUnstructuredGrid *ugrid = this->UnstructuredGrid; + + if (this->NumberOfPoints < this->TotalNumberOfPoints) + { + // if we don't do this, ugrid->GetNumberOfPoints() gives + // the wrong value + + ugrid->GetPoints()->GetData()->Resize(this->NumberOfPoints); + } + + ugrid->Squeeze(); + + return; +} + +// Use an array of global node ids to map all points to +// their new Ids in the merged grid. + +vtkIdType *vtkMergeCells::MapPointsToIdsUsingGlobalIds(vtkDataSet *set) +{ + int success = this->GlobalNodeIdAccessStart(set); + + if (!success) + { + vtkErrorMacro("global id array is not available"); + return NULL; + } + + vtkIdType npoints = set->GetNumberOfPoints(); + + vtkIdType *idMap = new vtkIdType [npoints]; + + vtkIdType nextNewLocalId = this->GlobalIdMap->IdTypeMap.size(); + + // map global point Ids to Ids in the new data set + + for (vtkIdType oldId=0; oldIdGlobalNodeIdAccessGetId(oldId); + + vtkstd::pair::iterator, bool> inserted = + + this->GlobalIdMap->IdTypeMap.insert( + vtkstd::map::value_type(globalId, nextNewLocalId)); + + if (inserted.second) + { + // this is a new global node Id + + idMap[oldId] = nextNewLocalId; + + nextNewLocalId++; + } + else + { + // a repeat, it was not inserted + + idMap[oldId] = inserted.first->second; + } + } + + return idMap; +} + +// Use a spatial locator to filter out duplicate points and map +// the new Ids to their Ids in the merged grid. + +vtkIdType *vtkMergeCells::MapPointsToIdsUsingLocator(vtkDataSet *set) +{ + vtkIdType ptId; + + vtkUnstructuredGrid *grid = this->UnstructuredGrid; + vtkPoints *points0 = grid->GetPoints(); + vtkIdType npoints0 = (vtkIdType)this->NumberOfPoints; + + vtkPointSet *ps = vtkPointSet::SafeDownCast(set); + vtkPoints *points1; + vtkIdType npoints1 = set->GetNumberOfPoints(); + + if (ps) + { + points1 = ps->GetPoints(); + } + else + { + points1 = vtkPoints::New(); + points1->SetNumberOfPoints(npoints1); + + for (ptId=0; ptIdSetPoint(ptId, set->GetPoint(ptId)); + } + } + + vtkIdType *idMap = new vtkIdType [npoints1]; + + vtkIdType nextNewLocalId = npoints0; + + if (this->PointMergeTolerance == 0.0) + { + // testing shows vtkMergePoints is fastest when tolerance is 0 + + vtkMergePoints *locator = vtkMergePoints::New(); + + vtkPoints *ptarray = vtkPoints::New(); + + double bounds[6]; + + set->GetBounds(bounds); + + if (npoints0 > 0) + { + double tmpbounds[6]; + grid->GetBounds(tmpbounds); + + bounds[0] = ((tmpbounds[0] < bounds[0]) ? tmpbounds[0] : bounds[0]); + bounds[2] = ((tmpbounds[2] < bounds[2]) ? tmpbounds[2] : bounds[2]); + bounds[4] = ((tmpbounds[4] < bounds[4]) ? tmpbounds[4] : bounds[4]); + + bounds[1] = ((tmpbounds[1] > bounds[1]) ? tmpbounds[1] : bounds[1]); + bounds[3] = ((tmpbounds[3] > bounds[3]) ? tmpbounds[3] : bounds[3]); + bounds[5] = ((tmpbounds[5] > bounds[5]) ? tmpbounds[5] : bounds[5]); + } + + locator->InitPointInsertion(ptarray, bounds); + + vtkIdType newId; + double x[3]; + + for (ptId = 0; ptId < npoints0; ptId++) + { + // We already know there are no duplicates in this array. + // Just add them to the locator's point array. + + points0->GetPoint(ptId, x); + locator->InsertUniquePoint(x, newId); + } + for (ptId = 0; ptId < npoints1; ptId++) + { + points1->GetPoint(ptId, x); + locator->InsertUniquePoint(x, newId); + + idMap[ptId] = newId; + } + + locator->Delete(); + ptarray->Delete(); + } + else + { + // testing shows vtkKdTree is fastest when tolerance is > 0 + + vtkKdTree *kd = vtkKdTree::New(); + + vtkPoints *ptArrays[2]; + int numArrays; + + if (npoints0 > 0) + { + // points0->GetNumberOfPoints() is equal to the upper bound + // on the points in the final merged grid. We need to temporarily + // set it to the number of points added to the merged grid so far. + + points0->GetData()->SetNumberOfTuples(npoints0); + + ptArrays[0] = points0; + ptArrays[1] = points1; + numArrays = 2; + } + else + { + ptArrays[0] = points1; + numArrays = 1; + } + + kd->BuildLocatorFromPoints(ptArrays, numArrays); + + vtkIdTypeArray *pointToEquivClassMap = + kd->BuildMapForDuplicatePoints(this->PointMergeTolerance); + + kd->Delete(); + + if (npoints0 > 0) + { + points0->GetData()->SetNumberOfTuples(this->TotalNumberOfPoints); + } + + // The map we get back isn't quite what we need. The range of + // the map is a subset of original point IDs which each + // represent an equivalence class of duplicate points. But the + // point chosen to represent the class could be any one of the + // equivalent points. We need to create a map that uses IDs + // of points in the points0 array as the representative, and + // then new logical contiguous point IDs + // (npoints0, npoints0+1, ..., numUniquePoints-1) for the + // points in the new set that are not duplicates of points + // in the points0 array. + + vtkstd::map newIdMap; + + if (npoints0 > 0) // these were already a unique set + { + for (ptId = 0; ptId < npoints0 ; ptId++) + { + vtkIdType EqClassRep = pointToEquivClassMap->GetValue(ptId); + + if (EqClassRep != ptId) + { + newIdMap.insert(vtkstd::map::value_type(EqClassRep, ptId)); + } + } + } + for (ptId = 0; ptId < npoints1; ptId++) + { + vtkIdType EqClassRep = pointToEquivClassMap->GetValue(ptId + npoints0); + + if (EqClassRep < npoints0){ + idMap[ptId] = EqClassRep; // a duplicate of a point in the first set + continue; + } + + vtkstd::pair::iterator, bool> inserted = + + newIdMap.insert( + vtkstd::map::value_type(EqClassRep, nextNewLocalId)); + + bool newEqClassRep = inserted.second; + vtkIdType existingMappedId = inserted.first->second; + + if (newEqClassRep) + { + idMap[ptId] = nextNewLocalId; // here's a new unique point + + nextNewLocalId++; + } + else + { + idMap[ptId] = existingMappedId; // a duplicate of a point in the new set + } + } + + pointToEquivClassMap->Delete(); + newIdMap.clear(); + } + + if (!ps) + { + points1->Delete(); + } + + return idMap; +} +//------------------------------------------------------------------------- +// Help with the complex business of efficient access to the node ID arrays. +// The array was given to us by the user, and we don't know the data type or +// size. +//------------------------------------------------------------------------- + +vtkIdType vtkMergeCells::GlobalCellIdAccessGetId(vtkIdType idx) +{ + if(this->GlobalCellIdArray) + { + switch (this->GlobalCellIdArrayType) + { + vtkTemplateMacro( + VTK_TT* ids = static_cast(this->GlobalCellIdArray); + return static_cast(ids[idx]) + ); + } + } + return 0; +} +int vtkMergeCells::GlobalCellIdAccessStart(vtkDataSet *set) +{ + if(vtkDataArray* da = + set->GetPointData()->GetArray(this->GlobalCellIdArrayName)) + { + this->GlobalCellIdArray = da->GetVoidPointer(0); + this->GlobalCellIdArrayType = da->GetDataType(); + return 1; + } + else + { + this->GlobalCellIdArray = 0; + return 0; + } +} + +vtkIdType vtkMergeCells::GlobalNodeIdAccessGetId(vtkIdType idx) +{ + if(this->GlobalIdArray) + { + switch (this->GlobalIdArrayType) + { + vtkTemplateMacro( + VTK_TT* ids = static_cast(this->GlobalIdArray); + return static_cast(ids[idx]) + ); + } + } + return 0; +} +int vtkMergeCells::GlobalNodeIdAccessStart(vtkDataSet *set) +{ + if(vtkDataArray* da = set->GetPointData()->GetArray(this->GlobalIdArrayName)) + { + this->GlobalIdArray = da->GetVoidPointer(0); + this->GlobalIdArrayType = da->GetDataType(); + return 1; + } + else + { + this->GlobalIdArray = 0; + return 0; + } +} + + +void vtkMergeCells::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "TotalNumberOfDataSets: " << this->TotalNumberOfDataSets << endl; + os << indent << "TotalNumberOfCells: " << this->TotalNumberOfCells << endl; + os << indent << "TotalNumberOfPoints: " << this->TotalNumberOfPoints << endl; + + os << indent << "NumberOfCells: " << this->NumberOfCells << endl; + os << indent << "NumberOfPoints: " << this->NumberOfPoints << endl; + + if (this->GlobalIdArrayName) + { + os << indent << "GlobalIdArrayName: " << this->GlobalIdArrayName << endl; + } + + if (this->GlobalCellIdArrayName) + { + os << indent << "GlobalCellIdArrayName: " << this->GlobalCellIdArrayName << endl; + } + + os << indent << "GlobalIdMap: " << this->GlobalIdMap->IdTypeMap.size() << endl; + os << indent << "GlobalCellIdMap: " << this->GlobalCellIdMap->IdTypeMap.size() << endl; + + os << indent << "PointMergeTolerance: " << this->PointMergeTolerance << endl; + os << indent << "MergeDuplicatePoints: " << this->MergeDuplicatePoints << endl; + os << indent << "InputIsUGrid: " << this->InputIsUGrid << endl; + os << indent << "InputIsPointSet: " << this->InputIsPointSet << endl; + os << indent << "UnstructuredGrid: " << this->UnstructuredGrid << endl; + os << indent << "ptList: " << this->ptList << endl; + os << indent << "cellList: " << this->cellList << endl; +} + diff --git a/Graphics/vtkMergeCells.h b/Graphics/vtkMergeCells.h new file mode 100644 index 0000000..25105c2 --- /dev/null +++ b/Graphics/vtkMergeCells.h @@ -0,0 +1,199 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeCells.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkMergeCells - merges any number of vtkDataSets back into a single +// vtkUnstructuredGrid +// +// .SECTION Description +// Designed to work with distributed vtkDataSets, this class will take +// vtkDataSets and merge them back into a single vtkUnstructuredGrid. +// +// The vtkPoints object of the unstructured grid will have data type +// VTK_FLOAT, regardless of the data type of the points of the +// input vtkDataSets. If this is a problem, someone must let me know. +// +// It is assumed the different DataSets have the same field arrays. If +// the name of a global point ID array is provided, this class will +// refrain from including duplicate points in the merged Ugrid. This +// class differs from vtkAppendFilter in these ways: (1) it uses less +// memory than that class (which uses memory equal to twice the size +// of the final Ugrid) but requires that you know the size of the +// final Ugrid in advance (2) this class assumes the individual DataSets have +// the same field arrays, while vtkAppendFilter intersects the field +// arrays (3) this class knows duplicate points may be appearing in +// the DataSets and can filter those out, (4) this class is not a filter. + +#ifndef __vtkMergeCells_h +#define __vtkMergeCells_h + +#include "vtkObject.h" +#include "vtkDataSetAttributes.h" // Needed for FieldList + +class vtkDataSet; +class vtkUnstructuredGrid; +class vtkPointData; +class vtkCellData; +class vtkMergeCellsSTLCloak; + +class VTK_GRAPHICS_EXPORT vtkMergeCells : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkMergeCells, vtkObject); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + static vtkMergeCells *New(); + + // Description: + // Set the vtkUnstructuredGrid object that will become the + // union of the DataSets specified in MergeDataSet calls. + // vtkMergeCells assumes this grid is empty at first. + + virtual void SetUnstructuredGrid(vtkUnstructuredGrid*); + vtkGetObjectMacro(UnstructuredGrid, vtkUnstructuredGrid); + + // Description: + // Specify the total number of cells in the final vtkUnstructuredGrid. + // Make this call before any call to MergeDataSet(). + + vtkSetMacro(TotalNumberOfCells, vtkIdType); + vtkGetMacro(TotalNumberOfCells, vtkIdType); + + // Description: + // Specify the total number of points in the final vtkUnstructuredGrid + // Make this call before any call to MergeDataSet(). This is an + // upper bound, since some points may be duplicates. + + vtkSetMacro(TotalNumberOfPoints, vtkIdType); + vtkGetMacro(TotalNumberOfPoints, vtkIdType); + + // Description: + // vtkMergeCells attempts eliminate duplicate points when merging + // data sets. This is done most efficiently if a global point ID + // field array is available. Set the name of the point array if you + // have one. + + vtkSetStringMacro(GlobalIdArrayName); + vtkGetStringMacro(GlobalIdArrayName); + + // Description: + // vtkMergeCells attempts eliminate duplicate points when merging + // data sets. If no global point ID field array name is provided, + // it will use a point locator to find duplicate points. You can + // set a tolerance for that locator here. The default tolerance + // is 10e-4. + + vtkSetClampMacro(PointMergeTolerance, float, 0.0, .25); + vtkGetMacro(PointMergeTolerance, float); + + // Description: + // vtkMergeCells will detect and filter out duplicate cells if you + // provide it the name of a global cell ID array. + + vtkSetStringMacro(GlobalCellIdArrayName); + vtkGetStringMacro(GlobalCellIdArrayName); + + // Description: + // vtkMergeCells attempts eliminate duplicate points when merging + // data sets. If for some reason you don't want it to do this, + // than MergeDuplicatePointsOff(). + + vtkSetMacro(MergeDuplicatePoints, int); + vtkGetMacro(MergeDuplicatePoints, int); + vtkBooleanMacro(MergeDuplicatePoints, int); + + // Description: + // We need to know the number of different data sets that will + // be merged into one so we can pre-allocate some arrays. + // This can be an upper bound, not necessarily exact. + + vtkSetMacro(TotalNumberOfDataSets, int); + vtkGetMacro(TotalNumberOfDataSets, int); + + // Description: + // Provide a DataSet to be merged in to the final UnstructuredGrid. + // This call returns after the merge has completed. Be sure to call + // SetTotalNumberOfCells, SetTotalNumberOfPoints, and SetTotalNumberOfDataSets + // before making this call. Return 0 if OK, -1 if error. + + int MergeDataSet(vtkDataSet *set); + + // Description: + // Call Finish() after merging last DataSet to free unneeded memory and to + // make sure the ugrid's GetNumberOfPoints() reflects the actual + // number of points set, not the number allocated. + + void Finish(); + +protected: + + vtkMergeCells(); + ~vtkMergeCells(); + +private: + + void FreeLists(); + void StartUGrid(vtkDataSet *set); + vtkIdType *MapPointsToIdsUsingGlobalIds(vtkDataSet *set); + vtkIdType *MapPointsToIdsUsingLocator(vtkDataSet *set); + vtkIdType AddNewCellsUnstructuredGrid(vtkDataSet *set, vtkIdType *idMap); + vtkIdType AddNewCellsDataSet(vtkDataSet *set, vtkIdType *idMap); + + vtkIdType GlobalCellIdAccessGetId(vtkIdType idx); + int GlobalCellIdAccessStart(vtkDataSet *set); + vtkIdType GlobalNodeIdAccessGetId(vtkIdType idx); + int GlobalNodeIdAccessStart(vtkDataSet *set); + + int TotalNumberOfDataSets; + + vtkIdType TotalNumberOfCells; + vtkIdType TotalNumberOfPoints; + + vtkIdType NumberOfCells; // so far + vtkIdType NumberOfPoints; + + char *GlobalIdArrayName; // point, or node, IDs + int GlobalIdArrayType; + void* GlobalIdArray; + + char *GlobalCellIdArrayName; // cell IDs + int GlobalCellIdArrayType; + void* GlobalCellIdArray; + + float PointMergeTolerance; + int MergeDuplicatePoints; + + char InputIsUGrid; + char InputIsPointSet; + + vtkMergeCellsSTLCloak *GlobalIdMap; + vtkMergeCellsSTLCloak *GlobalCellIdMap; + +//BTX + vtkDataSetAttributes::FieldList *ptList; + vtkDataSetAttributes::FieldList *cellList; +//ETX + + vtkUnstructuredGrid *UnstructuredGrid; + + int nextGrid; + + vtkMergeCells(const vtkMergeCells&); // Not implemented + void operator=(const vtkMergeCells&); // Not implemented +}; +#endif diff --git a/Graphics/vtkMergeDataObjectFilter.cxx b/Graphics/vtkMergeDataObjectFilter.cxx new file mode 100644 index 0000000..68b8de3 --- /dev/null +++ b/Graphics/vtkMergeDataObjectFilter.cxx @@ -0,0 +1,184 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeDataObjectFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMergeDataObjectFilter.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkFieldData.h" +#include "vtkFieldDataToAttributeDataFilter.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkMergeDataObjectFilter, "$Revision: 1.21.12.1 $"); +vtkStandardNewMacro(vtkMergeDataObjectFilter); + +//---------------------------------------------------------------------------- +// Create object with no input or output. +vtkMergeDataObjectFilter::vtkMergeDataObjectFilter() +{ + this->OutputField = VTK_DATA_OBJECT_FIELD; + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +vtkMergeDataObjectFilter::~vtkMergeDataObjectFilter() +{ +} + +//---------------------------------------------------------------------------- +// Specify a data object at a specified table location. +void vtkMergeDataObjectFilter::SetDataObject(vtkDataObject *d) +{ + this->SetInput(1, d); +} + +//---------------------------------------------------------------------------- +// Get a pointer to a data object at a specified table location. +vtkDataObject *vtkMergeDataObjectFilter::GetDataObject() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return this->GetExecutive()->GetInputData(1, 0); +} + + +//---------------------------------------------------------------------------- +// Merge it all together +int vtkMergeDataObjectFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *dataObjectInfo = 0; + if (this->GetNumberOfInputConnections(1) > 0) + { + dataObjectInfo = inputVector[1]->GetInformationObject(0); + } + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataObject *dataObject=0; + if (dataObjectInfo) + { + dataObject = dataObjectInfo->Get(vtkDataObject::DATA_OBJECT()); + } + + vtkFieldData *fd; + + vtkDebugMacro(<<"Merging dataset and data object"); + + if (!dataObject) + { + vtkErrorMacro(<< "Data Object's Field Data is NULL."); + return 1; + } + + fd=dataObject->GetFieldData(); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( this->OutputField == VTK_CELL_DATA_FIELD ) + { + int ncells=fd->GetNumberOfTuples(); + if ( ncells != input->GetNumberOfCells() ) + { + vtkErrorMacro(<<"Field data size incompatible with number of cells"); + return 1; + } + for(int i=0; iGetNumberOfArrays(); i++) + { + output->GetCellData()->AddArray(fd->GetArray(i)); + } + } + else if ( this->OutputField == VTK_POINT_DATA_FIELD ) + { + int npts=fd->GetNumberOfTuples(); + if ( npts != input->GetNumberOfPoints() ) + { + vtkErrorMacro(<<"Field data size incompatible with number of points"); + return 1; + } + for(int i=0; iGetNumberOfArrays(); i++) + { + output->GetPointData()->AddArray(fd->GetArray(i)); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkMergeDataObjectFilter::SetOutputFieldToDataObjectField() +{ + this->SetOutputField(VTK_DATA_OBJECT_FIELD); +} + +//---------------------------------------------------------------------------- +void vtkMergeDataObjectFilter::SetOutputFieldToPointDataField() +{ + this->SetOutputField(VTK_POINT_DATA_FIELD); +} + +//---------------------------------------------------------------------------- +void vtkMergeDataObjectFilter::SetOutputFieldToCellDataField() +{ + this->SetOutputField(VTK_CELL_DATA_FIELD); +} + +//---------------------------------------------------------------------------- +int vtkMergeDataObjectFilter::FillInputPortInformation(int port, + vtkInformation *info) +{ + if (port == 0) + { + return this->Superclass::FillInputPortInformation(port, info); + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject"); + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkMergeDataObjectFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Output Field: "; + if ( this->OutputField == VTK_DATA_OBJECT_FIELD ) + { + os << "DataObjectField\n"; + } + else if ( this->OutputField == VTK_POINT_DATA_FIELD ) + { + os << "PointDataField\n"; + } + else //if ( this->OutputField == VTK_CELL_DATA_FIELD ) + { + os << "CellDataField\n"; + } + +} diff --git a/Graphics/vtkMergeDataObjectFilter.h b/Graphics/vtkMergeDataObjectFilter.h new file mode 100644 index 0000000..db07ca9 --- /dev/null +++ b/Graphics/vtkMergeDataObjectFilter.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeDataObjectFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMergeDataObjectFilter - merge dataset and data object field to create dataset with attribute data +// .SECTION Description +// vtkMergeDataObjectFilter is a filter that merges the field from a +// vtkDataObject with a vtkDataSet. The resulting combined dataset can +// then be processed by other filters (e.g., +// vtkFieldDataToAttributeDataFilter) to create attribute data like +// scalars, vectors, etc. +// +// The filter operates as follows. The field data from the +// vtkDataObject is merged with the input's vtkDataSet and then placed +// in the output. You can choose to place the field data into the cell +// data field, the point data field, or the datasets field (i.e., the +// one inherited from vtkDataSet's superclass vtkDataObject). All this +// data shuffling occurs via reference counting, therefore memory is +// not copied. +// +// One of the uses of this filter is to allow you to read/generate the +// structure of a dataset independent of the attributes. So, for +// example, you could store the dataset geometry/topology in one file, +// and field data in another. Then use this filter in combination with +// vtkFieldDataToAttributeData to create a dataset ready for +// processing in the visualization pipeline. + +#ifndef __vtkMergeDataObjectFilter_h +#define __vtkMergeDataObjectFilter_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkMergeDataObjectFilter : public vtkDataSetAlgorithm +{ +public: + static vtkMergeDataObjectFilter *New(); + vtkTypeRevisionMacro(vtkMergeDataObjectFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the data object to merge with the input dataset. + void SetDataObject(vtkDataObject *object); + vtkDataObject *GetDataObject(); + + // Description: + // Specify where to place the field data during the merge process. There + // are three choices: the field data associated with the vtkDataObject + // superclass; the point field attribute data; and the cell field attribute + // data. + vtkSetMacro(OutputField,int); + vtkGetMacro(OutputField,int); + void SetOutputFieldToDataObjectField(); + void SetOutputFieldToPointDataField(); + void SetOutputFieldToCellDataField(); + +protected: + vtkMergeDataObjectFilter(); + ~vtkMergeDataObjectFilter(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int FillInputPortInformation(int port, vtkInformation *info); + + int OutputField; // which output field + +private: + vtkMergeDataObjectFilter(const vtkMergeDataObjectFilter&); // Not implemented. + void operator=(const vtkMergeDataObjectFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkMergeFields.cxx b/Graphics/vtkMergeFields.cxx new file mode 100644 index 0000000..9794274 --- /dev/null +++ b/Graphics/vtkMergeFields.cxx @@ -0,0 +1,449 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeFields.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMergeFields.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDataSetAttributes.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkMergeFields, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkMergeFields); + +char vtkMergeFields::FieldLocationNames[3][12] += { "DATA_OBJECT", + "POINT_DATA", + "CELL_DATA" }; + +typedef vtkMergeFields::Component Component; + +vtkMergeFields::vtkMergeFields() +{ + this->FieldName = 0; + this->FieldLocation = -1; + this->NumberOfComponents = 0; + + this->Head = 0; + this->Tail = 0; +} + +vtkMergeFields::~vtkMergeFields() +{ + delete[] this->FieldName; + this->FieldName = 0; + this->DeleteAllComponents(); +} + +void vtkMergeFields::SetOutputField(const char* name, int fieldLoc) +{ + if (!name) + { + return; + } + + if ( (fieldLoc != vtkMergeFields::DATA_OBJECT) && + (fieldLoc != vtkMergeFields::POINT_DATA) && + (fieldLoc != vtkMergeFields::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return; + } + + this->Modified(); + this->FieldLocation = fieldLoc; + + delete[] this->FieldName; + this->FieldName = new char[strlen(name)+1]; + strcpy(this->FieldName, name); +} + + +void vtkMergeFields::SetOutputField(const char* name, const char* fieldLoc) +{ + if ( !name || !fieldLoc) + { + return; + } + + int numFieldLocs = 3; + int i; + + // Convert fieldLoc to int an call the other SetOutputField() + int loc=-1; + for(i=0; iSetOutputField(name, loc); + +} + +void vtkMergeFields::Merge(int component, const char* arrayName, + int sourceComp) +{ + if (!arrayName) + { + return; + } + + this->Modified(); + Component* comp = this->FindComponent(component); + if ( comp ) + { + // If component already exists, replace information + comp->SetName(arrayName); + comp->SourceIndex = sourceComp; + } + else + { + // otherwise create a new one + comp = new Component; + comp->SetName(arrayName); + comp->Index = component; + comp->SourceIndex = sourceComp; + this->AddComponent(comp); + } +} + +int vtkMergeFields::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // This has to be here because it initialized all field datas. + output->CopyStructure( input ); + + // Pass all. (data object's field data is passed by the + // superclass after this method) + output->GetPointData()->PassData( input->GetPointData() ); + output->GetCellData()->PassData( input->GetCellData() ); + + vtkFieldData* fd = 0; + vtkFieldData* outputFD = 0; + Component* cur = this->GetFirst(); + Component* before; + + if (!cur) { return 1; } + + // Get the input and output field data + if ( this->FieldLocation == vtkMergeFields::DATA_OBJECT) + { + fd = input->GetFieldData(); + outputFD = output->GetFieldData(); + if (!fd || !outputFD) + { + vtkErrorMacro("No field data in vtkDataObject."); + return 1; + } + } + else if ( this->FieldLocation == vtkMergeFields::POINT_DATA ) + { + fd = input->GetPointData(); + outputFD = output->GetPointData(); + } + else if ( this->FieldLocation == vtkMergeFields::CELL_DATA ) + { + fd = input->GetCellData(); + outputFD = output->GetCellData(); + } + + // Check if the data types of the input fields are the same + // Otherwise warn the user. + // Check if the number of tuples are the same for all arrays. + vtkDataArray* inputArray; + int dataType=-1; + int sameDataType=1; + int numTuples=-1; + int sameNumTuples=1; + do + { + before = cur; + cur = cur->Next; + inputArray = fd->GetArray(before->FieldName); + if (!inputArray) + { + continue; + } + else + { + if (dataType == -1) + { + dataType = inputArray->GetDataType(); + } + else + { + if ( inputArray->GetDataType() != dataType ) + { + sameDataType = 0; + } + } + if (numTuples == -1) + { + numTuples = inputArray->GetNumberOfTuples(); + } + else + { + if ( inputArray->GetNumberOfTuples() != numTuples ) + { + sameNumTuples = 0; + } + } + } + } + while (cur); + if (!sameNumTuples) + { + vtkErrorMacro("The number of tuples in the input arrays do not match."); + return 1; + } + if ( dataType == -1 ) + { + vtkErrorMacro("No input array(s) were found."); + return 1; + } + vtkDataArray* outputArray; + if (!sameDataType) + { + vtkWarningMacro("The input data types do not match. The output will be "<< + "float. This will potentially cause accuracy and speed."); + outputArray = vtkFloatArray::New(); + } + else + { + outputArray = vtkDataArray::CreateDataArray(dataType); + } + + if (this->NumberOfComponents <= 0) + { + vtkErrorMacro("NumberOfComponents has be set prior to the execution of " + "this filter"); + } + + outputArray->SetNumberOfComponents(this->NumberOfComponents); + outputArray->SetNumberOfTuples(numTuples); + outputArray->SetName(this->FieldName); + + // Merge + cur = this->GetFirst(); + do + { + before = cur; + cur = cur->Next; + inputArray = fd->GetArray(before->FieldName); + if (inputArray) + { + if (!this->MergeArray(inputArray, outputArray, + before->SourceIndex, before->Index)) + { + outputArray->Delete(); + return 1; + } + } + else + { + if (before->FieldName) + { + vtkWarningMacro("Input array " << before->FieldName + << " does not exist."); + } + continue; + } + } + while (cur); + outputFD->AddArray(outputArray); + outputArray->Delete(); + + return 1; +} + +// fast pointer copy +template +void vtkMergeFieldsCopyTuples(T* input, T* output, vtkIdType numTuples, + int numInComp, int numOutComp, int inComp, int outComp) +{ + for (int i=0; i in->GetNumberOfComponents()) || + (outComp < 0) || (outComp > out->GetNumberOfComponents()) ) + { + vtkErrorMacro("Invalid component. Can not merge."); + return 0; + } + + int numTuples = in->GetNumberOfTuples(); + int i; + + if ( numTuples > 0 ) + { + // If data types match, use templated, fast method + if ( in->GetDataType() == out->GetDataType() ) + { + switch (out->GetDataType()) + { + vtkTemplateMacro( + vtkMergeFieldsCopyTuples((VTK_TT *)in->GetVoidPointer(0), + (VTK_TT *)out->GetVoidPointer(0), numTuples, + in->GetNumberOfComponents(), + out->GetNumberOfComponents(), + inComp, outComp )); + // This is not supported by the template macro. + // Switch to using the float interface. + case VTK_BIT: + { + for(i=0; iSetComponent(i, outComp, in->GetComponent(i, inComp)); + } + } + break; + default: + vtkErrorMacro(<<"Sanity check failed: Unsupported data type."); + return 0; + } + } + // otherwise use slow float copy + else + { + for(i=0; iSetComponent(i, outComp, in->GetComponent(i, inComp)); + } + } + } + + return 1; + +} + +// linked list methods +void vtkMergeFields::AddComponent(Component* op) +{ + op->Next = 0; + + if (!this->Head) + { + this->Head = op; + this->Tail = op; + return; + } + this->Tail->Next = op; + this->Tail = op; +} + +Component* vtkMergeFields::FindComponent(int index) +{ + Component* cur = this->GetFirst(); + if (!cur) { return 0; } + + if (cur->Index == index) { return cur; } + while (cur->Next) + { + if (cur->Next->Index == index) + { + return cur->Next; + } + cur = cur->Next; + } + return 0; +} + +void vtkMergeFields::DeleteAllComponents() +{ + Component* cur = this->GetFirst(); + if (!cur) {return;} + Component* before; + do + { + before = cur; + cur = cur->Next; + delete before; + } + while (cur); + this->Head = 0; + this->Tail = 0; +} + +void vtkMergeFields::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Field name: "; + if (this->FieldName) + { + os << this->FieldName << endl; + } + else + { + os << "(none)" << endl; + } + os << indent << "Field location: " << this->FieldLocation << endl; + os << indent << "Linked list head: " << this->Head << endl; + os << indent << "Linked list tail: " << this->Tail << endl; + os << indent << "NumberOfComponents: " << this->NumberOfComponents << endl; + os << indent << "Components: " << endl; + this->PrintAllComponents(os, indent.GetNextIndent()); +} + +void vtkMergeFields::PrintComponent(Component* op, ostream& os, vtkIndent indent) +{ + os << indent << "Field name: " << op->FieldName << endl; + os << indent << "Component index: " << op->Index << endl; + os << indent << "Source component index: " << op->SourceIndex << endl; +} + +void vtkMergeFields::PrintAllComponents(ostream& os, vtkIndent indent) +{ + Component* cur = this->GetFirst(); + if (!cur) { return; } + Component* before; + do + { + before = cur; + cur = cur->Next; + os << endl; + this->PrintComponent(before, os, indent); + } + while (cur); +} diff --git a/Graphics/vtkMergeFields.h b/Graphics/vtkMergeFields.h new file mode 100644 index 0000000..32932e9 --- /dev/null +++ b/Graphics/vtkMergeFields.h @@ -0,0 +1,158 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeFields.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMergeFields - Merge multiple fields into one. +// .SECTION Description +// vtkMergeFields is used to merge mutliple field into one. +// The new field is put in the same field data as the original field. +// For example +// @verbatim +// mf->SetOutputField("foo", vtkMergeFields::POINT_DATA); +// mf->SetNumberOfComponents(2); +// mf->Merge(0, "array1", 1); +// mf->Merge(1, "array2", 0); +// @endverbatim +// will tell vtkMergeFields to use the 2nd component of array1 and +// the 1st component of array2 to create a 2 component field called foo. +// The same can be done using Tcl: +// @verbatim +// mf SetOutputField foo POINT_DATA +// mf Merge 0 array1 1 +// mf Merge 1 array2 0 +// +// Field locations: DATA_OBJECT, POINT_DATA, CELL_DATA +// @endverbatim + +// .SECTION See Also +// vtkFieldData vtkDataSet vtkDataObjectToDataSetFilter +// vtkDataSetAttributes vtkDataArray vtkRearrangeFields +// vtkSplitField vtkAssignAttribute + +#ifndef __vtkMergeFields_h +#define __vtkMergeFields_h + +#include "vtkDataSetAlgorithm.h" + +class vtkDataArray; +class vtkFieldData; + +class VTK_GRAPHICS_EXPORT vtkMergeFields : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkMergeFields,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a new vtkMergeFields. + static vtkMergeFields *New(); + + // Description: + // The output field will have the given name and it will be in + // fieldLoc (the input fields also have to be in fieldLoc). + void SetOutputField(const char* name, int fieldLoc); + + // Description: + // Helper method used by the other language bindings. Allows the caller to + // specify arguments as strings instead of enums.Returns an operation id + // which can later be used to remove the operation. + void SetOutputField(const char* name, const char* fieldLoc); + + // Description: + // Add a component (arrayName,sourceComp) to the output field. + void Merge(int component, const char* arrayName, int sourceComp); + + // Description: + // Set the number of the components in the output field. + // This has to be set before execution. Default value is 0. + vtkSetMacro(NumberOfComponents, int); + +//BTX + enum FieldLocations + { + DATA_OBJECT=0, + POINT_DATA=1, + CELL_DATA=2 + }; +//ETX + +//BTX + struct Component + { + int Index; + int SourceIndex; + char* FieldName; + Component* Next; // linked list + void SetName(const char* name) + { + delete[] this->FieldName; + this->FieldName = 0; + if (name) + { + this->FieldName = new char[strlen(name)+1]; + strcpy(this->FieldName, name); + } + } + Component() { FieldName = 0; } + ~Component() { delete[] FieldName; } + }; +//ETX + +protected: + +//BTX + enum FieldType + { + NAME, + ATTRIBUTE + }; +//ETX + + vtkMergeFields(); + virtual ~vtkMergeFields(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char* FieldName; + int FieldLocation; + int NumberOfComponents; + int OutputDataType; + + static char FieldLocationNames[3][12]; + + + int MergeArray(vtkDataArray* in, vtkDataArray* out, int inComp, int outComp); + + // Components are stored as a linked list. + Component* Head; + Component* Tail; + + // Methods to browse/modify the linked list. + Component* GetNextComponent(Component* op) + { return op->Next; } + Component* GetFirst() + { return this->Head; } + void AddComponent(Component* op); + Component* FindComponent(int index); + void DeleteAllComponents(); + + void PrintComponent(Component* op, ostream& os, vtkIndent indent); + void PrintAllComponents(ostream& os, vtkIndent indent); +private: + vtkMergeFields(const vtkMergeFields&); // Not implemented. + void operator=(const vtkMergeFields&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkMergeFilter.cxx b/Graphics/vtkMergeFilter.cxx new file mode 100644 index 0000000..dd1e7c5 --- /dev/null +++ b/Graphics/vtkMergeFilter.cxx @@ -0,0 +1,523 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMergeFilter.h" + +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkMergeFilter, "$Revision: 1.69 $"); +vtkStandardNewMacro(vtkMergeFilter); + +class vtkFieldNode +{ +public: + vtkFieldNode(const char* name, vtkDataSet* ptr=0) + { + int length = static_cast(strlen(name)); + if (length > 0) + { + this->Name = new char[length+1]; + strcpy(this->Name, name); + } + else + { + this->Name = 0; + } + this->Ptr = ptr; + this->Next = 0; + } + ~vtkFieldNode() + { + delete[] this->Name; + } + + const char* GetName() + { + return Name; + } + vtkDataSet* Ptr; + vtkFieldNode* Next; +private: + vtkFieldNode(const vtkFieldNode&) {} + void operator=(const vtkFieldNode&) {} + char* Name; +}; + +class vtkFieldList +{ +public: + vtkFieldList() + { + this->First = 0; + this->Last = 0; + } + ~vtkFieldList() + { + vtkFieldNode* node = this->First; + vtkFieldNode* next; + while(node) + { + next = node->Next; + delete node; + node = next; + } + } + + + void Add(const char* name, vtkDataSet* ptr) + { + vtkFieldNode* newNode = new vtkFieldNode(name, ptr); + if (!this->First) + { + this->First = newNode; + this->Last = newNode; + } + else + { + this->Last->Next = newNode; + this->Last = newNode; + } + } + + friend class vtkFieldListIterator; + +private: + vtkFieldNode* First; + vtkFieldNode* Last; +}; + +class vtkFieldListIterator +{ +public: + vtkFieldListIterator(vtkFieldList* list) + { + this->List = list; + this->Position = 0; + } + void Begin() + { + this->Position = this->List->First; + } + void Next() + { + if (this->Position) + { + this->Position = this->Position->Next; + } + } + int End() + { + return this->Position ? 0 : 1; + } + vtkFieldNode* Get() + { + return this->Position; + } + +private: + vtkFieldNode* Position; + vtkFieldList* List; +}; + +//------------------------------------------------------------------------------ + +// Create object with no input or output. +vtkMergeFilter::vtkMergeFilter() +{ + this->FieldList = new vtkFieldList; + this->SetNumberOfInputPorts(6); +} + +vtkMergeFilter::~vtkMergeFilter() +{ + delete this->FieldList; +} + +vtkDataSet* vtkMergeFilter::GetGeometry() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return NULL; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +void vtkMergeFilter::SetScalars(vtkDataSet *input) +{ + this->SetInput(1, input); +} +vtkDataSet *vtkMergeFilter::GetScalars() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +void vtkMergeFilter::SetVectors(vtkDataSet *input) +{ + this->SetInput(2, input); +} +vtkDataSet *vtkMergeFilter::GetVectors() +{ + if (this->GetNumberOfInputConnections(2) < 1) + { + return NULL; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(2, 0)); +} + +void vtkMergeFilter::SetNormals(vtkDataSet *input) +{ + this->SetInput(3, input); +} +vtkDataSet *vtkMergeFilter::GetNormals() +{ + if (this->GetNumberOfInputConnections(3) < 1) + { + return NULL; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(3, 0)); +} + +void vtkMergeFilter::SetTCoords(vtkDataSet *input) +{ + this->SetInput(4, input); +} +vtkDataSet *vtkMergeFilter::GetTCoords() +{ + if (this->GetNumberOfInputConnections(4) < 1) + { + return NULL; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(4, 0)); +} + +void vtkMergeFilter::SetTensors(vtkDataSet *input) +{ + this->SetInput(5, input); +} +vtkDataSet *vtkMergeFilter::GetTensors() +{ + if (this->GetNumberOfInputConnections(5) < 1) + { + return NULL; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(5, 0)); +} + +void vtkMergeFilter::AddField(const char* name, vtkDataSet* input) +{ + this->FieldList->Add(name, input); +} + +int vtkMergeFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *scalarsInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *vectorsInfo = inputVector[2]->GetInformationObject(0); + vtkInformation *normalsInfo = inputVector[3]->GetInformationObject(0); + vtkInformation *tCoordsInfo = inputVector[4]->GetInformationObject(0); + vtkInformation *tensorsInfo = inputVector[5]->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *scalarsData = 0; + vtkDataSet *vectorsData = 0; + vtkDataSet *normalsData = 0; + vtkDataSet *tCoordsData = 0; + vtkDataSet *tensorsData = 0; + if (scalarsInfo) + { + scalarsData = vtkDataSet::SafeDownCast( + scalarsInfo->Get(vtkDataObject::DATA_OBJECT())); + } + if (vectorsInfo) + { + vectorsData = vtkDataSet::SafeDownCast( + vectorsInfo->Get(vtkDataObject::DATA_OBJECT())); + } + if (normalsInfo) + { + normalsData = vtkDataSet::SafeDownCast( + normalsInfo->Get(vtkDataObject::DATA_OBJECT())); + } + if (tCoordsInfo) + { + tCoordsData = vtkDataSet::SafeDownCast( + tCoordsInfo->Get(vtkDataObject::DATA_OBJECT())); + } + if (tensorsInfo) + { + tensorsData = vtkDataSet::SafeDownCast( + tensorsInfo->Get(vtkDataObject::DATA_OBJECT())); + } + + vtkIdType numPts, numScalars=0, numVectors=0, numNormals=0, numTCoords=0; + vtkIdType numTensors=0; + vtkIdType numCells, numCellScalars=0, numCellVectors=0, numCellNormals=0; + vtkIdType numCellTCoords=0, numCellTensors=0; + vtkPointData *pd; + vtkDataArray *scalars = NULL; + vtkDataArray *vectors = NULL; + vtkDataArray *normals = NULL; + vtkDataArray *tcoords = NULL; + vtkDataArray *tensors = NULL; + vtkCellData *cd; + vtkDataArray *cellScalars = NULL; + vtkDataArray *cellVectors = NULL; + vtkDataArray *cellNormals = NULL; + vtkDataArray *cellTCoords = NULL; + vtkDataArray *cellTensors = NULL; + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + + vtkDebugMacro(<<"Merging data!"); + + // geometry needs to be copied + output->CopyStructure(input); + if ( (numPts = input->GetNumberOfPoints()) < 1 ) + { + vtkWarningMacro(<<"Nothing to merge!"); + } + numCells = input->GetNumberOfCells(); + + if ( scalarsData ) + { + pd = scalarsData->GetPointData(); + scalars = pd->GetScalars(); + if ( scalars != NULL ) + { + numScalars = scalars->GetNumberOfTuples(); + } + cd = scalarsData->GetCellData(); + cellScalars = cd->GetScalars(); + if ( cellScalars != NULL ) + { + numCellScalars = cellScalars->GetNumberOfTuples(); + } + } + + if ( vectorsData ) + { + pd = vectorsData->GetPointData(); + vectors = pd->GetVectors(); + if ( vectors != NULL ) + { + numVectors= vectors->GetNumberOfTuples(); + } + cd = vectorsData->GetCellData(); + cellVectors = cd->GetVectors(); + if ( cellVectors != NULL ) + { + numCellVectors = cellVectors->GetNumberOfTuples(); + } + } + + if ( normalsData ) + { + pd = normalsData->GetPointData(); + normals = pd->GetNormals(); + if ( normals != NULL ) + { + numNormals= normals->GetNumberOfTuples(); + } + cd = normalsData->GetCellData(); + cellNormals = cd->GetNormals(); + if ( cellNormals != NULL ) + { + numCellNormals = cellNormals->GetNumberOfTuples(); + } + } + + if ( tCoordsData ) + { + pd = tCoordsData->GetPointData(); + tcoords = pd->GetTCoords(); + if ( tcoords != NULL ) + { + numTCoords= tcoords->GetNumberOfTuples(); + } + cd = tCoordsData->GetCellData(); + cellTCoords = cd->GetTCoords(); + if ( cellTCoords != NULL ) + { + numCellTCoords = cellTCoords->GetNumberOfTuples(); + } + } + + if ( tensorsData ) + { + pd = tensorsData->GetPointData(); + tensors = pd->GetTensors(); + if ( tensors != NULL ) + { + numTensors = tensors->GetNumberOfTuples(); + } + cd = tensorsData->GetCellData(); + cellTensors = cd->GetTensors(); + if ( cellTensors != NULL ) + { + numCellTensors = cellTensors->GetNumberOfTuples(); + } + } + + // merge data only if it is consistent + if ( numPts == numScalars ) + { + outputPD->SetScalars(scalars); + } + if ( numCells == numCellScalars ) + { + outputCD->SetScalars(cellScalars); + } + + if ( numPts == numVectors ) + { + outputPD->SetVectors(vectors); + } + if ( numCells == numCellVectors ) + { + outputCD->SetVectors(cellVectors); + } + + if ( numPts == numNormals ) + { + outputPD->SetNormals(normals); + } + if ( numCells == numCellNormals ) + { + outputCD->SetNormals(cellNormals); + } + + if ( numPts == numTCoords ) + { + outputPD->SetTCoords(tcoords); + } + if ( numCells == numCellTCoords ) + { + outputCD->SetTCoords(cellTCoords); + } + + if ( numPts == numTensors ) + { + outputPD->SetTensors(tensors); + } + if ( numCells == numCellTensors ) + { + outputCD->SetTensors(cellTensors); + } + + vtkFieldListIterator it(this->FieldList); + vtkDataArray* da; + const char* name; + vtkIdType num; + for(it.Begin(); !it.End() ; it.Next()) + { + pd = it.Get()->Ptr->GetPointData(); + cd = it.Get()->Ptr->GetCellData(); + name = it.Get()->GetName(); + if ( (da=pd->GetArray(name)) ) + { + num = da->GetNumberOfTuples(); + if (num == numPts) + { + outputPD->AddArray(da); + } + } + if ( (da=cd->GetArray(name)) ) + { + num = da->GetNumberOfTuples(); + if (num == numPts) + { + outputCD->AddArray(da); + } + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Trick: Abstract data types that may or may not be the same type +// (structured/unstructured), but the points/cells match up. +// Output/Geometry may be structured while ScalarInput may be +// unstructured (but really have same triagulation/topology as geometry). +// Just request all the input. Always generate all of the output (todo). +int vtkMergeFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + vtkInformation *inputInfo; + int idx; + + for (idx = 0; idx < 6; ++idx) + { + inputInfo = inputVector[idx]->GetInformationObject(0); + if (inputInfo) + { + inputInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + inputInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + inputInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + inputInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + } + } + return 1; +} + +int vtkMergeFilter::FillInputPortInformation(int port, vtkInformation *info) +{ + int retval = this->Superclass::FillInputPortInformation(port, info); + if (port > 0) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + return retval; +} + +void vtkMergeFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + +} + diff --git a/Graphics/vtkMergeFilter.h b/Graphics/vtkMergeFilter.h new file mode 100644 index 0000000..66d2ccd --- /dev/null +++ b/Graphics/vtkMergeFilter.h @@ -0,0 +1,145 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMergeFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMergeFilter - extract separate components of data from different datasets +// .SECTION Description +// vtkMergeFilter is a filter that extracts separate components of data from +// different datasets and merges them into a single dataset. The output from +// this filter is of the same type as the input (i.e., vtkDataSet.) It treats +// both cell and point data set attributes. + +#ifndef __vtkMergeFilter_h +#define __vtkMergeFilter_h + +#include "vtkDataSetAlgorithm.h" + +class vtkFieldList; + +class VTK_GRAPHICS_EXPORT vtkMergeFilter : public vtkDataSetAlgorithm +{ +public: + static vtkMergeFilter *New(); + vtkTypeRevisionMacro(vtkMergeFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify object from which to extract geometry information. + // Old style. Use SetGeometryConnection() instead. + void SetGeometry(vtkDataSet *input) {this->SetInput(input);}; + vtkDataSet *GetGeometry(); + + // Description: + // Specify object from which to extract geometry information. + // Equivalent to SetInputConnection(0, algOutput) + void SetGeometryConnection(vtkAlgorithmOutput* algOutput) + { + this->SetInputConnection(algOutput); + } + + // Description: + // Specify object from which to extract scalar information. + // Old style. Use SetScalarsConnection() instead. + void SetScalars(vtkDataSet *); + vtkDataSet *GetScalars(); + + // Description: + // Specify object from which to extract scalar information. + // Equivalent to SetInputConnection(1, algOutput) + void SetScalarsConnection(vtkAlgorithmOutput* algOutput) + { + this->SetInputConnection(1, algOutput); + } + + // Description: + // Set / get the object from which to extract vector information. + // Old style. Use SetVectorsConnection() instead. + void SetVectors(vtkDataSet *); + vtkDataSet *GetVectors(); + + // Description: + // Set the connection from which to extract vector information. + // Equivalent to SetInputConnection(2, algOutput) + void SetVectorsConnection(vtkAlgorithmOutput* algOutput) + { + this->SetInputConnection(2, algOutput); + } + + // Description: + // Set / get the object from which to extract normal information. + // Old style. Use SetNormalsConnection() instead. + void SetNormals(vtkDataSet *); + vtkDataSet *GetNormals(); + + // Description: + // Set the connection from which to extract normal information. + // Equivalent to SetInputConnection(3, algOutput) + void SetNormalsConnection(vtkAlgorithmOutput* algOutput) + { + this->SetInputConnection(3, algOutput); + } + + // Description: + // Set / get the object from which to extract texture coordinates + // information. + // Old style. Use SetTCoordsConnection() instead. + void SetTCoords(vtkDataSet *); + vtkDataSet *GetTCoords(); + + // Description: + // Set the connection from which to extract texture coordinates + // information. + // Equivalent to SetInputConnection(4, algOutput) + void SetTCoordsConnection(vtkAlgorithmOutput* algOutput) + { + this->SetInputConnection(4, algOutput); + } + + // Description: + // Set / get the object from which to extract tensor data. + // Old style. Use SetTensorsConnection() instead. + void SetTensors(vtkDataSet *); + vtkDataSet *GetTensors(); + + // Description: + // Set the connection from which to extract tensor data. + // Equivalent to SetInputConnection(5, algOutput) + void SetTensorsConnection(vtkAlgorithmOutput* algOutput) + { + this->SetInputConnection(5, algOutput); + } + + // Description: + // Set the object from which to extract a field and the name + // of the field. Note that this does not create pipeline + // connectivity. + void AddField(const char* name, vtkDataSet* input); + +protected: + vtkMergeFilter(); + ~vtkMergeFilter(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int FillInputPortInformation(int port, vtkInformation *info); + + vtkFieldList* FieldList; +private: + vtkMergeFilter(const vtkMergeFilter&); // Not implemented. + void operator=(const vtkMergeFilter&); // Not implemented. + }; + +#endif + + diff --git a/Graphics/vtkMeshQuality.cxx b/Graphics/vtkMeshQuality.cxx new file mode 100644 index 0000000..dbf74b4 --- /dev/null +++ b/Graphics/vtkMeshQuality.cxx @@ -0,0 +1,1476 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMeshQuality.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkMeshQuality.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkDataSet.h" +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDoubleArray.h" +#include "vtkCell.h" +#include "vtkCellTypes.h" +#include "vtkPoints.h" +#include "vtkMath.h" +#include "vtkTetra.h" + +vtkCxxRevisionMacro(vtkMeshQuality,"$Revision: 1.31 $"); +vtkStandardNewMacro(vtkMeshQuality); + +typedef double (*CellQualityType)( vtkCell* ); + +double TetVolume( vtkCell* cell ); + +const char* QualityMeasureNames[] = +{ + "EdgeRatio", + "AspectRatio", + "RadiusRatio", + "FrobeniusNorm", + "MedFrobeniusNorm", + "MaxFrobeniusNorm", + "MinAngle" +}; + +void vtkMeshQuality::PrintSelf(ostream& os, vtkIndent indent ) +{ + const char onStr[] = "On"; + const char offStr[] = "Off"; + + this->Superclass::PrintSelf( os, indent ); + + os << indent << "SaveCellQuality: " + << (this->SaveCellQuality ? onStr : offStr) << endl; + os << indent << "TriangleQualityMeasure: " + << QualityMeasureNames[this->TriangleQualityMeasure] << endl; + os << indent << "QuadQualityMeasure: " + << QualityMeasureNames[this->QuadQualityMeasure] << endl; + os << indent << "TetQualityMeasure: " + << QualityMeasureNames[this->TetQualityMeasure] << endl; + os << indent << "HexQualityMeasure: " + << QualityMeasureNames[this->HexQualityMeasure] << endl; + os << indent << "Volume: " + << (this->Volume ? onStr : offStr) << endl; + os << indent << "CompatibilityMode: " + << (this->CompatibilityMode ? onStr : offStr) << endl; +} + +vtkMeshQuality::vtkMeshQuality() +{ + this->SaveCellQuality = 1; // Default is On + this->TriangleQualityMeasure = VTK_QUALITY_ASPECT_RATIO; + this->QuadQualityMeasure = VTK_QUALITY_EDGE_RATIO; + this->TetQualityMeasure = VTK_QUALITY_ASPECT_RATIO; + this->HexQualityMeasure = VTK_QUALITY_EDGE_RATIO; + this->Volume = 0; + this->CompatibilityMode = 0; +} + +vtkMeshQuality::~vtkMeshQuality() +{ + // Nothing yet. +} + +int vtkMeshQuality::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *in = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *out = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + CellQualityType TriangleQuality,QuadQuality,TetQuality,HexQuality; + vtkDoubleArray* quality = 0; + vtkDoubleArray* volume = 0; + vtkIdType N = in->GetNumberOfCells(); + double qtrim,qtriM,Eqtri,Eqtri2; + double qquam,qquaM,Eqqua,Eqqua2; + double qtetm,qtetM,Eqtet,Eqtet2; + double qhexm,qhexM,Eqhex,Eqhex2; + double q; + double V = 0.; + vtkIdType ntri = 0; + vtkIdType nqua = 0; + vtkIdType ntet = 0; + vtkIdType nhex = 0; + vtkCell* cell; + + // Initialize the min and max values, std deviations, etc. + qtriM = qquaM = qtetM = qhexM = VTK_DOUBLE_MIN; + qtrim = qquam = qtetm = qhexm = VTK_DOUBLE_MAX; + Eqtri = Eqtri2 = Eqqua = Eqqua2 = Eqtet = Eqtet2 = Eqhex = Eqhex2 = 0.; + + switch ( this->GetTriangleQualityMeasure() ) + { + case VTK_QUALITY_EDGE_RATIO: + TriangleQuality = TriangleEdgeRatio; + break; + case VTK_QUALITY_ASPECT_RATIO: + TriangleQuality = TriangleAspectRatio; + break; + case VTK_QUALITY_RADIUS_RATIO: + TriangleQuality = TriangleRadiusRatio; + break; + case VTK_QUALITY_FROBENIUS_NORM: + TriangleQuality = TriangleFrobeniusNorm; + break; + case VTK_QUALITY_MIN_ANGLE: + TriangleQuality = TriangleMinAngle; + break; + default: + vtkWarningMacro( "Bad TriangleQualityMeasure (" + << this->GetTriangleQualityMeasure() << "), using RadiusRatio instead"); + TriangleQuality = TriangleRadiusRatio; + break; + } + + switch ( this->GetQuadQualityMeasure() ) + { + case VTK_QUALITY_EDGE_RATIO: + QuadQuality = QuadEdgeRatio; + break; + case VTK_QUALITY_ASPECT_RATIO: + QuadQuality = QuadAspectRatio; + break; + case VTK_QUALITY_RADIUS_RATIO: + QuadQuality = QuadRadiusRatio; + break; + case VTK_QUALITY_MED_FROBENIUS_NORM: + QuadQuality = QuadMedFrobeniusNorm; + break; + case VTK_QUALITY_MAX_FROBENIUS_NORM: + QuadQuality = QuadMaxFrobeniusNorm; + break; + case VTK_QUALITY_MIN_ANGLE: + QuadQuality = QuadMinAngle; + break; + default: + vtkWarningMacro( "Bad QuadQualityMeasure (" + << this->GetQuadQualityMeasure() << "), using EdgeRatio instead"); + QuadQuality = QuadEdgeRatio; + break; + } + + switch ( this->GetTetQualityMeasure() ) + { + case VTK_QUALITY_EDGE_RATIO: + TetQuality = TetEdgeRatio; + break; + case VTK_QUALITY_ASPECT_RATIO: + TetQuality = TetAspectRatio; + break; + case VTK_QUALITY_RADIUS_RATIO: + TetQuality = TetRadiusRatio; + break; + case VTK_QUALITY_FROBENIUS_NORM: + TetQuality = TetFrobeniusNorm; + break; + case VTK_QUALITY_MIN_ANGLE: + TetQuality = TetMinAngle; + break; + default: + vtkWarningMacro( "Bad TetQualityMeasure (" + << this->GetTetQualityMeasure() << "), using RadiusRatio instead"); + TetQuality = TetRadiusRatio; + break; + } + + switch ( this->GetHexQualityMeasure() ) + { + case VTK_QUALITY_EDGE_RATIO: + HexQuality = HexEdgeRatio; + break; + default: + vtkWarningMacro( "Bad HexQualityMeasure (" + << this->GetTetQualityMeasure() << "), using EdgeRatio instead"); + HexQuality = HexEdgeRatio; + break; + } + + out->ShallowCopy( in ); + + if ( this->SaveCellQuality ) + { + quality = vtkDoubleArray::New(); + if ( this->CompatibilityMode ) + { + if ( this->Volume ) + { + quality->SetNumberOfComponents(2); + } + else + { + quality->SetNumberOfComponents(1); + } + } + else + { + quality->SetNumberOfComponents(1); + } + quality->SetNumberOfTuples( N ); + quality->SetName( "Quality" ); + out->GetCellData()->AddArray( quality ); + out->GetCellData()->SetActiveAttribute( "Quality", vtkDataSetAttributes::SCALARS ); + quality->Delete(); + + if ( ! this->CompatibilityMode ) + { + if ( this->Volume ) + { + volume = vtkDoubleArray::New(); + volume->SetNumberOfComponents(1); + volume->SetNumberOfTuples( N ); + volume->SetName( "Volume" ); + out->GetCellData()->AddArray( volume ); + volume->Delete(); + } + } + } + + int p; + vtkIdType c = 0; + vtkIdType sz = N < 19 ? 1 : N / 19; + vtkIdType inner; + this->UpdateProgress( 0.01 ); + for ( p = 0; p < 20; ++p ) + { + for ( inner = 0; (inner < sz && c < N); ++c, ++inner ) + { + cell = out->GetCell( c ); + V = 0.; + switch ( cell->GetCellType() ) + { + case VTK_TRIANGLE: + q = TriangleQuality( cell ); + if ( q > qtriM ) + { + if ( qtrim > qtriM ) + { + qtrim = q; + } + qtriM = q; + } + else if ( q < qtrim ) + { + qtrim = q; + } + Eqtri += q; + Eqtri2 += q * q; + ntri++; + break; + case VTK_QUAD: + q = QuadQuality( cell ); + if ( q > qquaM ) + { + if ( qquam > qquaM ) + { + qquam = q; + } + qquaM = q; + } + else if ( q < qquam ) + { + qquam = q; + } + Eqqua += q; + Eqqua2 += q * q; + nqua++; + break; + case VTK_TETRA: + q = TetQuality( cell ); + if ( q > qtetM ) + { + if ( qtetm > qtetM ) + { + qtetm = q; + } + qtetM = q; + } + else if ( q < qtetm ) + { + qtetm = q; + } + Eqtet += q; + Eqtet2 += q * q; + ntet++; + if ( this->Volume ) + { + V = TetVolume( cell ); + if ( ! this->CompatibilityMode ) + { + volume->SetTuple1( 0, V ); + } + } + break; + case VTK_HEXAHEDRON: + q = HexQuality( cell ); + if ( q > qhexM ) + { + if ( qhexm > qhexM ) + { + qhexm = q; + } + qhexM = q; + } + else if ( q < qhexm ) + { + qhexm = q; + } + Eqhex += q; + Eqhex2 += q * q; + nhex++; + break; + default: + q = 0.; + } + + if ( this->SaveCellQuality ) + { + if ( this->CompatibilityMode && this->Volume ) + { + quality->SetTuple2( c, V, q ); + } + else + { + quality->SetTuple1( c, q ); + } + } + } + this->UpdateProgress( double(p+1)/20. ); + } + + if ( ntri ) + { + Eqtri /= (double) ntri; + Eqtri2 /= (double) ntri; + } + else + { + qtrim = Eqtri = qtriM = Eqtri2 = 0.; + } + + if ( nqua ) + { + Eqqua /= (double) nqua; + Eqqua2 /= (double) nqua; + } + else + { + qquam = Eqqua = qquaM = Eqqua2 = 0.; + } + + if ( ntet ) + { + Eqtet /= (double) ntet; + Eqtet2 /= (double) ntet; + } + else + { + qtetm = Eqtet = qtetM = Eqtet2 = 0.; + } + + if ( nhex ) + { + Eqhex /= (double) nhex; + Eqhex2 /= (double) nhex; + } + else + { + qhexm = Eqhex = qhexM = Eqhex2 = 0.; + } + + double tuple[5]; + quality = vtkDoubleArray::New(); + quality->SetName( "Mesh Triangle Quality" ); + quality->SetNumberOfComponents(5); + tuple[0] = qtrim; + tuple[1] = Eqtri; + tuple[2] = qtriM; + tuple[3] = Eqtri2; + tuple[4] = ntri; + quality->InsertNextTuple( tuple ); + out->GetFieldData()->AddArray( quality ); + quality->Delete(); + + quality = vtkDoubleArray::New(); + quality->SetName( "Mesh Quadrilateral Quality" ); + quality->SetNumberOfComponents(5); + tuple[0] = qquam; + tuple[1] = Eqqua; + tuple[2] = qquaM; + tuple[3] = Eqqua2; + tuple[4] = nqua; + quality->InsertNextTuple( tuple ); + out->GetFieldData()->AddArray( quality ); + quality->Delete(); + + quality = vtkDoubleArray::New(); + quality->SetName( "Mesh Tetrahedron Quality" ); + quality->SetNumberOfComponents(5); + tuple[0] = qtetm; + tuple[1] = Eqtet; + tuple[2] = qtetM; + tuple[3] = Eqtet2; + tuple[4] = ntet; + quality->InsertNextTuple( tuple ); + out->GetFieldData()->AddArray( quality ); + quality->Delete(); + + quality = vtkDoubleArray::New(); + quality->SetName( "Mesh Hexahedron Quality" ); + quality->SetNumberOfComponents(5); + tuple[0] = qhexm; + tuple[1] = Eqhex; + tuple[2] = qhexM; + tuple[3] = Eqhex2; + tuple[4] = nhex; + quality->InsertNextTuple( tuple ); + out->GetFieldData()->AddArray( quality ); + quality->Delete(); + + return 1; +} + +// Triangle quality measures: +// edge ratio, aspect ratio, radius ratio, Frobenius norm, minimal angle + +double vtkMeshQuality::TriangleEdgeRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3]; + double a[3],b[3],c[3]; + double a2,b2,c2,m2,M2; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p2[0]-p0[0]; + c[1] = p2[1]-p0[1]; + c[2] = p2[2]-p0[2]; + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + + if ( a2 < b2 ) + { + if ( b2 < c2 ) + { + m2 = a2; + M2 = c2; + } + else // b2 <= a2 + { + if ( a2 < c2 ) + { + m2 = a2; + M2 = b2; + } + else // c2 <= a2 + { + m2 = c2; + M2 = b2; + } + } + } + else // b2 <= a2 + { + if ( a2 < c2 ) + { + m2 = b2; + M2 = c2; + } + else // c2 <= a2 + { + if ( b2 < c2 ) + { + m2 = b2; + M2 = a2; + } + else // c2 <= b2 + { + m2 = c2; + M2 = a2; + } + } + } + + return sqrt(M2 / m2); +} + +double vtkMeshQuality::TriangleAspectRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3]; + double a[3],b[3],c[3]; + double a1,b1,c1,hm; + const double normal_coeff = sqrt(3.) / 6.; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p2[0]-p0[0]; + c[1] = p2[1]-p0[1]; + c[2] = p2[2]-p0[2]; + + a1 = sqrt(vtkMath::Dot(a,a)); + b1 = sqrt(vtkMath::Dot(b,b)); + c1 = sqrt(vtkMath::Dot(c,c)); + + hm = a1 > b1 ? a1 : b1; + hm = hm > c1 ? hm : c1; + + vtkMath::Cross(a,b,c); + + return normal_coeff * hm * (a1 + b1 + c1) / vtkMath::Norm(c); +} + +double vtkMeshQuality::TriangleRadiusRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3]; + double a[3],b[3],c[3]; + double a1,b1,c1,ab; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p2[0]-p0[0]; + c[1] = p2[1]-p0[1]; + c[2] = p2[2]-p0[2]; + + a1 = sqrt(vtkMath::Dot(a,a)); + b1 = sqrt(vtkMath::Dot(b,b)); + c1 = sqrt(vtkMath::Dot(c,c)); + + vtkMath::Cross(a,b,c); + ab = vtkMath::Norm(c); + + return .25 * a1 * b1 * c1 * (a1 + b1 + c1) / (ab * ab); +} + +double vtkMeshQuality::TriangleFrobeniusNorm( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3]; + double a[3],b[3],c[3]; + double t22; + const double normal_coeff = .5 / sqrt(3.); + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p2[0]-p0[0]; + c[1] = p2[1]-p0[1]; + c[2] = p2[2]-p0[2]; + + t22 = vtkMath::Dot(a,a); + t22 += vtkMath::Dot(b,b); + t22 += vtkMath::Dot(c,c); + + vtkMath::Cross(a,b,c); + + return normal_coeff * t22 / vtkMath::Norm(c); +} + +double vtkMeshQuality::TriangleMinAngle( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3]; + double a[3],b[3],c[3]; + double a2,b2,c2,alpha,beta,gamma; + const double normal_coeff = .3183098861837906715377675267450287; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p2[0]-p0[0]; + c[1] = p2[1]-p0[1]; + c[2] = p2[2]-p0[2]; + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + + alpha = acos(vtkMath::Dot(b,c) / sqrt(b2 * c2)); + beta = acos(vtkMath::Dot(c,a) / sqrt(c2 * a2)); + gamma = acos(vtkMath::Dot(a,b) / sqrt(a2 * b2)); + + alpha = alpha < beta ? alpha : beta; + + return (alpha < gamma ? alpha : gamma) * 180. * normal_coeff; +} + +// Quadrangle quality measures: +// edge ratio, aspect ratio, radius ratio, average Frobenius norm, +// maximal Frobenius norm, minimal angle +// (only edge ratio and minimal angle are intended for nonplanar quads) + +double vtkMeshQuality::QuadEdgeRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double a[3],b[3],c[3],d[3]; + double a2,b2,c2,d2,mab,Mab,mcd,Mcd,m2,M2; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p3[0]-p2[0]; + c[1] = p3[1]-p2[1]; + c[2] = p3[2]-p2[2]; + + d[0] = p0[0]-p3[0]; + d[1] = p0[1]-p3[1]; + d[2] = p0[2]-p3[2]; + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + d2 = vtkMath::Dot(d,d); + + if ( a2 < b2 ) + { + mab = a2; + Mab = b2; + } + else // b2 <= a2 + { + mab = b2; + Mab = a2; + } + if ( c2 < d2 ) + { + mcd = c2; + Mcd = d2; + } + else // d2 <= c2 + { + mcd = d2; + Mcd = c2; + } + m2 = mab < mcd ? mab : mcd; + M2 = Mab > Mcd ? Mab : Mcd; + + return sqrt(M2 / m2); +} + +double vtkMeshQuality::QuadAspectRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double a[3],b[3],c[3],d[3],ab[3],cd[3]; + double a1,b1,c1,d1; + double ma,mb,hm; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p3[0]-p2[0]; + c[1] = p3[1]-p2[1]; + c[2] = p3[2]-p2[2]; + + d[0] = p0[0]-p3[0]; + d[1] = p0[1]-p3[1]; + d[2] = p0[2]-p3[2]; + + a1 = sqrt(vtkMath::Dot(a,a)); + b1 = sqrt(vtkMath::Dot(b,b)); + c1 = sqrt(vtkMath::Dot(c,c)); + d1 = sqrt(vtkMath::Dot(d,d)); + + ma = a1 > b1 ? a1 : b1; + mb = c1 > d1 ? c1 : d1; + hm = ma > mb ? ma : mb; + + vtkMath::Cross(a,b,ab); + vtkMath::Cross(c,d,cd); + + return .5 * hm * (a1 + b1 + c1 + d1) / (vtkMath::Norm(ab) + vtkMath::Norm(cd)); +} + +double vtkMeshQuality::QuadRadiusRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double a[3],b[3],c[3],d[3],m[3],n[3]; + double ab[3],bc[3],cd[3],da[3]; + double a2,b2,c2,d2,m2,n2,h2; + double t0,t1,t2,t3; + const double normal_coeff = 1. / (2.*sqrt(2.)); + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p3[0]-p2[0]; + c[1] = p3[1]-p2[1]; + c[2] = p3[2]-p2[2]; + + d[0] = p0[0]-p3[0]; + d[1] = p0[1]-p3[1]; + d[2] = p0[2]-p3[2]; + + m[0] = p2[0]-p0[0]; + m[1] = p2[1]-p0[1]; + m[2] = p2[2]-p0[2]; + + n[0] = p3[0]-p1[0]; + n[1] = p3[1]-p1[1]; + n[2] = p3[2]-p1[2]; + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + d2 = vtkMath::Dot(d,d); + m2 = vtkMath::Dot(m,m); + n2 = vtkMath::Dot(n,n); + + t0 = a2 > b2 ? a2 : b2; + t1 = c2 > d2 ? c2 : d2; + t2 = m2 > n2 ? m2 : n2; + h2 = t0 > t1 ? t0 : t1; + h2 = h2 > t2 ? h2 : t2; + + vtkMath::Cross(a,b,ab); + vtkMath::Cross(b,c,bc); + vtkMath::Cross(c,d,cd); + vtkMath::Cross(d,a,da); + + t0 = vtkMath::Norm(da); + t1 = vtkMath::Norm(ab); + t2 = vtkMath::Norm(bc); + t3 = vtkMath::Norm(cd); + + t0 = t0 < t1 ? t0 : t1; + t2 = t2 < t3 ? t2 : t3; + t0 = t0 < t2 ? t0 : t2; + + return normal_coeff * sqrt((a2 + b2 + c2 + d2) * h2) / t0; +} + +double vtkMeshQuality::QuadMedFrobeniusNorm( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double a[3],b[3],c[3],d[3],ab[3],bc[3],cd[3],da[3]; + double a2,b2,c2,d2; + double kappa2; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p3[0]-p2[0]; + c[1] = p3[1]-p2[1]; + c[2] = p3[2]-p2[2]; + + d[0] = p0[0]-p3[0]; + d[1] = p0[1]-p3[1]; + d[2] = p0[2]-p3[2]; + + vtkMath::Cross(a,b,ab); + vtkMath::Cross(b,c,bc); + vtkMath::Cross(c,d,cd); + vtkMath::Cross(d,a,da); + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + d2 = vtkMath::Dot(d,d); + + kappa2 = (a2 + b2) / vtkMath::Norm(ab); + kappa2 += (b2 + c2) / vtkMath::Norm(bc); + kappa2 += (c2 + d2) / vtkMath::Norm(cd); + kappa2 += (d2 + a2) / vtkMath::Norm(da); + + return .125 * kappa2; +} + +double vtkMeshQuality::QuadMaxFrobeniusNorm( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double a[3],b[3],c[3],d[3],ab[3],bc[3],cd[3],da[3]; + double a2,b2,c2,d2; + double kmax,kcur; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p3[0]-p2[0]; + c[1] = p3[1]-p2[1]; + c[2] = p3[2]-p2[2]; + + d[0] = p0[0]-p3[0]; + d[1] = p0[1]-p3[1]; + d[2] = p0[2]-p3[2]; + + vtkMath::Cross(a,b,ab); + vtkMath::Cross(b,c,bc); + vtkMath::Cross(c,d,cd); + vtkMath::Cross(d,a,da); + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + d2 = vtkMath::Dot(d,d); + + kmax = (a2 + b2) / vtkMath::Norm(ab); + + kcur = (b2 + c2) / vtkMath::Norm(bc); + kmax = kmax > kcur ? kmax : kcur; + + kcur = (c2 + d2) / vtkMath::Norm(cd); + kmax = kmax > kcur ? kmax : kcur; + + kcur = (d2 + a2) / vtkMath::Norm(da); + kmax = kmax > kcur ? kmax : kcur; + + return .5 * kmax; +} + +double vtkMeshQuality::QuadMinAngle( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double a[3],b[3],c[3],d[3]; + double a2,b2,c2,d2,alpha,beta,gamma,delta; + const double normal_coeff = .3183098861837906715377675267450287; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p3[0]-p2[0]; + c[1] = p3[1]-p2[1]; + c[2] = p3[2]-p2[2]; + + d[0] = p0[0]-p3[0]; + d[1] = p0[1]-p3[1]; + d[2] = p0[2]-p3[2]; + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + d2 = vtkMath::Dot(d,d); + + alpha = acos(vtkMath::Dot(b,c) / sqrt(b2 * c2)); + beta = acos(vtkMath::Dot(c,d) / sqrt(c2 * d2)); + gamma = acos(vtkMath::Dot(d,a) / sqrt(d2 * a2)); + delta = acos(vtkMath::Dot(a,b) / sqrt(a2 * b2)); + + alpha = alpha < beta ? alpha : beta; + gamma = gamma < delta ? gamma : delta; + + return (alpha < gamma ? alpha : gamma) * 180. * normal_coeff; +} + +// Volume of a tetrahedron, for compatibility with the original vtkMeshQuality + +double TetVolume( vtkCell* cell ) +{ + double x0[3]; + double x1[3]; + double x2[3]; + double x3[3]; + cell->Points->GetPoint( 0, x0 ); + cell->Points->GetPoint( 1, x1 ); + cell->Points->GetPoint( 2, x2 ); + cell->Points->GetPoint( 3, x3 ); + return vtkTetra::ComputeVolume( x0, x1, x2, x3 ); +} + +// Tetrahedron quality measures: +// edge ratio, aspect ratio, radius ratio, Frobenius norm, minimal angle + +double vtkMeshQuality::TetEdgeRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double a[3],b[3],c[3],d[3],e[3],f[3]; + double a2,b2,c2,d2,e2,f2; + double m2,M2,mab,mcd,mef,Mab,Mcd,Mef; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p2[0]-p0[0]; + c[1] = p2[1]-p0[1]; + c[2] = p2[2]-p0[2]; + + d[0] = p3[0]-p0[0]; + d[1] = p3[1]-p0[1]; + d[2] = p3[2]-p0[2]; + + e[0] = p3[0]-p1[0]; + e[1] = p3[1]-p1[1]; + e[2] = p3[2]-p1[2]; + + f[0] = p3[0]-p2[0]; + f[1] = p3[1]-p2[1]; + f[2] = p3[2]-p2[2]; + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + d2 = vtkMath::Dot(d,d); + e2 = vtkMath::Dot(e,e); + f2 = vtkMath::Dot(f,f); + + if ( a2 < b2 ) + { + mab = a2; + Mab = b2; + } + else // b2 <= a2 + { + mab = b2; + Mab = a2; + } + if ( c2 < d2 ) + { + mcd = c2; + Mcd = d2; + } + else // d2 <= c2 + { + mcd = d2; + Mcd = c2; + } + if ( e2 < f2 ) + { + mef = e2; + Mef = f2; + } + else // f2 <= e2 + { + mef = f2; + Mef = e2; + } + + m2 = mab < mcd ? mab : mcd; + m2 = m2 < mef ? m2 : mef; + M2 = Mab > Mcd ? Mab : Mcd; + M2 = M2 > Mef ? M2 : Mef; + + return sqrt(M2 / m2); +} + +double vtkMeshQuality::TetAspectRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double ab[3],bc[3],ac[3],ad[3],bd[3],cd[3]; + double t0,t1,t2,t3,t4,t5; + double ma,mb,mc,hm; + const double normal_coeff = sqrt(6.) / 12.; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + ab[0] = p1[0]-p0[0]; + ab[1] = p1[1]-p0[1]; + ab[2] = p1[2]-p0[2]; + + bc[0] = p2[0]-p1[0]; + bc[1] = p2[1]-p1[1]; + bc[2] = p2[2]-p1[2]; + + ac[0] = p2[0]-p0[0]; + ac[1] = p2[1]-p0[1]; + ac[2] = p2[2]-p0[2]; + + ad[0] = p3[0]-p0[0]; + ad[1] = p3[1]-p0[1]; + ad[2] = p3[2]-p0[2]; + + bd[0] = p3[0]-p1[0]; + bd[1] = p3[1]-p1[1]; + bd[2] = p3[2]-p1[2]; + + cd[0] = p3[0]-p2[0]; + cd[1] = p3[1]-p2[1]; + cd[2] = p3[2]-p2[2]; + + t0 = vtkMath::Dot(ab,ab); + t1 = vtkMath::Dot(bc,bc); + t2 = vtkMath::Dot(ac,ac); + t3 = vtkMath::Dot(ad,ad); + t4 = vtkMath::Dot(bd,bd); + t5 = vtkMath::Dot(cd,cd); + + ma = t0 > t1 ? t0 : t1; + mb = t2 > t3 ? t2 : t3; + mc = t4 > t5 ? t4 : t5; + hm = ma > mb ? ma : mb; + hm = hm > mc ? sqrt(hm) : sqrt(mc); + + vtkMath::Cross(ab,bc,bd); + t0 = vtkMath::Norm(bd); + vtkMath::Cross(ab,ad,bd); + t1 = vtkMath::Norm(bd); + vtkMath::Cross(ac,ad,bd); + t2 = vtkMath::Norm(bd); + vtkMath::Cross(bc,cd,bd); + t3 = vtkMath::Norm(bd); + + t4 = fabs(vtkMath::Determinant3x3(ab,ac,ad)); + + return normal_coeff * hm * (t0 + t1 + t2 + t3) / t4; +} + +double vtkMeshQuality::TetRadiusRatio( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double ab[3],bc[3],ac[3],ad[3],bd[3],cd[3],u[3]; + double abc,abd,acd,bcd,a,b,c,det; + const double normal_coeff = 1. / 12.; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + ab[0] = p1[0]-p0[0]; + ab[1] = p1[1]-p0[1]; + ab[2] = p1[2]-p0[2]; + + bc[0] = p2[0]-p1[0]; + bc[1] = p2[1]-p1[1]; + bc[2] = p2[2]-p1[2]; + + ac[0] = p2[0]-p0[0]; + ac[1] = p2[1]-p0[1]; + ac[2] = p2[2]-p0[2]; + + ad[0] = p3[0]-p0[0]; + ad[1] = p3[1]-p0[1]; + ad[2] = p3[2]-p0[2]; + + bd[0] = p3[0]-p1[0]; + bd[1] = p3[1]-p1[1]; + bd[2] = p3[2]-p1[2]; + + cd[0] = p3[0]-p2[0]; + cd[1] = p3[1]-p2[1]; + cd[2] = p3[2]-p2[2]; + + a = sqrt(vtkMath::Dot(ab,ab) * vtkMath::Dot(cd,cd)); + b = sqrt(vtkMath::Dot(ac,ac) * vtkMath::Dot(bd,bd)); + c = sqrt(vtkMath::Dot(ad,ad) * vtkMath::Dot(bc,bc)); + + vtkMath::Cross(ab,bc,u); + abc = vtkMath::Norm(u); + vtkMath::Cross(ab,ad,u); + abd = vtkMath::Norm(u); + vtkMath::Cross(ac,ad,u); + acd = vtkMath::Norm(u); + vtkMath::Cross(bc,cd,u); + bcd = vtkMath::Norm(u); + + det = vtkMath::Determinant3x3(ab,ac,ad); + + return normal_coeff * sqrt((a+b+c) * (a+b-c) * (a+c-b) * (b+c-a)) * (abc + abd + acd + bcd) \ + / (det * det); +} + +double vtkMeshQuality::TetFrobeniusNorm( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double u[3],v[3],w[3]; + double numerator,radicand; + const double normal_exp = 1./3.; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + u[0] = p1[0]-p0[0]; + u[1] = p1[1]-p0[1]; + u[2] = p1[2]-p0[2]; + + v[0] = p2[0]-p0[0]; + v[1] = p2[1]-p0[1]; + v[2] = p2[2]-p0[2]; + + w[0] = p3[0]-p0[0]; + w[1] = p3[1]-p0[1]; + w[2] = p3[2]-p0[2]; + + numerator = u[0] * u[0] + u[1] * u[1] + u[2] * u[2]; + numerator += v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + numerator += w[0] * w[0] + w[1] * w[1] + w[2] * w[2]; + numerator *= 1.5; + numerator -= v[0] * u[0] + v[1] * u[1] + v[2] * u[2]; + numerator -= w[0] * u[0] + w[1] * u[1] + w[2] * u[2]; + numerator -= w[0] * v[0] + w[1] * v[1] + w[2] * v[2]; + + radicand = vtkMath::Determinant3x3(u,v,w); + radicand *= radicand; + radicand *= 2.; + + return numerator / (3. * pow(radicand,normal_exp)); +} + +double vtkMeshQuality::TetMinAngle( vtkCell* cell ) +{ + double p0[3],p1[3],p2[3],p3[3]; + double ab[3],bc[3],ad[3],cd[3]; + double abc[3],abd[3],acd[3],bcd[3]; + double nabc,nabd,nacd,nbcd; + double alpha,beta,gamma,delta,epsilon,zeta; + const double normal_coeff = .3183098861837906715377675267450287; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + + ab[0] = p1[0]-p0[0]; + ab[1] = p1[1]-p0[1]; + ab[2] = p1[2]-p0[2]; + + bc[0] = p2[0]-p1[0]; + bc[1] = p2[1]-p1[1]; + bc[2] = p2[2]-p1[2]; + + ad[0] = p3[0]-p0[0]; + ad[1] = p3[1]-p0[1]; + ad[2] = p3[2]-p0[2]; + + cd[0] = p3[0]-p2[0]; + cd[1] = p3[1]-p2[1]; + cd[2] = p3[2]-p2[2]; + + vtkMath::Cross(ab,bc,abc); + nabc = vtkMath::Norm(abc); + vtkMath::Cross(ab,ad,abd); + nabd = vtkMath::Norm(abd); + vtkMath::Cross(ad,cd,acd); + nacd = vtkMath::Norm(acd); + vtkMath::Cross(bc,cd,bcd); + nbcd = vtkMath::Norm(bcd); + + alpha = acos(vtkMath::Dot(abc,abd) / (nabc * nabd)); + beta = acos(vtkMath::Dot(abc,acd) / (nabc * nacd)); + gamma = acos(vtkMath::Dot(abc,bcd) / (nabc * nbcd)); + delta = acos(vtkMath::Dot(abd,acd) / (nabd * nacd)); + epsilon = acos(vtkMath::Dot(abd,bcd) / (nabd * nbcd)); + zeta = acos(vtkMath::Dot(acd,bcd) / (nacd * nbcd)); + + alpha = alpha < beta ? alpha : beta; + alpha = alpha < gamma ? alpha : gamma; + alpha = alpha < delta ? alpha : delta; + alpha = alpha < epsilon ? alpha : epsilon; + + return (alpha < zeta ? alpha : zeta) * 180. * normal_coeff; +} + +// Hexahedron quality measure: +// edge ratio + +double vtkMeshQuality::HexEdgeRatio( vtkCell* cell) +{ + double p0[3],p1[3],p2[3],p3[3]; + double p4[3],p5[3],p6[3],p7[3]; + double a[3],b[3],c[3],d[3],e[3],f[3]; + double g[3],h[3],i[3],j[3],k[3],l[3]; + double a2,b2,c2,d2,e2,f2; + double g2,h2,i2,j2,k2,l2; + double mab,mcd,mef,Mab,Mcd,Mef; + double mgh,mij,mkl,Mgh,Mij,Mkl; + double m2,M2; + + vtkPoints *p = cell->GetPoints(); + p->GetPoint(0, p0); + p->GetPoint(1, p1); + p->GetPoint(2, p2); + p->GetPoint(3, p3); + p->GetPoint(4, p4); + p->GetPoint(5, p5); + p->GetPoint(6, p6); + p->GetPoint(7, p7); + + a[0] = p1[0]-p0[0]; + a[1] = p1[1]-p0[1]; + a[2] = p1[2]-p0[2]; + + b[0] = p2[0]-p1[0]; + b[1] = p2[1]-p1[1]; + b[2] = p2[2]-p1[2]; + + c[0] = p3[0]-p2[0]; + c[1] = p3[1]-p2[1]; + c[2] = p3[2]-p2[2]; + + d[0] = p0[0]-p3[0]; + d[1] = p0[1]-p3[1]; + d[2] = p0[2]-p3[2]; + + e[0] = p4[0]-p0[0]; + e[1] = p4[1]-p0[1]; + e[2] = p4[2]-p0[2]; + + f[0] = p5[0]-p1[0]; + f[1] = p5[1]-p1[1]; + f[2] = p5[2]-p1[2]; + + g[0] = p6[0]-p2[0]; + g[1] = p6[1]-p2[1]; + g[2] = p6[2]-p2[2]; + + h[0] = p7[0]-p3[0]; + h[1] = p7[1]-p3[1]; + h[2] = p7[2]-p3[2]; + + i[0] = p5[0]-p4[0]; + i[1] = p5[1]-p4[1]; + i[2] = p5[2]-p4[2]; + + j[0] = p6[0]-p5[0]; + j[1] = p6[1]-p5[1]; + j[2] = p6[2]-p5[2]; + + k[0] = p7[0]-p6[0]; + k[1] = p7[1]-p6[1]; + k[2] = p7[2]-p6[2]; + + l[0] = p4[0]-p7[0]; + l[1] = p4[1]-p7[1]; + l[2] = p4[2]-p7[2]; + + a2 = vtkMath::Dot(a,a); + b2 = vtkMath::Dot(b,b); + c2 = vtkMath::Dot(c,c); + d2 = vtkMath::Dot(d,d); + e2 = vtkMath::Dot(e,e); + f2 = vtkMath::Dot(f,f); + g2 = vtkMath::Dot(g,g); + h2 = vtkMath::Dot(h,h); + i2 = vtkMath::Dot(i,i); + j2 = vtkMath::Dot(j,j); + k2 = vtkMath::Dot(k,k); + l2 = vtkMath::Dot(l,l); + + if ( a2 < b2 ) + { + mab = a2; + Mab = b2; + } + else // b2 <= a2 + { + mab = b2; + Mab = a2; + } + if ( c2 < d2 ) + { + mcd = c2; + Mcd = d2; + } + else // d2 <= c2 + { + mcd = d2; + Mcd = c2; + } + if ( e2 < f2 ) + { + mef = e2; + Mef = f2; + } + else // f2 <= e2 + { + mef = f2; + Mef = e2; + } + if ( g2 < h2 ) + { + mgh = g2; + Mgh = h2; + } + else // h2 <= g2 + { + mgh = h2; + Mgh = g2; + } + if ( i2 < j2 ) + { + mij = i2; + Mij = j2; + } + else // j2 <= i2 + { + mij = j2; + Mij = i2; + } + if ( k2 < l2 ) + { + mkl = k2; + Mkl = l2; + } + else // l2 <= k2 + { + mkl = l2; + Mkl = k2; + } + + m2 = mab < mcd ? mab : mcd; + m2 = m2 < mef ? m2 : mef; + m2 = m2 < mgh ? m2 : mgh; + m2 = m2 < mij ? m2 : mij; + m2 = m2 < mkl ? m2 : mkl; + M2 = Mab > Mcd ? Mab : Mcd; + M2 = M2 > Mef ? M2 : Mef; + M2 = M2 > Mgh ? M2 : Mgh; + M2 = M2 > Mij ? M2 : Mij; + M2 = M2 > Mkl ? M2 : Mkl; + + return sqrt(M2 / m2); +} + diff --git a/Graphics/vtkMeshQuality.h b/Graphics/vtkMeshQuality.h new file mode 100644 index 0000000..0f04738 --- /dev/null +++ b/Graphics/vtkMeshQuality.h @@ -0,0 +1,490 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMeshQuality.h,v $ + Language: C++ + Date: $Date: 2005/02/19 01:50:46 $ + Version: $Revision: 1.21 $ + + Copyright 2003 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + + Contact: dcthomp@sandia.gov,pppebay@ca.sandia.gov + +=========================================================================*/ +// .NAME vtkMeshQuality - Calculate measures of quality of a mesh +// +// .SECTION Description +// vtkMeshQuality computes one or more measures of (geometric) +// quality for each 2-D and 3-D cell (triangle, quadrilateral, tetrahedron, +// or hexahedron) of a mesh. These measures of quality are then averaged +// over the entire mesh. The minimum, average, maximum, and variance +// of quality for each type of cell is stored in the output mesh's FieldData. +// The FieldData arrays are named "Mesh Triangle Quality," +// "Mesh Quadrilateral Quality," "Mesh Tetrahedron Quality," +// and "Mesh Hexahedron Quality." Each array has a single tuple +// with 5 components. The first 4 components are the quality statistics +// mentioned above; the final value is the number of cells of the given type. +// This final component makes aggregation of statistics for distributed +// mesh data possible. +// +// By default, the per-cell quality is added to the mesh's cell data, in +// an array named "Quality." Cell types not supported by +// this filter will have an entry of 0. Use SaveCellQualityOff() to +// store only the final statistics. +// +// This version of the filter overtakes an older version written by +// Leila Baghdadi, Hanif Ladak, and David Steinman at the Imaging Research +// Labs, Robarts Research Institute. That version focused solely on +// tetrahedra. See the CompatibilityModeOn() member for information on +// how to make this filter behave like the previous implementation. +// +// .SECTION Caveats +// While more general than before, this class does not address many +// cell types, including wedges and pyramids in 3D and triangle strips +// and fans in 2D (among others). +// Most quadrilateral quality measures are intended for planar quadrilaterals +// only. +// The minimal angle is not, strictly speaking, a quality measure, but it is +// provided because of its useage by many authors. + +#ifndef vtkMeshQuality_h +#define vtkMeshQuality_h + +#include "vtkDataSetAlgorithm.h" + +class vtkCell; + +#define VTK_QUALITY_EDGE_RATIO 0 +#define VTK_QUALITY_ASPECT_RATIO 1 +#define VTK_QUALITY_RADIUS_RATIO 2 +#define VTK_QUALITY_FROBENIUS_NORM 3 +#define VTK_QUALITY_MED_FROBENIUS_NORM 4 +#define VTK_QUALITY_MAX_FROBENIUS_NORM 5 +#define VTK_QUALITY_MIN_ANGLE 6 + +class VTK_GRAPHICS_EXPORT vtkMeshQuality : public vtkDataSetAlgorithm +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkMeshQuality,vtkDataSetAlgorithm); + static vtkMeshQuality* New(); + + // Description: + // This variable controls whether or not cell quality is stored as + // cell data in the resulting mesh or discarded (leaving only the + // aggregate quality average of the entire mesh, recorded in the + // FieldData). + vtkSetMacro(SaveCellQuality,int); + vtkGetMacro(SaveCellQuality,int); + vtkBooleanMacro(SaveCellQuality,int); + + // Description: + // Set/Get the particular estimator used to measure the quality of triangles. + // The default is VTK_QUALITY_RADIUS_RATIO and valid values also include + // VTK_QUALITY_ASPECT_RATIO, VTK_QUALITY_FROBENIUS_NORM, and VTK_QUALITY_EDGE_RATIO. + vtkSetMacro(TriangleQualityMeasure,int); + vtkGetMacro(TriangleQualityMeasure,int); + void SetTriangleQualityMeasureToEdgeRatio() + { + this->SetTriangleQualityMeasure( VTK_QUALITY_EDGE_RATIO ); + } + void SetTriangleQualityMeasureToAspectRatio() + { + this->SetTriangleQualityMeasure( VTK_QUALITY_ASPECT_RATIO ); + } + void SetTriangleQualityMeasureToRadiusRatio() + { + this->SetTriangleQualityMeasure( VTK_QUALITY_RADIUS_RATIO ); + } + void SetTriangleQualityMeasureToFrobeniusNorm() + { + this->SetTriangleQualityMeasure( VTK_QUALITY_FROBENIUS_NORM ); + } + void SetTriangleQualityMeasureToMinAngle() + { + this->SetTriangleQualityMeasure( VTK_QUALITY_MIN_ANGLE ); + } + + // Description: + // Set/Get the particular estimator used to measure the quality of quadrilaterals. + // The default is VTK_QUALITY_EDGE_RATIO and valid values also include + // VTK_QUALITY_RADIUS_RATIO and VTK_QUALITY_ASPECT_RATIO. + // Scope: Except for VTK_QUALITY_EDGE_RATIO, these estimators are intended for planar + // quadrilaterals only; use at your own risk if you really want to assess non-planar + // quadrilateral quality with those. + vtkSetMacro(QuadQualityMeasure,int); + vtkGetMacro(QuadQualityMeasure,int); + void SetQuadQualityMeasureToEdgeRatio() + { + this->SetQuadQualityMeasure( VTK_QUALITY_EDGE_RATIO ); + } + void SetQuadQualityMeasureToAspectRatio() + { + this->SetQuadQualityMeasure( VTK_QUALITY_ASPECT_RATIO ); + } + void SetQuadQualityMeasureToRadiusRatio() + { + this->SetQuadQualityMeasure( VTK_QUALITY_RADIUS_RATIO ); + } + void SetQuadQualityMeasureToMedFrobeniusNorm() + { + this->SetQuadQualityMeasure( VTK_QUALITY_MED_FROBENIUS_NORM ); + } + void SetQuadQualityMeasureToMaxFrobeniusNorm() + { + this->SetQuadQualityMeasure( VTK_QUALITY_MAX_FROBENIUS_NORM ); + } + void SetQuadQualityMeasureToMinAngle() + { + this->SetQuadQualityMeasure( VTK_QUALITY_MIN_ANGLE ); + } + + // Description: + // Set/Get the particular estimator used to measure the quality of tetrahedra. + // The default is VTK_QUALITY_RADIUS_RATIO and valid values also include + // VTK_QUALITY_ASPECT_RATIO, VTK_QUALITY_FROBENIUS_NORM, and VTK_QUALITY_EDGE_RATIO. + vtkSetMacro(TetQualityMeasure,int); + vtkGetMacro(TetQualityMeasure,int); + void SetTetQualityMeasureToEdgeRatio() + { + this->SetTetQualityMeasure( VTK_QUALITY_EDGE_RATIO ); + } + void SetTetQualityMeasureToAspectRatio() + { + this->SetTetQualityMeasure( VTK_QUALITY_ASPECT_RATIO ); + } + void SetTetQualityMeasureToRadiusRatio() + { + this->SetTetQualityMeasure( VTK_QUALITY_RADIUS_RATIO ); + } + void SetTetQualityMeasureToFrobeniusNorm() + { + this->SetTetQualityMeasure( VTK_QUALITY_FROBENIUS_NORM ); + } + void SetTetQualityMeasureToMinAngle() + { + this->SetTetQualityMeasure( VTK_QUALITY_MIN_ANGLE ); + } + + // Description: + // Set/Get the particular estimator used to measure the quality of hexahedra. + // The default is VTK_QUALITY_RADIUS_RATIO and valid values also include + // VTK_QUALITY_ASPECT_RATIO. + vtkSetMacro(HexQualityMeasure,int); + vtkGetMacro(HexQualityMeasure,int); + void SetHexQualityMeasureToEdgeRatio() + { + this->SetHexQualityMeasure( VTK_QUALITY_EDGE_RATIO ); + } + + // Description: + // This is a static function used to calculate the edge ratio of a triangle. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The edge ratio of a triangle \f$t\f$ is: + // \f$\frac{|t|_\infty}{|t|_0}\f$, + // where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and + // the smallest edge lengths of \f$t\f$. + static double TriangleEdgeRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the aspect ratio of a triangle. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The aspect ratio of a triangle \f$t\f$ is: + // \f$\frac{|t|_\infty}{2\sqrt{3}r}\f$, + // where \f$|t|_\infty\f$ and \f$r\f$ respectively denote the greatest edge + // length and the inradius of \f$t\f$. + static double TriangleAspectRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the radius ratio of a triangle. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The radius ratio of a triangle \f$t\f$ is: + // \f$\frac{R}{2r}\f$, + // where \f$R\f$ and \f$r\f$ respectively denote the circumradius and + // the inradius of \f$t\f$. + static double TriangleRadiusRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the Frobenius norm of a triangle + // when the reference element is equilateral. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The Frobenius norm of a triangle \f$t\f$, when the reference element is + // equilateral, is: + // \f$\frac{|t|^2_2}{2\sqrt{3}{\cal A}}\f$, + // where \f$|t|^2_2\f$ and \f$\cal A\f$ respectively denote the sum of the + // squared edge lengths and the area of \f$t\f$. + static double TriangleFrobeniusNorm( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the minimal (nonoriented) angle + // of a triangle, expressed in degrees. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + static double TriangleMinAngle( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the edge ratio of a quadrilateral. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The edge ratio of a quadrilateral \f$q\f$ is: + // \f$\frac{|q|_\infty}{|q|_0}\f$, + // where \f$|q|_\infty\f$ and \f$|q|_0\f$ respectively denote the greatest and + // the smallest edge lengths of \f$q\f$. + static double QuadEdgeRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the aspect ratio of a planar + // quadrilateral. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. Use at your own risk with nonplanar quadrilaterals. + // The aspect ratio of a planar quadrilateral \f$q\f$ is: + // \f$\frac{|q|_1|q|_\infty}{4{\cal A}}\f$, + // where \f$|q|_1\f$, $|q|_\infty\f$ and \f${\cal A}\f$ respectively denote the + // perimeter, the greatest edge length and the area of \f$q\f$. + static double QuadAspectRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the radius ratio of a planar + // quadrilateral. The name is only used by analogy with the triangle radius + // ratio, because in general a quadrilateral does not have a circumcircle nor + // an incircle. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. Use at your own risk with nonplanar quadrilaterals. + // The radius ratio of a planar quadrilateral \f$q\f$ is: + // \f$\frac{|q|_2h_{\max}}{\min_i{\cal A}_i}\f$, + // where \f$|q|_2\f$, \f$h_{\max}\f$ and \f$\min{\cal A}_i\f$ respectively denote + // the sum of the squared edge lengths, the greatest amongst diagonal and edge + // lengths and the smallest area of the 4 triangles extractable from \f$q\f$. + static double QuadRadiusRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the average Frobenius norm of the + // 4 triangles extractable from a planar quadrilateral, when the reference + // triangle elements are right isosceles at the quadrangle vertices. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. Use at your own risk with nonplanar quadrilaterals. + // The Frobenius norm of a triangle \f$t\f$, when the reference element is + // right isosceles at vertex \f$V\f$, is: + // \f$\frac{f^2+g^2}{4{\cal A}}\f$, + // where \f$f^2+g^2\f$ and \f$\cal A\f$ respectively denote the sum of the + // squared lengths of the edges attached to \f$V\f$ and the area of \f$t\f$. + static double QuadMedFrobeniusNorm( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the maximal Frobenius norm of the + // 4 triangles extractable from a planar quadrilateral, when the reference + // triangle elements are right isosceles at the quadrangle vertices. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. Use at your own risk with nonplanar quadrilaterals. + // The Frobenius norm of a triangle \f$t\f$, when the reference element is + // right isosceles at vertex \f$V\f$, is: + // \f$\frac{f^2+g^2}{4{\cal A}}\f$, + // where \f$f^2+g^2\f$ and \f$\cal A\f$ respectively denote the sum of the + // squared lengths of the edges attached to \f$V\f$ and the area of \f$t\f$. + static double QuadMaxFrobeniusNorm( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the minimal (nonoriented) angle + // of a quadrilateral, expressed in degrees. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + static double QuadMinAngle( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the edge ratio of a tetrahedron. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The edge ratio of a tetrahedron \f$K\f$ is: + // \f$\frac{|K|_\infty}{|K|_0}\f$, + // where \f$|K|_\infty\f$ and \f$|K|_0\f$ respectively denote the greatest and + // the smallest edge lengths of \f$K\f$. + static double TetEdgeRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the aspect ratio of a tetrahedron. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The aspect ratio of a tetrahedron \f$K\f$ is: + // \f$\frac{|K|_\infty}{2\sqrt{6}r}\f$, + // where \f$|K|_\infty\f$ and \f$r\f$ respectively denote the greatest edge + // length and the inradius of \f$K\f$. + static double TetAspectRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the radius ratio of a tetrahedron. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The radius ratio of a tetrahedron \f$K\f$ is: + // \f$\frac{R}{3r}\f$, + // where \f$R\f$ and \f$r\f$ respectively denote the circumradius and + // the inradius of \f$K\f$. + static double TetRadiusRatio( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the Frobenius norm of a tetrahedron + // when the reference element is regular. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The Frobenius norm of a tetrahedron \f$K\f$, when the reference element is + // regular, is: + // \f$\frac{\frac{3}{2}(l_{11}+l_{22}+l_{33}) - (l_{12}+l_{13}+l_{23})} + // {3(\sqrt{2}\det{T})^\frac{2}{3}}\f$, + // where \f$T\f$ and \f$l_{ij}\f$ respectively denote the edge matrix of \f$K\f$ + // and the entries of \f$L=T^t\,T\f$. + static double TetFrobeniusNorm( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the minimal (nonoriented) dihedral + // angle of a tetrahedron, expressed in degrees. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + static double TetMinAngle( vtkCell* cell ); + + // Description: + // This is a static function used to calculate the edge ratio of a hexahedron. + // It assumes that you pass the correct type of cell -- no type checking is + // performed because this method is called from the inner loop of the Execute() + // member function. + // The edge ratio of a tetrahedron \f$H\f$ is: + // \f$\frac{|H|_\infty}{|H|_0}\f$, + // where \f$|H|_\infty\f$ and \f$|H|_0\f$ respectively denote the greatest and + // the smallest edge lengths of \f$H\f$. + static double HexEdgeRatio( vtkCell* cell ); + + // Description: + // These methods are deprecated. Use Get/SetSaveCellQuality() instead. + // + // Formerly, SetRatio could be used to disable computation + // of the tetrahedral radius ratio so that volume alone could be computed. + // Now, cell quality is always computed, but you may decide not + // to store the result for each cell. + // This allows average cell quality of a mesh to be + // calculated without requiring per-cell storage. + virtual void SetRatio( int r ) { this->SetSaveCellQuality( r ); } + int GetRatio() { return this->GetSaveCellQuality(); } + vtkBooleanMacro(Ratio,int); + + // Description: + // These methods are deprecated. The functionality of computing cell + // volume is being removed until it can be computed for any 3D cell. + // (The previous implementation only worked for tetrahedra.) + // + // For now, turning on the volume computation will put this + // filter into "compatibility mode," where tetrahedral cell + // volume is stored in first component of each output tuple and + // the radius ratio is stored in the second component. You may + // also use CompatibilityModeOn()/Off() to enter this mode. + // In this mode, cells other than tetrahedra will have report + // a volume of 0.0 (if volume computation is enabled). + // + // By default, volume computation is disabled and compatibility + // mode is off, since it does not make a lot of sense for + // meshes with non-tetrahedral cells. + virtual void SetVolume( int cv ) + { + if ( ! ((cv != 0) ^ (this->Volume != 0)) ) + { + return; + } + this->Modified(); + this->Volume = cv; + if ( this->Volume ) + { + this->CompatibilityModeOn(); + } + } + int GetVolume() + { + return this->Volume; + } + vtkBooleanMacro(Volume,int); + + // Description: + // CompatibilityMode governs whether, when both a quality measure + // and cell volume are to be stored as cell data, the two values + // are stored in a single array. When compatibility mode is off + // (the default), two separate arrays are used -- one labeled + // "Quality" and the other labeled "Volume". + // When compatibility mode is on, both values are stored in a + // single array, with volume as the first component and quality + // as the second component. + // + // Enabling CompatibilityMode changes the default tetrahedral + // quality measure to VTK_QUALITY_RADIUS_RATIO and turns volume + // computation on. (This matches the default behavior of the + // initial implementation of vtkMeshQuality.) You may change + // quality measure and volume computation without leaving + // compatibility mode. + // + // Disabling compatibility mode does not affect the current + // volume computation or tetrahedral quality measure settings. + // + // The final caveat to CompatibilityMode is that regardless of + // its setting, the resulting array will be of type vtkDoubleArray + // rather than the original vtkFloatArray. + // This is a safety measure to keep the authors from + // diving off of the Combinatorial Coding Cliff into + // Certain Insanity. + virtual void SetCompatibilityMode( int cm ) + { + if ( !((cm != 0) ^ (this->CompatibilityMode != 0)) ) + { + return; + } + this->CompatibilityMode = cm; + this->Modified(); + if ( this->CompatibilityMode ) + { + this->Volume = 1; + this->TetQualityMeasure = VTK_QUALITY_RADIUS_RATIO; + } + } + vtkGetMacro(CompatibilityMode,int); + vtkBooleanMacro(CompatibilityMode,int); + +protected: + vtkMeshQuality(); + ~vtkMeshQuality(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int SaveCellQuality; + int TriangleQualityMeasure; + int QuadQualityMeasure; + int TetQualityMeasure; + int HexQualityMeasure; + + int CompatibilityMode; + int Volume; + +private: + vtkMeshQuality( const vtkMeshQuality& ); // Not implemented. + void operator = ( const vtkMeshQuality& ); // Not implemented. +}; + +#endif // vtkMeshQuality_h diff --git a/Graphics/vtkModelMetadata.cxx b/Graphics/vtkModelMetadata.cxx new file mode 100644 index 0000000..de6cbbf --- /dev/null +++ b/Graphics/vtkModelMetadata.cxx @@ -0,0 +1,4332 @@ +/*========================================================================= + + Program: ParaView + Module: $RCSfile: vtkModelMetadata.cxx,v $ + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkModelMetadata.h" +#include "vtkDataSet.h" +#include "vtkObjectFactory.h" +#include "vtkFieldData.h" +#include "vtkCharArray.h" +#include "vtkFloatArray.h" +#include "vtkDataArray.h" +#include "vtkIntArray.h" +#include "vtkIdList.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include + +vtkCxxRevisionMacro(vtkModelMetadata, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkModelMetadata); + +#include +#include +#include + +class vtkModelMetadataSTLCloak +{ +public: + vtkstd::set IntSet; + vtkstd::map IntMap; +}; + + +#undef FREE +#undef FREELIST + +#define FREE(x) \ + if (x) \ + { \ + delete [] x;\ + x = NULL; \ + } + +#define FREELIST(x, len) \ + if (x && len) \ + { \ + for (i=0; iTitle = NULL; + + this->NumberOfQARecords = 0; + this->QARecord = NULL; + + this->NumberOfInformationLines = 0; + this->InformationLine = NULL; + + this->Dimension = 0; + this->CoordinateNames = NULL; + + this->TimeStepIndex = -1; + this->NumberOfTimeSteps = 0; + this->TimeStepValues = NULL; + + this->NumberOfBlocks = 0; + + this->BlockIds = NULL; + this->BlockElementType = NULL; + this->BlockNumberOfElements = NULL; + this->BlockNodesPerElement = NULL; + this->BlockNumberOfAttributesPerElement = NULL; + this->BlockAttributes = NULL; + this->BlockElementIdList = NULL; + + this->NumberOfNodeSets = 0; + + this->NodeSetIds = NULL; + this->NodeSetSize = NULL; + this->NodeSetNumberOfDistributionFactors = NULL; + this->NodeSetNodeIdList = NULL; + this->NodeSetDistributionFactors = NULL; + + this->NodeSetNodeIdListIndex = NULL; + this->NodeSetDistributionFactorIndex = NULL; + + this->NumberOfSideSets = 0; + + this->SideSetIds = NULL; + this->SideSetSize = NULL; + this->SideSetNumberOfDistributionFactors = NULL; + this->SideSetElementList = NULL; + this->SideSetSideList = NULL; + this->SideSetNumDFPerSide = NULL; + this->SideSetDistributionFactors = NULL; + + this->SideSetListIndex = NULL; + this->SideSetDistributionFactorIndex = NULL; + + this->NumberOfBlockProperties = 0; + this->BlockPropertyNames = NULL; + this->BlockPropertyValue = NULL; + + this->NumberOfNodeSetProperties = 0; + this->NodeSetPropertyNames = NULL; + this->NodeSetPropertyValue = NULL; + + this->NumberOfSideSetProperties = 0; + this->SideSetPropertyNames = NULL; + this->SideSetPropertyValue = NULL; + + this->NumberOfGlobalVariables = 0; + this->GlobalVariableNames = NULL; + this->GlobalVariableValue = NULL; + + this->OriginalNumberOfElementVariables = 0; + this->OriginalElementVariableNames = NULL; + this->NumberOfElementVariables = 0; + this->MaxNumberOfElementVariables = 0; + this->ElementVariableNames = NULL; + this->ElementVariableNumberOfComponents = NULL; + this->MapToOriginalElementVariableNames = NULL; + + this->ElementVariableTruthTable = NULL; + + this->OriginalNumberOfNodeVariables = 0; + this->OriginalNodeVariableNames = NULL; + this->NumberOfNodeVariables = 0; + this->MaxNumberOfNodeVariables = 0; + this->NodeVariableNames = NULL; + this->NodeVariableNumberOfComponents = NULL; + this->MapToOriginalNodeVariableNames = NULL; +} +void vtkModelMetadata::InitializeAllIvars() +{ + this->InitializeAllMetadata(); + + this->SumElementsPerBlock = 0; + this->BlockElementIdListIndex = NULL; + + this->SizeBlockAttributeArray = 0; + this->BlockAttributesIndex = NULL; + + this->SumNodesPerNodeSet = 0; + this->SumDistFactPerNodeSet = 0; + + this->NodeSetNodeIdListIndex = NULL; + this->NodeSetDistributionFactorIndex = NULL; + + this->SumSidesPerSideSet = 0; + this->SumDistFactPerSideSet = 0; + + this->SideSetListIndex = NULL; + this->SideSetDistributionFactorIndex = NULL; + + this->AllVariablesDefinedInAllBlocks = 0; + + this->BlockIdIndex = NULL; +} +void vtkModelMetadata::FreeAllGlobalData() +{ + // All the fields which apply to the whole data set, and so + // don't differ depending on which time step, which blocks, + // or which variables are read in. + + this->SetTitle(NULL); + this->FreeQARecords(); + this->SetInformationLines(0, NULL); + + this->SetCoordinateNames(0, NULL); + this->SetTimeSteps(0, NULL); + + this->SetBlockIds(NULL); + this->SetBlockElementType(NULL); + this->SetBlockNodesPerElement(NULL); + this->SetBlockNumberOfAttributesPerElement(NULL); + + if (this->BlockIdIndex) + { + delete this->BlockIdIndex; + this->BlockIdIndex = NULL; + } + + this->SetNodeSetIds(NULL); + this->SetSideSetIds(NULL); + + this->SetBlockPropertyNames(0, NULL); + this->SetBlockPropertyValue(NULL); + this->SetNodeSetPropertyNames(0, NULL); + this->SetNodeSetPropertyValue(NULL); + this->SetSideSetPropertyNames(0, NULL); + this->SetSideSetPropertyValue(NULL); + this->SetGlobalVariableNames(0, NULL); + + this->SetElementVariableTruthTable(NULL); + + this->FreeOriginalElementVariableNames(); + this->FreeOriginalNodeVariableNames(); +} + +void vtkModelMetadata::FreeAllLocalData() +{ + // All the fields that depend on which blocks, which time step, + // and which variables were read in. + + this->FreeBlockDependentData(); // depends on blocks + this->FreeUsedElementVariables(); // depends on variables + this->FreeUsedNodeVariables(); + this->SetGlobalVariableValue(NULL); // depends on time step +} + +void vtkModelMetadata::FreeBlockDependentData() +{ + // All the fields that depend on exactly which blocks + // are in the vtkUnstructuredGrid + + this->SetBlockNumberOfElements(NULL); + this->SetBlockElementIdList(NULL); + this->SetBlockAttributes(NULL); + + this->SetNodeSetSize(NULL); + this->SetNodeSetNumberOfDistributionFactors(NULL); + this->SetNodeSetNodeIdList(NULL); + this->SetNodeSetDistributionFactors(NULL); + + this->SetSideSetSize(NULL); + this->SetSideSetNumberOfDistributionFactors(NULL); + this->SetSideSetElementList(NULL); + this->SetSideSetSideList(NULL); + this->SetSideSetNumDFPerSide(NULL); + this->SetSideSetDistributionFactors(NULL); +} + +void vtkModelMetadata::FreeOriginalElementVariableNames() +{ + int i; + FREELIST(this->OriginalElementVariableNames, + this->OriginalNumberOfElementVariables); +} +void vtkModelMetadata::FreeOriginalNodeVariableNames() +{ + int i; + FREELIST(this->OriginalNodeVariableNames, + this->OriginalNumberOfNodeVariables); +} +void vtkModelMetadata::FreeUsedElementVariableNames() +{ + int i; + FREELIST(this->ElementVariableNames, + this->MaxNumberOfElementVariables); +} + +void vtkModelMetadata::FreeUsedNodeVariableNames() +{ + int i; + FREELIST(this->NodeVariableNames, + this->MaxNumberOfNodeVariables); +} +void vtkModelMetadata::FreeUsedElementVariables() +{ + this->FreeUsedElementVariableNames(); + FREE(this->ElementVariableNumberOfComponents); + FREE(this->MapToOriginalElementVariableNames); +} +void vtkModelMetadata::FreeUsedNodeVariables() +{ + this->FreeUsedNodeVariableNames(); + FREE(this->NodeVariableNumberOfComponents); + FREE(this->MapToOriginalNodeVariableNames); +} + +void vtkModelMetadata::FreeAllMetadata() +{ + this->FreeAllLocalData(); + this->FreeAllGlobalData(); +} +void vtkModelMetadata::FreeAllIvars() +{ + this->FreeAllMetadata(); + + FREE(this->BlockElementIdListIndex); + FREE(this->BlockAttributesIndex); + FREE(this->NodeSetNodeIdListIndex); + FREE(this->NodeSetDistributionFactorIndex); + FREE(this->SideSetListIndex); + FREE(this->SideSetDistributionFactorIndex); +} +// +// At last: The constructor, destructor and copy operator +// +vtkModelMetadata::vtkModelMetadata() +{ + this->InitializeAllIvars(); +} +vtkModelMetadata::~vtkModelMetadata() +{ + this->FreeAllIvars(); +} +void vtkModelMetadata::Reset() +{ + this->FreeAllIvars(); + this->InitializeAllIvars(); +} + +//------------------------------------------------- +// information && QA fields +//------------------------------------------------- + +void vtkModelMetadata::SetInformationLines(int nlines, char **lines) +{ + int i; + + FREELIST(this->InformationLine, this->NumberOfInformationLines); + + this->NumberOfInformationLines = nlines; + this->InformationLine = lines; +} +void vtkModelMetadata::AddInformationLine(char *line) +{ + int newNum = this->NumberOfInformationLines + 1; + char **lines = new char * [newNum]; + + for (int i=0; iNumberOfInformationLines; i++) + { + lines[i] = this->InformationLine[i]; + } + + lines[newNum-1] = line; + + delete [] this->InformationLine; + + this->InformationLine = lines; +} +int vtkModelMetadata::GetInformationLines(char ***lines) const +{ + *lines = this->InformationLine; + + return this->NumberOfInformationLines; +} + +void vtkModelMetadata::FreeQARecords() +{ + if ((this->NumberOfQARecords > 0) && this->QARecord) + { + for (int i=0; iNumberOfQARecords; i++) + { + if (this->QARecord[i]) + { + delete [] this->QARecord[i][0]; + delete [] this->QARecord[i][1]; + delete [] this->QARecord[i][2]; + delete [] this->QARecord[i][3]; + } + } + delete [] this->QARecord; + } + this->QARecord = NULL; + this->NumberOfQARecords = 0; +} +void vtkModelMetadata::SetQARecords(int nrecords, char *rec[][4]) +{ + this->FreeQARecords(); + + if (nrecords > 0) + { + this->QARecord = rec; + this->NumberOfQARecords = nrecords; + } +} +void vtkModelMetadata::AddQARecord(char *name, char *ver, char *recDate, char *recTime) +{ + typedef char *p4[4]; + + int newNum = this->NumberOfQARecords + 1; + + p4 *qaRecs = new p4 [newNum]; + + for (int i=0; iNumberOfQARecords; i++) + { + qaRecs[i][0] = this->QARecord[i][0]; qaRecs[i][1] = this->QARecord[i][1]; + qaRecs[i][2] = this->QARecord[i][2]; qaRecs[i][3] = this->QARecord[i][3]; + } + + delete [] this->QARecord; + + if ((recDate == NULL) || (recTime == NULL)) + { + time_t currentTime = time(NULL); + struct tm *timeDate = localtime(¤tTime); + + if (timeDate->tm_year >= 100) timeDate->tm_year -= 100; // Y2K + + if (recDate == NULL) + { + char *dateStr = new char [10]; + sprintf(dateStr, "%02d/%02d/%02d", + timeDate->tm_mon, timeDate->tm_mday, timeDate->tm_year); + qaRecs[newNum-1][2] = dateStr; + } + + if (recTime == NULL) + { + char *timeStr = new char [10]; + sprintf(timeStr, "%02d:%02d:%02d", + timeDate->tm_hour, timeDate->tm_min, timeDate->tm_sec); + qaRecs[newNum-1][3] = timeStr; + } + } + + qaRecs[newNum-1][0] = name; + qaRecs[newNum-1][1] = ver; + + if (recDate) qaRecs[newNum-1][2] = recDate; + if (recTime) qaRecs[newNum-1][3] = recTime; + + this->QARecord = qaRecs; + + this->NumberOfQARecords = newNum; +} +void vtkModelMetadata::GetQARecord(int which, + char **name, char **ver, char **date, char **time) const +{ + if ( which >= this->NumberOfQARecords) + { + return; + } + + *name = this->QARecord[which][0]; + *ver = this->QARecord[which][1]; + *date = this->QARecord[which][2]; + *time = this->QARecord[which][3]; +} + +void vtkModelMetadata::SetTimeSteps(int num, float *steps) +{ + FREE(this->TimeStepValues); + + this->NumberOfTimeSteps = num; + this->TimeStepValues = steps; +} + +void vtkModelMetadata::SetCoordinateNames(int dimension, char **n) +{ + int i; + if (this->CoordinateNames) + { + FREELIST(this->CoordinateNames, this->Dimension); + } + + this->CoordinateNames = n; + this->Dimension = dimension; +} + +//------------------------------------------------- +// Blocks +//------------------------------------------------- +int vtkModelMetadata::GetBlockLocalIndex(int id) +{ + if (this->BlockIdIndex == NULL) + { + this->BlockIdIndex = new vtkModelMetadataSTLCloak; + } + + vtkstd::map blockIdIndex = this->BlockIdIndex->IntMap; + + if (blockIdIndex.size() == 0) + { + for (int i=0; iNumberOfBlocks; i++) + { + int gid = this->BlockIds[i]; + + blockIdIndex.insert(vtkstd::map::value_type(gid, i)); + } + } + + vtkstd::map::iterator mapit = blockIdIndex.find(id); + + int retVal = -1; + + if (mapit != blockIdIndex.end()) + { + retVal = mapit->second; + } + + return retVal; +} + +void vtkModelMetadata::SetBlockIds(int *b) +{ + FREE(this->BlockIds); + + this->BlockIds = b; +} +void vtkModelMetadata::SetBlockElementType(char **t) +{ + int i; + + FREELIST(this->BlockElementType, this->NumberOfBlocks); + + this->BlockElementType = t; +} +void vtkModelMetadata::SetBlockNodesPerElement(int *e) +{ + FREE(this->BlockNodesPerElement); + + this->BlockNodesPerElement = e; +} +void vtkModelMetadata::SetBlockElementIdList(int *e) +{ + FREE(this->BlockElementIdList); + + this->BlockElementIdList = e; +} +void vtkModelMetadata::SetBlockAttributes(float *a) +{ + FREE(this->BlockAttributes); + + this->BlockAttributes = a; +} +int vtkModelMetadata::BuildBlockAttributesIndex() +{ + int nblocks = this->NumberOfBlocks; + int *nelts = this->BlockNumberOfElements; + int *natts = this->BlockNumberOfAttributesPerElement; + + if ((nblocks < 1) || !nelts || !natts) + { + return 1; + } + + if (this->BlockAttributesIndex) + { + delete [] this->BlockAttributesIndex; + } + + this->BlockAttributesIndex = new int [nblocks]; + + int idx = 0; + + for (int i=0; iBlockAttributesIndex[i] = idx; + idx += (int)(nelts[i] * natts[i]); + } + + this->SizeBlockAttributeArray = idx; + + return 0; +} +int vtkModelMetadata::BuildBlockElementIdListIndex() +{ + int nblocks = this->NumberOfBlocks; + int *size = this->BlockNumberOfElements; + + if ((nblocks < 1) || !size) + { + return 1; + } + + if (this->BlockElementIdListIndex) + { + delete [] this->BlockElementIdListIndex; + } + this->BlockElementIdListIndex = new int [ nblocks ]; + + int idx = 0; + for (int i=0; iBlockElementIdListIndex[i] = idx; + idx += size[i]; + } + + this->SumElementsPerBlock = idx; + return 0; +} +int vtkModelMetadata::SetBlockNumberOfElements(int *nelts) +{ + FREE(this->BlockNumberOfElements); + + if (nelts) + { + this->BlockNumberOfElements = nelts; + + this->BuildBlockAttributesIndex(); + this->BuildBlockElementIdListIndex(); + } + + return 0; +} +int vtkModelMetadata::SetBlockNumberOfAttributesPerElement(int *natts) +{ + FREE(this->BlockNumberOfAttributesPerElement); + + if (natts) + { + this->BlockNumberOfAttributesPerElement = natts; + + this->BuildBlockAttributesIndex(); + } + + return 0; +} + +//------------------------------------------------- +// node set calculations +//------------------------------------------------- + +void vtkModelMetadata::SetNodeSetIds(int *n) +{ + FREE(this->NodeSetIds); + + this->NodeSetIds = n; +} +void vtkModelMetadata::SetNodeSetNodeIdList(int *n) +{ + FREE(this->NodeSetNodeIdList); + + this->NodeSetNodeIdList = n; +} +void vtkModelMetadata::SetNodeSetDistributionFactors(float *d) +{ + FREE(this->NodeSetDistributionFactors); + + this->NodeSetDistributionFactors = d; +} +int vtkModelMetadata::BuildNodeSetNodeIdListIndex() +{ + int nsets = this->NumberOfNodeSets; + int *size = this->NodeSetSize; + + if ((nsets < 1) || !size) + { + return 1; + } + + if (this->NodeSetNodeIdListIndex) + { + delete [] this->NodeSetNodeIdListIndex; + } + this->NodeSetNodeIdListIndex = new int [ nsets ]; + + int idx = 0; + for (int i=0; iNodeSetNodeIdListIndex[i] = idx; + idx += size[i]; + } + + this->SumNodesPerNodeSet = idx; + return 0; +} +int vtkModelMetadata::BuildNodeSetDistributionFactorIndex() +{ + int nsets = this->NumberOfNodeSets; + int *numFactors = this->NodeSetNumberOfDistributionFactors; + + if ((nsets < 1) || !numFactors) + { + return 1; + } + + if (this->NodeSetDistributionFactorIndex) + { + delete [] this->NodeSetDistributionFactorIndex; + } + this->NodeSetDistributionFactorIndex = new int [ nsets ]; + + int idx = 0; + + for (int i=0; iNodeSetDistributionFactorIndex[i] = idx; + + idx += numFactors[i]; + } + + this->SumDistFactPerNodeSet = idx; + + return 0; +} +int vtkModelMetadata::SetNodeSetSize(int *size) +{ + FREE(this->NodeSetSize); + + if (size) + { + this->NodeSetSize = size; + + this->BuildNodeSetNodeIdListIndex(); + } + + return 0; +} +int vtkModelMetadata::SetNodeSetNumberOfDistributionFactors(int *df) +{ + FREE(this->NodeSetNumberOfDistributionFactors); + + if (df) + { + this->NodeSetNumberOfDistributionFactors = df; + + this->BuildNodeSetDistributionFactorIndex(); + } + + return 0; +} + +//------------------------------------------------- +// side set calculations +//------------------------------------------------- + +void vtkModelMetadata::SetSideSetIds(int *s) +{ + FREE(this->SideSetIds); + + this->SideSetIds = s; +} +void vtkModelMetadata::SetSideSetElementList(int *s) +{ + FREE(this->SideSetElementList); + + this->SideSetElementList= s; +} +void vtkModelMetadata::SetSideSetSideList(int *s) +{ + FREE(this->SideSetSideList); + + this->SideSetSideList= s; +} +void vtkModelMetadata::SetSideSetNumDFPerSide(int *s) +{ + FREE(this->SideSetNumDFPerSide); + + this->SideSetNumDFPerSide= s; +} +int vtkModelMetadata::SetSideSetSize(int *size) +{ + FREE(this->SideSetSize); + + if (size) + { + this->SideSetSize = size; + + this->BuildSideSetListIndex(); + } + + return 0; +} +int vtkModelMetadata::SetSideSetNumberOfDistributionFactors(int *df) +{ + FREE(this->SideSetNumberOfDistributionFactors) + + if (df) + { + this->SideSetNumberOfDistributionFactors = df; + + this->BuildSideSetDistributionFactorIndex(); + } + + return 0; +} +void vtkModelMetadata::SetSideSetDistributionFactors(float *d) +{ + FREE(this->SideSetDistributionFactors); + + this->SideSetDistributionFactors = d; +} + +int vtkModelMetadata::BuildSideSetListIndex() +{ + int nsets = this->NumberOfSideSets; + int *size = this->SideSetSize; + + if ((nsets < 1) || !size) + { + return 1; + } + + if (this->SideSetListIndex) + { + delete [] this->SideSetListIndex; + } + this->SideSetListIndex = new int [ nsets ]; + + int idx = 0; + for (int i=0; iSideSetListIndex[i] = idx; + idx += size[i]; + } + + this->SumSidesPerSideSet = idx; + return 0; +} +int vtkModelMetadata::BuildSideSetDistributionFactorIndex() +{ + int nsets = this->NumberOfSideSets; + int *numFactors = this->SideSetNumberOfDistributionFactors; + + if ((nsets < 1) || !numFactors) + { + return 1; + } + + if (this->SideSetDistributionFactorIndex) + { + delete [] this->SideSetDistributionFactorIndex; + } + this->SideSetDistributionFactorIndex = new int [ nsets ]; + + int idx = 0; + + for (int i=0; iSideSetDistributionFactorIndex[i] = idx; + idx += numFactors[i]; + } + + this->SumDistFactPerSideSet = idx; + + return 0; +} + +//------------------------------------------------- +// Properties +//------------------------------------------------- + +void vtkModelMetadata::SetBlockPropertyNames(int nprop, char **nms) +{ + int i; + + FREELIST(this->BlockPropertyNames, this->NumberOfBlockProperties); + + this->NumberOfBlockProperties = nprop; + this->BlockPropertyNames = nms; +} +void vtkModelMetadata::SetBlockPropertyValue(int *v) +{ + FREE(this->BlockPropertyValue); + + this->BlockPropertyValue = v; +} +void vtkModelMetadata::SetNodeSetPropertyNames(int nprops, char **nms) +{ + int i; + + FREELIST(this->NodeSetPropertyNames, this->NumberOfNodeSetProperties); + + this->NumberOfNodeSetProperties = nprops; + this->NodeSetPropertyNames = nms; +} +void vtkModelMetadata::SetNodeSetPropertyValue(int *v) +{ + FREE(this->NodeSetPropertyValue); + + this->NodeSetPropertyValue = v; +} +void vtkModelMetadata::SetSideSetPropertyNames(int nprops, char **nms) +{ + int i; + + FREELIST(this->SideSetPropertyNames, this->NumberOfSideSetProperties); + + this->NumberOfSideSetProperties = nprops; + this->SideSetPropertyNames = nms; +} +void vtkModelMetadata::SetSideSetPropertyValue(int *v) +{ + FREE(this->SideSetPropertyValue); + + this->SideSetPropertyValue = v; +} +//------------------------------------------------- +// Global variables +//------------------------------------------------- + +void vtkModelMetadata::SetGlobalVariableNames(int num, char **n) +{ + int i; + + FREELIST(this->GlobalVariableNames, this->NumberOfGlobalVariables); + + this->GlobalVariableNames = n; + this->NumberOfGlobalVariables = num; +} +void vtkModelMetadata::SetGlobalVariableValue(float *f) +{ + FREE(this->GlobalVariableValue); + + this->GlobalVariableValue = f; +} +//------------------------------------------------- +// Element variables +//------------------------------------------------- + +int vtkModelMetadata::FindNameOnList(char *name, char **list, int listLen) +{ + int found = -1; + + for (int i=0; iFreeOriginalElementVariableNames(); + + this->OriginalNumberOfElementVariables = nvars; + this->OriginalElementVariableNames = names; +} +void vtkModelMetadata::SetElementVariableNames(int nvars, char **names) +{ + this->FreeUsedElementVariableNames(); + + this->NumberOfElementVariables = nvars; + this->MaxNumberOfElementVariables = nvars; + this->ElementVariableNames = names; +} +void vtkModelMetadata::SetElementVariableNumberOfComponents(int *comp) +{ + FREE(this->ElementVariableNumberOfComponents); + this->ElementVariableNumberOfComponents = comp; +} +void vtkModelMetadata::SetMapToOriginalElementVariableNames(int *map) +{ + FREE(this->MapToOriginalElementVariableNames); + this->MapToOriginalElementVariableNames = map; +} + +int vtkModelMetadata::AddUGridElementVariable(char *ugridVarName, + char *origName, int numComponents) +{ + int i; + + int maxVarNames = this->OriginalNumberOfElementVariables; + + if (maxVarNames < 1) + { + vtkErrorMacro(<< "Can't have grid variables if there are no file variables"); + return 1; + } + + if (this->ElementVariableNames == NULL) + { + this->FreeUsedElementVariables(); + + this->ElementVariableNames = new char * [maxVarNames]; // upper bound + + memset(this->ElementVariableNames, 0, sizeof (char *) * maxVarNames); + + this->NumberOfElementVariables = 0; + this->MaxNumberOfElementVariables = maxVarNames; + + this->MapToOriginalElementVariableNames = new int [maxVarNames]; + this->ElementVariableNumberOfComponents = new int [maxVarNames]; + } + else if (vtkModelMetadata::FindNameOnList(ugridVarName, + this->ElementVariableNames, this->NumberOfElementVariables) >= 0) + { + return 0; // already got it + } + + int next = this->NumberOfElementVariables; + + if (next >= this->MaxNumberOfElementVariables) + { + int newSize = this->MaxNumberOfElementVariables + maxVarNames; + + char **names = new char * [newSize]; + memset(names, 0, sizeof(char *) * newSize); + int *comp = new int [newSize]; + int *map = new int [newSize]; + + memcpy(names, this->ElementVariableNames, sizeof(char *) * next); + memcpy(comp, this->ElementVariableNumberOfComponents, sizeof(int) * next); + memcpy(map, this->MapToOriginalElementVariableNames, sizeof(int) * next); + + this->FreeUsedElementVariables(); + + this->ElementVariableNames = names; + this->ElementVariableNumberOfComponents = comp; + this->MapToOriginalElementVariableNames = map; + + this->MaxNumberOfElementVariables = newSize; + } + + this->ElementVariableNames[next] = ugridVarName; + this->ElementVariableNumberOfComponents[next] = numComponents; + + int idx = -1; + + for (i=0; iOriginalNumberOfElementVariables; i++) + { + if (!strcmp(this->OriginalElementVariableNames[i], origName)) + { + idx = i; + break; + } + } + + this->MapToOriginalElementVariableNames[next] = idx; + + this->NumberOfElementVariables++; + + delete [] origName; + + return 0; +} +int vtkModelMetadata::RemoveUGridElementVariable(char *ugridVarName) +{ + int i; + int maxVarNames = this->NumberOfElementVariables; + + int idx = vtkModelMetadata::FindNameOnList(ugridVarName, + this->ElementVariableNames, maxVarNames); + + if (idx == -1) return 1; + + delete [] this->ElementVariableNames[idx]; + + for (i=idx+1; iElementVariableNames[prev] = this->ElementVariableNames[i]; + this->ElementVariableNumberOfComponents[prev] = + this->ElementVariableNumberOfComponents[i]; + this->MapToOriginalElementVariableNames[prev] = + this->MapToOriginalElementVariableNames[i]; + } + + this->ElementVariableNames[maxVarNames-1] = NULL; + + this->NumberOfElementVariables--; + + return 0; +} +void vtkModelMetadata::SetElementVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map) +{ + this->SetOriginalElementVariableNames(numOrigNames, origNames); + this->SetElementVariableNames(numNames, names); + this->SetElementVariableNumberOfComponents(numComp); + this->SetMapToOriginalElementVariableNames(map); +} +//------------------------------------------------- +// Truth table +//------------------------------------------------- + +void vtkModelMetadata::SetElementVariableTruthTable(int *n) +{ + FREE(this->ElementVariableTruthTable); + this->AllVariablesDefinedInAllBlocks = 1; // the default + + if (n) + { + this->ElementVariableTruthTable= n; + + int numEntries = this->NumberOfBlocks * this->OriginalNumberOfElementVariables; + + for (int i=0; iAllVariablesDefinedInAllBlocks = 0; + break; + } + } + } +} + +//------------------------------------------------- +// Node variables +//------------------------------------------------- + +void vtkModelMetadata::SetOriginalNodeVariableNames(int nvars, char **names) +{ + this->FreeOriginalNodeVariableNames(); + + this->OriginalNumberOfNodeVariables = nvars; + this->OriginalNodeVariableNames = names; +} +void vtkModelMetadata::SetNodeVariableNames(int nvars, char **names) +{ + this->FreeUsedNodeVariableNames(); + + this->NumberOfNodeVariables = nvars; + this->MaxNumberOfNodeVariables = nvars; + this->NodeVariableNames = names; +} +void vtkModelMetadata::SetNodeVariableNumberOfComponents(int *comp) +{ + FREE(this->NodeVariableNumberOfComponents); + this->NodeVariableNumberOfComponents = comp; +} +void vtkModelMetadata::SetMapToOriginalNodeVariableNames(int *map) +{ + FREE(this->MapToOriginalNodeVariableNames); + this->MapToOriginalNodeVariableNames = map; +} + +int vtkModelMetadata::AddUGridNodeVariable(char *ugridVarName, + char *origName, int numComponents) +{ + int i; + + int maxVarNames = this->OriginalNumberOfNodeVariables; + + if (maxVarNames < 1) + { + vtkErrorMacro(<< "Can't have grid variables if there are no file variables"); + return 1; + } + + if (this->NodeVariableNames == NULL) + { + this->FreeUsedNodeVariableNames(); + + this->NodeVariableNames = new char * [maxVarNames]; // upper bound + + memset(this->NodeVariableNames, 0, sizeof (char *) * maxVarNames); + + this->NumberOfNodeVariables = 0; + this->MaxNumberOfNodeVariables = maxVarNames; + + this->MapToOriginalNodeVariableNames = new int [maxVarNames]; + this->NodeVariableNumberOfComponents = new int [maxVarNames]; + } + else if (vtkModelMetadata::FindNameOnList(ugridVarName, + this->NodeVariableNames, this->NumberOfNodeVariables) >= 0) + { + return 0; // already got it + } + + int next = this->NumberOfNodeVariables; + + if (next >= this->MaxNumberOfNodeVariables) + { + int newSize = this->MaxNumberOfNodeVariables + maxVarNames; + + char **names = new char * [newSize]; + memset(names, 0, sizeof(char *) * newSize); + int *comp = new int [newSize]; + int *map = new int [newSize]; + + memcpy(names, this->NodeVariableNames, sizeof(char *) * next); + memcpy(comp, this->NodeVariableNumberOfComponents, sizeof(int) * next); + memcpy(map, this->MapToOriginalNodeVariableNames, sizeof(int) * next); + + this->FreeUsedNodeVariableNames(); + + this->NodeVariableNames = names; + this->NodeVariableNumberOfComponents = comp; + this->MapToOriginalNodeVariableNames = map; + + this->MaxNumberOfNodeVariables = newSize; + } + + this->NodeVariableNames[next] = ugridVarName; + this->NodeVariableNumberOfComponents[next] = numComponents; + + int idx = -1; + + for (i=0; iOriginalNumberOfNodeVariables; i++) + { + if (!strcmp(this->OriginalNodeVariableNames[i], origName)) + { + idx = i; + break; + } + } + + this->MapToOriginalNodeVariableNames[next] = idx; + + this->NumberOfNodeVariables++; + + delete [] origName; + + return 0; +} +int vtkModelMetadata::RemoveUGridNodeVariable(char *ugridVarName) +{ + int i; + int maxVarNames = this->NumberOfNodeVariables; + + int idx = vtkModelMetadata::FindNameOnList(ugridVarName, + this->NodeVariableNames, maxVarNames); + + if (idx == -1) return 1; + + delete [] this->NodeVariableNames[idx]; + + for (i=idx+1; iNodeVariableNames[prev] = this->NodeVariableNames[i]; + this->NodeVariableNumberOfComponents[prev] = + this->NodeVariableNumberOfComponents[i]; + this->MapToOriginalNodeVariableNames[prev] = + this->MapToOriginalNodeVariableNames[i]; + } + + this->NodeVariableNames[maxVarNames-1] = NULL; + + this->NumberOfNodeVariables--; + + return 0; +} +void vtkModelMetadata::SetNodeVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map) +{ + this->SetOriginalNodeVariableNames(numOrigNames, origNames); + this->SetNodeVariableNames(numNames, names); + this->SetNodeVariableNumberOfComponents(numComp); + this->SetMapToOriginalNodeVariableNames(map); +} + +//--------------------------------------------------------------- +// Pack all the metadata into an unstructured grid, or +// initialize this vtkModelMetadata object with information packed +// into an unstructured grid (i.e. unpack). +//--------------------------------------------------------------- + +#define SIZE_ARRAY "vtkModelMetadataSizes" +#define INT_ARRAY "vtkModelMetadataInts" +#define FLOAT_ARRAY "vtkModelMetadataFloats" +#define CHAR_ARRAY "vtkModelMetadataChars" + +void vtkModelMetadata::RemoveMetadata(vtkDataSet *grid) +{ + grid->GetFieldData()->RemoveArray(SIZE_ARRAY); + grid->GetFieldData()->RemoveArray(INT_ARRAY); + grid->GetFieldData()->RemoveArray(FLOAT_ARRAY); + grid->GetFieldData()->RemoveArray(CHAR_ARRAY); +} + +int vtkModelMetadata::HasMetadata(vtkDataSet *grid) +{ + int hasMetadata = 0; + + if (grid) + { + vtkFieldData *fa = grid->GetFieldData(); + + if (fa) + { + vtkDataArray *da = fa->GetArray(SIZE_ARRAY); + if (da) hasMetadata = 1; + } + } + + return hasMetadata; +} + +void vtkModelMetadata::Pack(vtkDataSet *grid) +{ + int maxStringLength, maxLineLength; + + this->CalculateMaximumLengths(maxStringLength, maxLineLength); + + vtkIntArray *sizes = this->PackSizeArray(maxStringLength, maxLineLength); + vtkIntArray *ints = this->PackIntArray(); + vtkCharArray *chars = this->PackCharArray(maxStringLength, maxLineLength); + vtkFloatArray *floats = this->PackFloatArray(); + + vtkFieldData *fa = grid->GetFieldData(); + + if (!fa) + { + fa = vtkFieldData::New(); + grid->SetFieldData(fa); + fa->Delete(); + fa = grid->GetFieldData(); + } + + fa->AddArray(sizes); + sizes->Delete(); + + if (ints->GetNumberOfTuples() > 0) + { + fa->AddArray(ints); + ints->Delete(); + } + + if (chars->GetNumberOfTuples() > 0) + { + fa->AddArray(chars); + chars->Delete(); + } + + if (floats->GetNumberOfTuples() > 0) + { + fa->AddArray(floats); + floats->Delete(); + } +} +int vtkModelMetadata::Unpack(vtkDataSet *grid, int deleteIt) +{ + vtkFieldData *fa = grid->GetFieldData(); + + if (!fa) + { + return 1; + } + + vtkDataArray *da = fa->GetArray(SIZE_ARRAY); + vtkIntArray *sizes = vtkIntArray::SafeDownCast(da); + + if (!sizes) + { + return 1; + } + + this->Reset(); + + // NOTE: The size array must be unpacked before any other, because + // it provides information about the contents of the other arrays. + // We keep the sizes in a temporary object until "this" object is set. + + vtkModelMetadata *temp = vtkModelMetadata::New(); + + int maxString=0; + int maxLine=0; + + int fail = temp->InitializeFromSizeArray(sizes, maxString, maxLine); + + if (fail) + { + temp->Delete(); + return 1; + } + + if (deleteIt) + { + fa->RemoveArray(SIZE_ARRAY); + } + + da = fa->GetArray(INT_ARRAY); + vtkIntArray *ints = vtkIntArray::SafeDownCast(da); + + if (ints) + { + fail = this->InitializeFromIntArray(temp, ints); + + if (fail) + { + temp->Delete(); + return 1; + } + if (deleteIt) + { + fa->RemoveArray(INT_ARRAY); + } + } + + da = fa->GetArray(CHAR_ARRAY); + vtkCharArray *chars = vtkCharArray::SafeDownCast(da); + + if (chars) + { + fail = this->InitializeFromCharArray(temp, chars, maxString, maxLine); + + if (fail) + { + temp->Delete(); + return 1; + } + if (deleteIt) + { + fa->RemoveArray(CHAR_ARRAY); + } + } + + da = fa->GetArray(FLOAT_ARRAY); + vtkFloatArray *floats = vtkFloatArray::SafeDownCast(da); + + if (floats) + { + fail = this->InitializeFromFloatArray(floats); + + if (fail) + { + temp->Delete(); + return 1; + } + + if (deleteIt) + { + fa->RemoveArray(FLOAT_ARRAY); + } + } + + temp->Delete(); + + return 0; +} +vtkIntArray *vtkModelMetadata::PackSizeArray(int maxStr, int maxLine) +{ +// Fields stored in size array: +// int NumberOfQARecords; +// int NumberOfInformationLines; +// int Dimension; +// int NumberOfBlocks; +// int NumberOfNodeSets; +// int NumberOfSideSets; +// int NumberOfBlockProperties; +// int NumberOfNodeSetProperties; +// int NumberOfSideSetProperties; +// int NumberOfGlobalVariables; +// int NumberOfElementVariables; +// int NumberOfNodeVariables; +// int OriginalNumberOfElementVariables; +// int OriginalNumberOfNodeVariables; +// int MaxStringLength +// int MaxLineLength + + vtkIntArray *sizeInfo = vtkIntArray::New(); + sizeInfo->SetName(SIZE_ARRAY); + + sizeInfo->SetNumberOfValues(16); + + sizeInfo->SetValue(0, this->NumberOfQARecords); + sizeInfo->SetValue(1, this->NumberOfInformationLines); + sizeInfo->SetValue(2, this->Dimension); + sizeInfo->SetValue(3, this->NumberOfBlocks); + sizeInfo->SetValue(4, this->NumberOfNodeSets); + sizeInfo->SetValue(5, this->NumberOfSideSets); + sizeInfo->SetValue(6, this->NumberOfBlockProperties); + sizeInfo->SetValue(7, this->NumberOfNodeSetProperties); + sizeInfo->SetValue(8, this->NumberOfSideSetProperties); + sizeInfo->SetValue(9, this->NumberOfGlobalVariables); + sizeInfo->SetValue(10, this->NumberOfElementVariables); + sizeInfo->SetValue(11, this->NumberOfNodeVariables); + sizeInfo->SetValue(12, this->OriginalNumberOfElementVariables); + sizeInfo->SetValue(13, this->OriginalNumberOfNodeVariables); + sizeInfo->SetValue(14, maxStr); + sizeInfo->SetValue(15, maxLine); + + return sizeInfo; +} +int vtkModelMetadata::InitializeFromSizeArray(vtkIntArray *ia, int &maxS, int &maxL) +{ + int nvals = ia->GetNumberOfTuples(); + + if (nvals < 16) return 1; + + this->NumberOfQARecords = ia->GetValue(0); + this->NumberOfInformationLines = ia->GetValue(1); + this->Dimension = ia->GetValue(2); + this->NumberOfBlocks = ia->GetValue(3); + this->NumberOfNodeSets = ia->GetValue(4); + this->NumberOfSideSets = ia->GetValue(5); + this->NumberOfBlockProperties = ia->GetValue(6); + this->NumberOfNodeSetProperties = ia->GetValue(7); + this->NumberOfSideSetProperties = ia->GetValue(8); + this->NumberOfGlobalVariables = ia->GetValue(9); + this->NumberOfElementVariables = ia->GetValue(10); + this->NumberOfNodeVariables = ia->GetValue(11); + this->OriginalNumberOfElementVariables = ia->GetValue(12); + this->OriginalNumberOfNodeVariables = ia->GetValue(13); + maxS = ia->GetValue(14); + maxL = ia->GetValue(15); + + return 0; +} +#define __CHECK_COPY(to, from, size) \ + (from ? memcpy(to, from, size) : memset(to, 0, size)); + +vtkIntArray *vtkModelMetadata::PackIntArray() +{ +// Fields stored in the integer array +// 3 counts: Sum of all node set sizes, sum of all side set sizes, +// and sum of all elements per block +// 1 integer: the current time step index +// int *BlockIds; // NumberOfBlocks +// int *BlockNumberOfElements; // NumberOfBlocks +// int *BlockNodesPerElement; // NumberOfBlocks +// int *BlockNumberOfAttributesPerElement;// NumberOfBlocks +// int *BlockElementIdList; // SumElementsPerBlock +// int *NodeSetIds; // NumberOfNodeSets +// int *NodeSetSize; // NumberOfNodeSets +// int *NodeSetNumberOfDistributionFactors; // NumberOfNodeSets +// int *NodeSetNodeIdList; // SumNodesPerNodeSet +// int *SideSetIds; // NumberOfSideSets +// int *SideSetSize; // NumberOfSideSets +// int *SideSetNumberOfDistributionFactors; // NumberOfSideSets +// int *SideSetElementList; // SumSidesPerSideSet +// int *SideSetSideList; // SumSidesPerSideSet +// int *SideSetNumDFPerSide; // SumSidesPerSideSet +// int *BlockPropertyValue; // NumBlocks * NumBlockProperties +// int *NodeSetPropertyValue; // NumNodeSets * NumNodeSetProperties +// int *SideSetPropertyValue; // NumSideSets * NumSideSetProperties +// int *ElementVariableTruthTable; // NumBlocks * OrigNumElementVariables +// int *ElementVariableNumberOfComponents; // NumberOfElementVariables +// int *MapToOriginalElementVariableNames; // NumberOfElementVariables +// int *NodeVariableNumberOfComponents; // NumberOfNodeVariables +// int *MapToOriginalNodeVariableNames; // NumberOfNodeVariables + + int nblocks = this->NumberOfBlocks; + int nnsets = this->NumberOfNodeSets; + int nssets = this->NumberOfSideSets; + int nblockProp = this->NumberOfBlockProperties; + int nnsetProp = this->NumberOfNodeSetProperties; + int nssetProp = this->NumberOfSideSetProperties; + int nOrigEltVars = this->OriginalNumberOfElementVariables; + int nEltVars = this->NumberOfElementVariables; + int nNodeVars = this->NumberOfNodeVariables; + + vtkIdType nvals = 4 + + (nblocks * 4) + this->SumElementsPerBlock + + (nnsets * 3) + this->SumNodesPerNodeSet + + (nssets * 3) + (this->SumSidesPerSideSet * 3) + + (nblocks * nblockProp) + + (nnsets * nnsetProp) + + (nssets * nssetProp) + + (nblocks * nOrigEltVars) + + (nEltVars * 2) + + (nNodeVars * 2); + + int *packed = new int [nvals]; + int *p = packed; + + p[0] = this->SumNodesPerNodeSet; + p[1] = this->SumSidesPerSideSet; + p[2] = this->SumElementsPerBlock; + p[3] = this->TimeStepIndex; + + p += 4; + + if (nblocks > 0) + { + size_t n = sizeof(int) * nblocks; + + __CHECK_COPY(p, this->BlockIds, n) + p += nblocks; + + __CHECK_COPY(p, this->BlockNumberOfElements, n) + p += nblocks; + + __CHECK_COPY(p, this->BlockNodesPerElement, n) + p += nblocks; + + __CHECK_COPY(p, this->BlockNumberOfAttributesPerElement, n) + p += nblocks; + + __CHECK_COPY(p, this->BlockElementIdList, sizeof(int) * this->SumElementsPerBlock) + p += this->SumElementsPerBlock; + } + + if (nnsets > 0) + { + size_t n = sizeof(int) * nnsets; + + __CHECK_COPY(p, this->NodeSetIds, n); + p += nnsets; + + __CHECK_COPY(p, this->NodeSetSize, n); + p += nnsets; + + __CHECK_COPY(p, this->NodeSetNumberOfDistributionFactors, n); + p += nnsets; + + __CHECK_COPY(p, this->NodeSetNodeIdList, sizeof(int) * this->SumNodesPerNodeSet); + p += this->SumNodesPerNodeSet; + } + + if (nssets > 0) + { + size_t n = sizeof(int) * nssets; + + __CHECK_COPY(p, this->SideSetIds, n); + p += nssets; + + __CHECK_COPY(p, this->SideSetSize, n); + p += nssets; + + __CHECK_COPY(p, this->SideSetNumberOfDistributionFactors, n); + p += nssets; + + size_t sum = sizeof(int) * this->SumSidesPerSideSet; + + __CHECK_COPY(p, this->SideSetElementList, sum); + p += this->SumSidesPerSideSet; + + __CHECK_COPY(p, this->SideSetSideList, sum); + p += this->SumSidesPerSideSet; + + __CHECK_COPY(p, this->SideSetNumDFPerSide, sum); + p += this->SumSidesPerSideSet; + } + + if (nblockProp > 0) + { + __CHECK_COPY(p, this->BlockPropertyValue, + sizeof(int) * nblockProp * nblocks); + p += (nblockProp * nblocks); + } + + if (nnsetProp > 0) + { + __CHECK_COPY(p, this->NodeSetPropertyValue, + sizeof(int) * nnsetProp * nnsets); + p += (nnsetProp * nnsets); + } + + if (nssetProp > 0) + { + __CHECK_COPY(p, this->SideSetPropertyValue, + sizeof(int) * nssetProp * nssets); + p += (nssetProp * nssets); + } + + if ((nblocks > 0) && (nOrigEltVars > 0)) + { + __CHECK_COPY(p, this->ElementVariableTruthTable, + sizeof(int) * nblocks * nOrigEltVars); + p += (nblocks * nOrigEltVars); + } + + if (nEltVars > 0) + { + __CHECK_COPY(p, this->ElementVariableNumberOfComponents, + sizeof(int) * nEltVars); + p += nEltVars; + + __CHECK_COPY(p, this->MapToOriginalElementVariableNames, + sizeof(int) * nEltVars); + p += nEltVars; + } + + if (nNodeVars > 0) + { + __CHECK_COPY(p, this->NodeVariableNumberOfComponents, + sizeof(int) * nNodeVars); + p += nNodeVars; + + __CHECK_COPY(p, this->MapToOriginalNodeVariableNames, + sizeof(int) * nNodeVars); + p += nNodeVars; + } + + vtkIntArray *ia = vtkIntArray::New(); + ia->SetName(INT_ARRAY); + ia->SetArray(packed, nvals, 0); + + return ia; +} +int vtkModelMetadata::InitializeFromIntArray(vtkModelMetadata *sizes, vtkIntArray *ia) +{ + int nblocks = sizes->NumberOfBlocks; + int nnsets = sizes->NumberOfNodeSets; + int nssets = sizes->NumberOfSideSets; + int nblockProp = sizes->NumberOfBlockProperties; + int nnsetProp = sizes->NumberOfNodeSetProperties; + int nssetProp = sizes->NumberOfSideSetProperties; + int nEltVars = sizes->NumberOfElementVariables; + int nNodeVars = sizes->NumberOfNodeVariables; + int ttsize = nblocks * sizes->OriginalNumberOfElementVariables; + + int *p = ia->GetPointer(0); + + int sumNodeSetSizes = p[0]; + int sumSideSetSizes = p[1]; + int sumElementIds = p[2]; + + this->TimeStepIndex = p[3]; + + p += 4; + + if (nblocks > 0) + { + int *buf = new int [nblocks]; + memcpy(buf, p, nblocks * sizeof(int)); + p += nblocks; + + this->SetNumberOfBlocks(nblocks); + this->SetBlockIds(buf); + + buf = new int [nblocks]; + memcpy(buf, p, nblocks * sizeof(int)); + p += nblocks; + + this->SetBlockNumberOfElements(buf); + + buf = new int [nblocks]; + memcpy(buf, p, nblocks * sizeof(int)); + p += nblocks; + + this->SetBlockNodesPerElement(buf); + + buf = new int [nblocks]; + memcpy(buf, p, nblocks * sizeof(int)); + p += nblocks; + + this->SetBlockNumberOfAttributesPerElement(buf); + + buf = new int [sumElementIds]; + memcpy(buf, p, sumElementIds * sizeof(int)); + p += sumElementIds; + + this->SetBlockElementIdList(buf); + } + + if (nnsets > 0) + { + int *buf = new int [nnsets]; + memcpy(buf, p, nnsets * sizeof(int)); + p += nnsets; + + this->SetNumberOfNodeSets(nnsets); + this->SetNodeSetIds(buf); + + buf = new int [nnsets]; + memcpy(buf, p, nnsets * sizeof(int)); + p += nnsets; + + this->SetNodeSetSize(buf); + + buf = new int [nnsets]; + memcpy(buf, p, nnsets * sizeof(int)); + p += nnsets; + + this->SetNodeSetNumberOfDistributionFactors(buf); + + buf = new int [sumNodeSetSizes]; + memcpy(buf, p, sumNodeSetSizes * sizeof(int)); + p += sumNodeSetSizes; + + this->SetNodeSetNodeIdList(buf); + } + + if (nssets > 0) + { + int *buf = new int [nssets]; + memcpy(buf, p, nssets * sizeof(int)); + p += nssets; + + this->SetNumberOfSideSets(nssets); + this->SetSideSetIds(buf); + + buf = new int [nssets]; + memcpy(buf, p, nssets * sizeof(int)); + p += nssets; + + this->SetSideSetSize(buf); + + buf = new int [nssets]; + memcpy(buf, p, nssets * sizeof(int)); + p += nssets; + + this->SetSideSetNumberOfDistributionFactors(buf); + + buf = new int [sumSideSetSizes]; + memcpy(buf, p, sumSideSetSizes * sizeof(int)); + p += sumSideSetSizes; + + this->SetSideSetElementList(buf); + + buf = new int [sumSideSetSizes]; + memcpy(buf, p, sumSideSetSizes * sizeof(int)); + p += sumSideSetSizes; + + this->SetSideSetSideList(buf); + + buf = new int [sumSideSetSizes]; + memcpy(buf, p, sumSideSetSizes * sizeof(int)); + p += sumSideSetSizes; + + this->SetSideSetNumDFPerSide(buf); + } + + if (nblockProp > 0) + { + int nvals = nblocks * nblockProp; + + int *buf = new int [nvals]; + memcpy(buf, p, nvals * sizeof(int)); + p += nvals ; + + this->SetBlockPropertyValue(buf); + } + + if (nnsetProp > 0) + { + int nvals = nnsets * nnsetProp; + + int *buf = new int [nvals]; + memcpy(buf, p, nvals * sizeof(int)); + p += nvals ; + + this->SetNodeSetPropertyValue(buf); + } + + if (nssetProp > 0) + { + int nvals = nssets * nssetProp; + + int *buf = new int [nvals]; + memcpy(buf, p, nvals * sizeof(int)); + p += nvals ; + + this->SetSideSetPropertyValue(buf); + } + + if (ttsize > 0) + { + int *buf = new int [ttsize]; + memcpy(buf, p, ttsize * sizeof(int)); + p += ttsize; + + this->SetElementVariableTruthTable(buf); + } + + if (nEltVars > 0) + { + int *buf1 = new int [nEltVars]; + memcpy(buf1, p, nEltVars * sizeof(int)); + p += nEltVars; + + int *buf2 = new int [nEltVars]; + memcpy(buf2, p, nEltVars * sizeof(int)); + p += nEltVars; + + this->SetElementVariableNumberOfComponents(buf1); + this->SetMapToOriginalElementVariableNames(buf2); + } + + if (nNodeVars > 0) + { + int *buf1 = new int [nNodeVars]; + memcpy(buf1, p, nNodeVars * sizeof(int)); + p += nNodeVars; + + int *buf2 = new int [nNodeVars]; + memcpy(buf2, p, nNodeVars * sizeof(int)); + p += nNodeVars; + + this->SetNodeVariableNumberOfComponents(buf1); + this->SetMapToOriginalNodeVariableNames(buf2); + } + + return 0; +} +char *vtkModelMetadata::WriteLines( + char *p, int maxLines, int maxLen, char **lines) +{ + for (int i=0; iNumberOfQARecords * 4 * maxS); + + len += (this->NumberOfInformationLines * maxL); + + len += (this->Dimension * maxS); + + len += (this->NumberOfBlocks * maxS); + + len += (this->NumberOfBlockProperties * maxS); + + len += (this->NumberOfNodeSetProperties * maxS); + + len += (this->NumberOfSideSetProperties * maxS); + + len += (this->NumberOfGlobalVariables * maxS); + + len += (this->OriginalNumberOfElementVariables * maxS); + + len += (this->NumberOfElementVariables * maxS); + + len += (this->OriginalNumberOfNodeVariables * maxS); + + len += (this->NumberOfNodeVariables * maxS); + + char *uc = new char [len]; + + memset(uc, 0, len); + + char *p = uc; + + if (this->Title) + { + strcpy(p, this->Title); + } + else + { + strcpy(p, "NULL"); + } + + p += maxL; + + for (int i=0; iNumberOfQARecords; i++) + { + for (int j=0; j<4; j++) + { + int l = strlen(this->QARecord[i][j]); + if (l > maxS) l = maxS; + + memcpy(p, this->QARecord[i][j], l); + + p += maxS; + } + } + + p = vtkModelMetadata::WriteLines(p, this->NumberOfInformationLines, + maxL, this->InformationLine); + + p = vtkModelMetadata::WriteLines(p, this->Dimension, + maxS, this->CoordinateNames); + + p = vtkModelMetadata::WriteLines(p, this->NumberOfBlocks, + maxS, this->BlockElementType); + + p = vtkModelMetadata::WriteLines(p, this->NumberOfBlockProperties, + maxS, this->BlockPropertyNames); + + p = vtkModelMetadata::WriteLines(p, this->NumberOfNodeSetProperties, + maxS, this->NodeSetPropertyNames); + + p = vtkModelMetadata::WriteLines(p, this->NumberOfSideSetProperties, + maxS, this->SideSetPropertyNames); + + p = vtkModelMetadata::WriteLines(p, this->NumberOfGlobalVariables, + maxS, this->GlobalVariableNames); + + p = vtkModelMetadata::WriteLines(p, this->OriginalNumberOfElementVariables, + maxS, this->OriginalElementVariableNames); + + p = vtkModelMetadata::WriteLines(p, this->NumberOfElementVariables, + maxS, this->ElementVariableNames); + + p = vtkModelMetadata::WriteLines(p, this->OriginalNumberOfNodeVariables, + maxS, this->OriginalNodeVariableNames); + + p = vtkModelMetadata::WriteLines(p, this->NumberOfNodeVariables, + maxS, this->NodeVariableNames); + + vtkCharArray *uca = vtkCharArray::New(); + uca->SetArray(uc, len, 0); + uca->SetName(CHAR_ARRAY); + + return uca; +} +char *vtkModelMetadata::ReadLines( + char ***to, int maxLines, int maxLen, char *from) +{ + char **lineList = new char * [maxLines]; + + for (int i=0; iGetPointer(0); + char **buf = NULL; + + if (!uc) + { + return 1; + } + + this->Title = new char [maxL + 1]; + memcpy(this->Title, uc, maxL); + this->Title[maxL] = '\0'; + + uc += maxL; + + int num = sizes->GetNumberOfQARecords(); + + if (num > 0) + { + typedef char *p4[4]; + + p4 *qaRec = new p4 [num]; + + for (int i=0; iSetQARecords(num, qaRec); + } + + num = sizes->GetNumberOfInformationLines(); + + if (num > 0) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxL, uc); + this->SetInformationLines(num, buf); + } + + num = sizes->GetDimension(); + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetCoordinateNames(num, buf); + } + + if (this->NumberOfBlocks) // set in InitializeFromIntArray + { + uc = vtkModelMetadata::ReadLines(&this->BlockElementType, + this->NumberOfBlocks, maxS, uc); + } + + num = sizes->GetNumberOfBlockProperties(); + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetBlockPropertyNames(num, buf); + } + + num = sizes->GetNumberOfNodeSetProperties(); + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetNodeSetPropertyNames(num, buf); + } + + num = sizes->GetNumberOfSideSetProperties(); + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetSideSetPropertyNames(num, buf); + } + + num = sizes->GetNumberOfGlobalVariables(); + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetGlobalVariableNames(num, buf); + } + + num = sizes->OriginalNumberOfElementVariables; + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetOriginalElementVariableNames(num, buf); + } + + num = sizes->NumberOfElementVariables; + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetElementVariableNames(num, buf); + } + + num = sizes->OriginalNumberOfNodeVariables; + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetOriginalNodeVariableNames(num, buf); + } + + num = sizes->NumberOfNodeVariables; + + if (num) + { + uc = vtkModelMetadata::ReadLines(&buf, num, maxS, uc); + this->SetNodeVariableNames(num, buf); + } + + return 0; +} +vtkFloatArray *vtkModelMetadata::PackFloatArray() +{ +// Fields stored in the float array: +// 4 counts: SizeBlockAttributeArray, SumDistFactPerNodeSet, +// SumDistFactPerSideSet, and NumberOfTimeSteps +// float *BlockAttributes; // SizeBlockAttributeArray +// float *NodeSetDistributionFactors; // SumDistFactPerNodeSet +// float *SideSetDistributionFactors; // SumDistFactPerSideSet +// float *GlobalVariableValue; // NumberOfGlobalVariables +// float *TimeStepValues; // NumberOfTimeSteps +// + + vtkIdType len = 4 + + this->SizeBlockAttributeArray + + this->SumDistFactPerNodeSet + + this->SumDistFactPerSideSet + + this->NumberOfGlobalVariables + + this->NumberOfTimeSteps; + + float *f = new float [len]; + + f[0] = static_cast(this->SizeBlockAttributeArray); + f[1] = static_cast(this->SumDistFactPerNodeSet); + f[2] = static_cast(this->SumDistFactPerSideSet); + f[3] = static_cast(this->NumberOfTimeSteps); + + float *nextf = f + 4; + + if (this->SizeBlockAttributeArray) + { + memcpy(nextf, this->BlockAttributes, + this->SizeBlockAttributeArray * sizeof(float)); + nextf += this->SizeBlockAttributeArray; + } + + if (this->SumDistFactPerNodeSet) + { + memcpy(nextf, this->NodeSetDistributionFactors, + this->SumDistFactPerNodeSet * sizeof(float)); + nextf += this->SumDistFactPerNodeSet; + } + + if (this->SumDistFactPerSideSet) + { + memcpy(nextf, this->SideSetDistributionFactors, + this->SumDistFactPerSideSet * sizeof(float)); + nextf += this->SumDistFactPerSideSet; + } + + if (this->NumberOfGlobalVariables) + { + memcpy(nextf, this->GlobalVariableValue, + this->NumberOfGlobalVariables * sizeof(float)); + nextf += this->NumberOfGlobalVariables; + } + + if (this->NumberOfTimeSteps) + { + memcpy(nextf, this->TimeStepValues, + this->NumberOfTimeSteps* sizeof(float)); + nextf += this->NumberOfTimeSteps; + } + + vtkFloatArray *fa = vtkFloatArray::New(); + fa->SetArray(f, len, 0); + fa->SetName(FLOAT_ARRAY); + + return fa; +} +int vtkModelMetadata::InitializeFromFloatArray(vtkFloatArray *fa) +{ + float *f = fa->GetPointer(0); + + int sizeBlockAttributeArray = static_cast(f[0]); + int sumDistFactPerNodeSet= static_cast(f[1]); + int sumDistFactPerSideSet= static_cast(f[2]); + int numTimeSteps = static_cast(f[3]); + + f += 4; + + if ((sizeBlockAttributeArray != this->SizeBlockAttributeArray) || + (sumDistFactPerNodeSet != this->SumDistFactPerNodeSet) || + (sumDistFactPerSideSet != this->SumDistFactPerSideSet)) + { + return 1; + } + + if (this->SizeBlockAttributeArray) + { + float *buf = new float [this->SizeBlockAttributeArray]; + memcpy(buf, f, sizeof(float) * this->SizeBlockAttributeArray); + this->SetBlockAttributes(buf); + + f += this->SizeBlockAttributeArray; + } + + if (this->SumDistFactPerNodeSet) + { + float *buf = new float [this->SumDistFactPerNodeSet]; + memcpy(buf, f, sizeof(float) * this->SumDistFactPerNodeSet); + this->SetNodeSetDistributionFactors(buf); + + f += this->SumDistFactPerNodeSet; + } + + if (this->SumDistFactPerSideSet) + { + float *buf = new float [this->SumDistFactPerSideSet]; + memcpy(buf, f, sizeof(float) * this->SumDistFactPerSideSet); + this->SetSideSetDistributionFactors(buf); + + f += this->SumDistFactPerSideSet; + } + + if (this->NumberOfGlobalVariables) + { + float *buf = new float [this->NumberOfGlobalVariables]; + memcpy(buf, f, sizeof(float) * this->NumberOfGlobalVariables); + this->SetGlobalVariableValue(buf); + + f += this->NumberOfGlobalVariables; + } + + if (numTimeSteps) + { + float *buf = new float [numTimeSteps]; + memcpy(buf, f, sizeof(float) * numTimeSteps); + this->SetTimeSteps(numTimeSteps, buf); + + f += numTimeSteps; + } + + return 0; +} + +//--------------------------------------------------------------- +// Merge and subset vtkModelMetadata objects. Because grids get +// merged and subsetted on their journey through the VTK reader and filters. +//--------------------------------------------------------------- + +int vtkModelMetadata::AppendFloatLists( + int numSubLists, + float *id1, int *id1Idx, int id1Len, + float *id2, int *id2Idx, int id2Len, + float **idNew, int **idNewIdx, int *idNewLen) +{ + if ((id1Len == 0) && (id2Len == 0)) + { + if (idNew) + { + *idNew = NULL; + } + if (idNewIdx) + { + *idNewIdx = NULL; + } + if (idNewLen) + { + *idNewLen = 0; + } + return 0; + } + + int i; + + int newIdListLength = id1Len + id2Len; + + float *newIdList = new float [newIdListLength]; + int *newIdListIndex = new int [numSubLists]; + + if (id1Len == 0) + { + memcpy(newIdList, id2, id2Len * sizeof(float)); + memcpy(newIdListIndex, id2Idx, numSubLists * sizeof(int)); + } + else if (id2Len == 0) + { + memcpy(newIdList, id1, id1Len * sizeof(float)); + memcpy(newIdListIndex, id1Idx, numSubLists * sizeof(int)); + } + else + { + newIdListIndex[0] = 0; + + int nextid = 0; + + for (i=0; i 0) + { + memcpy(newIdList + nextid, ids, numids * sizeof(float)); + nextid += numids; + } + + ids = id2 + id2Idx[i]; + numids = (lastList ? id2Len : id2Idx[i+1]) - id2Idx[i]; + + if (numids > 0) + { + memcpy(newIdList + nextid, ids, numids * sizeof(float)); + nextid += numids; + } + + if (!lastList) + { + newIdListIndex[i+1] = nextid; + } + else + { + newIdListLength = nextid; + } + } + } + + if (idNew) + { + *idNew = newIdList; + } + else + { + delete [] newIdList; + } + if (idNewIdx) + { + *idNewIdx = newIdListIndex; + } + else + { + delete [] newIdListIndex; + } + if (idNewLen) + { + *idNewLen = newIdListLength; + } + + return 0; +} +int vtkModelMetadata::AppendIntegerLists( + int numSubLists, + int *id1, int *id1Idx, int id1Len, + int *id2, int *id2Idx, int id2Len, + int **idNew, int **idNewIdx, int *idNewLen) +{ + if ((id1Len == 0) && (id2Len == 0)) + { + return 1; + } + + int i; + + int newIdListLength = id1Len + id2Len; + + int *newIdList = new int [newIdListLength]; + int *newIdListIndex = new int [numSubLists]; + + if (id1Len == 0) + { + memcpy(newIdList, id2, id2Len * sizeof(int)); + memcpy(newIdListIndex, id2Idx, numSubLists * sizeof(int)); + } + else if (id2Len == 0) + { + memcpy(newIdList, id1, id1Len * sizeof(int)); + memcpy(newIdListIndex, id1Idx, numSubLists * sizeof(int)); + } + else + { + newIdListIndex[0] = 0; + + int nextid = 0; + + for (i=0; i 0) + { + memcpy(newIdList + nextid, ids, numids * sizeof(int)); + nextid += numids; + } + + ids = id2 + id2Idx[i]; + numids = (lastList ? id2Len : id2Idx[i+1]) - id2Idx[i]; + + if (numids > 0) + { + memcpy(newIdList + nextid, ids, numids * sizeof(int)); + nextid += numids; + } + + if (!lastList) + { + newIdListIndex[i+1] = nextid; + } + else + { + newIdListLength = nextid; + } + } + } + + if (idNew) + { + *idNew = newIdList; + } + else + { + delete [] newIdList; + } + if (idNewIdx) + { + *idNewIdx = newIdListIndex; + } + else + { + delete [] newIdListIndex; + } + if (idNewLen) + { + *idNewLen = newIdListLength; + } + + return 0; +} + +int vtkModelMetadata::MergeIdLists(int numSubLists, + int *id1, int *id1Idx, int id1Len, + float *dist1, int *dist1Idx, int dist1Len, + int *id2, int *id2Idx, int id2Len, + float *dist2, int *dist2Idx, int dist2Len, + int **idNew, int **idNewIdx, int *idNewLen, + float **distNew, int **distNewIdx, int *distNewLen) +{ + if ((id1Len == 0) && (id2Len == 0)) + { + return 1; + } + + // Here we take two lists of IDs, and their associated lists of + // floating point factors. Some of the IDs in the second list may + // be duplicates of IDs in the first list, and we need to filter + // these out when we build the lists combining both. + + int i, id; + + int *newIdList=NULL; + int *newIdListIndex = NULL; + int newIdListLength = 0; + + float *newDistFact=NULL; + int *newDistFactIndex=NULL; + int newDistFactLength = 0; + + int maxIdListLength = id1Len + id2Len; + int maxDistFactLength = dist1Len + dist2Len; + + newIdList = new int [maxIdListLength]; + newIdListIndex = new int [numSubLists]; + newIdListIndex[0] = 0; + + int distFact = (maxDistFactLength > 0); + + if (distFact) + { + newDistFact = new float [maxDistFactLength]; + newDistFactIndex = new int [numSubLists]; + newDistFactIndex[0] = 0; + } + + if (id1Len == 0) + { + memcpy(newIdList, id2, sizeof(int) * id2Len); + memcpy(newIdListIndex, id2Idx, sizeof(int) * numSubLists); + newIdListLength = id2Len; + + if (newDistFact) + { + memcpy(newDistFact, dist2, sizeof(float) * dist2Len); + memcpy(newDistFactIndex, dist2Idx, sizeof(int) * numSubLists); + } + + newDistFactLength = dist2Len; + } + else if (id2Len == 0) + { + memcpy(newIdList, id1, sizeof(int) * id1Len); + memcpy(newIdListIndex, id1Idx, sizeof(int) * numSubLists); + newIdListLength = id1Len; + + if (newDistFact) + { + memcpy(newDistFact, dist1, sizeof(float) * dist1Len); + memcpy(newDistFactIndex, dist1Idx, sizeof(int) * numSubLists); + } + + newDistFactLength = dist1Len; + } + else + { + int nextid = 0; + int nextdf = 0; + + float *dist = NULL; + int numdf = 0; + + for (i=0; i 0) + { + memcpy(newIdList + nextid, ids, numids * sizeof(int)); + } + + nextid += numids; + + if (distFact) + { + dist = dist1 + dist1Idx[i]; + numdf = (lastList ? dist1Len : dist1Idx[i+1]) - dist1Idx[i]; + if (numdf > 0) + { + memcpy(newDistFact + nextdf, dist, numdf * sizeof(float)); + nextdf += numdf; + } + } + + // Make a set of the ids we've just written. We only want to add + // ids from list 2 if they did not exist in list 1. + + vtkstd::set idSet; + + for (id=0; id < numids; id++) + { + idSet.insert(ids[id]); + } + + ids = id2 + id2Idx[i]; + numids = (lastList ? id2Len : id2Idx[i+1]) - id2Idx[i]; + + if (distFact) + { + dist = dist2 + dist2Idx[i]; + numdf = (lastList ? dist2Len : dist2Idx[i+1]) - dist2Idx[i]; + } + else + { + numdf = 0; + } + + for (id=0; id < numids; id++) + { + vtkstd::pair::iterator, bool> inserted = + + idSet.insert(ids[id]); + + if (inserted.second) // here's a new ID + { + newIdList[nextid++] = ids[id]; + + if (numdf > 0) + { + // There is either 1 or 0 distribution factors + + newDistFact[nextdf++] = dist[id]; + } + } + } + + if (!lastList) + { + newIdListIndex[i+1] = nextid; + if (distFact) + { + newDistFactIndex[i+1] = nextdf; + } + } + else + { + newIdListLength = nextid; + newDistFactLength = nextdf; + } + } + } + + if (idNew) + { + *idNew = newIdList; + } + else + { + delete [] newIdList; + } + if (idNewIdx) + { + *idNewIdx = newIdListIndex; + } + else + { + delete [] newIdListIndex; + } + if (idNewLen) + { + *idNewLen = newIdListLength; + } + + if (distNew) + { + *distNew = newDistFact; + } + else if (newDistFact) + { + delete [] newDistFact; + } + if (distNewIdx) + { + *distNewIdx = newDistFactIndex; + } + else if (newDistFactIndex) + { + delete [] newDistFactIndex; + } + if (distNewLen) + { + *distNewLen = newDistFactLength; + } + + return 0; +} + +// This merge function serves two purposes. It can initialize +// the global fields of the current object with the values in the +// the global fields on the object passed in. +// +// Or it can carefully merge missing global fields in to our global +// fields. Often in Exodus files, global data is missing if it +// is irrelevant. For example, a block name is "NULL" if the +// the file has no cells in that block. +// +// "Global" in this context means merge all fields which don't depend +// on which cells are included in the model. (In other contexts we +// use "global" to refer to all metadata which doesn't depend on the +// cells, the time step, or the variables chosen.) +// +// TODO - We may need to write a version that detects duplicate +// cells in the two models that are to be merged. Maybe detecting +// and filtering duplicate cells should be an option. + +int vtkModelMetadata::MergeGlobalInformation(const vtkModelMetadata *em) +{ + int i; + + if (!this->Title && em->GetTitle()) + { + this->SetTitle(vtkModelMetadata::StrDupWithNew(em->GetTitle())); + } + + int num = em->GetNumberOfQARecords(); + + if (this->NumberOfQARecords < num) + { + typedef char *p4[4]; + + p4 *qaRecs = new p4 [num]; + char *name, *version, *date, *time; + + for (i=0; iGetQARecord(i, &name, &version, &date, &time); + qaRecs[i][0] = vtkModelMetadata::StrDupWithNew(name); + qaRecs[i][1] = vtkModelMetadata::StrDupWithNew(version); + qaRecs[i][2] = vtkModelMetadata::StrDupWithNew(date); + qaRecs[i][3] = vtkModelMetadata::StrDupWithNew(time); + } + + this->SetQARecords(num, qaRecs); + } + + num = em->GetNumberOfInformationLines(); + + if (this->NumberOfInformationLines < num) + { + char **newLines; + em->GetInformationLines(&newLines); + + char **lines = vtkModelMetadata::CopyLines(newLines, num); + this->SetInformationLines(num, lines); + } + + if (this->CoordinateNames == NULL) + { + num = em->GetDimension(); + char **lines = vtkModelMetadata::CopyLines(em->GetCoordinateNames(), num); + this->SetCoordinateNames(num, lines); + } + + num = em->GetNumberOfTimeSteps(); + + if (this->NumberOfTimeSteps < num) + { + float *ts = new float [num]; + memcpy(ts, em->GetTimeStepValues(), num * sizeof(float)); + + this->SetTimeSteps(num, ts); + this->TimeStepIndex = em->TimeStepIndex; + } + + // Assumption - Either we have no block information and are copying + // it from the supplied model, or the block IDs are the same and in the + // same order in both models, but we may be missing some information. + + num = em->GetNumberOfBlocks(); + int nblocks = this->GetNumberOfBlocks(); + + if (nblocks == 0) + { + this->SetNumberOfBlocks(num); + + this->SetBlockIds( + vtkModelMetadata::CopyInts(em->GetBlockIds(), num)); + + int *nvals = new int [num]; + memset(nvals , 0, sizeof(int) * num); + + this->SetBlockNumberOfElements(nvals); + + this->SetBlockElementType( + vtkModelMetadata::CopyLines(em->GetBlockElementType(), num)); + + this->SetBlockNodesPerElement( + vtkModelMetadata::CopyInts(em->GetBlockNodesPerElement(), num)); + + this->SetBlockNumberOfAttributesPerElement( + vtkModelMetadata::CopyInts(em->GetBlockNumberOfAttributesPerElement(), num)); + } + else if (nblocks != num) + { + vtkErrorMacro(<< "Merging metadata from different files"); + return 1; + } + else + { + char **types = em->GetBlockElementType(); + int *nodes = em->GetBlockNodesPerElement(); + int *atts = em->GetBlockNumberOfAttributesPerElement(); + + for (i=0; i < nblocks; i++) + { + if (!strcmp(this->BlockElementType[i], "NULL") && + strcmp(em->BlockElementType[i], "NULL")) + { + delete [] this->BlockElementType[i]; + this->BlockElementType[i] = vtkModelMetadata::StrDupWithNew(types[i]); + this->BlockNodesPerElement[i] = nodes[i]; + this->BlockNumberOfAttributesPerElement[i] = atts[i]; + } + } + } + + num = em->GetNumberOfNodeSets(); + + if (this->NumberOfNodeSets < num) + { + int *ids = vtkModelMetadata::CopyInts(em->GetNodeSetIds(), num); + + this->SetNumberOfNodeSets(num); + this->SetNodeSetIds(ids); + } + + num = em->GetNumberOfSideSets(); + + if (this->NumberOfSideSets < num) + { + int *ids = vtkModelMetadata::CopyInts(em->GetSideSetIds(), num); + + this->SetNumberOfSideSets(num); + this->SetSideSetIds(ids); + } + + num = em->GetNumberOfBlockProperties(); + int nblockProp = this->NumberOfBlockProperties; + int nvals = num * this->NumberOfBlocks; + + if (nvals > 0) + { + if (nblockProp < num) + { + this->SetBlockPropertyNames(num, + vtkModelMetadata::CopyLines(em->GetBlockPropertyNames(), num)); + + this->SetBlockPropertyValue( + vtkModelMetadata::CopyInts(em->GetBlockPropertyValue(), nvals)); + } + else if (nblockProp == num) + { + int *myVal = this->BlockPropertyValue; + int *newVal = em->GetBlockPropertyValue(); + + for (i=0; iGetNumberOfNodeSetProperties(); + int nnsetProp = this->NumberOfNodeSetProperties; + nvals = num * this->NumberOfNodeSets; + + if (nvals > 0) + { + if (nnsetProp < num) + { + this->SetNodeSetPropertyNames(num, + vtkModelMetadata::CopyLines(em->GetNodeSetPropertyNames(), num)); + + this->SetNodeSetPropertyValue( + vtkModelMetadata::CopyInts(em->GetNodeSetPropertyValue(), nvals)); + } + else if (nnsetProp == num) + { + int *myVal = this->NodeSetPropertyValue; + int *newVal = em->GetNodeSetPropertyValue(); + + for (i=0; iGetNumberOfSideSetProperties(); + int nssetProp = this->NumberOfSideSetProperties; + nvals = num * this->NumberOfSideSets; + + if (nvals > 0) + { + if (nssetProp < num) + { + this->SetSideSetPropertyNames(num, + vtkModelMetadata::CopyLines(em->GetSideSetPropertyNames(), num)); + + this->SetSideSetPropertyValue( + vtkModelMetadata::CopyInts(em->GetSideSetPropertyValue(), nvals)); + } + else if (nssetProp == num) + { + int *myVal = this->SideSetPropertyValue; + int *newVal = em->GetSideSetPropertyValue(); + + for (i=0; iGetNumberOfGlobalVariables(); + + if (num > this->NumberOfGlobalVariables) + { + this->SetGlobalVariableNames(num, + vtkModelMetadata::CopyLines(em->GetGlobalVariableNames(), num)); + + float *gv = new float [num]; + memcpy(gv, em->GetGlobalVariableValue(), sizeof(float) * num); + + this->SetGlobalVariableValue(gv); + } + + num = em->GetOriginalNumberOfElementVariables(); + + if (num > this->OriginalNumberOfElementVariables) + { + char **orig = + vtkModelMetadata::CopyLines(em->GetOriginalElementVariableNames(), num); + + int numvar = em->GetNumberOfElementVariables(); + char **varname = + vtkModelMetadata::CopyLines(em->GetElementVariableNames(), numvar); + + int *comp = + vtkModelMetadata::CopyInts(em->GetElementVariableNumberOfComponents(), + numvar); + int *map = + vtkModelMetadata::CopyInts(em->GetMapToOriginalElementVariableNames(), + numvar); + + this->SetElementVariableInfo(num, orig, numvar, varname, comp, map); + } + + num = em->GetOriginalNumberOfNodeVariables(); + + if (num > this->OriginalNumberOfNodeVariables) + { + char **orig = + vtkModelMetadata::CopyLines(em->GetOriginalNodeVariableNames(), num); + + int numvar = em->GetNumberOfNodeVariables(); + char **varname = + vtkModelMetadata::CopyLines(em->GetNodeVariableNames(), numvar); + + int *comp = + vtkModelMetadata::CopyInts(em->GetNodeVariableNumberOfComponents(), numvar); + int *map = + vtkModelMetadata::CopyInts(em->GetMapToOriginalNodeVariableNames(), numvar); + + this->SetNodeVariableInfo(num, orig, numvar, varname, comp, map); + } + + int *mytt = this->ElementVariableTruthTable; + int *newtt = em->GetElementVariableTruthTable(); + int nvars = em->GetOriginalNumberOfElementVariables(); + + if (newtt) + { + int ttsize = this->NumberOfBlocks * nvars; + + if (mytt == NULL) + { + mytt = new int [ttsize]; + memcpy(mytt, newtt, ttsize * sizeof(int)); + this->SetElementVariableTruthTable(mytt); + } + else + { + for (i=0; iMergeGlobalInformation(em); + + if (rc) + { + return 1; + } + + // If the input object is empty, we're done + + int nBlocksNew = em->GetNumberOfBlocks(); + int *nelts = em->GetBlockNumberOfElements(); + int nCellsNew = 0; + + for (i=0; nelts && (i < nBlocksNew); i++) + { + nCellsNew += nelts[i]; + } + + if (nCellsNew == 0) return 0; + + // BLOCKS + + float *farray = NULL; + int *index = NULL; + int newSize = 0; + int nblocks = this->NumberOfBlocks; + + this->AppendFloatLists(nblocks, + this->BlockAttributes, this->BlockAttributesIndex, this->SizeBlockAttributeArray, + em->BlockAttributes, em->BlockAttributesIndex, em->SizeBlockAttributeArray, + &farray, &index, &newSize); + + FREE(this->BlockAttributes); + FREE(this->BlockAttributesIndex); + + this->BlockAttributes = farray; + this->BlockAttributesIndex = index; + this->SizeBlockAttributeArray = newSize; + + int *iarray = NULL; + + this->AppendIntegerLists(nblocks, + this->BlockElementIdList, this->BlockElementIdListIndex, this->SumElementsPerBlock, + em->BlockElementIdList, em->BlockElementIdListIndex, em->SumElementsPerBlock, + &iarray, &index, &newSize); + + FREE(this->BlockElementIdList); + FREE(this->BlockElementIdListIndex); + + this->BlockElementIdList = iarray; + this->BlockElementIdListIndex = index; + this->SumElementsPerBlock = newSize; + + for (i=0; iBlockNumberOfElements[i] += em->BlockNumberOfElements[i]; + } + + // NODE SETS + + if (em->SumNodesPerNodeSet > 0) + { + int *index2 = NULL; + int newSize2 = 0; + int nnsets = this->NumberOfNodeSets; + + this->MergeIdLists( nnsets, + this->NodeSetNodeIdList, this->NodeSetNodeIdListIndex, this->SumNodesPerNodeSet, + this->NodeSetDistributionFactors, this->NodeSetDistributionFactorIndex, + this->SumDistFactPerNodeSet, + em->NodeSetNodeIdList, em->NodeSetNodeIdListIndex, em->SumNodesPerNodeSet, + em->NodeSetDistributionFactors, em->NodeSetDistributionFactorIndex, + em->SumDistFactPerNodeSet, + &iarray, &index, &newSize, + &farray, &index2, &newSize2); + + FREE(this->NodeSetNodeIdList); + FREE(this->NodeSetNodeIdListIndex); + FREE(this->NodeSetDistributionFactors); + FREE(this->NodeSetDistributionFactorIndex); + + this->NodeSetNodeIdList = iarray; + this->NodeSetNodeIdListIndex = index; + this->NodeSetDistributionFactors = farray; + this->NodeSetDistributionFactorIndex = index2; + + this->SumNodesPerNodeSet = newSize; + this->SumDistFactPerNodeSet = newSize2; + + int lastset = nnsets-1; + int *setSize = new int [nnsets]; + int *setDF = new int [nnsets]; + + for (i=0; iNodeSetNumberOfDistributionFactors); + this->NodeSetNumberOfDistributionFactors = setDF; + + FREE(this->NodeSetSize); + this->NodeSetSize = setSize; + } + + // SIDE SETS + + if (em->SumSidesPerSideSet > 0) + { + int nssets = this->NumberOfSideSets; + + this->AppendIntegerLists(nssets, + this->SideSetElementList, this->SideSetListIndex, this->SumSidesPerSideSet, + em->SideSetElementList, em->SideSetListIndex, em->SumSidesPerSideSet, + &iarray, &index, &newSize); + + FREE(this->SideSetElementList); + this->SideSetElementList = iarray; + + FREE(index); + + this->AppendIntegerLists(nssets, + this->SideSetSideList, this->SideSetListIndex, this->SumSidesPerSideSet, + em->SideSetSideList, em->SideSetListIndex, em->SumSidesPerSideSet, + &iarray, &index, &newSize); + + FREE(this->SideSetSideList); + this->SideSetSideList = iarray; + + FREE(index); + + this->AppendIntegerLists(nssets, + this->SideSetNumDFPerSide, this->SideSetListIndex, this->SumSidesPerSideSet, + em->SideSetNumDFPerSide, em->SideSetListIndex, em->SumSidesPerSideSet, + &iarray, &index, &newSize); + + FREE(this->SideSetNumDFPerSide); + this->SideSetNumDFPerSide= iarray; + + FREE(this->SideSetListIndex); + this->SideSetListIndex = index; + + this->SumSidesPerSideSet = newSize; + + this->AppendFloatLists(nssets, + this->SideSetDistributionFactors, this->SideSetDistributionFactorIndex, + this->SumDistFactPerSideSet, + em->SideSetDistributionFactors, em->SideSetDistributionFactorIndex, + em->SumDistFactPerSideSet, + &farray, &index, &newSize); + + FREE(this->SideSetDistributionFactors); + FREE(this->SideSetDistributionFactorIndex); + + this->SideSetDistributionFactors = farray; + this->SideSetDistributionFactorIndex = index; + this->SumDistFactPerSideSet = newSize; + + int lastset = nssets - 1; + int *setSize = new int [nssets]; + int *setDF = new int [nssets]; + + for (i=0; iSideSetListIndex[i+1] - this->SideSetListIndex[i]; + if (index) + { + setDF[i] = index[i+1] - index[i]; + } + else + { + setDF[i] = 0; + } + } + + setSize[lastset] = this->SumSidesPerSideSet - this->SideSetListIndex[lastset]; + + if (index) + { + setDF[lastset] = newSize - index[lastset]; + } + else + { + setDF[lastset] = 0; + } + + FREE(this->SideSetNumberOfDistributionFactors); + this->SideSetNumberOfDistributionFactors = setDF; + + FREE(this->SideSetSize); + this->SideSetSize = setSize; + } + + return 0; +} +int *vtkModelMetadata::CopyInts(int *vals, int num) +{ + int *newvals = NULL; + + if (num == 0) return newvals; + + newvals = new int [num]; + memcpy(newvals, vals, sizeof(int) * num); + + return newvals; +} +char **vtkModelMetadata::CopyLines(char **lines, int num) +{ + char **newlines = NULL; + + if (num == 0) return newlines; + + newlines = new char * [num]; + + for (int i=0; iNumberOfBlocks) < 1) return; + + if ((nelts = this->SumElementsPerBlock) < 1) return; + + char *extractElt = new char [nelts]; + + int *eltIds = this->BlockElementIdList; + float *eltAtts = this->BlockAttributes; + int *blockSize = this->BlockNumberOfElements; + int *blockAtts = this->BlockNumberOfAttributesPerElement; + + int *newEltIds = NULL; + float *newEltAtts = NULL; + int *newBlockSize = new int [nblocks]; + + int numNewElts = 0; + int numNewAtts = 0; + int ii=0; + + for (i=0; i::iterator it = idset->IntSet.find(eltIds[ii]); + + if (it == idset->IntSet.end()) + { + extractElt[ii] = 0; + } + else + { + extractElt[ii] = 1; + newBlockSize[i]++; + } + + ii++; + } + + numNewElts += newBlockSize[i]; + numNewAtts += (newBlockSize[i] * blockAtts[i]); + } + + if (numNewElts > 0) + { + newEltIds = new int [numNewElts]; + + if (numNewAtts > 0) + { + newEltAtts = new float [numNewAtts]; + } + + int *nextId = newEltIds; + float *nextAtt = newEltAtts; + + ii=0; + + for (i=0; iSetBlockNumberOfElements(newBlockSize); + + if (newEltIds) + { + mmd->SetBlockElementIdList(newEltIds); + + if (newEltAtts) + { + mmd->SetBlockAttributes(newEltAtts); + } + } + + delete [] extractElt; + + return; +} +void vtkModelMetadata::ExtractNodesFromNodeSetData(vtkModelMetadataSTLCloak *idset, + vtkModelMetadata *mmd) +{ + int i, j; + int nnsets, nnodes; + + if ((nnsets = this->NumberOfNodeSets) < 1) return; + + if ((nnodes = this->SumNodesPerNodeSet) < 1) return; + + char *extractNodes = new char [nnodes]; + + int *nsIds = this->NodeSetNodeIdList; + float *nsDF = this->NodeSetDistributionFactors; + int *nsSize = this->NodeSetSize; + int *nsNumDF = this->NodeSetNumberOfDistributionFactors; + + int *newnsIds = NULL; + float *newnsDF = NULL; + int *newnsSize = new int [nnsets]; + int *newnsNumDF = new int [nnsets]; + + int numNewNodes = 0; + int numNewDF = 0; + int ii=0; + + for (i=0; i::iterator it = idset->IntSet.find(nsIds[ii]); + + if (it == idset->IntSet.end()) + { + extractNodes[ii] = 0; + } + else + { + extractNodes[ii] = 1; + newnsSize[i]++; + } + + ii++; + } + + if (nsNumDF[i] > 0) newnsNumDF[i] = newnsSize[i]; + else newnsNumDF[i] = 0; + + numNewNodes += newnsSize[i]; + numNewDF += newnsNumDF[i]; + } + + if (numNewNodes > 0) + { + newnsIds = new int [numNewNodes]; + + if (numNewDF > 0) + { + newnsDF = new float [numNewDF]; + } + + int *nextId = newnsIds; + float *nextDF = newnsDF; + ii = 0; + + for (i=0; i 0); + + for (j=0; jSetNodeSetSize(newnsSize); + mmd->SetNodeSetNumberOfDistributionFactors(newnsNumDF); + + if (newnsIds) + { + mmd->SetNodeSetNodeIdList(newnsIds); + + if (newnsDF) + { + mmd->SetNodeSetDistributionFactors(newnsDF); + } + } + + delete [] extractNodes; + + return; +} +void vtkModelMetadata::ExtractSidesFromSideSetData(vtkModelMetadataSTLCloak *idset, + vtkModelMetadata *mmd) +{ + int i, j; + int nssets, nsides; + + if ((nssets = this->NumberOfSideSets) < 1) return; + + if ((nsides = this->SumSidesPerSideSet) < 1) return; + + char *extractSides = new char [nsides]; + + int *ssElts = this->SideSetElementList; + int *ssSides = this->SideSetSideList; + int *ssNumDFperSide = this->SideSetNumDFPerSide; + float *ssDF = this->SideSetDistributionFactors; + int *ssSize = this->SideSetSize; + + int *newssElts = NULL; + int *newssSides = NULL; + int *newssNumDFperSide = NULL; + float *newssDF = NULL; + int *newssSize = new int [nssets]; + int *newssNumDF = new int [nssets]; + + int numNewSides = 0; + int numNewDF = 0; + int ii=0; + + for (i=0; i::iterator it = idset->IntSet.find(ssElts[ii]); + + if (it == idset->IntSet.end()) + { + extractSides[ii] = 0; + } + else + { + extractSides[ii] = 1; + newssSize[i]++; + newssNumDF[i] += ssNumDFperSide[ii]; + } + + ii++; + } + + numNewSides += newssSize[i]; + numNewDF += newssNumDF[i]; + } + + if (numNewSides > 0) + { + newssElts = new int [numNewSides]; + newssSides = new int [numNewSides]; + newssNumDFperSide = new int [numNewSides]; + + if (numNewDF > 0) + { + newssDF = new float [numNewDF]; + } + + int nextId = 0; + int nextDF = 0; + + for (ii=0; iiSetSideSetSize(newssSize); + mmd->SetSideSetNumberOfDistributionFactors(newssNumDF); + + if (newssElts) + { + mmd->SetSideSetElementList(newssElts); + mmd->SetSideSetSideList(newssSides); + mmd->SetSideSetNumDFPerSide(newssNumDFperSide); + + if (newssDF) + { + mmd->SetSideSetDistributionFactors(newssDF); + } + } + + return; +} + +vtkModelMetadata *vtkModelMetadata::ExtractGlobalMetadata() +{ + vtkModelMetadata *mmd = vtkModelMetadata::New(); + + mmd->MergeGlobalInformation(this); + + return mmd; +} + +vtkModelMetadata *vtkModelMetadata::ExtractModelMetadata( + vtkIntArray *globalCellIdList, + vtkDataSet *grid, + const char *globalCellIdArrayName, + const char *globalNodeIdArrayName) +{ + int i; + + vtkModelMetadata *em = this->ExtractGlobalMetadata(); + + int ncells = globalCellIdList->GetNumberOfTuples(); + + if (ncells < 1) + { + return em; + } + + vtkModelMetadataSTLCloak *cellIds = + new vtkModelMetadataSTLCloak; // the cells we want to extract + vtkModelMetadataSTLCloak *nodeIds = + new vtkModelMetadataSTLCloak; // the nodes they include + + int *ids = globalCellIdList->GetPointer(0); + + for (i=0; iIntSet.insert(ids[i]); + } + + ncells = cellIds->IntSet.size(); + + vtkDataArray *ca = grid->GetCellData()->GetArray(globalCellIdArrayName); + vtkDataArray *pa = grid->GetPointData()->GetArray(globalNodeIdArrayName); + + if (!ca || !pa) + { + vtkErrorMacro(<< "vtkModelMetadata::ExtractModelMetadata needs id arrays"); + em->Delete(); + return NULL; + } + + vtkIntArray *ica = vtkIntArray::SafeDownCast(ca); + vtkIntArray *ipa = vtkIntArray::SafeDownCast(pa); + + if (!ica || !ipa) + { + vtkErrorMacro(<< "vtkModelMetadata::ExtractModelMetadata id arrays not ints"); + em->Delete(); + return NULL; + } + + int *gcids = ica->GetPointer(0); // global cell ids + int *gpids = ipa->GetPointer(0); // global point ids + + int gridCells = grid->GetNumberOfCells(); + vtkIdList *ptIds = vtkIdList::New(); + + for (vtkIdType c = 0; c::iterator it = cellIds->IntSet.find(gcids[c]); + + if (it != cellIds->IntSet.end()) + { + grid->GetCellPoints(c, ptIds); + + vtkIdType npoints = ptIds->GetNumberOfIds(); + + for (i=0; iIntSet.insert(gpids[ptIds->GetId(i)]); + } + } + } + + ptIds->Delete(); + + // Block information + + if (this->NumberOfBlocks) + { + this->ExtractCellsFromBlockData(cellIds, em); + } + + // Node set information + + if (this->NumberOfNodeSets) + { + this->ExtractNodesFromNodeSetData(nodeIds, em); + } + + // Side set information + + if (this->NumberOfSideSets) + { + this->ExtractSidesFromSideSetData(cellIds, em); + } + + delete cellIds; + delete nodeIds; + + return em; +} +char *vtkModelMetadata::StrDupWithNew(const char *s) +{ + char *newstr = NULL; + + if (s) + { + int len = strlen(s); + if (len == 0) + { + newstr = new char [1]; + newstr[0] = '\0'; + } + else + { + newstr = new char [len + 1]; + strcpy(newstr, s); + } + } + + return newstr; +} + +char *vtkModelMetadata::FindOriginalNodeVariableName(const char *name, int component) +{ + int idx = -1; + + for (int i=0; iNumberOfNodeVariables; i++) + { + if (!strcmp(name, this->NodeVariableNames[i])) + { + idx = i; + break; + } + } + + if (idx < 0) + { + return NULL; + } + + int origIdx = this->MapToOriginalNodeVariableNames[idx]; + + if ( (component<0) || + (component >= this->NodeVariableNumberOfComponents[idx])) + { + return NULL; + } + + return this->OriginalNodeVariableNames[origIdx + component]; +} +int vtkModelMetadata::ElementVariableIsDefinedInBlock(char *varname, int blockId) +{ + int i; + int varIdx = -1; + + if (this->AllVariablesDefinedInAllBlocks) + { + return 1; + } + + for (i=0; iOriginalNumberOfElementVariables; i++) + { + if (!strcmp(varname, this->OriginalElementVariableNames[i])) + { + varIdx = i; + break; + } + } + + int blockIdx = this->GetBlockLocalIndex(blockId); + + if ( (blockIdx<0) || (varIdx<0)) + { + return 1; // by default we say everything is defined + } + + int loc = (blockIdx * this->OriginalNumberOfElementVariables) + varIdx; + + return (int)this->ElementVariableTruthTable[loc]; +} + +char *vtkModelMetadata::FindOriginalElementVariableName(const char *name, int component) +{ + int idx = -1; + + for (int i=0; iNumberOfElementVariables; i++) + { + if (!strcmp(name, this->ElementVariableNames[i])) + { + idx = i; + break; + } + } + + if (idx < 0) + { + return NULL; + } + + int origIdx = this->MapToOriginalElementVariableNames[idx]; + + if ( (component<0) || + (component >= this->ElementVariableNumberOfComponents[idx])) + { + return NULL; + } + + return this->OriginalElementVariableNames[origIdx + component]; +} +//------------------------------------- +// Display contents for debugging +//------------------------------------- + +void vtkModelMetadata::ShowFloats(const char *what, int num, float *f) +{ + if (num < 1) return; + if (!f) return; + cout << what << endl; + for (int i=0; iTimeStepIndex << endl; + + this->ShowInts("BlockNumberOfElements", this->NumberOfBlocks, + this->BlockNumberOfElements); + + if (verbose) + { + // Only show these for really small data sets. + + this->ShowListsOfInts("BlockElementIdList", this->BlockElementIdList, + this->NumberOfBlocks, this->BlockElementIdListIndex, + this->SumElementsPerBlock, (verbose>1)); + this->ShowListsOfFloats("BlockAttributes", this->BlockAttributes, + this->NumberOfBlocks, this->BlockAttributesIndex, + this->SizeBlockAttributeArray, (verbose>1)); + } + + this->ShowInts("NodeSetSize", this->NumberOfNodeSets, this->NodeSetSize); + this->ShowInts("NodeSetNumberOfDistributionFactors", this->NumberOfNodeSets, + this->NodeSetNumberOfDistributionFactors); + + if (verbose) + { + this->ShowListsOfInts("NodeSetNodeIdList", this->NodeSetNodeIdList, + this->NumberOfNodeSets, this->NodeSetNodeIdListIndex, + this->SumNodesPerNodeSet, (verbose>1)); + this->ShowListsOfFloats("NodeSetDistributionFactors", + this->NodeSetDistributionFactors, + this->NumberOfNodeSets, + this->NodeSetDistributionFactorIndex, + this->SumDistFactPerNodeSet, (verbose>1)); + } + + this->ShowInts("SideSetSize", this->NumberOfSideSets, this->SideSetSize); + this->ShowInts("SideSetNumberOfDistributionFactors", this->NumberOfSideSets, + this->SideSetNumberOfDistributionFactors); + + if (verbose) + { + this->ShowListsOfInts("SideSetElementList", this->SideSetElementList, + this->NumberOfSideSets, this->SideSetListIndex, + this->SumSidesPerSideSet, (verbose>1)); + this->ShowListsOfInts("SideSetSideList", this->SideSetSideList, + this->NumberOfSideSets, this->SideSetListIndex, + this->SumSidesPerSideSet, (verbose>1)); + this->ShowListsOfInts("SideSetNumDFPerSide", this->SideSetNumDFPerSide, + this->NumberOfSideSets, this->SideSetListIndex, + this->SumSidesPerSideSet, (verbose>1)); + this->ShowListsOfFloats("SideSetDistributionFactors", + this->SideSetDistributionFactors, + this->NumberOfSideSets, + this->SideSetDistributionFactorIndex, + this->SumDistFactPerSideSet, (verbose>1)); + } + + this->ShowFloats("GlobalVariables", this->NumberOfGlobalVariables, this->GlobalVariableValue); + + cout << "NumberOfElementVariables " << this->NumberOfElementVariables << endl; + this->ShowLines("ElementVariableNames", this->NumberOfElementVariables, this->ElementVariableNames); + this->ShowInts("ElementVariableNumberOfComponents", this->NumberOfElementVariables, this->ElementVariableNumberOfComponents); + this->ShowInts("MapToOriginalElementVariableNames", this->NumberOfElementVariables, this->MapToOriginalElementVariableNames); + + cout << "NumberOfNodeVariables " << this->NumberOfNodeVariables << endl; + this->ShowLines("NodeVariableNames", this->NumberOfNodeVariables, this->NodeVariableNames); + this->ShowInts("NodeVariableNumberOfComponents", this->NumberOfNodeVariables, this->NodeVariableNumberOfComponents); + this->ShowInts("MapToOriginalNodeVariableNames", this->NumberOfNodeVariables, this->MapToOriginalNodeVariableNames); +} + +void vtkModelMetadata::PrintGlobalInformation() +{ + int i,j; + + cout << "Metadata global information" << endl; + cout << "========================================" << endl; + + if (this->Title) cout << "Title: " << this->Title << endl; + + if (this->NumberOfQARecords) + { + cout << "QA Records:" << endl; + + char *name, *ver, *date, *time; + + for (i=0; iNumberOfQARecords; i++) + { + this->GetQARecord(i, &name, &ver, &date, &time); + cout << " " << name << " " << ver << " " << date << " " << time << endl; + } + } + + this->ShowLines("InformationLines", + this->NumberOfInformationLines, this->InformationLine); + + this->ShowLines("CoordinateNames", this->Dimension, this->CoordinateNames); + + cout << "NumberOfTimeSteps " << this->NumberOfTimeSteps << endl; + this->ShowFloats("TimeStepValues", this->NumberOfTimeSteps, this->TimeStepValues); + + cout << "NumberOfBlocks " << this->NumberOfBlocks << endl; + this->ShowInts("BlockIds", this->NumberOfBlocks, this->BlockIds); + this->ShowLines("BlockElementType", this->NumberOfBlocks, this->BlockElementType); + this->ShowInts("BlockNodesPerElement", this->NumberOfBlocks, this->BlockNodesPerElement); + this->ShowInts("BlockNumberOfAttributesPerElement", this->NumberOfBlocks, this->BlockNumberOfAttributesPerElement); + + cout << "NumberOfNodeSets " << this->NumberOfNodeSets << endl; + this->ShowInts("NodeSetIds", this->NumberOfNodeSets, this->NodeSetIds); + + cout << "NumberOfSideSets " << this->NumberOfSideSets << endl; + this->ShowInts("SideSetIds", this->NumberOfSideSets, this->SideSetIds); + + cout << "NumberOfBlockProperties " << this->NumberOfBlockProperties << endl; + this->ShowLines("BlockPropertyNames", this->NumberOfBlockProperties, this->BlockPropertyNames); + this->ShowIntArray("BlockPropertyValue", this->NumberOfBlocks, this->NumberOfBlockProperties, this->BlockPropertyValue); + + cout << "NumberOfNodeSetProperties " << this->NumberOfNodeSetProperties << endl; + this->ShowLines("NodeSetPropertyNames", this->NumberOfNodeSetProperties, this->NodeSetPropertyNames); + this->ShowIntArray("NodeSetPropertyValue", this->NumberOfNodeSets, this->NumberOfNodeSetProperties, this->NodeSetPropertyValue); + + cout << "NumberOfSideSetProperties " << this->NumberOfSideSetProperties << endl; + this->ShowLines("SideSetPropertyNames", this->NumberOfSideSetProperties, this->SideSetPropertyNames); + this->ShowIntArray("SideSetPropertyValue", this->NumberOfSideSets, this->NumberOfSideSetProperties, this->SideSetPropertyValue); + + cout << "NumberOfGlobalVariables " << this->NumberOfGlobalVariables << endl; + this->ShowLines("GlobalVariableNames", this->NumberOfGlobalVariables, this->GlobalVariableNames); + + cout << "OriginalNumberOfElementVariables " << this->OriginalNumberOfElementVariables << endl; + this->ShowLines("OriginalElementVariableNames", this->OriginalNumberOfElementVariables, this->OriginalElementVariableNames); + + cout << "OriginalNumberOfNodeVariables " << this->OriginalNumberOfNodeVariables << endl; + this->ShowLines("OriginalNodeVariableNames", this->OriginalNumberOfNodeVariables, this->OriginalNodeVariableNames); + + int *tt = this->ElementVariableTruthTable; + int nblocks = this->NumberOfBlocks; + int nelts = this->OriginalNumberOfElementVariables; + int ttsize = nblocks * nelts; + + if (tt && ttsize) + { + cout << "Block/Element variable truth table" << endl; + for (i=0; iTitle ? strlen(this->Title) : 0); + maxLine = ((sizeLine > maxLine) ? sizeLine : maxLine); + + for (i=0; iNumberOfInformationLines; i++) + { + sizeLine = (this->InformationLine[i] ? + strlen(this->InformationLine[i]) : 0); + maxLine = ((sizeLine > maxLine) ? sizeLine : maxLine); + } + + for (i=0; iNumberOfQARecords; i++) + { + sizeLine = (this->QARecord[i][0] ? + strlen(this->QARecord[i][0]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + + sizeLine = (this->QARecord[i][1] ? + strlen(this->QARecord[i][1]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + + sizeLine = (this->QARecord[i][2] ? + strlen(this->QARecord[i][2]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + + sizeLine = (this->QARecord[i][3] ? + strlen(this->QARecord[i][3]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + } + + for (i=0; iDimension; i++) + { + sizeLine = (this->CoordinateNames[i] ? + strlen(this->CoordinateNames[i]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + } + + for (i=0; iNumberOfBlocks; i++) + { + sizeLine = (this->BlockElementType[i] ? + strlen(this->BlockElementType[i]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + } + + for (i=0; iNumberOfBlockProperties; i++) + { + sizeLine = (this->BlockPropertyNames[i] ? + strlen(this->BlockPropertyNames[i]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + } + + for (i=0; iNumberOfNodeSetProperties; i++) + { + sizeLine = (this->NodeSetPropertyNames[i] ? + strlen(this->NodeSetPropertyNames[i]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + } + + for (i=0; iNumberOfSideSetProperties; i++) + { + sizeLine = (this->SideSetPropertyNames[i] ? + strlen(this->SideSetPropertyNames[i]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + } + + for (i=0; iNumberOfGlobalVariables; i++) + { + sizeLine = (this->GlobalVariableNames[i] ? + strlen(this->GlobalVariableNames[i]) : 0); + maxString = (sizeLine > maxString) ? sizeLine : maxString; + } + + return 0; +} + +void vtkModelMetadata::PrintSelf(ostream& os, vtkIndent indent) +{ + int i; + this->Superclass::PrintSelf(os,indent); + + os << indent << "Title: " << (this->Title?this->Title:"(none)") << endl; + os << indent << "NumberOfQARecords: " << + this->NumberOfQARecords << endl; + os << indent << "NumberOfInformationLines: " << + this->NumberOfInformationLines << endl; + os << indent << "Dimension: " << + this->Dimension << endl; + os << indent << "CoordinateNames: " << endl; + for(i=0;iDimension;i++) + { + os << indent << "-" << (this->CoordinateNames[i]?this->CoordinateNames[i]:"(none)") << endl; + } + os << indent << "NumberOfBlocks: " << + this->NumberOfBlocks << endl; + os << indent << "NumberOfNodeSets: " << + this->NumberOfNodeSets << endl; + os << indent << "NodeSetIds: "; + for(i=0;iNumberOfNodeSets;i++) + { + os << this->NodeSetIds[i] << " "; + } + os << endl; + if (this->NodeSetSize) + { + os << indent << "NodeSetSize: "; + for(i=0;iNumberOfNodeSets;i++) + { + os << this->NodeSetSize[i] << " "; + } + os << endl; + } + os << indent << "NodeSetNodeIdList: "; + for(i=0;iSumNodesPerNodeSet;i++) + { + os << this->NodeSetNodeIdList[i] << " "; + } + os << endl; +// os << indent << "NodeSetNumberOfDistributionFactors: " << +// (this->NodeSetNumberOfDistributionFactors?this->NodeSetNumberOfDistributionFactors:"(none)") << endl; + os << indent << "NodeSetDistributionFactors: "; + for(i=0;iSumDistFactPerNodeSet;i++) + { + os << this->NodeSetDistributionFactors[i] << " "; + } + os << endl; + os << indent << "NumberOfSideSets: " << + this->NumberOfSideSets << endl; + os << indent << "SideSetIds: "; + for(i=0;iNumberOfSideSets;i++) + { + os << this->SideSetIds[i] << " "; + } + os << endl; + if (this->SideSetSize) + { + os << indent << "SideSetSize: "; + for(i=0;iNumberOfSideSets;i++) + { + os << this->SideSetSize[i] << " "; + } + os << endl; + } +// os << indent << "SideSetNumberOfDistributionFactors: " << +// (this->SideSetNumberOfDistributionFactors?this->SideSetNumberOfDistributionFactors:"(none)" << endl; + os << indent << "SideSetElementList: "; + for(i=0;iSumSidesPerSideSet;i++) + { + os << this->SideSetElementList[i] << " "; + } + os << endl; + os << indent << "SideSetSideList: "; + for(i=0;iSumSidesPerSideSet;i++) + { + os << this->SideSetSideList[i] << " "; + } + os << endl; + os << indent << "SideSetNumDFPerSide: "; + for(i=0;iSumSidesPerSideSet;i++) + { + os << this->SideSetNumDFPerSide[i] << " "; + } + os << endl; + os << indent << "SideSetDistributionFactors: "; + for(i=0;iSumDistFactPerSideSet;i++) + { + os << this->SideSetDistributionFactors[i] << " "; + } + os << endl; + os << indent << "NumberOfBlockProperties: " << + this->NumberOfBlockProperties << endl; + os << indent << "BlockPropertyNames: "; + for(i=0;iNumberOfBlockProperties;i++) + { + os << indent << "-" << (this->BlockPropertyNames[i]?this->BlockPropertyNames[i]:"(none)") << endl; + } +// os << indent << "BlockPropertyValue: " << +// (this->BlockPropertyValue?this->BlockPropertyValue:"(none)") << endl; + os << indent << "NumberOfNodeSetProperties: " << + this->NumberOfNodeSetProperties << endl; + os << indent << "NodeSetPropertyNames: "; + for(i=0;iNumberOfNodeSetProperties;i++) + { + os << indent << "-" << (this->NodeSetPropertyNames[i]?this->NodeSetPropertyNames[i]:"(none)") << endl; + } +// os << indent << "NodeSetPropertyValue: " << +// (this->NodeSetPropertyValue?this->NodeSetPropertyValue:"(none)") << endl; + os << indent << "NumberOfSideSetProperties: " << + this->NumberOfSideSetProperties << endl; + os << indent << "SideSetPropertyNames: "; + for(i=0;iNumberOfSideSetProperties;i++) + { + os << indent << "-" << (this->SideSetPropertyNames[i]?this->SideSetPropertyNames[i]:"(none)") << endl; + } +// os << indent << "SideSetPropertyValue: " << +// (this->SideSetPropertyValue?this->SideSetPropertyValue:"(none)") << endl; + os << indent << "NumberOfElementVariables: " << + this->NumberOfElementVariables << endl; + os << indent << "ElementVariableNames: "; + for(i=0;iMaxNumberOfElementVariables;i++) + { + os << indent << "-" << (this->ElementVariableNames[i]?this->ElementVariableNames[i]:"(none)") << endl; + } + os << indent << "NumberOfNodeVariables: " << + this->NumberOfNodeVariables << endl; + os << indent << "NodeVariableNames: "; + for(i=0;iNumberOfNodeVariables;i++) + { + os << indent << "-" << (this->NodeVariableNames[i]?this->NodeVariableNames[i]:"(none)") << endl; + } +// os << indent << "ElementVariableTruthTable: " << +// (this->ElementVariableTruthTable?this->ElementVariableTruthTable:"(none)") << endl; + os << indent << "TimeStepIndex: " << + this->TimeStepIndex << endl; + os << indent << "AllVariablesDefinedInAllBlocks: " << + this->AllVariablesDefinedInAllBlocks << endl; +} diff --git a/Graphics/vtkModelMetadata.h b/Graphics/vtkModelMetadata.h new file mode 100644 index 0000000..c6707c9 --- /dev/null +++ b/Graphics/vtkModelMetadata.h @@ -0,0 +1,905 @@ +/*========================================================================= + + Program: ParaView + Module: $RCSfile: vtkModelMetadata.h,v $ + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkModelMetadata - This class encapsulates the metadata +// that appear in mesh-based file formats but do not appear in +// vtkUnstructuredGrid. It can pack itself into the field +// arrays of a vtkUnstructuredGrid, and be unpacked by metadata +// aware filters and writers later on. +// +// .SECTION Description +// This class is inspired by the Exodus II file format, but +// because this class does not depend on the Exodus library, it +// should be possible to use it to represent metadata for other +// dataset file formats. Sandia Labs uses it in their Exodus II +// reader, their Exodus II writer and their EnSight writer. +// vtkDistributedDataFilter looks for metadata attached to +// it's input and redistributes the metadata with the grid. +// +// The fields in this class are those described in the document +// "EXODUS II: A Finite Element Data Model", SAND92-2137, November 1995. +// +// Element and node IDs stored in this object must be global IDs, +// in the event that the original dataset was partitioned across +// many files. +// +// One way to initialize this object is by using vtkExodusModel +// (a Sandia class used by the Sandia Exodus reader). +// That class will take an open Exodus II file and a +// vtkUnstructuredGrid drawn from it and will set the required fields. +// +// Alternatively, you can use all the Set* +// methods to set the individual fields. This class does not +// copy the data, it simply uses your pointer. This +// class will free the storage associated with your pointer +// when the class is deleted. Most fields have sensible defaults. +// The only requirement is that if you are using this ModelMetadata +// to write out an Exodus or EnSight file in parallel, you must +// SetBlockIds and SetBlockIdArrayName. Your vtkUnstructuredGrid must +// have a cell array giving the block ID for each cell. +// +// .SECTION Caveats +// The Exodus II library supports an optimized element order map +// (section 3.7 in the SAND document). It contains all the element +// IDs, listed in the order in which a solver should process them. +// We don't include this, and won't unless there is a request. +// +// There is an assumption in some classes that the name of the cell +// array containing global element ids is "GlobalElementId" and the +// name of the point array containing global node ids is "GlobalNodeId". +// (element == cell) and (node == point). +// +// .SECTION See also +// vtkDistributedDataFilter vtkExtractCells + +#ifndef __vtkModelMetadata_h +#define __vtkModelMetadata_h + +#include "vtkObject.h" + +#define myVtkGetMacro(name, type) virtual type Get##name() const { return this->name; } + +#define myVtkGetStringMacro(name) virtual char* Get##name () const { return this->name; } + +class vtkDataSet; +class vtkCharArray; +class vtkIntArray; +class vtkFloatArray; +class vtkIntArray; +class vtkModelMetadataSTLCloak; + +class VTK_GRAPHICS_EXPORT vtkModelMetadata : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkModelMetadata, vtkObject); + virtual void PrintSelf(ostream &os, vtkIndent indent); + static vtkModelMetadata *New(); + + // Description: + // The global fields are those which pertain to the whole + // file. Examples are the title, information lines, + // and list of block IDs. This method prints out all the + // global information. + + virtual void PrintGlobalInformation(); + + // Description: + // The local fields are those which depend on exactly which + // blocks, which time step, and which variables you read in + // from the file. Examples are the number of cells in + // each block, and the list of nodes in a node set, or the + // value of the global variables at a time step. If + // VERBOSE_TESTING is defined in your execution environment, + // this method will print more than mere counts, and actually + // print a few of the IDs, distribution factors and so on. If + // VERY_VERBOSE_TESTING is defined, it will print out + // all ID lists, distribution factor lists, and so on. + + virtual void PrintLocalInformation(); + + // Description: + // The title of the dataset. + vtkSetStringMacro(Title); + myVtkGetStringMacro(Title); + + // Description: + // Set the information lines. + void SetInformationLines(int numLines, char **lines); + + // Description: + // Add an information line. + void AddInformationLine(char *info); + + // Description: + // Get a pointer to all the information lines. The number + // of lines is returned; + int GetInformationLines(char ***lines) const; + + // Description: + // Get the number of information lines. + myVtkGetMacro(NumberOfInformationLines, int); + + // Description: + // Set the list of QA records. If there was already a + // a list, it will be replaced with this one. We use your + // pointer and delete the records when done. + void SetQARecords(int numberOfRecords, char *QARecords[][4]); + + // Description: + // Add a QA record. They fields are: + // The code name + // The code version number + // The date (MM/DD/YY or NULL for today) + // The time (HH:MM:SS or NULL for right now) + void AddQARecord(char *name, char *version, char *date, char *time); + + // Description: + // Get a pointer to the 4 fields of a QA record + void GetQARecord(int which, + char **name, char **version, char **date, char **time) const; + + // Description: + // Get the number of QA records + myVtkGetMacro(NumberOfQARecords, int); + + // Description: + // Set the index of the time step represented by the results + // data in the file attached to this ModelMetadata object. Time + // step indices start at 0 in this file, they start at 1 in + // an Exodus file. + vtkSetMacro(TimeStepIndex, int); + myVtkGetMacro(TimeStepIndex, int); + + // Description: + // Set the total number of time steps in the file, + // and the value at each time step. We use your time + // step value array and delete it when we're done. + void SetTimeSteps(int numberOfTimeSteps, float *timeStepValues); + myVtkGetMacro(NumberOfTimeSteps, int); + + // Description: + // Get the time step values + float *GetTimeStepValues() const {return this->TimeStepValues;} + + // Description: + // The name of the one, two or three coordinate dimensions. + void SetCoordinateNames(int dimension, char **); + char **GetCoordinateNames() const {return this->CoordinateNames;} + + // Description: + // Get the dimension of the model. This is also the number + // of coordinate names. + myVtkGetMacro(Dimension, int); + + // Description: + // The number of blocks in the file. Set this before setting + // any of the block arrays. + vtkSetMacro(NumberOfBlocks, int); + myVtkGetMacro(NumberOfBlocks, int); + + // Description: + // An arbitrary integer ID for each block. + // We use your pointer, and free the memory when the object is freed. + void SetBlockIds(int *); + int *GetBlockIds() const {return this->BlockIds;} + + // Description: + // Element type for each block - a name that means + // something to person who created the file. + // We use your pointers, and free the memory when the object is freed. + void SetBlockElementType(char **); + char **GetBlockElementType() const {return this->BlockElementType;} + + // Description: + // Set or get a pointer to a list of the number of elements in + // each block. + // We use your pointers, and free the memory when the object is freed. + int SetBlockNumberOfElements(int *nelts); + int *GetBlockNumberOfElements()const{return this->BlockNumberOfElements;} + + // Description: + // Set or get a pointer to a list of the number of nodes in the + // elements of each block. + // We use your pointers, and free the memory when the object is freed. + void SetBlockNodesPerElement(int *); + int *GetBlockNodesPerElement()const{return this->BlockNodesPerElement;} + + // Description: + // Set or get a pointer to a list global element IDs for the + // elements in each block. + // We use your pointers, and free the memory when the object is freed. + void SetBlockElementIdList(int *); + int *GetBlockElementIdList() const {return this->BlockElementIdList;} + + // Description: + // Get the length of the list of elements in every block. + myVtkGetMacro(SumElementsPerBlock, int); + + // Description: + // Get a list of the index into the BlockElementIdList of the + // start of each block's elements. + int *GetBlockElementIdListIndex()const {return this->BlockElementIdListIndex;} + + // Description: + // Set or get a pointer to a list of the number of attributes + // stored for the elements in each block. + // We use your pointers, and free the memory when the object is freed. + int SetBlockNumberOfAttributesPerElement(int *natts); + int *GetBlockNumberOfAttributesPerElement()const {return this->BlockNumberOfAttributesPerElement;} + + // Description: + // Set or get a pointer to a list of the attributes for all + // blocks. The order of the list should be by block, by element + // within the block, by attribute. Omit blocks that don't + // have element attributes. + void SetBlockAttributes(float *); + float *GetBlockAttributes()const {return this->BlockAttributes;} + + // Description: + // Get the length of the list of floating point block attributes. + myVtkGetMacro(SizeBlockAttributeArray, int); + + // Description: + // Get a list of the index into the BlockAttributes of the + // start of each block's element attribute list. + int *GetBlockAttributesIndex()const {return this->BlockAttributesIndex;}; + + // Description: + // The number of node sets in the file. Set this value before + // setting the various node set arrays. + vtkSetMacro(NumberOfNodeSets, int); + myVtkGetMacro(NumberOfNodeSets, int); + + // Description: + // Set or get the list the IDs for each node set. + // Length of list is the number of node sets. + // We use your pointer, and free the memory when the object is freed. + void SetNodeSetIds(int *); + int *GetNodeSetIds()const {return this->NodeSetIds;} + + // Description: + // Set or get a pointer to a list of the number of nodes in each node set. + // We use your pointer, and free the memory when the object is freed. + int SetNodeSetSize(int *); + int *GetNodeSetSize()const {return this->NodeSetSize;} + + // Description: + // Set or get a pointer to a concatenated list of the + // IDs of all nodes in each node set. First list all IDs in + // node set 0, then all IDs in node set 1, and so on. + // We use your pointer, and free the memory when the object is freed. + void SetNodeSetNodeIdList(int *); + int *GetNodeSetNodeIdList()const {return this->NodeSetNodeIdList;} + + // Description: + // Set or get a list of the number of distribution factors stored + // by each node set. This is either 0 or equal to the number of + // nodes in the node set. + // Length of list is number of node sets. + // We use your pointer, and free the memory when the object is freed. + int SetNodeSetNumberOfDistributionFactors(int *); + int *GetNodeSetNumberOfDistributionFactors()const {return this->NodeSetNumberOfDistributionFactors;} + + // Description: + // Set or get a list of the distribution factors for the node sets. + // The list is organized by node set, and within node set by node. + // We use your pointer, and free the memory when the object is freed. + void SetNodeSetDistributionFactors(float *); + float *GetNodeSetDistributionFactors()const {return this->NodeSetDistributionFactors;} + + // Description: + // Get the total number of nodes in all node sets + myVtkGetMacro(SumNodesPerNodeSet, int); + + // Description: + // Get the total number of distribution factors stored for all node sets + myVtkGetMacro(SumDistFactPerNodeSet, int); + + // Description: + // Get a list of the index of the starting entry for each node set + // in the list of node set node IDs. + int *GetNodeSetNodeIdListIndex() const {return this->NodeSetNodeIdListIndex;} + + // Description: + // Get a list of the index of the starting entry for each node set + // in the list of node set distribution factors. + int *GetNodeSetDistributionFactorIndex() const {return this->NodeSetDistributionFactorIndex;} + + // Description: + // Set or get the number of side sets. Set this value before + // setting any of the other side set arrays. + vtkSetMacro(NumberOfSideSets, int); + myVtkGetMacro(NumberOfSideSets, int); + + // Description: + // Set or get a pointer to a list giving the ID of each side set. + // We use your pointer, and free the memory when the object is freed. + void SetSideSetIds(int *); + int *GetSideSetIds()const {return this->SideSetIds;} + + // Description: + // Set or get a pointer to a list of the number of sides in each side set. + // We use your pointer, and free the memory when the object is freed. + int SetSideSetSize(int *sizes); + int *GetSideSetSize()const {return this->SideSetSize;} + + // Description: + // Set or get a pointer to a list of the number of distribution + // factors stored by each side set. Each side set has either + // no distribution factors, or 1 per node in the side set. + // We use your pointer, and free the memory when the object is freed. + int SetSideSetNumberOfDistributionFactors(int *df); + int *GetSideSetNumberOfDistributionFactors()const {return this->SideSetNumberOfDistributionFactors;} + + // Description: + // Set or get a pointer to a list of the elements containing each + // side in each side set. The list is organized by side set, and + // within side set by element. + // We use your pointer, and free the memory when the object is freed. + void SetSideSetElementList(int *); + int *GetSideSetElementList()const {return this->SideSetElementList;} + + // Description: + // Set or get a pointer to the element side for each side in the side set. + // (See the manual for the convention for numbering sides in different + // types of cells.) Side Ids are arranged by side set and within + // side set by side, and correspond to the SideSetElementList. + // We use your pointer, and free the memory when the object is freed. + void SetSideSetSideList( int *); + int *GetSideSetSideList()const {return this->SideSetSideList;} + + // Description: + // Set or get a pointer to a list of the number of nodes in each + // side of each side set. This list is organized by side set, and + // within side set by side. + // We use your pointer, and free the memory when the object is freed. + void SetSideSetNumDFPerSide(int *numNodes); + int *GetSideSetNumDFPerSide()const {return this->SideSetNumDFPerSide;} + + // Description: + // Set or get a pointer to a list of all the distribution factors. + // For every side set that has distribution factors, the number of + // factors per node was given in the SideSetNumberOfDistributionFactors + // array. If this number for a given side set is N, then for that + // side set we have N floating point values for each node for each + // side in the side set. If nodes are repeated in more than one + // side, we repeat the distribution factors. So this list is in order + // by side set, by node. + // We use your pointer, and free the memory when the object is freed. + void SetSideSetDistributionFactors(float *); + float *GetSideSetDistributionFactors()const {return this->SideSetDistributionFactors;} + + // Description: + // Get the total number of sides in all side sets + myVtkGetMacro(SumSidesPerSideSet, int); + + // Description: + // Get the total number of distribution factors stored for all side sets + myVtkGetMacro(SumDistFactPerSideSet, int); + + // Description: + // Get a list of the index of the starting entry for each side set + // in the list of side set side IDs. + int *GetSideSetListIndex()const {return this->SideSetListIndex;} + + // Description: + // Get a list of the index of the starting entry for each side set + // in the list of side set distribution factors. + int *GetSideSetDistributionFactorIndex()const {return this->SideSetDistributionFactorIndex;} + + // Description: + // The number of block properties (global variables) + myVtkGetMacro(NumberOfBlockProperties, int); + + // Description: + // Set or get the names of the block properties. + void SetBlockPropertyNames(int numProp, char **names); + char **GetBlockPropertyNames()const {return this->BlockPropertyNames;} + + // Description: + // Set or get value for each variable for each block. List + // the integer values in order by variable and within variable + // by block. + void SetBlockPropertyValue(int *); + int *GetBlockPropertyValue()const {return this->BlockPropertyValue;} + + // Description: + // The number of node set properties (global variables) + myVtkGetMacro(NumberOfNodeSetProperties, int); + + // Description: + // Set or get the names of the node setproperties. + void SetNodeSetPropertyNames(int numProp, char **names); + char **GetNodeSetPropertyNames()const {return this->NodeSetPropertyNames;} + + // Description: + // Set or get value for each variable for each node set. List + // the integer values in order by variable and within variable + // by node set. + void SetNodeSetPropertyValue(int *); + int *GetNodeSetPropertyValue()const {return this->NodeSetPropertyValue;} + + // Description: + // The number of side set properties (global variables) + myVtkGetMacro(NumberOfSideSetProperties, int); + + // Description: + // Set or get the names of the side set properties. + void SetSideSetPropertyNames(int numProp, char **names); + char **GetSideSetPropertyNames()const {return this->SideSetPropertyNames;} + + // Description: + // Set or get value for each variable for each side set. List + // the integer values in order by variable and within variable + // by side set. + void SetSideSetPropertyValue(int *); + int *GetSideSetPropertyValue()const {return this->SideSetPropertyValue;} + + // Description: + // Get the number of global variables per time step + myVtkGetMacro(NumberOfGlobalVariables, int); + + // Description: + // Set or get the names of the global variables + void SetGlobalVariableNames(int numVarNames, char **n); + char **GetGlobalVariableNames()const {return this->GlobalVariableNames;} + + // Description: + // Set or get the values of the global variables at the current + // time step. + void SetGlobalVariableValue(float *f); + float *GetGlobalVariableValue()const {return this->GlobalVariableValue;} + + // Description: + // The ModelMetadata maintains a list of the element variables that + // were in the original file, and a list of the cell variables + // in the UGrid derived from that file. Some of the scalar variables + // in the original file were combined into vectors in the UGrid. + // In this method, provide the number of original element variables, + // the names of the original element variables, the number of + // element variables in the UGrid, the number of components for each + // of those variables, and a map from each UGrid variable to the + // the variable in the list of original names that represents it's + // first component. + void SetElementVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map); + + // Description: + // The ModelMetadata maintains a list of the node variables that + // were in the original file, and a list of the node variables + // in the UGrid derived from that file. Some of the scalar variables + // in the original file were combined into vectors in the UGrid. + // In this method, provide the number of original node variables, + // the names of the original node variables, the number of + // node variables in the UGrid, the number of components for each + // of those variables, and a map from each UGrid variable to the + // the variable in the list of original names that represents it's + // first component. + void SetNodeVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map); + + // Description: + // A truth table indicating which element variables are + // defined for which blocks. The variables are all the original + // element variables that were in the file. + // The table is by block ID and within block ID by variable. + void SetElementVariableTruthTable(int *); + int *GetElementVariableTruthTable()const {return this->ElementVariableTruthTable;} + + // Description: + // Instead of a truth table of all "1"s, you can set this + // instance variable to indicate that all variables are + // defined in all blocks. + vtkSetMacro(AllVariablesDefinedInAllBlocks, int); + myVtkGetMacro(AllVariablesDefinedInAllBlocks, int); + vtkBooleanMacro(AllVariablesDefinedInAllBlocks, int); + + // Description: + // If the element variable named is defined for the block Id + // provided (in the element variable truth table) return a + // 1, otherwise return a 0. If the variable name or block Id + // are unrecognized, the default value of 1 is returned. + // (This is an "original" variable name, from the file, + // not a name created for the vtkUnstructuredGrid. Use + // FindOriginal*VariableName to map between the two.) + int ElementVariableIsDefinedInBlock(char *varname, int blockId); + + // Description: + // The ModelMetadata object may contain these lists: + // o the variables in the original data file + // o the variables created in the u grid from those original variables + // o a mapping from the grid variable names to the original names + // o a list of the number of components each grid variable has + // + // (Example: Variables in Exodus II files are all scalars. Some are + // combined by the ExodusReader into vector variables in the grid.) + // + // These methods return names of the original variables, the names + // of the grid variables, a list of the number of components in + // each grid variable, and a list of the index into the list of + // original variable names where the original name of the first + // component of a grid variable may be found. The names of subsequent + // components would immediately follow the name of the the first + // component. + myVtkGetMacro(OriginalNumberOfElementVariables, int); + char **GetOriginalElementVariableNames()const {return this->OriginalElementVariableNames;} + myVtkGetMacro(NumberOfElementVariables, int); + char **GetElementVariableNames()const {return this->ElementVariableNames;} + int *GetElementVariableNumberOfComponents()const {return this->ElementVariableNumberOfComponents;} + int *GetMapToOriginalElementVariableNames()const {return this->MapToOriginalElementVariableNames;} + + myVtkGetMacro(OriginalNumberOfNodeVariables, int); + char **GetOriginalNodeVariableNames()const {return this->OriginalNodeVariableNames;} + myVtkGetMacro(NumberOfNodeVariables, int); + char **GetNodeVariableNames()const {return this->NodeVariableNames;} + int *GetNodeVariableNumberOfComponents()const {return this->NodeVariableNumberOfComponents;} + int *GetMapToOriginalNodeVariableNames()const {return this->MapToOriginalNodeVariableNames;} + + // Description: + // Given the name of an element variable the vtkUnstructuredGrid + // described by this ModelMetadata, and a component number, give + // the name of the scalar array in the original + // file that turned into that component when the file was + // read into VTK. + char *FindOriginalElementVariableName(const char *name, int component); + + // Description: + // Given the name of an node variable the vtkUnstructuredGrid + // described by this ModelMetadata, and a component number, give + // the name of the scalar array in the original + // file that turned into that component when the file was + // read into VTK. + char *FindOriginalNodeVariableName(const char *name, int component); + + // Description: + // Static function that returns 1 if the vtkUnstructuredGrid + // has metadata packed into it's field arrays, and 0 otherwise. + static int HasMetadata(vtkDataSet *grid); + + // Description: + // Static function that removes the packed metadata arrays + // from a dataset. + static void RemoveMetadata(vtkDataSet *grid); + + // Description: + // Pack this object's metadata into a field array of a dataset. + void Pack(vtkDataSet *ugrid); + + // Description: + // Unpack the metadata stored in a dataset, + // and initialize this object with it. Return 1 if there's + // no metadata packed into the grid, 0 if OK. + // If deleteIt is ON, then delete the grid's packed data after + // unpacking it into the object. + int Unpack(vtkDataSet *ugrid, int deleteIt); + + // Description: + // In order to write Exodus files from vtkUnstructuredGrid + // objects that were read from Exodus files, we need to know + // the mapping from variable names in the UGrid to variable + // names in the Exodus file. (The Exodus reader combines + // scalar variables with similar names into vectors in the + // UGrid.) When building the UGrid to which this + // ModelMetadata refers, add each element and node variable + // name with this call, including the name of original variable + // that yielded it's first component, and the number of components. + // If a variable is removed from the UGrid, remove it from + // the ModelMetadata. (If this information is missing or + // incomplete, the ExodusIIWriter can still do something + // sensible in creating names for variables.) + int AddUGridElementVariable(char *ugridVarName, char *origName, int numComponents); + int RemoveUGridElementVariable(char *ugridVarName); + + int AddUGridNodeVariable(char *ugridVarName, char *origName, int numComponents); + int RemoveUGridNodeVariable(char *ugridVarName); + + // Description: + // In VTK we take vtkUnstructuredGrids and perform + // operations on them, including subsetting and merging + // grids. We need to modify the metadata object + // when this happens. MergeModelMetadata merges the supplied + // model (both global and local metadata) into this model. + // The models must be from the same file set. + // + // MergeModelMetadata assumes that no element in one metadata + // object appears in the other. (It doesn't test for duplicate + // elements when merging the two metadata objects.) + int MergeModelMetadata(const vtkModelMetadata *em); + + // Description: + // The metadata is divided into global metadata and local + // metadata. MergeGlobalInformation merges just the + // global metadata of the supplied object into the + // global metadata of this object. + int MergeGlobalInformation(const vtkModelMetadata *em); + + // Description: + // Create and return a new metadata object which contains + // the information for the subset of global cell IDs provided. + // We need the grid containing the cells so we can find point + // Ids as well, and also the name of the global cell ID array + // and the name of the global point ID array. + vtkModelMetadata *ExtractModelMetadata(vtkIntArray *globalCellIdList, + vtkDataSet *grid, + const char *globalCellIdArrayName, + const char *globalNodeIdArrayName); + + // Description: + // Create and return a new metadata object containing only the + // global metadata of this metadata object. + vtkModelMetadata *ExtractGlobalMetadata(); + + // Description: + // Free selected portions of the metadata when updating values + // in the vtkModelMetadata object. Resetting a particular field, + // (i.e. SetNodeSetIds) frees the previous setting, but if you + // are not setting every field, you may want to do a wholesale + // "Free" first. + // + // FreeAllGlobalData frees all the fields which don't depend on + // which time step, which blocks, or which variables are in the input. + // FreeAllLocalData frees all the fields which do depend on which + // time step, blocks or variables are in the input. + // FreeBlockDependentData frees all metadata fields which depend on + // which blocks were read in. + void FreeAllGlobalData(); + void FreeAllLocalData(); + void FreeBlockDependentData(); + void FreeOriginalElementVariableNames(); + void FreeOriginalNodeVariableNames(); + void FreeUsedElementVariableNames(); + void FreeUsedNodeVariableNames(); + void FreeUsedElementVariables(); + void FreeUsedNodeVariables(); + + // Description: + // Set the object back to it's initial state + void Reset(); + + // Description: + // Block information is stored in arrays. This method returns + // the array index for a given block ID. + int GetBlockLocalIndex(int id); + +protected: + vtkModelMetadata(); + ~vtkModelMetadata(); + +private: + void InitializeAllMetadata(); + void InitializeAllIvars(); + + void FreeAllMetadata(); + void FreeAllIvars(); + + void FreeQARecords(); + + int BuildBlockElementIdListIndex(); + int BuildBlockAttributesIndex(); + int BuildNodeSetNodeIdListIndex(); + int BuildNodeSetDistributionFactorIndex(); + int BuildSideSetListIndex(); + int BuildSideSetDistributionFactorIndex(); + + int InitializeFromSizeArray(vtkIntArray *ia, int &maxStr, int &maxLine); + vtkIntArray *PackSizeArray(int maxStr, int maxLine); + int InitializeFromIntArray(vtkModelMetadata *sizes, vtkIntArray *ia); + vtkIntArray *PackIntArray(); + int InitializeFromCharArray(vtkModelMetadata *sizes, + vtkCharArray *uca, int maxStr, int maxLine); + vtkCharArray *PackCharArray(int maxStr, int maxLine); + int InitializeFromFloatArray(vtkFloatArray *fa); + vtkFloatArray *PackFloatArray(); + + static char *StrDupWithNew(const char *s); + + static char *WriteLines(char *p, int maxLines, int maxLen, char **lines); + static char *ReadLines(char ***to, int maxLines, + int maxLen, char *from); + static char **CopyLines(char **lines, int num); + static int *CopyInts(int *vals, int num); + + static int FindNameOnList(char *name, char **list, int listLen); + + int MergeIdLists(int numSubLists, + int *id1, int *id1Idx, int id1Len, + float *dist1, int *dist1Idx, int dist1Len, + int *id2, int *id2Idx, int id2Len, + float *dist2, int *dist2Idx, int dist2Len, + int **idNew, int **idNewIdx, int *idNewLen, + float **distNew, int **distNewIdx, int *distNewLen); + + int AppendFloatLists(int numSubLists, + float *id1, int *id1Idx, int id1Len, + float *id2, int *id2Idx, int id2Len, + float **idNew, int **idNewIdx, int *idNewLen); + + int AppendIntegerLists(int numSubLists, + int *id1, int *id1Idx, int id1Len, + int *id2, int *id2Idx, int id2Len, + int **idNew, int **idNewIdx, int *idNewLen); + + void ExtractCellsFromBlockData(vtkModelMetadataSTLCloak *idset, + vtkModelMetadata *mmd); + void ExtractNodesFromNodeSetData(vtkModelMetadataSTLCloak *idset, + vtkModelMetadata *mmd); + void ExtractSidesFromSideSetData(vtkModelMetadataSTLCloak *idset, + vtkModelMetadata *mmd); + + void ShowFloats(const char *what, int num, float *f); + void ShowLines(const char *what, int num, char **l); + void ShowIntArray(const char *what, int numx, int numy, int *id); + void ShowInts(const char *what, int num, int *id); + void ShowListsOfInts(const char *what, int *list, + int nlists, int *idx, int len, int verbose); + void ShowListsOfFloats(const char *what, float *list, + int nlists, int *idx, int len, int verbose); + + void SetOriginalElementVariableNames(int nvars, char **names); + void SetElementVariableNames(int nvars, char **names); + void SetElementVariableNumberOfComponents(int *comp); + void SetMapToOriginalElementVariableNames(int *map); + + void SetOriginalNodeVariableNames(int nvars, char **names); + void SetNodeVariableNames(int nvars, char **names); + void SetNodeVariableNumberOfComponents(int *comp); + void SetMapToOriginalNodeVariableNames(int *map); + + int CalculateMaximumLengths(int &maxString, int &maxLine); + + // Fields in Exodus II file and their size (defined in exodusII.h) + // (G - global fields, relevant to entire file or file set) + // (L - local fields, they differ depending on which cells and nodes are + // in a file of a partitioned set, or are read in from file) + + char *Title; // (G) + + int NumberOfQARecords; // (G) +//BTX + char *(*QARecord)[4]; // NumberOfQARecords * 4 (G) +//ETX + + int NumberOfInformationLines; // (G) + char **InformationLine; // (G) + + int Dimension; // (G) + char **CoordinateNames; // (at most 3 of these) (G) + + // Time steps + + int TimeStepIndex; // starting at 0 (Exodus file starts at 1) + int NumberOfTimeSteps; // (G) + float *TimeStepValues; // (G) + + // Block information - arrays that are input with Set* + + int NumberOfBlocks; // (G) + + int *BlockIds; // NumberOfBlocks (G) (start at 1) + char **BlockElementType; // NumberOfBlocks (G) + int *BlockNumberOfElements; // NumberOfBlocks (L) + int *BlockNodesPerElement; // NumberOfBlocks (G) + int *BlockNumberOfAttributesPerElement;// NumberOfBlocks (G) + int *BlockElementIdList; // SumElementsPerBlock (L) + float *BlockAttributes; // SizeBlockAttributeArray (L) + + // Block information - values that we calculate + + int SumElementsPerBlock; + int SizeBlockAttributeArray; + + int *BlockElementIdListIndex; // NumberOfBlocks + int *BlockAttributesIndex; // NumberOfBlocks + + vtkModelMetadataSTLCloak *BlockIdIndex; // computed map + + // Node Sets - arrays that are input to the class with Set* + + int NumberOfNodeSets; // (G) + + int *NodeSetIds; // NumberOfNodeSets (G) + int *NodeSetSize; // NumberOfNodeSets (L) + int *NodeSetNumberOfDistributionFactors; // NNS (L) (NSNDF[i] is 0 or NSS[i]) + int *NodeSetNodeIdList; // SumNodesPerNodeSet (L) + float *NodeSetDistributionFactors; // SumDistFactPerNodeSet (L) + + // Node Sets - values or arrays that the class computes + + int SumNodesPerNodeSet; + int SumDistFactPerNodeSet; + + int *NodeSetNodeIdListIndex; // NumberOfNodeSets + int *NodeSetDistributionFactorIndex; // NumberOfNodeSets + + // Side Sets - input to class with Set* + + int NumberOfSideSets; // (G) + + int *SideSetIds; // NumberOfSideSets (G) + int *SideSetSize; // NumberOfSideSets (L) + int *SideSetNumberOfDistributionFactors; // NSS (L) (SSNDF[i] = 0 or NumNodesInSide) + int *SideSetElementList; // SumSidesPerSideSet (L) + int *SideSetSideList; // SumSidesPerSideSet (L) + int *SideSetNumDFPerSide; // SumSidesPerSideSet (L) + float *SideSetDistributionFactors; // SumDistFactPerSideSet (L) + + // Side Sets - calculated by class + + int SumSidesPerSideSet; + int SumDistFactPerSideSet; + + int *SideSetListIndex; // NumberOfSideSets + int *SideSetDistributionFactorIndex; // NumberOfSideSets + + // Other properties, provided as input with Set* + + int NumberOfBlockProperties; // (G) + char **BlockPropertyNames; // one per property (G) + int *BlockPropertyValue; // NumBlocks * NumBlockProperties (G) + + int NumberOfNodeSetProperties; // (G) + char **NodeSetPropertyNames; // one per property (G) + int *NodeSetPropertyValue; // NumNodeSets * NumNodeSetProperties (G) + + int NumberOfSideSetProperties; // (G) + char **SideSetPropertyNames; // one per property (G) + int *SideSetPropertyValue; // NumSideSets * NumSideSetProperties (G) + + // Global variables, 1 value per time step per variable. We store + // these as floats, even if they are doubles in the file. The values + // are global in the sense that they apply to the whole data set, but + // the are local in the sense that they can change with each time step. + // For the purpose of this object, which represents a particular + // time step, they are therefore considered "local". (Since they need + // to be updated everytime another read is done from the file.) + + int NumberOfGlobalVariables; // (G) + char **GlobalVariableNames; // (G) NumberOfGlobalVariables + float *GlobalVariableValue; // (G) NumberOfGlobalVariables + + // The element and node arrays in the file were all scalar arrays. + // Those with similar names were combined into vectors in VTK. Here + // are all the original names from the Exodus file, the names given + // the variables in the VTK ugrid, and a mapping from the VTK names + // to the Exodus names. + + int OriginalNumberOfElementVariables; // (G) + char **OriginalElementVariableNames; // (G) OriginalNumberOfElementVariables + int NumberOfElementVariables; // (G) + int MaxNumberOfElementVariables; // (G) + char **ElementVariableNames; // (G) MaxNumberOfElementVariables + int *ElementVariableNumberOfComponents; // (G) MaxNumberOfElementVariables + int *MapToOriginalElementVariableNames; // (G) MaxNumberOfElementVariables + + int OriginalNumberOfNodeVariables; // (G) + char **OriginalNodeVariableNames; // (G) OriginalNumberOfNodeVariables + int NumberOfNodeVariables; // (G) + int MaxNumberOfNodeVariables; // (G) + char **NodeVariableNames; // (G) NumberOfNodeVariables + int *NodeVariableNumberOfComponents; // (G) NumberOfNodeVariables + int *MapToOriginalNodeVariableNames; // (G) NumberOfNodeVariables + + int *ElementVariableTruthTable; // (G) NumBlocks*OrigNumberOfElementVariables + int AllVariablesDefinedInAllBlocks; + +private: + vtkModelMetadata(const vtkModelMetadata&); // Not implemented + void operator=(const vtkModelMetadata&); // Not implemented +}; +#endif diff --git a/Graphics/vtkOBBDicer.cxx b/Graphics/vtkOBBDicer.cxx new file mode 100644 index 0000000..c710edf --- /dev/null +++ b/Graphics/vtkOBBDicer.cxx @@ -0,0 +1,239 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBBDicer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOBBDicer.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkOBBTree.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkShortArray.h" + +vtkCxxRevisionMacro(vtkOBBDicer, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkOBBDicer); + +void vtkOBBDicer::BuildTree(vtkIdList *ptIds, vtkOBBNode *OBBptr, + vtkDataSet *input) +{ + vtkIdType i, numPts=ptIds->GetNumberOfIds(); + vtkIdType ptId; + vtkOBBTree *OBB = vtkOBBTree::New(); + + double size[3]; + + // Gather all the points into a single list + // + for ( this->PointsList->Reset(), i=0; i < numPts; i++ ) + { + ptId = ptIds->GetId(i); + this->PointsList->InsertNextPoint(input->GetPoint(ptId)); + } + + // Now compute the OBB + // + OBB->ComputeOBB(this->PointsList, OBBptr->Corner, OBBptr->Axes[0], + OBBptr->Axes[1], OBBptr->Axes[2], size); + OBB->Delete(); + + // Check whether to continue recursing; if so, create two children and + // assign cells to appropriate child. + // + if ( numPts > this->NumberOfPointsPerPiece ) + { + vtkOBBNode *LHnode= new vtkOBBNode; + vtkOBBNode *RHnode= new vtkOBBNode; + OBBptr->Kids = new vtkOBBNode *[2]; + OBBptr->Kids[0] = LHnode; + OBBptr->Kids[1] = RHnode; + vtkIdList *LHlist = vtkIdList::New(); + LHlist->Allocate(numPts/2); + vtkIdList *RHlist = vtkIdList::New(); + RHlist->Allocate(numPts/2); + LHnode->Parent = OBBptr; + RHnode->Parent = OBBptr; + double n[3], p[3], x[3], val; + + //split the longest axis down the middle + for (i=0; i < 3; i++) //compute split point + { + p[i] = OBBptr->Corner[i] + OBBptr->Axes[0][i]/2.0 + + OBBptr->Axes[1][i]/2.0 + OBBptr->Axes[2][i]/2.0; + } + + // compute split normal + for (i=0 ; i < 3; i++) + { + n[i] = OBBptr->Axes[0][i]; + } + vtkMath::Normalize(n); + + //traverse cells, assigning to appropriate child list as necessary + for ( i=0; i < numPts; i++ ) + { + ptId = ptIds->GetId(i); + input->GetPoint(ptId, x); + val = n[0]*(x[0]-p[0]) + n[1]*(x[1]-p[1]) + n[2]*(x[2]-p[2]); + + if ( val < 0.0 ) + { + LHlist->InsertNextId(ptId); + } + else + { + RHlist->InsertNextId(ptId); + } + + }//for all points + + ptIds->Delete(); //don't need to keep anymore + this->BuildTree(LHlist, LHnode, input); + this->BuildTree(RHlist, RHnode, input); + }//if should build tree + + else //terminate recursion + { + ptIds->Squeeze(); + OBBptr->Cells = ptIds; + } +} + +// Current implementation uses an OBBTree to split up the dataset. +int vtkOBBDicer::RequestData( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkIdType ptId, numPts; + vtkIdList *ptIds; + vtkShortArray *groupIds; + vtkOBBNode *root; + vtkDataSet *input= vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output= vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Dicing object"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( (numPts = input->GetNumberOfPoints()) < 1 ) + { + vtkErrorMacro(<<"No data to dice!"); + return 1; + } + + // The superclass computes piece size limits based on filter ivars + this->UpdatePieceMeasures(input); + + // Create list of points + // + this->PointsList = vtkPoints::New(); + this->PointsList->Allocate(numPts); + ptIds = vtkIdList::New(); + ptIds->SetNumberOfIds(numPts); + for ( ptId=0; ptId < numPts; ptId++ ) + { + ptIds->SetId(ptId,ptId); + } + + root = new vtkOBBNode; + this->BuildTree(ptIds,root, input); + + // Generate scalar values + // + this->PointsList->Delete(); + this->PointsList = NULL; + groupIds = vtkShortArray::New(); + groupIds->SetNumberOfTuples(numPts); + groupIds->SetName("vtkOBBDicer_GroupIds"); + this->NumberOfActualPieces = 0; + this->MarkPoints(root,groupIds); + this->DeleteTree(root); + delete root; + + vtkDebugMacro(<<"Created " << this->NumberOfActualPieces << " pieces"); + + // Update self + // + if ( this->FieldData ) + { + output->GetPointData()->AddArray(groupIds); + output->GetPointData()->CopyFieldOff("vtkOBBDicer_GroupIds"); + output->GetPointData()->PassData(input->GetPointData()); + } + else + { + output->GetPointData()->AddArray(groupIds); + output->GetPointData()->SetActiveScalars(groupIds->GetName()); + output->GetPointData()->CopyScalarsOff(); + output->GetPointData()->PassData(input->GetPointData()); + } + + output->GetCellData()->PassData(input->GetCellData()); + + groupIds->Delete(); + + return 1; +} + +void vtkOBBDicer::MarkPoints(vtkOBBNode *OBBptr, vtkShortArray *groupIds) +{ + if ( OBBptr->Kids == NULL ) //leaf OBB + { + vtkIdList *ptIds; + vtkIdType i, ptId, numIds; + + ptIds = OBBptr->Cells; + if ( (numIds=ptIds->GetNumberOfIds()) > 0 ) + { + for ( i=0; i < numIds; i++ ) + { + ptId = ptIds->GetId(i); + groupIds->SetValue(ptId,this->NumberOfActualPieces); + } + this->NumberOfActualPieces++; + }//if any points in this leaf OBB + } + else + { + this->MarkPoints(OBBptr->Kids[0],groupIds); + this->MarkPoints(OBBptr->Kids[1],groupIds); + } +} + +void vtkOBBDicer::DeleteTree(vtkOBBNode *OBBptr) +{ + if ( OBBptr->Kids != NULL ) + { + this->DeleteTree(OBBptr->Kids[0]); + this->DeleteTree(OBBptr->Kids[1]); + delete OBBptr->Kids[0]; + delete OBBptr->Kids[1]; + } +} + +void vtkOBBDicer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkOBBDicer.h b/Graphics/vtkOBBDicer.h new file mode 100644 index 0000000..6118bae --- /dev/null +++ b/Graphics/vtkOBBDicer.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBBDicer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOBBDicer - divide dataset into spatially aggregated pieces +// .SECTION Description +// vtkOBBDicer separates the cells of a dataset into spatially +// aggregated pieces using a Oriented Bounding Box (OBB). These pieces +// can then be operated on by other filters (e.g., vtkThreshold). One +// application is to break very large polygonal models into pieces and +// performing viewing and occlusion culling on the pieces. +// +// Refer to the superclass documentation (vtkDicer) for more information. + +// .SECTION See Also +// vtkDicer vtkConnectedDicer + +#ifndef __vtkOBBDicer_h +#define __vtkOBBDicer_h + +#include "vtkDicer.h" + +class vtkOBBNode; +class vtkShortArray; +class vtkIdList; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkOBBDicer : public vtkDicer +{ +public: + vtkTypeRevisionMacro(vtkOBBDicer,vtkDicer); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate an object. + static vtkOBBDicer *New(); + +protected: + vtkOBBDicer() {}; + ~vtkOBBDicer() {}; + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + //implementation ivars and methods + void BuildTree(vtkIdList *ptIds, vtkOBBNode *OBBptr, vtkDataSet *input); + void MarkPoints(vtkOBBNode *OBBptr, vtkShortArray *groupIds); + void DeleteTree(vtkOBBNode *OBBptr); + vtkPoints *PointsList; + +private: + vtkOBBDicer(const vtkOBBDicer&); // Not implemented. + void operator=(const vtkOBBDicer&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkOBBTree.cxx b/Graphics/vtkOBBTree.cxx new file mode 100644 index 0000000..c773d31 --- /dev/null +++ b/Graphics/vtkOBBTree.cxx @@ -0,0 +1,1933 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBBTree.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOBBTree.h" + +#include "vtkCellArray.h" +#include "vtkGenericCell.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkTriangle.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkOBBTree, "$Revision: 1.63.14.1 $"); +vtkStandardNewMacro(vtkOBBTree); + +#define vtkCELLTRIANGLES(CELLPTIDS, TYPE, IDX, PTID0, PTID1, PTID2) \ + { switch( TYPE ) \ + { \ + case VTK_TRIANGLE: \ + case VTK_POLYGON: \ + case VTK_QUAD: \ + PTID0 = CELLPTIDS[0]; \ + PTID1 = CELLPTIDS[(IDX)+1]; \ + PTID2 = CELLPTIDS[(IDX)+2]; \ + break; \ + case VTK_TRIANGLE_STRIP: \ + PTID0 = CELLPTIDS[IDX]; \ + PTID1 = CELLPTIDS[(IDX)+1+((IDX)&1)]; \ + PTID2 = CELLPTIDS[(IDX)+2-((IDX)&1)]; \ + break; \ + default: \ + PTID0 = PTID1 = PTID2 = -1; \ + } } + +vtkOBBNode::vtkOBBNode() +{ + this->Cells = NULL; + this->Parent = NULL; + this->Kids = NULL; +} + +vtkOBBNode::~vtkOBBNode() +{ + if (this->Kids) + { + delete [] this->Kids; + } + if (this->Cells) + { + this->Cells->Delete(); + } +} + +// Construct with automatic computation of divisions, averaging +// 25 cells per octant. +vtkOBBTree::vtkOBBTree() +{ + this->DataSet = NULL; + this->Level = 4; + this->MaxLevel = 12; + this->Automatic = 1; + this->Tolerance = 0.01; + this->Tree = NULL; + this->PointsList = NULL; + this->InsertedPoints = NULL; + this->OBBCount = this->DeepestLevel = 0; +} + +vtkOBBTree::~vtkOBBTree() +{ + this->FreeSearchStructure(); +} + +void vtkOBBTree::FreeSearchStructure() +{ + if ( this->Tree ) + { + this->DeleteTree(this->Tree); + delete this->Tree; + this->Tree = NULL; + } +} + +void vtkOBBTree::DeleteTree(vtkOBBNode *OBBptr) +{ + if ( OBBptr->Kids != NULL ) + { + this->DeleteTree(OBBptr->Kids[0]); + this->DeleteTree(OBBptr->Kids[1]); + delete OBBptr->Kids[0]; + delete OBBptr->Kids[1]; + } +} + +// Compute an OBB from the list of points given. Return the corner point +// and the three axes defining the orientation of the OBB. Also return +// a sorted list of relative "sizes" of axes for comparison purposes. +void vtkOBBTree::ComputeOBB(vtkPoints *pts, double corner[3], double max[3], + double mid[3], double min[3], double size[3]) +{ + int i; + vtkIdType numPts, pointId; + double x[3], mean[3], xp[3], *v[3], v0[3], v1[3], v2[3]; + double *a[3], a0[3], a1[3], a2[3]; + double tMin[3], tMax[3], closest[3], t; + + // + // Compute mean + // + numPts = pts->GetNumberOfPoints(); + mean[0] = mean[1] = mean[2] = 0.0; + for (pointId=0; pointId < numPts; pointId++ ) + { + pts->GetPoint(pointId, x); + for (i=0; i < 3; i++) + { + mean[i] += x[i]; + } + } + for (i=0; i < 3; i++) + { + mean[i] /= numPts; + } + + // + // Compute covariance matrix + // + a[0] = a0; a[1] = a1; a[2] = a2; + for (i=0; i < 3; i++) + { + a0[i] = a1[i] = a2[i] = 0.0; + } + + for (pointId=0; pointId < numPts; pointId++ ) + { + pts->GetPoint(pointId, x); + xp[0] = x[0] - mean[0]; xp[1] = x[1] - mean[1]; xp[2] = x[2] - mean[2]; + for (i=0; i < 3; i++) + { + a0[i] += xp[0] * xp[i]; + a1[i] += xp[1] * xp[i]; + a2[i] += xp[2] * xp[i]; + } + }//for all points + + for (i=0; i < 3; i++) + { + a0[i] /= numPts; + a1[i] /= numPts; + a2[i] /= numPts; + } + + // + // Extract axes (i.e., eigenvectors) from covariance matrix. + // + v[0] = v0; v[1] = v1; v[2] = v2; + vtkMath::Jacobi(a,size,v); + max[0] = v[0][0]; max[1] = v[1][0]; max[2] = v[2][0]; + mid[0] = v[0][1]; mid[1] = v[1][1]; mid[2] = v[2][1]; + min[0] = v[0][2]; min[1] = v[1][2]; min[2] = v[2][2]; + + for (i=0; i < 3; i++) + { + a[0][i] = mean[i] + max[i]; + a[1][i] = mean[i] + mid[i]; + a[2][i] = mean[i] + min[i]; + } + + // + // Create oriented bounding box by projecting points onto eigenvectors. + // + tMin[0] = tMin[1] = tMin[2] = VTK_DOUBLE_MAX; + tMax[0] = tMax[1] = tMax[2] = -VTK_DOUBLE_MAX; + + for (pointId=0; pointId < numPts; pointId++ ) + { + pts->GetPoint(pointId, x); + for (i=0; i < 3; i++) + { + vtkLine::DistanceToLine(x, mean, a[i], t, closest); + if ( t < tMin[i] ) + { + tMin[i] = t; + } + if ( t > tMax[i] ) + { + tMax[i] = t; + } + } + }//for all points + + for (i=0; i < 3; i++) + { + corner[i] = mean[i] + tMin[0]*max[i] + tMin[1]*mid[i] + tMin[2]*min[i]; + + max[i] = (tMax[0] - tMin[0]) * max[i]; + mid[i] = (tMax[1] - tMin[1]) * mid[i]; + min[i] = (tMax[2] - tMin[2]) * min[i]; + } +} + +// a method to compute the OBB of a dataset without having to go through the +// Execute method; It does set +void vtkOBBTree::ComputeOBB(vtkDataSet *input, double corner[3], double max[3], + double mid[3], double min[3], double size[3]) +{ + vtkIdType numPts, numCells, i; + vtkIdList *cellList; + vtkDataSet *origDataSet; + + vtkDebugMacro(<<"Computing OBB"); + + if ( input == NULL || (numPts = input->GetNumberOfPoints()) < 1 || + (input->GetNumberOfCells()) < 1 ) + { + vtkErrorMacro(<<"Can't compute OBB - no data available!"); + return; + } + numCells = input->GetNumberOfCells(); + + // save previous value of DataSet and reset after calling ComputeOBB because + // computeOBB used this->DataSet internally + origDataSet = this->DataSet; + this->DataSet = input; + + // these are other member variables that ComputeOBB requires + this->OBBCount = 0; + this->InsertedPoints = new int[numPts]; + for (i=0; i < numPts; i++) + { + this->InsertedPoints[i] = 0; + } + this->PointsList = vtkPoints::New(); + this->PointsList->Allocate(numPts); + + cellList = vtkIdList::New(); + cellList->Allocate(numCells); + for (i=0; i < numCells; i++) + { + cellList->InsertId(i,i); + } + + this->ComputeOBB(cellList, corner, max, mid, min, size); + + this->DataSet = origDataSet; + delete [] this->InsertedPoints; + this->PointsList->Delete(); + cellList->Delete(); +} + +// Compute an OBB from the list of cells given. Return the corner point +// and the three axes defining the orientation of the OBB. Also return +// a sorted list of relative "sizes" of axes for comparison purposes. +void vtkOBBTree::ComputeOBB(vtkIdList *cells, double corner[3], double max[3], + double mid[3], double min[3], double size[3]) +{ + vtkIdType numCells, i, j, cellId, ptId, pId, qId, rId; + int k, type; + vtkIdType numPts = 0; + vtkIdType *ptIds = 0; + double p[3], q[3], r[3], mean[3], xp[3], *v[3], v0[3], v1[3], v2[3]; + double *a[3], a0[3], a1[3], a2[3]; + double tMin[3], tMax[3], closest[3], t; + double dp0[3], dp1[3], tri_mass, tot_mass, c[3]; + + this->OBBCount++; + this->PointsList->Reset(); + // + // Compute mean & moments + // + + numCells = cells->GetNumberOfIds(); + mean[0] = mean[1] = mean[2] = 0.0; + tot_mass = 0.0; + a[0] = a0; a[1] = a1; a[2] = a2; + for ( i=0; i<3; i++ ) + { + a0[i] = a1[i] = a2[i] = 0.0; + } + + for ( i=0; i < numCells; i++ ) + { + cellId = cells->GetId( i ); + type = this->DataSet->GetCellType( cellId ); + switch (this->DataSet->GetDataObjectType()) + { + case VTK_POLY_DATA: + ((vtkPolyData *)this->DataSet)->GetCellPoints( cellId, numPts, ptIds ); + break; + case VTK_UNSTRUCTURED_GRID: + ((vtkUnstructuredGrid *)this->DataSet)->GetCellPoints( cellId, numPts, ptIds ); + break; + default: + vtkErrorMacro( <<"DataSet " << this->DataSet->GetClassName() << + " not supported." ); + break; + } + for ( j=0; jDataSet->GetPoint(pId, p); + this->DataSet->GetPoint(qId, q); + this->DataSet->GetPoint(rId, r); + // p, q, and r are the oriented triangle points. + // Compute the components of the moment of inertia tensor. + for ( k=0; k<3; k++ ) + { + // two edge vectors + dp0[k] = q[k] - p[k]; + dp1[k] = r[k] - p[k]; + // centroid + c[k] = (p[k] + q[k] + r[k])/3; + } + vtkMath::Cross( dp0, dp1, xp ); + tri_mass = 0.5*vtkMath::Norm( xp ); + tot_mass += tri_mass; + for ( k=0; k<3; k++ ) + { + mean[k] += tri_mass*c[k]; + } + + // on-diagonal terms + a0[0] += tri_mass*(9*c[0]*c[0] + p[0]*p[0] + q[0]*q[0] + r[0]*r[0])/12; + a1[1] += tri_mass*(9*c[1]*c[1] + p[1]*p[1] + q[1]*q[1] + r[1]*r[1])/12; + a2[2] += tri_mass*(9*c[2]*c[2] + p[2]*p[2] + q[2]*q[2] + r[2]*r[2])/12; + + // off-diagonal terms + a0[1] += tri_mass*(9*c[0]*c[1] + p[0]*p[1] + q[0]*q[1] + r[0]*r[1])/12; + a0[2] += tri_mass*(9*c[0]*c[2] + p[0]*p[2] + q[0]*q[2] + r[0]*r[2])/12; + a1[2] += tri_mass*(9*c[1]*c[2] + p[1]*p[2] + q[1]*q[2] + r[1]*r[2])/12; + } // end foreach triangle + + // While computing cell moments, gather all the cell's + // point coordinates into a single list. + // + for ( j=0; j < numPts; j++ ) + { + if ( this->InsertedPoints[ptIds[j]] != this->OBBCount ) + { + this->InsertedPoints[ptIds[j]] = this->OBBCount; + this->PointsList->InsertNextPoint(this->DataSet->GetPoint(ptIds[j])); + } + }//for all points of this cell + } // end foreach cell + + + // normalize data + for ( i=0; i<3; i++ ) + { + mean[i] = mean[i]/tot_mass; + } + + // matrix is symmetric + a1[0] = a0[1]; + a2[0] = a0[2]; + a2[1] = a1[2]; + + // get covariance from moments + for ( i=0; i<3; i++ ) + { + for ( j=0; j<3; j++ ) + { + a[i][j] = a[i][j]/tot_mass - mean[i]*mean[j]; + } + } + + // + // Extract axes (i.e., eigenvectors) from covariance matrix. + // + v[0] = v0; v[1] = v1; v[2] = v2; + vtkMath::Jacobi(a,size,v); + max[0] = v[0][0]; max[1] = v[1][0]; max[2] = v[2][0]; + mid[0] = v[0][1]; mid[1] = v[1][1]; mid[2] = v[2][1]; + min[0] = v[0][2]; min[1] = v[1][2]; min[2] = v[2][2]; + + for (i=0; i < 3; i++) + { + a[0][i] = mean[i] + max[i]; + a[1][i] = mean[i] + mid[i]; + a[2][i] = mean[i] + min[i]; + } + + // + // Create oriented bounding box by projecting points onto eigenvectors. + // + tMin[0] = tMin[1] = tMin[2] = VTK_DOUBLE_MAX; + tMax[0] = tMax[1] = tMax[2] = -VTK_DOUBLE_MAX; + + numPts = this->PointsList->GetNumberOfPoints(); + for (ptId=0; ptId < numPts; ptId++ ) + { + this->PointsList->GetPoint(ptId, p); + for (i=0; i < 3; i++) + { + vtkLine::DistanceToLine(p, mean, a[i], t, closest); + if ( t < tMin[i] ) + { + tMin[i] = t; + } + if ( t > tMax[i] ) + { + tMax[i] = t; + } + } + }//for all points + + for (i=0; i < 3; i++) + { + corner[i] = mean[i] + tMin[0]*max[i] + tMin[1]*mid[i] + tMin[2]*min[i]; + + max[i] = (tMax[0] - tMin[0]) * max[i]; + mid[i] = (tMax[1] - tMin[1]) * mid[i]; + min[i] = (tMax[2] - tMin[2]) * min[i]; + } +} + +// Efficient check for whether a line p1,p2 intersects with triangle +// pt1,pt2,pt3 to within specified tolerance. This is included here +// because vtkTriangle doesn't have an equivalently efficient method. + +// The intersection point is returned, along with the parametric +// coordinate t and the sense of the intersection (+1 if entering +// or -1 if exiting, according to normal of triangle) + +// The function return value is 1 if an intersection was found. + +static inline +int vtkOBBTreeLineIntersectsTriangle(double p1[3], double p2[3], + double pt1[3], double pt2[3], double pt3[3], + double tolerance, double point[3], + double &t, int &sense) +{ + double normal[3]; + vtkTriangle::ComputeNormal(pt1, pt2, pt3, normal); + + // vector from p1 to p2 + double v12[3]; + v12[0] = p2[0] - p1[0]; + v12[1] = p2[1] - p1[1]; + v12[2] = p2[2] - p1[2]; + + // vector from p1 to triangle + double v1t[3]; + v1t[0] = pt1[0] - p1[0]; + v1t[1] = pt1[1] - p1[1]; + v1t[2] = pt1[2] - p1[2]; + + // compute numerator/denominator of parametric distance + double numerator = vtkMath::Dot(normal, v1t); + double denominator = vtkMath::Dot(normal, v12); + if (denominator == 0) + { + return 0; + } + + // If denominator less than the tolerance, then the + // line and plane are considered parallel. + double fabsden = denominator; + sense = -1; + if (fabsden < 0.0) + { + sense = 1; + fabsden = -fabsden; + } + if (fabsden > 1e-6 + tolerance) + { + // calculate the distance to the intersection along the line + t = numerator/denominator; + if (t < 0.0 || t > 1.0) + { + return 0; + } + + // intersection point + point[0] = p1[0] + t*v12[0]; + point[1] = p1[1] + t*v12[1]; + point[2] = p1[2] + t*v12[2]; + + // find axis permutation to allow us to do the rest of the + // math in 2D (much more efficient than doing the math in 3D) + int xi = 0, yi = 1, zi = 2; + if (normal[0]*normal[0] < normal[1]*normal[1]) + { + xi = 1; yi = 2; zi = 0; + } + if (normal[xi]*normal[xi] < normal[2]*normal[2]) + { + xi = 2; yi = 0; zi = 1; + } + + // calculate vector from triangle corner to point + double u0 = point[yi] - pt1[yi]; + double v0 = point[zi] - pt1[zi]; + // calculate edge vectors for triangle + double u1 = pt2[yi] - pt1[yi]; + double v1 = pt2[zi] - pt1[zi]; + double u2 = pt3[yi] - pt1[yi]; + double v2 = pt3[zi] - pt1[zi]; + + // area of projected triangle (multiplied by 2) via cross product + double area = (v2*u1 - u2*v1); + + // sub-areas that must sum to less than the total area + double alpha = (v2*u0 - u2*v0); + double beta = (v0*u1 - u0*v1); + double gamma = area - alpha - beta; + + if (area < 0) + { + area = -area; + alpha = -alpha; + beta = -beta; + gamma = -gamma; + } + + if (alpha > 0 && beta > 0 && gamma > 0) + { // inside of polygon + return 1; + } + } + + // if zero tolerance, nothing more that we can do! + if (tolerance == 0) + { + return 0; + } + + // check the edges of the triangle (because triangles share edges, + // this check should be identical for adjacent triangles which is + // a 'good thing' + double tolsquared = tolerance*tolerance; + + // make sure that order of points in each line segment is the + // same for faces pointed in opposite directions + double *tpoints[4]; + if (sense > 0) + { + tpoints[0] = pt1; + tpoints[1] = pt2; + tpoints[2] = pt3; + tpoints[3] = pt1; + } + else + { + tpoints[0] = pt3; + tpoints[1] = pt2; + tpoints[2] = pt1; + tpoints[3] = pt3; + } + + double vec[3]; + double v; + for (int i = 0; i < 3; i++) + { + pt1 = tpoints[i]; + pt2 = tpoints[i+1]; + + if (vtkLine::Intersection(p1,p2, pt1,pt2, t,v) == 2) + { + vec[0] = (p1[0] + v12[0]*t) - (pt1[0] + (pt2[0] - pt1[0])*v); + vec[1] = (p1[1] + v12[1]*t) - (pt1[1] + (pt2[1] - pt1[1])*v); + vec[2] = (p1[2] + v12[2]*t) - (pt1[2] + (pt2[2] - pt1[2])*v); + + if (vtkMath::Dot(vec,vec) < tolsquared) + { + return 1; + } + } + } + + return 0; +} + +// just check whether a point lies inside or outside the DataSet, +// assuming that the data is a closed vtkPolyData surface. +int vtkOBBTree::InsideOrOutside(const double point[3]) +{ + // no points! + // shoot a ray that is guaranteed to hit one of the cells and use + // that as our inside/outside check + vtkIdType numCells = this->DataSet->GetNumberOfCells(); + for (vtkIdType i = 0; i < numCells; i++) + { + vtkIdType numPts; + vtkIdType *ptIds; + int cellType = this->DataSet->GetCellType(i); + ((vtkPolyData *)this->DataSet)->GetCellPoints(i, numPts, ptIds); + + // break the cell into triangles + for (vtkIdType j = 0; j < numPts-2; j++) + { + vtkIdType pt1Id, pt2Id, pt3Id; + vtkCELLTRIANGLES(ptIds, cellType, j, pt1Id, pt2Id, pt3Id); + if (pt1Id < 0) + { // cell wasn't a polygon, triangle, quad, or triangle strip + continue; + } + // create a point that is guaranteed to be inside the cell + double pt1[3], pt2[3], pt3[3]; + this->DataSet->GetPoint(pt1Id, pt1); + this->DataSet->GetPoint(pt2Id, pt2); + this->DataSet->GetPoint(pt3Id, pt3); + + double x[3]; + x[0] = (pt1[0] + pt2[0] + pt3[0])/3; + x[1] = (pt1[1] + pt2[1] + pt3[1])/3; + x[2] = (pt1[2] + pt2[2] + pt3[2])/3; + // make a line guaranteed to pass through the cell's first triangle + x[0] += x[0] - point[0]; + x[1] += x[1] - point[1]; + x[2] += x[2] - point[2]; + + // calculate vector + double v12[3]; + v12[0] = x[0] - point[0]; + v12[1] = x[1] - point[1]; + v12[2] = x[2] - point[2]; + + // get triangle normal, we need a triangle for whose face is + // not parallel to the line + double normal[3]; + vtkTriangle::ComputeNormal(pt1, pt2, pt3, normal); + double dotProd = vtkMath::Dot(normal, v12); + if (dotProd < 0) + { + dotProd = -dotProd; + } + if (dotProd >= this->Tolerance + 1e-6) + { + return this->IntersectWithLine(point, x, NULL, NULL); + } + // otherwise go on to next triangle + } + } + return 0; +} + + +// Take the passed line segment and intersect it with the OBB cells. +// This method assumes that the data set is a vtkPolyData that describes +// a closed surface, and the intersection points that are returned in +// 'points' alternate between entrance points and exit points. +// The return value of the function is 0 if no intersection was found, +// 1 if point 'p1' lies inside the polydata surface, or -1 if point 'p1' +// lies outside the polydata surface. +int vtkOBBTree::IntersectWithLine(const double p1[3], const double p2[3], + vtkPoints *points, vtkIdList *cellIds) +{ + if (this->DataSet == NULL) + { + if (points) + { + points->SetNumberOfPoints(0); + } + if (cellIds) + { + cellIds->SetNumberOfIds(0); + } + return 0; + } + if (!this->DataSet->IsA("vtkPolyData")) + { + vtkErrorMacro("IntersectWithLine: this method requires a vtkPolyData"); + return 0; + } + + int rval = 0; // return value for function + vtkIdList *cells; + + // temporary list used to sort intersections + int listSize = 0; + int listMaxSize = 10; + double *distanceList = new double[listMaxSize]; + vtkIdType *cellList = new vtkIdType[listMaxSize]; + char *senseList = new char[listMaxSize]; + + double point[3]; + double distance = 0; + int sense = 0; + vtkIdType cellId; + + // compute line vector from p1 to p2 + double v12[3]; + v12[0] = p2[0] - p1[0]; + v12[1] = p2[1] - p1[1]; + v12[2] = p2[2] - p1[2]; + + vtkOBBNode **OBBstack = new vtkOBBNode *[this->GetLevel()+1]; + OBBstack[0] = this->Tree; + + // depth counter for stack + int depth = 1; + while(depth > 0) + { // simulate recursion without the overhead or limitations + vtkOBBNode *node = OBBstack[--depth]; + + // check for intersection with node + if (this->LineIntersectsNode(node, (double *)p1, (double *)p2)) + { + if (node->Kids == NULL) + { // then this is a leaf node...get Cells + cells = node->Cells; + vtkIdType numCells = cells->GetNumberOfIds(); + for (vtkIdType i = 0; i < numCells; i++) + { + // get the current cell + cellId = cells->GetId(i); + int cellType = this->DataSet->GetCellType(cellId); + vtkIdType numPts; + vtkIdType *ptIds; + ((vtkPolyData *)this->DataSet)->GetCellPoints(cellId, numPts, ptIds); + + // break the cell into triangles + for (vtkIdType j = 0; j < numPts-2; j++) + { + vtkIdType pt1Id, pt2Id, pt3Id; + vtkCELLTRIANGLES(ptIds, cellType, j, pt1Id, pt2Id, pt3Id); + if (pt1Id < 0) + { // cell wasn't a polygon, triangle, quad, or triangle strip + continue; + } + + // get the points for this triangle + double pt1[3], pt2[3], pt3[3]; + this->DataSet->GetPoint(pt1Id, pt1); + this->DataSet->GetPoint(pt2Id, pt2); + this->DataSet->GetPoint(pt3Id, pt3); + + if (vtkOBBTreeLineIntersectsTriangle((double *)p1, (double *)p2, + pt1, pt2, pt3, + this->Tolerance, point, + distance, sense) <= 0) + { // no intersection with triangle + continue; + } + + // we made it! we have a hit! + + if (listSize >= listMaxSize) + { // have to grow the distanceList + listMaxSize *= 2; + double *tmpDistanceList = new double[listMaxSize]; + vtkIdType *tmpCellList = new vtkIdType[listMaxSize]; + char *tmpSenseList = new char[listMaxSize]; + for (int k = 0; k < listSize; k++) + { + tmpDistanceList[k] = distanceList[k]; + tmpCellList[k] = cellList[k]; + tmpSenseList[k] = senseList[k]; + } + delete [] distanceList; + distanceList = tmpDistanceList; + delete [] cellList; + cellList = tmpCellList; + delete [] senseList; + senseList = tmpSenseList; + } + // store in the distanceList + distanceList[listSize] = distance; + cellList[listSize] = cellId; + senseList[listSize++] = sense; + + // if cell is planar (i.e. not a triangle strip) then proceed + // immediately to the next cell, otherwise go to next triangle + if (cellType != VTK_TRIANGLE_STRIP) + { + break; + } + } + } + } + else + { // push kids onto stack + OBBstack[depth] = node->Kids[0]; + OBBstack[depth+1] = node->Kids[1]; + depth += 2; + } + } + } // end while + + if (listSize != 0) + { + // Look at the distanceList and return the intersection point + // sorted according to their distance from p1. + + if (points) + { + points->SetNumberOfPoints(listSize); + } + if (cellIds) + { + cellIds->SetNumberOfIds(0); + } + double ptol = this->Tolerance/sqrt(vtkMath::Dot(v12,v12)); + double lastDistance = 0.0; + int lastSense = 0; + int nPoints = 0; + int listRemainder = listSize; + while (listRemainder) + { + int minIdx = 0; + for (int j = 1; j < listRemainder; j++) + { // check for closest intersection of the correct sense + if (senseList[j] != lastSense && + distanceList[j] < distanceList[minIdx]) + { + minIdx = j; + } + } + + distance = distanceList[minIdx]; + cellId = cellList[minIdx]; + sense = senseList[minIdx]; + listRemainder--; + distanceList[minIdx] = distanceList[listRemainder]; + cellList[minIdx] = cellList[listRemainder]; + senseList[minIdx] = senseList[listRemainder]; + + // only use point if it moves us forward, + // or it moves us backward by less than tol + if (distance > lastDistance - ptol && sense != lastSense) + { + if (points) + { + point[0] = p1[0] + distance*v12[0]; + point[1] = p1[1] + distance*v12[1]; + point[2] = p1[2] + distance*v12[2]; + points->SetPoint(nPoints, point); + } + if (cellIds) + { + cellIds->InsertNextId(cellId); + } + nPoints++; + + // set return value according to sense of first intersection + if (rval == 0) + { + rval = sense; + } + // remember the last point + lastDistance = distance; + lastSense = sense; + } + } + // shrink points array if not all points were used + if (nPoints < listSize) + { + if (points) + { + points->GetData()->Resize(nPoints); + } + } + // done! + } + else + { + if (points) + { + points->SetNumberOfPoints(0); + } + if (cellIds) + { + cellIds->SetNumberOfIds(0); + } + } + + delete [] senseList; + delete [] cellList; + delete [] distanceList; + delete [] OBBstack; + // return 1 if p1 is inside, 0 is p1 is outside + return rval; +} + +// Return intersection point of line defined by two points (a0,a1) in dataset +// coordinate system; returning cellId (or -1 if no intersection). The +// argument list returns the intersection parametric coordinate, t, along +// the line; the coordinate of intersection, x[3]; the cell parametric +// coordinates, pcoords[3]; and subId of the cell. (Not yet implemented.) +int vtkOBBTree::IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId) +{ + vtkIdType cellId = -1; + + return this->IntersectWithLine( a0, a1, tol, t, x, pcoords, + subId, cellId ); +} + +// Return intersection point of line defined by two points (a0,a1) in dataset +// coordinate system; returning cellId (or -1 if no intersection). The +// argument list returns the intersection parametric coordinate, t, along +// the line; the coordinate of intersection, x[3]; the cell parametric +// coordinates, pcoords[3]; and subId of the cell. (Not yet implemented.) +int vtkOBBTree::IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId) +{ + vtkGenericCell *cell=vtkGenericCell::New(); + int returnVal; + + returnVal = this->IntersectWithLine( a0, a1, tol, t, x, pcoords, subId, + cellId, cell); + + cell->Delete(); + return returnVal; +} + +// Return intersection point (if any) AND the cell which was intersected by +// finite line +int vtkOBBTree::IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId, + vtkGenericCell *cell) +{ + vtkOBBNode **OBBstack, *node; + vtkIdList *cells; + int depth, ii, foundIntersection = 0, bestIntersection = 0; + double tBest = VTK_DOUBLE_MAX, xBest[3], pcoordsBest[3]; + int subIdBest = -1; + vtkIdType thisId, cellIdBest = -1; + + OBBstack = new vtkOBBNode *[this->GetLevel()+1]; + OBBstack[0] = this->Tree; + depth = 1; + while( depth > 0 ) + { // simulate recursion without the overhead or limitations + depth--; + node = OBBstack[depth]; + if ( this->LineIntersectsNode( node, a0, a1 ) ) + { + if ( node->Kids == NULL ) + { // then this is a leaf node...get Cells + cells = node->Cells; + for ( ii=0; iiGetNumberOfIds(); ii++ ) + { + thisId = cells->GetId(ii); + this->DataSet->GetCell( thisId, cell); + if ( cell->IntersectWithLine( a0, a1, tol, t, x, + pcoords, subId ) ) + { // line intersects cell, but is it the best one? + foundIntersection++; + if ( t < tBest ) + { // Yes, it's the best. + bestIntersection = foundIntersection; + tBest = t; + xBest[0] = x[0]; xBest[1] = x[1]; xBest[2] = x[2]; + pcoordsBest[0] = pcoords[0]; pcoordsBest[1] = pcoords[1]; + pcoordsBest[2] = pcoords[2]; + subIdBest = subId; + cellIdBest = thisId; + } + } + } + } + else + { // push kids onto stack + OBBstack[depth] = node->Kids[0]; + OBBstack[depth+1] = node->Kids[1]; + depth += 2; + } + } + } // end while + + if ( foundIntersection != bestIntersection ) + { + t = tBest; + x[0] = xBest[0]; x[1] = xBest[1]; x[2] = xBest[2]; + pcoords[0] = pcoordsBest[0]; pcoords[1] = pcoordsBest[1]; + pcoords[2] = pcoordsBest[2]; + subId= subIdBest ; + } + + delete [] OBBstack; + + if ( cellIdBest < 0 ) + { + return 0; + } + else + { + cellId = cellIdBest; + return 1; + } +} + +void vtkOBBNode::DebugPrintTree( int level, double *leaf_vol, + int *minCells, int *maxCells ) + { + double xp[3], volume, c[3]; + int i; + vtkIdType nCells; + + if ( this->Cells != NULL ) + { + nCells = this->Cells->GetNumberOfIds(); + } + else + { + nCells = 0; + } + + vtkMath::Cross( this->Axes[0], this->Axes[1], xp ); + volume = fabs( vtkMath::Dot( xp, this->Axes[2] ) ); + for ( i=0; i<3; i++ ) + { + c[i] = this->Corner[i] + 0.5*this->Axes[0][i] + 0.5*this->Axes[1][i] + + 0.5*this->Axes[2][i]; + } + + for ( i=0; iAxes[0] ) << " X " << + vtkMath::Norm( this->Axes[1] ) << " X " << + vtkMath::Norm( this->Axes[2] ) << "\n"; + for ( i=0; i *maxCells ) + { + *maxCells = nCells; + } + } + if ( this->Kids != NULL ) + { + this->Kids[0]->DebugPrintTree( level+1, leaf_vol, minCells, maxCells ); + this->Kids[1]->DebugPrintTree( level+1, leaf_vol, minCells, maxCells ); + } + } + +// +// Method to form subdivision of space based on the cells provided and +// subject to the constraints of levels and NumberOfCellsInOctant. +// The result is directly addressable and of uniform subdivision. +// +void vtkOBBTree::BuildLocator() +{ + vtkIdType numPts, numCells, i; + vtkIdList *cellList; + + vtkDebugMacro(<<"Building OBB tree"); + if ( (this->Tree != NULL) && (this->BuildTime > this->MTime) + && (this->BuildTime > this->DataSet->GetMTime()) ) + { + return; + } + + numPts = this->DataSet->GetNumberOfPoints(); + numCells = this->DataSet->GetNumberOfCells(); + if ( this->DataSet == NULL || numPts < 1 || numCells < 1 ) + { + vtkErrorMacro(<<"Can't build OBB tree - no data available!"); + return; + } + + this->OBBCount = 0; + this->InsertedPoints = new int[numPts]; + for (i=0; i < numPts; i++) + { + this->InsertedPoints[i] = 0; + } + this->PointsList = vtkPoints::New(); + this->PointsList->Allocate(numPts); + + // + // Begin recursively creating OBB's + // + cellList = vtkIdList::New(); + cellList->Allocate(numCells); + for (i=0; i < numCells; i++) + { + cellList->InsertId(i,i); + } + + if ( this->Tree ) + { + this->DeleteTree(this->Tree); + delete this->Tree; + } + this->Tree = new vtkOBBNode; + this->DeepestLevel = 0; + this->BuildTree(cellList,this->Tree,0); + this->Level = this->DeepestLevel; + + vtkDebugMacro(<<"# Cells: " << numCells << ", Deepest tree level: " << + this->DeepestLevel <<", Created: " << this->OBBCount << " OBB nodes"); + if ( this->GetDebug() > 1 ) + { // print tree + double volume = 0.0; + int minCells = 65535, maxCells = 0; + this->Tree->DebugPrintTree( 0, &volume, &minCells, &maxCells ); + cout<<"Total leafnode volume = "<InsertedPoints; + this->PointsList->Delete(); + + this->BuildTime.Modified(); +} + +// NOTE: for better memory usage this recursive method +// frees its first argument +void vtkOBBTree::BuildTree(vtkIdList *cells, vtkOBBNode *OBBptr, int level) +{ + vtkIdType i, j, numCells=cells->GetNumberOfIds(); + vtkIdType cellId; + int ptId; + vtkIdList *cellPts = vtkIdList::New(); + double size[3]; + + if ( level > this->DeepestLevel ) + { + this->DeepestLevel = level; + } + // + // Now compute the OBB + // + this->ComputeOBB(cells, OBBptr->Corner, OBBptr->Axes[0], + OBBptr->Axes[1], OBBptr->Axes[2], size); + + // + // Check whether to continue recursing; if so, create two children and + // assign cells to appropriate child. + // + if ( level < this->MaxLevel && numCells > this->NumberOfCellsPerBucket ) + { + vtkIdList *LHlist = vtkIdList::New(); + LHlist->Allocate(cells->GetNumberOfIds()/2); + vtkIdList *RHlist = vtkIdList::New(); + RHlist->Allocate(cells->GetNumberOfIds()/2); + double n[3], p[3], c[3], x[3], val, ratio, bestRatio; + int negative, positive, splitAcceptable, splitPlane; + int foundBestSplit, bestPlane=0, numPts; + int numInLHnode, numInRHnode; + + //loop over three split planes to find acceptable one + for (i=0; i < 3; i++) //compute split point + { + p[i] = OBBptr->Corner[i] + OBBptr->Axes[0][i]/2.0 + + OBBptr->Axes[1][i]/2.0 + OBBptr->Axes[2][i]/2.0; + } + + bestRatio = 1.0; // worst case ratio + foundBestSplit = 0; + for (splitPlane=0,splitAcceptable=0; !splitAcceptable && splitPlane < 3; ) + { + // compute split normal + for (i=0 ; i < 3; i++) + { + n[i] = OBBptr->Axes[splitPlane][i]; + } + vtkMath::Normalize(n); + + //traverse cells, assigning to appropriate child list as necessary + for ( i=0; i < numCells; i++ ) + { + cellId = cells->GetId(i); + this->DataSet->GetCellPoints(cellId, cellPts); + c[0] = c[1] = c[2] = 0.0; + numPts = cellPts->GetNumberOfIds(); + for ( negative=positive=j=0; j < numPts; j++ ) + { + ptId = cellPts->GetId(j); + this->DataSet->GetPoint(ptId, x); + val = n[0]*(x[0]-p[0]) + n[1]*(x[1]-p[1]) + n[2]*(x[2]-p[2]); + c[0] += x[0]; + c[1] += x[1]; + c[2] += x[2]; + if ( val < 0.0 ) + { + negative = 1; + } + else + { + positive = 1; + } + } + + if ( negative && positive ) + { // Use centroid to decide straddle cases + c[0] /= numPts; + c[1] /= numPts; + c[2] /= numPts; + if ( n[0]*(c[0]-p[0])+n[1]*(c[1]-p[1])+n[2]*(c[2]-p[2]) < 0.0 ) + { + LHlist->InsertNextId(cellId); + } + else + { + RHlist->InsertNextId(cellId); + } + } + else + { + if ( negative ) + { + LHlist->InsertNextId(cellId); + } + else + { + RHlist->InsertNextId(cellId); + } + } + }//for all cells + + //evaluate this split + numInLHnode = LHlist->GetNumberOfIds(); + numInRHnode = RHlist->GetNumberOfIds(); + ratio = fabs(((double)numInRHnode-numInLHnode)/numCells); + + //see whether we've found acceptable split plane + if ( ratio < 0.6 || foundBestSplit ) //accept right off the bat + { + splitAcceptable = 1; + } + else + { //not a great split try another + LHlist->Reset(); + RHlist->Reset(); + if ( ratio < bestRatio ) + { + bestRatio = ratio; + bestPlane = splitPlane; + } + if ( ++splitPlane == 3 && bestRatio < 0.95 ) + { //at closing time, even the ugly ones look good + splitPlane = bestPlane; + foundBestSplit = 1; + } + } //try another split + + }//for each split + + if ( splitAcceptable ) //otherwise recursion terminates + { + vtkOBBNode *LHnode= new vtkOBBNode; + vtkOBBNode *RHnode= new vtkOBBNode; + OBBptr->Kids = new vtkOBBNode *[2]; + OBBptr->Kids[0] = LHnode; + OBBptr->Kids[1] = RHnode; + LHnode->Parent = OBBptr; + RHnode->Parent = OBBptr; + + cells->Delete(); cells = NULL; //don't need to keep anymore + this->BuildTree(LHlist, LHnode, level+1); + this->BuildTree(RHlist, RHnode, level+1); + } + else + { + // free up local objects + LHlist->Delete(); + RHlist->Delete(); + } + }//if should build tree + + if ( cells && this->RetainCellLists ) + { + cells->Squeeze(); + OBBptr->Cells = cells; + } + else if ( cells ) + { + cells->Delete(); + } + cellPts->Delete(); +} + +// Create polygonal representation for OBB tree at specified level. If +// level < 0, then the leaf OBB nodes will be gathered. The aspect ratio (ar) +// and line diameter (d) are used to control the building of the +// representation. If a OBB node edge ratio's are greater than ar, then the +// dimension of the OBB is collapsed (OBB->plane->line). A "line" OBB will be +// represented either as two crossed polygons, or as a line, depending on +// the relative diameter of the OBB compared to the diameter (d). + +void vtkOBBTree::GenerateRepresentation(int level, vtkPolyData *pd) +{ + vtkPoints *pts; + vtkCellArray *polys; + + if ( this->Tree == NULL ) + { + vtkErrorMacro(<<"No tree to generate representation from"); + return; + } + + pts = vtkPoints::New(); + pts->Allocate(5000); + polys = vtkCellArray::New(); + polys->Allocate(10000); + this->GeneratePolygons(this->Tree,0,level,pts,polys); + + pd->SetPoints(pts); + pts->Delete(); + pd->SetPolys(polys); + polys->Delete(); + pd->Squeeze(); +} + +void vtkOBBTree::GeneratePolygons(vtkOBBNode *OBBptr, int level, int repLevel, + vtkPoints *pts, vtkCellArray *polys) + +{ + if ( level == repLevel || (repLevel < 0 && OBBptr->Kids == NULL) ) + { + double x[3]; + vtkIdType cubeIds[8]; + vtkIdType ptIds[4]; + + x[0] = OBBptr->Corner[0]; + x[1] = OBBptr->Corner[1]; + x[2] = OBBptr->Corner[2]; + cubeIds[0] = pts->InsertNextPoint(x); + + x[0] = OBBptr->Corner[0] + OBBptr->Axes[0][0]; + x[1] = OBBptr->Corner[1] + OBBptr->Axes[0][1]; + x[2] = OBBptr->Corner[2] + OBBptr->Axes[0][2]; + cubeIds[1] = pts->InsertNextPoint(x); + + x[0] = OBBptr->Corner[0] + OBBptr->Axes[1][0]; + x[1] = OBBptr->Corner[1] + OBBptr->Axes[1][1]; + x[2] = OBBptr->Corner[2] + OBBptr->Axes[1][2]; + cubeIds[2] = pts->InsertNextPoint(x); + + x[0] = OBBptr->Corner[0] + OBBptr->Axes[0][0] + OBBptr->Axes[1][0]; + x[1] = OBBptr->Corner[1] + OBBptr->Axes[0][1] + OBBptr->Axes[1][1]; + x[2] = OBBptr->Corner[2] + OBBptr->Axes[0][2] + OBBptr->Axes[1][2]; + cubeIds[3] = pts->InsertNextPoint(x); + + x[0] = OBBptr->Corner[0] + OBBptr->Axes[2][0]; + x[1] = OBBptr->Corner[1] + OBBptr->Axes[2][1]; + x[2] = OBBptr->Corner[2] + OBBptr->Axes[2][2]; + cubeIds[4] = pts->InsertNextPoint(x); + + x[0] = OBBptr->Corner[0] + OBBptr->Axes[0][0] + OBBptr->Axes[2][0]; + x[1] = OBBptr->Corner[1] + OBBptr->Axes[0][1] + OBBptr->Axes[2][1]; + x[2] = OBBptr->Corner[2] + OBBptr->Axes[0][2] + OBBptr->Axes[2][2]; + cubeIds[5] = pts->InsertNextPoint(x); + + x[0] = OBBptr->Corner[0] + OBBptr->Axes[1][0] + OBBptr->Axes[2][0]; + x[1] = OBBptr->Corner[1] + OBBptr->Axes[1][1] + OBBptr->Axes[2][1]; + x[2] = OBBptr->Corner[2] + OBBptr->Axes[1][2] + OBBptr->Axes[2][2]; + cubeIds[6] = pts->InsertNextPoint(x); + + x[0] = OBBptr->Corner[0] + OBBptr->Axes[0][0] + OBBptr->Axes[1][0] + + OBBptr->Axes[2][0]; + x[1] = OBBptr->Corner[1] + OBBptr->Axes[0][1] + OBBptr->Axes[1][1] + + OBBptr->Axes[2][1]; + x[2] = OBBptr->Corner[2] + OBBptr->Axes[0][2] + OBBptr->Axes[1][2] + + OBBptr->Axes[2][2]; + cubeIds[7] = pts->InsertNextPoint(x); + + ptIds[0] = cubeIds[0]; ptIds[1] = cubeIds[2]; + ptIds[2] = cubeIds[3]; ptIds[3] = cubeIds[1]; + polys->InsertNextCell(4,ptIds); + + ptIds[0] = cubeIds[0]; ptIds[1] = cubeIds[1]; + ptIds[2] = cubeIds[5]; ptIds[3] = cubeIds[4]; + polys->InsertNextCell(4,ptIds); + + ptIds[0] = cubeIds[0]; ptIds[1] = cubeIds[4]; + ptIds[2] = cubeIds[6]; ptIds[3] = cubeIds[2]; + polys->InsertNextCell(4,ptIds); + + ptIds[0] = cubeIds[1]; ptIds[1] = cubeIds[3]; + ptIds[2] = cubeIds[7]; ptIds[3] = cubeIds[5]; + polys->InsertNextCell(4,ptIds); + + ptIds[0] = cubeIds[4]; ptIds[1] = cubeIds[5]; + ptIds[2] = cubeIds[7]; ptIds[3] = cubeIds[6]; + polys->InsertNextCell(4,ptIds); + + ptIds[0] = cubeIds[2]; ptIds[1] = cubeIds[6]; + ptIds[2] = cubeIds[7]; ptIds[3] = cubeIds[3]; + polys->InsertNextCell(4,ptIds); + } + + else if ( (level < repLevel || repLevel < 0) && OBBptr->Kids != NULL ) + { + this->GeneratePolygons(OBBptr->Kids[0],level+1,repLevel,pts,polys); + this->GeneratePolygons(OBBptr->Kids[1],level+1,repLevel,pts,polys); + } +} + +int vtkOBBTree::DisjointOBBNodes( vtkOBBNode *nodeA, + vtkOBBNode *nodeB, + vtkMatrix4x4 *XformBtoA ) + { + vtkOBBNode nodeBxformed, *pB, *pA; + double centerA[3], centerB[3], AtoB[3], in[4], out[4]; + double rangeAmin, rangeAmax, rangeBmin, rangeBmax, dotA, dotB, + dotAB[3][3]; + double eps; + int ii, jj, kk; + + eps = this->Tolerance; + pA = nodeA; + if ( XformBtoA != NULL ) + { // Here we assume that XformBtoA is an orthogonal matrix + pB = &nodeBxformed; + in[0] = nodeB->Corner[0]; in[1] = nodeB->Corner[1] ; + in[2] = nodeB->Corner[2]; in[3] = 1.0; + XformBtoA->MultiplyPoint( in, out ); + pB->Corner[0] = out[0]/out[3]; + pB->Corner[1] = out[1]/out[3]; + pB->Corner[2] = out[2]/out[3]; + // Clean this up when the bug in MultiplyVectors is fixed! + for ( ii=0; ii<3; ii++ ) + { + pB->Axes[0][ii] = nodeB->Corner[ii] + nodeB->Axes[0][ii]; + pB->Axes[1][ii] = nodeB->Corner[ii] + nodeB->Axes[1][ii]; + pB->Axes[2][ii] = nodeB->Corner[ii] + nodeB->Axes[2][ii]; + } + for ( ii=0; ii<3; ii++ ) + { + in[0] = pB->Axes[ii][0]; in[1] = pB->Axes[ii][1]; + in[2] = pB->Axes[ii][2]; in[3] = 1.0; + XformBtoA->MultiplyPoint( in, out ); + pB->Axes[ii][0] = out[0]/out[3]; + pB->Axes[ii][1] = out[1]/out[3]; + pB->Axes[ii][2] = out[2]/out[3]; + } + for ( ii=0; ii<3; ii++ ) + { + pB->Axes[0][ii] = pB->Axes[0][ii] - pB->Corner[ii]; + pB->Axes[1][ii] = pB->Axes[1][ii] - pB->Corner[ii]; + pB->Axes[2][ii] = pB->Axes[2][ii] - pB->Corner[ii]; + } + } + else + { + pB = nodeB; + } + for ( ii=0; ii<3; ii++ ) + { + centerA[ii] = pA->Corner[ii] + + 0.5*(pA->Axes[0][ii] + pA->Axes[1][ii] + pA->Axes[2][ii]); + centerB[ii] = pB->Corner[ii] + + 0.5*(pB->Axes[0][ii] + pB->Axes[1][ii] + pB->Axes[2][ii]); + AtoB[ii] = centerB[ii] - centerA[ii]; + } + + // Project maximal and minimal corners onto line between centers + rangeAmin = rangeAmax = vtkMath::Dot( pA->Corner, AtoB ); + rangeBmin = rangeBmax = vtkMath::Dot( pB->Corner, AtoB ); + for ( ii=0; ii<3; ii++ ) + { + // compute A range + dotA = vtkMath::Dot( pA->Axes[ii], AtoB ); + if ( dotA > 0 ) + { + rangeAmax += dotA; + } + else + { + rangeAmin += dotA; + } + + // compute B range + dotB = vtkMath::Dot( pB->Axes[ii], AtoB ); + if ( dotB > 0 ) + { + rangeBmax += dotB; + } + else + { + rangeBmin += dotB; + } + } + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return( 1 ); // A and B are Disjoint by the 1st test. + } + + // now check for a separation plane parallel to the faces of B + for ( ii=0; ii<3; ii++ ) + { // plane is normal to pB->Axes[ii] + // computing B range is easy... + rangeBmin = rangeBmax = vtkMath::Dot( pB->Corner, pB->Axes[ii] ); + rangeBmax += vtkMath::Dot( pB->Axes[ii], pB->Axes[ii] ); + + // compute A range... + rangeAmin = rangeAmax = vtkMath::Dot( pA->Corner, pB->Axes[ii] ); + for ( jj=0; jj<3; jj++ ) + { + // (note: we are saving all 9 dotproducts for future use) + dotA = dotAB[ii][jj] = vtkMath::Dot( pB->Axes[ii], pA->Axes[jj] ); + if ( dotA > 0 ) + { + rangeAmax += dotA; + } + else + { + rangeAmin += dotA; + } + } + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return( 2 ); // A and B are Disjoint by the 3rd test. + } + } + + // now check for a separation plane parallel to the faces of A + for ( ii=0; ii<3; ii++ ) + { // plane is normal to pA->Axes[ii] + // computing A range is easy... + rangeAmin = rangeAmax = vtkMath::Dot( pA->Corner, pA->Axes[ii] ); + rangeAmax += vtkMath::Dot( pA->Axes[ii], pA->Axes[ii] ); + + // compute B range... + rangeBmin = rangeBmax = vtkMath::Dot( pB->Corner, pA->Axes[ii] ); + for ( jj=0; jj<3; jj++ ) + { + // (note: we are using the 9 dotproducts computed earlier) + dotB = dotAB[jj][ii]; + if ( dotB > 0 ) + { + rangeBmax += dotB; + } + else + { + rangeBmin += dotB; + } + } + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return( 3 ); // A and B are Disjoint by the 2nd test. + } + } + + // Bad luck: now we must look for a separation plane parallel + // to one edge from A and one edge from B. + for ( ii=0; ii<3; ii++ ) + { + for ( jj=0; jj<3; jj++ ) + { + // the plane is normal to pA->Axes[ii] X pB->Axes[jj] + vtkMath::Cross( pA->Axes[ii], pB->Axes[jj], AtoB ); + rangeAmin = rangeAmax = vtkMath::Dot( pA->Corner, AtoB ); + rangeBmin = rangeBmax = vtkMath::Dot( pB->Corner, AtoB ); + for ( kk=0; kk<3; kk++ ) + { + // compute A range + dotA = vtkMath::Dot( pA->Axes[kk], AtoB ); + if ( dotA > 0 ) + { + rangeAmax += dotA; + } + else + { + rangeAmin += dotA; + } + + // compute B range + dotB = vtkMath::Dot( pB->Axes[kk], AtoB ); + if ( dotB > 0 ) + { + rangeBmax += dotB; + } + else + { + rangeBmin += dotB; + } + } + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return( 4 ); // A and B are Disjoint by the 4th test. + } + } + } + // if we fall through to here, the OBB's overlap + return( 0 ); + } + +int vtkOBBTree::TriangleIntersectsNode( vtkOBBNode *nodeA, + double p0[3], double p1[3], double p2[3], + vtkMatrix4x4 *XformBtoA ) + { + vtkOBBNode *pA; + double p0Xformed[3], p1Xformed[3], p2Xformed[3]; + double *pB[3], in[4], out[4], v0[3], v1[3], AtoB[3], xprod[3]; + double rangeAmin, rangeAmax, rangeBmin, rangeBmax, dotA, dotB; + double eps; + int ii, jj, kk; + + eps = this->Tolerance; + pA = nodeA; + if ( XformBtoA != NULL ) + { // Here we assume that XformBtoA is an orthogonal matrix + pB[0] = p0Xformed; pB[1] = p1Xformed; pB[2] = p2Xformed; + for ( ii=0; ii<3; ii++ ) + { + p0Xformed[ii] = p0[ii]; + p1Xformed[ii] = p1[ii]; + p2Xformed[ii] = p2[ii]; + } + for ( ii=0; ii<3; ii++ ) + { + in[0] = pB[ii][0]; in[1] = pB[ii][1] ; in[2] = pB[ii][2]; in[3] = 1.0; + XformBtoA->MultiplyPoint( in, out ); + pB[ii][0] = out[0]/out[3]; + pB[ii][1] = out[1]/out[3]; + pB[ii][2] = out[2]/out[3]; + } + } + else + { + pB[0] = p0; pB[1] = p1; pB[2] = p2; + } + + // now check for a separation plane parallel to the triangle + for ( ii=0; ii<3; ii++ ) + { // plane is normal to the triangle + v0[ii] = pB[1][ii] - pB[0][ii]; + v1[ii] = pB[2][ii] - pB[0][ii]; + } + vtkMath::Cross( v0, v1, xprod ); + // computing B range is easy... + rangeBmin = rangeBmax = vtkMath::Dot( pB[0], xprod ); + // compute A range... + rangeAmin = rangeAmax = vtkMath::Dot( pA->Corner, xprod ); + for ( jj=0; jj<3; jj++ ) + { + dotA = vtkMath::Dot( xprod, pA->Axes[jj] ); + if ( dotA > 0 ) + { + rangeAmax += dotA; + } + else + { + rangeAmin += dotA; + } + } + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return( 0 ); // A and B are Disjoint by the 1st test. + } + + // now check for a separation plane parallel to the faces of A + for ( ii=0; ii<3; ii++ ) + { // plane is normal to pA->Axes[ii] + // computing A range is easy... + rangeAmin = rangeAmax = vtkMath::Dot( pA->Corner, pA->Axes[ii] ); + rangeAmax += vtkMath::Dot( pA->Axes[ii], pA->Axes[ii] ); + + // compute B range... + rangeBmin = rangeBmax = vtkMath::Dot( pB[0], pA->Axes[ii] ); + dotB = vtkMath::Dot( pB[1], pA->Axes[ii] ); + if ( dotB > rangeBmax ) + { + rangeBmax = dotB; + } + else + { + rangeBmin = dotB; + } + + dotB = vtkMath::Dot( pB[2], pA->Axes[ii] ); + if ( dotB > rangeBmax ) + { + rangeBmax = dotB; + } + else if ( dotB < rangeBmin ) + { + rangeBmin = dotB; + } + + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return( 0 ); // A and B are Disjoint by the 2nd test. + } + } + + // Bad luck: now we must look for a separation plane parallel + // to one edge from A and one edge from B. + for ( ii=0; ii<3; ii++ ) + { + for ( jj=0; jj<3; jj++ ) + { + // the plane is normal to pA->Axes[ii] X (pB[jj+1]-pB[jj]) + v0[0] = pB[(jj+1)%3][0] - pB[jj][0]; + v0[1] = pB[(jj+1)%3][1] - pB[jj][1]; + v0[2] = pB[(jj+1)%3][2] - pB[jj][2]; + vtkMath::Cross( pA->Axes[ii], v0, AtoB ); + rangeAmin = rangeAmax = vtkMath::Dot( pA->Corner, AtoB ); + rangeBmin = rangeBmax = vtkMath::Dot( pB[jj], AtoB ); + for ( kk=0; kk<3; kk++ ) + { + // compute A range + dotA = vtkMath::Dot( pA->Axes[kk], AtoB ); + if ( dotA > 0 ) + { + rangeAmax += dotA; + } + else + { + rangeAmin += dotA; + } + } + // compute B range + dotB = vtkMath::Dot( pB[(jj+2)%3], AtoB ); + if ( dotB > rangeBmax ) + { + rangeBmax = dotB; + } + else + { + rangeBmin = dotB; + } + + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return( 0 ); // A and B are Disjoint by the 3rd test. + } + } + } + + // if we fall through to here, the OBB overlaps the triangle. + return( 1 ); + } + + +// check if a line intersects the node: the line doesn't have to actually +// pass all the way through the node, but at least some portion of the line +// must lie within the node. +int vtkOBBTree::LineIntersectsNode( vtkOBBNode *pA, + double b0[3], double b1[3] ) +{ + double rangeAmin, rangeAmax, rangeBmin, rangeBmax, dotB; + double eps; + int ii; + + for ( ii = 0; ii < 3; ii++ ) + { + // computing A range is easy... + rangeAmin = vtkMath::Dot( pA->Corner, pA->Axes[ii] ); + rangeAmax = rangeAmin + vtkMath::Dot( pA->Axes[ii], pA->Axes[ii] ); + + // compute B range... + rangeBmin = vtkMath::Dot( b0, pA->Axes[ii] ); + rangeBmax = rangeBmin; + dotB = vtkMath::Dot( b1, pA->Axes[ii] ); + if ( dotB < rangeBmin ) + { + rangeBmin = dotB; + } + else + { + rangeBmax = dotB; + } + + eps = this->Tolerance; + if ( eps != 0 ) + { // avoid sqrt call if tolerance check isn't being done + eps *= sqrt(fabs(rangeAmax - rangeAmin)); + } + + if ( (rangeAmax+eps < rangeBmin) || (rangeBmax+eps < rangeAmin) ) + { + return ( 0 ); + } + } + + // if we fall through to here, the OBB overlaps the line segment. + return ( 1 ); +} + +// Intersect this OBBTree with OBBTreeB (as transformed) and +// call processing function for each intersecting leaf node pair. +// If the processing function returns a negative integer, terminate. +int vtkOBBTree::IntersectWithOBBTree( vtkOBBTree *OBBTreeB, + vtkMatrix4x4 *XformBtoA, + int(*function)( vtkOBBNode *nodeA, + vtkOBBNode *nodeB, + vtkMatrix4x4 *Xform, + void *arg ), + void *data_arg ) + { + int maxdepth, mindepth, depth, returnValue = 0, count = 0, maxStackDepth; + vtkOBBNode **OBBstackA, **OBBstackB, *nodeA, *nodeB; + + // Intersect OBBs and process intersecting leaf nodes. + maxdepth = this->GetLevel(); + if ( (mindepth = OBBTreeB->GetLevel()) > maxdepth ) + { + mindepth = maxdepth; + maxdepth = OBBTreeB->GetLevel(); + } + // Compute maximum theoretical recursion depth. + maxStackDepth = 3*mindepth + 2*(maxdepth-mindepth) + 1; + + OBBstackA = new vtkOBBNode *[maxStackDepth]; + OBBstackB = new vtkOBBNode *[maxStackDepth]; + OBBstackA[0] = this->Tree; + OBBstackB[0] = OBBTreeB->Tree; + depth = 1; + while( depth > 0 && returnValue > -1 ) + { // simulate recursion without overhead of real recursion. + depth--; + nodeA = OBBstackA[depth]; + nodeB = OBBstackB[depth]; + if ( !this->DisjointOBBNodes( nodeA, nodeB, XformBtoA ) ) + { + if ( nodeA->Kids == NULL ) + { + if ( nodeB->Kids == NULL ) + { // then this is a pair of intersecting leaf nodes to process + returnValue = (*function)( nodeA, nodeB, XformBtoA, data_arg ); + if ( returnValue >= 0 ) + { + count += returnValue; + } + else + { + count = returnValue; + } + } + else + { // A is a leaf, but B goes deeper. + OBBstackA[depth] = nodeA; + OBBstackB[depth] = nodeB->Kids[0]; + OBBstackA[depth+1] = nodeA; + OBBstackB[depth+1] = nodeB->Kids[1]; + depth += 2; + } + } + else + { + if ( nodeB->Kids == NULL ) + { // B is a leaf, but A goes deeper. + OBBstackB[depth] = nodeB; + OBBstackA[depth] = nodeA->Kids[0]; + OBBstackB[depth+1] = nodeB; + OBBstackA[depth+1] = nodeA->Kids[1]; + depth += 2; + } + else + { // neither A nor B are leaves. Go to the next level. + OBBstackA[depth] = nodeA->Kids[0]; + OBBstackB[depth] = nodeB->Kids[0]; + OBBstackA[depth+1] = nodeA->Kids[1]; + OBBstackB[depth+1] = nodeB->Kids[0]; + OBBstackA[depth+2] = nodeA->Kids[0]; + OBBstackB[depth+2] = nodeB->Kids[1]; + OBBstackA[depth+3] = nodeA->Kids[1]; + OBBstackB[depth+3] = nodeB->Kids[1]; + depth += 4; + } + } + } + } + // cleanup + delete OBBstackA; + delete OBBstackB; + + return( count ); + } + +void vtkOBBTree::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + if ( this->Tree ) + { + os << indent << "Tree " << this->Tree << "\n"; + } + else + { + os << indent << "Tree: (null)\n"; + } + if ( this->PointsList ) + { + os << indent << "PointsList " << this->PointsList << "\n"; + } + else + { + os << indent << "PointsList: (null)\n"; + } + if( this->InsertedPoints ) + { + os << indent << "InsertedPoints " << this->InsertedPoints << "\n"; + } + else + { + os << indent << "InsertedPoints: (null)\n"; + } + + os << indent << "OBBCount " << this->OBBCount << "\n"; + os << indent << "DeepestLevel " << this->DeepestLevel << "\n"; +} diff --git a/Graphics/vtkOBBTree.h b/Graphics/vtkOBBTree.h new file mode 100644 index 0000000..0101411 --- /dev/null +++ b/Graphics/vtkOBBTree.h @@ -0,0 +1,209 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBBTree.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOBBTree - generate oriented bounding box (OBB) tree +// .SECTION Description +// vtkOBBTree is an object to generate oriented bounding box (OBB) trees. +// An oriented bounding box is a bounding box that does not necessarily line +// up along coordinate axes. The OBB tree is a hierarchical tree structure +// of such boxes, where deeper levels of OBB confine smaller regions of space. +// +// To build the OBB, a recursive, top-down process is used. First, the root OBB +// is constructed by finding the mean and covariance matrix of the cells (and +// their points) that define the dataset. The eigenvectors of the covariance +// matrix are extracted, giving a set of three orthogonal vectors that define +// the tightest-fitting OBB. To create the two children OBB's, a split plane +// is found that (approximately) divides the number cells in half. These are +// then assigned to the children OBB's. This process then continues until +// the MaxLevel ivar limits the recursion, or no split plane can be found. +// +// A good reference for OBB-trees is Gottschalk & Manocha in Proceedings of +// Siggraph `96. + +// .SECTION Caveats +// Since this algorithms works from a list of cells, the OBB tree will only +// bound the "geometry" attached to the cells if the convex hull of the +// cells bounds the geometry. +// +// Long, skinny cells (i.e., cells with poor aspect ratio) may cause +// unsatisfactory results. This is due to the fact that this is a top-down +// implementation of the OBB tree, requiring that one or more complete cells +// are contained in each OBB. This requirement makes it hard to find good +// split planes during the recursion process. A bottom-up implementation would +// go a long way to correcting this problem. + +// .SECTION See Also +// vtkLocator vtkCellLocator vtkPointLocator + +#ifndef __vtkOBBTree_h +#define __vtkOBBTree_h + +#include "vtkCellLocator.h" + +class vtkMatrix4x4; + +// Special class defines node for the OBB tree +// +//BTX +// +class vtkOBBNode { //;prevent man page generation +public: + vtkOBBNode(); + ~vtkOBBNode(); + + double Corner[3]; //center point of this node + double Axes[3][3]; //the axes defining the OBB - ordered from long->short + vtkOBBNode *Parent; //parent node; NULL if root + vtkOBBNode **Kids; //two children of this node; NULL if leaf + vtkIdList *Cells; //list of cells in node + void DebugPrintTree( int level, double *leaf_vol, int *minCells, + int *maxCells ); +}; +//ETX +// + +class VTK_GRAPHICS_EXPORT vtkOBBTree : public vtkCellLocator +{ +public: + vtkTypeRevisionMacro(vtkOBBTree,vtkCellLocator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with automatic computation of divisions, averaging + // 25 cells per octant. + static vtkOBBTree *New(); + + // Description: + // Compute an OBB from the list of points given. Return the corner point + // and the three axes defining the orientation of the OBB. Also return + // a sorted list of relative "sizes" of axes for comparison purposes. + void ComputeOBB(vtkPoints *pts, double corner[3], double max[3], + double mid[3], double min[3], double size[3]); + + // Description: + // Compute an OBB for the input dataset using the cells in the data. + // Return the corner point and the three axes defining the orientation + // of the OBB. Also return a sorted list of relative "sizes" of axes for + // comparison purposes. + void ComputeOBB(vtkDataSet *input, double corner[3], double max[3], + double mid[3], double min[3], double size[3]); + + // Description: + // Determine whether a point is inside or outside the data used to build + // this OBB tree. The data must be a closed surface vtkPolyData data set. + // The return value is +1 if outside, -1 if inside, and 0 if undecided. + int InsideOrOutside(const double point[3]); + + // Description: + // Take the passed line segment and intersect it with the data set. + // This method assumes that the data set is a vtkPolyData that describes + // a closed surface, and the intersection points that are returned in + // 'points' alternate between entrance points and exit points. + // The return value of the function is 0 if no intersections were found, + // -1 if point 'a0' lies inside the closed surface, or +1 if point 'a0' + // lies outside the closed surface. + // Either 'points' or 'cellIds' can be set to NULL if you don't want + // to receive that information. + int IntersectWithLine(const double a0[3], const double a1[3], + vtkPoints *points, vtkIdList *cellIds); + + // Description: + // Return the first intersection of the specified line segment with + // the OBB tree, as well as information about the cell which the + // line segment intersected. + int IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId); + + int IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId); + + int IntersectWithLine(double a0[3], double a1[3], double tol, + double& t, double x[3], double pcoords[3], + int &subId, vtkIdType &cellId, vtkGenericCell *cell); + + //BTX + + // Description: + // Returns true if nodeB and nodeA are disjoint after optional + // transformation of nodeB with matrix XformBtoA + int DisjointOBBNodes( vtkOBBNode *nodeA, vtkOBBNode *nodeB, + vtkMatrix4x4 *XformBtoA ); + + // Description: + // Returns true if line intersects node. + int LineIntersectsNode( vtkOBBNode *pA, double b0[3], double b1[3] ); + + // Description: + // Returns true if triangle (optionally transformed) intersects node. + int TriangleIntersectsNode( vtkOBBNode *pA, + double p0[3], double p1[3], + double p2[3], vtkMatrix4x4 *XformBtoA ); + + // Description: + // For each intersecting leaf node pair, call function. + // OBBTreeB is optionally transformed by XformBtoA before testing. + int IntersectWithOBBTree( vtkOBBTree *OBBTreeB, vtkMatrix4x4 *XformBtoA, + int(*function)( vtkOBBNode *nodeA, + vtkOBBNode *nodeB, + vtkMatrix4x4 *Xform, + void *arg ), + void *data_arg ); + //ETX + + // Description: + // Satisfy locator's abstract interface, see vtkLocator. + void FreeSearchStructure(); + void BuildLocator(); + + // Description: + // Create polygonal representation for OBB tree at specified level. If + // level < 0, then the leaf OBB nodes will be gathered. The aspect ratio (ar) + // and line diameter (d) are used to control the building of the + // representation. If a OBB node edge ratio's are greater than ar, then the + // dimension of the OBB is collapsed (OBB->plane->line). A "line" OBB will be + // represented either as two crossed polygons, or as a line, depending on + // the relative diameter of the OBB compared to the diameter (d). + void GenerateRepresentation(int level, vtkPolyData *pd); + + //BTX +protected: + vtkOBBTree(); + ~vtkOBBTree(); + + // Compute an OBB from the list of cells given. This used to be + // public but should not have been. A public call has been added + // so that the functionality can be accessed. + void ComputeOBB(vtkIdList *cells, double corner[3], double max[3], + double mid[3], double min[3], double size[3]); + + vtkOBBNode *Tree; + void BuildTree(vtkIdList *cells, vtkOBBNode *parent, int level); + vtkPoints *PointsList; + int *InsertedPoints; + int OBBCount; + int DeepestLevel; + + void DeleteTree(vtkOBBNode *OBBptr); + void GeneratePolygons(vtkOBBNode *OBBptr, int level, int repLevel, + vtkPoints* pts, vtkCellArray *polys); + + //ETX +private: + vtkOBBTree(const vtkOBBTree&); // Not implemented. + void operator=(const vtkOBBTree&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkOutlineCornerFilter.cxx b/Graphics/vtkOutlineCornerFilter.cxx new file mode 100644 index 0000000..db50913 --- /dev/null +++ b/Graphics/vtkOutlineCornerFilter.cxx @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineCornerFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOutlineCornerFilter.h" + +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineCornerSource.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkOutlineCornerFilter, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkOutlineCornerFilter); + +vtkOutlineCornerFilter::vtkOutlineCornerFilter () +{ + this->CornerFactor = 0.2; + this->OutlineCornerSource = vtkOutlineCornerSource::New(); +} + +vtkOutlineCornerFilter::~vtkOutlineCornerFilter () +{ + if (this->OutlineCornerSource != NULL) + { + this->OutlineCornerSource->Delete (); + this->OutlineCornerSource = NULL; + } +} + +int vtkOutlineCornerFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<< "Creating dataset outline"); + + // + // Let OutlineCornerSource do all the work + // + this->OutlineCornerSource->SetBounds(input->GetBounds()); + this->OutlineCornerSource->SetCornerFactor(this->GetCornerFactor()); + this->OutlineCornerSource->Update(); + + output->CopyStructure(this->OutlineCornerSource->GetOutput()); + + return 1; +} + +int vtkOutlineCornerFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkOutlineCornerFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "CornerFactor: " << this->CornerFactor << "\n"; +} diff --git a/Graphics/vtkOutlineCornerFilter.h b/Graphics/vtkOutlineCornerFilter.h new file mode 100644 index 0000000..1a6d3a1 --- /dev/null +++ b/Graphics/vtkOutlineCornerFilter.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineCornerFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOutlineCornerFilter - create wireframe outline corners for arbitrary data set +// .SECTION Description +// vtkOutlineCornerFilter is a filter that generates wireframe outline corners of any +// data set. The outline consists of the eight corners of the dataset +// bounding box. + +#ifndef __vtkOutlineCornerFilter_h +#define __vtkOutlineCornerFilter_h + +#include "vtkPolyDataAlgorithm.h" +class vtkOutlineCornerSource; + +class VTK_GRAPHICS_EXPORT vtkOutlineCornerFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkOutlineCornerFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct outline corner filter with default corner factor = 0.2 + static vtkOutlineCornerFilter *New(); + + // Description: + // Set/Get the factor that controls the relative size of the corners + // to the length of the corresponding bounds + vtkSetClampMacro(CornerFactor, double, 0.001, 0.5); + vtkGetMacro(CornerFactor, double); + +protected: + vtkOutlineCornerFilter(); + ~vtkOutlineCornerFilter(); + + vtkOutlineCornerSource *OutlineCornerSource; + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + double CornerFactor; +private: + vtkOutlineCornerFilter(const vtkOutlineCornerFilter&); // Not implemented. + void operator=(const vtkOutlineCornerFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkOutlineCornerSource.cxx b/Graphics/vtkOutlineCornerSource.cxx new file mode 100644 index 0000000..ea467b4 --- /dev/null +++ b/Graphics/vtkOutlineCornerSource.cxx @@ -0,0 +1,118 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineCornerSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOutlineCornerSource.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkOutlineCornerSource, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkOutlineCornerSource); + +//---------------------------------------------------------------------------- +vtkOutlineCornerSource::vtkOutlineCornerSource() + : vtkOutlineSource() +{ + this->CornerFactor = 0.2; +} + +//---------------------------------------------------------------------------- +int vtkOutlineCornerSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + double *bounds; + double inner_bounds[6]; + + int i, j, k; + + // Initialize + double delta; + + bounds = this->Bounds; + for (i = 0; i < 3; i++) + { + delta = (bounds[2*i + 1] - bounds[2*i]) * this->CornerFactor; + inner_bounds[2*i] = bounds[2*i] + delta; + inner_bounds[2*i + 1] = bounds[2*i + 1] - delta; + } + + // Allocate storage and create outline + vtkPoints *newPts; + vtkCellArray *newLines; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + newPts = vtkPoints::New(); + newPts->Allocate(32); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(24,2)); + + double x[3]; + vtkIdType pts[2]; + + int pid = 0; + + // 32 points and 24 lines + for (i = 0; i <= 1; i++) + { + for (j = 2; j <= 3; j++) + { + for (k = 4; k <= 5; k++) + { + pts[0] = pid; + x[0] = bounds[i]; x[1] = bounds[j]; x[2] = bounds[k]; + newPts->InsertPoint(pid++, x); + + pts[1] = pid; + x[0] = inner_bounds[i]; x[1] = bounds[j]; x[2] = bounds[k]; + newPts->InsertPoint(pid++, x); + newLines->InsertNextCell(2,pts); + + pts[1] = pid; + x[0] = bounds[i]; x[1] = inner_bounds[j]; x[2] = bounds[k]; + newPts->InsertPoint(pid++, x); + newLines->InsertNextCell(2,pts); + + pts[1] = pid; + x[0] = bounds[i]; x[1] = bounds[j]; x[2] = inner_bounds[k]; + newPts->InsertPoint(pid++, x); + newLines->InsertNextCell(2,pts); + } + } + } + + // Update selves and release memory + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkOutlineCornerSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "CornerFactor: " << this->CornerFactor << "\n"; +} diff --git a/Graphics/vtkOutlineCornerSource.h b/Graphics/vtkOutlineCornerSource.h new file mode 100644 index 0000000..534dd0a --- /dev/null +++ b/Graphics/vtkOutlineCornerSource.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineCornerSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOutlineCornerSource - create wireframe outline corners around bounding box +// .SECTION Description +// vtkOutlineCornerSource creates wireframe outline corners around a user-specified +// bounding box. + +#ifndef __vtkOutlineCornerSource_h +#define __vtkOutlineCornerSource_h + +#include "vtkOutlineSource.h" + +class VTK_GRAPHICS_EXPORT vtkOutlineCornerSource : public vtkOutlineSource +{ +public: + vtkTypeRevisionMacro(vtkOutlineCornerSource,vtkOutlineSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct outline corner source with default corner factor = 0.2 + static vtkOutlineCornerSource *New(); + + // Description: + // Set/Get the factor that controls the relative size of the corners + // to the length of the corresponding bounds + vtkSetClampMacro(CornerFactor, double, 0.001, 0.5); + vtkGetMacro(CornerFactor, double); + +protected: + vtkOutlineCornerSource(); + ~vtkOutlineCornerSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double CornerFactor; +private: + vtkOutlineCornerSource(const vtkOutlineCornerSource&); // Not implemented. + void operator=(const vtkOutlineCornerSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkOutlineFilter.cxx b/Graphics/vtkOutlineFilter.cxx new file mode 100644 index 0000000..d640ee3 --- /dev/null +++ b/Graphics/vtkOutlineFilter.cxx @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOutlineFilter.h" + +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineSource.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkOutlineFilter, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkOutlineFilter); + +vtkOutlineFilter::vtkOutlineFilter () +{ + this->OutlineSource = vtkOutlineSource::New(); +} + +vtkOutlineFilter::~vtkOutlineFilter () +{ + if (this->OutlineSource != NULL) + { + this->OutlineSource->Delete (); + this->OutlineSource = NULL; + } +} + +int vtkOutlineFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<< "Creating dataset outline"); + + // + // Let OutlineSource do all the work + // + + this->OutlineSource->SetBounds(input->GetBounds()); + this->OutlineSource->Update(); + + output->CopyStructure(this->OutlineSource->GetOutput()); + + return 1; +} + +int vtkOutlineFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} diff --git a/Graphics/vtkOutlineFilter.h b/Graphics/vtkOutlineFilter.h new file mode 100644 index 0000000..6696880 --- /dev/null +++ b/Graphics/vtkOutlineFilter.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOutlineFilter - create wireframe outline for arbitrary data set +// .SECTION Description +// vtkOutlineFilter is a filter that generates a wireframe outline of any +// data set. The outline consists of the twelve edges of the dataset +// bounding box. + +#ifndef __vtkOutlineFilter_h +#define __vtkOutlineFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkOutlineSource; + +class VTK_GRAPHICS_EXPORT vtkOutlineFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkOutlineFilter *New(); + vtkTypeRevisionMacro(vtkOutlineFilter,vtkPolyDataAlgorithm); + +protected: + vtkOutlineFilter(); + ~vtkOutlineFilter(); + + vtkOutlineSource *OutlineSource; + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkOutlineFilter(const vtkOutlineFilter&); // Not implemented. + void operator=(const vtkOutlineFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkOutlineSource.cxx b/Graphics/vtkOutlineSource.cxx new file mode 100644 index 0000000..ca67c33 --- /dev/null +++ b/Graphics/vtkOutlineSource.cxx @@ -0,0 +1,189 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOutlineSource.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkOutlineSource, "$Revision: 1.35 $"); +vtkStandardNewMacro(vtkOutlineSource); + +//---------------------------------------------------------------------------- +vtkOutlineSource::vtkOutlineSource() +{ + this->BoxType = VTK_BOX_TYPE_AXIS_ALIGNED; + for (int i=0; i<3; i++) + { + this->Bounds[2*i] = -1.0; + this->Bounds[2*i+1] = 1.0; + } + + // Sensible initial values + this->Corners[0] = 0.0; + this->Corners[1] = 0.0; + this->Corners[2] = 0.0; + this->Corners[3] = 1.0; + this->Corners[4] = 0.0; + this->Corners[5] = 0.0; + this->Corners[6] = 0.0; + this->Corners[7] = 1.0; + this->Corners[8] = 0.0; + this->Corners[9] = 1.0; + this->Corners[10] = 1.0; + this->Corners[11] = 0.0; + this->Corners[12] = 0.0; + this->Corners[13] = 0.0; + this->Corners[14] = 1.0; + this->Corners[15] = 1.0; + this->Corners[16] = 0.0; + this->Corners[17] = 1.0; + this->Corners[18] = 0.0; + this->Corners[19] = 1.0; + this->Corners[20] = 1.0; + this->Corners[21] = 1.0; + this->Corners[22] = 1.0; + this->Corners[23] = 1.0; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +int vtkOutlineSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double *bounds; + double x[3]; + vtkIdType pts[2]; + vtkPoints *newPts; + vtkCellArray *newLines; + + // + // Initialize + // + bounds = this->Bounds; + // + // Allocate storage and create outline + // + newPts = vtkPoints::New(); + newPts->Allocate(8); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(12,2)); + + if (this->BoxType==VTK_BOX_TYPE_AXIS_ALIGNED) + { + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[4]; + newPts->InsertPoint(0,x); + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[4]; + newPts->InsertPoint(1,x); + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[4]; + newPts->InsertPoint(2,x); + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[4]; + newPts->InsertPoint(3,x); + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[5]; + newPts->InsertPoint(4,x); + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[5]; + newPts->InsertPoint(5,x); + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[5]; + newPts->InsertPoint(6,x); + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[5]; + newPts->InsertPoint(7,x); + } + else //VTK_BOX_TYPE_ORIENTED + { + newPts->InsertPoint(0, &Corners[0]); + newPts->InsertPoint(1, &Corners[3]); + newPts->InsertPoint(2, &Corners[6]); + newPts->InsertPoint(3, &Corners[9]); + newPts->InsertPoint(4, &Corners[12]); + newPts->InsertPoint(5, &Corners[15]); + newPts->InsertPoint(6, &Corners[18]); + newPts->InsertPoint(7, &Corners[21]); + } + + pts[0] = 0; pts[1] = 1; + newLines->InsertNextCell(2,pts); + pts[0] = 2; pts[1] = 3; + newLines->InsertNextCell(2,pts); + pts[0] = 4; pts[1] = 5; + newLines->InsertNextCell(2,pts); + pts[0] = 6; pts[1] = 7; + newLines->InsertNextCell(2,pts); + pts[0] = 0; pts[1] = 2; + newLines->InsertNextCell(2,pts); + pts[0] = 1; pts[1] = 3; + newLines->InsertNextCell(2,pts); + pts[0] = 4; pts[1] = 6; + newLines->InsertNextCell(2,pts); + pts[0] = 5; pts[1] = 7; + newLines->InsertNextCell(2,pts); + pts[0] = 0; pts[1] = 4; + newLines->InsertNextCell(2,pts); + pts[0] = 1; pts[1] = 5; + newLines->InsertNextCell(2,pts); + pts[0] = 2; pts[1] = 6; + newLines->InsertNextCell(2,pts); + pts[0] = 3; pts[1] = 7; + newLines->InsertNextCell(2,pts); + + // Update selves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkOutlineSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Box Type: "; + if ( this->BoxType == VTK_BOX_TYPE_AXIS_ALIGNED ) + { + os << "Axis Aligned\n"; + os << indent << "Bounds: " + << "(" << this->Bounds[0] << ", " << this->Bounds[1] << ") " + << "(" << this->Bounds[2] << ", " << this->Bounds[3] << ") " + << "(" << this->Bounds[4] << ", " << this->Bounds[5] << ")\n"; + } + else + { + os << "Corners: (\n"; + for (int i=0; i<8; i++) + { + os << "\t" << this->Corners[3*i] << ", " + << this->Corners[3*i+1] << ", " + << this->Corners[3*i+2] << "\n"; + } + os << ")\n"; + } +} diff --git a/Graphics/vtkOutlineSource.h b/Graphics/vtkOutlineSource.h new file mode 100644 index 0000000..fad0c53 --- /dev/null +++ b/Graphics/vtkOutlineSource.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutlineSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOutlineSource - create wireframe outline around bounding box +// .SECTION Description +// vtkOutlineSource creates a wireframe outline around a +// user-specified bounding box. The outline may be created aligned +// with the {x,y,z} axis - in which case it is defined by the 6 bounds +// {xmin,xmax,ymin,ymax,zmin,zmax} via SetBounds(). Alternatively, the +// box may be arbitrarily aligned, in which case it should be set via +// the SetCorners() member. + +#ifndef __vtkOutlineSource_h +#define __vtkOutlineSource_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_BOX_TYPE_AXIS_ALIGNED 0 +#define VTK_BOX_TYPE_ORIENTED 1 + +class VTK_GRAPHICS_EXPORT vtkOutlineSource : public vtkPolyDataAlgorithm +{ +public: + static vtkOutlineSource *New(); + vtkTypeRevisionMacro(vtkOutlineSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set box type to AxisAligned (default) or Oriented. + // Use the method SetBounds() with AxisAligned mode, and SetCorners() + // with Oriented mode. + vtkSetMacro(BoxType,int); + vtkGetMacro(BoxType,int); + void SetBoxTypeToAxisAligned() + {this->SetBoxType(VTK_BOX_TYPE_AXIS_ALIGNED);} + void SetBoxTypeToOriented() + {this->SetBoxType(VTK_BOX_TYPE_ORIENTED);} + + // Description: + // Specify the bounds of the box to be used in Axis Aligned mode. + vtkSetVector6Macro(Bounds,double); + vtkGetVectorMacro(Bounds,double,6); + + // Description: + // Specify the corners of the outline when in Oriented mode, the + // values are supplied as 8*3 double values The correct corner + // ordering is using {x,y,z} convention for the unit cube as follows: + // {0,0,0},{1,0,0},{0,1,0},{1,1,0},{0,0,1},{1,0,1},{0,1,1},{1,1,1}. + vtkSetVectorMacro(Corners,double,24); + vtkGetVectorMacro(Corners,double,24); + +protected: + vtkOutlineSource(); + ~vtkOutlineSource() {} + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int BoxType; + double Bounds[6]; + double Corners[24]; + +private: + vtkOutlineSource(const vtkOutlineSource&); // Not implemented. + void operator=(const vtkOutlineSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkParametricFunctionSource.cxx b/Graphics/vtkParametricFunctionSource.cxx new file mode 100644 index 0000000..848b666 --- /dev/null +++ b/Graphics/vtkParametricFunctionSource.cxx @@ -0,0 +1,681 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricFunctionSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParametricFunctionSource.h" +#include "vtkParametricFunction.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include "vtkFloatArray.h" +#include "vtkPoints.h" +#include "vtkTriangleFilter.h" +#include "vtkPolyDataNormals.h" +#include "vtkPointData.h" +#include "vtkCellArray.h" +#include "vtkPolyData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" + +#include +#include + +vtkCxxRevisionMacro(vtkParametricFunctionSource, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkParametricFunctionSource); +vtkCxxSetObjectMacro(vtkParametricFunctionSource,ParametricFunction,vtkParametricFunction); + +//---------------------------------------------------------------------------- +vtkParametricFunctionSource::vtkParametricFunctionSource() : + ParametricFunction(NULL) + , UResolution(50) + , VResolution(50) + , WResolution(50) + , GenerateTextureCoordinates(0) + , ScalarMode(vtkParametricFunctionSource::SCALAR_NONE) +{ + this->SetNumberOfInputPorts(0); +} + + +//---------------------------------------------------------------------------- +vtkParametricFunctionSource::~vtkParametricFunctionSource() +{ + this->SetParametricFunction(NULL); +} + +//---------------------------------------------------------------------------- +void vtkParametricFunctionSource::MakeTriangleStrips ( vtkCellArray * strips, + int PtsU, int PtsV ) +{ + int id1; + int id2; + + vtkDebugMacro(<< "Executing MakeTriangleStrips()"); + + for ( int i = 0; i < PtsU - 1; ++i ) + { + // Allocate space + if ( this->ParametricFunction->GetJoinV() ) + { + strips->InsertNextCell( PtsV * 2 + 2 ); + } + else + { + strips->InsertNextCell( PtsV * 2 ); + } + + // Fill the allocated space with the indexes to the points. + for ( int j = 0; j < PtsV; ++j ) + { + id1 = j + i * PtsV; + id2 = (i + 1 ) * PtsV + j; + if ( this->ParametricFunction->GetClockwiseOrdering() ) + { + strips->InsertCellPoint(id1); + strips->InsertCellPoint(id2); + } + else + { + strips->InsertCellPoint(id2); + strips->InsertCellPoint(id1); + } + } + // If necessary, connect the ends of the triangle strip. + if ( this->ParametricFunction->GetJoinV() ) + { + if ( this->ParametricFunction->GetTwistV() ) + { + id1 = (i + 1) * PtsV; + id2 = i * PtsV; + } + else + { + id1 = i * PtsV; + id2 = (i + 1) * PtsV; + } + if ( this->ParametricFunction->GetClockwiseOrdering() ) + { + strips->InsertCellPoint(id1); + strips->InsertCellPoint(id2); + } + else + { + strips->InsertCellPoint(id2); + strips->InsertCellPoint(id1); + } + } + } + // If required, connect the last triangle strip to the first by + // adding a new triangle strip and filling it with the indexes + // to the points. + if ( this->ParametricFunction->GetJoinU() ) + { + if ( this->ParametricFunction->GetJoinV() ) + { + strips->InsertNextCell( PtsV * 2 + 2 ); + } + else + { + strips->InsertNextCell( PtsV * 2 ); + } + for ( int j = 0; j < PtsV; ++j ) + { + if ( this->ParametricFunction->GetTwistU() ) + { + id1 = ( PtsU - 1 ) * PtsV + j; + id2 = PtsV - 1 - j; + } + else + { + id1 = ( PtsU - 1 ) * PtsV + j; + id2 = j; + } + if ( this->ParametricFunction->GetClockwiseOrdering() ) + { + strips->InsertCellPoint(id1); + strips->InsertCellPoint(id2); + } + else + { + strips->InsertCellPoint(id2); + strips->InsertCellPoint(id1); + } + } + + // If necessary, connect the ends of the triangle strip. + if ( this->ParametricFunction->GetJoinV() ) + { + if ( this->ParametricFunction->GetTwistU() ) + { + if ( this->ParametricFunction->GetTwistV() ) + { + id1 = PtsV - 1; + id2 = ( PtsU - 1 ) * PtsV; + } + else + { + id1 = ( PtsU - 1 ) * PtsV; + id2 = PtsV - 1; + } + } + else + { + if ( this->ParametricFunction->GetTwistV() ) + { + id1 = 0; + id2 = ( PtsU - 1 ) * PtsV; + } + else + { + id1 = ( PtsU - 1 ) * PtsV; + id2 = 0; + } + } + if ( this->ParametricFunction->GetClockwiseOrdering() ) + { + strips->InsertCellPoint(id1); + strips->InsertCellPoint(id2); + } + else + { + strips->InsertCellPoint(id2); + strips->InsertCellPoint(id1); + } + } + } + vtkDebugMacro(<< "MakeTriangleStrips() finished."); +} + +//---------------------------------------------------------------------------- +int vtkParametricFunctionSource::RequestData(vtkInformation *vtkNotUsed(info), + vtkInformationVector **vtkNotUsed(inputV), + vtkInformationVector *output) +{ + vtkDebugMacro(<< "Executing"); + + // Check that a parametric function has been defined + if ( !this->ParametricFunction ) + { + vtkErrorMacro(<<"Parametric function not defined"); + return 1; + } + + switch ( this->ParametricFunction->GetDimension() ) + { + case 1: + this->Produce1DOutput(output); + break; + case 2: + this->Produce2DOutput(output); + break; + default: + vtkErrorMacro("Functions of dimension " + << this->ParametricFunction->GetDimension() + << " are not supported."); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkParametricFunctionSource::Produce1DOutput(vtkInformationVector *output) +{ + vtkIdType numPts = this->UResolution + 1; + vtkCellArray *lines = vtkCellArray::New(); + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(numPts); + vtkIdType i; + double x[3], Du[3], t[3]; + + lines->Allocate(lines->EstimateSize(1,numPts)); + lines->InsertNextCell(numPts); + + // Insert points and cell points + for (i=0; iUResolution; + this->ParametricFunction->Evaluate(t,x,Du); + pts->SetPoint(i,x); + lines->InsertCellPoint(i); + } + + vtkInformation *outInfo = output->GetInformationObject(0); + vtkPolyData *outData = static_cast + (outInfo->Get( vtkDataObject::DATA_OBJECT() )); + outData->SetPoints(pts); + outData->SetLines(lines); + + pts->Delete(); + lines->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkParametricFunctionSource::Produce2DOutput(vtkInformationVector *output) +{ + // Used to hold the surface + vtkPolyData * pd = vtkPolyData::New(); + + // Adjust so the range this->MinimumU ... this->ParametricFunction->GetMaximumU(), this->MinimumV + // ... this->ParametricFunction->GetMaximumV() is included in the triangulation. + double MaxU = this->ParametricFunction->GetMaximumU() + + (this->ParametricFunction->GetMaximumU() - this->ParametricFunction->GetMinimumU()) / + (this->UResolution-1); + int PtsU = this->UResolution; + double MaxV = this->ParametricFunction->GetMaximumV() + + (this->ParametricFunction->GetMaximumV() - this->ParametricFunction->GetMinimumV()) / + (this->VResolution-1); + int PtsV = this->VResolution; + int totPts = PtsU * PtsV; + + // Scalars associated with each point + vtkFloatArray * sval = vtkFloatArray::New(); + sval->SetNumberOfTuples( totPts ); + + // The normals to the surface + vtkFloatArray * nval = vtkFloatArray::New(); + nval->SetNumberOfComponents(3); + nval->SetNumberOfTuples(totPts); + + // Texture coordinates + double tc[2]; + vtkFloatArray *newTCoords; + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*totPts); + + vtkPoints * points = vtkPoints::New(); + points->SetNumberOfPoints( totPts ); + + double uStep = ( MaxU - this->ParametricFunction->GetMinimumU() ) / PtsU; + double vStep = ( MaxV - this->ParametricFunction->GetMinimumV() ) / PtsV; + + // Find the mid points of the (u,v) map. + double u0 = this->ParametricFunction->GetMinimumU(); + double u_mp = (MaxU - u0)/2.0 + u0 - uStep; + while ( u0 < u_mp ) + { + u0 += uStep; + } + + double v0 = this->ParametricFunction->GetMinimumV(); + double v_mp = (MaxV - v0)/2.0 + v0 - vStep; + while ( v0 < v_mp ) + { + v0 += vStep; + } + u_mp += uStep; + v_mp += vStep; + + // At this point (u_mp, v_mp) is the midpoint of the (u,v) map and (u0,v0) + // corresponds to the nearest grid point to the midpoint of the (u,v) map. + // + double rel_u = 0; // will be u - u_mp + double rel_v = 0; // will be v - v_mp + + int k = 0; + double uv[3]; + uv[0] = this->ParametricFunction->GetMinimumU() - uStep; + + float MaxI = PtsU - 1; + float MaxJ = PtsV - 1; + + for ( int i = 0; i < PtsU; ++i ) + { + uv[0] += uStep; + uv[1] = this->ParametricFunction->GetMinimumV() - vStep; + + if ( this->GenerateTextureCoordinates != 0 ) + { + tc[0] = i/MaxI; + } + + for ( int j = 0; j < PtsV; ++j ) + { + uv[1] += vStep; + + if ( this->GenerateTextureCoordinates != 0 ) + { + tc[1] = 1.0 - j/MaxJ; + newTCoords->InsertNextTuple(tc); + } + + // The point + double Pt[3]; + // Partial derivative at Pt with respect to u,v,w. + double Du[9]; + // Partial derivative at Pt with respect to v. + double *Dv = Du+3; + + // Calculate fn(u)->(Pt,Du). + this->ParametricFunction->Evaluate(uv,Pt,Du); + + // Insert the points and scalar. + points->InsertPoint(k, Pt[0], Pt[1], Pt[2]); + double scalar; + + if ( this->ScalarMode != SCALAR_NONE ) + { + switch ( this->ScalarMode ) + { + case SCALAR_U: + scalar = uv[0]; + break; + case SCALAR_V: + scalar = uv[1]; + break; + case SCALAR_U0: + scalar = uv[0] == u0 ? 1 : 0; + break; + case SCALAR_V0: + scalar = uv[1] == v0 ? 1 : 0; + break; + case SCALAR_U0V0: + scalar = 0; + // u0, v0 + if ( uv[0] == u0 && uv[1] == v0 ) + { + scalar = 3; + } + else + { + // u0 line + if ( uv[0] == u0 ) + { + scalar = 1; + } + else + { + // v0 line + if ( uv[1] == v0 ) scalar = 2; + } + } + break; + case SCALAR_MODULUS: + rel_u = uv[0] - u_mp; + rel_v = uv[1] - v_mp; + scalar = sqrt(rel_u * rel_u + rel_v * rel_v); + break; + case SCALAR_PHASE: + rel_u = uv[0] - u_mp; + rel_v = uv[1] - v_mp; + if ( rel_v == 0 && rel_u == 0 ) + { + scalar = 0; + } + else + { + scalar = vtkMath::RadiansToDegrees() * atan2(rel_v,rel_u); + if ( scalar < 0 ) scalar += 360; + } + break; + case SCALAR_QUADRANT: + if ( uv[0] >= u0 && uv[1] >= v0 ) + { + scalar = 1; + break; + } + if ( uv[0] < u0 && uv[1] >= v0 ) + { + scalar = 2; + break; + } + if ( uv[0] < u0 && uv[1] < v0 ) + { + scalar = 3; + } + else + { + scalar = 4; + } + break; + case SCALAR_X: + scalar = Pt[0]; + break; + case SCALAR_Y: + scalar = Pt[1]; + break; + case SCALAR_Z: + scalar = Pt[2]; + break; + case SCALAR_DISTANCE: + scalar = sqrt(Pt[0]*Pt[0] + Pt[1]*Pt[1] + Pt[2]*Pt[2]); + break; + case SCALAR_FUNCTION_DEFINED: + scalar = this->ParametricFunction->EvaluateScalar(uv, Pt, Du); + break; + case SCALAR_NONE: + default: + scalar = 0; + } + sval->SetValue(k, scalar); + } + + // Calculate the normal. + if ( this->ParametricFunction->GetDerivativesAvailable() ) + { + double n[3]; + vtkMath::Cross(Du,Dv,n); + vtkMath::Normalize(n); + nval->SetTuple3(k, n[0], n[1], n[2]); + } + + ++k; + } + } + + // Make the triangle strips + vtkCellArray * strips = vtkCellArray::New(); + // This is now a list of ID's defining the triangles. + this->MakeTriangleStrips ( strips, PtsU, PtsV ); + + pd->SetPoints( points ); + pd->SetVerts( strips ); + pd->SetStrips( strips ); + if ( this->ScalarMode != SCALAR_NONE ) + { + pd->GetPointData()->SetScalars( sval ); + } + + if ( this->ParametricFunction->GetDerivativesAvailable() ) + { + pd->GetPointData()->SetNormals( nval ); + } + pd->Modified(); + + vtkTriangleFilter * tri = vtkTriangleFilter::New(); + vtkPolyDataNormals * norm = vtkPolyDataNormals::New(); + if ( this->ParametricFunction->GetDerivativesAvailable() ) + { + //Generate polygons from the triangle strips + tri->SetInput(pd); + } + else + { + // Calculate Normals + norm->SetInput(pd); + // Generate polygons from the triangle strips + tri->SetInput(norm->GetOutput()); + } + tri->PassLinesOn(); + tri->PassVertsOff(); + tri->Update(); + + vtkInformation *outInfo = output->GetInformationObject(0); + vtkPolyData *outData = static_cast(outInfo->Get( vtkDataObject::DATA_OBJECT() )); + outData->DeepCopy(tri->GetOutput()); + + if ( this->GenerateTextureCoordinates != 0 ) + { + outData->GetPointData()->SetTCoords( newTCoords ); + } + + // Were done, clean up. + points->Delete(); + sval->Delete(); + nval->Delete(); + newTCoords->Delete(); + strips->Delete(); + pd->Delete(); + tri->Delete(); + norm->Delete(); +} + +/* +//---------------------------------------------------------------------------- +void vtkParametricFunctionSource::GetAllParametricTriangulatorParameters ( + int & numberOfUPoints, + int & numberOfVPoints, + double & minimumU, + double & maximumU, + double & minimumV, + double & maximumV, + int & joinU, + int & joinV, + int & twistU, + int & twistV, + int & clockwiseOrdering, + int & scalarMode) +{ + uResolution = this->UResolution; + vResolution = this->VResolution; + minimumU = this->MinimumU; + maximumU = this->ParametricFunction->GetMaximumU(); + minimumV = this->ParametricFunction->GetMinimumV(); + maximumV = this->ParametricFunction->GetMaximumV(); + joinU = this->ParametricFunction->GetJoinU(); + joinV = this->ParametricFunction->GetJoinV; + twistU = this->ParametricFunction->GetTwistU(); + twistV = this->ParametricFunction->GetTwistV(); + clockwiseOrdering = this->ParametricFunction->GetClockwiseOrdering(); + scalarMode = this->ScalarMode; +} + +//---------------------------------------------------------------------------- +void vtkParametricFunctionSource::SetAllParametricTriangulatorParameters ( + int uResolution, + int vResolution, + double minimumU, + double maximumU, + double minimumV, + double maximumV, + int joinU, + int joinV, + int twistU, + int twistV, + int ParametricFunction->GetclockwiseOrdering(), + int scalarMode) +{ + this->UResolution = uResolution; + this->VResolution = vResolution; + this->ParametricFunction->SetMinimumU( minimumU ); + this->ParametricFunction->SetMaximumU( maximumU ); + this->ParametricFunction->SetMinimumV( minimumV ); + this->ParametricFunction->SetMaximumV( maximumV ); + this->ParametricFunction->SetJoinU( joinU ); + this->ParametricFunction->SetJoinV( joinV ); + this->ParametricFunction->SetTwistU( twistU ); + this->ParametricFunction->SetTwistV( twistV ); + this->ParametricFunction->SetClockwiseOrdering( clockwiseOrdering ); + this->ScalarMode = scalarMode; + if ( ScalarMode < SCALAR_NONE || ScalarMode > SCALAR_USER_DEFINED ) + { + this->ScalarMode = SCALAR_NONE; + } + this->Modified(); +} +*/ + +//---------------------------------------------------------------------------- +unsigned long vtkParametricFunctionSource::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long funcMTime; + + if ( this->ParametricFunction != NULL ) + { + funcMTime = this->ParametricFunction->GetMTime(); + mTime = ( funcMTime > mTime ? funcMTime : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +void vtkParametricFunctionSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "U Resolution: " << this->UResolution << "\n"; + os << indent << "V Resolution: " << this->VResolution << "\n"; + os << indent << "W Resolution: " << this->WResolution << "\n"; + + if ( this->ParametricFunction ) + { + os << indent << "Parametric Function: " << this->ParametricFunction << "\n"; + } + else + { + os << indent << "No Parametric function defined\n"; + } + + vtkstd::string s; + switch ( this->ScalarMode ) + { + case SCALAR_NONE: + s = "SCALAR_NONE"; + break; + case SCALAR_U: + s = "SCALAR_U"; + break; + case SCALAR_V: + s = "SCALAR_V"; + break; + case SCALAR_U0: + s = "SCALAR_U0"; + break; + case SCALAR_V0: + s = "SCALAR_V0"; + break; + case SCALAR_U0V0: + s = "SCALAR_U0V0"; + break; + case SCALAR_MODULUS: + s = "SCALAR_MODULUS"; + break; + case SCALAR_PHASE: + s = "SCALAR_PHASE"; + break; + case SCALAR_QUADRANT: + s = "SCALAR_QUADRANT"; + break; + case SCALAR_X: + s = "SCALAR_X"; + break; + case SCALAR_Y: + s = "SCALAR_Y"; + break; + case SCALAR_Z: + s = "SCALAR_Z"; + break; + case SCALAR_DISTANCE: + s = "SCALAR_DISTANCE"; + break; + case SCALAR_FUNCTION_DEFINED: + s = "SCALAR_FUNCTION_DEFINED"; + break; + default: + s = "Unknown scalar mode."; + } + os << indent << "Scalar Mode: " << s.c_str() << "\n"; + os << indent << "GenerateTextureCoordinates:" << (this->GenerateTextureCoordinates ? "On" : "Off" ) << "\n"; + +} diff --git a/Graphics/vtkParametricFunctionSource.h b/Graphics/vtkParametricFunctionSource.h new file mode 100644 index 0000000..d4eb6ae --- /dev/null +++ b/Graphics/vtkParametricFunctionSource.h @@ -0,0 +1,202 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParametricFunctionSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParametricFunctionSource - tessellate parametric functions +// .SECTION Description +// This class tessellates parametric functions. The user must specify how +// many points in the parametric coordinate directions are required (i.e., +// the resolution), and the mode to use to generate scalars. +// +// .SECTION Thanks +// Andrew Maclean a.maclean@cas.edu.au for creating and contributing the +// class. +// +// .SECTION See Also +// vtkParametricFunction +// +// Implementation of parametrics for 1D lines: +// vtkParametricSpline +// +// Subclasses of vtkParametricFunction implementing non-orentable surfaces: +// vtkParametricBoy vtkParametricCrossCap vtkParametricFigure8Klein +// vtkParametricKlein vtkParametricMobius vtkParametricRoman +// +// Subclasses of vtkParametricFunction implementing orientable surfaces: +// vtkParametricConicSpiral vtkParametricDini vtkParametricEllipsoid +// vtkParametricEnneper vtkParametricRandomHills vtkParametricSuperEllipsoid +// vtkParametricSuperToroid vtkParametricTorus +// +#ifndef __vtkParametricFunctionSource_h +#define __vtkParametricFunctionSource_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkParametricFunction; + +class VTK_GRAPHICS_EXPORT vtkParametricFunctionSource : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkParametricFunctionSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a new instance with (50,50,50) points in the (u-v-w) directions. + static vtkParametricFunctionSource *New(); + + // Description: + // Specify the parametric function to use to generate the tessellation. + virtual void SetParametricFunction(vtkParametricFunction*); + vtkGetObjectMacro(ParametricFunction,vtkParametricFunction); + + // Description: + // Set/Get the number of subdivisions / tessellations in the u parametric + // direction. Note that the number of tessellant points in the u + // direction is the UResolution + 1. + vtkSetMacro(UResolution,int); + vtkGetMacro(UResolution,int); + + // Description: + // Set/Get the number of subdivisions / tessellations in the v parametric + // direction. Note that the number of tessellant points in the v + // direction is the VResolution + 1. + vtkSetMacro(VResolution,int); + vtkGetMacro(VResolution,int); + + // Description: + // Set/Get the number of subdivisions / tessellations in the w parametric + // direction. Note that the number of tessellant points in the w + // direction is the WResolution + 1. + vtkSetMacro(WResolution,int); + vtkGetMacro(WResolution,int); + + // Description: + // Set/Get the generation of texture coordinates. This is off by + // default. + // Note that this is only applicable to parametric surfaces + // whose parametric dimension is 2. + // Note that texturing may fail in some cases. + vtkBooleanMacro(GenerateTextureCoordinates,int); + vtkSetMacro(GenerateTextureCoordinates,int); + vtkGetMacro(GenerateTextureCoordinates,int); + + //BTX + // Description: + // Enumerate the supported scalar generation modes. + //

+  // SCALAR_NONE, (default) scalars are not generated.
+  // SCALAR_U, the scalar is set to the u-value. 
+  // SCALAR_V, the scalar is set to the v-value.
+  // SCALAR_U0, the scalar is set to 1 if u = (u_max - u_min)/2 = u_avg, 0 otherwise.
+  // SCALAR_V0, the scalar is set to 1 if v = (v_max - v_min)/2 = v_avg, 0 otherwise.
+  // SCALAR_U0V0, the scalar is 
+  //   set to 1 if u == u_avg, 2 if v == v_avg, 3 if u = u_avg && v = v_avg, 0 otherwise.
+  // SCALAR_MODULUS, the scalar is set to (sqrt(u*u+v*v)), this is measured relative to (u_avg,v_avg).
+  // SCALAR_PHASE, the scalar is set to (atan2(v,u)) (in degrees, 0 to 360), this is measured relative to (u_avg,v_avg).
+  // SCALAR_QUADRANT, the scalar is set to 1, 2, 3 or 4 
+  //   depending upon the quadrant of the point (u,v).
+  // SCALAR_X, the scalar is set to the x-value. 
+  // SCALAR_Y, the scalar is set to the y-value. 
+  // SCALAR_Z, the scalar is set to the z-value. 
+  // SCALAR_DISTANCE, the scalar is set to (sqrt(x*x+y*y+z*z)). I.e. distance from the origin.
+  // SCALAR_USER_DEFINED, the scalar is set to the value returned from EvaluateScalar().
+  // 
+ enum SCALAR_MODE { SCALAR_NONE = 0, + SCALAR_U, SCALAR_V, + SCALAR_U0, SCALAR_V0, SCALAR_U0V0, + SCALAR_MODULUS, SCALAR_PHASE, SCALAR_QUADRANT, + SCALAR_X, SCALAR_Y, SCALAR_Z, SCALAR_DISTANCE, + SCALAR_FUNCTION_DEFINED }; + //ETX + + // Description: + // Get/Set the mode used for the scalar data. The options are: + // SCALAR_NONE, (default) scalars are not generated. + // SCALAR_U, the scalar is set to the u-value. + // SCALAR_V, the scalar is set to the v-value. + // SCALAR_U0, the scalar is set to 1 if u = (u_max - u_min)/2 = u_avg, 0 otherwise. + // SCALAR_V0, the scalar is set to 1 if v = (v_max - v_min)/2 = v_avg, 0 otherwise. + // SCALAR_U0V0, the scalar is + // set to 1 if u == u_avg, 2 if v == v_avg, 3 if u = u_avg && v = v_avg, 0 otherwise. + // SCALAR_MODULUS, the scalar is set to (sqrt(u*u+v*v)), this is measured relative to (u_avg,v_avg). + // SCALAR_PHASE, the scalar is set to (atan2(v,u)) (in degrees, 0 to 360), this is measured relative to (u_avg,v_avg). + // SCALAR_QUADRANT, the scalar is set to 1, 2, 3 or 4 + // depending upon the quadrant of the point (u,v). + // SCALAR_X, the scalar is set to the x-value. + // SCALAR_Y, the scalar is set to the y-value. + // SCALAR_Z, the scalar is set to the z-value. + // SCALAR_DISTANCE, the scalar is set to (sqrt(x*x+y*y+z*z)). I.e. distance from the origin. + // SCALAR_FUNCTION_DEFINED, the scalar is set to the value returned from EvaluateScalar(). + vtkSetClampMacro(ScalarMode, int, SCALAR_NONE, SCALAR_FUNCTION_DEFINED); + vtkGetMacro(ScalarMode, int); + void SetScalarModeToNone( void ) {this->SetScalarMode(SCALAR_NONE);} + void SetScalarModeToU( void ) {this->SetScalarMode(SCALAR_U);} + void SetScalarModeToV( void ) {this->SetScalarMode(SCALAR_V);} + void SetScalarModeToU0( void ) {this->SetScalarMode(SCALAR_U0);} + void SetScalarModeToV0( void ) {this->SetScalarMode(SCALAR_V0);} + void SetScalarModeToU0V0( void ) {this->SetScalarMode(SCALAR_U0V0);} + void SetScalarModeToModulus( void ) {this->SetScalarMode(SCALAR_MODULUS);} + void SetScalarModeToPhase( void ) {this->SetScalarMode(SCALAR_PHASE);} + void SetScalarModeToQuadrant( void ) {this->SetScalarMode(SCALAR_QUADRANT);} + void SetScalarModeToX( void ) {this->SetScalarMode(SCALAR_X);} + void SetScalarModeToY( void ) {this->SetScalarMode(SCALAR_Y);} + void SetScalarModeToZ( void ) {this->SetScalarMode(SCALAR_Z);} + void SetScalarModeToDistance( void ) {this->SetScalarMode(SCALAR_DISTANCE);} + void SetScalarModeToFunctionDefined( void ) {this->SetScalarMode(SCALAR_FUNCTION_DEFINED);} + + // Description: + // Return the MTime also considering the parametric function. + unsigned long GetMTime(); + +protected: + vtkParametricFunctionSource(); + virtual ~vtkParametricFunctionSource(); + + // Usual data generation method + int RequestData(vtkInformation *info, vtkInformationVector **input, + vtkInformationVector *output); + + // Variables + vtkParametricFunction *ParametricFunction; + + int UResolution; + int VResolution; + int WResolution; + int GenerateTextureCoordinates; + int ScalarMode; + +private: + // Create output depending on function dimension + void Produce1DOutput(vtkInformationVector *output); + void Produce2DOutput(vtkInformationVector *output); + + // Description: + // Generate triangle strips from an ordered set of points. + // + // Given a parametrization f(u,v)->(x,y,z), this function generates + // a vtkCellAarray of point IDs over the range MinimumU <= u < MaximumU + // and MinimumV <= v < MaximumV. + // + // Before using this function, ensure that: UResolution, + // VResolution, MinimumU, MaximumU, MinimumV, MaximumV, JoinU, JoinV, + // TwistU, TwistV, ordering are set appropriately for the parametric function. + // + void MakeTriangleStrips ( vtkCellArray * strips, int PtsU, int PtsV ); + + vtkParametricFunctionSource(const vtkParametricFunctionSource&); // Not implemented. + void operator=(const vtkParametricFunctionSource&); // Not implemented. + +}; + +#endif diff --git a/Graphics/vtkPlaneSource.cxx b/Graphics/vtkPlaneSource.cxx new file mode 100644 index 0000000..5154e2d --- /dev/null +++ b/Graphics/vtkPlaneSource.cxx @@ -0,0 +1,422 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlaneSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPlaneSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkPlaneSource, "$Revision: 1.63 $"); +vtkStandardNewMacro(vtkPlaneSource); + +// Construct plane perpendicular to z-axis, resolution 1x1, width and height +// 1.0, and centered at the origin. +vtkPlaneSource::vtkPlaneSource() +{ + this->XResolution = 1; + this->YResolution = 1; + + this->Origin[0] = this->Origin[1] = -0.5; + this->Origin[2] = 0.0; + + this->Point1[0] = 0.5; + this->Point1[1] = -0.5; + this->Point1[2] = 0.0; + + this->Point2[0] = -0.5; + this->Point2[1] = 0.5; + this->Point2[2] = 0.0; + + this->Normal[2] = 1.0; + this->Normal[0] = this->Normal[1] = 0.0; + + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + + this->SetNumberOfInputPorts(0); +} + +// Set the number of x-y subdivisions in the plane. +void vtkPlaneSource::SetResolution(const int xR, const int yR) +{ + if ( xR != this->XResolution || yR != this->YResolution ) + { + this->XResolution = xR; + this->YResolution = yR; + + this->XResolution = (this->XResolution > 0 ? this->XResolution : 1); + this->YResolution = (this->YResolution > 0 ? this->YResolution : 1); + + this->Modified(); + } +} + +int vtkPlaneSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double x[3], tc[2], v1[3], v2[3]; + vtkIdType pts[4]; + int i, j, ii; + int numPts; + int numPolys; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkFloatArray *newTCoords; + vtkCellArray *newPolys; + + // Check input + for ( i=0; i < 3; i++ ) + { + v1[i] = this->Point1[i] - this->Origin[i]; + v2[i] = this->Point2[i] - this->Origin[i]; + } + if ( !this->UpdatePlane(v1,v2) ) + { + return 0; + } + + // Set things up; allocate memory + // + numPts = (this->XResolution+1) * (this->YResolution+1); + numPolys = this->XResolution * this->YResolution; + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*numPts); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys,4)); + + // Generate points and point data + // + for (numPts=0, i=0; i<(this->YResolution+1); i++) + { + tc[1] = (double) i / this->YResolution; + for (j=0; j<(this->XResolution+1); j++) + { + tc[0] = (double) j / this->XResolution; + + for ( ii=0; ii < 3; ii++) + { + x[ii] = this->Origin[ii] + tc[0]*v1[ii] + tc[1]*v2[ii]; + } + + newPoints->InsertPoint(numPts,x); + newTCoords->InsertTuple(numPts,tc); + newNormals->InsertTuple(numPts++,this->Normal); + } + } + + // Generate polygon connectivity + // + for (i=0; iYResolution; i++) + { + for (j=0; jXResolution; j++) + { + pts[0] = j + i*(this->XResolution+1); + pts[1] = pts[0] + 1; + pts[2] = pts[0] + this->XResolution + 2; + pts[3] = pts[0] + this->XResolution + 1; + newPolys->InsertNextCell(4,pts); + } + } + + // Update ourselves and release memory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + newNormals->SetName("Normals"); + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + newTCoords->SetName("TextureCoordinates"); + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +// Set the normal to the plane. Will modify the Origin, Point1, and Point2 +// instance variables as necessary (i.e., rotate the plane around its center). +void vtkPlaneSource::SetNormal(double N[3]) +{ + double n[3], rotVector[3], theta; + + //make sure input is decent + n[0] = N[0]; + n[1] = N[1]; + n[2] = N[2]; + if ( vtkMath::Normalize(n) == 0.0 ) + { + vtkErrorMacro(<<"Specified zero normal"); + return; + } + + // Compute rotation vector using a transformation matrix. + // Note that if normals are parallel then the rotation is either + // 0 or 180 degrees. + double dp = vtkMath::Dot(this->Normal,n); + if ( dp >= 1.0 ) + { + return; //zero rotation + } + else if ( dp <= -1.0 ) + { + theta = 180.0; + rotVector[0] = this->Point1[0] - this->Origin[0]; + rotVector[1] = this->Point1[1] - this->Origin[1]; + rotVector[2] = this->Point1[2] - this->Origin[2]; + } + else + { + vtkMath::Cross(this->Normal,n,rotVector); + theta = acos((double)dp) / vtkMath::DoubleDegreesToRadians(); + } + + // create rotation matrix + vtkTransform *transform = vtkTransform::New(); + transform->PostMultiply(); + + transform->Translate(-this->Center[0],-this->Center[1],-this->Center[2]); + transform->RotateWXYZ(theta,rotVector[0],rotVector[1],rotVector[2]); + transform->Translate(this->Center[0],this->Center[1],this->Center[2]); + + // transform the three defining points + transform->TransformPoint(this->Origin,this->Origin); + transform->TransformPoint(this->Point1,this->Point1); + transform->TransformPoint(this->Point2,this->Point2); + + this->Normal[0] = n[0]; this->Normal[1] = n[1]; this->Normal[2] = n[2]; + + this->Modified(); + transform->Delete(); +} + +// Set the normal to the plane. Will modify the Origin, Point1, and Point2 +// instance variables as necessary (i.e., rotate the plane around its center). +void vtkPlaneSource::SetNormal(double nx, double ny, double nz) +{ + double n[3]; + + n[0] = nx; n[1] = ny; n[2] = nz; + this->SetNormal(n); +} + +// Set the center of the plane. Will modify the Origin, Point1, and Point2 +// instance variables as necessary (i.e., translate the plane). +void vtkPlaneSource::SetCenter(double center[3]) +{ + if ( this->Center[0] == center[0] && this->Center[1] == center[1] && + this->Center[2] == center[2] ) + { + return; //no change + } + else + { + int i; + double v1[3], v2[3]; + + for ( i=0; i < 3; i++ ) + { + v1[i] = this->Point1[i] - this->Origin[i]; + v2[i] = this->Point2[i] - this->Origin[i]; + } + + for ( i=0; i < 3; i++ ) + { + this->Center[i] = center[i]; + this->Origin[i] = this->Center[i] - 0.5*(v1[i] + v2[i]); + this->Point1[i] = this->Origin[i] + v1[i]; + this->Point2[i] = this->Origin[i] + v2[i]; + } + this->Modified(); + } +} + +// Set the center of the plane. Will modify the Origin, Point1, and Point2 +// instance variables as necessary (i.e., translate the plane). +void vtkPlaneSource::SetCenter(double x, double y, double z) +{ + double center[3]; + + center[0] = x; center[1] = y; center[2] = z; + this->SetCenter(center); +} + +// modifies the normal and origin +void vtkPlaneSource::SetPoint1(double pnt[3]) +{ + if ( this->Point1[0] == pnt[0] && this->Point1[1] == pnt[1] && + this->Point1[2] == pnt[2] ) + { + return; //no change + } + else + { + int i; + double v1[3], v2[3]; + + for ( i=0; i < 3; i++ ) + { + this->Point1[i] = pnt[i]; + v1[i] = this->Point1[i] - this->Origin[i]; + v2[i] = this->Point2[i] - this->Origin[i]; + } + + // set plane normal + this->UpdatePlane(v1,v2); + this->Modified(); + } +} + +// modifies the normal and origin +void vtkPlaneSource::SetPoint2(double pnt[3]) +{ + if ( this->Point2[0] == pnt[0] && this->Point2[1] == pnt[1] && + this->Point2[2] == pnt[2] ) + { + return; //no change + } + else + { + int i; + double v1[3], v2[3]; + + for ( i=0; i < 3; i++ ) + { + this->Point2[i] = pnt[i]; + v1[i] = this->Point1[i] - this->Origin[i]; + v2[i] = this->Point2[i] - this->Origin[i]; + } + // set plane normal + this->UpdatePlane(v1,v2); + this->Modified(); + } +} + +void vtkPlaneSource::SetPoint1(double x, double y, double z) +{ + double pnt[3]; + + pnt[0] = x; pnt[1] = y; pnt[2] = z; + this->SetPoint1(pnt); +} +void vtkPlaneSource::SetPoint2(double x, double y, double z) +{ + double pnt[3]; + + pnt[0] = x; pnt[1] = y; pnt[2] = z; + this->SetPoint2(pnt); +} + +// Translate the plane in the direction of the normal by the distance specified. +// Negative values move the plane in the opposite direction. +void vtkPlaneSource::Push(double distance) +{ + int i; + + if ( distance == 0.0 ) + { + return; + } + for (i=0; i < 3; i++ ) + { + this->Origin[i] += distance * this->Normal[i]; + this->Point1[i] += distance * this->Normal[i]; + this->Point2[i] += distance * this->Normal[i]; + } + // set the new center + for ( i=0; i < 3; i++ ) + { + this->Center[i] = 0.5*(this->Point1[i] + this->Point2[i]); + } + + this->Modified(); +} + +// Protected method updates normals and plane center from two axes. +int vtkPlaneSource::UpdatePlane(double v1[3], double v2[3]) +{ + // set plane center + for ( int i=0; i < 3; i++ ) + { + this->Center[i] = this->Origin[i] + 0.5*(v1[i] + v2[i]); + } + + // set plane normal + vtkMath::Cross(v1,v2,this->Normal); + if ( vtkMath::Normalize(this->Normal) == 0.0 ) + { + vtkErrorMacro(<<"Bad plane coordinate system"); + return 0; + } + else + { + return 1; + } +} + +void vtkPlaneSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "X Resolution: " << this->XResolution << "\n"; + os << indent << "Y Resolution: " << this->YResolution << "\n"; + + os << indent << "Origin: (" << this->Origin[0] << ", " + << this->Origin[1] << ", " + << this->Origin[2] << ")\n"; + + os << indent << "Point 1: (" << this->Point1[0] << ", " + << this->Point1[1] << ", " + << this->Point1[2] << ")\n"; + + os << indent << "Point 2: (" << this->Point2[0] << ", " + << this->Point2[1] << ", " + << this->Point2[2] << ")\n"; + + os << indent << "Normal: (" << this->Normal[0] << ", " + << this->Normal[1] << ", " + << this->Normal[2] << ")\n"; + + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << ")\n"; + +} diff --git a/Graphics/vtkPlaneSource.h b/Graphics/vtkPlaneSource.h new file mode 100644 index 0000000..bf6dc14 --- /dev/null +++ b/Graphics/vtkPlaneSource.h @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlaneSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPlaneSource - create an array of quadrilaterals located in a plane +// .SECTION Description +// vtkPlaneSource creates an m x n array of quadrilaterals arranged as +// a regular tiling in a plane. The plane is defined by specifying an +// origin point, and then two other points that, together with the +// origin, define two axes for the plane. These axes do not have to be +// orthogonal - so you can create a parallelogram. (The axes must not +// be parallel.) By default, the plane is centered at the origin and +// perpendicular to the z-axis, with width and height of length 1. The +// resolution of the plane (i.e., number of subdivisions) is +// controlled by the ivars XResolution and YResolution. +// +// There are three convenience methods that allow you to easily move the +// plane. The first, SetNormal(), allows you to specify the plane +// normal. The effect of this method is to rotate the plane around the center +// of the plane, aligning the plane normal with the specified normal. The +// rotation is about the axis defined by the cross product of the current +// normal with the new normal. The second, SetCenter(), translates the center +// of the plane to the specified center point. The third method, Push(), +// allows you to translate the plane along the plane normal by the distance +// specified. (Negative Push values translate the plane in the negative +// normal direction.) Note that the SetNormal(), SetCenter() and Push() +// methods modify the Origin, Point1, and/or Point2 instance variables. + +// .SECTION Caveats +// The normal to the plane will point in the direction of the cross product +// of the first axis (Origin->Point1) with the second (Origin->Point2). This +// also affects the normals to the generated polygons. + +#ifndef __vtkPlaneSource_h +#define __vtkPlaneSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkPlaneSource : public vtkPolyDataAlgorithm +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkPlaneSource,vtkPolyDataAlgorithm); + + // Description: + // Construct plane perpendicular to z-axis, resolution 1x1, width + // and height 1.0, and centered at the origin. + static vtkPlaneSource *New(); + + // Description: + // Specify the resolution of the plane along the first axes. + vtkSetMacro(XResolution,int); + vtkGetMacro(XResolution,int); + + // Description: + // Specify the resolution of the plane along the second axes. + vtkSetMacro(YResolution,int); + vtkGetMacro(YResolution,int); + + // Description: + // Set the number of x-y subdivisions in the plane. + void SetResolution(const int xR, const int yR); + void GetResolution(int& xR,int& yR) { + xR=this->XResolution; yR=this->YResolution;}; + + // Description: + // Specify a point defining the origin of the plane. + vtkSetVector3Macro(Origin,double); + vtkGetVectorMacro(Origin,double,3); + + // Description: + // Specify a point defining the first axis of the plane. + void SetPoint1(double x, double y, double z); + void SetPoint1(double pnt[3]); + vtkGetVectorMacro(Point1,double,3); + + // Description: + // Specify a point defining the second axis of the plane. + void SetPoint2(double x, double y, double z); + void SetPoint2(double pnt[3]); + vtkGetVectorMacro(Point2,double,3); + + // Description: + // Set/Get the center of the plane. Works in conjunction with the plane + // normal to position the plane. Don't use this method to define the plane. + // Instead, use it to move the plane to a new center point. + void SetCenter(double x, double y, double z); + void SetCenter(double center[3]); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set/Get the plane normal. Works in conjunction with the plane center to + // orient the plane. Don't use this method to define the plane. Instead, use + // it to rotate the plane around the current center point. + void SetNormal(double nx, double ny, double nz); + void SetNormal(double n[3]); + vtkGetVectorMacro(Normal,double,3); + + // Description: + // Translate the plane in the direction of the normal by the + // distance specified. Negative values move the plane in the + // opposite direction. + void Push(double distance); + +protected: + vtkPlaneSource(); + ~vtkPlaneSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int XResolution; + int YResolution; + double Origin[3]; + double Point1[3]; + double Point2[3]; + double Normal[3]; + double Center[3]; + + int UpdatePlane(double v1[3], double v2[3]); +private: + vtkPlaneSource(const vtkPlaneSource&); // Not implemented. + void operator=(const vtkPlaneSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkPlanesIntersection.cxx b/Graphics/vtkPlanesIntersection.cxx new file mode 100644 index 0000000..8d0148e --- /dev/null +++ b/Graphics/vtkPlanesIntersection.cxx @@ -0,0 +1,881 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlanesIntersection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkMath.h" +#include "vtkPlanesIntersection.h" +#include "vtkPointsProjectedHull.h" +#include "vtkFloatArray.h" +#include "vtkCell.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPlanesIntersection, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkPlanesIntersection); + +// Experiment shows that we get plane equation values on the +// order of 10e-6 when the point is actually on the plane + +#define VTK_SMALL_DOUBLE (10e-5) + +const int Inside = 0; +const int Outside = 1; +const int Straddle = 2; + +const int Xdim=0; // don't change these three values +const int Ydim=1; +const int Zdim=2; + +vtkPlanesIntersection::vtkPlanesIntersection() +{ + this->Plane = NULL; + this->regionPts = NULL; +} +vtkPlanesIntersection::~vtkPlanesIntersection() +{ + if (this->regionPts) + { + this->regionPts->Delete(); + this->regionPts = NULL; + } + if (this->Plane) + { + delete [] this->Plane; + this->Plane = NULL; + } +} +void vtkPlanesIntersection::SetRegionVertices(vtkPoints *v) +{ + int i; + if (this->regionPts) this->regionPts->Delete(); + this->regionPts = vtkPointsProjectedHull::New(); + + if (v->GetDataType() == VTK_DOUBLE) + { + this->regionPts->DeepCopy(v); + } + else + { + this->regionPts->SetDataTypeToDouble(); + + int npts = v->GetNumberOfPoints(); + this->regionPts->SetNumberOfPoints(npts); + + double *pt; + for (i=0; iGetPoint(i); + regionPts->SetPoint(i, pt[0], pt[1], pt[2]); + } + } +} +void vtkPlanesIntersection::SetRegionVertices(double *v, int nvertices) +{ + int i; + if (this->regionPts) this->regionPts->Delete(); + this->regionPts = vtkPointsProjectedHull::New(); + + this->regionPts->SetDataTypeToDouble(); + this->regionPts->SetNumberOfPoints(nvertices); + + for (i=0; iregionPts->SetPoint(i, v + (i*3)); + } +} +int vtkPlanesIntersection::GetRegionVertices(double *v, int nvertices) +{ + int i; + if (this->regionPts == NULL) this->ComputeRegionVertices(); + + int npts = this->regionPts->GetNumberOfPoints(); + + if (npts > nvertices) npts = nvertices; + + for (i=0; iregionPts->GetPoint(i, v + i*3); + } + + return npts; +} +int vtkPlanesIntersection::GetNumRegionVertices() +{ + if (this->regionPts == NULL) this->ComputeRegionVertices(); + + return this->regionPts->GetNumberOfPoints(); +} + +//--------------------------------------------------------------------- +// Determine whether the axis aligned box provided intersects +// the convex region bounded by the planes. +//--------------------------------------------------------------------- + +int vtkPlanesIntersection::IntersectsRegion(vtkPoints *R) +{ + int plane; + int allInside=0; + int nplanes = this->GetNumberOfPlanes(); + + if (nplanes < 4) + { + vtkErrorMacro("invalid region - less than 4 planes"); + return 0; + } + + if (this->regionPts == NULL) + { + this->ComputeRegionVertices(); + if (this->regionPts->GetNumberOfPoints() < 4) + { + vtkErrorMacro("Invalid region: zero-volume intersection"); + return 0; + } + } + + if (R->GetNumberOfPoints() < 8) + { + vtkErrorMacro("invalid box"); + return 0; + } + + int *where = new int[nplanes]; + + int intersects = -1; + +// Here's the algorithm from Graphics Gems IV, page 81, +// +// R is an axis aligned box (could represent a region in a spatial +// spatial partitioning of a volume of data). +// +// P is a set of planes defining a convex region in space (could be +// a view frustum). +// +// The question is does P intersect R. We expect to be doing the +// calculation for one P and many Rs. + +// You may wonder why we don't do what vtkClipPolyData does, which +// computes the following on every point of it's PolyData input: +// +// for each point in the input +// for each plane defining the convex region +// evaluate plane eq to determine if outside, inside or on plane +// +// For each cell, if some points are inside and some outside, then +// vtkClipPolyData decides it straddles the region and clips it. If +// every point is inside, it tosses it. +// +// The reason is that the Graphics Gems algorithm is faster in some +// cases (we may only need to evaluate one vertex of the box). And +// also because if the convex region passes through the box without +// including any vertices of the box, all box vertices will be +// "outside" and the algorithm will fail. vtkClipPolyData assumes +// cells are very small relative to the clip region. In general +// the axis-aligned box may be a large portion of world coordinate +// space, and the convex region a view frustum representing a +// small portion of the screen. + + +// 1. If R does not intersect P's bounding box, return 0. + + if (this->IntersectsBoundingBox(R) == 0) + { + intersects = 0; + } + +// 2. If P's bounding box is entirely inside R, return 1. + + else if (this->EnclosesBoundingBox(R) == 1) + { + intersects = 1; + } + +// 3. For each face plane F of P +// +// Suppose the plane equation is negative inside P and +// positive outside P. Choose the vertex (n) of R which is +// most in the direction of the negative pointing normal of +// the plane. The opposite vertex (p) is most in the +// direction of the positive pointing normal. (This is +// a very quick calculation.) +// +// If n is on the positive side of the plane, R is +// completely outside of P, so return 0. +// +// If n and p are both on the negative side, then R is on +// the "inside" of F. Keep track to see if all R is inside +// all planes defining the region. + + else + { + if (this->Plane == NULL) this->SetPlaneEquations(); + + allInside = 1; + + for (plane=0; plane < nplanes; plane++) + { + where[plane] = this->EvaluateFacePlane(plane, R); + + if (allInside && (where[plane] != Inside)) + { + allInside = 0; + } + + if (where[plane] == Outside) + { + intersects = 0; + + break; + } + } + } + + if (intersects == -1) + { + +// 4. If n and p were "inside" all faces, R is inside P +// so return 1. + + if ( allInside) + { + intersects = 1; + } +// 5. For each of three orthographic projections (X, Y and Z) +// +// Compute the equations of the edge lines of P in those views. +// +// If R's projection lies outside any of these lines (using 2D +// version of n & p tests), return 0. + + else if ((this->IntersectsProjection(R, Xdim) == 0) || + (this->IntersectsProjection(R, Ydim) == 0) || + (this->IntersectsProjection(R, Zdim) == 0) ) + { + } + else + { +// 6. Return 1. + + intersects = 1; + } + } + + delete [] where; + + return (intersects==1); +} + +// a static convenience function - since we have all the machinery +// in this class, we can compute whether an arbitrary polygon intersects +// an axis aligned box +// +// it is assumed "pts" represents a planar polygon +// + +int vtkPlanesIntersection::PolygonIntersectsBBox(double bounds[6], vtkPoints *pts) +{ + // a bogus vtkPlanesIntersection object containing only one plane + + vtkPlanesIntersection *pi = vtkPlanesIntersection::New(); + + pi->SetRegionVertices(pts); + + vtkPoints *Box = vtkPoints::New(); + Box->SetNumberOfPoints(8); + Box->SetPoint(0, bounds[0], bounds[2], bounds[4]); + Box->SetPoint(1, bounds[1], bounds[2], bounds[4]); + Box->SetPoint(2, bounds[1], bounds[3], bounds[4]); + Box->SetPoint(3, bounds[0], bounds[3], bounds[4]); + Box->SetPoint(4, bounds[0], bounds[2], bounds[5]); + Box->SetPoint(5, bounds[1], bounds[2], bounds[5]); + Box->SetPoint(6, bounds[1], bounds[3], bounds[5]); + Box->SetPoint(7, bounds[0], bounds[3], bounds[5]); + + int intersects = -1; + +// 1. Does Box intersect the polygon's bounding box? + + if (pi->IntersectsBoundingBox(Box) == 0) + { + intersects = 0; + } + +// 2. If so, does Box entirely contain the polygon's bounding box? + + else if (pi->EnclosesBoundingBox(Box) == 1) + { + intersects = 1; + } + + + if (intersects == -1) + { + +// 3. If not, determine whether the Box intersects the plane of the polygon + + vtkPoints *origin = vtkPoints::New(); + origin->SetNumberOfPoints(1); + origin->SetPoint(0, pts->GetPoint(0)); + + vtkFloatArray *normal = vtkFloatArray::New(); + normal->SetNumberOfComponents(3); + normal->SetNumberOfTuples(1); + + // find 3 points that are not co-linear and compute a normal + + double nvec[3], p0[3], p1[3], pp[3]; + + int npts = pts->GetNumberOfPoints(); + + pts->GetPoint(0, p0); + pts->GetPoint(1, p1); + + for (int p = 2; p < npts; p++) + { + pts->GetPoint(p, pp); + + vtkPlanesIntersection::ComputeNormal(p0, p1, pp, nvec); + + if (vtkPlanesIntersection::GoodNormal(nvec)) + { + break; + } + } + + normal->SetTuple(0, nvec); + + pi->SetPoints(origin); + pi->SetNormals(normal); + + origin->Delete(); + normal->Delete(); + + pi->SetPlaneEquations(); + + int where = pi->EvaluateFacePlane(0, Box); + + if (where != Straddle) + { + intersects = 0; + } + } + + if (intersects == -1) + { + +// 4. The Box intersects the plane of the polygon. +// +// For each of three orthographic projections (X, Y and Z), +// compute the equations of the edge lines of the polygon in those views. +// +// If Box's projection lies outside any of these projections, they +// don't intersect in 3D. Otherwise they do intersect in 3D. + + if ((pi->IntersectsProjection(Box, Xdim) == 0) || + (pi->IntersectsProjection(Box, Ydim) == 0) || + (pi->IntersectsProjection(Box, Zdim) == 0) ) + { + intersects = 0; + } + else + { + intersects = 1; + } + } + + Box->Delete(); + pi->Delete(); + + return intersects; +} + +//--------------------------------------------------------------------- +// Some convenience functions that build a vtkPlanesIntersection object +// out of a convex region. +//--------------------------------------------------------------------- + +// a static convenience function that converts a 3D cell into a +// vtkPlanesIntersection object + +vtkPlanesIntersection *vtkPlanesIntersection::Convert3DCell(vtkCell *cell) +{ + int i; + int nfaces = cell->GetNumberOfFaces(); + + vtkPoints *origins = vtkPoints::New(); + origins->SetNumberOfPoints(nfaces); + + vtkFloatArray *normals = vtkFloatArray::New(); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(nfaces); + + double inside[3] = {0.0, 0.0, 0.0}; + + for (i=0; i < nfaces; i++) + { + vtkCell *face = cell->GetFace(i); + + vtkPoints *facePts = face->GetPoints(); + int npts = facePts->GetNumberOfPoints(); + + double p0[3], p1[3], pp[3], n[3]; + + facePts->GetPoint(0, p0); + facePts->GetPoint(1, p1); + + for (int p = 2; p < npts; p++) + { + facePts->GetPoint(p, pp); + + vtkPlanesIntersection::ComputeNormal(pp, p1, p0, n); + + if (vtkPlanesIntersection::GoodNormal(n)) + { + break; + } + } + + origins->SetPoint(i, pp); + normals->SetTuple(i, n); + + inside[0] += p1[0]; + inside[1] += p1[1]; + inside[2] += p1[2]; + } + + inside[0] /= (double)nfaces; + inside[1] /= (double)nfaces; + inside[2] /= (double)nfaces; + + // ensure that all normals are outward pointing + + for (i=0; i < nfaces; i++) + { + double ns[3], xs[3]; + double n[3], x[3], p[4]; + + normals->GetTuple(i, ns); + origins->GetPoint(i, xs); + + n[0] = (double)ns[0]; x[0] = (double)xs[0]; + n[1] = (double)ns[1]; x[1] = (double)xs[1]; + n[2] = (double)ns[2]; x[2] = (double)xs[2]; + + double outside[3]; + + outside[0] = x[0] + n[0]; + outside[1] = x[1] + n[1]; + outside[2] = x[2] + n[2]; + + vtkPlanesIntersection::PlaneEquation(n, x, p); + + double insideVal = vtkPlanesIntersection::EvaluatePlaneEquation(inside, p); + + double normalDirection = + vtkPlanesIntersection::EvaluatePlaneEquation(outside, p); + + int sameSide = + ( (insideVal < 0) && (normalDirection < 0)) || + ( (insideVal > 0) && (normalDirection > 0)); + + if (sameSide) + { + ns[0] = -ns[0]; + ns[1] = -ns[1]; + ns[2] = -ns[2]; + + normals->SetTuple(i, ns); + } + } + + vtkPlanesIntersection *pi = vtkPlanesIntersection::New(); + + pi->SetPoints(origins); + pi->SetNormals(normals); + + origins->Delete(); + normals->Delete(); + + pi->SetRegionVertices(cell->GetPoints()); + + return pi; +} + +//-------------------------------------------------------------------------- + +void vtkPlanesIntersection::ComputeNormal(double *p1, double *p2, double *p3, + double normal[3]) +{ + double v1[3], v2[3]; + + v1[0] = p1[0] - p2[0]; v1[1] = p1[1] - p2[1]; v1[2] = p1[2] - p2[2]; + v2[0] = p3[0] - p2[0]; v2[1] = p3[1] - p2[1]; v2[2] = p3[2] - p2[2]; + + vtkMath::Cross(v1, v2, normal); + + return; +} +int vtkPlanesIntersection::GoodNormal(double *n) +{ + if ( (n[0] < VTK_SMALL_DOUBLE) || (n[0] > VTK_SMALL_DOUBLE) || + (n[1] < VTK_SMALL_DOUBLE) || (n[1] > VTK_SMALL_DOUBLE) || + (n[2] < VTK_SMALL_DOUBLE) || (n[2] > VTK_SMALL_DOUBLE) ) + { + return 1; + } + else + { + return 0; + } +} +double vtkPlanesIntersection::EvaluatePlaneEquation(double *x, double *p) +{ + return (x[0]*p[0] + x[1]*p[1] + x[2]*p[2] + p[3]); +} +void vtkPlanesIntersection::PlaneEquation(double *n, double *x, double *p) +{ + p[0] = n[0]; + p[1] = n[1]; + p[2] = n[2]; + p[3] = -(n[0]*x[0] + n[1]*x[1] + n[2]*x[2]); +} + +// The plane equations *********************************************** + +void vtkPlanesIntersection::SetPlaneEquations() +{ + int i; + int nplanes = this->GetNumberOfPlanes(); + + // vtkPlanes stores normals & pts instead of + // plane equation coefficients + + if (this->Plane) delete [] this->Plane; + + this->Plane = new double[nplanes*4]; + + for (i=0; iPoints->GetPoint(i, x); + this->Normals->GetTuple(i, n); + + double nd[3], xd[3]; + + nd[0] = n[0]; xd[0] = x[0]; + nd[1] = n[1]; xd[1] = x[1]; + nd[2] = n[2]; xd[2] = x[2]; + + double *p = this->Plane + (i*4); + + vtkPlanesIntersection::PlaneEquation(nd, xd, p); + } +} + +// Compute region vertices if not set explicity ******************** + +void vtkPlanesIntersection::ComputeRegionVertices() +{ + double M[3][3]; + double rhs[3]; + double testv[3]; + int i, j, k; + int nplanes = this->GetNumberOfPlanes(); + + if (this->regionPts) this->regionPts->Delete(); + this->regionPts = vtkPointsProjectedHull::New(); + + if (nplanes <= 3) + { + vtkErrorMacro( << + "vtkPlanesIntersection::ComputeRegionVertices invalid region"); + return; + } + + if (this->Plane == NULL) + { + this->SetPlaneEquations(); + } + + // This is an expensive process. Better if vertices are + // set in SetRegionVertices(). We're testing every triple of + // planes to see if they intersect in a point that is + // not "outside" any plane. + + int nvertices=0; + + for (i=0; i < nplanes; i++) + { + for (j=i+1; j < nplanes; j++) + { + for (k=j+1; k < nplanes; k++) + { + this->planesMatrix(i, j, k, M); + + int notInvertible = this->Invert3x3(M); + + if (notInvertible) continue; + + this->planesRHS(i, j, k, rhs); + + vtkMath::Multiply3x3(M, rhs, testv); + + if (duplicate(testv)) continue; + + int outside = this->outsideRegion(testv); + + if (!outside) + { + this->regionPts->InsertPoint(nvertices, testv); + nvertices++; + } + } + } + } +} +int vtkPlanesIntersection::duplicate(double testv[3]) const +{ + int i; + double pt[3]; + int npts = this->regionPts->GetNumberOfPoints(); + + for (i=0; iregionPts->GetPoint(i, pt); + + if ( (pt[0] == testv[0]) && (pt[1] == testv[1]) && (pt[2] == testv[2])) + { + return 1; + } + } + return 0; +} +void vtkPlanesIntersection::planesMatrix(int p1, int p2, int p3, double M[3][3]) const +{ + int i; + for (i=0; i<3; i++) + { + M[0][i] = this->Plane[p1*4 + i]; + M[1][i] = this->Plane[p2*4 + i]; + M[2][i] = this->Plane[p3*4 + i]; + } +} +void vtkPlanesIntersection::planesRHS(int p1, int p2, int p3, double r[3]) const +{ + r[0] = -(this->Plane[p1*4 + 3]); + r[1] = -(this->Plane[p2*4 + 3]); + r[2] = -(this->Plane[p3*4 + 3]); +} +int vtkPlanesIntersection::outsideRegion(double testv[3]) +{ + int i; + int outside = 0; + int nplanes = this->GetNumberOfPlanes(); + + for (i=0; iPlane + row); + + if (fx > VTK_SMALL_DOUBLE) + { + outside = 1; + break; + } + } + return outside; +} +int vtkPlanesIntersection::Invert3x3(double M[3][3]) +{ + int i, j; + double temp[3][3]; + + double det = vtkMath::Determinant3x3(M); + + if ( (det > -VTK_SMALL_DOUBLE) && (det < VTK_SMALL_DOUBLE)) return -1; + + vtkMath::Invert3x3(M, temp); + + for (i=0; i<3; i++) + { + for (j=0; j<3; j++) + { + M[i][j] = temp[i][j]; + } + } + + return 0; +} + +// Region / box intersection tests ******************************* + +int vtkPlanesIntersection::IntersectsBoundingBox(vtkPoints *R) +{ + double BoxBounds[6], RegionBounds[6]; + + R->GetBounds(BoxBounds); + + this->regionPts->GetBounds(RegionBounds); + + if ((BoxBounds[1] <= RegionBounds[0]) || + (BoxBounds[0] >= RegionBounds[1]) || + (BoxBounds[3] <= RegionBounds[2]) || + (BoxBounds[2] >= RegionBounds[3]) || + (BoxBounds[5] <= RegionBounds[4]) || + (BoxBounds[4] >= RegionBounds[5])) + { + return 0; + } + return 1; +} +int vtkPlanesIntersection::EnclosesBoundingBox(vtkPoints *R) +{ + double BoxBounds[6], RegionBounds[6]; + + R->GetBounds(BoxBounds); + + this->regionPts->GetBounds(RegionBounds); + + if ((BoxBounds[0] > RegionBounds[0]) || + (BoxBounds[1] < RegionBounds[1]) || + (BoxBounds[2] > RegionBounds[2]) || + (BoxBounds[3] < RegionBounds[3]) || + (BoxBounds[4] > RegionBounds[4]) || + (BoxBounds[5] < RegionBounds[5])) + { + return 0; + } + + return 1; +} +int vtkPlanesIntersection::EvaluateFacePlane(int plane, vtkPoints *R) +{ + int i; + double n[3], bounds[6]; + double withN[3], oppositeN[3]; + + R->GetBounds(bounds); + + this->Normals->GetTuple(plane, n); + + // Find vertex of R most in direction of normal, and find + // oppposite vertex + + for (i=0; i<3; i++) + { + if (n[i] < 0) + { + withN[i] = (double)bounds[i*2]; + oppositeN[i] = (double)bounds[i*2 + 1]; + } + else + { + withN[i] = (double)bounds[i*2 + 1]; + oppositeN[i] = (double)bounds[i*2]; + } + } + + // Determine whether R is in negative half plane ("inside" frustum), + // positive half plane, or whether it straddles the plane. + // The normal points in direction of positive half plane. + + double *p = this->Plane + (plane * 4); + + double negVal = + + vtkPlanesIntersection::EvaluatePlaneEquation(oppositeN, p); + + if (negVal >= 0) + { + return Outside; + } + + double posVal = + + vtkPlanesIntersection::EvaluatePlaneEquation(withN, p); + + if (posVal <= 0) + { + return Inside; + } + + else return Straddle; +} +int vtkPlanesIntersection::IntersectsProjection(vtkPoints *R, int dir) +{ + int intersects = 0; + + switch (dir) + { + case Xdim: + + intersects = this->regionPts->RectangleIntersectionX(R); + break; + + case Ydim: + + intersects = this->regionPts->RectangleIntersectionY(R); + break; + + case Zdim: + + intersects = this->regionPts->RectangleIntersectionZ(R); + break; + } + + return intersects; +} + +void vtkPlanesIntersection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Plane: " << this->Plane << endl; + os << indent << "regionPts: " << this->regionPts << endl; + + int i, npts; + + if (this->Points) + { + npts = this->Points->GetNumberOfPoints(); + + for (i=0; iPoints->GetPoint(i); + double *n = this->Normals->GetTuple(i); + + os << indent << "Origin " << pt[0] << " " << pt[1] << " " << pt[2] << " " ; + + os << indent << "Normal " << n[0] << " " << n[1] << " " << n[2] << endl; + } + } + + if (this->regionPts) + { + npts = this->regionPts->GetNumberOfPoints(); + + for (i=0; iregionPts->GetPoint(i); + + os << indent << "Vertex " << pt[0] << " " << pt[1] << " " << pt[2] << endl; + } + } +} diff --git a/Graphics/vtkPlanesIntersection.h b/Graphics/vtkPlanesIntersection.h new file mode 100644 index 0000000..c3c05d2 --- /dev/null +++ b/Graphics/vtkPlanesIntersection.h @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlanesIntersection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkPlanesIntersection - A vtkPlanesIntersection object is a +// vtkPlanes object that can compute whether the arbitrary convex region +// bounded by it's planes intersects an axis-aligned box. +// +// .SECTION Description +// A subclass of vtkPlanes, this class determines whether it +// intersects an axis aligned box. This is motivated by the +// need to intersect the axis aligned region of a spacial +// decomposition of volume data with various other regions. +// It uses the algorithm from Graphics Gems IV, page 81. +// +// .SECTION Caveat +// An instance of vtkPlanes can be redefined by changing the planes, +// but this subclass then will not know if the region vertices are +// up to date. (Region vertices can be specified in SetRegionVertices +// or computed by the subclass.) So Delete and recreate if you want +// to change the set of planes. +// + +#ifndef __vtkPlanesIntersection_h +#define __vtkPlanesIntersection_h + +#include "vtkPlanes.h" + +class vtkPoints; +class vtkRenderer; +class vtkPointsProjectedHull; +class vtkCell; + +class VTK_GRAPHICS_EXPORT vtkPlanesIntersection : public vtkPlanes +{ + vtkTypeRevisionMacro(vtkPlanesIntersection, vtkPlanes); + +public: + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkPlanesIntersection *New(); + + // Description: + // It helps if you know the vertices of the convex region. + // If you don't, we will calculate them. Region vertices + // are 3-tuples. + + void SetRegionVertices(vtkPoints *pts); + void SetRegionVertices(double *v, int nvertices); + int GetNumRegionVertices(); + int GetRegionVertices(double *v, int nvertices); + + // Description: + // Return 1 if the axis aligned box defined by R intersects + // the region defined by the planes, or 0 otherwise. + + int IntersectsRegion(vtkPoints *R); + + // Description: + // A convenience function provided by this class, returns + // 1 if the polygon defined in pts intersects the bounding + // box defined in bounds, 0 otherwise. + // + // The points must define a planar polygon. + + static int PolygonIntersectsBBox(double bounds[6], vtkPoints *pts); + + // Description: + // Another convenience function provided by this class, returns + // the vtkPlanesIntersection object representing a 3D + // cell. The point IDs for each face must be given in + // counter-clockwise order from the outside of the cell. + + static vtkPlanesIntersection *Convert3DCell(vtkCell *cell); + +protected: + + static void ComputeNormal(double *p1, double *p2, double *p3, double normal[3]); + static double EvaluatePlaneEquation(double *x, double *p); + static void PlaneEquation(double *n, double *x, double *p); + static int GoodNormal(double *n); + static int Invert3x3(double M[3][3]); + + vtkPlanesIntersection(); + ~vtkPlanesIntersection(); + +private: + + int IntersectsBoundingBox(vtkPoints *R); + int EnclosesBoundingBox(vtkPoints *R); + int EvaluateFacePlane(int plane, vtkPoints *R); + int IntersectsProjection(vtkPoints *R, int direction); + + void SetPlaneEquations(); + void ComputeRegionVertices(); + + void planesMatrix(int p1, int p2, int p3, double M[3][3]) const; + int duplicate(double testv[3]) const; + void planesRHS(int p1, int p2, int p3, double r[3]) const; + int outsideRegion(double v[3]) ; + + // plane equations + double *Plane; + + // vertices of convex regions enclosed by the planes, also + // the ccw hull of that region projected in 3 orthog. directions + vtkPointsProjectedHull *regionPts; + + vtkPlanesIntersection(const vtkPlanesIntersection&); // Not implemented + void operator=(const vtkPlanesIntersection&); // Not implemented +}; +#endif + + diff --git a/Graphics/vtkPlatonicSolidSource.cxx b/Graphics/vtkPlatonicSolidSource.cxx new file mode 100644 index 0000000..75065f0 --- /dev/null +++ b/Graphics/vtkPlatonicSolidSource.cxx @@ -0,0 +1,219 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlatonicSolidSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPlatonicSolidSource.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkPlatonicSolidSource, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkPlatonicSolidSource); + +// The geometry and topology of each solid. Solids are centered at +// the origin with radius 1.0. +// The golden ration phi = (1+sqrt(5))/2=1.61803398875 enters into many +// of these values. +static double TetraPoints[] = { + 1.0,1.0,1.0, -1.0,1.0,-1.0, 1.0,-1.0,-1.0, -1.0,-1.0,1.0 +}; +static vtkIdType TetraVerts[] = { + 0,1,2, 1,3,2, 0,2,3, 0,3,1 +}; + +static double CubePoints[] = { + -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.0,1.0, 1.0,-1.0,1.0, 1.0,1.0,1.0, -1.0,1.0,1.0 +}; +static vtkIdType CubeVerts[] = { + 0,1,5,4, 0,4,7,3, 4,5,6,7, 3,7,6,2, 1,2,6,5, 0,3,2,1 +}; + +static double OctPoints[] = { + -1.0,-1.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,-1.4142135623731, 0.0,0.0,1.4142135623731 +}; +static vtkIdType OctVerts[] = { + 4,1,0, 4,2,1, 4,3,2, 4,0,3, 0,1,5, 1,2,5, 2,3,5, 3,0,5 +}; + +static double a = 0.61803398875; +static double b = 0.381966011250; +static double DodePoints[] = { + b, 0, 1, -b, 0, 1, b, 0,-1, -b, 0,-1, 0, 1,-b, + 0, 1, b, 0,-1,-b, 0,-1, b, 1, b, 0, 1,-b, 0, + -1, b, 0, -1,-b, 0, -a, a, a, a,-a, a, -a,-a,-a, + a, a,-a, a, a, a, -a, a,-a, -a,-a, a, a,-a,-a +}; +static vtkIdType DodeVerts[] = { + 0,1,12,5,16, 1,0,13,7,18, 2,3,14,6,19, 3,2,15,4,17, 4,5,16,8,15, + 5,4,17,10,12, 6,7,18,11,14, 7,6,19,9,13, 8,9,13,0,16, 9,8,15,2,19, + 10,11,14,3,17, 11,10,12,1,18 +}; + +static double c = 0.5; +static double d = 0.30901699; +static double IcosaPoints[] = { + 0.0,d,-c, 0.0,d,c, 0.0,-d,c, -d,c,0.0, + -d,-c,0.0, d,c,0.0, d,-c,0.0, 0.0,-d,-c, + c,0.0,d, -c,0.0,d, -c,0.0,-d, c,0.0,-d +}; +static vtkIdType IcosaVerts[] = { + 0,5,3, 1,3,5, 1,2,9, 1,8,2, 0,7,11, 0,10,7, 2,6,4, 7,4,6, 3,9,10, + 4,10,9, 5,11,8, 6,8,11, 1,9,3, 1,5,8, 0,3,10, 0,11,5, 7,10,4, 7,6,11, + 2,4,9, 2,8,6 +}; + +vtkPlatonicSolidSource::vtkPlatonicSolidSource() +{ + this->SolidType = VTK_SOLID_TETRAHEDRON; + this->SetNumberOfInputPorts(0); +} + +int vtkPlatonicSolidSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int i; + double *pptr, *solidPoints=NULL, solidScale=1.0; + vtkIdType *cptr, numPts=0, numCells=0, cellSize=0, *solidVerts=NULL; + + vtkDebugMacro(<<"Creating Platonic solid"); + + // Based on type, select correct connectivity and point arrays + // + switch (this->SolidType) + { + case VTK_SOLID_TETRAHEDRON: + numPts = 4; + cellSize = 3; + numCells = 4; + solidPoints = TetraPoints; + solidVerts = TetraVerts; + solidScale = 1.0/sqrt(3.0); + break; + + case VTK_SOLID_CUBE: + numPts = 8; + cellSize = 4; + numCells = 6; + solidPoints = CubePoints; + solidVerts = CubeVerts; + solidScale = 1.0/sqrt(3.0); + break; + + case VTK_SOLID_OCTAHEDRON: + numPts = 6; + cellSize = 3; + numCells = 8; + solidPoints = OctPoints; + solidVerts = OctVerts; + solidScale = 1.0/sqrt(2.0); + break; + + case VTK_SOLID_ICOSAHEDRON: + numPts = 12; + cellSize = 3; + numCells = 20; + solidPoints = IcosaPoints; + solidVerts = IcosaVerts; + solidScale = 1.0/0.58778524999243; + break; + + case VTK_SOLID_DODECAHEDRON: + numPts = 20; + cellSize = 5; + numCells = 12; + solidPoints = DodePoints; + solidVerts = DodeVerts; + solidScale = 1.0/1.070466269319; + break; + } + + // Create the solids + // + vtkPoints *pts = vtkPoints::New(); + pts->SetDataTypeToDouble(); + pts->SetNumberOfPoints(numPts); + vtkCellArray *polys = vtkCellArray::New(); + polys->Allocate(polys->EstimateSize(numCells,cellSize)); + vtkIntArray *colors = vtkIntArray::New(); + colors->SetNumberOfComponents(1); + colors->SetNumberOfTuples(numCells); + + // Points + for ( i=0, pptr=solidPoints; iSetPoint(i, solidScale*(pptr[0]), solidScale*(pptr[1]), + solidScale*(pptr[2])); + } + + // Cells + for ( i=0, cptr=solidVerts; iInsertNextCell(cellSize,cptr); + colors->SetTuple1(i,i); + } + + // Assemble the output + output->SetPoints(pts); + output->SetPolys(polys); + int idx = output->GetCellData()->AddArray(colors); + output->GetCellData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + + pts->Delete(); + polys->Delete(); + colors->Delete(); + + return 1; +} + +void vtkPlatonicSolidSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Solid Type: " << "\n"; + if ( this->SolidType == VTK_SOLID_TETRAHEDRON ) + { + os << "Tetrahedron\n"; + } + else if ( this->SolidType == VTK_SOLID_CUBE ) + { + os << "Cube\n"; + } + else if ( this->SolidType == VTK_SOLID_OCTAHEDRON ) + { + os << "Octahedron\n"; + } + else if ( this->SolidType == VTK_SOLID_ICOSAHEDRON ) + { + os << "Icosahedron\n"; + } + else //if ( this->SolidType == VTK_SOLID_DODECAHEDRON ) + { + os << "Dodecahedron\n"; + } +} diff --git a/Graphics/vtkPlatonicSolidSource.h b/Graphics/vtkPlatonicSolidSource.h new file mode 100644 index 0000000..7c2efc7 --- /dev/null +++ b/Graphics/vtkPlatonicSolidSource.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlatonicSolidSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPlatonicSolidSource - produce polygonal Platonic solids +// .SECTION Description +// vtkPlatonicSolidSource can generate each of the five Platonic solids: +// tetrahedron, cube, octahedron, icosahedron, and dodecahedron. Each of the +// solids is placed inside a sphere centered at the origin with radius 1.0. +// To use this class, simply specify the solid to create. Note that this +// source object creates cell scalars that are (integral value) face numbers. + +#ifndef __vtkPlatonicSolidSource_h +#define __vtkPlatonicSolidSource_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_SOLID_TETRAHEDRON 0 +#define VTK_SOLID_CUBE 1 +#define VTK_SOLID_OCTAHEDRON 2 +#define VTK_SOLID_ICOSAHEDRON 3 +#define VTK_SOLID_DODECAHEDRON 4 + +class VTK_GRAPHICS_EXPORT vtkPlatonicSolidSource : public vtkPolyDataAlgorithm +{ +public: + static vtkPlatonicSolidSource *New(); + vtkTypeRevisionMacro(vtkPlatonicSolidSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the type of PlatonicSolid solid to create. + vtkSetClampMacro(SolidType,int,VTK_SOLID_TETRAHEDRON,VTK_SOLID_DODECAHEDRON); + vtkGetMacro(SolidType,int); + void SetSolidTypeToTetrahedron() + {this->SetSolidType(VTK_SOLID_TETRAHEDRON);} + void SetSolidTypeToCube() + {this->SetSolidType(VTK_SOLID_CUBE);} + void SetSolidTypeToOctahedron() + {this->SetSolidType(VTK_SOLID_OCTAHEDRON);} + void SetSolidTypeToIcosahedron() + {this->SetSolidType(VTK_SOLID_ICOSAHEDRON);} + void SetSolidTypeToDodecahedron() + {this->SetSolidType(VTK_SOLID_DODECAHEDRON);} + +protected: + vtkPlatonicSolidSource(); + ~vtkPlatonicSolidSource() {} + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int SolidType; + +private: + vtkPlatonicSolidSource(const vtkPlatonicSolidSource&); // Not implemented. + void operator=(const vtkPlatonicSolidSource&); // Not implemented. + +}; + +#endif + + diff --git a/Graphics/vtkPointDataToCellData.cxx b/Graphics/vtkPointDataToCellData.cxx new file mode 100644 index 0000000..bab4a16 --- /dev/null +++ b/Graphics/vtkPointDataToCellData.cxx @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointDataToCellData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointDataToCellData.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkPointDataToCellData, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkPointDataToCellData); + +//---------------------------------------------------------------------------- +// Instantiate object so that point data is not passed to output. +vtkPointDataToCellData::vtkPointDataToCellData() +{ + this->PassPointData = 0; +} + +//---------------------------------------------------------------------------- +int vtkPointDataToCellData::RequestData( + vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, ptId; + vtkIdType numCells, numPts; + vtkPointData *inPD=input->GetPointData(); + vtkCellData *outCD=output->GetCellData(); + int maxCellSize=input->GetMaxCellSize(); + vtkIdList *cellPts; + double weight; + double *weights; + + vtkDebugMacro(<<"Mapping point data to cell data"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( (numCells=input->GetNumberOfCells()) < 1 ) + { + vtkDebugMacro(<<"No input cells!"); + return 1; + } + weights=new double[maxCellSize]; + + cellPts = vtkIdList::New(); + cellPts->Allocate(maxCellSize); + + // Pass the cell data first. The fields and attributes + // which also exist in the point data of the input will + // be over-written during CopyAllocate + output->GetCellData()->PassData(input->GetCellData()); + + // notice that inPD and outCD are vtkPointData and vtkCellData; respectively. + // It's weird, but it works. + outCD->CopyAllocate(inPD,numCells); + + int abort=0; + vtkIdType progressInterval=numCells/20 + 1; + for (cellId=0; cellId < numCells && !abort; cellId++) + { + if ( !(cellId % progressInterval) ) + { + this->UpdateProgress((double)cellId/numCells); + abort = GetAbortExecute(); + } + + input->GetCellPoints(cellId, cellPts); + numPts = cellPts->GetNumberOfIds(); + if ( numPts > 0 ) + { + weight = 1.0 / numPts; + for (ptId=0; ptId < numPts; ptId++) + { + weights[ptId] = weight; + } + outCD->InterpolatePoint(inPD, cellId, cellPts, weights); + } + } + + if ( this->PassPointData ) + { + output->GetPointData()->PassData(input->GetPointData()); + } + + cellPts->Delete(); + delete [] weights; + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPointDataToCellData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Pass Point Data: " << (this->PassPointData ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkPointDataToCellData.h b/Graphics/vtkPointDataToCellData.h new file mode 100644 index 0000000..bf1c474 --- /dev/null +++ b/Graphics/vtkPointDataToCellData.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointDataToCellData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointDataToCellData - map point data to cell data +// .SECTION Description +// vtkPointDataToCellData is a filter that transforms point data (i.e., data +// specified per point) into cell data (i.e., data specified per cell). +// The method of transformation is based on averaging the data +// values of all points defining a particular cell. Optionally, the input point +// data can be passed through to the output as well. + +// .SECTION Caveats +// This filter is an abstract filter, that is, the output is an abstract type +// (i.e., vtkDataSet). Use the convenience methods (e.g., +// vtkGetPolyDataOutput(), GetStructuredPointsOutput(), etc.) to get the type +// of output you want. + +// .SECTION See Also +// vtkPointData vtkCellData vtkCellDataToPointData + + +#ifndef __vtkPointDataToCellData_h +#define __vtkPointDataToCellData_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkPointDataToCellData : public vtkDataSetAlgorithm +{ +public: + static vtkPointDataToCellData *New(); + vtkTypeRevisionMacro(vtkPointDataToCellData,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Control whether the input point data is to be passed to the output. If + // on, then the input point data is passed through to the output; otherwise, + // only generated point data is placed into the output. + vtkSetMacro(PassPointData,int); + vtkGetMacro(PassPointData,int); + vtkBooleanMacro(PassPointData,int); + +protected: + vtkPointDataToCellData(); + ~vtkPointDataToCellData() {}; + + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + int PassPointData; +private: + vtkPointDataToCellData(const vtkPointDataToCellData&); // Not implemented. + void operator=(const vtkPointDataToCellData&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkPointSource.cxx b/Graphics/vtkPointSource.cxx new file mode 100644 index 0000000..215c845 --- /dev/null +++ b/Graphics/vtkPointSource.cxx @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointSource.h" + +#include "vtkCellArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +#include +#include + +vtkCxxRevisionMacro(vtkPointSource, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkPointSource); + +//---------------------------------------------------------------------------- +vtkPointSource::vtkPointSource(vtkIdType numPts) +{ + this->NumberOfPoints = (numPts > 0 ? numPts : 10); + + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; + + this->Radius = 0.5; + + this->Distribution = VTK_POINT_UNIFORM; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +int vtkPointSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType i; + double theta, rho, cosphi, sinphi, radius; + double x[3]; + vtkPoints *newPoints; + vtkCellArray *newVerts; + + newPoints = vtkPoints::New(); + newPoints->Allocate(this->NumberOfPoints); + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(1,this->NumberOfPoints)); + + newVerts->InsertNextCell(this->NumberOfPoints); + + if (this->Distribution == VTK_POINT_SHELL) + { // only produce points on the surface of the sphere + for (i=0; iNumberOfPoints; i++) + { + cosphi = 1 - 2*vtkMath::Random(); + sinphi = sqrt(1 - cosphi*cosphi); + radius = this->Radius * sinphi; + theta = 6.2831853 * vtkMath::Random(); + x[0] = this->Center[0] + radius*cos(theta); + x[1] = this->Center[1] + radius*sin(theta); + x[2] = this->Center[2] + this->Radius*cosphi; + newVerts->InsertCellPoint(newPoints->InsertNextPoint(x)); + } + } + else + { // uniform distribution throughout the sphere volume + for (i=0; iNumberOfPoints; i++) + { + cosphi = 1 - 2*vtkMath::Random(); + sinphi = sqrt(1 - cosphi*cosphi); + rho = this->Radius*pow(vtkMath::Random(),0.33333333); + radius = rho * sinphi; + theta = 6.2831853 * vtkMath::Random(); + x[0] = this->Center[0] + radius*cos(theta); + x[1] = this->Center[1] + radius*sin(theta); + x[2] = this->Center[2] + rho*cosphi; + newVerts->InsertCellPoint(newPoints->InsertNextPoint(x)); + } + } + // + // Update ourselves and release memory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + output->SetVerts(newVerts); + newVerts->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPointSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Points: " << this->NumberOfPoints << "\n"; + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << ")\n"; + os << indent << "Distribution: " << + ((this->Distribution == VTK_POINT_SHELL) ? "Shell\n" : "Uniform\n"); +} diff --git a/Graphics/vtkPointSource.h b/Graphics/vtkPointSource.h new file mode 100644 index 0000000..428b918 --- /dev/null +++ b/Graphics/vtkPointSource.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointSource - create a random cloud of points +// .SECTION Description +// vtkPointSource is a source object that creates a user-specified number +// of points within a specified radius about a specified center point. +// By default location of the points is random within the sphere. It is +// also possible to generate random points only on the surface of the +// sphere. + +#ifndef __vtkPointSource_h +#define __vtkPointSource_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_POINT_UNIFORM 1 +#define VTK_POINT_SHELL 0 + +class VTK_GRAPHICS_EXPORT vtkPointSource : public vtkPolyDataAlgorithm +{ +public: + static vtkPointSource *New(); + vtkTypeRevisionMacro(vtkPointSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the number of points to generate. + vtkSetClampMacro(NumberOfPoints,vtkIdType,1,VTK_LARGE_ID); + vtkGetMacro(NumberOfPoints,vtkIdType); + + // Description: + // Set the center of the point cloud. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set the radius of the point cloud. If you are + // generating a Gaussian distribution, then this is + // the standard deviation for each of x, y, and z. + vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Radius,double); + + // Description: + // Specify the distribution to use. The default is a + // uniform distribution. The shell distribution produces + // random points on the surface of the sphere, none in the interior. + vtkSetMacro(Distribution,int); + void SetDistributionToUniform() { + this->SetDistribution(VTK_POINT_UNIFORM);}; + void SetDistributionToShell() { + this->SetDistribution(VTK_POINT_SHELL);}; + vtkGetMacro(Distribution,int); + +protected: + vtkPointSource(vtkIdType numPts=10); + ~vtkPointSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkIdType NumberOfPoints; + double Center[3]; + double Radius; + int Distribution; + +private: + vtkPointSource(const vtkPointSource&); // Not implemented. + void operator=(const vtkPointSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkPointsProjectedHull.cxx b/Graphics/vtkPointsProjectedHull.cxx new file mode 100644 index 0000000..d12e28f --- /dev/null +++ b/Graphics/vtkPointsProjectedHull.cxx @@ -0,0 +1,799 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointsProjectedHull.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkPointsProjectedHull.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPointsProjectedHull, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPointsProjectedHull); + +static const int xdim=0, ydim=1, zdim=2; +static const int xmin=0, xmax=1, ymin=2, ymax=3; +static double firstPt[3]; + +// Return: >0 for P2 left of the line through P0 and P1 +// =0 for P2 on the line +// <0 for P2 right of the line +#define VTK_ISLEFT(P0, P1, P2) \ +(((P1)[0] - (P0)[0])*((P2)[1] - (P0)[1]) - ((P2)[0] - (P0)[0])*((P1)[1] - (P0)[1])) + +vtkPointsProjectedHull::vtkPointsProjectedHull() +{ + this->InitFlags(); +} +vtkPointsProjectedHull::~vtkPointsProjectedHull() +{ + this->ClearAllocations(); +} +void vtkPointsProjectedHull::Initialize() +{ + this->ClearAllocations(); + this->InitFlags(); + + vtkPoints::Initialize(); +} +void vtkPointsProjectedHull::Update() +{ + this->ClearAllocations(); + this->InitFlags(); +} +void vtkPointsProjectedHull::InitFlags() +{ + int i; + + this->Pts = NULL; + this->Npts = 0; + + for (i=0; i<3; i++) + { + this->CCWHull[i] = NULL; + this->HullSize[i] = 0; + for (int j=0; j<4; j++) + { + this->HullBBox[i][j] = 0.0; + } + } +} + +void vtkPointsProjectedHull::ClearAllocations() +{ + int i; + for (i=0; i<3; i++) + { + if (this->CCWHull[i]) + { + delete [] this->CCWHull[i]; + this->CCWHull[i] = NULL; + } + } + if (this->Pts) + { + delete [] this->Pts; + this->Pts = NULL; + } +} +#define VTK_GETCCWHULL(which, dim) \ +int vtkPointsProjectedHull::GetCCWHull##which(float *pts, int len)\ +{ \ + int i; \ + double *dpts = new double [len*2]; \ + int copypts = this->GetCCWHull##which(dpts, len); \ + for (i=0; iHullSize[dim] == 0) || (this->GetMTime() > this->HullTime[dim]))\ + { \ + GrahamScanAlgorithm(dim); \ + } \ + int copylen = (this->HullSize[dim] <= len) ? this->HullSize[dim] : len; \ + if (copylen <= 0) return 0; \ + memcpy(pts, this->CCWHull[dim], sizeof(double) * 2 * copylen); \ + return copylen; \ +} +VTK_GETCCWHULL(X, 0); +VTK_GETCCWHULL(Y, 1); +VTK_GETCCWHULL(Z, 2); + +#define VTK_GETSIZECCWHULL(which, dim) \ +int vtkPointsProjectedHull::GetSizeCCWHull##which()\ +{ \ + if ((this->HullSize[dim] == 0) || (this->GetMTime() > this->HullTime[dim]))\ + { \ + GrahamScanAlgorithm(dim); \ + } \ + return this->HullSize[dim]; \ +} +VTK_GETSIZECCWHULL(X, 0); +VTK_GETSIZECCWHULL(Y, 1); +VTK_GETSIZECCWHULL(Z, 2); + +#define VTK_RECTANGLEINTERSECTION(which, dim) \ +int vtkPointsProjectedHull::RectangleIntersection##which(vtkPoints *R) \ +{ \ + double bounds[6]; \ + R->Modified(); \ + R->GetBounds(bounds); \ + double hmin, hmax, vmin, vmax; \ + \ + hmin = (double)bounds[(dim*2+2)%6]; \ + hmax = (double)bounds[(dim*2+2)%6+1]; \ + vmin = (double)bounds[(dim*2+4)%6]; \ + vmax = (double)bounds[(dim*2+4)%6 + 1]; \ + \ + return RectangleIntersection##which(hmin, hmax, vmin, vmax); \ +} \ +int vtkPointsProjectedHull::RectangleIntersection##which(float hmin, \ + float hmax, float vmin, float vmax) \ +{ \ + return RectangleIntersection##which((double)hmin, (double)hmax, \ + (double)vmin, (double)vmax); \ +} \ +int vtkPointsProjectedHull::RectangleIntersection##which(double hmin,\ + double hmax, double vmin, double vmax) \ +{ \ + if ((this->HullSize[dim] == 0) || (this->GetMTime() > this->HullTime[dim]))\ + { \ + GrahamScanAlgorithm(dim); \ + } \ + return RectangleIntersection(hmin, hmax, vmin, vmax ,dim); \ +} +VTK_RECTANGLEINTERSECTION(X, 0); +VTK_RECTANGLEINTERSECTION(Y, 1); +VTK_RECTANGLEINTERSECTION(Z, 2); + +// Does the axis-aligned rectangle R intersect the convex polygon +// given by the counter-clockwise enumeration of it's vertices. +// +// Graphics Gems IV, Rectangle-Polygon intersection: Rectangle R +// intersects polygon P if and only if (1) the bounding box +// of P intersects R and (2) R does not lie entirely outside +// any infinite line defined by P's edges. (Outside means if +// you are walking the line in the direction given by the +// ccw orientation of the points of P, R lies completely +// in the half plane on your right.) (Ned Greene) + +int vtkPointsProjectedHull::RectangleIntersection(double hmin, double hmax, + double vmin, double vmax, int dim) +{ + if (RectangleBoundingBoxIntersection(hmin,hmax,vmin,vmax,dim) == 0) + { + return 0; + } + + if (RectangleOutside(hmin,hmax,vmin,vmax, dim) == 1) + { + return 0; + } + + return 1; +} +// +// Suppose the points are projected orthogonally in the dir +// of the positive x, y or z axis. Compute the points (2 components) +// of the convex hull of that projection, in counter clockwise order. +// +// "Right hand rule": +// +// | | | +// Z| X| Y| +// | | | +// | | | +// ------- Y -------- Z -------X +// along X-axis along Y-axis along Z-axis +// +// Algorithm comes from Graphics Gems IV +// +extern "C" +{ + int vtkPointsProjectedHullIncrVertAxis(const void *p1, const void *p2); + int vtkPointsProjectedHullCCW(const void *p1, const void *p2); +} +int vtkPointsProjectedHull::GrahamScanAlgorithm(int dir) +{ +int horizAxis = 0, vertAxis = 0; +int i,j; + + if ((this->Npts == 0) || (this->GetMTime() > this->PtsTime)) + { + GetPoints(); + } + + // I'm not sure what I'm doing here but the current code is clearly screwed + // up and doesn't handle some degenerate cases + if (this->Npts == 0) + { + return 0; + } + + switch (dir) + { + case xdim: + horizAxis = ydim; + vertAxis = zdim; + break; + + case ydim: + horizAxis = zdim; + vertAxis = xdim; + break; + + case zdim: + horizAxis = xdim; + vertAxis = ydim; + break; + } + + // Find the lowest, rightmost point in the set + + double *hullPts = new double[this->Npts*2]; + + for (i=0; iNpts; i++) + { + hullPts[i*2] = this->Pts[i*3 + horizAxis]; + hullPts[i*2 + 1] = this->Pts[i*3 + vertAxis]; + } + + qsort(hullPts, this->Npts, sizeof(double) * 2, vtkPointsProjectedHullIncrVertAxis); + + int firstId = 0; + + for (i=1; iNpts; i++) + { + if (hullPts[i*2 + 1] != hullPts[1]) break; + + if (hullPts[i*2] > hullPts[firstId*2]) + { + firstId = i; + } + } + + firstPt[0] = hullPts[firstId * 2]; // lowest, rightmost + firstPt[1] = hullPts[firstId * 2 + 1]; + + if (firstId != 0) + { + hullPts[2*firstId] = hullPts[0]; + hullPts[2*firstId + 1] = hullPts[1]; + hullPts[0] = firstPt[0]; + hullPts[1] = firstPt[1]; + } + // If there are duplicates of the first point in the + // projection, the vtkPointsProjectedHullCCW sort will fail. + + int dups = 0; + + for (j=1, i=1; j < this->Npts; j++) + { + if ( !dups && (hullPts[j*2+1] != hullPts[1])) break; + + if ( (hullPts[j*2+1] != hullPts[1]) || (hullPts[j*2] != hullPts[0])) + { + if (j > i) + { + hullPts[i*2] = hullPts[j*2]; + hullPts[i*2+1] = hullPts[j*2+1]; + } + i++; + } + else + { + dups++; + } + } + int nHullPts = this->Npts - dups; + + // I'm not sure what I'm doing here but the current code is clearly screwed + // up and doesn't handle some degenerate cases + if (nHullPts == 0) + { + return 0; + } + + // Sort in counter clockwise order the other points by the angle + // they make with the line through firstPt parallel to the + // horizontal axis. + // (For a tie: choose the point furthest from firstPt.) + // P2 makes a greater angle than P1 if it is left of the line + // formed by firstPt - P1. + + qsort(hullPts+2, nHullPts - 1, sizeof(double)*2, vtkPointsProjectedHullCCW); + + // Remove sequences of duplicate points, and remove interior + // points on the same ray from the initial point + + nHullPts = RemoveExtras(hullPts, nHullPts); + + // Now make list of points on the convex hull. + + int top = 1; + + for (i=2; i x1) + { + x1 = hullPts[2*i]; + } + + if (hullPts[2*i+1] < y0) + { + y0 = hullPts[2*i+1]; + } + else if (hullPts[2*i+1] > y1) + { + y1 = hullPts[2*i+1]; + } + } + this->HullBBox[dir][xmin] = (float)x0; + this->HullBBox[dir][xmax] = (float)x1; + this->HullBBox[dir][ymin] = (float)y0; + this->HullBBox[dir][ymax] = (float)y1; + + this->HullSize[dir] = nHullPts; + + if (this->CCWHull[dir]) + { + delete [] this->CCWHull[dir]; + } + + this->CCWHull[dir] = new double[nHullPts*2]; + + memcpy(this->CCWHull[dir], hullPts, sizeof(double) * 2 * nHullPts); + + delete [] hullPts; + + this->HullTime[dir].Modified(); + + return 0; +} +double vtkPointsProjectedHull::Distance(double *p1, double *p2) +{ + return (p1[0] - p2[0])*(p1[0] - p2[0]) + (p1[1] - p2[1])*(p1[1] - p2[1]); +} +int vtkPointsProjectedHull::RemoveExtras(double *pts, int n) +{ + int i, prev, skipMe, coord; + double where; + + prev = 0; + + for (i=1; i= 1) + { + where = VTK_ISLEFT(pts, pts + prev*2, pts + i*2); + + if (where == 0) // on same ray from first point + { + double d1 = Distance(pts, pts + prev*2); + double d2 = Distance(pts, pts + i*2); + + if (d2 > d1) // save only the most distant + { + for (coord=0; coord<2; coord++) + { + pts[prev*2+ coord] = pts[i*2+ coord]; + } + } + skipMe = 1; + } + } + + if (!skipMe) + { + prev++; + if (prev < i) + { + for (coord=0; coord<2; coord++) + { + pts[prev*2+ coord] = pts[i*2+ coord]; + } + } + } + } + + return prev+1; // size of new list +} +int vtkPointsProjectedHull::PositionInHull(double *base, double *top, double *pt) +{ +double *p1, *p2; +double where; + + p2 = top; + p1 = p2 - 2; + + // Because of the way the vertices are sorted, the new vertex + // is part of convex hull so far. But the previous vertex + // could now be inside the convex hull if the new vertex is to + // the right of the line formed by the previous two vertices. + + while (p2 > base) + { + where = VTK_ISLEFT(p1, p2, pt); + + // If vertex is to left of line, don't remove previous points + + if (where > 0) + { + break; + } + + // If vertex is to right of line, remove previous point and + // check again. If vertex is on line, previous point is + // redundant. + + p2 -= 2; // pop top of stack + p1 -= 2; + } + + // return the position in the list where the new vertex goes + + return ((p2 - base) / 2) + 1; +} +void vtkPointsProjectedHull::GetPoints() +{ + int i; + + if (this->Pts) + { + delete [] this->Pts; + } + this->Npts = this->Data->GetNumberOfTuples(); + + this->Pts = new double [this->Npts*3]; + + for (i=0; iNpts; i++) + { + this->Pts[i*3] = this->Data->GetComponent(i, 0); + this->Pts[i*3 + 1] = this->Data->GetComponent(i, 1); + this->Pts[i*3 + 2] = this->Data->GetComponent(i, 2); + } + + this->PtsTime.Modified(); +} +int vtkPointsProjectedHull:: +RectangleBoundingBoxIntersection(double hmin, double hmax, + double vmin, double vmax, int dim) +{ + float *r2Bounds = this->HullBBox[dim]; + + if ((hmin >= r2Bounds[xmax]) || + (hmax <= r2Bounds[xmin]) || + (vmin >= r2Bounds[ymax]) || + (vmax <= r2Bounds[ymin])) + { + return 0; + } + + return 1; +} + +#define sameDirection(a, b) ((((a)==0) && ((b)<0)) || (((a)>0) && ((b)>0))) + +int vtkPointsProjectedHull:: +OutsideHorizontalLine(double vmin, double vmax, + double *p0, double *, double *insidePt) +{ + if (insidePt[1] > p0[1]) + { + if (vmax <= p0[1]) + { + return 1; + } + else + { + return 0; + } + } + else + { + if (vmin >= p0[1]) + { + return 1; + } + else + { + return 0; + } + } +} +int vtkPointsProjectedHull:: +OutsideVerticalLine(double hmin, double hmax, + double *p0, double *, double *insidePt) +{ + if (insidePt[0] > p0[0]) + { + if (hmax <= p0[0]) + { + return 1; + } + else + { + return 0; + } + } + else + { + if (hmin >= p0[0]) + { + return 1; + } + else + { + return 0; + } + } +} +int vtkPointsProjectedHull:: +OutsideLine(double hmin, double hmax, double vmin, double vmax, + double *p0, double *p1, double *insidePt) +{ + int i; + + if ((p1[1] - p0[1]) == 0) + { + return OutsideHorizontalLine(vmin, vmax, p0, p1, insidePt); + } + + if ((p1[0] - p0[0]) == 0) + { + return OutsideVerticalLine(hmin, hmax, p0, p1, insidePt); + } + + // Are any of the points of the rectangle in the same half-plane as the + // inside point? + + double ip = VTK_ISLEFT(p0, p1, insidePt); + double rp; + + double pts[4][2]; + + pts[0][0] = hmin; pts[0][1] = vmin; + pts[1][0] = hmin; pts[1][1] = vmax; + pts[2][0] = hmax; pts[2][1] = vmax; + pts[3][0] = hmax; pts[3][1] = vmin; + + for (i=0; i < 4; i++) + { + rp = VTK_ISLEFT(p0, p1, pts[i]); + + if ( ((rp < 0) && (ip < 0)) || ((rp > 0) && (ip > 0)) ) + { + return 0; + } + } + + return 1; +} +int vtkPointsProjectedHull::RectangleOutside(double hmin, double hmax, + double vmin, double vmax, int dir) +{ + int i; + + int npts = this->HullSize[dir]; + + if (npts == 2) + { + return this->RectangleOutside1DPolygon(hmin, hmax, vmin, vmax, dir); + } + + // a representative point inside the polygon + + double *insidePt = new double[2]; + + insidePt[0] = this->CCWHull[dir][0]; + insidePt[1] = this->CCWHull[dir][1]; + + insidePt[0] += this->CCWHull[dir][4]; + insidePt[1] += this->CCWHull[dir][5]; + + if (npts == 3) + { + insidePt[0] += this->CCWHull[dir][2]; + insidePt[1] += this->CCWHull[dir][3]; + + insidePt[0] /= 3; + insidePt[1] /= 3; + } + else + { + insidePt[0] /= 2; + insidePt[1] /= 2; + } + + // For each infinite line given by the line segments of the + // polygon, determine if rectangle is entirely outside that line. + // If so, it must be outside the polygon. + + for (i=0; i < npts-1; i++) + { + if (OutsideLine(hmin,hmax,vmin,vmax, + this->CCWHull[dir] + 2*i, + this->CCWHull[dir] + 2*i + 2, + insidePt)) + { + return 1; + } + } + + delete [] insidePt; + + return 0; +} +int vtkPointsProjectedHull::RectangleOutside1DPolygon(double hmin, double hmax, + double vmin, double vmax, int dir) +{ + int i; + + double *p0 = this->CCWHull[dir]; + double *p1 = this->CCWHull[dir] + 2; + + double pts[4][2]; + + pts[0][0] = hmin; pts[0][1] = vmin; + pts[1][0] = hmin; pts[1][1] = vmax; + pts[2][0] = hmax; pts[2][1] = vmax; + pts[3][0] = hmax; pts[3][1] = vmin; + + double side; + double reference=0.0; + + for (i=0; i<4; i++) + { + side = VTK_ISLEFT(p0, p1,pts[i]); + + if (reference != 0.0) + { + if (side != reference) + { + return 0; // two points are on opposite sides of the line + } + } + else if (side != 0.0) + { + reference = side; + } + } + + // all four vertices are either on the line or on the same side + // of the line + + return 1; +} + +// The sort functions + +extern "C" +{ + int vtkPointsProjectedHullIncrVertAxis(const void *p1, const void *p2) + { + double *a, *b; + + a = (double *)p1; + b = (double *)p2; + + if (a[1] < b[1]) + { + return -1; + } + else if (a[1] == b[1]) + { + return 0; + } + else + { + return 1; + } + } + + int vtkPointsProjectedHullCCW(const void *p1, const void *p2) + { + double *a, *b; + double val; + + a = (double *)p1; + b = (double *)p2; + + // sort in counter clockwise order from first point + + val = VTK_ISLEFT(firstPt, a, b); + + if (val < 0) + { + return 1; // b is right of line firstPt->a + } + else if (val == 0) + { + return 0; // b is on line firstPt->a + } + else + { + return -1; // b is left of line firstPt->a + } + } +} + +void vtkPointsProjectedHull::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Pts: " << this->Pts << endl; + os << indent << "Npts: " << this->Npts << endl; + os << indent << "PtsTime: " << this->PtsTime << endl; + + os << indent << "CCWHull X: " << this->CCWHull[0] << endl; + os << indent << "HullBBox X: [" ; + os << this->HullBBox[0][0] << ", " << this->HullBBox[0][1] << "] ["; + os << this->HullBBox[0][2] << ", " << this->HullBBox[0][3] << "] "; + os << indent << "HullSize X: " << this->HullSize[0] << endl; + os << indent << "HullTime X: " << this->HullTime[0] << endl; + + os << indent << "CCWHull Y: " << this->CCWHull[1] << endl; + os << indent << "HullBBox Y: [" ; + os << this->HullBBox[1][0] << ", " << this->HullBBox[1][1] << "] ["; + os << this->HullBBox[1][2] << ", " << this->HullBBox[1][3] << "] "; + os << indent << "HullSize Y: " << this->HullSize[1] << endl; + os << indent << "HullTime Y: " << this->HullTime[1] << endl; + + os << indent << "CCWHull Z: " << this->CCWHull[2] << endl; + os << indent << "HullBBox Z: [" ; + os << this->HullBBox[2][0] << ", " << this->HullBBox[2][1] << "] ["; + os << this->HullBBox[2][2] << ", " << this->HullBBox[2][3] << "] "; + os << indent << "HullSize Z: " << this->HullSize[2] << endl; + os << indent << "HullTime Z: " << this->HullTime[2] << endl; +} diff --git a/Graphics/vtkPointsProjectedHull.h b/Graphics/vtkPointsProjectedHull.h new file mode 100644 index 0000000..050fbfe --- /dev/null +++ b/Graphics/vtkPointsProjectedHull.h @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointsProjectedHull.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkPointsProjectedHull - the convex hull of the orthogonal +// projection of the vtkPoints in the 3 coordinate directions +// .SECTION Description +// a subclass of vtkPoints, it maintains the counter clockwise +// convex hull of the points (projected orthogonally in the +// three coordinate directions) and has a method to +// test for intersection of that hull with an axis aligned +// rectangle. This is used for intersection tests of 3D volumes. + +#ifndef __vtkPointsProjectedHull_h +#define __vtkPointsProjectedHull_h + +#include "vtkPoints.h" + +class VTK_GRAPHICS_EXPORT vtkPointsProjectedHull : public vtkPoints +{ + vtkTypeRevisionMacro(vtkPointsProjectedHull, vtkPoints); + +public: + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkPointsProjectedHull *New(); + + // Description: Project the box R along the positive X axis and + // determine whether the resulting rectangle intersects the + // convex hull of the projection of the points along that axis. + + int RectangleIntersectionX(vtkPoints *R); + + // Description: Determine whether the given rectangle intersects + // the convex hull of the projection of the points along the + // positive X-axis. + + int RectangleIntersectionX(float ymin, float ymax, float zmin, float zmax); + int RectangleIntersectionX(double ymin, double ymax, double zmin, double zmax); + + // Description: Determine if a rectangle intersects the convex hull + // of the parallel projection along the Y axis of the points + + int RectangleIntersectionY(vtkPoints *R); + + // Description: Determine whether the given rectangle intersects + // the convex hull of the projection of the points along the + // positive Y-axis. + + int RectangleIntersectionY(float zmin, float zmax, float xmin, float xmax); + int RectangleIntersectionY(double zmin, double zmax, double xmin, double xmax); + + // Description: Determine if a rectangle intersects the convex hull + // of the parallel projection along the Z axis of the points + + int RectangleIntersectionZ(vtkPoints *R); + + // Description: Determine whether the given rectangle intersects + // the convex hull of the projection of the points along the + // positive Z-axis. + + int RectangleIntersectionZ(float xmin, float xmax, float ymin, float ymax); + int RectangleIntersectionZ(double xmin, double xmax, double ymin, double ymax); + + // Description: + // Returns the coordinates (y,z) of the points in the convex hull + // of the projection of the points down the positive x-axis. pts has + // storage for len*2 values. + + int GetCCWHullX(float *pts, int len); + int GetCCWHullX(double *pts, int len); + + // Description: + // Returns the coordinates (z, x) of the points in the convex hull + // of the projection of the points down the positive y-axis. pts has + // storage for len*2 values. + + int GetCCWHullY(float *pts, int len); + int GetCCWHullY(double *pts, int len); + + // Description: + // Returns the coordinates (x, y) of the points in the convex hull + // of the projection of the points down the positive z-axis. pts has + // storage for len*2 values. + + int GetCCWHullZ(float *pts, int len); + int GetCCWHullZ(double *pts, int len); + + // Description: + // Returns the number of points in the convex hull of the projection + // of the points down the positive x-axis + + int GetSizeCCWHullX(); + + // Description: + // Returns the number of points in the convex hull of the projection + // of the points down the positive y-axis + + int GetSizeCCWHullY(); + + // Description: + // Returns the number of points in the convex hull of the projection + // of the points down the positive z-axis + + int GetSizeCCWHullZ(); + + void Initialize(); + void Reset(){this->Initialize();} + + // Description: + // Forces recalculation of convex hulls, use this if + // you delete/add points + + void Update(); + +protected: + + vtkPointsProjectedHull(); + ~vtkPointsProjectedHull(); + +private: + + int RectangleIntersection(double hmin, double hmax, + double vmin, double vmax, int direction); + int GrahamScanAlgorithm(int direction); + void GetPoints(); + int RectangleBoundingBoxIntersection(double hmin, double hmax, + double vmin, double vmax, int direction); + int RectangleOutside(double hmin, double hmax, + double vmin, double vmax, int direction); + + int RectangleOutside1DPolygon(double hmin, double hmax, + double vmin, double vmax, int dir); + + void InitFlags(); + void ClearAllocations(); + + + static int RemoveExtras(double *pts, int n); + static double Distance(double *p1, double *p2); + static int PositionInHull(double *base, double *top, double *pt); + static int OutsideLine(double hmin, double hmax, + double vmin, double vmax, double *p0, double *p1, double *insidePt); + static int OutsideHorizontalLine(double vmin, double vmax, + double *p0, double *p1, double *insidePt); + static int OutsideVerticalLine(double hmin, double hmax, double *p0, + double *p1, double *insidePt); + + double *Pts; + int Npts; + vtkTimeStamp PtsTime; + + double *CCWHull[3]; + float HullBBox[3][4]; + int HullSize[3]; + vtkTimeStamp HullTime[3]; + + vtkPointsProjectedHull(const vtkPointsProjectedHull&); // Not implemented + void operator=(const vtkPointsProjectedHull&); // Not implemented +}; +#endif + + diff --git a/Graphics/vtkPolyDataConnectivityFilter.cxx b/Graphics/vtkPolyDataConnectivityFilter.cxx new file mode 100644 index 0000000..d69deff --- /dev/null +++ b/Graphics/vtkPolyDataConnectivityFilter.cxx @@ -0,0 +1,570 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataConnectivityFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataConnectivityFilter.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkPolyDataConnectivityFilter, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkPolyDataConnectivityFilter); + +// Construct with default extraction mode to extract largest regions. +vtkPolyDataConnectivityFilter::vtkPolyDataConnectivityFilter() +{ + this->RegionSizes = vtkIdTypeArray::New(); + this->ExtractionMode = VTK_EXTRACT_LARGEST_REGION; + this->ColorRegions = 0; + + this->ScalarConnectivity = 0; + this->ScalarRange[0] = 0.0; + this->ScalarRange[1] = 1.0; + + this->ClosestPoint[0] = this->ClosestPoint[1] = this->ClosestPoint[2] = 0.0; + + this->CellScalars = vtkFloatArray::New(); + this->CellScalars->Allocate(8); + + this->NeighborCellPointIds = vtkIdList::New(); + this->NeighborCellPointIds->Allocate(8); + + this->Seeds = vtkIdList::New(); + this->SpecifiedRegionIds = vtkIdList::New(); +} + +vtkPolyDataConnectivityFilter::~vtkPolyDataConnectivityFilter() +{ + this->RegionSizes->Delete(); + this->CellScalars->Delete(); + this->NeighborCellPointIds->Delete(); + this->Seeds->Delete(); + this->SpecifiedRegionIds->Delete(); +} + +int vtkPolyDataConnectivityFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, newCellId, i, pt; + int j; + vtkIdType numPts, numCells; + vtkPoints *inPts; + vtkPoints *newPts; + vtkIdType *cells, *pts, npts, id, n; + unsigned short ncells; + vtkIdType maxCellsInRegion; + int largestRegionId = 0; + vtkPointData *pd=input->GetPointData(), *outputPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outputCD=output->GetCellData(); + + vtkDebugMacro(<<"Executing polygon connectivity filter."); + + // Check input/allocate storage + // + inPts = input->GetPoints(); + + if (inPts == NULL) + { + vtkErrorMacro("No points!"); + return 1; + } + + numPts = inPts->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + + if ( numPts < 1 || numCells < 1 ) + { + vtkDebugMacro(<<"No data to connect!"); + return 1; + } + + // See whether to consider scalar connectivity + // + this->InScalars = input->GetPointData()->GetScalars(); + if ( !this->ScalarConnectivity ) + { + this->InScalars = NULL; + } + else + { + if ( this->ScalarRange[1] < this->ScalarRange[0] ) + { + this->ScalarRange[1] = this->ScalarRange[0]; + } + } + + // Build cell structure + // + this->Mesh = vtkPolyData::New(); + this->Mesh->CopyStructure(input); + this->Mesh->BuildLinks(); + this->UpdateProgress(0.10); + + // Initialize. Keep track of points and cells visited. + // + this->RegionSizes->Reset(); + this->Visited = new int[numCells]; + for ( i=0; i < numCells; i++ ) + { + this->Visited[i] = -1; + } + this->PointMap = new vtkIdType[numPts]; + for ( i=0; i < numPts; i++ ) + { + this->PointMap[i] = -1; + } + + this->NewScalars = vtkFloatArray::New(); + this->NewScalars->SetNumberOfTuples(numPts); + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + + // Traverse all cells marking those visited. Each new search + // starts a new connected region. Connected region grows + // using a connected wave propagation. + // + this->Wave = vtkIdList::New(); + this->Wave->Allocate(numPts/4+1,numPts); + this->Wave2 = vtkIdList::New(); + this->Wave2->Allocate(numPts/4+1,numPts); + + this->PointNumber = 0; + this->RegionNumber = 0; + maxCellsInRegion = 0; + + this->CellIds = vtkIdList::New(); + this->CellIds->Allocate(8, VTK_CELL_SIZE); + this->PointIds = vtkIdList::New(); + this->PointIds->Allocate(8, VTK_CELL_SIZE); + + if ( this->ExtractionMode != VTK_EXTRACT_POINT_SEEDED_REGIONS && + this->ExtractionMode != VTK_EXTRACT_CELL_SEEDED_REGIONS && + this->ExtractionMode != VTK_EXTRACT_CLOSEST_POINT_REGION ) + { //visit all cells marking with region number + for (cellId=0; cellId < numCells; cellId++) + { + if ( cellId && !(cellId % 5000) ) + { + this->UpdateProgress (0.1 + 0.8*cellId/numCells); + } + + if ( this->Visited[cellId] < 0 ) + { + this->NumCellsInRegion = 0; + this->Wave->InsertNextId(cellId); + this->TraverseAndMark (); + + if ( this->NumCellsInRegion > maxCellsInRegion ) + { + maxCellsInRegion = this->NumCellsInRegion; + largestRegionId = this->RegionNumber; + } + + this->RegionSizes->InsertValue(this->RegionNumber++, + this->NumCellsInRegion); + this->Wave->Reset(); + this->Wave2->Reset(); + } + } + } + else // regions have been seeded, everything considered in same region + { + this->NumCellsInRegion = 0; + + if ( this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS ) + { + for (i=0; i < this->Seeds->GetNumberOfIds(); i++) + { + pt = this->Seeds->GetId(i); + if ( pt >= 0 ) + { + this->Mesh->GetPointCells(pt,ncells,cells); + for (j=0; j < ncells; j++) + { + this->Wave->InsertNextId(cells[j]); + } + } + } + } + else if ( this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS ) + { + for (i=0; i < this->Seeds->GetNumberOfIds(); i++) + { + cellId = this->Seeds->GetId(i); + if ( cellId >= 0 ) + { + this->Wave->InsertNextId(cellId); + } + } + } + else if ( this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION ) + {//loop over points, find closest one + double minDist2, dist2, x[3]; + int minId = 0; + for (minDist2=VTK_DOUBLE_MAX, i=0; iGetPoint(i,x); + dist2 = vtkMath::Distance2BetweenPoints(x,this->ClosestPoint); + if ( dist2 < minDist2 ) + { + minId = i; + minDist2 = dist2; + } + } + this->Mesh->GetPointCells(minId,ncells,cells); + for (j=0; j < ncells; j++) + { + this->Wave->InsertNextId(cells[j]); + } + } + this->UpdateProgress (0.5); + + //mark all seeded regions + this->TraverseAndMark (); + this->RegionSizes->InsertValue(this->RegionNumber,this->NumCellsInRegion); + this->UpdateProgress (0.9); + }//else extracted seeded cells + + vtkDebugMacro (<<"Extracted " << this->RegionNumber << " region(s)"); + this->Wave->Delete(); + this->Wave2->Delete(); + + // Now that points and cells have been marked, traverse these lists pulling + // everything that has been visited. + // + //Pass through point data that has been visited + pd = input->GetPointData(); + if ( this->ColorRegions ) + { + outputPD->CopyScalarsOff(); + } + outputPD->CopyAllocate(pd); + outputCD->CopyAllocate(cd); + + for (i=0; i < numPts; i++) + { + if ( this->PointMap[i] > -1 ) + { + newPts->InsertPoint(this->PointMap[i],inPts->GetPoint(i)); + outputPD->CopyData(pd,i,this->PointMap[i]); + } + } + + // if coloring regions; send down new scalar data + if ( this->ColorRegions ) + { + int idx = outputPD->AddArray(this->NewScalars); + outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + } + this->NewScalars->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + + // Create output cells. Have to allocate storage first. + // + if ( (n=input->GetVerts()->GetNumberOfCells()) > 0 ) + { + vtkCellArray *newVerts = vtkCellArray::New(); + newVerts->Allocate(n,n); + output->SetVerts(newVerts); + newVerts->Delete(); + } + if ( (n=input->GetLines()->GetNumberOfCells()) > 0 ) + { + vtkCellArray *newLines = vtkCellArray::New(); + newLines->Allocate(2*n,n); + output->SetLines(newLines); + newLines->Delete(); + } + if ( (n=input->GetPolys()->GetNumberOfCells()) > 0 ) + { + vtkCellArray *newPolys = vtkCellArray::New(); + newPolys->Allocate(3*n,n); + output->SetPolys(newPolys); + newPolys->Delete(); + } + if ( (n=input->GetStrips()->GetNumberOfCells()) > 0 ) + { + vtkCellArray *newStrips = vtkCellArray::New(); + newStrips->Allocate(5*n,n); + output->SetStrips(newStrips); + newStrips->Delete(); + } + + if ( this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS || + this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS || + this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION || + this->ExtractionMode == VTK_EXTRACT_ALL_REGIONS) + { // extract any cell that's been visited + for (cellId=0; cellId < numCells; cellId++) + { + if ( this->Visited[cellId] >= 0 ) + { + this->Mesh->GetCellPoints(cellId, npts, pts); + this->PointIds->Reset(); + for (i=0; i < npts; i++) + { + id = this->PointMap[pts[i]]; + this->PointIds->InsertId(i,id); + } + newCellId = output->InsertNextCell(this->Mesh->GetCellType(cellId), + this->PointIds); + outputCD->CopyData(cd,cellId,newCellId); + } + } + } + else if ( this->ExtractionMode == VTK_EXTRACT_SPECIFIED_REGIONS ) + { + for (cellId=0; cellId < numCells; cellId++) + { + int inReg, regionId; + if ( (regionId=this->Visited[cellId]) >= 0 ) + { + for (inReg=0,i=0; iSpecifiedRegionIds->GetNumberOfIds(); i++) + { + if ( regionId == this->SpecifiedRegionIds->GetId(i) ) + { + inReg = 1; + break; + } + } + if ( inReg ) + { + this->Mesh->GetCellPoints(cellId, npts, pts); + this->PointIds->Reset (); + for (i=0; i < npts; i++) + { + id = this->PointMap[pts[i]]; + this->PointIds->InsertId(i,id); + } + newCellId = output->InsertNextCell(this->Mesh->GetCellType(cellId), + this->PointIds); + outputCD->CopyData(cd,cellId,newCellId); + } + } + } + } + else //extract largest region + { + for (cellId=0; cellId < numCells; cellId++) + { + if ( this->Visited[cellId] == largestRegionId ) + { + this->Mesh->GetCellPoints(cellId, npts, pts); + this->PointIds->Reset (); + for (i=0; i < npts; i++) + { + id = this->PointMap[pts[i]]; + this->PointIds->InsertId(i,id); + } + newCellId = output->InsertNextCell(this->Mesh->GetCellType(cellId), + this->PointIds); + outputCD->CopyData(cd,cellId,newCellId); + } + } + } + + delete [] this->Visited; + delete [] this->PointMap; + this->Mesh->Delete(); + output->Squeeze(); + this->CellIds->Delete(); + this->PointIds->Delete(); + + int num = this->GetNumberOfExtractedRegions(); + vtkIdType count = 0; + + for (int ii = 0; ii < num; ii++) + { + count += this->RegionSizes->GetValue (ii); + } + vtkDebugMacro (<< "Total # of cells accounted for: " << count); + vtkDebugMacro (<<"Extracted " << output->GetNumberOfCells() << " cells"); + + return 1; +} + +// Mark current cell as visited and assign region number. Note: +// traversal occurs across shared vertices. +// +void vtkPolyDataConnectivityFilter::TraverseAndMark () +{ + vtkIdType cellId, ptId, numIds, i; + int j, k; + vtkIdType *pts, *cells, npts; + vtkIdList *tmpWave; + unsigned short ncells; + + while ( (numIds=this->Wave->GetNumberOfIds()) > 0 ) + { + for ( i=0; i < numIds; i++ ) + { + cellId = this->Wave->GetId(i); + if ( this->Visited[cellId] < 0 ) + { + this->Visited[cellId] = this->RegionNumber; + this->NumCellsInRegion++; + this->Mesh->GetCellPoints(cellId, npts, pts); + + for (j=0; j < npts; j++) + { + if ( this->PointMap[ptId=pts[j]] < 0 ) + { + this->PointMap[ptId] = this->PointNumber++; + this->NewScalars->SetComponent(this->PointMap[ptId], 0, + this->RegionNumber); + } + + this->Mesh->GetPointCells(ptId,ncells,cells); + + // check connectivity criterion (geometric + scalar) + for (k=0; k < ncells; k++) + { + cellId = cells[k]; + if ( this->InScalars ) + { + int numScalars, ii; + double s, range[2]; + + this->Mesh->GetCellPoints(cellId, this->NeighborCellPointIds); + numScalars = this->NeighborCellPointIds->GetNumberOfIds(); + this->CellScalars->SetNumberOfTuples(numScalars); + this->InScalars->GetTuples(this->NeighborCellPointIds, + this->CellScalars); + range[0] = VTK_DOUBLE_MAX; range[1] = -VTK_DOUBLE_MAX; + for (ii=0; ii < numScalars; ii++) + { + s = this->CellScalars->GetComponent(ii, 0); + if ( s < range[0] ) + { + range[0] = s; + } + if ( s > range[1] ) + { + range[1] = s; + } + } + if ( range[1] >= this->ScalarRange[0] && + range[0] <= this->ScalarRange[1] ) + { + this->Wave2->InsertNextId(cellId); + } + } + else + { + this->Wave2->InsertNextId(cellId); + } + }//for all cells using this point + }//for all points of this cell + }//if cell not yet visited + }//for all cells in this wave + + tmpWave = this->Wave; + this->Wave = this->Wave2; + this->Wave2 = tmpWave; + tmpWave->Reset(); + } //while wave is not empty + + return; +} + +// Obtain the number of connected regions. +int vtkPolyDataConnectivityFilter::GetNumberOfExtractedRegions() +{ + return this->RegionSizes->GetMaxId() + 1; +} + +// Initialize list of point ids/cell ids used to seed regions. +void vtkPolyDataConnectivityFilter::InitializeSeedList() +{ + this->Modified(); + this->Seeds->Reset(); +} + +// Add a seed id (point or cell id). Note: ids are 0-offset. +void vtkPolyDataConnectivityFilter::AddSeed(int id) +{ + this->Modified(); + this->Seeds->InsertNextId(id); +} + +// Delete a seed id (point or cell id). Note: ids are 0-offset. +void vtkPolyDataConnectivityFilter::DeleteSeed(int id) +{ + this->Modified(); + this->Seeds->DeleteId(id); +} + +// Initialize list of region ids to extract. +void vtkPolyDataConnectivityFilter::InitializeSpecifiedRegionList() +{ + this->Modified(); + this->SpecifiedRegionIds->Reset(); +} + +// Add a region id to extract. Note: ids are 0-offset. +void vtkPolyDataConnectivityFilter::AddSpecifiedRegion(int id) +{ + this->Modified(); + this->SpecifiedRegionIds->InsertNextId(id); +} + +// Delete a region id to extract. Note: ids are 0-offset. +void vtkPolyDataConnectivityFilter::DeleteSpecifiedRegion(int id) +{ + this->Modified(); + this->SpecifiedRegionIds->DeleteId(id); +} + +void vtkPolyDataConnectivityFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Extraction Mode: "; + os << this->GetExtractionModeAsString() << "\n"; + + os << indent << "Closest Point: (" << this->ClosestPoint[0] << ", " + << this->ClosestPoint[1] << ", " << this->ClosestPoint[2] << ")\n"; + + os << indent << "Color Regions: " << (this->ColorRegions ? "On\n" : "Off\n"); + + os << indent << "Scalar Connectivity: " + << (this->ScalarConnectivity ? "On\n" : "Off\n"); + + double *range = this->GetScalarRange(); + os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n"; +} + diff --git a/Graphics/vtkPolyDataConnectivityFilter.h b/Graphics/vtkPolyDataConnectivityFilter.h new file mode 100644 index 0000000..d77afbe --- /dev/null +++ b/Graphics/vtkPolyDataConnectivityFilter.h @@ -0,0 +1,212 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataConnectivityFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataConnectivityFilter - extract polygonal data based on geometric connectivity +// .SECTION Description +// vtkPolyDataConnectivityFilter is a filter that extracts cells that +// share common points and/or satisfy a scalar threshold +// criterion. (Such a group of cells is called a region.) The filter +// works in one of six ways: 1) extract the largest connected region +// in the dataset; 2) extract specified region numbers; 3) extract all +// regions sharing specified point ids; 4) extract all regions sharing +// specified cell ids; 5) extract the region closest to the specified +// point; or 6) extract all regions (used to color regions). +// +// This filter is specialized for polygonal data. This means it runs a bit +// faster and is easier to construct visualization networks that process +// polygonal data. +// +// The behavior of vtkPolyDataConnectivityFilter can be modified by turning +// on the boolean ivar ScalarConnectivity. If this flag is on, the +// connectivity algorithm is modified so that cells are considered connected +// only if 1) they are geometrically connected (share a point) and 2) the +// scalar values of one of the cell's points falls in the scalar range +// specified. This use of ScalarConnectivity is particularly useful for +// selecting cells for later processing. + +// .SECTION See Also +// vtkConnectivityFilter + +#ifndef __vtkPolyDataConnectivityFilter_h +#define __vtkPolyDataConnectivityFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_EXTRACT_POINT_SEEDED_REGIONS 1 +#define VTK_EXTRACT_CELL_SEEDED_REGIONS 2 +#define VTK_EXTRACT_SPECIFIED_REGIONS 3 +#define VTK_EXTRACT_LARGEST_REGION 4 +#define VTK_EXTRACT_ALL_REGIONS 5 +#define VTK_EXTRACT_CLOSEST_POINT_REGION 6 + +class vtkDataArray; +class vtkIdList; +class vtkIdTypeArray; + +class VTK_GRAPHICS_EXPORT vtkPolyDataConnectivityFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkPolyDataConnectivityFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with default extraction mode to extract largest regions. + static vtkPolyDataConnectivityFilter *New(); + + // Description: + // Turn on/off connectivity based on scalar value. If on, cells are connected + // only if they share points AND one of the cells scalar values falls in the + // scalar range specified. + vtkSetMacro(ScalarConnectivity,int); + vtkGetMacro(ScalarConnectivity,int); + vtkBooleanMacro(ScalarConnectivity,int); + + // Description: + // Set the scalar range to use to extract cells based on scalar connectivity. + vtkSetVector2Macro(ScalarRange,double); + vtkGetVector2Macro(ScalarRange,double); + + // Description: + // Control the extraction of connected surfaces. + vtkSetClampMacro(ExtractionMode,int, + VTK_EXTRACT_POINT_SEEDED_REGIONS, + VTK_EXTRACT_CLOSEST_POINT_REGION); + vtkGetMacro(ExtractionMode,int); + void SetExtractionModeToPointSeededRegions() + {this->SetExtractionMode(VTK_EXTRACT_POINT_SEEDED_REGIONS);}; + void SetExtractionModeToCellSeededRegions() + {this->SetExtractionMode(VTK_EXTRACT_CELL_SEEDED_REGIONS);}; + void SetExtractionModeToLargestRegion() + {this->SetExtractionMode(VTK_EXTRACT_LARGEST_REGION);}; + void SetExtractionModeToSpecifiedRegions() + {this->SetExtractionMode(VTK_EXTRACT_SPECIFIED_REGIONS);}; + void SetExtractionModeToClosestPointRegion() + {this->SetExtractionMode(VTK_EXTRACT_CLOSEST_POINT_REGION);}; + void SetExtractionModeToAllRegions() + {this->SetExtractionMode(VTK_EXTRACT_ALL_REGIONS);}; + const char *GetExtractionModeAsString(); + + // Description: + // Initialize list of point ids/cell ids used to seed regions. + void InitializeSeedList(); + + // Description: + // Add a seed id (point or cell id). Note: ids are 0-offset. + void AddSeed(int id); + + // Description: + // Delete a seed id (point or cell id). Note: ids are 0-offset. + void DeleteSeed(int id); + + // Description: + // Initialize list of region ids to extract. + void InitializeSpecifiedRegionList(); + + // Description: + // Add a region id to extract. Note: ids are 0-offset. + void AddSpecifiedRegion(int id); + + // Description: + // Delete a region id to extract. Note: ids are 0-offset. + void DeleteSpecifiedRegion(int id); + + // Description: + // Use to specify x-y-z point coordinates when extracting the region + // closest to a specified point. + vtkSetVector3Macro(ClosestPoint,double); + vtkGetVectorMacro(ClosestPoint,double,3); + + // Description: + // Obtain the number of connected regions. + int GetNumberOfExtractedRegions(); + + // Description: + // Turn on/off the coloring of connected regions. + vtkSetMacro(ColorRegions,int); + vtkGetMacro(ColorRegions,int); + vtkBooleanMacro(ColorRegions,int); + +protected: + vtkPolyDataConnectivityFilter(); + ~vtkPolyDataConnectivityFilter(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int ColorRegions; //boolean turns on/off scalar gen for separate regions + int ExtractionMode; //how to extract regions + vtkIdList *Seeds; //id's of points or cells used to seed regions + vtkIdList *SpecifiedRegionIds; //regions specified for extraction + vtkIdTypeArray *RegionSizes; //size (in cells) of each region extracted + + double ClosestPoint[3]; + + int ScalarConnectivity; + double ScalarRange[2]; + + void TraverseAndMark(); + +private: + // used to support algorithm execution + vtkDataArray *CellScalars; + vtkIdList *NeighborCellPointIds; + int *Visited; + vtkIdType *PointMap; + vtkDataArray *NewScalars; + int RegionNumber; + vtkIdType PointNumber; + vtkIdType NumCellsInRegion; + vtkDataArray *InScalars; + vtkPolyData *Mesh; + vtkIdList *Wave; + vtkIdList *Wave2; + vtkIdList *PointIds; + vtkIdList *CellIds; +private: + vtkPolyDataConnectivityFilter(const vtkPolyDataConnectivityFilter&); // Not implemented. + void operator=(const vtkPolyDataConnectivityFilter&); // Not implemented. +}; + +// Description: +// Return the method of extraction as a string. +inline const char *vtkPolyDataConnectivityFilter::GetExtractionModeAsString(void) +{ + if ( this->ExtractionMode == VTK_EXTRACT_POINT_SEEDED_REGIONS ) + { + return "ExtractPointSeededRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_CELL_SEEDED_REGIONS ) + { + return "ExtractCellSeededRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_SPECIFIED_REGIONS ) + { + return "ExtractSpecifiedRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_ALL_REGIONS ) + { + return "ExtractAllRegions"; + } + else if ( this->ExtractionMode == VTK_EXTRACT_CLOSEST_POINT_REGION ) + { + return "ExtractClosestPointRegion"; + } + else + { + return "ExtractLargestRegion"; + } +} + + +#endif diff --git a/Graphics/vtkPolyDataNormals.cxx b/Graphics/vtkPolyDataNormals.cxx new file mode 100644 index 0000000..b6799f2 --- /dev/null +++ b/Graphics/vtkPolyDataNormals.cxx @@ -0,0 +1,734 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataNormals.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataNormals.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkTriangleStrip.h" +#include "vtkPriorityQueue.h" + +vtkCxxRevisionMacro(vtkPolyDataNormals, "$Revision: 1.66 $"); +vtkStandardNewMacro(vtkPolyDataNormals); + +// Construct with feature angle=30, splitting and consistency turned on, +// flipNormals turned off, and non-manifold traversal turned on. +vtkPolyDataNormals::vtkPolyDataNormals() +{ + this->FeatureAngle = 30.0; + this->Splitting = 1; + this->Consistency = 1; + this->FlipNormals = 0; + this->ComputePointNormals = 1; + this->ComputeCellNormals = 0; + this->NonManifoldTraversal = 1; + this->AutoOrientNormals = 0; + // some internal data + this->NumFlips = 0; +} + +#define VTK_CELL_NOT_VISITED 0 +#define VTK_CELL_VISITED 1 + +// Generate normals for polygon meshes +int vtkPolyDataNormals::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int j; + vtkIdType npts = 0; + vtkIdType i; + vtkIdType *pts = 0; + vtkIdType numNewPts; + double polyNormal[3], vertNormal[3], length; + double flipDirection=1.0; + vtkIdType numPolys, numStrips; + vtkIdType cellId; + vtkIdType numPts; + vtkPoints *inPts; + vtkCellArray *inPolys, *inStrips, *polys; + vtkPoints *newPts = NULL; + vtkFloatArray *newNormals; + vtkPointData *pd, *outPD; + vtkCellData *outCD; + double n[3]; + vtkCellArray *newPolys; + vtkIdType ptId, oldId; + + vtkDebugMacro(<<"Generating surface normals"); + + numPolys=input->GetNumberOfPolys(); + numStrips=input->GetNumberOfStrips(); + if ( (numPts=input->GetNumberOfPoints()) < 1 ) + { + vtkErrorMacro(<<"No data to generate normals for!"); + return 1; + } + + + // If there is nothing to do, pass the data through + if ( this->ComputePointNormals == 0 && this->ComputeCellNormals == 0 || + (numPolys < 1 && numStrips < 1) ) + { //don't do anything! pass data through + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + return 1; + } + output->GetCellData()->PassData(input->GetCellData()); + output->SetFieldData(input->GetFieldData()); + + // Load data into cell structure. We need two copies: one is a + // non-writable mesh used to perform topological queries. The other + // is used to write into and modify the connectivity of the mesh. + // + inPts = input->GetPoints(); + inPolys = input->GetPolys(); + inStrips = input->GetStrips(); + + this->OldMesh = vtkPolyData::New(); + this->OldMesh->SetPoints(inPts); + if ( numStrips > 0 ) //have to decompose strips into triangles + { + if ( numPolys > 0 ) + { + polys = vtkCellArray::New(); + polys->DeepCopy(inPolys); + } + else + { + polys = vtkCellArray::New(); + polys->Allocate(polys->EstimateSize(numStrips,5)); + } + for ( inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + vtkTriangleStrip::DecomposeStrip(npts, pts, polys); + } + this->OldMesh->SetPolys(polys); + polys->Delete(); + numPolys = polys->GetNumberOfCells();//added some new triangles + } + else + { + this->OldMesh->SetPolys(inPolys); + polys = inPolys; + } + this->OldMesh->BuildLinks(); + this->UpdateProgress(0.10); + + pd = input->GetPointData(); + outPD = output->GetPointData(); + + outCD = output->GetCellData(); + + this->NewMesh = vtkPolyData::New(); + this->NewMesh->SetPoints(inPts); + // create a copy because we're modifying it + newPolys = vtkCellArray::New(); + newPolys->DeepCopy(polys); + this->NewMesh->SetPolys(newPolys); + this->NewMesh->BuildCells(); //builds connectivity + + // The visited array keeps track of which polygons have been visited. + // + if ( this->Consistency || this->Splitting || this->AutoOrientNormals ) + { + this->Visited = new int[numPolys]; + memset(this->Visited, VTK_CELL_NOT_VISITED, numPolys*sizeof(int)); + this->CellIds = vtkIdList::New(); + this->CellIds->Allocate(VTK_CELL_SIZE); + } + else + { + this->Visited = NULL; + } + + // Traverse all polygons insuring proper direction of ordering. This + // works by propagating a wave from a seed polygon to the polygon's + // edge neighbors. Each neighbor may be reordered to maintain consistency + // with its (already checked) neighbors. + // + this->NumFlips = 0; + if (this->AutoOrientNormals) + { + // No need to check this->Consistency. It's implied. + + // Ok, here's the basic idea: the "left-most" polygon should + // have its outward pointing normal facing left. If it doesn't, + // reverse the vertex order. Then use it as the seed for other + // connected polys. To find left-most polygon, first find left-most + // point, and examine neighboring polys and see which one + // has a normal that's "most aligned" with the X-axis. This process + // will need to be repeated to handle all connected components in + // the mesh. Report bugs/issues to cvolpe@ara.com. + int foundLeftmostCell; + vtkIdType leftmostCellID=-1, currentPointID, currentCellID; + vtkIdType *leftmostCells; + unsigned short nleftmostCells; + vtkIdType *cellPts; + vtkIdType nCellPts; + int cIdx; + double bestNormalAbsXComponent; + int bestReverseFlag; + vtkPriorityQueue *leftmostPoints = vtkPriorityQueue::New(); + this->Wave = vtkIdList::New(); + this->Wave->Allocate(numPolys/4+1,numPolys); + this->Wave2 = vtkIdList::New(); + this->Wave2->Allocate(numPolys/4+1,numPolys); + + // Put all the points in the priority queue, based on x coord + // So that we can find leftmost point + leftmostPoints->Allocate(numPts); + for (ptId=0; ptId < numPts; ptId++) + { + leftmostPoints->Insert(inPts->GetPoint(ptId)[0],ptId); + } + + // Repeat this while loop as long as the queue is not empty, + // because there may be multiple connected components, each of + // which needs to be seeded independently with a correctly + // oriented polygon. + while (leftmostPoints->GetNumberOfItems()) + { + foundLeftmostCell = 0; + // Keep iterating through leftmost points and cells located at + // those points until I've got a leftmost point with + // unvisited cells attached and I've found the best cell + // at that point + do { + currentPointID = leftmostPoints->Pop(); + this->OldMesh->GetPointCells(currentPointID, nleftmostCells, leftmostCells); + bestNormalAbsXComponent = 0.0; + bestReverseFlag = 0; + for (cIdx = 0; cIdx < nleftmostCells; cIdx++) + { + currentCellID = leftmostCells[cIdx]; + if (this->Visited[currentCellID] == VTK_CELL_VISITED) + { + continue; + } + this->OldMesh->GetCellPoints(currentCellID, nCellPts, cellPts); + vtkPolygon::ComputeNormal(inPts, nCellPts, cellPts, n); + // Ok, see if this leftmost cell candidate is the best + // so far + if (fabs(n[0]) > bestNormalAbsXComponent) + { + bestNormalAbsXComponent = fabs(n[0]); + leftmostCellID = currentCellID; + // If the current leftmost cell's normal is pointing to the + // right, then the vertex ordering is wrong + bestReverseFlag = (n[0] > 0); + foundLeftmostCell = 1; + } // if this normal is most x-aligned so far + } // for each cell at current leftmost point + } while (leftmostPoints->GetNumberOfItems() && !foundLeftmostCell); + if (foundLeftmostCell) + { + // We've got the seed for a connected component! But do + // we need to flip it first? We do, if it was pointed the wrong + // way to begin with, or if the user requested flipping all + // normals, but if both are true, then we leave it as it is. + if (bestReverseFlag ^ this->FlipNormals) + { + this->NewMesh->ReverseCell(leftmostCellID); + this->NumFlips++; + } + this->Wave->InsertNextId(leftmostCellID); + this->Visited[leftmostCellID] = VTK_CELL_VISITED; + this->TraverseAndOrder(); + this->Wave->Reset(); + this->Wave2->Reset(); + } // if found leftmost cell + } // Still some points in the queue + this->Wave->Delete(); + this->Wave2->Delete(); + vtkDebugMacro(<<"Reversed ordering of " << this->NumFlips << " polygons"); + } // automatically orient normals + else + { + if ( this->Consistency ) + { + this->Wave = vtkIdList::New(); + this->Wave->Allocate(numPolys/4+1,numPolys); + this->Wave2 = vtkIdList::New(); + this->Wave2->Allocate(numPolys/4+1,numPolys); + for (cellId=0; cellId < numPolys; cellId++) + { + if ( this->Visited[cellId] == VTK_CELL_NOT_VISITED) + { + if ( this->FlipNormals ) + { + this->NumFlips++; + this->NewMesh->ReverseCell(cellId); + } + this->Wave->InsertNextId(cellId); + this->Visited[cellId] = VTK_CELL_VISITED; + this->TraverseAndOrder(); + } + + this->Wave->Reset(); + this->Wave2->Reset(); + } + + this->Wave->Delete(); + this->Wave2->Delete(); + vtkDebugMacro(<<"Reversed ordering of " << this->NumFlips << " polygons"); + }//Consistent ordering + } // don't automatically orient normals + + this->UpdateProgress(0.333); + + // Initial pass to compute polygon normals without effects of neighbors + // + this->PolyNormals = vtkFloatArray::New(); + this->PolyNormals->SetNumberOfComponents(3); + this->PolyNormals->Allocate(3*numPolys); + this->PolyNormals->SetName("Normals"); + this->PolyNormals->SetNumberOfTuples(numPolys); + + for (cellId=0, newPolys->InitTraversal(); newPolys->GetNextCell(npts,pts); + cellId++ ) + { + if ((cellId % 1000) == 0) + { + this->UpdateProgress (0.333 + 0.333 * (double) cellId / (double) numPolys); + if (this->GetAbortExecute()) + { + break; + } + } + vtkPolygon::ComputeNormal(inPts, npts, pts, n); + this->PolyNormals->SetTuple(cellId,n); + } + + // Split mesh if sharp features + if ( this->Splitting ) + { + // Traverse all nodes; evaluate loops and feature edges. If feature + // edges found, split mesh creating new nodes. Update polygon + // connectivity. + // + this->CosAngle = cos ((double) + vtkMath::DegreesToRadians() * this->FeatureAngle); + // Splitting will create new points. We have to create index array + // to map new points into old points. + // + this->Map = vtkIdList::New(); + this->Map->SetNumberOfIds(numPts); + for (i=0; i < numPts; i++) + { + this->Map->SetId(i,i); + } + + for (ptId=0; ptId < numPts; ptId++) + { + this->MarkAndSplit(ptId); + }//for all input points + + numNewPts = this->Map->GetNumberOfIds(); + + vtkDebugMacro(<<"Created " << numNewPts-numPts << " new points"); + + // Now need to map attributes of old points into new points. + // + outPD->CopyNormalsOff(); + outPD->CopyAllocate(pd,numNewPts); + + newPts = vtkPoints::New(); newPts->SetNumberOfPoints(numNewPts); + for (ptId=0; ptId < numNewPts; ptId++) + { + oldId = this->Map->GetId(ptId); + newPts->SetPoint(ptId,inPts->GetPoint(oldId)); + outPD->CopyData(pd,oldId,ptId); + } + this->Map->Delete(); + } //splitting + + else //no splitting, so no new points + { + numNewPts = numPts; + outPD->CopyNormalsOff(); + outPD->PassData(pd); + } + + if ( this->Consistency || this->Splitting ) + { + delete [] this->Visited; + this->CellIds->Delete(); + } + + this->UpdateProgress(0.80); + + // Finally, traverse all elements, computing polygon normals and + // accumulating them at the vertices. + // + if ( this->FlipNormals && ! this->Consistency ) + { + flipDirection = -1.0; + } + + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->SetNumberOfTuples(numNewPts); + newNormals->SetName("Normals"); + n[0] = n[1] = n[2] = 0.0; + for (i=0; i < numNewPts; i++) + { + newNormals->SetTuple(i,n); + } + + if (this->ComputePointNormals) + { + for (cellId=0, newPolys->InitTraversal(); newPolys->GetNextCell(npts,pts); + cellId++ ) + { + this->PolyNormals->GetTuple(cellId, polyNormal); + + for (i=0; i < npts; i++) + { + newNormals->GetTuple(pts[i], vertNormal); + for (j=0; j < 3; j++) + { + n[j] = vertNormal[j] + polyNormal[j]; + } + newNormals->SetTuple(pts[i],n); + } + } + + for (i=0; i < numNewPts; i++) + { + newNormals->GetTuple(i, vertNormal); + length = vtkMath::Norm(vertNormal); + if (length != 0.0) + { + for (j=0; j < 3; j++) + { + n[j] = vertNormal[j] / length * flipDirection; + } + } + newNormals->SetTuple(i,n); + } + } + + // Update ourselves. If no new nodes have been created (i.e., no + // splitting), we can simply pass data through. + // + if ( ! this->Splitting ) + { + output->SetPoints(inPts); + } + + // If there is splitting, then have to send down the new data. + // + else + { + output->SetPoints(newPts); + newPts->Delete(); + } + + if (this->ComputeCellNormals) + { + outCD->SetNormals(this->PolyNormals); + } + this->PolyNormals->Delete(); + + if (this->ComputePointNormals) + { + outPD->SetNormals(newNormals); + } + newNormals->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + // copy the original vertices and lines to the output + output->SetVerts(input->GetVerts()); + output->SetLines(input->GetLines()); + + this->OldMesh->Delete(); + this->NewMesh->Delete(); + + return 1; +} + +// Propagate wave of consistently ordered polygons. +// +void vtkPolyDataNormals::TraverseAndOrder (void) +{ + vtkIdType p1, p2, i, k; + int j, l; + vtkIdType numIds, cellId; + vtkIdType *pts, *neiPts, npts, numNeiPts; + vtkIdType neighbor; + vtkIdList *tmpWave; + + // propagate wave until nothing left in wave + while ( (numIds=this->Wave->GetNumberOfIds()) > 0 ) + { + for ( i=0; i < numIds; i++ ) + { + cellId = this->Wave->GetId(i); + + this->NewMesh->GetCellPoints(cellId, npts, pts); + + for (j=0; j < npts; j++) //for each edge neighbor + { + p1 = pts[j]; + p2 = pts[(j+1)%npts]; + + this->OldMesh->GetCellEdgeNeighbors(cellId, p1, p2, this->CellIds); + + // Check the direction of the neighbor ordering. Should be + // consistent with us (i.e., if we are n1->n2, + // neighbor should be n2->n1). + if ( this->CellIds->GetNumberOfIds() == 1 || + this->NonManifoldTraversal ) + { + for (k=0; k < this->CellIds->GetNumberOfIds(); k++) + { + if (this->Visited[this->CellIds->GetId(k)]==VTK_CELL_NOT_VISITED) + { + neighbor = this->CellIds->GetId(k); + this->NewMesh->GetCellPoints(neighbor,numNeiPts,neiPts); + for (l=0; l < numNeiPts; l++) + { + if (neiPts[l] == p2) + { + break; + } + } + + // Have to reverse ordering if neighbor not consistent + // + if ( neiPts[(l+1)%numNeiPts] != p1 ) + { + this->NumFlips++; + this->NewMesh->ReverseCell(neighbor); + } + this->Visited[neighbor] = VTK_CELL_VISITED; + this->Wave2->InsertNextId(neighbor); + }// if cell not visited + } // for each edge neighbor + } //for manifold or non-manifold traversal allowed + } // for all edges of this polygon + } //for all cells in wave + + //swap wave and proceed with propagation + tmpWave = this->Wave; + this->Wave = this->Wave2; + this->Wave2 = tmpWave; + this->Wave2->Reset(); + } //while wave still propagating + + return; +} + +// +// Mark polygons around vertex. Create new vertex (if necessary) and +// replace (i.e., split mesh). +// +void vtkPolyDataNormals::MarkAndSplit (vtkIdType ptId) +{ + int i,j; + + // Get the cells using this point and make sure that we have to do something + unsigned short ncells; + vtkIdType *cells; + this->OldMesh->GetPointCells(ptId,ncells,cells); + if ( ncells <= 1 ) + { + return; //point does not need to be further disconnected + } + + // Start moving around the "cycle" of points using the point. Label + // each point as requiring a visit. Then label each subregion of cells + // connected to this point that are connected (and not separated by + // a feature edge) with a given region number. For each N regions + // created, N-1 duplicate (split) points are created. The split point + // replaces the current point ptId in the polygons connectivity array. + // + // Start by initializing the cells as unvisited + for (i=0; iVisited[cells[i]] = -1; + } + + // Loop over all cells and mark the region that each is in. + // + vtkIdType numPts; + vtkIdType *pts; + int numRegions = 0; + vtkIdType spot, neiPt[2], nei, cellId, neiCellId; + double thisNormal[3], neiNormal[3]; + for (j=0; jVisited[cells[j]] < 0 ) //for all unvisited cells + { + this->Visited[cells[j]] = numRegions; + //okay, mark all the cells connected to this seed cell and using ptId + this->OldMesh->GetCellPoints(cells[j],numPts,pts); + + //find the two edges + for (spot=0; spot < numPts; spot++) + { + if ( pts[spot] == ptId ) + { + break; + } + } + + if ( spot == 0 ) + { + neiPt[0] = pts[spot+1]; + neiPt[1] = pts[numPts-1]; + } + else if ( spot == (numPts-1) ) + { + neiPt[0] = pts[spot-1]; + neiPt[1] = pts[0]; + } + else + { + neiPt[0] = pts[spot+1]; + neiPt[1] = pts[spot-1]; + } + + for (i=0; i<2; i++) //for each of the two edges of the seed cell + { + cellId = cells[j]; + nei = neiPt[i]; + while ( cellId >= 0 ) //while we can grow this region + { + this->OldMesh->GetCellEdgeNeighbors(cellId,ptId,nei,this->CellIds); + if ( this->CellIds->GetNumberOfIds() == 1 && + this->Visited[(neiCellId=this->CellIds->GetId(0))] < 0 ) + { + this->PolyNormals->GetTuple(cellId, thisNormal); + this->PolyNormals->GetTuple(neiCellId, neiNormal); + + if ( vtkMath::Dot(thisNormal,neiNormal) > CosAngle ) + { + //visit and arrange to visit next edge neighbor + this->Visited[neiCellId] = numRegions; + cellId = neiCellId; + this->OldMesh->GetCellPoints(cellId,numPts,pts); + + for (spot=0; spot < numPts; spot++) + { + if ( pts[spot] == ptId ) + { + break; + } + } + + if (spot == 0) + { + nei = (pts[spot+1] != nei ? pts[spot+1] : pts[numPts-1]); + } + else if (spot == (numPts-1)) + { + nei = (pts[spot-1] != nei ? pts[spot-1] : pts[0]); + } + else + { + nei = (pts[spot+1] != nei ? pts[spot+1] : pts[spot-1]); + } + + }//if not separated by edge angle + else + { + cellId = -1; //separated by edge angle + } + }//if can move to edge neighbor + else + { + cellId = -1;//separated by previous visit, boundary, or non-manifold + } + }//while visit wave is propagating + }//for each of the two edges of the starting cell + numRegions++; + }//if cell is unvisited + }//for all cells connected to point ptId + + if ( numRegions <=1 ) + { + return; //a single region, no splitting ever required + } + + // Okay, for all cells not in the first region, the ptId is + // replaced with a new ptId, which is a duplicate of the first + // point, but disconnected topologically. + // + vtkIdType lastId = this->Map->GetNumberOfIds(); + vtkIdType replacementPoint; + for (j=0; jVisited[cells[j]] > 0 ) //replace point if splitting needed + { + replacementPoint = lastId + this->Visited[cells[j]] - 1; + + this->Map->InsertId(replacementPoint, ptId); + + this->NewMesh->GetCellPoints(cells[j],numPts,pts); + for (i=0; i < numPts; i++) + { + if ( pts[i] == ptId ) + { + pts[i] = replacementPoint; // this is very nasty! direct write! + break; + } + }//replace ptId with split point + }//if not in first regions and requiring splitting + }//for all cells connected to ptId + + return; +} + +void vtkPolyDataNormals::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Feature Angle: " << this->FeatureAngle << "\n"; + os << indent << "Splitting: " << (this->Splitting ? "On\n" : "Off\n"); + os << indent << "Consistency: " << (this->Consistency ? "On\n" : "Off\n"); + os << indent << "Flip Normals: " << (this->FlipNormals ? "On\n" : "Off\n"); + os << indent << "Auto Orient Normals: " << (this->AutoOrientNormals ? "On\n" : "Off\n"); + os << indent << "Num Flips: " << this->NumFlips << endl; + os << indent << "Compute Point Normals: " + << (this->ComputePointNormals ? "On\n" : "Off\n"); + os << indent << "Compute Cell Normals: " + << (this->ComputeCellNormals ? "On\n" : "Off\n"); + os << indent << "Non-manifold Traversal: " + << (this->NonManifoldTraversal ? "On\n" : "Off\n"); +} + diff --git a/Graphics/vtkPolyDataNormals.h b/Graphics/vtkPolyDataNormals.h new file mode 100644 index 0000000..fb6712f --- /dev/null +++ b/Graphics/vtkPolyDataNormals.h @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataNormals.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataNormals - compute normals for polygonal mesh +// .SECTION Description +// vtkPolyDataNormals is a filter that computes point normals for a polygonal +// mesh. The filter can reorder polygons to insure consistent orientation +// across polygon neighbors. Sharp edges can be split and points duplicated +// with separate normals to give crisp (rendered) surface definition. It is +// also possible to globally flip the normal orientation. +// +// The algorithm works by determining normals for each polygon and then +// averaging them at shared points. When sharp edges are present, the edges +// are split and new points generated to prevent blurry edges (due to +// Gouraud shading). + +// .SECTION Caveats +// Normals are computed only for polygons and triangle strips. Normals are +// not computed for lines or vertices. +// +// Triangle strips are broken up into triangle polygons. You may want to +// restrip the triangles. + +#ifndef __vtkPolyDataNormals_h +#define __vtkPolyDataNormals_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkFloatArray; +class vtkIdList; +class vtkPolyData; + +class VTK_GRAPHICS_EXPORT vtkPolyDataNormals : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkPolyDataNormals,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with feature angle=30, splitting and consistency turned on, + // flipNormals turned off, and non-manifold traversal turned on. + // ComputePointNormals is on and ComputeCellNormals is off. + static vtkPolyDataNormals *New(); + + // Description: + // Specify the angle that defines a sharp edge. If the difference in + // angle across neighboring polygons is greater than this value, the + // shared edge is considered "sharp". + vtkSetClampMacro(FeatureAngle,double,0.0,180.0); + vtkGetMacro(FeatureAngle,double); + + // Description: + // Turn on/off the splitting of sharp edges. + vtkSetMacro(Splitting,int); + vtkGetMacro(Splitting,int); + vtkBooleanMacro(Splitting,int); + + // Description: + // Turn on/off the enforcement of consistent polygon ordering. + vtkSetMacro(Consistency,int); + vtkGetMacro(Consistency,int); + vtkBooleanMacro(Consistency,int); + + // Description: + // Turn on/off the automatic determination of correct normal + // orientation. NOTE: This assumes a completely closed surface + // (i.e. no boundary edges) and no non-manifold edges. If these + // constraints do not hold, all bets are off. This option adds some + // computational complexity, and is useful if you don't want to have + // to inspect the rendered image to determine whether to turn on the + // FlipNormals flag. However, this flag can work with the FlipNormals + // flag, and if both are set, all the normals in the output will + // point "inward". + vtkSetMacro(AutoOrientNormals, int); + vtkGetMacro(AutoOrientNormals, int); + vtkBooleanMacro(AutoOrientNormals, int); + + // Description: + // Turn on/off the computation of point normals. + vtkSetMacro(ComputePointNormals,int); + vtkGetMacro(ComputePointNormals,int); + vtkBooleanMacro(ComputePointNormals,int); + + // Description: + // Turn on/off the computation of cell normals. + vtkSetMacro(ComputeCellNormals,int); + vtkGetMacro(ComputeCellNormals,int); + vtkBooleanMacro(ComputeCellNormals,int); + + // Description: + // Turn on/off the global flipping of normal orientation. Flipping + // reverves the meaning of front and back for Frontface and Backface + // culling in vtkProperty. Flipping modifies both the normal + // direction and the order of a cell's points. + vtkSetMacro(FlipNormals,int); + vtkGetMacro(FlipNormals,int); + vtkBooleanMacro(FlipNormals,int); + + // Description: + // Turn on/off traversal across non-manifold edges. This will prevent + // problems where the consistency of polygonal ordering is corrupted due + // to topological loops. + vtkSetMacro(NonManifoldTraversal,int); + vtkGetMacro(NonManifoldTraversal,int); + vtkBooleanMacro(NonManifoldTraversal,int); + +protected: + vtkPolyDataNormals(); + ~vtkPolyDataNormals() {}; + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double FeatureAngle; + int Splitting; + int Consistency; + int FlipNormals; + int AutoOrientNormals; + int NonManifoldTraversal; + int ComputePointNormals; + int ComputeCellNormals; + int NumFlips; + +private: + vtkIdList *Wave; + vtkIdList *Wave2; + vtkIdList *CellIds; + vtkIdList *Map; + vtkPolyData *OldMesh; + vtkPolyData *NewMesh; + int *Visited; + vtkFloatArray *PolyNormals; + double CosAngle; + + // Uses the list of cell ids (this->Wave) to propagate a wave of + // checked and properly ordered polygons. + void TraverseAndOrder(void); + + // Check the point id give to see whether it lies on a feature + // edge. If so, split the point (i.e., duplicate it) to topologically + // separate the mesh. + void MarkAndSplit(vtkIdType ptId); + +private: + vtkPolyDataNormals(const vtkPolyDataNormals&); // Not implemented. + void operator=(const vtkPolyDataNormals&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkPolyDataStreamer.cxx b/Graphics/vtkPolyDataStreamer.cxx new file mode 100644 index 0000000..09260c8 --- /dev/null +++ b/Graphics/vtkPolyDataStreamer.cxx @@ -0,0 +1,156 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataStreamer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataStreamer.h" + +#include "vtkAppendPolyData.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPolyDataStreamer, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkPolyDataStreamer); + +//---------------------------------------------------------------------------- +vtkPolyDataStreamer::vtkPolyDataStreamer() +{ + this->NumberOfStreamDivisions = 2; + this->ColorByPiece = 0; +} + +//---------------------------------------------------------------------------- +vtkPolyDataStreamer::~vtkPolyDataStreamer() +{ +} + +//---------------------------------------------------------------------------- +void vtkPolyDataStreamer::SetNumberOfStreamDivisions(int num) +{ + if (this->NumberOfStreamDivisions == num) + { + return; + } + + this->Modified(); + this->NumberOfStreamDivisions = num; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataStreamer::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // If we are actually streaming, then bypass the normal update process. + if (this->NumberOfStreamDivisions > 1) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), -1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Append data sets into single unstructured grid +int vtkPolyDataStreamer::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPolyData *copy; + vtkAppendPolyData *append = vtkAppendPolyData::New(); + int outPiece, outNumPieces, outGhost; + int i, j, inPiece; + vtkFloatArray *pieceColors = NULL; + float tmp; + + if (this->ColorByPiece) + { + pieceColors = vtkFloatArray::New(); + } + + outGhost = output->GetUpdateGhostLevel(); + outPiece = output->GetUpdatePiece(); + outNumPieces = output->GetUpdateNumberOfPieces(); + for (i = 0; i < this->NumberOfStreamDivisions; ++i) + { + inPiece = outPiece * this->NumberOfStreamDivisions + i; + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + inPiece); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outNumPieces *this->NumberOfStreamDivisions); + input->Update(); + copy = vtkPolyData::New(); + copy->ShallowCopy(input); + append->AddInput(copy); + copy->Delete(); + if (pieceColors) + { + for (j = 0; j < input->GetNumberOfCells(); ++j) + { + tmp = static_cast(inPiece); + pieceColors->InsertNextTuple(&tmp); + } + } + } + + append->Update(); + output->ShallowCopy(append->GetOutput()); + // set the piece and number of pieces back to the correct value + // since the shallow copy of the append filter has overwritten them. + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outNumPieces); + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outPiece); + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outGhost); + + if (pieceColors) + { + int idx = output->GetCellData()->AddArray(pieceColors); + output->GetCellData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + pieceColors->Delete(); + } + append->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPolyDataStreamer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfStreamDivisions: " << this->NumberOfStreamDivisions << endl; + os << indent << "ColorByPiece: " << this->ColorByPiece << endl; +} diff --git a/Graphics/vtkPolyDataStreamer.h b/Graphics/vtkPolyDataStreamer.h new file mode 100644 index 0000000..c17f980 --- /dev/null +++ b/Graphics/vtkPolyDataStreamer.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataStreamer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataStreamer - Stream appends input pieces to the output. +// .SECTION Description +// vtkPolyDataStreamer initiates streaming by requesting pieces from its +// single input it appends these pieces it to the requested output. +// Note that since vtkPolyDataStreamer uses an append filter, all the +// polygons generated have to be kept in memory before rendering. If +// these do not fit in the memory, it is possible to make the vtkPolyDataMapper +// stream. Since the mapper will render each piece separately, all the +// polygons do not have to stored in memory. +// .SECTION Note +// The output may be slightly different if the pipeline does not handle +// ghost cells properly (i.e. you might see seames between the pieces). +// .SECTION See Also +// vtkAppendFilter + +#ifndef __vtkPolyDataStreamer_h +#define __vtkPolyDataStreamer_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkPolyDataStreamer : public vtkPolyDataAlgorithm +{ +public: + static vtkPolyDataStreamer *New(); + + vtkTypeRevisionMacro(vtkPolyDataStreamer,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the number of pieces to divide the problem into. + void SetNumberOfStreamDivisions(int num); + vtkGetMacro(NumberOfStreamDivisions,int); + + // Description: + // By default, this option is off. When it is on, cell scalars are generated + // based on which piece they are in. + vtkSetMacro(ColorByPiece, int); + vtkGetMacro(ColorByPiece, int); + vtkBooleanMacro(ColorByPiece, int); + + +protected: + vtkPolyDataStreamer(); + ~vtkPolyDataStreamer(); + + // Append the pieces. + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int NumberOfStreamDivisions; + int ColorByPiece; +private: + vtkPolyDataStreamer(const vtkPolyDataStreamer&); // Not implemented. + void operator=(const vtkPolyDataStreamer&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkProbeFilter.cxx b/Graphics/vtkProbeFilter.cxx new file mode 100644 index 0000000..bbc7223 --- /dev/null +++ b/Graphics/vtkProbeFilter.cxx @@ -0,0 +1,351 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProbeFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProbeFilter.h" + +#include "vtkCell.h" +#include "vtkIdTypeArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkProbeFilter, "$Revision: 1.82.12.2 $"); +vtkStandardNewMacro(vtkProbeFilter); + +//---------------------------------------------------------------------------- +vtkProbeFilter::vtkProbeFilter() +{ + this->SpatialMatch = 0; + this->ValidPoints = vtkIdTypeArray::New(); + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +vtkProbeFilter::~vtkProbeFilter() +{ + this->ValidPoints->Delete(); + this->ValidPoints = NULL; +} + +//---------------------------------------------------------------------------- +void vtkProbeFilter::SetSourceConnection(vtkAlgorithmOutput* algOutput) +{ + this->SetInputConnection(1, algOutput); +} + +//---------------------------------------------------------------------------- +void vtkProbeFilter::SetSource(vtkDataObject *input) +{ + this->SetInput(1, input); +} + +//---------------------------------------------------------------------------- +vtkDataObject *vtkProbeFilter::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + + return this->GetExecutive()->GetInputData(1, 0); +} + +//---------------------------------------------------------------------------- +int vtkProbeFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *source = vtkDataSet::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (!source) + { + return 0; + } + + this->Probe(input, source, output); + return 1; +} + +void vtkProbeFilter::Probe(vtkDataSet *input, vtkDataSet *source, + vtkDataSet *output) +{ + vtkIdType ptId, numPts; + double x[3], tol2; + vtkCell *cell; + vtkPointData *pd, *outPD; + int subId; + double pcoords[3], *weights; + double fastweights[256]; + + vtkDebugMacro(<<"Probing data"); + + pd = source->GetPointData(); + int size = input->GetNumberOfPoints(); + + // lets use a stack allocated array if possible for performance reasons + int mcs = source->GetMaxCellSize(); + if (mcs<=256) + { + weights = fastweights; + } + else + { + weights = new double[mcs]; + } + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + numPts = input->GetNumberOfPoints(); + this->ValidPoints->Allocate(numPts); + + // Allocate storage for output PointData + // + outPD = output->GetPointData(); + outPD->InterpolateAllocate(pd, size, size); + + // Use tolerance as a function of size of source data + // + tol2 = source->GetLength(); + tol2 = tol2 ? tol2*tol2 / 1000.0 : 0.001; + + // Loop over all input points, interpolating source data + // + int abort=0; + vtkIdType progressInterval=numPts/20 + 1; + for (ptId=0; ptId < numPts && !abort; ptId++) + { + if ( !(ptId % progressInterval) ) + { + this->UpdateProgress((double)ptId/numPts); + abort = GetAbortExecute(); + } + + // Get the xyz coordinate of the point in the input dataset + input->GetPoint(ptId, x); + + // Find the cell that contains xyz and get it + cell = source->FindAndGetCell(x,NULL,-1,tol2,subId,pcoords,weights); + if (cell) + { + // Interpolate the point data + outPD->InterpolatePoint(pd,ptId,cell->PointIds,weights); + this->ValidPoints->InsertNextValue(ptId); + } + else + { + outPD->NullPoint(ptId); + } + } + // BUG FIX: JB. + // Output gets setup from input, but when output is imagedata, scalartype + // depends on source scalartype not input scalartype + if (output->IsA("vtkImageData")) + { + vtkImageData *out = (vtkImageData*)output; + vtkDataArray *s = outPD->GetScalars(); + out->SetScalarType(s->GetDataType()); + out->SetNumberOfScalarComponents(s->GetNumberOfComponents()); + } + if (mcs>256) + { + delete [] weights; + } +} + +//---------------------------------------------------------------------------- +int vtkProbeFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->CopyEntry(sourceInfo, + vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()), + 6); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + inInfo->Get( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES())); + + // Special case for ParaView. + if (this->SpatialMatch == 2) + { + outInfo->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + sourceInfo->Get( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES())); + } + + if (this->SpatialMatch == 1) + { + int m1 = + inInfo->Get(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES()); + int m2 = + sourceInfo->Get( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES()); + if (m1 < 0 && m2 < 0) + { + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + } + else + { + if (m1 < -1) + { + m1 = VTK_LARGE_INTEGER; + } + if (m2 < -1) + { + m2 = VTK_LARGE_INTEGER; + } + if (m2 < m1) + { + m1 = m2; + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + m1); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkProbeFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int usePiece = 0; + + // What ever happend to CopyUpdateExtent in vtkDataObject? + // Copying both piece and extent could be bad. Setting the piece + // of a structured data set will affect the extent. + vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT()); + if (output && + (!strcmp(output->GetClassName(), "vtkUnstructuredGrid") || + !strcmp(output->GetClassName(), "vtkPolyData"))) + { + usePiece = 1; + } + + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + + if ( ! this->SpatialMatch) + { + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + } + else if (this->SpatialMatch == 1) + { + if (usePiece) + { + // Request an extra ghost level because the probe + // gets external values with computation prescision problems. + // I think the probe should be changed to have an epsilon ... + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())+1); + } + else + { + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()), + 6); + } + } + + if (usePiece) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + } + else + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()), + 6); + } + + // Use the whole input in all processes, and use the requested update + // extent of the output to divide up the source. + if (this->SpatialMatch == 2) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkProbeFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkDataObject *source = this->GetSource(); + + this->Superclass::PrintSelf(os,indent); + os << indent << "Source: " << source << "\n"; + if (this->SpatialMatch) + { + os << indent << "SpatialMatchOn\n"; + } + else + { + os << indent << "SpatialMatchOff\n"; + } + os << indent << "ValidPoints: " << this->ValidPoints << "\n"; +} diff --git a/Graphics/vtkProbeFilter.h b/Graphics/vtkProbeFilter.h new file mode 100644 index 0000000..edcceef --- /dev/null +++ b/Graphics/vtkProbeFilter.h @@ -0,0 +1,92 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProbeFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProbeFilter - sample data values at specified point locations +// .SECTION Description +// vtkProbeFilter is a filter that computes point attributes (e.g., scalars, +// vectors, etc.) at specified point positions. The filter has two inputs: +// the Input and Source. The Input geometric structure is passed through the +// filter. The point attributes are computed at the Input point positions +// by interpolating into the source data. For example, we can compute data +// values on a plane (plane specified as Input) from a volume (Source). +// +// This filter can be used to resample data, or convert one dataset form into +// another. For example, an unstructured grid (vtkUnstructuredGrid) can be +// probed with a volume (three-dimensional vtkImageData), and then volume +// rendering techniques can be used to visualize the results. Another example: +// a line or curve can be used to probe data to produce x-y plots along +// that line or curve. + +#ifndef __vtkProbeFilter_h +#define __vtkProbeFilter_h + +#include "vtkDataSetAlgorithm.h" + +class vtkIdTypeArray; + +class VTK_GRAPHICS_EXPORT vtkProbeFilter : public vtkDataSetAlgorithm +{ +public: + static vtkProbeFilter *New(); + vtkTypeRevisionMacro(vtkProbeFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the point locations used to probe input. Any geometry + // can be used. Old style. Do not use unless for backwards compatibility. + void SetSource(vtkDataObject *source); + vtkDataObject *GetSource(); + + // Description: + // Specify the point locations used to probe input. Any geometry + // can be used. New style. Equivalent to SetInputConnection(1, algOutput). + void SetSourceConnection(vtkAlgorithmOutput* algOutput); + + // Description: + // This flag is used only when a piece is requested to update. By default + // the flag is off. Because no spatial correspondence between input pieces + // and source pieces is known, all of the source has to be requested no + // matter what piece of the output is requested. When there is a spatial + // correspondence, the user/application can set this flag. This hint allows + // the breakup of the probe operation to be much more efficient. When piece + // m of n is requested for update by the user, then only n of m needs to + // be requested of the source. + vtkSetMacro(SpatialMatch, int); + vtkGetMacro(SpatialMatch, int); + vtkBooleanMacro(SpatialMatch, int); + + // Description: + // Get the list of point ids in the output that contain attribute data + // interpolated from the source. + vtkGetObjectMacro(ValidPoints, vtkIdTypeArray); + +protected: + vtkProbeFilter(); + ~vtkProbeFilter(); + + int SpatialMatch; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void Probe(vtkDataSet *input, vtkDataSet *source, vtkDataSet *output); + + vtkIdTypeArray *ValidPoints; +private: + vtkProbeFilter(const vtkProbeFilter&); // Not implemented. + void operator=(const vtkProbeFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkProgrammableAttributeDataFilter.cxx b/Graphics/vtkProgrammableAttributeDataFilter.cxx new file mode 100644 index 0000000..1905578 --- /dev/null +++ b/Graphics/vtkProgrammableAttributeDataFilter.cxx @@ -0,0 +1,154 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableAttributeDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProgrammableAttributeDataFilter.h" + +#include "vtkCellData.h" +#include "vtkDataSetCollection.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkProgrammableAttributeDataFilter, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkProgrammableAttributeDataFilter); + +vtkProgrammableAttributeDataFilter::vtkProgrammableAttributeDataFilter() +{ + this->ExecuteMethod = NULL; + this->ExecuteMethodArg = NULL; + this->ExecuteMethodArgDelete = NULL; + this->InputList = vtkDataSetCollection::New(); +} + +vtkProgrammableAttributeDataFilter::~vtkProgrammableAttributeDataFilter() +{ + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } + if (this->InputList) + { + this->InputList->Delete(); + this->InputList = NULL; + } +} + +// Add a dataset to the list of data to process. +void vtkProgrammableAttributeDataFilter::AddInput(vtkDataSet *ds) +{ + if ( ! this->InputList->IsItemPresent(ds) ) + { + this->Modified(); + this->InputList->AddItem(ds); + } +} + +// Remove a dataset from the list of data to process. +void vtkProgrammableAttributeDataFilter::RemoveInput(vtkDataSet *ds) +{ + if ( this->InputList->IsItemPresent(ds) ) + { + this->Modified(); + this->InputList->RemoveItem(ds); + } +} + +// Specify the function to use to operate on the point attribute data. Note +// that the function takes a single (void *) argument. +void vtkProgrammableAttributeDataFilter::SetExecuteMethod(void (*f)(void *), void *arg) +{ + if ( f != this->ExecuteMethod || arg != this->ExecuteMethodArg ) + { + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } + this->ExecuteMethod = f; + this->ExecuteMethodArg = arg; + this->Modified(); + } +} + +// Set the arg delete method. This is used to free user memory. +void vtkProgrammableAttributeDataFilter::SetExecuteMethodArgDelete(void (*f)(void *)) +{ + if ( f != this->ExecuteMethodArgDelete) + { + this->ExecuteMethodArgDelete = f; + this->Modified(); + } +} + +int vtkProgrammableAttributeDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Executing programmable point data filter"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + // Output data is the same as input data by default. + output->GetCellData()->PassData(input->GetCellData()); + output->GetPointData()->PassData(input->GetPointData()); + + // Now invoke the procedure, if specified. + if ( this->ExecuteMethod != NULL ) + { + (*this->ExecuteMethod)(this->ExecuteMethodArg); + } + + return 1; +} + +void vtkProgrammableAttributeDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Input DataSets:\n"; + this->InputList->PrintSelf(os,indent.GetNextIndent()); + + if ( this->ExecuteMethod ) + { + os << indent << "An ExecuteMethod has been defined\n"; + } + else + { + os << indent << "An ExecuteMethod has NOT been defined\n"; + } +} + +//---------------------------------------------------------------------------- +void +vtkProgrammableAttributeDataFilter +::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->InputList, "InputList"); +} diff --git a/Graphics/vtkProgrammableAttributeDataFilter.h b/Graphics/vtkProgrammableAttributeDataFilter.h new file mode 100644 index 0000000..229c0c0 --- /dev/null +++ b/Graphics/vtkProgrammableAttributeDataFilter.h @@ -0,0 +1,130 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableAttributeDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProgrammableAttributeDataFilter - manipulate attribute (cell and point) data via a user-specified function +// .SECTION Description +// vtkProgrammableAttributeDataFilter is a filter that allows you to write a +// custom procedure to manipulate attribute data - either point or cell +// data. For example, you could generate scalars based on a complex formula; +// convert vectors to normals; compute scalar values as a function of +// vectors, texture coords, and/or any other point data attribute; and so +// on. The filter takes multiple inputs (input plus an auxiliary input list), +// so you can write procedures that combine several dataset point +// attributes. Note that the output of the filter is the same type +// (topology/geometry) as the input. +// +// The filter works as follows. It operates like any other filter (i.e., +// checking and managing modified and execution times, processing Update() +// and Execute() methods, managing release of data, etc.), but the difference +// is that the Execute() method simply invokes a user-specified function with +// an optional (void *) argument (typically the "this" pointer in C++). It is +// also possible to specify a function to delete the argument via +// ExecuteMethodArgDelete(). +// +// To use the filter, you write a procedure to process the input datasets, +// process the data, and generate output data. Typically, this means grabbing +// the input point or cell data (using GetInput() and maybe GetInputList()), +// operating on it (creating new point and cell attributes such as scalars, +// vectors, etc.), and then setting the point and/or cell attributes in the +// output dataset (you'll need to use GetOutput() to access the output). +// (Note: besides C++, it is possible to do the same thing in Tcl, Java, or +// other languages that wrap the C++ core.) Remember, proper filter protocol +// requires that you don't modify the input data - you create new output data +// from the input. +// +// .SECTION Caveats +// This filter operates on any combination of the filter input plus a list of +// additional inputs (at a minimum you must set the filter input via +// SetInput()). It is up to you check whether the input is valid, and to +// insure that the output is valid. Also, you have to write the control +// structure for the traversal and operation on the point and cell attribute +// data. +// +// By default the output point and cell data will be copied through from the +// input point data (using reference counting). You can control this using +// the output's CopyAllOff() flag, or by using individual flags for each +// point data field (i.e., scalars, vectors, etc.) +// +// The output of this filter is the abstract type vtkDataSet, even if your +// input is a concrete type like vtkPolyData. Thus you may need to use +// vtkCastToConcrete to obtain the output as a particular concrete type, or +// one of the special methods of the superclass (e.g., +// vtkDataSetAlgorithm::GetPolyDataOutput) to retrieve output of the +// correct type. +// +// The filter correctly manages modified time and network execution in most +// cases. However, if you change the definition of the filter function, +// you'll want to send a manual Modified() method to the filter to force it +// to reexecute. + +#ifndef __vtkProgrammableAttributeDataFilter_h +#define __vtkProgrammableAttributeDataFilter_h + +#include "vtkDataSetAlgorithm.h" + +class vtkDataSetCollection; + +class VTK_GRAPHICS_EXPORT vtkProgrammableAttributeDataFilter : public vtkDataSetAlgorithm +{ +public: + static vtkProgrammableAttributeDataFilter *New(); + vtkTypeRevisionMacro(vtkProgrammableAttributeDataFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a dataset to the list of data to process. + void AddInput(vtkDataSet *in); + + // Description: + // Remove a dataset from the list of data to process. + void RemoveInput(vtkDataSet *in); + + // Description: + // Return the list of inputs. + vtkDataSetCollection *GetInputList() {return this->InputList;}; + + // Description: + // Specify the function to use to operate on the point attribute data. Note + // that the function takes a single (void *) argument. + void SetExecuteMethod(void (*f)(void *), void *arg); + + // Description: + // Set the arg delete method. This is used to free user memory. + void SetExecuteMethodArgDelete(void (*f)(void *)); + +protected: + vtkProgrammableAttributeDataFilter(); + ~vtkProgrammableAttributeDataFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + vtkDataSetCollection *InputList; //list of datasets to process + void (*ExecuteMethod)(void *); //function to invoke + void (*ExecuteMethodArgDelete)(void *); + void *ExecuteMethodArg; + + virtual void ReportReferences(vtkGarbageCollector*); + +private: + // hide the superclass' AddInput() from the user and the compiler + void AddInput(vtkDataObject *) + { vtkErrorMacro( << "AddInput() must be called with a vtkDataSet not a vtkDataObject."); }; + +private: + vtkProgrammableAttributeDataFilter(const vtkProgrammableAttributeDataFilter&); // Not implemented. + void operator=(const vtkProgrammableAttributeDataFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkProgrammableDataObjectSource.cxx b/Graphics/vtkProgrammableDataObjectSource.cxx new file mode 100644 index 0000000..de26853 --- /dev/null +++ b/Graphics/vtkProgrammableDataObjectSource.cxx @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableDataObjectSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProgrammableDataObjectSource.h" + +#include "vtkDataObject.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkProgrammableDataObjectSource, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkProgrammableDataObjectSource); + +// Construct programmable filter with empty execute method. +vtkProgrammableDataObjectSource::vtkProgrammableDataObjectSource() +{ + this->ExecuteMethod = NULL; + this->ExecuteMethodArg = NULL; + this->ExecuteMethodArgDelete = NULL; + + vtkDataObject *output = vtkDataObject::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); + + this->SetNumberOfInputPorts(0); +} + +vtkProgrammableDataObjectSource::~vtkProgrammableDataObjectSource() +{ + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } +} + +// Specify the function to use to generate the source data. Note +// that the function takes a single (void *) argument. +void vtkProgrammableDataObjectSource::SetExecuteMethod(void (*f)(void *), void *arg) +{ + if ( f != this->ExecuteMethod || arg != this->ExecuteMethodArg ) + { + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } + this->ExecuteMethod = f; + this->ExecuteMethodArg = arg; + this->Modified(); + } +} + +// Set the arg delete method. This is used to free user memory. +void vtkProgrammableDataObjectSource::SetExecuteMethodArgDelete(void (*f)(void *)) +{ + if ( f != this->ExecuteMethodArgDelete) + { + this->ExecuteMethodArgDelete = f; + this->Modified(); + } +} + +int vtkProgrammableDataObjectSource::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *) +{ + vtkDebugMacro(<<"Executing programmable data object filter"); + + // Now invoke the procedure, if specified. + if ( this->ExecuteMethod != NULL ) + { + (*this->ExecuteMethod)(this->ExecuteMethodArg); + } + + return 1; +} + +void vtkProgrammableDataObjectSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->ExecuteMethod ) + { + os << indent << "An ExecuteMethod has been defined\n"; + } + else + { + os << indent << "An ExecuteMethod has NOT been defined\n"; + } +} diff --git a/Graphics/vtkProgrammableDataObjectSource.h b/Graphics/vtkProgrammableDataObjectSource.h new file mode 100644 index 0000000..378b40c --- /dev/null +++ b/Graphics/vtkProgrammableDataObjectSource.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableDataObjectSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProgrammableDataObjectSource - generate source data object via a user-specified function +// .SECTION Description +// vtkProgrammableDataObjectSource is a source object that is programmable by +// the user. The output of the filter is a data object (vtkDataObject) which +// represents data via an instance of field data. To use this object, you +// must specify a function that creates the output. +// +// Example use of this filter includes reading tabular data and encoding it +// as vtkFieldData. You can then use filters like vtkDataObjectToDataSetFilter +// to convert the data object to a dataset and then visualize it. Another +// important use of this class is that it allows users of interpreters (e.g., +// Tcl or Java) the ability to write source objects without having to +// recompile C++ code or generate new libraries. +// +// .SECTION See Also +// vtkProgrammableFilter vtkProgrammableAttributeDataFilter +// vtkProgrammableSource vtkDataObjectToDataSetFilter + +#ifndef __vtkProgrammableDataObjectSource_h +#define __vtkProgrammableDataObjectSource_h + +#include "vtkDataObjectAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkProgrammableDataObjectSource : public vtkDataObjectAlgorithm +{ +public: + static vtkProgrammableDataObjectSource *New(); + vtkTypeRevisionMacro(vtkProgrammableDataObjectSource,vtkDataObjectAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the function to use to generate the output data object. Note + // that the function takes a single (void *) argument. + void SetExecuteMethod(void (*f)(void *), void *arg); + + // Description: + // Set the arg delete method. This is used to free user memory. + void SetExecuteMethodArgDelete(void (*f)(void *)); + +protected: + vtkProgrammableDataObjectSource(); + ~vtkProgrammableDataObjectSource(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + void (*ExecuteMethod)(void *); //function to invoke + void (*ExecuteMethodArgDelete)(void *); + void *ExecuteMethodArg; +private: + vtkProgrammableDataObjectSource(const vtkProgrammableDataObjectSource&); // Not implemented. + void operator=(const vtkProgrammableDataObjectSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkProgrammableFilter.cxx b/Graphics/vtkProgrammableFilter.cxx new file mode 100644 index 0000000..093fa98 --- /dev/null +++ b/Graphics/vtkProgrammableFilter.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProgrammableFilter.h" +#include "vtkPolyData.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkRectilinearGrid.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkProgrammableFilter, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkProgrammableFilter); + +// Construct programmable filter with empty execute method. +vtkProgrammableFilter::vtkProgrammableFilter() +{ + this->ExecuteMethod = NULL; + this->ExecuteMethodArg = NULL; + this->ExecuteMethodArgDelete = NULL; +} + +vtkProgrammableFilter::~vtkProgrammableFilter() +{ + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } +} + + +// Get the input as a concrete type. This method is typically used by the +// writer of the filter function to get the input as a particular type (i.e., +// it essentially does type casting). It is the users responsibility to know +// the correct type of the input data. +vtkPolyData *vtkProgrammableFilter::GetPolyDataInput() +{ + return (vtkPolyData *)this->GetInput(); +} + +// Get the input as a concrete type. +vtkStructuredPoints *vtkProgrammableFilter::GetStructuredPointsInput() +{ + return (vtkStructuredPoints *)this->GetInput(); +} + +// Get the input as a concrete type. +vtkStructuredGrid *vtkProgrammableFilter::GetStructuredGridInput() +{ + return (vtkStructuredGrid *)this->GetInput(); +} + +// Get the input as a concrete type. +vtkUnstructuredGrid *vtkProgrammableFilter::GetUnstructuredGridInput() +{ + return (vtkUnstructuredGrid *)this->GetInput(); +} + +// Get the input as a concrete type. +vtkRectilinearGrid *vtkProgrammableFilter::GetRectilinearGridInput() +{ + return (vtkRectilinearGrid *)this->GetInput(); +} + +// Specify the function to use to operate on the point attribute data. Note +// that the function takes a single (void *) argument. +void vtkProgrammableFilter::SetExecuteMethod(void (*f)(void *), void *arg) +{ + if ( f != this->ExecuteMethod || arg != this->ExecuteMethodArg ) + { + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } + this->ExecuteMethod = f; + this->ExecuteMethodArg = arg; + this->Modified(); + } +} + +// Set the arg delete method. This is used to free user memory. +void vtkProgrammableFilter::SetExecuteMethodArgDelete(void (*f)(void *)) +{ + if ( f != this->ExecuteMethodArgDelete) + { + this->ExecuteMethodArgDelete = f; + this->Modified(); + } +} + + +int vtkProgrammableFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Executing programmable filter"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + // Now invoke the procedure, if specified. + if ( this->ExecuteMethod != NULL ) + { + (*this->ExecuteMethod)(this->ExecuteMethodArg); + } + + return 1; +} + diff --git a/Graphics/vtkProgrammableFilter.h b/Graphics/vtkProgrammableFilter.h new file mode 100644 index 0000000..383634b --- /dev/null +++ b/Graphics/vtkProgrammableFilter.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProgrammableFilter - a user-programmable filter +// .SECTION Description +// vtkProgrammableFilter is a filter that can be programmed by the user. To +// use the filter you define a function that retrieves input of the correct +// type, creates data, and then manipulates the output of the filter. Using +// this filter avoids the need for subclassing - and the function can be +// defined in an interpreter wrapper language such as Tcl or Java. +// +// The trickiest part of using this filter is that the input and output +// methods are unusual and cannot be compile-time type checked. Instead, as a +// user of this filter it is your responsibility to set and get the correct +// input and output types. + +// .SECTION Caveats +// The filter correctly manages modified time and network execution in most +// cases. However, if you change the definition of the filter function, +// you'll want to send a manual Modified() method to the filter to force it +// to reexecute. + +// .SECTION See Also +// vtkProgrammablePointDataFilter vtkProgrammableSource + +#ifndef __vtkProgrammableFilter_h +#define __vtkProgrammableFilter_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkProgrammableFilter : public vtkDataSetAlgorithm +{ +public: + static vtkProgrammableFilter *New(); + vtkTypeRevisionMacro(vtkProgrammableFilter,vtkDataSetAlgorithm); + + // Description: + // Specify the function to use to operate on the point attribute data. Note + // that the function takes a single (void *) argument. + void SetExecuteMethod(void (*f)(void *), void *arg); + + // Description: + // Set the arg delete method. This is used to free user memory. + void SetExecuteMethodArgDelete(void (*f)(void *)); + + // Description: + // Get the input as a concrete type. This method is typically used by the + // writer of the filter function to get the input as a particular type (i.e., + // it essentially does type casting). It is the users responsibility to know + // the correct type of the input data. + vtkPolyData *GetPolyDataInput(); + + // Description: + // Get the input as a concrete type. + vtkStructuredPoints *GetStructuredPointsInput(); + + // Description: + // Get the input as a concrete type. + vtkStructuredGrid *GetStructuredGridInput(); + + // Description: + // Get the input as a concrete type. + vtkUnstructuredGrid *GetUnstructuredGridInput(); + + // Description: + // Get the input as a concrete type. + vtkRectilinearGrid *GetRectilinearGridInput(); + +protected: + vtkProgrammableFilter(); + ~vtkProgrammableFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void (*ExecuteMethod)(void *); //function to invoke + void (*ExecuteMethodArgDelete)(void *); + void *ExecuteMethodArg; + +private: + vtkProgrammableFilter(const vtkProgrammableFilter&); // Not implemented. + void operator=(const vtkProgrammableFilter&); // Not implemented. +}; + +#endif + diff --git a/Graphics/vtkProgrammableGlyphFilter.cxx b/Graphics/vtkProgrammableGlyphFilter.cxx new file mode 100644 index 0000000..7b4a696 --- /dev/null +++ b/Graphics/vtkProgrammableGlyphFilter.cxx @@ -0,0 +1,353 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableGlyphFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProgrammableGlyphFilter.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkProgrammableGlyphFilter, "$Revision: 1.32.12.1 $"); +vtkStandardNewMacro(vtkProgrammableGlyphFilter); + +// Construct object with scaling on, scaling mode is by scalar value, +// scale factor = 1.0, the range is (0,1), orient geometry is on, and +// orientation is by vector. Clamping and indexing are turned off. No +// initial sources are defined. +vtkProgrammableGlyphFilter::vtkProgrammableGlyphFilter() +{ + this->GlyphMethod = NULL; + this->GlyphMethodArgDelete = NULL; + this->GlyphMethodArg = NULL; + + this->Point[0] = this->Point[1] = this->Point[2] = 0.0; + this->PointId = -1; + this->PointData = NULL; + + this->ColorMode = VTK_COLOR_BY_INPUT; + + this->SetNumberOfInputPorts(2); +} + +vtkProgrammableGlyphFilter::~vtkProgrammableGlyphFilter() +{ + if ((this->GlyphMethodArg)&&(this->GlyphMethodArgDelete)) + { + (*this->GlyphMethodArgDelete)(this->GlyphMethodArg); + } +} + +// Specify a source object at a specified table location. +void vtkProgrammableGlyphFilter::SetSource(vtkPolyData *pd) +{ + this->SetInput(1, pd); +} + +// Get a pointer to a source object at a specified table location. +vtkPolyData *vtkProgrammableGlyphFilter::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +int vtkProgrammableGlyphFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *source = vtkPolyData::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *inputPD = input->GetPointData(); + vtkCellData *inputCD = input->GetCellData(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + vtkPoints *newPts, *sourcePts; + vtkFloatArray *ptScalars=NULL, *cellScalars=NULL; + vtkDataArray *inPtScalars = NULL, *inCellScalars = NULL; + vtkIdType numPts = input->GetNumberOfPoints(); + vtkPointData *sourcePD; + vtkCellData *sourceCD; + vtkIdType numSourcePts, numSourceCells, ptOffset=0, cellId, ptId, id, idx; + int i, npts; + vtkIdList *pts; + vtkIdList *cellPts; + vtkCell *cell; + + // Initialize + vtkDebugMacro(<<"Generating programmable glyphs!"); + + if ( numPts < 1 ) + { + vtkErrorMacro(<<"No input points to glyph"); + } + + pts=vtkIdList::New(); + pts->Allocate(VTK_CELL_SIZE); + sourcePD = source->GetPointData(); + sourceCD = source->GetCellData(); + numSourcePts = source->GetNumberOfPoints(); + numSourceCells = source->GetNumberOfCells(); + + outputPD->CopyScalarsOff(); //'cause we control the coloring process + outputCD->CopyScalarsOff(); + + output->Allocate(numSourceCells*numPts,numSourceCells*numPts); + outputPD->CopyAllocate(sourcePD, numSourcePts*numPts, numSourcePts*numPts); + outputCD->CopyAllocate(sourceCD, numSourceCells*numPts, numSourceCells*numPts); + newPts = vtkPoints::New(); + newPts->Allocate(numSourcePts*numPts); + + // figure out how to color the data and setup + if ( this->ColorMode == VTK_COLOR_BY_INPUT ) + { + if ( (inPtScalars = inputPD->GetScalars()) ) + { + ptScalars = vtkFloatArray::New(); + ptScalars->Allocate(numSourcePts*numPts); + } + if ( (inCellScalars = inputCD->GetScalars()) ) + { + cellScalars = vtkFloatArray::New(); + cellScalars->Allocate(numSourcePts*numPts); + } + } + + else + { + if ( sourcePD->GetScalars() ) + { + ptScalars = vtkFloatArray::New(); + ptScalars->Allocate(numSourcePts*numPts); + } + if ( sourceCD->GetScalars() ) + { + cellScalars = vtkFloatArray::New(); + cellScalars->Allocate(numSourcePts*numPts); + } + } + + // Loop over all points, invoking glyph method and Update(), + // then append output of source to output of this filter. + // +// this->Updating = 1; // to prevent infinite recursion + this->PointData = input->GetPointData(); + for (this->PointId=0; this->PointId < numPts; this->PointId++) + { + if ( ! (this->PointId % 10000) ) + { + this->UpdateProgress ((double)this->PointId/numPts); + if (this->GetAbortExecute()) + { + break; + } + } + + input->GetPoint(this->PointId, this->Point); + + if ( this->GlyphMethod ) + { + (*this->GlyphMethod)(this->GlyphMethodArg); + } + + if ( source ) + { + source->Update(); + + sourcePts = source->GetPoints(); + numSourcePts = source->GetNumberOfPoints(); + numSourceCells = source->GetNumberOfCells(); + sourcePD = source->GetPointData(); + sourceCD = source->GetCellData(); + + if ( this->ColorMode == VTK_COLOR_BY_SOURCE ) + { + inPtScalars = sourcePD->GetScalars(); + inCellScalars = sourceCD->GetScalars(); + } + + // Copy all data from source to output. + for (ptId=0; ptId < numSourcePts; ptId++) + { + id = newPts->InsertNextPoint(sourcePts->GetPoint(ptId)); + outputPD->CopyData(sourcePD, ptId, id); + } + + for (cellId=0; cellId < numSourceCells; cellId++) + { + cell = source->GetCell(cellId); + cellPts = cell->GetPointIds(); + npts = cellPts->GetNumberOfIds(); + for (pts->Reset(), i=0; i < npts; i++) + { + pts->InsertId(i,cellPts->GetId(i) + ptOffset); + } + id = output->InsertNextCell(cell->GetCellType(),pts); + outputCD->CopyData(sourceCD, cellId, id); + } + + // If we're coloring the output with scalars, do that now + if ( ptScalars ) + { + for (ptId=0; ptId < numSourcePts; ptId++) + { + idx = (this->ColorMode == VTK_COLOR_BY_INPUT ? this->PointId : ptId); + ptScalars->InsertNextValue(inPtScalars->GetComponent(idx,0)); + } + } + else if ( cellScalars ) + { + for (cellId=0; cellId < numSourceCells; cellId++) + { + idx = (this->ColorMode == VTK_COLOR_BY_INPUT ? this->PointId : cellId); + cellScalars->InsertNextValue(inCellScalars->GetComponent(idx,0)); + } + } + + ptOffset += numSourcePts; + + }//if a source is available + } //for all input points + +// this->Updating = 0; + + pts->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + + if ( ptScalars ) + { + idx = outputPD->AddArray(ptScalars); + outputPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + ptScalars->Delete(); + } + + if ( cellScalars ) + { + idx = outputCD->AddArray(cellScalars); + outputCD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + cellScalars->Delete(); + } + + output->Squeeze(); + + return 1; +} + + +// Specify function to be called before object executes. +void vtkProgrammableGlyphFilter::SetGlyphMethod(void (*f)(void *), void *arg) +{ + if ( f != this->GlyphMethod || arg != this->GlyphMethodArg ) + { + // delete the current arg if there is one and a delete meth + if ((this->GlyphMethodArg)&&(this->GlyphMethodArgDelete)) + { + (*this->GlyphMethodArgDelete)(this->GlyphMethodArg); + } + this->GlyphMethod = f; + this->GlyphMethodArg = arg; + this->Modified(); + } +} + +// Set the arg delete method. This is used to free user memory. +void vtkProgrammableGlyphFilter::SetGlyphMethodArgDelete(void (*f)(void *)) +{ + if ( f != this->GlyphMethodArgDelete) + { + this->GlyphMethodArgDelete = f; + this->Modified(); + } +} + +// Description: +// Return the method of coloring as a descriptive character string. +const char *vtkProgrammableGlyphFilter::GetColorModeAsString(void) +{ + if ( this->ColorMode == VTK_COLOR_BY_INPUT ) + { + return "ColorByInput"; + } + else + { + return "ColorBySource"; + } +} + +int vtkProgrammableGlyphFilter::FillInputPortInformation(int port, + vtkInformation *info) +{ + if (port == 0) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} + +void vtkProgrammableGlyphFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Color Mode: " << this->GetColorModeAsString() << endl; + os << indent << "Point Id: " << this->PointId << "\n"; + os << indent << "Point: " << this->Point[0] + << ", " << this->Point[1] + << ", " << this->Point[2] << "\n"; + if (this->PointData) + { + os << indent << "PointData: " << this->PointData << "\n"; + } + else + { + os << indent << "PointData: (not defined)\n"; + } + + if ( this->GlyphMethod ) + { + os << indent << "Glyph Method defined\n"; + } + else + { + os << indent << "No Glyph Method\n"; + } +} diff --git a/Graphics/vtkProgrammableGlyphFilter.h b/Graphics/vtkProgrammableGlyphFilter.h new file mode 100644 index 0000000..8816132 --- /dev/null +++ b/Graphics/vtkProgrammableGlyphFilter.h @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableGlyphFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProgrammableGlyphFilter - control the generation and placement of glyphs at input points +// .SECTION Description +// vtkProgrammableGlyphFilter is a filter that allows you to place a glyph at +// each input point in the dataset. In addition, the filter is programmable +// which means the user has control over the generation of the glyph. The +// glyphs can be controlled via the point data attributes (e.g., scalars, +// vectors, etc.) or any other information in the input dataset. +// +// This is the way the filter works. You must define an input dataset which +// at a minimum contains points with associated attribute values. Also, the +// Source instance variable must be set which is of type vtkPolyData. Then, +// for each point in the input, the PointId is set to the current point id, +// and a user-defined function is called (i.e., GlyphMethod). In this method +// you can manipulate the Source data (including changing to a different +// Source object). After the GlyphMethod is called, +// vtkProgrammableGlyphFilter will invoke an Update() on its Source object, +// and then copy its data to the output of the +// vtkProgrammableGlyphFilter. Therefore the output of this filter is of type +// vtkPolyData. +// +// Another option to this filter is the way you color the glyphs. You can use +// the scalar data from the input or the source. The instance variable +// ColorMode controls this behavior. + +// .SECTION Caveats +// This filter operates on point data attributes. If you want to use cell +// data attributes, use a filter like vtkCellCenters to generate points at +// the centers of cells, and then use these points. +// +// Note that the data attributes (cell and point) are passed to the output of +// this filter from the Source object. This works well as long as you are not +// changing the class of the Source object during execution. However, if the +// class of the Source object changes, then the potential exists that the +// data attributes might change during execution (e.g., scalars available +// from one source and not the next), possibly fouling up the copying of data +// attributes to the output. In this case, you may have to manually set the +// output's copy flags (e.g., CopyScalarsOn/Off(), CopyVectorsOn/Off(), etc.) +// to control what's being copied. + +// .SECTION See Also +// vtkGlyph3D vtkTensorGlyph vtkCellCenters + +#ifndef __vtkProgrammableGlyphFilter_h +#define __vtkProgrammableGlyphFilter_h + +#define VTK_COLOR_BY_INPUT 0 +#define VTK_COLOR_BY_SOURCE 1 + +#include "vtkPolyDataAlgorithm.h" + +class vtkPointData; + +class VTK_GRAPHICS_EXPORT vtkProgrammableGlyphFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkProgrammableGlyphFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct object with NULL GlyphMethod() and no source object. The ColorMode + // is set to color by the input. + static vtkProgrammableGlyphFilter *New(); + + // Description: + // Set/Get the source to use for this glyph. + // Note: you can change the source during execution of this filter. + void SetSource(vtkPolyData *source); + vtkPolyData *GetSource(); + + // Description: + // Specify function to be called for each input point. + void SetGlyphMethod(void (*f)(void *), void *arg); + + // Description: + // Set the arg delete method. This is used to free user memory that might + // be associated with the GlyphMethod(). + void SetGlyphMethodArgDelete(void (*f)(void *)); + + // Description: + // Get the current point id during processing. Value only valid during the + // Execute() method of this filter. (Meant to be called by the GlyphMethod().) + vtkGetMacro(PointId, vtkIdType); + + // Description: + // Get the current point coordinates during processing. Value only valid during the + // Execute() method of this filter. (Meant to be called by the GlyphMethod().) + vtkGetVector3Macro(Point,double); + + // Description: + // Get the set of point data attributes for the input. A convenience to the + // programmer to be used in the GlyphMethod(). Only valid during the Execute() + // method of this filter. + vtkGetObjectMacro(PointData,vtkPointData); + + // Description: + // Either color by the input or source scalar data. + vtkSetMacro(ColorMode,int); + vtkGetMacro(ColorMode,int); + void SetColorModeToColorByInput() + {this->SetColorMode(VTK_COLOR_BY_INPUT);}; + void SetColorModeToColorBySource() + {this->SetColorMode(VTK_COLOR_BY_SOURCE);}; + const char *GetColorModeAsString(); + +protected: + vtkProgrammableGlyphFilter(); + ~vtkProgrammableGlyphFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int, vtkInformation *); + + double Point[3]; // Coordinates of point + vtkIdType PointId; // Current point id during processing + vtkPointData *PointData; + int ColorMode; + + void (*GlyphMethod)(void *); // Support GlyphMethod + void (*GlyphMethodArgDelete)(void *); + void *GlyphMethodArg; + +private: + vtkProgrammableGlyphFilter(const vtkProgrammableGlyphFilter&); // Not implemented. + void operator=(const vtkProgrammableGlyphFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkProgrammableSource.cxx b/Graphics/vtkProgrammableSource.cxx new file mode 100644 index 0000000..4050371 --- /dev/null +++ b/Graphics/vtkProgrammableSource.cxx @@ -0,0 +1,333 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProgrammableSource.h" +#include "vtkPolyData.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkRectilinearGrid.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + +vtkCxxRevisionMacro(vtkProgrammableSource, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkProgrammableSource); + +// Construct programmable filter with empty execute method. +vtkProgrammableSource::vtkProgrammableSource() +{ + this->ExecuteMethod = NULL; + this->ExecuteMethodArg = NULL; + this->ExecuteMethodArgDelete = NULL; + this->RequestInformationMethod = NULL; + + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(5); + + vtkDataSet *output; + output = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(0,output); + output->Delete(); + + output = vtkStructuredPoints::New(); + this->GetExecutive()->SetOutputData(1,output); + output->Delete(); + + output = vtkStructuredGrid::New(); + this->GetExecutive()->SetOutputData(2,output); + output->Delete(); + + output = vtkUnstructuredGrid::New(); + this->GetExecutive()->SetOutputData(3,output); + output->Delete(); + + output = vtkRectilinearGrid::New(); + this->GetExecutive()->SetOutputData(4,output); + output->Delete(); + + this->RequestedDataType = VTK_POLY_DATA; +} + +vtkProgrammableSource::~vtkProgrammableSource() +{ + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } +} + +// Specify the function to use to generate the source data. Note +// that the function takes a single (void *) argument. +void vtkProgrammableSource::SetExecuteMethod(void (*f)(void *), void *arg) +{ + if ( f != this->ExecuteMethod || arg != this->ExecuteMethodArg ) + { + // delete the current arg if there is one and a delete meth + if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete)) + { + (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg); + } + this->ExecuteMethod = f; + this->ExecuteMethodArg = arg; + this->Modified(); + } +} + +// Set the arg delete method. This is used to free user memory. +void vtkProgrammableSource::SetExecuteMethodArgDelete(void (*f)(void *)) +{ + if ( f != this->ExecuteMethodArgDelete) + { + this->ExecuteMethodArgDelete = f; + this->Modified(); + } +} + +void vtkProgrammableSource::SetRequestInformationMethod(void (*f)(void *)) +{ + if ( f != this->RequestInformationMethod ) + { + this->RequestInformationMethod = f; + this->Modified(); + } +} + + +// Get the output as a concrete type. This method is typically used by the +// writer of the source function to get the output as a particular type (i.e., +// it essentially does type casting). It is the users responsibility to know +// the correct type of the output data. +vtkPolyData *vtkProgrammableSource::GetPolyDataOutput() +{ + if (this->GetNumberOfOutputPorts() < 5) + { + return NULL; + } + + this->RequestedDataType = VTK_POLY_DATA; + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetOutputData(0)); +} + +// Get the output as a concrete type. +vtkStructuredPoints *vtkProgrammableSource::GetStructuredPointsOutput() +{ + if (this->GetNumberOfOutputPorts() < 5) + { + return NULL; + } + + this->RequestedDataType = VTK_STRUCTURED_POINTS; + return vtkStructuredPoints::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + +// Get the output as a concrete type. +vtkStructuredGrid *vtkProgrammableSource::GetStructuredGridOutput() +{ + if (this->GetNumberOfOutputPorts() < 5) + { + return NULL; + } + + this->RequestedDataType = VTK_STRUCTURED_GRID; + return vtkStructuredGrid::SafeDownCast( + this->GetExecutive()->GetOutputData(2)); +} + +// Get the output as a concrete type. +vtkUnstructuredGrid *vtkProgrammableSource::GetUnstructuredGridOutput() +{ + if (this->GetNumberOfOutputPorts() < 5) + { + return NULL; + } + + this->RequestedDataType = VTK_UNSTRUCTURED_GRID; + return vtkUnstructuredGrid::SafeDownCast( + this->GetExecutive()->GetOutputData(3)); +} + +// Get the output as a concrete type. +vtkRectilinearGrid *vtkProgrammableSource::GetRectilinearGridOutput() +{ + if (this->GetNumberOfOutputPorts() < 5) + { + return NULL; + } + + this->RequestedDataType = VTK_RECTILINEAR_GRID; + return vtkRectilinearGrid::SafeDownCast( + this->GetExecutive()->GetOutputData(4)); +} + +int vtkProgrammableSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + vtkDebugMacro(<<"Executing programmable filter"); + + // Now invoke the procedure, if specified. + if ( this->ExecuteMethod != NULL ) + { + (*this->ExecuteMethod)(this->ExecuteMethodArg); + } + + return 1; +} + +int vtkProgrammableSource::RequestDataObject( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo; + vtkDataSet *output = 0; + switch (this->RequestedDataType) + { + case VTK_POLY_DATA: + outInfo = outputVector->GetInformationObject(0); + if (!outInfo) + { + output = vtkPolyData::New(); + } + else + { + output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + if (!output) + { + output = vtkPolyData::New(); + } + else + { + return 1; + } + } + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + break; + case VTK_STRUCTURED_POINTS: + outInfo = outputVector->GetInformationObject(1); + if (!outInfo) + { + output = vtkStructuredPoints::New(); + } + else + { + output = vtkStructuredPoints::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + if (!output) + { + output = vtkStructuredPoints::New(); + } + else + { + return 1; + } + } + this->GetExecutive()->SetOutputData(1, output); + output->Delete(); + break; + case VTK_STRUCTURED_GRID: + outInfo = outputVector->GetInformationObject(2); + if (!outInfo) + { + output = vtkStructuredGrid::New(); + } + else + { + output = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + if (!output) + { + output = vtkStructuredGrid::New(); + } + else + { + return 1; + } + } + this->GetExecutive()->SetOutputData(2, output); + output->Delete(); + break; + case VTK_UNSTRUCTURED_GRID: + outInfo = outputVector->GetInformationObject(3); + if (!outInfo) + { + output = vtkUnstructuredGrid::New(); + } + else + { + output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + if (!output) + { + output = vtkUnstructuredGrid::New(); + } + else + { + return 1; + } + } + this->GetExecutive()->SetOutputData(3, output); + output->Delete(); + break; + case VTK_RECTILINEAR_GRID: + outInfo = outputVector->GetInformationObject(4); + if (!outInfo) + { + output = vtkRectilinearGrid::New(); + } + else + { + output = vtkRectilinearGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + if (!output) + { + output = vtkRectilinearGrid::New(); + } + else + { + return 1; + } + } + this->GetExecutive()->SetOutputData(3, output); + output->Delete(); + break; + default: + return 0; + } + return 1; +} + +int vtkProgrammableSource::RequestInformation(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *) +{ + vtkDebugMacro(<<"requesting information"); + + // Now invoke the procedure, if specified. + if ( this->RequestInformationMethod != NULL ) + { + (*this->RequestInformationMethod)(NULL); + } + + return 1; +} diff --git a/Graphics/vtkProgrammableSource.h b/Graphics/vtkProgrammableSource.h new file mode 100644 index 0000000..5cc2bc8 --- /dev/null +++ b/Graphics/vtkProgrammableSource.h @@ -0,0 +1,110 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProgrammableSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProgrammableSource - generate source dataset via a user-specified function +// .SECTION Description +// vtkProgrammableSource is a source object that is programmable by the +// user. To use this object, you must specify a function that creates the +// output. It is possible to generate an output dataset of any (concrete) +// type; it is up to the function to properly initialize and define the +// output. Typically, you use one of the methods to get a concrete output +// type (e.g., GetPolyDataOutput() or GetStructuredPointsOutput()), and +// then manipulate the output in the user-specified function. +// +// Example use of this include writing a function to read a data file or +// interface to another system. (You might want to do this in favor of +// deriving a new class.) Another important use of this class is that it +// allows users of interpreters (e.g., Tcl or Java) the ability to write +// source objects without having to recompile C++ code or generate new +// libraries. +// .SECTION See Also +// vtkProgrammableFilter vtkProgrammableAttributeDataFilter +// vtkProgrammableDataObjectSource + +#ifndef __vtkProgrammableSource_h +#define __vtkProgrammableSource_h + +#include "vtkDataSetAlgorithm.h" + +class vtkPolyData; +class vtkStructuredPoints; +class vtkStructuredGrid; +class vtkUnstructuredGrid; +class vtkRectilinearGrid; + +class VTK_GRAPHICS_EXPORT vtkProgrammableSource : public vtkDataSetAlgorithm +{ +public: + static vtkProgrammableSource *New(); + vtkTypeRevisionMacro(vtkProgrammableSource,vtkDataSetAlgorithm); + + // Description: + // Specify the function to use to generate the source data. Note + // that the function takes a single (void *) argument. + void SetExecuteMethod(void (*f)(void *), void *arg); + + // Description: + // Set the arg delete method. This is used to free user memory. + void SetExecuteMethodArgDelete(void (*f)(void *)); + + // Description: + // Specify the function to use to fill in information about the source data. + void SetRequestInformationMethod(void (*f)(void *)); + + // Description: + // Get the output as a concrete type. This method is typically used by the + // writer of the source function to get the output as a particular type + // (i.e., it essentially does type casting). It is the users responsibility + // to know the correct type of the output data. + vtkPolyData *GetPolyDataOutput(); + + // Description: + // Get the output as a concrete type. + vtkStructuredPoints *GetStructuredPointsOutput(); + + // Description: + // Get the output as a concrete type. + vtkStructuredGrid *GetStructuredGridOutput(); + + // Description: + // Get the output as a concrete type. + vtkUnstructuredGrid *GetUnstructuredGridOutput(); + + // Description: + // Get the output as a concrete type. + vtkRectilinearGrid *GetRectilinearGridOutput(); + +protected: + vtkProgrammableSource(); + ~vtkProgrammableSource(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestDataObject(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void (*ExecuteMethod)(void *); //function to invoke + void (*ExecuteMethodArgDelete)(void *); + void *ExecuteMethodArg; + void (*RequestInformationMethod)(void *); // function to invoke + + vtkTimeStamp ExecuteTime; + int RequestedDataType; + +private: + vtkProgrammableSource(const vtkProgrammableSource&); // Not implemented. + void operator=(const vtkProgrammableSource&); // Not implemented. +}; + +#endif + diff --git a/Graphics/vtkProjectedTexture.cxx b/Graphics/vtkProjectedTexture.cxx new file mode 100644 index 0000000..e76ef60 --- /dev/null +++ b/Graphics/vtkProjectedTexture.cxx @@ -0,0 +1,288 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProjectedTexture.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProjectedTexture.h" + +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkProjectedTexture, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkProjectedTexture); + +// Description: +// Initialize the projected texture filter with a position of (0, 0, 1), +// a focal point of (0, 0, 0), an up vector on the +y axis, +// an aspect ratio of the projection frustum of equal width, height, and focal +// length, an S range of (0, 1) and a T range of (0, 1). +vtkProjectedTexture::vtkProjectedTexture() +{ + this->Position[0] = 0.0; + this->Position[1] = 0.0; + this->Position[2] = 1.0; + this->Orientation[0] = this->Orientation[1] = this->Orientation[2] = 0.0; + this->SetFocalPoint(0.0, 0.0, 0.0); + this->Up[0] = 0.0; + this->Up[1] = 1.0; + this->Up[2] = 0.0; + this->AspectRatio[0] = 1.0; + this->AspectRatio[1] = 1.0; + this->AspectRatio[2] = 1.0; + this->MirrorSeparation = 1.0; + this->CameraMode = VTK_PROJECTED_TEXTURE_USE_PINHOLE; + this->SRange[0] = 0.0; + this->SRange[1] = 1.0; + this->TRange[0] = 0.0; + this->TRange[1] = 1.0; +} + + +void vtkProjectedTexture::SetFocalPoint(double fp[3]) +{ + this->SetFocalPoint(fp[0], fp[1], fp[2]); +} + +void vtkProjectedTexture::SetFocalPoint(double x, double y, double z) +{ + double orientation[3]; + + orientation[0] = x - this->Position[0]; + orientation[1] = y - this->Position[1]; + orientation[2] = z - this->Position[2]; + vtkMath::Normalize(orientation); + if (this->Orientation[0] != orientation[0] || + this->Orientation[1] != orientation[1] || + this->Orientation[2] != orientation[2]) + { + this->Orientation[0] = orientation[0]; + this->Orientation[1] = orientation[1]; + this->Orientation[2] = orientation[2]; + this->Modified(); + } + this->FocalPoint[0] = x; + this->FocalPoint[1] = y; + this->FocalPoint[2] = z; +} + +int vtkProjectedTexture::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double tcoords[2]; + vtkIdType numPts; + vtkFloatArray *newTCoords; + vtkIdType i; + int j; + double proj; + double rightv[3], upv[3], diff[3]; + double sScale, tScale, sOffset, tOffset, sSize, tSize, s, t; + double p[3]; + + vtkDebugMacro(<<"Generating texture coordinates!"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + numPts=input->GetNumberOfPoints(); + + // + // Allocate texture data + // + + newTCoords = vtkFloatArray::New(); + newTCoords->SetName("ProjectedTextureCoordinates"); + newTCoords->SetNumberOfComponents(2); + newTCoords->SetNumberOfTuples(numPts); + + vtkMath::Normalize (this->Orientation); + + vtkMath::Cross (this->Orientation, this->Up, rightv); + vtkMath::Normalize (rightv); + + vtkMath::Cross (rightv, this->Orientation, upv); + vtkMath::Normalize (upv); + + sSize = this->AspectRatio[0] / this->AspectRatio[2]; + tSize = this->AspectRatio[1] / this->AspectRatio[2]; + + sScale = (this->SRange[1] - this->SRange[0])/sSize; + tScale = (this->TRange[1] - this->TRange[0])/tSize; + + sOffset = (this->SRange[1] - this->SRange[0])/2.0 + this->SRange[0]; + tOffset = (this->TRange[1] - this->TRange[0])/2.0 + this->TRange[0]; + + + // compute s-t coordinates + for (i = 0; i < numPts; i++) + { + output->GetPoint(i, p); + + for (j = 0; j < 3; j++) + { + diff[j] = p[j] - this->Position[j]; + } + + proj = vtkMath::Dot(diff, this->Orientation); + + // New mode to handle a two mirror camera with separation of + // MirrorSeparation -- In this case, we assume that the first mirror + // controls the elevation and the second controls the azimuth. Texture + // coordinates for the elevation are handled as normal, while those for + // the azimuth must be calculated based on a new baseline difference to + // include the mirror separation. + if (this->CameraMode == VTK_PROJECTED_TEXTURE_USE_TWO_MIRRORS) + { + // First calculate elevation coordinate t. + if(proj < 1.0e-10 && proj > -1.0e-10) + { + vtkWarningMacro(<<"Singularity: point located at elevation frustum Position"); + tcoords[1] = tOffset; + } + else + { + for (j = 0; j < 3; j++) + { + diff[j] = diff[j]/proj - this->Orientation[j]; + } + + t = vtkMath::Dot(diff, upv); + tcoords[1] = t * tScale + tOffset; + } + + // Now with t complete, continue on to calculate coordinate s + // by offsetting the center of the lens back by MirrorSeparation + // in direction opposite to the orientation. + for (j = 0; j < 3; j++) + { + diff[j] = p[j] - this->Position[j] + (this->MirrorSeparation*this->Orientation[j]); + } + + proj = vtkMath::Dot(diff, this->Orientation); + + if(proj < 1.0e-10 && proj > -1.0e-10) + { + vtkWarningMacro(<<"Singularity: point located at azimuth frustum Position"); + tcoords[0] = sOffset; + } + else + { + for (j = 0; j < 3; j++) + { + diff[j] = diff[j]/proj - this->Orientation[j]; + } + + s = vtkMath::Dot(diff, rightv); + sSize = this->AspectRatio[0] / (this->AspectRatio[2] + this->MirrorSeparation); + sScale = (this->SRange[1] - this->SRange[0])/sSize; + sOffset = (this->SRange[1] - this->SRange[0])/2.0 + this->SRange[0]; + tcoords[0] = s * sScale + sOffset; + } + } + else + { + if(proj < 1.0e-10 && proj > -1.0e-10) + { + vtkWarningMacro(<<"Singularity: point located at frustum Position"); + tcoords[0] = sOffset; + tcoords[1] = tOffset; + } + else + { + for (j = 0; j < 3; j++) + { + diff[j] = diff[j]/proj - this->Orientation[j]; + } + + s = vtkMath::Dot(diff, rightv); + t = vtkMath::Dot(diff, upv); + + tcoords[0] = s * sScale + sOffset; + tcoords[1] = t * tScale + tOffset; + } + } + newTCoords->SetTuple(i,tcoords); + } + // + // Update ourselves + // + output->GetPointData()->CopyTCoordsOff(); + output->GetPointData()->PassData(input->GetPointData()); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + return 1; +} + +void vtkProjectedTexture::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "S Range: (" << this->SRange[0] << ", " + << this->SRange[1] << ")\n"; + + os << indent << "T Range: (" << this->TRange[0] << ", " + << this->TRange[1] << ")\n"; + + os << indent << "Position: (" << this->Position[0] << ", " + << this->Position[1] << ", " + << this->Position[2] << ")\n"; + + os << indent << "Orientation: (" << this->Orientation[0] << ", " + << this->Orientation[1] << ", " + << this->Orientation[2] << ")\n"; + + os << indent << "Focal Point: (" << this->FocalPoint[0] << ", " + << this->FocalPoint[1] << ", " + << this->FocalPoint[2] << ")\n"; + + os << indent << "Up: (" << this->Up[0] << ", " + << this->Up[1] << ", " + << this->Up[2] << ")\n"; + + os << indent << "AspectRatio: (" << this->AspectRatio[0] << ", " + << this->AspectRatio[1] << ", " + << this->AspectRatio[2] << ")\n"; + + os << indent << "CameraMode: "; + if (this->CameraMode == VTK_PROJECTED_TEXTURE_USE_PINHOLE) + { + os << "Pinhole\n"; + } + else if (this->CameraMode == VTK_PROJECTED_TEXTURE_USE_TWO_MIRRORS) + { + os << "Two Mirror\n"; + } + else + { + os << "Illegal Mode\n"; + } + + os << indent << "MirrorSeparation: " << this->MirrorSeparation << "\n"; +} diff --git a/Graphics/vtkProjectedTexture.h b/Graphics/vtkProjectedTexture.h new file mode 100644 index 0000000..2115ae4 --- /dev/null +++ b/Graphics/vtkProjectedTexture.h @@ -0,0 +1,118 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProjectedTexture.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProjectedTexture - assign texture coordinates for a projected texture +// .SECTION Description +// vtkProjectedTexture assigns texture coordinates to a dataset as if +// the texture was projected from a slide projected located somewhere in the +// scene. Methods are provided to position the projector and aim it at a +// location, to set the width of the projector's frustum, and to set the +// range of texture coordinates assigned to the dataset. +// +// Objects in the scene that appear behind the projector are also assigned +// texture coordinates; the projected image is left-right and top-bottom +// flipped, much as a lens' focus flips the rays of light that pass through +// it. A warning is issued if a point in the dataset falls at the focus +// of the projector. + +#ifndef __vtkProjectedTexture_h +#define __vtkProjectedTexture_h + +#include "vtkDataSetAlgorithm.h" + +#define VTK_PROJECTED_TEXTURE_USE_PINHOLE 0 +#define VTK_PROJECTED_TEXTURE_USE_TWO_MIRRORS 1 + +class VTK_GRAPHICS_EXPORT vtkProjectedTexture : public vtkDataSetAlgorithm +{ +public: + static vtkProjectedTexture *New(); + vtkTypeRevisionMacro(vtkProjectedTexture,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the position of the focus of the projector. + vtkSetVector3Macro(Position,double); + vtkGetVectorMacro(Position,double,3); + + // Description: + // Set/Get the focal point of the projector (a point that lies along + // the center axis of the projector's frustum). + void SetFocalPoint(double focalPoint[3]); + void SetFocalPoint(double x, double y, double z); + vtkGetVectorMacro(FocalPoint,double,3); + + // Description: + // Set/Get the camera mode of the projection -- pinhole projection or + // two mirror projection. + vtkSetMacro(CameraMode, int); + vtkGetMacro(CameraMode, int); + void SetCameraModeToPinhole() {this->SetCameraMode(VTK_PROJECTED_TEXTURE_USE_PINHOLE);} + void SetCameraModeToTwoMirror() {this->SetCameraMode(VTK_PROJECTED_TEXTURE_USE_TWO_MIRRORS);} + + // Description: + // Set/Get the mirror separation for the two mirror system. + vtkSetMacro(MirrorSeparation, double); + vtkGetMacro(MirrorSeparation, double); + + // Description: + // Get the normalized orientation vector of the projector. + vtkGetVectorMacro(Orientation,double,3); + + // Set/Get the up vector of the projector. + vtkSetVector3Macro(Up,double); + vtkGetVectorMacro(Up,double,3); + + // Set/Get the aspect ratio of a perpendicular cross-section of the + // the projector's frustum. The aspect ratio consists of three + // numbers: (x, y, z), where x is the width of the + // frustum, y is the height, and z is the perpendicular + // distance from the focus of the projector. + vtkSetVector3Macro(AspectRatio,double); + vtkGetVectorMacro(AspectRatio,double,3); + + // Description: + // Specify s-coordinate range for texture s-t coordinate pair. + vtkSetVector2Macro(SRange,double); + vtkGetVectorMacro(SRange,double,2); + + // Description: + // Specify t-coordinate range for texture s-t coordinate pair. + vtkSetVector2Macro(TRange,double); + vtkGetVectorMacro(TRange,double,2); + +protected: + vtkProjectedTexture(); + ~vtkProjectedTexture() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void ComputeNormal(); + + int CameraMode; + + double Position[3]; + double Orientation[3]; + double FocalPoint[3]; + double Up[3]; + double MirrorSeparation; + double AspectRatio[3]; + double SRange[2]; + double TRange[2]; +private: + vtkProjectedTexture(const vtkProjectedTexture&); // Not implemented. + void operator=(const vtkProjectedTexture&); // Not implemented. +}; + +#endif + diff --git a/Graphics/vtkQuadricClustering.cxx b/Graphics/vtkQuadricClustering.cxx new file mode 100644 index 0000000..26674bd --- /dev/null +++ b/Graphics/vtkQuadricClustering.cxx @@ -0,0 +1,1520 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadricClustering.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuadricClustering.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkExecutive.h" +#include "vtkFeatureEdges.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkTimerLog.h" +#include "vtkTriangle.h" + +vtkCxxRevisionMacro(vtkQuadricClustering, "$Revision: 1.77 $"); +vtkStandardNewMacro(vtkQuadricClustering); + +//---------------------------------------------------------------------------- +// Construct with default NumberOfDivisions to 50, DivisionSpacing to 1 +// in all (x,y,z) directions. AutoAdjustNumberOfDivisions is set to ON. +// ComputeNumberOfDivisions to OFF. UseFeatureEdges and UseFeaturePoints +// are set to OFF by default +// The default behavior is also to compute an optimal position in each +// bin to produce the output triangles (this is also recommended) +vtkQuadricClustering::vtkQuadricClustering() +{ + this->Bounds[0] = this->Bounds[1] = this->Bounds[2] = 0.0; + this->Bounds[3] = this->Bounds[4] = this->Bounds[5] = 0.0; + this->NumberOfXDivisions = 50; + this->NumberOfYDivisions = 50; + this->NumberOfZDivisions = 50; + this->QuadricArray = NULL; + this->NumberOfBinsUsed = 0; + this->AbortExecute = 0; + + this->AutoAdjustNumberOfDivisions = 1; + this->ComputeNumberOfDivisions = 0; + this->DivisionOrigin[0] = 0.0; + this->DivisionOrigin[1] = 0.0; + this->DivisionOrigin[2] = 0.0; + this->DivisionSpacing[0] = 1.0; + this->DivisionSpacing[1] = 1.0; + this->DivisionSpacing[2] = 1.0; + + this->UseFeatureEdges = 0; + this->UseFeaturePoints = 0; + this->FeaturePointsAngle = 30.0; + this->UseInternalTriangles = 1; + + this->UseInputPoints = 0; + + this->OutputTriangleArray = NULL; + this->OutputLines = NULL; + + // Used for matching boundaries. + this->FeatureEdges = vtkFeatureEdges::New(); + this->FeatureEdges->FeatureEdgesOff(); + this->FeatureEdges->BoundaryEdgesOn(); + this->FeaturePoints = vtkPoints::New(); + + this->InCellCount = this->OutCellCount = 0; + this->CopyCellData = 0; +} + +//---------------------------------------------------------------------------- +vtkQuadricClustering::~vtkQuadricClustering() +{ + this->FeatureEdges->Delete(); + this->FeatureEdges = NULL; + this->FeaturePoints->Delete(); + this->FeaturePoints = NULL; + if (this->QuadricArray) + { + delete [] this->QuadricArray; + this->QuadricArray = NULL; + } + if (this->OutputTriangleArray) + { + this->OutputTriangleArray->Delete(); + this->OutputTriangleArray = NULL; + } + if (this->OutputLines) + { + this->OutputLines->Delete(); + this->OutputLines = NULL; + } +} + +//---------------------------------------------------------------------------- +int vtkQuadricClustering::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = 0; + if (inInfo) + { + input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + } + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkTimerLog *tlog=NULL; + + if (!input || (input->GetNumberOfPoints() == 0)) + { + // The user may be calling StartAppend, Append, and EndAppend explicitly. + return 1; + } + + if (input->CheckAttributes()) + { + // avoid crashing if input is not all we expect (is not consistent). + return 1; + } + + if (this->Debug) + { + tlog = vtkTimerLog::New(); + tlog->StartTimer(); + } + + // Lets limit the number of divisions based on + // the number of points in the input. + int target = input->GetNumberOfPoints(); + int numDiv = (this->NumberOfXDivisions * this->NumberOfYDivisions + * this->NumberOfZDivisions) / 2; + if (this->AutoAdjustNumberOfDivisions && numDiv > target) + { + double factor = pow(((double)numDiv/(double)target),0.33333); + this->NumberOfDivisions[0] = + (int)(0.5+(double)(this->NumberOfXDivisions)/factor); + this->NumberOfDivisions[1] = + (int)(0.5+(double)(this->NumberOfYDivisions)/factor); + this->NumberOfDivisions[2] = + (int)(0.5+(double)(this->NumberOfZDivisions)/factor); + } + else + { + this->NumberOfDivisions[0] = this->NumberOfXDivisions; + this->NumberOfDivisions[1] = this->NumberOfYDivisions; + this->NumberOfDivisions[2] = this->NumberOfZDivisions; + } + + this->UpdateProgress(.01); + + this->StartAppend(input->GetBounds()); + this->UpdateProgress(.2); + this->SliceSize = this->NumberOfDivisions[0]*this->NumberOfDivisions[1]; + + this->Append(input); + if (this->UseFeatureEdges) + { // Adjust bin points that contain boundary edges. + this->AppendFeatureQuadrics(input, output); + } + + if (this->UseInputPoints) + { + this->EndAppendUsingPoints(input, output); + } + else + { + this->EndAppend(); + } + + // Free up some memory. + if (this->QuadricArray) + { + delete [] this->QuadricArray; + this->QuadricArray = NULL; + } + + if ( this->Debug ) + { + tlog->StopTimer(); + vtkDebugMacro(<<"Execution took: "<GetElapsedTime()<<" seconds."); + tlog->Delete(); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::StartAppend(double *bounds) +{ + vtkIdType i; + + // Copy over the bounds. + for (i = 0; i < 6; ++i) + { + this->Bounds[i]= bounds[i]; + } + + if (this->ComputeNumberOfDivisions) + { + // extend the bounds so that it will not produce fractions of bins. + double x, y, z; + x = floor((bounds[0]-this->DivisionOrigin[0])/this->DivisionSpacing[0]); + y = floor((bounds[2]-this->DivisionOrigin[1])/this->DivisionSpacing[1]); + z = floor((bounds[4]-this->DivisionOrigin[2])/this->DivisionSpacing[2]); + this->Bounds[0] = this->DivisionOrigin[0]+(x * this->DivisionSpacing[0]); + this->Bounds[2] = this->DivisionOrigin[1]+(y * this->DivisionSpacing[1]); + this->Bounds[4] = this->DivisionOrigin[2]+(z * this->DivisionSpacing[2]); + x = ceil((bounds[1]-this->Bounds[0])/this->DivisionSpacing[0]); + y = ceil((bounds[3]-this->Bounds[2])/this->DivisionSpacing[1]); + z = ceil((bounds[5]-this->Bounds[4])/this->DivisionSpacing[2]); + this->Bounds[1] = this->Bounds[0] + (x * this->DivisionSpacing[0]); + this->Bounds[3] = this->Bounds[2] + (y * this->DivisionSpacing[1]); + this->Bounds[5] = this->Bounds[4] + (z * this->DivisionSpacing[2]); + this->NumberOfDivisions[0] = (int)x > 0 ? (int)x : 1; + this->NumberOfDivisions[1] = (int)y > 0 ? (int)y : 1; + this->NumberOfDivisions[2] = (int)z > 0 ? (int)z : 1; + } + else + { + this->DivisionOrigin[0] = bounds[0]; + this->DivisionOrigin[1] = bounds[2]; + this->DivisionOrigin[2] = bounds[4]; + this->DivisionSpacing[0] = (bounds[1]-bounds[0])/this->NumberOfDivisions[0]; + this->DivisionSpacing[1] = (bounds[3]-bounds[2])/this->NumberOfDivisions[1]; + this->DivisionSpacing[2] = (bounds[5]-bounds[4])/this->NumberOfDivisions[2]; + } + + // Check for conditions that can occur if the Append methods + // are not called in the correct order. + if (this->OutputTriangleArray) + { + this->OutputTriangleArray->Delete(); + this->OutputTriangleArray = NULL; + //vtkWarningMacro("Array already created. Did you call EndAppend?"); + } + if (this->OutputLines) + { + this->OutputLines->Delete(); + this->OutputLines = NULL; + //vtkWarningMacro("Array already created. Did you call EndAppend?"); + } + + this->OutputTriangleArray = vtkCellArray::New(); + this->OutputLines = vtkCellArray::New(); + + this->XBinSize = (this->Bounds[1]-this->Bounds[0])/this->NumberOfDivisions[0]; + this->YBinSize = (this->Bounds[3]-this->Bounds[2])/this->NumberOfDivisions[1]; + this->ZBinSize = (this->Bounds[5]-this->Bounds[4])/this->NumberOfDivisions[2]; + + this->NumberOfBinsUsed = 0; + if (this->QuadricArray) + { + delete [] this->QuadricArray; + this->QuadricArray = NULL; + } + this->QuadricArray = + new vtkQuadricClustering::PointQuadric[this->NumberOfDivisions[0] * + this->NumberOfDivisions[1] * + this->NumberOfDivisions[2]]; + if (this->QuadricArray == NULL) + { + vtkErrorMacro("Could not allocate quadric grid."); + return; + } + + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0); + vtkPolyData *input = 0; + if (inInfo) + { + input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + } + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Allocate CellData here. + if (this->CopyCellData && input) + { + output->GetCellData()->CopyAllocate( + input->GetCellData(), this->NumberOfBinsUsed); + this->InCellCount = this->OutCellCount = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::Append(vtkPolyData *pd) +{ + vtkCellArray *inputPolys, *inputStrips, *inputLines, *inputVerts; + vtkPoints *inputPoints = pd->GetPoints(); + + // Check for mis-use of the Append methods. + if (this->OutputTriangleArray == NULL || this->OutputLines == NULL) + { + vtkDebugMacro("Missing Array: Did you call StartAppend?"); + return; + } + + vtkInformation *outInfo = + this->GetExecutive()->GetOutputInformation(0); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + inputVerts = pd->GetVerts(); + if (inputVerts) + { + this->AddVertices(inputVerts, inputPoints, 1, pd, output); + } + this->UpdateProgress(.40); + + inputLines = pd->GetLines(); + if (inputLines) + { + this->AddEdges(inputLines, inputPoints, 1, pd, output); + } + this->UpdateProgress(.60); + + inputPolys = pd->GetPolys(); + if (inputPolys) + { + this->AddPolygons(inputPolys, inputPoints, 1, pd, output); + } + this->UpdateProgress(.80); + + inputStrips = pd->GetStrips(); + if (inputStrips) + { + this->AddStrips(inputStrips, inputPoints, 1, pd, output); + } +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::AddPolygons(vtkCellArray *polys, vtkPoints *points, + int geometryFlag, + vtkPolyData *input, vtkPolyData *output) +{ + int j; + vtkIdType *ptIds = 0; + vtkIdType numPts = 0; + double pts0[3], pts1[3], pts2[3]; + vtkIdType binIds[3]; + + double total = polys->GetNumberOfCells(); + double curr = 0; + double step = total / 10; + if (step < 1000.0) + { + step = 1000.0; + } + double cstep = step; + + for ( polys->InitTraversal(); polys->GetNextCell(numPts, ptIds); ) + { + points->GetPoint(ptIds[0],pts0); + binIds[0] = this->HashPoint(pts0); + for (j=0; j < numPts-2; j++)//creates triangles; assumes poly is convex + { + points->GetPoint(ptIds[j+1],pts1); + binIds[1] = this->HashPoint(pts1); + points->GetPoint(ptIds[j+2],pts2); + binIds[2] = this->HashPoint(pts2); + this->AddTriangle(binIds, pts0, pts1, pts2, geometryFlag, input, output); + } + ++this->InCellCount; + if ( curr > cstep ) + { + this->UpdateProgress(.6 + .2 * curr / total); + cstep += step; + } + curr += 1; + }//for all polygons +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::AddStrips(vtkCellArray *strips, vtkPoints *points, + int geometryFlag, + vtkPolyData *input, vtkPolyData *output) +{ + int j; + vtkIdType *ptIds = 0; + vtkIdType numPts = 0; + double pts[3][3]; + vtkIdType binIds[3]; + int odd; // Used to flip order of every other triangle in a strip. + + for ( strips->InitTraversal(); strips->GetNextCell(numPts, ptIds); ) + { + points->GetPoint(ptIds[0], pts[0]); + binIds[0] = this->HashPoint(pts[0]); + points->GetPoint(ptIds[1], pts[1]); + binIds[1] = this->HashPoint(pts[1]); + // This internal loop handles triangle strips. + odd = 0; + for (j = 2; j < numPts; ++j) + { + points->GetPoint(ptIds[j], pts[2]); + binIds[2] = this->HashPoint(pts[2]); + this->AddTriangle(binIds, pts[0], pts[1], pts[2], geometryFlag, input, + output); + pts[odd][0] = pts[2][0]; + pts[odd][1] = pts[2][1]; + pts[odd][2] = pts[2][2]; + binIds[odd] = binIds[2]; + // Toggle odd. + odd = odd ? 0 : 1; + } + ++this->InCellCount; + } +} + +//---------------------------------------------------------------------------- +inline void vtkQuadricClustering::InitializeQuadric(double quadric[9]) +{ + quadric[0] = 0.0; + quadric[1] = 0.0; + quadric[2] = 0.0; + quadric[3] = 0.0; + quadric[4] = 0.0; + quadric[5] = 0.0; + quadric[6] = 0.0; + quadric[7] = 0.0; + quadric[8] = 0.0; +} + +//---------------------------------------------------------------------------- +// The error function is the volume (squared) of the tetrahedron formed by the +// triangle and the point. We ignore constant factors across all coefficents, +// and the constant coefficient. +// If geomertyFlag is 1 then the triangle is added to the output. Otherwise, +// only the quadric is affected. +void vtkQuadricClustering::AddTriangle(vtkIdType *binIds, double *pt0, double *pt1, + double *pt2, int geometryFlag, + vtkPolyData *input, vtkPolyData *output) +{ + int i; + vtkIdType triPtIds[3]; + double quadric[9], quadric4x4[4][4]; + + // Compute the quadric. + vtkTriangle::ComputeQuadric(pt0, pt1, pt2, quadric4x4); + quadric[0] = quadric4x4[0][0]; + quadric[1] = quadric4x4[0][1]; + quadric[2] = quadric4x4[0][2]; + quadric[3] = quadric4x4[0][3]; + quadric[4] = quadric4x4[1][1]; + quadric[5] = quadric4x4[1][2]; + quadric[6] = quadric4x4[1][3]; + quadric[7] = quadric4x4[2][2]; + quadric[8] = quadric4x4[2][3]; + + // Special condition for fast execution. + // Only add triangles that traverse three bins to quadrics. + if (this->UseInternalTriangles == 0) + { + if (binIds[0] == binIds[1] || binIds[0] == binIds[2] || + binIds[1] == binIds[2]) + { + return; + } + } + + // Add the quadric to each of the three corner bins. + for (i = 0; i < 3; ++i) + { + // If the current quadric is not initialized, then clear it out. + if (this->QuadricArray[binIds[i]].Dimension > 2) + { + this->QuadricArray[binIds[i]].Dimension = 2; + // Initialize the coeff + this->InitializeQuadric(this->QuadricArray[binIds[i]].Quadric); + } + if (this->QuadricArray[binIds[i]].Dimension == 2) + { // Points and segments supercede triangles. + this->AddQuadric(binIds[i], quadric); + } + } + + if (geometryFlag) + { + // Now add the triangle to the geometry. + for (i = 0; i < 3; i++) + { + // Get the vertex from each bin. + if (this->QuadricArray[binIds[i]].VertexId == -1) + { + this->QuadricArray[binIds[i]].VertexId = this->NumberOfBinsUsed; + this->NumberOfBinsUsed++; + } + triPtIds[i] = this->QuadricArray[binIds[i]].VertexId; + } + // This comparison could just as well be on triPtIds. + if (binIds[0] != binIds[1] && binIds[0] != binIds[2] && + binIds[1] != binIds[2]) + { + this->OutputTriangleArray->InsertNextCell(3, triPtIds); + if (this->CopyCellData && input) + { + output->GetCellData()-> + CopyData(input->GetCellData(), this->InCellCount, + this->OutCellCount++); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::AddEdges(vtkCellArray *edges, vtkPoints *points, + int geometryFlag, + vtkPolyData *input, vtkPolyData *output) +{ + int j; + vtkIdType numCells, i; + vtkIdType *ptIds = 0; + vtkIdType numPts = 0; + double pt0[3], pt1[3]; + vtkIdType binIds[2]; + + // Add the edges to the error fuction. + numCells = edges->GetNumberOfCells(); + edges->InitTraversal(); + for (i = 0; i < numCells; ++i) + { + edges->GetNextCell(numPts, ptIds); + points->GetPoint(ptIds[0], pt0); + binIds[0] = this->HashPoint(pt0); + // This internal loop handles line strips. + for (j = 1; j < numPts; ++j) + { + points->GetPoint(ptIds[j], pt1); + binIds[1] = this->HashPoint(pt1); + this->AddEdge(binIds, pt0, pt1, geometryFlag, input, output); + pt0[0] = pt1[0]; + pt0[1] = pt1[1]; + pt0[2] = pt1[2]; + binIds[0] = binIds[1]; + } + ++this->InCellCount; + } +} +//---------------------------------------------------------------------------- +// The error function is the square of the area of the triangle formed by the +// edge and the point. We ignore constants across all terms. +// If geometryFlag is 1 then the edge is added to the output. Otherwise, +// only the quadric is affected. +void vtkQuadricClustering::AddEdge(vtkIdType *binIds, double *pt0, double *pt1, + int geometryFlag, + vtkPolyData *input, vtkPolyData *output) +{ + int i; + vtkIdType edgePtIds[2]; + double length2, tmp; + double d[3]; + double m[3]; // The mid point of the segement.(p1 or p2 could be used also). + double md; // The dot product of m and d. + double q[9]; + + // Compute quadric for line segment. + // Line segment quadric is the area (squared) of the triangle (seg,pt) + // Compute the direction vector of the segment. + d[0] = pt1[0] - pt0[0]; + d[1] = pt1[1] - pt0[1]; + d[2] = pt1[2] - pt0[2]; + + // Compute the length^2 of the line segement. + length2 = d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; + + if (length2 == 0.0) + { // Coincident points. Avoid divide by zero. + return; + } + + // Normalize the direction vector. + tmp = 1.0 / sqrt(length2); + d[0] = d[0] * tmp; + d[1] = d[1] * tmp; + d[2] = d[2] * tmp; + + // Compute the mid point of the segment. + m[0] = 0.5 * (pt1[0] + pt0[0]); + m[1] = 0.5 * (pt1[1] + pt0[1]); + m[2] = 0.5 * (pt1[2] + pt0[2]); + + // Compute dot(m, d); + md = m[0]*d[0] + m[1]*d[1] + m[2]*d[2]; + + // We save nine coefficients of the error function cooresponding to: + // 0: Px^2 + // 1: PxPy + // 2: PxPz + // 3: Px + // 4: Py^2 + // 5: PyPz + // 6: Py + // 7: Pz^2 + // 8: Pz + // We ignore the constant because it disappears with the derivative. + q[0] = length2*(1.0 - d[0]*d[0]); + q[1] = -length2*(d[0]*d[1]); + q[2] = -length2*(d[0]*d[2]); + q[3] = length2*(d[0]*md - m[0]); + q[4] = length2*(1.0 - d[1]*d[1]); + q[5] = -length2*(d[1]*d[2]); + q[6] = length2*(d[1]*md - m[1]); + q[7] = length2*(1.0 - d[2]*d[2]); + q[8] = length2*(d[2]*md - m[2]); + + for (i = 0; i < 2; ++i) + { + // If the current quadric is from triangles (or not initialized), then clear it out. + if (this->QuadricArray[binIds[i]].Dimension > 1) + { + this->QuadricArray[binIds[i]].Dimension = 1; + // Initialize the coeff + this->InitializeQuadric(this->QuadricArray[binIds[i]].Quadric); + } + if (this->QuadricArray[binIds[i]].Dimension == 1) + { // Points supercede segements. + this->AddQuadric(binIds[i], q); + } + } + + if (geometryFlag) + { + // Now add the edge to the geometry. + for (i = 0; i < 2; i++) + { + // Get the vertex from each bin. + if (this->QuadricArray[binIds[i]].VertexId == -1) + { + this->QuadricArray[binIds[i]].VertexId = this->NumberOfBinsUsed; + this->NumberOfBinsUsed++; + } + edgePtIds[i] = this->QuadricArray[binIds[i]].VertexId; + } + // This comparison could just as well be on edgePtIds. + if (binIds[0] != binIds[1]) + { + this->OutputLines->InsertNextCell(2, edgePtIds); + if (this->CopyCellData && input) + { + output->GetCellData()-> + CopyData(input->GetCellData(),this->InCellCount, + this->OutCellCount++); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::AddVertices(vtkCellArray *verts, vtkPoints *points, + int geometryFlag, vtkPolyData *input, + vtkPolyData *output) +{ + int j; + vtkIdType numCells, i; + vtkIdType *ptIds = 0; + vtkIdType numPts = 0; + double pt[3]; + vtkIdType binId; + + numCells = verts->GetNumberOfCells(); + double cstep = (double)numCells / 10.0; + if (cstep < 1000.0) + { + cstep = 1000.0; + } + double next = cstep; + double curr = 0; + + verts->InitTraversal(); + for (i = 0; i < numCells; ++i) + { + verts->GetNextCell(numPts, ptIds); + // Can there be poly vertices? + for (j = 0; j < numPts; ++j) + { + points->GetPoint(ptIds[j], pt); + binId = this->HashPoint(pt); + this->AddVertex(binId, pt, geometryFlag, input, output); + } + ++this->InCellCount; + + if ( curr > next ) + { + this->UpdateProgress(.2 + .2 * curr / (double)numCells); + next += cstep; + } + curr += 1; + } +} + +//---------------------------------------------------------------------------- +// The error function is the length (point to vert) squared. +// We ignore constants across all terms. +// If geomertyFlag is 1 then the vert is added to the output. Otherwise, +// only the quadric is affected. +void vtkQuadricClustering::AddVertex(vtkIdType binId, double *pt, + int geometryFlag, + vtkPolyData *input, vtkPolyData *output) +{ + double q[9]; + + // Compute quadric for the vertex. + + // We save nine coefficients of the error function cooresponding to: + // 0: Px^2 + // 1: PxPy + // 2: PxPz + // 3: Px + // 4: Py^2 + // 5: PyPz + // 6: Py + // 7: Pz^2 + // 8: Pz + // We ignore the constant because it disappears with the derivative. + q[0] = 1.0; + q[1] = 0.0; + q[2] = 0.0; + q[3] = -pt[0]; + q[4] = 1.0; + q[5] = 0.0; + q[6] = -pt[1]; + q[7] = 1.0; + q[8] = -pt[2]; + + // If the current quadric is from triangles, edges (or not initialized), + // then clear it out. + if (this->QuadricArray[binId].Dimension > 0) + { + this->QuadricArray[binId].Dimension = 0; + // Initialize the coeff + this->InitializeQuadric(this->QuadricArray[binId].Quadric); + } + if (this->QuadricArray[binId].Dimension == 0) + { // Points supercede all other types of quadrics. + this->AddQuadric(binId, q); + } + + if (geometryFlag) + { + // Now add the vert to the geometry. + // Get the vertex from the bin. + if (this->QuadricArray[binId].VertexId == -1) + { + this->QuadricArray[binId].VertexId = this->NumberOfBinsUsed; + this->NumberOfBinsUsed++; + + if (this->CopyCellData && input) + { + output->GetCellData()-> + CopyData(output->GetCellData(), this->InCellCount, + this->OutCellCount++); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::AddQuadric(vtkIdType binId, double quadric[9]) +{ + double *q = this->QuadricArray[binId].Quadric; + + for (int i=0; i<9; i++) + { + q[i] += (quadric[i] * 100000000.0); + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkQuadricClustering::HashPoint(double point[3]) +{ + vtkIdType binId; + int xBinCoord = 0; + int yBinCoord = 0; + int zBinCoord = 0; + + if (this->XBinSize > 0.0) + { + xBinCoord = + static_cast((point[0] - this->Bounds[0]) / this->XBinSize); + if (xBinCoord < 0) + { + xBinCoord = 0; + } + else if (xBinCoord >= this->NumberOfDivisions[0]) + { + xBinCoord = this->NumberOfDivisions[0] - 1; + } + } + + if (this->YBinSize > 0.0) + { + yBinCoord = + static_cast((point[1] - this->Bounds[2]) / this->YBinSize); + if (yBinCoord < 0) + { + yBinCoord = 0; + } + else if (yBinCoord >= this->NumberOfDivisions[1]) + { + yBinCoord = this->NumberOfDivisions[1] - 1; + } + } + + if (this->ZBinSize > 0.0) + { + zBinCoord = + static_cast((point[2] - this->Bounds[4]) / this->ZBinSize); + if (zBinCoord < 0) + { + zBinCoord = 0; + } + else if (zBinCoord >= this->NumberOfDivisions[2]) + { + zBinCoord = this->NumberOfDivisions[2] - 1; + } + } + + // vary x fastest, then y, then z + binId = xBinCoord + yBinCoord*this->NumberOfDivisions[0] + + zBinCoord*this->SliceSize; + + return binId; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::EndAppend() +{ + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0); + vtkPolyData *input = 0; + if (inInfo) + { + input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + } + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType i, numBuckets; + int abortExecute=0; + vtkPoints *outputPoints; + double newPt[3]; + numBuckets = this->NumberOfDivisions[0] * this->NumberOfDivisions[1] * + this->NumberOfDivisions[2]; + double step = (double)numBuckets / 10.0; + if (step < 1000.0) + { + step = 1000.0; + } + double cstep = 0; + + // Check for mis use of the Append methods. + if (this->OutputTriangleArray == NULL || this->OutputLines == NULL) + { + vtkDebugMacro("Missing Array: Did you call StartAppend?"); + return; + } + + outputPoints = vtkPoints::New(); + + for (i = 0; !abortExecute && i < numBuckets; i++ ) + { + if (cstep > step) + { + cstep = 0; + vtkDebugMacro(<<"Finding point in bin #" << i); + this->UpdateProgress (0.8+0.2*i/numBuckets); + abortExecute = this->GetAbortExecute(); + } + ++cstep; + + if (this->QuadricArray[i].VertexId != -1) + { + this->ComputeRepresentativePoint(this->QuadricArray[i].Quadric, i, newPt); + outputPoints->InsertPoint(this->QuadricArray[i].VertexId, newPt); + } + } + + // Set up the output data object. + output->SetPoints(outputPoints); + outputPoints->Delete(); + + if (this->OutputTriangleArray->GetNumberOfCells() > 0) + { + output->SetPolys(this->OutputTriangleArray); + } + this->OutputTriangleArray->Delete(); + this->OutputTriangleArray = NULL; + + if (this->OutputLines->GetNumberOfCells() > 0) + { + output->SetLines(this->OutputLines); + } + this->OutputLines->Delete(); + this->OutputLines = NULL; + + this->EndAppendVertexGeometry(input, output); + + // Tell the data is is up to date + // (in case the user calls this method directly). + output->DataHasBeenGenerated(); + + // Free the quadric array. + if (this->QuadricArray) + { + delete [] this->QuadricArray; + this->QuadricArray = NULL; + } +} + + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::ComputeRepresentativePoint(double quadric[9], + vtkIdType binId, + double point[3]) +{ + int i, j; + double A[3][3], U[3][3], UT[3][3], VT[3][3], V[3][3]; + double b[3], w[3]; + double W[3][3], tempMatrix[3][3]; + double cellCenter[3], tempVector[3]; + double cellBounds[6]; + int x, y, z; + double quadric4x4[4][4]; + + quadric4x4[0][0] = quadric[0]; + quadric4x4[0][1] = quadric4x4[1][0] = quadric[1]; + quadric4x4[0][2] = quadric4x4[2][0] = quadric[2]; + quadric4x4[0][3] = quadric4x4[3][0] = quadric[3]; + quadric4x4[1][1] = quadric[4]; + quadric4x4[1][2] = quadric4x4[2][1] = quadric[5]; + quadric4x4[1][3] = quadric4x4[3][1] = quadric[6]; + quadric4x4[2][2] = quadric[7]; + quadric4x4[2][3] = quadric4x4[3][2] = quadric[8]; + quadric4x4[3][3] = 1; // arbitrary value + + x = binId % this->NumberOfDivisions[0]; + y = (binId / this->NumberOfDivisions[0]) % this->NumberOfDivisions[1]; + z = binId / this->SliceSize; + + cellBounds[0] = this->Bounds[0] + x * this->XBinSize; + cellBounds[1] = this->Bounds[0] + (x+1) * this->XBinSize; + cellBounds[2] = this->Bounds[2] + y * this->YBinSize; + cellBounds[3] = this->Bounds[2] + (y+1) * this->YBinSize; + cellBounds[4] = this->Bounds[4] + z * this->ZBinSize; + cellBounds[5] = this->Bounds[4] + (z+1) * this->ZBinSize; + + for (i = 0; i < 3; i++) + { + b[i] = -quadric4x4[3][i]; + cellCenter[i] = (cellBounds[i*2+1] + cellBounds[i*2]) / 2.0; + for (j = 0; j < 3; j++) + { + A[i][j] = quadric4x4[i][j]; + } + } + + // Compute diagonal matrix W + // +#define VTK_SVTHRESHOLD 1.0E-3 + double maxW = 0.0, temp; + vtkMath::SingularValueDecomposition3x3(A, U, w, VT); + + // Find maximum (magnitude) eigenvalue from SVD + for (i = 0; i < 3; i++) + { + if ((temp = fabs(w[i])) > maxW) + { + maxW = temp; + } + } + // Initialize matrix + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + if (i == j) + { + if ( fabs(w[i] / maxW) > VTK_SVTHRESHOLD) + { + // If this is true, then w[i] != 0, so this division is ok. + W[i][j] = 1.0/w[i]; + } + else + { + W[i][j] = 0.0; + } + } + else + { + W[i][j] = 0.0; + } + } + } +#undef VTK_SVTHRESHOLD + + vtkMath::Transpose3x3(U, UT); + vtkMath::Transpose3x3(VT, V); + vtkMath::Multiply3x3(W, UT, tempMatrix); + vtkMath::Multiply3x3(V, tempMatrix, tempMatrix); + vtkMath::Multiply3x3(A, cellCenter, tempVector); + for (i = 0; i < 3; i++) + { + tempVector[i] = b[i] - tempVector[i]; + } + vtkMath::Multiply3x3(tempMatrix, tempVector, tempVector); + + // Make absolutely sure that the point lies in the vicinity (enclosing + // sphere) of the bin. If not, then clamp the point to the enclosing sphere. + double deltaMag = vtkMath::Norm(tempVector); + double radius = sqrt(this->XBinSize*this->XBinSize + + this->YBinSize*this->YBinSize + + this->ZBinSize*this->ZBinSize) / 2.0; + if (deltaMag > radius) + { + tempVector[0] *= radius / deltaMag; + tempVector[1] *= radius / deltaMag; + tempVector[2] *= radius / deltaMag; + } + + point[0] = cellCenter[0] + tempVector[0]; + point[1] = cellCenter[1] + tempVector[1]; + point[2] = cellCenter[2] + tempVector[2]; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::SetNumberOfDivisions(int div0, int div1, int div2) +{ + this->SetNumberOfXDivisions(div0); + this->SetNumberOfYDivisions(div1); + this->SetNumberOfZDivisions(div2); +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::SetNumberOfXDivisions(int num) +{ + if (this->NumberOfXDivisions == num && this->ComputeNumberOfDivisions == 0) + { + return; + } + if (num < 2) + { + vtkErrorMacro("You cannot use less than two divisions."); + return; + } + this->Modified(); + this->NumberOfXDivisions = num; + this->ComputeNumberOfDivisions = 0; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::SetNumberOfYDivisions(int num) +{ + if (this->NumberOfYDivisions == num && this->ComputeNumberOfDivisions == 0) + { + return; + } + if (num < 2) + { + vtkErrorMacro("You cannot use less than two divisions."); + return; + } + this->Modified(); + this->NumberOfYDivisions = num; + this->ComputeNumberOfDivisions = 0; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::SetNumberOfZDivisions(int num) +{ + if (this->NumberOfZDivisions == num && this->ComputeNumberOfDivisions == 0) + { + return; + } + if (num < 2) + { + vtkErrorMacro("You cannot use less than two divisions."); + return; + } + this->Modified(); + this->NumberOfZDivisions = num; + this->ComputeNumberOfDivisions = 0; +} + + +//---------------------------------------------------------------------------- +int *vtkQuadricClustering::GetNumberOfDivisions() +{ + static int divs[3]; + this->GetNumberOfDivisions(divs); + return divs; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::GetNumberOfDivisions(int divs[3]) +{ + divs[0] = this->NumberOfXDivisions; + divs[1] = this->NumberOfYDivisions; + divs[2] = this->NumberOfZDivisions; +} + + + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::SetDivisionOrigin(double x, double y, double z) +{ + if (this->ComputeNumberOfDivisions && this->DivisionOrigin[0] == x && + this->DivisionOrigin[1] == y && this->DivisionOrigin[2] == z) + { + return; + } + this->Modified(); + this->DivisionOrigin[0] = x; + this->DivisionOrigin[1] = y; + this->DivisionOrigin[2] = z; + this->ComputeNumberOfDivisions = 1; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::SetDivisionSpacing(double x, double y, double z) +{ + if (this->ComputeNumberOfDivisions && this->DivisionSpacing[0] == x && + this->DivisionSpacing[1] == y && this->DivisionSpacing[2] == z) + { + return; + } + if ( x <= 0 ) + { + vtkErrorMacro( << "Spacing (x) should be larger than 0.0, setting to 1.0" ); + x = 1.0; + } + if ( y <= 0 ) + { + vtkErrorMacro( << "Spacing (y) should be larger than 0.0, setting to 1.0" ); + y = 1.0; + } + if ( z <= 0 ) + { + vtkErrorMacro( << "Spacing (z) should be larger than 0.0, setting to 1.0" ); + z = 1.0; + } + this->Modified(); + this->DivisionSpacing[0] = x; + this->DivisionSpacing[1] = y; + this->DivisionSpacing[2] = z; + this->ComputeNumberOfDivisions = 1; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::EndAppendUsingPoints(vtkPolyData *input, + vtkPolyData *output) +{ + vtkIdType i; + vtkIdType outPtId; + vtkPoints *inputPoints; + vtkPoints *outputPoints; + vtkIdType numPoints, numBins; + vtkIdType binId; + double *minError, e, pt[3]; + double *q; + + inputPoints = input->GetPoints(); + if (inputPoints == NULL) + { + return; + } + + // Check for misuse of the Append methods. + if (this->OutputTriangleArray == NULL || this->OutputLines == NULL) + { + vtkDebugMacro("Missing Array: Did you call StartAppend?"); + return; + } + + outputPoints = vtkPoints::New(); + + // Prepare to copy point data to output + output->GetPointData()-> + CopyAllocate(input->GetPointData(), this->NumberOfBinsUsed); + + // Allocate and initialize an array to hold errors for each bin. + numBins = this->NumberOfDivisions[0] * this->NumberOfDivisions[1] + * this->NumberOfDivisions[2]; + minError = new double[numBins]; + for (i = 0; i < numBins; ++i) + { + minError[i] = VTK_DOUBLE_MAX; + } + + // Loop through the input points. + numPoints = inputPoints->GetNumberOfPoints(); + for (i = 0; i < numPoints; ++i) + { + inputPoints->GetPoint(i, pt); + binId = this->HashPoint(pt); + outPtId = this->QuadricArray[binId].VertexId; + // Sanity check. + if (outPtId == -1) + { + // This condition happens when there are points in the input that are + // not used in any triangles, and therefore are never added to the + // 3D hash structure. + continue; + } + + // Compute the error for this point. Note: the constant term is ignored. + // It will be the same for every point in this bin, and it + // is not stored in the quadric array anyway. + q = this->QuadricArray[binId].Quadric; + e = q[0]*pt[0]*pt[0] + 2.0*q[1]*pt[0]*pt[1] + 2.0*q[2]*pt[0]*pt[2] + 2.0*q[3]*pt[0] + + q[4]*pt[1]*pt[1] + 2.0*q[5]*pt[1]*pt[2] + 2.0*q[6]*pt[1] + + q[7]*pt[2]*pt[2] + 2.0*q[8]*pt[2]; + if (e < minError[binId]) + { + minError[binId] = e; + outputPoints->InsertPoint(outPtId, pt); + + // Since this is the same point as the input point, copy point data here too. + output->GetPointData()->CopyData(input->GetPointData(),i,outPtId); + } + } + + output->SetPolys(this->OutputTriangleArray); + output->SetPoints(outputPoints); + outputPoints->Delete(); + this->OutputTriangleArray->Delete(); + this->OutputTriangleArray = NULL; + + if (this->OutputLines->GetNumberOfCells() > 0) + { + output->SetLines(this->OutputLines); + } + this->OutputLines->Delete(); + this->OutputLines = NULL; + + this->EndAppendVertexGeometry(input, output); + + if (this->QuadricArray) + { + delete [] this->QuadricArray; + this->QuadricArray = NULL; + } + + delete [] minError; +} + +//---------------------------------------------------------------------------- +// This is not a perfect implementation, because it does not determine +// which vertex cell is the best for a bin. The first detected is used. +void vtkQuadricClustering::EndAppendVertexGeometry(vtkPolyData *input, + vtkPolyData *output) +{ + vtkCellArray *inVerts, *outVerts; + vtkIdType *tmp = NULL; + int tmpLength = 0; + int tmpIdx; + double pt[3]; + int j; + vtkIdType *ptIds = 0; + vtkIdType numPts = 0; + vtkIdType outPtId; + vtkIdType binId, cellId, outCellId; + + inVerts = input->GetVerts(); + outVerts = vtkCellArray::New(); + + for (cellId=0, inVerts->InitTraversal(); inVerts->GetNextCell(numPts, ptIds); cellId++) + { + if (tmpLength < numPts) + { + if (tmp) + { + delete tmp; + } + tmp = new vtkIdType[numPts]; + tmpLength = numPts; + } + tmpIdx = 0; + for (j = 0; j < numPts; ++j) + { + input->GetPoint(ptIds[j], pt); + binId = this->HashPoint(pt); + outPtId = this->QuadricArray[binId].VertexId; + if (outPtId >= 0) + { + // Do not use this point. Destroy infomration in Quadric array. + this->QuadricArray[binId].VertexId = -1; + tmp[tmpIdx] = outPtId; + ++tmpIdx; + } + } + if (tmpIdx > 0) + { + // add poly vertex to output. + outCellId = outVerts->InsertNextCell(tmpIdx, tmp); + output->GetCellData()-> + CopyData(input->GetCellData(), cellId, outCellId); + } + } + + if (tmp) + { + delete [] tmp; + } + + if (outVerts->GetNumberOfCells() > 0) + { + output->SetVerts(outVerts); + } + outVerts->Delete(); +} + + +//---------------------------------------------------------------------------- +// This method is called after the execution, but before the vertex array +// is deleted. It changes some points to be based on the boundary edges. +void vtkQuadricClustering::AppendFeatureQuadrics(vtkPolyData *pd, + vtkPolyData *output) +{ + vtkPolyData *input = vtkPolyData::New(); + vtkPoints *edgePts; + vtkCellArray *edges; + vtkIdType i; + vtkIdType binId; + double featurePt[3]; + + // Find the boundary edges. + input->ShallowCopy(pd); + this->FeatureEdges->SetInput(input); + this->FeatureEdges->Update(); + edgePts = this->FeatureEdges->GetOutput()->GetPoints(); + edges = this->FeatureEdges->GetOutput()->GetLines(); + + if (edges && edges->GetNumberOfCells() && edgePts) + { + this->AddEdges(edges, edgePts, 0, pd, output); + if (this->UseFeaturePoints) + { + this->FindFeaturePoints(edges, edgePts, this->FeaturePointsAngle); + for (i = 0; i < this->FeaturePoints->GetNumberOfPoints(); i++) + { + this->FeaturePoints->GetPoint(i, featurePt); + binId = this->HashPoint(featurePt); + this->AddVertex(binId, featurePt, 0, input, output); + } + } + } + + // Release data. + this->FeatureEdges->SetInputConnection(0, 0); + this->FeatureEdges->GetOutput()->ReleaseData(); + input->Delete(); +} + +// Find the feature points of a given set of edges. +// The points returned are (1) those used by only one edge, (2) those +// used by > 2 edges, and (3) those where the angle between 2 edges +// using this point is < angle. +void vtkQuadricClustering::FindFeaturePoints(vtkCellArray *edges, + vtkPoints *edgePts, + double vtkNotUsed(angle)) +{ + vtkIdType i, pointIds[2]; + int j; + vtkIdType *cellPts = 0; + vtkIdType numCellPts; + vtkIdList *pointIdList = vtkIdList::New(); + vtkIdType numPts = edgePts->GetNumberOfPoints(); + vtkIdType numEdges = edges->GetNumberOfCells(); + vtkIdType edgeCount; + vtkIdType **pointTable = new vtkIdType *[numPts]; + double featurePoint[3]; + double featureEdges[2][3]; + double point1[3], point2[3]; + vtkIdType *cellPointIds; + double radAngle = vtkMath::DegreesToRadians() * this->FeaturePointsAngle; + + this->FeaturePoints->Allocate(numPts); + + for (i = 0; i < numPts; i++) + { + pointTable[i] = new vtkIdType[4]; + pointTable[i][1] = 0; + } + + edges->InitTraversal(); + for (i = 0; i < numEdges; i++) + { + edges->GetNextCell(numCellPts, cellPts); + for (j = 0; j < 2; j++) + { + pointIds[j] = pointIdList->InsertUniqueId(cellPts[j]); + pointTable[pointIds[j]][0] = cellPts[j]; + edgeCount = pointTable[pointIds[j]][1]; + if (edgeCount < 2) + { + pointTable[pointIds[j]][edgeCount+2] = i; + } + pointTable[pointIds[j]][1]++; + } + } + + for (i = 0; i < numPts; i++) + { + if (pointTable[i][1] == 1) + { + edgePts->GetPoint(pointTable[i][0], featurePoint); + } + else if (pointTable[i][1] > 2) + { + edgePts->GetPoint(pointTable[i][0], featurePoint); + } + else if (pointTable[i][1] == 2) + { + for (j = 0; j < 2; j++) + { + edges->GetCell(3*pointTable[i][j+2], numCellPts, cellPointIds); + if (cellPointIds[0] == pointTable[i][0]) + { + edgePts->GetPoint(cellPointIds[0], point1); + edgePts->GetPoint(cellPointIds[1], point2); + } + else + { + edgePts->GetPoint(cellPointIds[1], point1); + edgePts->GetPoint(cellPointIds[0], point2); + } + featureEdges[j][0] = point2[0] - point1[0]; + featureEdges[j][1] = point2[1] - point1[1]; + featureEdges[j][2] = point2[2] - point1[2]; + vtkMath::Normalize(featureEdges[j]); + } + if (acos(vtkMath::Dot(featureEdges[0], featureEdges[1])) < radAngle) + { + edgePts->GetPoint(pointTable[i][0], featurePoint); + } + } + } + + pointIdList->Delete(); + for (i = 0; i < numPts; i++) + { + delete [] pointTable[i]; + } + delete [] pointTable; +} + +//---------------------------------------------------------------------------- +int vtkQuadricClustering::FillInputPortInformation(int port, + vtkInformation *info) +{ + int retval = this->Superclass::FillInputPortInformation(port, info); + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + return retval; +} + +//---------------------------------------------------------------------------- +void vtkQuadricClustering::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Bounds: " << this->Bounds[0] << " " << this->Bounds[1] + << " " << this->Bounds[2] << " " << this->Bounds[3] << " " + << this->Bounds[4] << " " << this->Bounds[5] << "\n"; + os << indent << "Use Input Points: " + << (this->UseInputPoints ? "On\n" : "Off\n"); + + if (this->ComputeNumberOfDivisions) + { + os << indent << "Using Spacing and Origin to construct bins\n"; + } + else + { + os << indent << "Using input bounds and NumberOfDivisions to construct bins\n"; + } + os << indent << "Division Spacing: " << this->DivisionSpacing[0] << ", " + << this->DivisionSpacing[1] << ", " << this->DivisionSpacing[2] << endl; + os << indent << "Division Origin: " << this->DivisionOrigin[0] << ", " + << this->DivisionOrigin[1] << ", " << this->DivisionOrigin[2] << endl; + + os << indent << "Number of X Divisions: " << this->NumberOfXDivisions + << "\n"; + os << indent << "Number of Y Divisions: " << this->NumberOfYDivisions + << "\n"; + os << indent << "Number of Z Divisions: " << this->NumberOfZDivisions + << "\n"; + + os << indent << "Auto Adjust Number Of Divisions: " + << (this->AutoAdjustNumberOfDivisions ? "On\n" : "Off\n"); + + os << indent << "Use Internal Triangles: " + << (this->UseInternalTriangles ? "On\n" : "Off\n"); + + os << indent << "Use Feature Edges: " << this->UseFeatureEdges << endl; + os << indent << "FeatureEdges: (" << this->FeatureEdges << ")\n"; + + os << indent << "Feature Points Angle: " << this->FeaturePointsAngle << endl; + os << indent << "Use Feature Points: " + << (this->UseFeaturePoints ? "On\n" : "Off\n"); + os << indent << "Copy Cell Data : " << this->CopyCellData << endl; +} + diff --git a/Graphics/vtkQuadricClustering.h b/Graphics/vtkQuadricClustering.h new file mode 100644 index 0000000..883a450 --- /dev/null +++ b/Graphics/vtkQuadricClustering.h @@ -0,0 +1,329 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadricClustering.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadricClustering - reduce the number of triangles in a mesh +// .SECTION Description +// vtkQuadricClustering is a filter to reduce the number of triangles in a +// triangle mesh, forming a good approximation to the original geometry. The +// input to vtkQuadricClustering is a vtkPolyData object, and all types of +// polygonal data are handled. +// +// The algorithm used is the one described by Peter Lindstrom in his Siggraph +// 2000 paper, "Out-of-Core Simplification of Large Polygonal Models." The +// general approach of the algorithm is to cluster vertices in a uniform +// binning of space, accumulating the quadric of each triangle (pushed out to +// the triangles vertices) within each bin, and then determining an optimal +// position for a single vertex in a bin by using the accumulated quadric. In +// more detail, the algorithm first gets the bounds of the input poly data. +// It then breaks this bounding volume into a user-specified number of +// spatial bins. It then reads each triangle from the input and hashes its +// vertices into these bins. (If this is the first time a bin has been +// visited, initialize its quadric to the 0 matrix.) The algorithm computes +// the error quadric for this triangle and adds it to the existing quadric of +// the bin in which each vertex is contained. Then, if 2 or more vertices of +// the triangle fall in the same bin, the triangle is dicarded. If the +// triangle is not discarded, it adds the triangle to the list of output +// triangles as a list of vertex identifiers. (There is one vertex id per +// bin.) After all the triangles have been read, the representative vertex +// for each bin is computed (an optimal location is found) using the quadric +// for that bin. This determines the spatial location of the vertices of +// each of the triangles in the output. +// +// To use this filter, specify the divisions defining the spatial subdivision +// in the x, y, and z directions. You must also specify an input vtkPolyData. +// Then choose to either 1) use the original points that minimize the quadric +// error to produce the output triangles or 2) compute an optimal position in +// each bin to produce the output triangles (recommended and default behavior). +// +// This filter can take multiple inputs. To do this, the user must explicity +// call StartAppend, Append (once for each input), and EndAppend. StartAppend +// sets up the data structure to hold the quadric matrices. Append processes +// each triangle in the input poly data it was called on, hashes its vertices +// to the appropriate bins, determines whether to keep this triangle, and +// updates the appropriate quadric matrices. EndAppend determines the spatial +// location of each of the representative vertices for the visited bins. While +// this approach does not fit into the visualization architecture and requires +// manual control, it has the advantage that extremely large data can be +// processed in pieces and appended to the filter piece-by-piece. + + +// .SECTION Caveats +// This filter can drastically affect topology, i.e., topology is not +// preserved. +// +// The filter handles input triangle strips and arbitrary polygons. Arbitrary +// polygons are assumed convex: during insertion they are triangulated using +// a fan of triangles from the first point in the polygons. If the polygon is +// concave, this can produce bad results. In this case, use vtkTriangleFilter +// to triangulate the polygons first. + +// .SECTION See Also +// vtkQuadricDecimation vtkDecimatePro vtkDecimate + +#ifndef __vtkQuadricClustering_h +#define __vtkQuadricClustering_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkFeatureEdges; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkQuadricClustering : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkQuadricClustering, vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkQuadricClustering *New(); + + // Description: + // Set/Get the number of divisions along each axis for the spatial bins. + // The number of spatial bins is NumberOfXDivisions*NumberOfYDivisions* + // NumberOfZDivisions. The filter may choose to ignore large numbers of + // divisions if the input has few points and AutoAdjustNumberOfDivisions + // is enabled. + void SetNumberOfXDivisions(int num); + void SetNumberOfYDivisions(int num); + void SetNumberOfZDivisions(int num); + vtkGetMacro(NumberOfXDivisions, int); + vtkGetMacro(NumberOfYDivisions, int); + vtkGetMacro(NumberOfZDivisions, int); + void SetNumberOfDivisions(int div[3]) + { this->SetNumberOfDivisions(div[0], div[1], div[2]); } + void SetNumberOfDivisions(int div0, int div1, int div2); + int *GetNumberOfDivisions(); + void GetNumberOfDivisions(int div[3]); + + // Description: + // Enable automatic adjustment of number of divisions. If off, the number + // of divisions specified by the user is always used (as long as it is valid). + vtkSetMacro(AutoAdjustNumberOfDivisions,int); + vtkGetMacro(AutoAdjustNumberOfDivisions,int); + vtkBooleanMacro(AutoAdjustNumberOfDivisions,int); + + // Description: + // This is an alternative way to set up the bins. If you are trying to match + // boundaries between pieces, then you should use these methods rather than + // SetNumberOfDivisions. To use these methods, specify the origin and spacing + // of the spatial binning. + void SetDivisionOrigin(double x, double y, double z); + void SetDivisionOrigin(double o[3]) + {this->SetDivisionOrigin(o[0],o[1],o[2]);} + vtkGetVector3Macro(DivisionOrigin, double); + void SetDivisionSpacing(double x, double y, double z); + void SetDivisionSpacing(double s[3]) + {this->SetDivisionSpacing(s[0],s[1],s[2]);} + vtkGetVector3Macro(DivisionSpacing, double); + + // Description: + // Normally the point that minimizes the quadric error function is used as + // the output of the bin. When this flag is on, the bin point is forced to + // be one of the points from the input (the one with the smallest + // error). This option does not work (i.e., input points cannot be used) + // when the append methods (StartAppend(), Append(), EndAppend()) are being + // called directly. + vtkSetMacro(UseInputPoints, int); + vtkGetMacro(UseInputPoints, int); + vtkBooleanMacro(UseInputPoints, int); + + // Description: + // By default, this flag is off. When "UseFeatureEdges" is on, then + // quadrics are computed for boundary edges/feature edges. They influence + // the quadrics (position of points), but not the mesh. Which features to + // use can be controlled by the filter "FeatureEdges". + vtkSetMacro(UseFeatureEdges, int); + vtkGetMacro(UseFeatureEdges, int); + vtkBooleanMacro(UseFeatureEdges, int); + vtkFeatureEdges *GetFeatureEdges() {return this->FeatureEdges;} + + // Description: + // By default, this flag is off. It only has an effect when + // "UseFeatureEdges" is also on. When "UseFeaturePoints" is on, then + // quadrics are computed for boundary / feature points used in the boundary + // / feature edges. They influence the quadrics (position of points), but + // not the mesh. + vtkSetMacro(UseFeaturePoints, int); + vtkGetMacro(UseFeaturePoints, int); + vtkBooleanMacro(UseFeaturePoints, int); + + // Description: + // Set/Get the angle to use in determining whether a point on a boundary / + // feature edge is a feature point. + vtkSetClampMacro(FeaturePointsAngle, double, 0.0, 180.0); + vtkGetMacro(FeaturePointsAngle, double); + + // Description: + // When this flag is on (and it is on by default), then triangles that are + // completely contained in a bin are added to the bin quadrics. When the + // the flag is off the filter operates faster, but the surface may not be + // as well behaved. + vtkSetMacro(UseInternalTriangles, int); + vtkGetMacro(UseInternalTriangles, int); + vtkBooleanMacro(UseInternalTriangles, int); + + // Description: + // These methods provide an alternative way of executing the filter. + // PolyData can be added to the result in pieces (append). + // In this mode, the user must specify the bounds of the entire model + // as an argument to the "StartAppend" method. + void StartAppend(double *bounds); + void StartAppend(double x0,double x1,double y0,double y1,double z0,double z1) + {double b[6]; b[0]=x0; b[1]=x1; b[2]=y0; b[3]=y1; b[4]=z0; b[5]=z1; + this->StartAppend(b);} + void Append(vtkPolyData *piece); + void EndAppend(); + + // Description: + // This flag makes the filter copy cell data from input to output + // (the best it can). It uses input cells that trigger the addition + // of output cells (no averaging). This is off by default, and does + // not work when append is being called explicitely (non-pipeline usage). + vtkSetMacro(CopyCellData, int); + vtkGetMacro(CopyCellData, int); + vtkBooleanMacro(CopyCellData, int); + +protected: + vtkQuadricClustering(); + ~vtkQuadricClustering(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int FillInputPortInformation(int, vtkInformation *); + + // Description: + // Given a point, determine what bin it falls into. + vtkIdType HashPoint(double point[3]); + + // Description: + // Determine the representative point for this bin. + void ComputeRepresentativePoint(double quadric[9], vtkIdType binId, + double point[3]); + + // Description: + // Add triangles to the quadric array. If geometry flag is on then + // triangles are added to the output. + void AddPolygons(vtkCellArray *polys, vtkPoints *points, int geometryFlag, + vtkPolyData *input, vtkPolyData *output); + void AddStrips(vtkCellArray *strips, vtkPoints *points, int geometryFlag, + vtkPolyData *input, vtkPolyData *output); + void AddTriangle(vtkIdType *binIds, double *pt0, double *pt1, double *pt2, + int geometeryFlag, vtkPolyData *input, vtkPolyData *output); + + // Description: + // Add edges to the quadric array. If geometry flag is on then + // edges are added to the output. + void AddEdges(vtkCellArray *edges, vtkPoints *points, + int geometryFlag, + vtkPolyData *input, vtkPolyData *output); + void AddEdge(vtkIdType *binIds, double *pt0, double *pt1, int geometeryFlag, + vtkPolyData *input, vtkPolyData *output); + + // Description: + // Add vertices to the quadric array. If geometry flag is on then + // vertices are added to the output. + void AddVertices(vtkCellArray *verts, vtkPoints *points, int geometryFlag, + vtkPolyData *input, vtkPolyData *output); + void AddVertex(vtkIdType binId, double *pt, int geometryFlag, + vtkPolyData *input, vtkPolyData *output); + + // Description: + // Initialize the quadric matrix to 0's. + void InitializeQuadric(double quadric[9]); + + // Description: + // Add this quadric to the quadric already associated with this bin. + void AddQuadric(vtkIdType binId, double quadric[9]); + + // Description: + // Find the feature points of a given set of edges. + // The points returned are (1) those used by only one edge, (2) those + // used by > 2 edges, and (3) those where the angle between 2 edges + // using this point is < angle. + void FindFeaturePoints(vtkCellArray *edges, vtkPoints *edgePts, double angle); + + // Description: + // This method will rep[lace the quadric generated points with the + // input points with the lowest error. + void EndAppendUsingPoints(vtkPolyData *input, vtkPolyData *output); + int UseInputPoints; + + // Description: + // This method sets the verticies of the output. + // It duplicates the structure of the input cells (but decimiated). + void EndAppendVertexGeometry(vtkPolyData *input, vtkPolyData *output); + + // Unfinished option to handle boundary edges differently. + void AppendFeatureQuadrics(vtkPolyData *pd, vtkPolyData *output); + int UseFeatureEdges; + int UseFeaturePoints; + int UseInternalTriangles; + + int NumberOfXDivisions; + int NumberOfYDivisions; + int NumberOfZDivisions; + + // Used internally. + // can be smaller than user values when input numb er of points is small. + int NumberOfDivisions[3]; + + // Since there are two was of specifing the grid, we have this flag + // to indicate which the user has set. When this flag is on, + // the bin sizes are computed from the DivisionOrigin and DivisionSpacing. + int ComputeNumberOfDivisions; + + double DivisionOrigin[3]; + double DivisionSpacing[3]; + int AutoAdjustNumberOfDivisions; + + double Bounds[6]; + double XBinSize; + double YBinSize; + double ZBinSize; + vtkIdType SliceSize; //eliminate one multiplication + + //BTX + struct PointQuadric + { + PointQuadric():VertexId(-1),Dimension(255) {} + + vtkIdType VertexId; + // Dimension is supposed to be a flag representing the dimension of the + // cells contributing to the quadric. Lines: 1, Triangles: 2 (and points + // 0 in the future?) + unsigned char Dimension; + double Quadric[9]; + }; + //ETX + + PointQuadric* QuadricArray; + vtkIdType NumberOfBinsUsed; + + // Have to make these instance variables if we are going to allow + // the algorithm to be driven by the Append methods. + vtkCellArray *OutputTriangleArray; + vtkCellArray *OutputLines; + + vtkFeatureEdges *FeatureEdges; + vtkPoints *FeaturePoints; + double FeaturePointsAngle; + + int CopyCellData; + int InCellCount; + int OutCellCount; + +private: + vtkQuadricClustering(const vtkQuadricClustering&); // Not implemented. + void operator=(const vtkQuadricClustering&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkQuadricDecimation.cxx b/Graphics/vtkQuadricDecimation.cxx new file mode 100644 index 0000000..3759864 --- /dev/null +++ b/Graphics/vtkQuadricDecimation.cxx @@ -0,0 +1,1377 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadricDecimation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Comments from Brad--- +// FIXME: I do not have a very good method for detecting the stability of a +// matrix + +// FIXME: improve the combination of boundary constraints and texture +// coordinates + +// FIXME: I want to turn off copying an attribute by default and then enable +// it in the ComputeNumberOfComponets function + +// ISSUE: CheckPlacement is not really a manifold check, should there be a +// topological manifold check? + +// ISSUE: I know I use to think that there was an error in the way Hugues +// desribed the area coefficient, but it now seems wrong to me and seems to +// produce better results with it not squared, may be this should be some +// kind of user parameter? Both seem useful ie uniform area vs. more +// curvature dependent + +// ISSUE: policy on attributes, normals should be renomrlized, should texture +// coordinates be clamped? or just indicate that one might want to use the +// array calculator to fix these? + +// ISSUE: the initial value of the Attribute weights is one, this is generaly +// not useful, ussually set around .1, but I did this because the the +// toggling on and off sets it to 1 and 0 + +#include "vtkQuadricDecimation.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkEdgeTable.h" +#include "vtkDoubleArray.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPointData.h" +#include "vtkPriorityQueue.h" +#include "vtkTriangle.h" + +vtkCxxRevisionMacro(vtkQuadricDecimation, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkQuadricDecimation); + + +//---------------------------------------------------------------------------- +vtkQuadricDecimation::vtkQuadricDecimation() +{ + this->Edges = vtkEdgeTable::New(); + this->EdgeCosts = vtkPriorityQueue::New(); + this->EndPoint1List = vtkIdList::New(); + this->EndPoint2List = vtkIdList::New(); + this->ErrorQuadrics = NULL; + this->TargetPoints = vtkDoubleArray::New(); + + this->TargetReduction = 0.9; + this->NumberOfEdgeCollapses = 0; + this->NumberOfComponents = 0; + + this->AttributeErrorMetric = 0; + this->ScalarsAttribute = 1; + this->VectorsAttribute = 1; + this->NormalsAttribute = 1; + this->TCoordsAttribute = 1; + this->TensorsAttribute = 1; + + this->ScalarsWeight = 0.1; + this->VectorsWeight = 0.1; + this->NormalsWeight = 0.1; + this->TCoordsWeight = 0.1; + this->TensorsWeight = 0.1; + + this->ActualReduction = 0.0; +} + +//---------------------------------------------------------------------------- +vtkQuadricDecimation::~vtkQuadricDecimation() +{ + this->Edges->Delete(); + this->EdgeCosts->Delete(); + this->EndPoint1List->Delete(); + this->EndPoint2List->Delete(); + this->TargetPoints->Delete(); +} + +void vtkQuadricDecimation::SetPointAttributeArray(vtkIdType ptId, + const double *x) +{ + int i; + this->Mesh->GetPoints()->SetPoint(ptId, x); + + for (i = 0; i < this->NumberOfComponents; i++) + { + if (i < this->AttributeComponents[0]) + { + this->Mesh->GetPointData()->GetScalars()-> + SetComponent(ptId, i, x[3+i]/this->AttributeScale[0]); + } + else if (i < this->AttributeComponents[1]) + { + this->Mesh->GetPointData()->GetVectors()-> + SetComponent(ptId, i-this->AttributeComponents[0], x[3+i]/this->AttributeScale[1]); + } + else if (i < this->AttributeComponents[2]) + { + this->Mesh->GetPointData()->GetNormals()-> + SetComponent(ptId, i-this->AttributeComponents[1], x[3+i]/this->AttributeScale[2]); + } + else if (i < this->AttributeComponents[3]) + { + this->Mesh->GetPointData()->GetTCoords()-> + SetComponent(ptId, i-this->AttributeComponents[2], x[3+i]/this->AttributeScale[3]); + } + else if (i < this->AttributeComponents[4]) + { + this->Mesh->GetPointData()->GetTensors()-> + SetComponent(ptId, i-this->AttributeComponents[3], x[3+i]/this->AttributeScale[4]); + } + } +} + +void vtkQuadricDecimation::GetPointAttributeArray(vtkIdType ptId, double *x) +{ + int i; + this->Mesh->GetPoints()->GetPoint(ptId, x); + + for (i = 0; i < this->NumberOfComponents; i++) + { + if (i < this->AttributeComponents[0]) + { + x[3+i] = this->Mesh->GetPointData()->GetScalars()-> + GetComponent(ptId, i) * this->AttributeScale[0]; + } + else if (i < this->AttributeComponents[1]) + { + x[3+i] = this->Mesh->GetPointData()->GetVectors()-> + GetComponent(ptId, i-this->AttributeComponents[0]) * this->AttributeScale[1]; + } + else if (i < this->AttributeComponents[2]) + { + x[3+i] = this->Mesh->GetPointData()->GetNormals()-> + GetComponent(ptId, i-this->AttributeComponents[1]) * this->AttributeScale[2]; + } + else if (i < this->AttributeComponents[3]) + { + x[3+i] = this->Mesh->GetPointData()->GetTCoords()-> + GetComponent(ptId, i-this->AttributeComponents[2]) * this->AttributeScale[3]; + } + else if (i < this->AttributeComponents[4]) + { + x[3+i] = this->Mesh->GetPointData()->GetTensors()-> + GetComponent(ptId, i-this->AttributeComponents[3]) * this->AttributeScale[4]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkQuadricDecimation::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numTris = input->GetNumberOfPolys(); + vtkIdType edgeId, i; + int j; + double cost; + double *x; + vtkCellArray *polys; + vtkDataArray *attrib; + vtkPoints *points; + vtkPointData *pointData; + vtkIdType endPtIds[2]; + vtkIdList *outputCellList; + vtkIdType npts, *pts; + vtkIdType numDeletedTris=0; + + // check some assuptiona about the data + if (input->GetPolys() == NULL || input->GetPoints() == NULL || + input->GetPointData() == NULL || input->GetFieldData() == NULL) + { + vtkErrorMacro("Nothing to decimate"); + return 1; + } + + if (input->GetPolys()->GetMaxCellSize() > 3) + { + vtkErrorMacro("Can only decimate triangles"); + return 1; + } + + polys = vtkCellArray::New(); + points = vtkPoints::New(); + pointData = vtkPointData::New(); + outputCellList = vtkIdList::New(); + + // copy the input (only polys) to our working mesh + this->Mesh = vtkPolyData::New(); + points->DeepCopy(input->GetPoints()); + this->Mesh->SetPoints(points); + points->Delete(); + polys->DeepCopy(input->GetPolys()); + this->Mesh->SetPolys(polys); + polys->Delete(); + if (this->AttributeErrorMetric) + { + this->Mesh->GetPointData()->DeepCopy(input->GetPointData()); + } + pointData->Delete(); + this->Mesh->GetFieldData()->PassData(input->GetFieldData()); + this->Mesh->BuildCells(); + this->Mesh->BuildLinks(); + + this->ErrorQuadrics = + new vtkQuadricDecimation::ErrorQuadric[numPts]; + + vtkDebugMacro(<<"Computing Edges"); + this->Edges->InitEdgeInsertion(numPts, 1); // storing edge id as attribute + this->EdgeCosts->Allocate(this->Mesh->GetPolys()->GetNumberOfCells() * 3); + for (i = 0; i < this->Mesh->GetNumberOfCells(); i++) + { + this->Mesh->GetCellPoints(i, npts, pts); + + for (j = 0; j < 3; j++) + { + if (this->Edges->IsEdge(pts[j], pts[(j+1)%3]) == -1) + { + // If this edge has not been processed, get an id for it, add it to + // the edge list (Edges), and add its endpoints to the EndPoint1List + // and EndPoint2List (the 2 endpoints to different lists). + edgeId = this->Edges->GetNumberOfEdges(); + this->Edges->InsertEdge(pts[j], pts[(j+1)%3], edgeId); + this->EndPoint1List->InsertId(edgeId, pts[j]); + this->EndPoint2List->InsertId(edgeId, pts[(j+1)%3]); + } + } + } + + this->UpdateProgress(0.1); + + this->NumberOfComponents = 0; + if (this->AttributeErrorMetric) + { + this->ComputeNumberOfComponents(); + } + x = new double [3+this->NumberOfComponents]; + this->CollapseCellIds = vtkIdList::New(); + this->TempX = new double [3+this->NumberOfComponents]; + this->TempQuad = new double[11 + 4 * this->NumberOfComponents]; + + this->TempB = new double [3 + this->NumberOfComponents]; + this->TempA = new double*[3 + this->NumberOfComponents]; + this->TempData = new double [(3 + this->NumberOfComponents)*(3 + this->NumberOfComponents)]; + for (i = 0; i < 3 + this->NumberOfComponents; i++) + { + this->TempA[i] = this->TempData+i*(3 + this->NumberOfComponents); + } + this->TargetPoints->SetNumberOfComponents(3+this->NumberOfComponents); + + vtkDebugMacro(<<"Computing Quadrics"); + this->InitializeQuadrics(numPts); + this->AddBoundaryConstraints(); + this->UpdateProgress(0.15); + + vtkDebugMacro(<<"Computing Costs"); + // Compute the cost of and target point for collapsing each edge. + for (i = 0; i < this->Edges->GetNumberOfEdges(); i++) + { + if (this->AttributeErrorMetric) + { + cost = this->ComputeCost2(i, x); + } + else + { + cost = this->ComputeCost(i, x); + } + this->EdgeCosts->Insert(cost, i); + this->TargetPoints->InsertTuple(i, x); + } + this->UpdateProgress(0.20); + + // Okay collapse edges until desired reduction is reached + this->ActualReduction = 0.0; + this->NumberOfEdgeCollapses = 0; + edgeId = this->EdgeCosts->Pop(0,cost); + + int abort = 0; + while ( !abort && edgeId >= 0 && cost < VTK_DOUBLE_MAX && + this->ActualReduction < this->TargetReduction ) + { + if ( ! (this->NumberOfEdgeCollapses % 10000) ) + { + vtkDebugMacro(<<"Collapsing edge#" << this->NumberOfEdgeCollapses); + this->UpdateProgress (0.20 + 0.80*this->NumberOfEdgeCollapses/numPts); + abort = this->GetAbortExecute(); + } + + endPtIds[0] = this->EndPoint1List->GetId(edgeId); + endPtIds[1] = this->EndPoint2List->GetId(edgeId); + this->TargetPoints->GetTuple(edgeId, x); + + // check for a poorly placed point + if ( !this->IsGoodPlacement(endPtIds[0], endPtIds[1], x)) + { + vtkDebugMacro(<<"Poor placement detected " << edgeId << " " << cost); + // return the point to the queue but with the max cost so that + // when it is recomputed it will be reconsidered + this->EdgeCosts->Insert(VTK_DOUBLE_MAX, edgeId); + + edgeId = this->EdgeCosts->Pop(0, cost); + continue; + } + + this->NumberOfEdgeCollapses++; + + // Set the new coordinates of point0. + this->SetPointAttributeArray(endPtIds[0], x); + vtkDebugMacro(<<"Cost: " << cost << " Edge: " + << endPtIds[0] << " " << endPtIds[1]); + + // Merge the quadrics of the two points. + this->AddQuadric(endPtIds[1], endPtIds[0]); + + this->UpdateEdgeData(endPtIds[0], endPtIds[1]); + + // Update the output triangles. + numDeletedTris += this->CollapseEdge(endPtIds[0], endPtIds[1]); + this->ActualReduction = (double) numDeletedTris / numTris; + edgeId = this->EdgeCosts->Pop(0, cost); + } + + vtkDebugMacro(<<"Number Of Edge Collapses: " + << this->NumberOfEdgeCollapses << " Cost: " << cost); + + // clean up working data + for (i = 0; i < numPts; i++) + { + delete [] this->ErrorQuadrics[i].Quadric; + } + delete [] this->ErrorQuadrics; + delete [] x; + this->CollapseCellIds->Delete(); + delete [] this->TempX; + delete [] this->TempQuad; + delete [] this->TempB; + delete [] this->TempA; + delete [] this->TempData; + + // copy the simplified mesh from the working mesh to the output mesh + for (i = 0; i < this->Mesh->GetNumberOfCells(); i++) + { + if (this->Mesh->GetCell(i)->GetCellType() != VTK_EMPTY_CELL) + { + outputCellList->InsertNextId(i); + } + } + + output->Reset(); + output->Allocate(this->Mesh, outputCellList->GetNumberOfIds()); + output->GetPointData()->CopyAllocate(this->Mesh->GetPointData(),1); + output->CopyCells(this->Mesh, outputCellList); + + this->Mesh->DeleteLinks(); + this->Mesh->Delete(); + outputCellList->Delete(); + + // renormalize, clamp attributes + if (this->AttributeErrorMetric) + { + if (NULL != (attrib = output->GetPointData()->GetNormals())) + { + for (i = 0; i < attrib->GetNumberOfTuples(); i++) + { + vtkMath::Normalize(attrib->GetTuple3(i)); + } + } + // might want to add clamping texture coordinates?? + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkQuadricDecimation::InitializeQuadrics(vtkIdType numPts) +{ + vtkPolyData *input = this->Mesh; + double *QEM; + vtkIdType ptId; + int i, j; + vtkCellArray *polys; + vtkIdType npts, *pts=NULL; + double point0[3], point1[3], point2[3]; + double n[3]; + double tempP1[3], tempP2[3], d, triArea2; + double data[16]; + double *A[4], x[4]; + int index[4]; + A[0] = data; + A[1] = data+4; + A[2] = data+8; + A[3] = data+12; + + // allocate local QEM sparce matrix + QEM = new double[11 + 4 * this->NumberOfComponents]; + + // clear and allocate global QEM array + for (ptId = 0; ptId < numPts; ptId++) + { + this->ErrorQuadrics[ptId].Quadric = + new double[11 + 4 * this->NumberOfComponents]; + for (i = 0; i < 11 + 4 * this->NumberOfComponents; i++) + { + this->ErrorQuadrics[ptId].Quadric[i] = 0.0; + } + } + + polys = input->GetPolys(); + // compute the QEM for each face + for (polys->InitTraversal(); polys->GetNextCell(npts, pts); ) + { + input->GetPoint(pts[0], point0); + input->GetPoint(pts[1], point1); + input->GetPoint(pts[2], point2); + for (i = 0; i < 3; i++) + { + tempP1[i] = point1[i] - point0[i]; + tempP2[i] = point2[i] - point0[i]; + } + vtkMath::Cross(tempP1, tempP2, n); + triArea2 = vtkMath::Normalize(n); + //triArea2 = (triArea2 * triArea2 * 0.25); + triArea2 = triArea2 * 0.5; + // I am unsure whether this should be squared or not?? + d = -vtkMath::Dot(n, point0); + // could possible add in angle weights?? + + // set the geometric part of the QEM + QEM[0] = n[0] * n[0]; + QEM[1] = n[0] * n[1]; + QEM[2] = n[0] * n[2]; + QEM[3] = d * n[0]; + + QEM[4] = n[1] * n[1]; + QEM[5] = n[1] * n[2]; + QEM[6] = d * n[1]; + + QEM[7] = n[2] * n[2]; + QEM[8] = d * n[2]; + + QEM[9] = d * d; + QEM[10] = 1; + + if (this->AttributeErrorMetric) + { + for (i = 0; i < 3; i++) + { + A[0][i] = point0[i]; + A[1][i] = point1[i]; + A[2][i] = point2[i]; + A[3][i] = n[i]; + } + A[0][3] = A[1][3] = A[2][3] = 1; + A[3][3] = 0; + + // should handle poorly condition matrix better + if (vtkMath::LUFactorLinearSystem(A, index, 4)) + { + for (i = 0; i < this->NumberOfComponents; i++) + { + x[3] = 0; + if (i < this->AttributeComponents[0]) + { + x[0] = input->GetPointData()->GetScalars()->GetComponent(pts[0], i) * this->AttributeScale[0]; + x[1] = input->GetPointData()->GetScalars()->GetComponent(pts[1], i) * this->AttributeScale[0]; + x[2] = input->GetPointData()->GetScalars()->GetComponent(pts[2], i) * this->AttributeScale[0]; + } + else if (i < this->AttributeComponents[1]) + { + x[0] = input->GetPointData()->GetVectors()->GetComponent(pts[0], i - this->AttributeComponents[0]) * this->AttributeScale[1]; + x[1] = input->GetPointData()->GetVectors()->GetComponent(pts[1], i - this->AttributeComponents[0]) * this->AttributeScale[1]; + x[2] = input->GetPointData()->GetVectors()->GetComponent(pts[2], i - this->AttributeComponents[0]) * this->AttributeScale[1]; + } + else if (i < this->AttributeComponents[2]) + { + x[0] = input->GetPointData()->GetNormals()->GetComponent(pts[0], i - this->AttributeComponents[1]) * this->AttributeScale[2]; + x[1] = input->GetPointData()->GetNormals()->GetComponent(pts[1], i - this->AttributeComponents[1]) * this->AttributeScale[2]; + x[2] = input->GetPointData()->GetNormals()->GetComponent(pts[2], i - this->AttributeComponents[1]) * this->AttributeScale[2]; + } + else if (i < this->AttributeComponents[3]) + { + x[0] = input->GetPointData()->GetTCoords()->GetComponent(pts[0], i - this->AttributeComponents[2]) * this->AttributeScale[3]; + x[1] = input->GetPointData()->GetTCoords()->GetComponent(pts[1], i - this->AttributeComponents[2])* this->AttributeScale[3]; + x[2] = input->GetPointData()->GetTCoords()->GetComponent(pts[2], i - this->AttributeComponents[2])* this->AttributeScale[3]; + } + else if (i < this->AttributeComponents[4]) + { + x[0] = input->GetPointData()->GetTensors()->GetComponent(pts[0], i - this->AttributeComponents[3])* this->AttributeScale[4]; + x[1] = input->GetPointData()->GetTensors()->GetComponent(pts[1], i - this->AttributeComponents[3])* this->AttributeScale[4]; + x[2] = input->GetPointData()->GetTensors()->GetComponent(pts[2], i - this->AttributeComponents[3])* this->AttributeScale[4]; + } + vtkMath::LUSolveLinearSystem(A, index, x, 4); + + // add in the contribution of this element into the QEM + QEM[0] += x[0] * x[0]; + QEM[1] += x[0] * x[1]; + QEM[2] += x[0] * x[2]; + QEM[3] += x[3] * x[0]; + + QEM[4] += x[1] * x[1]; + QEM[5] += x[1] * x[2]; + QEM[6] += x[3] * x[1]; + + QEM[7] += x[2] * x[2]; + QEM[8] += x[3] * x[2]; + + QEM[9] += x[3] * x[3]; + + QEM[11+i*4] = -x[0]; + QEM[12+i*4] = -x[1]; + QEM[13+i*4] = -x[2]; + QEM[14+i*4] = -x[3]; + } + } + else + { + vtkErrorMacro(<<"Unable to factor attribute matrix!"); + } + } + + // add the QEM to all point of the face + for (i = 0; i < 3; i++) + { + for (j = 0; j < 11 + 4 * this->NumberOfComponents; j++) + { + this->ErrorQuadrics[pts[i]].Quadric[j] += QEM[j] * triArea2; + } + } + }//for all triangles + + delete [] QEM; +} + + +void vtkQuadricDecimation::AddBoundaryConstraints(void) +{ + vtkPolyData *input = this->Mesh; + double *QEM; + vtkIdType cellId; + int i, j; + vtkIdType npts, *pts; + double t0[3], t1[3], t2[3]; + double e0[3], e1[3], n[3], c, d, w; + vtkIdList *cellIds = vtkIdList::New(); + + // allocate local QEM space matrix + QEM = new double[11 + 4 * this->NumberOfComponents]; + + for (cellId = 0; cellId < input->GetNumberOfCells(); cellId++) + { + input->GetCellPoints(cellId, npts, pts); + + for (i = 0; i < 3; i++) + { + input->GetCellEdgeNeighbors(cellId, pts[i], pts[(i+1)%3], cellIds); + if (cellIds->GetNumberOfIds() == 0) + { + // this is a boundary + input->GetPoint(pts[(i+2)%3], t0); + input->GetPoint(pts[i], t1); + input->GetPoint(pts[(i+1)%3], t2); + + // computing a plane which is orthogonal to line t1, t2 and incident + // with it + for (j = 0; j < 3; j++) + { + e0[j] = t2[j] - t1[j]; + } + for (j = 0; j < 3; j++) + { + e1[j] = t0[j] - t1[j]; + } + + // compute n so that it is orthogonal to e0 and parallel to the + // triangle + c = vtkMath::Dot(e0,e1)/(e0[0]*e0[0]+e0[1]*e0[1]+e0[2]*e0[2]); + for (j = 0; j < 3; j++) + { + n[j] = e1[j] - c*e0[j]; + } + vtkMath::Normalize(n); + d = -vtkMath::Dot(n, t1); + w = vtkMath::Norm(e0); + + //w *= w; + // area issue ?? + // could possible add in angle weights?? + QEM[0] = n[0] * n[0]; + QEM[1] = n[0] * n[1]; + QEM[2] = n[0] * n[2]; + QEM[3] = d * n[0]; + + QEM[4] = n[1] * n[1]; + QEM[5] = n[1] * n[2]; + QEM[6] = d * n[1]; + + QEM[7] = n[2] * n[2]; + QEM[8] = d * n[2]; + + QEM[9] = d * d; + + QEM[10] = 1; + + // need to add orthogonal plane with the other Attributes, but this + // is not clear?? + // check to interaction with attribute data + for (j = 0; j < 11; j++) + { + this->ErrorQuadrics[pts[i]].Quadric[j] += QEM[j]*w; + this->ErrorQuadrics[pts[(i+1)%3]].Quadric[j] += QEM[j]*w; + } + } + } + } + cellIds->Delete(); + delete [] QEM; +} + +//---------------------------------------------------------------------------- +void vtkQuadricDecimation::AddQuadric(vtkIdType oldPtId, vtkIdType newPtId) +{ + int i; + + for (i = 0; i < 11 + 4*this->NumberOfComponents; i++) + { + this->ErrorQuadrics[newPtId].Quadric[i] += + this->ErrorQuadrics[oldPtId].Quadric[i]; + } +} + +//---------------------------------------------------------------------------- +void vtkQuadricDecimation::FindAffectedEdges(vtkIdType p1Id, vtkIdType p2Id, + vtkIdList *edges) +{ + unsigned short ncells; + vtkIdType *cells, npts, *pts, edgeId; + unsigned short i, j; + + edges->Reset(); + this->Mesh->GetPointCells(p2Id, ncells, cells); + for (i = 0; i < ncells; i++) + { + this->Mesh->GetCellPoints(cells[i], npts, pts); + for (j = 0; j < 3; j++) + { + if (pts[j] != p1Id && pts[j] != p2Id && + (edgeId = this->Edges->IsEdge(pts[j], p2Id)) >= 0 && + edges->IsId(edgeId) == -1) + { + edges->InsertNextId(edgeId); + } + } + } + + this->Mesh->GetPointCells(p1Id, ncells, cells); + for (i = 0; i < ncells; i++) + { + this->Mesh->GetCellPoints(cells[i], npts, pts); + for (j = 0; j < 3; j++) + { + if (pts[j] != p1Id && pts[j] != p2Id && + (edgeId = this->Edges->IsEdge(pts[j], p1Id)) >= 0 && + edges->IsId(edgeId) == -1) + { + edges->InsertNextId(edgeId); + } + } + } +} + +// FIXME: memory allocation clean up +void vtkQuadricDecimation::UpdateEdgeData(vtkIdType pt0Id, vtkIdType pt1Id) +{ + vtkIdList *changedEdges = vtkIdList::New(); + vtkIdType i, edgeId, edge[2]; + double cost; + + // Find all edges with exactly either of these 2 endpoints. + this->FindAffectedEdges(pt0Id, pt1Id, changedEdges); + + // Reset the endpoints for these edges to reflect the new point from the + // collapsed edge. + // Add these new edges to the edge table. + // Remove the the changed edges from the priority queue. + for (i = 0; i < changedEdges->GetNumberOfIds(); i++) + { + edge[0] = this->EndPoint1List->GetId(changedEdges->GetId(i)); + edge[1] = this->EndPoint2List->GetId(changedEdges->GetId(i)); + + // Remove all affected edges from the priority queue. + // This does not include collapsed edge. + this->EdgeCosts->DeleteId(changedEdges->GetId(i)); + + // Determine the new set of edges + if (edge[0] == pt1Id) + { + if (this->Edges->IsEdge(edge[1], pt0Id) == -1) + { // The edge will be completely new, add it. + edgeId = this->Edges->GetNumberOfEdges(); + this->Edges->InsertEdge(edge[1], pt0Id, edgeId); + this->EndPoint1List->InsertId(edgeId, edge[1]); + this->EndPoint2List->InsertId(edgeId, pt0Id); + // Compute cost (target point/data) and add to priority cue. + if (this->AttributeErrorMetric) + { + cost = this->ComputeCost2(edgeId, this->TempX); + } + else + { + cost = this->ComputeCost(edgeId, this->TempX); + } + this->EdgeCosts->Insert(cost, edgeId); + this->TargetPoints->InsertTuple(edgeId, this->TempX); + } + } + else if (edge[1] == pt1Id) + { // The edge will be completely new, add it. + if (this->Edges->IsEdge(edge[0], pt0Id) == -1) + { + edgeId = this->Edges->GetNumberOfEdges(); + this->Edges->InsertEdge(edge[0], pt0Id, edgeId); + this->EndPoint1List->InsertId(edgeId, edge[0]); + this->EndPoint2List->InsertId(edgeId, pt0Id); + // Compute cost (target point/data) and add to priority cue. + if (this->AttributeErrorMetric) + { + cost = this->ComputeCost2(edgeId, this->TempX); + } + else + { + cost = this->ComputeCost(edgeId, this->TempX); + } + this->EdgeCosts->Insert(cost, edgeId); + this->TargetPoints->InsertTuple(edgeId, this->TempX); + } + } + else + { // This edge already has one point as the merged point. + if (this->AttributeErrorMetric) + { + cost = this->ComputeCost2(changedEdges->GetId(i), this->TempX); + } + else + { + cost = this->ComputeCost(changedEdges->GetId(i), this->TempX); + } + this->EdgeCosts->Insert(cost, changedEdges->GetId(i)); + this->TargetPoints->InsertTuple(changedEdges->GetId(i), this->TempX); + } + } + + changedEdges->Delete(); + return; +} + +//---------------------------------------------------------------------------- +double vtkQuadricDecimation::ComputeCost(vtkIdType edgeId, double *x) +{ + static const double errorNumber = 1e-10; + double temp[3], A[3][3], b[3]; + vtkIdType pointIds[2]; + double cost = 0.0; + double *index; + int i, j; + double newPoint [4]; + double v[3], c, norm, normTemp, temp2[3]; + double pt1[3], pt2[3]; + + pointIds[0] = this->EndPoint1List->GetId(edgeId); + pointIds[1] = this->EndPoint2List->GetId(edgeId); + + for (i = 0; i < 11 + 4 * this->NumberOfComponents; i++) + { + this->TempQuad[i] = this->ErrorQuadrics[pointIds[0]].Quadric[i] + + this->ErrorQuadrics[pointIds[1]].Quadric[i]; + } + + A[0][0] = this->TempQuad[0]; + A[0][1] = A[1][0] = this->TempQuad[1]; + A[0][2] = A[2][0] = this->TempQuad[2]; + A[1][1] = this->TempQuad[4]; + A[1][2] = A[2][1] = this->TempQuad[5]; + A[2][2] = this->TempQuad[7]; + + b[0] = -this->TempQuad[3]; + b[1] = -this->TempQuad[6]; + b[2] = -this->TempQuad[8]; + + norm = vtkMath::Norm(A[0]); + normTemp = vtkMath::Norm(A[1]); + norm = norm > normTemp ? norm : normTemp; + normTemp = vtkMath::Norm(A[2]); + norm = norm > normTemp ? norm : normTemp; + + if (fabs(vtkMath::Determinant3x3(A))/(norm*norm*norm) > errorNumber) + { + // it would be better to use the normal of the matrix to test singularity?? + vtkMath::LinearSolve3x3(A, b, x); + vtkMath::Multiply3x3(A,x,temp); + // error too high, backup plans + } + else + { + // cheapest point along the edge + this->Mesh->GetPoints()->GetPoint(pointIds[0], pt1); + this->Mesh->GetPoints()->GetPoint(pointIds[1], pt2); + v[0] = pt2[0] - pt1[0]; + v[1] = pt2[1] - pt1[1]; + v[2] = pt2[2] - pt1[2]; + + // equation for the edge pt1 + c * v + // attempt least squares fit for c for A*(pt1 + c * v) = b + vtkMath::Multiply3x3(A,v,temp2); + if (vtkMath::Dot(temp2, temp2) > errorNumber) + { + vtkMath::Multiply3x3(A,pt1,temp); + for (i = 0; i < 3; i++) + temp[i] = b[i] - temp[i]; + c = vtkMath::Dot(temp2, temp) / vtkMath::Dot(temp2, temp2); + for (i = 0; i < 3; i++) + x[i] = pt1[i]+c*v[i]; + } + else + { + // use mid point + // might want to change to best of mid and end points?? + for (i = 0; i < 3; i++) + { + x[i] = 0.5*(pt1[i]+pt2[i]); + } + } + } + + newPoint[0] = x[0]; + newPoint[1] = x[1]; + newPoint[2] = x[2]; + newPoint[3] = 1; + + // Compute the cost + // x'*quad*x + index = this->TempQuad; + for (i = 0; i < 4; i++) + { + cost += (*index++)*newPoint[i]*newPoint[i]; + for (j = i +1; j < 4; j++) + { + cost += 2.0*(*index++)*newPoint[i]*newPoint[j]; + } + } + + return cost; +} + + +//---------------------------------------------------------------------------- +double vtkQuadricDecimation::ComputeCost2(vtkIdType edgeId, double *x) +{ + // this function is so ugly because the functionality of converting an QEM + // into a dence matrix was not extracted into a separate function and + // neither was multiplication and some other matrix and vector primatives + static const double errorNumber = 1e-10; + vtkIdType pointIds[2]; + double cost = 0.0; + int i, j; + int solveOk; + + pointIds[0] = this->EndPoint1List->GetId(edgeId); + pointIds[1] = this->EndPoint2List->GetId(edgeId); + + for (i = 0; i < 11 + 4 * this->NumberOfComponents; i++) + { + this->TempQuad[i] = this->ErrorQuadrics[pointIds[0]].Quadric[i] + + this->ErrorQuadrics[pointIds[1]].Quadric[i]; + } + + // copy the temp quad into TempA + // converting from the sparce matrix format into a dence + this->TempA[0][0] = this->TempQuad[0]; + this->TempA[0][1] = this->TempA[1][0] = this->TempQuad[1]; + this->TempA[0][2] = this->TempA[2][0] = this->TempQuad[2]; + this->TempA[1][1] = this->TempQuad[4]; + this->TempA[1][2] = this->TempA[2][1] = this->TempQuad[5]; + this->TempA[2][2] = this->TempQuad[7]; + + this->TempB[0] = -this->TempQuad[3]; + this->TempB[1] = -this->TempQuad[6]; + this->TempB[2] = -this->TempQuad[8]; + + for (i = 3; i < 3 + this->NumberOfComponents; i++) + { + this->TempA[0][i] = this->TempA[i][0] = this->TempQuad[11+4*(i-3)]; + this->TempA[1][i] = this->TempA[i][1] = this->TempQuad[11+4*(i-3)+1]; + this->TempA[2][i] = this->TempA[i][2] = this->TempQuad[11+4*(i-3)+2]; + this->TempB[i] = -this->TempQuad[11+4*(i-3)+3]; + } + + for (i = 3; i < 3 + this->NumberOfComponents; i++) + { + for (j = 3; j < 3 + this->NumberOfComponents; j++) + { + if (i == j) + { + this->TempA[i][j] = this->TempQuad[10]; + } + else + { + this->TempA[i][j] = 0; + } + } + } + + for (i = 0; i < 3 + this->NumberOfComponents; i++) + { + x[i] = this->TempB[i]; + } + + // solve A*x = b + // this clobers A + // need to develop a quality of the solution test?? + solveOk = vtkMath::SolveLinearSystem(this->TempA, x, 3 + this->NumberOfComponents); + + // need to copy back into A + this->TempA[0][0] = this->TempQuad[0]; + this->TempA[0][1] = this->TempA[1][0] = this->TempQuad[1]; + this->TempA[0][2] = this->TempA[2][0] = this->TempQuad[2]; + this->TempA[1][1] = this->TempQuad[4]; + this->TempA[1][2] = this->TempA[2][1] = this->TempQuad[5]; + this->TempA[2][2] = this->TempQuad[7]; + + for (i = 3; i < 3 + this->NumberOfComponents; i++) + { + this->TempA[0][i] = this->TempA[i][0] = this->TempQuad[11+4*(i-3)]; + this->TempA[1][i] = this->TempA[i][1] = this->TempQuad[11+4*(i-3)+1]; + this->TempA[2][i] = this->TempA[i][2] = this->TempQuad[11+4*(i-3)+2]; + } + + for (i = 3; i < 3 + this->NumberOfComponents; i++) + { + for (j = 3; j < 3 + this->NumberOfComponents; j++) + { + if (i == j) + { + this->TempA[i][j] = this->TempQuad[10]; + } + else + { + this->TempA[i][j] = 0; + } + } + } + + // check for failure to solve the system + if (!solveOk) + { + // cheapest point along the edge + // this should not frequently occour, so I am using dynamic allocation + double *pt1 = new double [3+this->NumberOfComponents]; + double *pt2 = new double [3+this->NumberOfComponents]; + double *v = new double [3+this->NumberOfComponents]; + double *temp = new double [3+this->NumberOfComponents]; + double *temp2 = new double [3+this->NumberOfComponents]; + double d = 0; + double c = 0; + + this->GetPointAttributeArray(pointIds[0], pt1); + this->GetPointAttributeArray(pointIds[1], pt2); + for (i = 0; i < 3+this->NumberOfComponents; ++i) + { + v[i] = pt2[i] - pt2[i]; + } + + // equation for the edge pt1 + c * v + // attempt least squares fit for c for A*(pt1 + c * v) = b + // temp2 = A*v + for (i = 0; i < 3 + this->NumberOfComponents; ++i) + { + temp2[i] = 0; + for (j = 0; j < 3 + this->NumberOfComponents; ++j) + { + temp2[i] += this->TempA[i][j]*v[j]; + } + } + + // c = v dot v + for (i = 0; i < 3 + this->NumberOfComponents; ++i) + { + d += temp2[i]*temp2[i]; + } + + if ( d > errorNumber) + { + // temp = A*pt1 + for (i = 0; i < 3 + this->NumberOfComponents; ++i) + { + temp[i] = 0; + for (j = 0; j < 3 + this->NumberOfComponents; ++j) + { + temp[i] += this->TempA[i][j]*pt1[j]; + } + } + + for (i = 0; i < 3 + this->NumberOfComponents; i++) + { + temp[i] = this->TempB[i] - temp[i]; + } + + for (i = 0; i < 3 + this->NumberOfComponents; i++) + { + c += temp2[i]*temp[i]; + } + c = c/d; + + for (i = 0; i < 3 + this->NumberOfComponents; i++) + { + x[i] = pt1[i]+c*v[i]; + } + } + else + { + // use mid point + // might want to change to best of mid and end points?? + for (i = 0; i < 3 + this->NumberOfComponents; i++) + { + x[i] = 0.5*(pt1[i]+pt2[i]); + } + } + delete[] pt1; + delete[] pt2; + delete[] v; + delete[] temp; + delete[] temp2; + } + + // Compute the cost + // x'*A*x - 2*b*x + d + for (i = 0; i < 3+this->NumberOfComponents; i++) + { + cost += this->TempA[i][i]*x[i]*x[i]; + for (j = i+1; j < 3+this->NumberOfComponents; j++) + { + cost += 2.0*this->TempA[i][j]*x[i]*x[j]; + } + } + for (i = 0; i < 3+this->NumberOfComponents; i++) + { + cost -= 2.0 * this->TempB[i]*x[i]; + } + + cost += this->TempQuad[9]; + + return cost; +} + + +int vtkQuadricDecimation::CollapseEdge(vtkIdType pt0Id, vtkIdType pt1Id) +{ + int j, numDeleted=0; + vtkIdType i, npts, *pts, cellId; + + this->Mesh->GetPointCells(pt0Id, this->CollapseCellIds); + for (i = 0; i < this->CollapseCellIds->GetNumberOfIds(); i++) + { + cellId = this->CollapseCellIds->GetId(i); + this->Mesh->GetCellPoints(cellId, npts, pts); + for (j = 0; j < 3; j++) + { + if (pts[j] == pt1Id) + { + this->Mesh->RemoveCellReference(cellId); + this->Mesh->DeleteCell(cellId); + numDeleted++; + } + } + } + + this->Mesh->GetPointCells(pt1Id, this->CollapseCellIds); + this->Mesh->ResizeCellList(pt0Id, this->CollapseCellIds->GetNumberOfIds()); + for (i=0; i < this->CollapseCellIds->GetNumberOfIds(); i++) + { + cellId = this->CollapseCellIds->GetId(i); + this->Mesh->GetCellPoints(cellId, npts, pts); + // making sure we don't already have the triangle we're about to + // change this one to + if (pts[0] == pt1Id && this->Mesh->IsTriangle(pt0Id, pts[1], pts[2]) || + (pts[1] == pt1Id && this->Mesh->IsTriangle(pts[0], pt0Id, pts[2])) || + (pts[2] == pt1Id && this->Mesh->IsTriangle(pts[0], pts[1], pt0Id))) + { + this->Mesh->RemoveCellReference(cellId); + this->Mesh->DeleteCell(cellId); + numDeleted++; + } + else + { + this->Mesh->AddReferenceToCell(pt0Id, cellId); + this->Mesh->ReplaceCellPoint(cellId, pt1Id, pt0Id); + } + } + this->Mesh->DeletePoint(pt1Id); + + return numDeleted; +} + + +// triangle t0, t1, t2 and point x +// determins if t0 and x are on the same side of the plane defined by +// t1 and t2, and parallel to the normal of the triangle +int vtkQuadricDecimation::TrianglePlaneCheck(const double t0[3], + const double t1[3], + const double t2[3], + const double *x) { + double e0[3], e1[3], n[3], e2[3]; + double c; + int i; + + for (i = 0; i < 3; i++) + { + e0[i] = t2[i] - t1[i]; + } + for (i = 0; i < 3; i++) + { + e1[i] = t0[i] - t1[i]; + } + + // projection of e0 onto e1 + c = vtkMath::Dot(e0,e1)/(e0[0]*e0[0]+e0[1]*e0[1]+e0[2]*e0[2]); + for (i = 0; i < 3; i++) + { + n[i] = e1[i] - c*e0[i]; + } + + for ( i = 0; i < 3; i++) + { + e2[i] = x[i] - t1[i]; + } + + vtkMath::Normalize(n); + vtkMath::Normalize(e2); + if (vtkMath::Dot(n, e2) > 1e-5) + { + return 1; + } + else + { + return 0; + } +} + +int vtkQuadricDecimation::IsGoodPlacement(vtkIdType pt0Id, vtkIdType pt1Id, +const double *x) +{ + unsigned short ncells, i; + vtkIdType npts, *pts, ptId, *cells; + double pt1[3], pt2[3], pt3[3]; + + this->Mesh->GetPointCells(pt0Id, ncells, cells); + for (i = 0; i < ncells; i++) { + this->Mesh->GetCellPoints(cells[i], npts, pts); + // assume triangle + if (pts[0] != pt1Id && pts[1] != pt1Id && pts[2] != pt1Id) + { + for (ptId = 0; ptId < 3; ptId++) + { + if (pts[ptId] == pt0Id) + { + this->Mesh->GetPoint(pts[ptId], pt1); + this->Mesh->GetPoint(pts[(ptId+1)%3], pt2); + this->Mesh->GetPoint(pts[(ptId+2)%3], pt3); + if(!this->TrianglePlaneCheck(pt1, pt2, pt3, x)) + { + return 0; + } + } + } + } + } + + this->Mesh->GetPointCells(pt1Id, ncells, cells); + for (i = 0; i < ncells; i++) + { + this->Mesh->GetCellPoints(cells[i], npts, pts); + // assume triangle + if (pts[0] != pt0Id && pts[1] != pt0Id && pts[2] != pt0Id) + { + for (ptId = 0; ptId < 3; ptId++) + { + if (pts[ptId] == pt1Id) + { + this->Mesh->GetPoint(pts[ptId], pt1); + this->Mesh->GetPoint(pts[(ptId+1)%3], pt2); + this->Mesh->GetPoint(pts[(ptId+2)%3], pt3); + if(!this->TrianglePlaneCheck(pt1, pt2, pt3, x)) + { + return 0; + } + } + } + } + } + + return 1; +} + + +void vtkQuadricDecimation::ComputeNumberOfComponents(void) +{ + vtkPointData *pd = this->Mesh->GetPointData(); + int i, j; + double range[2], maxRange=0.0; + + this->NumberOfComponents = 0; + pd->CopyAllOff(); + + for (i = 0; i < 6; i++) + { + this->AttributeComponents[i] = 0; + this->AttributeScale[i] = 1.0; + } + + // Scalar attributes + if (pd->GetScalars() != NULL && this->ScalarsAttribute) + { + for (j = 0; j < pd->GetScalars()->GetNumberOfComponents(); j++) + { + pd->GetScalars()->GetRange(range, j); + maxRange = (maxRange < (range[1] - range[0]) ? + (range[1] - range[0]) : maxRange); + } + if (maxRange != 0.0) + { + this->NumberOfComponents += pd->GetScalars()->GetNumberOfComponents(); + pd->CopyScalarsOn(); + this->AttributeScale[0] = this->ScalarsWeight/maxRange; + maxRange = 0.0; + } + vtkDebugMacro("scalars "<< this->NumberOfComponents << " " + << this->AttributeScale[0]); + } + this->AttributeComponents[0] = this->NumberOfComponents; + + // Vector attributes + if (pd->GetVectors() != NULL && this->VectorsAttribute) + { + for (j = 0; j < pd->GetVectors()->GetNumberOfComponents(); j++) + { + pd->GetVectors()->GetRange(range, j); + maxRange = (maxRange < (range[1] - range[0]) ? + (range[1] - range[0]) : maxRange); + } + if (maxRange != 0.0) + { + this->NumberOfComponents += pd->GetVectors()->GetNumberOfComponents(); + pd->CopyVectorsOn(); + this->AttributeScale[1] = this->VectorsWeight/maxRange; + maxRange = 0.0; + } + vtkDebugMacro("vectors "<< this->NumberOfComponents << " " + << this->AttributeScale[1]); + } + this->AttributeComponents[1] = this->NumberOfComponents; + + // Normals attributes -- normals are assumed normalized + if (pd->GetNormals() != NULL && this->NormalsAttribute) + { + this->NumberOfComponents += 3; + pd->CopyNormalsOn(); + this->AttributeScale[2] = 0.5*this->NormalsWeight; + vtkDebugMacro("normals "<< this->NumberOfComponents << " " + << this->AttributeScale[2]); + } + this->AttributeComponents[2] = this->NumberOfComponents; + + // Texture coords attributes + if (pd->GetTCoords() != NULL && this->TCoordsAttribute) + { + for (j = 0; j < pd->GetTCoords()->GetNumberOfComponents(); j++) + { + pd->GetTCoords()->GetRange(range, j); + maxRange = (maxRange < (range[1] - range[0]) ? + (range[1] - range[0]) : maxRange); + } + if (maxRange != 0.0) + { + this->NumberOfComponents += pd->GetTCoords()->GetNumberOfComponents(); + pd->CopyTCoordsOn(); + this->AttributeScale[3] = this->TCoordsWeight/maxRange; + maxRange = 0.0; + } + vtkDebugMacro("tcoords "<< this->NumberOfComponents << " " + << this->AttributeScale[3]); + } + this->AttributeComponents[3] = this->NumberOfComponents; + + // Tensors attributes + if (pd->GetTensors() != NULL && this->TensorsAttribute) + { + for (j = 0; j < 9; j++) + { + pd->GetTensors()->GetRange(range, j); + maxRange = (maxRange < (range[1] - range[0]) ? + (range[1] - range[0]) : maxRange); + } + if (maxRange != 0.0) + { + this->NumberOfComponents += 9; + pd->CopyTensorsOn(); + this->AttributeScale[4] = this->TensorsWeight/maxRange; + } + vtkDebugMacro("tensors "<< this->NumberOfComponents << " " + << this->AttributeScale[4]); + } + this->AttributeComponents[4] = this->NumberOfComponents; + + vtkDebugMacro("Number of components: " << this->NumberOfComponents); +} + +//---------------------------------------------------------------------------- +void vtkQuadricDecimation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Target Reduction: " << this->TargetReduction << "\n"; + os << indent << "Actual Reduction: " << this->ActualReduction << "\n"; + + os << indent << "Attribute Error Metric: " + << (this->AttributeErrorMetric ? "On\n" : "Off\n"); + os << indent << "Scalars Attribute: " + << (this->ScalarsAttribute ? "On\n" : "Off\n"); + os << indent << "Vectors Attribute: " + << (this->VectorsAttribute ? "On\n" : "Off\n"); + os << indent << "Normals Attribute: " + << (this->NormalsAttribute ? "On\n" : "Off\n"); + os << indent << "TCoords Attribute: " + << (this->TCoordsAttribute ? "On\n" : "Off\n"); + os << indent << "Tensors Attribute: " + << (this->TensorsAttribute ? "On\n" : "Off\n"); + + os << indent << "Scalars Weight: " << this->ScalarsWeight << "\n"; + os << indent << "Vectors Weight: " << this->VectorsWeight << "\n"; + os << indent << "Normals Weight: " << this->NormalsWeight << "\n"; + os << indent << "TCoords Weight: " << this->TCoordsWeight << "\n"; + os << indent << "Tensors Weight: " << this->TensorsWeight << "\n"; +} diff --git a/Graphics/vtkQuadricDecimation.h b/Graphics/vtkQuadricDecimation.h new file mode 100644 index 0000000..44eda0e --- /dev/null +++ b/Graphics/vtkQuadricDecimation.h @@ -0,0 +1,236 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuadricDecimation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuadricDecimation - reduce the number of triangles in a mesh +// .SECTION Description +// vtkQuadricDecimation is a filter to reduce the number of triangles in +// a triangle mesh, forming a good approximation to the original geometry. +// The input to vtkQuadricDecimation is a vtkPolyData object, and only +// triangles are treated. If you desire to decimate polygonal meshes, first +// triangulate the polygons with vtkTriangleFilter. +// +// The algorithm is based on repeated edge collapses until the requested mesh +// reduction is achieved. Edges are placed in a priority queue based on the +// "cost" to delete the edge. The cost is an approximate measure of error +// (distance to the original surface)--described by the so-called quadric +// error measure. The quadric error measure is associated with each vertex of +// the mesh and represents a matrix of planes incident on that vertex. The +// distance of the planes to the vertex is the error in the position of the +// vertex (originally the vertex error iz zero). As edges are deleted, the +// quadric error measure associated with the two end points of the edge are +// summed (this combines the plane equations) and an optimal collapse point +// can be computed. Edges connected to the collapse point are then reinserted +// into the queue after computing the new cost to delete them. The process +// continues until the desired reduction level is reached or topological +// constraints prevent further reduction. Note that this basic algorithm can +// be extended to higher dimensions by +// taking into account variation in attributes (i.e., scalars, vectors, and +// so on). +// +// This paper is based on the work of Garland and Heckbert who first +// presented the quadric error measure at Siggraph '97 "Surface +// Simplification Using Quadric Error Metrics". For details of the algorithm +// Michael Garland's Ph.D. thesis is also recommended. Hughues Hoppe's Vis +// '99 paper, "New Quadric Metric for Simplifying Meshes with Appearance +// Attributes" is also a good take on the subject especially as it pertains +// to the error metric applied to attributes. +// +// .SECTION Thanks +// Thanks to Bradley Lowekamp of the National Library of Medicine/NIH for +// contributing this class. + +#ifndef __vtkQuadricDecimation_h +#define __vtkQuadricDecimation_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkEdgeTable; +class vtkIdList; +class vtkPointData; +class vtkPriorityQueue; +class vtkDoubleArray; + +class VTK_GRAPHICS_EXPORT vtkQuadricDecimation : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkQuadricDecimation, vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkQuadricDecimation *New(); + + // Description: + // Set/Get the desired reduction (expressed as a fraction of the original + // number of triangles). The actual reduction may be less depending on + // triangulation and topological constraints. + vtkSetClampMacro(TargetReduction, double, 0.0, 1.0); + vtkGetMacro(TargetReduction, double); + + // Description: + // Decide whether to include data attributes in the error metric. If off, + // then only geometric error is used to control the decimation. By default + // the attribute errors are off. + vtkSetMacro(AttributeErrorMetric, int); + vtkGetMacro(AttributeErrorMetric, int); + vtkBooleanMacro(AttributeErrorMetric, int); + + // Description: + // If attribute errors are to be included in the metric (i.e., + // AttributeErrorMetric is on), then the following flags control which + // attributes are to be included in the error calculation. By default all + // of these are on. + vtkSetMacro(ScalarsAttribute, int); + vtkGetMacro(ScalarsAttribute, int); + vtkBooleanMacro(ScalarsAttribute, int); + vtkSetMacro(VectorsAttribute, int); + vtkGetMacro(VectorsAttribute, int); + vtkBooleanMacro(VectorsAttribute, int); + vtkSetMacro(NormalsAttribute, int); + vtkGetMacro(NormalsAttribute, int); + vtkBooleanMacro(NormalsAttribute, int); + vtkSetMacro(TCoordsAttribute, int); + vtkGetMacro(TCoordsAttribute, int); + vtkBooleanMacro(TCoordsAttribute, int); + vtkSetMacro(TensorsAttribute, int); + vtkGetMacro(TensorsAttribute, int); + vtkBooleanMacro(TensorsAttribute, int); + + // Description: + // Set/Get the scaling weight contribution of the attribute. These + // values are used to weight the contribution of the attributes + // towards the error metric. + vtkSetMacro(ScalarsWeight, double); + vtkSetMacro(VectorsWeight, double); + vtkSetMacro(NormalsWeight, double); + vtkSetMacro(TCoordsWeight, double); + vtkSetMacro(TensorsWeight, double); + vtkGetMacro(ScalarsWeight, double); + vtkGetMacro(VectorsWeight, double); + vtkGetMacro(NormalsWeight, double); + vtkGetMacro(TCoordsWeight, double); + vtkGetMacro(TensorsWeight, double); + + // Description: + // Get the actual reduction. This value is only valid after the + // filter has executed. + vtkGetMacro(ActualReduction, double); + +protected: + vtkQuadricDecimation(); + ~vtkQuadricDecimation(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // Description: + // Do the dirty work of eliminating the edge; return the number of + // triangles deleted. + int CollapseEdge(vtkIdType pt0Id, vtkIdType pt1Id); + + // Description: + // Compute quadric for all vertices + void InitializeQuadrics(vtkIdType numPts); + + // Description: + // Free boundary edges are weighted + void AddBoundaryConstraints(void); + + // Description: + // Compute quadric for this vertex. + void ComputeQuadric(vtkIdType pointId); + + // Description: + // Add the quadrics for these 2 points since the edge between them has + // been collapsed. + void AddQuadric(vtkIdType oldPtId, vtkIdType newPtId); + + // Description: + // Compute cost for contracting this edge and the point that gives us this + // cost. + double ComputeCost(vtkIdType edgeId, double *x); + double ComputeCost2(vtkIdType edgeId, double *x); + + // Description: + // Find all edges that will have an endpoint change ids because of an edge + // collapse. p1Id and p2Id are the endpoints of the edge. p2Id is the + // pointId being removed. + void FindAffectedEdges(vtkIdType p1Id, vtkIdType p2Id, vtkIdList *edges); + + // Description: + // Find a cell that uses this edge. + vtkIdType GetEdgeCellId(vtkIdType p1Id, vtkIdType p2Id); + + int IsGoodPlacement(vtkIdType pt0Id, vtkIdType pt1Id, const double *x); + int TrianglePlaneCheck(const double t0[3], const double t1[3], + const double t2[3], const double *x); + void ComputeNumberOfComponents(void); + void UpdateEdgeData(vtkIdType ptoId, vtkIdType pt1Id); + + // Description: + // Helper function to set and get the point and it's attributes as an array + void SetPointAttributeArray(vtkIdType ptId, const double *x); + void GetPointAttributeArray(vtkIdType ptId, double *x); + + // Description: + // Find out how many components there are for each attribute for this + // poly data. + void GetAttributeComponents(); + + double TargetReduction; + double ActualReduction; + int AttributeErrorMetric; + + int ScalarsAttribute; + int VectorsAttribute; + int NormalsAttribute; + int TCoordsAttribute; + int TensorsAttribute; + + double ScalarsWeight; + double VectorsWeight; + double NormalsWeight; + double TCoordsWeight; + double TensorsWeight; + + int NumberOfEdgeCollapses; + vtkEdgeTable *Edges; + vtkIdList *EndPoint1List; + vtkIdList *EndPoint2List; + vtkPriorityQueue *EdgeCosts; + vtkDoubleArray *TargetPoints; + int NumberOfComponents; + vtkPolyData *Mesh; + + //BTX + struct ErrorQuadric + { + double *Quadric; + }; + //ETX + + ErrorQuadric *ErrorQuadrics; + int AttributeComponents[6]; + double AttributeScale[6]; + + // Temporary variables for performance + vtkIdList *CollapseCellIds; + double *TempX; + double *TempQuad; + double *TempB; + double **TempA; + double *TempData; + +private: + vtkQuadricDecimation(const vtkQuadricDecimation&); // Not implemented. + void operator=(const vtkQuadricDecimation&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkQuantizePolyDataPoints.cxx b/Graphics/vtkQuantizePolyDataPoints.cxx new file mode 100644 index 0000000..46c0301 --- /dev/null +++ b/Graphics/vtkQuantizePolyDataPoints.cxx @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuantizePolyDataPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuantizePolyDataPoints.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkQuantizePolyDataPoints, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkQuantizePolyDataPoints); + +//-------------------------------------------------------------------------- +// Construct object with initial QFactor of 0.25 +vtkQuantizePolyDataPoints::vtkQuantizePolyDataPoints() +{ + this->QFactor = 0.25; + this->Tolerance = 0.0; +} + +//-------------------------------------------------------------------------- +void vtkQuantizePolyDataPoints::OperateOnPoint(double in[3], double out[3]) +{ + out[0] = floor(in[0]/this->QFactor + 0.5)*this->QFactor; + out[1] = floor(in[1]/this->QFactor + 0.5)*this->QFactor; + out[2] = floor(in[2]/this->QFactor + 0.5)*this->QFactor; +} + +//------------------------------------------------------------------------- +void vtkQuantizePolyDataPoints::OperateOnBounds(double in[6], double out[6]) +{ + out[0] = floor(in[0]/this->QFactor + 0.5)*this->QFactor; + out[1] = floor(in[1]/this->QFactor + 0.5)*this->QFactor; + out[2] = floor(in[2]/this->QFactor + 0.5)*this->QFactor; + out[3] = floor(in[3]/this->QFactor + 0.5)*this->QFactor; + out[4] = floor(in[4]/this->QFactor + 0.5)*this->QFactor; + out[5] = floor(in[5]/this->QFactor + 0.5)*this->QFactor; +} + +//-------------------------------------------------------------------------- +void vtkQuantizePolyDataPoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "QFactor: " << this->QFactor << "\n"; +} + diff --git a/Graphics/vtkQuantizePolyDataPoints.h b/Graphics/vtkQuantizePolyDataPoints.h new file mode 100644 index 0000000..da89448 --- /dev/null +++ b/Graphics/vtkQuantizePolyDataPoints.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuantizePolyDataPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuantizePolyDataPoints - quantizes x,y,z coordinates of points +// .SECTION Description +// vtkQuantizePolyDataPoints is a subclass of vtkCleanPolyData and +// inherits the functionality of vtkCleanPolyData with the addition that +// it quantizes the point coordinates before inserting into the point list. +// The user should set QFactor to a positive value (0.25 by default) and all +// {x,y,z} coordinates will be quantized to that grain size. +// +// A tolerance of zero is expected, though positive values may be used, the +// quantization will take place before the tolerance is applied. +// +// .SECTION Caveats +// Merging points can alter topology, including introducing non-manifold +// forms. Handling of degenerate cells is controlled by switches in +// vtkCleanPolyData. +// +// .SECTION See Also +// vtkCleanPolyData + +#ifndef __vtkQuantizePolyDataPoints_h +#define __vtkQuantizePolyDataPoints_h + +#include "vtkCleanPolyData.h" + +class VTK_GRAPHICS_EXPORT vtkQuantizePolyDataPoints : public vtkCleanPolyData +{ +public: + static vtkQuantizePolyDataPoints *New(); + vtkTypeRevisionMacro(vtkQuantizePolyDataPoints,vtkCleanPolyData); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify quantization grain size + vtkSetClampMacro(QFactor,double,1E-5,VTK_LARGE_FLOAT); + vtkGetMacro(QFactor,double); + + // Description: + // Perform quantization on a point + virtual void OperateOnPoint(double in[3], double out[3]); + + // Description: + // Perform quantization on bounds + virtual void OperateOnBounds(double in[6], double out[6]); + +protected: + vtkQuantizePolyDataPoints(); + ~vtkQuantizePolyDataPoints() {}; + + double QFactor; +private: + vtkQuantizePolyDataPoints(const vtkQuantizePolyDataPoints&); // Not implemented. + void operator=(const vtkQuantizePolyDataPoints&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkRearrangeFields.cxx b/Graphics/vtkRearrangeFields.cxx new file mode 100644 index 0000000..0691b13 --- /dev/null +++ b/Graphics/vtkRearrangeFields.cxx @@ -0,0 +1,712 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRearrangeFields.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRearrangeFields.h" + +#include "vtkCellData.h" +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDataSetAttributes.h" +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkRearrangeFields, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkRearrangeFields); + +typedef vtkRearrangeFields::Operation Operation; + +// Used by AddOperation() and RemoveOperation() designed to be used +// from other language bindings. +char vtkRearrangeFields::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10] += { "SCALARS", + "VECTORS", + "NORMALS", + "TCOORDS", + "TENSORS" }; +char vtkRearrangeFields::OperationTypeNames[2][5] += { "COPY", + "MOVE" }; +char vtkRearrangeFields::FieldLocationNames[3][12] += { "DATA_OBJECT", + "POINT_DATA", + "CELL_DATA" }; + + +//-------------------------------------------------------------------------- + + +vtkRearrangeFields::vtkRearrangeFields() +{ + this->Head = 0; + this->Tail = 0; + this->LastId = 0; +} + +vtkRearrangeFields::~vtkRearrangeFields() +{ + this->DeleteAllOperations(); +} + +int vtkRearrangeFields::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // This has to be here because it initialized all field datas. + output->CopyStructure( input ); + + // Apply all operations. + Operation* cur = this->GetFirst(); + if (cur) + { + Operation* before; + do + { + before = cur; + cur = cur->Next; + this->ApplyOperation(before, input, output); + } + while (cur); + } + + // Pass all. + if ( output->GetFieldData() && input->GetFieldData() ) + { + output->GetFieldData()->PassData( input->GetFieldData() ); + } + output->GetPointData()->PassData( input->GetPointData() ); + output->GetCellData()->PassData( input->GetCellData() ); + + return 1; +} + +// Given location (DATA_OBJECT, CELL_DATA, POINT_DATA) return the +// pointer to the corresponding field data. +vtkFieldData* vtkRearrangeFields::GetFieldDataFromLocation(vtkDataSet* ds, + int fieldLoc) +{ + vtkFieldData* fd=0; + + switch (fieldLoc) + { + case vtkRearrangeFields::DATA_OBJECT: + fd = ds->GetFieldData(); + break; + case vtkRearrangeFields::POINT_DATA: + fd = ds->GetPointData(); + break; + case vtkRearrangeFields::CELL_DATA: + fd = ds->GetCellData(); + break; + } + return fd; +} + +void vtkRearrangeFields::ApplyOperation(Operation* op, vtkDataSet* input, + vtkDataSet* output) +{ + vtkDebugMacro("Applying operation: " << op->Id); + + // Get the field data corresponding to the operation + // from input and output + vtkFieldData* inputFD = this->GetFieldDataFromLocation(input, + op->FromFieldLoc); + vtkFieldData* outputFD = this->GetFieldDataFromLocation(output, + op->ToFieldLoc); + if ( !inputFD || !outputFD) + { + vtkWarningMacro("Can not apply operation " << op->Id + << ": Inappropriate input or output location" + << " specified for the operation."); + return; + } + + // If the source is specified by name + if ( op->FieldType == vtkRearrangeFields::NAME ) + { + vtkDebugMacro("Copy by name:" << op->FieldName); + // Pass the array + outputFD->AddArray(inputFD->GetArray(op->FieldName)); + // If moving the array, make sure that it is not copied + // with PassData() + if ( op->OperationType == vtkRearrangeFields::MOVE ) + { + vtkFieldData* fd = this->GetFieldDataFromLocation(output, + op->FromFieldLoc); + fd->CopyFieldOff(op->FieldName); + } + else if ( op->OperationType == vtkRearrangeFields::COPY ) + { + } + else + { + vtkWarningMacro("Can not apply operation " << op->Id + << ": Inappropriate operation type."); + return; + } + } + // If source is specified as attribute + else if ( op->FieldType == vtkRearrangeFields::ATTRIBUTE ) + { + vtkDebugMacro("Copy by attribute"); + // Get the attribute and pass it + vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(inputFD); + if (!dsa) + { + vtkWarningMacro("Can not apply operation " << op->Id + << ": Input has to be vtkDataSetAttributes."); + } + outputFD->AddArray(dsa->GetAttribute(op->AttributeType)); + // If moving the array, make sure that it is not copied + // with PassData() + if ( op->OperationType == vtkRearrangeFields::MOVE ) + { + vtkFieldData* fd = this->GetFieldDataFromLocation(output, + op->FromFieldLoc); + vtkDataSetAttributes* dsa2 = vtkDataSetAttributes::SafeDownCast(fd); + if (dsa2) + { + dsa2->SetCopyAttribute(op->AttributeType,0); + } + } + else if ( op->OperationType == vtkRearrangeFields::COPY ) + { + } + else + { + vtkWarningMacro("Can not apply operation " << op->Id + << ": Inappropriate operation type."); + return; + } + } + else + { + vtkWarningMacro("Can not apply operation " << op->Id + << ": Inappropriate field type" + << " specified for the operation."); + return; + } +} + +// Helper method used by the Tcl bindings. Allows the caller to +// specify arguments as strings instead of enums.Returns an operation id +// which can later be used to remove the operation. +int vtkRearrangeFields::AddOperation(const char* operationType, + const char* name, + const char* fromFieldLoc, + const char* toFieldLoc) +{ + int numAttr = vtkDataSetAttributes::NUM_ATTRIBUTES; + int numOpTypes = 2; + int numFieldLocs = 3; + int opType=-1, i; + // Convert strings to ints and call the appropriate AddOperation() + for(i=0; iAddOperation(opType, name, fromLoc, toLoc); + } + else + { + vtkDebugMacro("Adding operation with parameters: " + << opType << " " << attributeType << " " + << fromLoc << " " << toLoc); + return this->AddOperation(opType, attributeType, fromLoc, toLoc); + } +} + + +int vtkRearrangeFields::AddOperation(int operationType, const char* name, + int fromFieldLoc, int toFieldLoc) +{ + if (!name) + { return -1; } + + // Syntax and sanity checks. + if ( (operationType != vtkRearrangeFields::COPY) && + (operationType != vtkRearrangeFields::MOVE) ) + { + vtkErrorMacro("Wrong operation type."); + return -1; + } + if ( (fromFieldLoc != vtkRearrangeFields::DATA_OBJECT) && + (fromFieldLoc != vtkRearrangeFields::POINT_DATA) && + (fromFieldLoc != vtkRearrangeFields::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return -1; + } + if ( (toFieldLoc != vtkRearrangeFields::DATA_OBJECT) && + (toFieldLoc != vtkRearrangeFields::POINT_DATA) && + (toFieldLoc != vtkRearrangeFields::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return -1; + } + + // Create an operation with the specified parameters. + Operation* op = new Operation; + op->OperationType = operationType; + op->FieldName = new char [strlen(name)+1]; + strcpy(op->FieldName, name); + op->FromFieldLoc = fromFieldLoc; + op->ToFieldLoc = toFieldLoc; + op->FieldType = vtkRearrangeFields::NAME; + op->Id = this->LastId++; + // assign this anyway + op->AttributeType = 0; + + this->AddOperation(op); + this->Modified(); + + return op->Id; +} + +int vtkRearrangeFields::AddOperation(int operationType, int attributeType, + int fromFieldLoc, int toFieldLoc) +{ + + // Syntax and sanity checks. + if ( (operationType != vtkRearrangeFields::COPY) && + (operationType != vtkRearrangeFields::MOVE) ) + { + vtkErrorMacro("Wrong operation type."); + return -1; + } + if ( (fromFieldLoc != vtkRearrangeFields::DATA_OBJECT) && + (fromFieldLoc != vtkRearrangeFields::POINT_DATA) && + (fromFieldLoc != vtkRearrangeFields::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return -1; + } + if ( (attributeType < 0) || + (attributeType > vtkDataSetAttributes::NUM_ATTRIBUTES) ) + { + vtkErrorMacro("Wrong attribute type."); + return -1; + } + if ( (toFieldLoc != vtkRearrangeFields::DATA_OBJECT) && + (toFieldLoc != vtkRearrangeFields::POINT_DATA) && + (toFieldLoc != vtkRearrangeFields::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return -1; + } + + // Create an operation with the specified parameters. + Operation* op = new Operation; + op->OperationType = operationType; + op->AttributeType = attributeType; + op->FromFieldLoc = fromFieldLoc; + op->ToFieldLoc = toFieldLoc; + op->FieldType = vtkRearrangeFields::ATTRIBUTE; + op->Id = this->LastId++; + + this->AddOperation(op); + this->Modified(); + + return op->Id; +} + +// Helper method used by the Tcl bindings. Allows the caller to +// specify arguments as strings instead of enums.Returns an operation id +// which can later be used to remove the operation. +int vtkRearrangeFields::RemoveOperation(const char* operationType, + const char* name, + const char* fromFieldLoc, + const char* toFieldLoc) +{ + if (!operationType || !name || !fromFieldLoc || !toFieldLoc) + { + return 0; + } + + int numAttr = vtkDataSetAttributes::NUM_ATTRIBUTES; + int numOpTypes = 2; + int numFieldLocs = 3; + int opType=-1, i; + // Convert strings to ints and call the appropriate AddOperation() + for(i=0; iRemoveOperation(opType, name, fromLoc, toLoc); + } + else + { + vtkDebugMacro("Removing operation with parameters: " + << opType << " " << attributeType << " " + << fromLoc << " " << toLoc); + return this->RemoveOperation(opType, attributeType, fromLoc, toLoc); + } +} + +int vtkRearrangeFields::RemoveOperation(int operationId) +{ + Operation* before; + Operation* op; + + op = this->FindOperation(operationId, before); + if (!op) {return 0;} + this->DeleteOperation(op, before); + return 1; +} + +int vtkRearrangeFields::RemoveOperation(int operationType, const char* name, + int fromFieldLoc, int toFieldLoc) +{ + Operation* before; + Operation* op; + op = this->FindOperation(operationType, name, fromFieldLoc, toFieldLoc, + before); + if (!op) { return 0;} + this->Modified(); + this->DeleteOperation(op, before); + return 1; +} + +int vtkRearrangeFields::RemoveOperation(int operationType, int attributeType, + int fromFieldLoc, int toFieldLoc) +{ + Operation* before; + Operation* op; + op = this->FindOperation(operationType, attributeType, fromFieldLoc, + toFieldLoc, before); + if (!op) { return 0;} + this->Modified(); + this->DeleteOperation(op, before); + return 1; +} + +void vtkRearrangeFields::AddOperation(Operation* op) +{ + op->Next = 0; + + if (!this->Head) + { + this->Head = op; + this->Tail = op; + return; + } + this->Tail->Next = op; + this->Tail = op; +} + +void vtkRearrangeFields::DeleteOperation(Operation* op, Operation* before) +{ + if (!op) { return; } + if (!before) + { + this->Head = op->Next; + } + else + { + before->Next = op->Next; + if (!before->Next) + { + this->Tail=before; + } + } + delete op; +} + +Operation* vtkRearrangeFields::FindOperation(int id, Operation*& before) +{ + Operation* cur = this->GetFirst(); + if (!cur) { return 0; } + + before = 0; + if (cur->Id == id) { return cur; } + while (cur->Next) + { + before = cur; + if (cur->Next->Id == id) + { + return cur->Next; + } + cur = cur->Next; + } + return 0; +} + +Operation* vtkRearrangeFields::FindOperation(int operationType, + const char* name, + int fromFieldLoc, + int toFieldLoc, + Operation*& before) +{ + if (!name) {return 0;} + + Operation op; + op.OperationType = operationType; + op.FieldName = new char [strlen(name)+1]; + strcpy(op.FieldName, name); + op.FromFieldLoc = fromFieldLoc; + op.ToFieldLoc = toFieldLoc; + + Operation* cur = this->GetFirst(); + before = 0; + if ( (cur->FieldType == vtkRearrangeFields::NAME) && + this->CompareOperationsByName(cur, &op)) { return cur; } + while (cur->Next) + { + before = cur; + if ( (cur->Next->FieldType == vtkRearrangeFields::NAME) && + this->CompareOperationsByName(cur->Next, &op)) + { + return cur->Next; + } + cur = cur->Next; + } + return 0; +} + +Operation* vtkRearrangeFields::FindOperation(int operationType, + int attributeType, + int fromFieldLoc, + int toFieldLoc, + Operation*& before) +{ + Operation op; + op.OperationType = operationType; + op.AttributeType = attributeType; + op.FromFieldLoc = fromFieldLoc; + op.ToFieldLoc = toFieldLoc; + + Operation* cur = this->GetFirst(); + before = 0; + if ( (cur->FieldType == vtkRearrangeFields::ATTRIBUTE) && + this->CompareOperationsByType(cur, &op)) { return cur; } + while (cur->Next) + { + before = cur; + if ( (cur->Next->FieldType == vtkRearrangeFields::ATTRIBUTE) && + this->CompareOperationsByType(cur->Next, &op)) + { + return cur->Next; + } + cur = cur->Next; + } + return 0; +} + +void vtkRearrangeFields::DeleteAllOperations() +{ + Operation* cur = this->GetFirst(); + if (!cur) {return;} + Operation* before; + do + { + before = cur; + cur = cur->Next; + delete before; + } + while (cur); + this->Head = 0; + this->Tail = 0; +} + +int vtkRearrangeFields::CompareOperationsByName(const Operation* op1, + const Operation* op2) +{ + if ( op1->OperationType != op2->OperationType ) + { return 0; } + if ( !op1->FieldName || !op2->FieldName || strcmp(op1->FieldName, + op2->FieldName) ) + { return 0; } + if ( op1->FromFieldLoc != op2->FromFieldLoc ) + { return 0; } + if ( op1->ToFieldLoc != op2->ToFieldLoc ) + { return 0; } + return 1; +} + +int vtkRearrangeFields::CompareOperationsByType(const Operation* op1, + const Operation* op2) +{ + if ( op1->OperationType != op2->OperationType ) + { return 0; } + if ( op1->AttributeType != op2->AttributeType ) + { return 0; } + if ( op1->FromFieldLoc != op2->FromFieldLoc ) + { return 0; } + if ( op1->ToFieldLoc != op2->ToFieldLoc ) + { return 0; } + return 1; +} + + +void vtkRearrangeFields::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Linked list head: " << this->Head << endl; + os << indent << "Linked list tail: " << this->Tail << endl; + os << indent << "Last id: " << this->LastId << endl; + os << indent << "Operations: " << endl; + this->PrintAllOperations(os, indent.GetNextIndent()); +} + +void vtkRearrangeFields::PrintAllOperations(ostream& os, vtkIndent indent) +{ + Operation* cur = this->GetFirst(); + if (!cur) { return; } + Operation* before; + do + { + before = cur; + cur = cur->Next; + os << endl; + this->PrintOperation(before, os, indent); + } + while (cur); +} + +void vtkRearrangeFields::PrintOperation(Operation* op, ostream& os, vtkIndent indent) +{ + os << indent << "Id: " << op->Id << endl; + os << indent << "Type: " << op->OperationType << endl; + os << indent << "Field type: " << op->FieldType << endl; + if ( op->FieldName) + { + os << indent << "Field name: " << op->FieldName << endl; + } + else + { + os << indent << "Field name: (none)" << endl; + } + os << indent << "Attribute type: " << op->AttributeType << endl; + os << indent << "Source field location: " << op->FromFieldLoc << endl; + os << indent << "Target field location: " << op->ToFieldLoc << endl; + os << indent << "Next operation: " << op->Next << endl; + os << endl; +} diff --git a/Graphics/vtkRearrangeFields.h b/Graphics/vtkRearrangeFields.h new file mode 100644 index 0000000..cc91ca7 --- /dev/null +++ b/Graphics/vtkRearrangeFields.h @@ -0,0 +1,212 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRearrangeFields.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRearrangeFields - Move/copy fields between field data, point data and cell data +// .SECTION Description +// vtkRearrangeFields is used to copy/move fields (vtkDataArrays) between +// data object's field data, point data and cell data. To specify which +// fields are copied/moved, the user adds operations. There are two types +// of operations: 1. the type which copies/moves an attribute's data +// (i.e. the field will be copied but will not be an attribute in the +// target), 2. the type which copies/moves fields by name. For example: +// @verbatim +// rf->AddOperation(vtkRearrangeFields::COPY, "foo", +// vtkRearrangeFields::DATA_OBJECT, +// vtkRearrangeFields::POINT_DATA); +// @endverbatim +// adds an operation which copies a field (data array) called foo from +// the data object's field data to point data. +// From Tcl, the same operation can be added as follows: +// @verbatim +// rf AddOperation COPY foo DATA_OBJECT POINT_DATA +// @endverbatim +// The same can be done using Python and Java bindings by passing +// strings as arguments. +// @verbatim +// Operation types: COPY, MOVE +// AttributeTypes: SCALARS, VECTORS, NORMALS, TCOORDS, TENSORS +// Field data locations: DATA_OBJECT, POINT_DATA, CELL_DATA +// @endverbatim + +// .SECTION Caveats +// When using Tcl, Java, Python or Visual Basic bindings, the array name +// can not be one of the AttributeTypes when calling AddOperation() which +// takes strings as arguments. The Tcl (Java etc.) command will +// always assume the string corresponds to an attribute type when +// the argument is one of the AttributeTypes. In this situation, +// use the AddOperation() which takes enums. + +// .SECTION See Also +// vtkFieldData vtkDataSet vtkDataObjectToDataSetFilter +// vtkDataSetAttributes vtkDataArray vtkAssignAttribute +// vtkSplitField vtkMergeFields + +#ifndef __vtkRearrangeFields_h +#define __vtkRearrangeFields_h + +#include "vtkDataSetAlgorithm.h" + +#include "vtkDataSetAttributes.h" // Needed for NUM_ATTRIBUTES + +class vtkFieldData; + +class VTK_GRAPHICS_EXPORT vtkRearrangeFields : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkRearrangeFields,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a new vtkRearrangeFields with an empty operation list. + static vtkRearrangeFields *New(); + +//BTX + enum OperationType + { + COPY=0, + MOVE=1 + }; + enum FieldLocation + { + DATA_OBJECT=0, + POINT_DATA=1, + CELL_DATA=2 + }; +//ETX + + // Description: + // Add an operation which copies an attribute's field (data array) from + // one field data to another. Returns an operation id which can later + // be used to remove the operation. + int AddOperation(int operationType, int attributeType, int fromFieldLoc, + int toFieldLoc); + // Description: + // Add an operation which copies a field (data array) from one field + // data to another. Returns an operation id which can later + // be used to remove the operation. + int AddOperation(int operationType, const char* name, int fromFieldLoc, + int toFieldLoc); + // Description: + // Helper method used by other language bindings. Allows the caller to + // specify arguments as strings instead of enums.Returns an operation id + // which can later be used to remove the operation. + int AddOperation(const char* operationType, const char* attributeType, + const char* fromFieldLoc, const char* toFieldLoc); + + // Description: + // Remove an operation with the given id. + int RemoveOperation(int operationId); + // Description: + // Remove an operation with the given signature. See AddOperation + // for details. + int RemoveOperation(int operationType, int attributeType, int fromFieldLoc, + int toFieldLoc); + // Description: + // Remove an operation with the given signature. See AddOperation + // for details. + int RemoveOperation(int operationType, const char* name, int fromFieldLoc, + int toFieldLoc); + // Description: + // Remove an operation with the given signature. See AddOperation + // for details. + int RemoveOperation(const char* operationType, const char* attributeType, + const char* fromFieldLoc, const char* toFieldLoc); + + // Description: + // Remove all operations. + void RemoveAllOperations() + { + this->Modified(); + this->LastId = 0; + this->DeleteAllOperations(); + } + +//BTX + enum FieldType + { + NAME, + ATTRIBUTE + }; + + struct Operation + { + int OperationType; // COPY or MOVE + int FieldType; // NAME or ATTRIBUTE + char* FieldName; + int AttributeType; + int FromFieldLoc; // fd, pd or do + int ToFieldLoc; // fd, pd or do + int Id; // assigned during creation + Operation* Next; // linked list + Operation() { FieldName = 0; } + ~Operation() { delete[] FieldName; } + }; +//ETX + +protected: + + vtkRearrangeFields(); + virtual ~vtkRearrangeFields(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + + // Operations are stored as a linked list. + Operation* Head; + Operation* Tail; + // This is incremented whenever a new operation is created. + // It is not decremented when an operation is deleted. + int LastId; + + // Methods to browse/modify the linked list. + Operation* GetNextOperation(Operation* op) + { return op->Next; } + Operation* GetFirst() + { return this->Head; } + void AddOperation(Operation* op); + void DeleteOperation(Operation* op, Operation* before); + Operation* FindOperation(int id, Operation*& before); + Operation* FindOperation(const char* name, Operation*& before); + Operation* FindOperation(int operationType, const char* name, + int fromFieldLoc, int toFieldLoc, + Operation*& before); + Operation* FindOperation(int operationType, int attributeType, + int fromFieldLoc, int toFieldLoc, + Operation*& before); + // Used when finding/deleting an operation given a signature. + int CompareOperationsByType(const Operation* op1, const Operation* op2); + int CompareOperationsByName(const Operation* op1, const Operation* op2); + + void DeleteAllOperations(); + void ApplyOperation(Operation* op, vtkDataSet* input, vtkDataSet* output); + // Given location (DATA_OBJECT, CELL_DATA, POINT_DATA) return the + // pointer to the corresponding field data. + vtkFieldData* GetFieldDataFromLocation(vtkDataSet* ds, int fieldLoc); + + // Used by AddOperation() and RemoveOperation() designed to be used + // from other language bindings. + static char OperationTypeNames[2][5]; + static char FieldLocationNames[3][12]; + static char AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10]; + + void PrintAllOperations(ostream& os, vtkIndent indent); + void PrintOperation(Operation* op, ostream& os, vtkIndent indent); +private: + vtkRearrangeFields(const vtkRearrangeFields&); // Not implemented. + void operator=(const vtkRearrangeFields&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkRectangularButtonSource.cxx b/Graphics/vtkRectangularButtonSource.cxx new file mode 100644 index 0000000..94307f3 --- /dev/null +++ b/Graphics/vtkRectangularButtonSource.cxx @@ -0,0 +1,243 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectangularButtonSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectangularButtonSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkRectangularButtonSource, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkRectangularButtonSource); + +// Construct +vtkRectangularButtonSource::vtkRectangularButtonSource() +{ + this->Width = 0.5; + this->Height = 0.5; + this->Depth = 0.05; + + this->BoxRatio = 1.1; + this->TextureRatio = 0.9; + this->TextureHeightRatio = 0.95; +} + +// One half of the button is made up of nine (quad) polygons. +// +static vtkIdType vtkRButtonPolys[72] = { + 0,1,5,4, 1,2,6,5, 2,3,7,6, 3,0,4,7, + 4,5,9,8, 5,6,10,9, 6,7,11,10, 7,4,8,11, 12,13,14,15, + 1,0,16,17, 2,1,17,18, 3,2,18,19, 0,3,19,16, + 17,16,20,21, 18,17,21,22, 19,18,22,23, 16,19,23,20, 25,24,27,26}; + +// Generate the button. +// +int vtkRectangularButtonSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int i; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Generating rectangular button"); + + // Check input + if ( this->Width <= 0.0 || this->Height <= 0.0 ) + { + vtkErrorMacro(<<"Button must have non-zero height and width"); + return 1; + } + + // Create the button in several steps. First, create the button in + // the x-y plane. After this, the z-depth is created. And if + // it is a two-sided button, then a mirror reflection of the button + // in the negative z-direction is created. + int numPts = 16; + int numCells = 9; + if ( this->TwoSided ) + { + numPts *= 2; + numCells *= 2; + } + + // Allocate memory for everything + vtkPoints *newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + + vtkFloatArray *tcoords = vtkFloatArray::New(); + tcoords->SetNumberOfComponents(2); + tcoords->SetNumberOfTuples(numPts); + + vtkCellArray *newPolys = vtkCellArray::New(); + newPolys->Allocate(numCells); + + // Generate the points and texture coordinates----------------------------- + // + double shoulderX = this->Width / 2.0; + double boxX = this->BoxRatio * shoulderX; + double textureX = this->TextureRatio * shoulderX; //may be adjusted later + + double shoulderY = this->Height / 2.0; + double boxY = this->BoxRatio * shoulderY; + double textureY = this->TextureRatio * shoulderY; //may be adjusted later + + double shoulderZ = this->Depth; + double boxZ = 0.0; + double textureZ = this->TextureHeightRatio * this->Depth; + + // Adjust the texture region if the texture region should be fit to the image + if ( this->TextureStyle == VTK_TEXTURE_STYLE_FIT_IMAGE ) + { + double dX = (double)this->TextureDimensions[0]; + double dY = (double)this->TextureDimensions[1]; + + double f1 = textureX/dX; + double f2 = textureY/dY; + if ( f1 < f2 ) + { + textureX = f1 * dX; + textureY = f1 * dY; + } + else + { + textureX = f2 * dX; + textureY = f2 * dY; + } + } + + // The first four points are around the base + newPts->SetPoint(0, this->Center[0]-boxX, this->Center[1]-boxY, this->Center[2]+boxZ); + newPts->SetPoint(1, this->Center[0]+boxX, this->Center[1]-boxY, this->Center[2]+boxZ); + newPts->SetPoint(2, this->Center[0]+boxX, this->Center[1]+boxY, this->Center[2]+boxZ); + newPts->SetPoint(3, this->Center[0]-boxX, this->Center[1]+boxY, this->Center[2]+boxZ); + + // The next four points are around the shoulder + newPts->SetPoint(4, this->Center[0]-shoulderX, this->Center[1]-shoulderY, this->Center[2]+shoulderZ); + newPts->SetPoint(5, this->Center[0]+shoulderX, this->Center[1]-shoulderY, this->Center[2]+shoulderZ); + newPts->SetPoint(6, this->Center[0]+shoulderX, this->Center[1]+shoulderY, this->Center[2]+shoulderZ); + newPts->SetPoint(7, this->Center[0]-shoulderX, this->Center[1]+shoulderY, this->Center[2]+shoulderZ); + + // The next four points are between the shoulder and texture region + newPts->SetPoint(8, this->Center[0]-textureX, this->Center[1]-textureY, this->Center[2]+textureZ); + newPts->SetPoint(9, this->Center[0]+textureX, this->Center[1]-textureY, this->Center[2]+textureZ); + newPts->SetPoint(10,this->Center[0]+textureX, this->Center[1]+textureY, this->Center[2]+textureZ); + newPts->SetPoint(11,this->Center[0]-textureX, this->Center[1]+textureY, this->Center[2]+textureZ); + + // The last four points define the texture region + newPts->SetPoint(12, this->Center[0]-textureX, this->Center[1]-textureY, this->Center[2]+textureZ); + newPts->SetPoint(13, this->Center[0]+textureX, this->Center[1]-textureY, this->Center[2]+textureZ); + newPts->SetPoint(14, this->Center[0]+textureX, this->Center[1]+textureY, this->Center[2]+textureZ); + newPts->SetPoint(15, this->Center[0]-textureX, this->Center[1]+textureY, this->Center[2]+textureZ); + + if ( this->TwoSided ) + { + // The next four points are around the shoulder + newPts->SetPoint(16, this->Center[0]-shoulderX, this->Center[1]-shoulderY, this->Center[2]-shoulderZ); + newPts->SetPoint(17, this->Center[0]+shoulderX, this->Center[1]-shoulderY, this->Center[2]-shoulderZ); + newPts->SetPoint(18, this->Center[0]+shoulderX, this->Center[1]+shoulderY, this->Center[2]-shoulderZ); + newPts->SetPoint(19, this->Center[0]-shoulderX, this->Center[1]+shoulderY, this->Center[2]-shoulderZ); + + // The next four points are between the shoulder and texture region + newPts->SetPoint(20, this->Center[0]-textureX, this->Center[1]-textureY, this->Center[2]-textureZ); + newPts->SetPoint(21, this->Center[0]+textureX, this->Center[1]-textureY, this->Center[2]-textureZ); + newPts->SetPoint(22,this->Center[0]+textureX, this->Center[1]+textureY, this->Center[2]-textureZ); + newPts->SetPoint(23,this->Center[0]-textureX, this->Center[1]+textureY, this->Center[2]-textureZ); + + // The last four points define the texture region + newPts->SetPoint(24, this->Center[0]-textureX, this->Center[1]-textureY, this->Center[2]-textureZ); + newPts->SetPoint(25, this->Center[0]+textureX, this->Center[1]-textureY, this->Center[2]-textureZ); + newPts->SetPoint(26, this->Center[0]+textureX, this->Center[1]+textureY, this->Center[2]-textureZ); + newPts->SetPoint(27, this->Center[0]-textureX, this->Center[1]+textureY, this->Center[2]-textureZ); + } + + // Generate the texture coordinates----------------------------- + // + // The shoulder has the same value. + for (i=0; i<12; i++) + { + tcoords->SetTuple(i,this->ShoulderTextureCoordinate); + } + + // The texture region has just the four points + tcoords->SetTuple2(12,0.0, 0.0); + tcoords->SetTuple2(13,1.0, 0.0); + tcoords->SetTuple2(14,1.0, 1.0); + tcoords->SetTuple2(15,0.0, 1.0); + + if ( this->TwoSided ) + { + for (i=16; i<24; i++) + { + tcoords->SetTuple(i,this->ShoulderTextureCoordinate); + } + // The texture region has just the four points + tcoords->SetTuple2(24,1.0, 0.0); + tcoords->SetTuple2(25,0.0, 0.0); + tcoords->SetTuple2(26,0.0, 1.0); + tcoords->SetTuple2(27,1.0, 1.0); + } + + // Create the polygons------------------------------------------------------ + // + vtkIdType *buttonPtr = vtkRButtonPolys; + for (i=0; i<9; i++, buttonPtr+=4) + { + newPolys->InsertNextCell(4,buttonPtr); + } + + // If two sided, create the opposite side. + // Make sure that faces ordering is reversed. + if ( this->TwoSided ) + { + for (i=0; i<9; i++, buttonPtr+=4) + { + newPolys->InsertNextCell(4,buttonPtr); + } + } + + // Clean up and get out + output->SetPoints(newPts); + output->GetPointData()->SetTCoords(tcoords); + output->SetPolys(newPolys); + + newPts->Delete(); + tcoords->Delete(); + newPolys->Delete(); + + return 1; +} + +void vtkRectangularButtonSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Width: " << this->Width << "\n"; + os << indent << "Height: " << this->Height << "\n"; + os << indent << "Depth: " << this->Depth << "\n"; + + os << indent << "BoxRatio: " << this->BoxRatio << "\n"; + os << indent << "TextureRatio: " << this->TextureRatio << "\n"; + os << indent << "TextureHeightRatio: " << this->TextureHeightRatio << "\n"; +} diff --git a/Graphics/vtkRectangularButtonSource.h b/Graphics/vtkRectangularButtonSource.h new file mode 100644 index 0000000..7208624 --- /dev/null +++ b/Graphics/vtkRectangularButtonSource.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectangularButtonSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectangularButtonSource - create a rectangular button +// .SECTION Description +// vtkRectangularButtonSource creates a rectangular shaped button with +// texture coordinates suitable for application of a texture map. This +// provides a way to make nice looking 3D buttons. The buttons are +// represented as vtkPolyData that includes texture coordinates and +// normals. The button lies in the x-y plane. +// +// To use this class you must define its width, height and length. These +// measurements are all taken with respect to the shoulder of the button. +// The shoulder is defined as follows. Imagine a box sitting on the floor. +// The distance from the floor to the top of the box is the depth; the other +// directions are the length (x-direction) and height (y-direction). In +// this particular widget the box can have a smaller bottom than top. The +// ratio in size between bottom and top is called the box ratio (by +// default=1.0). The ratio of the texture region to the shoulder region +// is the texture ratio. And finally the texture region may be out of plane +// compared to the shoulder. The texture height ratio controls this. + +// .SECTION See Also +// vtkButtonSource vtkRectangularButtonSource + +// .SECTION Caveats +// The button is defined in the x-y plane. Use vtkTransformPolyDataFilter +// or vtkGlyph3D to orient the button in a different direction. + + +#ifndef __vtkRectangularButtonSource_h +#define __vtkRectangularButtonSource_h + +#include "vtkButtonSource.h" + +class vtkCellArray; +class vtkFloatArray; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkRectangularButtonSource : public vtkButtonSource +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkRectangularButtonSource,vtkButtonSource); + + // Description: + // Construct a circular button with depth 10% of its height. + static vtkRectangularButtonSource *New(); + + // Description: + // Set/Get the width of the button. + vtkSetClampMacro(Width,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Width,double); + + // Description: + // Set/Get the height of the button. + vtkSetClampMacro(Height,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Height,double); + + // Description: + // Set/Get the depth of the button (the z-eliipsoid axis length). + vtkSetClampMacro(Depth,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Depth,double); + + // Description: + // Set/Get the ratio of the bottom of the button with the + // shoulder region. Numbers greater than one produce buttons + // with a wider bottom than shoulder; ratios less than one + // produce buttons that have a wider shoulder than bottom. + vtkSetClampMacro(BoxRatio,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(BoxRatio,double); + + // Description: + // Set/Get the ratio of the texture region to the + // shoulder region. This number must be 0<=tr<=1. + // If the texture style is to fit the image, then satisfying + // the texture ratio may only be possible in one of the + // two directions (length or width) depending on the + // dimensions of the texture. + vtkSetClampMacro(TextureRatio,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(TextureRatio,double); + + // Description: + // Set/Get the ratio of the height of the texture region + // to the shoulder height. Values greater than 1.0 yield + // convex buttons with the texture region raised above the + // shoulder. Values less than 1.0 yield concave buttons with + // the texture region below the shoulder. + vtkSetClampMacro(TextureHeightRatio,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(TextureHeightRatio,double); + +protected: + vtkRectangularButtonSource(); + ~vtkRectangularButtonSource() {} + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Width; + double Height; + double Depth; + + double BoxRatio; + double TextureRatio; + double TextureHeightRatio; + +private: + vtkRectangularButtonSource(const vtkRectangularButtonSource&); // Not implemented. + void operator=(const vtkRectangularButtonSource&); // Not implemented. + +}; + +#endif + + diff --git a/Graphics/vtkRectilinearGridClip.cxx b/Graphics/vtkRectilinearGridClip.cxx new file mode 100644 index 0000000..43eae9d --- /dev/null +++ b/Graphics/vtkRectilinearGridClip.cxx @@ -0,0 +1,248 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridClip.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridClip.h" + +#include "vtkCellData.h" +#include "vtkExtentTranslator.h" +#include "vtkRectilinearGrid.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkRectilinearGridClip, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkRectilinearGridClip); + +//---------------------------------------------------------------------------- +vtkRectilinearGridClip::vtkRectilinearGridClip() +{ + this->ClipData = 0; + this->Initialized = 0; + + this->OutputWholeExtent[0] = + this->OutputWholeExtent[2] = + this->OutputWholeExtent[4] = -VTK_LARGE_INTEGER; + + this->OutputWholeExtent[1] = + this->OutputWholeExtent[3] = + this->OutputWholeExtent[5] = VTK_LARGE_INTEGER; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridClip::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + + os << indent << "OutputWholeExtent: (" << this->OutputWholeExtent[0] + << "," << this->OutputWholeExtent[1]; + for (idx = 1; idx < 3; ++idx) + { + os << indent << ", " << this->OutputWholeExtent[idx * 2] + << "," << this->OutputWholeExtent[idx*2 + 1]; + } + os << ")\n"; + if (this->ClipData) + { + os << indent << "ClipDataOn\n"; + } + else + { + os << indent << "ClipDataOff\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridClip::SetOutputWholeExtent(int extent[6], vtkInformation *outInfo) +{ + int idx; + int modified = 0; + + for (idx = 0; idx < 6; ++idx) + { + if (this->OutputWholeExtent[idx] != extent[idx]) + { + this->OutputWholeExtent[idx] = extent[idx]; + modified = 1; + } + } + this->Initialized = 1; + if (modified) + { + this->Modified(); + if (!outInfo) + { + outInfo = this->GetExecutive()->GetOutputInformation(0); + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); + } +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridClip::SetOutputWholeExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetOutputWholeExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridClip::GetOutputWholeExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + extent[idx] = this->OutputWholeExtent[idx]; + } +} + +//---------------------------------------------------------------------------- +// Change the WholeExtent +int vtkRectilinearGridClip::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int idx, extent[6]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + if ( ! this->Initialized) + { + this->SetOutputWholeExtent(extent, outInfo); + } + + // Clip the OutputWholeExtent with the input WholeExtent + for (idx = 0; idx < 3; ++idx) + { + if (this->OutputWholeExtent[idx*2] >= extent[idx*2] && + this->OutputWholeExtent[idx*2] <= extent[idx*2+1]) + { + extent[idx*2] = this->OutputWholeExtent[idx*2]; + } + if (this->OutputWholeExtent[idx*2+1] >= extent[idx*2] && + this->OutputWholeExtent[idx*2+1] <= extent[idx*2+1]) + { + extent[idx*2+1] = this->OutputWholeExtent[idx*2+1]; + } + // make usre the order is correct + if (extent[idx*2] > extent[idx*2+1]) + { + extent[idx*2] = extent[idx*2+1]; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// Sets the output whole extent to be the input whole extent. +void vtkRectilinearGridClip::ResetOutputWholeExtent() +{ + if ( ! this->GetInput()) + { + vtkWarningMacro("ResetOutputWholeExtent: No input"); + return; + } + + this->GetInput()->UpdateInformation(); + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + this->SetOutputWholeExtent(inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); +} + +//---------------------------------------------------------------------------- +// This method simply copies by reference the input data to the output. +int vtkRectilinearGridClip::RequestData(vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int *inExt; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkRectilinearGrid *outData = vtkRectilinearGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkRectilinearGrid *inData = vtkRectilinearGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + inExt = inData->GetExtent(); + + outData->SetExtent(inExt); + outData->GetPointData()->PassData(inData->GetPointData()); + outData->GetCellData()->PassData(inData->GetCellData()); + outData->SetXCoordinates(inData->GetXCoordinates()); + outData->SetYCoordinates(inData->GetYCoordinates()); + outData->SetZCoordinates(inData->GetZCoordinates()); + + if (this->ClipData) + { + outData->Crop(); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridClip::SetOutputWholeExtent(int piece, int numPieces) +{ + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0); + vtkRectilinearGrid *input = vtkRectilinearGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkRectilinearGrid *output = vtkRectilinearGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkExtentTranslator *translator; + int ext[6]; + + if (input == NULL) + { + vtkErrorMacro("We must have an input to set the output extent by piece."); + return; + } + if (output == NULL) + { + vtkErrorMacro("We must have an output to set the output extent by piece."); + return; + } + translator = output->GetExtentTranslator(); + if (translator == NULL) + { + vtkErrorMacro("Output does not have an extent translator."); + return; + } + + input->UpdateInformation(); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext); + translator->SetWholeExtent(ext); + translator->SetPiece(piece); + translator->SetNumberOfPieces(numPieces); + translator->SetGhostLevel(0); + translator->PieceToExtent(); + translator->GetExtent(ext); + this->SetOutputWholeExtent(ext); +} diff --git a/Graphics/vtkRectilinearGridClip.h b/Graphics/vtkRectilinearGridClip.h new file mode 100644 index 0000000..a588d73 --- /dev/null +++ b/Graphics/vtkRectilinearGridClip.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridClip.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridClip - Reduces the image extent of the input. +// .SECTION Description +// vtkRectilinearGridClip will make an image smaller. The output must have +// an image extent which is the subset of the input. The filter has two +// modes of operation: +// 1: By default, the data is not copied in this filter. +// Only the whole extent is modified. +// 2: If ClipDataOn is set, then you will get no more that the clipped +// extent. +#ifndef __vtkRectilinearGridClip_h +#define __vtkRectilinearGridClip_h + +// I did not make this a subclass of in place filter because +// the references on the data do not matter. I make no modifications +// to the data. +#include "vtkRectilinearGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkRectilinearGridClip : public vtkRectilinearGridAlgorithm +{ +public: + static vtkRectilinearGridClip *New(); + vtkTypeRevisionMacro(vtkRectilinearGridClip,vtkRectilinearGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The whole extent of the output has to be set explicitly. + void SetOutputWholeExtent(int extent[6], vtkInformation *outInfo=0); + void SetOutputWholeExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + void GetOutputWholeExtent(int extent[6]); + int *GetOutputWholeExtent() {return this->OutputWholeExtent;} + + void ResetOutputWholeExtent(); + + // Description: + // By default, ClipData is off, and only the WholeExtent is modified. + // the data's extent may actually be larger. When this flag is on, + // the data extent will be no more than the OutputWholeExtent. + vtkSetMacro(ClipData, int); + vtkGetMacro(ClipData, int); + vtkBooleanMacro(ClipData, int); + + // Description: + // Hack set output by piece + void SetOutputWholeExtent(int piece, int numPieces); + +protected: + vtkRectilinearGridClip(); + ~vtkRectilinearGridClip() {}; + + // Time when OutputImageExtent was computed. + vtkTimeStamp CTime; + int Initialized; // Set the OutputImageExtent for the first time. + int OutputWholeExtent[6]; + + int ClipData; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + void CopyData(vtkRectilinearGrid *inData, vtkRectilinearGrid *outData, int *ext); + + int SplitExtentTmp(int piece, int numPieces, int *ext); + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + +private: + vtkRectilinearGridClip(const vtkRectilinearGridClip&); // Not implemented. + void operator=(const vtkRectilinearGridClip&); // Not implemented. +}; + + + +#endif + + + diff --git a/Graphics/vtkRectilinearGridGeometryFilter.cxx b/Graphics/vtkRectilinearGridGeometryFilter.cxx new file mode 100644 index 0000000..5bc0f09 --- /dev/null +++ b/Graphics/vtkRectilinearGridGeometryFilter.cxx @@ -0,0 +1,437 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridGeometryFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" + +vtkCxxRevisionMacro(vtkRectilinearGridGeometryFilter, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkRectilinearGridGeometryFilter); + +// Construct with initial extent (0,100, 0,100, 0,0) (i.e., a k-plane). +vtkRectilinearGridGeometryFilter::vtkRectilinearGridGeometryFilter() +{ + this->Extent[0] = 0; + this->Extent[1] = VTK_LARGE_INTEGER; + this->Extent[2] = 0; + this->Extent[3] = VTK_LARGE_INTEGER; + this->Extent[4] = 0; + this->Extent[5] = VTK_LARGE_INTEGER; +} + +int vtkRectilinearGridGeometryFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkRectilinearGrid *input = vtkRectilinearGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int *dims, dimension, dir[3], diff[3]; + int i, j, k, extent[6]; + vtkIdType idx, startIdx, startCellIdx; + vtkIdType ptIds[4]; + vtkIdType cellId; + vtkPoints *newPts=0; + vtkCellArray *newVerts=0; + vtkCellArray *newLines=0; + vtkCellArray *newPolys=0; + vtkIdType totPoints, pos; + int offset[3], numPolys; + double x[3]; + vtkPointData *pd, *outPD; + vtkCellData *cd, *outCD; + + vtkDebugMacro(<< "Extracting rectilinear points geometry"); + + pd = input->GetPointData(); + outPD = output->GetPointData(); + outPD->CopyNormalsOff(); + cd = input->GetCellData(); + outCD = output->GetCellData(); + dims = input->GetDimensions(); + // + // Based on the dimensions of the rectilinear data, + // and the extent of the geometry, + // compute the combined extent plus the dimensionality of the data + // + for (dimension=3, i=0; i<3; i++) + { + extent[2*i] = this->Extent[2*i] < 0 ? 0 : this->Extent[2*i]; + extent[2*i] = this->Extent[2*i] >= dims[i] ? dims[i]-1 : this->Extent[2*i]; + extent[2*i+1] = this->Extent[2*i+1] >= dims[i] ? dims[i]-1 : this->Extent[2*i+1]; + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + if ( (extent[2*i+1] - extent[2*i]) == 0 ) + { + dimension--; + } + } + // + // Now create polygonal data based on dimension of data + // + startIdx = extent[0] + extent[2]*dims[0] + extent[4]*dims[0]*dims[1]; + // The cell index is a bit more complicated at the boundaries + if (dims[0] == 1) + { + startCellIdx = extent[0]; + } + else + { + startCellIdx = (extent[0] < dims[0] - 1) ? extent[0] + : extent[0]-1; + } + if (dims[1] == 1) + { + startCellIdx += extent[2]*(dims[0]-1); + } + else + { + startCellIdx += (extent[2] < dims[1] - 1) ? extent[2]*(dims[0]-1) + : (extent[2]-1)*(dims[0]-1); + } + if (dims[2] == 1) + { + startCellIdx += extent[4]*(dims[0]-1)*(dims[1]-1); + } + else + { + startCellIdx += (extent[4] < dims[2] - 1) ? extent[4]*(dims[0]-1)*(dims[1]-1) + : (extent[4]-1)*(dims[0]-1)*(dims[1]-1); + } + + switch (dimension) + { + default: + break; + + case 0: // --------------------- build point ----------------------- + + newPts = vtkPoints::New(); + newPts->Allocate(1); + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(1,1)); + outPD->CopyAllocate(pd,1); + outCD->CopyAllocate(cd,1); + + ptIds[0] = newPts->InsertNextPoint(input->GetPoint(startIdx)); + outPD->CopyData(pd,startIdx,ptIds[0]); + + cellId = newVerts->InsertNextCell(1,ptIds); + outCD->CopyData(cd,startIdx,cellId); + break; + + case 1: // --------------------- build line ----------------------- + + for (dir[0]=dir[1]=dir[2]=totPoints=0, i=0; i<3; i++) + { + if ( (diff[i] = extent[2*i+1] - extent[2*i]) > 0 ) + { + dir[0] = i; + totPoints = diff[i] + 1; + break; + } + } + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(totPoints-1,2)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,totPoints - 1); +// +// Load data +// + if ( dir[0] == 0 ) + { + offset[0] = 1; + } + else if (dir[0] == 1) + { + offset[0] = dims[0]; + } + else + { + offset[0] = dims[0]*dims[1]; + } + + for (i=0; iGetPoint(idx, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,idx,ptIds[0]); + } + + if ( dir[0] == 0 ) + { + offset[0] = 1; + } + else if (dir[0] == 1) + { + offset[0] = dims[0] - 1; + } + else + { + offset[0] = (dims[0] - 1) * (dims[1] - 1); + } + + for (i=0; i<(totPoints-1); i++) + { + idx = startCellIdx + i*offset[0]; + ptIds[0] = i; + ptIds[1] = i + 1; + cellId = newLines->InsertNextCell(2,ptIds); + outCD->CopyData(cd,idx,cellId); + } + break; + + case 2: // --------------------- build plane ----------------------- +// +// Create the data objects +// + for (dir[0]=dir[1]=dir[2]=idx=0,i=0; i<3; i++) + { + if ( (diff[i] = extent[2*i+1] - extent[2*i]) != 0 ) + { + dir[idx++] = i; + } + else + { + dir[2] = i; + } + } + + totPoints = (diff[dir[0]]+1) * (diff[dir[1]]+1); + numPolys = diff[dir[0]] * diff[dir[1]]; + + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newLines->EstimateSize(numPolys,4)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,numPolys); +// +// Create polygons +// + for (i=0; i<2; i++) + { + if ( dir[i] == 0 ) + { + offset[i] = 1; + } + else if ( dir[i] == 1 ) + { + offset[i] = dims[0]; + } + else if ( dir[i] == 2 ) + { + offset[i] = dims[0]*dims[1]; + } + } + + // create points whether visible or not. Makes coding easier but generates + // extra data. + for (pos=startIdx, j=0; j < (diff[dir[1]]+1); j++) + { + for (i=0; i < (diff[dir[0]]+1); i++) + { + idx = pos + i*offset[0]; + input->GetPoint(idx, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,idx,ptIds[0]); + } + pos += offset[1]; + } + + // create any polygon who has a visible vertex. To turn off a polygon, all + // vertices have to be blanked. + for (i=0; i<2; i++) + { + if ( dir[i] == 0 ) + { + offset[i] = 1; + } + else if ( dir[i] == 1 ) + { + offset[i] = (dims[0] - 1); + } + else if ( dir[i] == 2 ) + { + offset[i] = (dims[0] - 1) * (dims[1] - 1); + } + } + + for (pos=startCellIdx, j=0; j < diff[dir[1]]; j++) + { + for (i=0; i < diff[dir[0]]; i++) + { + idx = pos + i*offset[0]; + ptIds[0] = i + j*(diff[dir[0]]+1); + ptIds[1] = ptIds[0] + 1; + ptIds[2] = ptIds[1] + diff[dir[0]] + 1; + ptIds[3] = ptIds[2] - 1; + cellId = newPolys->InsertNextCell(4,ptIds); + outCD->CopyData(cd,idx,cellId); + } + pos += offset[1]; + } + break; + + case 3: // ------------------- grab points in volume -------------- + +// +// Create data objects +// + for (i=0; i<3; i++) + { + diff[i] = extent[2*i+1] - extent[2*i]; + } + + totPoints = (diff[0]+1) * (diff[1]+1) * (diff[2]+1); + + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(totPoints,1)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,totPoints); +// +// Create vertices +// + offset[0] = dims[0]; + offset[1] = dims[0]*dims[1]; + + for (k=0; k < (diff[2]+1); k++) + { + for (j=0; j < (diff[1]+1); j++) + { + pos = startIdx + j*offset[0] + k*offset[1]; + for (i=0; i < (diff[0]+1); i++) + { + input->GetPoint(pos+i, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,pos+i,ptIds[0]); + cellId = newVerts->InsertNextCell(1,ptIds); + outCD->CopyData(cd,pos+i,cellId); + } + } + } + break; /* end this case */ + + } // switch +// +// Update self and release memory +// + if (newPts) + { + output->SetPoints(newPts); + newPts->Delete(); + } + + if (newVerts) + { + output->SetVerts(newVerts); + newVerts->Delete(); + } + + if (newLines) + { + output->SetLines(newLines); + newLines->Delete(); + } + + if (newPolys) + { + output->SetPolys(newPolys); + newPolys->Delete(); + } + + return 1; +} + +// Specify (imin,imax, jmin,jmax, kmin,kmax) indices. +void vtkRectilinearGridGeometryFilter::SetExtent(int iMin, int iMax, int jMin, + int jMax, int kMin, int kMax) +{ + int extent[6]; + + extent[0] = iMin; + extent[1] = iMax; + extent[2] = jMin; + extent[3] = jMax; + extent[4] = kMin; + extent[5] = kMax; + + this->SetExtent(extent); +} + +// Specify (imin,imax, jmin,jmax, kmin,kmax) indices in array form. +void vtkRectilinearGridGeometryFilter::SetExtent(int extent[6]) +{ + int i; + + if ( extent[0] != this->Extent[0] || extent[1] != this->Extent[1] || + extent[2] != this->Extent[2] || extent[3] != this->Extent[3] || + extent[4] != this->Extent[4] || extent[5] != this->Extent[5] ) + { + this->Modified(); + for (i=0; i<3; i++) + { + if ( extent[2*i] < 0 ) + { + extent[2*i] = 0; + } + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + this->Extent[2*i] = extent[2*i]; + this->Extent[2*i+1] = extent[2*i+1]; + } + } +} + +int vtkRectilinearGridGeometryFilter::FillInputPortInformation( + int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} + +void vtkRectilinearGridGeometryFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Extent: \n"; + os << indent << " Imin,Imax: (" << this->Extent[0] << ", " << this->Extent[1] << ")\n"; + os << indent << " Jmin,Jmax: (" << this->Extent[2] << ", " << this->Extent[3] << ")\n"; + os << indent << " Kmin,Kmax: (" << this->Extent[4] << ", " << this->Extent[5] << ")\n"; +} diff --git a/Graphics/vtkRectilinearGridGeometryFilter.h b/Graphics/vtkRectilinearGridGeometryFilter.h new file mode 100644 index 0000000..2a38527 --- /dev/null +++ b/Graphics/vtkRectilinearGridGeometryFilter.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridGeometryFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridGeometryFilter - extract geometry for a rectilinear grid +// .SECTION Description +// vtkRectilinearGridGeometryFilter is a filter that extracts geometry from a +// rectilinear grid. By specifying appropriate i-j-k indices, it is possible +// to extract a point, a curve, a surface, or a "volume". The volume +// is actually a (n x m x o) region of points. +// +// The extent specification is zero-offset. That is, the first k-plane in +// a 50x50x50 rectilinear grid is given by (0,49, 0,49, 0,0). + +// .SECTION Caveats +// If you don't know the dimensions of the input dataset, you can use a large +// number to specify extent (the number will be clamped appropriately). For +// example, if the dataset dimensions are 50x50x50, and you want a the fifth +// k-plane, you can use the extents (0,100, 0,100, 4,4). The 100 will +// automatically be clamped to 49. + +// .SECTION See Also +// vtkGeometryFilter vtkExtractGrid + +#ifndef __vtkRectilinearGridGeometryFilter_h +#define __vtkRectilinearGridGeometryFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkRectilinearGridGeometryFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkRectilinearGridGeometryFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with initial extent (0,100, 0,100, 0,0) (i.e., a k-plane). + static vtkRectilinearGridGeometryFilter *New(); + + // Description: + // Get the extent in topological coordinate range (imin,imax, jmin,jmax, + // kmin,kmax). + vtkGetVectorMacro(Extent,int,6); + + // Description: + // Specify (imin,imax, jmin,jmax, kmin,kmax) indices. + void SetExtent(int iMin, int iMax, int jMin, int jMax, int kMin, int kMax); + + // Description: + // Specify (imin,imax, jmin,jmax, kmin,kmax) indices in array form. + void SetExtent(int extent[6]); + +protected: + vtkRectilinearGridGeometryFilter(); + ~vtkRectilinearGridGeometryFilter() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int Extent[6]; +private: + vtkRectilinearGridGeometryFilter(const vtkRectilinearGridGeometryFilter&); // Not implemented. + void operator=(const vtkRectilinearGridGeometryFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkRectilinearGridToTetrahedra.cxx b/Graphics/vtkRectilinearGridToTetrahedra.cxx new file mode 100644 index 0000000..295c26f --- /dev/null +++ b/Graphics/vtkRectilinearGridToTetrahedra.cxx @@ -0,0 +1,602 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridToTetrahedra.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridToTetrahedra.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkSignedCharArray.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" +#include "vtkUnstructuredGrid.h" +#include "vtkVoxel.h" + +vtkCxxRevisionMacro(vtkRectilinearGridToTetrahedra, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkRectilinearGridToTetrahedra); + +// ways to convert to a voxel to tetrahedra. +// Note that the values 0 and 1 and -1 and 2 are important in +// DetermineGridDivisionTypes() +#define VTK_TETRAHEDRALIZE_5 0 +#define VTK_TETRAHEDRALIZE_5_FLIP 1 +#define VTK_TETRAHEDRALIZE_6 6 +#define VTK_TETRAHEDRALIZE_12_CONFORM -1 +#define VTK_TETRAHEDRALIZE_12_CONFORM_FLIP 2 +#define VTK_TETRAHEDRALIZE_12 10 + +//------------------------------------------------------------------------- + +vtkRectilinearGridToTetrahedra::vtkRectilinearGridToTetrahedra() +{ + this->TetraPerCell = VTK_VOXEL_TO_5_TET; + this->RememberVoxelId = 0; +} + +//---------------------------------------------------------------------------- + +void vtkRectilinearGridToTetrahedra::SetInput(const double ExtentX, + const double ExtentY, + const double ExtentZ, + const double SpacingX, + const double SpacingY, + const double SpacingZ, + const double tol) +{ + double Extent[3]; + double Spacing[3]; + Extent[0] = ExtentX; Extent[1] = ExtentY; Extent[2] = ExtentZ; + Spacing[0] = SpacingX; Spacing[1] = SpacingY; Spacing[2] = SpacingZ; + this->SetInput(Extent,Spacing,tol); +} + + +//---------------------------------------------------------------------------- + +// Create an input for the filter +void vtkRectilinearGridToTetrahedra::SetInput(const double Extent[3], + const double Spacing[3], + const double tol) +{ + // + // Determine the number of points in each direction, and the positions + // The last voxel may have a different spacing to fit inside + // the selected region + // + + int i, j; + int NumPointsInDir[3]; + vtkFloatArray *Coord[3]; + for(i = 0;i<3;i++) + { + double NumRegion = Extent[i]/Spacing[i]; + + // If we are really close to an integer number of elements, use the + // integer number + if (fabs(NumRegion - floor(NumRegion+0.5)) < tol*Spacing[i]) + NumPointsInDir[i] = ((int) floor(NumRegion+0.5)) + 1; + else + NumPointsInDir[i] = (int) ceil(Extent[i]/Spacing[i])+1; + Coord[i] = vtkFloatArray::New(); + Coord[i]->SetNumberOfValues(NumPointsInDir[i]+1); + + // The last data point inserted is exactly the Extent + // Thus avoiding a bit of numerical error. + for(j=0;jSetValue(j,Spacing[i]*j); + } + Coord[i]->SetValue(NumPointsInDir[i]-1,Extent[i]); + } + + // + // Form the grid + // + + vtkRectilinearGrid *RectGrid = vtkRectilinearGrid::New(); + RectGrid->SetDimensions(NumPointsInDir); + RectGrid->SetXCoordinates(Coord[0]); + RectGrid->SetYCoordinates(Coord[1]); + RectGrid->SetZCoordinates(Coord[2]); + + Coord[0]->Delete(); + Coord[1]->Delete(); + Coord[2]->Delete(); + + // Get the reference counting right. + this->Superclass::SetInput(RectGrid); + RectGrid->Delete(); +} + +//---------------------------------------------------------------------------- + +// Determine how to Divide each voxel in the vtkRectilinearGrid +void vtkRectilinearGridToTetrahedra::DetermineGridDivisionTypes( + vtkRectilinearGrid *RectGrid, + vtkSignedCharArray *VoxelSubdivisionType, + const int &TetraPerCell) +{ + int numRec = RectGrid->GetNumberOfCells(); + int NumPointsInDir[3]; + RectGrid->GetDimensions(NumPointsInDir); + + // How to break into Tetrahedra. + // For division into 5's, we need to flip from one orientation to + // the next + + int Rec[3]; + int flip; + int i; + + switch (TetraPerCell) + { + case (VTK_VOXEL_TO_12_TET): + for(i=0;iSetValue(i,VTK_TETRAHEDRALIZE_12); + } + break; + case (VTK_VOXEL_TO_6_TET): + for(i=0;iSetValue(i,VTK_TETRAHEDRALIZE_6); + } + break; + case (VTK_VOXEL_TO_5_TET): + for(Rec[0] = 0; Rec[0]SetValue(RectGrid->ComputeCellId(Rec),flip); + flip = 1 - flip; + } + } + } + break; + case (VTK_VOXEL_TO_5_AND_12_TET): + for(Rec[0] = 0; Rec[0]ComputeCellId(Rec); + if (VoxelSubdivisionType->GetValue(CellId) == 12) + VoxelSubdivisionType->SetValue(CellId,3*flip-1); + else VoxelSubdivisionType->SetValue(CellId,flip); + flip = 1 - flip; + } + } + } + break; + } +} + +//---------------------------------------------------------------------------- + +// Take the grid and make it into a tetrahedral mesh. +void vtkRectilinearGridToTetrahedra::GridToTetMesh(vtkRectilinearGrid *RectGrid, + vtkSignedCharArray *VoxelSubdivisionType, + const int &TetraPerCell, + const int &RememberVoxelId, + vtkUnstructuredGrid *TetMesh) +{ + int i, j; + int numPts = RectGrid->GetNumberOfPoints(); + int numRec = RectGrid->GetNumberOfCells(); + + // We need a point list and a cell list + vtkPoints *NodePoints = vtkPoints::New(); + vtkCellArray *TetList = vtkCellArray::New(); + + // Guess number of points and cells!! + // For mixture of 5 and 12 tet per cell, + // it is easier to way overguess to avoid re-allocation + // slowness and range checking during insertion. + + switch (TetraPerCell) + { + case (VTK_VOXEL_TO_5_TET): + NodePoints->Allocate(numPts); + TetList->Allocate(numPts*5*5,numPts); + break; + case (VTK_VOXEL_TO_5_AND_12_TET): + case (VTK_VOXEL_TO_12_TET): + NodePoints->Allocate(numPts*2); + TetList->Allocate(numPts*5*12,numPts); + break; + } + + // Start by copying over the points + for(i=0;iInsertNextPoint(RectGrid->GetPoint(i)); + } + + // If they want, we can add Scalar Data + // to the Tets indicating the Voxel Id the tet + // came from. + vtkIntArray *TetOriginalVoxel = NULL; + if (RememberVoxelId) { + TetOriginalVoxel = vtkIntArray::New(); + TetOriginalVoxel->Allocate(12*numRec); + } + + // 9 ids, 8 corners and a possible center to be added later + // during the tet creation + vtkIdList *VoxelCorners = vtkIdList::New(); + VoxelCorners->SetNumberOfIds(9); + + int NumTetFromVoxel; + for(i=0;iGetCellPoints(i,VoxelCorners); + NumTetFromVoxel = TetrahedralizeVoxel(VoxelCorners, + (int)VoxelSubdivisionType->GetValue(i), + NodePoints,TetList); + if (RememberVoxelId) + { + for(j=0;jInsertNextValue(i); + } + } + } + + // + // It may be there are extra points at the end of the PointList. + // + + NodePoints->Squeeze(); + + // + // Form the Mesh + // + + // Need to tell the tet mesh that every cell is a Tetrahedron + int numTet = TetList->GetNumberOfCells(); + int *CellTypes = new int[numTet]; + for(i=0;iSetPoints(NodePoints); + TetMesh->SetCells(CellTypes,TetList); + + // + // Add Scalar Types if wanted + // + + if(RememberVoxelId) + { + TetOriginalVoxel->Squeeze(); + int idx = TetMesh->GetCellData()->AddArray(TetOriginalVoxel); + TetMesh->GetCellData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + TetOriginalVoxel->Delete(); + } + + // + // Clean Up + // + delete[] CellTypes; + NodePoints->Delete(); + TetList->Delete(); + VoxelCorners->Delete(); + + TetMesh->Squeeze(); +} + +//---------------------------------------------------------------------------- +// Helper Function for Tetrahedralize Voxel +inline void vtkRectilinearGridToTetrahedra::TetrahedralizeAddCenterPoint( + vtkIdList *VoxelCorners, + vtkPoints *NodeList) +{ + // Need to add a center point + double c1[3], c2[3]; + NodeList->GetPoint(VoxelCorners->GetId(0), c2); + NodeList->GetPoint(VoxelCorners->GetId(7), c1); + double center[3]; + center[0] = (c1[0] + c2[0])/2.0; + center[1] = (c1[1] + c2[1])/2.0; + center[2] = (c1[2] + c2[2])/2.0; + + VoxelCorners->InsertId(8,NodeList->InsertNextPoint(center)); +} + +//---------------------------------------------------------------------------- + +// Split A Cube into Tetrahedrons +// According to the DivisionType +// There had better be 0..8 voxel corners, though only 0..7 maybe needed. +// Why? This function may add id 8 to VoxelCorners. +// If a point needs to be inserted into the nodelist, itselt +// it at NextPointId. Assume there is space in the nodelist. +// Return the number of Tets Added. + + +int vtkRectilinearGridToTetrahedra::TetrahedralizeVoxel(vtkIdList *VoxelCorners, + const int &DivisionType, + vtkPoints *NodeList, + vtkCellArray *TetList) +{ + +// See vtkVoxel::Triangulate +/* Looking at the rect: Corner labeling + + 0 1 + 2 3 + + Directly behind them: + 4 5 + 6 7 + +and 8 is in the middle of the cube if used + +Want right handed Tetrahedra... +*/ + + // Split voxel in 2 along diagonal, 3 tets on either side + static int tet6[6][4] = + { + {1,6,2,3}, {1,6,7,5}, {1,6,3,7}, + {1,6,0,2}, {1,6,5,4}, {1,6,4,0}, + }; + + static int tet5[5][4] = + { {0,1,4,2},{1,4,7,5},{1,4,2,7},{1,2,3,7},{2,7,4,6} }; + static int tet5flip[5][4] = + { {3,1,0,5}, {0,3,6,2}, {3,5,6,7}, {0,6,5,4}, {0,3,5,6}}; + + // 12 tet to confirm to tet5 + static int tet12_conform[12][4] = { + /* Left side */ + {8,2,4,0}, + {8,4,2,6}, + /* Back side */ + {8,7,4,6}, + {8,4,7,5}, + /* Bottom side */ + {8,7,2,3}, + {8,2,7,6}, + /* Right side */ + {8,7,1,5}, + {8,1,7,3}, + /* Front side */ + {8,1,2,0}, + {8,2,1,3}, + /* Top side */ + {8,4,1,0}, + {8,1,4,5}}; + + // 12 tet to confirm to tet5flip + static int tet12_conform_flip[12][4] = { + /* Left side */ + {8,0,6,4}, + {8,6,0,2}, + /* Back side */ + {8,5,6,7}, + {8,6,5,4}, + /* Bottom side */ + {8,3,6,2}, + {8,6,3,7}, + /* Right side */ + {8,3,5,7}, + {8,5,3,1}, + /* Front side */ + {8,3,0,1}, + {8,0,3,2}, + /* Top side */ + {8,5,0,4}, + {8,0,5,1}}; + + // 12 tet chosen to have the least number of edges per node + static int tet12[12][4] = { + /* Left side */ + {8,2,4,0}, + {8,4,2,6}, + /* Back side */ + {8,7,4,6}, + {8,4,7,5}, + /* Right side */ + {8,3,5,7}, + {8,5,3,1}, + /* Front side */ + {8,3,0,1}, + {8,0,3,2}, + /* Top side */ + {8,5,0,4}, + {8,0,5,1}, + /* Bottom side */ + {8,7,2,3}, + {8,2,7,6}}; + + + int i, j; + // Get the point Ids + int numTet = 0; // =0 removes warning messages + vtkIdType TetPts[4]; + + switch (DivisionType) + { + case (VTK_TETRAHEDRALIZE_6) : + numTet = 6; + for(i=0;iGetId(tet6[i][j]); + } + TetList->InsertNextCell((vtkIdType)4,TetPts); + } + break; + case (VTK_TETRAHEDRALIZE_5) : + numTet = 5; + for(i=0;iGetId(tet5[i][j]); + } + TetList->InsertNextCell((vtkIdType)4,TetPts); + } + break; + case (VTK_TETRAHEDRALIZE_5_FLIP) : + numTet = 5; + for(i=0;iGetId(tet5flip[i][j]); + } + TetList->InsertNextCell((vtkIdType)4,TetPts); + } + break; + case (VTK_TETRAHEDRALIZE_12) : + numTet = 12; + TetrahedralizeAddCenterPoint(VoxelCorners,NodeList); + for(i=0;iGetId(tet12[i][j]); + } + TetList->InsertNextCell((vtkIdType)4,TetPts); + } + break; + case (VTK_TETRAHEDRALIZE_12_CONFORM) : + numTet = 12; + TetrahedralizeAddCenterPoint(VoxelCorners,NodeList); + for(i=0;iGetId(tet12_conform[i][j]); + } + TetList->InsertNextCell((vtkIdType)4,TetPts); + } + break; + case (VTK_TETRAHEDRALIZE_12_CONFORM_FLIP) : + numTet = 12; + TetrahedralizeAddCenterPoint(VoxelCorners,NodeList); + for(i=0;iGetId(tet12_conform_flip[i][j]); + } + TetList->InsertNextCell((vtkIdType)4,TetPts); + } + break; + } + return numTet; +} + +//---------------------------------------------------------------------------- + +int vtkRectilinearGridToTetrahedra::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkRectilinearGrid *RectGrid = vtkRectilinearGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Create internal version of VoxelSubdivisionType + // VoxelSubdivisionType indicates how to subdivide each cell + vtkSignedCharArray *VoxelSubdivisionType; + VoxelSubdivisionType = vtkSignedCharArray::New(); + + // If we have a mixture of 5 and 12 Tet, we need to get the information from + // the scalars of the Input. Note that we will modify the array internally + // so we need to copy it. + if (this->TetraPerCell == VTK_VOXEL_TO_5_AND_12_TET) + { + vtkDataArray *TempVoxelSubdivisionType = RectGrid->GetCellData()->GetScalars(); + if((TempVoxelSubdivisionType == NULL)) + { + vtkErrorMacro(<< "Scalars to input Should be set!"); + return 1; + } + VoxelSubdivisionType->SetNumberOfValues(RectGrid->GetNumberOfCells()); + VoxelSubdivisionType->vtkSignedCharArray::DeepCopy(TempVoxelSubdivisionType); + } + else + { // Otherwise, just create the GridDivisionTypes + VoxelSubdivisionType->SetNumberOfValues(RectGrid->GetNumberOfCells()); + } + + vtkDebugMacro(<<"Number of points: " + << RectGrid->GetNumberOfPoints()); + vtkDebugMacro(<< "Number of voxels in input: " + << RectGrid->GetNumberOfCells()); + + // Determine how each Cell should be subdivided + DetermineGridDivisionTypes(RectGrid,VoxelSubdivisionType, + this->TetraPerCell); + + // Subdivide each cell to a tetrahedron, forming the TetMesh + GridToTetMesh(RectGrid,VoxelSubdivisionType,this->TetraPerCell, + this->RememberVoxelId,output); + + vtkDebugMacro(<< "Number of output points: " + << output->GetNumberOfPoints()); + vtkDebugMacro(<< "Number of output tetrahedra: " + << output->GetNumberOfCells()); + + // Clean Up + VoxelSubdivisionType->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int +vtkRectilinearGridToTetrahedra +::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} + +//---------------------------------------------------------------------------- + +void vtkRectilinearGridToTetrahedra::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Mesh Type: " << this->TetraPerCell << "\n"; + os << indent << "RememberVoxel Id: " << this->RememberVoxelId << "\n"; +} diff --git a/Graphics/vtkRectilinearGridToTetrahedra.h b/Graphics/vtkRectilinearGridToTetrahedra.h new file mode 100644 index 0000000..81082c1 --- /dev/null +++ b/Graphics/vtkRectilinearGridToTetrahedra.h @@ -0,0 +1,155 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridToTetrahedra.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridToTetrahedra - create a Tetrahedral mesh from a RectilinearGrid +// .SECTION Description +// vtkRectilinearGridToTetrahedra forms a mesh of Tetrahedra from a +// vtkRectilinearGrid. The tetrahedra can be 5 per cell, 6 per cell, +// or a mixture of 5 or 12 per cell. The resulting mesh is consistent, +// meaning that there are no edge crossings and that each tetrahedron +// face is shared by two tetrahedra, except those tetrahedra on the +// boundary. All tetrahedra are right handed. +// +// Note that 12 tetrahedra per cell means adding a point in the +// center of the cell. +// +// In order to subdivide some cells into 5 and some cells into 12 tetrahedra: +// SetTetraPerCellTo5And12(); +// Set the Scalars of the Input RectilinearGrid to be 5 or 12 +// depending on what you want per cell of the RectilinearGrid. +// +// If you set RememberVoxelId, the scalars of the tetrahedron +// will be set to the Id of the Cell in the RectilinearGrid from which +// the tetrahedron came. +// +// .SECTION Thanks +// This class was developed by Samson J. Timoner of the +// MIT Artificial Intelligence Laboratory +// +// .SECTION See Also +// vtkDelaunay3D + +#ifndef __vtkRectilinearGridToTetrahedra_h +#define __vtkRectilinearGridToTetrahedra_h + +// ways to create the mesh from voxels +#define VTK_VOXEL_TO_12_TET 12 +#define VTK_VOXEL_TO_5_TET 5 +#define VTK_VOXEL_TO_6_TET 6 +#define VTK_VOXEL_TO_5_AND_12_TET -1 + +#include "vtkUnstructuredGridAlgorithm.h" +class vtkRectilinearGrid; +class vtkSignedCharArray; +class vtkIdList; +class vtkCellArray; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkRectilinearGridToTetrahedra : public vtkUnstructuredGridAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkRectilinearGridToTetrahedra,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Form 5 Tetrahedra per cube. Do not RememberVoxelId. + static vtkRectilinearGridToTetrahedra *New(); + + // Description: + // Set the method to divide each cell (voxel) in the RectilinearGrid + // into tetrahedra. + void SetTetraPerCellTo5() {SetTetraPerCell(VTK_VOXEL_TO_5_TET);}; + void SetTetraPerCellTo6() {SetTetraPerCell(VTK_VOXEL_TO_6_TET);}; + void SetTetraPerCellTo12() {SetTetraPerCell(VTK_VOXEL_TO_12_TET);}; + void SetTetraPerCellTo5And12() {SetTetraPerCell(VTK_VOXEL_TO_5_AND_12_TET);}; + vtkSetMacro(TetraPerCell,int); + vtkGetMacro(TetraPerCell,int); + + // Description: + // Should the tetrahedra have scalar data + // indicating which Voxel they came from in the vtkRectilinearGrid? + vtkSetMacro(RememberVoxelId,int); + vtkGetMacro(RememberVoxelId,int); + vtkBooleanMacro(RememberVoxelId,int); + + // Description: + // This function for convenience for creating a Rectilinear Grid + // If Spacing does not fit evenly into extent, the last cell will + // have a different width (or height or depth). + // If Extent[i]/Spacing[i] is within tol of an integer, then + // assume the programmer meant an integer for direction i. + void SetInput(const double Extent[3], const double Spacing[3], + const double tol=0.001); + // Description: + // This version of the function for the wrappers + void SetInput(const double ExtentX, + const double ExtentY, + const double ExtentZ, + const double SpacingX, + const double SpacingY, + const double SpacingZ, + const double tol=0.001); + +protected: + vtkRectilinearGridToTetrahedra(); + ~vtkRectilinearGridToTetrahedra() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int RememberVoxelId; + int TetraPerCell; + + virtual int FillInputPortInformation(int, vtkInformation*); + + private: + vtkRectilinearGridToTetrahedra(const vtkRectilinearGridToTetrahedra&); // Not implemented. + + void operator=(const vtkRectilinearGridToTetrahedra&); // Not implemented. + +//BTX + // Description: + // Determine how to Divide each cell (voxel) in the RectilinearGrid + // Overwrites VoxelSubdivisionType with flipping information for forming the mesh + static void DetermineGridDivisionTypes(vtkRectilinearGrid *RectGrid, + vtkSignedCharArray *VoxelSubdivisionType, + const int &TetraPerCell); + + // Description: + // Take the grid and make it into a tetrahedral mesh. + static void GridToTetMesh(vtkRectilinearGrid *RectGrid, + vtkSignedCharArray *VoxelSubdivisionType, + const int &TetraPerCell, + const int &RememberVoxelId, + vtkUnstructuredGrid *TetMesh); + + // Description: + // Take a voxel and make tetrahedra out of it. + // Add the resulting tetrahedra to TetraMesh. Also, should new + // points need to be created, add them to NodeList. + // Note that vtkIdList may be changed during this process (a point added). + static int TetrahedralizeVoxel(vtkIdList *VoxelCorners, + const int &DivisionType, + vtkPoints *NodeList, + vtkCellArray *TetList); + + // Description: + // Helper Function for TetrahedraizeVoxel + // Adds a center point in the middle of the voxel + static inline void TetrahedralizeAddCenterPoint(vtkIdList *VoxelCorners, + vtkPoints *NodeList); +//ETX +}; + +#endif /* __vtkRectilinearGridToTetrahedra_h */ + diff --git a/Graphics/vtkRectilinearSynchronizedTemplates.cxx b/Graphics/vtkRectilinearSynchronizedTemplates.cxx new file mode 100644 index 0000000..dbce44d --- /dev/null +++ b/Graphics/vtkRectilinearSynchronizedTemplates.cxx @@ -0,0 +1,914 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearSynchronizedTemplates.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearSynchronizedTemplates.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkExtentTranslator.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredPoints.h" +#include "vtkSynchronizedTemplates3D.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include + +vtkCxxRevisionMacro(vtkRectilinearSynchronizedTemplates, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkRectilinearSynchronizedTemplates); + +//---------------------------------------------------------------------------- +// Description: +// Construct object with initial scalar range (0,1) and single contour value +// of 0.0. The ImageRange are set to extract the first k-plane. +vtkRectilinearSynchronizedTemplates::vtkRectilinearSynchronizedTemplates() +{ + this->ContourValues = vtkContourValues::New(); + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->ExecuteExtent[0] = this->ExecuteExtent[1] + = this->ExecuteExtent[2] = this->ExecuteExtent[3] + = this->ExecuteExtent[4] = this->ExecuteExtent[5] = 0; + + this->ArrayComponent = 0; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//---------------------------------------------------------------------------- +vtkRectilinearSynchronizedTemplates::~vtkRectilinearSynchronizedTemplates() +{ + this->ContourValues->Delete(); +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkRectilinearSynchronizedTemplates::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long mTime2=this->ContourValues->GetMTime(); + + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + return mTime; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearSynchronizedTemplatesInitializeOutput( + int *ext, vtkRectilinearGrid *input, vtkPolyData *o, vtkFloatArray *scalars, + vtkFloatArray *normals, vtkFloatArray *gradients, vtkDataArray *inScalars) +{ + vtkPoints *newPts; + vtkCellArray *newPolys; + long estimatedSize; + + estimatedSize = (int) pow ((double) + ((ext[1]-ext[0]+1)*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1)), .75); + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(estimatedSize,3)); + + o->GetPointData()->CopyAllOn(); + // It is more efficient to just create the scalar array + // rather than redundantly interpolate the scalars. + if (input->GetPointData()->GetScalars() == inScalars) + { + o->GetPointData()->CopyScalarsOff(); + } + else + { + o->GetPointData()->CopyFieldOff(inScalars->GetName()); + } + + if (normals) + { + normals->SetNumberOfComponents(3); + normals->Allocate(3*estimatedSize,3*estimatedSize/2); + normals->SetName("Normals"); + } + if (gradients) + { + gradients->SetNumberOfComponents(3); + gradients->Allocate(3*estimatedSize,3*estimatedSize/2); + gradients->SetName("Gradients"); + } + if (scalars) + { + // A temporary name. + scalars->SetName("Scalars"); + } + + o->GetPointData()->InterpolateAllocate(input->GetPointData(), + estimatedSize,estimatedSize/2); + o->GetCellData()->CopyAllocate(input->GetCellData(), + estimatedSize,estimatedSize/2); + + o->SetPoints(newPts); + newPts->Delete(); + + o->SetPolys(newPolys); + newPolys->Delete(); +} + +//---------------------------------------------------------------------------- +// Calculate the gradient using central difference. +template +void vtkRSTComputePointGradient(int i, int j, int k, T *s, int *wholeExt, + int xInc, int yInc, int zInc, + double *spacing, double n[3]) +{ + double sp, sm; + + // x-direction + if ( i == wholeExt[0] ) + { + sp = *(s+xInc); + sm = *s; + n[0] = (sp - sm) / spacing[1]; + } + else if ( i == wholeExt[1] ) + { + sp = *s; + sm = *(s-xInc); + n[0] = (sp - sm) / spacing[0]; + } + else + { + sp = *(s+xInc); + sm = *(s-xInc); + n[0] = (sp - sm) / (spacing[0]+spacing[1]); + } + + // y-direction + if ( j == wholeExt[2] ) + { + sp = *(s+yInc); + sm = *s; + n[1] = (sp - sm) / spacing[3]; + } + else if ( j == wholeExt[3] ) + { + sp = *s; + sm = *(s-yInc); + n[1] = (sp - sm) / spacing[2]; + } + else + { + sp = *(s+yInc); + sm = *(s-yInc); + n[1] = (sp - sm) / (spacing[2]+spacing[3]); + } + + // z-direction + if ( k == wholeExt[4] ) + { + sp = *(s+zInc); + sm = *s; + n[2] = (sp - sm) / spacing[5]; + } + else if ( k == wholeExt[5] ) + { + sp = *s; + sm = *(s-zInc); + n[2] = (sp - sm) / spacing[4]; + } + else + { + sp = *(s+zInc); + sm = *(s-zInc); + n[2] = (sp - sm) / (spacing[4]+spacing[5]); + } +} + +//---------------------------------------------------------------------------- +#define VTK_RECT_CSP3PA(i2,j2,k2,s) \ +if (NeedGradients) \ +{ \ + if (!g0) \ + { \ + self->ComputeSpacing(data, i, j, k, exExt, spacing); \ + vtkRSTComputePointGradient(i, j, k, s0, exExt, xInc, yInc, zInc, spacing, n0); \ + g0 = 1; \ + } \ + self->ComputeSpacing(data, i2, j2, k2, exExt, spacing); \ + vtkRSTComputePointGradient(i2, j2, k2, s, exExt, xInc, yInc, zInc, spacing, n1); \ + for (jj=0; jj<3; jj++) \ + { \ + n[jj] = n0[jj] + t * (n1[jj] - n0[jj]); \ + } \ + if (ComputeGradients) \ + { \ + newGradients->InsertNextTuple(n); \ + } \ + if (ComputeNormals) \ + { \ + vtkMath::Normalize(n); \ + n[0] = -n[0]; n[1] = -n[1]; n[2] = -n[2]; \ + newNormals->InsertNextTuple(n); \ + } \ +} \ +if (ComputeScalars) \ +{ \ + newScalars->InsertNextTuple(&value); \ +} + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images +// +template +void ContourRectilinearGrid(vtkRectilinearSynchronizedTemplates *self, int *exExt, + vtkRectilinearGrid *data, vtkPolyData *output, T *ptr, + vtkDataArray *inScalars) +{ + int *inExt = data->GetExtent(); + int xdim = exExt[1] - exExt[0] + 1; + int ydim = exExt[3] - exExt[2] + 1; + double *values = self->GetValues(); + int numContours = self->GetNumberOfContours(); + T *inPtrX, *inPtrY, *inPtrZ; + T *s0, *s1, *s2, *s3; + int xMin, xMax, yMin, yMax, zMin, zMax; + int xInc, yInc, zInc; + int *isect1Ptr, *isect2Ptr; + double y, z, t; + int i, j, k; + int zstep, yisectstep; + int offsets[12]; + int ComputeNormals = self->GetComputeNormals(); + int ComputeGradients = self->GetComputeGradients(); + int ComputeScalars = self->GetComputeScalars(); + int NeedGradients = ComputeGradients || ComputeNormals; + double n[3], n0[3], n1[3]; + int jj, g0; + int *tablePtr; + int idx, vidx; + double x[3], xz[3]; + int v0, v1, v2, v3; + vtkIdType ptIds[3]; + double value; + // We need to know the edgePointId's for interpolating attributes. + int edgePtId, inCellId, outCellId; + vtkPointData *inPD = data->GetPointData(); + vtkCellData *inCD = data->GetCellData(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *outCD = output->GetCellData(); + // Use to be arguments + vtkFloatArray *newScalars = NULL; + vtkFloatArray *newNormals = NULL; + vtkFloatArray *newGradients = NULL; + vtkPoints *newPts; + vtkCellArray *newPolys; + ptr += self->GetArrayComponent(); + vtkDataArray *xCoords = data->GetXCoordinates(); + vtkDataArray *yCoords = data->GetYCoordinates(); + vtkDataArray *zCoords = data->GetZCoordinates(); + double x1, x2, y2, z2; + double spacing[6]; + + if (ComputeScalars) + { + newScalars = vtkFloatArray::New(); + } + if (ComputeNormals) + { + newNormals = vtkFloatArray::New(); + } + if (ComputeGradients) + { + newGradients = vtkFloatArray::New(); + } + vtkRectilinearSynchronizedTemplatesInitializeOutput(exExt, data, output, + newScalars, newNormals, newGradients, inScalars); + newPts = output->GetPoints(); + newPolys = output->GetPolys(); + + // this is an exploded execute extent. + xMin = exExt[0]; + xMax = exExt[1]; + yMin = exExt[2]; + yMax = exExt[3]; + zMin = exExt[4]; + zMax = exExt[5]; + + // increments to move through scalars Compute these ourself because + // we may be contouring an array other than scalars. + + xInc = inScalars->GetNumberOfComponents(); + yInc = xInc*(inExt[1]-inExt[0]+1); + zInc = yInc*(inExt[3]-inExt[2]+1); + + // Kens increments, probably to do with edge array + zstep = xdim*ydim; + yisectstep = xdim*3; + // compute offsets probably how to get to the edges in the edge array. + offsets[0] = -xdim*3; + offsets[1] = -xdim*3 + 1; + offsets[2] = -xdim*3 + 2; + offsets[3] = -xdim*3 + 4; + offsets[4] = -xdim*3 + 5; + offsets[5] = 0; + offsets[6] = 2; + offsets[7] = 5; + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + + // allocate storage array + int *isect1 = new int [xdim*ydim*3*2]; + // set impossible edges to -1 + for (i = 0; i < ydim; i++) + { + isect1[(i+1)*xdim*3-3] = -1; + isect1[(i+1)*xdim*3*2-3] = -1; + } + for (i = 0; i < xdim; i++) + { + isect1[((ydim-1)*xdim + i)*3 + 1] = -1; + isect1[((ydim-1)*xdim + i)*3*2 + 1] = -1; + } + + // for each contour + for (vidx = 0; vidx < numContours; vidx++) + { + value = values[vidx]; + inPtrZ = ptr; + s2 = inPtrZ; + v2 = (*s2 < value ? 0 : 1); + + //================================================================== + for (k = zMin; k <= zMax; k++) + { + self->UpdateProgress((double)vidx/numContours + + (k-zMin)/((zMax - zMin+1.0)*numContours)); + + z = zCoords->GetComponent(k-inExt[4], 0); + x[2] = z; + + // swap the buffers + if (k%2) + { + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + isect1Ptr = isect1; + isect2Ptr = isect1 + xdim*ydim*3; + } + else + { + offsets[8] = (-zstep - xdim)*3; + offsets[9] = (-zstep - xdim)*3 + 1; + offsets[10] = (-zstep - xdim)*3 + 4; + offsets[11] = -zstep*3; + isect1Ptr = isect1 + xdim*ydim*3; + isect2Ptr = isect1; + } + + inPtrY = inPtrZ; + for (j = yMin; j <= yMax; j++) + { + // Should not impact perfomance here/ + edgePtId = (j-inExt[2])*yInc + (k-inExt[4])*zInc; + // Increments are different for cells. + // Since the cells are not contoured until the second row of templates, + // subtract 1 from i,j,and k. Note: first cube is formed when i=0, j=1, and k=1. + inCellId = (xMin-inExt[0]) + (inExt[1]-inExt[0])*( (j-inExt[2]-1) + (k-inExt[4]-1)*(inExt[3]-inExt[2]) ); + + y = yCoords->GetComponent(j-inExt[2], 0); + xz[1] = y; + + s1 = inPtrY; + v1 = (*s1 < value ? 0 : 1); + + inPtrX = inPtrY; + for (i = xMin; i <= xMax; i++) + { + s0 = s1; + v0 = v1; + // this flag keeps up from computing gradient for grid point 0 twice. + g0 = 0; + *isect2Ptr = -1; + *(isect2Ptr + 1) = -1; + *(isect2Ptr + 2) = -1; + if (i < xMax) + { + s1 = (inPtrX + xInc); + v1 = (*s1 < value ? 0 : 1); + if (v0 ^ v1) + { + // watch for degenerate points + if (*s0 == value) + { + if (i > xMin && *(isect2Ptr-3) > -1) + { + *isect2Ptr = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *isect2Ptr = *(isect1Ptr+2); + } + } + else if (*s1 == value) + { + if (j > yMin && *(isect2Ptr - yisectstep +4) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 4); + } + else if (k > zMin && i < xMax && *(isect1Ptr + 5) > -1) + { + *isect2Ptr = *(isect1Ptr + 5); + } + } + // if the edge has not been set yet then it is a new point + if (*isect2Ptr == -1) + { + t = (value - (double)(*s0)) / ((double)(*s1) - (double)(*s0)); + x1 = xCoords->GetComponent(i-inExt[0], 0); + x2 = xCoords->GetComponent(i-inExt[0]+1, 0); + x[0] = x1 + t*(x2-x1); + x[1] = y; + + *isect2Ptr = newPts->InsertNextPoint(x); + VTK_RECT_CSP3PA(i+1,j,k,s1); + outPD->InterpolateEdge(inPD, *isect2Ptr, edgePtId, edgePtId+1, t); + } + } + } + if (j < yMax) + { + s2 = (inPtrX + yInc); + v2 = (*s2 < value ? 0 : 1); + if (v0 ^ v2) + { + // watch for degen points + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 1) = *isect2Ptr; + } + else if (i > xMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 1) = *(isect1Ptr+2); + } + } + else if (*s2 == value && k > zMin && *(isect1Ptr + yisectstep + 2) > -1) + { + *(isect2Ptr+1) = *(isect1Ptr + yisectstep + 2); + } + // if the edge has not been set yet then it is a new point + if (*(isect2Ptr + 1) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s2) - (double)(*s0)); + x[0] = xCoords->GetComponent(i-inExt[0], 0); + + y2 = yCoords->GetComponent(j-inExt[2]+1, 0); + x[1] = y + t*(y2-y); + + *(isect2Ptr + 1) = newPts->InsertNextPoint(x); + VTK_RECT_CSP3PA(i,j+1,k,s2); + outPD->InterpolateEdge(inPD, *(isect2Ptr+1), edgePtId, edgePtId+yInc, t); + } + } + } + if (k < zMax) + { + s3 = (inPtrX + zInc); + v3 = (*s3 < value ? 0 : 1); + if (v0 ^ v3) + { + // watch for degen points + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 2) = *isect2Ptr; + } + else if (*(isect2Ptr+1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr+1); + } + else if (i > xMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 2) = *(isect1Ptr+2); + } + } + if (*(isect2Ptr + 2) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s3) - (double)(*s0)); + xz[0] = xCoords->GetComponent(i-inExt[0], 0); + + z2 = zCoords->GetComponent(k-inExt[4]+1, 0); + xz[2] = z + t*(z2-z); + + *(isect2Ptr + 2) = newPts->InsertNextPoint(xz); + VTK_RECT_CSP3PA(i,j,k+1,s3); + outPD->InterpolateEdge(inPD, *(isect2Ptr+2), edgePtId, edgePtId+zInc, t); + } + } + } + // To keep track of ids for interpolating attributes. + ++edgePtId; + + // now add any polys that need to be added + // basically look at the isect values, + // form an index and lookup the polys + if (j > yMin && i < xMax && k > zMin) + { + idx = (v0 ? 4096 : 0); + idx = idx + (*(isect1Ptr - yisectstep) > -1 ? 2048 : 0); + idx = idx + (*(isect1Ptr -yisectstep +1) > -1 ? 1024 : 0); + idx = idx + (*(isect1Ptr -yisectstep +2) > -1 ? 512 : 0); + idx = idx + (*(isect1Ptr -yisectstep +4) > -1 ? 256 : 0); + idx = idx + (*(isect1Ptr -yisectstep +5) > -1 ? 128 : 0); + idx = idx + (*(isect1Ptr) > -1 ? 64 : 0); + idx = idx + (*(isect1Ptr + 2) > -1 ? 32 : 0); + idx = idx + (*(isect1Ptr + 5) > -1 ? 16 : 0); + idx = idx + (*(isect2Ptr -yisectstep) > -1 ? 8 : 0); + idx = idx + (*(isect2Ptr -yisectstep +1) > -1 ? 4 : 0); + idx = idx + (*(isect2Ptr -yisectstep +4) > -1 ? 2 : 0); + idx = idx + (*(isect2Ptr) > -1 ? 1 : 0); + + tablePtr = VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_2 + + VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_1[idx]; + while (*tablePtr != -1) + { + ptIds[0] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[1] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[2] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + if (ptIds[0] != ptIds[1] && + ptIds[0] != ptIds[2] && + ptIds[1] != ptIds[2]) + { + outCellId = newPolys->InsertNextCell(3,ptIds); + outCD->CopyData(inCD, inCellId, outCellId); + } + } + } + inPtrX += xInc; + isect2Ptr += 3; + isect1Ptr += 3; + // To keep track of ids for copying cell attributes.. + ++inCellId; + } + inPtrY += yInc; + } + inPtrZ += zInc; + } + } + delete [] isect1; + + if (newScalars) + { + // Lets set the name of the scalars here. + if (inScalars) + { + newScalars->SetName(inScalars->GetName()); + } + idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + newScalars = NULL; + } + if (newGradients) + { + output->GetPointData()->SetVectors(newGradients); + newGradients->Delete(); + newGradients = NULL; + } + if (newNormals) + { + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + newNormals = NULL; + } +} + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images (or slices from images) +// +int vtkRectilinearSynchronizedTemplates::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkRectilinearGrid *data = vtkRectilinearGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + void *ptr; + vtkDataArray *inScalars; + + vtkDebugMacro(<< "Executing 3D structured contour"); + + if ( this->ExecuteExtent[0] >= this->ExecuteExtent[1] || + this->ExecuteExtent[2] >= this->ExecuteExtent[3] || + this->ExecuteExtent[4] >= this->ExecuteExtent[5] ) + { + vtkDebugMacro(<<"3D structured contours requires 3D data"); + return 1; + } + + // + // Check data type and execute appropriate function + // + inScalars = this->GetInputArrayToProcess(0,inputVector); + if (inScalars == NULL) + { + vtkErrorMacro("No scalars for contouring."); + } + int numComps = inScalars->GetNumberOfComponents(); + + if (this->ArrayComponent >= numComps) + { + vtkErrorMacro("Scalars have " << numComps << " components. " + "ArrayComponent must be smaller than " << numComps); + return 1; + } + + ptr = this->GetScalarsForExtent(inScalars, this->ExecuteExtent, data); + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + ContourRectilinearGrid(this, this->ExecuteExtent, data, + output, (VTK_TT *)ptr, inScalars)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkRectilinearSynchronizedTemplates::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces; + int *wholeExt; + int ext[6]; + vtkExtentTranslator *translator; + + translator = vtkExtentTranslator::SafeDownCast( + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + + wholeExt = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + memcpy(ext, wholeExt, 6*sizeof(int)); + + // Get request from output + piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + // get the extent associated with the piece. + if (translator == NULL) + { + // Default behavior + if (piece != 0) + { + ext[0] = ext[2] = ext[4] = 0; + ext[1] = ext[3] = ext[5] = -1; + } + } + else + { + translator->PieceToExtentThreadSafe(piece, numPieces, 0, wholeExt, ext, + translator->GetSplitMode(),0); + } + + // As a side product of this call, ExecuteExtent is set. + // This is the region that we are really updating, although + // we may require a larger input region in order to generate + // it if normals / gradients are being computed + + this->ExecuteExtent[0] = ext[0]; + this->ExecuteExtent[1] = ext[1]; + this->ExecuteExtent[2] = ext[2]; + this->ExecuteExtent[3] = ext[3]; + this->ExecuteExtent[4] = ext[4]; + this->ExecuteExtent[5] = ext[5]; + + // expand if we need to compute gradients + if (this->ComputeGradients || this->ComputeNormals) + { + ext[0] -= 1; + if (ext[0] < wholeExt[0]) + { + ext[0] = wholeExt[0]; + } + ext[1] += 1; + if (ext[1] > wholeExt[1]) + { + ext[1] = wholeExt[1]; + } + + ext[2] -= 1; + if (ext[2] < wholeExt[2]) + { + ext[2] = wholeExt[2]; + } + ext[3] += 1; + if (ext[3] > wholeExt[3]) + { + ext[3] = wholeExt[3]; + } + + ext[4] -= 1; + if (ext[4] < wholeExt[4]) + { + ext[4] = wholeExt[4]; + } + ext[5] += 1; + if (ext[5] > wholeExt[5]) + { + ext[5] = wholeExt[5]; + } + } + + // Set the update extent of the input. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +void* vtkRectilinearSynchronizedTemplates::GetScalarsForExtent( + vtkDataArray *array, int extent[6], vtkRectilinearGrid *input) +{ + if ( ! array ) + { + return NULL; + } + + int increments[3], iExt[6], idx; + + input->GetExtent(iExt); + + for (idx = 0; idx < 3; idx++) + { + if (extent[idx*2] < iExt[idx*2] || + extent[idx*2] > iExt[idx*2+1]) + { + vtkErrorMacro("requested extent not in input's extent"); + return NULL; + } + } + + increments[0] = array->GetNumberOfComponents(); + increments[1] = increments[0] * (iExt[1]-iExt[0]+1); + increments[2] = increments[1] * (iExt[3]-iExt[2]+1); + + idx = (extent[0] - iExt[0]) * increments[0] + + (extent[2] - iExt[2]) * increments[1] + + (extent[4] - iExt[4]) * increments[2]; + + if (idx < 0 || idx > array->GetMaxId()) + { + vtkErrorMacro("computed coordinate outside of array bounds"); + return NULL; + } + + return array->GetVoidPointer(idx); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearSynchronizedTemplates::ComputeSpacing( + vtkRectilinearGrid *data, int i, int j, int k, int extent[6], + double spacing[6]) +{ + vtkDataArray *xCoords = data->GetXCoordinates(); + vtkDataArray *yCoords = data->GetYCoordinates(); + vtkDataArray *zCoords = data->GetZCoordinates(); + + spacing[0] = 0; + spacing[1] = 0; + spacing[2] = 0; + spacing[3] = 0; + spacing[4] = 0; + spacing[5] = 0; + + if (i > extent[0]) + { + spacing[0] = xCoords->GetComponent(i-extent[0], 0) - + xCoords->GetComponent(i-extent[0]-1, 0); + } + if (i < extent[1]) + { + spacing[1] = xCoords->GetComponent(i-extent[0]+1, 0) - + xCoords->GetComponent(i-extent[0], 0); + } + if (j > extent[2]) + { + spacing[2] = yCoords->GetComponent(j-extent[2], 0) - + yCoords->GetComponent(j-extent[2]-1, 0); + } + if (j < extent[3]) + { + spacing[3] = yCoords->GetComponent(j-extent[2]+1, 0) - + yCoords->GetComponent(j-extent[2], 0); + } + if (k > extent[4]) + { + spacing[4] = zCoords->GetComponent(k-extent[4], 0) - + zCoords->GetComponent(k-extent[4]-1, 0); + } + if (k < extent[5]) + { + spacing[5] = zCoords->GetComponent(k-extent[4]+1, 0) - + zCoords->GetComponent(k-extent[4], 0); + } +} + +//---------------------------------------------------------------------------- +int vtkRectilinearSynchronizedTemplates::FillInputPortInformation( + int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearSynchronizedTemplates::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Gradients: " << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " << (this->ComputeScalars ? "On\n" : "Off\n"); + os << indent << "ArrayComponent: " << this->ArrayComponent << endl; +} + diff --git a/Graphics/vtkRectilinearSynchronizedTemplates.h b/Graphics/vtkRectilinearSynchronizedTemplates.h new file mode 100644 index 0000000..c0c6926 --- /dev/null +++ b/Graphics/vtkRectilinearSynchronizedTemplates.h @@ -0,0 +1,169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearSynchronizedTemplates.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearSynchronizedTemplates - generate isosurface from rectilinear grid + +// .SECTION Description +// vtkRectilinearSynchronizedTemplates is a 3D implementation (for rectilinear +// grids) of the synchronized template algorithm. Note that vtkContourFilter +// will automatically use this class when appropriate. + +// .SECTION Caveats +// This filter is specialized to rectilinear grids. + +// .SECTION See Also +// vtkContourFilter vtkSynchronizedTemplates2D vtkSynchronizedTemplates3D + +#ifndef __vtkRectilinearSynchronizedTemplates_h +#define __vtkRectilinearSynchronizedTemplates_h + +#include "vtkPolyDataAlgorithm.h" +#include "vtkContourValues.h" // Passes calls through + +class vtkRectilinearGrid; +class vtkKitwareContourFilter; +class vtkDataArray; + +class VTK_GRAPHICS_EXPORT vtkRectilinearSynchronizedTemplates : public vtkPolyDataAlgorithm +{ +public: + static vtkRectilinearSynchronizedTemplates *New(); + + vtkTypeRevisionMacro(vtkRectilinearSynchronizedTemplates,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Because we delegate to vtkContourValues + unsigned long int GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Set a particular contour value at contour number i. The index i ranges + // between 0<=iContourValues->SetValue(i,value);} + + // Description: + // Get the ith contour value. + double GetValue(int i) {return this->ContourValues->GetValue(i);} + + // Description: + // Get a pointer to an array of contour values. There will be + // GetNumberOfContours() values in the list. + double *GetValues() {return this->ContourValues->GetValues();} + + // Description: + // Fill a supplied list with contour values. There will be + // GetNumberOfContours() values in the list. Make sure you allocate + // enough memory to hold the list. + void GetValues(double *contourValues) { + this->ContourValues->GetValues(contourValues);} + + // Description: + // Set the number of contours to place into the list. You only really + // need to use this method to reduce list size. The method SetValue() + // will automatically increase list size as needed. + void SetNumberOfContours(int number) { + this->ContourValues->SetNumberOfContours(number);} + + // Description: + // Get the number of contours in the list of contour values. + int GetNumberOfContours() { + return this->ContourValues->GetNumberOfContours();} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double range[2]) { + this->ContourValues->GenerateValues(numContours, range);} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double rangeStart, double rangeEnd) + {this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + // Description: + // Needed by templated functions. + int *GetExecuteExtent() {return this->ExecuteExtent;} + + // Description: + // Set/get which component of the scalar array to contour on; defaults to 0. + vtkSetMacro(ArrayComponent, int); + vtkGetMacro(ArrayComponent, int); + + // Description: + // Compute the spacing between this point and its 6 neighbors. This method + // needs to be public so it can be accessed from a templated function. + void ComputeSpacing(vtkRectilinearGrid *data, int i, int j, int k, + int extent[6], double spacing[6]); + +protected: + vtkRectilinearSynchronizedTemplates(); + ~vtkRectilinearSynchronizedTemplates(); + + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkContourValues *ContourValues; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int ExecuteExtent[6]; + + int ArrayComponent; + + void* GetScalarsForExtent(vtkDataArray *array, int extent[6], + vtkRectilinearGrid *input); + +private: + vtkRectilinearSynchronizedTemplates(const vtkRectilinearSynchronizedTemplates&); // Not implemented. + void operator=(const vtkRectilinearSynchronizedTemplates&); // Not implemented. +}; + +// template table. +//BTX + +extern int VTK_RECTILINEAR_SYNCHONIZED_TEMPLATES_TABLE_1[]; +extern int VTK_RECTILINEAR_SYNCHONIZED_TEMPLATES_TABLE_2[]; + +//ETX + +#endif diff --git a/Graphics/vtkRecursiveDividingCubes.cxx b/Graphics/vtkRecursiveDividingCubes.cxx new file mode 100644 index 0000000..6bd06d0 --- /dev/null +++ b/Graphics/vtkRecursiveDividingCubes.cxx @@ -0,0 +1,352 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRecursiveDividingCubes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRecursiveDividingCubes.h" + +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkVoxel.h" + +vtkCxxRevisionMacro(vtkRecursiveDividingCubes, "$Revision: 1.42 $"); +vtkStandardNewMacro(vtkRecursiveDividingCubes); + +vtkRecursiveDividingCubes::vtkRecursiveDividingCubes() +{ + this->Value = 0.0; + this->Distance = 0.1; + this->Increment = 1; + this->Count = 0; + this->Voxel = vtkVoxel::New(); +} + +vtkRecursiveDividingCubes::~vtkRecursiveDividingCubes() +{ + this->Voxel->Delete(); +} + +static double X[3]; //origin of current voxel +static double Spacing[3]; //spacing of current voxel +static double Normals[8][3]; //voxel normals +static vtkPoints *NewPts; //points being generated +static vtkDoubleArray *NewNormals; //points being generated +static vtkCellArray *NewVerts; //verts being generated + +int vtkRecursiveDividingCubes::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int i, j, k; + vtkIdType idx; + vtkDataArray *inScalars; + vtkIdList *voxelPts; + double origin[3]; + int dim[3], jOffset, kOffset, sliceSize; + int above, below, vertNum; + vtkDoubleArray *voxelScalars; + + vtkDebugMacro(<< "Executing recursive dividing cubes..."); + // + // Initialize self; check input; create output objects + // + this->Count = 0; + + // make sure we have scalar data + if ( ! (inScalars = input->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"No scalar data to contour"); + return 1; + } + + // just deal with volumes + if ( input->GetDataDimension() != 3 ) + { + vtkErrorMacro("Bad input: only treats 3D structured point datasets"); + return 1; + } + input->GetDimensions(dim); + input->GetSpacing(Spacing); + input->GetOrigin(origin); + + // creating points + NewPts = vtkPoints::New(); + NewPts->Allocate(50000,100000); + NewNormals = vtkDoubleArray::New(); + NewNormals->SetNumberOfComponents(3); + NewNormals->Allocate(50000,100000); + NewVerts = vtkCellArray::New(); + NewVerts->Allocate(50000,100000); + NewVerts->InsertNextCell(0); //temporary cell count + + voxelPts = vtkIdList::New(); + voxelPts->Allocate(8); + voxelPts->SetNumberOfIds(8); + + voxelScalars = vtkDoubleArray::New(); + voxelScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + voxelScalars->Allocate(8*inScalars->GetNumberOfComponents()); + + // + // Loop over all cells checking to see which straddle the specified value. + // Since we know that we are working with a volume, can create + // appropriate data directly. + // + sliceSize = dim[0] * dim[1]; + for ( k=0; k < (dim[2]-1); k++) + { + kOffset = k*sliceSize; + X[2] = origin[2] + k*Spacing[2]; + + for ( j=0; j < (dim[1]-1); j++) + { + jOffset = j*dim[0]; + X[1] = origin[1] + j*Spacing[1]; + + for ( i=0; i < (dim[0]-1); i++) + { + idx = i + jOffset + kOffset; + X[0] = origin[0] + i*Spacing[0]; + + // get point ids of this voxel + voxelPts->SetId(0, idx); + voxelPts->SetId(1, idx + 1); + voxelPts->SetId(2, idx + dim[0]); + voxelPts->SetId(3, idx + dim[0] + 1); + voxelPts->SetId(4, idx + sliceSize); + voxelPts->SetId(5, idx + sliceSize + 1); + voxelPts->SetId(6, idx + sliceSize + dim[0]); + voxelPts->SetId(7, idx + sliceSize + dim[0] + 1); + + // get scalars of this voxel + inScalars->GetTuples(voxelPts,voxelScalars); + + // loop over 8 points of voxel to check if cell straddles value + for ( above=below=0, vertNum=0; vertNum < 8; vertNum++ ) + { + if ( voxelScalars->GetComponent(vertNum,0) >= this->Value ) + { + above = 1; + } + else if ( voxelScalars->GetComponent(vertNum,0) < this->Value ) + { + below = 1; + } + + if ( above && below ) // recursively generate points + { //compute voxel normals and subdivide + input->GetPointGradient(i,j,k, inScalars, Normals[0]); + input->GetPointGradient(i+1,j,k, inScalars, Normals[1]); + input->GetPointGradient(i,j+1,k, inScalars, Normals[2]); + input->GetPointGradient(i+1,j+1,k, inScalars, Normals[3]); + input->GetPointGradient(i,j,k+1, inScalars, Normals[4]); + input->GetPointGradient(i+1,j,k+1, inScalars, Normals[5]); + input->GetPointGradient(i,j+1,k+1, inScalars, Normals[6]); + input->GetPointGradient(i+1,j+1,k+1, inScalars, Normals[7]); + + this->SubDivide(X, Spacing, voxelScalars->GetPointer(0)); + } + } + } + } + } + + voxelPts->Delete(); + voxelScalars->Delete(); + NewVerts->UpdateCellCount(NewPts->GetNumberOfPoints()); + vtkDebugMacro(<< "Created " << NewPts->GetNumberOfPoints() << " points"); + // + // Update ourselves and release memory + // + output->SetPoints(NewPts); + NewPts->Delete(); + + output->SetVerts(NewVerts); + NewVerts->Delete(); + + output->GetPointData()->SetNormals(NewNormals); + NewNormals->Delete(); + + output->Squeeze(); + + return 1; +} + +static int ScalarInterp[8][8] = {{0,8,12,24,16,22,20,26}, + {8,1,24,13,22,17,26,21}, + {12,24,2,9,20,26,18,23}, + {24,13,9,3,26,21,23,19}, + {16,22,20,26,4,10,14,25}, + {22,17,26,21,10,5,25,15}, + {20,26,18,23,14,25,6,11}, + {26,21,23,19,25,15,11,7}}; + +#define VTK_POINTS_PER_POLY_VERTEX 10000 + +void vtkRecursiveDividingCubes::SubDivide(double origin[3], double h[3], + double values[8]) +{ + int i; + double hNew[3]; + + for (i=0; i<3; i++) + { + hNew[i] = h[i] / 2.0; + } + + // if subdivided far enough, create point and end termination + if ( h[0] < this->Distance && h[1] < this->Distance && h[2] < this->Distance ) + { + vtkIdType id; + double x[3], n[3]; + double p[3], w[8]; + + for (i=0; i <3; i++) + { + x[i] = origin[i] + hNew[i]; + } + + if ( ! (this->Count++ % this->Increment) ) //add a point + { + id = NewPts->InsertNextPoint(x); + NewVerts->InsertCellPoint(id); + for (i=0; i<3; i++) + { + p[i] = (x[i] - X[i]) / Spacing[i]; + } + this->Voxel->InterpolationFunctions(p,w); + for (n[0]=n[1]=n[2]=0.0, i=0; i<8; i++) + { + n[0] += Normals[i][0]*w[i]; + n[1] += Normals[i][1]*w[i]; + n[2] += Normals[i][2]*w[i]; + } + vtkMath::Normalize(n); + NewNormals->InsertTuple(id,n); + + if ( !(NewPts->GetNumberOfPoints() % VTK_POINTS_PER_POLY_VERTEX) ) + { + vtkDebugMacro(<<"point# "<GetNumberOfPoints()); + } + } + + return; + } + + // otherwise, create eight sub-voxels and recurse + else + { + int j, k, idx, above, below, ii; + double x[3]; + double newValues[8]; + double s[27], scalar; + + for (i=0; i<8; i++) + { + s[i] = values[i]; + } + + s[8] = (s[0] + s[1]) / 2.0; // edge verts + s[9] = (s[2] + s[3]) / 2.0; + s[10] = (s[4] + s[5]) / 2.0; + s[11] = (s[6] + s[7]) / 2.0; + s[12] = (s[0] + s[2]) / 2.0; + s[13] = (s[1] + s[3]) / 2.0; + s[14] = (s[4] + s[6]) / 2.0; + s[15] = (s[5] + s[7]) / 2.0; + s[16] = (s[0] + s[4]) / 2.0; + s[17] = (s[1] + s[5]) / 2.0; + s[18] = (s[2] + s[6]) / 2.0; + s[19] = (s[3] + s[7]) / 2.0; + + s[20] = (s[0] + s[2] + s[4] + s[6]) / 4.0; // face verts + s[21] = (s[1] + s[3] + s[5] + s[7]) / 4.0; + s[22] = (s[0] + s[1] + s[4] + s[5]) / 4.0; + s[23] = (s[2] + s[3] + s[6] + s[7]) / 4.0; + s[24] = (s[0] + s[1] + s[2] + s[3]) / 4.0; + s[25] = (s[4] + s[5] + s[6] + s[7]) / 4.0; + + s[26] = (s[0] + s[1] + s[2] + s[3] + s[4] + s[5] + s[6] + s[7]) / 8.0; //middle + + for (k=0; k < 2; k++) + { + x[2] = origin[2] + k*hNew[2]; + + for (j=0; j < 2; j++) + { + x[1] = origin[1] + j*hNew[1]; + + for (i=0; i < 2; i++) + { + idx = i + j*2 + k*4; + x[0] = origin[0] + i*hNew[0]; + + for (above=below=0,ii=0; ii<8; ii++) + { + scalar = s[ScalarInterp[idx][ii]]; + + if ( scalar >= this->Value ) + { + above = 1; + } + else if ( scalar < this->Value ) + { + below = 1; + } + + newValues[ii] = scalar; + } + + if ( above && below ) + { + this->SubDivide(x, hNew, newValues); + } + } + } + } + } +} + +int vtkRecursiveDividingCubes::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkRecursiveDividingCubes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Value: " << this->Value << "\n"; + os << indent << "Distance: " << this->Distance << "\n"; + os << indent << "Increment: " << this->Increment << "\n"; +} + + diff --git a/Graphics/vtkRecursiveDividingCubes.h b/Graphics/vtkRecursiveDividingCubes.h new file mode 100644 index 0000000..4bc0efd --- /dev/null +++ b/Graphics/vtkRecursiveDividingCubes.h @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRecursiveDividingCubes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRecursiveDividingCubes - create points lying on isosurface (using recursive approach) +// .SECTION Description +// vtkRecursiveDividingCubes is a filter that generates points lying on a +// surface of constant scalar value (i.e., an isosurface). Dense point +// clouds (i.e., at screen resolution) will appear as a surface. Less dense +// clouds can be used as a source to generate streamlines or to generate +// "transparent" surfaces. +// +// This implementation differs from vtkDividingCubes in that it uses a +// recursive procedure. In many cases this can result in generating +// more points than the procedural implementation of vtkDividingCubes. This is +// because the recursive procedure divides voxels by multiples of powers of +// two. This can over-constrain subdivision. One of the advantages of the +// recursive technique is that the recursion is terminated earlier, which in +// some cases can be more efficient. + +// .SECTION See Also +// vtkDividingCubes vtkContourFilter vtkMarchingCubes + +#ifndef __vtkRecursiveDividingCubes_h +#define __vtkRecursiveDividingCubes_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkVoxel; + +class VTK_GRAPHICS_EXPORT vtkRecursiveDividingCubes : public vtkPolyDataAlgorithm +{ +public: + static vtkRecursiveDividingCubes *New(); + vtkTypeRevisionMacro(vtkRecursiveDividingCubes,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set isosurface value. + vtkSetMacro(Value,double); + vtkGetMacro(Value,double); + + // Description: + // Specify sub-voxel size at which to generate point. + vtkSetClampMacro(Distance,double,1.0e-06,VTK_DOUBLE_MAX); + vtkGetMacro(Distance,double); + + // Description: + // Every "Increment" point is added to the list of points. This parameter, if + // set to a large value, can be used to limit the number of points while + // retaining good accuracy. + vtkSetClampMacro(Increment,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(Increment,int); + +protected: + vtkRecursiveDividingCubes(); + ~vtkRecursiveDividingCubes(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + void SubDivide(double origin[3], double h[3], double values[8]); + + double Value; + double Distance; + int Increment; + + // working variable + int Count; + + // to replace a static + vtkVoxel *Voxel; +private: + vtkRecursiveDividingCubes(const vtkRecursiveDividingCubes&); // Not implemented. + void operator=(const vtkRecursiveDividingCubes&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkReflectionFilter.cxx b/Graphics/vtkReflectionFilter.cxx new file mode 100644 index 0000000..72a7df4 --- /dev/null +++ b/Graphics/vtkReflectionFilter.cxx @@ -0,0 +1,283 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkReflectionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkReflectionFilter.h" + +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkReflectionFilter, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkReflectionFilter); + +//--------------------------------------------------------------------------- +vtkReflectionFilter::vtkReflectionFilter() +{ + this->Plane = USE_X_MIN; + this->Center = 0.0; + this->CopyInput = 1; +} + +//--------------------------------------------------------------------------- +vtkReflectionFilter::~vtkReflectionFilter() +{ +} + +//--------------------------------------------------------------------------- +void vtkReflectionFilter::FlipVector(double tuple[3], int mirrorDir[3]) +{ + for(int j=0; j<3; j++) + { + tuple[j] *= mirrorDir[j]; + } +} + +//--------------------------------------------------------------------------- +int vtkReflectionFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType i; + vtkPointData *inPD = input->GetPointData(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *inCD = input->GetCellData(); + vtkCellData *outCD = output->GetCellData(); + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + double bounds[6]; + double tuple[3]; + vtkPoints *outPoints; + double point[3]; + double constant[3] = {0.0, 0.0, 0.0}; + int mirrorDir[3] = { 1, 1, 1}; + int ptId, cellId, j; + vtkGenericCell *cell = vtkGenericCell::New(); + vtkIdList *ptIds = vtkIdList::New(); + + input->GetBounds(bounds); + outPoints = vtkPoints::New(); + + if (this->CopyInput) + { + outPoints->Allocate(2* numPts); + output->Allocate(numCells * 2); + } + else + { + outPoints->Allocate(numPts); + output->Allocate(numCells); + } + outPD->CopyAllocate(inPD); + outCD->CopyAllocate(inCD); + + vtkDataArray *inPtVectors, *outPtVectors, *inPtNormals, *outPtNormals; + vtkDataArray *inCellVectors, *outCellVectors, *inCellNormals; + vtkDataArray *outCellNormals; + + inPtVectors = inPD->GetVectors(); + outPtVectors = outPD->GetVectors(); + inPtNormals = inPD->GetNormals(); + outPtNormals = outPD->GetNormals(); + inCellVectors = inCD->GetVectors(); + outCellVectors = outCD->GetVectors(); + inCellNormals = inCD->GetNormals(); + outCellNormals = outCD->GetNormals(); + + // Copy first points. + if (this->CopyInput) + { + for (i = 0; i < numPts; i++) + { + input->GetPoint(i, point); + ptId = outPoints->InsertNextPoint(point); + outPD->CopyData(inPD, i, ptId); + } + } + + // Copy reflected points. + switch (this->Plane) + { + case USE_X_MIN: + constant[0] = 2*bounds[0]; + mirrorDir[0] = -1; + break; + case USE_X_MAX: + constant[0] = 2*bounds[1]; + mirrorDir[0] = -1; + break; + case USE_X: + constant[0] = this->Center; + mirrorDir[0] = -1; + break; + case USE_Y_MIN: + constant[1] = 2*bounds[2]; + mirrorDir[1] = -1; + break; + case USE_Y_MAX: + constant[1] = 2*bounds[3]; + mirrorDir[1] = -1; + break; + case USE_Y: + constant[1] = this->Center; + mirrorDir[1] = -1; + break; + case USE_Z_MIN: + constant[2] = 2*bounds[4]; + mirrorDir[2] = -1; + break; + case USE_Z_MAX: + constant[2] = 2*bounds[5]; + mirrorDir[2] = -1; + break; + case USE_Z: + constant[2] = this->Center; + mirrorDir[2] = -1; + break; + } + + for (i = 0; i < numPts; i++) + { + input->GetPoint(i, point); + ptId = + outPoints->InsertNextPoint( mirrorDir[0]*point[0] + constant[0], + mirrorDir[1]*point[1] + constant[1], + mirrorDir[2]*point[2] + constant[2] ); + outPD->CopyData(inPD, i, ptId); + if (inPtVectors) + { + inPtVectors->GetTuple(i, tuple); + this->FlipVector(tuple, mirrorDir); + outPtVectors->SetTuple(ptId, tuple); + } + if (inPtNormals) + { + inPtNormals->GetTuple(i, tuple); + this->FlipVector(tuple, mirrorDir); + outPtNormals->SetTuple(ptId, tuple); + } + } + + + int numCellPts, cellType; + vtkIdType *newCellPts; + vtkIdList *cellPts; + + // Copy original cells. + if (this->CopyInput) + { + for (i = 0; i < numCells; i++) + { + input->GetCellPoints(i, ptIds); + output->InsertNextCell(input->GetCellType(i), ptIds); + outCD->CopyData(inCD, i, i); + } + } + + // Generate reflected cells. + for (i = 0; i < numCells; i++) + { + input->GetCell(i, cell); + numCellPts = cell->GetNumberOfPoints(); + cellType = cell->GetCellType(); + cellPts = cell->GetPointIds(); + // Triangle strips with even number of triangles have + // to be handled specially. A degenerate triangle is + // introduce to flip all the triangles properly. + if (cellType == VTK_TRIANGLE_STRIP && numCellPts % 2 == 0) + { + numCellPts++; + newCellPts = new vtkIdType[numCellPts]; + newCellPts[0] = cellPts->GetId(0); + newCellPts[1] = cellPts->GetId(2); + newCellPts[2] = cellPts->GetId(1); + newCellPts[3] = cellPts->GetId(2); + for (j = 4; j < numCellPts; j++) + { + newCellPts[j] = cellPts->GetId(j-1); + if (this->CopyInput) + { + newCellPts[j] += numPts; + } + } + } + else + { + newCellPts = new vtkIdType[numCellPts]; + for (j = numCellPts-1; j >= 0; j--) + { + newCellPts[numCellPts-1-j] = cellPts->GetId(j); + if (this->CopyInput) + { + newCellPts[numCellPts-1-j] += numPts; + } + } + } + cellId = output->InsertNextCell(cellType, numCellPts, newCellPts); + delete [] newCellPts; + outCD->CopyData(inCD, i, cellId); + if (inCellVectors) + { + inCellVectors->GetTuple(i, tuple); + this->FlipVector(tuple, mirrorDir); + outCellVectors->SetTuple(cellId, tuple); + } + if (inCellNormals) + { + inCellNormals->GetTuple(i, tuple); + this->FlipVector(tuple, mirrorDir); + outCellNormals->SetTuple(cellId, tuple); + } + } + + cell->Delete(); + ptIds->Delete(); + output->SetPoints(outPoints); + outPoints->Delete(); + output->CheckAttributes(); + + return 1; +} + +//--------------------------------------------------------------------------- +int vtkReflectionFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//--------------------------------------------------------------------------- +void vtkReflectionFilter::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Plane: " << this->Plane << endl; + os << indent << "Center: " << this->Center << endl; + os << indent << "CopyInput: " << this->CopyInput << endl; +} diff --git a/Graphics/vtkReflectionFilter.h b/Graphics/vtkReflectionFilter.h new file mode 100644 index 0000000..f8105b7 --- /dev/null +++ b/Graphics/vtkReflectionFilter.h @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkReflectionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkReflectionFilter - reflects a data set across a plane +// .SECTION Description +// The vtkReflectionFilter reflects a data set across one of the +// planes formed by the data set's bounding box. +// Since it converts data sets into unstructured grids, it is not effeicient +// for structured data sets. + +#ifndef __vtkReflectionFilter_h +#define __vtkReflectionFilter_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkReflectionFilter : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkReflectionFilter *New(); + + vtkTypeRevisionMacro(vtkReflectionFilter, vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream &os, vtkIndent indent); + +//BTX + enum ReflectionPlane + { + USE_X_MIN = 0, + USE_Y_MIN = 1, + USE_Z_MIN = 2, + USE_X_MAX = 3, + USE_Y_MAX = 4, + USE_Z_MAX = 5, + USE_X = 6, + USE_Y = 7, + USE_Z = 8 + }; +//ETX + + // Description: + // Set the normal of the plane to use as mirror. + vtkSetClampMacro(Plane, int, 0, 8); + vtkGetMacro(Plane, int); + void SetPlaneToX() { this->SetPlane(USE_X); }; + void SetPlaneToY() { this->SetPlane(USE_Y); }; + void SetPlaneToZ() { this->SetPlane(USE_Z); }; + void SetPlaneToXMin() { this->SetPlane(USE_X_MIN); }; + void SetPlaneToYMin() { this->SetPlane(USE_Y_MIN); }; + void SetPlaneToZMin() { this->SetPlane(USE_Z_MIN); }; + void SetPlaneToXMax() { this->SetPlane(USE_X_MAX); }; + void SetPlaneToYMax() { this->SetPlane(USE_Y_MAX); }; + void SetPlaneToZMax() { this->SetPlane(USE_Z_MAX); }; + + // Description: + // If the reflection plane is set to X, Y or Z, this variable + // is use to set the position of the plane. + vtkSetMacro(Center, double); + vtkGetMacro(Center, double); + + // Description: + // If on (the default), copy the input geometry to the output. If off, + // the output will only contain the reflection. + vtkSetMacro(CopyInput, int); + vtkGetMacro(CopyInput, int); + vtkBooleanMacro(CopyInput, int); + +protected: + vtkReflectionFilter(); + ~vtkReflectionFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int Plane; + double Center; + int CopyInput; + + void FlipVector(double tuple[3], int mirrorDir[3]); + +private: + vtkReflectionFilter(const vtkReflectionFilter&); // Not implemented + void operator=(const vtkReflectionFilter&); // Not implemented +}; + +#endif + + diff --git a/Graphics/vtkRegularPolygonSource.cxx b/Graphics/vtkRegularPolygonSource.cxx new file mode 100644 index 0000000..5d5d4e7 --- /dev/null +++ b/Graphics/vtkRegularPolygonSource.cxx @@ -0,0 +1,194 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRegularPolygonSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRegularPolygonSource.h" + +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkRegularPolygonSource, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkRegularPolygonSource); + +vtkRegularPolygonSource::vtkRegularPolygonSource() +{ + this->NumberOfSides = 6; + this->Center[0] = 0.0; this->Center[1] = 0.0; this->Center[2] = 0.0; + this->Normal[0] = 0.0; this->Normal[1] = 0.0; this->Normal[2] = 1.0; + this->Radius = 0.5; + this->GeneratePolygon = 1; + this->GeneratePolyline = 1; + + this->SetNumberOfInputPorts(0); +} + +int vtkRegularPolygonSource::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),-1); + + return 1; +} + +int vtkRegularPolygonSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // Get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // Get the output + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // We only produce one piece + if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) + { + return 1; + } + + double x[3], r[3]; + int i, j, numPts=this->NumberOfSides; + vtkPoints *newPoints; + vtkCellArray *newPoly; + vtkCellArray *newLine; + + // Prepare to produce the output; create the connectivity array(s) + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + + if ( this->GeneratePolyline ) + { + newLine = vtkCellArray::New(); + newLine->Allocate(newLine->EstimateSize(1,numPts)); + newLine->InsertNextCell(numPts+1); + for (i=0; iInsertCellPoint(i); + } + newLine->InsertCellPoint(0); //close the polyline + output->SetLines(newLine); + newLine->Delete(); + } + + if ( this->GeneratePolygon ) + { + newPoly = vtkCellArray::New(); + newPoly->Allocate(newPoly->EstimateSize(1,numPts)); + newPoly->InsertNextCell(numPts); + for (i=0; iInsertCellPoint(i); + } + output->SetPolys(newPoly); + newPoly->Delete(); + } + + // Produce a unit vector in the plane of the polygon (i.e., perpendicular + // to the normal) + double n[3], axis[3], px[3], py[3]; + + // Make sure the polygon normal is a unit vector + n[0] = this->Normal[0]; + n[1] = this->Normal[1]; + n[2] = this->Normal[2]; + if ( vtkMath::Normalize(n) == 0.0 ) + { + n[0] = 0.0; + n[1] = 0.0; + n[2] = 1.0; + } + + // Cross with unit axis vectors and eventually find vector in the polygon plane + int foundPlaneVector = 0; + axis[0] = 1.0; + axis[1] = 0.0; + axis[2] = 0.0; + vtkMath::Cross(n,axis,px); + if ( vtkMath::Normalize(px) > 1.0E-3 ) + { + foundPlaneVector = 1; + } + if ( ! foundPlaneVector ) + { + axis[0] = 0.0; + axis[1] = 1.0; + axis[2] = 0.0; + vtkMath::Cross(n,axis,px); + if ( vtkMath::Normalize(px) > 1.0E-3 ) + { + foundPlaneVector = 1; + } + } + if ( ! foundPlaneVector ) + { + axis[0] = 0.0; + axis[1] = 0.0; + axis[2] = 1.0; + vtkMath::Cross(n,axis,px); + vtkMath::Normalize(px); + } + vtkMath::Cross(px,n,py); //created two orthogonal axes in the polygon plane, px & py + + // Now run around normal vector to produce polygon points. + double theta = 2.0 * vtkMath::DoublePi() / numPts; + for (j=0; jCenter[i] + this->Radius * r[i]; + } + newPoints->InsertNextPoint(x); + } + + output->SetPoints(newPoints); + newPoints->Delete(); + + return 1; +} + +void vtkRegularPolygonSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of Sides: " << this->NumberOfSides << "\n"; + + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << ")\n"; + + os << indent << "Normal: (" << this->Normal[0] << ", " + << this->Normal[1] << ", " + << this->Normal[2] << ")\n"; + + os << indent << "Radius: " << this->Radius << "\n"; + + os << indent << "Generate Polygon: " << (this->GeneratePolygon ? "On\n" : "Off\n"); + + os << indent << "Generate Polyline: " << (this->GeneratePolyline ? "On\n" : "Off\n"); + +} diff --git a/Graphics/vtkRegularPolygonSource.h b/Graphics/vtkRegularPolygonSource.h new file mode 100644 index 0000000..d227a1b --- /dev/null +++ b/Graphics/vtkRegularPolygonSource.h @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRegularPolygonSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRegularPolygonSource - create a regular, n-sided polygon and/or polyline +// .SECTION Description +// vtkRegularPolygonSource is a source object that creates a single n-sided polygon and/or +// polyline. The polygon is centered at a specified point, orthogonal to +// a specified normal, and with a circumscribing radius set by the user. The user can +// also specify the number of sides of the polygon ranging from [3,N]. +// +// This object can be used for seeding streamlines or defining regions for clipping/cutting. + +#ifndef __vtkRegularPolygonSource_h +#define __vtkRegularPolygonSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkRegularPolygonSource : public vtkPolyDataAlgorithm +{ +public: + // Description: + // Standard methods for instantiation, obtaining type and printing instance values. + static vtkRegularPolygonSource *New(); + vtkTypeRevisionMacro(vtkRegularPolygonSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the number of sides of the polygon. By default, the number of sides + // is set to six. + vtkSetClampMacro(NumberOfSides,int,3,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfSides,int); + + // Description: + // Set/Get the center of the polygon. By default, the center is set at the + // origin (0,0,0). + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set/Get the normal to the polygon. The ordering of the polygon will be + // counter-clockwise around the normal (i.e., using the right-hand rule). + // By default, the normal is set to (0,0,1). + vtkSetVector3Macro(Normal,double); + vtkGetVectorMacro(Normal,double,3); + + // Description: + // Set/Get the radius of the polygon. By default, the radius is set to 0.5. + vtkSetMacro(Radius,double); + vtkGetMacro(Radius,double); + + // Description: + // Control whether a polygon is produced. By default, GeneratePolygon is enabled. + vtkSetMacro(GeneratePolygon,int); + vtkGetMacro(GeneratePolygon,int); + vtkBooleanMacro(GeneratePolygon,int); + + // Description: + // Control whether a polyline is produced. By default, GeneratePolyline is enabled. + vtkSetMacro(GeneratePolyline,int); + vtkGetMacro(GeneratePolyline,int); + vtkBooleanMacro(GeneratePolyline,int); + +protected: + vtkRegularPolygonSource(); + ~vtkRegularPolygonSource() {} + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int NumberOfSides; + double Center[3]; + double Normal[3]; + double Radius; + int GeneratePolygon; + int GeneratePolyline; + +private: + vtkRegularPolygonSource(const vtkRegularPolygonSource&); // Not implemented. + void operator=(const vtkRegularPolygonSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkReverseSense.cxx b/Graphics/vtkReverseSense.cxx new file mode 100644 index 0000000..3de0136 --- /dev/null +++ b/Graphics/vtkReverseSense.cxx @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkReverseSense.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkReverseSense.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkReverseSense, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkReverseSense); + +// Construct object so that behavior is to reverse cell ordering and +// leave normal orientation as is. +vtkReverseSense::vtkReverseSense() +{ + this->ReverseCells = 1; + this->ReverseNormals = 0; +} + +int vtkReverseSense::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *normals=input->GetPointData()->GetNormals(); + vtkDataArray *cellNormals=input->GetCellData()->GetNormals(); + + vtkDebugMacro(<<"Reversing sense of poly data"); + + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + //If specified, traverse all cells and reverse them + int abort=0; + vtkIdType progressInterval; + + if ( this->ReverseCells ) + { + vtkIdType numCells=input->GetNumberOfCells(); + vtkCellArray *verts, *lines, *polys, *strips; + + //Instantiate necessary topology arrays + verts = vtkCellArray::New(); + verts->DeepCopy(input->GetVerts()); + lines = vtkCellArray::New(); + lines->DeepCopy(input->GetLines()); + polys = vtkCellArray::New(); + polys->DeepCopy(input->GetPolys()); + strips = vtkCellArray::New(); + strips->DeepCopy(input->GetStrips()); + + output->SetVerts(verts); verts->Delete(); + output->SetLines(lines); lines->Delete(); + output->SetPolys(polys); polys->Delete(); + output->SetStrips(strips); strips->Delete(); + + progressInterval=numCells/10+1; + for (vtkIdType cellId=0; cellId < numCells && !abort; cellId++ ) + { + if ( ! (cellId % progressInterval) ) //manage progress / early abort + { + this->UpdateProgress (0.6*cellId/numCells); + abort = this->GetAbortExecute(); + } + output->ReverseCell(cellId); + } + } + + //If specified and normals available, reverse orientation of normals. + // Using NewInstance() creates normals of the same data type. + if ( this->ReverseNormals && normals ) + { + //first do point normals + vtkIdType numPoints=input->GetNumberOfPoints(); + vtkDataArray *outNormals=normals->NewInstance(); + outNormals->SetNumberOfComponents(normals->GetNumberOfComponents()); + outNormals->SetNumberOfTuples(numPoints); + double n[3]; + + progressInterval=numPoints/5+1; + for ( int ptId=0; ptId < numPoints; ptId++ ) + { + if ( ! (ptId % progressInterval) ) //manage progress / early abort + { + this->UpdateProgress (0.6 + 0.2*ptId/numPoints); + abort = this->GetAbortExecute(); + } + normals->GetTuple(ptId,n); + n[0] = -n[0]; n[1] = -n[1]; n[2] = -n[2]; + outNormals->SetTuple(ptId,n); + } + + output->GetPointData()->SetNormals(outNormals); + outNormals->Delete(); + } + + //now do cell normals + if ( this->ReverseNormals && cellNormals ) + { + vtkIdType numCells=input->GetNumberOfCells(); + vtkDataArray *outNormals=cellNormals->NewInstance(); + outNormals->SetNumberOfComponents(cellNormals->GetNumberOfComponents()); + outNormals->SetNumberOfTuples(numCells); + double n[3]; + + progressInterval=numCells/5+1; + for (vtkIdType cellId=0; cellId < numCells && !abort; cellId++ ) + { + if ( ! (cellId % progressInterval) ) //manage progress / early abort + { + this->UpdateProgress (0.8 + 0.2*cellId/numCells); + abort = this->GetAbortExecute(); + } + + cellNormals->GetTuple(cellId,n); + n[0] = -n[0]; n[1] = -n[1]; n[2] = -n[2]; + outNormals->SetTuple(cellId,n); + } + + output->GetCellData()->SetNormals(outNormals); + outNormals->Delete(); + } + + return 1; +} + + +void vtkReverseSense::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Reverse Cells: " + << (this->ReverseCells ? "On\n" : "Off\n"); + os << indent << "Reverse Normals: " + << (this->ReverseNormals ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkReverseSense.h b/Graphics/vtkReverseSense.h new file mode 100644 index 0000000..94d8939 --- /dev/null +++ b/Graphics/vtkReverseSense.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkReverseSense.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkReverseSense - reverse the ordering of polygonal cells and/or vertex normals +// .SECTION Description +// +// vtkReverseSense is a filter that reverses the order of polygonal cells +// and/or reverses the direction of point and cell normals. Two flags are +// used to control these operations. Cell reversal means reversing the order +// of indices in the cell connectivity list. Normal reversal means +// multiplying the normal vector by -1 (both point and cell normals, +// if present). + +// .SECTION Caveats +// Normals can be operated on only if they are present in the data. + +#ifndef __vtkReverseSense_h +#define __vtkReverseSense_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkReverseSense : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkReverseSense,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object so that behavior is to reverse cell ordering and + // leave normal orientation as is. + static vtkReverseSense *New(); + + // Description: + // Flag controls whether to reverse cell ordering. + vtkSetMacro(ReverseCells,int); + vtkGetMacro(ReverseCells,int); + vtkBooleanMacro(ReverseCells,int); + + // Description: + // Flag controls whether to reverse normal orientation. + vtkSetMacro(ReverseNormals,int); + vtkGetMacro(ReverseNormals,int); + vtkBooleanMacro(ReverseNormals,int); + + +protected: + vtkReverseSense(); + ~vtkReverseSense() {}; + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int ReverseCells; + int ReverseNormals; +private: + vtkReverseSense(const vtkReverseSense&); // Not implemented. + void operator=(const vtkReverseSense&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkRibbonFilter.cxx b/Graphics/vtkRibbonFilter.cxx new file mode 100644 index 0000000..5007b96 --- /dev/null +++ b/Graphics/vtkRibbonFilter.cxx @@ -0,0 +1,540 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRibbonFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRibbonFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyLine.h" + +vtkCxxRevisionMacro(vtkRibbonFilter, "$Revision: 1.80 $"); +vtkStandardNewMacro(vtkRibbonFilter); + +// Construct ribbon so that width is 0.1, the width does +// not vary with scalar values, and the width factor is 2.0. +vtkRibbonFilter::vtkRibbonFilter() +{ + this->Width = 0.5; + this->Angle = 0.0; + this->VaryWidth = 0; + this->WidthFactor = 2.0; + + this->DefaultNormal[0] = this->DefaultNormal[1] = 0.0; + this->DefaultNormal[2] = 1.0; + + this->UseDefaultNormal = 0; + + this->GenerateTCoords = 0; + this->TextureLength = 1.0; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); + + // by default process active point vectors + this->SetInputArrayToProcess(1,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::NORMALS); +} + +vtkRibbonFilter::~vtkRibbonFilter() +{ +} + + +int vtkRibbonFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(); + vtkPointData *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(); + vtkCellData *outCD=output->GetCellData(); + vtkCellArray *inLines; + vtkDataArray *inNormals; + vtkDataArray *inScalars = this->GetInputArrayToProcess(0,inputVector); + + vtkPoints *inPts; + vtkIdType numPts; + vtkIdType numLines; + vtkIdType numNewPts, numNewCells; + vtkPoints *newPts; + int deleteNormals=0; + vtkFloatArray *newNormals; + vtkIdType i; + double range[2]; + vtkCellArray *newStrips; + vtkIdType npts=0, *pts=NULL; + vtkIdType offset=0; + vtkFloatArray *newTCoords=NULL; + int abort=0; + vtkIdType inCellId; + + // Check input and initialize + // + vtkDebugMacro(<<"Creating ribbon"); + + if ( !(inPts=input->GetPoints()) || + (numPts = inPts->GetNumberOfPoints()) < 1 || + !(inLines = input->GetLines()) || + (numLines = inLines->GetNumberOfCells()) < 1 ) + { + return 1; + } + + // Create the geometry and topology + numNewPts = 2 * numPts; + newPts = vtkPoints::New(); + newPts->Allocate(numNewPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numNewPts); + newStrips = vtkCellArray::New(); + newStrips->Allocate(newStrips->EstimateSize(1,numNewPts)); + vtkCellArray *singlePolyline = vtkCellArray::New(); + + // Point data: copy scalars, vectors, tcoords. Normals may be computed here. + outPD->CopyNormalsOff(); + if ( (this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS && inScalars) || + this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH || + this->GenerateTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH ) + { + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(numNewPts); + outPD->CopyTCoordsOff(); + } + outPD->CopyAllocate(pd,numNewPts); + + int generateNormals = 0; + inNormals = this->GetInputArrayToProcess(1,inputVector); + if ( !inNormals || this->UseDefaultNormal ) + { + deleteNormals = 1; + inNormals = vtkFloatArray::New(); + inNormals->SetNumberOfComponents(3); + inNormals->SetNumberOfTuples(numPts); + + if ( this->UseDefaultNormal ) + { + for ( i=0; i < numPts; i++) + { + inNormals->SetTuple(i,this->DefaultNormal); + } + } + else + { + // Normal generation has been moved to lower in the function. + // This allows each different polylines to share vertices, but have + // their normals (and hence their ribbons) calculated independently + generateNormals = 1; + } + } + + // If varying width, get appropriate info. + // + if ( this->VaryWidth && inScalars ) + { + inScalars->GetRange(range,0); + if ((range[1] - range[0]) == 0.0) + { + vtkWarningMacro(<< "Scalar range is zero!"); + range[1] = range[0] + 1.0; + } + } + + // Copy selected parts of cell data; certainly don't want normals + // + numNewCells = inLines->GetNumberOfCells(); + outCD->CopyNormalsOff(); + outPD->CopyAllocate(pd,numNewCells); + + // Create points along each polyline that are connected into NumberOfSides + // triangle strips. Texture coordinates are optionally generated. + // + this->Theta = this->Angle * vtkMath::DegreesToRadians(); + vtkPolyLine *lineNormalGenerator = vtkPolyLine::New(); + for (inCellId=0, inLines->InitTraversal(); + inLines->GetNextCell(npts,pts) && !abort; inCellId++) + { + this->UpdateProgress((double)inCellId/numLines); + abort = this->GetAbortExecute(); + + if (npts < 2) + { + vtkWarningMacro(<< "Less than two points in line!"); + continue; //skip tubing this polyline + } + + // If necessary calculate normals, each polyline calculates its + // normals independently, avoiding conflicts at shared vertices. + if (generateNormals) + { + singlePolyline->Reset(); //avoid instantiation + singlePolyline->InsertNextCell(npts,pts); + if ( !lineNormalGenerator->GenerateSlidingNormals(inPts,singlePolyline, + inNormals) ) + { + vtkWarningMacro(<< "No normals for line!"); + continue; //skip tubing this polyline + } + } + + // Generate the points around the polyline. The strip is not created + // if the polyline is bad. + // + if ( !this->GeneratePoints(offset,npts,pts,inPts,newPts,pd,outPD, + newNormals,inScalars,range,inNormals) ) + { + vtkWarningMacro(<< "Could not generate points!"); + continue; //skip ribboning this polyline + } + + // Generate the strip for this polyline + // + this->GenerateStrip(offset,npts,pts,inCellId,cd,outCD,newStrips); + + // Generate the texture coordinates for this polyline + // + if ( newTCoords ) + { + this->GenerateTextureCoords(offset,npts,pts,inPts,inScalars,newTCoords); + } + + // Compute the new offset for the next polyline + offset = this->ComputeOffset(offset,npts); + + }//for all polylines + + singlePolyline->Delete(); + + // Update ourselves + // + if ( deleteNormals ) + { + inNormals->Delete(); + } + + if ( newTCoords ) + { + outPD->SetTCoords(newTCoords); + newTCoords->Delete(); + } + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetStrips(newStrips); + newStrips->Delete(); + + outPD->SetNormals(newNormals); + newNormals->Delete(); + lineNormalGenerator->Delete(); + + output->Squeeze(); + + return 1; +} + +int vtkRibbonFilter::GeneratePoints(vtkIdType offset, + vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, vtkPoints *newPts, + vtkPointData *pd, vtkPointData *outPD, + vtkFloatArray *newNormals, + vtkDataArray *inScalars, double range[2], + vtkDataArray *inNormals) +{ + vtkIdType j; + int i; + double p[3]; + double pNext[3]; + double sNext[3]; + double sPrev[3]; + double n[3]; + double s[3], sp[3], sm[3], v[3]; + //double bevelAngle; + double w[3]; + double nP[3]; + double sFactor=1.0; + vtkIdType ptId=offset; + + // Use "averaged" segment to create beveled effect. + // Watch out for first and last points. + // + for (j=0; j < npts; j++) + { + if ( j == 0 ) //first point + { + inPts->GetPoint(pts[0],p); + inPts->GetPoint(pts[1],pNext); + for (i=0; i<3; i++) + { + sNext[i] = pNext[i] - p[i]; + sPrev[i] = sNext[i]; + } + } + else if ( j == (npts-1) ) //last point + { + for (i=0; i<3; i++) + { + sPrev[i] = sNext[i]; + p[i] = pNext[i]; + } + } + else + { + for (i=0; i<3; i++) + { + p[i] = pNext[i]; + } + inPts->GetPoint(pts[j+1],pNext); + for (i=0; i<3; i++) + { + sPrev[i] = sNext[i]; + sNext[i] = pNext[i] - p[i]; + } + } + + inNormals->GetTuple(pts[j], n); + + if ( vtkMath::Normalize(sNext) == 0.0 ) + { + vtkWarningMacro(<<"Coincident points!"); + return 0; + } + + for (i=0; i<3; i++) + { + s[i] = (sPrev[i] + sNext[i]) / 2.0; //average vector + } + // if s is zero then just use sPrev cross n + if (vtkMath::Normalize(s) == 0.0) + { + vtkWarningMacro(<< "Using alternate bevel vector"); + vtkMath::Cross(sPrev,n,s); + if (vtkMath::Normalize(s) == 0.0) + { + vtkWarningMacro(<< "Using alternate bevel vector"); + } + } +/* + if ( (bevelAngle = vtkMath::Dot(sNext,sPrev)) > 1.0 ) + { + bevelAngle = 1.0; + } + if ( bevelAngle < -1.0 ) + { + bevelAngle = -1.0; + } + bevelAngle = acos((double)bevelAngle) / 2.0; //(0->90 degrees) + if ( (bevelAngle = cos(bevelAngle)) == 0.0 ) + { + bevelAngle = 1.0; + } + + bevelAngle = this->Width / bevelAngle; //keep ribbon constant width +*/ + vtkMath::Cross(s,n,w); + if ( vtkMath::Normalize(w) == 0.0) + { + vtkWarningMacro(<<"Bad normal s = " <VaryWidth ) // varying by scalar values + { + sFactor = 1.0 + ((this->WidthFactor - 1.0) * + (inScalars->GetComponent(pts[j],0) - range[0]) + / (range[1]-range[0])); + } + + for (i=0; i<3; i++) + { + v[i] = (w[i]*cos(this->Theta) + nP[i]*sin(this->Theta)); + sp[i] = p[i] + this->Width * sFactor * v[i]; + sm[i] = p[i] - this->Width * sFactor * v[i]; + } + newPts->InsertPoint(ptId,sm); + newNormals->InsertTuple(ptId,nP); + outPD->CopyData(pd,pts[j],ptId); + ptId++; + newPts->InsertPoint(ptId,sp); + newNormals->InsertTuple(ptId,nP); + outPD->CopyData(pd,pts[j],ptId); + ptId++; + }//for all points in polyline + + return 1; +} + +void vtkRibbonFilter::GenerateStrip(vtkIdType offset, vtkIdType npts, + vtkIdType* vtkNotUsed(pts), + vtkIdType inCellId, + vtkCellData *cd, vtkCellData *outCD, + vtkCellArray *newStrips) +{ + vtkIdType i, idx, outCellId; + + outCellId = newStrips->InsertNextCell(npts*2); + outCD->CopyData(cd,inCellId,outCellId); + for (i=0; i < npts; i++) + { + idx = 2*i; + newStrips->InsertCellPoint(offset+idx); + newStrips->InsertCellPoint(offset+idx+1); + } +} + +void vtkRibbonFilter::GenerateTextureCoords(vtkIdType offset, + vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, + vtkDataArray *inScalars, + vtkFloatArray *newTCoords) +{ + vtkIdType i; + int k; + double tc; + + double s0, s; + //The first texture coordinate is always 0. + for ( k=0; k < 2; k++) + { + newTCoords->InsertTuple2(offset+k,0.0,0.0); + } + if ( this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS && inScalars) + { + s0 = inScalars->GetTuple1(pts[0]); + for (i=1; i < npts; i++) + { + s = inScalars->GetTuple1(pts[i]); + tc = (s - s0) / this->TextureLength; + for ( k=0; k < 2; k++) + { + newTCoords->InsertTuple2(offset+i*2+k,tc,0.0); + } + } + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH ) + { + double xPrev[3], x[3], len=0.0; + inPts->GetPoint(pts[0],xPrev); + for (i=1; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + tc = len / this->TextureLength; + for ( k=0; k < 2; k++) + { + newTCoords->InsertTuple2(offset+i*2+k,tc,0.0); + } + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH ) + { + double xPrev[3], x[3], length=0.0, len=0.0; + inPts->GetPoint(pts[0],xPrev); + for (i=1; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + length += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + + inPts->GetPoint(pts[0],xPrev); + for (i=1; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + tc = len / length; + for ( k=0; k < 2; k++) + { + newTCoords->InsertTuple2(offset+i*2+k,tc,0.0); + } + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + } +} + +// Compute the number of points in this ribbon +vtkIdType vtkRibbonFilter::ComputeOffset(vtkIdType offset, vtkIdType npts) +{ + offset += 2 * npts; + return offset; +} + +// Description: +// Return the method of generating the texture coordinates. +const char *vtkRibbonFilter::GetGenerateTCoordsAsString(void) +{ + if ( this->GenerateTCoords == VTK_TCOORDS_OFF ) + { + return "GenerateTCoordsOff"; + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS ) + { + return "GenerateTCoordsFromScalar"; + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH ) + { + return "GenerateTCoordsFromLength"; + } + else + { + return "GenerateTCoordsFromNormalizedLength"; + } +} + +void vtkRibbonFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Width: " << this->Width << "\n"; + os << indent << "Angle: " << this->Angle << "\n"; + os << indent << "VaryWidth: " << (this->VaryWidth ? "On\n" : "Off\n"); + os << indent << "Width Factor: " << this->WidthFactor << "\n"; + os << indent << "Use Default Normal: " << this->UseDefaultNormal << "\n"; + os << indent << "Default Normal: " << "( " + << this->DefaultNormal[0] << ", " + << this->DefaultNormal[1] << ", " + << this->DefaultNormal[2] << " )\n"; + + os << indent << "Generate TCoords: " + << this->GetGenerateTCoordsAsString() << endl; + os << indent << "Texture Length: " << this->TextureLength << endl; +} + diff --git a/Graphics/vtkRibbonFilter.h b/Graphics/vtkRibbonFilter.h new file mode 100644 index 0000000..ff4d3d9 --- /dev/null +++ b/Graphics/vtkRibbonFilter.h @@ -0,0 +1,157 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRibbonFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRibbonFilter - create oriented ribbons from lines defined in polygonal dataset +// .SECTION Description +// vtkRibbonFilter is a filter to create oriented ribbons from lines defined +// in polygonal dataset. The orientation of the ribbon is along the line +// segments and perpendicular to "projected" line normals. Projected line +// normals are the original line normals projected to be perpendicular to +// the local line segment. An offset angle can be specified to rotate the +// ribbon with respect to the normal. +// +// .SECTION Caveats +// The input line must not have duplicate points, or normals at points that +// are parallel to the incoming/outgoing line segments. (Duplicate points +// can be removed with vtkCleanPolyData.) If a line does not meet this +// criteria, then that line is not tubed. + +// .SECTION See Also +// vtkTubeFilter + +#ifndef __vtkRibbonFilter_h +#define __vtkRibbonFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_TCOORDS_OFF 0 +#define VTK_TCOORDS_FROM_NORMALIZED_LENGTH 1 +#define VTK_TCOORDS_FROM_LENGTH 2 +#define VTK_TCOORDS_FROM_SCALARS 3 + +class vtkCellArray; +class vtkCellData; +class vtkDataArray; +class vtkFloatArray; +class vtkPointData; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkRibbonFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkRibbonFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct ribbon so that width is 0.1, the width does + // not vary with scalar values, and the width factor is 2.0. + static vtkRibbonFilter *New(); + + // Description: + // Set the "half" width of the ribbon. If the width is allowed to vary, + // this is the minimum width. + vtkSetClampMacro(Width,double,0,VTK_DOUBLE_MAX); + vtkGetMacro(Width,double); + + // Description: + // Set the offset angle of the ribbon from the line normal. (The angle + // is expressed in degrees.) + vtkSetClampMacro(Angle,double,0,360); + vtkGetMacro(Angle,double); + + // Description: + // Turn on/off the variation of ribbon width with scalar value. + vtkSetMacro(VaryWidth,int); + vtkGetMacro(VaryWidth,int); + vtkBooleanMacro(VaryWidth,int); + + // Description: + // Set the maximum ribbon width in terms of a multiple of the minimum width. + vtkSetMacro(WidthFactor,double); + vtkGetMacro(WidthFactor,double); + + // Description: + // Set the default normal to use if no normals are supplied, and the + // DefaultNormalOn is set. + vtkSetVector3Macro(DefaultNormal,double); + vtkGetVectorMacro(DefaultNormal,double,3); + + // Description: + // Set a boolean to control whether to use default normals. + // DefaultNormalOn is set. + vtkSetMacro(UseDefaultNormal,int); + vtkGetMacro(UseDefaultNormal,int); + vtkBooleanMacro(UseDefaultNormal,int); + + // Description: + // Control whether and how texture coordinates are produced. This is + // useful for striping the ribbon with time textures, etc. + vtkSetClampMacro(GenerateTCoords,int,VTK_TCOORDS_OFF, + VTK_TCOORDS_FROM_SCALARS); + vtkGetMacro(GenerateTCoords,int); + void SetGenerateTCoordsToOff() + {this->SetGenerateTCoords(VTK_TCOORDS_OFF);} + void SetGenerateTCoordsToNormalizedLength() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_NORMALIZED_LENGTH);} + void SetGenerateTCoordsToUseLength() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_LENGTH);} + void SetGenerateTCoordsToUseScalars() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_SCALARS);} + const char *GetGenerateTCoordsAsString(); + + // Description: + // Control the conversion of units during the texture coordinates + // calculation. The TextureLength indicates what length (whether + // calculated from scalars or length) is mapped to the [0,1) + // texture space. + vtkSetClampMacro(TextureLength,double,0.000001,VTK_LARGE_INTEGER); + vtkGetMacro(TextureLength,double); + +protected: + vtkRibbonFilter(); + ~vtkRibbonFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double Width; + double Angle; + int VaryWidth; //controls whether width varies with scalar data + double WidthFactor; + double DefaultNormal[3]; + int UseDefaultNormal; + int GenerateTCoords; //control texture coordinate generation + double TextureLength; //this length is mapped to [0,1) texture space + + // Helper methods + int GeneratePoints(vtkIdType offset, vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, vtkPoints *newPts, + vtkPointData *pd, vtkPointData *outPD, + vtkFloatArray *newNormals, vtkDataArray *inScalars, + double range[2], vtkDataArray *inNormals); + void GenerateStrip(vtkIdType offset, vtkIdType npts, vtkIdType *pts, + vtkIdType inCellId, vtkCellData *cd, vtkCellData *outCD, + vtkCellArray *newStrips); + void GenerateTextureCoords(vtkIdType offset, vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, vtkDataArray *inScalars, + vtkFloatArray *newTCoords); + vtkIdType ComputeOffset(vtkIdType offset,vtkIdType npts); + + // Helper data members + double Theta; + +private: + vtkRibbonFilter(const vtkRibbonFilter&); // Not implemented. + void operator=(const vtkRibbonFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkRotationFilter.cxx b/Graphics/vtkRotationFilter.cxx new file mode 100644 index 0000000..3f606e8 --- /dev/null +++ b/Graphics/vtkRotationFilter.cxx @@ -0,0 +1,259 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRotationFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRotationFilter.h" + +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" +#include "vtkMath.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkRotationFilter, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkRotationFilter); + +//--------------------------------------------------------------------------- +vtkRotationFilter::vtkRotationFilter() +{ + this->Axis = 2; + this->CopyInput = 0; + this->Center[0] = this->Center[1] = this->Center[2] = 0; + this->NumberOfCopies = 0; + this->Angle = 0; +} + +//--------------------------------------------------------------------------- +vtkRotationFilter::~vtkRotationFilter() +{ +} + +//--------------------------------------------------------------------------- +void vtkRotationFilter::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Axis: " << this->Axis << endl; + os << indent << "CopyInput: " << this->CopyInput << endl; + os << indent << "Center: (" << this->Center[0] << "," << this->Center[1] + << "," << this->Center[2] << ")" << endl; + os << indent << "NumberOfCopies: " << this->NumberOfCopies << endl; + os << indent << "Angle: " << this->Angle << endl; +} + +//--------------------------------------------------------------------------- +int vtkRotationFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType i; + vtkPointData *inPD = input->GetPointData(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *inCD = input->GetCellData(); + vtkCellData *outCD = output->GetCellData(); + + if (!this->GetNumberOfCopies()) + { + vtkErrorMacro("No number of copy set!"); + return 1; + } + + double tuple[3]; + vtkPoints *outPoints; + double point[3], center[3], negativCenter[3]; + int ptId, cellId, j, k; + vtkGenericCell *cell = vtkGenericCell::New(); + vtkIdList *ptIds = vtkIdList::New(); + + outPoints = vtkPoints::New(); + + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + + if (this->CopyInput) + { + outPoints->Allocate((this->CopyInput + this->GetNumberOfCopies()) * numPts); + output->Allocate((this->CopyInput + this->GetNumberOfCopies()) * numPts); + } + else + { + outPoints->Allocate( this->GetNumberOfCopies() * numPts); + output->Allocate( this->GetNumberOfCopies() * numPts); + } + + outPD->CopyAllocate(inPD); + outCD->CopyAllocate(inCD); + + vtkDataArray *inPtVectors, *outPtVectors, *inPtNormals; + vtkDataArray *inCellVectors, *outCellVectors, *inCellNormals; + + inPtVectors = inPD->GetVectors(); + outPtVectors = outPD->GetVectors(); + inPtNormals = inPD->GetNormals(); + inCellVectors = inCD->GetVectors(); + outCellVectors = outCD->GetVectors(); + inCellNormals = inCD->GetNormals(); + + // Copy first points. + if (this->CopyInput) + { + for (i = 0; i < numPts; i++) + { + input->GetPoint(i, point); + ptId = outPoints->InsertNextPoint(point); + outPD->CopyData(inPD, i, ptId); + } + } + vtkTransform *localTransform = vtkTransform::New(); + // Rotate points. + // double angle = this->GetAngle()*vtkMath::DegreesToRadians(); + this->GetCenter(center); + negativCenter[0] = -center[0]; + negativCenter[1] = -center[1]; + negativCenter[2] = -center[2]; + + for (k = 0; k < this->GetNumberOfCopies(); k++) + { + localTransform->Identity(); + localTransform->Translate(center); + switch (this->Axis) + { + case USE_X: + localTransform->RotateX((k+1)*this->GetAngle()); + break; + + case USE_Y: + localTransform->RotateY((k+1)*this->GetAngle()); + break; + + case USE_Z: + localTransform->RotateZ((k+1)*this->GetAngle()); + break; + } + localTransform->Translate(negativCenter); + for (i = 0; i < numPts; i++) + { + input->GetPoint(i, point); + localTransform->TransformPoint(point, point); + ptId = outPoints->InsertNextPoint(point); + outPD->CopyData(inPD, i, ptId); + if (inPtVectors) + { + inPtVectors->GetTuple(i, tuple); + outPtVectors->SetTuple(ptId, tuple); + } + if (inPtNormals) + { + //inPtNormals->GetTuple(i, tuple); + //outPtNormals->SetTuple(ptId, tuple); + } + } + } + + localTransform->Delete(); + + int numCellPts, cellType; + vtkIdType *newCellPts; + vtkIdList *cellPts; + + // Copy original cells. + if (this->CopyInput) + { + for (i = 0; i < numCells; i++) + { + input->GetCellPoints(i, ptIds); + output->InsertNextCell(input->GetCellType(i), ptIds); + outCD->CopyData(inCD, i, i); + } + } + + // Generate rotated cells. + for (k = 0; k < this->GetNumberOfCopies(); k++) + { + for (i = 0; i < numCells; i++) + { + input->GetCellPoints(i, ptIds); + input->GetCell(i, cell); + numCellPts = cell->GetNumberOfPoints(); + cellType = cell->GetCellType(); + cellPts = cell->GetPointIds(); + // Triangle strips with even number of triangles have + // to be handled specially. A degenerate triangle is + // introduce to flip all the triangles properly. + if (cellType == VTK_TRIANGLE_STRIP && numCellPts % 2 == 0) + { + vtkErrorMacro(<< "Triangles with bad points"); + return 0; + } + else + { + vtkDebugMacro(<< "celltype " << cellType << " numCellPts " << numCellPts); + newCellPts = new vtkIdType[numCellPts]; + //for (j = numCellPts-1; j >= 0; j--) + for (j = 0; j < numCellPts; j++) + { + //newCellPts[numCellPts-1-j] = cellPts->GetId(j) + numPts*k; + newCellPts[j] = cellPts->GetId(j) + numPts*k; + if (this->CopyInput) + { + //newCellPts[numCellPts-1-j] += numPts; + newCellPts[j] += numPts; + } + } + } + cellId = output->InsertNextCell(cellType, numCellPts, newCellPts); + delete [] newCellPts; + outCD->CopyData(inCD, i, cellId); + if (inCellVectors) + { + inCellVectors->GetTuple(i, tuple); + outCellVectors->SetTuple(cellId, tuple); + } + if (inCellNormals) + { + //inCellNormals->GetTuple(i, tuple); + //outCellNormals->SetTuple(cellId, tuple); + } + } + } + + cell->Delete(); + ptIds->Delete(); + output->SetPoints(outPoints); + outPoints->Delete(); + output->CheckAttributes(); + + return 1; +} + +int vtkRotationFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} diff --git a/Graphics/vtkRotationFilter.h b/Graphics/vtkRotationFilter.h new file mode 100644 index 0000000..8ecbdfc --- /dev/null +++ b/Graphics/vtkRotationFilter.h @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRotationFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRotationFilter - Duplicates a data set by rotation about an axis +// .SECTION Description +// The vtkRotationFilter duplicates a data set by rotation about one of the +// 3 axis of the dataset's reference. +// Since it converts data sets into unstructured grids, it is not efficient +// for structured data sets. +// +// .SECTION Thanks +// Theophane Foggia of The Swiss National Supercomputing Centre (CSCS) +// for creating and contributing this filter + +#ifndef __vtkRotationFilter_h +#define __vtkRotationFilter_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkRotationFilter : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkRotationFilter *New(); + vtkTypeRevisionMacro(vtkRotationFilter, vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream &os, vtkIndent indent); + +//BTX + enum RotationAxis + { + USE_X = 0, + USE_Y = 1, + USE_Z = 2 + }; +//ETX + + // Description: + // Set the axis of rotation to use. It is set by default to Z. + vtkSetClampMacro(Axis, int, 0, 2); + vtkGetMacro(Axis, int); + void SetAxisToX() { this->SetAxis(USE_X); }; + void SetAxisToY() { this->SetAxis(USE_Y); }; + void SetAxisToZ() { this->SetAxis(USE_Z); }; + + // Description: + // Set the rotation angle to use. + vtkSetMacro(Angle, double); + vtkGetMacro(Angle, double); + + // Description: + // Set the rotation center coordinates. + vtkSetVector3Macro(Center,double); + vtkGetVector3Macro(Center,double); + + // Description: + // Set the number of copies to create. The source will be rotated N times + // and a new polydata copy of the original created at each angular position + // All copies will be appended to form a single output + vtkSetMacro(NumberOfCopies, int); + vtkGetMacro(NumberOfCopies, int); + + // Description: + // If on (the default), copy the input geometry to the output. If off, + // the output will only contain the rotation. + vtkSetMacro(CopyInput, int); + vtkGetMacro(CopyInput, int); + vtkBooleanMacro(CopyInput, int); + + +protected: + vtkRotationFilter(); + ~vtkRotationFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int Axis; + double Angle; + double Center[3]; + int NumberOfCopies; + int CopyInput; + +private: + vtkRotationFilter(const vtkRotationFilter&); // Not implemented + void operator=(const vtkRotationFilter&); // Not implemented +}; + +#endif + + diff --git a/Graphics/vtkRotationalExtrusionFilter.cxx b/Graphics/vtkRotationalExtrusionFilter.cxx new file mode 100644 index 0000000..8785635 --- /dev/null +++ b/Graphics/vtkRotationalExtrusionFilter.cxx @@ -0,0 +1,377 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRotationalExtrusionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRotationalExtrusionFilter.h" + +#include "vtkCellArray.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkRotationalExtrusionFilter, "$Revision: 1.56 $"); +vtkStandardNewMacro(vtkRotationalExtrusionFilter); + +// Create object with capping on, angle of 360 degrees, resolution = 12, and +// no translation along z-axis. +// vector (0,0,1), and point (0,0,0). +vtkRotationalExtrusionFilter::vtkRotationalExtrusionFilter() +{ + this->Capping = 1; + this->Angle = 360.0; + this->DeltaRadius = 0.0; + this->Translation = 0.0; + this->Resolution = 12; // 30 degree increments +} + +int vtkRotationalExtrusionFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells; + vtkPointData *pd=input->GetPointData(); + vtkCellData *cd=input->GetCellData(); + vtkPolyData *mesh; + vtkPoints *inPts; + vtkCellArray *inVerts, *inLines, *inPolys, *inStrips; + int numEdges; + vtkIdType *pts = 0; + vtkIdType npts = 0; + vtkIdType cellId, ptId, ncells; + double x[3], newX[3], radius, angleIncr, radIncr, transIncr; + double psi, theta; + vtkPoints *newPts; + vtkCellArray *newLines=NULL, *newPolys=NULL, *newStrips; + vtkCell *edge; + vtkIdList *cellIds; + int i, j, k; + vtkIdType p1, p2; + vtkPointData *outPD=output->GetPointData(); + vtkCellData *outCD=output->GetCellData(); + double tempd; + int abort=0; + + // Initialize / check input + // + vtkDebugMacro(<<"Rotationally extruding data"); + + numPts = input->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + if (numPts < 1 || numCells < 1) + { + vtkErrorMacro(<<"No data to extrude!"); + return 1; + } + + // Build cell data structure. + // + mesh = vtkPolyData::New(); + inPts = input->GetPoints(); + inVerts = input->GetVerts(); + inLines = input->GetLines(); + inPolys = input->GetPolys(); + inStrips = input->GetStrips(); + mesh->SetPoints(inPts); + mesh->SetVerts(inVerts); + mesh->SetLines(inLines); + mesh->SetPolys(inPolys); + mesh->SetStrips(inStrips); + if ( inPolys || inStrips ) + { + mesh->BuildLinks(); + } + + // Allocate memory for output. We don't copy normals because surface geometry + // is modified. + // + outPD->CopyNormalsOff(); + outPD->CopyAllocate(pd,(this->Resolution+1)*numPts); + newPts = vtkPoints::New(); + newPts->Allocate((this->Resolution+1)*numPts); + if ( (ncells=inVerts->GetNumberOfCells()) > 0 ) + { + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(ncells,this->Resolution+1)); + } + // arbitrary initial allocation size + ncells = inLines->GetNumberOfCells() + inPolys->GetNumberOfCells()/10 + + inStrips->GetNumberOfCells()/10; + ncells = (ncells < 100 ? 100 : ncells); + newStrips = vtkCellArray::New(); + newStrips->Allocate(newStrips->EstimateSize(ncells,2*(this->Resolution+1))); + outCD->CopyNormalsOff(); + outCD->CopyAllocate(cd,ncells); + + // copy points + for (ptId=0; ptId < numPts; ptId++) //base level + { + newPts->InsertPoint(ptId,inPts->GetPoint(ptId)); + outPD->CopyData(pd,ptId,ptId); + } + this->UpdateProgress(0.1); + + // loop assumes rotation around z-axis + radIncr = this->DeltaRadius / this->Resolution; + transIncr = this->Translation / this->Resolution; + angleIncr = this->Angle / this->Resolution * vtkMath::DegreesToRadians(); + for ( i = 1; i <= this->Resolution; i++ ) + { + this->UpdateProgress(0.1 + 0.5*(i-1)/this->Resolution); + for (ptId=0; ptId < numPts; ptId++) + { + inPts->GetPoint(ptId, x); + //convert to cylindrical + radius = sqrt(x[0]*x[0] + x[1]*x[1]); + if (radius > 0.0) + { + tempd = (double)x[0]/radius; + if (tempd < -1.0) + { + tempd = -1.0; + } + if (tempd > 1.0) + { + tempd = 1.0; + } + theta = acos(tempd); + tempd = (double)x[1]/radius; + if (tempd < -1.0) + { + tempd = -1.0; + } + if (tempd > 1.0) + { + tempd = 1.0; + } + if ( (psi=asin(tempd)) < 0.0 ) + { + if ( theta < (vtkMath::Pi()/2.0) ) + { + theta = 2.0*vtkMath::Pi() + psi; + } + else + { + theta = vtkMath::Pi() - psi; + } + } + + //increment angle + radius += i*radIncr; + newX[0] = radius * cos (i*angleIncr + theta); + newX[1] = radius * sin (i*angleIncr + theta); + newX[2] = x[2] + i * transIncr; + } + else // radius is zero + { + newX[0] = 0.0; + newX[1] = 0.0; + newX[2] = x[2] + i * transIncr; + } + newPts->InsertPoint(ptId+i*numPts,newX); + outPD->CopyData(pd,ptId,ptId+i*numPts); + } + } + + // To insure that cell attributes are in consistent order with the + // cellId's, we process the verts, lines, polys and strips in order. + vtkIdType newCellId=0; + int type; + if ( newLines ) // there are verts which produce lines + { + for ( cellId=0; cellId < numCells && !abort; cellId++) + { + type = mesh->GetCellType(cellId); + if ( type == VTK_VERTEX || type == VTK_POLY_VERTEX ) + { + mesh->GetCellPoints(cellId,npts,pts); + for (i=0; iInsertNextCell(this->Resolution+1); + for ( j=0; j<=this->Resolution; j++ ) + { + newLines->InsertCellPoint(ptId + j*numPts); + } + outCD->CopyData(cd,cellId,newCellId++); + } + }//if a vertex or polyVertex + }//for all cells + }//if there are verts generating lines + this->UpdateProgress (0.25); + abort = this->GetAbortExecute(); + + // If capping is on, copy 2D cells to output (plus create cap). Notice + // that polygons are done first, then strips. + // + if ( this->Capping && (this->Angle != 360.0 || this->DeltaRadius != 0.0 + || this->Translation != 0.0) ) + { + if ( inPolys->GetNumberOfCells() > 0 ) + { + newPolys = vtkCellArray::New(); + newPolys->Allocate(inPolys->GetSize()); + + for ( cellId=0; cellId < numCells && !abort; cellId++ ) + { + type = mesh->GetCellType(cellId); + if ( type == VTK_TRIANGLE || type == VTK_QUAD || type == VTK_POLYGON ) + { + mesh->GetCellPoints(cellId, npts, pts); + newPolys->InsertNextCell(npts,pts); + outCD->CopyData(cd,cellId,newCellId++); + newPolys->InsertNextCell(npts); + for (i=0; i < npts; i++) + { + newPolys->InsertCellPoint(pts[i] + this->Resolution*numPts); + } + outCD->CopyData(cd,cellId,newCellId++); + } + } + } + + for ( cellId=0; cellId < numCells && !abort; cellId++ ) + { + type = mesh->GetCellType(cellId); + if ( type == VTK_TRIANGLE_STRIP ) + { + mesh->GetCellPoints(cellId, npts, pts); + newStrips->InsertNextCell(npts,pts); + outCD->CopyData(cd,cellId,newCellId++); + newStrips->InsertNextCell(npts); + for (i=0; i < npts; i++) + { + newStrips->InsertCellPoint(pts[i] + this->Resolution*numPts); + } + outCD->CopyData(cd,cellId,newCellId++); + } + } + }//if capping + this->UpdateProgress (0.5); + abort = this->GetAbortExecute(); + + // Now process lines, polys and/or strips to produce strips + // + if ( inLines->GetNumberOfCells() || inPolys->GetNumberOfCells() || + inStrips->GetNumberOfCells() ) + { + cellIds = vtkIdList::New(); + cellIds->Allocate(VTK_CELL_SIZE); + vtkGenericCell *cell = vtkGenericCell::New(); + + for ( cellId=0; cellId < numCells && !abort; cellId++) + { + type = mesh->GetCellType(cellId); + if ( type == VTK_LINE || type == VTK_POLY_LINE ) + { + mesh->GetCellPoints(cellId,npts,pts); + for (i=0; i<(npts-1); i++) + { + p1 = pts[i]; + p2 = pts[i+1]; + newStrips->InsertNextCell(2*(this->Resolution+1)); + for ( j=0; j<=this->Resolution; j++) + { + newStrips->InsertCellPoint(p2 + j*numPts); + newStrips->InsertCellPoint(p1 + j*numPts); + } + outCD->CopyData(cd,cellId,newCellId++); + } + }//if a line + + else if ( type == VTK_TRIANGLE || type == VTK_QUAD || + type == VTK_POLYGON || type == VTK_TRIANGLE_STRIP ) + {// create strips from boundary edges + mesh->GetCell(cellId,cell); + numEdges = cell->GetNumberOfEdges(); + for (i=0; iGetEdge(i); + for (j=0; j<(edge->GetNumberOfPoints()-1); j++) + { + p1 = edge->PointIds->GetId(j); + p2 = edge->PointIds->GetId(j+1); + mesh->GetCellEdgeNeighbors(cellId, p1, p2, cellIds); + + if ( cellIds->GetNumberOfIds() < 1 ) //generate strip + { + newStrips->InsertNextCell(2*(this->Resolution+1)); + for (k=0; k<=this->Resolution; k++) + { + newStrips->InsertCellPoint(p2 + k*numPts); + newStrips->InsertCellPoint(p1 + k*numPts); + } + outCD->CopyData(cd,cellId,newCellId++); + } //if boundary edge + } //for each sub-edge + } //for each edge + } //for each polygon or triangle strip + }//for all cells + + cellIds->Delete(); + cell->Delete(); + } //if strips are being generated + this->UpdateProgress (1.00); + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + mesh->Delete(); + + if ( newLines ) + { + output->SetLines(newLines); + newLines->Delete(); + } + + if ( newPolys ) + { + output->SetPolys(newPolys); + newPolys->Delete(); + } + + output->SetStrips(newStrips); + newStrips->Delete(); + + output->Squeeze(); + + return 1; +} + +void vtkRotationalExtrusionFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Resolution: " << this->Resolution << "\n"; + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); + os << indent << "Angle: " << this->Angle << "\n"; + os << indent << "Translation: " << this->Translation << "\n"; + os << indent << "Delta Radius: " << this->DeltaRadius << "\n"; +} diff --git a/Graphics/vtkRotationalExtrusionFilter.h b/Graphics/vtkRotationalExtrusionFilter.h new file mode 100644 index 0000000..5ab6b3c --- /dev/null +++ b/Graphics/vtkRotationalExtrusionFilter.h @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRotationalExtrusionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRotationalExtrusionFilter - sweep polygonal data creating "skirt" from free edges and lines, and lines from vertices +// .SECTION Description +// vtkRotationalExtrusionFilter is a modeling filter. It takes polygonal +// data as input and generates polygonal data on output. The input dataset +// is swept around the z-axis to create new polygonal primitives. These +// primitives form a "skirt" or swept surface. For example, sweeping a +// line results in a cylindrical shell, and sweeping a circle creates a +// torus. +// +// There are a number of control parameters for this filter. You can +// control whether the sweep of a 2D object (i.e., polygon or triangle +// strip) is capped with the generating geometry via the "Capping" instance +// variable. Also, you can control the angle of rotation, and whether +// translation along the z-axis is performed along with the rotation. +// (Translation is useful for creating "springs".) You also can adjust +// the radius of the generating geometry using the "DeltaRotation" instance +// variable. +// +// The skirt is generated by locating certain topological features. Free +// edges (edges of polygons or triangle strips only used by one polygon or +// triangle strips) generate surfaces. This is true also of lines or +// polylines. Vertices generate lines. +// +// This filter can be used to model axisymmetric objects like cylinders, +// bottles, and wine glasses; or translational/rotational symmetric objects +// like springs or corkscrews. + +// .SECTION Caveats +// If the object sweeps 360 degrees, radius does not vary, and the object +// does not translate, capping is not performed. This is because the cap +// is unnecessary. +// +// Some polygonal objects have no free edges (e.g., sphere). When swept, +// this will result in two separate surfaces if capping is on, or no surface +// if capping is off. + +// .SECTION See Also +// vtkLinearExtrusionFilter + +#ifndef __vtkRotationalExtrusionFilter_h +#define __vtkRotationalExtrusionFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkRotationalExtrusionFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkRotationalExtrusionFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create object with capping on, angle of 360 degrees, resolution = 12, and + // no translation along z-axis. + // vector (0,0,1), and point (0,0,0). + static vtkRotationalExtrusionFilter *New(); + + // Description: + // Set/Get resolution of sweep operation. Resolution controls the number + // of intermediate node points. + vtkSetClampMacro(Resolution,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(Resolution,int); + + // Description: + // Turn on/off the capping of the skirt. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + + // Description: + // Set/Get angle of rotation. + vtkSetMacro(Angle,double); + vtkGetMacro(Angle,double); + + // Description: + // Set/Get total amount of translation along the z-axis. + vtkSetMacro(Translation,double); + vtkGetMacro(Translation,double); + + // Description: + // Set/Get change in radius during sweep process. + vtkSetMacro(DeltaRadius,double); + vtkGetMacro(DeltaRadius,double); + +protected: + vtkRotationalExtrusionFilter(); + ~vtkRotationalExtrusionFilter() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int Resolution; + int Capping; + double Angle; + double Translation; + double DeltaRadius; +private: + vtkRotationalExtrusionFilter(const vtkRotationalExtrusionFilter&); // Not implemented. + void operator=(const vtkRotationalExtrusionFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkRuledSurfaceFilter.cxx b/Graphics/vtkRuledSurfaceFilter.cxx new file mode 100644 index 0000000..ef14178 --- /dev/null +++ b/Graphics/vtkRuledSurfaceFilter.cxx @@ -0,0 +1,503 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRuledSurfaceFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRuledSurfaceFilter.h" + +#include "vtkCellArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyLine.h" + +vtkCxxRevisionMacro(vtkRuledSurfaceFilter, "$Revision: 1.24 $"); +vtkStandardNewMacro(vtkRuledSurfaceFilter); + +vtkRuledSurfaceFilter::vtkRuledSurfaceFilter() +{ + this->DistanceFactor = 3.0; + this->OnRatio = 1; + this->Offset = 0; + this->CloseSurface = 0; + this->RuledMode = VTK_RULED_MODE_RESAMPLE; + this->Resolution[0] = 1; + this->Resolution[1] = 1; + this->PassLines = 0; + + this->Ids = vtkIdList::New(); + this->Ids->SetNumberOfIds(4); +} + +vtkRuledSurfaceFilter::~vtkRuledSurfaceFilter() +{ + this->Ids->Delete(); +} + +int vtkRuledSurfaceFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts, *newPts = NULL; + vtkIdType i, numPts, numLines; + vtkCellArray *inLines, *newPolys, *newStrips; + vtkIdType *pts = 0; + vtkIdType *pts2 = 0; + vtkIdType npts = 0; + vtkIdType npts2 = 0; + vtkPointData *inPD=input->GetPointData(), *outPD=output->GetPointData(); + + // Check input, pass data if requested + // + vtkDebugMacro(<<"Creating a ruled surface"); + + inPts = input->GetPoints(); + inLines = input->GetLines(); + if ( !inPts || !inLines) + { + return 1; + } + numLines=inLines->GetNumberOfCells(); + numPts = inPts->GetNumberOfPoints(); + if (numPts < 1 || numLines < 2 ) + { + return 1; + } + + if ( this->PassLines ) + { + output->SetLines(inLines); + } + + if ( this->RuledMode == VTK_RULED_MODE_RESAMPLE ) //generating new points + { + newPts = vtkPoints::New(); + output->SetPoints(newPts); + outPD->InterpolateAllocate(inPD,numPts); + if ( this->PassLines ) //need to copy input points + { + newPts->DeepCopy(inPts); + for (i=0; iCopyData(inPD,i,i); + } + } + newPts->Delete(); + newStrips = vtkCellArray::New(); + newStrips->Allocate( + 2*(this->Resolution[1]+1)*this->Resolution[0]*(numLines-1)); + output->SetStrips(newStrips); + newStrips->Delete(); + } + else //using original points + { + output->SetPoints(inPts); + output->GetPointData()->PassData(input->GetPointData()); + newPolys = vtkCellArray::New(); + newPolys->Allocate(2*numPts); + output->SetPolys(newPolys); + newPolys->Delete(); + } + + // For each pair of lines (as selected by Offset and OnRatio), create a + // stripe (a ruled surfac between two lines). + // + inLines->InitTraversal(); + inLines->GetNextCell(npts,pts); + for (i=0; iUpdateProgress ((double)i/numLines); + if (this->GetAbortExecute()) + { + break; //out of line loop + } + + inLines->GetNextCell(npts2,pts2); //get the next edge + + // Determine whether this stripe should be generated + if ( (i-this->Offset) >= 0 && !((i - this->Offset ) % this->OnRatio) && + npts >= 2 && npts2 >= 2) + { + switch (this->RuledMode) + { + case VTK_RULED_MODE_RESAMPLE: + this->Resample(output, input, inPts, newPts, npts, pts, npts2, pts2); + break; + case VTK_RULED_MODE_POINT_WALK: + this->PointWalk(output, inPts, npts, pts, npts2, pts2); + break; + }//switch + }//generate this stripe + + //Get the next line for generating the next stripe + npts = npts2; + pts = pts2; + if ( i == (numLines-2) ) + { + if ( this->CloseSurface ) + { + inLines->InitTraversal(); + } + else + { + i++; //will cause the loop to end + } + }//add far boundary of surface + }//for all selected line pairs + + return 1; +} + +void vtkRuledSurfaceFilter::Resample(vtkPolyData *output, vtkPolyData *input, + vtkPoints *inPts, vtkPoints *newPts, + int npts, vtkIdType *pts, + int npts2, vtkIdType *pts2) +{ + vtkIdType offset, id; + int i, j; + double length, length2; + vtkCellArray *newStrips; + vtkPointData *inPD=input->GetPointData(); + vtkPointData *outPD=output->GetPointData(); + double v, uu, vv; + double s, t; + double deltaV; + double deltaS, deltaT; + double d0, d1, l0, l1; + double pt[3], pt0[3], pt1[3], pt00[3], pt01[3], pt10[3], pt11[3]; + int i00, i01, i10, i11; + + if (this->Resolution[0] < 1) + { + vtkErrorMacro(<< "Resolution[0] must be greater than 0"); + return; + } + if (this->Resolution[1] < 1) + { + vtkErrorMacro(<< "Resolution[1] must be greater than 0"); + return; + } + + // Measure the length of each boundary line + // + // first line + length = 0.0; + for (i=0; i < npts-1; i++) + { + inPts->GetPoint(pts[i], pt00); + inPts->GetPoint(pts[i+1], pt01); + length += sqrt(vtkMath::Distance2BetweenPoints(pt00, pt01)); + } + + // second line + length2 = 0.0; + for (i=0; i < npts2-1; i++) + { + inPts->GetPoint(pts2[i], pt00); + inPts->GetPoint(pts2[i+1], pt01); + length2 += sqrt(vtkMath::Distance2BetweenPoints(pt00, pt01)); + } + + // Create the ruled surface as a set of triangle strips. Allocate + // additional memory for new points. + // + // forces allocation so that SetPoint() can be safely used + offset = newPts->GetNumberOfPoints(); + newPts->InsertPoint(offset+(this->Resolution[0]+1)*(this->Resolution[1]+1)-1, + 0.0, 0.0, 0.0); + newStrips = output->GetStrips(); + + // We'll construct the points for the ruled surface in column major order, + // i.e. all the points between the first point of the two polylines. + for (i=0; i < this->Resolution[0]; i++) + { + newStrips->InsertNextCell( 2*(this->Resolution[1]+1) ); + for (j=0; j < this->Resolution[1] + 1; j++) + { + newStrips->InsertCellPoint(offset + i*(this->Resolution[1]+1)+j); + newStrips->InsertCellPoint(offset + (i+1)*(this->Resolution[1]+1)+j); + } + } + + // Now, compute all the points. + // + // parametric delta + deltaV = 1.0 / (double) (this->Resolution[1]); + + // arc-length deltas + deltaS = length / (double) (this->Resolution[0]); + deltaT = length2 / (double) (this->Resolution[0]); + + t = 0.0; + d0 = d1 = 0.0; + l0 = l1 = 0.0; + i00 = 0; + i01 = 1; + i10 = 0; + i11 = 1; + + inPts->GetPoint(pts[0], pt00); + inPts->GetPoint(pts[1], pt01); + inPts->GetPoint(pts2[0], pt10); + inPts->GetPoint(pts2[1], pt11); + + for (i=0; i < this->Resolution[0]+1; i++) + { + // compute the end points a rule, one point from the first polyline, + // one point from the second line + s = i*deltaS; + t = i*deltaT; + + // find for the interval containing s + while (s > l0 && i00 < (npts - 1)) + { + inPts->GetPoint(pts[i00], pt00); + inPts->GetPoint(pts[i01], pt01); + d0 = sqrt(vtkMath::Distance2BetweenPoints(pt00, pt01)); + // doubleing point discrepancy: sgi needs the following test to be + // s <= length while win32 needs it to be s < length. We account + // for this by using the <= test here and adjusting the maximum parameter + // value below (see #1) + if ((s > l0 + d0) && (s <= length)) + { + // s's interval is still to the right + l0 += d0; + i00++; + i01++; + } + else + { + // found the correct interval + break; + } + } + + // compute the point at s on the first polyline + if (i01 > (npts - 1)) + { + i00--; + i01--; + } + this->Ids->SetId(0,pts[i00]); + this->Ids->SetId(1,pts[i01]); + if (d0 == 0.0) + { + uu = 0.0; + } + else + { + uu = (s - l0) / d0; + } + // #1: fix to address the win32/sgi doubleing point differences + if (s >= length) + { + uu = 1.0; + } + pt0[0] = (1.0-uu) * pt00[0] + uu * pt01[0]; + pt0[1] = (1.0-uu) * pt00[1] + uu * pt01[1]; + pt0[2] = (1.0-uu) * pt00[2] + uu * pt01[2]; + + // find for the interval containing t + while (t > l1 && i10 < (npts2 - 1)) + { + inPts->GetPoint(pts2[i10], pt10); + inPts->GetPoint(pts2[i11], pt11); + d1 = sqrt(vtkMath::Distance2BetweenPoints(pt10, pt11)); + // doubleing point discrepancy: sgi needs the following test to be + // t <= length2 while win32 needs it to be t < length2. We account + // for this by using the <= test here and adjusting the maximum parameter + // value below (see #1) + if ((t > l1 + d1) && (t <= length2)) + { + // t's interval is still to the right + l1 += d1; + i10++; + i11++; + } + else + { + // found the correct interval + break; + } + } + // compute the point at t on the second polyline + if (i11 > npts2 - 1) + { + i10--; + i11--; + } + this->Ids->SetId(2,pts2[i10]); + this->Ids->SetId(3,pts2[i11]); + if (d1 == 0.0) + { + vv = 0.0; + } + else + { + vv = (t - l1) / d1; + } + // #1: fix to address the win32/sgi doubleing point differences + if (t >= length2) + { + vv = 1.0; + } + pt1[0] = (1.0-vv) * pt10[0] + vv * pt11[0]; + pt1[1] = (1.0-vv) * pt10[1] + vv * pt11[1]; + pt1[2] = (1.0-vv) * pt10[2] + vv * pt11[2]; + + // Now, compute the points along the rule + for (j=0; j < this->Resolution[1]+1; j++) + { + v = j*deltaV; + pt[0] = (1.0 - v) * pt0[0] + v * pt1[0]; + pt[1] = (1.0 - v) * pt0[1] + v * pt1[1]; + pt[2] = (1.0 - v) * pt0[2] + v * pt1[2]; + + id = offset + i*(this->Resolution[1] + 1) + j; + newPts->SetPoint(id, pt); + this->Weights[0] = (1.0 - v)*(1.0 - uu); + this->Weights[1] = (1.0 - v)*uu; + this->Weights[2] = v*(1.0 - vv); + this->Weights[3] = v*vv; + outPD->InterpolatePoint(inPD, id, this->Ids, this->Weights); + } + } +} + +void vtkRuledSurfaceFilter::PointWalk(vtkPolyData *output, vtkPoints *inPts, + int npts, vtkIdType *pts, + int npts2, vtkIdType *pts2) +{ + int loc, loc2; + vtkCellArray *newPolys=output->GetPolys(); + double x[3], y[3], a[3], b[3], xa, xb, ya, distance2; + + // Compute distance factor based on first two points + // + inPts->GetPoint(pts[0],x); + inPts->GetPoint(pts2[0],y); + distance2 = vtkMath::Distance2BetweenPoints(x,y) * + this->DistanceFactor * this->DistanceFactor; + + // Walk "edge" along the two lines maintaining closest distance + // and generating triangles as we go. + loc = loc2 = 0; + while ( loc < (npts-1) || loc2 < (npts2-1) ) + { + if ( loc >= (npts-1) ) //clamped at end of first line + { + inPts->GetPoint(pts[loc],x); + inPts->GetPoint(pts2[loc2],a); + inPts->GetPoint(pts2[loc2+1],b); + xa = vtkMath::Distance2BetweenPoints(x,a); + xb = vtkMath::Distance2BetweenPoints(x,b); + if ( xa <= distance2 && xb <= distance2 ) + { + newPolys->InsertNextCell(3); + newPolys->InsertCellPoint(pts[loc]); //x + newPolys->InsertCellPoint(pts2[loc2+1]); //b + newPolys->InsertCellPoint(pts2[loc2]); //a + } + loc2++; + } + else if ( loc2 >= (npts2-1) ) //clamped at end of second line + { + inPts->GetPoint(pts[loc],x); + inPts->GetPoint(pts[loc+1],y); + inPts->GetPoint(pts2[loc2],a); + xa = vtkMath::Distance2BetweenPoints(x,a); + ya = vtkMath::Distance2BetweenPoints(y,a); + if ( xa <= distance2 && ya <= distance2 ) + { + newPolys->InsertNextCell(3); + newPolys->InsertCellPoint(pts[loc]); //x + newPolys->InsertCellPoint(pts[loc+1]); //y + newPolys->InsertCellPoint(pts2[loc2]); //a + } + loc++; + } + else //not at either end + { + inPts->GetPoint(pts[loc],x); + inPts->GetPoint(pts[loc+1],y); + inPts->GetPoint(pts2[loc2],a); + inPts->GetPoint(pts2[loc2+1],b); + xa = vtkMath::Distance2BetweenPoints(x,a); + xb = vtkMath::Distance2BetweenPoints(x,b); + ya = vtkMath::Distance2BetweenPoints(a,y); + if ( xb <= ya ) + { + if ( xb <= distance2 && xa <= distance2 ) + { + newPolys->InsertNextCell(3); + newPolys->InsertCellPoint(pts[loc]); //x + newPolys->InsertCellPoint(pts2[loc2+1]); //b + newPolys->InsertCellPoint(pts2[loc2]); //a + } + loc2++; + } + else + { + if ( ya <= distance2 && xa <= distance2 ) + { + newPolys->InsertNextCell(3); + newPolys->InsertCellPoint(pts[loc]); //x + newPolys->InsertCellPoint(pts[loc+1]); //y + newPolys->InsertCellPoint(pts2[loc2]); //a + } + loc++; + } + }//where in the lines + }//while still building the stripe +} + +const char *vtkRuledSurfaceFilter::GetRuledModeAsString(void) +{ + if ( this->RuledMode == VTK_RULED_MODE_RESAMPLE ) + { + return "Resample"; + } + else //if ( this->RuledMode == VTK_RULED_MODE_POINT_WALK ) + { + return "PointWalk"; + } +} + +void vtkRuledSurfaceFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Distance Factor: " << this->DistanceFactor << "\n"; + os << indent << "On Ratio: " << this->OnRatio << "\n"; + os << indent << "Offset: " << this->Offset << "\n"; + os << indent << "Close Surface: " << (this->CloseSurface ? "On\n" : "Off\n"); + os << indent << "Ruled Mode: " << this->GetRuledModeAsString() << "\n"; + os << indent << "Resolution: (" << this->Resolution[0] + << ", " << this->Resolution[1] << ")" << endl; + os << indent << "Pass Lines: " << (this->PassLines ? "On\n" : "Off\n"); +} + diff --git a/Graphics/vtkRuledSurfaceFilter.h b/Graphics/vtkRuledSurfaceFilter.h new file mode 100644 index 0000000..ec56bf3 --- /dev/null +++ b/Graphics/vtkRuledSurfaceFilter.h @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRuledSurfaceFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRuledSurfaceFilter - generates a surface from a set of lines +// .SECTION Description +// vtkRuledSurfaceFilter is a filter that generates a surface from a set of +// lines. The lines are assumed to be "parallel" in the sense that they do +// not intersect and remain somewhat close to one another. A surface is +// generated by connecting the points defining each pair of lines with +// straight lines. This creates a strip for each pair of lines (i.e., a +// triangulation is created from two generating lines). The filter can handle +// an arbitrary number of lines, with lines i and i+1 assumed connected. +// Note that there are several different approaches for creating the ruled +// surface, the method for creating the surface can either use the input +// points or resample from the polylines (using a user-specified resolution). +// +// This filter offers some other important features. A DistanceFactor ivar is +// used to decide when two lines are too far apart to connect. (The factor is +// a multiple of the distance between the first two points of the two lines +// defining the strip.) If the distance between the two generating lines +// becomes too great, then the surface is not generated in that +// region. (Note: if the lines separate and then merge, then a hole can be +// generated in the surface.) In addition, the Offset and OnRation ivars can +// be used to create nifty striped surfaces. Closed surfaces (e.g., tubes) can +// be created by setting the CloseSurface ivar. (The surface can be closed +// in the other direction by repeating the first and last point in the +// polylines defining the surface.) +// +// An important use of this filter is to combine it with vtkStreamLine to +// generate stream surfaces. It can also be used to create surfaces from +// contours. + +// .SECTION Caveats +// The number of lines must be greater than two if a surface is to be +// generated. sides (i.e., a ribbon), use vtkRibbonFilter. + +// .SECTION See Also +// vtkRibbonFilter vtkStreamLine + +#ifndef __vtkRuledSurfaceFilter_h +#define __vtkRuledSurfaceFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkIdList; +class vtkPoints; +class vtkPolyData; + +#define VTK_RULED_MODE_RESAMPLE 0 +#define VTK_RULED_MODE_POINT_WALK 1 + +class VTK_GRAPHICS_EXPORT vtkRuledSurfaceFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkRuledSurfaceFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with OnRatio=1, Offset=0. DistanceFactor=3.0, + // CloseSurface off, and PassLines off. + static vtkRuledSurfaceFilter *New(); + + // Description: + // Set/Get the factor that controls tearing of the surface. + vtkSetClampMacro(DistanceFactor,double,1.0,VTK_DOUBLE_MAX); + vtkGetMacro(DistanceFactor,double); + + // Description: + // Control the striping of the ruled surface. If OnRatio is greater + // than 1, then every nth strip is turned on, beginning with the Offset + // strip. + vtkSetClampMacro(OnRatio,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(OnRatio,int); + + // Description: + // Control the striping of the ruled surface. The offset sets the + // first stripe that is visible. Offset is generally used with + // OnRatio to create nifty striping effects. + vtkSetClampMacro(Offset,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(Offset,int); + + // Description: + // Indicate whether the surface is to be closed. If this boolean is + // on, then the first and last polyline are used to generate a stripe + // that closes the surface. (Note: to close the surface in the other + // direction, repeat the first point in the polyline as the last + // point in the polyline.) + vtkSetMacro(CloseSurface,int); + vtkGetMacro(CloseSurface,int); + vtkBooleanMacro(CloseSurface,int); + + // Description: + // Set the mode by which to create the ruled surface. (Dramatically + // different results are possible depending on the chosen mode.) The + // resample mode evenly resamples the polylines (based on length) and + // generates triangle strips. The point walk mode uses the existing + // points and walks around the polyline using existing points. + vtkSetClampMacro(RuledMode,int, + VTK_RULED_MODE_RESAMPLE,VTK_RULED_MODE_POINT_WALK); + vtkGetMacro(RuledMode,int); + void SetRuledModeToResample() + {this->SetRuledMode(VTK_RULED_MODE_RESAMPLE);} + void SetRuledModeToPointWalk() + {this->SetRuledMode(VTK_RULED_MODE_POINT_WALK);} + const char *GetRuledModeAsString(); + + // Description: + // If the ruled surface generation mode is RESAMPLE, then these parameters + // are used to determine the resample rate. Resolution[0] defines the + // resolution in the direction of the polylines; Resolution[1] defines + // the resolution across the polylines (i.e., direction orthogonal to + // Resolution[0]). + vtkSetVector2Macro(Resolution, int); + vtkGetVectorMacro(Resolution, int, 2); + + // Description: + // Indicate whether the generating lines are to be passed to the output. + // By defualt lines are not passed to the output. + vtkSetMacro(PassLines,int); + vtkGetMacro(PassLines,int); + vtkBooleanMacro(PassLines,int); + +protected: + vtkRuledSurfaceFilter(); + ~vtkRuledSurfaceFilter(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double DistanceFactor; + int OnRatio; + int Offset; + int CloseSurface; + int RuledMode; + int Resolution[2]; + int PassLines; + +private: + vtkIdList *Ids; + double Weights[4]; + + void Resample(vtkPolyData *output, vtkPolyData *input, + vtkPoints *inPts, vtkPoints *newPts, + int npts, vtkIdType *pts, int npts2, vtkIdType *pts2); + void PointWalk(vtkPolyData *output, vtkPoints *inPts, + int npts, vtkIdType *pts, int npts2, vtkIdType *pts2); + +private: + vtkRuledSurfaceFilter(const vtkRuledSurfaceFilter&); // Not implemented. + void operator=(const vtkRuledSurfaceFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkSelectPolyData.cxx b/Graphics/vtkSelectPolyData.cxx new file mode 100644 index 0000000..b6e1e7b --- /dev/null +++ b/Graphics/vtkSelectPolyData.cxx @@ -0,0 +1,640 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSelectPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSelectPolyData.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkTriangleFilter.h" +#include "vtkTriangleStrip.h" + +vtkCxxRevisionMacro(vtkSelectPolyData, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkSelectPolyData); + +vtkCxxSetObjectMacro(vtkSelectPolyData,Loop,vtkPoints); + +// Description: +// Instantiate object with InsideOut turned off. +vtkSelectPolyData::vtkSelectPolyData() +{ + this->GenerateSelectionScalars = 0; + this->InsideOut = 0; + this->Loop = NULL; + this->SelectionMode = VTK_INSIDE_SMALLEST_REGION; + this->ClosestPoint[0] = this->ClosestPoint[1] = this->ClosestPoint[2] = 0.0; + this->GenerateUnselectedOutput = 0; + + this->SetNumberOfOutputPorts(3); + + vtkPolyData *output2 = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(1, output2); + output2->Delete(); + + vtkPolyData *output3 = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(2, output3); + output3->Delete(); +} + +vtkSelectPolyData::~vtkSelectPolyData() +{ + if (this->Loop) + { + this->Loop->Delete(); + } +} + +vtkPolyData *vtkSelectPolyData::GetUnselectedOutput() +{ + if (this->GetNumberOfOutputPorts() < 2) + { + return NULL; + } + + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + +vtkPolyData *vtkSelectPolyData::GetSelectionEdges() +{ + if (this->GetNumberOfOutputPorts() < 3) + { + return NULL; + } + + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetOutputData(2)); +} + +int vtkSelectPolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numLoopPts; + vtkPolyData *triMesh; + vtkPointData *inPD, *outPD=output->GetPointData(); + vtkCellData *inCD, *outCD=output->GetCellData(); + vtkIdType closest=0, numPolys, i, j; + int k; + vtkIdList *loopIds, *edgeIds, *neighbors; + double x[3], xLoop[3], closestDist2, dist2, t; + double x0[3], x1[3], vec[3], dir[3], neiX[3]; + vtkCellArray *inPolys; + vtkPoints *inPts; + int numNei; + vtkIdType id, currentId = 0, nextId, pt1, pt2, numCells, neiId; + vtkIdType *cells, *pts, npts, numMeshLoopPts, prevId; + unsigned short int ncells; + int mark, s1, s2, val; + + // Initialize and check data + vtkDebugMacro(<<"Selecting data..."); + + this->GetUnselectedOutput()->Initialize(); + this->GetSelectionEdges()->Initialize(); + + if ( (numPts = input->GetNumberOfPoints()) < 1 ) + { + vtkErrorMacro("Input contains no points"); + return 1; + } + + if ( this->Loop == NULL || + (numLoopPts=this->Loop->GetNumberOfPoints()) < 3 ) + { + vtkErrorMacro("Please define a loop with at least three points"); + return 1; + } + + // Okay, now we build unstructured representation. Make sure we're + // working with triangles. + vtkTriangleFilter *tf=vtkTriangleFilter::New(); + tf->SetInput(input); + tf->PassLinesOff(); + tf->PassVertsOff(); + tf->Update(); + triMesh = tf->GetOutput(); + triMesh->Register(this); + tf->Delete(); + inPD = triMesh->GetPointData(); + inCD = triMesh->GetCellData(); + + numPts = triMesh->GetNumberOfPoints(); + inPts = triMesh->GetPoints(); + inPolys = triMesh->GetPolys(); + numPolys = inPolys->GetNumberOfCells(); + if ( numPolys < 1 ) + { + vtkErrorMacro("This filter operates on surface primitives"); + tf->Delete(); + return 1; + } + + this->Mesh = vtkPolyData::New(); + this->Mesh->SetPoints(inPts); //inPts + this->Mesh->SetPolys(inPolys); + this->Mesh->BuildLinks(); //to do neighborhood searching + numCells = this->Mesh->GetNumberOfCells(); + + // First thing to do is find the closest mesh points to the loop + // points. This creates a list of point ids. + loopIds = vtkIdList::New(); + loopIds->SetNumberOfIds(numLoopPts); + + for ( i=0; i < numLoopPts; i++) + { + this->Loop->GetPoint(i,xLoop); + closest = -1; + closestDist2 = VTK_DOUBLE_MAX; + + for ( j=0; j < numPts; j++) + { + inPts->GetPoint(j,x); + + dist2 = vtkMath::Distance2BetweenPoints(x, xLoop); + if ( dist2 < closestDist2 ) + { + closest = j; + closestDist2 = dist2; + } + } //for all input points + + loopIds->SetId(i,closest); + } //for all loop points + + // Now that we've got point ids, we build the loop. Start with the + // first two points in the loop (which define a line), and find the + // mesh edge that is directed along the line, and whose + // end point is closest to the line. Continue until loop closes in on + // itself. + edgeIds = vtkIdList::New(); + edgeIds->Allocate(numLoopPts*10,1000); + neighbors = vtkIdList::New(); + neighbors->Allocate(10000); + edgeIds->InsertNextId(loopIds->GetId(0)); + + for ( i=0; i < numLoopPts; i++ ) + { + currentId = loopIds->GetId(i); + nextId = loopIds->GetId((i+1)%numLoopPts); + prevId = (-1); + inPts->GetPoint(currentId, x); + inPts->GetPoint(currentId, x0); + inPts->GetPoint(nextId, x1); + for (j=0; j<3; j++) + { + vec[j] = x1[j] - x0[j]; + } + + // track edge + for (id=currentId; id != nextId; ) + { + this->GetPointNeighbors(id,neighbors); //points connected by edge + numNei = neighbors->GetNumberOfIds(); + closest = -1; + closestDist2 = VTK_DOUBLE_MAX; + for (j=0; jGetId(j); + inPts->GetPoint(neiId, neiX); + for (k=0; k<3; k++) + { + dir[k] = neiX[k] - x[k]; + } + if ( neiId != prevId && vtkMath::Dot(dir,vec) > 0.0 ) //candidate + { + dist2 = vtkLine::DistanceToLine(neiX, x0, x1); + if ( dist2 < closestDist2 ) + { + closest = neiId; + closestDist2 = dist2; + } + }//in direction of line + }//for all neighbors + + if ( closest < 0 ) + { + vtkErrorMacro(<<"Can't follow edge"); + return 1; + } + else + { + edgeIds->InsertNextId(closest); + prevId = id; + id = closest; + inPts->GetPoint(id, x); + } + }//for tracking edge + }//for all edges of loop + + // mainly for debugging + numMeshLoopPts = edgeIds->GetNumberOfIds(); + vtkCellArray *selectionEdges=vtkCellArray::New(); + selectionEdges->Allocate(selectionEdges->EstimateSize(1,numMeshLoopPts),100); + selectionEdges->InsertNextCell(numMeshLoopPts); + for (i=0; iInsertCellPoint(edgeIds->GetId(i)); + } + this->GetSelectionEdges()->SetPoints(inPts); + this->GetSelectionEdges()->SetLines(selectionEdges); + selectionEdges->Delete(); + + // Phew...we've defined loop, now want to do a fill so we can extract the + // inside from the outside. Depending on GenerateSelectionScalars flag, + // we either set the distance of the points to the selection loop as + // zero (GenerateSelectionScalarsOff) or we evaluate the distance of these + // points to the lines. (Later we'll use a connected traversal to compute + // the distances to the remaining points.) + + // Next, prepare to mark off inside/outside and on boundary of loop. + // Mark the boundary of the loop using point marks. Also initialize + // the advancing front (used to mark traversal/compute scalars). + // Prepare to compute the advancing front + vtkIntArray *cellMarks = vtkIntArray::New(); + cellMarks->SetNumberOfValues(numCells); + for (i=0; iSetValue(i,VTK_LARGE_INTEGER); + } + vtkIntArray *pointMarks = vtkIntArray::New(); + pointMarks->SetNumberOfValues(numPts); + for (i=0; iSetValue(i,VTK_LARGE_INTEGER); + } + + vtkIdList *currentFront = vtkIdList::New(), *tmpFront; + vtkIdList *nextFront = vtkIdList::New(); + for (i=0; iGetId(i); + pointMarks->SetValue(id, 0); //marks the start of the front + currentFront->InsertNextId(id); + } + + // Traverse the front as long as we can. We're basically computing a + // topological distance. + int maxFront=0; + vtkIdType maxFrontCell=(-1); + int currentFrontNumber=1, numPtsInFront; + while ( (numPtsInFront = currentFront->GetNumberOfIds()) ) + { + for (i=0; i < numPtsInFront; i++) + { + id = currentFront->GetId(i); + this->Mesh->GetPointCells(id, ncells, cells); + for (j=0; jGetValue(id) == VTK_LARGE_INTEGER ) + { + if ( currentFrontNumber > maxFront ) + { + maxFrontCell = id; + } + cellMarks->SetValue(id, currentFrontNumber); + this->Mesh->GetCellPoints(id,npts,pts); + for (k=0; kGetValue(pts[k]) == VTK_LARGE_INTEGER ) + { + pointMarks->SetValue(pts[k], 1); + nextFront->InsertNextId(pts[k]); + } + } + } + } //for cells surrounding point + } //all points in front + + currentFrontNumber++; + tmpFront = currentFront; + currentFront = nextFront; + nextFront = tmpFront; + nextFront->Reset(); + } //while still advancing + + // Okay, now one of the regions is filled with negative values. This fill + // operation assumes that everthing is connected. + if ( this->SelectionMode == VTK_INSIDE_CLOSEST_POINT_REGION ) + {// find closest point and use as a seed + for (closestDist2=VTK_DOUBLE_MAX, j=0; j < numPts; j++) + { + inPts->GetPoint(j,x); + + dist2 = vtkMath::Distance2BetweenPoints(x, this->ClosestPoint); + // get closest point not on the boundary + if ( dist2 < closestDist2 && pointMarks->GetValue(j) != 0 ) + { + closest = j; + closestDist2 = dist2; + } + } //for all input points + this->Mesh->GetPointCells(closest, ncells, cells); + } + + // We do the fill as a moving front. This is an alternative to recursion. The + // fill negates one region of the mesh on one side of the loop. + currentFront->Reset(); nextFront->Reset(); + currentFront->InsertNextId(maxFrontCell); + vtkIdType numCellsInFront; + + cellMarks->SetValue(maxFrontCell,-1); + + while ( (numCellsInFront = currentFront->GetNumberOfIds()) > 0 ) + { + for (i=0; i < numCellsInFront; i++) + { + id = currentFront->GetId(i); + + this->Mesh->GetCellPoints(id, npts, pts); + for (j=0; j<3; j++) + { + pt1 = pts[j]; + pt2 = pts[(j+1)%3]; + s1 = pointMarks->GetValue(pt1); + s2 = pointMarks->GetValue(pt2); + + if ( s1 != 0 ) + { + pointMarks->SetValue(pt1, -1); + } + + if ( ! (s1 == 0 && s2 == 0) ) + { + this->Mesh->GetCellEdgeNeighbors(id, pt1, pt2, neighbors); + numNei = neighbors->GetNumberOfIds(); + for (k=0; kGetId(k); + val = cellMarks->GetValue(neiId); + if ( val != -1 ) //-1 is what we're filling with + { + cellMarks->SetValue(neiId,-1); + nextFront->InsertNextId(neiId); + } + } + }//if can cross boundary + }//for all edges of cell + } //all cells in front + + tmpFront = currentFront; + currentFront = nextFront; + nextFront = tmpFront; + nextFront->Reset(); + } //while still advancing + + // Now may have to invert fill value depending on what we wan to extract + if ( this->SelectionMode == VTK_INSIDE_SMALLEST_REGION ) + { + for (i=0; i < numCells; i++) + { + mark = cellMarks->GetValue(i); + cellMarks->SetValue(i, -mark); + } + for (i=0; i < numPts; i++) + { + mark = pointMarks->GetValue(i); + pointMarks->SetValue(i, -mark); + } + } + + // If generating selection scalars, we now have to modify the scalars to + // approximate a distance function. Otherwise, we can create the output. + if ( ! this->GenerateSelectionScalars ) + {//spit out all the negative cells + vtkCellArray *newPolys=vtkCellArray::New(); + newPolys->Allocate(numCells/2, numCells/2); + for (i=0; i< numCells; i++) + { + if ( (cellMarks->GetValue(i) < 0) || + (cellMarks->GetValue(i) > 0 && this->InsideOut) ) + { + this->Mesh->GetCellPoints(i, npts, pts); + newPolys->InsertNextCell(npts,pts); + } + } + output->SetPoints(inPts); + output->SetPolys(newPolys); + outPD->PassData(inPD); + newPolys->Delete(); + + if ( this->GenerateUnselectedOutput ) + { + vtkCellArray *unPolys=vtkCellArray::New(); + unPolys->Allocate(numCells/2, numCells/2); + for (i=0; i< numCells; i++) + { + if ( (cellMarks->GetValue(i) >= 0) || + (cellMarks->GetValue(i) < 0 && this->InsideOut) ) + { + this->Mesh->GetCellPoints(i, npts, pts); + unPolys->InsertNextCell(npts,pts); + } + } + this->GetUnselectedOutput()->SetPoints(inPts); + this->GetUnselectedOutput()->SetPolys(unPolys); + this->GetUnselectedOutput()->GetPointData()->PassData(inPD); + unPolys->Delete(); + } + + } + else //modify scalars to generate selection scalars + { + vtkFloatArray *selectionScalars=vtkFloatArray::New(); + selectionScalars->SetNumberOfTuples(numPts); + + // compute distance to lines. Really this should be computed based on + // the connected fill distance. + for (j=0; j < numPts; j++) //compute minimum distance to loop + { + if ( pointMarks->GetValue(j) != 0 ) + { + inPts->GetPoint(j,x); + for ( closestDist2=VTK_DOUBLE_MAX, i=0; i < numLoopPts; i++ ) + { + this->Loop->GetPoint(i, x0); + this->Loop->GetPoint((i+1)%numLoopPts, x1); + dist2 = vtkLine::DistanceToLine(x, x0, x1, t, xLoop); + if ( dist2 < closestDist2 ) + { + closestDist2 = dist2; + } + }//for all loop edges + closestDist2 = sqrt((double)closestDist2); + selectionScalars->SetComponent(j,0, + closestDist2*pointMarks->GetValue(j)); + } + } + + // Now, determine the sign of those points "on the boundary" to give a + // better approximation to the scalar field. + for (j=0; j < numMeshLoopPts; j++) + { + id = edgeIds->GetId(j); + inPts->GetPoint(id, x); + for ( closestDist2=VTK_DOUBLE_MAX, i=0; i < numLoopPts; i++ ) + { + this->Loop->GetPoint(i, x0); + this->Loop->GetPoint((i+1)%numLoopPts, x1); + dist2 = vtkLine::DistanceToLine(x, x0, x1, t, xLoop); + if ( dist2 < closestDist2 ) + { + closestDist2 = dist2; + neiX[0] = xLoop[0]; neiX[1] = xLoop[1]; neiX[2] = xLoop[2]; + } + }//for all loop edges + closestDist2 = sqrt((double)closestDist2); + + // find neighbor not on boundary and compare negative/positive values + // to see what makes the most sense + this->GetPointNeighbors(id, neighbors); + numNei = neighbors->GetNumberOfIds(); + for (dist2=0.0, i=0; iGetId(i); + if ( pointMarks->GetValue(neiId) != 0 ) //find the furthest away + { + if ( fabs(selectionScalars->GetComponent(neiId,0)) > dist2 ) + { + currentId = neiId; + dist2 = fabs(selectionScalars->GetComponent(neiId,0)); + } + } + } + + inPts->GetPoint(currentId, x0); + if ( vtkMath::Distance2BetweenPoints(x0,x) < + vtkMath::Distance2BetweenPoints(x0,neiX) ) + { + closestDist2 = closestDist2 * pointMarks->GetValue(currentId); + } + else + { + closestDist2 = -closestDist2 * pointMarks->GetValue(currentId); + } + + selectionScalars->SetComponent(id,0,closestDist2); + }//for all boundary points + + output->CopyStructure(this->Mesh); //pass geometry/topology unchanged + int idx = outPD->AddArray(selectionScalars); + outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + outPD->CopyScalarsOff(); + outPD->PassData(inPD); + outCD->PassData(inCD); + selectionScalars->Delete(); + } + + // Clean up and update output + triMesh->UnRegister(this); + this->Mesh->Delete(); + neighbors->Delete(); + edgeIds->Delete(); + loopIds->Delete(); + cellMarks->Delete(); + pointMarks->Delete(); + currentFront->Delete(); + nextFront->Delete(); + + return 1; +} + +void vtkSelectPolyData::GetPointNeighbors (vtkIdType ptId, vtkIdList *nei) +{ + unsigned short ncells; + int i, j; + vtkIdType *cells, *pts, npts; + + nei->Reset(); + this->Mesh->GetPointCells(ptId, ncells, cells); + for (i=0; iMesh->GetCellPoints(cells[i], npts, pts); + for (j=0; j<3; j++) + { + if ( pts[j] != ptId ) + { + nei->InsertUniqueId(pts[j]); + } + } + } +} + +unsigned long int vtkSelectPolyData::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Loop != NULL ) + { + time = this->Loop->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +void vtkSelectPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Generate Unselected Output: " + << (this->GenerateUnselectedOutput ? "On\n" : "Off\n"); + + os << indent << "Inside Mode: "; + os << this->GetSelectionModeAsString() << "\n"; + + os << indent << "Closest Point: (" << this->ClosestPoint[0] << ", " + << this->ClosestPoint[1] << ", " << this->ClosestPoint[2] << ")\n"; + + os << indent << "Generate Selection Scalars: " + << (this->GenerateSelectionScalars ? "On\n" : "Off\n"); + + os << indent << "Inside Out: " << (this->InsideOut ? "On\n" : "Off\n"); + + if ( this->Loop ) + { + os << indent << "Loop of " << this->Loop->GetNumberOfPoints() + << "points defined\n"; + } + else + { + os << indent << "Loop not defined\n"; + } +} + diff --git a/Graphics/vtkSelectPolyData.h b/Graphics/vtkSelectPolyData.h new file mode 100644 index 0000000..aa87db1 --- /dev/null +++ b/Graphics/vtkSelectPolyData.h @@ -0,0 +1,195 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSelectPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSelectPolyData - select portion of polygonal mesh; generate selection scalars +// .SECTION Description +// vtkSelectPolyData is a filter that selects polygonal data based on +// defining a "loop" and indicating the region inside of the loop. The +// mesh within the loop consists of complete cells (the cells are not +// cut). Alternatively, this filter can be used to generate scalars. +// These scalar values, which are a distance measure to the loop, can +// be used to clip, contour. or extract data (i.e., anything that an +// implicit function can do). +// +// The loop is defined by an array of x-y-z point coordinates. +// (Coordinates should be in the same coordinate space as the input +// polygonal data.) The loop can be concave and non-planar, but not +// self-intersecting. The input to the filter is a polygonal mesh +// (only surface primitives such as triangle strips and polygons); the +// output is either a) a portion of the original mesh laying within +// the selection loop (GenerateSelectionScalarsOff); or b) the same +// polygonal mesh with the addition of scalar values +// (GenerateSelectionScalarsOn). +// +// The algorithm works as follows. For each point coordinate in the +// loop, the closest point in the mesh is found. The result is a loop +// of closest point ids from the mesh. Then, the edges in the mesh +// connecting the closest points (and laying along the lines forming +// the loop) are found. A greedy edge tracking procedure is used as +// follows. At the current point, the mesh edge oriented in the +// direction of and whose end point is closest to the line is +// chosen. The edge is followed to the new end point, and the +// procedure is repeated. This process continues until the entire loop +// has been created. +// +// To determine what portion of the mesh is inside and outside of the +// loop, three options are possible. 1) the smallest connected region, +// 2) the largest connected region, and 3) the connected region +// closest to a user specified point. (Set the ivar SelectionMode.) +// +// Once the loop is computed as above, the GenerateSelectionScalars +// controls the output of the filter. If on, then scalar values are +// generated based on distance to the loop lines. Otherwise, the cells +// laying inside the selection loop are output. By default, the mesh +// lying within the loop is output; however, if InsideOut is on, then +// the portion of the mesh lying outside of the loop is output. +// +// The filter can be configured to generate the unselected portions of +// the mesh as output by setting GenerateUnselectedOutput. Use the +// method GetUnselectedOutput to access this output. (Note: this flag +// is pertinent only when GenerateSelectionScalars is off.) + +// .SECTION Caveats +// Make sure that the points you pick are on a connected surface. If +// not, then the filter will generate an empty or partial result. Also, +// self-intersecting loops will generate unpredictable results. +// +// During processing of the data, non-triangular cells are converted to +// triangles if GenerateSelectionScalars is off. + +// .SECTION See Also +// vtkImplicitSelectionLoop + +#ifndef __vtkSelectPolyData_h +#define __vtkSelectPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_INSIDE_SMALLEST_REGION 0 +#define VTK_INSIDE_LARGEST_REGION 1 +#define VTK_INSIDE_CLOSEST_POINT_REGION 2 + +class vtkCharArray; +class vtkPoints; +class vtkIdList; + +class VTK_GRAPHICS_EXPORT vtkSelectPolyData : public vtkPolyDataAlgorithm +{ +public: + // Description: + // Instantiate object with InsideOut turned off, and + // GenerateSelectionScalars turned off. The unselected output + // is not generated, and the inside mode is the smallest region. + static vtkSelectPolyData *New(); + + vtkTypeRevisionMacro(vtkSelectPolyData,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the flag to control behavior of the filter. If + // GenerateSelectionScalars is on, then the output of the filter + // is the same as the input, except that scalars are generated. + // If off, the filter outputs the cells laying inside the loop, and + // does not generate scalars. + vtkSetMacro(GenerateSelectionScalars,int); + vtkGetMacro(GenerateSelectionScalars,int); + vtkBooleanMacro(GenerateSelectionScalars,int); + + // Description: + // Set/Get the InsideOut flag. When off, the mesh within the loop is + // extracted. When on, the mesh outside the loop is extracted. + vtkSetMacro(InsideOut,int); + vtkGetMacro(InsideOut,int); + vtkBooleanMacro(InsideOut,int); + + // Description: + // Set/Get the array of point coordinates defining the loop. There must + // be at least three points used to define a loop. + virtual void SetLoop(vtkPoints*); + vtkGetObjectMacro(Loop,vtkPoints); + + // Description: + // Control how inside/outside of loop is defined. + vtkSetClampMacro(SelectionMode,int, + VTK_INSIDE_SMALLEST_REGION,VTK_INSIDE_CLOSEST_POINT_REGION); + vtkGetMacro(SelectionMode,int); + void SetSelectionModeToSmallestRegion() + {this->SetSelectionMode(VTK_INSIDE_SMALLEST_REGION);}; + void SetSelectionModeToLargestRegion() + {this->SetSelectionMode(VTK_INSIDE_LARGEST_REGION);}; + void SetSelectionModeToClosestPointRegion() + {this->SetSelectionMode(VTK_INSIDE_CLOSEST_POINT_REGION);}; + const char *GetSelectionModeAsString(); + + // Description: + // Control whether a second output is generated. The second output + // contains the polygonal data that's not been selected. + vtkSetMacro(GenerateUnselectedOutput,int); + vtkGetMacro(GenerateUnselectedOutput,int); + vtkBooleanMacro(GenerateUnselectedOutput,int); + + // Description: + // Return output that hasn't been selected (if GenreateUnselectedOutput is + // enabled). + vtkPolyData *GetUnselectedOutput(); + + // Description: + // Return the (mesh) edges of the selection region. + vtkPolyData *GetSelectionEdges(); + + // Overload GetMTime() because we depend on Loop + unsigned long int GetMTime(); + +protected: + vtkSelectPolyData(); + ~vtkSelectPolyData(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int GenerateSelectionScalars; + int InsideOut; + vtkPoints *Loop; + int SelectionMode; + double ClosestPoint[3]; + int GenerateUnselectedOutput; + +private: + vtkPolyData *Mesh; + void GetPointNeighbors (vtkIdType ptId, vtkIdList *nei); +private: + vtkSelectPolyData(const vtkSelectPolyData&); // Not implemented. + void operator=(const vtkSelectPolyData&); // Not implemented. +}; + +// Description: +// Return the method of determining in/out of loop as a string. +inline const char *vtkSelectPolyData::GetSelectionModeAsString(void) +{ + if ( this->SelectionMode == VTK_INSIDE_SMALLEST_REGION ) + { + return "InsideSmallestRegion"; + } + else if ( this->SelectionMode == VTK_INSIDE_LARGEST_REGION ) + { + return "InsideLargestRegion"; + } + else + { + return "InsideClosestPointRegion"; + } +} + +#endif + + diff --git a/Graphics/vtkShrinkFilter.cxx b/Graphics/vtkShrinkFilter.cxx new file mode 100644 index 0000000..d26c2a0 --- /dev/null +++ b/Graphics/vtkShrinkFilter.cxx @@ -0,0 +1,171 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShrinkFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkShrinkFilter.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkSmartPointer.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkShrinkFilter, "$Revision: 1.64.12.2 $"); +vtkStandardNewMacro(vtkShrinkFilter); + +//---------------------------------------------------------------------------- +vtkShrinkFilter::vtkShrinkFilter() +{ + this->ShrinkFactor = 0.5; +} + +//---------------------------------------------------------------------------- +vtkShrinkFilter::~vtkShrinkFilter() +{ +} + +//---------------------------------------------------------------------------- +void vtkShrinkFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Shrink Factor: " << this->ShrinkFactor << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkShrinkFilter::FillInputPortInformation(int, vtkInformation* info) +{ + // This filter uses the vtkDataSet cell traversal methods so it + // suppors any data set type as input. + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkShrinkFilter::RequestData(vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // Get input and output data. + vtkDataSet* input = vtkDataSet::GetData(inputVector[0]); + vtkUnstructuredGrid* output = vtkUnstructuredGrid::GetData(outputVector); + + // We are now executing this filter. + vtkDebugMacro("Shrinking cells"); + + // Skip execution if there is no input geometry. + vtkIdType numCells = input->GetNumberOfCells(); + vtkIdType numPts = input->GetNumberOfPoints(); + if(numCells < 1 || numPts < 1) + { + vtkDebugMacro("No data to shrink!"); + return 1; + } + + // Allocate working space for new and old cell point lists. + vtkSmartPointer ptIds = vtkSmartPointer::New(); + vtkSmartPointer newPtIds = vtkSmartPointer::New(); + ptIds->Allocate(VTK_CELL_SIZE); + newPtIds->Allocate(VTK_CELL_SIZE); + + // Allocate approximately the space needed for the output cells. + output->Allocate(numCells); + + // Allocate space for a new set of points. + vtkSmartPointer newPts = vtkSmartPointer::New(); + newPts->Allocate(numPts*8, numPts); + + // Allocate space for data associated with the new set of points. + vtkPointData* inPD = input->GetPointData(); + vtkPointData* outPD = output->GetPointData(); + outPD->CopyAllocate(inPD, numPts*8, numPts); + + // Support progress and abort. + vtkIdType tenth = (numCells >= 10? numCells/10 : 1); + double numCellsInv = 1.0/numCells; + int abort = 0; + + // Traverse all cells, obtaining node coordinates. Compute "center" + // of cell, then create new vertices shrunk towards center. + for(vtkIdType cellId = 0; cellId < numCells && !abort; ++cellId) + { + // Get the list of points for this cell. + input->GetCellPoints(cellId, ptIds); + vtkIdType numIds = ptIds->GetNumberOfIds(); + + // Periodically update progress and check for an abort request. + if(cellId % tenth == 0) + { + this->UpdateProgress((cellId+1)*numCellsInv); + abort = this->GetAbortExecute(); + } + + // Compute the center of mass of the cell points. + double center[3] = {0,0,0}; + for(vtkIdType i=0; i < numIds; ++i) + { + double p[3]; + input->GetPoint(ptIds->GetId(i), p); + for(int j=0; j < 3; ++j) + { + center[j] += p[j]; + } + } + for(int j=0; j < 3; ++j) + { + center[j] /= numIds; + } + + // Create new points for this cell. + newPtIds->Reset(); + for(vtkIdType i=0; i < numIds; ++i) + { + // Get the old point location. + double p[3]; + input->GetPoint(ptIds->GetId(i), p); + + // Compute the new point location. + double newPt[3]; + for(int j=0; j < 3; ++j) + { + newPt[j] = center[j] + this->ShrinkFactor*(p[j] - center[j]); + } + + // Create the new point for this cell. + vtkIdType newId = newPts->InsertNextPoint(newPt); + newPtIds->InsertId(i, newId); + + // Copy point data from the old point. + vtkIdType oldId = ptIds->GetId(i); + outPD->CopyData(inPD, oldId, newId); + } + + // Store the new cell in the output. + output->InsertNextCell(input->GetCellType(cellId), newPtIds); + } + + // Store the new set of points in the output. + output->SetPoints(newPts); + + // Just pass cell data through because we still have the same number + // and type of cells. + output->GetCellData()->PassData(input->GetCellData()); + + // Avoid keeping extra memory around. + output->Squeeze(); + + return 1; +} diff --git a/Graphics/vtkShrinkFilter.h b/Graphics/vtkShrinkFilter.h new file mode 100644 index 0000000..d9d0b53 --- /dev/null +++ b/Graphics/vtkShrinkFilter.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShrinkFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkShrinkFilter - shrink cells composing an arbitrary data set +// .SECTION Description +// vtkShrinkFilter shrinks cells composing an arbitrary data set +// towards their centroid. The centroid of a cell is computed as the +// average position of the cell points. Shrinking results in +// disconnecting the cells from one another. The output of this filter +// is of general dataset type vtkUnstructuredGrid. + +// .SECTION Caveats +// It is possible to turn cells inside out or cause self intersection +// in special cases. + +// .SECTION See Also +// vtkShrinkPolyData + +#ifndef __vtkShrinkFilter_h +#define __vtkShrinkFilter_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkShrinkFilter : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkShrinkFilter *New(); + vtkTypeRevisionMacro(vtkShrinkFilter,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get/Set the fraction of shrink for each cell. + vtkSetClampMacro(ShrinkFactor, double, 0.0, 1.0); + vtkGetMacro(ShrinkFactor, double); + +protected: + vtkShrinkFilter(); + ~vtkShrinkFilter(); + + // Override to specify support for any vtkDataSet input type. + virtual int FillInputPortInformation(int port, vtkInformation* info); + + // Main implementation. + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + double ShrinkFactor; + +private: + vtkShrinkFilter(const vtkShrinkFilter&); // Not implemented. + void operator=(const vtkShrinkFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkShrinkPolyData.cxx b/Graphics/vtkShrinkPolyData.cxx new file mode 100644 index 0000000..c7d1b2d --- /dev/null +++ b/Graphics/vtkShrinkPolyData.cxx @@ -0,0 +1,316 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShrinkPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkShrinkPolyData.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkShrinkPolyData, "$Revision: 1.69 $"); +vtkStandardNewMacro(vtkShrinkPolyData); + +vtkShrinkPolyData::vtkShrinkPolyData(double sf) +{ + sf = ( sf < 0.0 ? 0.0 : (sf > 1.0 ? 1.0 : sf)); + this->ShrinkFactor = sf; +} + +template +void vtkShrinkPolyDataExecute(vtkShrinkPolyData *self, T *inPts, + double shrinkFactor, + vtkInformation *inInfo, vtkInformation *outInfo) +{ + int j, k; + T center[3]; + int abortExecute=0; + vtkCellArray *newVerts, *newLines, *newPolys; + vtkPointData *pd; + vtkCellArray *inVerts,*inLines,*inPolys,*inStrips; + vtkIdType numNewPts, numNewLines, numNewPolys, polyAllocSize; + vtkIdType npts = 0; + vtkIdType *pts = 0; + vtkIdType newIds[3]; + vtkPoints *newPoints; + T *p1, *p2, *p3; + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output= vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointData *pointData = output->GetPointData(); + + pd = input->GetPointData(); + + inVerts = input->GetVerts(); + inLines = input->GetLines(); + inPolys = input->GetPolys(); + inStrips = input->GetStrips(); + + // Count the number of new points and other primitives that + // need to be created. + // + numNewPts = input->GetNumberOfVerts(); + numNewLines = 0; + numNewPolys = 0; + polyAllocSize = 0; + + for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); ) + { + numNewPts += (npts-1) * 2; + numNewLines += npts - 1; + } + for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + numNewPts += npts; + numNewPolys++; + polyAllocSize += npts + 1; + } + for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + numNewPts += (npts-2) * 3; + polyAllocSize += (npts - 2) * 4; + } + + // Allocate + // + newVerts = vtkCellArray::New(); + newVerts->Allocate(input->GetNumberOfVerts()); + + newLines = vtkCellArray::New(); + newLines->Allocate(numNewLines*3); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(polyAllocSize); + + pointData->CopyAllocate(pd); + + newPoints = input->GetPoints()->NewInstance(); + newPoints->SetDataType(input->GetPoints()->GetDataType()); + newPoints->Allocate(numNewPts); + newPoints->SetNumberOfPoints(numNewPts); + T *outPts = (T *)newPoints->GetVoidPointer(0); + vtkIdType outCount = 0; + + // Copy vertices (no shrinking necessary) + // + for (inVerts->InitTraversal(); + inVerts->GetNextCell(npts,pts) && !abortExecute; ) + { + newVerts->InsertNextCell(npts); + for (j=0; jInsertCellPoint(outCount); + pointData->CopyData(pd,pts[j],outCount); + outCount++; + } + abortExecute = self->GetAbortExecute(); + } + self->UpdateProgress (0.10); + + // Lines need to be shrunk, and if polyline, split into separate pieces + // + for (inLines->InitTraversal(); + inLines->GetNextCell(npts,pts) && !abortExecute; ) + { + for (j=0; j<(npts-1); j++) + { + p1 = inPts + pts[j]*3; + p2 = inPts + pts[j+1]*3; + for (k=0; k<3; k++) + { + center[k] = (p1[k] + p2[k]) / 2; + } + + for (k=0; k<3; k++) + { + outPts[k] = (T)(center[k] + shrinkFactor*(p1[k] - center[k])); + } + outPts += 3; + pointData->CopyData(pd,pts[j],outCount); + outCount++; + + for (k=0; k<3; k++) + { + outPts[k] = (T)(center[k] + shrinkFactor*(p2[k] - center[k])); + } + outPts += 3; + pointData->CopyData(pd,pts[j+1],outCount); + newIds[0] = outCount - 1; + newIds[1] = outCount; + newLines->InsertNextCell(2,newIds); + outCount++; + } + abortExecute = self->GetAbortExecute(); + } + self->UpdateProgress (0.25); + + // Polygons need to be shrunk + // + for (inPolys->InitTraversal(); + inPolys->GetNextCell(npts,pts) && !abortExecute; ) + { + for (center[0]=center[1]=center[2]=0, j=0; jInsertNextCell(npts); + for (j=0; jInsertCellPoint(outCount); + pointData->CopyData(pd,pts[j],outCount); + outCount++; + } + abortExecute = self->GetAbortExecute(); + } + self->UpdateProgress (0.75); + + // Triangle strips need to be shrunk and split into separate pieces. + // + vtkIdType tmp; + for (inStrips->InitTraversal(); + inStrips->GetNextCell(npts,pts) && !abortExecute; ) + { + for (j=0; j<(npts-2); j++) + { + p1 = inPts + pts[j]*3; + p2 = inPts + pts[j+1]*3; + p3 = inPts + pts[j+2]*3; + for (k=0; k<3; k++) + { + center[k] = (p1[k] + p2[k] + p3[k]) / 3; + } + + for (k=0; k<3; k++) + { + outPts[k] = (T)(center[k] + shrinkFactor*(p1[k] - center[k])); + } + outPts += 3; + pointData->CopyData(pd,pts[j],outCount); + newIds[0] = outCount; + outCount++; + + for (k=0; k<3; k++) + { + outPts[k] = (T)(center[k] + shrinkFactor*(p2[k] - center[k])); + } + outPts += 3; + pointData->CopyData(pd,pts[j+1],outCount); + newIds[1] = outCount; + outCount++; + + for (k=0; k<3; k++) + { + outPts[k] = (T)(center[k] + shrinkFactor*(p3[k] - center[k])); + } + outPts += 3; + pointData->CopyData(pd,pts[j+2],outCount); + newIds[1] = outCount; + outCount++; + + // must reverse order for every other triangle + if (j%2) + { + tmp = newIds[0]; + newIds[0] = newIds[2]; + newIds[2] = tmp; + } + newPolys->InsertNextCell(3,newIds); + } + abortExecute = self->GetAbortExecute(); + } + + // Update self and release memory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + output->SetVerts(newVerts); + newVerts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + output->GetCellData()->PassData(input->GetCellData()); +} + +int vtkShrinkPolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Initialize + vtkDebugMacro(<<"Shrinking polygonal data"); + + if (input == NULL || input->GetPoints() == NULL) + { + return 1; + } + + // get the input pointer for templating + void *inPtr = input->GetPoints()->GetVoidPointer(0); + + // call templated function + switch (input->GetPoints()->GetDataType()) + { + vtkTemplateMacro( + vtkShrinkPolyDataExecute(this, + (VTK_TT *)(inPtr), this->ShrinkFactor, + inInfo, outInfo)); + default: + break; + } + + return 1; +} + +void vtkShrinkPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Shrink Factor: " << this->ShrinkFactor << "\n"; +} diff --git a/Graphics/vtkShrinkPolyData.h b/Graphics/vtkShrinkPolyData.h new file mode 100644 index 0000000..748548e --- /dev/null +++ b/Graphics/vtkShrinkPolyData.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShrinkPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkShrinkPolyData - shrink cells composing PolyData +// .SECTION Description +// vtkShrinkPolyData shrinks cells composing a polygonal dataset (e.g., +// vertices, lines, polygons, and triangle strips) towards their centroid. +// The centroid of a cell is computed as the average position of the +// cell points. Shrinking results in disconnecting the cells from +// one another. The output dataset type of this filter is polygonal data. +// +// During execution the filter passes its input cell data to its +// output. Point data attributes are copied to the points created during the +// shrinking process. + +// .SECTION Caveats +// It is possible to turn cells inside out or cause self intersection +// in special cases. +// Users should use the vtkTriangleFilter to triangulate meshes that +// contain triangle strips. + +// .SECTION See Also +// vtkShrinkFilter + +#ifndef __vtkShrinkPolyData_h +#define __vtkShrinkPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkShrinkPolyData : public vtkPolyDataAlgorithm +{ +public: + static vtkShrinkPolyData *New(); + vtkTypeRevisionMacro(vtkShrinkPolyData,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the fraction of shrink for each cell. + vtkSetClampMacro(ShrinkFactor,double,0.0,1.0); + + // Description: + // Get the fraction of shrink for each cell. + vtkGetMacro(ShrinkFactor,double); + +protected: + vtkShrinkPolyData(double sf=0.5); + ~vtkShrinkPolyData() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double ShrinkFactor; +private: + vtkShrinkPolyData(const vtkShrinkPolyData&); // Not implemented. + void operator=(const vtkShrinkPolyData&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkSimpleElevationFilter.cxx b/Graphics/vtkSimpleElevationFilter.cxx new file mode 100644 index 0000000..5a3a76e --- /dev/null +++ b/Graphics/vtkSimpleElevationFilter.cxx @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleElevationFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSimpleElevationFilter.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkSimpleElevationFilter, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkSimpleElevationFilter); + +// Construct object with LowPoint=(0,0,0) and HighPoint=(0,0,1). Scalar +// range is (0,1). +vtkSimpleElevationFilter::vtkSimpleElevationFilter() +{ + this->Vector[0] = 0.0; + this->Vector[1] = 0.0; + this->Vector[2] = 1.0; +} + +// Convert position along ray into scalar value. Example use includes +// coloring terrain by elevation. +// +int vtkSimpleElevationFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType i, numPts; + vtkFloatArray *newScalars; + double s, x[3]; + + // Initialize + // + vtkDebugMacro(<<"Generating elevation scalars!"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( ((numPts=input->GetNumberOfPoints()) < 1) ) + { + vtkDebugMacro(<< "No input!"); + return 1; + } + + // Allocate + // + newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfTuples(numPts); + + // Set up 1D parametric system + // + if ( vtkMath::Dot(this->Vector,this->Vector) == 0.0) + { + vtkErrorMacro(<< "Bad vector, using (0,0,1)"); + this->Vector[0] = this->Vector[1] = 0.0; this->Vector[2] = 1.0; + } + + // Compute dot product + // + int abort=0; + vtkIdType progressInterval=numPts/20 + 1; + for (i=0; iUpdateProgress ((double)i/numPts); + abort = this->GetAbortExecute(); + } + + input->GetPoint(i,x); + s = vtkMath::Dot(this->Vector,x); + newScalars->SetComponent(i,0,s); + } + + // Update self + // + output->GetPointData()->CopyScalarsOff(); + output->GetPointData()->PassData(input->GetPointData()); + + output->GetCellData()->PassData(input->GetCellData()); + + newScalars->SetName("Elevation"); + output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveScalars(newScalars->GetName()); + newScalars->Delete(); + + return 1; +} + +void vtkSimpleElevationFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Vector: (" << this->Vector[0] << ", " + << this->Vector[1] << ", " << this->Vector[2] << ")\n"; +} diff --git a/Graphics/vtkSimpleElevationFilter.h b/Graphics/vtkSimpleElevationFilter.h new file mode 100644 index 0000000..4656e41 --- /dev/null +++ b/Graphics/vtkSimpleElevationFilter.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleElevationFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSimpleElevationFilter - generate scalars along a specified direction +// .SECTION Description +// vtkSimpleElevationFilter is a filter to generate scalar values from a +// dataset. The scalar values are generated by dotting a user-specified +// vector against a vector defined from the input dataset points to the +// origin. +// .SECTION See Also +// vtkElevationFilter + +#ifndef __vtkSimpleElevationFilter_h +#define __vtkSimpleElevationFilter_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkSimpleElevationFilter : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSimpleElevationFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with Vector=(0,0,1); + static vtkSimpleElevationFilter *New(); + + // Description: + // Define one end of the line (small scalar values). + vtkSetVector3Macro(Vector,double); + vtkGetVectorMacro(Vector,double,3); + +protected: + vtkSimpleElevationFilter(); + ~vtkSimpleElevationFilter() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double Vector[3]; +private: + vtkSimpleElevationFilter(const vtkSimpleElevationFilter&); // Not implemented. + void operator=(const vtkSimpleElevationFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkSliceCubes.cxx b/Graphics/vtkSliceCubes.cxx new file mode 100644 index 0000000..165f7b8 --- /dev/null +++ b/Graphics/vtkSliceCubes.cxx @@ -0,0 +1,620 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSliceCubes.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSliceCubes.h" + +#include "vtkByteSwap.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMarchingCubesCases.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkShortArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" +#include "vtkVolumeReader.h" + +vtkCxxRevisionMacro(vtkSliceCubes, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkSliceCubes); + +vtkCxxSetObjectMacro(vtkSliceCubes,Reader,vtkVolumeReader); + +// Description: +// Construct with NULL reader, output FileName specification, and limits +// FileName. +vtkSliceCubes::vtkSliceCubes() +{ + this->Reader = NULL; + this->FileName = NULL; + this->LimitsFileName = NULL; + this->Value = 0.0; +} + +vtkSliceCubes::~vtkSliceCubes() +{ + if (this->FileName) + { + delete [] this->FileName; + } + if (this->LimitsFileName) + { + delete [] this->LimitsFileName; + } + this->SetReader(NULL); +} + +// Description: +// Method causes object to read slices and generate isosurface. +void vtkSliceCubes::Update() +{ + this->Execute(); +} + +// Calculate the gradient using central difference. +// NOTE: We calculate the negative of the gradient for efficiency +template +void ComputePointGradient(int i, int j, int k, int dims[3], + double Spacing[3], double n[3], T *s0, T *s1, T *s2) +{ + double sp, sm; + + // x-direction + if ( i == 0 ) + { + sp = s1[i+1 + j*dims[0]]; + sm = s1[i + j*dims[0]]; + n[0] = (sm - sp) / Spacing[0]; + } + else if ( i == (dims[0]-1) ) + { + sp = s1[i + j*dims[0]]; + sm = s1[i-1 + j*dims[0]]; + n[0] = (sm - sp) / Spacing[0]; + } + else + { + sp = s1[i+1 + j*dims[0]]; + sm = s1[i-1 + j*dims[0]]; + n[0] = 0.5 * (sm - sp) / Spacing[0]; + } + + // y-direction + if ( j == 0 ) + { + sp = s1[i + (j+1)*dims[0]]; + sm = s1[i + j*dims[0]]; + n[1] = (sm - sp) / Spacing[1]; + } + else if ( j == (dims[1]-1) ) + { + sp = s1[i + j*dims[0]]; + sm = s1[i + (j-1)*dims[0]]; + n[1] = (sm - sp) / Spacing[1]; + } + else + + { + sp = s1[i + (j+1)*dims[0]]; + sm = s1[i + (j-1)*dims[0]]; + n[1] = 0.5 * (sm - sp) / Spacing[1]; + } + + // z-direction + // z-direction + if ( k == 0 ) + { + sp = s2[i + j*dims[0]]; + sm = s1[i + j*dims[0]]; + n[2] = (sm - sp) / Spacing[2]; + } + else if ( k == (dims[2]-1) ) + { + sp = s1[i + j*dims[0]]; + sm = s0[i + j*dims[0]]; + n[2] = (sm - sp) / Spacing[2]; + } + else + { + sp = s2[i + j*dims[0]]; + sm = s0[i + j*dims[0]]; + n[2] = 0.5 * (sm - sp) / Spacing[2]; + } +} + +template +int vtkSliceCubesContour(T *slice, S *scalars, int imageRange[2], int dims[3], + double origin[3], double Spacing[3], double value, + double xmin[3], double xmax[3], FILE *outFP, + vtkVolumeReader *reader, unsigned char debug) +{ + S *slice0scalars=NULL, *slice1scalars; + S *slice2scalars, *slice3scalars; + T *slice0, *slice1, *slice2, *slice3; + vtkImageData *sp; + vtkDoubleArray *doubleScalars=NULL; + int numTriangles=0, numComp = 0; + double s[8]; + int i, j, k, idx, jOffset, ii, index, *vert, jj, sliceSize=0; + static int CASE_MASK[8] = {1,2,4,8,16,32,64,128}; + vtkMarchingCubesTriangleCases *triCase, *triCases; + EDGE_LIST *edge; + double pts[8][3], grad[8][3]; + double t, *x1, *x2, *n1, *n2; + double xp, yp, zp; + float point[6]; + static int edges[12][2] = { {0,1}, {1,2}, {3,2}, {0,3}, + {4,5}, {5,6}, {7,6}, {4,7}, + {0,4}, {1,5}, {3,7}, {2,6}}; + + triCases = vtkMarchingCubesTriangleCases::GetCases(); + + if ( slice == NULL ) //have to do conversion to double slice-by-slice + { + sliceSize = dims[0] * dims[1]; + doubleScalars = vtkDoubleArray::New(); + doubleScalars->Allocate(sliceSize); + } + + slice1scalars = NULL; + slice2scalars = scalars; + slice2scalars->Register(NULL); + + if (debug) vtkGenericWarningMacro(<< " Slice# " << imageRange[0]); + + if ( slice2scalars == NULL ) + { + return 0; + } + if ( slice != NULL ) + { + slice1 = slice2 = slice2scalars->GetPointer(0); + } + else + {//get as double + numComp = scalars->GetNumberOfComponents(); + slice2scalars->GetData(0,sliceSize-1,0,numComp-1,doubleScalars); + slice1 = slice2 = (T *) doubleScalars->GetPointer(0); + } + + sp = reader->GetImage(imageRange[0]+1); + slice3scalars = (S *) sp->GetPointData()->GetScalars(); + slice3scalars->Register(NULL); + sp->Delete(); + + if (debug) vtkGenericWarningMacro(<< " Slice# " << imageRange[0]+1 ); + + if ( slice != NULL ) + { + slice3 = slice3scalars->GetPointer(0); + } + else + {//get as double: cast is ok because this code is only executed for double type + slice3scalars->GetData(0,sliceSize-1,0,numComp-1,doubleScalars); + slice3 = (T *) doubleScalars->GetPointer(0); + } + + if ( !slice2 || !slice3 ) + { + vtkGenericWarningMacro(<< "Cannot allocate data!"); + return 0; + } + + // Generate triangles and normals from slices + for (k=0; k < (dims[2]-1); k++) + { + + // swap things around + if ( slice0scalars != NULL ) + { + slice0scalars->Delete(); + } + slice0scalars = slice1scalars; + slice0 = slice1; + slice1scalars = slice2scalars; + slice1 = slice2; + slice2scalars = slice3scalars; + slice2 = slice3; + if ( k < (dims[2]-2) ) + { + if (debug) vtkGenericWarningMacro(<< " Slice# " << imageRange[0]+k+2); + sp = reader->GetImage(imageRange[0]+k+2); + slice3scalars = (S *) sp->GetPointData()->GetScalars(); + if ( slice3scalars == NULL ) + { + vtkGenericWarningMacro(<< "Can't read all the requested slices"); + goto PREMATURE_TERMINATION; + } + slice3scalars->Register(NULL); + sp->Delete(); + if ( slice != NULL ) + { + slice3 = slice3scalars->GetPointer(0); + } + else + {//get as double + slice3scalars->GetData(0,sliceSize-1,0,numComp-1,doubleScalars); + slice3 = (T *) doubleScalars->GetPointer(0); + } + } + + pts[0][2] = origin[2] + k*Spacing[2]; + zp = origin[2] + (k+1)*Spacing[2]; + for ( j=0; j < (dims[1]-1); j++) + { + jOffset = j*dims[0]; + pts[0][1] = origin[1] + j*Spacing[1]; + yp = origin[1] + (j+1)*Spacing[1]; + for ( i=0; i < (dims[0]-1); i++) + { + //get scalar values + idx = i + jOffset; + s[0] = slice1[idx]; + s[1] = slice1[idx+1]; + s[2] = slice1[idx+1 + dims[0]]; + s[3] = slice1[idx + dims[0]]; + s[4] = slice2[idx]; + s[5] = slice2[idx+1]; + s[6] = slice2[idx+1 + dims[0]]; + s[7] = slice2[idx + dims[0]]; + + // Build the case table + for ( ii=0, index = 0; ii < 8; ii++) + { + if ( s[ii] >= value ) + { + index |= CASE_MASK[ii]; + } + } + + if ( index == 0 || index == 255 ) // no surface + { + continue; + } + //create voxel points + pts[0][0] = origin[0] + i*Spacing[0]; + xp = origin[0] + (i+1)*Spacing[0]; + + pts[1][0] = xp; + pts[1][1] = pts[0][1]; + pts[1][2] = pts[0][2]; + + pts[2][0] = xp; + pts[2][1] = yp; + pts[2][2] = pts[0][2]; + + pts[3][0] = pts[0][0]; + pts[3][1] = yp; + pts[3][2] = pts[0][2]; + + pts[4][0] = pts[0][0]; + pts[4][1] = pts[0][1]; + pts[4][2] = zp; + + pts[5][0] = xp; + pts[5][1] = pts[0][1]; + pts[5][2] = zp; + + pts[6][0] = xp; + pts[6][1] = yp; + pts[6][2] = zp; + + pts[7][0] = pts[0][0]; + pts[7][1] = yp; + pts[7][2] = zp; + + //create gradients + ComputePointGradient(i,j, k, dims, Spacing, grad[0], + slice0, slice1, slice2); + ComputePointGradient(i+1,j, k, dims, Spacing, grad[1], + slice0, slice1, slice2); + ComputePointGradient(i+1,j+1, k, dims, Spacing, grad[2], + slice0, slice1, slice2); + ComputePointGradient(i,j+1, k, dims, Spacing, grad[3], + slice0, slice1, slice2); + ComputePointGradient(i,j, k+1, dims, Spacing, grad[4], + slice1, slice2, slice3); + ComputePointGradient(i+1,j, k+1, dims, Spacing, grad[5], + slice1, slice2, slice3); + ComputePointGradient(i+1,j+1, k+1, dims, Spacing, grad[6], + slice1, slice2, slice3); + ComputePointGradient(i,j+1, k+1, dims, Spacing, grad[7], + slice1, slice2, slice3); + + triCase = triCases + index; + edge = triCase->edges; + + for ( ; edge[0] > -1; edge += 3 ) + { + for (ii=0; ii<3; ii++) //insert triangle + { + vert = edges[edge[ii]]; + t = (value - s[vert[0]]) / (s[vert[1]] - s[vert[0]]); + x1 = pts[vert[0]]; + x2 = pts[vert[1]]; + n1 = grad[vert[0]]; + n2 = grad[vert[1]]; + for (jj=0; jj<3; jj++) + { + point[jj] = x1[jj] + t * (x2[jj] - x1[jj]); + point[jj+3] = n1[jj] + t * (n2[jj] - n1[jj]); + if (point[jj] < xmin[jj] ) + { + xmin[jj] = point[jj]; + } + if (point[jj] > xmax[jj] ) + { + xmax[jj] = point[jj]; + } + } + vtkMath::Normalize(point+3); + // swap bytes if necessary + vtkByteSwap::SwapWrite4BERange(point,6,outFP); + } + numTriangles++; + }//for each triangle + }//for i + }//for j + }//for k + + // Close things down + PREMATURE_TERMINATION: + + fclose(outFP); + if ( slice == NULL ) + { + doubleScalars->Delete(); + } + if (slice0scalars && slice0scalars != slice1scalars) + { + slice0scalars->Delete(); + } + if (slice3scalars && slice3scalars != slice2scalars) + { + slice3scalars->Delete(); + } + slice1scalars->Delete(); + slice2scalars->Delete(); + + return numTriangles; +} + +void vtkSliceCubes::Execute() +{ + FILE *outFP; + vtkImageData *tempStructPts; + vtkDataArray *inScalars; + int dims[3], imageRange[2]; + double xmin[3], xmax[3]; + double origin[3], Spacing[3]; + int numTriangles = 0; + + // check input/initalize + vtkDebugMacro(<< "Executing slice cubes"); + if ( this->Reader == NULL ) + { + vtkErrorMacro(<<"No reader specified...can't generate isosurface"); + return; + } + + if ( this->FileName == NULL ) + { + vtkErrorMacro(<<"No FileName specified...can't output isosurface"); + return; + } + + if ( (outFP = fopen(this->FileName, "wb")) == NULL ) + { + vtkErrorMacro(<<"Cannot open specified output file..."); + return; + } + + // get image dimensions from the readers first slice + this->Reader->GetImageRange(imageRange); + tempStructPts = this->Reader->GetImage(imageRange[0]); + tempStructPts->GetDimensions(dims); + tempStructPts->GetOrigin(origin); + tempStructPts->GetSpacing(Spacing); + + dims[2] = (imageRange[1] - imageRange[0] + 1); + + if ( (dims[0]*dims[1]*dims[2]) <= 1 || dims[2] < 2 ) + { + vtkErrorMacro(<<"Bad dimensions...slice must be 3D volume"); + return; + } + + xmin[0]=xmin[1]=xmin[2] = VTK_DOUBLE_MAX; + xmax[0]=xmax[1]=xmax[2] = -VTK_DOUBLE_MAX; + + inScalars = tempStructPts->GetPointData()->GetScalars(); + if ( inScalars == NULL ) + { + vtkErrorMacro(<<"Must have scalars to generate isosurface"); + tempStructPts->Delete(); + return; + } + inScalars->Register(this); + tempStructPts->Delete(); + + if (inScalars->GetNumberOfComponents() == 1 ) + { + switch (inScalars->GetDataType()) + { + case VTK_CHAR: + { + vtkCharArray *scalars = (vtkCharArray *)inScalars; + char *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_UNSIGNED_CHAR: + { + vtkUnsignedCharArray *scalars = (vtkUnsignedCharArray *)inScalars; + unsigned char *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_SHORT: + { + vtkShortArray *scalars = (vtkShortArray *)inScalars; + short *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_UNSIGNED_SHORT: + { + vtkUnsignedShortArray *scalars = (vtkUnsignedShortArray *)inScalars; + unsigned short *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_INT: + { + vtkIntArray *scalars = (vtkIntArray *)inScalars; + int *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_UNSIGNED_INT: + { + vtkUnsignedIntArray *scalars = (vtkUnsignedIntArray *)inScalars; + unsigned int *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_LONG: + { + vtkLongArray *scalars = (vtkLongArray *)inScalars; + long *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_UNSIGNED_LONG: + { + vtkUnsignedLongArray *scalars = (vtkUnsignedLongArray *)inScalars; + unsigned long *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_FLOAT: + { + vtkFloatArray *scalars = (vtkFloatArray *)inScalars; + float *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + case VTK_DOUBLE: + { + vtkDoubleArray *scalars = (vtkDoubleArray *)inScalars; + double *s = scalars->GetPointer(0); + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + break; + }//switch + } + + else //multiple components have to convert + { + vtkDoubleArray *scalars = (vtkDoubleArray *)inScalars; + double *s = NULL; //clue to convert data to double + numTriangles = vtkSliceCubesContour(s,scalars,imageRange,dims,origin, + Spacing,this->Value, + xmin,xmax,outFP,this->Reader,this->Debug); + } + + inScalars->UnRegister(this); + vtkDebugMacro(<<"Created: " << 3*numTriangles << " points, " + << numTriangles << " triangles"); + + if ( this->LimitsFileName ) + { + int i; + float t; + + if ( (outFP = fopen(this->LimitsFileName, "wb")) == NULL ) + { + vtkWarningMacro(<<"Sorry, couldn't write limits file..."); + } + else + { + float forigin[3]; + for (i=0; i<3; i++) + { + t = origin[i] + (dims[i] - 1)*Spacing[i]; + forigin[i] = (float)origin[i]; + vtkByteSwap::SwapWrite4BERange(forigin+i,1,outFP); + // swap if neccessary + vtkByteSwap::SwapWrite4BERange(&t,1,outFP); + } + float ftmp; + for (i=0; i<3; i++) + { + ftmp = (float)xmin[i]; + vtkByteSwap::SwapWrite4BERange(&ftmp,1,outFP); + ftmp = (float)xmax[i]; + vtkByteSwap::SwapWrite4BERange(&ftmp,1,outFP); + } + } + fclose(outFP); + } +} + +void vtkSliceCubes::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Iso Value: " << this->Value << "\n"; + + if ( this->Reader ) + { + os << indent << "Reader:\n"; + this->Reader->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Reader: (none)\n"; + } + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "Limits File Name: " + << (this->LimitsFileName ? this->LimitsFileName : "(none)") << "\n"; +} diff --git a/Graphics/vtkSliceCubes.h b/Graphics/vtkSliceCubes.h new file mode 100644 index 0000000..da6f676 --- /dev/null +++ b/Graphics/vtkSliceCubes.h @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSliceCubes.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSliceCubes - generate isosurface(s) from volume four slices at a time +// .SECTION Description +// vtkSliceCubes is a special version of the marching cubes filter. Instead +// of ingesting an entire volume at once it processes only four slices at +// a time. This way, it can generate isosurfaces from huge volumes. Also, the +// output of this object is written to a marching cubes triangle file. That +// way, output triangles do not need to be held in memory. +// +// To use vtkSliceCubes you must specify an instance of vtkVolumeReader to +// read the data. Set this object up with the proper file prefix, image range, +// data origin, data dimensions, header size, data mask, and swap bytes flag. +// The vtkSliceCubes object will then take over and read slices as necessary. +// You also will need to specify the name of an output marching cubes triangle +// file. +// +// .SECTION Caveats +// This process object is both a source and mapper (i.e., it reads and writes +// data to a file). This is different than the other marching cubes objects +// (and most process objects in the system). It's specialized to handle very +// large data. +// +// This object only extracts a single isosurface. This compares with the other +// contouring objects in vtk that generate multiple surfaces. +// +// To read the output file use vtkMCubesReader. + +// .SECTION See Also +// vtkMarchingCubes vtkContourFilter vtkMCubesReader vtkDividingCubes vtkVolumeReader + +#ifndef __vtkSliceCubes_h +#define __vtkSliceCubes_h + +#include "vtkObject.h" + +class vtkVolumeReader; + +class VTK_GRAPHICS_EXPORT vtkSliceCubes : public vtkObject +{ +public: + static vtkSliceCubes *New(); + vtkTypeRevisionMacro(vtkSliceCubes,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // methods to make it look like a filter + void Write() {this->Update();}; + void Update(); + + // Description: + // Set/get object to read slices. + virtual void SetReader(vtkVolumeReader*); + vtkGetObjectMacro(Reader,vtkVolumeReader); + + // Description: + // Specify file name of marching cubes output file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Set/get isosurface contour value. + vtkSetMacro(Value,double); + vtkGetMacro(Value,double); + + // Description: + // Specify file name of marching cubes limits file. The limits file + // speeds up subsequent reading of output triangle file. + vtkSetStringMacro(LimitsFileName); + vtkGetStringMacro(LimitsFileName); + +protected: + vtkSliceCubes(); + ~vtkSliceCubes(); + + void Execute(); + + vtkVolumeReader *Reader; + char *FileName; + double Value; + char *LimitsFileName; + +private: + vtkSliceCubes(const vtkSliceCubes&); // Not implemented. + void operator=(const vtkSliceCubes&); // Not implemented. +}; + +#endif + diff --git a/Graphics/vtkSmoothPolyDataFilter.cxx b/Graphics/vtkSmoothPolyDataFilter.cxx new file mode 100644 index 0000000..5958011 --- /dev/null +++ b/Graphics/vtkSmoothPolyDataFilter.cxx @@ -0,0 +1,729 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSmoothPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSmoothPolyDataFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCellLocator.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTriangleFilter.h" + +vtkCxxRevisionMacro(vtkSmoothPolyDataFilter, "$Revision: 1.42 $"); +vtkStandardNewMacro(vtkSmoothPolyDataFilter); + +// The following code defines a helper class for performing mesh smoothing +// across the surface of another mesh. +typedef struct _vtkSmoothPoint { + vtkIdType cellId; // cell + int subId; // cell sub id + double p[3]; // parametric coords in cell +} vtkSmoothPoint; + +class vtkSmoothPoints { //;prevent man page generation +public: + vtkSmoothPoints(); + ~vtkSmoothPoints() + { + if (this->Array) + { + delete [] this->Array; + } + }; + vtkIdType GetNumberOfPoints() {return this->MaxId + 1;}; + vtkSmoothPoint *GetSmoothPoint(vtkIdType i) {return this->Array + i;}; + vtkSmoothPoint *InsertSmoothPoint(vtkIdType ptId) + { + if ( ptId >= this->Size ) + { + this->Resize(ptId+1); + } + if ( ptId > this->MaxId ) + { + this->MaxId = ptId; + } + return this->Array + ptId; + } + vtkSmoothPoint *Resize(vtkIdType sz); //reallocates data + void Reset() {this->MaxId = -1;}; + + vtkSmoothPoint *Array; // pointer to data + vtkIdType MaxId; // maximum index inserted thus far + vtkIdType Size; // allocated size of data + vtkIdType Extend; // grow array by this amount +}; + +vtkSmoothPoints::vtkSmoothPoints() +{ + this->MaxId = -1; + this->Array = new vtkSmoothPoint[1000]; + this->Size = 1000; + this->Extend = 5000; +} + +vtkSmoothPoint *vtkSmoothPoints::Resize(vtkIdType sz) +{ + vtkSmoothPoint *newArray; + vtkIdType newSize; + + if (sz >= this->Size) + { + newSize = this->Size + + this->Extend*(((sz-this->Size)/this->Extend)+1); + } + else + { + newSize = sz; + } + + newArray = new vtkSmoothPoint[newSize]; + + memcpy(newArray, this->Array, + (sz < this->Size ? sz : this->Size) * sizeof(vtkSmoothPoint)); + + this->Size = newSize; + delete [] this->Array; + this->Array = newArray; + + return this->Array; +} + +// The following code defines methods for the vtkSmoothPolyDataFilter class +// + +// Construct object with number of iterations 20; relaxation factor .01; +// feature edge smoothing turned off; feature +// angle 45 degrees; edge angle 15 degrees; and boundary smoothing turned +// on. Error scalars and vectors are not generated (by default). The +// convergence criterion is 0.0 of the bounding box diagonal. +vtkSmoothPolyDataFilter::vtkSmoothPolyDataFilter() +{ + this->Convergence = 0.0; //goes to number of specied iterations + this->NumberOfIterations = 20; + + this->RelaxationFactor = .01; + + this->FeatureAngle = 45.0; + this->EdgeAngle = 15.0; + this->FeatureEdgeSmoothing = 0; + this->BoundarySmoothing = 1; + + this->GenerateErrorScalars = 0; + this->GenerateErrorVectors = 0; + + // optional second input + this->SetNumberOfInputPorts(2); +} + +void vtkSmoothPolyDataFilter::SetSource(vtkPolyData *source) +{ + this->SetInput(1, source); +} + +vtkPolyData *vtkSmoothPolyDataFilter::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +#define VTK_SIMPLE_VERTEX 0 +#define VTK_FIXED_VERTEX 1 +#define VTK_FEATURE_EDGE_VERTEX 2 +#define VTK_BOUNDARY_EDGE_VERTEX 3 + +// Special structure for marking vertices +typedef struct _vtkMeshVertex + { + char type; + vtkIdList *edges; // connected edges (list of connected point ids) +} vtkMeshVertex, *vtkMeshVertexPtr; + +int vtkSmoothPolyDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *source = 0; + if (sourceInfo) + { + source = vtkPolyData::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + } + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells, i, numPolys, numStrips; + int j, k; + vtkIdType npts = 0; + vtkIdType *pts = 0; + vtkIdType p1, p2; + double x[3], y[3], deltaX[3], xNew[3], conv, maxDist, dist, factor; + double x1[3], x2[3], x3[3], l1[3], l2[3]; + double CosFeatureAngle; //Cosine of angle between adjacent polys + double CosEdgeAngle; // Cosine of angle between adjacent edges + double closestPt[3], dist2, *w = NULL; + int iterationNumber, abortExecute; + vtkIdType numSimple=0, numBEdges=0, numFixed=0, numFEdges=0; + vtkPolyData *inMesh, *Mesh; + vtkPoints *inPts; + vtkTriangleFilter *toTris=NULL; + vtkCellArray *inVerts, *inLines, *inPolys, *inStrips; + vtkPoints *newPts; + vtkMeshVertexPtr Verts; + vtkCellLocator *cellLocator=NULL; + + // Check input + // + numPts=input->GetNumberOfPoints(); + numCells=input->GetNumberOfCells(); + if (numPts < 1 || numCells < 1) + { + vtkErrorMacro(<<"No data to smooth!"); + return 1; + } + + CosFeatureAngle = + cos((double) vtkMath::DegreesToRadians() * this->FeatureAngle); + CosEdgeAngle = cos((double) vtkMath::DegreesToRadians() * this->EdgeAngle); + + vtkDebugMacro(<<"Smoothing " << numPts << " vertices, " << numCells + << " cells with:\n" + << "\tConvergence= " << this->Convergence << "\n" + << "\tIterations= " << this->NumberOfIterations << "\n" + << "\tRelaxation Factor= " << this->RelaxationFactor << "\n" + << "\tEdge Angle= " << this->EdgeAngle << "\n" + << "\tBoundary Smoothing " << (this->BoundarySmoothing ? "On\n" : "Off\n") + << "\tFeature Edge Smoothing " << (this->FeatureEdgeSmoothing ? "On\n" : "Off\n") + << "\tError Scalars " << (this->GenerateErrorScalars ? "On\n" : "Off\n") + << "\tError Vectors " << (this->GenerateErrorVectors ? "On\n" : "Off\n")); + + if ( this->NumberOfIterations <= 0 || this->RelaxationFactor == 0.0) + { //don't do anything! pass data through + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + return 1; + } + + // Peform topological analysis. What we're gonna do is build a connectivity + // array of connected vertices. The outcome will be one of three + // classifications for a vertex: VTK_SIMPLE_VERTEX, VTK_FIXED_VERTEX. or + // VTK_EDGE_VERTEX. Simple vertices are smoothed using all connected + // vertices. FIXED vertices are never smoothed. Edge vertices are smoothed + // using a subset of the attached vertices. + // + vtkDebugMacro(<<"Analyzing topology..."); + Verts = new vtkMeshVertex[numPts]; + for (i=0; iGetPoints(); + conv = this->Convergence * input->GetLength(); + + // check vertices first. Vertices are never smoothed_-------------- + for (inVerts=input->GetVerts(), inVerts->InitTraversal(); + inVerts->GetNextCell(npts,pts); ) + { + for (j=0; jUpdateProgress(0.10); + + // now check lines. Only manifold lines can be smoothed------------ + for (inLines=input->GetLines(), inLines->InitTraversal(); + inLines->GetNextCell(npts,pts); ) + { + for (j=0; jGetPoint(pts[0],x2); + inPts->GetPoint(pts[1],x3); + } + else //is edge vertex (unless already edge vertex!) + { + Verts[pts[j]].type = VTK_FEATURE_EDGE_VERTEX; + Verts[pts[j]].edges = vtkIdList::New(); + Verts[pts[j]].edges->SetNumberOfIds(2); + Verts[pts[j]].edges->SetId(0,pts[j-1]); + Verts[pts[j]].edges->SetId(1,pts[j+1]); + } + } //if simple vertex + + else if ( Verts[pts[j]].type == VTK_FEATURE_EDGE_VERTEX ) + { //multiply connected, becomes fixed! + Verts[pts[j]].type = VTK_FIXED_VERTEX; + Verts[pts[j]].edges->Delete(); + Verts[pts[j]].edges = NULL; + } + + } //for all points in this line + } //for all lines + this->UpdateProgress(0.25); + + // now polygons and triangle strips------------------------------- + inPolys=input->GetPolys(); + numPolys = inPolys->GetNumberOfCells(); + inStrips=input->GetStrips(); + numStrips = inStrips->GetNumberOfCells(); + + if ( numPolys > 0 || numStrips > 0 ) + { //build cell structure + vtkCellArray *polys; + vtkIdType cellId; + int numNei, nei, edge; + vtkIdType numNeiPts; + vtkIdType *neiPts; + double normal[3], neiNormal[3]; + vtkIdList *neighbors; + + neighbors = vtkIdList::New(); + neighbors->Allocate(VTK_CELL_SIZE); + + inMesh = vtkPolyData::New(); + inMesh->SetPoints(inPts); + inMesh->SetPolys(inPolys); + Mesh = inMesh; + + if ( (numStrips = inStrips->GetNumberOfCells()) > 0 ) + { // convert data to triangles + inMesh->SetStrips(inStrips); + toTris = vtkTriangleFilter::New(); + toTris->SetInput(inMesh); + toTris->Update(); + Mesh = toTris->GetOutput(); + } + + Mesh->BuildLinks(); //to do neighborhood searching + polys = Mesh->GetPolys(); + this->UpdateProgress(0.375); + + for (cellId=0, polys->InitTraversal(); polys->GetNextCell(npts,pts); + cellId++) + { + for (i=0; i < npts; i++) + { + p1 = pts[i]; + p2 = pts[(i+1)%npts]; + + if ( Verts[p1].edges == NULL ) + { + Verts[p1].edges = vtkIdList::New(); + Verts[p1].edges->Allocate(16,6); + } + if ( Verts[p2].edges == NULL ) + { + Verts[p2].edges = vtkIdList::New(); + Verts[p2].edges->Allocate(16,6); + } + + Mesh->GetCellEdgeNeighbors(cellId,p1,p2,neighbors); + numNei = neighbors->GetNumberOfIds(); + + edge = VTK_SIMPLE_VERTEX; + if ( numNei == 0 ) + { + edge = VTK_BOUNDARY_EDGE_VERTEX; + } + + else if ( numNei >= 2 ) + { + // check to make sure that this edge hasn't been marked already + for (j=0; j < numNei; j++) + { + if ( neighbors->GetId(j) < cellId ) + { + break; + } + } + if ( j >= numNei ) + { + edge = VTK_FEATURE_EDGE_VERTEX; + } + } + + else if ( numNei == 1 && (nei=neighbors->GetId(0)) > cellId ) + { + vtkPolygon::ComputeNormal(inPts,npts,pts,normal); + Mesh->GetCellPoints(nei,numNeiPts,neiPts); + vtkPolygon::ComputeNormal(inPts,numNeiPts,neiPts,neiNormal); + + if ( this->FeatureEdgeSmoothing && + vtkMath::Dot(normal,neiNormal) <= CosFeatureAngle ) + { + edge = VTK_FEATURE_EDGE_VERTEX; + } + } + else // a visited edge; skip rest of analysis + { + continue; + } + + if ( edge && Verts[p1].type == VTK_SIMPLE_VERTEX ) + { + Verts[p1].edges->Reset(); + Verts[p1].edges->InsertNextId(p2); + Verts[p1].type = edge; + } + else if ( (edge && Verts[p1].type == VTK_BOUNDARY_EDGE_VERTEX) || + (edge && Verts[p1].type == VTK_FEATURE_EDGE_VERTEX) || + (!edge && Verts[p1].type == VTK_SIMPLE_VERTEX ) ) + { + Verts[p1].edges->InsertNextId(p2); + if ( Verts[p1].type && edge == VTK_BOUNDARY_EDGE_VERTEX ) + { + Verts[p1].type = VTK_BOUNDARY_EDGE_VERTEX; + } + } + + if ( edge && Verts[p2].type == VTK_SIMPLE_VERTEX ) + { + Verts[p2].edges->Reset(); + Verts[p2].edges->InsertNextId(p1); + Verts[p2].type = edge; + } + else if ( (edge && Verts[p2].type == VTK_BOUNDARY_EDGE_VERTEX ) || + (edge && Verts[p2].type == VTK_FEATURE_EDGE_VERTEX) || + (!edge && Verts[p2].type == VTK_SIMPLE_VERTEX ) ) + { + Verts[p2].edges->InsertNextId(p1); + if ( Verts[p2].type && edge == VTK_BOUNDARY_EDGE_VERTEX ) + { + Verts[p2].type = VTK_BOUNDARY_EDGE_VERTEX; + } + } + } + } + + inMesh->Delete(); + if (toTris) {toTris->Delete();} + + neighbors->Delete(); + }//if strips or polys + + this->UpdateProgress(0.50); + + //post-process edge vertices to make sure we can smooth them + for (i=0; iBoundarySmoothing && + Verts[i].type == VTK_BOUNDARY_EDGE_VERTEX ) + { + Verts[i].type = VTK_FIXED_VERTEX; + numBEdges++; + } + + else if ( (npts = Verts[i].edges->GetNumberOfIds()) != 2 ) + { + Verts[i].type = VTK_FIXED_VERTEX; + numFixed++; + } + + else //check angle between edges + { + inPts->GetPoint(Verts[i].edges->GetId(0),x1); + inPts->GetPoint(i,x2); + inPts->GetPoint(Verts[i].edges->GetId(1),x3); + + for (k=0; k<3; k++) + { + l1[k] = x2[k] - x1[k]; + l2[k] = x3[k] - x2[k]; + } + if ( vtkMath::Normalize(l1) >= 0.0 && + vtkMath::Normalize(l2) >= 0.0 && + vtkMath::Dot(l1,l2) < CosEdgeAngle) + { + numFixed++; + Verts[i].type = VTK_FIXED_VERTEX; + } + else + { + if ( Verts[i].type == VTK_FEATURE_EDGE_VERTEX ) + { + numFEdges++; + } + else + { + numBEdges++; + } + } + }//if along edge + }//if edge vertex + }//for all points + + vtkDebugMacro(<<"Found\n\t" << numSimple << " simple vertices\n\t" + << numFEdges << " feature edge vertices\n\t" + << numBEdges << " boundary edge vertices\n\t" + << numFixed << " fixed vertices\n\t"); + + vtkDebugMacro(<<"Beginning smoothing iterations..."); + + // We've setup the topology...now perform Laplacian smoothing + // + newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + + // If Source defined, we do constrained smoothing (that is, points are + // constrained to the surface of the mesh object). + if ( source ) + { + this->SmoothPoints = new vtkSmoothPoints; + vtkSmoothPoint *sPtr; + cellLocator = vtkCellLocator::New(); + w = new double[input->GetMaxCellSize()]; + + cellLocator->SetDataSet(source); + cellLocator->BuildLocator(); + + for (i=0; i < numPts; i++) + { + sPtr = this->SmoothPoints->InsertSmoothPoint(i); + cellLocator->FindClosestPoint(inPts->GetPoint(i), closestPt, + sPtr->cellId, sPtr->subId, dist2); + newPts->SetPoint(i, closestPt); + } + } + else //smooth normally + { + for (i=0; iSetPoint(i,inPts->GetPoint(i)); + } + } + + factor = this->RelaxationFactor; + for ( maxDist=VTK_DOUBLE_MAX, iterationNumber=0, abortExecute=0; + maxDist > conv && iterationNumber < this->NumberOfIterations && !abortExecute; + iterationNumber++ ) + { + + if ( iterationNumber && !(iterationNumber % 5) ) + { + this->UpdateProgress (0.5 + 0.5*iterationNumber/this->NumberOfIterations); + if (this->GetAbortExecute()) + { + abortExecute = 1; + break; + } + } + + maxDist=0.0; + for (i=0; iGetNumberOfIds()) > 0 ) + { + newPts->GetPoint(i, x); //use current points + deltaX[0] = deltaX[1] = deltaX[2] = 0.0; + for (j=0; jGetPoint(Verts[i].edges->GetId(j), y); + for (k=0; k<3; k++) + { + deltaX[k] += (y[k] - x[k]) / npts; + } + }//for all connected points + + for (k=0;k<3;k++) + { + xNew[k] = x[k] + factor * deltaX[k]; + } + + // Constrain point to surface + if ( source ) + { + vtkSmoothPoint *sPtr = this->SmoothPoints->GetSmoothPoint(i); + vtkCell *cell=NULL; + + if ( sPtr->cellId >= 0 ) //in cell + { + cell = source->GetCell(sPtr->cellId); + } + + if ( !cell || cell->EvaluatePosition(xNew, closestPt, + sPtr->subId, sPtr->p, dist2, w) == 0) + { // not in cell anymore + cellLocator->FindClosestPoint(xNew, closestPt, sPtr->cellId, + sPtr->subId, dist2); + } + for (k=0; k<3; k++) + { + xNew[k] = closestPt[k]; + } + } + + newPts->SetPoint(i,xNew); + if ( (dist = vtkMath::Norm(deltaX)) > maxDist ) + { + maxDist = dist; + } + }//if can move point + }//for all points + } //for not converged or within iteration count + + vtkDebugMacro(<<"Performed " << iterationNumber << " smoothing passes"); + if ( source ) + { + cellLocator->Delete(); + delete this->SmoothPoints; + delete [] w; + } + + // Update output. Only point coordinates have changed. + // + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + if ( this->GenerateErrorScalars ) + { + vtkFloatArray *newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfTuples(numPts); + for (i=0; iGetPoint(i,x1); + newPts->GetPoint(i,x2); + newScalars->SetComponent(i,0, + sqrt(vtkMath::Distance2BetweenPoints(x1,x2))); + } + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + if ( this->GenerateErrorVectors ) + { + vtkFloatArray *newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->SetNumberOfTuples(numPts); + for (i=0; iGetPoint(i,x1); + newPts->GetPoint(i,x2); + for (j=0; j<3; j++) + { + x3[j] = x2[j] - x1[j]; + } + newVectors->SetTuple(i,x3); + } + output->GetPointData()->SetVectors(newVectors); + newVectors->Delete(); + } + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetVerts(input->GetVerts()); + output->SetLines(input->GetLines()); + output->SetPolys(input->GetPolys()); + output->SetStrips(input->GetStrips()); + + //free up connectivity storage + for (i=0; iDelete(); + Verts[i].edges = NULL; + } + } + delete [] Verts; + + return 1; +} + +int vtkSmoothPolyDataFilter::FillInputPortInformation(int port, + vtkInformation *info) +{ + if (!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + return 1; +} + +void vtkSmoothPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Convergence: " << this->Convergence << "\n"; + os << indent << "Number of Iterations: " << this->NumberOfIterations << "\n"; + os << indent << "Relaxation Factor: " << this->RelaxationFactor << "\n"; + os << indent << "Feature Edge Smoothing: " << (this->FeatureEdgeSmoothing ? "On\n" : "Off\n"); + os << indent << "Feature Angle: " << this->FeatureAngle << "\n"; + os << indent << "Edge Angle: " << this->EdgeAngle << "\n"; + os << indent << "Boundary Smoothing: " << (this->BoundarySmoothing ? "On\n" : "Off\n"); + os << indent << "Generate Error Scalars: " << (this->GenerateErrorScalars ? "On\n" : "Off\n"); + os << indent << "Generate Error Vectors: " << (this->GenerateErrorVectors ? "On\n" : "Off\n"); + if ( this->GetSource() ) + { + os << indent << "Source: " << (void *)this->GetSource() << "\n"; + } + else + { + os << indent << "Source (none)\n"; + } + +} diff --git a/Graphics/vtkSmoothPolyDataFilter.h b/Graphics/vtkSmoothPolyDataFilter.h new file mode 100644 index 0000000..345c76a --- /dev/null +++ b/Graphics/vtkSmoothPolyDataFilter.h @@ -0,0 +1,196 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSmoothPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSmoothPolyDataFilter - adjust point positions using Laplacian smoothing +// .SECTION Description +// vtkSmoothPolyDataFilter is a filter that adjusts point coordinates using +// Laplacian smoothing. The effect is to "relax" the mesh, making the cells +// better shaped and the vertices more evenly distributed. Note that this +// filter operates on the lines, polygons, and triangle strips composing an +// instance of vtkPolyData. Vertex or poly-vertex cells are never modified. +// +// The algorithm proceeds as follows. For each vertex v, a topological and +// geometric analysis is performed to determine which vertices are connected +// to v, and which cells are connected to v. Then, a connectivity array is +// constructed for each vertex. (The connectivity array is a list of lists +// of vertices that directly attach to each vertex.) Next, an iteration +// phase begins over all vertices. For each vertex v, the coordinates of v +// are modified according to an average of the connected vertices. (A +// relaxation factor is available to control the amount of displacement of +// v). The process repeats for each vertex. This pass over the list of +// vertices is a single iteration. Many iterations (generally around 20 or +// so) are repeated until the desired result is obtained. +// +// There are some special instance variables used to control the execution +// of this filter. (These ivars basically control what vertices can be +// smoothed, and the creation of the connectivity array.) The +// BoundarySmoothing ivar enables/disables the smoothing operation on +// vertices that are on the "boundary" of the mesh. A boundary vertex is one +// that is surrounded by a semi-cycle of polygons (or used by a single +// line). +// +// Another important ivar is FeatureEdgeSmoothing. If this ivar is +// enabled, then interior vertices are classified as either "simple", +// "interior edge", or "fixed", and smoothed differently. (Interior +// vertices are manifold vertices surrounded by a cycle of polygons; or used +// by two line cells.) The classification is based on the number of feature +// edges attached to v. A feature edge occurs when the angle between the two +// surface normals of a polygon sharing an edge is greater than the +// FeatureAngle ivar. Then, vertices used by no feature edges are classified +// "simple", vertices used by exactly two feature edges are classified +// "interior edge", and all others are "fixed" vertices. +// +// Once the classification is known, the vertices are smoothed +// differently. Corner (i.e., fixed) vertices are not smoothed at all. +// Simple vertices are smoothed as before (i.e., average of connected +// vertex coordinates). Interior edge vertices are smoothed only along +// their two connected edges, and only if the angle between the edges +// is less than the EdgeAngle ivar. +// +// The total smoothing can be controlled by using two ivars. The +// NumberOfIterations is a cap on the maximum number of smoothing passes. +// The Convergence ivar is a limit on the maximum point motion. If the +// maximum motion during an iteration is less than Convergence, then the +// smoothing process terminates. (Convergence is expressed as a fraction of +// the diagonal of the bounding box.) +// +// There are two instance variables that control the generation of error +// data. If the ivar GenerateErrorScalars is on, then a scalar value indicating +// the distance of each vertex from its original position is computed. If the +// ivar GenerateErrorVectors is on, then a vector representing change in +// position is computed. +// +// Optionally you can further control the smoothing process by defining a +// second input: the Source. If defined, the input mesh is constrained to +// lie on the surface defined by the Source ivar. +// +// .SECTION Caveats +// +// The Laplacian operation reduces high frequency information in the geometry +// of the mesh. With excessive smoothing important details may be lost, and +// the surface may shrink towards the centroid. Enabling FeatureEdgeSmoothing +// helps reduce this effect, but cannot entirely eliminate it. You may also +// wish to try vtkWindowedSincPolyDataFilter. It does a better job of +// minimizing shrinkage. +// +// .SECTION See Also +// vtkWindowedSincPolyDataFilter vtkDecimate vtkDecimatePro + +#ifndef __vtkSmoothPolyDataFilter_h +#define __vtkSmoothPolyDataFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkSmoothPoints; + +class VTK_GRAPHICS_EXPORT vtkSmoothPolyDataFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSmoothPolyDataFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with number of iterations 20; relaxation factor .01; + // feature edge smoothing turned off; feature + // angle 45 degrees; edge angle 15 degrees; and boundary smoothing turned + // on. Error scalars and vectors are not generated (by default). The + // convergence criterion is 0.0 of the bounding box diagonal. + static vtkSmoothPolyDataFilter *New(); + + // Description: + // Specify a convergence criterion for the iteration + // process. Smaller numbers result in more smoothing iterations. + vtkSetClampMacro(Convergence,double,0.0,1.0); + vtkGetMacro(Convergence,double); + + // Description: + // Specify the number of iterations for Laplacian smoothing, + vtkSetClampMacro(NumberOfIterations,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfIterations,int); + + // Description: + // Specify the relaxation factor for Laplacian smoothing. As in all + // iterative methods, the stability of the process is sensitive to + // this parameter. In general, small relaxation factors and large + // numbers of iterations are more stable than larger relaxation + // factors and smaller numbers of iterations. + vtkSetMacro(RelaxationFactor,double); + vtkGetMacro(RelaxationFactor,double); + + // Description: + // Turn on/off smoothing along sharp interior edges. + vtkSetMacro(FeatureEdgeSmoothing,int); + vtkGetMacro(FeatureEdgeSmoothing,int); + vtkBooleanMacro(FeatureEdgeSmoothing,int); + + // Description: + // Specify the feature angle for sharp edge identification. + vtkSetClampMacro(FeatureAngle,double,0.0,180.0); + vtkGetMacro(FeatureAngle,double); + + // Description: + // Specify the edge angle to control smoothing along edges (either interior + // or boundary). + vtkSetClampMacro(EdgeAngle,double,0.0,180.0); + vtkGetMacro(EdgeAngle,double); + + // Description: + // Turn on/off the smoothing of vertices on the boundary of the mesh. + vtkSetMacro(BoundarySmoothing,int); + vtkGetMacro(BoundarySmoothing,int); + vtkBooleanMacro(BoundarySmoothing,int); + + // Description: + // Turn on/off the generation of scalar distance values. + vtkSetMacro(GenerateErrorScalars,int); + vtkGetMacro(GenerateErrorScalars,int); + vtkBooleanMacro(GenerateErrorScalars,int); + + // Description: + // Turn on/off the generation of error vectors. + vtkSetMacro(GenerateErrorVectors,int); + vtkGetMacro(GenerateErrorVectors,int); + vtkBooleanMacro(GenerateErrorVectors,int); + + // Description: + // Specify the source object which is used to constrain smoothing. The + // source defines a surface that the input (as it is smoothed) is + // constrained to lie upon. + void SetSource(vtkPolyData *source); + vtkPolyData *GetSource(); + +protected: + vtkSmoothPolyDataFilter(); + ~vtkSmoothPolyDataFilter() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + double Convergence; + int NumberOfIterations; + double RelaxationFactor; + int FeatureEdgeSmoothing; + double FeatureAngle; + double EdgeAngle; + int BoundarySmoothing; + int GenerateErrorScalars; + int GenerateErrorVectors; + + vtkSmoothPoints *SmoothPoints; +private: + vtkSmoothPolyDataFilter(const vtkSmoothPolyDataFilter&); // Not implemented. + void operator=(const vtkSmoothPolyDataFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkSortDataArray.cxx b/Graphics/vtkSortDataArray.cxx new file mode 100644 index 0000000..3a81b0a --- /dev/null +++ b/Graphics/vtkSortDataArray.cxx @@ -0,0 +1,236 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSortDataArray.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkSortDataArray.h" + +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkIdList.h" +#include "vtkDataArray.h" + +#include + +// ------------------------------------------------------------------------- + +vtkStandardNewMacro(vtkSortDataArray); +vtkCxxRevisionMacro(vtkSortDataArray,"$Revision: 1.1 $"); + +vtkSortDataArray::vtkSortDataArray() +{ +} + +vtkSortDataArray::~vtkSortDataArray() +{ +} + +void vtkSortDataArray::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +// Sorting templates ------------------------------------------------------- + +template +inline void vtkSortDataArraySwap(TKey *keys, TValue *values, int tupleSize, + vtkIdType index1, vtkIdType index2) +{ + TKey tmpkey; + TValue tmpvalue; + TKey *k1 = keys + index1; + TValue *v1 = values + index1*tupleSize; + TKey *k2 = keys + index2; + TValue *v2 = values + index2*tupleSize; + + tmpkey = *k1; + *k1 = *k2; + *k2 = tmpkey; + + for (int i = 0; i < tupleSize; i++) + { + tmpvalue = v1[i]; + v1[i] = v2[i]; + v2[i] = tmpvalue; + } +} +template +void vtkSortDataArrayBubbleSort(TKey *keys, TValue *values, + vtkIdType size, int tupleSize) +{ + for (int i = 1; i < size; i++) + { + for (int j = i; (j > 0) && (keys[j] < keys[j-1]); j--) + { + vtkSortDataArraySwap(keys, values, tupleSize, j, j-1); + } + } +} +template +void vtkSortDataArrayQuickSort(TKey *keys, TValue *values, + vtkIdType size, int tupleSize) +{ + while (1) + { + if (size < 8) + { + vtkSortDataArrayBubbleSort(keys, values, size, tupleSize); + return; + } + + vtkIdType pivot = (vtkIdType)(vtkMath::Random(0, size)); + //vtkIdType pivot = size/2; + vtkSortDataArraySwap(keys, values, tupleSize, 0, pivot); + // Pivot now stored at index 0. + + vtkIdType left = 1; + vtkIdType right = size - 1; + while (1) + { + while ((left <= right) && (keys[left] <= keys[0])) left++; + while ((left <= right) && (keys[right] >= keys[0])) right--; + if (left > right) break; + vtkSortDataArraySwap(keys, values, tupleSize, left, right); + } + + // Place the pivot back in the middle + vtkSortDataArraySwap(keys, values, tupleSize, 0, left-1); + + // Recurse + vtkSortDataArrayQuickSort(keys + left, values + left*tupleSize, + size-left, tupleSize); + size = left-1; + } +} + +template +inline void vtkSortDataArraySort00(TKey *keys, TValue *values, + vtkIdType array_size, int tuple_size) +{ + vtkSortDataArrayQuickSort(keys, values, array_size, tuple_size); +} + +template +void vtkSortDataArraySort01(TKey *keys, vtkDataArray *values, int array_size) +{ + if (array_size != values->GetNumberOfTuples()) + { + vtkGenericWarningMacro("Could not sort arrays. Key and value arrays have different sizes."); + return; + } + + switch (values->GetDataType()) + { + vtkTemplateMacro( + vtkSortDataArraySort00(keys, (VTK_TT *)values->GetVoidPointer(0), + array_size, values->GetNumberOfComponents())); + } +} + +template +void vtkSortDataArraySort10(vtkDataArray *keys, TValue *values, + int array_size, int tuple_size) +{ + if (array_size != keys->GetNumberOfTuples()) + { + vtkGenericWarningMacro("Could not sort arrays. Key and value arrays have different sizes."); + return; + } + + if (keys->GetNumberOfComponents() != 1) + { + vtkGenericWarningMacro("Could not sort arrays. Keys must be 1-tuples."); + return; + } + + switch (keys->GetDataType()) + { + vtkTemplateMacro( + vtkSortDataArraySort00((VTK_TT*)keys->GetVoidPointer(0), values, + array_size, tuple_size)); + } +} + +void vtkSortDataArraySort11(vtkDataArray *keys, vtkDataArray *values) +{ + switch (values->GetDataType()) + { + vtkTemplateMacro( + vtkSortDataArraySort10(keys, (VTK_TT *)values->GetVoidPointer(0), + values->GetNumberOfTuples(), + values->GetNumberOfComponents())); + } +} + +// vtkSortDataArray methods ------------------------------------------------------- + +void vtkSortDataArray::Sort(vtkIdList *keys) +{ + vtkIdType *data = keys->GetPointer(0); + vtkIdType numKeys = keys->GetNumberOfIds(); + vtkstd::sort(data, data + numKeys); +} + +void vtkSortDataArray::Sort(vtkDataArray *keys) +{ + if (keys->GetNumberOfComponents() != 1) + { + vtkGenericWarningMacro("Can only sort keys that are 1-tuples."); + return; + } + + void *data = keys->GetVoidPointer(0); + vtkIdType numKeys = keys->GetNumberOfTuples(); + + switch (keys->GetDataType()) + { + vtkTemplateMacro(vtkstd::sort((VTK_TT *)data, ((VTK_TT *)data) + numKeys)); + } +} + +void vtkSortDataArray::Sort(vtkIdList *keys, vtkIdList *values) +{ + vtkIdType size = keys->GetNumberOfIds(); + if (size != values->GetNumberOfIds()) + { + vtkGenericWarningMacro("Cannot sort arrays. Sizes of keys and values do not agree"); + return; + } + + vtkSortDataArraySort00(keys->GetPointer(0), values->GetPointer(0), size, 1); +} + +void vtkSortDataArray::Sort(vtkIdList *keys, vtkDataArray *values) +{ + vtkSortDataArraySort01(keys->GetPointer(0), values, keys->GetNumberOfIds()); +} + +void vtkSortDataArray::Sort(vtkDataArray *keys, vtkIdList *values) +{ + vtkSortDataArraySort10(keys, values->GetPointer(0), + values->GetNumberOfIds(), 1); +} + +void vtkSortDataArray::Sort(vtkDataArray *keys, vtkDataArray *values) +{ + vtkSortDataArraySort11(keys, values); +} diff --git a/Graphics/vtkSortDataArray.h b/Graphics/vtkSortDataArray.h new file mode 100644 index 0000000..6f83327 --- /dev/null +++ b/Graphics/vtkSortDataArray.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSortDataArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkSortDataArray - Provides several methods for sorting vtk arrays. + +#ifndef __vtkSortDataArray_h +#define __vtkSortDataArray_h + +#include "vtkObject.h" + +class vtkIdList; +class vtkDataArray; + +class VTK_GRAPHICS_EXPORT vtkSortDataArray : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkSortDataArray, vtkObject); + static vtkSortDataArray *New(); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + // Description: + // Sorts the given array. + static void Sort(vtkIdList *keys); + static void Sort(vtkDataArray *keys); + + // Description: + // Sorts the given key/value pairs based on the keys. A pair is given + // as the entries at a given index of each of the arrays. Obviously, + // the two arrays must be of equal size. + static void Sort(vtkIdList *keys, vtkIdList *values); + static void Sort(vtkIdList *keys, vtkDataArray *values); + static void Sort(vtkDataArray *keys, vtkIdList *values); + static void Sort(vtkDataArray *keys, vtkDataArray *values); + +protected: + vtkSortDataArray(); + virtual ~vtkSortDataArray(); + +private: + vtkSortDataArray(const vtkSortDataArray &); // Not implemented. + void operator=(const vtkSortDataArray &); // Not implemented. +}; + +#endif //__vtkSortDataArray_h diff --git a/Graphics/vtkSpatialRepresentationFilter.cxx b/Graphics/vtkSpatialRepresentationFilter.cxx new file mode 100644 index 0000000..50b870f --- /dev/null +++ b/Graphics/vtkSpatialRepresentationFilter.cxx @@ -0,0 +1,208 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpatialRepresentationFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSpatialRepresentationFilter.h" + +#include "vtkLocator.h" +#include "vtkInformation.h" +#include "vtkGarbageCollector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkSpatialRepresentationFilter, "$Revision: 1.37 $"); +vtkStandardNewMacro(vtkSpatialRepresentationFilter); +vtkCxxSetObjectMacro(vtkSpatialRepresentationFilter, + SpatialRepresentation,vtkLocator); + +vtkSpatialRepresentationFilter::vtkSpatialRepresentationFilter() +{ + this->NumberOfRequiredInputs = 1; + this->SetNumberOfInputPorts(1); + this->SpatialRepresentation = NULL; + this->Level = 0; + this->TerminalNodesRequested = 0; +} + +vtkSpatialRepresentationFilter::~vtkSpatialRepresentationFilter() +{ + if ( this->SpatialRepresentation ) + { + this->SpatialRepresentation->UnRegister(this); + this->SpatialRepresentation = NULL; + } +} + +vtkPolyData *vtkSpatialRepresentationFilter::GetOutput() +{ + if ( !this->TerminalNodesRequested ) + { + this->TerminalNodesRequested = 1; + this->Modified(); + } + return this->vtkPolyDataSource::GetOutput(); +} + +vtkPolyData *vtkSpatialRepresentationFilter::GetOutput(int level) +{ + if ( level < 0 || !this->SpatialRepresentation || + level > this->SpatialRepresentation->GetMaxLevel() ) + { + vtkErrorMacro(<<"Level requested is <0 or >= Locator's MaxLevel"); + return this->GetOutput(); + } + + if ( this->GetNumberOfOutputs() <= level || + this->Outputs[level] == NULL ) + { + this->vtkSource::SetNthOutput(level, vtkPolyData::New()); + this->Modified(); //asking for new output + } + + return (vtkPolyData *)(this->Outputs[level]); +} + +void vtkSpatialRepresentationFilter::ResetOutput() +{ + this->TerminalNodesRequested = 0; + for ( int i=0; i <= VTK_MAX_SPATIAL_REP_LEVEL; i++) + { + this->vtkSource::SetNthOutput(i, NULL); + } +} + + +// Build OBB tree +void vtkSpatialRepresentationFilter::Execute() +{ + vtkDebugMacro(<<"Building OBB representation"); + + if (this->SpatialRepresentation == NULL) + { + vtkErrorMacro(<< "SpatialRepresentation is NULL."); + return; + } + + this->SpatialRepresentation->SetDataSet(this->GetInput()); + this->SpatialRepresentation->Update(); + this->Level = this->SpatialRepresentation->GetLevel(); + + vtkDebugMacro(<<"OBB deepest tree level: " << this->Level); + this->GenerateOutput(); +} + +// Generate OBB representations at different requested levels. +void vtkSpatialRepresentationFilter::GenerateOutput() +{ + vtkDataSet *input = this->GetInput(); + if (!input) + { + return; + } + vtkPolyData *output; + int inputModified=(input->GetMTime() > this->GetMTime() ? 1 : 0); + int i; + + // + // If input to filter is modified, have to update all levels of OBB + // + if ( inputModified ) + { + for ( i=0; i <= this->Level; i++ ) + { + if ( i < this->NumberOfOutputs && this->Outputs[i] != NULL ) + { + output = (vtkPolyData *)(this->Outputs[i]); + output->Initialize(); + } + } + } + + // + // Loop over all requested levels generating new levels as necessary + // + for ( i=0; i <= this->Level && i < this->NumberOfOutputs; i++ ) + { + output = (vtkPolyData *)(this->Outputs[i]); + if ( output != NULL && output->GetNumberOfPoints() < 1 ) //compute OBB + { + this->SpatialRepresentation->GenerateRepresentation(i, output); + } + } + // + // If terminal leafs requested, generate rep + // + if ( this->TerminalNodesRequested ) + { + output = this->GetOutput(); + this->SpatialRepresentation->GenerateRepresentation(-1, output); + } +} + +void vtkSpatialRepresentationFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Level: " << this->Level << "\n"; + + if ( this->SpatialRepresentation ) + { + os << indent << "Spatial Representation: " << this->SpatialRepresentation + << "\n"; + } + else + { + os << indent << "Spatial Representation: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkSpatialRepresentationFilter::SetInput(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkSpatialRepresentationFilter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkDataSet *)(this->Inputs[0]); +} + + +//---------------------------------------------------------------------------- +void vtkSpatialRepresentationFilter::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // This filter shares our input and is therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->SpatialRepresentation, + "SpatialRepresentation"); +} + +//---------------------------------------------------------------------------- +int vtkSpatialRepresentationFilter::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} diff --git a/Graphics/vtkSpatialRepresentationFilter.h b/Graphics/vtkSpatialRepresentationFilter.h new file mode 100644 index 0000000..64418fd --- /dev/null +++ b/Graphics/vtkSpatialRepresentationFilter.h @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpatialRepresentationFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSpatialRepresentationFilter - generate polygonal model of spatial search object (i.e., a vtkLocator) +// .SECTION Description +// vtkSpatialRepresentationFilter generates an polygonal representation of a +// spatial search (vtkLocator) object. The representation varies depending +// upon the nature of the spatial search object. For example, the +// representation for vtkOBBTree is a collection of oriented bounding +// boxes. Ths input to this filter is a dataset of any type, and the output +// is polygonal data. You must also specify the spatial search object to +// use. +// +// Generally spatial search objects are used for collision detection and +// other geometric operations, but in this filter one or more levels of +// spatial searchers can be generated to form a geometric approximation to +// the input data. This is a form of data simplification, generally used to +// accelerate the rendering process. Or, this filter can be used as a +// debugging/ visualization aid for spatial search objects. +// +// This filter can generate one or more output vtkPolyData corresponding to +// different levels in the spatial search tree. The output data is retrieved +// using the GetOutput(id) method, where id ranges from 0 (root level) +// to Level. Note that the output for level "id" is not computed unless a +// GetOutput(id) method is issued. Thus, if you desire three levels of output +// (say 2,4,7), you would have to invoke GetOutput(2), GetOutput(4), and +// GetOutput(7). (Also note that the Level ivar is computed automatically +// depending on the size and nature of the input data.) There is also +// another GetOutput() method that takes no parameters. This method returns +// the leafs of the spatial search tree, which may be at different levels. + +// .SECTION Caveats +// You can specify the number of levels of to generate with the MaxLevels +// ivar. However, when the spatial search tree is built, this number of levels +// may not actually be generated. The actual number available can be found in +// the Levels ivar. Note that the value of Levels may change after filter +// execution. + +// .SECTION See Also +// vtkLocator vtkPointLocator vtkCellLocator vtkOBBTree + +#ifndef __vtkSpatialRepresentationFilter_h +#define __vtkSpatialRepresentationFilter_h + +#include "vtkPolyDataSource.h" + +#define VTK_MAX_SPATIAL_REP_LEVEL 24 + +class vtkLocator; +class vtkDataSet; + +class VTK_GRAPHICS_EXPORT vtkSpatialRepresentationFilter : public vtkPolyDataSource +{ +public: + static vtkSpatialRepresentationFilter *New(); + vtkTypeRevisionMacro(vtkSpatialRepresentationFilter,vtkPolyDataSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the locator that will be used to generate the representation. + virtual void SetSpatialRepresentation(vtkLocator*); + vtkGetObjectMacro(SpatialRepresentation,vtkLocator); + + // Description: + // Get the maximum number of outputs actually available. + vtkGetMacro(Level,int); + + // Description: + // A special form of the GetOutput() method that returns multiple outputs. + vtkPolyData *GetOutput(int level); + + // Description: + // Output of terminal nodes/leaves. + vtkPolyData *GetOutput(); + + // Description: + // Reset requested output levels + void ResetOutput(); + + // Description: + // Set / get the input data or filter. + virtual void SetInput(vtkDataSet *input); + vtkDataSet *GetInput(); + +protected: + vtkSpatialRepresentationFilter(); + ~vtkSpatialRepresentationFilter(); + + void Execute(); + void GenerateOutput(); + + int Level; + int TerminalNodesRequested; + + vtkLocator *SpatialRepresentation; + + virtual void ReportReferences(vtkGarbageCollector*); + virtual int FillInputPortInformation(int, vtkInformation*); +private: + vtkSpatialRepresentationFilter(const vtkSpatialRepresentationFilter&); // Not implemented. + void operator=(const vtkSpatialRepresentationFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkSpherePuzzle.cxx b/Graphics/vtkSpherePuzzle.cxx new file mode 100644 index 0000000..667b3c1 --- /dev/null +++ b/Graphics/vtkSpherePuzzle.cxx @@ -0,0 +1,470 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpherePuzzle.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSpherePuzzle.h" + +#include "vtkAppendPolyData.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLinearExtrusionFilter.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" +#include "vtkTransformFilter.h" + +#include + +vtkCxxRevisionMacro(vtkSpherePuzzle, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkSpherePuzzle); + +//---------------------------------------------------------------------------- +// Construct a new puzzle. +vtkSpherePuzzle::vtkSpherePuzzle() +{ + this->Transform = vtkTransform::New(); + this->Reset(); + this->Active = 0; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +// Construct a new puzzle. +vtkSpherePuzzle::~vtkSpherePuzzle() +{ + this->Transform->Delete(); + this->Transform = NULL; +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzle::Reset() +{ + int idx; + + this->Modified(); + for (idx = 0; idx < 32; ++idx) + { + this->State[idx] = idx; + this->PieceMask[idx] = 0; + } + this->Transform->Identity(); + for (idx = 0; idx < 4; ++idx) + { + this->Colors[0 + idx*8*3] = 255; + this->Colors[1 + idx*8*3] = 0; + this->Colors[2 + idx*8*3] = 0; + + this->Colors[3 + idx*8*3] = 255; + this->Colors[4 + idx*8*3] = 175; + this->Colors[5 + idx*8*3] = 0; + + this->Colors[6 + idx*8*3] = 255; + this->Colors[7 + idx*8*3] = 255; + this->Colors[8 + idx*8*3] = 0; + + this->Colors[9 + idx*8*3] = 0; + this->Colors[10 + idx*8*3] = 255; + this->Colors[11 + idx*8*3] = 0; + + this->Colors[12 + idx*8*3] = 0; + this->Colors[13 + idx*8*3] = 255; + this->Colors[14 + idx*8*3] = 255; + + this->Colors[15 + idx*8*3] = 0; + this->Colors[16 + idx*8*3] = 0; + this->Colors[17 + idx*8*3] = 255; + + this->Colors[18 + idx*8*3] = 175; + this->Colors[19 + idx*8*3] = 0; + this->Colors[20 + idx*8*3] = 255; + + this->Colors[21 + idx*8*3] = 255; + this->Colors[22 + idx*8*3] = 50; + this->Colors[23 + idx*8*3] = 150; + } +} + +//---------------------------------------------------------------------------- +int vtkSpherePuzzle::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // We are about to create/destroy alot of objects. Defer garbage + // collection until we are done. + vtkGarbageCollector::DeferredCollectionPush(); + + int i, j, k, num; + int color; + vtkAppendPolyData *append = vtkAppendPolyData::New(); + vtkSphereSource *sphere = vtkSphereSource::New(); + vtkTransformFilter *tf = vtkTransformFilter::New(); + vtkUnsignedCharArray *scalars = vtkUnsignedCharArray::New(); + vtkPolyData *tmp; + int count = 0; + unsigned char r, g, b; + + scalars->SetNumberOfComponents(3); + + sphere->SetPhiResolution(4); + sphere->SetThetaResolution(4); + + tf->SetTransform(this->Transform); + tf->SetInput(sphere->GetOutput()); + + for (j = 0; j < 4; ++j) + { + for (i = 0; i < 8; ++i) + { + color = this->State[count] * 3; + sphere->SetStartTheta((360.0 * (double)(i) / 8.0)); + sphere->SetEndTheta((360.0 * (double)(i+1) / 8.0)); + sphere->SetStartPhi((180.0 * (double)(j) / 4.0)); + sphere->SetEndPhi((180.0 * (double)(j+1) / 4.0)); + tmp = vtkPolyData::New(); + if (this->PieceMask[count]) + { // Spheres original output is transforms input. Put it back. + tf->Update(); + tmp->ShallowCopy(tf->GetOutput()); + } + else + { // Piece not involved in partial move. Just use the sphere. + sphere->Update(); + tmp->ShallowCopy(sphere->GetOutput()); + } + // Now create the colors for the faces. + num = tmp->GetNumberOfPoints(); + for (k = 0; k < num; ++k) + { + r = this->Colors[color]; + g = this->Colors[color+1]; + b = this->Colors[color+2]; + // Lighten the active pieces + if (this->Active && this->PieceMask[count]) + { + r = r + (unsigned char)((255 - r) * 0.4); + g = g + (unsigned char)((255 - g) * 0.4); + b = b + (unsigned char)((255 - b) * 0.4); + } + scalars->InsertNextValue(r); + scalars->InsertNextValue(g); + scalars->InsertNextValue(b); + } + + // append all the pieces. + append->AddInput(tmp); + tmp->FastDelete(); + ++count; + } + } + + append->Update(); + + // Move the data to the output. + tmp = output; + tmp->CopyStructure(append->GetOutput()); + tmp->GetPointData()->PassData(append->GetOutput()->GetPointData()); + tmp->GetPointData()->SetScalars(scalars); + + sphere->Delete(); + scalars->Delete(); + append->Delete(); + tf->Delete(); + + // We are done creating/destroying objects. + vtkGarbageCollector::DeferredCollectionPop(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzle::MarkHorizontal(int section) +{ + int i; + + for (i = 0; i < 32; ++i) + { + this->PieceMask[i] = 0; + } + // Find the start of the section. + section = section * 8; + for (i = 0; i < 8; ++i) + { + this->PieceMask[i+section] = 1; + } +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzle::MarkVertical(int section) +{ + int i, j, offset; + + for (i = 0; i < 32; ++i) + { + this->PieceMask[i] = 1; + } + for (i = 0; i < 4; ++i) + { + offset = (section + i) % 8; + for (j = 0; j < 4; ++j) + { + this->PieceMask[offset+(j*8)] = 0; + } + } +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzle::MoveHorizontal(int slab, int percentage, int rightFlag) +{ + int offset; + int tmp; + int i; + + this->Modified(); + + // Clear out previous partial moves. + this->Transform->Identity(); + this->MarkHorizontal(slab); + + // Move zero does nothing. + if (percentage <= 0) + { + return; + } + + // Offset is used to determine which pieces are involved. + offset = slab * 8; + + // Move 100 percent changes state. + if (percentage >= 100) + { // Just do the state change. + if (rightFlag) + { + tmp = this->State[offset+7]; + for (i = 7; i > 0; --i) + { + this->State[i+offset] = this->State[i-1+offset]; + } + this->State[offset] = tmp; + } + else + { + tmp = this->State[offset]; + for (i = 0; i < 7; ++i) + { + this->State[i+offset] = this->State[i+1+offset]; + } + this->State[offset+7] = tmp; + } + return; + } + + // Partial move. + // This does not change the state. It is ust for animating + // the move. + // Setup the pieces that are involved in the move. + if ( ! rightFlag) + { + percentage = -percentage; + } + this->Transform->RotateZ(((double)(percentage) / 100.0) + * (360.0 / 8.0) ); +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzle::MoveVertical(int half, int percentage, int rightFlag) +{ + int tmp; + int off0, off1, off2, off3; + double theta; + + this->Modified(); + + // Clear out previous partial moves. + this->Transform->Identity(); + this->MarkVertical(half); + + // Move zero does nothing. + if (percentage <= 0) + { + return; + } + + off0 = (4+half) % 8; + off1 = (5+half) % 8; + off2 = (6+half) % 8; + off3 = (7+half) % 8; + + // Move 100 percent changes state. + if (percentage >= 100) + { // Just do the state change. + tmp = this->State[off0]; + this->State[off0] = this->State[24+off3]; + this->State[24+off3] = tmp; + + tmp = this->State[off1]; + this->State[off1] = this->State[24+off2]; + this->State[24+off2] = tmp; + + tmp = this->State[off2]; + this->State[off2] = this->State[24+off1]; + this->State[24+off1] = tmp; + + tmp = this->State[off3]; + this->State[off3] = this->State[24+off0]; + this->State[24+off0] = tmp; + + + tmp = this->State[8+off0]; + this->State[8+off0] = this->State[16+off3]; + this->State[16+off3] = tmp; + + tmp = this->State[8+off1]; + this->State[8+off1] = this->State[16+off2]; + this->State[16+off2] = tmp; + + tmp = this->State[8+off2]; + this->State[8+off2] = this->State[16+off1]; + this->State[16+off1] = tmp; + + tmp = this->State[8+off3]; + this->State[8+off3] = this->State[16+off0]; + this->State[16+off0] = tmp; + return; + } + + // Partial move. + // This does not change the state. It is use for animating the move. + if (rightFlag) + { + percentage = -percentage; + } + theta = (double)(half) * vtkMath::Pi() / 4.0; + this->Transform->RotateWXYZ(((double)(percentage)/100.0)*(360.0/2.0), + sin(theta), -cos(theta), 0.0); + +} + +//---------------------------------------------------------------------------- +int vtkSpherePuzzle::SetPoint(double x, double y, double z) +{ + double pt[3]; + double theta, phi; + int xi, yi; + double xp, yp; + double xn, yn; + + this->Modified(); + + if (x < 0.2 && x > -0.2 && y < 0.2 && y > -0.2 && z < 0.2 && z > -0.2) + { + this->Active = 0; + return 0; + } + + // normalize + pt[0] = x; + pt[1] = y; + pt[2] = z; + vtkMath::Normalize(pt); + + // Convert this into phi and theta. + theta = 180.0 - atan2(pt[0], pt[1]) * 180 / vtkMath::Pi(); + phi = 90.0 - asin(pt[2]) * 180 / vtkMath::Pi(); + + // Compute the piece the point is in. + xi = (int)(theta * 8.0 / 360.0); + yi = (int)(phi * 8 / 360.0); + xn = (theta/(360.0/8.0)) - (double)(xi); + yn = (phi/(360.0/8.0)) - (double)(yi); + + vtkDebugMacro("point: " << x << ", " << y << ", " << z); + vtkDebugMacro("theta: " << theta << ", phi: " << phi); + vtkDebugMacro("theta: " << xi << ", " << xn << ", phi: " << yi << ", " << y); + + xp = 1.0 - xn; + yp = 1.0 - yn; + if (xn > 0.2 && xp > 0.2 && yn > 0.2 && yp > 0.2) + { // Do nothing in the center of the face. + this->Active = 0; + return 0; + } + this->Active = 1; + if (xn < xp && xn < yp && xn < yn) + { + this->VerticalFlag = 1; + this->RightFlag = (yn < yp); + this->Section = xi+2; + this->MarkVertical(this->Section); + return this->Section + this->VerticalFlag * 10 + this->RightFlag * 100; + } + if (xp < xn && xp < yp && xp < yn) + { + this->VerticalFlag = 1; + this->RightFlag = (yp < yn); + this->Section = xi+7; + this->MarkVertical(this->Section); + return this->Section + this->VerticalFlag * 10 + this->RightFlag * 100; + } + // The remaining options move a horizontal slab. + this->VerticalFlag = 0; + this->RightFlag = (xn > xp); + this->Section = yi; + this->MarkHorizontal(this->Section); + return this->Section + this->VerticalFlag * 10 + this->RightFlag * 100; +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzle::MovePoint(int percentage) +{ + if ( ! this->Active) + { + return; + } + this->Modified(); + + if (this->VerticalFlag) + { + this->MoveVertical(this->Section, percentage, this->RightFlag); + } + else + { + this->MoveHorizontal(this->Section, percentage, this->RightFlag); + } +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzle::PrintSelf(ostream& os, vtkIndent indent) +{ + int idx; + this->Superclass::PrintSelf(os,indent); + + os << indent << "State: " << this->State[0]; + for (idx = 1; idx < 16; ++idx) + { + os << ", " << this->State[idx]; + } + os << endl; +} diff --git a/Graphics/vtkSpherePuzzle.h b/Graphics/vtkSpherePuzzle.h new file mode 100644 index 0000000..4eeb063 --- /dev/null +++ b/Graphics/vtkSpherePuzzle.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpherePuzzle.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSpherePuzzle - create a polygonal sphere centered at the origin +// .SECTION Description +// vtkSpherePuzzle creates + +#ifndef __vtkSpherePuzzle_h +#define __vtkSpherePuzzle_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_MAX_SPHERE_RESOLUTION 1024 + +class vtkTransform; + +class VTK_GRAPHICS_EXPORT vtkSpherePuzzle : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSpherePuzzle,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + static vtkSpherePuzzle *New(); + + // Description: + // Reset the state of this puzzle back to its original state. + void Reset(); + + // Description: + // Move the top/bottom half one segment either direction. + void MoveHorizontal(int section, int percentage, int rightFlag); + + // Description: + // Rotate vertical half of sphere along one of the longitude lines. + void MoveVertical(int section, int percentage, int rightFlag); + + // Description: + // SetPoint will be called as the mouse moves over the screen. + // The output will change to indicate the pending move. + // SetPoint returns zero if move is not activated by point. + // Otherwise it encodes the move into a unique integer so that + // the caller can determine if the move state has changed. + // This will answer the question, "Should I render." + int SetPoint(double x, double y, double z); + + // Description: + // Move actually implements the pending move. When percentage + // is 100, the pending move becomes inactive, and SetPoint + // will have to be called again to setup another move. + void MovePoint(int percentage); + + // Description: + // For drawing state as arrows. + int *GetState() {return this->State;} + +protected: + vtkSpherePuzzle(); + ~vtkSpherePuzzle(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void MarkVertical(int section); + void MarkHorizontal(int section); + + int State[32]; + + // Stuff for storing a partial move. + int PieceMask[32]; + vtkTransform *Transform; + + // Colors for faces. + unsigned char Colors[96]; + + // State for potential move. + int Active; + int VerticalFlag; + int RightFlag; + int Section; + +private: + vtkSpherePuzzle(const vtkSpherePuzzle&); // Not implemented + void operator=(const vtkSpherePuzzle&); // Not implemented +}; + +#endif diff --git a/Graphics/vtkSpherePuzzleArrows.cxx b/Graphics/vtkSpherePuzzleArrows.cxx new file mode 100644 index 0000000..8225431 --- /dev/null +++ b/Graphics/vtkSpherePuzzleArrows.cxx @@ -0,0 +1,224 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpherePuzzleArrows.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSpherePuzzleArrows.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkSpherePuzzle.h" + +#include + +vtkCxxRevisionMacro(vtkSpherePuzzleArrows, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkSpherePuzzleArrows); + +//---------------------------------------------------------------------------- +// Construct a new puzzle. +vtkSpherePuzzleArrows::vtkSpherePuzzleArrows() +{ + int idx; + + for (idx = 0; idx < 32; ++idx) + { + this->Permutation[idx] = idx; + } + + this->Radius = 0.51; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +// Destruct the puzzle. +vtkSpherePuzzleArrows::~vtkSpherePuzzleArrows() +{ +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzleArrows::SetPermutationComponent(int comp, int val) +{ + if (this->Permutation[comp] == val) + { + return; + } + + this->Permutation[comp] = val; + this->Modified(); +} + +//---------------------------------------------------------------------------- +int vtkSpherePuzzleArrows::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *pts = vtkPoints::New(); + vtkCellArray *polys = vtkCellArray::New(); + int idx; + + for (idx = 0; idx < 32; ++idx) + { + if (this->Permutation[idx] != idx) + { + //this->AppendArrow(idx, this->Permutation[idx], pts, polys); + this->AppendArrow(this->Permutation[idx], idx, pts, polys); + } + } + output->SetPoints(pts); + output->SetPolys(polys); + pts->Delete(); + polys->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +// Draw an arrow for piece with id1 to piece with id2. +void vtkSpherePuzzleArrows::AppendArrow(int id1, int id2, + vtkPoints *pts, vtkCellArray *polys) +{ + double phi1, phi2, dPhi; + double theta1, theta2, dTheta; + double phi=0, theta=0, phiOff, thetaOff; + double length; + double x, y, z; + int num, idx; + vtkIdType ptId1, ptId2, ptId3, ptId4, ptId5; + + // Convert the start and end piece ids into sphere coordinates. + phi1 = vtkMath::Pi() * ((id1 / 8)+0.5) / 4.0; + theta1 = vtkMath::Pi() * ((id1 % 8)+0.5) / 4.0; + phi2 = vtkMath::Pi() * ((id2 / 8)+0.5) / 4.0; + theta2 = vtkMath::Pi() * ((id2 % 8)+0.5) / 4.0; + dPhi = phi2 - phi1; + dTheta = theta2 - theta1; + // Take the short way around. + while (dPhi > vtkMath::Pi()) + { + dPhi -= 2*vtkMath::Pi(); + } + while (dPhi < -vtkMath::Pi()) + { + dPhi += 2*vtkMath::Pi(); + } + while (dTheta > vtkMath::Pi()) + { + dTheta -= 2*vtkMath::Pi(); + } + while (dTheta < -vtkMath::Pi()) + { + dTheta += 2*vtkMath::Pi(); + } + theta2 = theta1 + dTheta; + phi2 = phi1 + dPhi; + + // Compute the length (world coords). + length = dTheta * sin(0.5*(phi1+phi2)); + length = sqrt(length*length + dPhi*dPhi); + // How many division do we need. + num = (int)(length / 0.1); + + // Compute the perpendicular phi theta step. + thetaOff = dPhi; + phiOff = -dTheta; + // Normalize (sphere coords). + length = sqrt(thetaOff*thetaOff + phiOff*phiOff); + phiOff = 0.08 * phiOff / length; + thetaOff = 0.08 * thetaOff / length; + + // First point. + x = cos(theta1+thetaOff)*sin(phi1+phiOff); + y = sin(theta1+thetaOff)*sin(phi1+phiOff); + z = cos(phi1+phiOff); + ptId1 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z); + x = cos(theta1+2*thetaOff)*sin(phi1+2*phiOff); + y = sin(theta1+2*thetaOff)*sin(phi1+2*phiOff); + z = cos(phi1+2*phiOff); + ptId2 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z); + for (idx = 1; idx < num; ++idx) + { + // Interpolate angles. + theta = theta1 + ((double)(idx)/(double)(num)) * dTheta; + phi = phi1 + ((double)(idx)/(double)(num)) * (phi2-phi1); + x = cos(theta+thetaOff)*sin(phi+phiOff); + y = sin(theta+thetaOff)*sin(phi+phiOff); + z = cos(phi+phiOff); + ptId3 = + pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z); + x = cos(theta+2*thetaOff)*sin(phi+2*phiOff); + y = sin(theta+2*thetaOff)*sin(phi+2*phiOff); + z = cos(phi+2*phiOff); + ptId4 = + pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z); + // Create the rectangle. + polys->InsertNextCell(4); + polys->InsertCellPoint(ptId1); + polys->InsertCellPoint(ptId2); + polys->InsertCellPoint(ptId4); + polys->InsertCellPoint(ptId3); + // Initialize the next step. + ptId1 = ptId3; + ptId2 = ptId4; + } + // Now create the arrow. + x = cos(theta)*sin(phi); + y = sin(theta)*sin(phi); + z = cos(phi); + ptId3 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z); + x = cos(theta+3*thetaOff)*sin(phi+3*phiOff); + y = sin(theta+3*thetaOff)*sin(phi+3*phiOff); + z = cos(phi+3*phiOff); + ptId4 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z); + x = cos(theta2+1.5*thetaOff)*sin(phi2+1.5*phiOff); + y = sin(theta2+1.5*thetaOff)*sin(phi2+1.5*phiOff); + z = cos(phi2+1.5*phiOff); + ptId5 = pts->InsertNextPoint(this->Radius*x, this->Radius*y, this->Radius*z); + polys->InsertNextCell(5); + polys->InsertCellPoint(ptId5); + polys->InsertCellPoint(ptId4); + polys->InsertCellPoint(ptId2); + polys->InsertCellPoint(ptId1); + polys->InsertCellPoint(ptId3); +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzleArrows::SetPermutation(vtkSpherePuzzle *puz) +{ + this->SetPermutation(puz->GetState()); +} + +//---------------------------------------------------------------------------- +void vtkSpherePuzzleArrows::PrintSelf(ostream& os, vtkIndent indent) +{ + int i; + this->Superclass::PrintSelf(os,indent); + + os << indent << "Permutation: "; + for (i = 0; i < 32; ++i) + { + os << this->Permutation[i] << " "; + } + os << endl; +} diff --git a/Graphics/vtkSpherePuzzleArrows.h b/Graphics/vtkSpherePuzzleArrows.h new file mode 100644 index 0000000..b93f5bc --- /dev/null +++ b/Graphics/vtkSpherePuzzleArrows.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSpherePuzzleArrows.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSpherePuzzleArrows - Visualize permutation of the sphere puzzle. +// .SECTION Description +// vtkSpherePuzzleArrows creates + +#ifndef __vtkSpherePuzzleArrows_h +#define __vtkSpherePuzzleArrows_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkPoints; +class vtkSpherePuzzle; + +class VTK_GRAPHICS_EXPORT vtkSpherePuzzleArrows : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSpherePuzzleArrows,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + static vtkSpherePuzzleArrows *New(); + + // Description: + vtkSetVectorMacro(Permutation,int,32); + vtkGetVectorMacro(Permutation,int,32); + void SetPermutationComponent(int comp, int val); + void SetPermutation(vtkSpherePuzzle *puz); + +protected: + vtkSpherePuzzleArrows(); + ~vtkSpherePuzzleArrows(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void AppendArrow(int id0, int id1, vtkPoints *pts, vtkCellArray *polys); + + int Permutation[32]; + + double Radius; + +private: + vtkSpherePuzzleArrows(const vtkSpherePuzzleArrows&); // Not implemented + void operator=(const vtkSpherePuzzleArrows&); // Not implemented +}; + +#endif diff --git a/Graphics/vtkSphereSource.cxx b/Graphics/vtkSphereSource.cxx new file mode 100644 index 0000000..0ec1396 --- /dev/null +++ b/Graphics/vtkSphereSource.cxx @@ -0,0 +1,328 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphereSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSphereSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkSphereSource, "$Revision: 1.69 $"); +vtkStandardNewMacro(vtkSphereSource); + +//---------------------------------------------------------------------------- +// Construct sphere with radius=0.5 and default resolution 8 in both Phi +// and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees. +vtkSphereSource::vtkSphereSource(int res) +{ + res = res < 4 ? 4 : res; + this->Radius = 0.5; + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; + + this->ThetaResolution = res; + this->PhiResolution = res; + this->StartTheta = 0.0; + this->EndTheta = 360.0; + this->StartPhi = 0.0; + this->EndPhi = 180.0; + this->LatLongTessellation = 0; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +int vtkSphereSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int i, j; + int jStart, jEnd, numOffset; + int numPts, numPolys; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkCellArray *newPolys; + double x[3], n[3], deltaPhi, deltaTheta, phi, theta, radius, norm; + double startTheta, endTheta, startPhi, endPhi; + int base, numPoles=0, thetaResolution, phiResolution; + vtkIdType pts[4]; + int piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + if (numPieces > this->ThetaResolution) + { + numPieces = this->ThetaResolution; + } + if (piece >= numPieces) + { + // Although the super class should take care of this, + // it cannot hurt to check here. + return 1; + } + + // I want to modify the ivars resoultion start theta and end theta, + // so I will make local copies of them. THese might be able to be merged + // with the other copies of them, ... + int localThetaResolution = this->ThetaResolution; + double localStartTheta = this->StartTheta; + double localEndTheta = this->EndTheta; + + while (localEndTheta < localStartTheta) + { + localEndTheta += 360.0; + } + deltaTheta = (localEndTheta - localStartTheta) / localThetaResolution; + + // Change the ivars based on pieces. + int start, end; + start = piece * localThetaResolution / numPieces; + end = (piece+1) * localThetaResolution / numPieces; + localEndTheta = localStartTheta + (double)(end) * deltaTheta; + localStartTheta = localStartTheta + (double)(start) * deltaTheta; + localThetaResolution = end - start; + + // Set things up; allocate memory + // + vtkDebugMacro("SphereSource Executing piece index " << piece + << " of " << numPieces << " pieces."); + + numPts = this->PhiResolution * localThetaResolution + 2; + // creating triangles + numPolys = this->PhiResolution * 2 * localThetaResolution; + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + newNormals->SetName("Normals"); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys, 3)); + + // Create sphere + // + // Create north pole if needed + if ( this->StartPhi <= 0.0 ) + { + x[0] = this->Center[0]; + x[1] = this->Center[1]; + x[2] = this->Center[2] + this->Radius; + newPoints->InsertPoint(numPoles,x); + + x[0] = x[1] = 0.0; x[2] = 1.0; + newNormals->InsertTuple(numPoles,x); + numPoles++; + } + + // Create south pole if needed + if ( this->EndPhi >= 180.0 ) + { + x[0] = this->Center[0]; + x[1] = this->Center[1]; + x[2] = this->Center[2] - this->Radius; + newPoints->InsertPoint(numPoles,x); + + x[0] = x[1] = 0.0; x[2] = -1.0; + newNormals->InsertTuple(numPoles,x); + numPoles++; + } + + // Check data, determine increments, and convert to radians + startTheta = (localStartTheta < localEndTheta ? localStartTheta : localEndTheta); + startTheta *= vtkMath::Pi() / 180.0; + endTheta = (localEndTheta > localStartTheta ? localEndTheta : localStartTheta); + endTheta *= vtkMath::Pi() / 180.0; + + startPhi = (this->StartPhi < this->EndPhi ? this->StartPhi : this->EndPhi); + startPhi *= vtkMath::Pi() / 180.0; + endPhi = (this->EndPhi > this->StartPhi ? this->EndPhi : this->StartPhi); + endPhi *= vtkMath::Pi() / 180.0; + + phiResolution = this->PhiResolution - numPoles; + deltaPhi = (endPhi - startPhi) / (this->PhiResolution - 1); + thetaResolution = localThetaResolution; + if (fabs(localStartTheta - localEndTheta) < 360.0) + { + ++localThetaResolution; + } + deltaTheta = (endTheta - startTheta) / thetaResolution; + + jStart = (this->StartPhi <= 0.0 ? 1 : 0); + jEnd = (this->EndPhi >= 180.0 ? this->PhiResolution - 1 + : this->PhiResolution); + + this->UpdateProgress(0.1); + + // Create intermediate points + for (i=0; i < localThetaResolution; i++) + { + theta = localStartTheta * vtkMath::Pi() / 180.0 + i*deltaTheta; + + for (j=jStart; jRadius * sin((double)phi); + n[0] = radius * cos((double)theta); + n[1] = radius * sin((double)theta); + n[2] = this->Radius * cos((double)phi); + x[0] = n[0] + this->Center[0]; + x[1] = n[1] + this->Center[1]; + x[2] = n[2] + this->Center[2]; + newPoints->InsertNextPoint(x); + + if ( (norm = vtkMath::Norm(n)) == 0.0 ) + { + norm = 1.0; + } + n[0] /= norm; n[1] /= norm; n[2] /= norm; + newNormals->InsertNextTuple(n); + } + this->UpdateProgress (0.10 + 0.50*i/static_cast(localThetaResolution)); + } + + // Generate mesh connectivity + base = phiResolution * localThetaResolution; + + if (fabs(localStartTheta - localEndTheta) < 360.0) + { + --localThetaResolution; + } + + if ( this->StartPhi <= 0.0 ) // around north pole + { + for (i=0; i < localThetaResolution; i++) + { + pts[0] = phiResolution*i + numPoles; + pts[1] = (phiResolution*(i+1) % base) + numPoles; + pts[2] = 0; + newPolys->InsertNextCell(3, pts); + } + } + + if ( this->EndPhi >= 180.0 ) // around south pole + { + numOffset = phiResolution - 1 + numPoles; + + for (i=0; i < localThetaResolution; i++) + { + pts[0] = phiResolution*i + numOffset; + pts[2] = ((phiResolution*(i+1)) % base) + numOffset; + pts[1] = numPoles - 1; + newPolys->InsertNextCell(3, pts); + } + } + this->UpdateProgress (0.70); + + // bands in-between poles + for (i=0; i < localThetaResolution; i++) + { + for (j=0; j < (phiResolution-1); j++) + { + pts[0] = phiResolution*i + j + numPoles; + pts[1] = pts[0] + 1; + pts[2] = ((phiResolution*(i+1)+j) % base) + numPoles + 1; + if ( !this->LatLongTessellation ) + { + newPolys->InsertNextCell(3, pts); + pts[1] = pts[2]; + pts[2] = pts[1] - 1; + newPolys->InsertNextCell(3, pts); + } + else + { + pts[3] = pts[2] - 1; + newPolys->InsertNextCell(4, pts); + } + } + this->UpdateProgress (0.70 + 0.30*i/static_cast(localThetaResolution)); + } + + // Update ourselves and release memeory + // + newPoints->Squeeze(); + output->SetPoints(newPoints); + newPoints->Delete(); + + newNormals->Squeeze(); + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + newPolys->Squeeze(); + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkSphereSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Theta Resolution: " << this->ThetaResolution << "\n"; + os << indent << "Phi Resolution: " << this->PhiResolution << "\n"; + os << indent << "Theta Start: " << this->StartTheta << "\n"; + os << indent << "Phi Start: " << this->StartPhi << "\n"; + os << indent << "Theta End: " << this->EndTheta << "\n"; + os << indent << "Phi End: " << this->EndPhi << "\n"; + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << ")\n"; + os << indent + << "LatLong Tessellation: " << this->LatLongTessellation << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkSphereSource::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_BOUNDING_BOX(), + this->Center[0] - this->Radius, + this->Center[0] + this->Radius, + this->Center[1] - this->Radius, + this->Center[1] + this->Radius, + this->Center[2] - this->Radius, + this->Center[2] + this->Radius); + + return 1; +} diff --git a/Graphics/vtkSphereSource.h b/Graphics/vtkSphereSource.h new file mode 100644 index 0000000..3d71040 --- /dev/null +++ b/Graphics/vtkSphereSource.h @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphereSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSphereSource - create a polygonal sphere centered at the origin +// .SECTION Description +// vtkSphereSource creates a sphere (represented by polygons) of specified +// radius centered at the origin. The resolution (polygonal discretization) +// in both the latitude (phi) and longitude (theta) directions can be +// specified. It also is possible to create partial spheres by specifying +// maximum phi and theta angles. By default, the surface tessellation of +// the sphere uses triangles; however you can set LatLongTessellation to +// produce a tessellation using quadrilaterals. +// .SECTION Caveats +// Resolution means the number of latitude or longitude lines for a complete +// sphere. If you create partial spheres the number of latitude/longitude +// lines may be off by one. + +#ifndef __vtkSphereSource_h +#define __vtkSphereSource_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_MAX_SPHERE_RESOLUTION 1024 + +class VTK_GRAPHICS_EXPORT vtkSphereSource : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSphereSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct sphere with radius=0.5 and default resolution 8 in both Phi + // and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees. + static vtkSphereSource *New(); + + // Description: + // Set radius of sphere. Default is .5. + vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Radius,double); + + // Description: + // Set the center of the sphere. Default is 0,0,0. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set the number of points in the longitude direction (ranging from + // StartTheta to EndTheta). + vtkSetClampMacro(ThetaResolution,int,3,VTK_MAX_SPHERE_RESOLUTION); + vtkGetMacro(ThetaResolution,int); + + // Description: + // Set the number of points in the latitude direction (ranging + // from StartPhi to EndPhi). + vtkSetClampMacro(PhiResolution,int,3,VTK_MAX_SPHERE_RESOLUTION); + vtkGetMacro(PhiResolution,int); + + // Description: + // Set the starting longitude angle. By default StartTheta=0 degrees. + vtkSetClampMacro(StartTheta,double,0.0,360.0); + vtkGetMacro(StartTheta,double); + + // Description: + // Set the ending longitude angle. By default EndTheta=360 degrees. + vtkSetClampMacro(EndTheta,double,0.0,360.0); + vtkGetMacro(EndTheta,double); + + // Description: + // Set the starting latitude angle (0 is at north pole). By default + // StartPhi=0 degrees. + vtkSetClampMacro(StartPhi,double,0.0,360.0); + vtkGetMacro(StartPhi,double); + + // Description: + // Set the ending latitude angle. By default EndPhi=180 degrees. + vtkSetClampMacro(EndPhi,double,0.0,360.0); + vtkGetMacro(EndPhi,double); + + // Description: + // Cause the sphere to be tessellated with edges along the latitude + // and longitude lines. If off, triangles are generated at non-polar + // regions, which results in edges that are not parallel to latitude and + // longitude lines. If on, quadrilaterals are generated everywhere + // except at the poles. This can be useful for generating a wireframe + // sphere with natural latitude and longitude lines. + vtkSetMacro(LatLongTessellation,int); + vtkGetMacro(LatLongTessellation,int); + vtkBooleanMacro(LatLongTessellation,int); + +protected: + vtkSphereSource(int res=8); + ~vtkSphereSource() {} + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Radius; + double Center[3]; + int ThetaResolution; + int PhiResolution; + double StartTheta; + double EndTheta; + double StartPhi; + double EndPhi; + int LatLongTessellation; + +private: + vtkSphereSource(const vtkSphereSource&); // Not implemented. + void operator=(const vtkSphereSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkSplineFilter.cxx b/Graphics/vtkSplineFilter.cxx new file mode 100644 index 0000000..62d8f5f --- /dev/null +++ b/Graphics/vtkSplineFilter.cxx @@ -0,0 +1,376 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSplineFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSplineFilter.h" + +#include "vtkCardinalSpline.h" +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkSplineFilter, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkSplineFilter); +vtkCxxSetObjectMacro(vtkSplineFilter,Spline,vtkSpline); + +vtkSplineFilter::vtkSplineFilter() +{ + this->Subdivide = VTK_SUBDIVIDE_SPECIFIED; + this->MaximumNumberOfSubdivisions = VTK_LARGE_INTEGER; + this->NumberOfSubdivisions = 100; + this->Length = 0.1; + this->GenerateTCoords = VTK_TCOORDS_FROM_NORMALIZED_LENGTH; + this->TextureLength = 1.0; + + this->Spline = vtkCardinalSpline::New(); + this->TCoordMap = vtkFloatArray::New(); +} + +vtkSplineFilter::~vtkSplineFilter() +{ + this->Spline->Delete(); + this->TCoordMap->Delete(); +} + +int vtkSplineFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(); + vtkPointData *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(); + vtkCellData *outCD=output->GetCellData(); + vtkCellArray *inLines; + + vtkPoints *inPts; + vtkIdType numLines; + vtkCellArray *newLines; + vtkIdType numNewPts, numNewCells; + vtkPoints *newPts; + vtkIdType npts=0, *pts=NULL; + vtkIdType offset=0; + vtkFloatArray *newTCoords=NULL; + int abort=0; + vtkIdType inCellId, numGenPts; + int genTCoords = VTK_TCOORDS_OFF; + + // Check input and initialize + // + vtkDebugMacro(<<"Splining polylines"); + + if ( !(inPts=input->GetPoints()) || inPts->GetNumberOfPoints() < 1 || + !(inLines = input->GetLines()) || + (numLines = inLines->GetNumberOfCells()) < 1 ) + { + vtkWarningMacro(<< " No input data!"); + return 1; + } + + if ( this->Spline == NULL ) + { + vtkWarningMacro(<< "Need to specify a spline!"); + return 1; + } + + // Create the geometry and topology + numNewPts = this->NumberOfSubdivisions * numLines; + newPts = vtkPoints::New(); + newPts->Allocate(numNewPts); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(1,numNewPts)); + + // Point data + if ( (this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS && + pd->GetScalars() != NULL) || + (this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH || + this->GenerateTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH) ) + { + genTCoords = this->GenerateTCoords; + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(numNewPts); + outPD->CopyTCoordsOff(); + } + outPD->InterpolateAllocate(pd,numNewPts); + this->TCoordMap->Allocate(VTK_CELL_SIZE); + + // Copy cell data + numNewCells = numLines; + outCD->CopyNormalsOff(); + outCD->CopyAllocate(cd,numNewCells); + + // Set up the splines + this->XSpline = this->Spline->NewInstance(); + this->XSpline->DeepCopy(this->Spline); + this->YSpline = this->Spline->NewInstance(); + this->YSpline->DeepCopy(this->Spline); + this->ZSpline = this->Spline->NewInstance(); + this->ZSpline->DeepCopy(this->Spline); + + // Create points along each polyline. + // + for (inCellId=0, inLines->InitTraversal(); + inLines->GetNextCell(npts,pts) && !abort; inCellId++) + { + this->UpdateProgress((double)inCellId/numLines); + abort = this->GetAbortExecute(); + + if (npts < 2) + { + vtkWarningMacro(<< "Less than two points in line!"); + continue; //skip tubing this polyline + } + + // Generate the points around the polyline. The strip is not created + // if the polyline is bad. + // + this->TCoordMap->Reset(); + numGenPts = this->GeneratePoints(offset, npts, pts, inPts, newPts, + pd, outPD, genTCoords, newTCoords); + if ( ! numGenPts ) + { + vtkWarningMacro(<< "Could not generate points!"); + continue; //skip splining + } + + // Generate the polyline + // + this->GenerateLine(offset,numGenPts,inCellId,cd,outCD,newLines); + + // Compute the new offset for the next polyline + offset += numGenPts; + + }//for all polylines + + // Update ourselves + // + this->TCoordMap->Initialize(); + + this->XSpline->Delete(); + this->YSpline->Delete(); + this->ZSpline->Delete(); + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + if ( newTCoords ) + { + outPD->SetTCoords(newTCoords); + newTCoords->Delete(); + } + + output->Squeeze(); + + return 1; +} + +int vtkSplineFilter::GeneratePoints(vtkIdType offset, vtkIdType npts, + vtkIdType *pts, vtkPoints *inPts, + vtkPoints *newPts, vtkPointData *pd, + vtkPointData *outPD, int genTCoords, + vtkFloatArray *newTCoords) +{ + vtkIdType i; + + // Initialize the splines + this->XSpline->RemoveAllPoints(); + this->YSpline->RemoveAllPoints(); + this->ZSpline->RemoveAllPoints(); + + // Compute the length of the resulting spline + double xPrev[3], x[3], length=0.0, len, t, tc; + inPts->GetPoint(pts[0],xPrev); + for (i=1; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + len = sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + if ( len <= 0.0 ) + { + return 0; //failure + } + length += len; + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + if ( length <= 0.0 ) + { + return 0; //failure + } + + // Now we insert points into the splines with the parametric coordinate + // based on (polyline) length. We keep track of the parametric coordinates + // of the points for later point interpolation. + inPts->GetPoint(pts[0],xPrev); + for (len=0,i=0; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + t = len/length; + this->TCoordMap->InsertValue(i,t); + + this->XSpline->AddPoint(t,x[0]); + this->YSpline->AddPoint(t,x[1]); + this->ZSpline->AddPoint(t,x[2]); + + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + + // Compute the number of subdivisions + vtkIdType numDivs, numNewPts; + if ( this->Subdivide == VTK_SUBDIVIDE_SPECIFIED ) + { + numDivs = this->NumberOfSubdivisions; + } + else + { + numDivs = (int) (length / this->Length); + } + numDivs = ( numDivs < 1 ? 1 : (numDivs > this->MaximumNumberOfSubdivisions ? + this->MaximumNumberOfSubdivisions : numDivs)); + + // Now compute the new points + numNewPts = numDivs + 1; + vtkIdType idx; + double s, s0=0.0; + if ( genTCoords == VTK_TCOORDS_FROM_SCALARS ) + { + s0=pd->GetScalars()->GetTuple1(pts[0]); + } + double tLo = this->TCoordMap->GetValue(0); + double tHi = this->TCoordMap->GetValue(1); + for (idx=0, i=0; i < numNewPts; i++) + { + t = (double) i / numDivs; + x[0] = this->XSpline->Evaluate(t); + x[1] = this->YSpline->Evaluate(t); + x[2] = this->ZSpline->Evaluate(t); + newPts->InsertPoint(offset+i,x); + + // interpolate point data + while ( t > tHi && idx < (npts-2)) + { + idx++; + tLo = this->TCoordMap->GetValue(idx); + tHi = this->TCoordMap->GetValue(idx+1); + } + tc = (t - tLo) / (tHi - tLo); + outPD->InterpolateEdge(pd,offset+i,pts[idx],pts[idx+1],tc); + + // generate texture coordinates if desired + if ( genTCoords != VTK_TCOORDS_OFF ) + { + if ( genTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH ) + { + tc = t; + } + else if ( genTCoords == VTK_TCOORDS_FROM_LENGTH ) + { + tc = t * length / this->TextureLength; + } + else if ( genTCoords == VTK_TCOORDS_FROM_SCALARS ) + { + s = outPD->GetScalars()->GetTuple1(offset+i); //data just interpolated + tc = (s - s0) / this->TextureLength; + } + newTCoords->InsertTuple2(offset+i,tc,0.0); + } //if generating tcoords + } //for all new points + + return numNewPts; +} + +void vtkSplineFilter::GenerateLine(vtkIdType offset, vtkIdType npts, + vtkIdType inCellId, + vtkCellData *cd, vtkCellData *outCD, + vtkCellArray *newLines) +{ + vtkIdType i, outCellId; + + outCellId = newLines->InsertNextCell(npts); + outCD->CopyData(cd,inCellId,outCellId); + for (i=0; i < npts; i++) + { + newLines->InsertCellPoint(offset+i); + } +} + + +const char *vtkSplineFilter::GetSubdivideAsString() +{ + if ( this->Subdivide == VTK_SUBDIVIDE_SPECIFIED ) + { + return "Specified by Number of Subdivisions"; + } + else + { + return "Specified by Length"; + } +} + +// Return the method of generating the texture coordinates. +const char *vtkSplineFilter::GetGenerateTCoordsAsString(void) +{ + if ( this->GenerateTCoords == VTK_TCOORDS_OFF ) + { + return "GenerateTCoordsOff"; + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS ) + { + return "GenerateTCoordsFromScalar"; + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH ) + { + return "GenerateTCoordsFromLength"; + } + else + { + return "GenerateTCoordsFromNormalizedLength"; + } +} + +void vtkSplineFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Subdivide: :" << this->GetSubdivideAsString() << "\n"; + os << indent << "Maximum Number of Subdivisions: " + << this->MaximumNumberOfSubdivisions << "\n"; + os << indent << "Number of Subdivisions: " + << this->NumberOfSubdivisions << "\n"; + os << indent << "Length: " << this->Length << "\n"; + os << indent << "Spline: " << this->Spline << "\n"; + os << indent << "Generate TCoords: " + << this->GetGenerateTCoordsAsString() << endl; + os << indent << "Texture Length: " << this->TextureLength << endl; +} + diff --git a/Graphics/vtkSplineFilter.h b/Graphics/vtkSplineFilter.h new file mode 100644 index 0000000..4d67e13 --- /dev/null +++ b/Graphics/vtkSplineFilter.h @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSplineFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSplineFilter - generate uniformly subdivided polylines from a set of input polyline using a vtkSpline +// .SECTION Description +// vtkSplineFilter is a filter that generates an output polylines from an +// input set of polylines. The polylines are uniformly subdivided and produced +// with the help of a vtkSpline class that the user can specify (by default a +// vtkCardinalSpline is used). The number of subdivisions of the line can be +// controlled in several ways. The user can either specify the number of +// subdivisions or a length of each subdivision can be provided (and the +// class will figure out how many subdivisions is required over the whole +// polyline). The maximum number of subdivisions can also be set. +// +// The output of this filter is a polyline per input polyline (or line). New +// points and texture coordinates are created. Point data is interpolated and +// cell data passed on. Any polylines with less than two points, or who have +// coincident points, are ignored. + +// .SECTION See Also +// vtkRibbonFilter vtkTubeFilter + +#ifndef __vtkSplineFilter_h +#define __vtkSplineFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_SUBDIVIDE_SPECIFIED 0 +#define VTK_SUBDIVIDE_LENGTH 1 + +#define VTK_TCOORDS_OFF 0 +#define VTK_TCOORDS_FROM_NORMALIZED_LENGTH 1 +#define VTK_TCOORDS_FROM_LENGTH 2 +#define VTK_TCOORDS_FROM_SCALARS 3 + +class vtkCellArray; +class vtkCellData; +class vtkFloatArray; +class vtkPointData; +class vtkPoints; +class vtkSpline; + +class VTK_GRAPHICS_EXPORT vtkSplineFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSplineFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct the class with no limit on the number of subdivisions + // and using an instance of vtkCardinalSpline to perform interpolation. + static vtkSplineFilter *New(); + + // Description: + // Set the maximum number of subdivisions that are created for each + // polyline. + vtkSetClampMacro(MaximumNumberOfSubdivisions,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(MaximumNumberOfSubdivisions,int); + + // Description: + // Specify how the number of subdivisions is determined. + vtkSetClampMacro(Subdivide,int,VTK_SUBDIVIDE_SPECIFIED,VTK_SUBDIVIDE_LENGTH); + vtkGetMacro(Subdivide,int); + void SetSubdivideToSpecified() + {this->SetSubdivide(VTK_SUBDIVIDE_SPECIFIED);} + void SetSubdivideToLength() + {this->SetSubdivide(VTK_SUBDIVIDE_LENGTH);} + const char *GetSubdivideAsString(); + + // Description: + // Set the number of subdivisions that are created for the + // polyline. This method only has effect if Subdivisions is set + // to SetSubdivisionsToSpecify(). + vtkSetClampMacro(NumberOfSubdivisions,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfSubdivisions,int); + + // Description: + // Control the number of subdivisions that are created for the + // polyline based on an absolute length. The length of the spline + // is divided by this length to determine the number of subdivisions. + vtkSetClampMacro(Length,double,0.0000001,VTK_DOUBLE_MAX); + vtkGetMacro(Length,double); + + // Description: + // Specify an instance of vtkSpline to use to perform the interpolation. + virtual void SetSpline(vtkSpline*); + vtkGetObjectMacro(Spline,vtkSpline); + + // Description: + // Control whether and how texture coordinates are produced. This is + // useful for striping the output polyline. The texture coordinates + // can be generated in three ways: a normalized (0,1) generation; + // based on the length (divided by the texture length); and by using + // the input scalar values. + vtkSetClampMacro(GenerateTCoords,int,VTK_TCOORDS_OFF, + VTK_TCOORDS_FROM_SCALARS); + vtkGetMacro(GenerateTCoords,int); + void SetGenerateTCoordsToOff() + {this->SetGenerateTCoords(VTK_TCOORDS_OFF);} + void SetGenerateTCoordsToNormalizedLength() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_NORMALIZED_LENGTH);} + void SetGenerateTCoordsToUseLength() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_LENGTH);} + void SetGenerateTCoordsToUseScalars() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_SCALARS);} + const char *GetGenerateTCoordsAsString(); + + // Description: + // Control the conversion of units during the texture coordinates + // calculation. The TextureLength indicates what length (whether + // calculated from scalars or length) is mapped to the [0,1) + // texture space. + vtkSetClampMacro(TextureLength,double,0.000001,VTK_LARGE_INTEGER); + vtkGetMacro(TextureLength,double); + +protected: + vtkSplineFilter(); + ~vtkSplineFilter(); + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int MaximumNumberOfSubdivisions; + int Subdivide; + int NumberOfSubdivisions; + double Length; + vtkSpline *Spline; + vtkSpline *XSpline; + vtkSpline *YSpline; + vtkSpline *ZSpline; + int GenerateTCoords; + double TextureLength; //this length is mapped to [0,1) texture space + + //helper methods + int GeneratePoints(vtkIdType offset, vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, vtkPoints *newPts, vtkPointData *pd, + vtkPointData *outPD, int genTCoords, + vtkFloatArray *newTCoords); + + void GenerateLine(vtkIdType offset, vtkIdType numGenPts, vtkIdType inCellId, + vtkCellData *cd, vtkCellData *outCD, vtkCellArray *newLines); + + //helper members + vtkFloatArray *TCoordMap; + +private: + vtkSplineFilter(const vtkSplineFilter&); // Not implemented. + void operator=(const vtkSplineFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkSplitField.cxx b/Graphics/vtkSplitField.cxx new file mode 100644 index 0000000..e4b9a58 --- /dev/null +++ b/Graphics/vtkSplitField.cxx @@ -0,0 +1,415 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSplitField.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSplitField.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkDataSetAttributes.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkSplitField, "$Revision: 1.18 $"); +vtkStandardNewMacro(vtkSplitField); + +char vtkSplitField::FieldLocationNames[3][12] += { "DATA_OBJECT", + "POINT_DATA", + "CELL_DATA" }; + +char vtkSplitField::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10] += { "SCALARS", + "VECTORS", + "NORMALS", + "TCOORDS", + "TENSORS" }; + +typedef vtkSplitField::Component Component; + +vtkSplitField::vtkSplitField() +{ + this->FieldName = 0; + this->FieldLocation = -1; + this->AttributeType = -1; + this->FieldType = -1; + + this->Head = 0; + this->Tail = 0; +} + +vtkSplitField::~vtkSplitField() +{ + delete[] this->FieldName; + this->FieldName = 0; + this->DeleteAllComponents(); +} + +void vtkSplitField::SetInputField(const char* name, int fieldLoc) +{ + if (!name) + { + return; + } + + if ( (fieldLoc != vtkSplitField::DATA_OBJECT) && + (fieldLoc != vtkSplitField::POINT_DATA) && + (fieldLoc != vtkSplitField::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return; + } + + this->Modified(); + this->FieldLocation = fieldLoc; + this->FieldType = vtkSplitField::NAME; + + delete[] this->FieldName; + this->FieldName = new char[strlen(name)+1]; + strcpy(this->FieldName, name); +} + +void vtkSplitField::SetInputField(int attributeType, int fieldLoc) +{ + if ( (fieldLoc != vtkSplitField::POINT_DATA) && + (fieldLoc != vtkSplitField::CELL_DATA) ) + { + vtkErrorMacro("The source for the field is wrong."); + return; + } + + this->Modified(); + this->FieldLocation = fieldLoc; + this->FieldType = vtkSplitField::ATTRIBUTE; + this->AttributeType = attributeType; + +} + +void vtkSplitField::SetInputField(const char* name, + const char* fieldLoc) +{ + if ( !name || !fieldLoc) + { + return; + } + + int numAttr = vtkDataSetAttributes::NUM_ATTRIBUTES; + int numFieldLocs = 3; + int i; + + // Convert strings to ints and call the appropriate SetInputField() + int attrType=-1; + for(i=0; iSetInputField(name, loc); + } + else + { + this->SetInputField(attrType, loc); + } + +} + +void vtkSplitField::Split(int component, const char* arrayName) +{ + if (!arrayName) + { + return; + } + + this->Modified(); + Component* comp = this->FindComponent(component); + // If component is already there, just reset the information + if ( comp ) + { + comp->SetName(arrayName); + } + // otherwise add a new one + else + { + comp = new Component; + comp->SetName(arrayName); + comp->Index = component; + this->AddComponent(comp); + } +} + +int vtkSplitField::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // This has to be here because it initialized all field datas. + output->CopyStructure( input ); + + // Pass all. (data object's field data is passed by the + // superclass after this method) + output->GetPointData()->PassData( input->GetPointData() ); + output->GetCellData()->PassData( input->GetCellData() ); + + vtkDataArray* outputArray; + vtkDataArray* inputArray = 0; + vtkFieldData* fd = 0; + vtkFieldData* outputFD = 0; + Component* cur = this->GetFirst(); + Component* before; + + if (!cur) { return 1; } + + // find the input and output field data + if ( this->FieldLocation == vtkSplitField::DATA_OBJECT) + { + fd = input->GetFieldData(); + outputFD = output->GetFieldData(); + if (!fd || !outputFD) + { + vtkErrorMacro("No field data in vtkDataObject."); + return 1; + } + } + else if ( this->FieldLocation == vtkSplitField::POINT_DATA ) + { + fd = input->GetPointData(); + outputFD = output->GetPointData(); + } + else if ( this->FieldLocation == vtkSplitField::CELL_DATA ) + { + fd = input->GetCellData(); + outputFD = output->GetCellData(); + } + + if ( this->FieldType == vtkSplitField::NAME ) + { + inputArray = fd->GetArray(this->FieldName); + } + else if ( this->FieldType == vtkSplitField::ATTRIBUTE ) + { + // If we are working with attributes, we also need to have + // access to vtkDataSetAttributes methods. + vtkDataSetAttributes* dsa=vtkDataSetAttributes::SafeDownCast(fd); + if (!dsa) + { + vtkErrorMacro("Sanity check failed, returning."); + return 1; + } + inputArray = dsa->GetAttribute(this->AttributeType); + } + + if (!inputArray) + { + vtkErrorMacro("Sanity check failed, returning."); + return 1; + } + + // iterate over all components in the linked list and + // generate them + do + { + before = cur; + cur = cur->Next; + if (before->FieldName) + { + outputArray = this->SplitArray(inputArray, before->Index); + if (outputArray) + { + outputArray->SetName(before->FieldName); + outputFD->AddArray(outputArray); + outputArray->UnRegister(this); + } + } + } + while (cur); + + return 1; +} + +// fast pointer copy +template +void vtkSplitFieldCopyTuples(T* input, T* output, vtkIdType numTuples, + int numComp, int component) +{ + for (int i=0; i da->GetNumberOfComponents()) ) + { + vtkErrorMacro("Invalid component. Can not split"); + return 0; + } + + vtkDataArray* output = da->NewInstance(); + output->SetNumberOfComponents(1); + int numTuples = da->GetNumberOfTuples(); + output->SetNumberOfTuples(numTuples); + if ( numTuples > 0 ) + { + switch (output->GetDataType()) + { + vtkTemplateMacro( + vtkSplitFieldCopyTuples((VTK_TT *)da->GetVoidPointer(0), + (VTK_TT *)output->GetVoidPointer(0), + numTuples, + da->GetNumberOfComponents(), + component)); + // This is not supported by the template macro. + // Switch to using the float interface. + case VTK_BIT: + { + for(int i=0; iSetComponent(i, 0, da->GetComponent(i, component)); + } + } + break; + default: + vtkErrorMacro(<<"Sanity check failed: Unsupported data type."); + return 0; + } + } + + return output; + +} + + +// Linked list methods +void vtkSplitField::AddComponent(Component* op) +{ + op->Next = 0; + + if (!this->Head) + { + this->Head = op; + this->Tail = op; + return; + } + this->Tail->Next = op; + this->Tail = op; +} + +Component* vtkSplitField::FindComponent(int index) +{ + Component* cur = this->GetFirst(); + if (!cur) { return 0; } + + if (cur->Index == index) { return cur; } + while (cur->Next) + { + if (cur->Next->Index == index) + { + return cur->Next; + } + cur = cur->Next; + } + return 0; +} + +void vtkSplitField::DeleteAllComponents() +{ + Component* cur = this->GetFirst(); + if (!cur) {return;} + Component* before; + do + { + before = cur; + cur = cur->Next; + delete before; + } + while (cur); + this->Head = 0; + this->Tail = 0; +} + +void vtkSplitField::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Field name: "; + if (this->FieldName) + { + os << this->FieldName << endl; + } + else + { + os << "(none)" << endl; + } + os << indent << "Field type: " << this->FieldType << endl; + os << indent << "Attribute type: " << this->AttributeType << endl; + os << indent << "Field location: " << this->FieldLocation << endl; + os << indent << "Linked list head: " << this->Head << endl; + os << indent << "Linked list tail: " << this->Tail << endl; + os << indent << "Components: " << endl; + this->PrintAllComponents(os, indent.GetNextIndent()); +} + +void vtkSplitField::PrintComponent(Component* op, ostream& os, + vtkIndent indent) +{ + os << indent << "Field name: " << op->FieldName << endl; + os << indent << "Component index: " << op->Index << endl; +} + +void vtkSplitField::PrintAllComponents(ostream& os, vtkIndent indent) +{ + Component* cur = this->GetFirst(); + if (!cur) { return; } + Component* before; + do + { + before = cur; + cur = cur->Next; + os << endl; + this->PrintComponent(before, os, indent); + } + while (cur); +} diff --git a/Graphics/vtkSplitField.h b/Graphics/vtkSplitField.h new file mode 100644 index 0000000..e1b4638 --- /dev/null +++ b/Graphics/vtkSplitField.h @@ -0,0 +1,167 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSplitField.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSplitField - Split a field into single component fields +// .SECTION Description +// vtkSplitField is used to split a multi-component field (vtkDataArray) +// into multiple single component fields. The new fields are put in +// the same field data as the original field. The output arrays +// are of the same type as the input array. Example: +// @verbatim +// sf->SetInputField("gradient", vtkSplitField::POINT_DATA); +// sf->Split(0, "firstcomponent"); +// @endverbatim +// tells vtkSplitField to extract the first component of the field +// called gradient and create an array called firstcomponent (the +// new field will be in the output's point data). +// The same can be done from Tcl: +// @verbatim +// sf SetInputField gradient POINT_DATA +// sf Split 0 firstcomponent +// +// AttributeTypes: SCALARS, VECTORS, NORMALS, TCOORDS, TENSORS +// Field locations: DATA_OBJECT, POINT_DATA, CELL_DATA +// @endverbatim +// Note that, by default, the original array is also passed through. + +// .SECTION Caveats +// When using Tcl, Java, Python or Visual Basic bindings, the array name +// can not be one of the AttributeTypes when calling Split() which takes +// strings as arguments. The Tcl (Java etc.) command will +// always assume the string corresponds to an attribute type when +// the argument is one of the AttributeTypes. In this situation, +// use the Split() which takes enums. + +// .SECTION See Also +// vtkFieldData vtkDataSet vtkDataObjectToDataSetFilter +// vtkDataSetAttributes vtkDataArray vtkRearrangeFields +// vtkAssignAttribute vtkMergeFields + +#ifndef __vtkSplitField_h +#define __vtkSplitField_h + +#include "vtkDataSetAlgorithm.h" + +#include "vtkDataSetAttributes.h" // Needed for NUM_ATTRIBUTES + +class vtkFieldData; + +class VTK_GRAPHICS_EXPORT vtkSplitField : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSplitField,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a new vtkSplitField. + static vtkSplitField *New(); + + // Description: + // Use the given attribute in the field data given + // by fieldLoc as input. + void SetInputField(int attributeType, int fieldLoc); + + // Description: + // Use the array with given name in the field data given + // by fieldLoc as input. + void SetInputField(const char* name, int fieldLoc); + + // Description: + // Helper method used by other language bindings. Allows the caller to + // specify arguments as strings instead of enums. + void SetInputField(const char* name, const char* fieldLoc); + + // Description: + // Create a new array with the given component. + void Split(int component, const char* arrayName); + +//BTX + enum FieldLocations + { + DATA_OBJECT=0, + POINT_DATA=1, + CELL_DATA=2 + }; +//ETX + +//BTX + struct Component + { + int Index; + char* FieldName; + Component* Next; // linked list + void SetName(const char* name) + { + delete[] this->FieldName; + this->FieldName = 0; + if (name) + { + this->FieldName = new char[strlen(name)+1]; + strcpy(this->FieldName, name); + } + } + Component() { FieldName = 0; } + ~Component() { delete[] FieldName; } + }; +//ETX + +protected: + +//BTX + enum FieldTypes + { + NAME, + ATTRIBUTE + }; +//ETX + + vtkSplitField(); + virtual ~vtkSplitField(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char* FieldName; + int FieldType; + int AttributeType; + int FieldLocation; + + static char FieldLocationNames[3][12]; + static char AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10]; + + vtkDataArray* SplitArray(vtkDataArray* da, int component); + + + // Components are stored as a linked list. + Component* Head; + Component* Tail; + + // Methods to browse/modify the linked list. + Component* GetNextComponent(Component* op) + { return op->Next; } + Component* GetFirst() + { return this->Head; } + void AddComponent(Component* op); + Component* FindComponent(int index); + void DeleteAllComponents(); + + void PrintComponent(Component* op, ostream& os, vtkIndent indent); + void PrintAllComponents(ostream& os, vtkIndent indent); +private: + vtkSplitField(const vtkSplitField&); // Not implemented. + void operator=(const vtkSplitField&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkStreamLine.cxx b/Graphics/vtkStreamLine.cxx new file mode 100644 index 0000000..b759ad8 --- /dev/null +++ b/Graphics/vtkStreamLine.cxx @@ -0,0 +1,260 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamLine.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStreamLine.h" + +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyLine.h" + +vtkCxxRevisionMacro(vtkStreamLine, "$Revision: 1.59 $"); +vtkStandardNewMacro(vtkStreamLine); + +// Construct object with step size set to 1.0. +vtkStreamLine::vtkStreamLine() +{ + this->StepLength = 1.0; + this->NumberOfStreamers = 0; +} + +int vtkStreamLine::RequestData( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *source = 0; + if (sourceInfo) + { + source = vtkDataSet::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + } + + vtkStreamer::StreamPoint *sPrev, *sPtr; + vtkPoints *newPts; + vtkFloatArray *newVectors; + vtkFloatArray *newScalars=NULL; + vtkCellArray *newLines; + vtkIdType ptId, i, id; + int j; + vtkIdList *pts; + double tOffset, x[3], v[3], s, r; + double theta; + vtkPolyLine* lineNormalGenerator = NULL; + vtkFloatArray* normals = NULL; + vtkFloatArray* rotation = 0; + + this->SavePointInterval = this->StepLength; + this->vtkStreamer::Integrate(input, source); + if ( this->NumberOfStreamers <= 0 ) {return 1;} + + pts = vtkIdList::New(); + pts->Allocate(2500); + + // + // Convert streamer into lines. Lines may be dashed. + // + newPts = vtkPoints::New(); + newPts->Allocate(1000); + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(3000); + if ( this->Vorticity ) + { + lineNormalGenerator = vtkPolyLine::New(); + normals = vtkFloatArray::New(); + normals->SetNumberOfComponents(3); + normals->Allocate(3000); + rotation = vtkFloatArray::New(); + rotation->SetNumberOfComponents(1); + rotation->Allocate(1000); + rotation->SetName("Thetas"); + output->GetPointData()->AddArray(rotation); + } + + if ( input->GetPointData()->GetScalars() || this->SpeedScalars + || this->OrientationScalars) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(1000); + } + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(2*this->NumberOfStreamers, + VTK_CELL_SIZE)); + // + // Loop over all streamers generating points + // + for (ptId=0; ptId < this->NumberOfStreamers; ptId++) + { + if ( this->Streamers[ptId].GetNumberOfPoints() < 2 ) + { + continue; + } + sPrev = this->Streamers[ptId].GetStreamPoint(0); + sPtr = this->Streamers[ptId].GetStreamPoint(1); + + if ( this->Streamers[ptId].GetNumberOfPoints() == 2 && sPtr->cellId >= 0 ) + { + continue; + } + + tOffset = sPrev->t; + + for ( i=1; + i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0; + i++, sPrev=sPtr, sPtr=this->Streamers[ptId].GetStreamPoint(i) ) + { + // + // Create points for line + // + while ( tOffset >= sPrev->t && tOffset < sPtr->t ) + { + r = (tOffset - sPrev->t) / (sPtr->t - sPrev->t); + + for (j=0; j<3; j++) + { + x[j] = sPrev->x[j] + r * (sPtr->x[j] - sPrev->x[j]); + v[j] = sPrev->v[j] + r * (sPtr->v[j] - sPrev->v[j]); + } + + // add point to line + id = newPts->InsertNextPoint(x); + pts->InsertNextId(id); + newVectors->InsertTuple(id,v); + + if ( newScalars ) + { + s = sPrev->s + r * (sPtr->s - sPrev->s); + newScalars->InsertTuple(id,&s); + } + + if ( this->Vorticity ) + { + // Store the rotation values. Used after all the streamlines + // are generated. + theta = sPrev->theta + r * (sPtr->theta - sPrev->theta); + rotation->InsertTuple(id, &theta); + } + + tOffset += this->StepLength; + + } // while + } //for this streamer + + if ( pts->GetNumberOfIds() > 1 ) + { + newLines->InsertNextCell(pts); + pts->Reset(); + } + } //for all streamers + + vtkDebugMacro(<<"Created " << newPts->GetNumberOfPoints() << " points, " + << newLines->GetNumberOfCells() << " lines"); + + if (this->Vorticity) + { + // Rotate the normal vectors with stream vorticity + vtkIdType nPts=0; + vtkIdType *linePts=0; + double normal[3], local1[3], local2[3], length, costheta, sintheta; + + lineNormalGenerator->GenerateSlidingNormals(newPts,newLines,normals); + + // Loop over all lines, from the above code we are know that each line + // will have at least two points and that no points will be shared + // between lines. It is important to loop over the points used by the + // lines because newPts may actually contain points that are not used by + // any lines. The normals are only calculated for points that are used + // in lines so referencing normals for all points can lead to UMRs + for (newLines->InitTraversal(); newLines->GetNextCell(nPts,linePts); ) + { + for(i=0; iGetTuple(linePts[i], normal); + newVectors->GetTuple(linePts[i], v); + // obtain two unit orthogonal vectors on the plane perpendicular to + // the streamline + for(j=0; j<3; j++) + { + local1[j] = normal[j]; + } + length = vtkMath::Normalize(local1); + vtkMath::Cross(local1, v, local2); + vtkMath::Normalize(local2); + // Rotate the normal with theta + rotation->GetTuple(linePts[i], &theta); + costheta = cos(theta); + sintheta = sin(theta); + for(j=0; j<3; j++) + { + normal[j] = length* (costheta*local1[j] + sintheta*local2[j]); + } + normals->SetTuple(linePts[i], normal); + } + } + output->GetPointData()->SetNormals(normals); + normals->Delete(); + lineNormalGenerator->Delete(); + rotation->Delete(); + } + + output->SetPoints(newPts); + newPts->Delete(); + + output->GetPointData()->SetVectors(newVectors); + newVectors->Delete(); + + if ( newScalars ) + { + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + pts->Delete(); + output->SetLines(newLines); + newLines->Delete(); + + // Delete the streamers since they are no longer needed + delete[] this->Streamers; + this->Streamers = 0; + this->NumberOfStreamers = 0; + + output->Squeeze(); + + return 1; +} + +void vtkStreamLine::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Step Length: " << this->StepLength << "\n"; + +} diff --git a/Graphics/vtkStreamLine.h b/Graphics/vtkStreamLine.h new file mode 100644 index 0000000..195aa5e --- /dev/null +++ b/Graphics/vtkStreamLine.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamLine.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStreamLine - generate streamline in arbitrary dataset +// .SECTION Description +// vtkStreamLine is a filter that generates a streamline for an arbitrary +// dataset. A streamline is a line that is everywhere tangent to the vector +// field. Scalar values also are calculated along the streamline and can be +// used to color the line. Streamlines are calculated by integrating from +// a starting point through the vector field. Integration can be performed +// forward in time (see where the line goes), backward in time (see where the +// line came from), or in both directions. It also is possible to compute +// vorticity along the streamline. Vorticity is the projection (i.e., dot +// product) of the flow rotation on the velocity vector, i.e., the rotation +// of flow around the streamline. +// +// vtkStreamLine defines the instance variable StepLength. This parameter +// controls the time increment used to generate individual points along +// the streamline(s). Smaller values result in more line +// primitives but smoother streamlines. The StepLength instance variable is +// defined in terms of time (i.e., the distance that the particle travels in +// the specified time period). Thus, the line segments will be smaller in areas +// of low velocity and larger in regions of high velocity. (NOTE: This is +// different than the IntegrationStepLength defined by the superclass +// vtkStreamer. IntegrationStepLength is used to control integration step +// size and is expressed as a fraction of the cell length.) The StepLength +// instance variable is important because subclasses of vtkStreamLine (e.g., +// vtkDashedStreamLine) depend on this value to build their representation. + +// .SECTION See Also +// vtkStreamer vtkDashedStreamLine vtkStreamPoints + +#ifndef __vtkStreamLine_h +#define __vtkStreamLine_h + +#include "vtkStreamer.h" + +class VTK_GRAPHICS_EXPORT vtkStreamLine : public vtkStreamer +{ +public: + vtkTypeRevisionMacro(vtkStreamLine,vtkStreamer); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with step size set to 1.0. + static vtkStreamLine *New(); + + // Description: + // Specify the length of a line segment. The length is expressed in terms of + // elapsed time. Smaller values result in smoother appearing streamlines, but + // greater numbers of line primitives. + vtkSetClampMacro(StepLength,double,0.000001,VTK_DOUBLE_MAX); + vtkGetMacro(StepLength,double); + +protected: + vtkStreamLine(); + ~vtkStreamLine() {}; + + // Convert streamer array into vtkPolyData + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // the length of line primitives + double StepLength; + +private: + vtkStreamLine(const vtkStreamLine&); // Not implemented. + void operator=(const vtkStreamLine&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkStreamPoints.cxx b/Graphics/vtkStreamPoints.cxx new file mode 100644 index 0000000..ff547ce --- /dev/null +++ b/Graphics/vtkStreamPoints.cxx @@ -0,0 +1,176 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStreamPoints.h" + +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkStreamPoints, "$Revision: 1.42 $"); +vtkStandardNewMacro(vtkStreamPoints); + +// Construct object with time increment set to 1.0. +vtkStreamPoints::vtkStreamPoints() +{ + this->TimeIncrement = 1.0; + this->NumberOfStreamers = 0; +} + +int vtkStreamPoints::RequestData( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + + vtkStreamer::StreamPoint *sPrev, *sPtr; + vtkPoints *newPts; + vtkFloatArray *newVectors; + vtkFloatArray *newScalars=NULL; + vtkCellArray *newVerts; + vtkIdType i, ptId, id; + int j; + double tOffset, x[3], v[3], s, r; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *source = 0; + if (sourceInfo) + { + source = vtkDataSet::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + } + vtkIdList *pts; + + this->SavePointInterval = this->TimeIncrement; + this->vtkStreamer::Integrate(input, source); + if ( this->NumberOfStreamers <= 0 ) + { + return 1; + } + + pts = vtkIdList::New(); + pts->Allocate(2500); + newPts = vtkPoints::New(); + newPts ->Allocate(1000); + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors ->Allocate(3000); + if ( input->GetPointData()->GetScalars() || this->SpeedScalars + || this->OrientationScalars) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(1000); + } + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(2*this->NumberOfStreamers,VTK_CELL_SIZE)); + + // + // Loop over all streamers generating points + // + for (ptId=0; ptId < this->NumberOfStreamers; ptId++) + { + // tOffset is the time that the next point will have. + tOffset = 0.0; + + for ( sPrev=sPtr=this->Streamers[ptId].GetStreamPoint(0), i=0; + i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0; + i++, sPrev=sPtr, sPtr=this->Streamers[ptId].GetStreamPoint(i) ) + { + // + // For each streamer, create points "time increment" apart + // + if ( tOffset < sPtr->t ) + { + while ( tOffset < sPtr->t ) + { + r = (tOffset - sPrev->t) / (sPtr->t - sPrev->t); + + for (j=0; j<3; j++) + { + x[j] = sPrev->x[j] + r * (sPtr->x[j] - sPrev->x[j]); + v[j] = sPrev->v[j] + r * (sPtr->v[j] - sPrev->v[j]); + } + + // add point to line + id = newPts->InsertNextPoint(x); + pts->InsertNextId(id); + newVectors->InsertTuple(id,v); + + if ( newScalars ) + { + s = sPrev->s + r * (sPtr->s - sPrev->s); + newScalars->InsertTuple(id,&s); + } + + tOffset += this->TimeIncrement; + } // while + + } //if points should be created + + } //for this streamer + if ( pts->GetNumberOfIds() > 1 ) + { + newVerts->InsertNextCell(pts); + pts->Reset(); + } + } //for all streamers + // + // Update ourselves + // + vtkDebugMacro(<<"Created " << newPts->GetNumberOfPoints() << " points"); + + output->SetPoints(newPts); + newPts->Delete(); + output->SetVerts(newVerts); + newVerts->Delete(); + + output->GetPointData()->SetVectors(newVectors); + newVectors->Delete(); + + if ( newScalars ) + { + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + // Delete the streamers since they are no longer needed + delete[] this->Streamers; + this->Streamers = 0; + this->NumberOfStreamers = 0; + + output->Squeeze(); + pts->Delete(); + + return 1; +} + +void vtkStreamPoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Time Increment: " << this->TimeIncrement << " <<\n"; +} diff --git a/Graphics/vtkStreamPoints.h b/Graphics/vtkStreamPoints.h new file mode 100644 index 0000000..d86dd12 --- /dev/null +++ b/Graphics/vtkStreamPoints.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStreamPoints - generate points along streamer separated by constant time increment +// .SECTION Description +// vtkStreamPoints is a filter that generates points along a streamer. +// The points are separated by a constant time increment. The resulting visual +// effect (especially when coupled with vtkGlyph3D) is an indication of +// particle speed. + +// .SECTION See Also +// vtkStreamer vtkStreamLine vtkDashedStreamLine + +#ifndef __vtkStreamPoints_h +#define __vtkStreamPoints_h + +#include "vtkStreamer.h" + +class VTK_GRAPHICS_EXPORT vtkStreamPoints : public vtkStreamer +{ +public: + vtkTypeRevisionMacro(vtkStreamPoints,vtkStreamer); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with time increment set to 1.0. + static vtkStreamPoints *New(); + + // Description: + // Specify the separation of points in terms of absolute time. + vtkSetClampMacro(TimeIncrement,double,0.000001,VTK_DOUBLE_MAX); + vtkGetMacro(TimeIncrement,double); + +protected: + vtkStreamPoints(); + ~vtkStreamPoints() {}; + + // Convert streamer array into vtkPolyData + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // the separation of points + double TimeIncrement; + +private: + vtkStreamPoints(const vtkStreamPoints&); // Not implemented. + void operator=(const vtkStreamPoints&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkStreamTracer.cxx b/Graphics/vtkStreamTracer.cxx new file mode 100644 index 0000000..a28423f --- /dev/null +++ b/Graphics/vtkStreamTracer.cxx @@ -0,0 +1,1328 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkStreamTracer.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStreamTracer.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDataSetAttributes.h" +#include "vtkDoubleArray.h" +#include "vtkExecutive.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkInterpolatedVelocityField.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPolyData.h" +#include "vtkPolyLine.h" +#include "vtkRungeKutta2.h" +#include "vtkRungeKutta4.h" +#include "vtkRungeKutta45.h" + +vtkCxxRevisionMacro(vtkStreamTracer, "$Revision: 1.35.6.1 $"); +vtkStandardNewMacro(vtkStreamTracer); +vtkCxxSetObjectMacro(vtkStreamTracer,Integrator,vtkInitialValueProblemSolver); +vtkCxxSetObjectMacro(vtkStreamTracer,InterpolatorPrototype,vtkInterpolatedVelocityField); + +const double vtkStreamTracer::EPSILON = 1.0E-12; + +vtkStreamTracer::vtkStreamTracer() +{ + this->Integrator = vtkRungeKutta2::New(); + this->IntegrationDirection = FORWARD; + for(int i=0; i<3; i++) + { + this->StartPosition[i] = 0.0; + } + this->MaximumPropagation.Unit = LENGTH_UNIT; + this->MaximumPropagation.Interval = 1.0; + + this->MinimumIntegrationStep.Unit = CELL_LENGTH_UNIT; + this->MinimumIntegrationStep.Interval = 1.0E-2; + + this->MaximumIntegrationStep.Unit = CELL_LENGTH_UNIT; + this->MaximumIntegrationStep.Interval = 1.0; + + this->InitialIntegrationStep.Unit = CELL_LENGTH_UNIT; + this->InitialIntegrationStep.Interval = 0.5; + + this->MaximumError = 1.0e-6; + + this->MaximumNumberOfSteps = 2000; + + this->TerminalSpeed = EPSILON; + + this->ComputeVorticity = 1; + this->RotationScale = 1.0; + + this->LastUsedTimeStep = 0.0; + + this->GenerateNormalsInIntegrate = 1; + + this->InterpolatorPrototype = 0; + + this->SetNumberOfInputPorts(2); + + // by default process active point vectors + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::VECTORS); +} + +vtkStreamTracer::~vtkStreamTracer() +{ + this->SetIntegrator(0); + this->SetInterpolatorPrototype(0); +} + +void vtkStreamTracer::SetSourceConnection(vtkAlgorithmOutput* algOutput) +{ + this->SetInputConnection(1, algOutput); +} + +void vtkStreamTracer::SetSource(vtkDataSet *source) +{ + this->SetInput(1, source); +} + +vtkDataSet *vtkStreamTracer::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return 0; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +void vtkStreamTracer::AddInput(vtkDataSet* input) +{ + this->Superclass::AddInput(input); +} + +int vtkStreamTracer::GetIntegratorType() +{ + if (!this->Integrator) + { + return NONE; + } + if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta2")) + { + return RUNGE_KUTTA2; + } + if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta4")) + { + return RUNGE_KUTTA4; + } + if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta45")) + { + return RUNGE_KUTTA45; + } + return UNKNOWN; +} + +void vtkStreamTracer::SetIntegratorType(int type) +{ + vtkInitialValueProblemSolver* ivp=0; + switch (type) + { + case RUNGE_KUTTA2: + ivp = vtkRungeKutta2::New(); + break; + case RUNGE_KUTTA4: + ivp = vtkRungeKutta4::New(); + break; + case RUNGE_KUTTA45: + ivp = vtkRungeKutta45::New(); + break; + default: + vtkWarningMacro("Unrecognized integrator type. Keeping old one."); + break; + } + if (ivp) + { + this->SetIntegrator(ivp); + ivp->Delete(); + } +} + +void vtkStreamTracer::SetIntervalInformation( + int unit, vtkStreamTracer::IntervalInformation& currentValues) +{ + if ( unit == currentValues.Unit ) + { + return; + } + + if ( (unit < TIME_UNIT) || (unit > CELL_LENGTH_UNIT) ) + { + vtkWarningMacro("Unrecognized unit. Using TIME_UNIT instead."); + currentValues.Unit = TIME_UNIT; + } + else + { + currentValues.Unit = unit; + } + + this->Modified(); +} + +void vtkStreamTracer::SetIntervalInformation( + int unit, double interval, vtkStreamTracer::IntervalInformation& currentValues) +{ + if ( (unit == currentValues.Unit) && (interval == currentValues.Interval) ) + { + return; + } + + this->SetIntervalInformation(unit, currentValues); + + currentValues.Interval = interval; + this->Modified(); +} + +void vtkStreamTracer::SetMaximumPropagation(int unit, double max) +{ + this->SetIntervalInformation(unit, max, this->MaximumPropagation); +} +void vtkStreamTracer::SetMaximumPropagation( double max) +{ + if ( max == this->MaximumPropagation.Interval ) + { + return; + } + this->MaximumPropagation.Interval = max; + this->Modified(); +} +void vtkStreamTracer::SetMaximumPropagationUnit(int unit) +{ + this->SetIntervalInformation(unit, this->MaximumPropagation); +} +int vtkStreamTracer::GetMaximumPropagationUnit() +{ + return this->MaximumPropagation.Unit; +} +double vtkStreamTracer::GetMaximumPropagation() +{ + return this->MaximumPropagation.Interval; +} + +void vtkStreamTracer::SetMinimumIntegrationStep(int unit, double step) +{ + this->SetIntervalInformation(unit, step, this->MinimumIntegrationStep); +} +void vtkStreamTracer::SetMinimumIntegrationStepUnit(int unit) +{ + this->SetIntervalInformation(unit, this->MinimumIntegrationStep); +} +void vtkStreamTracer::SetMinimumIntegrationStep(double step) +{ + if ( step == this->MinimumIntegrationStep.Interval ) + { + return; + } + this->MinimumIntegrationStep.Interval = step; + this->Modified(); +} +int vtkStreamTracer::GetMinimumIntegrationStepUnit() +{ + return this->MinimumIntegrationStep.Unit; +} +double vtkStreamTracer::GetMinimumIntegrationStep() +{ + return this->MinimumIntegrationStep.Interval; +} + +void vtkStreamTracer::SetMaximumIntegrationStep(int unit, double step) +{ + this->SetIntervalInformation(unit, step, this->MaximumIntegrationStep); +} +void vtkStreamTracer::SetMaximumIntegrationStepUnit(int unit) +{ + this->SetIntervalInformation(unit, this->MaximumIntegrationStep); +} +void vtkStreamTracer::SetMaximumIntegrationStep(double step) +{ + if ( step == this->MaximumIntegrationStep.Interval ) + { + return; + } + this->MaximumIntegrationStep.Interval = step; + this->Modified(); +} +int vtkStreamTracer::GetMaximumIntegrationStepUnit() +{ + return this->MaximumIntegrationStep.Unit; +} +double vtkStreamTracer::GetMaximumIntegrationStep() +{ + return this->MaximumIntegrationStep.Interval; +} + +void vtkStreamTracer::SetInitialIntegrationStep(int unit, double step) +{ + this->SetIntervalInformation(unit, step, this->InitialIntegrationStep); +} +void vtkStreamTracer::SetInitialIntegrationStepUnit(int unit) +{ + this->SetIntervalInformation(unit, this->InitialIntegrationStep); +} +void vtkStreamTracer::SetInitialIntegrationStep(double step) +{ + if ( step == this->InitialIntegrationStep.Interval ) + { + return; + } + this->InitialIntegrationStep.Interval = step; + this->Modified(); +} +int vtkStreamTracer::GetInitialIntegrationStepUnit() +{ + return this->InitialIntegrationStep.Unit; +} +double vtkStreamTracer::GetInitialIntegrationStep() +{ + return this->InitialIntegrationStep.Interval; +} + +double vtkStreamTracer::ConvertToTime( + vtkStreamTracer::IntervalInformation& interval, double cellLength, double speed) +{ + double retVal = 0.0; + switch (interval.Unit) + { + case TIME_UNIT: + retVal = interval.Interval; + break; + case LENGTH_UNIT: + retVal = interval.Interval/speed; + break; + case CELL_LENGTH_UNIT: + retVal = interval.Interval*cellLength/speed; + break; + } + return retVal; +} + +double vtkStreamTracer::ConvertToLength( + vtkStreamTracer::IntervalInformation& interval, double cellLength, double speed) +{ + double retVal = 0.0; + switch (interval.Unit) + { + case TIME_UNIT: + retVal = interval.Interval * speed; + break; + case LENGTH_UNIT: + retVal = interval.Interval; + break; + case CELL_LENGTH_UNIT: + retVal = interval.Interval*cellLength; + break; + } + return retVal; +} + +double vtkStreamTracer::ConvertToCellLength( + vtkStreamTracer::IntervalInformation& interval, double cellLength, double speed) +{ + double retVal = 0.0; + switch (interval.Unit) + { + case TIME_UNIT: + retVal = (interval.Interval * speed)/cellLength; + break; + case LENGTH_UNIT: + retVal = interval.Interval/cellLength; + break; + case CELL_LENGTH_UNIT: + retVal = interval.Interval; + break; + } + return retVal; +} + +double vtkStreamTracer::ConvertToUnit( + vtkStreamTracer::IntervalInformation& interval, + int unit, + double cellLength, + double speed) +{ + double retVal = 0.0; + switch (unit) + { + case TIME_UNIT: + retVal = ConvertToTime(interval, cellLength, speed); + break; + case LENGTH_UNIT: + retVal = ConvertToLength(interval, cellLength, speed); + break; + case CELL_LENGTH_UNIT: + retVal = ConvertToCellLength(interval, cellLength, speed); + break; + } + return retVal; +} + +void vtkStreamTracer::ConvertIntervals(double& step, double& minStep, + double& maxStep, int direction, + double cellLength, double speed) +{ + step = direction * this->ConvertToTime( + this->InitialIntegrationStep, cellLength, speed); + if ( this->MinimumIntegrationStep.Interval <= 0.0 ) + { + minStep = step; + } + else + { + minStep = this->ConvertToTime(this->MinimumIntegrationStep, cellLength, + speed); + } + if ( this->MaximumIntegrationStep.Interval <= 0.0 ) + { + maxStep = step; + } + else + { + maxStep = this->ConvertToTime(this->MaximumIntegrationStep,cellLength, + speed); + } +} + +void vtkStreamTracer::CalculateVorticity(vtkGenericCell* cell, + double pcoords[3], + vtkDoubleArray* cellVectors, + double vorticity[3]) +{ + double* cellVel; + double derivs[9]; + + cellVel = cellVectors->GetPointer(0); + cell->Derivatives(0, pcoords, cellVel, 3, derivs); + vorticity[0] = derivs[7] - derivs[5]; + vorticity[1] = derivs[2] - derivs[6]; + vorticity[2] = derivs[3] - derivs[1]; + +} + +void vtkStreamTracer::InitializeSeeds(vtkDataArray*& seeds, + vtkIdList*& seedIds, + vtkIntArray*& integrationDirections, + vtkDataSet *source) +{ + seedIds = vtkIdList::New(); + integrationDirections = vtkIntArray::New(); + seeds=0; + + if (source) + { + int i; + vtkIdType numSeeds = source->GetNumberOfPoints(); + if (numSeeds > 0) + { + // For now, one thread will do all + + if (this->IntegrationDirection == BOTH) + { + seedIds->SetNumberOfIds(2*numSeeds); + for (i=0; iSetId(i, i); + seedIds->SetId(numSeeds + i, i); + } + } + else + { + seedIds->SetNumberOfIds(numSeeds); + for (i=0; iSetId(i, i); + } + } + // Check if the source is a PointSet + vtkPointSet* seedPts = vtkPointSet::SafeDownCast(source); + if (seedPts) + { + // If it is, use it's points as source + vtkDataArray* orgSeeds = seedPts->GetPoints()->GetData(); + seeds = orgSeeds->NewInstance(); + seeds->DeepCopy(orgSeeds); + } + else + { + // Else, create a seed source + seeds = vtkDoubleArray::New(); + seeds->SetNumberOfComponents(3); + seeds->SetNumberOfTuples(numSeeds); + for (i=0; iSetTuple(i, source->GetPoint(i)); + } + } + } + } + else + { + seeds = vtkDoubleArray::New(); + seeds->SetNumberOfComponents(3); + seeds->InsertNextTuple(this->StartPosition); + seedIds->InsertNextId(0); + if (this->IntegrationDirection == BOTH) + { + seedIds->InsertNextId(0); + } + } + + if (seeds) + { + vtkIdType i; + vtkIdType numSeeds = seeds->GetNumberOfTuples(); + if (this->IntegrationDirection == BOTH) + { + for(i=0; iInsertNextValue(FORWARD); + } + for(i=0; iInsertNextValue(BACKWARD); + } + } + else + { + for(i=0; iInsertNextValue(this->IntegrationDirection); + } + } + } +} + +int vtkStreamTracer::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkDataSet *source = 0; + if (sourceInfo) + { + source = vtkDataSet::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + } + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray* seeds = 0; + vtkIdList* seedIds = 0; + vtkIntArray* integrationDirections = 0; + this->InitializeSeeds(seeds, seedIds, integrationDirections, source); + + if (seeds) + { + double lastPoint[3]; + vtkInterpolatedVelocityField* func; + int maxCellSize = 0; + if (this->CheckInputs(func, &maxCellSize, inputVector) != VTK_OK) + { + vtkDebugMacro("No appropriate inputs have been found. Can not execute."); + func->Delete(); + seeds->Delete(); + integrationDirections->Delete(); + seedIds->Delete(); + return 1; + } + vtkDataArray *vectors = this->GetInputArrayToProcess(0,inputVector); + if (vectors) + { + const char *vecName = vectors->GetName(); + this->Integrate(input, output, + seeds, seedIds, + integrationDirections, + lastPoint, func, + maxCellSize, vecName); + } + func->Delete(); + seeds->Delete(); + } + + integrationDirections->Delete(); + seedIds->Delete(); + + return 1; +} + +int vtkStreamTracer::CheckInputs(vtkInterpolatedVelocityField*& func, + int* maxCellSize, + vtkInformationVector **inputVector) +{ + // Set the function set to be integrated + if (!this->InterpolatorPrototype) + { + func = vtkInterpolatedVelocityField::New(); + } + else + { + func = this->InterpolatorPrototype->NewInstance(); + func->CopyParameters(this->InterpolatorPrototype); + } + vtkDataArray *vectors = this->GetInputArrayToProcess(0,inputVector); + if (!vectors) + { + return 1; + } + const char *vecName = vectors->GetName(); + func->SelectVectors(vecName); + + // Add all the inputs ( except source, of course ) which + // have the appropriate vectors and compute the maximum + // cell size. + int numInputs = 0; + int numInputConnections = this->GetNumberOfInputConnections(0); + for (int i = 0; i < numInputConnections; i++) + { + vtkInformation *info = inputVector[0]->GetInformationObject(i); + vtkDataSet* inp = 0; + if (info) + { + inp = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + } + if (inp) + { + if (!inp->GetPointData()->GetVectors(vecName)) + { + vtkDebugMacro("Input " << i << "does not contain a velocity vector."); + continue; + } + int cellSize = inp->GetMaxCellSize(); + if ( cellSize > *maxCellSize ) + { + *maxCellSize = cellSize; + } + func->AddDataSet(inp); + numInputs++; + } + } + if ( numInputs == 0 ) + { + vtkDebugMacro("No appropriate inputs have been found. Can not execute."); + return VTK_ERROR; + } + return VTK_OK; +} + +void vtkStreamTracer::Integrate(vtkDataSet *input0, + vtkPolyData* output, + vtkDataArray* seedSource, + vtkIdList* seedIds, + vtkIntArray* integrationDirections, + double lastPoint[3], + vtkInterpolatedVelocityField* func, + int maxCellSize, + const char *vecName) +{ + int i; + vtkIdType numLines = seedIds->GetNumberOfIds(); + + // Useful pointers + vtkDataSetAttributes* outputPD = output->GetPointData(); + vtkDataSetAttributes* outputCD = output->GetCellData(); + vtkPointData* inputPD; + vtkDataSet* input; + vtkDataArray* inVectors; + + int direction=1; + + double* weights = 0; + if ( maxCellSize > 0 ) + { + weights = new double[maxCellSize]; + } + + if (this->GetIntegrator() == 0) + { + vtkErrorMacro("No integrator is specified."); + return; + } + + // Used in GetCell() + vtkGenericCell* cell = vtkGenericCell::New(); + + // Create a new integrator, the type is the same as Integrator + vtkInitialValueProblemSolver* integrator = + this->GetIntegrator()->NewInstance(); + integrator->SetFunctionSet(func); + + // Since we do not know what the total number of points + // will be, we do not allocate any. This is important for + // cases where a lot of streamers are used at once. If we + // were to allocate any points here, potentially, we can + // waste a lot of memory if a lot of streamers are used. + // Always insert the first point + vtkPoints* outputPoints = vtkPoints::New(); + vtkCellArray* outputLines = vtkCellArray::New(); + + // We will keep track of time in this array + vtkDoubleArray* time = vtkDoubleArray::New(); + time->SetName("IntegrationTime"); + + // This array explains why the integration stopped + vtkIntArray* retVals = vtkIntArray::New(); + retVals->SetName("ReasonForTermination"); + + vtkDoubleArray* cellVectors = 0; + vtkDoubleArray* vorticity = 0; + vtkDoubleArray* rotation = 0; + vtkDoubleArray* angularVel = 0; + if (this->ComputeVorticity) + { + cellVectors = vtkDoubleArray::New(); + cellVectors->SetNumberOfComponents(3); + cellVectors->Allocate(3*VTK_CELL_SIZE); + + vorticity = vtkDoubleArray::New(); + vorticity->SetName("Vorticity"); + vorticity->SetNumberOfComponents(3); + + rotation = vtkDoubleArray::New(); + rotation->SetName("Rotation"); + + angularVel = vtkDoubleArray::New(); + angularVel->SetName("AngularVelocity"); + } + + // We will interpolate all point attributes of the input on + // each point of the output (unless they are turned off) + // Note that we are using only the first input, if there are more + // than one, the attributes have to match. + outputPD->InterpolateAllocate(input0->GetPointData()); + // Note: It is an overestimation to have the estimate the same number of + // output points and input points. We sill have to squeeze at end. + + vtkIdType numPtsTotal=0; + double velocity[3]; + + int shouldAbort = 0; + + for(int currentLine = 0; currentLine < numLines; currentLine++) + { + + double progress = static_cast(currentLine)/numLines; + this->UpdateProgress(progress); + + switch (integrationDirections->GetValue(currentLine)) + { + case FORWARD: + direction = 1; + break; + case BACKWARD: + direction = -1; + break; + } + + // temporary variables used in the integration + double point1[3], point2[3], pcoords[3], vort[3], omega; + vtkIdType index, numPts=0; + + // Clear the last cell to avoid starting a search from + // the last point in the streamline + func->ClearLastCellId(); + + // Initial point + seedSource->GetTuple(seedIds->GetId(currentLine), point1); + memcpy(point2, point1, 3*sizeof(double)); + if (!func->FunctionValues(point1, velocity)) + { + continue; + } + + numPts++; + numPtsTotal++; + vtkIdType nextPoint = outputPoints->InsertNextPoint(point1); + time->InsertNextValue(0.0); + + // We will always pass a time step to the integrator. + // If the user specifies a step size with another unit, we will + // have to convert it to time. + IntervalInformation delT; + delT.Unit = TIME_UNIT; + delT.Interval = 0; + IntervalInformation aStep; + aStep.Unit = this->MaximumPropagation.Unit; + double propagation = 0.0, step, minStep=0, maxStep=0; + double stepTaken, accumTime=0; + double speed; + double cellLength; + int retVal=OUT_OF_TIME, tmp; + + // Make sure we use the dataset found by the vtkInterpolatedVelocityField + input = func->GetLastDataSet(); + inputPD = input->GetPointData(); + inVectors = inputPD->GetVectors(vecName); + + // Convert intervals to time unit + input->GetCell(func->GetLastCellId(), cell); + cellLength = sqrt(static_cast(cell->GetLength2())); + speed = vtkMath::Norm(velocity); + + // Never call conversion methods if speed == 0 + if (speed != 0.0) + { + this->ConvertIntervals(delT.Interval, minStep, maxStep, direction, + cellLength, speed); + } + + // Interpolate all point attributes on first point + func->GetLastWeights(weights); + outputPD->InterpolatePoint(inputPD, nextPoint, cell->PointIds, weights); + + // Compute vorticity if required + // This can be used later for streamribbon generation. + if (this->ComputeVorticity) + { + inVectors->GetTuples(cell->PointIds, cellVectors); + func->GetLastLocalCoordinates(pcoords); + vtkStreamTracer::CalculateVorticity(cell, pcoords, cellVectors, vort); + vorticity->InsertNextTuple(vort); + // rotation + // local rotation = vorticity . unit tangent ( i.e. velocity/speed ) + if (speed != 0.0) + { + omega = vtkMath::Dot(vort, velocity); + omega /= speed; + omega *= this->RotationScale; + } + else + { + omega = 0.0; + } + angularVel->InsertNextValue(omega); + rotation->InsertNextValue(0.0); + } + + vtkIdType numSteps = 0; + double error = 0; + // Integrate until the maximum propagation length is reached, + // maximum number of steps is reached or until a boundary is encountered. + // Begin Integration + while ( propagation < this->MaximumPropagation.Interval ) + { + + if (numSteps > this->MaximumNumberOfSteps) + { + retVal = OUT_OF_STEPS; + break; + } + + if ( numSteps++ % 1000 == 1 ) + { + progress = + (currentLine + propagation / this->MaximumPropagation.Interval) / + numLines ; + this->UpdateProgress(progress); + + if (this->GetAbortExecute()) + { + shouldAbort = 1; + break; + } + } + + // Never call conversion methods if speed == 0 + if ( (speed == 0) || (speed <= this->TerminalSpeed) ) + { + retVal = STAGNATION; + break; + } + + // If, with the next step, propagation will be larger than + // max, reduce it so that it is (approximately) equal to max. + aStep.Interval = fabs(this->ConvertToUnit(delT, + this->MaximumPropagation.Unit, + cellLength, speed)); + if ( (propagation + aStep.Interval) > + this->MaximumPropagation.Interval ) + { + aStep.Interval = this->MaximumPropagation.Interval - propagation; + if (delT.Interval >= 0) + { + delT.Interval = this->ConvertToTime(aStep, cellLength, speed); + } + else + { + delT.Interval = -1.0 * this->ConvertToTime(aStep, cellLength, speed); + } + maxStep = delT.Interval; + } + this->LastUsedTimeStep = delT.Interval; + + // Calculate the next step using the integrator provided + // Break if the next point is out of bounds. + if ((tmp= + integrator->ComputeNextStep(point1, point2, 0, delT.Interval, + stepTaken, minStep, maxStep, + this->MaximumError, error)) != 0) + { + retVal = tmp; + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + + // It is not enough to use the starting point for stagnation calculation + // Use delX/delT to calculate speed and check if it is below + // stagnation threshold + double disp[3]; + for (i=0; i<3; i++) + { + disp[i] = point2[i] - point1[i]; + } + if ( (delT.Interval == 0) || + (vtkMath::Norm(disp) / fabs(delT.Interval) <= this->TerminalSpeed) ) + { + retVal = STAGNATION; + break; + } + + accumTime += stepTaken; + // Calculate propagation (using the same units as MaximumPropagation + propagation += fabs(this->ConvertToUnit(delT, + this->MaximumPropagation.Unit, + cellLength, speed)); + + + + // This is the next starting point + for(i=0; i<3; i++) + { + point1[i] = point2[i]; + } + + // Interpolate the velocity at the next point + if ( !func->FunctionValues(point2, velocity) ) + { + retVal = OUT_OF_DOMAIN; + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + // Make sure we use the dataset found by the vtkInterpolatedVelocityField + input = func->GetLastDataSet(); + inputPD = input->GetPointData(); + inVectors = inputPD->GetVectors(vecName); + + // Point is valid. Insert it. + numPts++; + numPtsTotal++; + nextPoint = outputPoints->InsertNextPoint(point1); + time->InsertNextValue(accumTime); + + // Calculate cell length and speed to be used in unit conversions + input->GetCell(func->GetLastCellId(), cell); + cellLength = sqrt(static_cast(cell->GetLength2())); + speed = vtkMath::Norm(velocity); + + // Interpolate all point attributes on current point + func->GetLastWeights(weights); + outputPD->InterpolatePoint(inputPD, nextPoint, cell->PointIds, weights); + + // Compute vorticity if required + // This can be used later for streamribbon generation. + if (this->ComputeVorticity) + { + inVectors->GetTuples(cell->PointIds, cellVectors); + func->GetLastLocalCoordinates(pcoords); + vtkStreamTracer::CalculateVorticity(cell, pcoords, cellVectors, vort); + vorticity->InsertNextTuple(vort); + // rotation + // angular velocity = vorticity . unit tangent ( i.e. velocity/speed ) + // rotation = sum ( angular velocity * delT ) + omega = vtkMath::Dot(vort, velocity); + omega /= speed; + omega *= this->RotationScale; + index = angularVel->InsertNextValue(omega); + rotation->InsertNextValue(rotation->GetValue(index-1) + + (angularVel->GetValue(index-1) + omega)/2 * + (accumTime - time->GetValue(index-1))); + } + + // Never call conversion methods if speed == 0 + if ( (speed == 0) || (speed <= this->TerminalSpeed) ) + { + retVal = STAGNATION; + break; + } + + // Convert all intervals to time + this->ConvertIntervals(step, minStep, maxStep, direction, + cellLength, speed); + + + // If the solver is adaptive and the next time step (delT.Interval) + // that the solver wants to use is smaller than minStep or larger + // than maxStep, re-adjust it. This has to be done every step + // because minStep and maxStep can change depending on the cell + // size (unless it is specified in time units) + if (integrator->IsAdaptive()) + { + if (fabs(delT.Interval) < fabs(minStep)) + { + delT.Interval = fabs(minStep) * delT.Interval/fabs(delT.Interval); + } + else if (fabs(delT.Interval) > fabs(maxStep)) + { + delT.Interval = fabs(maxStep) * delT.Interval/fabs(delT.Interval); + } + } + else + { + delT.Interval = step; + } + + // End Integration + } + + if (shouldAbort) + { + break; + } + + if (numPts > 1) + { + outputLines->InsertNextCell(numPts); + for (i=numPtsTotal-numPts; iInsertCellPoint(i); + } + retVals->InsertNextValue(retVal); + } + } + + if (!shouldAbort) + { + // Create the output polyline + output->SetPoints(outputPoints); + outputPD->AddArray(time); + if (vorticity) + { + outputPD->AddArray(vorticity); + outputPD->AddArray(rotation); + outputPD->AddArray(angularVel); + } + + vtkIdType numPts = outputPoints->GetNumberOfPoints(); + if ( numPts > 1 ) + { + // Assign geometry and attributes + output->SetLines(outputLines); + if (this->GenerateNormalsInIntegrate) + { + this->GenerateNormals(output, 0, vecName); + } + + outputCD->AddArray(retVals); + } + } + + if (vorticity) + { + vorticity->Delete(); + rotation->Delete(); + angularVel->Delete(); + } + + if (cellVectors) + { + cellVectors->Delete(); + } + retVals->Delete(); + + outputPoints->Delete(); + outputLines->Delete(); + + time->Delete(); + + + integrator->Delete(); + cell->Delete(); + + delete[] weights; + + output->Squeeze(); + return; +} + +void vtkStreamTracer::GenerateNormals(vtkPolyData* output, double* firstNormal, + const char *vecName) +{ + // Useful pointers + vtkDataSetAttributes* outputPD = output->GetPointData(); + + vtkPoints* outputPoints = output->GetPoints(); + vtkCellArray* outputLines = output->GetLines(); + + vtkDataArray* rotation = outputPD->GetArray("Rotation"); + + vtkIdType numPts = outputPoints->GetNumberOfPoints(); + if ( numPts > 1 ) + { + if (this->ComputeVorticity) + { + vtkPolyLine* lineNormalGenerator = vtkPolyLine::New(); + vtkDoubleArray* normals = vtkDoubleArray::New(); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(numPts); + // Make sure the normals are initialized in case + // GenerateSlidingNormals() fails and returns before + // creating all normals + for(vtkIdType idx=0; idxSetTuple3(idx, 1, 0, 0); + } + + lineNormalGenerator->GenerateSlidingNormals(outputPoints, + outputLines, + normals, + firstNormal); + lineNormalGenerator->Delete(); + + vtkIdType i; + int j; + double normal[3], local1[3], local2[3], theta, costheta, sintheta, length; + double velocity[3]; + normals->SetName("Normals"); + vtkDataArray* newVectors = + outputPD->GetVectors(vecName); + for(i=0; iGetTuple(i, normal); + if (newVectors == NULL) + { // This should never happen. + vtkErrorMacro("Could not find output array."); + return; + } + newVectors->GetTuple(i, velocity); + // obtain two unit orthogonal vectors on the plane perpendicular to + // the streamline + for(j=0; j<3; j++) { local1[j] = normal[j]; } + length = vtkMath::Normalize(local1); + vtkMath::Cross(local1, velocity, local2); + vtkMath::Normalize(local2); + // Rotate the normal with theta + rotation->GetTuple(i, &theta); + costheta = cos(theta); + sintheta = sin(theta); + for(j=0; j<3; j++) + { + normal[j] = length* (costheta*local1[j] + sintheta*local2[j]); + } + normals->SetTuple(i, normal); + } + outputPD->AddArray(normals); + outputPD->SetActiveAttribute("Normals", vtkDataSetAttributes::VECTORS); + normals->Delete(); + } + } +} + + +// This is used by sub-classes in certain situations. It +// does a lot less (for example, does not compute attributes) +// than Integrate. +void vtkStreamTracer::SimpleIntegrate(double seed[3], + double lastPoint[3], + double delt, + vtkInterpolatedVelocityField* func) +{ + vtkIdType numSteps = 0; + vtkIdType maxSteps = 20; + double error = 0; + double stepTaken; + double point1[3], point2[3]; + double velocity[3]; + double speed; + + (void)seed; // Seed is not used + + memcpy(point1, lastPoint, 3*sizeof(double)); + + // Create a new integrator, the type is the same as Integrator + vtkInitialValueProblemSolver* integrator = + this->GetIntegrator()->NewInstance(); + integrator->SetFunctionSet(func); + + while ( 1 ) + { + + if (numSteps++ > maxSteps) + { + break; + } + + // Calculate the next step using the integrator provided + // Break if the next point is out of bounds. + if (integrator->ComputeNextStep(point1, point2, 0, delt, + stepTaken, 0, 0, 0, error) != 0) + { + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + + + // This is the next starting point + for(int i=0; i<3; i++) + { + point1[i] = point2[i]; + } + + // Interpolate the velocity at the next point + if ( !func->FunctionValues(point2, velocity) ) + { + memcpy(lastPoint, point2, 3*sizeof(double)); + break; + } + + speed = vtkMath::Norm(velocity); + + // Never call conversion methods if speed == 0 + if ( (speed == 0) || (speed <= this->TerminalSpeed) ) + { + break; + } + + memcpy(point1, point2, 3*sizeof(double)); + // End Integration + } + + integrator->Delete(); +} + +int vtkStreamTracer::FillInputPortInformation(int port, vtkInformation *info) +{ + if (port == 0) + { + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + } + else if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkStreamTracer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Start position: " + << this->StartPosition[0] << " " + << this->StartPosition[1] << " " + << this->StartPosition[2] << endl; + os << indent << "Terminal speed: " << this->TerminalSpeed << endl; + os << indent << "Maximum propagation: " << this->MaximumPropagation.Interval + << " unit: "; + switch (this->MaximumPropagation.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Min. integration step: " + << this->MinimumIntegrationStep.Interval + << " unit: "; + switch (this->MinimumIntegrationStep.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Max. integration step: " + << this->MaximumIntegrationStep.Interval + << " unit: "; + switch (this->MaximumIntegrationStep.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Initial integration step: " + << this->InitialIntegrationStep.Interval + << " unit: "; + switch (this->InitialIntegrationStep.Unit) + { + case TIME_UNIT: + os << "time."; + break; + case LENGTH_UNIT: + os << "length."; + break; + case CELL_LENGTH_UNIT: + os << "cell length."; + break; + } + os << endl; + + os << indent << "Integration direction: "; + switch (this->IntegrationDirection) + { + case FORWARD: + os << "forward."; + break; + case BACKWARD: + os << "backward."; + break; + } + os << endl; + + os << indent << "Integrator: " << this->Integrator << endl; + os << indent << "Maximum error: " << this->MaximumError << endl; + os << indent << "Max. number of steps: " << this->MaximumNumberOfSteps + << endl; + os << indent << "Vorticity computation: " + << (this->ComputeVorticity ? " On" : " Off") << endl; + os << indent << "Rotation scale: " << this->RotationScale << endl; +} diff --git a/Graphics/vtkStreamTracer.h b/Graphics/vtkStreamTracer.h new file mode 100644 index 0000000..4c66c0d --- /dev/null +++ b/Graphics/vtkStreamTracer.h @@ -0,0 +1,388 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamTracer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStreamTracer - Streamline generator +// .SECTION Description +// vtkStreamTracer is a filter that integrates a vector field to generate +// streamlines. The integration is performed using the provided integrator. +// The default is second order Runge-Kutta. +// +// vtkStreamTracer generate polylines as output. Each cell (polyline) +// corresponds to one streamline. The values associated with each streamline +// are stored in the cell data whereas the values associated with points +// are stored in point data. +// +// Note that vtkStreamTracer can integrate both forward and backward. +// The length of the streamline is controlled by specifying either +// a maximum value in the units of length, cell length or elapsed time +// (the elapsed time is the time each particle would have traveled if +// flow were steady). Otherwise, the integration terminates after exiting +// the dataset or if the particle speed is reduced to a value less than +// the terminal speed or when a maximum number of steps is reached. +// The reason for the termination is stored in a cell array named +// ReasonForTermination. +// +// The quality of integration can be controlled by setting integration +// step (InitialIntegrationStep) and in the case of adaptive solvers +// the maximum error, the minimum integration step and the maximum +// integration step. All of these can have units of length, cell length +// or elapsed time. +// +// The integration time, vorticity, rotation and angular velocity +// are stored in point arrays named "IntegrationTime", "Vorticity", +// "Rotation" and "AngularVelocity" respectively (vorticity, rotation +// and angular velocity are computed only when ComputeVorticity is on). +// All point attributes in the source data set are interpolated on the +// new streamline points. +// +// vtkStreamTracer integrates through any type of dataset. As a result, if the +// dataset contains 2D cells such as polygons or triangles, the integration is +// constrained to lie on the surface defined by the 2D cells. +// +// The starting point of traces may be defined in two different ways. +// Starting from global x-y-z "position" allows you to start a single trace +// at a specified x-y-z coordinate. If you specify a source object, +// a trace will be generated for each point in the source that is +// inside the dataset. +// +// .SECTION See Also +// vtkRibbonFilter vtkRuledSurfaceFilter vtkInitialValueProblemSolver +// vtkRungeKutta2 vtkRungeKutta4 vtkRungeKutta45 + +#ifndef __vtkStreamTracer_h +#define __vtkStreamTracer_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkInitialValueProblemSolver.h" // Needed for constants + +class vtkDataArray; +class vtkDoubleArray; +class vtkGenericCell; +class vtkIdList; +class vtkIntArray; +class vtkInterpolatedVelocityField; + +class VTK_GRAPHICS_EXPORT vtkStreamTracer : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkStreamTracer,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object to start from position (0,0,0), integrate forward, + // terminal speed 1.0E-12, vorticity computation on, integration + // step length 0.5 (unit cell length), maximum number of steps 2000, + // using 2nd order Runge Kutta and maximum propagation 1.0 (unit length). + static vtkStreamTracer *New(); + + // Description: + // Specify the start of the streamline in the global coordinate + // system. Search must be performed to find initial cell to start + // integration from. + vtkSetVector3Macro(StartPosition, double); + vtkGetVector3Macro(StartPosition, double); + + // Description: + // Specify the source object used to generate starting points. + // Old style. Do not use. + void SetSource(vtkDataSet *source); + vtkDataSet *GetSource(); + + // Description: + // Specify the source object used to generate starting points. + // New style. + void SetSourceConnection(vtkAlgorithmOutput* algOutput); + +//BTX + enum Units + { + TIME_UNIT, + LENGTH_UNIT, + CELL_LENGTH_UNIT + }; + + enum Solvers + { + RUNGE_KUTTA2, + RUNGE_KUTTA4, + RUNGE_KUTTA45, + NONE, + UNKNOWN + }; + + enum ReasonForTermination + { + OUT_OF_DOMAIN = vtkInitialValueProblemSolver::OUT_OF_DOMAIN, + NOT_INITIALIZED = vtkInitialValueProblemSolver::NOT_INITIALIZED , + UNEXPECTED_VALUE = vtkInitialValueProblemSolver::UNEXPECTED_VALUE, + OUT_OF_TIME = 4, + OUT_OF_STEPS = 5, + STAGNATION = 6 + }; +//ETX + + // Description: + // Set/get the integrator type to be used in the stream line + // calculation. The object passed is not actually used but + // is cloned with NewInstance in the process of integration + // (prototype pattern). The default is 2nd order Runge Kutta. + // The integrator can also be changed using SetIntegratorType. + // The recognized solvers are: + // RUNGE_KUTTA2 = 0 + // RUNGE_KUTTA4 = 1 + // RUNGE_KUTTA45 = 2 + void SetIntegrator(vtkInitialValueProblemSolver *); + vtkGetObjectMacro ( Integrator, vtkInitialValueProblemSolver ); + void SetIntegratorType(int type); + int GetIntegratorType(); + void SetIntegratorTypeToRungeKutta2() + {this->SetIntegratorType(RUNGE_KUTTA2);}; + void SetIntegratorTypeToRungeKutta4() + {this->SetIntegratorType(RUNGE_KUTTA4);}; + void SetIntegratorTypeToRungeKutta45() + {this->SetIntegratorType(RUNGE_KUTTA45);}; + + // Description: + // Specify the maximum length of the streamlines expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + void SetMaximumPropagation(int unit, double max); + void SetMaximumPropagation(double max); + void SetMaximumPropagationUnit(int unit); + int GetMaximumPropagationUnit(); + double GetMaximumPropagation(); + void SetMaximumPropagationUnitToTimeUnit() + {this->SetMaximumPropagationUnit(TIME_UNIT);}; + void SetMaximumPropagationUnitToLengthUnit() + {this->SetMaximumPropagationUnit(LENGTH_UNIT);}; + void SetMaximumPropagationUnitToCellLengthUnit() + {this->SetMaximumPropagationUnit(CELL_LENGTH_UNIT);}; + + // Description: + // Specify the minimum step used in the integration expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + // Only valid when using adaptive integrators. + void SetMinimumIntegrationStep(int unit, double step); + void SetMinimumIntegrationStepUnit(int unit); + void SetMinimumIntegrationStep(double step); + int GetMinimumIntegrationStepUnit(); + double GetMinimumIntegrationStep(); + void SetMinimumIntegrationStepUnitToTimeUnit() + {this->SetMinimumIntegrationStepUnit(TIME_UNIT);}; + void SetMinimumIntegrationStepUnitToLengthUnit() + {this->SetMinimumIntegrationStepUnit(LENGTH_UNIT);}; + void SetMinimumIntegrationStepUnitToCellLengthUnit() + {this->SetMinimumIntegrationStepUnit(CELL_LENGTH_UNIT);}; + + // Description: + // Specify the maximum step used in the integration expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + // Only valid when using adaptive integrators. + void SetMaximumIntegrationStep(int unit, double step); + void SetMaximumIntegrationStepUnit(int unit); + void SetMaximumIntegrationStep(double step); + int GetMaximumIntegrationStepUnit(); + double GetMaximumIntegrationStep(); + void SetMaximumIntegrationStepUnitToTimeUnit() + {this->SetMaximumIntegrationStepUnit(TIME_UNIT);}; + void SetMaximumIntegrationStepUnitToLengthUnit() + {this->SetMaximumIntegrationStepUnit(LENGTH_UNIT);}; + void SetMaximumIntegrationStepUnitToCellLengthUnit() + {this->SetMaximumIntegrationStepUnit(CELL_LENGTH_UNIT);}; + + // Description: + // Specify the initial step used in the integration expressed in + // one of the: + // TIME_UNIT = 0 + // LENGTH_UNIT = 1 + // CELL_LENGTH_UNIT = 2 + // If the integrator is not adaptive, this is the actual + // step used. + void SetInitialIntegrationStep(int unit, double step); + void SetInitialIntegrationStepUnit(int unit); + void SetInitialIntegrationStep(double step); + int GetInitialIntegrationStepUnit(); + double GetInitialIntegrationStep(); + void SetInitialIntegrationStepUnitToTimeUnit() + {this->SetInitialIntegrationStepUnit(TIME_UNIT);}; + void SetInitialIntegrationStepUnitToLengthUnit() + {this->SetInitialIntegrationStepUnit(LENGTH_UNIT);}; + void SetInitialIntegrationStepUnitToCellLengthUnit() + {this->SetInitialIntegrationStepUnit(CELL_LENGTH_UNIT);}; + + // Description + // Specify the maximum error in the integration. This value + // is passed to the integrator. Therefore, it's meaning depends + // on the integrator used. + vtkSetMacro(MaximumError, double); + vtkGetMacro(MaximumError, double); + + // Description + // Specify the maximum number of steps used in the integration. + vtkSetMacro(MaximumNumberOfSteps, vtkIdType); + vtkGetMacro(MaximumNumberOfSteps, vtkIdType); + + // Description + // If at any point, the speed is below this value, the integration + // is terminated. + vtkSetMacro(TerminalSpeed, double); + vtkGetMacro(TerminalSpeed, double); + +//BTX + enum + { + FORWARD, + BACKWARD, + BOTH + }; +//ETX + + // Description: + // Specify whether the streamtrace will be generated in the + // upstream or downstream direction. + vtkSetClampMacro(IntegrationDirection, int, FORWARD, BOTH); + vtkGetMacro(IntegrationDirection, int); + void SetIntegrationDirectionToForward() + {this->SetIntegrationDirection(FORWARD);}; + void SetIntegrationDirectionToBackward() + {this->SetIntegrationDirection(BACKWARD);}; + void SetIntegrationDirectionToBoth() + {this->SetIntegrationDirection(BOTH);}; + + // Description + // Turn on/off calculation of vorticity at streamline points + // (necessary for generating proper streamribbons using the + // vtkRibbonFilter. + vtkSetMacro(ComputeVorticity, int); + vtkGetMacro(ComputeVorticity, int); + vtkBooleanMacro(ComputeVorticity, int); + + // Description + // This can be used to scale the rate with which the streamribbons + // twist. The default is 1. + vtkSetMacro(RotationScale, double); + vtkGetMacro(RotationScale, double); + + // Description: + // Add a dataset to the list inputs + void AddInput(vtkDataSet *in); + + // Description: + void SetInterpolatorPrototype(vtkInterpolatedVelocityField* ivf); + +protected: + + vtkStreamTracer(); + ~vtkStreamTracer(); + + // hide the superclass' AddInput() from the user and the compiler + void AddInput(vtkDataObject *) + { vtkErrorMacro( << "AddInput() must be called with a vtkDataSet not a vtkDataObject."); }; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int, vtkInformation *); + + void CalculateVorticity( vtkGenericCell* cell, double pcoords[3], + vtkDoubleArray* cellVectors, double vorticity[3] ); + void Integrate(vtkDataSet *input, + vtkPolyData* output, + vtkDataArray* seedSource, + vtkIdList* seedIds, + vtkIntArray* integrationDirections, + double lastPoint[3], + vtkInterpolatedVelocityField* func, + int maxCellSize, + const char *vecFieldName); + void SimpleIntegrate(double seed[3], + double lastPoint[3], + double delt, + vtkInterpolatedVelocityField* func); + int CheckInputs(vtkInterpolatedVelocityField*& func, + int* maxCellSize, + vtkInformationVector **inputVector); + void GenerateNormals(vtkPolyData* output, double* firstNormal, const char *vecName); + + int GenerateNormalsInIntegrate; + + // starting from global x-y-z position + double StartPosition[3]; + + static const double EPSILON; + double TerminalSpeed; + + double LastUsedTimeStep; + +//BTX + struct IntervalInformation + { + double Interval; + int Unit; + }; + + IntervalInformation MaximumPropagation; + IntervalInformation MinimumIntegrationStep; + IntervalInformation MaximumIntegrationStep; + IntervalInformation InitialIntegrationStep; + + void SetIntervalInformation(int unit, double interval, + IntervalInformation& currentValues); + void SetIntervalInformation(int unit,IntervalInformation& currentValues); + static double ConvertToTime(IntervalInformation& interval, + double cellLength, double speed); + static double ConvertToLength(IntervalInformation& interval, + double cellLength, double speed); + static double ConvertToCellLength(IntervalInformation& interval, + double cellLength, double speed); + static double ConvertToUnit(IntervalInformation& interval, int unit, + double cellLength, double speed); + void ConvertIntervals(double& step, double& minStep, double& maxStep, + int direction, double cellLength, double speed); +//ETX + + void InitializeSeeds(vtkDataArray*& seeds, + vtkIdList*& seedIds, + vtkIntArray*& integrationDirections, + vtkDataSet *source); + + int IntegrationDirection; + + // Prototype showing the integrator type to be set by the user. + vtkInitialValueProblemSolver* Integrator; + + double MaximumError; + vtkIdType MaximumNumberOfSteps; + + int ComputeVorticity; + double RotationScale; + + vtkInterpolatedVelocityField* InterpolatorPrototype; + +private: + vtkStreamTracer(const vtkStreamTracer&); // Not implemented. + void operator=(const vtkStreamTracer&); // Not implemented. +}; + + +#endif + + diff --git a/Graphics/vtkStreamer.cxx b/Graphics/vtkStreamer.cxx new file mode 100644 index 0000000..6e14984 --- /dev/null +++ b/Graphics/vtkStreamer.cxx @@ -0,0 +1,757 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStreamer.h" + +#include "vtkCell.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkExecutive.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInterpolatedVelocityField.h" +#include "vtkMath.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkRungeKutta2.h" + +vtkCxxRevisionMacro(vtkStreamer, "$Revision: 1.93 $"); +vtkCxxSetObjectMacro(vtkStreamer,Integrator,vtkInitialValueProblemSolver); + +#define VTK_START_FROM_POSITION 0 +#define VTK_START_FROM_LOCATION 1 + +struct vtkStreamerThreadStruct +{ + vtkStreamer *Filter; + vtkDataSet *Input; + vtkDataSet *Source; +}; + +vtkStreamer::StreamArray::StreamArray() +{ + this->MaxId = -1; + this->Array = new vtkStreamer::StreamPoint[1000]; + this->Size = 1000; + this->Extend = 5000; + this->Direction = VTK_INTEGRATE_FORWARD; +} + +vtkStreamer::StreamPoint *vtkStreamer::StreamArray::Resize(vtkIdType sz) +{ + vtkStreamer::StreamPoint *newArray; + vtkIdType newSize; + + if (sz >= this->Size) + { + newSize = this->Size + + this->Extend*(((sz-this->Size)/this->Extend)+1); + } + else + { + newSize = sz; + } + + newArray = new vtkStreamer::StreamPoint[newSize]; + + memcpy(newArray, this->Array, + (sz < this->Size ? sz : this->Size) * sizeof(vtkStreamer::StreamPoint)); + + this->Size = newSize; + delete [] this->Array; + this->Array = newArray; + + return this->Array; +} + +// Construct object to start from position (0,0,0); integrate forward; terminal +// speed 0.0; vorticity computation off; integrations step length 0.2; and +// maximum propagation time 100.0. +vtkStreamer::vtkStreamer() +{ + this->StartFrom = VTK_START_FROM_POSITION; + + this->StartCell = 0; + this->StartSubId = 0; + this->StartPCoords[0] = this->StartPCoords[1] = this->StartPCoords[2] = 0.5; + this->StartPosition[0] = this->StartPosition[1] = this->StartPosition[2] = 0.0; + this->Streamers = NULL; + this->MaximumPropagationTime = 100.0; + this->IntegrationDirection = VTK_INTEGRATE_FORWARD; + this->IntegrationStepLength = 0.2; + this->Vorticity = 0; + this->TerminalSpeed = 0.0; + this->SpeedScalars = 0; + this->OrientationScalars = 0; + this->NumberOfStreamers = 0; + this->Threader = vtkMultiThreader::New(); + this->NumberOfThreads = this->Threader->GetNumberOfThreads(); + this->Integrator = vtkRungeKutta2::New(); + this->SavePointInterval = 0.00001; + + this->SetNumberOfInputPorts(2); +} + +vtkStreamer::~vtkStreamer() +{ + if( this->Streamers ) + { + delete [] this->Streamers; + } + + if (this->Threader) + { + this->Threader->Delete(); + } + this->SetIntegrator(0); +} + +void vtkStreamer::SetSource(vtkDataSet *source) +{ + this->SetInput(1, source); +} + +vtkDataSet *vtkStreamer::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +// Specify the start of the streamline in the cell coordinate system. That is, +// cellId and subId (if composite cell), and parametric coordinates. +void vtkStreamer::SetStartLocation(vtkIdType cellId, int subId, + double pcoords[3]) +{ + if ( cellId != this->StartCell || subId != this->StartSubId || + pcoords[0] != this->StartPCoords[0] || + pcoords[1] != this->StartPCoords[1] || + pcoords[2] != this->StartPCoords[2] ) + { + this->Modified(); + this->StartFrom = VTK_START_FROM_LOCATION; + + this->StartCell = cellId; + this->StartSubId = subId; + this->StartPCoords[0] = pcoords[0]; + this->StartPCoords[1] = pcoords[1]; + this->StartPCoords[2] = pcoords[2]; + } +} + +// Specify the start of the streamline in the cell coordinate system. That is, +// cellId and subId (if composite cell), and parametric coordinates. +void vtkStreamer::SetStartLocation(vtkIdType cellId, int subId, double r, + double s, double t) +{ + double pcoords[3]; + pcoords[0] = r; + pcoords[1] = s; + pcoords[2] = t; + + this->SetStartLocation(cellId, subId, pcoords); +} + +// Get the starting location of the streamline in the cell coordinate system. +vtkIdType vtkStreamer::GetStartLocation(int& subId, double pcoords[3]) +{ + subId = this->StartSubId; + pcoords[0] = this->StartPCoords[0]; + pcoords[1] = this->StartPCoords[1]; + pcoords[2] = this->StartPCoords[2]; + return this->StartCell; +} + +// Specify the start of the streamline in the global coordinate system. Search +// must be performed to find initial cell to start integration from. +void vtkStreamer::SetStartPosition(double x[3]) +{ + if ( x[0] != this->StartPosition[0] || x[1] != this->StartPosition[1] || + x[2] != this->StartPosition[2] ) + { + this->Modified(); + this->StartFrom = VTK_START_FROM_POSITION; + + this->StartPosition[0] = x[0]; + this->StartPosition[1] = x[1]; + this->StartPosition[2] = x[2]; + } +} + +// Specify the start of the streamline in the global coordinate system. Search +// must be performed to find initial cell to start integration from. +void vtkStreamer::SetStartPosition(double x, double y, double z) +{ + double pos[3]; + pos[0] = x; + pos[1] = y; + pos[2] = z; + + this->SetStartPosition(pos); +} + +// Get the start position in global x-y-z coordinates. +double *vtkStreamer::GetStartPosition() +{ + return this->StartPosition; +} + +static const double VTK_EPSILON=1E-12; + +VTK_THREAD_RETURN_TYPE vtkStreamer::ThreadedIntegrate( void *arg ) +{ + vtkStreamer *self; + vtkStreamerThreadStruct *str; + int thread_count; + int thread_id; + vtkStreamer::StreamArray *streamer; + vtkStreamer::StreamPoint *sNext = 0, *sPtr; + vtkStreamer::StreamPoint pt1, pt2; + int i; + vtkIdType idxNext, ptId; + double d, step, dir; + double xNext[3], vel[3]; + double *cellVel; + double derivs[9]; + double *w, pcoords[3]; + double coords[4]; + vtkDataSet *input; + vtkGenericCell *cell; + vtkPointData *pd; + vtkDataArray *inScalars; + vtkDataArray *inVectors; + vtkDoubleArray *cellVectors; + vtkDataArray *cellScalars=0; + double tOffset, vort[3]; + double err; + int counter=0; + + thread_id = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + thread_count = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + str = (vtkStreamerThreadStruct*)(((vtkMultiThreader::ThreadInfo *)(arg))->UserData); + self = str->Filter; + + input = str->Input; + pd = input->GetPointData(); + inScalars = pd->GetScalars(); + inVectors = pd->GetVectors(); + + cell = vtkGenericCell::New(); + cellVectors = vtkDoubleArray::New(); + cellVectors->SetNumberOfComponents(3); + cellVectors->Allocate(3*VTK_CELL_SIZE); + if (inScalars) + { + cellScalars = inScalars->NewInstance(); + cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + cellScalars->Allocate(inScalars->GetNumberOfComponents()*VTK_CELL_SIZE); + } + + w = new double[input->GetMaxCellSize()]; + + // Set the function set to be integrated + vtkInterpolatedVelocityField* func = vtkInterpolatedVelocityField::New(); + func->AddDataSet(input); + + if (self->GetIntegrator() == 0) + { + vtkGenericWarningMacro("No integrator is specified."); + return VTK_THREAD_RETURN_VALUE; + } + + // Create a new integrator, the type is the same as Integrator + vtkInitialValueProblemSolver* integrator = + self->GetIntegrator()->NewInstance(); + integrator->SetFunctionSet(func); + + // Used to avoid calling these function many times during + // the integration + double termspeed = self->GetTerminalSpeed(); + double maxtime = self->GetMaximumPropagationTime(); + double savePointInterval = self->GetSavePointInterval(); + + // For each streamer, integrate in appropriate direction + // Do only the streamers that this thread should handle. + for (ptId=0; ptId < self->GetNumberOfStreamers(); ptId++) + { + if ( ptId % thread_count == thread_id ) + { + // Get starting step + streamer = self->GetStreamers() + ptId; + sPtr = streamer->GetStreamPoint(0); + if ( sPtr->cellId < 0 ) + { + continue; + } + // Set the last cell id in the vtkInterpolatedVelocityField + // object to speed up FindCell calls + func->SetLastCellId(sPtr->cellId); + + dir = streamer->Direction; + + // Copy the first point + pt1 = *sPtr; + pt2 = *sPtr; + tOffset = pt1.t; + + //integrate until time has been exceeded + while ( pt1.cellId >= 0 && pt1.speed > termspeed && pt1.t < maxtime ) + { + + if ( counter++ % 1000 == 0 ) + { + if (!thread_id) + { + self->UpdateProgress((double)ptId/self->GetNumberOfStreamers() + +pt1.t/maxtime/self->GetNumberOfStreamers()); + } + if (self->GetAbortExecute()) + { + break; + } + } + + // Set the integration step to be characteristic cell length + // time IntegrationStepLength + input->GetCell(pt1.cellId, cell); + step = dir*self->GetIntegrationStepLength() + * sqrt((double)cell->GetLength2())/pt1.speed; + + // Calculate the next step using the integrator provided + if (integrator->ComputeNextStep(pt1.x, pt1.v, xNext, 0, step, 0, err) + != 0) + { + break; + } + + for(i=0; i<3; i++) + { + coords[i] = xNext[i]; + } + + // Interpolate the velocity field at coords + if ( !func->FunctionValues(coords, vel) ) + { + break; + } + + for(i=0; i<3; i++) + { + pt2.v[i] = vel[i]; + } + + for (i=0; i<3; i++) + { + pt2.x[i] = xNext[i]; + } + + pt2.cellId = func->GetLastCellId(); + func->GetLastWeights(w); + func->GetLastLocalCoordinates(pcoords); + input->GetCell(pt2.cellId, cell); + + if ( inScalars ) + { + // Interpolate scalars + inScalars->GetTuples(cell->PointIds, cellScalars); + for (pt2.s=0.0, i=0; i < cell->GetNumberOfPoints(); i++) + { + pt2.s += cellScalars->GetComponent(i,0) * w[i]; + } + } + + pt2.speed = vtkMath::Norm(pt2.v); + + d = sqrt((double)vtkMath::Distance2BetweenPoints(pt1.x,pt2.x)); + pt2.d = pt1.d + d; + // If at stagnation region, stop the integration + if ( d == 0 || (pt1.speed + pt2.speed) < VTK_EPSILON ) + { + pt2.t = pt1.t; + break; + } + pt2.t = pt1.t + (2.0 * d / (pt1.speed + pt2.speed)); + + if (self->GetVorticity() && inVectors) + { + // compute vorticity + inVectors->GetTuples(cell->PointIds, cellVectors); + cellVel = cellVectors->GetPointer(0); + cell->Derivatives(0, pcoords, cellVel, 3, derivs); + vort[0] = derivs[7] - derivs[5]; + vort[1] = derivs[2] - derivs[6]; + vort[2] = derivs[3] - derivs[1]; + // rotation + pt2.omega = vtkMath::Dot(vort, pt2.v); + pt2.omega /= pt2.speed; + pt2.theta += (pt1.omega+pt2.omega)/2 * (pt2.t - pt1.t); + } + + + // Store only points which have a point to be displayed + // between them + if (tOffset >= pt1.t && tOffset <= pt2.t) + { + // Do not store if same as the last point. + // To avoid storing some points twice. + if ( !sNext || sNext->x[0] != pt1.x[0] || sNext->x[1] != pt1.x[1] + || sNext->x[2] != pt1.x[2] ) + { + idxNext = streamer->InsertNextStreamPoint(); + sNext = streamer->GetStreamPoint(idxNext); + *sNext = pt1; + } + idxNext = streamer->InsertNextStreamPoint(); + sNext = streamer->GetStreamPoint(idxNext); + *sNext = pt2; + } + if (tOffset < pt2.t) + { + tOffset += ((int)(( pt2.t - tOffset) / savePointInterval) + 1) + * savePointInterval; + } + pt1 = pt2; + + } + // Store the last point anyway. + if ( !sNext || sNext->x[0] != pt2.x[0] || sNext->x[1] != pt2.x[1] + || sNext->x[2] != pt2.x[2] ) + { + idxNext = streamer->InsertNextStreamPoint(); + sNext = streamer->GetStreamPoint(idxNext); + *sNext = pt2; + } + // Clear the last cell to avoid starting a search from + // the last point in the streamline + func->ClearLastCellId(); + } + } + + integrator->Delete(); + func->Delete(); + + cell->Delete(); + cellVectors->Delete(); + if (cellScalars) + { + cellScalars->Delete(); + } + delete[] w; + + return VTK_THREAD_RETURN_VALUE; +} + +void vtkStreamer::Integrate(vtkDataSet *input, vtkDataSet *source) +{ + vtkPointData *pd = input->GetPointData(); + vtkDataArray *inScalars; + vtkDataArray *inVectors; + vtkIdType numSourcePts, idx, idxNext; + vtkStreamer::StreamPoint *sNext, *sPtr; + vtkIdType ptId, i; + int j, offset; + vtkCell *cell; + double v[3], *cellVel, derivs[9], xNext[3], vort[3]; + double tol2; + double *w = new double[input->GetMaxCellSize()]; + vtkDoubleArray *cellVectors; + vtkDataArray *cellScalars=0; + + vtkDebugMacro(<<"Generating streamers"); + this->NumberOfStreamers = 0; + + // reexecuting - delete old stuff + if( this->Streamers ) + { + delete [] this->Streamers; + } + this->Streamers = NULL; + + if ( ! (inVectors=pd->GetVectors()) ) + { + delete [] w; + vtkErrorMacro(<<"No vector data defined!"); + return; + } + + cellVectors = vtkDoubleArray::New(); + cellVectors->SetNumberOfComponents(3); + cellVectors->Allocate(3*VTK_CELL_SIZE); + + inScalars = pd->GetScalars(); + + if (inScalars) + { + cellScalars = inScalars->NewInstance(); + cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + cellScalars->Allocate(cellScalars->GetNumberOfComponents()*VTK_CELL_SIZE); + } + + tol2 = input->GetLength()/1000; + tol2 = tol2*tol2; + + // + // Create starting points + // + this->NumberOfStreamers = numSourcePts = offset = 1; + if ( source ) + { + this->NumberOfStreamers = numSourcePts = source->GetNumberOfPoints(); + } + + if ( this->IntegrationDirection == VTK_INTEGRATE_BOTH_DIRECTIONS ) + { + offset = 2; + this->NumberOfStreamers *= 2; + } + + this->Streamers = new vtkStreamer::StreamArray[this->NumberOfStreamers]; + + if ( this->StartFrom == VTK_START_FROM_POSITION && !source ) + { + idx = this->Streamers[0].InsertNextStreamPoint(); + sPtr = this->Streamers[0].GetStreamPoint(idx); + sPtr->subId = 0; + for (i=0; i<3; i++) + { + sPtr->x[i] = this->StartPosition[i]; + } + sPtr->cellId = input->FindCell(this->StartPosition, NULL, -1, 0.0, + sPtr->subId, sPtr->p, w); + } + + else if ( this->StartFrom == VTK_START_FROM_LOCATION && !source ) + { + idx = this->Streamers[0].InsertNextStreamPoint(); + sPtr = this->Streamers[0].GetStreamPoint(idx); + sPtr->subId = 0; + cell = input->GetCell(sPtr->cellId); + cell->EvaluateLocation(sPtr->subId, sPtr->p, sPtr->x, w); + } + + else //VTK_START_FROM_SOURCE + { + for (ptId=0; ptId < numSourcePts; ptId++) + { + idx = this->Streamers[offset*ptId].InsertNextStreamPoint(); + sPtr = this->Streamers[offset*ptId].GetStreamPoint(idx); + sPtr->subId = 0; + source->GetPoint(ptId,sPtr->x); + sPtr->cellId = input->FindCell(sPtr->x, NULL, -1, tol2, + sPtr->subId, sPtr->p, w); + } + } + + // Finish initializing each streamer + // + for (idx=0, ptId=0; ptId < numSourcePts; ptId++) + { + this->Streamers[offset*ptId].Direction = 1.0; + sPtr = this->Streamers[offset*ptId].GetStreamPoint(idx); + sPtr->d = 0.0; + sPtr->t = 0.0; + sPtr->s = 0.0; + sPtr->theta = 0.0; + sPtr->omega = 0.0; + + if ( sPtr->cellId >= 0 ) //starting point in dataset + { + cell = input->GetCell(sPtr->cellId); + cell->EvaluateLocation(sPtr->subId, sPtr->p, xNext, w); + + inVectors->GetTuples(cell->PointIds, cellVectors); + sPtr->v[0] = sPtr->v[1] = sPtr->v[2] = 0.0; + for (i=0; i < cell->GetNumberOfPoints(); i++) + { + cellVectors->GetTuple(i, v); + for (j=0; j<3; j++) + { + sPtr->v[j] += v[j] * w[i]; + } + } + + sPtr->speed = vtkMath::Norm(sPtr->v); + + if (this->GetVorticity() && inVectors) + { + // compute vorticity + inVectors->GetTuples(cell->PointIds, cellVectors); + cellVel = cellVectors->GetPointer(0); + cell->Derivatives(0, sPtr->p, cellVel, 3, derivs); + vort[0] = derivs[7] - derivs[5]; + vort[1] = derivs[2] - derivs[6]; + vort[2] = derivs[3] - derivs[1]; + // rotation + sPtr->omega = vtkMath::Dot(vort, sPtr->v); + sPtr->omega /= sPtr->speed; + sPtr->theta = 0; + } + + if ( inScalars ) + { + inScalars->GetTuples(cell->PointIds, cellScalars); + for (sPtr->s=0, i=0; i < cell->GetNumberOfPoints(); i++) + { + sPtr->s += cellScalars->GetComponent(i,0) * w[i]; + } + } + } + else + { + for (j=0; j<3; j++) + { + sPtr->p[j] = 0.0; + sPtr->v[j] = 0.0; + } + sPtr->speed = 0; + } + + if ( this->IntegrationDirection == VTK_INTEGRATE_BOTH_DIRECTIONS ) + { + this->Streamers[offset*ptId+1].Direction = -1.0; + idxNext = this->Streamers[offset*ptId+1].InsertNextStreamPoint(); + sNext = this->Streamers[offset*ptId+1].GetStreamPoint(idxNext); + sPtr = this->Streamers[offset*ptId].GetStreamPoint(idx); + *sNext = *sPtr; + } + else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD ) + { + this->Streamers[offset*ptId].Direction = -1.0; + } + + + } //for each streamer + + // Some data access methods must be called once from a single thread before they + // can safely be used. Call those now + vtkGenericCell *gcell = vtkGenericCell::New(); + input->GetCell(0,gcell); + gcell->Delete(); + + // Set up and execute the thread + this->Threader->SetNumberOfThreads( this->NumberOfThreads ); + vtkStreamerThreadStruct str; + str.Filter = this; + str.Input = input; + str.Source = source; + this->Threader->SetSingleMethod( vtkStreamer::ThreadedIntegrate, &str ); + this->Threader->SingleMethodExecute(); + + // + // Now create appropriate representation + // + if ( this->OrientationScalars && !this->SpeedScalars) + { + for (ptId=0; ptId < this->NumberOfStreamers; ptId++) + { + for ( sPtr=this->Streamers[ptId].GetStreamPoint(0), i=0; + i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0; + i++, sPtr=this->Streamers[ptId].GetStreamPoint(i) ) + { + sPtr->s = sPtr->theta; + } + } + } + + if ( this->SpeedScalars ) + { + for (ptId=0; ptId < this->NumberOfStreamers; ptId++) + { + for ( sPtr=this->Streamers[ptId].GetStreamPoint(0), i=0; + i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0; + i++, sPtr=this->Streamers[ptId].GetStreamPoint(i) ) + { + sPtr->s = sPtr->speed; + } + } + } + delete [] w; + cellVectors->Delete(); + if (cellScalars) + { + cellScalars->Delete(); + } +} + +int vtkStreamer::FillInputPortInformation(int port, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + return 1; +} + +void vtkStreamer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->StartFrom == VTK_START_FROM_POSITION && !this->GetSource()) + { + os << indent << "Starting Position: (" << this->StartPosition[0] << "," + << this->StartPosition[1] << ", " << this->StartPosition[2] << ")\n"; + } + else if ( this->StartFrom == VTK_START_FROM_LOCATION && !this->GetSource()) + { + os << indent << "Starting Location:\n\tCell: " << this->StartCell + << "\n\tSubId: " << this->StartSubId << "\n\tP.Coordinates: (" + << this->StartPCoords[0] << ", " + << this->StartPCoords[1] << ", " + << this->StartPCoords[2] << ")\n"; + } + else + { + os << indent << "Starting Source: " << (void *)this->GetSource() << "\n"; + } + + os << indent << "Maximum Propagation Time: " + << this->MaximumPropagationTime << "\n"; + + if ( this->IntegrationDirection == VTK_INTEGRATE_FORWARD ) + { + os << indent << "Integration Direction: FORWARD\n"; + } + else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD ) + { + os << indent << "Integration Direction: BACKWARD\n"; + } + else + { + os << indent << "Integration Direction: FORWARD & BACKWARD\n"; + } + + os << indent << "Integration Step Length: " << this->IntegrationStepLength << "\n"; + + os << indent << "Vorticity: " << (this->Vorticity ? "On\n" : "Off\n"); + + os << indent << "Terminal Speed: " << this->TerminalSpeed << "\n"; + + os << indent << "Speed Scalars: " << (this->SpeedScalars ? "On\n" : "Off\n"); + + os << indent << "Orientation Scalars: " << (this->OrientationScalars ? "On\n" : "Off\n"); + + os << indent << "Interval with which points are stored:" + << this->SavePointInterval << endl; + + os << indent << "Integrator: " << this->Integrator << endl; + + os << indent << "Number Of Streamers: " << this->NumberOfStreamers << "\n"; + os << indent << "Number Of Threads: " << this->NumberOfThreads << "\n"; +} diff --git a/Graphics/vtkStreamer.h b/Graphics/vtkStreamer.h new file mode 100644 index 0000000..1442214 --- /dev/null +++ b/Graphics/vtkStreamer.h @@ -0,0 +1,322 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStreamer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStreamer - abstract object implements integration of massless particle through vector field +// .SECTION Description +// vtkStreamer is a filter that integrates a massless particle through a vector +// field. The integration is performed using second order Runge-Kutta method. +// vtkStreamer often serves as a base class for other classes that perform +// numerical integration through a vector field (e.g., vtkStreamLine). +// +// Note that vtkStreamer can integrate both forward and backward in time, +// or in both directions. The length of the streamer is controlled by +// specifying an elapsed time. (The elapsed time is the time each particle +// travels.) Otherwise, the integration terminates after exiting the dataset or +// if the particle speed is reduced to a value less than the terminal speed. +// +// vtkStreamer integrates through any type of dataset. As a result, if the +// dataset contains 2D cells such as polygons or triangles, the integration is +// constrained to lie on the surface defined by the 2D cells. +// +// The starting point of streamers may be defined in three different ways. +// Starting from global x-y-z "position" allows you to start a single streamer +// at a specified x-y-z coordinate. Starting from "location" allows you to +// start at a specified cell, subId, and parametric coordinate. Finally, you +// may specify a source object to start multiple streamers. If you start +// streamers using a source object, for each point in the source that is +// inside the dataset a streamer is created. +// +// vtkStreamer implements the integration process in the Integrate() method. +// Because vtkStreamer does not implement the Execute() method that its +// superclass (i.e., Filter) requires, it is an abstract class. Its subclasses +// implement the execute method and use the Integrate() method, and then build +// their own representation of the integration path (i.e., lines, dashed +// lines, points, etc.). + +// .SECTION See Also +// vtkStreamLine vtkDashedStreamLine vtkStreamPoints + +#ifndef __vtkStreamer_h +#define __vtkStreamer_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkInitialValueProblemSolver; +class vtkMultiThreader; + +#define VTK_INTEGRATE_FORWARD 0 +#define VTK_INTEGRATE_BACKWARD 1 +#define VTK_INTEGRATE_BOTH_DIRECTIONS 2 + +class VTK_GRAPHICS_EXPORT vtkStreamer : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkStreamer,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the start of the streamline in the cell coordinate system. That + // is, cellId and subId (if composite cell), and parametric coordinates. + void SetStartLocation(vtkIdType cellId, int subId, double pcoords[3]); + + // Description: + // Specify the start of the streamline in the cell coordinate system. That + // is, cellId and subId (if composite cell), and parametric coordinates. + void SetStartLocation(vtkIdType cellId, int subId, double r, double s, + double t); + + // Description: + // Get the starting location of the streamline in the cell coordinate system. + vtkIdType GetStartLocation(int& subId, double pcoords[3]); + + // Description: + // Specify the start of the streamline in the global coordinate + // system. Search must be performed to find initial cell to start + // integration from. + void SetStartPosition(double x[3]); + + // Description: + // Specify the start of the streamline in the global coordinate + // system. Search must be performed to find initial cell to start + // integration from. + void SetStartPosition(double x, double y, double z); + + // Description: + // Get the start position in global x-y-z coordinates. + double *GetStartPosition(); + + // Description: + // Specify the source object used to generate starting points. + void SetSource(vtkDataSet *source); + vtkDataSet *GetSource(); + + // Description: + // Specify the maximum length of the Streamer expressed in elapsed time. + vtkSetClampMacro(MaximumPropagationTime,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(MaximumPropagationTime,double); + + // Description: + // Specify the direction in which to integrate the Streamer. + vtkSetClampMacro(IntegrationDirection,int, + VTK_INTEGRATE_FORWARD,VTK_INTEGRATE_BOTH_DIRECTIONS); + vtkGetMacro(IntegrationDirection,int); + void SetIntegrationDirectionToForward() + {this->SetIntegrationDirection(VTK_INTEGRATE_FORWARD);}; + void SetIntegrationDirectionToBackward() + {this->SetIntegrationDirection(VTK_INTEGRATE_BACKWARD);}; + void SetIntegrationDirectionToIntegrateBothDirections() + {this->SetIntegrationDirection(VTK_INTEGRATE_BOTH_DIRECTIONS);}; + const char *GetIntegrationDirectionAsString(); + + // Description: + // Specify a nominal integration step size (expressed as a fraction of + // the size of each cell). This value can be larger than 1. + vtkSetClampMacro(IntegrationStepLength,double,0.0000001,VTK_DOUBLE_MAX); + vtkGetMacro(IntegrationStepLength,double); + + // Description: + // Turn on/off the creation of scalar data from velocity magnitude. If off, + // and input dataset has scalars, input dataset scalars are used. + vtkSetMacro(SpeedScalars,int); + vtkGetMacro(SpeedScalars,int); + vtkBooleanMacro(SpeedScalars,int); + + // Description: + // Turn on/off the creation of scalar data from vorticity information. + // The scalar information is currently the orientation value "theta" + // used in rotating stream tubes. If off, and input dataset has scalars, + // then input dataset scalars are used, unless SpeedScalars is also on. + // SpeedScalars takes precedence over OrientationScalars. + vtkSetMacro(OrientationScalars, int); + vtkGetMacro(OrientationScalars, int); + vtkBooleanMacro(OrientationScalars, int); + + // Description: + // Set/get terminal speed (i.e., speed is velocity magnitude). Terminal + // speed is speed at which streamer will terminate propagation. + vtkSetClampMacro(TerminalSpeed,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(TerminalSpeed,double); + + // Description: + // Turn on/off the computation of vorticity. Vorticity is an indication of + // the rotation of the flow. In combination with vtkStreamLine and + // vtkTubeFilter can be used to create rotated tubes. + // If vorticity is turned on, in the output, the velocity vectors + // are replaced by vorticity vectors. + vtkSetMacro(Vorticity,int); + vtkGetMacro(Vorticity,int); + vtkBooleanMacro(Vorticity,int); + + vtkSetMacro( NumberOfThreads, int ); + vtkGetMacro( NumberOfThreads, int ); + + vtkSetMacro( SavePointInterval, double ); + vtkGetMacro( SavePointInterval, double ); + + // Description: + // Set/get the integrator type to be used in the stream line + // calculation. The object passed is not actually used but + // is cloned with NewInstance by each thread/process in the + // process of integration (prototype pattern). The default is + // 2nd order Runge Kutta. + void SetIntegrator(vtkInitialValueProblemSolver *); + vtkGetObjectMacro ( Integrator, vtkInitialValueProblemSolver ); + +protected: + // Description: + // Construct object to start from position (0,0,0); integrate forward; + // terminal speed 0.0; vorticity computation off; integrations step length + // 0.2; and maximum propagation time 100.0. + vtkStreamer(); + ~vtkStreamer(); + + // Integrate data + void Integrate(vtkDataSet *input, vtkDataSet *source); + + // Controls where streamlines start from (either position or location). + int StartFrom; + + // Starting from cell location + vtkIdType StartCell; + int StartSubId; + double StartPCoords[3]; + + // starting from global x-y-z position + double StartPosition[3]; + + // + // Special classes for manipulating data + // + //BTX - begin tcl exclude + // + class StreamPoint { + public: + double x[3]; // position + vtkIdType cellId; // cell + int subId; // cell sub id + double p[3]; // parametric coords in cell + double v[3]; // velocity + double speed; // velocity norm + double s; // scalar value + double t; // time travelled so far + double d; // distance travelled so far + double omega; // stream vorticity, if computed + double theta; // rotation angle, if vorticity is computed + }; + + class StreamArray; + friend class StreamArray; + class StreamArray { //;prevent man page generation + public: + StreamArray(); + ~StreamArray() + { + if (this->Array) + { + delete [] this->Array; + } + }; + vtkIdType GetNumberOfPoints() {return this->MaxId + 1;}; + StreamPoint *GetStreamPoint(vtkIdType i) {return this->Array + i;}; + vtkIdType InsertNextStreamPoint() + { + if ( ++this->MaxId >= this->Size ) + { + this->Resize(this->MaxId); + } + return this->MaxId; //return offset from array + } + StreamPoint *Resize(vtkIdType sz); //reallocates data + void Reset() {this->MaxId = -1;}; + + StreamPoint *Array; // pointer to data + vtkIdType MaxId; // maximum index inserted thus far + vtkIdType Size; // allocated size of data + vtkIdType Extend; // grow array by this amount + double Direction; // integration direction + }; + //ETX + // + + //array of streamers + StreamArray *Streamers; + vtkIdType NumberOfStreamers; + + // length of Streamer is generated by time, or by MaximumSteps + double MaximumPropagationTime; + + // integration direction + int IntegrationDirection; + + // the length (fraction of cell size) of integration steps + double IntegrationStepLength; + + // boolean controls whether vorticity is computed + int Vorticity; + + // terminal propagation speed + double TerminalSpeed; + + // boolean controls whether data scalars or velocity magnitude are used + int SpeedScalars; + + // boolean controls whether data scalars or vorticity orientation are used + int OrientationScalars; + + // Prototype showing the integrator type to be set by the user. + vtkInitialValueProblemSolver* Integrator; + + // Interval with which the stream points will be stored. + // Useful in reducing the memory footprint. Since the initial + // value is small, by default, it will store all/most points. + double SavePointInterval; + + static VTK_THREAD_RETURN_TYPE ThreadedIntegrate( void *arg ); + + // Description: + // These methods were added to allow access to these variables from the + // threads. + vtkGetMacro( NumberOfStreamers, int ); + StreamArray *GetStreamers() { return this->Streamers; }; + + void InitializeThreadedIntegrate(); + vtkMultiThreader *Threader; + int NumberOfThreads; + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkStreamer(const vtkStreamer&); // Not implemented. + void operator=(const vtkStreamer&); // Not implemented. +}; + +// Description: +// Return the integration direction as a character string. +inline const char *vtkStreamer::GetIntegrationDirectionAsString() +{ + if ( this->IntegrationDirection == VTK_INTEGRATE_FORWARD ) + { + return "IntegrateForward"; + } + else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD ) + { + return "IntegrateBackward"; + } + else + { + return "IntegrateBothDirections"; + } +} + +#endif diff --git a/Graphics/vtkStripper.cxx b/Graphics/vtkStripper.cxx new file mode 100644 index 0000000..0429d1c --- /dev/null +++ b/Graphics/vtkStripper.cxx @@ -0,0 +1,495 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStripper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStripper.h" + +#include "vtkCellArray.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkStripper, "$Revision: 1.70 $"); +vtkStandardNewMacro(vtkStripper); + +// Construct object with MaximumLength set to 1000. +vtkStripper::vtkStripper() +{ + this->MaximumLength = 1000; + this->PassCellDataAsFieldData = 0; +} + +int vtkStripper::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, numCells, i; + int longestStrip, longestLine, j, numPts; + vtkIdType numLines, numStrips, nei; + vtkCellArray *newStrips=NULL, *inStrips, *newLines=NULL, *inLines, *inPolys; + vtkCellArray *newPolys=0; + vtkIdType numLinePts = 0; + vtkIdList *cellIds; + int foundOne; + vtkIdType *pts, neighbor=0; + vtkPolyData *mesh; + char *visited; + vtkIdType numStripPts = 0; + vtkIdType *stripPts = 0; + vtkIdType *linePts = 0; + vtkIdType *triPts; + vtkIdType numTriPts; + vtkPointData *pd=input->GetPointData(); + vtkCellData* cd = input->GetCellData(); + + // The field data, needs to be ordered properly for rendering + // to work.Hence cell data for each type of cell is collected + // separately and appended later. + vtkFieldData* newfd = 0; + vtkFieldData* newfdPolys = 0; + vtkFieldData* newfdLines = 0; + vtkFieldData* newfdStrips = 0; + + vtkDebugMacro(<<"Executing triangle strip / poly-line filter"); + + // build cell structure + inStrips = input->GetStrips(); + inLines = input->GetLines(); + inPolys = input->GetPolys(); + vtkIdType inNumVerts = input->GetVerts()->GetNumberOfCells(); + vtkIdType inNumLines = inLines->GetNumberOfCells(); + vtkIdType inNumPolys = inPolys->GetNumberOfCells(); + + mesh = vtkPolyData::New(); + mesh->SetPoints(input->GetPoints()); + mesh->SetLines(inLines); + mesh->SetPolys(inPolys); + mesh->BuildLinks(); + + // check input + if ( (numCells=mesh->GetNumberOfCells()) < 1 && inStrips->GetNumberOfCells() < 1) + { + // pass through verts + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + mesh->Delete(); + vtkDebugMacro(<<"No data to strip!"); + return 1; + } + + pts = new vtkIdType[this->MaximumLength + 2]; //working array + cellIds = vtkIdList::New(); + cellIds->Allocate(this->MaximumLength + 2); + + // The new field data object that maintains the transformed cell data. + if (this->PassCellDataAsFieldData) + { + newfd = vtkFieldData::New(); + newfd->CopyStructure(cd); + newfd->Allocate(3*numCells + 3); + + newfdPolys = vtkFieldData::New(); + newfdPolys->CopyStructure(cd); + newfdPolys->Allocate(inNumPolys + 1); + + newfdLines = vtkFieldData::New(); + newfdLines->CopyStructure(cd); + newfdLines->Allocate(inNumLines + 1); + + newfdStrips = vtkFieldData::New(); + newfdStrips->CopyStructure(cd); + // this is a very gross estimate since we cannot know how long the already + // present strips are. + newfdStrips->Allocate(3*inNumPolys + 3); + } + + // pre-load existing strips + if ( inStrips->GetNumberOfCells() > 0 || inPolys->GetNumberOfCells() > 0 ) + { + newStrips = vtkCellArray::New(); + newStrips->Allocate(newStrips->EstimateSize(numCells,6)); + cellId = inNumVerts + inNumLines + inNumPolys; + for(inStrips->InitTraversal(); + inStrips->GetNextCell(numStripPts,stripPts); ) + { + newStrips->InsertNextCell(numStripPts,stripPts); + if (this->PassCellDataAsFieldData) + { + for (i=2; i < numStripPts; i++) + { + newfdStrips->InsertNextTuple(cd->GetTuple(cellId)); + } + } + cellId++; + } + // These are for passing through non-triangle polygons + newPolys = vtkCellArray::New(); + newPolys->Allocate(newStrips->EstimateSize(numCells/2,4)); + } + + // pre-load existing poly-lines + if ( inLines->GetNumberOfCells() > 0 ) + { + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(numCells,6)); + cellId = inNumVerts; + for (inLines->InitTraversal(); inLines->GetNextCell(numLinePts,linePts); cellId++) + { + if ( numLinePts > 2 ) + { + newLines->InsertNextCell(numLinePts,linePts); + if (this->PassCellDataAsFieldData) + { + newfdLines->InsertNextTuple(cd->GetTuple(cellId)); + } + } + } + } + + // array keeps track of data that's been visited + visited = new char[numCells]; + for (i=0; i < numCells; i++) + { + visited[i] = 0; + } + + // Loop over all cells and find one that hasn't been visited. + // Start a triangle strip (or poly-line) and mark as visited, and + // then find a neighbor that isn't visited. Add this to the strip + // (or poly-line) and mark as visited (and so on). + // + longestStrip = 0; numStrips = 0; + longestLine = 0; numLines = 0; + + int cellType; + int abort=0; + vtkIdType progressInterval=numCells/20 + 1; + for ( cellId=0; cellId < numCells && !abort; cellId++) + { + if ( !(cellId % progressInterval) ) + { + this->UpdateProgress ((float) cellId/numCells); + abort = this->GetAbortExecute(); + } + if ( ! visited[cellId] ) + { + visited[cellId] = 1; + if ( (cellType=mesh->GetCellType(cellId)) == VTK_TRIANGLE ) + { + // Got a starting point for the strip. Initialize. Find a neighbor + // to extend strip. + // + numStrips++; + numPts = 3; + + mesh->GetCellPoints(cellId,numTriPts,triPts); + + for (i=0; i<3; i++) + { + pts[1] = triPts[i]; + pts[2] = triPts[(i+1)%3]; + + mesh->GetCellEdgeNeighbors(cellId, pts[1], pts[2], cellIds); + if ( cellIds->GetNumberOfIds() > 0 && + !visited[neighbor=cellIds->GetId(0)] && + mesh->GetCellType(neighbor) == VTK_TRIANGLE ) + { + pts[0] = triPts[(i+2)%3]; + break; + } + } + // If no unvisited neighbor, just create the strip of one triangle. + // + if ( i >= 3 ) + { + pts[0] = triPts[0];; + pts[1] = triPts[1]; + pts[2] = triPts[2]; + newStrips->InsertNextCell(3,pts); + if (this->PassCellDataAsFieldData) + { + newfdStrips->InsertNextTuple(cd->GetTuple(cellId)); + } + } + else // continue strip + { + // Have a neighbor. March along grabbing new points + // + if (this->PassCellDataAsFieldData) + { + newfdStrips->InsertNextTuple(cd->GetTuple(cellId)); + } + while ( neighbor >= 0 ) + { + visited[neighbor] = 1; + mesh->GetCellPoints(neighbor,numTriPts, triPts); + if (this->PassCellDataAsFieldData) + { + newfdStrips->InsertNextTuple(cd->GetTuple(neighbor)); + } + + for (i=0; i<3; i++) + { + if ( triPts[i] != pts[numPts-2] && + triPts[i] != pts[numPts-1] ) + { + break; + } + } + + // only add the triangle to the strip if it isn't degenerate. + if (i < 3) + { + pts[numPts] = triPts[i]; + mesh->GetCellEdgeNeighbors(neighbor, pts[numPts], + pts[numPts-1], cellIds); + numPts++; + } + + if ( numPts > longestStrip ) + { + longestStrip = numPts; + } + + // note: if updates value of neighbor + // Note2: for a degenerate triangle this test will + // correctly fail because the visited[neighbor] will + // now be visited + if ( cellIds->GetNumberOfIds() <= 0 || + visited[neighbor=cellIds->GetId(0)] || + mesh->GetCellType(neighbor) != VTK_TRIANGLE || + numPts >= (this->MaximumLength+2) ) + { + newStrips->InsertNextCell(numPts,pts); + neighbor = (-1); + } + } // while + } // else continue strip + } // if triangle + + else if ( cellType == VTK_LINE ) + { + // + // Got a starting point for the line. Initialize. Find a neighbor + // to extend poly-line. + // + numLines++; + numPts = 2; + + mesh->GetCellPoints(cellId,numLinePts,linePts); + + for ( foundOne=i=0; !foundOne && i<2; i++) + { + pts[0] = linePts[i]; + pts[1] = linePts[(i+1)%2]; + mesh->GetPointCells(pts[1], cellIds); + for (j=0; j < cellIds->GetNumberOfIds(); j++ ) + { + neighbor = cellIds->GetId(j); + if ( neighbor != cellId && !visited[neighbor] && + mesh->GetCellType(neighbor) == VTK_LINE ) + { + foundOne = 1; + break; + } + } + } + + // for each polyline that we construct, we set the cell data to be that + // for the first cell that formed the polyline. We may build the field data + // for the mini-cells in the polyline, similar to triangle strips, + // but that is not required currently. + if (this->PassCellDataAsFieldData) + { + newfdLines->InsertNextTuple(cd->GetTuple(cellId)); + } + + // If no unvisited neighbor, just create the poly-line from one line. + // + if ( !foundOne ) + { + newLines->InsertNextCell(2,linePts); + + } + else // continue poly-line + { + // Have a neighbor. March along grabbing new points + // + while ( neighbor >= 0 ) + { + visited[neighbor] = 1; + mesh->GetCellPoints(neighbor, numLinePts, linePts); + for (i=0; i<2; i++) + { + if ( linePts[i] != pts[numPts-1] ) + { + break; + } + } + pts[numPts] = linePts[i]; + mesh->GetPointCells(pts[numPts], cellIds); + if ( ++numPts > longestLine ) + { + longestLine = numPts; + } + + // get new neighbor + for ( j=0; j < cellIds->GetNumberOfIds(); j++ ) + { + nei = cellIds->GetId(j); + if ( nei != neighbor && !visited[nei] && + mesh->GetCellType(nei) == VTK_LINE ) + { + neighbor = nei; + break; + } + } + + if ( j >= cellIds->GetNumberOfIds() || + numPts >= (this->MaximumLength+1) ) + { + newLines->InsertNextCell(numPts,pts); + neighbor = (-1); + } + } // while + } // else continue line + } // if line + + //not line, triangle, or strip must be quad or tpolygon which we pass through + else if ( cellType == VTK_POLYGON || cellType == VTK_QUAD ) + { + mesh->GetCellPoints(cellId,numTriPts,triPts); + newPolys->InsertNextCell(numTriPts,triPts); + if (this->PassCellDataAsFieldData) + { + newfdPolys->InsertNextTuple(cd->GetTuple(cellId)); + } + } + + } // if not visited + } // for all elements + + // Update output and release memory + // + delete [] pts; + delete [] visited; + mesh->Delete(); + + output->SetPoints(input->GetPoints()); + output->GetPointData()->PassData(pd); + + // output strips + if ( newStrips ) + { + newStrips->Squeeze(); + output->SetStrips(newStrips); + newStrips->Delete(); + vtkDebugMacro (<<"Reduced " << numCells << " cells to " << numStrips + << " triangle strips \n\t(Average " + << (float)numCells/numStrips + << " triangles per strip, longest strip = " + << ((longestStrip-2)>0?(longestStrip-2):0) << " triangles)"); + + if ( newPolys->GetNumberOfCells() > 0 ) + { + vtkDebugMacro(<<"Passed " << newPolys->GetNumberOfCells() + << " polygons"); + newPolys->Squeeze(); + output->SetPolys(newPolys); + } + newPolys->Delete(); + } + + // output poly-lines + if ( newLines ) + { + newLines->Squeeze(); + output->SetLines(newLines); + newLines->Delete(); + vtkDebugMacro (<<"Reduced " << numCells << " cells to " << numLines + << " poly-lines \n\t(Average " << (float)numCells/numLines + << " lines per poly-line, longest poly-line = " + << ((longestLine-1)>0?(longestLine-1):0) << " lines)"); + + } + + // pass through verts + output->SetVerts(input->GetVerts()); + cellIds->Delete(); + + if (this->PassCellDataAsFieldData) + { + cellId = 0; + int max; + for (i=0; i < inNumVerts; i++, cellId++) + { + newfd->InsertNextTuple(cd->GetTuple(cellId)); + } + if (newfdLines) + { + max = newfdLines->GetNumberOfTuples(); + for (i=0; i < max; i++) + { + newfd->InsertNextTuple(newfdLines->GetTuple(i)); + } + newfdLines->Delete(); + } + if (newfdPolys) + { + max = newfdPolys->GetNumberOfTuples(); + for (i=0; i < max; i++) + { + newfd->InsertNextTuple(newfdPolys->GetTuple(i)); + } + newfdPolys->Delete(); + } + if (newfdStrips) + { + max = newfdStrips->GetNumberOfTuples(); + for (i=0; i < max; i++) + { + newfd->InsertNextTuple(newfdStrips->GetTuple(i)); + } + newfdStrips->Delete(); + } + newfd->Squeeze(); + output->SetFieldData(newfd); + newfd->Delete(); + } + + return 1; +} + +void vtkStripper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum Length: " << this->MaximumLength << "\n"; + os << indent << "PassCellDataAsFieldData: " << this->PassCellDataAsFieldData << endl; +} diff --git a/Graphics/vtkStripper.h b/Graphics/vtkStripper.h new file mode 100644 index 0000000..6cb84f8 --- /dev/null +++ b/Graphics/vtkStripper.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStripper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStripper - create triangle strips and/or poly-lines +// .SECTION Description + +// vtkStripper is a filter that generates triangle strips and/or poly-lines +// from input polygons, triangle strips, and lines. Input polygons are +// assembled into triangle strips only if they are triangles; other types of +// polygons are passed through to the output and not stripped. (Use +// vtkTriangleFilter to triangulate non-triangular polygons prior to running +// this filter if you need to strip all the data.) The filter will pass +// through (to the output) vertices if they are present in the input +// polydata. +// +// The ivar MaximumLength can be used to control the maximum +// allowable triangle strip and poly-line length. +// +// By default, this filter discards any cell data associated with the input. +// Thus is because the cell structure changes and and the old cell data +// is no longer valid. When PassCellDataAsFieldData flag is set, +// the cell data is passed as FieldData to the output using the following rule: +// 1) for every cell in the output that is not a triangle strip, +// the cell data is inserted once per cell in the output field data. +// 2) for every triangle strip cell in the output: +// ii) 1 tuple is inserted for every point(j|j>=2) in the strip. +// This is the cell data for the cell formed by (j-2, j-1, j) in +// the input. +// The field data order is same as cell data i.e. (verts,line,polys,tsrips). + +// .SECTION Caveats +// If triangle strips or poly-lines exist in the input data they will +// be passed through to the output data. This filter will only construct +// triangle strips if triangle polygons are available; and will only +// construct poly-lines if lines are available. + +// .SECTION See Also +// vtkTriangleFilter + +#ifndef __vtkStripper_h +#define __vtkStripper_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkStripper : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkStripper,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with MaximumLength set to 1000. + static vtkStripper *New(); + + // Description: + // Specify the maximum number of triangles in a triangle strip, + // and/or the maximum number of lines in a poly-line. + vtkSetClampMacro(MaximumLength,int,4,100000); + vtkGetMacro(MaximumLength,int); + + // Description: + // Enable/Disable passing of the CellData in the input to + // the output as FieldData. Note the field data is tranformed. + vtkBooleanMacro(PassCellDataAsFieldData, int); + vtkSetMacro(PassCellDataAsFieldData, int); + vtkGetMacro(PassCellDataAsFieldData, int); + +protected: + vtkStripper(); + ~vtkStripper() {} + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int MaximumLength; + int PassCellDataAsFieldData; + +private: + vtkStripper(const vtkStripper&); // Not implemented. + void operator=(const vtkStripper&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkStructuredGridClip.cxx b/Graphics/vtkStructuredGridClip.cxx new file mode 100644 index 0000000..1f94c0e --- /dev/null +++ b/Graphics/vtkStructuredGridClip.cxx @@ -0,0 +1,246 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridClip.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridClip.h" + +#include "vtkCellData.h" +#include "vtkExtentTranslator.h" +#include "vtkStructuredGrid.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkStructuredGridClip, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkStructuredGridClip); + +//---------------------------------------------------------------------------- +vtkStructuredGridClip::vtkStructuredGridClip() +{ + this->ClipData = 0; + this->Initialized = 0; + + this->OutputWholeExtent[0] = + this->OutputWholeExtent[2] = + this->OutputWholeExtent[4] = -VTK_LARGE_INTEGER; + + this->OutputWholeExtent[1] = + this->OutputWholeExtent[3] = + this->OutputWholeExtent[5] = VTK_LARGE_INTEGER; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridClip::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + + os << indent << "OutputWholeExtent: (" << this->OutputWholeExtent[0] + << "," << this->OutputWholeExtent[1]; + for (idx = 1; idx < 3; ++idx) + { + os << indent << ", " << this->OutputWholeExtent[idx * 2] + << "," << this->OutputWholeExtent[idx*2 + 1]; + } + os << ")\n"; + if (this->ClipData) + { + os << indent << "ClipDataOn\n"; + } + else + { + os << indent << "ClipDataOff\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridClip::SetOutputWholeExtent(int extent[6], vtkInformation *outInfo) +{ + int idx; + int modified = 0; + + for (idx = 0; idx < 6; ++idx) + { + if (this->OutputWholeExtent[idx] != extent[idx]) + { + this->OutputWholeExtent[idx] = extent[idx]; + modified = 1; + } + } + this->Initialized = 1; + if (modified) + { + this->Modified(); + if (!outInfo) + { + outInfo = this->GetExecutive()->GetOutputInformation(0); + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); + } +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridClip::SetOutputWholeExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetOutputWholeExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridClip::GetOutputWholeExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + extent[idx] = this->OutputWholeExtent[idx]; + } +} + +//---------------------------------------------------------------------------- +// Change the WholeExtent +int vtkStructuredGridClip::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int idx, extent[6]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + if ( ! this->Initialized) + { + this->SetOutputWholeExtent(extent, outInfo); + } + + // Clip the OutputWholeExtent with the input WholeExtent + for (idx = 0; idx < 3; ++idx) + { + if (this->OutputWholeExtent[idx*2] >= extent[idx*2] && + this->OutputWholeExtent[idx*2] <= extent[idx*2+1]) + { + extent[idx*2] = this->OutputWholeExtent[idx*2]; + } + if (this->OutputWholeExtent[idx*2+1] >= extent[idx*2] && + this->OutputWholeExtent[idx*2+1] <= extent[idx*2+1]) + { + extent[idx*2+1] = this->OutputWholeExtent[idx*2+1]; + } + // make usre the order is correct + if (extent[idx*2] > extent[idx*2+1]) + { + extent[idx*2] = extent[idx*2+1]; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// Sets the output whole extent to be the input whole extent. +void vtkStructuredGridClip::ResetOutputWholeExtent() +{ + if ( ! this->GetInput()) + { + vtkWarningMacro("ResetOutputWholeExtent: No input"); + return; + } + + this->GetInput()->UpdateInformation(); + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + this->SetOutputWholeExtent(inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); +} + +//---------------------------------------------------------------------------- +// This method simply copies by reference the input data to the output. +int vtkStructuredGridClip::RequestData(vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int *inExt; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkStructuredGrid *outData = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkStructuredGrid *inData = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + inExt = inData->GetExtent(); + + outData->SetExtent(inExt); + outData->GetPointData()->PassData(inData->GetPointData()); + outData->GetCellData()->PassData(inData->GetCellData()); + outData->SetPoints(inData->GetPoints()); + + if (this->ClipData) + { + outData->Crop(); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkStructuredGridClip::SetOutputWholeExtent(int piece, int numPieces) +{ + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0); + vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkExtentTranslator *translator; + int ext[6]; + + if (input == NULL) + { + vtkErrorMacro("We must have an input to set the output extent by piece."); + return; + } + if (output == NULL) + { + vtkErrorMacro("We must have an output to set the output extent by piece."); + return; + } + translator = output->GetExtentTranslator(); + if (translator == NULL) + { + vtkErrorMacro("Output does not have an extent translator."); + return; + } + + input->UpdateInformation(); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext); + translator->SetWholeExtent(ext); + translator->SetPiece(piece); + translator->SetNumberOfPieces(numPieces); + translator->SetGhostLevel(0); + translator->PieceToExtent(); + translator->GetExtent(ext); + this->SetOutputWholeExtent(ext); +} diff --git a/Graphics/vtkStructuredGridClip.h b/Graphics/vtkStructuredGridClip.h new file mode 100644 index 0000000..49531a4 --- /dev/null +++ b/Graphics/vtkStructuredGridClip.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridClip.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridClip - Reduces the image extent of the input. +// .SECTION Description +// vtkStructuredGridClip will make an image smaller. The output must have +// an image extent which is the subset of the input. The filter has two +// modes of operation: +// 1: By default, the data is not copied in this filter. +// Only the whole extent is modified. +// 2: If ClipDataOn is set, then you will get no more that the clipped +// extent. +#ifndef __vtkStructuredGridClip_h +#define __vtkStructuredGridClip_h + +// I did not make this a subclass of in place filter because +// the references on the data do not matter. I make no modifications +// to the data. +#include "vtkStructuredGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkStructuredGridClip : public vtkStructuredGridAlgorithm +{ +public: + static vtkStructuredGridClip *New(); + vtkTypeRevisionMacro(vtkStructuredGridClip,vtkStructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The whole extent of the output has to be set explicitly. + void SetOutputWholeExtent(int extent[6], vtkInformation *outInfo=0); + void SetOutputWholeExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + void GetOutputWholeExtent(int extent[6]); + int *GetOutputWholeExtent() {return this->OutputWholeExtent;} + + void ResetOutputWholeExtent(); + + // Description: + // By default, ClipData is off, and only the WholeExtent is modified. + // the data's extent may actually be larger. When this flag is on, + // the data extent will be no more than the OutputWholeExtent. + vtkSetMacro(ClipData, int); + vtkGetMacro(ClipData, int); + vtkBooleanMacro(ClipData, int); + + // Description: + // Hack set output by piece + void SetOutputWholeExtent(int piece, int numPieces); + +protected: + vtkStructuredGridClip(); + ~vtkStructuredGridClip() {}; + + // Time when OutputImageExtent was computed. + vtkTimeStamp CTime; + int Initialized; // Set the OutputImageExtent for the first time. + int OutputWholeExtent[6]; + + int ClipData; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + void CopyData(vtkStructuredGrid *inData, vtkStructuredGrid *outData, int *ext); + + int SplitExtentTmp(int piece, int numPieces, int *ext); + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + +private: + vtkStructuredGridClip(const vtkStructuredGridClip&); // Not implemented. + void operator=(const vtkStructuredGridClip&); // Not implemented. +}; + + + +#endif + + + diff --git a/Graphics/vtkStructuredGridGeometryFilter.cxx b/Graphics/vtkStructuredGridGeometryFilter.cxx new file mode 100644 index 0000000..0f118df --- /dev/null +++ b/Graphics/vtkStructuredGridGeometryFilter.cxx @@ -0,0 +1,541 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridGeometryFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkExtentTranslator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" + +vtkCxxRevisionMacro(vtkStructuredGridGeometryFilter, "$Revision: 1.64 $"); +vtkStandardNewMacro(vtkStructuredGridGeometryFilter); + +// Construct with initial extent of all the data +vtkStructuredGridGeometryFilter::vtkStructuredGridGeometryFilter() +{ + this->Extent[0] = 0; + this->Extent[1] = VTK_LARGE_INTEGER; + this->Extent[2] = 0; + this->Extent[3] = VTK_LARGE_INTEGER; + this->Extent[4] = 0; + this->Extent[5] = VTK_LARGE_INTEGER; +} + +int vtkStructuredGridGeometryFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int *dims, dimension, dir[3], diff[3]; + int i, j, k, extent[6], *inExt; + vtkIdType ptIds[4], idx, startIdx, startCellIdx, cellId; + vtkPoints *newPts=0; + vtkCellArray *newVerts=0; + vtkCellArray *newLines=0; + vtkCellArray *newPolys=0; + vtkIdType totPoints, pos, cellPos; + int offset[3], cellOffset[3], numPolys; + double x[3]; + vtkPointData *pd, *outPD; + vtkCellData *cd, *outCD; + + vtkDebugMacro(<< "Extracting structured points geometry"); + + if ( input->GetPoints() == NULL) + { + vtkDebugMacro(<<"No data to extract"); + return 1; + } + + pd = input->GetPointData(); + outPD = output->GetPointData(); + outPD->CopyNormalsOff(); + cd = input->GetCellData(); + outCD = output->GetCellData(); + dims = input->GetDimensions(); + inExt = input->GetExtent(); + + // Based on the dimensions of the structured data, and the extent of + // the geometry, compute the combined extent plus the dimensionality + // of the data. + // + dimension = 3; + for (i=0; i<3; i++) + { + extent[2*i] = this->Extent[2*i]; + if (extent[2*i] < inExt[2*i]) + { + extent[2*i] = inExt[2*i]; + } + extent[2*i+1] = this->Extent[2*i+1]; + if (extent[2*i+1] > inExt[2*i+1]) + { + extent[2*i+1] = inExt[2*i+1]; + } + + // Handle empty extent. + if (extent[2*i] > extent[2*i+1]) + { + return 1; + } + + // Compute dimensions. + if ( (extent[2*i+1] - extent[2*i]) == 0 ) + { + dimension--; + } + } + + // The easiest way to handle the rest of this is to use the "electric slide". + // Translate the input extent so that it has minimums 0, 0, 0. + // It is only internal to this method, so it is OK. + extent[0] -= inExt[0]; + extent[1] -= inExt[0]; + extent[2] -= inExt[2]; + extent[3] -= inExt[2]; + extent[4] -= inExt[4]; + extent[5] -= inExt[4]; + + // Now create polygonal data based on dimension of data + // + // Compute starting index of the point and cell. First the starting + // point index. + startIdx = (extent[0]) + (extent[2])*dims[0] + + (extent[4])*dims[0]*dims[1]; + + // The cell index is a bit more complicated at the boundaries + if (dims[0] == 1) + { + startCellIdx = extent[0]; + } + else + { + startCellIdx = (extent[0] < dims[0] - 1) ? extent[0] + : extent[0]-1; + } + if (dims[1] == 1) + { + startCellIdx += extent[2]*(dims[0]-1); + } + else + { + startCellIdx += (extent[2] < dims[1] - 1) ? extent[2]*(dims[0]-1) + : (extent[2]-1)*(dims[0]-1); + } + if (dims[2] == 1) + { + startCellIdx += extent[4]*(dims[0]-1)*(dims[1]-1); + } + else + { + startCellIdx += (extent[4] < dims[2] - 1) ? extent[4]*(dims[0]-1)*(dims[1]-1) + : (extent[4]-1)*(dims[0]-1)*(dims[1]-1); + } + switch (dimension) + { + default: + break; + + case 0: // --------------------- build point ----------------------- + + if ( input->IsPointVisible(startIdx) ) + { + newPts = vtkPoints::New(); + newPts->Allocate(1); + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(1,1)); + outPD->CopyAllocate(pd,1); + outCD->CopyAllocate(cd,1); + + ptIds[0] = newPts->InsertNextPoint(input->GetPoint(startIdx)); + outPD->CopyData(pd,startIdx,ptIds[0]); + + cellId = newVerts->InsertNextCell(1,ptIds); + outCD->CopyData(cd,startIdx,cellId); + } + break; + + case 1: // --------------------- build line ----------------------- + + for (dir[0]=dir[1]=dir[2]=totPoints=0, i=0; i<3; i++) + { + if ( (diff[i] = extent[2*i+1] - extent[2*i]) > 0 ) + { + dir[0] = i; + totPoints = diff[i] + 1; + break; + } + } + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(totPoints-1,2)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,totPoints - 1); + + // Load data + // + if ( dir[0] == 0 ) + { + offset[0] = 1; + cellOffset[0] = 1; + } + else if (dir[0] == 1) + { + offset[0] = dims[0]; + cellOffset[0] = dims[0] - 1; + } + else + { + offset[0] = dims[0]*dims[1]; + cellOffset[0] = (dims[0] - 1) * (dims[1] - 1); + } + + for (i=0; iGetPoint(idx, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,idx,ptIds[0]); + } + + for (i=0; i<(totPoints-1); i++) + { + if ( input->IsPointVisible(startIdx + i*offset[0]) && + input->IsPointVisible(startIdx + (i+1)*offset[0]) ) + { + idx = startCellIdx + i*cellOffset[0]; + ptIds[0] = i; + ptIds[1] = i + 1; + cellId = newLines->InsertNextCell(2,ptIds); + outCD->CopyData(cd,idx,cellId); + } + } + break; + + case 2: // --------------------- build plane ----------------------- + + // Create the data objects + // + for (dir[0]=dir[1]=dir[2]=idx=0,i=0; i<3; i++) + { + if ( (diff[i] = extent[2*i+1] - extent[2*i]) != 0 ) + { + dir[idx++] = i; + } + else + { + dir[2] = i; + } + } + + totPoints = (diff[dir[0]]+1) * (diff[dir[1]]+1); + numPolys = diff[dir[0]] * diff[dir[1]]; + + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newLines->EstimateSize(numPolys,4)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,numPolys); + + // Create polygons + // + for (i=0; i<2; i++) + { + if ( dir[i] == 0 ) + { + offset[i] = 1; + cellOffset[i] = 1; + } + else if ( dir[i] == 1 ) + { + offset[i] = dims[0]; + cellOffset[i] = (dims[0] - 1); + } + else if ( dir[i] == 2 ) + { + offset[i] = dims[0]*dims[1]; + cellOffset[i] = (dims[0] - 1) * (dims[1] - 1); + } + } + + // Create points whether visible or not. Makes coding easier + // but generates extra data. + for (pos=startIdx, j=0; j < (diff[dir[1]]+1); j++) + { + for (i=0; i < (diff[dir[0]]+1); i++) + { + idx = pos + i*offset[0]; + input->GetPoint(idx, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,idx,ptIds[0]); + } + pos += offset[1]; + } + + for (pos=startIdx, cellPos=startCellIdx, j=0; j < diff[dir[1]]; j++) + { + for (i=0; i < diff[dir[0]]; i++) + { + if (input->IsPointVisible(pos+i*offset[0]) + && input->IsPointVisible(pos+(i+1)*offset[0]) + && input->IsPointVisible(pos+i*offset[0]+offset[1]) + && input->IsPointVisible(pos+(i+1)*offset[0]+offset[1]) ) + { + idx = cellPos + i*cellOffset[0]; + ptIds[0] = i + j*(diff[dir[0]]+1); + ptIds[1] = ptIds[0] + 1; + ptIds[2] = ptIds[1] + diff[dir[0]] + 1; + ptIds[3] = ptIds[2] - 1; + cellId = newPolys->InsertNextCell(4,ptIds); + outCD->CopyData(cd,idx,cellId); + } + } + cellPos += cellOffset[1]; + pos += offset[1]; + } + break; + + case 3: // ------------------- grab points in volume -------------- + + // Create data objects + // + for (i=0; i<3; i++) + { + diff[i] = extent[2*i+1] - extent[2*i]; + } + + totPoints = (diff[0]+1) * (diff[1]+1) * (diff[2]+1); + + newPts = vtkPoints::New(); + newPts->Allocate(totPoints); + newVerts = vtkCellArray::New(); + newVerts->Allocate(newVerts->EstimateSize(totPoints,1)); + outPD->CopyAllocate(pd,totPoints); + outCD->CopyAllocate(cd,totPoints); + + // Create vertices + // + offset[0] = dims[0]; + offset[1] = dims[0]*dims[1]; + + for (k=0; k < (diff[2]+1); k++) + { + for (j=0; j < (diff[1]+1); j++) + { + pos = startIdx + j*offset[0] + k*offset[1]; + for (i=0; i < (diff[0]+1); i++) + { + if ( input->IsPointVisible(pos+i) ) + { + input->GetPoint(pos+i, x); + ptIds[0] = newPts->InsertNextPoint(x); + outPD->CopyData(pd,pos+i,ptIds[0]); + cellId = newVerts->InsertNextCell(1,ptIds); + outCD->CopyData(cd,pos+i,cellId); + } + } + } + } + break; /* end this case */ + + } // switch + + // Update self and release memory + // + if (newPts) + { + output->SetPoints(newPts); + newPts->Delete(); + } + + if (newVerts) + { + output->SetVerts(newVerts); + newVerts->Delete(); + } + + if (newLines) + { + output->SetLines(newLines); + newLines->Delete(); + } + + if (newPolys) + { + output->SetPolys(newPolys); + newPolys->Delete(); + } + + return 1; +} + +// Specify (imin,imax, jmin,jmax, kmin,kmax) indices. +void vtkStructuredGridGeometryFilter::SetExtent(int iMin, int iMax, int jMin, + int jMax, int kMin, int kMax) +{ + int extent[6]; + + extent[0] = iMin; + extent[1] = iMax; + extent[2] = jMin; + extent[3] = jMax; + extent[4] = kMin; + extent[5] = kMax; + + this->SetExtent(extent); +} + +// Specify (imin,imax, jmin,jmax, kmin,kmax) indices in array form. +void vtkStructuredGridGeometryFilter::SetExtent(int extent[6]) +{ + int i; + + if ( extent[0] != this->Extent[0] || extent[1] != this->Extent[1] || + extent[2] != this->Extent[2] || extent[3] != this->Extent[3] || + extent[4] != this->Extent[4] || extent[5] != this->Extent[5] ) + { + this->Modified(); + for (i=0; i<3; i++) + { + if ( extent[2*i] < 0 ) + { + extent[2*i] = 0; + } + if ( extent[2*i+1] < extent[2*i] ) + { + extent[2*i+1] = extent[2*i]; + } + this->Extent[2*i] = extent[2*i]; + this->Extent[2*i+1] = extent[2*i+1]; + } + } +} + +int vtkStructuredGridGeometryFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces; + int *wholeExt; + int ext[6]; + vtkExtentTranslator *translator; + + translator = vtkExtentTranslator::SafeDownCast( + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + wholeExt = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + memcpy(ext, wholeExt, 6*sizeof(int)); + + // Get request from output information + piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + // get the extent associated with the piece. + if (translator == NULL) + { + // Default behavior + if (piece != 0) + { + ext[0] = ext[2] = ext[4] = 0; + ext[1] = ext[3] = ext[5] = -1; + } + } + else + { + translator->PieceToExtentThreadSafe(piece, numPieces, 0, wholeExt, ext, + translator->GetSplitMode(),0); + } + + if (ext[0] < this->Extent[0]) + { + ext[0] = this->Extent[0]; + } + if (ext[1] > this->Extent[1]) + { + ext[1] = this->Extent[1]; + } + if (ext[2] < this->Extent[2]) + { + ext[2] = this->Extent[2]; + } + if (ext[3] > this->Extent[3]) + { + ext[3] = this->Extent[3]; + } + if (ext[4] < this->Extent[4]) + { + ext[4] = this->Extent[4]; + } + if (ext[5] > this->Extent[5]) + { + ext[5] = this->Extent[5]; + } + + // Should not be necessary, but will make things clearer. + if (ext[0] > ext[1] || ext[2] > ext[3] || ext[4] > ext[5]) + { + ext[0] = ext[2] = ext[4] = 0; + ext[1] = ext[3] = ext[5] = -1; + } + + // Set the update extent of the input. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + return 1; +} + +int vtkStructuredGridGeometryFilter::FillInputPortInformation( + int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} + +void vtkStructuredGridGeometryFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Extent: \n"; + os << indent << " Imin,Imax: (" + << this->Extent[0] << ", " << this->Extent[1] << ")\n"; + os << indent << " Jmin,Jmax: (" + << this->Extent[2] << ", " << this->Extent[3] << ")\n"; + os << indent << " Kmin,Kmax: (" + << this->Extent[4] << ", " << this->Extent[5] << ")\n"; +} diff --git a/Graphics/vtkStructuredGridGeometryFilter.h b/Graphics/vtkStructuredGridGeometryFilter.h new file mode 100644 index 0000000..a05a8d1 --- /dev/null +++ b/Graphics/vtkStructuredGridGeometryFilter.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridGeometryFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridGeometryFilter - extract geometry for structured grid +// .SECTION Description +// vtkStructuredGridGeometryFilter is a filter that extracts geometry from a +// structured grid. By specifying appropriate i-j-k indices, it is possible +// to extract a point, a curve, a surface, or a "volume". Depending upon the +// type of data, the curve and surface may be curved or planar. (The volume +// is actually a (n x m x o) region of points.) +// +// The extent specification is zero-offset. That is, the first k-plane in +// a 50x50x50 structured grid is given by (0,49, 0,49, 0,0). +// +// The output of this filter is affected by the structured grid blanking. +// If blanking is on, and a blanking array defined, then those cells +// attached to blanked points are not output. (Blanking is a property of +// the input vtkStructuredGrid.) + +// .SECTION Caveats +// If you don't know the dimensions of the input dataset, you can use a large +// number to specify extent (the number will be clamped appropriately). For +// example, if the dataset dimensions are 50x50x50, and you want a the fifth +// k-plane, you can use the extents (0,100, 0,100, 4,4). The 100 will +// automatically be clamped to 49. + +// .SECTION See Also +// vtkGeometryFilter vtkExtractGrid vtkStructuredGrid + +#ifndef __vtkStructuredGridGeometryFilter_h +#define __vtkStructuredGridGeometryFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkStructuredGridGeometryFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkStructuredGridGeometryFilter *New(); + vtkTypeRevisionMacro(vtkStructuredGridGeometryFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the extent in topological coordinate range (imin,imax, jmin,jmax, + // kmin,kmax). + vtkGetVectorMacro(Extent,int,6); + + // Description: + // Specify (imin,imax, jmin,jmax, kmin,kmax) indices. + void SetExtent(int iMin, int iMax, int jMin, int jMax, int kMin, int kMax); + + // Description: + // Specify (imin,imax, jmin,jmax, kmin,kmax) indices in array form. + void SetExtent(int extent[6]); + +protected: + vtkStructuredGridGeometryFilter(); + ~vtkStructuredGridGeometryFilter() {} + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int Extent[6]; +private: + vtkStructuredGridGeometryFilter(const vtkStructuredGridGeometryFilter&); // Not implemented. + void operator=(const vtkStructuredGridGeometryFilter&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkStructuredGridOutlineFilter.cxx b/Graphics/vtkStructuredGridOutlineFilter.cxx new file mode 100644 index 0000000..c17ed9b --- /dev/null +++ b/Graphics/vtkStructuredGridOutlineFilter.cxx @@ -0,0 +1,260 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridOutlineFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridOutlineFilter.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" + +vtkCxxRevisionMacro(vtkStructuredGridOutlineFilter, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkStructuredGridOutlineFilter); + +//---------------------------------------------------------------------------- +// ComputeDivisionExtents has done most of the work for us. +// Now just connect the points. +int vtkStructuredGridOutlineFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int *ext, *wExt, cExt[6]; + int xInc, yInc, zInc; + vtkPoints *inPts; + vtkPoints *newPts; + vtkCellArray *newLines; + int idx; + vtkIdType ids[2], numPts, offset; + // for marching through the points along an edge. + vtkIdType start = 0, id; + int num = 0, inc = 0; + int edgeFlag; + int i; + + inPts = input->GetPoints(); + if (!inPts) + { + return 1; + } + + newLines = vtkCellArray::New(); + newPts = vtkPoints::New(); + + ext = input->GetExtent(); + wExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + // Since it is possible that the extent is larger than the whole extent, + // and we want the outline to be the whole extent, + // compute the clipped extent. + inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), cExt); + for (i = 0; i < 3; ++i) + { + if (cExt[2*i] < wExt[2*i]) + { + cExt[2*i] = wExt[2*i]; + } + if (cExt[2*i+1] > wExt[2*i+1]) + { + cExt[2*i+1] = wExt[2*i+1]; + } + } + + for (i = 0; i < 12; i++ ) + { + // Find the start of this edge, the length of this edge, and increment. + xInc = 1; + yInc = ext[1]-ext[0]+1; + zInc = yInc * (ext[3]-ext[2]+1); + edgeFlag = 0; + switch (i) + { + case 0: + // start (0, 0, 0) increment z axis. + if (cExt[0] <= wExt[0] && cExt[2] <= wExt[2]) + { + edgeFlag = 1; + } + num = cExt[5]-cExt[4]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = zInc; + break; + case 1: + // start (xMax, 0, 0) increment z axis. + if (cExt[1] >= wExt[1] && cExt[2] <= wExt[2]) + { + edgeFlag = 1; + } + num = cExt[5]-cExt[4]+1; + start = (cExt[1]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = zInc; + break; + case 2: + // start (0, yMax, 0) increment z axis. + if (cExt[0] <= wExt[0] && cExt[3] >= wExt[3]) + { + edgeFlag = 1; + } + num = cExt[5]-cExt[4]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[3]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = zInc; + break; + case 3: + // start (xMax, yMax, 0) increment z axis. + if (cExt[1] >= wExt[1] && cExt[3] >= wExt[3]) + { + edgeFlag = 1; + } + num = cExt[5]-cExt[4]+1; + start = (cExt[1]-ext[0])*xInc + (cExt[3]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = zInc; + break; + case 4: + // start (0, 0, 0) increment y axis. + if (cExt[0] <= wExt[0] && cExt[4] <= wExt[4]) + { + edgeFlag = 1; + } + num = cExt[3]-cExt[2]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = yInc; + break; + case 5: + // start (xMax, 0, 0) increment y axis. + if (cExt[1] >= wExt[1] && cExt[4] <= wExt[4]) + { + edgeFlag = 1; + } + num = cExt[3]-cExt[2]+1; + start = (cExt[1]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = yInc; + break; + case 6: + // start (0, 0, zMax) increment y axis. + if (cExt[0] <= wExt[0] && cExt[5] >= wExt[5]) + { + edgeFlag = 1; + } + num = cExt[3]-cExt[2]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[5]-ext[4])*zInc; + inc = yInc; + break; + case 7: + // start (xMax, 0, zMax) increment y axis. + if (cExt[1] >= wExt[1] && cExt[5] >= wExt[5]) + { + edgeFlag = 1; + } + num = cExt[3]-cExt[2]+1; + start = (cExt[1]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[5]-ext[4])*zInc; + inc = yInc; + break; + case 8: + // start (0, 0, 0) increment x axis. + if (cExt[2] <= wExt[2] && cExt[4] <= wExt[4]) + { + edgeFlag = 1; + } + num = cExt[1]-cExt[0]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = xInc; + break; + case 9: + // start (0, yMax, 0) increment x axis. + if (cExt[3] >= wExt[3] && cExt[4] <= wExt[4]) + { + edgeFlag = 1; + } + num = cExt[1]-cExt[0]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[3]-ext[2])*yInc + (cExt[4]-ext[4])*zInc; + inc = xInc; + break; + case 10: + // start (0, 0, zMax) increment x axis. + if (cExt[2] <= wExt[2] && cExt[5] >= wExt[5]) + { + edgeFlag = 1; + } + num = cExt[1]-cExt[0]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[2]-ext[2])*yInc + (cExt[5]-ext[4])*zInc; + inc = xInc; + break; + case 11: + // start (0, yMax, zMax) increment x axis. + if (cExt[3] >= wExt[3] && cExt[5] >= wExt[5]) + { + edgeFlag = 1; + } + num = cExt[1]-cExt[0]+1; + start = (cExt[0]-ext[0])*xInc + (cExt[3]-ext[2])*yInc + (cExt[5]-ext[4])*zInc; + inc = xInc; + break; + } + + if (edgeFlag && num > 1) + { + offset = newPts->GetNumberOfPoints(); + numPts = inPts->GetNumberOfPoints(); + + // add points + for (idx = 0; idx < num; ++idx) + { + id = start + idx * inc; + // sanity check + if (id < 0 || id >= numPts) + { + vtkErrorMacro("Error stepping through points."); + return 0; + } + newPts->InsertNextPoint(inPts->GetPoint(id)); + } + + // add lines + for (idx = 1; idx < num; ++idx) + { + ids[0] = idx+offset-1; + ids[1] = idx+offset; + newLines->InsertNextCell(2, ids); + } + } + } + + output->SetPoints(newPts); + newPts->Delete(); + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +int vtkStructuredGridOutlineFilter::FillInputPortInformation( + int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} + diff --git a/Graphics/vtkStructuredGridOutlineFilter.h b/Graphics/vtkStructuredGridOutlineFilter.h new file mode 100644 index 0000000..c22d5d3 --- /dev/null +++ b/Graphics/vtkStructuredGridOutlineFilter.h @@ -0,0 +1,44 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridOutlineFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridOutlineFilter - create wireframe outline for structured grid +// .SECTION Description +// vtkStructuredGridOutlineFilter is a filter that generates a wireframe +// outline of a structured grid (vtkStructuredGrid). Structured data is +// topologically a cube, so the outline will have 12 "edges". + +#ifndef __vtkStructuredGridOutlineFilter_h +#define __vtkStructuredGridOutlineFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkStructuredGridOutlineFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkStructuredGridOutlineFilter *New(); + vtkTypeRevisionMacro(vtkStructuredGridOutlineFilter,vtkPolyDataAlgorithm); + +protected: + vtkStructuredGridOutlineFilter() {}; + ~vtkStructuredGridOutlineFilter() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkStructuredGridOutlineFilter(const vtkStructuredGridOutlineFilter&); // Not implemented. + void operator=(const vtkStructuredGridOutlineFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkStructuredPointsGeometryFilter.cxx b/Graphics/vtkStructuredPointsGeometryFilter.cxx new file mode 100644 index 0000000..299433b --- /dev/null +++ b/Graphics/vtkStructuredPointsGeometryFilter.cxx @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsGeometryFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsGeometryFilter.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkStructuredPointsGeometryFilter, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkStructuredPointsGeometryFilter); + +vtkStructuredPointsGeometryFilter::vtkStructuredPointsGeometryFilter() +{ + vtkErrorMacro("vtkStructuredPointsGeometryFilter will be deprecated in" << endl << + "the next release after VTK 4.0. Please use" << endl << + "vtkImageDataGeometryFilter instead" ); +} diff --git a/Graphics/vtkStructuredPointsGeometryFilter.h b/Graphics/vtkStructuredPointsGeometryFilter.h new file mode 100644 index 0000000..ce640e4 --- /dev/null +++ b/Graphics/vtkStructuredPointsGeometryFilter.h @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsGeometryFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsGeometryFilter - obsolete class +// .SECTION Description +// vtkStructuredPointsGeometryFilter has been renamed to +// vtkImageDataGeometryFilter + +#ifndef __vtkStructuredPointsGeometryFilter_h +#define __vtkStructuredPointsGeometryFilter_h + +#include "vtkImageDataGeometryFilter.h" + +class VTK_GRAPHICS_EXPORT vtkStructuredPointsGeometryFilter : public vtkImageDataGeometryFilter +{ +public: + vtkTypeRevisionMacro(vtkStructuredPointsGeometryFilter,vtkImageDataGeometryFilter); + + // Description: + // Construct with initial extent of all the data + static vtkStructuredPointsGeometryFilter *New(); + +protected: + vtkStructuredPointsGeometryFilter(); + ~vtkStructuredPointsGeometryFilter() {}; + +private: + vtkStructuredPointsGeometryFilter(const vtkStructuredPointsGeometryFilter&); // Not implemented + void operator=(const vtkStructuredPointsGeometryFilter&); // Not implemented +}; + +#endif diff --git a/Graphics/vtkSubPixelPositionEdgels.cxx b/Graphics/vtkSubPixelPositionEdgels.cxx new file mode 100644 index 0000000..a9af2da --- /dev/null +++ b/Graphics/vtkSubPixelPositionEdgels.cxx @@ -0,0 +1,770 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSubPixelPositionEdgels.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSubPixelPositionEdgels.h" + +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredPoints.h" + +vtkCxxRevisionMacro(vtkSubPixelPositionEdgels, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkSubPixelPositionEdgels); + +vtkSubPixelPositionEdgels::vtkSubPixelPositionEdgels() +{ + this->TargetFlag = 0; + this->TargetValue = 0.0; + + this->SetNumberOfInputPorts(2); +} + +vtkSubPixelPositionEdgels::~vtkSubPixelPositionEdgels() +{ +} + +int vtkSubPixelPositionEdgels::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *gradMapsInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkStructuredPoints *gradMaps = vtkStructuredPoints::SafeDownCast( + gradMapsInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts=input->GetNumberOfPoints(); + vtkPoints *newPts; + vtkDoubleArray *newNormals; + vtkPoints *inPts; + vtkDataArray *inVectors; + vtkIdType ptId; + float *MapData = 0; + double *DMapData = 0; + double pnt[3]; + int *dimensions; + double result[3], resultNormal[3]; + double *spacing, *origin; + + vtkDebugMacro(<<"SubPixelPositioning Edgels"); + + if ( numPts < 1 || (inPts=input->GetPoints()) == NULL ) + { + vtkErrorMacro(<<"No data to fit!"); + return 1; + } + + newPts = vtkPoints::New(); + newNormals = vtkDoubleArray::New(); + newNormals->SetNumberOfComponents(3); + + dimensions = gradMaps->GetDimensions(); + spacing = gradMaps->GetSpacing(); + origin = gradMaps->GetOrigin(); + if (vtkDoubleArray::SafeDownCast(gradMaps->GetPointData()->GetScalars())) + { + DMapData = vtkDoubleArray::SafeDownCast(gradMaps->GetPointData() + ->GetScalars())->GetPointer(0); + } + else if (vtkFloatArray::SafeDownCast(gradMaps->GetPointData()->GetScalars())) + { + MapData = vtkFloatArray::SafeDownCast(gradMaps->GetPointData() + ->GetScalars())->GetPointer(0); + } + + inVectors = gradMaps->GetPointData()->GetVectors(); + + // + // Loop over all points, adjusting locations + // + for (ptId=0; ptId < inPts->GetNumberOfPoints(); ptId++) + { + inPts->GetPoint(ptId,pnt); + pnt[0] = (pnt[0] - origin[0])/spacing[0]; + pnt[1] = (pnt[1] - origin[1])/spacing[1]; + pnt[2] = (pnt[2] - origin[2])/spacing[2]; + if (MapData) + { + this->Move(dimensions[0],dimensions[1],dimensions[2], + (int)(pnt[0]+0.5),(int)(pnt[1]+0.5),MapData, + inVectors, result, (int)(pnt[2]+0.5), spacing, + resultNormal); + } + else if (DMapData) + { + this->Move(dimensions[0],dimensions[1],dimensions[2], + (int)(pnt[0]+0.5),(int)(pnt[1]+0.5),DMapData, + inVectors, result, (int)(pnt[2]+0.5), spacing, + resultNormal); + } + result[0] = result[0]*spacing[0] + origin[0]; + result[1] = result[1]*spacing[1] + origin[1]; + result[2] = result[2]*spacing[2] + origin[2]; + newPts->InsertNextPoint(result); + newNormals->InsertNextTuple(resultNormal); + } + + output->CopyStructure(input); + output->GetPointData()->CopyNormalsOff(); + output->GetPointData()->PassData(input->GetPointData()); + output->GetPointData()->SetNormals(newNormals); + output->SetPoints(newPts); + newPts->Delete(); + newNormals->Delete(); + + return 1; +} + +void vtkSubPixelPositionEdgels::Move(int xdim, int ydim, int zdim, + int x, int y, + double *img, vtkDataArray *inVecs, + double *result, int z, double *spacing, + double *resultNormal) +{ + int ypos; + vtkIdType zpos; + double vec[3]; + double valn, valp; + double mag; + double a,b,c; + double xp, yp, zp; + double xn, yn, zn; + int xi, yi, zi, i; + + zpos = z*xdim*ydim; + + ypos = y*xdim; + + // handle the 2d case + if (zdim < 2) + { + if (x < 1 || y < 1 || x >= (xdim-2) || y >= (ydim -2)) + { + result[0] = x; + result[1] = y; + result[2] = z; + // if the point of off of the grad map just make up a value + if (x < 0 || y < 0 || x > xdim || y > ydim) + { + resultNormal[0] = 1; + resultNormal[1] = 0; + resultNormal[2] = 0; + } + else + { + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(x + xdim*y)[i]; + } + vtkMath::Normalize(resultNormal); + } + } + else + { + // first get the orientation + inVecs->GetTuple(x+ypos,vec); + vec[0] = vec[0]*spacing[0]; + vec[1] = vec[1]*spacing[1]; + vec[2] = 0; + vtkMath::Normalize(vec); + mag = img[x+ypos]; + + // compute the sample points + xp = (double)x + vec[0]; + yp = (double)y + vec[1]; + xn = (double)x - vec[0]; + yn = (double)y - vec[1]; + + // compute their values + xi = (int)xp; + yi = (int)yp; + valp = + img[xi +xdim*yi]*(1.0 -xp +xi)*(1.0 -yp +yi) + + img[1 +xi + xdim*yi]*(xp -xi)*(1.0 -yp +yi) + + img[xi +xdim*(yi +1)]*(1.0 -xp +xi)*(yp -yi) + + img[1 + xi + xdim*(yi +1)]*(xp -xi)*(yp -yi); + + xi = (int)xn; + yi = (int)yn; + valn = + img[xi +xdim*yi]*(1.0 -xn +xi)*(1.0 -yn +yi) + + img[1 + xi +xdim*yi]*(xn -xi)*(1.0 -yn +yi) + + img[xi + xdim*(yi +1)]*(1.0 -xn +xi)*(yn -yi) + + img[1 + xi + xdim*(yi +1)]*(xn -xi)*(yn -yi); + + result[0] = x; + result[1] = y; + result[2] = z; + + // now fit to a parabola and find max + c = mag; + b = (valp - valn)/2.0; + a = (valp - c - b); + // assign the root to c because MSVC5.0 optimizer has problems with this + // function + c = -0.5*b/a; + if (c > 1.0) + { + c = 1.0; + } + if (c < -1.0) + { + c = -1.0; + } + result[0] += vec[0]*c; + result[1] += vec[1]*c; + + // now calc the normal, trilinear interp of vectors + xi = (int)result[0]; + yi = (int)result[1]; + //zi = (int)result[2]; + xn = result[0]; + yn = result[1]; + //zn = result[2]; + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(xi + xdim*yi)[i] * (1.0 -xn +xi)*(1.0 -yn +yi) + + inVecs->GetTuple(1 + xi + xdim*yi)[i] * (xn -xi)*(1.0 -yn +yi) + + inVecs->GetTuple(xi + xdim*(yi +1))[i] * (1.0 -xn +xi)*(yn -yi) + + inVecs->GetTuple(1 + xi + xdim*(yi +1))[i] * (xn -xi)*(yn -yi); + } + vtkMath::Normalize(resultNormal); + } + } + else + { + if (x < 1 || y < 1 || z < 1 || + x >= (xdim-2) || y >= (ydim -2) || z >= (zdim -2)) + { + result[0] = x; + result[1] = y; + result[2] = z; + if (x < 0 || y < 0 || z < 0 || + x > xdim || y > ydim || z > zdim) + { + resultNormal[0] = 1; + resultNormal[1] = 1; + resultNormal[2] = 1; + } + else + { + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(x + xdim*y + xdim*ydim*z)[i]; + } + vtkMath::Normalize(resultNormal); + } + } + else + { + // first get the orientation + inVecs->GetTuple(x+ypos+zpos,vec); + vec[0] = vec[0]*spacing[0]; + vec[1] = vec[1]*spacing[1]; + vec[2] = vec[2]*spacing[2]; + vtkMath::Normalize(vec); + mag = img[x+ypos+zpos]; + + // compute the sample points + xp = (double)x + vec[0]; + yp = (double)y + vec[1]; + zp = (double)z + vec[2]; + xn = (double)x - vec[0]; + yn = (double)y - vec[1]; + zn = (double)z - vec[2]; + + // compute their values + xi = (int)xp; + yi = (int)yp; + zi = (int)zp; + + // This set of statements used to be one statement. It was broken up + // due to problems with MSVC 5.0 + valp = + img[xi +xdim*(yi +zi*ydim)]*(1.0 -xp +xi)*(1.0 -yp +yi)*(1.0 -zp +zi); + valp += + img[1 +xi + xdim*(yi + zi*ydim)]*(xp -xi)*(1.0 -yp +yi)*(1.0 -zp +zi); + valp += + img[xi +xdim*(yi +1 + zi*ydim)]*(1.0 -xp +xi)*(yp -yi)*(1.0 -zp +zi); + valp += + img[1 + xi + xdim*(yi +1 +zi*ydim)]*(xp -xi)*(yp -yi)*(1.0 -zp +zi); + valp += + img[xi +xdim*(yi + (zi+1)*ydim)]*(1.0 -xp +xi)*(1.0 -yp +yi)*(zp -zi); + valp += + img[1 + xi + xdim*(yi + (zi+1)*ydim)]*(xp -xi)*(1.0 -yp +yi)*(zp -zi); + valp += + img[xi + xdim*(yi +1 + (zi+1)*ydim)]*(1.0 -xp +xi)*(yp -yi)*(zp -zi); + valp += + img[1 + xi + xdim*(yi +1 +(zi+1)*ydim)]*(xp -xi)*(yp -yi)*(zp -zi); + + xi = (int)xn; + yi = (int)yn; + zi = (int)zn; + // This set of statements used to be one statement. It was broken up + // due to problems with MSVC 5.0 + valn = + img[xi +xdim*(yi +zi*ydim)]*(1.0 -xn +xi)*(1.0 -yn +yi)*(1.0 -zn +zi); + valn += + img[1 + xi +xdim*(yi + zi*ydim)]*(xn -xi)*(1.0 -yn +yi)*(1.0 -zn +zi); + valn += + img[xi + xdim*(yi +1 + zi*ydim)]*(1.0 -xn +xi)*(yn -yi)*(1.0 -zn +zi); + valn += + img[1 + xi + xdim*(yi +1 +zi*ydim)]*(xn -xi)*(yn -yi)*(1.0 -zn +zi); + valn += + img[xi +xdim*(yi + (zi+1)*ydim)]*(1.0 -xn +xi)*(1.0 -yn +yi)*(zn -zi); + valn += + img[1 + xi + xdim*(yi + (zi+1)*ydim)]*(xn -xi)*(1.0 -yn +yi)*(zn -zi); + valn += + img[xi + xdim*(yi +1 + (zi+1)*ydim)]*(1.0 -xn +xi)*(yn -yi)*(zn -zi); + valn += + img[1 + xi + xdim*(yi +1 +(zi+1)*ydim)]*(xn -xi)*(yn -yi)*(zn -zi); + + result[0] = x; + result[1] = y; + result[2] = z; + + if (this->TargetFlag) + { + // For target, do a simple linear interpolation to avoid binomial. + c = mag; + if (c == this->TargetValue) + { + c = 0.0; + } + else if ((this->TargetValue < c && valp < c) || + (this->TargetValue > c && valp > c)) + { + c = (this->TargetValue - c) / (valp - c); + } + else if ((this->TargetValue < c && valn < c) || + (this->TargetValue < c && valn > c)) + { + c = (this->TargetValue - c) / (c - valn); + } + else + { + c = 0.0; + } + } + else + { + // now fit to a parabola and find max + c = mag; + b = (valp - valn)/2.0; + a = (valp - c - b); + + //assign the root to c because MSVC5.0 optimizer has problems with this + // function + c = -0.5*b/a; + } + + if (c > 1.0) + { + c = 1.0; + } + if (c < -1.0) + { + c = -1.0; + } + result[0] = result[0] + vec[0]*c; + result[1] = result[1] + vec[1]*c; + result[2] = result[2] + vec[2]*c; + + // now calc the normal, trilinear interp of vectors + xi = (int)result[0]; + yi = (int)result[1]; + zi = (int)result[2]; + xn = result[0]; + yn = result[1]; + zn = result[2]; + + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(xi + xdim*(yi + zi*ydim))[i] * + (1.0 -xn +xi)*(1.0 -yn +yi)*(1.0 -zn +zi) + + inVecs->GetTuple(1 + xi + xdim*(yi + zi*ydim))[i] * + (xn -xi)*(1.0 -yn +yi)*(1.0 -zn +zi) + + inVecs->GetTuple(xi + xdim*(yi +1 + zi*ydim))[i] * + (1.0 -xn +xi)*(yn -yi)*(1.0 -zn +zi) + + inVecs->GetTuple(1 + xi + xdim*(yi +1 +zi*ydim))[i] * + (xn -xi)*(yn -yi)*(1.0 -zn +zi) + + inVecs->GetTuple(xi + xdim*(yi + (zi+1)*ydim))[i] * + (1.0 -xn +xi)*(1.0 -yn +yi)*(zn -zi) + + inVecs->GetTuple(1 + xi + xdim*(yi + (zi+1)*ydim))[i] * + (xn -xi)*(1.0 -yn +yi)*(zn -zi) + + inVecs->GetTuple(xi + xdim*(yi +1 + (zi+1)*ydim))[i] * + (1.0 -xn +xi)*(yn -yi)*(zn -zi) + + inVecs->GetTuple(1 + xi + xdim*(yi +1 +(zi+1)*ydim))[i] * + (xn -xi)*(yn -yi)*(zn -zi); + } + vtkMath::Normalize(resultNormal); + + } + } +} + +void vtkSubPixelPositionEdgels::Move(int xdim, int ydim, int zdim, + int x, int y, + float *img, vtkDataArray *inVecs, + double *result, int z, double *spacing, + double *resultNormal) +{ + int ypos; + vtkIdType zpos; + double vec[3]; + double valn, valp; + double mag; + double a,b,c; + double xp, yp, zp; + double xn, yn, zn; + int xi, yi, zi, i; + + zpos = z*xdim*ydim; + + ypos = y*xdim; + + // handle the 2d case + if (zdim < 2) + { + if (x < 1 || y < 1 || x >= (xdim-2) || y >= (ydim -2)) + { + result[0] = x; + result[1] = y; + result[2] = z; + // if the point of off of the grad map just make up a value + if (x < 0 || y < 0 || x > xdim || y > ydim) + { + resultNormal[0] = 1; + resultNormal[1] = 0; + resultNormal[2] = 0; + } + else + { + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(x + xdim*y)[i]; + } + vtkMath::Normalize(resultNormal); + } + } + else + { + // first get the orientation + inVecs->GetTuple(x+ypos,vec); + vec[0] = vec[0]*spacing[0]; + vec[1] = vec[1]*spacing[1]; + vec[2] = 0; + vtkMath::Normalize(vec); + mag = img[x+ypos]; + + // compute the sample points + xp = (double)x + vec[0]; + yp = (double)y + vec[1]; + xn = (double)x - vec[0]; + yn = (double)y - vec[1]; + + // compute their values + xi = (int)xp; + yi = (int)yp; + valp = + img[xi +xdim*yi]*(1.0 -xp +xi)*(1.0 -yp +yi) + + img[1 +xi + xdim*yi]*(xp -xi)*(1.0 -yp +yi) + + img[xi +xdim*(yi +1)]*(1.0 -xp +xi)*(yp -yi) + + img[1 + xi + xdim*(yi +1)]*(xp -xi)*(yp -yi); + + xi = (int)xn; + yi = (int)yn; + valn = + img[xi +xdim*yi]*(1.0 -xn +xi)*(1.0 -yn +yi) + + img[1 + xi +xdim*yi]*(xn -xi)*(1.0 -yn +yi) + + img[xi + xdim*(yi +1)]*(1.0 -xn +xi)*(yn -yi) + + img[1 + xi + xdim*(yi +1)]*(xn -xi)*(yn -yi); + + result[0] = x; + result[1] = y; + result[2] = z; + + // now fit to a parabola and find max + c = mag; + b = (valp - valn)/2.0; + a = (valp - c - b); + // assign the root to c because MSVC5.0 optimizer has problems with this + // function + c = -0.5*b/a; + if (c > 1.0) + { + c = 1.0; + } + if (c < -1.0) + { + c = -1.0; + } + result[0] += vec[0]*c; + result[1] += vec[1]*c; + + // now calc the normal, trilinear interp of vectors + xi = (int)result[0]; + yi = (int)result[1]; + //zi = (int)result[2]; + xn = result[0]; + yn = result[1]; + //zn = result[2]; + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(xi + xdim*yi)[i] * (1.0 -xn +xi)*(1.0 -yn +yi) + + inVecs->GetTuple(1 + xi + xdim*yi)[i] * (xn -xi)*(1.0 -yn +yi) + + inVecs->GetTuple(xi + xdim*(yi +1))[i] * (1.0 -xn +xi)*(yn -yi) + + inVecs->GetTuple(1 + xi + xdim*(yi +1))[i] * (xn -xi)*(yn -yi); + } + vtkMath::Normalize(resultNormal); + } + } + else + { + if (x < 1 || y < 1 || z < 1 || + x >= (xdim-2) || y >= (ydim -2) || z >= (zdim -2)) + { + result[0] = x; + result[1] = y; + result[2] = z; + if (x < 0 || y < 0 || z < 0 || + x > xdim || y > ydim || z > zdim) + { + resultNormal[0] = 1; + resultNormal[1] = 1; + resultNormal[2] = 1; + } + else + { + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(x + xdim*y + xdim*ydim*z)[i]; + } + vtkMath::Normalize(resultNormal); + } + } + else + { + // first get the orientation + inVecs->GetTuple(x+ypos+zpos,vec); + vec[0] = vec[0]*spacing[0]; + vec[1] = vec[1]*spacing[1]; + vec[2] = vec[2]*spacing[2]; + vtkMath::Normalize(vec); + mag = img[x+ypos+zpos]; + + // compute the sample points + xp = (double)x + vec[0]; + yp = (double)y + vec[1]; + zp = (double)z + vec[2]; + xn = (double)x - vec[0]; + yn = (double)y - vec[1]; + zn = (double)z - vec[2]; + + // compute their values + xi = (int)xp; + yi = (int)yp; + zi = (int)zp; + + // This set of statements used to be one statement. It was broken up + // due to problems with MSVC 5.0 + valp = + img[xi +xdim*(yi +zi*ydim)]*(1.0 -xp +xi)*(1.0 -yp +yi)*(1.0 -zp +zi); + valp += + img[1 +xi + xdim*(yi + zi*ydim)]*(xp -xi)*(1.0 -yp +yi)*(1.0 -zp +zi); + valp += + img[xi +xdim*(yi +1 + zi*ydim)]*(1.0 -xp +xi)*(yp -yi)*(1.0 -zp +zi); + valp += + img[1 + xi + xdim*(yi +1 +zi*ydim)]*(xp -xi)*(yp -yi)*(1.0 -zp +zi); + valp += + img[xi +xdim*(yi + (zi+1)*ydim)]*(1.0 -xp +xi)*(1.0 -yp +yi)*(zp -zi); + valp += + img[1 + xi + xdim*(yi + (zi+1)*ydim)]*(xp -xi)*(1.0 -yp +yi)*(zp -zi); + valp += + img[xi + xdim*(yi +1 + (zi+1)*ydim)]*(1.0 -xp +xi)*(yp -yi)*(zp -zi); + valp += + img[1 + xi + xdim*(yi +1 +(zi+1)*ydim)]*(xp -xi)*(yp -yi)*(zp -zi); + + xi = (int)xn; + yi = (int)yn; + zi = (int)zn; + // This set of statements used to be one statement. It was broken up + // due to problems with MSVC 5.0 + valn = + img[xi +xdim*(yi +zi*ydim)]*(1.0 -xn +xi)*(1.0 -yn +yi)*(1.0 -zn +zi); + valn += + img[1 + xi +xdim*(yi + zi*ydim)]*(xn -xi)*(1.0 -yn +yi)*(1.0 -zn +zi); + valn += + img[xi + xdim*(yi +1 + zi*ydim)]*(1.0 -xn +xi)*(yn -yi)*(1.0 -zn +zi); + valn += + img[1 + xi + xdim*(yi +1 +zi*ydim)]*(xn -xi)*(yn -yi)*(1.0 -zn +zi); + valn += + img[xi +xdim*(yi + (zi+1)*ydim)]*(1.0 -xn +xi)*(1.0 -yn +yi)*(zn -zi); + valn += + img[1 + xi + xdim*(yi + (zi+1)*ydim)]*(xn -xi)*(1.0 -yn +yi)*(zn -zi); + valn += + img[xi + xdim*(yi +1 + (zi+1)*ydim)]*(1.0 -xn +xi)*(yn -yi)*(zn -zi); + valn += + img[1 + xi + xdim*(yi +1 +(zi+1)*ydim)]*(xn -xi)*(yn -yi)*(zn -zi); + + result[0] = x; + result[1] = y; + result[2] = z; + + if (this->TargetFlag) + { + // For target, do a simple linear interpolation to avoid binomial. + c = mag; + if (c == this->TargetValue) + { + c = 0.0; + } + else if ((this->TargetValue < c && valp < c) || + (this->TargetValue > c && valp > c)) + { + c = (this->TargetValue - c) / (valp - c); + } + else if ((this->TargetValue < c && valn < c) || + (this->TargetValue < c && valn > c)) + { + c = (this->TargetValue - c) / (c - valn); + } + else + { + c = 0.0; + } + } + else + { + // now fit to a parabola and find max + c = mag; + b = (valp - valn)/2.0; + a = (valp - c - b); + + //assign the root to c because MSVC5.0 optimizer has problems with this + // function + c = -0.5*b/a; + } + + if (c > 1.0) + { + c = 1.0; + } + if (c < -1.0) + { + c = -1.0; + } + result[0] = result[0] + vec[0]*c; + result[1] = result[1] + vec[1]*c; + result[2] = result[2] + vec[2]*c; + + // now calc the normal, trilinear interp of vectors + xi = (int)result[0]; + yi = (int)result[1]; + zi = (int)result[2]; + xn = result[0]; + yn = result[1]; + zn = result[2]; + + for (i = 0; i < 3; i++) + { + resultNormal[i] = + inVecs->GetTuple(xi + xdim*(yi + zi*ydim))[i] * + (1.0 -xn +xi)*(1.0 -yn +yi)*(1.0 -zn +zi) + + inVecs->GetTuple(1 + xi + xdim*(yi + zi*ydim))[i] * + (xn -xi)*(1.0 -yn +yi)*(1.0 -zn +zi) + + inVecs->GetTuple(xi + xdim*(yi +1 + zi*ydim))[i] * + (1.0 -xn +xi)*(yn -yi)*(1.0 -zn +zi) + + inVecs->GetTuple(1 + xi + xdim*(yi +1 +zi*ydim))[i] * + (xn -xi)*(yn -yi)*(1.0 -zn +zi) + + inVecs->GetTuple(xi + xdim*(yi + (zi+1)*ydim))[i] * + (1.0 -xn +xi)*(1.0 -yn +yi)*(zn -zi) + + inVecs->GetTuple(1 + xi + xdim*(yi + (zi+1)*ydim))[i] * + (xn -xi)*(1.0 -yn +yi)*(zn -zi) + + inVecs->GetTuple(xi + xdim*(yi +1 + (zi+1)*ydim))[i] * + (1.0 -xn +xi)*(yn -yi)*(zn -zi) + + inVecs->GetTuple(1 + xi + xdim*(yi +1 +(zi+1)*ydim))[i] * + (xn -xi)*(yn -yi)*(zn -zi); + } + vtkMath::Normalize(resultNormal); + + } + } +} + +void vtkSubPixelPositionEdgels::SetGradMaps(vtkStructuredPoints *gm) +{ + this->SetInput(1, gm); +} + +vtkStructuredPoints *vtkSubPixelPositionEdgels::GetGradMaps() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkStructuredPoints::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +int vtkSubPixelPositionEdgels::FillInputPortInformation(int port, + vtkInformation *info) +{ + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredPoints"); + return 1; + } + + return this->Superclass::FillInputPortInformation(port, info); +} + +// Print the state of the class. +void vtkSubPixelPositionEdgels::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->GetGradMaps() ) + { + os << indent << "Gradient Data: " << this->GetGradMaps() << "\n"; + } + else + { + os << indent << "Gradient Data: (none)\n"; + } + + os << indent << "TargetFlag: " << this->TargetFlag << endl; + os << indent << "TargetValue: " << this->TargetValue << endl; +} diff --git a/Graphics/vtkSubPixelPositionEdgels.h b/Graphics/vtkSubPixelPositionEdgels.h new file mode 100644 index 0000000..dc43b0a --- /dev/null +++ b/Graphics/vtkSubPixelPositionEdgels.h @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSubPixelPositionEdgels.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSubPixelPositionEdgels - adjust edgel locations based on gradients. +// .SECTION Description +// vtkSubPixelPositionEdgels is a filter that takes a series of linked +// edgels (digital curves) and gradient maps as input. It then adjusts +// the edgel locations based on the gradient data. Specifically, the +// algorithm first determines the neighboring gradient magnitudes of +// an edgel using simple interpolation of its neighbors. It then fits +// the following three data points: negative gradient direction +// gradient magnitude, edgel gradient magnitude and positive gradient +// direction gradient magnitude to a quadratic function. It then +// solves this quadratic to find the maximum gradient location along +// the gradient orientation. It then modifies the edgels location +// along the gradient orientation to the calculated maximum +// location. This algorithm does not adjust an edgel in the direction +// orthogonal to its gradient vector. + +// .SECTION see also +// vtkImageData vtkImageGradient vtkLinkEdgels + +#ifndef __vtkSubPixelPositionEdgels_h +#define __vtkSubPixelPositionEdgels_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkStructuredPoints; +class vtkDataArray; + +class VTK_GRAPHICS_EXPORT vtkSubPixelPositionEdgels : public vtkPolyDataAlgorithm +{ +public: + static vtkSubPixelPositionEdgels *New(); + vtkTypeRevisionMacro(vtkSubPixelPositionEdgels,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the gradient data for doing the position adjustments. + void SetGradMaps(vtkStructuredPoints *gm); + vtkStructuredPoints *GetGradMaps(); + + // Description: + // These methods can make the positioning look for a target scalar value + // instead of looking for a maximum. + vtkSetMacro(TargetFlag, int); + vtkGetMacro(TargetFlag, int); + vtkBooleanMacro(TargetFlag, int); + vtkSetMacro(TargetValue, double); + vtkGetMacro(TargetValue, double); + +protected: + vtkSubPixelPositionEdgels(); + ~vtkSubPixelPositionEdgels(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + void Move(int xdim, int ydim, int zdim, int x, int y, + float *img, vtkDataArray *inVecs, + double *result, int z, double *aspect, double *resultNormal); + void Move(int xdim, int ydim, int zdim, int x, int y, + double *img, vtkDataArray *inVecs, + double *result, int z, double *aspect, double *resultNormal); + // extension for target instead of maximum + int TargetFlag; + double TargetValue; +private: + vtkSubPixelPositionEdgels(const vtkSubPixelPositionEdgels&); // Not implemented. + void operator=(const vtkSubPixelPositionEdgels&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkSubdivideTetra.cxx b/Graphics/vtkSubdivideTetra.cxx new file mode 100644 index 0000000..6ad7973 --- /dev/null +++ b/Graphics/vtkSubdivideTetra.cxx @@ -0,0 +1,248 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSubdivideTetra.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSubdivideTetra.h" + +#include "vtkCellType.h" +#include "vtkGenericCell.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkSubdivideTetra, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkSubdivideTetra); + +//---------------------------------------------------------------------------- +// Description: +// Construct with all types of clipping turned off. +vtkSubdivideTetra::vtkSubdivideTetra() +{ +} + +//---------------------------------------------------------------------------- +int vtkSubdivideTetra::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts = input->GetNumberOfPoints(); + vtkIdType numCells = input->GetNumberOfCells(); + vtkPoints *inPts = input->GetPoints(); + vtkIdType cellId, i; + vtkIdType pts[4]; + vtkGenericCell *cell; + vtkPointData *pd = input->GetPointData(); + vtkPointData *outputPD = output->GetPointData(); + vtkPoints *newPts; + vtkIdType ptId; + + double weights[4], x0[3], x1[3], x2[3], x3[3], x[3]; + int p0, p1, p2, p3; + vtkIdType center, e01, e02, e03, e12, e13, e23; + vtkMergePoints *locator; + + vtkDebugMacro(<<"Executing mesh subdivide"); + + if (input->IsHomogeneous() == 0 || + input->GetCellType(0) != VTK_TETRA) + { + vtkErrorMacro(<<"all cells must be tetrahedra."); + return 1; + } + + // Copy original points and point data + newPts = vtkPoints::New(); + newPts->Allocate(5*numPts,numPts); + outputPD->InterpolateAllocate(pd,5*numPts,numPts); + + output->Allocate(numCells); + output->SetPoints(newPts); + + locator = vtkMergePoints::New(); + locator->InitPointInsertion (newPts, input->GetBounds()); + + for (ptId=0; ptId < numPts; ptId++) + { + locator->InsertNextPoint(inPts->GetPoint(ptId)); + outputPD->CopyData(pd,ptId,ptId); + } + + cell = vtkGenericCell::New(); + + // loop over tetrahedra, generating sixteen new ones for each. This is + // done by introducing mid-edge nodes and a single mid-tetra node. + for(cellId=0; cellId < numCells; cellId++) + { + input->GetCell(cellId, cell); + + // get tetra points + cell->Points->GetPoint(0,x0); + cell->Points->GetPoint(1,x1); + cell->Points->GetPoint(2,x2); + cell->Points->GetPoint(3,x3); + + p0 = cell->PointIds->GetId(0); + p1 = cell->PointIds->GetId(1); + p2 = cell->PointIds->GetId(2); + p3 = cell->PointIds->GetId(3); + + // compute center point + weights[0] = weights[1] = weights[2] = weights[3] = 0.25; + for (i=0; i<3; i++) + { + x[i] = 0.25*(x0[i] + x1[i] + x2[i] + x3[i]); + } + center = locator->InsertNextPoint(x); + outputPD->InterpolatePoint(pd, center, cell->PointIds, weights); + + // compute edge points + // edge 0-1 + for (i=0; i<3; i++) + { + x[i] = 0.5 * (x1[i] + x0[i]); + } + e01 = locator->InsertNextPoint(x); + outputPD->InterpolateEdge(pd, e01, p0, p1, 0.5); + + // edge 1-2 + for (i=0; i<3; i++) + { + x[i] = 0.5 * (x2[i] + x1[i]); + } + e12 = locator->InsertNextPoint(x); + outputPD->InterpolateEdge(pd, e12, p1, p2, 0.5); + + // edge 2-0 + for (i=0; i<3; i++) + { + x[i] = 0.5 * (x2[i] + x0[i]); + } + e02 = locator->InsertNextPoint(x); + outputPD->InterpolateEdge(pd, e02, p2, p0, 0.5); + + // edge 0-3 + for (i=0; i<3; i++) + { + x[i] = 0.5 * (x3[i] + x0[i]); + } + e03 = locator->InsertNextPoint(x); + outputPD->InterpolateEdge(pd, e03, p0, p3, 0.5); + + // edge 1-3 + for (i=0; i<3; i++) + { + x[i] = 0.5 * (x3[i] + x1[i]); + } + e13 = locator->InsertNextPoint(x); + outputPD->InterpolateEdge(pd, e13, p1, p3, 0.5); + + // edge 2-3 + for (i=0; i<3; i++) + { + x[i] = 0.5 * (x3[i] + x2[i]); + } + e23 = locator->InsertNextPoint(x); + outputPD->InterpolateEdge(pd, e23, p2, p3, 0.5); + + // Now create tetrahedra + // First, four tetra from each vertex + pts[0] = p0; + pts[1] = e01; + pts[2] = e02; + pts[3] = e03; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[0] = p1; + pts[1] = e01; + pts[2] = e12; + pts[3] = e13; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[0] = p2; + pts[1] = e02; + pts[2] = e12; + pts[3] = e23; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[0] = p3; + pts[1] = e03; + pts[2] = e13; + pts[3] = e23; + output->InsertNextCell(VTK_TETRA, 4, pts); + + // Now four tetra from cut-off tetra corners + pts[0] = center; + pts[1] = e01; + pts[2] = e02; + pts[3] = e03; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[1] = e01; + pts[2] = e12; + pts[3] = e13; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[1] = e02; + pts[2] = e12; + pts[3] = e23; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[1] = e03; + pts[2] = e13; + pts[3] = e23; + output->InsertNextCell(VTK_TETRA, 4, pts); + + // Now four tetra from triangles on tetra faces + pts[0] = center; + pts[1] = e01; + pts[2] = e12; + pts[3] = e02; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[1] = e01; + pts[2] = e13; + pts[3] = e03; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[1] = e12; + pts[2] = e23; + pts[3] = e13; + output->InsertNextCell(VTK_TETRA, 4, pts); + pts[1] = e02; + pts[2] = e23; + pts[3] = e03; + output->InsertNextCell(VTK_TETRA, 4, pts); + + } //for all cells + cell->Delete(); + + vtkDebugMacro(<<"Subdivided " << numCells << " cells"); + + locator->Delete(); + newPts->Delete(); + output->Squeeze(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkSubdivideTetra::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkSubdivideTetra.h b/Graphics/vtkSubdivideTetra.h new file mode 100644 index 0000000..369ef9e --- /dev/null +++ b/Graphics/vtkSubdivideTetra.h @@ -0,0 +1,46 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSubdivideTetra.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSubdivideTetra - subdivide one tetrahedron into twelve for every tetra +// .SECTION Description +// This filter subdivides tetrahedra in an unstructured grid into twelve tetrahedra. + + +#ifndef __vtkSubdivideTetra_h +#define __vtkSubdivideTetra_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkSubdivideTetra : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkSubdivideTetra *New(); + vtkTypeRevisionMacro(vtkSubdivideTetra,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + +protected: + vtkSubdivideTetra(); + ~vtkSubdivideTetra() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkSubdivideTetra(const vtkSubdivideTetra&); // Not implemented. + void operator=(const vtkSubdivideTetra&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkSuperquadricSource.cxx b/Graphics/vtkSuperquadricSource.cxx new file mode 100644 index 0000000..eb19d87 --- /dev/null +++ b/Graphics/vtkSuperquadricSource.cxx @@ -0,0 +1,406 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSuperquadricSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* vtkSuperquadric originally written by Michael Halle, + Brigham and Women's Hospital, July 1998. + + Based on "Rigid physically based superquadrics", A. H. Barr, + in "Graphics Gems III", David Kirk, ed., Academic Press, 1992. +*/ +#include "vtkSuperquadricSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +#include + +vtkCxxRevisionMacro(vtkSuperquadricSource, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkSuperquadricSource); + +static void evalSuperquadric(double u, double v, + double du, double dv, + double n, double e, + double dims[3], + double alpha, + double xyz[3], + double nrm[3]); + +// Description: +vtkSuperquadricSource::vtkSuperquadricSource(int res) +{ + res = res < 4 ? 4 : res; + + this->Toroidal = 0; + this->Thickness = 0.3333; + this->PhiRoundness = 0.0; + this->SetPhiRoundness(1.0); + this->ThetaRoundness = 0.0; + this->SetThetaRoundness(1.0); + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + this->Scale[0] = this->Scale[1] = this->Scale[2] = 1.0; + this->Size = .5; + this->ThetaResolution = 0; + this->SetThetaResolution(res); + this->PhiResolution = 0; + this->SetPhiResolution(res); + + this->SetNumberOfInputPorts(0); +} + +void vtkSuperquadricSource::SetPhiResolution(int i) +{ + if(i < 4) + { + i = 4; + } + i = (i+3)/4*4; // make it divisible by 4 + if(i > VTK_MAX_SUPERQUADRIC_RESOLUTION) + { + i = VTK_MAX_SUPERQUADRIC_RESOLUTION; + } + + if (this->PhiResolution != i) + { + this->PhiResolution = i; + this->Modified (); + } +} + +void vtkSuperquadricSource::SetThetaResolution(int i) +{ + if(i < 8) + { + i = 8; + } + i = (i+7)/8*8; // make it divisible by 8 + if(i > VTK_MAX_SUPERQUADRIC_RESOLUTION) + { + i = VTK_MAX_SUPERQUADRIC_RESOLUTION; + } + + if (this->ThetaResolution != i) + { + this->ThetaResolution = i; + this->Modified (); + } +} + +void vtkSuperquadricSource::SetThetaRoundness(double e) +{ + if(e < VTK_MIN_SUPERQUADRIC_ROUNDNESS) + { + e = VTK_MIN_SUPERQUADRIC_ROUNDNESS; + } + + if (this->ThetaRoundness != e) + { + this->ThetaRoundness = e; + this->Modified(); + } +} + +void vtkSuperquadricSource::SetPhiRoundness(double e) +{ + if(e < VTK_MIN_SUPERQUADRIC_ROUNDNESS) + { + e = VTK_MIN_SUPERQUADRIC_ROUNDNESS; + } + + if (this->PhiRoundness != e) + { + this->PhiRoundness = e; + this->Modified(); + } +} + +static const double SQ_SMALL_OFFSET = 0.01; + +int vtkSuperquadricSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int i, j; + vtkIdType numPts; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkFloatArray *newTCoords; + vtkCellArray *newPolys; + vtkIdType *ptidx; + double pt[3], nv[3], dims[3]; + double len; + double alpha; + double deltaPhi, deltaTheta, phi, theta; + double phiLim[2], thetaLim[2]; + double deltaPhiTex, deltaThetaTex; + int base, pbase; + vtkIdType numStrips; + int ptsPerStrip; + int phiSubsegs, thetaSubsegs, phiSegs, thetaSegs; + int iq, jq, rowOffset; + double thetaOffset, phiOffset; + double texCoord[2]; + + dims[0] = this->Scale[0] * this->Size; + dims[1] = this->Scale[1] * this->Size; + dims[2] = this->Scale[2] * this->Size; + + if(this->Toroidal) + { + phiLim[0] = -vtkMath::Pi(); + phiLim[1] = vtkMath::Pi(); + + thetaLim[0] = -vtkMath::Pi(); + thetaLim[1] = vtkMath::Pi(); + + alpha = (1.0 / this->Thickness); + dims[0] /= (alpha + 1.0); + dims[1] /= (alpha + 1.0); + dims[2] /= (alpha + 1.0); + } + else + { + //Ellipsoidal + phiLim[0] = -vtkMath::Pi() / 2.0; + phiLim[1] = vtkMath::Pi() / 2.0; + + thetaLim[0] = -vtkMath::Pi(); + thetaLim[1] = vtkMath::Pi(); + + alpha = 0.0; + } + + deltaPhi = (phiLim[1] - phiLim[0]) / this->PhiResolution; + deltaPhiTex = 1.0 / this->PhiResolution; + deltaTheta = (thetaLim[1] - thetaLim[0]) / this->ThetaResolution; + deltaThetaTex = 1.0 / this->ThetaResolution; + + phiSegs = 4; + thetaSegs = 8; + + phiSubsegs = this->PhiResolution / phiSegs; + thetaSubsegs = this->ThetaResolution / thetaSegs; + + numPts = (this->PhiResolution + phiSegs)*(this->ThetaResolution + thetaSegs); + // creating triangles + numStrips = this->PhiResolution * thetaSegs; + ptsPerStrip = thetaSubsegs*2 + 2; + + // + // Set things up; allocate memory + // + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + newNormals->SetName("Normals"); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*numPts); + newTCoords->SetName("TextureCoords"); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numStrips,ptsPerStrip)); + + // generate! + for(iq = 0; iq < phiSegs; iq++) + { + for(i = 0; i <= phiSubsegs; i++) + { + phi = phiLim[0] + deltaPhi*(i + iq*phiSubsegs); + texCoord[1] = deltaPhiTex*(i + iq*phiSubsegs); + + // SQ_SMALL_OFFSET makes sure that the normal vector isn't + // evaluated exactly on a crease; if that were to happen, + // large shading errors can occur. + if(i == 0) + { + phiOffset = SQ_SMALL_OFFSET*deltaPhi; + } + else if (i == phiSubsegs) + { + phiOffset = -SQ_SMALL_OFFSET*deltaPhi; + } + else + { + phiOffset = 0.0; + } + + for(jq = 0; jq < thetaSegs; jq++) + { + for(j = 0; j <= thetaSubsegs; j++) + { + theta = thetaLim[0] + deltaTheta*(j + jq*thetaSubsegs); + texCoord[0] = deltaThetaTex*(j + jq*thetaSubsegs); + + if(j == 0) + { + thetaOffset = SQ_SMALL_OFFSET*deltaTheta; + } + else if (j == thetaSubsegs) + { + thetaOffset = -SQ_SMALL_OFFSET*deltaTheta; + } + else + { + thetaOffset = 0.0; + } + + evalSuperquadric(theta, phi, + thetaOffset, phiOffset, + this->PhiRoundness, this->ThetaRoundness, + dims, alpha, pt, nv); + + if((len = vtkMath::Norm(nv)) == 0.0) + { + len = 1.0; + } + nv[0] /= len; nv[1] /= len; nv[2] /= len; + + if(!this->Toroidal && + ((iq == 0 && i == 0) || (iq == (phiSegs-1) && i == phiSubsegs))) { + + // we're at a pole: + // make sure the pole is at the same location for all evals + // (the superquadric evaluation is numerically unstable + // at the poles) + + pt[0] = pt[2] = 0.0; + } + + pt[0] += this->Center[0]; + pt[1] += this->Center[1]; + pt[2] += this->Center[2]; + + newPoints->InsertNextPoint(pt); + newNormals->InsertNextTuple(nv); + newTCoords->InsertNextTuple(texCoord); + } + } + } + } + + // mesh! + // build triangle strips for efficiency.... + ptidx = new vtkIdType[ptsPerStrip]; + + rowOffset = this->ThetaResolution+thetaSegs; + + for(iq = 0; iq < phiSegs; iq++) + { + for(i = 0; i < phiSubsegs; i++) + { + pbase = rowOffset*(i +iq*(phiSubsegs+1)); + for(jq = 0; jq < thetaSegs; jq++) + { + base = pbase + jq*(thetaSubsegs+1); + for(j = 0; j <= thetaSubsegs; j++) + { + ptidx[2*j] = base + rowOffset + j; + ptidx[2*j+1] = base + j; + } + newPolys->InsertNextCell(ptsPerStrip, ptidx); + } + } + } + delete[] ptidx; + + output->SetPoints(newPoints); + newPoints->Delete(); + + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + output->SetStrips(newPolys); + newPolys->Delete(); + + return 1; +} + +void vtkSuperquadricSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Toroidal: " << (this->Toroidal ? "On\n" : "Off\n"); + os << indent << "Size: " << this->Size << "\n"; + os << indent << "Thickness: " << this->Thickness << "\n"; + os << indent << "Theta Resolution: " << this->ThetaResolution << "\n"; + os << indent << "Theta Roundness: " << this->ThetaRoundness << "\n"; + os << indent << "Phi Resolution: " << this->PhiResolution << "\n"; + os << indent << "Phi Roundness: " << this->PhiRoundness << "\n"; + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << ")\n"; + os << indent << "Scale: (" << this->Scale[0] << ", " + << this->Scale[1] << ", " << this->Scale[2] << ")\n"; +} + +static double cf(double w, double m, double a) +{ + double c; + double sgn; + + c = cos(w); + sgn = c < 0.0 ? -1.0 : 1.0; + return a + sgn*pow(sgn*c, m); +} + +static double sf(double w, double m) +{ + double s; + double sgn; + + s = sin(w); + sgn = s < 0.0 ? -1.0 : 1.0; + return sgn*pow(sgn*s, m); +} + +static void evalSuperquadric(double u, double v, // parametric coords + double du, double dv, // offsets for normals + double n, double e, // roundness params + double dims[3], // x, y, z dimensions + double alpha, // hole size + double xyz[3], // output coords + double nrm[3]) // output normals + +{ + double cf1, cf2; + + cf1 = cf(v, n, alpha); + xyz[0] = dims[0] * cf1 * sf(u, e); + xyz[1] = dims[1] * sf(v, n); + xyz[2] = dims[2] * cf1 * cf(u, e, 0.0); + + cf2 = cf(v+dv, 2.0-n, 0.0); + nrm[0] = 1.0/dims[0] * cf2 * sf(u+du, 2.0-e); + nrm[1] = 1.0/dims[1] * sf(v+dv, 2.0-n); + nrm[2] = 1.0/dims[2] * cf2 * cf(u+du, 2.0-e, 0.0); +} diff --git a/Graphics/vtkSuperquadricSource.h b/Graphics/vtkSuperquadricSource.h new file mode 100644 index 0000000..3cf3a50 --- /dev/null +++ b/Graphics/vtkSuperquadricSource.h @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSuperquadricSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSuperquadricSource - create a polygonal superquadric centered +// at the origin +// .SECTION Description +// vtkSuperquadricSource creates a superquadric (represented by polygons) +// of specified +// size centered at the origin. The resolution (polygonal discretization) +// in both the latitude (phi) and longitude (theta) directions can be +// specified. Roundness parameters (PhiRoundness and ThetaRoundness) control +// the shape of the superquadric. The Toroidal boolean controls whether +// a toroidal superquadric is produced. If so, the Thickness parameter +// controls the thickness of the toroid: 0 is the thinnest allowable +// toroid, and 1 has a minimum sized hole. The Scale parameters allow +// the superquadric to be scaled in x, y, and z (normal vectors are correctly +// generated in any case). The Size parameter controls size of the +// superquadric. +// +// This code is based on "Rigid physically based superquadrics", A. H. Barr, +// in "Graphics Gems III", David Kirk, ed., Academic Press, 1992. +// +// .SECTION Caveats +// Resolution means the number of latitude or longitude lines for a complete +// superquadric. The resolution parameters are rounded to the nearest 4 +// in phi and 8 in theta. +// +// Texture coordinates are not equally distributed around all superquadrics. +// +// The Size and Thickness parameters control coefficients of superquadric +// generation, and may do not exactly describe the size of the superquadric. +// + +#ifndef __vtkSuperquadricSource_h +#define __vtkSuperquadricSource_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_MAX_SUPERQUADRIC_RESOLUTION 1024 +#define VTK_MIN_SUPERQUADRIC_THICKNESS 1e-4 +#define VTK_MIN_SUPERQUADRIC_ROUNDNESS 1e-24 + +class VTK_GRAPHICS_EXPORT vtkSuperquadricSource : public vtkPolyDataAlgorithm +{ +public: + // Description: + // Create a default superquadric with a radius of 0.5, non-toroidal, + // spherical, and centered at the origin. + static vtkSuperquadricSource *New(); + + vtkTypeRevisionMacro(vtkSuperquadricSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the center of the superquadric. Default is 0,0,0. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Set the scale factors of the superquadric. Default is 1,1,1. + vtkSetVector3Macro(Scale,double); + vtkGetVectorMacro(Scale,double,3); + + // Description: + // Set the number of points in the longitude direction. + vtkGetMacro(ThetaResolution,int); + void SetThetaResolution(int i); + + // Description: + // Set the number of points in the latitude direction. + vtkGetMacro(PhiResolution,int); + void SetPhiResolution(int i); + + // Description: + // Set/Get Superquadric ring thickness (toroids only). + // Changing thickness maintains the outside diameter of the toroid. + vtkGetMacro(Thickness,double); + vtkSetClampMacro(Thickness,double,VTK_MIN_SUPERQUADRIC_THICKNESS,1.0); + + // Description: + // Set/Get Superquadric north/south roundness. + // Values range from 0 (rectangular) to 1 (circular) to higher orders. + vtkGetMacro(PhiRoundness,double); + void SetPhiRoundness(double e); + + // Description: + // Set/Get Superquadric east/west roundness. + // Values range from 0 (rectangular) to 1 (circular) to higher orders. + vtkGetMacro(ThetaRoundness,double); + void SetThetaRoundness(double e); + + // Description: + // Set/Get Superquadric isotropic size. + vtkSetMacro(Size,double); + vtkGetMacro(Size,double); + + // Description: + // Set/Get whether or not the superquadric is toroidal (1) or ellipsoidal (0). + vtkBooleanMacro(Toroidal,int); + vtkGetMacro(Toroidal,int); + vtkSetMacro(Toroidal,int); + +protected: + vtkSuperquadricSource(int res=16); + ~vtkSuperquadricSource() {}; + + int Toroidal; + double Thickness; + double Size; + double PhiRoundness; + double ThetaRoundness; + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double Center[3]; + double Scale[3]; + int ThetaResolution; + int PhiResolution; + +private: + vtkSuperquadricSource(const vtkSuperquadricSource&); // Not implemented. + void operator=(const vtkSuperquadricSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkSynchronizedTemplates2D.cxx b/Graphics/vtkSynchronizedTemplates2D.cxx new file mode 100644 index 0000000..8d99544 --- /dev/null +++ b/Graphics/vtkSynchronizedTemplates2D.cxx @@ -0,0 +1,536 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSynchronizedTemplates2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSynchronizedTemplates2D.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include + +vtkCxxRevisionMacro(vtkSynchronizedTemplates2D, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkSynchronizedTemplates2D); + +//---------------------------------------------------------------------------- +// Description: +// Construct object with initial scalar range (0,1) and single contour value +// of 0.0. The ImageRange are set to extract the first k-plane. +vtkSynchronizedTemplates2D::vtkSynchronizedTemplates2D() +{ + this->ContourValues = vtkContourValues::New(); + this->ComputeScalars = 1; + this->ArrayComponent = 0; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +vtkSynchronizedTemplates2D::~vtkSynchronizedTemplates2D() +{ + this->ContourValues->Delete(); +} + +//---------------------------------------------------------------------------- +// Description: +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkSynchronizedTemplates2D::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long mTime2=this->ContourValues->GetMTime(); + + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + return mTime; +} + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images +// +template +void vtkContourImage(vtkSynchronizedTemplates2D *self, + T *scalars, vtkPoints *newPts, + vtkDataArray *newScalars, vtkCellArray *lines, + vtkImageData *input, int *updateExt) +{ + double *values = self->GetValues(); + int numContours = self->GetNumberOfContours(); + T *inPtr, *rowPtr; + double x[3]; + double *origin = input->GetOrigin(); + double *spacing = input->GetSpacing(); + double y, t; + int *isect1Ptr, *isect2Ptr; + vtkIdType ptIds[2]; + int *tablePtr; + int v0, v1 = 0, v2; + int idx, vidx; + double s0, s1, s2, value; + int i, j; + int lineCases[64]; + + // The update extent may be different than the extent of the image. + // The only problem with using the update extent is that one or two + // sources enlarge the update extent. This behavior is slated to be + // eliminated. + vtkIdType *incs = input->GetIncrements(); + int *ext = input->GetExtent(); + int axis0, axis1; + int min0, max0, dim0; + int min1, max1; + int inc0, inc1; + + // Figure out which plane the image lies in. + if (updateExt[4] == updateExt[5]) + { // z collapsed + axis0 = 0; + min0 = updateExt[0]; + max0 = updateExt[1]; + inc0 = incs[0]; + axis1 = 1; + min1 = updateExt[2]; + max1 = updateExt[3]; + inc1 = incs[1]; + x[2] = origin[2] + (updateExt[4]*spacing[2]); + } + else if (updateExt[2] == updateExt[3]) + { // y collapsed + axis0 = 0; + min0 = updateExt[0]; + max0 = updateExt[1]; + inc0 = incs[0]; + axis1 = 2; + min1 = updateExt[4]; + max1 = updateExt[5]; + inc1 = incs[2]; + x[1] = origin[1] + (updateExt[2]*spacing[1]); + } + else if (updateExt[0] == updateExt[1]) + { // x collapsed + axis0 = 1; + min0 = updateExt[2]; + max0 = updateExt[3]; + inc0 = incs[1]; + axis1 = 2; + min1 = updateExt[4]; + max1 = updateExt[5]; + inc1 = incs[2]; + x[0] = origin[0] + (updateExt[0]*spacing[0]); + } + else + { + vtkGenericWarningMacro("Expecting 2D data."); + return; + } + dim0 = max0-min0+1; + + + // setup the table entries + for (i = 0; i < 64; i++) + { + lineCases[i] = -1; + } + + lineCases[12] = 3; + lineCases[13] = dim0*2; + + lineCases[20] = 1; + lineCases[21] = dim0*2; + + lineCases[24] = 1; + lineCases[25] = 3; + + lineCases[36] = 0; + lineCases[37] = dim0*2; + + lineCases[40] = 0; + lineCases[41] = 3; + + lineCases[48] = 0; + lineCases[49] = 1; + + lineCases[60] = 0; + lineCases[61] = 1; + lineCases[62] = 3; + lineCases[63] = dim0*2; + + // allocate storage arrays + int *isect1 = new int [dim0*4]; + isect1[dim0*2-2] = -1; + isect1[dim0*2-1] = -1; + isect1[dim0*4-2] = -1; + isect1[dim0*4-1] = -1; + + + // Compute the staring location. We may be operating + // on a part of the image. + scalars += incs[0]*(updateExt[0]-ext[0]) + + incs[1]*(updateExt[2]-ext[2]) + + incs[2]*(updateExt[4]-ext[4]) + self->GetArrayComponent(); + + // for each contour + for (vidx = 0; vidx < numContours; vidx++) + { + rowPtr = scalars; + inPtr = rowPtr; + + lineCases[13] = dim0*2; + lineCases[21] = dim0*2; + lineCases[37] = dim0*2; + lineCases[63] = dim0*2; + + value = values[vidx]; + + // Traverse all pixel cells, generating line segements using templates + for (j = min1; j <= max1; j++) + { + inPtr = rowPtr; + rowPtr += inc1; + + // set the y coordinate + y = origin[axis1] + j*spacing[axis1]; + // first compute the intersections + s1 = *inPtr; + + // swap the buffers + if (j%2) + { + lineCases[13] = dim0*2; + lineCases[21] = dim0*2; + lineCases[37] = dim0*2; + lineCases[63] = dim0*2; + isect1Ptr = isect1; + isect2Ptr = isect1 + dim0*2; + } + else + { + lineCases[13] = -dim0*2; + lineCases[21] = -dim0*2; + lineCases[37] = -dim0*2; + lineCases[63] = -dim0*2; + isect1Ptr = isect1 + dim0*2; + isect2Ptr = isect1; + } + + for (i = min0; i < max0; i++) + { + s0 = s1; + s1 = *(inPtr + inc0); + // compute in/out for verts + v0 = (s0 < value ? 0 : 1); + v1 = (s1 < value ? 0 : 1); + // if we have an intersection + *isect2Ptr = -1; + *(isect2Ptr + 1) = -1; + if (v0 ^ v1) + { + // watch for degenerate points + if (s0 == value) + { + if (i > min0 && *(isect2Ptr-2) > -1) + { + *isect2Ptr = *(isect2Ptr-2); + } + else if (j > min1 && *(isect1Ptr+1) > -1) + { + *isect2Ptr = *(isect1Ptr+1); + } + } + else if (s1 == value && j > min1 && *(isect1Ptr+3) > -1) + { + *isect2Ptr = *(isect1Ptr+3); + } + // if the edge has not been set yet then it is a new point + if (*isect2Ptr == -1) + { + t = (value - s0) / (s1 - s0); + x[axis0] = origin[axis0] + spacing[axis0]*(i+t); + x[axis1] = y; + *isect2Ptr = newPts->InsertNextPoint(x); + if (newScalars) + { + newScalars->InsertNextTuple(&value); + } + } + } + if (j < max1) + { + s2 = *(inPtr + inc1); + v2 = (s2 < value ? 0 : 1); + if (v0 ^ v2) + { + if (s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 1) = *isect2Ptr; + } + else if (j > min1 && *(isect1Ptr+1) > -1) + { + *(isect2Ptr + 1) = *(isect1Ptr+1); + } + else if (i > min0 && *(isect2Ptr-2) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr-2); + } + } + // if the edge has not been set yet then it is a new point + if (*(isect2Ptr + 1) == -1) + { + t = (value - s0) / (s2 - s0); + x[axis0] = origin[axis0] + spacing[axis0]*i; + x[axis1] = y + spacing[axis1]*t; + *(isect2Ptr + 1) = newPts->InsertNextPoint(x); + if (newScalars) + { + newScalars->InsertNextTuple(&value); + } + } + } + } + + if (j > min1) + { + // now add any lines that need to be added + // basically look at the isect values, + // form an index and lookup the lines + idx = (*isect1Ptr > -1 ? 8 : 0); + idx = idx + (*(isect1Ptr +1) > -1 ? 4 : 0); + idx = idx + (*(isect1Ptr +3) > -1 ? 2 : 0); + idx = idx + (*isect2Ptr > -1 ? 1 : 0); + tablePtr = lineCases + idx*4; + + if (*tablePtr != -1) + { + ptIds[0] = *(isect1Ptr + *tablePtr); + tablePtr++; + ptIds[1] = *(isect1Ptr + *tablePtr); + if (ptIds[0] != ptIds[1]) + { + // insert non-degenerate lines + lines->InsertNextCell(2,ptIds); + } + tablePtr++; + if (*tablePtr != -1) + { + ptIds[0] = *(isect1Ptr + *tablePtr); + tablePtr++; + ptIds[1] = *(isect1Ptr + *tablePtr); + if (ptIds[0] != ptIds[1]) + { + lines->InsertNextCell(2,ptIds); + } + } + } + } + inPtr += inc0; + isect2Ptr += 2; + isect1Ptr += 2; + } + // now compute the last column, use s2 since it is around + if (j < max1) + { + s2 = *(inPtr + dim0); + v2 = (s2 < value ? 0 : 1); + *(isect2Ptr + 1) = -1; + if (v1 ^ v2) + { + if (s1 == value && *(isect2Ptr-2) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr-2); + } + else if (s1 == value && *(isect1Ptr+1) > -1) + { + *(isect2Ptr + 1) = *(isect1Ptr+1); + } + else + { + t = (value - s1) / (s2 - s1); + x[axis0] = origin[axis0] + spacing[axis0]*max0; + x[axis1] = y + spacing[axis1]*t; + *(isect2Ptr + 1) = newPts->InsertNextPoint(x); + if (newScalars) + { + newScalars->InsertNextTuple(&value); + } + } + } + } + } + } + + delete [] isect1; +} + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images (or slices from images) +// +int vtkSynchronizedTemplates2D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *newPts; + vtkCellArray *newLines; + vtkDataArray *inScalars; + vtkDataArray *newScalars = NULL; + int *ext; + int dims[3]; + int dataSize, estimatedSize; + + + vtkDebugMacro(<< "Executing 2D structured contour"); + + ext = + inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + inScalars = this->GetInputArrayToProcess(0,inputVector); + if ( inScalars == NULL ) + { + vtkErrorMacro(<<"Scalars must be defined for contouring"); + return 1; + } + + int numComps = inScalars->GetNumberOfComponents(); + if (this->ArrayComponent >= numComps) + { + vtkErrorMacro("Scalars have " << numComps << " components. " + "ArrayComponent must be smaller than " << numComps); + return 1; + } + + // We have to compute the dimenisons from the update extent because + // the extent may be larger. + dims[0] = ext[1]-ext[0]+1; + dims[1] = ext[3]-ext[2]+1; + dims[2] = ext[5]-ext[4]+1; + + // + // Check dimensionality of data and get appropriate form + // + dataSize = dims[0] * dims[1] * dims[2]; + + // + // Allocate necessary objects + // + estimatedSize = (int) (sqrt((double)(dataSize))); + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(estimatedSize,2)); + + // + // Check data type and execute appropriate function + // + + void *scalars = inScalars->GetVoidPointer(0); + if (this->ComputeScalars) + { + newScalars = inScalars->NewInstance(); + newScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents()); + newScalars->SetName(inScalars->GetName()); + newScalars->Allocate(5000,25000); + } + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + vtkContourImage(this,(VTK_TT *)scalars, newPts, + newScalars, newLines, input, ext)); + }//switch + + // Lets set the name of the scalars here. + if (newScalars) + { + newScalars->SetName(inScalars->GetName()); + } + + vtkDebugMacro(<<"Created: " + << newPts->GetNumberOfPoints() << " points, " + << newLines->GetNumberOfCells() << " lines"); + // + // Update ourselves. Because we don't know up front how many lines + // we've created, take care to reclaim memory. + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + if (newScalars) + { + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + output->Squeeze(); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSynchronizedTemplates2D::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkSynchronizedTemplates2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + if (this->ComputeScalars) + { + os << indent << "ComputeScalarsOn\n"; + } + else + { + os << indent << "ComputeScalarsOff\n"; + } + os << indent << "ArrayComponent: " << this->ArrayComponent << endl; +} diff --git a/Graphics/vtkSynchronizedTemplates2D.h b/Graphics/vtkSynchronizedTemplates2D.h new file mode 100644 index 0000000..e35beba --- /dev/null +++ b/Graphics/vtkSynchronizedTemplates2D.h @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSynchronizedTemplates2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSynchronizedTemplates2D - generate isoline(s) from a structured points set +// .SECTION Description +// vtkSynchronizedTemplates2D is a 2D implementation of the synchronized +// template algorithm. Note that vtkContourFilter will automatically +// use this class when appropriate. + +// .SECTION Caveats +// This filter is specialized to 2D images. + +// .SECTION See Also +// vtkContourFilter vtkSynchronizedTemplates3D + +#ifndef __vtkSynchronizedTemplates2D_h +#define __vtkSynchronizedTemplates2D_h + +#include "vtkPolyDataAlgorithm.h" + +#include "vtkContourValues.h" // Needed for direct access to ContourValues + +class vtkImageData; + +class VTK_GRAPHICS_EXPORT vtkSynchronizedTemplates2D : public vtkPolyDataAlgorithm +{ +public: + static vtkSynchronizedTemplates2D *New(); + vtkTypeRevisionMacro(vtkSynchronizedTemplates2D,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Because we delegate to vtkContourValues + unsigned long int GetMTime(); + + // Description: + // Set a particular contour value at contour number i. The index i ranges + // between 0<=iContourValues->SetValue(i,value);} + + // Description: + // Get the ith contour value. + double GetValue(int i) {return this->ContourValues->GetValue(i);} + + // Description: + // Get a pointer to an array of contour values. There will be + // GetNumberOfContours() values in the list. + double *GetValues() {return this->ContourValues->GetValues();} + + // Description: + // Fill a supplied list with contour values. There will be + // GetNumberOfContours() values in the list. Make sure you allocate + // enough memory to hold the list. + void GetValues(double *contourValues) { + this->ContourValues->GetValues(contourValues);} + + // Description: + // Set the number of contours to place into the list. You only really + // need to use this method to reduce list size. The method SetValue() + // will automatically increase list size as needed. + void SetNumberOfContours(int number) { + this->ContourValues->SetNumberOfContours(number);} + + // Description: + // Get the number of contours in the list of contour values. + int GetNumberOfContours() { + return this->ContourValues->GetNumberOfContours();} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double range[2]) { + this->ContourValues->GenerateValues(numContours, range);} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double rangeStart, double rangeEnd) + {this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + // Description: + // Option to set the point scalars of the output. The scalars will be the + // iso value of course. By default this flag is on. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Set/get which component of the scalar array to contour on; defaults to 0. + vtkSetMacro(ArrayComponent, int); + vtkGetMacro(ArrayComponent, int); + +protected: + vtkSynchronizedTemplates2D(); + ~vtkSynchronizedTemplates2D(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + vtkContourValues *ContourValues; + + int ComputeScalars; + int ArrayComponent; + +private: + vtkSynchronizedTemplates2D(const vtkSynchronizedTemplates2D&); // Not implemented. + void operator=(const vtkSynchronizedTemplates2D&); // Not implemented. +}; + + +#endif + diff --git a/Graphics/vtkSynchronizedTemplates3D.cxx b/Graphics/vtkSynchronizedTemplates3D.cxx new file mode 100644 index 0000000..e747038 --- /dev/null +++ b/Graphics/vtkSynchronizedTemplates3D.cxx @@ -0,0 +1,1912 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSynchronizedTemplates3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSynchronizedTemplates3D.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkExtentTranslator.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredPoints.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include + +vtkCxxRevisionMacro(vtkSynchronizedTemplates3D, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkSynchronizedTemplates3D); + +//---------------------------------------------------------------------------- +// Description: +// Construct object with initial scalar range (0,1) and single contour value +// of 0.0. The ImageRange are set to extract the first k-plane. +vtkSynchronizedTemplates3D::vtkSynchronizedTemplates3D() +{ + this->ContourValues = vtkContourValues::New(); + this->ComputeNormals = 1; + this->ComputeGradients = 0; + this->ComputeScalars = 1; + + this->ExecuteExtent[0] = this->ExecuteExtent[1] + = this->ExecuteExtent[2] = this->ExecuteExtent[3] + = this->ExecuteExtent[4] = this->ExecuteExtent[5] = 0; + + this->ArrayComponent = 0; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +//---------------------------------------------------------------------------- +vtkSynchronizedTemplates3D::~vtkSynchronizedTemplates3D() +{ + this->ContourValues->Delete(); +} + +//---------------------------------------------------------------------------- +// Overload standard modified time function. If contour values are modified, +// then this object is modified as well. +unsigned long vtkSynchronizedTemplates3D::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long mTime2=this->ContourValues->GetMTime(); + + mTime = ( mTime2 > mTime ? mTime2 : mTime ); + return mTime; +} + + +//---------------------------------------------------------------------------- +void vtkSynchronizedTemplates3DInitializeOutput( + int *ext,vtkImageData *input, + vtkPolyData *o, vtkFloatArray *scalars, vtkFloatArray *normals, + vtkFloatArray *gradients, vtkDataArray *inScalars) +{ + vtkPoints *newPts; + vtkCellArray *newPolys; + long estimatedSize; + + estimatedSize = (int) pow ((double) + ((ext[1]-ext[0]+1)*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1)), .75); + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(estimatedSize,3)); + + o->GetPointData()->CopyAllOn(); + // It is more efficient to just create the scalar array + // rather than redundantly interpolate the scalars. + if (input->GetPointData()->GetScalars() == inScalars) + { + o->GetPointData()->CopyScalarsOff(); + } + else + { + o->GetPointData()->CopyFieldOff(inScalars->GetName()); + } + + if (normals) + { + normals->SetNumberOfComponents(3); + normals->Allocate(3*estimatedSize,3*estimatedSize/2); + normals->SetName("Normals"); + } + if (gradients) + { + gradients->SetNumberOfComponents(3); + gradients->Allocate(3*estimatedSize,3*estimatedSize/2); + gradients->SetName("Gradients"); + } + if (scalars) + { + // A temporary name. + scalars->SetName("Scalars"); + } + + o->GetPointData()->InterpolateAllocate(input->GetPointData(), + estimatedSize,estimatedSize/2); + o->GetCellData()->CopyAllocate(input->GetCellData(), + estimatedSize,estimatedSize/2); + + o->SetPoints(newPts); + newPts->Delete(); + + o->SetPolys(newPolys); + newPolys->Delete(); + +} + + +//---------------------------------------------------------------------------- +// Calculate the gradient using central difference. +template +void vtkSTComputePointGradient(int i, int j, int k, T *s, int *wholeExt, + int xInc, int yInc, int zInc, + double *spacing, double n[3]) +{ + double sp, sm; + + // x-direction + if ( i == wholeExt[0] ) + { + sp = *(s+xInc); + sm = *s; + n[0] = (sp - sm) / spacing[0]; + } + else if ( i == wholeExt[1] ) + { + sp = *s; + sm = *(s-xInc); + n[0] = (sp - sm) / spacing[0]; + } + else + { + sp = *(s+xInc); + sm = *(s-xInc); + n[0] = 0.5 * (sp - sm) / spacing[0]; + } + + // y-direction + if ( j == wholeExt[2] ) + { + sp = *(s+yInc); + sm = *s; + n[1] = (sp - sm) / spacing[1]; + } + else if ( j == wholeExt[3] ) + { + sp = *s; + sm = *(s-yInc); + n[1] = (sp - sm) / spacing[1]; + } + else + { + sp = *(s+yInc); + sm = *(s-yInc); + n[1] = 0.5 * (sp - sm) / spacing[1]; + } + + // z-direction + if ( k == wholeExt[4] ) + { + sp = *(s+zInc); + sm = *s; + n[2] = (sp - sm) / spacing[2]; + } + else if ( k == wholeExt[5] ) + { + sp = *s; + sm = *(s-zInc); + n[2] = (sp - sm) / spacing[2]; + } + else + { + sp = *(s+zInc); + sm = *(s-zInc); + n[2] = 0.5 * (sp - sm) / spacing[2]; + } +} + +//---------------------------------------------------------------------------- +#define VTK_CSP3PA(i2,j2,k2,s) \ +if (NeedGradients) \ +{ \ + if (!g0) \ + { \ + vtkSTComputePointGradient(i, j, k, s0, wholeExt, xInc, yInc, zInc, spacing, n0); \ + g0 = 1; \ + } \ + vtkSTComputePointGradient(i2, j2, k2, s, wholeExt, xInc, yInc, zInc, spacing, n1); \ + for (jj=0; jj<3; jj++) \ + { \ + n[jj] = n0[jj] + t * (n1[jj] - n0[jj]); \ + } \ + if (ComputeGradients) \ + { \ + newGradients->InsertNextTuple(n); \ + } \ + if (ComputeNormals) \ + { \ + vtkMath::Normalize(n); \ + n[0] = -n[0]; n[1] = -n[1]; n[2] = -n[2]; \ + newNormals->InsertNextTuple(n); \ + } \ +} \ +if (ComputeScalars) \ +{ \ + newScalars->InsertNextTuple(&value); \ +} + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images +// +template +void ContourImage(vtkSynchronizedTemplates3D *self, int *exExt, + vtkInformation *inInfo, + vtkImageData *data, vtkPolyData *output, T *ptr, + vtkDataArray *inScalars) +{ + int *inExt = data->GetExtent(); + int xdim = exExt[1] - exExt[0] + 1; + int ydim = exExt[3] - exExt[2] + 1; + double *values = self->GetValues(); + int numContours = self->GetNumberOfContours(); + T *inPtrX, *inPtrY, *inPtrZ; + T *s0, *s1, *s2, *s3; + int xMin, xMax, yMin, yMax, zMin, zMax; + int xInc, yInc, zInc; + double *origin = data->GetOrigin(); + double *spacing = data->GetSpacing(); + int *isect1Ptr, *isect2Ptr; + double y, z, t; + int i, j, k; + int zstep, yisectstep; + int offsets[12]; + int ComputeNormals = self->GetComputeNormals(); + int ComputeGradients = self->GetComputeGradients(); + int ComputeScalars = self->GetComputeScalars(); + int NeedGradients = ComputeGradients || ComputeNormals; + double n[3], n0[3], n1[3]; + int jj, g0; + int *tablePtr; + int idx, vidx; + double x[3], xz[3]; + int v0, v1, v2, v3; + vtkIdType ptIds[3]; + double value; + int *wholeExt; + // We need to know the edgePointId's for interpolating attributes. + int edgePtId, inCellId, outCellId; + vtkPointData *inPD = data->GetPointData(); + vtkCellData *inCD = data->GetCellData(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *outCD = output->GetCellData(); + // Use to be arguments + vtkFloatArray *newScalars = NULL; + vtkFloatArray *newNormals = NULL; + vtkFloatArray *newGradients = NULL; + vtkPoints *newPts; + vtkCellArray *newPolys; + ptr += self->GetArrayComponent(); + + if (ComputeScalars) + { + newScalars = vtkFloatArray::New(); + } + if (ComputeNormals) + { + newNormals = vtkFloatArray::New(); + } + if (ComputeGradients) + { + newGradients = vtkFloatArray::New(); + } + vtkSynchronizedTemplates3DInitializeOutput(exExt, + data, output, + newScalars, newNormals, + newGradients, inScalars); + newPts = output->GetPoints(); + newPolys = output->GetPolys(); + + // this is an exploded execute extent. + xMin = exExt[0]; + xMax = exExt[1]; + yMin = exExt[2]; + yMax = exExt[3]; + zMin = exExt[4]; + zMax = exExt[5]; + + // increments to move through scalars. Compute these ourself because + // we may be contouring an array other than scalars. + xInc = inScalars->GetNumberOfComponents(); + yInc = xInc*(inExt[1]-inExt[0]+1); + zInc = yInc*(inExt[3]-inExt[2]+1); + + wholeExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + // Kens increments, probably to do with edge array + zstep = xdim*ydim; + yisectstep = xdim*3; + // compute offsets probably how to get to the edges in the edge array. + offsets[0] = -xdim*3; + offsets[1] = -xdim*3 + 1; + offsets[2] = -xdim*3 + 2; + offsets[3] = -xdim*3 + 4; + offsets[4] = -xdim*3 + 5; + offsets[5] = 0; + offsets[6] = 2; + offsets[7] = 5; + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + + // allocate storage array + int *isect1 = new int [xdim*ydim*3*2]; + // set impossible edges to -1 + for (i = 0; i < ydim; i++) + { + isect1[(i+1)*xdim*3-3] = -1; + isect1[(i+1)*xdim*3*2-3] = -1; + } + for (i = 0; i < xdim; i++) + { + isect1[((ydim-1)*xdim + i)*3 + 1] = -1; + isect1[((ydim-1)*xdim + i)*3*2 + 1] = -1; + } + + // for each contour + for (vidx = 0; vidx < numContours; vidx++) + { + value = values[vidx]; + inPtrZ = ptr; + + //================================================================== + for (k = zMin; k <= zMax; k++) + { + self->UpdateProgress((double)vidx/numContours + + (k-zMin)/((zMax - zMin+1.0)*numContours)); + z = origin[2] + spacing[2]*k; + x[2] = z; + + // swap the buffers + if (k%2) + { + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + isect1Ptr = isect1; + isect2Ptr = isect1 + xdim*ydim*3; + } + else + { + offsets[8] = (-zstep - xdim)*3; + offsets[9] = (-zstep - xdim)*3 + 1; + offsets[10] = (-zstep - xdim)*3 + 4; + offsets[11] = -zstep*3; + isect1Ptr = isect1 + xdim*ydim*3; + isect2Ptr = isect1; + } + + inPtrY = inPtrZ; + for (j = yMin; j <= yMax; j++) + { + // Should not impact perfomance here/ + edgePtId = (j-inExt[2])*yInc + (k-inExt[4])*zInc; + // Increments are different for cells. Since the cells are not + // contoured until the second row of templates, subtract 1 from + // i,j,and k. Note: first cube is formed when i=0, j=1, and k=1. + inCellId = + (xMin-inExt[0]) + (inExt[1]-inExt[0])* + ( (j-inExt[2]-1) + (k-inExt[4]-1)*(inExt[3]-inExt[2]) ); + + y = origin[1] + j*spacing[1]; + xz[1] = y; + s1 = inPtrY; + v1 = (*s1 < value ? 0 : 1); + + inPtrX = inPtrY; + for (i = xMin; i <= xMax; i++) + { + s0 = s1; + v0 = v1; + // this flag keeps up from computing gradient for grid point 0 twice. + g0 = 0; + *isect2Ptr = -1; + *(isect2Ptr + 1) = -1; + *(isect2Ptr + 2) = -1; + if (i < xMax) + { + s1 = (inPtrX + xInc); + v1 = (*s1 < value ? 0 : 1); + if (v0 ^ v1) + { + // watch for degenerate points + if (*s0 == value) + { + if (i > xMin && *(isect2Ptr-3) > -1) + { + *isect2Ptr = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *isect2Ptr = *(isect1Ptr+2); + } + } + else if (*s1 == value) + { + if (j > yMin && *(isect2Ptr - yisectstep +4) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 4); + } + else if (k > zMin && i < xMax && *(isect1Ptr + 5) > -1) + { + *isect2Ptr = *(isect1Ptr + 5); + } + } + // if the edge has not been set yet then it is a new point + if (*isect2Ptr == -1) + { + t = (value - (double)(*s0)) / ((double)(*s1) - (double)(*s0)); + x[0] = origin[0] + spacing[0]*(i+t); + x[1] = y; + *isect2Ptr = newPts->InsertNextPoint(x); + VTK_CSP3PA(i+1,j,k,s1); + outPD->InterpolateEdge(inPD, *isect2Ptr, edgePtId, edgePtId+1, t); + } + } + } + if (j < yMax) + { + s2 = (inPtrX + yInc); + v2 = (*s2 < value ? 0 : 1); + if (v0 ^ v2) + { + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 1) = *isect2Ptr; + } + else if (i > xMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 1) = *(isect1Ptr+2); + } + } + else if (*s2 == value && k > zMin && *(isect1Ptr + yisectstep + 2) > -1) + { + *(isect2Ptr+1) = *(isect1Ptr + yisectstep + 2); + } + // if the edge has not been set yet then it is a new point + if (*(isect2Ptr + 1) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s2) - (double)(*s0)); + x[0] = origin[0] + spacing[0]*i; + x[1] = y + spacing[1]*t; + *(isect2Ptr + 1) = newPts->InsertNextPoint(x); + VTK_CSP3PA(i,j+1,k,s2); + outPD->InterpolateEdge(inPD, *(isect2Ptr+1), edgePtId, edgePtId+yInc, t); + } + } + } + if (k < zMax) + { + s3 = (inPtrX + zInc); + v3 = (*s3 < value ? 0 : 1); + if (v0 ^ v3) + { + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 2) = *isect2Ptr; + } + else if (*(isect2Ptr+1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr+1); + } + else if (i > xMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 2) = *(isect1Ptr+2); + } + } + if (*(isect2Ptr + 2) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s3) - (double)(*s0)); + xz[0] = origin[0] + spacing[0]*i; + xz[2] = z + spacing[2]*t; + *(isect2Ptr + 2) = newPts->InsertNextPoint(xz); + VTK_CSP3PA(i,j,k+1,s3); + outPD->InterpolateEdge(inPD, *(isect2Ptr+2), edgePtId, edgePtId+zInc, t); + } + } + } + // To keep track of ids for interpolating attributes. + ++edgePtId; + + // now add any polys that need to be added + // basically look at the isect values, + // form an index and lookup the polys + if (j > yMin && i < xMax && k > zMin) + { + idx = (v0 ? 4096 : 0); + idx = idx + (*(isect1Ptr - yisectstep) > -1 ? 2048 : 0); + idx = idx + (*(isect1Ptr -yisectstep +1) > -1 ? 1024 : 0); + idx = idx + (*(isect1Ptr -yisectstep +2) > -1 ? 512 : 0); + idx = idx + (*(isect1Ptr -yisectstep +4) > -1 ? 256 : 0); + idx = idx + (*(isect1Ptr -yisectstep +5) > -1 ? 128 : 0); + idx = idx + (*(isect1Ptr) > -1 ? 64 : 0); + idx = idx + (*(isect1Ptr + 2) > -1 ? 32 : 0); + idx = idx + (*(isect1Ptr + 5) > -1 ? 16 : 0); + idx = idx + (*(isect2Ptr -yisectstep) > -1 ? 8 : 0); + idx = idx + (*(isect2Ptr -yisectstep +1) > -1 ? 4 : 0); + idx = idx + (*(isect2Ptr -yisectstep +4) > -1 ? 2 : 0); + idx = idx + (*(isect2Ptr) > -1 ? 1 : 0); + + tablePtr = VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_2 + + VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_1[idx]; + while (*tablePtr != -1) + { + ptIds[0] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[1] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[2] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + if (ptIds[0] != ptIds[1] && + ptIds[0] != ptIds[2] && + ptIds[1] != ptIds[2]) + { + outCellId = newPolys->InsertNextCell(3,ptIds); + outCD->CopyData(inCD, inCellId, outCellId); + } + } + } + inPtrX += xInc; + isect2Ptr += 3; + isect1Ptr += 3; + // To keep track of ids for copying cell attributes.. + ++inCellId; + } + inPtrY += yInc; + } + inPtrZ += zInc; + } + } + delete [] isect1; + + if (newScalars) + { + // Lets set the name of the scalars here. + if (inScalars) + { + newScalars->SetName(inScalars->GetName()); + } + idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + newScalars = NULL; + } + if (newGradients) + { + output->GetPointData()->SetVectors(newGradients); + newGradients->Delete(); + newGradients = NULL; + } + if (newNormals) + { + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + newNormals = NULL; + } +} + + + + +//---------------------------------------------------------------------------- +void vtkSynchronizedTemplates3D::SetInputMemoryLimit( + unsigned long vtkNotUsed(limit) ) +{ + vtkErrorMacro( << "This filter no longer supports a memory limit." ); + vtkErrorMacro( << "This filter no longer initiates streaming." ); + vtkErrorMacro( << "Please use a vtkPolyDataStreamer after this filter to achieve similar functionality." ); +} + + +//---------------------------------------------------------------------------- +unsigned long vtkSynchronizedTemplates3D::GetInputMemoryLimit() +{ + vtkErrorMacro( << "This filter no longer supports a memory limit." ); + vtkErrorMacro( << "This filter no longer initiates streaming." ); + vtkErrorMacro( << "Please use a vtkPolyDataStreamer after this filter to achieve similar functionality." ); + + return 0; +} + + + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images (or slices from images) +// +void vtkSynchronizedTemplates3D::ThreadedExecute(vtkImageData *data, + vtkInformation *inInfo, + vtkInformation *outInfo, + int *exExt, vtkDataArray *inScalars) +{ + void *ptr; + vtkPolyData *output; + + vtkDebugMacro(<< "Executing 3D structured contour"); + + output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if ( exExt[0] >= exExt[1] || exExt[2] >= exExt[3] || exExt[4] >= exExt[5] ) + { + vtkDebugMacro(<<"3D structured contours requires 3D data"); + return; + } + + // + // Check data type and execute appropriate function + // + if (inScalars == NULL) + { + vtkDebugMacro("No scalars for contouring."); + return; + } + int numComps = inScalars->GetNumberOfComponents(); + + if (this->ArrayComponent >= numComps) + { + vtkErrorMacro("Scalars have " << numComps << " components. " + "ArrayComponent must be smaller than " << numComps); + return; + } + + ptr = data->GetArrayPointerForExtent(inScalars, exExt); + switch (inScalars->GetDataType()) + { + vtkTemplateMacro( + ContourImage(this, exExt, inInfo, data, output, + (VTK_TT *)ptr, inScalars)); + } +} + +//---------------------------------------------------------------------------- +int vtkSynchronizedTemplates3D::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // to be safe recompute the + this->RequestUpdateExtent(request,inputVector,outputVector); + + vtkDataArray *inScalars = this->GetInputArrayToProcess(0,inputVector); + + // Just call the threaded execute directly. + this->ThreadedExecute(input, inInfo, outInfo, this->ExecuteExtent, inScalars); + + output->Squeeze(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSynchronizedTemplates3D::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces; + int *wholeExt; + int ext[6]; + + vtkExtentTranslator *translator = vtkExtentTranslator::SafeDownCast( + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + wholeExt = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + // Get request from output + piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + // Start with the whole grid. + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext); + + // get the extent associated with the piece. + if (translator == NULL) + { + // Default behavior + if (piece != 0) + { + ext[0] = ext[2] = ext[4] = 0; + ext[1] = ext[3] = ext[5] = -1; + } + } + else + { + translator->PieceToExtentThreadSafe(piece, numPieces, 0, wholeExt, ext, + translator->GetSplitMode(),0); + } + + // As a side product of this call, ExecuteExtent is set. + // This is the region that we are really updating, although + // we may require a larger input region in order to generate + // it if normals / gradients are being computed + + this->ExecuteExtent[0] = ext[0]; + this->ExecuteExtent[1] = ext[1]; + this->ExecuteExtent[2] = ext[2]; + this->ExecuteExtent[3] = ext[3]; + this->ExecuteExtent[4] = ext[4]; + this->ExecuteExtent[5] = ext[5]; + + // expand if we need to compute gradients + if (this->ComputeGradients || this->ComputeNormals) + { + ext[0] -= 1; + if (ext[0] < wholeExt[0]) + { + ext[0] = wholeExt[0]; + } + ext[1] += 1; + if (ext[1] > wholeExt[1]) + { + ext[1] = wholeExt[1]; + } + + ext[2] -= 1; + if (ext[2] < wholeExt[2]) + { + ext[2] = wholeExt[2]; + } + ext[3] += 1; + if (ext[3] > wholeExt[3]) + { + ext[3] = wholeExt[3]; + } + + ext[4] -= 1; + if (ext[4] < wholeExt[4]) + { + ext[4] = wholeExt[4]; + } + ext[5] += 1; + if (ext[5] > wholeExt[5]) + { + ext[5] = wholeExt[5]; + } + } + + // Set the update extent of the input. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSynchronizedTemplates3D::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkSynchronizedTemplates3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + this->ContourValues->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n"); + os << indent << "Compute Gradients: " << (this->ComputeGradients ? "On\n" : "Off\n"); + os << indent << "Compute Scalars: " << (this->ComputeScalars ? "On\n" : "Off\n"); + os << indent << "ArrayComponent: " << this->ArrayComponent << endl; +} + + +// template table. + +int VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 592, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1312, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 585, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 260, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 948, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 935, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 620, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 530, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1263, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 988, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 288, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 874, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 106, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 746, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1119, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 404, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 414, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1126, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 736, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 786, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 355, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1064, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1172, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 448, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 687, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1211, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 484, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 660, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 822, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 328, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1028, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 441, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1162, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 700, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 773, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1080, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 368, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1018, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 315, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 838, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 647, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 494, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1218, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 278, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 975, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 890, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 214, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 610, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1276, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 540, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1011, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 305, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 848, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 637, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 504, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1231, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 271, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 965, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 903, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 603, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1292, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 553, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1201, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 471, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 667, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 809, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 335, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1038, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 431, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1149, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 710, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 763, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1093, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 378, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 753, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 391, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 421, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1136, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 723, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 796, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 345, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1051, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1185, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 458, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 55, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 677, 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, 596, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1299, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 569, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 264, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 955, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 919, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 237, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 627, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 517, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1247, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 998, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 295, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 191, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 861, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2036, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1316, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2040, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2404, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1641, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1648, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2408, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1993, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2696, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2080, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1344, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1592, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2361, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2460, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1688, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2594, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1837, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1470, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2218, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2211, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1460, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1850, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2598, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1776, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2557, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2270, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1510, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1411, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2168, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2632, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1896, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1384, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2132, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2662, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1941, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1740, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2512, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2315, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1546, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2184, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1424, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1886, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2625, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2564, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1792, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1497, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2254, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1562, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2322, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2499, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1724, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1954, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2666, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1371, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2374, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1602, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1675, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2444, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2700, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2000, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1334, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2067, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1572, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2335, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2489, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1711, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1967, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2676, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2103, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1361, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2384, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1615, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1665, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2431, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2707, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2016, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1327, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2057, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1391, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2142, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2655, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1925, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1750, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2525, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2299, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1533, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2191, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1434, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1873, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2615, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2574, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1805, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1487, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2241, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2587, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1821, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1477, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2228, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2201, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1447, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1860, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2605, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1763, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2541, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2283, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1520, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1401, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2155, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2642, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1909, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +2711, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2029, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1320, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2047, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2391, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1625, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1655, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2418, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1977, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2683, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2090, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1351, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1579, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2345, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2473, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1698 }; + + +int VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_2[] = { + -1, 0, 1, 2, -1, 0, 4, 3, -1, 3, 1, 2, + 4, 3, 2, -1, 3, 7, 5, -1, 0, 1, 2, 3, + 7, 5, -1, 4, 7, 5, 0, 4, 5, -1, 5, 1, + 2, 5, 2, 7, 7, 2, 4, -1, 1, 5, 6, -1, + 0, 5, 6, 2, 0, 6, -1, 3, 0, 4, 5, 6, + 1, -1, 3, 5, 6, 3, 6, 4, 4, 6, 2, -1, + 1, 3, 7, 6, 1, 7, -1, 0, 3, 7, 0, 7, + 2, 2, 7, 6, -1, 1, 0, 4, 1, 4, 6, 6, + 4, 7, -1, 4, 7, 2, 7, 6, 2, -1, 8, 2, + 9, -1, 8, 0, 1, 9, 8, 1, -1, 0, 4, 3, + 2, 9, 8, -1, 8, 4, 3, 8, 3, 9, 9, 3, + 1, -1, 3, 7, 5, 2, 9, 8, -1, 1, 9, 8, + 1, 8, 0, 3, 7, 5, -1, 4, 7, 5, 4, 5, + 0, 2, 9, 8, -1, 5, 4, 7, 5, 9, 4, 5, + 1, 9, 9, 8, 4, -1, 2, 9, 8, 1, 5, 6, + -1, 6, 9, 8, 6, 8, 5, 5, 8, 0, -1, 4, + 3, 0, 2, 9, 8, 5, 6, 1, -1, 8, 6, 9, + 4, 6, 8, 4, 5, 6, 4, 3, 5, -1, 1, 3, + 7, 1, 7, 6, 9, 8, 2, -1, 3, 7, 6, 3, + 6, 8, 3, 8, 0, 9, 8, 6, -1, 8, 2, 9, + 4, 6, 0, 4, 7, 6, 6, 1, 0, -1, 8, 6, + 9, 8, 4, 6, 4, 7, 6, -1, 4, 8, 10, -1, + 4, 8, 10, 0, 1, 2, -1, 0, 8, 10, 3, 0, + 10, -1, 2, 8, 10, 2, 10, 1, 1, 10, 3, -1, + 3, 7, 5, 4, 8, 10, -1, 1, 2, 0, 3, 7, + 5, 8, 10, 4, -1, 10, 7, 5, 10, 5, 8, 8, + 5, 0, -1, 5, 10, 7, 1, 10, 5, 1, 8, 10, + 1, 2, 8, -1, 4, 8, 10, 5, 6, 1, -1, 0, + 5, 6, 0, 6, 2, 8, 10, 4, -1, 0, 8, 10, + 0, 10, 3, 5, 6, 1, -1, 5, 10, 3, 5, 2, + 10, 5, 6, 2, 8, 10, 2, -1, 7, 6, 1, 7, + 1, 3, 4, 8, 10, -1, 8, 10, 4, 0, 3, 2, + 2, 3, 7, 2, 7, 6, -1, 10, 0, 8, 10, 6, + 0, 10, 7, 6, 6, 1, 0, -1, 10, 2, 8, 10, + 7, 2, 7, 6, 2, -1, 4, 2, 9, 10, 4, 9, + -1, 4, 0, 1, 4, 1, 10, 10, 1, 9, -1, 0, + 2, 9, 0, 9, 3, 3, 9, 10, -1, 3, 1, 10, + 1, 9, 10, -1, 4, 2, 9, 4, 9, 10, 7, 5, + 3, -1, 7, 5, 3, 4, 0, 10, 10, 0, 1, 10, + 1, 9, -1, 2, 5, 0, 2, 10, 5, 2, 9, 10, + 7, 5, 10, -1, 5, 10, 7, 5, 1, 10, 1, 9, + 10, -1, 9, 10, 4, 9, 4, 2, 1, 5, 6, -1, + 4, 9, 10, 4, 5, 9, 4, 0, 5, 5, 6, 9, + -1, 5, 6, 1, 0, 2, 3, 3, 2, 9, 3, 9, + 10, -1, 6, 3, 5, 6, 9, 3, 9, 10, 3, -1, + 4, 2, 10, 2, 9, 10, 7, 1, 3, 7, 6, 1, + -1, 10, 0, 9, 10, 4, 0, 9, 0, 6, 3, 7, + 0, 6, 0, 7, -1, 6, 0, 7, 6, 1, 0, 7, + 0, 10, 2, 9, 0, 10, 0, 9, -1, 6, 10, 7, + 9, 10, 6, -1, 7, 10, 11, -1, 0, 1, 2, 10, + 11, 7, -1, 4, 3, 0, 10, 11, 7, -1, 3, 1, + 2, 3, 2, 4, 10, 11, 7, -1, 3, 10, 11, 5, + 3, 11, -1, 3, 10, 11, 3, 11, 5, 1, 2, 0, + -1, 4, 10, 11, 4, 11, 0, 0, 11, 5, -1, 10, + 2, 4, 10, 5, 2, 10, 11, 5, 1, 2, 5, -1, + 5, 6, 1, 7, 10, 11, -1, 6, 2, 0, 6, 0, + 5, 7, 10, 11, -1, 0, 4, 3, 5, 6, 1, 10, + 11, 7, -1, 10, 11, 7, 3, 5, 4, 4, 5, 6, + 4, 6, 2, -1, 11, 6, 1, 11, 1, 10, 10, 1, + 3, -1, 0, 6, 2, 0, 10, 6, 0, 3, 10, 10, + 11, 6, -1, 1, 11, 6, 0, 11, 1, 0, 10, 11, + 0, 4, 10, -1, 11, 4, 10, 11, 6, 4, 6, 2, + 4, -1, 10, 11, 7, 8, 2, 9, -1, 8, 0, 1, + 8, 1, 9, 11, 7, 10, -1, 3, 0, 4, 10, 11, + 7, 2, 9, 8, -1, 7, 10, 11, 3, 9, 4, 3, + 1, 9, 9, 8, 4, -1, 11, 5, 3, 11, 3, 10, + 8, 2, 9, -1, 3, 10, 5, 10, 11, 5, 1, 8, + 0, 1, 9, 8, -1, 2, 9, 8, 4, 10, 0, 0, + 10, 11, 0, 11, 5, -1, 9, 4, 1, 9, 8, 4, + 1, 4, 5, 10, 11, 4, 5, 4, 11, -1, 1, 5, + 6, 9, 8, 2, 7, 10, 11, -1, 10, 11, 7, 8, + 5, 9, 8, 0, 5, 5, 6, 9, -1, 0, 4, 3, + 8, 2, 9, 5, 6, 1, 10, 11, 7, -1, 4, 3, + 5, 4, 5, 6, 4, 6, 8, 9, 8, 6, 10, 11, + 7, -1, 2, 9, 8, 1, 10, 6, 1, 3, 10, 10, + 11, 6, -1, 10, 6, 3, 10, 11, 6, 3, 6, 0, + 9, 8, 6, 0, 6, 8, -1, 0, 4, 10, 0, 10, + 11, 0, 11, 1, 6, 1, 11, 2, 9, 8, -1, 11, + 4, 10, 11, 6, 4, 8, 4, 9, 9, 4, 6, -1, + 7, 4, 8, 11, 7, 8, -1, 8, 11, 7, 8, 7, + 4, 0, 1, 2, -1, 7, 3, 0, 7, 0, 11, 11, + 0, 8, -1, 2, 3, 1, 2, 11, 3, 2, 8, 11, + 11, 7, 3, -1, 3, 4, 8, 3, 8, 5, 5, 8, + 11, -1, 1, 2, 0, 3, 4, 5, 5, 4, 8, 5, + 8, 11, -1, 0, 8, 5, 8, 11, 5, -1, 2, 5, + 1, 2, 8, 5, 8, 11, 5, -1, 7, 4, 8, 7, + 8, 11, 6, 1, 5, -1, 0, 5, 2, 5, 6, 2, + 8, 7, 4, 8, 11, 7, -1, 1, 5, 6, 0, 11, + 3, 0, 8, 11, 11, 7, 3, -1, 11, 3, 8, 11, + 7, 3, 8, 3, 2, 5, 6, 3, 2, 3, 6, -1, + 4, 8, 11, 4, 11, 1, 4, 1, 3, 6, 1, 11, + -1, 2, 3, 6, 2, 0, 3, 6, 3, 11, 4, 8, + 3, 11, 3, 8, -1, 1, 11, 6, 1, 0, 11, 0, + 8, 11, -1, 11, 2, 8, 6, 2, 11, -1, 9, 11, + 7, 9, 7, 2, 2, 7, 4, -1, 0, 1, 9, 0, + 9, 7, 0, 7, 4, 11, 7, 9, -1, 7, 9, 11, + 3, 9, 7, 3, 2, 9, 3, 0, 2, -1, 7, 9, + 11, 7, 3, 9, 3, 1, 9, -1, 3, 11, 5, 3, + 2, 11, 3, 4, 2, 2, 9, 11, -1, 5, 4, 11, + 5, 3, 4, 11, 4, 9, 0, 1, 4, 9, 4, 1, + -1, 9, 0, 2, 9, 11, 0, 11, 5, 0, -1, 9, + 5, 1, 11, 5, 9, -1, 5, 6, 1, 7, 2, 11, + 7, 4, 2, 2, 9, 11, -1, 5, 9, 0, 5, 6, + 9, 0, 9, 4, 11, 7, 9, 4, 9, 7, -1, 3, + 0, 2, 3, 2, 9, 3, 9, 7, 11, 7, 9, 5, + 6, 1, -1, 6, 3, 5, 6, 9, 3, 7, 3, 11, + 11, 3, 9, -1, 2, 11, 4, 2, 9, 11, 4, 11, + 3, 6, 1, 11, 3, 11, 1, -1, 0, 3, 4, 6, + 9, 11, -1, 9, 0, 2, 9, 11, 0, 1, 0, 6, + 6, 0, 11, -1, 9, 11, 6, -1, 9, 6, 11, -1, + 1, 2, 0, 6, 11, 9, -1, 0, 4, 3, 6, 11, + 9, -1, 2, 4, 3, 2, 3, 1, 6, 11, 9, -1, + 7, 5, 3, 11, 9, 6, -1, 3, 7, 5, 1, 2, + 0, 11, 9, 6, -1, 5, 0, 4, 5, 4, 7, 11, + 9, 6, -1, 11, 9, 6, 5, 1, 7, 7, 1, 2, + 7, 2, 4, -1, 9, 1, 5, 11, 9, 5, -1, 9, + 2, 0, 9, 0, 11, 11, 0, 5, -1, 5, 11, 9, + 5, 9, 1, 0, 4, 3, -1, 3, 5, 11, 3, 11, + 2, 3, 2, 4, 2, 11, 9, -1, 7, 11, 9, 7, + 9, 3, 3, 9, 1, -1, 7, 11, 9, 3, 7, 9, + 3, 9, 2, 3, 2, 0, -1, 0, 9, 1, 0, 7, + 9, 0, 4, 7, 11, 9, 7, -1, 9, 7, 11, 9, + 2, 7, 2, 4, 7, -1, 11, 8, 2, 6, 11, 2, + -1, 1, 6, 11, 1, 11, 0, 0, 11, 8, -1, 2, + 6, 11, 2, 11, 8, 4, 3, 0, -1, 4, 11, 8, + 4, 1, 11, 4, 3, 1, 6, 11, 1, -1, 11, 8, + 2, 11, 2, 6, 5, 3, 7, -1, 3, 7, 5, 1, + 6, 0, 0, 6, 11, 0, 11, 8, -1, 8, 2, 6, + 8, 6, 11, 0, 4, 5, 5, 4, 7, -1, 7, 1, + 4, 7, 5, 1, 4, 1, 8, 6, 11, 1, 8, 1, + 11, -1, 2, 1, 5, 2, 5, 8, 8, 5, 11, -1, + 0, 5, 8, 8, 5, 11, -1, 3, 0, 4, 5, 8, + 1, 5, 11, 8, 8, 2, 1, -1, 3, 8, 4, 3, + 5, 8, 5, 11, 8, -1, 2, 1, 3, 2, 3, 11, + 2, 11, 8, 11, 3, 7, -1, 7, 0, 3, 7, 11, + 0, 11, 8, 0, -1, 8, 1, 11, 8, 2, 1, 11, + 1, 7, 0, 4, 1, 7, 1, 4, -1, 7, 8, 4, + 11, 8, 7, -1, 8, 10, 4, 9, 6, 11, -1, 0, + 1, 2, 8, 10, 4, 6, 11, 9, -1, 10, 3, 0, + 10, 0, 8, 9, 6, 11, -1, 6, 11, 9, 2, 8, + 1, 1, 8, 10, 1, 10, 3, -1, 4, 8, 10, 7, + 5, 3, 9, 6, 11, -1, 11, 9, 6, 3, 7, 5, + 0, 1, 2, 8, 10, 4, -1, 9, 6, 11, 10, 7, + 8, 8, 7, 5, 8, 5, 0, -1, 1, 2, 8, 1, + 8, 10, 1, 10, 5, 7, 5, 10, 6, 11, 9, -1, + 9, 1, 5, 9, 5, 11, 10, 4, 8, -1, 4, 8, + 10, 0, 11, 2, 0, 5, 11, 11, 9, 2, -1, 1, + 5, 11, 1, 11, 9, 3, 0, 10, 10, 0, 8, -1, + 11, 2, 5, 11, 9, 2, 5, 2, 3, 8, 10, 2, + 3, 2, 10, -1, 4, 8, 10, 7, 11, 3, 3, 11, + 9, 3, 9, 1, -1, 3, 7, 11, 3, 11, 9, 3, + 9, 0, 2, 0, 9, 4, 8, 10, -1, 8, 7, 0, + 8, 10, 7, 0, 7, 1, 11, 9, 7, 1, 7, 9, + -1, 9, 7, 11, 9, 2, 7, 10, 7, 8, 8, 7, + 2, -1, 11, 10, 4, 11, 4, 6, 6, 4, 2, -1, + 1, 6, 11, 0, 1, 11, 0, 11, 10, 0, 10, 4, + -1, 0, 2, 6, 0, 6, 10, 0, 10, 3, 10, 6, + 11, -1, 11, 1, 6, 11, 10, 1, 10, 3, 1, -1, + 3, 7, 5, 4, 6, 10, 4, 2, 6, 6, 11, 10, + -1, 0, 1, 6, 0, 6, 11, 0, 11, 4, 10, 4, + 11, 3, 7, 5, -1, 6, 10, 2, 6, 11, 10, 2, + 10, 0, 7, 5, 10, 0, 10, 5, -1, 11, 1, 6, + 11, 10, 1, 5, 1, 7, 7, 1, 10, -1, 10, 4, + 2, 10, 2, 5, 10, 5, 11, 1, 5, 2, -1, 4, + 11, 10, 4, 0, 11, 0, 5, 11, -1, 3, 2, 10, + 3, 0, 2, 10, 2, 11, 1, 5, 2, 11, 2, 5, + -1, 3, 11, 10, 5, 11, 3, -1, 3, 11, 1, 3, + 7, 11, 1, 11, 2, 10, 4, 11, 2, 11, 4, -1, + 7, 0, 3, 7, 11, 0, 4, 0, 10, 10, 0, 11, + -1, 0, 2, 1, 10, 7, 11, -1, 7, 11, 10, -1, + 6, 7, 10, 9, 6, 10, -1, 6, 7, 10, 6, 10, + 9, 2, 0, 1, -1, 10, 9, 6, 10, 6, 7, 3, + 0, 4, -1, 7, 10, 9, 7, 9, 6, 4, 3, 2, + 2, 3, 1, -1, 6, 5, 3, 6, 3, 9, 9, 3, + 10, -1, 0, 1, 2, 3, 9, 5, 3, 10, 9, 9, + 6, 5, -1, 4, 10, 9, 4, 9, 5, 4, 5, 0, + 5, 9, 6, -1, 9, 5, 10, 9, 6, 5, 10, 5, + 4, 1, 2, 5, 4, 5, 2, -1, 5, 7, 10, 5, + 10, 1, 1, 10, 9, -1, 2, 0, 5, 2, 5, 10, + 2, 10, 9, 7, 10, 5, -1, 4, 3, 0, 10, 1, + 7, 10, 9, 1, 1, 5, 7, -1, 4, 5, 2, 4, + 3, 5, 2, 5, 9, 7, 10, 5, 9, 5, 10, -1, + 3, 10, 1, 1, 10, 9, -1, 0, 9, 2, 0, 3, + 9, 3, 10, 9, -1, 4, 1, 0, 4, 10, 1, 10, + 9, 1, -1, 4, 9, 2, 10, 9, 4, -1, 10, 8, + 2, 10, 2, 7, 7, 2, 6, -1, 10, 8, 0, 10, + 0, 6, 10, 6, 7, 6, 0, 1, -1, 0, 4, 3, + 2, 7, 8, 2, 6, 7, 7, 10, 8, -1, 7, 8, + 6, 7, 10, 8, 6, 8, 1, 4, 3, 8, 1, 8, + 3, -1, 5, 3, 10, 5, 10, 2, 5, 2, 6, 8, + 2, 10, -1, 0, 6, 8, 0, 1, 6, 8, 6, 10, + 5, 3, 6, 10, 6, 3, -1, 0, 10, 5, 0, 4, + 10, 5, 10, 6, 8, 2, 10, 6, 10, 2, -1, 4, + 10, 8, 5, 1, 6, -1, 5, 7, 10, 1, 5, 10, + 1, 10, 8, 1, 8, 2, -1, 10, 5, 7, 10, 8, + 5, 8, 0, 5, -1, 1, 5, 7, 1, 7, 10, 1, + 10, 2, 8, 2, 10, 0, 4, 3, -1, 10, 5, 7, + 10, 8, 5, 3, 5, 4, 4, 5, 8, -1, 2, 10, + 8, 2, 1, 10, 1, 3, 10, -1, 0, 10, 8, 3, + 10, 0, -1, 2, 10, 8, 2, 1, 10, 4, 10, 0, + 0, 10, 1, -1, 4, 10, 8, -1, 8, 9, 6, 8, + 6, 4, 4, 6, 7, -1, 0, 1, 2, 8, 9, 4, + 4, 9, 6, 4, 6, 7, -1, 3, 6, 7, 3, 8, + 6, 3, 0, 8, 9, 6, 8, -1, 1, 8, 3, 1, + 2, 8, 3, 8, 7, 9, 6, 8, 7, 8, 6, -1, + 8, 9, 6, 4, 8, 6, 4, 6, 5, 4, 5, 3, + -1, 4, 8, 9, 4, 9, 6, 4, 6, 3, 5, 3, + 6, 0, 1, 2, -1, 6, 8, 9, 6, 5, 8, 5, + 0, 8, -1, 6, 8, 9, 6, 5, 8, 2, 8, 1, + 1, 8, 5, -1, 5, 7, 4, 5, 4, 9, 5, 9, + 1, 9, 4, 8, -1, 4, 9, 7, 4, 8, 9, 7, + 9, 5, 2, 0, 9, 5, 9, 0, -1, 1, 7, 9, + 1, 5, 7, 9, 7, 8, 3, 0, 7, 8, 7, 0, + -1, 3, 5, 7, 2, 8, 9, -1, 8, 3, 4, 8, + 9, 3, 9, 1, 3, -1, 8, 3, 4, 8, 9, 3, + 0, 3, 2, 2, 3, 9, -1, 8, 1, 0, 9, 1, + 8, -1, 8, 9, 2, -1, 4, 2, 7, 7, 2, 6, + -1, 1, 4, 0, 1, 6, 4, 6, 7, 4, -1, 0, + 7, 3, 0, 2, 7, 2, 6, 7, -1, 1, 7, 3, + 6, 7, 1, -1, 3, 6, 5, 3, 4, 6, 4, 2, + 6, -1, 1, 4, 0, 1, 6, 4, 3, 4, 5, 5, + 4, 6, -1, 0, 6, 5, 2, 6, 0, -1, 1, 6, + 5, -1, 5, 2, 1, 5, 7, 2, 7, 4, 2, -1, + 4, 5, 7, 0, 5, 4, -1, 5, 2, 1, 5, 7, + 2, 0, 2, 3, 3, 2, 7, -1, 3, 5, 7, -1, + 3, 2, 1, 4, 2, 3, -1, 0, 3, 4, -1, 0, + 2, 1, -1 }; + + diff --git a/Graphics/vtkSynchronizedTemplates3D.h b/Graphics/vtkSynchronizedTemplates3D.h new file mode 100644 index 0000000..c2d2fd6 --- /dev/null +++ b/Graphics/vtkSynchronizedTemplates3D.h @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSynchronizedTemplates3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSynchronizedTemplates3D - generate isosurface from structured points + +// .SECTION Description +// vtkSynchronizedTemplates3D is a 3D implementation of the synchronized +// template algorithm. Note that vtkContourFilter will automatically +// use this class when appropriate. + +// .SECTION Caveats +// This filter is specialized to 3D images (aka volumes). + +// .SECTION See Also +// vtkContourFilter vtkSynchronizedTemplates2D + +#ifndef __vtkSynchronizedTemplates3D_h +#define __vtkSynchronizedTemplates3D_h + +#include "vtkPolyDataAlgorithm.h" +#include "vtkContourValues.h" // Passes calls through + +class vtkImageData; + +class VTK_GRAPHICS_EXPORT vtkSynchronizedTemplates3D : public vtkPolyDataAlgorithm +{ +public: + static vtkSynchronizedTemplates3D *New(); + + vtkTypeRevisionMacro(vtkSynchronizedTemplates3D,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Because we delegate to vtkContourValues + unsigned long int GetMTime(); + + // Description: + // Set/Get the computation of normals. Normal computation is fairly + // expensive in both time and storage. If the output data will be + // processed by filters that modify topology or geometry, it may be + // wise to turn Normals and Gradients off. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Set/Get the computation of gradients. Gradient computation is + // fairly expensive in both time and storage. Note that if + // ComputeNormals is on, gradients will have to be calculated, but + // will not be stored in the output dataset. If the output data + // will be processed by filters that modify topology or geometry, it + // may be wise to turn Normals and Gradients off. + vtkSetMacro(ComputeGradients,int); + vtkGetMacro(ComputeGradients,int); + vtkBooleanMacro(ComputeGradients,int); + + // Description: + // Set/Get the computation of scalars. + vtkSetMacro(ComputeScalars,int); + vtkGetMacro(ComputeScalars,int); + vtkBooleanMacro(ComputeScalars,int); + + // Description: + // Set a particular contour value at contour number i. The index i ranges + // between 0<=iContourValues->SetValue(i,value);} + + // Description: + // Get the ith contour value. + double GetValue(int i) {return this->ContourValues->GetValue(i);} + + // Description: + // Get a pointer to an array of contour values. There will be + // GetNumberOfContours() values in the list. + double *GetValues() {return this->ContourValues->GetValues();} + + // Description: + // Fill a supplied list with contour values. There will be + // GetNumberOfContours() values in the list. Make sure you allocate + // enough memory to hold the list. + void GetValues(double *contourValues) { + this->ContourValues->GetValues(contourValues);} + + // Description: + // Set the number of contours to place into the list. You only really + // need to use this method to reduce list size. The method SetValue() + // will automatically increase list size as needed. + void SetNumberOfContours(int number) { + this->ContourValues->SetNumberOfContours(number);} + + // Description: + // Get the number of contours in the list of contour values. + int GetNumberOfContours() { + return this->ContourValues->GetNumberOfContours();} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double range[2]) { + this->ContourValues->GenerateValues(numContours, range);} + + // Description: + // Generate numContours equally spaced contour values between specified + // range. Contour values will include min/max range values. + void GenerateValues(int numContours, double rangeStart, double rangeEnd) + {this->ContourValues->GenerateValues(numContours, rangeStart, rangeEnd);} + + // Description: + // Needed by templated functions. + int *GetExecuteExtent() {return this->ExecuteExtent;} + void ThreadedExecute(vtkImageData *data, vtkInformation *inInfo, + vtkInformation *outInfo, + int *exExt, vtkDataArray *inScalars); + + // Description: + // Determines the chunk size fro streaming. This filter will act like a + // collector: ask for many input pieces, but generate one output. Limit is + // in KBytes + void SetInputMemoryLimit(unsigned long limit); + unsigned long GetInputMemoryLimit(); + + // Description: + // Set/get which component of the scalar array to contour on; defaults to 0. + vtkSetMacro(ArrayComponent, int); + vtkGetMacro(ArrayComponent, int); + +protected: + vtkSynchronizedTemplates3D(); + ~vtkSynchronizedTemplates3D(); + + int ComputeNormals; + int ComputeGradients; + int ComputeScalars; + vtkContourValues *ContourValues; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int ExecuteExtent[6]; + + int ArrayComponent; + +private: + vtkSynchronizedTemplates3D(const vtkSynchronizedTemplates3D&); // Not implemented. + void operator=(const vtkSynchronizedTemplates3D&); // Not implemented. +}; + + +// template table. +//BTX + +extern int VTK_GRAPHICS_EXPORT VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_1[]; +extern int VTK_GRAPHICS_EXPORT VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_2[]; + +//ETX + +#endif + diff --git a/Graphics/vtkSynchronizedTemplatesCutter3D.cxx b/Graphics/vtkSynchronizedTemplatesCutter3D.cxx new file mode 100644 index 0000000..f23c756 --- /dev/null +++ b/Graphics/vtkSynchronizedTemplatesCutter3D.cxx @@ -0,0 +1,542 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSynchronizedTemplatesCutter3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSynchronizedTemplatesCutter3D.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkExtentTranslator.h" +#include "vtkFloatArray.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredPoints.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include + +vtkCxxRevisionMacro(vtkSynchronizedTemplatesCutter3D, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkSynchronizedTemplatesCutter3D); +vtkCxxSetObjectMacro(vtkSynchronizedTemplatesCutter3D,CutFunction,vtkImplicitFunction); + +//---------------------------------------------------------------------------- +// Description: +// Construct object with initial scalar range (0,1) and single contour value +// of 0.0. The ImageRange are set to extract the first k-plane. +vtkSynchronizedTemplatesCutter3D::vtkSynchronizedTemplatesCutter3D() +{ + this->CutFunction = 0; +} + +//---------------------------------------------------------------------------- +vtkSynchronizedTemplatesCutter3D::~vtkSynchronizedTemplatesCutter3D() +{ + this->SetCutFunction(NULL); +} + +//---------------------------------------------------------------------------- +void vtkSynchronizedTemplatesCutter3DInitializeOutput( + int *ext,vtkImageData *input, vtkPolyData *o) +{ + vtkPoints *newPts; + vtkCellArray *newPolys; + long estimatedSize; + + estimatedSize = (int) pow ((double) + ((ext[1]-ext[0]+1)*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1)), .75); + if (estimatedSize < 1024) + { + estimatedSize = 1024; + } + newPts = vtkPoints::New(); + newPts->Allocate(estimatedSize,estimatedSize); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(estimatedSize,3)); + + o->GetPointData()->CopyAllOn(); + + o->GetPointData()->InterpolateAllocate(input->GetPointData(), + estimatedSize,estimatedSize/2); + o->GetCellData()->CopyAllocate(input->GetCellData(), + estimatedSize,estimatedSize/2); + + o->SetPoints(newPts); + newPts->Delete(); + + o->SetPolys(newPolys); + newPolys->Delete(); +} + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images +// +template +void ContourImage(vtkSynchronizedTemplatesCutter3D *self, int *exExt, + vtkImageData *data, vtkPolyData *output, T *ptr) +{ + int *inExt = data->GetExtent(); + int xdim = exExt[1] - exExt[0] + 1; + int ydim = exExt[3] - exExt[2] + 1; + double *values = self->GetValues(); + int numContours = self->GetNumberOfContours(); + T *inPtrX, *inPtrY, *inPtrZ; + T *s0, *s1, *s2, *s3; + int xMin, xMax, yMin, yMax, zMin, zMax; + int xInc, yInc, zInc, scalarZInc; + double *origin = data->GetOrigin(); + double *spacing = data->GetSpacing(); + int *isect1Ptr, *isect2Ptr; + double y, z, t; + int i, j, k; + int zstep, yisectstep; + int offsets[12]; + int *tablePtr; + int idx, vidx; + double x[3], xz[3]; + int v0, v1, v2, v3; + vtkIdType ptIds[3]; + double value; + // We need to know the edgePointId's for interpolating attributes. + int edgePtId, inCellId, outCellId; + vtkPointData *inPD = data->GetPointData(); + vtkCellData *inCD = data->GetCellData(); + vtkPointData *outPD = output->GetPointData(); + vtkCellData *outCD = output->GetCellData(); + // Use to be arguments + vtkPoints *newPts; + vtkCellArray *newPolys; + ptr += self->GetArrayComponent(); + + vtkSynchronizedTemplatesCutter3DInitializeOutput(exExt, data, output); + newPts = output->GetPoints(); + newPolys = output->GetPolys(); + + // this is an exploded execute extent. + xMin = exExt[0]; + xMax = exExt[1]; + yMin = exExt[2]; + yMax = exExt[3]; + zMin = exExt[4]; + zMax = exExt[5]; + + vtkImplicitFunction *func = self->GetCutFunction(); + if (!func) + { + return; + } + + // implicit functions are 1 component + xInc = 1; + yInc = xInc*(inExt[1]-inExt[0]+1); + zInc = yInc*(inExt[3]-inExt[2]+1); + scalarZInc = zInc; + + // Kens increments, probably to do with edge array + zstep = xdim*ydim; + yisectstep = xdim*3; + // compute offsets probably how to get to the edges in the edge array. + offsets[0] = -xdim*3; + offsets[1] = -xdim*3 + 1; + offsets[2] = -xdim*3 + 2; + offsets[3] = -xdim*3 + 4; + offsets[4] = -xdim*3 + 5; + offsets[5] = 0; + offsets[6] = 2; + offsets[7] = 5; + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + + // allocate storage array + int *isect1 = new int [xdim*ydim*3*2]; + // set impossible edges to -1 + for (i = 0; i < ydim; i++) + { + isect1[(i+1)*xdim*3-3] = -1; + isect1[(i+1)*xdim*3*2-3] = -1; + } + for (i = 0; i < xdim; i++) + { + isect1[((ydim-1)*xdim + i)*3 + 1] = -1; + isect1[((ydim-1)*xdim + i)*3*2 + 1] = -1; + } + + // allocate scalar storage for two slices + T *scalars = 0; + T *scalars1 = 0; + T *scalars2 = 0; + scalars = new T [xdim*ydim*2]; + scalars1 = scalars; + scalars2 = scalars + xdim*ydim; + + // for each contour + for (vidx = 0; vidx < numContours; vidx++) + { + value = values[vidx]; + inPtrZ = ptr; + + // fill the first slice + z = origin[2] + spacing[2]*zMin; + x[2] = z; + T *scalarsTmp = scalars1; + scalars1 = scalars2; + scalars2 = scalarsTmp; + for (j = yMin; j <= yMax; j++) + { + x[1] = origin[1] + spacing[1]*j; + for (i = xMin; i <= xMax; i++) + { + x[0] = origin[0] + spacing[0]*i; + *scalarsTmp = func->FunctionValue(x); + scalarsTmp++; + } + } + scalarZInc = -scalarZInc; + + //================================================================== + for (k = zMin; k <= zMax; k++) + { + self->UpdateProgress((double)vidx/numContours + + (k-zMin)/((zMax - zMin+1.0)*numContours)); + inPtrY = inPtrZ; + + // for each slice compute the scalars + z = origin[2] + spacing[2]*(k+1); + x[2] = z; + scalarsTmp = scalars1; + scalars1 = scalars2; + scalars2 = scalarsTmp; + // if not the last slice then get more scalars + if (k < zMax) + { + for (j = yMin; j <= yMax; j++) + { + x[1] = origin[1] + spacing[1]*j; + for (i = xMin; i <= xMax; i++) + { + x[0] = origin[0] + spacing[0]*i; + *scalarsTmp = func->FunctionValue(x); + scalarsTmp++; + } + } + } + inPtrY = scalars1; + scalarZInc = -scalarZInc; + + z = origin[2] + spacing[2]*k; + x[2] = z; + + // swap the buffers + if (k%2) + { + offsets[8] = (zstep - xdim)*3; + offsets[9] = (zstep - xdim)*3 + 1; + offsets[10] = (zstep - xdim)*3 + 4; + offsets[11] = zstep*3; + isect1Ptr = isect1; + isect2Ptr = isect1 + xdim*ydim*3; + } + else + { + offsets[8] = (-zstep - xdim)*3; + offsets[9] = (-zstep - xdim)*3 + 1; + offsets[10] = (-zstep - xdim)*3 + 4; + offsets[11] = -zstep*3; + isect1Ptr = isect1 + xdim*ydim*3; + isect2Ptr = isect1; + } + + for (j = yMin; j <= yMax; j++) + { + // Should not impact perfomance here/ + edgePtId = (j-inExt[2])*yInc + (k-inExt[4])*zInc; + // Increments are different for cells. Since the cells are not + // contoured until the second row of templates, subtract 1 from + // i,j,and k. Note: first cube is formed when i=0, j=1, and k=1. + inCellId = + (xMin-inExt[0]) + (inExt[1]-inExt[0])* + ( (j-inExt[2]-1) + (k-inExt[4]-1)*(inExt[3]-inExt[2]) ); + + y = origin[1] + j*spacing[1]; + xz[1] = y; + + s1 = inPtrY; + v1 = (*s1 < value ? 0 : 1); + + inPtrX = inPtrY; + for (i = xMin; i <= xMax; i++) + { + s0 = s1; + v0 = v1; + *isect2Ptr = -1; + *(isect2Ptr + 1) = -1; + *(isect2Ptr + 2) = -1; + if (i < xMax) + { + s1 = (inPtrX + xInc); + v1 = (*s1 < value ? 0 : 1); + if (v0 ^ v1) + { + // watch for degenerate points + if (*s0 == value) + { + if (i > xMin && *(isect2Ptr-3) > -1) + { + *isect2Ptr = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *isect2Ptr = *(isect1Ptr+2); + } + } + else if (*s1 == value) + { + if (j > yMin && *(isect2Ptr - yisectstep +4) > -1) + { + *isect2Ptr = *(isect2Ptr - yisectstep + 4); + } + else if (k > zMin && i < xMax && *(isect1Ptr + 5) > -1) + { + *isect2Ptr = *(isect1Ptr + 5); + } + } + // if the edge has not been set yet then it is a new point + if (*isect2Ptr == -1) + { + t = (value - (double)(*s0)) / ((double)(*s1) - (double)(*s0)); + x[0] = origin[0] + spacing[0]*(i+t); + x[1] = y; + *isect2Ptr = newPts->InsertNextPoint(x); + outPD->InterpolateEdge(inPD, *isect2Ptr, edgePtId, edgePtId+1, t); + } + } + } + if (j < yMax) + { + s2 = (inPtrX + yInc); + v2 = (*s2 < value ? 0 : 1); + if (v0 ^ v2) + { + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 1) = *isect2Ptr; + } + else if (i > xMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 1) = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 1) = *(isect1Ptr+2); + } + } + else if (*s2 == value && k > zMin && *(isect1Ptr + yisectstep + 2) > -1) + { + *(isect2Ptr+1) = *(isect1Ptr + yisectstep + 2); + } + // if the edge has not been set yet then it is a new point + if (*(isect2Ptr + 1) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s2) - (double)(*s0)); + x[0] = origin[0] + spacing[0]*i; + x[1] = y + spacing[1]*t; + *(isect2Ptr + 1) = newPts->InsertNextPoint(x); + outPD->InterpolateEdge(inPD, *(isect2Ptr+1), edgePtId, edgePtId+yInc, t); + } + } + } + if (k < zMax) + { + s3 = (inPtrX + scalarZInc); + v3 = (*s3 < value ? 0 : 1); + if (v0 ^ v3) + { + if (*s0 == value) + { + if (*isect2Ptr > -1) + { + *(isect2Ptr + 2) = *isect2Ptr; + } + else if (*(isect2Ptr+1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr+1); + } + else if (i > xMin && *(isect2Ptr-3) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr-3); + } + else if (j > yMin && *(isect2Ptr - yisectstep + 1) > -1) + { + *(isect2Ptr + 2) = *(isect2Ptr - yisectstep + 1); + } + else if (k > zMin && *(isect1Ptr+2) > -1) + { + *(isect2Ptr + 2) = *(isect1Ptr+2); + } + } + if (*(isect2Ptr + 2) == -1) + { + t = (value - (double)(*s0)) / ((double)(*s3) - (double)(*s0)); + xz[0] = origin[0] + spacing[0]*i; + xz[2] = z + spacing[2]*t; + *(isect2Ptr + 2) = newPts->InsertNextPoint(xz); + outPD->InterpolateEdge(inPD, *(isect2Ptr+2), edgePtId, edgePtId+zInc, t); + } + } + } + // To keep track of ids for interpolating attributes. + ++edgePtId; + + // now add any polys that need to be added + // basically look at the isect values, + // form an index and lookup the polys + if (j > yMin && i < xMax && k > zMin) + { + idx = (v0 ? 4096 : 0); + idx = idx + (*(isect1Ptr - yisectstep) > -1 ? 2048 : 0); + idx = idx + (*(isect1Ptr -yisectstep +1) > -1 ? 1024 : 0); + idx = idx + (*(isect1Ptr -yisectstep +2) > -1 ? 512 : 0); + idx = idx + (*(isect1Ptr -yisectstep +4) > -1 ? 256 : 0); + idx = idx + (*(isect1Ptr -yisectstep +5) > -1 ? 128 : 0); + idx = idx + (*(isect1Ptr) > -1 ? 64 : 0); + idx = idx + (*(isect1Ptr + 2) > -1 ? 32 : 0); + idx = idx + (*(isect1Ptr + 5) > -1 ? 16 : 0); + idx = idx + (*(isect2Ptr -yisectstep) > -1 ? 8 : 0); + idx = idx + (*(isect2Ptr -yisectstep +1) > -1 ? 4 : 0); + idx = idx + (*(isect2Ptr -yisectstep +4) > -1 ? 2 : 0); + idx = idx + (*(isect2Ptr) > -1 ? 1 : 0); + + tablePtr = VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_2 + + VTK_SYNCHRONIZED_TEMPLATES_3D_TABLE_1[idx]; + while (*tablePtr != -1) + { + ptIds[0] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[1] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + ptIds[2] = *(isect1Ptr + offsets[*tablePtr]); + tablePtr++; + if (ptIds[0] != ptIds[1] && + ptIds[0] != ptIds[2] && + ptIds[1] != ptIds[2]) + { + outCellId = newPolys->InsertNextCell(3,ptIds); + outCD->CopyData(inCD, inCellId, outCellId); + } + } + } + inPtrX += xInc; + isect2Ptr += 3; + isect1Ptr += 3; + // To keep track of ids for copying cell attributes.. + ++inCellId; + } + inPtrY += yInc; + } + inPtrZ += zInc; + } + } + delete [] isect1; + + if (scalars) + { + delete [] scalars; + } +} + +//---------------------------------------------------------------------------- +// +// Contouring filter specialized for images (or slices from images) +// +void vtkSynchronizedTemplatesCutter3D::ThreadedExecute(vtkImageData *data, + vtkInformation *outInfo, + int *exExt, int) +{ + vtkPolyData *output; + + vtkDebugMacro(<< "Executing Cutter3D structured contour"); + + output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if ( exExt[0] >= exExt[1] || exExt[2] >= exExt[3] || exExt[4] >= exExt[5] ) + { + vtkDebugMacro(<<"Cutter3D structured contours requires Cutter3D data"); + return; + } + + + // Check data type and execute appropriate function + ContourImage(this, exExt, data, output, (double *)0); +} + +//---------------------------------------------------------------------------- +int vtkSynchronizedTemplatesCutter3D::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // to be safe recompute the + this->RequestUpdateExtent(request,inputVector,outputVector); + + // Just call the threaded execute directly. + this->ThreadedExecute(input, outInfo, this->ExecuteExtent, 0); + + output->Squeeze(); + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkSynchronizedTemplatesCutter3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Cut Function: " << this->CutFunction << "\n"; +} + diff --git a/Graphics/vtkSynchronizedTemplatesCutter3D.h b/Graphics/vtkSynchronizedTemplatesCutter3D.h new file mode 100644 index 0000000..4216508 --- /dev/null +++ b/Graphics/vtkSynchronizedTemplatesCutter3D.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSynchronizedTemplatesCutter3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSynchronizedTemplatesCutter3D - generate cut surface from structured points + +// .SECTION Description +// vtkSynchronizedTemplatesCutter3D is an implementation of the synchronized +// template algorithm. Note that vtkCutFilter will automatically +// use this class when appropriate. + +// .SECTION See Also +// vtkContourFilter vtkSynchronizedTemplates3D + +#ifndef __vtkSynchronizedTemplatesCutter3D_h +#define __vtkSynchronizedTemplatesCutter3D_h + +#include "vtkSynchronizedTemplates3D.h" + +class vtkImplicitFunction; + +class VTK_GRAPHICS_EXPORT vtkSynchronizedTemplatesCutter3D : public vtkSynchronizedTemplates3D +{ +public: + static vtkSynchronizedTemplatesCutter3D *New(); + + vtkTypeRevisionMacro(vtkSynchronizedTemplatesCutter3D,vtkSynchronizedTemplates3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Needed by templated functions. + void ThreadedExecute(vtkImageData *data, vtkInformation *outInfo, + int *exExt, int); + + // Description + // Specify the implicit function to perform the cutting. + virtual void SetCutFunction(vtkImplicitFunction*); + vtkGetObjectMacro(CutFunction,vtkImplicitFunction); + +protected: + vtkSynchronizedTemplatesCutter3D(); + ~vtkSynchronizedTemplatesCutter3D(); + + vtkImplicitFunction *CutFunction; + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + +private: + vtkSynchronizedTemplatesCutter3D(const vtkSynchronizedTemplatesCutter3D&); // Not implemented. + void operator=(const vtkSynchronizedTemplatesCutter3D&); // Not implemented. +}; + +#endif + diff --git a/Graphics/vtkTensorGlyph.cxx b/Graphics/vtkTensorGlyph.cxx new file mode 100644 index 0000000..20e4d12 --- /dev/null +++ b/Graphics/vtkTensorGlyph.cxx @@ -0,0 +1,496 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTensorGlyph.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTensorGlyph.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkTensorGlyph, "$Revision: 1.57.12.1 $"); +vtkStandardNewMacro(vtkTensorGlyph); + +// Construct object with scaling on and scale factor 1.0. Eigenvalues are +// extracted, glyphs are colored with input scalar data, and logarithmic +// scaling is turned off. +vtkTensorGlyph::vtkTensorGlyph() +{ + this->Scaling = 1; + this->ScaleFactor = 1.0; + this->ExtractEigenvalues = 1; + this->ColorGlyphs = 1; + this->ColorMode = COLOR_BY_SCALARS; + this->ClampScaling = 0; + this->MaxScaleFactor = 100; + this->ThreeGlyphs = 0; + this->Symmetric = 0; + this->Length = 1.0; + + this->SetNumberOfInputPorts(2); +} + +vtkTensorGlyph::~vtkTensorGlyph() +{ +} + +int vtkTensorGlyph::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *source = vtkPolyData::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *inTensors; + double tensor[9]; + vtkDataArray *inScalars; + vtkIdType numPts, numSourcePts, numSourceCells, inPtId, i; + int j; + vtkPoints *sourcePts; + vtkDataArray *sourceNormals; + vtkCellArray *sourceCells, *cells; + vtkPoints *newPts; + vtkFloatArray *newScalars=NULL; + vtkFloatArray *newNormals=NULL; + double x[3], s; + vtkTransform *trans; + vtkCell *cell; + vtkIdList *cellPts; + int npts; + vtkIdType *pts; + vtkIdType ptIncr, cellId; + vtkIdType subIncr; + int numDirs, dir, eigen_dir, symmetric_dir; + vtkMatrix4x4 *matrix; + double *m[3], w[3], *v[3]; + double m0[3], m1[3], m2[3]; + double v0[3], v1[3], v2[3]; + double xv[3], yv[3], zv[3]; + double maxScale; + vtkPointData *pd, *outPD; + + numDirs = (this->ThreeGlyphs?3:1)*(this->Symmetric+1); + + pts = new vtkIdType[source->GetMaxCellSize()]; + trans = vtkTransform::New(); + matrix = vtkMatrix4x4::New(); + + // set up working matrices + m[0] = m0; m[1] = m1; m[2] = m2; + v[0] = v0; v[1] = v1; v[2] = v2; + + vtkDebugMacro(<<"Generating tensor glyphs"); + + pd = input->GetPointData(); + outPD = output->GetPointData(); + inTensors = pd->GetTensors(); + inScalars = pd->GetScalars(); + numPts = input->GetNumberOfPoints(); + + if ( !inTensors || numPts < 1 ) + { + vtkErrorMacro(<<"No data to glyph!"); + return 1; + } + // + // Allocate storage for output PolyData + // + sourcePts = source->GetPoints(); + numSourcePts = sourcePts->GetNumberOfPoints(); + numSourceCells = source->GetNumberOfCells(); + + newPts = vtkPoints::New(); + newPts->Allocate(numDirs*numPts*numSourcePts); + + // Setting up for calls to PolyData::InsertNextCell() + if ( (sourceCells=source->GetVerts())->GetNumberOfCells() > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate(numDirs*numPts*sourceCells->GetSize()); + output->SetVerts(cells); + cells->Delete(); + } + if ( (sourceCells=this->GetSource()->GetLines())->GetNumberOfCells() > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate(numDirs*numPts*sourceCells->GetSize()); + output->SetLines(cells); + cells->Delete(); + } + if ( (sourceCells=this->GetSource()->GetPolys())->GetNumberOfCells() > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate(numDirs*numPts*sourceCells->GetSize()); + output->SetPolys(cells); + cells->Delete(); + } + if ( (sourceCells=this->GetSource()->GetStrips())->GetNumberOfCells() > 0 ) + { + cells = vtkCellArray::New(); + cells->Allocate(numDirs*numPts*sourceCells->GetSize()); + output->SetStrips(cells); + cells->Delete(); + } + + // only copy scalar data through + pd = this->GetSource()->GetPointData(); + // generate scalars if eigenvalues are chosen or if scalars exist. + if (this->ColorGlyphs && + ((this->ColorMode == COLOR_BY_EIGENVALUES) || + (inScalars && (this->ColorMode == COLOR_BY_SCALARS)) ) ) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(numDirs*numPts*numSourcePts); + } + else + { + outPD->CopyAllOff(); + outPD->CopyScalarsOn(); + outPD->CopyAllocate(pd,numDirs*numPts*numSourcePts); + } + if ( (sourceNormals = pd->GetNormals()) ) + { + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(numDirs*3*numPts*numSourcePts); + } + // + // First copy all topology (transformation independent) + // + for (inPtId=0; inPtId < numPts; inPtId++) + { + ptIncr = numDirs * inPtId * numSourcePts; + for (cellId=0; cellId < numSourceCells; cellId++) + { + cell = this->GetSource()->GetCell(cellId); + cellPts = cell->GetPointIds(); + npts = cellPts->GetNumberOfIds(); + for (dir=0; dir < numDirs; dir++) + { + // This variable may be removed, but that + // will not improve readability + subIncr = ptIncr + dir*numSourcePts; + for (i=0; i < npts; i++) + { + pts[i] = cellPts->GetId(i) + subIncr; + } + output->InsertNextCell(cell->GetCellType(),npts,pts); + } + } + } + // + // Traverse all Input points, transforming glyph at Source points + // + trans->PreMultiply(); + + for (inPtId=0; inPtId < numPts; inPtId++) + { + ptIncr = numDirs * inPtId * numSourcePts; + + // Translation is postponed + + inTensors->GetTuple(inPtId, tensor); + + // compute orientation vectors and scale factors from tensor + if ( this->ExtractEigenvalues ) // extract appropriate eigenfunctions + { + for (j=0; j<3; j++) + { + for (i=0; i<3; i++) + { + m[i][j] = tensor[i+3*j]; + } + } + vtkMath::Jacobi(m, w, v); + + //copy eigenvectors + xv[0] = v[0][0]; xv[1] = v[1][0]; xv[2] = v[2][0]; + yv[0] = v[0][1]; yv[1] = v[1][1]; yv[2] = v[2][1]; + zv[0] = v[0][2]; zv[1] = v[1][2]; zv[2] = v[2][2]; + } + else //use tensor columns as eigenvectors + { + for (i=0; i<3; i++) + { + xv[i] = tensor[i]; + yv[i] = tensor[i+3]; + zv[i] = tensor[i+6]; + } + w[0] = vtkMath::Normalize(xv); + w[1] = vtkMath::Normalize(yv); + w[2] = vtkMath::Normalize(zv); + } + + // compute scale factors + w[0] *= this->ScaleFactor; + w[1] *= this->ScaleFactor; + w[2] *= this->ScaleFactor; + + if ( this->ClampScaling ) + { + for (maxScale=0.0, i=0; i<3; i++) + { + if ( maxScale < fabs(w[i]) ) + { + maxScale = fabs(w[i]); + } + } + if ( maxScale > this->MaxScaleFactor ) + { + maxScale = this->MaxScaleFactor / maxScale; + for (i=0; i<3; i++) + { + w[i] *= maxScale; //preserve overall shape of glyph + } + } + } + + // normalization is postponed + + // make sure scale is okay (non-zero) and scale data + for (maxScale=0.0, i=0; i<3; i++) + { + if ( w[i] > maxScale ) + { + maxScale = w[i]; + } + } + if ( maxScale == 0.0 ) + { + maxScale = 1.0; + } + for (i=0; i<3; i++) + { + if ( w[i] == 0.0 ) + { + w[i] = maxScale * 1.0e-06; + } + } + + // Now do the real work for each "direction" + + for (dir=0; dir < numDirs; dir++) + { + eigen_dir = dir%(this->ThreeGlyphs?3:1); + symmetric_dir = dir/(this->ThreeGlyphs?3:1); + + // Remove previous scales ... + trans->Identity(); + + // translate Source to Input point + input->GetPoint(inPtId, x); + trans->Translate(x[0], x[1], x[2]); + + // normalized eigenvectors rotate object for eigen direction 0 + matrix->Element[0][0] = xv[0]; + matrix->Element[0][1] = yv[0]; + matrix->Element[0][2] = zv[0]; + matrix->Element[1][0] = xv[1]; + matrix->Element[1][1] = yv[1]; + matrix->Element[1][2] = zv[1]; + matrix->Element[2][0] = xv[2]; + matrix->Element[2][1] = yv[2]; + matrix->Element[2][2] = zv[2]; + trans->Concatenate(matrix); + + if (eigen_dir == 1) + { + trans->RotateZ(90.0); + } + + if (eigen_dir == 2) + { + trans->RotateY(-90.0); + } + + if (this->ThreeGlyphs) + { + trans->Scale(w[eigen_dir], this->ScaleFactor, this->ScaleFactor); + } + else + { + trans->Scale(w[0], w[1], w[2]); + } + + // Mirror second set to the symmetric position + if (symmetric_dir == 1) + { + trans->Scale(-1.,1.,1.); + } + + // if the eigenvalue is negative, shift to reverse direction. + // The && is there to ensure that we do not change the + // old behaviour of vtkTensorGlyphs (which only used one dir), + // in case there is an oriented glyph, e.g. an arrow. + if (w[eigen_dir] < 0 && numDirs > 1) + { + trans->Translate(-this->Length, 0., 0.); + } + + // multiply points (and normals if available) by resulting + // matrix + trans->TransformPoints(sourcePts,newPts); + + // Apply the transformation to a series of points, + // and append the results to outPts. + if ( newNormals ) + { + trans->TransformNormals(sourceNormals,newNormals); + } + + // Copy point data from source + if ( this->ColorGlyphs && inScalars && + (this->ColorMode == COLOR_BY_SCALARS) ) + { + s = inScalars->GetComponent(inPtId, 0); + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(ptIncr+i, &s); + } + } + else if (this->ColorGlyphs && + (this->ColorMode == COLOR_BY_EIGENVALUES) ) + { + // If ThreeGlyphs is false we use the first (largest) + // eigenvalue as scalar. + s = w[eigen_dir]; + for (i=0; i < numSourcePts; i++) + { + newScalars->InsertTuple(ptIncr+i, &s); + } + } + else + { + for (i=0; i < numSourcePts; i++) + { + outPD->CopyData(pd,i,ptIncr+i); + } + } + ptIncr += numSourcePts; + } + } + vtkDebugMacro(<<"Generated " << numPts <<" tensor glyphs"); + // + // Update output and release memory + // + delete [] pts; + + output->SetPoints(newPts); + newPts->Delete(); + + if ( newScalars ) + { + int idx = outPD->AddArray(newScalars); + outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + if ( newNormals ) + { + outPD->SetNormals(newNormals); + newNormals->Delete(); + } + + output->Squeeze(); + trans->Delete(); + matrix->Delete(); + + return 1; +} + +void vtkTensorGlyph::SetSourceConnection(int id, vtkAlgorithmOutput* algOutput) +{ + if (id < 0) + { + vtkErrorMacro("Bad index " << id << " for source."); + return; + } + + int numConnections = this->GetNumberOfInputConnections(1); + if (id < numConnections) + { + this->SetNthInputConnection(1, id, algOutput); + } + else if (id == numConnections && algOutput) + { + this->AddInputConnection(1, algOutput); + } + else if (algOutput) + { + vtkWarningMacro("The source id provided is larger than the maximum " + "source id, using " << numConnections << " instead."); + this->AddInputConnection(1, algOutput); + } +} + +void vtkTensorGlyph::SetSource(vtkPolyData *source) +{ + this->SetInput(1, source); +} + +vtkPolyData *vtkTensorGlyph::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkPolyData::SafeDownCast(this->GetExecutive()->GetInputData(1, 0)); +} + +int vtkTensorGlyph::FillInputPortInformation(int port, vtkInformation *info) +{ + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkTensorGlyph::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Source: " << this->GetSource() << "\n"; + os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n"); + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; + os << indent << "Extract Eigenvalues: " << (this->ExtractEigenvalues ? "On\n" : "Off\n"); + os << indent << "Color Glyphs: " << (this->ColorGlyphs ? "On\n" : "Off\n"); + os << indent << "Color Mode: " << this->ColorMode << endl; + os << indent << "Clamp Scaling: " << (this->ClampScaling ? "On\n" : "Off\n"); + os << indent << "Max Scale Factor: " << this->MaxScaleFactor << "\n"; + os << indent << "Three Glyphs: " << (this->ThreeGlyphs ? "On\n" : "Off\n"); + os << indent << "Symmetric: " << (this->Symmetric ? "On\n" : "Off\n"); + os << indent << "Length: " << this->Length << "\n"; +} diff --git a/Graphics/vtkTensorGlyph.h b/Graphics/vtkTensorGlyph.h new file mode 100644 index 0000000..119042a --- /dev/null +++ b/Graphics/vtkTensorGlyph.h @@ -0,0 +1,215 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTensorGlyph.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTensorGlyph - scale and orient glyph(s) according to tensor eigenvalues and eigenvectors +// .SECTION Description +// vtkTensorGlyph is a filter that copies a geometric representation +// (specified as polygonal data) to every input point. The geometric +// representation, or glyph, can be scaled and/or rotated according to +// the tensor at the input point. Scaling and rotation is controlled +// by the eigenvalues/eigenvectors of the tensor as follows. For each +// tensor, the eigenvalues (and associated eigenvectors) are sorted to +// determine the major, medium, and minor eigenvalues/eigenvectors. +// +// If the boolean variable ThreeGlyphs is not set the major eigenvalue +// scales the glyph in the x-direction, the medium in the y-direction, +// and the minor in the z-direction. Then, the glyph is rotated so +// that the glyph's local x-axis lies along the major eigenvector, +// y-axis along the medium eigenvector, and z-axis along the minor. +// +// If the boolean variable ThreeGlyphs is set three glyphs are produced, +// each of them oriented along an eigenvector and scaled according to the +// corresponding eigenvector. +// +// If the boolean variable Symmetric is set each glyph is mirrored (2 or 6 +// glyphs will be produced) +// +// The x-axis of the source glyph will correspond to the eigenvector +// on output. Point (0,0,0) in the source will be placed in the data point. +// Variable Length will normally correspond to the distance from the +// origin to the tip of the source glyph along the x-axis, +// but can be changed to produce other results when Symmetric is on, +// e.g. glyphs that do not touch or that overlap. +// +// Please note that when Symmetric is false it will generally be better +// to place the source glyph from (-0.5,0,0) to (0.5,0,0), i.e. centred +// at the origin. When symmetric is true the placement from (0,0,0) to +// (1,0,0) will generally be more convenient. +// +// A scale factor is provided to control the amount of scaling. Also, you +// can turn off scaling completely if desired. The boolean variable +// ClampScaling controls the maximum scaling (in conjunction with +// MaxScaleFactor.) This is useful in certain applications where +// singularities or large order of magnitude differences exist in +// the eigenvalues. +// +// If the boolean variable ColorGlyphs is set to true the glyphs are +// colored. The glyphs can be colored using the input scalars +// (SetColorModeToScalars), which is the default, or colored using the +// eigenvalues (SetColorModeToEigenvalues). +// +// Another instance variable, ExtractEigenvalues, has been provided to +// control extraction of eigenvalues/eigenvectors. If this boolean is +// false, then eigenvalues/eigenvectors are not extracted, and the +// columns of the tensor are taken as the eigenvectors (the norm of +// column, always positive, is the eigenvalue). This allows +// additional capability over the vtkGlyph3D object. That is, the +// glyph can be oriented in three directions instead of one. + +// .SECTION Thanks +// Thanks to Jose Paulo Moitinho de Almeida for enhancements. + +// .SECTION See Also +// vtkGlyph3D vtkPointLoad vtkHyperStreamline + +#ifndef __vtkTensorGlyph_h +#define __vtkTensorGlyph_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTensorGlyph : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTensorGlyph,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Construct object with scaling on and scale factor 1.0. Eigenvalues are + // extracted, glyphs are colored with input scalar data, and logarithmic + // scaling is turned off. + static vtkTensorGlyph *New(); + + // Description: + // Specify the geometry to copy to each point. Old style. See + // SetSourceConnection. + void SetSource(vtkPolyData *source); + vtkPolyData *GetSource(); + + // Description: + // Specify a source object at a specified table location. New style. + // Source connection is stored in port 1. This method is equivalent + // to SetInputConnection(1, id, outputPort). + void SetSourceConnection(int id, vtkAlgorithmOutput* algOutput); + void SetSourceConnection(vtkAlgorithmOutput* algOutput) + { + this->SetSourceConnection(0, algOutput); + } + + // Description: + // Turn on/off scaling of glyph with eigenvalues. + vtkSetMacro(Scaling,int); + vtkGetMacro(Scaling,int); + vtkBooleanMacro(Scaling,int); + + // Description: + // Specify scale factor to scale object by. (Scale factor always affects + // output even if scaling is off.) + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Turn on/off drawing three glyphs + vtkSetMacro(ThreeGlyphs,int); + vtkGetMacro(ThreeGlyphs,int); + vtkBooleanMacro(ThreeGlyphs,int); + + // Description: + // Turn on/off drawing a mirror of each glyph + vtkSetMacro(Symmetric,int); + vtkGetMacro(Symmetric,int); + vtkBooleanMacro(Symmetric,int); + + // Description: + // Set/Get the distance, along x, from the origin to the end of the + // source glyph. It is used to draw the symmetric glyphs. + vtkSetMacro(Length,double); + vtkGetMacro(Length,double); + + // Description: + // Turn on/off extraction of eigenvalues from tensor. + vtkSetMacro(ExtractEigenvalues,int); + vtkBooleanMacro(ExtractEigenvalues,int); + vtkGetMacro(ExtractEigenvalues,int); + + // Description: + // Turn on/off coloring of glyph with input scalar data or + // eigenvalues. If false, or input scalar data not present, then the + // scalars from the source object are passed through the filter. + vtkSetMacro(ColorGlyphs,int); + vtkGetMacro(ColorGlyphs,int); + vtkBooleanMacro(ColorGlyphs,int); + +//BTX + enum + { + COLOR_BY_SCALARS, + COLOR_BY_EIGENVALUES + }; +//ETX + + // Description: + // Set the color mode to be used for the glyphs. This can be set to + // use the input scalars (default) or to use the eigenvalues at the + // point. If ThreeGlyphs is set and the eigenvalues are chosen for + // coloring then each glyph is colored by the corresponding + // eigenvalue and if not set the color corresponding to the largest + // eigenvalue is chosen. The recognized values are: + // COLOR_BY_SCALARS = 0 (default) + // COLOR_BY_EIGENVALUES = 1 + vtkSetClampMacro(ColorMode, int, COLOR_BY_SCALARS, COLOR_BY_EIGENVALUES); + vtkGetMacro(ColorMode, int); + void SetColorModeToScalars() + {this->SetColorMode(COLOR_BY_SCALARS);}; + void SetColorModeToEigenvalues() + {this->SetColorMode(COLOR_BY_EIGENVALUES);}; + + // Description: + // Turn on/off scalar clamping. If scalar clamping is on, the ivar + // MaxScaleFactor is used to control the maximum scale factor. (This is + // useful to prevent uncontrolled scaling near singularities.) + vtkSetMacro(ClampScaling,int); + vtkGetMacro(ClampScaling,int); + vtkBooleanMacro(ClampScaling,int); + + // Description: + // Set/Get the maximum allowable scale factor. This value is compared to the + // combination of the scale factor times the eigenvalue. If less, the scale + // factor is reset to the MaxScaleFactor. The boolean ClampScaling has to + // be "on" for this to work. + vtkSetMacro(MaxScaleFactor,double); + vtkGetMacro(MaxScaleFactor,double); + +protected: + vtkTensorGlyph(); + ~vtkTensorGlyph(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int Scaling; // Determine whether scaling of geometry is performed + double ScaleFactor; // Scale factor to use to scale geometry + int ExtractEigenvalues; // Boolean controls eigenfunction extraction + int ColorGlyphs; // Boolean controls coloring with input scalar data + int ColorMode; // The coloring mode to use for the glyphs. + int ClampScaling; // Boolean controls whether scaling is clamped. + double MaxScaleFactor; // Maximum scale factor (ScaleFactor*eigenvalue) + int ThreeGlyphs; // Boolean controls drawing 1 or 3 glyphs + int Symmetric; // Boolean controls drawing a "mirror" of each glyph + double Length; // Distance, in x, from the origin to the end of the glyph +private: + vtkTensorGlyph(const vtkTensorGlyph&); // Not implemented. + void operator=(const vtkTensorGlyph&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTextSource.cxx b/Graphics/vtkTextSource.cxx new file mode 100644 index 0000000..3738ad5 --- /dev/null +++ b/Graphics/vtkTextSource.cxx @@ -0,0 +1,452 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextSource.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkTextSource, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkTextSource); + +#define vtkfont_width 9 +#define vtkfont_row_width 864 +#define vtkfont_height 15 +static unsigned char vtkfont_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xe0,0x00,0x10,0x90,0x00,0x00,0x40,0x88,0x03,0x1c,0x10,0x08,0x00, + 0x00,0x00,0x00,0x00,0x00,0x20,0x1c,0x10,0xf8,0xf8,0x03,0xe2,0x0f,0x8f,0x3f, + 0x3e,0x7c,0x00,0x00,0x00,0x02,0x80,0x00,0x1f,0x3e,0x10,0xfc,0xf0,0xf1,0xe3, + 0xcf,0x1f,0x1f,0x41,0x7c,0xe0,0x09,0x12,0x20,0x48,0x10,0x1f,0x3f,0x7c,0xfc, + 0xf0,0xf1,0x27,0x48,0x90,0x20,0x41,0x82,0xfc,0xe1,0x11,0xc0,0x03,0x02,0x00, + 0x0e,0x00,0x04,0x00,0x00,0x04,0x00,0x0e,0x00,0x01,0x00,0x00,0x08,0xc0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x80,0x83,0xe0,0x80,0x11,0xe0,0x00,0x10,0x90,0x90,0x80,0xa0,0x44,0x04,0x0c, + 0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x22,0x18,0x04,0x01,0x02,0x23, + 0x80,0x00,0x20,0x41,0x82,0x00,0x00,0x00,0x01,0x00,0x81,0x20,0x41,0x28,0x08, + 0x09,0x22,0x44,0x80,0x80,0x20,0x41,0x10,0x80,0x08,0x11,0x20,0x48,0x90,0x20, + 0x41,0x82,0x04,0x09,0x82,0x20,0x48,0x90,0x20,0x41,0x82,0x00,0x21,0x20,0x00, + 0x02,0x05,0x00,0x0c,0x00,0x04,0x00,0x00,0x04,0x00,0x11,0x00,0x01,0x10,0x80, + 0x08,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x40,0x80,0x00,0x41,0x12,0xe0,0x00,0x10,0x90,0x90,0xe0,0xa3, + 0x44,0x04,0x02,0x08,0x10,0x00,0x40,0x00,0x00,0x00,0x00,0x10,0x41,0x14,0x04, + 0x01,0x81,0x22,0x40,0x00,0x20,0x41,0x82,0x00,0x00,0x80,0x00,0x00,0x82,0x20, + 0x41,0x44,0x08,0x09,0x20,0x44,0x80,0x80,0x00,0x41,0x10,0x80,0x88,0x10,0x60, + 0xcc,0x90,0x20,0x41,0x82,0x04,0x09,0x80,0x20,0x48,0x90,0x20,0x22,0x44,0x80, + 0x20,0x20,0x00,0x82,0x08,0x00,0x10,0x00,0x04,0x00,0x00,0x04,0x00,0x11,0x00, + 0x01,0x00,0x00,0x08,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x00,0x41,0x0c,0xe0,0x00,0x10,0x00, + 0xf8,0x91,0x40,0x42,0x04,0x00,0x04,0x20,0x88,0x40,0x00,0x00,0x00,0x00,0x08, + 0x41,0x10,0x00,0x81,0x40,0xa2,0x47,0x00,0x10,0x41,0x82,0x20,0x40,0x40,0x00, + 0x00,0x04,0x20,0x79,0x82,0x08,0x09,0x20,0x44,0x80,0x80,0x00,0x41,0x10,0x80, + 0x48,0x10,0xa0,0x4a,0x91,0x20,0x41,0x82,0x04,0x09,0x80,0x20,0x88,0x88,0x20, + 0x14,0x28,0x40,0x20,0x40,0x00,0x42,0x10,0x00,0x00,0x7c,0xf4,0xf0,0xe1,0xc5, + 0x07,0x01,0x2f,0x3d,0x18,0xe0,0x08,0x82,0xe0,0x46,0x0f,0x1f,0x3d,0xbc,0xe4, + 0xf0,0xf1,0x23,0x44,0x90,0x20,0x41,0x42,0xfc,0x81,0x80,0x80,0x00,0x00,0xe0, + 0x00,0x10,0x00,0x90,0x90,0x00,0x81,0x03,0x00,0x04,0x20,0x50,0x40,0x00,0x00, + 0x00,0x00,0x04,0x41,0x10,0x80,0xc0,0x21,0x62,0x48,0x0f,0x08,0x3e,0xc2,0x70, + 0xe0,0x20,0xe0,0x0f,0x08,0x10,0x45,0x82,0xf8,0x08,0x20,0xc4,0x83,0x87,0x00, + 0x7f,0x10,0x80,0x38,0x10,0xa0,0x4a,0x92,0x20,0x3f,0x82,0xfc,0xf0,0x81,0x20, + 0x88,0x88,0x24,0x08,0x10,0x20,0x20,0x80,0x00,0x02,0x00,0x00,0x00,0x80,0x0c, + 0x09,0x12,0x26,0x08,0x81,0x10,0x43,0x10,0x80,0x88,0x81,0x20,0xc9,0x90,0x20, + 0x43,0xc2,0x18,0x09,0x42,0x20,0x44,0x90,0x20,0x22,0x42,0x80,0x60,0x80,0x00, + 0x03,0x00,0xe0,0x00,0x10,0x00,0x90,0xe0,0x03,0x41,0x04,0x00,0x04,0x20,0xfc, + 0xf9,0x03,0xe0,0x0f,0x00,0x04,0x41,0x10,0x40,0x00,0x12,0x02,0xc8,0x10,0x04, + 0x41,0xbc,0x20,0x40,0x20,0x00,0x00,0x08,0x08,0x65,0x82,0x08,0x09,0x20,0x44, + 0x80,0x80,0x38,0x41,0x10,0x80,0x28,0x10,0x20,0x49,0x94,0x20,0x01,0x82,0x24, + 0x00,0x82,0x20,0x88,0x88,0x24,0x08,0x10,0x10,0x20,0x80,0x00,0x02,0x00,0x00, + 0x00,0x80,0x04,0x09,0x10,0x24,0xc8,0x87,0x10,0x41,0x10,0x80,0x68,0x80,0x20, + 0x49,0x90,0x20,0x41,0x82,0x08,0x09,0x40,0x20,0x84,0x88,0x24,0x14,0x42,0x40, + 0x60,0x80,0x00,0x03,0x00,0xe0,0x00,0x10,0x00,0xf8,0x81,0x84,0x44,0x14,0x00, + 0x04,0x20,0x50,0x40,0x00,0x00,0x00,0x00,0x02,0x41,0x10,0x30,0x00,0xf2,0x07, + 0x48,0x10,0x02,0x41,0x80,0x00,0x00,0x40,0x00,0x00,0x04,0x04,0x59,0xfe,0x08, + 0x09,0x20,0x44,0x80,0x80,0x20,0x41,0x10,0x80,0x48,0x10,0x20,0x49,0x98,0x20, + 0x01,0x82,0x44,0x00,0x82,0x20,0x08,0x85,0x24,0x14,0x10,0x08,0x20,0x00,0x01, + 0x02,0x00,0x00,0x00,0xfc,0x04,0x09,0x10,0xe4,0x0f,0x81,0x10,0x41,0x10,0x80, + 0x18,0x80,0x20,0x49,0x90,0x20,0x41,0x82,0x08,0xf0,0x41,0x20,0x84,0x88,0x24, + 0x08,0x42,0x20,0x80,0x80,0x80,0x00,0x00,0xe0,0x00,0x10,0x00,0x90,0x80,0x44, + 0x4a,0x08,0x00,0x08,0x10,0x88,0x40,0x00,0x00,0x00,0x00,0x01,0x41,0x10,0x08, + 0x00,0x02,0x02,0x48,0x10,0x02,0x41,0x80,0x00,0x00,0x80,0xe0,0x0f,0x02,0x04, + 0x01,0x82,0x08,0x09,0x20,0x44,0x80,0x80,0x20,0x41,0x10,0x80,0x88,0x10,0x20, + 0x48,0x90,0x20,0x01,0x92,0x84,0x00,0x82,0x20,0x08,0x85,0x24,0x22,0x10,0x04, + 0x20,0x00,0x02,0x02,0x00,0x00,0x00,0x82,0x04,0x09,0x10,0x24,0x00,0x01,0x0f, + 0x41,0x10,0x80,0x68,0x80,0x20,0x49,0x90,0x20,0x41,0x82,0x08,0x00,0x42,0x20, + 0x04,0x85,0x24,0x14,0x42,0x10,0x40,0x80,0x00,0x01,0x00,0xe0,0x00,0x00,0x00, + 0x90,0xe0,0x43,0x4a,0x0c,0x00,0x08,0x10,0x00,0x40,0xc0,0x01,0x00,0x02,0x01, + 0x22,0x10,0x04,0x08,0x02,0x22,0x48,0x10,0x01,0x41,0x40,0x20,0xe0,0x00,0x01, + 0x00,0x01,0x00,0x01,0x82,0x08,0x09,0x22,0x44,0x80,0x80,0x20,0x41,0x10,0x84, + 0x08,0x11,0x20,0x48,0x90,0x20,0x01,0xa2,0x04,0x09,0x82,0x20,0x08,0x85,0x2a, + 0x41,0x10,0x04,0x20,0x00,0x02,0x02,0x00,0x00,0x00,0xc2,0x0c,0x09,0x12,0x26, + 0x00,0x81,0x00,0x41,0x10,0x80,0x88,0x81,0x20,0x49,0x90,0x20,0x43,0xc2,0x08, + 0x08,0x42,0x24,0x04,0x85,0x2a,0x22,0x62,0x08,0x40,0x80,0x00,0x01,0x00,0xe0, + 0x00,0x10,0x00,0x00,0x80,0x20,0x84,0x13,0x00,0x10,0x08,0x00,0x00,0xc0,0x00, + 0x00,0x87,0x00,0x1c,0x7c,0xfc,0xf1,0x01,0xc2,0x87,0x0f,0x01,0x3e,0x3c,0x70, + 0x60,0x00,0x02,0x80,0x00,0x04,0x3e,0x82,0xfc,0xf0,0xf1,0xe3,0x8f,0x00,0x1f, + 0x41,0x7c,0x78,0x08,0xf2,0x27,0x48,0x10,0x1f,0x01,0x7c,0x04,0xf1,0x81,0xc0, + 0x07,0x02,0x11,0x41,0x10,0xfc,0xe1,0x01,0xc4,0x03,0x00,0x00,0x00,0xbc,0xf4, + 0xf0,0xe1,0xc5,0x07,0x01,0x1f,0x41,0x7c,0x84,0x08,0xe2,0x23,0x48,0x10,0x1f, + 0x3d,0xbc,0x08,0xf0,0x81,0xc3,0x0b,0x02,0x11,0x41,0x5c,0xfc,0x81,0x83,0xe0, + 0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x3f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x84,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x84, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f, + 0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0 + }; + +// Construct object with no string set and backing enabled. +vtkTextSource::vtkTextSource() +{ + this->Text = NULL; + this->Backing = 1; + this->ForegroundColor[0] = 1.0; + this->ForegroundColor[1] = 1.0; + this->ForegroundColor[2] = 1.0; + this->ForegroundColor[3] = 1.0; + this->BackgroundColor[0] = 0.0; + this->BackgroundColor[1] = 0.0; + this->BackgroundColor[2] = 0.0; + this->BackgroundColor[3] = 1.0; + + this->SetNumberOfInputPorts(0); +} + +vtkTextSource::~vtkTextSource() +{ + if (this->Text) + { + delete [] this->Text; + } +} + +int vtkTextSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int row, col; + vtkPoints *newPoints; + vtkCellArray *newPolys; + vtkUnsignedCharArray *newScalars; + double x[3]; + int pos = 0; + int pixelPos; + vtkIdType pts[5]; + vtkIdType numPolys = 0; + int acol; + int drawingWhite = 0; + int drawingBlack = 0; + unsigned char white[4]; + unsigned char black[4]; + + if (this->Text == NULL) + { + vtkErrorMacro (<< "Text is not set!"); + return 1; + } + + // convert colors to unsigned char + for (int i = 0; i < 4; i++) + { + white[i] = (unsigned char) (this->ForegroundColor[i] * 255.0); + black[i] = (unsigned char) (this->BackgroundColor[i] * 255.0); + } + + // Set things up; allocate memory + x[2] = 0; + + newPoints = vtkPoints::New(); + newPolys = vtkCellArray::New(); + newScalars = vtkUnsignedCharArray::New(); + newScalars->SetNumberOfComponents(4); + + // Create Text + while (this->Text[pos]) + { + if (this->Text[pos] != 32) + { + for (col = 0; col < vtkfont_width; col++) + { + acol = (this->Text[pos] - 32)*vtkfont_width + col - 1; + for (row = 0; row < vtkfont_height; row++) + { + pixelPos = acol + row*vtkfont_row_width; + if (vtkfont_bits[pixelPos/8] & (0x01 << pixelPos%8)) + { + if (drawingBlack) + { + x[0] = pos*vtkfont_width + col + 1; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + x[0] = pos*vtkfont_width + col; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + pts[0] = numPolys*4; + pts[1] = numPolys*4 + 1; + pts[2] = numPolys*4 + 2; + pts[3] = numPolys*4 + 3; + newPolys->InsertNextCell(4,pts); + numPolys++; + drawingBlack = 0; + } + if (!drawingWhite) + { + x[0] = pos*vtkfont_width + col; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(white[0]); + newScalars->InsertNextValue(white[1]); + newScalars->InsertNextValue(white[2]); + newScalars->InsertNextValue(white[3]); + + x[0] = pos*vtkfont_width + col + 1; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(white[0]); + newScalars->InsertNextValue(white[1]); + newScalars->InsertNextValue(white[2]); + newScalars->InsertNextValue(white[3]); + drawingWhite = 1; + } + } + // if the pixel is not set the close up the rectangle + else + { + if (drawingWhite) + { + x[0] = pos*vtkfont_width + col + 1; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(white[0]); + newScalars->InsertNextValue(white[1]); + newScalars->InsertNextValue(white[2]); + newScalars->InsertNextValue(white[3]); + + x[0] = pos*vtkfont_width + col; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(white[0]); + newScalars->InsertNextValue(white[1]); + newScalars->InsertNextValue(white[2]); + newScalars->InsertNextValue(white[3]); + + pts[0] = numPolys*4; + pts[1] = numPolys*4 + 1; + pts[2] = numPolys*4 + 2; + pts[3] = numPolys*4 + 3; + newPolys->InsertNextCell(4,pts); + numPolys++; + drawingWhite = 0; + } + if (!drawingBlack && this->Backing) + { + x[0] = pos*vtkfont_width + col; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + x[0] = pos*vtkfont_width + col + 1; + x[1] = vtkfont_height - row; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + drawingBlack = 1; + } + } + } + // if we finished up a row but are still drawing close it up + if (drawingWhite) + { + x[0] = pos*vtkfont_width + col + 1; + x[1] = 0; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(white[0]); + newScalars->InsertNextValue(white[1]); + newScalars->InsertNextValue(white[2]); + newScalars->InsertNextValue(white[3]); + + x[0] = pos*vtkfont_width + col; + x[1] = 0; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(white[0]); + newScalars->InsertNextValue(white[1]); + newScalars->InsertNextValue(white[2]); + newScalars->InsertNextValue(white[3]); + + pts[0] = numPolys*4; + pts[1] = numPolys*4 + 1; + pts[2] = numPolys*4 + 2; + pts[3] = numPolys*4 + 3; + newPolys->InsertNextCell(4,pts); + numPolys++; + drawingWhite = 0; + } + if (drawingBlack) + { + x[0] = pos*vtkfont_width + col + 1; + x[1] = 0; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + x[0] = pos*vtkfont_width + col; + x[1] = 0; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + pts[0] = numPolys*4; + pts[1] = numPolys*4 + 1; + pts[2] = numPolys*4 + 2; + pts[3] = numPolys*4 + 3; + newPolys->InsertNextCell(4,pts); + numPolys++; + drawingBlack = 0; + } + } + } + else + { + // draw a black square for a space + if (this->Backing) + { + x[0] = pos*vtkfont_width; + x[1] = vtkfont_height; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + x[0] = pos*vtkfont_width + vtkfont_width; + x[1] = vtkfont_height; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + x[0] = pos*vtkfont_width + vtkfont_width; + x[1] = 0; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + x[0] = pos*vtkfont_width; + x[1] = 0; + newPoints->InsertNextPoint(x); + newScalars->InsertNextValue(black[0]); + newScalars->InsertNextValue(black[1]); + newScalars->InsertNextValue(black[2]); + newScalars->InsertNextValue(black[3]); + + pts[0] = numPolys*4; + pts[1] = numPolys*4 + 1; + pts[2] = numPolys*4 + 2; + pts[3] = numPolys*4 + 3; + newPolys->InsertNextCell(4,pts); + numPolys++; + } + } + pos++; + } +// +// Update ourselves and release memory +// + output->SetPoints(newPoints); + newPoints->Delete(); + + output->GetPointData()->SetScalars(newScalars); + newScalars->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +void vtkTextSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Text: " << (this->Text ? this->Text : "(none)") << "\n"; + os << indent << "Background Drawn: " << (this->Backing ? "On\n" : "Off\n"); + os << indent << "ForegroundColor: (" << this->ForegroundColor[0] << ", " + << this->ForegroundColor[1] << ", " << this->ForegroundColor[2] << ")\n"; + os << indent << "BackgroundColor: (" << this->BackgroundColor[0] << ", " + << this->BackgroundColor[1] << ", " << this->BackgroundColor[2] << ")\n"; +} diff --git a/Graphics/vtkTextSource.h b/Graphics/vtkTextSource.h new file mode 100644 index 0000000..ade938c --- /dev/null +++ b/Graphics/vtkTextSource.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextSource - create polygonal text +// .SECTION Description +// vtkTextSource converts a text string into polygons. This way you can +// insert text into your renderings. It uses the 9x15 font from X Windows. +// You can specify if you want the background to be drawn or not. The +// characters are formed by scan converting the raster font into +// quadrilaterals. Colors are assigned to the letters using scalar data. +// To set the color of the characters with the source's actor property, set +// BackingOff on the text source and ScalarVisibilityOff on the associated +// vtkPolyDataMapper. Then, the color can be set using the associated actor's +// property. +// +// vtkVectorText generates higher quality polygonal representations of +// characters. + +// .SECTION See Also +// vtkVectorText + +#ifndef __vtkTextSource_h +#define __vtkTextSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTextSource : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTextSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with no string set and backing enabled. + static vtkTextSource *New(); + + // Description: + // Set/Get the text to be drawn. + vtkSetStringMacro(Text); + vtkGetStringMacro(Text); + + // Description: + // Controls whether or not a background is drawn with the text. + vtkSetMacro(Backing,int); + vtkGetMacro(Backing,int); + vtkBooleanMacro(Backing,int); + + // Description: + // Set/Get the foreground color. Default is white (1,1,1). ALpha is always 1. + vtkSetVector3Macro(ForegroundColor,double); + vtkGetVectorMacro(ForegroundColor,double,3); + + // Description: + // Set/Get the background color. Default is black (0,0,0). Alpha is always 1. + vtkSetVector3Macro(BackgroundColor,double); + vtkGetVectorMacro(BackgroundColor,double,3); + +protected: + vtkTextSource(); + ~vtkTextSource(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + char *Text; + int Backing; + double ForegroundColor[4]; + double BackgroundColor[4]; +private: + vtkTextSource(const vtkTextSource&); // Not implemented. + void operator=(const vtkTextSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTextureMapToCylinder.cxx b/Graphics/vtkTextureMapToCylinder.cxx new file mode 100644 index 0000000..0ae03d9 --- /dev/null +++ b/Graphics/vtkTextureMapToCylinder.cxx @@ -0,0 +1,196 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextureMapToCylinder.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextureMapToCylinder.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkMath.h" +#include "vtkOBBTree.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkTextureMapToCylinder, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkTextureMapToCylinder); + +// Create object with cylinder axis parallel to z-axis (points (0,0,-0.5) +// and (0,0,0.5)). The PreventSeam ivar is set to true. The cylinder is +// automatically generated. +vtkTextureMapToCylinder::vtkTextureMapToCylinder() +{ + this->Point1[0] = 0.0; + this->Point1[1] = 0.0; + this->Point1[2] = -0.5; + + this->Point2[0] = 0.0; + this->Point2[1] = 0.0; + this->Point2[2] = 0.5; + + this->AutomaticCylinderGeneration = 1; + this->PreventSeam = 1; +} + +int vtkTextureMapToCylinder::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkFloatArray *newTCoords; + vtkIdType numPts=input->GetNumberOfPoints(); + vtkIdType ptId; + int i; + double x[3], tc[2], thetaX, thetaY, closest[3], v[3]; + double axis[3], vP[3], vec[3]; + + vtkDebugMacro(<<"Generating Cylindrical Texture Coordinates"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( numPts < 1 ) + { + vtkErrorMacro(<<"Can't generate texture coordinates without points"); + return 1; + } + + if ( this->AutomaticCylinderGeneration ) + { + vtkPoints *pts=vtkPoints::New(); pts->SetNumberOfPoints(numPts); + double corner[3], max[3], mid[3], min[3], size[3], l; + vtkOBBTree *OBB = vtkOBBTree::New(); + + for ( ptId=0; ptId < numPts; ptId++ ) + { + input->GetPoint(ptId, x); + pts->SetPoint(ptId,x); + } + + OBB->ComputeOBB(pts,corner,max,mid,min,size); + pts->Delete(); + OBB->Delete(); + + for ( i=0; i < 3; i++) + { + l = (mid[i] + min[i])/2.0; + this->Point1[i] = corner[i] + l; + this->Point2[i] = corner[i] + max[i] + l; + } + + vtkDebugMacro(<<"Cylinder axis computed as \tPoint1: (" + << this->Point1[0] <<", " << this->Point1[1] <<", " + << this->Point1[2] <<")\n\t\t\t\tPoint2: (" + << this->Point2[0] <<", " << this->Point2[1] <<", " + << this->Point2[2] <<")"); + } + + //compute axis which is theta (angle measure) origin + for ( i=0; i < 3; i++ ) + { + axis[i] = this->Point2[i] - this->Point1[i]; + } + if ( vtkMath::Norm(axis) == 0.0 ) + { + vtkErrorMacro(<<"Bad cylinder axis"); + return 1; + } + + v[0] = 1.0; v[1] = v[2] = 0.0; + vtkMath::Cross(axis,v,vP); + if ( vtkMath::Norm(vP) == 0.0 ) + {//must be prependicular + v[1] = 1.0; v[0] = v[2] = 0.0; + vtkMath::Cross(axis,v,vP); + } + vtkMath::Cross(vP,axis,vec); + if ( vtkMath::Normalize(vec) == 0.0 ) + { + vtkErrorMacro(<<"Bad cylinder axis"); + return 1; + } + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*numPts); + + //loop over all points computing spherical coordinates + for ( ptId=0; ptId < numPts; ptId++ ) + { + input->GetPoint(ptId, x); + vtkLine::DistanceToLine(x,this->Point1,this->Point2,tc[1],closest); + + for (i=0; i < 3; i++) + { + v[i] = x[i] - closest[i]; + } + vtkMath::Normalize(v); + + thetaX = acos ((double)vtkMath::Dot(v,vec)); + vtkMath::Cross(vec,v,vP); + thetaY = vtkMath::Dot(axis,vP); //not really interested in angle, just +/- sign + + if ( this->PreventSeam ) + { + tc[0] = thetaX / vtkMath::Pi(); + } + else + { + tc[0] = thetaX / (2.0*vtkMath::Pi()); + if ( thetaY < 0.0 ) + { + tc[0] = 1.0 - tc[0]; + } + } + + newTCoords->InsertTuple(ptId,tc); + } + + output->GetPointData()->CopyTCoordsOff(); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + return 1; +} + +void vtkTextureMapToCylinder::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Automatic Cylinder Generation: " << + (this->AutomaticCylinderGeneration ? "On\n" : "Off\n"); + os << indent << "Prevent Seam: " << + (this->PreventSeam ? "On\n" : "Off\n"); + os << indent << "Point1: (" << this->Point1[0] << ", " + << this->Point1[1] << ", " + << this->Point1[2] << ")\n"; + os << indent << "Point2: (" << this->Point2[0] << ", " + << this->Point2[1] << ", " + << this->Point2[2] << ")\n"; +} diff --git a/Graphics/vtkTextureMapToCylinder.h b/Graphics/vtkTextureMapToCylinder.h new file mode 100644 index 0000000..df74ae3 --- /dev/null +++ b/Graphics/vtkTextureMapToCylinder.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextureMapToCylinder.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextureMapToCylinder - generate texture coordinates by mapping points to cylinder +// .SECTION Description +// vtkTextureMapToCylinder is a filter that generates 2D texture coordinates +// by mapping input dataset points onto a cylinder. The cylinder can either be +// user specified or generated automatically. (The cylinder is generated +// automatically by computing the axis of the cylinder.) Note that the +// generated texture coordinates for the s-coordinate ranges from (0-1) +// (corresponding to angle of 0->360 around axis), while the mapping of +// the t-coordinate is controlled by the projection of points along the axis. +// +// To specify a cylinder manually, you must provide two points that +// define the axis of the cylinder. The length of the axis will affect the +// t-coordinates. +// +// A special ivar controls how the s-coordinate is generated. If PreventSeam +// is set to true, the s-texture varies from 0->1 and then 1->0 (corresponding +// to angles of 0->180 and 180->360). + +// .SECTION Caveats +// Since the resulting texture s-coordinate will lie between (0,1), and the +// origin of the texture coordinates is not user-controllable, you may want +// to use the class vtkTransformTexture to linearly scale and shift the origin +// of the texture coordinates. + +// .SECTION See Also +// vtkTextureMapToPlane vtkTextureMapToSphere vtkTextureMapToBox +// vtkTransformTexture vtkThresholdTextureCoords + +#ifndef __vtkTextureMapToCylinder_h +#define __vtkTextureMapToCylinder_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTextureMapToCylinder : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTextureMapToCylinder,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create object with cylinder axis parallel to z-axis (points (0,0,-0.5) + // and (0,0,0.5)). The PreventSeam ivar is set to true. The cylinder is + // automatically generated. + static vtkTextureMapToCylinder *New(); + + // Description: + // Specify the first point defining the cylinder axis, + vtkSetVector3Macro(Point1,double); + vtkGetVectorMacro(Point1,double,3); + + // Description: + // Specify the second point defining the cylinder axis, + vtkSetVector3Macro(Point2,double); + vtkGetVectorMacro(Point2,double,3); + + // Description: + // Turn on/off automatic cylinder generation. This means it automatically + // finds the cylinder center and axis. + vtkSetMacro(AutomaticCylinderGeneration,int); + vtkGetMacro(AutomaticCylinderGeneration,int); + vtkBooleanMacro(AutomaticCylinderGeneration,int); + + // Description: + // Control how the texture coordinates are generated. If PreventSeam is + // set, the s-coordinate ranges from 0->1 and 1->0 corresponding to the + // angle variation from 0->180 and 180->0. Otherwise, the s-coordinate + // ranges from 0->1 from 0->360 degrees. + vtkSetMacro(PreventSeam,int); + vtkGetMacro(PreventSeam,int); + vtkBooleanMacro(PreventSeam,int); + +protected: + vtkTextureMapToCylinder(); + ~vtkTextureMapToCylinder() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Point1[3]; + double Point2[3]; + int AutomaticCylinderGeneration; + int PreventSeam; + +private: + vtkTextureMapToCylinder(const vtkTextureMapToCylinder&); // Not implemented. + void operator=(const vtkTextureMapToCylinder&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkTextureMapToPlane.cxx b/Graphics/vtkTextureMapToPlane.cxx new file mode 100644 index 0000000..6b59d22 --- /dev/null +++ b/Graphics/vtkTextureMapToPlane.cxx @@ -0,0 +1,340 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextureMapToPlane.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextureMapToPlane.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkTextureMapToPlane, "$Revision: 1.49 $"); +vtkStandardNewMacro(vtkTextureMapToPlane); + +// Construct with s,t range=(0,1) and automatic plane generation turned on. +vtkTextureMapToPlane::vtkTextureMapToPlane() +{ + // all zero - indicates that using normal is preferred and automatic is off + this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.0; + this->Point1[0] = this->Point1[1] = this->Point1[2] = 0.0; + this->Point2[0] = this->Point2[1] = this->Point2[2] = 0.0; + + this->Normal[0] = 0.0; + this->Normal[1] = 0.0; + this->Normal[2] = 1.0; + + this->SRange[0] = 0.0; + this->SRange[1] = 1.0; + + this->TRange[0] = 0.0; + this->TRange[1] = 1.0; + + this->AutomaticPlaneGeneration = 1; +} + +int vtkTextureMapToPlane::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double tcoords[2]; + vtkIdType numPts; + vtkFloatArray *newTCoords; + vtkIdType i; + int j; + double *bounds; + double proj, minProj, axis[3], sAxis[3], tAxis[3]; + int dir = 0; + double s, t, sSf, tSf, p[3]; + int abort=0; + vtkIdType progressInterval; + + vtkDebugMacro(<<"Generating texture coordinates!"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( (numPts=input->GetNumberOfPoints()) < 3 && + this->AutomaticPlaneGeneration ) + { + vtkErrorMacro(<< "Not enough points for automatic plane mapping\n"); + return 1; + } + + // Allocate texture data + // + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->SetNumberOfTuples(numPts); + progressInterval = numPts/20 + 1; + + // Compute least squares plane if on automatic mode; otherwise use + // normal specified or plane specified + // + if ( this->AutomaticPlaneGeneration && + (this->Origin[0] == 0.0 && this->Origin[1] == 0.0 && + this->Origin[2] == 0.0 && this->Point1[0] == 0.0 && + this->Point1[1] == 0.0 && this->Point1[2] == 0.0) ) + { + if ( this->AutomaticPlaneGeneration ) + { + this->ComputeNormal(output); + } + + vtkMath::Normalize (this->Normal); + + // Now project each point onto plane generating s,t texture coordinates + // + // Create local s-t coordinate system. Need to find the two axes on + // the plane and encompassing all the points. Hence use the bounding + // box as a reference. + // + for (minProj=1.0, i=0; i<3; i++) + { + axis[0] = axis[1] = axis[2] = 0.0; + axis[i] = 1.0; + if ( (proj=fabs(vtkMath::Dot(this->Normal,axis))) < minProj ) + { + minProj = proj; + dir = i; + } + } + axis[0] = axis[1] = axis[2] = 0.0; + axis[dir] = 1.0; + + vtkMath::Cross (this->Normal, axis, tAxis); + vtkMath::Normalize (tAxis); + + vtkMath::Cross (tAxis, this->Normal, sAxis); + + // Construct projection matrices + // + // Arrange s-t axes so that parametric location of points will fall + // between s_range and t_range. Simplest to do by projecting maximum + // corner of bounding box unto plane and backing out scale factors. + // + bounds = output->GetBounds(); + for (i=0; i<3; i++) + { + axis[i] = bounds[2*i+1] - bounds[2*i]; + } + + s = vtkMath::Dot(sAxis,axis); + t = vtkMath::Dot(tAxis,axis); + + sSf = (this->SRange[1] - this->SRange[0]) / s; + tSf = (this->TRange[1] - this->TRange[0]) / t; + + // Now can loop over all points, computing parametric coordinates. + // + for (i=0; iUpdateProgress((double)i/numPts); + abort = this->GetAbortExecute(); + } + + output->GetPoint(i, p); + for (j=0; j<3; j++) + { + axis[j] = p[j] - bounds[2*j]; + } + + tcoords[0] = this->SRange[0] + vtkMath::Dot(sAxis,axis) * sSf; + tcoords[1] = this->TRange[0] + vtkMath::Dot(tAxis,axis) * tSf; + + newTCoords->SetTuple(i,tcoords); + } + } //compute plane and/or parametric range + + else //use the axes specified + { + double num, sDenom, tDenom; + + for ( i=0; i < 3; i++ ) //compute axes + { + sAxis[i] = this->Point1[i] - this->Origin[i]; + tAxis[i] = this->Point2[i] - this->Origin[i]; + } + + sDenom = vtkMath::Dot(sAxis,sAxis); + tDenom = vtkMath::Dot(tAxis,tAxis); + + if ( sDenom == 0.0 || tDenom == 0.0 ) + { + vtkErrorMacro("Bad plane definition"); + sDenom = tDenom = 1.0; + } + + // compute s-t coordinates + for (i=0; i < numPts && !abort; i++) + { + if ( !(i % progressInterval) ) + { + this->UpdateProgress((double)i/numPts); + abort = this->GetAbortExecute(); + } + output->GetPoint(i, p); + for (j=0; j<3; j++) + { + axis[j] = p[j] - this->Origin[j]; + } + + //s-coordinate + num = sAxis[0]*axis[0] + sAxis[1]*axis[1] + sAxis[2]*axis[2]; + tcoords[0] = num / sDenom; + + //t-coordinate + num = tAxis[0]*axis[0] + tAxis[1]*axis[1] + tAxis[2]*axis[2]; + tcoords[1] = num / tDenom; + + newTCoords->SetTuple(i,tcoords); + } + } + + // Update ourselves + // + output->GetPointData()->CopyTCoordsOff(); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + return 1; +} + +#define VTK_TOLERANCE 1.0e-03 + +void vtkTextureMapToPlane::ComputeNormal(vtkDataSet *output) +{ + vtkIdType numPts=output->GetNumberOfPoints(); + double m[9], v[3], x[3]; + vtkIdType ptId; + int dir = 0, i; + double length, w, *c1, *c2, *c3, det; + double *bounds; + + // First thing to do is to get an initial normal and point to define + // the plane. Then, use this information to construct better + // matrices. If problem occurs, then the point and plane becomes the + // fallback value. + // + // Get minimum width of bounding box. + bounds = output->GetBounds(); + length = output->GetLength(); + + for (w=length, i=0; i<3; i++) + { + this->Normal[i] = 0.0; + if ( (bounds[2*i+1] - bounds[2*i]) < w ) + { + dir = i; + w = bounds[2*i+1] - bounds[2*i]; + } + } + + // If the bounds is perpendicular to one of the axes, then can + // quickly compute normal. + // + this->Normal[dir] = 1.0; + if ( w <= (length*VTK_TOLERANCE) ) + { + return; + } + + // Need to compute least squares approximation. Depending on major + // normal direction (dir), construct matrices appropriately. + // + // Compute 3x3 least squares matrix + v[0] = v[1] = v[2] = 0.0; + for (i=0; i<9; i++) + { + m[i] = 0.0; + } + + for (ptId=0; ptId < numPts; ptId++) + { + output->GetPoint(ptId, x); + + v[0] += x[0]*x[2]; + v[1] += x[1]*x[2]; + v[2] += x[2]; + + m[0] += x[0]*x[0]; + m[1] += x[0]*x[1]; + m[2] += x[0]; + + m[3] += x[0]*x[1]; + m[4] += x[1]*x[1]; + m[5] += x[1]; + + m[6] += x[0]; + m[7] += x[1]; + } + m[8] = numPts; + + // Solve linear system using Kramers rule + // + c1 = m; c2 = m+3; c3 = m+6; + if ( (det = vtkMath::Determinant3x3 (c1,c2,c3)) <= VTK_TOLERANCE ) + { + return; + } + + this->Normal[0] = vtkMath::Determinant3x3 (v,c2,c3) / det; + this->Normal[1] = vtkMath::Determinant3x3 (c1,v,c3) / det; + this->Normal[2] = -1.0; // because of the formulation + + return; +} + +void vtkTextureMapToPlane::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Origin: (" << this->Origin[0] << ", " + << this->Origin[1] << ", " << this->Origin[2] << " )\n"; + + os << indent << "Axis Point 1: (" << this->Point1[0] << ", " + << this->Point1[1] << ", " << this->Point1[2] << " )\n"; + + os << indent << "Axis Point 2: (" << this->Point2[0] << ", " + << this->Point2[1] << ", " << this->Point2[2] << " )\n"; + + os << indent << "S Range: (" << this->SRange[0] << ", " + << this->SRange[1] << ")\n"; + os << indent << "T Range: (" << this->TRange[0] << ", " + << this->TRange[1] << ")\n"; + os << indent << "Automatic Normal Generation: " << + (this->AutomaticPlaneGeneration ? "On\n" : "Off\n"); + os << indent << "Normal: (" << this->Normal[0] << ", " + << this->Normal[1] << ", " + << this->Normal[2] << ")\n"; +} diff --git a/Graphics/vtkTextureMapToPlane.h b/Graphics/vtkTextureMapToPlane.h new file mode 100644 index 0000000..6b2396f --- /dev/null +++ b/Graphics/vtkTextureMapToPlane.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextureMapToPlane.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextureMapToPlane - generate texture coordinates by mapping points to plane +// .SECTION Description +// vtkTextureMapToPlane is a filter that generates 2D texture coordinates +// by mapping input dataset points onto a plane. The plane can either be +// user specified or generated automatically. (A least squares method is +// used to generate the plane automatically.) +// +// There are two ways you can specify the plane. The first is to provide a +// plane normal. In this case the points are projected to a plane, and the +// points are then mapped into the user specified s-t coordinate range. For +// more control, you can specify a plane with three points: an origin and two +// points defining the two axes of the plane. (This is compatible with the +// vtkPlaneSource.) Using the second method, the SRange and TRange vectors +// are ignored, since the presumption is that the user does not want to scale +// the texture coordinates; and you can adjust the origin and axes points to +// achieve the texture coordinate scaling you need. Note also that using the +// three point method the axes do not have to be orthogonal. + +// .SECTION See Also +// vtkTextureMapToBox vtkPlaneSource vtkTextureMapToCylinder +// vtkTextureMapToSphere vtkThresholdTextureCoords + +#ifndef __vtkTextureMapToPlane_h +#define __vtkTextureMapToPlane_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTextureMapToPlane : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTextureMapToPlane,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with s,t range=(0,1) and automatic plane generation turned on. + static vtkTextureMapToPlane *New(); + + // Description: + // Specify a point defining the origin of the plane. Used in conjunction with + // the Point1 and Point2 ivars to specify a map plane. + vtkSetVector3Macro(Origin,double); + vtkGetVectorMacro(Origin,double,3); + + // Description: + // Specify a point defining the first axis of the plane. + vtkSetVector3Macro(Point1,double); + vtkGetVectorMacro(Point1,double,3); + + // Description: + // Specify a point defining the second axis of the plane. + vtkSetVector3Macro(Point2,double); + vtkGetVectorMacro(Point2,double,3); + + // Description: + // Specify plane normal. An alternative way to specify a map plane. Using + // this method, the object will scale the resulting texture coordinate + // between the SRange and TRange specified. + vtkSetVector3Macro(Normal,double); + vtkGetVectorMacro(Normal,double,3); + + // Description: + // Specify s-coordinate range for texture s-t coordinate pair. + vtkSetVector2Macro(SRange,double); + vtkGetVectorMacro(SRange,double,2); + + // Description: + // Specify t-coordinate range for texture s-t coordinate pair. + vtkSetVector2Macro(TRange,double); + vtkGetVectorMacro(TRange,double,2); + + // Description: + // Turn on/off automatic plane generation. + vtkSetMacro(AutomaticPlaneGeneration,int); + vtkGetMacro(AutomaticPlaneGeneration,int); + vtkBooleanMacro(AutomaticPlaneGeneration,int); + +protected: + vtkTextureMapToPlane(); + ~vtkTextureMapToPlane() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void ComputeNormal(vtkDataSet *output); + + double Origin[3]; + double Point1[3]; + double Point2[3]; + double Normal[3]; + double SRange[2]; + double TRange[2]; + int AutomaticPlaneGeneration; + +private: + vtkTextureMapToPlane(const vtkTextureMapToPlane&); // Not implemented. + void operator=(const vtkTextureMapToPlane&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTextureMapToSphere.cxx b/Graphics/vtkTextureMapToSphere.cxx new file mode 100644 index 0000000..52cdc38 --- /dev/null +++ b/Graphics/vtkTextureMapToSphere.cxx @@ -0,0 +1,204 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextureMapToSphere.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextureMapToSphere.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkTextureMapToSphere, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkTextureMapToSphere); + +// Create object with Center (0,0,0) and the PreventSeam ivar is set to true. The +// sphere center is automatically computed. +vtkTextureMapToSphere::vtkTextureMapToSphere() +{ + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + + this->AutomaticSphereGeneration = 1; + this->PreventSeam = 1; +} + +int vtkTextureMapToSphere::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkFloatArray *newTCoords; + vtkIdType numPts=input->GetNumberOfPoints(); + vtkIdType ptId; + double x[3], rho, r, tc[2], phi=0.0, thetaX, thetaY; + double diff, PiOverTwo=vtkMath::Pi()/2.0; + + vtkDebugMacro(<<"Generating Spherical Texture Coordinates"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( numPts < 1 ) + { + vtkErrorMacro(<<"Can't generate texture coordinates without points"); + return 1; + } + + if ( this->AutomaticSphereGeneration ) + { + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + for ( ptId=0; ptId < numPts; ptId++ ) + { + input->GetPoint(ptId, x); + this->Center[0] += x[0]; + this->Center[1] += x[1]; + this->Center[2] += x[2]; + } + this->Center[0] /= numPts; + this->Center[1] /= numPts; + this->Center[2] /= numPts; + + vtkDebugMacro(<<"Center computed as: (" << this->Center[0] <<", " + << this->Center[1] <<", " << this->Center[2] <<")"); + } + + //loop over all points computing spherical coordinates. Only tricky part + //is keeping track of singularities/numerical problems. + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->SetNumberOfTuples(numPts); + for ( ptId=0; ptId < numPts; ptId++ ) + { + input->GetPoint(ptId, x); + rho = sqrt((double)vtkMath::Distance2BetweenPoints(x,this->Center)); + if ( rho != 0.0 ) + { + // watch for truncation problems + if ( fabs((diff=x[2]-this->Center[2])) > rho ) + { + phi = 0.0; + if ( diff > 0.0 ) + { + tc[1] = 0.0; + } + else + { + tc[1] = 1.0; + } + } + else + { + phi = acos((double)(diff/rho)); + tc[1] = phi / vtkMath::Pi(); + } + } + else + { + tc[1] = 0.0; + } + + r = rho * sin((double)phi); + if ( r != 0.0 ) + { + // watch for truncation problems + if ( fabs((diff=x[0]-this->Center[0])) > r ) + { + if ( diff > 0.0 ) + { + thetaX = 0.0; + } + else + { + thetaX = vtkMath::Pi(); + } + } + else + { + thetaX = acos ((double)diff/r); + } + + if ( fabs((diff=x[1]-this->Center[1])) > r ) + { + if ( diff > 0.0 ) + { + thetaY = PiOverTwo; + } + else + { + thetaY = -PiOverTwo; + } + } + else + { + thetaY = asin ((double)diff/r); + } + } + else + { + thetaX = thetaY = 0.0; + } + + if ( this->PreventSeam ) + { + tc[0] = thetaX / vtkMath::Pi(); + } + else + { + tc[0] = thetaX / (2.0*vtkMath::Pi()); + if ( thetaY < 0.0 ) + { + tc[0] = 1.0 - tc[0]; + } + } + + newTCoords->SetTuple(ptId,tc); + } + + output->GetPointData()->CopyTCoordsOff(); + output->GetPointData()->PassData(input->GetPointData()); + + output->GetCellData()->PassData(input->GetCellData()); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + return 1; +} + +void vtkTextureMapToSphere::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Automatic Sphere Generation: " << + (this->AutomaticSphereGeneration ? "On\n" : "Off\n"); + os << indent << "Prevent Seam: " << + (this->PreventSeam ? "On\n" : "Off\n"); + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << ")\n"; +} + diff --git a/Graphics/vtkTextureMapToSphere.h b/Graphics/vtkTextureMapToSphere.h new file mode 100644 index 0000000..bae63ff --- /dev/null +++ b/Graphics/vtkTextureMapToSphere.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextureMapToSphere.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextureMapToSphere - generate texture coordinates by mapping points to sphere +// .SECTION Description +// vtkTextureMapToSphere is a filter that generates 2D texture coordinates by +// mapping input dataset points onto a sphere. The sphere can either be user +// specified or generated automatically. (The sphere is generated +// automatically by computing the center (i.e., averaged coordinates) of the +// sphere.) Note that the generated texture coordinates range between +// (0,1). The s-coordinate lies in the angular direction around the z-axis, +// measured counter-clockwise from the x-axis. The t-coordinate lies in the +// angular direction measured down from the north pole towards the south +// pole. +// +// A special ivar controls how the s-coordinate is generated. If PreventSeam +// is set to true, the s-texture varies from 0->1 and then 1->0 (corresponding +// to angles of 0->180 and 180->360). + +// .SECTION Caveats +// The resulting texture coordinates will lie between (0,1), and the texture +// coordinates are determined with respect to the modeler's x-y-z coordinate +// system. Use the class vtkTransformTextureCoords to linearly scale and +// shift the origin of the texture coordinates (if necessary). + +// .SECTION See Also +// vtkTextureMapToPlane vtkTextureMapToCylinder vtkTextureMapToBox +// vtkTransformTexture vtkThresholdTextureCoords + +#ifndef __vtkTextureMapToSphere_h +#define __vtkTextureMapToSphere_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTextureMapToSphere : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTextureMapToSphere,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create object with Center (0,0,0) and the PreventSeam ivar is set to + // true. The sphere center is automatically computed. + static vtkTextureMapToSphere *New(); + + // Description: + // Specify a point defining the center of the sphere. + vtkSetVector3Macro(Center,double); + vtkGetVectorMacro(Center,double,3); + + // Description: + // Turn on/off automatic sphere generation. This means it automatically + // finds the sphere center. + vtkSetMacro(AutomaticSphereGeneration,int); + vtkGetMacro(AutomaticSphereGeneration,int); + vtkBooleanMacro(AutomaticSphereGeneration,int); + + // Description: + // Control how the texture coordinates are generated. If PreventSeam is + // set, the s-coordinate ranges from 0->1 and 1->0 corresponding to the + // theta angle variation between 0->180 and 180->0 degrees. Otherwise, the + // s-coordinate ranges from 0->1 between 0->360 degrees. + vtkSetMacro(PreventSeam,int); + vtkGetMacro(PreventSeam,int); + vtkBooleanMacro(PreventSeam,int); + +protected: + vtkTextureMapToSphere(); + ~vtkTextureMapToSphere() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Center[3]; + int AutomaticSphereGeneration; + int PreventSeam; + +private: + vtkTextureMapToSphere(const vtkTextureMapToSphere&); // Not implemented. + void operator=(const vtkTextureMapToSphere&); // Not implemented. +}; + +#endif + + diff --git a/Graphics/vtkTexturedSphereSource.cxx b/Graphics/vtkTexturedSphereSource.cxx new file mode 100644 index 0000000..c4d959e --- /dev/null +++ b/Graphics/vtkTexturedSphereSource.cxx @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTexturedSphereSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTexturedSphereSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkTexturedSphereSource, "$Revision: 1.31 $"); +vtkStandardNewMacro(vtkTexturedSphereSource); + +// Construct sphere with radius=0.5 and default resolution 8 in both Phi +// and Theta directions. +vtkTexturedSphereSource::vtkTexturedSphereSource(int res) +{ + res = res < 4 ? 4 : res; + this->Radius = 0.5; + this->ThetaResolution = res; + this->PhiResolution = res; + this->Theta = 0.0; + this->Phi = 0.0; + + this->SetNumberOfInputPorts(0); +} + +int vtkTexturedSphereSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int i, j; + int numPts; + int numPolys; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkFloatArray *newTCoords; + vtkCellArray *newPolys; + double x[3], deltaPhi, deltaTheta, phi, theta, radius, norm; + vtkIdType pts[3]; + double tc[2]; + + // + // Set things up; allocate memory + // + + numPts = (this->PhiResolution + 1) * (this->ThetaResolution + 1); + // creating triangles + numPolys = this->PhiResolution * 2 * this->ThetaResolution; + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*numPts); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys,3)); + // + // Create sphere + // + // Create intermediate points + deltaPhi = vtkMath::Pi() / this->PhiResolution; + deltaTheta = 2.0 * vtkMath::Pi() / this->ThetaResolution; + for (i=0; i <= this->ThetaResolution; i++) + { + theta = i * deltaTheta; + tc[0] = theta/(2.0*3.1415926); + for (j=0; j <= this->PhiResolution; j++) + { + phi = j * deltaPhi; + radius = this->Radius * sin((double)phi); + x[0] = radius * cos((double)theta); + x[1] = radius * sin((double)theta); + x[2] = this->Radius * cos((double)phi); + newPoints->InsertNextPoint(x); + + if ( (norm = vtkMath::Norm(x)) == 0.0 ) + { + norm = 1.0; + } + x[0] /= norm; x[1] /= norm; x[2] /= norm; + newNormals->InsertNextTuple(x); + + tc[1] = 1.0 - phi/3.1415926; + newTCoords->InsertNextTuple(tc); + } + } + // + // Generate mesh connectivity + // + // bands inbetween poles + for (i=0; i < this->ThetaResolution; i++) + { + for (j=0; j < this->PhiResolution; j++) + { + pts[0] = (this->PhiResolution+1)*i + j; + pts[1] = pts[0] + 1; + pts[2] = ((this->PhiResolution+1)*(i+1)+j) + 1; + newPolys->InsertNextCell(3,pts); + + pts[1] = pts[2]; + pts[2] = pts[1] - 1; + newPolys->InsertNextCell(3,pts); + } + } +// +// Update ourselves and release memeory +// + output->SetPoints(newPoints); + newPoints->Delete(); + + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +void vtkTexturedSphereSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Theta Resolution: " << this->ThetaResolution << "\n"; + os << indent << "Phi Resolution: " << this->PhiResolution << "\n"; + os << indent << "Theta: " << this->Theta << "\n"; + os << indent << "Phi: " << this->Phi << "\n"; + os << indent << "Radius: " << this->Radius << "\n"; +} diff --git a/Graphics/vtkTexturedSphereSource.h b/Graphics/vtkTexturedSphereSource.h new file mode 100644 index 0000000..c2e8d54 --- /dev/null +++ b/Graphics/vtkTexturedSphereSource.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTexturedSphereSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTexturedSphereSource - create a sphere centered at the origin +// .SECTION Description +// vtkTexturedSphereSource creates a polygonal sphere of specified radius +// centered at the origin. The resolution (polygonal discretization) in both +// the latitude (phi) and longitude (theta) directions can be specified. +// It also is possible to create partial sphere by specifying maximum phi and +// theta angles. + +#ifndef __vtkTexturedSphereSource_h +#define __vtkTexturedSphereSource_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_MAX_SPHERE_RESOLUTION 1024 + +class VTK_GRAPHICS_EXPORT vtkTexturedSphereSource : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTexturedSphereSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct sphere with radius=0.5 and default resolution 8 in both Phi + // and Theta directions. + static vtkTexturedSphereSource *New(); + + // Description: + // Set radius of sphere. + vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Radius,double); + + // Description: + // Set the number of points in the longitude direction. + vtkSetClampMacro(ThetaResolution,int,4,VTK_MAX_SPHERE_RESOLUTION); + vtkGetMacro(ThetaResolution,int); + + // Description: + // Set the number of points in the latitude direction. + vtkSetClampMacro(PhiResolution,int,4,VTK_MAX_SPHERE_RESOLUTION); + vtkGetMacro(PhiResolution,int); + + // Description: + // Set the maximum longitude angle. + vtkSetClampMacro(Theta,double,0.0,360.0); + vtkGetMacro(Theta,double); + + // Description: + // Set the maximum latitude angle (0 is at north pole). + vtkSetClampMacro(Phi,double,0.0,180.0); + vtkGetMacro(Phi,double); + +protected: + vtkTexturedSphereSource(int res=8); + ~vtkTexturedSphereSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double Radius; + double Theta; + double Phi; + int ThetaResolution; + int PhiResolution; + +private: + vtkTexturedSphereSource(const vtkTexturedSphereSource&); // Not implemented. + void operator=(const vtkTexturedSphereSource&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkThreshold.cxx b/Graphics/vtkThreshold.cxx new file mode 100644 index 0000000..04fe282 --- /dev/null +++ b/Graphics/vtkThreshold.cxx @@ -0,0 +1,318 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThreshold.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkThreshold.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkThreshold, "$Revision: 1.68 $"); +vtkStandardNewMacro(vtkThreshold); + +// Construct with lower threshold=0, upper threshold=1, and threshold +// function=upper AllScalars=1. +vtkThreshold::vtkThreshold() +{ + this->LowerThreshold = 0.0; + this->UpperThreshold = 1.0; + this->AllScalars = 1; + this->AttributeMode = -1; + this->ThresholdFunction = &vtkThreshold::Upper; + this->ComponentMode = VTK_COMPONENT_MODE_USE_SELECTED; + this->SelectedComponent = 0; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS_THEN_CELLS, + vtkDataSetAttributes::SCALARS); +} + +vtkThreshold::~vtkThreshold() +{ +} + +// Criterion is cells whose scalars are less or equal to lower threshold. +void vtkThreshold::ThresholdByLower(double lower) +{ + if ( this->LowerThreshold != lower || + this->ThresholdFunction != &vtkThreshold::Lower) + { + this->LowerThreshold = lower; + this->ThresholdFunction = &vtkThreshold::Lower; + this->Modified(); + } +} + +// Criterion is cells whose scalars are greater or equal to upper threshold. +void vtkThreshold::ThresholdByUpper(double upper) +{ + if ( this->UpperThreshold != upper || + this->ThresholdFunction != &vtkThreshold::Upper) + { + this->UpperThreshold = upper; + this->ThresholdFunction = &vtkThreshold::Upper; + this->Modified(); + } +} + +// Criterion is cells whose scalars are between lower and upper thresholds. +void vtkThreshold::ThresholdBetween(double lower, double upper) +{ + if ( this->LowerThreshold != lower || this->UpperThreshold != upper || + this->ThresholdFunction != &vtkThreshold::Between) + { + this->LowerThreshold = lower; + this->UpperThreshold = upper; + this->ThresholdFunction = &vtkThreshold::Between; + this->Modified(); + } +} + +int vtkThreshold::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType cellId, newCellId; + vtkIdList *cellPts, *pointMap; + vtkIdList *newCellPts; + vtkCell *cell; + vtkPoints *newPoints; + int i, ptId, newId, numPts; + int numCellPts; + double x[3]; + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + int keepCell, usePointScalars; + + vtkDebugMacro(<< "Executing threshold filter"); + + if (this->AttributeMode != -1) + { + vtkErrorMacro(<<"You have set the attribute mode on vtkThreshold. This method is deprecated, please use SetInputArrayToProcess instead."); + return 1; + } + + vtkDataArray *inScalars = this->GetInputArrayToProcess(0,inputVector); + + if (!inScalars) + { + vtkDebugMacro(<<"No scalar data to threshold"); + return 1; + } + + outPD->CopyAllocate(pd); + outCD->CopyAllocate(cd); + + numPts = input->GetNumberOfPoints(); + output->Allocate(input->GetNumberOfCells()); + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + + pointMap = vtkIdList::New(); //maps old point ids into new + pointMap->SetNumberOfIds(numPts); + for (i=0; i < numPts; i++) + { + pointMap->SetId(i,-1); + } + + newCellPts = vtkIdList::New(); + + // are we using pointScalars? + usePointScalars = (inScalars->GetNumberOfTuples() == numPts); + + // Check that the scalars of each cell satisfy the threshold criterion + for (cellId=0; cellId < input->GetNumberOfCells(); cellId++) + { + cell = input->GetCell(cellId); + cellPts = cell->GetPointIds(); + numCellPts = cell->GetNumberOfPoints(); + + if ( usePointScalars ) + { + if (this->AllScalars) + { + keepCell = 1; + for ( i=0; keepCell && (i < numCellPts); i++) + { + ptId = cellPts->GetId(i); + keepCell = this->EvaluateComponents( inScalars, ptId ); + } + } + else + { + keepCell = 0; + for ( i=0; (!keepCell) && (i < numCellPts); i++) + { + ptId = cellPts->GetId(i); + keepCell = this->EvaluateComponents( inScalars, ptId ); + } + } + } + else //use cell scalars + { + keepCell = this->EvaluateComponents( inScalars, cellId ); + } + + if ( numCellPts > 0 && keepCell ) + { + // satisfied thresholding (also non-empty cell, i.e. not VTK_EMPTY_CELL) + for (i=0; i < numCellPts; i++) + { + ptId = cellPts->GetId(i); + if ( (newId = pointMap->GetId(ptId)) < 0 ) + { + input->GetPoint(ptId, x); + newId = newPoints->InsertNextPoint(x); + pointMap->SetId(ptId,newId); + outPD->CopyData(pd,ptId,newId); + } + newCellPts->InsertId(i,newId); + } + newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts); + outCD->CopyData(cd,cellId,newCellId); + newCellPts->Reset(); + } // satisfied thresholding + } // for all cells + + vtkDebugMacro(<< "Extracted " << output->GetNumberOfCells() + << " number of cells."); + + // now clean up / update ourselves + pointMap->Delete(); + newCellPts->Delete(); + + output->SetPoints(newPoints); + newPoints->Delete(); + + output->Squeeze(); + + return 1; +} + +int vtkThreshold::EvaluateComponents( vtkDataArray *scalars, vtkIdType id ) +{ + int keepCell = 0; + int numComp = scalars->GetNumberOfComponents(); + int c; + + switch ( this->ComponentMode ) + { + case VTK_COMPONENT_MODE_USE_SELECTED: + c = (this->SelectedComponent < numComp)?(this->SelectedComponent):(0); + keepCell = + (this->*(this->ThresholdFunction))(scalars->GetComponent(id,c)); + break; + case VTK_COMPONENT_MODE_USE_ANY: + keepCell = 0; + for ( c = 0; (!keepCell) && (c < numComp); c++ ) + { + keepCell = + (this->*(this->ThresholdFunction))(scalars->GetComponent(id,c)); + } + break; + case VTK_COMPONENT_MODE_USE_ALL: + keepCell = 1; + for ( c = 0; keepCell && (c < numComp); c++ ) + { + keepCell = + (this->*(this->ThresholdFunction))(scalars->GetComponent(id,c)); + } + break; + } + return keepCell; +} + +// Return the method for manipulating scalar data as a string. +const char *vtkThreshold::GetAttributeModeAsString(void) +{ + if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_DEFAULT ) + { + return "Default"; + } + else if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else + { + return "UseCellData"; + } +} + +// Return a string representation of the component mode +const char *vtkThreshold::GetComponentModeAsString(void) +{ + if ( this->ComponentMode == VTK_COMPONENT_MODE_USE_SELECTED ) + { + return "UseSelected"; + } + else if ( this->ComponentMode == VTK_COMPONENT_MODE_USE_ANY ) + { + return "UseAny"; + } + else + { + return "UseAll"; + } +} + +int vtkThreshold::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkThreshold::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Attribute Mode: " << this->GetAttributeModeAsString() << endl; + os << indent << "Component Mode: " << this->GetComponentModeAsString() << endl; + os << indent << "Selected Component: " << this->SelectedComponent << endl; + + os << indent << "All Scalars: " << this->AllScalars << "\n"; + if ( this->ThresholdFunction == &vtkThreshold::Upper ) + { + os << indent << "Threshold By Upper\n"; + } + + else if ( this->ThresholdFunction == &vtkThreshold::Lower ) + { + os << indent << "Threshold By Lower\n"; + } + + else if ( this->ThresholdFunction == &vtkThreshold::Between ) + { + os << indent << "Threshold Between\n"; + } + + os << indent << "Lower Threshold: " << this->LowerThreshold << "\n"; + os << indent << "Upper Threshold: " << this->UpperThreshold << "\n"; +} diff --git a/Graphics/vtkThreshold.h b/Graphics/vtkThreshold.h new file mode 100644 index 0000000..2a43153 --- /dev/null +++ b/Graphics/vtkThreshold.h @@ -0,0 +1,157 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThreshold.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkThreshold - extracts cells where scalar value in cell satisfies threshold criterion +// .SECTION Description +// vtkThreshold is a filter that extracts cells from any dataset type that +// satisfy a threshold criterion. A cell satisfies the criterion if the +// scalar value of (every or any) point satisfies the criterion. The +// criterion can take three forms: 1) greater than a particular value; 2) +// less than a particular value; or 3) between two values. The output of this +// filter is an unstructured grid. +// +// Note that scalar values are available from the point and cell attribute +// data. By default, point data is used to obtain scalars, but you can +// control this behavior. See the AttributeMode ivar below. +// +// By default only the first scalar value is used in the decision. Use the ComponentMode +// and SelectedComponent ivars to control this behavior. + +// .SECTION See Also +// vtkThresholdPoints vtkThresholdTextureCoords + +#ifndef __vtkThreshold_h +#define __vtkThreshold_h + +#include "vtkUnstructuredGridAlgorithm.h" + +#define VTK_ATTRIBUTE_MODE_DEFAULT 0 +#define VTK_ATTRIBUTE_MODE_USE_POINT_DATA 1 +#define VTK_ATTRIBUTE_MODE_USE_CELL_DATA 2 + +// order / values are important because of the SetClampMacro +#define VTK_COMPONENT_MODE_USE_SELECTED 0 +#define VTK_COMPONENT_MODE_USE_ALL 1 +#define VTK_COMPONENT_MODE_USE_ANY 2 + +class vtkDataArray; + +class VTK_GRAPHICS_EXPORT vtkThreshold : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkThreshold *New(); + vtkTypeRevisionMacro(vtkThreshold,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Criterion is cells whose scalars are less or equal to lower threshold. + void ThresholdByLower(double lower); + + // Description: + // Criterion is cells whose scalars are greater or equal to upper threshold. + void ThresholdByUpper(double upper); + + // Description: + // Criterion is cells whose scalars are between lower and upper thresholds + // (inclusive of the end values). + void ThresholdBetween(double lower, double upper); + + // Description: + // Get the Upper and Lower thresholds. + vtkGetMacro(UpperThreshold,double); + vtkGetMacro(LowerThreshold,double); + + // Description: + // Control how the filter works with scalar point data and cell attribute + // data. By default (AttributeModeToDefault), the filter will use point + // data, and if no point data is available, then cell data is + // used. Alternatively you can explicitly set the filter to use point data + // (AttributeModeToUsePointData) or cell data (AttributeModeToUseCellData). + vtkSetMacro(AttributeMode,int); + vtkGetMacro(AttributeMode,int); + void SetAttributeModeToDefault() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_DEFAULT);}; + void SetAttributeModeToUsePointData() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_POINT_DATA);}; + void SetAttributeModeToUseCellData() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_CELL_DATA);}; + const char *GetAttributeModeAsString(); + + // Description: + // Control how the decision of in / out is made with multi-component data. + // The choices are to use the selected component (specified in the + // SelectedComponent ivar), or to look at all components. When looking at + // all components, the evaluation can pass if all the components satisfy + // the rule (UseAll) or if any satisfy is (UseAny). The default value is + // UseSelected. + vtkSetClampMacro(ComponentMode,int, + VTK_COMPONENT_MODE_USE_SELECTED, + VTK_COMPONENT_MODE_USE_ANY); + vtkGetMacro(ComponentMode,int); + void SetComponentModeToUseSelected() + {this->SetComponentMode(VTK_COMPONENT_MODE_USE_SELECTED);}; + void SetComponentModeToUseAll() + {this->SetComponentMode(VTK_COMPONENT_MODE_USE_ALL);}; + void SetComponentModeToUseAny() + {this->SetComponentMode(VTK_COMPONENT_MODE_USE_ANY);}; + const char *GetComponentModeAsString(); + + // Description: + // When the component mode is UseSelected, this ivar indicated the selected + // component. The default value is 0. + vtkSetClampMacro(SelectedComponent,int,0,VTK_INT_MAX); + vtkGetMacro(SelectedComponent,int); + + // Description: + // If using scalars from point data, all scalars for all points in a cell + // must satisfy the threshold criterion if AllScalars is set. Otherwise, + // just a single scalar value satisfying the threshold criterion enables + // will extract the cell. + vtkSetMacro(AllScalars,int); + vtkGetMacro(AllScalars,int); + vtkBooleanMacro(AllScalars,int); + +protected: + vtkThreshold(); + ~vtkThreshold(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int AllScalars; + double LowerThreshold; + double UpperThreshold; + int AttributeMode; + int ComponentMode; + int SelectedComponent; + + //BTX + int (vtkThreshold::*ThresholdFunction)(double s); + //ETX + + int Lower(double s) {return ( s <= this->LowerThreshold ? 1 : 0 );}; + int Upper(double s) {return ( s >= this->UpperThreshold ? 1 : 0 );}; + int Between(double s) {return ( s >= this->LowerThreshold ? + ( s <= this->UpperThreshold ? 1 : 0 ) : 0 );}; + + int EvaluateComponents( vtkDataArray *scalars, vtkIdType id ); + +private: + vtkThreshold(const vtkThreshold&); // Not implemented. + void operator=(const vtkThreshold&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkThresholdPoints.cxx b/Graphics/vtkThresholdPoints.cxx new file mode 100644 index 0000000..92ac8a9 --- /dev/null +++ b/Graphics/vtkThresholdPoints.cxx @@ -0,0 +1,202 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThresholdPoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkThresholdPoints.h" + +#include "vtkCellArray.h" +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkThresholdPoints, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkThresholdPoints); + +// Construct with lower threshold=0, upper threshold=1, and threshold +// function=upper. +vtkThresholdPoints::vtkThresholdPoints() +{ + this->LowerThreshold = 0.0; + this->UpperThreshold = 1.0; + + this->ThresholdFunction = &vtkThresholdPoints::Upper; +} + +// Criterion is cells whose scalars are less than lower threshold. +void vtkThresholdPoints::ThresholdByLower(double lower) +{ + int isModified=0; + + if ( this->ThresholdFunction != &vtkThresholdPoints::Lower ) + { + this->ThresholdFunction = &vtkThresholdPoints::Lower; + isModified=1; + } + + if ( this->LowerThreshold != lower ) + { + this->LowerThreshold = lower; + isModified=1; + } + + if(isModified) + { + this->Modified(); + } +} + +// Criterion is cells whose scalars are less than upper threshold. +void vtkThresholdPoints::ThresholdByUpper(double upper) +{ + int isModified=0; + + if ( this->ThresholdFunction != &vtkThresholdPoints::Upper ) + { + this->ThresholdFunction = &vtkThresholdPoints::Upper; + isModified=1; + } + + if ( this->UpperThreshold != upper ) + { + this->UpperThreshold = upper; + isModified=1; + } + + if(isModified) + { + this->Modified(); + } +} + +// Criterion is cells whose scalars are between lower and upper thresholds. +void vtkThresholdPoints::ThresholdBetween(double lower, double upper) +{ + int isModified=0; + + if ( this->ThresholdFunction != &vtkThresholdPoints::Between ) + { + this->ThresholdFunction = &vtkThresholdPoints::Between; + isModified=1; + } + + if ( this->LowerThreshold != lower ) + { + this->LowerThreshold = lower; + isModified=1; + } + + if ( this->UpperThreshold != upper ) + { + this->UpperThreshold = upper; + isModified=1; + } + + if(isModified) + { + this->Modified(); + } +} + +int vtkThresholdPoints::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *inScalars; + vtkPoints *newPoints; + vtkPointData *pd, *outPD; + vtkCellArray *verts; + vtkIdType ptId, numPts, pts[1]; + double x[3]; + + vtkDebugMacro(<< "Executing threshold points filter"); + + if ( ! (inScalars = input->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"No scalar data to threshold"); + return 1; + } + + numPts = input->GetNumberOfPoints(); + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + pd = input->GetPointData(); + outPD = output->GetPointData(); + outPD->CopyAllocate(pd); + verts = vtkCellArray::New(); + verts->Allocate(verts->EstimateSize(numPts,1)); + + // Check that the scalars of each point satisfy the threshold criterion + int abort=0; + vtkIdType progressInterval = numPts/20+1; + + for (ptId=0; ptId < numPts && !abort; ptId++) + { + if ( !(ptId % progressInterval) ) + { + this->UpdateProgress((double)ptId/numPts); + abort = this->GetAbortExecute(); + } + + if ( (this->*(this->ThresholdFunction))(inScalars->GetComponent(ptId,0)) ) + { + input->GetPoint(ptId, x); + pts[0] = newPoints->InsertNextPoint(x); + outPD->CopyData(pd,ptId,pts[0]); + verts->InsertNextCell(1,pts); + } // satisfied thresholding + } // for all points + + vtkDebugMacro(<< "Extracted " << output->GetNumberOfPoints() << " points."); + + // Update ourselves and release memory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + output->SetVerts(verts); + verts->Delete(); + + output->Squeeze(); + + return 1; +} + +int vtkThresholdPoints::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkThresholdPoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Lower Threshold: " << this->LowerThreshold << "\n";; + os << indent << "Upper Threshold: " << this->UpperThreshold << "\n";; +} diff --git a/Graphics/vtkThresholdPoints.h b/Graphics/vtkThresholdPoints.h new file mode 100644 index 0000000..95ed351 --- /dev/null +++ b/Graphics/vtkThresholdPoints.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThresholdPoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkThresholdPoints - extracts points whose scalar value satisfies threshold criterion +// .SECTION Description +// vtkThresholdPoints is a filter that extracts points from a dataset that +// satisfy a threshold criterion. The criterion can take three forms: +// 1) greater than a particular value; 2) less than a particular value; or +// 3) between a particular value. The output of the filter is polygonal data. +// .SECTION See Also +// vtkThreshold + +#ifndef __vtkThresholdPoints_h +#define __vtkThresholdPoints_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkThresholdPoints : public vtkPolyDataAlgorithm +{ +public: + static vtkThresholdPoints *New(); + vtkTypeRevisionMacro(vtkThresholdPoints,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Criterion is cells whose scalars are less or equal to lower threshold. + void ThresholdByLower(double lower); + + // Description: + // Criterion is cells whose scalars are greater or equal to upper threshold. + void ThresholdByUpper(double upper); + + // Description: + // Criterion is cells whose scalars are between lower and upper thresholds + // (inclusive of the end values). + void ThresholdBetween(double lower, double upper); + + // Description: + // Get the upper and lower thresholds. + vtkGetMacro(UpperThreshold,double); + vtkGetMacro(LowerThreshold,double); + +protected: + vtkThresholdPoints(); + ~vtkThresholdPoints() {}; + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + double LowerThreshold; + double UpperThreshold; + + //BTX + int (vtkThresholdPoints::*ThresholdFunction)(double s); + //ETX + + int Lower(double s) {return ( s <= this->LowerThreshold ? 1 : 0 );}; + int Upper(double s) {return ( s >= this->UpperThreshold ? 1 : 0 );}; + int Between(double s) {return ( s >= this->LowerThreshold ? + ( s <= this->UpperThreshold ? 1 : 0 ) : 0 );}; +private: + vtkThresholdPoints(const vtkThresholdPoints&); // Not implemented. + void operator=(const vtkThresholdPoints&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkThresholdTextureCoords.cxx b/Graphics/vtkThresholdTextureCoords.cxx new file mode 100644 index 0000000..f5ebdbf --- /dev/null +++ b/Graphics/vtkThresholdTextureCoords.cxx @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThresholdTextureCoords.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkThresholdTextureCoords.h" + +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkThresholdTextureCoords, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkThresholdTextureCoords); + +// Construct with lower threshold=0, upper threshold=1, threshold +// function=upper, and texture dimension = 2. The "out" texture coordinate +// is (0.25,0,0); the "in" texture coordinate is (0.75,0,0). +vtkThresholdTextureCoords::vtkThresholdTextureCoords() +{ + this->LowerThreshold = 0.0; + this->UpperThreshold = 1.0; + this->TextureDimension = 2; + + this->ThresholdFunction = &vtkThresholdTextureCoords::Upper; + + this->OutTextureCoord[0] = 0.25; + this->OutTextureCoord[1] = 0.0; + this->OutTextureCoord[2] = 0.0; + + this->InTextureCoord[0] = 0.75; + this->InTextureCoord[1] = 0.0; + this->InTextureCoord[2] = 0.0; +} + +// Criterion is cells whose scalars are less than lower threshold. +void vtkThresholdTextureCoords::ThresholdByLower(double lower) +{ + if ( this->LowerThreshold != lower ) + { + this->LowerThreshold = lower; + this->ThresholdFunction = &vtkThresholdTextureCoords::Lower; + this->Modified(); + } +} + +// Criterion is cells whose scalars are less than upper threshold. +void vtkThresholdTextureCoords::ThresholdByUpper(double upper) +{ + if ( this->UpperThreshold != upper ) + { + this->UpperThreshold = upper; + this->ThresholdFunction = &vtkThresholdTextureCoords::Upper; + this->Modified(); + } +} + +// Criterion is cells whose scalars are between lower and upper thresholds. +void vtkThresholdTextureCoords::ThresholdBetween(double lower, double upper) +{ + if ( this->LowerThreshold != lower || this->UpperThreshold != upper ) + { + this->LowerThreshold = lower; + this->UpperThreshold = upper; + this->ThresholdFunction = &vtkThresholdTextureCoords::Between; + this->Modified(); + } +} + +int vtkThresholdTextureCoords::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts; + vtkFloatArray *newTCoords; + vtkIdType ptId; + vtkDataArray *inScalars; + + vtkDebugMacro(<< "Executing texture threshold filter"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( ! (inScalars = input->GetPointData()->GetScalars()) ) + { + vtkErrorMacro(<<"No scalar data to texture threshold"); + return 1; + } + + numPts = input->GetNumberOfPoints(); + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*this->TextureDimension); + + // Check that the scalars of each point satisfy the threshold criterion + for (ptId=0; ptId < numPts; ptId++) + { + if ( (this->*(this->ThresholdFunction))(inScalars->GetComponent(ptId,0)) ) + { + newTCoords->InsertTuple(ptId,this->InTextureCoord); + } + else //doesn't satisfy criterion + { + newTCoords->InsertTuple(ptId,this->OutTextureCoord); + } + + } //for all points + + output->GetPointData()->CopyTCoordsOff(); + output->GetPointData()->PassData(input->GetPointData()); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + return 1; +} + +void vtkThresholdTextureCoords::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->ThresholdFunction == &vtkThresholdTextureCoords::Upper ) + { + os << indent << "Threshold By Upper\n"; + } + + else if ( this->ThresholdFunction == &vtkThresholdTextureCoords::Lower ) + { + os << indent << "Threshold By Lower\n"; + } + + else if ( this->ThresholdFunction == &vtkThresholdTextureCoords::Between ) + { + os << indent << "Threshold Between\n"; + } + + os << indent << "Lower Threshold: " << this->LowerThreshold << "\n";; + os << indent << "Upper Threshold: " << this->UpperThreshold << "\n";; + os << indent << "Texture Dimension: " << this->TextureDimension << "\n";; + + os << indent << "Out Texture Coordinate: (" << this->OutTextureCoord[0] + << ", " << this->OutTextureCoord[1] + << ", " << this->OutTextureCoord[2] << ")\n"; + + os << indent << "In Texture Coordinate: (" << this->InTextureCoord[0] + << ", " << this->InTextureCoord[1] + << ", " << this->InTextureCoord[2] << ")\n"; +} diff --git a/Graphics/vtkThresholdTextureCoords.h b/Graphics/vtkThresholdTextureCoords.h new file mode 100644 index 0000000..61dccdd --- /dev/null +++ b/Graphics/vtkThresholdTextureCoords.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThresholdTextureCoords.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkThresholdTextureCoords - compute 1D, 2D, or 3D texture coordinates based on scalar threshold +// .SECTION Description +// vtkThresholdTextureCoords is a filter that generates texture coordinates for +// any input dataset type given a threshold criterion. The criterion can take +// three forms: 1) greater than a particular value (ThresholdByUpper()); +// 2) less than a particular value (ThresholdByLower(); or 3) between two +// values (ThresholdBetween(). If the threshold criterion is satisfied, +// the "in" texture coordinate will be set (this can be specified by the +// user). If the threshold criterion is not satisfied the "out" is set. + +// .SECTION Caveats +// There is a texture map - texThres.vtk - that can be used in conjunction +// with this filter. This map defines a "transparent" region for texture +// coordinates 0<=r<0.5, and an opaque full intensity map for texture +// coordinates 0.5LowerThreshold ? 1 : 0 );}; + int Upper(double s) {return ( s >= this->UpperThreshold ? 1 : 0 );}; + int Between(double s) {return ( s >= this->LowerThreshold ? + ( s <= this->UpperThreshold ? 1 : 0 ) : 0 );}; +private: + vtkThresholdTextureCoords(const vtkThresholdTextureCoords&); // Not implemented. + void operator=(const vtkThresholdTextureCoords&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTransformFilter.cxx b/Graphics/vtkTransformFilter.cxx new file mode 100644 index 0000000..ee85f25 --- /dev/null +++ b/Graphics/vtkTransformFilter.cxx @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransformFilter.h" + +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLinearTransform.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" + +vtkCxxRevisionMacro(vtkTransformFilter, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkTransformFilter); +vtkCxxSetObjectMacro(vtkTransformFilter,Transform,vtkAbstractTransform); + +vtkTransformFilter::vtkTransformFilter() +{ + this->Transform = NULL; +} + +vtkTransformFilter::~vtkTransformFilter() +{ + this->SetTransform(NULL); +} + +int vtkTransformFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts; + vtkPoints *newPts; + vtkDataArray *inVectors, *inCellVectors;; + vtkFloatArray *newVectors=NULL, *newCellVectors=NULL; + vtkDataArray *inNormals, *inCellNormals; + vtkFloatArray *newNormals=NULL, *newCellNormals=NULL; + vtkIdType numPts, numCells; + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + + vtkDebugMacro(<<"Executing transform filter"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + // Check input + // + if ( this->Transform == NULL ) + { + vtkErrorMacro(<<"No transform defined!"); + return 1; + } + + inPts = input->GetPoints(); + inVectors = pd->GetVectors(); + inNormals = pd->GetNormals(); + inCellVectors = cd->GetVectors(); + inCellNormals = cd->GetNormals(); + + if ( !inPts ) + { + vtkErrorMacro(<<"No input data"); + return 1; + } + + numPts = inPts->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + if ( inVectors ) + { + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(3*numPts); + newVectors->SetName(inVectors->GetName()); + } + if ( inNormals ) + { + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + newNormals->SetName(inNormals->GetName()); + } + + this->UpdateProgress (.2); + // Loop over all points, updating position + // + + if ( inVectors || inNormals ) + { + this->Transform->TransformPointsNormalsVectors(inPts,newPts, + inNormals,newNormals, + inVectors,newVectors); + } + else + { + this->Transform->TransformPoints(inPts,newPts); + } + + this->UpdateProgress (.6); + + // Can only transform cell normals/vectors if the transform + // is linear. + vtkLinearTransform* lt=vtkLinearTransform::SafeDownCast(this->Transform); + if (lt) + { + if ( inCellVectors ) + { + newCellVectors = vtkFloatArray::New(); + newCellVectors->SetNumberOfComponents(3); + newCellVectors->Allocate(3*numCells); + lt->TransformVectors(inCellVectors,newCellVectors); + } + if ( inCellNormals ) + { + newCellNormals = vtkFloatArray::New(); + newCellNormals->SetNumberOfComponents(3); + newCellNormals->Allocate(3*numCells); + lt->TransformNormals(inCellNormals,newCellNormals); + } + } + + this->UpdateProgress (.8); + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newNormals) + { + outPD->SetNormals(newNormals); + newNormals->Delete(); + outPD->CopyNormalsOff(); + } + + if (newVectors) + { + outPD->SetVectors(newVectors); + newVectors->Delete(); + outPD->CopyVectorsOff(); + } + + if (newCellNormals) + { + outCD->SetNormals(newCellNormals); + newCellNormals->Delete(); + outCD->CopyNormalsOff(); + } + + if (newCellVectors) + { + outCD->SetVectors(newCellVectors); + newCellVectors->Delete(); + outCD->CopyVectorsOff(); + } + + outPD->PassData(pd); + outCD->PassData(cd); + + vtkFieldData* inFD = input->GetFieldData(); + if (inFD) + { + vtkFieldData* outFD = output->GetFieldData(); + if (!outFD) + { + outFD = vtkFieldData::New(); + output->SetFieldData(outFD); + // We can still use outFD since it's registered + // by the output + outFD->Delete(); + } + outFD->PassData(inFD); + } + + return 1; +} + +unsigned long vtkTransformFilter::GetMTime() +{ + unsigned long mTime=this->MTime.GetMTime(); + unsigned long transMTime; + + if ( this->Transform ) + { + transMTime = this->Transform->GetMTime(); + mTime = ( transMTime > mTime ? transMTime : mTime ); + } + + return mTime; +} + +void vtkTransformFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Transform: " << this->Transform << "\n"; +} diff --git a/Graphics/vtkTransformFilter.h b/Graphics/vtkTransformFilter.h new file mode 100644 index 0000000..f74a8eb --- /dev/null +++ b/Graphics/vtkTransformFilter.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransformFilter - transform points and associated normals and vectors +// .SECTION Description +// vtkTransformFilter is a filter to transform point coordinates, and +// associated point normals and vectors. Other point data is passed +// through the filter. +// +// An alternative method of transformation is to use vtkActor's methods +// to scale, rotate, and translate objects. The difference between the +// two methods is that vtkActor's transformation simply effects where +// objects are rendered (via the graphics pipeline), whereas +// vtkTransformFilter actually modifies point coordinates in the +// visualization pipeline. This is necessary for some objects +// (e.g., vtkProbeFilter) that require point coordinates as input. + +// .SECTION See Also +// vtkAbstractTransform vtkTransformPolyDataFilter vtkActor + +#ifndef __vtkTransformFilter_h +#define __vtkTransformFilter_h + +#include "vtkPointSetAlgorithm.h" + +class vtkAbstractTransform; + +class VTK_GRAPHICS_EXPORT vtkTransformFilter : public vtkPointSetAlgorithm +{ +public: + static vtkTransformFilter *New(); + vtkTypeRevisionMacro(vtkTransformFilter,vtkPointSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the MTime also considering the transform. + unsigned long GetMTime(); + + // Description: + // Specify the transform object used to transform points. + virtual void SetTransform(vtkAbstractTransform*); + vtkGetObjectMacro(Transform,vtkAbstractTransform); + +protected: + vtkTransformFilter(); + ~vtkTransformFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + vtkAbstractTransform *Transform; +private: + vtkTransformFilter(const vtkTransformFilter&); // Not implemented. + void operator=(const vtkTransformFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTransformPolyDataFilter.cxx b/Graphics/vtkTransformPolyDataFilter.cxx new file mode 100644 index 0000000..af645a0 --- /dev/null +++ b/Graphics/vtkTransformPolyDataFilter.cxx @@ -0,0 +1,210 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransformPolyDataFilter.h" + +#include "vtkAbstractTransform.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkLinearTransform.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkTransformPolyDataFilter, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkTransformPolyDataFilter); +vtkCxxSetObjectMacro(vtkTransformPolyDataFilter, + Transform,vtkAbstractTransform); + +vtkTransformPolyDataFilter::vtkTransformPolyDataFilter() +{ + this->Transform = NULL; +} + +vtkTransformPolyDataFilter::~vtkTransformPolyDataFilter() +{ + this->SetTransform(NULL); +} + +int vtkTransformPolyDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts; + vtkPoints *newPts; + vtkDataArray *inVectors, *inCellVectors; + vtkFloatArray *newVectors=NULL, *newCellVectors=NULL; + vtkDataArray *inNormals, *inCellNormals; + vtkFloatArray *newNormals=NULL, *newCellNormals=NULL; + vtkIdType numPts, numCells; + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + + vtkDebugMacro(<<"Executing polygonal transformation"); + + // Check input + // + if ( this->Transform == NULL ) + { + vtkErrorMacro(<<"No transform defined!"); + return 1; + } + + inPts = input->GetPoints(); + inVectors = pd->GetVectors(); + inNormals = pd->GetNormals(); + inCellVectors = cd->GetVectors(); + inCellNormals = cd->GetNormals(); + + if ( !inPts ) + { + vtkErrorMacro(<<"No input data"); + return 1; + } + + numPts = inPts->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + if ( inVectors ) + { + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(3*numPts); + } + if ( inNormals ) + { + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + } + + this->UpdateProgress (.2); + // Loop over all points, updating position + // + + if ( inVectors || inNormals ) + { + this->Transform->TransformPointsNormalsVectors(inPts,newPts, + inNormals,newNormals, + inVectors,newVectors); + } + else + { + this->Transform->TransformPoints(inPts,newPts); + } + + this->UpdateProgress (.6); + + // Can only transform cell normals/vectors if the transform + // is linear. + vtkLinearTransform* lt = vtkLinearTransform::SafeDownCast(this->Transform); + if (lt) + { + if ( inCellVectors ) + { + newCellVectors = vtkFloatArray::New(); + newCellVectors->SetNumberOfComponents(3); + newCellVectors->Allocate(3*numCells); + lt->TransformVectors(inCellVectors,newCellVectors); + } + if ( inCellNormals ) + { + newCellNormals = vtkFloatArray::New(); + newCellNormals->SetNumberOfComponents(3); + newCellNormals->Allocate(3*numCells); + lt->TransformNormals(inCellNormals,newCellNormals); + } + } + + this->UpdateProgress (.8); + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + output->SetVerts(input->GetVerts()); + output->SetLines(input->GetLines()); + output->SetPolys(input->GetPolys()); + output->SetStrips(input->GetStrips()); + + if (newNormals) + { + outPD->SetNormals(newNormals); + newNormals->Delete(); + outPD->CopyNormalsOff(); + } + + if (newVectors) + { + outPD->SetVectors(newVectors); + newVectors->Delete(); + outPD->CopyVectorsOff(); + } + + if (newCellNormals) + { + outCD->SetNormals(newCellNormals); + newCellNormals->Delete(); + outCD->CopyNormalsOff(); + } + + if (newCellVectors) + { + outCD->SetVectors(newCellVectors); + newCellVectors->Delete(); + outCD->CopyVectorsOff(); + } + + outPD->PassData(pd); + outCD->PassData(cd); + + return 1; +} + +unsigned long vtkTransformPolyDataFilter::GetMTime() +{ + unsigned long mTime=this->MTime.GetMTime(); + unsigned long transMTime; + + if ( this->Transform ) + { + transMTime = this->Transform->GetMTime(); + mTime = ( transMTime > mTime ? transMTime : mTime ); + } + + return mTime; +} + +void vtkTransformPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Transform: " << this->Transform << "\n"; +} diff --git a/Graphics/vtkTransformPolyDataFilter.h b/Graphics/vtkTransformPolyDataFilter.h new file mode 100644 index 0000000..53bb52e --- /dev/null +++ b/Graphics/vtkTransformPolyDataFilter.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransformPolyDataFilter - transform points and associated normals and vectors for polygonal dataset +// .SECTION Description +// vtkTransformPolyDataFilter is a filter to transform point +// coordinates and associated point and cell normals and +// vectors. Other point and cell data is passed through the filter +// unchanged. This filter is specialized for polygonal data. See +// vtkTransformFilter for more general data. +// +// An alternative method of transformation is to use vtkActor's methods +// to scale, rotate, and translate objects. The difference between the +// two methods is that vtkActor's transformation simply effects where +// objects are rendered (via the graphics pipeline), whereas +// vtkTransformPolyDataFilter actually modifies point coordinates in the +// visualization pipeline. This is necessary for some objects +// (e.g., vtkProbeFilter) that require point coordinates as input. + +// .SECTION See Also +// vtkTransform vtkTransformFilter vtkActor + +#ifndef __vtkTransformPolyDataFilter_h +#define __vtkTransformPolyDataFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkAbstractTransform; + +class VTK_GRAPHICS_EXPORT vtkTransformPolyDataFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkTransformPolyDataFilter *New(); + vtkTypeRevisionMacro(vtkTransformPolyDataFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the MTime also considering the transform. + unsigned long GetMTime(); + + // Description: + // Specify the transform object used to transform points. + virtual void SetTransform(vtkAbstractTransform*); + vtkGetObjectMacro(Transform,vtkAbstractTransform); + +protected: + vtkTransformPolyDataFilter(); + ~vtkTransformPolyDataFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + vtkAbstractTransform *Transform; +private: + vtkTransformPolyDataFilter(const vtkTransformPolyDataFilter&); // Not implemented. + void operator=(const vtkTransformPolyDataFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTransformTextureCoords.cxx b/Graphics/vtkTransformTextureCoords.cxx new file mode 100644 index 0000000..067f305 --- /dev/null +++ b/Graphics/vtkTransformTextureCoords.cxx @@ -0,0 +1,193 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformTextureCoords.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransformTextureCoords.h" + +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkTransformTextureCoords, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkTransformTextureCoords); + +// Create instance with Origin (0.5,0.5,0.5); Position (0,0,0); and Scale +// set to (1,1,1). Rotation of the texture coordinates is turned off. +vtkTransformTextureCoords::vtkTransformTextureCoords() +{ + this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.5; + this->Position[0] = this->Position[1] = this->Position[2] = 0.0; + this->Scale[0] = this->Scale[1] = this->Scale[2] = 1.0; + + this->FlipR = 0; + this->FlipS = 0; + this->FlipT = 0; +} + +// Incrementally change the position of the texture map (i.e., does a +// translate or shift of the texture coordinates). +void vtkTransformTextureCoords::AddPosition (double dPX, double dPY, double dPZ) +{ + double position[3]; + + position[0] = this->Position[0] + dPX; + position[1] = this->Position[1] + dPY; + position[2] = this->Position[2] + dPZ; + + this->SetPosition(position); +} + +void vtkTransformTextureCoords::AddPosition(double deltaPosition[3]) +{ + this->AddPosition (deltaPosition[0], deltaPosition[1], deltaPosition[2]); +} + +int vtkTransformTextureCoords::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *inTCoords=input->GetPointData()->GetTCoords(); + vtkDataArray *newTCoords; + vtkIdType numPts=input->GetNumberOfPoints(), ptId; + int i, j, texDim; + vtkTransform *transform; + vtkMatrix4x4 *matrix; + double TC[3], newTC[3]; + + vtkDebugMacro(<<"Transforming texture coordinates..."); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( inTCoords == NULL || numPts < 1 ) + { + vtkErrorMacro(<<"No texture coordinates to transform"); + return 1; + } + transform = vtkTransform::New(); + matrix = vtkMatrix4x4::New(); + + // create same type as input + texDim = inTCoords->GetNumberOfComponents(); + newTCoords = inTCoords->NewInstance(); + newTCoords->SetNumberOfComponents(inTCoords->GetNumberOfComponents()); + newTCoords->Allocate(numPts*texDim); + + // just pretend texture coordinate is 3D point and use transform object to + // manipulate + transform->PostMultiply(); + // shift back to origin + transform->Translate(-this->Origin[0], -this->Origin[1], -this->Origin[2]); + + // scale + transform->Scale(this->Scale[0], this->Scale[1], this->Scale[2]); + + // rotate about z, then x, then y + if ( this->FlipT ) + { + transform->RotateZ(180.0); + } + if ( this->FlipR ) + { + transform->RotateX(180.0); + } + if ( this->FlipS ) + { + transform->RotateY(180.0); + } + + // move back from origin and translate + transform->Translate(this->Origin[0] + this->Position[0], + this->Origin[1] + this->Position[1], + this->Origin[2] + this->Position[2]); + + matrix->DeepCopy(transform->GetMatrix()); + + newTC[0] = newTC[1] = newTC[2] = 0.0; + newTC[0] = newTC[1] = newTC[2] = 0.0; + + int abort=0; + int progressInterval = numPts/20+1; + + for (ptId=0; ptId < numPts && !abort; ptId++) + { + if ( !(ptId % progressInterval) ) + { + this->UpdateProgress((double)ptId/numPts); + abort = this->GetAbortExecute(); + } + + inTCoords->GetTuple(ptId, TC); + for (i=0; iElement[i][3]; + for (j=0; jElement[i][j] * TC[j]; + } + } + + newTCoords->InsertTuple(ptId,newTC); + } + + // Update self + // + output->GetPointData()->CopyTCoordsOff(); + output->GetPointData()->PassData(input->GetPointData()); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + matrix->Delete(); + transform->Delete(); + + return 1; +} + +void vtkTransformTextureCoords::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Scale: (" + << this->Scale[0] << ", " + << this->Scale[1] << ", " + << this->Scale[2] << ")\n"; + + os << indent << "Position: (" + << this->Position[0] << ", " + << this->Position[1] << ", " + << this->Position[2] << ")\n"; + + os << indent << "Origin: (" + << this->Origin[0] << ", " + << this->Origin[1] << ", " + << this->Origin[2] << ")\n"; + + os << indent << "FlipR: " << (this->FlipR ? "On\n" : "Off\n"); + os << indent << "FlipS: " << (this->FlipS ? "On\n" : "Off\n"); + os << indent << "FlipT: " << (this->FlipT ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkTransformTextureCoords.h b/Graphics/vtkTransformTextureCoords.h new file mode 100644 index 0000000..6e98c94 --- /dev/null +++ b/Graphics/vtkTransformTextureCoords.h @@ -0,0 +1,112 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformTextureCoords.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransformTextureCoords - transform (scale, rotate, translate) texture coordinates +// .SECTION Description +// vtkTransformTextureCoords is a filter that operates on texture +// coordinates. It ingests any type of dataset, and outputs a dataset of the +// same type. The filter lets you scale, translate, and rotate texture +// coordinates. For example, by using the the Scale ivar, you can shift +// texture coordinates that range from (0->1) to range from (0->10) (useful +// for repeated patterns). +// +// The filter operates on texture coordinates of dimension 1->3. The texture +// coordinates are referred to as r-s-t. If the texture map is two dimensional, +// the t-coordinate (and operations on the t-coordinate) are ignored. + +// .SECTION See Also +// vtkTextureMapToPlane vtkTextureMapToBox vtkTextureMapToCylinder +// vtkTextureMapToSphere vtkThresholdTextureCoords vtkTexture + +#ifndef __vtkTransformTextureCoords_h +#define __vtkTransformTextureCoords_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTransformTextureCoords : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTransformTextureCoords,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create instance with Origin (0.5,0.5,0.5); Position (0,0,0); and Scale + // set to (1,1,1). Rotation of the texture coordinates is turned off. + static vtkTransformTextureCoords *New(); + + // Description: + // Set/Get the position of the texture map. Setting the position translates + // the texture map by the amount specified. + vtkSetVector3Macro(Position,double); + vtkGetVectorMacro(Position,double,3); + + // Description: + // Incrementally change the position of the texture map (i.e., does a + // translate or shift of the texture coordinates). + void AddPosition(double deltaR, double deltaS, double deltaT); + void AddPosition(double deltaPosition[3]); + + // Description: + // Set/Get the scale of the texture map. Scaling in performed independently + // on the r, s and t axes. + vtkSetVector3Macro(Scale,double); + vtkGetVectorMacro(Scale,double,3); + + // Description: + // Set/Get the origin of the texture map. This is the point about which the + // texture map is flipped (e.g., rotated). Since a typical texture map ranges + // from (0,1) in the r-s-t coordinates, the default origin is set at + // (0.5,0.5,0.5). + vtkSetVector3Macro(Origin,double); + vtkGetVectorMacro(Origin,double,3); + + // Description: + // Boolean indicates whether the texture map should be flipped around the + // s-axis. Note that the flips occur around the texture origin. + vtkSetMacro(FlipR,int); + vtkGetMacro(FlipR,int); + vtkBooleanMacro(FlipR,int); + + // Description: + // Boolean indicates whether the texture map should be flipped around the + // s-axis. Note that the flips occur around the texture origin. + vtkSetMacro(FlipS,int); + vtkGetMacro(FlipS,int); + vtkBooleanMacro(FlipS,int); + + // Description: + // Boolean indicates whether the texture map should be flipped around the + // t-axis. Note that the flips occur around the texture origin. + vtkSetMacro(FlipT,int); + vtkGetMacro(FlipT,int); + vtkBooleanMacro(FlipT,int); + +protected: + vtkTransformTextureCoords(); + ~vtkTransformTextureCoords() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Origin[3]; //point around which map rotates + double Position[3]; //controls translation of map + double Scale[3]; //scales the texture map + int FlipR; //boolean indicates whether to flip texture around r-axis + int FlipS; //boolean indicates whether to flip texture around s-axis + int FlipT; //boolean indicates whether to flip texture around t-axis +private: + vtkTransformTextureCoords(const vtkTransformTextureCoords&); // Not implemented. + void operator=(const vtkTransformTextureCoords&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTriangleFilter.cxx b/Graphics/vtkTriangleFilter.cxx new file mode 100644 index 0000000..b7b5371 --- /dev/null +++ b/Graphics/vtkTriangleFilter.cxx @@ -0,0 +1,246 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangleFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTriangleFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkTriangleStrip.h" + +vtkCxxRevisionMacro(vtkTriangleFilter, "$Revision: 1.53 $"); +vtkStandardNewMacro(vtkTriangleFilter); + +int vtkTriangleFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numCells=input->GetNumberOfCells(); + vtkIdType cellNum=0; + vtkIdType numPts, newId; + vtkIdType npts = 0; + vtkIdType *pts = 0; + int i, j; + vtkCellData *inCD=input->GetCellData(); + vtkCellData *outCD=output->GetCellData(); + vtkIdType updateInterval; + vtkCellArray *cells, *newCells; + vtkPoints *inPts=input->GetPoints(); + + int abort=0; + updateInterval = numCells/100 + 1; + outCD->CopyAllocate(inCD,numCells); + + // Do each of the verts, lines, polys, and strips separately + // verts + if ( !abort && input->GetVerts()->GetNumberOfCells() > 0 ) + { + cells = input->GetVerts(); + if ( this->PassVerts ) + { + newId = output->GetNumberOfCells(); + newCells = vtkCellArray::New(); + newCells->EstimateSize(cells->GetNumberOfCells(),1); + for (cells->InitTraversal(); cells->GetNextCell(npts,pts) && !abort; cellNum++) + { + if ( ! (cellNum % updateInterval) ) //manage progress reports / early abort + { + this->UpdateProgress ((float)cellNum / numCells); + abort = this->GetAbortExecute(); + } + if ( npts > 1 ) + { + for (i=0; iInsertNextCell(1,pts+i); + outCD->CopyData(inCD, cellNum, newId++); + } + } + else + { + newCells->InsertNextCell(1,pts); + outCD->CopyData(inCD, cellNum, newId++); + } + } + output->SetVerts(newCells); + newCells->Delete(); + } + else + { + cellNum += cells->GetNumberOfCells(); //skip over verts + } + } + + // lines + if ( !abort && input->GetLines()->GetNumberOfCells() > 0 ) + { + cells = input->GetLines(); + if ( this->PassLines ) + { + newId = output->GetNumberOfCells(); + newCells = vtkCellArray::New(); + newCells->EstimateSize(cells->GetNumberOfCells(),2); + for (cells->InitTraversal(); cells->GetNextCell(npts,pts) && !abort; cellNum++) + { + if ( ! (cellNum % updateInterval) ) //manage progress reports / early abort + { + this->UpdateProgress ((float)cellNum / numCells); + abort = this->GetAbortExecute(); + } + if ( npts > 2 ) + { + for (i=0; i<(npts-1); i++) + { + newCells->InsertNextCell(2,pts+i); + outCD->CopyData(inCD, cellNum, newId++); + } + } + else + { + newCells->InsertNextCell(2,pts); + outCD->CopyData(inCD, cellNum, newId++); + } + }//for all lines + output->SetLines(newCells); + newCells->Delete(); + } + else + { + cellNum += cells->GetNumberOfCells(); //skip over lines + } + } + + vtkCellArray *newPolys=NULL; + if ( !abort && input->GetPolys()->GetNumberOfCells() > 0 ) + { + cells = input->GetPolys(); + newId = output->GetNumberOfCells(); + newPolys = vtkCellArray::New(); + newPolys->EstimateSize(cells->GetNumberOfCells(),3); + output->SetPolys(newPolys); + vtkIdList *ptIds = vtkIdList::New(); + ptIds->Allocate(VTK_CELL_SIZE); + int numSimplices; + vtkPolygon *poly=vtkPolygon::New(); + vtkIdType triPts[3]; + + for (cells->InitTraversal(); cells->GetNextCell(npts,pts) && !abort; cellNum++) + { + if ( ! (cellNum % updateInterval) ) //manage progress reports / early abort + { + this->UpdateProgress ((float)cellNum / numCells); + abort = this->GetAbortExecute(); + } + if ( npts == 3 ) + { + newPolys->InsertNextCell(3,pts); + outCD->CopyData(inCD, cellNum, newId++); + } + else //triangulate polygon + { + //initialize polygon + poly->PointIds->SetNumberOfIds(npts); + poly->Points->SetNumberOfPoints(npts); + for (i=0; iPointIds->SetId(i,pts[i]); + poly->Points->SetPoint(i,inPts->GetPoint(pts[i])); + } + poly->Triangulate(ptIds); + numPts = ptIds->GetNumberOfIds(); + numSimplices = numPts / 3; + for ( i=0; i < numSimplices; i++ ) + { + for (j=0; j<3; j++) + { + triPts[j] = poly->PointIds->GetId(ptIds->GetId(3*i+j)); + } + newPolys->InsertNextCell(3, triPts); + outCD->CopyData(inCD, cellNum, newId++); + }//for each simplex + }//triangulate polygon + } + ptIds->Delete(); + poly->Delete(); + } + + //strips + if ( !abort && input->GetStrips()->GetNumberOfCells() > 0 ) + { + cells = input->GetStrips(); + newId = output->GetNumberOfCells(); + if ( newPolys == NULL ) + { + newPolys = vtkCellArray::New(); + newPolys->EstimateSize(cells->GetNumberOfCells(),3); + output->SetPolys(newPolys); + } + for (cells->InitTraversal(); cells->GetNextCell(npts,pts) && !abort; cellNum++) + { + if ( ! (cellNum % updateInterval) ) //manage progress reports / early abort + { + this->UpdateProgress ((float)cellNum / numCells); + abort = this->GetAbortExecute(); + } + vtkTriangleStrip::DecomposeStrip(npts,pts,newPolys); + for (i=0; i<(npts-2); i++) + { + outCD->CopyData(inCD, cellNum, newId++); + } + }//for all strips + } + + if ( newPolys != NULL ) + { + newPolys->Delete(); + } + + // Update output + output->SetPoints(input->GetPoints()); + output->GetPointData()->PassData(input->GetPointData()); + output->Squeeze(); + + vtkDebugMacro(<<"Converted " << input->GetNumberOfCells() + << "input cells to " + << output->GetNumberOfCells() + <<" output cells"); + + + return 1; +} + +void vtkTriangleFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Pass Verts: " << (this->PassVerts ? "On\n" : "Off\n"); + os << indent << "Pass Lines: " << (this->PassLines ? "On\n" : "Off\n"); + +} diff --git a/Graphics/vtkTriangleFilter.h b/Graphics/vtkTriangleFilter.h new file mode 100644 index 0000000..fb3d150 --- /dev/null +++ b/Graphics/vtkTriangleFilter.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangleFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTriangleFilter - create triangle polygons from input polygons and triangle strips +// .SECTION Description +// vtkTriangleFilter generates triangles from input polygons and triangle +// strips. The filter also will pass through vertices and lines, if +// requested. + +#ifndef __vtkTriangleFilter_h +#define __vtkTriangleFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTriangleFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkTriangleFilter *New(); + vtkTypeRevisionMacro(vtkTriangleFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Turn on/off passing vertices through filter. + vtkBooleanMacro(PassVerts,int); + vtkSetMacro(PassVerts,int); + vtkGetMacro(PassVerts,int); + + // Description: + // Turn on/off passing lines through filter. + vtkBooleanMacro(PassLines,int); + vtkSetMacro(PassLines,int); + vtkGetMacro(PassLines,int); + +protected: + vtkTriangleFilter() : PassVerts(1), PassLines(1) {}; + ~vtkTriangleFilter() {}; + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int PassVerts; + int PassLines; +private: + vtkTriangleFilter(const vtkTriangleFilter&); // Not implemented. + void operator=(const vtkTriangleFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTriangularTCoords.cxx b/Graphics/vtkTriangularTCoords.cxx new file mode 100644 index 0000000..0176a21 --- /dev/null +++ b/Graphics/vtkTriangularTCoords.cxx @@ -0,0 +1,206 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangularTCoords.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTriangularTCoords.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +#include + +vtkCxxRevisionMacro(vtkTriangularTCoords, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkTriangularTCoords); + +int vtkTriangularTCoords::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType tmp; + int j; + vtkPoints *inPts; + vtkPointData *pd; + vtkCellArray *inPolys,*inStrips; + vtkIdType numNewPts, numNewPolys, polyAllocSize; + vtkFloatArray *newTCoords; + vtkIdType newId, numCells, cellId; + vtkIdType *pts = 0; + vtkIdType newIds[3]; + vtkIdType npts = 0;; + int errorLogging = 1; + vtkPoints *newPoints; + vtkCellArray *newPolys; + double p1[3], p2[3], p3[3]; + double tCoords[6]; + vtkPointData *pointData = output->GetPointData(); + + // Initialize + // + vtkDebugMacro(<<"Generating triangular texture coordinates"); + + inPts = input->GetPoints(); + pd = input->GetPointData(); + + inPolys = input->GetPolys(); + inStrips = input->GetStrips(); + + // Count the number of new points and other primitives that + // need to be created. + // + numNewPts = input->GetNumberOfVerts(); + + numNewPolys = 0; + polyAllocSize = 0; + + for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + numNewPts += npts; + numNewPolys++; + polyAllocSize += npts + 1; + } + for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); ) + { + numNewPts += (npts-2) * 3; + polyAllocSize += (npts - 2) * 4; + } + numCells = inPolys->GetNumberOfCells() + inStrips->GetNumberOfCells(); + + // Allocate texture data + // + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(2*numNewPts); + + // Allocate + // + newPoints = vtkPoints::New(); + newPoints->Allocate(numNewPts); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(polyAllocSize); + + pointData->CopyTCoordsOff(); + pointData->CopyAllocate(pd); + + // Texture coordinates are the same for each triangle + // + tCoords[0]= 0.0; + tCoords[1]= 0.0; + tCoords[2]= 1.0; + tCoords[3]= 0.0; + tCoords[4]= 0.5; + tCoords[5]= sqrt(3.0)/2.0; + + int abort=0; + vtkIdType progressInterval=numCells/20 + 1; + for (cellId=0, inPolys->InitTraversal(); + inPolys->GetNextCell(npts,pts) && !abort; cellId++) + { + if ( !(cellId % progressInterval) ) + { + this->UpdateProgress((double)cellId/numCells); + abort = this->GetAbortExecute(); + } + + if (npts != 3) + { + if (errorLogging) vtkWarningMacro( + << "No texture coordinates for this cell, it is not a triangle"); + errorLogging = 0; + continue; + } + newPolys->InsertNextCell(npts); + for (j=0; jGetPoint(pts[j], p1); + newId = newPoints->InsertNextPoint(p1); + newPolys->InsertCellPoint(newId); + pointData->CopyData(pd,pts[j],newId); + newTCoords->InsertNextTuple (&tCoords[2*j]); + } + } + + // Triangle strips + // + for (inStrips->InitTraversal(); + inStrips->GetNextCell(npts,pts) && !abort; cellId++) + { + if ( !(cellId % progressInterval) ) + { + this->UpdateProgress((double)cellId/numCells); + abort = this->GetAbortExecute(); + } + + for (j=0; j<(npts-2); j++) + { + inPts->GetPoint(pts[j], p1); + inPts->GetPoint(pts[j+1], p2); + inPts->GetPoint(pts[j+2], p3); + + newIds[0] = newPoints->InsertNextPoint(p1); + pointData->CopyData(pd,pts[j],newIds[0]); + newTCoords->InsertNextTuple (&tCoords[0]); + + newIds[1] = newPoints->InsertNextPoint(p2); + pointData->CopyData(pd,pts[j+1],newIds[1]); + newTCoords->InsertNextTuple (&tCoords[2]); + + newIds[2] = newPoints->InsertNextPoint(p3); + pointData->CopyData(pd,pts[j+2],newIds[2]); + newTCoords->InsertNextTuple (&tCoords[4]); + + // flip orientation for odd tris + if (j%2) + { + tmp = newIds[0]; + newIds[0] = newIds[2]; + newIds[2] = tmp; + } + newPolys->InsertNextCell(3,newIds); + } + } + + // Update self and release memory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); + + return 1; +} + +void vtkTriangularTCoords::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Graphics/vtkTriangularTCoords.h b/Graphics/vtkTriangularTCoords.h new file mode 100644 index 0000000..f584f8f --- /dev/null +++ b/Graphics/vtkTriangularTCoords.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangularTCoords.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTriangularTCoords - 2D texture coordinates based for triangles. +// .SECTION Description +// vtkTriangularTCoords is a filter that generates texture coordinates +// for triangles. Texture coordinates for each triangle are: +// (0,0), (1,0) and (.5,sqrt(3)/2). This filter assumes that the triangle +// texture map is symmetric about the center of the triangle. Thus the order +// Of the texture coordinates is not important. The procedural texture +// in vtkTriangularTexture is designed with this symmetry. For more information +// see the paper "Opacity-modulating Triangular Textures for Irregular +// Surfaces," by Penny Rheingans, IEEE Visualization '96, pp. 219-225. +// .SECTION See Also +// vtkTriangularTexture vtkThresholdPoints vtkTextureMapToPlane +// vtkTextureMapToSphere vtkTextureMapToCylinder vtkTextureMapToBox + +#ifndef __vtkTriangularTCoords_h +#define __vtkTriangularTCoords_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkTriangularTCoords : public vtkPolyDataAlgorithm +{ +public: + static vtkTriangularTCoords *New(); + vtkTypeRevisionMacro(vtkTriangularTCoords,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkTriangularTCoords() {}; + ~vtkTriangularTCoords() {}; + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); +private: + vtkTriangularTCoords(const vtkTriangularTCoords&); // Not implemented. + void operator=(const vtkTriangularTCoords&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkTubeFilter.cxx b/Graphics/vtkTubeFilter.cxx new file mode 100644 index 0000000..9dbb2c9 --- /dev/null +++ b/Graphics/vtkTubeFilter.cxx @@ -0,0 +1,808 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTubeFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTubeFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyLine.h" + +vtkCxxRevisionMacro(vtkTubeFilter, "$Revision: 1.87.6.1 $"); +vtkStandardNewMacro(vtkTubeFilter); + +// Construct object with radius 0.5, radius variation turned off, the number +// of sides set to 3, and radius factor of 10. +vtkTubeFilter::vtkTubeFilter() +{ + this->Radius = 0.5; + this->VaryRadius = VTK_VARY_RADIUS_OFF; + this->NumberOfSides = 3; + this->RadiusFactor = 10; + + this->DefaultNormal[0] = this->DefaultNormal[1] = 0.0; + this->DefaultNormal[2] = 1.0; + + this->UseDefaultNormal = 0; + this->SidesShareVertices = 1; + this->Capping = 0; + this->OnRatio = 1; + this->Offset = 0; + + this->GenerateTCoords = VTK_TCOORDS_OFF; + this->TextureLength = 1.0; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); + + // by default process active point vectors + this->SetInputArrayToProcess(1,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::VECTORS); +} + +int vtkTubeFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(); + vtkPointData *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(); + vtkCellData *outCD=output->GetCellData(); + vtkCellArray *inLines; + vtkDataArray *inNormals; + vtkDataArray *inScalars=this->GetInputArrayToProcess(0,inputVector); + vtkDataArray *inVectors=this->GetInputArrayToProcess(1,inputVector); + + vtkPoints *inPts; + vtkIdType numPts; + vtkIdType numLines; + vtkIdType numNewPts, numNewCells; + vtkPoints *newPts; + int deleteNormals=0; + vtkFloatArray *newNormals; + vtkIdType i; + double range[2], maxSpeed=0; + vtkCellArray *newStrips; + vtkIdType npts=0, *pts=NULL; + vtkIdType offset=0; + vtkFloatArray *newTCoords=NULL; + int abort=0; + vtkIdType inCellId; + double oldRadius=1.0; + + // Check input and initialize + // + vtkDebugMacro(<<"Creating tube"); + + if ( !(inPts=input->GetPoints()) || + (numPts = inPts->GetNumberOfPoints()) < 1 || + !(inLines = input->GetLines()) || + (numLines = inLines->GetNumberOfCells()) < 1 ) + { + return 1; + } + + // Create the geometry and topology + numNewPts = numPts * this->NumberOfSides; + newPts = vtkPoints::New(); + newPts->Allocate(numNewPts); + newNormals = vtkFloatArray::New(); + newNormals->SetName("TubeNormals"); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numNewPts); + newStrips = vtkCellArray::New(); + newStrips->Allocate(newStrips->EstimateSize(1,numNewPts)); + vtkCellArray *singlePolyline = vtkCellArray::New(); + + // Point data: copy scalars, vectors, tcoords. Normals may be computed here. + outPD->CopyNormalsOff(); + if ( (this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS && inScalars) || + this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH || + this->GenerateTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH ) + { + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(2); + newTCoords->Allocate(numNewPts); + outPD->CopyTCoordsOff(); + } + outPD->CopyAllocate(pd,numNewPts); + + int generateNormals = 0; + if ( !(inNormals=pd->GetNormals()) || this->UseDefaultNormal ) + { + deleteNormals = 1; + inNormals = vtkFloatArray::New(); + inNormals->SetNumberOfComponents(3); + inNormals->SetNumberOfTuples(numPts); + + if ( this->UseDefaultNormal ) + { + for ( i=0; i < numPts; i++) + { + inNormals->SetTuple(i,this->DefaultNormal); + } + } + else + { + // Normal generation has been moved to lower in the function. + // This allows each different polylines to share vertices, but have + // their normals (and hence their tubes) calculated independently + generateNormals = 1; + } + } + + // If varying width, get appropriate info. + // + if ( inScalars ) + { + inScalars->GetRange(range,0); + if ((range[1] - range[0]) == 0.0) + { + if (this->VaryRadius == VTK_VARY_RADIUS_BY_SCALAR ) + { + vtkWarningMacro(<< "Scalar range is zero!"); + } + range[1] = range[0] + 1.0; + } + if (this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR) + { + // temporarily set the radius to 1.0 so that radius*scalar = scalar + oldRadius = this->Radius; + this->Radius = 1.0; + if (range[0] < 0.0) + { + vtkWarningMacro(<< "Scalar values fall below zero when using absolute radius values!"); + } + } + } + if ( inVectors ) + { + maxSpeed = inVectors->GetMaxNorm(); + } + + // Copy selected parts of cell data; certainly don't want normals + // + numNewCells = inLines->GetNumberOfCells() * this->NumberOfSides + 2; + outCD->CopyNormalsOff(); + outCD->CopyAllocate(cd,numNewCells); + + // Create points along each polyline that are connected into NumberOfSides + // triangle strips. Texture coordinates are optionally generated. + // + this->Theta = 2.0*vtkMath::Pi() / this->NumberOfSides; + vtkPolyLine *lineNormalGenerator = vtkPolyLine::New(); + for (inCellId=0, inLines->InitTraversal(); + inLines->GetNextCell(npts,pts) && !abort; inCellId++) + { + this->UpdateProgress((double)inCellId/numLines); + abort = this->GetAbortExecute(); + + if (npts < 2) + { + vtkWarningMacro(<< "Less than two points in line!"); + continue; //skip tubing this polyline + } + + // If necessary calculate normals, each polyline calculates its + // normals independently, avoiding conflicts at shared vertices. + if (generateNormals) + { + singlePolyline->Reset(); //avoid instantiation + singlePolyline->InsertNextCell(npts,pts); + if ( !lineNormalGenerator->GenerateSlidingNormals(inPts,singlePolyline, + inNormals) ) + { + vtkWarningMacro("Could not generate normals for line. " + "Skipping to next."); + continue; //skip tubing this polyline + } + } + + // Generate the points around the polyline. The tube is not stripped + // if the polyline is bad. + // + if ( !this->GeneratePoints(offset,npts,pts,inPts,newPts,pd,outPD, + newNormals,inScalars,range,inVectors, + maxSpeed,inNormals) ) + { + vtkWarningMacro(<< "Could not generate points!"); + continue; //skip tubing this polyline + } + + // Generate the strips for this polyline (including caps) + // + this->GenerateStrips(offset,npts,pts,inCellId,cd,outCD,newStrips); + + // Generate the texture coordinates for this polyline + // + if ( newTCoords ) + { + this->GenerateTextureCoords(offset,npts,pts,inPts,inScalars,newTCoords); + } + + // Compute the new offset for the next polyline + offset = this->ComputeOffset(offset,npts); + + }//for all polylines + + singlePolyline->Delete(); + + // reset the radius to ite orginal value if necessary + if (this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR) + { + this->Radius = oldRadius; + } + + // Update ourselves + // + if ( deleteNormals ) + { + inNormals->Delete(); + } + + if ( newTCoords ) + { + outPD->SetTCoords(newTCoords); + newTCoords->Delete(); + } + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetStrips(newStrips); + newStrips->Delete(); + + outPD->SetNormals(newNormals); + newNormals->Delete(); + lineNormalGenerator->Delete(); + + output->Squeeze(); + + return 1; +} + +int vtkTubeFilter::GeneratePoints(vtkIdType offset, + vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, vtkPoints *newPts, + vtkPointData *pd, vtkPointData *outPD, + vtkFloatArray *newNormals, + vtkDataArray *inScalars, double range[2], + vtkDataArray *inVectors, double maxSpeed, + vtkDataArray *inNormals) +{ + vtkIdType j; + int i, k; + double p[3]; + double pNext[3]; + double sNext[3]; + double sPrev[3]; + double startCapNorm[3], endCapNorm[3]; + double n[3]; + double s[3]; + //double bevelAngle; + double w[3]; + double nP[3]; + double sFactor=1.0; + double normal[3]; + vtkIdType ptId=offset; + + // Use "averaged" segment to create beveled effect. + // Watch out for first and last points. + // + for (j=0; j < npts; j++) + { + if ( j == 0 ) //first point + { + inPts->GetPoint(pts[0],p); + inPts->GetPoint(pts[1],pNext); + for (i=0; i<3; i++) + { + sNext[i] = pNext[i] - p[i]; + sPrev[i] = sNext[i]; + startCapNorm[i] = -sPrev[i]; + } + vtkMath::Normalize(startCapNorm); + } + else if ( j == (npts-1) ) //last point + { + for (i=0; i<3; i++) + { + sPrev[i] = sNext[i]; + p[i] = pNext[i]; + endCapNorm[i] = sNext[i]; + } + vtkMath::Normalize(endCapNorm); + } + else + { + for (i=0; i<3; i++) + { + p[i] = pNext[i]; + } + inPts->GetPoint(pts[j+1],pNext); + for (i=0; i<3; i++) + { + sPrev[i] = sNext[i]; + sNext[i] = pNext[i] - p[i]; + } + } + + inNormals->GetTuple(pts[j], n); + + if ( vtkMath::Normalize(sNext) == 0.0 ) + { + vtkWarningMacro(<<"Coincident points!"); + return 0; + } + + for (i=0; i<3; i++) + { + s[i] = (sPrev[i] + sNext[i]) / 2.0; //average vector + } + // if s is zero then just use sPrev cross n + if (vtkMath::Normalize(s) == 0.0) + { + vtkDebugMacro(<< "Using alternate bevel vector"); + vtkMath::Cross(sPrev,n,s); + if (vtkMath::Normalize(s) == 0.0) + { + vtkDebugMacro(<< "Using alternate bevel vector"); + } + } + +/* if ( (bevelAngle = vtkMath::Dot(sNext,sPrev)) > 1.0 ) + { + bevelAngle = 1.0; + } + if ( bevelAngle < -1.0 ) + { + bevelAngle = -1.0; + } + bevelAngle = acos((double)bevelAngle) / 2.0; //(0->90 degrees) + if ( (bevelAngle = cos(bevelAngle)) == 0.0 ) + { + bevelAngle = 1.0; + } + + bevelAngle = this->Radius / bevelAngle; //keep tube constant radius +*/ + vtkMath::Cross(s,n,w); + if ( vtkMath::Normalize(w) == 0.0) + { + vtkWarningMacro(<<"Bad normal s = " <VaryRadius == VTK_VARY_RADIUS_BY_SCALAR ) + { + sFactor = 1.0 + ((this->RadiusFactor - 1.0) * + (inScalars->GetComponent(pts[j],0) - range[0]) + / (range[1]-range[0])); + } + else if ( inVectors && this->VaryRadius == VTK_VARY_RADIUS_BY_VECTOR ) + { + sFactor = + sqrt((double)maxSpeed/vtkMath::Norm(inVectors->GetTuple(pts[j]))); + if ( sFactor > this->RadiusFactor ) + { + sFactor = this->RadiusFactor; + } + } + else if ( inScalars && + this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR ) + { + sFactor = inScalars->GetComponent(pts[j],0); + if (sFactor < 0.0) + { + vtkWarningMacro(<<"Scalar value less than zero, skipping line"); + return 0; + } + } + + //create points around line + if (this->SidesShareVertices) + { + for (k=0; k < this->NumberOfSides; k++) + { + for (i=0; i<3; i++) + { + normal[i] = w[i]*cos((double)k*this->Theta) + + nP[i]*sin((double)k*this->Theta); + s[i] = p[i] + this->Radius * sFactor * normal[i]; + } + newPts->InsertPoint(ptId,s); + newNormals->InsertTuple(ptId,normal); + outPD->CopyData(pd,pts[j],ptId); + ptId++; + }//for each side + } + else + { + double n_left[3], n_right[3]; + for (k=0; k < this->NumberOfSides; k++) + { + for (i=0; i<3; i++) + { + // Create duplicate vertices at each point + // and adjust the associated normals so that they are + // oriented with the facets. This preserves the tube's + // polygonal appearance, as if by flat-shading around the tube, + // while still allowing smooth (gouraud) shading along the + // tube as it bends. + normal[i] = w[i]*cos((double)(k+0.0)*this->Theta) + + nP[i]*sin((double)(k+0.0)*this->Theta); + n_right[i] = w[i]*cos((double)(k-0.5)*this->Theta) + + nP[i]*sin((double)(k-0.5)*this->Theta); + n_left[i] = w[i]*cos((double)(k+0.5)*this->Theta) + + nP[i]*sin((double)(k+0.5)*this->Theta); + s[i] = p[i] + this->Radius * sFactor * normal[i]; + } + newPts->InsertPoint(ptId,s); + newNormals->InsertTuple(ptId,n_right); + outPD->CopyData(pd,pts[j],ptId); + newPts->InsertPoint(ptId+1,s); + newNormals->InsertTuple(ptId+1,n_left); + outPD->CopyData(pd,pts[j],ptId+1); + ptId += 2; + }//for each side + }//else separate vertices + }//for all points in polyline + + //Produce end points for cap. They are placed at tail end of points. + if (this->Capping) + { + int numCapSides = this->NumberOfSides; + int capIncr = 1; + if ( ! this->SidesShareVertices ) + { + numCapSides = 2 * this->NumberOfSides; + capIncr = 2; + } + + //the start cap + for (k=0; k < numCapSides; k+=capIncr) + { + newPts->GetPoint(offset+k,s); + newPts->InsertPoint(ptId,s); + newNormals->InsertTuple(ptId,startCapNorm); + outPD->CopyData(pd,pts[0],ptId); + ptId++; + } + //the end cap + int endOffset = offset + (npts-1)*this->NumberOfSides; + if ( ! this->SidesShareVertices ) + { + endOffset = offset + 2*(npts-1)*this->NumberOfSides; + } + for (k=0; k < numCapSides; k+=capIncr) + { + newPts->GetPoint(endOffset+k,s); + newPts->InsertPoint(ptId,s); + newNormals->InsertTuple(ptId,endCapNorm); + outPD->CopyData(pd,pts[npts-1],ptId); + ptId++; + } + }//if capping + + return 1; +} + +void vtkTubeFilter::GenerateStrips(vtkIdType offset, vtkIdType npts, + vtkIdType* vtkNotUsed(pts), + vtkIdType inCellId, + vtkCellData *cd, vtkCellData *outCD, + vtkCellArray *newStrips) +{ + vtkIdType i, outCellId; + int k; + int i1, i2, i3; + + if (this->SidesShareVertices) + { + for (k=this->Offset; k<(this->NumberOfSides+this->Offset); + k+=this->OnRatio) + { + i1 = k % this->NumberOfSides; + i2 = (k+1) % this->NumberOfSides; + outCellId = newStrips->InsertNextCell(npts*2); + outCD->CopyData(cd,inCellId,outCellId); + for (i=0; i < npts; i++) + { + i3 = i*this->NumberOfSides; + newStrips->InsertCellPoint(offset+i2+i3); + newStrips->InsertCellPoint(offset+i1+i3); + } + } //for each side of the tube + } + else + { + for (k=this->Offset; k<(this->NumberOfSides+this->Offset); + k+=this->OnRatio) + { + i1 = 2*(k % this->NumberOfSides) + 1; + i2 = 2*((k+1) % this->NumberOfSides); + outCellId = newStrips->InsertNextCell(npts*2); + outCD->CopyData(cd,inCellId,outCellId); + for (i=0; i < npts; i++) + { + i3 = i*2*this->NumberOfSides; + newStrips->InsertCellPoint(offset+i2+i3); + newStrips->InsertCellPoint(offset+i1+i3); + } + } //for each side of the tube + } + + // Take care of capping. The caps are n-sided polygons that can be + // easily triangle stripped. + if (this->Capping) + { + vtkIdType startIdx = offset + npts*this->NumberOfSides; + vtkIdType idx; + + if ( ! this->SidesShareVertices ) + { + startIdx = offset + 2*npts*this->NumberOfSides; + } + + //The start cap + outCellId = newStrips->InsertNextCell(this->NumberOfSides); + outCD->CopyData(cd,inCellId,outCellId); + newStrips->InsertCellPoint(startIdx); + newStrips->InsertCellPoint(startIdx+1); + for (i1=this->NumberOfSides-1, i2=2, k=0; k<(this->NumberOfSides-2); k++) + { + if ( (k%2) ) + { + idx = startIdx + i2; + newStrips->InsertCellPoint(idx); + i2++; + } + else + { + idx = startIdx + i1; + newStrips->InsertCellPoint(idx); + i1--; + } + } + + //The end cap - reversed order to be consistent with normal + startIdx += this->NumberOfSides; + outCellId = newStrips->InsertNextCell(this->NumberOfSides); + outCD->CopyData(cd,inCellId,outCellId); + newStrips->InsertCellPoint(startIdx); + newStrips->InsertCellPoint(startIdx+this->NumberOfSides-1); + for (i1=this->NumberOfSides-2, i2=1, k=0; k<(this->NumberOfSides-2); k++) + { + if ( (k%2) ) + { + idx = startIdx + i1; + newStrips->InsertCellPoint(idx); + i1--; + } + else + { + idx = startIdx + i2; + newStrips->InsertCellPoint(idx); + i2++; + } + } + } +} + +void vtkTubeFilter::GenerateTextureCoords(vtkIdType offset, + vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, + vtkDataArray *inScalars, + vtkFloatArray *newTCoords) +{ + vtkIdType i; + int k; + double tc=0.0; + + int numSides = this->NumberOfSides; + if ( ! this->SidesShareVertices ) + { + numSides = 2 * this->NumberOfSides; + } + + double s0, s; + //The first texture coordinate is always 0. + for ( k=0; k < numSides; k++) + { + newTCoords->InsertTuple2(offset+k,0.0,0.0); + } + if ( this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS ) + { + s0 = inScalars->GetTuple1(pts[0]); + for (i=1; i < npts; i++) + { + s = inScalars->GetTuple1(pts[i]); + tc = (s - s0) / this->TextureLength; + for ( k=0; k < numSides; k++) + { + newTCoords->InsertTuple2(offset+i*numSides+k,tc,0.0); + } + } + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH ) + { + double xPrev[3], x[3], len=0.0; + inPts->GetPoint(pts[0],xPrev); + for (i=1; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + tc = len / this->TextureLength; + for ( k=0; k < numSides; k++) + { + newTCoords->InsertTuple2(offset+i*numSides+k,tc,0.0); + } + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH ) + { + double xPrev[3], x[3], length=0.0, len=0.0; + inPts->GetPoint(pts[0],xPrev); + for (i=1; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + length += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + + inPts->GetPoint(pts[0],xPrev); + for (i=1; i < npts; i++) + { + inPts->GetPoint(pts[i],x); + len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + tc = len / length; + for ( k=0; k < numSides; k++) + { + newTCoords->InsertTuple2(offset+i*2+k,tc,0.0); + } + xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2]; + } + } + + // Capping, set the endpoints as appropriate + if ( this->Capping ) + { + int ik; + vtkIdType startIdx = offset + npts*numSides; + + //start cap + for (ik=0; ik < this->NumberOfSides; ik++) + { + newTCoords->InsertTuple2(startIdx+ik,0.0,0.0); + } + + //end cap + for (ik=0; ik < this->NumberOfSides; ik++) + { + newTCoords->InsertTuple2(startIdx+this->NumberOfSides+ik,tc,0.0); + } + } +} + +// Compute the number of points in this tube +vtkIdType vtkTubeFilter::ComputeOffset(vtkIdType offset, vtkIdType npts) +{ + if ( this->SidesShareVertices ) + { + offset += this->NumberOfSides * npts; + } + else + { + offset += 2 * this->NumberOfSides * npts; //points are duplicated + } + + if ( this->Capping ) + { + offset += 2*this->NumberOfSides; //cap points are duplicated + } + + return offset; +} + +// Description: +// Return the method of varying tube radius descriptive character string. +const char *vtkTubeFilter::GetVaryRadiusAsString(void) +{ + if ( this->VaryRadius == VTK_VARY_RADIUS_OFF ) + { + return "VaryRadiusOff"; + } + else if ( this->VaryRadius == VTK_VARY_RADIUS_BY_SCALAR ) + { + return "VaryRadiusByScalar"; + } + else if ( this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR ) + { + return "VaryRadiusByAbsoluteScalar"; + } + else + { + return "VaryRadiusByVector"; + } +} + +// Description: +// Return the method of generating the texture coordinates. +const char *vtkTubeFilter::GetGenerateTCoordsAsString(void) +{ + if ( this->GenerateTCoords == VTK_TCOORDS_OFF ) + { + return "GenerateTCoordsOff"; + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS ) + { + return "GenerateTCoordsFromScalar"; + } + else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH ) + { + return "GenerateTCoordsFromLength"; + } + else + { + return "GenerateTCoordsFromNormalizedLength"; + } +} + +void vtkTubeFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Vary Radius: " << this->GetVaryRadiusAsString() << endl; + os << indent << "Radius Factor: " << this->RadiusFactor << "\n"; + os << indent << "Number Of Sides: " << this->NumberOfSides << "\n"; + os << indent << "On Ratio: " << this->OnRatio << "\n"; + os << indent << "Offset: " << this->Offset << "\n"; + + os << indent << "Use Default Normal: " + << (this->UseDefaultNormal ? "On\n" : "Off\n"); + os << indent << "Sides Share Vertices: " + << (this->SidesShareVertices ? "On\n" : "Off\n"); + os << indent << "Default Normal: " << "( " << this->DefaultNormal[0] << + ", " << this->DefaultNormal[1] << ", " << this->DefaultNormal[2] << + " )\n"; + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); + os << indent << "Generate TCoords: " + << this->GetGenerateTCoordsAsString() << endl; + os << indent << "Texture Length: " << this->TextureLength << endl; +} diff --git a/Graphics/vtkTubeFilter.h b/Graphics/vtkTubeFilter.h new file mode 100644 index 0000000..5b6086f --- /dev/null +++ b/Graphics/vtkTubeFilter.h @@ -0,0 +1,223 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTubeFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTubeFilter - filter that generates tubes around lines +// .SECTION Description +// vtkTubeFilter is a filter that generates a tube around each input line. +// The tubes are made up of triangle strips and rotate around the tube with +// the rotation of the line normals. (If no normals are present, they are +// computed automatically.) The radius of the tube can be set to vary with +// scalar or vector value. If the radius varies with scalar value the radius +// is linearly adjusted. If the radius varies with vector value, a mass +// flux preserving variation is used. The number of sides for the tube also +// can be specified. You can also specify which of the sides are visible. This +// is useful for generating interesting striping effects. Other options +// include the ability to cap the tube and generate texture coordinates. +// Texture coordinates can be used with an associated texture map to create +// interesting effects such as marking the tube with stripes corresponding +// to length or time. +// +// This filter is typically used to create thick or dramatic lines. Another +// common use is to combine this filter with vtkStreamLine to generate +// streamtubes. + +// .SECTION Caveats +// The number of tube sides must be greater than 3. If you wish to use fewer +// sides (i.e., a ribbon), use vtkRibbonFilter. +// +// The input line must not have duplicate points, or normals at points that +// are parallel to the incoming/outgoing line segments. (Duplicate points +// can be removed with vtkCleanPolyData.) If a line does not meet this +// criteria, then that line is not tubed. + +// .SECTION See Also +// vtkRibbonFilter vtkStreamLine + +// .SECTION Thanks +// Michael Finch for absolute scalar radius + +#ifndef __vtkTubeFilter_h +#define __vtkTubeFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_VARY_RADIUS_OFF 0 +#define VTK_VARY_RADIUS_BY_SCALAR 1 +#define VTK_VARY_RADIUS_BY_VECTOR 2 +#define VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR 3 + +#define VTK_TCOORDS_OFF 0 +#define VTK_TCOORDS_FROM_NORMALIZED_LENGTH 1 +#define VTK_TCOORDS_FROM_LENGTH 2 +#define VTK_TCOORDS_FROM_SCALARS 3 + +class vtkCellArray; +class vtkCellData; +class vtkDataArray; +class vtkFloatArray; +class vtkPointData; +class vtkPoints; + +class VTK_GRAPHICS_EXPORT vtkTubeFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTubeFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with radius 0.5, radius variation turned off, the + // number of sides set to 3, and radius factor of 10. + static vtkTubeFilter *New(); + + // Description: + // Set the minimum tube radius (minimum because the tube radius may vary). + vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(Radius,double); + + // Description: + // Turn on/off the variation of tube radius with scalar value. + vtkSetClampMacro(VaryRadius,int, + VTK_VARY_RADIUS_OFF,VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR); + vtkGetMacro(VaryRadius,int); + void SetVaryRadiusToVaryRadiusOff() + {this->SetVaryRadius(VTK_VARY_RADIUS_OFF);}; + void SetVaryRadiusToVaryRadiusByScalar() + {this->SetVaryRadius(VTK_VARY_RADIUS_BY_SCALAR);}; + void SetVaryRadiusToVaryRadiusByVector() + {this->SetVaryRadius(VTK_VARY_RADIUS_BY_VECTOR);}; + void SetVaryRadiusToVaryRadiusByAbsoluteScalar() + {this->SetVaryRadius(VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR);}; + const char *GetVaryRadiusAsString(); + + // Description: + // Set the number of sides for the tube. At a minimum, number of sides is 3. + vtkSetClampMacro(NumberOfSides,int,3,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfSides,int); + + // Description: + // Set the maximum tube radius in terms of a multiple of the minimum radius. + vtkSetMacro(RadiusFactor,double); + vtkGetMacro(RadiusFactor,double); + + // Description: + // Set the default normal to use if no normals are supplied, and the + // DefaultNormalOn is set. + vtkSetVector3Macro(DefaultNormal,double); + vtkGetVectorMacro(DefaultNormal,double,3); + + // Description: + // Set a boolean to control whether to use default normals. + // DefaultNormalOn is set. + vtkSetMacro(UseDefaultNormal,int); + vtkGetMacro(UseDefaultNormal,int); + vtkBooleanMacro(UseDefaultNormal,int); + + // Description: + // Set a boolean to control whether tube sides should share vertices. + // This creates independent strips, with constant normals so the + // tube is always faceted in appearance. + vtkSetMacro(SidesShareVertices, int); + vtkGetMacro(SidesShareVertices, int); + vtkBooleanMacro(SidesShareVertices, int); + + // Description: + // Turn on/off whether to cap the ends with polygons. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + + // Description: + // Control the striping of the tubes. If OnRatio is greater than 1, + // then every nth tube side is turned on, beginning with the Offset + // side. + vtkSetClampMacro(OnRatio,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(OnRatio,int); + + // Description: + // Control the striping of the tubes. The offset sets the + // first tube side that is visible. Offset is generally used with + // OnRatio to create nifty striping effects. + vtkSetClampMacro(Offset,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(Offset,int); + + // Description: + // Control whether and how texture coordinates are produced. This is + // useful for striping the tube with length textures, etc. If you + // use scalars to create the texture, the scalars are assumed to be + // monotonically increasing (or decreasing). + vtkSetClampMacro(GenerateTCoords,int,VTK_TCOORDS_OFF, + VTK_TCOORDS_FROM_SCALARS); + vtkGetMacro(GenerateTCoords,int); + void SetGenerateTCoordsToOff() + {this->SetGenerateTCoords(VTK_TCOORDS_OFF);} + void SetGenerateTCoordsToNormalizedLength() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_NORMALIZED_LENGTH);} + void SetGenerateTCoordsToUseLength() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_LENGTH);} + void SetGenerateTCoordsToUseScalars() + {this->SetGenerateTCoords(VTK_TCOORDS_FROM_SCALARS);} + const char *GetGenerateTCoordsAsString(); + + // Description: + // Control the conversion of units during the texture coordinates + // calculation. The TextureLength indicates what length (whether + // calculated from scalars or length) is mapped to the [0,1) + // texture space. + vtkSetClampMacro(TextureLength,double,0.000001,VTK_LARGE_INTEGER); + vtkGetMacro(TextureLength,double); + +protected: + vtkTubeFilter(); + ~vtkTubeFilter() {} + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Radius; //minimum radius of tube + int VaryRadius; //controls radius variation + int NumberOfSides; //number of sides to create tube + double RadiusFactor; //maxium allowablew radius + double DefaultNormal[3]; + int UseDefaultNormal; + int SidesShareVertices; + int Capping; //control whether tubes are capped + int OnRatio; //control the generation of the sides of the tube + int Offset; //control the generation of the sides + int GenerateTCoords; //control texture coordinate generation + double TextureLength; //this length is mapped to [0,1) texture space + + // Helper methods + int GeneratePoints(vtkIdType offset, vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, vtkPoints *newPts, + vtkPointData *pd, vtkPointData *outPD, + vtkFloatArray *newNormals, vtkDataArray *inScalars, + double range[2], vtkDataArray *inVectors, double maxNorm, + vtkDataArray *inNormals); + void GenerateStrips(vtkIdType offset, vtkIdType npts, vtkIdType *pts, + vtkIdType inCellId, vtkCellData *cd, vtkCellData *outCD, + vtkCellArray *newStrips); + void GenerateTextureCoords(vtkIdType offset, vtkIdType npts, vtkIdType *pts, + vtkPoints *inPts, vtkDataArray *inScalars, + vtkFloatArray *newTCoords); + vtkIdType ComputeOffset(vtkIdType offset,vtkIdType npts); + + // Helper data members + double Theta; + +private: + vtkTubeFilter(const vtkTubeFilter&); // Not implemented. + void operator=(const vtkTubeFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkVectorDot.cxx b/Graphics/vtkVectorDot.cxx new file mode 100644 index 0000000..e3e98a7 --- /dev/null +++ b/Graphics/vtkVectorDot.cxx @@ -0,0 +1,149 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVectorDot.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVectorDot.h" + +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkVectorDot, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkVectorDot); + +// Construct object with scalar range is (-1,1). +vtkVectorDot::vtkVectorDot() +{ + this->ScalarRange[0] = -1.0; + this->ScalarRange[1] = 1.0; +} + +// +// Compute dot product. +// +int vtkVectorDot::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType ptId, numPts; + vtkFloatArray *newScalars; + vtkDataArray *inNormals; + vtkDataArray *inVectors; + double s, n[3], v[3], min, max, dR, dS; + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + + // Initialize + // + vtkDebugMacro(<<"Generating vector/normal dot product!"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if ( (numPts=input->GetNumberOfPoints()) < 1 ) + { + vtkErrorMacro(<< "No points!"); + return 1; + } + if ( (inVectors=pd->GetVectors()) == NULL ) + { + vtkErrorMacro(<< "No vectors defined!"); + return 1; + } + if ( (inNormals=pd->GetNormals()) == NULL ) + { + vtkErrorMacro(<< "No normals defined!"); + return 1; + } + + // Allocate + // + newScalars = vtkFloatArray::New(); + newScalars->Allocate(numPts); + + // Compute initial scalars + // + int abort=0; + vtkIdType progressInterval=numPts/20 + 1; + for (min=VTK_DOUBLE_MAX,max=(-VTK_DOUBLE_MAX),ptId=0; + ptId < numPts && !abort; ptId++) + { + if ( ! (ptId % progressInterval) ) + { + this->UpdateProgress ((double)ptId/numPts); + abort = this->GetAbortExecute(); + } + inNormals->GetTuple(ptId, n); + inVectors->GetTuple(ptId, v); + s = vtkMath::Dot(n,v); + if ( s < min ) + { + min = s; + } + if ( s > max ) + { + max = s; + } + newScalars->InsertTuple(ptId,&s); + } + + // Map scalars into scalar range + // + if ( (dR=this->ScalarRange[1]-this->ScalarRange[0]) == 0.0 ) + { + dR = 1.0; + } + if ( (dS=max-min) == 0.0 ) + { + dS = 1.0; + } + + for ( ptId=0; ptId < numPts; ptId++ ) + { + s = newScalars->GetComponent(ptId,0); + s = ((s - min)/dS) * dR + this->ScalarRange[0]; + newScalars->InsertTuple(ptId,&s); + } + + // Update self and relase memory + // + outPD->PassData(input->GetPointData()); + + int idx = outPD->AddArray(newScalars); + outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + + return 1; +} + +void vtkVectorDot::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Scalar Range: (" << this->ScalarRange[0] << ", " + << this->ScalarRange[1] << ")\n"; +} diff --git a/Graphics/vtkVectorDot.h b/Graphics/vtkVectorDot.h new file mode 100644 index 0000000..7732365 --- /dev/null +++ b/Graphics/vtkVectorDot.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVectorDot.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVectorDot - generate scalars from dot product of vectors and normals (e.g., show displacement plot) +// .SECTION Description +// vtkVectorDot is a filter to generate scalar values from a dataset. +// The scalar value at a point is created by computing the dot product +// between the normal and vector at that point. Combined with the appropriate +// color map, this can show nodal lines/mode shapes of vibration, or a +// displacement plot. + +#ifndef __vtkVectorDot_h +#define __vtkVectorDot_h + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkVectorDot : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkVectorDot,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with scalar range is (-1,1). + static vtkVectorDot *New(); + + // Description: + // Specify range to map scalars into. + vtkSetVector2Macro(ScalarRange,double); + + // Description: + // Get the range that scalars map into. + vtkGetVectorMacro(ScalarRange,double,2); + +protected: + vtkVectorDot(); + ~vtkVectorDot() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double ScalarRange[2]; +private: + vtkVectorDot(const vtkVectorDot&); // Not implemented. + void operator=(const vtkVectorDot&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkVectorNorm.cxx b/Graphics/vtkVectorNorm.cxx new file mode 100644 index 0000000..3306596 --- /dev/null +++ b/Graphics/vtkVectorNorm.cxx @@ -0,0 +1,200 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVectorNorm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVectorNorm.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkVectorNorm, "$Revision: 1.44 $"); +vtkStandardNewMacro(vtkVectorNorm); + +// Construct with normalize flag off. +vtkVectorNorm::vtkVectorNorm() +{ + this->Normalize = 0; + this->AttributeMode = VTK_ATTRIBUTE_MODE_DEFAULT; +} + +int vtkVectorNorm::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numVectors, i; + int computePtScalars=1, computeCellScalars=1; + vtkFloatArray *newScalars; + double v[3], s, maxScalar; + vtkDataArray *ptVectors, *cellVectors; + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + + // Initialize + vtkDebugMacro(<<"Computing norm of vectors!"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + ptVectors = pd->GetVectors(); + cellVectors = cd->GetVectors(); + if (!ptVectors || this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_CELL_DATA) + { + computePtScalars = 0; + } + + if (!cellVectors || this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_POINT_DATA) + { + computeCellScalars = 0; + } + + if ( !computeCellScalars && !computePtScalars ) + { + vtkErrorMacro(<< "No vector norm to compute!"); + return 1; + } + + // Allocate / operate on point data + int abort=0; + vtkIdType progressInterval; + if ( computePtScalars ) + { + numVectors = ptVectors->GetNumberOfTuples(); + newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfTuples(numVectors); + + progressInterval=numVectors/10+1; + for (maxScalar=0.0, i=0; i < numVectors && !abort; i++) + { + ptVectors->GetTuple(i, v); + s = sqrt((double)v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); + if ( s > maxScalar ) + { + maxScalar = s; + } + newScalars->SetComponent(i,0,s); + + if ( ! (i % progressInterval) ) + { + vtkDebugMacro(<<"Computing point vector norm #" << i); + this->UpdateProgress (0.5*i/numVectors); + } + } + + // If necessary, normalize + if ( this->Normalize && maxScalar > 0.0 ) + { + for (i=0; i < numVectors; i++) + { + s = newScalars->GetComponent(i,0); + s /= maxScalar; + newScalars->SetComponent(i,0,s); + } + } + + int idx = outPD->AddArray(newScalars); + outPD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + outPD->CopyScalarsOff(); + }//if computing point scalars + + // Allocate / operate on cell data + if ( computeCellScalars ) + { + numVectors = cellVectors->GetNumberOfTuples(); + newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfTuples(numVectors); + + progressInterval=numVectors/10+1; + for (maxScalar=0.0, i=0; i < numVectors && !abort; i++) + { + cellVectors->GetTuple(i, v); + s = sqrt((double)v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); + if ( s > maxScalar ) + { + maxScalar = s; + } + newScalars->SetComponent(i,0,s); + if ( ! (i % progressInterval) ) + { + vtkDebugMacro(<<"Computing cell vector norm #" << i); + this->UpdateProgress (0.5+0.5*i/numVectors); + } + } + + // If necessary, normalize + if ( this->Normalize && maxScalar > 0.0 ) + { + for (i=0; i < numVectors; i++) + { + s = newScalars->GetComponent(i,0); + s /= maxScalar; + newScalars->SetComponent(i,0,s); + } + } + + int idx = outCD->AddArray(newScalars); + outCD->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + outCD->CopyScalarsOff(); + }//if computing cell scalars + + // Pass appropriate data through to output + outPD->PassData(pd); + outCD->PassData(cd); + + return 1; +} + +// Return the method for generating scalar data as a string. +const char *vtkVectorNorm::GetAttributeModeAsString(void) +{ + if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_DEFAULT ) + { + return "Default"; + } + else if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else + { + return "UseCellData"; + } +} + +void vtkVectorNorm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Normalize: " << (this->Normalize ? "On\n" : "Off\n"); + os << indent << "Attribute Mode: " << this->GetAttributeModeAsString() + << endl; +} diff --git a/Graphics/vtkVectorNorm.h b/Graphics/vtkVectorNorm.h new file mode 100644 index 0000000..f649fc6 --- /dev/null +++ b/Graphics/vtkVectorNorm.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVectorNorm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVectorNorm - generate scalars from Euclidean norm of vectors +// .SECTION Description +// vtkVectorNorm is a filter that generates scalar values by computing +// Euclidean norm of vector triplets. Scalars can be normalized +// 0<=s<=1 if desired. +// +// Note that this filter operates on point or cell attribute data, or +// both. By default, the filter operates on both point and cell data +// if vector point and cell data, respectively, are available from the +// input. Alternatively, you can choose to generate scalar norm values +// for just cell or point data. + +#ifndef __vtkVectorNorm_h +#define __vtkVectorNorm_h + +#define VTK_ATTRIBUTE_MODE_DEFAULT 0 +#define VTK_ATTRIBUTE_MODE_USE_POINT_DATA 1 +#define VTK_ATTRIBUTE_MODE_USE_CELL_DATA 2 + +#include "vtkDataSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkVectorNorm : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkVectorNorm,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with normalize flag off. + static vtkVectorNorm *New(); + + // Description: + // Specify whether to normalize scalar values. + vtkSetMacro(Normalize,int); + vtkGetMacro(Normalize,int); + vtkBooleanMacro(Normalize,int); + + // Description: + // Control how the filter works to generate scalar data from the + // input vector data. By default, (AttributeModeToDefault) the + // filter will generate the scalar norm for point and cell data (if + // vector data present in the input). Alternatively, you can + // explicitly set the filter to generate point data + // (AttributeModeToUsePointData) or cell data + // (AttributeModeToUseCellData). + vtkSetMacro(AttributeMode,int); + vtkGetMacro(AttributeMode,int); + void SetAttributeModeToDefault() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_DEFAULT);}; + void SetAttributeModeToUsePointData() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_POINT_DATA);}; + void SetAttributeModeToUseCellData() + {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_CELL_DATA);}; + const char *GetAttributeModeAsString(); + +protected: + vtkVectorNorm(); + ~vtkVectorNorm() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int Normalize; // normalize 0<=n<=1 if true. + int AttributeMode; //control whether to use point or cell data, or both +private: + vtkVectorNorm(const vtkVectorNorm&); // Not implemented. + void operator=(const vtkVectorNorm&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkVisibilitySort.cxx b/Graphics/vtkVisibilitySort.cxx new file mode 100644 index 0000000..5011a6c --- /dev/null +++ b/Graphics/vtkVisibilitySort.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVisibilitySort.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ +#include "vtkVisibilitySort.h" + +#include "vtkIdList.h" +#include "vtkDataSet.h" +#include "vtkMatrix4x4.h" +#include "vtkCamera.h" +#include "vtkGarbageCollector.h" + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkVisibilitySort, "$Revision: 1.1 $"); +vtkCxxSetObjectMacro(vtkVisibilitySort, Camera, vtkCamera); +vtkCxxSetObjectMacro(vtkVisibilitySort, Input, vtkDataSet); + +//----------------------------------------------------------------------------- + +vtkVisibilitySort::vtkVisibilitySort() +{ + this->ModelTransform = vtkMatrix4x4::New(); + this->ModelTransform->Identity(); + this->InverseModelTransform = vtkMatrix4x4::New(); + this->InverseModelTransform->Identity(); + + this->Camera = NULL; + this->Input = NULL; + + this->Direction = vtkVisibilitySort::BACK_TO_FRONT; + + this->MaxCellsReturned = VTK_LARGE_INTEGER; +} + +//----------------------------------------------------------------------------- + +vtkVisibilitySort::~vtkVisibilitySort() +{ + this->ModelTransform->Delete(); + this->InverseModelTransform->Delete(); + + this->SetCamera(NULL); + this->SetInput(NULL); +} + +//----------------------------------------------------------------------------- + +void vtkVisibilitySort::Register(vtkObjectBase *o) +{ + this->RegisterInternal(o, 1); +} + +void vtkVisibilitySort::UnRegister(vtkObjectBase *o) +{ + this->UnRegisterInternal(o, 1); +} + +void vtkVisibilitySort::ReportReferences(vtkGarbageCollector *collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->Input, "Input"); +} + +//----------------------------------------------------------------------------- + +void vtkVisibilitySort::SetModelTransform(vtkMatrix4x4 *mat) +{ + // Less efficent than vtkMatrix4x4::DeepCopy, but only sets Modified if + // there is a real change. + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + this->ModelTransform->SetElement(i, j, mat->GetElement(i, j)); + } + } + + if ( this->ModelTransform->GetMTime() + > this->InverseModelTransform->GetMTime() ) + { + this->InverseModelTransform->DeepCopy(this->ModelTransform); + this->InverseModelTransform->Invert(); + } +} + +//----------------------------------------------------------------------------- + +void vtkVisibilitySort::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Input: (" << this->Input << ")" << endl; + os << indent << "Direction: "; + switch (this->Direction) + { + case vtkVisibilitySort::BACK_TO_FRONT: + os << "back to front" << endl; + break; + case vtkVisibilitySort::FRONT_TO_BACK: + os << "front to back" << endl; + break; + default: + os << "unknown" << endl; + break; + } + + os << indent << "MaxCellsReturned: " << this->MaxCellsReturned << endl; + + os << indent << "ModelTransform:" << endl; + this->ModelTransform->PrintSelf(os, indent.GetNextIndent()); + os << indent << "InverseModelTransform:" << endl; + this->InverseModelTransform->PrintSelf(os, indent.GetNextIndent()); + + os << indent << "Camera: (" << this->Camera << ")" << endl; +} diff --git a/Graphics/vtkVisibilitySort.h b/Graphics/vtkVisibilitySort.h new file mode 100644 index 0000000..cddc5f3 --- /dev/null +++ b/Graphics/vtkVisibilitySort.h @@ -0,0 +1,137 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVisibilitySort.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkVisibilitySort - Abstract class that can sort cell data along a viewpoint. +// +// .SECTION Description +// vtkVisibilitySort encapsulates a method for depth sorting the cells of a +// vtkDataSet for a given viewpoint. It should be noted that subclasses +// are not required to give an absolutely correct sorting. Many types of +// unstructured grids may have sorting cycles, meaning that there is no +// possible correct sorting. Some subclasses also only give an approximate +// sorting in the interest of speed. +// +// .SECTION Note +// The Input field of this class tends to causes reference cycles. To help +// break these cycles, garbage collection is enabled on this object and the +// input parameter is traced. For this to work, though, an object in the +// loop holding the visibility sort should also report that to the garbage +// collector. +// + +#ifndef __vtkVisibilitySort_h +#define __vtkVisibilitySort_h + +#include "vtkObject.h" + +class vtkIdTypeArray; +class vtkDataSet; +class vtkMatrix4x4; +class vtkCamera; + +class VTK_GRAPHICS_EXPORT vtkVisibilitySort : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkVisibilitySort, vtkObject); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + // Description: + // To facilitate incremental sorting algorithms, the cells are retrieved + // in an iteration process. That is, call InitTraversal to start the + // iteration and call GetNextCells to get the cell IDs in order. + // However, for efficiencies sake, GetNextCells returns an ordered list + // of several id's in once call (but not necessarily all). GetNextCells + // will return NULL once the entire sorted list is output. The + // vtkIdTypeArray returned from GetNextCells is a cached array, so do not + // delete it. At the same note, do not expect the array to be valid + // after subsequent calls to GetNextCells. + virtual void InitTraversal() = 0; + virtual vtkIdTypeArray *GetNextCells() = 0; + + // Description: + // Set/Get the maximum number of cells that GetNextCells will return + // in one invocation. + vtkSetClampMacro(MaxCellsReturned, int, 1, VTK_LARGE_INTEGER); + vtkGetMacro(MaxCellsReturned, int); + + // Description: + // Set/Get the matrix that transforms from object space to world space. + // Generally, you get this matrix from a call to GetMatrix of a vtkProp3D + // (vtkActor). + virtual void SetModelTransform(vtkMatrix4x4 *mat); + vtkGetObjectMacro(ModelTransform, vtkMatrix4x4); + + vtkGetObjectMacro(InverseModelTransform, vtkMatrix4x4); + + // Description: + // Set/Get the camera that specifies the viewing parameters. + virtual void SetCamera(vtkCamera *camera); + vtkGetObjectMacro(Camera, vtkCamera); + + // Description: + // Set/Get the data set containing the cells to sort. + virtual void SetInput(vtkDataSet *data); + vtkGetObjectMacro(Input, vtkDataSet); + + // Description: + // Set/Get the sorting direction. Be default, the direction is set + // to back to front. + vtkGetMacro(Direction, int); + vtkSetMacro(Direction, int); + void SetDirectionToBackToFront() { this->SetDirection(BACK_TO_FRONT); } + void SetDirectionToFrontToBack() { this->SetDirection(FRONT_TO_BACK); } + +//BTX + enum { BACK_TO_FRONT, FRONT_TO_BACK }; +//ETX + + // Description: + // Overwritten to enable garbage collection. + virtual void Register(vtkObjectBase *o); + virtual void UnRegister(vtkObjectBase *o); + +protected: + vtkVisibilitySort(); + virtual ~vtkVisibilitySort(); + + vtkTimeStamp LastSortTime; + + vtkMatrix4x4 *ModelTransform; + vtkMatrix4x4 *InverseModelTransform; + vtkCamera *Camera; + vtkDataSet *Input; + + int MaxCellsReturned; + + int Direction; + + virtual void ReportReferences(vtkGarbageCollector *collector); + +private: + vtkVisibilitySort(const vtkVisibilitySort &); // Not implemented. + void operator=(const vtkVisibilitySort &); // Not implemented. +}; + +#endif //__vtkVisibilitySort_h + diff --git a/Graphics/vtkVoxelContoursToSurfaceFilter.cxx b/Graphics/vtkVoxelContoursToSurfaceFilter.cxx new file mode 100644 index 0000000..74f4302 --- /dev/null +++ b/Graphics/vtkVoxelContoursToSurfaceFilter.cxx @@ -0,0 +1,695 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoxelContoursToSurfaceFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVoxelContoursToSurfaceFilter.h" + +#include "vtkAppendPolyData.h" +#include "vtkCellArray.h" +#include "vtkContourFilter.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStructuredPoints.h" + +vtkCxxRevisionMacro(vtkVoxelContoursToSurfaceFilter, "$Revision: 1.27 $"); +vtkStandardNewMacro(vtkVoxelContoursToSurfaceFilter); + +vtkVoxelContoursToSurfaceFilter::vtkVoxelContoursToSurfaceFilter() +{ + this->MemoryLimitInBytes = 10000000; + this->Spacing[0] = 1.0; + this->Spacing[1] = 1.0; + this->Spacing[2] = 1.0; + this->LineList = new double[4*1000]; + this->LineListLength = 0; + this->LineListSize = 1000; + this->SortedXList = NULL; + this->SortedYList = NULL; + this->WorkingList = NULL; + this->IntersectionList = NULL; + this->SortedListSize = 0; +} + +vtkVoxelContoursToSurfaceFilter::~vtkVoxelContoursToSurfaceFilter() +{ + if ( this->LineList ) + { + delete [] this->LineList; + } + if ( this->SortedXList ) + { + delete [] this->SortedXList; + } + if ( this->SortedYList ) + { + delete [] this->SortedYList; + } + if ( this->WorkingList ) + { + delete [] this->WorkingList; + } + if ( this->IntersectionList ) + { + delete [] this->IntersectionList; + } +} + +void vtkVoxelContoursToSurfaceFilter::AddLineToLineList( double x1, double y1, + double x2, double y2 ) +{ + // Do we need to increase the size of our list? + if ( this->LineListLength >= this->LineListSize ) + { + // Double the space we had before + double *newList = new double[this->LineListSize*4*2]; + memcpy( newList, this->LineList, 4*this->LineListSize*sizeof(double) ); + delete [] this->LineList; + this->LineList = newList; + this->LineListSize *= 2; + } + + // Now we are sure we have space - add the line + this->LineList[4*this->LineListLength + 0] = x1; + this->LineList[4*this->LineListLength + 1] = y1; + this->LineList[4*this->LineListLength + 2] = x2; + this->LineList[4*this->LineListLength + 3] = y2; + this->LineListLength++; +} + +void vtkVoxelContoursToSurfaceFilter::SortLineList() +{ + int i, j; + double tmp[4]; + double tmpval; + + + // Make sure we have enough space in our sorted list + if ( this->SortedListSize < this->LineListLength ) + { + if ( this->SortedXList ) + { + delete [] this->SortedXList; + } + if ( this->SortedYList ) + { + delete [] this->SortedYList; + } + if ( this->WorkingList ) + { + delete [] this->WorkingList; + } + if ( this->IntersectionList ) + { + delete [] this->IntersectionList; + } + + this->SortedXList = new double[4*this->LineListLength]; + this->SortedYList = new double[4*this->LineListLength]; + this->SortedListSize = this->LineListLength; + + // Create the space we'll need for our working list of indices + // The is the list of lines that we are currently considering + // for intersections. Lines move in then out of the list as + // we pass the first then the second endpoint. This will be + // used during the CastXLines and CastYLines methods, and is + // the same size as the number of lines. + this->WorkingList = new int[this->LineListLength]; + + // Create the space we'll need for the intersection list + // There can't be more intersections than there are possible + // lines. Although it is highly doubtful we'll actually use + // all this space, it isn't much and it makes the code simpler + // not to have to worry about exceeding the bounds. This will be + // used during the CastXLines and CastYLines methods, and is + // the same size as the number of lines. + this->IntersectionList = new double[this->LineListLength]; + } + + // Copy the lines into the lists + memcpy( this->SortedXList, this->LineList, + 4*this->LineListLength*sizeof(double) ); + memcpy( this->SortedYList, this->LineList, + 4*this->LineListLength*sizeof(double) ); + + // Now sort on x and y + // Use a simple bubble sort - will improve if necessary + for ( i = 0; i < this->LineListLength; i++ ) + { + // swap x entry if necessary to keep min x the first endpoint + if ( this->SortedXList[4*i + 0] > this->SortedXList[4*i + 2] ) + { + tmpval = this->SortedXList[4*i]; + this->SortedXList[4*i] = this->SortedXList[4*i + 2]; + this->SortedXList[4*i + 2] = tmpval; + tmpval = this->SortedXList[4*i + 1]; + this->SortedXList[4*i + 1] = this->SortedXList[4*i + 3]; + this->SortedXList[4*i + 3] = tmpval; + } + + // swap y entry if necessary to keep min y the first endpoint + if ( this->SortedYList[4*i + 1] > this->SortedYList[4*i + 3] ) + { + tmpval = this->SortedYList[4*i]; + this->SortedYList[4*i] = this->SortedYList[4*i + 2]; + this->SortedYList[4*i + 2] = tmpval; + tmpval = this->SortedYList[4*i + 1]; + this->SortedYList[4*i + 1] = this->SortedYList[4*i + 3]; + this->SortedYList[4*i + 3] = tmpval; + } + + // Sort x list + for ( j = i; j > 0; j-- ) + { + if ( this->SortedXList[j*4] < this->SortedXList[(j-1)*4] ) + { + memcpy( tmp, this->SortedXList + j*4, 4*sizeof(double) ); + memcpy( this->SortedXList + j*4, + this->SortedXList + (j-1)*4, 4*sizeof(double) ); + memcpy( this->SortedXList + (j-1)*4, tmp, 4*sizeof(double) ); + } + else + { + break; + } + } + + // Sort y list + for ( j = i; j > 0; j-- ) + { + if ( this->SortedYList[j*4+1] < this->SortedYList[(j-1)*4+1] ) + { + memcpy( tmp, this->SortedYList + j*4, 4*sizeof(double) ); + memcpy( this->SortedYList + j*4, this->SortedYList + (j-1)*4, + 4*sizeof(double) ); + memcpy( this->SortedYList + (j-1)*4, tmp, 4*sizeof(double) ); + } + else + { + break; + } + } + } +} + + +void vtkVoxelContoursToSurfaceFilter::CastLines( float *slicePtr, + double gridOrigin[3], + int gridSize[3], + int type ) +{ + double axis1, axis2; + double d1, d2; + int index; + int i, j; + double tmp; + double *line; + float *currSlicePtr; + int currSlice; + int currentIntersection; + double sign; + double *sortedList; + double low1, low2, high1, high2; + int increment1, increment2; + int offset1, offset2, offset3, offset4; + + // this is the x direction + if ( type == 0 ) + { + low1 = gridOrigin[0]; + high1 = gridOrigin[0] + (double)gridSize[0]; + low2 = gridOrigin[1]; + high2 = gridOrigin[1] + (double)gridSize[1]; + increment1 = gridSize[0]; + increment2 = 1; + sortedList = this->SortedXList; + offset1 = 0; + offset2 = 2; + offset3 = 1; + offset4 = 3; + } + // This is the y direction + else + { + low1 = gridOrigin[1]; + high1 = gridOrigin[1] + (double)gridSize[1]; + low2 = gridOrigin[0]; + high2 = gridOrigin[0] + (double)gridSize[0]; + increment1 = 1; + increment2 = gridSize[0]; + sortedList = this->SortedYList; + offset1 = 1; + offset2 = 3; + offset3 = 0; + offset4 = 2; + } + + // Initialize the working list to nothing. We will start + // looking at index = 0 for the next line to add to the + // working list + this->WorkingListLength = 0; + index = 0; + + // Loop through the x or y lines + for ( axis1 = low1, currSlice = 0; axis1 < high1; axis1 += 1.0, currSlice++ ) + { + // Initialize the intersection list to nothing + this->IntersectionListLength = 0; + + // Add lines to the working list if necessary + for ( ; index < this->LineListLength; index++ ) + { + if ( sortedList[4*index + offset1] < axis1 ) + { + this->WorkingList[this->WorkingListLength] = index; + this->WorkingListLength++; + } + else + { + break; + } + } + + // Do the intersections, removing lines from the + // working list if necessary + for ( i = 0; i < this->WorkingListLength; i++ ) + { + line = sortedList + 4*this->WorkingList[i]; + + // Yes, it intersects, add it to the intersection list + if ( line[offset1] < axis1 && line[offset2] > axis1 ) + { + // Compute the intersection distance + // For x lines this is y = y1 + (y2 - y1)*((x - x1)/(x2 - x1)) + // For y lines this is x = x1 + (x2 - x1)*((y - y1)/(y2 - y1)) + this->IntersectionList[this->IntersectionListLength] = + line[offset3] + (line[offset4] - line[offset3]) * + ((axis1 - line[offset1]) / (line[offset2] - line[offset1] )); + + // Make sure this distance is sorted + for ( j = this->IntersectionListLength; j > 0; j-- ) + { + if ( this->IntersectionList[j] < this->IntersectionList[j-1] ) + { + tmp = this->IntersectionList[j]; + this->IntersectionList[j] = this->IntersectionList[j-1]; + this->IntersectionList[j-1] = tmp; + } + else + { + break; + } + } + this->IntersectionListLength++; + } + // No, it doesn't intersect, remove it from the working list + else + { + for ( j = i; j < (this->WorkingListLength-1); j++ ) + { + this->WorkingList[j] = this->WorkingList[j+1]; + } + this->WorkingListLength--; + i--; + } + } + + // Now we have all the intersections for the x or y line, in sorted + // order. Use them to fill in distances (as long as there are + // any) + if ( this->IntersectionListLength ) + { + currSlicePtr = slicePtr + currSlice*increment2; + currentIntersection = 0; + // We are starting outside which has a negative distance + sign = -1.0; + for ( axis2 = low2; axis2 < high2; axis2 += 1.0 ) + { + while( currentIntersection < this->IntersectionListLength && + this->IntersectionList[currentIntersection] < axis2 ) + + { + currentIntersection++; + + // Each time we cross a line we are moving across an + // inside/outside boundary + sign *= -1.0; + } + // We are now positioned at an x or y value between currentIntersection + // and currentIntersection - 1 (except at boundaries where we are + // before intersection 0 or after the last intersection) + + if ( currentIntersection == 0 ) + { + d1 = axis2 - this->IntersectionList[currentIntersection]; + *currSlicePtr = (*currSlicePtr > d1 )?(*currSlicePtr):(d1); + } + else if ( currentIntersection == this->IntersectionListLength ) + { + d1 = this->IntersectionList[currentIntersection-1] - axis2; + *currSlicePtr = (*currSlicePtr > d1 )?(*currSlicePtr):(d1); + } + else + { + d1 = axis2 - this->IntersectionList[currentIntersection-1]; + d2 = this->IntersectionList[currentIntersection] - axis2; + d1 = ( d1 < d2 )?(d1):(d2); + if ( type == 0 ) + { + *currSlicePtr = sign*d1; + } + else + { + *currSlicePtr = + (sign*(*currSlicePtr) < d1 )?(*currSlicePtr):(sign*d1); + } + } + + currSlicePtr += increment1; + } + } + } +} + +void vtkVoxelContoursToSurfaceFilter::PushDistances( float *volumePtr, + int gridSize[3], + int chunkSize ) +{ + int i, j, k; + float *vptr; + + // Push distances along x (both ways) and y (both ways) on each slice + for ( k = 0; k < chunkSize; k++ ) + { + // Do the x rows + for ( j = 0; j < gridSize[1]; j++ ) + { + vptr = volumePtr + k*gridSize[0]*gridSize[1] + j*gridSize[0]; + vptr++; + + // first one way + for ( i = 1; i < gridSize[0]; i++ ) + { + if ( *vptr > 0 && *(vptr-1) + 1 < *(vptr) ) + { + *vptr = *(vptr-1) + 1; + } + else if ( *vptr < 0 && *(vptr-1) - 1 > *(vptr) ) + { + *vptr = *(vptr-1) - 1; + } + vptr++; + } + + vptr -= 2; + i -= 2; + + // then the other + for ( ; i >= 0; i-- ) + { + if ( *vptr > 0 && *(vptr+1) + 1 < *(vptr) ) + { + *vptr = *(vptr+1) + 1; + } + else if ( *vptr < 0 && *(vptr+1) - 1 > *(vptr) ) + { + *vptr = *(vptr+1) - 1; + } + } + + } + + + // Do the y columns + for ( i = 0; i < gridSize[0]; i++ ) + { + vptr = volumePtr + k*gridSize[0]*gridSize[1] + i; + + vptr+=gridSize[0]; + + // first one way + for ( j = 1; j < gridSize[1]; j++ ) + { + if ( *vptr > 0 && *(vptr-gridSize[0]) + 1 < *(vptr) ) + { + *vptr = *(vptr-gridSize[0]) + 1; + } + else if ( *vptr < 0 && *(vptr-gridSize[0]) - 1 > *(vptr) ) + { + *vptr = *(vptr-gridSize[0]) - 1; + } + vptr += gridSize[0]; + } + + vptr -= 2*gridSize[0]; + j -= 2; + + // then the other + for ( ; j >= 0; j-- ) + { + if ( *vptr > 0 && *(vptr+gridSize[0]) + 1 < *(vptr) ) + { + *vptr = *(vptr+gridSize[0]) + 1; + } + else if ( *vptr < 0 && *(vptr+gridSize[0]) - 1 > *(vptr) ) + { + *vptr = *(vptr+gridSize[0]) - 1; + } + } + + } + } +} + +// Append data sets into single unstructured grid +int vtkVoxelContoursToSurfaceFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkCellArray *inputPolys = input->GetPolys(); + int gridSize[3]; + double gridOrigin[3]; + double contourBounds[6]; + int chunkSize; + int currentSlice, lastSlice, currentIndex; + int i, j; + int numberOfInputCells; + int currentInputCellIndex; + vtkIdType npts = 0; + vtkIdType *pts = 0; + double point1[3], point2[3]; + double currentZ; + vtkStructuredPoints *volume; + float *volumePtr, *slicePtr; + vtkContourFilter *contourFilter; + vtkPolyData *contourOutput; + vtkAppendPolyData *appendFilter; + + vtkDebugMacro(<<"Creating surfaces from contours"); + + // Get the bounds of the input contours + input->GetBounds( contourBounds ); + + if (contourBounds[0] > contourBounds[1]) + { // empty input + return 1; + } + + // From the bounds, compute the grid size, and origin + + // The origin of the grid should be (-0.5, -0.5, 0.0) away from the + // lower bounds of the contours. This is because we want the grid + // to lie halfway between integer endpoint locations of the line + // segments on each plane. Also, we want an extra plane on each end + // for capping + gridOrigin[0] = contourBounds[0] - 0.5; + gridOrigin[1] = contourBounds[2] - 0.5; + gridOrigin[2] = contourBounds[4] - 1.0; + + // The difference between the bounds, plus one to account a + // sample on the first and last location, plus one to account + // for the larger grid size ( the 0.5 unit border ) On Z, we + // want to sample exactly on the contours so we don't need to + // add the extra 1, but we have added two extra planes so we + // need another 2. + gridSize[0] = (int) (contourBounds[1] - contourBounds[0] + 2); + gridSize[1] = (int) (contourBounds[3] - contourBounds[2] + 2); + gridSize[2] = (int) (contourBounds[5] - contourBounds[4] + 3); + + // How many slices in a chunk? This will later be decremented + // by one to account for the fact that the last slice in the + // previous chuck is copied to the first slice in the next chunk. + // Stay within memory limit. There are 4 bytes per double. + chunkSize = this->MemoryLimitInBytes / ( gridSize[0] * gridSize[1] * 4 ); + if ( chunkSize > gridSize[2] ) + { + chunkSize = gridSize[2]; + } + + currentSlice = 0; + currentZ = contourBounds[4] - 1.0; + currentIndex = 0; + lastSlice = gridSize[2] - 1; + numberOfInputCells = inputPolys->GetNumberOfCells(); + currentInputCellIndex = 0; + + volume = vtkStructuredPoints::New(); + volume->SetDimensions( gridSize[0], gridSize[1], chunkSize ); + volume->SetSpacing( this->Spacing ); + volume->SetScalarType( VTK_FLOAT ); + volume->AllocateScalars(); + volumePtr = + (float *)(volume->GetPointData()->GetScalars()->GetVoidPointer(0)); + + + contourFilter = vtkContourFilter::New(); + contourFilter->SetInput( volume ); + contourFilter->SetNumberOfContours(1); + contourFilter->SetValue( 0, 0.0 ); + + appendFilter = vtkAppendPolyData::New(); + + inputPolys->InitTraversal(); + inputPolys->GetNextCell( npts, pts ); + + while ( currentSlice <= lastSlice ) + { + // Make sure the origin of the volume is in the right + // place so that the appended polydata all matches up + // nicely. + volume->SetOrigin( gridOrigin[0], gridOrigin[1], + gridOrigin[2] + + this->Spacing[2] * (currentSlice - (currentSlice!=0)) ); + + for ( i = currentIndex; i < chunkSize; i++ ) + { + slicePtr = volumePtr + i * gridSize[0] * gridSize[1]; + + // Clear out the slice memory - set it all to a large negative + // value indicating no surfaces are nearby, and we assume we + // are outside of any surface + for ( j = 0; j < gridSize[0] * gridSize[1]; j++ ) + { + *(slicePtr+j) = -9.99e10; + } + + // If we are past the end, don't do anything + if ( currentSlice > lastSlice ) + { + continue; + } + + this->LineListLength = 0; + + // Read in the lines for the contours on this slice + while ( currentInputCellIndex < numberOfInputCells ) + { + // Check if we are still on the right z slice + input->GetPoint( pts[0], point1 ); + if ( point1[2] != currentZ ) + { + break; + } + + // This contour is on the right z slice - add the lines + // to our list + for ( j = 0; j < npts; j++ ) + { + input->GetPoint( pts[j], point1 ); + input->GetPoint( pts[(j+1)%npts], point2 ); + this->AddLineToLineList( point1[0], point1[1], + point2[0], point2[1] ); + } + + inputPolys->GetNextCell( npts, pts ); + currentInputCellIndex++; + } + + // Sort the contours in x and y + this->SortLineList(); + + // Cast lines in x and y filling in distance + this->CastLines( slicePtr, gridOrigin, gridSize, 0 ); + this->CastLines( slicePtr, gridOrigin, gridSize, 1 ); + + // Move on to the next slice + currentSlice++; + currentIndex++; + currentZ += 1.0; + } + + this->PushDistances( volumePtr, gridSize, chunkSize ); + + // Update the contour filter and grab the output + // Make a new output for it, then grab the output and + // add it to the append filter, then delete the output + // which is ok since it was registered by the appendFilter + contourOutput = vtkPolyData::New(); + contourFilter->Update(); + contourOutput->ShallowCopy(contourFilter->GetOutput()); + appendFilter->AddInput( contourOutput ); + contourOutput->Delete(); + + + if ( currentSlice <= lastSlice ) + { + // Copy last slice to first slice + memcpy( volumePtr, volumePtr + (chunkSize-1)*gridSize[0]*gridSize[1], + sizeof(float) * gridSize[0] * gridSize[1] ); + + // reset currentIndex to 1 + currentIndex = 1; + } + } + + appendFilter->Update(); + + // Grab the appended data as the output to this filter + output->SetPoints( appendFilter->GetOutput()->GetPoints() ); + output->SetVerts( appendFilter->GetOutput()->GetVerts() ); + output->SetLines( appendFilter->GetOutput()->GetLines() ); + output->SetPolys( appendFilter->GetOutput()->GetPolys() ); + output->SetStrips( appendFilter->GetOutput()->GetStrips() ); + output->GetPointData()->PassData(appendFilter->GetOutput()->GetPointData()); + + contourFilter->Delete(); + appendFilter->Delete(); + volume->Delete(); + + return 1; +} + + +void vtkVoxelContoursToSurfaceFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Memory Limit (in bytes): " << + this->MemoryLimitInBytes << endl; + + os << indent << "Spacing: " << this->Spacing[0] << " " << + this->Spacing[1] << " " << this->Spacing[2] << endl; +} diff --git a/Graphics/vtkVoxelContoursToSurfaceFilter.h b/Graphics/vtkVoxelContoursToSurfaceFilter.h new file mode 100644 index 0000000..43b10b0 --- /dev/null +++ b/Graphics/vtkVoxelContoursToSurfaceFilter.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoxelContoursToSurfaceFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVoxelContoursToSurfaceFilter - create surface from contours +// .SECTION Description +// vtkVoxelContoursToSurfaceFilter is a filter that takes contours and +// produces surfaces. There are some restrictions for the contours: +// +// - The contours are input as vtkPolyData, with the contours being +// polys in the vtkPolyData. +// - The contours lie on XY planes - each contour has a constant Z +// - The contours are ordered in the polys of the vtkPolyData such +// that all contours on the first (lowest) XY plane are first, then +// continuing in order of increasing Z value. +// - The X, Y and Z coordinates are all integer values. +// - The desired sampling of the contour data is 1x1x1 - Aspect can +// be used to control the aspect ratio in the output polygonal +// dataset. +// +// This filter takes the contours and produces a structured points +// dataset of signed floating point number indicating distance from +// a contour. A contouring filter is then applied to generate 3D +// surfaces from a stack of 2D contour distance slices. This is +// done in a streaming fashion so as not to use to much memory. + +// .SECTION See Also +// vtkPolyDataAlgorithm + +#ifndef __vtkVoxelContoursToSurfaceFilter_h +#define __vtkVoxelContoursToSurfaceFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkVoxelContoursToSurfaceFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkVoxelContoursToSurfaceFilter *New(); + vtkTypeRevisionMacro(vtkVoxelContoursToSurfaceFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / Get the memory limit in bytes for this filter. This is the limit + // of the size of the structured points data set that is created for + // intermediate processing. The data will be streamed through this volume + // in as many pieces as necessary. + vtkSetMacro( MemoryLimitInBytes, int ); + vtkGetMacro( MemoryLimitInBytes, int ); + + vtkSetVector3Macro( Spacing, double ); + vtkGetVectorMacro( Spacing, double, 3 ); + +protected: + vtkVoxelContoursToSurfaceFilter(); + ~vtkVoxelContoursToSurfaceFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int MemoryLimitInBytes; + + double Spacing[3]; + + double *LineList; + int LineListLength; + int LineListSize; + + double *SortedXList; + double *SortedYList; + int SortedListSize; + + int *WorkingList; + int WorkingListLength; + + double *IntersectionList; + int IntersectionListLength; + + void AddLineToLineList( double x1, double y1, double x2, double y2 ); + void SortLineList(); + + void CastLines( float *slice, double gridOrigin[3], + int gridSize[3], int type ); + + void PushDistances( float *ptr, int gridSize[3], int chunkSize ); +private: + vtkVoxelContoursToSurfaceFilter(const vtkVoxelContoursToSurfaceFilter&); // Not implemented. + void operator=(const vtkVoxelContoursToSurfaceFilter&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkWarpLens.cxx b/Graphics/vtkWarpLens.cxx new file mode 100644 index 0000000..323453e --- /dev/null +++ b/Graphics/vtkWarpLens.cxx @@ -0,0 +1,180 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpLens.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWarpLens.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkWarpLens, "$Revision: 1.29 $"); +vtkStandardNewMacro(vtkWarpLens); + +// +// Preserve old Kappa instance variable. It appears to be the +// second order symmetric radial lens distortion parameter +// +void vtkWarpLens::SetKappa(double kappa) +{ + this->SetK1(kappa); +} + +double vtkWarpLens::GetKappa() +{ + return this->GetK1(); +} + +// +// Preserve old Center point instance variable. +// It appears to be the center of radial distortion in pixel coordinates +// +void vtkWarpLens::SetCenter(double centerX, double centerY) +{ + this->SetPrincipalPoint(centerX, centerY); +} + +double *vtkWarpLens::GetCenter() +{ + return this->GetPrincipalPoint(); +} + +vtkWarpLens::vtkWarpLens() +{ + this->PrincipalPoint[0] = 0.0; + this->PrincipalPoint[1] = 0.0; + this->K1 = -1.0e-6; + this->K2 = 0.0; + this->P1 = 0.0; + this->P2 = 0.0; + this->FormatWidth = 1.0; + this->FormatHeight = 1.0; + this->ImageWidth = 1; + this->ImageHeight = 1; +} + +int vtkWarpLens::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts; + vtkPoints *newPts; + vtkIdType ptId, numPts; + double pixel[3], newPixel[3]; + double x; + double y; + double newX; + double newY; + double rSquared; + + vtkDebugMacro(<<"Warping data to a point"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + inPts = input->GetPoints(); + if (!inPts ) + { + vtkErrorMacro(<<"No input data"); + return 1; + } + + numPts = inPts->GetNumberOfPoints(); + newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + + // + // Loop over all pixels, adjusting locations + // + for (ptId=0; ptId < numPts; ptId++) + { + inPts->GetPoint(ptId, pixel); + + // + // Convert to working in mm from pixels and make the Principal Point (0,0) + // + x = pixel[0] / this->ImageWidth * this->FormatWidth - + this->PrincipalPoint[0]; + y = (- pixel[1]) / this->ImageHeight * this->FormatHeight + + this->PrincipalPoint[1]; + + // + // Lens distortion causes a point's image on the imaging surface to + // shifted from its true position as if it had been imaged by an ideal pin- + // hole camera. + // + // The corrected location adds the correction for radial len distortion + // and for the decentering lens distortion + // + rSquared = x*x + y*y; + + newX = x * (1 + this->K1 * rSquared + this->K2 * rSquared*rSquared ) + + this->P1 * (rSquared + 2 * x*x) + 2 * this->P2 * x * y; + + newY = y * (1 + this->K1 * rSquared + this->K2 * rSquared*rSquared ) + + this->P2 * (rSquared + 2 * y*y) + 2 * this->P1 * x * y; + + // + // Convert back to pixels + // + newPixel[0] = (newX + this->PrincipalPoint[0]) / this->FormatWidth * + this->ImageWidth; + newPixel[1] = (newY - this->PrincipalPoint[1]) / + this->FormatHeight * this->ImageHeight * -1; + + newPixel[2] = pixel[2]; // pixel color + newPts->SetPoint(ptId, newPixel); + } + + // + // Update ourselves and release memory + // + output->GetPointData()->CopyNormalsOff(); // distorted geometry + output->GetPointData()->PassData(input->GetPointData()); + + output->SetPoints(newPts); + newPts->Delete(); + + return 1; +} + +void vtkWarpLens::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PrincipalPoint: (" << this->PrincipalPoint[0] << ", " + << this->PrincipalPoint[1] << ") in mm\n"; + os << indent << "K1: " << this->K1 << "\n"; + os << indent << "K2: " << this->K2 << "\n"; + os << indent << "P1: " << this->P1 << "\n"; + os << indent << "P2: " << this->P2 << "\n"; + os << indent << "FormatWidth: " << this->FormatWidth << " in mm\n"; + os << indent << "FormatHeight: " << this->FormatHeight << " in mm\n"; + os << indent << "ImageWidth: " << this->ImageWidth << " in pixels\n"; + os << indent << "ImageHeight: " << this->ImageHeight << " in pixels\n"; +} diff --git a/Graphics/vtkWarpLens.h b/Graphics/vtkWarpLens.h new file mode 100644 index 0000000..0af89b5 --- /dev/null +++ b/Graphics/vtkWarpLens.h @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpLens.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWarpLens - deform geometry by applying lens distortion +// .SECTION Description +// vtkWarpLens is a filter that modifies point coordinates by moving +// in accord with a lens distortion model. + +#ifndef __vtkWarpLens_h +#define __vtkWarpLens_h + +#include "vtkPointSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkWarpLens : public vtkPointSetAlgorithm +{ +public: + static vtkWarpLens *New(); + vtkTypeRevisionMacro(vtkWarpLens,vtkPointSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify second order symmetric radial lens distortion parameter. + // This is obsoleted by newer instance variables. + void SetKappa(double kappa); + double GetKappa(); + + // Description: + // Specify the center of radial distortion in pixels. + // This is obsoleted by newer instance variables. + void SetCenter(double centerX, double centerY); + double *GetCenter(); + + // Description: + // Specify the calibrated principal point of the camera/lens + vtkSetVector2Macro(PrincipalPoint,double); + vtkGetVectorMacro(PrincipalPoint,double,2); + + // Description: + // Specify the symmetric radial distortion parameters for the lens + vtkSetMacro(K1,double); + vtkGetMacro(K1,double); + vtkSetMacro(K2,double); + vtkGetMacro(K2,double); + + // Description: + // Specify the decentering distortion parameters for the lens + vtkSetMacro(P1,double); + vtkGetMacro(P1,double); + vtkSetMacro(P2,double); + vtkGetMacro(P2,double); + + // Description: + // Specify the imager format width / height in mm + vtkSetMacro(FormatWidth,double); + vtkGetMacro(FormatWidth,double); + vtkSetMacro(FormatHeight,double); + vtkGetMacro(FormatHeight,double); + + // Description: + // Specify the image width / height in pixels + vtkSetMacro(ImageWidth,int); + vtkGetMacro(ImageWidth,int); + vtkSetMacro(ImageHeight,int); + vtkGetMacro(ImageHeight,int); + +protected: + vtkWarpLens(); + ~vtkWarpLens() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double PrincipalPoint[2]; // The calibrated principal point of camera/lens in mm + double K1; // Symmetric radial distortion parameters + double K2; + double P1; // Decentering distortion parameters + double P2; + double FormatWidth; // imager format width in mm + double FormatHeight; // imager format height in mm + int ImageWidth; // image width in pixels + int ImageHeight; // image height in pixels +private: + vtkWarpLens(const vtkWarpLens&); // Not implemented. + void operator=(const vtkWarpLens&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkWarpScalar.cxx b/Graphics/vtkWarpScalar.cxx new file mode 100644 index 0000000..b9bad50 --- /dev/null +++ b/Graphics/vtkWarpScalar.cxx @@ -0,0 +1,179 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpScalar.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWarpScalar.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDataSetAttributes.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkWarpScalar, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkWarpScalar); + +vtkWarpScalar::vtkWarpScalar() +{ + this->ScaleFactor = 1.0; + this->UseNormal = 0; + this->Normal[0] = 0.0; + this->Normal[1] = 0.0; + this->Normal[2] = 1.0; + this->XYPlane = 0; + + // by default process active point scalars + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::SCALARS); +} + +vtkWarpScalar::~vtkWarpScalar() +{ +} + +double *vtkWarpScalar::DataNormal(vtkIdType id, vtkDataArray *normals) +{ + return normals->GetTuple(id); +} + +double *vtkWarpScalar::InstanceNormal(vtkIdType vtkNotUsed(id), + vtkDataArray *vtkNotUsed(normals)) +{ + return this->Normal; +} + +double *vtkWarpScalar::ZNormal(vtkIdType vtkNotUsed(id), + vtkDataArray *vtkNotUsed(normals)) +{ + static double zNormal[3]={0.0,0.0,1.0}; + return zNormal; +} + +int vtkWarpScalar::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts; + vtkDataArray *inNormals; + vtkDataArray *inScalars; + vtkPoints *newPts; + vtkPointData *pd; + int i; + vtkIdType ptId, numPts; + double x[3], *n, s, newX[3]; + + vtkDebugMacro(<<"Warping data with scalars"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + inPts = input->GetPoints(); + pd = input->GetPointData(); + inNormals = pd->GetNormals(); + + inScalars = this->GetInputArrayToProcess(0,inputVector); + if ( !inPts || !inScalars ) + { + vtkDebugMacro(<<"No data to warp"); + return 1; + } + + numPts = inPts->GetNumberOfPoints(); + + if ( inNormals && !this->UseNormal ) + { + this->PointNormal = &vtkWarpScalar::DataNormal; + vtkDebugMacro(<<"Using data normals"); + } + else if ( this->XYPlane ) + { + this->PointNormal = &vtkWarpScalar::ZNormal; + vtkDebugMacro(<<"Using x-y plane normal"); + } + else + { + this->PointNormal = &vtkWarpScalar::InstanceNormal; + vtkDebugMacro(<<"Using Normal instance variable"); + } + + newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + + // Loop over all points, adjusting locations + // + for (ptId=0; ptId < numPts; ptId++) + { + if ( ! (ptId % 10000) ) + { + this->UpdateProgress ((double)ptId/numPts); + if (this->GetAbortExecute()) + { + break; + } + } + + inPts->GetPoint(ptId, x); + n = (this->*(this->PointNormal))(ptId,inNormals); + if ( this->XYPlane ) + { + s = x[2]; + } + else + { + s = inScalars->GetComponent(ptId,0); + } + for (i=0; i<3; i++) + { + newX[i] = x[i] + this->ScaleFactor * s * n[i]; + } + newPts->SetPoint(ptId, newX); + } + + // Update ourselves and release memory + // + output->GetPointData()->CopyNormalsOff(); // distorted geometry + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->CopyNormalsOff(); // distorted geometry + output->GetCellData()->PassData(input->GetCellData()); + + output->SetPoints(newPts); + newPts->Delete(); + + return 1; +} + +void vtkWarpScalar::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; + os << indent << "Use Normal: " << (this->UseNormal ? "On\n" : "Off\n"); + os << indent << "Normal: (" << this->Normal[0] << ", " + << this->Normal[1] << ", " << this->Normal[2] << ")\n"; + os << indent << "XY Plane: " << (this->XYPlane ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkWarpScalar.h b/Graphics/vtkWarpScalar.h new file mode 100644 index 0000000..1adbf2a --- /dev/null +++ b/Graphics/vtkWarpScalar.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpScalar.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWarpScalar - deform geometry with scalar data +// .SECTION Description +// vtkWarpScalar is a filter that modifies point coordinates by moving +// points along point normals by the scalar amount times the scale factor. +// Useful for creating carpet or x-y-z plots. +// +// If normals are not present in data, the Normal instance variable will +// be used as the direction along which to warp the geometry. If normals are +// present but you would like to use the Normal instance variable, set the +// UseNormal boolean to true. +// +// If XYPlane boolean is set true, then the z-value is considered to be +// a scalar value (still scaled by scale factor), and the displacement is +// along the z-axis. If scalars are also present, these are copied through +// and can be used to color the surface. +// +// Note that the filter passes both its point data and cell data to +// its output, except for normals, since these are distorted by the +// warping. + + +#ifndef __vtkWarpScalar_h +#define __vtkWarpScalar_h + +#include "vtkPointSetAlgorithm.h" + +class vtkDataArray; + +class VTK_GRAPHICS_EXPORT vtkWarpScalar : public vtkPointSetAlgorithm +{ +public: + static vtkWarpScalar *New(); + vtkTypeRevisionMacro(vtkWarpScalar,vtkPointSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify value to scale displacement. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Turn on/off use of user specified normal. If on, data normals + // will be ignored and instance variable Normal will be used instead. + vtkSetMacro(UseNormal,int); + vtkGetMacro(UseNormal,int); + vtkBooleanMacro(UseNormal,int); + + // Description: + // Normal (i.e., direction) along which to warp geometry. Only used + // if UseNormal boolean set to true or no normals available in data. + vtkSetVector3Macro(Normal,double); + vtkGetVectorMacro(Normal,double,3); + + // Description: + // Turn on/off flag specifying that input data is x-y plane. If x-y plane, + // then the z value is used to warp the surface in the z-axis direction + // (times the scale factor) and scalars are used to color the surface. + vtkSetMacro(XYPlane,int); + vtkGetMacro(XYPlane,int); + vtkBooleanMacro(XYPlane,int); + +protected: + vtkWarpScalar(); + ~vtkWarpScalar(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double ScaleFactor; + int UseNormal; + double Normal[3]; + int XYPlane; + + //BTX + double *(vtkWarpScalar::*PointNormal)(vtkIdType id, vtkDataArray *normals); + double *DataNormal(vtkIdType id, vtkDataArray *normals=NULL); + double *InstanceNormal(vtkIdType id, vtkDataArray *normals=NULL); + double *ZNormal(vtkIdType id, vtkDataArray *normals=NULL); + //ETX + +private: + vtkWarpScalar(const vtkWarpScalar&); // Not implemented. + void operator=(const vtkWarpScalar&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkWarpTo.cxx b/Graphics/vtkWarpTo.cxx new file mode 100644 index 0000000..c88faa1 --- /dev/null +++ b/Graphics/vtkWarpTo.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpTo.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWarpTo.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkWarpTo, "$Revision: 1.42 $"); +vtkStandardNewMacro(vtkWarpTo); + +vtkWarpTo::vtkWarpTo() +{ + this->ScaleFactor = 0.5; + this->Absolute = 0; + this->Position[0] = this->Position[1] = this->Position[2] = 0.0; +} + +int vtkWarpTo::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts; + vtkPoints *newPts; + vtkIdType ptId, numPts; + int i; + double x[3], newX[3]; + double mag; + double minMag = 0; + + vtkDebugMacro(<<"Warping data to a point"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + inPts = input->GetPoints(); + + if (!inPts ) + { + vtkErrorMacro(<<"No input data"); + return 1; + } + + numPts = inPts->GetNumberOfPoints(); + newPts = vtkPoints::New(); newPts->SetNumberOfPoints(numPts); + + if (this->Absolute) + { + minMag = 1.0e10; + for (ptId=0; ptId < numPts; ptId++) + { + inPts->GetPoint(ptId, x); + mag = sqrt(vtkMath::Distance2BetweenPoints(this->Position,x)); + if (mag < minMag) + { + minMag = mag; + } + } + } + + // + // Loop over all points, adjusting locations + // + for (ptId=0; ptId < numPts; ptId++) + { + inPts->GetPoint(ptId, x); + if (this->Absolute) + { + mag = sqrt(vtkMath::Distance2BetweenPoints(this->Position,x)); + for (i=0; i<3; i++) + { + newX[i] = this->ScaleFactor* + (this->Position[i] + minMag*(x[i] - this->Position[i])/mag) + + (1.0 - this->ScaleFactor)*x[i]; + } + } + else + { + for (i=0; i<3; i++) + { + newX[i] = (1.0 - this->ScaleFactor)*x[i] + + this->ScaleFactor*this->Position[i]; + } + } + newPts->SetPoint(ptId, newX); + } + // + // Update ourselves and release memory + // + output->GetPointData()->CopyNormalsOff(); // distorted geometry + output->GetPointData()->PassData(input->GetPointData()); + + output->SetPoints(newPts); + newPts->Delete(); + + return 1; +} + +void vtkWarpTo::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Absolute: " << (this->Absolute ? "On\n" : "Off\n"); + + os << indent << "Position: (" << this->Position[0] << ", " + << this->Position[1] << ", " << this->Position[2] << ")\n"; + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; +} diff --git a/Graphics/vtkWarpTo.h b/Graphics/vtkWarpTo.h new file mode 100644 index 0000000..f771c03 --- /dev/null +++ b/Graphics/vtkWarpTo.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpTo.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWarpTo - deform geometry by warping towards a point +// .SECTION Description +// vtkWarpTo is a filter that modifies point coordinates by moving the +// points towards a user specified position. + +#ifndef __vtkWarpTo_h +#define __vtkWarpTo_h + +#include "vtkPointSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkWarpTo : public vtkPointSetAlgorithm +{ +public: + static vtkWarpTo *New(); + vtkTypeRevisionMacro(vtkWarpTo,vtkPointSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the value to scale displacement. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Set/Get the position to warp towards. + vtkGetVectorMacro(Position,double,3); + vtkSetVector3Macro(Position,double); + + // Description: + // Set/Get the Absolute ivar. Turning Absolute on causes scale factor + // of the new position to be one unit away from Position. + vtkSetMacro(Absolute,int); + vtkGetMacro(Absolute,int); + vtkBooleanMacro(Absolute,int); + +protected: + vtkWarpTo(); + ~vtkWarpTo() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double ScaleFactor; + double Position[3]; + int Absolute; +private: + vtkWarpTo(const vtkWarpTo&); // Not implemented. + void operator=(const vtkWarpTo&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkWarpVector.cxx b/Graphics/vtkWarpVector.cxx new file mode 100644 index 0000000..c8ce67f --- /dev/null +++ b/Graphics/vtkWarpVector.cxx @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpVector.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWarpVector.h" + +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkWarpVector, "$Revision: 1.47 $"); +vtkStandardNewMacro(vtkWarpVector); + +vtkWarpVector::vtkWarpVector() +{ + this->ScaleFactor = 1.0; + + // by default process active point vectors + this->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS, + vtkDataSetAttributes::VECTORS); +} + +vtkWarpVector::~vtkWarpVector() +{ +} + +template +void vtkWarpVectorExecute2(vtkWarpVector *self, T1 *inPts, + T1 *outPts, T2 *inVec, vtkIdType max) +{ + vtkIdType ptId; + T1 scaleFactor = (T1)self->GetScaleFactor(); + + // Loop over all points, adjusting locations + for (ptId=0; ptId < max; ptId++) + { + if (!(ptId & 0xfff)) + { + self->UpdateProgress ((double)ptId/(max+1)); + if (self->GetAbortExecute()) + { + break; + } + } + + *outPts = *inPts + scaleFactor * (T1)(*inVec); + outPts++; inPts++; inVec++; + *outPts = *inPts + scaleFactor * (T1)(*inVec); + outPts++; inPts++; inVec++; + *outPts = *inPts + scaleFactor * (T1)(*inVec); + outPts++; inPts++; inVec++; + } +} + +template +void vtkWarpVectorExecute(vtkWarpVector *self, + T *inPts, + T *outPts, + vtkIdType max, + vtkDataArray *vectors) +{ + void *inVec; + inVec = vectors->GetVoidPointer(0); + + // call templated function + switch (vectors->GetDataType()) + { + vtkTemplateMacro( + vtkWarpVectorExecute2(self, inPts, outPts, + (VTK_TT *)(inVec), max)); + default: + break; + } +} + +//---------------------------------------------------------------------------- +int vtkWarpVector::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *points; + vtkIdType numPts; + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + if (input == NULL || input->GetPoints() == NULL) + { + return 1; + } + numPts = input->GetPoints()->GetNumberOfPoints(); + + vtkDataArray *vectors = this->GetInputArrayToProcess(0,inputVector); + + if ( !vectors || !numPts) + { + vtkDebugMacro(<<"No input data"); + return 1; + } + + // SETUP AND ALLOCATE THE OUTPUT + numPts = input->GetNumberOfPoints(); + points = input->GetPoints()->NewInstance(); + points->SetDataType(input->GetPoints()->GetDataType()); + points->Allocate(numPts); + points->SetNumberOfPoints(numPts); + output->SetPoints(points); + points->Delete(); + + void *inPtr = input->GetPoints()->GetVoidPointer(0); + void *outPtr = output->GetPoints()->GetVoidPointer(0); + + // call templated function + switch (input->GetPoints()->GetDataType()) + { + vtkTemplateMacro( + vtkWarpVectorExecute( this, (VTK_TT *)(inPtr), + (VTK_TT *)(outPtr), numPts, vectors) ); + default: + break; + } + + // now pass the data. + output->GetPointData()->CopyNormalsOff(); // distorted geometry + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + return 1; +} + +void vtkWarpVector::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; +} diff --git a/Graphics/vtkWarpVector.h b/Graphics/vtkWarpVector.h new file mode 100644 index 0000000..facadcd --- /dev/null +++ b/Graphics/vtkWarpVector.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWarpVector.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWarpVector - deform geometry with vector data +// .SECTION Description +// vtkWarpVector is a filter that modifies point coordinates by moving +// points along vector times the scale factor. Useful for showing flow +// profiles or mechanical deformation. +// +// The filter passes both its point data and cell data to its output. + +#ifndef __vtkWarpVector_h +#define __vtkWarpVector_h + +#include "vtkPointSetAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkWarpVector : public vtkPointSetAlgorithm +{ +public: + static vtkWarpVector *New(); + vtkTypeRevisionMacro(vtkWarpVector,vtkPointSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify value to scale displacement. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + +protected: + vtkWarpVector(); + ~vtkWarpVector(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + double ScaleFactor; + +private: + vtkWarpVector(const vtkWarpVector&); // Not implemented. + void operator=(const vtkWarpVector&); // Not implemented. +}; + +#endif diff --git a/Graphics/vtkWindowedSincPolyDataFilter.cxx b/Graphics/vtkWindowedSincPolyDataFilter.cxx new file mode 100644 index 0000000..289ba19 --- /dev/null +++ b/Graphics/vtkWindowedSincPolyDataFilter.cxx @@ -0,0 +1,812 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindowedSincPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWindowedSincPolyDataFilter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkTriangle.h" +#include "vtkTriangleFilter.h" + +vtkCxxRevisionMacro(vtkWindowedSincPolyDataFilter, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkWindowedSincPolyDataFilter); + +// Construct object with number of iterations 20; passband .1; +// feature edge smoothing turned off; feature + +// angle 45 degrees; edge angle 15 degrees; and boundary smoothing turned +// on. Error scalars and vectors are not generated (by default). The +// convergence criterion is 0.0 of the bounding box diagonal. +vtkWindowedSincPolyDataFilter::vtkWindowedSincPolyDataFilter() +{ + this->NumberOfIterations = 20; + this->PassBand = 0.1; + + this->FeatureAngle = 45.0; + this->EdgeAngle = 15.0; + this->FeatureEdgeSmoothing = 0; + this->BoundarySmoothing = 1; + this->NonManifoldSmoothing = 0; + + this->GenerateErrorScalars = 0; + this->GenerateErrorVectors = 0; + + this->NormalizeCoordinates = 0; +} + +#define VTK_SIMPLE_VERTEX 0 +#define VTK_FIXED_VERTEX 1 +#define VTK_FEATURE_EDGE_VERTEX 2 +#define VTK_BOUNDARY_EDGE_VERTEX 3 + +// Special structure for marking vertices +typedef struct _vtkMeshVertex + { + char type; + vtkIdList *edges; // connected edges (list of connected point ids) +} vtkMeshVertex, *vtkMeshVertexPtr; + +int vtkWindowedSincPolyDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numPts, numCells, numPolys, numStrips, i; + int j, k; + vtkIdType npts = 0; + vtkIdType *pts = 0; + vtkIdType p1, p2; + double x[3], y[3], deltaX[3], xNew[3]; + double x1[3], x2[3], x3[3], l1[3], l2[3]; + double CosFeatureAngle; //Cosine of angle between adjacent polys + double CosEdgeAngle; // Cosine of angle between adjacent edges + int iterationNumber, abortExecute; + vtkIdType numSimple=0, numBEdges=0, numFixed=0, numFEdges=0; + vtkPolyData *inMesh = NULL, *Mesh; + vtkPoints *inPts; + vtkTriangleFilter *toTris=NULL; + vtkCellArray *inVerts, *inLines, *inPolys, *inStrips; + vtkPoints *newPts[4]; + vtkMeshVertexPtr Verts; + + // variables specific to windowed sinc interpolation + double theta_pb, k_pb, sigma, p_x0[3], p_x1[3], p_x3[3]; + double *w, *c, *cprime; + int zero, one, two, three; + +// +// Check input +// + numPts=input->GetNumberOfPoints(); + numCells=input->GetNumberOfCells(); + if (numPts < 1 || numCells < 1) + { + vtkErrorMacro(<<"No data to smooth!"); + return 1; + } + + CosFeatureAngle = + cos((double) vtkMath::DegreesToRadians() * this->FeatureAngle); + CosEdgeAngle = cos((double) vtkMath::DegreesToRadians() * this->EdgeAngle); + + vtkDebugMacro(<<"Smoothing " << numPts << " vertices, " << numCells + << " cells with:\n" + << "\tIterations= " << this->NumberOfIterations << "\n" + << "\tPassBand= " << this->PassBand << "\n" + << "\tEdge Angle= " << this->EdgeAngle << "\n" + << "\tBoundary Smoothing " + << (this->BoundarySmoothing ? "On\n" : "Off\n") + << "\tFeature Edge Smoothing " + << (this->FeatureEdgeSmoothing ? "On\n" : "Off\n") + << "\tNonmanifold Smoothing " + << (this->NonManifoldSmoothing ? "On\n" : "Off\n") + << "\tError Scalars " + << (this->GenerateErrorScalars ? "On\n" : "Off\n") + << "\tError Vectors " + << (this->GenerateErrorVectors ? "On\n" : "Off\n")); + + if ( this->NumberOfIterations <= 0 ) //don't do anything! + { + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + vtkWarningMacro(<<"Number of iterations == 0: passing data through unchanged"); + return 1; + } +// +// Peform topological analysis. What we're gonna do is build a connectivity +// array of connected vertices. The outcome will be one of three +// classifications for a vertex: VTK_SIMPLE_VERTEX, VTK_FIXED_VERTEX. or +// VTK_EDGE_VERTEX. Simple vertices are smoothed using all connected +// vertices. FIXED vertices are never smoothed. Edge vertices are smoothed +// using a subset of the attached vertices. +// + vtkDebugMacro(<<"Analyzing topology..."); + Verts = new vtkMeshVertex[numPts]; + for (i=0; iGetPoints(); + + // check vertices first. Vertices are never smoothed_-------------- + for (inVerts=input->GetVerts(), inVerts->InitTraversal(); + inVerts->GetNextCell(npts,pts); ) + { + for (j=0; jUpdateProgress(0.10); + + // now check lines. Only manifold lines can be smoothed------------ + for (inLines=input->GetLines(), inLines->InitTraversal(); + inLines->GetNextCell(npts,pts); ) + { + for (j=0; jGetPoint(pts[0],x2); + inPts->GetPoint(pts[1],x3); + } + else //is edge vertex (unless already edge vertex!) + { + Verts[pts[j]].type = VTK_FEATURE_EDGE_VERTEX; + Verts[pts[j]].edges = vtkIdList::New(); + Verts[pts[j]].edges->SetNumberOfIds(2); + //Verts[pts[j]].edges = new vtkIdList(2,2); + Verts[pts[j]].edges->SetId(0,pts[j-1]); + Verts[pts[j]].edges->SetId(1,pts[j+1]); + } + } //if simple vertex + + else if ( Verts[pts[j]].type == VTK_FEATURE_EDGE_VERTEX ) + { //multiply connected, becomes fixed! + Verts[pts[j]].type = VTK_FIXED_VERTEX; + Verts[pts[j]].edges->Delete(); + Verts[pts[j]].edges = NULL; + } + + } //for all points in this line + } //for all lines + + this->UpdateProgress(0.25); + + // now polygons and triangle strips------------------------------- + inPolys=input->GetPolys(); + numPolys = inPolys->GetNumberOfCells(); + inStrips=input->GetStrips(); + numStrips = inStrips->GetNumberOfCells(); + + if ( numPolys > 0 || numStrips > 0 ) + { //build cell structure + vtkCellArray *polys; + vtkIdType cellId; + int numNei, nei, edge; + vtkIdType numNeiPts; + vtkIdType *neiPts; + double normal[3], neiNormal[3]; + vtkIdList *neighbors; + + inMesh = vtkPolyData::New(); + inMesh->SetPoints(inPts); + inMesh->SetPolys(inPolys); + Mesh = inMesh; + neighbors = vtkIdList::New(); + neighbors->Allocate(VTK_CELL_SIZE); + + if ( (numStrips = inStrips->GetNumberOfCells()) > 0 ) + { // convert data to triangles + inMesh->SetStrips(inStrips); + toTris = vtkTriangleFilter::New(); + toTris->SetInput(inMesh); + toTris->Update(); + Mesh = toTris->GetOutput(); + } + + Mesh->BuildLinks(); //to do neighborhood searching + polys = Mesh->GetPolys(); + + for (cellId=0, polys->InitTraversal(); polys->GetNextCell(npts,pts); + cellId++) + { + for (i=0; i < npts; i++) + { + p1 = pts[i]; + p2 = pts[(i+1)%npts]; + + if ( Verts[p1].edges == NULL ) + { + Verts[p1].edges = vtkIdList::New(); + Verts[p1].edges->Allocate(16,6); + // Verts[p1].edges = new vtkIdList(6,6); + } + if ( Verts[p2].edges == NULL ) + { + Verts[p2].edges = vtkIdList::New(); + Verts[p2].edges->Allocate(16,6); + // Verts[p2].edges = new vtkIdList(6,6); + } + + Mesh->GetCellEdgeNeighbors(cellId,p1,p2,neighbors); + numNei = neighbors->GetNumberOfIds(); + + edge = VTK_SIMPLE_VERTEX; + if ( numNei == 0 ) + { + edge = VTK_BOUNDARY_EDGE_VERTEX; + } + + else if ( numNei >= 2 ) + { + // non-manifold case, check nonmanifold smoothing state + if (!this->NonManifoldSmoothing) + { + // check to make sure that this edge hasn't been marked already + for (j=0; j < numNei; j++) + { + if ( neighbors->GetId(j) < cellId ) + { + break; + } + } + if ( j >= numNei ) + { + edge = VTK_FEATURE_EDGE_VERTEX; + } + } + } + + else if ( numNei == 1 && (nei=neighbors->GetId(0)) > cellId ) + { + if (this->FeatureEdgeSmoothing) + { + vtkPolygon::ComputeNormal(inPts,npts,pts,normal); + Mesh->GetCellPoints(nei,numNeiPts,neiPts); + vtkPolygon::ComputeNormal(inPts,numNeiPts,neiPts,neiNormal); + + if ( vtkMath::Dot(normal,neiNormal) <= CosFeatureAngle ) + { + edge = VTK_FEATURE_EDGE_VERTEX; + } + } + } + else // a visited edge; skip rest of analysis + { + continue; + } + + if ( edge && Verts[p1].type == VTK_SIMPLE_VERTEX ) + { + Verts[p1].edges->Reset(); + Verts[p1].edges->InsertNextId(p2); + Verts[p1].type = edge; + } + else if ( (edge && Verts[p1].type == VTK_BOUNDARY_EDGE_VERTEX) || + (edge && Verts[p1].type == VTK_FEATURE_EDGE_VERTEX) || + (!edge && Verts[p1].type == VTK_SIMPLE_VERTEX ) ) + { + Verts[p1].edges->InsertNextId(p2); + if ( Verts[p1].type && edge == VTK_BOUNDARY_EDGE_VERTEX ) + { + Verts[p1].type = VTK_BOUNDARY_EDGE_VERTEX; + } + } + + if ( edge && Verts[p2].type == VTK_SIMPLE_VERTEX ) + { + Verts[p2].edges->Reset(); + Verts[p2].edges->InsertNextId(p1); + Verts[p2].type = edge; + } + else if ( (edge && Verts[p2].type == VTK_BOUNDARY_EDGE_VERTEX ) || + (edge && Verts[p2].type == VTK_FEATURE_EDGE_VERTEX) || + (!edge && Verts[p2].type == VTK_SIMPLE_VERTEX ) ) + { + Verts[p2].edges->InsertNextId(p1); + if ( Verts[p2].type && edge == VTK_BOUNDARY_EDGE_VERTEX ) + { + Verts[p2].type = VTK_BOUNDARY_EDGE_VERTEX; + } + } + } + } + + // delete inMesh; // delete this later, windowed sinc smoothing needs it + if (toTris) + { + toTris->Delete(); + } + neighbors->Delete(); + }//if strips or polys + + this->UpdateProgress(0.50); + + //post-process edge vertices to make sure we can smooth them + for (i=0; iBoundarySmoothing && + Verts[i].type == VTK_BOUNDARY_EDGE_VERTEX ) + { + Verts[i].type = VTK_FIXED_VERTEX; + numBEdges++; + } + + else if ( (npts = Verts[i].edges->GetNumberOfIds()) != 2 ) + { + // can only smooth edges on 2-manifold surfaces + Verts[i].type = VTK_FIXED_VERTEX; + numFixed++; + } + + else //check angle between edges + { + inPts->GetPoint(Verts[i].edges->GetId(0),x1); + inPts->GetPoint(i,x2); + inPts->GetPoint(Verts[i].edges->GetId(1),x3); + + for (k=0; k<3; k++) + { + l1[k] = x2[k] - x1[k]; + l2[k] = x3[k] - x2[k]; + } + if ((vtkMath::Normalize(l1) >= 0.0) && (vtkMath::Normalize(l2) >= 0.0) + && (vtkMath::Dot(l1,l2) < CosEdgeAngle)) + { + numFixed++; + Verts[i].type = VTK_FIXED_VERTEX; + } + else + { + if ( Verts[i].type == VTK_FEATURE_EDGE_VERTEX ) + { + numFEdges++; + } + else + { + numBEdges++; + } + } + }//if along edge + }//if edge vertex + }//for all points + + vtkDebugMacro(<<"Found\n\t" << numSimple << " simple vertices\n\t" + << numFEdges << " feature edge vertices\n\t" + << numBEdges << " boundary edge vertices\n\t" + << numFixed << " fixed vertices\n\t"); +// +// Perform Windowed Sinc function interpolation +// + vtkDebugMacro(<<"Beginning smoothing iterations..."); + + // need 4 vectors of points + zero=0; one=1; two=2; three=3; + + newPts[0] = vtkPoints::New(); + newPts[0]->SetNumberOfPoints(numPts); + newPts[1] = vtkPoints::New(); + newPts[1]->SetNumberOfPoints(numPts); + newPts[2] = vtkPoints::New(); + newPts[2]->SetNumberOfPoints(numPts); + newPts[3] = vtkPoints::New(); + newPts[3]->SetNumberOfPoints(numPts); + + // Get the center and length of the input dataset + double *inCenter = input->GetCenter(); + double inLength = input->GetLength(); + + if (!this->NormalizeCoordinates) + { + for (i=0; iSetPoint(i,inPts->GetPoint(i)); + } + } + else + { + // center the data and scale to be within unit cube [-1, 1] + double normalizedPoint[3]; + for (i=0; iGetPoint(i, normalizedPoint); + for (j=0; j<3; ++j) + { + normalizedPoint[j] = (normalizedPoint[j] - inCenter[j]) / inLength; + } + newPts[zero]->SetPoint(i,normalizedPoint); + } + } + + // Smooth with a low pass filter defined as a windowed sinc function. + // Taubin describes this methodology is the IBM tech report RC-20404 + // (#90237, dated 3/12/96) "Optimal Surface Smoothing as Filter Design" + // G. Taubin, T. Zhang and G. Golub. (Zhang and Golub are at Stanford + // University) + + // The formulas here follow the notation of Taubin's TR, i.e. + // newPts[zero], newPts[one], etc. + + // calculate weights and filter coefficients + k_pb = this->PassBand; // reasonable default for k_pb in [0, 2] is 0.1 + theta_pb = acos( 1.0 - 0.5 * k_pb ); // theta_pb in [0, M_PI/2] + + //vtkDebugMacro(<< "theta_pb = " << theta_pb); + + w = new double[this->NumberOfIterations+1]; + c = new double[this->NumberOfIterations+1]; + cprime = new double[this->NumberOfIterations+1]; + + double zerovector[3]; + zerovector[0] = zerovector[1] = zerovector[2] = 0.0; + + // + // Calculate the weights and the Chebychev coefficients c. + // + + // Windowed sinc function weights. This is for a Hamming window. Other + // windowing function could be implemented here. + for (i=0; i <= (this->NumberOfIterations); i++) + { + w[i] = 0.54 + 0.46*cos(((double)i)*vtkMath::Pi() + /(double)(this->NumberOfIterations+1)); + } + + // Calculate the optimal sigma (offset or fudge factor for the filter). + // This is a Newton-Raphson Search. + double f_kpb = 0.0, fprime_kpb; + int done = 0; + sigma = 0.0; + + for (j=0; !done && (j<500); j++) + { + // Chebyshev coefficients + c[0] = w[0]*(theta_pb + sigma)/vtkMath::Pi(); + for (i=1; i <= this->NumberOfIterations; i++) + { + c[i] = 2.0*w[i]*sin(((double)i)*(theta_pb+sigma))/ + (((double)i)*vtkMath::Pi()); + } + + // calculate the Chebyshev coefficients for the derivative of the filter + cprime[this->NumberOfIterations] = 0.0; + cprime[this->NumberOfIterations-1] = 0.0; + if (this->NumberOfIterations > 1) + { + cprime[this->NumberOfIterations-2] = 2.0*(this->NumberOfIterations-1) + * c[this->NumberOfIterations-1]; + } + for (i=this->NumberOfIterations-3; i>=0; i--) + { + cprime[i] = cprime[i+2] + 2.0*(i+1)*c[i+1]; + } + // Evaluate the filter and its derivative at k_pb (note the discrepancy + // of calculating the c's based on theta_pb + sigma and evaluating the + // filter at k_pb (which is equivalent to theta_pb) + f_kpb = 0.0; + fprime_kpb = 0.0; + f_kpb += c[0]; + fprime_kpb += cprime[0]; + for (i=1; i<= this->NumberOfIterations; i++) + { + if (i==1) + { + f_kpb += c[i]*(1.0 - 0.5*k_pb); + fprime_kpb += cprime[i]*(1.0 - 0.5*k_pb); + } + else + { + f_kpb += c[i]*cos(((double) i)*acos(1.0-0.5*k_pb)); + fprime_kpb += cprime[i]*cos(((double) i)*acos(1.0-0.5*k_pb)); + } + } + // if f_kpb is not close enough to 1.0, then adjust sigma + if (this->NumberOfIterations > 1) + { + if (fabs(f_kpb - 1.0) >= 1e-3) + { + sigma -= (f_kpb - 1.0)/fprime_kpb; // Newton-Rhapson (want f=1) + } + else + { + done = 1; + } + } + else + { + // Order of Chebyshev is 1. Can't use Newton-Raphson to find an + // optimal sigma. Object will most likely shrink. + done = 1; + sigma = 0.0; + } + } + if (fabs(f_kpb - 1.0) >= 1e-3) + { + vtkErrorMacro(<< "An optimal offset for the smoothing filter could not be found. Unpredictable smoothing/shrinkage may result."); + } + + // first iteration + for (i=0; iGetNumberOfIds()) > 0 ) + { + // point is allowed to move + newPts[zero]->GetPoint(i, x); //use current points + deltaX[0] = deltaX[1] = deltaX[2] = 0.0; + + // calculate the negative of the laplacian + for (j=0; jGetPoint(Verts[i].edges->GetId(j), y); + for (k=0; k<3; k++) + { + deltaX[k] += (x[k] - y[k]) / npts; + } + } + // newPts[one] = newPts[zero] - 0.5 newPts[one] + for (k=0; k<3; k++) + { + deltaX[k] = x[k] - 0.5*deltaX[k]; + } + newPts[one]->SetPoint(i, deltaX); + + // calculate newPts[three] = c0 newPts[zero] + c1 newPts[one] + for (k=0; k < 3; k++) + { + deltaX[k] = c[0]*x[k] + c[1]*deltaX[k]; + } + if (Verts[i].type == VTK_FIXED_VERTEX) + { + newPts[three]->SetPoint(i, newPts[zero]->GetPoint(i)); + } + else + { + newPts[three]->SetPoint(i, deltaX); + } + }//if can move point + else + { + // point is not allowed to move, just use the old point... + // (zero out the Laplacian) + newPts[one]->SetPoint(i, zerovector); + newPts[three]->SetPoint(i, newPts[zero]->GetPoint(i)); + } + }//for all points + + // for the rest of the iterations + for ( iterationNumber=2, abortExecute=0; + iterationNumber <= this->NumberOfIterations && !abortExecute; + iterationNumber++ ) + { + if ( iterationNumber && !(iterationNumber % 5) ) + { + this->UpdateProgress (0.5 + 0.5*iterationNumber/this->NumberOfIterations); + if (this->GetAbortExecute()) + { + abortExecute = 1; + break; + } + } + + for (i=0; iGetNumberOfIds()) > 0 ) + { + // point is allowed to move + newPts[zero]->GetPoint(i, p_x0); //use current points + newPts[one]->GetPoint(i, p_x1); + + deltaX[0] = deltaX[1] = deltaX[2] = 0.0; + + // calculate the negative laplacian of x1 + for (j=0; jGetPoint(Verts[i].edges->GetId(j), y); + for (k=0; k<3; k++) + { + deltaX[k] += (p_x1[k] - y[k]) / npts; + } + }//for all connected points + + // Taubin: x2 = (x1 - x0) + (x1 - x2) + for (k=0; k<3; k++) + { + deltaX[k] = p_x1[k] - p_x0[k] + p_x1[k] - deltaX[k]; + } + newPts[two]->SetPoint(i, deltaX); + + // smooth the vertex (x3 = x3 + cj x2) + newPts[three]->GetPoint(i, p_x3); + for (k=0;k<3;k++) + { + xNew[k] = p_x3[k] + c[iterationNumber] * deltaX[k]; + } + if (Verts[i].type != VTK_FIXED_VERTEX) + { + newPts[three]->SetPoint(i,xNew); + } + }//if can move point + else + { + // point is not allowed to move, just use the old point... + // (zero out the Laplacian) + newPts[one]->SetPoint(i, zerovector); + newPts[two]->SetPoint(i, zerovector); + } + }//for all points + + // update the pointers. three is always three. all other pointers + // shift by one and wrap. + zero = (1+zero)%3; + one = (1+one)%3; + two = (1+two)%3; + + }//for all iterations or until converge + + // move the iteration count back down so that it matches the + // actual number of iterations executed + --iterationNumber; + + // set zero to three so the correct set of positions is outputted + zero = three; + + delete [] w; + delete [] c; + delete [] cprime; + + vtkDebugMacro(<<"Performed " << iterationNumber << " smoothing passes"); + + // if we scaled the data down to the unit cube, then scale data back + // up to the original space + if (this->NormalizeCoordinates) + { + // Re-position the coordinated + double repositionedPoint[3]; + for (i=0; iGetPoint(i, repositionedPoint); + for (j=0; j<3; ++j) + { + repositionedPoint[j] = repositionedPoint[j] * inLength + inCenter[j]; + } + newPts[zero]->SetPoint(i,repositionedPoint); + } + } + +// +// Update output. Only point coordinates have changed. +// + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + if ( this->GenerateErrorScalars ) + { + vtkFloatArray *newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfTuples(numPts); + for (i=0; iGetPoint(i,x1); + newPts[zero]->GetPoint(i,x2); + newScalars->SetComponent(i,0, + sqrt(vtkMath::Distance2BetweenPoints(x1,x2))); + } + int idx = output->GetPointData()->AddArray(newScalars); + output->GetPointData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + newScalars->Delete(); + } + + if ( this->GenerateErrorVectors ) + { + vtkFloatArray *newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->SetNumberOfTuples(numPts); + for (i=0; iGetPoint(i,x1); + newPts[zero]->GetPoint(i,x2); + for (j=0; j<3; j++) + { + x3[j] = x2[j] - x1[j]; + } + newVectors->SetTuple(i,x3); + } + output->GetPointData()->SetVectors(newVectors); + newVectors->Delete(); + } + + output->SetPoints(newPts[zero]); + newPts[0]->Delete(); + newPts[1]->Delete(); + newPts[2]->Delete(); + newPts[3]->Delete(); + + output->SetVerts(input->GetVerts()); + output->SetLines(input->GetLines()); + output->SetPolys(input->GetPolys()); + output->SetStrips(input->GetStrips()); + + // finally delete the constructed (local) mesh + inMesh->Delete(); + + //free up connectivity storage + for (i=0; iDelete();} + } + delete [] Verts; + + return 1; +} + +void vtkWindowedSincPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of Iterations: " << this->NumberOfIterations << "\n"; + os << indent << "Passband: " << this->PassBand << "\n"; + os << indent << "Normalize Coordinates: " << (this->NormalizeCoordinates ? "On\n" : "Off\n"); + os << indent << "Feature Edge Smoothing: " << (this->FeatureEdgeSmoothing ? "On\n" : "Off\n"); + os << indent << "Feature Angle: " << this->FeatureAngle << "\n"; + os << indent << "Edge Angle: " << this->EdgeAngle << "\n"; + os << indent << "Boundary Smoothing: " << (this->BoundarySmoothing ? "On\n" : "Off\n"); + os << indent << "Nonmanifold Smoothing: " << (this->NonManifoldSmoothing ? "On\n" : "Off\n"); + os << indent << "Generate Error Scalars: " << (this->GenerateErrorScalars ? "On\n" : "Off\n"); + os << indent << "Generate Error Vectors: " << (this->GenerateErrorVectors ? "On\n" : "Off\n"); +} diff --git a/Graphics/vtkWindowedSincPolyDataFilter.h b/Graphics/vtkWindowedSincPolyDataFilter.h new file mode 100644 index 0000000..411091c --- /dev/null +++ b/Graphics/vtkWindowedSincPolyDataFilter.h @@ -0,0 +1,241 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindowedSincPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWindowedSincPolyDataFilter - adjust point positions using a windowed sinc function interpolation kernel +// .SECTION Description +// vtkWindowedSincPolyDataFiler adjust point coordinate using a windowed +// sinc function interpolation kernel. The effect is to "relax" the mesh, +// making the cells better shaped and the vertices more evenly distributed. +// Note that this filter operates the lines, polygons, and triangle strips +// composing an instance of vtkPolyData. Vertex or poly-vertex cells are +// never modified. +// +// The algorithm proceeds as follows. For each vertex v, a topological and +// geometric analysis is performed to determine which vertices are connected +// to v, and which cells are connected to v. Then, a connectivity array is +// constructed for each vertex. (The connectivity array is a list of lists +// of vertices that directly attach to each vertex.) Next, an iteration +// phase begins over all vertices. For each vertex v, the coordinates of v +// are modified using a windowed sinc function interpolation kernel. +// Taubin describes this methodology is the IBM tech report RC-20404 +// (#90237, dated 3/12/96) "Optimal Surface Smoothing as Filter Design" +// G. Taubin, T. Zhang and G. Golub. (Zhang and Golub are at Stanford +// University). +// +// This report discusses using standard signal processing low-pass filters +// (in particular windowed sinc functions) to smooth polyhedra. The +// transfer functions of the low-pass filters are approximated by +// Chebyshev polynomials. This facilitates applying the filters in an +// iterative diffusion process (as opposed to a kernel convolution). The +// more smoothing iterations applied, the higher the degree of polynomial +// approximating the low-pass filter transfer function. Each smoothing +// iteration, therefore, applies the next higher term of the Chebyshev +// filter approximation to the polyhedron. This decoupling of the filter +// into an iteratively applied polynomial is possible since the Chebyshev +// polynomials are orthogonal, i.e. increasing the order of the +// approximation to the filter transfer function does not alter the +// previously calculated coefficients for the low order terms. +// +// Note: Care must be taken to avoid smoothing with too few iterations. +// A Chebyshev approximation with too few terms is an poor approximation. +// The first few smoothing iterations represent a severe scaling and +// translation of the data. Subsequent iterations cause the smoothed +// polyhedron to converge to the true location and scale of the object. +// We have attempted to protect against this by automatically adjusting +// the filter, effectively widening the pass band. This adjustment is only +// possible if the number of iterations is greater than 1. Note that this +// sacrifices some degree of smoothing for model integrity. For those +// interested, the filter is adjusted by searching for a value sigma +// such that the actual pass band is k_pb + sigma and such that the +// filter transfer function evaluates to unity at k_pb, i.e. f(k_pb) = 1 +// +// To improve the numerical stability of the solution and minimize the +// scaling the translation effects, the algorithm can translate and +// scale the position coordinates to within the unit cube [-1, 1], +// perform the smoothing, and translate and scale the position +// coordinates back to the original coordinate frame. This mode is +// controlled with the NormalizeCoordinatesOn() / +// NormalizeCoordinatesOff() methods. For legacy reasons, the default +// is NormalizeCoordinatesOff. +// +// This implementation is currently limited to using an interpolation +// kernel based on Hamming windows. Other windows (such as Hann, Blackman, +// Kaiser, Lanczos, Gaussian, and exponential windows) could be used +// instead. +// +// There are some special instance variables used to control the execution +// of this filter. (These ivars basically control what vertices can be +// smoothed, and the creation of the connectivity array.) The +// BoundarySmoothing ivar enables/disables the smoothing operation on +// vertices that are on the "boundary" of the mesh. A boundary vertex is one +// that is surrounded by a semi-cycle of polygons (or used by a single +// line). +// +// Another important ivar is FeatureEdgeSmoothing. If this ivar is +// enabled, then interior vertices are classified as either "simple", +// "interior edge", or "fixed", and smoothed differently. (Interior +// vertices are manifold vertices surrounded by a cycle of polygons; or used +// by two line cells.) The classification is based on the number of feature +// edges attached to v. A feature edge occurs when the angle between the two +// surface normals of a polygon sharing an edge is greater than the +// FeatureAngle ivar. Then, vertices used by no feature edges are classified +// "simple", vertices used by exactly two feature edges are classified +// "interior edge", and all others are "fixed" vertices. +// +// Once the classification is known, the vertices are smoothed +// differently. Corner (i.e., fixed) vertices are not smoothed at all. +// Simple vertices are smoothed as before . Interior edge vertices are +// smoothed only along their two connected edges, and only if the angle +// between the edges is less than the EdgeAngle ivar. +// +// The total smoothing can be controlled by using two ivars. The +// NumberOfIterations determines the maximum number of smoothing passes. +// The NumberOfIterations corresponds to the degree of the polynomial that +// is used to approximate the windowed sinc function. Ten or twenty +// iterations is all the is usually necessary. Contrast this with +// vtkSmoothPolyDataFilter which usually requires 100 to 200 smoothing +// iterations. vtkSmoothPolyDataFilter is also not an approximation to +// an ideal low-pass filter, which can cause the geometry to shrink as the +// amount of smoothing increases. +// +// The second ivar is the specification of the PassBand for the windowed +// sinc filter. By design, the PassBand is specified as a doubleing point +// number between 0 and 2. Lower PassBand values produce more smoothing. +// A good default value for the PassBand is 0.1 (for those interested, the +// PassBand (and frequencies) for PolyData are based on the valence of the +// vertices, this limits all the frequency modes in a polyhedral mesh to +// between 0 and 2.) +// +// There are two instance variables that control the generation of error +// data. If the ivar GenerateErrorScalars is on, then a scalar value indicating +// the distance of each vertex from its original position is computed. If the +// ivar GenerateErrorVectors is on, then a vector representing change in +// position is computed. +// +// .SECTION Caveats +// The smoothing operation reduces high frequency information in the +// geometry of the mesh. With excessive smoothing important details may be +// lost. Enabling FeatureEdgeSmoothing helps reduce this effect, but cannot +// entirely eliminate it. +// +// .SECTION See Also +// vtkSmoothPolyDataFilter vtkDecimate vtkDecimatePro + + +#ifndef __vtkWindowedSincPolyDataFilter_h +#define __vtkWindowedSincPolyDataFilter_h + + +#include "vtkPolyDataAlgorithm.h" + +class VTK_GRAPHICS_EXPORT vtkWindowedSincPolyDataFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkWindowedSincPolyDataFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with number of iterations 20; passband .1; + // feature edge smoothing turned off; feature + // angle 45 degrees; edge angle 15 degrees; and boundary smoothing turned + // on. Error scalars and vectors are not generated (by default). The + // convergence criterion is 0.0 of the bounding box diagonal. + static vtkWindowedSincPolyDataFilter *New(); + + // Description: + // Specify the number of iterations (or degree of the polynomial + // approximating the windowed sinc function). + vtkSetClampMacro(NumberOfIterations,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfIterations,int); + + // Description: + // Set the passband value for the windowed sinc filter + vtkSetClampMacro(PassBand,double, 0.0, 2.0); + vtkGetMacro(PassBand,double); + + // Description: + // Turn on/off coordinate normalization. The positions can be + // translated and scaled such that they fit within a [-1, 1] prior + // to the smoothing computation. The default is off. The numerical + // stability of the solution can be improved by turning + // normalization on. If normalization is on, the coordinates will + // be rescaled to the original coordinate system after smoothing has + // completed. + vtkSetMacro(NormalizeCoordinates, int); + vtkGetMacro(NormalizeCoordinates, int); + vtkBooleanMacro(NormalizeCoordinates, int); + + // Description: + // Turn on/off smoothing along sharp interior edges. + vtkSetMacro(FeatureEdgeSmoothing,int); + vtkGetMacro(FeatureEdgeSmoothing,int); + vtkBooleanMacro(FeatureEdgeSmoothing,int); + + // Description: + // Specify the feature angle for sharp edge identification. + vtkSetClampMacro(FeatureAngle,double,0.0,180.0); + vtkGetMacro(FeatureAngle,double); + + // Description: + // Specify the edge angle to control smoothing along edges (either interior + // or boundary). + vtkSetClampMacro(EdgeAngle,double,0.0,180.0); + vtkGetMacro(EdgeAngle,double); + + // Description: + // Turn on/off the smoothing of vertices on the boundary of the mesh. + vtkSetMacro(BoundarySmoothing,int); + vtkGetMacro(BoundarySmoothing,int); + vtkBooleanMacro(BoundarySmoothing,int); + + // Description: + // Smooth non-manifold vertices. + vtkSetMacro(NonManifoldSmoothing,int); + vtkGetMacro(NonManifoldSmoothing,int); + vtkBooleanMacro(NonManifoldSmoothing,int); + + // Description: + // Turn on/off the generation of scalar distance values. + vtkSetMacro(GenerateErrorScalars,int); + vtkGetMacro(GenerateErrorScalars,int); + vtkBooleanMacro(GenerateErrorScalars,int); + + // Description: + // Turn on/off the generation of error vectors. + vtkSetMacro(GenerateErrorVectors,int); + vtkGetMacro(GenerateErrorVectors,int); + vtkBooleanMacro(GenerateErrorVectors,int); + + protected: + vtkWindowedSincPolyDataFilter(); + ~vtkWindowedSincPolyDataFilter() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int NumberOfIterations; + double PassBand; + int FeatureEdgeSmoothing; + double FeatureAngle; + double EdgeAngle; + int BoundarySmoothing; + int NonManifoldSmoothing; + int GenerateErrorScalars; + int GenerateErrorVectors; + int NormalizeCoordinates; +private: + vtkWindowedSincPolyDataFilter(const vtkWindowedSincPolyDataFilter&); // Not implemented. + void operator=(const vtkWindowedSincPolyDataFilter&); // Not implemented. +}; + +#endif diff --git a/Hybrid/CMakeLists.txt b/Hybrid/CMakeLists.txt new file mode 100644 index 0000000..259c1f3 --- /dev/null +++ b/Hybrid/CMakeLists.txt @@ -0,0 +1,103 @@ +SET(KIT Hybrid) +SET(UKIT HYBRID) + +SET(KIT_TCL_LIBS vtkRenderingTCL vtkIOTCL) +SET(KIT_PYTHON_LIBS vtkRenderingPythonD vtkIOPythonD) +SET(KIT_JAVA_LIBS vtkRenderingJava vtkIOJava) +SET(KIT_LIBS vtkRendering vtkIO) +IF(VTK_HAS_EXODUS) + SET(KIT_LIBS ${KIT_LIBS} vtkexoIIc) +ENDIF(VTK_HAS_EXODUS) + +IF (WIN32) + IF (VTK_VFW_SUPPORTS_CAPTURE) + IF(BORLAND) + INCLUDE ("${CMAKE_ROOT}/Modules/CheckLibraryExists.cmake") + CHECK_LIBRARY_EXISTS("vfw32" "printf" "" HAVE_VFW32) + IF(NOT HAVE_VFW32) + MESSAGE(SEND_ERROR "Bad installation of Borland compiler. PSDK is not in ilink32.cfg and in bcc32.cfg.") + ENDIF(NOT HAVE_VFW32) + ENDIF(BORLAND) + SET(KIT_LIBS ${KIT_LIBS} vfw32) + ENDIF (VTK_VFW_SUPPORTS_CAPTURE) + IF (VTK_USE_MATROX_IMAGING) + SET(KIT_LIBS ${KIT_LIBS} ${MIL_LIBRARY}) + ENDIF (VTK_USE_MATROX_IMAGING) +ENDIF (WIN32) + +SET ( Kit_SRCS +vtk3DSImporter.cxx +vtkArcPlotter.cxx +vtkAnnotatedCubeActor.cxx +vtkAxesActor.cxx +vtkCaptionActor2D.cxx +vtkCornerAnnotation.cxx +vtkCubeAxesActor2D.cxx +vtkDepthSortPolyData.cxx +vtkEarthSource.cxx +vtkFacetReader.cxx +vtkGreedyTerrainDecimation.cxx +vtkGridTransform.cxx +vtkImageToPolyDataFilter.cxx +vtkImplicitModeller.cxx +vtkIterativeClosestPointTransform.cxx +vtkLandmarkTransform.cxx +vtkLegendBoxActor.cxx +vtkPCAAnalysisFilter.cxx +vtkPolyDataToImageStencil.cxx +vtkProcrustesAlignmentFilter.cxx +vtkProjectedTerrainPath.cxx +vtkRIBExporter.cxx +vtkRIBLight.cxx +vtkRIBProperty.cxx +vtkRenderLargeImage.cxx +vtkThinPlateSplineTransform.cxx +vtkTransformToGrid.cxx +vtkVRMLImporter.cxx +vtkVectorText.cxx +vtkVideoSource.cxx +vtkWeightedTransformFilter.cxx +vtkXYPlotActor.cxx +) +IF(VTK_HAS_EXODUS) + SET(Kit_SRCS ${Kit_SRCS} + vtkPExodusReader.cxx + vtkExodusReader.cxx + vtkDSPFilterDefinition.cxx + vtkExodusModel.cxx + vtkDSPFilterGroup.cxx + ) +ENDIF(VTK_HAS_EXODUS) + +IF (WIN32) + IF (VTK_VFW_SUPPORTS_CAPTURE) + SET (Kit_SRCS ${Kit_SRCS} vtkWin32VideoSource.cxx) + ENDIF (VTK_VFW_SUPPORTS_CAPTURE) + + IF (VTK_USE_MATROX_IMAGING) + SET (Kit_SRCS ${Kit_SRCS} vtkMILVideoSource.cxx) + # Include directory needed for vtkMILVideoSource.cxx. + ENDIF (VTK_USE_MATROX_IMAGING) +ENDIF (WIN32) + +SET_SOURCE_FILES_PROPERTIES( +vtkVRML +WRAP_EXCLUDE) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h vtk3DS) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Hybrid/Testing/CMakeLists.txt b/Hybrid/Testing/CMakeLists.txt new file mode 100644 index 0000000..e4aeae2 --- /dev/null +++ b/Hybrid/Testing/CMakeLists.txt @@ -0,0 +1,21 @@ +# Commented out to avoid problems with Borland dashboards +# until new tests are added to Cxx/CMakeLists.txt. +#SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Hybrid ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Hybrid" + VTK_HYBRID_EXPORT + vtk3DS.h + vtkVRML.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/Hybrid/Testing/Cxx/CMakeLists.txt b/Hybrid/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..2683401 --- /dev/null +++ b/Hybrid/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,36 @@ +SET(KIT Hybrid) +# add tests that do not require data +SET(MyTests + ) +IF (VTK_DATA_ROOT) + # add tests that require data + SET(MyTests ${MyTests} + ) +ENDIF (VTK_DATA_ROOT) + +# remove some tests if there is no display +IF(NOT VTK_USE_DISPLAY) + REMOVE(MyTests + ) +ENDIF(NOT VTK_USE_DISPLAY) + +CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx ${MyTests} + EXTRA_INCLUDE vtkTestDriver.h) + +ADD_EXECUTABLE(${KIT}CxxTests ${Tests}) +TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkHybrid) +SET (TestsToRun ${Tests}) +REMOVE (TestsToRun ${KIT}CxxTests.cxx) + +# +# Add all the executables +FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + IF (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName} + -D ${VTK_DATA_ROOT} + -V Baseline/${KIT}/${TName}.png) + ELSE (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) + ENDIF (VTK_DATA_ROOT) +ENDFOREACH (test) diff --git a/Hybrid/Testing/Python/CMakeLists.txt b/Hybrid/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..61cf01a --- /dev/null +++ b/Hybrid/Testing/Python/CMakeLists.txt @@ -0,0 +1,58 @@ +INCLUDE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake) +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + IF (VTK_PYTHON_EXE) + # Add test converted from Tcl + SET( tests + 3DMorph + appendImplicitModel + appendImplicitModelNoBounds + banana + bore + camera + clipHex + clipPyramid + clipTet + clipWedge + cubeAxes + depthSort + earth + imageToPolyData + #financialField2 -- arrays + #financialField3 -- arrays + largeImageOffset + largeImageParallel + #MassProperties -- complicated global/local mess up + OverlayTextOnImage + TestCaptionActor + TestFacetReader + TestGreedyTerrainDecimation + TestGridWarp3D + TestGridWarpCubic + TestGridWarpLinear + TestGridWarpNearest + #TestICPTransform --complex arrays + TestImageStencilWithPolydata + TestPCA + TestProcrustes + TestProjectedTerrainPath + TestThinPlateWarp + TestThinPlateWarp3D + text + VRMLImporter + WarpPolyData + xyPlot + xyPlot2 + xyPlot3 + xyPlot4 + ) + CONVERT_TCL_TEST_TO_PY ( + tests + Hybrid) + + ENDIF (VTK_PYTHON_EXE) + ENDIF (VTK_DATA_ROOT) +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) diff --git a/Hybrid/Testing/Tcl/3DMorph.tcl b/Hybrid/Testing/Tcl/3DMorph.tcl new file mode 100644 index 0000000..cac26ef --- /dev/null +++ b/Hybrid/Testing/Tcl/3DMorph.tcl @@ -0,0 +1,100 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# use implicit modeller / interpolation to perform 3D morphing +# +# make the letter v +vtkVectorText letterV + letterV SetText "v" + +# read the geometry file containing the letter t +vtkVectorText letterT + letterT SetText "t" + +# read the geometry file containing the letter k +vtkVectorText letterK + letterK SetText "k" + +# create implicit models of each +vtkImplicitModeller blobbyV + blobbyV SetInputConnection [letterV GetOutputPort] + blobbyV SetMaximumDistance .2 + blobbyV SetSampleDimensions 50 50 12 + blobbyV SetModelBounds -0.5 1.5 -0.5 1.5 -0.5 0.5 + +# create implicit models of each +vtkImplicitModeller blobbyT + blobbyT SetInputConnection [letterT GetOutputPort] + blobbyT SetMaximumDistance .2 + blobbyT SetSampleDimensions 50 50 12 + blobbyT SetModelBounds -0.5 1.5 -0.5 1.5 -0.5 0.5 + +# create implicit models of each +vtkImplicitModeller blobbyK + blobbyK SetInputConnection [letterK GetOutputPort] + blobbyK SetMaximumDistance .2 + blobbyK SetSampleDimensions 50 50 12 + blobbyK SetModelBounds -0.5 1.5 -0.5 1.5 -0.5 0.5 + +# Interpolate the data +vtkInterpolateDataSetAttributes interpolate + interpolate AddInput [blobbyV GetOutput] + interpolate AddInput [blobbyT GetOutput] + interpolate AddInput [blobbyK GetOutput] + interpolate SetT 0.0 + +# extract an iso surface +vtkContourFilter blobbyIso + blobbyIso SetInputConnection [interpolate GetOutputPort] + blobbyIso SetValue 0 0.1 + +# map to rendering primitives +vtkPolyDataMapper blobbyMapper + blobbyMapper SetInputConnection [blobbyIso GetOutputPort] + blobbyMapper ScalarVisibilityOff + +# now an actor +vtkActor blobby + blobby SetMapper blobbyMapper + eval [blobby GetProperty] SetDiffuseColor $banana + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkCamera camera + camera SetClippingRange 0.265 13.2 + camera SetFocalPoint 0.539 0.47464 0 + camera SetPosition 0.539 0.474674 2.644 + camera SetViewUp 0 1 0 +ren1 SetActiveCamera camera + +# now make a renderer and tell it about lights and actors +renWin SetSize 300 350 + +ren1 AddActor blobby +ren1 SetBackground 1 1 1 +renWin Render + +set subIters 4.0 +for {set i 0} {$i < 2} {incr i} { + for {set j 1} {$j <= $subIters} {incr j} { + set t [expr $i + $j/$subIters] + interpolate SetT $t + renWin Render + } +} + + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/CMakeLists.txt b/Hybrid/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..5c075f5 --- /dev/null +++ b/Hybrid/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,96 @@ +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + FOREACH ( tfile + 3DMorph + appendImplicitModel + appendImplicitModelNoBounds + banana + bore + camera + clipHex + clipPyramid + clipTet + clipWedge + cubeAxes + depthSort + earth + imageToPolyData + financialField2 + financialField3 + largeImageOffset + largeImageParallel + MassProperties + OverlayTextOnImage + TestCaptionActor + TestFacetReader + TestGreedyTerrainDecimation + TestGridWarp3D + TestGridWarpCubic + TestGridWarpLinear + TestGridWarpNearest + TestICPTransform + TestImageStencilWithPolydata + TestPCA + TestProcrustes + TestProjectedTerrainPath + TestThinPlateWarp + TestThinPlateWarp3D + text + VRMLImporter + WarpPolyData + xyPlot + xyPlot2 + xyPlot3 + xyPlot4 + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Hybrid/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -V Baseline/Hybrid/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + # + # If we do not have the data, still run the tests that we can + # + ELSE (VTK_DATA_ROOT) + FOREACH ( tfile + 3DMorph + banana + camera + clipHex + clipPyramid + clipTet + clipWedge + depthSort + MassProperties + TestICPTransform + TestPCA + TestProcrustes + text + WarpPolyData + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Hybrid/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Hybrid/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + +ADD_TEST(PrintSelf-Hybrid ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Hybrid) + +ADD_TEST(TestSetObjectMacro-Hybrid ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Hybrid/vtk\\\\*.h" + "vtkSetObjectMacro") diff --git a/Hybrid/Testing/Tcl/MassProperties.tcl b/Hybrid/Testing/Tcl/MassProperties.tcl new file mode 100644 index 0000000..e9fbb93 --- /dev/null +++ b/Hybrid/Testing/Tcl/MassProperties.tcl @@ -0,0 +1,110 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkConeSource cone + cone SetResolution 50 + +vtkSphereSource sphere + sphere SetPhiResolution 50 + sphere SetThetaResolution 50 + +vtkCubeSource cube + cube SetXLength 1 + cube SetYLength 1 + cube SetZLength 1 + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn + +vtkActor sphereActor + sphereActor SetMapper sphereMapper +[sphereActor GetProperty] SetDiffuseColor 1 .2 .4 +vtkPolyDataMapper coneMapper + coneMapper SetInputConnection [cone GetOutputPort] + coneMapper GlobalImmediateModeRenderingOn + +vtkActor coneActor + coneActor SetMapper coneMapper +[coneActor GetProperty] SetDiffuseColor .2 .4 1 + +vtkPolyDataMapper cubeMapper + cubeMapper SetInputConnection [cube GetOutputPort] + cubeMapper GlobalImmediateModeRenderingOn + +vtkActor cubeActor + cubeActor SetMapper cubeMapper + [cubeActor GetProperty] SetDiffuseColor .2 1 .4 + +#Add the actors to the renderer, set the background and size +# +sphereActor SetPosition -5 0 0 +ren1 AddActor sphereActor +coneActor SetPosition 0 0 0 +ren1 AddActor coneActor +coneActor SetPosition 5 0 0 +ren1 AddActor cubeActor + +proc MakeText { primitive } { + + vtkTriangleFilter ${primitive}TriangleFilter + ${primitive}TriangleFilter SetInputConnection [${primitive} GetOutputPort] + + vtkMassProperties ${primitive}Mass + ${primitive}Mass SetInputConnection [${primitive}TriangleFilter GetOutputPort] + + set summary [${primitive}Mass Print] + set startSum [string first " VolumeX" $summary] + set endSum [string length $summary] + + vtkVectorText ${primitive}Text + ${primitive}Text SetText [string range $summary $startSum $endSum] + + vtkPolyDataMapper ${primitive}TextMapper + ${primitive}TextMapper SetInputConnection [${primitive}Text GetOutputPort] + + vtkActor ${primitive}TextActor + ${primitive}TextActor SetMapper ${primitive}TextMapper + ${primitive}TextActor SetScale .2 .2 .2 + return ${primitive}TextActor +} + +ren1 AddActor [MakeText sphere] +ren1 AddActor [MakeText cube] +ren1 AddActor [MakeText cone] + +eval sphereTextActor SetPosition [sphereActor GetPosition] + sphereTextActor AddPosition -2 -1 0 +eval cubeTextActor SetPosition [cubeActor GetPosition] + cubeTextActor AddPosition -2 -1 0 +eval coneTextActor SetPosition [coneActor GetPosition] + coneTextActor AddPosition -2 -1 0 + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 786 256 +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Dolly 3 +ren1 ResetCameraClippingRange + +iren Initialize +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/OverlayTextOnImage.tcl b/Hybrid/Testing/Tcl/OverlayTextOnImage.tcl new file mode 100644 index 0000000..f65cb09 --- /dev/null +++ b/Hybrid/Testing/Tcl/OverlayTextOnImage.tcl @@ -0,0 +1,45 @@ +# +# display text over an image +# + +package require vtk +package require vtkinteraction +package require vtktesting + +vtkImageEllipsoidSource ellipse + +vtkImageMapper mapImage + mapImage SetInputConnection [ellipse GetOutputPort] + mapImage SetColorWindow 255 + mapImage SetColorLevel 127.5 + +vtkActor2D img + img SetMapper mapImage + +vtkTextMapper mapText + mapText SetInput "Text Overlay" + [mapText GetTextProperty] SetFontSize 15 + [mapText GetTextProperty] SetColor 0 1 1 + [mapText GetTextProperty] BoldOn + [mapText GetTextProperty] ShadowOn + +vtkActor2D txt + txt SetMapper mapText + txt SetPosition 138 128 + +vtkRenderer ren1 + ren1 AddActor2D img + ren1 AddActor2D txt + +vtkRenderWindow renWin + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render +iren Initialize + +wm withdraw . diff --git a/Hybrid/Testing/Tcl/TestCaptionActor.tcl b/Hybrid/Testing/Tcl/TestCaptionActor.tcl new file mode 100644 index 0000000..e3b84aa --- /dev/null +++ b/Hybrid/Testing/Tcl/TestCaptionActor.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +vtkConeSource coneGlyph + coneGlyph SetResolution 6 + +vtkSphereSource sphereGlyph + sphereGlyph SetThetaResolution 12 + sphereGlyph SetPhiResolution 6 + +vtkCaptionActor2D caption + caption SetCaption "This is the\nsouth pole" + caption SetAttachmentPoint 0 0 -0.5 + [caption GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport + [caption GetPositionCoordinate] SetReferenceCoordinate {} + [caption GetPositionCoordinate] SetValue 0.05 0.05 + caption SetWidth 0.25 + caption SetHeight 0.15 + caption ThreeDimensionalLeaderOn + caption SetLeaderGlyph [coneGlyph GetOutput] + caption SetMaximumLeaderGlyphSize 10 + caption SetLeaderGlyphSize 0.025 + [caption GetProperty] SetColor 1 0 0 + +set tprop [caption GetCaptionTextProperty] + eval $tprop SetColor [[caption GetProperty] GetColor] + $tprop SetJustificationToCentered + +vtkCaptionActor2D caption2 + caption2 SetCaption "Santa lives here" + [caption2 GetProperty] SetColor 1 0 0 + caption2 SetAttachmentPoint 0 0 0.5 + caption2 SetHeight 0.05 + caption2 BorderOff + caption2 SetPosition 25 10 + caption2 ThreeDimensionalLeaderOff + caption2 SetLeaderGlyph [coneGlyph GetOutput] + caption2 SetWidth 0.35 + caption2 SetHeight 0.10 + caption2 SetMaximumLeaderGlyphSize 10 + caption2 SetLeaderGlyphSize 0.025 + +set tprop [caption2 GetCaptionTextProperty] + eval $tprop SetColor [[caption2 GetProperty] GetColor] + +ren1 AddActor2D caption2 +ren1 AddActor2D caption +ren1 AddActor sphereActor +ren1 SetBackground 1 1 1 +[ren1 GetActiveCamera] SetFocalPoint 0 0 0 +[ren1 GetActiveCamera] SetPosition 1 0 0 +[ren1 GetActiveCamera] SetViewUp 0 0 1 +ren1 ResetCamera + +renWin SetSize 250 250 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Hybrid/Testing/Tcl/TestFacetReader.tcl b/Hybrid/Testing/Tcl/TestFacetReader.tcl new file mode 100644 index 0000000..5530e4f --- /dev/null +++ b/Hybrid/Testing/Tcl/TestFacetReader.tcl @@ -0,0 +1,46 @@ +package require vtk +package require vtkinteraction +vtkRenderer ren1 + ren1 SetBackground 0 0 0 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 300 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkFacetReader facet0 + facet0 SetFileName "$VTK_DATA_ROOT/Data/clown.facet" + +vtkPolyDataMapper Mapper5 + Mapper5 SetInputConnection [facet0 GetOutputPort] + Mapper5 SetImmediateModeRendering 1 + Mapper5 UseLookupTableScalarRangeOff + Mapper5 SetScalarVisibility 1 + Mapper5 SetScalarModeToDefault +vtkLODActor Actor5 + Actor5 SetMapper Mapper5 + [Actor5 GetProperty] SetRepresentationToSurface + [Actor5 GetProperty] SetInterpolationToGouraud + [Actor5 GetProperty] SetAmbient 0.15 + [Actor5 GetProperty] SetDiffuse 0.85 + [Actor5 GetProperty] SetSpecular 0.1 + [Actor5 GetProperty] SetSpecularPower 100 + [Actor5 GetProperty] SetSpecularColor 1 1 1 + [Actor5 GetProperty] SetColor 1 1 1 + Actor5 SetNumberOfCloudPoints 30000 + +ren1 AddActor Actor5 + +vtkCamera camera + camera SetClippingRange 3 6 + camera SetFocalPoint .1 .03 -.5 + camera SetPosition 4.4 -0.5 -.5 + camera SetViewUp 0 0 -1 +ren1 SetActiveCamera camera + +# enable user interface interactor +#iren SetUserMethod {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/TestGreedyTerrainDecimation.tcl b/Hybrid/Testing/Tcl/TestGreedyTerrainDecimation.tcl new file mode 100644 index 0000000..d6b828d --- /dev/null +++ b/Hybrid/Testing/Tcl/TestGreedyTerrainDecimation.tcl @@ -0,0 +1,69 @@ +package require vtk +package require vtkinteraction + +vtkLookupTable lut + lut SetHueRange 0.6 0 + lut SetSaturationRange 1.0 0 + lut SetValueRange 0.5 1.0 + +# Read the data: a height field results +vtkDEMReader demReader + demReader SetFileName "$VTK_DATA_ROOT/Data/SainteHelens.dem" + demReader Update + +set lo [lindex [[demReader GetOutput] GetScalarRange] 0] +set hi [lindex [[demReader GetOutput] GetScalarRange] 1] + +# Decimate the terrain +vtkGreedyTerrainDecimation deci + deci SetInputConnection [demReader GetOutputPort] + deci BoundaryVertexDeletionOn +# deci SetErrorMeasureToSpecifiedReduction +# deci SetReduction 0.95 + deci SetErrorMeasureToNumberOfTriangles + deci SetNumberOfTriangles 5000 +# deci SetErrorMeasureToAbsoluteError +# deci SetAbsoluteError 25.0 +# deci SetErrorMeasureToRelativeError +# deci SetAbsoluteError 0.01 + +vtkPolyDataNormals normals + normals SetInputConnection [deci GetOutputPort] + normals SetFeatureAngle 60 + normals ConsistencyOn + normals SplittingOff + +vtkPolyDataMapper demMapper + demMapper SetInputConnection [normals GetOutputPort] + eval demMapper SetScalarRange $lo $hi + demMapper SetLookupTable lut + +vtkLODActor actor + actor SetMapper demMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground .1 .2 .4 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren SetDesiredUpdateRate 5 + +[ren1 GetActiveCamera] SetViewUp 0 0 1 +[ren1 GetActiveCamera] SetPosition -99900 -21354 131801 +[ren1 GetActiveCamera] SetFocalPoint 41461 41461 2815 +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +renWin Render + +wm withdraw . diff --git a/Hybrid/Testing/Tcl/TestGridWarp3D.tcl b/Hybrid/Testing/Tcl/TestGridWarp3D.tcl new file mode 100644 index 0000000..bc6f1ea --- /dev/null +++ b/Hybrid/Testing/Tcl/TestGridWarp3D.tcl @@ -0,0 +1,68 @@ +package require vtk + +# Image pipeline + +vtkImageReader reader + reader ReleaseDataFlagOff + reader SetDataByteOrderToLittleEndian + reader SetDataExtent 0 63 0 63 1 93 + reader SetDataSpacing 3.2 3.2 1.5 + reader SetDataOrigin -100.8 -100.8 -69 + reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + reader SetDataMask 0x7fff + reader Update + +vtkPoints p1 +vtkPoints p2 + +p1 InsertNextPoint 0 0 0 +p2 InsertNextPoint -60 10 20 +p1 InsertNextPoint -100 -100 -50 +p2 InsertNextPoint -100 -100 -50 +p1 InsertNextPoint -100 -100 50 +p2 InsertNextPoint -100 -100 50 +p1 InsertNextPoint -100 100 -50 +p2 InsertNextPoint -100 100 -50 +p1 InsertNextPoint -100 100 50 +p2 InsertNextPoint -100 100 50 +p1 InsertNextPoint 100 -100 -50 +p2 InsertNextPoint 100 -100 -50 +p1 InsertNextPoint 100 -100 50 +p2 InsertNextPoint 100 -100 50 +p1 InsertNextPoint 100 100 -50 +p2 InsertNextPoint 100 100 -50 +p1 InsertNextPoint 100 100 50 +p2 InsertNextPoint 100 100 50 + +vtkThinPlateSplineTransform transform + transform SetSourceLandmarks p1 + transform SetTargetLandmarks p2 + transform SetBasisToR + +vtkTransformToGrid gridThinPlate + gridThinPlate SetInput transform + gridThinPlate SetGridExtent 0 64 0 64 0 50 + gridThinPlate SetGridSpacing 3.2 3.2 3.0 + gridThinPlate SetGridOrigin -102.4 -102.4 -75 + gridThinPlate SetGridScalarTypeToUnsignedChar + +vtkGridTransform gridTransform + gridTransform SetDisplacementGrid [gridThinPlate GetOutput] + gridTransform SetDisplacementShift [gridThinPlate GetDisplacementShift] + gridTransform SetDisplacementScale [gridThinPlate GetDisplacementScale] + +vtkImageReslice reslice + reslice SetInputConnection [reader GetOutputPort] + reslice SetResliceTransform gridTransform + reslice SetInterpolationModeToLinear + reslice SetOutputSpacing 1 1 1 + +vtkImageViewer viewer + viewer SetInputConnection [reslice GetOutputPort] + viewer SetZSlice 70 + viewer SetColorWindow 2000 + viewer SetColorLevel 1000 + viewer Render + + + diff --git a/Hybrid/Testing/Tcl/TestGridWarpCubic.tcl b/Hybrid/Testing/Tcl/TestGridWarpCubic.tcl new file mode 100644 index 0000000..2df9904 --- /dev/null +++ b/Hybrid/Testing/Tcl/TestGridWarpCubic.tcl @@ -0,0 +1,90 @@ +package require vtk + + +# first, create an image to warp +vtkImageGridSource imageGrid +imageGrid SetGridSpacing 16 16 0 +imageGrid SetGridOrigin 0 0 0 +imageGrid SetDataExtent 0 255 0 255 0 0 +imageGrid SetDataScalarTypeToUnsignedChar + +vtkLookupTable table +table SetTableRange 0 1 +table SetValueRange 1.0 0.0 +table SetSaturationRange 0.0 0.0 +table SetHueRange 0.0 0.0 +table SetAlphaRange 0.0 1.0 +table Build + +vtkImageMapToColors alpha +alpha SetInputConnection [imageGrid GetOutputPort] +alpha SetLookupTable table + +vtkBMPReader reader1 +reader1 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +vtkImageBlend blend +blend AddInput [reader1 GetOutput] +blend AddInput [alpha GetOutput] + +# next, create a ThinPlateSpline transform + +vtkPoints p1 +p1 SetNumberOfPoints 8 +p1 SetPoint 0 0 0 0 +p1 SetPoint 1 0 255 0 +p1 SetPoint 2 255 0 0 +p1 SetPoint 3 255 255 0 +p1 SetPoint 4 96 96 0 +p1 SetPoint 5 96 159 0 +p1 SetPoint 6 159 159 0 +p1 SetPoint 7 159 96 0 + +vtkPoints p2 +p2 SetNumberOfPoints 8 +p2 SetPoint 0 0 0 0 +p2 SetPoint 1 0 255 0 +p2 SetPoint 2 255 0 0 +p2 SetPoint 3 255 255 0 +p2 SetPoint 4 96 159 0 +p2 SetPoint 5 159 159 0 +p2 SetPoint 6 159 96 0 +p2 SetPoint 7 96 96 0 + +vtkThinPlateSplineTransform thinPlate + thinPlate SetSourceLandmarks p2 + thinPlate SetTargetLandmarks p1 + thinPlate SetBasisToR2LogR + +# convert the thin plate spline into a grid + +vtkTransformToGrid transformToGrid + transformToGrid SetInput thinPlate + transformToGrid SetGridSpacing 16 16 1 + transformToGrid SetGridOrigin -0.5 -0.5 0 + transformToGrid SetGridExtent 0 16 0 16 0 0 + +vtkGridTransform transform + transform SetDisplacementGrid [transformToGrid GetOutput] + transform SetInterpolationModeToCubic +# you must invert the transform before passing it to vtkImageReslice + transform Inverse + +# apply the grid warp to the image + +vtkImageReslice reslice + reslice SetInputConnection [blend GetOutputPort] + reslice SetResliceTransform transform + reslice SetInterpolationModeToLinear + +# set the window/level to 255.0/127.5 to view full range +vtkImageViewer viewer +viewer SetInputConnection [reslice GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 0 +viewer Render + + + + diff --git a/Hybrid/Testing/Tcl/TestGridWarpLinear.tcl b/Hybrid/Testing/Tcl/TestGridWarpLinear.tcl new file mode 100644 index 0000000..4193a72 --- /dev/null +++ b/Hybrid/Testing/Tcl/TestGridWarpLinear.tcl @@ -0,0 +1,89 @@ +package require vtk + +# first, create an image to warp +vtkImageGridSource imageGrid +imageGrid SetGridSpacing 16 16 0 +imageGrid SetGridOrigin 0 0 0 +imageGrid SetDataExtent 0 255 0 255 0 0 +imageGrid SetDataScalarTypeToUnsignedChar + +vtkLookupTable table +table SetTableRange 0 1 +table SetValueRange 1.0 0.0 +table SetSaturationRange 0.0 0.0 +table SetHueRange 0.0 0.0 +table SetAlphaRange 0.0 1.0 +table Build + +vtkImageMapToColors alpha +alpha SetInputConnection [imageGrid GetOutputPort] +alpha SetLookupTable table + +vtkBMPReader reader1 +reader1 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +vtkImageBlend blend +blend AddInputConnection 0 [reader1 GetOutputPort 0] +blend AddInputConnection 0 [alpha GetOutputPort 0] + +# next, create a ThinPlateSpline transform + +vtkPoints p1 +p1 SetNumberOfPoints 8 +p1 SetPoint 0 0 0 0 +p1 SetPoint 1 0 255 0 +p1 SetPoint 2 255 0 0 +p1 SetPoint 3 255 255 0 +p1 SetPoint 4 96 96 0 +p1 SetPoint 5 96 159 0 +p1 SetPoint 6 159 159 0 +p1 SetPoint 7 159 96 0 + +vtkPoints p2 +p2 SetNumberOfPoints 8 +p2 SetPoint 0 0 0 0 +p2 SetPoint 1 0 255 0 +p2 SetPoint 2 255 0 0 +p2 SetPoint 3 255 255 0 +p2 SetPoint 4 96 159 0 +p2 SetPoint 5 159 159 0 +p2 SetPoint 6 159 96 0 +p2 SetPoint 7 96 96 0 + +vtkThinPlateSplineTransform thinPlate + thinPlate SetSourceLandmarks p2 + thinPlate SetTargetLandmarks p1 + thinPlate SetBasisToR2LogR + +# convert the thin plate spline into a grid + +vtkTransformToGrid transformToGrid + transformToGrid SetInput thinPlate + transformToGrid SetGridSpacing 16 16 1 + transformToGrid SetGridOrigin -0.5 -0.5 0 + transformToGrid SetGridExtent 0 16 0 16 0 0 + +vtkGridTransform transform + transform SetDisplacementGrid [transformToGrid GetOutput] + +# apply the grid warp to the image + +vtkTransform transform2 +transform2 RotateZ 30 + +vtkImageReslice reslice + reslice SetInputConnection [blend GetOutputPort] + reslice SetResliceTransform [transform GetInverse] + reslice SetInterpolationModeToLinear + reslice SetOptimization 1 + +# set the window/level to 255.0/127.5 to view full range +vtkImageViewer viewer +viewer SetInputConnection [reslice GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 0 +viewer Render + + + diff --git a/Hybrid/Testing/Tcl/TestGridWarpNearest.tcl b/Hybrid/Testing/Tcl/TestGridWarpNearest.tcl new file mode 100644 index 0000000..41b90cc --- /dev/null +++ b/Hybrid/Testing/Tcl/TestGridWarpNearest.tcl @@ -0,0 +1,93 @@ +package require vtk + +# first, create an image to warp +vtkImageGridSource imageGrid +imageGrid SetGridSpacing 16 16 0 +imageGrid SetGridOrigin 0 0 0 +imageGrid SetDataExtent 0 255 0 255 0 0 +imageGrid SetDataScalarTypeToUnsignedChar + +vtkLookupTable table +table SetTableRange 0 1 +table SetValueRange 1.0 0.0 +table SetSaturationRange 0.0 0.0 +table SetHueRange 0.0 0.0 +table SetAlphaRange 0.0 1.0 +table Build + +vtkImageMapToColors alpha +alpha SetInputConnection [imageGrid GetOutputPort] +alpha SetLookupTable table + +vtkBMPReader reader1 +reader1 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +vtkImageBlend blend +blend AddInput [reader1 GetOutput] +blend AddInput [alpha GetOutput] + +# next, create a ThinPlateSpline transform + +vtkPoints p1 +p1 SetNumberOfPoints 8 +p1 SetPoint 0 0 0 0 +p1 SetPoint 1 0 255 0 +p1 SetPoint 2 255 0 0 +p1 SetPoint 3 255 255 0 +p1 SetPoint 4 96 96 0 +p1 SetPoint 5 96 159 0 +p1 SetPoint 6 159 159 0 +p1 SetPoint 7 159 96 0 + +vtkPoints p2 +p2 SetNumberOfPoints 8 +p2 SetPoint 0 0 0 0 +p2 SetPoint 1 0 255 0 +p2 SetPoint 2 255 0 0 +p2 SetPoint 3 255 255 0 +p2 SetPoint 4 96 159 0 +p2 SetPoint 5 159 159 0 +p2 SetPoint 6 159 96 0 +p2 SetPoint 7 96 96 0 + +vtkThinPlateSplineTransform thinPlate + thinPlate SetSourceLandmarks p2 + thinPlate SetTargetLandmarks p1 + thinPlate SetBasisToR2LogR + +# convert the thin plate spline into a grid + +# for nearest neighbor interpolation, the grid should precicely +# overlay the image you want to warp + +vtkTransformToGrid transformToGrid + transformToGrid SetInput thinPlate + transformToGrid SetGridSpacing 1 1 1 + transformToGrid SetGridOrigin 0 0 0 + transformToGrid SetGridExtent 0 255 0 255 0 0 + +vtkGridTransform transform + transform SetDisplacementGrid [transformToGrid GetOutput] + transform SetInterpolationModeToNearestNeighbor + # must lower the tolerance or it won't invert + transform SetInverseTolerance 2.0 +# you must invert the transform before passing it to vtkImageReslice + transform Inverse + +# apply the grid warp to the image + +vtkImageReslice reslice + reslice SetInputConnection [blend GetOutputPort] + reslice SetResliceTransform transform + reslice SetInterpolationModeToLinear + +# set the window/level to 255.0/127.5 to view full range +vtkImageViewer viewer +viewer SetInputConnection [reslice GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 0 +viewer Render + + + diff --git a/Hybrid/Testing/Tcl/TestICPTransform.tcl b/Hybrid/Testing/Tcl/TestICPTransform.tcl new file mode 100644 index 0000000..fb8d5fd --- /dev/null +++ b/Hybrid/Testing/Tcl/TestICPTransform.tcl @@ -0,0 +1,117 @@ +package require vtk +package require vtkinteraction + +vtkRenderWindow renWin + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create objects + +array set sscale { + s2 {0.7 0.7 0.7} + s3 {0.5 0.5 0.5} +} +array set scenter { + s2 {-0.25 0.25 0.0} + s3 { 0.4 -0.3 0.0} +} +array set scolors { + s2 {0.2 0.6 0.1} + s3 {0.1 0.2 0.6} +} + +for {set sidx 1} {$sidx <= 3} {incr sidx} { + vtkSuperquadricSource s${sidx} + s${sidx} ToroidalOff + s${sidx} SetThetaResolution 20 + s${sidx} SetPhiResolution 20 + s${sidx} SetPhiRoundness [expr 0.7 + ($sidx-2)*0.4] + s${sidx} SetThetaRoundness [expr 0.85 + ($sidx-1)*0.4] + if [info exists sscale(s${sidx})] { + eval s${sidx} SetScale $sscale(s${sidx}) + } + if [info exists scenter(s${sidx})] { + eval s${sidx} SetCenter $scenter(s${sidx}) + } + s${sidx} Update +} + +# Create renderers + +for {set ridx 1} {$ridx <= 3} {incr ridx} { + + vtkRenderer ren${ridx} + ren${ridx} SetViewport [expr ($ridx-1)/3.0] 0.0 [expr ($ridx)/3.0] 1.0 + ren${ridx} SetBackground 0.7 0.8 1.0 + set cam [ren${ridx} GetActiveCamera] + $cam SetPosition 1.7 1.4 1.7 + renWin AddRenderer ren${ridx} + + # renderer 1 has all 3 objects, render i has object 1 and i (i=2, 3) + # add actors (corresponding to the objects) to each renderer + # and ICP transforms from objects i or to 1. + # object 1 has feature edges too. + + for {set sidx 1} {$sidx <= 3} {incr sidx} { + + if {$ridx == 1 || $sidx == 1 || $ridx == $sidx} { + vtkPolyDataMapper ren${ridx}s${sidx}m + ren${ridx}s${sidx}m SetInputConnection [s${sidx} GetOutputPort] + + vtkActor ren${ridx}s${sidx}a + ren${ridx}s${sidx}a SetMapper ren${ridx}s${sidx}m + + set prop [ren${ridx}s${sidx}a GetProperty] + if [info exists scolors(s${sidx})] { + eval $prop SetColor $scolors(s${sidx}) + } + + if {$sidx == 1} { + $prop SetOpacity 0.2 + + vtkFeatureEdges ren${ridx}s${sidx}fe + ren${ridx}s${sidx}fe SetInputConnection [s${sidx} GetOutputPort] + ren${ridx}s${sidx}fe BoundaryEdgesOn + ren${ridx}s${sidx}fe ColoringOff + ren${ridx}s${sidx}fe ManifoldEdgesOff + + vtkPolyDataMapper ren${ridx}s${sidx}fem + ren${ridx}s${sidx}fem SetInput \ + [ren${ridx}s${sidx}fe GetOutput] + ren${ridx}s${sidx}fem \ + SetResolveCoincidentTopologyToPolygonOffset + + vtkActor ren${ridx}s${sidx}fea + ren${ridx}s${sidx}fea SetMapper ren${ridx}s${sidx}fem + + ren${ridx} AddActor ren${ridx}s${sidx}fea + } + + ren${ridx} AddActor ren${ridx}s${sidx}a + } + + if {$ridx > 1 && $ridx == $sidx} { + vtkIterativeClosestPointTransform ren${ridx}icp${sidx} + ren${ridx}icp${sidx} SetSource [s${sidx} GetOutput] + ren${ridx}icp${sidx} SetTarget [s1 GetOutput] + ren${ridx}icp${sidx} SetCheckMeanDistance 1 + ren${ridx}icp${sidx} SetMaximumMeanDistance 0.001 + ren${ridx}icp${sidx} SetMaximumNumberOfIterations 30 + ren${ridx}icp${sidx} SetMaximumNumberOfLandmarks 50 + ren${ridx}s${sidx}a SetUserTransform ren${ridx}icp${sidx} + } + } +} + +ren3icp3 StartByMatchingCentroidsOn + +renWin SetSize 400 100 +renWin Render + +catch { + iren AddObserver UserEvent {wm deiconify .vtkInteract} +} + +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/TestImageStencilWithPolydata.tcl b/Hybrid/Testing/Tcl/TestImageStencilWithPolydata.tcl new file mode 100644 index 0000000..e6cf19d --- /dev/null +++ b/Hybrid/Testing/Tcl/TestImageStencilWithPolydata.tcl @@ -0,0 +1,45 @@ +package require vtk + +# A script to test the stencil filter with a polydata stencil. + +# Image pipeline + +vtkPNGReader reader +reader SetDataSpacing 0.8 0.8 1.5 +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkSphereSource sphere +sphere SetPhiResolution 12 +sphere SetThetaResolution 12 +sphere SetCenter 102 102 0 +sphere SetRadius 60 + +vtkTriangleFilter triangle +triangle SetInputConnection [sphere GetOutputPort] + +vtkStripper stripper +stripper SetInputConnection [triangle GetOutputPort] + +vtkPolyDataToImageStencil dataToStencil +dataToStencil SetInputConnection [stripper GetOutputPort] + +vtkImageStencil stencil +stencil SetInputConnection [reader GetOutputPort] +stencil SetStencil [dataToStencil GetOutput] +stencil ReverseStencilOn +stencil SetBackgroundValue 500 + +vtkImageViewer viewer +viewer SetInputConnection [stencil GetOutputPort] +viewer SetZSlice 0 +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 +viewer Render + + + + + + + + diff --git a/Hybrid/Testing/Tcl/TestPCA.tcl b/Hybrid/Testing/Tcl/TestPCA.tcl new file mode 100644 index 0000000..f6530cd --- /dev/null +++ b/Hybrid/Testing/Tcl/TestPCA.tcl @@ -0,0 +1,261 @@ +# This example shows how to visualise the variation in shape in a set of objects using +# vtkPCAAnalysisFilter. +# +# We make three ellipsoids by distorting and translating a sphere and then align them together +# using vtkProcrustesAlignmentFilter, and then pass the output to vtkPCAAnalysisFilter. We visualise +# the first and second modes - the major sources of variation that were in the training set. + +package require vtk +package require vtkinteraction + +vtkSphereSource sphere + sphere SetPhiResolution 36 + sphere SetThetaResolution 36 + +# make two copies of the shape and distort them a little + +vtkTransform transform1 + transform1 Translate 0.2 0.1 0.3 + transform1 Scale 1.3 1.1 0.8 + +vtkTransform transform2 + transform2 Translate 0.3 0.7 0.1 + transform2 Scale 1.0 0.1 1.8 + +vtkTransformPolyDataFilter transformer1 + transformer1 SetInputConnection [sphere GetOutputPort] + transformer1 SetTransform transform1 + +vtkTransformPolyDataFilter transformer2 + transformer2 SetInputConnection [sphere GetOutputPort] + transformer2 SetTransform transform2 + +#------------------------------------------------------------------ +# map these three shapes into the first renderer +#------------------------------------------------------------------ +vtkPolyDataMapper map1a + map1a SetInputConnection [sphere GetOutputPort] +vtkActor Actor1a + Actor1a SetMapper map1a + [Actor1a GetProperty] SetDiffuseColor 1.0000 0.3882 0.2784 + +vtkPolyDataMapper map1b + map1b SetInputConnection [transformer1 GetOutputPort] +vtkActor Actor1b + Actor1b SetMapper map1b + [Actor1b GetProperty] SetDiffuseColor 0.3882 1.0000 0.2784 + +vtkPolyDataMapper map1c + map1c SetInputConnection [transformer2 GetOutputPort] +vtkActor Actor1c + Actor1c SetMapper map1c + [Actor1c GetProperty] SetDiffuseColor 0.3882 0.2784 1.0000 + +#------------------------------------------------------------------ +# align the shapes using Procrustes (using SetModeToRigidBody) +# and map the aligned shapes into the second renderer +#------------------------------------------------------------------ +vtkProcrustesAlignmentFilter procrustes + procrustes SetNumberOfInputs 3 + procrustes SetInput 0 [sphere GetOutput] + procrustes SetInput 1 [transformer1 GetOutput] + procrustes SetInput 2 [transformer2 GetOutput] + [procrustes GetLandmarkTransform] SetModeToRigidBody + +vtkPolyDataMapper map2a + map2a SetInput [procrustes GetOutput 0] +vtkActor Actor2a + Actor2a SetMapper map2a + [Actor2a GetProperty] SetDiffuseColor 1.0000 0.3882 0.2784 + +vtkPolyDataMapper map2b + map2b SetInput [procrustes GetOutput 1] +vtkActor Actor2b + Actor2b SetMapper map2b + [Actor2b GetProperty] SetDiffuseColor 0.3882 1.0000 0.2784 + +vtkPolyDataMapper map2c + map2c SetInput [procrustes GetOutput 2] +vtkActor Actor2c + Actor2c SetMapper map2c + [Actor2c GetProperty] SetDiffuseColor 0.3882 0.2784 1.0000 + +#------------------------------------------------------------------ +# pass the output of Procrustes to vtkPCAAnalysisFilter +#------------------------------------------------------------------ +vtkPCAAnalysisFilter pca + pca SetNumberOfInputs 3 + pca SetInput 0 [procrustes GetOutput 0] + pca SetInput 1 [procrustes GetOutput 1] + pca SetInput 2 [procrustes GetOutput 2] + +pca Update +# we need to call Update because GetParameterisedShape is not +# part of the normal SetInput/GetOutput pipeline + +#------------------------------------------------------------------ +# map the first mode into the third renderer: +# -3,0,3 standard deviations on the first mode +# illustrate the extremes around the average shape +#------------------------------------------------------------------ +vtkFloatArray params + params SetNumberOfComponents 1 + params SetNumberOfTuples 1 + params SetTuple1 0 0.0 +vtkPolyData shapea + shapea DeepCopy [sphere GetOutput] +pca GetParameterisedShape params shapea +vtkPolyDataNormals normalsa + normalsa SetInput shapea +vtkPolyDataMapper map3a + map3a SetInputConnection [normalsa GetOutputPort] +vtkActor Actor3a + Actor3a SetMapper map3a + [Actor3a GetProperty] SetDiffuseColor 1 1 1 + + params SetTuple1 0 -3.0 +vtkPolyData shapeb + shapeb DeepCopy [sphere GetOutput] +pca GetParameterisedShape params shapeb +vtkPolyDataNormals normalsb + normalsb SetInput shapeb +vtkPolyDataMapper map3b + map3b SetInputConnection [normalsb GetOutputPort] +vtkActor Actor3b + Actor3b SetMapper map3b + [Actor3b GetProperty] SetDiffuseColor 1 1 1 + + params SetTuple1 0 3.0 +vtkPolyData shapec + shapec DeepCopy [sphere GetOutput] +pca GetParameterisedShape params shapec +vtkPolyDataNormals normalsc + normalsc SetInput shapec +vtkPolyDataMapper map3c + map3c SetInputConnection [normalsc GetOutputPort] +vtkActor Actor3c + Actor3c SetMapper map3c + [Actor3c GetProperty] SetDiffuseColor 1 1 1 + +#------------------------------------------------------------------ +# map the second mode into the fourth renderer: +#------------------------------------------------------------------ +vtkFloatArray params4 + params4 SetNumberOfComponents 1 + params4 SetNumberOfTuples 2 + params4 SetTuple1 0 0.0 + params4 SetTuple1 1 -3.0 +vtkPolyData shape4a + shape4a DeepCopy [sphere GetOutput] +pca GetParameterisedShape params4 shape4a +vtkPolyDataNormals normals4a + normals4a SetInput shape4a +vtkPolyDataMapper map4a + map4a SetInputConnection [normals4a GetOutputPort] +vtkActor Actor4a + Actor4a SetMapper map4a + [Actor4a GetProperty] SetDiffuseColor 1 1 1 + + params4 SetTuple1 1 0.0 +vtkPolyData shape4b + shape4b DeepCopy [sphere GetOutput] +pca GetParameterisedShape params4 shape4b +vtkPolyDataNormals normals4b + normals4b SetInput shape4b +vtkPolyDataMapper map4b + map4b SetInputConnection [normals4b GetOutputPort] +vtkActor Actor4b + Actor4b SetMapper map4b + [Actor4b GetProperty] SetDiffuseColor 1 1 1 + + params4 SetTuple1 1 3.0 +vtkPolyData shape4c + shape4c DeepCopy [sphere GetOutput] +pca GetParameterisedShape params4 shape4c +vtkPolyDataNormals normals4c + normals4c SetInput shape4c +vtkPolyDataMapper map4c + map4c SetInputConnection [normals4c GetOutputPort] +vtkActor Actor4c + Actor4c SetMapper map4c + [Actor4c GetProperty] SetDiffuseColor 1 1 1 + +#------------------------------------------------------------------ +# Create the RenderWindow and its four Renderers +#------------------------------------------------------------------ + +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderer ren3 +vtkRenderer ren4 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin AddRenderer ren3 + renWin AddRenderer ren4 + renWin SetSize 600 200 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer + +ren1 AddActor Actor1a +ren1 AddActor Actor1b +ren1 AddActor Actor1c + +ren2 AddActor Actor2a +ren2 AddActor Actor2b +ren2 AddActor Actor2c + +ren3 AddActor Actor3a +ren3 AddActor Actor3b +ren3 AddActor Actor3c + +ren4 AddActor Actor4a +ren4 AddActor Actor4b +ren4 AddActor Actor4c + +# set the properties of the renderers + +ren1 SetBackground 1 1 1 +ren1 SetViewport 0.0 0.0 0.25 1.0 +ren1 ResetCamera +[ren1 GetActiveCamera] SetPosition 1 -1 0 +ren1 ResetCamera + +ren2 SetBackground 1 1 1 +ren2 SetViewport 0.25 0.0 0.5 1.0 +ren2 ResetCamera +[ren2 GetActiveCamera] SetPosition 1 -1 0 +ren2 ResetCamera + +ren3 SetBackground 1 1 1 +ren3 SetViewport 0.5 0.0 0.75 1.0 +ren3 ResetCamera +[ren3 GetActiveCamera] SetPosition 1 -1 0 +ren3 ResetCamera + +ren4 SetBackground 1 1 1 +ren4 SetViewport 0.75 0.0 1.0 1.0 +ren4 ResetCamera +[ren4 GetActiveCamera] SetPosition 1 -1 0 +ren4 ResetCamera + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# output the image to file (used to generate the initial regression image) +#vtkWindowToImageFilter to_image +#to_image SetInput renWin +#vtkPNGWriter to_png +#to_png SetFileName "TestPCA.png" +#to_png SetInputConnection [to_image GetOutputPort] +#to_png Write + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Hybrid/Testing/Tcl/TestProcrustes.tcl b/Hybrid/Testing/Tcl/TestProcrustes.tcl new file mode 100644 index 0000000..4ea13f6 --- /dev/null +++ b/Hybrid/Testing/Tcl/TestProcrustes.tcl @@ -0,0 +1,149 @@ +package require vtk +package require vtkinteraction + +vtkSphereSource sphere + +# make two copies of the shape and distort them a little + +vtkTransform transform1 + transform1 Translate 0.2 0.1 0.3 + transform1 Scale 1.3 1.1 0.8 + +vtkTransform transform2 + transform2 Translate 0.3 0.7 0.1 + transform2 Scale 1.0 0.1 1.8 + +vtkTransformPolyDataFilter transformer1 + transformer1 SetInputConnection [sphere GetOutputPort] + transformer1 SetTransform transform1 + +vtkTransformPolyDataFilter transformer2 + transformer2 SetInputConnection [sphere GetOutputPort] + transformer2 SetTransform transform2 + +# map these three shapes into the first renderer +vtkPolyDataMapper map1a + map1a SetInputConnection [sphere GetOutputPort] +vtkActor Actor1a + Actor1a SetMapper map1a + [Actor1a GetProperty] SetDiffuseColor 1.0000 0.3882 0.2784 + +vtkPolyDataMapper map1b + map1b SetInputConnection [transformer1 GetOutputPort] +vtkActor Actor1b + Actor1b SetMapper map1b + [Actor1b GetProperty] SetDiffuseColor 0.3882 1.0000 0.2784 + +vtkPolyDataMapper map1c + map1c SetInputConnection [transformer2 GetOutputPort] +vtkActor Actor1c + Actor1c SetMapper map1c + [Actor1c GetProperty] SetDiffuseColor 0.3882 0.2784 1.0000 + +# -- align the shapes using Procrustes (using SetModeToRigidBody) -- +vtkProcrustesAlignmentFilter procrustes1 + procrustes1 SetNumberOfInputs 3 + procrustes1 SetInput 0 [sphere GetOutput] + procrustes1 SetInput 1 [transformer1 GetOutput] + procrustes1 SetInput 2 [transformer2 GetOutput] + [procrustes1 GetLandmarkTransform] SetModeToRigidBody + +# map the aligned shapes into the second renderer +vtkPolyDataMapper map2a + map2a SetInput [procrustes1 GetOutput 0] +vtkActor Actor2a + Actor2a SetMapper map2a + [Actor2a GetProperty] SetDiffuseColor 1.0000 0.3882 0.2784 + +vtkPolyDataMapper map2b + map2b SetInput [procrustes1 GetOutput 1] +vtkActor Actor2b + Actor2b SetMapper map2b + [Actor2b GetProperty] SetDiffuseColor 0.3882 1.0000 0.2784 + +vtkPolyDataMapper map2c + map2c SetInput [procrustes1 GetOutput 2] +vtkActor Actor2c + Actor2c SetMapper map2c + [Actor2c GetProperty] SetDiffuseColor 0.3882 0.2784 1.0000 + +# -- align the shapes using Procrustes (using SetModeToSimilarity (default)) -- +vtkProcrustesAlignmentFilter procrustes2 + procrustes2 SetNumberOfInputs 3 + procrustes2 SetInput 0 [sphere GetOutput] + procrustes2 SetInput 1 [transformer1 GetOutput] + procrustes2 SetInput 2 [transformer2 GetOutput] + +# map the aligned shapes into the third renderer +vtkPolyDataMapper map3a + map3a SetInput [procrustes2 GetOutput 0] +vtkActor Actor3a + Actor3a SetMapper map3a + [Actor3a GetProperty] SetDiffuseColor 1.0000 0.3882 0.2784 + +vtkPolyDataMapper map3b + map3b SetInput [procrustes2 GetOutput 1] +vtkActor Actor3b + Actor3b SetMapper map3b + [Actor3b GetProperty] SetDiffuseColor 0.3882 1.0000 0.2784 + +vtkPolyDataMapper map3c + map3c SetInput [procrustes2 GetOutput 2] +vtkActor Actor3c + Actor3c SetMapper map3c + [Actor3c GetProperty] SetDiffuseColor 0.3882 0.2784 1.0000 + +# Create the RenderWindow and its three Renderers + +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderer ren3 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin AddRenderer ren3 + renWin SetSize 300 100 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer + +ren1 AddActor Actor1a +ren1 AddActor Actor1b +ren1 AddActor Actor1c + +ren2 AddActor Actor2a +ren2 AddActor Actor2b +ren2 AddActor Actor2c + +ren3 AddActor Actor3a +ren3 AddActor Actor3b +ren3 AddActor Actor3c + +# set the properties of the renderers + +ren1 SetBackground 1 1 1 +ren1 SetViewport 0.0 0.0 0.33 1.0 +ren1 ResetCamera +[ren1 GetActiveCamera] SetPosition 1 -1 0 +ren1 ResetCamera + +ren2 SetBackground 1 1 1 +ren2 SetViewport 0.33 0.0 0.66 1.0 +ren2 ResetCamera +[ren2 GetActiveCamera] SetPosition 1 -1 0 +ren2 ResetCamera + +ren3 SetBackground 1 1 1 +ren3 SetViewport 0.66 0.0 1.0 1.0 +ren3 ResetCamera +[ren3 GetActiveCamera] SetPosition 1 -1 0 +ren3 ResetCamera + +renWin Render + +catch { + iren AddObserver UserEvent {wm deiconify .vtkInteract} +} + +wm withdraw . \ No newline at end of file diff --git a/Hybrid/Testing/Tcl/TestProjectedTerrainPath.tcl b/Hybrid/Testing/Tcl/TestProjectedTerrainPath.tcl new file mode 100644 index 0000000..1384749 --- /dev/null +++ b/Hybrid/Testing/Tcl/TestProjectedTerrainPath.tcl @@ -0,0 +1,106 @@ +package require vtk +package require vtkinteraction + +vtkLookupTable lut + lut SetHueRange 0.6 0 + lut SetSaturationRange 1.0 0 + lut SetValueRange 0.5 1.0 + +# Read the data: a height field results +vtkDEMReader demReader + demReader SetFileName "$VTK_DATA_ROOT/Data/SainteHelens.dem" + demReader Update + +set lo [lindex [[demReader GetOutput] GetScalarRange] 0] +set hi [lindex [[demReader GetOutput] GetScalarRange] 1] + +vtkImageDataGeometryFilter surface + surface SetInputConnection [demReader GetOutputPort] + +vtkWarpScalar warp + warp SetInputConnection [surface GetOutputPort] + warp SetScaleFactor 1 + warp UseNormalOn + warp SetNormal 0 0 1 + +vtkPolyDataNormals normals + normals SetInput [warp GetPolyDataOutput] + normals SetFeatureAngle 60 + normals SplittingOff + +vtkPolyDataMapper demMapper + demMapper SetInputConnection [normals GetOutputPort] + eval demMapper SetScalarRange $lo $hi + demMapper SetLookupTable lut + +vtkLODActor demActor + demActor SetMapper demMapper + +# Create some paths +vtkPoints pts + pts InsertNextPoint 562669 5.1198e+006 1992.77 + pts InsertNextPoint 562801 5.11618e+006 2534.97 + pts InsertNextPoint 562913 5.11157e+006 1911.1 + pts InsertNextPoint 559849 5.11083e+006 1681.34 + pts InsertNextPoint 562471 5.11633e+006 2593.57 + pts InsertNextPoint 563223 5.11616e+006 2598.31 + pts InsertNextPoint 566579 5.11127e+006 1697.83 + pts InsertNextPoint 569000 5.11127e+006 1697.83 +vtkCellArray lines + lines InsertNextCell 3 + lines InsertCellPoint 0 + lines InsertCellPoint 1 + lines InsertCellPoint 2 + lines InsertNextCell 5 + lines InsertCellPoint 3 + lines InsertCellPoint 4 + lines InsertCellPoint 5 + lines InsertCellPoint 6 + lines InsertCellPoint 7 + +vtkPolyData terrainPaths + terrainPaths SetPoints pts + terrainPaths SetLines lines + +vtkProjectedTerrainPath projectedPaths + projectedPaths SetInput terrainPaths + projectedPaths SetSource [demReader GetOutput] + projectedPaths SetHeightOffset 25 + projectedPaths SetHeightTolerance 5 + projectedPaths SetProjectionModeToNonOccluded + projectedPaths SetProjectionModeToHug + +vtkPolyDataMapper pathMapper + pathMapper SetInputConnection [projectedPaths GetOutputPort] + +vtkActor paths + paths SetMapper pathMapper + [paths GetProperty] SetColor 1 0 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor demActor +ren1 AddActor paths +ren1 SetBackground .1 .2 .4 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren SetDesiredUpdateRate 5 + +[ren1 GetActiveCamera] SetViewUp 0 0 1 +[ren1 GetActiveCamera] SetPosition -99900 -21354 131801 +[ren1 GetActiveCamera] SetFocalPoint 41461 41461 2815 +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +renWin Render + +wm withdraw . diff --git a/Hybrid/Testing/Tcl/TestThinPlateWarp.tcl b/Hybrid/Testing/Tcl/TestThinPlateWarp.tcl new file mode 100644 index 0000000..5d3165d --- /dev/null +++ b/Hybrid/Testing/Tcl/TestThinPlateWarp.tcl @@ -0,0 +1,77 @@ +package require vtk + +# warp an image with a thin plate spline + +# first, create an image to warp +vtkImageGridSource imageGrid +imageGrid SetGridSpacing 16 16 0 +imageGrid SetGridOrigin 0 0 0 +imageGrid SetDataExtent 0 255 0 255 0 0 +imageGrid SetDataScalarTypeToUnsignedChar + +vtkLookupTable table +table SetTableRange 0 1 +table SetValueRange 1.0 0.0 +table SetSaturationRange 0.0 0.0 +table SetHueRange 0.0 0.0 +table SetAlphaRange 0.0 1.0 +table Build + +vtkImageMapToColors alpha +alpha SetInputConnection [imageGrid GetOutputPort] +alpha SetLookupTable table + +vtkBMPReader reader1 +reader1 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +vtkImageBlend blend +blend AddInput 0 [reader1 GetOutput] +blend AddInput 0 [alpha GetOutput] + +# next, create a ThinPlateSpline transform + +vtkPoints p1 +p1 SetNumberOfPoints 8 +p1 SetPoint 0 0 0 0 +p1 SetPoint 1 0 255 0 +p1 SetPoint 2 255 0 0 +p1 SetPoint 3 255 255 0 +p1 SetPoint 4 96 96 0 +p1 SetPoint 5 96 159 0 +p1 SetPoint 6 159 159 0 +p1 SetPoint 7 159 96 0 + +vtkPoints p2 +p2 SetNumberOfPoints 8 +p2 SetPoint 0 0 0 0 +p2 SetPoint 1 0 255 0 +p2 SetPoint 2 255 0 0 +p2 SetPoint 3 255 255 0 +p2 SetPoint 4 96 159 0 +p2 SetPoint 5 159 159 0 +p2 SetPoint 6 159 96 0 +p2 SetPoint 7 96 96 0 + +vtkThinPlateSplineTransform transform + transform SetSourceLandmarks p2 + transform SetTargetLandmarks p1 + transform SetBasisToR2LogR +# you must invert the transform before passing it to vtkImageReslice + transform Inverse + +vtkImageReslice reslice + reslice SetInputConnection [blend GetOutputPort] + reslice SetResliceTransform transform + reslice SetInterpolationModeToLinear + +# set the window/level to 255.0/127.5 to view full range +vtkImageViewer viewer +viewer SetInputConnection [reslice GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 0 +viewer Render + + + + diff --git a/Hybrid/Testing/Tcl/TestThinPlateWarp3D.tcl b/Hybrid/Testing/Tcl/TestThinPlateWarp3D.tcl new file mode 100644 index 0000000..9be0509 --- /dev/null +++ b/Hybrid/Testing/Tcl/TestThinPlateWarp3D.tcl @@ -0,0 +1,61 @@ +package require vtk + + +# Image pipeline + +vtkImageReader reader + reader ReleaseDataFlagOff + reader SetDataByteOrderToLittleEndian + reader SetDataExtent 0 63 0 63 1 93 + reader SetDataSpacing 3.2 3.2 1.5 + reader SetDataOrigin -100.8 -100.8 -69 + reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + reader SetDataMask 0x7fff + reader Update + +vtkPoints p1 +vtkPoints p2 + +p1 InsertNextPoint 0 0 0 +p2 InsertNextPoint -60 10 20 +p1 InsertNextPoint -100 -100 -50 +p2 InsertNextPoint -100 -100 -50 +p1 InsertNextPoint -100 -100 50 +p2 InsertNextPoint -100 -100 50 +p1 InsertNextPoint -100 100 -50 +p2 InsertNextPoint -100 100 -50 +p1 InsertNextPoint -100 100 50 +p2 InsertNextPoint -100 100 50 +p1 InsertNextPoint 100 -100 -50 +p2 InsertNextPoint 100 -100 -50 +p1 InsertNextPoint 100 -100 50 +p2 InsertNextPoint 100 -100 50 +p1 InsertNextPoint 100 100 -50 +p2 InsertNextPoint 100 100 -50 +p1 InsertNextPoint 100 100 50 +p2 InsertNextPoint 100 100 50 + +vtkThinPlateSplineTransform transform + transform SetSourceLandmarks p1 + transform SetTargetLandmarks p2 + transform SetBasisToR + +vtkImageReslice reslice + reslice SetInputConnection [reader GetOutputPort] + reslice SetResliceTransform transform + reslice SetInterpolationModeToLinear + reslice SetOutputSpacing 1 1 1 + +vtkImageCacheFilter cac + cac SetInputConnection [reslice GetOutputPort] + cac SetCacheSize 1000 + +cac SetInputConnection [reslice GetOutputPort] + +vtkImageViewer viewer + viewer SetInputConnection [cac GetOutputPort] + viewer SetZSlice 90 + viewer SetColorWindow 2000 + viewer SetColorLevel 1000 + viewer Render + diff --git a/Hybrid/Testing/Tcl/VRMLImporter.tcl b/Hybrid/Testing/Tcl/VRMLImporter.tcl new file mode 100644 index 0000000..af7f28c --- /dev/null +++ b/Hybrid/Testing/Tcl/VRMLImporter.tcl @@ -0,0 +1,44 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + +vtkVRMLImporter importer + importer SetRenderWindow renWin + importer SetFileName "$VTK_DATA_ROOT/Data/bot2.wrl" + importer Read + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[importer GetRenderer] SetBackground 0.1 0.2 0.4 +[importer GetRenderWindow] SetSize 300 300 + +# +# the importer created the renderer +set renCollection [renWin GetRenderers] +$renCollection InitTraversal +set ren [$renCollection GetNextItem] + +# +# change view up to +z +# +[$ren GetActiveCamera] SetPosition -3.25303 3.46205 3.15906 +[$ren GetActiveCamera] SetFocalPoint 0 0 0 +[$ren GetActiveCamera] SetViewUp 0.564063 0.825024 -0.0341876 + +# +# let the renderer compute good position and focal point +# +$ren ResetCamera +[$ren GetActiveCamera] Dolly 1.75 +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/WarpPolyData.tcl b/Hybrid/Testing/Tcl/WarpPolyData.tcl new file mode 100644 index 0000000..0ab1d45 --- /dev/null +++ b/Hybrid/Testing/Tcl/WarpPolyData.tcl @@ -0,0 +1,249 @@ +package require vtk + +# this example tests the warping of PolyData using thin plate splines +# and with grid transforms using different interpolation modes + +# create a rendering window +vtkRenderWindow renWin +renWin SetSize 600 300 + +vtkSphereSource sphere + sphere SetThetaResolution 20 + sphere SetPhiResolution 20 + +vtkPolyDataNormals ap + ap SetInputConnection [sphere GetOutputPort] + +#--------------------------- +# thin plate spline transform +vtkPoints spoints + spoints SetNumberOfPoints 10 + spoints SetPoint 0 0.000 0.000 0.500 + spoints SetPoint 1 0.000 0.000 -0.500 + spoints SetPoint 2 0.433 0.000 0.250 + spoints SetPoint 3 0.433 0.000 -0.250 + spoints SetPoint 4 -0.000 0.433 0.250 + spoints SetPoint 5 -0.000 0.433 -0.250 + spoints SetPoint 6 -0.433 -0.000 0.250 + spoints SetPoint 7 -0.433 -0.000 -0.250 + spoints SetPoint 8 0.000 -0.433 0.250 + spoints SetPoint 9 0.000 -0.433 -0.250 + +vtkPoints tpoints + tpoints SetNumberOfPoints 10 + tpoints SetPoint 0 0.000 0.000 0.800 + tpoints SetPoint 1 0.000 0.000 -0.200 + tpoints SetPoint 2 0.433 0.000 0.350 + tpoints SetPoint 3 0.433 0.000 -0.150 + tpoints SetPoint 4 -0.000 0.233 0.350 + tpoints SetPoint 5 -0.000 0.433 -0.150 + tpoints SetPoint 6 -0.433 -0.000 0.350 + tpoints SetPoint 7 -0.433 -0.000 -0.150 + tpoints SetPoint 8 0.000 -0.233 0.350 + tpoints SetPoint 9 0.000 -0.433 -0.150 + +vtkThinPlateSplineTransform thin + thin SetSourceLandmarks spoints + thin SetTargetLandmarks tpoints + thin SetBasisToR2LogR +# thin Inverse + +vtkGeneralTransform t1 + t1 SetInput thin + +vtkTransformPolyDataFilter f11 +f11 SetInputConnection [ap GetOutputPort] +f11 SetTransform t1 + +vtkDataSetMapper m11 +m11 SetInputConnection [f11 GetOutputPort] + +vtkActor a11 +a11 SetMapper m11 +a11 RotateY 90 +[a11 GetProperty] SetColor 1 0 0 +#[a11 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren11 +ren11 SetViewport 0.0 0.5 0.25 1.0 +ren11 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren11 AddActor a11 +renWin AddRenderer ren11 + +# inverse thin plate spline transform +vtkTransformPolyDataFilter f12 +f12 SetInputConnection [ap GetOutputPort] +f12 SetTransform [t1 GetInverse] + +vtkDataSetMapper m12 +m12 SetInputConnection [f12 GetOutputPort] + +vtkActor a12 +a12 SetMapper m12 +a12 RotateY 90 +[a12 GetProperty] SetColor 0.9 0.9 0 +#[a12 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren12 +ren12 SetViewport 0.0 0.0 0.25 0.5 +ren12 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren12 AddActor a12 +renWin AddRenderer ren12 + + +#-------------------------- +# grid transform, cubic interpolation +vtkTransformToGrid gridTrans +gridTrans SetInput t1 +gridTrans SetGridOrigin -1.5 -1.5 -1.5 +gridTrans SetGridExtent 0 60 0 60 0 60 +gridTrans SetGridSpacing 0.05 0.05 0.05 + +vtkGridTransform t2 +t2 SetDisplacementGrid [gridTrans GetOutput] +t2 SetInterpolationModeToCubic + +vtkTransformPolyDataFilter f21 +f21 SetInputConnection [ap GetOutputPort] +f21 SetTransform t2 + +vtkDataSetMapper m21 +m21 SetInputConnection [f21 GetOutputPort] + +vtkActor a21 +a21 SetMapper m21 +a21 RotateY 90 +[a21 GetProperty] SetColor 1 0 0 +#[a21 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren21 +ren21 SetViewport 0.25 0.5 0.50 1.0 +ren21 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren21 AddActor a21 +renWin AddRenderer ren21 + +# inverse +vtkTransformPolyDataFilter f22 +f22 SetInputConnection [ap GetOutputPort] +f22 SetTransform [t2 GetInverse] + +vtkDataSetMapper m22 +m22 SetInputConnection [f22 GetOutputPort] + +vtkActor a22 +a22 SetMapper m22 +a22 RotateY 90 +[a22 GetProperty] SetColor 0.9 0.9 0 +#[a22 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren22 +ren22 SetViewport 0.25 0.0 0.50 0.5 +ren22 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren22 AddActor a22 +renWin AddRenderer ren22 + + +#-------------------------- +# grid transform, linear +vtkGridTransform t3 +t3 SetDisplacementGrid [gridTrans GetOutput] +t3 SetInterpolationModeToLinear + +vtkTransformPolyDataFilter f31 +f31 SetInputConnection [ap GetOutputPort] +f31 SetTransform t3 + +vtkDataSetMapper m31 +m31 SetInputConnection [f31 GetOutputPort] + +vtkActor a31 +a31 SetMapper m31 +a31 RotateY 90 +[a31 GetProperty] SetColor 1 0 0 +#[a31 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren31 +ren31 SetViewport 0.50 0.5 0.75 1.0 +ren31 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren31 AddActor a31 +renWin AddRenderer ren31 + +# inverse +vtkTransformPolyDataFilter f32 +f32 SetInputConnection [ap GetOutputPort] +f32 SetTransform [t3 GetInverse] + +vtkDataSetMapper m32 +m32 SetInputConnection [f32 GetOutputPort] + +vtkActor a32 +a32 SetMapper m32 +a32 RotateY 90 +[a32 GetProperty] SetColor 0.9 0.9 0 +#[a32 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren32 +ren32 SetViewport 0.5 0.0 0.75 0.5 +ren32 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren32 AddActor a32 +renWin AddRenderer ren32 + + +#-------------------------- +# grid transform, nearest +vtkGridTransform t4 +t4 SetDisplacementGrid [gridTrans GetOutput] +t4 SetInterpolationModeToNearestNeighbor +t4 SetInverseTolerance 0.05 + +vtkTransformPolyDataFilter f41 +f41 SetInputConnection [ap GetOutputPort] +f41 SetTransform t4 + +vtkDataSetMapper m41 +m41 SetInputConnection [f41 GetOutputPort] + +vtkActor a41 +a41 SetMapper m41 +a41 RotateY 90 +[a41 GetProperty] SetColor 1 0 0 +#[a41 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren41 +ren41 SetViewport 0.75 0.5 1.0 1.0 +ren41 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren41 AddActor a41 +renWin AddRenderer ren41 + +#inverse +vtkTransformPolyDataFilter f42 +f42 SetInputConnection [ap GetOutputPort] +f42 SetTransform [t4 GetInverse] + +vtkDataSetMapper m42 +m42 SetInputConnection [f42 GetOutputPort] + +vtkActor a42 +a42 SetMapper m42 +a42 RotateY 90 +[a42 GetProperty] SetColor 0.9 0.9 0 +#[a42 GetProperty] SetRepresentationToWireframe + +vtkRenderer ren42 +ren42 SetViewport 0.75 0.0 1.0 0.5 +ren42 ResetCamera -0.5 0.5 -0.5 0.5 -1 1 +ren42 AddActor a42 +renWin AddRenderer ren42 + +t1 RotateX -100 +t1 PostMultiply +t1 RotateX +100 + +renWin Render + + + + + + + diff --git a/Hybrid/Testing/Tcl/appendImplicitModel.tcl b/Hybrid/Testing/Tcl/appendImplicitModel.tcl new file mode 100644 index 0000000..89377c1 --- /dev/null +++ b/Hybrid/Testing/Tcl/appendImplicitModel.tcl @@ -0,0 +1,88 @@ +package require vtk +package require vtkinteraction + +# this demonstrates appending data to generate an implicit model + +vtkLineSource lineX + lineX SetPoint1 -2.0 0.0 0.0 + lineX SetPoint2 2.0 0.0 0.0 + lineX Update +vtkLineSource lineY + lineY SetPoint1 0.0 -2.0 0.0 + lineY SetPoint2 0.0 2.0 0.0 + lineY Update +vtkLineSource lineZ + lineZ SetPoint1 0.0 0.0 -2.0 + lineZ SetPoint2 0.0 0.0 2.0 + lineZ Update +vtkPlaneSource aPlane + aPlane Update + +# set Data(0) "lineX" +# set Data(1) "lineY" +# set Data(2) "lineZ" +# set Data(3) "aPlane" + +vtkImplicitModeller imp + imp SetModelBounds -2.5 2.5 -2.5 2.5 -2.5 2.5 + imp SetSampleDimensions 60 60 60 + imp SetCapValue 1000 + imp SetProcessModeToPerVoxel + +# Okay now let's see if we can append +imp StartAppend +# for {set i 0} {$i < 4} {incr i} { +# imp Append [$Data($i) GetOutput] +# } +imp Append [lineX GetOutput] +imp Append [lineY GetOutput] +imp Append [lineZ GetOutput] +imp Append [aPlane GetOutput] +imp EndAppend + + +vtkContourFilter cf +cf SetInputConnection [imp GetOutputPort] + cf SetValue 0 0.1 +vtkPolyDataMapper mapper + mapper SetInputConnection [cf GetOutputPort] +vtkActor actor + actor SetMapper mapper + +vtkOutlineFilter outline + outline SetInputConnection [imp GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +vtkImageDataGeometryFilter plane + plane SetInputConnection [imp GetOutputPort] + plane SetExtent 0 60 0 60 30 30 +vtkPolyDataMapper planeMapper + planeMapper SetInputConnection [plane GetOutputPort] + planeMapper SetScalarRange 0.197813 0.710419 +vtkActor planeActor + planeActor SetMapper planeMapper + +# graphics stuff +vtkRenderer ren1 + ren1 AddActor actor + ren1 AddActor planeActor + ren1 AddActor outlineActor +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.1 0.2 0.4 +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +ren1 ResetCameraClippingRange +renWin Render + +wm withdraw . diff --git a/Hybrid/Testing/Tcl/appendImplicitModelNoBounds.tcl b/Hybrid/Testing/Tcl/appendImplicitModelNoBounds.tcl new file mode 100644 index 0000000..e3c7d35 --- /dev/null +++ b/Hybrid/Testing/Tcl/appendImplicitModelNoBounds.tcl @@ -0,0 +1,95 @@ +package require vtk +package require vtkinteraction + +# this demonstrates appending data to generate an implicit model +# contrast this with appendImplicitModel.tcl which set the bounds +# explicitly. this scrip should produce the same results. + + +vtkCubeSource cubeForBounds + cubeForBounds SetBounds -2.5 2.5 -2.5 2.5 -2.5 2.5 + cubeForBounds Update + +vtkLineSource lineX + lineX SetPoint1 -2.0 0.0 0.0 + lineX SetPoint2 2.0 0.0 0.0 + lineX Update +vtkLineSource lineY + lineY SetPoint1 0.0 -2.0 0.0 + lineY SetPoint2 0.0 2.0 0.0 + lineY Update +vtkLineSource lineZ + lineZ SetPoint1 0.0 0.0 -2.0 + lineZ SetPoint2 0.0 0.0 2.0 + lineZ Update +vtkPlaneSource aPlane + aPlane Update + +# set Data(3) "lineX" +# set Data(1) "lineY" +# set Data(2) "lineZ" +# set Data(0) "aPlane" + +vtkImplicitModeller imp + imp SetSampleDimensions 60 60 60 + imp SetCapValue 1000 + imp ComputeModelBounds [cubeForBounds GetOutput] + +# Okay now let's see if we can append +imp StartAppend +# for {set i 0} {$i < 4} {incr i} { +# imp Append [$Data($i) GetOutput] +# } +imp Append [aPlane GetOutput] +imp Append [lineZ GetOutput] +imp Append [lineY GetOutput] +imp Append [lineX GetOutput] +imp EndAppend + + +vtkContourFilter cf +cf SetInputConnection [imp GetOutputPort] + cf SetValue 0 0.1 +vtkPolyDataMapper mapper + mapper SetInputConnection [cf GetOutputPort] +vtkActor actor + actor SetMapper mapper + +vtkOutlineFilter outline + outline SetInputConnection [imp GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +vtkImageDataGeometryFilter plane + plane SetInputConnection [imp GetOutputPort] + plane SetExtent 0 60 0 60 30 30 +vtkPolyDataMapper planeMapper + planeMapper SetInputConnection [plane GetOutputPort] + planeMapper SetScalarRange 0.197813 0.710419 +vtkActor planeActor + planeActor SetMapper planeMapper + +# graphics stuff +vtkRenderer ren1 + ren1 AddActor actor + ren1 AddActor planeActor + ren1 AddActor outlineActor +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.1 0.2 0.4 +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 30 +ren1 ResetCameraClippingRange +renWin Render + + +wm withdraw . diff --git a/Hybrid/Testing/Tcl/banana.tcl b/Hybrid/Testing/Tcl/banana.tcl new file mode 100644 index 0000000..91f0be7 --- /dev/null +++ b/Hybrid/Testing/Tcl/banana.tcl @@ -0,0 +1,110 @@ +package require vtk +package require vtkinteraction + + +# use a sphere as a basis of the shape +vtkSphereSource sphere +sphere SetPhiResolution 40 +sphere SetThetaResolution 40 +sphere Update + +set sphereData [sphere GetOutput] + +# create a data array to hold the weighting coefficients +vtkFloatArray tfarray +set npoints [$sphereData GetNumberOfPoints] +tfarray SetNumberOfComponents 2 +tfarray SetNumberOfTuples $npoints + +# parameterize the sphere along the z axis, and fill the weights +# with (1.0-a, a) to linearly interpolate across the shape +for {set i 0} {$i < $npoints} {incr i} { + set pt [$sphereData GetPoint $i] + set x [lindex $pt 0] + set y [lindex $pt 1] + set z [lindex $pt 2] +#foreach {x y z} $pt {} + + # -0.5 < z < 0.5 + set zn [expr $z + 0.5] + set zn1 [expr 1.0 - $zn] + if {$zn > 1.0} {set zn 1.0} + if {$zn1 < 0.0} {set zn1 0.0} + + tfarray SetComponent $i 0 $zn1 + tfarray SetComponent $i 1 $zn +} + +# create field data to hold the array, and bind it to the sphere +vtkFieldData fd +tfarray SetName "weights" +[$sphereData GetPointData] AddArray tfarray + +# use an ordinary transform to stretch the shape +vtkTransform stretch +stretch Scale 1 1 3.2 + +vtkTransformFilter stretchFilter +stretchFilter SetInput $sphereData +stretchFilter SetTransform stretch + +# now, for the weighted transform stuff +vtkWeightedTransformFilter weightedTrans + +# create two transforms to interpolate between +vtkTransform identity +identity Identity + +vtkTransform rotated +set rotatedAngle 45 +rotated RotateX $rotatedAngle + +weightedTrans SetNumberOfTransforms 2 +weightedTrans SetTransform identity 0 +weightedTrans SetTransform rotated 1 +# which data array should the filter use ? +weightedTrans SetWeightArray "weights" + +weightedTrans SetInputConnection [stretchFilter GetOutputPort] + +vtkPolyDataMapper weightedTransMapper + weightedTransMapper SetInputConnection [weightedTrans GetOutputPort] +vtkActor weightedTransActor + weightedTransActor SetMapper weightedTransMapper + [weightedTransActor GetProperty] SetDiffuseColor 0.8 0.8 0.1 + [weightedTransActor GetProperty] SetRepresentationToSurface + + +# create simple poly data so we can apply glyph + +# +# Create the rendering stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor weightedTransActor +ren1 SetBackground 0.1 0.2 0.5 +renWin SetSize 300 300 + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 90 +[ren1 GetActiveCamera] Dolly 1 +# Get handles to some useful objects +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop + +proc cmd {s} { + rotated Identity + rotated RotateX $s + renWin Render +} +cmd $rotatedAngle + +wm withdraw . diff --git a/Hybrid/Testing/Tcl/bore.tcl b/Hybrid/Testing/Tcl/bore.tcl new file mode 100644 index 0000000..64a8664 --- /dev/null +++ b/Hybrid/Testing/Tcl/bore.tcl @@ -0,0 +1,105 @@ +package require vtk +package require vtkinteraction + + +# Create arc plots + +# get the interactor ui + +vtkCamera camera + +# read the bore +vtkPolyDataReader bore + bore SetFileName "$VTK_DATA_ROOT/Data/bore.vtk" +vtkTubeFilter tuber + tuber SetInputConnection [bore GetOutputPort] + tuber SetNumberOfSides 6 + tuber SetRadius 15 +vtkPolyDataMapper mapBore + mapBore SetInputConnection [tuber GetOutputPort] + mapBore ScalarVisibilityOff +vtkActor boreActor + boreActor SetMapper mapBore + [boreActor GetProperty] SetColor 0 0 0 + +# create the arc plots +# +vtkPolyDataReader track1 + track1 SetFileName "$VTK_DATA_ROOT/Data/track1.binary.vtk" +vtkArcPlotter ap + ap SetInputConnection [track1 GetOutputPort] + ap SetCamera camera + ap SetRadius 250.0 + ap SetHeight 200.0 + ap UseDefaultNormalOn + ap SetDefaultNormal 1 1 0 +vtkPolyDataMapper mapArc + mapArc SetInputConnection [ap GetOutputPort] +vtkActor arcActor + arcActor SetMapper mapArc + [arcActor GetProperty] SetColor 0 1 0 + +vtkPolyDataReader track2 + track2 SetFileName "$VTK_DATA_ROOT/Data/track2.binary.vtk" +vtkArcPlotter ap2 + ap2 SetInputConnection [track2 GetOutputPort] + ap2 SetCamera camera + ap2 SetRadius 450.0 + ap2 SetHeight 200.0 + ap2 UseDefaultNormalOn + ap2 SetDefaultNormal 1 1 0 +vtkPolyDataMapper mapArc2 + mapArc2 SetInputConnection [ap2 GetOutputPort] +vtkActor arcActor2 + arcActor2 SetMapper mapArc2 + [arcActor2 GetProperty] SetColor 0 0 1 + +vtkPolyDataReader track3 + track3 SetFileName "$VTK_DATA_ROOT/Data/track3.binary.vtk" +vtkArcPlotter ap3 + ap3 SetInputConnection [track3 GetOutputPort] + ap3 SetCamera camera + ap3 SetRadius 250.0 + ap3 SetHeight 50.0 + ap3 SetDefaultNormal 1 1 0 +vtkPolyDataMapper mapArc3 + mapArc3 SetInputConnection [ap3 GetOutputPort] +vtkActor arcActor3 + arcActor3 SetMapper mapArc3 + [arcActor3 GetProperty] SetColor 1 0 1 + +# Create graphics objects +# Create the rendering window renderer and interactive renderer +vtkRenderer ren1 + ren1 SetActiveCamera camera +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer set the background and size +ren1 AddActor boreActor +ren1 AddActor arcActor +ren1 AddActor arcActor2 +ren1 AddActor arcActor3 + +ren1 SetBackground 1 1 1 +renWin SetSize 235 500 + +camera SetClippingRange 14144 32817 +camera SetFocalPoint -1023 680 5812 +camera SetPosition 15551 -2426 19820 +camera SetViewUp -0.651889 -0.07576 0.754521 +camera SetViewAngle 20 + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Hybrid/Testing/Tcl/camera.tcl b/Hybrid/Testing/Tcl/camera.tcl new file mode 100644 index 0000000..1ae3c32 --- /dev/null +++ b/Hybrid/Testing/Tcl/camera.tcl @@ -0,0 +1,246 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a camera model +vtkConeSource camCS +camCS SetHeight 1.5 +camCS SetResolution 12 +camCS SetRadius 0.4 + +vtkCubeSource camCBS +camCBS SetXLength 1.5 +camCBS SetZLength 0.8 +camCBS SetCenter 0.4 0 0 + +vtkAppendFilter camAPD +camAPD AddInput [camCS GetOutput] +camAPD AddInput [camCBS GetOutput] + +vtkDataSetMapper camMapper + camMapper SetInputConnection [camAPD GetOutputPort] +vtkLODActor camActor + camActor SetMapper camMapper +camActor SetScale 2 2 2 + +# draw the arrows +vtkPolyData pd +vtkCellArray ca +vtkPoints fp +fp InsertNextPoint 0 1 0 +fp InsertNextPoint 8 1 0 +fp InsertNextPoint 8 2 0 +fp InsertNextPoint 10 0.01 0 +fp InsertNextPoint 8 -2 0 +fp InsertNextPoint 8 -1 0 +fp InsertNextPoint 0 -1 0 +ca InsertNextCell 7 +ca InsertCellPoint 0 +ca InsertCellPoint 1 +ca InsertCellPoint 2 +ca InsertCellPoint 3 +ca InsertCellPoint 4 +ca InsertCellPoint 5 +ca InsertCellPoint 6 +pd SetPoints fp +pd SetPolys ca + +vtkPolyData pd2 +vtkCellArray ca2 +vtkPoints fp2 +fp2 InsertNextPoint 0 1 0 +fp2 InsertNextPoint 8 1 0 +fp2 InsertNextPoint 8 2 0 +fp2 InsertNextPoint 10 0.01 0;#prevents degenerate triangles +ca2 InsertNextCell 4 +ca2 InsertCellPoint 0 +ca2 InsertCellPoint 1 +ca2 InsertCellPoint 2 +ca2 InsertCellPoint 3 +pd2 SetPoints fp2 +pd2 SetLines ca2 + +vtkImplicitModeller arrowIM +arrowIM SetInput pd +arrowIM SetSampleDimensions 50 20 8 + +vtkContourFilter arrowCF +arrowCF SetInputConnection [arrowIM GetOutputPort] +arrowCF SetValue 0 0.2 + +vtkWarpTo arrowWT +arrowWT SetInputConnection [arrowCF GetOutputPort] +arrowWT SetPosition 5 0 5 +arrowWT SetScaleFactor 0.85 +arrowWT AbsoluteOn + +vtkTransform arrowT +arrowT RotateY 60 +arrowT Translate -1.33198 0 -1.479 +arrowT Scale 1 0.5 1 + +vtkTransformFilter arrowTF +arrowTF SetInputConnection [arrowWT GetOutputPort] +arrowTF SetTransform arrowT + +vtkDataSetMapper arrowMapper +arrowMapper SetInputConnection [arrowTF GetOutputPort] +arrowMapper ScalarVisibilityOff + +# draw the azimuth arrows +vtkLODActor a1Actor +a1Actor SetMapper arrowMapper +a1Actor RotateZ 180 +a1Actor SetPosition 1 0 -1 +[a1Actor GetProperty] SetColor 1 0.3 0.3 +[a1Actor GetProperty] SetSpecularColor 1 1 1 +[a1Actor GetProperty] SetSpecular 0.3 +[a1Actor GetProperty] SetSpecularPower 20 +[a1Actor GetProperty] SetAmbient 0.2 +[a1Actor GetProperty] SetDiffuse 0.8 + +vtkLODActor a2Actor +a2Actor SetMapper arrowMapper +a2Actor RotateZ 180 +a2Actor RotateX 180 +a2Actor SetPosition 1 0 1 +[a2Actor GetProperty] SetColor 1 0.3 0.3 +[a2Actor GetProperty] SetSpecularColor 1 1 1 +[a2Actor GetProperty] SetSpecular 0.3 +[a2Actor GetProperty] SetSpecularPower 20 +[a2Actor GetProperty] SetAmbient 0.2 +[a2Actor GetProperty] SetDiffuse 0.8 + +# draw the elevation arrows +vtkLODActor a3Actor +a3Actor SetMapper arrowMapper +a3Actor RotateZ 180 +a3Actor RotateX 90 +a3Actor SetPosition 1 -1 0 +[a3Actor GetProperty] SetColor 0.3 1 0.3 +[a3Actor GetProperty] SetSpecularColor 1 1 1 +[a3Actor GetProperty] SetSpecular 0.3 +[a3Actor GetProperty] SetSpecularPower 20 +[a3Actor GetProperty] SetAmbient 0.2 +[a3Actor GetProperty] SetDiffuse 0.8 + +vtkLODActor a4Actor +a4Actor SetMapper arrowMapper +a4Actor RotateZ 180 +a4Actor RotateX -90 +a4Actor SetPosition 1 1 0 +[a4Actor GetProperty] SetColor 0.3 1 0.3 +[a4Actor GetProperty] SetSpecularColor 1 1 1 +[a4Actor GetProperty] SetSpecular 0.3 +[a4Actor GetProperty] SetSpecularPower 20 +[a4Actor GetProperty] SetAmbient 0.2 +[a4Actor GetProperty] SetDiffuse 0.8 + +# draw the DOP +vtkTransform arrowT2 +arrowT2 Scale 1 0.6 1 +arrowT2 RotateY 90 + +vtkTransformPolyDataFilter arrowTF2 +arrowTF2 SetInput pd2 +arrowTF2 SetTransform arrowT2 + +vtkRotationalExtrusionFilter arrowREF +arrowREF SetInputConnection [arrowTF2 GetOutputPort] +arrowREF CappingOff +arrowREF SetResolution 30 + +vtkPolyDataMapper spikeMapper +spikeMapper SetInputConnection [arrowREF GetOutputPort] + +vtkLODActor a5Actor +a5Actor SetMapper spikeMapper +a5Actor SetScale .3 .3 .6 +a5Actor RotateY 90 +a5Actor SetPosition -2 0 0 +[a5Actor GetProperty] SetColor 1 0.3 1 +[a5Actor GetProperty] SetAmbient 0.2 +[a5Actor GetProperty] SetDiffuse 0.8 + +# focal point +vtkSphereSource fps +fps SetRadius 0.5 +vtkPolyDataMapper fpMapper +fpMapper SetInputConnection [fps GetOutputPort] +vtkLODActor fpActor +fpActor SetMapper fpMapper +fpActor SetPosition -9 0 0 +[fpActor GetProperty] SetSpecularColor 1 1 1 +[fpActor GetProperty] SetSpecular 0.3 +[fpActor GetProperty] SetAmbient 0.2 +[fpActor GetProperty] SetDiffuse 0.8 +[fpActor GetProperty] SetSpecularPower 20 + +# create the roll arrows +vtkWarpTo arrowWT2 +arrowWT2 SetInputConnection [arrowCF GetOutputPort] +arrowWT2 SetPosition 5 0 2.5 +arrowWT2 SetScaleFactor 0.95 +arrowWT2 AbsoluteOn + +vtkTransform arrowT3 +arrowT3 Translate -2.50358 0 -1.70408 +arrowT3 Scale 0.5 0.3 1 + +vtkTransformFilter arrowTF3 +arrowTF3 SetInputConnection [arrowWT2 GetOutputPort] +arrowTF3 SetTransform arrowT3 + +vtkDataSetMapper arrowMapper2 +arrowMapper2 SetInputConnection [arrowTF3 GetOutputPort] +arrowMapper2 ScalarVisibilityOff + +# draw the roll arrows +vtkLODActor a6Actor +a6Actor SetMapper arrowMapper2 +a6Actor RotateZ 90 +a6Actor SetPosition -4 0 0 +a6Actor SetScale 1.5 1.5 1.5 +[a6Actor GetProperty] SetColor 1 1 0.3 +[a6Actor GetProperty] SetSpecularColor 1 1 1 +[a6Actor GetProperty] SetSpecular 0.3 +[a6Actor GetProperty] SetSpecularPower 20 +[a6Actor GetProperty] SetAmbient 0.2 +[a6Actor GetProperty] SetDiffuse 0.8 + +# Add the actors to the renderer, set the background and size +ren1 AddActor camActor +ren1 AddActor a1Actor +ren1 AddActor a2Actor +ren1 AddActor a3Actor +ren1 AddActor a4Actor +ren1 AddActor a5Actor +ren1 AddActor a6Actor +ren1 AddActor fpActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.5 +$cam1 Azimuth 150 +$cam1 Elevation 30 + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# for testing +set threshold 15 + + diff --git a/Hybrid/Testing/Tcl/clipHex.tcl b/Hybrid/Testing/Tcl/clipHex.tcl new file mode 100644 index 0000000..ce46182 --- /dev/null +++ b/Hybrid/Testing/Tcl/clipHex.tcl @@ -0,0 +1,179 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +#define a Single Cube +vtkFloatArray Scalars + Scalars InsertNextValue 1.0 + Scalars InsertNextValue 1.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + +vtkPoints Points + Points InsertNextPoint 0 0 0 + Points InsertNextPoint 1 0 0 + Points InsertNextPoint 1 1 0 + Points InsertNextPoint 0 1 0 + Points InsertNextPoint 0 0 1 + Points InsertNextPoint 1 0 1 + Points InsertNextPoint 1 1 1 + Points InsertNextPoint 0 1 1 + +vtkIdList Ids + Ids InsertNextId 0 + Ids InsertNextId 1 + Ids InsertNextId 2 + Ids InsertNextId 3 + Ids InsertNextId 4 + Ids InsertNextId 5 + Ids InsertNextId 6 + Ids InsertNextId 7 + +vtkUnstructuredGrid Grid + Grid Allocate 10 10 + Grid InsertNextCell 12 Ids + Grid SetPoints Points + [Grid GetPointData] SetScalars Scalars + +#Clip the hex +vtkClipDataSet clipper + clipper SetInput Grid + clipper SetValue 0.5 + +# build tubes for the triangle edges +# +vtkExtractEdges tetEdges + tetEdges SetInputConnection [clipper GetOutputPort] +vtkTubeFilter tetEdgeTubes + tetEdgeTubes SetInputConnection [tetEdges GetOutputPort] + tetEdgeTubes SetRadius .005 + tetEdgeTubes SetNumberOfSides 6 + tetEdgeTubes UseDefaultNormalOn + tetEdgeTubes SetDefaultNormal .577 .577 .577 +vtkPolyDataMapper tetEdgeMapper + tetEdgeMapper SetInputConnection [tetEdgeTubes GetOutputPort] + tetEdgeMapper ScalarVisibilityOff +vtkActor tetEdgeActor + tetEdgeActor SetMapper tetEdgeMapper + eval [tetEdgeActor GetProperty] SetDiffuseColor $lamp_black + [tetEdgeActor GetProperty] SetSpecular .4 + [tetEdgeActor GetProperty] SetSpecularPower 10 + +#shrink the triangles so we can see each one +vtkShrinkFilter aShrinker + aShrinker SetShrinkFactor 1 + aShrinker SetInputConnection [clipper GetOutputPort] +vtkDataSetMapper aMapper + aMapper ScalarVisibilityOff + aMapper SetInputConnection [aShrinker GetOutputPort] +vtkActor Tets + Tets SetMapper aMapper + eval [Tets GetProperty] SetDiffuseColor $banana + +#build a model of the cube +vtkCubeSource CubeModel + CubeModel SetCenter .5 .5 .5 +vtkExtractEdges Edges + Edges SetInputConnection [CubeModel GetOutputPort] +vtkTubeFilter Tubes + Tubes SetInputConnection [Edges GetOutputPort] + Tubes SetRadius .01 + Tubes SetNumberOfSides 6 + Tubes UseDefaultNormalOn + Tubes SetDefaultNormal .577 .577 .577 +vtkPolyDataMapper TubeMapper + TubeMapper SetInputConnection [Tubes GetOutputPort] +vtkActor CubeEdges + CubeEdges SetMapper TubeMapper + eval [CubeEdges GetProperty] SetDiffuseColor $khaki + [CubeEdges GetProperty] SetSpecular .4 + [CubeEdges GetProperty] SetSpecularPower 10 + +# build the vertices of the cube +# +vtkSphereSource Sphere + Sphere SetRadius 0.04 + Sphere SetPhiResolution 20 + Sphere SetThetaResolution 20 +vtkThresholdPoints ThresholdIn + ThresholdIn SetInput Grid + ThresholdIn ThresholdByUpper .5 +vtkGlyph3D Vertices + Vertices SetInputConnection [ThresholdIn GetOutputPort] + Vertices SetSource [Sphere GetOutput] +vtkPolyDataMapper SphereMapper + SphereMapper SetInputConnection [Vertices GetOutputPort] + SphereMapper ScalarVisibilityOff +vtkActor CubeVertices + CubeVertices SetMapper SphereMapper + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + +#define the text for the labels +vtkVectorText caseLabel + caseLabel SetText "Case 2" + +vtkTransform aLabelTransform + aLabelTransform Identity + aLabelTransform Translate -.2 0 1.25 + aLabelTransform Scale .05 .05 .05 + +vtkTransformPolyDataFilter labelTransform + labelTransform SetTransform aLabelTransform + labelTransform SetInputConnection [caseLabel GetOutputPort] + +vtkPolyDataMapper labelMapper + labelMapper SetInputConnection [labelTransform GetOutputPort]; + +vtkActor labelActor + labelActor SetMapper labelMapper + +#define the base +vtkCubeSource baseModel + baseModel SetXLength 1.5 + baseModel SetYLength .01 + baseModel SetZLength 1.5 +vtkPolyDataMapper baseMapper + baseMapper SetInputConnection [baseModel GetOutputPort] +vtkActor base + base SetMapper baseMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# position the base +base SetPosition .5 -.09 .5 + +ren1 AddActor tetEdgeActor +ren1 AddActor base +ren1 AddActor labelActor +ren1 AddActor CubeEdges +ren1 AddActor CubeVertices +ren1 AddActor Tets +eval ren1 SetBackground $slate_grey +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +case2 Scalars 1 0 +renWin SetSize 400 400 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +ren1 ResetCameraClippingRange + +renWin Render +iren Initialize + +wm withdraw . + + diff --git a/Hybrid/Testing/Tcl/clipPyramid.tcl b/Hybrid/Testing/Tcl/clipPyramid.tcl new file mode 100644 index 0000000..53bdd6b --- /dev/null +++ b/Hybrid/Testing/Tcl/clipPyramid.tcl @@ -0,0 +1,181 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +#define a Single Cube +vtkFloatArray Scalars + Scalars InsertNextValue 1.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + +vtkPoints Points + Points InsertNextPoint 0 0 0 + Points InsertNextPoint 1 0 0 + Points InsertNextPoint 1 1 0 + Points InsertNextPoint 0 1 0 + Points InsertNextPoint .5 .5 1 + +vtkIdList Ids + Ids InsertNextId 0 + Ids InsertNextId 1 + Ids InsertNextId 2 + Ids InsertNextId 3 + Ids InsertNextId 4 + +vtkUnstructuredGrid Grid + Grid Allocate 10 10 + Grid InsertNextCell 14 Ids + Grid SetPoints Points + [Grid GetPointData] SetScalars Scalars + +#Clip the pyramid +vtkClipDataSet clipper + clipper SetInput Grid + clipper SetValue 0.5 + +# build tubes for the triangle edges +# +vtkExtractEdges pyrEdges + pyrEdges SetInputConnection [clipper GetOutputPort] +vtkTubeFilter pyrEdgeTubes + pyrEdgeTubes SetInputConnection [pyrEdges GetOutputPort] + pyrEdgeTubes SetRadius .005 + pyrEdgeTubes SetNumberOfSides 6 +vtkPolyDataMapper pyrEdgeMapper + pyrEdgeMapper SetInputConnection [pyrEdgeTubes GetOutputPort] + pyrEdgeMapper ScalarVisibilityOff +vtkActor pyrEdgeActor + pyrEdgeActor SetMapper pyrEdgeMapper + eval [pyrEdgeActor GetProperty] SetDiffuseColor $lamp_black + [pyrEdgeActor GetProperty] SetSpecular .4 + [pyrEdgeActor GetProperty] SetSpecularPower 10 + +#shrink the triangles so we can see each one +vtkShrinkFilter aShrinker + aShrinker SetShrinkFactor 1 + aShrinker SetInputConnection [clipper GetOutputPort] +vtkDataSetMapper aMapper + aMapper ScalarVisibilityOff + aMapper SetInputConnection [aShrinker GetOutputPort] +vtkActor Pyrs + Pyrs SetMapper aMapper + eval [Pyrs GetProperty] SetDiffuseColor $banana + +#build a model of the pyramid +vtkExtractEdges Edges + Edges SetInput Grid +vtkTubeFilter Tubes + Tubes SetInputConnection [Edges GetOutputPort] + Tubes SetRadius .01 + Tubes SetNumberOfSides 6 +vtkPolyDataMapper TubeMapper + TubeMapper SetInputConnection [Tubes GetOutputPort] + TubeMapper ScalarVisibilityOff +vtkActor CubeEdges + CubeEdges SetMapper TubeMapper + eval [CubeEdges GetProperty] SetDiffuseColor $khaki + [CubeEdges GetProperty] SetSpecular .4 + [CubeEdges GetProperty] SetSpecularPower 10 + +# build the vertices of the pyramid +# +vtkSphereSource Sphere + Sphere SetRadius 0.04 + Sphere SetPhiResolution 20 + Sphere SetThetaResolution 20 +vtkThresholdPoints ThresholdIn + ThresholdIn SetInput Grid + ThresholdIn ThresholdByUpper .5 +vtkGlyph3D Vertices + Vertices SetInputConnection [ThresholdIn GetOutputPort] + Vertices SetSource [Sphere GetOutput] +vtkPolyDataMapper SphereMapper + SphereMapper SetInputConnection [Vertices GetOutputPort] + SphereMapper ScalarVisibilityOff +vtkActor CubeVertices + CubeVertices SetMapper SphereMapper + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + +#define the text for the labels +vtkVectorText caseLabel + caseLabel SetText "Case 1" + +vtkTransform aLabelTransform + aLabelTransform Identity + aLabelTransform Translate -.2 0 1.25 + aLabelTransform Scale .05 .05 .05 + +vtkTransformPolyDataFilter labelTransform + labelTransform SetTransform aLabelTransform + labelTransform SetInputConnection [caseLabel GetOutputPort] + +vtkPolyDataMapper labelMapper + labelMapper SetInputConnection [labelTransform GetOutputPort]; + +vtkActor labelActor + labelActor SetMapper labelMapper + +#define the base +vtkCubeSource baseModel + baseModel SetXLength 1.5 + baseModel SetYLength .01 + baseModel SetZLength 1.5 +vtkPolyDataMapper baseMapper + baseMapper SetInputConnection [baseModel GetOutputPort] +vtkActor base + base SetMapper baseMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# position the base +base SetPosition .5 -.09 .5 + +ren1 AddActor pyrEdgeActor +ren1 AddActor base +ren1 AddActor labelActor +ren1 AddActor CubeEdges +ren1 AddActor CubeVertices +ren1 AddActor Pyrs +eval ren1 SetBackground $slate_grey +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin SetSize 400 400 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.3 +[ren1 GetActiveCamera] Elevation 15 +ren1 ResetCameraClippingRange + +renWin Render +iren Initialize + +set mask "1 2 4 8 16 32" +proc cases {id} { + global mask + for {set i 0} {$i < 5} {incr i} { + set m [lindex $mask $i] + if {[expr $m & $id] == 0} { + Scalars SetValue $i 0 + } else { + Scalars SetValue $i 1 + } + caseLabel SetText "Case $id" + } + Grid Modified + renWin Render +} + +cases 20 + +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/clipTet.tcl b/Hybrid/Testing/Tcl/clipTet.tcl new file mode 100644 index 0000000..f37de26 --- /dev/null +++ b/Hybrid/Testing/Tcl/clipTet.tcl @@ -0,0 +1,179 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +#define a Single Cube +vtkFloatArray Scalars + Scalars InsertNextValue 1.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 1.0 + +vtkPoints Points + Points InsertNextPoint 0 0 0 + Points InsertNextPoint 1 0 0 + Points InsertNextPoint 0 1 0 + Points InsertNextPoint 0 0 1 + +vtkIdList Ids + Ids InsertNextId 0 + Ids InsertNextId 1 + Ids InsertNextId 2 + Ids InsertNextId 3 + +vtkUnstructuredGrid Grid + Grid Allocate 10 10 + Grid InsertNextCell 10 Ids + Grid SetPoints Points + [Grid GetPointData] SetScalars Scalars + +#Clip the tetra +vtkClipDataSet clipper + clipper SetInput Grid + clipper SetValue 0.5 + clipper Update + +# build tubes for the triangle edges +# +vtkExtractEdges tetEdges + tetEdges SetInputConnection [clipper GetOutputPort] +vtkTubeFilter tetEdgeTubes + tetEdgeTubes SetInputConnection [tetEdges GetOutputPort] + tetEdgeTubes SetRadius .005 + tetEdgeTubes SetNumberOfSides 6 +vtkPolyDataMapper tetEdgeMapper + tetEdgeMapper SetInputConnection [tetEdgeTubes GetOutputPort] + tetEdgeMapper ScalarVisibilityOff +vtkActor tetEdgeActor + tetEdgeActor SetMapper tetEdgeMapper + eval [tetEdgeActor GetProperty] SetDiffuseColor $lamp_black + [tetEdgeActor GetProperty] SetSpecular .4 + [tetEdgeActor GetProperty] SetSpecularPower 10 + +#shrink the triangles so we can see each one +vtkShrinkFilter aShrinker + aShrinker SetShrinkFactor 1 + aShrinker SetInputConnection [clipper GetOutputPort] +vtkDataSetMapper aMapper + aMapper ScalarVisibilityOff + aMapper SetInputConnection [aShrinker GetOutputPort] +vtkActor Tets + Tets SetMapper aMapper + eval [Tets GetProperty] SetDiffuseColor $banana + +#build a model of the cube +vtkExtractEdges Edges + Edges SetInput Grid +vtkTubeFilter Tubes + Tubes SetInputConnection [Edges GetOutputPort] + Tubes SetRadius .01 + Tubes SetNumberOfSides 6 +vtkPolyDataMapper TubeMapper + TubeMapper SetInputConnection [Tubes GetOutputPort] + TubeMapper ScalarVisibilityOff +vtkActor CubeEdges + CubeEdges SetMapper TubeMapper + eval [CubeEdges GetProperty] SetDiffuseColor $khaki + [CubeEdges GetProperty] SetSpecular .4 + [CubeEdges GetProperty] SetSpecularPower 10 + +# build the vertices of the cube +# +vtkSphereSource Sphere + Sphere SetRadius 0.04 + Sphere SetPhiResolution 20 + Sphere SetThetaResolution 20 +vtkThresholdPoints ThresholdIn + ThresholdIn SetInput Grid + ThresholdIn ThresholdByUpper .5 +vtkGlyph3D Vertices + Vertices SetInputConnection [ThresholdIn GetOutputPort] + Vertices SetSource [Sphere GetOutput] +vtkPolyDataMapper SphereMapper + SphereMapper SetInputConnection [Vertices GetOutputPort] + SphereMapper ScalarVisibilityOff +vtkActor CubeVertices + CubeVertices SetMapper SphereMapper + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + +#define the text for the labels +vtkVectorText caseLabel + caseLabel SetText "Case 1" + +vtkTransform aLabelTransform + aLabelTransform Identity + aLabelTransform Translate -.2 0 1.25 + aLabelTransform Scale .05 .05 .05 + +vtkTransformPolyDataFilter labelTransform + labelTransform SetTransform aLabelTransform + labelTransform SetInputConnection [caseLabel GetOutputPort] + +vtkPolyDataMapper labelMapper + labelMapper SetInputConnection [labelTransform GetOutputPort]; + +vtkActor labelActor + labelActor SetMapper labelMapper + +#define the base +vtkCubeSource baseModel + baseModel SetXLength 1.5 + baseModel SetYLength .01 + baseModel SetZLength 1.5 +vtkPolyDataMapper baseMapper + baseMapper SetInputConnection [baseModel GetOutputPort] +vtkActor base + base SetMapper baseMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# position the base +base SetPosition .5 -.09 .5 + +ren1 AddActor tetEdgeActor +ren1 AddActor base +ren1 AddActor labelActor +ren1 AddActor CubeEdges +ren1 AddActor CubeVertices +ren1 AddActor Tets +eval ren1 SetBackground $slate_grey +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +Grid Modified +renWin SetSize 400 400 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +ren1 ResetCameraClippingRange + +renWin Render +iren Initialize + +set mask "1 2 4 8 16 32" +proc cases {id} { + global mask + for {set i 0} {$i < 4} {incr i} { + set m [lindex $mask $i] + if {[expr $m & $id] == 0} { + Scalars SetValue $i 0 + } else { + Scalars SetValue $i 1 + } + caseLabel SetText "Case $id" + } + Grid Modified + renWin Render +} +cases 3 + +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/clipWedge.tcl b/Hybrid/Testing/Tcl/clipWedge.tcl new file mode 100644 index 0000000..7dbfe62 --- /dev/null +++ b/Hybrid/Testing/Tcl/clipWedge.tcl @@ -0,0 +1,184 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +#define a Single Cube +vtkFloatArray Scalars + Scalars InsertNextValue 1.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + Scalars InsertNextValue 0.0 + +vtkPoints Points + Points InsertNextPoint 0 0 0 + Points InsertNextPoint 1 0 0 + Points InsertNextPoint 0 0 1 + Points InsertNextPoint 0 1 0 + Points InsertNextPoint 1 1 0 + Points InsertNextPoint 0 1 1 + +vtkIdList Ids + Ids InsertNextId 0 + Ids InsertNextId 1 + Ids InsertNextId 2 + Ids InsertNextId 3 + Ids InsertNextId 4 + Ids InsertNextId 5 + +vtkUnstructuredGrid Grid + Grid Allocate 10 10 + Grid InsertNextCell 13 Ids + Grid SetPoints Points + [Grid GetPointData] SetScalars Scalars + +#Clip the wedge +vtkClipDataSet clipper + clipper SetInput Grid + clipper SetValue 0.5 + +# build tubes for the triangle edges +# +vtkExtractEdges wedgeEdges + wedgeEdges SetInputConnection [clipper GetOutputPort] +vtkTubeFilter wedgeEdgeTubes + wedgeEdgeTubes SetInputConnection [wedgeEdges GetOutputPort] + wedgeEdgeTubes SetRadius .005 + wedgeEdgeTubes SetNumberOfSides 6 +vtkPolyDataMapper wedgeEdgeMapper + wedgeEdgeMapper SetInputConnection [wedgeEdgeTubes GetOutputPort] + wedgeEdgeMapper ScalarVisibilityOff +vtkActor wedgeEdgeActor + wedgeEdgeActor SetMapper wedgeEdgeMapper + eval [wedgeEdgeActor GetProperty] SetDiffuseColor $lamp_black + [wedgeEdgeActor GetProperty] SetSpecular .4 + [wedgeEdgeActor GetProperty] SetSpecularPower 10 + +#shrink the triangles so we can see each one +vtkShrinkFilter aShrinker + aShrinker SetShrinkFactor 1 + aShrinker SetInputConnection [clipper GetOutputPort] +vtkDataSetMapper aMapper + aMapper ScalarVisibilityOff + aMapper SetInputConnection [aShrinker GetOutputPort] +vtkActor Wedges + Wedges SetMapper aMapper + eval [Wedges GetProperty] SetDiffuseColor $banana + +#build a model of the cube +vtkExtractEdges Edges + Edges SetInput Grid +vtkTubeFilter Tubes + Tubes SetInputConnection [Edges GetOutputPort] + Tubes SetRadius .01 + Tubes SetNumberOfSides 6 +vtkPolyDataMapper TubeMapper + TubeMapper SetInputConnection [Tubes GetOutputPort] + TubeMapper ScalarVisibilityOff +vtkActor CubeEdges + CubeEdges SetMapper TubeMapper + eval [CubeEdges GetProperty] SetDiffuseColor $khaki + [CubeEdges GetProperty] SetSpecular .4 + [CubeEdges GetProperty] SetSpecularPower 10 + +# build the vertices of the cube +# +vtkSphereSource Sphere + Sphere SetRadius 0.04 + Sphere SetPhiResolution 20 + Sphere SetThetaResolution 20 +vtkThresholdPoints ThresholdIn + ThresholdIn SetInput Grid + ThresholdIn ThresholdByUpper .5 +vtkGlyph3D Vertices + Vertices SetInputConnection [ThresholdIn GetOutputPort] + Vertices SetSource [Sphere GetOutput] +vtkPolyDataMapper SphereMapper + SphereMapper SetInputConnection [Vertices GetOutputPort] + SphereMapper ScalarVisibilityOff +vtkActor CubeVertices + CubeVertices SetMapper SphereMapper + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + eval [CubeVertices GetProperty] SetDiffuseColor $tomato + +#define the text for the labels +vtkVectorText caseLabel + caseLabel SetText "Case 1" + +vtkTransform aLabelTransform + aLabelTransform Identity + aLabelTransform Translate -.2 0 1.25 + aLabelTransform Scale .05 .05 .05 + +vtkTransformPolyDataFilter labelTransform + labelTransform SetTransform aLabelTransform + labelTransform SetInputConnection [caseLabel GetOutputPort] + +vtkPolyDataMapper labelMapper + labelMapper SetInputConnection [labelTransform GetOutputPort]; + +vtkActor labelActor + labelActor SetMapper labelMapper + +#define the base +vtkCubeSource baseModel + baseModel SetXLength 1.5 + baseModel SetYLength .01 + baseModel SetZLength 1.5 +vtkPolyDataMapper baseMapper + baseMapper SetInputConnection [baseModel GetOutputPort] +vtkActor base + base SetMapper baseMapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# position the base +base SetPosition .5 -.09 .5 + +ren1 AddActor wedgeEdgeActor +ren1 AddActor base +ren1 AddActor labelActor +ren1 AddActor CubeEdges +ren1 AddActor CubeVertices +ren1 AddActor Wedges +eval ren1 SetBackground $slate_grey +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin SetSize 400 400 + +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +ren1 ResetCameraClippingRange + +renWin Render +iren Initialize + +set mask "1 2 4 8 16 32" +proc cases {id} { + global mask + for {set i 0} {$i < 6} {incr i} { + set m [lindex $mask $i] + if {[expr $m & $id] == 0} { + Scalars SetValue $i 0 + } else { + Scalars SetValue $i 1 + } + caseLabel SetText "Case $id" + } + Grid Modified + renWin Render +} + +cases 7 + +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/cubeAxes.tcl b/Hybrid/Testing/Tcl/cubeAxes.tcl new file mode 100644 index 0000000..bc27c83 --- /dev/null +++ b/Hybrid/Testing/Tcl/cubeAxes.tcl @@ -0,0 +1,101 @@ +package require vtk +package require vtkinteraction + +# read in an interesting object and outline it +# +vtkBYUReader fohe + fohe SetGeometryFileName "$VTK_DATA_ROOT/Data/teapot.g" +vtkPolyDataNormals normals + normals SetInputConnection [fohe GetOutputPort] +vtkPolyDataMapper foheMapper + foheMapper SetInputConnection [normals GetOutputPort] +vtkLODActor foheActor + foheActor SetMapper foheMapper + +vtkOutlineFilter outline + outline SetInputConnection [normals GetOutputPort] +vtkPolyDataMapper mapOutline + mapOutline SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper mapOutline + [outlineActor GetProperty] SetColor 0 0 0 + +# Create the RenderWindow, Renderer, and setup viewports +vtkCamera camera + camera SetClippingRange 1.60187 20.0842 + camera SetFocalPoint 0.21406 1.5 0 + camera SetPosition 11.63 6.32 5.77 + camera SetViewUp 0.180325 0.549245 -0.815974 +vtkLight light + light SetFocalPoint 0.21406 1.5 0 + light SetPosition 8.3761 4.94858 4.12505 + +vtkRenderer ren1 + ren1 SetViewport 0 0 0.5 1.0 + ren1 SetActiveCamera camera + ren1 AddLight light +vtkRenderer ren2 + ren2 SetViewport 0.5 0 1.0 1.0 + ren2 SetActiveCamera camera + ren2 AddLight light +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 + renWin SetWindowName "VTK - Cube Axes" + renWin SetSize 790 400 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddViewProp foheActor +ren1 AddViewProp outlineActor +ren2 AddViewProp foheActor +if { [info command "rtExMath"] == ""} { + ren2 AddViewProp outlineActor +} + +ren1 SetBackground 0.1 0.2 0.4 +ren2 SetBackground 0.1 0.2 0.4 + +vtkTextProperty tprop + tprop SetColor 1 1 1 + tprop ShadowOn + +vtkCubeAxesActor2D axes + axes SetInput [normals GetOutput] + axes SetCamera [ren1 GetActiveCamera] + axes SetLabelFormat "%6.1f" + axes SetFlyModeToOuterEdges + axes SetFontFactor 0.8 + axes SetAxisTitleTextProperty tprop + axes SetAxisLabelTextProperty tprop +ren1 AddViewProp axes + +vtkCubeAxesActor2D axes2 + axes2 SetViewProp foheActor + axes2 SetCamera [ren2 GetActiveCamera] + axes2 SetLabelFormat [axes GetLabelFormat] + axes2 SetFlyModeToClosestTriad + axes2 SetFontFactor [axes GetFontFactor] + axes2 ScalingOff + axes2 SetAxisTitleTextProperty tprop + axes2 SetAxisLabelTextProperty tprop +ren2 AddViewProp axes2 + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +iren Initialize + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" {TkCheckAbort} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/depthSort.tcl b/Hybrid/Testing/Tcl/depthSort.tcl new file mode 100644 index 0000000..ab03ef8 --- /dev/null +++ b/Hybrid/Testing/Tcl/depthSort.tcl @@ -0,0 +1,82 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +vtkCamera camera + ren1 SetActiveCamera camera + +# create a sphere source and actor +# +vtkSphereSource sphere + sphere SetThetaResolution 80 + sphere SetPhiResolution 40 + sphere SetRadius 1 + sphere SetCenter 0 0 0 +vtkSphereSource sphere2 + sphere2 SetThetaResolution 80 + sphere2 SetPhiResolution 40 + sphere2 SetRadius 0.5 + sphere2 SetCenter 1 0 0 +vtkSphereSource sphere3 + sphere3 SetThetaResolution 80 + sphere3 SetPhiResolution 40 + sphere3 SetRadius 0.5 + sphere3 SetCenter -1 0 0 +vtkSphereSource sphere4 + sphere4 SetThetaResolution 80 + sphere4 SetPhiResolution 40 + sphere4 SetRadius 0.5 + sphere4 SetCenter 0 1 0 +vtkSphereSource sphere5 + sphere5 SetThetaResolution 80 + sphere5 SetPhiResolution 40 + sphere5 SetRadius 0.5 + sphere5 SetCenter 0 -1 0 +vtkAppendPolyData appendData + appendData AddInput [sphere GetOutput] + appendData AddInput [sphere2 GetOutput] + appendData AddInput [sphere3 GetOutput] + appendData AddInput [sphere4 GetOutput] + appendData AddInput [sphere5 GetOutput] + +vtkDepthSortPolyData depthSort + depthSort SetInputConnection [appendData GetOutputPort] + depthSort SetDirectionToBackToFront + depthSort SetVector 1 1 1 + depthSort SetCamera camera + depthSort SortScalarsOn + depthSort Update + +vtkPolyDataMapper mapper + mapper SetInputConnection [depthSort GetOutputPort] + mapper SetScalarRange 0 [[depthSort GetOutput] GetNumberOfCells] +vtkActor actor + actor SetMapper mapper + [actor GetProperty] SetOpacity 0.5 + [actor GetProperty] SetColor 1 0 0 + actor RotateX -72 + +depthSort SetProp3D actor + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 300 200 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 2.2 +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/earth.tcl b/Hybrid/Testing/Tcl/earth.tcl new file mode 100644 index 0000000..dd2af5c --- /dev/null +++ b/Hybrid/Testing/Tcl/earth.tcl @@ -0,0 +1,58 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkTexturedSphereSource tss + tss SetThetaResolution 18 + tss SetPhiResolution 9 +vtkPolyDataMapper earthMapper + earthMapper SetInputConnection [tss GetOutputPort] +vtkActor earthActor + earthActor SetMapper earthMapper + +# load in the texture map +# +vtkTexture atext +vtkPNMReader pnmReader + pnmReader SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +atext SetInputConnection [pnmReader GetOutputPort] +atext InterpolateOn +earthActor SetTexture atext + +# create a earth source and actor +# +vtkEarthSource es + es SetRadius 0.501 + es SetOnRatio 2 +vtkPolyDataMapper earth2Mapper + earth2Mapper SetInputConnection [es GetOutputPort] +vtkActor earth2Actor + earth2Actor SetMapper earth2Mapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor earthActor +ren1 AddActor earth2Actor +ren1 SetBackground 0 0 0.1 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Hybrid/Testing/Tcl/financialField2.tcl b/Hybrid/Testing/Tcl/financialField2.tcl new file mode 100644 index 0000000..56a06de --- /dev/null +++ b/Hybrid/Testing/Tcl/financialField2.tcl @@ -0,0 +1,228 @@ +package require vtk +package require vtkinteraction + +# demonstrate the use and manipulation of fields and use of +# vtkProgrammableDataObjectSource. This creates fields the hard way +# (as compared to reading a vtk field file), but shows you how to +# interfaceto your own raw data. + +# The image should be the same as financialField.tcl + +set xAxis INTEREST_RATE +set yAxis MONTHLY_PAYMENT +set zAxis MONTHLY_INCOME +set scalar TIME_LATE + +# Parse an ascii file and manually create a field. Then construct a +# dataset from the field. +vtkProgrammableDataObjectSource dos + dos SetExecuteMethod parseFile +proc parseFile {} { + global VTK_DATA_ROOT + set file [open "$VTK_DATA_ROOT/Data/financial.txt" "r"] + set line [gets $file] + scan $line "%*s %d" numPts + set numLines [expr (($numPts - 1) / 8) + 1 ] + + # create the data object + vtkFieldData field + field AllocateArrays 4 + + # read TIME_LATE - dependent variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray timeLate + timeLate SetName TIME_LATE + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {timeLate InsertNextValue $v($j)} + } + field AddArray timeLate + + # MONTHLY_PAYMENT - independent variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray monthlyPayment + monthlyPayment SetName MONTHLY_PAYMENT + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {monthlyPayment InsertNextValue $v($j)} + } + field AddArray monthlyPayment + + # UNPAID_PRINCIPLE - skip + while { [gets $file arrayName] == 0 } {} + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + } + + # LOAN_AMOUNT - skip + while { [gets $file arrayName] == 0 } {} + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + } + + # INTEREST_RATE - independnet variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray interestRate + interestRate SetName INTEREST_RATE + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {interestRate InsertNextValue $v($j)} + } + field AddArray interestRate + + # MONTHLY_INCOME - independent variable + while { [gets $file arrayName] == 0 } {} + vtkIntArray monthlyIncome + monthlyIncome SetName MONTHLY_INCOME + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%d %d %d %d %d %d %d %d" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {monthlyIncome InsertNextValue $v($j)} + } + field AddArray monthlyIncome + + [dos GetOutput] SetFieldData field +} + +# Create the dataset +vtkDataObjectToDataSetFilter do2ds + do2ds SetInputConnection [dos GetOutputPort] + do2ds SetDataSetTypeToPolyData + #format: component#, arrayname, arraycomp, minArrayId, maxArrayId, normalize + do2ds DefaultNormalizeOn + do2ds SetPointComponent 0 $xAxis 0 + do2ds SetPointComponent 1 $yAxis 0 + do2ds SetPointComponent 2 $zAxis 0 + do2ds Update +vtkFieldDataToAttributeDataFilter fd2ad + fd2ad SetInputConnection [do2ds GetOutputPort] + fd2ad SetInputFieldToDataObjectField + fd2ad SetOutputAttributeDataToPointData + fd2ad DefaultNormalizeOn + fd2ad SetScalarComponent 0 $scalar 0 + +# construct pipeline for original population +vtkGaussianSplatter popSplatter + popSplatter SetInputConnection [fd2ad GetOutputPort] + popSplatter SetSampleDimensions 50 50 50 + popSplatter SetRadius 0.05 + popSplatter ScalarWarpingOff +vtkContourFilter popSurface + popSurface SetInputConnection [popSplatter GetOutputPort] + popSurface SetValue 0 0.01 +vtkPolyDataMapper popMapper + popMapper SetInputConnection [popSurface GetOutputPort] + popMapper ScalarVisibilityOff + popMapper ImmediateModeRenderingOn +vtkActor popActor + popActor SetMapper popMapper + [popActor GetProperty] SetOpacity 0.3 + [popActor GetProperty] SetColor .9 .9 .9 + +# construct pipeline for delinquent population +vtkGaussianSplatter lateSplatter + lateSplatter SetInputConnection [fd2ad GetOutputPort] + lateSplatter SetSampleDimensions 50 50 50 + lateSplatter SetRadius 0.05 + lateSplatter SetScaleFactor 0.05 +vtkContourFilter lateSurface + lateSurface SetInputConnection [lateSplatter GetOutputPort] + lateSurface SetValue 0 0.01 +vtkPolyDataMapper lateMapper + lateMapper SetInputConnection [lateSurface GetOutputPort] + lateMapper ScalarVisibilityOff +vtkActor lateActor + lateActor SetMapper lateMapper + [lateActor GetProperty] SetColor 1.0 0.0 0.0 + +# create axes +popSplatter Update +set bounds [[popSplatter GetOutput] GetBounds] +vtkAxes axes + axes SetOrigin [lindex $bounds 0] [lindex $bounds 2] [lindex $bounds 4] + axes SetScaleFactor [expr [[popSplatter GetOutput] GetLength]/5.0] +vtkTubeFilter axesTubes + axesTubes SetInputConnection [axes GetOutputPort] + axesTubes SetRadius [expr [axes GetScaleFactor]/25.0] + axesTubes SetNumberOfSides 6 +vtkPolyDataMapper axesMapper + axesMapper SetInputConnection [axesTubes GetOutputPort] +vtkActor axesActor + axesActor SetMapper axesMapper + +# label the axes +vtkVectorText XText + XText SetText $xAxis +vtkPolyDataMapper XTextMapper + XTextMapper SetInputConnection [XText GetOutputPort] +vtkFollower XActor + XActor SetMapper XTextMapper + XActor SetScale 0.02 .02 .02 + XActor SetPosition 0.35 -0.05 -0.05 + [XActor GetProperty] SetColor 0 0 0 + +vtkVectorText YText + YText SetText $yAxis +vtkPolyDataMapper YTextMapper + YTextMapper SetInputConnection [YText GetOutputPort] +vtkFollower YActor + YActor SetMapper YTextMapper + YActor SetScale 0.02 .02 .02 + YActor SetPosition -0.05 0.35 -0.05 + [YActor GetProperty] SetColor 0 0 0 + +vtkVectorText ZText + ZText SetText $zAxis +vtkPolyDataMapper ZTextMapper + ZTextMapper SetInputConnection [ZText GetOutputPort] +vtkFollower ZActor + ZActor SetMapper ZTextMapper + ZActor SetScale 0.02 .02 .02 + ZActor SetPosition -0.05 -0.05 0.35 + [ZActor GetProperty] SetColor 0 0 0 + +# Graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetWindowName "vtk - Field Data" +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor axesActor +ren1 AddActor lateActor +ren1 AddActor XActor +ren1 AddActor YActor +ren1 AddActor ZActor +ren1 AddActor popActor;#it's last because its translucent +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 + +vtkCamera camera + camera SetClippingRange .274 13.72 + camera SetFocalPoint 0.433816 0.333131 0.449 + camera SetPosition -1.96987 1.15145 1.49053 + camera SetViewUp 0.378927 0.911821 0.158107 +ren1 SetActiveCamera camera +XActor SetCamera camera +YActor SetCamera camera +ZActor SetCamera camera + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/financialField3.tcl b/Hybrid/Testing/Tcl/financialField3.tcl new file mode 100644 index 0000000..036a16a --- /dev/null +++ b/Hybrid/Testing/Tcl/financialField3.tcl @@ -0,0 +1,249 @@ +package require vtk +package require vtkinteraction + +# demonstrate the use and manipulation of fields and use of +# vtkProgrammableDataObjectSource. This creates fields the hard way +# (as compared to reading a vtk field file), but shows you how to +# interfaceto your own raw data. + +# The image should be the same as financialField.tcl + +set xAxis INTEREST_RATE +set yAxis MONTHLY_PAYMENT +set zAxis MONTHLY_INCOME +set scalar TIME_LATE + +# Parse an ascii file and manually create a field. Then construct a +# dataset from the field. +vtkProgrammableDataObjectSource dos + dos SetExecuteMethod parseFile +proc parseFile {} { + global VTK_DATA_ROOT + set file [open "$VTK_DATA_ROOT/Data/financial.txt" r] + set line [gets $file] + scan $line "%*s %d" numPts + set numLines [expr (($numPts - 1) / 8) + 1 ] + + # create the data object + vtkFieldData field + field AllocateArrays 4 + + # read TIME_LATE - dependent variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray timeLate + timeLate SetName TIME_LATE + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {timeLate InsertNextValue $v($j)} + } + field AddArray timeLate + + # MONTHLY_PAYMENT - independent variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray monthlyPayment + monthlyPayment SetName MONTHLY_PAYMENT + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {monthlyPayment InsertNextValue $v($j)} + } + field AddArray monthlyPayment + + # UNPAID_PRINCIPLE - skip + while { [gets $file arrayName] == 0 } {} + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + } + + # LOAN_AMOUNT - skip + while { [gets $file arrayName] == 0 } {} + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + } + + # INTEREST_RATE - independnet variable + while { [gets $file arrayName] == 0 } {} + vtkFloatArray interestRate + interestRate SetName INTEREST_RATE + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%f %f %f %f %f %f %f %f" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {interestRate InsertNextValue $v($j)} + } + field AddArray interestRate + + # MONTHLY_INCOME - independent variable + while { [gets $file arrayName] == 0 } {} + vtkIntArray monthlyIncome + monthlyIncome SetName MONTHLY_INCOME + for {set i 0} {$i < $numLines} {incr i} { + set line [gets $file] + set m [scan $line "%d %d %d %d %d %d %d %d" \ + v(0) v(1) v(2) v(3) v(4) v(5) v(6) v(7)] + for {set j 0} {$j < $m} {incr j} {monthlyIncome InsertNextValue $v($j)} + } + field AddArray monthlyIncome + + [dos GetOutput] SetFieldData field +} + + +# Create the dataset +vtkDataObjectToDataSetFilter do2ds + do2ds SetInputConnection [dos GetOutputPort] + do2ds SetDataSetTypeToPolyData + #format: component#, arrayname, arraycomp, minArrayId, maxArrayId, normalize + do2ds DefaultNormalizeOn + do2ds SetPointComponent 0 $xAxis 0 + do2ds SetPointComponent 1 $yAxis 0 + do2ds SetPointComponent 2 $zAxis 0 + do2ds Update + +vtkRearrangeFields rf + rf SetInputConnection [do2ds GetOutputPort] + rf AddOperation MOVE $scalar DATA_OBJECT POINT_DATA + rf RemoveOperation MOVE $scalar DATA_OBJECT POINT_DATA + rf AddOperation MOVE $scalar DATA_OBJECT POINT_DATA + rf RemoveAllOperations + rf AddOperation MOVE $scalar DATA_OBJECT POINT_DATA + rf Update + set max [lindex [[[[rf GetOutput] GetPointData] GetArray $scalar] GetRange 0] 1] + +vtkArrayCalculator calc + calc SetInputConnection [rf GetOutputPort] + calc SetAttributeModeToUsePointData + calc SetFunction "s / $max" + calc AddScalarVariable s $scalar 0 + calc SetResultArrayName resArray + +vtkAssignAttribute aa + aa SetInputConnection [calc GetOutputPort] + aa Assign resArray SCALARS POINT_DATA + aa Update + +vtkRearrangeFields rf2 + rf2 SetInputConnection [aa GetOutputPort] + rf2 AddOperation COPY SCALARS POINT_DATA DATA_OBJECT + +# construct pipeline for original population +vtkGaussianSplatter popSplatter + popSplatter SetInputConnection [rf2 GetOutputPort] + popSplatter SetSampleDimensions 50 50 50 + popSplatter SetRadius 0.05 + popSplatter ScalarWarpingOff +vtkContourFilter popSurface + popSurface SetInputConnection [popSplatter GetOutputPort] + popSurface SetValue 0 0.01 +vtkPolyDataMapper popMapper + popMapper SetInputConnection [popSurface GetOutputPort] + popMapper ScalarVisibilityOff + popMapper ImmediateModeRenderingOn +vtkActor popActor + popActor SetMapper popMapper + [popActor GetProperty] SetOpacity 0.3 + [popActor GetProperty] SetColor .9 .9 .9 + +# construct pipeline for delinquent population +vtkGaussianSplatter lateSplatter + lateSplatter SetInputConnection [aa GetOutputPort] + lateSplatter SetSampleDimensions 50 50 50 + lateSplatter SetRadius 0.05 + lateSplatter SetScaleFactor 0.05 +vtkContourFilter lateSurface + lateSurface SetInputConnection [lateSplatter GetOutputPort] + lateSurface SetValue 0 0.01 +vtkPolyDataMapper lateMapper + lateMapper SetInputConnection [lateSurface GetOutputPort] + lateMapper ScalarVisibilityOff +vtkActor lateActor + lateActor SetMapper lateMapper + [lateActor GetProperty] SetColor 1.0 0.0 0.0 + +# create axes +popSplatter Update +set bounds [[popSplatter GetOutput] GetBounds] +vtkAxes axes + axes SetOrigin [lindex $bounds 0] [lindex $bounds 2] [lindex $bounds 4] + axes SetScaleFactor [expr [[popSplatter GetOutput] GetLength]/5.0] +vtkTubeFilter axesTubes + axesTubes SetInputConnection [axes GetOutputPort] + axesTubes SetRadius [expr [axes GetScaleFactor]/25.0] + axesTubes SetNumberOfSides 6 +vtkPolyDataMapper axesMapper + axesMapper SetInputConnection [axesTubes GetOutputPort] +vtkActor axesActor + axesActor SetMapper axesMapper + +# label the axes +vtkVectorText XText + XText SetText $xAxis +vtkPolyDataMapper XTextMapper + XTextMapper SetInputConnection [XText GetOutputPort] +vtkFollower XActor + XActor SetMapper XTextMapper + XActor SetScale 0.02 .02 .02 + XActor SetPosition 0.35 -0.05 -0.05 + [XActor GetProperty] SetColor 0 0 0 + +vtkVectorText YText + YText SetText $yAxis +vtkPolyDataMapper YTextMapper + YTextMapper SetInputConnection [YText GetOutputPort] +vtkFollower YActor + YActor SetMapper YTextMapper + YActor SetScale 0.02 .02 .02 + YActor SetPosition -0.05 0.35 -0.05 + [YActor GetProperty] SetColor 0 0 0 + +vtkVectorText ZText + ZText SetText $zAxis +vtkPolyDataMapper ZTextMapper + ZTextMapper SetInputConnection [ZText GetOutputPort] +vtkFollower ZActor + ZActor SetMapper ZTextMapper + ZActor SetScale 0.02 .02 .02 + ZActor SetPosition -0.05 -0.05 0.35 + [ZActor GetProperty] SetColor 0 0 0 + +# Graphics stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetWindowName "vtk - Field Data" + renWin SetSize 300 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor axesActor +ren1 AddActor lateActor +ren1 AddActor XActor +ren1 AddActor YActor +ren1 AddActor ZActor +ren1 AddActor popActor;#it's last because its translucent +ren1 SetBackground 1 1 1 + +vtkCamera camera + camera SetClippingRange .274 13.72 + camera SetFocalPoint 0.433816 0.333131 0.449 + camera SetPosition -1.96987 1.15145 1.49053 + camera SetViewUp 0.378927 0.911821 0.158107 +ren1 SetActiveCamera camera +XActor SetCamera camera +YActor SetCamera camera +ZActor SetCamera camera + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/imageToPolyData.tcl b/Hybrid/Testing/Tcl/imageToPolyData.tcl new file mode 100644 index 0000000..952ae14 --- /dev/null +++ b/Hybrid/Testing/Tcl/imageToPolyData.tcl @@ -0,0 +1,57 @@ +package require vtk +package require vtkinteraction + +# create reader and extract the velocity and temperature +vtkPNGReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/vtk.png" + +vtkImageQuantizeRGBToIndex quant + quant SetInputConnection [reader GetOutputPort] + quant SetNumberOfColors 32 + +vtkImageToPolyDataFilter i2pd + i2pd SetInputConnection [quant GetOutputPort] + i2pd SetLookupTable [quant GetLookupTable] + i2pd SetColorModeToLUT + i2pd SetOutputStyleToPolygonalize + i2pd SetError 0 + i2pd DecimationOn + i2pd SetDecimationError 0.0 + i2pd SetSubImageSize 25 + +#Need a triangle filter because the polygons are complex and concave +vtkTriangleFilter tf + tf SetInputConnection [i2pd GetOutputPort] + +vtkPolyDataMapper mapper + mapper SetInputConnection [tf GetOutputPort] + +vtkActor actor + actor SetMapper mapper + +# Create graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +ren1 AddActor actor + +ren1 SetBackground 1 1 1 +renWin SetSize 300 250 + +vtkCamera acamera + acamera SetClippingRange 343.331 821.78 + acamera SetPosition -139.802 -85.6604 437.485 + acamera SetFocalPoint 117.424 106.656 -14.6 + acamera SetViewUp 0.430481 0.716032 0.549532 + acamera SetViewAngle 30 +ren1 SetActiveCamera acamera + +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/largeImageOffset.tcl b/Hybrid/Testing/Tcl/largeImageOffset.tcl new file mode 100644 index 0000000..1ccb1c3 --- /dev/null +++ b/Hybrid/Testing/Tcl/largeImageOffset.tcl @@ -0,0 +1,60 @@ +package require vtk + +vtkRenderer ren1 +vtkRenderWindow renWin1 + renWin1 AddRenderer ren1 + +vtk3DSImporter importer + importer SetRenderWindow renWin1 + importer ComputeNormalsOn + importer SetFileName "$VTK_DATA_ROOT/Data/iflamigm.3ds" + importer Read + +[importer GetRenderer] SetBackground 0.1 0.2 0.4 +[importer GetRenderWindow] SetSize 150 150 + +# +# the importer created the renderer +set renCollection [renWin1 GetRenderers] +$renCollection InitTraversal +set ren [$renCollection GetNextItem] + +# +# change view up to +z +# +[$ren GetActiveCamera] SetWindowCenter -0.2 0.3 +[$ren GetActiveCamera] SetPosition 0 1 0 +[$ren GetActiveCamera] SetFocalPoint 0 0 0 +[$ren GetActiveCamera] SetViewUp 0 0 1 + +# +# let the renderer compute good position and focal point +# +$ren ResetCamera +[$ren GetActiveCamera] Dolly 1.4 +ren1 ResetCameraClippingRange + +# render the large image +# +wm withdraw . + +vtkRenderLargeImage renderLarge + renderLarge SetInput ren1 + renderLarge SetMagnification 3 + renderLarge Update + +vtkImageViewer viewer + viewer SetInputConnection [renderLarge GetOutputPort] + viewer SetColorWindow 255 + viewer SetColorLevel 127.5 + viewer Render + +# on several opengl X window unix implementations +# multiple context deletes cause errors +# so we leak the renWin1 in this test for unix +if { $tcl_platform(platform) == "unix" } { + renWin1 Register ren1 + vtkDebugLeaks dl + dl SetExitError 0 + dl Delete +} diff --git a/Hybrid/Testing/Tcl/largeImageParallel.tcl b/Hybrid/Testing/Tcl/largeImageParallel.tcl new file mode 100644 index 0000000..8b25172 --- /dev/null +++ b/Hybrid/Testing/Tcl/largeImageParallel.tcl @@ -0,0 +1,60 @@ +package require vtk + +vtkRenderer ren1 +vtkRenderWindow renWin1 + renWin1 AddRenderer ren1 + +vtk3DSImporter importer + importer SetRenderWindow renWin1 + importer ComputeNormalsOn + importer SetFileName "$VTK_DATA_ROOT/Data/iflamigm.3ds" + importer Read + +[importer GetRenderer] SetBackground 0.1 0.2 0.4 +[importer GetRenderWindow] SetSize 150 150 + +# +# the importer created the renderer +set renCollection [renWin1 GetRenderers] +$renCollection InitTraversal +set ren [$renCollection GetNextItem] + +# +# change view up to +z +# +[$ren GetActiveCamera] ParallelProjectionOn +[$ren GetActiveCamera] SetPosition 0 1 0 +[$ren GetActiveCamera] SetFocalPoint 0 0 0 +[$ren GetActiveCamera] SetViewUp 0 0 1 + +# +# let the renderer compute good position and focal point +# +$ren ResetCamera +[$ren GetActiveCamera] Zoom 1.4 +ren1 ResetCameraClippingRange + +# render the large image +# +wm withdraw . + +vtkRenderLargeImage renderLarge + renderLarge SetInput ren1 + renderLarge SetMagnification 3 + renderLarge Update + +vtkImageViewer viewer + viewer SetInputConnection [renderLarge GetOutputPort] + viewer SetColorWindow 255 + viewer SetColorLevel 127.5 + viewer Render + +# on several opengl X window unix implementations +# multiple context deletes cause errors +# so we leak teh renWin1 in this test for unix +if { $tcl_platform(platform) == "unix" } { + renWin1 Register ren1 + vtkDebugLeaks dl + dl SetExitError 0 + dl Delete +} diff --git a/Hybrid/Testing/Tcl/text.tcl b/Hybrid/Testing/Tcl/text.tcl new file mode 100644 index 0000000..f48a7b2 --- /dev/null +++ b/Hybrid/Testing/Tcl/text.tcl @@ -0,0 +1,77 @@ +package require vtk +package require vtkinteraction + +# Created oriented text + +vtkTextSource text0Source + text0Source SetText "Text Source with Scalars (default)" + +vtkPolyDataMapper text0Mapper + text0Mapper SetInputConnection [text0Source GetOutputPort] + +vtkActor text0Actor + text0Actor SetMapper text0Mapper + text0Actor SetScale .1 .1 .1 + text0Actor AddPosition 0 2 0 + +vtkTextSource text1Source + text1Source SetText "Text Source with Scalars" + text1Source SetForegroundColor 1 0 0 + text1Source SetBackgroundColor 1 1 1 + +vtkPolyDataMapper text1Mapper + text1Mapper SetInputConnection [text1Source GetOutputPort] + +vtkActor text1Actor + text1Actor SetMapper text1Mapper + text1Actor SetScale .1 .1 .1 + +vtkTextSource text2Source + text2Source SetText "Text Source without Scalars" + text2Source BackingOff + +vtkPolyDataMapper text2Mapper + text2Mapper SetInputConnection [text2Source GetOutputPort] + text2Mapper ScalarVisibilityOff + +vtkActor text2Actor + text2Actor SetMapper text2Mapper + [text2Actor GetProperty] SetColor 1 1 0 + text2Actor SetScale .1 .1 .1 + text2Actor AddPosition 0 -2 0 + +vtkVectorText text3Source + text3Source SetText "Vector Text" + +vtkPolyDataMapper text3Mapper + text3Mapper SetInputConnection [text3Source GetOutputPort] + text3Mapper ScalarVisibilityOff + +vtkActor text3Actor + text3Actor SetMapper text3Mapper + [text3Actor GetProperty] SetColor .1 1 0 + text3Actor AddPosition 0 -4 0 + +# create graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 350 100 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor text0Actor +ren1 AddActor text1Actor +ren1 AddActor text2Actor +ren1 AddActor text3Actor +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 3 +ren1 SetBackground .1 .2 .4 + +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . diff --git a/Hybrid/Testing/Tcl/xyPlot.tcl b/Hybrid/Testing/Tcl/xyPlot.tcl new file mode 100644 index 0000000..86fd992 --- /dev/null +++ b/Hybrid/Testing/Tcl/xyPlot.tcl @@ -0,0 +1,175 @@ +package require vtk +package require vtkinteraction + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# create three line probes +vtkLineSource line + line SetResolution 30 + +vtkTransform transL1 + transL1 Translate 3.7 0.0 28.37 + transL1 Scale 5 5 5 + transL1 RotateY 90 +vtkTransformPolyDataFilter tf + tf SetInputConnection [line GetOutputPort] + tf SetTransform transL1 +vtkProbeFilter probe + probe SetInputConnection [tf GetOutputPort] + probe SetSource [pl3d GetOutput] + +vtkTransform transL2 + transL2 Translate 9.2 0.0 31.20 + transL2 Scale 5 5 5 + transL2 RotateY 90 +vtkTransformPolyDataFilter tf2 + tf2 SetInputConnection [line GetOutputPort] + tf2 SetTransform transL2 +vtkProbeFilter probe2 + probe2 SetInputConnection [tf2 GetOutputPort] + probe2 SetSource [pl3d GetOutput] + +vtkTransform transL3 + transL3 Translate 13.27 0.0 33.40 + transL3 Scale 4.5 4.5 4.5 + transL3 RotateY 90 +vtkTransformPolyDataFilter tf3 + tf3 SetInputConnection [line GetOutputPort] + tf3 SetTransform transL3 +vtkProbeFilter probe3 + probe3 SetInputConnection [tf3 GetOutputPort] + probe3 SetSource [pl3d GetOutput] + +vtkAppendPolyData appendF + appendF AddInput [probe GetPolyDataOutput] + appendF AddInput [probe2 GetPolyDataOutput] + appendF AddInput [probe3 GetPolyDataOutput] +vtkTubeFilter tuber + tuber SetInputConnection [appendF GetOutputPort] + tuber SetRadius 0.1 +vtkPolyDataMapper lineMapper + lineMapper SetInputConnection [tuber GetOutputPort] +vtkActor lineActor + lineActor SetMapper lineMapper + +# probe the line and plot it +vtkXYPlotActor xyplot + xyplot AddInput [probe GetOutput] + xyplot AddInput [probe2 GetOutput] + xyplot AddInput [probe3 GetOutput] + [xyplot GetPositionCoordinate] SetValue 0.0 0.67 0 + [xyplot GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot SetXValuesToArcLength + xyplot SetNumberOfXLabels 6 + xyplot SetTitle "Pressure vs. Arc Length (Zoomed View)" + xyplot SetXTitle "" + xyplot SetYTitle "P" + xyplot SetXRange .1 .35 + xyplot SetYRange .2 .4 + [xyplot GetProperty] SetColor 0 0 0 + [xyplot GetProperty] SetLineWidth 2 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot GetTitleTextProperty] + eval $tprop SetColor [[xyplot GetProperty] GetColor] + xyplot SetAxisTitleTextProperty $tprop + xyplot SetAxisLabelTextProperty $tprop + xyplot SetLabelFormat "%-#6.2f" + +vtkXYPlotActor xyplot2 + xyplot2 AddInput [probe GetOutput] + xyplot2 AddInput [probe2 GetOutput] + xyplot2 AddInput [probe3 GetOutput] + [xyplot2 GetPositionCoordinate] SetValue 0.00 0.33 0 + [xyplot2 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot2 SetXValuesToNormalizedArcLength + xyplot2 SetNumberOfXLabels 6 + xyplot2 SetTitle "Pressure vs. Normalized Arc Length" + xyplot2 SetXTitle "" + xyplot2 SetYTitle "P" + xyplot2 PlotPointsOn + xyplot2 PlotLinesOff + [xyplot2 GetProperty] SetColor 1 0 0 + [xyplot2 GetProperty] SetPointSize 2 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot2 GetTitleTextProperty] + eval $tprop SetColor [[xyplot2 GetProperty] GetColor] + xyplot2 SetAxisTitleTextProperty $tprop + xyplot2 SetAxisLabelTextProperty $tprop + xyplot2 SetLabelFormat [xyplot GetLabelFormat] + +vtkXYPlotActor xyplot3 + xyplot3 AddInput [probe GetOutput] + xyplot3 AddInput [probe2 GetOutput] + xyplot3 AddInput [probe3 GetOutput] + [xyplot3 GetPositionCoordinate] SetValue 0.0 0.0 0 + [xyplot3 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot3 SetXValuesToIndex + xyplot3 SetNumberOfXLabels 6 + xyplot3 SetTitle "Pressure vs. Point Id" + xyplot3 SetXTitle "Probe Length" + xyplot3 SetYTitle "P" + xyplot3 PlotPointsOn + [xyplot3 GetProperty] SetColor 0 0 1 + [xyplot3 GetProperty] SetPointSize 3 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot3 GetTitleTextProperty] + eval $tprop SetColor [[xyplot3 GetProperty] GetColor] + xyplot3 SetAxisTitleTextProperty $tprop + xyplot3 SetAxisLabelTextProperty $tprop + xyplot3 SetLabelFormat [xyplot GetLabelFormat] + +# draw an outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.6784 0.8471 0.9020 +ren1 SetViewport 0 0 .5 1 +ren1 AddActor outlineActor +ren1 AddActor lineActor + +ren2 SetBackground 1 1 1 +ren2 SetViewport 0.5 0.0 1.0 1.0 +ren2 AddActor2D xyplot +ren2 AddActor2D xyplot2 +ren2 AddActor2D xyplot3 +renWin SetSize 790 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.95297 100 + $cam1 SetFocalPoint 8.88908 0.595038 29.3342 + $cam1 SetPosition -12.3332 31.7479 41.2387 + $cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Hybrid/Testing/Tcl/xyPlot2.tcl b/Hybrid/Testing/Tcl/xyPlot2.tcl new file mode 100644 index 0000000..db377b7 --- /dev/null +++ b/Hybrid/Testing/Tcl/xyPlot2.tcl @@ -0,0 +1,224 @@ +package require vtk +package require vtkinteraction + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# create three line probes +vtkLineSource line + line SetResolution 30 + +vtkTransform transL1 + transL1 Translate 3.7 0.0 28.37 + transL1 Scale 5 5 5 + transL1 RotateY 90 +vtkTransformPolyDataFilter tf + tf SetInputConnection [line GetOutputPort] + tf SetTransform transL1 +vtkProbeFilter probe + probe SetInputConnection [tf GetOutputPort] + probe SetSource [pl3d GetOutput] + +vtkTransform transL2 + transL2 Translate 9.2 0.0 31.20 + transL2 Scale 5 5 5 + transL2 RotateY 90 +vtkTransformPolyDataFilter tf2 + tf2 SetInputConnection [line GetOutputPort] + tf2 SetTransform transL2 +vtkProbeFilter probe2 + probe2 SetInputConnection [tf2 GetOutputPort] + probe2 SetSource [pl3d GetOutput] + +vtkTransform transL3 + transL3 Translate 13.27 0.0 33.40 + transL3 Scale 4.5 4.5 4.5 + transL3 RotateY 90 +vtkTransformPolyDataFilter tf3 + tf3 SetInputConnection [line GetOutputPort] + tf3 SetTransform transL3 +vtkProbeFilter probe3 + probe3 SetInputConnection [tf3 GetOutputPort] + probe3 SetSource [pl3d GetOutput] + +vtkAppendPolyData appendF + appendF AddInput [probe GetPolyDataOutput] + appendF AddInput [probe2 GetPolyDataOutput] + appendF AddInput [probe3 GetPolyDataOutput] +vtkTubeFilter tuber + tuber SetInputConnection [appendF GetOutputPort] + tuber SetRadius 0.1 +vtkPolyDataMapper lineMapper + lineMapper SetInputConnection [tuber GetOutputPort] +vtkActor lineActor + lineActor SetMapper lineMapper + +# probe the line and plot it +vtkGlyphSource2D triangle + triangle SetGlyphTypeToTriangle +vtkGlyphSource2D cross + cross SetGlyphTypeToCross +vtkXYPlotActor xyplot + xyplot AddInput [probe GetOutput] + xyplot AddInput [probe2 GetOutput] + xyplot AddInput [probe3 GetOutput] + [xyplot GetPositionCoordinate] SetValue 0.0 0.67 0 + [xyplot GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot SetXValuesToArcLength + xyplot SetNumberOfXLabels 6 + xyplot SetTitle "Pressure vs. Arc Length (Zoomed View)" + xyplot SetXTitle "" + xyplot SetYTitle "P" + xyplot SetXRange .1 .35 + xyplot SetYRange .2 .4 + [xyplot GetProperty] SetColor 0 0 0 + xyplot PlotLinesOn + [xyplot GetProperty] SetLineWidth 1 + xyplot PlotPointsOn + [xyplot GetProperty] SetPointSize 3 + xyplot LegendOn + xyplot SetPlotSymbol 2 [triangle GetOutput] + xyplot SetPlotColor 2 0 0 1 + xyplot SetPlotColor 1 0 0 0 + xyplot SetPlotColor 0 0 0 0 + xyplot SetGlyphSize 0.025 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot GetTitleTextProperty] + eval $tprop SetColor [[xyplot GetProperty] GetColor] + xyplot SetAxisTitleTextProperty $tprop + xyplot SetAxisLabelTextProperty $tprop + xyplot SetLabelFormat "%-#6.2f" + +vtkSphereSource vertexGlyph +vtkXYPlotActor xyplot2 + xyplot2 AddInput [probe GetOutput] + xyplot2 AddInput [probe2 GetOutput] + xyplot2 AddInput [probe3 GetOutput] + [xyplot2 GetPositionCoordinate] SetValue 0.00 0.33 0 + [xyplot2 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot2 SetXValuesToNormalizedArcLength + xyplot2 SetNumberOfXLabels 6 + xyplot2 SetXRange 0.2 1.0 + xyplot2 SetTitle "VTK Quality vs. Alcohol Consumption" + xyplot2 SetXTitle "" + xyplot2 SetYTitle "A" + xyplot2 PlotPointsOn + xyplot2 PlotLinesOff + xyplot2 LegendOn + xyplot2 SetLegendPosition 0.4 0.6 + xyplot2 SetLegendPosition2 0.40 0.25 + [xyplot2 GetProperty] SetColor 1 0 0 + [xyplot2 GetProperty] SetPointSize 2 + xyplot2 SetPlotSymbol 0 [vertexGlyph GetOutput] + xyplot2 SetPlotLabel 0 "Ken's Mudslide Consumption" + xyplot2 SetPlotColor 0 1 0 0 + xyplot2 SetPlotSymbol 1 [cross GetOutput] + xyplot2 SetPlotColor 1 1 0 1 + xyplot2 SetPlotLabel 1 "Bill's Beer Consumption" + xyplot2 SetPlotSymbol 2 [triangle GetOutput] + xyplot2 SetPlotColor 2 0 0 1 + xyplot2 SetPlotLabel 2 "VTK Quality" + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot2 GetTitleTextProperty] + eval $tprop SetColor [[xyplot2 GetProperty] GetColor] + xyplot2 SetAxisTitleTextProperty $tprop + xyplot2 SetAxisLabelTextProperty $tprop + xyplot2 SetLabelFormat [xyplot GetLabelFormat] + +#Okay exercise data object stuff +vtkDataSetToDataObjectFilter ds2do + ds2do SetInputConnection [probe GetOutputPort] +vtkDataSetToDataObjectFilter ds2do2 + ds2do2 SetInputConnection [probe GetOutputPort] +vtkDataSetToDataObjectFilter ds2do3 + ds2do3 SetInputConnection [probe GetOutputPort] +vtkXYPlotActor xyplot3 + xyplot3 AddDataObjectInput [ds2do GetOutput] + xyplot3 SetDataObjectXComponent 0 2 + xyplot3 SetDataObjectYComponent 0 5 + xyplot3 SetPlotColor 0 1 0 0 + xyplot3 SetPlotLabel 0 "Mx" + xyplot3 AddDataObjectInput [ds2do2 GetOutput] + xyplot3 SetDataObjectXComponent 1 2 + xyplot3 SetDataObjectYComponent 1 6 + xyplot3 SetPlotColor 1 0 1 0 + xyplot3 SetPlotLabel 1 "My" + xyplot3 AddDataObjectInput [ds2do3 GetOutput] + xyplot3 SetDataObjectXComponent 2 2 + xyplot3 SetDataObjectYComponent 2 7 + xyplot3 SetPlotColor 2 0 0 1 + xyplot3 SetPlotLabel 2 "Mz" + [xyplot3 GetPositionCoordinate] SetValue 0.0 0.0 0 + [xyplot3 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot3 SetXValuesToIndex + xyplot3 SetNumberOfXLabels 6 + xyplot3 SetTitle "Momentum Component vs. Point Id" + xyplot3 SetXTitle "Point Id" + xyplot3 SetYTitle "M" + xyplot3 PlotPointsOn + [xyplot3 GetProperty] SetColor 0 0 1 + [xyplot3 GetProperty] SetPointSize 3 + xyplot3 LegendOn + xyplot3 SetLegendPosition 0.8 0.28 + xyplot3 SetLegendPosition2 0.20 0.20 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot3 GetTitleTextProperty] + eval $tprop SetColor [[xyplot3 GetProperty] GetColor] + xyplot3 SetAxisTitleTextProperty $tprop + xyplot3 SetAxisLabelTextProperty $tprop + xyplot3 SetLabelFormat "%4.f" + +# draw an outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.6784 0.8471 0.9020 +ren1 SetViewport 0 0 .5 1 +ren1 AddActor outlineActor +ren1 AddActor lineActor + +ren2 SetBackground 1 1 1 +ren2 SetViewport 0.5 0.0 1.0 1.0 +ren2 AddActor2D xyplot +ren2 AddActor2D xyplot2 +ren2 AddActor2D xyplot3 +renWin SetSize 790 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.95297 100 + $cam1 SetFocalPoint 8.88908 0.595038 29.3342 + $cam1 SetPosition -12.3332 31.7479 41.2387 + $cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/xyPlot3.tcl b/Hybrid/Testing/Tcl/xyPlot3.tcl new file mode 100644 index 0000000..1610aad --- /dev/null +++ b/Hybrid/Testing/Tcl/xyPlot3.tcl @@ -0,0 +1,213 @@ +package require vtk +package require vtkinteraction + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# create three line probes +vtkLineSource line + line SetResolution 30 + +vtkTransform transL1 + transL1 Translate 3.7 0.0 28.37 + transL1 Scale 5 5 5 + transL1 RotateY 90 +vtkTransformPolyDataFilter tf + tf SetInputConnection [line GetOutputPort] + tf SetTransform transL1 +vtkProbeFilter probe + probe SetInputConnection [tf GetOutputPort] + probe SetSource [pl3d GetOutput] + +vtkTransform transL2 + transL2 Translate 9.2 0.0 31.20 + transL2 Scale 5 5 5 + transL2 RotateY 90 +vtkTransformPolyDataFilter tf2 + tf2 SetInputConnection [line GetOutputPort] + tf2 SetTransform transL2 +vtkProbeFilter probe2 + probe2 SetInputConnection [tf2 GetOutputPort] + probe2 SetSource [pl3d GetOutput] + +vtkTransform transL3 + transL3 Translate 13.27 0.0 33.40 + transL3 Scale 4.5 4.5 4.5 + transL3 RotateY 90 +vtkTransformPolyDataFilter tf3 + tf3 SetInputConnection [line GetOutputPort] + tf3 SetTransform transL3 +vtkProbeFilter probe3 + probe3 SetInputConnection [tf3 GetOutputPort] + probe3 SetSource [pl3d GetOutput] + +vtkAppendPolyData appendF + appendF AddInput [probe GetPolyDataOutput] + appendF AddInput [probe2 GetPolyDataOutput] + appendF AddInput [probe3 GetPolyDataOutput] +vtkTubeFilter tuber + tuber SetInputConnection [appendF GetOutputPort] + tuber SetRadius 0.1 +vtkPolyDataMapper lineMapper + lineMapper SetInputConnection [tuber GetOutputPort] +vtkActor lineActor + lineActor SetMapper lineMapper + +# probe the line and plot it +vtkGlyphSource2D triangle + triangle SetGlyphTypeToTriangle +vtkGlyphSource2D cross + cross SetGlyphTypeToCross +vtkXYPlotActor xyplot + xyplot AddInput [probe GetOutput] + xyplot AddInput [probe2 GetOutput] + xyplot AddInput [probe3 GetOutput] + [xyplot GetPositionCoordinate] SetValue 0.0 0.5 0 + [xyplot GetPosition2Coordinate] SetValue 1.0 0.5 0;#relative to Position + xyplot SetXValuesToValue + xyplot SetPointComponent 0 2 + xyplot SetPointComponent 1 2 + xyplot SetPointComponent 2 2 + xyplot LogxOn + xyplot SetNumberOfXLabels 6 + xyplot SetTitle "Pressure vs. Log10 Probe Z-Value" + xyplot SetXTitle "" + xyplot SetYTitle "P" + + xyplot PlotCurveLinesOn + xyplot PlotCurvePointsOn + + xyplot SetPlotLines 0 1 + xyplot SetPlotLines 1 0 + xyplot SetPlotLines 2 1 + + xyplot SetPlotPoints 0 0 + xyplot SetPlotPoints 1 1 + xyplot SetPlotPoints 2 1 + + [xyplot GetProperty] SetColor 0 0 0 + + [xyplot GetProperty] SetLineWidth 1 + + [xyplot GetProperty] SetPointSize 3 + + xyplot SetPlotSymbol 2 [triangle GetOutput] + xyplot SetPlotColor 2 0 0 1 + xyplot SetGlyphSize 0.025 + + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot GetTitleTextProperty] + eval $tprop SetColor [[xyplot GetProperty] GetColor] + xyplot SetAxisTitleTextProperty $tprop + xyplot SetAxisLabelTextProperty $tprop + + xyplot SetLabelFormat "%-#6.2f" + +#Okay exercise data object stuff +vtkDataSetToDataObjectFilter ds2do + ds2do SetInputConnection [probe GetOutputPort] +vtkDataSetToDataObjectFilter ds2do2 + ds2do2 SetInputConnection [probe GetOutputPort] +vtkDataSetToDataObjectFilter ds2do3 + ds2do3 SetInputConnection [probe GetOutputPort] +vtkXYPlotActor xyplot3 + xyplot3 AddDataObjectInput [ds2do GetOutput] + xyplot3 SetDataObjectXComponent 0 2 + xyplot3 SetDataObjectYComponent 0 5 + xyplot3 SetPlotColor 0 1 0 0 + xyplot3 SetPlotLabel 0 "Mx" + xyplot3 AddDataObjectInput [ds2do2 GetOutput] + xyplot3 SetDataObjectXComponent 1 2 + xyplot3 SetDataObjectYComponent 1 6 + xyplot3 SetPlotColor 1 0 1 0 + xyplot3 SetPlotLabel 1 "My" + xyplot3 AddDataObjectInput [ds2do3 GetOutput] + xyplot3 SetDataObjectXComponent 2 2 + xyplot3 SetDataObjectYComponent 2 7 + xyplot3 SetPlotColor 2 0 0 1 + xyplot3 SetPlotLabel 2 "Mz" + [xyplot3 GetPositionCoordinate] SetValue 0.0 0.0 0 + [xyplot3 GetPosition2Coordinate] SetValue 1.0 0.5 0;#relative to Position + xyplot3 SetXValuesToValue + xyplot3 SetNumberOfXLabels 6 + xyplot3 SetTitle "Momentum Component vs. Log10 Probe Z-Value" + xyplot3 SetXTitle "Log10 Probe Z-Value" + xyplot3 SetYTitle "M" + + [xyplot3 GetProperty] SetColor 0 0 1 + [xyplot3 GetProperty] SetPointSize 5 + + xyplot3 PlotCurveLinesOn + xyplot3 PlotCurvePointsOn + + xyplot3 SetPlotLines 0 1 + xyplot3 SetPlotLines 1 0 + xyplot3 SetPlotLines 2 1 + + xyplot3 SetPlotPoints 0 0 + xyplot3 SetPlotPoints 1 1 + xyplot3 SetPlotPoints 2 1 + + xyplot3 LogxOn + + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot3 GetTitleTextProperty] + eval $tprop SetColor [[xyplot3 GetProperty] GetColor] + xyplot3 SetAxisTitleTextProperty $tprop + xyplot3 SetAxisLabelTextProperty $tprop + + [xyplot3 GetYAxisActor2D] SetLabelFormat "%4.f" + [xyplot3 GetXAxisActor2D] SetLabelFormat "%-#6.2f" + +# draw an outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.6784 0.8471 0.9020 +ren1 SetViewport 0 0 .5 1 +ren1 AddActor outlineActor +ren1 AddActor lineActor + +ren2 SetBackground 1 1 1 +ren2 SetViewport 0.5 0.0 1.0 1.0 +ren2 AddActor2D xyplot +ren2 AddActor2D xyplot3 +renWin SetSize 790 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.95297 100 + $cam1 SetFocalPoint 8.88908 0.595038 29.3342 + $cam1 SetPosition -12.3332 31.7479 41.2387 + $cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/Testing/Tcl/xyPlot4.tcl b/Hybrid/Testing/Tcl/xyPlot4.tcl new file mode 100644 index 0000000..aaeb7cb --- /dev/null +++ b/Hybrid/Testing/Tcl/xyPlot4.tcl @@ -0,0 +1,220 @@ +package require vtk +package require vtkinteraction + +# This version of the script +# test ploting arbitrary array components (Momentum) +# without using the dataset to data object filter +# and its cryptic indexing of arrays. + +# create pipeline +# +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 100 + pl3d SetVectorFunctionNumber 202 + pl3d Update + +# create three line probes +vtkLineSource line + line SetResolution 30 + +vtkTransform transL1 + transL1 Translate 3.7 0.0 28.37 + transL1 Scale 5 5 5 + transL1 RotateY 90 +vtkTransformPolyDataFilter tf + tf SetInputConnection [line GetOutputPort] + tf SetTransform transL1 +vtkProbeFilter probe + probe SetInputConnection [tf GetOutputPort] + probe SetSource [pl3d GetOutput] + +vtkTransform transL2 + transL2 Translate 9.2 0.0 31.20 + transL2 Scale 5 5 5 + transL2 RotateY 90 +vtkTransformPolyDataFilter tf2 + tf2 SetInputConnection [line GetOutputPort] + tf2 SetTransform transL2 +vtkProbeFilter probe2 + probe2 SetInputConnection [tf2 GetOutputPort] + probe2 SetSource [pl3d GetOutput] + +vtkTransform transL3 + transL3 Translate 13.27 0.0 33.40 + transL3 Scale 4.5 4.5 4.5 + transL3 RotateY 90 +vtkTransformPolyDataFilter tf3 + tf3 SetInputConnection [line GetOutputPort] + tf3 SetTransform transL3 +vtkProbeFilter probe3 + probe3 SetInputConnection [tf3 GetOutputPort] + probe3 SetSource [pl3d GetOutput] + +vtkAppendPolyData appendF + appendF AddInput [probe GetPolyDataOutput] + appendF AddInput [probe2 GetPolyDataOutput] + appendF AddInput [probe3 GetPolyDataOutput] +vtkTubeFilter tuber + tuber SetInputConnection [appendF GetOutputPort] + tuber SetRadius 0.1 +vtkPolyDataMapper lineMapper + lineMapper SetInputConnection [tuber GetOutputPort] +vtkActor lineActor + lineActor SetMapper lineMapper + +# probe the line and plot it +vtkGlyphSource2D triangle + triangle SetGlyphTypeToTriangle +vtkGlyphSource2D cross + cross SetGlyphTypeToCross +vtkXYPlotActor xyplot + xyplot AddInput [probe GetOutput] + xyplot AddInput [probe2 GetOutput] + xyplot AddInput [probe3 GetOutput] + [xyplot GetPositionCoordinate] SetValue 0.0 0.67 0 + [xyplot GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot SetXValuesToArcLength + xyplot SetNumberOfXLabels 6 + xyplot SetTitle "Pressure vs. Arc Length (Zoomed View)" + xyplot SetXTitle "" + xyplot SetYTitle "P" + xyplot SetXRange .1 .35 + xyplot SetYRange .2 .4 + [xyplot GetProperty] SetColor 0 0 0 + xyplot PlotLinesOn + [xyplot GetProperty] SetLineWidth 1 + xyplot PlotPointsOn + [xyplot GetProperty] SetPointSize 3 + xyplot LegendOn + xyplot SetPlotSymbol 2 [triangle GetOutput] + xyplot SetPlotColor 2 0 0 1 + xyplot SetPlotColor 1 0 0 0 + xyplot SetPlotColor 0 0 0 0 + xyplot SetGlyphSize 0.025 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot GetTitleTextProperty] + eval $tprop SetColor [[xyplot GetProperty] GetColor] + xyplot SetAxisTitleTextProperty $tprop + xyplot SetAxisLabelTextProperty $tprop + xyplot SetLabelFormat "%-#6.2f" + +vtkSphereSource vertexGlyph +vtkXYPlotActor xyplot2 + xyplot2 AddInput [probe GetOutput] + xyplot2 AddInput [probe2 GetOutput] + xyplot2 AddInput [probe3 GetOutput] + [xyplot2 GetPositionCoordinate] SetValue 0.00 0.33 0 + [xyplot2 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot2 SetXValuesToNormalizedArcLength + xyplot2 SetNumberOfXLabels 6 + xyplot2 SetXRange 0.2 1.0 + xyplot2 SetTitle "VTK Quality vs. Alcohol Consumption" + xyplot2 SetXTitle "" + xyplot2 SetYTitle "A" + xyplot2 PlotPointsOn + xyplot2 PlotLinesOff + xyplot2 LegendOn + xyplot2 SetLegendPosition 0.4 0.6 + xyplot2 SetLegendPosition2 0.40 0.25 + [xyplot2 GetProperty] SetColor 1 0 0 + [xyplot2 GetProperty] SetPointSize 2 + xyplot2 SetPlotSymbol 0 [vertexGlyph GetOutput] + xyplot2 SetPlotLabel 0 "Ken's Mudslide Consumption" + xyplot2 SetPlotColor 0 1 0 0 + xyplot2 SetPlotSymbol 1 [cross GetOutput] + xyplot2 SetPlotColor 1 1 0 1 + xyplot2 SetPlotLabel 1 "Bill's Beer Consumption" + xyplot2 SetPlotSymbol 2 [triangle GetOutput] + xyplot2 SetPlotColor 2 0 0 1 + xyplot2 SetPlotLabel 2 "VTK Quality" + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot2 GetTitleTextProperty] + eval $tprop SetColor [[xyplot2 GetProperty] GetColor] + xyplot2 SetAxisTitleTextProperty $tprop + xyplot2 SetAxisLabelTextProperty $tprop + xyplot2 SetLabelFormat [xyplot GetLabelFormat] + +vtkXYPlotActor xyplot3 + xyplot3 AddInput [probe GetOutput] "Momentum" 0 + xyplot3 AddInput [probe GetOutput] "Density" 0 + xyplot3 AddInput [probe GetOutput] "Momentum" 1 + xyplot3 AddInput [probe GetOutput] "Momentum" 2 + xyplot3 RemoveInput [probe GetOutput] "Density" 0 + xyplot3 SetPlotLabel 0 "Mx" + xyplot3 SetPlotColor 0 1 0 0 + xyplot3 SetPlotLabel 1 "My" + xyplot3 SetPlotColor 1 0 1 0 + xyplot3 SetPlotColor 2 0 0 1 + xyplot3 SetPlotLabel 2 "Mz" + #xyplot3 SetPlotColor 3 1 0 1 + #xyplot3 SetPlotLabel 3 "D" + [xyplot3 GetPositionCoordinate] SetValue 0.0 0.0 0 + [xyplot3 GetPosition2Coordinate] SetValue 1.0 0.33 0;#relative to Position + xyplot3 SetXValuesToIndex + xyplot3 SetNumberOfXLabels 6 + xyplot3 SetTitle "Momentum Component vs. Point Id" + xyplot3 SetXTitle "Point Id" + xyplot3 SetYTitle "M" + xyplot3 PlotPointsOn + [xyplot3 GetProperty] SetColor 0 0 1 + [xyplot3 GetProperty] SetPointSize 3 + xyplot3 LegendOn + xyplot3 SetLegendPosition 0.8 0.28 + xyplot3 SetLegendPosition2 0.20 0.20 + # Set text prop color (same color for backward compat with test) + # Assign same object to all text props + set tprop [xyplot3 GetTitleTextProperty] + eval $tprop SetColor [[xyplot3 GetProperty] GetColor] + xyplot3 SetAxisTitleTextProperty $tprop + xyplot3 SetAxisLabelTextProperty $tprop + xyplot3 SetLabelFormat "%4.f" + +# draw an outline +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + [outlineActor GetProperty] SetColor 0 0 0 + +# Create graphics stuff +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.6784 0.8471 0.9020 +ren1 SetViewport 0 0 .5 1 +ren1 AddActor outlineActor +ren1 AddActor lineActor + +ren2 SetBackground 1 1 1 +ren2 SetViewport 0.5 0.0 1.0 1.0 +ren2 AddActor2D xyplot +ren2 AddActor2D xyplot2 +ren2 AddActor2D xyplot3 +renWin SetSize 790 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.95297 100 + $cam1 SetFocalPoint 8.88908 0.595038 29.3342 + $cam1 SetPosition -12.3332 31.7479 41.2387 + $cam1 SetViewUp 0.060772 -0.319905 0.945498 +iren Initialize +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Hybrid/vtk3DS.h b/Hybrid/vtk3DS.h new file mode 100644 index 0000000..1e0a585 --- /dev/null +++ b/Hybrid/vtk3DS.h @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk3DS.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include + +class vtkLight; +class vtkCamera; +class vtkProperty; + +typedef float vtk3DSVector[3]; + +/* A generic list type */ +#define VTK_LIST_INSERT(root, node) list_insert ((vtk3DSList **)&root, reinterpret_cast(node)) +#define VTK_LIST_FIND(root, name) list_find ((vtk3DSList **)&root, name) +#define VTK_LIST_DELETE(root, node) list_delete ((vtk3DSList **)&root, (vtk3DSList *)node) +#define VTK_LIST_KILL(root) list_kill ((vtk3DSList **)&root) + +#define VTK_LIST_FIELDS \ + char name[80]; \ + void *next; + + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned int dword; + +typedef struct { + VTK_LIST_FIELDS +} vtk3DSList; + + +typedef struct { + int a, b, c; +} vtk3DSFace; + + +typedef struct { + float red, green, blue; +} vtk3DSColour; + + +/* Omni light command */ +typedef struct { + VTK_LIST_FIELDS + + vtk3DSVector pos; /* Light position */ + vtk3DSColour col; /* Light colour */ + vtkLight *aLight; +} vtk3DSOmniLight; + + +/* Spotlight command */ +typedef struct { + VTK_LIST_FIELDS + + vtk3DSVector pos; /* Spotlight position */ + vtk3DSVector target; /* Spotlight target location */ + vtk3DSColour col; /* Spotlight colour */ + float hotspot; /* Hotspot angle (degrees) */ + float falloff; /* Falloff angle (degrees) */ + int shadow_flag; /* Shadow flag (not used) */ + vtkLight *aLight; +} vtk3DSSpotLight; + + +/* Camera command */ +typedef struct { + VTK_LIST_FIELDS + + vtk3DSVector pos; /* Camera location */ + vtk3DSVector target; /* Camera target */ + float bank; /* Banking angle (degrees) */ + float lens; /* Camera lens size (mm) */ + vtkCamera *aCamera; +} vtk3DSCamera; + + +/* Material list */ +typedef struct { + VTK_LIST_FIELDS + + int external; /* Externally defined material? */ +} vtk3DSMaterial; + + +/* Object summary */ +typedef struct { + VTK_LIST_FIELDS + + vtk3DSVector center; /* Min value of object extents */ + vtk3DSVector lengths; /* Max value of object extents */ +} vtk3DSSummary; + + +/* Material property */ +typedef struct { + VTK_LIST_FIELDS + + vtk3DSColour ambient; + vtk3DSColour diffuse; + vtk3DSColour specular; + float shininess; + float transparency; + float reflection; + int self_illum; + char tex_map[40]; + float tex_strength; + char bump_map[40]; + float bump_strength; + vtkProperty *aProperty; +} vtk3DSMatProp; + + + +class vtkActor; +class vtkPolyDataMapper; +class vtkPolyDataNormals; +class vtkStripper; +class vtkPoints; +class vtkCellArray; +class vtkPolyData; + +/* A mesh object */ +typedef struct { + VTK_LIST_FIELDS + + int vertices; /* Number of vertices */ + vtk3DSVector *vertex; /* List of object vertices */ + + int faces; /* Number of faces */ + vtk3DSFace *face; /* List of object faces */ + vtk3DSMaterial **mtl; /* Materials for each face */ + + int hidden; /* Hidden flag */ + int shadow; /* Shadow flag */ + vtkActor *anActor; + vtkPolyDataMapper *aMapper; + vtkPolyDataNormals *aNormals; + vtkStripper *aStripper; + vtkPoints *aPoints; + vtkCellArray *aCellArray; + vtkPolyData *aPolyData; + +} vtk3DSMesh; + + +typedef struct { + dword start; + dword end; + dword length; + word tag; +} vtk3DSChunk; + + +typedef struct { + byte red; + byte green; + byte blue; +} vtk3DSColour_24; + + + diff --git a/Hybrid/vtk3DSImporter.cxx b/Hybrid/vtk3DSImporter.cxx new file mode 100644 index 0000000..4b3bac6 --- /dev/null +++ b/Hybrid/vtk3DSImporter.cxx @@ -0,0 +1,1294 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk3DSImporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtk3DSImporter.h" + +#include "vtkActor.h" +#include "vtkByteSwap.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkLight.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyDataNormals.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkStripper.h" + +vtkCxxRevisionMacro(vtk3DSImporter, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtk3DSImporter); + +static vtk3DSColour Black = {0.0, 0.0, 0.0}; +static char obj_name[80] = ""; +static vtk3DSColour fog_colour = {0.0, 0.0, 0.0}; +static vtk3DSColour col = {0.0, 0.0, 0.0}; +static vtk3DSColour global_amb = {0.1, 0.1, 0.1}; +static vtk3DSVector pos = {0.0, 0.0, 0.0}; +static vtk3DSVector target = {0.0, 0.0, 0.0}; +static float hotspot = -1; +static float falloff = -1; +/* Default material property */ +static vtk3DSMatProp DefaultMaterial = + { "Default", NULL, + {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, + 70.0, // shininess + 0.0, // transparency + 0.0, // reflection + 0,// self illumination + "", // tex_map + 0.0, // tex_strength + "", // bump_map + 0.0, // bump_strength + NULL};// vtkProperty + +static void cleanup_name (char *); +static void list_insert (vtk3DSList **root, vtk3DSList *new_node); +static void *list_find (vtk3DSList **root, const char *name); +static void list_kill (vtk3DSList **root); +static vtk3DSMatProp *create_mprop (void); +static vtk3DSMesh *create_mesh (char *name, int vertices, int faces); +static int parse_3ds_file (vtk3DSImporter *importer); +static void parse_3ds (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static void parse_mdata (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static void parse_fog (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static void parse_fog_bgnd (vtk3DSImporter *importer); +static void parse_mat_entry (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static char *parse_mapname (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static void parse_named_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static void parse_n_tri_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static void parse_point_array (vtk3DSImporter *importer, vtk3DSMesh *mesh); +static void parse_face_array (vtk3DSImporter *importer, vtk3DSMesh *mesh, vtk3DSChunk *mainchunk); +static void parse_msh_mat_group (vtk3DSImporter *importer, vtk3DSMesh *mesh); +static void parse_smooth_group (vtk3DSImporter *importer); +static void parse_mesh_matrix (vtk3DSImporter *importer, vtk3DSMesh *mesh); +static void parse_n_direct_light (vtk3DSImporter *importer, vtk3DSChunk *mainchunk); +static void parse_dl_spotlight (vtk3DSImporter *importer); +static void parse_n_camera (vtk3DSImporter *importer); +static void parse_colour (vtk3DSImporter *importer, vtk3DSColour *colour); +static void parse_colour_f (vtk3DSImporter *importer, vtk3DSColour *colour); +static void parse_colour_24 (vtk3DSImporter *importer, vtk3DSColour_24 *colour); +static float parse_percentage (vtk3DSImporter *importer); +static short parse_int_percentage (vtk3DSImporter *importer); +static float parse_float_percentage (vtk3DSImporter *importer); +static vtk3DSMaterial *update_materials (vtk3DSImporter *importer, const char *new_material, int ext); +static void start_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk); +static void end_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk); +static byte read_byte (vtk3DSImporter *importer); +static word read_word (vtk3DSImporter *importer); +static dword read_dword (vtk3DSImporter *importer); +static float read_float (vtk3DSImporter *importer); +static void read_point (vtk3DSImporter *importer, vtk3DSVector v); +static char *read_string (vtk3DSImporter *importer); + +vtk3DSImporter::vtk3DSImporter () +{ + this->OmniList = NULL; + this->SpotLightList = NULL; + this->CameraList = NULL; + this->MeshList = NULL; + this->MaterialList = NULL; + this->MatPropList = NULL; + this->FileName = NULL; + this->FileFD = NULL; + this->ComputeNormals = 0; +} + +int vtk3DSImporter::ImportBegin () +{ + vtkDebugMacro(<< "Opening import file as binary"); + this->FileFD = fopen (this->FileName, "rb"); + if (this->FileFD == NULL) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + return 0; + } + return this->Read3DS (); +} + +void vtk3DSImporter::ImportEnd () +{ + vtkDebugMacro(<<"Closing import file"); + if ( this->FileFD != NULL ) + { + fclose (this->FileFD); + } + this->FileFD = NULL; +} + +int vtk3DSImporter::Read3DS () +{ + vtk3DSMatProp *aMaterial; + + if (parse_3ds_file (this) == 0) + { + vtkErrorMacro (<< "Error readings .3ds file: " << this->FileName << "\n"); + return 0; + } + + + // create a vtk3DSMatProp and fill if in with default + aMaterial = (vtk3DSMatProp *) malloc (sizeof (vtk3DSMatProp)); + *aMaterial = DefaultMaterial; + aMaterial->aProperty = vtkProperty::New (); + VTK_LIST_INSERT (this->MatPropList, aMaterial); + return 1; +} + +void vtk3DSImporter::ImportActors (vtkRenderer *renderer) +{ + vtk3DSMatProp *material; + vtk3DSMesh *mesh; + vtkStripper *polyStripper; + vtkPolyDataNormals *polyNormals; + vtkPolyDataMapper *polyMapper; + vtkPolyData *polyData; + vtkActor *actor; + + // walk the list of meshes, creating actors + for (mesh = this->MeshList; mesh != (vtk3DSMesh *) NULL; + mesh = (vtk3DSMesh *) mesh->next) + { + if (mesh->faces == 0) + { + vtkWarningMacro (<< "part " << mesh->name << " has zero faces... skipping\n"); + continue; + } + + polyData = this->GeneratePolyData (mesh); + mesh->aMapper = polyMapper = vtkPolyDataMapper::New (); + mesh->aStripper = polyStripper = vtkStripper::New (); + + // if ComputeNormals is on, insert a vtkPolyDataNormals filter + if (this->ComputeNormals) + { + mesh->aNormals = polyNormals = vtkPolyDataNormals::New (); + polyNormals->SetInput (polyData); + polyStripper->SetInput (polyNormals->GetOutput ()); + } + else + { + polyStripper->SetInput (polyData); + } + + polyMapper->SetInput (polyStripper->GetOutput ()); + vtkDebugMacro (<< "Importing Actor: " << mesh->name); + mesh->anActor = actor = vtkActor::New (); + actor->SetMapper (polyMapper); + material = (vtk3DSMatProp *)VTK_LIST_FIND(this->MatPropList, mesh->mtl[0]->name); + actor->SetProperty (material->aProperty); + renderer->AddActor (actor); + } +} + +vtkPolyData *vtk3DSImporter::GeneratePolyData (vtk3DSMesh *mesh) +{ + int i; + vtk3DSFace *face; + vtkCellArray *triangles; + vtkPoints *vertices; + vtkPolyData *polyData; + + face = mesh->face; + mesh->aCellArray = triangles = vtkCellArray::New (); + triangles->Allocate(mesh->faces * 3); + for (i = 0; i < mesh->faces; i++, face++) + { + triangles->InsertNextCell (3); + triangles->InsertCellPoint (face->a); + triangles->InsertCellPoint (face->b); + triangles->InsertCellPoint (face->c); + } + + mesh->aPoints = vertices = vtkPoints::New (); + vertices->Allocate(mesh->vertices); + for (i = 0; i < mesh->vertices; i++) + { + vertices->InsertPoint (i, (float *) mesh->vertex[i]); + } + mesh->aPolyData = polyData = vtkPolyData::New (); + polyData->SetPolys (triangles); + polyData->SetPoints (vertices); + + return polyData; +} + +void vtk3DSImporter::ImportCameras (vtkRenderer *renderer) +{ + vtkCamera *aCamera; + vtk3DSCamera *camera; + + // walk the list of cameras and create vtk cameras + for (camera = this->CameraList; camera != (vtk3DSCamera *) NULL; camera = (vtk3DSCamera *) camera->next) + { + camera->aCamera = aCamera = vtkCamera::New (); + aCamera->SetPosition (camera->pos[0], camera->pos[1], camera->pos[2]); + aCamera->SetFocalPoint (camera->target[0], camera->target[1], camera->target[2]); + aCamera->SetViewUp (0, 0, 1); + aCamera->SetClippingRange (.1,10000); + aCamera->Roll (camera->bank); + renderer->SetActiveCamera (aCamera); + vtkDebugMacro (<< "Importing Camera: " << camera->name); + } +} + +void vtk3DSImporter::ImportLights (vtkRenderer *renderer) +{ + vtk3DSOmniLight *omniLight; + vtk3DSSpotLight *spotLight; + vtkLight *aLight; + + // just walk the list of omni lights, creating vtk lights + for (omniLight = this->OmniList; omniLight != (vtk3DSOmniLight *) NULL; + omniLight = (vtk3DSOmniLight *) omniLight->next) + { + omniLight->aLight = aLight = vtkLight::New (); + aLight->SetPosition (omniLight->pos[0], + omniLight->pos[1], + omniLight->pos[2]); + aLight->SetFocalPoint (0, 0, 0); + aLight->SetColor (omniLight->col.red, + omniLight->col.green, + omniLight->col.blue); + renderer->AddLight (aLight); + vtkDebugMacro (<< "Importing Omni Light: " << omniLight->name); + } + + // now walk the list of spot lights, creating vtk lights + for (spotLight = this->SpotLightList; spotLight != (vtk3DSSpotLight *) NULL; + spotLight = (vtk3DSSpotLight *) spotLight->next) + { + spotLight->aLight = aLight = vtkLight::New (); + aLight->PositionalOn (); + aLight->SetPosition (spotLight->pos[0], + spotLight->pos[1], + spotLight->pos[2]); + aLight->SetFocalPoint (spotLight->target[0], + spotLight->target[1], + spotLight->target[2]); + aLight->SetColor (spotLight->col.red, + spotLight->col.green, + spotLight->col.blue); + aLight->SetConeAngle (spotLight->falloff); + renderer->AddLight (aLight); + vtkDebugMacro (<< "Importing Spot Light: " << spotLight->name); + } +} + +void vtk3DSImporter::ImportProperties (vtkRenderer *vtkNotUsed(renderer)) +{ + float amb = 0.1, dif = 0.9; + float dist_white, dist_diff, phong, phong_size; + vtkProperty *property; + vtk3DSMatProp *m; + + // just walk the list of material properties, creating vtk properties + for (m = this->MatPropList; m != (vtk3DSMatProp *) NULL; m = (vtk3DSMatProp *) m->next) + { + if (m->self_illum) + { + amb = 0.9; + dif = 0.1; + } + + dist_white = fabs(1.0 - m->specular.red) + + fabs(1.0 - m->specular.green) + + fabs(1.0 - m->specular.blue); + + dist_diff = fabs(m->diffuse.red - m->specular.red) + + fabs(m->diffuse.green - m->specular.green) + + fabs(m->diffuse.blue - m->specular.blue); + + if (dist_diff < dist_white) + { + dif = .1; amb = .8; + } + + phong_size = 0.7*m->shininess; + if (phong_size < 1.0) + { + phong_size = 1.0; + } + if (phong_size > 30.0) + { + phong = 1.0; + } + else + { + phong = phong_size/30.0; + } + property = m->aProperty; + property->SetAmbientColor(m->ambient.red, m->ambient.green, m->ambient.blue); + property->SetAmbient (amb); + property->SetDiffuseColor(m->diffuse.red, m->diffuse.green, m->diffuse.blue); + property->SetDiffuse (dif); + property->SetSpecularColor(m->specular.red, m->specular.green, m->specular.blue); + property->SetSpecular (phong); + property->SetSpecularPower(phong_size); + property->SetOpacity(1.0 - m->transparency); + vtkDebugMacro(<< "Importing Property: " << m->name); + + m->aProperty = property; + } +} + +/* Insert a new node into the list */ +static void list_insert (vtk3DSList **root, vtk3DSList *new_node) +{ + new_node->next = *root; + *root = new_node; +} + + +/* Find the node with the specified name */ +static void *list_find (vtk3DSList **root, const char *name) +{ + vtk3DSList *p; + for (p = *root; p != (vtk3DSList *) NULL; p = (vtk3DSList *) p->next) + { + if (strcmp (p->name, name) == 0) + { + break; + } + } + return (void *)p; +} + +/* Delete the entire list */ +static void list_kill (vtk3DSList **root) +{ + vtk3DSList *temp; + + while (*root != (vtk3DSList *) NULL) + { + temp = *root; + *root = (vtk3DSList *) (*root)->next; + free (temp); + } +} + +/* Add a new material to the material list */ +static vtk3DSMaterial *update_materials (vtk3DSImporter *importer, const char *new_material, int ext) +{ + vtk3DSMaterial *p; + + p = (vtk3DSMaterial *) VTK_LIST_FIND (importer->MaterialList, new_material); + + if (p == NULL) + { + p = (vtk3DSMaterial *) malloc (sizeof (*p)); + strcpy (p->name, new_material); + p->external = ext; + VTK_LIST_INSERT (importer->MaterialList, p); + } + return p; +} + + +static vtk3DSMatProp *create_mprop() +{ + vtk3DSMatProp *new_mprop; + + new_mprop = (vtk3DSMatProp *) malloc (sizeof(*new_mprop)); + strcpy (new_mprop->name, ""); + new_mprop->ambient = Black; + new_mprop->diffuse = Black; + new_mprop->specular = Black; + new_mprop->shininess = 0.0; + new_mprop->transparency = 0.0; + new_mprop->reflection = 0.0; + new_mprop->self_illum = 0; + + strcpy (new_mprop->tex_map, ""); + new_mprop->tex_strength = 0.0; + + strcpy (new_mprop->bump_map, ""); + new_mprop->bump_strength = 0.0; + + new_mprop->aProperty = vtkProperty::New (); + return new_mprop; +} + + +/* Create a new mesh */ +static vtk3DSMesh *create_mesh (char *name, int vertices, int faces) +{ + vtk3DSMesh *new_mesh; + + new_mesh = (vtk3DSMesh *) malloc (sizeof(*new_mesh)); + strcpy (new_mesh->name, name); + + new_mesh->vertices = vertices; + + if (vertices <= 0) + { + new_mesh->vertex = NULL; + } + else + { + new_mesh->vertex = (vtk3DSVector *) malloc(vertices * sizeof(*new_mesh->vertex)); + } + + new_mesh->faces = faces; + + if (faces <= 0) + { + new_mesh->face = NULL; + new_mesh->mtl = NULL; + } + else + { + new_mesh->face = (vtk3DSFace *) malloc (faces * sizeof(*new_mesh->face)); + new_mesh->mtl = (vtk3DSMaterial **) malloc (faces * sizeof(*new_mesh->mtl)); + } + + new_mesh->hidden = 0; + new_mesh->shadow = 1; + + new_mesh->anActor = NULL; + new_mesh->aMapper = NULL; + new_mesh->aNormals = NULL; + new_mesh->aStripper = NULL; + new_mesh->aPoints = NULL; + new_mesh->aCellArray = NULL; + new_mesh->aPolyData = NULL; + return new_mesh; +} + + +static int parse_3ds_file(vtk3DSImporter *importer) +{ + vtk3DSChunk chunk; + + start_chunk(importer, &chunk); + + if (chunk.tag == 0x4D4D) + { + parse_3ds (importer, &chunk); + } + else + { + vtkGenericWarningMacro(<< "Error: Input file is not .3DS format\n"); + return 0; + } + + end_chunk (importer, &chunk); + return 1; +} + +static void parse_3ds (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + vtk3DSChunk chunk; + + do + { + start_chunk (importer, &chunk); + + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0x3D3D: parse_mdata (importer, &chunk); + break; + } + } + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); +} + + +static void parse_mdata (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + vtk3DSChunk chunk; + vtk3DSColour bgnd_colour; + + do + { + start_chunk (importer, &chunk); + + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0x2100: parse_colour (importer, &global_amb); + break; + case 0x1200: parse_colour (importer, &bgnd_colour); + break; + case 0x2200: parse_fog (importer, &chunk); + break; + case 0x2210: parse_fog_bgnd(importer); + break; + case 0xAFFF: parse_mat_entry (importer, &chunk); + break; + case 0x4000: parse_named_object (importer, &chunk); + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); +} + + +static void parse_fog (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + vtk3DSChunk chunk; + + (void)read_float(importer); + (void)read_float(importer); + (void) read_float(importer); + (void)read_float(importer); + + parse_colour (importer, &fog_colour); + + do + { + start_chunk (importer, &chunk); + + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0x2210: parse_fog_bgnd(importer); + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); +} + + +static void parse_fog_bgnd(vtk3DSImporter *vtkNotUsed(importer)) +{ +} + + +static void parse_mat_entry (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + vtk3DSChunk chunk; + vtk3DSMatProp *mprop; + + mprop = create_mprop(); + + do + { + start_chunk (importer, &chunk); + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0xA000: strcpy (mprop->name, read_string(importer)); + cleanup_name (mprop->name); + break; + + case 0xA010: parse_colour (importer, &mprop->ambient); + break; + + case 0xA020: parse_colour (importer, &mprop->diffuse); + break; + + case 0xA030: parse_colour (importer, &mprop->specular); + break; + + case 0xA040: mprop->shininess = 100.0*parse_percentage(importer); + break; + + case 0xA050: mprop->transparency = parse_percentage(importer); + break; + + case 0xA080: mprop->self_illum = 1; + break; + + case 0xA220: mprop->reflection = parse_percentage(importer); + (void)parse_mapname (importer, &chunk); + break; + + case 0xA310: if (mprop->reflection == 0.0) + { + mprop->reflection = 1.0; + } + break; + + case 0xA200: mprop->tex_strength = parse_percentage(importer); + strcpy (mprop->tex_map, parse_mapname (importer, &chunk)); + break; + + case 0xA230: mprop->bump_strength = parse_percentage(importer); + strcpy (mprop->bump_map, parse_mapname (importer, &chunk)); + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); + + VTK_LIST_INSERT (importer->MatPropList, mprop); +} + + +static char *parse_mapname (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + static char name[80] = ""; + vtk3DSChunk chunk; + + do + { + start_chunk (importer, &chunk); + + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0xA300: strcpy (name, read_string(importer)); + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); + + return name; +} + + +static void parse_named_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + vtk3DSMesh *mesh; + vtk3DSChunk chunk; + + strcpy (obj_name, read_string(importer)); + cleanup_name (obj_name); + + mesh = NULL; + + do + { + start_chunk (importer, &chunk); + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0x4100: parse_n_tri_object (importer, &chunk); + break; + case 0x4600: parse_n_direct_light (importer, &chunk); + break; + case 0x4700: parse_n_camera(importer); + break; + case 0x4010: if (mesh != NULL) + { + mesh->hidden = 1; + } + break; + case 0x4012: if (mesh != NULL) + { + mesh->shadow = 0; + } + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); + +} + +static void parse_n_tri_object (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + vtk3DSMesh *mesh; + vtk3DSChunk chunk; + + mesh = create_mesh (obj_name, 0, 0); + + do + { + start_chunk (importer, &chunk); + + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0x4110: parse_point_array(importer, mesh); + break; + case 0x4120: parse_face_array (importer, mesh, &chunk); + break; + case 0x4160: parse_mesh_matrix(importer, mesh); + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); + + VTK_LIST_INSERT (importer->MeshList, mesh); +} + + +static void parse_point_array(vtk3DSImporter *importer, vtk3DSMesh *mesh) +{ + int i; + + mesh->vertices = read_word(importer); + mesh->vertex = (vtk3DSVector *) malloc (mesh->vertices * sizeof(*(mesh->vertex))); + for (i = 0; i < mesh->vertices; i++) + { + read_point (importer, mesh->vertex[i]); + } +} + +static void parse_face_array (vtk3DSImporter *importer, vtk3DSMesh *mesh, vtk3DSChunk *mainchunk) +{ + vtk3DSChunk chunk; + int i; + + mesh->faces = read_word(importer); + mesh->face = (vtk3DSFace *) malloc (mesh->faces * sizeof(*(mesh->face))); + mesh->mtl = (vtk3DSMaterial **) malloc (mesh->faces * sizeof(*(mesh->mtl))); + + for (i = 0; i < mesh->faces; i++) + { + mesh->face[i].a = read_word(importer); + mesh->face[i].b = read_word(importer); + mesh->face[i].c = read_word(importer); + (void)read_word(importer); + + mesh->mtl[i] = NULL; + } + + do + { + start_chunk (importer, &chunk); + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0x4130: parse_msh_mat_group(importer, mesh); + break; + case 0x4150: parse_smooth_group(importer); + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); + + for (i = 0; i < mesh->faces; i++) + { + if (mesh->mtl[i] == (vtk3DSMaterial *) NULL) + { + mesh->mtl[i] = update_materials (importer, "Default", 0); + } + } +} + + +static void parse_msh_mat_group(vtk3DSImporter *importer, vtk3DSMesh *mesh) +{ + vtk3DSMaterial *new_mtl; + char mtlname[80]; + int mtlcnt; + int i, face; + + strcpy (mtlname, read_string(importer)); + cleanup_name (mtlname); + + new_mtl = update_materials (importer, mtlname, 0); + + mtlcnt = read_word(importer); + + for (i = 0; i < mtlcnt; i++) + { + face = read_word(importer); + mesh->mtl[face] = new_mtl; + } +} + +static void parse_smooth_group(vtk3DSImporter *vtkNotUsed(importer)) +{ +} + +static void parse_mesh_matrix(vtk3DSImporter *vtkNotUsed(importer), vtk3DSMesh *vtkNotUsed(mesh)) +{ + // vtkGenericWarningMacro(<< "mesh matrix detected but not used\n"); +} + + +static void parse_n_direct_light (vtk3DSImporter *importer, vtk3DSChunk *mainchunk) +{ + vtk3DSChunk chunk; + vtk3DSSpotLight *s; + vtk3DSOmniLight *o; + int spot_flag = 0; + + read_point (importer, pos); + parse_colour (importer, &col); + + do + { + start_chunk (importer, &chunk); + + if (chunk.end <= mainchunk->end) + { + switch (chunk.tag) + { + case 0x4620: break; + case 0x4610: parse_dl_spotlight(importer); + spot_flag = 1; + break; + } + } + + end_chunk (importer, &chunk); + } while (chunk.end <= mainchunk->end); + + if (!spot_flag) + { + o = (vtk3DSOmniLight *) VTK_LIST_FIND (importer->OmniList, obj_name); + + if (o != NULL) + { + pos[0] = o->pos[0]; + pos[1] = o->pos[1]; + pos[2] = o->pos[2]; + col = o->col; + } + else + { + o = (vtk3DSOmniLight *) malloc (sizeof (*o)); + o->pos[0] = pos[0]; + o->pos[1] = pos[1]; + o->pos[2] = pos[2]; + o->col = col ; + strcpy (o->name, obj_name); + VTK_LIST_INSERT (importer->OmniList, o); + } + } + else + { + s = (vtk3DSSpotLight *) VTK_LIST_FIND (importer->SpotLightList, obj_name); + + if (s != NULL) + { + pos[0] = s->pos[0]; + pos[1] = s->pos[1]; + pos[2] = s->pos[2]; + target[0] = s->target[0]; + target[1] = s->target[1]; + target[2] = s->target[2]; + col = s->col; + hotspot = s->hotspot; + falloff = s->falloff; + } + else + { + if (falloff <= 0.0) + { + falloff = 180.0; + } + if (hotspot <= 0.0) + { + hotspot = 0.7*falloff; + } + s = (vtk3DSSpotLight *) malloc (sizeof (*s)); + s->pos[0] = pos[0]; + s->pos[1] = pos[1]; + s->pos[2] = pos[2]; + s->target[0] = target[0]; + s->target[1] = target[1]; + s->target[2] = target[2]; + s->col = col ; + s->hotspot = hotspot; + s->falloff = falloff; + strcpy (s->name, obj_name); + VTK_LIST_INSERT (importer->SpotLightList, s); + } + } +} + + +static void parse_dl_spotlight(vtk3DSImporter *importer) +{ + read_point (importer, target); + + hotspot = read_float(importer); + falloff = read_float(importer); +} + + +static void parse_n_camera(vtk3DSImporter *importer) +{ + float bank; + float lens; + vtk3DSCamera *c = (vtk3DSCamera *) malloc (sizeof (vtk3DSCamera)); + + read_point (importer, pos); + read_point (importer, target); + bank = read_float(importer); + lens = read_float(importer); + + strcpy (c->name, obj_name); + c->pos[0] = pos[0]; + c->pos[1] = pos[1]; + c->pos[2] = pos[2]; + c->target[0] = target[0]; + c->target[1] = target[1]; + c->target[2] = target[2]; + c->lens = lens; + c->bank = bank; + + VTK_LIST_INSERT (importer->CameraList, c); +} + +static void parse_colour (vtk3DSImporter *importer, vtk3DSColour *colour) +{ + vtk3DSChunk chunk; + vtk3DSColour_24 colour_24; + + start_chunk (importer, &chunk); + + switch (chunk.tag) + { + case 0x0010: parse_colour_f (importer, colour); + break; + + case 0x0011: parse_colour_24 (importer, &colour_24); + colour->red = colour_24.red/255.0; + colour->green = colour_24.green/255.0; + colour->blue = colour_24.blue/255.0; + break; + + default: vtkGenericWarningMacro(<< "Error parsing colour"); + } + + end_chunk (importer, &chunk); +} + + +static void parse_colour_f (vtk3DSImporter *importer, vtk3DSColour *colour) +{ + colour->red = read_float(importer); + colour->green = read_float(importer); + colour->blue = read_float(importer); +} + + +static void parse_colour_24 (vtk3DSImporter *importer, vtk3DSColour_24 *colour) +{ + colour->red = read_byte(importer); + colour->green = read_byte(importer); + colour->blue = read_byte(importer); +} + + +static float parse_percentage(vtk3DSImporter *importer) +{ + vtk3DSChunk chunk; + float percent = 0.0; + + start_chunk (importer, &chunk); + + switch (chunk.tag) + { + case 0x0030: percent = parse_int_percentage(importer)/100.0; + break; + + case 0x0031: percent = parse_float_percentage(importer); + break; + + default: vtkGenericWarningMacro( << "Error parsing percentage\n"); + } + + end_chunk (importer, &chunk); + + return percent; +} + + +static short parse_int_percentage(vtk3DSImporter *importer) +{ + word percent = read_word(importer); + + return percent; +} + + +static float parse_float_percentage(vtk3DSImporter *importer) +{ + float percent = read_float(importer); + + return percent; +} + + +static void start_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk) +{ + chunk->start = ftell(importer->GetFileFD()); + chunk->tag = read_word(importer); + chunk->length = read_dword(importer); + if (chunk->length == 0) + { + chunk->length = 1; + } + chunk->end = chunk->start + chunk->length; +} + + +static void end_chunk (vtk3DSImporter *importer, vtk3DSChunk *chunk) +{ + fseek (importer->GetFileFD(), chunk->end, 0); +} + + +static byte read_byte(vtk3DSImporter *importer) +{ + byte data; + + data = fgetc (importer->GetFileFD()); + + return data; +} + + +static word read_word(vtk3DSImporter *importer) +{ + word data; + + fread (&data, 2, 1, importer->GetFileFD()); + vtkByteSwap::Swap2LE ((short *) &data); +/* swab ((char *) &data, (char *) &sdata, 2);*/ + + return data; +} + +static dword read_dword(vtk3DSImporter *importer) +{ + dword data; + + if (fread (&data, 4, 1, importer->GetFileFD()) != 1) + { +// vtkGenericWarningMacro(<<"Pre-mature end of file in read_dword\n"); + data = 0; + } + + vtkByteSwap::Swap4LE ((char *) &data); + return data; +} + + +static float read_float(vtk3DSImporter *importer) +{ + float data; + + fread (&data, 4, 1, importer->GetFileFD()); + vtkByteSwap::Swap4LE ((char *) &data); +/* TIFFSwabLong (&data);*/ + + return data; +} + + +static void read_point (vtk3DSImporter *importer, vtk3DSVector v) +{ + v[0] = read_float(importer); + v[1] = read_float(importer); + v[2] = read_float(importer); +} + + +static char *read_string(vtk3DSImporter *importer) +{ + static char string[80]; + int i; + + for (i = 0; i < 80; i++) + { + string[i] = read_byte(importer); + + if (string[i] == '\0') + { + break; + } + } + + return string; +} + + + +static void cleanup_name (char *name) +{ + char *tmp = (char *) malloc (strlen(name)+2); + int i; + + /* Remove any leading blanks or quotes */ + i = 0; + while ((name[i] == ' ' || name[i] == '"') && name[i] != '\0') + { + i++; + } + strcpy (tmp, &name[i]); + + /* Remove any trailing blanks or quotes */ + for (i = static_cast(strlen(tmp))-1; i >= 0; i--) + { + if (isprint(tmp[i]) && !isspace(tmp[i]) && tmp[i] != '"') + { + break; + } + else + { + tmp[i] = '\0'; + } + } + + strcpy (name, tmp); + + /* Prefix the letter 'N' to materials that begin with a digit */ + if (!isdigit (name[0])) + { + strcpy (tmp, name); + } + else + { + tmp[0] = 'N'; + strcpy (&tmp[1], name); + } + + /* Replace all illegal charaters in name with underscores */ + for (i = 0; tmp[i] != '\0'; i++) + { + if (!isalnum(tmp[i])) + { + tmp[i] = '_'; + } + } + + strcpy (name, tmp); + + free (tmp); +} + +vtk3DSImporter::~vtk3DSImporter() +{ + vtk3DSOmniLight *omniLight; + vtk3DSSpotLight *spotLight; + + // walk the light list and delete vtk objects + for (omniLight = this->OmniList; omniLight != (vtk3DSOmniLight *) NULL; omniLight = (vtk3DSOmniLight *) omniLight->next) + { + omniLight->aLight->Delete(); + } + VTK_LIST_KILL (this->OmniList); + + // walk the spot light list and delete vtk objects + for (spotLight = this->SpotLightList; spotLight != (vtk3DSSpotLight *) NULL; + spotLight = (vtk3DSSpotLight *) spotLight->next) + { + spotLight->aLight->Delete(); + } + VTK_LIST_KILL (this->SpotLightList); + + vtk3DSCamera *camera; + // walk the camera list and delete vtk objects + for (camera = this->CameraList; camera != (vtk3DSCamera *) NULL; + camera = (vtk3DSCamera *) camera->next) + { + camera->aCamera->Delete (); + } + VTK_LIST_KILL (this->CameraList); + + // walk the mesh list and delete malloced datra and vtk objects + vtk3DSMesh *mesh; + for (mesh = this->MeshList; mesh != (vtk3DSMesh *) NULL; + mesh = (vtk3DSMesh *) mesh->next) + { + if (mesh->anActor != NULL) + { + mesh->anActor->Delete (); + } + if (mesh->aMapper != NULL) + { + mesh->aMapper->Delete (); + } + if (mesh->aNormals != NULL) + { + mesh->aNormals->Delete (); + } + if (mesh->aStripper != NULL) + { + mesh->aStripper->Delete (); + } + if (mesh->aPoints != NULL) + { + mesh->aPoints->Delete (); + } + if (mesh->aCellArray != NULL) + { + mesh->aCellArray->Delete (); + } + if (mesh->aPolyData != NULL) + { + mesh->aPolyData->Delete (); + } + if (mesh->vertex) + { + free (mesh->vertex); + } + if (mesh->face) + { + free (mesh->face); + } + if (mesh->mtl) + { + free (mesh->mtl); + } + } + + // then delete the list structure + + VTK_LIST_KILL (this->MeshList); + VTK_LIST_KILL (this->MaterialList); + + // objects allocated in Material Property List + vtk3DSMatProp *m; + // just walk the list of material properties, deleting vtk properties + for (m = this->MatPropList; m != (vtk3DSMatProp *) NULL; m = (vtk3DSMatProp *) m->next) + { + m->aProperty->Delete(); + } + + // then delete the list structure + VTK_LIST_KILL (this->MatPropList); + + if (this->FileName) + { + delete [] this->FileName; + } +} + +void vtk3DSImporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + os << indent << "Compute Normals: " + << (this->ComputeNormals ? "On\n" : "Off\n"); +} + + + + + + diff --git a/Hybrid/vtk3DSImporter.h b/Hybrid/vtk3DSImporter.h new file mode 100644 index 0000000..cd20fd7 --- /dev/null +++ b/Hybrid/vtk3DSImporter.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk3DSImporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtk3DSImporter - imports 3D Studio files. +// .SECTION Description +// vtk3DSImporter imports 3D Studio files into vtk. + +// .SECTION See Also +// vtkImporter + + +#ifndef __vtk3DSImporter_h +#define __vtk3DSImporter_h + +#include "vtkImporter.h" +#include "vtk3DS.h" // Needed for all the 3DS structures + +class vtkPolyData; + +class VTK_HYBRID_EXPORT vtk3DSImporter : public vtkImporter +{ +public: + static vtk3DSImporter *New(); + + vtkTypeRevisionMacro(vtk3DSImporter,vtkImporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the name of the file to read. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Set/Get the computation of normals. If on, imported geometry will + // be run through vtkPolyDataNormals. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Return the file pointer to the open file. + FILE *GetFileFD() {return this->FileFD;}; + + vtk3DSOmniLight *OmniList; + vtk3DSSpotLight *SpotLightList; + vtk3DSCamera *CameraList; + vtk3DSMesh *MeshList; + vtk3DSMaterial *MaterialList; + vtk3DSMatProp *MatPropList; + +protected: + vtk3DSImporter(); + ~vtk3DSImporter(); + + virtual int ImportBegin (); + virtual void ImportEnd (); + virtual void ImportActors (vtkRenderer *renderer); + virtual void ImportCameras (vtkRenderer *renderer); + virtual void ImportLights (vtkRenderer *renderer); + virtual void ImportProperties (vtkRenderer *renderer); + vtkPolyData *GeneratePolyData (vtk3DSMesh *meshPtr); + int Read3DS (); + + char *FileName; + FILE *FileFD; + int ComputeNormals; +private: + vtk3DSImporter(const vtk3DSImporter&); // Not implemented. + void operator=(const vtk3DSImporter&); // Not implemented. +}; + +#endif + diff --git a/Hybrid/vtkAnnotatedCubeActor.cxx b/Hybrid/vtkAnnotatedCubeActor.cxx new file mode 100644 index 0000000..bae71f1 --- /dev/null +++ b/Hybrid/vtkAnnotatedCubeActor.cxx @@ -0,0 +1,616 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAnnotatedCubeActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAnnotatedCubeActor.h" + +#include "vtkActor.h" +#include "vtkAppendPolyData.h" +#include "vtkCubeSource.h" +#include "vtkFeatureEdges.h" +#include "vtkObject.h" +#include "vtkObjectFactory.h" +#include "vtkPropCollection.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyData.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkTransformFilter.h" +#include "vtkVectorText.h" + +vtkCxxRevisionMacro(vtkAnnotatedCubeActor, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkAnnotatedCubeActor); + +vtkAnnotatedCubeActor::vtkAnnotatedCubeActor() +{ + this->Cube = 1; + this->TextEdges = 1; + this->FaceText = 1; + this->FaceTextScale = 0.5; + this->XPlusFaceText = NULL; + this->XMinusFaceText = NULL; + this->YPlusFaceText = NULL; + this->YMinusFaceText = NULL; + this->ZPlusFaceText = NULL; + this->ZMinusFaceText = NULL; + + this->CubeSource = vtkCubeSource::New(); + this->CubeSource->SetBounds(-0.5, 0.5, -0.5, 0.5, -0.5, 0.5); + this->CubeSource->SetCenter(0, 0, 0); + + vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); + this->CubeActor = vtkActor::New(); + cubeMapper->SetInput( this->CubeSource->GetOutput() ); + this->CubeActor->SetMapper( cubeMapper ); + cubeMapper->Delete(); + + vtkProperty* prop = this->CubeActor->GetProperty(); + prop->SetRepresentationToSurface(); + prop->SetColor(1, 1, 1); + prop->SetLineWidth(1); + + this->SetXPlusFaceText ( "A" ); + this->SetXMinusFaceText( "P" ); + this->SetYPlusFaceText ( "L" ); + this->SetYMinusFaceText( "R" ); + this->SetZPlusFaceText ( "S" ); + this->SetZMinusFaceText( "I" ); + + this->XPlusFaceVectorText = vtkVectorText::New(); + this->XMinusFaceVectorText = vtkVectorText::New(); + this->YPlusFaceVectorText = vtkVectorText::New(); + this->YMinusFaceVectorText = vtkVectorText::New(); + this->ZPlusFaceVectorText = vtkVectorText::New(); + this->ZMinusFaceVectorText = vtkVectorText::New(); + + vtkPolyDataMapper *xplusMapper = vtkPolyDataMapper::New(); + vtkPolyDataMapper *xminusMapper = vtkPolyDataMapper::New(); + vtkPolyDataMapper *yplusMapper = vtkPolyDataMapper::New(); + vtkPolyDataMapper *yminusMapper = vtkPolyDataMapper::New(); + vtkPolyDataMapper *zplusMapper = vtkPolyDataMapper::New(); + vtkPolyDataMapper *zminusMapper = vtkPolyDataMapper::New(); + + xplusMapper->SetInput ( this->XPlusFaceVectorText->GetOutput() ); + xminusMapper->SetInput( this->XMinusFaceVectorText->GetOutput() ); + yplusMapper->SetInput ( this->YPlusFaceVectorText->GetOutput() ); + yminusMapper->SetInput( this->YMinusFaceVectorText->GetOutput() ); + zplusMapper->SetInput ( this->ZPlusFaceVectorText->GetOutput() ); + zminusMapper->SetInput( this->ZMinusFaceVectorText->GetOutput() ); + + this->XPlusFaceActor = vtkActor::New(); + this->XMinusFaceActor = vtkActor::New(); + this->YPlusFaceActor = vtkActor::New(); + this->YMinusFaceActor = vtkActor::New(); + this->ZPlusFaceActor = vtkActor::New(); + this->ZMinusFaceActor = vtkActor::New(); + + this->XPlusFaceActor-> SetMapper( xplusMapper ); + this->XMinusFaceActor->SetMapper( xminusMapper ); + this->YPlusFaceActor-> SetMapper( yplusMapper ); + this->YMinusFaceActor->SetMapper( yminusMapper ); + this->ZPlusFaceActor-> SetMapper( zplusMapper ); + this->ZMinusFaceActor->SetMapper( zminusMapper ); + + xplusMapper->Delete(); + xminusMapper->Delete(); + yplusMapper->Delete(); + yminusMapper->Delete(); + zplusMapper->Delete(); + zminusMapper->Delete(); + + prop = this->XPlusFaceActor->GetProperty(); + prop->SetColor(1, 1, 1); + prop->SetDiffuse(0); + prop->SetAmbient(1); + prop->BackfaceCullingOn(); + this->XMinusFaceActor->GetProperty()->DeepCopy( prop ); + this->YPlusFaceActor-> GetProperty()->DeepCopy( prop ); + this->YMinusFaceActor->GetProperty()->DeepCopy( prop ); + this->ZPlusFaceActor-> GetProperty()->DeepCopy( prop ); + this->ZMinusFaceActor->GetProperty()->DeepCopy( prop ); + + this->AppendTextEdges = vtkAppendPolyData::New(); + this->AppendTextEdges->UserManagedInputsOn(); + this->AppendTextEdges->SetNumberOfInputs(6); + + for (int i = 0; i < 6; i++) + { + vtkPolyData *edges = vtkPolyData::New(); + this->AppendTextEdges->SetInputByNumber(i,edges); + edges->Delete(); + } + + this->ExtractTextEdges = vtkFeatureEdges::New(); + this->ExtractTextEdges->BoundaryEdgesOn(); + this->ExtractTextEdges->ColoringOff(); + this->ExtractTextEdges->SetInput( this->AppendTextEdges->GetOutput() ); + + vtkPolyDataMapper* edgesMapper = vtkPolyDataMapper::New(); + edgesMapper->SetInput( this->ExtractTextEdges->GetOutput() ); + + this->TextEdgesActor = vtkActor::New(); + this->TextEdgesActor->SetMapper( edgesMapper ); + edgesMapper->Delete(); + + prop = this->TextEdgesActor->GetProperty(); + prop->SetRepresentationToWireframe(); + prop->SetColor(1,0.5,0); + prop->SetDiffuse(0); + prop->SetAmbient(1); + prop->SetLineWidth(1); + + this->TransformFilter = vtkTransformFilter::New(); + this->Transform = vtkTransform::New(); + this->TransformFilter->SetTransform( this->Transform ); + + this->XFaceTextRotation = 0.0; + this->YFaceTextRotation = 0.0; + this->ZFaceTextRotation = 0.0; + + this->UpdateProps(); +} + +vtkAnnotatedCubeActor::~vtkAnnotatedCubeActor() +{ + this->CubeSource->Delete(); + this->CubeActor->Delete(); + + this->SetXPlusFaceText ( NULL ); + this->SetXMinusFaceText( NULL ); + this->SetYPlusFaceText ( NULL ); + this->SetYMinusFaceText( NULL ); + this->SetZPlusFaceText ( NULL ); + this->SetZMinusFaceText( NULL ); + + this->XPlusFaceVectorText->Delete(); + this->XMinusFaceVectorText->Delete(); + this->YPlusFaceVectorText->Delete(); + this->YMinusFaceVectorText->Delete(); + this->ZPlusFaceVectorText->Delete(); + this->ZMinusFaceVectorText->Delete(); + + this->XPlusFaceActor->Delete(); + this->XMinusFaceActor->Delete(); + this->YPlusFaceActor->Delete(); + this->YMinusFaceActor->Delete(); + this->ZPlusFaceActor->Delete(); + this->ZMinusFaceActor->Delete(); + + this->AppendTextEdges->Delete(); + this->ExtractTextEdges->Delete(); + this->TextEdgesActor->Delete(); + + this->TransformFilter->Delete(); + this->Transform->Delete(); +} + +// Shallow copy of an actor. +void vtkAnnotatedCubeActor::ShallowCopy(vtkProp *prop) +{ + vtkAnnotatedCubeActor *a = vtkAnnotatedCubeActor::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetXPlusFaceText( a->GetXPlusFaceText() ); + this->SetXMinusFaceText( a->GetXMinusFaceText() ); + this->SetYPlusFaceText( a->GetYPlusFaceText() ); + this->SetYMinusFaceText( a->GetYMinusFaceText() ); + this->SetZPlusFaceText( a->GetZPlusFaceText() ); + this->SetZMinusFaceText( a->GetZMinusFaceText() ); + this->SetFaceTextScale( a->GetFaceTextScale() ); + this->SetTextEdges( a->GetTextEdges() ); + this->SetCube( a->GetCube() ); + this->SetFaceText( a->GetFaceText() ); + } + + // Now do superclass + this->vtkProp3D::ShallowCopy(prop); +} + +void vtkAnnotatedCubeActor::GetActors(vtkPropCollection *ac) +{ + ac->AddItem( this->CubeActor ); + ac->AddItem( this->XPlusFaceActor ); + ac->AddItem( this->XMinusFaceActor ); + ac->AddItem( this->YPlusFaceActor ); + ac->AddItem( this->YMinusFaceActor ); + ac->AddItem( this->ZPlusFaceActor ); + ac->AddItem( this->ZMinusFaceActor ); + ac->AddItem( this->TextEdgesActor ); +} + +int vtkAnnotatedCubeActor::RenderOpaqueGeometry(vtkViewport *vp) +{ + this->UpdateProps(); + int renderedSomething = 0; + + if ( this->Cube ) + { + renderedSomething += this->CubeActor->RenderOpaqueGeometry( vp ); + } + if ( this->FaceText ) + { + renderedSomething += this->XPlusFaceActor->RenderOpaqueGeometry( vp ); + renderedSomething += this->XMinusFaceActor->RenderOpaqueGeometry( vp ); + renderedSomething += this->YPlusFaceActor->RenderOpaqueGeometry( vp ); + renderedSomething += this->YMinusFaceActor->RenderOpaqueGeometry( vp ); + renderedSomething += this->ZPlusFaceActor->RenderOpaqueGeometry( vp ); + renderedSomething += this->ZMinusFaceActor->RenderOpaqueGeometry( vp ); + } + if ( this->TextEdges ) + { + renderedSomething += this->TextEdgesActor->RenderOpaqueGeometry( vp ); + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + return renderedSomething; +} + +int vtkAnnotatedCubeActor::RenderTranslucentGeometry(vtkViewport *vp) +{ + this->UpdateProps(); + int renderedSomething = 0; + + if ( this->Cube ) + { + renderedSomething += this->CubeActor->RenderTranslucentGeometry( vp ); + } + if ( this->FaceText ) + { + renderedSomething += this->XPlusFaceActor->RenderTranslucentGeometry( vp ); + renderedSomething += this->XMinusFaceActor->RenderTranslucentGeometry( vp ); + renderedSomething += this->YPlusFaceActor->RenderTranslucentGeometry( vp ); + renderedSomething += this->YMinusFaceActor->RenderTranslucentGeometry( vp ); + renderedSomething += this->ZPlusFaceActor->RenderTranslucentGeometry( vp ); + renderedSomething += this->ZMinusFaceActor->RenderTranslucentGeometry( vp ); + } + if ( this->TextEdges ) + { + renderedSomething += this->TextEdgesActor->RenderTranslucentGeometry( vp ); + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + return renderedSomething; +} + +void vtkAnnotatedCubeActor::ReleaseGraphicsResources(vtkWindow *win) +{ + this->CubeActor->ReleaseGraphicsResources( win ); + this->XPlusFaceActor->ReleaseGraphicsResources( win ); + this->XMinusFaceActor->ReleaseGraphicsResources( win ); + this->YPlusFaceActor->ReleaseGraphicsResources( win ); + this->YMinusFaceActor->ReleaseGraphicsResources( win ); + this->ZPlusFaceActor->ReleaseGraphicsResources( win ); + this->ZMinusFaceActor->ReleaseGraphicsResources( win ); + this->TextEdgesActor->ReleaseGraphicsResources( win ); +} + +void vtkAnnotatedCubeActor::GetBounds(double bounds[6]) +{ + double *bds = this->GetBounds(); + bounds[0] = bds[0]; + bounds[1] = bds[1]; + bounds[2] = bds[2]; + bounds[3] = bds[3]; + bounds[4] = bds[4]; + bounds[5] = bds[5]; +} + +// Get the bounds for this Actor as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkAnnotatedCubeActor::GetBounds() +{ + double bounds[6]; + int i; + + this->CubeActor->GetBounds(this->Bounds); + + this->XPlusFaceActor->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->XMinusFaceActor->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->YPlusFaceActor->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->YMinusFaceActor->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->ZPlusFaceActor->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->ZMinusFaceActor->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + // We want this actor to rotate / re-center about the origin, so give it + // the bounds it would have if everything were symmetric. + for (i = 0; i < 3; i++) + { + this->Bounds[2*i] = -this->Bounds[2*i+1]; + } + + return this->Bounds; +} + +unsigned long int vtkAnnotatedCubeActor::GetMTime() +{ + unsigned long mTime = this->Superclass::GetMTime(); + return mTime; +} + +unsigned long int vtkAnnotatedCubeActor::GetRedrawMTime() +{ + unsigned long mTime = this->GetMTime(); + return mTime; +} + +vtkProperty *vtkAnnotatedCubeActor::GetXPlusFaceProperty() +{ + return this->XPlusFaceActor->GetProperty(); +} + +vtkProperty *vtkAnnotatedCubeActor::GetXMinusFaceProperty() +{ + return this->XMinusFaceActor->GetProperty(); +} + +vtkProperty *vtkAnnotatedCubeActor::GetYPlusFaceProperty() +{ + return this->YPlusFaceActor->GetProperty(); +} + +vtkProperty *vtkAnnotatedCubeActor::GetYMinusFaceProperty() +{ + return this->YMinusFaceActor->GetProperty(); +} + +vtkProperty *vtkAnnotatedCubeActor::GetZPlusFaceProperty() +{ + return this->ZPlusFaceActor->GetProperty(); +} + +vtkProperty *vtkAnnotatedCubeActor::GetZMinusFaceProperty() +{ + return this->ZMinusFaceActor->GetProperty(); +} + +vtkProperty *vtkAnnotatedCubeActor::GetCubeProperty() +{ + return this->CubeActor->GetProperty(); +} + +vtkProperty *vtkAnnotatedCubeActor::GetTextEdgesProperty() +{ + return this->TextEdgesActor->GetProperty(); +} + +void vtkAnnotatedCubeActor::SetFaceTextScale(double scale) +{ + if(this->FaceTextScale == scale) + { + return; + } + this->FaceTextScale = scale; + this->UpdateProps(); +} + +void vtkAnnotatedCubeActor::UpdateProps() +{ + this->XPlusFaceVectorText-> SetText( this->XPlusFaceText ); + this->XMinusFaceVectorText->SetText( this->XMinusFaceText ); + this->YPlusFaceVectorText-> SetText( this->YPlusFaceText ); + this->YMinusFaceVectorText->SetText( this->YMinusFaceText ); + this->ZPlusFaceVectorText-> SetText( this->ZPlusFaceText ); + this->ZMinusFaceVectorText->SetText( this->ZMinusFaceText ); + + vtkProperty* prop = this->CubeActor->GetProperty(); + + // Place the text slightly offset from the cube face to prevent + // rendering problems when the cube is in surface render mode. + double offset = (prop->GetRepresentation() == VTK_SURFACE)? (0.501) : (0.5); + + this->XPlusFaceVectorText->Update(); + double* bounds = this->XPlusFaceVectorText->GetOutput()->GetBounds(); + double cu = -this->FaceTextScale*fabs(0.5*(bounds[0] + bounds[1])); + double cv = -this->FaceTextScale*fabs(0.5*(bounds[2] + bounds[3])); + + this->XPlusFaceActor->SetScale( this->FaceTextScale ); + this->XPlusFaceActor->SetPosition( offset, cu, cv ); + this->XPlusFaceActor->SetOrientation( 90 , 0, 90 ); + + this->XMinusFaceVectorText->Update(); + bounds = this->XMinusFaceVectorText->GetOutput()->GetBounds(); + cu = this->FaceTextScale*fabs(0.5*(bounds[0] + bounds[1])); + cv = -this->FaceTextScale*fabs(0.5*(bounds[2] + bounds[3])); + + this->XMinusFaceActor->SetScale( this->FaceTextScale ); + this->XMinusFaceActor->SetPosition( -offset, cu, cv ); + this->XMinusFaceActor->SetOrientation( 90 , 0, -90 ); + + if ( this->XFaceTextRotation != 0.0 ) + { + vtkTransform* transform = vtkTransform::New(); + transform->Identity(); + transform->RotateX( this->XFaceTextRotation ); + this->XPlusFaceActor->SetUserTransform( transform ); + this->XMinusFaceActor->SetUserTransform( transform ); + transform->Delete(); + } + + this->YPlusFaceVectorText->Update(); + bounds = this->YPlusFaceVectorText->GetOutput()->GetBounds(); + cu = this->FaceTextScale*0.5*(bounds[0] + bounds[1]); + cv = -this->FaceTextScale*0.5*(bounds[2] + bounds[3]); + + this->YPlusFaceActor->SetScale( this->FaceTextScale ); + this->YPlusFaceActor->SetPosition( cu, offset, cv ); + this->YPlusFaceActor->SetOrientation( 90, 0, 180 ); + + this->YMinusFaceVectorText->Update(); + bounds = this->YMinusFaceVectorText->GetOutput()->GetBounds(); + cu = -this->FaceTextScale*0.5*(bounds[0] + bounds[1]); + cv = -this->FaceTextScale*0.5*(bounds[2] + bounds[3]); + + this->YMinusFaceActor->SetScale( this->FaceTextScale ); + this->YMinusFaceActor->SetPosition( cu, -offset, cv ); + this->YMinusFaceActor->SetOrientation( 90, 0, 0 ); + + if ( this->YFaceTextRotation != 0.0 ) + { + vtkTransform* transform = vtkTransform::New(); + transform->Identity(); + transform->RotateY( this->YFaceTextRotation ); + this->YPlusFaceActor->SetUserTransform( transform ); + this->YMinusFaceActor->SetUserTransform( transform ); + transform->Delete(); + } + + this->ZPlusFaceVectorText->Update(); + bounds = this->ZPlusFaceVectorText->GetOutput()->GetBounds(); + cu = this->FaceTextScale*0.5*(bounds[0] + bounds[1]); + cv = -this->FaceTextScale*0.5*(bounds[2] + bounds[3]); + + this->ZPlusFaceActor->SetScale( this->FaceTextScale ); + this->ZPlusFaceActor->SetPosition( cv, cu, offset ); + this->ZPlusFaceActor->SetOrientation( 0, 0, -90 ); + + this->ZMinusFaceVectorText->Update(); + bounds = this->ZMinusFaceVectorText->GetOutput()->GetBounds(); + cu = -this->FaceTextScale*0.5*(bounds[0] + bounds[1]); + cv = -this->FaceTextScale*0.5*(bounds[2] + bounds[3]); + + this->ZMinusFaceActor->SetScale( this->FaceTextScale ); + this->ZMinusFaceActor->SetPosition( cv, cu, -offset ); + this->ZMinusFaceActor->SetOrientation( 180, 0, 90 ); + + if ( this->ZFaceTextRotation != 0.0 ) + { + vtkTransform* transform = vtkTransform::New(); + transform->Identity(); + transform->RotateZ( this->ZFaceTextRotation ); + this->ZPlusFaceActor->SetUserTransform( transform ); + this->ZMinusFaceActor->SetUserTransform( transform ); + transform->Delete(); + } + + this->XPlusFaceActor->ComputeMatrix(); + this->TransformFilter->SetInput( this->XPlusFaceVectorText->GetOutput() ); + this->Transform->SetMatrix( this->XPlusFaceActor->GetMatrix() ); + this->TransformFilter->Update(); + vtkPolyData* edges = this->AppendTextEdges->GetInput( 0 ); + edges->CopyStructure( this->TransformFilter->GetOutput() ); + + this->XMinusFaceActor->ComputeMatrix(); + this->TransformFilter->SetInput( this->XMinusFaceVectorText->GetOutput() ); + this->Transform->SetMatrix( this->XMinusFaceActor->GetMatrix() ); + this->TransformFilter->Update(); + edges = this->AppendTextEdges->GetInput( 1 ); + edges->CopyStructure( this->TransformFilter->GetOutput() ); + + this->YPlusFaceActor->ComputeMatrix(); + this->TransformFilter->SetInput( this->YPlusFaceVectorText->GetOutput() ); + this->Transform->SetMatrix( this->YPlusFaceActor->GetMatrix() ); + this->TransformFilter->Update(); + edges = this->AppendTextEdges->GetInput( 2 ); + edges->CopyStructure( this->TransformFilter->GetOutput() ); + + this->YMinusFaceActor->ComputeMatrix(); + this->TransformFilter->SetInput( this->YMinusFaceVectorText->GetOutput() ); + this->Transform->SetMatrix( this->YMinusFaceActor->GetMatrix() ); + this->TransformFilter->Update(); + edges = this->AppendTextEdges->GetInput( 3 ); + edges->CopyStructure( this->TransformFilter->GetOutput() ); + + this->ZPlusFaceActor->ComputeMatrix(); + this->TransformFilter->SetInput( this->ZPlusFaceVectorText->GetOutput() ); + this->Transform->SetMatrix( this->ZPlusFaceActor->GetMatrix() ); + this->TransformFilter->Update(); + edges = this->AppendTextEdges->GetInput( 4 ); + edges->CopyStructure(this->TransformFilter->GetOutput()); + + this->ZMinusFaceActor->ComputeMatrix(); + this->TransformFilter->SetInput( this->ZMinusFaceVectorText->GetOutput() ); + this->Transform->SetMatrix( this->ZMinusFaceActor->GetMatrix() ); + this->TransformFilter->Update(); + edges = this->AppendTextEdges->GetInput( 5 ); + edges->CopyStructure( this->TransformFilter->GetOutput() ); +} + +void vtkAnnotatedCubeActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "XPlusFaceText: " << (this->XPlusFaceText ? + this->XPlusFaceText : "(none)") + << endl; + + os << indent << "XMinusFaceText: " << (this->XMinusFaceText ? + this->XMinusFaceText : "(none)") + << endl; + + os << indent << "YPlusFaceText: " << (this->YPlusFaceText ? + this->YPlusFaceText : "(none)") + << endl; + + os << indent << "YMinusFaceText: " << (this->YMinusFaceText ? + this->YMinusFaceText : "(none)") + << endl; + + os << indent << "ZPlusFaceText: " << (this->ZPlusFaceText ? + this->ZPlusFaceText : "(none)") + << endl; + + os << indent << "ZMinusFaceText: " << (this->ZMinusFaceText ? + this->ZMinusFaceText : "(none)") + << endl; + + os << indent << "FaceTextScale: " << this->FaceTextScale << endl; + + os << indent << "TextEdges: " << (this->TextEdges ? "On\n" : "Off\n"); + + os << indent << "FaceText: " << (this->FaceText ? "On\n" : "Off\n"); + + os << indent << "Cube: " << (this->Cube ? "On\n" : "Off\n"); + + os << indent << "XFaceTextRotation: " << this->XFaceTextRotation << endl; + + os << indent << "YFaceTextRotation: " << this->YFaceTextRotation << endl; + + os << indent << "ZFaceTextRotation: " << this->ZFaceTextRotation << endl; +} + diff --git a/Hybrid/vtkAnnotatedCubeActor.h b/Hybrid/vtkAnnotatedCubeActor.h new file mode 100644 index 0000000..e43a936 --- /dev/null +++ b/Hybrid/vtkAnnotatedCubeActor.h @@ -0,0 +1,213 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAnnotatedCubeActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAnnotatedCubeActor - a 3D cube with face labels +// .SECTION Description +// vtkAnnotatedCubeActor is a hybrid 3D actor used to represent an anatomical +// orientation marker in a scene. The class consists of a 3D unit cube centered +// on the origin with each face labelled in correspondance to a particular +// coordinate direction. For example, with Cartesian directions, the user +// defined text labels could be: +X, -X, +Y, -Y, +Z, -Z, while for anatomical +// directions: A, P, L, R, S, I. Text is automatically centered on each cube +// face and is not restriceted to single characters. In addition to or in +// replace of a solid text label representation, the outline edges of the labels +// can be displayed. The individual properties of the cube, face labels +// and text outlines can be manipulated as can their visibility. + +// .SECTION Caveats +// vtkAnnotatedCubeActor is primarily intended for use with +// vtkOrientationMarkerWidget. The cube face text is generated by vtkVectorText +// and therefore the font attributes are restricted. + +// .SECTION See Also +// vtkAxesActor vtkOrientationMarkerWidget vtkVectorText + +#ifndef __vtkAnnotatedCubeActor_h +#define __vtkAnnotatedCubeActor_h + +#include "vtkProp3D.h" + +class vtkActor; +class vtkAppendPolyData; +class vtkCubeSource; +class vtkFeatureEdges; +class vtkPropCollection; +class vtkProperty; +class vtkRenderer; +class vtkTransform; +class vtkTransformFilter; +class vtkVectorText; + +class VTK_HYBRID_EXPORT vtkAnnotatedCubeActor : public vtkProp3D +{ +public: + static vtkAnnotatedCubeActor *New(); + vtkTypeRevisionMacro(vtkAnnotatedCubeActor,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. These methods + // are used in that process. + virtual void GetActors(vtkPropCollection *); + + // Description: + // Support the standard render methods. + virtual int RenderOpaqueGeometry(vtkViewport *viewport); + virtual int RenderTranslucentGeometry(vtkViewport *viewport); + + // Description: + // Shallow copy of an axes actor. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Get the bounds for this Actor as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). (The + // method GetBounds(double bounds[6]) is available from the superclass.) + void GetBounds(double bounds[6]); + double *GetBounds(); + + // Description: + // Get the actors mtime plus consider its properties and texture if set. + unsigned long int GetMTime(); + + // Description: + // Return the mtime of anything that would cause the rendered image to + // appear differently. Usually this involves checking the mtime of the + // prop plus anything else it depends on such as properties, textures + // etc. + virtual unsigned long GetRedrawMTime(); + + // Description: + // Set/Get the scale factor for the face text + void SetFaceTextScale(double); + vtkGetMacro(FaceTextScale, double); + + // Description: + // Get the individual face text properties. + vtkProperty *GetXPlusFaceProperty(); + vtkProperty *GetXMinusFaceProperty(); + vtkProperty *GetYPlusFaceProperty(); + vtkProperty *GetYMinusFaceProperty(); + vtkProperty *GetZPlusFaceProperty(); + vtkProperty *GetZMinusFaceProperty(); + + // Description: + // Get the cube properties. + vtkProperty *GetCubeProperty(); + + // Description: + // Get the text edges properties. + vtkProperty *GetTextEdgesProperty(); + + // Description: + // Set/get the face text. + vtkSetStringMacro( XPlusFaceText ); + vtkGetStringMacro( XPlusFaceText ); + vtkSetStringMacro( XMinusFaceText ); + vtkGetStringMacro( XMinusFaceText ); + vtkSetStringMacro( YPlusFaceText ); + vtkGetStringMacro( YPlusFaceText ); + vtkSetStringMacro( YMinusFaceText ); + vtkGetStringMacro( YMinusFaceText ); + vtkSetStringMacro( ZPlusFaceText ); + vtkGetStringMacro( ZPlusFaceText ); + vtkSetStringMacro( ZMinusFaceText ); + vtkGetStringMacro( ZMinusFaceText ); + + // Description: + // Enable/disable drawing the vector text edges. + vtkSetMacro(TextEdges, int); + vtkGetMacro(TextEdges, int); + vtkBooleanMacro(TextEdges, int); + + // Description: + // Enable/disable drawing the cube. + vtkSetMacro(Cube, int); + vtkGetMacro(Cube, int); + vtkBooleanMacro(Cube, int); + + // Description: + // Enable/disable drawing the vector text. + vtkSetMacro(FaceText, int); + vtkGetMacro(FaceText, int); + vtkBooleanMacro(FaceText, int); + + // Description: + // Augment individual face text orientations. + vtkSetMacro(XFaceTextRotation,double); + vtkGetMacro(XFaceTextRotation,double); + vtkSetMacro(YFaceTextRotation,double); + vtkGetMacro(YFaceTextRotation,double); + vtkSetMacro(ZFaceTextRotation,double); + vtkGetMacro(ZFaceTextRotation,double); + +protected: + vtkAnnotatedCubeActor(); + ~vtkAnnotatedCubeActor(); + + vtkCubeSource *CubeSource; + vtkActor *CubeActor; + int Cube; + + vtkAppendPolyData *AppendTextEdges; + vtkFeatureEdges *ExtractTextEdges; + vtkActor *TextEdgesActor; + int TextEdges; + + void UpdateProps(); + + char *XPlusFaceText; + char *XMinusFaceText; + char *YPlusFaceText; + char *YMinusFaceText; + char *ZPlusFaceText; + char *ZMinusFaceText; + + double FaceTextScale; + int FaceText; + + double XFaceTextRotation; + double YFaceTextRotation; + double ZFaceTextRotation; + + vtkVectorText *XPlusFaceVectorText; + vtkVectorText *XMinusFaceVectorText; + vtkVectorText *YPlusFaceVectorText; + vtkVectorText *YMinusFaceVectorText; + vtkVectorText *ZPlusFaceVectorText; + vtkVectorText *ZMinusFaceVectorText; + + vtkActor *XPlusFaceActor; + vtkActor *XMinusFaceActor; + vtkActor *YPlusFaceActor; + vtkActor *YMinusFaceActor; + vtkActor *ZPlusFaceActor; + vtkActor *ZMinusFaceActor; + + vtkTransformFilter *TransformFilter; + vtkTransform *Transform; + +private: + vtkAnnotatedCubeActor(const vtkAnnotatedCubeActor&); // Not implemented. + void operator=(const vtkAnnotatedCubeActor&); // Not implemented. +}; + +#endif + diff --git a/Hybrid/vtkArcPlotter.cxx b/Hybrid/vtkArcPlotter.cxx new file mode 100644 index 0000000..75f6f5f --- /dev/null +++ b/Hybrid/vtkArcPlotter.cxx @@ -0,0 +1,460 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkArcPlotter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkArcPlotter.h" + +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkArcPlotter, "$Revision: 1.25 $"); +vtkStandardNewMacro(vtkArcPlotter); + +vtkCxxSetObjectMacro(vtkArcPlotter,Camera,vtkCamera); + +vtkArcPlotter::vtkArcPlotter() +{ + this->Camera = NULL; + this->PlotMode = VTK_PLOT_SCALARS; + this->PlotComponent = (-1); //plot all components + this->Radius = 0.5; + this->Height = 0.5; + this->Offset = 0.0; + + this->DefaultNormal[0] = this->DefaultNormal[1] = 0.0; + this->DefaultNormal[2] = 1.0; + this->UseDefaultNormal = 0; + + this->FieldDataArray = 0; + + this->DataRange = NULL; + this->Tuple = NULL; + this->ActiveComponent = 0; + this->NumberOfComponents = 0; +} + +vtkArcPlotter::~vtkArcPlotter() +{ + if ( this->DataRange ) + { + delete [] this->DataRange; + delete [] this->Tuple; + } + if ( this->Camera ) + { + this->Camera->UnRegister (this); + this->Camera = NULL; + } +} + +int vtkArcPlotter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *inPD; + vtkPoints *inPts; + vtkCellArray *inLines; + int j; + vtkIdType numPts, i; + double x[3], normal[3], point[3], aveNormal[3]; + int id; + vtkIdType *pts = 0; + vtkIdType npts = 0; + double x1[3], x2[3], x21[3], n[3]; + vtkFloatArray *lineNormals; + vtkPoints *newPts; + vtkCellArray *newLines; + double *range, offset; + int plotNum, compNum; + vtkPoints *projPts; + + inPD = input->GetPointData(); + + // Initialize + // + vtkDebugMacro(<<"Plotting along arc"); + + if ( !(inPts=input->GetPoints()) || + (numPts=inPts->GetNumberOfPoints()) < 1 || + !(inLines=input->GetLines()) || inLines->GetNumberOfCells() < 1 ) + { + vtkErrorMacro(<< "No input data!"); + return 0; + } + + // Process attribute data to determine ranges, number of components, etc. + if ( this->ProcessComponents(numPts, inPD) <= 0 ) + { + return 0; + } + + // Allocate points for projection + // + // Determine the projection plane. Project to a plane if camera is available + // and defulat normal is not desired. + if ( this->Camera && ! this->UseDefaultNormal ) + { + double xProj[3]; + projPts = vtkPoints::New(); + projPts->SetNumberOfPoints(numPts); + this->Camera->GetViewPlaneNormal(normal); + this->Camera->GetFocalPoint(point); + vtkMath::Normalize(normal); + for ( i=0; i < numPts; i++ ) + { + inPts->GetPoint(i, x); + vtkPlane::ProjectPoint(x, point, normal, xProj); + projPts->SetPoint(i,xProj); + } + } + else + { + normal[0] = this->DefaultNormal[0]; + normal[1] = this->DefaultNormal[1]; + normal[2] = this->DefaultNormal[2]; + vtkMath::Normalize(normal); + projPts = inPts; //use existing points + } + + // For each polyline, compute a normal that lies in the + // projection plane and is roughly perpendicular to the projected + // polyline. Then generate the arc. + // + newPts = vtkPoints::New(); + newPts->Allocate(numPts,numPts); + lineNormals = vtkFloatArray::New(); + lineNormals->SetNumberOfComponents(3); + + newLines = vtkCellArray::New(); + newLines->Allocate(inLines->GetSize()); + + for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); ) + { + lineNormals->SetNumberOfTuples(npts); + if ( !this->Camera || this->UseDefaultNormal ) + {//use default normal + for (i=0; i < npts; i++) + { + lineNormals->SetTuple(i,normal); + } + } + else //generate normals + { + // Compute normals on each line segment perpendicular to view normal + for (i=0; i < (npts-1); i++) + { + projPts->GetPoint(pts[i], x1); + projPts->GetPoint(pts[i+1], x2); + for (j=0; j<3; j++) + { + x21[j] = x2[j] - x1[j]; + } + vtkMath::Cross(normal,x21,n); + vtkMath::Normalize(n); + lineNormals->SetTuple(i,n); + } + lineNormals->SetTuple(npts-1,n); + } + + // Now average the normal calculation to get smoother results + // + vtkIdType window = npts / 100; + if ( window < 5 ) + { + window = 5; + } + // Start by computing an initial average normal + aveNormal[0] = aveNormal[1] = aveNormal[2] = 0.0; + for (i=0; i < npts && i < window; i++) + { + lineNormals->GetTuple(i,n); + aveNormal[0] += n[0]; aveNormal[1] += n[1]; aveNormal[2] += n[2]; + } + + for (i=0; i < npts; i++) + { + if ( (i+window) < npts ) + { + lineNormals->GetTuple(i+window,n); + aveNormal[0] += n[0]; aveNormal[1] += n[1]; aveNormal[2] += n[2]; + } + if ( (i-window) >= 0 ) + { + lineNormals->GetTuple(i-window,n); + aveNormal[0] -= n[0]; aveNormal[1] -= n[1]; aveNormal[2] -= n[2]; + } + n[0] = aveNormal[0]; n[1] = aveNormal[1]; n[2] = aveNormal[2]; + vtkMath::Normalize(n); + lineNormals->SetTuple(i, n); + } + this->UpdateProgress(0.50); + + // For each component, create an offset plot. + for (plotNum=0, compNum=this->StartComp; compNum <= this->EndComp; + compNum++, plotNum++) + { + offset = this->Radius + plotNum*this->Offset; + range = this->DataRange + 2*compNum; + + newLines->InsertNextCell(npts); + + // Continue average normal computation using sliding window + for (i=0; i < npts; i++) + { + this->Data->GetTuple(pts[i], this->Tuple); + lineNormals->GetTuple(i,n); + id = this->OffsetPoint(pts[i], inPts, n, newPts, + offset, range, this->Tuple[compNum]); + newLines->InsertCellPoint(id); + } + } //for all components + } //for all polylines + this->UpdateProgress(0.90); + + lineNormals->Delete(); + if ( projPts != inPts ) + { + projPts->Delete(); + } + + // Update output + output->SetPoints(newPts); + newPts->Delete(); + output->SetLines(newLines); + newLines->Delete(); + + return 1; +} + +int vtkArcPlotter::ProcessComponents(vtkIdType numPts, vtkPointData *pd) +{ + vtkIdType i; + int j; + double *range; + + this->Data = NULL; + switch (this->PlotMode) + { + case VTK_PLOT_SCALARS: + if ( pd->GetScalars() ) + { + this->Data = pd->GetScalars(); + } + break; + case VTK_PLOT_VECTORS: + if ( pd->GetVectors() ) + { + this->Data = pd->GetVectors(); + } + break; + case VTK_PLOT_NORMALS: + if ( pd->GetNormals() ) + { + this->Data = pd->GetNormals(); + } + break; + case VTK_PLOT_TCOORDS: + if ( pd->GetTCoords() ) + { + this->Data = pd->GetTCoords(); + } + break; + case VTK_PLOT_TENSORS: + if ( pd->GetTensors() ) + { + this->Data = pd->GetTensors(); + } + break; + case VTK_PLOT_FIELD_DATA: + int arrayNum = (this->FieldDataArray < pd->GetNumberOfArrays() ? + this->FieldDataArray : pd->GetNumberOfArrays() - 1); + this->Data = pd->GetArray(arrayNum); + break; + } + + // Determine the number of components + if ( this->Data ) + { + this->NumberOfComponents = this->Data->GetNumberOfComponents(); + if ( this->PlotComponent >= 0 ) + { + this->ActiveComponent = (this->PlotComponent < this->NumberOfComponents ? + this->PlotComponent : this->NumberOfComponents - 1); + this->StartComp = this->EndComp = this->ActiveComponent; + } + else + { + this->StartComp = 0; + this->EndComp = this->NumberOfComponents - 1; + } + } + else + { + vtkErrorMacro(<<"Need input data to plot"); + return 0; + } + + // Get the range of the components (for scaling the plot later) + if ( this->DataRange ) + { + delete [] this->DataRange; + delete [] this->Tuple; + } + + this->DataRange = new double [2*this->NumberOfComponents]; + this->Tuple = new double [this->NumberOfComponents]; + + for (i=this->StartComp; i <= this->EndComp; i++) + { + range = this->DataRange + 2*i; + range[0] = VTK_LARGE_FLOAT; + range[1] = -VTK_LARGE_FLOAT; + } + + for (i=0; iData->GetTuple(i, this->Tuple); + + for (j=this->StartComp; j <= this->EndComp; j++) + { + range = this->DataRange + 2*j; + if ( this->Tuple[j] < range[0] ) + { + range[0] = this->Tuple[j]; + } + if ( this->Tuple[j] > range[1] ) + { + range[1] = this->Tuple[j]; + } + } + } + + return this->NumberOfComponents; +} + + +int vtkArcPlotter::OffsetPoint(vtkIdType ptId, vtkPoints *inPts, double n[3], + vtkPoints *newPts, double offset, + double *range, double v) +{ + double x[3], xNew[3]; + int i; + double median = (range[0] + range[1])/2.0; + double denom = range[1] - range[0]; + + inPts->GetPoint(ptId, x); + for (i=0; i<3; i++) + { + xNew[i] = x[i] + n[i] * (offset + ((v - median)/denom)*this->Height); + } + + return newPts->InsertNextPoint(xNew); +} + +unsigned long vtkArcPlotter::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long cameraMTime; + + if ( this->Camera && ! this->UseDefaultNormal ) + { + cameraMTime = this->Camera->GetMTime(); + return (cameraMTime > mTime ? cameraMTime : mTime); + } + else + { + return mTime; + } +} + +void vtkArcPlotter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Camera ) + { + os << indent << "Camera:\n"; + this->Camera->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Camera: (none)\n"; + } + + os << indent << "Plot Mode: "; + if ( this->PlotMode == VTK_PLOT_SCALARS ) + { + os << "Plot Scalars\n"; + } + else if ( this->PlotMode == VTK_PLOT_VECTORS ) + { + os << "Plot Vectors\n"; + } + else if ( this->PlotMode == VTK_PLOT_NORMALS ) + { + os << "Plot Normals\n"; + } + else if ( this->PlotMode == VTK_PLOT_TCOORDS ) + { + os << "Plot TCoords\n"; + } + else if ( this->PlotMode == VTK_PLOT_TENSORS ) + { + os << "Plot Tensors\n"; + } + else + { + os << "Plot Field Data\n"; + } + + os << indent << "Plot Component: "; + if ( this->PlotComponent < 0 ) + { + os << "(All Components)\n"; + } + else + { + os << this->PlotComponent << "\n"; + } + + os << indent << "Field Data Array: " << this->FieldDataArray << "\n"; + + os << indent << "Use Default Normal: " + << (this->UseDefaultNormal ? "On\n" : "Off\n"); + os << indent << "Default Normal: " << "( " << this->DefaultNormal[0] + << ", " << this->DefaultNormal[1] << ", " << this->DefaultNormal[2] + << " )\n"; + + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Height: " << this->Height << "\n"; + os << indent << "Offset: " << this->Offset << "\n"; +} diff --git a/Hybrid/vtkArcPlotter.h b/Hybrid/vtkArcPlotter.h new file mode 100644 index 0000000..a27f016 --- /dev/null +++ b/Hybrid/vtkArcPlotter.h @@ -0,0 +1,168 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkArcPlotter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkArcPlotter - plot data along an arbitrary polyline +// .SECTION Description +// vtkArcPlotter performs plotting of attribute data along polylines defined +// with an input vtkPolyData data object. Any type of attribute data can be +// plotted including scalars, vectors, tensors, normals, texture coordinates, +// and field data. Either one or multiple data components can be plotted. +// +// To use this class you must specify an input data set that contains one or +// more polylines, and some attribute data including which component of the +// attribute data. (By default, this class processes the first component of +// scalar data.) You will also need to set an offset radius (the distance +// of the polyline to the median line of the plot), a width for the plot +// (the distance that the minimum and maximum plot values are mapped into), +// an possibly an offset (used to offset attribute data with multiple +// components). +// +// Normally the filter automatically computes normals for generating the +// offset arc plot. However, you can specify a default normal and use that +// instead. + +// .SECTION See Also +// vtkXYPlotActor + +#ifndef __vtkArcPlotter_h +#define __vtkArcPlotter_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_PLOT_SCALARS 1 +#define VTK_PLOT_VECTORS 2 +#define VTK_PLOT_NORMALS 3 +#define VTK_PLOT_TCOORDS 4 +#define VTK_PLOT_TENSORS 5 +#define VTK_PLOT_FIELD_DATA 6 + +class vtkCamera; +class vtkDataArray; +class vtkPointData; +class vtkPoints; + +class VTK_HYBRID_EXPORT vtkArcPlotter : public vtkPolyDataAlgorithm +{ +public: + // Description: + // Instantiate with no default camera and plot mode set to + // VTK_SCALARS. + static vtkArcPlotter *New(); + + vtkTypeRevisionMacro(vtkArcPlotter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify a camera used to orient the plot along the arc. If no camera + // is specified, then the orientation of the plot is arbitrary. + virtual void SetCamera(vtkCamera*); + vtkGetObjectMacro(Camera,vtkCamera); + + // Description: + // Specify which data to plot: scalars, vectors, normals, texture coords, + // tensors, or field data. If the data has more than one component, use + // the method SetPlotComponent to control which component to plot. + vtkSetMacro(PlotMode, int); + vtkGetMacro(PlotMode, int); + void SetPlotModeToPlotScalars() {this->SetPlotMode(VTK_PLOT_SCALARS);}; + void SetPlotModeToPlotVectors() {this->SetPlotMode(VTK_PLOT_VECTORS);}; + void SetPlotModeToPlotNormals() {this->SetPlotMode(VTK_PLOT_NORMALS);}; + void SetPlotModeToPlotTCoords() {this->SetPlotMode(VTK_PLOT_TCOORDS);}; + void SetPlotModeToPlotTensors() {this->SetPlotMode(VTK_PLOT_TENSORS);}; + void SetPlotModeToPlotFieldData() + {this->SetPlotMode(VTK_PLOT_FIELD_DATA);}; + + // Description: + // Set/Get the component number to plot if the data has more than one + // component. If the value of the plot component is == (-1), then all + // the components will be plotted. + vtkSetMacro(PlotComponent,int); + vtkGetMacro(PlotComponent,int); + + // Description: + // Set the radius of the "median" value of the first plotted component. + vtkSetClampMacro(Radius,double,0.0,VTK_LARGE_FLOAT); + vtkGetMacro(Radius,double); + + // Description: + // Set the height of the plot. (The radius combined with the height + // define the location of the plot relative to the generating polyline.) + vtkSetClampMacro(Height,double,0.0,VTK_LARGE_FLOAT); + vtkGetMacro(Height,double); + + // Description: + // Specify an offset that translates each subsequent plot (if there is + // more than one component plotted) from the defining arc (i.e., polyline). + vtkSetClampMacro(Offset, double, 0.0, VTK_LARGE_FLOAT); + vtkGetMacro(Offset, double); + + // Description: + // Set a boolean to control whether to use default normals. + // By default, normals are automatically computed from the generating + // polyline and camera. + vtkSetMacro(UseDefaultNormal,int); + vtkGetMacro(UseDefaultNormal,int); + vtkBooleanMacro(UseDefaultNormal,int); + + // Description: + // Set the default normal to use if you do not wish automatic normal + // calculation. The arc plot will be generated using this normal. + vtkSetVector3Macro(DefaultNormal,float); + vtkGetVectorMacro(DefaultNormal,float,3); + + // Description: + // Set/Get the field data array to plot. This instance variable is + // only applicable if field data is plotted. + vtkSetClampMacro(FieldDataArray,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(FieldDataArray,int); + + // Description: + // New GetMTime because of camera dependency. + unsigned long GetMTime(); + +protected: + vtkArcPlotter(); + ~vtkArcPlotter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int OffsetPoint(vtkIdType ptId, vtkPoints *inPts, double n[3], + vtkPoints *newPts, double offset, + double *range, double val); + int ProcessComponents(vtkIdType numPts, vtkPointData *pd); + + vtkCamera *Camera; + int PlotMode; + int PlotComponent; + double Radius; + double Height; + double Offset; + float DefaultNormal[3]; + int UseDefaultNormal; + int FieldDataArray; + +private: + vtkDataArray *Data; + double *DataRange; + double *Tuple; + int NumberOfComponents; + int ActiveComponent; + int StartComp; + int EndComp; + +private: + vtkArcPlotter(const vtkArcPlotter&); // Not implemented. + void operator=(const vtkArcPlotter&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkAxesActor.cxx b/Hybrid/vtkAxesActor.cxx new file mode 100644 index 0000000..3da6ac1 --- /dev/null +++ b/Hybrid/vtkAxesActor.cxx @@ -0,0 +1,831 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAxesActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAxesActor.h" + +#include "vtkActor.h" +#include "vtkCaptionActor2D.h" +#include "vtkConeSource.h" +#include "vtkCylinderSource.h" +#include "vtkLineSource.h" +#include "vtkObject.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPropCollection.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkSphereSource.h" +#include "vtkTextProperty.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkAxesActor, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkAxesActor); + +vtkCxxSetObjectMacro( vtkAxesActor, UserDefinedTip, vtkPolyData ); +vtkCxxSetObjectMacro( vtkAxesActor, UserDefinedShaft, vtkPolyData ); + +vtkAxesActor::vtkAxesActor() +{ + this->AxisLabels = 1; + + this->XAxisLabelText = NULL; + this->YAxisLabelText = NULL; + this->ZAxisLabelText = NULL; + + this->SetXAxisLabelText("X"); + this->SetYAxisLabelText("Y"); + this->SetZAxisLabelText("Z"); + + this->XAxisShaft = vtkActor::New(); + this->XAxisShaft->GetProperty()->SetColor(1, 0, 0); + this->YAxisShaft = vtkActor::New(); + this->YAxisShaft->GetProperty()->SetColor(0, 1, 0); + this->ZAxisShaft = vtkActor::New(); + this->ZAxisShaft->GetProperty()->SetColor(0, 0, 1); + + this->XAxisTip = vtkActor::New(); + this->XAxisTip->GetProperty()->SetColor(1, 0, 0); + this->YAxisTip = vtkActor::New(); + this->YAxisTip->GetProperty()->SetColor(0, 1, 0); + this->ZAxisTip = vtkActor::New(); + this->ZAxisTip->GetProperty()->SetColor(0, 0, 1); + + this->CylinderSource = vtkCylinderSource::New(); + this->CylinderSource->SetHeight(1.0); + + this->LineSource = vtkLineSource::New(); + this->LineSource->SetPoint1( 0.0, 0.0, 0.0 ); + this->LineSource->SetPoint2( 0.0, 1.0, 0.0 ); + + this->ConeSource = vtkConeSource::New(); + this->ConeSource->SetDirection( 0, 1, 0 ); + this->ConeSource->SetHeight( 1.0 ); + + this->SphereSource = vtkSphereSource::New(); + + vtkPolyDataMapper *shaftMapper = vtkPolyDataMapper::New(); + + this->XAxisShaft->SetMapper( shaftMapper ); + this->YAxisShaft->SetMapper( shaftMapper ); + this->ZAxisShaft->SetMapper( shaftMapper ); + + shaftMapper->Delete(); + + vtkPolyDataMapper *tipMapper = vtkPolyDataMapper::New(); + + this->XAxisTip->SetMapper( tipMapper ); + this->YAxisTip->SetMapper( tipMapper ); + this->ZAxisTip->SetMapper( tipMapper ); + + tipMapper->Delete(); + + this->TotalLength[0] = 1.0; + this->TotalLength[1] = 1.0; + this->TotalLength[2] = 1.0; + + this->NormalizedShaftLength[0] = 0.8; + this->NormalizedShaftLength[1] = 0.8; + this->NormalizedShaftLength[2] = 0.8; + + this->NormalizedTipLength[0] = 0.2; + this->NormalizedTipLength[1] = 0.2; + this->NormalizedTipLength[2] = 0.2; + + this->NormalizedLabelPosition[0] = 1.0; + this->NormalizedLabelPosition[1] = 1.0; + this->NormalizedLabelPosition[2] = 1.0; + + this->ConeResolution = 16; + this->SphereResolution = 16; + this->CylinderResolution = 16; + + this->ConeRadius = 0.4; + this->SphereRadius = 0.5; + this->CylinderRadius = 0.05; + + this->ShaftType = vtkAxesActor::LINE_SHAFT; + this->TipType = vtkAxesActor::CONE_TIP; + + this->UserDefinedTip = NULL; + this->UserDefinedShaft = NULL; + + this->XAxisLabel = vtkCaptionActor2D::New(); + this->YAxisLabel = vtkCaptionActor2D::New(); + this->ZAxisLabel = vtkCaptionActor2D::New(); + + this->XAxisLabel->ThreeDimensionalLeaderOff(); + this->XAxisLabel->LeaderOff(); + this->XAxisLabel->BorderOff(); + this->XAxisLabel->SetPosition(0, 0); + + this->YAxisLabel->ThreeDimensionalLeaderOff(); + this->YAxisLabel->LeaderOff(); + this->YAxisLabel->BorderOff(); + this->YAxisLabel->SetPosition(0, 0); + + this->ZAxisLabel->ThreeDimensionalLeaderOff(); + this->ZAxisLabel->LeaderOff(); + this->ZAxisLabel->BorderOff(); + this->ZAxisLabel->SetPosition(0, 0); + + this->UpdateProps(); +} + +vtkAxesActor::~vtkAxesActor() +{ + this->CylinderSource->Delete(); + this->LineSource->Delete(); + this->ConeSource->Delete(); + this->SphereSource->Delete(); + + this->XAxisShaft->Delete(); + this->YAxisShaft->Delete(); + this->ZAxisShaft->Delete(); + + this->XAxisTip->Delete(); + this->YAxisTip->Delete(); + this->ZAxisTip->Delete(); + + this->SetUserDefinedTip( NULL ); + this->SetUserDefinedShaft( NULL ); + + this->SetXAxisLabelText( NULL ); + this->SetYAxisLabelText( NULL ); + this->SetZAxisLabelText( NULL ); + + this->XAxisLabel->Delete(); + this->YAxisLabel->Delete(); + this->ZAxisLabel->Delete(); +} + +// Shallow copy of an actor. +void vtkAxesActor::ShallowCopy(vtkProp *prop) +{ + vtkAxesActor *a = vtkAxesActor::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetAxisLabels( a->GetAxisLabels() ); + this->SetXAxisLabelText( a->GetXAxisLabelText() ); + this->SetYAxisLabelText( a->GetYAxisLabelText() ); + this->SetZAxisLabelText( a->GetZAxisLabelText() ); + this->SetTotalLength( a->GetTotalLength() ); + this->SetNormalizedShaftLength( a->GetNormalizedShaftLength() ); + this->SetNormalizedTipLength( a->GetNormalizedTipLength() ); + this->SetNormalizedLabelPosition( a->GetNormalizedLabelPosition() ); + this->SetConeResolution( a->GetConeResolution() ); + this->SetSphereResolution( a->GetSphereResolution() ); + this->SetCylinderResolution( a->GetCylinderResolution() ); + this->SetConeRadius( a->GetConeRadius() ); + this->SetSphereRadius( a->GetSphereRadius() ); + this->SetCylinderRadius( a->GetCylinderRadius() ); + this->SetTipType( a->GetTipType() ); + this->SetShaftType( a->GetShaftType() ); + this->SetUserDefinedTip( a->GetUserDefinedTip() ); + this->SetUserDefinedShaft( a->GetUserDefinedShaft() ); + } + + // Now do superclass + this->vtkProp3D::ShallowCopy(prop); +} + +void vtkAxesActor::GetActors(vtkPropCollection *ac) +{ + ac->AddItem( this->XAxisShaft ); + ac->AddItem( this->YAxisShaft ); + ac->AddItem( this->ZAxisShaft ); + ac->AddItem( this->XAxisTip ); + ac->AddItem( this->YAxisTip ); + ac->AddItem( this->ZAxisTip ); +} + +int vtkAxesActor::RenderOpaqueGeometry(vtkViewport *vp) +{ + int renderedSomething = 0; + + this->UpdateProps(); + + renderedSomething += this->XAxisShaft->RenderOpaqueGeometry( vp ); + renderedSomething += this->YAxisShaft->RenderOpaqueGeometry( vp ); + renderedSomething += this->ZAxisShaft->RenderOpaqueGeometry( vp ); + + renderedSomething += this->XAxisTip->RenderOpaqueGeometry( vp ); + renderedSomething += this->YAxisTip->RenderOpaqueGeometry( vp ); + renderedSomething += this->ZAxisTip->RenderOpaqueGeometry( vp ); + + if ( this->AxisLabels ) + { + renderedSomething += this->XAxisLabel->RenderOpaqueGeometry( vp ); + renderedSomething += this->YAxisLabel->RenderOpaqueGeometry( vp ); + renderedSomething += this->ZAxisLabel->RenderOpaqueGeometry( vp ); + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + return renderedSomething; +} + +int vtkAxesActor::RenderTranslucentGeometry(vtkViewport *vp) +{ + int renderedSomething = 0; + + this->UpdateProps(); + + renderedSomething += this->XAxisShaft->RenderTranslucentGeometry( vp ); + renderedSomething += this->YAxisShaft->RenderTranslucentGeometry( vp ); + renderedSomething += this->ZAxisShaft->RenderTranslucentGeometry( vp ); + + renderedSomething += this->XAxisTip->RenderTranslucentGeometry( vp ); + renderedSomething += this->YAxisTip->RenderTranslucentGeometry( vp ); + renderedSomething += this->ZAxisTip->RenderTranslucentGeometry( vp ); + + if ( this->AxisLabels ) + { + renderedSomething += this->XAxisLabel->RenderTranslucentGeometry( vp ); + renderedSomething += this->YAxisLabel->RenderTranslucentGeometry( vp ); + renderedSomething += this->ZAxisLabel->RenderTranslucentGeometry( vp ); + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + return renderedSomething; +} + +int vtkAxesActor::RenderOverlay(vtkViewport *vp) +{ + int renderedSomething = 0; + + if ( !this->AxisLabels ) + { + return renderedSomething; + } + + this->UpdateProps(); + + renderedSomething += this->XAxisLabel->RenderOverlay( vp ); + renderedSomething += this->YAxisLabel->RenderOverlay( vp ); + renderedSomething += this->ZAxisLabel->RenderOverlay( vp ); + + renderedSomething = (renderedSomething > 0)?(1):(0); + return renderedSomething; +} + +void vtkAxesActor::ReleaseGraphicsResources(vtkWindow *win) +{ + this->XAxisShaft->ReleaseGraphicsResources( win ); + this->YAxisShaft->ReleaseGraphicsResources( win ); + this->ZAxisShaft->ReleaseGraphicsResources( win ); + + this->XAxisTip->ReleaseGraphicsResources( win ); + this->YAxisTip->ReleaseGraphicsResources( win ); + this->ZAxisTip->ReleaseGraphicsResources( win ); + + this->XAxisLabel->ReleaseGraphicsResources( win ); + this->YAxisLabel->ReleaseGraphicsResources( win ); + this->ZAxisLabel->ReleaseGraphicsResources( win ); +} + +void vtkAxesActor::GetBounds(double bounds[6]) +{ + double *bds = this->GetBounds(); + bounds[0] = bds[0]; + bounds[1] = bds[1]; + bounds[2] = bds[2]; + bounds[3] = bds[3]; + bounds[4] = bds[4]; + bounds[5] = bds[5]; +} + +// Get the bounds for this Actor as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkAxesActor::GetBounds() +{ + double bounds[6]; + int i; + + this->XAxisShaft->GetBounds(this->Bounds); + + this->YAxisShaft->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->ZAxisShaft->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->XAxisTip->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->YAxisTip->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + this->ZAxisTip->GetBounds(bounds); + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (bounds[2*i+1]>this->Bounds[2*i+1])?(bounds[2*i+1]):(this->Bounds[2*i+1]); + } + + double dbounds[6]; + (vtkPolyDataMapper::SafeDownCast(this->YAxisShaft->GetMapper()))-> + GetInput()->GetBounds( dbounds ); + + for (i=0; i<3; i++) + { + this->Bounds[2*i+1] = + (dbounds[2*i+1]>this->Bounds[2*i+1])?(dbounds[2*i+1]):(this->Bounds[2*i+1]); + } + + // We want this actor to rotate / re-center about the origin, so give it + // the bounds it would have if the axes were symmetric. + for (i = 0; i < 3; i++) + { + this->Bounds[2*i] = -this->Bounds[2*i+1]; + } + + return this->Bounds; +} + +unsigned long int vtkAxesActor::GetMTime() +{ + unsigned long mTime = this->Superclass::GetMTime(); + return mTime; +} + +unsigned long int vtkAxesActor::GetRedrawMTime() +{ + unsigned long mTime = this->GetMTime(); + return mTime; +} + +void vtkAxesActor::SetTotalLength( double x, double y, double z ) +{ + if ( this->TotalLength[0] != x || + this->TotalLength[1] != y || + this->TotalLength[2] != z ) + { + this->TotalLength[0] = x; + this->TotalLength[1] = y; + this->TotalLength[2] = z; + + if ( x < 0.0 || y < 0.0 || z < 0.0) + { + vtkGenericWarningMacro("One or more axes lengths are < 0 \ + and may produce unexpected results."); + } + + this->Modified(); + + this->UpdateProps(); + } +} + +void vtkAxesActor::SetNormalizedShaftLength( double x, double y, double z ) +{ + if ( this->NormalizedShaftLength[0] != x || + this->NormalizedShaftLength[1] != y || + this->NormalizedShaftLength[2] != z ) + { + this->NormalizedShaftLength[0] = x; + this->NormalizedShaftLength[1] = y; + this->NormalizedShaftLength[2] = z; + + if ( x < 0.0 || x > 1.0 || y < 0.0 || y > 1.0 || z < 0.0 || z > 1.0 ) + { + vtkGenericWarningMacro( "One or more normalized shaft lengths \ + are < 0 or > 1 and may produce unexpected results." ); + } + + this->Modified(); + + this->UpdateProps(); + } +} + +void vtkAxesActor::SetNormalizedTipLength( double x, double y, double z ) +{ + if ( this->NormalizedTipLength[0] != x || + this->NormalizedTipLength[1] != y || + this->NormalizedTipLength[2] != z ) + { + this->NormalizedTipLength[0] = x; + this->NormalizedTipLength[1] = y; + this->NormalizedTipLength[2] = z; + + if ( x < 0.0 || x > 1.0 || y < 0.0 || y > 1.0 || z < 0.0 || z > 1.0 ) + { + vtkGenericWarningMacro( "One or more normalized tip lengths \ + are < 0 or > 1 and may produce unexpected results." ); + } + + this->Modified(); + + this->UpdateProps(); + } +} + +void vtkAxesActor::SetNormalizedLabelPosition( double x, double y, double z ) +{ + if ( this->NormalizedLabelPosition[0] != x || + this->NormalizedLabelPosition[1] != y || + this->NormalizedLabelPosition[2] != z ) + { + this->NormalizedLabelPosition[0] = x; + this->NormalizedLabelPosition[1] = y; + this->NormalizedLabelPosition[2] = z; + + if ( x < 0.0 || y < 0.0 || z < 0.0 ) + { + vtkGenericWarningMacro( "One or more label positions are < 0 \ + and may produce unexpected results." ); + } + + this->Modified(); + + this->UpdateProps(); + } +} + +void vtkAxesActor::SetShaftType( int type ) +{ + if ( this->ShaftType != type ) + { + if (type < vtkAxesActor::CYLINDER_SHAFT || \ + type > vtkAxesActor::USER_DEFINED_SHAFT) + { + vtkErrorMacro( "Undefined axes shaft type." ); + return; + } + + if ( type == vtkAxesActor::USER_DEFINED_SHAFT && \ + this->UserDefinedShaft == NULL) + { + vtkErrorMacro( "Set the user defined shaft before changing the type." ); + return; + } + + this->ShaftType = type; + + this->Modified(); + + this->UpdateProps(); + } +} + +void vtkAxesActor::SetTipType( int type ) +{ + if ( this->TipType != type ) + { + if (type < vtkAxesActor::CONE_TIP || \ + type > vtkAxesActor::USER_DEFINED_TIP) + { + vtkErrorMacro( "Undefined axes tip type." ); + return; + } + + if ( type == vtkAxesActor::USER_DEFINED_TIP && \ + this->UserDefinedTip == NULL) + { + vtkErrorMacro( "Set the user defined tip before changing the type." ); + return; + } + + this->TipType = type; + + this->Modified(); + + this->UpdateProps(); + } +} + +void vtkAxesActor::UpdateProps() +{ + this->CylinderSource->SetRadius( this->CylinderRadius ); + this->CylinderSource->SetResolution( this->CylinderResolution ); + + this->ConeSource->SetResolution( this->ConeResolution ); + this->ConeSource->SetRadius( this->ConeRadius ); + + this->SphereSource->SetThetaResolution( this->SphereResolution ); + this->SphereSource->SetPhiResolution( this->SphereResolution ); + this->SphereSource->SetRadius( this->SphereRadius ); + + switch ( this->ShaftType ) + { + case vtkAxesActor::CYLINDER_SHAFT: + (vtkPolyDataMapper::SafeDownCast(this->XAxisShaft->GetMapper()))-> + SetInput( this->CylinderSource->GetOutput() ); + break; + case vtkAxesActor::LINE_SHAFT: + (vtkPolyDataMapper::SafeDownCast(this->XAxisShaft->GetMapper()))-> + SetInput( this->LineSource->GetOutput() ); + break; + case vtkAxesActor::USER_DEFINED_SHAFT: + (vtkPolyDataMapper::SafeDownCast(this->XAxisShaft->GetMapper()))-> + SetInput( this->UserDefinedShaft ); + } + + switch ( this->TipType ) + { + case vtkAxesActor::CONE_TIP: + (vtkPolyDataMapper::SafeDownCast(this->XAxisTip->GetMapper()))-> + SetInput( this->ConeSource->GetOutput() ); + break; + case vtkAxesActor::SPHERE_TIP: + (vtkPolyDataMapper::SafeDownCast(this->XAxisTip->GetMapper()))-> + SetInput( this->SphereSource->GetOutput() ); + break; + case vtkAxesActor::USER_DEFINED_TIP: + (vtkPolyDataMapper::SafeDownCast(this->XAxisTip->GetMapper()))-> + SetInput( this->UserDefinedTip ); + } + + (vtkPolyDataMapper::SafeDownCast(this->XAxisTip->GetMapper()))-> + GetInput()->Update(); + (vtkPolyDataMapper::SafeDownCast(this->XAxisShaft->GetMapper()))-> + GetInput()->Update(); + + if ( this->GetUserTransform() ) + { + this->XAxisShaft->SetUserTransform( NULL ); + this->YAxisShaft->SetUserTransform( NULL ); + this->ZAxisShaft->SetUserTransform( NULL ); + this->XAxisTip->SetUserTransform( NULL ); + this->YAxisTip->SetUserTransform( NULL ); + this->ZAxisTip->SetUserTransform( NULL ); + } + + double scale[3]; + double bounds[6]; + + (vtkPolyDataMapper::SafeDownCast(this->XAxisShaft->GetMapper()))-> + GetInput()->GetBounds( bounds ); + + // The shaft and tip geometry are both initially along direction 0 1 0 + // in the case of cylinder, line, and cone. Build up the axis from + // constituent elements defined in their default positions. + + int i; + for ( i = 0; i < 3; i++ ) + { + scale[i] = + this->NormalizedShaftLength[i]*this->TotalLength[i] / + (bounds[3] - bounds[2]); + } + + vtkTransform *xTransform = vtkTransform::New(); + vtkTransform *yTransform = vtkTransform::New(); + vtkTransform *zTransform = vtkTransform::New(); + + xTransform->RotateZ( -90 ); + zTransform->RotateX( 90 ); + + xTransform->Scale( scale[0], scale[0], scale[0] ); + yTransform->Scale( scale[1], scale[1], scale[1] ); + zTransform->Scale( scale[2], scale[2], scale[2] ); + + xTransform->Translate( -(bounds[0]+bounds[1])/2, + -bounds[2], + -(bounds[4]+bounds[5])/2 ); + yTransform->Translate( -(bounds[0]+bounds[1])/2, + -bounds[2], + -(bounds[4]+bounds[5])/2 ); + zTransform->Translate( -(bounds[0]+bounds[1])/2, + -bounds[2], + -(bounds[4]+bounds[5])/2 ); + + this->XAxisShaft->SetScale( xTransform->GetScale() ); + this->XAxisShaft->SetPosition( xTransform->GetPosition() ); + this->XAxisShaft->SetOrientation( xTransform->GetOrientation() ); + + this->YAxisShaft->SetScale( yTransform->GetScale() ); + this->YAxisShaft->SetPosition( yTransform->GetPosition() ); + this->YAxisShaft->SetOrientation( yTransform->GetOrientation() ); + + this->ZAxisShaft->SetScale( zTransform->GetScale() ); + this->ZAxisShaft->SetPosition( zTransform->GetPosition() ); + this->ZAxisShaft->SetOrientation( zTransform->GetOrientation() ); + + (vtkPolyDataMapper::SafeDownCast(this->XAxisTip->GetMapper()))-> + GetInput()->GetBounds( bounds ); + + xTransform->Identity(); + yTransform->Identity(); + zTransform->Identity(); + + xTransform->RotateZ( -90 ); + zTransform->RotateX( 90 ); + + xTransform->Scale( this->TotalLength[0], this->TotalLength[0], this->TotalLength[0] ); + yTransform->Scale( this->TotalLength[1], this->TotalLength[1], this->TotalLength[1] ); + zTransform->Scale( this->TotalLength[2], this->TotalLength[2], this->TotalLength[2] ); + + xTransform->Translate( 0, (1.0 - this->NormalizedTipLength[0]), 0 ); + yTransform->Translate( 0, (1.0 - this->NormalizedTipLength[1]), 0 ); + zTransform->Translate( 0, (1.0 - this->NormalizedTipLength[2]), 0 ); + + xTransform->Scale( this->NormalizedTipLength[0], + this->NormalizedTipLength[0], + this->NormalizedTipLength[0] ); + + yTransform->Scale( this->NormalizedTipLength[1], + this->NormalizedTipLength[1], + this->NormalizedTipLength[1] ); + + zTransform->Scale( this->NormalizedTipLength[2], + this->NormalizedTipLength[2], + this->NormalizedTipLength[2] ); + + xTransform->Translate( -(bounds[0]+bounds[1])/2, + -bounds[2], + -(bounds[4]+bounds[5])/2 ); + yTransform->Translate( -(bounds[0]+bounds[1])/2, + -bounds[2], + -(bounds[4]+bounds[5])/2 ); + zTransform->Translate( -(bounds[0]+bounds[1])/2, + -bounds[2], + -(bounds[4]+bounds[5])/2 ); + + this->XAxisTip->SetScale( xTransform->GetScale() ); + this->XAxisTip->SetPosition( xTransform->GetPosition() ); + this->XAxisTip->SetOrientation( xTransform->GetOrientation() ); + + this->YAxisTip->SetScale( yTransform->GetScale() ); + this->YAxisTip->SetPosition( yTransform->GetPosition() ); + this->YAxisTip->SetOrientation( yTransform->GetOrientation() ); + + this->ZAxisTip->SetScale( zTransform->GetScale() ); + this->ZAxisTip->SetPosition( zTransform->GetPosition() ); + this->ZAxisTip->SetOrientation( zTransform->GetOrientation() ); + + xTransform->Delete(); + yTransform->Delete(); + zTransform->Delete(); + + this->XAxisLabel->SetCaption( this->XAxisLabelText ); + this->YAxisLabel->SetCaption( this->YAxisLabelText ); + this->ZAxisLabel->SetCaption( this->ZAxisLabelText ); + + this->XAxisShaft->GetBounds(bounds); + double offset = this->NormalizedLabelPosition[0]*(bounds[1]-bounds[0]); + this->XAxisLabel->SetAttachmentPoint( bounds[0] + offset, + bounds[2] - (bounds[3]-bounds[2])*2.0, + bounds[5] + (bounds[5]-bounds[4])/2.0); + + this->YAxisShaft->GetBounds(bounds); + offset = this->NormalizedLabelPosition[1]*(bounds[3]-bounds[2]); + this->YAxisLabel->SetAttachmentPoint( (bounds[0]+bounds[1])/2, + bounds[2] + offset, + bounds[5] + (bounds[5]-bounds[4])/2.0 ); + + this->ZAxisShaft->GetBounds(bounds); + offset = this->NormalizedLabelPosition[2]*(bounds[5]-bounds[4]); + this->ZAxisLabel->SetAttachmentPoint( bounds[0], + bounds[2] - (bounds[3]-bounds[2])*2.0, + bounds[4] + offset ); + + vtkLinearTransform* transform = this->GetUserTransform(); + if ( transform ) + { + this->XAxisShaft->SetUserTransform( transform ); + this->YAxisShaft->SetUserTransform( transform ); + this->ZAxisShaft->SetUserTransform( transform ); + + this->XAxisTip->SetUserTransform( transform ); + this->YAxisTip->SetUserTransform( transform ); + this->ZAxisTip->SetUserTransform( transform ); + + double newpos[3]; + double* pos = this->XAxisLabel->GetAttachmentPoint(); + transform->TransformVector( pos, newpos ); + this->XAxisLabel->SetAttachmentPoint( newpos ); + + pos = this->YAxisLabel->GetAttachmentPoint(); + transform->TransformVector( pos, newpos ); + this->YAxisLabel->SetAttachmentPoint( newpos ); + + pos = this->ZAxisLabel->GetAttachmentPoint(); + transform->TransformVector( pos, newpos ); + this->ZAxisLabel->SetAttachmentPoint( newpos ); + } + +} + +vtkProperty *vtkAxesActor::GetXAxisTipProperty() +{ + return this->XAxisTip->GetProperty(); +} + +vtkProperty *vtkAxesActor::GetYAxisTipProperty() +{ + return this->YAxisTip->GetProperty(); +} + +vtkProperty *vtkAxesActor::GetZAxisTipProperty() +{ + return this->ZAxisTip->GetProperty(); +} + +vtkProperty *vtkAxesActor::GetXAxisShaftProperty() +{ + return this->XAxisShaft->GetProperty(); +} + +vtkProperty *vtkAxesActor::GetYAxisShaftProperty() +{ + return this->YAxisShaft->GetProperty(); +} + +vtkProperty *vtkAxesActor::GetZAxisShaftProperty() +{ + return this->ZAxisShaft->GetProperty(); +} + +void vtkAxesActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "UserDefinedShaft: "; + if (this->UserDefinedShaft) + { + os << this->UserDefinedShaft << endl; + } + else + { + os << "(none)" << endl; + } + + os << indent << "UserDefinedTip: "; + if (this->UserDefinedTip) + { + os << this->UserDefinedTip << endl; + } + else + { + os << "(none)" << endl; + } + + os << indent << "XAxisLabelText: " << (this->XAxisLabelText ? + this->XAxisLabelText : "(none)") + << endl; + os << indent << "YAxisLabelText: " << (this->YAxisLabelText ? + this->YAxisLabelText : "(none)") + << endl; + os << indent << "ZAxisLabelText: " << (this->ZAxisLabelText ? + this->ZAxisLabelText : "(none)") + << endl; + + os << indent << "AxisLabels: " << (this->AxisLabels ? "On\n" : "Off\n"); + + os << indent << "ShaftType: " << this->ShaftType << endl; + os << indent << "TipType: " << this->TipType << endl; + os << indent << "SphereRadius: " << this->SphereRadius << endl; + os << indent << "SphereResolution: " << this->SphereResolution << endl; + os << indent << "CylinderRadius: " << this->CylinderRadius << endl; + os << indent << "CylinderResolution: " << this->CylinderResolution << endl; + os << indent << "ConeRadius: " << this->ConeRadius << endl; + os << indent << "ConeResolution: " << this->ConeResolution << endl; + + os << indent << "NormalizedShaftLength: " + << this->NormalizedShaftLength[0] << "," + << this->NormalizedShaftLength[1] << "," + << this->NormalizedShaftLength[2] << endl; + + os << indent << "NormalizedTipLength: " + << this->NormalizedTipLength[0] << "," + << this->NormalizedTipLength[1] << "," + << this->NormalizedTipLength[2] << endl; + + os << indent << "TotalLength: " + << this->TotalLength[0] << "," + << this->TotalLength[1] << "," + << this->TotalLength[2] << endl; + + os << indent << "NormalizedLabelPosition: " + << this->NormalizedLabelPosition[0] << "," + << this->NormalizedLabelPosition[1] << "," + << this->NormalizedLabelPosition[2] << endl; +} diff --git a/Hybrid/vtkAxesActor.h b/Hybrid/vtkAxesActor.h new file mode 100644 index 0000000..e472759 --- /dev/null +++ b/Hybrid/vtkAxesActor.h @@ -0,0 +1,295 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAxesActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAxesActor - a 3D axes representation +// .SECTION Description +// vtkAxesActor is a hybrid 2D/3D actor used to represent 3D axes in a scene. +// The user can define the geometry to use for the shaft or the tip, and the +// user can set the text for the three axes. The text will appear to follow the +// camera since it is implemented by means of vtkCaptionActor2D. All of the +// functionality of the underlying vtkCaptionActor2D objects are accessable so +// that, for instance, the font attributes of the axes text can be manipulated +// through vtkTextProperty. Since this class inherits from vtkProp3D, one can +// apply a user transform to the underlying geometry and the positioning of the +// labels. For example, a rotation transform could be used to generate a +// left-handed axes representation. + +// .SECTION Thanks +// Thanks to Goodwin Lawlor for posting a tcl script which featured the +// use of vtkCaptionActor2D to implement the text labels. This class is +// based on Paraview's vtkPVAxesActor. + +// .SECTION Caveats +// vtkAxesActor is primarily intended for use with vtkOrientationMarkerWidget. +// The bounds of this actor are calculated as though the geometry of the axes +// were symmetric: that is, although only positive axes are visible, bounds +// are calculated as though negative axes are present too. This is done +// intentionally to implement functionality of the camera update mechanism +// in vtkOrientationMarkerWidget. + +// .SECTION See Also +// vtkAnnotatedCubeActor vtkOrientationMarkerWidget vtkCaptionActor2D +// vtkTextProperty + +#ifndef __vtkAxesActor_h +#define __vtkAxesActor_h + +#include "vtkProp3D.h" + +class vtkActor; +class vtkCaptionActor2D; +class vtkConeSource; +class vtkCylinderSource; +class vtkLineSource; +class vtkPolyData; +class vtkPropCollection; +class vtkProperty; +class vtkRenderer; +class vtkSphereSource; + +class VTK_HYBRID_EXPORT vtkAxesActor : public vtkProp3D +{ +public: + static vtkAxesActor *New(); + vtkTypeRevisionMacro(vtkAxesActor,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. These methods + // are used in that process. + virtual void GetActors(vtkPropCollection *); + + // Description: + // Support the standard render methods. + virtual int RenderOpaqueGeometry(vtkViewport *viewport); + virtual int RenderTranslucentGeometry(vtkViewport *viewport); + virtual int RenderOverlay(vtkViewport *viewport); + + // Description: + // Shallow copy of an axes actor. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Get the bounds for this Actor as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). (The + // method GetBounds(double bounds[6]) is available from the superclass.) + void GetBounds(double bounds[6]); + double *GetBounds(); + + // Description: + // Get the actors mtime plus consider its properties and texture if set. + unsigned long int GetMTime(); + + // Description: + // Return the mtime of anything that would cause the rendered image to + // appear differently. Usually this involves checking the mtime of the + // prop plus anything else it depends on such as properties, textures + // etc. + virtual unsigned long GetRedrawMTime(); + + // Description: + // Set the total length of the axes in 3 dimensions. + void SetTotalLength( double v[3] ) + { this->SetTotalLength( v[0], v[1], v[2] ); } + void SetTotalLength( double x, double y, double z ); + vtkGetVectorMacro( TotalLength, double, 3 ); + + // Description: + // Set the normalized (0-1) length of the shaft. + void SetNormalizedShaftLength( double v[3] ) + { this->SetNormalizedShaftLength( v[0], v[1], v[2] ); } + void SetNormalizedShaftLength( double x, double y, double z ); + vtkGetVectorMacro( NormalizedShaftLength, double, 3 ); + + // Description: + // Set the normalized (0-1) length of the tip. Normally, this would be + // 1 - the normalized length of the shaft. + void SetNormalizedTipLength( double v[3] ) + { this->SetNormalizedTipLength( v[0], v[1], v[2] ); } + void SetNormalizedTipLength( double x, double y, double z ); + vtkGetVectorMacro( NormalizedTipLength, double, 3 ); + + // Description: + // Set the normalized (0-1) position of the label along the length of + // the shaft. A value > 1 is permissible. + void SetNormalizedLabelPosition( double v[3] ) + { this->SetNormalizedLabelPosition( v[0], v[1], v[2] ); } + void SetNormalizedLabelPosition( double x, double y, double z ); + vtkGetVectorMacro( NormalizedLabelPosition, double, 3 ); + + // Description: + // Set/get the resolution of the pieces of the axes actor. + vtkSetClampMacro(ConeResolution, int, 3, 128); + vtkGetMacro(ConeResolution, int); + vtkSetClampMacro(SphereResolution, int, 3, 128); + vtkGetMacro(SphereResolution, int); + vtkSetClampMacro(CylinderResolution, int, 3, 128); + vtkGetMacro(CylinderResolution, int); + + // Description: + // Set/get the radius of the pieces of the axes actor. + vtkSetClampMacro(ConeRadius, double, 0, VTK_LARGE_FLOAT); + vtkGetMacro(ConeRadius, double); + vtkSetClampMacro(SphereRadius, double, 0, VTK_LARGE_FLOAT); + vtkGetMacro(SphereRadius, double); + vtkSetClampMacro(CylinderRadius, double, 0, VTK_LARGE_FLOAT); + vtkGetMacro(CylinderRadius, double); + + // Description: + // Set the type of the shaft to a cylinder, line, or user defined geometry. + void SetShaftType( int type ); + void SetShaftTypeToCylinder() + { this->SetShaftType( vtkAxesActor::CYLINDER_SHAFT ); } + void SetShaftTypeToLine() + { this->SetShaftType( vtkAxesActor::LINE_SHAFT ); } + void SetShaftTypeToUserDefined() + { this->SetShaftType( vtkAxesActor::USER_DEFINED_SHAFT ); } + vtkGetMacro(ShaftType, int); + + // Description: + // Set the type of the tip to a cone, sphere, or user defined geometry. + void SetTipType( int type ); + void SetTipTypeToCone() + { this->SetTipType( vtkAxesActor::CONE_TIP ); } + void SetTipTypeToSphere() + { this->SetTipType( vtkAxesActor::SPHERE_TIP ); } + void SetTipTypeToUserDefined() + { this->SetTipType( vtkAxesActor::USER_DEFINED_TIP ); } + vtkGetMacro(TipType, int); + + // Description: + // Set the user defined tip polydata. + void SetUserDefinedTip( vtkPolyData * ); + vtkGetObjectMacro( UserDefinedTip, vtkPolyData ); + + // Description: + // Set the user defined shaft polydata. + void SetUserDefinedShaft( vtkPolyData * ); + vtkGetObjectMacro( UserDefinedShaft, vtkPolyData ); + + // Description: + // Get the tip properties. + vtkProperty *GetXAxisTipProperty(); + vtkProperty *GetYAxisTipProperty(); + vtkProperty *GetZAxisTipProperty(); + + // Description: + // Get the shaft properties. + vtkProperty *GetXAxisShaftProperty(); + vtkProperty *GetYAxisShaftProperty(); + vtkProperty *GetZAxisShaftProperty(); + + // Description: + // Retrieve handles to the X, Y and Z axis (so that you can set their text + // properties for example) + vtkCaptionActor2D *GetXAxisCaptionActor2D() + {return this->XAxisLabel;} + vtkCaptionActor2D *GetYAxisCaptionActor2D() + {return this->YAxisLabel;} + vtkCaptionActor2D *GetZAxisCaptionActor2D() + {return this->ZAxisLabel;} + + // Description: + // Set/get the label text. + vtkSetStringMacro( XAxisLabelText ); + vtkGetStringMacro( XAxisLabelText ); + vtkSetStringMacro( YAxisLabelText ); + vtkGetStringMacro( YAxisLabelText ); + vtkSetStringMacro( ZAxisLabelText ); + vtkGetStringMacro( ZAxisLabelText ); + + // Description: + // Enable/disable drawing the axis labels. + vtkSetMacro(AxisLabels, int); + vtkGetMacro(AxisLabels, int); + vtkBooleanMacro(AxisLabels, int); + +//BTX + enum + { + CYLINDER_SHAFT, + LINE_SHAFT, + USER_DEFINED_SHAFT + }; + + enum + { + CONE_TIP, + SPHERE_TIP, + USER_DEFINED_TIP + }; +//ETX + +protected: + vtkAxesActor(); + ~vtkAxesActor(); + + vtkCylinderSource *CylinderSource; + vtkLineSource *LineSource; + vtkConeSource *ConeSource; + vtkSphereSource *SphereSource; + + vtkActor *XAxisShaft; + vtkActor *YAxisShaft; + vtkActor *ZAxisShaft; + + vtkActor *XAxisTip; + vtkActor *YAxisTip; + vtkActor *ZAxisTip; + + void UpdateProps(); + + double TotalLength[3]; + double NormalizedShaftLength[3]; + double NormalizedTipLength[3]; + double NormalizedLabelPosition[3]; + + int ShaftType; + int TipType; + + vtkPolyData *UserDefinedTip; + vtkPolyData *UserDefinedShaft; + + char *XAxisLabelText; + char *YAxisLabelText; + char *ZAxisLabelText; + + vtkCaptionActor2D *XAxisLabel; + vtkCaptionActor2D *YAxisLabel; + vtkCaptionActor2D *ZAxisLabel; + + int AxisLabels; + + + int ConeResolution; + int SphereResolution; + int CylinderResolution; + + double ConeRadius; + double SphereRadius; + double CylinderRadius; + +private: + vtkAxesActor(const vtkAxesActor&); // Not implemented. + void operator=(const vtkAxesActor&); // Not implemented. +}; + +#endif + diff --git a/Hybrid/vtkCaptionActor2D.cxx b/Hybrid/vtkCaptionActor2D.cxx new file mode 100644 index 0000000..e1ae98e --- /dev/null +++ b/Hybrid/vtkCaptionActor2D.cxx @@ -0,0 +1,523 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCaptionActor2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCaptionActor2D.h" + +#include "vtkActor.h" +#include "vtkAppendPolyData.h" +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkGlyph2D.h" +#include "vtkGlyph3D.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkProperty.h" +#include "vtkProperty2D.h" +#include "vtkTextActor.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" + +vtkCxxRevisionMacro(vtkCaptionActor2D, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkCaptionActor2D); + +vtkCxxSetObjectMacro(vtkCaptionActor2D,LeaderGlyph,vtkPolyData); +vtkCxxSetObjectMacro(vtkCaptionActor2D,CaptionTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +vtkCaptionActor2D::vtkCaptionActor2D() +{ + // Positioning information + this->AttachmentPointCoordinate = vtkCoordinate::New(); + this->AttachmentPointCoordinate->SetCoordinateSystemToWorld(); + this->AttachmentPointCoordinate->SetValue(0.0,0.0,0.0); + + this->PositionCoordinate->SetCoordinateSystemToDisplay(); + this->PositionCoordinate->SetReferenceCoordinate( + this->AttachmentPointCoordinate); + this->PositionCoordinate->SetValue(static_cast(10), + static_cast(10)); + + // This sets up the Position2Coordinate + this->vtkActor2D::SetWidth(0.25); + this->vtkActor2D::SetHeight(0.10); + + this->Caption = NULL; + this->Border = 1; + this->Leader = 1; + this->ThreeDimensionalLeader = 1; + this->LeaderGlyphSize = 0.025; + this->MaximumLeaderGlyphSize = 20; + this->LeaderGlyph = NULL; + + // Control font properties + this->Padding = 3; + + this->CaptionTextProperty = vtkTextProperty::New(); + this->CaptionTextProperty->SetBold(1); + this->CaptionTextProperty->SetItalic(1); + this->CaptionTextProperty->SetShadow(1); + this->CaptionTextProperty->SetFontFamily(VTK_ARIAL); + this->CaptionTextProperty->SetJustification(VTK_TEXT_LEFT); + this->CaptionTextProperty->SetVerticalJustification(VTK_TEXT_CENTERED); + + // What is actually drawn + this->TextActor = vtkTextActor::New(); + this->TextActor->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); + this->TextActor->GetPositionCoordinate()->SetReferenceCoordinate(NULL); + this->TextActor->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); + this->TextActor->GetPosition2Coordinate()->SetReferenceCoordinate(NULL); + this->TextActor->SetScaledText(1); + this->TextActor->SetTextProperty(this->CaptionTextProperty); + + this->BorderPolyData = vtkPolyData::New(); + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(4); + this->BorderPolyData->SetPoints(pts); + pts->Delete(); + vtkCellArray *border = vtkCellArray::New(); + border->InsertNextCell(5); + border->InsertCellPoint(0); + border->InsertCellPoint(1); + border->InsertCellPoint(2); + border->InsertCellPoint(3); + border->InsertCellPoint(0); + this->BorderPolyData->SetLines(border); + border->Delete(); + + this->BorderMapper = vtkPolyDataMapper2D::New(); + this->BorderMapper->SetInput(this->BorderPolyData); + this->BorderActor = vtkActor2D::New(); + this->BorderActor->SetMapper(this->BorderMapper); + + // Set border mapper coordinate system to Display. + vtkCoordinate *coord = vtkCoordinate::New(); + coord->SetCoordinateSystemToDisplay(); + this->BorderMapper->SetTransformCoordinate(coord); + coord->Delete(); + + // This is for glyphing the head of the leader + // A single point with a vector for glyph orientation + this->HeadPolyData = vtkPolyData::New(); + pts = vtkPoints::New(); + pts->SetNumberOfPoints(1); + this->HeadPolyData->SetPoints(pts); + pts->Delete(); + vtkDoubleArray *vecs = vtkDoubleArray::New(); + vecs->SetNumberOfComponents(3); + vecs->SetNumberOfTuples(1); + this->HeadPolyData->GetPointData()->SetVectors(vecs); + vecs->Delete(); + + // This is the leader (line) from the attachment point to the caption + this->LeaderPolyData = vtkPolyData::New(); + pts = vtkPoints::New(); + pts->SetNumberOfPoints(2); + this->LeaderPolyData->SetPoints(pts); + pts->Delete(); + vtkCellArray *leader = vtkCellArray::New(); + leader->InsertNextCell(2); + leader->InsertCellPoint(0); + leader->InsertCellPoint(1); //at the attachment point + this->LeaderPolyData->SetLines(leader); + leader->Delete(); + + // Used to generate the glyph on the leader head + this->HeadGlyph = vtkGlyph3D::New(); + this->HeadGlyph->SetInput(this->HeadPolyData); + this->HeadGlyph->SetScaleModeToDataScalingOff(); + this->HeadGlyph->SetScaleFactor(0.1); + + // Appends the leader and the glyph head + this->AppendLeader = vtkAppendPolyData::New(); + this->AppendLeader->UserManagedInputsOn(); + this->AppendLeader->SetNumberOfInputs(2); + this->AppendLeader->SetInputByNumber(0,this->LeaderPolyData); + this->AppendLeader->SetInputByNumber(1,this->HeadGlyph->GetOutput()); + + // Used to transform from world to other coordinate systems + this->MapperCoordinate2D = vtkCoordinate::New(); + this->MapperCoordinate2D->SetCoordinateSystemToWorld(); + + // If 2D leader is used, then use this mapper/actor combination + this->LeaderMapper2D = vtkPolyDataMapper2D::New(); + this->LeaderMapper2D->SetTransformCoordinate(this->MapperCoordinate2D); + this->LeaderActor2D = vtkActor2D::New(); + this->LeaderActor2D->SetMapper(this->LeaderMapper2D); + + // If 3D leader is used, then use this mapper/actor combination + this->LeaderMapper3D = vtkPolyDataMapper::New(); + this->LeaderActor3D = vtkActor::New(); + this->LeaderActor3D->SetMapper(this->LeaderMapper3D); +} + +//---------------------------------------------------------------------------- +vtkCaptionActor2D::~vtkCaptionActor2D() +{ + if ( this->Caption ) + { + delete [] this->Caption; + } + + this->AttachmentPointCoordinate->Delete(); + + this->TextActor->Delete(); + + if ( this->LeaderGlyph ) + { + this->LeaderGlyph->Delete(); + } + + this->BorderPolyData->Delete(); + this->BorderMapper->Delete(); + this->BorderActor->Delete(); + + this->HeadPolyData->Delete(); + this->LeaderPolyData->Delete(); + this->HeadGlyph->Delete(); + this->AppendLeader->Delete(); + + this->MapperCoordinate2D->Delete(); + + this->LeaderMapper2D->Delete(); + this->LeaderActor2D->Delete(); + + this->LeaderMapper3D->Delete(); + this->LeaderActor3D->Delete(); + + this->SetCaptionTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkCaptionActor2D::ReleaseGraphicsResources(vtkWindow *win) +{ + this->TextActor->ReleaseGraphicsResources(win); + this->BorderActor->ReleaseGraphicsResources(win); + this->LeaderActor2D->ReleaseGraphicsResources(win); + this->LeaderActor3D->ReleaseGraphicsResources(win); +} + +int vtkCaptionActor2D::RenderOverlay(vtkViewport *viewport) +{ + int renderedSomething = 0; + + renderedSomething += this->TextActor->RenderOverlay(viewport); + + if ( this->Border ) + { + renderedSomething += this->BorderActor->RenderOverlay(viewport); + } + + if ( this->Leader ) + { + if ( this->ThreeDimensionalLeader ) + { + renderedSomething += this->LeaderActor3D->RenderOverlay(viewport); + } + else + { + renderedSomething += this->LeaderActor2D->RenderOverlay(viewport); + } + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +int vtkCaptionActor2D::RenderOpaqueGeometry(vtkViewport *viewport) +{ + // Build the caption (almost always needed so we don't check mtime) + vtkDebugMacro(<<"Rebuilding caption"); + + // compute coordinates and set point values + // + double *w1, *w2; + int *x1, *x2, *x3; + double p1[4], p2[4], p3[4]; + x1 = this->AttachmentPointCoordinate->GetComputedDisplayValue(viewport); + x2 = this->PositionCoordinate->GetComputedDisplayValue(viewport); + x3 = this->Position2Coordinate->GetComputedDisplayValue(viewport); + p1[0] = (double)x1[0]; p1[1] = (double)x1[1]; p1[2] = 0.0; + p2[0] = (double)x2[0]; p2[1] = (double)x2[1]; p2[2] = p1[2]; + p3[0] = (double)x3[0]; p3[1] = (double)x3[1]; p3[2] = p1[2]; + + // Set up the scaled text - take into account the padding + this->TextActor->SetTextProperty(this->CaptionTextProperty); + this->TextActor->GetPositionCoordinate()->SetValue( + p2[0]+this->Padding,p2[1]+this->Padding,0.0); + this->TextActor->GetPosition2Coordinate()->SetValue( + p3[0]-this->Padding,p3[1]-this->Padding,0.0); + + // Define the border + vtkPoints *pts = this->BorderPolyData->GetPoints(); + pts->SetPoint(0, p2); + pts->SetPoint(1, p3[0],p2[1],p1[2]); + pts->SetPoint(2, p3[0],p3[1],p1[2]); + pts->SetPoint(3, p2[0],p3[1],p1[2]); + + // Define the leader. Have to find the closest point from the + // border to the attachment point. We look at the four vertices + // and four edge centers. + double d2, minD2, pt[3], minPt[3]; + minD2 = VTK_DOUBLE_MAX; + + pt[0] = p2[0]; pt[1] = p2[1]; pt[2] = minPt[2] = 0.0; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + pt[0] = (p2[0]+p3[0])/2.0; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + pt[0] = p3[0]; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + pt[1] = (p2[1]+p3[1])/2.0; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + pt[1] = p3[1]; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + pt[0] = (p2[0]+p3[0])/2.0; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + pt[0] = p2[0]; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + pt[1] = (p2[1]+p3[1])/2.0; + if ( (d2 = vtkMath::Distance2BetweenPoints(p1,pt)) < minD2 ) + { + minD2 = d2; + minPt[0] = pt[0]; minPt[1] = pt[1]; + } + + // Set the leader coordinates in appropriate coordinate system + // The pipeline is connected differently depending on the dimension + // and availability of a leader head. + if ( this->Leader ) + { + pts = this->LeaderPolyData->GetPoints(); + + w1 = this->AttachmentPointCoordinate->GetComputedWorldValue(viewport); + viewport->SetWorldPoint(w1[0],w1[1],w1[2],1.0); + viewport->WorldToView(); + viewport->GetViewPoint(p1); + + // minPt is in display coordinates and it is OK + double val[3]; + val[0] = minPt[0]; + val[1] = minPt[1]; + val[2] = 0; + // convert to view + viewport->DisplayToNormalizedDisplay(val[0],val[1]); + viewport->NormalizedDisplayToViewport(val[0],val[1]); + viewport->ViewportToNormalizedViewport(val[0],val[1]); + viewport->NormalizedViewportToView(val[0],val[1],val[2]); + + // use the zvalue from the attach point + val[2] = p1[2]; + viewport->SetViewPoint(val); + viewport->ViewToWorld(); + double w3[4]; + viewport->GetWorldPoint(w3); + if ( w3[3] != 0.0 ) + { + w3[0] /= w3[3]; w3[1] /= w3[3]; w3[2] /= w3[3]; + } + w2 = w3; + + pts->SetPoint(0, w1); + pts->SetPoint(1, w2); + this->HeadPolyData->GetPoints()->SetPoint(0,w1); + this->HeadPolyData->GetPointData()-> + GetVectors()->SetTuple3(0,w1[0]-w2[0],w1[1]-w2[1],w1[2]-w2[2]); + + pts->Modified(); + this->HeadPolyData->Modified(); + } + + if ( this->LeaderGlyph ) + { + // compute the scale + this->LeaderGlyph->Update(); + double length = this->LeaderGlyph->GetLength(); + int *sze = viewport->GetSize(); + int numPixels = static_cast (this->LeaderGlyphSize * + sqrt(static_cast(sze[0]*sze[0] + sze[1]*sze[1]))); + numPixels = (numPixels > this->MaximumLeaderGlyphSize ? + this->MaximumLeaderGlyphSize : numPixels ); + + // determine the number of units length per pixel + viewport->SetDisplayPoint(sze[0]/2,sze[1]/2,0); + viewport->DisplayToWorld(); + viewport->GetWorldPoint(p1); + if ( p1[3] != 0.0 ) {p1[0] /= p1[3]; p1[1] /= p1[3]; p1[2] /= p1[3];} + + viewport->SetDisplayPoint(sze[0]/2+1,sze[1]/2+1,0); + viewport->DisplayToWorld(); + viewport->GetWorldPoint(p2); + if ( p2[3] != 0.0 ) {p2[0] /= p2[3]; p2[1] /= p2[3]; p2[2] /= p2[3];} + + // Arbitrary 1.5 factor makes up for the use of "diagonals" in length + // calculations; otherwise the scale factor tends to be too small + double sf = 1.5 * numPixels * + sqrt(vtkMath::Distance2BetweenPoints(p1,p2)) / length; + + vtkDebugMacro(<<"Scale factor: " << sf); + + this->HeadGlyph->SetSource(this->LeaderGlyph); + this->HeadGlyph->SetScaleFactor(sf); + + this->LeaderMapper2D->SetInput(this->AppendLeader->GetOutput()); + this->LeaderMapper3D->SetInput(this->AppendLeader->GetOutput()); + this->AppendLeader->Update(); + } + else + { + this->LeaderMapper2D->SetInput(this->LeaderPolyData); + this->LeaderMapper3D->SetInput(this->LeaderPolyData); + this->LeaderPolyData->Update(); + } + + // assign properties + // + this->TextActor->SetInput(this->Caption); + + this->TextActor->SetProperty(this->GetProperty()); + this->BorderActor->SetProperty(this->GetProperty()); + this->LeaderActor2D->SetProperty(this->GetProperty()); + this->LeaderActor3D->GetProperty()->SetColor( + this->GetProperty()->GetColor()); + + // Okay we are ready to render something + int renderedSomething = 0; + renderedSomething += this->TextActor->RenderOpaqueGeometry(viewport); + if ( this->Border ) + { + renderedSomething += this->BorderActor->RenderOpaqueGeometry(viewport); + } + + if ( this->Leader ) + { + if ( this->ThreeDimensionalLeader ) + { + renderedSomething += this->LeaderActor3D->RenderOpaqueGeometry(viewport); + } + else + { + renderedSomething += this->LeaderActor2D->RenderOpaqueGeometry(viewport); + } + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +void vtkCaptionActor2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Text Actor: " << this->TextActor << "\n"; + if (this->CaptionTextProperty) + { + os << indent << "Caption Text Property:\n"; + this->CaptionTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Caption Text Property: (none)\n"; + } + + os << indent << "Caption: "; + if ( this->Caption ) + { + os << this->Caption << "\n"; + } + else + { + os << "(none)\n"; + } + + os << indent << "Leader: " << (this->Leader ? "On\n" : "Off\n"); + os << indent << "Three Dimensional Leader: " + << (this->ThreeDimensionalLeader ? "On\n" : "Off\n"); + os << indent << "Leader Glyph Size: " + << this->LeaderGlyphSize << "\n"; + os << indent << "MaximumLeader Glyph Size: " + << this->MaximumLeaderGlyphSize << "\n"; + if ( ! this->LeaderGlyph ) + { + os << indent << "Leader Glyph: (none)\n"; + } + else + { + os << indent << "Leader Glyph: (" << this->LeaderGlyph << ")\n"; + } + os << indent << "Padding: " << this->Padding << "\n"; + os << indent << "Border: " << (this->Border ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +void vtkCaptionActor2D::ShallowCopy(vtkProp *prop) +{ + vtkCaptionActor2D *a = vtkCaptionActor2D::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetCaption(a->GetCaption()); + this->SetAttachmentPoint(a->GetAttachmentPoint()); + this->SetBorder(a->GetBorder()); + this->SetLeader(a->GetLeader()); + this->SetThreeDimensionalLeader(a->GetThreeDimensionalLeader()); + this->SetLeaderGlyph(a->GetLeaderGlyph()); + this->SetLeaderGlyphSize(a->GetLeaderGlyphSize()); + this->SetMaximumLeaderGlyphSize(a->GetMaximumLeaderGlyphSize()); + this->SetPadding(a->GetPadding()); + this->SetCaptionTextProperty(a->GetCaptionTextProperty()); + } + + // Now do superclass + this->vtkActor2D::ShallowCopy(prop); +} diff --git a/Hybrid/vtkCaptionActor2D.h b/Hybrid/vtkCaptionActor2D.h new file mode 100644 index 0000000..a9f9bdb --- /dev/null +++ b/Hybrid/vtkCaptionActor2D.h @@ -0,0 +1,218 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCaptionActor2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCaptionActor2D - draw text label associated with a point +// .SECTION Description +// vtkCaptionActor2D is a hybrid 2D/3D actor that is used to associate text +// with a point (the AttachmentPoint) in the scene. The caption can be +// drawn with a rectangular border and a leader connecting +// the caption to the attachment point. Optionally, the leader can be +// glyphed at its endpoint to create arrow heads or other indicators. +// +// To use the caption actor, you normally specify the Position and Position2 +// coordinates (these are inherited from the vtkActor2D superclass). (Note +// that Position2 can be set using vtkActor2D's SetWidth() and SetHeight() +// methods.) Position and Position2 define the size of the caption, and a +// third point, the AttachmentPoint, defines a point that the caption is +// associated with. You must also define the caption text, +// whether you want a border around the caption, and whether you want a +// leader from the caption to the attachment point. The font attributes of +// the text can be set through the vtkTextProperty associated to this actor. +// You also indicate whether you want +// the leader to be 2D or 3D. (2D leaders are always drawn over the +// underlying geometry. 3D leaders may be occluded by the geometry.) The +// leader may also be terminated by an optional glyph (e.g., arrow). +// +// The trickiest part about using this class is setting Position, Position2, +// and AttachmentPoint correctly. These instance variables are +// vtkCoordinates, and can be set up in various ways. In default usage, the +// AttachmentPoint is defined in the world coordinate system, Position is the +// lower-left corner of the caption and relative to AttachmentPoint (defined +// in display coordaintes, i.e., pixels), and Position2 is relative to +// Position and is the upper-right corner (also in display +// coordinates). However, the user has full control over the coordinates, and +// can do things like place the caption in a fixed position in the renderer, +// with the leader moving with the AttachmentPoint. + +// .SECTION See Also +// vtkLegendBoxActor vtkTextMapper vtkTextActor vtkTextProperty +// vtkCoordinate + +#ifndef __vtkCaptionActor2D_h +#define __vtkCaptionActor2D_h + +#include "vtkActor2D.h" + +class vtkActor; +class vtkAppendPolyData; +class vtkGlyph2D; +class vtkGlyph3D; +class vtkPolyData; +class vtkPolyDataMapper2D; +class vtkPolyDataMapper; +class vtkTextActor; +class vtkTextMapper; +class vtkTextProperty; + +class VTK_HYBRID_EXPORT vtkCaptionActor2D : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkCaptionActor2D,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkCaptionActor2D *New(); + + // Description: + // Define the text to be placed in the caption. The text can be multiple + // lines (separated by "\n"). + vtkSetStringMacro(Caption); + vtkGetStringMacro(Caption); + + // Description: + // Set/Get the attachment point for the caption. By default, the attachment + // point is defined in world coordinates, but this can be changed using + // vtkCoordinate methods. + vtkWorldCoordinateMacro(AttachmentPoint); + + // Description: + // Enable/disable the placement of a border around the text. + vtkSetMacro(Border,int); + vtkGetMacro(Border,int); + vtkBooleanMacro(Border,int); + + // Description: + // Enable/disable drawing a "line" from the caption to the + // attachment point. + vtkSetMacro(Leader,int); + vtkGetMacro(Leader,int); + vtkBooleanMacro(Leader,int); + + // Description: + // Indicate whether the leader is 2D (no hidden line) or 3D (z-buffered). + vtkSetMacro(ThreeDimensionalLeader,int); + vtkGetMacro(ThreeDimensionalLeader,int); + vtkBooleanMacro(ThreeDimensionalLeader,int); + + // Description: + // Specify a glyph to be used as the leader "head". This could be something + // like an arrow or sphere. If not specified, no glyph is drawn. Note that + // the glyph is assumed to be aligned along the x-axis and is rotated about + // the origin. + virtual void SetLeaderGlyph(vtkPolyData*); + vtkGetObjectMacro(LeaderGlyph,vtkPolyData); + + // Description: + // Specify the relative size of the leader head. This is expressed as a + // fraction of the size (diagonal length) of the renderer. The leader + // head is automatically scaled so that window resize, zooming or other + // camera motion results in proportional changes in size to the leader + // glyph. + vtkSetClampMacro(LeaderGlyphSize,double,0.0,0.1); + vtkGetMacro(LeaderGlyphSize,double); + + // Description: + // Specify the maximum size of the leader head (if any) in pixels. This + // is used in conjunction with LeaderGlyphSize to cap the maximum size of + // the LeaderGlyph. + vtkSetClampMacro(MaximumLeaderGlyphSize,int,1,1000); + vtkGetMacro(MaximumLeaderGlyphSize,int); + + // Description: + // Set/Get the padding between the caption and the border. The value + // is specified in pixels. + vtkSetClampMacro(Padding, int, 0, 50); + vtkGetMacro(Padding, int); + + // Description: + // Get the text actor used by the caption. This is useful if you want to control + // justification and other characteristics of the text actor. + vtkGetObjectMacro(TextActor,vtkTextActor); + + // Description: + // Set/Get the text property. + virtual void SetCaptionTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(CaptionTextProperty,vtkTextProperty); + + // Description: + // Shallow copy of this scaled text actor. Overloads the virtual + // vtkProp method. + void ShallowCopy(vtkProp *prop); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Draw the legend box to the screen. + int RenderOpaqueGeometry(vtkViewport* viewport); + int RenderTranslucentGeometry(vtkViewport* ) {return 0;} + int RenderOverlay(vtkViewport* viewport); +//ETX + +protected: + vtkCaptionActor2D(); + ~vtkCaptionActor2D(); + + vtkCoordinate *AttachmentPointCoordinate; + + char *Caption; + int Border; + int Leader; + int ThreeDimensionalLeader; + double LeaderGlyphSize; + int MaximumLeaderGlyphSize; + + vtkPolyData *LeaderGlyph; //what to put on the end of the leader + + int Padding; + +private: + vtkTextActor *TextActor; + vtkTextProperty *CaptionTextProperty; + + vtkPolyData *BorderPolyData; + vtkPolyDataMapper2D *BorderMapper; + vtkActor2D *BorderActor; + + vtkPolyData *HeadPolyData; // single attachment point for glyphing + vtkGlyph3D *HeadGlyph; // for 3D leader + vtkPolyData *LeaderPolyData; // line represents the leader + vtkAppendPolyData *AppendLeader; // append head and leader + + // for 2D leader + vtkCoordinate *MapperCoordinate2D; + vtkPolyDataMapper2D *LeaderMapper2D; + vtkActor2D *LeaderActor2D; + + // for 3D leader + vtkPolyDataMapper *LeaderMapper3D; + vtkActor *LeaderActor3D; + +private: + vtkCaptionActor2D(const vtkCaptionActor2D&); // Not implemented. + void operator=(const vtkCaptionActor2D&); // Not implemented. +}; + + +#endif + + + diff --git a/Hybrid/vtkCornerAnnotation.cxx b/Hybrid/vtkCornerAnnotation.cxx new file mode 100644 index 0000000..3ce7bc8 --- /dev/null +++ b/Hybrid/vtkCornerAnnotation.cxx @@ -0,0 +1,697 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCornerAnnotation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCornerAnnotation.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkImageActor.h" +#include "vtkImageData.h" +#include "vtkImageMapToWindowLevelColors.h" +#include "vtkObjectFactory.h" +#include "vtkPropCollection.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" +#include "vtkWindow.h" + +//---------------------------------------------------------------------------- +vtkStandardNewMacro(vtkCornerAnnotation); +vtkCxxRevisionMacro(vtkCornerAnnotation, "$Revision: 1.3.4.3 $"); + +vtkSetObjectImplementationMacro(vtkCornerAnnotation,ImageActor,vtkImageActor); +vtkSetObjectImplementationMacro(vtkCornerAnnotation,WindowLevel, + vtkImageMapToWindowLevelColors); +vtkCxxSetObjectMacro(vtkCornerAnnotation,TextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +vtkCornerAnnotation::vtkCornerAnnotation() +{ + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.2,0.85); + + this->LastSize[0] = 0; + this->LastSize[1] = 0; + + this->MaximumLineHeight = 1.0; + this->MinimumFontSize = 6; + this->MaximumFontSize = 200; + this->LinearFontScaleFactor = 5.0; + this->NonlinearFontScaleFactor = 0.35; + this->FontSize = 15; + + this->TextProperty = vtkTextProperty::New(); + this->TextProperty->ShadowOff(); + + for (int i = 0; i < 4; i++) + { + this->CornerText[i] = NULL; + this->TextMapper[i] = vtkTextMapper::New(); + this->TextActor[i] = vtkActor2D::New(); + this->TextActor[i]->SetMapper(this->TextMapper[i]); + } + + this->ImageActor = NULL; + this->LastImageActor = 0; + this->WindowLevel = NULL; + + this->LevelShift = 0; + this->LevelScale = 1; + + this->ShowSliceAndImage = 1; +} + +//---------------------------------------------------------------------------- +vtkCornerAnnotation::~vtkCornerAnnotation() +{ + this->SetTextProperty(NULL); + + for (int i = 0; i < 4; i++) + { + delete [] this->CornerText[i]; + this->TextMapper[i]->Delete(); + this->TextActor[i]->Delete(); + } + + this->SetWindowLevel(NULL); + this->SetImageActor(NULL); +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkCornerAnnotation::ReleaseGraphicsResources(vtkWindow *win) +{ + this->Superclass::ReleaseGraphicsResources(win); + for (int i = 0; i < 4; i++) + { + this->TextActor[i]->ReleaseGraphicsResources(win); + } +} + +//---------------------------------------------------------------------------- +void vtkCornerAnnotation::TextReplace(vtkImageActor *ia, + vtkImageMapToWindowLevelColors *wl) +{ + int i; + char *text, *text2; + int slice = 0, slice_max = 0; + char *rpos, *tmp; + double window = 0, level = 0; + long int windowi = 0, leveli = 0; + vtkImageData *wl_input = NULL, *ia_input = NULL; + int input_type_is_float = 0; + + if (wl) + { + window = wl->GetWindow(); + window *= this->LevelScale; + level = wl->GetLevel(); + level = level * this->LevelScale + this->LevelShift; + windowi = (long int)window; + leveli = (long int)level; + wl_input = vtkImageData::SafeDownCast(wl->GetInput()); + if (wl_input) + { + input_type_is_float = (wl_input->GetScalarType() == VTK_FLOAT || + wl_input->GetScalarType() == VTK_DOUBLE); + } + } + if (ia) + { + slice = ia->GetSliceNumber() + 1; + slice_max = ia->GetWholeZMax() + 1; + ia_input = ia->GetInput(); + if (!wl_input && ia_input) + { + input_type_is_float = (ia_input->GetScalarType() == VTK_FLOAT || + ia_input->GetScalarType() == VTK_DOUBLE); + } + } + + + // search for tokens, replace and then assign to TextMappers + for (i = 0; i < 4; i++) + { + if (this->CornerText[i] && strlen(this->CornerText[i])) + { + text = new char [strlen(this->CornerText[i])+1000]; + text2 = new char [strlen(this->CornerText[i])+1000]; + strcpy(text,this->CornerText[i]); + + // now do the replacements + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (ia && this->ShowSliceAndImage) + { + sprintf(text2,"%sImage: %i%s",text,slice,rpos+7); + } + else + { + sprintf(text2,"%s%s",text,rpos+7); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (ia && this->ShowSliceAndImage) + { + sprintf(text2,"%sImage: %i / %i%s",text,slice,slice_max,rpos+15); + } + else + { + sprintf(text2,"%s%s",text,rpos+15); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (ia && this->ShowSliceAndImage) + { + sprintf(text2,"%sSlice: %i%s",text,slice,rpos+7); + } + else + { + sprintf(text2,"%s%s",text,rpos+7); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (ia && this->ShowSliceAndImage) + { + sprintf(text2,"%sSlice: %i / %i%s",text,slice,slice_max,rpos+15); + } + else + { + sprintf(text2,"%s%s",text,rpos+15); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (ia && this->ShowSliceAndImage) + { + double *dbounds = ia->GetDisplayBounds(); + int *dext = ia->GetDisplayExtent(); + double pos; + if (dext[0] == dext[1]) + { + pos = dbounds[0]; + } + else if (dext[2] == dext[3]) + { + pos = dbounds[2]; + } + else + { + pos = dbounds[4]; + } + sprintf(text2,"%s%g%s",text,pos,rpos+11); + } + else + { + sprintf(text2,"%s%s",text,rpos+11); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (wl) + { + if (input_type_is_float) + { + sprintf(text2,"%sWindow: %g%s",text,window,rpos+8); + } + else + { + sprintf(text2,"%sWindow: %li%s",text,windowi,rpos+8); + } + } + else + { + sprintf(text2,"%s%s",text,rpos+8); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (wl) + { + if (input_type_is_float) + { + sprintf(text2,"%sLevel: %g%s",text,level,rpos+7); + } + else + { + sprintf(text2,"%sLevel: %li%s",text,leveli,rpos+7); + } + } + else + { + sprintf(text2,"%s%s",text,rpos+7); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + rpos = strstr(text,""); + while (rpos) + { + *rpos = '\0'; + if (wl) + { + if (input_type_is_float) + { + sprintf(text2,"%sWW/WL: %g / %g%s",text,window,level,rpos+14); + } + else + { + sprintf(text2,"%sWW/WL: %li / %li%s",text,windowi,leveli,rpos+14); + } + } + else + { + sprintf(text2,"%s%s",text,rpos+14); + } + tmp = text; + text = text2; + text2 = tmp; + rpos = strstr(text,""); + } + + this->TextMapper[i]->SetInput(text); + delete [] text; + delete [] text2; + } + else + { + this->TextMapper[i]->SetInput(""); + } + } +} + +//---------------------------------------------------------------------------- +int vtkCornerAnnotation::RenderOverlay(vtkViewport *viewport) +{ + // Everything is built, just have to render + // only render if font is at least minimum font + if (this->FontSize >= this->MinimumFontSize) + { + for (int i = 0; i < 4; i++) + { + this->TextActor[i]->RenderOverlay(viewport); + } + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkCornerAnnotation::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int fontSize; + int i; + + // Check to see whether we have to rebuild everything + // If the viewport has changed we may - or may not need + // to rebuild, it depends on if the projected coords chage + int viewport_size_has_changed = 0; + if (viewport->GetMTime() > this->BuildTime || + (viewport->GetVTKWindow() && + viewport->GetVTKWindow()->GetMTime() > this->BuildTime)) + { + int *vSize = viewport->GetSize(); + if (this->LastSize[0] != vSize[0] || this->LastSize[1] != vSize[1]) + { + viewport_size_has_changed = 1; + } + } + + // Is there an image actor ? + vtkImageMapToWindowLevelColors *wl = this->WindowLevel; + vtkImageActor *ia = NULL; + if (this->ImageActor) + { + ia = this->ImageActor; + } + else + { + vtkPropCollection *pc = viewport->GetViewProps(); + int numProps = pc->GetNumberOfItems(); + for (i = 0; i < numProps; i++) + { + ia = vtkImageActor::SafeDownCast(pc->GetItemAsObject(i)); + if (ia) + { + if (ia->GetInput() && !wl) + { + wl = vtkImageMapToWindowLevelColors::SafeDownCast( + ia->GetInput()->GetProducerPort()->GetProducer()); + } + break; + } + } + } + + int tprop_has_changed = (this->TextProperty && + this->TextProperty->GetMTime() > this->BuildTime); + + // Check to see whether we have to rebuild everything + if (viewport_size_has_changed || + tprop_has_changed || + (this->GetMTime() > this->BuildTime) || + (ia && (ia != this->LastImageActor || + ia->GetMTime() > this->BuildTime)) || + (wl && wl->GetMTime() > this->BuildTime)) + { + int *vSize = viewport->GetSize(); + + vtkDebugMacro(<<"Rebuilding text"); + + // Replace text + this->TextReplace(ia, wl); + + // Get the viewport size in display coordinates + this->LastSize[0] = vSize[0]; + this->LastSize[1] = vSize[1]; + + // Only adjust size then the text changes due to non w/l slice reasons + if (viewport_size_has_changed || + tprop_has_changed || + this->GetMTime() > this->BuildTime) + { + // Rebuid text props. + // Perform shallow copy here since each individual corner has a + // different aligment/size but they share the other this->TextProperty + // attributes. + fontSize = this->TextMapper[0]->GetTextProperty()->GetFontSize(); + + if (tprop_has_changed) + { + vtkTextProperty *tprop = this->TextMapper[0]->GetTextProperty(); + tprop->ShallowCopy(this->TextProperty); + tprop->SetFontSize(fontSize); + + tprop = this->TextMapper[1]->GetTextProperty(); + tprop->ShallowCopy(this->TextProperty); + tprop->SetFontSize(fontSize); + + tprop = this->TextMapper[2]->GetTextProperty(); + tprop->ShallowCopy(this->TextProperty); + tprop->SetFontSize(fontSize); + + tprop = this->TextMapper[3]->GetTextProperty(); + tprop->ShallowCopy(this->TextProperty); + tprop->SetFontSize(fontSize); + + this->SetTextActorsJustification(); + } + + // Update all the composing objects to find the best size for the font + // use the last size as a first guess + + /* + +--------+ + |2 3| + | | + | | + |0 1| + +--------+ + */ + + int tempi[8]; + int allZeros = 1; + for (i = 0; i < 4; i++) + { + this->TextMapper[i]->GetSize(viewport, tempi + i * 2); + if (tempi[2*i] > 0 || tempi[2*i+1] > 0) + { + allZeros = 0; + } + } + + if (allZeros) + { + return 0; + } + + int height_02 = tempi[1] + tempi[5]; + int height_13 = tempi[3] + tempi[7]; + + int width_01 = tempi[0] + tempi[2]; + int width_23 = tempi[4] + tempi[6]; + + int max_width = (width_01 > width_23) ? width_01 : width_23; + + int num_lines_02 = + this->TextMapper[0]->GetNumberOfLines() + + this->TextMapper[2]->GetNumberOfLines(); + + int num_lines_13 = + this->TextMapper[1]->GetNumberOfLines() + + this->TextMapper[3]->GetNumberOfLines(); + + int line_max_02 = (int)(vSize[1] * this->MaximumLineHeight) * + (num_lines_02 ? num_lines_02 : 1); + + int line_max_13 = (int)(vSize[1] * this->MaximumLineHeight) * + (num_lines_13 ? num_lines_13 : 1); + + // Target size is to use 90% of x and y + + int tSize[2]; + tSize[0] = (int)(0.9*vSize[0]); + tSize[1] = (int)(0.9*vSize[1]); + + // While the size is too small increase it + + while (height_02 < tSize[1] && + height_13 < tSize[1] && + max_width < tSize[0] && + height_02 < line_max_02 && + height_13 < line_max_13 && + fontSize < 100) + { + fontSize++; + for (i = 0; i < 4; i++) + { + this->TextMapper[i]->GetTextProperty()->SetFontSize(fontSize); + this->TextMapper[i]->GetSize(viewport, tempi + i * 2); + } + height_02 = tempi[1] + tempi[5]; + height_13 = tempi[3] + tempi[7]; + width_01 = tempi[0] + tempi[2]; + width_23 = tempi[4] + tempi[6]; + max_width = (width_01 > width_23) ? width_01 : width_23; + } + + // While the size is too large decrease it + + while ((height_02 > tSize[1] || + height_13 > tSize[1] || + max_width > tSize[0] || + height_02 > line_max_02 || + height_13 > line_max_13) && + fontSize > 0) + { + fontSize--; + for (i = 0; i < 4; i++) + { + this->TextMapper[i]->GetTextProperty()->SetFontSize(fontSize); + this->TextMapper[i]->GetSize(viewport, tempi + i * 2); + } + height_02 = tempi[1] + tempi[5]; + height_13 = tempi[3] + tempi[7]; + width_01 = tempi[0] + tempi[2]; + width_23 = tempi[4] + tempi[6]; + max_width = (width_01 > width_23) ? width_01 : width_23; + } + + fontSize = static_cast(pow((double)fontSize, + NonlinearFontScaleFactor)*LinearFontScaleFactor); + if (fontSize > this->MaximumFontSize) + { + fontSize = this->MaximumFontSize; + } + this->FontSize = fontSize; + for (i = 0; i < 4; i++) + { + this->TextMapper[i]->GetTextProperty()->SetFontSize(fontSize); + } + + // Now set the position of the TextActors + + this->SetTextActorsPosition(vSize); + + for (i = 0; i < 4; i++) + { + this->TextActor[i]->SetProperty(this->GetProperty()); + } + } + this->BuildTime.Modified(); + this->LastImageActor = ia; + } + + // Everything is built, just have to render + + if (this->FontSize >= this->MinimumFontSize) + { + for (i = 0; i < 4; i++) + { + this->TextActor[i]->RenderOpaqueGeometry(viewport); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkCornerAnnotation::SetTextActorsPosition(int vsize[2]) +{ + this->TextActor[0]->SetPosition(5, 5); + this->TextActor[1]->SetPosition(vsize[0] - 5, 5); + this->TextActor[2]->SetPosition(5, vsize[1] - 5); + this->TextActor[3]->SetPosition(vsize[0] - 5, vsize[1] - 5); +} + +//---------------------------------------------------------------------------- +void vtkCornerAnnotation::SetTextActorsJustification() +{ + vtkTextProperty *tprop = this->TextMapper[0]->GetTextProperty(); + tprop->SetJustificationToLeft(); + tprop->SetVerticalJustificationToBottom(); + + tprop = this->TextMapper[1]->GetTextProperty(); + tprop->SetJustificationToRight(); + tprop->SetVerticalJustificationToBottom(); + + tprop = this->TextMapper[2]->GetTextProperty(); + tprop->SetJustificationToLeft(); + tprop->SetVerticalJustificationToTop(); + + tprop = this->TextMapper[3]->GetTextProperty(); + tprop->SetJustificationToRight(); + tprop->SetVerticalJustificationToTop(); +} + +//---------------------------------------------------------------------------- +void vtkCornerAnnotation::SetText(int i, const char *text) +{ + if (i < 0 || i > 3) + { + return; + } + + if (!text || + (this->CornerText[i] && text && (!strcmp(this->CornerText[i],text)))) + { + return; + } + delete [] this->CornerText[i]; + this->CornerText[i] = new char [strlen(text)+1]; + strcpy(this->CornerText[i],text); + this->Modified(); +} + +//---------------------------------------------------------------------------- +char* vtkCornerAnnotation::GetText(int i) +{ + if (i < 0 || i > 3) + { + return NULL; + } + + return this->CornerText[i]; +} + +//---------------------------------------------------------------------------- +void vtkCornerAnnotation::ClearAllTexts() +{ + int i; + for (i = 0; i < 4; i++) + { + this->SetText(i, ""); + } +} + +//---------------------------------------------------------------------------- +void vtkCornerAnnotation::CopyAllTextsFrom(vtkCornerAnnotation *ca) +{ + int i; + for (i = 0; i < 4; i++) + { + this->SetText(i, ca->GetText(i)); + } +} + +//---------------------------------------------------------------------------- +void vtkCornerAnnotation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "ImageActor: " << this->GetImageActor() << endl; + os << indent << "MinimumFontSize: " << this->GetMinimumFontSize() << endl; + os << indent << "MaximumFontSize: " << this->GetMaximumFontSize() << endl; + os << indent << "LinearFontScaleFactor: " << this->GetLinearFontScaleFactor() << endl; + os << indent << "NonlinearFontScaleFactor: " << this->GetNonlinearFontScaleFactor() << endl; + os << indent << "WindowLevel: " << this->GetWindowLevel() << endl; + os << indent << "Mapper: " << this->GetMapper() << endl; + os << indent << "MaximumLineHeight: " << this->MaximumLineHeight << endl; + os << indent << "LevelShift: " << this->LevelShift << endl; + os << indent << "LevelScale: " << this->LevelScale << endl; + os << indent << "TextProperty: " << this->TextProperty << endl; + os << indent << "ShowSliceAndImage: " << this->ShowSliceAndImage << endl; +} + + diff --git a/Hybrid/vtkCornerAnnotation.h b/Hybrid/vtkCornerAnnotation.h new file mode 100644 index 0000000..5c77825 --- /dev/null +++ b/Hybrid/vtkCornerAnnotation.h @@ -0,0 +1,172 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCornerAnnotation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCornerAnnotation - text annotation in four corners +// .SECTION Description +// This is an annotation object that manages four text actors / mappers +// to provide annotation in the four corners of a viewport +// +// .SECTION See Also +// vtkActor2D vtkTextMapper + +#ifndef __vtkCornerAnnotation_h +#define __vtkCornerAnnotation_h + +#include "vtkActor2D.h" + +class vtkTextMapper; +class vtkImageMapToWindowLevelColors; +class vtkImageActor; +class vtkTextProperty; + +class VTK_HYBRID_EXPORT vtkCornerAnnotation : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkCornerAnnotation,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with a rectangle in normaled view coordinates + // of (0.2,0.85, 0.8, 0.95). + static vtkCornerAnnotation *New(); + + // Description: + // Draw the scalar bar and annotation text to the screen. + int RenderOpaqueGeometry(vtkViewport* viewport); + int RenderTranslucentGeometry(vtkViewport* ) {return 0;}; + int RenderOverlay(vtkViewport* viewport); + + // Description: + // Set/Get the maximum height of a line of text as a + // percentage of the vertical area allocated to this + // scaled text actor. Defaults to 1.0 + vtkSetMacro(MaximumLineHeight,double); + vtkGetMacro(MaximumLineHeight,double); + + // Description: + // Set/Get the minimum/maximum size font that will be shown. + // If the font drops below the minimum size it will not be rendered. + vtkSetMacro(MinimumFontSize,int); + vtkGetMacro(MinimumFontSize,int); + vtkSetMacro(MaximumFontSize,int); + vtkGetMacro(MaximumFontSize,int); + + // Description: + // Set/Get font scaling factors + // The font size, f, is calculated as the largest possible value + // such that the annotations for the given viewport do not overlap. + // This font size is scaled non-linearly with the viewport size, + // to maintain an acceptable readable size at larger viewport sizes, + // without being too big. + // f' = linearScale * pow(f,nonlinearScale) + vtkSetMacro( LinearFontScaleFactor, double ); + vtkGetMacro( LinearFontScaleFactor, double ); + vtkSetMacro( NonlinearFontScaleFactor, double ); + vtkGetMacro( NonlinearFontScaleFactor, double ); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Set/Get the text to be displayed for each corner + void SetText(int i, const char *text); + char* GetText(int i); + void ClearAllTexts(); + void CopyAllTextsFrom(vtkCornerAnnotation *ca); + + // Description: + // Set an image actor to look at for slice information + void SetImageActor(vtkImageActor*); + vtkGetObjectMacro(ImageActor,vtkImageActor); + + // Description: + // Set an instance of vtkImageMapToWindowLevelColors to use for + // looking at window level changes + void SetWindowLevel(vtkImageMapToWindowLevelColors*); + vtkGetObjectMacro(WindowLevel,vtkImageMapToWindowLevelColors); + + // Description: + // Set the value to shift the level by. + vtkSetMacro(LevelShift, double); + vtkGetMacro(LevelShift, double); + + // Description: + // Set the value to scale the level by. + vtkSetMacro(LevelScale, double); + vtkGetMacro(LevelScale, double); + + // Description: + // Set/Get the text property of all corners. + virtual void SetTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TextProperty,vtkTextProperty); + + // Description: + // Even if there is an image actor, should and be displayed? + vtkBooleanMacro(ShowSliceAndImage, int); + vtkSetMacro(ShowSliceAndImage, int); + vtkGetMacro(ShowSliceAndImage, int); + +protected: + vtkCornerAnnotation(); + ~vtkCornerAnnotation(); + + double MaximumLineHeight; + + vtkTextProperty *TextProperty; + + vtkImageMapToWindowLevelColors *WindowLevel; + double LevelShift; + double LevelScale; + vtkImageActor *ImageActor; + vtkImageActor *LastImageActor; + + char *CornerText[4]; + + int FontSize; + vtkActor2D *TextActor[4]; + vtkTimeStamp BuildTime; + int LastSize[2]; + vtkTextMapper *TextMapper[4]; + + int MinimumFontSize; + int MaximumFontSize; + + double LinearFontScaleFactor; + double NonlinearFontScaleFactor; + + int ShowSliceAndImage; + + // Description: + // Search for replacable tokens and replace + virtual void TextReplace( + vtkImageActor *ia, vtkImageMapToWindowLevelColors *wl); + + // Description: + // Set text actor positions given a viewport size and justification + virtual void SetTextActorsPosition(int vsize[2]); + virtual void SetTextActorsJustification(); + +private: + vtkCornerAnnotation(const vtkCornerAnnotation&); // Not implemented. + void operator=(const vtkCornerAnnotation&); // Not implemented. +}; + + +#endif + + + diff --git a/Hybrid/vtkCubeAxesActor2D.cxx b/Hybrid/vtkCubeAxesActor2D.cxx new file mode 100644 index 0000000..c8fee6d --- /dev/null +++ b/Hybrid/vtkCubeAxesActor2D.cxx @@ -0,0 +1,1071 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCubeAxesActor2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCubeAxesActor2D.h" + +#include "vtkAxisActor2D.h" +#include "vtkCamera.h" +#include "vtkDataSet.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" + +vtkCxxRevisionMacro(vtkCubeAxesActor2D, "$Revision: 1.52.10.1 $"); +vtkStandardNewMacro(vtkCubeAxesActor2D); + +vtkCxxSetObjectMacro(vtkCubeAxesActor2D,Input, vtkDataSet); +vtkCxxSetObjectMacro(vtkCubeAxesActor2D,Camera,vtkCamera); +vtkCxxSetObjectMacro(vtkCubeAxesActor2D,ViewProp,vtkProp); +vtkCxxSetObjectMacro(vtkCubeAxesActor2D,AxisLabelTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(vtkCubeAxesActor2D,AxisTitleTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Instantiate this object. +vtkCubeAxesActor2D::vtkCubeAxesActor2D() +{ + this->Input = NULL; + this->ViewProp = NULL; + this->Bounds[0] = -1.0; this->Bounds[1] = 1.0; + this->Bounds[2] = -1.0; this->Bounds[3] = 1.0; + this->Bounds[4] = -1.0; this->Bounds[5] = 1.0; + + this->UseRanges = 0; + this->Ranges[0] = 0; this->Ranges[1] = 0; + this->Ranges[2] = 0; this->Ranges[3] = 0; + this->Ranges[4] = 0; this->Ranges[5] = 0; + + this->Camera = NULL; + this->FlyMode = VTK_FLY_CLOSEST_TRIAD; + this->Scaling = 1; + + this->XAxis = vtkAxisActor2D::New(); + this->XAxis->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); + this->XAxis->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); + this->XAxis->AdjustLabelsOff(); + + this->YAxis = vtkAxisActor2D::New(); + this->YAxis->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); + this->YAxis->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); + this->YAxis->AdjustLabelsOff(); + + this->ZAxis = vtkAxisActor2D::New(); + this->ZAxis->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); + this->ZAxis->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); + this->ZAxis->AdjustLabelsOff(); + + this->NumberOfLabels = 3; + + this->AxisLabelTextProperty = vtkTextProperty::New(); + this->AxisLabelTextProperty->SetBold(1); + this->AxisLabelTextProperty->SetItalic(1); + this->AxisLabelTextProperty->SetShadow(1); + this->AxisLabelTextProperty->SetFontFamilyToArial(); + + this->AxisTitleTextProperty = vtkTextProperty::New(); + this->AxisTitleTextProperty->ShallowCopy(this->AxisLabelTextProperty); + + this->LabelFormat = new char[8]; + sprintf(this->LabelFormat,"%s","%-#6.3g"); + this->FontFactor = 1.0; + this->CornerOffset = 0.05; + this->Inertia = 1; + this->ShowActualBounds = 1; + this->RenderCount = 0; + + this->XAxisVisibility = 1; + this->YAxisVisibility = 1; + this->ZAxisVisibility = 1; + + this->XLabel = new char[2]; + sprintf(this->XLabel,"%s","X"); + this->YLabel = new char[2]; + sprintf(this->YLabel,"%s","Y"); + this->ZLabel = new char[2]; + sprintf(this->ZLabel,"%s","Z"); +} + +//---------------------------------------------------------------------------- +// Shallow copy of an actor. +void vtkCubeAxesActor2D::ShallowCopy(vtkCubeAxesActor2D *actor) +{ + this->vtkActor2D::ShallowCopy(actor); + this->SetAxisLabelTextProperty(actor->GetAxisLabelTextProperty()); + this->SetAxisTitleTextProperty(actor->GetAxisTitleTextProperty()); + this->SetLabelFormat(actor->GetLabelFormat()); + this->SetFontFactor(actor->GetFontFactor()); + this->SetCornerOffset(actor->GetCornerOffset()); + this->SetInertia(static_cast(actor->GetInertia())); + this->SetXLabel(actor->GetXLabel()); + this->SetYLabel(actor->GetYLabel()); + this->SetZLabel(actor->GetZLabel()); + this->SetFlyMode(actor->GetFlyMode()); + this->SetInput(actor->GetInput()); + this->SetViewProp(actor->GetViewProp()); + this->SetCamera(actor->GetCamera()); +} + +//---------------------------------------------------------------------------- +vtkCubeAxesActor2D::~vtkCubeAxesActor2D() +{ + if ( this->Input ) + { + this->Input->Delete(); + } + + if ( this->ViewProp ) + { + this->ViewProp->Delete(); + } + + if ( this->Camera ) + { + this->Camera->UnRegister(this); + } + + this->XAxis->Delete(); + this->YAxis->Delete(); + this->ZAxis->Delete(); + + if (this->LabelFormat) + { + delete [] this->LabelFormat; + this->LabelFormat = NULL; + } + + if ( this->XLabel ) + { + delete [] this->XLabel; + } + if ( this->YLabel ) + { + delete [] this->YLabel; + } + if ( this->ZLabel ) + { + delete [] this->ZLabel; + } + + this->SetAxisLabelTextProperty(NULL); + this->SetAxisTitleTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +// Static variable describes connections in cube. +static int Conn[8][3] = {{1,2,4}, {0,3,5}, {3,0,6}, {2,1,7}, + {5,6,0}, {4,7,1}, {7,4,2}, {6,5,3}}; + +//---------------------------------------------------------------------------- +// Project the bounding box and compute edges on the border of the bounding +// cube. Determine which parts of the edges are visible via intersection +// with the boundary of the viewport (minus borders). +int vtkCubeAxesActor2D::RenderOverlay(vtkViewport *viewport) +{ + int renderedSomething=0; + + // Initialization + if ( ! this->RenderSomething ) + { + return 0; + } + + //Render the axes + if ( this->XAxisVisibility ) + { + renderedSomething += this->XAxis->RenderOverlay(viewport); + } + if ( this->YAxisVisibility ) + { + renderedSomething += this->YAxis->RenderOverlay(viewport); + } + if ( this->ZAxisVisibility ) + { + renderedSomething += this->ZAxis->RenderOverlay(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +// Project the bounding box and compute edges on the border of the bounding +// cube. Determine which parts of the edges are visible via intersection +// with the boundary of the viewport (minus borders). +int vtkCubeAxesActor2D::RenderOpaqueGeometry(vtkViewport *viewport) +{ + double bounds[6]; + double slope = 0.0, minSlope, num, den; + double pts[8][3], d2, d2Min, min; + int i, idx = 0; + int xIdx, yIdx = 0, zIdx = 0, zIdx2, renderedSomething=0; + int xAxes = 0, yAxes, zAxes; + + // Initialization + if ( !this->Camera ) + { + vtkErrorMacro(<<"No camera!"); + this->RenderSomething = 0; + return 0; + } + + this->RenderSomething = 1; + + // determine the bounds to use + this->GetBounds(bounds); + + // Build the axes (almost always needed so we don't check mtime) + // Transform all points into display coordinates + this->TransformBounds(viewport, bounds, pts); + + // Find the portion of the bounding box that fits within the viewport, + if ( !this->ShowActualBounds && (this->ClipBounds(viewport, pts, bounds) == 0) ) + { + this->RenderSomething = 0; + return 0; + } + + // Take into account the inertia. Process only so often. + if ( this->RenderCount++ == 0 || !(this->RenderCount % this->Inertia) ) + { + // Okay, we have a bounding box, maybe clipped and scaled, that is visible. + // We setup the axes depending on the fly mode. + if ( this->FlyMode == VTK_FLY_CLOSEST_TRIAD ) + { + // Loop over points and find the closest point to the camera + min = VTK_DOUBLE_MAX; + for (i=0; i < 8; i++) + { + if ( pts[i][2] < min ) + { + idx = i; + min = pts[i][2]; + } + } + + // Setup the three axes to be drawn + xAxes = 0; + xIdx = Conn[idx][0]; + yAxes = 1; + yIdx = Conn[idx][1]; + zAxes = 2; + zIdx = idx; + zIdx2 = Conn[idx][2]; + } + else + { + double e1[2], e2[2], e3[2]; + + // Find distance to origin + d2Min = VTK_DOUBLE_MAX; + for (i=0; i < 8; i++) + { + d2 = pts[i][0]*pts[i][0] + pts[i][1]*pts[i][1]; + if ( d2 < d2Min ) + { + d2Min = d2; + idx = i; + } + } + + // find minimum slope point connected to closest point and on + // right side (in projected coordinates). This is the first edge. + minSlope = VTK_DOUBLE_MAX; + for (xIdx=0, i=0; i<3; i++) + { + num = (pts[Conn[idx][i]][1] - pts[idx][1]); + den = (pts[Conn[idx][i]][0] - pts[idx][0]); + if ( den != 0.0 ) + { + slope = num / den; + } + if ( slope < minSlope && den > 0 ) + { + xIdx = Conn[idx][i]; + yIdx = Conn[idx][(i+1)%3]; + zIdx = Conn[idx][(i+2)%3]; + xAxes = i; + minSlope = slope; + } + } + + // find edge (connected to closest point) on opposite side + for ( i=0; i<2; i++) + { + e1[i] = (pts[xIdx][i] - pts[idx][i]); + e2[i] = (pts[yIdx][i] - pts[idx][i]); + e3[i] = (pts[zIdx][i] - pts[idx][i]); + } + vtkMath::Normalize2D(e1); + vtkMath::Normalize2D(e2); + vtkMath::Normalize2D(e3); + + if ( vtkMath::Dot2D(e1,e2) < vtkMath::Dot2D(e1,e3) ) + { + yAxes = (xAxes + 1) % 3; + } + else + { + yIdx = zIdx; + yAxes = (xAxes + 2) % 3; + } + + // Find the final point by determining which global x-y-z axes have not + // been represented, and then determine the point closest to the viewer. + zAxes = (xAxes != 0 && yAxes != 0 ? 0 : + (xAxes != 1 && yAxes != 1 ? 1 : 2)); + if ( pts[Conn[xIdx][zAxes]][2] < pts[Conn[yIdx][zAxes]][2] ) + { + zIdx = xIdx; + zIdx2 = Conn[xIdx][zAxes]; + } + else + { + zIdx = yIdx; + zIdx2 = Conn[yIdx][zAxes]; + } + }//else boundary edges fly mode + this->InertiaAxes[0] = idx; + this->InertiaAxes[1] = xIdx; + this->InertiaAxes[2] = yIdx; + this->InertiaAxes[3] = zIdx; + this->InertiaAxes[4] = zIdx2; + this->InertiaAxes[5] = xAxes; + this->InertiaAxes[6] = yAxes; + this->InertiaAxes[7] = zAxes; + } //inertia + else + { + idx = this->InertiaAxes[0]; + xIdx = this->InertiaAxes[1]; + yIdx = this->InertiaAxes[2]; + zIdx = this->InertiaAxes[3]; + zIdx2 = this->InertiaAxes[4]; + xAxes = this->InertiaAxes[5]; + yAxes = this->InertiaAxes[6]; + zAxes = this->InertiaAxes[7]; + } + + // Setup the axes for plotting + double xCoords[4], yCoords[4], zCoords[4], xRange[2], yRange[2], zRange[2]; + this->AdjustAxes(pts, bounds, idx, xIdx, yIdx, zIdx, zIdx2, + xAxes, yAxes, zAxes, + xCoords, yCoords, zCoords, xRange, yRange, zRange); + + // Sorry for ugly hack. I find the fonts slightly too large on the axis. BNW + double AxisFontFactor = this->FontFactor*.75; + + + // Upate axes + this->Labels[0] = this->XLabel; + this->Labels[1] = this->YLabel; + this->Labels[2] = this->ZLabel; + + this->XAxis->GetPositionCoordinate()->SetValue(xCoords[0], xCoords[1]); + this->XAxis->GetPosition2Coordinate()->SetValue(xCoords[2], xCoords[3]); + this->XAxis->SetRange(xRange[0], xRange[1]); + this->XAxis->SetTitle(this->Labels[xAxes]); + this->XAxis->SetNumberOfLabels(this->NumberOfLabels); + this->XAxis->SetLabelFormat(this->LabelFormat); + this->XAxis->SetFontFactor(AxisFontFactor); + this->XAxis->SetProperty(this->GetProperty()); + + this->YAxis->GetPositionCoordinate()->SetValue(yCoords[2], yCoords[3]); + this->YAxis->GetPosition2Coordinate()->SetValue(yCoords[0], yCoords[1]); + this->YAxis->SetRange(yRange[1], yRange[0]); + this->YAxis->SetTitle(this->Labels[yAxes]); + this->YAxis->SetNumberOfLabels(this->NumberOfLabels); + this->YAxis->SetLabelFormat(this->LabelFormat); + this->YAxis->SetFontFactor(AxisFontFactor); + this->YAxis->SetProperty(this->GetProperty()); + + this->ZAxis->GetPositionCoordinate()->SetValue(zCoords[0], zCoords[1]); + this->ZAxis->GetPosition2Coordinate()->SetValue(zCoords[2], zCoords[3]); + this->ZAxis->SetRange(zRange[0], zRange[1]); + this->ZAxis->SetTitle(this->Labels[zAxes]); + this->ZAxis->SetNumberOfLabels(this->NumberOfLabels); + this->ZAxis->SetLabelFormat(this->LabelFormat); + this->ZAxis->SetFontFactor(AxisFontFactor); + this->ZAxis->SetProperty(this->GetProperty()); + + // Rebuid text props + // Perform shallow copy here since each individual axis can be + // accessed through the class API (i.e. each individual axis text prop + // can be changed). Therefore, we can not just assign pointers otherwise + // each individual axis text prop would point to the same text prop. + + if (this->AxisLabelTextProperty && + this->AxisLabelTextProperty->GetMTime() > this->BuildTime) + { + if (this->XAxis->GetLabelTextProperty()) + { + this->XAxis->GetLabelTextProperty()->ShallowCopy( + this->AxisLabelTextProperty); + } + if (this->YAxis->GetLabelTextProperty()) + { + this->YAxis->GetLabelTextProperty()->ShallowCopy( + this->AxisLabelTextProperty); + } + if (this->ZAxis->GetLabelTextProperty()) + { + this->ZAxis->GetLabelTextProperty()->ShallowCopy( + this->AxisLabelTextProperty); + } + } + + if (this->AxisTitleTextProperty && + this->AxisTitleTextProperty->GetMTime() > this->BuildTime) + { + if (this->XAxis->GetLabelTextProperty()) + { + this->XAxis->GetTitleTextProperty()->ShallowCopy( + this->AxisTitleTextProperty); + } + if (this->YAxis->GetLabelTextProperty()) + { + this->YAxis->GetTitleTextProperty()->ShallowCopy( + this->AxisTitleTextProperty); + } + if (this->ZAxis->GetLabelTextProperty()) + { + this->ZAxis->GetTitleTextProperty()->ShallowCopy( + this->AxisTitleTextProperty); + } + } + + this->BuildTime.Modified(); + + //Render the axes + if ( this->XAxisVisibility ) + { + renderedSomething += this->XAxis->RenderOpaqueGeometry(viewport); + } + if ( this->YAxisVisibility ) + { + renderedSomething += this->YAxis->RenderOpaqueGeometry(viewport); + } + if ( this->ZAxisVisibility ) + { + renderedSomething += this->ZAxis->RenderOpaqueGeometry(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +// Do final adjustment of axes to control offset, etc. +void vtkCubeAxesActor2D::AdjustAxes(double pts[8][3], double bounds[6], + int idx, int xIdx, int yIdx, int zIdx, int zIdx2, + int xAxes, int yAxes, int zAxes, + double xCoords[4], double yCoords[4], double zCoords[4], + double xRange[2], double yRange[2], double zRange[2]) +{ + double *internal_bounds; + if ( this->UseRanges ) + { + internal_bounds = this->Ranges; + } + else + { + internal_bounds = bounds; + } + + // The x-axis + xCoords[0] = pts[idx][0]; + xCoords[1] = pts[idx][1]; + xCoords[2] = pts[xIdx][0]; + xCoords[3] = pts[xIdx][1]; + if ( idx < xIdx ) + { + xRange[0] = internal_bounds[2*xAxes]; + xRange[1] = internal_bounds[2*xAxes+1]; + } + else + { + xRange[0] = internal_bounds[2*xAxes+1]; + xRange[1] = internal_bounds[2*xAxes]; + } + + // The y-axis + yCoords[0] = pts[idx][0]; + yCoords[1] = pts[idx][1]; + yCoords[2] = pts[yIdx][0]; + yCoords[3] = pts[yIdx][1]; + if ( idx < yIdx ) + { + yRange[0] = internal_bounds[2*yAxes]; + yRange[1] = internal_bounds[2*yAxes+1]; + } + else + { + yRange[0] = internal_bounds[2*yAxes+1]; + yRange[1] = internal_bounds[2*yAxes]; + } + + // The z-axis + if ( zIdx != xIdx && zIdx != idx ) //rearrange for labels + { + zIdx = zIdx2; + zIdx2 = yIdx; + } + + zCoords[0] = pts[zIdx][0]; + zCoords[1] = pts[zIdx][1]; + zCoords[2] = pts[zIdx2][0]; + zCoords[3] = pts[zIdx2][1]; + if ( zIdx < zIdx2 ) + { + zRange[0] = internal_bounds[2*zAxes]; + zRange[1] = internal_bounds[2*zAxes+1]; + } + else + { + zRange[0] = internal_bounds[2*zAxes+1]; + zRange[1] = internal_bounds[2*zAxes]; + } + + // Pull back the corners if specified + if ( this->CornerOffset > 0.0 ) + { + double ave; + + // x-axis + ave = (xCoords[0] + xCoords[2]) / 2.0; + xCoords[0] = xCoords[0] - this->CornerOffset * (xCoords[0] - ave); + xCoords[2] = xCoords[2] - this->CornerOffset * (xCoords[2] - ave); + + ave = (xCoords[1] + xCoords[3]) / 2.0; + xCoords[1] = xCoords[1] - this->CornerOffset * (xCoords[1] - ave); + xCoords[3] = xCoords[3] - this->CornerOffset * (xCoords[3] - ave); + + ave = (xRange[1] + xRange[0]) / 2.0; + if (!this->ShowActualBounds) + { + xRange[0] = xRange[0] - this->CornerOffset * (xRange[0] - ave); + xRange[1] = xRange[1] - this->CornerOffset * (xRange[1] - ave); + } + + // y-axis + ave = (yCoords[0] + yCoords[2]) / 2.0; + yCoords[0] = yCoords[0] - this->CornerOffset * (yCoords[0] - ave); + yCoords[2] = yCoords[2] - this->CornerOffset * (yCoords[2] - ave); + + ave = (yCoords[1] + yCoords[3]) / 2.0; + yCoords[1] = yCoords[1] - this->CornerOffset * (yCoords[1] - ave); + yCoords[3] = yCoords[3] - this->CornerOffset * (yCoords[3] - ave); + + ave = (yRange[1] + yRange[0]) / 2.0; + if (!this->ShowActualBounds) + { + yRange[0] = yRange[0] - this->CornerOffset * (yRange[0] - ave); + yRange[1] = yRange[1] - this->CornerOffset * (yRange[1] - ave); + } + + // z-axis + ave = (zCoords[0] + zCoords[2]) / 2.0; + zCoords[0] = zCoords[0] - this->CornerOffset * (zCoords[0] - ave); + zCoords[2] = zCoords[2] - this->CornerOffset * (zCoords[2] - ave); + + ave = (zCoords[1] + zCoords[3]) / 2.0; + zCoords[1] = zCoords[1] - this->CornerOffset * (zCoords[1] - ave); + zCoords[3] = zCoords[3] - this->CornerOffset * (zCoords[3] - ave); + + ave = (zRange[1] + zRange[0]) / 2.0; + if (!this->ShowActualBounds) + { + zRange[0] = zRange[0] - this->CornerOffset * (zRange[0] - ave); + zRange[1] = zRange[1] - this->CornerOffset * (zRange[1] - ave); + } + } +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkCubeAxesActor2D::ReleaseGraphicsResources(vtkWindow *win) +{ + this->XAxis->ReleaseGraphicsResources(win); + this->YAxis->ReleaseGraphicsResources(win); + this->ZAxis->ReleaseGraphicsResources(win); +} + +//---------------------------------------------------------------------------- +// Return the ranges +void vtkCubeAxesActor2D::GetRanges(double ranges[6]) +{ + int i; + for ( i=0; i<6; i++ ) + { + ranges[i] = this->Ranges[i]; + } +} + +//---------------------------------------------------------------------------- +// Compute the ranges +void vtkCubeAxesActor2D::GetRanges(double& xmin, double& xmax, + double& ymin, double& ymax, + double& zmin, double& zmax) +{ + double ranges[6]; + this->GetRanges(ranges); + xmin = ranges[0]; + xmax = ranges[1]; + ymin = ranges[2]; + ymax = ranges[3]; + zmin = ranges[4]; + zmax = ranges[5]; +} + +//---------------------------------------------------------------------------- +// Compute the bounds +double *vtkCubeAxesActor2D::GetRanges() +{ + double ranges[6]; + this->GetRanges(ranges); + return this->Ranges; +} + +//---------------------------------------------------------------------------- +// Compute the bounds +void vtkCubeAxesActor2D::GetBounds(double bounds[6]) +{ + double *propBounds; + int i; + + if ( this->Input ) + { + this->Input->Update(); + this->Input->GetBounds(bounds); + for (i=0; i< 6; i++) + { + this->Bounds[i] = bounds[i]; + } + } + else if ( this->ViewProp && + ((propBounds = this->ViewProp->GetBounds()) && propBounds != NULL) ) + { + for (i=0; i< 6; i++) + { + bounds[i] = this->Bounds[i] = propBounds[i]; + } + } + else + { + for (i=0; i< 6; i++) + { + bounds[i] = this->Bounds[i]; + } + } +} + +//---------------------------------------------------------------------------- +// Compute the bounds +void vtkCubeAxesActor2D::GetBounds(double& xmin, double& xmax, + double& ymin, double& ymax, + double& zmin, double& zmax) +{ + double bounds[6]; + this->GetBounds(bounds); + xmin = bounds[0]; + xmax = bounds[1]; + ymin = bounds[2]; + ymax = bounds[3]; + zmin = bounds[4]; + zmax = bounds[5]; +} + +//---------------------------------------------------------------------------- +// Compute the bounds +double *vtkCubeAxesActor2D::GetBounds() +{ + this->GetBounds(this->Bounds); + return this->Bounds; +} + +//---------------------------------------------------------------------------- +void vtkCubeAxesActor2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Input ) + { + os << indent << "Input: (" << (void *)this->Input << ")\n"; + } + else + { + os << indent << "Input: (none)\n"; + } + + if ( this->ViewProp ) + { + os << indent << "ViewProp: (" << (void *)this->ViewProp << ")\n"; + } + else + { + os << indent << "ViewProp: (none)\n"; + } + + os << indent << "Bounds: \n"; + os << indent << " Xmin,Xmax: (" << this->Bounds[0] << ", " + << this->Bounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->Bounds[2] << ", " + << this->Bounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->Bounds[4] << ", " + << this->Bounds[5] << ")\n"; + + if ( this->Camera ) + { + os << indent << "Camera:\n"; + this->Camera->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Camera: (none)\n"; + } + + if (this->AxisTitleTextProperty) + { + os << indent << "Axis Title Text Property:\n"; + this->AxisTitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Axis Title Text Property: (none)\n"; + } + + if (this->AxisLabelTextProperty) + { + os << indent << "Axis Label Text Property:\n"; + this->AxisLabelTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Axis Label Text Property: (none)\n"; + } + + if ( this->FlyMode == VTK_FLY_CLOSEST_TRIAD ) + { + os << indent << "Fly Mode: CLOSEST_TRIAD\n"; + } + else + { + os << indent << "Fly Mode: OUTER_EDGES\n"; + } + + os << indent << "Scaling: " << (this->Scaling ? "On\n" : "Off\n"); + os << indent << "UseRanges: " << (this->UseRanges ? "On\n" : "Off\n"); + os << indent << "Ranges: \n"; + os << indent << " Xmin,Xmax: (" << this->Ranges[0] << ", " + << this->Ranges[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->Ranges[2] << ", " + << this->Ranges[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->Ranges[4] << ", " + << this->Ranges[5] << ")\n"; + + os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n"; + os << indent << "X Label: " << this->XLabel << "\n"; + os << indent << "Y Label: " << this->YLabel << "\n"; + os << indent << "Z Label: " << this->ZLabel << "\n"; + + os << indent << "X Axis Visibility: " << (this->XAxisVisibility ? "On\n" : "Off\n"); + os << indent << "Y Axis Visibility: " << (this->YAxisVisibility ? "On\n" : "Off\n"); + os << indent << "Z Axis Visibility: " << (this->ZAxisVisibility ? "On\n" : "Off\n"); + + os << indent << "Label Format: " << this->LabelFormat << "\n"; + os << indent << "Font Factor: " << this->FontFactor << "\n"; + os << indent << "Inertia: " << this->Inertia << "\n"; + os << indent << "Corner Offset: " << this->CornerOffset << "\n"; + os << indent << "UseRanges: " << (this->UseRanges ? "On" : "Off") << "\n"; + os << indent << "Ranges: " + << this->Ranges[0] << ", " << this->Ranges[1] << ", " + << this->Ranges[2] << ", " << this->Ranges[3] << ", " + << this->Ranges[4] << ", " << this->Ranges[5] << "\n"; + os << indent << "Show Actual Bounds: " << (this->ShowActualBounds ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +static int IsInBounds(double x[3], double bounds[6]); + +// Clip the axes to fit into the viewport. Do this clipping each of the three +// axes to determine which part of the cube is in view. Returns 0 if +// nothing should be drawn. +#define VTK_DIVS 10 +int vtkCubeAxesActor2D::ClipBounds(vtkViewport *viewport, double pts[8][3], + double bounds[6]) +{ + int i, j, k, numIters; + double planes[24]; + double x[3]; + double val, maxVal=0, anchor[3], scale; + double delX, delY, delZ; + double bounds2[6]; + double scale2, newScale, origin[3]; + double aspect[2]; + + // Only do this mojo if scaling is required + if ( ! this->Scaling ) + { + return 1; + } + + // Get the 6 planes defining the view frustrum + viewport->GetAspect( aspect ); + this->Camera->GetFrustumPlanes((aspect[0] / aspect[1]), planes); + + // Hunt for the point in the bounds furthest inside the frustum + // Iteratively loop over points in bounding box and evaluate the + // maximum minimum distance. Find the point furthest inside of the + // bounding box. Use this as an anchor point to scale to. Repeat + // the process to hone in on the best point. + delX = (bounds[1]-bounds[0]) / (VTK_DIVS-1); + delY = (bounds[3]-bounds[2]) / (VTK_DIVS-1); + delZ = (bounds[5]-bounds[4]) / (VTK_DIVS-1); + anchor[0] = (bounds[1]+bounds[0])/2.0; + anchor[1] = (bounds[3]+bounds[2])/2.0; + anchor[2] = (bounds[5]+bounds[4])/2.0; + + for ( numIters=0; numIters < 8; numIters++) + { + origin[0] = anchor[0] - delX*(VTK_DIVS-1)/2.0; + origin[1] = anchor[1] - delY*(VTK_DIVS-1)/2.0; + origin[2] = anchor[2] - delZ*(VTK_DIVS-1)/2.0; + + for (maxVal=0.0, k=0; kEvaluatePoint(planes, x); + if ( val > maxVal ) + { + anchor[0] = x[0]; + anchor[1] = x[1]; + anchor[2] = x[2]; + maxVal = val; + } + }//if in bounding box + }//i + }//j + }//k + + delX /= (VTK_DIVS-1) * 1.414; + delY /= (VTK_DIVS-1) * 1.414; + delZ /= (VTK_DIVS-1) * 1.414; + }//Iteratively find anchor point + + if ( maxVal <= 0.0 ) + { + return 0; //couldn't find a point inside + } + + // Now iteratively scale the bounding box until all points are inside + // the frustrum. Use bisection method. + scale = 1.0; + scale2 = 0.00001; + val = this->EvaluateBounds(planes, bounds); + + // Get other end point for bisection technique + for (i=0; i<3; i++) + { + bounds2[2*i] = (bounds[2*i]-anchor[i])*scale2 + anchor[i]; + bounds2[2*i+1] = (bounds[2*i+1]-anchor[i])*scale2 + anchor[i]; + } + val = this->EvaluateBounds(planes, bounds2); + if ( val <= 0.0 ) + { + return 0; //not worth drawing - too small + } + + for ( numIters=0; numIters < 10; numIters++) + { + newScale = (scale + scale2) / 2.0; + for (i=0; i<3; i++) + { + bounds2[2*i] = (bounds[2*i]-anchor[i])*newScale + anchor[i]; + bounds2[2*i+1] = (bounds[2*i+1]-anchor[i])*newScale + anchor[i]; + } + val = this->EvaluateBounds(planes, bounds2); + + if ( val > 0.0 ) + { + scale2 = newScale; + } + else + { + scale = newScale; + } + }//for converged + + for (i=0; i<6; i++) //copy the result + { + bounds[i] = bounds2[i]; + } + + this->TransformBounds(viewport, bounds, pts); + + return 1; +} +#undef VTK_DIVS + +//---------------------------------------------------------------------------- +void vtkCubeAxesActor2D::TransformBounds(vtkViewport *viewport, + double bounds[6], double pts[8][3]) +{ + int i, j, k, idx; + double x[3]; + + //loop over verts of bounding box + for (k=0; k<2; k++) + { + x[2] = bounds[4+k]; + for (j=0; j<2; j++) + { + x[1] = bounds[2+j]; + for (i=0; i<2; i++) + { + idx = i + 2*j + 4*k; + x[0] = bounds[i]; + viewport->SetWorldPoint(x[0],x[1],x[2],1.0); + viewport->WorldToDisplay(); + viewport->GetDisplayPoint(pts[idx]); + } + } + } +} + +//---------------------------------------------------------------------------- +// Return smallest value of point evaluated against frustum planes. Also +// sets the closest point coordinates in xyz. +double vtkCubeAxesActor2D::EvaluatePoint(double planes[24], double x[3]) +{ + int kk; + double *plane; + double val, minPlanesValue; + + for (minPlanesValue=VTK_DOUBLE_MAX, kk=0; kk<6 ; kk++) + { + plane = planes + kk*4; + val = plane[0]*x[0] + plane[1]*x[1] + plane[2]*x[2] + plane[3]; + + if ( val < minPlanesValue ) + { + minPlanesValue = val; + } + }//for all planes + + return minPlanesValue; +} + +//---------------------------------------------------------------------------- +// Return the smallest point of the bounding box evaluated against the +// frustum planes. +double vtkCubeAxesActor2D::EvaluateBounds(double planes[24], double bounds[6]) +{ + double val, minVal, x[3]; + int i, j, k; + + for (minVal=VTK_DOUBLE_MAX, k=0; k<2; k++) + { + x[2] = bounds[4+k]; + for (j=0; j<2; j++) + { + x[1] = bounds[2+j]; + for (i=0; i<2; i++) + { + x[0] = bounds[i]; + val = this->EvaluatePoint(planes, x); + if ( val < minVal ) + { + minVal = val; + } + } + } + }//loop over verts of bounding box + + return minVal; +} + +//---------------------------------------------------------------------------- +static int IsInBounds(double x[3], double bounds[6]) +{ + if ( x[0] < bounds[0] || x[0] > bounds[1] || + x[1] < bounds[2] || x[1] > bounds[3] || + x[2] < bounds[4] || x[2] > bounds[5]) + { + return 0; + } + else + { + return 1; + } +} + +//---------------------------------------------------------------------------- + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (disable:858) +#endif + +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SetProp +# undef GetProp +void const vtkCubeAxesActor2D::SetPropA(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::SetProp, "VTK 5.0", + vtkCubeAxesActor2D::SetViewProp); + this->SetViewProp(prop); +} +void const vtkCubeAxesActor2D::SetPropW(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::SetProp, "VTK 5.0", + vtkCubeAxesActor2D::SetViewProp); + this->SetViewProp(prop); +} +vtkProp* const vtkCubeAxesActor2D::GetPropA() +{ + VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::GetProp, "VTK 5.0", + vtkCubeAxesActor2D::GetViewProp); + return this->GetViewProp(); +} +vtkProp* const vtkCubeAxesActor2D::GetPropW() +{ + VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::GetProp, "VTK 5.0", + vtkCubeAxesActor2D::GetViewProp); + return this->GetViewProp(); +} +# endif +void const vtkCubeAxesActor2D::SetProp(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::SetProp, "VTK 5.0", + vtkCubeAxesActor2D::SetViewProp); + this->SetViewProp(prop); +} +vtkProp* const vtkCubeAxesActor2D::GetProp() +{ + VTK_LEGACY_REPLACED_BODY(vtkCubeAxesActor2D::GetProp, "VTK 5.0", + vtkCubeAxesActor2D::GetViewProp); + return this->GetViewProp(); +} +#endif diff --git a/Hybrid/vtkCubeAxesActor2D.h b/Hybrid/vtkCubeAxesActor2D.h new file mode 100644 index 0000000..7a4b21d --- /dev/null +++ b/Hybrid/vtkCubeAxesActor2D.h @@ -0,0 +1,350 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCubeAxesActor2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCubeAxesActor2D - create a 2D plot of a bounding box edges - used for navigation +// .SECTION Description +// vtkCubeAxesActor2D is a composite actor that draws three axes of the +// bounding box of an input dataset. The axes include labels and titles +// for the x-y-z axes. The algorithm selects the axes that are on the +// "exterior" of the bounding box, exterior as determined from examining +// outer edges of the bounding box in projection (display) space. Alternatively, +// the edges closest to the viewer (i.e., camera position) can be drawn. +// +// To use this object you must define a bounding box and the camera used +// to render the vtkCubeAxesActor2D. The camera is used to control the +// scaling and position of the vtkCubeAxesActor2D so that it fits in the +// viewport and always remains visible.) +// +// The font property of the axes titles and labels can be modified through the +// AxisTitleTextProperty and AxisLabelTextProperty attributes. You may also +// use the GetXAxisActor2D, GetYAxisActor2D or GetZAxisActor2D methods +// to access each individual axis actor to modify their font properties. +// +// The bounding box to use is defined in one of three ways. First, if the Input +// ivar is defined, then the input dataset's bounds is used. If the Input is +// not defined, and the Prop (superclass of all actors) is defined, then the +// Prop's bounds is used. If neither the Input or Prop is defined, then the +// Bounds instance variable (an array of six doubles) is used. +// +// .SECTION See Also +// vtkActor2D vtkAxisActor2D vtkXYPlotActor vtkTextProperty + +#ifndef __vtkCubeAxesActor2D_h +#define __vtkCubeAxesActor2D_h + +#include "vtkActor2D.h" + +#define VTK_FLY_OUTER_EDGES 0 +#define VTK_FLY_CLOSEST_TRIAD 1 + +class vtkAxisActor2D; +class vtkCamera; +class vtkDataSet; +class vtkTextProperty; + +class VTK_HYBRID_EXPORT vtkCubeAxesActor2D : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkCubeAxesActor2D,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with bold, italic, and shadow enabled; font family + // set to Arial; and label format "6.3g". The number of labels per axis + // is set to 3. + static vtkCubeAxesActor2D *New(); + + // Description: + // Draw the axes as per the vtkProp superclass' API. + int RenderOverlay(vtkViewport*); + int RenderOpaqueGeometry(vtkViewport*); + int RenderTranslucentGeometry(vtkViewport *) {return 0;} + + // Description: + // Use the bounding box of this input dataset to draw the cube axes. If this + // is not specified, then the class will attempt to determine the bounds from + // the defined Prop or Bounds. + virtual void SetInput(vtkDataSet*); + vtkGetObjectMacro(Input, vtkDataSet); + + // Description: + // Use the bounding box of this prop to draw the cube axes. The + // ViewProp is used to determine the bounds only if the Input is not + // defined. + void SetViewProp(vtkProp* prop); + vtkGetObjectMacro(ViewProp, vtkProp); + + // Description: + // Explicitly specify the region in space around which to draw the bounds. + // The bounds is used only when no Input or Prop is specified. The bounds + // are specified according to (xmin,xmax, ymin,ymax, zmin,zmax), making + // sure that the min's are less than the max's. + vtkSetVector6Macro(Bounds,double); + double *GetBounds(); + void GetBounds(double& xmin, double& xmax, double& ymin, double& ymax, + double& zmin, double& zmax); + void GetBounds(double bounds[6]); + + // Description: + // Explicitly specify the range of values used on the bounds. + // The ranges are specified according to (xmin,xmax, ymin,ymax, zmin,zmax), + // making sure that the min's are less than the max's. + vtkSetVector6Macro(Ranges,double); + double *GetRanges(); + void GetRanges(double& xmin, double& xmax, double& ymin, double& ymax, + double& zmin, double& zmax); + void GetRanges(double ranges[6]); + + // Description: + // Set/Get a flag that controls whether the axes use the data ranges + // or the ranges set by SetRanges. By default the axes use the data + // ranges. + vtkSetMacro(UseRanges,int); + vtkGetMacro(UseRanges,int); + vtkBooleanMacro(UseRanges,int); + + // Description: + // Set/Get the camera to perform scaling and translation of the + // vtkCubeAxesActor2D. + virtual void SetCamera(vtkCamera*); + vtkGetObjectMacro(Camera,vtkCamera); + + // Description: + // Specify a mode to control how the axes are drawn: either outer edges + // or closest triad to the camera position. + vtkSetClampMacro(FlyMode, int, VTK_FLY_OUTER_EDGES, VTK_FLY_CLOSEST_TRIAD); + vtkGetMacro(FlyMode, int); + void SetFlyModeToOuterEdges() + {this->SetFlyMode(VTK_FLY_OUTER_EDGES);}; + void SetFlyModeToClosestTriad() + {this->SetFlyMode(VTK_FLY_CLOSEST_TRIAD);}; + + // Description: + // Set/Get a flag that controls whether the axes are scaled to fit in + // the viewport. If off, the axes size remains constant (i.e., stay the + // size of the bounding box). By default scaling is on so the axes are + // scaled to fit inside the viewport. + vtkSetMacro(Scaling,int); + vtkGetMacro(Scaling,int); + vtkBooleanMacro(Scaling,int); + + // Description: + // Set/Get the number of annotation labels to show along the x, y, and + // z axes. This values is a suggestion: the number of labels may vary + // depending on the particulars of the data. + vtkSetClampMacro(NumberOfLabels, int, 0, 50); + vtkGetMacro(NumberOfLabels, int); + + // Description: + // Set/Get the labels for the x, y, and z axes. By default, + // use "X", "Y" and "Z". + vtkSetStringMacro(XLabel); + vtkGetStringMacro(XLabel); + vtkSetStringMacro(YLabel); + vtkGetStringMacro(YLabel); + vtkSetStringMacro(ZLabel); + vtkGetStringMacro(ZLabel); + + // Description: + // Retrieve handles to the X, Y and Z axis (so that you can set their text + // properties for example) + vtkAxisActor2D *GetXAxisActor2D() + {return this->XAxis;} + vtkAxisActor2D *GetYAxisActor2D() + {return this->YAxis;} + vtkAxisActor2D *GetZAxisActor2D() + {return this->ZAxis;} + + // Description: + // Set/Get the title text property of all axes. Note that each axis can + // be controlled individually through the GetX/Y/ZAxisActor2D() methods. + virtual void SetAxisTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(AxisTitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the labels text property of all axes. Note that each axis can + // be controlled individually through the GetX/Y/ZAxisActor2D() methods. + virtual void SetAxisLabelTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(AxisLabelTextProperty,vtkTextProperty); + + // Description: + // Set/Get the format with which to print the labels on each of the + // x-y-z axes. + vtkSetStringMacro(LabelFormat); + vtkGetStringMacro(LabelFormat); + + // Description: + // Set/Get the factor that controls the overall size of the fonts used + // to label and title the axes. + vtkSetClampMacro(FontFactor, double, 0.1, 2.0); + vtkGetMacro(FontFactor, double); + + // Description: + // Set/Get the inertial factor that controls how often (i.e, how + // many renders) the axes can switch position (jump from one axes + // to another). + vtkSetClampMacro(Inertia, int, 1, VTK_LARGE_INTEGER); + vtkGetMacro(Inertia, int); + + // Description: + // Set/Get the variable that controls whether the actual + // bounds of the dataset are always shown. Setting this variable + // to 1 means that clipping is disabled and that the actual + // value of the bounds is displayed even with corner offsets + // Setting this variable to 0 means these axis will clip + // themselves and show variable bounds (legacy mode) + vtkSetClampMacro(ShowActualBounds, int, 0, 1); + vtkGetMacro(ShowActualBounds, int); + + // Description: + // Specify an offset value to "pull back" the axes from the corner at + // which they are joined to avoid overlap of axes labels. The + // "CornerOffset" is the fraction of the axis length to pull back. + vtkSetMacro(CornerOffset, double); + vtkGetMacro(CornerOffset, double); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Turn on and off the visibility of each axis. + vtkSetMacro(XAxisVisibility,int); + vtkGetMacro(XAxisVisibility,int); + vtkBooleanMacro(XAxisVisibility,int); + vtkSetMacro(YAxisVisibility,int); + vtkGetMacro(YAxisVisibility,int); + vtkBooleanMacro(YAxisVisibility,int); + vtkSetMacro(ZAxisVisibility,int); + vtkGetMacro(ZAxisVisibility,int); + vtkBooleanMacro(ZAxisVisibility,int); + + // Description: + // Shallow copy of a CubeAxesActor2D. + void ShallowCopy(vtkCubeAxesActor2D *actor); + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (push) +# pragma warning (disable:858) +#endif + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define SetPropA SetProp +# define SetPropW SetProp +# define GetPropA GetProp +# define GetPropW GetProp +#endif + + // Description: + // @deprecated Replaced by vtkCubeAxesActor2D::SetViewProp() as of VTK 5.0. + VTK_LEGACY(virtual void const SetProp(vtkProp* prop)); + + // Description: + // @deprecated Replaced by vtkCubeAxesActor2D::GetViewProp() as of VTK 5.0. + VTK_LEGACY(virtual vtkProp* const GetProp()); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SetPropW +# undef SetPropA +# undef GetPropW +# undef GetPropA + //BTX + VTK_LEGACY(virtual void const SetPropA(vtkProp* prop)); + VTK_LEGACY(virtual void const SetPropW(vtkProp* prop)); + VTK_LEGACY(virtual vtkProp* const GetPropA()); + VTK_LEGACY(virtual vtkProp* const GetPropW()); + //ETX +#endif + +// Reset disabled warning about qualifiers on return types. +#if defined(__INTEL_COMPILER) +# pragma warning (pop) +#endif +#if defined(_COMPILER_VERSION) +# pragma reset woff 3303 +#endif + +protected: + vtkCubeAxesActor2D(); + ~vtkCubeAxesActor2D(); + + vtkDataSet *Input; //Define bounds from input data, or + vtkProp *ViewProp; //Define bounds from actor/assembly, or + double Bounds[6]; //Define bounds explicitly + double Ranges[6]; //Define ranges explicitly + int UseRanges; //Flag to use ranges or not + + vtkCamera *Camera; + int FlyMode; + int Scaling; + + vtkAxisActor2D *XAxis; + vtkAxisActor2D *YAxis; + vtkAxisActor2D *ZAxis; + + vtkTextProperty *AxisTitleTextProperty; + vtkTextProperty *AxisLabelTextProperty; + + vtkTimeStamp BuildTime; + + int NumberOfLabels; + char *XLabel; + char *YLabel; + char *ZLabel; + char *Labels[3]; + + int XAxisVisibility; + int YAxisVisibility; + int ZAxisVisibility; + + char *LabelFormat; + double FontFactor; + double CornerOffset; + int Inertia; + int RenderCount; + int InertiaAxes[8]; + + int RenderSomething; + + // Always show the actual bounds of the object + int ShowActualBounds; + + // various helper methods + void TransformBounds(vtkViewport *viewport, double bounds[6], + double pts[8][3]); + int ClipBounds(vtkViewport *viewport, double pts[8][3], double bounds[6]); + double EvaluatePoint(double planes[24], double x[3]); + double EvaluateBounds(double planes[24], double bounds[6]); + void AdjustAxes(double pts[8][3], double bounds[6], + int idx, int xIdx, int yIdx, int zIdx, int zIdx2, + int xAxes, int yAxes, int zAxes, + double xCoords[4], double yCoords[4], double zCoords[4], + double xRange[2], double yRange[2], double zRange[2]); + +private: + // hide the superclass' ShallowCopy() from the user and the compiler. + void ShallowCopy(vtkProp *prop) { this->vtkProp::ShallowCopy( prop ); }; +private: + vtkCubeAxesActor2D(const vtkCubeAxesActor2D&); // Not implemented. + void operator=(const vtkCubeAxesActor2D&); // Not implemented. +}; + + +#endif diff --git a/Hybrid/vtkDSPFilterDefinition.cxx b/Hybrid/vtkDSPFilterDefinition.cxx new file mode 100644 index 0000000..150c387 --- /dev/null +++ b/Hybrid/vtkDSPFilterDefinition.cxx @@ -0,0 +1,227 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDSPFilterDefinition.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkDSPFilterDefinition.h" +#include "vtkObjectFactory.h" + +#include +#include +#include +#include +#include + +vtkCxxRevisionMacro(vtkDSPFilterDefinition, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkDSPFilterDefinition); + +class vtkDSPFilterDefinitionVectorDoubleSTLCloak +{ +public: + vtkstd::vector m_vector; +}; +class vtkDSPFilterDefinitionStringSTLCloak +{ +public: + vtkstd::string m_string; +}; + + +//---------------------------------------------------------------------------- +vtkDSPFilterDefinition::vtkDSPFilterDefinition() +{ + //printf(" in vtkDSPFilterDefinition::vtkDSPFilterDefinition()\n"); + this->NumeratorWeights = new vtkDSPFilterDefinitionVectorDoubleSTLCloak; + this->ForwardNumeratorWeights = new vtkDSPFilterDefinitionVectorDoubleSTLCloak; + this->DenominatorWeights = new vtkDSPFilterDefinitionVectorDoubleSTLCloak; + this->InputVariableName = new vtkDSPFilterDefinitionStringSTLCloak; + this->OutputVariableName = new vtkDSPFilterDefinitionStringSTLCloak; + + this->NumeratorWeights->m_vector.resize(0); + this->ForwardNumeratorWeights->m_vector.resize(0); + this->DenominatorWeights->m_vector.resize(0); + this->InputVariableName->m_string=""; + this->OutputVariableName->m_string=""; +} +//---------------------------------------------------------------------------- +vtkDSPFilterDefinition::vtkDSPFilterDefinition(vtkDSPFilterDefinition *other) +{ + //printf(" in vtkDSPFilterDefinition::vtkDSPFilterDefinition(vtkDSPFilterDefinition *other)\n"); + this->NumeratorWeights = new vtkDSPFilterDefinitionVectorDoubleSTLCloak; + this->ForwardNumeratorWeights = new vtkDSPFilterDefinitionVectorDoubleSTLCloak; + this->DenominatorWeights = new vtkDSPFilterDefinitionVectorDoubleSTLCloak; + this->InputVariableName = new vtkDSPFilterDefinitionStringSTLCloak; + this->OutputVariableName = new vtkDSPFilterDefinitionStringSTLCloak; + + this->NumeratorWeights->m_vector = other->NumeratorWeights->m_vector; + this->ForwardNumeratorWeights->m_vector = other->ForwardNumeratorWeights->m_vector; + this->DenominatorWeights->m_vector = other->DenominatorWeights->m_vector; + this->InputVariableName->m_string = other->InputVariableName->m_string; + this->OutputVariableName->m_string = other->OutputVariableName->m_string; +} +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::Copy(vtkDSPFilterDefinition *other) +{ + //printf(" in vtkDSPFilterDefinition::Copy(vtkDSPFilterDefinition *other)\n"); + this->NumeratorWeights->m_vector = other->NumeratorWeights->m_vector; + this->ForwardNumeratorWeights->m_vector = other->ForwardNumeratorWeights->m_vector; + this->DenominatorWeights->m_vector = other->DenominatorWeights->m_vector; + this->InputVariableName->m_string = other->InputVariableName->m_string; + this->OutputVariableName->m_string = other->OutputVariableName->m_string; +} +//---------------------------------------------------------------------------- +vtkDSPFilterDefinition::~vtkDSPFilterDefinition() +{ + this->NumeratorWeights->m_vector.resize(0); + this->ForwardNumeratorWeights->m_vector.resize(0); + this->DenominatorWeights->m_vector.resize(0); + this->InputVariableName->m_string=""; + this->OutputVariableName->m_string=""; + + + delete this->NumeratorWeights; + delete this->ForwardNumeratorWeights; + delete this->DenominatorWeights; + delete this->InputVariableName; + delete this->OutputVariableName; +} +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::Clear() +{ + this->NumeratorWeights->m_vector.resize(0); + this->ForwardNumeratorWeights->m_vector.resize(0); + this->DenominatorWeights->m_vector.resize(0); + this->InputVariableName->m_string=""; + this->OutputVariableName->m_string=""; +} +//---------------------------------------------------------------------------- +bool vtkDSPFilterDefinition::IsThisInputVariableInstanceNeeded( int a_timestep, int a_outputTimestep ) +{ + if(a_outputTimestepForwardNumeratorWeights->m_vector.size())>=l_index ) + { + //the filter does use this future input + //printf("FILTER USES FUTURE INPUT %d for output %d\n",a_timestep,a_outputTimestep); + return(true); + } + else + { + //future inputs not used for 1d filter + //printf("FILTER doesnt use FUTURE INPUT %d for output %d\n",a_timestep,a_outputTimestep); + return(false); + } + } + if( this->DenominatorWeights->m_vector.size() > 1 ) + { + //with an iir filter, all prev outputs since the beginning of time are used, + //therefore all prev inputs are used as well + return(true); + } + + //For an fir filter, only a certain number of past inputs are needed + if( a_timestep < a_outputTimestep-((int)(this->NumeratorWeights->m_vector.size())-1) ) + { + //this input is too far in the past + return(false); + } + return(true); +} + + +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::PushBackNumeratorWeight(double a_value) +{ + this->NumeratorWeights->m_vector.push_back(a_value); +} +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::PushBackDenominatorWeight(double a_value) +{ + this->DenominatorWeights->m_vector.push_back(a_value); +} +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::PushBackForwardNumeratorWeight(double a_value) +{ + this->ForwardNumeratorWeights->m_vector.push_back(a_value); +} + +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::SetInputVariableName(char *a_value) +{ + this->InputVariableName->m_string = a_value; +} +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::SetOutputVariableName(char *a_value) +{ + this->OutputVariableName->m_string = a_value; +} + +//---------------------------------------------------------------------------- +const char *vtkDSPFilterDefinition::GetInputVariableName() +{ + return this->InputVariableName->m_string.c_str(); +} +//---------------------------------------------------------------------------- +const char *vtkDSPFilterDefinition::GetOutputVariableName() +{ + return this->OutputVariableName->m_string.c_str(); +} + + +//---------------------------------------------------------------------------- +int vtkDSPFilterDefinition::GetNumNumeratorWeights() +{ + return this->NumeratorWeights->m_vector.size(); +} +//---------------------------------------------------------------------------- +int vtkDSPFilterDefinition::GetNumDenominatorWeights() +{ + return this->DenominatorWeights->m_vector.size(); +} +//---------------------------------------------------------------------------- +int vtkDSPFilterDefinition::GetNumForwardNumeratorWeights() +{ + return this->ForwardNumeratorWeights->m_vector.size(); +} + + + +//---------------------------------------------------------------------------- +double vtkDSPFilterDefinition::GetNumeratorWeight(int a_which) +{ + return this->NumeratorWeights->m_vector[a_which]; +} +//---------------------------------------------------------------------------- +double vtkDSPFilterDefinition::GetDenominatorWeight(int a_which) +{ + return this->DenominatorWeights->m_vector[a_which]; +} +//---------------------------------------------------------------------------- +double vtkDSPFilterDefinition::GetForwardNumeratorWeight(int a_which) +{ + return this->ForwardNumeratorWeights->m_vector[a_which]; +} + + +//---------------------------------------------------------------------------- +void vtkDSPFilterDefinition::PrintSelf(ostream &os, vtkIndent indent) +{ + + this->Superclass::PrintSelf( os, indent ); +} diff --git a/Hybrid/vtkDSPFilterDefinition.h b/Hybrid/vtkDSPFilterDefinition.h new file mode 100644 index 0000000..7658cef --- /dev/null +++ b/Hybrid/vtkDSPFilterDefinition.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDSPFilterDefinition.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#ifndef __vtkDSPFilterDefinition_h +#define __vtkDSPFilterDefinition_h + + + +#include "vtkObject.h" + +class vtkDSPFilterDefinitionVectorDoubleSTLCloak; +class vtkDSPFilterDefinitionStringSTLCloak; + +class VTK_HYBRID_EXPORT vtkDSPFilterDefinition : public vtkObject +{ + public: + vtkTypeRevisionMacro(vtkDSPFilterDefinition, vtkObject); + void PrintSelf(ostream &os, vtkIndent indent); + static vtkDSPFilterDefinition *New(); + + protected: + vtkDSPFilterDefinition(); + vtkDSPFilterDefinition(vtkDSPFilterDefinition *other); + ~vtkDSPFilterDefinition(); + + public: + void Copy(vtkDSPFilterDefinition *other); + void Clear(); + bool IsThisInputVariableInstanceNeeded( int a_timestep, int a_outputTimestep ); + + void PushBackNumeratorWeight(double a_value); + void PushBackDenominatorWeight(double a_value); + void PushBackForwardNumeratorWeight(double a_value); + void SetInputVariableName(char *a_value); + void SetOutputVariableName(char *a_value); + const char *GetInputVariableName(); + const char *GetOutputVariableName(); + + int GetNumNumeratorWeights(); + int GetNumDenominatorWeights(); + int GetNumForwardNumeratorWeights(); + + double GetNumeratorWeight(int a_which); + double GetDenominatorWeight(int a_which); + double GetForwardNumeratorWeight(int a_which); + + + vtkDSPFilterDefinitionVectorDoubleSTLCloak *NumeratorWeights; + vtkDSPFilterDefinitionVectorDoubleSTLCloak *DenominatorWeights; + vtkDSPFilterDefinitionVectorDoubleSTLCloak *ForwardNumeratorWeights; + + vtkDSPFilterDefinitionStringSTLCloak *InputVariableName; + vtkDSPFilterDefinitionStringSTLCloak *OutputVariableName; + +protected: + +private: + vtkDSPFilterDefinition(const vtkDSPFilterDefinition&); // Not implemented + void operator=(const vtkDSPFilterDefinition&); // Not implemented +}; + + + +#endif diff --git a/Hybrid/vtkDSPFilterGroup.cxx b/Hybrid/vtkDSPFilterGroup.cxx new file mode 100644 index 0000000..1e13d29 --- /dev/null +++ b/Hybrid/vtkDSPFilterGroup.cxx @@ -0,0 +1,548 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDSPFilterGroup.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkDSPFilterGroup.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkIntArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkStructuredGrid.h" +#include "vtkObjectFactory.h" +#include "vtkDSPFilterDefinition.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkDSPFilterGroup, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkDSPFilterGroup); + + +class vtkDSPFilterGroupVectorIntSTLCloak +{ +public: + vtkstd::vector m_vector; +}; +class vtkDSPFilterGroupVectorVectorIntSTLCloak +{ +public: + vtkstd::vector< vtkstd::vector > m_vector; +}; + +class vtkDSPFilterGroupVectorArraySTLCloak +{ +public: + vtkstd::vector m_vector; +}; +class vtkDSPFilterGroupVectorVectorArraySTLCloak +{ +public: + vtkstd::vector< vtkstd::vector > m_vector; +}; +class vtkDSPFilterGroupVectorStringSTLCloak +{ +public: + vtkstd::vector m_vector; +}; + +class vtkDSPFilterGroupVectorDefinitionSTLCloak +{ +public: + vtkstd::vector m_vector; +}; + + +//---------------------------------------------------------------------------- +vtkDSPFilterGroup::vtkDSPFilterGroup() +{ + this->FilterDefinitions = new vtkDSPFilterGroupVectorDefinitionSTLCloak; + this->CachedInputs = new vtkDSPFilterGroupVectorArraySTLCloak; + this->CachedInputNames = new vtkDSPFilterGroupVectorStringSTLCloak; + this->CachedInputTimesteps = new vtkDSPFilterGroupVectorIntSTLCloak; + this->CachedOutputs = new vtkDSPFilterGroupVectorVectorArraySTLCloak; + this->CachedOutputTimesteps = new vtkDSPFilterGroupVectorVectorIntSTLCloak; + + this->FilterDefinitions->m_vector.resize(0); + this->CachedInputs->m_vector.resize(0); + this->CachedInputNames->m_vector.resize(0); + this->CachedInputTimesteps->m_vector.resize(0); + this->CachedOutputs->m_vector.resize(0); + this->CachedOutputTimesteps->m_vector.resize(0); +} + +//---------------------------------------------------------------------------- +vtkDSPFilterGroup::~vtkDSPFilterGroup() +{ + this->FilterDefinitions->m_vector.resize(0); + this->CachedInputs->m_vector.resize(0); + this->CachedInputNames->m_vector.resize(0); + this->CachedInputTimesteps->m_vector.resize(0); + this->CachedOutputs->m_vector.resize(0); + this->CachedOutputTimesteps->m_vector.resize(0); + + delete this->FilterDefinitions; + delete this->CachedInputs; + delete this->CachedInputNames; + delete this->CachedInputTimesteps; + delete this->CachedOutputs; + delete this->CachedOutputTimesteps; +} + + +//---------------------------------------------------------------------------- +void vtkDSPFilterGroup::AddFilter(vtkDSPFilterDefinition *filter) +{ + //XXX cant just add this filter, need to check for duplicates and removals? + + vtkDSPFilterDefinition *thefilter = vtkDSPFilterDefinition::New(); + thefilter->Copy(filter); + + + this->FilterDefinitions->m_vector.push_back( thefilter ); + + vtkstd::vector l_cachedOutsForThisFilter; + l_cachedOutsForThisFilter.resize(0); + this->CachedOutputs->m_vector.push_back( l_cachedOutsForThisFilter ); + + vtkstd::vector l_cachedOutTimesForThisFilter; + l_cachedOutTimesForThisFilter.resize(0); + this->CachedOutputTimesteps->m_vector.push_back(l_cachedOutTimesForThisFilter); + + +#if 0 + printf("**********************FILTERS AFTER ADDING FILTER***********************\n"); + for(int i=0;iGetNumFilters();i++) + { + vtkDSPFilterDefinition *filterfromlist = this->FilterDefinitions->m_vector[i]; + printf("vtkDSPFilterGroup::AddFilter %d of %d input=%s output=%s nums=%d dens=%d forwardnums=%d this=%p\n", + i,this->GetNumFilters(), + filterfromlist->GetInputVariableName(), + filterfromlist->GetOutputVariableName(), + filterfromlist->GetNumNumeratorWeights(), + filterfromlist->GetNumDenominatorWeights(), + filterfromlist->GetNumForwardNumeratorWeights(), + this); + } + printf("************************************************************************\n"); +#endif +} + +//---------------------------------------------------------------------------- +void vtkDSPFilterGroup::RemoveFilter(char *a_outputVariableName) +{ + vtkstd::vector::iterator l_iter; + vtkstd::vector< vtkstd::vector >::iterator l_cachedOutputsIter = this->CachedOutputs->m_vector.begin(); + vtkstd::vector< vtkstd::vector >::iterator l_cachedOutputTimesIter = this->CachedOutputTimesteps->m_vector.begin(); + + for(l_iter=this->FilterDefinitions->m_vector.begin();l_iter!=this->FilterDefinitions->m_vector.end();l_iter++) + { + if(!strcmp(a_outputVariableName,(*l_iter)->GetOutputVariableName())) + { + //this is the filter to delete + this->FilterDefinitions->m_vector.erase(l_iter); + if(l_cachedOutputsIter!=this->CachedOutputs->m_vector.end()) + this->CachedOutputs->m_vector.erase(l_cachedOutputsIter); + if(l_cachedOutputTimesIter!=this->CachedOutputTimesteps->m_vector.end()) + this->CachedOutputTimesteps->m_vector.erase(l_cachedOutputTimesIter); + break; + } + l_cachedOutputsIter++; + l_cachedOutputTimesIter++; + } + +#if 0 + printf("**********************FILTERS AFTER REMOVING FILTER*********************\n"); + for(int i=0;iGetNumFilters();i++) + { + vtkDSPFilterDefinition *filterfromlist = this->FilterDefinitions[i]; + printf("vtkDSPFilterGroup::RemoveFilter %d of %d input=%s output=%s nums=%d dens=%d this=%p\n", + i,this->GetNumFilters(), + filterfromlist->GetInputVariableName(), + filterfromlist->GetOutputVariableName(), + filterfromlist->GetNumNumeratorWeights(), + filterfromlist->GetNumDenominatorWeights(), + this); + } + printf("************************************************************************\n"); +#endif +} + + +//---------------------------------------------------------------------------- +void vtkDSPFilterGroup::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + + +//---------------------------------------------------------------------------- +const char *vtkDSPFilterGroup::GetInputVariableName( int a_whichFilter ) +{ + return this->FilterDefinitions->m_vector[a_whichFilter]->GetInputVariableName(); +} +//---------------------------------------------------------------------------- +bool vtkDSPFilterGroup::IsThisInputVariableInstanceNeeded( const char *a_name, int a_timestep, int a_outputTimestep ) +{ + for(int i=0; iGetNumFilters(); i++) + { + if( !strcmp(this->FilterDefinitions->m_vector[i]->GetInputVariableName(),a_name) ) + { + if( this->FilterDefinitions->m_vector[i]->IsThisInputVariableInstanceNeeded(a_timestep,a_outputTimestep) ) + { + return(true); + } + } + } + return(false); +} +//---------------------------------------------------------------------------- +bool vtkDSPFilterGroup::IsThisInputVariableInstanceCached( const char *a_name, int a_timestep ) +{ + for(int i=0;i<(int)this->CachedInputTimesteps->m_vector.size();i++) + { + if(this->CachedInputTimesteps->m_vector[i]==a_timestep) + { + if( this->CachedInputNames->m_vector[i]==a_name ) + { + return(true); + } + } + } + return(false); +} +//---------------------------------------------------------------------------- +void vtkDSPFilterGroup::AddInputVariableInstance( const char *a_name, int a_timestep, vtkFloatArray *a_data ) +{ + //This assumes that the instance is not already cached! perhaps should check anyway? + + this->CachedInputTimesteps->m_vector.push_back(a_timestep); + this->CachedInputNames->m_vector.push_back(a_name); + + vtkFloatArray *l_array = vtkFloatArray::New(); + l_array->DeepCopy(a_data); + this->CachedInputs->m_vector.push_back(l_array); +} + +//---------------------------------------------------------------------------- +vtkFloatArray *vtkDSPFilterGroup::GetCachedInput( int a_whichFilter, int a_whichTimestep ) +{ + vtkstd::string l_inputName = this->FilterDefinitions->m_vector[a_whichFilter]->GetInputVariableName(); + for(int i=0;i<(int)this->CachedInputTimesteps->m_vector.size();i++) + { + if(this->CachedInputTimesteps->m_vector[i]==a_whichTimestep) + { + if( this->CachedInputNames->m_vector[i]==l_inputName ) + { + return(this->CachedInputs->m_vector[i]); + } + } + } + return(NULL); +} + + +//---------------------------------------------------------------------------- +vtkFloatArray *vtkDSPFilterGroup::GetCachedOutput( int a_whichFilter, int a_whichTimestep ) +{ + for(int i=0;i<(int)this->CachedOutputs->m_vector[a_whichFilter].size();i++) + { + if(a_whichTimestep==this->CachedOutputTimesteps->m_vector[a_whichFilter][i]) + { + vtkFloatArray *l_tmp = (this->CachedOutputs->m_vector[a_whichFilter])[i]; + if( !strcmp( l_tmp->GetName(), + this->FilterDefinitions->m_vector[a_whichFilter]->GetOutputVariableName() )) + { + //printf("vtkDSPFilterGroup::GetCachedOutput found time %d output in cache\n",a_whichTimestep); + return(l_tmp); + } + + //else printf("vtkDSPFilterGroup::GetCachedOutput DID NOT FIND time %d output in cache %s %s\n",a_whichTimestep, + // l_tmp->GetName(), this->FilterDefinitions[a_whichFilter]->OutputVariableName.c_str() ); + } + } + + return(NULL); +} + + +//---------------------------------------------------------------------------- +void vtkDSPFilterGroup::Copy( vtkDSPFilterGroup *other ) +{ + this->FilterDefinitions->m_vector = other->FilterDefinitions->m_vector; +} + + + +//---------------------------------------------------------------------------- +int vtkDSPFilterGroup::GetNumFilters( ) +{ + return this->FilterDefinitions->m_vector.size(); +} + + +//---------------------------------------------------------------------------- +vtkDSPFilterDefinition * vtkDSPFilterGroup::GetFilter(int a_whichFilter) +{ + return this->FilterDefinitions->m_vector[a_whichFilter]; +} + + +//---------------------------------------------------------------------------- +vtkFloatArray *vtkDSPFilterGroup::GetOutput( int a_whichFilter, int a_whichTimestep, int &a_instancesCalculated ) +{ + int i,j,k; + int l_numFilters = this->GetNumFilters(); + + + + if( (int)this->CachedOutputs->m_vector.size() < l_numFilters ) + { + //this shouldnt happen with saf. Should happen 1 time with exodus. + //printf("vtkDSPFilterGroup::GetOutput resizing cache vector\n"); + + int l_numNow=(int)this->CachedOutputs->m_vector.size(); + for(i=l_numNow;i l_cachedOutsForThisFilter; + l_cachedOutsForThisFilter.resize(0); + this->CachedOutputs->m_vector.push_back( l_cachedOutsForThisFilter ); + + vtkstd::vector l_cachedOutTimesForThisFilter; + l_cachedOutTimesForThisFilter.resize(0); + this->CachedOutputTimesteps->m_vector.push_back(l_cachedOutTimesForThisFilter); + } + } + + //is this output array already cached? + vtkFloatArray *l_tmp = this->GetCachedOutput( a_whichFilter, a_whichTimestep ); + if(l_tmp) + { + //printf("vtkDSPFilterGroup::GetOutput found time %d output in cache\n",a_whichTimestep); + return(l_tmp); + } + //else printf("vtkDSPFilterGroup::GetOutput DID NOT FIND time %d output in cache (%d cache slots)\n", + // a_whichTimestep,(int)this->CachedOutputs[a_whichFilter].size() ); + + + vtkFloatArray *l_output = vtkFloatArray::New(); + l_output->SetName( FilterDefinitions->m_vector[a_whichFilter]->GetOutputVariableName() ); + + int l_numNumerators = (int)FilterDefinitions->m_vector[a_whichFilter]->GetNumNumeratorWeights(); + int l_numForwardNumerators = (int)FilterDefinitions->m_vector[a_whichFilter]->GetNumForwardNumeratorWeights(); + if(!l_numNumerators && !l_numForwardNumerators) + { + printf("vtkDSPFilterGroup::GetOutput there are no numerator filter weights?\n"); + return(NULL); + } + int l_numDenominators = (int)FilterDefinitions->m_vector[a_whichFilter]->GetNumDenominatorWeights(); + + double l_a1 = 1.0; + if(l_numDenominators) + { + l_a1 = FilterDefinitions->m_vector[a_whichFilter]->GetDenominatorWeight(0); + } + + + //printf("vtkDSPFilterGroup::GetOutput numerators=%d forwardnums=%d dens=%d\n", + // l_numNumerators,l_numForwardNumerators,l_numDenominators); + + + //There should always be a valid input at the same time as an output + vtkFloatArray *l_firstInput = this->GetCachedInput(a_whichFilter,a_whichTimestep); + + if(!l_firstInput) + { + printf("\n vtkDSPFilterGroup::GetOutput error time %d has no input\n\n",a_whichTimestep); + return(NULL); + } + + const int l_numEntries = l_firstInput->GetNumberOfTuples(); + const int l_numComponents = l_firstInput->GetNumberOfComponents(); + + if(!l_numEntries || !l_numComponents) + { + printf("\n vtkDSPFilterGroup::GetOutput error time %d, l_numEntries=%d, l_numComponents=%d\n\n", + a_whichTimestep,l_numEntries,l_numComponents); + return(NULL); + } + + //printf("vtkDSPFilterGroup::GetOutput first input entries=%d comps=%d\n",l_numEntries,l_numComponents); + + + l_output->SetNumberOfComponents(l_numComponents); + l_output->SetNumberOfTuples(l_numEntries); + + for( i=0; iFilterDefinitions->m_vector[a_whichFilter]->GetNumeratorWeight(i)/l_a1; + + if(l_useThisTimestep < 0) l_useThisTimestep=0; //pre-time is considered infinite procession of input value at time 0 + + //printf("vtkDSPFilterGroup::GetOutput numerator weight %d is %e (incl a1=%e) time=%d\n",i,l_weight,l_a1,l_useThisTimestep); + + vtkFloatArray *l_input = this->GetCachedInput(a_whichFilter,l_useThisTimestep); + float *l_outPtr = (float *)l_output->GetVoidPointer(0); + + if(!i) + { + for(j=0;jGetVoidPointer(0); + for(j=0;jFilterDefinitions->m_vector[a_whichFilter]->GetDenominatorWeight(i)/l_a1; + + + if(a_whichTimestep-i < 0) break;//pre-time outputs are considered to be zero + + //printf("vtkDSPFilterGroup::GetOutput denominator weight %d is %e (incl a1=%e) time=%d\n",i,l_weight,l_a1,a_whichTimestep-i); + + vtkFloatArray *l_input = this->GetOutput( a_whichFilter, a_whichTimestep-i, a_instancesCalculated ); + + float *l_outPtr = (float *)l_output->GetVoidPointer(0); + + if(l_input) + { + float *l_inPtr = (float *)l_input->GetVoidPointer(0); + for(j=0;jFilterDefinitions->m_vector[a_whichFilter]->GetForwardNumeratorWeight(i)/l_a1; + + + float *l_outPtr = (float *)l_output->GetVoidPointer(0); + + vtkFloatArray *l_input = this->GetCachedInput(a_whichFilter,l_useThisTimestep); + + while(!l_input && l_useThisTimestep>=0) + { + //printf(" time %d failed......trying prev time.....\n",l_useThisTimestep); + + //Try the timestep before: all post-time inputs are considered to be the same as the last input + l_useThisTimestep--; + l_input = this->GetCachedInput(a_whichFilter,l_useThisTimestep); + } + + if(l_input) + { + + //printf("vtkDSPFilterGroup::GetOutput forward numerator weight %d is %e (incl a1=%e) time=%d\n",i,l_weight,l_a1,l_useThisTimestep); + + float *l_inPtr = (float *)l_input->GetVoidPointer(0); + for(j=0;jGetVoidPointer(0); + float *l_inPtr = (float *)l_firstInput->GetVoidPointer(0); + float l_maxDiff=0; + for(j=0;j l_maxDiff ) l_maxDiff = fabs(l_inPtr[0] - l_outPtr[0]); + + + printf("j=%d k=%d \t in=%f \t out=%f \t diff=%e maxdiff=%e diffperc=%f\n",j,k, + l_inPtr[0],l_outPtr[0],l_inPtr[0] - l_outPtr[0],l_maxDiff, + fabs(l_inPtr[0] - l_outPtr[0]) / fabs(l_inPtr[0]) ); + + } + l_inPtr++; + l_outPtr++; + } + } + } + +#endif + + + a_instancesCalculated++; + + //printf("****vtkDSPFilterGroup::GetOutput calculated filter=%d time=%d entries=%d comps=%d*** out cache was %d slots\n",a_whichFilter, + // a_whichTimestep,l_numEntries,l_numComponents, + // this->CachedOutputs[a_whichFilter].size() ); + + + this->CachedOutputs->m_vector[a_whichFilter].push_back(l_output); + this->CachedOutputTimesteps->m_vector[a_whichFilter].push_back(a_whichTimestep); + + + return(l_output); +} + diff --git a/Hybrid/vtkDSPFilterGroup.h b/Hybrid/vtkDSPFilterGroup.h new file mode 100644 index 0000000..81dc6c5 --- /dev/null +++ b/Hybrid/vtkDSPFilterGroup.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDSPFilterGroup.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#ifndef __vtkDSPFilterGroup_h +#define __vtkDSPFilterGroup_h + +#include "vtkObject.h" + +class vtkDSPFilterGroupVectorIntSTLCloak; +class vtkDSPFilterGroupVectorVectorIntSTLCloak; +class vtkDSPFilterGroupVectorArraySTLCloak; +class vtkDSPFilterGroupVectorVectorArraySTLCloak; +class vtkDSPFilterGroupVectorStringSTLCloak; +class vtkDSPFilterGroupVectorDefinitionSTLCloak; +class vtkFloatArray; +class vtkDSPFilterDefinition; + +class VTK_HYBRID_EXPORT vtkDSPFilterGroup : public vtkObject +{ +public: + static vtkDSPFilterGroup *New(); + vtkTypeRevisionMacro(vtkDSPFilterGroup,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + + void AddFilter(vtkDSPFilterDefinition *filter); + void RemoveFilter(char *a_outputVariableName); + + bool IsThisInputVariableInstanceNeeded( const char *a_name, int a_timestep, int a_outputTimestep ); + bool IsThisInputVariableInstanceCached( const char *a_name, int a_timestep ); + void AddInputVariableInstance( const char *a_name, int a_timestep, vtkFloatArray *a_data ); + + vtkFloatArray *GetOutput( int a_whichFilter, int a_whichTimestep, int &a_instancesCalculated ); + + vtkFloatArray *GetCachedInput( int a_whichFilter, int a_whichTimestep ); + vtkFloatArray *GetCachedOutput( int a_whichFilter, int a_whichTimestep ); + + const char *GetInputVariableName(int a_whichFilter); + + int GetNumFilters(); + + void Copy( vtkDSPFilterGroup *other ); + + vtkDSPFilterDefinition *GetFilter(int a_whichFilter); + + vtkDSPFilterGroupVectorDefinitionSTLCloak * /*vtkstd::vector*/ FilterDefinitions; + +protected: + vtkDSPFilterGroup(); + ~vtkDSPFilterGroup(); + + + vtkDSPFilterGroupVectorArraySTLCloak * /*vtkstd::vector*/ CachedInputs; + vtkDSPFilterGroupVectorStringSTLCloak * /*vtkstd::vector*/ CachedInputNames; + vtkDSPFilterGroupVectorIntSTLCloak * /*vtkstd::vector*/ CachedInputTimesteps; + + vtkDSPFilterGroupVectorVectorArraySTLCloak * /*vtkstd::vector< vtkstd::vector >*/ CachedOutputs; + vtkDSPFilterGroupVectorVectorIntSTLCloak * /*vtkstd::vector< vtkstd::vector >*/ CachedOutputTimesteps; + +private: + vtkDSPFilterGroup(const vtkDSPFilterGroup&); // Not implemented + void operator=(const vtkDSPFilterGroup&); // Not implemented +}; + +#endif diff --git a/Hybrid/vtkDepthSortPolyData.cxx b/Hybrid/vtkDepthSortPolyData.cxx new file mode 100644 index 0000000..f07e843 --- /dev/null +++ b/Hybrid/vtkDepthSortPolyData.cxx @@ -0,0 +1,402 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDepthSortPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDepthSortPolyData.h" + +#include "vtkCamera.h" +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkProp3D.h" +#include "vtkTransform.h" +#include "vtkUnsignedIntArray.h" + +vtkCxxRevisionMacro(vtkDepthSortPolyData, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkDepthSortPolyData); + +vtkCxxSetObjectMacro(vtkDepthSortPolyData,Camera,vtkCamera); + +vtkDepthSortPolyData::vtkDepthSortPolyData() +{ + this->Camera = NULL; + this->Prop3D = NULL; + this->Direction = VTK_DIRECTION_BACK_TO_FRONT; + this->DepthSortMode = VTK_SORT_FIRST_POINT; + this->Vector[0] = this->Vector[1] = 0.0; + this->Vector[2] = 0.0; + this->Origin[0] = this->Origin[1] = this->Origin[2] = 0.0; + this->Transform = vtkTransform::New(); + this->SortScalars = 0; +} + +vtkDepthSortPolyData::~vtkDepthSortPolyData() +{ + this->Transform->Delete(); + + if ( this->Camera ) + { + this->Camera->Delete(); + } + + //Note: vtkProp3D is not deleted to avoid reference count cycle +} + +// Don't reference count to avoid nasty cycle +void vtkDepthSortPolyData::SetProp3D(vtkProp3D *prop3d) +{ + if ( this->Prop3D != prop3d ) + { + this->Prop3D = prop3d; + this->Modified(); + } +} + +vtkProp3D *vtkDepthSortPolyData::GetProp3D() +{ + return this->Prop3D; +} + +typedef struct _vtkSortValues { + double z; + vtkIdType cellId; +} vtkSortValues; + +extern "C" +{ + int vtkCompareBackToFront(const void *val1, const void *val2) + { + if (((vtkSortValues *)val1)->z > ((vtkSortValues *)val2)->z) + { + return (-1); + } + else if (((vtkSortValues *)val1)->z < ((vtkSortValues *)val2)->z) + { + return (1); + } + else + { + return (0); + } + } +} + +extern "C" +{ + int vtkCompareFrontToBack(const void *val1, const void *val2) + { + if (((vtkSortValues *)val1)->z < ((vtkSortValues *)val2)->z) + { + return (-1); + } + else if (((vtkSortValues *)val1)->z > ((vtkSortValues *)val2)->z) + { + return (1); + } + else + { + return (0); + } + } +} + +int vtkDepthSortPolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkSortValues *depth; + vtkIdType cellId, id; + vtkGenericCell *cell; + vtkIdType numCells=input->GetNumberOfCells(); + vtkCellData *inCD=input->GetCellData(); + vtkCellData *outCD=output->GetCellData(); + vtkUnsignedIntArray *sortScalars = NULL; + unsigned int *scalars = NULL; + double x[3]; + double p[3], *bounds, *w = NULL, xf[3]; + double vector[3]; + double origin[3]; + int type, npts, subId; + vtkIdType newId; + vtkIdType *pts; + + // Initialize + // + vtkDebugMacro(<<"Sorting polygonal data"); + + // Compute the sort vector + if ( this->Direction == VTK_DIRECTION_SPECIFIED_VECTOR ) + { + for (int i=0; i<3; i++) + { + vector[i] = this->Vector[i]; + origin[i] = this->Origin[i]; + } + } + else //compute view vector + { + if ( this->Camera == NULL) + { + vtkErrorMacro(<<"Need a camera to sort"); + return 0; + } + + this->ComputeProjectionVector(vector, origin); + } + cell=vtkGenericCell::New(); + + if ( this->DepthSortMode == VTK_SORT_PARAMETRIC_CENTER ) + { + w = new double [input->GetMaxCellSize()]; + } + + // Create temporary input + vtkPolyData *tmpInput = vtkPolyData::New(); + tmpInput->CopyStructure(input); + + // Compute the depth value + depth = new vtkSortValues [numCells]; + for ( cellId=0; cellId < numCells; cellId++ ) + { + tmpInput->GetCell(cellId, cell); + if ( this->DepthSortMode == VTK_SORT_FIRST_POINT ) + { + cell->Points->GetPoint(0,x); + } + else if ( this->DepthSortMode == VTK_SORT_BOUNDS_CENTER ) + { + bounds = cell->GetBounds(); + x[0] = (bounds[0]+bounds[1])/2.0; + x[1] = (bounds[2]+bounds[3])/2.0; + x[2] = (bounds[4]+bounds[5])/2.0; + } + else // VTK_SORT_PARAMETRIC_CENTER ) + { + subId = cell->GetParametricCenter(p); + cell->EvaluateLocation(subId, p, xf, w); + x[0] = xf[0]; + x[1] = xf[1]; + x[2] = xf[2]; + } + x[0] -= origin[0]; + x[1] -= origin[1]; + x[2] -= origin[2]; + depth[cellId].z = vtkMath::Dot(x,vector); + depth[cellId].cellId = cellId; + } + if ( this->DepthSortMode == VTK_SORT_PARAMETRIC_CENTER ) + { + delete [] w; + } + this->UpdateProgress(0.20); + + // Sort the depths + if ( this->Direction == VTK_DIRECTION_FRONT_TO_BACK ) + { + qsort((void *)depth, numCells, sizeof(vtkSortValues), + vtkCompareFrontToBack); + } + else + { + qsort((void *)depth, numCells, sizeof(vtkSortValues), + vtkCompareBackToFront); + } + this->UpdateProgress(0.60); + + // Generate sorted output + if ( this->SortScalars ) + { + sortScalars = vtkUnsignedIntArray::New(); + sortScalars->SetNumberOfTuples(numCells); + scalars = sortScalars->GetPointer(0); + } + outCD->CopyAllocate(inCD); + output->Allocate(tmpInput,numCells); + for ( cellId=0; cellId < numCells; cellId++ ) + { + id = depth[cellId].cellId; + tmpInput->GetCell(id, cell); + type = cell->GetCellType(); + npts = cell->GetNumberOfPoints(); + pts = cell->GetPointIds()->GetPointer(0); + + // copy cell data + newId = output->InsertNextCell(type, npts, pts); + outCD->CopyData(inCD, id, newId); + if ( this->SortScalars ) + { + scalars[newId] = newId; + } + } + this->UpdateProgress(0.90); + + // Points are left alone + output->SetPoints(input->GetPoints()); + output->GetPointData()->PassData(input->GetPointData()); + if ( this->SortScalars ) + { + int idx = output->GetCellData()->AddArray(sortScalars); + output->GetCellData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS); + sortScalars->Delete(); + } + + // Clean up and get out + tmpInput->Delete(); + delete [] depth; + cell->Delete(); + output->Squeeze(); + + return 1; +} + +void vtkDepthSortPolyData::ComputeProjectionVector(double vector[3], + double origin[3]) +{ + double *focalPoint = this->Camera->GetFocalPoint(); + double *position = this->Camera->GetPosition(); + + // If a camera is present, use it + if ( !this->Prop3D ) + { + for(int i=0; i<3; i++) + { + vector[i] = focalPoint[i] - position[i]; + origin[i] = position[i]; + } + } + + else //Otherwise, use Prop3D + { + double focalPt[4], pos[4]; + int i; + + this->Transform->SetMatrix(this->Prop3D->GetMatrix()); + this->Transform->Push(); + this->Transform->Inverse(); + + for(i=0; i<4; i++) + { + focalPt[i] = focalPoint[i]; + pos[i] = position[i]; + } + + this->Transform->TransformPoint(focalPt,focalPt); + this->Transform->TransformPoint(pos,pos); + + for (i=0; i<3; i++) + { + vector[i] = focalPt[i] - pos[i]; + origin[i] = pos[i]; + } + this->Transform->Pop(); + } +} + +unsigned long int vtkDepthSortPolyData::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + + if ( this->Direction != VTK_DIRECTION_SPECIFIED_VECTOR ) + { + unsigned long time; + if ( this->Camera != NULL ) + { + time = this->Camera->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->Prop3D != NULL ) + { + time = this->Prop3D->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + } + + return mTime; +} + +void vtkDepthSortPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Camera ) + { + os << indent << "Camera:\n"; + this->Camera->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Camera: (none)\n"; + } + + if ( this->Prop3D ) + { + os << indent << "Prop3D:\n"; + this->Prop3D->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Prop3D: (none)\n"; + } + + os << indent << "Direction: "; + if ( this->Direction == VTK_DIRECTION_BACK_TO_FRONT ) + { + os << "Back To Front" << endl; + } + else if ( this->Direction == VTK_DIRECTION_FRONT_TO_BACK ) + { + os << "Front To Back"; + } + else + { + os << "Specified Direction: "; + os << "(" << this->Vector[0] << ", " << this->Vector[1] << ", " + << this->Vector[2] << ")\n"; + os << "Specified Origin: "; + os << "(" << this->Origin[0] << ", " << this->Origin[1] << ", " + << this->Origin[2] << ")\n"; + } + + os << indent << "Depth Sort Mode: "; + if ( this->DepthSortMode == VTK_SORT_FIRST_POINT ) + { + os << "First Point" << endl; + } + else if ( this->DepthSortMode == VTK_SORT_BOUNDS_CENTER ) + { + os << "Bounding Box Center" << endl; + } + else + { + os << "Paramteric Center" << endl; + } + + os << indent << "Sort Scalars: " << (this->SortScalars ? "On\n" : "Off\n"); +} diff --git a/Hybrid/vtkDepthSortPolyData.h b/Hybrid/vtkDepthSortPolyData.h new file mode 100644 index 0000000..62ae986 --- /dev/null +++ b/Hybrid/vtkDepthSortPolyData.h @@ -0,0 +1,146 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDepthSortPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDepthSortPolyData - sort poly data along camera view direction +// .SECTION Description +// vtkDepthSortPolyData rearranges the order of cells so that certain +// rendering operations (e.g., transparency or Painter's algorithms) +// generate correct results. To use this filter you must specify the +// direction vector along which to sort the cells. You can do this by +// specifying a camera and/or prop to define a view direction; or +// explicitly set a view direction. + +// .SECTION Caveats +// The sort operation will not work well for long, thin primitives, or cells +// that intersect, overlap, or interpenetrate each other. + +#ifndef __vtkDepthSortPolyData_h +#define __vtkDepthSortPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_DIRECTION_BACK_TO_FRONT 0 +#define VTK_DIRECTION_FRONT_TO_BACK 1 +#define VTK_DIRECTION_SPECIFIED_VECTOR 2 + +#define VTK_SORT_FIRST_POINT 0 +#define VTK_SORT_BOUNDS_CENTER 1 +#define VTK_SORT_PARAMETRIC_CENTER 2 + +class vtkCamera; +class vtkProp3D; +class vtkTransform; + +class VTK_HYBRID_EXPORT vtkDepthSortPolyData : public vtkPolyDataAlgorithm +{ +public: + // Description: + // Instantiate object. + static vtkDepthSortPolyData *New(); + + vtkTypeRevisionMacro(vtkDepthSortPolyData,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the sort method for the polygonal primitives. By default, the + // poly data is sorted from back to front. + vtkSetMacro(Direction,int); + vtkGetMacro(Direction,int); + void SetDirectionToFrontToBack() + {this->SetDirection(VTK_DIRECTION_FRONT_TO_BACK);} + void SetDirectionToBackToFront() + {this->SetDirection(VTK_DIRECTION_BACK_TO_FRONT);} + void SetDirectionToSpecifiedVector() + {this->SetDirection(VTK_DIRECTION_SPECIFIED_VECTOR);} + + // Description: + // Specify the point to use when sorting. The fastest is to just + // take the first cell point. Other options are to take the bounding + // box center or the parametric center of the cell. By default, the + // first cell point is used. + vtkSetMacro(DepthSortMode,int); + vtkGetMacro(DepthSortMode,int); + void SetDepthSortModeToFirstPoint() + {this->SetDepthSortMode(VTK_SORT_FIRST_POINT);} + void SetDepthSortModeToBoundsCenter() + {this->SetDepthSortMode(VTK_SORT_BOUNDS_CENTER);} + void SetDepthSortModeToParametricCenter() + {this->SetDepthSortMode(VTK_SORT_PARAMETRIC_CENTER);} + + // Description: + // Specify a camera that is used to define a view direction along which + // the cells are sorted. This ivar only has effect if the direction is set + // to front-to-back or back-to-front, and a camera is specified. + virtual void SetCamera(vtkCamera*); + vtkGetObjectMacro(Camera,vtkCamera); + + // Description: + // Specify a transformation matrix (via the vtkProp3D::GetMatrix() method) + // that is used to include the effects of transformation. This ivar only + // has effect if the direction is set to front-to-back or back-to-front, + // and a camera is specified. Specifying the vtkProp3D is optional. + void SetProp3D(vtkProp3D *); + vtkProp3D *GetProp3D(); + + // Description: + // Set/Get the sort direction. This ivar only has effect if the sort + // direction is set to SetDirectionToSpecifiedVector(). The sort occurs + // in the direction of the vector. + vtkSetVector3Macro(Vector,double); + vtkGetVectorMacro(Vector,double,3); + + // Description: + // Set/Get the sort origin. This ivar only has effect if the sort + // direction is set to SetDirectionToSpecifiedVector(). The sort occurs + // in the direction of the vector, with this point specifying the + // origin. + vtkSetVector3Macro(Origin,double); + vtkGetVectorMacro(Origin,double,3); + + // Description: + // Set/Get a flag that controls the generation of scalar values + // corresponding to the sort order. If enabled, the output of this + // filter will include scalar values that range from 0 to (ncells-1), + // where 0 is closest to the sort direction. + vtkSetMacro(SortScalars, int); + vtkGetMacro(SortScalars, int); + vtkBooleanMacro(SortScalars, int); + + // Description: + // Return MTime also considering the dependent objects: the camera + // and/or the prop3D. + unsigned long GetMTime(); + +protected: + vtkDepthSortPolyData(); + ~vtkDepthSortPolyData(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void ComputeProjectionVector(double vector[3], double origin[3]); + + int Direction; + int DepthSortMode; + vtkCamera *Camera; + vtkProp3D *Prop3D; + vtkTransform *Transform; + double Vector[3]; + double Origin[3]; + int SortScalars; + +private: + vtkDepthSortPolyData(const vtkDepthSortPolyData&); // Not implemented. + void operator=(const vtkDepthSortPolyData&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkEarthSource.cxx b/Hybrid/vtkEarthSource.cxx new file mode 100644 index 0000000..56bd3f6 --- /dev/null +++ b/Hybrid/vtkEarthSource.cxx @@ -0,0 +1,6948 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEarthSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEarthSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +#include + +vtkCxxRevisionMacro(vtkEarthSource, "$Revision: 1.27 $"); +vtkStandardNewMacro(vtkEarthSource); + +// Description: +// Construct an Earth with radius = 1.0 and OnRatio set at 10. The outlines are drawn +// in wireframe as default. +vtkEarthSource::vtkEarthSource() +{ + this->Radius = 1.0; + this->OnRatio = 10; + this->Outline = 1; + + this->SetNumberOfInputPorts(0); +} + +void vtkEarthSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "OnRatio: " << this->OnRatio << "\n"; + os << indent << "Outline: " << (this->Outline ? "On\n" : "Off\n"); +} + +// vtkEarthData[] is a big array of short (16-bit) ints, as follows: +// the vtkEarthData[] info is a sequence of closed curves + +// the first value in a curve is the number of points in the curve the second +// value in a curve indicates land/water (1 or -1, respectively) this is +// followed by an [x,y,z] triple that indicates a point on the unit sphere +// (each of x, y, and z has been scaled by 30000), where the x axis points +// "to the right" (towards 0 N 90 E), the y axis points "up" (towards the +// north pole), and the z axis points "out of the screen" (towards 0 N 0 +// E). this is the starting point of the curve. + +// this is followed by (one less than the number of points in the curve) +// triples [dx,dy,dz]; the [x,y,z] triple for each successive point in the +// curve is obtained by adding [dx,dy,dz] onto the previous [x,y,z] values. + +// the curves are [must be!] non-self-intersecting and traced in a +// counter-clockwise direction +// +// the curves are sampled at a (roughly) 20 mile resolution. + +// Source: on the Internet somewhere, originator unknown. +// Someone obviously put work into this. Wish the author was known +// to give proper credit... + +short vtkEarthData[] = { +/* 0 */ +3903, 1, 13663, 15523, 21733, + -138, 74, 34, 69, 29, -64, -38, 19, 10, -93, 24, 41, + -123, 2, 74, -139, 23, 68, -93, -54, 94, -46, 17, 16, + 33, 33, -44, -145, -37, 113, -59, -82, 92, -117, -44, 99, + -83, -79, 101, -98, -59, 97, -129, 1, 70, -132, 62, 30, + -136, 30, 54, -146, 22, 63, -120, 37, 38, -137, 40, 44, + -132, 50, 34, -137, 27, 51, -140, 23, 54, -141, 32, 48, + -133, 4, 62, -123, -34, 82, -124, 44, 28, -95, 124, -40, + -134, 50, 28, -136, -5, 65, -143, 24, 48, -135, 51, 25, + -151, 13, 57, -116, 80, -5, -70, 114, -49, -151, 52, 28, + -141, 44, 27, -137, 28, 36, -151, 0, 61, -115, -55, 84, + -137, -19, 66, -113, -59, 83, -106, -67, 85, -83, -88, 91, + -56, -106, 92, 4, -127, 82, 57, -127, 62, 81, -117, 47, + 4, -126, 79, -56, -109, 89, -81, -94, 88, -111, -65, 80, + -137, -19, 60, -140, 50, 16, -129, 77, -4, -125, 84, -11, + -140, 59, 9, -141, 51, 13, -141, 46, 16, -146, 36, 22, + -145, 24, 28, -147, 4, 41, -146, 30, 23, -136, 66, -3, + -101, 105, -39, -69, 120, -58, -46, 125, -69, -119, 79, -19, + -150, 23, 25, -143, 45, 7, -135, 65, -9, -147, 32, 16, + -145, 29, 16, -142, 15, 24, -138, -36, 55, -149, 6, 29, + -142, 46, 1, -154, 71, -14, -125, 38, 0, -122, 43, -4, + -131, 126, -59, -138, 25, 9, -148, 44, -2, -111, 93, -43, + -32, 122, -79, 97, 86, -77, 111, 74, -72, 87, 91, -80, + 55, 110, -89, 20, 109, -83, -52, 128, -82, -122, 81, -36, + -105, 100, -54, -10, 122, -89, 103, 79, -78, 66, 104, -92, + -18, 101, -74, -145, -63, 76, -125, -11, 32, -59, 130, -89, + -132, 44, -11, -122, 31, -2, -140, -37, 51, -116, -63, 67, + -123, -52, 59, -148, -9, 28, -165, -12, 33, -130, 47, -18, + -137, 6, 13, -141, -43, 50, -141, 43, -15, -120, -13, 23, + -120, -62, 60, -141, -30, 36, -134, -48, 49, -126, 58, -32, + -147, 39, -17, -152, 5, 8, -152, -1, 12, -138, -34, 35, + -152, -18, 23, -141, -6, 11, -140, -63, 54, -146, -2, 7, + -148, -18, 19, -152, -10, 12, -146, -17, 16, -134, -51, 40, + -137, -51, 39, -122, -67, 50, -94, -101, 74, -153, -3, 1, + -142, -45, 31, -141, -36, 24, -96, -91, 63, -113, -76, 51, + -131, -64, 42, -148, -12, 3, -148, 11, -14, -140, 28, -26, + -91, 63, -49, -167, -51, 26, -149, 14, -19, -148, -15, 0, + -147, -15, 0, -141, 43, -42, -112, 79, -66, -79, 97, -77, + -61, 80, -64, -177, -45, 16, -75, -108, 69, -60, -116, 77, + -58, -117, 76, -67, -115, 73, -74, -111, 69, -82, -109, 65, + -94, -100, 58, -130, -71, 31, -136, -61, 24, -140, -54, 17, + -142, -49, 13, -136, -61, 21, -108, -86, 40, -109, -96, 47, + -114, -89, 40, -67, -108, 58, -32, -126, 76, -92, -106, 52, + -95, -106, 50, -65, -120, 64, -22, -130, 76, -16, -131, 77, + 18, -106, 67, 52, -115, 78, -47, -130, 68, -87, -111, 50, + -97, -107, 45, -92, -108, 45, -107, -102, 39, -124, -81, 22, + -137, -67, 11, -117, -90, 27, -110, -101, 34, -137, -63, 6, + -142, -53, -1, -148, -33, -13, -149, -22, -22, -131, -55, 1, + -102, -108, 34, -70, -128, 52, -73, -122, 47, -62, -129, 53, + -110, -97, 23, -136, -69, 2, -130, -68, 2, -97, -100, 27, + -63, -128, 47, -72, -127, 45, -68, -126, 43, -24, -137, 61, + -48, -134, 51, -105, -101, 20, -115, -97, 14, -113, -102, 17, + -124, -85, 4, -45, -85, 27, -86, -166, 50, -81, -132, 36, + -63, -120, 34, -64, -131, 39, -91, -126, 28, -120, -81, -2, + -82, -125, 28, -39, -135, 45, -41, -142, 46, -36, -139, 45, + 11, -63, 29, 88, 49, 7, 55, -128, 68, 94, -66, 54, + 72, -129, 71, 25, -129, 57, -35, -131, 40, -72, -140, 30, + -12, -75, 25, 57, -175, 80, 29, -137, 57, 23, -139, 56, + 5, -143, 51, -9, -144, 46, -25, -144, 40, -51, -140, 32, + -67, -134, 24, -71, -130, 20, -54, -138, 27, -39, -142, 32, + -15, -146, 40, -39, -140, 30, -86, -127, 11, -87, -123, 9, + -101, -113, 1, -125, -80, -16, -35, -55, 4, 131, -79, 62, + 79, -115, 55, 55, -132, 52, 48, -37, 24, 80, 37, 14, + -24, -130, 27, 5, -132, 35, 86, -97, 49, 143, 40, 32, + 151, 15, 39, 139, 11, 37, 23, -12, 9, -165, -14, -43, + -150, -15, -39, -124, -71, -18, -137, 66, -57, -95, -40, -19, + 4, -145, 37, -10, -150, 33, 68, -38, 29, 109, -29, 39, + 169, 19, 45, 140, -28, 46, 108, 53, 18, 32, 16, 5, + -131, -86, -16, -144, 20, -46, -145, -14, -39, -139, 0, -41, + -63, -98, 4, 132, -84, 59, 105, -1, 30, 30, -154, 43, + 141, 35, 33, 23, -19, 11, -4, -74, 15, 145, 44, 31, + 138, 22, 33, 85, -33, 31, -198, -69, -40, 68, -43, 28, + 74, -18, 24, -111, -109, -7, 57, -133, 43, 67, -24, 23, + 37, -29, 16, 51, -69, 28, 93, 5, 23, 42, -89, 29, + 50, 7, 12, -20, -138, 21, 87, -128, 47, 146, -64, 49, + 100, -103, 43, 114, -63, 40, 40, -145, 35, 105, -106, 43, + 55, -111, 32, 51, -127, 32, 3, -125, 20, 49, -47, 19, + -112, -70, -15, 99, -97, 37, 66, -128, 34, 69, -98, 30, + 130, -47, 35, 64, -103, 28, 124, -117, 43, 137, -54, 36, + 123, -81, 35, 103, -103, 34, 110, -85, 32, 132, -68, 34, + 80, -100, 27, 164, -73, 38, 115, -81, 30, 105, -101, 29, + 109, -105, 30, 109, -98, 28, 107, -112, 28, 118, -87, 27, + 130, -70, 27, 131, -69, 26, 132, -73, 26, 140, -50, 24, + 136, -62, 24, 144, -33, 22, 137, 60, 13, 138, 61, 12, + 135, 58, 12, 141, 51, 12, 143, 53, 11, 140, 57, 10, + 154, 36, 13, 144, 15, 12, 80, 34, 4, 221, -11, 21, + 150, 21, 10, 153, 12, 10, 31, 26, 0, -186, -21, -12, + -70, 16, -7, 216, 24, 15, 145, 2, 10, 70, -27, 7, + 241, -37, 18, 88, 41, 1, 74, -80, 12, 215, -66, 16, + 148, -42, 10, 139, -66, 11, 145, 61, 0, 127, 75, -3, + 152, 42, 0, 142, 47, -2, 142, 46, -2, 131, 71, -5, + 138, 62, -5, 135, 65, -7, 139, 51, -5, 127, 55, -7, + -86, 84, -8, 179, -137, 12, 126, 67, -9, 101, 104, -12, + 145, 45, -9, 147, 33, -7, 150, 23, -8, 151, 18, -8, + 151, 15, -8, 152, 14, -9, 152, 2, -8, 118, 66, -15, + 96, -12, -4, 194, -39, -9, 150, -20, -8, 138, -57, -5, + 119, -93, 1, 116, -123, 3, 104, -60, -4, 93, -111, 3, + 72, -52, -2, -60, -116, 16, 22, -115, 9, 66, -152, 6, + 111, -118, -1, 127, -59, -9, 123, 10, -14, 172, 14, -20, + 81, 57, -14, 16, 106, -11, 97, -87, -4, 83, 20, -12, + 13, 34, -5, 114, -41, -11, 107, 4, -14, 144, -25, -18, + 172, 14, -25, 57, 94, -16, 10, 60, -7, 117, -110, -8, + 125, -37, -16, 93, -200, 1, 128, -95, -14, 128, -3, -20, + 103, -40, -15, 18, -169, 8, 77, -131, -5, 50, -132, -1, + -31, -147, 13, -24, -149, 11, -20, -146, 10, 0, -155, 5, + -58, -164, 16, -80, -104, 16, -38, -144, 10, 131, -77, -21, + -34, -206, 9, -55, -13, 9, -78, -47, 14, 106, -119, -17, + 145, -47, -25, -5, -38, 1, -148, 11, 26, -107, 24, 17, + -17, -219, 3, -58, -133, 9, -72, -120, 10, -86, -22, 13, + -68, 14, 11, 81, -166, -15, 78, -129, -15, 131, -79, -23, + 25, -86, -7, -143, 111, 26, -24, 16, 5, 89, -154, -19, + 76, -104, -16, 30, -67, -7, 110, -201, -26, 122, -55, -23, + 48, -37, -10, -95, -2, 16, 116, -113, -26, 116, -93, -25, + 108, -103, -25, 91, -120, -24, 103, -106, -26, 89, -118, -25, + 104, -105, -28, 95, -110, -27, 110, -104, -30, 78, -131, -27, + 57, -122, -23, 82, -96, -26, 50, -176, -27, -13, -142, -11, + 102, -132, -36, 104, -28, -26, 127, 73, -21, 93, -26, -24, + -201, -68, 38, -145, -55, 26, 65, -176, -34, 77, -125, -32, + 81, -121, -33, 28, -149, -25, 49, -142, -31, 54, -139, -31, + 63, -136, -34, 66, -131, -35, 13, -141, -25, -66, -116, -2, + -103, -102, 7, 18, -151, -29, 41, -143, -34, 36, -135, -32, + 49, -132, -35, 63, -140, -41, 80, -124, -43, 39, -130, -35, + 20, -148, -34, -29, -145, -23, -11, -149, -29, -32, -147, -24, + -72, -145, -14, -85, -112, -5, -122, -66, 14, -122, -104, 4, + -63, -130, -16, -105, -105, -2, -74, -124, -13, -34, -157, -32, + -69, -133, -19, -16, -143, -33, -36, -147, -32, -55, -134, -24, + -50, -135, -26, -44, -152, -34, -93, -118, -14, -41, -114, -24, + 0, -144, -43, 2, -144, -43, -19, -144, -41, -27, -148, -40, + -22, -140, -40, -12, -144, -44, 14, -143, -49, 61, -126, -55, + 56, -127, -56, 98, -104, -56, 78, -117, -58, 64, -122, -58, + 51, -130, -58, 58, -125, -59, 57, -126, -59, 67, -119, -60, + 36, -136, -61, 39, -134, -61, 51, -126, -61, 67, -120, -64, + 69, -117, -64, 50, -128, -65, 77, -111, -65, 74, -113, -66, + 50, -126, -66, 16, -135, -62, -51, -115, -38, -7, -166, -71, + -8, -132, -57, -15, -140, -60, -13, -136, -59, 33, -133, -71, + 44, -122, -69, 31, -129, -70, -17, -137, -62, 0, -135, -66, + -2, -133, -66, 18, -132, -71, 21, -122, -68, 21, -125, -70, + 12, -128, -71, 19, -130, -74, 41, -121, -76, 52, -119, -79, + 58, -116, -80, 84, -100, -79, 88, -94, -78, 98, -93, -81, + 61, -104, -78, 59, -112, -82, 37, -121, -82, 30, -125, -83, + 16, -127, -81, 24, -125, -83, 31, -121, -83, 45, -116, -86, + 41, -117, -86, 51, -113, -88, 57, -108, -87, 61, -107, -90, + 21, -123, -87, -4, -129, -84, -31, -128, -75, -113, -90, -23, + -98, -49, -2, 35, -95, -76, 20, -75, -58, 78, -152, -131, + 6, -123, -89, -60, -113, -60, 47, -37, -42, 134, 23, -29, + 68, -84, -84, 108, -67, -86, 80, -84, -90, 125, -33, -69, + 120, 35, -18, 134, 79, 9, 151, 38, -29, 129, 19, -35, + 138, -2, -56, 150, 15, -49, 131, 79, 6, 134, 50, -18, + 145, 18, -47, 117, -26, -69, 139, 5, -55, 142, 26, -43, + 131, -22, -74, 122, -33, -80, 139, -17, -76, 122, 77, 1, + 139, -10, -74, 110, 29, -30, 112, 94, 16, 135, -5, -70, + 135, 4, -64, 138, 53, -30, 135, 59, -24, 131, 75, -13, + 131, 75, -12, 129, 77, -12, 124, 90, -1, 128, 79, -11, + 122, 91, -1, 118, 93, 2, 113, 99, 8, 113, 99, 7, + 126, 83, -13, 126, 80, -15, 115, 101, 4, 108, 105, 10, + 101, 112, 18, 98, 113, 19, 95, 118, 24, 103, 110, 12, + 87, 122, 29, 106, 111, 9, 112, 98, -4, 119, 92, -13, + 122, 70, -31, 127, 93, -20, 85, 115, 20, 83, 127, 29, + 55, 132, 47, 65, 130, 40, 76, 128, 29, 70, 131, 35, + 48, 133, 49, 45, 135, 51, -9, 92, 60, -74, 102, 107, + 104, 114, -1, 117, 120, -7, 131, 81, -40, 122, 53, -51, + 130, 55, -55, 130, 46, -62, 131, 49, -61, 130, 49, -63, + 128, 60, -55, 110, 95, -25, 103, 114, -9, 70, 138, 25, + -30, 65, 57, 76, 199, 53, 59, 134, 28, 32, 109, 34, + 26, 155, 61, 42, 142, 42, -38, 14, 34, -44, -59, 2, + 31, 186, 71, 10, 140, 62, -18, 132, 76, 3, 115, 53, + 15, 152, 60, -54, 105, 86, -37, 109, 76, 49, 147, 32, + 20, 140, 48, 3, 59, 24, 117, -35, -97, 114, 87, -42, + 108, 102, -32, 96, 108, -23, 120, 104, -41, 123, 58, -66, + 95, 68, -40, 108, 117, -32, 117, 122, -36, 72, 132, -1, + 115, 90, -50, 109, 78, -51, 120, 74, -63, 119, 65, -67, + 99, 59, -54, 147, 55, -94, 106, 38, -70, 135, 57, -87, + 102, 89, -48, 115, 73, -66, 102, 97, -48, 86, 104, -32, + 85, 115, -28, 98, 117, -40, 99, 115, -41, 60, 144, 0, + 42, 99, 0, 42, 96, -3, 30, 174, 35, -10, 83, 36, + -10, 101, 43, 18, 182, 45, 13, 138, 32, 22, 135, 24, + 6, 161, 44, 47, 139, 1, -9, 159, 54, 25, 141, 20, + 4, 141, 35, 10, 153, 33, 10, 126, 25, 63, 149, -15, + 25, 140, 13, -29, 151, 62, -84, 79, 90, -85, 64, 86, + -73, 102, 85, -2, 156, 37, -21, 134, 47, -19, 149, 47, + -19, 119, 39, -35, 164, 61, 14, 142, 16, 54, 146, -17, + -35, 114, 49, 11, 161, 18, 59, 120, -28, 44, 119, -17, + -78, 96, 80, -61, 118, 67, -77, 87, 75, -36, 161, 52, + 23, 148, 1, 52, 143, -24, 50, 144, -23, 41, 151, -15, + 49, 140, -25, 92, 92, -66, 62, 139, -37, 37, 138, -18, + 72, 152, -47, 26, 97, -13, 71, 122, -50, 52, 152, -33, + 18, 145, -6, 101, 86, -81, 107, 41, -89, 71, 113, -55, + 34, 134, -23, 127, 38, -109, 89, 107, -74, 72, 119, -59, + 65, 140, -53, 52, 131, -44, 71, 99, -62, 80, 121, -71, + 70, 106, -63, 82, 114, -75, 76, 109, -70, 75, 111, -70, + 75, 110, -71, 75, 109, -74, 81, 101, -79, 85, 91, -84, + 78, 102, -78, 80, 99, -82, 85, 91, -87, 87, 85, -89, + 91, 74, -94, 92, 69, -97, 90, 77, -95, 89, 76, -96, + 78, 96, -87, 69, 108, -80, 73, 103, -84, 71, 105, -82, + 66, 112, -80, 64, 112, -79, 66, 109, -81, 64, 110, -82, + 61, 115, -78, 62, 112, -81, 49, 125, -69, 40, 132, -62, + 51, 123, -73, 53, 119, -77, 47, 126, -71, 43, 128, -69, + 38, 132, -64, 12, 144, -39, 20, 142, -48, 32, 134, -61, + 42, 124, -73, 44, 123, -75, 31, 137, -65, 11, 140, -43, + 58, 113, -94, 38, 127, -74, 30, 129, -66, 24, 138, -63, + 42, 119, -80, 33, 131, -74, -10, 152, -29, -2, 147, -38, + -10, 152, -31, 69, 73, -106, 24, 26, -38, -53, 40, 54, + -13, 145, -27, -24, 153, -18, -28, 142, -10, 15, 138, -62, + -35, 100, 10, -105, 49, 113, -83, -34, 112, -46, -113, 93, + -75, -66, 111, -89, -32, 116, -91, -28, 117, -82, -53, 112, + -93, -32, 117, -101, 25, 108, -98, -13, 116, -83, -61, 110, + -98, -19, 115, -101, 15, 106, -96, -14, 108, -74, -80, 104, + -79, -74, 105, -87, -57, 108, -101, 22, 101, -113, 29, 108, + -91, -1, 94, -84, -72, 105, -85, -65, 103, -86, -55, 101, + -112, -5, 112, -109, 12, 104, -102, 86, 77, -96, 96, 67, + -86, 113, 52, -74, 136, 34, -89, 95, 57, -99, 63, 75, + -117, -24, 116, -43, 19, 34, 87, 98, -107, 88, 66, -102, + 77, 82, -96, -35, 155, -13, -75, 117, 35, -92, 112, 52, + -100, 62, 73, -97, 117, 53, -86, 83, 52, -79, 138, 26, + -97, 97, 57, -109, 73, 73, -94, 111, 46, -86, 117, 37, + -94, 110, 44, -121, 46, 89, -92, 89, 49, -102, 50, 70, + -112, 33, 83, -66, 134, 8, -86, 29, 62, -21, -93, 50, + -96, 161, 23, -64, 103, 15, -85, 138, 19, -56, 143, -7, + -44, 144, -19, -46, 136, -16, -62, 143, -5, -64, 135, -2, + -76, 133, 7, -83, 129, 14, -79, 109, 17, -110, 64, 60, + -100, 91, 41, -122, 107, 49, -110, 57, 61, -78, 129, 4, + -59, 140, -16, -63, 146, -17, -32, 132, -35, -52, 137, -23, + -33, 149, -44, -47, 136, -28, -56, 143, -27, 10, 76, -44, + -128, 195, 1, -63, 134, -19, -57, 131, -24, -120, 83, 47, + -108, 96, 31, -111, 87, 37, -134, 73, 59, -73, 102, 0, + -93, 125, 0, -48, 134, -37, -20, 153, -68, 43, 57, -62, + -128, 103, 35, -123, 123, 19, -84, 121, -9, -82, 124, -13, + -91, 123, -7, -86, 122, -10, -91, 122, -9, -96, 117, -3, + -91, 122, -10, -92, 124, -13, -67, 126, -30, -68, 124, -31, + -88, 115, -12, -105, 134, -13, -42, 105, -39, -113, 113, 2, + -110, 104, 6, -106, 108, -1, -95, 114, -12, -85, 119, -24, + -61, 127, -45, -109, 113, -7, -5, 135, -88, 49, 1, -32, + 86, -151, 47, 88, -107, 16, 114, -104, -5, 80, -117, 25, + 65, -125, 39, 116, -100, -12, 110, -101, -7, 115, -93, -18, + 134, -51, -58, 42, 108, -98, -38, 135, -61, 8, 122, -86, + -7, 130, -82, -17, 126, -74, 10, 119, -87, 50, -2, -33, + 14, -138, 84, 20, -130, 74, 25, -132, 70, -1, -137, 90, + 43, -69, 16, 141, -10, -92, 115, -95, -20, 98, -116, 6, + 97, -116, 4, 94, -115, 6, 104, -108, -7, 100, -114, -2, + 94, -115, 2, 99, -119, 1, 85, -103, -1, 86, -96, -7, + 104, -120, -6, 97, -117, -3, 58, -142, 39, 51, -108, 23, + 104, -121, -9, 102, -81, -32, 121, -53, -64, 122, -83, -49, + 111, -96, -33, 94, -121, -7, 87, -129, 1, 76, -122, 6, + 68, -99, 0, 98, -169, 11, 16, -130, 55, 19, -142, 59, + 68, -123, 8, 49, -139, 31, 60, -134, 18, 101, -119, -23, + 83, -108, -17, 97, -113, -24, 110, -56, -65, 124, -71, -71, + 111, -91, -51, 98, -97, -38, 86, -115, -20, 88, -136, -13, + 80, -130, -9, 64, -143, 8, 90, -117, -27, 73, -128, -7, + 90, -126, -26, 106, -94, -54, 103, -93, -53, 82, -118, -25, + 58, -121, -2, 102, -128, -40, 72, -124, -16, 53, -141, 8, + 41, -148, 20, -12, -138, 64, 40, -140, 17, 12, -117, 33, + 97, -176, -26, 53, -134, -1, 28, -110, 13, 65, -183, 2, + 74, -127, -25, 29, -144, 20, 24, -145, 25, 74, -136, -27, + 75, -114, -35, 127, -42, -108, 105, -7, -100, 93, 42, -104, + 94, 34, -103, 92, 9, -95, 64, 101, -96, 81, 71, -105, + 62, 98, -97, 96, 35, -111, 104, 10, -111, 104, 4, -111, + 93, 36, -111, 90, 45, -112, 89, 46, -113, 65, 93, -104, + 76, 71, -111, 96, 5, -108, 94, 6, -109, 90, 45, -118, + 46, 110, -96, 44, 108, -93, 76, 66, -115, 80, 52, -115, + 89, 32, -118, 84, 36, -116, 73, 67, -115, 87, 32, -120, + 85, 34, -121, 80, 47, -119, 70, 61, -116, 65, 68, -113, + 63, 83, -118, -38, 151, -21, 3, 138, -69, 50, 93, -110, + 72, 53, -121, 73, 52, -121, 76, 43, -124, 78, 34, -123, + 68, 63, -125, 69, 47, -119, 86, 6, -123, 92, -28, -116, + 73, 43, -127, 10, 133, -87, -30, 138, -32, 27, 112, -102, + 75, 35, -129, 79, 18, -128, 73, 30, -126, 22, 110, -100, + -19, 144, -57, 15, 115, -93, 54, 64, -124, 69, 33, -128, + 80, 10, -133, 2, 92, -61, -55, 140, -5, -51, 141, -14, + -17, 137, -65, -21, 139, -62, 8, 116, -95, 56, -22, -73, + 66, -9, -102, -3, 146, -99, -3, 110, -77, 9, 114, -100, + 31, 90, -120, 15, 102, -103, -7, 124, -86, -6, 121, -87, + -19, 131, -74, -69, 85, 49, -92, 72, 98, -86, 113, 51, + -88, 108, 57, -85, 116, 46, -84, 92, 60, -86, 26, 120, + -94, 38, 120, -88, 27, 117, -94, 42, 114, -95, 53, 104, + -96, 94, 71, -91, 110, 48, -89, 112, 42, -81, 127, 16, + -63, 134, -18, -55, 135, -33, -63, 129, -17, -35, 140, -71, + -52, 93, -3, -22, -178, 188, -23, -89, 111, -31, -81, 115, + -14, -111, 114, -22, -100, 113, -38, -91, 128, -14, -93, 94, + -5, -92, 80, -19, -114, 115, -59, -61, 127, -80, -22, 127, + -96, 21, 114, -89, 18, 106, -100, 6, 127, -65, -24, 103, + -64, -60, 127, -97, 15, 113, -96, 115, 39, -70, 26, 69, + -65, 57, 41, -26, 95, -37, 3, 161, -123, -50, 136, -40, + -70, 137, -16, -27, 111, -52, -102, 122, 33, -82, 23, 85, + -7, -115, 97, 20, -126, 72, 18, -129, 75, 64, -135, 22, + 9, -77, 45, -113, 146, 31, -93, 140, 8, -98, 105, 39, + -90, 132, 9, -23, 84, -37, -31, 122, -57, -81, 129, -4, + -84, 90, 30, -110, 86, 63, -92, 67, 55, -105, 120, 27, + -124, 79, 80, -67, 94, 2, -102, 129, 12, -94, 130, 1, + -90, 122, 1, -88, 113, 7, -90, 119, 1, -95, 94, 26, + -62, 54, 23, 42, 90, -122, -74, 158, -54, 147, -35, -134, + 67, 37, -108, 6, 90, -87, -19, 107, -73, 55, -45, -23, + 112, -93, -47, 102, -43, -82, 82, 50, -141, 100, -108, -22, + 108, -111, -30, 108, -99, -43, 85, -130, 11, 92, -103, -22, + 97, -111, -22, 82, -131, 12, 93, -121, -12, 100, -103, -37, + 101, -51, -85, 102, -25, -107, 108, -63, -87, 106, -94, -58, + 89, -88, -41, 105, -72, -78, 110, -54, -100, 100, -94, -55, + 94, -33, -101, 91, -5, -120, 100, -57, -91, 92, -32, -103, + 48, 68, -126, 57, 50, -127, 39, 69, -119, 56, 56, -132, + 49, 61, -129, 83, 0, -125, 98, -44, -108, 79, -89, -38, + 83, -141, 4, 68, -132, 15, 71, -127, 4, 94, -116, -41, + 101, -37, -127, 84, -36, -101, 86, -23, -117, 79, -2, -127, + 89, -42, -109, 82, -30, -108, 72, 8, -130, 86, -24, -124, + 84, -14, -132, 73, -2, -126, 91, -52, -112, 86, -30, -126, + 85, -25, -130, 53, 13, -111, 73, -23, -115, 51, 29, -124, + 37, 18, -89, 69, 19, -152, 70, -4, -133, 68, 5, -141, + 32, 59, -126, 66, 6, -143, 86, -53, -119, 67, -15, -125, + 51, 34, -146, 51, 22, -136, 61, 1, -135, 50, 25, -140, + 53, 20, -141, 20, 17, -67, 132, -165, -108, 64, -132, 8, + 78, -36, -142, 59, -87, -36, 69, -126, -17, 82, -136, -38, + 70, -92, -62, 67, -7, -154, 61, -60, -82, 52, -32, -93, + 17, 75, -133, 9, -7, -15, 4, -112, 125, 62, -112, -24, + 74, -107, -64, 77, -73, -112, 72, -61, -117, 65, -33, -136, + 30, 42, -131, 32, 47, -146, 39, -4, -103, 24, -180, 155, + -30, -54, 148, -31, -37, 130, -49, -18, 149, -33, -6, 93, + 89, -158, -53, 73, -92, -89, 77, -102, -89, 74, -102, -84, + 74, -110, -77, 72, -96, -92, 71, -77, -110, 65, -51, -127, + 38, 23, -139, 27, 56, -143, 17, 60, -125, 22, 64, -145, + -8, 94, -95, -34, 140, -75, -74, 137, 55, -40, 161, -91, + 18, 29, -95, 54, -38, -120, 36, -139, 72, 52, -115, -11, + 41, -10, -118, 11, -135, 145, 66, -140, -30, 66, -125, -54, + 51, -142, 20, 31, -133, 66, 38, -139, 50, 47, -133, 11, + 54, -123, -26, 54, -119, -33, 48, -125, -8, 43, -134, 15, + 53, -149, -4, 47, -129, -8, 60, -158, -19, 53, -138, -25, + 50, -137, -17, 51, -145, -13, 54, -159, -12, 35, -108, -4, + 59, -160, -35, 51, -123, -49, 60, -131, -71, 47, -113, -50, + 54, -157, -34, 58, -129, -77, 53, -122, -70, 39, -100, -44, + 44, -137, -28, 54, -154, -52, 41, -124, -33, 36, -139, -4, + 48, -169, -26, 36, -109, -40, 52, -167, -50, 45, -130, -56, + 48, -119, -81, 46, -117, -82, 44, -128, -66, 41, -123, -60, + 41, -147, -44, 37, -137, -39, 41, -140, -55, 36, -126, -51, + 28, -99, -42, 30, -135, -22, 34, -195, -1, 29, -109, -48, + 35, -111, -67, 47, -161, -94, 39, -116, -90, 40, -98, -112, + 39, -50, -139, 23, 51, -139, 15, 82, -129, -5, 131, -67, + -13, 127, -37, 4, 120, -113, 21, 47, -142, 22, 41, -143, + 30, -9, -149, 5, 5, -30, -40, 53, 161, -26, 128, 22, + -6, 125, -84, -9, 129, -72, -2, 108, -91, 25, -3, -132, + 5, 62, -91, -29, 150, 1, -28, 148, -7, -38, 164, 28, + -23, 115, 1, -29, 160, -28, -21, 155, -68, -10, 107, -78, + -19, 133, -65, -27, 145, -36, -29, 146, -33, -32, 122, 17, + -28, 89, 40, -35, 149, -13, -45, 151, 39, -32, 147, -39, + -38, 128, 24, -43, 146, 21, -34, 145, -30, -27, 134, -66, + -14, 110, -99, 16, 30, -147, 14, -6, -75, 1, 34, -72, + -26, 154, -116, -3, 70, -117, 24, -12, -144, 7, 49, -146, + -8, 83, -127, -38, 140, -30, -32, 120, -35, -12, 88, -121, + -3, 64, -137, -7, 76, -139, -18, 89, -88, -25, 114, -107, + -13, 87, -134, -9, 70, -133, -26, 108, -106, -25, 104, -102, + -30, 113, -95, -28, 101, -68, -28, 113, -137, -21, 87, -122, + -9, 29, -19, -4, -10, 94, -34, 124, -122, 27, -56, -83, + -1, 45, -207, -23, 87, -134, -13, 53, -105, -35, 116, -129, + -37, 110, -67, -31, 89, -47, -61, 153, 48, -49, 129, -38, + -29, 92, -116, -9, 39, -146, -12, 44, -145, -34, 95, -113, + -49, 127, -48, -29, 67, 32, 62, -145, -77, 57, -142, -11, + 8, -13, -68, -14, 40, -98, -52, 133, -70, 75, -182, -57, + -12, 35, -112, -44, 109, -9, 33, -76, -139, -48, 120, -77, + -21, 54, -26, 65, -162, -49, -42, 106, -96, -59, 144, -14, + -1, 4, -21, 61, -150, -42, 33, -82, -72, -48, 117, -129, + -48, 115, -84, -57, 138, 37, -53, 128, 7, -57, 134, 0, + -44, 104, 54, -21, 49, 122, -39, 88, 132, -26, 59, 139, + -22, 48, 48, 3, -3, -138, 47, -107, -105, 34, -78, -126, + 4, -12, -148, 72, -167, -24, 44, -106, -87, 15, -43, -144, + -5, 4, -156, 46, -116, -110, 54, -137, -75, 48, -121, -40, + 56, -142, -41, 52, -133, -24, 53, -139, -34, 45, -123, -74, + 9, -27, -38, -22, 59, 8, 54, -149, -71, 38, -114, -94, + 9, -30, -61, -24, 61, -13, 48, -135, -53, 3, -16, -54, + -16, 36, -44, 62, -169, -7, 0, -8, -58, -17, 26, -129, + 27, -95, -117, 32, -103, -77, 45, -136, -47, 24, -40, 146, + 33, -125, -154, -37, 96, -55, 58, -178, -50, 28, -93, -52, + 48, -161, -73, 39, -130, -51, 43, -142, -32, 38, -126, -30, + 48, -147, 26, 49, -146, 40, 47, -148, 37, 40, -122, 44, + 44, -147, 15, 2, -29, -76, -42, 117, -105, -17, 42, -53, + 50, -175, -19, -23, 51, -92, 33, -122, -32, -32, 84, -84, + 15, -70, -58, -15, 39, -41, 26, -110, -54, -39, 103, -107, + -43, 117, -85, -33, 69, -124, -36, 88, -93, -24, 83, 4, + -3, -54, -168, -48, 120, -98, -41, 123, -30, -44, 128, -30, + 31, -151, -129, 40, -155, -57, 14, -85, -92, -2, -35, -92, + 56, -180, 20, 30, -130, -54, 37, -146, -32, 38, -142, -12, + 37, -146, -21, 27, -134, -67, 33, -147, -32, 30, -143, -55, + 37, -155, -14, 11, -70, -40, -28, 99, -27, 29, -160, -70, + 21, -130, -68, 26, -144, -58, 29, -148, -37, 31, -141, -4, + 31, -141, 3, 33, -158, -10, 6, -71, -55, 13, -72, -15, + 33, -145, 19, 33, -156, 14, 36, -130, 69, 29, -134, 26, + 26, -148, -14, 2, -59, -53, -15, 50, -44, 39, -168, 63, + 27, -129, 31, 34, -153, 54, 26, -142, 18, 30, -145, 45, + 22, -137, 11, 7, -139, -93, -24, 27, -135, 5, -134, -93, + -1, -104, -102, -2, -95, -95, 3, -152, -107, -7, -70, -96, + 7, -124, -52, 1, -114, -73, -5, -112, -101, 1, -126, -77, + 1, -132, -75, 11, -156, -28, 14, -142, -6, 10, -151, -22, + 7, -139, -30, -4, -115, -74, 12, -146, 0, 3, -140, -38, + -2, -122, -58, -9, -132, -95, -10, -122, -90, -10, -121, -86, + 5, -156, -18, -14, -115, -96, -23, -76, -131, -18, -93, -106, + -24, -88, -128, -27, -66, -136, -22, -98, -112, -27, -72, -129, + -28, -72, -129, -22, -96, -106, -20, -35, -86, -40, 49, -157, + -22, 21, -88, -26, 2, -102, 8, 154, 50, 10, 136, 59, + 11, 135, 65, 13, 138, 78, 24, 89, 116, 8, 136, 63, + -8, 153, 2, -6, 142, 11, -5, 153, 23, -15, 144, -22, + -16, 146, -19, -9, 152, 15, 1, 137, 55, 5, 133, 70, + 9, 123, 90, 20, 85, 124, 15, 100, 112, 6, 121, 87, + 16, 85, 115, 19, 71, 126, 11, 103, 109, 3, 127, 88, + 19, 58, 133, 31, -16, 146, 18, 68, 134, 12, 80, 121, + 8, 86, 105, -2, 133, 85, -15, 41, -55, 3, -124, -72, + 0, -49, -38, -16, 196, 57, -14, 146, 35, -16, 147, 32, + -2, 103, 72, -2, 124, 97, -20, 150, 21, -12, 142, 64, + 29, -19, 151, 12, 45, 117, -18, 149, 43, -22, 146, 25, + -28, 150, -11, -27, 123, -22, -36, 141, -59, -35, 128, -61, + -34, 150, -27, -37, 143, -45, -40, 134, -67, -38, 133, -56, + -36, 134, -38, -30, 149, 21, -36, 144, -20, -34, 137, -9, + -28, 122, 7, -37, 54, -137, -33, 23, -144, -16, -59, -160, + 39, -162, -1, 37, -146, 12, 9, -83, -52, -31, -7, -164, + -30, 8, -140, -27, -21, -151, -7, -56, -96, -5, -88, -112, + -10, -97, -145, -5, -87, -105, 13, -135, -73, -4, -53, -63, + 29, -193, -50, 21, -154, -43, -36, 34, -123, -30, 51, -83, + 19, -149, -42, 27, -125, 12, -38, 23, -137, -34, -36, -164, + -18, -78, -129, -9, -95, -104, -27, -58, -142, 7, -100, -41, + 46, -128, 86, 27, -147, 6, 26, -152, 2, 17, -163, -35, + 12, -82, -2, -52, 57, -162, -42, 111, -88, -42, 110, -85, + -46, 58, -132, -51, 62, -140, -25, 121, -13, 4, 123, 89, + -1, 39, 21, -18, -128, -141, -39, -14, -140, -9, 147, 56, + 3, 81, 64, -30, -77, -152, 4, 97, 73, -40, 11, -127, + -6, 92, 40, -42, 114, -68, -40, 10, -127, -32, -63, -142, + -59, 75, -141, -54, 62, -131, -50, 90, -97, -53, 60, -123, + -58, 91, -120, -54, 71, -114, -46, 100, -72, -41, 93, -60, + -37, 148, -13, -31, 158, 14, -30, 109, -13, -50, 117, -63, + -30, 153, 20, -15, 138, 55, -25, 124, 17, -34, 152, 15, + -28, 158, 39, -20, 136, 50, -22, 134, 43, -15, 136, 65, + -26, 140, 40, 0, 105, 90, 3, 119, 114, -8, 120, 83, + -7, 106, 75, 14, 94, 131, 14, 90, 130, 7, 80, 101, + 10, 118, 149, -10, 109, 83, 7, 95, 122, -2, 105, 108, + -3, 106, 110, -15, 45, -3, -38, 137, 29, 4, 83, 113, + 1, 91, 112, -17, 130, 97, -20, 110, 68, -57, 138, -24, + -54, 137, -16, -55, 130, -24, -66, 120, -76, -58, 70, -105, + -72, 109, -102, -57, 131, -21, -57, 108, -48, -36, 71, -26, + -45, 12, -132, -61, 63, -114, -59, 95, -65, -72, 78, -126, + -46, 24, -111, -62, 43, -134, -41, 48, -62, -34, 60, -27, + -14, -62, -118, -10, -97, -149, -36, -22, -129, -64, 65, -103, + 2, -104, -116, 77, -141, 52, 45, -140, -33, 24, -120, -67, + 17, -115, -77, -58, -12, -173, -57, 124, -22, -18, 111, 74, + -26, 121, 63, -73, 123, -61, -16, 13, -28, -46, 17, -105, + -78, 58, -139, -50, 16, -113, -62, 28, -127, -75, 77, -107, + -63, 51, -103, -62, 6, -144, -29, 49, -18, -32, -36, -116, + -70, 53, -111, -73, 78, -93, -56, 79, -47, -13, 65, 38, + -30, -67, -139, -58, 161, 33, -19, 119, 82, -75, 112, -55, + -2, -33, -39, 34, -104, -32, 5, -131, -123, -1, -80, -85, + -55, 26, -96, -54, 54, -65, -40, 45, -43, -53, 30, -85, + -32, -3, -73, -87, 63, -122, -50, -9, -116, -65, 19, -116, + -71, 17, -130, -80, 46, -117, -98, 116, -87, -28, 51, -6, + -14, 31, 1, -91, 99, -85, -74, 32, -114, -103, 87, -115, + -79, 73, -82, -82, 82, -76, -50, 91, -8, -13, 71, 46, + -78, 49, -99, -77, 5, -139, -82, 111, -44, -83, 71, -82, + -64, 95, -23, -62, 48, -66, -44, 102, 22, -40, -15, -85, + -28, -6, -56, -58, 141, 35, -39, 101, 30, 46, 34, 115, + -127, 87, -137, -54, 85, -10, -56, 143, 46, -47, -20, -103, + 15, -44, -16, -73, 105, -22, -90, 112, -42, -64, 95, -13, + -115, 119, -74, -79, 122, -6, -41, 102, 36, -5, 21, 13, + -83, 22, -116, -94, 84, -69, -101, 50, -113, -20, 139, 110, + 1, 35, 40, -102, 57, -106, -29, 101, 59, -77, 74, -46, + -58, 12, -81, -32, 114, 70, 67, -11, 98, -159, 133, -114, + -20, 42, 13, 50, 52, 138, 8, 96, 119, 63, 18, 124, + 116, -69, 116, 31, 53, 113, 29, 28, 82, -126, 35, -174, + -93, 81, -63, -105, 73, -90, -99, 59, -93, -86, 56, -77, + -34, 133, 99, 25, 76, 128, 10, 90, 123, 40, 56, 135, + 4, 74, 95, 73, 9, 136, 76, 5, 137, 5, 99, 132, + -36, 38, -15, 11, -124, -136, -72, 8, -113, -84, 29, -107, + -24, -78, -135, -62, -21, -130, -51, -42, -133, -70, 17, -93, + -12, 121, 124, 7, 78, 105, -13, 101, 103, 33, 74, 145, + -62, 121, 49, -41, 121, 84, -33, 114, 91, -36, 114, 88, + -44, 117, 81, -44, 121, 87, 19, 71, 130, 38, 52, 136, + 15, 79, 139, 1, 59, 85, -94, 108, -13, -104, 105, -34, + -115, 101, -56, -91, 70, -58, -105, 97, -40, -64, 75, -3, + -66, -10, -127, -103, 105, -21, -82, 81, -20, -136, 62, -137, + -76, 32, -78, -125, 58, -119, -47, -24, -109, -91, 71, -42, + -94, 124, 27, 58, 52, 166, 74, -12, 100, 64, 25, 141, + 39, 56, 147, 23, 65, 135, 97, -31, 118, 88, -61, 57, + 129, -98, 73, 102, -82, 52, 80, -6, 131, 25, 59, 137, + -74, 118, 55, -84, 108, 19, -38, 109, 106, 59, 10, 125, + 65, 14, 144, 24, 51, 131, -22, 92, 115, -74, 112, 52, + -105, 109, -13, -101, 67, -74, -37, -43, -143, -102, 33, -130, + -65, 19, -86, -133, 124, -31, -106, 97, -22, -106, 68, -72, + -105, 53, -95, -110, 54, -98, -106, 87, -34, -134, 101, -57, + -102, 77, -41, -78, 4, -122, -71, -5, -122, 0, -91, -149, + 60, -97, -60, 113, -96, 28, 108, -82, 42, 123, -93, 52, + 88, -91, 0, -19, -77, -152, 136, -111, 47, 93, -79, 32, + -144, 58, -147, -113, 62, -85, -115, 90, -44, -111, 61, -81, + -113, 56, -91, -106, 46, -91, -97, 31, -101, -93, 3, -134, + -105, 44, -89, -1, -105, -155, -62, -37, -142, -27, -60, -125, + 94, -121, -38, 106, -109, -4, -1, -61, -85, -7, -28, -51, + 120, -40, 116, 118, -122, 0, 52, -66, -17, -29, -65, -130, + -35, -59, -128, -109, 51, -83, -59, -48, -147, -101, -1, -137, + 24, -67, -55, 65, -148, -103, 37, -87, -62, 39, -74, -39, + 87, 11, 130, 88, -84, 13, 26, -142, -142, 57, -118, -69, + 16, -93, -91, 119, -132, 1, 112, -116, 12, 74, -115, -36, + 25, -109, -94, 66, -86, -11, -7, -85, -108, -97, 52, -70, + -111, 45, -94, -37, -21, -73, -70, 78, -3, -81, 57, -40, + -112, 37, -103, -90, -7, -121, -106, 68, -57, -97, -5, -126, + -126, 95, -48, -86, 98, 4, -101, 132, 28, -28, 89, 67, + -63, 130, 74, -78, 121, 47, -64, 123, 66, -43, 115, 85, + -18, 107, 106, -15, 103, 109, -2, 97, 117, -18, 104, 107, + -29, 108, 102, -13, 98, 110, 27, 76, 134, 18, 79, 126, + -3, 85, 110, -93, 116, 36, -98, 88, -8, -119, 65, -63, + -108, 31, -97, -125, 72, -58, -123, 70, -58, -122, 86, -33, + -120, 63, -62, -97, 76, -14, -88, 121, 59, -57, 107, 81, + -116, 101, 0, -118, 89, -16, -123, 77, -37, -113, 40, -77, + -117, 100, 6, -124, 41, -85, -107, 85, -3, -127, 95, -8, + -61, 9, -56, -24, -24, -61, -64, 8, -58, 50, -110, -99, + -88, -27, -132, -63, -35, -115, -145, 38, -102, -118, 38, -73, + -132, 67, -45, -131, 59, -55, -129, 67, -41, -130, 83, -18, + -121, 80, -12, -106, 90, 18, -121, 90, 6, -129, 72, -29, + -123, 89, 5, -125, 84, -4, -126, 85, -1, -132, 74, -20, + -129, 82, -5, -128, 80, -6, -125, 85, 6, -114, 92, 27, + -114, 91, 26, -109, 100, 45, -119, 88, 21, -131, 79, 0, + -116, 93, 34, -120, 89, 25, -134, 76, -3, -132, 74, -3, + -118, 84, 25, -97, 100, 66, -71, 79, 59, -102, 100, 66, + -105, 106, 75, -63, 93, 90, -75, 74, 54, -61, 108, 117, + -79, 93, 83, -110, 89, 51, -105, 100, 74, -107, 80, 43, + -132, 75, 15, -109, 82, 47, -36, 61, 73, -24, 76, 107, + -79, 91, 89, 19, 67, 129, -18, 21, 21, -106, 11, -66, + -41, 73, 92, 32, 53, 118, 48, 67, 155, -14, 78, 128, + 23, 66, 140, 68, 17, 87, 116, -7, 88, 92, -13, 56, + 94, -97, -96, 121, -86, -49, 36, 8, 46, -84, 73, 57, + 198, -81, 31, 88, 15, 107, -139, 99, 55, -15, 57, 95, + -48, 44, 39, 132, -65, -1, 101, -71, -41, 56, 19, 90, + -109, 95, 76, -84, 83, 80, 0, 44, 86, 127, -10, 101, + 86, 14, 110, 30, 54, 137, -139, 80, 23, -137, 46, -42, + -135, 61, -7, -136, 58, -12, -136, 51, -26, -136, 54, -17, + -142, 64, 0, -143, 71, 15, -119, 71, 38, -139, 69, 17, + -130, 52, -6, -149, 58, -10, -141, 57, -1, -142, 57, -2, + -125, 55, 9, -115, 77, 66, -138, 60, 13, -145, 46, -19, + -135, 63, 25, -131, 63, 30, -145, 46, -15, -144, 29, -48, + -126, 9, -75, -131, 2, -89, -103, -2, -78, -145, 8, -85, + -73, -25, -101, -59, -25, -91, -125, 51, 20, -111, -21, -115, + -110, -10, -90, -144, 20, -50, -93, -27, -111, -87, 54, 54, + -145, 67, 47, -122, 0, -72, -96, -31, -117, -70, -24, -85, + -163, 1, -89, -50, -59, -140, -12, -32, -67, 158, -11, 64, + 80, -49, -49, -105, -24, -102, -154, 32, -21, -130, -6, -79, + -155, 53, 20, -111, -1, -57, -135, -2, -70, -150, 10, -52, + -53, 63, 93, 122, 17, 89, 33, 27, 67, -87, 73, 97, + -111, 65, 72, -127, 62, 59, -142, 49, 30, -136, 52, 41, + -111, 67, 81, -142, 54, 45, -96, 68, 93, -145, 51, 42, + -138, 21, -15, -134, 3, -48, -143, 18, -19, -112, -14, -72, + -69, -19, -64, -127, 17, -11, 106, -88, -136, 73, -56, -82, + -17, -66, -133, -14, -67, -133, -156, 43, 26, -129, 56, 62, + -127, 53, 61, -121, 47, 50, -165, 41, 27, -100, 5, -21, + -39, 83, 150, -67, 73, 125, -70, 56, 90, -158, 25, 6, + -138, 1, -37, -115, -32, -97, -19, -22, -49, 170, 0, 48, + 129, -52, -68, 49, -72, -127, 69, -67, -110, 37, -63, -111, + 81, -63, -95, 66, -61, -96, 131, -36, -28, 169, -43, -28, + 150, -47, -39, 90, -65, -90, 128, -53, -54, 120, -61, -71, + 138, -48, -39, 123, -61, -65, 132, -58, -56, 91, -73, -96, + 134, -71, -75, 115, -51, -44, 139, -53, -37, 119, -52, -43, + 159, -20, 30, 145, -37, -3, 85, -30, -17, 36, -84, -128, + 117, -79, -83, 122, -58, -44, 106, -49, -36, 109, -94, -106, + 82, -82, -98, 75, -82, -101, 65, -85, -107, 62, -85, -108, + 41, -87, -117, 33, -86, -120, 30, -89, -123, 20, -86, -123, + 25, -88, -120, 33, -89, -119, 32, -90, -118, 34, -90, -117, + 22, -90, -119, -12, -73, -110, 29, -103, -133, 32, -93, -116, + 50, -95, -109, 14, -91, -119, -30, -84, -125, -195, 88, 36, + -121, 70, 44, -137, 65, 33, -119, 79, 60, -98, 87, 82, + -56, 82, 91, -57, 83, 96, -59, 73, 80, -205, 54, -2, + -151, 27, -18, -78, 5, -23, -22, 101, 138, -37, 90, 117, + -88, 84, 91, -127, 63, 47, -135, 56, 35, -139, 6, -38, + -140, 1, -47, -134, 70, 61, 5, 81, 122, 17, 78, 125, + -41, 86, 117, -89, 79, 93, -98, 75, 85, -119, 64, 62, + -100, 19, -1, 17, -95, -143, -132, 50, 38, -20, 87, 131, + 47, 56, 102, 18, 68, 116, -29, 86, 130, -106, 66, 74, + -66, 73, 102, 130, 32, 94, 103, -30, -19, 47, 77, 145, + -70, 79, 111, -99, 71, 90, -128, 63, 68, -114, 62, 73, + -87, 70, 95, -55, 78, 123, -97, 68, 93, -121, 24, 7, + -147, 9, -24, -105, -31, -85, -80, 65, 96, -168, 46, 39, + -100, 19, 9, 53, -101, -168, -37, -29, -61, -127, 65, 85, + -121, 58, 77, -134, 29, 22, -156, 25, 12, -144, -2, -33, + -137, -3, -32, -103, -67, -138, -35, -62, -117, -94, -9, -32, + -79, 89, 144, -103, 42, 58, -147, 52, 71, -131, 39, 52, + -94, 50, 77, -110, 45, 69, -88, 41, 63, -145, 58, 91, + -135, 28, 39, -149, 33, 45, -154, 42, 67, -110, 29, 47, + -142, 33, 52, -122, 43, 75, -88, 36, 65, -48, 26, 48, + -79, -44, -90, -151, -18, -40, -139, -29, -58, -91, 10, 17, + -85, 59, 112, 37, 70, 137, 32, 61, 121, 79, 42, 84, + 57, 43, 89, 16, 96, 195, 36, 62, 129, 70, 9, 19, + 137, 40, 90, 51, 50, 108, 169, -17, -27, 36, 11, 26, + 61, 36, 80, 155, -21, -32, 83, -6, -5, -231, 34, 53, + -136, -5, -19, -97, 17, 29, 72, 29, 68, -155, -33, -80, + -91, -42, -93, -163, -15, -36, -124, 23, 46, -123, 34, 71, + -112, 47, 100, -74, 53, 114, -24, 59, 131, 77, 57, 126, + -49, 54, 121, -99, 29, 69, -108, -6, -12, 54, -64, -146, + -67, -63, -139, -79, -39, -84, -150, 6, 20, -139, 16, 41, + -148, -25, -46, -76, -52, -109, -43, -62, -131, -129, -32, -58, + -159, -30, -48, -105, -46, -87, -124, -6, 0, -30, 8, 22, + -73, -24, -43, -57, 44, 101, 39, 66, 136, -102, 62, 146, + 30, 32, 67, 11, 49, 105, 29, 27, 57, -151, -27, -39, + -117, 24, 70, 16, 27, 60, -138, -5, 10, -65, 55, 136, + -33, 35, 84, 122, 35, 61, 121, 49, 94, 115, 44, 86, + 113, 41, 79, 158, 6, -6, 124, 3, -8, 183, 20, 27, + 23, -15, -38, -80, -60, -133, -18, -46, -105, 10, -32, -75, + 86, 19, 35, 82, 53, 115, 21, 61, 141, 16, 64, 151, + 76, 33, 75, 102, 59, 134, 129, 33, 73, 138, 35, 80, + 111, 28, 63, 105, 29, 69, 121, 41, 101, 115, 40, 102, + 82, 18, 44, 870, 23, 91, 110, 40, 114, 77, 23, 70, + 168, 28, 91, 133, 20, 70, 114, 30, 98, 147, 9, 46, + -90, 27, 62, 141, 13, 57, 73, -15, -30, 53, -51, -132, + -19, -34, -96, -41, -51, -145, 15, -49, -127, 95, -34, -73, + 169, 5, 42, 52, 49, 140, 124, 28, 99, 17, 53, 147, + 69, 28, 93, 171, -33, -53, 144, 4, 48, 140, 8, 58, + 131, 12, 67, 113, 11, 64, 150, -6, 27, 138, -14, 5, + 138, -42, -71, 49, -51, -127, 60, -54, -127, 76, -29, -53, + -71, 79, 190, -14, 52, 140, 1, 50, 144, 110, 25, 109, + -28, 52, 141, -81, 43, 99, -8, 49, 144, 48, 39, 136, + 93, 26, 116, 113, 17, 100, 135, 5, 72, 150, -3, 56, + 113, -7, 29, 162, -13, 33, 146, -15, 25, 140, -3, 62, + 52, 28, 120, -7, 49, 156, 114, 7, 87, 44, 10, 60, + 14, 38, 140, 41, 25, 111, -150, 31, 21, 30, 35, 144, + 94, 17, 120, 126, 4, 94, 139, -28, -16, 135, -41, -62, + 151, -29, -4, 25, 19, 88, -141, 35, 31, -58, 13, 9, + 14, -26, -86, -127, 49, 98, 155, 0, 104, 71, 5, 70, + -208, 7, -117, -46, 10, 7, 91, 20, 141, 98, 13, 115, + 101, 9, 110, 114, 4, 102, 96, 10, 117, 95, 1, 79, + 109, -40, -76, 133, -7, 81, 117, -41, -68, -35, -14, -89, + 120, -42, -66, 96, -58, -148, 89, 0, 74, 65, 10, 99, + 130, -44, -61, 71, -13, 15, 25, 41, 188, 42, 22, 129, + 122, -11, 72, 140, -30, 16, 82, 17, 155, -11, 36, 147, + 11, 19, 96, 183, -61, -70, 112, -43, -66, 155, -51, -47, + 84, -4, 77, 16, 27, 138, -14, 31, 125, -75, 53, 155, + -80, 36, 74, -32, 23, 74, -15, 35, 154, -25, 35, 141, + 72, 0, 99, 109, -54, -133, 105, -45, -94, 50, -21, -34, + -128, 64, 153, -73, 48, 147, 30, 17, 135, -15, 32, 149, + 18, 21, 148, 53, 10, 136, 28, 19, 158, 37, 11, 129, + 65, 4, 136, 47, -2, 67, -5, 36, 232, -126, 44, 76, + 38, 14, 176, 36, 11, 147, 59, 2, 141, 104, -14, 111, + 123, -27, 48, 138, -42, -32, 187, -62, -75, -42, 18, 54, + -141, 44, 29, -118, 42, 81, -131, 41, 52, -47, 24, 99, + 100, -12, 127, -67, 31, 125, 69, -3, 154, 111, -34, -29, + -3, -9, -99, 147, -28, 121, 100, -20, 81, 90, -18, 85, + 77, -8, 160, 91, -20, 75, 130, -34, 57, -12, 7, 30, + -147, 40, -39, -126, 31, -55, -140, 35, -59, -92, 16, -109, + -133, 32, -52, -138, 31, -73, -128, 32, -25, -139, 29, -69, + -131, 24, -93, -135, 29, -56, -140, 29, -51, -155, 38, 9, + -68, 29, 120, -52, 14, 26, -2, -10, -105, -127, 37, 72, + -73, 28, 119, -80, 32, 142, -82, 30, 140, 29, 5, 136, + 51, 1, 149, 91, -14, 95, 46, -1, 124, -187, 43, 23, + 2, 10, 158, -32, 14, 112, -177, 35, -56, -60, 23, 186, + 83, -11, 131, 135, -25, 77, 148, -30, 61, 135, -30, 13, + 142, -36, -57, 44, -12, -44, 21, 3, 184, 63, -11, 92, + 147, -40, -107, 144, -35, 15, 202, -54, -65, -73, 21, 54, + -123, 32, 26, -149, 37, 6, -32, 13, 130, 106, -21, 127, + 51, -9, 130, -27, 8, 64, -59, 17, 91, 33, -5, 135, + 77, -18, 95, 108, -26, 130, 55, -13, 135, 48, -11, 147, + 66, -18, 128, 103, -27, 104, 85, -24, 134, 147, -41, 64, + 19, -6, 68, 15, -5, 55, 129, -34, -105, 26, -8, 31, + 25, -8, 70, 136, -36, -112, 129, -37, -45, 103, -32, 103, + 80, -25, 120, 132, -38, -81, 21, -7, 3, -143, 41, 91, + -118, 37, -84, -104, 31, -37, 37, -15, 193, 1, -4, 148, + 12, -8, 152, -17, -1, 153, 3, -8, 154, 55, -21, 114, + 136, -42, 33, 138, -40, -30, 143, -45, 34, 130, -38, -51, + 84, -20, -134, 141, -43, -46, 99, -28, -115, 139, -44, -30, + 133, -47, 62, 126, -43, 4, 155, -52, -32, 141, -50, 9, + 67, -29, 129, -217, 78, -48, -91, 30, 49, 147, -56, 97, + 75, -27, 24, -208, 74, -46, -143, 50, -14, -108, 40, -86, + -122, 44, -87, -69, 19, 95, -20, -1, 153, -144, 42, 95, + -91, 26, 69, -105, 27, 110, -56, 9, 142, 31, -19, 141, + 84, -28, 24, 106, -34, 10, -98, 21, 131, 30, -19, 134, + 148, -48, 3, 117, -31, -89, 78, -17, -117, 122, -36, -74, + 69, -22, -14, -138, 31, 215, -60, 10, 119, -78, 16, 122, + -115, 38, -4, -151, 50, -18, -124, 44, -71, -124, 43, -54, + -144, 45, -14, -64, 14, 67, 179, -57, 30, 125, -44, 67, + 52, -28, 137, 63, -31, 126, 126, -49, 95, 144, -44, -27, + 145, -47, -12, 144, -46, -26, 122, -48, 68, 107, -46, 95, + 131, -53, 64, 136, -49, 11, 136, -52, 28, 89, -28, -48, + 36, 2, -152, -16, 20, -148, 86, -19, -130, 104, -30, -102, + 111, -37, -68, 140, -53, -1, 120, -48, 13, 104, -50, 107, + 129, -49, -15, 73, -19, -133, 41, -13, -37, -39, 1, 179, + -129, 44, 82, -136, 57, -40, -129, 53, -27, -126, 47, 10, + -142, 50, 53, -63, 13, 112, 8, -18, 149, 45, -31, 143, + 136, -57, 59, 142, -53, -20, 138, -57, 23, 102, -50, 93, + 82, -46, 121, 126, -59, 66, 78, -45, 115, 43, -35, 140, + 57, -39, 119, 74, -46, 108, -89, 19, 130, -46, -2, 147, + -88, 19, 119, -113, 31, 99, -93, 46, -59, 72, -8, -137, + 102, -28, -92, 11, 18, -161, -96, 49, -74, -84, 51, -134, + -94, 51, -104, -79, 46, -124, -107, 51, -78, -132, 56, -46, + -104, 51, -100, -143, 47, 58, -132, 44, 48, -138, 54, -39, + -127, 51, -45, -138, 54, -54, -142, 53, -26, -121, 47, -58, + -126, 49, -59, -139, 50, -36, -135, 41, 25, -146, 45, 24, + -107, 44, -100, -115, 44, -86, -124, 45, -74, -148, 49, -40, + -125, 31, 66, -83, 14, 108, -48, -1, 147, -42, -1, 123, + 116, -48, 130, 127, -47, 76, 124, -46, 79, 112, -45, 93, + 74, -39, 124, 41, -31, 146, 95, -43, 99, 120, -41, 17, + 125, -39, -7, 123, -50, 70, 110, -45, 58, 111, -53, 108, + 78, -23, -21, 122, -24, -128, 143, -52, 19, 146, -46, -48, + 73, -19, -46, 128, -61, 101, 66, -43, 127, -160, 48, 75, + -148, 45, 55, -120, 29, 88, -120, 29, 81, -122, 25, 107, + -140, 42, 39, -122, 26, 88, -106, 18, 107, -87, 7, 124, + -101, 13, 115, -20, -16, 122, 55, -38, 110, 148, -51, 18, + 124, -43, 8, 82, -56, 149, 10, -26, 114, 62, -41, 104, + -119, 33, 37, -113, 55, -90, -93, 27, 22, 4, -32, 149, + -4, -32, 163, -60, -8, 131, -85, 3, 112, -35, -21, 147, + 41, -47, 149, -77, -2, 113, -87, 20, 38, -90, 56, -120, + -88, 48, -90, -8, 17, -64, -53, -20, 162, -10, -31, 147, + 55, -34, 69, -14, -15, 81, -74, -7, 122, -44, -22, 144, + -2, -43, 171, -14, -29, 128, -19, -34, 149, -41, -25, 138, + 26, -38, 109, 85, -58, 111, 53, -51, 120, -70, -19, 143, + -68, 2, 64, -159, 44, 17, -135, 42, -6, -111, 47, -48, + -14, 46, -145, 77, 18, -141, 3, 26, -96, -128, 49, -44, + -150, 49, -21, -141, 24, 57, -100, -4, 114, -90, -3, 96, + 222, -83, 76, 62, -44, 91, 74, -55, 118, 90, -69, 142, + 142, -41, 0, 117, -61, 82, 66, -54, 112, 64, -59, 127, + 39, -38, 80, -114, 24, 35, -160, 55, -21, -116, 7, 85, + -21, -50, 172, -30, -38, 141, -44, -33, 136, -18, -44, 143, + 15, -50, 132, 125, -58, 61, 134, -55, 39, 87, -65, 108, + -108, -7, 111, -171, 30, 57, -122, 8, 76, -161, 52, -16, + -157, 32, 34, -14, -54, 156, 100, -54, 67, 150, -56, 35, + 136, -17, -59, 121, -76, 104, -62, -35, 139, -143, 18, 62, + -138, 38, 4, -140, 47, -18, -139, 20, 48, -134, 64, -69, + -83, 61, -101, -108, 57, -75, -77, 52, -85, -35, 66, -152, + -97, 53, -78, -153, 45, -17, -139, 35, -4, -122, 43, -38, + -145, 48, -39, -131, 50, -55, -35, 17, -25, 137, -22, -26, + 172, -52, 33, 120, -16, -36, 126, -23, -20, 163, -31, -28, + 144, -22, -41, 137, -12, -66, 138, -19, -52, 141, -23, -41, + 122, -3, -88, 89, 17, -123, 62, 29, -135, 27, 39, -143, + -8, 50, -143, -36, 54, -137, -97, 54, -86, -118, 58, -80, + -129, 45, -36, -124, 35, -5, -133, 33, 4, -164, 34, 26, + -107, 20, 20, -188, 54, -27, -146, 34, 0, -150, 34, 3, + -145, 30, 10, -127, 8, 63, -145, 14, 55, -85, -11, 92, + -32, -14, 67, -106, 45, -73, -137, 20, 24, -42, 26, -57, + 73, 11, -81, -168, 22, 37, -53, -27, 118, -158, 15, 48, + -68, -6, 58, -88, 16, 1, -103, 34, -50, -68, 18, -19, + 189, -4, -93, 63, 34, -146, -88, 35, -63, -131, 25, -8, + -159, 26, 8, -61, -27, 121, 26, -41, 118, 15, -28, 81, + -100, 59, -136, -39, 43, -117, -48, 35, -90, -92, -13, 92, + 24, -50, 148, -47, -22, 93, -103, 51, -111, -30, -54, 187, + -4, -45, 141, -43, -10, 52, -44, 57, -156, -3, 55, -172, + -113, 9, 23, -46, -29, 115, -20, -42, 140, -51, -43, 155, + -8, -37, 114, -142, 27, -21, -138, 10, 25, 3, -21, 63, + 99, -27, 38, 1, -24, 71, -133, 8, 28, -51, -34, 119, + 20, -39, 105, -49, -14, 57, -19, 63, -172, -63, 18, -30, + 3, -52, 148, -27, -6, 29, -81, 38, -80, -1, -47, 132, + 41, -28, 66, -100, 12, 0, -57, -14, 60, -78, -50, 161, + 19, -50, 132, -110, -31, 118, 37, -32, 72, 121, -13, -3, + -55, -17, 61, -119, -5, 51, 22, -32, 75, -8, -30, 81, + -128, 34, -51, -13, -34, 92, -68, -38, 115, 104, -25, 35, + -22, -38, 101, -97, -8, 46, 10, -31, 75, 96, -15, 11, + -150, -26, 102, -89, -41, 122, -29, -49, 124, -5, -59, 142, + 102, -25, 34, -142, -35, 113, -11, -42, 101, -17, -61, 141, + 32, -65, 140, -65, -49, 121, -116, -25, 80, -12, -22, 49, + 74, 4, -24, -32, -65, 149, -87, -22, 64, -107, -19, 61, + -74, -53, 125, -30, -54, 117, -20, -47, 102, 103, -40, 63, + 121, 38, -100, 11, 45, -95, 83, 15, -48, -5, -52, 109, + -74, -49, 115, -125, -37, 99, -78, 21, -28, -105, 24, -32, + -65, -36, 84, -117, -54, 126, -12, -43, 88, 3, -20, 39, + -93, 17, -21, 40, -36, 67, -187, 32, -38, -68, -35, 77, + 142, -19, 19, 44, -6, 7, -107, -31, 73, -170, 5, 11, + -38, -29, 61, 138, -35, 51, 19, -30, 56, -139, 30, -41, + -26, -22, 45, -79, -18, 43, -10, -20, 39, -119, 5, 2, + -73, -15, 35, 51, -34, 60, 135, -9, 4, 88, -13, 15, + -204, 6, 8, -58, -54, 107, 41, -62, 111, -12, -60, 111, + 165, 3, -22, 141, 9, -30, 81, 9, -26, 121, 5, -25, + 46, 10, -23, -65, -71, 137, -113, 15, -13, -165, 6, 8, + -137, -10, 31, -71, -39, 77, 44, -55, 96, 56, -52, 87, + -60, -51, 95, 76, -8, 8, 32, -7, 9, 58, -30, 46, + 91, 74, -140, 133, 14, -40, -101, -58, 115, -116, -74, 141, + 22, -36, 61, 36, -9, 12, -128, -39, 79, -45, -62, 111, + 96, -4, -3, 89, 24, -50, 69, 16, -36, -27, -68, 119, + -8, -73, 125, 52, -14, 17, -163, -5, 26, -11, -80, 133, + 113, -56, 81, 164, -41, 48, 93, -44, 62, 120, -27, 28, + 139, 12, -38, 114, 32, -68, 113, 56, -108, 91, 75, -138, + 71, 50, -95, 85, 48, -96, 129, 23, -62, 16, 79, -137, + -21, 60, -100, 45, 39, -76, 43, -102, 168, 100, -60, 85, + 86, -42, 54, 22, -91, 149, 77, -82, 121, 102, -39, 44, + 30, -102, 160, 52, -68, 100, 79, -76, 105, 81, -75, 101, + 100, -72, 92, 107, -82, 103, -20, -80, 129, 43, -77, 108, + 97, -78, 95, 31, -91, 130, 152, -23, -2, 139, 15, -55, + 85, 37, -78, -46, 84, -116, 82, 66, -121, 93, 34, -76, + 140, 2, -42, 120, 7, -44, 27, 94, -155, 33, 71, -122, + -10, 85, -133, -17, 82, -129, -22, 77, -118, -36, 75, -113, + 0, 71, -119, -42, 78, -120, -84, 51, -62, -18, 8, -8, + 158, 11, -67, 92, 44, -104, 59, 43, -94, 109, 50, -124, + -4, 43, -75, -166, -24, 98, -135, 18, 11, -144, 30, -10, + -87, 17, -4, 167, 12, -72, 119, 0, -37, 2, 31, -55, + 149, -74, 84, 81, 29, -78, 74, 63, -140, -30, 63, -103, + -137, 64, -72, -118, 56, -65, -130, 36, -23, -116, 42, -42, + -64, 75, -122, -41, 74, -128, -29, 75, -135, 10, 49, -99, + -15, 80, -154, -40, 69, -124, 76, 46, -118, -7, 57, -113, + 69, 41, -108, 71, 47, -122, 85, 54, -144, 93, 36, -111, + 75, 31, -94, 48, 61, -151, 27, 60, -142, 7, 54, -123, + -98, 55, -87, 11, 62, -146, -33, 63, -135, 49, 45, -126, + -1, 19, -44, 43, 11, -45, 45, 31, -92, 136, -8, -38, + 142, 2, -68, 121, -7, -38, 168, -56, 59, 69, -63, 119, + 54, -65, 129, -102, -29, 116, -19, -59, 146, -32, -54, 138, + -35, -54, 138, -50, -50, 131, -57, -41, 114, -34, -55, 135, + -52, -49, 125, -61, -30, 89, -21, -65, 145, 24, -66, 128, + 78, -59, 90, 58, -76, 131, 98, -70, 104, 39, -58, 98, + 35, -86, 155, 29, -67, 119, 95, -70, 98, 126, -32, 10, + 161, -43, 16, 118, -28, 2, 88, -64, 85, 11, -26, 43, + 80, 38, -106, 156, 9, -87, 89, 28, -93, 101, 21, -88, + 125, 31, -120, 87, 26, -94, 91, 14, -71, 143, 6, -86, + 115, 7, -74, 136, 12, -97, 132, -76, 79, 140, -29, -19, + 134, -20, -36, 62, -45, 55, -190, 9, 90, -75, -38, 116, + -100, -25, 103, -13, -67, 136, -131, -8, 83, -145, 16, 45, + -146, 21, 32, -137, 6, 55, -107, -24, 97, -117, -9, 71, + -105, -33, 110, -98, -41, 117, 21, -66, 111, 73, -68, 92, + 97, -88, 114, 158, -25, -26, 66, -81, 113, 35, -79, 122, + 68, -81, 109, 16, -74, 121, -89, -48, 120, -143, 29, 13, + -109, 73, -77, -134, 61, -47, -107, 36, -17, -124, -37, 114, + -48, -64, 126, 16, -80, 128, -34, -71, 129, 31, -93, 141, + 30, -73, 105, 61, -83, 110, 66, -83, 105, 74, -87, 106, + 34, -78, 107, -27, -60, 104, -107, 38, -18, 47, 87, -152, + -16, 52, -75, -34, -119, 198, -91, -45, 103, -86, -36, 85, + -11, -86, 133, -87, -52, 109, -140, -7, 59, -122, 57, -43, + -29, 57, -75, -218, 21, 39, -130, -21, 74, -112, -40, 93, + -111, -38, 89, -63, -56, 100, -148, -32, 88, -129, -25, 72, + -126, -32, 78, -132, -15, 55, -87, 9, 10, 190, -58, 34, + -36, -31, 53, -140, 41, -22, -103, 81, -90, -133, 38, -21, + -139, 51, -42, -94, -4, 27, -136, -64, 122, -128, -38, 80, + -91, -22, 48, -108, 37, -30, -13, 81, -112, -199, 13, 18, + -104, 55, -58, -90, 68, -83, -50, 40, -48, -25, 89, -125, + 1, 91, -135, 42, 64, -102, 84, 60, -105, 60, 68, -113, + 96, 51, -97, -95, 45, -50, -102, 33, -33, -46, 108, -159, + 68, 72, -125, -33, 84, -128, -29, 28, -39, -132, -44, 93, + -66, -71, 124, -120, -33, 72, -139, -21, 54, -71, -78, 132, + 72, -25, 27, 91, 85, -145, 98, 9, -30, 90, -10, 1, + -70, -93, 155, -18, -17, 29, -92, 29, -29, -109, -42, 80, + -76, -38, 70, 13, -54, 79, 32, -90, 131, 5, -98, 145, + 84, -39, 46, 72, -99, 134, 40, -83, 114, 75, -76, 97, + -8, -64, 92, 19, -48, 65, 63, -79, 100, 137, -58, 59, + 59, -44, 51, -210, 58, -47, -104, -26, 52, -25, -83, 118, + -102, 23, -17, -129, 39, -35, -146, -27, 55, 4, -80, 109, + -47, -11, 21, -127, 39, -37, -147, -12, 32, -140, -28, 53, + -93, -63, 94, -127, -54, 83, -74, -49, 71, -18, -91, 121, + -46, -85, 114, -90, -78, 108, -68, -65, 87, 16, -45, 57, + 47, -36, 41, -117, -21, 35, 128, -38, 39, -230, 4, 9, + -135, -41, 59, -128, -49, 67, -143, -27, 39, -139, -41, 56, + -32, -93, 115, 6, -98, 119, -35, -60, 72, -123, -64, 80, + -144, -29, 37, -135, -47, 56, -12, -90, 106, -152, -52, 60, + -149, 15, -18, -155, 15, -20, -86, 84, -100, -162, -7, 4, + 52, -114, 135, 32, -91, 106, 9, -114, 130, -161, -25, 24, + -133, 4, -10, -139, -10, 5, -111, 74, -90, -151, -18, 12, + -136, -26, 20, -161, -16, 8, -72, -73, 77, 57, -63, 75, + -53, -87, 93, 137, -50, 67, 137, -19, 29, 162, -32, 46, + 100, -45, 55, 119, -19, 27, 91, -75, 85, 133, -37, 45, + -30, -117, 125, 67, -94, 103, 85, -65, 71, 146, -61, 67, + 44, -104, 109, -9, -94, 97, 103, -89, 93, 52, -99, 101, + 23, -57, 57, -115, 142, -145, -71, -3, 2, -22, -109, 110, + -19, -107, 106, 14, -78, 78, -40, -136, 133, -28, -107, 103, + -32, -106, 101, -74, -99, 92, -138, -42, 35, -146, 0, -5, + -143, 33, -37, -142, -16, 8, -151, 34, -42, -139, -3, -6, + -172, -22, 9, -145, 9, -21, -145, 24, -35, -138, 23, -34, + -148, 23, -37, -159, -13, -4, -147, -4, -14, -148, -5, -12, + -141, 50, -67, -128, 15, -31, -139, -42, 21, -62, -79, 67, + -211, -45, 10, -123, -56, 35, -32, -88, 78, 77, -89, 95, + 53, -76, 79, -2, -93, 86, -45, -126, 108, -2, -102, 92, + 2, -115, 103, 22, -108, 99, -27, -115, 98, -8, -54, 45, + -83, -186, 148, -46, -98, 76, -66, -108, 81, -83, -102, 72, + -64, -84, 59, -44, -119, 91, 19, -93, 79, 126, 53, -22, + 61, 39, -23, -122, -131, 87, 47, -63, 58, 109, -10, 26, + -38, -152, 115, -1, -121, 95, -19, -114, 86, -49, -117, 83, + 18, -67, 55, 169, 15, 14, 153, -25, 40, 133, 6, 14, + 142, 54, -22, 157, 13, 10, 84, -19, 25, 121, -86, 80, + 70, -67, 58, 30, -135, 104, 79, -114, 93, 127, -64, 60, + 128, 33, -12, 92, 101, -65, 140, 50, -25, 138, 39, -17, + 123, 56, -33, 151, 11, 3, 151, -8, 16, 148, 11, 0, + 152, -13, 18, 134, 36, -21, 159, -4, 9, 106, 95, -67, + 69, 112, -83, 114, 78, -56, 141, 35, -24, 133, 37, -26, + 39, 115, -89, 58, 119, -92, 90, 88, -69, 131, 65, -52, + 61, 86, -69, -122, 102, -82, -43, 111, -91, 13, 111, -91, + 73, 102, -84, 87, 93, -79, 93, 91, -77, 81, 100, -86, + 77, 60, -52, 88, 121, -106, 134, 42, -40, 147, 33, -32, + 144, 32, -34, 110, 76, -70, 132, 56, -56, 124, 59, -59, + 73, 90, -85, 0, 111, -100, -56, 113, -101, -23, 112, -102, + 34, 91, -87, 120, 73, -76, 120, 69, -72, 103, 22, -29, + 168, -48, 33, 114, 8, -17, 115, -6, -4, 128, -73, 57, + 153, -46, 29, 141, -6, -10, 144, 54, -67, 82, 80, -86, + 112, 69, -80, 121, 50, -63, 145, 31, -49, 99, 69, -81, + 80, 84, -95, 121, 57, -75, 149, -25, 2, 134, -51, 28, + 136, -50, 26, 130, -60, 35, 52, -105, 93, 70, -99, 83, + 55, -106, 91, 69, -75, 59, 122, -75, 47, 102, -99, 73, + 141, -44, 13, 116, -90, 59, 127, -69, 37, 105, -88, 57, + 126, -83, 47, 135, -58, 22, 123, -28, -3, 147, -15, -22, + 126, -70, 33, 105, -88, 52, 132, -70, 28, 155, -24, -19, + 74, -117, 83, 113, -80, 41, 135, -26, -15, 107, -79, 39, + 69, -110, 75, 82, -106, 67, 60, -114, 80, 26, -104, 80, + -78, -77, 86, -23, -114, 101, -26, -99, 88, 115, -56, 13, + 83, 65, -77, 68, 93, -96, 53, 91, -91, -1, 112, -93, + 128, 48, -79, 49, 65, -70, -51, 122, -89, -128, 78, -28, + -125, 71, -24, 8, 117, -104, 39, 103, -103, 86, 76, -94, + 104, -33, -2, 164, -45, -12, 114, -71, 26, 89, -93, 54, + 97, 12, -43, -10, 118, -102, -113, 94, -46, -123, 78, -31, + -144, 57, -5, -133, 65, -17, -139, 59, -10, -143, 42, 4, + -142, 49, -3, -141, 79, -31, 14, 125, -120, -172, 27, 24, + -145, 1, 39, -142, 41, 0, -124, 69, -32, -127, 77, -40, + -115, 84, -50, -80, 101, -77, -62, 107, -87, -76, 104, -82, + -102, 74, -48, -137, 65, -31, -133, 63, -32, -126, 69, -40, + -81, 97, -79, -38, 109, -101, 34, 91, -101, -89, 117, -101, + 60, 86, -102, 128, 30, -60, 109, 51, -79, 144, -3, -31, + 37, -68, 62, 12, -104, 106, 70, -91, 77, 105, -36, 12, + 54, 87, -104, 82, 59, -82, 137, -74, 40, 56, -99, 89, + 72, -97, 79, 123, -77, 46, 1, -51, 51, 118, -122, 90, + 134, -72, 34, 107, -73, 41, 151, -4, -39, 153, -49, 1, + 130, -72, 32, 136, -74, 30, 31, -32, 22, -122, 21, 18, + 213, -65, -5, 139, -55, 9, 144, -73, 23, 103, -35, -1, + 148, -91, 37, 112, -86, 43, 138, -77, 24, -10, -96, 95, + 35, -112, 91, 22, -110, 94, 18, -133, 116, 33, -91, 71, + 140, -97, 36, 114, -81, 32, 83, -104, 62, 88, -88, 45, + 129, -94, 34, 135, -66, 6, 69, -40, 8, -23, -79, 78, + 115, -110, 50, 89, -38, -3, 126, -18, -34, 159, 17, -78, + 142, -3, -56, 130, -29, -28, 119, -85, 22, -228, 24, 75, + -138, 50, 14, -119, -8, 55, -120, -49, 88, -42, -110, 108, + 111, -102, 42, 122, -103, 37, 19, -127, 96, 120, -89, 24, + 113, 33, -72, 102, -109, 47, 63, -49, 12, 89, 76, -98, + 119, -92, 24, 37, 13, -26, -57, 117, -70, -80, 121, -65, + -91, 110, -52, 25, 58, -59, 134, -63, -5, 47, 72, -80, + -121, 89, -23, -21, 73, -53, 144, 21, -80, 128, -70, 4, + 87, -9, -31, -51, 146, -103, -119, 77, -13, -136, 65, 3, + -121, 63, -2, -151, 55, 16, -61, 42, -11, 63, 83, -100, + -9, 85, -71, 85, -38, -2, -133, 153, -80, -101, 103, -51, + -106, 100, -46, -27, 125, -104, 68, 49, -73, 134, -93, 29, + 112, -92, 36, 75, -17, -16, -36, 90, -68, 134, -79, 14, + 41, 11, -28, -67, 96, -59, 113, -7, -44, -169, 116, -33, + 11, 66, -66, 125, 23, -78, 96, 39, -80, 125, 5, -63, + 105, 13, -62, 149, -35, -38, 149, -29, -43, 116, -76, 15, + 140, 11, -79, 28, -41, 24, -103, -68, 116, 35, -72, 52, + 96, 112, -154, 98, 57, -105, 75, 70, -106, 56, 82, -109, + 128, 13, -81, 127, 12, -79, 112, -18, -44, 95, 62, -113, + -145, 71, 8, -141, 52, 25, -122, 78, -13, -72, 105, -68, + -105, 106, -53, -118, 86, -27, -5, 75, -75, 43, 77, -102, + -37, 120, -108, 39, 89, -115, 102, 41, -100, -33, 122, -114, + -32, 111, -104, -30, 100, -95, 3, 95, -108, 22, 84, -107, + 160, 5, -96, -13, 108, -117, -43, 104, -96, -38, 95, -89, + 72, 25, -71, 82, 100, -168, 27, 90, -125, 11, 88, -114, + 111, 33, -107, 76, 31, -85, 88, 25, -87, -59, 90, -76, + -21, 26, -20, 98, -112, 81, 108, -71, 21, 69, -16, -24, + -180, -4, 118, -23, -14, 31, 114, -65, 10, 158, -67, -16, + 132, -5, -78, 125, 10, -94, 134, -33, -47, 47, -66, 51, + -99, -45, 120, -80, -55, 119, -12, -79, 103, 182, -57, -48, + 134, -44, -36, 78, -102, 70, 37, -104, 100, 148, -59, -29, + 89, 44, -113, 40, 79, -121, 101, 33, -110, 79, 41, -105, + 65, 56, -115, 144, -23, -75, 92, 32, -108, -42, 108, -105, + -159, 7, 107, -90, -33, 108, -132, 55, 25, -118, 90, -29, + -103, 98, -51, -28, 90, -95, 70, 20, -75, 80, 89, -172, + 92, 41, -119, 84, 19, -87, 107, 13, -98, 85, 61, -144, + 62, 52, -118, 125, 7, -107, 86, 30, -108, 72, 14, -78, + 154, -9, -111, -4, -62, 89, -80, -44, 124, -41, -57, 111, + -114, -27, 126, -13, -39, 63, 115, -63, -7, 145, -69, -22, + 8, -33, 38, -49, -42, 94, -32, -19, 49, -4, -135, 179, + 30, -76, 74, -119, -11, 106, -110, 8, 72, 26, -75, 74, + 162, -54, -53, 120, -86, 15, 134, -31, -63, 127, -64, -19, + 133, -52, -41, 132, -45, -49, 131, -71, -18, 131, -76, -11, + 128, -82, -5, 130, -75, -16, 137, -72, -27, 125, -50, -44, + 131, -43, -60, 125, -75, -16, 123, -73, -18, 94, -109, 49, + 99, -108, 43, 72, -113, 72, -6, -94, 117, -37, -74, 120, + -73, -52, 124, -70, -54, 122, -89, -43, 125, -122, 14, 87, + -132, 33, 71, -112, -8, 101, -98, -33, 116, -106, -14, 99, + -136, 29, 75, -115, 31, 55, -132, 22, 76, -126, 63, 27, + -119, 4, 84, -114, 25, 57, -133, 114, -27, -108, -4, 81, + -131, 31, 60, -111, 101, -33, -88, 5, 57, -112, -20, 99, + -128, 7, 80, -130, 7, 80, -127, 2, 81, -101, -39, 109, + -106, -35, 104, -82, -52, 107, -80, -62, 115, -85, -56, 112, + -46, -79, 108, -112, -35, 103, -136, 22, 59, -130, 13, 63, + -131, -5, 82, -136, 18, 59, -107, -21, 81, 65, -99, 62, + 120, -47, -21, 86, -22, -27, -177, -28, 128, -37, -77, 95, + -126, -30, 99, -132, 3, 68, -125, 14, 53, -140, -26, 99, + -120, 26, 36, -121, -25, 86, -74, -77, 110, -52, -90, 110, + 18, -115, 97, 63, -74, 37, 134, 27, -91, 87, -35, -12, + -6, -95, 91, 120, -127, 55, 1, -112, 100, 34, -86, 60, + -158, 38, 45, 42, -116, 82, 178, -55, -41, 144, -64, -17, + 24, -119, 91, 90, -110, 49, 95, -87, 25, -4, -78, 69, + 140, 2, -75, 128, 11, -77, 27, -34, 14, -66, -60, 87, + -90, -34, 75, 184, -9, -90, 135, 38, -104, 151, -52, -39, + 91, -55, -3, 109, -105, 27, 139, -47, -38, 111, 10, -72, + 124, 27, -95, 56, 55, -80, -20, 119, -91, 42, 74, -89, + 136, -10, -73, 133, -37, -48, 139, -57, -36, 133, -59, -31, + 117, -98, 11, 130, -69, -22, 125, 1, -82, 110, 25, -93, + 116, 15, -90, 91, 52, -107, 48, 96, -119, 61, 81, -114, + 103, 26, -94, 133, -55, -43, 129, -24, -70, 42, 57, -82, + 118, 50, -132, 58, -114, 63, -48, -95, 121, 81, -123, 53, + 13, -114, 92, 40, -113, 72, 91, -122, 41, 36, -120, 78, + 75, -122, 50, -4, -99, 87, -24, -99, 101, 12, -122, 93, + -4, -114, 97, -9, -114, 98, 1, -113, 91, 2, -125, 97, + 1, -114, 89, 20, -125, 83, 9, -123, 88, -6, -117, 93, + -27, -109, 100, -52, -94, 105, -86, -64, 105, -114, -26, 95, + -130, -8, 92, -97, -4, 66, -89, -7, 62, -155, 22, 83, + 50, -167, 88, 34, -111, 55, + +/* 1 */ +2737, 1, -14284, 23878, -11217, + -82, -105, -117, -15, 25, 72, -60, -31, 10, -79, -19, 62, + 9, 110, 225, -46, -61, -72, -154, -85, 22, 40, 7, -38, + 54, -36, -148, 1, -47, -99, -122, -119, -90, -97, 31, 190, + 25, -21, -77, -3, -73, -146, -91, -31, 55, 11, -36, -89, + -159, -97, 12, -70, -4, 82, -94, 2, 131, -118, -56, 45, + -43, 51, 167, -40, -46, -43, 34, -54, -159, -75, -37, 27, + -59, 19, 122, -93, -16, 98, 60, 99, 126, -21, -11, 5, + -93, -116, -113, -75, 5, 120, -18, -24, -28, -75, -101, -104, + -108, -75, 1, -89, -3, 123, 55, 85, 101, -32, -19, 6, + -123, -105, -42, -7, -27, -46, -43, -47, -35, -81, 17, 159, + -116, -60, 49, -40, -57, -60, -105, -66, 22, -127, -79, 29, + -105, -95, -35, -124, -106, -28, -98, -74, 1, -88, -112, -92, + -92, -106, -71, 18, -79, -186, 29, 58, 71, 40, 78, 93, + 80, 93, 65, 18, -7, -42, -45, -114, -161, 40, 41, 20, + 30, 80, 115, 96, 95, 47, 95, 26, -94, 91, 7, -122, + 101, 19, -114, 137, 43, -116, -52, -83, -87, -118, -92, -9, + -117, -93, -10, -108, -96, -29, -143, -117, -12, -135, -130, -48, + -50, -79, -75, -157, -56, 130, 47, -16, -100, -29, -66, -80, + -93, -105, -58, -83, -98, -54, -84, -112, -77, -75, -105, -78, + -91, -115, -68, -70, -99, -70, -81, -109, -68, -79, -107, -67, + -72, -119, -97, -41, -94, -95, -65, -112, -90, -101, -106, -26, + -87, -112, -55, -110, -104, -6, -98, -108, -29, -104, -110, -19, + -75, -117, -75, -84, -126, -70, -25, -76, -80, -75, -126, -82, + -115, -95, 27, -115, -90, 35, -103, -111, -12, -80, -119, -56, + -97, -117, -25, -103, -98, 10, -115, -91, 43, -161, -129, 59, + -58, -77, -21, -114, -71, 74, -7, 56, 92, -67, 27, 148, + -90, -7, 134, 1, -10, -18, 84, 0, -134, 22, -52, -112, + -131, -135, 12, 72, 27, -74, -56, -101, -58, -97, -115, -11, + -110, -72, 74, -100, -74, 55, -42, -104, -80, -100, -122, -9, + -113, -93, 54, -106, -102, 31, -103, -87, 50, -115, -98, 55, + -100, -98, 32, -86, -121, -19, -91, -125, -18, -92, -40, 104, + -84, -16, 124, -85, -18, 123, -114, -81, 90, -91, -59, 81, + -80, -14, 125, -100, -90, 58, -75, -40, 83, -109, -75, 98, + -100, -79, 80, -101, -100, 50, -88, -122, -1, -77, -103, 4, + -104, -135, 15, -99, -113, 37, -104, -118, 43, -74, -117, -13, + -98, -106, 51, -92, -124, 16, -93, -102, 52, -101, -150, 3, + -74, -80, 45, -85, -138, -7, -88, -117, 27, -92, -81, 86, + -90, -67, 101, -91, -76, 95, -94, -102, 67, -88, -91, 72, + -88, -94, 70, -71, -130, -14, -61, -137, -44, -62, -124, -21, + 22, -4, -54, 54, 10, -108, 83, 17, -158, -35, -68, -8, + -90, -85, 87, -88, -108, 61, -83, -64, 101, -84, -69, 103, + -95, -84, 110, -62, 13, 159, -81, -98, 64, -88, -89, 95, + -79, -62, 109, -79, -94, 70, -115, -182, 49, -40, -70, 8, + -56, -132, -30, -56, -147, -45, -58, -85, 38, -92, -109, 97, + -89, -97, 105, -69, -68, 91, -77, -78, 102, -78, -94, 87, + -77, -89, 95, -74, -86, 91, -73, -123, 44, -75, -139, 31, + -41, 7, 123, -3, 91, 124, 38, 129, 60, 75, 109, -70, + 75, 120, -54, 66, 92, -61, 83, 66, -140, 48, 13, -114, + 74, 106, -59, 56, 136, 28, 68, 124, -18, 78, 115, -53, + 78, 123, -40, 83, 113, -65, 70, 128, -8, 74, 133, -10, + 74, 120, -22, 75, 71, -94, 55, 56, -62, 78, 120, -30, + 84, 100, -69, 88, 119, -51, 85, 86, -87, 76, 126, -10, + 83, 133, -13, 79, 83, -72, 96, 128, -46, 82, 80, -79, + 92, 121, -43, 91, 103, -61, 91, 88, -82, 90, 83, -87, + 94, 102, -64, 81, 122, -5, 74, 130, 21, 83, 131, 7, + 86, 113, -25, 72, 131, 35, 103, 170, 26, -42, -12, 72, + -90, -65, 101, -91, -42, 139, -45, 4, 109, -93, -93, 68, + -88, -49, 130, -71, -79, 43, -66, -126, -37, -88, -117, 29, + -87, -114, 34, -86, -133, 7, -87, -114, 37, -89, -115, 45, + -78, -97, 45, -90, -131, 29, -89, -101, 72, -91, -113, 60, + -85, -83, 93, -88, -111, 61, -89, -78, 117, -60, -23, 123, + -62, -104, 9, -85, -141, 17, -80, -87, 88, -82, -66, 126, + -85, -125, 47, -58, -24, 127, -98, -125, 90, -43, -84, -3, + -31, -134, -109, -78, -137, 23, -52, 0, 150, -18, -42, -12, + -34, -42, 39, -63, -65, 90, -117, -117, 174, -58, -89, 46, + -45, -70, 33, -105, -136, 122, -37, -55, 33, -72, -83, 102, + -71, -86, 103, -73, -100, 85, -72, -113, 67, -73, -107, 82, + -68, -107, 68, -78, -110, 101, -63, -90, 83, -67, -112, 64, + -64, -137, 21, -59, -136, 6, -69, -126, 60, -67, -105, 87, + -57, -153, -18, -21, -129, -108, -53, -103, 46, -5, -91, -114, + -25, -98, -42, -62, -133, 40, -65, -120, 71, -63, -107, 87, + -66, -113, 89, -52, -66, 109, -55, -54, 138, -55, -69, 119, + -56, -76, 116, -58, -103, 90, -59, -114, 86, -51, -59, 131, + -48, -48, 134, -45, -43, 137, -43, -37, 139, -32, -3, 142, + -47, -65, 124, -54, -103, 99, -49, -79, 115, -50, -83, 118, + -44, -63, 129, -41, -47, 137, -41, -53, 136, -44, -59, 143, + -42, -72, 116, -33, -27, 146, -32, -30, 145, -35, -40, 142, + -45, -93, 116, -43, -58, 172, -33, -60, 113, -35, -67, 116, + -25, -17, 150, -27, -27, 146, -35, -66, 134, -29, -40, 149, + -14, 9, 148, 0, 52, 139, 1, 54, 142, 0, 51, 145, + 11, 80, 128, 5, 56, 134, -7, 7, 104, -26, -55, 123, + -30, -59, 172, 25, 62, -90, -7, -4, 85, -32, -82, 117, + -35, -95, 120, -33, -91, 116, -33, -94, 112, -43, -128, 158, + -22, -72, 54, -33, -106, 101, -32, -104, 104, -30, -96, 111, + -27, -92, 117, -24, -81, 124, -20, -65, 134, -12, -33, 146, + -1, 3, 152, -6, -14, 149, -13, -53, 140, -16, -63, 136, + -17, -71, 124, -4, -20, 157, -8, -44, 143, -16, -86, 237, + 2, 3, 72, -4, -32, 105, 5, -2, 175, 27, 99, 105, + 3, -12, 139, -35, -165, 74, -8, -14, -108, -21, -95, 14, + -16, -90, 97, -16, -92, 106, -13, -92, 128, -18, -108, 97, + -21, -122, 85, -15, -103, 109, -11, -92, 117, -12, -98, 114, + -25, -149, 52, -21, -128, 50, -23, -111, -36, -27, -130, -35, + -19, -140, 74, -1, -63, 128, -5, -97, 143, 22, 71, 115, + 17, 158, -124, 7, 2, 79, -3, -81, 127, -16, -132, 72, + -7, -90, 90, 6, -49, 148, 2, -72, 134, -2, -92, 118, + -17, -140, 51, -24, -136, -28, 4, -85, 148, 17, 108, -1, + 10, -4, 92, -12, -118, 54, -7, -129, 92, 8, 23, 39, + 24, 62, 114, 18, 5, 136, 11, -45, 124, 18, -43, 173, + -3, -104, 84, -4, -117, 78, 30, 28, 174, -1, -120, 95, + -10, -143, 56, 23, -13, 155, 31, 74, 126, 32, 74, 128, + 6, 141, -78, -2, 111, -104, 18, 127, 0, 33, 54, 142, + 39, 100, 135, 29, 124, 58, 32, 80, 105, 47, 60, 198, + 4, -59, 69, 13, -90, 141, 5, -141, 131, 23, -19, 127, + 16, -116, 158, -24, 23, -131, -39, -129, -98, -13, -148, 42, + 0, -121, 77, 6, -115, 99, 11, -107, 115, -4, -121, 54, + 10, -111, 107, -14, -160, 19, -15, -129, -3, 2, -130, 72, + -31, -136, -76, -5, -116, 28, -12, -155, 12, -7, -162, 32, + -14, -141, -11, -15, -186, -2, 11, -98, 78, -2, -105, 25, + -26, -135, -79, -24, -112, -78, -30, -150, -95, -16, -111, -47, + -23, -93, -86, -30, -35, -138, -33, -39, -151, -22, -114, -85, + -4, -170, 15, -36, -101, -166, 6, -160, 53, -17, -111, -74, + -27, -53, -138, -33, -65, -171, -21, -26, -112, -24, -93, -125, + 1, -170, 15, -4, -145, -17, -14, -124, -84, -18, -110, -108, + 4, -151, 15, -15, -138, -98, -21, -80, -137, 8, -155, 32, + 2, -150, -16, 10, -154, 35, -6, -140, -71, 7, -91, 21, + 24, -76, 129, 28, -94, 141, 22, 97, 153, 13, 20, 77, + -5, 164, 11, 3, -13, 11, 10, -156, 22, 6, -135, 2, + -1, -144, -50, -6, -131, -75, -20, -69, -134, -14, -89, -119, + -15, -91, -122, -8, -112, -98, -8, -113, -101, -4, -122, -85, + 10, -152, -16, 26, -152, 82, 12, -139, -4, 26, -119, 99, + 20, -144, 37, -9, -86, -115, 19, -129, 32, 29, -83, 126, + 30, -70, 132, 30, -70, 131, 31, -83, 122, 30, -119, 87, + 30, -120, 86, 29, -138, 56, 30, -135, 62, 32, -123, 80, + 35, -102, 104, 32, -130, 70, 34, -129, 73, 31, -145, 41, + 33, -133, 55, 35, -126, 67, 35, -143, 52, 34, -138, 43, + 34, -136, 49, 39, -127, 69, 40, -127, 74, 39, -131, 62, + 35, -144, 26, 46, -102, 113, 43, -120, 78, 39, -154, 26, + 42, -114, 73, 47, -116, 90, 44, -128, 64, 45, -127, 64, + 46, -124, 66, 47, -125, 70, 32, -162, -34, 15, -96, -38, + 48, -136, 50, 50, -120, 77, 51, -121, 72, 52, -85, 116, + 53, -104, 93, 55, -111, 91, 50, -94, 90, 54, -68, 124, + 54, -71, 122, 54, -71, 118, 54, -75, 114, 59, -82, 116, + 53, -47, 133, 55, -66, 118, 60, -66, 129, 57, -55, 126, + 58, -60, 126, 62, -96, 97, 62, -79, 113, 62, -62, 126, + 61, -93, 91, 56, -133, 35, 68, -87, 114, 65, -89, 101, + 68, -87, 104, 68, -103, 91, 47, -147, -14, 53, -143, 3, + 53, -141, 2, 58, -139, 15, 55, -139, 6, 49, -143, -17, + 42, -138, -35, 50, -147, -23, 58, -138, 5, 61, -139, 10, + 44, -134, -32, 44, -140, -45, 43, -137, -41, 49, -141, -37, + 47, -137, -36, 36, -137, -72, 4, -78, -87, 62, -138, -4, + 62, -111, 29, 43, -131, -51, 56, -141, -31, 53, -137, -36, + 62, -135, -10, 70, -132, 13, 55, -134, -36, 24, -110, -90, + 60, -137, -28, 66, -138, -14, 54, -127, -37, 51, -134, -57, + 52, -134, -60, 44, -117, -56, 66, -137, -28, 34, -115, -84, + 57, -129, -48, 59, -132, -46, 44, -120, -73, 40, -123, -92, + 76, -129, 1, 84, -125, 28, 71, -130, -20, 57, -123, -54, + 26, -100, -104, 50, -118, -71, 75, -131, -20, 78, -129, -10, + 82, -129, -3, 84, -130, 0, 76, -123, -14, 81, -130, -13, + 78, -119, -7, 63, -121, -55, 51, -118, -89, 76, -125, -31, + 81, -125, -19, 43, -108, -100, 57, -117, -78, 74, -121, -44, + 72, -124, -53, 64, -118, -69, 46, -103, -94, 51, -109, -97, + 72, -117, -50, 55, -110, -92, 78, -122, -50, 65, -122, -96, + 42, -82, -70, 87, -130, -52, -11, -41, -145, 71, -110, -56, + 88, -116, -17, 100, -112, 30, 85, -119, -42, 110, -137, -12, + 83, -92, 18, 105, -118, 19, 87, -110, -27, 73, -111, -74, + 42, -78, -86, 70, -110, -90, 89, -116, -50, 78, -111, -71, + 81, -108, -55, 107, -116, 5, 98, -91, 49, 47, -47, 10, + 69, -38, 112, -33, 70, 110, 20, 15, 109, 40, 7, 146, + 39, -52, -29, 21, -74, -152, 88, -69, 71, 102, -105, 9, + -32, 12, -66, 53, -66, -33, 28, -44, -43, 94, -112, -47, + 75, -89, -41, 70, -106, -108, 126, -123, 13, 50, -68, -58, + 89, -110, -76, 128, -91, 118, 48, -36, 35, 74, -96, -84, + 22, -62, -139, 38, -66, -102, 120, -94, 70, -19, -6, -83, + 92, -105, -67, 61, -77, -71, 103, -112, -62, -4, 21, 62, + 25, -27, -11, 74, -103, -134, -90, 77, -19, -51, 13, -130, + -21, 37, 64, -80, 80, 25, -44, 10, -122, 44, -71, -113, + 41, -65, -111, 30, -57, -118, 108, -124, -107, -26, 30, 28, + -11, 46, 149, 33, -26, 18, 109, -71, 111, 32, 2, 123, + 146, -121, 40, 31, -60, -127, 123, -103, 21, -19, -7, -94, + 48, -45, -14, 52, -14, 131, -16, 48, 132, 35, -25, 24, + 100, -72, 57, 2, -6, -18, 65, -58, -7, -43, 11, -101, + -43, 2, -143, -44, 18, -81, 26, -28, -22, 126, -84, 98, + 86, -86, -53, 59, -67, -71, 102, -98, -55, 133, -113, -8, + -71, 88, 125, 73, -62, -12, 133, -103, 28, -27, 12, -39, + 13, -32, -97, 94, -71, 26, 76, -69, -33, -28, -4, -118, + 59, -52, -18, 106, -64, 89, 107, -88, -18, -26, 53, 148, + 61, -54, -29, 50, -69, -132, 110, -78, 34, 122, -91, 11, + 92, -73, -12, 130, -91, 31, -52, 53, 65, 66, -47, 7, + -52, 53, 66, 23, 7, 102, -112, 74, -45, 38, -13, 69, + 134, -90, 44, 89, -78, -45, 112, -96, -59, -31, 26, 10, + -113, 88, 22, 12, -22, -60, 2, -18, -69, -59, 11, -148, + 42, -39, -34, 135, -106, -30, 21, 12, 126, 27, -17, 10, + 85, -83, -96, 93, -63, 20, -42, 51, 94, -94, 85, 72, + 7, 23, 125, 76, -8, 204, 2, -26, -102, 5, -42, -169, + 9, -32, -114, 115, -92, -38, 123, -74, 55, -78, 77, 97, + -23, 34, 76, -7, 36, 136, -20, 50, 149, 82, -53, 22, + 44, -63, -128, 86, -89, -121, -26, 22, 12, -49, 18, -70, + 6, -27, -100, 132, -79, 61, 88, -39, 99, 69, -15, 139, + -71, 73, 99, -116, 90, 37, -104, 92, 74, -99, 90, 83, + 5, 32, 137, 1, 38, 148, -20, 47, 123, -14, 45, 125, + 95, -22, 171, -112, 84, 9, -125, 85, -23, -110, 50, -111, + -1, 15, 51, -48, 55, 71, -148, 108, -12, -55, 45, 13, + -91, 92, 75, -78, 87, 93, -27, 69, 159, -102, 65, -46, + -35, 39, 38, 6, 7, 38, 119, -74, 59, 7, 39, 145, + -78, 89, 88, -121, 116, 62, -72, 75, 55, -57, 83, 110, + -42, 75, 123, -14, 59, 137, -12, 60, 141, -26, 71, 141, + -86, 88, 46, -35, 49, 54, -61, 88, 101, -106, 102, 32, + -94, 46, -87, -71, 11, -132, -100, 51, -95, -112, 74, -64, + -114, 76, -62, -113, 99, -4, -86, 99, 63, -59, 91, 102, + -56, 92, 108, -33, 77, 122, 13, 41, 135, 13, 50, 154, + 64, -2, 138, -71, 86, 50, -44, 95, 131, -71, 99, 77, + -89, 105, 50, -103, 109, 26, -50, 96, 109, -34, 84, 116, + 19, 58, 165, -54, 43, -20, -122, 78, -88, -13, 80, 145, + 91, -47, 90, 102, -80, 41, 33, 37, 145, -76, 109, 74, + -106, 110, 11, -67, -7, -152, 51, -78, -57, -81, 27, -112, + -102, 62, -85, -106, 89, -36, -85, 112, 55, -97, 108, 19, + -104, 112, 10, -72, 119, 88, 32, 6, 83, 99, -47, 112, + 96, -45, 110, 98, -50, 100, 70, -3, 136, 57, 13, 137, + 25, 48, 139, -10, 97, 164, -71, 84, 20, -106, 119, 17, + -69, 116, 77, -22, 75, 93, -107, 151, 65, -80, 71, -28, + -100, 134, 43, 73, -19, 108, 89, -23, 125, 71, 2, 135, + 67, 8, 133, 61, 18, 139, 59, 21, 137, 60, 21, 139, + 54, 30, 138, 56, 27, 137, 46, 40, 139, 49, 38, 138, + 37, 51, 136, 27, 61, 134, -22, 95, 103, -38, 107, 95, + -5, 91, 122, -23, 103, 109, -22, 103, 110, -48, 112, 79, + -99, 139, 38, -86, 39, -79, -116, 84, -65, -94, 116, 7, + -35, 112, 95, -55, 108, 58, -109, 97, -44, -109, 73, -75, + -105, 60, -90, -107, 62, -89, -101, 101, -33, -41, 95, 58, + -75, 122, 35, -89, 122, 11, -55, 126, 71, -28, 108, 90, + -10, 89, 92, -87, 138, 28, 20, -14, 15, 86, -125, -14, + 12, -97, -99, 32, -109, -85, 58, -122, -60, 84, -122, -19, + 107, -98, 46, 108, -95, 52, 83, -34, 87, 77, 5, 127, + 98, -51, 88, 106, -66, 79, 105, -49, 97, 89, -24, 103, + 62, 42, 144, 98, -20, 117, 104, -36, 107, 68, 23, 123, + 43, 86, 165, 42, 31, 94, 18, 89, 130, -10, 106, 107, + -20, 110, 97, 4, 95, 113, 20, 86, 122, 19, 88, 121, + -6, 105, 106, -26, 118, 91, -35, 122, 83, -14, 135, 121, + -51, 89, 26, -45, 147, 90, -17, 105, 83, 32, 78, 118, + 16, 95, 113, -14, 129, 106, -26, 123, 83, -61, 122, 38, + 42, -16, 37, 134, -47, 122, 53, -93, -21, 27, -119, -79, + -15, -103, -116, -2, -92, -91, 6, -109, -100, -23, -73, -99, + -55, -129, -200, 39, 25, 75, 46, 69, 127, 31, 84, 122, + 22, 92, 117, 14, 99, 113, 2, 108, 105, -1, 111, 102, + -7, 115, 97, -24, 123, 84, -19, 123, 88, -8, 117, 95, + 5, 111, 102, 13, 106, 107, 27, 95, 113, 43, 82, 118, + 21, 114, 119, 4, 99, 85, -34, 135, 71, -55, 131, 42, + -48, 132, 50, -33, 119, 55, -80, 153, 26, -57, 132, 36, + -77, 147, 23, -26, 152, 83, 18, 104, 96, -83, 84, -33, + 22, 52, 63, 66, 23, 90, 55, 87, 123, -8, 77, 44, + 53, 100, 128, 67, 63, 116, 61, 84, 123, 32, 97, 99, + 66, 73, 118, 83, 76, 136, 58, 56, 97, 94, 28, 114, + 101, 10, 109, 51, 99, 114, 61, 66, 101, 101, 33, 121, + -18, 61, 19, 12, 97, 70, 85, 9, 89, 142, -3, 135, + 92, -23, 75, 109, 26, 118, 4, 103, 64, 53, -40, 26, + 106, -50, 70, 106, 13, 105, 135, -4, 121, 36, 89, 83, + -19, 132, 57, 57, 96, 104, 91, 54, 110, 89, 56, 108, + 8, 109, 65, -51, 142, 30, -6, 136, 66, 15, 129, 79, + 45, 101, 90, 54, 101, 97, 10, 143, 78, 26, 122, 80, + 19, 122, 75, 61, 99, 96, 11, 134, 71, -41, 143, 31, + -38, 144, 32, -18, 141, 47, 7, 137, 65, 45, 118, 87, + 69, 99, 99, -24, 139, 36, -31, 146, 34, -4, 140, 52, + -7, 144, 50, 2, 141, 56, 7, 139, 57, -12, 143, 43, + -50, 145, 12, -40, 145, 19, -35, 154, 24, -35, 137, 19, + -3, 147, 46, -21, 153, 33, -42, 129, 7, -23, 129, 22, + 28, 139, 65, 8, 208, 68, 46, 83, 61, 97, -111, 45, + 87, 20, 76, 63, 112, 81, 48, 122, 72, 52, 121, 74, + 41, 130, 66, 39, 174, 76, 18, 127, 46, 55, 111, 70, + 62, 93, 70, 67, 111, 76, 94, 80, 89, 88, 82, 83, + 59, 118, 70, 70, 109, 75, 44, 143, 63, 93, 85, 84, + 68, 113, 72, 59, 123, 66, 38, 135, 53, 31, 139, 47, + 24, 142, 43, 19, 142, 38, -15, 166, 17, 8, 111, 24, + -25, 186, 11, -31, 118, -3, -35, 149, -4, -55, 165, -16, + -29, 123, -4, -40, 145, -9, -46, 144, -16, -72, 130, -36, + -113, 64, -74, -124, 19, -87, -121, -17, -90, -123, 1, -91, + -112, 45, -78, -117, 47, -84, -94, 97, -60, -111, 64, -79, + -94, 98, -62, -98, 95, -68, -86, 113, -57, -90, 120, -61, + -99, 69, -73, -99, 88, -72, -100, 83, -74, -103, 76, -80, + -113, 73, -87, -98, 73, -77, -108, 42, -88, -118, 12, -99, + -115, -23, -100, -115, -17, -100, -105, -27, -95, -117, 27, -101, + -118, 59, -101, -105, -19, -97, -110, 42, -96, -97, 69, -86, + -102, 62, -90, -110, 46, -100, -99, -47, -97, -101, -35, -98, + -144, -109, -146, 30, 126, 37, -70, 5, -68, -40, -97, -44, + -29, -148, -39, -81, -122, -89, -4, 36, -2, 10, 141, 21, + 23, 149, 32, 47, 139, 54, -84, -1, -82, 4, 58, 8, + 38, 136, 43, -76, 114, -69, -80, 101, -76, -117, -33, -119, + -63, 103, -60, -92, 70, -92, -80, 35, -80, -91, 62, -93, + -80, 22, -83, -107, 62, -112, -91, 64, -95, -96, 57, -102, + -92, 3, -100, -109, -4, -119, -103, -28, -114, -58, -151, -69, + -40, -110, -48, -31, -140, -40, -71, -3, -80, -78, -95, -94, + -74, -89, -88, -61, -107, -77, -35, -140, -49, -49, -142, -67, + -8, 45, -6, 27, 146, 41, -11, 182, -3, -108, -34, -129, + -85, 58, -97, -100, -67, -124, -82, 76, -95, -35, 121, -38, + -39, 139, -42, -18, 138, -18, -35, 60, -41, -75, -100, -96, + -72, -75, -92, -89, -73, -116, -81, -77, -106, -90, -15, -115, + -108, 19, -141, 15, 41, 22, 86, 61, 114, 90, 27, 116, + 54, 124, 74, 29, 135, 40, 46, 136, 61, 54, 108, 70, + 44, 138, 56, 79, 87, 98, 81, 81, 99, 66, 113, 79, + 54, 127, 64, 66, 111, 77, 74, 98, 87, 38, 125, 41, + -10, 148, -18, -71, 91, -89, -95, 37, -116, -79, 135, -104, + -8, 130, -18, -29, 131, -44, -26, 148, -43, -27, 146, -45, + -8, 150, -25, -12, 170, -31, -13, 127, -30, -76, 142, -112, + -17, -116, -7, -29, 21, -40, -33, 100, -52, -62, 104, -92, + -42, 110, -68, -74, 78, -106, -59, 106, -93, -64, 99, -98, + -62, 101, -98, -85, 40, -118, -83, 41, -120, -78, 70, -117, + -92, -113, -107, 13, 75, 6, -27, 103, -55, -85, 32, -124, + -84, 27, -123, -92, 9, -133, 5, -52, 17, -12, -14, -15, + -72, 37, -110, -84, 23, -126, -93, -75, -123, -62, 2, -93, + -78, 42, -123, -79, 22, -125, -86, 9, -132, -73, -172, -81, + 5, 71, -6, 11, 147, -11, -52, 116, -104, -49, 62, -89, + -48, 105, -98, -54, 96, -109, -76, 39, -129, -88, -164, -108, + 4, 91, -13, 40, 143, 32, 24, 150, 3, -30, 139, -84, + -38, 97, -87, -44, 104, -101, -49, 91, -107, -75, 77, -148, + -49, 45, -97, -46, 96, -108, -70, 41, -135, -72, -32, -118, + -78, 7, -140, -62, -56, -95, -93, 37, -181, 48, 34, 77, + 55, 90, 71, 51, 161, 41, 60, 100, 74, -5, 115, -47, + -58, 47, -122, -61, 111, -152, -68, -37, -112, -75, 67, -165, + -43, -6, -79, -24, 130, -97, -84, -17, -155, 39, 43, 60, + -32, 126, -112, 46, 78, 58, 69, -5, 135, 113, 64, 189, + -45, 17, -93, -69, 17, -138, -69, -5, -131, -72, -8, -139, + -69, -22, -127, -73, -3, -146, -96, -25, -187, 55, -46, 133, + -45, -34, -77, -78, -48, -142, -59, -65, -96, -58, -56, -98, + -75, -29, -148, -55, 34, -134, -65, 54, -168, -32, 40, -88, + -19, 117, -96, -47, 41, -126, -62, -2, -141, -61, -9, -138, + -62, -27, -135, -61, -16, -139, -63, -22, -142, -52, 18, -139, + -9, 126, -86, 14, 107, -19, -7, 131, -88, -34, 82, -132, + -45, 40, -138, -47, 25, -139, -55, 1, -146, -5, 123, -88, + 16, 145, -43, -25, 62, -110, -54, -104, -83, -14, -134, 43, + 52, -49, 173, -47, -52, -98, -47, -65, -90, -57, -52, -131, + -57, -30, -142, -56, -64, -123, -64, -68, -148, -41, -115, -55, + -17, -148, 36, 2, -128, 81, 6, -128, 89, -7, -136, 51, + -30, -157, -7, -49, -116, -86, -54, -49, -133, -19, 85, -101, + -1, 110, -64, -7, 78, -63, 12, 153, -47, 46, 132, 68, + 50, 119, 81, 43, 124, 58, 16, 167, -52, 6, 94, -42, + -2, 123, -85, 31, 130, 12, 57, 46, 143, 54, 68, 114, + 55, 123, 81, 5, 134, -75, -47, 48, -173, -55, -74, -113, + -45, -45, -111, -50, -139, -57, -54, -73, -119, -53, -57, -131, + -53, -86, -113, -53, -88, -111, -47, -29, -139, -41, 9, -146, + -38, 13, -143, -42, -130, -52, -56, -133, -106, 16, 67, 9, + 3, 32, -10, -31, 46, -148, -42, -55, -114, -50, -104, -112, + -52, -113, -113, -41, -143, -52, -19, -114, 8, -35, -159, -27, + -32, -151, -22, -37, -31, -124, -40, -96, -98, -40, -127, -78, + -43, -93, -113, -49, -103, -139, -12, -141, 39, -22, -159, 8, + -9, 38, -65, -2, 110, -77, -9, 111, -113, -9, 99, -111, + -10, 92, -110, -5, 113, -106, -13, 81, -127, -20, 55, -141, + -23, 35, -141, -27, 26, -157, -18, 35, -127, -27, 18, -160, + -38, -89, -123, -29, -61, -106, -36, -68, -143, -31, -46, -140, + -33, -79, -124, -30, -56, -136, -25, -11, -150, -11, 129, -209, + -18, -47, -75, -10, 63, -142, 9, 100, -57, 9, 124, -89, + -3, 84, -129, 4, 98, -107, 6, 103, -98, 9, 118, -105, + 13, 124, -83, 18, 133, -63, 13, 113, -80, 23, 146, -59, + 32, 130, 58, 29, 134, 2, 28, 135, -4, 30, 125, 26, + 40, 177, 11, -14, -74, 22, 3, -8, 43, 37, 164, -3, + 32, 145, -17, 33, 147, -10, 38, 143, 23, 39, 142, 37, + 40, 122, 78, 37, 136, 18, 31, 148, -65, 21, 67, 28, + 27, 99, 5, 10, 99, -155, -12, 15, -146, 12, 76, -78, + 24, 96, -28, 9, 95, -179, -9, -1, -93, 5, 66, -146, + -17, -17, -142, -16, -12, -151, 0, 38, -139, -11, -10, -126, + -32, -73, -156, -11, -9, -146, -12, -11, -150, -3, 19, -151, + -2, 20, -165, 0, 19, -147, -25, -71, -125, 2, 20, -131, + 3, 24, -133, 15, 62, -139, 42, 140, 100, 43, 133, 129, + 22, 72, 40, 43, 138, 34, 42, 140, -20, 48, 151, 22, + 43, 136, 8, 46, 136, 47, 44, 137, -24, 14, 50, -76, + 55, 155, 85, -22, -70, 55, -42, -135, 73, 9, 23, 49, + 49, 140, 37, 50, 141, 46, 56, 160, 19, 50, 140, 9, + 50, 140, 17, 30, 77, 27, 51, 137, 29, 47, 116, 83, + 43, 100, 105, 50, 121, 77, 51, 128, 19, 46, 126, -58, + 6, 36, -160, -18, -34, -104, 4, 27, -143, 6, 31, -179, + -9, -13, -122, -18, -37, -144, -21, -45, -141, -12, -24, -148, + -8, -18, -150, -12, -28, -147, -22, -58, -137, -43, -113, -113, + -43, -114, -41, -53, -142, -13, -54, -145, -2, -43, -119, -51, + -43, -124, -61, -48, -137, -39, -32, -98, -113, -33, -105, -164, + -36, -102, 24, -32, -103, -95, 4, -2, -173, 25, 67, -69, + 17, 31, -155, -13, -58, -173, -7, -37, -107, -6, -41, -144, + 10, -12, -243, -9, -41, -66, 0, -27, -131, -2, -39, -146, + 19, 28, -134, 47, 118, -94, 34, 68, -128, 30, 53, -132, + 19, 9, -162, 25, 42, -104, 57, 139, -86, 47, 106, -93, + 51, 128, -54, 55, 140, -41, 52, 117, -82, 51, 108, -91, + 51, 106, -95, 54, 119, -73, 57, 128, -55, 58, 131, -52, + 54, 117, -60, 84, 188, -60, -24, -44, 43, -84, -179, 93, + 32, 84, 12, 55, 105, -97, 59, 126, -61, 61, 138, -22, + 56, 132, -7, 48, 130, 53, 66, 154, 3, 74, 176, 20, + 41, 94, 3, 62, 147, 27, 59, 138, 27, 57, 135, 40, + 57, 134, 44, 52, 127, 63, 48, 122, 78, 57, 131, 52, + 62, 122, -17, 71, 128, -61, 61, 115, -30, 76, 142, -28, + 57, 119, 33, 60, 92, -89, -4, 9, 63, 26, 73, 95, + 70, 131, -8, 14, 37, 42, 38, 92, 91, 22, 60, 88, + 38, 100, 131, 50, 107, 79, -22, -10, 147, -7, 13, 127, + 16, 45, 85, 19, 57, 138, 46, 104, 119, 52, 110, 114, + 67, 114, -21, 31, 64, 62, -45, -65, 87, -29, -52, -1, + -7, -11, 9, 23, 59, 139, 15, 46, 156, 47, 90, 50, + -19, -29, 49, -19, -14, 167, -15, -11, 148, -36, -51, 137, + -26, -34, 144, 18, 42, 151, 29, 58, 109, -35, -56, 127, + -35, -54, 123, -47, -82, 59, -37, -64, 38, -21, -34, 138, + 27, 52, 132, -19, -33, 138, 59, 107, 66, -4, -8, 122, + -36, -65, 121, -50, -92, 117, 29, 48, 103, 48, 89, -112, + 37, 67, -134, 50, 88, 26, 57, 98, 77, 19, 35, -58, + 15, 27, -100, 7, 12, -104, 5, 9, -168, 62, 107, 47, + -17, -29, 140, -24, -42, 142, 36, 59, 133, 25, 39, 160, + -5, -14, 129, 3, -1, 151, 55, 86, 135, -59, -104, 74, + -22, -40, 38, 36, 51, 147, 31, 44, 116, 9, 8, 77, + -4, -21, 146, 15, 8, 176, -28, -60, 109, -19, -57, 201, + -40, -78, 59, -56, -108, 86, 9, -11, 173, 31, 35, 121, + 51, 67, 131, 43, 55, 117, -12, -48, 149, -39, -90, 112, + -49, -103, 94, -46, -103, 105, -29, -79, 124, -42, -96, 96, + -58, -113, 33, -83, -148, -12, -71, -123, -31, -71, -133, -2, + 14, 12, 58, 12, 1, 91, -86, -149, -59, -47, -98, 37, + -59, -132, 72, -14, -61, 125, -49, -123, 104, -39, -86, 28, + -61, -140, 60, -42, -107, 77, -15, -74, 144, -44, -116, 79, + -50, -129, 75, -10, -53, 94, 38, 26, 158, 44, 67, 73, + 69, 133, 26, 64, 111, 58, 72, 142, 7, 72, 141, 8, + 66, 132, -4, 58, 125, -42, 43, 109, -75, 66, 145, -60, + 56, 125, -64, 53, 121, -71, 56, 124, -68, 66, 135, -51, + 7, 0, 40, -46, -102, 64, -66, -128, 24, -26, -56, 23, + 98, 190, -32, 58, 122, -57, 51, 118, -89, 52, 114, -78, + 59, 122, -68, 62, 125, -62, 65, 124, -47, 69, 129, -43, + 68, 125, -44, 92, 158, -25, 60, 92, 29, 77, 119, 30, + 76, 112, 42, 73, 99, 67, 83, 110, 86, 72, 114, -11, + 4, -5, 45, 24, 21, 68, 50, 49, 105, 78, 83, 137, + 58, 59, 108, 70, 79, 99, 81, 101, 73, 81, 102, 63, + 81, 95, 85, 70, 68, 124, 37, 11, 140, 63, 60, 99, + 81, 100, 56, 91, 97, 107, 61, 68, 56, 48, 25, 134, + 95, 69, 193, 4, 59, -161, 23, 9, 69, 72, 89, 35, + 26, 85, -155, 10, 9, 15, 30, -9, 154, 18, -25, 150, + 84, 79, 104, 87, 109, 25, -33, -15, -88, 14, 31, -36, + 5, 41, -103, 1, 40, -121, 5, 23, -51, 63, 28, 174, + 40, 11, 129, 42, 54, 3, 60, 94, -46, 8, -2, 39, + -75, -117, 58, -81, -138, 88, 20, 29, -8, 66, 113, -76, + 75, 118, -55, 74, 121, -75, -19, 24, -155, 29, 76, -125, + 18, 79, -187, 13, -4, 70, -9, -71, 196, 65, 112, -92, + 13, -9, 81, 59, 64, 36, 32, 76, -114, 75, 146, -180, + -24, -52, 77, -36, -88, 143, 67, 69, 48, 43, 90, -123, + 14, 63, -154, 21, 64, -133, 118, 139, 20, -74, -92, 5, + -31, -74, 127, -15, -71, 175, 81, 117, -57, 56, 69, 1, + 106, 135, -25, 68, 85, -11, 73, 76, 39, 94, 73, 131, + -38, -49, 13, -104, -106, -57, -91, -108, -7, -47, -74, 60, + -60, -68, -20, -42, -81, 99, -28, -56, 70, -62, -95, 57, + -86, -105, -8, -131, -160, -16, 64, 62, 63, 78, 79, 59, + 100, 112, 37, 100, 108, 51, 97, 105, 43, 72, 99, -36, + 74, 120, -100, 77, 113, -67, 76, 113, -78, 90, 93, 38, + 55, 46, 61, -148, -151, -74, -47, -93, 123, -30, -85, 157, + 99, 85, 98, 85, 80, 61, 153, 155, 70, 40, 40, 20, + 97, 112, -3, 58, 86, -66, 73, 91, -27, 159, 166, 33, + -81, -96, 19, 19, 6, 50, 90, 69, 92, 83, 50, 125, + 70, 38, 117, 60, 12, 154, 52, 11, 133, 60, 12, 147, + 131, 119, 60, 17, -21, 107, 62, 13, 146, 43, -7, 138, + 91, 70, 72, 40, 42, -1, -92, -53, -116, 55, 100, -113, + 57, 110, -139, 115, 106, 35, 65, 82, -46, 115, 115, 8, + 121, 104, 49, 104, 88, 41, 110, 78, 84, 48, 34, 38, + 28, 8, 55, 75, 30, 116, 92, 65, 64, 121, 108, 21, + -3, -30, 74, 62, 26, 88, 54, 3, 128, 80, 39, 94, + 85, 37, 110, 109, 74, 71, 80, 94, -52, 28, 9, 44, + 40, -16, 131, 126, 64, 129, 30, -8, 88, 93, 38, 113, + 105, 56, 94, 107, 52, 103, 121, 107, -2, -8, -35, 69, + -4, -29, 60, -178, -122, -86, 32, -15, 103, 66, 1, 136, + 72, -9, 167, -38, -22, -26, -130, -69, -107, -7, 37, -101, + -67, -14, -107, -103, -53, -97, -159, -94, -120, -65, -45, -35, + -104, -60, -89, -103, -95, -3, -96, -103, 31, -41, -79, 93, + -20, -77, 136, 82, 32, 106, 95, 49, 95, 108, 74, 63, + 123, 90, 55, 82, 63, 30, 99, 72, 40, 23, -25, 104, + 83, 40, 80, 102, 39, 117, 93, 25, 125, 92, 42, 89, + 112, 46, 113, 93, 39, 89, 123, 44, 134, 22, 57, -80, + 36, 85, -115, -20, 43, -130, -30, 11, -80, -105, -46, -100, + -28, 22, -100, -64, 26, -185, -34, 27, -132, 22, 71, -121, + 5, 51, -111, -17, 47, -147, 80, 110, -104, 68, 88, -76, + 40, 80, -117, 134, 108, 12, 123, 104, -5, 2, 40, -99, + -108, -42, -127, 5, 41, -96, 1, 50, -135, -47, 24, -171, + 32, 19, 19, 79, 21, 123, 42, -12, 125, 33, -26, 144, + 110, 50, 102, 112, 65, 68, 120, 67, 74, 82, 95, -79, + 61, 82, -89, -11, 45, -144, -43, 18, -144, -67, -4, -134, + -74, -13, -131, -89, -30, -116, -99, -42, -108, -94, -38, -113, + -98, -44, -106, -98, -45, -106, -106, -58, -90, -103, -55, -93, + -115, -73, -74, -112, -73, -67, -116, -83, -49, -113, -78, -60, + -114, -82, -55, -109, -72, -76, -115, -56, -147, 53, 45, 6, + 104, 65, 88, 121, 91, 47, 108, 69, 75, 117, 83, 57, + 113, 98, -9, 16, 57, -140, -26, 43, -219, 24, -2, 74, + 16, -31, 148, 12, -36, 152, 108, 62, 91, 118, 86, 38, + 114, 76, 55, 131, 77, 94, 84, 41, 79, 92, 39, 110, + 86, 27, 124, 120, 92, 10, 113, 81, 18, 139, 79, 87, + 77, 33, 78, 70, 13, 120, 81, 13, 143, 58, -5, 138, + 69, 4, 136, 63, -2, 137, 60, -6, 137, 64, -1, 130, + 75, 7, 127, 56, -9, 131, 52, -32, 181, 44, -3, 90, + 99, 20, 130, 74, 5, 119, 76, 7, 118, 108, 46, 75, + 134, 72, 56, 129, 65, 61, 115, 75, 12, 132, 71, 48, + 99, 24, 105, 124, 40, 102, 81, 4, 118, 91, 21, 92, + 132, 64, 53, 120, 49, 69, 144, 82, 24, 74, 85, -86, + -14, 53, -143, 67, 20, 52, 87, 76, -48, 80, 68, -44, + 97, 75, -36, 35, 76, -132, -21, 48, -149, -156, -38, -144, + 95, 70, -28, 64, 77, -97, -12, 40, -122, -80, 5, -142, + -12, -31, 64, -30, -11, -21, -110, -27, -105, -127, -59, -55, + -107, -47, -55, -128, -45, -96, -125, -59, -58, 19, 24, -33, + 54, 97, -171, 53, -13, 131, 118, 50, 66, 101, 22, 112, + 171, 62, 118, -98, -11, -134, 70, 22, 59, 106, 27, 102, + 107, 39, 73, 154, 49, 114, 21, 60, -124, -52, 22, -141, + -43, 27, -143, 33, 72, -146, -152, -58, -96, 79, 48, 0, + 14, 40, -88, -94, -11, -134, 100, 83, -66, 71, 76, -100, + -11, 39, -135, 24, 62, -148, 29, 65, -150, 72, 74, -101, + 53, 75, -145, -13, -19, 41, 59, 2, 103, 160, 82, 31, + 37, 63, -137, 26, 63, -161, 85, 41, 23, 94, 82, -98, + 21, 40, -98, -49, 12, -135, 53, 25, 16, 92, 54, -15, + -52, 10, -138, 17, 20, -37, 156, 74, 39, 59, 61, -107, + -28, 16, -117, 60, 38, -23, 63, 57, -88, 69, 57, -77, + 102, 83, -118, 8, 24, -79, 20, 20, -37, 74, 49, -46, + -111, -42, -64, -130, -69, 5, -146, -88, 43, -99, -48, -22, + -96, -58, 25, -49, -28, 7, -95, -41, -49, -150, -98, 59, + 34, 27, -29, 17, 41, -129, -147, -71, -48, -110, -42, -86, + -152, -73, -58, 50, 47, -75, 79, 60, -67, -57, -21, -49, + -132, -76, 3, -160, -61, -146, 61, 26, 47, 109, 43, 88, + 143, 85, -13, 94, 70, -73, 37, 50, -133, -63, -7, -132, + -117, -40, -128, 87, 51, -3, 81, 32, 66, 111, 70, -42, + 100, 74, -88, 118, 74, -45, 15, 33, -126, -36, 14, -172, + 9, 0, 27, 45, -2, 137, 84, 29, 79, 128, 82, -65, + 129, 69, -4, 125, 66, -7, -63, -16, -85, 20, 36, -138, + -29, 12, -144, -2, 26, -156, 89, 63, -95, 66, 48, -86, + 60, 51, -121, 40, 35, -94, 67, 52, -111, 57, 50, -139, + -47, -6, -120, -118, -44, -117, 1, 20, -137, -44, -5, -136, + 38, 40, -163, 14, 25, -149, -28, 2, -138, -115, -48, -100, + -134, -70, 10, -122, -72, 69, -90, -59, 99, -141, -75, 4, + -126, -64, -36, -75, -48, 63, -110, -70, 73, -136, -81, 52, + -81, -55, 72, -147, -81, -18, -117, -61, -47, -106, -58, -32, + -127, -65, -71, -116, -66, -23, -72, -51, 68, -61, -54, 134, + -54, -51, 138, -72, -60, 117, -96, -71, 91, -106, -77, 75, + -114, -80, 62, -121, -83, 40, -123, -83, 30, -125, -83, 17, + -126, -79, -24, -132, -77, -69, -106, -62, -54, -111, -61, -90, + -99, -53, -99, -91, -47, -109, -81, -39, -122, -100, -48, -164, + -81, -59, 24, -107, -89, 97, -75, -63, 74, -113, -87, 43, + -105, -79, 29, -130, -103, 48, -103, -85, 61, -109, -89, 55, + -102, -90, 84, -111, -81, -25, -113, -76, -66, -171, -140, 51, + 34, 42, -103, -4, 11, -101, -114, -81, -55, -149, -133, 97, + 41, 43, -63, 60, 64, -122, 0, 21, -147, -105, -68, -124, + 22, 18, 1, 111, 76, 92, 111, 92, -45, 79, 75, -102, + 54, 56, -120, 40, 49, -163, 60, 45, 13, 107, 92, -91, + 85, 75, -103, 103, 81, -53, 114, 83, 17, 117, 88, -23, + 118, 88, -25, 97, 77, -75, 128, 91, -1, 128, 88, 17, + 117, 86, -53, 10, 22, -157, 2, 16, -180, 1, 7, -79, + -1, 10, -152, -23, -6, -149, -67, -37, -156, 60, 41, 10, + 92, 69, -93, 64, 49, -125, 36, 31, -144, 43, 35, -143, + 34, 29, -159, 75, 53, -86, 104, 71, -92, 74, 51, -124, + 85, 58, -119, 40, 28, -137, 36, 24, -147, 65, 42, -134, + 50, 31, -135, -11, -8, -147, -44, -31, -140, -40, -31, -200, + 110, 72, 10, 124, 78, -12, 123, 77, -49, 127, 78, -27, + 121, 74, -43, 146, 88, -45, 51, 26, -131, -32, -25, -132, + -139, -87, -39, 9, 5, -11, 128, 80, 28, 67, 38, -60, + 112, 63, -78, 124, 75, 31, 127, 75, -3, 138, 80, 10, + 121, 72, 33, 140, 80, 26, 111, 66, 70, 123, 71, 80, + 121, 68, 47, 114, 65, 51, 111, 62, 99, 85, 47, 51, + 101, 56, 71, 11, 7, 65, 95, 51, 27, 48, 27, 106, + 63, 33, -10, 60, 31, 34, -13, -4, 161, 65, 34, 141, + 106, 55, 41, 105, 52, -52, 72, 35, -130, 37, 15, -168, + 83, 39, -90, 46, 19, -161, 79, 36, -75, 3, 3, 49, + -79, -35, 130, -59, -26, 161, -35, -15, 131, -59, -27, 128, + 18, 9, 136, 118, 59, 92, 101, 49, 32, -31, -15, 113, + -16, -9, 126, 50, 23, 132, 103, 48, 78, 127, 60, 65, + 110, 50, 64, 141, 65, 60, 77, 38, -96, -2, 1, -144, + 15, 9, -154, 78, 37, -114, 106, 48, -94, 68, 30, -131, + 19, 8, -167, 23, 11, 24, -25, -11, 189, 7, 3, 112, + -100, -45, 171, -61, -29, 68, -89, -42, 116, 12, 2, 157, + 103, 45, 94, 121, 53, 77, 128, 54, 77, 159, 73, -115, + 60, 22, 148, -61, -30, 111, -42, -24, 145, -3, -7, 123, + 39, 15, 46, 131, 61, -85, 138, 64, -138, -35, -19, 110, + -59, -28, 68, -116, -54, 85, 46, 14, 109, 93, 34, 114, + 115, 45, 65, 101, 37, 94, 152, 62, 24, 119, 52, -55, + 96, 45, -107, 135, 57, -57, 109, 48, -81, 56, 19, 54, + 66, 19, 122, 134, 54, -47, 120, 45, 14, 79, 37, -138, + 77, 36, -149, 41, 13, 45, 50, 19, -23, -6, 5, -150, + 45, 22, -146, -22, -2, -170, -101, -37, -34, -127, -47, 19, + -127, -52, 103, -127, -48, -19, -89, -31, -100, -148, -58, -11, + -144, -57, -30, -122, -47, -64, -175, -71, -30, -117, -46, -126, + 87, 38, -89, 112, 48, -94, 131, 54, -56, 153, 61, 26, + 91, 35, 63, 141, 56, -31, 116, 46, -79, 111, 43, -130, + -81, -30, -107, -154, -60, -23, -162, -63, -72, 76, 30, -75, + 143, 55, 4, 196, 75, -91, 86, 33, 78, 71, 26, -98, + 11, 3, -102, 54, 18, -147, 88, 33, 26, 157, 58, 68, + 116, 41, -5, 120, 42, -55, 125, 42, -76, 158, 55, 8, + 128, 42, -55, 132, 41, -112, 70, 22, -75, 23, 5, -78, + -125, -45, -117, -114, -39, -27, -76, -30, -127, -123, -43, -32, + -160, -53, 55, -110, -42, -70, -136, -49, -22, -142, -49, 71, + -89, -29, 108, -55, -16, 124, -71, -22, 150, -83, -30, 38, + -1, -1, -34, 33, 11, -33, -107, -42, -58, -131, -52, -69, + 13, 8, 119, -132, -49, 48, -96, -40, -84, -108, -46, -91, + -57, -27, -143, -83, -37, -88, -125, -51, 2, -141, -57, 24, + -144, -61, -14, -41, -22, -92, -95, -41, -26, 114, 46, -52, + 38, 22, 135, 113, 45, -60, 128, 49, -80, 118, 50, 32, + 181, 75, 49, -20, -12, -96, 69, 26, -27, 132, 44, -152, + -31, -18, -122, -48, -23, -73, -149, -58, 36, -19, 0, 130, + -129, -50, 41, 33, 6, -131, 146, 54, -83, -67, -29, -38, + -30, -20, -127, 59, 15, -137, 23, -3, -164, -13, -16, -141, + 43, 5, -140, 94, 26, -126, 115, 37, -94, 38, -1, -166, + 125, 41, -72, 115, 37, -70, 142, 54, 6, 102, 28, -92, + -15, -22, -149, -12, -22, -150, -12, -22, -146, -138, -61, -71, + -43, 0, 128, 6, 19, 144, 20, 29, 187, -75, -34, -47, + -42, -28, -104, -9, -26, -190, -108, -52, -82, -154, -60, 4, + -152, -59, 7, -108, -50, -50, -174, -79, -54, 68, 23, -40, + 184, 68, -58, 50, 31, 85, 182, 65, -57, 38, 5, -74, + 139, 47, -49, 119, 35, -77, 39, 0, -111, -4, -24, -154, + 32, -10, -145, 36, -10, -149, 68, 5, -132, 84, 9, -131, + 127, 25, -132, 114, 57, 88, -14, 17, 135, 47, 32, 91, + 142, 47, -23, 132, 37, -62, 108, 14, -139, 21, -11, -110, + 87, 11, -105, 116, 20, -113, 132, 32, -67, 113, 19, -100, + 112, 18, -99, 140, 36, -44, 131, 29, -67, 98, 8, -115, + 38, -12, -122, -82, -53, -131, 62, -7, -132, 142, 57, 68, + 135, 54, 59, 40, 1, -51, -82, -50, -118, -89, -53, -125, + 79, 1, -103, 147, 43, -6, 135, 49, 40, 141, 48, 36, + 170, 45, -16, -69, -36, -77, -55, -47, -138, -9, -37, -150, + 72, -6, -117, 20, -29, -143, -66, -60, -170, 86, 24, -3, + 53, -18, -131, 2, -32, -129, -63, -49, -118, 24, -19, -101, + 70, 46, 101, 12, 39, 137, 16, 42, 151, -49, 20, 136, + -25, 24, 126, 33, 63, 227, 99, 7, -88, 13, -32, -147, + 44, -32, -180, 30, -15, -95, -5, -39, -151, 40, -27, -142, + -4, -41, -153, -110, -55, -92, 45, 5, -27, 85, -6, -106, + 108, 11, -66, 125, 10, -82, 138, 21, -55, 174, 38, -24, + 120, 27, -11, 156, 35, -11, 117, 9, -67, 135, 8, -83, + 135, 22, -30, 145, 30, -9, 152, 26, -26, 105, -5, -96, + 100, -12, -111, 136, 17, -37, 146, 17, -43, 124, 1, -78, + 151, 20, -27, 140, 19, -26, 147, 16, -33, 124, -6, -91, + 115, -6, -86, 160, 20, -20, 122, 46, 82, 136, 16, -18, + 124, -13, -100, 161, 35, 35, 87, -29, -131, 55, 33, 77, + 139, 42, 76, 73, -25, -112, 42, -38, -138, 104, -20, -104, + 133, -3, -61, 49, -34, -123, -41, -40, -104, 66, 16, 23, + 106, -15, -82, 140, -26, -125, 66, -15, -64, 37, -42, -134, + 27, -46, -138, -11, -53, -145, 41, -44, -135, 89, -34, -116, + 135, -12, -71, 148, -3, -46, 47, -29, -88, 20, -60, -161, + -50, -23, -49, -136, -35, -57, -140, -33, -47, -120, -35, -57, + -138, -47, -79, -81, -56, -117, -109, -36, -56, -160, -3, 41, + -158, -18, 6, -68, -67, -143, -117, -6, 24, -158, -13, 25, + 67, -29, -95, 140, 17, -7, 205, 63, 88, -60, -34, -63, + -179, -70, -111, 42, -48, -129, 145, -3, -55, 141, 6, -29, + 156, 23, 8, 29, 73, 166, 142, 5, -28, 107, -28, -95, + 87, -40, -119, 70, -21, -65, 127, -24, -87, 96, -37, -107, + 105, -32, -96, -20, -34, -73, -192, -36, -37, -147, -15, 0, + 62, -27, -73, -50, -46, -90, -64, -47, -89, -113, -45, -70, + -151, -17, 3, -124, 0, 32, -127, 18, 75, -194, -8, 39, + -100, -17, -8, -68, 13, 51, -91, 47, 133, -117, 28, 102, + -108, -23, -15, 39, -62, -152, -86, -54, -89, -79, -64, -112, + -34, -63, -124, 72, -46, -124, 159, -3, -57, 77, -31, -90, + 67, -50, -124, 141, -12, -69, 124, 38, 43, 80, -39, -102, + 26, -74, -158, -43, -63, -113, 109, -12, -55, 55, -60, -133, + 8, -75, -147, 46, -53, -112, -48, -53, -89, -123, -74, -110, + -57, 27, 66, -61, 60, 130, -4, -8, -14, 37, -64, -132, + -77, -54, -81, -137, -36, -30, -162, 9, 65, -61, -42, -61, + 114, -19, -69, 160, 46, 41, 86, -61, -135, -67, -54, -82, + -129, -49, -55, -129, -67, -84, -119, -42, -42, -138, 10, 60, + -116, 33, 95, -4, 65, 119, -34, 91, 179, 6, -43, -82, + -48, -58, -91, -90, -77, -112, -97, -71, -96, -11, -72, -125, + -53, -59, -87, -43, -35, -47, -17, -85, -143, -102, -12, 14, + -72, 49, 109, -131, 44, 123, -147, -31, -2, -112, -4, 34, + -197, -92, -87, 4, 87, 151, -95, 49, 126, 19, -17, -38, + -77, -73, -99, -120, 5, 56, -104, 35, 105, -63, 53, 124, + -10, -6, -7, -5, -72, -129, 51, -64, -135, -57, -80, -116, + 13, -75, -135, -69, -96, -137, -6, -24, -38, 106, -35, -103, + 67, -57, -122, 33, -94, -169, 82, -34, -87, 89, -37, -93, + 96, -49, -115, 63, -62, -121, -41, -96, -137, 86, -23, -66, + 130, 44, 24, 125, -16, -67, 99, -44, -102, 83, -75, -141, + 42, -58, -101, 91, -40, -88, 36, -71, -117, -44, 19, 42, + -137, 27, 82, -127, -2, 37, -57, 52, 97, -37, 84, 141, + -93, -22, -3, -141, 5, 56, -90, 27, 74, -97, 52, 116, + -101, -20, 6, -32, 19, 41, -73, 40, 90, -127, 49, 126, + -43, 45, 90, 26, 63, 92, -86, 40, 98, -96, 48, 119, + -95, 41, 107, -79, 44, 109, -10, 69, 120, -50, 62, 128, + -69, 42, 103, -74, 48, 118, -71, 56, 132, -91, 31, 97, + -19, 54, 106, -31, 67, 136, -69, 61, 148, 75, 55, 64, + 165, 34, -18, 13, 77, 137, -48, 65, 147, -67, 31, 93, + -58, 46, 119, 90, 73, 96, -41, 10, 41, -47, 57, 138, + -36, 64, 148, -17, 59, 129, -75, 42, 126, -82, 38, 126, + -160, 31, 156, 12, -41, -93, -177, -73, -50, 89, -3, -57, + 138, 10, -58, 88, -34, -121, 46, -49, -124, -61, -78, -125, + 1, -67, -133, -8, -72, -138, -147, -34, 14, -19, -46, -80, + 77, -45, -127, -100, -39, -21, -108, 17, 91, -81, 72, 186, + -63, 18, 70, -43, 51, 126, -61, 51, 138, -149, -7, 76, + -28, 56, 131, 21, 67, 125, 69, 16, -9, 34, 13, 6, + 47, 46, 67, 24, 56, 103, -37, 49, 128, -27, -27, -40, + -92, -20, 15, -102, 4, 73, -89, 33, 130, -12, -27, -52, + -111, -57, -49, -142, -41, 8, -133, -53, -22, -87, 46, 159, + -48, -46, -65, -135, -53, -18, -131, -41, 5, -130, 1, 98, + -109, 11, 107, -130, -9, 78, -177, -14, 109, -103, -45, -18, + -140, -29, 51, -106, 6, 100, -39, 52, 151, -118, -16, 62, + 9, -26, -65, 11, -46, -113, -103, -54, -34, -114, -32, 27, + -154, -41, 44, -142, -49, 18, -163, -73, -16, -109, -48, -5, + -176, -51, 49, -66, 10, 85, -13, 38, 99, 130, 56, 2, + 129, 43, -24, 29, 28, 35, -139, -21, 84, -80, -15, 43, + -154, -101, -82, -135, -44, 34, -15, 25, 71, 115, 79, 68, + 160, 107, 91, 75, 63, 75, -35, -16, -4, -117, -76, -63, + -115, -66, -40, -141, -81, -45, -143, -15, 110, -116, -71, -46, + -136, -59, 6, -127, -79, -49, -82, -67, -64, -65, -50, -45, + -143, -56, 26, -148, -70, 1, -106, -61, -19, -197, -86, 23, + -38, -63, -98, -99, -108, -127, -11, 37, 93, -37, 63, 181, + -104, -51, 5, -113, -78, -43, -131, -99, -69, -39, -48, -61, + -90, -69, -46, -52, 22, 110, 36, 78, 129, 79, 77, 80, + 94, 82, 74, 23, 21, 21, -131, -106, -85, -88, -89, -96, + -22, 4, 35, 76, 92, 117, -38, -8, 26, -83, -108, -141, + -18, -45, -80, -56, -75, -99, -85, -68, -47, 60, 12, -44, + -75, -60, -42, -128, -21, 106, -14, -35, -56, -7, -46, -91, + -126, -71, -1, -154, -77, 21, 2, 45, 95, 18, 77, 144, + -56, -15, 36, -91, -90, -80, -163, -46, 103, 49, 9, -42, + 118, 28, -87, -8, -31, -56, -136, -78, 3, -154, -87, 7, + +/* 2 */ +855, 1, 10146, -28113, 2593, + -64, -14, 99, -80, -18, 106, -94, -21, 118, -117, -32, 89, + -142, -49, -9, -125, -42, 5, -128, -35, 72, -151, -47, 23, + -146, -50, -18, -133, -46, -35, -151, -45, 14, -129, -32, 74, + -134, -34, 54, -100, -18, 108, 15, 23, 153, 86, 38, 101, + 166, 53, 22, 114, 38, 26, 140, 39, -36, 135, 37, -51, + 143, 47, 6, 145, 55, 58, -124, -32, 67, 28, 23, 110, + 85, 41, 95, 148, 50, 1, 46, 0, -116, 126, 38, -40, + 98, 45, 85, 98, 27, -54, 87, 31, 0, 117, 48, 45, + 135, 50, 10, 123, 45, -4, 105, 53, 98, 140, 63, 69, + -39, 1, 110, -64, -4, 137, -33, 10, 148, -42, 7, 144, + -39, 9, 148, -38, 12, 148, -37, 11, 146, -28, 16, 148, + -87, -10, 120, -70, -3, 117, -42, 15, 156, -32, 15, 133, + -44, 13, 141, -80, -2, 130, -5, 24, 117, -7, 29, 148, + -32, 21, 143, -35, 21, 147, 87, 40, 36, 96, 40, 22, + -19, 30, 156, 11, 38, 140, 31, 47, 141, -43, 21, 144, + -83, 3, 129, -86, 1, 122, -113, -13, 102, -111, -11, 104, + -142, -38, 40, -137, -36, 41, -138, -35, 40, -116, -59, -74, + -56, -54, -130, -62, -27, -26, -49, 23, 143, -52, 19, 131, + -144, -27, 65, -26, -48, -141, -89, -34, -22, -138, -28, 50, + -92, -1, 101, 74, 51, 99, -49, 22, 131, -127, -50, -42, + -141, -33, 32, -124, -13, 80, -149, -37, 17, -130, -15, 74, + -132, -14, 77, -147, -42, -9, -144, -26, 44, -143, -29, 27, + -147, -33, 15, -138, -38, -14, -110, -61, -115, -105, -49, -84, + -193, -49, -13, 38, 41, 110, -101, -31, -25, -72, 23, 133, + 127, 47, 62, -51, 10, 74, -161, -49, -43, -33, 28, 117, + 43, 40, 100, -56, 30, 138, -19, 42, 146, 36, 53, 142, + -86, 16, 108, -145, -37, -16, -97, -52, -97, -128, -51, -76, + -146, -38, -26, -149, -29, -1, -148, -30, -2, -141, -7, 60, + -141, -10, 48, -149, -24, 8, -150, -20, 19, -141, -7, 49, + -150, -18, 18, -147, -14, 28, -149, -16, 19, -149, -15, 22, + -142, -3, 50, -112, 19, 105, -133, 6, 71, -116, 18, 96, + -112, 20, 101, -125, 15, 86, -121, 16, 87, -159, -19, -3, + -150, -19, -10, -151, -12, 6, -135, 9, 64, -132, 4, 44, + -156, -14, -3, -118, -35, -73, -114, -37, -85, -153, 4, 42, + -88, 34, 115, -81, 37, 121, -112, 32, 108, -35, -26, -68, + -76, -33, -82, -115, 38, 126, -117, -31, -73, -110, -34, -83, + -152, -6, -1, -152, -7, -6, -147, -13, -25, -145, -16, -37, + -144, -16, -40, -132, -26, -70, -139, -21, -59, -109, -33, -97, + -99, -36, -108, -90, 36, 108, -127, -5, -17, -96, 20, 55, + -117, 5, 9, -147, -8, -32, -150, -1, -14, -149, -14, -56, + -83, 28, 76, 58, 42, 129, -20, 42, 118, -126, -13, -49, + -86, -37, -120, -54, -44, -136, 15, -53, -156, -135, -21, -85, + -82, 49, 137, -70, 46, 126, -119, 36, 88, -81, -19, -70, + -22, -46, -143, -69, -43, -144, -140, 38, 89, -43, -33, -110, + 114, -37, -91, 71, -44, -122, -30, -42, -140, -71, -35, -129, + -97, -29, -116, -138, -9, -65, 23, -25, -77, -7, -32, -110, + -136, -7, -58, -104, -24, -113, -14, -51, -183, 21, -28, -96, + 58, -21, -58, 132, 9, 68, 127, 15, 86, 27, -28, -92, + -97, -23, -110, -67, -30, -130, -79, -27, -125, -47, -32, -134, + -5, -37, -148, -31, -33, -141, 48, -40, -150, -136, -10, -84, + -104, -10, -83, -111, -10, -85, -125, -4, -66, -120, -8, -87, + -117, -10, -97, -90, -20, -132, -69, -16, -107, -93, -15, -121, + -67, -21, -132, -38, -25, -144, -55, -21, -141, -31, -25, -148, + -77, -16, -131, -27, -24, -147, 3, -27, -149, 4, -26, -149, + 22, -28, -148, 55, -29, -137, 103, -29, -106, 150, -18, -6, + 145, -20, -31, 134, -7, 46, 80, 13, 129, 78, 14, 128, + 132, 10, 135, 16, -14, -76, -32, -21, -147, 4, -26, -155, + 162, -21, -42, 93, -24, -108, -32, -18, -138, -96, -10, -124, + -65, -13, -134, -90, -9, -122, -69, -11, -134, -79, -9, -128, + -44, -14, -146, -57, -11, -139, -22, -15, -147, 59, -21, -143, + -61, -7, -129, -124, 4, -86, -90, -3, -120, -57, -6, -139, + -36, -9, -146, -21, -10, -149, 30, -15, -148, 71, -17, -133, + 75, -19, -163, -105, 10, -3, -134, 19, 54, -145, 14, -43, + -144, 14, -52, -142, 14, -50, -140, 15, -54, -141, 16, -55, + -136, 15, -68, -124, 13, -86, -100, 9, -114, -115, 13, -97, + -126, 16, -86, -144, 21, -33, -145, 22, -49, -126, 14, -211, + 10, 2, 103, -62, 16, 132, -128, 25, 66, -141, 24, -30, + -57, 5, -132, -39, 2, -151, 107, -22, -83, -36, 5, -47, + -142, 25, -56, -109, 18, -94, -147, 29, -31, -156, 30, -34, + -31, 9, 92, 136, -26, 79, 112, -19, 99, 54, -6, 141, + -19, 9, 150, -108, 25, 85, -133, 25, -57, -88, 13, -124, + -107, 18, -129, -114, 24, 14, 24, -1, 120, 84, -12, 129, + 60, -7, 138, 77, -9, 129, 83, -11, 124, -50, 19, 144, + -119, 31, 98, -114, 19, -79, -47, 1, -148, -123, 22, -77, + -136, 28, -54, -143, 30, -42, -142, 31, -37, -139, 32, -11, + -116, 34, 108, 60, -8, 127, 139, -31, 32, 129, -26, 64, + 70, -8, 134, 61, -5, 139, 61, -3, 139, 54, -1, 147, + -91, 30, 115, -36, 19, 136, -3, 14, 148, 5, 14, 152, + -21, 19, 148, -30, 23, 145, -30, 23, 149, -106, 31, 50, + -96, 33, 86, -112, 41, 116, 95, -17, 48, -6, 13, 93, + -117, 39, 85, -90, 36, 105, -94, 32, 62, -40, 17, 51, + -61, 31, 110, -130, 30, -29, -131, 37, 18, 66, -4, 97, + 25, 9, 103, -109, 39, 70, -156, 39, -21, -120, 26, -45, + -54, 31, 103, -124, 41, 45, -115, 11, -148, -38, 20, 61, + 29, 15, 151, -109, 31, -3, -62, 25, 43, -64, 36, 103, + -146, 51, 42, -111, 23, -65, -72, 33, 67, -134, 39, -15, + -96, 44, 80, -156, 50, -3, -129, 54, 68, -134, 41, -21, + -134, 39, -38, -150, 60, 54, -117, 42, 3, -27, 36, 152, + -53, 11, -44, -6, -26, -159, 113, -44, -30, -20, -4, -58, + -82, 9, -121, -125, 48, 21, -84, 50, 117, -82, 22, -47, + -147, 63, 50, -120, 52, 44, -39, 38, 132, -100, 56, 97, + -23, 41, 177, -118, 61, 82, -71, 52, 123, 202, -60, 96, + -114, 60, 80, 93, -7, 139, 20, 19, 131, -21, 39, 142, + -73, 14, -67, -18, -25, -152, -142, 44, -57, -88, 65, 143, + -97, 45, 31, -51, 46, 113, -18, 42, 157, -42, 48, 133, + -38, 47, 138, 18, 29, 150, 86, -9, 108, -40, 35, 75, + -97, 66, 102, -47, 52, 129, -2, 40, 151, 56, 18, 152, + -95, 59, 72, -85, 8, -104, -7, -35, -144, -28, -30, -156, + 25, -48, -147, -15, -25, -128, -24, -22, -132, -5, -34, -151, + 73, -59, -120, 23, -40, -133, 3, -39, -169, 21, -33, -111, + 38, -44, -131, -54, -9, -152, 126, -67, -76, 70, -43, -69, + 53, -45, -120, 47, -38, -98, 1, -24, -130, 48, -43, -128, + 75, -51, -119, 85, -50, -97, 50, -39, -115, 16, -28, -131, + 145, -69, -78, 92, -14, 130, 81, -38, -46, 92, -49, -90, + 135, -55, -30, 105, -50, -76, 120, -56, -82, 123, -40, 17, + 101, -51, -102, -31, -10, -145, -5, -15, -118, 144, -53, -23, + 127, -51, -60, 141, -46, 15, 142, -48, -7, 141, -48, -20, + 139, -48, -27, 129, -49, -68, 142, -47, -20, 144, -43, 2, + 134, -47, -55, 118, -43, -65, 95, -41, -118, 48, -30, -133, + 40, -27, -148, 9, -19, -150, -25, -8, -148, 2, -15, -146, + -5, -12, -156, 31, -21, -145, -2, -12, -152, -15, -7, -143, + 9, -13, -157, -86, 24, -2, -77, 18, -69, 16, -15, -167, + -97, 25, -49, -131, 35, -68, -99, 24, -107, 55, -20, -57, + 93, -30, -67, 129, -40, -49, 84, -29, -95, -35, 5, -125, + -80, 19, -128, -38, 7, -140, -68, 16, -139, -184, 54, -42, + 30, -11, -109, -23, 5, -131, -40, 10, -134, -186, 56, -83, + 112, -34, -78, 70, -22, -118, 55, -16, -134, -40, 13, -157, + 4, 1, -147, 49, -12, -139, -6, 5, -150, 40, -7, -148, + 4, 4, -147, -49, 20, -153, -49, 20, -120, 42, -5, -148, + 39, -4, -144, 28, 1, -165, -30, 17, -116, -70, 28, -110, + 110, -29, -54, 130, -44, 72, 26, -16, 138, -25, -2, 147, + -13, -5, 153, 70, -28, 142, 78, -20, -44, 36, -3, -147, + -24, 16, -149, 53, -7, -129, 110, -37, 77, 57, -23, 124, + 143, -44, 74, 27, -14, 135, 126, -36, 32, 75, -23, 68, + 98, -29, 76, 82, -17, -108, 28, 0, -145, -68, 25, -127, + 24, 4, -161, 49, -4, -144, 86, -13, -128, 107, -19, -105, + 27, 5, -144, -12, 15, -154, 84, -6, -166, -127, 38, -63, + -148, 36, 15, -143, 44, -72, -19, 20, -144, 109, -26, -31, + 136, -40, 54, 109, -23, -50, -14, 17, -123, -89, 31, -83, + -123, 39, -67, -87, 35, -107, 77, -9, -97, 155, -46, 54, + 104, -16, -88, 94, -9, -114, 8, 18, -157, 92, -13, -73, + 110, -17, -77, 101, -8, -114, 95, -6, -120, 67, 5, -135, + 95, -5, -114, 65, 6, -140, 81, 3, -128, 85, 1, -126, + 109, -7, -101, 130, -14, -76, 103, -3, -108, 79, 6, -131, + 87, 5, -123, 129, -10, -87, 18, 26, -156, 96, 3, -108, + 151, -19, -53, 144, -31, 23, 139, -14, -57, 133, -6, -84, + 146, -32, 31, 140, -18, -24, 118, 0, -95, 127, -12, -39, + 156, -16, -38, 134, -22, 14, 143, -10, -54, 81, -45, 165, + 104, 3, -81, 78, 19, -143, 165, -22, 5, -30, -18, 107, + -130, 3, 66, -57, -19, 133, 6, -28, 137, 79, -26, 81, + 97, -32, 107, 88, 0, -61, 160, -18, -5, 141, -19, 14, + 98, -1, -51, 42, 24, -149, 104, 4, -76, 77, 5, -66, + 52, 22, -135, 113, 9, -95, 125, -16, 19, 118, 4, -70, + 89, -27, 97, 77, -31, 117, 41, -30, 136, -72, -25, 156, + -144, 6, 35, -121, -2, 69, 69, -30, 124, 161, -14, 3, + 37, -21, 100, -45, -22, 142, -92, -12, 117, -82, -13, 121, + -60, -18, 139, -79, -13, 131, -69, -14, 132, -35, -19, 147, + 27, -24, 148, 60, -25, 134, 135, -21, 64, 138, -19, 55, + 133, -23, 87, 126, -7, -24, 71, 13, -132, 96, 8, -112, + 117, 6, -96, 151, -12, 12, -16, -15, 116, -64, -16, 145, + 86, -21, 123, 23, -21, 148, -22, -17, 154, 7, -18, 148, + 106, -18, 108, 92, -18, 118, 66, -18, 136, 75, -16, 129, + 56, -16, 137, 9, -14, 151, -32, -11, 148, -72, -7, 133, + -86, -6, 126, -84, -4, 126, -14, -8, 133, 123, -8, 18, + 89, 4, -130, 125, 1, -97, 157, -11, 62, 114, 1, -81, + 157, -2, -36, 120, 3, -96, 85, 8, -121, 92, 8, -118, + 75, 8, -118, 108, 9, -118, 128, 6, -80, 153, 1, -24, + 123, 5, -53, 115, 10, -101, 132, 8, -74, 135, 9, -67, + 113, 8, -67, 85, 13, -99, 153, 6, -28, 38, 8, -63, + 45, 16, -122, 89, 13, -90, 109, 16, -106, 112, 15, -84, + 81, 16, -100, 104, 20, -116, 151, 21, -102, 20, 22, -149, + 111, 19, -87, 53, 22, -133, 53, 22, -123, 132, 8, 1, + 71, 16, -73, -64, 23, -163, 42, 23, -122, -1, 27, -158, + 66, 27, -132, -52, 19, -120, -108, 12, -98, -88, 18, -123, + -106, 12, -92, -181, 0, -44, 53, 12, -52, 133, 30, -117, + 100, 13, -34, 82, 37, -157, 82, 20, -73, 63, 33, -132, + 115, 28, -95, 35, 21, -85, 31, 32, -130, 61, 37, -142, + 27, 33, -132, 16, 32, -130, 62, 36, -128, 76, 39, -130, + -76, 23, -114, -33, 36, -149, -108, 11, -73, -26, 28, -111, + 74, 41, -132, -110, 13, -76, 9, 25, -88, -85, 32, -135, + -90, 31, -127, -103, -6, -2, -99, 8, -46, -25, 40, -142, + -56, 34, -126, -32, 47, -159, 9, 45, -144, 40, 39, -116, + -74, 30, -107, -14, 40, -127, 106, 39, -102, 153, 10, -1, + 126, 33, -75, 143, 33, -68, 84, 42, -106, 163, 15, -9, + 136, 8, 12, 146, 15, -9, 154, 12, 8, 123, -13, 73, + 140, 35, -61, 147, 12, 11, 142, 13, 8, 142, 26, -26, + 106, 40, -77, 132, 38, -62, 143, 29, -28, 135, 34, -44, + 194, 36, -27, 97, -12, 78, 124, -4, 64, 150, 16, 23, + 159, 37, -31, 46, 48, -115, 156, 45, -53, -15, -36, 94, + -26, -53, 138, 147, 11, 43, 118, 0, 64, 138, -8, 98, + 120, 71, -143, 138, 11, 45, 145, 21, 23, 146, 6, 68, + 113, 50, -75, 115, 32, -22, 87, -32, 148, 71, 25, -26, + 148, 46, -37, 171, 21, 52, 60, 55, -120, 84, 45, -71, + 112, -11, 108, 134, 20, 40, 147, 29, 20, 107, -15, 126, + 147, 32, 16, 131, 8, 82, 130, 11, 73, 131, 16, 60, + 141, 21, 56, 125, 8, 85, 139, 21, 58, 133, 18, 65, + 111, 2, 99, 144, 26, 57, 153, 29, 56, 87, 53, -79, + 72, 62, -121, 120, 61, -70, 123, 47, -21, 79, -2, 88, + -86, -65, 114, -106, -63, 88, -125, -59, 59, -42, -50, 118, + 131, 12, 99, 76, -14, 129, 81, -11, 124, 87, -7, 121, + 105, 3, 111, 32, -30, 145, -31, -50, 141, -74, -56, 114, + -40, -47, 127, 112, 11, 101, 121, 18, 85, 137, 36, 41, + 131, 62, -66, 141, 35, 58, 25, -32, 158, -43, -49, 136, + 95, 18, 63, 95, 12, 88, 17, -29, 150, 74, 7, 81, + 119, 18, 111, 27, -25, 152, 17, -25, 144, 64, -7, 141, + 44, -14, 140, 73, -1, 140, 52, -8, 136, 110, 21, 107, + 140, 49, 19, 136, 45, 44, 78, 7, 125, 25, -20, 159, + 129, 47, 22, 139, 49, 40, 139, 48, 50, 59, 4, 115, + 7, -23, 148, 32, -11, 148, -6, -27, 148, -101, -55, 90, + -76, -48, 104, -17, -28, 144, 16, -18, 175, 104, 29, 94, + 124, 40, 85, 58, 5, 144, 73, 15, 129, 78, 17, 127, + 88, 23, 124, 82, 22, 122, 59, 11, 135, 67, 15, 133, + 30, -1, 147, -6, -17, 148, -18, -20, 147, -90, -49, 114, + -65, -38, 129, -105, -54, 130, 66, 23, 86, 82, 28, 102, + -29, -22, 162, 43, 11, 136, -8, -12, 155, 9, -3, 157, + 54, 18, 141, -20, -14, 150, 30, 9, 148, -2, -4, 155, + 38, 14, 144, 0, -2, 154, -38, -17, 145, -30, -13, 146, + -13, -5, 165, 118, 51, 49, 159, 71, 70, -58, -25, 54, + -147, -64, 16, -117, -49, 76, -86, -35, 120, -43, -14, 142, + -63, -23, 129, -10, 1, 153, -12, 1, 149, -21, -2, 150, + -87, -30, 128, -7, 4, 134, -138, -53, 64, -79, -30, 35, + -98, -32, 115, -59, -15, 138, -81, -23, 127, -102, -32, 104, + -125, -43, 76, -134, -48, 36, -137, -54, -19, -115, -37, 69, + -97, -26, 116, -95, -26, 95, + +/* 3 */ +533, 1, 14413, -10720, -24028, + 106, 64, 35, 41, 145, -39, 45, 121, -25, 118, 62, 45, + 108, 59, 42, 130, 65, 53, 121, 63, 49, 125, 156, 13, + 105, 16, 61, 116, 68, 46, 134, 43, 70, 123, 76, 50, + 78, 121, 2, 37, 136, -31, 102, 110, 25, 28, 136, -35, + 3, 139, -52, 41, 137, -25, 71, 135, -3, 71, 132, -1, + 106, 109, 33, 94, 119, 21, 23, 137, -33, 49, 144, -17, + 50, 142, -13, 38, 151, -25, 25, 132, -27, 44, 100, -1, + 117, 83, 55, 114, 84, 53, 77, 128, 14, 100, 11, 68, + 77, -59, 74, 102, -33, 85, 81, 128, 19, 59, 137, 0, + 45, 141, -9, 21, 141, -27, 40, 147, -13, 49, 131, -2, + 55, 141, 2, 99, 120, 41, 12, 152, -33, 97, 77, 53, + 59, 144, 7, 26, 145, -17, 59, 151, 8, 83, 100, 39, + 77, -10, 61, 69, -98, 78, -3, -158, 37, 16, -145, 50, + 6, -150, 44, 28, -68, 40, 47, -117, 69, -62, -183, 3, + 25, -97, 47, 27, -119, 56, -34, -144, 17, 30, -138, 66, + -8, -148, 39, -63, -137, -5, -3, -148, 45, -37, -145, 19, + -51, -146, 9, 10, -137, 56, 16, -141, 62, -6, -146, 48, + -18, -141, 38, 10, -146, 62, 22, -132, 68, 43, -119, 81, + 8, -136, 60, 28, -124, 73, 85, -76, 100, 103, -39, 102, + 114, 21, 87, 118, 63, 73, 114, 73, 68, 103, 83, 54, + 74, 129, 12, 119, 59, 79, 116, 34, 89, 116, 41, 87, + 107, 90, 60, 96, 110, 43, 112, 66, 76, 109, 71, 73, + 114, 56, 83, 102, 33, 84, 106, 93, 64, 98, 100, 55, + 101, 89, 63, 107, 85, 72, 105, 76, 74, 45, 130, -4, + -39, 126, -84, -51, 115, -92, -23, 126, -65, 10, 141, -39, + 49, 132, 2, -28, 103, -60, -91, 36, -100, -74, 6, -72, + -3, 145, -49, -37, 155, -83, -53, 99, -80, 74, 82, 45, + 87, 113, 49, 72, -11, 71, 12, -108, 44, 35, -107, 66, + 67, 112, 31, 62, 10, 57, 48, 21, 40, -31, 120, -66, + 19, 34, 9, 75, -92, 100, 92, -81, 115, 82, -8, 84, + 109, 97, 80, 90, -10, 94, 116, 25, 110, 106, 78, 87, + 85, 40, 76, 101, -2, 107, 98, 47, 89, 108, 136, 75, + 93, -18, 105, 101, 107, 79, 72, -5, 80, 45, 4, 49, + 66, -13, 77, -92, -105, -70, -116, -3, -126, -80, -112, -54, + -41, -175, 10, 55, -93, 89, 75, 5, 80, 98, -28, 118, + 99, -9, 114, 116, 57, 113, 75, -20, 92, 46, -138, 98, + 60, 6, 68, 39, -81, 73, 60, -72, 95, 43, -109, 90, + -49, -156, -2, 56, -99, 103, 50, -71, 86, -4, -133, 46, + 44, -94, 90, 23, -141, 85, -100, -116, -74, -87, -100, -64, + 17, -35, 35, 10, -127, 65, 48, 36, 43, 92, -10, 115, + 51, 51, 42, 103, 56, 103, 109, 16, 130, 28, -100, 78, + 18, -163, 94, 41, 49, 31, 15, 153, -49, 18, 117, -26, + 99, 103, 83, 78, 114, 53, 90, 103, 74, 89, 65, 90, + 76, 53, 79, 62, -14, 88, 19, -118, 75, 56, 19, 66, + 49, -39, 84, 65, 59, 63, 17, -34, 39, -23, -173, 43, + 60, -55, 107, 55, 99, 32, 14, -38, 36, 32, -76, 79, + 49, -70, 100, -47, -125, -9, -20, -79, 9, 80, 18, 105, + -21, -130, 32, 56, -2, 81, 36, -42, 73, 46, -97, 113, + -68, -135, -32, -26, -92, 9, 12, -100, 68, -109, -64, -125, + 17, -12, 31, 88, 5, 126, 85, 45, 101, 98, 10, 141, + 33, -89, 96, -10, -72, 24, -108, -124, -95, -9, -120, 52, + 7, -166, 103, 59, 52, 60, 73, 129, 39, 75, 139, 38, + 64, 131, 26, 40, 8, 56, 10, -123, 85, 35, -95, 108, + 38, -102, 118, -6, -132, 67, -46, -141, 11, -57, -137, -9, + -32, -109, 18, 35, -92, 112, 37, -91, 117, 7, -117, 86, + -8, -141, 79, 7, -120, 92, 25, -100, 109, 43, -74, 123, + 53, -57, 130, 57, -51, 132, 67, -25, 134, 61, -36, 133, + 69, -2, 122, 76, 10, 129, 24, -97, 116, 41, -63, 123, + 68, -18, 141, 49, -44, 126, 26, -88, 117, 52, -38, 132, + 78, 18, 135, 79, 17, 141, 39, -36, 107, 37, -65, 131, + 30, -62, 114, 22, -89, 124, 18, -91, 117, 14, -95, 118, + 40, -60, 139, 40, -50, 134, 15, -97, 124, -18, -110, 68, + -10, -135, 113, 59, 79, 51, 69, 184, -27, 23, -36, 85, + -27, -131, 71, -24, -129, 79, -54, -125, 5, -65, -137, -2, + -50, -138, 32, -25, -122, 75, -19, -121, 89, -40, -134, 59, + -56, -139, 28, -80, -120, -45, -70, -128, -14, -80, -119, -43, + -82, -123, -40, -83, -118, -49, -75, -119, -27, -53, -167, 84, + 100, 105, 97, 60, 81, 39, 98, 141, 53, -23, -83, 47, + -79, -124, -31, -87, -103, -72, -57, -134, 37, 63, 50, 81, + 103, 130, 75, -27, -77, 34, -85, -107, -64, -87, -106, -64, + -85, -114, -49, -85, -119, -40, -82, -127, -22, -63, -133, 29, + -81, -128, -14, -89, -107, -59, -88, -115, -41, -79, -124, -8, + -93, -112, -54, -84, -127, -12, -67, -131, 32, -71, -133, 28, + -77, -127, 10, -81, -128, 3, -90, -122, -21, -92, -115, -32, + -91, -119, -25, -94, -115, -31, -85, -125, -1, -77, -137, 40, + -92, -172, 59, -23, -67, 51, -85, -127, 14, -63, -112, 36, + -33, -122, 120, 50, -14, 128, 8, -34, 69, -75, -127, 40, + -100, -130, -6, -84, -36, -120, -97, -70, -91, -105, -98, -61, + -98, -58, -109, -69, -40, -76, -88, -26, -136, -69, 0, -135, + -85, -22, -130, -62, 9, -131, -36, 52, -145, 4, 92, -127, + -10, 81, -134, -54, 23, -132, -42, 37, -127, 30, 113, -104, + -19, 73, -132, -69, 10, -132, -67, 12, -130, -64, 23, -138, + -69, 12, -130, -82, -5, -128, -97, -18, -133, -83, -38, -84, + -62, 26, -130, -73, 16, -134, -92, -30, -104, -67, 39, -149, + -2, 101, -125, 22, 108, -95, 31, 118, -93, -30, 71, -126, + -69, 31, -135, -37, 68, -130, -46, 59, -131, -44, 61, -128, + -40, 68, -130, -79, 17, -126, -101, -20, -116, -90, 2, -122, + -82, 15, -124, -66, 41, -128, -72, 36, -130, -66, 44, -129, + -59, 54, -129, -54, 61, -126, -77, 32, -128, -88, 16, -122, + -91, 12, -122, -94, 8, -120, -101, -6, -112, -94, 8, -117, + -78, 34, -120, -119, -51, -88, -117, -66, -71, -117, -80, -56, + -104, -26, -91, -87, 18, -111, -122, -68, -68, -121, -27, -104, + -86, 2, -92, -126, -117, -26, -112, -44, -74, -38, -120, 71, + -98, -130, 20, -129, -42, -92, -107, -99, -16, -85, -115, 23, + -124, -98, -31, -87, -113, 21, -80, -156, 70, -62, -71, 9, + -173, -72, -100, 30, 103, -70, -25, 85, -105, -8, 117, -118, + -31, 90, -114, -65, 81, -136, -70, 41, -102, -11, 108, -108, + 11, 117, -95, -39, 91, -115, 36, 126, -78, -31, -5, -23, + -84, -123, 30, -33, -105, 63, -57, -130, 65, 4, -102, 94, + 11, -104, 105, -21, -114, 85, -51, -122, 66, -60, -146, 83, + 84, -30, 106, 5, -114, 113, -106, 3, -101, -105, 24, -119, + -2, 109, -105, 33, 121, -83, 13, 141, -119, -96, -66, -25, + -122, -121, 3, -61, -111, 49, -43, -125, 79, 3, -137, 133, + -119, -18, -87, -85, 45, -119, -83, 53, -122, -35, -85, 51, + -7, -50, 41, -116, -89, -16, -71, -54, -8, 227, 159, 44, + -34, -26, -6, -122, -85, -24, -113, -99, -1, -100, -112, 23, + -87, -116, 39, -22, -117, 95, -75, -117, 53, -127, -103, -3, + -114, -89, -7, -114, -97, 4, -128, -46, -59, -127, -32, -70, + -138, -91, -19, -80, 19, -83, -136, -18, -88, -123, -15, -80, + -134, -63, -39, -134, -55, -47, -135, -49, -51, -89, 37, -102, + -50, 81, -118, -69, 69, -117, -36, 76, -99, -50, 97, -129, + -109, -60, -18, 27, -110, 124, -68, -50, 1, -74, 71, -120, + -83, -61, 1, -118, -90, 6, -118, -72, -10, -166, -79, -35, + 33, 81, -56, -45, 52, -80, -106, 31, -99, -54, 89, -120, + -53, 84, -113, -65, 76, -112, -91, 53, -107, -114, 29, -96, + -127, 5, -82, -132, 6, -85, -118, 12, -81, -75, 78, -114, + -42, 85, -100, 49, 106, -64, 45, 112, -72, 8, 121, -99, + 16, 118, -92, 34, 114, -76, -2, 118, -100, -22, 114, -106, + -32, 107, -105, -28, 83, -82, 18, 123, -89, 15, 102, -72, + -23, 126, -112, -27, 98, -90, 16, 148, -104, -36, 111, -104, + -29, 92, -85, -33, 108, -97, -98, 84, -113, -57, 79, -88, + -55, 94, -96, 26, 127, -77, -46, 113, -103, -21, 121, -94, + 3, 124, -84, 5, 131, -85, 52, 127, -59, 3, 127, -83, + -8, 125, -85, -2, 126, -83, 9, 129, -78, 18, 131, -73, + -17, 125, -87, -17, 124, -85, 46, 131, -57, 49, 127, -52, + 73, 127, -39, 73, 123, -36, 98, 120, -20, 37, 121, -51, + 26, 144, -69, 42, 129, -52, 37, 130, -53, 35, 153, -67, + 94, 112, -12, 39, 138, -54, 130, 95, 16, 83, 115, -18, + 94, 105, -6, 121, 87, 19, 92, 135, -20, 126, 100, 16, + 107, 31, 42, 122, 95, 19, 132, 110, 18, 78, 104, -8, + 52, 139, -39, 13, 134, -58, 91, 140, -16, 131, 17, 66, + 131, 106, 25, 24, -114, 68, 87, 14, 43, 94, 98, 9, + 73, 136, -21, 48, 153, -43, 78, 105, -2, 70, 133, -19, + +/* 4 */ +521, 1, -7056, 27453, 9826, + 48, 26, -40, 102, -3, 82, 129, 39, -21, 109, 39, -34, + 149, 63, -76, 128, 57, -78, 109, 51, -74, 115, 37, -34, + 155, 37, -8, 74, 53, -109, 30, 53, -140, 34, 5, 8, + 16, -47, 150, 31, -29, 102, 147, 9, 62, 99, 17, 11, + 87, 16, 4, 95, 1, 51, 162, 24, 19, 128, 16, 22, + 150, 20, 22, 150, 21, 14, 147, 40, -44, 112, 37, -54, + 138, 36, -40, 141, 35, -40, 136, 40, -59, 124, 28, -26, + 101, 31, -51, -186, 8, -106, -101, 20, -105, -103, 19, -105, + -143, -14, -27, -148, -10, -40, -143, -34, 32, -74, 15, -85, + 215, 32, 9, 77, 25, -38, -169, -3, -78, -107, 8, -83, + -49, 5, -41, 160, 34, -24, 89, 49, -114, 72, 13, -3, + 104, -15, 104, 144, 20, 5, 117, 36, -60, -34, 35, -133, + -138, 6, -87, -100, 9, -84, -26, 2, -22, 106, 27, -34, + -46, 31, -131, 9, 15, -50, 67, -33, 153, 51, -38, 155, + 115, -8, 83, 73, -31, 138, 68, -22, 102, -7, -50, 156, + -23, -48, 143, 63, -35, 135, 127, 12, 17, 55, 24, -51, + 83, -28, 119, 58, 46, -118, 28, 48, -137, 40, 54, -155, + -28, 28, -103, 19, 24, -71, -62, 10, -58, 48, 38, -104, + -81, 31, -138, -60, 27, -121, -117, -1, -50, -49, -1, -21, + 156, 41, -69, -66, 30, -137, -147, -11, -32, -25, 17, -76, + 183, 8, 61, 84, 29, -64, -116, 16, -113, -119, -4, -45, + 77, 37, -102, 147, -12, 121, 151, 36, -63, 12, 32, -114, + 100, -13, 92, 106, 9, 16, 105, -20, 118, -3, -3, 10, + -130, -1, -53, 79, -42, 189, 132, 10, 16, 121, 14, -3, + 106, 20, -32, 35, 40, -131, -138, 11, -95, -50, -21, 57, + 10, 46, -169, 69, 37, -110, 76, 18, -43, 138, -12, 102, + 87, -21, 110, 101, 33, -87, -53, 19, -95, -114, 12, -87, + 12, 41, -158, -85, 7, -59, 152, 22, -32, -85, 29, -153, + 15, 11, -41, 84, -23, 129, 122, -16, 112, 95, 37, -117, + 21, 34, -136, -87, 20, -116, -75, 5, -50, 179, 24, -36, + -114, 10, -86, -64, 32, -167, 41, 27, -107, 139, 16, -18, + 125, 9, 5, 132, -15, 116, 94, 23, -70, -19, 32, -157, + -106, 8, -74, -49, 18, -107, 81, 19, -60, 78, 3, 13, + -125, 21, -150, -109, -17, 43, 95, 44, -183, 83, 32, -133, + 61, 27, -122, 133, 24, -80, 108, 28, -115, 38, 30, -154, + 110, 20, -81, 127, 17, -55, -21, 16, -102, -151, -11, 11, + -62, -7, 23, 131, 29, -132, 152, -1, 58, 123, 15, -53, + -21, 16, -106, -143, -1, -43, -83, 3, -50, 228, 12, 1, + 155, 6, 10, 102, 20, -101, 124, 18, -90, 107, 21, -118, + -44, 18, -138, -120, 9, -92, -151, -8, 10, -119, -20, 108, + -142, 0, -54, -144, -19, 79, -121, -20, 92, -119, -20, 86, + -67, -9, 34, 143, 31, -154, 100, 21, -98, 96, 22, -124, + 58, 22, -139, -64, 9, -94, -117, -19, 93, -141, -15, 49, + -96, -5, -11, 191, 29, -131, -90, 8, -108, -158, -5, -43, + -133, -6, -26, -88, -3, -36, 207, 24, -69, 163, 2, 76, + 131, -2, 79, 148, 8, 6, 140, 11, -31, 71, 17, -112, + -85, 10, -124, -73, 5, -72, 0, 13, -123, -135, -1, -55, + -129, -1, -65, -138, -7, -14, -103, -3, -43, 161, 11, -4, + 140, 4, 45, 135, 0, 78, 110, 11, -52, -95, 9, -131, + -94, 6, -119, -143, -1, -77, -135, -4, -55, -94, -4, -21, + -93, -10, 28, -41, -13, 106, -121, -11, 22, -31, 17, -204, + -68, 2, -87, -140, -11, -12, -69, -8, 23, 94, -3, 118, + 85, -4, 125, -5, -13, 134, -42, -6, 17, -30, 11, -134, + -79, 8, -159, -81, -8, 3, -33, -17, 156, -47, -12, 77, + -162, -23, 72, -64, -5, -20, 28, 18, -155, 0, 14, -147, + 4, 14, -151, -96, -8, -23, -86, -20, 128, -92, -17, 74, + -60, -11, 44, -16, 16, -196, -135, -16, 6, 192, 35, -159, + -33, 5, -106, -101, -6, -76, -153, -13, -66, -100, -22, 129, + -62, -18, 139, -13, -2, 1, 47, 17, -149, 52, 17, -141, + -120, -10, -67, -128, -23, 88, -156, -23, 29, -96, -6, -97, + -75, -11, 9, -161, -17, -91, -135, -17, -46, -158, -24, -9, + -66, -19, 118, 82, 4, 124, 20, 1, 35, -159, -26, 8, + -131, -27, 69, -149, -26, 5, -115, -15, -68, -79, -5, -112, + -136, -20, -71, -132, -18, -97, -92, -11, -104, -134, -22, -57, + -126, -27, 35, -85, -27, 146, 3, -8, 117, -31, -12, 78, + -78, -22, 78, 72, 6, 114, 84, 7, 125, 27, -2, 88, + -125, -28, 30, -53, 2, -158, -83, -15, -23, 37, -8, 187, + -6, -3, 18, -45, 4, -159, -37, 4, -148, -69, -4, -134, + -122, -27, 3, -14, -11, 103, 23, 2, 47, -56, -24, 133, + -16, -10, 74, -160, -31, -52, -68, -28, 146, 2, -15, 161, + 38, 5, 36, 82, 20, -10, 39, -2, 103, 14, -6, 92, + 100, 14, 75, 91, 6, 131, 28, -10, 139, 4, -17, 155, + -15, -22, 150, -14, -21, 139, -64, -30, 120, -86, -26, 53, + -80, -37, 132, -46, -34, 162, -75, -38, 138, -88, -29, 54, + -74, -22, 30, -46, -35, 152, -96, -36, 80, -86, -47, 153, + -106, -40, 80, -72, -45, 154, -114, -39, 58, -87, -20, -17, + -31, -22, 74, -100, -39, 73, -184, -50, -1, -85, -46, 120, + 47, -12, 127, 129, 32, 18, 96, 30, -20, 135, 52, -87, + 58, 25, -52, -84, -59, 192, -29, -33, 130, 30, -7, 72, + -124, -33, 1, 72, 1, 88, -94, -29, 17, 21, -3, 40, + -42, -19, 38, 4, -18, 88, -59, -44, 134, -73, -40, 89, + -68, -28, 39, -40, 22, -146, 2, 33, -152, -53, 15, -141, + -78, 5, -131, -105, -33, 17, -23, -37, 147, 48, -17, 142, + -9, -35, 153, 54, -16, 137, 72, 1, 89, 28, -16, 102, + -118, -44, 46, -91, -40, 58, -86, -48, 95, -70, -32, 47, + -128, -40, 7, -97, -41, 45, -118, -10, -108, -108, -16, -70, + -100, -36, 16, 94, -8, 155, 118, 26, 45, 30, -3, 48, + -88, -50, 90, -5, -29, 108, -83, 20, -181, -61, 13, -130, + -50, 4, -82, -53, -5, -51, -41, -34, 87, -148, -38, -42, + -56, -34, 64, 161, 41, 50, 129, 23, 72, 36, -12, 94, + 100, 1, 123, 7, -9, 41, -86, -24, -11, 37, -16, 107, + -82, -3, -89, -56, 15, -129, -59, 16, -141, -96, -15, -64, + -170, -44, -50, -53, -35, 69, 117, 12, 110, 106, 9, 101, + 71, -8, 121, 15, -30, 131, 6, -3, 21, -63, 14, -130, + -40, 21, -135, -110, -11, -99, -118, -16, -95, -78, -29, 14, + -1, -26, 101, 63, -15, 139, -126, -37, -22, -51, -34, 62, + -122, -20, -87, -65, -49, 103, 145, 31, 74, 142, 41, 32, + 143, 44, 17, 143, 37, 37, 121, 19, 78, -6, -8, 22, + -106, -25, -34, -154, -31, -77, -146, -44, -22, -143, -39, -39, + -139, -40, -33, -62, -35, 48, 85, -1, 116, 53, 0, 68, + -184, -35, -112, -17, -28, 83, -15, -32, 96, 130, 28, 64, + 136, 29, 71, 24, -11, 68, -165, -25, -119, -135, -42, -24, + -69, -39, 52, -100, -73, 125, 28, -5, 54, 51, 8, 36, + -181, -67, 0, -74, -63, 122, 195, 74, -5, 104, 26, 40, + 119, 64, -69, -31, -71, 201, -58, -63, 136, -23, -15, 23, + 1, 55, -181, -66, -27, 10, -35, -28, 52, -152, -42, -51, + -76, -18, -34, 133, 15, 117, 47, -3, 66, -180, -32, -116, + -70, -33, 20, 3, -16, 55, -107, -47, 18, 47, -7, 82, + 12, -6, 35, -83, -41, 28, 22, -12, 65, -73, -36, 24, + 25, -30, 122, -38, -42, 84, 60, 16, 22, -98, -49, 33, + -130, -83, 94, 19, -34, 122, -13, -35, 90, -21, -28, 56, + 54, 7, 40, -92, -51, 43, 58, 10, 37, -98, -67, 77, + 57, -17, 114, -21, -11, 7, -77, -40, 22, 13, -34, 109, + 37, -10, 67, -72, -48, 51, -35, -37, 59, 92, 13, 67, + 126, 5, 125, 142, 35, 58, 116, 22, 61, 41, -17, 87, + -146, -56, -6, 60, -3, 69, -97, -55, 42, 59, 0, 61, + -3, -18, 43, 63, -2, 65, -120, -76, 71, 103, 34, 18, + -126, -76, 63, 185, 44, 72, 79, -31, 151, 88, 23, 29, + 4, 50, -116, -5, 45, -116, 126, -9, 141, 57, 37, -37, + 21, 43, -83, 112, 43, -3, -39, 21, -88, 74, 12, 38, + 12, 9, -12, 33, 17, -10, 8, 15, -29, 95, 37, -6, + 19, 27, -49, 73, 31, -12, 4, 15, -35, 104, 47, -23, + 84, 70, -102, 40, 56, -109, 58, 66, -120, 125, 26, 48, + 101, 24, 26, 42, 40, -68, 85, 33, -10, 57, 40, -58, + 43, 2, 32, 57, 10, 24, 76, 29, -11, -12, 32, -96, + 127, 17, 64, 44, 59, -121, -19, 47, -146, 170, 32, 60, + 62, 78, -163, 57, 57, -112, 113, 7, 77, 114, 33, 3, + 98, 67, -107, 127, 23, 38, 118, 1, 92, 107, 28, 6, + 82, 50, -75, 128, 61, -78, 76, 16, 15, -11, -28, 72, + -127, -57, 64, 89, -12, 100, 147, 19, 57, 106, 16, 32, + +/* 5 */ +321, 1, -10216, 27876, 4312, + -33, -1, -76, 72, 20, 45, -2, 15, -106, -14, 19, -164, + 39, 12, 16, 27, 27, -123, 65, 8, 111, 85, 31, -9, + 8, 22, -136, 71, 20, 39, 8, 15, -85, 28, 3, 48, + 4, -19, 148, 36, -10, 148, 91, 34, -10, 5, 22, -145, + -23, 12, -142, -74, 2, -199, 39, 5, 60, 101, 19, 116, + 97, 15, 136, 111, 41, -23, 83, 46, -134, -80, -19, -64, + -122, -34, -49, -149, -37, -113, 40, 14, 2, 175, 50, 71, + -13, 9, -102, -138, -39, -64, 31, 12, -10, 122, 36, 43, + 129, 29, 115, 102, 31, 16, 46, 35, -157, -87, -11, -138, + -56, -6, -113, -222, -73, -11, 83, 30, -16, -1, 8, -72, + 42, 15, -13, 111, 28, 86, 158, 51, 1, -51, -7, -85, + -141, -30, -150, 119, 40, -9, 109, 25, 97, 130, 48, -48, + 40, 27, -149, -81, -18, -74, -180, -53, -52, 108, 42, -72, + -67, -16, -56, 21, 9, -21, 157, 48, 17, -26, -2, -67, + -175, -51, -57, 83, 31, -45, 72, 26, -34, 127, 32, 93, + 78, 33, -99, -164, -42, -116, 93, 29, 7, -46, -7, -95, + 29, 9, 1, 98, 22, 110, 124, 39, -10, 36, 22, -141, + 38, 22, -136, -15, 5, -146, -116, -29, -96, -131, -52, 162, + -2, 9, -138, -168, -59, 92, 30, 17, -111, 82, 29, -61, + 58, 25, -106, -53, -14, -52, -97, -26, -78, 108, 38, -70, + 84, 26, -3, 138, 41, 41, 138, 44, -54, 109, 37, -90, + 137, 43, -56, 61, 23, -112, -40, -7, -144, -129, -34, -103, + -72, -18, -120, -116, -36, 59, -11, 0, -126, -95, -32, 94, + 12, 7, -103, -111, -33, -55, -128, -42, 81, -118, -41, 121, + 9, 6, -99, -97, -29, -88, -120, -41, 52, -76, -28, 121, + -132, -45, 25, -156, -52, -3, 31, 11, -43, -48, -11, -205, + 55, 18, 52, 82, 24, 128, 114, 40, -67, 113, 40, -102, + 130, 44, -64, 145, 46, -1, 132, 43, -41, 135, 42, -15, + 136, 40, 48, 138, 41, 56, 119, 33, 92, 89, 26, -38, + 6, 5, -152, -47, -11, -143, -92, -26, -117, -137, -39, -88, + -116, -35, -60, -150, -46, -31, -133, -41, -51, -142, -45, -12, + -118, -39, -20, -147, -48, 5, -147, -49, 3, -69, -23, 127, + -17, -7, 159, -97, -35, 131, -30, -9, -143, 16, 7, -160, + -128, -44, 2, -123, -44, 84, -87, -32, 123, 5, 0, 128, + 48, 15, 108, -26, -10, 41, -121, -45, 61, -16, -9, 122, + 4, -3, 150, -18, -12, 161, 16, -1, 147, -33, -20, 163, + 142, 56, -94, -32, -16, 89, -94, -43, 172, 87, 35, -57, + 33, 8, 63, -16, -15, 156, -31, -20, 134, 77, 20, 120, + 224, 86, -107, -50, -25, 106, -45, -24, 121, -143, -57, 81, + -4, -6, 52, -12, -10, 76, -63, -30, 87, -88, -41, 97, + -89, -44, 123, -97, -26, -101, -126, -48, 6, 104, 26, 133, + 61, 11, 121, -78, -35, 67, -48, -33, 136, -7, -9, 59, + -98, -47, 90, -40, -27, 104, -124, -58, 86, -110, -55, 90, + -119, -57, 82, -121, -47, -10, -139, -52, -35, -26, -26, 124, + 28, -11, 166, 165, 60, 53, -23, -27, 123, -19, -27, 133, + -49, -40, 137, -121, -51, 7, -58, 0, -158, -127, -38, -102, + 72, 37, -48, 110, 57, -83, 22, 29, -151, -29, 8, -149, + -73, -16, -111, -128, -46, -65, -134, -47, -73, -106, -57, 89, + -119, -68, 133, -79, -22, -93, -88, -24, -123, -86, -20, -158, + -74, -40, 60, -104, -51, 36, 15, 11, -34, 105, 55, -70, + 40, 33, -139, 8, 24, -185, -97, -38, -54, -122, -47, -84, + -136, -60, -25, -121, -62, 56, -57, -38, 119, -8, -19, 140, + 53, 12, 112, 102, 35, 117, 51, 13, 85, 22, -10, 161, + 136, 69, -54, 9, 0, 39, -73, -51, 134, 57, 9, 131, + -80, -45, 58, -83, -53, 109, -76, -54, 126, -40, -37, 125, + -10, -27, 141, -118, -50, -33, -83, -49, 60, -26, -39, 160, + -43, -39, 111, 5, -29, 182, -3, -24, 125, -70, -55, 117, + -21, -37, 139, 21, -21, 160, 19, -20, 146, 3, -29, 150, + 9, -29, 158, 108, 53, -2, 74, 56, -98, 77, 62, -118, + 33, 42, -131, 48, 52, -147, 29, 36, -118, 66, 56, -133, + 81, 63, -139, 58, 14, 68, -45, -49, 153, 69, 32, -2, + 5, -4, 34, -65, -58, 148, -52, -49, 128, 35, 12, 22, + 6, 0, 13, -36, -43, 131, 3, -27, 132, -51, -50, 126, + 48, 17, 25, 94, 46, -11, 111, 64, -64, 148, 89, -103, + -51, -52, 135, 106, 52, -17, 93, 65, -109, 46, 40, -98, + 104, 66, -102, 60, 44, -88, 59, 48, -118, 7, 33, -157, + 61, 47, -111, 96, 62, -119, 45, 40, -122, 45, 33, -83, + 124, 73, -132, -1, -12, 72, -14, -25, 114, 85, 32, 18, + 104, 68, -154, 13, -7, 76, 64, 28, -15, 60, 14, 63, + -60, -47, 133, 21, -19, 153, -70, -34, 34, 1, -17, 94, + 169, 50, 93, -76, -32, 11, -140, -45, -62, -77, -48, 87, + -46, -28, 50, -52, -44, 112, -24, -34, 123, -24, -34, 117, + 48, 9, 49, 121, 63, -59, 141, 74, -81, 41, -4, 97, + 74, 22, 40, 108, 55, -61, 56, 6, 82, 71, 52, -120, + 92, 12, 116, 74, 35, -30, 82, 28, 15, 84, 54, -109, + -55, -3, -90, -92, -25, -50, 27, 17, -35, -66, -7, -93, + 27, 15, -25, 168, 65, -10, -77, -16, -67, -89, -7, -146, + 62, 29, -26, 97, 33, 19, 105, 56, -96, -22, 11, -108, + 61, 32, -54, -91, -27, -41, 30, 18, -40, -51, -10, -57, + 79, 38, -48, -64, -18, -37, 23, 20, -72, 30, 34, -145, + +/* 6 */ +232, 1, 18592, -4797, -23051, + -106, 15, -88, -120, -24, -91, -119, 8, -94, -118, 7, -93, + -120, -52, -82, -108, 20, -87, -97, 76, -88, -109, 63, -95, + 10, 142, -19, 95, 107, 50, 118, 58, 78, 117, 25, 84, + 129, 55, 90, -36, 0, -28, -107, -30, -77, -120, -9, -89, + -118, 13, -91, -134, 35, -107, 36, 120, 6, -13, 12, -11, + -146, -1, -108, 61, 204, 10, -49, -33, -30, -119, -65, -75, + -99, 38, -78, -75, 44, -61, -122, -40, -80, -111, -70, -66, + -120, -44, -76, -131, -23, -86, -92, -37, -57, -116, -80, -64, + -78, -127, -30, -86, -126, -34, -63, -120, -20, -133, -100, -68, + -47, -112, -9, -98, -97, -45, -110, -83, -54, -81, -130, -25, + -117, -86, -56, -123, -29, -71, -124, -22, -72, -145, -4, -88, + -117, -41, -63, -131, -11, -75, -123, -34, -66, -185, -57, -96, + -47, -75, -11, -128, -41, -65, -123, 32, -77, 40, 107, 0, + -100, 58, -68, 45, 25, 20, 127, 31, 66, 127, 50, 61, + 118, 67, 55, -31, 116, -41, 72, 59, 30, 131, 18, 74, + 117, 87, 52, 6, 176, -30, 138, 9, 81, 129, -9, 80, + 77, 116, 25, 78, 118, 27, 64, 119, 19, 56, 148, 9, + 114, 75, 59, 107, 85, 53, 93, 102, 44, 110, 89, 56, + 63, 156, 17, 62, 136, 21, -86, 71, -66, -129, -7, -82, + -135, 30, -90, -20, 131, -30, 76, 119, 32, 95, 108, 47, + 124, 25, 76, 123, 42, 74, 116, 64, 69, 117, 74, 68, + 122, 39, 77, 132, 36, 85, 29, 140, 4, 8, 153, -11, + 81, 116, 43, 89, 110, 51, 116, 51, 75, 100, 96, 62, + 100, 82, 63, 95, 92, 60, 126, 13, 89, 114, 54, 78, + 104, 83, 70, 107, 77, 73, 122, 28, 89, 119, 30, 88, + 117, 44, 86, 115, 52, 84, 111, 58, 82, 111, 59, 84, + 110, 66, 82, 109, 62, 83, 115, 26, 92, 106, 29, 84, + 116, 62, 92, 108, 32, 88, 115, 2, 96, 110, 49, 91, + 106, 67, 87, 105, 65, 88, 107, 57, 90, 101, 75, 86, + 109, 46, 94, 104, 60, 91, 102, 33, 91, 102, -62, 96, + 99, -71, 94, 20, -114, 24, 54, -82, 54, 102, -52, 98, + 111, 0, 105, 59, -109, 62, 65, -115, 69, 63, -110, 69, + 63, -114, 69, 76, -102, 82, 93, -48, 96, 111, 34, 107, + 62, 101, 55, 41, 106, 33, 51, 178, 40, 49, -74, 54, + 47, 53, 45, 60, 125, 53, 28, 146, 21, 13, 151, 6, + -26, 132, -32, -7, 147, -13, 49, 159, 46, 26, 101, 24, + 100, 19, 104, 106, 7, 112, 93, 80, 97, 94, 61, 99, + 99, 46, 107, 103, 0, 112, 92, -59, 102, 79, -95, 89, + 102, -47, 116, 95, -44, 108, 27, -144, 35, 66, -107, 79, + -26, -80, -28, -89, 10, -101, -113, -40, -126, -79, -43, -87, + -25, -126, -21, -48, -117, -49, -96, -86, -100, -104, -7, -113, + -103, -7, -111, -104, 22, -113, -109, -1, -114, -95, 41, -103, + -39, -73, -36, 47, -135, 57, 106, -18, 112, 49, 35, 51, + 92, 22, 96, 70, -108, 81, 83, -45, 93, 94, 29, 101, + 111, -45, 126, -51, -80, -51, -99, -57, -104, -78, -112, -76, + -68, -98, -65, 17, -122, 30, -25, -150, -12, -85, -55, -86, + -90, 52, -101, -34, 127, -48, -36, 147, -52, -73, 194, -92, + 21, -74, 27, -15, -191, 2, -79, -92, -74, -104, -65, -102, + -102, -37, -100, -121, 16, -124, 34, -53, 39, -61, -124, -48, + -100, -76, -92, -105, -15, -103, -110, -21, -105, -106, -32, -100, + -102, -61, -90, -104, -53, -94, -108, -63, -94, -102, -25, -93, + -101, -45, -88, -111, -79, -92, -100, -81, -81, -87, -94, -67, + -89, -135, -61, -38, -138, -15, -47, -141, -22, -114, -156, -77, + -40, -83, -22, -121, -73, -93, 17, -1, 14, 130, -9, 115, + -146, -136, -105, 90, -8, 80, -9, -55, 1, -90, -119, -58, + -3, -143, 23, 17, -176, 48, -104, 50, -100, -46, -39, -32, + -109, -13, -91, -167, 68, -154, -25, -111, 0, -104, -104, -67, + -94, -101, -59, -84, -116, -46, -96, -102, -57, + +/* 7 */ +154, 1, 26493, 2257, -13893, + -76, -31, -149, -74, 37, -134, -66, 79, -108, 57, 125, 126, + -2, 122, 18, -70, 10, -127, -71, 7, -130, -74, 49, -125, + -55, 104, -77, 43, 75, 91, 54, 35, 105, 57, 73, 117, + 53, 89, 117, 73, -38, 129, -4, 82, 10, 35, 49, 76, + 65, -40, 116, 5, 32, 15, -31, 140, -26, -9, 133, 15, + 53, 62, 116, 26, 133, 85, 38, 28, 81, 59, -90, 93, + 25, 88, 73, 47, -149, 54, 56, -117, 82, 48, -93, 74, + 42, -130, 54, 50, -135, 71, 65, -82, 116, 50, -45, 94, + 7, -114, -9, 4, -113, -15, 66, -64, 125, 45, 19, 101, + 66, -38, 135, 57, -93, 104, 62, -52, 127, 54, -50, 112, + 33, -153, 44, 46, -120, 83, 52, -101, 102, 42, -120, 79, + 45, -118, 87, 46, -102, 92, 58, -44, 133, 58, -36, 134, + 57, -37, 135, 57, -22, 139, 54, -54, 127, 26, -133, 49, + 25, -75, 56, 18, -121, 35, 29, -156, 57, 6, -124, 5, + -9, -102, -29, 81, 61, 215, 46, 78, 129, 40, 25, 111, + 57, 3, 156, 39, 94, 117, 26, 50, 77, 42, -95, 109, + 33, -121, 83, 9, -151, 16, 29, -118, 75, 13, -155, 32, + -4, -158, -18, -19, -112, -56, -28, -126, -82, 14, -146, 40, + -12, -145, -30, -32, -83, -88, -10, -97, -26, -50, -35, -138, + -38, -109, -101, -29, -130, -70, 7, -157, 32, -8, -110, -14, + -22, -139, -46, -22, -167, -40, -8, -126, -4, -26, -111, -54, + -57, -16, -152, -43, -3, -113, -56, -11, -142, -51, 28, -136, + -43, 22, -113, -17, 22, -44, -20, -161, -27, -26, -159, -42, + -61, 77, -162, -61, -39, -142, -50, 59, -128, -32, 100, -89, + -26, 34, -66, -52, -93, -110, -56, -29, -123, -35, -99, -66, + -53, 64, -130, -44, 15, -99, -56, -73, -114, -34, -133, -54, + -13, -154, -5, -33, -74, -59, -56, 70, -131, -55, 59, -128, + -58, 55, -130, -56, 67, -126, -38, 95, -92, -27, 130, -73, + 4, 111, -6, -20, 68, -47, -22, 171, -65, -39, 115, -88, + 28, 83, 49, 20, 62, 35, 10, 163, 7, -47, 142, -102, + -36, 123, -79, -12, 41, -25, -60, 19, -119, -48, 126, -100, + -59, 63, -115, -4, 145, -12, 19, 146, 35, -8, 159, -15, + -17, 144, -31, -32, 136, -60, -51, 96, -94, -20, 76, -35, + -5, 39, -8, -65, -89, -125, -68, -15, -126, -73, 10, -133, + -26, 105, -43, 53, 108, 101, 61, 93, 116, 55, 87, 108, + 53, 95, 104, 32, 132, 70, -50, 137, -83, 32, 133, 71, + 38, 140, 87, 23, 98, 55, 49, 127, 109, 6, 116, 26, + 20, 83, 51, -86, 28, -162, -47, 53, -82, 38, 99, 86, + 20, 88, 52, + +/* 8 */ +165, 1, -3761, 29749, 925, + 105, 16, -88, 20, 5, -115, -80, -9, -37, -29, -3, -31, + -47, -4, -80, -110, -14, -41, -136, -19, 81, -100, -17, 132, + 1, 1, -30, 72, 13, -169, 33, 6, -71, 95, 14, -116, + -71, -8, -70, -163, -23, 48, 0, 1, -106, 9, 2, -129, + -147, -21, -153, -110, -16, 31, -7, -1, 135, -53, -8, -61, + -122, -19, -35, -63, -10, 95, 83, 11, 213, -84, -12, -44, + -61, -9, -181, -128, -21, 73, 71, 11, 96, 120, 18, 87, + 71, 9, 180, -31, -5, -34, -70, -9, -133, -142, -22, -76, + -76, -13, 72, 82, 11, 161, 14, 1, 95, -8, -5, 121, + 111, 15, 104, 152, 24, 26, 154, 20, 94, -47, -7, -9, + -156, -22, -41, -25, -8, 124, -41, -6, -17, -91, -11, -125, + -40, -8, 50, -29, -4, -16, -67, -7, -129, -78, -9, -150, + -110, -19, 4, -113, -22, 102, -96, -21, 116, -46, -7, -35, + 58, 13, -93, 118, 23, -94, 104, 20, -112, 24, 7, -151, + -68, -11, -87, -130, -23, 56, -120, -22, 56, -114, -23, 91, + -158, -31, 75, -82, -16, 16, 15, -2, 197, -113, -21, -44, + 25, 8, -118, 19, 7, -151, -71, -13, -140, -128, -25, -53, + -165, -34, -4, 8, 0, 136, 119, 23, 111, -68, -14, 33, + -86, -18, 2, -119, -25, -28, -119, -27, 44, -30, -9, 120, + 205, 42, 85, -71, -15, 8, -158, -33, -60, -80, -16, -72, + 15, 6, -141, 110, 26, -69, 106, 24, -103, -43, -8, -138, + -141, -31, 34, -114, -26, 87, -72, -16, -23, -46, -10, -142, + -126, -28, -99, -150, -36, 4, 32, 7, 90, -57, -14, 93, + 15, 2, 148, -64, -18, 122, 50, 10, 115, 89, 18, 123, + 30, 3, 144, -27, -10, 120, -120, -32, 101, 30, 2, 119, + 126, 25, 109, 91, 18, 84, 144, 33, -15, -11, 3, -107, + 91, 23, -68, 12, 8, -124, 0, 6, -162, 115, 26, -25, + -3, -2, 51, -49, -16, 139, 46, 4, 146, 133, 26, 68, + 161, 36, -43, 69, 8, 150, 100, 19, 16, 75, 13, 51, + 97, 23, -71, 60, 8, 68, 132, 27, -12, 35, 13, -141, + -62, -5, -151, 42, 10, -41, 84, 13, 67, 50, 5, 82, + -5, -8, 156, 61, 14, -56, -16, 6, -192, 78, 13, 33, + 36, 0, 138, 75, 7, 128, 133, 27, -61, 21, 0, 70, + 44, -1, 150, 152, 29, -54, 167, 24, 52, 92, 10, 74, + 145, 21, 23, 139, 18, 43, 150, 19, 39, 151, 18, 47, + 11, 7, -78, -117, -10, -95, -148, -15, -126, 48, 7, 13, + 141, 14, 96, 37, 12, -110, 20, 0, 43, 101, 6, 127, + 105, 9, 88, 154, 15, 60, 145, 17, 13, 77, 17, -129, + 66, 14, -106, 21, 9, -121, -130, -8, -126, 76, 8, 5, + 41, 9, -86, -23, 5, -159, -33, -1, -85, -109, -11, -52, + 25, 6, -75, 8, 5, -139, -90, -10, -11, -124, -18, 83, + +/* 9 */ +141, -1, -21883, 20471, 1436, + 65, 72, -30, 87, 96, -65, 100, 105, -11, 107, 111, -3, + 102, 102, 54, 109, 109, 17, 92, 90, 60, 101, 90, 127, + -65, -68, 57, 36, 31, 57, 109, 106, 20, 79, 70, 98, + 111, 104, 51, -8, -21, 150, -38, -50, 135, -36, -49, 136, + -43, -57, 130, -92, -95, 31, -111, -115, 37, -111, -111, -3, + -90, -84, -66, -92, -84, -97, -97, -100, -2, 16, 3, 123, + 93, 86, 76, 54, 39, 143, -62, -78, 107, -99, -108, 41, + -99, -110, 38, -57, -72, 90, 77, 63, 126, 93, 86, 74, + 105, 111, -16, 107, 112, -13, 106, 102, 39, 99, 89, 73, + 106, 107, -9, 100, 116, -107, 24, 10, 84, -82, -96, 103, + -64, -76, 75, -8, -30, 135, -15, -42, 160, 116, 101, 83, + 60, 64, -21, 94, 106, -86, 61, 78, -109, 63, 76, -93, + 73, 86, -101, 3, 26, -151, 0, 22, -151, 9, 29, -154, + 2, 22, -155, -15, 3, -139, -8, 9, -146, 7, 24, -151, + 28, 40, -138, 43, 54, -139, 91, 89, -30, 73, 74, -77, + 119, 111, -7, 88, 89, -104, 118, 108, -11, 24, 31, -124, + -13, -1, -150, 60, 61, -116, 100, 93, -69, 110, 101, -66, + 28, 31, -127, -2, 5, -150, 26, 30, -153, 34, 34, -165, + -125, -107, -95, -72, -60, -133, -3, 0, -117, -97, -86, -61, + -81, -72, -89, -64, -57, -131, -43, -39, -140, -43, -40, -140, + -67, -63, -120, -81, -77, -105, -74, -71, -112, -82, -81, -130, + -45, -39, 74, 36, 37, 155, 35, 36, 139, -75, -70, 33, + -34, -31, 69, -4, -3, 150, 54, 51, 132, 31, 29, 142, + 51, 45, 135, 68, 61, 144, -91, -86, 86, -2, -5, 78, + 4, -1, 145, -62, -61, 110, -67, -69, 114, -13, -20, 160, + 38, 29, 127, 56, 45, 132, 16, 4, 152, 38, 22, 175, + -80, -81, 76, -9, -21, 153, -37, -46, 111, -91, -95, 80, + -42, -32, -78, -24, -11, -141, 0, 11, -124, 24, 35, -148, + -54, -41, -140, -27, -15, -151, -85, -77, -108, 9, 12, -37, + 14, 18, -89, -17, -13, -76, -97, -91, -71, -97, -92, -70, + -97, -94, -70, -126, -123, -92, 37, 32, 153, -110, -113, 18, + -105, -107, -20, -102, -103, -53, -103, -107, -10, -100, -104, -41, + -103, -108, 0, -99, -109, 34, -103, -112, 0, -102, -112, 13, + -90, -102, 61, -85, -99, 76, -3, -10, 140, 58, 57, 128, + 87, 91, 82, 94, 99, 65, 100, 107, 35, 102, 110, 3, + +/* 10 */ +132, 1, 25827, -2922, -14981, + -63, 23, -112, 19, 140, 5, 21, 141, 11, -16, 138, -50, + 13, 153, -1, 15, 150, 2, 6, 149, -11, -3, 144, -22, + 16, 158, 7, 42, 141, 56, -44, 112, -86, -60, 83, -109, + -75, -8, -126, -28, -102, -36, -4, -168, 10, 29, -144, 65, + -51, -124, -70, -63, -96, -91, -77, -86, -116, -10, -125, 1, + 4, -160, 31, -56, -106, -75, -92, -2, -147, -29, 144, -68, + -75, 45, -127, -81, 15, -127, -33, 114, -68, 61, 79, 85, + 42, 105, 52, 77, 107, 108, -6, 149, -27, -10, 119, -28, + 50, 128, 66, 63, 116, 89, 43, 135, 59, 58, 105, 86, + 82, 146, 124, -61, 9, -101, -61, 102, -105, -75, 53, -123, + -69, 72, -112, -53, 112, -89, -48, 117, -79, -64, 75, -102, + -81, -47, -121, -42, 124, -68, 69, 87, 103, 89, -54, 137, + 55, -52, 87, 80, 8, 126, 72, -53, 115, 74, -45, 120, + 77, 43, 124, 66, -102, 111, 43, -122, 76, 61, -53, 103, + 75, 38, 125, 38, 141, 57, 63, 82, 104, 52, 115, 88, + 20, 146, 31, 1, 150, 0, -27, 141, -45, -44, 124, -75, + -68, 67, -115, -74, -34, -125, -76, -10, -127, -81, 22, -133, + -73, 11, -119, -75, -29, -121, -79, 18, -125, -87, 6, -138, + -72, -3, -112, -84, -17, -131, -72, -76, -110, -85, -8, -128, + -84, 18, -126, -83, 27, -122, -79, 62, -115, -46, 119, -65, + -62, 111, -87, -57, 114, -77, -48, 140, -63, 17, 126, 30, + 71, -46, 100, 74, -113, 101, 46, -90, 63, 68, -92, 97, + 80, -71, 115, 82, -11, 122, 81, 24, 124, 77, 22, 118, + 83, -36, 125, 78, 45, 123, 79, 29, 125, 80, 20, 129, + 77, 10, 124, 72, 58, 119, 63, 41, 105, 81, 33, 135, + 38, -108, 60, 49, -123, 78, 73, 5, 124, 53, -60, 89, + 42, -121, 70, 42, -135, 71, 20, -165, 34, -5, -129, -7, + -5, -218, -5, 50, -60, 89, 37, -137, 69, 31, -131, 61, + -2, -151, 4, -6, -157, -1, 35, -133, 73, 10, -147, 30, + 52, -105, 103, 11, -115, 32, -4, -145, 7, -35, -179, -41, + -67, -3, -120, -71, -23, -124, -23, -150, -21, -35, -129, -43, + -10, -165, 6, 8, -149, 38, 1, -148, 26, 17, -139, 57, + -25, -158, -14, -61, -75, -93, -72, 30, -132, + +/* 11 */ +133, 1, 29737, 2888, -2716, + 9, -113, -12, 8, -138, -52, 6, -140, -72, -2, -106, -100, + -2, -111, -113, -5, -99, -114, -5, -101, -110, -4, -106, -109, + -16, -34, -151, -6, -108, -107, -4, -123, -92, -4, -124, -82, + -10, -97, -118, 1, -147, -41, -1, -134, -54, -18, -43, -138, + -15, -85, -133, -17, -73, -129, -13, -126, -116, -1, -136, -24, + -5, -142, -55, -5, -144, -46, -5, -143, -50, -6, -154, -42, + -20, -65, -126, -23, -73, -133, -11, -130, -64, -16, -117, -89, + -18, -115, -96, -18, -122, -91, -10, -146, -42, -19, -126, -84, + -15, -136, -61, -19, -130, -78, -8, -149, -12, -19, -137, -69, + -25, -105, -103, -24, -111, -94, -22, -131, -73, -26, -107, -100, + -31, -88, -120, -31, -93, -119, -21, -139, -52, -30, -107, -102, + -33, -90, -116, -33, -98, -110, -35, -84, -122, -34, -94, -108, + -38, -70, -134, -36, -100, -107, -31, -118, -80, -38, -108, -108, + -50, -131, -143, 11, 129, -8, -21, 16, -85, -51, -87, -158, + -12, 85, -78, -28, -11, -98, -44, -106, -121, -14, 86, -78, + 11, 150, -16, 9, 150, -19, 11, 150, -8, 11, 150, -5, + 19, 146, 27, -2, 156, -48, 19, 137, 34, -6, 148, -55, + -10, 124, -58, 31, 104, 87, 28, 122, 77, 29, 133, 80, + 43, 39, 151, 41, 13, 150, 34, -129, 151, 1, 99, -15, + -14, 144, -74, 34, 85, 116, 16, 106, 50, 12, 151, 27, + 9, 148, 24, 24, 72, 85, 40, 15, 160, 31, 36, 124, + 31, 99, 122, -1, 135, -10, 6, 103, 22, -5, 70, -21, + -27, 80, -116, -8, 134, -29, 24, 93, 101, 33, 40, 138, + 30, -79, 128, 48, -65, 208, -16, 34, -70, -32, 86, -138, + 11, 125, 52, 32, 29, 145, 28, 59, 129, 17, 117, 89, + 8, 142, 49, 21, 102, 112, 25, 64, 128, 25, 57, 130, + 7, 141, 61, 19, 104, 114, 22, -104, 94, 17, 33, 97, + 19, 84, 121, 14, 168, 114, 17, 44, 107, 0, 140, 42, + 12, 110, 102, 17, 81, 126, 13, 95, 116, 16, 79, 127, + 17, 69, 139, 9, 106, 103, 17, 75, 150, -6, 95, 13, + 3, 124, 86, 0, 119, 72, 3, 113, 91, 7, 106, 117, + 19, 1, 150, 14, 39, 141, 19, -8, 148, 18, -11, 149, + 13, 33, 146, 5, 87, 123, 5, 77, 128, 14, 7, 148, + +/* 12 */ +129, -1, 17606, 18970, 15171, + -13, -69, 100, 24, -118, 119, 79, -124, 60, 75, -119, 57, + 88, -117, 38, 105, -103, 1, 120, -58, -71, 115, -15, -117, + 107, -39, -82, 114, -100, -19, 119, -75, -55, 119, -64, -69, + 111, -41, -90, 109, -28, -102, 103, -17, -111, 72, 31, -131, + 75, 26, -129, 69, 33, -132, 71, 28, -131, 83, 13, -127, + 26, 2, -40, -103, 181, -91, -89, 118, -32, -85, 121, -42, + -65, 119, -69, -79, 119, -52, -55, 115, -80, -90, 101, -15, + -97, 78, 26, -117, 33, 112, -71, 83, -19, 27, 21, -65, + 43, 18, -83, -112, 123, -21, -104, -5, 146, -111, 83, 31, + -87, 114, -44, -49, 113, -96, -21, 93, -105, 128, -44, -107, + 73, -19, -72, 88, -33, -72, 52, 40, -132, 35, 56, -132, + -61, 93, -54, -129, 77, 65, -119, 82, 41, -103, 112, -27, + -111, 101, -2, -98, 4, 127, -60, -33, 129, 37, -112, 118, + 76, -104, 52, 43, -80, 60, -175, 159, -1, -94, 108, -37, + -68, 104, -66, -36, 102, -106, -71, 91, -44, -136, 52, 97, + -108, 31, 93, -127, 86, 30, -99, 45, 57, -105, 116, -45, + -116, 93, 3, -111, 99, -15, -114, 71, 31, -118, 47, 69, + -37, 83, -81, 105, -3, -124, 117, -34, -92, 23, 30, -75, + -173, 114, 35, -11, 82, -119, -5, 84, -127, 73, 16, -120, + 99, 0, -126, 103, -17, -107, 50, 18, -95, -136, 110, -8, + -28, 92, -120, -61, 101, -93, -100, 104, -49, -77, 98, -69, + -117, 55, 57, -84, -14, 134, -69, -10, 106, -112, 43, 68, + -117, 32, 91, -63, -37, 142, -40, -45, 124, -33, -54, 130, + -51, -57, 155, -69, -21, 116, 16, -82, 112, -33, -62, 136, + 6, -73, 108, -68, -55, 161, -91, -26, 142, -28, -31, 78, + 65, -125, 116, 26, -99, 118, -5, -63, 97, 3, -96, 136, + 113, -74, -14, 126, -73, -31, 128, -109, 16, 69, -71, 25, + 101, -143, 90, 74, -109, 72, 117, -96, 4, 112, -93, 3, + 122, -91, -11, 116, -97, 3, 118, -79, -27, 124, -87, -23, + 119, -92, -12, 104, -107, 22, 117, -94, -11, 115, -91, -14, + 122, -32, -100, 119, -63, -59, 6, -38, 42, -102, -1, 123, + -37, -76, 143, 51, -113, 87, 48, -116, 92, 70, -87, 27, + +/* 13 */ +124, 1, 19067, -11237, 20253, + -33, -122, -37, -29, -151, -59, -10, -135, -68, 31, -113, -96, + -3, -132, -75, -21, -117, -50, -58, -142, -31, -39, -139, -48, + -8, -125, -70, 25, -112, -96, -3, -132, -82, 61, -101, -125, + 57, -50, -88, 90, -39, -116, 62, -82, -117, 98, -12, -107, + 113, 52, -80, 114, 71, -69, 115, 51, -85, 112, 14, -108, + 112, 48, -86, 99, 84, -50, 84, 137, 2, 78, 132, 5, + 79, 128, -2, 81, 128, -4, 66, 137, 16, 73, 133, 6, + 68, 135, 11, 59, 138, 20, 67, 136, 10, 71, 133, 3, + 77, 128, -9, 71, 135, 1, 69, 135, 2, 65, 138, 8, + 63, 138, 7, 66, 137, 4, 74, 132, -11, 62, 123, -2, + 67, 148, 4, 69, 134, -8, 66, 137, -2, 71, 133, -13, + 70, 134, -12, 64, 138, -4, 50, 138, 11, 55, 142, 6, + 15, 140, 50, 55, 141, 4, 81, 114, -42, 53, 86, -22, + 56, 154, 5, 10, 135, 49, 5, 138, 55, 14, 146, 47, + 79, 50, -71, 13, -135, -75, 51, -82, -97, 83, 123, -46, + 60, 141, -11, 13, 136, 44, -18, 131, 76, 3, 142, 54, + 22, 147, 34, 18, 146, 35, 14, 147, 40, -2, 145, 57, + -2, 136, 52, -8, 136, 58, -47, 91, 89, -15, 145, 67, + -63, 151, 124, -75, -67, 64, -95, -104, 75, -2, -149, -48, + -41, -140, -2, -54, -146, 9, -100, -65, 91, -94, -118, 63, + -71, 56, 100, -64, -50, 53, -14, -217, -65, -54, -64, 35, + -33, -189, -35, -79, -71, 59, -81, -136, 36, -8, 95, 45, + -59, -48, 45, -115, -224, 35, -47, 52, 72, -109, -77, 85, + -93, -85, 64, -42, -128, -9, -26, -34, 14, -77, 54, 103, + -96, -1, 98, -95, -83, 64, -107, -29, 96, -115, -54, 94, + -101, -38, 85, -108, -40, 91, -38, -156, -28, -71, -134, 14, + -84, -126, 28, -80, -121, 25, -45, -139, -18, -10, -135, -50, + -26, -143, -40, -12, -139, -52, 16, -129, -77, -24, -134, -40, + 6, -139, -73, 2, -130, -66, -41, -141, -31, -45, -126, -20, + -86, -125, 20, -83, -112, 23, -94, -127, 23, -69, -137, -6, + -101, -89, 49, -79, -92, 25, -68, -146, -15, + +/* 14 */ +122, 1, 14146, 19873, -17463, + 104, -90, -18, -83, -22, -92, 35, -96, -78, 124, -19, 79, + 34, 103, 143, 90, -59, 8, 110, -101, -22, 114, -79, 6, + 38, -117, -98, 122, -132, -43, -14, -100, -120, 73, -117, -66, + 97, -107, -32, 92, -115, -44, 111, -100, -11, 100, -112, -31, + 95, -109, -32, 129, -66, 43, 117, -85, 15, 108, -105, -13, + 122, -84, 22, 126, -56, 55, 128, -50, 65, 124, -60, 52, + 109, -21, 80, -26, 124, 104, -148, 120, -13, 56, 19, 71, + 123, -63, 49, 59, -112, -61, 78, -122, -52, 112, -100, 3, + 123, -89, 27, 116, -101, 10, 61, -129, -71, 121, -80, 37, + 112, -15, 95, 39, 56, 95, 115, 1, 116, 111, -11, 102, + 120, -40, 81, 112, -13, 103, 119, 3, 127, 79, 17, 103, + 127, -51, 83, 113, -91, 28, 118, -84, 42, 118, -83, 43, + 122, -71, 62, 115, -81, 46, 105, -30, 89, 100, -76, 36, + 25, -102, -77, -105, -3, -123, -105, 13, -106, -64, -64, -135, + -67, 52, -22, -93, 123, 22, -79, -2, -89, -140, 23, -128, + -81, 13, -73, -106, 51, -61, -130, 25, -112, -119, 61, -63, + -113, 41, -75, -90, -25, -115, -91, -16, -107, -52, -37, -88, + 133, -120, 16, 74, -125, -45, 2, -108, -101, -17, -89, -99, + -88, -30, -115, -106, 89, -20, -124, 123, -4, -101, 92, -11, + -128, 42, -82, -65, 56, -8, 45, 91, 128, -73, 118, 44, + -75, -7, -77, -47, -80, -121, -48, -27, -69, -113, 7, -97, + -123, -9, -120, -108, 79, -23, -159, 95, -51, 5, -137, -123, + -122, 86, -27, -72, 118, 46, -148, 21, -106, -146, 127, -5, + 41, -97, -56, 72, -134, -63, -73, 11, -52, -131, 69, -45, + -89, 124, 40, -123, 82, -26, -54, 64, 16, 6, 109, 107, + -49, 118, 71, -87, 119, 44, -104, 108, 19, -96, 105, 23, + -69, 120, 62, -46, 118, 80, -34, 117, 89, -106, 120, 36, + -113, 25, -66, -58, 35, -10, -57, 106, 63, -108, 106, 23, + -116, 100, 11, -90, 116, 51, -50, 111, 78, -30, 116, 99, + -18, 105, 98, 26, 93, 122, -20, 107, 102, -61, 115, 79, + -36, 99, 82, + +/* 15 */ +125, 1, -1369, 25599, 15582, + -20, -57, 92, -68, -54, 82, 2, -61, 99, -37, -16, 22, + -100, -31, 38, -10, -85, 134, 26, -58, 95, -46, -77, 115, + -69, -80, 116, 34, -51, 81, 137, 48, -60, 11, -18, 29, + -57, -58, 82, -68, -102, 148, -8, -72, 106, -43, -121, 173, + 63, 41, -53, 40, 81, -116, 76, 85, -120, 50, -47, 75, + 20, -62, 93, 45, -78, 120, -71, -85, 116, -66, -81, 111, + 56, -59, 90, 165, 12, -4, 137, 10, -5, 179, 39, -45, + -9, -27, 39, -83, -86, 117, 38, -81, 116, 105, -49, 74, + 34, -64, 90, -22, -82, 111, -3, -101, 137, -99, -17, 17, + -155, -4, -5, -140, -41, 46, -127, -85, 103, 77, -13, 24, + 88, -67, 94, -29, -83, 107, -108, -65, 76, -141, -42, 42, + -111, -69, 79, 75, -53, 75, 202, 7, 6, 82, -38, 55, + 115, -27, 42, 136, -25, 40, 204, 73, -82, -53, -57, 69, + -93, -72, 86, -150, -12, 6, -157, 0, -10, -113, -56, 61, + -88, -76, 87, -105, -74, 82, -96, -71, 78, -147, -70, 71, + 56, -32, 44, 112, 17, -11, 108, 55, -57, 163, 21, -12, + 143, -28, 44, 105, 50, -54, 71, 78, -90, 165, 19, -14, + 136, -37, 50, 150, 25, -23, 162, 43, -49, 127, 8, -6, + 109, -13, 17, 169, 11, -12, 154, -12, 15, 143, 34, -43, + 126, 40, -51, 112, 90, -113, -210, 52, -62, 51, 85, -108, + 113, 70, -92, 97, 61, -79, 47, 88, -116, 0, 90, -117, + -95, 69, -88, -143, 26, -32, -149, -21, 30, -109, 7, -8, + 53, 94, -126, -68, 83, -110, -171, 63, -86, 117, -4, 5, + -23, 73, -99, -29, 82, -113, -91, 80, -113, -134, 48, -69, + -81, 47, -67, -50, 85, -123, -36, 83, -120, -40, 84, -123, + -91, 65, -98, -114, 49, -77, -131, 10, -21, -170, -1, -8, + 40, 14, -19, 158, 50, -66, -58, 48, -74, 3, 15, -24, + 128, 39, -52, 79, 68, -101, 63, 78, -116, 60, 76, -117, + 10, 69, -108, -137, 20, -37, -150, 3, -12, -151, 2, -11, + -198, -25, 27, 48, 56, -86, 63, 67, -102, 116, 55, -81, + 73, 86, -136, -130, 13, -29, -172, -18, 17, -125, 4, -17, + +/* 16 */ +107, 1, -8155, 28629, -3723, + 43, 22, 74, 114, 43, 87, 145, 42, 14, 39, -6, -131, + -6, -21, -148, -12, -24, -151, -31, -28, -139, -45, -33, -139, + -123, -45, -76, -72, -40, -127, -132, -55, -107, -93, -12, 98, + -74, -20, 6, -81, -15, 60, -49, 9, 155, -49, 7, 153, + -17, -12, -53, -6, -18, -105, 12, -19, -152, 17, -19, -152, + -76, -38, -93, -155, -41, 44, -84, -7, 118, -71, -3, 126, + -63, 2, 143, -30, 12, 149, -75, -6, 125, -103, -19, 106, + -136, -31, 101, -16, -15, -73, 31, -7, -125, 82, 8, -136, + 74, 5, -129, 44, -8, -146, 35, -12, -147, 24, -16, -149, + -75, -40, -97, -153, -48, 19, -124, -37, 26, -124, -25, 98, + -70, -3, 130, -87, -6, 156, -108, -36, 9, -131, -53, -43, + -145, -48, 26, -55, 1, 138, -46, 7, 166, -26, 8, 121, + -37, 7, 149, -13, 15, 152, 41, 34, 148, -9, 14, 143, + 35, 29, 142, 108, 52, 114, -85, -25, 61, -85, -21, 96, + -99, -27, 92, -83, -19, 116, -72, -14, 140, -20, 5, 146, + 75, 42, 168, 150, 55, -9, -25, -22, -156, 57, 21, 0, + 115, 40, -23, 5, 9, 95, 60, 32, 128, -63, -12, 140, + 52, 26, 98, 134, 46, -35, 97, 27, -97, 155, 43, -139, + 47, 9, -88, 125, 37, -72, 145, 44, -49, 139, 50, 50, + 140, 47, 24, 142, 44, -22, 144, 45, 1, 147, 45, 5, + 142, 44, 11, 142, 40, -31, 131, 32, -77, 69, 7, -136, + -56, -26, -110, -156, -49, -36, -143, -44, -18, -138, -44, -21, + -157, -48, 5, -91, -36, -72, 53, 10, -68, 141, 45, 13, + 149, 46, 9, 140, 43, 3, 135, 34, -52, 119, 26, -86, + -104, -33, -24, -118, -38, -32, 3, -15, -141, -15, -17, -108, + 21, 4, -18, 108, 45, 108, 134, 33, -41, 111, 19, -114, + -69, -37, -145, -15, -19, -114, + +/* 17 */ +87, 1, -27734, 11163, 2489, + 19, 13, 151, 8, -8, 114, 41, 66, 143, 46, 87, 101, + 23, 15, 150, 38, 58, 119, 51, 92, 110, 48, 75, 125, + 23, 8, 151, 18, -5, 151, 6, -45, 174, -52, -82, -123, + -24, -76, 54, 7, -30, 134, 17, -24, 175, 11, -4, 84, + 6, -40, 142, 33, 17, 158, -21, -103, 125, -4, -70, 140, + 15, -33, 154, 8, -44, 138, 29, 4, 148, 30, 2, 146, + -31, -125, 96, -43, -133, 48, -13, -95, 115, -1, -71, 127, + 28, -12, 151, 33, -11, 167, -25, -118, 92, -62, -109, -91, + -74, -129, -116, 17, -35, 132, 34, 9, 138, 41, 21, 144, + 40, 10, 150, 39, 11, 143, 33, -10, 147, 25, -31, 147, + 56, 28, 174, 28, 1, 102, 54, 47, 133, 73, 59, 183, + 6, 95, -110, 5, 98, -119, -18, 56, -147, -34, 13, -147, + -26, 37, -156, 35, 105, -27, -16, 51, -142, -12, 48, -123, + -27, 26, -158, -10, 45, -116, 2, 88, -143, -4, 36, -84, + 21, 121, -126, -13, -44, 25, -7, -7, -22, -7, 70, -162, + 6, 72, -113, 2, 72, -129, -1, 62, -134, -11, 32, -121, + -30, 7, -168, -3, 53, -136, 23, 103, -108, 13, 79, -121, + -15, 27, -150, -4, 57, -164, -12, 16, -116, -19, 16, -168, + -24, -5, -136, -8, 24, -127, -17, 10, -152, -24, -7, -150, + -40, -51, -137, -30, -23, -156, -24, -20, -131, -39, -54, -141, + -37, -48, -143, -37, -57, -129, -54, -104, -106, -60, -143, -8, + -25, -50, -49, -33, -45, -160, + +/* 18 */ +90, 1, -15425, 23492, 10498, + -58, 1, -87, -121, -46, -78, -123, -67, -36, -115, -76, -3, + -150, -98, -10, -111, -74, -9, -121, -91, 15, -123, -90, 8, + -140, -124, 52, -108, -53, -58, -57, -91, 109, -74, -19, -79, + -202, -127, -49, -95, -37, -76, 59, -35, 174, -100, -68, -17, + -123, -69, -56, -124, -80, -33, -59, -94, 103, 93, 5, 144, + 92, 25, 97, 70, -9, 131, 68, -15, 139, 65, -15, 129, + 77, 6, 109, 128, 39, 115, 109, 47, 69, -18, -33, 37, + -91, -67, -3, 22, -20, 72, 98, 36, 73, 82, 22, 76, + 29, -15, 71, -129, -75, -42, -126, -83, -24, -120, -48, -86, + -25, -57, 73, 105, 25, 106, 117, 75, 26, 167, 94, 60, + 55, 14, 53, 138, 110, -15, 49, 4, 59, -67, -110, 114, + -92, -81, 24, -126, -104, 16, 10, -33, 73, 137, 84, 35, + 2, -23, 44, -76, -97, 73, 64, -24, 128, 138, 100, 5, + 95, 91, -35, 139, 135, -62, -112, -42, -70, 7, 42, -68, + 168, 143, -38, -94, -29, -72, -151, -107, -5, 9, 60, -100, + 90, 96, -57, 109, 58, 39, 166, 93, 46, -59, 6, -90, + -109, -28, -94, 50, 45, -17, 31, 65, -82, 110, 82, -11, + 122, 87, -4, -28, 62, -160, -90, -9, -107, -88, -16, -91, + -105, -24, -103, -11, 43, -103, -60, 20, -130, 24, 49, -67, + 143, 89, 25, -21, 50, -137, -98, -37, -69, -144, -84, -36, + 14, 29, -42, 109, 90, -28, 142, 98, 3, 114, 74, 10, + 124, 88, -10, 127, 75, 23, 36, 67, -95, 60, 35, 11, + 112, 50, 53, + +/* 19 */ +80, 1, 1236, -19143, -23066, + 4, 78, -64, -62, 100, -85, -134, 51, -49, -152, -25, 15, + -51, 9, -9, -6, 134, -109, -98, 76, -64, -52, 106, -86, + -10, 119, -94, -47, 131, -104, 132, 74, -53, 141, -39, 35, + 96, -86, 71, 153, -52, 48, 130, 28, -16, 140, 50, -31, + 184, 72, -44, 56, 78, -56, 49, 121, -89, 49, 124, -90, + 106, 96, -64, 26, -76, 59, -28, -145, 107, 111, 52, -31, + 185, 68, -34, 34, 89, -64, 6, 109, -81, 60, 113, -78, + 86, 128, -85, -13, 95, -70, 101, 119, -75, 101, 59, -31, + 124, 67, -35, 156, 44, -13, 120, 51, -21, 106, 128, -77, + 17, -60, 44, -97, -101, 58, -37, -121, 81, -126, -90, 50, + -22, -105, 73, -98, -107, 66, -161, -157, 98, 46, 101, -70, + -19, -20, 13, -150, -66, 33, -21, -114, 83, 18, -66, 51, + -79, -123, 84, -127, -26, 8, 17, -62, 48, -18, -95, 71, + -63, -151, 111, 6, -115, 90, 33, -74, 61, 33, -132, 109, + 18, -117, 95, 106, -71, 68, 134, -48, 53, 68, -90, 81, + -95, -89, 64, -140, -46, 24, -125, -73, 48, -147, -47, 27, + -111, -103, 77, 4, -80, 69, 30, -117, 102, 69, -104, 96, + 78, -95, 91, -65, -52, 40, -140, -75, 54, -125, 9, -18, + -117, 69, -70, -87, 88, -83, -64, 99, -91, -71, 102, -93, + -83, 99, -89, -74, 93, -83, -53, 144, -123, + +/* 20 */ +78, 1, 24076, 9507, -15164, + 72, -75, 68, 83, 5, 136, 48, 63, 117, 50, 69, 127, + 79, -2, 131, 85, -69, 98, 67, -149, 17, 60, -142, 10, + 52, -139, 2, 27, -144, -44, 40, -147, -23, 64, -144, 24, + 35, -135, -20, 25, -149, -43, 59, -44, 76, 45, 108, 140, + 61, -134, 28, 0, -120, -68, 28, -143, -33, 12, -137, -55, + 20, -151, -45, -23, -78, -82, -26, -143, -118, -68, 139, -44, + -67, -35, -130, 24, -122, -21, 90, -111, 95, 35, -131, -5, + -23, -58, -67, -46, -79, -116, -75, -39, -142, -69, 93, -69, + -87, 51, -117, -59, -72, -129, -41, -96, -108, -47, -146, -139, + -34, 112, -4, -4, 168, 69, -58, -22, -101, -27, -107, -90, + -54, -93, -123, -9, -131, -71, -31, -83, -82, -93, -54, -162, + -1, -132, -55, -55, 5, -80, -40, 175, 12, 68, 60, 126, + 0, 101, 43, 28, 143, 103, -85, 78, -93, 13, 73, 52, + 75, 54, 137, 65, -48, 78, 35, 93, 96, 45, 111, 120, + 71, 12, 116, 83, -91, 88, 54, -93, 43, 68, 62, 137, + 8, 122, 73, -16, 158, 51, -19, 113, 25, 3, 134, 74, + -11, 130, 50, -77, 145, -48, -38, 135, 11, -128, 111, -146, + -35, 5, -54, -60, 122, -28, -72, 141, -35, -64, 134, -25, + -26, 135, 36, 23, 98, 92, -11, 145, 69, -46, 146, 16, + -67, 132, -25, + +/* 21 */ +83, 1, 2308, -19901, -22330, + -8, 114, -102, 37, 64, -52, 88, -4, 12, 15, 49, -40, + 143, -68, 75, 129, -20, 33, 58, 130, -108, 117, 79, -53, + 13, 52, -44, 159, -88, 97, 48, -95, 90, -6, -118, 104, + 58, -104, 101, 115, -73, 82, 56, -86, 87, 28, -109, 103, + -44, -49, 39, -48, 15, -21, 137, -79, 94, 23, -106, 102, + 64, -21, 31, 128, -64, 81, 82, -62, 72, 125, -95, 113, + 111, -64, 83, 114, -43, 62, 54, -65, 75, 180, -33, 68, + 104, -70, 91, 75, -72, 87, 52, -95, 106, 89, -78, 99, + 92, -69, 91, 5, -84, 88, 28, -42, 50, 48, -41, 54, + 4, -88, 93, 43, -78, 93, -69, -50, 36, -151, -62, 32, + -151, 13, -47, -142, -55, 28, -128, -40, 15, -81, -36, 22, + -166, -20, -10, -139, 5, -32, -122, 48, -75, -90, 81, -102, + -75, 81, -98, -121, 75, -99, -19, 93, -100, -36, 101, -109, + -26, 116, -123, 95, 51, -36, -142, 51, -74, -6, 106, -106, + 64, 76, -66, -8, 10, -11, -117, 26, -43, -130, 40, -58, + -86, 73, -83, 130, 90, -69, 113, 80, -60, 71, 52, -39, + -183, -124, 91, -130, -69, 48, -122, -15, -2, -89, -14, 2, + -131, 22, -38, 101, 77, -61, 147, 37, -17, 75, 28, -16, + -148, 29, -47, 47, 27, -20, -128, 29, -44, -120, 64, -75, + -75, 86, -89, -59, 105, -105, -82, 82, -84, -50, 84, -81, + -93, 114, -114, 49, 50, -39, + +/* 22 */ +75, 1, 27917, -4121, -10180, + -55, -66, -125, -56, -60, -126, -57, -37, -134, -56, -23, -138, + -57, -18, -139, -57, -16, -138, -52, 10, -134, -62, -21, -142, + -61, -38, -134, -55, 13, -137, -48, 51, -133, -62, -38, -130, + -64, -61, -123, -62, -52, -121, -63, -24, -134, -50, 5, -112, + 41, 208, 16, 8, 151, -34, 46, 99, 69, 64, 39, 130, + 58, -28, 139, 58, -13, 139, 55, 6, 125, 62, 60, 126, + 35, 106, 46, 37, 122, 49, 42, 130, 59, 62, 14, 144, + 57, 36, 129, 58, 46, 132, 53, 31, 124, 56, 17, 137, + 49, 109, 92, 42, -55, 128, 5, -142, 61, 33, -69, 114, + 52, 21, 133, 54, 10, 146, 53, 21, 139, 49, -6, 144, + 49, 22, 134, 52, 36, 139, 37, 135, 61, 50, 96, 115, + 46, 11, 137, 45, 32, 130, 49, 64, 129, 44, 70, 117, + 32, -31, 117, 40, -15, 136, 44, 24, 140, 45, 29, 144, + 27, -48, 110, -1, -141, 51, 9, -110, 80, 19, -109, 115, + 9, -45, 53, -52, -16, -181, -41, 3, -146, -48, -63, -137, + -36, -68, -93, -17, -140, 4, -49, -31, -150, -46, -12, -146, + -49, -24, -145, -48, -52, -130, -49, -60, -128, -51, -35, -140, + -46, 9, -142, -41, 48, -142, -48, -18, -133, -52, -9, -148, + -52, -31, -132, -42, -26, -108, + +/* 23 */ +73, 1, 11139, 23963, -14202, + 89, -95, -89, 96, -86, -67, 88, -87, -74, 62, -93, -103, + 27, -75, -102, -2, -91, -146, 41, -93, -115, 103, -92, -64, + 82, -97, -84, 49, -95, -108, 72, -97, -91, 71, -97, -90, + 86, -97, -78, 85, -98, -77, 102, -97, -62, 46, -94, -100, + 21, -93, -116, 65, -102, -94, 106, -97, -53, 82, -103, -79, + 46, -100, -102, 94, -101, -63, 99, -102, -60, 50, -103, -98, + -12, -80, -115, -153, 136, 60, -137, 87, 12, -101, -27, -114, + -59, -43, -100, 5, -82, -103, -106, 161, 132, 58, 36, 92, + -16, 109, 132, -15, 93, 115, 18, 72, 113, -37, 101, 112, + -80, 99, 76, -103, 98, 60, -102, 95, 58, -98, 96, 63, + -108, 86, 43, -123, 40, -33, -120, -28, -129, -46, -66, -128, + -22, -79, -126, -11, -17, -32, 10, 103, 152, -23, 94, 117, + -41, 96, 110, -32, 94, 113, -21, 90, 119, -28, 91, 115, + -49, 95, 107, -44, 93, 110, -39, 90, 110, -28, 92, 123, + -42, 94, 116, -47, 86, 103, -77, 88, 84, -61, 43, 25, + -122, 144, 145, -50, 96, 124, -25, 80, 115, -34, 76, 105, + -87, 97, 101, 32, 59, 126, 80, -38, -4, 18, -93, -149, + 66, -71, -71, 143, -69, -8, 122, -18, 64, 55, -58, -55, + +/* 24 */ +68, 1, 24092, 5088, -17137, + 14, -98, -10, -5, -145, -48, 33, -140, 7, 93, -40, 121, + 96, -9, 134, 49, -171, 25, 57, -37, 72, 72, -13, 102, + 56, -137, 47, 123, -90, 158, -21, 70, -12, -5, 154, 32, + 54, 76, 103, 63, -11, 91, 88, -70, 116, 54, -134, 47, + 83, -56, 112, 82, -37, 119, 74, -87, 95, 36, -142, 21, + 41, -143, 30, 42, -141, 33, -57, -49, -101, -54, 145, -53, + -54, 139, -51, -58, 116, -63, -56, -80, -107, -75, 2, -114, + -74, -50, -126, -60, 146, -55, -78, -17, -121, -65, -72, -115, + -30, -130, -74, 58, -132, 56, 28, -144, 10, -1, -148, -32, + -21, -132, -58, -60, -86, -105, -70, -71, -115, -78, -52, -121, + -71, 72, -88, -25, -40, -43, 3, -135, -19, -55, -11, -80, + -62, 126, -66, -30, 143, -15, 18, 145, 53, 41, 111, 80, + -43, 155, -30, -89, 144, -92, -48, -107, -90, -25, -135, -62, + -6, -187, -45, -28, 47, -29, -26, 172, -2, -61, 91, -64, + -61, 132, -55, -17, 146, 9, 25, 128, 63, -10, 163, 25, + 4, 129, 36, 30, 118, 71, -41, 143, -19, 15, 171, 66, + 51, 99, 98, 43, 85, 85, 56, 91, 104, + +/* 25 */ +68, 1, -3077, 27485, 11624, + -135, -30, 35, -65, 39, -111, -105, 10, -54, -99, -64, 121, + -154, -21, 2, -120, 1, -38, -66, -57, 110, -20, 0, -4, + -33, 53, -136, -80, 19, -73, -139, -60, 93, -102, 32, -111, + -81, -55, 100, -91, -36, 52, -127, -52, 72, -35, 8, -32, + -7, 58, -140, 67, 56, -108, -25, 45, -117, -63, 49, -144, + -114, 16, -88, 21, -24, 67, -45, -62, 133, -100, 18, -85, + -92, -30, 34, -25, -40, 85, -48, -17, 20, -111, -25, 13, + -18, -25, 52, 131, 3, 50, 151, 20, 17, 116, -18, 89, + -92, -52, 85, 59, -27, 87, -70, -19, 17, -141, -8, -40, + -184, -28, -14, 47, -17, 60, 159, -3, 75, 33, -37, 97, + 90, -9, 58, -7, -32, 70, -65, -57, 100, -173, -51, 44, + 79, -27, 92, 165, 9, 44, 126, -28, 110, 44, -40, 104, + 116, -19, 81, 130, -23, 95, 170, 15, 27, 110, 36, -41, + 101, 29, -31, 152, 19, 8, 146, 34, -28, 138, 43, -54, + 144, 30, -24, 160, 37, -36, 77, 51, -91, 115, 46, -73, + 38, 28, -52, 37, 37, -73, 19, 40, -85, -72, 46, -121, + -70, 39, -109, -20, 60, -144, 37, 49, -104, + +/* 26 */ +58, 1, -26874, 10130, 8671, + -30, 19, -117, -23, 66, -151, -42, 6, -144, -51, -24, -138, + -43, -88, -36, 31, -48, 163, 11, -85, 140, -45, -130, 7, + -25, -118, 58, 4, -100, 125, -32, -83, -7, -62, -49, -143, + -43, 6, -149, -37, 19, -145, -34, 20, -136, -35, 25, -152, + -32, 27, -147, -55, -103, -67, 2, -78, 105, 18, -88, 166, + 54, 57, 120, 44, 9, 138, 34, -28, 142, 40, -11, 145, + 50, 23, 132, 51, 8, 154, 28, -48, 138, -3, -114, 107, + -6, -95, 79, 34, 16, 85, 63, 116, 69, 64, 135, 53, + 68, 67, 128, 18, -60, 109, 53, -3, 152, 69, 87, 106, + 54, 3, 144, 53, -1, 142, 48, -14, 141, 27, -65, 128, + 48, 29, 96, 70, 121, 68, 2, 113, -98, -17, 86, -124, + -46, 19, -139, -52, 52, -189, 58, 60, 97, -4, 42, -55, + -57, -7, -146, 0, 99, -97, -7, 69, -95, -41, 28, -142, + -35, 39, -140, -28, 57, -142, -55, -27, -132, -47, 19, -160, + -67, -83, -107, + +/* 27 */ +56, 1, 12962, 21402, -16551, + 83, -38, 16, 93, -94, -47, 24, -103, -113, 56, -107, -91, + 92, -105, -58, 75, -108, -76, 119, -90, -15, 74, -104, -67, + 76, -102, -64, 114, -19, 69, 123, 34, 142, 74, -101, -62, + 123, -89, -5, 138, -68, 34, 93, -120, -65, -16, -90, -120, + 45, -102, -82, 78, -121, -75, -106, 20, -66, -130, 85, -8, + -111, -5, -96, -35, 58, 38, 51, 73, 126, 74, 50, 120, + -52, 98, 73, -114, 32, -57, -59, -67, -127, -156, 66, -47, + -124, 18, -77, -72, -56, -123, -64, -63, -122, -78, -53, -119, + -108, -43, -130, -113, 119, 50, -117, 97, 24, -127, 81, -1, + -135, 60, -29, -130, -6, -100, -136, 31, -61, -222, 90, -51, + 53, 27, 67, -12, 111, 120, -41, 101, 89, -122, 116, 52, + 50, -4, 30, 133, -79, 0, 125, -16, 70, 73, 54, 116, + 107, 29, 113, 63, 62, 122, 53, 69, 124, 39, 77, 125, + 17, 88, 122, 19, 86, 122, 28, 80, 125, + +/* 28 */ +49, 1, -6596, 29135, -2761, + 64, 5, -105, 143, 26, -49, -45, -23, -137, -7, -11, -80, + -52, -24, -120, -117, -14, 109, -4, -7, -48, 12, -16, -167, + -112, -12, 117, -20, -17, -107, 15, -13, -142, -115, -29, -16, + -102, -10, 120, -70, -4, 110, 64, 35, 178, -97, -24, -2, + -46, 4, 143, -51, 3, 152, -58, -16, -15, 11, -11, -139, + -6, -17, -145, -41, -26, -149, -146, -33, 37, -68, -3, 132, + 2, 16, 151, 51, 28, 150, 21, 17, 128, 12, 17, 157, + -43, 0, 130, -45, 0, 144, 64, 25, 116, 130, 38, 77, + 128, 36, 64, 141, 33, -25, -48, -21, -136, 56, 7, -87, + 145, 32, -32, 156, 37, 20, 155, 37, 21, 5, -7, -104, + -96, -31, -111, -131, -29, 5, -136, -35, -40, -164, -37, 32, + -15, -13, -109, 72, 4, -146, 157, 33, -47, 128, 29, -12, + +/* 29 */ +50, 1, -2179, 24668, 16933, + -94, -47, 56, -114, 2, -19, -121, -63, 74, -71, -57, 72, + 55, -51, 81, -74, -79, 100, -74, -24, 23, -140, 1, -23, + -215, -15, -16, 15, -80, 115, 25, -50, 74, -131, -82, 90, + 69, -50, 81, 176, -48, 94, -77, -77, 92, -116, -97, 110, + 78, -13, 30, 150, 24, -7, -7, -19, 24, -155, -21, 3, + -117, -60, 58, -114, -68, 70, -67, -96, 113, 136, -15, 44, + -56, -41, 42, 101, -3, 22, -24, -38, 44, 40, -22, 35, + 140, 9, 12, 156, 30, -14, 130, 61, -59, 134, 30, -19, + 124, 54, -53, 169, 33, -22, 148, 16, -3, 87, 67, -77, + 60, 91, -113, 54, 87, -110, -12, 100, -135, 4, 79, -107, + -34, 87, -123, 50, 59, -77, 130, 54, -61, 66, 69, -90, + -38, 83, -120, -40, 70, -104, -66, 70, -108, -232, -9, -14, + -56, 48, -76, + +/* 30 */ +50, 1, -8496, -28645, 2696, + 6, 7, 97, 49, 0, 144, 24, 8, 146, -32, 25, 135, + -71, 36, 135, -115, 45, 86, -123, 47, 78, -138, 48, 41, + -135, 49, 46, -138, 49, 36, -143, 49, 26, -145, 47, -16, + -142, 48, 4, -141, 51, 18, -144, 51, 5, -134, 43, -34, + -154, 58, 22, -65, 9, -110, 10, -22, -149, 67, -40, -132, + 140, -51, -5, 133, -47, 2, 131, -52, -59, 147, -52, -17, + 62, -38, -146, 114, -35, 26, 94, -18, 115, 144, -49, -11, + -14, -13, -167, -62, 6, -134, 96, -33, -22, -1, -9, -91, + 43, -21, -74, -3, -8, -95, 16, -15, -117, 27, -18, -104, + 129, -41, -1, 104, -23, 110, -59, 29, 117, 5, 7, 92, + -49, 28, 130, 53, -10, 69, 122, -30, 76, 62, -26, -69, + 82, -16, 90, 54, -17, -7, -33, -5, -145, -65, 6, -150, + 110, -37, -35, + +/* 31 */ +48, 1, -16082, -24523, 6323, + 62, -6, 135, 71, -10, 133, 70, -10, 134, 98, -29, 121, + 35, 19, 149, 50, 7, 135, -18, 47, 120, -72, 37, -32, + -70, 7, -129, -108, 41, -100, -120, 59, -71, -114, 52, -85, + -119, 59, -75, -119, 66, -48, -126, 76, -37, -158, 98, -42, + -90, 76, 48, -125, 77, -41, -60, 16, -96, -79, 27, -111, + 6, -32, -100, 10, -53, -177, 66, -69, -86, 106, -91, -66, + 77, -31, 92, 56, 6, 173, 62, -71, -105, 26, -52, -137, + 124, -87, -10, 104, -47, 95, 106, -45, 107, 63, -54, -47, + -33, 17, -21, -78, 27, -102, -70, 21, -104, -120, 44, -157, + 127, -72, 60, -25, -5, -96, -64, 3, -173, -15, -21, -138, + 61, -36, 23, 33, 3, 116, 90, -31, 126, 78, -22, 127, + 38, 8, 137, 98, -37, 112, 48, 5, 145, + +/* 32 */ +48, -1, -13245, 26217, -6103, + -33, 17, 145, 9, 34, 134, 88, 65, 92, -23, 16, 132, + -12, 24, 141, 56, 55, 134, 71, 62, 134, 67, 53, 99, + 20, 37, 146, -27, 10, 130, 31, 23, 44, 30, 2, -71, + 45, 45, 128, 43, -2, -129, 7, -27, -165, -8, -15, -61, + 47, 61, 209, -28, 10, 131, -81, -16, 134, -34, -3, 80, + 147, 46, -148, 50, -2, -145, -7, -31, -150, -67, -54, -119, + -76, -59, -114, -44, -49, -140, 20, -21, -151, 57, 0, -131, + 122, 46, -65, 113, 36, -81, 117, 32, -108, 125, 38, -90, + 10, -8, -59, -144, -53, 65, -133, -61, 10, -154, -69, 24, + -2, -31, -133, -11, -33, -121, -82, -67, -111, -15, -28, -88, + 70, 3, -126, 39, -12, -127, 20, 0, -39, -135, -43, 95, + -98, -23, 100, -103, -25, 110, -57, 2, 125, + +/* 33 */ +47, 1, -6930, 29187, -252, + -51, -13, -133, 84, 20, -8, 117, 26, -82, 65, 13, -132, + -2, -5, -157, -116, -27, -23, -134, -30, 78, -112, -25, 89, + -11, 1, 173, -70, -16, 98, -136, -33, 52, -146, -37, 22, + -139, -36, -46, -134, -35, 28, -161, -44, 34, -27, -6, 117, + -79, -21, 134, 90, 24, 168, -115, -32, 93, 2, -2, 158, + 22, 5, 108, 34, 6, 130, -10, -5, 92, 109, 26, 166, + -73, -24, 108, -11, -8, 138, 67, 12, 154, 164, 41, 55, + 91, 26, -33, 146, 35, 46, 85, 27, -99, 66, 22, -142, + 32, 14, -143, -39, -5, -156, -64, -13, -131, -91, -20, -132, + -61, -15, -91, 53, 16, -144, -4, 1, -154, 36, 9, -107, + 132, 34, -37, 32, 8, -118, 82, 20, -41, 55, 14, 123, + 133, 32, -108, 101, 24, -60, + +/* 34 */ +48, 1, 1042, 29488, 5419, + 98, -20, 87, 52, -28, 136, 48, -30, 145, 90, -18, 74, + 119, -22, 80, 56, 21, -116, 10, 26, -136, 46, 1, -20, + 77, -17, 65, 58, 4, -37, 18, -24, 117, -127, -21, 144, + -84, -16, 96, 66, -25, 107, 145, 9, -82, 87, -4, -10, + -100, -22, 137, 57, -12, 41, -157, -3, 54, 75, -34, 135, + 146, -18, 44, 54, -16, 58, 120, -27, 82, 3, 44, -197, + -15, 34, -151, 32, 26, -132, -23, 34, -158, 6, 27, -135, + -22, 32, -159, 62, 22, -133, 69, 16, -114, -170, 29, -92, + -124, 18, -61, -124, 26, -103, -78, 29, -141, -134, 10, -20, + -23, -23, 141, 58, -27, 135, 68, -27, 132, -9, -7, 38, + -96, 31, -142, -74, 27, -129, -76, 1, 11, -52, -14, 94, + -74, 27, -137, -106, -7, 63, -63, -14, 94, + +/* 35 */ +44, -1, 14587, -2200, 26122, + 18, -53, -14, -39, -136, 9, -28, -156, 1, 7, -151, -19, + 52, -138, -43, 34, -136, -35, -65, -137, 21, 28, -129, -31, + 52, -143, -48, 40, -135, -40, 75, -119, -60, 98, -83, -68, + 86, -101, -64, 19, -146, -33, 37, -140, -44, 83, -113, -67, + -4, -196, -31, 100, -60, -69, 118, -90, -87, 54, 91, -17, + -44, 128, 50, -47, 126, 49, -53, 138, 54, -57, 134, 55, + -15, 150, 31, -10, 135, 26, -63, 145, 57, -85, 114, 65, + -118, 38, 73, -68, 131, 56, 69, 122, -25, 18, 132, 6, + -48, 139, 43, 18, 150, 5, -67, 130, 52, 3, 147, 12, + -9, 143, 18, -54, 138, 43, -47, 140, 37, -31, 192, 31, + -63, -85, 29, -21, -147, 1, -15, -153, -4, + +/* 36 */ +44, -1, 15944, 24781, -5628, + 93, -52, 33, 124, -87, -25, 126, -79, 19, 127, -81, 15, + 127, -78, 31, 126, -81, 22, 126, -81, 26, 115, -62, 80, + 121, -74, 51, 111, -60, 83, 122, -74, 64, 118, -78, 32, + 107, -60, 81, 101, -54, 99, 119, -77, 53, 109, -66, 77, + 84, -39, 121, 67, -26, 127, 73, -22, 171, 52, -52, -63, + -4, -26, -148, -53, 14, -135, -74, 29, -129, -81, 36, -126, + -113, 69, -72, -121, 88, -11, -87, 45, -87, -77, 36, -94, + -102, 53, -98, -84, 33, -122, -109, 58, -87, -116, 73, -41, + -107, 52, -101, -84, 68, 40, -92, 63, -6, -26, -2, -86, + -130, 82, -29, -117, 83, 11, -119, 89, 37, -124, 82, -1, + -123, 85, 16, -125, 86, 20, -122, 95, 65, + +/* 37 */ +44, 1, 6601, 28935, 4379, + 16, -21, 118, 74, -36, 115, 54, -21, 53, 5, -26, 150, + 77, -36, 110, 77, -8, -64, 63, -35, 120, 137, -8, -153, + 99, -9, -94, -67, 34, -105, -78, 32, -79, 1, 17, -112, + -95, 35, -77, -28, 26, -131, -93, 35, -87, -13, 23, -140, + -53, 31, -142, -50, 24, -95, -39, 28, -148, -21, 25, -161, + -7, 20, -157, 6, 15, -149, -10, 18, -150, -12, 18, -148, + -31, 21, -151, -53, 22, -115, -115, 35, -98, -143, 30, 10, + -62, 2, 131, 40, -23, 150, 77, -27, 112, 14, -20, 162, + -14, -14, 160, -51, -2, 116, -35, -8, 136, 20, -18, 110, + -6, -21, 176, 29, -27, 157, 59, -32, 142, 15, -21, 127, + 45, -28, 124, 126, -39, 69, 80, -10, -54, + +/* 38 */ +42, -1, -10564, 27211, -6925, + -102, -15, 98, -92, -3, 131, 66, 56, 126, 44, 48, 128, + -57, 9, 136, -104, -63, -95, -54, -66, -186, -40, 2, 75, + 9, 41, 155, 35, 51, 160, 133, 62, 44, -1, 29, 132, + -131, -12, 184, 91, 59, 109, 63, 45, 100, 124, 63, 73, + 24, -12, -107, -3, -29, -133, 85, 0, -151, 111, 20, -101, + 62, 43, 91, 5, 40, 175, 101, 33, -17, 61, -4, -125, + 29, -22, -150, 4, -30, -141, 29, -27, -165, 44, -16, -138, + 31, -22, -139, 26, -52, -249, -70, -3, 91, -103, -4, 137, + -17, 20, 107, -68, 9, 145, -127, -29, 83, -63, -37, -57, + 112, 8, -146, -59, -26, -18, -81, -51, -84, -38, -43, -113, + -39, -46, -124, + +/* 39 */ +42, -1, 15744, -1075, 25514, + 6, -136, -9, 63, -186, -49, 95, 83, -55, 94, 90, -55, + 119, -70, -79, 97, -30, -63, 12, -169, -17, 55, 17, -35, + -7, 158, 13, 95, 44, -59, 122, -38, -82, 132, 139, -81, + -154, 62, 105, 36, 92, -19, 83, 111, -51, 82, 122, -51, + 58, 107, -36, 70, 141, -44, 14, 129, -6, 26, 143, -16, + 116, 32, -79, 133, 71, -91, -25, 92, 18, -136, -72, 93, + -92, 61, 63, -65, 100, 44, -74, 99, 49, -106, 9, 71, + -92, 63, 61, -106, -54, 69, -100, -66, 66, -117, 11, 75, + -123, -63, 78, -116, -49, 73, -53, -98, 33, -59, -142, 36, + -45, -145, 26, 35, -135, -25, -5, -167, 0, -37, -133, 19, + -39, -149, 18, + +/* 40 */ +41, -1, 10098, 22921, 16512, + 73, -48, 22, 138, -59, -3, 139, -57, -9, 146, -60, -11, + 142, -45, -30, 126, -12, -66, 134, -54, -16, 141, -51, -25, + 138, -54, -20, 147, -37, -50, 94, -98, 68, 58, -99, 93, + 28, -94, 108, -126, -8, 97, -117, -8, 91, -8, -77, 107, + -15, -95, 133, -18, -79, 114, -148, -47, 156, 50, 10, -45, + 121, 26, -112, 31, 60, -98, 25, 112, -163, 21, 49, -78, + 108, 22, -104, 142, -26, -64, 12, 61, -90, -98, 100, -65, + -59, 95, -88, -67, 119, -116, -45, 3, 27, -138, 24, 63, + -147, 67, 8, -111, 47, 11, -158, 44, 44, -137, 49, 23, + -164, 88, -15, -109, 6, 60, -145, 39, 38, -141, 48, 21, + +/* 41 */ +41, 1, 13989, -2192, -26448, + 86, -38, 49, 159, 11, 84, -19, -147, 3, -25, -168, 2, + 103, -47, 60, 110, -69, 67, 65, -124, 49, 84, -90, 56, + 118, -11, 68, 123, -16, 72, 99, 59, 50, -6, 147, -20, + 43, 4, 25, 33, -150, 35, 103, -59, 67, 125, -26, 76, + 126, 17, 72, 128, 20, 76, 129, 3, 77, 96, -39, 64, + -67, -118, -28, -129, -48, -73, -115, -87, -58, -94, -19, -54, + -126, -33, -70, -108, -70, -55, -133, 3, -77, -126, 3, -73, + -125, 47, -77, -109, 65, -69, -126, 46, -76, -104, 90, -67, + -74, 114, -54, -136, 14, -74, -116, 80, -71, 47, 156, 9, + -83, 70, -51, -84, 109, -55, 3, 156, -13, 72, 103, 29, + +/* 42 */ +42, -1, 119, 4674, 29633, + -31, -95, 15, -26, -156, 24, 18, -132, 19, -62, -159, 23, + -136, 104, -15, -64, 53, -8, -123, 30, -5, -88, 126, -20, + -38, 71, -11, -139, 147, -25, -6, -84, 13, -198, -34, 1, + 59, 0, 1, 140, -44, 10, 126, -68, 12, 76, -142, 22, + 77, -71, 11, 119, -34, 6, 90, -119, 17, -168, -97, 12, + 162, -8, 2, 59, -58, 8, 85, -120, 15, -8, -136, 17, + -64, -114, 14, -133, -14, 1, -143, 29, -4, 5, -38, 4, + 141, -66, 9, 144, -85, 10, 53, -82, 9, 12, 12, -1, + 65, 176, -20, 5, 123, -15, 18, 141, -17, -3, 172, -22, + -15, 165, -22, -40, 106, -15, 22, 154, -22, -38, 130, -19, + 37, 142, -22, + +/* 43 */ +38, -1, 16496, -5129, 24527, + 30, -143, -51, 63, -127, -70, -14, -142, -22, -2, -152, -34, + -16, -147, -24, 6, -147, -40, -37, -135, -8, -79, -127, 21, + -32, -147, -17, 40, -121, -59, 23, -149, -56, 4, -137, -41, + -17, -147, -30, 65, -116, -79, -4, -132, -36, -3, -139, -41, + 80, -8, -57, 66, 36, -35, 90, -60, -82, -28, 223, 88, + -65, 92, 72, 4, 149, 41, 4, 148, 40, 24, 146, 23, + -14, 143, 49, 31, 146, 18, 82, 121, -26, 40, 144, 9, + -26, 133, 51, -64, 103, 69, -7, 139, 38, 15, 147, 24, + -7, 146, 38, -7, 149, 37, -52, 127, 62, -73, 108, 73, + -84, 19, 60, + +/* 44 */ +38, -1, 18721, 21147, 10116, + -41, 87, -107, -98, 62, 52, -143, 106, 36, -110, 75, 41, + -97, 105, -49, -39, 91, -123, -46, 84, -102, -82, 96, -61, + -35, -57, 189, -109, 39, 111, -41, -10, 94, -11, -64, 155, + 88, -98, 52, -75, 4, 120, 98, -117, 73, -45, 9, 59, + -82, 2, 132, 31, -83, 115, 63, -100, 91, 55, -99, 103, + 60, -102, 97, 96, -108, 48, 92, -108, 53, 108, -100, 10, + 112, -125, 47, 61, 31, -157, 50, -8, -69, 81, -13, -111, + 107, -67, -56, 78, -43, -52, 35, 42, -143, 60, 12, -128, + 7, 52, -114, -103, 91, 4, -42, 103, -130, -71, 104, -81, + -14, 51, -79, + +/* 45 */ +36, 1, -7108, 28862, -4057, + 112, 21, -44, 141, 26, -58, 70, -2, -127, 59, -8, -140, + 41, -15, -162, -132, -43, -72, -146, -39, -28, -93, -43, -120, + -79, -41, -127, -101, -41, -90, -99, -46, -118, -72, -42, -130, + -89, -47, -126, -104, -19, 42, -139, -29, 46, -140, -32, 33, + -141, -45, -27, -129, -30, 33, 1, 29, 162, -10, 20, 126, + -22, 20, 151, 107, 46, 95, 125, 53, 110, 13, 24, 123, + 84, 42, 122, 47, 33, 137, 23, 28, 147, 21, 26, 147, + 19, 25, 147, 47, 31, 140, 148, 38, -8, 145, 33, -34, + 143, 31, -45, 90, 7, -118, -2, -20, -139, + +/* 46 */ +37, 1, -12612, 27178, 1511, + 72, 38, -86, 51, 30, -137, 29, 20, -140, 86, 43, -98, + 125, 58, -54, 2, 5, -97, -129, -57, -48, -136, -62, -7, + -142, -65, 0, -127, -59, -16, -136, -65, -10, -141, -68, 27, + -101, -46, -110, -135, -65, -67, -7, -7, 122, 43, 17, 161, + -73, -39, 70, -138, -70, 15, -30, -19, 113, 92, 41, 116, + 125, 59, 68, 102, 44, 111, 135, 64, 33, 21, 3, 114, + -78, -46, 138, -81, -44, 78, -23, -22, 149, -10, -16, 146, + 117, 48, 114, 81, 43, -43, 56, 36, -114, -34, -6, -149, + 48, 26, -31, 141, 69, -32, 100, 54, -100, 42, 28, -134, + +/* 47 */ +37, 1, 29276, 3899, 5265, + 22, -156, -12, 20, -148, -7, 25, -149, -40, 23, -141, -38, + 27, -130, -71, 29, -62, -133, 23, 8, -143, 17, 59, -142, + 16, 48, -138, 12, 78, -134, 5, 102, -112, -8, 137, -61, + -14, 147, -29, -24, 168, 21, -25, 121, 59, -21, 105, 46, + -35, 154, 89, -29, 151, 46, -24, 87, 73, -36, 155, 77, + -27, 94, 71, -31, 125, 63, -36, 109, 111, -35, 100, 108, + -9, 13, 37, 13, -41, -33, -21, 12, 111, 40, -94, -140, + -21, -21, 139, 23, -150, 12, 9, -135, 75, 20, -154, 24, + 13, -144, 45, 8, -106, 45, 28, -187, -8, 12, -81, -7, + +/* 48 */ +36, 1, 23365, 142, -18817, + 54, 94, 69, 71, 84, 90, 55, 106, 71, -89, 97, -109, + -51, 107, -61, 5, 156, 13, 85, 6, 106, 83, -108, 102, + 38, -107, 44, 63, -122, 77, 59, 53, 78, -71, 119, -88, + -39, 126, -45, 12, 149, 21, 2, 179, 13, 60, -35, 75, + 58, -128, 68, 26, -140, 27, 34, -167, 38, -33, -127, -46, + -5, -131, -9, -18, -143, -27, -26, -127, -33, 5, -151, 6, + -42, -120, -55, -55, -125, -68, -98, -123, -122, 18, 69, 21, + 51, 128, 63, 35, 139, 44, 20, 146, 25, -13, 161, -16, + -91, 11, -115, -90, -33, -115, -90, -48, -113, + +/* 49 */ +37, 1, 12054, -19593, -19257, + 58, -35, 73, 97, -42, 105, 128, -35, 118, 76, -28, 78, + 119, -11, 92, 139, 38, 53, 138, 60, 31, 139, 47, 46, + 150, 29, 75, 20, -63, 80, -55, -105, 73, -90, -108, 53, + -102, -105, 42, -115, -92, 20, -144, -146, 60, -2, -74, 81, + -90, -96, 45, -115, -98, 31, -136, -92, 12, -107, -61, -2, + -121, -47, -28, -125, -31, -47, -44, 57, -94, 2, 89, -98, + -12, 104, -125, -58, 4, -41, -130, -56, -20, -12, 60, -73, + 56, 106, -82, 24, 102, -94, -22, 103, -124, 4, 65, -66, + 55, 112, -84, 57, 124, -94, 51, 106, -79, 89, 97, -43, + +/* 50 */ +35, -1, 19917, 21699, 5700, + 29, -54, 98, 74, -89, 80, 71, -89, 81, 117, -98, -43, + 149, -117, -89, -65, 77, -55, -92, 102, -55, -66, 74, -48, + -63, 79, -75, -15, 46, -128, -73, 99, -122, -7, 36, -126, + 0, 20, -82, 55, -15, -153, 24, 8, -132, 59, -21, -154, + 38, -6, -140, 57, -21, -152, 56, -26, -134, 24, 4, -131, + 12, 19, -164, -98, 108, -91, -24, 0, 117, 13, -42, 160, + -47, 15, 150, -32, 3, 135, -31, -10, 186, -40, 10, 120, + -62, 32, 114, -59, 24, 133, -18, -19, 153, -60, 19, 148, + -14, -23, 145, 51, -77, 121, + +/* 51 */ +41, 1, -4651, 29635, -334, + -52, -9, -74, -147, -23, 34, -42, -8, -77, -99, -18, -81, + -123, -20, 85, -33, -7, -116, -111, -20, -20, -90, -14, 125, + -50, -10, -19, -114, -21, -33, -8, 1, 154, -26, -4, 153, + -56, -10, 94, -19, -3, 3, -17, -5, -154, -57, -12, -126, + -136, -26, 27, -122, -24, 97, -135, -27, 24, -69, -14, 135, + 99, 21, 106, -44, -9, 81, 29, 6, 59, 132, 26, 32, + 192, 38, 20, -76, -15, 25, 68, 13, 79, 90, 16, 80, + 176, 33, 59, 66, 14, -123, 115, 21, -51, 121, 22, -35, + 132, 23, -23, -34, -5, -74, 72, 12, -59, 92, 16, -81, + 130, 21, -85, 143, 23, -50, 127, 19, -77, -47, -8, -78, + +/* 52 */ +36, -1, -17857, 23953, -2714, + -69, -60, -74, -114, -77, 71, -109, -75, 72, -111, -79, 56, + -48, -29, 82, 11, 18, 91, -92, -64, 75, -104, -78, 30, + -34, -17, 108, -110, -89, -23, -114, -97, -55, -121, -99, -25, + -87, -64, 75, 84, 79, 111, 148, 122, 32, 97, 77, 3, + 108, 81, -59, 113, 84, -44, 119, 88, -48, 109, 83, -14, + 127, 93, -33, 122, 88, -40, 115, 85, -19, 118, 82, -46, + 120, 84, -39, 117, 82, -19, 111, 82, 21, 20, 10, -41, + -121, -93, -68, -89, -63, 17, 41, 6, -221, -119, -96, -77, + -111, -88, -54, -84, -51, 93, -21, -2, 111, + +/* 53 */ +35, 1, 18868, 16148, -16830, + -118, 111, -25, -43, 93, 43, 11, 86, 96, 13, 65, 80, + -48, 105, 49, 114, -9, 121, 18, 89, 111, 17, 51, 71, + 110, -37, 91, 106, -88, 33, 119, -56, 84, 104, -67, 55, + 59, -94, -25, 14, -90, -75, 31, -109, -72, -118, 47, -94, + -89, 136, 32, 1, -144, -144, 42, -99, -48, 106, -129, -3, + 109, -104, 29, 50, -132, -68, 70, -135, -46, -4, -81, -81, + -71, 16, -68, -57, 139, 63, -46, 8, -45, 42, -135, -77, + 28, -89, -51, -151, 124, -59, -109, 73, -57, -77, 126, 31, + -77, 126, 31, -79, 109, 15, + +/* 54 */ +34, -1, -21907, 20246, 3192, + -62, -57, -63, -62, -48, -135, -75, -66, -110, -9, 14, -170, + 89, 99, -5, 37, 16, 170, 72, 80, -15, 8, 22, -95, + -99, -99, -67, -102, -102, -62, -104, -108, -58, -69, -101, 179, + -23, -35, 65, 4, -14, 128, 45, 28, 147, 34, 15, 146, + 79, 69, 114, 66, 51, 126, 59, 41, 134, 78, 57, 154, + 53, 39, 99, 73, 56, 121, 83, 67, 108, 86, 73, 96, + 96, 95, 30, -4, 7, -52, -61, -36, -142, -38, -12, -144, + -92, -70, -152, -38, -33, -48, -3, 24, -148, -11, 13, -148, + -54, -35, -133, + +/* 55 */ +35, -1, 16309, 24931, -3533, + 24, -3, 89, 102, -57, 80, 68, -50, -39, 119, -92, -89, + 3, -15, -89, 113, -84, -51, -16, 8, -19, -118, 83, 21, + -65, 59, 106, -107, 77, 39, -82, 40, -99, -36, 5, -122, + 95, -76, -91, 106, -81, -69, 108, -83, -62, 121, -82, -3, + 117, -79, 4, 120, -91, -49, 114, -76, 25, 143, -110, -53, + 45, -39, -40, 151, -125, -101, -105, 68, -46, -62, 57, 77, + -92, 82, 95, -114, 79, -6, -96, 70, 18, -103, 81, 65, + -121, 83, -3, -122, 84, 8, -113, 84, 57, -102, 78, 64, + -130, 97, 79, -13, 30, 141, + +/* 56 */ +34, 1, -15019, 23246, -11578, + 109, 18, -104, -8, -59, -108, -129, -62, 43, -61, -2, 74, + -119, -114, -69, -118, -32, 90, -114, -45, 62, -120, -54, 54, + -76, -47, 10, -63, -67, -48, -110, -26, 101, -106, -69, 10, + -122, -55, 61, -65, 16, 124, -4, 20, 46, -69, -112, -125, + -155, -65, 94, -104, -37, 77, -117, -37, 99, -52, 21, 122, + 94, 83, 26, 134, 97, -1, 115, 80, -6, 112, 50, -61, + 129, 45, -96, 120, 79, -9, 126, 83, -9, 123, 85, 1, + 117, 61, -36, 110, 26, -100, 108, 20, -106, 110, 25, -95, + 117, 39, -76, + +/* 57 */ +31, 1, 24179, -4896, -17070, + -65, 75, -114, -78, 42, -120, -77, 49, -120, -76, 50, -118, + -72, 60, -113, -75, 58, -116, -73, 68, -113, -20, 115, -55, + 105, 9, 137, 84, -42, 122, 87, -6, 119, 85, -18, 122, + 87, -9, 122, 82, -28, 122, 76, -55, 122, 38, -121, 87, + 63, -80, 112, 67, -61, 115, 75, -44, 123, 64, -73, 116, + 48, -105, 102, 6, -142, 53, -20, -122, 10, -9, -116, 25, + -88, 19, -138, -65, 66, -119, -79, 37, -127, -50, 101, -104, + -46, 108, -98, -25, 98, -65, + +/* 58 */ +32, -1, 13075, 24485, 11382, + -40, 52, -67, 14, 58, -144, 17, 52, -134, 58, 32, -141, + 64, 23, -131, 84, 3, -110, 29, 56, -168, -70, 28, 21, + 28, -54, 92, -76, -21, 143, -85, -7, 120, -75, -15, 123, + -112, 2, 128, 48, -60, 76, 21, -74, 139, 51, -82, 117, + 6, -62, 126, 108, -94, 76, 136, -62, -25, 95, -80, 56, + 132, -88, 31, -6, -35, 77, 19, -10, -1, 87, 45, -194, + -90, 24, 57, -82, 74, -60, -55, 107, -160, -47, -20, 96, + -93, 19, 67, -130, 74, -7, 6, 68, -152, + +/* 59 */ +29, 1, -3768, -29624, 2870, + 45, 4, 94, 51, 8, 142, 59, 8, 138, 57, 8, 140, + 32, 14, 147, -48, 21, 129, -31, 19, 118, -91, 29, 135, + -153, 28, 63, -79, 26, 117, -175, 25, 11, -15, 23, 147, + -106, 32, 113, -149, 24, 16, -144, 16, -43, -99, -1, -109, + -16, -19, -150, 25, -24, -149, 63, -27, -134, 90, -29, -121, + 104, -29, -106, 115, -28, -96, 77, -26, -128, 55, -24, -143, + 18, -17, -146, 25, -18, -143, 94, -24, -118, 135, -18, 2, + +/* 60 */ +30, 1, -8205, 28819, -1455, + -49, -18, -95, -107, -35, -74, -126, -34, 63, -131, -39, -8, + -112, -37, -59, 28, 1, -121, 135, 35, -82, -84, -32, -116, + -139, -40, 39, -129, -35, 72, -87, -21, 110, -125, -35, 71, + -130, -38, 69, -142, -45, 39, -90, -25, 91, 165, 60, 100, + -39, -7, 122, 87, 34, 140, 111, 37, 34, 135, 43, 22, + 151, 48, -12, 99, 28, -61, 93, 23, -132, 107, 34, 45, + 114, 37, 99, 118, 37, 66, 92, 23, -93, -35, -17, -168, + 71, 16, -104, + +/* 61 */ +29, 1, 7341, 28492, 5857, + 97, -32, 32, 101, -8, -91, 129, -14, -97, 162, -48, 17, + 98, -50, 115, 136, -21, -86, 121, -12, -115, 86, -3, -109, + 72, -2, -102, -8, 21, -96, -159, 39, 35, -146, 40, 12, + -144, 44, -24, -140, 46, -37, -124, 42, -50, -140, 56, -98, + -76, 35, -88, -83, 41, -114, -72, 38, -113, -150, 34, 21, + -99, 7, 103, -38, -17, 146, 65, -39, 131, 10, -25, 118, + 113, -37, 53, 95, -48, 123, 24, -30, 120, 10, -30, 139, + +/* 62 */ +29, -1, 13904, 22523, 14121, + -19, 93, -130, -23, 88, -121, -50, 95, -107, -21, 87, -123, + -56, 98, -110, 21, 65, -132, 94, 11, -117, -1, 23, -38, + -119, 33, 67, -106, 103, -71, -21, 80, -120, -112, 91, -46, + -36, 86, -118, 14, 66, -135, 29, 34, -93, -62, -54, 165, + 2, -75, 134, 67, -88, 88, 98, -84, 48, 7, -77, 128, + 102, -95, 60, 3, -81, 136, 40, -91, 114, 25, -96, 136, + 43, -85, 97, 37, -90, 110, 16, -85, 122, 27, -77, 97, + +/* 63 */ +28, 1, 25599, 5928, -14475, + 33, -94, 20, 47, -160, 19, 25, -90, 9, 54, -136, 45, + 62, -80, 82, 68, -111, 82, 64, -115, 73, 67, -111, 84, + 64, -114, 80, 67, -92, 92, 70, -85, 104, 66, -104, 89, + 83, -190, 98, -58, 18, -106, -67, 77, -103, -69, 92, -101, + -62, 118, -76, -74, 76, -112, -63, 115, -76, -50, 130, -45, + -49, 115, -48, -82, 54, -127, -63, 120, -70, -85, 80, -120, + -20, 137, 18, -2, 140, 50, -28, 146, 8, + +/* 64 */ +32, -1, 6784, 26265, 12812, + 67, -5, -26, 37, 57, -138, -28, 66, -122, 80, 12, -69, + 61, 44, -129, -45, 71, -128, -100, 88, -136, -27, -50, 125, + -98, -3, 60, -133, 7, 57, -138, 81, -102, 150, -27, -21, + -68, 39, -49, -93, 73, -111, -118, 16, 28, -118, 39, -26, + -94, 67, -101, 3, -10, 21, 80, -70, 114, 132, -63, 72, + 51, -75, 137, 30, -24, 37, 111, -40, 28, 127, -51, 42, + 128, -39, 13, -13, -32, 75, -26, -49, 117, -67, 10, 14, + -87, 2, 44, -6, -49, 104, 157, -56, 33, + +/* 65 */ +26, 1, 23238, 12726, -14073, + 76, -64, 69, 88, -121, 37, 88, -105, 55, 84, -121, 34, + 85, -121, 37, 85, -123, 38, 63, -143, -15, 66, -149, -15, + 20, -115, -62, 24, -144, -78, -22, -86, -109, 2, -174, -136, + -72, 113, -31, -71, 134, -10, -86, 111, -53, -84, 118, -43, + -72, 126, -15, -71, 138, 0, -69, 136, 2, -69, 134, 1, + -84, 129, -26, -57, 123, 16, -79, 157, 9, 20, 93, 117, + 66, -5, 101, + +/* 66 */ +30, -1, -15626, 24491, 7484, + -83, -67, 46, -114, -88, 46, -68, -5, -126, 97, 105, -140, + -44, -32, 12, -109, -104, 110, -71, -25, -74, 17, 58, -157, + 56, 86, -168, 55, 54, -62, 99, 90, -93, -46, -30, 1, + -111, -81, 30, -107, -95, 90, 51, 32, 2, 18, -7, 67, + -44, -71, 143, -29, -57, 126, -127, -117, 107, 61, 42, -4, + 84, 48, 25, 129, 58, 89, 23, -29, 138, 54, -12, 150, + 97, 37, 80, 1, 22, -66, -33, 14, -112, 39, 65, -125, + 78, 80, -95, + +/* 67 */ +28, 1, 5003, 28957, -6038, + -142, 13, -55, -88, -5, -93, -122, 12, -36, 6, 39, 188, + -80, 41, 141, -68, 3, -37, 111, -44, -128, -14, -26, -135, + -116, 1, -81, -120, 35, 77, -93, 33, 90, 63, 26, 174, + 99, 6, 101, 23, 27, 152, 62, -3, 38, 127, -37, -87, + 58, -6, 16, 1, 28, 142, 27, 27, 171, 115, -13, 30, + 134, -33, -55, 109, -32, -70, 98, -34, -89, 43, -40, -165, + 3, -30, -143, -109, 2, -89, -95, 20, 19, + +/* 68 */ +26, 1, 7323, -10567, -27106, + 121, 94, -3, 142, 73, 11, 122, 50, 15, 31, -23, 18, + -79, -118, 23, -100, -126, 21, -116, -102, 8, -99, -88, 8, + -118, -114, 14, -116, -87, 5, -129, -67, -7, -133, -64, -7, + -148, -82, -3, -104, -89, 11, -126, -59, -5, -162, -43, -21, + -51, 84, -47, 121, 97, -12, 115, 83, -7, 115, 86, -8, + 145, 83, 2, 105, 59, 3, 128, 90, -4, 105, 115, -18, + 106, 86, -6, + +/* 69 */ +26, -1, -20783, 20998, 5211, + -67, -40, -109, -67, -36, -125, -76, -30, -203, -20, -37, 79, + -61, -46, -71, -3, 31, -149, -35, -6, -136, -49, -20, -142, + -48, -19, -142, -60, -36, -128, -82, -63, -113, -105, -93, -75, + -44, -64, 90, 45, 20, 138, 58, 32, 135, 44, 16, 144, + 25, -6, 149, 1, -33, 149, 37, 2, 157, 44, 16, 125, + 87, 62, 112, 80, 63, 76, 114, 121, -22, 74, 80, -27, + 100, 72, 109, + +/* 70 */ +27, 1, -22450, -137, 19899, + -70, 14, -79, -99, 23, -113, -98, 19, -113, -86, -40, -100, + -104, 11, -123, -96, 32, -113, -97, 9, -116, -84, -60, -104, + -22, -179, -28, -32, -108, -41, 50, -137, 58, -19, -49, -25, + -30, -140, -42, 56, -135, 63, 66, -76, 77, 47, 77, 60, + 23, 0, 27, 79, -32, 94, 92, 11, 109, 82, 77, 100, + 97, 22, 114, 89, 69, 105, 33, 101, 41, 70, 117, 83, + 32, 144, 39, 35, 156, 42, + +/* 71 */ +25, 1, 23559, -1507, -18512, + 27, -75, 40, 43, -174, 71, -57, 80, -80, -63, -34, -78, + -88, -88, -102, -96, 83, -128, -85, -47, -100, -97, -34, -115, + -66, 45, -84, -109, -20, -130, -84, -84, -92, -92, -58, -103, + -106, -83, -115, -37, 97, -53, 50, 123, 46, 60, 131, 59, + 87, 78, 95, 102, 9, 121, 87, 54, 99, 99, 35, 117, + 97, -53, 123, 84, 32, 102, 97, -3, 120, 94, -4, 119, + +/* 72 */ +25, 1, 25640, -4315, -14965, + 31, -45, 66, 54, -65, 113, -15, -155, 20, -76, -10, -128, + -74, -2, -127, -82, -20, -132, -78, -42, -117, -79, 26, -139, + -74, 13, -124, -72, 1, -117, -70, 50, -127, -81, 13, -132, + -77, 64, -138, -16, 182, -75, 15, -33, 33, 65, -78, 123, + 50, -80, 100, 83, 61, 115, 72, 4, 114, 69, -29, 120, + 79, 35, 120, 80, 57, 116, 85, 40, 131, 72, 15, 117, + +/* 73 */ +25, 1, 6329, 18585, 22684, + -107, -21, 47, -119, -30, 56, -133, -23, 54, -136, -32, 61, + -142, -5, 39, -143, 15, 24, -151, 47, -3, -153, -26, 57, + -110, -33, 51, -5, -114, 92, 127, -70, 27, 147, -37, -4, + 135, -68, 21, 136, -61, 15, 141, -32, -11, 132, -59, 13, + 114, -83, 35, 151, -27, -19, 56, 56, -58, 26, 118, -100, + -68, 102, -61, -5, 117, -92, 38, 106, -95, 58, 104, -101, + +/* 74 */ +26, -1, 7748, 26705, 11261, + 129, -68, 72, 75, -7, -35, 137, -55, 31, -13, -50, 125, + -161, 55, -14, 49, -48, 77, -43, -4, 39, -135, 66, -60, + 2, -12, 25, 126, -63, 59, 99, -70, 91, 122, -60, 54, + 141, -38, -16, 147, -75, 66, -108, 0, 77, 30, -27, 38, + 172, -30, -57, 50, 41, -128, -18, 56, -112, -120, 65, -62, + -126, 68, -62, -106, 65, -74, -69, 75, -127, -124, 50, -29, + -152, 41, 9, + +/* 75 */ +24, 1, 14610, -1401, -26164, + -43, -57, -21, -121, -61, -64, -114, -84, -57, -111, -85, -55, + -108, -95, -52, -127, -52, -64, -100, -97, -45, -86, -118, -37, + -64, -137, -22, -14, -151, 6, -73, -146, -24, -89, 52, -51, + -27, 143, -26, 41, 133, 10, 95, 100, 40, 117, 78, 55, + 94, 100, 41, 108, 104, 50, 105, 90, 50, 116, 72, 58, + 117, 80, 58, 121, 59, 63, 112, 86, 57, + +/* 76 */ +25, 1, 26396, -4371, -13570, + 27, -28, 63, 47, -88, 120, -11, -160, 33, -56, -86, -80, + -64, 15, -130, -65, 22, -135, -62, 42, -131, -63, 33, -130, + -48, 80, -115, -27, -30, -40, -87, -20, -155, -63, 65, -133, + 31, 142, 11, 67, -4, 122, 35, 47, 51, 74, 2, 136, + 69, 92, 100, 70, -21, 139, -48, -125, -52, -73, -63, -118, + 3, -64, 27, 69, -13, 135, 70, 102, 98, 63, 32, 111, + +/* 77 */ +23, 1, 26582, 10216, -9436, + 30, -17, 65, 49, -62, 75, 75, -102, 105, 70, -87, 108, + 50, -116, 22, 46, -147, -22, 35, -144, -49, -19, -79, -135, + -30, -43, -131, -46, -32, -162, -77, 83, -132, -44, 43, -79, + -77, 97, -116, -52, 90, -53, -60, 147, -15, -92, 167, -77, + -58, 74, -78, -40, 143, 40, 36, 48, 144, 48, -10, 118, + 63, -23, 148, 48, 1, 132, + +/* 78 */ +23, 1, -8254, 28832, -761, + -97, -27, 32, -31, -10, -50, -97, -30, -58, -158, -48, -10, + -145, -44, -22, -132, -40, 25, -139, -43, 23, -146, -46, 14, + -16, -2, 144, 146, 49, 85, 167, 51, -32, 34, 13, 112, + -19, -4, 154, 118, 38, 92, 128, 39, 47, 135, 41, 74, + 140, 41, 77, 82, 23, -61, 17, 4, -155, 43, 11, -104, + 41, 10, -148, -16, -8, -141, + +/* 79 */ +24, -1, 14884, 12125, 23053, + -8, -117, 67, 30, -56, 9, 26, -101, 36, -42, -130, 92, + -29, -120, 79, -101, -11, 69, -108, -19, 77, -76, -80, 87, + -61, -124, 97, -48, -109, 82, -33, -127, 80, -2, -59, 28, + 57, 166, -112, 62, 118, -94, 74, 73, -82, 52, 104, -83, + 117, 0, -73, 92, 82, -99, 54, 95, -82, 72, 29, -62, + -24, 146, -59, -33, 131, -46, -56, 133, -33, + +/* 80 */ +24, 1, -6839, 29182, -1275, + -120, -28, 3, -163, -38, 26, 40, 6, -75, 150, 32, -101, + -80, -22, -42, -160, -38, 24, -18, -7, -50, -43, -16, -102, + -84, -21, -8, -1, 8, 163, 1, 10, 202, -56, -17, -58, + -100, -29, -83, -143, -37, 2, -35, -4, 135, 14, 11, 157, + 134, 36, 49, 74, 22, 69, 135, 33, -19, 158, 41, 35, + 152, 36, -3, 91, 18, -110, 41, 5, -116, + +/* 81 */ +22, 1, 3600, 19765, 22280, + -77, -59, 64, -106, -70, 78, -159, -8, 31, -4, -102, 89, + 93, -99, 72, 21, -114, 94, 35, -110, 88, -12, -117, 100, + 13, -132, 107, 38, -71, 53, 123, -42, 16, 95, 103, -100, + 127, 4, -24, 82, 36, -43, 7, 116, -98, -1, 119, -100, + -19, 110, -91, 7, 106, -91, -6, 104, -89, -74, 113, -87, + -86, 90, -65, + +/* 82 */ +22, 1, 17666, 16854, -17432, + 58, 31, 90, 67, 45, 112, 127, -40, 93, 77, -78, 4, + 118, -56, 71, 88, 35, 127, 118, -100, 28, 110, -93, 28, + 132, -78, 69, -25, 0, -27, -25, -67, -93, 41, -117, -70, + -50, -92, -141, -97, 70, -37, -107, 106, -14, -97, 92, -15, + -122, 47, -83, -86, -65, -151, -117, 93, -33, -118, 80, -43, + -51, 74, 19, + +/* 83 */ +23, -1, 5861, 26752, 12246, + 82, -33, 32, 44, -67, 125, 76, -64, 100, 4, -66, 137, + -2, -60, 126, 26, -61, 114, 56, -72, 119, 85, -65, 91, + 113, 19, -91, -80, 25, -13, -77, 59, -82, -48, 72, -125, + -16, 64, -126, 27, 80, -182, 83, 25, -95, 1, 56, -122, + -73, 49, -71, -16, -45, 108, -29, -53, 127, -52, -5, 37, + -15, 55, -111, -63, 57, -93, + +/* 84 */ +21, -1, -14603, 25601, -5597, + -10, 25, 142, 72, 67, 124, 9, 35, 145, -23, 16, 145, + -38, 6, 147, -17, 20, 157, 8, 28, 124, -63, -10, 152, + -54, -3, 159, 20, 6, -30, 59, 11, -131, 70, 16, -134, + 72, 16, -137, 31, -8, -139, 65, 22, -75, 81, 21, -120, + -49, -52, -125, -49, -56, -141, -43, -51, -128, -51, -59, -142, + +/* 85 */ +22, 1, -5757, 29270, -3178, + -36, -18, -100, -68, -28, -130, -59, -28, -136, -54, -28, -139, + -12, -22, -151, -104, -29, -57, -107, -3, 153, -77, -12, 39, + -63, -5, 65, 100, 36, 117, 69, 31, 137, 90, 32, 119, + -54, -10, 14, -143, -35, -43, 22, 18, 118, 56, 27, 139, + 125, 32, 58, 110, 32, 92, 119, 26, 24, 9, -8, -107, + 35, -5, -114, + +/* 86 */ +21, -1, 20081, 22197, 2006, + -52, 51, -44, -84, 68, 86, -104, 80, 129, -69, 58, 28, + -120, 102, 37, -73, 72, -95, -48, 58, -182, -84, 68, 55, + -110, 87, 70, -18, 8, 85, 64, -52, -33, 78, -55, -118, + 78, -70, 26, 34, -43, 145, 91, -86, 70, 115, -101, 0, + 61, -64, 105, 67, -57, -30, 57, -37, -136, 75, -56, -119, + +/* 87 */ +20, 1, -17819, 21913, 10114, + -28, 11, -73, -142, -94, -50, -103, -82, -6, -124, -90, -31, + -113, -92, -6, -78, -105, 82, 23, -33, 112, 76, 6, 124, + 103, 33, 114, 116, 67, 63, 95, 87, -16, -56, 30, -159, + -112, -81, -27, -102, -84, -3, -35, 13, -90, 78, 74, -17, + 142, 85, 72, 90, 79, -10, 109, 95, -13, + +/* 88 */ +20, -1, 7617, 6776, 28215, + -100, 37, 17, -132, 61, 21, -141, -23, 42, -89, 78, 3, + -96, 12, 21, -102, 53, 13, 7, 147, -39, -119, 93, 6, + -141, -63, 49, 40, -153, 29, 77, -127, 13, 116, -87, -7, + 54, -69, 3, 16, -124, 25, 121, -114, -4, 95, 65, -38, + 115, 89, -51, 119, 41, -40, 150, 29, -48, + +/* 89 */ +19, 1, 10847, 17337, 21949, + -55, -34, 54, -136, -1, 68, -125, 41, 27, -145, 19, 54, + -134, 22, 45, -141, -18, 79, -130, 62, 9, -164, 26, 53, + -47, -61, 68, 70, -81, 33, 147, -15, -54, 141, -18, -50, + 144, -61, -18, 126, -37, -30, 129, 17, -74, 133, 12, -73, + 135, 5, -69, 64, 69, -85, + +/* 90 */ +20, 1, 2092, 29573, 4591, + -46, -9, 79, -90, 13, -48, 2, -21, 135, -89, 7, -11, + -133, 16, -49, -43, -2, 32, -29, -14, 96, -26, -16, 102, + 78, -24, 118, 217, 0, -82, -44, -15, 105, 58, -18, 82, + 160, -5, -33, 149, -15, 25, 91, 14, -122, 30, 20, -136, + 19, 23, -151, -57, 26, -134, -157, 12, -2, + +/* 91 */ +20, -1, -20217, 21829, -3845, + -71, -59, 41, -110, -106, -18, -100, -95, 2, -110, -103, 7, + -95, -95, -14, -36, -35, -3, -92, -87, 16, -71, -87, -94, + 0, -28, -153, -18, -16, 10, -98, -75, 125, 44, 47, 13, + 84, 99, 88, 78, 86, 54, 114, 110, -6, 97, 96, 15, + 98, 90, -25, 111, 102, -14, 116, 111, 14, + +/* 92 */ +18, 1, 24559, 5678, -16267, + 45, 23, 76, 82, -17, 120, 53, -117, 40, 48, -136, 28, + 29, -161, -10, 79, -73, 100, 62, -105, 63, -13, -129, -61, + -56, -87, -115, -34, -125, -90, -73, 6, -110, -35, 134, -13, + 15, 127, 61, -34, 158, -2, -54, 138, -37, -51, 138, -32, + -55, 139, -37, + +/* 93 */ +20, -1, 7773, 28919, -1814, + -89, 16, -118, -83, 13, -134, -41, 10, 2, -8, 13, 153, + 162, -37, 87, 52, -6, 135, 18, 3, 148, -94, 31, 106, + -54, 17, 47, 200, -56, -53, 108, -26, 75, 31, -8, 11, + 11, -11, -150, 130, -40, -79, 27, -11, -54, -161, 49, 66, + -70, 20, 5, 1, -8, -121, -91, 22, -50, + +/* 94 */ +19, 1, 28847, -786, -8199, + 14, -81, 55, 17, 10, 63, 33, -16, 120, 21, -153, 93, + -27, -81, -85, -41, -5, -147, -26, -117, -78, -18, -132, -42, + -24, -120, -62, -43, -55, -138, -40, -73, -123, -13, 54, -52, + -1, 171, -32, 26, 67, 75, 42, 57, 133, 23, 143, 60, + 13, 150, 26, 24, 136, 69, + +/* 95 */ +19, -1, -13526, 25075, -9397, + -104, -57, 0, -169, -104, -31, -81, -44, 5, -119, -56, 27, + -136, -62, 41, -155, -91, -5, 21, 21, 24, 125, 71, -5, + 135, 72, -11, 34, 50, 83, -79, 4, 130, -78, 13, 159, + 39, 17, -17, 54, -22, -142, 66, -7, -119, 128, 39, -89, + 119, 53, -33, 130, 72, 1, + +/* 96 */ +20, 1, -8960, -28564, -1947, + -4, -7, 116, -2, -8, 149, 17, -15, 170, 40, -19, 128, + -19, -1, 158, 3, -7, 144, -60, 14, 121, -106, 34, -11, + -17, 9, -106, -78, 25, 14, -77, 27, -65, 101, -30, -68, + 12, 1, -102, -83, 31, -101, 76, -21, -60, 44, -10, -76, + -10, 10, -123, 16, 4, -148, 77, -15, -153, + +/* 97 */ +17, -1, 17593, 2406, 24180, + -46, -122, 46, -2, -152, 15, -14, -147, 23, 32, -145, -12, + 61, -134, -35, 60, -128, -35, 91, -110, -59, 82, -162, -52, + 51, 105, -43, -51, 108, 31, -94, 101, 62, -58, 133, 34, + -12, 155, -3, -12, 148, -4, -3, 151, -11, -17, 154, -2, + +/* 98 */ +17, -1, 7274, 26419, 12212, + -30, -53, 132, -26, -63, 149, 90, -55, 61, 121, -62, 59, + 112, -69, 77, 111, -66, 68, 136, -77, 76, 45, 47, -124, + 109, 9, -86, 69, 26, -97, -23, 64, -119, -68, 73, -111, + -118, 65, -65, -148, 50, -12, -139, 44, -10, -135, 48, -21, + +/* 99 */ +18, 1, -5378, 29484, -1323, + 7, -3, -94, -75, -18, -97, -134, -22, 66, -123, -21, 55, + -78, -18, -54, -45, -14, -99, -88, -13, 91, -23, 2, 131, + -90, -13, 129, -141, -28, 38, -61, -8, 119, 130, 29, 54, + 147, 29, -35, 140, 28, 5, 121, 21, -86, 99, 14, -122, + 143, 25, -49, + +/* 100 */ +18, -1, 13477, 22776, 14129, + 109, -76, 17, 41, -79, 87, -6, -77, 128, -25, -78, 145, + 21, -91, 121, 32, -82, 95, -81, -30, 118, -6, -70, 111, + 92, -30, -39, 85, 48, -150, 1, 51, -78, -51, 92, -93, + -5, 96, -142, -21, 78, -104, -25, 85, -108, -32, 83, -102, + -120, 75, -7, + +/* 101 */ +17, 1, 13832, 17499, 20061, + -49, -24, 54, -87, -54, 108, -99, -46, 105, -113, -24, 96, + -145, 5, 90, -63, -73, 103, -121, -41, 111, 20, -94, 65, + 118, -79, -9, 138, -22, -72, 110, 42, -106, 81, 58, -102, + 102, 48, -108, -30, 92, -58, 35, 96, -105, 73, 73, -114, + +/* 102 */ +17, 1, 24192, 6529, -16496, + 5, -81, -25, -12, -132, -68, -58, -89, -117, -44, -93, -99, + 9, -107, -24, 11, -90, -17, -48, -108, -106, -117, -38, -177, + -17, 120, 16, 4, 156, 60, -22, 140, 20, -18, 140, 26, + 28, 112, 82, 69, 65, 123, 82, -21, 109, 87, 10, 130, + +/* 103 */ +16, -1, 13005, -9227, 25411, + 89, 107, -7, 117, 91, -28, 96, 129, -5, 124, 84, -36, + 90, 79, -20, 135, 59, -53, 192, 71, -80, -94, 74, 77, + -136, -44, 59, -116, -94, 30, -130, -64, 47, -93, -97, 15, + -108, -131, 10, -73, -112, -2, -93, -119, 5, + +/* 104 */ +17, -1, 12753, 25778, 8535, + 52, -64, 114, 99, -58, 27, -5, -49, 150, 9, -5, 1, + 88, -14, -90, 143, -79, 19, 196, -98, -11, -76, 66, -78, + -85, 33, 34, -159, 84, -9, -83, 82, -118, -127, 73, -28, + -31, 59, -134, -108, 74, -64, -53, 33, -23, 131, -100, 112, + +/* 105 */ +17, -1, -16206, 24956, -3814, + 36, 36, 80, 46, 51, 147, 74, 60, 88, 97, 75, 103, + 123, 82, 32, 170, 122, 119, 112, 64, -32, -8, -16, -86, + -85, -70, -130, -116, -86, -105, -110, -66, 20, -171, -113, -32, + -59, -52, -95, 72, 44, -17, -35, -27, -34, -79, -59, -52, + +/* 106 */ +16, 1, -27904, 9377, 5782, + 14, -34, 121, -8, -99, 117, 14, -47, 134, 25, -36, 169, + 56, 65, 149, 27, -4, 118, 34, -11, 159, 32, 89, 9, + -6, 72, -124, -13, 58, -137, -16, 45, -140, -25, 26, -147, + -27, 16, -146, -35, -14, -143, -43, -42, -136, + +/* 107 */ +16, 1, 24919, 6169, -15523, + -15, -83, -57, 15, -144, -32, 30, -148, -7, 46, -148, 19, + 27, -152, -11, -30, -15, -54, -79, 68, -101, -85, 43, -118, + -72, 102, -77, -78, 95, -86, -59, 170, -28, 55, 27, 94, + 69, 29, 118, 60, 64, 119, 58, 69, 119, + +/* 108 */ +15, 1, 25878, -4981, -14336, + -65, -92, -84, -74, -17, -126, -74, -48, -113, -75, -84, -102, + -71, -100, -87, -80, -25, -128, -62, 61, -127, 26, 118, 4, + 71, 113, 81, 76, 61, 110, 79, 105, 100, 67, 7, 115, + 75, -1, 131, 72, -13, 133, + +/* 109 */ +16, 1, 5450, 29486, -929, + -154, 29, 9, -133, 25, 53, 15, 0, 102, 55, -8, 59, + -131, 24, 83, 51, -6, 146, 117, -19, 76, 152, -27, 86, + 46, -9, -54, 171, -34, -108, 46, -11, -133, 67, -16, -143, + 2, -5, -140, -115, 20, -79, -112, 23, 66, + +/* 110 */ +16, -1, 17357, 24467, -289, + 93, -67, -83, 114, -83, -67, 118, -86, -7, -13, 8, -49, + -63, 46, 4, -131, 96, 35, -99, 72, 119, -113, 81, 37, + -79, 53, -96, -30, 19, -139, -102, 66, -178, 18, -10, 75, + 61, -39, 123, 40, -26, 142, 85, -58, 90, + +/* 111 */ +16, 1, -10217, 28170, -1431, + -65, -26, -59, -121, -47, -38, -112, -47, -83, -64, -32, -142, + -103, -35, 66, -74, -21, 123, -113, -36, 147, -52, -14, 123, + 22, 14, 136, 72, 32, 111, 73, 28, -15, 127, 46, -75, + 129, 46, -48, 120, 40, -116, 91, 30, -63, + +/* 112 */ +15, 1, 29126, 7027, -1524, + 25, -95, 61, 35, -144, 21, 37, -153, 29, 32, -136, 22, + 32, -147, -4, 36, -156, 67, 31, -153, -26, -10, 34, -50, + -33, 155, -14, -35, 150, -55, -27, 117, -36, -41, 183, 10, + -27, 109, -30, -35, 145, -19, + +/* 113 */ +15, 1, 6145, 29344, -1095, + -111, 18, -111, -53, 5, -138, -82, 10, -139, -105, 16, -86, + -147, 32, 55, -78, 19, 94, -45, 14, 107, 69, -11, 60, + -161, 34, 74, 151, -26, 74, 141, -26, 15, 139, -26, 36, + 145, -29, 16, 127, -25, 23, + +/* 114 */ +15, 1, 24375, 5854, -16479, + 40, -64, 35, 43, -140, 16, 59, -133, 43, 58, -133, 43, + 65, -133, 54, 43, -126, 24, 37, -157, 9, -33, -4, -52, + -54, 137, -39, -51, 140, -32, -78, 112, -80, -58, 111, -51, + -26, 150, 12, -23, 147, 17, + +/* 115 */ +15, -1, -17689, 24006, -3293, + 3, -14, -112, -73, -60, -41, -34, -11, 101, -70, -38, 105, + -89, -57, 66, -106, -88, -56, -163, -125, 4, -104, -72, 56, + 44, 39, 37, 120, 91, -4, 106, 86, 36, 112, 90, 43, + 115, 84, -14, 93, 53, -126, + +/* 116 */ +14, 1, 12744, -2905, -27003, + -5, -145, 14, -77, -123, -22, -103, -99, -37, -63, -118, -14, + -67, -122, -15, -128, -69, -50, -133, 51, -66, 17, 147, -12, + 107, 117, 35, 104, 79, 37, 99, 120, 32, 86, 134, 25, + 119, 58, 49, + +/* 117 */ +15, 1, -12039, 24973, -11465, + -64, -40, -18, -136, -75, -18, -97, -85, -81, -115, -86, -58, + -106, -47, 12, -128, -64, 5, -126, -69, -8, -7, 38, 87, + 99, 75, 51, 156, 93, 28, 61, 55, 53, 130, 77, 25, + 140, 57, -26, 124, 60, -2, + +/* 118 */ +14, 1, 7404, 28675, -4785, + -29, -17, -146, -17, -21, -148, 7, -29, -149, -45, -11, -123, + -150, 53, 81, -131, 42, 51, -114, 46, 103, -17, 24, 116, + 7, 24, 148, 56, 10, 138, 125, -25, 35, 146, -55, -111, + 129, -30, 17, + +/* 119 */ +15, 1, -18411, 21935, 8938, + -115, -81, -40, -37, -70, 94, -16, -67, 130, -6, -58, 124, + 71, 2, 136, -17, -59, 103, 77, 18, 109, 131, 91, 45, + -20, 35, -117, -69, -11, -111, -56, 16, -148, -52, 11, -130, + 18, 47, -75, 70, 90, -75, + +/* 120 */ +16, -1, -19925, -10993, 19549, + -85, 60, -54, -81, 131, -10, -95, 132, -25, 49, 44, 74, + 124, -109, 68, 104, -49, 79, -38, 35, -20, -106, 137, -32, + -67, 38, -48, -111, -16, -125, 11, -76, -29, 64, -118, 1, + 29, -126, -41, 51, -24, 39, 100, -47, 78, + +/* 121 */ +15, -1, -18321, 23571, -2957, + -21, -25, -65, -55, -44, -12, -127, -88, 93, -93, -71, 26, + -105, -81, 20, -118, -90, 42, -124, -99, 20, -24, -4, 132, + 89, 77, 41, 107, 79, -71, 90, 60, -111, 99, 80, 11, + 155, 117, -44, 66, 45, -56, + +/* 122 */ +13, 1, -17336, 22935, 8569, + -77, 9, -181, -36, -51, 65, 5, -50, 144, -33, -72, 123, + 11, -49, 149, 36, -30, 146, 45, -23, 142, 99, 30, 115, + 31, 78, -136, -4, 53, -140, -9, 49, -144, -26, 36, -146, + +/* 123 */ +15, 1, 18292, -22847, 6589, + 17, 51, 129, 65, 27, -88, 38, 6, -87, 81, 84, 64, + -109, -44, 152, 4, 37, 115, -16, 21, 109, 75, 88, 88, + -100, -69, 39, -92, -89, -47, -125, -112, -40, 46, 6, -100, + 56, 0, -148, 7, -22, -92, + +/* 124 */ +14, 1, 25183, 6987, -14730, + -19, -68, -66, -34, -107, -106, -1, -140, -65, -8, -124, -68, + -18, -137, -89, -55, -30, -104, -61, 102, -57, -40, 142, -5, + -29, 159, 24, 18, 114, 80, 56, 74, 126, 63, 25, 117, + 76, 10, 133, + +/* 125 */ +14, 1, -8316, 28793, 1345, + -112, -33, 14, -106, -36, 84, -119, -39, 70, -83, -31, 115, + 70, 13, 135, 41, 3, 142, 12, -7, 156, 99, 28, 19, + 108, 39, -100, 95, 35, -109, 42, 21, -148, -30, 0, -150, + 16, 13, -150, + +/* 126 */ +14, 1, -20941, -20602, 6087, + -57, 78, 65, -69, 88, 56, -96, 95, -13, -76, 82, 8, + -54, 95, 123, -116, 124, 1, -64, 28, -127, 47, -74, -79, + 82, -108, -69, 97, -111, -29, 98, -114, -42, 84, -109, -75, + 86, -65, 78, + +/* 127 */ +13, 1, -4213, -29615, 2279, + -54, 18, 127, -113, 24, 97, -128, 26, 79, -138, 28, 72, + -56, 2, -82, 112, -27, -103, 78, -21, -118, -45, -5, -145, + -127, 9, -160, 135, -23, -23, 80, -3, 125, 149, -19, 48, + +/* 128 */ +17, 1, -7190, 25393, -14265, + 78, -15, -66, -8, -71, -121, 96, 22, -9, 103, -22, -88, + -16, -69, -112, -123, -86, -89, -29, 14, 39, -51, 17, 54, + -61, -48, -53, -53, 22, 65, -54, 65, 139, -68, 50, 122, + -82, 20, 78, 25, 62, 96, 104, 44, 25, 88, 20, -10, + +/* 129 */ +14, -1, -19493, 22341, -4569, + 21, -10, -138, -18, -17, -9, -18, 15, 150, -41, -7, 140, + -104, -82, 48, -110, -85, 68, -76, -41, 140, -11, 27, 201, + 24, 10, -64, 19, -10, -144, 124, 90, -106, 57, 33, -93, + 103, 79, -54, + +/* 130 */ +14, 1, 631, -8774, -28681, + -95, 52, -18, -113, 74, -25, -126, -17, 4, -218, 65, -21, + 120, -18, 6, 3, 62, -18, -151, 163, -49, 118, 8, -2, + 126, -59, 18, 142, -43, 15, 136, -62, 21, 142, -64, 22, + -23, -89, 26, + +/* 131 */ +14, 1, 19698, -3856, -22297, + 66, -19, 63, 94, -67, 96, 59, -115, 73, 41, -133, 62, + 33, -144, 58, -56, -44, -42, -112, 1, -101, -112, -2, -100, + -88, 89, -95, -79, 93, -87, -35, 136, -55, 18, 126, -7, + 109, 85, 80, + +/* 132 */ +13, 1, -11506, 10377, -25689, + -24, -106, -32, 45, -133, -73, -57, -146, -31, -32, -145, -41, + -112, -83, 18, -96, 90, 78, -114, 58, 75, -114, 81, 84, + 67, 117, 15, 89, 117, 5, 131, 76, -30, 133, 55, -38, + +/* 133 */ +13, 1, 3573, 20459, 21649, + -18, -82, 80, -121, -55, 70, -106, -79, 91, 11, -107, 96, + 42, -113, 97, 64, -95, 76, 145, -61, 32, 58, 98, -98, + 18, 114, -107, 15, 110, -103, -40, 114, -99, -24, 107, -96, + +/* 134 */ +14, 1, -13127, 24311, -11689, + 32, -36, -111, -20, -65, -111, -11, -39, -67, 119, 108, 88, + 119, 35, -57, 12, -41, -96, -113, -93, -66, -148, -83, -6, + -78, -59, -31, -99, -15, 79, 15, 71, 124, 81, 88, 89, + 49, 83, 116, + +/* 135 */ +14, -1, -27102, -7955, 10108, + -41, 40, -76, 7, -121, -79, 2, -95, -72, 50, -76, 73, + 60, -59, 116, 54, -99, 63, 49, 14, 140, 58, -112, 59, + 41, 30, 130, -56, 115, -52, -55, 104, -59, -68, 105, -94, + -62, 98, -88, + +/* 136 */ +13, 1, 24282, 5951, -16583, + 1, -130, -43, -12, -124, -61, -62, -64, -112, 21, -145, -17, + -12, -193, -80, -75, 62, -87, -38, 114, -17, 22, 137, 75, + -22, 152, 20, 1, 137, 49, 74, 1, 106, 62, 51, 109, + +/* 137 */ +12, 1, -26265, 9394, 11041, + -25, -130, 52, 61, -10, 151, 61, 0, 140, 56, -11, 136, + 72, 36, 134, 82, 129, 80, -33, 84, -143, -47, 8, -112, + -59, 12, -145, -60, 2, -141, -63, -12, -136, + +/* 138 */ +13, 1, 959, -9398, -28474, + -96, 40, -16, -137, 30, -14, -46, 96, -32, 46, 137, -43, + 120, 104, -29, 106, 43, -11, 165, -34, 17, 122, -55, 22, + 71, -116, 41, 34, -132, 44, -128, -70, 17, -150, -39, 7, + +/* 139 */ +13, -1, 14782, -8096, 24818, + 69, -20, -48, 119, -33, -82, 133, 23, -74, 129, -1, -79, + 130, 19, -76, 172, 44, -94, -52, 24, 41, -129, -22, 74, + -124, -10, 75, -135, -5, 81, -127, -25, 69, -127, 11, 80, + +/* 140 */ +13, 1, -18588, -22992, 5084, + -30, 41, 75, -96, 84, 27, -117, 108, 51, -121, 106, 23, + -116, 92, -23, 16, -39, -112, 126, -112, -27, 33, -57, -133, + 146, -119, 7, -60, 76, 116, 53, -45, -2, 114, -97, -23, + +/* 141 */ +13, 1, 10930, 21399, -17962, + 112, -57, 2, 131, -9, 69, 89, -43, 5, 131, -71, -1, + 148, -86, -8, 121, -90, -27, -34, -14, -38, -131, 74, 3, + -134, 81, 9, -140, 53, -25, -138, 61, -13, -155, 53, -32, + +/* 142 */ +13, -1, 2123, 5909, 29336, + 91, -78, 9, 130, -73, 4, 65, -131, 20, -85, -112, 28, + -40, -133, 28, 50, -162, 25, 34, 36, -9, 28, 139, -28, + 10, 135, -25, 8, 152, -30, -103, 116, -14, -132, 66, -4, + +/* 143 */ +14, -1, -17261, 24337, -3127, + -106, -81, -41, -97, -73, -25, -70, -67, -119, -103, -69, 48, + -89, -51, 111, -27, 0, 147, 30, 31, 74, 43, 21, -85, + 52, 29, -72, 125, 88, -25, 82, 75, 129, 15, 1, -77, + 94, 67, -2, + +/* 144 */ +15, -1, -17925, 23424, 5478, + -56, -22, -89, -109, -64, -90, -96, -63, -50, -158, -128, 15, + -122, -105, 33, 71, 48, 36, 88, 74, -14, 119, 86, 31, + 133, 87, 74, -67, -52, 0, 43, 22, 48, 109, 65, 81, + 5, 10, -29, 16, 17, -20, + +/* 145 */ +12, 1, -11151, 25532, -11125, + -96, -60, -40, -113, -85, -80, -154, -96, -60, -89, -84, -95, + -39, 41, 132, 43, 56, 79, 187, 120, 81, -121, -59, -10, + 37, 33, 37, 135, 73, 29, 132, 34, -56, + +/* 146 */ +13, 1, -8245, 28241, 5871, + -116, -48, 68, -111, -45, 51, -55, -33, 79, 67, -11, 142, + -65, -18, -4, -34, -28, 75, 111, 13, 96, 134, 24, 67, + 120, 43, -35, 8, 38, -156, 32, 40, -143, -27, 24, -145, + +/* 147 */ +12, -1, -29258, 6281, 2126, + -23, -98, -32, -27, -136, 29, -23, -141, 72, -7, -82, 123, + 3, -46, 145, 8, -25, 154, 25, 105, 42, 17, 119, -83, + 14, 113, -102, 8, 88, -123, 9, 85, -120, + +/* 148 */ +12, -1, 15271, 556, 25816, + 72, 107, -45, 84, 120, -53, 109, 74, -69, 73, 123, -48, + 14, 199, -17, -60, -36, 38, -94, -101, 61, -101, -90, 64, + -93, -105, 59, -79, -120, 50, 19, -120, -8, + +/* 149 */ +13, 1, 4573, 29647, -405, + 107, -16, 122, 127, -20, 41, 164, -26, 40, 74, -13, 16, + 63, -11, -54, 48, -10, -152, -74, 11, -130, -85, 12, -108, + -165, 28, -1, -109, 18, 26, -117, 20, 93, -78, 13, 54, + +/* 150 */ +12, -1, 9509, 25746, 12114, + -81, -25, 114, 107, -45, 12, 57, -63, 87, -150, 26, 61, + 42, -29, 28, 151, -65, 19, 165, -64, 1, 86, 3, -73, + -2, 67, -137, -128, 58, -19, -139, 62, -20, + +/* 151 */ +12, 1, 10885, -3987, -27670, + -99, -113, -22, -113, -91, -30, -130, -74, -39, -127, -67, -37, + -158, -91, -44, -8, 63, -13, 108, 109, 23, 122, 81, 33, + 131, 59, 41, 117, 91, 32, 119, 64, 37, + +/* 152 */ +12, 1, -10784, 27846, 2885, + 31, 19, -71, -6, 13, -150, -84, -23, -112, -140, -51, -40, + -139, -55, -1, -127, -56, 54, -43, -30, 122, 55, 9, 143, + 106, 32, 100, 140, 55, 3, 133, 57, -42, + +/* 153 */ +12, -1, -20095, -16594, 14860, + -15, 59, 46, -47, 134, 85, 5, 91, 106, 32, 39, 83, + 57, 25, 102, -93, 188, 76, -37, -61, -113, -25, -95, -134, + 8, -95, -92, -9, -95, -115, 80, -131, -38, + +/* 154 */ +12, -1, -19229, 22976, -1545, + -67, -58, -11, -88, -82, -108, -97, -85, -32, -80, -76, -92, + -72, -59, 30, -25, -11, 149, 79, 79, 162, 92, 71, -119, + 3, 12, 140, 91, 76, -35, 97, 78, -55, + +/* 155 */ +11, 1, -1931, -29525, -4956, + -34, 25, -132, 27, 24, -147, 46, 23, -144, 42, 24, -147, + 128, 1, -45, 118, -27, 110, 37, -28, 139, -44, -23, 143, + -82, -17, 128, -119, -8, 89, + +/* 156 */ +11, 1, -7314, -28817, -4011, + 38, 10, -135, 63, 4, -137, 36, 13, -147, 80, 3, -145, + 86, -36, 93, 124, -44, 90, 31, -23, 107, -108, 11, 103, + -109, 12, 101, -119, 17, 85, + +/* 157 */ +14, 1, -10998, 25512, -11321, + 41, -28, -103, -54, -61, -84, -107, -71, -54, -129, -62, -11, + 25, 48, 82, -20, 9, 39, -150, -48, 44, 17, 44, 79, + 187, 57, -60, -74, -12, 49, 7, 37, 75, 121, 34, -43, + 45, 4, -36, + +/* 158 */ +11, 1, -29990, -14, -784, + -1, -139, 84, -1, -155, 84, 4, -105, -129, 1, -108, 22, + -3, -4, 154, -4, 87, 124, 0, 134, -44, 0, 128, -68, + 1, 125, -75, 2, 107, -82, + +/* 159 */ +11, 1, 24220, -1670, -17623, + -21, -142, -16, -68, -99, -83, -84, -67, -106, -86, -7, -115, + -81, 59, -114, -40, 112, -64, 55, 102, 63, 79, 92, 96, + 91, 14, 122, 90, -31, 124, + +/* 160 */ +11, 1, 140, 28342, -9835, + -148, 16, 46, -147, -2, -5, -152, 14, 45, -96, 34, 103, + 101, 41, 118, 139, 17, 48, 150, -6, -21, 122, -29, -85, + 100, -38, -111, 8, -41, -120, + +/* 161 */ +11, 1, 9134, 18840, 21486, + 134, -66, 0, 126, -91, 25, 135, -54, -13, 113, -67, 8, + 137, -82, 8, -43, 62, -34, -97, 100, -42, -91, 95, -42, + -150, 40, 31, -124, 74, -11, + +/* 162 */ +11, 1, -21516, 19701, 6996, + -54, -7, -149, -52, -18, -114, -56, -12, -145, -50, -13, -130, + -118, -89, -128, 6, -28, 106, 77, 37, 149, 69, 26, 145, + 65, 33, 115, 82, 47, 123, + +/* 163 */ +12, 1, -2471, 26742, -13370, + -106, 37, 95, 62, 32, 52, 133, 23, 22, 113, 42, 66, + 158, -1, -29, 145, 13, 5, 63, -27, -64, -93, -46, -80, + -176, 5, 39, -113, -29, -42, -113, -42, -63, + +/* 164 */ +12, 1, -10150, -24537, 13962, + -10, 36, 55, -102, 82, 68, -147, 64, 4, -127, 49, -11, + -133, 22, -63, -142, 13, -86, 47, -28, -11, 123, -35, 34, + 144, -49, 22, 137, -52, 12, 136, -74, -31, + +/* 165 */ +12, 1, -15831, -23712, 9333, + 11, 39, 120, 12, 45, 131, 33, 43, 159, 29, 38, 136, + -72, 62, 33, -54, 0, -87, -65, 29, -36, -103, 35, -86, + 60, -92, -122, 18, -56, -109, 34, -70, -119, + +/* 166 */ +11, -1, -26860, 12885, -3537, + -22, -68, -78, -64, -142, -24, -55, -120, -9, -54, -128, -42, + -98, -217, -5, 28, 66, 16, 59, 138, 29, 57, 135, 39, + 57, 134, 44, 56, 133, 53, + +/* 167 */ +10, -1, 21555, 20350, 4610, + -13, -13, 117, -23, -10, 147, -11, -25, 149, 15, -65, 193, + 89, -66, -109, 59, -32, -128, 32, 3, -154, -26, 61, -143, + -71, 111, -150, + +/* 168 */ +12, 1, 25080, -2304, -16299, + 36, -91, 68, 1, -152, 24, 5, -145, 32, 28, -138, 68, + -28, -123, -22, -47, 63, -85, -54, 77, -96, 14, 96, 4, + 34, 84, 39, -33, 137, -73, 5, 129, -10, + +/* 169 */ +11, 1, -5147, -29506, 1706, + 36, -1, 84, -95, 24, 126, -104, 26, 108, -85, 24, 125, + -103, 29, 129, -55, 5, -80, 41, -19, -145, 56, -20, -140, + 89, -24, -121, 131, -27, -73, + +/* 170 */ +11, 1, 3601, 24897, 16346, + -94, -65, 119, -106, -2, 25, -143, -42, 91, 31, -83, 117, + 72, -63, 79, 161, -49, 38, 88, 35, -69, 12, 73, -110, + 37, 67, -109, -8, 83, -124, + +/* 171 */ +12, 1, -16031, -24558, 6319, + -29, -8, -108, -28, -23, -166, 19, -42, -123, 130, -68, 69, + -58, 46, 37, 5, 16, 79, 101, -54, 43, 132, -49, 140, + -115, 70, -13, -118, 58, -72, 14, 12, 83, + +/* 172 */ +11, 1, 4179, 29039, -6267, + 73, -37, -121, -54, -26, -151, -57, -23, -136, -114, -7, -103, + -154, 15, -24, -87, 34, 96, 96, 17, 131, 92, 8, 92, + 101, 10, 108, 59, 10, 82, + +/* 173 */ +11, 1, 7225, 28615, -5385, + -150, 30, -40, -139, 24, -51, -152, 36, -3, -23, 32, 144, + -4, 26, 134, 100, -10, 76, 124, -44, -80, 137, -42, -45, + 123, -46, -80, 49, -24, -60, + +/* 174 */ +10, 1, 27028, -4267, -12299, + -47, -101, -69, -68, -50, -128, -76, -143, -112, -39, 74, -109, + -42, 100, -123, 53, 124, 69, 69, 41, 132, 55, -48, 134, + 67, 29, 136, + +/* 175 */ +11, -1, 17469, 24240, 2693, + -28, 25, -38, -83, 72, -130, -50, 50, -130, -52, 49, -133, + -57, 55, -170, -37, 23, 45, 59, -55, 143, 73, -63, 123, + 51, -50, 127, 70, -63, 122, + +/* 176 */ +11, 1, 9832, -4353, -28007, + -12, -95, 11, -32, -144, 12, -59, -142, 3, -104, -107, -18, + -134, -122, -24, -2, 72, -13, 44, 125, -7, 81, 123, 7, + 60, 126, 0, 75, 131, 5, + +/* 177 */ +11, -1, 3662, 25807, 14853, + -135, 2, 28, -21, -77, 138, -117, -27, 73, -24, -53, 95, + 13, -75, 123, 53, -20, 22, 115, 39, -92, 129, 32, -84, + 65, 57, -113, -8, 65, -110, + +/* 178 */ +10, 1, -6841, -28848, -4579, + -89, 40, -117, 11, 19, -132, -44, 36, -150, 0, 26, -145, + 120, -16, -75, 82, -38, 102, 0, -25, 145, 26, -31, 146, + -18, -20, 148, + +/* 179 */ +10, 1, 10303, -4850, -27755, + -3, -110, 18, -87, -118, -10, -139, -39, -44, -145, -16, -49, + -168, -5, -59, 51, 128, -5, 128, 85, 30, 144, 11, 50, + 127, 49, 38, + +/* 180 */ +11, 1, 27435, -3603, -11592, + 23, -70, 78, -36, -77, -61, -56, -11, -129, -70, -5, -160, + -45, 48, -118, -47, 48, -121, 14, 73, 10, 61, -2, 139, + 60, 0, 137, 60, 1, 140, + +/* 181 */ +11, -1, -19573, -21914, 6055, + -41, 72, 126, -22, 58, 133, 28, 17, 146, 73, -23, 140, + -46, 47, 21, -91, 40, -142, 13, -52, -136, -19, -29, -159, + 7, -23, -56, 76, -90, -80, + +/* 182 */ +10, 1, -16090, -23678, 8971, + 67, -15, 80, 5, 55, 152, 3, 53, 138, -68, 112, 164, + -100, 20, -121, -81, -5, -154, 100, -81, -30, 55, -62, -63, + -13, -40, -128, + +/* 183 */ +10, 1, -7427, 29059, -664, + -79, -23, -102, -94, -27, -62, -135, -36, -21, -102, -25, 98, + -81, -19, 122, 31, 12, 139, 154, 41, 18, 142, 38, -17, + 130, 32, -78, + +/* 184 */ +10, 1, 22146, -6178, -19271, + -60, 73, -92, -58, 116, -102, 55, 130, 23, 75, -34, 95, + 107, -20, 130, 99, 39, 103, 19, -78, 46, -68, -127, -39, + -96, -82, -86, + +/* 185 */ +11, -1, 13300, 25127, 9578, + 29, 41, -150, -7, 56, -141, 23, 35, -126, -131, 89, -57, + -40, 16, 13, 126, -92, 70, -14, -37, 123, 9, -49, 120, + -29, -40, 146, 39, -43, 58, + +/* 186 */ +10, -1, 11562, 21630, 17276, + 116, -40, -28, 140, -47, -37, 107, -42, -21, 214, -140, 24, + -64, 64, -33, -121, 92, -31, -136, 91, -20, -132, 38, 42, + -104, 7, 62, + +/* 187 */ +10, 1, -25792, 5633, 14249, + -43, -12, -74, -78, -55, -120, -19, -181, 35, -89, -108, -124, + 22, -32, 53, 73, 1, 134, 79, 31, 133, 37, 137, 15, + 34, 178, -7, + +/* 188 */ +10, 1, -11381, 25287, -11447, + 56, -2, -59, -84, -68, -68, -114, -80, -60, -126, -71, -28, + -165, -107, -62, 31, 58, 91, 86, 77, 80, 112, 81, 64, + 118, 75, 46, + +/* 189 */ +11, -1, -17257, 23572, 6821, + -79, -32, -89, -16, 23, -121, -53, -38, -4, -103, -94, 61, + -62, -78, 109, -89, -94, 93, 16, 8, 12, 124, 83, 35, + 113, 76, 31, 108, 92, -44, + +/* 190 */ +9, 1, 21029, -858, -21378, + -82, -38, -80, -104, -45, -99, -108, -41, -101, -166, 25, -159, + 75, 53, 68, 106, 28, 100, 109, 16, 104, 108, 13, 105, + +/* 191 */ +9, -1, 16710, 18554, 16629, + 40, -81, 51, 77, -100, 31, 90, -117, 38, 114, -123, 18, + 63, 61, -130, -74, 118, -54, -114, 76, 32, -75, 122, -59, + +/* 192 */ +10, 1, -26154, 13570, 5641, + 12, -36, 142, -22, -92, 112, -38, -97, 53, -91, -175, -11, + 33, 46, 40, 70, 120, 43, 37, 119, -105, 21, 92, -118, + -14, 33, -142, + +/* 193 */ +10, 1, -10691, -27735, 4062, + 89, -25, 58, -53, 43, 153, -92, 50, 88, -103, 49, 54, + -119, 59, 77, -44, 12, -36, 69, -48, -127, 98, -54, -100, + 91, -52, -105, + +/* 194 */ +9, 1, 5294, 28803, -6509, + 141, -38, -53, 58, -14, -13, -125, -7, -132, -82, -14, -124, + -128, 1, -92, -86, 43, 117, 12, 33, 151, 77, 15, 126, + +/* 195 */ +10, 1, -13366, 24028, -12001, + 65, -24, -120, -58, -49, -32, -118, -69, -5, -122, -71, -3, + -204, -95, 43, 57, 44, 22, 133, 68, -16, 108, 81, 37, + 61, 66, 65, + +/* 196 */ +9, 1, -13524, 26719, 1794, + -49, -16, -141, -59, -24, -103, -129, -63, -57, -127, -69, 46, + 11, -3, 148, 97, 43, 109, 110, 51, 85, 128, 63, 31, + +/* 197 */ +10, -1, -19280, 22118, -6250, + 3, 37, 124, -25, 20, 152, -29, 10, 132, -36, 9, 154, + 72, 66, 13, -1, -41, -155, 5, -30, -131, 31, -11, -139, + -4, -39, -126, + +/* 198 */ +9, 1, -5809, 29420, -843, + -132, -27, -12, -164, -32, 56, -135, -28, 15, -23, -2, 88, + 83, 20, 143, 154, 33, 14, 113, 21, -95, 112, 20, -106, + +/* 199 */ +10, -1, -2866, 4214, 29564, + -77, -108, 8, -26, -121, 14, -26, -158, 18, 141, -133, 31, + 54, 162, -16, -71, -12, -5, -48, 38, -10, 28, 155, -18, + 20, 115, -14, + +/* 200 */ +9, 1, 16380, -17659, -17885, + -77, 86, -154, 103, 64, 31, 97, 45, 45, 96, -26, 114, + 95, -32, 121, -11, -89, 78, -111, -41, -64, -107, 11, -109, + +/* 201 */ +8, 1, 2405, 29362, 5664, + -161, -1, 74, 55, -28, 117, 40, -40, 180, 167, -13, -2, + 108, 5, -68, 27, 32, -171, -115, 17, -38, + +/* 202 */ +10, -1, 15812, 18669, 17362, + 62, -1, -56, 121, -24, -85, 101, -18, -76, -52, 103, -62, + 26, 105, -142, -85, 18, 62, -29, -52, 84, -107, -11, 112, + -38, -69, 109, + +/* 203 */ +9, -1, -22192, 18429, -8241, + -24, -51, -48, -42, -105, -120, -45, -95, -83, 3, -94, -206, + -31, -5, 68, -7, 65, 158, 63, 115, 82, 45, 106, 111, + +/* 204 */ +9, 1, 11904, -3476, -27317, + -52, -83, -12, -106, -103, -32, -102, -113, -28, -187, -67, -70, + 48, 72, 10, 85, 121, 20, 114, 88, 37, 122, 81, 42, + +/* 205 */ +9, 1, 29712, 544, -4112, + 13, 98, 108, 12, 125, 117, 18, -20, 133, 2, -58, 5, + -9, -130, -90, -10, -97, -91, -13, -138, -111, -12, 92, -79, + +/* 206 */ +9, 1, 9469, -5342, -27961, + -76, -64, -13, -89, -111, -8, -123, -76, -26, -193, -36, -55, + 20, 109, -15, 111, 75, 21, 140, 40, 38, 133, 73, 30, + +/* 207 */ +9, 1, -4851, 24586, -16492, + 112, -15, -56, 112, -35, -83, 77, -73, -128, -49, -63, -78, + -117, 34, 82, -120, 28, 75, -155, 20, 75, 46, 45, 53, + +/* 208 */ +9, 1, 24496, 6480, -16061, + 42, -192, -12, -66, 29, -89, -56, -72, -113, -60, -98, -126, + -32, 66, -23, 30, 120, 90, 46, 90, 104, 59, 71, 119, + +/* 209 */ +9, 1, -5809, 29356, -2119, + 25, -3, -102, 10, -9, -147, -56, -22, -131, -154, -34, -30, + -109, -15, 91, 2, 14, 160, 131, 31, 59, 80, 23, 86, + +/* 210 */ +9, -1, 28373, 6866, -6918, + 16, -102, -31, -1, -97, -101, -9, -80, -107, -21, -107, -180, + -10, 66, 19, 7, 96, 117, -9, 131, 86, 7, 89, 112, + +/* 211 */ +9, 1, 6654, -7693, -28223, + 85, 43, 9, -37, -186, 42, -30, -149, 34, -106, -88, 0, + -146, 59, -50, 24, 144, -35, 100, 82, 0, 88, 19, 15, + +/* 212 */ +9, 1, 23496, 6501, 17484, + 57, -56, -56, 91, -46, -107, 87, 15, -125, 87, 76, -150, + -52, 72, 45, -85, 13, 113, -84, -4, 117, -82, -11, 114, + +/* 213 */ +9, -1, -6643, 25925, -13555, + 69, 0, -34, 128, -11, -84, 105, -27, -99, 109, -26, -98, + -71, -55, -69, -126, 21, 96, -97, 28, 97, -76, 47, 126, + +/* 214 */ +9, 1, -7497, 28006, -7711, + -100, -11, 58, -138, -24, 49, 27, 14, 24, 77, 47, 98, + 45, 58, 175, 104, 24, -16, 36, -35, -168, 12, -31, -128, + +/* 215 */ +9, -1, -20663, 19947, -8671, + -9, -40, -67, -99, -111, -19, -110, -98, 41, -117, -97, 63, + 8, 54, 105, 53, 64, 15, 102, 73, -80, 114, 93, -60, + +/* 216 */ +9, 1, 4747, 25258, 15476, + -15, -47, 81, -25, -76, 129, -32, -73, 126, 23, -91, 137, + 39, 12, -30, 3, 79, -126, 12, 80, -131, 10, 77, -128, + +/* 217 */ +8, 1, 8037, 27999, 7173, + 126, -37, 4, 70, 13, -132, -8, 42, -161, -67, 37, -70, + -146, 35, 28, -97, 4, 97, 30, -44, 140, + +/* 218 */ +8, 1, -8206, 28777, -2132, + 89, 20, -69, 43, 0, -147, -75, -30, -114, -146, -37, 57, + -176, -46, 61, 49, 22, 105, 122, 42, 81, + +/* 219 */ +8, 1, 26623, -4311, -13138, + 27, -94, 85, 6, -161, 68, -36, -68, -50, -84, -1, -169, + -19, 104, -74, -3, 147, -55, 61, 86, 94, + +/* 220 */ +9, -1, -19193, 23050, 547, + -3, 0, -116, -126, -104, -79, -91, -76, -9, -51, -45, 93, + -32, -30, 123, 62, 50, 72, 131, 111, 3, 92, 79, -39, + +/* 221 */ +9, -1, -21968, 17844, -9950, + -52, -145, -144, -65, -32, 87, -53, 11, 139, -99, -72, 94, + 6, 11, 5, 105, 80, -92, 45, -8, -115, 86, 123, 27, + +/* 222 */ +8, 1, -9395, -28397, 2317, + -3, 14, 145, -6, 15, 151, -50, 30, 144, -103, 31, -45, + 14, -17, -132, 18, -21, -163, 44, -26, -140, + +/* 223 */ +8, 1, -23532, -559, 18600, + -51, -140, -71, 78, 10, 100, 72, 112, 94, 44, 111, 58, + -18, 153, -19, -74, -18, -94, -47, -129, -61, + +/* 224 */ +8, 1, 29597, -880, -4821, + 11, 119, 49, 14, 132, 63, 15, 122, 85, 18, -57, 120, + -6, -139, -20, -16, -129, -81, -21, -93, -116, + +/* 225 */ +8, 1, -4242, 28374, 8769, + -111, -19, 10, -148, -19, -16, -174, -48, 66, 87, -11, 80, + 150, 10, 44, 156, 20, 13, 59, 45, -115, + +/* 226 */ +8, -1, 23521, 18132, -4238, + 22, 2, 127, 85, -98, 57, 62, -96, -62, 2, -37, -146, + -18, -15, -158, -76, 95, -24, -53, 98, 119, + +/* 227 */ +9, -1, -12721, 26335, -6680, + 101, 34, -59, -12, -37, -121, 21, -30, -150, 97, 11, -132, + -22, -9, 4, -87, -9, 120, -32, 24, 149, -30, 19, 133, + +/* 228 */ +8, 1, 28556, -1354, -9094, + 4, -123, 32, -10, -153, -7, -42, -14, -129, -41, -5, -126, + -13, 145, -64, 30, 120, 73, 44, 44, 129, + +/* 229 */ +9, -1, -13304, 26737, -2855, + -76, -34, 35, -77, -28, 107, 23, 22, 102, 145, 75, 25, + 91, 53, 92, 49, 18, -63, -12, -18, -126, -95, -61, -143, + +/* 230 */ +9, 1, -4166, 24261, -17148, + 79, -11, -35, 76, -52, -91, 33, -64, -96, 128, -60, -112, + -52, -17, -11, -135, 41, 86, -105, 58, 105, -31, 69, 105, + +/* 231 */ +10, -1, 22208, 16310, -11865, + -45, 2, -82, -109, 78, -95, -87, 149, 46, 91, -49, 101, + 52, -108, -53, 29, 8, 64, 39, 3, 77, 28, -4, 47, + -22, -51, -112, + +/* 232 */ +8, -1, 18389, 23461, -3379, + 78, -58, 17, 126, -102, -8, 148, -120, -6, -26, 11, -72, + -120, 91, -34, -120, 92, -23, -123, 105, 59, + +/* 233 */ +9, -1, -12115, 27105, 4305, + 73, 39, -40, 98, 61, -114, 58, 51, -174, -77, -33, 0, + -134, -60, 2, -95, -52, 66, 69, 14, 109, 8, -12, 101, + +/* 234 */ +9, 1, 22705, -5, -19608, + 49, -19, 57, 108, -56, 126, -44, -88, -51, -88, 25, -103, + -59, -15, -68, -104, -20, -119, -6, 99, -7, 89, 57, 101, + +/* 235 */ +9, -1, -21304, 20829, -3509, + -61, -67, -28, -89, -92, 7, -93, -82, 84, -97, -83, 115, + 17, 17, -6, 85, 72, -102, 93, 83, -81, 88, 91, -4, + +/* 236 */ +8, 1, 21301, -2864, -20930, + 49, -109, 66, -5, -141, 14, -17, -126, 3, -108, -60, -101, + -16, 142, -38, 0, 130, -20, 43, 142, 24, + +/* 237 */ +8, 1, -3541, 26084, -14390, + 91, -16, -52, 143, -42, -108, -84, -54, -78, -183, -37, -22, + -110, 17, 58, -27, 44, 86, 84, 68, 100, + +/* 238 */ +9, 1, -17503, -23888, 4794, + 98, -63, 45, 73, -33, 99, 90, -40, 118, 83, -41, 84, + -47, 33, -2, -82, 42, -75, -89, 41, -118, -87, 42, -97, + +/* 239 */ +8, 1, -20659, 21543, 3021, + -20, -9, -74, -10, 14, -179, -30, -5, -194, -34, -42, 74, + -22, -39, 146, -6, -28, 161, 69, 56, 82, + +/* 240 */ +8, 1, 24748, -885, -16934, + 0, -113, 6, -74, -41, -105, -86, 34, -125, -97, 38, -141, + 31, 56, 41, 88, 29, 123, 87, 22, 125, + +/* 241 */ +8, 1, 22276, -3747, -19742, + 48, -106, 75, 49, -132, 82, 14, -106, 39, -61, -71, -56, + -56, 105, -85, -48, 125, -80, 7, 156, -22, + +/* 242 */ +10, 1, -16881, -24201, 5419, + -73, 37, -65, -75, 32, -95, -64, 29, -74, 60, -59, -77, + 117, -85, -15, 9, 15, 101, 70, -48, 1, 35, -8, 76, + -39, 49, 98, + +/* 243 */ +8, 1, -26588, 12735, 5561, + -52, -110, -1, -64, -123, -29, -32, -112, 98, 26, 1, 117, + 60, 110, 43, 41, 123, -81, 39, 119, -83, + +/* 244 */ +8, -1, 15516, 21285, -14359, + 23, 35, 76, 93, 9, 115, 97, -78, -10, 65, -106, -84, + 1, -79, -116, -126, 63, -47, -117, 100, 21, + +/* 245 */ +8, 1, 7216, 28601, -5469, + -30, -19, -138, 2, -31, -152, -102, 13, -61, -63, 39, 115, + 40, 19, 146, 74, 4, 118, 101, -17, 42, + +/* 246 */ +8, 1, 3833, 29553, 3454, + 2, 11, -94, -34, 18, -128, 11, 16, -167, -129, 16, 5, + 28, -19, 150, -9, -15, 145, 51, -17, 88, + +/* 247 */ +8, 1, 8843, 28172, 5303, + 87, -18, -50, 96, -15, -85, -82, 41, -80, -143, 38, 39, + -156, 43, 31, -1, -21, 116, 113, -45, 51, + +/* 248 */ +7, 1, 21050, -381, -21372, + -94, -69, -91, -60, -120, -55, -138, -33, -132, 42, 113, 37, + 87, 98, 82, 100, 30, 97, + +/* 249 */ +7, -1, 3999, 25672, 14999, + -52, -42, 85, -37, -69, 127, -3, -123, 204, 68, 48, -97, + 34, 74, -133, 7, 66, -113, + +/* 250 */ +8, 1, -26361, 12892, 6235, + 1, -67, 145, -25, -108, 108, -66, -133, -7, 7, -5, 35, + 64, 140, -9, 25, 106, -109, 6, 79, -137, + +/* 251 */ +7, 1, 5148, 25410, 15094, + -78, -27, 72, -48, -71, 134, 82, -126, 180, 79, 41, -93, + 22, 67, -118, -13, 83, -135, + +/* 252 */ +7, 1, 24083, -4111, -17411, + -86, -14, -114, -93, -6, -126, -79, 82, -125, 26, 70, 20, + 82, -15, 114, 86, -24, 122, + +/* 253 */ +8, 1, 12234, -12996, -24113, + -13, 134, -78, -26, 127, -81, 41, 134, -49, 38, -2, 21, + 7, -140, 76, 11, -113, 66, -8, -133, 66, + +/* 254 */ +7, 1, 1263, 19267, 22961, + -88, -22, 23, -158, -114, 102, 113, -77, 58, 145, -30, 17, + 99, 111, -97, -85, 84, -65, + +/* 255 */ +7, 1, 24383, 5280, -16661, + 76, -40, 99, 82, -101, 90, 0, -112, -34, -83, -22, -130, + -94, 69, -117, -28, 126, -2, + +/* 256 */ +7, 1, -3500, 28664, 8132, + -101, 3, -56, -87, -33, 79, 32, -31, 122, 146, -35, 183, + 74, 35, -91, -25, 38, -140, + +/* 257 */ +8, -1, 10996, 25265, 11864, + 114, -70, 44, 116, -82, 64, 52, -26, 5, -116, 97, -94, + -74, 86, -116, -38, 46, -62, -72, -30, 131, + +/* 258 */ +7, 1, -8489, -28676, 2368, + -45, 2, -135, 100, -37, -107, 135, -40, -4, 125, -27, 112, + -82, 28, 67, -130, 43, 60, + +/* 259 */ +7, 1, -8544, -28708, 1696, + -64, 29, 149, -100, 35, 82, -99, 28, -39, -66, 10, -166, + 105, -33, -17, 131, -44, -61, + +/* 260 */ +7, 1, -13684, 26583, 2464, + -102, -45, -76, -137, -72, -1, -98, -61, 98, 57, 23, 82, + 129, 64, 34, 127, 69, -25, + +/* 261 */ +7, 1, -26462, 13710, -3429, + -39, -77, -11, -70, -135, 9, -110, -205, 50, 42, 81, -8, + 70, 130, -33, 70, 134, -11, + +/* 262 */ +8, 1, 25177, -2424, -16132, + 51, -55, 88, 15, -120, 43, 7, -149, 35, -50, -56, -68, + -40, 47, -72, -13, 136, -42, -1, 134, -23, + +/* 263 */ +7, 1, -3593, 28752, 7771, + -130, -26, 38, 52, -25, 114, 199, 4, 74, -100, 25, -133, + 94, -2, 50, -8, 17, -66, + +/* 264 */ +7, -1, 18992, 23204, -949, + 50, -38, 79, 76, -60, 101, 116, -98, -56, 11, -14, -132, + -109, 85, -121, -102, 88, 82, + +/* 265 */ +8, -1, 16204, 715, 25237, + 81, 6, -52, 141, -44, -91, 9, 71, -7, 57, 116, -41, + -71, -2, 46, -126, -45, 84, -122, -29, 79, + +/* 266 */ +7, 1, 11947, 21012, -17769, + 90, -72, -26, 194, -154, -48, -100, 47, -12, -129, 85, 11, + -141, 54, -30, 6, 35, 45, + +/* 267 */ +8, 1, -16323, 24985, 3054, + -64, -37, -40, -137, -88, -25, 45, 14, 127, 106, 64, 47, + -94, -61, -2, 45, 28, 14, 119, 78, 0, + +/* 268 */ +8, -1, 7459, 26926, 10924, + 54, -44, 73, 122, -54, 47, 141, -87, 112, -11, 22, -44, + -44, 63, -124, -40, 29, -43, -140, 56, -39, + +/* 269 */ +7, 1, 4421, 25599, -15005, + -163, 57, 51, -149, 43, 31, 21, 58, 107, 177, -45, -28, + 85, -78, -109, 70, -35, -40, + +/* 270 */ +7, 1, -3740, 24124, -17437, + 101, -6, -30, 60, -71, -110, 103, -102, -159, -74, 7, 24, + -92, 67, 110, -103, 58, 101, + +/* 271 */ +7, -1, 1630, 23899, 18060, + -7, -73, 97, 26, -79, 102, 152, 4, -20, 36, 74, -101, + -85, 82, -100, -54, 59, -73, + +/* 272 */ +8, -1, 17320, 22752, -9075, + 98, -58, 42, 126, -77, 52, 92, -86, -38, -16, -14, -65, + -118, 74, -44, -114, 64, -61, -33, 40, 37, + +/* 273 */ +7, 1, 6068, 25608, 14403, + -109, -11, 63, -81, -45, 113, 88, -96, 131, 38, 13, -37, + 76, 40, -102, 88, 57, -137, + +/* 274 */ +7, -1, 17827, 6043, 23359, + 31, 69, -41, 30, 130, -58, -71, 130, 20, -122, -25, 100, + -17, -150, 53, 104, -86, -57, + +/* 275 */ +7, 1, 1364, -29308, -6258, + -135, 6, -59, 24, 23, -99, 160, 6, 5, 116, 9, -12, + -36, -41, 177, -50, -18, 77, + +/* 276 */ +7, -1, -18191, -23193, 5583, + -74, 68, 39, -13, 62, 212, -55, 22, -91, -92, 34, -161, + 66, -58, -18, 115, -88, 14, + +/* 277 */ +7, 1, -5480, 29422, -2079, + -34, -15, -115, -39, -20, -165, -65, -8, 54, -52, 0, 129, + -26, 6, 157, 144, 28, 11, + +/* 278 */ +7, 1, -26312, 13467, 5132, + -14, -64, 92, 38, 20, 140, 63, 44, 193, -5, 18, -68, + -32, 5, -167, -49, -50, -118, + +/* 279 */ +7, 1, 22241, 13603, 14842, + -48, 6, 67, -63, -46, 135, -55, -108, 176, 47, -5, -64, + 67, 36, -130, 39, 71, -123, + +/* 280 */ +7, -1, -10783, 26096, -10136, + -73, -35, -11, -140, -53, 13, -193, -93, -27, 52, 35, 34, + 133, 61, 9, 143, 53, -17, + +/* 281 */ +7, 1, 29783, 1256, -3378, + 4, 68, 62, 9, 88, 122, 11, 87, 149, 6, -96, 12, + -11, -65, -136, -11, -87, -135, + +/* 282 */ +6, 1, -17758, 24025, 2727, + -29, -6, -136, -87, -59, -52, -36, -45, 161, -5, -25, 188, + 115, 91, -49, + +/* 283 */ +7, -1, -23952, 18049, 730, + -55, -75, 42, -87, -119, 38, -109, -148, 28, 35, 46, 27, + 86, 118, -37, 85, 116, -45, + +/* 284 */ +7, -1, -1959, 8253, 28776, + -85, -33, 3, -109, -82, 16, -4, -124, 34, 54, -81, 27, + -38, 210, -62, 109, 71, -12, + +/* 285 */ +7, 1, 24446, -969, -17363, + -58, -41, -79, -90, 6, -125, -105, 28, -146, 25, 31, 33, + 90, 3, 124, 90, -3, 125, + +/* 286 */ +8, 1, 2887, 27868, 10725, + 80, 24, -85, 93, 20, -77, 7, 53, -145, -59, -21, 75, + -54, 25, -53, -39, -26, 81, -25, -45, 125, + +/* 287 */ +7, 1, 21419, -3233, -20756, + -24, -119, -5, 12, -123, 32, -51, -112, -33, -75, 85, -91, + 2, 117, -17, 84, 108, 68, + +/* 288 */ +8, 1, 20078, -7369, -21038, + -57, -7, -51, -117, -24, -103, -4, 61, -24, 22, 130, -24, + 47, 74, 19, 75, -19, 78, 19, -139, 65, + +/* 289 */ +7, 1, 10608, 21446, -18098, + -155, 71, -6, -130, 74, 14, -41, 49, 34, 179, -75, 14, + 129, -71, -9, 65, -54, -26, + +/* 290 */ +7, 1, 16151, -1050, -25260, + 73, -1, 47, 122, 24, 78, 149, -61, 101, -61, -44, -39, + -138, -12, -89, -119, 62, -80, + +/* 291 */ +7, 1, 6256, -8530, -28073, + -89, -10, -17, -70, 70, -36, 128, 113, -6, 110, 109, -7, + 42, -69, 29, -89, -109, 12, + +/* 292 */ +7, 1, 21026, 13541, -16569, + 85, -69, 51, 75, -69, 41, 109, -154, 15, -55, 43, -35, + -94, 98, -42, -107, 95, -60, + +/* 293 */ +8, -1, -18859, -22602, 5789, + 106, -54, 128, -49, 49, 33, -140, 115, -9, 47, -48, -33, + -95, 67, -50, 48, -51, -39, 45, -53, -57, + +/* 294 */ +7, -1, 13656, 23661, 12396, + 32, 42, -116, -54, 77, -89, -37, 92, -139, -18, -4, 28, + 39, -82, 118, 30, -82, 124, + +/* 295 */ +6, 1, 8006, 23007, -17510, + -151, 56, 6, -121, 86, 60, 17, 53, 78, 158, -90, -50, + 129, -58, -17, + +/* 296 */ +6, 1, 3087, 24735, 16693, + -183, -19, 61, 72, -85, 112, 104, -38, 36, 118, 33, -70, + -33, 81, -113, + +/* 297 */ +8, 1, -12618, 24857, -11088, + 2, -45, -102, -53, -74, -102, -86, -31, 27, -39, -19, 5, + -60, -22, 19, 43, 77, 120, 114, 79, 46, + +/* 298 */ +7, 1, -11749, 25130, -11421, + -35, -49, -71, -110, -76, -53, -90, -82, -83, -13, 29, 76, + 66, 77, 98, 79, 60, 49, + +/* 299 */ +6, 1, 25018, -660, -16543, + 66, -4, 101, 79, 41, 119, 27, -147, 48, -86, -7, -132, + -78, 19, -120, + +/* 300 */ +6, 1, -15854, -24577, 6681, + -80, 25, -102, -66, -1, -162, 84, -61, -26, 86, -28, 105, + 62, -4, 134, + +/* 301 */ +7, -1, -17115, 24557, -2011, + -4, -10, -84, -33, -36, -146, -32, -36, -148, -29, -18, 28, + 31, 35, 137, 43, 41, 129, + +/* 302 */ +6, 1, 11398, -4172, -27435, + 70, -114, 47, -117, -58, -40, -136, -105, -39, 19, 127, -12, + 86, 103, 19, + +/* 303 */ +6, 1, -7436, 14318, 25292, + -138, -58, -8, -83, -61, 10, 93, -96, 81, 117, 106, -25, + 98, 110, -33, + +/* 304 */ +6, 1, 23814, -745, -18231, + 5, -93, 11, -74, -60, -93, -123, 36, -160, 55, 113, 66, + 88, 29, 112, + +/* 305 */ +6, 1, -1698, 25570, 15597, + -88, -23, 28, -115, -50, 69, -31, -88, 138, 120, 34, -41, + 93, 65, -95, + +/* 306 */ +6, 1, -11912, 25153, -11200, + 122, 17, -91, -65, -58, -60, -143, -93, -55, -30, 42, 124, + 22, 55, 98, + +/* 307 */ +7, -1, -20089, -9689, 20064, + -66, 89, -24, -76, 153, -4, -18, -81, -56, 69, -127, 9, + 0, -83, -41, 39, -9, 36, + +/* 308 */ +6, -1, 22251, 15516, -12811, + -4, -87, -113, -86, 26, -115, -20, 54, 30, -35, 135, 102, + 72, -15, 105, + +/* 309 */ +6, 1, -6458, 14255, 25595, + -96, -106, 34, -5, -26, 13, 156, 64, 4, 89, 105, -36, + -32, 97, -62, + +/* 310 */ +6, 1, 24489, -4261, -16797, + -10, -92, 9, -89, -34, -121, -92, 55, -144, 55, 71, 59, + 88, 1, 127, + +/* 311 */ +6, 1, -3316, 28682, 8146, + -99, 13, -88, -180, -9, -46, 35, -13, 63, 114, -17, 109, + 104, -4, 57, + +/* 312 */ +6, 1, 23528, 1053, -18582, + -67, 39, -83, -53, 129, -59, 31, 123, 48, 82, -81, 98, + 24, -132, 22, + +/* 313 */ +6, 1, -6353, 29317, -386, + 14, 2, -107, -3, -4, -150, -118, -26, -18, -33, -4, 162, + 41, 10, 114, + +/* 314 */ +6, 1, 23124, -10704, 15834, + -88, -20, 114, -37, -123, -29, 45, -75, -117, 87, 56, -90, + 11, 96, 50, + +/* 315 */ +6, 1, -10965, -27064, 6879, + 25, 16, 101, -67, 56, 109, -142, 44, -53, -20, -23, -122, + 130, -66, -46, + +/* 316 */ +6, -1, 4917, 27988, 9617, + 96, -21, 12, 87, 14, -86, -36, 72, -196, -54, -7, 52, + -60, -39, 146, + +/* 317 */ +6, 1, -11542, -27125, 5570, + 69, -16, 65, 6, 36, 182, -109, 54, 35, -56, 5, -86, + 48, -47, -128, + +/* 318 */ +6, 1, 22858, -880, -19409, + 54, -24, 64, 110, -68, 135, -61, -87, -69, -99, 7, -118, + -23, 91, -31, + +/* 319 */ +6, 1, -27648, 11150, 3354, + -39, -102, 17, -24, -74, 43, 36, 42, 159, 49, 126, -16, + 5, 55, -140, + +/* 320 */ +6, 1, 4612, 1962, 29578, + -94, -31, 17, -91, -132, 22, 33, -105, 1, 110, 57, -20, + 72, 140, -20, + +/* 321 */ +6, 1, -1839, 23767, -18214, + 43, -51, -70, 184, -58, -92, -78, -8, -5, -124, 19, 37, + -76, 60, 86, + +/* 322 */ +6, 1, -26596, 11995, 6985, + -39, -139, 86, -29, -85, 33, 2, -50, 90, 31, 136, -108, + 38, 127, -73, + +/* 323 */ +6, 1, 23795, -164, -18269, + 46, -55, 61, -29, -158, -37, -96, -53, -122, 18, 74, 22, + 25, 130, 30, + +/* 324 */ +6, -1, -22867, -15404, 11824, + 41, 24, 111, -8, 76, 82, -82, 57, -84, -53, -42, -157, + 49, -85, -16, + +/* 325 */ +6, 1, 11693, 24510, -12748, + -64, -20, -97, -125, 88, 56, 42, 40, 114, 136, -64, 1, + 67, -45, -25, + +/* 326 */ +6, 1, -11168, -26833, 7435, + 18, 20, 99, 82, 1, 123, -42, 34, 56, -107, 16, -99, + -14, -37, -154, + +/* 327 */ +6, 1, -13936, 24051, -11284, + -74, -76, -70, -60, -62, -58, -96, -32, 54, 16, 53, 90, + 118, 80, 24, + +/* 328 */ +6, 1, 29225, 434, -6762, + 18, 61, 82, 30, 61, 138, 16, -62, 70, -16, -81, -79, + -37, -17, -167, + +/* 329 */ +5, 1, -3608, -29413, 4678, + -92, 6, -37, -199, 3, -144, 96, -6, 43, 125, -3, 78, + +/* 330 */ +5, 1, 27658, 11617, -322, + 34, -81, 36, 84, -207, -52, -36, 85, -79, -53, 132, 33, + +/* 331 */ +5, 1, -2705, -28959, 7352, + -24, 22, 78, -115, 57, 175, -66, -24, -114, 139, -38, -97, + +/* 332 */ +5, -1, -15874, 23873, -8837, + -68, -40, 15, -221, -126, 61, 94, 56, -19, 128, 75, -31, + +/* 333 */ +5, 1, -22981, 137, 19284, + -96, -29, -116, 4, -81, 5, 107, -35, 129, 62, 114, 74, + +/* 334 */ +6, 1, -7340, 25545, -13913, + 87, 9, -28, 74, -38, -109, -2, -50, -89, -113, 4, 66, + -83, 37, 110, + +/* 335 */ +5, 1, 1932, 28169, -10137, + 142, 19, 82, 88, -34, -77, -105, -34, -118, -115, 11, 8, + +/* 336 */ +5, 1, -2239, 29202, 6500, + -27, -20, 78, -46, -58, 238, 41, 25, -94, 42, 36, -144, + +/* 337 */ +5, -1, -24505, 2604, 17110, + -50, -99, -58, -20, -122, -12, 90, 19, 128, 35, 129, 31, + +/* 338 */ +6, 1, -20336, -21189, 6121, + -11, 37, 90, -61, 85, 91, -79, 63, -47, 19, -48, -101, + 71, -85, -53, + +/* 339 */ +4, 1, 4254, 3683, -29468, + 320, 25, 52, -163, -16, -27, -105, -40, -21, + +/* 340 */ +5, 1, 4284, 29586, 2515, + 59, 0, -105, -86, 24, -147, -98, 6, 99, 20, -12, 112, + +/* 341 */ +5, 1, -26886, 10733, 7871, + 29, -12, 114, 85, 100, 149, -24, 16, -99, -51, -28, -135, + +/* 342 */ +5, 1, -13498, 24234, -11425, + -105, -65, -12, -169, -85, 22, 68, 62, 51, 135, 68, -19, + +/* 343 */ +6, -1, 22043, 16210, -12301, + -56, 32, -58, -70, 134, 52, 64, 2, 117, -33, -4, -66, + 48, -85, -26, + +/* 344 */ +5, 1, 22450, -6144, -18928, + -111, 30, -140, 55, 152, 16, 59, 16, 65, 15, -137, 61, + +/* 345 */ +5, 1, 20013, 16577, -14989, + 52, -6, 63, 140, -83, 97, -48, -44, -114, -124, 73, -85, + +/* 346 */ +5, 1, 8227, 28696, 2972, + -15, 23, -188, -99, 29, -5, -66, 8, 107, 111, -40, 86, + +/* 347 */ +5, 1, -6380, 29120, -3367, + -28, -18, -102, -113, -43, -141, -18, 11, 124, 101, 37, 117, + +/* 348 */ +5, 1, 23793, -10289, 15101, + -94, -116, 68, -13, -97, -48, 94, 56, -108, 39, 97, 6, + +/* 349 */ +5, 1, 18853, -3180, 23118, + 48, -117, -55, 67, 16, -53, -36, 157, 51, -37, 80, 41, + +/* 350 */ +5, 1, -2898, 29718, 2905, + 106, 19, -87, -6, 15, -174, -95, -14, 55, -20, -16, 149, + +/* 351 */ +5, 1, 4133, 24673, -16558, + 22, -39, -52, -49, -76, -124, -81, -28, -61, 43, 111, 173, + +/* 352 */ +5, 1, -17359, 23518, 6748, + -106, -60, -61, -67, -75, 87, 88, 36, 99, 82, 64, -9, + +/* 353 */ +5, 1, 24745, -5658, -15990, + -70, 25, -116, -48, 118, -113, 42, 17, 57, 54, -81, 111, + +/* 354 */ +5, 1, -6134, 29314, -1752, + -118, -26, -10, -166, -33, 39, 76, 20, 58, 144, 29, -27, + +/* 355 */ +5, -1, -18455, -22892, 5946, + -81, 50, -58, -89, 38, -136, 53, -53, -39, 76, -27, 138, + +/* 356 */ +5, 1, 7506, 28869, -3200, + -114, 35, 46, 63, -2, 141, 110, -29, -5, 21, -19, -124, + +/* 357 */ +5, 1, -19149, -22531, 5067, + -69, 67, 39, -156, 123, -52, 66, -66, -41, 108, -86, 30, + +/* 358 */ +4, 1, -11154, 10714, -25706, + -86, -136, -19, -138, 16, 67, 39, 94, 22, + +/* 359 */ +5, 1, -11977, -26541, 7220, + 35, 14, 107, 21, 37, 167, -80, 16, -72, -11, -35, -141, + +/* 360 */ +5, -1, 12975, 18669, 19573, + 11, 61, -65, -125, 125, -37, -62, -53, 91, 109, -97, 21, + +/* 361 */ +5, 1, -10778, 27815, 3183, + 3, 14, -112, -37, -4, -95, -103, -47, 69, 52, 2, 161, + +/* 362 */ +5, 1, 5802, 24352, 16532, + 54, 21, -49, 116, 84, -168, -73, -13, 47, -91, -61, 122, + +/* 363 */ +5, 1, 10271, 19027, 20796, + -105, -43, 91, 86, -57, 9, 138, -37, -34, -25, 72, -53, + +/* 364 */ +5, 1, -3812, -7158, -28883, + -111, 23, 9, 13, 124, -32, 177, -2, -23, -12, -93, 24, + +/* 365 */ +5, -1, -26344, 13706, 4261, + -48, -69, -76, -47, -96, 15, 4, -31, 122, 74, 139, 13, + +/* 366 */ +4, 1, 4332, -21849, -20096, + 26, -143, 162, -151, 20, -55, 29, 71, -71, + +/* 367 */ +5, 1, 11385, 17811, 21287, + -72, -41, 73, -16, -121, 108, 94, 11, -58, 28, 107, -104, + +/* 368 */ +5, 1, -25127, 12810, -10224, + -25, -70, -26, -55, -132, -27, -31, -66, -6, 84, 203, 43, + +/* 369 */ +5, 1, 12061, -19379, -19468, + 5, 59, -55, 129, 111, -29, 57, -24, 58, -99, -108, 46, + +/* 370 */ +5, 1, 14601, -4888, -25747, + -33, -105, 1, -141, -47, -70, -24, 67, -26, 108, 73, 46, + +/* 371 */ +5, 1, 3182, 28027, 10215, + 85, 25, -94, -63, 50, -119, -84, -20, 80, 0, -45, 125, + +/* 372 */ +5, 1, 24760, -13205, -10611, + 48, 83, 9, 95, 156, 31, -11, -49, 34, -80, -123, -34, + +/* 373 */ +5, 1, 22676, -468, -19636, + 56, -46, 66, -18, -132, -18, -76, -21, -86, -5, 159, -11, + +/* 374 */ +5, 1, -8077, 26065, -12464, + 24, -25, -69, 23, -83, -185, -55, 7, 48, -13, 63, 140, + +/* 375 */ +5, 1, -16783, -24152, 5918, + 73, -71, -85, 118, -89, -31, -30, 39, 75, -98, 81, 53, + +/* 376 */ +5, 1, 3471, 29597, 3461, + 97, -6, -45, 40, 14, -168, -80, 10, -3, -41, -11, 138, + +/* 377 */ +5, 1, -23913, 14805, -10440, + -45, -76, -3, -118, -129, 90, 31, 66, 22, 92, 106, -63, + +/* 378 */ +5, 1, -13537, 24149, -11558, + -78, -47, -6, -155, -73, 31, 19, 38, 57, 133, 62, -27, + +/* 379 */ +5, 1, 25723, -3019, -15140, + 2, -81, 20, -24, -199, 1, -13, 55, -33, 15, 150, -7, + +/* 380 */ +5, 1, 18791, -8648, -21728, + -47, 28, -51, -101, 94, -124, 74, 33, 50, 73, -79, 94, + +/* 381 */ +5, 1, -8993, -28620, -183, + 89, -27, -50, 148, -46, 22, -1, 0, 52, -139, 43, 28, + +/* 382 */ +5, 1, -8768, -28641, -1673, + 23, -13, 95, -32, 2, 151, -70, 24, -46, 16, 3, -153, + +/* 383 */ +5, -1, 16062, 838, 25324, + 49, 20, -32, 167, 83, -110, -83, -10, 54, -116, -55, 76, + +/* 384 */ +5, 1, -26157, 14015, 4405, + -30, -67, 29, -77, -171, 83, 22, 47, -18, 57, 127, -58, + +/* 385 */ +5, 1, 21813, 15801, -13211, + -2, -58, -71, -52, -66, -164, -11, 47, 39, 26, 72, 126, + +/* 386 */ +5, -1, -19641, 22184, 4702, + -76, -56, -55, -110, -117, 85, 52, 40, 29, 78, 83, -59, + +/* 387 */ +5, 1, 15005, -1299, -25945, + -59, -53, -32, -124, -41, -69, -8, 102, -9, 133, 23, 75, + +/* 388 */ +5, 1, -10453, 11094, -25839, + 67, -43, -46, -1, -102, -42, -151, -27, 49, 32, 108, 33, + +/* 389 */ +5, 1, -26735, 12315, 5795, + -46, -82, -39, -37, -127, 97, 35, 47, 62, 40, 120, -67, + +/* 390 */ +5, -1, -16802, 23231, -8833, + -19, -44, -78, -139, -124, -58, 33, 33, 22, 101, 96, 58, + +/* 391 */ +5, 1, 14422, -5109, -25805, + -79, -114, -21, -125, -36, -62, 57, 63, 19, 112, 85, 45, + +/* 392 */ +5, 1, 10064, -5982, -27621, + -68, -60, -12, -159, -76, -40, 16, 47, -5, 131, 70, 32, + +/* 393 */ +5, 1, 24783, -4317, -16345, + 6, -74, 28, -42, -75, -43, -68, 125, -136, 56, 14, 81, + +/* 394 */ +5, 1, -13180, 26791, 2922, + 52, 32, -58, 2, 16, -147, -90, -46, 20, -26, -27, 133, + +/* 395 */ +4, 1, -1749, 25344, 15957, + -94, -46, 62, 119, -78, 137, -3, 58, -93, + +/* 396 */ +5, 1, -26328, 14008, -3259, + -27, -66, -62, -66, -147, -86, 14, 34, 27, 52, 118, 77, + +/* 397 */ +4, 1, 24089, 7261, -16340, + 48, -182, -10, -71, 8, -101, -20, 136, 32, + +/* 398 */ +4, 1, -7194, 13999, 25540, + 129, 4, 33, 19, 128, -65, -131, -13, -29, + +/* 399 */ +5, -1, -24613, 17122, 1025, + -3, -11, 108, -31, -55, 138, 11, 15, 3, 31, 54, -135, + +/* 400 */ +5, 1, 20152, -5943, 21414, + -22, -105, -8, 22, -119, -55, 45, 37, -32, -6, 160, 52, + +/* 401 */ +5, 1, -1915, 23677, -18322, + -91, -20, -17, -173, 3, 23, 42, 15, 15, 142, 5, -9, + +/* 402 */ +5, 1, -23760, 17289, 6048, + 47, 40, 67, 89, 121, 3, 20, 27, -4, -112, -147, -13, + +/* 403 */ +5, 1, -14558, 23775, -11081, + 15, -31, -86, -12, -74, -142, -40, -5, 41, 4, 69, 142, + +/* 404 */ +5, 1, -12479, 24643, -11704, + -55, -50, -48, -152, -89, -22, 17, 26, 36, 120, 74, 27, + +/* 405 */ +4, 1, 5264, 29534, -120, + 82, -15, -121, -123, 21, -60, -42, 9, 160, + +/* 406 */ +5, 1, 13262, -5908, -26253, + -65, -72, -16, -137, -56, -56, 7, 54, -9, 131, 60, 52, + +/* 407 */ +4, 1, -20288, 22087, 756, + 19, 19, -81, -118, -104, -125, 29, 23, 110, + +/* 408 */ +5, 1, 19086, -2847, 22970, + 38, 55, -25, 26, 149, -4, -46, 33, 42, -22, -149, 1, + +/* 409 */ +4, 1, -2873, 28899, 7523, + -133, -13, 0, 14, -30, 117, 144, 12, 10, + +/* 410 */ +5, 1, 15596, 18597, -17633, + 67, -43, 14, 89, -115, -41, -45, -18, -58, -66, 96, 41, + +/* 411 */ +5, -1, -28925, 7951, 348, + 9, 27, 78, 35, 121, 116, -1, -1, -35, -24, -79, -152, + +/* 412 */ +5, -1, 9541, 23385, 16190, + -2, -50, 73, 79, -109, 108, 19, 19, -38, -53, 97, -107, + +/* 413 */ +5, 1, 29210, 473, -6823, + 15, 77, 72, 31, 35, 138, -2, -56, -13, -30, -68, -138, + +/* 414 */ +5, 1, -25829, 15180, 1561, + -4, 2, -86, -23, -24, -175, 1, 0, 31, 20, 19, 148, + +/* 415 */ +5, 1, -20000, 22355, 530, + -25, -22, -75, -69, -59, -143, -15, -14, 47, 64, 55, 123, + +/* 416 */ +4, 1, -444, -28368, 9750, + 52, 35, 103, -161, 22, 54, 22, -47, -132, + +/* 417 */ +4, 1, 2286, 29384, 5600, + -108, 22, -73, -64, -19, 124, 98, -19, 59, + +/* 418 */ +4, 1, -9750, 11346, -26004, + 114, -63, -70, -93, -91, -4, -88, 65, 60, + +/* 419 */ +4, 1, 29357, 1075, -6086, + 26, -12, 125, 3, -133, -7, -25, 20, -118, + +/* 420 */ +5, 1, -4180, -7285, -28800, + -96, 6, 12, 12, 67, -18, 173, 35, -34, -21, -79, 23, + +/* 421 */ +4, 1, 21812, -2819, -20403, + 43, -216, 77, -30, 61, -41, -39, 132, -60, + +/* 422 */ +4, 1, -6475, 29293, -129, + -137, -31, 54, 34, 8, 102, 130, 29, -57, + +/* 423 */ +4, 1, -9851, -28219, 2574, + -20, 18, 125, -123, 38, -61, 54, -29, -113, + +/* 424 */ +4, 1, 6163, -10670, -27353, + 84, 30, 8, -8, -122, 46, -130, -35, -16, + +/* 425 */ +5, 1, 24033, 10600, 14493, + -1, -61, 47, -4, -116, 90, 29, -16, -37, -1, 119, -84, + +/* 426 */ +4, 1, -10404, 28061, 2080, + -168, -58, -65, 15, 0, 83, 149, 52, 44, + +/* 427 */ +4, -1, -6287, 25435, -14613, + -175, -65, -37, -33, 20, 50, 109, 54, 46, + +/* 428 */ +4, 1, 3313, 24533, 16946, + 72, -54, 64, 137, 8, -41, -83, 49, -52, + +/* 429 */ +5, 1, -17749, 22168, 9672, + -55, -22, -51, -134, -84, -55, 35, 14, 33, 110, 69, 45, + +/* 430 */ +4, 1, -24211, 14614, -10014, + -45, -101, -37, -61, -44, 84, 77, 151, 33, + +/* 431 */ +5, 1, 6168, 20534, 20984, + 78, -19, -5, 155, -9, -37, -14, 11, -7, -148, 19, 25, + +/* 432 */ +4, 1, 25249, 3517, -15816, + 54, -55, 75, -32, -104, -73, -61, 98, -77, + +/* 433 */ +5, 1, 24510, 6812, -15901, + -3, -70, -35, -47, -99, -113, -7, 16, -4, 32, 110, 94, + +/* 434 */ +4, 1, 8900, 28579, 2013, + -28, 18, -145, -98, 29, 17, 48, -23, 129, + +/* 435 */ +4, 1, -19110, -22514, 5287, + -134, 112, -16, 34, -47, -73, 77, -68, -7, + +/* 436 */ +4, 1, -26431, 12476, 6763, + -53, -173, 112, 21, 25, 32, 28, 120, -106, + +/* 437 */ +4, 1, -6923, 29146, -1603, + -11, -10, -135, -86, -21, -1, 12, 12, 153, + +/* 438 */ +4, 1, -7322, 29032, -1885, + -93, -29, -71, -84, -16, 84, 116, 34, 54, + +/* 439 */ +4, 1, 3874, 29626, 2697, + 158, -14, -71, -62, 11, -39, -140, 12, 75, + +/* 440 */ +5, -1, -20399, -10562, 19296, + -47, 54, -21, -103, 82, -64, 4, -32, -13, 72, -61, 43, + +/* 441 */ +4, 1, -12040, -26645, 6714, + 91, -7, 132, -57, 34, 35, -79, -3, -151, + +/* 442 */ +4, 1, -8141, 28851, -1154, + -44, -19, -149, -67, -18, 19, 46, 19, 149, + +/* 443 */ +4, 1, -26611, 11542, 7659, + -88, -157, -73, 26, 23, 58, 70, 125, 54, + +/* 444 */ +4, 1, -25420, 7629, 13987, + 24, -119, 108, 39, 84, 24, -21, 80, -81, + +/* 445 */ +4, 1, -361, 26098, 14791, + -10, -64, 111, 54, -28, 50, 26, 82, -142, + +/* 446 */ +4, 1, -10298, 18382, 21356, + 130, -27, 85, 49, 46, -16, -147, 13, -81, + +/* 447 */ +4, 1, -6714, 29188, -1727, + -94, -24, -29, -73, -10, 108, 114, 26, -7, + +/* 448 */ +4, 1, -14486, -9145, -24628, + -107, -23, 72, 0, 72, -27, 104, 40, -76, + +/* 449 */ +3, 1, -12116, 27417, 1220, + -145, -70, 134, 73, 33, -17, + +/* 450 */ +4, 1, 12149, -27337, -2254, + -8, 3, -82, 91, 46, -59, -14, -19, 153, + +/* 451 */ +3, 1, 4304, 29609, 2188, + -48, 20, -185, -38, -3, 124, + +/* 452 */ +4, 1, -12276, 24972, -11211, + -4, -43, -90, -130, -57, 15, 74, 60, 50, + +/* 453 */ +4, 1, 3993, 24360, 17048, + 106, 2, -27, -55, 80, -102, -56, -28, 53, + +/* 454 */ +4, 1, 4361, 29555, 2736, + -38, 14, -91, -116, 16, 2, 75, -20, 101, + +/* 455 */ +4, 1, -18479, -23127, 4866, + -52, 67, 118, -61, 35, -66, 59, -62, -71, + +/* 456 */ +4, -1, 2259, 21690, 20602, + 163, 40, -61, -51, 30, -26, -119, -48, 64, + +/* 457 */ +4, 1, 20331, 14288, -16807, + 113, -62, 84, 2, -51, -41, -116, 87, -67, + +/* 458 */ +4, 1, -16786, -24244, 5517, + -13, -14, -98, 115, -77, 10, -36, 41, 70, + +/* 459 */ +4, 1, -1657, 25010, 16486, + -107, 31, -59, -27, -59, 86, 106, -9, 25, + +/* 460 */ +4, 1, -1331, -20857, -21523, + -32, 87, -81, 12, 31, -31, 94, -42, 35, + +/* 461 */ +3, 1, -26552, 5728, 12735, + 86, -10, 182, -41, 30, -98, + +/* 462 */ +3, 1, -11118, 27856, 637, + -170, -68, 5, 82, 32, 63, + +/* 463 */ +4, 1, 2831, -28218, 9783, + 42, 27, 67, -99, 15, 70, -19, -40, -108, + +/* 464 */ +3, 1, 23950, 2362, -17911, + 20, -179, 4, -44, 82, -49, + +/* 465 */ +3, 1, 29304, 688, -6390, + 3, -151, 3, -18, 18, -82, + +/* 466 */ +3, 1, -9197, -28136, 4878, + -159, 68, 85, 75, -37, -64, + +/* 467 */ +4, 1, -10259, 28140, 1705, + -56, -25, 63, 62, 17, 101, 34, 17, -76, + +/* 468 */ +3, 1, 29280, 766, -6487, + 34, 42, 158, -23, -96, -116, + +/* 469 */ +4, 1, 6865, 26520, 12229, + -38, -15, 54, 43, -56, 96, 50, 31, -93, + +/* 470 */ +3, 1, 13499, -19327, -18554, + 45, 135, -107, 13, -80, 93, + +/* 471 */ +3, -1, 16732, 5918, 24187, + -123, 131, 53, 50, -84, -14, + +/* 472 */ +3, 1, 13670, -4696, -26288, + -146, -71, -63, 60, 85, 15, + +/* 473 */ +3, 1, 2313, 23926, -17950, + -161, -16, -41, 80, 47, 72, + +/* 474 */ +3, 1, 3781, 28274, 9290, + 93, 34, -146, -91, -6, 58, + +/* 475 */ +3, 1, 25584, 3122, -15352, + -85, -26, -147, 17, 59, 39, + +/* 476 */ +3, 1, 29702, 3744, -1936, + 17, -153, -35, -15, 89, -55, + +/* 477 */ +3, 1, 24789, 6574, -15566, + 65, -169, 34, -52, 102, -40, + +/* 478 */ +3, -1, -29247, 6430, 1802, + -11, -85, 122, 17, 72, 23, + +/* 479 */ +3, 1, -6095, 14636, 25468, + -135, -95, 22, 97, 7, 20, + +/* 480 */ +3, 1, -10821, 10826, -25801, + -167, -23, 61, 65, 41, -11, + +/* 481 */ +3, 1, 29023, 590, -7570, + 34, -5, 129, -19, -95, -79, + +/* 482 */ +3, 1, 23976, 5439, -17192, + 39, -177, -1, -33, 87, -18, + +/* 483 */ +4, 1, 5247, 29038, -5412, + -99, 36, 100, 26, 0, 28, 97, -32, -81, + +/* 484 */ +4, 1, -18202, -23335, 4919, + 15, 5, 73, -62, 62, 68, 2, -22, -100, + +/* 485 */ +3, 1, 5756, -9056, -28015, + 57, -84, 39, -130, -10, -23, + +/* 486 */ +3, 1, -11472, -27071, 5962, + -89, 67, 132, 14, -25, -86, + +/* 487 */ +3, 1, -12893, 26395, 6088, + -47, 3, -113, -50, -50, 112, + +/* 488 */ +3, 1, 5886, -8242, -28239, + 26, 166, -42, 24, -67, 24, + +/* 489 */ +4, 1, 8245, 18657, 21999, + -25, -59, 59, 73, -66, 28, 2, 70, -60, + +/* 490 */ +3, 1, 5232, 21275, 20494, + 58, -123, 112, -13, 69, -68, + +/* 491 */ +4, 1, -16253, -24546, 5776, + -9, -21, -120, 76, -43, 33, -12, 23, 62, + +/* 492 */ +3, -1, 9502, 25942, 11694, + 165, -65, 8, -75, 35, -15, + +/* 493 */ +3, 1, -12159, 27406, 1045, + -141, -66, 59, 88, 39, 12, + +/* 494 */ +3, 1, 5425, 21100, 20624, + 135, -94, 60, -70, 58, -40, + +/* 495 */ +3, -1, 3389, 22127, 19973, + -144, 69, -53, 28, -42, 42, + +/* 496 */ +3, 1, -29998, -271, -211, + 1, -103, -27, -1, 44, 124, + +/* 497 */ +3, 1, -6646, 3953, 28986, + 154, -35, 40, -66, 64, -23, + +/* 498 */ +3, 1, 17776, -4397, -23763, + -125, -94, -76, 59, 61, 33, + +/* 499 */ +3, 1, 15919, -2901, -25262, + -86, -113, -41, 2, 103, -10, + +/* 500 */ +3, 1, 10276, 18702, 21087, + 34, -115, 84, 49, 48, -65, + +/* 501 */ +3, 1, -27182, 9729, 8156, + 24, -63, 152, 0, 71, -83, + +/* 502 */ +3, 1, -5062, 29557, -877, + -151, -26, 15, 102, 19, 47, + +/* 503 */ +3, 1, 5323, -9639, -27906, + 94, -7, 20, -115, -91, 10, + +/* 504 */ +3, 1, 9566, 21962, -18060, + 80, -60, -30, -146, 87, 28, + +/* 505 */ +3, 1, 7782, 19198, 21700, + 98, -114, 65, -23, 74, -57, + +/* 506 */ +3, 1, -25374, 8277, 13699, + 37, 132, -12, -48, -43, -63, + +/* 507 */ +3, 1, -21077, 21320, 1096, + -106, -101, -82, 53, 50, 70, + +/* 508 */ +3, 1, 24281, -1036, -17589, + -21, -166, -18, -1, 96, -8, + +/* 509 */ +3, 1, -22788, 37, 19512, + -85, -52, -100, 83, -20, 97, + +/* 510 */ +3, 1, 5240, 28832, -6422, + -69, 36, 103, 119, -31, -39, + +/* 511 */ +3, 1, -7468, -28825, -3652, + 127, -23, -73, -26, -5, 83, + +/* 512 */ +3, 1, 24788, 6981, -15389, + -28, -91, -85, -27, 111, 6, + +/* 513 */ +3, 1, -23208, -6, 19010, + -80, -82, -98, 74, 14, 91, + +/* 514 */ +3, 1, -2403, 29024, 7200, + 6, -38, 153, 37, 26, -90, + +/* 515 */ +3, 1, -8354, 27070, 9869, + 31, 63, -147, -39, -31, 53, + +/* 516 */ +3, 1, 25819, 2792, -15019, + 68, -90, 100, -56, 16, -93, + +/* 517 */ +3, 1, -13037, 26839, 3117, + 36, 33, -139, -71, -42, 72, + +/* 518 */ +3, 1, 19424, 15377, -16920, + 93, -132, -12, -64, 64, -15, + +/* 519 */ +3, 1, 25368, -2667, -15790, + -16, -138, -3, -25, 82, -54, + +/* 520 */ +3, 1, -27385, 6432, 10424, + 17, -117, 116, -6, 67, -55, + +/* 521 */ +3, 1, -16689, -24298, 5573, + 100, -55, 59, -44, 42, 51, + +/* 522 */ +3, 1, 7818, 28361, 5876, + -144, 51, -56, 68, -29, 50, + +/* 523 */ +3, 1, -1083, 23630, -18452, + 50, -78, -102, -92, 30, 44, + +/* 524 */ +3, 1, 25414, 6393, -14604, + -41, -106, -116, 11, 70, 48, + +/* 525 */ +3, 1, -11631, 906, -27639, + 120, 91, -47, -49, -80, 18, + +/* 526 */ +3, 1, 3474, 212, 29797, + -59, -123, 8, 98, 50, -12, + +/* 527 */ +3, 1, 2829, 27930, 10580, + 17, 48, -134, -69, -20, 73, + +/* 528 */ +3, 1, -18229, -23261, 5161, + -120, 85, -43, 79, -65, -12, + +/* 529 */ +3, 1, 1852, 23822, 18140, + -125, -44, 70, 101, 2, -12, + +/* 530 */ +3, 1, 17469, 17022, -17466, + 116, -106, 12, -62, 33, -30, + +/* 531 */ +3, 1, -13668, 26130, 5512, + -117, -58, -16, 61, 16, 79, + +/* 532 */ +3, 1, -16825, 22385, -10761, + -69, -60, -18, 116, 107, 41, + +/* 533 */ +3, 1, -17801, -23670, 4779, + -107, 95, 71, 39, -40, -52, + +/* 534 */ +3, -1, -16972, 24643, -2166, + -50, -47, -138, -6, 3, 78, + +/* 535 */ +3, 1, -29510, -1408, 5213, + -15, -102, -117, 12, 23, 79, + +/* 536 */ +3, 1, -8023, 14394, 25068, + -68, 34, -40, 15, -116, 71, + +/* 537 */ +3, 1, 18663, 8080, 22054, + -75, 93, 30, -31, -36, 39, + +/* 538 */ +3, 1, 20234, -5953, -21335, + -49, 130, -81, 31, -57, 45, + +/* 539 */ +3, 1, 9465, -4873, -28048, + -62, -145, 5, 10, 86, -12, + +/* 540 */ +3, 1, 11849, -3988, -27271, + -79, -106, -18, -3, 100, -16, + +/* 541 */ +3, 1, 19173, 8661, 21387, + 61, -39, -39, -116, 87, 69, + +/* 542 */ +3, 1, -25383, 8079, 13799, + -8, -129, 61, 32, 94, 5, + +/* 543 */ +3, 1, -947, 23612, -18482, + 119, -50, -69, -79, -3, 0, + +/* 544 */ +3, 1, -20303, -21276, 5923, + -76, 41, -110, 64, -56, 18, + +/* 545 */ +3, 1, -3266, 29707, 2611, + 37, 16, -138, -65, -11, 47, + +/* 546 */ +3, 1, 29437, 5643, -1268, + 24, -114, 44, -6, 9, -82, + +/* 547 */ +3, 1, 5941, -8348, -28196, + 33, -77, 30, -118, 6, -27, + +/* 548 */ +3, 1, 8674, 28665, 1747, + 63, -15, -64, -102, 33, -41, + +/* 549 */ +3, 1, 12119, -27290, -2892, + 132, 54, 46, -68, -33, 16, + +/* 550 */ +3, 1, 16774, 7079, -23844, + 82, -124, 22, -73, 54, -36, + +/* 551 */ +3, 1, 20757, 13260, 17126, + 63, -128, 22, -13, 88, -51, + +/* 552 */ +3, 1, -23106, 319, 19132, + -14, -153, -16, 23, 75, 27, + +/* 553 */ +3, 1, 28708, 8390, -2334, + 41, -117, 87, -18, 41, -74, + +/* 554 */ +3, -1, -17143, 22854, -9157, + -56, -49, -15, 111, 102, 47, + +/* 555 */ +3, 1, 24593, -4420, -16602, + -58, 81, -108, 42, -1, 63, + +/* 556 */ +3, 1, -5670, 29343, -2618, + -124, -24, 0, 70, 19, 69, + +/* 557 */ +3, 1, 29384, 4265, -4286, + 19, -142, -11, -16, 73, -41, + +/* 558 */ +3, -1, -26493, 13413, -4266, + 73, 129, -48, -41, -79, 9, + +/* 559 */ +3, 1, -12215, 8751, 25965, + 50, 90, -6, -110, -43, -38, + +/* 560 */ +3, 1, 942, -9821, -28331, + -127, 40, -18, 18, 36, -12, + +/* 561 */ +3, 1, 5791, -10962, -27318, + 72, -41, 31, -101, -56, 1, + +/* 562 */ +3, 1, -16110, -24557, 6118, + -55, 1, -140, 52, -15, 77, + +/* 563 */ +3, 1, 24603, 7780, -15303, + 19, -130, -35, -41, 81, -25, + +/* 564 */ +3, 1, -11587, 7787, 26554, + -77, 78, -57, 3, -100, 31, + +/* 565 */ +3, -1, -16566, 24953, -1701, + -34, -32, -139, -15, -5, 72, + +/* 566 */ +3, 1, -10538, 27951, 2769, + -113, -50, 71, 82, 32, -2, + +/* 567 */ +3, 1, -26227, 14265, -2946, + -29, -81, -126, 8, 32, 76, + +/* 568 */ +3, 1, -29996, -410, 275, + 1, -64, -4, 0, 96, 102, + +/* 569 */ +3, 1, -1328, 24397, 17407, + -88, -68, 88, 79, 22, -24, + +/* 570 */ +3, 1, 28640, 5411, -7103, + 16, -124, -30, -25, 81, -41, + +/* 571 */ +3, 1, 2879, 27986, 10415, + 44, 45, -133, -48, -14, 52, + +/* 572 */ +3, 1, -10402, -26170, 10341, + -140, 40, -40, 64, -24, 4, + +/* 573 */ +3, 1, -10281, 28087, 2329, + -106, -42, 34, 78, 24, 50, + +/* 574 */ +3, 1, 2742, 27846, 10820, + 85, 35, -111, -70, -7, 34, + +/* 575 */ +3, 1, -3438, -29243, -5748, + 43, 20, -125, 29, -18, 76, + +/* 576 */ +3, 1, -26723, 12841, 4584, + -66, -110, -80, 29, 43, 47, + +/* 577 */ +3, 1, -1401, 24087, 17828, + -1, -60, 81, 89, 26, -28, + +/* 578 */ +3, 1, 5935, -7944, -28314, + 15, 145, -37, 11, -47, 15, + +/* 579 */ +3, 1, 22691, -404, -19620, + 90, -40, 105, -74, 0, -86, + +/* 580 */ +3, 1, -615, 23609, -18500, + -27, -62, -78, -73, 25, 34, + +/* 581 */ +3, 1, -7610, 27327, 9765, + 86, 9, 39, 11, 34, -85, + +/* 582 */ +3, 1, 3275, 28106, 9967, + 66, 34, -120, -66, -8, 46, + +/* 583 */ +3, 1, -1798, 26125, -14637, + -125, -47, -69, 60, 25, 37, + +/* 584 */ +3, 1, 3404, 28154, 9786, + 16, 34, -104, -83, -3, 38, + +/* 585 */ +3, 1, -19236, -22431, 5182, + -95, 81, -4, 41, -48, -59, + +/* 586 */ +3, 1, 16386, -1104, 25106, + -73, 82, 50, -24, -52, 14, + +/* 587 */ +3, 1, 19553, -4260, -22350, + 63, -51, 65, -69, -44, -52, + +/* 588 */ +3, 1, -22905, 18425, 5990, + 96, 104, 47, -33, -35, -18, + +/* 589 */ +3, 1, -12241, 25010, -11164, + -117, -70, -28, 42, 42, 46, + +/* 590 */ +3, 1, -6089, -28902, -5253, + 34, 14, -117, 43, -22, 71, + +/* 591 */ +3, 1, 14736, -4824, -25682, + -43, -106, -5, -40, 63, -34, + +/* 592 */ +3, 1, 19044, 17073, -15679, + 94, -108, -3, -64, 54, -19, + +/* 593 */ +3, 1, -16277, 25021, 3001, + -102, -58, -78, 32, 15, 59, + +/* 594 */ +3, 1, 3248, 24619, 16833, + -38, -76, 118, 31, 32, -52, + +/* 595 */ +3, 1, -19337, -22287, 5420, + 18, 15, 122, -54, 25, -89, + +/* 596 */ +3, 1, 3510, 24558, 16869, + 47, -68, 89, 36, 36, -59, + +/* 597 */ +3, 1, -6842, 29209, -35, + -123, -29, 15, 65, 16, 45, + +/* 598 */ +3, 1, -15937, 22907, -11013, + -119, -62, 44, 55, 39, 1, + +/* 599 */ +3, 1, 27779, 11315, -526, + -49, 121, -23, 9, -22, 44, + +/* 600 */ +3, 1, -12034, 25103, -11183, + -63, -58, -60, -41, 5, 55, + +/* 601 */ +3, 1, 11603, -4113, -27358, + -14, -103, 10, -64, 53, -35, + +/* 602 */ +3, 1, 12813, -2626, -26999, + -4, -132, 12, -36, 71, -25, + +/* 603 */ +3, 1, -25308, 8431, 13728, + 38, -43, 95, 1, 89, -52, + +/* 604 */ +3, 1, -25475, 7114, 14157, + 31, 120, -5, -42, -62, -45, + +/* 605 */ +3, 1, 13199, -12085, -24077, + 70, 108, -16, 5, -60, 32, + +/* 606 */ +3, 1, -14219, 23894, -11265, + -85, -85, -73, 26, 40, 52, + +/* 607 */ +3, 1, 4551, -23163, -18514, + 29, -77, 104, -49, 25, -44, + +/* 608 */ +3, 1, 5199, -9999, -27803, + 75, 10, 11, -79, -92, 18, + +/* 609 */ +3, 1, -3465, -29255, -5667, + -50, -13, 95, -26, 22, -95, + +/* 610 */ +3, 1, 20448, -6320, 21022, + 74, -52, -87, -11, 63, 29, + +/* 611 */ +3, 1, -11210, -27380, 4968, + -67, 47, 106, 7, -15, -70, + +/* 612 */ +3, 1, -7114, 29104, -1523, + -31, -14, -125, -26, -3, 61, + +/* 613 */ +3, 1, 11126, 17559, 21631, + 8, -111, 86, 4, 44, -38, + +/* 614 */ +3, -1, -17516, 22482, -9368, + -37, -44, -36, 77, 91, 75, + +/* 615 */ +3, 1, 23571, -1939, -18457, + -68, 34, -90, 37, 41, 43, + +/* 616 */ +3, 1, -6394, -28910, -4832, + -27, 25, -112, 68, -24, 51, + +/* 617 */ +3, 1, 5794, 26057, 13692, + -56, -45, 108, 58, 8, -38, + +/* 618 */ +3, 1, -23934, 17129, 5813, + -32, -36, -30, 79, 85, 78, + +/* 619 */ +3, 1, -23357, -76, 18827, + -56, -97, -71, 41, 25, 52, + +/* 620 */ +3, 1, 7231, -5628, -28566, + -117, 22, -34, 64, 34, 9, + +/* 621 */ +3, -1, 8011, -2165, 28829, + -86, -20, 23, 42, -72, -17, + +/* 622 */ +3, 1, -17637, -23714, 5158, + -108, 70, -51, 50, -34, 13, + +/* 623 */ +3, 1, 21913, -8820, 18494, + 66, 118, -23, -34, -46, 20, + +/* 624 */ +3, 1, 9869, 19293, 20746, + -85, -38, 75, 55, -24, -4, + +/* 625 */ +3, 1, 22899, -4077, -18947, + -26, -86, -13, -37, 52, -57, + +/* 626 */ +3, 1, -14038, 23901, -11476, + -107, -72, -17, 35, 39, 38, + +/* 627 */ +3, 1, 4353, 24653, 16531, + 69, -61, 72, 12, 41, -63, + +/* 628 */ +3, 1, -18051, -23470, 4832, + -30, 48, 118, -10, -6, -67, + +/* 629 */ +3, 1, 28220, 10019, -1806, + 23, -82, -83, -25, 72, 3, + +/* 630 */ +3, 1, -20490, -21140, 5764, + -5, 32, 100, -44, 19, -85, + +/* 631 */ +3, 1, 3983, 28240, 9309, + 12, 35, -113, -52, -6, 40, + +/* 632 */ +3, 1, -18699, -22936, 4930, + -91, 67, -33, 37, -37, -36, + +/* 633 */ +3, 1, 627, 18932, 23264, + -84, -62, 52, 85, 7, -8, + +/* 634 */ +3, 1, 19354, 14991, 17340, + 50, -98, 28, 14, 46, -55, + +/* 635 */ +3, 1, -28747, 8411, 1693, + 22, 50, 121, -5, -4, -59, + +/* 636 */ +3, 1, -8901, 26791, 10151, + -2, 39, -105, -41, -14, 0, + +/* 637 */ +3, 1, -1847, 24835, 16728, + -27, -53, 75, 84, 19, -19, + +/* 638 */ +3, 1, -10396, 25971, 10836, + 84, 12, 51, -45, 21, -93, + +/* 639 */ +3, 1, -1746, 26561, 13836, + 46, -54, 110, 4, 27, -50, + +/* 640 */ +3, -1, -16548, 24985, -1391, + 30, 12, -123, -40, -23, 44, + +/* 641 */ +3, 1, -23092, 1143, 19117, + -29, -97, -30, 49, 20, 58, + +/* 642 */ +3, -1, -9616, 27575, -6867, + -86, -18, 48, 81, 35, 28, + +/* 643 */ +3, 1, 37, -8773, -28689, + -83, 89, -27, 70, -24, 8, + +/* 644 */ +3, 1, -5877, 24660, -16042, + 29, -63, -107, -41, 19, 43, + +/* 645 */ +3, 1, -7063, 29124, 1383, + -106, -24, -46, 12, 1, 50, + +/* 646 */ +3, 1, 9491, -28294, 3062, + 88, 35, 49, -28, -5, 40, + +/* 647 */ +3, 1, -10563, 28011, -1955, + -92, -37, -31, 2, 5, 62, + +/* 648 */ +3, 1, -23006, 339, 19251, + -51, -80, -59, 52, 6, 61, + +/* 649 */ +3, -1, 24368, 17193, -3258, + 40, -67, -52, -54, 71, -25, + +/* 650 */ +3, 1, -8017, 28176, 6466, + -87, -36, 52, 72, 15, 24, + +/* 651 */ +3, 1, -26550, 11424, 8038, + 29, -20, 121, -1, 36, -53, + +/* 652 */ +3, 1, 28996, 6412, -4254, + -29, 112, -31, 13, -29, 48, + +/* 653 */ +3, 1, -11839, 8554, 26204, + 61, 27, 19, -107, 18, -54, + +/* 654 */ +3, 1, -20098, -21617, 5362, + -31, 53, 101, -18, 2, -58, + +/* 655 */ +3, 1, 21155, 4033, -20886, + 40, -117, 19, -35, 34, -29, + +/* 656 */ +3, 1, 5515, 20897, 20806, + 103, -68, 41, -37, 35, -25, + +/* 657 */ +3, 1, -29988, -222, -832, + -2, 50, 61, 3, 22, -100, + +/* 658 */ +3, 1, 5034, 26084, 13938, + 21, -49, 84, 54, 10, -38, + +/* 659 */ +3, 1, 1691, 19298, 22907, + -89, 3, 4, 81, -54, 40, + +/* 660 */ +3, 1, 2119, 26865, 13182, + -116, -3, 25, 58, -16, 24, + +/* 661 */ +3, 1, 10789, 18377, 21116, + -103, -6, 58, 62, -29, -7, + +/* 662 */ +3, 1, -11870, -26301, 8207, + 27, 19, 101, -65, 14, -51, + +/* 663 */ +3, 1, -18344, -23246, 4807, + -84, 74, 38, 27, -34, -58, + +/* 664 */ +3, 1, -11295, 25251, -11610, + -65, -58, -63, -15, 21, 60, + +/* 665 */ +3, 1, 6300, 20443, 21033, + 123, -14, -23, -36, 19, -8, + +/* 666 */ +3, 1, 29102, 725, -7249, + 27, 3, 111, -11, -45, -52, + +/* 667 */ +3, 1, -29997, -152, -412, + -1, 22, 82, 1, 52, -85, + +/* 668 */ +3, 1, -28040, 10545, 1595, + -32, -71, -94, 4, 4, 55, + +/* 669 */ +3, 1, 11026, 18001, 21316, + -97, -31, 76, 47, 1, -24, + +/* 670 */ +3, 1, 24332, 1794, -17457, + 32, 101, 56, 1, -69, -6, + +/* 671 */ +3, 1, 4781, 16690, 24466, + -96, 20, 5, 32, -59, 34, + +/* 672 */ +3, 1, 21656, -5891, -19908, + 21, 116, -11, 16, -38, 28, + +/* 673 */ +3, 1, -19012, -22658, 5013, + -83, 57, -54, 41, -38, -15, + +/* 674 */ +3, -1, -25345, 15903, 2173, + -67, -106, -3, 15, 21, 14, + +/* 675 */ +3, 1, 22404, -4219, -19500, + 44, -78, 68, -52, 23, -66, + +/* 676 */ +3, 1, -10163, 28146, 2130, + -89, -29, -52, 21, 3, 69, + +/* 677 */ +3, 1, -725, 25703, 15454, + -107, 19, -37, 23, -25, 44, + +/* 678 */ +3, 1, 25446, 6214, -14625, + 2, -95, -36, -28, 38, -33, + +/* 679 */ +3, 1, -18014, -23519, 4728, + -68, 67, 75, 12, -18, -46, + +/* 680 */ +3, 1, 8350, 18419, 22159, + 86, -67, 23, -8, 45, -34, + +/* 681 */ +3, 1, -16265, 24998, 3250, + -89, -55, -27, 11, 2, 45, + +/* 682 */ +3, 1, -29435, 3954, 4235, + -7, -102, 43, 10, 58, 20, + +/* 683 */ +3, 1, 14345, -4396, -25979, + -2, -120, 20, -17, 45, -17, + +/* 684 */ +3, 1, -20159, -21497, 5615, + -47, 63, 68, -11, -7, -64, + +/* 685 */ +3, 1, 17291, -23956, 5209, + -23, -40, -109, 33, 32, 41, + +/* 686 */ +3, 1, 6171, 20591, 20926, + 108, -24, -8, -25, 33, -25, + +/* 687 */ +3, 1, -8736, -28700, -52, + -34, 11, 92, -38, 11, -52, + +/* 688 */ +3, 1, -5134, 25663, -14664, + 63, -34, -82, -50, -7, 5, + +/* 689 */ +3, 1, 23474, -4238, -18194, + -71, -46, -80, 21, 43, 16, + +/* 690 */ +3, 1, -12945, 26676, 4562, + 4, 17, -91, -51, -38, 80, + +/* 691 */ +3, 1, 11880, -13958, -23749, + -2, 99, -60, 27, -28, 31, + +/* 692 */ +3, 1, 9893, 18457, 21482, + 67, -72, 30, 17, 31, -34, + +/* 693 */ +3, 1, -14530, 23658, -11366, + -35, -60, -80, -23, 11, 53, + +/* 694 */ +3, 1, -17616, -23753, 5046, + -93, 61, -37, 33, -27, -10, + +/* 695 */ +3, 1, 25086, -5507, -15503, + -51, 11, -86, 23, 44, 21, + +/* 696 */ +3, 1, -15610, -24492, 7515, + -12, -16, -78, 52, -2, 101, + +/* 697 */ +3, 1, -15472, 22928, -11615, + -58, -51, -24, -15, 24, 68, + +/* 698 */ +3, 1, -12165, 24913, -11461, + 34, -28, -96, -48, -12, 24, + +/* 699 */ +3, 1, 5310, 21296, 20452, + 21, -66, 64, 46, 12, -25, + +/* 700 */ +3, -1, 17800, 23716, -4555, + 58, -61, -85, -31, 27, 21, + +/* 701 */ +3, 1, 18987, -4163, 22851, + 56, 89, -31, -54, -31, 40, + +/* 702 */ +3, 1, -13833, 24181, -11133, + 4, -47, -107, -21, 7, 43, + +/* 703 */ +3, 1, 6651, 29245, -700, + 50, -11, 4, -96, 20, -60, + +/* 704 */ +3, 1, -25607, 5901, 14473, + -58, -52, -82, 27, -3, 49, + +/* 705 */ +3, 1, -19397, -22308, 5108, + 1, 25, 114, -14, 3, -42, + +/* 706 */ +3, 1, -23259, -297, 18946, + -53, -60, -67, 39, -10, 48, + +/* 707 */ +3, 1, -13405, 24297, -11400, + 11, -34, -86, -50, -16, 26, + +/* 708 */ +3, 1, 25842, -4398, -14590, + -3, -99, 25, -21, 27, -45, + +/* 709 */ +3, 1, -25303, 12454, -10231, + -57, -52, 78, 24, 41, -8, + +/* 710 */ +3, 1, -8255, 26088, -12300, + 82, -6, -67, -56, -15, 5, + +/* 711 */ +3, 1, 6152, -8008, -28249, + -89, 40, -31, 63, 17, 9, + +/* 712 */ +3, 1, -25934, 14888, 2405, + -36, -47, -101, 8, 8, 37, + +/* 713 */ +3, 1, -6774, 29199, -1229, + -15, -8, -109, -22, -3, 41, + +/* 714 */ +3, 1, -1560, 24786, 16830, + -10, -53, 77, 53, 17, -21, + +/* 715 */ +3, -1, -21338, 21065, -960, + -45, -41, 97, 19, 19, -19, + +/* 716 */ +3, 1, -5625, 24695, -16078, + 11, -41, -67, -64, -5, 15, + +/* 717 */ +3, 1, -26663, 12045, 6635, + -9, -70, 90, 11, 38, -27, + +/* 718 */ +3, 1, -27183, 11286, 5804, + -3, -54, 92, 15, 44, -17, + +/* 719 */ +3, 1, -20085, -21491, 5891, + -63, 66, 28, 2, -16, -51, + +/* 720 */ +3, 1, 11920, -13784, -23831, + 22, 98, -45, 15, -28, 23, + +/* 721 */ +3, 1, -19179, -22536, 4928, + -34, 47, 83, -13, -1, -57, + +/* 722 */ +3, 1, -355, 23212, 19002, + -92, 11, -15, 20, -33, 40, + +/* 723 */ +3, 1, 10541, 18339, 21273, + -78, -33, 68, 42, -8, -15, + +/* 724 */ +3, 1, -14382, 25139, 7820, + -90, -56, 16, 38, 15, 21, + +/* 725 */ +3, 1, -17775, -23685, 4805, + -61, 60, 70, 10, -16, -41, + +/* 726 */ +3, 1, 15192, -711, -25859, + -36, -88, -18, -22, 47, -15, + +/* 727 */ +3, 1, -25173, 6788, 14841, + 3, 81, -33, -30, -45, -31, + +/* 728 */ +3, 1, 23886, -136, -18151, + 33, -60, 45, -38, -20, -50, + +/* 729 */ +3, 1, -17001, 21978, 11312, + -63, -71, 42, 24, 10, 16, + +/* 730 */ +3, 1, 11428, -4389, -27389, + 22, -99, 25, -34, 23, -17, + +/* 731 */ +3, 1, -14644, 23549, -11447, + -47, -58, -57, -17, 11, 44, + +/* 732 */ +3, 1, 20716, -6655, 20653, + 26, -20, -32, -11, 92, 40, + +/* 733 */ +3, 1, -27252, 6392, 10793, + 0, -79, 45, 16, 25, 26, + +/* 734 */ +3, 1, 8257, 18817, 21858, + -26, -56, 57, 41, -17, -1, + +/* 735 */ +3, 1, 17728, -4370, -23804, + -69, -43, -43, -2, 40, -9, + +/* 736 */ +3, 1, 7081, 29143, -744, + 46, -10, 33, -16, 1, -93, + +/* 737 */ +3, 1, 20340, -6075, -21198, + -58, 54, -71, 24, -5, 24, + +/* 738 */ +3, 1, -10500, -27772, 4297, + 13, 7, 78, -57, 18, -24, + +/* 739 */ +3, 1, -21551, 16797, -12387, + -61, -25, 74, 20, 27, 1, + +/* 740 */ +3, 1, -23937, 14156, -11253, + 40, 42, -32, -29, -72, -28, + +/* 741 */ +3, 1, 2497, 24497, 17137, + 31, 52, -79, -35, -7, 14, + +/* 742 */ +3, 1, 21770, -2150, -20529, + -61, -66, -57, 14, 28, 12, + +/* 743 */ +3, 1, -10876, -27085, 6937, + 24, 15, 94, -38, 8, -29, + +/* 744 */ +3, 1, -26625, 11639, 7461, + -2, -58, 82, 13, 34, -9, + +/* 745 */ +3, -1, -25621, 14760, -5070, + -8, 16, 87, 27, 22, -74, + +/* 746 */ +3, 1, -16344, 22674, -10897, + -89, -53, 23, 21, 14, -3, + +/* 747 */ +3, 1, -15599, 23126, -11040, + -60, -53, -25, -14, 9, 38, + +/* 748 */ +3, 1, 2618, 27824, 10908, + 49, 19, -60, -43, 11, -19, + +/* 749 */ +3, -1, 13838, 15180, 21865, + 70, -66, 2, 3, 22, -18, + +/* 750 */ +3, 1, 29104, 5954, -4186, + -25, 89, -43, 9, -21, 32, + +/* 751 */ +3, -1, -17298, 24161, -4125, + -9, -22, -94, -19, -8, 36, + +/* 752 */ +3, 1, 7494, 29029, 1081, + 29, -6, -36, -80, 21, -19, + +/* 753 */ +3, -1, -19537, -11007, 19928, + -32, 64, 4, -30, 8, -25, + +/* 754 */ +3, 1, -18953, -22734, 4895, + -43, 49, 59, -8, -4, -50, + +/* 755 */ +3, 1, 13593, -5535, -26165, + -86, -27, -39, 14, 23, 3, + +/* 756 */ +3, -1, -19136, 21815, -7612, + -73, -60, 14, 6, 12, 19, + +/* 757 */ +3, 1, -24002, 17079, 5677, + -28, -7, -99, 6, 1, 24, + +/* 758 */ +3, 1, -26057, 14705, -2194, + -28, -61, -74, 6, 16, 44, + +/* 759 */ +3, 1, -25874, 9131, 12130, + 37, -3, 82, 4, 26, -11, + +/* 760 */ +3, -1, -22516, 16997, -10205, + -66, -59, 49, 14, 16, -6, + +/* 761 */ +3, 1, 15992, -257, 25381, + -2, 95, 2, -18, -43, 11, + +/* 762 */ +3, 1, -8284, 26137, -12175, + 54, -16, -71, -23, -10, -5, + +/* 763 */ +3, 1, -20414, -21222, 5734, + 10, 12, 81, -31, 24, -22, + +/* 764 */ +3, 1, -15647, 23076, -11075, + -62, -58, -33, 0, 15, 30, + +/* 765 */ +3, 1, -28391, 9662, -763, + -10, -37, -88, -2, -1, 37, +/* 766 */ +3, 1, 23132, 6353, 18016, + 60, -29, -68, -13, 23, 9, +/* 767 */ +3, -1, -24613, 16950, 2623, + -44, -58, -39, 16, 15, 55, +/* 768 */ +3, -1, 10870, -14991, 23603, + 35, -65, -58, 7, 21, 11, +/* 769 */ +3, 1, -27204, 11625, 4977, + -5, -47, 82, 5, 20, -16, +/* 770 */ +3, 1, -26269, 14142, -3158, + -28, -66, -58, -1, 3, 22, +/* 771 */ +3, 1, 2537, 27833, 10903, + -20, -29, 79, 23, 2, -9, +/* 772 */ +3, 1, -27160, 11434, 5619, + 0, -35, 71, 12, 28, 5, +/* 773 */ +3, 1, 29168, 5584, -4248, + -10, 72, 27, 7, -18, 25, +/* 774 */ +3, 1, 29735, 1076, -3832, + 3, 68, 47, 2, -31, 8, +/* 775 */ +3, -1, -1224, 25269, 16124, + -57, -36, 52, 10, 1, 0, +/* 776 */ +3, 1, -28530, 9221, 1000, + 22, 64, 44, 0, 1, -17, +0, +}; + +int vtkEarthSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int i; + int maxPts; + int maxPolys; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkCellArray *newPolys; + double x[3], base[3]; + vtkIdType Pts[4000]; + int npts, land, offset; + int actualpts, actualpolys; + double scale = 1.0/30000.0; + + // + // Set things up; allocate memory + // + maxPts = 12000 / this->OnRatio; + maxPolys = 16; + actualpts = actualpolys = 0; + + newPoints = vtkPoints::New(); + newPoints->Allocate(maxPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*maxPts); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(maxPolys,4000/this->OnRatio)); + + // + // Create points + // + offset = 0; + while (1) + { + // read a polygon + npts = vtkEarthData[offset++]; + if ((npts == 0) || (actualpolys > maxPolys)) + { + break; + } + + land = vtkEarthData[offset++]; + + base[0] = 0; + base[1] = 0; + base[2] = 0; + + for (i=1; i<=npts; i++) + { + base[0] += vtkEarthData[offset++] * scale; + base[1] += vtkEarthData[offset++] * scale; + base[2] += vtkEarthData[offset++] * scale; + + x[0] = base[2] * this->Radius; + x[1] = base[0] * this->Radius; + x[2] = base[1] * this->Radius; + + if ((land == 1) && (npts > this->OnRatio * 3)) + { + // use only every OnRatioth point in the polygon + if ((i % this->OnRatio) == 0) + { + newPoints->InsertNextPoint(x); + vtkMath::Normalize(x); + newNormals->InsertNextTuple(x); + actualpts++; + } + } + } + + if ((land == 1) && (npts > this->OnRatio * 3)) + { + // + // Generate mesh connectivity for this polygon + // + + for (i = 0; i < (npts/this->OnRatio); i++) + { + Pts[i] = (actualpts - npts/this->OnRatio) + i; + } + + if ( this->Outline ) // close the loop in the line + { + Pts[i] = (actualpts - npts/this->OnRatio); + newPolys->InsertNextCell(i+1,Pts); + } + else + { + newPolys->InsertNextCell(i,Pts); + } + + actualpolys++; + } + } + + // + // Update ourselves and release memeory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + if ( this->Outline ) //lines or polygons + { + output->SetLines(newPolys); + } + else + { + output->SetPolys(newPolys); + } + newPolys->Delete(); + + output->Squeeze(); + + return 1; +} diff --git a/Hybrid/vtkEarthSource.h b/Hybrid/vtkEarthSource.h new file mode 100644 index 0000000..a2da54a --- /dev/null +++ b/Hybrid/vtkEarthSource.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEarthSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEarthSource - create the continents of the Earth as a sphere +// .SECTION Description +// vtkEarthSource creates a spherical rendering of the geographical shapes +// of the major continents of the earth. The OnRatio determines +// how much of the data is actually used. The radius defines the radius +// of the sphere at which the continents are placed. Obtains data from +// an imbedded array of coordinates. + +#ifndef __vtkEarthSource_h +#define __vtkEarthSource_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_HYBRID_EXPORT vtkEarthSource : public vtkPolyDataAlgorithm +{ +public: + static vtkEarthSource *New(); + vtkTypeRevisionMacro(vtkEarthSource,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set radius of earth. + vtkSetClampMacro(Radius,double,0.0,VTK_LARGE_FLOAT); + vtkGetMacro(Radius,double); + + // Description: + // Turn on every nth entity. This controls how much detail the model + // will have. The maximum ratio is sixteen. (The smaller OnRatio, the more + // detail there is.) + vtkSetClampMacro(OnRatio,int,1,16); + vtkGetMacro(OnRatio,int); + + // Description: + // Turn on/off drawing continents as filled polygons or as wireframe outlines. + // Warning: some graphics systems will have trouble with the very large, concave + // filled polygons. Recommend you use OutlienOn (i.e., disable filled polygons) + // for now. + vtkSetMacro(Outline,int); + vtkGetMacro(Outline,int); + vtkBooleanMacro(Outline,int); + +protected: + vtkEarthSource(); + ~vtkEarthSource() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Radius; + int OnRatio; + int Outline; +private: + vtkEarthSource(const vtkEarthSource&); // Not implemented. + void operator=(const vtkEarthSource&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Hybrid/vtkExodusModel.cxx b/Hybrid/vtkExodusModel.cxx new file mode 100644 index 0000000..847e7af --- /dev/null +++ b/Hybrid/vtkExodusModel.cxx @@ -0,0 +1,1287 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExodusModel.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkExodusModel.h" +#include "vtkUnstructuredGrid.h" +#include "vtkObjectFactory.h" +#include "vtkDataArray.h" +#include "vtkIntArray.h" +#include "vtkFloatArray.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include +#include +#include +#include +#include + + +vtkCxxRevisionMacro(vtkExodusModel, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkExodusModel); + +vtkExodusModel::vtkExodusModel() +{ + this->ModelMetadata = NULL; + this->GeometryCount = -1; +} + +vtkExodusModel::~vtkExodusModel() +{ + this->SetModelMetadata(NULL); +} + +void vtkExodusModel::Reset() +{ + if (this->ModelMetadata) + { + this->ModelMetadata->Reset(); + } +} + +vtkModelMetadata *vtkExodusModel::GetModelMetadata() +{ + if (!this->ModelMetadata) + { + this->ModelMetadata = vtkModelMetadata::New(); + this->ModelMetadata->Register(this); + } + + return this->ModelMetadata; +} + +void vtkExodusModel::SetModelMetadata(vtkModelMetadata *emd) +{ + if (this->ModelMetadata == emd) return; + + if (this->ModelMetadata) + { + this->ModelMetadata->UnRegister(this); + this->ModelMetadata->Delete(); + this->ModelMetadata = NULL; + } + + if (emd) + { + this->ModelMetadata = emd; + emd->Register(this); + } +} + +//--------------------------------------------------------------- +// Initialize this ExodusModel object with the ExodusModel +// packed into a vtkUnstructuredGrid's field arrays. +//--------------------------------------------------------------- + +int vtkExodusModel::HasMetadata(vtkUnstructuredGrid *grid) +{ + int hasIt = 0; + + if (grid) + { + hasIt = vtkModelMetadata::HasMetadata(grid); + } + + return hasIt; +} +int vtkExodusModel::UnpackExodusModel(vtkUnstructuredGrid *grid, int deleteIt) +{ + vtkModelMetadata *mmd = this->GetModelMetadata(); + + int fail = mmd->Unpack(grid, deleteIt); + + return fail; +} + +//--------------------------------------------------------------- +// Pack the metadata in this ExodusModel object into the +// supplied vtkUnstructuredGrid. +//--------------------------------------------------------------- + +void vtkExodusModel::PackExodusModel(vtkUnstructuredGrid *grid) +{ + vtkModelMetadata *mmd = this->GetModelMetadata(); + + mmd->Pack(grid); + + return; +} +//--------------------------------------------------------------- +// Set all the global fields of the Exodus Model from an open +// Exodus file. +//--------------------------------------------------------------- + +int vtkExodusModel::SetGlobalInformation(int fid, int compute_word_size) +{ + int i; + int use_floats = (compute_word_size == sizeof(float)); + + int intVal; + float floatVal; + char charVal; + + vtkModelMetadata *emd = this->GetModelMetadata(); + + ex_opts(0); // turn off all error messages + + emd->FreeAllGlobalData(); + emd->FreeAllLocalData(); + + // Title and dimension + + char *title = new char [MAX_LINE_LENGTH + 1]; + int dim; + + ex_inquire(fid, EX_INQ_TITLE, &intVal, &floatVal, title); + ex_inquire(fid, EX_INQ_DIM, &dim, &floatVal, &charVal); + + emd->SetTitle(title); + + // QA records + + int nqaRecs; + ex_inquire(fid, EX_INQ_QA, &nqaRecs, &floatVal, &charVal); + + if (nqaRecs > 0) + { + typedef char *p4[4]; + p4 *qarecs = new p4 [nqaRecs]; + + for (i=0; iSetQARecords(nqaRecs, qarecs); + } + + // Information lines + + int ninfoLines; + ex_inquire(fid, EX_INQ_INFO, &ninfoLines, &floatVal, &charVal); + + if (ninfoLines > 0) + { + char **lines = new char * [ninfoLines]; + for (i=0; iSetInformationLines(ninfoLines, lines); + } + + // Coordinate names + + char **coordNames = new char * [dim]; + for (i=0; iSetCoordinateNames(dim, coordNames); + + // Time steps + // TODO - We convert time steps to float. We should fix this + // to respect the precision of the time values in the input + // file. + + int nTimeSteps; + ex_inquire(fid, EX_INQ_TIME, &nTimeSteps, &floatVal, &charVal); + + if (nTimeSteps > 0) + { + float *ts = new float [nTimeSteps]; + if (use_floats) + { + ex_get_all_times(fid, ts); + } + else + { + double *dts = new double [nTimeSteps]; + ex_get_all_times(fid, dts); + for (i=0; iSetTimeSteps(nTimeSteps, ts); + } + + // Block information + + int nblocks; + int *bids = NULL; + ex_inquire(fid, EX_INQ_ELEM_BLK, &nblocks, &floatVal, &charVal); + emd->SetNumberOfBlocks(nblocks); + + if (nblocks > 0) + { + bids = new int [nblocks]; + + ex_get_elem_blk_ids(fid, bids); + + char **types = new char * [nblocks]; + int *nodesPerElement = new int [nblocks]; + int *numAtt = new int [nblocks]; + + for (i=0; iSetBlockIds(bids); + emd->SetBlockElementType(types); + emd->SetBlockNodesPerElement(nodesPerElement); + emd->SetBlockNumberOfAttributesPerElement(numAtt); + } + else + { + vtkWarningMacro(<< + "ExodusModel finds no blocks. We thought that couldn't happen"); + } + + // Node set and Side set global information + + int nnsets; + int *nids = NULL; + int nssets; + int *sids = NULL; + ex_inquire(fid, EX_INQ_NODE_SETS, &nnsets, &floatVal, &charVal); + ex_inquire(fid, EX_INQ_SIDE_SETS, &nssets, &floatVal, &charVal); + emd->SetNumberOfNodeSets(nnsets); + emd->SetNumberOfSideSets(nssets); + + if (nnsets > 0) + { + nids = new int [nnsets]; + ex_get_node_set_ids(fid, nids); + emd->SetNodeSetIds(nids); + } + + if (nssets > 0) + { + sids = new int [nssets]; + ex_get_side_set_ids(fid, sids); + emd->SetSideSetIds(sids); + } + + // Block, Node set and Side set properties + + int nBlockProperties; + ex_inquire(fid, EX_INQ_EB_PROP, &nBlockProperties, &floatVal, &charVal); + + if (nBlockProperties > 0) + { + char **names = new char * [nBlockProperties]; + + for (i=0; i 0) + { + emd->SetBlockPropertyNames(nBlockProperties, names); + emd->SetBlockPropertyValue(val); + } + else + { + delete [] names; + delete [] val; + } + } + + int nNodeSetProperties; + ex_inquire(fid, EX_INQ_NS_PROP, &nNodeSetProperties, &floatVal, &charVal); + + if (nNodeSetProperties > 0) + { + char **names = new char * [nNodeSetProperties]; + + for (i=0; i 0) + { + emd->SetNodeSetPropertyNames(nNodeSetProperties, names); + emd->SetNodeSetPropertyValue(val); + } + else + { + delete [] names; + delete [] val; + } + } + + int nSideSetProperties; + ex_inquire(fid, EX_INQ_SS_PROP, &nSideSetProperties, &floatVal, &charVal); + + if (nSideSetProperties > 0) + { + char **names = new char * [nSideSetProperties]; + + for (i=0; i 0) + { + emd->SetSideSetPropertyNames(nSideSetProperties, names); + emd->SetSideSetPropertyValue(val); + } + else + { + delete [] names; + delete [] val; + } + } + + // Element variables and node variables: + + int nEltVars; + int nNodeVars; + + ex_get_var_param(fid, "E", &nEltVars); + ex_get_var_param(fid, "N", &nNodeVars); + + if (nEltVars > 0) + { + char **names = new char * [nEltVars]; + + for (i=0; iRemoveBeginningAndTrailingSpaces(names, nEltVars); + + emd->SetElementVariableInfo(nEltVars, names, 0, NULL, NULL, NULL); + } + + if (nNodeVars > 0) + { + char **names = new char * [nNodeVars]; + + for (i=0; iRemoveBeginningAndTrailingSpaces(names, nNodeVars); + + emd->SetNodeVariableInfo(nNodeVars, names, 0, NULL, NULL, NULL); + } + + // Block/element variable truth table, by block by element variable + + if ((nEltVars > 0) && (nblocks > 0)) + { + int *tt = new int [nEltVars * nblocks]; + + ex_get_elem_var_tab(fid, nblocks, nEltVars, tt); + + emd->SetElementVariableTruthTable(tt); + } + + // Global variables + + int nvars = 0; + ex_get_var_param(fid, "G", &nvars); + + if (nvars > 0) + { + char **nms = new char * [nvars]; + for (i=0; iSetGlobalVariableNames(nvars, nms); + } + + ex_opts(EX_VERBOSE); // turn error messages back on + + return 0; +} + +void vtkExodusModel::CopyDoubleToFloat(float *f, double *d, int len) +{ + for (int i=0; iGetModelMetadata(); + int i; + + int newTimeStep = (timeStep != emd->GetTimeStepIndex()); + + int newGeometry = (geoCount > this->GeometryCount); + this->GeometryCount = geoCount; + + if (!newTimeStep && !newGeometry) + { + return 0; + } + + ex_opts(0); // turn off all error messages + + int use_floats = (compute_word_size == sizeof(float)); + + if (newTimeStep) + { + emd->SetGlobalVariableValue(NULL); + + // GLOBAL VARIABLE VALUES AT THIS TIMESTEP + + int numGlobalVars = emd->GetNumberOfGlobalVariables(); + int ts = timeStep + 1; + + emd->SetTimeStepIndex(timeStep); + + if (numGlobalVars > 0) + { + float *varf = new float [numGlobalVars]; + + if (use_floats) + { + ex_get_glob_vars(fid, ts, numGlobalVars, varf); + } + else + { + double *vard = new double [numGlobalVars]; + ex_get_glob_vars(fid, ts, numGlobalVars, vard); + + for (i=0; iSetGlobalVariableValue(varf); + } + } + + if (ugrid->GetNumberOfCells() < 1) + { + return 0; + } + + // Big assumptions - this vtkUnstructuredGrid was created with the + // vtkExodusReader. If it contains any elements of a block, it + // contains all the elements, and they appear together and in the + // same order in the vtkUnstructuredGrid as they do in the Exodus file. + // The order of the blocks may be different in the vtkUnstructuredGrid + // than it is in the Exodus file. The vtkUnstructuredGrid + // contains cell arrays called BlockId and + // GlobalElementId and a point array called GlobalNodeId. + // + // Another assumption is that the element number map in the Exodus file + // matches the global element IDs in the vtkUnstructuredGrid, and the + // node number map in the Exodus file matches the global node IDs in + // the vtkUnstructuredGrid. (That is, we are both using the same + // global IDs to identify points and cells.) + // + // TODO - fix behavior on error + + // Check input + + int *blockIds = NULL; + int *cellIds = NULL; + int *pointIds = NULL; + + vtkDataArray *da = ugrid->GetCellData()->GetArray("BlockId"); + if (da) + { + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + if (ia) + { + blockIds = ia->GetPointer(0); + } + } + + da = ugrid->GetCellData()->GetArray("GlobalElementId"); + if (da) + { + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + if (ia) + { + cellIds = ia->GetPointer(0); + } + } + + da = ugrid->GetPointData()->GetArray("GlobalNodeId"); + if (da) + { + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + if (ia) + { + pointIds = ia->GetPointer(0); + } + } + + if (!blockIds || !cellIds || !pointIds) + { + return 1; + } + + int nblocks = emd->GetNumberOfBlocks(); + int ncells = ugrid->GetNumberOfCells(); + int npoints = ugrid->GetNumberOfPoints(); + if ((nblocks < 1) || (ncells < 1)) return 1; + + if (newGeometry) + { + // BLOCK, NODE SET, AND SIDE SET LISTS + + emd->FreeBlockDependentData(); + + this->SetLocalBlockInformation(fid, use_floats, blockIds, + cellIds, ncells); + + if (emd->GetNumberOfNodeSets() > 0) + { + this->SetLocalNodeSetInformation(fid, use_floats, pointIds, npoints); + } + + if (emd->GetNumberOfSideSets() > 0) + { + this->SetLocalSideSetInformation(fid, use_floats, cellIds, ncells); + } + } + + ex_opts(EX_VERBOSE); // turn error messages back on + + return 0; +} +int vtkExodusModel::SetLocalBlockInformation( + int fid, int use_floats, int *blockIds , int *cellIds, int ncells) +{ + int i; + + vtkModelMetadata *emd = this->GetModelMetadata(); + + int nblocks = emd->GetNumberOfBlocks(); + + if (nblocks < 1) + { + return 0; // maybe this is really an error, I'm not sure + } + + int *count = new int [nblocks]; + memset(count, 0, sizeof(int) * nblocks); + int lastId = -1; + int idx = 0; + + vtkstd::map blockIdStart; + vtkstd::map::iterator it; + + for (i=0; iGetBlockLocalIndex(id); + + if ((idx < 0) || (count[idx] > 0)) + { + // Bad block ID or elements are not in order by block + + delete [] count; + return 1; + } + + blockIdStart.insert(vtkstd::map::value_type(idx, i)); + lastId = id; + } + + count[idx]++; + } + + int *GlobalBlockIds = emd->GetBlockIds(); + + for (idx=0; idxSetBlockNumberOfElements(count); + + int *idList = new int [ncells]; + float *attsF = NULL; + double *attsD = NULL; + + int natts = emd->GetSizeBlockAttributeArray(); + + if (natts > 0) + { + attsF = new float [natts]; + + if (!use_floats) + { + attsD = new double [natts]; + } + } + + int *eltIdIdx = emd->GetBlockElementIdListIndex(); + int *attIdx = emd->GetBlockAttributesIndex(); + int *numAttsPerElement = emd->GetBlockNumberOfAttributesPerElement(); + + for (idx=0; idxsecond; + + memcpy(idList + to, cellIds + from, sizeof(int) * count[idx]); + + if (attsF == NULL) continue; + + if (numAttsPerElement[idx] == 0) continue; + + to = attIdx[idx]; + + if (use_floats) + { + ex_get_elem_attr(fid, GlobalBlockIds[idx], attsF + to); + } + else + { + ex_get_elem_attr(fid, GlobalBlockIds[idx], attsD + to); + } + } + + blockIdStart.erase(blockIdStart.begin(), blockIdStart.end()); + + emd->SetBlockElementIdList(idList); + + if (attsF) + { + if (!use_floats) + { + this->CopyDoubleToFloat(attsF, attsD, natts); + delete [] attsD; + } + emd->SetBlockAttributes(attsF); + } + + return 0; +} +int vtkExodusModel::SetLocalNodeSetInformation( + int fid, int use_floats, int *pointIds, int npoints) +{ + int i, j; + float dummyFloat; + char dummyChar; + + vtkModelMetadata *emd = this->GetModelMetadata(); + + // external node IDs in file + + int numNodesInFile = 0; + ex_inquire(fid, EX_INQ_NODES, &numNodesInFile, &dummyFloat, &dummyChar); + int *nodeMap = new int [numNodesInFile]; + + ex_get_node_num_map(fid, nodeMap); + + // external node IDs in vtkUnstructuredGrid + + vtkstd::map localNodeIdMap; + vtkstd::map::iterator it; + + for (i=0; i::value_type(pointIds[i], i)); + } + + int nns = emd->GetNumberOfNodeSets(); + int *numDF = new int [nns]; + + int *nssize = new int [nns]; + memset(nssize, 0, sizeof(int) * nns); + + vtkIntArray *nsNodeIds = vtkIntArray::New(); + nsNodeIds->SetNumberOfComponents(1); + + vtkFloatArray *nsDF = vtkFloatArray::New(); + nsDF->SetNumberOfComponents(1); + + int total = 0; + + int *nodeSetIds = emd->GetNodeSetIds(); + + for (i=0; iCopyDoubleToFloat(dfF, dfD, nnodes); + delete [] dfD; + } + } + + // find which of my points are in this node set + + for (j=0; jInsertNextValue(gid); + + if (dfF) + { + nsDF->InsertNextValue(dfF[j]); + } + + nssize[i]++; + total++; + } + + delete [] nodes; + if (dfF) delete [] dfF; + } + + delete [] nodeMap; + + localNodeIdMap.erase(localNodeIdMap.begin(), localNodeIdMap.end()); + + emd->SetNodeSetSize(nssize); + + if (total > 0) + { + int *nsndf = new int [nns]; + + for (i=0; i 0) + { + nsndf[i] = nssize[i]; + } + else + { + nsndf[i] = 0; + } + } + + delete [] numDF; + + emd->SetNodeSetNumberOfDistributionFactors(nsndf); + + int *ids = new int [total]; + memcpy(ids, nsNodeIds->GetPointer(0), sizeof(int) * total); + + nsNodeIds->Delete(); + + emd->SetNodeSetNodeIdList(ids); + + int sizeDF = nsDF->GetNumberOfTuples(); + + if (sizeDF > 0) + { + float *df = new float [sizeDF]; + memcpy(df, nsDF->GetPointer(0), sizeof(float) * sizeDF); + emd->SetNodeSetDistributionFactors(df); + } + nsDF->Delete(); + } + else + { + delete [] numDF; + nsNodeIds->Delete(); + nsDF->Delete(); + } + + return 0; +} +int vtkExodusModel::SetLocalSideSetInformation( + int fid, int use_floats, int *cellIds, int ncells) +{ + // TODO - go over this and check it + + int i, j, k; + float dummyFloat; + char dummyChar; + + vtkModelMetadata *emd = this->GetModelMetadata(); + + // external cell IDs in file + + int numCellsInFile = 0; + ex_inquire(fid, EX_INQ_ELEM, &numCellsInFile, &dummyFloat, &dummyChar); + int *cellMap = new int [numCellsInFile]; + + ex_get_elem_num_map(fid, cellMap); + + // external cell IDs in vtkUnstructuredGrid + + vtkstd::map localCellIdMap; + vtkstd::map::iterator it; + + for (i=0; i::value_type(cellIds[i], i)); + } + + int nss = emd->GetNumberOfSideSets(); + int *numDF = new int [nss]; + + int *sssize = new int [nss]; + memset(sssize, 0, sizeof(int) * nss); + + vtkIntArray *ssCellIds = vtkIntArray::New(); + ssCellIds->SetNumberOfComponents(1); + + vtkIntArray *ssSideIds = vtkIntArray::New(); + ssSideIds->SetNumberOfComponents(1); + + vtkIntArray *ssDFPerSide = vtkIntArray::New(); + ssDFPerSide->SetNumberOfComponents(1); + + vtkFloatArray *ssDF = vtkFloatArray::New(); + ssDF->SetNumberOfComponents(1); + + int total = 0; + + int *sideSetIds = emd->GetSideSetIds(); + + for (i=0; iInsertNextValue(gid); + + ssSideIds->InsertNextValue(sides[j]); + + sssize[i]++; + total++; + } + + delete [] sides; + + if (sssize[i] > 0) + { + if (numDF[i] > 0) + { + int *nodeCount = new int [nsides]; + int *nodeList = new int [numDF[i]]; + + ex_get_side_set_node_list(fid, sideSetIds[i], nodeCount, nodeList); + + delete [] nodeList; + + float *dfF = NULL; + double *dfD = NULL; + int nextdf = 0; + + dfF = new float [numDF[i]]; + + if (use_floats) + { + ex_get_side_set_dist_fact(fid, sideSetIds[i], dfF); + } + else + { + dfD = new double [numDF[i]]; + ex_get_side_set_dist_fact(fid, sideSetIds[i], dfD); + this->CopyDoubleToFloat(dfF, dfD, numDF[i]); + delete [] dfD; + } + + for (j=0; j= 0) + { + ssDFPerSide->InsertNextValue(nodeCount[j]); + + for (k=0; k < nodeCount[j]; k++) + { + ssDF->InsertNextValue(dfF[nextdf++]); + } + } + else + { + nextdf += nodeCount[j]; + } + } + } + else + { + for (j=0; jInsertNextValue(0); + } + } + } + + delete [] elts; + } + + delete [] cellMap; + + localCellIdMap.erase(localCellIdMap.begin(), localCellIdMap.end()); + + emd->SetSideSetSize(sssize); + + if (total == 0) + { + delete [] numDF; + delete [] sssize; + ssCellIds->Delete(); + ssSideIds->Delete(); + ssDFPerSide->Delete(); + ssDF->Delete(); + return 0; + } + + int n = ssCellIds->GetNumberOfTuples(); + + int *buf = new int [n]; + memcpy(buf, ssCellIds->GetPointer(0), sizeof(int) * n); + ssCellIds->Delete(); + + emd->SetSideSetElementList(buf); + + buf = new int [n]; + memcpy(buf, ssSideIds->GetPointer(0), sizeof(int) * n); + ssSideIds->Delete(); + + emd->SetSideSetSideList(buf); + + buf = new int [n]; + memcpy(buf, ssDFPerSide->GetPointer(0), sizeof(int) * n); + ssDFPerSide->Delete(); + + emd->SetSideSetNumDFPerSide(buf); + + int *nssdf = new int [nss]; + + int *ndf = emd->GetSideSetNumDFPerSide(); + + int totaldf = 0; + + for (i=0; i 0) && (sssize[i] > 0)) + { + nssdf[i] = 0; + + for (j=0; jSetSideSetNumberOfDistributionFactors(nssdf); + + if (totaldf > 0) + { + float *df = new float [totaldf]; + memcpy(df, ssDF->GetPointer(0), sizeof(float) * totaldf); + emd->SetSideSetDistributionFactors(df); + } + + ssDF->Delete(); + + return 0; +} +//------------------------------------------------- +// Merge an ExodusModel into this one +//------------------------------------------------- +int vtkExodusModel::MergeExodusModel(vtkExodusModel *em) +{ + vtkModelMetadata *myMmd = this->GetModelMetadata(); + + vtkModelMetadata *newmd = em->GetModelMetadata(); + + int fail = myMmd->MergeModelMetadata(newmd); + + return (fail != 0); +} +vtkExodusModel *vtkExodusModel::ExtractExodusModel(vtkIntArray *globalCellIdList, + vtkUnstructuredGrid *grid, const char *globalCellIdArrayName, + const char *globalNodeIdArrayName) +{ + vtkExodusModel *em = vtkExodusModel::New(); + + vtkModelMetadata *mmd = this->GetModelMetadata()->ExtractModelMetadata( + globalCellIdList, grid, globalCellIdArrayName, globalNodeIdArrayName); + + if (mmd == NULL) + { + em->Delete(); + em = NULL; + } + else + { + em->SetModelMetadata(mmd); + } + + return em; +} +//------------------------------------------------- +// Element variables +//------------------------------------------------- +int vtkExodusModel::AddUGridElementVariable(char *ugridVarName, + char *origName, int numComponents) +{ + vtkModelMetadata *emd = this->GetModelMetadata(); + + int rc = emd->AddUGridElementVariable(ugridVarName, + origName, numComponents); + + return rc; +} +int vtkExodusModel::RemoveUGridElementVariable(char *ugridVarName) +{ + vtkModelMetadata *emd = this->GetModelMetadata(); + + int rc = emd->RemoveUGridElementVariable(ugridVarName); + + return rc; +} +void vtkExodusModel::SetElementVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map) +{ + vtkModelMetadata *emd = this->GetModelMetadata(); + + emd->SetElementVariableInfo(numOrigNames, origNames, + numNames, names, numComp, map); +} +//------------------------------------------------- +// Node variables +//------------------------------------------------- +int vtkExodusModel::AddUGridNodeVariable(char *ugridVarName, + char *origName, int numComponents) +{ + vtkModelMetadata *emd = this->GetModelMetadata(); + + int rc = emd->AddUGridNodeVariable(ugridVarName, + origName, numComponents); + + return rc; +} +int vtkExodusModel::RemoveUGridNodeVariable(char *ugridVarName) +{ + vtkModelMetadata *emd = this->GetModelMetadata(); + + int rc = emd->RemoveUGridNodeVariable(ugridVarName); + + return rc; +} +void vtkExodusModel::SetNodeVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map) +{ + vtkModelMetadata *emd = this->GetModelMetadata(); + + emd->SetNodeVariableInfo(numOrigNames, origNames, + numNames, names, numComp, map); +} +void vtkExodusModel::RemoveBeginningAndTrailingSpaces(char **names, int len) +{ + int i, j; + + for (i=0; iSuperclass::PrintSelf(os,indent); + + os << indent << "ModelMetadata: " << this->ModelMetadata << endl; + os << indent << "GeometryCount: " << this->GeometryCount << endl; +} diff --git a/Hybrid/vtkExodusModel.h b/Hybrid/vtkExodusModel.h new file mode 100644 index 0000000..5a796d4 --- /dev/null +++ b/Hybrid/vtkExodusModel.h @@ -0,0 +1,216 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExodusModel.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkExodusModel +// +// .SECTION Description +// +// A vtkUnstructuredGrid output by vtkExodusReader or vtkPExodusReader +// is missing a great deal of initialization and static model data +// that is in an Exodus II file. (Global variables, properties, +// node sets, side sets, and so on.) This data can be stored in a +// vtkModelMetadata object, which can be initialized using +// this vtkExodusModel class. +// +// This class can be initialized with a file handle for an open Exodus +// file, and the vtkUnstructuredGrid derived from that file. The methods +// used would be SetGlobalInformation, SetLocalInformation, +// AddUGridElementVariable and AddUGridNodeVariable. The vtkExodusReader +// does this. +// +// It can also be initialized (using UnpackExodusModel) from a +// vtkUnstructuredGrid that has had metadata packed into it's field +// arrays with PackExodusModel. The vtkExodusIIWriter does this. +// +// If you plan to write out the Exodus file (with vtkExodusIIWriter), +// you should direct the Exodus reader to create a vtkExodusModel object. +// This will be used by the Exodus writer to create a correct Exodus II +// file on output. In addition, the vtkDistributedDataFilter is +// cognizant of the ExodusModel object and will unpack, extract, merge, +// and pack these objects associated with the grids it is partitioning. +// +// .SECTION See also +// vtkExodusReader vtkPExodusReader vtkExodusIIWriter vtkModelMetadata +// vtkDistributedDataFilter + +#ifndef __vtkExodusModel_h +#define __vtkExodusModel_h + +#include "vtkObject.h" + +#include "vtkModelMetadata.h" // So those who include vtkExodusModel don't + // need to know anything about ModelMetadata + +class vtkUnstructuredGrid; + +class VTK_HYBRID_EXPORT vtkExodusModel : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkExodusModel, vtkObject); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + static vtkExodusModel *New(); + + // Description: + // In order to write a correct Exodus file from a + // vtkUnstructuredGrid, we need to know the global data + // which does not get represented in the UGrid. + // Initialize, with an open Exodus file, all the global + // fields of the ExodusModel object. fid is the file handle + // of the opened Exodus file. compute_word_size is the + // size of floating point values exchanged with the + // the Exodus library. (It's set in ex_open or ex_create.) + // The global fields are those which don't depend on + // which cells or field arrays are being read from the + // file. + + int SetGlobalInformation(int fid, int compute_word_size); + + // Description: + // In order to write Exodus files from vtkUnstructuredGrid + // objects that were read from Exodus files, we need to know + // the mapping from variable names in the UGrid to variable + // names in the Exodus file. (The Exodus reader combines + // scalar variables with similar names into vectors in the + // UGrid.) When building the UGrid to which this + // ExodusModel refers, add each element and node variable + // name with this call, including the name of original variable + // that yielded it's first component, and the number of components. + // If a variable is removed from the UGrid, remove it from + // the ExodusModel. (If this information is missing or + // incomplete, the ExodusIIWriter can still do something + // sensible in creating names for variables.) + + int AddUGridElementVariable(char *ugridVarName, char *origName, int numComponents); + int RemoveUGridElementVariable(char *ugridVarName); + + int AddUGridNodeVariable(char *ugridVarName, char *origName, int numComponents); + int RemoveUGridNodeVariable(char *ugridVarName); + + void SetElementVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map); + void SetNodeVariableInfo(int numOrigNames, char **origNames, + int numNames, char **names, int *numComp, int *map); + + // Description: + // Set the local information in the ExodusModel. This is + // information which depends on which blocks were read in, + // and which time step was read in. + // (Example - count of cells in each block, values of global + // variables, node IDs for nodes in each node set.) + // Provide the ugrid, the time step (the first time step is 0), + // the handle of an open Exodus file, and the + // size of floating point values exchanged with the Exodus library. + // Also indicate with a 1 if the geometry has changed (new blocks + // or blocks removed) since the last call. (When in doubt set to 1.) + // Please call SetGlobalInformation once before calling + // SetLocalInformation. SetLocalInformation may be called many + // times if different subsets of an Exodus file are read. Each + // call replaces the previous local values. + + int SetLocalInformation(vtkUnstructuredGrid *ugrid, + int fid, int timeStep, int newGeometry, int compute_word_size); + + // Description: + // Static function that returns 1 if the vtkUnstructuredGrid + // has metadata packed into it's field arrays, 0 otherwise. + + static int HasMetadata(vtkUnstructuredGrid *grid); + + // Description: + // Set or get the underlying vtkModelMetadata object. + + vtkModelMetadata *GetModelMetadata(); + void SetModelMetadata(vtkModelMetadata *emData); + + // Description: + // One way to initialize an ExodusModel object is to use + // SetGlobalInformation, SetLocalInformation, and the Add/Remove + // Variable calls to initialize it from an open Exodus file. + // + // Another way is to initialize it with the ExodusModel which + // has been packed into field arrays of a vtkUnstructuredGrid. + // Set the second argument to 1 if you would like the packed + // field arrays to be deleted after this ExodusModel is + // initialized. + // Returns 1 if there is no ExodusModel object associated with + // the grid, 0 otherwise. + + int UnpackExodusModel(vtkUnstructuredGrid *grid, int deleteIt); + + // Description: + // Merge the supplied vtkExodusModel object into this one. It is + // assumed the two objects represent portions of the same distributed + // data set. (So the list of block IDs is the same, and so on.) + + int MergeExodusModel(vtkExodusModel *em); + + // Description: + // Create a new vtkExodusModel object representing a subset of the + // cells of this vtkExodusModel object. We need a list of the + // global IDs of the cells to be extracted, the grid which + // generated the Exodus Model (so we can find the points associated + // with each cell), and the name of the grid's global cell ID array, + // and the name of the grid's global node ID array. + + vtkExodusModel *ExtractExodusModel(vtkIntArray *globalCellIdList, + vtkUnstructuredGrid *grid, const char *globalCellIdArrayName, + const char *globalNodeIdArrayName); + + // Description: + // The metadata encapsulated in a vtkExodusModel object can be + // written to field arrays which are then stored in the + // vtkUnstructuredGrid itself. PackExodusModel creates these + // field arrays and attaches them to the supplied grid. + + void PackExodusModel(vtkUnstructuredGrid *grid); + + // Description:: + // Reset all fields to their initial value. + + void Reset(); + +protected: + + vtkExodusModel(); + ~vtkExodusModel(); + +private: + + vtkModelMetadata *CheckSetModelMetadata(); + + static void CopyDoubleToFloat(float *f, double *d, int len); + + int SetLocalBlockInformation( + int fid, int use_floats, int *blockIds , int *cellIds, int ncells); + int SetLocalNodeSetInformation( + int fid, int use_floats, int *pointIds, int npoints); + int SetLocalSideSetInformation( + int fid, int use_floats, int *cellIds, int ncells); + + void RemoveBeginningAndTrailingSpaces(char **names, int len); + + vtkModelMetadata *ModelMetadata; + + int GeometryCount; + + vtkExodusModel(const vtkExodusModel&); // Not implemented + void operator=(const vtkExodusModel&); // Not implemented +}; +#endif diff --git a/Hybrid/vtkExodusReader.cxx b/Hybrid/vtkExodusReader.cxx new file mode 100644 index 0000000..dde509d --- /dev/null +++ b/Hybrid/vtkExodusReader.cxx @@ -0,0 +1,5002 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExodusReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkExodusReader.h" +#include "vtkExodusModel.h" +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationDoubleVectorKey.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLParser.h" +#include "vtkWarpVector.h" +#include "vtkDSPFilterDefinition.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "vtkStdString.h" + +#define DEBUG 0 + +// vtkExodusMetadata is an internal helper class that +// manages the metadata associated with the point and cell +// arrays. This class uses stl +class vtkExodusMetadata +{ +private: + int ArrayStatusInitValue[vtkExodusReader::NUM_ARRAY_TYPES]; + + // Field array stuff + vtkstd::vector pointArrayNames; + vtkstd::vector pointArrayComponents; + vtkstd::vector pointArrayStatus; + + vtkstd::vector cellArrayNames; + vtkstd::vector cellArrayComponents; + vtkstd::vector cellArrayStatus; + + int originalNumberOfPointArrays; + int originalNumberOfCellArrays; + + // This is a cruddy hack... because we need to pass a + // char ** pointer to the exodus function + char **pointArrayRawBuffer; + char **cellArrayRawBuffer; + + // Block stuff + vtkstd::vector blockNames; + vtkstd::vector blockIds; + vtkstd::vector blockStatus; + vtkstd::vector numElementsInBlock; + + // Node/Side set id stuff + // Store *Ids* for each node/side set + // Store *Size* for each node/side set + // Store number of *Distribution Factors** for each node/side set + // FIXME!!! since node/side set ids should be unique, should this + // be a 'set' instead of a 'vector'? + // FIXME!!! should we store side/edge type along with side set info? + vtkstd::vector nodeSetId; + vtkstd::vector nodeSetSize; + vtkstd::vector nodeSetDistFact; + vtkstd::vector nodeSetStatus; + vtkstd::vector nodeSetName; + + vtkstd::vector sideSetId; + vtkstd::vector sideSetSize; + vtkstd::vector sideSetDistFact; + vtkstd::vector sideSetStatus; + vtkstd::vector sideSetName; + + //part stuff. There is no PartStatus array + //a part is active only if all its blocks are active + vtkstd::vector partNames; + vtkstd::map blockIDToPartID; + vtkstd::map > partIDToBlockIDs; + + //material stuff. Again, no material array + //a material is active only is all its blocks are active + vtkstd::vector materialNames; + vtkstd::map blockIDToMaterialID; + vtkstd::map > materialIDToBlockIDs; + + //assembly stuff + vtkstd::vector assemblyNames; + vtkstd::map > blockIDToAssemblyIDs; + vtkstd::map > assemblyIDToBlockIDs; + + + //sortedorder[sortedID]=unsortedID + //can do name[sortedOrder[idx]] + vtkstd::map sortedOrder; + + int DisplayType; + +public: + + // Constructor + vtkExodusMetadata() + { + pointArrayRawBuffer = NULL; + cellArrayRawBuffer = NULL; + originalNumberOfPointArrays = 0; + originalNumberOfCellArrays = 0; + DisplayType=1; + for ( int i=0;iArrayStatusInitValue[i] = 0; + } + } + + // Destructor + ~vtkExodusMetadata() + { + int i; + for (i=0; i< this->originalNumberOfPointArrays; i++) + { + delete [] this->pointArrayRawBuffer[i]; + } + if (this->pointArrayRawBuffer) + { + delete [] this->pointArrayRawBuffer; + } + for (i=0; i< this->originalNumberOfCellArrays; i++) + { + delete [] this->cellArrayRawBuffer[i]; + } + if (this->cellArrayRawBuffer) + { + delete [] this->cellArrayRawBuffer; + } + } + + // Point array attributes + char** AllocatePointArrayNameBuffer(int num_strings); + char** GetPointArrayNameBuffer(); + char *GetPointArrayOriginalName(int i) + { + return pointArrayRawBuffer[i]; + } + inline int GetNumberOfPointArrays() + { + return pointArrayNames.size(); + } + inline const char* GetPointArrayName(int idx) + { + return pointArrayNames[idx].c_str(); + } + inline int GetPointArrayComponents(int idx) + { + return pointArrayComponents[idx]; + } + inline int GetPointArrayStatus(int idx) + { + return pointArrayStatus[idx]; + } + inline void SetPointArrayStatus(int idx, int on) + { + pointArrayStatus[idx] = on; + } + inline void SetPointArrayStatus(vtkStdString name, int flag) + { + for(int idx=0; idxGetNumberOfPointArrays(); ++idx) + { + if ( name == this->pointArrayNames[idx] ) + { + this->pointArrayStatus[idx] = flag; + return; + } + } + } + inline int GetPointArrayStatus(vtkStdString name) + { + for(int idx=0; idxGetNumberOfPointArrays(); ++idx) + { + if ( name == this->pointArrayNames[idx] ) + return this->pointArrayStatus[idx]; + } + return -1; + } + + // Cell array attributes + char** AllocateCellArrayNameBuffer(int num_strings); + char** GetCellArrayNameBuffer(); + char *GetCellArrayOriginalName(int i) + { + return cellArrayRawBuffer[i]; + } + inline int GetNumberOfCellArrays() + { + return cellArrayNames.size(); + } + inline const char* GetCellArrayName(int idx) + { + return cellArrayNames[idx].c_str(); + } + inline int GetCellArrayComponents(int idx) + { + return cellArrayComponents[idx]; + } + inline void SetCellArrayStatus(int idx, int flag) + { + cellArrayStatus[idx] = flag; + } + inline void SetCellArrayStatus(vtkStdString name, int flag) + { + for(int idx=0; idxGetNumberOfCellArrays(); ++idx) + { + if ( name == this->cellArrayNames[idx] ) + { + this->cellArrayStatus[idx] = flag; + return; + } + } + } + inline int GetCellArrayStatus(int idx) + { + return cellArrayStatus[idx]; + } + inline int GetCellArrayStatus(vtkStdString name) { + for(int idx=0; idxGetNumberOfCellArrays(); ++idx) + { + if ( name == this->cellArrayNames[idx] ) + return this->cellArrayStatus[idx]; + } + return -1; + } + + // These are used when accessing things like truth tables indices + inline int GetOriginalNumberOfPointArrays() + { + return originalNumberOfPointArrays; + } + inline int GetOriginalNumberOfCellArrays() + { + return originalNumberOfCellArrays; + } + +//----------------------------------------------------------------------- + // Node/Side set functions + //----------------------------------------------------------------------- + // id - node/side set exodus id + // size - node/side set size + // dist - number of distribution factors + // default node/side set status to 'of' or '0' + inline void AddNodeSet( const int id, const int size, const int dist ) + { + char buffer[80]; + sprintf(buffer, "NodeSet %d",id); + + this->nodeSetId.push_back( id ); + this->nodeSetName.push_back( buffer ); + this->nodeSetSize.push_back( size ); + this->nodeSetDistFact.push_back( dist ); + this->nodeSetStatus.push_back( 0 ); + } + inline void AddSideSet( const int id, const int size, const int dist ) + { + char buffer[80]; + sprintf(buffer, "SideSet %d",id); + + this->sideSetId.push_back( id ); + this->sideSetName.push_back( buffer ); + this->sideSetSize.push_back( size ); + this->sideSetDistFact.push_back( dist ); + this->sideSetStatus.push_back( 0 ); + } + + // Do a bound check and return a non-sensical -1 for a count if the user + // asks for a non-existent id. The return value is not an error value + // per se, but we have to return something instead of overrunning the + // array bounds + // + // FIXME!!! this is simply the number of node/side sets set by + // vtkExodusReader, it *could* be different than the number + // reported by the exodus file. since vtkExodusReader loads + // metadata for all node/side sets this *should* agree with + // the number reported by exodus. Status flags specify which + // node/side sets get loaded and visualized. + inline int GetNumberOfNodeSets() { return this->nodeSetId.size(); } + inline int GetNumberOfSideSets() { return this->sideSetId.size(); } + + inline int GetNodeSetId( const int id ) + { + return (id>=0 && id<(int)nodeSetId.size()) ? nodeSetId[id] : -1; + } + inline int GetSideSetId( const int id ) + { + return (id>=0 && id<(int)sideSetId.size()) ? sideSetId[id] : -1; + } + inline const char* GetNodeSetName( const int id ) + { + return nodeSetName[id].c_str(); + } + inline const char* GetSideSetName( const int id ) + { + return sideSetName[id].c_str(); + } + + inline int GetNodeSetSize( const int id ) + { + return (id>=0 && id<(int)nodeSetSize.size()) ? nodeSetSize[id] : -1; + } + inline int GetSideSetSize( const int id ) + { + return (id>=0 && id<(int)sideSetSize.size()) ? sideSetSize[id] : -1; + } + + inline int GetNodeSetDistFact( const int id ) + { + return (id>=0 && id<(int)nodeSetDistFact.size()) ? nodeSetDistFact[id] : -1; + } + inline int GetSideSetDistFact( const int id ) + { + return (id>=0 && id<(int)sideSetDistFact.size()) ? sideSetDistFact[id] : -1; + } + + inline void SetNodeSetStatus( const int id, const int status ) + { + if( id>=0 && id<(int)this->nodeSetStatus.size() ) + { + this->nodeSetStatus[id] = status; + } + return; + } + inline void SetNodeSetStatus(vtkStdString name, int status) + { + for(vtkstd::vector::size_type id=0; id < this->nodeSetStatus.size(); ++id) + { + if ( name == this->nodeSetName[id] ) + { + this->SetNodeSetStatus(id,status); + return; + } + } + } + inline void SetSideSetStatus( const int id, const int status ) + { + if( id>=0 && id<(int)this->sideSetStatus.size() ) + { + this->sideSetStatus[id] = status; + } + return; + } + inline void SetSideSetStatus(vtkStdString name, int status) + { + for(vtkstd::vector::size_type id=0; id < this->sideSetStatus.size(); ++id) + { + if ( name == this->sideSetName[id] ) + { + this->SetSideSetStatus(id,status); + return; + } + } + } + + // Return node/side set status if the id corresponds to a real node/side set. + // I the user asks for the status of a node/side set that doesn't exist, return + // zero and let the philosophers debate whether a node/side set that doesn't exist + // is on or off; that's at least 3 Phd thesies right there! + inline int GetNodeSetStatus(const int id ) + { + return (id>=0 && id<(int)nodeSetStatus.size()) ? nodeSetStatus[id] : 0; + } + inline int GetNodeSetStatus(vtkStdString name) + { + for(vtkstd::vector::size_type id=0; id < this->nodeSetStatus.size(); ++id) + { + if ( name == this->nodeSetName[id] ) + { + return this->GetNodeSetStatus(id); + } + } + return 0; + } + + inline int GetSideSetStatus( const int id ) + { + return (id>=0 && id<(int)sideSetStatus.size()) ? sideSetStatus[id] : 0; + } + inline int GetSideSetStatus(vtkStdString name) + { + for(vtkstd::vector::size_type id=0; id < this->sideSetStatus.size(); ++id) + { + if ( name == this->sideSetName[id] ) + { + return this->GetSideSetStatus(id); + } + } + return 0; + } + //----------------------------------------------------------------------- + // End Node/Side set functions + //----------------------------------------------------------------------- + + + // Block attributes + inline void AddBlock(vtkStdString blockName, vtkStdString partName, + vtkStdString materialName, + vtkstd::vector localAssemblyNames, + int id, int num_elem, int status) + { + blockNames.push_back(blockName); + //cout << "added block " << blockName << " " << blockNames.size() << endl; + blockIds.push_back(id); + blockStatus.push_back(status); + numElementsInBlock.push_back(num_elem); + unsigned int i; + int found=0; + int blockID=blockNames.size()-1; + sortedOrder[blockID]=blockID; + //set up the Part Arrays + for (i=0;i(); + partIDToBlockIDs[partID].push_back(blockID); + } + + //set up the material arrays + found=0; + for (i=0;i(); + materialIDToBlockIDs[materialID].push_back(blockID); + } + + //handle assembly stuff + for (i=0;i(); + blockIDToAssemblyIDs[blockID].push_back(assemblyID); + assemblyIDToBlockIDs[assemblyID]=vtkstd::vector(); + assemblyIDToBlockIDs[assemblyID].push_back(blockID); + //cout << "n added block " << blockID << " to assembly " << assemblyName << endl; + } + } + + } + + inline void ResetBlocks() + { + blockNames.erase(blockNames.begin(), blockNames.end()); + blockIds.erase(blockIds.begin(), blockIds.end()); + blockStatus.erase(blockStatus.begin(), blockStatus.end()); + numElementsInBlock.erase(numElementsInBlock.begin(), numElementsInBlock.end()); + partNames.erase(partNames.begin(),partNames.end()); + materialNames.erase(materialNames.begin(),materialNames.end()); + unsigned int i; + for (i=0;iGetNumberOfBlocks(); ++idx) + { + if ( name == this->blockNames[idx] ) + { + this->blockStatus[idx] = flag; + //this->SetBlockStatus(idx,flag); + return; + } + } + } + inline void SetUnsortedBlockStatus(int idx, int flag) + { + blockStatus[idx] = flag; + } + + inline int GetUnsortedBlockStatus(int idx) + { + return blockStatus[idx]; + } + inline int GetBlockStatus(int idx) + { + return blockStatus[sortedOrder[idx]]; + } + inline int GetBlockStatus(vtkStdString name) + { + for(int idx=0; idxGetNumberOfBlocks(); ++idx) + { + if ( name == this->blockNames[idx] ) + return this->blockStatus[idx]; + } + return -1; + } + + + + + //Parts and Materials need to act directly on the + //blockStatus array. Otherwise the index is put through + //the sortedOrder array, which gives us garbage since we have a + //valid index already + inline int GetNumberOfParts() + { + return partNames.size(); + } + inline const char* GetPartName(int idx) + { + return partNames[idx].c_str(); + } + inline const char* GetPartBlockInfo(int idx) + { + static vtkStdString blocks; + blocks.erase(); + char buffer[80]; + for (unsigned int i=0;iSetBlockStatus(partIDToBlockIDs[idx][i],on); + this->blockStatus[partIDToBlockIDs[idx][i]]=on; + } + } + + inline void SetPartStatus(vtkStdString name, int flag) + { + for(int idx=0; idxGetNumberOfParts(); ++idx) + { + if ( name == this->partNames[idx] ) + { + this->SetPartStatus(idx,flag); + return; + } + } + } + + inline int GetNumberOfMaterials() + { + return materialNames.size(); + } + + inline const char* GetMaterialName(int idx) + { + return materialNames[idx].c_str(); + } + + inline int GetMaterialStatus(int idx) + { + for (unsigned int i=0;iSetBlockStatus(materialIDToBlockIDs[idx][i],on); + this->blockStatus[materialIDToBlockIDs[idx][i]]=on; + } + } + + inline void SetMaterialStatus(vtkStdString name, int flag) + { + for(int idx=0; idxGetNumberOfMaterials(); ++idx) + { + if ( name == this->materialNames[idx] ) + { + this->SetMaterialStatus(idx,flag); + return; + } + } + } + + //Assembly stuff + inline int GetNumberOfAssemblies() + { + return assemblyNames.size(); + } + + inline const char* GetAssemblyName(int idx) + { + return assemblyNames[idx].c_str(); + } + + inline int GetAssemblyStatus(int idx) + { + for (unsigned int i=0;iSetBlockStatus(materialIDToBlockIDs[idx][i],on); + this->blockStatus[assemblyIDToBlockIDs[idx][i]]=on; + } + } + + inline void SetAssemblyStatus(vtkStdString name, int flag) + { + for(int idx=0; idxGetNumberOfAssemblies(); ++idx) + { + if ( name == this->assemblyNames[idx] ) + { + this->SetAssemblyStatus(idx,flag); + return; + } + } + } + + //performs a mapping from the exodus block ID to the block ID used by + //Set/GetUnsortedBlockStatus + inline int GetBlockIndex(int exodusID) + { + for (vtkstd::vector::size_type i=0;i *newNames, vtkstd::vector *newSize); +//ETX + + void SortBlocks() + { + int i; + for (i=blockIds.size()-1;i>=0;i--) + { + for (int j=1;j<=i;j++) + { + if (blockIds[sortedOrder[j-1]]>blockIds[sortedOrder[j]]) + { + int t=sortedOrder[j-1]; + sortedOrder[j-1]=sortedOrder[j]; + sortedOrder[j]=t; + } + } + } + } + + void SetArrayStatusInitValue( vtkExodusReader::ArrayType type, int value ) + { + this->ArrayStatusInitValue[type] = value; + } + + int GetArrayStatusInitValue( vtkExodusReader::ArrayType type ) + { + return this->ArrayStatusInitValue[type]; + } + +}; + + +class vtkExodusXMLParser: public vtkXMLParser +{ +private: + vtkstd::map MaterialSpecifications; + vtkstd::map MaterialDescriptions; + vtkstd::map PartDescriptions; + vtkstd::vector MaterialNames; + vtkstd::vector BlockNames; + char* Filename; + vtkStdString PartNumber; + vtkStdString InstanceNumber; + vtkstd::map BlockIDToPartNumber; + vtkstd::map > PartNumberToAssemblyNumbers; + vtkstd::map > PartNumberToAssemblyDescriptions; + vtkstd::map AssemblyDescriptions; + vtkstd::vector CurrentAssemblyNumbers; + vtkstd::vector CurrentAssemblyDescriptions; + + //hierarchical list mappings + vtkstd::list apbList; + vtkstd::map > apbToBlocks; + vtkstd::map apbIndents; +public: + + vtkExodusXMLParser(char* filename) + { + this->SetFileName(filename); + this->Parse(); + this->PartNumber=""; + this->InstanceNumber=""; + } + + virtual ~vtkExodusXMLParser() {} + + virtual vtkStdString GetPartNumber(int block) + { + return this->BlockIDToPartNumber[block]; + } + virtual vtkStdString GetPartDescription(int block) + { + return this->PartDescriptions[this->BlockIDToPartNumber[block]]; + } + virtual vtkStdString GetMaterialDescription(int block) + { + return this->MaterialDescriptions[this->BlockIDToPartNumber[block]]; + } + virtual vtkStdString GetMaterialSpecification(int block) + { + return this->MaterialSpecifications[this->BlockIDToPartNumber[block]]; + } + virtual vtkstd::vector GetAssemblyNumbers(int block) + { + return this->PartNumberToAssemblyNumbers[this->BlockIDToPartNumber[block]]; + } + virtual vtkstd::vector GetAssemblyDescriptions(int block) + { + return this->PartNumberToAssemblyDescriptions[this->BlockIDToPartNumber[block]]; + } + + virtual int GetNumberOfHierarchyEntries() + { + return this->apbList.size(); + } + + virtual vtkStdString GetHierarchyEntry(int num) + { + //since it's an STL list, we need to get the correct entry + vtkstd::list::iterator iter=this->apbList.begin(); + for(int i=0;i GetBlocksForEntry(int num) + { + return this->apbToBlocks[this->GetHierarchyEntry(num)]; + } + + virtual vtkstd::vector GetBlocksForEntry(vtkStdString entry) + { + return this->apbToBlocks[entry]; + } + +protected: + virtual void StartElement(const char* tname, const char** attrs) + { + const char* name=strrchr(tname,':'); + if (!name) + { + name=tname; + } + else + { + name++; + } + + if (strcmp(name,"assembly")==0) + { + const char* assemblyNumber=this->GetValue("number",attrs); + if (assemblyNumber) + { + this->CurrentAssemblyNumbers.push_back(vtkStdString(assemblyNumber)); + } + + const char* assemblyDescription=this->GetValue("description",attrs); + if (assemblyDescription) + { + this->CurrentAssemblyDescriptions.push_back(vtkStdString(assemblyDescription)); + } + + //make the entry for the hierarchical list + vtkStdString result=vtkStdString(""); + for (vtkstd::vector::size_type i=0; + iCurrentAssemblyNumbers.size()-1; + i++) + { + result+=vtkStdString(" "); + } + + result+=vtkStdString("Assembly: ")+ + assemblyDescription+vtkStdString(" (")+ + assemblyNumber+vtkStdString(")"); + apbList.push_back(result); + //record the indent level, used when we add blocks + apbIndents[result]=this->CurrentAssemblyNumbers.size()-1; + //make the blocks array + apbToBlocks[result]=vtkstd::vector(); + } + if (strcmp(name,"part")==0) + { + const char* instance=this->GetValue("instance",attrs); + vtkStdString instanceString=vtkStdString(""); + if (instance) + { + instanceString=vtkStdString(instance); + } + + const char* partString=this->GetValue("number",attrs); + if (partString) + { + this->PartNumber=vtkStdString(partString)+ + vtkStdString(" Instance: ")+ + instanceString; + } + + const char* partDescString=this->GetValue("description",attrs); + if (partDescString && this->PartNumber!="") + { + this->PartDescriptions[this->PartNumber]= + partDescString; + } + + //copy the current assemblies to the assemblies list for this part. + this->PartNumberToAssemblyNumbers[this->PartNumber]= + vtkstd::vector(this->CurrentAssemblyNumbers); + this->PartNumberToAssemblyDescriptions[this->PartNumber]= + vtkstd::vector(this->CurrentAssemblyDescriptions); + + //make the hierarchical display entry + vtkStdString result=vtkStdString(""); + for (vtkstd::vector::size_type i=0; + iCurrentAssemblyNumbers.size(); + i++) + { + result+=vtkStdString(" "); + } + result+=vtkStdString("Part: ")+ + partDescString+vtkStdString(" (")+ + partString+vtkStdString(")")+vtkStdString(" Instance: ")+ + instanceString; + apbList.push_back(result); + //record the indent level + apbIndents[result]=this->CurrentAssemblyNumbers.size(); + apbToBlocks[result]=vtkstd::vector(); + } + else if (strcmp(name,"material-specification")==0) + { + if (this->PartNumber!="") + { + const char * materialDescriptionString= + GetValue("description",attrs); + if (materialDescriptionString) + { + this->MaterialDescriptions[this->PartNumber]= + vtkStdString(materialDescriptionString); + } + + const char * materialSpecificationString= + GetValue("specification",attrs); + if (materialSpecificationString) + { + this->MaterialSpecifications[this->PartNumber]= + vtkStdString(materialSpecificationString); + } + } + } + else if (strcmp(name,"blocks")==0 || strcmp(name,"dart:blocks")==0) + { + const char* instance=this->GetValue("part-instance",attrs); + vtkStdString instanceString=vtkStdString(""); + if (instance) + { + this->InstanceNumber=vtkStdString(instance); + } + const char* partString=this->GetValue("part-number",attrs); + if (partString) + { + this->PartNumber=vtkStdString(partString); + } + } + else if (strcmp(name,"block")==0 || strcmp(name,"dart:block")==0) + { + + if (this->PartNumber!="") + { + const char* blockString=this->GetValue("id",attrs); + if (blockString) + { + int id=atoi(blockString); + this->BlockIDToPartNumber[id]=this->PartNumber+ + vtkStdString(" Instance: ")+this->InstanceNumber; + + //first insert block entry into apblist + vtkStdString apbIndexString=this->PartNumber+ + vtkStdString(") Instance: ")+this->InstanceNumber; + vtkStdString partEntry=findEntry(this->apbList,apbIndexString); + vtkStdString blockEntry; + if (partEntry!=vtkStdString("")) + { + //insert into apbList + vtkstd::list::iterator pos= + vtkstd::find(this->apbList.begin(),this->apbList.end(),partEntry); + pos++; + + vtkStdString result=vtkStdString(""); + for (int i=0;iapbList.insert(pos,result); + apbToBlocks[result]=vtkstd::vector(); + } + + //update mapping + //we know block number, so can get part number to update that. + //using part number, we can update assembly mappings + vtkStdString partIndexString=this->PartNumber+ + vtkStdString(" Instance: ")+this->InstanceNumber; + //we know the part entry + //add block ID to block entry + apbToBlocks[blockEntry].push_back(id); + //add block ID to part + apbToBlocks[partEntry].push_back(id); + + //get the assemblies + vtkstd::vector assemblies= + this->PartNumberToAssemblyNumbers[partIndexString]; + //add block ID to assemblies + for (vtkstd::vector::size_type j=0;japbList,assemblies[j]); + apbToBlocks[assemblyEntry].push_back(id); + } + } + } + } + } + + //returns the first string that contains sstring + virtual vtkStdString findEntry(vtkstd::list slist, + vtkStdString sstring){ + for (vtkstd::list::iterator i=slist.begin(); + i!=slist.end(); + i++) + { + if ((*i).find(sstring)!=vtkStdString::npos) + { + return (*i); + } + } + return vtkStdString(""); + } + + virtual void EndElement(const char* tname) + { + const char* name=strrchr(tname,':'); + if (!name) + { + name=tname; + } + else + { + name++; + } + + if (strcmp(name,"assembly")==0) + { + this->CurrentAssemblyNumbers.pop_back(); + this->CurrentAssemblyDescriptions.pop_back(); + } + if (strcmp(name,"blocks")==0 || strcmp(name,"dart:blocks")==0) + { + this->PartNumber=""; + } + } + + virtual int ParsingComplete() + { + //cout << "done parsing\n"; + //vtkstd::map::iterator i; + //for (i=this->BlockIDToPartNumber.begin(); + // i!=this->BlockIDToPartNumber.end();i++) + //{ + //cout << "Block " << (*i).first << "\n Part Number: " << (*i).second + // << "\n Part Description: " << this->PartDescriptions[(*i).second] + // << "\n Material Description: " + // << this->MaterialDescriptions[(*i).second] + // <<"\n Material Specifications: " + // << this->MaterialSpecifications[(*i).second] << endl; + // + // + //} + //cout << "Block " << (*i).first << "\n Part Number: " << (*i).second << " Assemblies: "; + //for (int j=0;jPartNumberToAssemblyNumbers[(*i).second].size();j++){ + // cout << this->PartNumberToAssemblyNumbers[(*i).second][j] << " "; + //} + //cout << endl; + //} + //int count=0; + //for (vtkstd::list::iterator i=this->apbList.begin();i!=this->apbList.end();i++){ + //cout << (*i) << " blocks:"; + //for (int j=0;jpointArrayRawBuffer; +} + +char** vtkExodusMetadata::AllocatePointArrayNameBuffer(int num_strings) +{ + int idx; + + if (this->pointArrayRawBuffer) + { + for (idx = 0; idx < this->originalNumberOfPointArrays; ++idx) + { + delete [] this->pointArrayRawBuffer[idx]; + } + delete [] this->pointArrayRawBuffer; + this->pointArrayRawBuffer = NULL; + this->originalNumberOfPointArrays = 0; + } + + if (num_strings > 0) + { + this->originalNumberOfPointArrays = num_strings; + this->pointArrayRawBuffer = new char*[num_strings]; + + for (idx = 0; idx < num_strings; ++idx) + { + this->pointArrayRawBuffer[idx] = new char[MAX_STR_LENGTH+1]; + } + } + + return this->pointArrayRawBuffer; +} + +char** vtkExodusMetadata::GetCellArrayNameBuffer() +{ + return this->cellArrayRawBuffer; +} + +char** vtkExodusMetadata::AllocateCellArrayNameBuffer(int num_strings) +{ + int idx; + + if (this->cellArrayRawBuffer) + { + for (idx = 0; idx < this->originalNumberOfCellArrays; ++idx) + { + delete [] this->cellArrayRawBuffer[idx]; + } + delete [] this->cellArrayRawBuffer; + this->cellArrayRawBuffer = NULL; + this->originalNumberOfCellArrays = 0; + } + + if (num_strings > 0) + { + this->originalNumberOfCellArrays = num_strings; + this->cellArrayRawBuffer = new char*[num_strings]; + + for (idx = 0; idx < num_strings; ++idx) + { + this->cellArrayRawBuffer[idx] = new char[MAX_STR_LENGTH+1]; + } + } + + return this->cellArrayRawBuffer; +} + +int vtkExodusMetadata::VectorizeArrays( + int numOriginalNames, char **originalNames, + vtkstd::vector *newNames, vtkstd::vector *newSize) +{ + newNames->erase(newNames->begin(),newNames->end()); + newSize->erase(newSize->begin(),newSize->end()); + + // Go through names and combine any vectors + // + // namex ) + // namey )-> name + // namez ) + + int idx = 0; + while (idx < numOriginalNames) + { + int len = strlen(originalNames[idx]); + char last_char = toupper(originalNames[idx][len-1]); + + char *newName = vtkExodusReader::StrDupWithNew(originalNames[idx]); + int nextIdx = idx + 1; + + if (last_char=='X') + { + if ((nextIdx < numOriginalNames) && + (toupper(originalNames[nextIdx][len-1])=='Y') && + !(strncmp(newName, originalNames[nextIdx], len-1))) + { + nextIdx++; + newName[len-1] = '\0'; + + if ((nextIdx < numOriginalNames) && + (toupper(originalNames[nextIdx][len-1])=='Z') && + !(strncmp(newName, originalNames[nextIdx], len-1))) + { + nextIdx++; + } + } + } + + int numComponents = nextIdx - idx; + + newNames->push_back(newName); + delete []newName; + newSize->push_back(numComponents); + + idx = nextIdx; + } + + return newNames->size(); +} + +void vtkExodusMetadata::Finalize() +{ + int i; + + //////////////////////////////// + // Point Arrays + //////////////////////////////// + + int numNewArrays = vtkExodusMetadata::VectorizeArrays( + originalNumberOfPointArrays, pointArrayRawBuffer, + &pointArrayNames, &pointArrayComponents); + + pointArrayStatus.erase(pointArrayStatus.begin(), pointArrayStatus.end()); + + for (i=0; iGetArrayStatusInitValue( vtkExodusReader::POINT ) ); + } + + //////////////////////////////// + // Cell Arrays + //////////////////////////////// + + numNewArrays = vtkExodusMetadata::VectorizeArrays( + originalNumberOfCellArrays, cellArrayRawBuffer, + &cellArrayNames, &cellArrayComponents); + + cellArrayStatus.erase(cellArrayStatus.begin(), cellArrayStatus.end()); + + for (i=0; iGetArrayStatusInitValue( vtkExodusReader::CELL ) ); + } + + this->SortBlocks(); +} + + +vtkCxxRevisionMacro(vtkExodusReader, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkExodusReader); + +#ifdef ARRAY_TYPE_NAMES_IN_CXX_FILE +const char *ArrayTypeNames[vtkExodusReader::NUM_ARRAY_TYPES] = { + "CELL", + "POINT", + "BLOCK", + "PART", + "MATERIAL", + "ASSEMBLY", + "HIERARCHY" +}; + +const char * +vtkExodusReader::GetArrayTypeName( vtkExodusReader::ArrayType type ) +{ + return ArrayTypeNames[ type ]; +} + +#else // method in .h file +const char *vtkExodusReader::ArrayTypeNames[NUM_ARRAY_TYPES] = { + "CELL", + "POINT", + "BLOCK", + "PART", + "MATERIAL", + "ASSEMBLY", + "HIERARCHY" +}; +#endif + +//---------------------------------------------------------------------------- +// Description: +// Instantiate object with NULL filename. +vtkExodusReader::vtkExodusReader() +{ + this->FileName = NULL; + this->XMLFileName=NULL; + + this->TimeStep = 0; + this->ActualTimeStep = 0; + this->GenerateBlockIdCellArray = 1; + this->GenerateGlobalElementIdArray = 0; + this->GenerateGlobalNodeIdArray = 1; + this->ApplyDisplacements = 1; + this->DisplacementMagnitude = 1; + + this->Title = new char[MAX_LINE_LENGTH+1]; + this->NumberOfBlocks = 0; + this->NumberOfUsedNodes = 0; + this->NumberOfNodesInFile = 0; + this->NumberOfTimeSteps = 0; + this->ExodusCPUWordSize = 0; + this->ExodusIOWordSize = 0; + this->ExodusVersion = 0.0; + this->CurrentHandle = -1; + this->CurrentFileName = NULL; + this->CurrentXMLFileName = NULL; + this->TimeStepRange[0] = 0; + this->TimeStepRange[1] = 0; + + this->DataCache = vtkUnstructuredGrid::New(); + this->MetaData = new vtkExodusMetadata; + this->RemakeDataCacheFlag = 1; + this->NewGeometryCount = 0; + + this->CellVarTruthTable = vtkIntArray::New(); + this->PointMap = vtkIntArray::New(); + this->ReversePointMap = vtkIntArray::New(); + + this->ExodusModel = NULL; + this->ExodusModelMetadata = 0; + this->PackExodusModelOntoOutput = 1; + this->DisplayType=1; + this->Parser=NULL; + + this->GlobalElementIdCache=NULL; + + //begin USE_EXO_DSP_FILTERS + this->DSPFilteringIsEnabled=0; + this->DSPFilters=NULL; + this->AddingFilter = vtkDSPFilterDefinition::New(); + //end USE_EXO_DSP_FILTERS + + this->SetNumberOfInputPorts(0); +} + + +//---------------------------------------------------------------------------- +vtkExodusReader::~vtkExodusReader() +{ + this->SetFileName(NULL); + this->SetXMLFileName(NULL); + + this->SetTitle(NULL); + this->SetCurrentFileName(NULL); + + this->DataCache->Delete(); + this->DataCache = NULL; + + this->CellVarTruthTable->Delete(); + this->CellVarTruthTable = NULL; + + this->PointMap->Delete(); + this->PointMap = NULL; + this->ReversePointMap->Delete(); + this->ReversePointMap = NULL; + + if (this->ExodusModel) + { + this->ExodusModel->Delete(); + this->ExodusModel = NULL; + } + + this->SetGlobalElementIdCache(NULL); + + //begin USE_EXO_DSP_FILTERS + if(this->DSPFilters) + { + for(int i=0;iGetNumberOfBlockArrays();i++) + { + this->DSPFilters[i]->Delete(); + } + delete[] this->DSPFilters ; + this->DSPFilters=NULL; + } + //end USE_EXO_DSP_FILTERS + + + if (this->Parser){ + this->Parser->Delete(); + this->Parser=NULL; + } + + delete this->MetaData; + + //begin USE_EXO_DSP_FILTERS + if (this->AddingFilter) + { + this->AddingFilter->Delete(); + } + //end USE_EXO_DSP_FILTERS + +} + +void vtkExodusReader::NewExodusModel() +{ + // These arrays are required by vtkExodusIIWriter + + this->GenerateBlockIdCellArrayOn(); + this->GenerateGlobalElementIdArrayOn(); + this->GenerateGlobalNodeIdArrayOn(); + + if (this->ExodusModel) + { + this->ExodusModel->Reset(); + return; + } + + this->ExodusModel = vtkExodusModel::New(); +} + +void vtkExodusReader::SetGlobalElementIdCache(int *list) +{ + if (this->GlobalElementIdCache) + { + delete [] this->GlobalElementIdCache; + this->GlobalElementIdCache = NULL; + } + + if (list) + { + this->GlobalElementIdCache = list; + } +} + +// Point array info accessors +int vtkExodusReader::GetNumberOfPointArrays() +{ + return this->MetaData->GetNumberOfPointArrays(); +} + +const char* vtkExodusReader::GetPointArrayName(int arrayIdx) +{ + return this->MetaData->GetPointArrayName(arrayIdx); +} + +int vtkExodusReader::GetPointArrayNumberOfComponents(int arrayIdx) +{ + return this->MetaData->GetPointArrayComponents(arrayIdx); +} + +void vtkExodusReader::SetPointArrayStatus(int index, int flag) +{ + int n = this->MetaData->GetOriginalNumberOfPointArrays(); + + if ((index >= 0) && (index < n)) + { + this->MetaData->SetPointArrayStatus(index, flag); + this->Modified(); + } +} + +void vtkExodusReader::SetPointArrayStatus(const char* name, int flag) +{ + this->MetaData->SetPointArrayStatus(name, flag); + this->Modified(); +} + +int vtkExodusReader::GetPointArrayStatus(int index) +{ + int n = this->MetaData->GetOriginalNumberOfPointArrays(); + + if ((index >= 0) && (index < n)) + { + return this->MetaData->GetPointArrayStatus(index); + } + + return 0; +} + +int vtkExodusReader::GetPointArrayStatus(const char* name) +{ + return this->MetaData->GetPointArrayStatus(name); +} + +// Cell array info accessors +int vtkExodusReader::GetNumberOfCellArrays() +{ + return this->MetaData->GetNumberOfCellArrays(); +} + +const char* vtkExodusReader::GetCellArrayName(int arrayIdx) +{ + return this->MetaData->GetCellArrayName(arrayIdx); +} + +int vtkExodusReader::GetCellArrayNumberOfComponents(int arrayIdx) +{ + return this->MetaData->GetCellArrayComponents(arrayIdx); +} + +void vtkExodusReader::SetCellArrayStatus(int index, int flag) +{ + int n = this->MetaData->GetOriginalNumberOfCellArrays(); + + if ((index >= 0) && (index < n)) + { + this->MetaData->SetCellArrayStatus(index, flag); + this->Modified(); + } +} + +void vtkExodusReader::SetCellArrayStatus(const char* name, int flag) +{ + this->MetaData->SetCellArrayStatus(name, flag); + this->Modified(); +} + +int vtkExodusReader::GetCellArrayStatus(int index) +{ + int n = this->MetaData->GetOriginalNumberOfCellArrays(); + + if ((index >= 0) && (index < n)) + { + return this->MetaData->GetCellArrayStatus(index); + } + + return 0; +} + +int vtkExodusReader::GetCellArrayStatus(const char* name) +{ + return this->MetaData->GetCellArrayStatus(name); +} + +// Block info accessors +int vtkExodusReader::GetNumberOfBlockArrays() +{ + return this->MetaData->GetNumberOfBlocks(); +} + +const char* vtkExodusReader::GetBlockArrayName(int arrayIdx) +{ + return this->MetaData->GetBlockName(arrayIdx); +} + +void vtkExodusReader::SetBlockArrayStatus(int index, int flag) +{ + // Only modify if we are 'out of sync' + //cout << "called SetBlockArrayStatus " << index << endl; + if (this->MetaData->GetBlockStatus(index) != flag) + { + this->MetaData->SetBlockStatus(index, flag); + + // Because which blocks are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +void vtkExodusReader::SetBlockArrayStatus(const char* name, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetBlockStatus(name) != flag) + { + this->MetaData->SetBlockStatus(name, flag); + + // Because which blocks are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +int vtkExodusReader::GetBlockArrayStatus(int index) +{ + return this->MetaData->GetBlockStatus(index); +} + +int vtkExodusReader::GetBlockArrayStatus(const char* name) +{ + return this->MetaData->GetBlockStatus(name); +} + +int vtkExodusReader::GetNumberOfElementsInBlock(int block_idx) +{ + return this->MetaData->GetNumElementsInBlock(block_idx); +} + +//---------------------------- +// Node/Side set accessors +//---------------------------- +void vtkExodusReader::SetNodeSetArrayStatus(int index, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetNodeSetStatus(index) != flag) + { + this->MetaData->SetNodeSetStatus(index, flag); + + // Because which node sets are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} +void vtkExodusReader::SetNodeSetArrayStatus(const char* name, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetNodeSetStatus(name) != flag) + { + this->MetaData->SetNodeSetStatus(name, flag); + + // Because which node sets are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} +int vtkExodusReader::GetNodeSetArrayStatus(int index ) +{ + return this->MetaData->GetNodeSetStatus( index ); +} +int vtkExodusReader::GetNodeSetArrayStatus(const char* name ) +{ + return this->MetaData->GetNodeSetStatus( name ); +} +const char* vtkExodusReader::GetNodeSetArrayName(int index) +{ + return this->MetaData->GetNodeSetName(index); +} + +void vtkExodusReader::SetSideSetArrayStatus(int index, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetSideSetStatus(index) != flag) + { + this->MetaData->SetSideSetStatus(index, flag); + + // Because which side sets are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} +void vtkExodusReader::SetSideSetArrayStatus(const char* name, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetSideSetStatus(name) != flag) + { + this->MetaData->SetSideSetStatus(name, flag); + + // Because which side sets are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} +int vtkExodusReader::GetSideSetArrayStatus(int index) +{ + return this->MetaData->GetSideSetStatus( index ); +} +int vtkExodusReader::GetSideSetArrayStatus(const char* name) +{ + return this->MetaData->GetSideSetStatus( name ); +} +const char* vtkExodusReader::GetSideSetArrayName(int index) +{ + return this->MetaData->GetSideSetName(index); +} + +//---------------------------- +// End Node/Side set accessors +//---------------------------- + +// Part info accessors +int vtkExodusReader::GetNumberOfPartArrays() +{ + return this->MetaData->GetNumberOfParts(); +} + +const char* vtkExodusReader::GetPartArrayName(int arrayIdx) +{ + return this->MetaData->GetPartName(arrayIdx); +} + +const char* vtkExodusReader::GetPartBlockInfo(int arrayIdx) +{ + return this->MetaData->GetPartBlockInfo(arrayIdx); +} + +void vtkExodusReader::SetPartArrayStatus(int index, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetPartStatus(index) != flag) + { + this->MetaData->SetPartStatus(index, flag); + + // Because which parts are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +void vtkExodusReader::SetPartArrayStatus(const char* name, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetPartStatus(name) != flag) + { + this->MetaData->SetPartStatus(name, flag); + + // Because which parts are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +int vtkExodusReader::GetPartArrayStatus(int index) +{ + return this->MetaData->GetPartStatus(index); +} + +int vtkExodusReader::GetPartArrayStatus(const char* name) +{ + return this->MetaData->GetPartStatus(name); +} + +// Material info accessors +int vtkExodusReader::GetNumberOfMaterialArrays() +{ + //cout << "reader asked for nummat " << this->MetaData->GetNumberOfMaterials() << endl; + return this->MetaData->GetNumberOfMaterials(); +} + +const char* vtkExodusReader::GetMaterialArrayName(int arrayIdx) +{ + return this->MetaData->GetMaterialName(arrayIdx); +} + +void vtkExodusReader::SetMaterialArrayStatus(int index, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetMaterialStatus(index) != flag) + { + this->MetaData->SetMaterialStatus(index, flag); + + // Because which materials are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +void vtkExodusReader::SetMaterialArrayStatus(const char* name, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetMaterialStatus(name) != flag) + { + this->MetaData->SetMaterialStatus(name, flag); + + // Because which materials are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +int vtkExodusReader::GetMaterialArrayStatus(int index) +{ + return this->MetaData->GetMaterialStatus(index); +} + +int vtkExodusReader::GetMaterialArrayStatus(const char* name) +{ + return this->MetaData->GetMaterialStatus(name); +} +//end of Material Accessors + +// Assembly info accessors +int vtkExodusReader::GetNumberOfAssemblyArrays() +{ + return this->MetaData->GetNumberOfAssemblies(); +} + +const char* vtkExodusReader::GetAssemblyArrayName(int arrayIdx) +{ + return this->MetaData->GetAssemblyName(arrayIdx); +} + +int vtkExodusReader::GetAssemblyArrayID( char const *name ) +{ + int numArrays = this->GetNumberOfAssemblyArrays(); + for ( int i=0;iGetAssemblyArrayName( i ) ) == 0 ) + { + return i; + } + } + return -1; +} + +void vtkExodusReader::SetAssemblyArrayStatus(int index, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetAssemblyStatus(index) != flag) + { + this->MetaData->SetAssemblyStatus(index, flag); + + // Because which materials are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +void vtkExodusReader::SetAssemblyArrayStatus(const char* name, int flag) +{ + // Only modify if we are 'out of sync' + if (this->MetaData->GetAssemblyStatus(name) != flag) + { + this->MetaData->SetAssemblyStatus(name, flag); + + // Because which materials are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +int vtkExodusReader::GetAssemblyArrayStatus(int index) +{ + return this->MetaData->GetAssemblyStatus(index); +} + +int vtkExodusReader::GetAssemblyArrayStatus(const char* name) +{ + return this->MetaData->GetAssemblyStatus(name); +} + +//end of Assembly Accessor + +// Hierarchy Entry info accessors +int vtkExodusReader::GetNumberOfHierarchyArrays() +{ + if (this->Parser) + { + return this->Parser->GetNumberOfHierarchyEntries(); + } + return 0; +} + +const char* vtkExodusReader::GetHierarchyArrayName(int arrayIdx) +{ + if (this->Parser) + { + //MEMORY LEAK - without copying the result, the list does not appear on SGI's + char* result=new char[512]; + sprintf(result,"%s",this->Parser->GetHierarchyEntry(arrayIdx).c_str()); + return result; + //return this->Parser->GetHierarchyEntry(arrayIdx).c_str(); + } + return "Should not see this"; +} + +void vtkExodusReader::SetHierarchyArrayStatus(int index, int flag) +{ + // Only modify if we are 'out of sync' + //if (this->GetHierarchyArrayStatus(index) != flag) + // { + if (this->Parser) + { + vtkstd::vector blocks=this->Parser->GetBlocksForEntry(index); + for (vtkstd::vector::size_type i=0;iMetaData->SetUnsortedBlockStatus + (this->MetaData->GetBlockIndex(blocks[i]),flag); + } + + // Because which materials are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +void vtkExodusReader::SetHierarchyArrayStatus(const char* name, int flag) +{ + // Only modify if we are 'out of sync' + //if (this->GetHierarchyArrayStatus(name) != flag) + //{ + if (this->Parser) + { + vtkstd::vector blocks=this->Parser->GetBlocksForEntry + (vtkStdString(name)); + for (vtkstd::vector::size_type i=0;iMetaData->SetUnsortedBlockStatus + (this->MetaData->GetBlockIndex(blocks[i]),flag); + } + + // Because which materials are on/off affects the + // geometry we need to remake the mesh cache + this->RemakeDataCacheFlag = 1; + this->Modified(); + } +} + +int vtkExodusReader::GetHierarchyArrayStatus(int index) +{ + if (this->Parser) + { + vtkstd::vector blocks=this->Parser->GetBlocksForEntry(index); + for (vtkstd::vector::size_type i=0;iMetaData->GetUnsortedBlockStatus + (this->MetaData->GetBlockIndex(blocks[i]))==0) + return 0; + } + } + return 1; +} + +int vtkExodusReader::GetHierarchyArrayStatus(const char* name) +{ + if (this->Parser) + { + vtkstd::vector blocks=this->Parser->GetBlocksForEntry(name); + for (vtkstd::vector::size_type i=0;iMetaData->GetUnsortedBlockStatus + (this->MetaData->GetBlockIndex(blocks[i]))==0) + return 0; + } + } + return 1; +} + +//end of Hierarchy Entry Accessors + +int vtkExodusReader::GetBlockId(int block_idx) +{ + return this->MetaData->GetBlockId(block_idx); +} + +void vtkExodusReader::SetDisplayType(int type){ + if (this->MetaData) + { + this->MetaData->SetDisplayType(type); + } + this->DisplayType=type; +} + +// Helper function +int vtkExodusReaderFileExist(char *file_name) +{ + struct stat fs; + if (file_name) + { + return (stat(file_name, &fs) != -1); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +int vtkExodusReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + int error; + float fdum; + int num_node_vars, num_ele_vars; + int i; + int num_elem_in_block; + int num_nodes_per_elem; + int num_attr; + char *cdum = NULL; + char elem_type[MAX_STR_LENGTH+1]; + + // We can skip ExecuteInformation if all of these are true: + // The filename has not changed + // The XML filename has not changed + // The request for metadata has not changed + + int newXMLFile = 1; + int newMetaData = 1; + + int newFile = + (vtkExodusReader::StringsEqual(this->FileName, this->CurrentFileName) == 0); + + if (!newFile) + { + newXMLFile = + (vtkExodusReader::StringsEqual(this->XMLFileName, this->CurrentXMLFileName) == 0); + + newMetaData = ((this->ExodusModelMetadata && (this->ExodusModel == NULL)) || + (!this->ExodusModelMetadata && this->ExodusModel)); + } + + if ( !newFile && !newXMLFile && !newMetaData) + { + return 1; + } + + if (newXMLFile) + { + // Clean up any old xml parsers + if (this->Parser) + { + this->Parser->Delete(); + this->Parser=NULL; + } + + // If the xml file does not exist, try try again + if (!vtkExodusReaderFileExist(this->XMLFileName)) + { + // Okay try to create an xml file using exodus file as basename + char tempName[512]; + strcpy(tempName,this->FileName); + char* fpt=strrchr(tempName,'.'); + if (fpt) strncpy(fpt,".xml\0",5); + // Does the xml file exist? + if (vtkExodusReaderFileExist(tempName)) + { + SetXMLFileName(tempName); + } + else + { + //try .dart + fpt=strrchr(tempName,'.'); + if (fpt) strncpy(fpt,".dart\0",6); + if (vtkExodusReaderFileExist(tempName)) + { + SetXMLFileName(tempName); + } + else + { + SetXMLFileName(NULL); + } + } + } + + // Okay if we have a valid file create a parser + if (this->XMLFileName) + { + //cout << "parsing: " << this->XMLFileName << endl; + this->Parser=new vtkExodusXMLParser(this->XMLFileName); + } + + // The filename is different so we need to open the file + // and remake the data cache and get all the metadata + this->RemakeDataCacheFlag = 1; + newFile = 1; + this->SetCurrentXMLFileName(this->XMLFileName); + } + + if ( this->OpenCurrentFile() != 1 ) + { + return 0; + } + + if (newMetaData) + { + if (this->ExodusModelMetadata) + { + // Write the global metadata now. This is all the information + // which does not depend on which cells, timestep, or field data + // we are going to read in. + + this->NewExodusModel(); + + this->ExodusModel->SetGlobalInformation( this->CurrentHandle, + this->ExodusCPUWordSize ); + } + else + { + if (this->ExodusModel) + { + this->ExodusModel->Delete(); + this->ExodusModel = NULL; + } + } + } + + // **KEN** Why not have vtkExodusMetadata do all of this instead. + // Encapsulate the functionality of reading it along with the data. + // That's the whole idea behind object oriented programming, right? + + if (newFile) + { + this->SetGlobalElementIdCache(NULL); + + // Get metadata + error = ex_get_init(this->CurrentHandle, this->Title, &this->Dimensionality, + &this->NumberOfNodesInFile, &this->NumberOfElementsInFile, + &this->NumberOfBlocks, &this->NumberOfNodeSets, &this->NumberOfSideSets); + if (error < 0) + { + vtkErrorMacro("Error: " << error << " calling ex_get_init " << this->FileName); + this->CloseCurrentFile(); + return 0; + } + + // Read the number of time steps available. + error = ex_inquire(this->CurrentHandle, + EX_INQ_TIME, &this->NumberOfTimeSteps, &fdum,cdum); + if (error < 0) + { + vtkErrorMacro("Error: " << error << " calling ex_inquire " << this->FileName); + this->CloseCurrentFile(); + return 0; + } + + this->TimeStepRange[0] = 0; + this->TimeStepRange[1] = this->NumberOfTimeSteps-1; + + this->GetAllTimes(outputVector); + + // Read element block paramemters. + this->MetaData->ResetBlocks(); + int *ids = new int[this->NumberOfBlocks]; + char block_name_buffer[80]; + ex_get_elem_blk_ids (this->CurrentHandle, ids); + + for (i = 0; i < this->NumberOfBlocks; ++i) + { + error = ex_get_elem_block (this->CurrentHandle, ids[i], elem_type, + &(num_elem_in_block), + &(num_nodes_per_elem), &(num_attr)); + if (error < 0) + { + vtkErrorMacro( + "Error: " << error << " calling ex_get_elem_blk_ids " << this->FileName); + this->CloseCurrentFile(); + delete [] ids; + return 0; + } + + // Check for empty block + if (!strcmp(elem_type,"NULL")) + { + strcpy(elem_type,"empty"); + } + + sprintf(block_name_buffer,"Block: %d (%s)",ids[i],elem_type); + if (this->Parser && this->Parser->GetPartDescription(ids[i])!="") + { + //construct assembly names from number and description arrays + vtkstd::vector assemblyNumbers= + this->Parser->GetAssemblyNumbers(ids[i]); + vtkstd::vector assemblyDescriptions= + this->Parser->GetAssemblyDescriptions(ids[i]); + + vtkstd::vector assemblyNames; + for (vtkstd::vector::size_type j=0;jParser->GetPartDescription(ids[i]).c_str(), + this->Parser->GetPartNumber(ids[i]).c_str()); + this->MetaData->AddBlock(block_name_buffer, + this->Parser->GetPartDescription(ids[i])+" ("+ + this->Parser->GetMaterialDescription(ids[i])+")"+" : "+ + this->Parser->GetPartNumber(ids[i]), + this->Parser->GetMaterialDescription(ids[i])+" : "+ + this->Parser->GetMaterialSpecification(ids[i]), + assemblyNames, + ids[i], num_elem_in_block, 1); + } + else + { + vtkstd::vector assemblyNames; + assemblyNames.push_back(vtkStdString("Default Assembly")); + this->MetaData->AddBlock(block_name_buffer,"Default Part", + "Default Material", assemblyNames,ids[i], + num_elem_in_block, 1); + } + + } + delete [] ids; + + // Read the number of node arrays + error = ex_get_var_param(this->CurrentHandle, "n", &(num_node_vars)); + if (error < 0) + { + vtkErrorMacro( + "Error: " << error << " calling ex_get_var_param " << this->FileName); + this->CloseCurrentFile(); + return 0; + } + + // Get node array information + if (num_node_vars > 0) + { + error = ex_get_var_names(this->CurrentHandle, "n", num_node_vars, + MetaData->AllocatePointArrayNameBuffer(num_node_vars)); + if (error < 0) + { + vtkErrorMacro( + "Error: " << error << " reading point array names " << this->FileName); + this->CloseCurrentFile(); + return 0; + } + + this->RemoveBeginningAndTrailingSpaces( + MetaData->GetPointArrayNameBuffer(),num_node_vars); + } + + // Read the number of cell arrays + error = ex_get_var_param(this->CurrentHandle, "e", &(num_ele_vars)); + if (error < 0) + { + vtkErrorMacro( + "Error: " << error << " calling ex_get_var_param " << this->FileName); + this->CloseCurrentFile(); + return 0; + } + + // Get cell array information + if (num_ele_vars > 0) + { + // Not all cell variables exist over all element blocks. A "truth table" + // will say whether a variable is defined for a certain block. + + this->CellVarTruthTable->Resize(num_ele_vars*this->NumberOfBlocks); + int *ptr = CellVarTruthTable->GetPointer(0); + ex_get_elem_var_tab(this->CurrentHandle, this->NumberOfBlocks, + num_ele_vars, ptr); + error = ex_get_var_names (this->CurrentHandle, "e", num_ele_vars, + MetaData->AllocateCellArrayNameBuffer(num_ele_vars)); + if (error < 0) + { + vtkErrorMacro("Error: " << error << " calling ex_get_var_names " << this->FileName); + this->CloseCurrentFile(); + return 0; + } + + this->RemoveBeginningAndTrailingSpaces( + MetaData->GetCellArrayNameBuffer(),num_ele_vars); + } + + // Read Node Set and Side Set metadata + this->ReadNodeSetMetadata(); + this->ReadSideSetMetadata(); + } + + // Close the exodus file + this->CloseCurrentFile(); + + if (newFile) + { + // Call finalize on the array metadata. This is important + // otherwise does not work at all + + MetaData->Finalize(); + } + + return 1; +} + + +//------------------------------------------------------------------------ +// Read Node Set and Side Set MetaData for future use +// Set ids +// Set size +// number of distribution factors in each set +//------------------------------------------------------------------------ +void vtkExodusReader::ReadNodeSetMetadata() +{ + // Stop if there are no Node Sets + if ( this->NumberOfNodeSets <= 0 ) + { + return; + } + // allocate memory for node set ids + vtkstd::vector nodeSetId( this->NumberOfNodeSets, -1 ); + int size = 0; + int dist = 0; + // read node set ids + int error = ex_get_node_set_ids( this->CurrentHandle, &nodeSetId[0] ); + if (error < 0) + { + vtkErrorMacro("Error: " << error << " calling ex_get_node_set_ids " << this->FileName); + } + // read meta data for each node set + int i = 0; + for( i = 0; i < this->NumberOfNodeSets; i++ ) + { + error = ex_get_node_set_param( this->CurrentHandle, nodeSetId[i], &size, &dist ); + if (error < 0) + { + vtkErrorMacro("Error: " << error << " calling ex_get_node_set_param " << this->FileName); + } + // Add a node set's metadata to vtkExodusMetaData + // Store it's Exodus Id, size, and number of distribution factors + this->MetaData->AddNodeSet( nodeSetId[i], size, dist ); + } +} +void vtkExodusReader::ReadSideSetMetadata() +{ + // Stop if there are no Side Sets + if ( this->NumberOfSideSets <= 0 ) + { + return; + } + // allocate memory for side set ids + vtkstd::vector sideSetId( this->NumberOfSideSets, -1 ); + int size = 0; + int dist = 0; + // read side set ids + int error = ex_get_side_set_ids( this->CurrentHandle, &sideSetId[0] ); + if (error < 0) + { + vtkErrorMacro(<< "Error: " << error + << " calling ex_get_side_set_ids " << this->FileName); + } + // read meta data for each side set + int i = 0; + for( i = 0; i < this->NumberOfSideSets; i++ ) + { + error = ex_get_side_set_param( this->CurrentHandle, sideSetId[i], &size, &dist ); + if (error < 0) + { + vtkErrorMacro(<< "Error: " << error + << " calling ex_get_side_set_param " << this->FileName); + } + // Add a side set's metadate to vtkExodusMetaData + // Store it's Exodus Id, size, and number of distribution factors + this->MetaData->AddSideSet( sideSetId[i], size, dist ); + } +} + +//---------------------------------------------------------------------------- +int vtkExodusReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + if ( this->OpenCurrentFile() != 1 ) + { + vtkWarningMacro(<< "Can't open file"); + return 0; + } + + this->ActualTimeStep = this->TimeStep; + + vtkInformation* outInfo = outputVector->GetInformationObject(0); + // get the ouptut + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Check if a particular time was requested. + if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_INDEX())) + { + // Get the requested time step. + this->ActualTimeStep = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_INDEX()); + + // Save the time value in the output data information. + int length = + outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + if(this->ActualTimeStep >= 0 && this->ActualTimeStep < length) + { + double* steps = + outInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + output->GetInformation()->Set(vtkDataObject::DATA_TIME(), + steps[this->ActualTimeStep]); + } + else + { + vtkErrorMacro("Time index " << this->ActualTimeStep + << " requested but there are " + << length << " time steps."); + } + output->GetInformation()->Set(vtkDataObject::DATA_TIME_INDEX(), + this->ActualTimeStep); + } + // Force TimeStep into the "known good" range. Although this + // could be accomplished inside SetTimeStep(), + // - we'd rather not override a VTK macro-defined method + // because the macro might change + // - it might be good to allow out-of-range values in + // places + // CHANGE: It is generally not good practice to change ivar + // publicly accessible (through Set) in Execute(). This can + // easily make the user interface (for example server manager) + // in a state inconsistent with the reader. Therefore, clamp a + // protected variable and use that instead. + if ( this->ActualTimeStep < this->TimeStepRange[0] ) + { + this->ActualTimeStep = this->TimeStepRange[0]; + } + else if ( this->ActualTimeStep > this->TimeStepRange[1] ) + { + this->ActualTimeStep = this->TimeStepRange[1]; + } + + // Okay because they may have changed which blocks are on/off + // we need to recompute the actual number of elements + int actualElements=0; + for (int i=0; i < this->MetaData->GetNumberOfBlocks(); ++i) + { + // Do we read this block? + if (this->MetaData->GetBlockStatus(i)==1) + actualElements += this->MetaData->GetNumElementsInBlock(i); + } +#if DEBUG + vtkWarningMacro(<< "NumElements: " << NumberOfElements + << " actualElements: " << actualElements); +#endif + this->NumberOfUsedElements = actualElements; + + + // In general the geometry of an exodus file remains the same + // So often you can just read in new field array + // The 'RemakeDataCacheFlag' is set if you need to read + // in the geometry again for some reason (eg new file or a + // change which blocks get read in etc) + if ( RemakeDataCacheFlag ) + { + this->ReadGeometry(this->CurrentHandle, output); + + this->NewGeometryCount++; + + // **KEN** Would it make sense to relase the DataCache data BEFORE + // reading the new geometry? That might reduce the amount of memory + // needed at one time. + + // Make a shallowcopy to the my DataCache + this->DataCache->ReleaseData(); // FIXME Do I need this? + this->DataCache->ShallowCopy(output); + + // Okay I don't need to do this again until someone + // says 'Hey you need to remake this mesh data!' + this->RemakeDataCacheFlag = 0; + +#if DEBUG + vtkWarningMacro("Remade data cache"); +#endif + } + else + { + // Just copy (shallow) the points and cells from the DataCache. + // The points and cell information is always the same for exodus + // Also copy the generated arrays which also stay the same + output->ShallowCopy(this->DataCache); + } + + // Read in the arrays. + // If we are in the execution method then either the file, the time + // step or array selections changed. In all cases we have to reload arrays. + this->ReadArrays(this->CurrentHandle, output); + + //begin USE_EXO_DSP_FILTERS + this->GetDSPOutputArrays(this->CurrentHandle, output); + //end USE_EXO_DSP_FILTERS + + // If the user wants the apply displacements then add here + // TODO: This is recalled everytime a user changes arrays + // look into avoiding this if possible + if (ApplyDisplacements) + { + AddDisplacements(output); + } + + // Generated arrays include block id, global node id, global element id + this->GenerateExtraArrays(output); + + // This just makes sure the arrays are the same size as the number + // of nodes or cell + output->CheckAttributes(); + + // We may have some mem that can be condensed + output->Squeeze(); + + if (this->ExodusModel) + { + int rc = this->ExodusModel->SetLocalInformation( + output, + this->CurrentHandle, this->ActualTimeStep, + this->NewGeometryCount, this->ExodusIOWordSize); + + if (rc) + { + vtkErrorMacro(<< "Can't create the local model information"); + } + + if (this->PackExodusModelOntoOutput) + { + // The metadata will be written to field arrays and added + // to the output. + + this->ExodusModel->GetModelMetadata()->Pack(output); + } + } + + // Close the exodus file + this->CloseCurrentFile(); + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkExodusReader::ReadGeometry(int handle, vtkUnstructuredGrid* output) +{ + // Reset the entire unstructured grid + output->Reset(); + + // Read in cell topology + this->ReadCells(handle, output); + + // Read in node and side sets + this->ReadNodeAndSideSets(handle, output); + + // Now read in the points + // Note: This should come after reading in + // the cells and node/side set so that + // we know which points should actually be + // stored and put in the output + this->ReadPoints(handle, output); + +} + +// Read in node and side set data +void vtkExodusReader::ReadNodeAndSideSets(int handle, vtkUnstructuredGrid* output) +{ + int i, j, k; + int *indexPtr; + vtkIdList *cellIds=vtkIdList::New(); + vtkIntArray *counts=vtkIntArray::New(); + vtkIntArray *nodeIndexes=vtkIntArray::New(); + int cellType; + int cellNumPoints; + + + // Read in all the node sets that are 'on' + for (i=0; i < this->GetNumberOfNodeSets(); ++i) + { + // Do we read this node set? + if (this->MetaData->GetNodeSetStatus(i)) + { + + // Allocate storage for node indexes + nodeIndexes->Reset(); + nodeIndexes->SetNumberOfValues(this->MetaData->GetNodeSetSize(i)); + + // Get the node indexes + ex_get_node_set(handle, this->MetaData->GetNodeSetId(i), nodeIndexes->GetPointer(0)); + + + // Okay now loop though the nodes indexes and insert into the output + for(j=0; j < this->MetaData->GetNodeSetSize(i); ++j) + { + cellIds->Reset(); + cellIds->InsertNextId(GetPointMapIndex(nodeIndexes->GetValue(j)-1)); + output->InsertNextCell(VTK_VERTEX, cellIds); + } + } + } + + + // Read in all the side sets that are 'on' + for (i=0; i < this->GetNumberOfSideSets(); ++i) + { + // Do we read this side set? + if (this->MetaData->GetSideSetStatus(i)) + { + + // Allocate storage for 'counts' (element size) array and node indexes (connectivity) + // Assumption: Side set elements will not be more than 4 nodes :) + counts->Reset(); + counts->SetNumberOfValues(this->MetaData->GetSideSetSize(i)); + nodeIndexes->Reset(); + nodeIndexes->SetNumberOfValues(this->MetaData->GetSideSetSize(i)*4); + + // Get the counts (element size) array and the node indexes + ex_get_side_set_node_list(handle, this->MetaData->GetSideSetId(i), counts->GetPointer(0), nodeIndexes->GetPointer(0)); + + indexPtr = nodeIndexes->GetPointer(0); + + // Okay now loop though for each element and set up the cells + for(j=0; j < this->MetaData->GetSideSetSize(i); ++j) + { + + // What kind of cell do we have + cellNumPoints = counts->GetValue(j); + switch (cellNumPoints) + { + case 1: + cellType=VTK_VERTEX; + break; + case 2: + cellType=VTK_LINE; + break; + case 3: + cellType=VTK_TRIANGLE; + break; + case 4: + cellType=VTK_QUAD; + break; + default: + vtkErrorMacro("Unknown side side element with: " << counts->GetValue(j) << " nodes"); + return; + } + + // Now set up connectivity for cell + cellIds->Reset(); + for (k=0; kInsertNextId(GetPointMapIndex(indexPtr[k]-1)); + } + indexPtr+=cellNumPoints; + + // Now insert the cell + output->InsertNextCell(cellType, cellIds); + } + } + } + + + // Delete any allocated stuff + cellIds->Delete(); + counts->Delete(); + nodeIndexes->Delete(); + + +} + +// Read in connectivity information +void vtkExodusReader::ReadCells(int handle, vtkUnstructuredGrid* output) +{ + int i, j, k; + int num_elem_in_block; + int num_nodes_per_elem; + int num_attr; + char sm_elem_type[MAX_STR_LENGTH+1]; + int *connect, *pConnect; + vtkIdList *cellIds=vtkIdList::New(); + int cellType; + int cellNumPoints; + + // Allocate memory in the output + output->Allocate(this->NumberOfUsedElements); + + // **KEN** The point maps can be really big. Therefore, they should be + // deleted as soon as possible. + + // Set up point map + this->SetUpPointMap(this->NumberOfNodesInFile); + + // Initialize using the type of cells. + // A block contains only one type of cell. + for (i=0; i < this->MetaData->GetNumberOfBlocks(); ++i) + { + // Do we read this block? + if (this->MetaData->GetBlockStatus(i)==0) + { + continue; + } + + // Read in the metadata about this block + ex_get_elem_block(handle, this->MetaData->GetBlockId(i), sm_elem_type, + &num_elem_in_block, &num_nodes_per_elem, &num_attr); + + // If for some weird reason the block has no elements go to next block + if (num_elem_in_block == 0) + { + continue; + } + + // Okay allocate memory for connectivity data + connect = new int [num_nodes_per_elem*num_elem_in_block]; + ex_get_elem_conn (handle, this->MetaData->GetBlockId(i), connect); + + // Grab the element type + char *elem_type = new char[MAX_STR_LENGTH]; + this->StringUppercase(sm_elem_type, elem_type); + + // Check for quadratic elements + if (!strncmp(elem_type,"TRI",3) && (num_nodes_per_elem==6)) + {cellType=VTK_QUADRATIC_TRIANGLE; cellNumPoints=6;} + else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==8)) + {cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;} + else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==9)) + {cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;} + else if (!strncmp(elem_type,"TET",3) && (num_nodes_per_elem==10)) + {cellType=VTK_QUADRATIC_TETRA; cellNumPoints=10;} + else if (!strncmp(elem_type,"TET",3) && (num_nodes_per_elem==11)) + {cellType=VTK_QUADRATIC_TETRA; cellNumPoints=10;} + else if (!strncmp(elem_type,"HEX",3) && (num_nodes_per_elem==20)) + {cellType=VTK_QUADRATIC_HEXAHEDRON; cellNumPoints=20;} + else if (!strncmp(elem_type,"HEX",3) && (num_nodes_per_elem==21)) + {cellType=VTK_QUADRATIC_HEXAHEDRON; cellNumPoints=20;} + else if (!strncmp(elem_type,"HEX",3) && (num_nodes_per_elem==27)) + {cellType=VTK_QUADRATIC_HEXAHEDRON; cellNumPoints=20;} + else if (!strncmp(elem_type,"QUA",3) && (num_nodes_per_elem==8)) + {cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;} + else if (!strncmp(elem_type,"QUA",3) && (num_nodes_per_elem==9)) + {cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;} + else if (!strncmp(elem_type,"TRU",3) && (num_nodes_per_elem==3)) + {cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;} + else if (!strncmp(elem_type,"BEA",3) && (num_nodes_per_elem==3)) + {cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;} + else if (!strncmp(elem_type,"BAR",3) && (num_nodes_per_elem==3)) + {cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;} + else if (!strncmp(elem_type,"EDG",3) && (num_nodes_per_elem==3)) + {cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;} + + // Check for regular elements + else if (!strncmp(elem_type,"CIR",3)) {cellType=VTK_VERTEX; cellNumPoints=1;} + else if (!strncmp(elem_type,"SPH",3)) {cellType=VTK_VERTEX; cellNumPoints=1;} + else if (!strncmp(elem_type,"BAR",3)) {cellType=VTK_LINE; cellNumPoints=2;} + else if (!strncmp(elem_type,"TRU",3)) {cellType=VTK_LINE; cellNumPoints=2;} + else if (!strncmp(elem_type,"BEA",3)) {cellType=VTK_LINE; cellNumPoints=2;} + else if (!strncmp(elem_type,"EDG",3)) {cellType=VTK_LINE; cellNumPoints=2;} + else if (!strncmp(elem_type,"TRI",3)) {cellType=VTK_TRIANGLE; cellNumPoints=3;} + else if (!strncmp(elem_type,"QUA",3)) {cellType=VTK_QUAD; cellNumPoints=4;} + else if (!strncmp(elem_type,"TET",3)) {cellType=VTK_TETRA; cellNumPoints=4;} + else if (!strncmp(elem_type,"PYR",3)) {cellType=VTK_PYRAMID; cellNumPoints=5;} + else if (!strncmp(elem_type,"WED",3)) {cellType=VTK_WEDGE; cellNumPoints=6;} + else if (!strncmp(elem_type,"HEX",3)) {cellType=VTK_HEXAHEDRON; cellNumPoints=8;} + else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==3)) {cellType=VTK_TRIANGLE; cellNumPoints=3;} + else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==4)) {cellType=VTK_QUAD; cellNumPoints=4;} + else + { + vtkErrorMacro("Unsupported element type: " << elem_type); + delete [] connect; + continue; + } + delete []elem_type; + + //cell types not currently handled + //quadratic wedge - 15,16 nodes + //quadratic pyramid - 13 nodes + + // Now save the cells in a cell array. + pConnect = connect; + for (j = 0; j < num_elem_in_block; ++j) + { + cellIds->Reset(); + + // Build up a list of cell pt ids to insert in to the output data set. + // Note: The '-1' is because Exodus stores ids starting from 1 not 0. + + // Special setup for quadratic hex because exodus node numbering + // for this cell type is different than vtk node numbering + if (cellType==VTK_QUADRATIC_HEXAHEDRON) + { + for (k=0; k<12; ++k) + cellIds->InsertNextId(GetPointMapIndex(pConnect[k]-1)); + for (k=12; k<16; ++k) + cellIds->InsertNextId(GetPointMapIndex(pConnect[k+4]-1)); + for (k=16; k<20; ++k) + cellIds->InsertNextId(GetPointMapIndex(pConnect[k-4]-1)); + } + + // All the rest of the cells have the same node numbering + else + { + for (k=0; kInsertNextId(GetPointMapIndex(pConnect[k]-1)); + } + + // Skip to next element. + pConnect += num_nodes_per_elem; + + // Insert cell into output. + output->InsertNextCell(cellType, cellIds); + } + + delete [] connect; + connect = NULL; + } + + cellIds->Delete(); + cellIds = NULL; +} + + + +void vtkExodusReader::ReadPoints(int handle, vtkUnstructuredGrid* output) +{ + vtkPoints *newPoints; + int pointId, point_index; + + // Sanity Check + if (this->NumberOfUsedNodes == 0) + { +#if DEBUG + vtkWarningMacro("The number of used nodes is zero\n"); +#endif + return; + } + + // Allocate point arrays + float *x = new float[this->NumberOfNodesInFile]; + float *y = new float[this->NumberOfNodesInFile]; + float *z = new float[this->NumberOfNodesInFile]; + + // Clear z values in case you don't really use them + memset(z,0,this->NumberOfNodesInFile*sizeof(float)); + + + // Get node coordinates + ex_get_coord(handle, x, y, z); + + // Create new points + newPoints = vtkPoints::New(); + newPoints->SetNumberOfPoints(this->NumberOfUsedNodes); + + // Set up points + for (pointId=0; pointIdNumberOfUsedNodes; ++pointId) + { + point_index = this->ReversePointMap->GetValue(pointId); + newPoints->InsertPoint(pointId, x[point_index], y[point_index], z[point_index]); + } + output->SetPoints(newPoints); + delete [] x; + delete [] y; + delete [] z; + newPoints->Delete(); + newPoints = NULL; + + // **KEN** I think this would be a good place to clear out the point + // map and squeeze the reverse map. +} + + +//---------------------------------------------------------------------------- +void vtkExodusReader::ReadArrays(int handle, vtkUnstructuredGrid* output) +{ + vtkDataArray *array; + int dim, arrayIdx, idx; + int haveArray, getArray; + char arrayName[MAX_STR_LENGTH]; + char arrayNameUpper[MAX_STR_LENGTH]; + + // Read point arrays. + // The first vector array encounters is set to vectors, + // and the first array encountered is set to scalars. + arrayIdx = 0; + for (idx = 0; idx < this->GetNumberOfPointArrays(); ++idx) + { + // Get the name of the array + strcpy(arrayName,this->GetPointArrayName(idx)); + + // Do I already have this array? + if (output->GetPointData()->GetArray(arrayName) != NULL) + { + haveArray=1; + } + else + { + haveArray=0; + } + + // Does user want displacements + this->StringUppercase(arrayName,arrayNameUpper); + if ((this->ApplyDisplacements || /* user wants displacement field */ + this->ExodusModelMetadata) /* user may plan to write out file */ + && + !strncmp(arrayNameUpper,"DISP",4)) + { + // Add it to the arrays I want + SetPointArrayStatus(idx, 1); + } + + // Does the user want this array? + getArray = this->GetPointArrayStatus(idx); + + // If I have the array and the user DOESN'T want it + // then remove the array from the output + if (haveArray && !getArray) + { + output->GetPointData()->RemoveArray(arrayName); + + if (this->ExodusModel) + { + this->ExodusModel->RemoveUGridNodeVariable(arrayName); + } + } + + // If the user wants this array AND I don't already have it + // then read in the data + else if (getArray && !haveArray) + { + + // How many dimensions is this array + dim = this->GetPointArrayNumberOfComponents(idx); + + if (dim == 1) + array = this->ReadPointArray(handle, arrayIdx); + else + array = this->ReadPointVector(handle, arrayIdx, dim); + + // Opps some sort of problem + if (array == NULL) + { + vtkErrorMacro("Problem reading node array " << this->GetPointArrayName(idx)); + // Do not try loading this again + this->MetaData->SetPointArrayStatus(idx,0); + } + else + { + array->SetName(this->GetPointArrayName(idx)); + output->GetPointData()->AddArray(array); + + // Delete array memory (FIXME this seems inefficient) + array->Delete(); + array = NULL; + + if (this->ExodusModel) + { + // So ExodusIIWriter can map names in UGrid back to names in + // Exodus II file. + + char *origName = + vtkExodusReader::StrDupWithNew( + this->MetaData->GetPointArrayOriginalName(arrayIdx)); + char *newName = + vtkExodusReader::StrDupWithNew(this->GetPointArrayName(idx)); + + this->ExodusModel->AddUGridNodeVariable(newName, origName, dim); + } + } + } + + // The array index needs to be incremented by the dimension + dim = this->GetPointArrayNumberOfComponents(idx); + arrayIdx += dim; + } + + // Read cell arrays. + arrayIdx = 0; + for (idx = 0; idx < this->GetNumberOfCellArrays(); ++idx) + { + + // Get the name of the array + strcpy(arrayName,this->GetCellArrayName(idx)); + + // Do I already have this array? + if (output->GetCellData()->GetArray(arrayName) != NULL) + haveArray=1; + else + haveArray=0; + + // Does the user want this array? + getArray = this->GetCellArrayStatus(idx); + + // If I have the array and the user DOESN'T want it + // then remove the array from the output + if (haveArray && !getArray) + { + output->GetCellData()->RemoveArray(arrayName); + + if (this->ExodusModel) + { + this->ExodusModel->RemoveUGridElementVariable(arrayName); + } + } + // If the user wants this array AND I don't already have it + // then read in the data + else if (getArray && !haveArray) + { + // How many dimensions is this array + dim = this->GetCellArrayNumberOfComponents(idx); + if (dim == 1) + array = this->ReadCellArray(handle, arrayIdx); + else + array = this->ReadCellVector(handle, arrayIdx, dim); + + // Opps some sort of problem + if (array == NULL) + { + vtkErrorMacro("Problem reading cell array " << this->GetCellArrayName(idx)); + // Do not try loading this again + this->MetaData->SetCellArrayStatus(idx, 0); + + } + else + { + array->SetName(this->GetCellArrayName(idx)); + output->GetCellData()->AddArray(array); + + array->Delete(); + array = NULL; + + if (this->ExodusModel) + { + // So ExodusIIWriter can map names in UGrid back to names in + // Exodus II file. + + char *origName = + vtkExodusReader::StrDupWithNew( + this->MetaData->GetCellArrayOriginalName(arrayIdx)); + char *newName = + vtkExodusReader::StrDupWithNew(this->GetCellArrayName(idx)); + + this->ExodusModel->AddUGridElementVariable(newName, origName, dim); + } + } + } + // The array index needs to be incremented by the dimension + dim = this->GetCellArrayNumberOfComponents(idx); + arrayIdx += dim; + } + +} + +void vtkExodusReader::AddDisplacements(vtkUnstructuredGrid* output) +{ + char arrayName[MAX_STR_LENGTH]; + char arrayNameUpper[MAX_STR_LENGTH]; + int FOUND = 0; + + // Now find the displacement array + strcpy(arrayName, "None"); + for (int idx = 0; idx < this->GetNumberOfPointArrays(); ++idx) + { + // Is this array displacement? + strcpy(arrayName, this->GetPointArrayName(idx)); + this->StringUppercase(arrayName,arrayNameUpper); + if (!strncmp(arrayNameUpper,"DISP",4)) + { + FOUND = 1; + break; + } + } + + // If I did not find displacements then just return + if (!FOUND) return; + + // Create warp vector filter + vtkWarpVector *warp = vtkWarpVector::New(); + + vtkUnstructuredGrid *geom = vtkUnstructuredGrid::New(); + geom->ShallowCopy(output); + + warp->SetInput(geom); + warp->SetInputArrayToProcess( + 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, arrayName); + warp->SetScaleFactor(DisplacementMagnitude); + warp->Update(); + + geom->Delete(); + + // Copy warped mesh and cell/point data to my output + + output->CopyStructure(warp->GetUnstructuredGridOutput()); + output->GetCellData()->PassData(warp->GetUnstructuredGridOutput()->GetCellData()); + output->GetPointData()->PassData(warp->GetUnstructuredGridOutput()->GetPointData()); + + // Delete warp filter + warp->Delete(); + + // Remove displacement field if it's possible the dataset will be + // written out to a new Exodus file later on. Since we've just + // applied displacements to the points, maintaining the displacement array + // will yield incorrect geometry when the output file is read in. + + if (this->ExodusModelMetadata){ + output->GetPointData()->RemoveArray(arrayName); + } +} + + +vtkDataArray *vtkExodusReader::ReadPointVector(int handle, int varIndex, int dim) +{ + // Sanity check + if (dim !=2 && dim!=3) + { + vtkErrorMacro("Error: Only support 2 or 3 dim vectors var_index:" \ + << varIndex << " dim:" << dim<< " file: " << this->FileName); + return NULL; + } + + // Create vector array + vtkFloatArray *vectors = vtkFloatArray::New(); + vectors->SetNumberOfComponents(3); + vectors->SetNumberOfTuples(this->NumberOfUsedNodes); + + // Grab first two arrays + vtkFloatArray *dim1 = (vtkFloatArray*)ReadPointArray(handle,varIndex); + vtkFloatArray *dim2 = (vtkFloatArray*)ReadPointArray(handle,varIndex+1); + + // Do they need a third + vtkFloatArray *dim3 = NULL; + if (dim == 3) + dim3 = (vtkFloatArray*)ReadPointArray(handle,varIndex+2); + + // Okay now set up memory pointers + float *vector_ptr = vectors->GetPointer(0); + float *dim1_ptr = dim1->GetPointer(0); + float *dim2_ptr = dim2->GetPointer(0); + float *dim3_ptr = NULL; if(dim==3) dim3_ptr = dim3->GetPointer(0); + + // Okay now swizzle into vector array + if (dim==2) + { + for(int i=0; iNumberOfUsedNodes; ++i) + { + *vector_ptr++ = *dim1_ptr++; + *vector_ptr++ = *dim2_ptr++; + *vector_ptr++ = 0; + } + } + else + { + for(int i=0; iNumberOfUsedNodes; ++i) + { + *vector_ptr++ = *dim1_ptr++; + *vector_ptr++ = *dim2_ptr++; + *vector_ptr++ = *dim3_ptr++; + } + } + + dim1->Delete(); + dim2->Delete(); + if ( dim3 ) + { + dim3->Delete(); + } + + // Okay all done + return vectors; +} + +vtkDataArray *vtkExodusReader::ReadPointArray(int handle, int varIndex) +{ + // Temp float array + float *exo_array_data; + exo_array_data = new float[this->NumberOfNodesInFile]; + + // Create data array + vtkFloatArray *array = vtkFloatArray::New(); + array->SetNumberOfValues(this->NumberOfUsedNodes); + + // Read in data into temp array (note that Exodus is 1 based) + int error = ex_get_nodal_var (handle, + this->ActualTimeStep+1, + varIndex+1, + this->NumberOfNodesInFile, + exo_array_data); + + // Opps something bad happened + if (error < 0) + { + vtkErrorMacro("Error: " << error << " ex_get_nodal_var timestep:" + << this->ActualTimeStep << " var_index: " << varIndex + << " file: " << this->FileName); + return NULL; + } + + // Okay copy the points that are actually used into the vtk array + int point_index; + for(int i=0; iNumberOfUsedNodes; i++) + { + point_index = this->ReversePointMap->GetValue(i); + array->SetValue(i, exo_array_data[point_index]); + } + + // Clean up temp float array + delete [] exo_array_data; + + + return array; +} + +vtkDataArray *vtkExodusReader::ReadCellVector(int handle, int varIndex, int dim) +{ + // Sanity check + if (dim !=2 && dim!=3) + { + vtkErrorMacro("Error: Only support 2 or 3 dim vectors var_index:" \ + << varIndex << " dim:" << dim<< " file: " << this->FileName); + return NULL; + } + + // Create vector array + vtkFloatArray *vectors = vtkFloatArray::New(); + vectors->SetNumberOfComponents(3); + vectors->SetNumberOfTuples(this->NumberOfUsedElements); + + // Grab first two arrays + vtkFloatArray *dim1 = (vtkFloatArray*)ReadCellArray(handle,varIndex); + vtkFloatArray *dim2 = (vtkFloatArray*)ReadCellArray(handle,varIndex+1); + + // Do they need a third + vtkFloatArray *dim3 = NULL; + if (dim == 3) + dim3 = (vtkFloatArray*)ReadCellArray(handle,varIndex+2); + + // Okay now set up memory pointers + float *vector_ptr = vectors->GetPointer(0); + float *dim1_ptr = dim1->GetPointer(0); + float *dim2_ptr = dim2->GetPointer(0); + float *dim3_ptr = NULL; if(dim==3) dim3_ptr = dim3->GetPointer(0); + + // Okay now swizzle into vector array + if (dim==2) + { + for(int i=0; iNumberOfUsedElements; ++i) + { + *vector_ptr++ = *dim1_ptr++; + *vector_ptr++ = *dim2_ptr++; + *vector_ptr++ = 0; + } + } + else + { + for(int i=0; iNumberOfUsedElements; ++i) + { + *vector_ptr++ = *dim1_ptr++; + *vector_ptr++ = *dim2_ptr++; + *vector_ptr++ = *dim3_ptr++; + } + } + + dim1->Delete(); + dim2->Delete(); + if ( dim3 ) + { + dim3->Delete(); + } + + // Okay all done + return vectors; +} + +void vtkExodusReader::FixMetadataTruthTable(int *table, int len) +{ + if (this->ExodusModelMetadata && this->ExodusModel) + { + // vtkModelMetadata will free table when it is destroyed + + int *newtable = new int [len]; + memcpy(newtable, table, len * sizeof(int)); + + this->ExodusModel->GetModelMetadata()->SetElementVariableTruthTable(newtable); + } +} + +// Read in the cell array specified by index 'varIndex' +vtkDataArray *vtkExodusReader::ReadCellArray(int handle, int varIndex) +{ + int i; + int error; + int blockIdx; + + // Create the data array + vtkFloatArray *array = vtkFloatArray::New(); + array->SetNumberOfValues(this->NumberOfUsedElements); + float *arrayPtr = array->GetPointer(0); + int nblocks = this->MetaData->GetNumberOfBlocks(); + + // Loop through the blocks. + for (blockIdx=0; blockIdx < nblocks; ++blockIdx) + { + // Do we read this block? + if (this->MetaData->GetBlockStatus(blockIdx)==0) + { + continue; + } + + // Get number of elements in block + int numBlockElements = this->MetaData->GetNumElementsInBlock(blockIdx); + + // Truth Table may say no variables on this block for this variable + int cell_arrays = this->MetaData->GetOriginalNumberOfCellArrays(); + int truthTableIdx = + this->MetaData->GetSortedOrder(blockIdx)*cell_arrays + varIndex; + + if (this->CellVarTruthTable->GetValue(truthTableIdx) == 1) + { + error = + ex_get_elem_var (handle, this->ActualTimeStep+1, varIndex+1, + this->MetaData->GetBlockId(blockIdx), numBlockElements, + arrayPtr); + + if (error < 0) + { + vtkWarningMacro("Warning: Truth Table indicated that cell variable " << + this->GetCellArrayName(varIndex) << + " appears in block " << this->MetaData->GetBlockId(blockIdx) << + ",\nhowever it is not there. " + "Truth table has been modified (in VTK memory only)."); + + // Assume the truth table is wrong. (Because we have seen this occur.) + // Change our table and change the one saved in the metadata. + this->CellVarTruthTable->SetValue(truthTableIdx, 0); + this->FixMetadataTruthTable(this->CellVarTruthTable->GetPointer(0), + nblocks * cell_arrays); + } + } + + if (this->CellVarTruthTable->GetValue(truthTableIdx) == 0) + { + for(i=0; iInsertNextValue(0); + } + + + // AOK so return array + return array; +} + + +int vtkExodusReader::GetExtraCellCountForNodeSideSets() +{ + int i; + int count=0; + + // Count number of additional 'cells' for nodesets + for (i=0; i < this->GetNumberOfNodeSets(); ++i) + { + // Do we read this node set? + if (this->MetaData->GetNodeSetStatus(i)) + { + count += this->MetaData->GetNodeSetSize(i); + } + } + + // Count number of additional 'cells' for sidesets + for (i=0; i < this->GetNumberOfSideSets(); ++i) + { + // Do we read this node set? + if (this->MetaData->GetSideSetStatus(i)) + { + count += this->MetaData->GetSideSetSize(i); + } + } + + + // Return number of additional cell values needed + // to accommodate scalar fields count + return count; + } + +//---------------------------------------------------------------------------- +void vtkExodusReader::GenerateExtraArrays(vtkUnstructuredGrid* output) +{ + vtkIntArray *array; + int count; + int blockId; + int i, j, numBlockElem; + int haveArray, getArray; + + /////////////////////////////////////// + // Get block array + /////////////////////////////////////// + + // Do I already have this array? + if (output->GetPointData()->GetArray( this->GetBlockIdArrayName() ) != NULL) + haveArray=1; + else + haveArray=0; + + // Does the user want this array? + getArray = this->GenerateBlockIdCellArray; + + // If I have the array and the user DOESN'T want it + // then remove the array from the output + if (haveArray && !getArray) + { + output->GetPointData()->RemoveArray( this->GetBlockIdArrayName() ); + } + // If the user wants this array AND I don't already have it + // then read in the data + else if (getArray && !haveArray) + { + array = vtkIntArray::New(); + array->SetNumberOfValues(this->NumberOfUsedElements); + count = 0; + for (i=0; i < this->MetaData->GetNumberOfBlocks(); ++i) + { + // Do we read this block? + if (this->MetaData->GetBlockStatus(i)==0) + continue; + + numBlockElem = this->MetaData->GetNumElementsInBlock(i); + blockId = this->MetaData->GetBlockId(i); + for (j = 0; j < numBlockElem; ++j) + { + array->SetValue(count++,blockId); + } + } + // Padding cell arrays to have 'some' value for the addition + // of nodesets and sidesets + for(i=0;iInsertNextValue(0); + } + array->SetName( this->GetBlockIdArrayName() ); + output->GetCellData()->AddArray(array); + + // Block IDs will be the default cell data + output->GetCellData()->SetScalars(array); + array->Delete(); + array = NULL; + } + + /////////////////////////////////////// + // Get node id array + /////////////////////////////////////// + + // Do I already have this array? + if ( output->GetPointData()->GetArray( + this->GetGlobalNodeIdArrayName() ) != NULL) + { + haveArray = 1; + } + else + { + haveArray = 0; + } + + // Does the user want this array? + getArray = this->GenerateGlobalNodeIdArray; + + // If I have the array and the user DOESN'T want it + // then remove the array from the output + if (haveArray && !getArray) + { + output->GetPointData()->RemoveArray( this->GetGlobalNodeIdArrayName() ); + } + // If the user wants this array AND I don't already have it + // then read in the data + else if (getArray && !haveArray) + { + // Temp int array + int *exo_array_data; + exo_array_data = new int[this->NumberOfNodesInFile]; + + // Temp vtk array + array = vtkIntArray::New(); + array->SetNumberOfValues(this->NumberOfUsedNodes); + + // Get the data into the temp int array + ex_get_node_num_map(this->CurrentHandle, exo_array_data); + + // Okay copy the points that are actually used into the vtk array + int point_index; + for (i=0; iNumberOfUsedNodes; i++) + { + point_index = this->ReversePointMap->GetValue(i); + array->SetValue(i, exo_array_data[point_index]); + } + + // Clean up temp int array + delete [] exo_array_data; + + // Set up array and 'give' to output + array->SetName( this->GetGlobalNodeIdArrayName() ); + output->GetPointData()->AddArray(array); + + // Delete my copy of the array + array->Delete(); + array = NULL; + } + + /////////////////////////////////////// + // Get element id array + /////////////////////////////////////// + + // Do I already have this array? + if (output->GetPointData()->GetArray( + this->GetGlobalElementIdArrayName() ) != NULL) + { + haveArray=1; + } + else + { + haveArray=0; + } + + // Does the user want this array? + getArray = this->GenerateGlobalElementIdArray; + + // If I have the array and the user DOESN'T want it + // then remove the array from the output + if (haveArray && !getArray) + { + output->GetPointData()->RemoveArray( this->GetGlobalElementIdArrayName() ); + } + // If the user wants this array AND I don't already have it + // then read in the data + else if (getArray && !haveArray) + { + int nblocks = this->GetNumberOfBlockArrays(); + int nblocksUsed = 0; + + for (i=0; iGetBlockArrayStatus(i) == 1) + { + nblocksUsed++; + } + } + if (!this->GlobalElementIdCache) + { + int *tmp = new int [this->NumberOfElementsInFile]; + ex_get_elem_num_map(this->CurrentHandle, tmp); + this->GlobalElementIdCache = tmp; + } + + int *idList = new int [this->NumberOfUsedElements]; + + if (nblocksUsed < nblocks) + { + int *from = this->GlobalElementIdCache; + int *to = idList; + + for (i=0; iGetBlockArrayStatus(i); + int bsize = this->GetNumberOfElementsInBlock(i); + + if (used) + { + memcpy(to, from, bsize * sizeof(int)); + to += bsize; + } + from += bsize; + } + } + else + { + memcpy(idList, this->GlobalElementIdCache, + this->NumberOfUsedElements * sizeof(int)); + } + + array = vtkIntArray::New(); + array->SetArray(idList, this->NumberOfUsedElements, 0); + array->SetName( this->GetGlobalElementIdArrayName() ); + + // Padding cell arrays to have 'some' value for the addition + // of nodesets and sidesets + for(i=0;iInsertNextValue(0); + } + + output->GetCellData()->AddArray(array); + array->Delete(); + array = NULL; + } + // **KEN** I think we should be done with the ReversePointMap. Should we + // delete it here? +} + + + +//---------------------------------------------------------------------------- +void vtkExodusReader::PrintSelf(ostream& os, vtkIndent indent) +{ + int idx; + + this->Superclass::PrintSelf(os,indent); + + if (this->GenerateBlockIdCellArray) + { + os << indent << "GenerateBlockIdCellArray: On\n"; + } + else + { + os << indent << "GenerateBlockIdCellArray: Off\n"; + } + + if (this->GenerateGlobalElementIdArray) + { + os << indent << "GenerateGlobalElementIdArray: On\n"; + } + else + { + os << indent << "GenerateGlobalElementIdArray: Off\n"; + } + + if (this->GenerateGlobalNodeIdArray) + { + os << indent << "GenerateGlobalNodeIdArray: On\n"; + } + else + { + os << indent << "GenerateGlobalNodeIdArray: Off\n"; + } + + if (this->PackExodusModelOntoOutput ) + { + os << indent << "PackExodusModelOntoOutput: On\n"; + } + else + { + os << indent << "PackExodusModelOntoOutput: Off\n"; + } + + if (this->ApplyDisplacements) + { + os << indent << "ApplyDisplacements: On\n"; + } + else + { + os << indent << "ApplyDisplacements: Off\n"; + } + + if (this->ExodusModelMetadata) + { + os << indent << "ExodusModelMetadata: On\n"; + } + else + { + os << indent << "ExodusModelMetadata: Off\n"; + } + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "XML File Name: " + << (this->XMLFileName ? this->XMLFileName : "(none)") << "\n"; + os << indent << "Title: " + << (this->Title ? this->Title : "(none)") << "\n"; + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; + os << indent << "NumberOfUsedNodes: " << this->NumberOfUsedNodes << "\n"; + os << indent << "NumberOfNodesInFile: " << this->NumberOfNodesInFile << "\n"; + os << indent << "NumberOfUsedElements: " << this->NumberOfUsedElements << "\n"; + os << indent << "NumberOfElementsInFile: " << this->NumberOfElementsInFile << "\n"; + os << indent << "NumberOfBlocks: " << this->NumberOfBlocks << "\n"; + for (idx = 0; idx < this->NumberOfBlocks; ++idx) + { + os << indent << " " << this->MetaData->GetNumElementsInBlock(idx) + << " elements in block " << this->MetaData->GetBlockId(idx) << "\n"; + } + os << indent << "NumberOfTimeSteps: " << this->NumberOfTimeSteps << "\n"; + os << indent << "NumberOfPointArrays: " << this->GetNumberOfPointArrays() << "\n"; + for (idx = 0; idx < this->GetNumberOfPointArrays(); ++idx) + { + os << indent << " " << this->GetPointArrayName(idx); + if (this->GetPointArrayNumberOfComponents(idx) != 1) + { + os << " " << this->GetPointArrayNumberOfComponents(idx) << " components"; + } + if (this->GetPointArrayStatus(idx) == 0) + { + os << " do not load"; + } + os << endl; + } + os << indent << "NumberOfCellArrays: " << this->GetNumberOfCellArrays() << "\n"; + for (idx = 0; idx < this->GetNumberOfCellArrays(); ++idx) + { + os << indent << " " << this->GetCellArrayName(idx); + if (this->GetCellArrayNumberOfComponents(idx) != 1) + { + os << " " << this->GetCellArrayNumberOfComponents(idx) << " components"; + } + if (this->GetCellArrayStatus(idx) == 0) + { + os << " do not load"; + } + os << endl; + } + os << indent << "NumberOfSideSets: " << this->NumberOfSideSets << "\n"; + os << indent << "NumberOfNodeSets: " << this->NumberOfNodeSets << "\n"; + os << indent << "TimeStep: " << this->TimeStep << endl; + os << indent << "TimeStepRange: " << this->TimeStepRange[0] << " " << this->TimeStepRange[1] << endl; + os << indent << "DisplacementMagnitude: " << this->DisplacementMagnitude << "\n"; + os << indent << "DisplayType: " << this->DisplayType << "\n"; +} + + +void vtkExodusReader::CloseCurrentFile() +{ + int error; + error = ex_close(this->CurrentHandle); + if (error < 0) + { + vtkErrorMacro("Error: " << error << " calling ex_close " << this->FileName); + } + this->CurrentHandle = -1; +} + +int vtkExodusReader::StringsEqual(const char* s1, char* s2) +{ + int same = 0; + + if ((s1 == NULL) && (s2 == NULL)) + { + same = 1; + } + else if (s1 && s2 && (strcmp(s1, s2) == 0)) + { + same = 1; + } + + return same; +} + +void vtkExodusReader::StringUppercase(const char* str, char* upperstr) +{ + int len = 0; + if ( str ) + { + len = strlen(str); + for (int i=0; iPointMap->SetNumberOfValues(num_points); + for(int i=0; iPointMap->SetValue(i, -1); + } + + // I have used zero nodes at this time + this->NumberOfUsedNodes = 0; + + // Also allocate the reverse point map + this->ReversePointMap->SetNumberOfValues(num_points); +} + +int vtkExodusReader::GetPointMapIndex(int point_id) +{ + // We may not have this point + if (this->PointMap->GetValue(point_id) == -1) + { + this->PointMap->SetValue(point_id, this->NumberOfUsedNodes); + + // Store reverse lookup + this->ReversePointMap->SetValue(this->NumberOfUsedNodes, point_id); + + // Increment the number of used nodes + this->NumberOfUsedNodes++; + + // Return the value of the stored index + return this->NumberOfUsedNodes-1; + } + + // We have the point so return it's mapped value + return this->PointMap->GetValue(point_id); +} + +void vtkExodusReader::SetAllAssemblyArrayStatus( int status ) +{ + this->MetaData->SetArrayStatusInitValue( vtkExodusReader::ASSEMBLY, status ); + int numVars = this->GetNumberOfAssemblyArrays(); + for ( int id=0;idMetaData->SetArrayStatusInitValue( vtkExodusReader::BLOCK, status ); + int numVars = this->GetNumberOfBlockArrays(); + for ( int id=0;idMetaData->SetArrayStatusInitValue( vtkExodusReader::CELL, status ); + int numVars = this->GetNumberOfCellArrays(); + for ( int id=0;idMetaData->SetArrayStatusInitValue( vtkExodusReader::HIERARCHY, status ); + int numVars = this->GetNumberOfHierarchyArrays(); + for ( int id=0;idMetaData->SetArrayStatusInitValue( vtkExodusReader::MATERIAL, status ); + int numVars = this->GetNumberOfMaterialArrays(); + for ( int id=0;idSetMaterialArrayStatus( id, status ); + } +} + +void vtkExodusReader::SetAllPartArrayStatus( int status ) +{ + this->MetaData->SetArrayStatusInitValue( vtkExodusReader::PART, status ); + int numVars = this->GetNumberOfPartArrays(); + for ( int id=0;idSetPartArrayStatus( id, status ); + } +} + +void vtkExodusReader::SetAllPointArrayStatus( int status ) +{ + this->MetaData->SetArrayStatusInitValue( vtkExodusReader::POINT, status ); + int numVars = this->GetNumberOfPointArrays(); + for ( int id=0;idSetPointArrayStatus( id, status ); + } +} + +char *vtkExodusReader::StrDupWithNew(const char *s) +{ + char *newstr = NULL; + + if (s) + { + int len = strlen(s); + if (len == 0) + { + newstr = new char [1]; + newstr[0] = '\0'; + } + else + { + newstr = new char [len + 1]; + strcpy(newstr, s); + } + } + + return newstr; +} + +void vtkExodusReader::SetArrayStatus ( vtkExodusReader::ArrayType type, + const char *name, int flag ) +{ + switch (type) + { + case vtkExodusReader::CELL: + this->SetCellArrayStatus( name, flag ); + break; + case vtkExodusReader::POINT: + this->SetPointArrayStatus( name, flag ); + break; + case vtkExodusReader::BLOCK: + this->SetBlockArrayStatus( name, flag ); + break; + case vtkExodusReader::PART: + this->SetPartArrayStatus( name, flag ); + break; + case vtkExodusReader::MATERIAL: + this->SetMaterialArrayStatus( name, flag ); + break; + case vtkExodusReader::ASSEMBLY: + this->SetAssemblyArrayStatus( name, flag ); + break; + case vtkExodusReader::HIERARCHY: + this->SetHierarchyArrayStatus( name, flag ); + break; + case vtkExodusReader::NUM_ARRAY_TYPES: + case vtkExodusReader::UNKNOWN_TYPE: + default: + break; + } +} + +void vtkExodusReader::SetAllArrayStatus ( vtkExodusReader::ArrayType type, + int flag ) +{ + switch (type) + { + case vtkExodusReader::CELL: + this->SetAllCellArrayStatus( flag ); + break; + case vtkExodusReader::POINT: + this->SetAllPointArrayStatus( flag ); + break; + case vtkExodusReader::BLOCK: + this->SetAllBlockArrayStatus( flag ); + break; + case vtkExodusReader::PART: + this->SetAllPartArrayStatus( flag ); + break; + case vtkExodusReader::MATERIAL: + this->SetAllMaterialArrayStatus( flag ); + break; + case vtkExodusReader::ASSEMBLY: + this->SetAllAssemblyArrayStatus( flag ); + break; + case vtkExodusReader::HIERARCHY: + this->SetAllHierarchyArrayStatus( flag ); + break; + case vtkExodusReader::NUM_ARRAY_TYPES: + case vtkExodusReader::UNKNOWN_TYPE: + default: + break; + } +} + + +int vtkExodusReader::GetArrayStatus ( vtkExodusReader::ArrayType type, + const char *name ) +{ + switch (type) + { + case vtkExodusReader::CELL: + return this->GetCellArrayStatus( name ); + break; + case vtkExodusReader::POINT: + return this->GetPointArrayStatus( name ); + break; + case vtkExodusReader::BLOCK: + return this->GetBlockArrayStatus( name ); + break; + case vtkExodusReader::PART: + return this->GetPartArrayStatus( name ); + break; + case vtkExodusReader::MATERIAL: + return this->GetMaterialArrayStatus( name ); + break; + case vtkExodusReader::ASSEMBLY: + return this->GetAssemblyArrayStatus( name ); + break; + case vtkExodusReader::HIERARCHY: + return this->GetHierarchyArrayStatus( name ); + break; + case vtkExodusReader::NUM_ARRAY_TYPES: + case vtkExodusReader::UNKNOWN_TYPE: + default: + return 0; + break; + } +} + +int vtkExodusReader::GetNumberOfArrays ( vtkExodusReader::ArrayType type ) +{ + switch (type) + { + case vtkExodusReader::CELL: + return this->GetNumberOfCellArrays(); + break; + case vtkExodusReader::POINT: + return this->GetNumberOfPointArrays(); + break; + case vtkExodusReader::BLOCK: + return this->GetNumberOfBlockArrays(); + break; + case vtkExodusReader::PART: + return this->GetNumberOfPartArrays(); + break; + case vtkExodusReader::MATERIAL: + return this->GetNumberOfMaterialArrays(); + break; + case vtkExodusReader::ASSEMBLY: + return this->GetNumberOfAssemblyArrays(); + break; + case vtkExodusReader::HIERARCHY: + return this->GetNumberOfHierarchyArrays(); + break; + case vtkExodusReader::NUM_ARRAY_TYPES: + case vtkExodusReader::UNKNOWN_TYPE: + default: + return 0; + break; + } +} + +const char*vtkExodusReader::GetArrayName ( vtkExodusReader::ArrayType type, + int id ) +{ + switch (type) + { + case vtkExodusReader::CELL: + return this->GetCellArrayName( id ); + break; + case vtkExodusReader::POINT: + return this->GetPointArrayName( id ); + break; + case vtkExodusReader::BLOCK: + return this->GetBlockArrayName( id ); + break; + case vtkExodusReader::PART: + return this->GetPartArrayName( id ); + break; + case vtkExodusReader::MATERIAL: + return this->GetMaterialArrayName( id ); + break; + case vtkExodusReader::ASSEMBLY: + return this->GetAssemblyArrayName( id ); + break; + case vtkExodusReader::HIERARCHY: + return this->GetHierarchyArrayName( id ); + break; + case vtkExodusReader::NUM_ARRAY_TYPES: + case vtkExodusReader::UNKNOWN_TYPE: + default: + return NULL; + break; + } +} + +void vtkExodusReader::SetXMLFileName(const char *filename) +{ + // NULL or "" then just return + if (!filename || !strcmp(filename,"")) + { + return; + } + else + { + XMLFileName = StrDupWithNew(filename); // Memory leak :) + } + + this->Modified(); + //cout << "Exodus XML file set to " << XMLFileName << endl; +} + +// Had to add this because displacement vector names had spaces +// following them (dispx{space}, dispy{space}, dispz{space}). They +// didn't get made into a vector, so displacement was garbage. + +void vtkExodusReader::RemoveBeginningAndTrailingSpaces(char **names, int len) +{ + int i, j; + + for (i=0; iOpenCurrentFile() ) + { + int numTimesteps = this->GetNumberOfTimeSteps(); + result->SetNumberOfComponents( 1 ); + result->SetNumberOfTuples( numTimesteps ); + // result->Initialize(); + result->SetName( vName ); + float *memory = result->GetPointer( 0 ); + + if ((strcmp(vType, "CELL") == 0) || (strcmp(vType, "cell") == 0) ) + { + int varid = GetCellArrayID( vName ); + ex_get_elem_var_time( this->CurrentHandle, varid, itemID, 1, + numTimesteps, memory ); + retVal = 1; + } + else if ((strcmp(vType, "POINT") == 0) || (strcmp(vType, "point") == 0) ) + { + int varid = GetPointArrayID( vName ); + ex_get_nodal_var_time( this->CurrentHandle, varid, itemID, 1, + numTimesteps, memory ); + retVal = 1; + } + else + { + } + this->CloseCurrentFile(); + } + + if ( retVal == 0 ) + { + // in case there was a problem, we initialize the return data, because + // the result is expected to reflect the data we got + result->Initialize(); + result->SetName( vName ); + } + + return retVal; +} + +void vtkExodusReader::GetAllTimes(vtkInformationVector *outputVector) +{ + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int numTimesteps = this->GetNumberOfTimeSteps(); + if (numTimesteps == 0) + { + return; + } + float* ftimeSteps = new float[numTimesteps]; + ex_get_all_times( this->CurrentHandle, ftimeSteps ); + double* timeSteps = new double[numTimesteps]; + for (int i=0; iSet(vtkStreamingDemandDrivenPipeline::TIME_STEPS(), + timeSteps, + numTimesteps); + delete[] timeSteps; + delete[] ftimeSteps; +} + +int vtkExodusReader::GetPointArrayID( const char *name ) +{ + int numArrays = this->GetNumberOfPointArrays(); + for ( int i=0;iGetPointArrayName( i ) ) == 0 ) + { + return i; + } + } + return -1; +} + +int vtkExodusReader::GetCellArrayID( const char *name ) +{ + int numArrays = this->GetNumberOfCellArrays(); + for ( int i=0;iGetCellArrayName( i ) ) == 0 ) + { + return i; + } + } + return -1; +} + +int vtkExodusReader::GetBlockArrayID( const char *name ) +{ + int numArrays = this->GetNumberOfBlockArrays(); + for ( int i=0;iGetBlockArrayName( i ) ) == 0 ) + { + return i; + } + } + return -1; +} + +int vtkExodusReader::GetPartArrayID( const char *name ) +{ + int numArrays = this->GetNumberOfPartArrays(); + for ( int i=0;iGetPartArrayName( i ) ) == 0 ) + { + return i; + } + } + return -1; +} + +int vtkExodusReader::GetMaterialArrayID( const char *name ) +{ + int numArrays = this->GetNumberOfMaterialArrays(); + for ( int i=0;iGetMaterialArrayName( i ) ) == 0 ) + { + return i; + } + } + return -1; +} + +int vtkExodusReader::OpenCurrentFile() +{ + int result = 0; + + // is there a file open now? + if ( this->CurrentHandle == -1 && this->FileName ) + { + this->CurrentHandle = ex_open( this->FileName, EX_READ, + &(this->ExodusCPUWordSize), + &(this->ExodusIOWordSize), + &(this->ExodusVersion) + ); + + // Problem opening the file + if (this->CurrentHandle < 0) + { + vtkErrorMacro("Problem with the ex_open function for file " << + this->FileName); + this->SetTitle( 0 ); + this->SetCurrentFileName( NULL ); + } + else + { + this->SetCurrentFileName( this->GetFileName() ); + result = 1; + } + } + + return result; +} + +//---------------------------------------------------------------------------- +//begin USE_EXO_DSP_FILTERS + +int vtkExodusReader::GetNumberOfVariableArrays() +{ + return( GetNumberOfPointArrays()+GetNumberOfCellArrays() ); +}; + +const char *vtkExodusReader::GetVariableArrayName(int a_which) +{ + if(a_whichDSPFilteringIsEnabled=1; + if(!this->DSPFilters && this->GetNumberOfBlockArrays() ) + { + this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()]; + for(int i=0;iGetNumberOfBlockArrays();i++) + { + this->DSPFilters[i] = vtkDSPFilterGroup::New(); + } + } +}; + +void vtkExodusReader::AddFilter(vtkDSPFilterDefinition *a_filter) +{ + //printf("vtkExodusReader(%p)::addFilter %s -> %s numDSPFilters=%d GetNumberOfBlockArrays()=%d\n",this, + // a_filter->GetInputVariableName(),a_filter->GetOutputVariableName(), + // this->DSPFilters[0]->GetNumFilters(), this->GetNumberOfBlockArrays() ); + + this->DSPFilteringIsEnabled = 1;//Is this var necessary any more? + + //allocate if necessary.....is this necessary? + if(!this->DSPFilters && this->GetNumberOfBlockArrays()) + { + this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()]; + for(int i=0;iGetNumberOfBlockArrays();i++) + { + this->DSPFilters[i] = vtkDSPFilterGroup::New(); + } + } + if(!this->DSPFilters) return; + + for(int i=0;iGetNumberOfBlockArrays();i++) + { + this->DSPFilters[i]->AddFilter(a_filter); + } + + //printf("after vtkExodusReader(%p)::addFilter %s -> %s numDSPFilters=%d GetNumberOfBlockArrays()=%d\n",this, + //a_filter->GetInputVariableName(),a_filter->GetOutputVariableName(), + //this->DSPFilters[0]->GetNumFilters(), this->GetNumberOfBlockArrays() ); + + this->Modified();//need to do this to cause the new filter to be calculated +}; + +//---------------------------------------------------------------------------- +void vtkExodusReader::RemoveFilter(char *a_outputVariableName) +{ + //allocate if necessary.....is this necessary? + if(!this->DSPFilters && this->GetNumberOfBlockArrays()) + { + this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()]; + for(int i=0;iGetNumberOfBlockArrays();i++) + { + this->DSPFilters[i] = vtkDSPFilterGroup::New(); + } + } + if(!this->DSPFilters) return; + + for(int i=0;iGetNumberOfBlockArrays();i++) + { + this->DSPFilters[i]->RemoveFilter(a_outputVariableName); + } + + this->Modified();//need to do this to cause the old filter to be removed +} + +void vtkExodusReader::StartAddingFilter() +{ + this->AddingFilter->Clear(); +} +void vtkExodusReader::AddFilterInputVar(char *name) +{ + this->AddingFilter->SetInputVariableName( name ); +} +void vtkExodusReader::AddFilterOutputVar(char *name) +{ + this->AddingFilter->SetOutputVariableName( name ); +} +void vtkExodusReader::AddFilterNumeratorWeight(double weight) +{ + this->AddingFilter->PushBackNumeratorWeight(weight); +} +void vtkExodusReader::AddFilterForwardNumeratorWeight(double weight) +{ + this->AddingFilter->PushBackForwardNumeratorWeight(weight); +} +void vtkExodusReader::AddFilterDenominatorWeight(double weight) +{ + this->AddingFilter->PushBackDenominatorWeight(weight); +} +void vtkExodusReader::FinishAddingFilter() +{ + this->AddFilter(AddingFilter); +} + +vtkExodusReader::ArrayType vtkExodusReader::GetArrayTypeID( const char *type ) +{ + if ( strcmp( type, "CELL" ) == 0 ) + { + return vtkExodusReader::CELL; + } + else if ( strcmp( type, "POINT" ) == 0 ) + { + return vtkExodusReader::POINT; + } + else if ( strcmp( type, "BLOCK" ) == 0 ) + { + return vtkExodusReader::BLOCK; + } + else if ( strcmp( type, "PART" ) == 0 ) + { + return vtkExodusReader::PART; + } + else if ( strcmp( type, "MATERIAL" ) == 0 ) + { + return vtkExodusReader::MATERIAL; + } + else if ( strcmp( type, "ASSEMBLY" ) == 0 ) + { + return vtkExodusReader::ASSEMBLY; + } + else if ( strcmp( type, "HIERARCHY" ) == 0 ) + { + return vtkExodusReader::HIERARCHY; + } + else + { + return vtkExodusReader::UNKNOWN_TYPE; + } +} + +void vtkExodusReader::GetDSPOutputArrays(int handle, vtkUnstructuredGrid* output) +{ + + //printf("\nvtkExodusReader(%p)::GetDSPOutputArrays numDSPFilters=%d numblocks=%d isenabled=%d numvars=%d num pt arrays=%d num cell arrays=%d\n\n", + // this,this->DSPFilters[0]->GetNumFilters(),this->GetNumberOfBlockArrays(), + // this->DSPFilteringIsEnabled,this->GetNumberOfVariableArrays(), + // this->GetOutput()->GetPointData()->GetNumberOfArrays(), this->GetOutput()->GetCellData()->GetNumberOfArrays() ); + + //allocate if necessary.....is this necessary? + if(!this->DSPFilters && this->GetNumberOfBlockArrays()) + { + this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()]; + for(int i=0;iGetNumberOfBlockArrays();i++) + { + this->DSPFilters[i] = vtkDSPFilterGroup::New(); + } + } + + if(this->DSPFilteringIsEnabled && this->DSPFilters) + { + //printf("in vtkExodusReader::GetDSPOutputArrays DSPFilters IS allocated\n"); + + int l_numPointVarInstancesLoaded=0; + int l_numCellVarInstancesLoaded=0; + int i,j; + + //GET ALL THE INPUTS + //This is a brute force approach, but will never be problem-sized + for(int l_whichVar=0; + l_whichVarGetNumberOfVariableArrays(); + l_whichVar++) + { + const char *l_name = this->GetVariableArrayName(l_whichVar); + for(int l_whichTime=0; + l_whichTimeGetNumberOfTimeSteps(); + l_whichTime++) + { + //assuming all blocks' filters have same needs + int l_needed = + this->DSPFilters[0]->IsThisInputVariableInstanceNeeded( + l_name,l_whichTime,this->ActualTimeStep); + if(l_needed) + { + //cannot assume all blocks' filters have the same cache, + //because a block may have been turned off before + for(i=0;iGetNumberOfBlockArrays();i++) + { + //XXX STILL NEED TO HANDLE TRUTH TABLES FOR SHIP.EXO + if( this->GetBlockArrayStatus(i) ) + { + int l_cached = + this->DSPFilters[i]->IsThisInputVariableInstanceCached( + l_name,l_whichTime); + if(!l_cached) + { + //Get the type of var, and the index of var + int l_varIndex=-1; + int l_pointArrayIndex=0, l_cellArrayIndex=0;//this is confusing + int l_isPointArray=0; + for(j=0;jGetNumberOfPointArrays();j++) + { + if(!strcmp(this->GetPointArrayName(j),l_name)) + { + l_varIndex=j; + l_isPointArray=1; + break; + } + l_pointArrayIndex += this->GetPointArrayNumberOfComponents(j); + } + for(j=0;jGetNumberOfCellArrays();j++) + { + if(!strcmp(this->GetCellArrayName(j),l_name)) + { + if(l_varIndex>=0) + { + vtkErrorMacro( + "Apparently there are cell and point vars with same name: " + << l_name); + break; + } + l_varIndex=j; + l_isPointArray=0; + break; + } + l_cellArrayIndex += this->GetCellArrayNumberOfComponents(j); + } + if(l_varIndex<0) + { + vtkErrorMacro( + "Cant find cell or point vars with name: " << l_name); + break; + } + + + + if(l_isPointArray) + { + //Cant use l_varIndex here, because the output's + // 'Point Data' may + //not have all the vars that the actual input Point Data has + vtkDataArray *l_array=output->GetPointData()->GetArray(l_name); + + if(!l_array) + { + int l_dim = + this->GetPointArrayNumberOfComponents(l_varIndex); + + if (l_dim == 1) + l_array = this->ReadPointArray(handle, l_pointArrayIndex); + else + l_array = this->ReadPointVector( + handle, l_pointArrayIndex, l_dim); + } + if(!l_array) + { + vtkErrorMacro("Cant get point array: " << l_name); + break; + } + + if(!l_array->GetNumberOfComponents() || + !l_array->GetNumberOfTuples()) + { + vtkErrorMacro("Zero sized point array: " << l_name); + break; + } + + + int l_type = l_array->GetDataType(); + if( l_type!=VTK_FLOAT) + { + printf("vtkExodusReader::GetDSPOutputArrays can only do " + "floats for now (type=%d)\n",l_type); + } + else + { + vtkFloatArray *l_floatArray = + static_cast (l_array); + this->DSPFilters[i]->AddInputVariableInstance( + l_name,l_whichTime,l_floatArray); + + l_numPointVarInstancesLoaded++; + } + + + //l_array->Delete(); //DONT DELETE HERE 26aug + + /*END OF POINT ARRAY PART*/ + } + else + { + //BEGIN CELL ARRAY PART + //Cant use l_varIndex here, because the output's 'Point Data' may + //not have all the vars that the actual input Point Data has + vtkDataArray *l_array = + output->GetCellData()->GetArray(l_name); + if(!l_array) + { + int l_dim = this->GetCellArrayNumberOfComponents(l_varIndex); + + if (l_dim == 1) + l_array = this->ReadCellArray(handle, l_cellArrayIndex); + else + l_array = + this->ReadCellVector(handle, l_cellArrayIndex, l_dim); + } + if(!l_array) + { + vtkErrorMacro("Cant get cell array: " << l_name); + break; + } + + if(!l_array->GetNumberOfComponents() || + !l_array->GetNumberOfTuples()) + { + vtkErrorMacro("Zero sized cell array: " << l_name); + break; + } + + + + int l_type = l_array->GetDataType(); + if( l_type!=VTK_FLOAT) + { + printf("vtkExodusReader::GetDSPOutputArrays can only " + "do floats for now (type=%d)\n",l_type); + } + else + { + vtkFloatArray *l_floatArray = + static_cast (l_array); + this->DSPFilters[i]->AddInputVariableInstance( + l_name,l_whichTime,l_floatArray); + + l_numCellVarInstancesLoaded++; + } + + + //l_array->Delete(); //DONT DELETE HERE 26aug + + /*END OF CELL ARRAY PART*/ + + } + } + //else printf("...vtkExodusReader DSP FILTERING not loading time %d %s for block %d of %d ALREADY CACHED\n",l_whichTime,l_name,i,this->GetNumberOfBlockArrays()); + + } + //else printf("...vtkExodusReader DSP FILTERING time %d %s for block %d of %d HAS 0 STATUS\n",l_whichTime,l_name,i,this->GetNumberOfBlockArrays()); + } + } + //else printf("...vtkExodusReader DSP FILTERING time %d %s NOT NEEDED\n",l_whichTime,l_name); + } + } + printf("vtkExodusReader::GetDSPOutputArrays() read %d dsp POINT " + "input variable instances\n",l_numPointVarInstancesLoaded); + printf("vtkExodusReader::GetDSPOutputArrays() read %d dsp CELL " + "input variable instances\n",l_numCellVarInstancesLoaded); + + //CALCULATE THE OUTPUTS + int l_numCalculated=0; + int l_numFilters = (int) this->DSPFilters[0]->GetNumFilters(); + for(i=0;iGetNumberOfBlockArrays();i++) + { + for(j=0;jGetNumberOfPointArrays();l_var++) + { + if(!strcmp(this->GetPointArrayName(l_var), + this->DSPFilters[i]->GetInputVariableName(j) )) + { + l_isCellVar=0; + break; + } + } + + vtkFloatArray *l_array=NULL; + if( this->GetBlockArrayStatus(i) ) + { + l_array = this->DSPFilters[i]->GetOutput( + j, this->ActualTimeStep, l_numCalculated ); + } + + + + if(l_array) + { + + +#if 0 //get the min/max and print it out + int l_datatype = l_array->GetDataType(); + if( l_datatype==VTK_FLOAT) + { + for(int l_comp=0;l_compGetNumberOfComponents();l_comp++) + { + float l_min,l_max; + float *l_data = (float *)l_array->GetVoidPointer(0); + + for(int l_tup=0;l_tupGetNumberOfTuples();l_tup++) + { + float l_val = + l_data[l_tup*l_array->GetNumberOfComponents()+l_comp]; + if(!l_tup) + { + l_min=l_max=l_val; + } + else if(l_min>l_val) + { + l_min=l_val; + } + else if(l_maxGetPointData()->AddArray(l_array); + //printf("added dsp point var block %d\n",i); + } + else + { + output->GetCellData()->AddArray(l_array); + //printf("added dsp cell var block %d\n",i); + } + } + + //printf("block %d AFTER DSP num pt arrays = %d, num cell arrays = %d num pts=%d num cells=%d\n", i, + // output->GetPointData()->GetNumberOfArrays(), output->GetCellData()->GetNumberOfArrays(), + // output->GetPoints()->GetNumberOfPoints(), output->GetNumberOfCells() ); + + + + + } + } + + printf("---vtkExodusReader::GetDSPOutputArrays() calculated %d dsp output " + "variable instances---\n",l_numCalculated); + + } + + +} +//end USE_EXO_DSP_FILTERS + + +int vtkExodusReader::IsValidVariable( const char *type, const char *name ) +{ + if ( this->GetVariableID( type, name ) != -1 ) + { + return 1; + } + + return 0; +} + +int vtkExodusReader::GetVariableID ( const char *type, const char *name ) +{ + ArrayType typeID = this->GetArrayTypeID( type ); + + switch ( typeID ) + { + case vtkExodusReader::CELL: + return this->GetCellArrayID( name ); + break; + case vtkExodusReader::POINT: + return this->GetPointArrayID( name ); + break; + case vtkExodusReader::BLOCK: + return this->GetBlockArrayID( name ); + break; + case vtkExodusReader::PART: + return this->GetPartArrayID( name ); + break; + case vtkExodusReader::MATERIAL: + return this->GetMaterialArrayID( name ); + break; + case vtkExodusReader::ASSEMBLY: + return this->GetAssemblyArrayID( name ); + break; + case vtkExodusReader::HIERARCHY: + case vtkExodusReader::NUM_ARRAY_TYPES: + case vtkExodusReader::UNKNOWN_TYPE: + default: + return -1; + break; + } +} + +int vtkExodusReader::GetGlobalElementID ( vtkDataSet *data, int localID ) +{ + return vtkExodusReader::GetIDHelper( + vtkExodusReader::GetGlobalElementIdArrayName(), + data, localID, vtkExodusReader::SEARCH_TYPE_ELEMENT ); +} + +int vtkExodusReader::GetGlobalElementID ( vtkDataSet *data, int localID, + int searchType ) +{ + return vtkExodusReader::GetGlobalID( + vtkExodusReader::GetGlobalElementIdArrayName(), data, + localID, searchType ); +} + +int vtkExodusReader::GetGlobalNodeID ( vtkDataSet *data, int localID ) +{ + return vtkExodusReader::GetIDHelper( + vtkExodusReader::GetGlobalNodeIdArrayName(), + data, localID, vtkExodusReader::SEARCH_TYPE_NODE ); +} + +int vtkExodusReader::GetGlobalNodeID ( vtkDataSet *data, int localID, + int searchType ) +{ + return vtkExodusReader::GetGlobalID( + vtkExodusReader::GetGlobalNodeIdArrayName(), data, + localID, searchType ); +} + +int vtkExodusReader::GetGlobalID ( const char *arrayName, vtkDataSet *data, + int localID, int searchType ) +{ + int newID = vtkExodusReader::ID_NOT_FOUND; + switch ( searchType ) + { + case vtkExodusReader::SEARCH_TYPE_ELEMENT: + case vtkExodusReader::SEARCH_TYPE_NODE: + newID = vtkExodusReader::GetIDHelper( arrayName, data, localID, searchType ); + break; + case vtkExodusReader::SEARCH_TYPE_ELEMENT_THEN_NODE: + // if this search fails ... + newID = vtkExodusReader::GetIDHelper( arrayName, data, localID, + vtkExodusReader::SEARCH_TYPE_ELEMENT ); + if ( newID == vtkExodusReader::ID_NOT_FOUND ) + { + // try this search + newID = vtkExodusReader::GetIDHelper( arrayName, data, localID, + vtkExodusReader::SEARCH_TYPE_NODE ); + } + break; + case vtkExodusReader::SEARCH_TYPE_NODE_THEN_ELEMENT: + // if this search fails ... + newID = vtkExodusReader::GetIDHelper( arrayName, data, localID, + vtkExodusReader::SEARCH_TYPE_NODE ); + if ( newID == vtkExodusReader::ID_NOT_FOUND ) + { + // try this search + newID = vtkExodusReader::GetIDHelper( arrayName, data, localID, + vtkExodusReader::SEARCH_TYPE_ELEMENT ); + } + break; + } + return newID; +} + +int vtkExodusReader::GetIDHelper ( const char *arrayName, vtkDataSet *data, + int localID, int searchType ) +{ + int newID = vtkExodusReader::ID_NOT_FOUND; + if ( data ) + { + vtkDataArray *IDs = NULL; + vtkCellData *cData = data->GetCellData(); + vtkPointData *pData = data->GetPointData(); + if ( searchType == vtkExodusReader::SEARCH_TYPE_ELEMENT ) + { + IDs = cData->GetScalars( arrayName ); + } + else if ( searchType == vtkExodusReader::SEARCH_TYPE_NODE ) + { + IDs = pData->GetScalars( arrayName ); + } + if ( IDs ) + { + if ( ( localID >=0 ) && ( localID < IDs->GetNumberOfTuples() ) ) + { + newID = (int)( IDs->GetTuple1( localID ) ); + } + } + } + return newID; +} diff --git a/Hybrid/vtkExodusReader.h b/Hybrid/vtkExodusReader.h new file mode 100644 index 0000000..9421739 --- /dev/null +++ b/Hybrid/vtkExodusReader.h @@ -0,0 +1,538 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExodusReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkExodusReader - Read exodus 2 files .ex2 +// .SECTION Description +// vtkExodusReader is a unstructured grid source object that reads ExodusII +// files. Most of the meta data associated with the file is loaded when +// UpdateInformation is called. This includes information like Title, number +// of blocks, number and names of arrays. This data can be retrieved from +// methods in this reader. Separate arrays that are meant to be a single +// vector, are combined internally for convenience. To be combined, the array +// names have to be identical except for a trailing X,Y and Z (or x,y,z). By +// default cell and point arrays are not loaded. However, the user can flag +// arrays to load with the methods "SetPointArrayStatus" and +// "SetCellArrayStatus". The reader DOES NOT respond to piece requests +// + + + +#ifndef __vtkExodusReader_h +#define __vtkExodusReader_h + +#define ARRAY_TYPE_NAMES_IN_CXX_FILE + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkIntArray; +class vtkFloatArray; +class vtkDataArray; +class vtkDataSet; +class vtkPoints; +class vtkExodusMetadata; +class vtkExodusModel; +class vtkExodusXMLParser; + + +#include "vtkDSPFilterGroup.h" //for USE_EXO_DSP_FILTERS + + +class VTK_HYBRID_EXPORT vtkExodusReader : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkExodusReader *New(); + vtkTypeRevisionMacro(vtkExodusReader,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of the Exodus file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Specify file name of the xml file. + void SetXMLFileName(const char *filename); + vtkGetStringMacro(XMLFileName); + + // Description: + // Which TimeStep to read. + vtkSetMacro(TimeStep, int); + vtkGetMacro(TimeStep, int); + + // Description: + // Extra cell data array that can be generated. By default, this array + // is ON. The value of the array is the integer id found + // in the exodus file. The name of the array is returned by + // GetBlockIdArrayName() + vtkSetMacro(GenerateBlockIdCellArray, int); + vtkGetMacro(GenerateBlockIdCellArray, int); + vtkBooleanMacro(GenerateBlockIdCellArray, int); + const char *GetBlockIdArrayName() { return "BlockId"; } + + + // Description: + // Extra cell data array that can be generated. By default, this array + // is off. The value of the array is the integer global id of the cell. + // The name of the array is returned by GetGlobalElementIdArrayName() + vtkSetMacro(GenerateGlobalElementIdArray, int); + vtkGetMacro(GenerateGlobalElementIdArray, int); + vtkBooleanMacro(GenerateGlobalElementIdArray, int); +//BTX + enum { + SEARCH_TYPE_ELEMENT=0, + SEARCH_TYPE_NODE, + SEARCH_TYPE_ELEMENT_THEN_NODE, + SEARCH_TYPE_NODE_THEN_ELEMENT, + ID_NOT_FOUND=-234121312 + }; +//ETX + static const char *GetGlobalElementIdArrayName() { return "GlobalElementId"; } + static int GetGlobalElementID( vtkDataSet *data, int localID ); + static int GetGlobalElementID ( vtkDataSet *data, int localID, + int searchType ); + + // Description: + // Extra point data array that can be generated. By default, this array + // is ON. The value of the array is the integer id of the node. + // The id is relative to the entire data set. + // The name of the array is returned by GlobalNodeIdArrayName(). + vtkSetMacro(GenerateGlobalNodeIdArray, int); + vtkGetMacro(GenerateGlobalNodeIdArray, int); + vtkBooleanMacro(GenerateGlobalNodeIdArray, int); + static const char *GetGlobalNodeIdArrayName() { return "GlobalNodeId"; } + static int GetGlobalNodeID( vtkDataSet *data, int localID ); + static int GetGlobalNodeID( vtkDataSet *data, int localID, + int searchType ); + + // Description: + // Geometric locations can include displacements. By default, + // this is ON. The nodal positions are 'displaced' by the + // standard exodus displacment vector. If displacements + // are turned 'off', the user can explicitly add them by + // applying a warp filter. + vtkSetMacro(ApplyDisplacements, int); + vtkGetMacro(ApplyDisplacements, int); + vtkBooleanMacro(ApplyDisplacements, int); + vtkSetMacro(DisplacementMagnitude, float); + vtkGetMacro(DisplacementMagnitude, float); + + // Description: + // Access to meta data generated by UpdateInformation. + vtkGetStringMacro(Title); + vtkGetMacro(Dimensionality, int); + vtkGetMacro(NumberOfTimeSteps, int); + int GetNumberOfElements() { return this->NumberOfUsedElements; } + vtkGetMacro(NumberOfNodeSets, int); + vtkGetMacro(NumberOfSideSets, int); + vtkGetMacro(NumberOfBlocks, int); + vtkGetVector2Macro(TimeStepRange, int); + vtkSetVector2Macro(TimeStepRange, int); + int GetNumberOfNodes() { return this->NumberOfUsedNodes; } + int GetNumberOfElementsInBlock(int block_idx); + int GetBlockId(int block_idx); + + + // Descriptions: + // By default arrays are not loaded. These methods allow the user to select + // which arrays they want to load. You can get information about the arrays + // by first caling UpdateInformation, and using GetPointArrayName ... + // (Developer Note) This meta data is all accessed through vtkExodusMetadata + int GetNumberOfPointArrays(); + const char *GetPointArrayName(int index); + int GetPointArrayID( const char *name ); + int GetPointArrayNumberOfComponents(int index); + void SetPointArrayStatus(int index, int flag); + void SetPointArrayStatus(const char*, int flag); + int GetPointArrayStatus(int index); + int GetPointArrayStatus(const char*); + + int GetNumberOfCellArrays(); + const char *GetCellArrayName(int index); + int GetCellArrayID( const char *name ); + int GetCellArrayNumberOfComponents(int index); + void SetCellArrayStatus(int index, int flag); + void SetCellArrayStatus(const char*, int flag); + int GetCellArrayStatus(int index); + int GetCellArrayStatus(const char*); + + // Descriptions: + // By default all blocks are loaded. These methods allow the user to select + // which blocks they want to load. You can get information about the blocks + // by first caling UpdateInformation, and using GetBlockArrayName ... + int GetNumberOfBlockArrays(); + const char *GetBlockArrayName(int index); + int GetBlockArrayID( const char *name ); + void SetBlockArrayStatus(int index, int flag); + void SetBlockArrayStatus(const char*, int flag); + int GetBlockArrayStatus(int index); + int GetBlockArrayStatus(const char*); + + + // Description: + // By default Node/Side sets are not loaded, These methods allow the user to + // select which Node/Side sets they want to load. NumberOfNodeSets and + // NumberOfSideSets (set by vtk macros) are stored in vtkExodusReader + // but other Node/Side set metadata are stored in vtkExodusMetaData + // Note: GetNumberOfNodeSetArrays and GetNumberOfSideSetArrays are + // just syntatic sugar for paraview server xml + int GetNumberOfNodeSetArrays(){return this->GetNumberOfNodeSets();} + int GetNodeSetArrayStatus(int index); + int GetNodeSetArrayStatus(const char* name); + void SetNodeSetArrayStatus(int index, int flag); + void SetNodeSetArrayStatus(const char* name, int flag); + const char *GetNodeSetArrayName(int index); + + int GetNumberOfSideSetArrays(){return this->GetNumberOfSideSets();} + int GetSideSetArrayStatus(int index); + int GetSideSetArrayStatus(const char* name); + void SetSideSetArrayStatus(int index, int flag); + void SetSideSetArrayStatus(const char* name, int flag); + const char *GetSideSetArrayName(int index); + + // Descriptions: + // By default all parts are loaded. These methods allow the user to select + // which parts they want to load. You can get information about the parts + // by first caling UpdateInformation, and using GetPartArrayName ... + int GetNumberOfPartArrays(); + const char *GetPartArrayName(int arrayIdx); + int GetPartArrayID( const char *name ); + const char *GetPartBlockInfo(int arrayIdx); + void SetPartArrayStatus(int index, int flag); + void SetPartArrayStatus(const char*, int flag); + int GetPartArrayStatus(int index); + int GetPartArrayStatus(const char*); + + + // Descriptions: + // By default all materials are loaded. These methods allow the user to + // select which materials they want to load. You can get information + // about the materials by first caling UpdateInformation, and using + // GetMaterialArrayName ... + int GetNumberOfMaterialArrays(); + const char *GetMaterialArrayName(int arrayIdx); + int GetMaterialArrayID( const char *name ); + void SetMaterialArrayStatus(int index, int flag); + void SetMaterialArrayStatus(const char*, int flag); + int GetMaterialArrayStatus(int index); + int GetMaterialArrayStatus(const char*); + + // Descriptions: + // By default all assemblies are loaded. These methods allow the user to + // select which assemblies they want to load. You can get information + // about the assemblies by first caling UpdateInformation, and using + // GetAssemblyArrayName ... + int GetNumberOfAssemblyArrays(); + const char *GetAssemblyArrayName(int arrayIdx); + int GetAssemblyArrayID( const char *name ); + void SetAssemblyArrayStatus(int index, int flag); + void SetAssemblyArrayStatus(const char*, int flag); + int GetAssemblyArrayStatus(int index); + int GetAssemblyArrayStatus(const char*); + + // Descriptions: + // By default all hierarchy entries are loaded. These methods allow + //the user to + // select which hierarchy entries they want to load. You can get information + // about the hierarchy entries by first caling UpdateInformation, and using + // GetHierarchyArrayName ... + //these methods do not call functions in metaData. They call functions on + //the ExodusXMLParser since it seemed silly to duplicate all the information + int GetNumberOfHierarchyArrays(); + const char *GetHierarchyArrayName(int arrayIdx); + void SetHierarchyArrayStatus(int index, int flag); + void SetHierarchyArrayStatus(const char*, int flag); + int GetHierarchyArrayStatus(int index); + int GetHierarchyArrayStatus(const char*); + + vtkGetMacro(DisplayType,int); + virtual void SetDisplayType(int type); + + // Description: + // There is a great deal of model information lost when an Exodus II + // file is read in to a vtkUnstructuredGrid. Turn this option ON + // if you want this metadata to be read in to a vtkExodusModel object. + // The default is OFF. + + vtkBooleanMacro(ExodusModelMetadata, int); + vtkSetMacro(ExodusModelMetadata, int); + vtkGetMacro(ExodusModelMetadata, int); + + // Description: + // Returns the object which encapsulates the model metadata. + + vtkExodusModel *GetExodusModel(){return this->ExodusModel;} + + // Description: + // By default, the ExodusModel metadata (if requested with + // ExodusModelMetadataOn()) is also encoded into field arrays + // and attached to the output unstructured grid. Set this OFF + // if you don't want this to happen. (The vtkExodusIIWriter and + // the vtkEnSightWriter can unpack this metadata from the field + // arrays and use it when writing out Exodus or EnSight files.) + + vtkSetMacro(PackExodusModelOntoOutput, int); + vtkGetMacro(PackExodusModelOntoOutput, int); + vtkBooleanMacro(PackExodusModelOntoOutput, int); + +//BTX + // Descriptions: + // Syntactic sugar funtions. + enum ArrayType { + CELL=0, + POINT, + BLOCK, + PART, + MATERIAL, + ASSEMBLY, + HIERARCHY, + NUM_ARRAY_TYPES, + UNKNOWN_TYPE + }; +//ETX + + // Descriptions: + // return boolean indicating whether the type,name is a valid variable + int IsValidVariable( const char *type, const char *name ); + +//BTX + // Description: + // Named type accessor for array information + int GetNumberOfArrays( vtkExodusReader::ArrayType type ); + const char *GetArrayName( vtkExodusReader::ArrayType type, int id ); +//ETX + + // Descriptions: + // Return the id of the type,name variable + int GetVariableID ( const char *type, const char *name ); + + void SetAllAssemblyArrayStatus( int status ); + void SetAllBlockArrayStatus( int status ); + void SetAllCellArrayStatus( int status ); + void SetAllHierarchyArrayStatus( int status ); + void SetAllMaterialArrayStatus( int status ); + void SetAllPartArrayStatus( int status ); + void SetAllPointArrayStatus( int status ); +//BTX + void SetAllArrayStatus ( vtkExodusReader::ArrayType type, int flag ); + void SetArrayStatus ( vtkExodusReader::ArrayType type, const char *name, + int flag ); +//ETX + void SetArrayStatus ( const char *type, const char *name, int flag ) + { + this->SetArrayStatus( this->GetArrayTypeID(type), name, flag ); + } +//BTX + int GetArrayStatus ( vtkExodusReader::ArrayType type, const char *name ); +//ETX + int GetArrayStatus ( const char *type, const char *name ) + { + return this->GetArrayStatus( this->GetArrayTypeID( type ), name ); + } + + // Helper functions + static int StringsEqual(const char* s1, char* s2); + static void StringUppercase(const char* str, char* upperstr); + static char *StrDupWithNew(const char *s); + + // time series query functions + int GetTimeSeriesData( int ID, const char *vName, const char *vType, + vtkFloatArray *result ); + + + //begin USE_EXO_DSP_FILTERS + int GetNumberOfVariableArrays(); + const char *GetVariableArrayName(int a_which); + void EnableDSPFiltering(); + void AddFilter(vtkDSPFilterDefinition *a_filter); + void StartAddingFilter(); + void AddFilterInputVar(char *name); + void AddFilterOutputVar(char *name); + void AddFilterNumeratorWeight(double weight); + void AddFilterForwardNumeratorWeight(double weight); + void AddFilterDenominatorWeight(double weight); + void FinishAddingFilter(); + void RemoveFilter(char *a_outputVariableName); + void GetDSPOutputArrays(int exoid, vtkUnstructuredGrid* output); +//BTX + vtkExodusReader::ArrayType GetArrayTypeID( const char *type ); + +#ifdef ARRAY_TYPE_NAMES_IN_CXX_FILE + static const char *GetArrayTypeName( vtkExodusReader::ArrayType type ); +#else + static const char *ArrayTypeNames[NUM_ARRAY_TYPES]; + + static const char *GetArrayTypeName( vtkExodusReader::ArrayType type ) + { + return ArrayTypeNames[type]; + } +#endif +//ETX + + vtkDSPFilterDefinition *AddingFilter; + int DSPFilteringIsEnabled; + vtkDSPFilterGroup **DSPFilters; + //end USE_EXO_DSP_FILTERS + + + +protected: + vtkExodusReader(); + ~vtkExodusReader(); + + void NewExodusModel(); + + void ReadGeometry(int exoid, vtkUnstructuredGrid* output); + void ReadCells(int exoid, vtkUnstructuredGrid* output); + void ReadPoints(int exoid, vtkUnstructuredGrid* output); + void ReadArrays(int exoid, vtkUnstructuredGrid* output); + void ReadNodeAndSideSets(int exoid, vtkUnstructuredGrid* output); + vtkDataArray *ReadPointArray(int exoid, int varIndex); + vtkDataArray *ReadPointVector(int handle, int varIndex, int dim); + vtkDataArray *ReadCellArray(int exoid, int varIndex); + vtkDataArray *ReadCellVector(int handle, int varIndex, int dim); + void ReadNodeSetMetadata(); + void ReadSideSetMetadata(); + + // helper for finding IDs + static int GetIDHelper ( const char *arrayName, vtkDataSet *data, int localID, + int searchType ); + static int GetGlobalID( const char *arrayName, vtkDataSet *data, int localID, + int searchType ); + + + // This method is a helper for determining the + // number of additional cell scalar field + // values needed to 'pad' for node and side sets + int GetExtraCellCountForNodeSideSets(); + + // This method generates arrays like blockid, global nodeid + // and global element id + void GenerateExtraArrays(vtkUnstructuredGrid* output); + + // Parameters for controlling what is read in. + char *FileName; + char *XMLFileName; + int TimeStep; + int ActualTimeStep; + int GenerateBlockIdCellArray; + int GenerateGlobalElementIdArray; + int GenerateGlobalNodeIdArray; + int ApplyDisplacements; + double DisplacementMagnitude; + + // Information specific for exodus files. + vtkSetStringMacro(Title); + char *Title; + int Dimensionality; + int NumberOfNodeSets; + int NumberOfSideSets; + int NumberOfBlocks; + int NumberOfUsedNodes; + int NumberOfNodesInFile; + int NumberOfUsedElements; + int NumberOfElementsInFile; + int NumberOfTimeSteps; + int ExodusCPUWordSize; + int ExodusIOWordSize; + float ExodusVersion; + vtkIntArray *CellVarTruthTable; + + //1=display Block names + //2=display Part names + //3=display Material names + int DisplayType; + + //Parser that understands the xml part and material file + vtkExodusXMLParser *Parser; + + // **KEN** By VTK convention, metaData should be Metadata. + + //////////////////////////////////////// + // Scalar Array and Block Info + //////////////////////////////////////// + vtkExodusMetadata *MetaData; + + + // Descriptions: + // Store current file name and current handle. + int CurrentHandle; + char* CurrentFileName; + char* CurrentXMLFileName; + vtkSetStringMacro(CurrentFileName); + vtkSetStringMacro(CurrentXMLFileName); + + // Open the exodus file, and set some basic information + int OpenCurrentFile(); + + // Close the exodus file + void CloseCurrentFile(); + + + // Descriptions: + // Store the range of time steps + int TimeStepRange[2]; + + // DataCache: this object keeps the points and cells + // around so they don't need to be re-read when the + // timestep changes or an scalar array is switched + vtkUnstructuredGrid *DataCache; + + // Should I re-read in the geometry and topology of the dataset + int RemakeDataCacheFlag; + + // vtkExodusModel needs to count changes in geometry, so it knows + // if geometry has changed since it last updated model data. + + int NewGeometryCount; + + // PointMap keeps track of which points are actually + // used by the cells that are read in (blocks) + vtkIntArray *PointMap; + vtkIntArray *ReversePointMap; + void SetUpPointMap(int num_points); + int GetPointMapIndex(int point_id); + + // Global element ID cache + int *GlobalElementIdCache; + void SetGlobalElementIdCache(int *list); + + // Time query function. Called by ExecuteInformation(). + // Fills the TimestepValues array. + void GetAllTimes(vtkInformationVector *); + + vtkExodusModel *ExodusModel; + int PackExodusModelOntoOutput; + int ExodusModelMetadata; + + int RequestInformation( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkExodusReader(const vtkExodusReader&); // Not implemented + void operator=(const vtkExodusReader&); // Not implemented + + void AddDisplacements(vtkUnstructuredGrid* output); + void RemoveBeginningAndTrailingSpaces(char **names, int len); + + void FixMetadataTruthTable(int *table, int len); +}; + +#endif diff --git a/Hybrid/vtkFacetReader.cxx b/Hybrid/vtkFacetReader.cxx new file mode 100644 index 0000000..a2fff1b --- /dev/null +++ b/Hybrid/vtkFacetReader.cxx @@ -0,0 +1,390 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFacetReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFacetReader.h" + +#include "vtkPolyData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkErrorCode.h" +#include "vtkCellType.h" +#include "vtkCellArray.h" +#include "vtkGarbageCollector.h" +#include "vtkAppendPolyData.h" +#include "vtkPointData.h" +#include "vtkCellData.h" + +#include "vtkUnsignedIntArray.h" +#include "vtkDoubleArray.h" +#include "vtkSmartPointer.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkFacetReader, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkFacetReader); + +//------------------------------------------------------------------------------ +// Due to a buggy stream library on the HP and another on Mac OSX, we +// need this very carefully written version of getline. Returns true +// if any data were read before the end-of-file was reached. +// +static bool GetLineFromStream(istream& is, + vtkstd::string& line, bool *has_newline = 0) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + line = ""; + bool haveData = false; + if ( has_newline ) + { + *has_newline = false; + } + + // If no characters are read from the stream, the end of file has + // been reached. + while((is.getline(buffer, bufferSize), is.gcount() > 0)) + { + haveData = true; + line.append(buffer); + + // If newline character was read, the gcount includes the + // character, but the buffer does not. The end of line has been + // reached. + if(strlen(buffer) < static_cast(is.gcount())) + { + if ( has_newline ) + { + *has_newline = true; + } + break; + } + + // The fail bit may be set. Clear it. + is.clear(is.rdstate() & ~ios::failbit); + } + return haveData; +} + +//---------------------------------------------------------------------------- +vtkFacetReader::vtkFacetReader() +{ + this->FileName = NULL; + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkFacetReader::~vtkFacetReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } +} + +//---------------------------------------------------------------------------- +int vtkFacetReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if ( !this->FileName ) + { + vtkErrorMacro("No filename specified"); + return 1; + } + + struct stat fs; + if ( stat(this->FileName, &fs) ) + { + this->SetErrorCode(vtkErrorCode::FileNotFoundError); + vtkErrorMacro("Specified filename not found"); + return 1; + } + + ifstream ifs(this->FileName, ios::in); + if (!ifs) + { + this->SetErrorCode(vtkErrorCode::FileNotFoundError); + vtkErrorMacro("Specified filename not found"); + return 1; + } + + vtkDebugMacro( << "Reading Facet file"); + vtkstd::string line; + + // Read first row + if ( !GetLineFromStream(ifs, line) ) + { + vtkErrorMacro("Cannot read file comment"); + return 1; + } + + // Read number of parts + int num_parts = 0; + if ( !GetLineFromStream(ifs, line) || + sscanf(line.c_str(), "%d", &num_parts) != 1 || + num_parts < 0 ) + { + vtkErrorMacro("Bad number of parts line"); + return 1; + } + + vtkDebugMacro("Number of parts is: " << num_parts); + + // Buffers for various information from file + vtkstd::vector pointList; + vtkstd::vector stringBuffer; + + // We will need append individual parts together. Once multiblock is + // supported, this should go out. + vtkSmartPointer appendPtr = vtkSmartPointer::New(); + + // Block garbage collection so that appends will not take too long. + vtkGarbageCollector::DeferredCollectionPush(); + + int part; + int error = 0; + + // Loop thrugh individual parts + for ( part = 0; part < num_parts || error; part ++ ) + { + vtkstd::string partName; + vtkDebugMacro("Reading part: " << part); + + // Read part name + if ( !GetLineFromStream(ifs, partName) ) + { + vtkErrorMacro("Cannot read part name"); + error = 1; + break; + } + vtkDebugMacro("Part name: " << partName.c_str()); + + // Read cell/point index and geometry information including the number of + // points. cell/point index for points is always 0 + int cell_point_index = -1; + int numpts = -1, tmp; + if ( !GetLineFromStream(ifs, line) || + sscanf(line.c_str(), "%d", &cell_point_index) != 1 || + cell_point_index != 0 || + !GetLineFromStream(ifs, line) || + sscanf(line.c_str(), "%d %d %d", &numpts, &tmp, &tmp) != 3 || + numpts < 0 ) + { + vtkErrorMacro("Problem reading number of points"); + error = 1; + break; + } + + vtkIdType num_points = numpts; + vtkIdType point; + vtkSmartPointer myPointsPtr = vtkSmartPointer::New(); + + // Read individual points + for ( point = 0; point < num_points; point ++ ) + { + // Read point + double x = 0, y = 0, z = 0; + if ( !GetLineFromStream(ifs, line) || + sscanf(line.c_str(), "%lf %lf %lf", &x, &y, &z) != 3 ) + { + vtkErrorMacro("Problem reading point: " << point); + error = 1; + break; + } + myPointsPtr->InsertNextPoint(x, y, z); + } + if ( error ) + { + break; + } + + // Read cell point index + if ( !GetLineFromStream(ifs, line) || + sscanf(line.c_str(), "%d", &cell_point_index) != 1 || + cell_point_index != 1 ) + { + vtkErrorMacro("Cannot read cell/point index or it is not 1"); + error = 1; + break; + } + + // Read part name + if ( !GetLineFromStream(ifs, line) || + partName != line ) + { + vtkErrorMacro("Cannot read part name or the part name does not match"); + error = 1; + break; + } + + // Read topology information + int numcells = -1, numpointpercell = -1; + if ( !GetLineFromStream(ifs, line) || + sscanf(line.c_str(), "%d %d", &numcells, &numpointpercell) != 2 || + numcells < 0 || numpointpercell < 0 ) + { + vtkErrorMacro("Problem reading number of cells and points per cell"); + error = 1; + break; + } + + vtkIdType num_cells = numcells; + vtkIdType num_points_per_cell = numpointpercell; + if ( pointList.size() < static_cast(num_points_per_cell) ) + { + pointList.resize(num_points_per_cell); + } + + // We need arrays to store material and part number + vtkSmartPointer materialArrayPtr = vtkSmartPointer::New(); + materialArrayPtr->SetName("Material"); + materialArrayPtr->SetNumberOfComponents(1); + materialArrayPtr->SetNumberOfTuples(num_cells); + + vtkSmartPointer relativePartArrayPtr = vtkSmartPointer::New(); + relativePartArrayPtr->SetName("RelativePartNumber"); + relativePartArrayPtr->SetNumberOfComponents(1); + relativePartArrayPtr->SetNumberOfTuples(num_cells); + + vtkSmartPointer myCellsPtr = vtkSmartPointer::New(); + + // Read cells + vtkIdType cell; + for ( cell = 0; cell < num_cells; cell ++ ) + { + // Read cell + if ( !GetLineFromStream(ifs, line) ) + { + vtkErrorMacro("Cannot read cell: " << cell); + error = 1; + break; + } + + // Read specified number of points from cell information + if ( stringBuffer.size() < line.size()+1 ) + { + stringBuffer.resize(line.size()+1); + } + char* strPtr = &(*stringBuffer.begin()); + strcpy(strPtr, line.c_str()); + istrstream lineStream(strPtr); + vtkIdType kk; + int material = -1, relativePartNumber = -1; + for ( kk = 0; kk < num_points_per_cell; kk ++ ) + { + int val; + if ( !(lineStream >> val) ) + { + vtkErrorMacro("Cannot extract cell points for cell: " << cell); + error = 1; + break; + } + // point indices start with 0, while cell descriptions have point + // indices starting with 1 + pointList[kk] = val -1; + } + + // Extract material and part number + if ( !(lineStream >> material >> relativePartNumber) ) + { + vtkErrorMacro("Cannot extract cell material and part for cell: " + << cell); + error = 1; + break; + } + materialArrayPtr->SetTuple1(cell, material); + relativePartArrayPtr->SetTuple1(cell, relativePartNumber); + + myCellsPtr->InsertNextCell(num_points_per_cell, &(*pointList.begin())); + } + if ( error ) + { + break; + } + + vtkIdType cc; + + // Create another array with absolute part number + vtkUnsignedIntArray* partNumberArray = vtkUnsignedIntArray::New(); + partNumberArray->SetName("PartNumber"); + partNumberArray->SetNumberOfComponents(1); + partNumberArray->SetNumberOfTuples(num_cells); + for ( cc = 0; cc < partNumberArray->GetNumberOfTuples(); cc ++ ) + { + partNumberArray->SetTuple1(cc, part); + } + + // Create part and store it + vtkPolyData* partGrid = vtkPolyData::New(); + switch ( num_points_per_cell ) + { + case 1: + partGrid->SetVerts(myCellsPtr); + break; + case 2: + partGrid->SetLines(myCellsPtr); + break; + case 3: + partGrid->SetPolys(myCellsPtr); + break; + default: + partGrid->SetPolys(myCellsPtr); + break; + } + partGrid->SetPoints(myPointsPtr); + partGrid->GetCellData()->AddArray(partNumberArray); + partGrid->GetCellData()->AddArray(materialArrayPtr); + partGrid->GetCellData()->AddArray(relativePartArrayPtr); + partGrid->GetCellData()->SetScalars(materialArrayPtr); + appendPtr->AddInput(partGrid); + + partNumberArray->Delete(); + partGrid->Delete(); + } + + if ( !error ) + { + // If everything ok, use append. + appendPtr->Update(); + output->ShallowCopy(appendPtr->GetOutput()); + } + + // Release garbage collection + vtkGarbageCollector::DeferredCollectionPop(); + vtkDebugMacro("Done reading file: " << this->FileName); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkFacetReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; +} + + diff --git a/Hybrid/vtkFacetReader.h b/Hybrid/vtkFacetReader.h new file mode 100644 index 0000000..3015d6b --- /dev/null +++ b/Hybrid/vtkFacetReader.h @@ -0,0 +1,67 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkFacetReader.h,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFacetReader - reads a dataset in Facet format +// .SECTION Description +// vtkFacetReader creates a poly data dataset. It reads ASCII files +// stored in Facet format +// +// The facet format looks like this: +// FACET FILE ... +// nparts +// Part 1 name +// 0 +// npoints 0 0 +// p1x p1y p1z +// p2x p2y p2z +// ... +// 1 +// Part 1 name +// ncells npointspercell +// p1c1 p2c1 p3c1 ... pnc1 materialnum partnum +// p1c2 p2c2 p3c2 ... pnc2 materialnum partnum +// ... + +#ifndef __vtkFacetReader_h +#define __vtkFacetReader_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_HYBRID_EXPORT vtkFacetReader : public vtkPolyDataAlgorithm +{ +public: + static vtkFacetReader *New(); + vtkTypeRevisionMacro(vtkFacetReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of Facet datafile to read + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkFacetReader(); + ~vtkFacetReader(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char *FileName; + +private: + vtkFacetReader(const vtkFacetReader&); // Not implemented. + void operator=(const vtkFacetReader&); // Not implemented. +}; + +#endif + diff --git a/Hybrid/vtkGreedyTerrainDecimation.cxx b/Hybrid/vtkGreedyTerrainDecimation.cxx new file mode 100644 index 0000000..6d2eeb0 --- /dev/null +++ b/Hybrid/vtkGreedyTerrainDecimation.cxx @@ -0,0 +1,1264 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGreedyTerrainDecimation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGreedyTerrainDecimation.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPriorityQueue.h" +#include "vtkImageData.h" +#include "vtkPolyData.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkCellArray.h" +#include "vtkTriangle.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" + +#include + +vtkCxxRevisionMacro(vtkGreedyTerrainDecimation, "$Revision: 1.22.12.1 $"); +vtkStandardNewMacro(vtkGreedyTerrainDecimation); + +// Define some constants describing vertices +// +#define VTK_VERTEX_NO_TRIANGLE -1 +#define VTK_VERTEX_INSERTED -2 + +#define VTK_IN_TRIANGLE 0 +#define VTK_INTERIOR_EDGE 1 +#define VTK_BOUNDARY_EDGE 2 + +//Supporting classes for points +class vtkTerrainInfo +{ +public: + vtkTerrainInfo():TriangleId(VTK_VERTEX_NO_TRIANGLE) {} + vtkIdType TriangleId; +}; + +//PIMPL STL encapsulation +// +// Maps input point ids to owning mesh triangle +class vtkGreedyTerrainDecimationTerrainInfoType : public vtkstd::vector +{ +public: + typedef vtkstd::vector Superclass; + typedef Superclass::size_type size_type; + vtkGreedyTerrainDecimationTerrainInfoType(size_type n, const vtkTerrainInfo& value): + vtkstd::vector(n,value) {} +}; + +// Maps mesh point id to input point id +class vtkGreedyTerrainDecimationPointInfoType : public vtkstd::vector {}; + + +// Begin vtkGreedyTerrainDecimation class implementation----------------------------------------- +// +vtkGreedyTerrainDecimation::vtkGreedyTerrainDecimation() +{ + this->ErrorMeasure = VTK_ERROR_SPECIFIED_REDUCTION; + this->NumberOfTriangles = 1000; + this->Reduction = 0.90; + this->AbsoluteError = 1; + this->RelativeError = 0.01; + this->BoundaryVertexDeletion = 1; + + this->ComputeNormals = 0; + this->Normals = 0; +} + +vtkGreedyTerrainDecimation::~vtkGreedyTerrainDecimation() +{ +} + +inline void vtkGreedyTerrainDecimation::GetTerrainPoint(int i, int j, double x[3]) +{ + x[0] = this->Origin[0] + i*this->Spacing[0]; + x[1] = this->Origin[1] + j*this->Spacing[1]; +} + +inline void vtkGreedyTerrainDecimation::ComputeImageCoordinates(vtkIdType inputPtId, int ij[2]) +{ + ij[0] = inputPtId % this->Dimensions[0]; + ij[1] = inputPtId / this->Dimensions[0]; +} + +inline vtkIdType vtkGreedyTerrainDecimation::InsertNextPoint(vtkIdType inputPtId, + double x[3]) +{ + if ( (this->CurrentPointId+1) >= (vtkIdType)this->PointInfo->size() ) + { + this->PointInfo->resize(2*this->PointInfo->size()); + } + + double *ptr = this->Points->WritePointer(3*this->CurrentPointId,3); + *ptr++ = *x++; + *ptr++ = *x++; + *ptr = *x; + + this->OutputPD->CopyData(this->InputPD,inputPtId,this->CurrentPointId); + (*this->PointInfo)[this->CurrentPointId] = inputPtId; + + return this->CurrentPointId++; +} + +inline double *vtkGreedyTerrainDecimation::GetPoint(vtkIdType id) +{ + return this->Points->GetPointer(3*id); +} + +inline void vtkGreedyTerrainDecimation::GetPoint(vtkIdType id, double x[3]) +{ + double *ptr = this->Points->GetPointer(3*id); + x[0] = *ptr++; + x[1] = *ptr++; + x[2] = *ptr; +} + +void vtkGreedyTerrainDecimation::EstimateOutputSize(const vtkIdType numInputPts, + vtkIdType &numPts, vtkIdType &numTris) +{ + switch (this->ErrorMeasure) + { + case VTK_ERROR_NUMBER_OF_TRIANGLES: + numTris = this->NumberOfTriangles; + break; + case VTK_ERROR_SPECIFIED_REDUCTION: + numTris = static_cast(2*numInputPts*(1.0-this->Reduction)); + break; + default: + numTris = numInputPts; + } + + numPts = numTris/2 + 1; + numPts = (numPts < 4 ? 4 : numPts); //insure enough storage for initial four corner points + return; +} + +int vtkGreedyTerrainDecimation::SatisfiesErrorMeasure(double error) +{ + switch (this->ErrorMeasure) + { + case VTK_ERROR_NUMBER_OF_TRIANGLES: + if ( this->Mesh->GetNumberOfPolys() >= this->NumberOfTriangles ) return 1; + break; + + case VTK_ERROR_SPECIFIED_REDUCTION: + { + double reduction = (double)this->Mesh->GetNumberOfPolys()/this->MaximumNumberOfTriangles; + if ( (1.0 - reduction) <= this->Reduction ) return 1; + } + break; + + case VTK_ERROR_ABSOLUTE: + if ( error <= this->AbsoluteError ) return 1; + break; + + case VTK_ERROR_RELATIVE: + if ( (error/this->Length) <= this->RelativeError ) return 1; + break; + } + + return 0; +} + +//Update all triangles connected to this mesh point +void vtkGreedyTerrainDecimation::UpdateTriangles(vtkIdType ptId) +{ + unsigned short ncells; + vtkIdType *cells, npts, *pts; + + this->Mesh->GetPointCells(ptId,ncells,cells); + for (unsigned short i=0; iMesh->GetCellPoints(cells[i], npts, pts); + this->UpdateTriangle(cells[i], (*this->PointInfo)[pts[0]], + (*this->PointInfo)[pts[1]], (*this->PointInfo)[pts[2]]); + } +} + +//Update all points as to which triangle they lie in. Basically a scanline algorithm. +void vtkGreedyTerrainDecimation::UpdateTriangle(vtkIdType triId, + vtkIdType p1, vtkIdType p2, vtkIdType p3) +{ + // Scan convert triangle / update points as to which triangle contains each point + int ij1[2], ij2[2], ij3[2]; + this->ComputeImageCoordinates(p1, ij1); + this->ComputeImageCoordinates(p2, ij2); + this->ComputeImageCoordinates(p3, ij3); + + double h[4]; //extra entry added for interpolated value + h[0] = (double) this->Heights->GetTuple1(p1); + h[1] = (double) this->Heights->GetTuple1(p2); + h[2] = (double) this->Heights->GetTuple1(p3); + + this->UpdateTriangle(triId, ij1, ij2, ij3, h); +} + +void vtkGreedyTerrainDecimation::InsertBoundaryVertices() +{ + int i, j; + vtkIdType inputPtId, offset; + + // Insert vertices around boundary of image + // Note that the four corner vertices are already inserted. + // Along x-axis at y=0. + for (i=1; i<(this->Dimensions[0]-1); i++) + { + inputPtId = i; + this->AddPointToTriangulation(inputPtId); + } + + // Along x-axis at y=dim[1]. + offset = this->Dimensions[0]*(this->Dimensions[1]-1); + for (i=1; i<(this->Dimensions[0]-1); i++) + { + inputPtId = offset + i; + this->AddPointToTriangulation(inputPtId); + } + + // Along y-axis at x=0. + for (j=1; j<(this->Dimensions[1]-1); j++) + { + inputPtId = j*this->Dimensions[0]; + this->AddPointToTriangulation(inputPtId); + } + + // Along y-axis at x=dims[0]. + offset = this->Dimensions[0]-1; + for (j=1; j<(this->Dimensions[1]-1); j++) + { + inputPtId = offset + j*this->Dimensions[0]; + this->AddPointToTriangulation(inputPtId); + } +} + +// Determine whether point x is inside of circumcircle of triangle +// defined by points (x1, x2, x3). Returns non-zero if inside circle. +// (Note that z-component is ignored.) +int vtkGreedyTerrainDecimation::InCircle (double x[3], double x1[3], double x2[3], + double x3[3]) +{ + double radius2, center[2], dist2; + + radius2 = vtkTriangle::Circumcircle(x1,x2,x3,center); + + // check if inside/outside circumcircle + dist2 = (x[0]-center[0]) * (x[0]-center[0]) + + (x[1]-center[1]) * (x[1]-center[1]); + + if ( dist2 < (0.999999999999*radius2) ) + { + return 1; + } + else + { + return 0; + } +} + +#define VTK_DEL2D_TOLERANCE 1.0e-014 + +// Recursive method to locate triangle containing point. Starts with arbitrary +// triangle (tri) and "walks" towards it. Influenced by some of Guibas and +// Stolfi's work. Returns id of enclosing triangle, or -1 if no triangle +// found. Also, the array nei[3] is used to communicate info about points +// that lie on triangle edges: nei[0] is neighboring triangle id, and nei[1] +// and nei[2] are the vertices defining the edge. +vtkIdType vtkGreedyTerrainDecimation::FindTriangle(double x[3], vtkIdType ptIds[3], + vtkIdType tri, double tol, + vtkIdType nei[3], vtkIdList *neighbors, + int& status) +{ + int i, j, ir, ic, inside, i2, i3; + vtkIdType *pts, npts, newNei; + double p[3][3], n[2], vp[2], vx[2], dp, minProj; + + // get local triangle info + this->Mesh->GetCellPoints(tri,npts,pts); + for (i=0; i<3; i++) + { + ptIds[i] = pts[i]; + this->GetPoint(ptIds[i], p[i]); + } + + // Randomization (of find edge neighbors) avoids walking in + // circles in certain weird cases + srand(tri); + ir = rand() % 3; + + // evaluate in/out of each edge + for (inside=1, minProj=VTK_DEL2D_TOLERANCE, ic=0; ic<3; ic++) + { + i = (ir+ic) % 3; + i2 = (i+1) % 3; + i3 = (i+2) % 3; + + // create a 2D edge normal to define a "half-space"; evaluate points (i.e., + // candiate point and other triangle vertex not on this edge). + n[0] = -(p[i2][1] - p[i][1]); + n[1] = p[i2][0] - p[i][0]; + vtkMath::Normalize2D(n); + + // compute local vectors + for (j=0; j<2; j++) + { + vp[j] = p[i3][j] - p[i][j]; + vx[j] = x[j] - p[i][j]; + } + + //check for duplicate point + vtkMath::Normalize2D(vp); + if ( vtkMath::Normalize2D(vx) <= tol ) + { + vtkErrorMacro("Duplicate point"); + return -1; + } + + // see if two points are in opposite half spaces + dp = vtkMath::Dot2D(n,vx) * (vtkMath::Dot2D(n,vp) < 0 ? -1.0 : 1.0); + if ( dp < VTK_DEL2D_TOLERANCE ) + { + if ( dp < minProj ) //track edge most orthogonal to point direction + { + inside = 0; + nei[1] = ptIds[i]; + nei[2] = ptIds[i2]; + minProj = dp; + } + }//outside this edge + }//for each edge + + if ( inside ) // all edges have tested positive + { + nei[0] = (-1); + status = VTK_IN_TRIANGLE; + return tri; + } + + else if ( !inside && (fabs(minProj) < VTK_DEL2D_TOLERANCE) ) // on edge + { + this->Mesh->GetCellEdgeNeighbors(tri,nei[1],nei[2],neighbors); + if ( neighbors->GetNumberOfIds() < 1 ) + { + nei[0] = (-1); + status = VTK_BOUNDARY_EDGE; + } + else + { + nei[0] = neighbors->GetId(0); + status = VTK_INTERIOR_EDGE; + } + return tri; + } + + else //walk towards point + { + this->Mesh->GetCellEdgeNeighbors(tri,nei[1],nei[2],neighbors); + if ( (newNei=neighbors->GetId(0)) == nei[0] ) + { + vtkErrorMacro("Degeneracy"); + return -1; + } + else + { + nei[0] = tri; + return this->FindTriangle(x,ptIds,newNei,tol,nei,neighbors,status); + } + } +} + +#undef VTK_DEL2D_TOLERANCE + +// Recursive method checks whether edge is Delaunay, and if not, swaps edge. +// Continues until all edges are Delaunay. Points p1 and p2 form the edge in +// question; x is the coordinates of the inserted point; tri is the current +// triangle id. +void vtkGreedyTerrainDecimation::CheckEdge(vtkIdType ptId, double x[3], vtkIdType p1, + vtkIdType p2, vtkIdType tri, int depth) +{ + if ( depth > 15 ) + { + return; + } + + int i; + vtkIdType *pts, npts, numNei, nei, p3; + double x1[3], x2[3], x3[3]; + vtkIdList *neighbors; + vtkIdType swapTri[3]; + + this->GetPoint(p1,x1); + this->GetPoint(p2,x2); + + neighbors = vtkIdList::New(); + neighbors->Allocate(2); + + this->Mesh->GetCellEdgeNeighbors(tri,p1,p2,neighbors); + numNei = neighbors->GetNumberOfIds(); + + if ( numNei > 0 ) //i.e., not a boundary edge + { + // get neighbor info including opposite point + nei = neighbors->GetId(0); + this->Mesh->GetCellPoints(nei, npts, pts); + for (i=0; i<2; i++) + { + if ( pts[i] != p1 && pts[i] != p2 ) + { + break; + } + } + p3 = pts[i]; + this->GetPoint(p3,x3); + + // see whether point is in circumcircle + if ( this->InCircle (x3, x, x1, x2) ) + {// swap diagonal + this->Mesh->RemoveReferenceToCell(p1,tri); + this->Mesh->RemoveReferenceToCell(p2,nei); + this->Mesh->ResizeCellList(ptId,1); + this->Mesh->AddReferenceToCell(ptId,nei); + this->Mesh->ResizeCellList(p3,1); + this->Mesh->AddReferenceToCell(p3,tri); + + swapTri[0] = ptId; swapTri[1] = p3; swapTri[2] = p2; + this->Mesh->ReplaceCell(tri,3,swapTri); + + swapTri[0] = ptId; swapTri[1] = p1; swapTri[2] = p3; + this->Mesh->ReplaceCell(nei,3,swapTri); + + // two new edges become suspect + this->CheckEdge(ptId, x, p3, p2, tri, ++depth); + this->CheckEdge(ptId, x, p1, p3, nei, depth); + + }//in circle + }//interior edge + + neighbors->Delete(); +} + +vtkIdType vtkGreedyTerrainDecimation::AddPointToTriangulation(vtkIdType inputPtId) +{ + vtkIdType ptId, nei[3], tri[4]; + vtkIdType nodes[4][3], pts[3], numNeiPts, *neiPts; + vtkIdType i, p1=0, p2=0; + int ij[2]; + double x[3]; + int status; + + //Make sure the point has not been previously inserted + if ( (*this->TerrainInfo)[inputPtId].TriangleId == VTK_VERTEX_INSERTED ) + { + return -1; + } + + //Start off by determining the image coordinates and the position + this->ComputeImageCoordinates(inputPtId, ij); + this->GetTerrainPoint(ij[0], ij[1], x); + x[2] = (double) this->Heights->GetTuple1(inputPtId); + + //Seed the search + nei[0] = (*this->TerrainInfo)[inputPtId].TriangleId; + tri[0] = (nei[0] < 0 ? 0 : nei[0]); + + tri[0] = this->FindTriangle(x,pts,tri[0],this->Tolerance,nei,this->Neighbors,status); + if ( tri[0] >= 0 ) //found a triangle + { + // Insert the point into the output + ptId = this->InsertNextPoint(inputPtId, x); + + if (this->Normals) + { + float n[3]; + this->ComputePointNormal(ij[0], ij[1], n); + this->Normals->InsertNextTuple(n); + } + if ( status == VTK_IN_TRIANGLE ) //in triangle + { + //delete this triangle; create three new triangles + //first triangle is replaced with one of the new ones + nodes[0][0] = ptId; nodes[0][1] = pts[0]; nodes[0][2] = pts[1]; + this->Mesh->RemoveReferenceToCell(pts[2], tri[0]); + this->Mesh->ReplaceCell(tri[0], 3, nodes[0]); + this->Mesh->InsertNextLinkedPoint(3); + this->Mesh->AddReferenceToCell(ptId,tri[0]); + + //create two new triangles + nodes[1][0] = ptId; nodes[1][1] = pts[1]; nodes[1][2] = pts[2]; + tri[1] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[1]); + + nodes[2][0] = ptId; nodes[2][1] = pts[2]; nodes[2][2] = pts[0]; + tri[2] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[2]); + + // Check edge neighbors for Delaunay criterion. If not satisfied, flip + // edge diagonal. (This is done recursively.) + this->CheckEdge(ptId, x, pts[0], pts[1], tri[0], 0); + this->CheckEdge(ptId, x, pts[1], pts[2], tri[1], 0); + this->CheckEdge(ptId, x, pts[2], pts[0], tri[2], 0); + } + + else if ( status == VTK_INTERIOR_EDGE ) // on interior triangle edge; has a neighbor + { + //update cell list + this->Mesh->GetCellPoints(nei[0],numNeiPts,neiPts); + for (i=0; i<3; i++) + { + if ( neiPts[i] != nei[1] && neiPts[i] != nei[2] ) + { + p1 = neiPts[i]; + } + if ( pts[i] != nei[1] && pts[i] != nei[2] ) + { + p2 = pts[i]; + } + } + this->Mesh->ResizeCellList(p1,1); + this->Mesh->ResizeCellList(p2,1); + + //replace two triangles + this->Mesh->RemoveReferenceToCell(nei[2],tri[0]); + this->Mesh->RemoveReferenceToCell(nei[2],nei[0]); + + nodes[0][0] = ptId; nodes[0][1] = p2; nodes[0][2] = nei[1]; + this->Mesh->ReplaceCell(tri[0], 3, nodes[0]); + + nodes[1][0] = ptId; nodes[1][1] = nei[1]; nodes[1][2] = p1; + this->Mesh->ReplaceCell(nei[0], 3, nodes[1]); + + this->Mesh->InsertNextLinkedPoint(4); + this->Mesh->AddReferenceToCell(ptId,tri[0]); + this->Mesh->AddReferenceToCell(ptId,nei[0]); + + tri[1] = nei[0]; + + //create two new triangles + nodes[2][0] = ptId; nodes[2][1] = nei[2]; nodes[2][2] = p2; + tri[2] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[2]); + + nodes[3][0] = ptId; nodes[3][1] = p1; nodes[3][2] = nei[2]; + tri[3] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[3]); + + // Check edge neighbors for Delaunay criterion. + for ( i=0; i<4; i++ ) + { + this->CheckEdge (ptId, x, nodes[i][1], nodes[i][2], tri[i], 0); + } + } + + else //if ( status == VTK_BOUNDARY_EDGE ) // on boundary triangle edge; no neighbor + { + //update cell list + for (i=0; i<3; i++) + { + if ( pts[i] != nei[1] && pts[i] != nei[2] ) + { + p1 = pts[i]; + } + } + this->Mesh->ResizeCellList(p1,1); + + //replace one triangle + this->Mesh->RemoveReferenceToCell(nei[2],tri[0]); + + nodes[0][0] = ptId; nodes[0][1] = p1; nodes[0][2] = nei[1]; + this->Mesh->ReplaceCell(tri[0], 3, nodes[0]); + + this->Mesh->InsertNextLinkedPoint(2); + this->Mesh->AddReferenceToCell(ptId,tri[0]); + + //create one new triangles + nodes[1][0] = ptId; nodes[1][1] = nei[2]; nodes[1][2] = p1; + tri[1] = this->Mesh->InsertNextLinkedCell(VTK_TRIANGLE, 3, nodes[1]); + + // Check edge neighbors for Delaunay criterion. + for ( i=0; i<2; i++ ) + { + this->CheckEdge (ptId, x, nodes[i][1], nodes[i][2], tri[i], 0); + } + } + + //Indicate that it is now inserted and reinsert errors + (*this->TerrainInfo)[inputPtId].TriangleId = VTK_VERTEX_INSERTED; + this->UpdateTriangles(ptId); + + }//if triangle containing point found + + return 0; +} + +void vtkGreedyTerrainDecimation::ComputePointNormal(int i, int j, float n[3]) +{ + vtkDataArray* scalars; + double x0, x1, y0, y1, dx, dy; + float vx[3], vy[3]; + + scalars = this->InputPD->GetScalars(); + + dx = dy = 0; + // X + if (i > 0) + { + x0 = scalars->GetTuple1(j*this->Dimensions[0] + i - 1); + dx += this->Spacing[0]; + } + else + { + x0 = scalars->GetTuple1(j*this->Dimensions[0] + i); + } + if (i < this->Dimensions[0]-1) + { + x1 = scalars->GetTuple1(j*this->Dimensions[0] + i + 1); + dx += this->Spacing[0]; + } + else + { + x1 = scalars->GetTuple1(j*this->Dimensions[0] + i); + } + // Y + if (j > 0) + { + y0 = scalars->GetTuple1((j-1)*this->Dimensions[0] + i); + dy += this->Spacing[1]; + } + else + { + y0 = scalars->GetTuple1(j*this->Dimensions[0] + i); + } + if (j < this->Dimensions[1]-1) + { + y1 = scalars->GetTuple1((j+1)*this->Dimensions[0] + i); + dy += this->Spacing[1]; + } + else + { + y1 = scalars->GetTuple1(j*this->Dimensions[0] + i); + } + + if (dx == 0.0 || dy == 0.0) + { + // This would only happen if the input was not an XY image. + vtkErrorMacro("Could not compute normal."); + return; + } + vx[0] = (float)(dx); + vx[1] = 0.0; + vx[2] = (float)(x1-x0); + vy[0] = 0.0; + vy[1] = (float)(dy); + vy[2] = (float)(y1-y0); + vtkMath::Cross(vx, vy, n); + vtkMath::Normalize(n); +} + +int vtkGreedyTerrainDecimation::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType numInputPts=input->GetNumberOfPoints(), numPts, numTris; + vtkIdType inputPtId; + double error, bounds[6], center[3]; + vtkCellArray *triangles; + this->Mesh = output; + this->InputPD = input->GetPointData(); + this->OutputPD = this->Mesh->GetPointData(); + + // Check input and initialize the algorithm. + // + vtkDebugMacro(<<"Decimating terrain..."); + + if ( input->GetDataDimension() != 2 ) + { + vtkWarningMacro(<<"This class treats 2D height fields only"); + return 1; + } + if ( (this->Heights = this->InputPD->GetScalars()) == NULL ) + { + vtkWarningMacro(<<"This class requires height scalars"); + return 1; + } + + input->GetBounds(bounds); + input->GetCenter(center); + input->GetDimensions(this->Dimensions); + double *origin = input->GetOrigin(); + double *spacing = input->GetSpacing(); + for (int ii=0; ii<3; ii++) + { + this->Origin[ii] = (double)origin[ii]; + this->Spacing[ii] = (double)spacing[ii]; + } + this->Length = input->GetLength(); + this->MaximumNumberOfTriangles = 2 * (this->Dimensions[0]-1) * (this->Dimensions[1]-1); + this->NumberOfTriangles = (this->NumberOfTriangles < this->MaximumNumberOfTriangles ? + this->NumberOfTriangles : this->MaximumNumberOfTriangles); + + // Points within this tolerance are considered coincident...should not happen + this->Tolerance = 0.01 * this->Spacing[0]; + + // Scratch data structures + this->Neighbors = vtkIdList::New(); this->Neighbors->Allocate(2); + + // Top element of VTK's priority queue returns the minimum error value. Since we want the + // maximum error, we use 1/error relationship to insert errors. + this->TerrainError = vtkPriorityQueue::New(); + this->TerrainError->Allocate(numInputPts, (vtkIdType)((double)0.25*numInputPts)); + + // Initialize the triangle mesh data structures. Double precision point coordinates + // are required because of the numerical requirements on the Delaunay algorithm. + // + this->EstimateOutputSize(numInputPts, numPts, numTris); + + vtkPoints *newPts = vtkPoints::New(); + newPts->SetDataTypeToDouble(); + newPts->Allocate(numPts); + this->Points = static_cast(newPts->GetData()); + + // initailize the normals + if (this->ComputeNormals) + { + this->Normals = vtkFloatArray::New(); + this->Normals->SetNumberOfComponents(3); + this->Normals->Allocate(numPts*3); + this->Normals->SetName("Normals"); + } + + // Supplemental arrays used to accelerate the algorithm. + // TerrainInfo contains the "containing" triangle for each point. PointInfo maps the + // triangle mesh point id to the input image point id. + this->TerrainInfo = new vtkGreedyTerrainDecimationTerrainInfoType(numInputPts,vtkTerrainInfo()); + + this->PointInfo = new vtkGreedyTerrainDecimationPointInfoType; + this->PointInfo->resize(numPts); + + // Setup the point attributes + this->OutputPD->CopyAllocate(this->InputPD,numPts); + + // Begin the algorithm proper. The image is initially triangulated with two triangles whose + // four vertices are located at the corners of the input image. + // + newPts->Allocate(numPts); + + inputPtId = 0; + newPts->InsertPoint(0, bounds[0],bounds[2], + (double)this->Heights->GetTuple1(inputPtId)); //ptId=0 + this->OutputPD->CopyData(this->InputPD,inputPtId,0); + (*this->PointInfo)[0] = inputPtId; + + inputPtId = this->Dimensions[0] - 1; + newPts->InsertPoint(1, bounds[1],bounds[2], + (double)this->Heights->GetTuple1(inputPtId)); //ptId=1 + this->OutputPD->CopyData(this->InputPD,inputPtId,1); + (*this->PointInfo)[1] = inputPtId; + + inputPtId = this->Dimensions[0]*this->Dimensions[1] - 1; + newPts->InsertPoint(2, bounds[1],bounds[3], + (double)this->Heights->GetTuple1(inputPtId)); //ptId=2 + this->OutputPD->CopyData(this->InputPD,inputPtId,2); + (*this->PointInfo)[2] = inputPtId; + + inputPtId = this->Dimensions[0]*(this->Dimensions[1]-1); + newPts->InsertPoint(3, bounds[0],bounds[3], + (double)this->Heights->GetTuple1(inputPtId)); //ptId=3 + this->OutputPD->CopyData(this->InputPD,inputPtId,3); + (*this->PointInfo)[3] = inputPtId; + this->CurrentPointId = 4; + + // Handle normals of the four corners. + if (this->Normals) + { + float n[3]; + this->ComputePointNormal(0, 0, n); + this->Normals->InsertNextTuple(n); + this->ComputePointNormal(this->Dimensions[0]-1, 0, n); + this->Normals->InsertNextTuple(n); + this->ComputePointNormal(this->Dimensions[0]-1, this->Dimensions[1]-1, n); + this->Normals->InsertNextTuple(n); + this->ComputePointNormal(0, this->Dimensions[1]-1, n); + this->Normals->InsertNextTuple(n); + } + + // Insert initial triangles into output mesh + triangles = vtkCellArray::New(); + triangles->Allocate(numTris,3); + + triangles->InsertNextCell(3); + triangles->InsertCellPoint(0); triangles->InsertCellPoint(1); triangles->InsertCellPoint(3); + + triangles->InsertNextCell(3); + triangles->InsertCellPoint(1); triangles->InsertCellPoint(2); triangles->InsertCellPoint(3); + + // Construct the topological hierarchy for the output mesh. The alternative BuildLinks(num) + // call reallocates the links from the points to the using triangles. + this->Mesh->SetPoints(newPts); + this->Mesh->SetPolys(triangles); + this->Mesh->BuildLinks(numPts); //build cell structure; give it initial size + + // Update all (two) triangles connected to this mesh point. The single point + // in each triangle with maximum error are inserted into the error queue. + // + this->UpdateTriangles(3); + + // If boundary vertex deletion is not allowed, insert the boundary + // points first. + if ( ! this->BoundaryVertexDeletion ) + { + this->InsertBoundaryVertices(); + } + + // While the error metric is not satisfied, add point with greatest error. + // Note that this algorithm can terminate "prematurely" (e.g. compared to + // the number of triangles) if the maximum error in the queue becomes zero. + // + int abortExecute=0; + vtkIdType numInsertedPoints=0; + int tenth=numPts/10+1; + + while ( !abortExecute && (inputPtId = this->TerrainError->Pop(0, error)) >= 0 ) + { + if ( this->SatisfiesErrorMeasure((1.0/error)) ) + { + break; + } + else + { + this->AddPointToTriangulation(inputPtId); + if ( ! (++numInsertedPoints % tenth) ) + { + this->UpdateProgress( (double)(numInsertedPoints>numPts?numPts:numInsertedPoints)/numPts); + abortExecute = this->GetAbortExecute(); + } + } + } + + if (this->Normals) + { + this->OutputPD->SetNormals(this->Normals); + this->Normals->Delete(); + this->Normals = 0; + } + + vtkDebugMacro(<<"Output TIN contains: " << this->Mesh->GetNumberOfPoints() << " points" + <<"and " << this->Mesh->GetNumberOfPolys() << " triangles"); + + // The output triangle data was created incrementally by the Delaunay algorithm. + // Here we just clean up the data structures. + // + this->Neighbors->Delete(); + this->TerrainError->Delete(); + delete this->TerrainInfo; + delete this->PointInfo; + + newPts->Delete(); + triangles->Delete(); + + return 1; +} + +/*---------------------------------------------------------------------- + "Scan conversion" routines to update all points lying in a triangle. + + Divide a triangle into two subtriangles as shown. + + o max + / \ + | \ + / \ + | \ + midL o..........o midR + | _/ + / _/ + | _/ + / _/ + | _/ + /_/ + o min + + This way we can scan the two subtriangles independently without worrying about + the transistion in interpolation that occurs at the vertices. + + A triangle may be characterized in one of four ways: + VTK_TWO_TRIANGLES: We can create a two triangle representation + VTK_BOTTOM_TRIANGLE: We should only scan the lower triangle + VTK_TOP_TRIANGLE: We should only scan the upper triangle + VTK_DEGENERATE: The points are colinear (not scan converted) + + Configuration of the two triangles + --------------------------------------------------------------------------*/ +#define VTK_TWO_TRIANGLES 0 //most often +#define VTK_BOTTOM_TRIANGLE 1 +#define VTK_TOP_TRIANGLE 2 +#define VTK_DEGENERATE 3 //should never happen in this application + +//--------------------------------------------------------------------------- +// Update all points lying in the given triangle. This means indicating the triangle +// that the point is in, plus computing the error in the height field. +// +void vtkGreedyTerrainDecimation::UpdateTriangle(vtkIdType tri, int ij1[2], int ij2[2], int ij3[2], + double h[3]) +{ + int *min, *max, *midL, *midR, *mid, mid2[2]; + double t, tt; + int i, j, xL, xR; + double hMin, hMax, hMidL, hMidR, hL, hR; + vtkIdType idx, inputPtId, maxInputPtId=0; + double error, maxError=0.0; + + int type = this->CharacterizeTriangle(ij1, ij2, ij3, min, max, midL, midR, mid, mid2, + h, hMin, hMax, hMidL, hMidR); + + switch(type) + { + case VTK_BOTTOM_TRIANGLE: + case VTK_TWO_TRIANGLES: + for (j=min[1]+1; jDimensions[0]; + t = (double)(j - min[1]) / (midL[1] - min[1]); + xL = (int)((1.0-t)*min[0] + t*midL[0]); + xR = (int)((1.0-t)*min[0] + t*midR[0]); + hL = (1.0-t)*hMin + t*hMidL; + hR = (1.0-t)*hMin + t*hMidR; + for (i=xL; i<=xR; i++) + { + inputPtId = i + idx; + if ( (*this->TerrainInfo)[inputPtId].TriangleId != VTK_VERTEX_INSERTED ) + { + (*this->TerrainInfo)[inputPtId].TriangleId = tri; + if ( (xR-xL) > 0 ) + { + tt = (double)(i-xL) / (xR-xL); + error = (1.0-tt)*hL + tt*hR; + } + else + { + error = hL; + } + error = fabs( (double)this->Heights->GetTuple1(inputPtId) - error ); + if ( error > maxError ) + { + maxError = error; + maxInputPtId = inputPtId; + } + } //if vertex not inserted + } //for this scanline + } //for all scanlines in this triangle + + if ( type == VTK_BOTTOM_TRIANGLE ) + { + break; + } + + case VTK_TOP_TRIANGLE: + //Start scanning the upper triangle + for (j=max[1]-1; j>midL[1]; j--) //for all scan lines; skip vertices + { + idx = j*this->Dimensions[0]; + t = (double)(j - midL[1]) / (max[1] - midL[1]); + xL = (int) (t*max[0] + (1.0-t)*midL[0]); + xR = (int) (t*max[0] + (1.0-t)*midR[0]); + hL = t*hMax + (1.0-t)*hMidL; + hR = t*hMax + (1.0-t)*hMidR; + for (i=xL; i<=xR; i++) + { + inputPtId = i + idx; + if ( (*this->TerrainInfo)[inputPtId].TriangleId != VTK_VERTEX_INSERTED ) + { + (*this->TerrainInfo)[inputPtId].TriangleId = tri; + if ( (xR-xL) > 0 ) + { + tt = (double)(i-xL) / (xR-xL); + error = (1.0-tt)*hL + tt*hR; + } + else + { + error = hL; + } + error = fabs( (double)this->Heights->GetTuple1(inputPtId) - error ); + if ( error > maxError ) + { + maxError = error; + maxInputPtId = inputPtId; + } + } + } + } + break; + + default: + return; + } + + //The maximum error in the triangle has been found. Insert it into the queue. + if ( maxError > 0.0 ) + { + this->TerrainError->DeleteId(maxInputPtId); //if previously inserted + this->TerrainError->Insert((1.0/maxError),maxInputPtId); + } +} + + +// Characterize the configuration of the triangle based on image coordinates +// (All points in triangulation are from an image). +// +int vtkGreedyTerrainDecimation::CharacterizeTriangle(int ij1[2], int ij2[2], int ij3[3], + int* &min, int* &max, int* &midL, int* &midR, + int* &mid, int mid2[2], double h[3], + double &hMin, double &hMax, double &hL, + double &hR) +{ + // Check for situations where one edge of triangle is horizontal + // + if ( ij1[1] == ij2[1] ) + { + if ( ij1[0] < ij2[0] ) + { + midL = ij1; + midR = ij2; + hL = h[0]; + hR = h[1]; + } + else + { + midL = ij2; + midR = ij1; + hL = h[1]; + hR = h[0]; + } + if( ij3[1] < ij1[1]) + { + min = ij3; + hMin = h[2]; + return VTK_BOTTOM_TRIANGLE; + } + else + { + max = ij3; + hMax = h[2]; + return VTK_TOP_TRIANGLE; + } + } + + else if ( ij2[1] == ij3[1] ) + { + if ( ij2[0] < ij3[0] ) + { + midL = ij2; + midR = ij3; + hL = h[1]; + hR = h[2]; + } + else + { + midL = ij3; + midR = ij2; + hL = h[2]; + hR = h[1]; + } + if( ij1[1] < ij2[1]) + { + min = ij1; + hMin = h[0]; + return VTK_BOTTOM_TRIANGLE; + } + else + { + max = ij1; + hMax = h[0]; + return VTK_TOP_TRIANGLE; + } + } + + else if ( ij3[1] == ij1[1] ) + { + if ( ij3[0] < ij1[0] ) + { + midL = ij3; + midR = ij1; + hL = h[2]; + hR = h[0]; + } + else + { + midL = ij1; + midR = ij3; + hL = h[0]; + hR = h[2]; + } + if( ij2[1] < ij3[1]) + { + min = ij2; + hMin = h[1]; + return VTK_BOTTOM_TRIANGLE; + } + else + { + max = ij2; + hMax = h[1]; + return VTK_TOP_TRIANGLE; + } + } + + // Default situation (two triangles with no horizontal edges). + // Determine max, min and mid vertices. + // + // Find minimum + if ( ij1[1] < ij2[1] ) + { + if ( ij1[1] < ij3[1] ) + { + min = ij1; + hMin = h[0]; + } + else + { + min = ij3; + hMin = h[2]; + } + } + else + { + if ( ij2[1] < ij3[1] ) + { + min = ij2; + hMin = h[1]; + } + else + { + min = ij3; + hMin = h[2]; + } + } + + // Find maximum + if ( ij1[1] > ij2[1] ) + { + if ( ij1[1] > ij3[1] ) + { + max = ij1; + hMax = h[0]; + } + else + { + max = ij3; + hMax = h[2]; + } + } + else + { + if ( ij2[1] > ij3[1] ) + { + max = ij2; + hMax = h[1]; + } + else + { + max = ij3; + hMax = h[2]; + } + } + + // Find the midL and midR + double hMid, hMid2; + if ( ij1 != min && ij1 != max) + { + mid = ij1; + hMid = h[0]; + } + else if ( ij2 != min && ij2 != max) + { + mid = ij2; + hMid = h[1]; + } + else //if ( ij3 != min && ij2 != max) + { + mid = ij3; + hMid = h[2]; + } + + // Computation of the intersection + // + mid2[1] = mid[1]; + double t = (double) (mid2[1] - min[1]) / (max[1] - min[1]); + mid2[0] = (int) ((1.0-t)*min[0] + t*max[0] + 0.5); //rounding + hMid2 = (1.0-t)*hMin + t*hMax; + + if ( mid[0] < mid2[0] ) + { + midL = mid; + midR = mid2; + hL = hMid; + hR = hMid2; + } + else + { + midL = mid2; + midR = mid; + hL = hMid2; + hR = hMid; + } + + return VTK_TWO_TRIANGLES; +} + +int vtkGreedyTerrainDecimation::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkGreedyTerrainDecimation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Error Measure: "; + if ( this->ErrorMeasure == VTK_ERROR_NUMBER_OF_TRIANGLES ) + { + os << "Number of triangles\n"; + os << indent << "Number of triangles: " << this->NumberOfTriangles << "\n"; + } + else if ( this->ErrorMeasure == VTK_ERROR_SPECIFIED_REDUCTION ) + { + os << "Specified reduction\n"; + os << indent << "Reduction: " << this->Reduction << "\n"; + } + else if ( this->ErrorMeasure == VTK_ERROR_ABSOLUTE ) + { + os << "Absolute\n"; + os << indent << "Absolute Error: " << this->AbsoluteError << "\n"; + } + else // this->ErrorMeasure == VTK_ERROR_RELATIVE + { + os << "Relative\n"; + os << indent << "Relative Error: " << this->RelativeError << "\n"; + } + + os << indent << "BoundaryVertexDeletion: " + << (this->BoundaryVertexDeletion ? "On\n" : "Off\n"); + os << indent << "ComputeNormals: " + << (this->ComputeNormals ? "On\n" : "Off\n"); +} diff --git a/Hybrid/vtkGreedyTerrainDecimation.h b/Hybrid/vtkGreedyTerrainDecimation.h new file mode 100644 index 0000000..3624136 --- /dev/null +++ b/Hybrid/vtkGreedyTerrainDecimation.h @@ -0,0 +1,231 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGreedyTerrainDecimation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGreedyTerrainDecimation - reduce height field (represented as image) to reduced TIN +// .SECTION Description +// vtkGreedyTerrainDecimation approximates a height field with a triangle +// mesh (triangulated irregular network - TIN) using a greedy insertion +// algorithm similar to that described by Garland and Heckbert in their paper +// "Fast Polygonal Approximations of Terrain and Height Fields" (Technical +// Report CMU-CS-95-181). The input to the filter is a height field +// (represented by a image whose scalar values are height) and the output of +// the filter is polygonal data consisting of triangles. The number of +// triangles in the output is reduced in number as compared to a naive +// tessellation of the input height field. This filter copies point data +// from the input to the output for those points present in the output. +// +// An brief description of the algorithm is as follows. The algorithm uses a +// top-down decimation approach that initially represents the height field +// with two triangles (whose vertices are at the four corners of the +// image). These two triangles form a Delaunay triangulation. In an iterative +// fashion, the point in the image with the greatest error (as compared to +// the original height field) is injected into the triangulation. (Note that +// the single point with the greatest error per triangle is identified and +// placed into a priority queue. As the triangulation is modified, the errors +// from the deleted triangles are removed from the queue, error values from +// the new triangles are added.) The point whose error is at the top of the +// queue is added to the triangulaion modifying it using the standard +// incremental Delaunay point insertion (see vtkDelaunay2D) algorithm. Points +// are repeatedly inserted until the appropriate (user-specified) error +// criterion is met. +// +// To use this filter, set the input and specify the error measure to be +// used. The error measure options are 1) the absolute number of triangles +// to be produced; 2) a fractional reduction of the mesh (numTris/maxTris) +// where maxTris is the largest possible number of triangles +// 2*(dims[0]-1)*(dims[1]-1); 3) an absolute measure on error (maximum +// difference in height field to reduced TIN); and 4) relative error (the +// absolute error is normalized by the diagonal of the bounding box of the +// height field). +// +// .SECTION Caveats +// This algorithm requires the entire input dataset to be in memory, hence it +// may not work for extremely large images. Invoking BoundaryVertexDeletionOff +// will allow you to stitch together images with matching boundaries. +// +// The input height image is assumed to be positioned in the x-y plane so the +// scalar value is the z-coordinate, height value. +// +// .SECTION See Also +// vtkDecimatePro vtkQuadricDecimation vtkQuadricClustering + +#ifndef __vtkGreedyTerrainDecimation_h +#define __vtkGreedyTerrainDecimation_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPriorityQueue; +class vtkDataArray; +class vtkPointData; +class vtkIdList; +class vtkDoubleArray; +class vtkFloatArray; + +//PIMPL Encapsulation for STL containers +class vtkGreedyTerrainDecimationTerrainInfoType; +class vtkGreedyTerrainDecimationPointInfoType; + +#define VTK_ERROR_NUMBER_OF_TRIANGLES 0 +#define VTK_ERROR_SPECIFIED_REDUCTION 1 +#define VTK_ERROR_ABSOLUTE 2 +#define VTK_ERROR_RELATIVE 3 + +class VTK_HYBRID_EXPORT vtkGreedyTerrainDecimation : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGreedyTerrainDecimation,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the class. + static vtkGreedyTerrainDecimation* New(); + + // Description: + // Specify how to terminate the algorithm: either as an absolute number of + // triangles, a relative number of triangles (normalized by the full + // resolution mesh), an absolute error (in the height field), or relative + // error (normalized by the length of the diagonal of the image). + vtkSetClampMacro(ErrorMeasure,int,VTK_ERROR_NUMBER_OF_TRIANGLES,VTK_ERROR_RELATIVE); + vtkGetMacro(ErrorMeasure,int); + void SetErrorMeasureToNumberOfTriangles() + {this->SetErrorMeasure(VTK_ERROR_NUMBER_OF_TRIANGLES);} + void SetErrorMeasureToSpecifiedReduction() + {this->SetErrorMeasure(VTK_ERROR_SPECIFIED_REDUCTION);} + void SetErrorMeasureToAbsoluteError() + {this->SetErrorMeasure(VTK_ERROR_ABSOLUTE);} + void SetErrorMeasureToRelativeError() + {this->SetErrorMeasure(VTK_ERROR_RELATIVE);} + + // Description: + // Specify the number of triangles to produce on output. (It is a + // good idea to make sure this is less than a tessellated mesh + // at full resolution.) You need to set this value only when + // the error measure is set to NumberOfTriangles. + vtkSetClampMacro(NumberOfTriangles,vtkIdType,2,VTK_LARGE_ID); + vtkGetMacro(NumberOfTriangles,vtkIdType); + + // Description: + // Specify the reduction of the mesh (represented as a fraction). Note + // that a value of 0.10 means a 10% reduction. You need to set this value + // only when the error measure is set to SpecifiedReduction. + vtkSetClampMacro(Reduction,double,0.0,1.0); + vtkGetMacro(Reduction,double); + + // Description: + // Specify the absolute error of the mesh; that is, the error in height + // between the decimated mesh and the original height field. You need to + // set this value only when the error measure is set to AbsoluteError. + vtkSetClampMacro(AbsoluteError,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(AbsoluteError,double); + + // Description: + // Specify the relative error of the mesh; that is, the error in height + // between the decimated mesh and the original height field normalized by + // the diagonal of the image. You need to set this value only when the + // error measure is set to RelativeError. + vtkSetClampMacro(RelativeError,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(RelativeError,double); + + // Description: + // Turn on/off the deletion of vertices on the boundary of a mesh. This + // may limit the maximum reduction that may be achieved. + vtkSetMacro(BoundaryVertexDeletion,int); + vtkGetMacro(BoundaryVertexDeletion,int); + vtkBooleanMacro(BoundaryVertexDeletion,int); + + // Description: + // Compute normals based on the input image. Off by default. + vtkSetMacro(ComputeNormals, int); + vtkGetMacro(ComputeNormals, int); + vtkBooleanMacro(ComputeNormals, int); + +protected: + vtkGreedyTerrainDecimation(); + ~vtkGreedyTerrainDecimation(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int ComputeNormals; + vtkFloatArray* Normals; + void ComputePointNormal(int i, int j, float n[3]); + + //ivars that the API addresses + int ErrorMeasure; + vtkIdType NumberOfTriangles; + double Reduction; + double AbsoluteError; + double RelativeError; + int BoundaryVertexDeletion; //Can we delete boundary vertices? + + //Used for convenience + vtkPolyData *Mesh; + vtkPointData *InputPD; + vtkPointData *OutputPD; + vtkDoubleArray *Points; + vtkDataArray *Heights; + vtkIdType CurrentPointId; + double Tolerance; + vtkIdList *Neighbors; + int Dimensions[3]; + double Origin[3]; + double Spacing[3]; + vtkIdType MaximumNumberOfTriangles; + double Length; + + //Bookeeping arrays + vtkPriorityQueue *TerrainError; //errors for each pt in height field + vtkGreedyTerrainDecimationTerrainInfoType *TerrainInfo; //owning triangle for each pt + vtkGreedyTerrainDecimationPointInfoType *PointInfo; //map mesh pt id to input pt id + + //Make a guess at initial allocation + void EstimateOutputSize(const vtkIdType numInputPts, vtkIdType &numPts, vtkIdType &numTris); + + //Returns non-zero if the error measure is satisfied. + virtual int SatisfiesErrorMeasure(double error); + + //Insert all the boundary vertices into the TIN + void InsertBoundaryVertices(); + + //Insert a point into the triangulation; get a point from the triangulation + vtkIdType AddPointToTriangulation(vtkIdType inputPtId); + vtkIdType InsertNextPoint(vtkIdType inputPtId, double x[3]); + double *GetPoint(vtkIdType id); + void GetPoint(vtkIdType id, double x[3]); + + //Helper functions + void GetTerrainPoint(int i, int j, double x[3]); + void ComputeImageCoordinates(vtkIdType inputPtId, int ij[2]); + int InCircle (double x[3], double x1[3], double x2[3], double x3[3]); + vtkIdType FindTriangle(double x[3], vtkIdType ptIds[3], vtkIdType tri, + double tol, vtkIdType nei[3], vtkIdList *neighbors, int& status); + void CheckEdge(vtkIdType ptId, double x[3], vtkIdType p1, vtkIdType p2, + vtkIdType tri, int depth); + + void UpdateTriangles(vtkIdType meshPtId); //update all points connected to this point + void UpdateTriangle(vtkIdType triId, vtkIdType p1, vtkIdType p2, vtkIdType p3); + void UpdateTriangle(vtkIdType triId, int ij1[2], int ij2[2], int ij3[2], double h[4]); + + int CharacterizeTriangle(int ij1[2], int ij2[2], int ij[3], + int* &min, int* &max, int* &midL, int* &midR, + int* &mid, int mid2[2], double h[3], double &hMin, double &hMax, + double &hL, double &hR); + +private: + vtkGreedyTerrainDecimation(const vtkGreedyTerrainDecimation&); // Not implemented. + void operator=(const vtkGreedyTerrainDecimation&); // Not implemented. + +}; + +#endif diff --git a/Hybrid/vtkGridTransform.cxx b/Hybrid/vtkGridTransform.cxx new file mode 100644 index 0000000..e054501 --- /dev/null +++ b/Hybrid/vtkGridTransform.cxx @@ -0,0 +1,1238 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGridTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGridTransform.h" + +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +#include "math.h" + +vtkCxxRevisionMacro(vtkGridTransform, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkGridTransform); + +vtkCxxSetObjectMacro(vtkGridTransform,DisplacementGrid,vtkImageData); + + +//-------------------------------------------------------------------------- +// The 'floor' function on x86 and mips is many times slower than these +// and is used a lot in this code, optimize for different CPU architectures +template +inline int vtkGridFloor(double x, F &f) +{ +#if defined mips || defined sparc || defined __ppc__ + x += 2147483648.0; + unsigned int i = (unsigned int)(x); + f = x - i; + return (int)(i - 2147483648U); +#elif defined i386 || defined _M_IX86 + union { double d; unsigned short s[4]; unsigned int i[2]; } dual; + dual.d = x + 103079215104.0; // (2**(52-16))*1.5 + f = dual.s[0]*0.0000152587890625; // 2**(-16) + return (int)((dual.i[1]<<16)|((dual.i[0])>>16)); +#elif defined ia64 || defined __ia64__ || defined IA64 + x += 103079215104.0; + long long i = (long long)(x); + f = x - i; + return (int)(i - 103079215104LL); +#else + double y = floor(x); + f = x - y; + return (int)(y); +#endif +} + +inline int vtkGridRound(double x) +{ +#if defined mips || defined sparc || defined __ppc__ + return (int)((unsigned int)(x + 2147483648.5) - 2147483648U); +#elif defined i386 || defined _M_IX86 + union { double d; unsigned int i[2]; } dual; + dual.d = x + 103079215104.5; // (2**(52-16))*1.5 + return (int)((dual.i[1]<<16)|((dual.i[0])>>16)); +#elif defined ia64 || defined __ia64__ || defined IA64 + x += 103079215104.5; + long long i = (long long)(x); + return (int)(i - 103079215104LL); +#else + return (int)(floor(x+0.5)); +#endif +} + +//---------------------------------------------------------------------------- +// Nearest-neighbor interpolation of a displacement grid. +// The displacement as well as the derivatives are returned. +// There are two versions: one which computes the derivatives, +// and one which doesn't. + +template +inline void vtkNearestHelper(double displacement[3], T *gridPtr, int increment) +{ + gridPtr += increment; + displacement[0] = gridPtr[0]; + displacement[1] = gridPtr[1]; + displacement[2] = gridPtr[2]; +} + +inline void vtkNearestNeighborInterpolation(double point[3], + double displacement[3], + void *gridPtr, int gridType, + int gridExt[6], + vtkIdType gridInc[3]) +{ + int gridId[3]; + gridId[0] = vtkGridRound(point[0])-gridExt[0]; + gridId[1] = vtkGridRound(point[1])-gridExt[2]; + gridId[2] = vtkGridRound(point[2])-gridExt[4]; + + int ext[3]; + ext[0] = gridExt[1]-gridExt[0]; + ext[1] = gridExt[3]-gridExt[2]; + ext[2] = gridExt[5]-gridExt[4]; + + // do bounds check, most points will be inside so optimize for that + if ((gridId[0] | (ext[0] - gridId[0]) | + gridId[1] | (ext[1] - gridId[1]) | + gridId[2] | (ext[2] - gridId[2])) < 0) + { + for (int i = 0; i < 3; i++) + { + if (gridId[i] < 0) + { + gridId[i] = 0; + } + else if (gridId[i] > ext[i]) + { + gridId[i] = ext[i]; + } + } + } + + // do nearest-neighbor interpolation + vtkIdType increment = gridId[0]*gridInc[0] + + gridId[1]*gridInc[1] + + gridId[2]*gridInc[2]; + + switch (gridType) + { + vtkTemplateMacro( + vtkNearestHelper(displacement, static_cast(gridPtr), increment)); + } +} + +template +inline void vtkNearestHelper(double displacement[3], double derivatives[3][3], + T *gridPtr, int gridId[3], int gridId0[3], + int gridId1[3], vtkIdType gridInc[3]) +{ + vtkIdType incX = gridId[0]*gridInc[0]; + vtkIdType incY = gridId[1]*gridInc[1]; + vtkIdType incZ = gridId[2]*gridInc[2]; + + T *gridPtr0; + T *gridPtr1 = gridPtr + incX + incY + incZ; + + displacement[0] = gridPtr1[0]; + displacement[1] = gridPtr1[1]; + displacement[2] = gridPtr1[2]; + + vtkIdType incX0 = gridId0[0]*gridInc[0]; + vtkIdType incX1 = gridId1[0]*gridInc[0]; + vtkIdType incY0 = gridId0[1]*gridInc[1]; + + vtkIdType incY1 = gridId1[1]*gridInc[1]; + vtkIdType incZ0 = gridId0[2]*gridInc[2]; + vtkIdType incZ1 = gridId1[2]*gridInc[2]; + + gridPtr0 = gridPtr + incX0 + incY + incZ; + gridPtr1 = gridPtr + incX1 + incY + incZ; + + derivatives[0][0] = gridPtr1[0] - gridPtr0[0]; + derivatives[1][0] = gridPtr1[1] - gridPtr0[1]; + derivatives[2][0] = gridPtr1[2] - gridPtr0[2]; + + gridPtr0 = gridPtr + incX + incY0 + incZ; + gridPtr1 = gridPtr + incX + incY1 + incZ; + + derivatives[0][1] = gridPtr1[0] - gridPtr0[0]; + derivatives[1][1] = gridPtr1[1] - gridPtr0[1]; + derivatives[2][1] = gridPtr1[2] - gridPtr0[2]; + + gridPtr0 = gridPtr + incX + incY + incZ0; + gridPtr1 = gridPtr + incX + incY + incZ1; + + derivatives[0][2] = gridPtr1[0] - gridPtr0[0]; + derivatives[1][2] = gridPtr1[1] - gridPtr0[1]; + derivatives[2][2] = gridPtr1[2] - gridPtr0[2]; +} + +void vtkNearestNeighborInterpolation(double point[3], double displacement[3], + double derivatives[3][3], void *gridPtr, + int gridType, int gridExt[6], + vtkIdType gridInc[3]) +{ + if (derivatives == NULL) + { + vtkNearestNeighborInterpolation(point,displacement,gridPtr,gridType, + gridExt,gridInc); + return; + } + + double f[3]; + int gridId0[3]; + gridId0[0] = vtkGridFloor(point[0],f[0])-gridExt[0]; + gridId0[1] = vtkGridFloor(point[1],f[1])-gridExt[2]; + gridId0[2] = vtkGridFloor(point[2],f[2])-gridExt[4]; + + int gridId[3], gridId1[3]; + gridId[0] = gridId1[0] = gridId0[0] + 1; + gridId[1] = gridId1[1] = gridId0[1] + 1; + gridId[2] = gridId1[2] = gridId0[2] + 1; + + if (f[0] < 0.5) + { + gridId[0] = gridId0[0]; + } + if (f[1] < 0.5) + { + gridId[1] = gridId0[1]; + } + if (f[2] < 0.5) + { + gridId[2] = gridId0[2]; + } + + int ext[3]; + ext[0] = gridExt[1] - gridExt[0]; + ext[1] = gridExt[3] - gridExt[2]; + ext[2] = gridExt[5] - gridExt[4]; + + // do bounds check, most points will be inside so optimize for that + if ((gridId0[0] | (ext[0] - gridId1[0]) | + gridId0[1] | (ext[1] - gridId1[1]) | + gridId0[2] | (ext[2] - gridId1[2])) < 0) + { + for (int i = 0; i < 3; i++) + { + if (gridId0[i] < 0) + { + gridId[i] = 0; + gridId0[i] = 0; + gridId1[i] = 0; + } + else if (gridId1[i] > ext[i]) + { + gridId[i] = ext[i]; + gridId0[i] = ext[i]; + gridId1[i] = ext[i]; + } + } + } + + // do nearest-neighbor interpolation + switch (gridType) + { + vtkTemplateMacro( + vtkNearestHelper(displacement, derivatives, static_cast(gridPtr), + gridId, gridId0, gridId1, gridInc)); + } +} + +//---------------------------------------------------------------------------- +// Trilinear interpolation of a displacement grid. +// The displacement as well as the derivatives are returned. + +template +inline void vtkLinearHelper(double displacement[3], double derivatives[3][3], + double fx, double fy, double fz, T *gridPtr, + int i000, int i001, int i010, int i011, + int i100, int i101, int i110, int i111) +{ + double rx = 1 - fx; + double ry = 1 - fy; + double rz = 1 - fz; + + double ryrz = ry*rz; + double ryfz = ry*fz; + double fyrz = fy*rz; + double fyfz = fy*fz; + + double rxryrz = rx*ryrz; + double rxryfz = rx*ryfz; + double rxfyrz = rx*fyrz; + double rxfyfz = rx*fyfz; + double fxryrz = fx*ryrz; + double fxryfz = fx*ryfz; + double fxfyrz = fx*fyrz; + double fxfyfz = fx*fyfz; + + if (!derivatives) + { + int i = 3; + do + { + *displacement++ = (rxryrz*gridPtr[i000] + rxryfz*gridPtr[i001] + + rxfyrz*gridPtr[i010] + rxfyfz*gridPtr[i011] + + fxryrz*gridPtr[i100] + fxryfz*gridPtr[i101] + + fxfyrz*gridPtr[i110] + fxfyfz*gridPtr[i111]); + gridPtr++; + } + while (--i); + } + else + { + double rxrz = rx*rz; + double rxfz = rx*fz; + double fxrz = fx*rz; + double fxfz = fx*fz; + + double rxry = rx*ry; + double rxfy = rx*fy; + double fxry = fx*ry; + double fxfy = fx*fy; + + double *derivative = *derivatives; + + int i = 3; + do + { + *displacement++ = (rxryrz*gridPtr[i000] + rxryfz*gridPtr[i001] + + rxfyrz*gridPtr[i010] + rxfyfz*gridPtr[i011] + + fxryrz*gridPtr[i100] + fxryfz*gridPtr[i101] + + fxfyrz*gridPtr[i110] + fxfyfz*gridPtr[i111]); + + *derivative++ = (ryrz*(gridPtr[i100] - gridPtr[i000]) + + ryfz*(gridPtr[i101] - gridPtr[i001]) + + fyrz*(gridPtr[i110] - gridPtr[i010]) + + fyfz*(gridPtr[i111] - gridPtr[i011])); + + *derivative++ = (rxrz*(gridPtr[i010] - gridPtr[i000]) + + rxfz*(gridPtr[i011] - gridPtr[i001]) + + fxrz*(gridPtr[i110] - gridPtr[i100]) + + fxfz*(gridPtr[i111] - gridPtr[i101])); + + *derivative++ = (rxry*(gridPtr[i001] - gridPtr[i000]) + + rxfy*(gridPtr[i011] - gridPtr[i010]) + + fxry*(gridPtr[i101] - gridPtr[i100]) + + fxfy*(gridPtr[i111] - gridPtr[i110])); + + gridPtr++; + } + while (--i); + } +} + +void vtkTrilinearInterpolation(double point[3], double displacement[3], + double derivatives[3][3], void *gridPtr, int gridType, + int gridExt[6], vtkIdType gridInc[3]) +{ + // change point into integer plus fraction + double f[3]; + int floorX = vtkGridFloor(point[0],f[0]); + int floorY = vtkGridFloor(point[1],f[1]); + int floorZ = vtkGridFloor(point[2],f[2]); + + int gridId0[3]; + gridId0[0] = floorX - gridExt[0]; + gridId0[1] = floorY - gridExt[2]; + gridId0[2] = floorZ - gridExt[4]; + + int gridId1[3]; + gridId1[0] = gridId0[0] + 1; + gridId1[1] = gridId0[1] + 1; + gridId1[2] = gridId0[2] + 1; + + int ext[3]; + ext[0] = gridExt[1] - gridExt[0]; + ext[1] = gridExt[3] - gridExt[2]; + ext[2] = gridExt[5] - gridExt[4]; + + // do bounds check, most points will be inside so optimize for that + if ((gridId0[0] | (ext[0] - gridId1[0]) | + gridId0[1] | (ext[1] - gridId1[1]) | + gridId0[2] | (ext[2] - gridId1[2])) < 0) + { + for (int i = 0; i < 3; i++) + { + if (gridId0[i] < 0) + { + gridId0[i] = 0; + gridId1[i] = 0; + f[i] = 0; + } + else if (gridId1[i] > ext[i]) + { + gridId0[i] = ext[i]; + gridId1[i] = ext[i]; + f[i] = 0; + } + } + } + + // do trilinear interpolation + vtkIdType factX0 = gridId0[0]*gridInc[0]; + vtkIdType factY0 = gridId0[1]*gridInc[1]; + vtkIdType factZ0 = gridId0[2]*gridInc[2]; + + vtkIdType factX1 = gridId1[0]*gridInc[0]; + vtkIdType factY1 = gridId1[1]*gridInc[1]; + vtkIdType factZ1 = gridId1[2]*gridInc[2]; + + vtkIdType i000 = factX0+factY0+factZ0; + vtkIdType i001 = factX0+factY0+factZ1; + vtkIdType i010 = factX0+factY1+factZ0; + vtkIdType i011 = factX0+factY1+factZ1; + vtkIdType i100 = factX1+factY0+factZ0; + vtkIdType i101 = factX1+factY0+factZ1; + vtkIdType i110 = factX1+factY1+factZ0; + vtkIdType i111 = factX1+factY1+factZ1; + + switch (gridType) + { + vtkTemplateMacro(vtkLinearHelper(displacement, derivatives, f[0], f[1], f[2], + static_cast(gridPtr), + i000, i001, i010, i011, i100, i101, i110, i111)); + } +} + +//---------------------------------------------------------------------------- +// Do tricubic interpolation of the input data 'gridPtr' of extent 'gridExt' +// at the 'point'. The result is placed at 'outPtr'. +// The number of scalar components in the data is 'numscalars' + +// The tricubic interpolation ensures that both the intensity and +// the first derivative of the intensity are smooth across the +// image. The first derivative is estimated using a +// centered-difference calculation. + + +// helper function: set up the lookup indices and the interpolation +// coefficients + +void vtkSetTricubicInterpCoeffs(double F[4], int *l, int *m, double f, + int interpMode) +{ + double fp1,fm1,fm2; + + switch (interpMode) + { + case 7: // cubic interpolation + *l = 0; *m = 4; + fm1 = f-1; + F[0] = -f*fm1*fm1/2; + F[1] = ((3*f-2)*f-2)*fm1/2; + F[2] = -((3*f-4)*f-1)*f/2; + F[3] = f*f*fm1/2; + break; + case 0: // no interpolation + case 2: + case 4: + case 6: + *l = 1; *m = 2; + F[0] = 0; + F[1] = 1; + F[2] = 0; + F[3] = 0; + break; + case 1: // linear interpolation + *l = 1; *m = 3; + F[0] = 0; + F[1] = 1-f; + F[2] = f; + F[3] = 0; + break; + case 3: // quadratic interpolation + *l = 1; *m = 4; + fm1 = f-1; fm2 = fm1-1; + F[0] = 0; + F[1] = fm1*fm2/2; + F[2] = -f*fm2; + F[3] = f*fm1/2; + break; + case 5: // quadratic interpolation + *l = 0; *m = 3; + fp1 = f+1; fm1 = f-1; + F[0] = f*fm1/2; + F[1] = -fp1*fm1; + F[2] = fp1*f/2; + F[3] = 0; + break; + } +} + +// set coefficients to be used to find the derivative of the cubic +void vtkSetTricubicDerivCoeffs(double F[4], double G[4], int *l, int *m, + double f, int interpMode) +{ + double fp1,fm1,fm2; + + switch (interpMode) + { + case 7: // cubic interpolation + *l = 0; *m = 4; + fm1 = f-1; + F[0] = -f*fm1*fm1/2; + F[1] = ((3*f-2)*f-2)*fm1/2; + F[2] = -((3*f-4)*f-1)*f/2; + F[3] = f*f*fm1/2; + G[0] = -((3*f-4)*f+1)/2; + G[1] = (9*f-10)*f/2; + G[2] = -((9*f-8)*f-1)/2; + G[3] = (3*f-2)*f/2; + break; + case 0: // no interpolation + case 2: + case 4: + case 6: + *l = 1; *m = 2; + F[0] = 0; + F[1] = 1; + F[2] = 0; + F[3] = 0; + G[0] = 0; + G[1] = 0; + G[2] = 0; + G[3] = 0; + break; + case 1: // linear interpolation + *l = 1; *m = 3; + F[0] = 0; + F[1] = 1-f; + F[2] = f; + F[3] = 0; + G[0] = 0; + G[1] = -1; + G[2] = 1; + G[3] = 0; + break; + case 3: // quadratic interpolation + *l = 1; *m = 4; + fm1 = f-1; fm2 = fm1-1; + F[0] = 0; + F[1] = fm1*fm2/2; + F[2] = -f*fm2; + F[3] = f*fm1/2; + G[0] = 0; + G[1] = f-1.5; + G[2] = 2-2*f; + G[3] = f-0.5; + break; + case 5: // quadratic interpolation + *l = 0; *m = 3; + fp1 = f+1; fm1 = f-1; + F[0] = f*fm1/2; + F[1] = -fp1*fm1; + F[2] = fp1*f/2; + F[3] = 0; + G[0] = f-0.5; + G[1] = -2*f; + G[2] = f+0.5; + G[3] = 0; + break; + } +} + +// tricubic interpolation of a warp grid with derivatives +// (set derivatives to NULL to avoid computing them). + +template +inline void vtkCubicHelper(double displacement[3], double derivatives[3][3], + double fx, double fy, double fz, T *gridPtr, + int interpModeX, int interpModeY, int interpModeZ, + vtkIdType factX[4], vtkIdType factY[4], + vtkIdType factZ[4]) +{ + double fX[4],fY[4],fZ[4]; + double gX[4],gY[4],gZ[4]; + int jl,jm,kl,km,ll,lm; + + if (derivatives) + { + for (int i = 0; i < 3; i++) + { + derivatives[i][0] = 0.0; + derivatives[i][1] = 0.0; + derivatives[i][2] = 0.0; + } + vtkSetTricubicDerivCoeffs(fX,gX,&ll,&lm,fx,interpModeX); + vtkSetTricubicDerivCoeffs(fY,gY,&kl,&km,fy,interpModeY); + vtkSetTricubicDerivCoeffs(fZ,gZ,&jl,&jm,fz,interpModeZ); + } + else + { + vtkSetTricubicInterpCoeffs(fX,&ll,&lm,fx,interpModeX); + vtkSetTricubicInterpCoeffs(fY,&kl,&km,fy,interpModeY); + vtkSetTricubicInterpCoeffs(fZ,&jl,&jm,fz,interpModeZ); + } + + // Here is the tricubic interpolation + // (or cubic-cubic-linear, or cubic-nearest-cubic, etc) + double vY[3],vZ[3]; + displacement[0] = 0; + displacement[1] = 0; + displacement[2] = 0; + for (int j = jl; j < jm; j++) + { + T *gridPtr1 = gridPtr + factZ[j]; + vZ[0] = 0; + vZ[1] = 0; + vZ[2] = 0; + for (int k = kl; k < km; k++) + { + T *gridPtr2 = gridPtr1 + factY[k]; + vY[0] = 0; + vY[1] = 0; + vY[2] = 0; + if (!derivatives) + { + for (int l = ll; l < lm; l++) + { + T *gridPtr3 = gridPtr2 + factX[l]; + double f = fX[l]; + vY[0] += gridPtr3[0] * f; + vY[1] += gridPtr3[1] * f; + vY[2] += gridPtr3[2] * f; + } + } + else + { + for (int l = ll; l < lm; l++) + { + T *gridPtr3 = gridPtr2 + factX[l]; + double f = fX[l]; + double gff = gX[l]*fY[k]*fZ[j]; + double fgf = fX[l]*gY[k]*fZ[j]; + double ffg = fX[l]*fY[k]*gZ[j]; + double inVal = gridPtr3[0]; + vY[0] += inVal * f; + derivatives[0][0] += inVal * gff; + derivatives[0][1] += inVal * fgf; + derivatives[0][2] += inVal * ffg; + inVal = gridPtr3[1]; + vY[1] += inVal * f; + derivatives[1][0] += inVal * gff; + derivatives[1][1] += inVal * fgf; + derivatives[1][2] += inVal * ffg; + inVal = gridPtr3[2]; + vY[2] += inVal * f; + derivatives[2][0] += inVal * gff; + derivatives[2][1] += inVal * fgf; + derivatives[2][2] += inVal * ffg; + } + } + vZ[0] += vY[0]*fY[k]; + vZ[1] += vY[1]*fY[k]; + vZ[2] += vY[2]*fY[k]; + } + displacement[0] += vZ[0]*fZ[j]; + displacement[1] += vZ[1]*fZ[j]; + displacement[2] += vZ[2]*fZ[j]; + } +} + +void vtkTricubicInterpolation(double point[3], double displacement[3], + double derivatives[3][3], void *gridPtr, + int gridType, int gridExt[6], + vtkIdType gridInc[3]) +{ + vtkIdType factX[4],factY[4],factZ[4]; + + // change point into integer plus fraction + double f[3]; + int floorX = vtkGridFloor(point[0],f[0]); + int floorY = vtkGridFloor(point[1],f[1]); + int floorZ = vtkGridFloor(point[2],f[2]); + + int gridId0[3]; + gridId0[0] = floorX - gridExt[0]; + gridId0[1] = floorY - gridExt[2]; + gridId0[2] = floorZ - gridExt[4]; + + int gridId1[3]; + gridId1[0] = gridId0[0] + 1; + gridId1[1] = gridId0[1] + 1; + gridId1[2] = gridId0[2] + 1; + + int ext[3]; + ext[0] = gridExt[1] - gridExt[0]; + ext[1] = gridExt[3] - gridExt[2]; + ext[2] = gridExt[5] - gridExt[4]; + + // the doInterpX,Y,Z variables are 0 if interpolation + // does not have to be done in the specified direction. + int doInterp[3]; + doInterp[0] = 1; + doInterp[1] = 1; + doInterp[2] = 1; + + // do bounds check, most points will be inside so optimize for that + if ((gridId0[0] | (ext[0] - gridId1[0]) | + gridId0[1] | (ext[1] - gridId1[1]) | + gridId0[2] | (ext[2] - gridId1[2])) < 0) + { + for (int i = 0; i < 3; i++) + { + if (gridId0[i] < 0) + { + gridId0[i] = 0; + gridId1[i] = 0; + doInterp[i] = 0; + f[i] = 0; + } + else if (gridId1[i] > ext[i]) + { + gridId0[i] = ext[i]; + gridId1[i] = ext[i]; + doInterp[i] = 0; + f[i] = 0; + } + } + } + + // do tricubic interpolation + + for (int i = 0; i < 4; i++) + { + factX[i] = (gridId0[0]-1+i)*gridInc[0]; + factY[i] = (gridId0[1]-1+i)*gridInc[1]; + factZ[i] = (gridId0[2]-1+i)*gridInc[2]; + } + + // depending on whether we are at the edge of the + // input extent, choose the appropriate interpolation + // method to use + + int interpModeX = ((gridId0[0] > 0) << 2) + + ((gridId1[0] < ext[0]) << 1) + + doInterp[0]; + int interpModeY = ((gridId0[1] > 0) << 2) + + ((gridId1[1] < ext[1]) << 1) + + doInterp[1]; + int interpModeZ = ((gridId0[2] > 0) << 2) + + ((gridId1[2] < ext[2]) << 1) + + doInterp[2]; + + switch (gridType) + { + vtkTemplateMacro( + vtkCubicHelper(displacement, derivatives, f[0], f[1], f[2], + static_cast(gridPtr), + interpModeX, interpModeY, interpModeZ, + factX, factY, factZ)); + } +} + +//---------------------------------------------------------------------------- +vtkGridTransform::vtkGridTransform() +{ + this->InterpolationMode = VTK_GRID_LINEAR; + this->InterpolationFunction = &vtkTrilinearInterpolation; + this->DisplacementGrid = NULL; + this->DisplacementScale = 1.0; + this->DisplacementShift = 0.0; + // the grid warp has a fairly large tolerance + this->InverseTolerance = 0.01; +} + +//---------------------------------------------------------------------------- +vtkGridTransform::~vtkGridTransform() +{ + this->SetDisplacementGrid(NULL); +} + +//---------------------------------------------------------------------------- +void vtkGridTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "InterpolationMode: " + << this->GetInterpolationModeAsString() << "\n"; + os << indent << "DisplacementScale: " << this->DisplacementScale << "\n"; + os << indent << "DisplacementShift: " << this->DisplacementShift << "\n"; + os << indent << "DisplacementGrid: " << this->DisplacementGrid << "\n"; + if(this->DisplacementGrid) + { + this->DisplacementGrid->PrintSelf(os,indent.GetNextIndent()); + } +} + +//---------------------------------------------------------------------------- +// need to check the input image data to determine MTime +unsigned long vtkGridTransform::GetMTime() +{ + unsigned long mtime,result; + result = vtkWarpTransform::GetMTime(); + if (this->DisplacementGrid) + { + this->DisplacementGrid->UpdateInformation(); + + mtime = this->DisplacementGrid->GetPipelineMTime(); + result = ( mtime > result ? mtime : result ); + + mtime = this->DisplacementGrid->GetMTime(); + result = ( mtime > result ? mtime : result ); + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkGridTransform::SetInterpolationMode(int mode) +{ + if (mode == this->InterpolationMode) + { + return; + } + this->InterpolationMode = mode; + switch(mode) + { + case VTK_GRID_NEAREST: + this->InterpolationFunction = &vtkNearestNeighborInterpolation; + break; + case VTK_GRID_LINEAR: + this->InterpolationFunction = &vtkTrilinearInterpolation; + break; + case VTK_GRID_CUBIC: + this->InterpolationFunction = &vtkTricubicInterpolation; + break; + default: + vtkErrorMacro( << "SetInterpolationMode: Illegal interpolation mode"); + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkGridTransform::ForwardTransformPoint(const double inPoint[3], + double outPoint[3]) +{ + if (this->DisplacementGrid == NULL) + { + outPoint[0] = inPoint[0]; + outPoint[1] = inPoint[1]; + outPoint[2] = inPoint[2]; + return; + } + + void *gridPtr = this->GridPointer; + int gridType = this->GridScalarType; + + double *spacing = this->GridSpacing; + double *origin = this->GridOrigin; + int *extent = this->GridExtent; + vtkIdType *increments = this->GridIncrements; + + double scale = this->DisplacementScale; + double shift = this->DisplacementShift; + + double point[3]; + double displacement[3]; + + // Convert the inPoint to i,j,k indices into the deformation grid + // plus fractions + point[0] = (inPoint[0] - origin[0])/spacing[0]; + point[1] = (inPoint[1] - origin[1])/spacing[1]; + point[2] = (inPoint[2] - origin[2])/spacing[2]; + + this->InterpolationFunction(point,displacement,NULL, + gridPtr,gridType,extent,increments); + + outPoint[0] = inPoint[0] + (displacement[0]*scale + shift); + outPoint[1] = inPoint[1] + (displacement[1]*scale + shift); + outPoint[2] = inPoint[2] + (displacement[2]*scale + shift); +} + +//---------------------------------------------------------------------------- +// convert double to double +void vtkGridTransform::ForwardTransformPoint(const float point[3], + float output[3]) +{ + double fpoint[3]; + fpoint[0] = point[0]; + fpoint[1] = point[1]; + fpoint[2] = point[2]; + + this->ForwardTransformPoint(fpoint,fpoint); + + output[0] = static_cast(fpoint[0]); + output[1] = static_cast(fpoint[1]); + output[2] = static_cast(fpoint[2]); +} + +//---------------------------------------------------------------------------- +// calculate the derivative of the grid transform: only cubic interpolation +// provides well-behaved derivative so we always use that. +void vtkGridTransform::ForwardTransformDerivative(const double inPoint[3], + double outPoint[3], + double derivative[3][3]) +{ + if (this->DisplacementGrid == NULL) + { + outPoint[0] = inPoint[0]; + outPoint[1] = inPoint[1]; + outPoint[2] = inPoint[2]; + vtkMath::Identity3x3(derivative); + return; + } + + void *gridPtr = this->GridPointer; + int gridType = this->GridScalarType; + + double *spacing = this->GridSpacing; + double *origin = this->GridOrigin; + int *extent = this->GridExtent; + vtkIdType *increments = this->GridIncrements; + + double scale = this->DisplacementScale; + double shift = this->DisplacementShift; + + double point[3]; + double displacement[3]; + + // convert the inPoint to i,j,k indices plus fractions + point[0] = (inPoint[0] - origin[0])/spacing[0]; + point[1] = (inPoint[1] - origin[1])/spacing[1]; + point[2] = (inPoint[2] - origin[2])/spacing[2]; + + this->InterpolationFunction(point,displacement,derivative, + gridPtr,gridType,extent,increments); + + for (int i = 0; i < 3; i++) + { + derivative[i][0] = derivative[i][0]*scale/spacing[0]; + derivative[i][1] = derivative[i][1]*scale/spacing[1]; + derivative[i][2] = derivative[i][2]*scale/spacing[2]; + derivative[i][i] += 1.0; + } + + outPoint[0] = inPoint[0] + (displacement[0]*scale + shift); + outPoint[1] = inPoint[1] + (displacement[1]*scale + shift); + outPoint[2] = inPoint[2] + (displacement[2]*scale + shift); +} + +//---------------------------------------------------------------------------- +// convert double to double +void vtkGridTransform::ForwardTransformDerivative(const float point[3], + float output[3], + float derivative[3][3]) +{ + double fpoint[3]; + double fderivative[3][3]; + fpoint[0] = point[0]; + fpoint[1] = point[1]; + fpoint[2] = point[2]; + + this->ForwardTransformDerivative(fpoint,fpoint,fderivative); + + for (int i = 0; i < 3; i++) + { + derivative[i][0] = static_cast(fderivative[i][0]); + derivative[i][1] = static_cast(fderivative[i][1]); + derivative[i][2] = static_cast(fderivative[i][2]); + output[i] = static_cast(fpoint[i]); + } +} + +//---------------------------------------------------------------------------- +// We use Newton's method to iteratively invert the transformation. +// This is actally quite robust as long as the Jacobian matrix is never +// singular. +// Note that this is similar to vtkWarpTransform::InverseTransformPoint() +// but has been optimized specifically for grid transforms. +void vtkGridTransform::InverseTransformDerivative(const double inPoint[3], + double outPoint[3], + double derivative[3][3]) +{ + if (this->DisplacementGrid == NULL) + { + outPoint[0] = inPoint[0]; + outPoint[1] = inPoint[1]; + outPoint[2] = inPoint[2]; + return; + } + + void *gridPtr = this->GridPointer; + int gridType = this->GridScalarType; + + double *spacing = this->GridSpacing; + double *origin = this->GridOrigin; + int *extent = this->GridExtent; + vtkIdType *increments = this->GridIncrements; + + double invSpacing[3]; + invSpacing[0] = 1.0/spacing[0]; + invSpacing[1] = 1.0/spacing[1]; + invSpacing[2] = 1.0/spacing[2]; + + double shift = this->DisplacementShift; + double scale = this->DisplacementScale; + + double point[3], inverse[3], lastInverse[3]; + double deltaP[3], deltaI[3]; + + double functionValue = 0; + double functionDerivative = 0; + double lastFunctionValue = VTK_DOUBLE_MAX; + + double errorSquared = 0.0; + double toleranceSquared = this->InverseTolerance; + toleranceSquared *= toleranceSquared; + + double f = 1.0; + double a; + + // convert the inPoint to i,j,k indices plus fractions + point[0] = (inPoint[0] - origin[0])*invSpacing[0]; + point[1] = (inPoint[1] - origin[1])*invSpacing[1]; + point[2] = (inPoint[2] - origin[2])*invSpacing[2]; + + // first guess at inverse point, just subtract displacement + // (the inverse point is given in i,j,k indices plus fractions) + this->InterpolationFunction(point, deltaP, NULL, + gridPtr, gridType, extent, increments); + + inverse[0] = point[0] - (deltaP[0]*scale + shift)*invSpacing[0]; + inverse[1] = point[1] - (deltaP[1]*scale + shift)*invSpacing[1]; + inverse[2] = point[2] - (deltaP[2]*scale + shift)*invSpacing[2]; + lastInverse[0] = inverse[0]; + lastInverse[1] = inverse[1]; + lastInverse[2] = inverse[2]; + + // do a maximum 500 iterations, usually less than 10 are required + int n = this->InverseIterations; + int i, j; + + for (i = 0; i < n; i++) + { + this->InterpolationFunction(inverse, deltaP, derivative, + gridPtr, gridType, extent, increments); + + // convert displacement + deltaP[0] = (inverse[0] - point[0])*spacing[0] + deltaP[0]*scale + shift; + deltaP[1] = (inverse[1] - point[1])*spacing[1] + deltaP[1]*scale + shift; + deltaP[2] = (inverse[2] - point[2])*spacing[2] + deltaP[2]*scale + shift; + + // convert derivative + for (j = 0; j < 3; j++) + { + derivative[j][0] = derivative[j][0]*scale*invSpacing[0]; + derivative[j][1] = derivative[j][1]*scale*invSpacing[1]; + derivative[j][2] = derivative[j][2]*scale*invSpacing[2]; + derivative[j][j] += 1.0; + } + + // get the current function value + functionValue = (deltaP[0]*deltaP[0] + + deltaP[1]*deltaP[1] + + deltaP[2]*deltaP[2]); + + // if the function value is decreasing, do next Newton step + // (the f < 1.0 is there because I found that convergence + // is more stable if only a single reduction step is done) + if (functionValue < lastFunctionValue || f < 1.0) + { + // here is the critical step in Newton's method + vtkMath::LinearSolve3x3(derivative,deltaP,deltaI); + + // get the error value in the output coord space + errorSquared = (deltaI[0]*deltaI[0] + + deltaI[1]*deltaI[1] + + deltaI[2]*deltaI[2]); + + // break if less than tolerance in both coordinate systems + if (errorSquared < toleranceSquared && + functionValue < toleranceSquared) + { + break; + } + + // save the last inverse point + lastInverse[0] = inverse[0]; + lastInverse[1] = inverse[1]; + lastInverse[2] = inverse[2]; + + // save error at last inverse point + lastFunctionValue = functionValue; + + // derivative of functionValue at last inverse point + functionDerivative = (deltaP[0]*derivative[0][0]*deltaI[0] + + deltaP[1]*derivative[1][1]*deltaI[1] + + deltaP[2]*derivative[2][2]*deltaI[2])*2; + + // calculate new inverse point + inverse[0] -= deltaI[0]*invSpacing[0]; + inverse[1] -= deltaI[1]*invSpacing[1]; + inverse[2] -= deltaI[2]*invSpacing[2]; + + // reset f to 1.0 + f = 1.0; + + continue; + } + + // the error is increasing, so take a partial step + // (see Numerical Recipes 9.7 for rationale, this code + // is a simplification of the algorithm provided there) + + // quadratic approximation to find best fractional distance + a = -functionDerivative/(2*(functionValue - + lastFunctionValue - + functionDerivative)); + + // clamp to range [0.1,0.5] + f *= (a < 0.1 ? 0.1 : (a > 0.5 ? 0.5 : a)); + + // re-calculate inverse using fractional distance + inverse[0] = lastInverse[0] - f*deltaI[0]*invSpacing[0]; + inverse[1] = lastInverse[1] - f*deltaI[1]*invSpacing[1]; + inverse[2] = lastInverse[2] - f*deltaI[2]*invSpacing[2]; + } + + vtkDebugMacro("Inverse Iterations: " << (i+1)); + + if (i >= n) + { + // didn't converge: back up to last good result + inverse[0] = lastInverse[0]; + inverse[1] = lastInverse[1]; + inverse[2] = lastInverse[2]; + + vtkWarningMacro("InverseTransformPoint: no convergence (" << + inPoint[0] << ", " << inPoint[1] << ", " << inPoint[2] << + ") error = " << sqrt(errorSquared) << " after " << + i << " iterations."); + } + + // convert point + outPoint[0] = inverse[0]*spacing[0] + origin[0]; + outPoint[1] = inverse[1]*spacing[1] + origin[1]; + outPoint[2] = inverse[2]*spacing[2] + origin[2]; +} + +//---------------------------------------------------------------------------- +// convert double to double and back again +void vtkGridTransform::InverseTransformDerivative(const float point[3], + float output[3], + float derivative[3][3]) +{ + double fpoint[3]; + double fderivative[3][3]; + fpoint[0] = point[0]; + fpoint[1] = point[1]; + fpoint[2] = point[2]; + + this->InverseTransformDerivative(fpoint,fpoint,fderivative); + + for (int i = 0; i < 3; i++) + { + output[i] = static_cast(fpoint[i]); + derivative[i][0] = static_cast(fderivative[i][0]); + derivative[i][1] = static_cast(fderivative[i][1]); + derivative[i][2] = static_cast(fderivative[i][2]); + } +} + +//---------------------------------------------------------------------------- +void vtkGridTransform::InverseTransformPoint(const double point[3], + double output[3]) +{ + // the derivative won't be used, but it is required for Newton's method + double derivative[3][3]; + this->InverseTransformDerivative(point,output,derivative); +} + +//---------------------------------------------------------------------------- +// convert double to double and back again +void vtkGridTransform::InverseTransformPoint(const float point[3], + float output[3]) +{ + double fpoint[3]; + double fderivative[3][3]; + fpoint[0] = point[0]; + fpoint[1] = point[1]; + fpoint[2] = point[2]; + + this->InverseTransformDerivative(fpoint,fpoint,fderivative); + + output[0] = static_cast(fpoint[0]); + output[1] = static_cast(fpoint[1]); + output[2] = static_cast(fpoint[2]); +} + +//---------------------------------------------------------------------------- +void vtkGridTransform::InternalDeepCopy(vtkAbstractTransform *transform) +{ + vtkGridTransform *gridTransform = (vtkGridTransform *)transform; + + this->SetInverseTolerance(gridTransform->InverseTolerance); + this->SetInverseIterations(gridTransform->InverseIterations); + this->SetInterpolationMode(gridTransform->InterpolationMode); + this->InterpolationFunction = gridTransform->InterpolationFunction; + this->SetDisplacementScale(gridTransform->DisplacementScale); + this->SetDisplacementGrid(gridTransform->DisplacementGrid); + this->SetDisplacementShift(gridTransform->DisplacementShift); + this->SetDisplacementScale(gridTransform->DisplacementScale); + + if (this->InverseFlag != gridTransform->InverseFlag) + { + this->InverseFlag = gridTransform->InverseFlag; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkGridTransform::InternalUpdate() +{ + vtkImageData *grid = this->DisplacementGrid; + + if (grid == 0) + { + return; + } + + grid->UpdateInformation(); + + if (grid->GetNumberOfScalarComponents() != 3) + { + vtkErrorMacro(<< "TransformPoint: displacement grid must have 3 components"); + return; + } + if (grid->GetScalarType() != VTK_CHAR && + grid->GetScalarType() != VTK_UNSIGNED_CHAR && + grid->GetScalarType() != VTK_SHORT && + grid->GetScalarType() != VTK_UNSIGNED_SHORT && + grid->GetScalarType() != VTK_FLOAT && + grid->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "TransformPoint: displacement grid is of unsupported numerical type"); + return; + } + + grid->SetUpdateExtent(grid->GetWholeExtent()); + grid->Update(); + + this->GridPointer = grid->GetScalarPointer(); + this->GridScalarType = grid->GetScalarType(); + + grid->GetSpacing(this->GridSpacing); + grid->GetOrigin(this->GridOrigin); + grid->GetExtent(this->GridExtent); + grid->GetIncrements(this->GridIncrements); +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkGridTransform::MakeTransform() +{ + return vtkGridTransform::New(); +} diff --git a/Hybrid/vtkGridTransform.h b/Hybrid/vtkGridTransform.h new file mode 100644 index 0000000..4bbc7f5 --- /dev/null +++ b/Hybrid/vtkGridTransform.h @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGridTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGridTransform - a nonlinear warp transformation +// .SECTION Description +// vtkGridTransform describes a nonlinear warp transformation as a set +// of displacement vectors sampled along a uniform 3D grid. +// .SECTION Caveats +// The inverse grid transform is calculated using an iterative method, +// and is several times more expensive than the forward transform. +// .SECTION see also +// vtkThinPlateSplineTransform vtkGeneralTransform vtkTransformToGrid + + +#ifndef __vtkGridTransform_h +#define __vtkGridTransform_h + +#include "vtkWarpTransform.h" + +class vtkImageData; + +#define VTK_GRID_NEAREST 0 +#define VTK_GRID_LINEAR 1 +#define VTK_GRID_CUBIC 3 + +class VTK_HYBRID_EXPORT vtkGridTransform : public vtkWarpTransform +{ +public: + static vtkGridTransform *New(); + vtkTypeRevisionMacro(vtkGridTransform,vtkWarpTransform); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the grid transform (the grid transform must have three + // components for displacement in x, y, and z respectively). + // The vtkGridTransform class will never modify the data. + virtual void SetDisplacementGrid(vtkImageData*); + vtkGetObjectMacro(DisplacementGrid,vtkImageData); + + // Description: + // Set scale factor to be applied to the displacements. + // This is used primarily for grids which contain integer + // data types. Default: 1 + vtkSetMacro(DisplacementScale,double); + vtkGetMacro(DisplacementScale,double); + + // Description: + // Set a shift to be applied to the displacements. The shift + // is applied after the scale, i.e. x = scale*y + shift. + // Default: 0 + vtkSetMacro(DisplacementShift,double); + vtkGetMacro(DisplacementShift,double); + + // Description: + // Set interpolation mode for sampling the grid. Higher-order + // interpolation allows you to use a sparser grid. + // Default: Linear. + void SetInterpolationMode(int mode); + vtkGetMacro(InterpolationMode,int); + void SetInterpolationModeToNearestNeighbor() + { this->SetInterpolationMode(VTK_GRID_NEAREST); }; + void SetInterpolationModeToLinear() + { this->SetInterpolationMode(VTK_GRID_LINEAR); }; + void SetInterpolationModeToCubic() + { this->SetInterpolationMode(VTK_GRID_CUBIC); }; + const char *GetInterpolationModeAsString(); + + // Description: + // Make another transform of the same type. + vtkAbstractTransform *MakeTransform(); + + // Description: + // Get the MTime. + unsigned long GetMTime(); + +protected: + vtkGridTransform(); + ~vtkGridTransform(); + + // Description: + // Update the displacement grid. + void InternalUpdate(); + + // Description: + // Copy this transform from another of the same type. + void InternalDeepCopy(vtkAbstractTransform *transform); + + // Description: + // Internal functions for calculating the transformation. + void ForwardTransformPoint(const float in[3], float out[3]); + void ForwardTransformPoint(const double in[3], double out[3]); + + void ForwardTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void ForwardTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + void InverseTransformPoint(const float in[3], float out[3]); + void InverseTransformPoint(const double in[3], double out[3]); + + void InverseTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void InverseTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + +//BTX + void (*InterpolationFunction)(double point[3], double displacement[3], + double derivatives[3][3], + void *gridPtr, int gridType, + int inExt[6], vtkIdType inInc[3]); +//ETX + int InterpolationMode; + vtkImageData *DisplacementGrid; + double DisplacementScale; + double DisplacementShift; + + void *GridPointer; + int GridScalarType; + double GridSpacing[3]; + double GridOrigin[3]; + int GridExtent[6]; + vtkIdType GridIncrements[3]; + +private: + vtkGridTransform(const vtkGridTransform&); // Not implemented. + void operator=(const vtkGridTransform&); // Not implemented. +}; + +//BTX + +//---------------------------------------------------------------------------- +inline const char *vtkGridTransform::GetInterpolationModeAsString() +{ + switch (this->InterpolationMode) + { + case VTK_GRID_NEAREST: + return "NearestNeighbor"; + case VTK_GRID_LINEAR: + return "Linear"; + case VTK_GRID_CUBIC: + return "Cubic"; + default: + return ""; + } +} +//ETX + +#endif + + + + + diff --git a/Hybrid/vtkImageToPolyDataFilter.cxx b/Hybrid/vtkImageToPolyDataFilter.cxx new file mode 100644 index 0000000..be34207 --- /dev/null +++ b/Hybrid/vtkImageToPolyDataFilter.cxx @@ -0,0 +1,1375 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToPolyDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageToPolyDataFilter.h" + +#include "vtkAppendPolyData.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkEdgeTable.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLine.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkScalarsToColors.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkImageToPolyDataFilter, "$Revision: 1.31 $"); +vtkStandardNewMacro(vtkImageToPolyDataFilter); + +vtkCxxSetObjectMacro(vtkImageToPolyDataFilter,LookupTable,vtkScalarsToColors); + +vtkImageToPolyDataFilter::vtkImageToPolyDataFilter() +{ + this->OutputStyle = VTK_STYLE_POLYGONALIZE; + this->ColorMode = VTK_COLOR_MODE_LINEAR_256; + this->Smoothing = 1; + this->NumberOfSmoothingIterations = 40; + this->Decimation = 1; + this->DecimationError = 1.5; + this->Error = 100; + this->SubImageSize = 250; + + this->Table = vtkUnsignedCharArray::New(); + this->LookupTable = NULL; +} + +vtkImageToPolyDataFilter::~vtkImageToPolyDataFilter() +{ + this->Table->Delete(); + if ( this->LookupTable ) + { + this->LookupTable->Delete(); + } +} + +// declare helper functions +// + +int vtkImageToPolyDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPolyData *tmpOutput; + vtkPolyData *tmpInput; + vtkAppendPolyData *append; + vtkPolyData *appendOutput; + vtkDataArray *inScalars = input->GetPointData()->GetScalars(); + vtkIdType numPixels=input->GetNumberOfPoints(); + int dims[3], numComp; + double origin[3], spacing[3]; + vtkUnsignedCharArray *pixels; + int type; + int numPieces[2], extent[4]; + int i, j, newDims[3], totalPieces, pieceNum, abortExecute=0; + double newOrigin[3]; + + // Check input and initialize + vtkDebugMacro(<<"Vectorizing image..."); + + if ( inScalars == NULL || numPixels < 1 ) + { + vtkDebugMacro(<<"Not enough input to create output"); + return 1; + } + + append = vtkAppendPolyData::New(); + tmpOutput=vtkPolyData::New(); + tmpInput=vtkPolyData::New(); + numComp=inScalars->GetNumberOfComponents(); + type=inScalars->GetDataType(); + + appendOutput=append->GetOutput(); + + input->GetDimensions(dims); + input->GetOrigin(origin); + input->GetSpacing(spacing); + + // Figure out how many pieces to break the image into (the image + // might be too big to process). The filter does a series of appends + // to join the pieces together. + numPieces[0] = ((dims[0]-2) / this->SubImageSize) + 1; + numPieces[1] = ((dims[1]-2) / this->SubImageSize) + 1; + totalPieces = numPieces[0]*numPieces[1]; + + appendOutput->Initialize(); //empty the output + append->AddInput(tmpOutput); //output of piece + append->AddInput(tmpInput); //output of previoius append + + // Loop over this many pieces + for (pieceNum=j=0; j < numPieces[1] && !abortExecute; j++) + { + extent[2] = j*this->SubImageSize; //the y range + extent[3] = (j+1)*this->SubImageSize; + if ( extent[3] >= dims[1] ) + { + extent[3] = dims[1] - 1; + } + + for (i=0; i < numPieces[0] && !abortExecute; i++) + { + extent[0] = i*this->SubImageSize; //the x range + extent[1] = (i+1)*this->SubImageSize; + if ( extent[1] >= dims[0] ) + { + extent[1] = dims[0] - 1; + } + + vtkDebugMacro(<<"Processing #" << pieceNum); + this->UpdateProgress ((double)pieceNum/totalPieces); + if (this->GetAbortExecute()) + { + abortExecute = 1; + break; + } + pieceNum++; + + // Figure out characteristics of current sub-image + newDims[0] = extent[1] - extent[0] + 1; + newDims[1] = extent[3] - extent[2] + 1; + newOrigin[0] = origin[0] + extent[0]*spacing[0]; + newOrigin[1] = origin[1] + extent[2]*spacing[1]; + newOrigin[2] = 0.0; + + // Create a quantized copy of the image based on the color table + // + pixels = this->QuantizeImage(inScalars, numComp, type, dims, extent); + vtkDebugMacro(<<"Quantizing color...image size (" <OutputStyle == VTK_STYLE_PIXELIZE ) + { + this->PixelizeImage(pixels, newDims, newOrigin, spacing, tmpOutput); + } + else if ( this->OutputStyle == VTK_STYLE_RUN_LENGTH ) + { + this->RunLengthImage(pixels, newDims, newOrigin, spacing, tmpOutput); + } + else //VTK_STYLE_POLYGONALIZE + { + this->PolygonalizeImage(pixels, newDims, newOrigin, spacing,tmpOutput); + } + + // Append pieces together + // + tmpInput->CopyStructure(appendOutput); + tmpInput->GetPointData()->PassData(appendOutput->GetPointData()); + tmpInput->GetCellData()->PassData(appendOutput->GetCellData()); + append->Update(); + + // Clean up this iteration + // + pixels->Delete(); + tmpInput->Initialize(); + tmpOutput->Initialize(); + } // for i pieces + } // for j pieces + + // Create the final output contained in the append filter + output->CopyStructure(appendOutput); + output->GetPointData()->PassData(appendOutput->GetPointData()); + output->GetCellData()->PassData(appendOutput->GetCellData()); + + append->Delete(); + tmpInput->Delete(); + tmpOutput->Delete(); + + return 1; +} + +void vtkImageToPolyDataFilter::PixelizeImage(vtkUnsignedCharArray *pixels, + int dims[3], double origin[3], + double spacing[3], + vtkPolyData *output) +{ + int numPts, numCells, i, j, id; + vtkIdType pts[4]; + vtkPoints *newPts; + vtkCellArray *newPolys; + double x[3]; + vtkUnsignedCharArray *polyColors; + unsigned char *ptr, *colors=pixels->GetPointer(0); + + // create the points - see whether to create or append + numPts = (dims[0]+1) * (dims[1]+1); + newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + + x[2] = 0.0; + for (id=0, j=0; j<=dims[1]; j++) + { + x[1] = origin[1] + j*spacing[1]; + for (i=0; i<=dims[0]; i++) + { + x[0] = origin[0] + i*spacing[0]; + newPts->SetPoint(id, x); + id++; + } + } + output->SetPoints(newPts); + newPts->Delete(); + + // create the cells and cell colors + // + numCells = dims[0] * dims[1]; + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numCells,4)); + + polyColors = vtkUnsignedCharArray::New(); + polyColors->SetNumberOfValues(3*numCells); //for rgb + polyColors->SetNumberOfComponents(3); + + // loop over all pixels, creating a quad per pixel. + // Note: copying point data (pixel values) to cell data (quad colors). + for (id=0, j=0; jInsertNextCell(4, pts); + ptr = colors + 3*id; + polyColors->SetValue(3*id, ptr[0]); + polyColors->SetValue(3*id+1, ptr[1]); + polyColors->SetValue(3*id+2, ptr[2]); + id++; + } + } + + output->SetPolys(newPolys); + newPolys->Delete(); + + output->GetCellData()->SetScalars(polyColors); + polyColors->Delete(); +} + +void vtkImageToPolyDataFilter::RunLengthImage(vtkUnsignedCharArray *pixels, + int dims[3], double origin[3], + double spacing[3], + vtkPolyData *output) +{ + int i, j; + vtkIdType pts[4], id; + vtkPoints *newPts; + vtkCellArray *newPolys; + double x[3], minX, maxX, minY, maxY; + vtkUnsignedCharArray *polyColors; + unsigned char *ptr, *colors=pixels->GetPointer(0), *color; + + // Setup data + newPts = vtkPoints::New(); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(dims[0]*dims[1]/10,4)); + + polyColors = vtkUnsignedCharArray::New(); + polyColors->Allocate(3*dims[0]*dims[1]/10); //for rgb + polyColors->SetNumberOfComponents(3); + + // Loop over row-by-row generating quad polygons + x[2] = 0.0; + for (j=0; jIsSameColor(color,ptr) ) + { + break; + } + else + { + i++; + } + } + + if ( i >= dims[0] ) + { + maxX = origin[0] + (dims[0]-1)*spacing[0]; + } + else + { + maxX = origin[0] + (i-1)*spacing[0] + 0.5*spacing[0]; + } + + // Create quad cell + x[0] = minX; + x[1] = minY; + pts[0] = newPts->InsertNextPoint(x); + x[0] = maxX; + pts[1] = newPts->InsertNextPoint(x); + x[1] = maxY; + pts[2] = newPts->InsertNextPoint(x); + x[0] = minX; + pts[3] = newPts->InsertNextPoint(x); + id = newPolys->InsertNextCell(4,pts); + polyColors->InsertValue(3*id, color[0]); + polyColors->InsertValue(3*id+1, color[1]); + polyColors->InsertValue(3*id+2, color[2]); + } + } + + output->SetPoints(newPts); + newPts->Delete(); + output->SetPolys(newPolys); + newPolys->Delete(); + + output->GetCellData()->SetScalars(polyColors); + polyColors->Delete(); +} + + +void vtkImageToPolyDataFilter::PolygonalizeImage(vtkUnsignedCharArray *pixels, + int dims[3], double origin[3], double spacing[3], + vtkPolyData *output) +{ + int numPolys; + int numPixels=dims[0]*dims[1]; + + // Perform connected traversal on quantized points. This builds + // the initial "polygons" in implicit form. + // + this->PolyColors = vtkUnsignedCharArray::New(); + this->PolyColors->SetNumberOfComponents(3); + this->PolyColors->Allocate(5000); + + numPolys = this->ProcessImage(pixels, dims); + vtkDebugMacro(<<"Visited regions..." << numPolys << " polygons"); + + // Build edges around the boundary of the polygons. Also identify + // junction points where 3 or 4 polygons meet. + // + vtkPoints *points = vtkPoints::New(); + points->Allocate(numPixels/2, numPixels/2); + + vtkUnsignedCharArray *pointDescr = vtkUnsignedCharArray::New(); + pointDescr->Allocate(numPixels/2, numPixels/2); + + vtkCellArray *edgeConn = vtkCellArray::New(); + edgeConn->Allocate(numPixels/2, numPixels/2); + vtkPolyData *edges = vtkPolyData::New(); + edges->SetPoints(points); + edges->SetLines(edgeConn); + points->Delete(); + edgeConn->Delete(); + + this->BuildEdges(pixels, dims, origin, spacing, pointDescr, edges); + vtkDebugMacro(<<"Edges built..."); + + // Now that we've got the edges, we have to build the "loops" around the + // polygons that define the polygon explicitly. + // + vtkUnsignedCharArray *polyColors = vtkUnsignedCharArray::New(); + polyColors->SetNumberOfComponents(3); + polyColors->SetNumberOfValues(numPolys*3); + + this->BuildPolygons(pointDescr, edges, numPolys, polyColors); + this->PolyColors->Delete(); + delete [] this->Visited; + vtkDebugMacro(<<"Constructed polygons..."); + + // Smooth edge network. Some points are identified as fixed, others + // move using Laplacian smoothing. + // + if ( this->Smoothing ) + { + this->SmoothEdges(pointDescr, edges); + vtkDebugMacro(<<"Edges smoothed..."); + } + + // Decimate edge network. There will be colinear vertices along edges. + // These are eliminated. + // + if ( this->Decimation ) + { + this->DecimateEdges(edges, pointDescr, this->DecimationError); + } + + // Create output polydata. Each polyon is output with its edges. + // + this->GeneratePolygons(edges, numPolys, output, polyColors, pointDescr); + vtkDebugMacro(<<"Output generated..."); + + // clean up and get out + edges->Delete(); + polyColors->Delete(); + pointDescr->Delete(); +} + +// The following are private helper functions---------------------------------- +// +vtkUnsignedCharArray *vtkImageToPolyDataFilter::QuantizeImage( + vtkDataArray *inScalars, int numComp, int type, + int dims[3], int extent[4]) +{ + int numPixels, i, j, idx, id; + vtkUnsignedCharArray *pixels; + unsigned char *ptr, *ptr2, *color, *outPixels; + unsigned char *inPixels; + + // doing a portion of the image + numPixels = (extent[1]-extent[0]+1) * (extent[3]-extent[2]+1); + pixels = vtkUnsignedCharArray::New(); + pixels->SetNumberOfValues(3*numPixels); + outPixels = pixels->GetPointer(0); + + // Figure out how to quantize + // + if ( this->ColorMode == VTK_COLOR_MODE_LINEAR_256 ) + { + // Check scalar type + if ( type != VTK_UNSIGNED_CHAR || numComp != 3 ) + { + vtkErrorMacro(<<"Wrong input scalar type"); + return 0; + } + else + { + inPixels = static_cast(inScalars)->GetPointer(0); + } + + // Generate a color table used to quantize the points + // + if ( this->GetMTime() > this->TableMTime ) + { + this->BuildTable(inPixels); + } + + for (id=0, j=extent[2]; j <= extent[3]; j++) + { + for (i=extent[0]; i <= extent[1]; i++) + { + idx = i + j*dims[0]; + ptr = inPixels + 3*idx; + ptr2 = outPixels + 3*id; + color = this->GetColor(ptr); + ptr2[0] = color[0]; + ptr2[1] = color[1]; + ptr2[2] = color[2]; + id++; + } + } + }//using build in table + + else //using provided lookup table + { + if ( numComp != 1 || this->LookupTable == NULL ) + { + vtkErrorMacro(<<"LUT mode requires single component scalar and LUT"); + return 0; + } + + double s; + for (id=0, j=extent[2]; j <= extent[3]; j++) + { + for (i=extent[0]; i <= extent[1]; i++) + { + idx = i + j*dims[0]; + s = inScalars->GetComponent(idx,0); + color = this->LookupTable->MapValue(s); + ptr2 = outPixels + 3*id; + ptr2[0] = color[0]; + ptr2[1] = color[1]; + ptr2[2] = color[2]; + id++; + } + } + } + + return pixels; +} + +void vtkImageToPolyDataFilter::BuildTable(unsigned char *vtkNotUsed(inPixels)) +{ + int red, green, blue, idx=0; + + this->Table->SetNumberOfValues(256*3); + + // use 3-3-2 bits for rgb + for (blue=0; blue<256; blue+=64) + { + for (green=0; green<256; green+=32) + { + for (red=0; red<256; red+=32) + { + this->Table->SetValue(idx++, red); + this->Table->SetValue(idx++, green); + this->Table->SetValue(idx++, blue); + } + } + } +} + +int vtkImageToPolyDataFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkImageToPolyDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Output Style: "; + if ( this->OutputStyle == VTK_STYLE_PIXELIZE ) + { + os << indent << "Pixelize\n"; + } + else if ( this->OutputStyle == VTK_STYLE_RUN_LENGTH ) + { + os << indent << "RunLength\n"; + } + else // this->OutputStyle == VTK_STYLE_POLYGONALIZE + { + os << indent << "Polygonalize\n"; + } + + os << indent << "Color Mode: "; + if ( this->ColorMode == VTK_STYLE_PIXELIZE ) + { + os << indent << "LUT\n"; + } + else // this->ColorMode == VTK_STYLE_POLYGONALIZE + { + os << indent << "Linear256\n"; + } + + os << indent << "Smoothing: " << (this->Smoothing ? "On\n" : "Off\n"); + os << indent << "Number of Smoothing Iterations: " + << this->NumberOfSmoothingIterations << "\n"; + + os << indent << "Decimation: " << (this->Decimation ? "On\n" : "Off\n"); + os << indent << "Decimation Error: " + << (this->DecimationError ? "On\n" : "Off\n"); + + os << indent << "Error: " << this->Error << "\n"; + os << indent << "Sub-Image Size: " << this->SubImageSize << "\n"; + + if ( this->LookupTable ) + { + os << indent << "LookupTable:\n"; + this->LookupTable->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "LookupTable: (none)\n"; + } + +} + + +//--------------------------private helper functions--------------------------- +// Determines whether two pixels are the same color +int vtkImageToPolyDataFilter::IsSameColor(unsigned char *p1, unsigned char *p2) +{ + int d2 = (p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + + (p1[2]-p2[2])*(p1[2]-p2[2]); + + return (d2 > this->Error ? 0 : 1); +} + +unsigned char *vtkImageToPolyDataFilter::GetColor(unsigned char *rgb) +{ + // round to nearest value + int red = (rgb[0] + 16) / 32; + red = (red > 7 ? 7 : red); + int green =(rgb[1] + 16) / 32; + green = (green > 7 ? 7 : green); + int blue = (rgb[2] + 32) / 64; + blue = (blue > 3 ? 3 : blue); + + return this->Table->GetPointer(3*(red + green*8 + blue*64)); +} + +void vtkImageToPolyDataFilter::GetIJ(int id, int &i, int &j, int dims[3]) +{ + i = id % dims[0]; + j = id / dims[0]; +} + +// Get the left-right-top-bottom neighboring pixels of a given pixel +// The method has been modified to return right neighbor (mode==0); +// or top neighbor (mode==1) or all neighbors (mode==2). +int vtkImageToPolyDataFilter::GetNeighbors(unsigned char *ptr, int &i, int &j, + int dims[2],unsigned char *neighbors[4], int mode) +{ + int numNeis=0; + + if ( mode == 0 ) + { + if ( (i+1) < dims[0] ) + { + neighbors[numNeis++] = ptr + 3; //jump over rgb + } + if ( (i-1) >= 0 ) + { + neighbors[numNeis++] = ptr - 3; //jump over rgb + } + } + + else if ( mode == 1 ) + { + if ( (j+1) < dims[1] ) + { + neighbors[numNeis++] = ptr + 3*dims[0]; + } + } + + else + { + if ( (i+1) < dims[0] ) + { + neighbors[numNeis++] = ptr + 3; //jump over rgb + } + if ( (i-1) >= 0 ) + { + neighbors[numNeis++] = ptr - 3; + } + + if ( (j+1) < dims[1] ) + { + neighbors[numNeis++] = ptr + 3*dims[0]; + } + if ( (j-1) >= 0 ) + { + neighbors[numNeis++] = ptr - 3*dims[0]; + } + } + + return numNeis; + +} + + +// Marks connected regions with different colors. +int vtkImageToPolyDataFilter::ProcessImage(vtkUnsignedCharArray *scalars, + int dims[2]) +{ + int numPixels = dims[0]*dims[1]; + vtkIdList *wave, *wave2, *tmpWave; + int numIds, regionNumber, i, j, k, id, x, y, numNeighbors; + unsigned char *neighbors[4], *ptr; + unsigned char *pixels = scalars->GetPointer(0); + + // Collect groups of pixels together into similar colored regions. These + // will be eventually grouped into polygons and/or lines. + // + // mark all pixels unvisited + regionNumber = -1; + this->Visited = new int [numPixels]; + memset (this->Visited, (int)-1, numPixels*sizeof(int)); + + // set up the connected traversal + wave = vtkIdList::New(); + wave->Allocate(static_cast(numPixels/4.0), + static_cast(numPixels/4.0)); + wave2 = vtkIdList::New(); + wave2->Allocate(static_cast(numPixels/4.0), + static_cast(numPixels/4.0)); + + // visit connected pixels. Pixels are connected if they are topologically + // adjacent and they have "equal" color values. + for (i=0; i < numPixels; i++) + { + if ( this->Visited[i] == -1 ) + {//start a connected wave + this->Visited[i] = ++regionNumber; + ptr = pixels + 3*i; + this->PolyColors->InsertValue(3*regionNumber, ptr[0]); //assign color + this->PolyColors->InsertValue(3*regionNumber+1, ptr[1]); + this->PolyColors->InsertValue(3*regionNumber+2, ptr[2]); + wave->Reset(); wave2->Reset(); + + // To prevent creating polygons with inner loops, we're going to start + // the wave as a "vertical" stack of pixels, and then propogate the + // wave horizontally only. + wave->InsertId(0,i); + this->GetIJ(i, x, y, dims); + while ( (numNeighbors = this->GetNeighbors(ptr, x, y, dims, neighbors, 1)) ) + { + id = (neighbors[0] - pixels) / 3; + if ( this->Visited[id] == -1 && this->IsSameColor(ptr, neighbors[0]) ) + { + this->Visited[id] = regionNumber; + wave->InsertNextId(id); + ptr = pixels + 3*id; + this->GetIJ(id, x, y, dims); + } + else + { + break; + } + } + + // Okay, defined vertical wave, now propogate horizontally + numIds = wave->GetNumberOfIds(); + while ( numIds > 0 ) + { + for (j=0; jGetId(j); + ptr = pixels + 3*id; + this->GetIJ(id, x, y, dims); + numNeighbors = this->GetNeighbors(ptr, x, y, dims, neighbors, 0); + for (k=0; kVisited[id] == -1 && this->IsSameColor(ptr, neighbors[k]) ) + { + this->Visited[id] = regionNumber; + wave2->InsertNextId(id); + } + }//for each pixel neighbor + }//for pixels left in wave + numIds = wave2->GetNumberOfIds(); + tmpWave = wave; + wave = wave2; + wave2 = tmpWave; + wave2->Reset(); + }//while still propogating + }//if not, start wave + }//for all pixels + + wave->Delete(); + wave2->Delete(); + + return regionNumber+1; +} + +// Create polygons and place into output +void vtkImageToPolyDataFilter::GeneratePolygons(vtkPolyData *edges, + int vtkNotUsed(numPolys), vtkPolyData *output, + vtkUnsignedCharArray *polyColors, + vtkUnsignedCharArray *pointDescr) +{ + vtkCellArray *newPolys, *inPolys; + int i, numPts; + vtkIdType *pts = 0; + vtkIdType npts = 0; + + // Copy the points via reference counting + // + output->SetPoints(edges->GetPoints()); + + // Create the polygons - points may have been decimated so these + // points have to be culled. + // + inPolys = edges->GetPolys(); + newPolys = vtkCellArray::New(); + newPolys->Allocate(inPolys->GetSize()); + + for ( inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + newPolys->InsertNextCell(0); + numPts = 0; + for (i=0; iGetValue(pts[i]) != 2 ) + { + newPolys->InsertCellPoint(pts[i]); + numPts++; + } + } + newPolys->UpdateCellCount(numPts); + } + + output->SetPolys(newPolys); + newPolys->Delete(); + + output->GetCellData()->SetScalars(polyColors); +} + +// Uses clipping approach to build the polygon edges +int vtkImageToPolyDataFilter::BuildEdges(vtkUnsignedCharArray *vtkNotUsed(pixels), + int dims[3], double origin[3], + double spacing[3], + vtkUnsignedCharArray *pointDescr, + vtkPolyData *edges) +{ + double x[3]; + int i, j, edgeCount; + vtkIdType ptId, p0, p1, p2, p3, startId, attrId, id[8], pts[4]; + vtkCellArray *edgeConn = edges->GetLines(); + vtkPoints *points = edges->GetPoints(); + + // Build edges around perimeter of image. Note that the point ids + // The first four points are the image corners and are inserted and + // marked so that they can't be moved during smoothing. + points->InsertPoint(0, origin); + pointDescr->InsertValue(0, 1); + + // Keep track of the polygons that use each edge as well as associated + // intersection points on edge (if any) + this->EdgeTable = vtkEdgeTable::New(); + this->EdgeTable->InitEdgeInsertion(dims[0]*dims[1],1); + + this->EdgeUseTable = vtkEdgeTable::New(); + this->EdgeUseTable->InitEdgeInsertion(dims[0]*dims[1],1); + + this->EdgeUses = vtkIntArray::New(); + this->EdgeUses->SetNumberOfComponents(2); + this->EdgeUses->Allocate(4*dims[0]*dims[1],dims[0]*dims[1]); + + // Generate corner points of image + x[0] = origin[0] + (dims[0]-1)*spacing[0]; + x[1] = origin[1]; + x[2] = 0.0; + points->InsertPoint(1, x); + pointDescr->InsertValue(1, 1); + + x[0] = origin[0] + (dims[0]-1)*spacing[0]; + x[1] = origin[1] + (dims[1]-1)*spacing[1];; + x[2] = 0.0; + points->InsertPoint(2, x); + pointDescr->InsertValue(2, 1); + + x[0] = origin[0]; + x[1] = origin[1] + (dims[1]-1)*spacing[1]; + x[2] = 0.0; + points->InsertPoint(3, x); + pointDescr->InsertValue(3, 1); + + // Let's create perimeter edges - bottom x edge + startId = 0; + x[1] = origin[1]; + for (i=0; i<(dims[0]-1); i++) + { + p0 = i; + p1 = i + 1; + if ( this->Visited[p0] != this->Visited[p1] ) + { + x[0] = origin[0] + i*spacing[0] + 0.5*spacing[0]; + ptId = points->InsertNextPoint(x); + this->EdgeTable->InsertEdge(p0,p1,ptId); + pointDescr->InsertValue(ptId, 1); //can't be smoothed + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(ptId); + attrId = this->EdgeUseTable->InsertEdge(startId,ptId); + this->EdgeUses->InsertValue(2*attrId, this->Visited[p0]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + startId = ptId; + } + } + edgeConn->InsertNextCell(2); //finish off the edge + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(1); + attrId = this->EdgeUseTable->InsertEdge(startId,1); + this->EdgeUses->InsertValue(2*attrId, this->Visited[dims[0]-1]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + + // Let's create perimeter edges - top x edge + startId = 3; + x[1] = origin[1] + (dims[1]-1)*spacing[1]; + for (i=0; i<(dims[0]-1); i++) + { + p0 = i + dims[0]*(dims[1]-1); + p1 = p0 + 1; + if ( this->Visited[p0] != this->Visited[p1] ) + { + x[0] = origin[0] + i*spacing[0] + 0.5*spacing[0]; + ptId = points->InsertNextPoint(x); + this->EdgeTable->InsertEdge(p0,p1,ptId); + pointDescr->InsertValue(ptId, 1); //can't be smoothed + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(ptId); + attrId = this->EdgeUseTable->InsertEdge(startId,ptId); + this->EdgeUses->InsertValue(2*attrId, this->Visited[p0]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + startId = ptId; + } + } + edgeConn->InsertNextCell(2); //finish off the edge + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(2); + attrId = this->EdgeUseTable->InsertEdge(startId,2); + this->EdgeUses->InsertValue(2*attrId, this->Visited[dims[1]*dims[0]-1]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + + // Let's create perimeter edges - min y edge + startId = 0; + x[0] = origin[0]; + for (j=0; j<(dims[1]-1); j++) + { + p0 = j*dims[0]; + p1 = p0 + dims[0]; + if ( this->Visited[p0] != this->Visited[p1] ) + { + x[1] = origin[1] + j*spacing[1] + 0.5*spacing[1]; + ptId = points->InsertNextPoint(x); + this->EdgeTable->InsertEdge(p0,p1,ptId); + pointDescr->InsertValue(ptId, 1); //can't be smoothed + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(ptId); + attrId = this->EdgeUseTable->InsertEdge(startId,ptId); + this->EdgeUses->InsertValue(2*attrId, this->Visited[p0]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + startId = ptId; + } + } + edgeConn->InsertNextCell(2); //finish off the edge + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(3); + attrId = this->EdgeUseTable->InsertEdge(startId,3); + this->EdgeUses->InsertValue(2*attrId, this->Visited[(dims[1]-1)*dims[0]]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + + // Let's create perimeter edges - max y edge + startId = 1; + x[0] = origin[0] + (dims[0]-1)*spacing[0]; + for (j=0; j<(dims[1]-1); j++) + { + p0 = j*dims[0] + (dims[0]-1); + p1 = p0 + dims[0]; + if ( this->Visited[p0] != this->Visited[p1] ) + { + x[1] = origin[1] + j*spacing[1] + 0.5*spacing[1]; + ptId = points->InsertNextPoint(x); + this->EdgeTable->InsertEdge(p0,p1,ptId); + pointDescr->InsertValue(ptId, 1); //can't be smoothed + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(ptId); + attrId = this->EdgeUseTable->InsertEdge(startId,ptId); + this->EdgeUses->InsertValue(2*attrId, this->Visited[p0]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + startId = ptId; + } + } + edgeConn->InsertNextCell(2); //finish off the edge + edgeConn->InsertCellPoint(startId); + edgeConn->InsertCellPoint(2); + attrId = this->EdgeUseTable->InsertEdge(startId,2); + this->EdgeUses->InsertValue(2*attrId, this->Visited[dims[1]*dims[0]-1]); + this->EdgeUses->InsertValue(2*attrId+1, -1); + + // Loop over all edges generating intersection points and outer boundary + // edge segments. + // + for (j=1; j<(dims[1]-1); j++) //loop over all x edges (except boundary) + { + x[1] = origin[1] + j*spacing[1]; + for (i=0; i<(dims[0]-1); i++) + { + p0 = i + j*dims[0]; + p1 = p0 + 1; + if ( this->Visited[p0] != this->Visited[p1] ) + { + x[0] = origin[0] + i*spacing[0] + 0.5*spacing[0]; + ptId = points->InsertNextPoint(x); + this->EdgeTable->InsertEdge(p0,p1,ptId); + pointDescr->InsertValue(ptId, 0); + } + } + } + + for (i=1; i<(dims[0]-1); i++) //loop over all y edges (except boundary) + { + x[0] = origin[0] + i*spacing[0]; + for (j=0; j<(dims[1]-1); j++) + { + p0 = i + j*dims[0]; + p1 = i + (j+1)*dims[0]; + if ( this->Visited[p0] != this->Visited[p1] ) + { + x[1] = origin[1] + j*spacing[1] + 0.5*spacing[1]; + ptId = points->InsertNextPoint(x); + this->EdgeTable->InsertEdge(p0,p1,ptId); + pointDescr->InsertValue(ptId, 0); //can be smoothed + } + } + } + + // All intersection points are generated, now create edges. Use a clipping + // approach to create line segments. Later we'll connect them into polylines. + // + for (j=0; j<(dims[1]-1); j++) //loop over all x edges + { + for (i=0; i<(dims[0]-1); i++) + { + edgeCount = 0; + p0 = i + j*dims[0]; + p1 = p0 + 1; + p2 = i+1 + (j+1)*dims[0]; + p3 = p2 - 1; + + if ( (ptId=this->EdgeTable->IsEdge(p0,p1)) != -1 ) + { + id[2*edgeCount] = p0; id[2*edgeCount+1] = p1; + pts[edgeCount++] = ptId; + } + if ( (ptId=this->EdgeTable->IsEdge(p1,p2)) != -1 ) + { + id[2*edgeCount] = p1; id[2*edgeCount+1] = p2; + pts[edgeCount++] = ptId; + } + if ( (ptId=this->EdgeTable->IsEdge(p2,p3)) != -1 ) + { + id[2*edgeCount] = p2; id[2*edgeCount+1] = p3; + pts[edgeCount++] = ptId; + } + if ( (ptId=this->EdgeTable->IsEdge(p3,p0)) != -1 ) + { + id[2*edgeCount] = p3; id[2*edgeCount+1] = p0; + pts[edgeCount++] = ptId; + } + + if ( edgeCount == 4 ) + { + x[0] = origin[0] + i*spacing[0] + 0.5*spacing[0]; + x[1] = origin[1] + j*spacing[1] + 0.5*spacing[1]; + ptId = points->InsertNextPoint(x); + pointDescr->InsertValue(ptId, 0); //intersection points are fixed + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(ptId); + edgeConn->InsertCellPoint(pts[0]); + attrId = this->EdgeUseTable->InsertEdge(ptId,pts[0]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[0]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[1]]); + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(ptId); + edgeConn->InsertCellPoint(pts[1]); + attrId = this->EdgeUseTable->InsertEdge(ptId,pts[1]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[2]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[3]]); + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(ptId); + edgeConn->InsertCellPoint(pts[2]); + attrId = this->EdgeUseTable->InsertEdge(ptId,pts[2]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[4]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[5]]); + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(ptId); + edgeConn->InsertCellPoint(pts[3]); + attrId = this->EdgeUseTable->InsertEdge(ptId,pts[3]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[6]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[7]]); + } + + else if ( edgeCount == 3 ) + { + x[0] = origin[0] + i*spacing[0] + 0.5*spacing[0]; + x[1] = origin[1] + j*spacing[1] + 0.5*spacing[1]; + ptId = points->InsertNextPoint(x); + pointDescr->InsertValue(ptId, 0); //intersection points are fixed + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(ptId); + edgeConn->InsertCellPoint(pts[0]); + attrId = this->EdgeUseTable->InsertEdge(ptId, pts[0]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[0]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[1]]); + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(ptId); + edgeConn->InsertCellPoint(pts[1]); + attrId = this->EdgeUseTable->InsertEdge(ptId, pts[1]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[2]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[3]]); + + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(ptId); + edgeConn->InsertCellPoint(pts[2]); + attrId = this->EdgeUseTable->InsertEdge(ptId, pts[2]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[4]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[5]]); + } + + else if ( edgeCount == 2 ) + { + edgeConn->InsertNextCell(2); + edgeConn->InsertCellPoint(pts[0]); + edgeConn->InsertCellPoint(pts[1]); + attrId = this->EdgeUseTable->InsertEdge(pts[0],pts[1]); + this->EdgeUses->InsertValue(2*attrId, this->Visited[id[0]]); + this->EdgeUses->InsertValue(2*attrId+1, this->Visited[id[1]]); + } + + else if ( edgeCount == 1 ) + { + vtkErrorMacro(<<"Bad mojo"); + return 0; + } + } + } + + // Cleanup + this->EdgeUseTable->Delete(); + this->EdgeTable->Delete(); + + return 0; +} + +void vtkImageToPolyDataFilter::BuildPolygons(vtkUnsignedCharArray *vtkNotUsed(pointDescr), + vtkPolyData *edges, int numPolys, + vtkUnsignedCharArray *polyColors) +{ + vtkPoints *points = edges->GetPoints(); + vtkIdType numPts = points->GetNumberOfPoints(), ptId; + int i, j, k, *polyId, *polyId2, edgeId; + vtkIdType *cells, *pts, *cells2, npts, cellId; + int numPolyPts, p1, p2; + unsigned short ncells, ncells2; + unsigned char *polyVisited, *ptr; + vtkCellArray *newPolys; + + // Make sure we can topological info + edges->BuildLinks(); + + // Mark all polygons as unvisited + polyVisited = new unsigned char [numPolys]; + for (i=0; iAllocate(newPolys->EstimateSize(numPolys,25)); + + // Loop over all edge points tracking around each polygon + for (ptId=0; ptIdGetPointCells(ptId, ncells, cells); + if (ncells < 2) + { + vtkErrorMacro(<<"Bad mojo"); + return; + } + //for each edge, walk around polygon (if not visited before) + for (i=0; iEdgeUses->GetPointer(2*edgeId); + for (j=0; j<2; j++) + { + if ( polyId[j] != -1 && !polyVisited[polyId[j]] ) + {//build loop + polyVisited[polyId[j]] = 1; + numPolyPts = 1; + cellId = newPolys->InsertNextCell(0); //will update count later + newPolys->InsertCellPoint(ptId); + + // Update polygonal color + ptr = this->PolyColors->GetPointer(3*polyId[j]); + polyColors->SetValue(3*cellId, ptr[0]); //assign poly color + polyColors->SetValue(3*cellId+1, ptr[1]); + polyColors->SetValue(3*cellId+2, ptr[2]); + + p1 = ptId; p2 = -1; + while ( 1 ) + { + edges->GetCellPoints(edgeId, npts, pts); + p2 = (pts[0] != p1 ? pts[0] : pts[1]); + if (p2 == ptId) + { + break; + } + + newPolys->InsertCellPoint(p2); + numPolyPts++; + edges->GetPointCells(p2, ncells2, cells2); + if (ncells < 2) + { + vtkErrorMacro(<<"Bad mojo"); + return; + } + for (k=0; kEdgeUses->GetPointer(2*cells2[k]); + if ( cells2[k] != edgeId && + (polyId2[0] == polyId[j] || polyId2[1] == polyId[j]) ) + { + p1 = p2; + edgeId = cells2[k]; + break; + } + } + }//while not completed loop + newPolys->UpdateCellCount(numPolyPts); + + }//if polygon not yet visited + }//for each use of edge by polygon (at most 2 polygons) + }//for each edge connected to this point + }//for all points in edge list + + edges->SetPolys(newPolys); + newPolys->Delete(); + this->EdgeUses->Delete(); + delete [] polyVisited; +} + +void vtkImageToPolyDataFilter::SmoothEdges(vtkUnsignedCharArray *pointDescr, + vtkPolyData *edges) +{ + + vtkPoints *points=edges->GetPoints(); + vtkIdType numPts=points->GetNumberOfPoints(), ptId; + int i, iterNum; + int connId; + double x[3], xconn[3], xave[3], factor; + unsigned short int ncells; + vtkIdType *cells, *pts, npts; + + + // For each smoothing operation, loop over points. Points that can be + // smoothed are moved in the direction of the average of their neighbor + // points. + for ( iterNum=0; iterNumNumberOfSmoothingIterations; iterNum++ ) + { + if ( (iterNum % 2) ) //alternate smoothing direction + { + factor = -0.331; + } + else + { + factor = 0.330; + } + + for (ptId=0; ptIdGetValue(ptId) == 0 ) //can smooth + { + points->GetPoint(ptId, x); + edges->GetPointCells(ptId, ncells, cells); + xave[0] = xave[1] = xave[2] = 0.0; + for (i=0; iGetCellPoints(cells[i], npts, pts); + if (pts[0] != ptId) + { + connId = pts[0]; + } + else if (npts > 1) + { + connId = pts[1]; + } + else + { + vtkErrorMacro("Bad cell in smoothing operation"); + connId = pts[0]; + } + points->GetPoint(connId, xconn); + xave[0] += xconn[0]; xave[1] += xconn[1]; xave[2] += xconn[2]; + } + if ( ncells > 0 ) + { + xave[0] /= ncells; xave[1] /= ncells; xave[2] /= ncells; + x[0] = x[0] + factor * (xave[0] - x[0]); + x[1] = x[1] + factor * (xave[1] - x[1]); + x[2] = x[2] + factor * (xave[2] - x[2]); + points->SetPoint(ptId, x); + } + + }//if smoothable point + }//for all points + }//for all smoothing operations +} + + +// Remove points that are nearly co-linear to reduce the total point count +// +void vtkImageToPolyDataFilter::DecimateEdges(vtkPolyData *edges, + vtkUnsignedCharArray *pointDescr, + double tol2) +{ + vtkPoints *points=edges->GetPoints(); + vtkIdType numPts=points->GetNumberOfPoints(), ptId, prevId, nextId; + vtkIdType npts; + double x[3], xPrev[3], xNext[3]; + unsigned short int ncells; + vtkIdType *cells, *pts; + + // Loop over all points, finding those that are connected to just two + // edges. If the point is colinear to the previous and next edge point, + // then mark it as deleted. + for (ptId=0; ptIdGetValue(ptId) == 0 ) + { + points->GetPoint(ptId, x); + edges->GetPointCells(ptId, ncells, cells); + if ( ncells == 2 ) + { + edges->GetCellPoints(cells[0], npts, pts); + prevId = (pts[0] != ptId ? pts[0] : pts[1]); + points->GetPoint(prevId, xPrev); + + edges->GetCellPoints(cells[1], npts, pts); + nextId = (pts[0] != ptId ? pts[0] : pts[1]); + points->GetPoint(nextId, xNext); + + if ( vtkLine::DistanceToLine(x, xPrev, xNext) <= tol2 ) + { + pointDescr->SetValue(ptId, 2); //mark deleted + } + } + } //if manifold + } //for all points +} diff --git a/Hybrid/vtkImageToPolyDataFilter.h b/Hybrid/vtkImageToPolyDataFilter.h new file mode 100644 index 0000000..44c66c3 --- /dev/null +++ b/Hybrid/vtkImageToPolyDataFilter.h @@ -0,0 +1,232 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToPolyDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageToPolyDataFilter - generate linear primitives (vtkPolyData) from an image +// .SECTION Description +// vtkImageToPolyDataFilter converts raster data (i.e., an image) into +// polygonal data (i.e., quads or n-sided polygons), with each polygon +// assigned a constant color. This is useful for writers that generate vector +// formats (i.e., CGM or PostScript). To use this filter, you specify how to +// quantize the color (or whether to use an image with a lookup table), and +// what style the output should be. The output is always polygons, but the +// choice is n x m quads (where n and m define the input image dimensions) +// "Pixelize" option; arbitrary polygons "Polygonalize" option; or variable +// number of quads of constant color generated along scan lines "RunLength" +// option. +// +// The algorithm quantizes color in order to create coherent regions that the +// polygons can represent with good compression. By default, the input image +// is quantized to 256 colors using a 3-3-2 bits for red-green-blue. However, +// you can also supply a single component image and a lookup table, with the +// single component assumed to be an index into the table. (Note: a quantized +// image can be generated with the filter vtkImageQuantizeRGBToIndex.) The +// number of colors on output is equal to the number of colors in the input +// lookup table (or 256 if the built in linear ramp is used). +// +// The output of the filter is polygons with a single color per polygon cell. +// If the output style is set to "Polygonalize", the polygons may have an +// large number of points (bounded by something like 2*(n+m)); and the +// polygon may not be convex which may cause rendering problems on some +// systems (use vtkTriangleFilter). Otherwise, each polygon will have four +// vertices. The output also contains scalar data defining RGB color in +// unsigned char form. +// +// .SECTION Caveats +// The input linear lookup table must +// be of the form of 3-component unsigned char. +// +// This filter defines constant cell colors. If you have a plotting +// device that supports Gouraud shading (linear interpolation of color), then +// superior algorithms are available for generating polygons from images. +// +// Note that many plotting devices/formats support only a limited number of +// colors. +// +// .SECTION See Also +// vtkCGMWriter vtkImageQuantizeRGBToIndex vtkTriangleFilter + +#ifndef __vtkImageToPolyDataFilter_h +#define __vtkImageToPolyDataFilter_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_STYLE_PIXELIZE 0 +#define VTK_STYLE_POLYGONALIZE 1 +#define VTK_STYLE_RUN_LENGTH 2 + +#define VTK_COLOR_MODE_LUT 0 +#define VTK_COLOR_MODE_LINEAR_256 1 + +class vtkAppendPolyData; +class vtkDataArray; +class vtkEdgeTable; +class vtkIdTypeArray; +class vtkIntArray; +class vtkScalarsToColors; +class vtkStructuredPoints; +class vtkTimeStamp; +class vtkUnsignedCharArray; + +class VTK_HYBRID_EXPORT vtkImageToPolyDataFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImageToPolyDataFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with initial number of colors 256. + static vtkImageToPolyDataFilter* New(); + + // Description: + // Specify how to create the output. Pixelize means converting the image + // to quad polygons with a constant color per quad. Polygonalize means + // merging colors together into polygonal regions, and then smoothing + // the regions (if smoothing is turned on). RunLength means creating + // quad polygons that may encompass several pixels on a scan line. The + // default behavior is Polygonalize. + vtkSetClampMacro(OutputStyle,int,VTK_STYLE_PIXELIZE,VTK_STYLE_RUN_LENGTH); + vtkGetMacro(OutputStyle,int); + void SetOutputStyleToPixelize() + {this->SetOutputStyle(VTK_STYLE_PIXELIZE);}; + void SetOutputStyleToPolygonalize() + {this->SetOutputStyle(VTK_STYLE_POLYGONALIZE);}; + void SetOutputStyleToRunLength() + {this->SetOutputStyle(VTK_STYLE_RUN_LENGTH);}; + + // Description: + // Specify how to quantize color. + vtkSetClampMacro(ColorMode,int,VTK_COLOR_MODE_LUT,VTK_COLOR_MODE_LINEAR_256); + vtkGetMacro(ColorMode,int); + void SetColorModeToLUT() + {this->SetColorMode(VTK_COLOR_MODE_LUT);}; + void SetColorModeToLinear256() + {this->SetColorMode(VTK_COLOR_MODE_LINEAR_256);}; + + // Description: + // Set/Get the vtkLookupTable to use. The lookup table is used when the + // color mode is set to LUT and a single component scalar is input. + virtual void SetLookupTable(vtkScalarsToColors*); + vtkGetObjectMacro(LookupTable,vtkScalarsToColors); + + // Description: + // If the output style is set to polygonalize, then you can control + // whether to smooth boundaries. + vtkSetMacro(Smoothing, int); + vtkGetMacro(Smoothing, int); + vtkBooleanMacro(Smoothing, int); + + // Description: + // Specify the number of smoothing iterations to smooth polygons. (Only + // in effect if output style is Polygonalize and smoothing is on.) + vtkSetClampMacro(NumberOfSmoothingIterations,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfSmoothingIterations,int); + + // Description: + // Turn on/off whether the final polygons should be decimated. + // whether to smooth boundaries. + vtkSetMacro(Decimation, int); + vtkGetMacro(Decimation, int); + vtkBooleanMacro(Decimation, int); + + // Description: + // Specify the error to use for decimation (if decimation is on). + // The error is an absolute number--the image spacing and + // dimensions are used to create points so the error should be + // consistent with the image size. + vtkSetClampMacro(DecimationError,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(DecimationError,double); + + // Description: + // Specify the error value between two colors where the colors are + // considered the same. Only use this if the color mode uses the + // default 256 table. + vtkSetClampMacro(Error,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(Error,int); + + // Description: + // Specify the size (n by n pixels) of the largest region to + // polygonalize. When the OutputStyle is set to VTK_STYLE_POLYGONALIZE, + // large amounts of memory are used. In order to process large images, + // the image is broken into pieces that are at most Size pixels in + // width and height. + vtkSetClampMacro(SubImageSize,int,10,VTK_LARGE_INTEGER); + vtkGetMacro(SubImageSize,int); + +protected: + vtkImageToPolyDataFilter(); + ~vtkImageToPolyDataFilter(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + int OutputStyle; + int ColorMode; + int Smoothing; + int NumberOfSmoothingIterations; + int Decimation; + double DecimationError; + int Error; + int SubImageSize; + vtkScalarsToColors *LookupTable; + + virtual void PixelizeImage(vtkUnsignedCharArray *pixels, int dims[3], + double origin[3], double spacing[3], + vtkPolyData *output); + virtual void PolygonalizeImage(vtkUnsignedCharArray *pixels, int dims[3], + double origin[3], double spacing[3], + vtkPolyData *output); + virtual void RunLengthImage(vtkUnsignedCharArray *pixels, int dims[3], + double origin[3], double spacing[3], + vtkPolyData *output); +private: + vtkUnsignedCharArray *Table; // color table used to quantize points + vtkTimeStamp TableMTime; + int *Visited; // traverse & mark connected regions + vtkUnsignedCharArray *PolyColors; // the colors of each region -> polygon + vtkEdgeTable *EdgeTable; // keep track of intersection points + vtkEdgeTable *EdgeUseTable; // keep track of polygons use of edges + vtkIntArray *EdgeUses; //the two polygons that use an edge + //and point id associated with edge (if any) + + vtkAppendPolyData *Append; + + void BuildTable(unsigned char *inPixels); + vtkUnsignedCharArray *QuantizeImage(vtkDataArray *inScalars, int numComp, + int type, int dims[3], int ext[4]); + int ProcessImage(vtkUnsignedCharArray *pixels, int dims[2]); + int BuildEdges(vtkUnsignedCharArray *pixels, int dims[3], double origin[3], + double spacing[3], vtkUnsignedCharArray *pointDescr, + vtkPolyData *edges); + void BuildPolygons(vtkUnsignedCharArray *pointDescr, vtkPolyData *edges, + int numPolys, vtkUnsignedCharArray *polyColors); + void SmoothEdges(vtkUnsignedCharArray *pointDescr, vtkPolyData *edges); + void DecimateEdges(vtkPolyData *edges, vtkUnsignedCharArray *pointDescr, + double tol2); + void GeneratePolygons(vtkPolyData *edges, int numPolys, vtkPolyData *output, + vtkUnsignedCharArray *polyColors, + vtkUnsignedCharArray *pointDescr); + + int GetNeighbors(unsigned char *ptr, int &i, int &j, int dims[3], + unsigned char *neighbors[4], int mode); + + void GetIJ(int id, int &i, int &j, int dims[3]); + unsigned char *GetColor(unsigned char *rgb); + int IsSameColor(unsigned char *p1, unsigned char *p2); + +private: + vtkImageToPolyDataFilter(const vtkImageToPolyDataFilter&); // Not implemented. + void operator=(const vtkImageToPolyDataFilter&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkImplicitModeller.cxx b/Hybrid/vtkImplicitModeller.cxx new file mode 100644 index 0000000..78c4414 --- /dev/null +++ b/Hybrid/vtkImplicitModeller.cxx @@ -0,0 +1,1178 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitModeller.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitModeller.h" + +#include "vtkCell.h" +#include "vtkCellLocator.h" +#include "vtkClipPolyData.h" +#include "vtkCommand.h" +#include "vtkFloatArray.h" +#include "vtkGenericCell.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkMultiThreader.h" +#include "vtkMutexLock.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" +#include "vtkImageIterator.h" +#include "vtkImageProgressIterator.h" + +#include + +vtkCxxRevisionMacro(vtkImplicitModeller, "$Revision: 1.98 $"); +vtkStandardNewMacro(vtkImplicitModeller); + +struct vtkImplicitModellerAppendInfo +{ + vtkImplicitModeller *Modeller; + vtkDataSet **Input; + double MaximumDistance; +}; + +//---------------------------------------------------------------------------- +// Construct with sample dimensions=(50,50,50), and so that model bounds are +// automatically computed from the input. Capping is turned on with CapValue +// equal to a large positive number. +vtkImplicitModeller::vtkImplicitModeller() +{ + this->MaximumDistance = 0.1; + + this->ModelBounds[0] = 0.0; + this->ModelBounds[1] = 0.0; + this->ModelBounds[2] = 0.0; + this->ModelBounds[3] = 0.0; + this->ModelBounds[4] = 0.0; + this->ModelBounds[5] = 0.0; + this->BoundsComputed = 0; + + this->SampleDimensions[0] = 50; + this->SampleDimensions[1] = 50; + this->SampleDimensions[2] = 50; + + this->Capping = 1; + this->OutputScalarType = VTK_FLOAT; + this->CapValue = this->GetScalarTypeMax( this->OutputScalarType ); + this->ScaleToMaximumDistance = 0; // only used for non-float output type + + this->DataAppended = 0; + this->AdjustBounds = 1; + this->AdjustDistance = 0.0125; + + this->ProcessMode = VTK_CELL_MODE; + this->LocatorMaxLevel = 5; + + this->Threader = vtkMultiThreader::New(); + this->NumberOfThreads = this->Threader->GetNumberOfThreads(); + +} + +vtkImplicitModeller::~vtkImplicitModeller() +{ + if (this->Threader) + { + this->Threader->Delete(); + } +} + + +void vtkImplicitModeller::SetOutputScalarType(int type) +{ + double scalarMax; + + vtkDebugMacro(<< this->GetClassName() << " (" << this << + "): setting OutputScalarType to " << type); + + scalarMax = this->GetScalarTypeMax(type); + if (scalarMax) // legal type + { + int modified = 0; + if (this->CapValue != scalarMax) + { + this->CapValue = scalarMax; + modified = 1; + } + if (this->OutputScalarType != type) + { + this->OutputScalarType = type; + modified = 1; + } + if (modified) + { + this->Modified(); + } + } +} + +void vtkImplicitModeller::SetCapValue(double value) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this << + "): setting CapValue to " << value); + // clamp to between 0 and max for scalar type + double max = this->GetScalarTypeMax(this->OutputScalarType); + if (this->CapValue != (value < 0 ? 0 : (value > max ? max : value))) + { + this->CapValue = (value < 0 ? 0 : (value > max ? max : value)); + this->Modified(); + } +} + + +double vtkImplicitModeller::GetScalarTypeMax(int type) +{ + switch (type) + { + case VTK_UNSIGNED_CHAR: return (double)VTK_UNSIGNED_CHAR_MAX; + case VTK_CHAR: return (double)VTK_CHAR_MAX; + case VTK_UNSIGNED_SHORT: return (double)VTK_UNSIGNED_SHORT_MAX; + case VTK_SHORT: return (double)VTK_SHORT_MAX; + case VTK_UNSIGNED_INT: return (double)VTK_UNSIGNED_INT_MAX; + case VTK_INT: return (double)VTK_INT_MAX; + case VTK_UNSIGNED_LONG: return (double)VTK_UNSIGNED_LONG_MAX; + case VTK_LONG: return (double)VTK_LONG_MAX; + case VTK_FLOAT: return (double)VTK_FLOAT_MAX; + case VTK_DOUBLE: return (double)VTK_DOUBLE_MAX; + default: return 0; + } +} + + +//---------------------------------------------------------------------------- +// Initialize the filter for appending data. You must invoke the +// StartAppend() method before doing successive Appends(). It's also a +// good idea to manually specify the model bounds; otherwise the input +// bounds for the data will be used. +void vtkImplicitModeller::StartAppend() +{ + this->StartAppend(0); +} + +void vtkImplicitModeller::StartAppend(int internal) +{ + vtkIdType numPts; + vtkIdType i; + double maxDistance; + + if (!internal) + { + // we must call update information because we can't be sure that + // it has been called. + this->UpdateInformation(); + } + this->GetOutput()->SetUpdateExtent(this->GetOutput()->GetWholeExtent()); + + vtkDebugMacro(<< "Initializing data"); + this->AllocateOutputData(this->GetOutput()); + this->UpdateProgress(0.0); + this->DataAppended = 1; + + numPts = this->SampleDimensions[0] * this->SampleDimensions[1] + * this->SampleDimensions[2]; + + // initialize output to CapValue at each location + maxDistance = this->CapValue; + vtkDataArray *newScalars = this->GetOutput()->GetPointData()->GetScalars(); + for (i=0; iSetComponent(i, 0, maxDistance); + } +} + + +template +void SetOutputDistance(double distance, OT *outputValue, double capValue, double scaleFactor) +{ + // for now, just doing "normal" cast... could consider doing round? + if (scaleFactor) // need to scale the distance + { + *outputValue = static_cast(distance * scaleFactor); + } + else + { + if (capValue && distance > capValue) // clamping iff non-float type + { + distance = capValue; + } + *outputValue = static_cast(distance); + } +} + + +// Convert distance as stored in output (could be scaled and/or non-double +// type) to double distance with correct scaling +void ConvertToDoubleDistance(double inDistance, double &distance, + double &distance2, double scaleFactor) +{ + if (scaleFactor) + { + distance = inDistance * scaleFactor; + } + else + { + distance = inDistance; + } + distance2 = distance * distance; +} + +//---------------------------------------------------------------------------- +// Templated append for VTK_VOXEL_MODE process mode and any type of output data +template +void vtkImplicitModellerAppendExecute(vtkImplicitModeller *self, + vtkDataSet *input, vtkImageData *outData, + int outExt[6], double maxDistance, + vtkCellLocator *locator, int id, OT *) +{ + int i, j, k; + int subId; + vtkIdType cellId; + double pcoords[3]; + double *spacing, *origin; + double maxDistance2 = maxDistance * maxDistance; + double x[3], prevDistance, prevDistance2, distance2, betterDistance; + double closestPoint[3], mDist; + + // allocate weights for the EvaluatePosition + double *weights = new double[input->GetMaxCellSize()]; + + // Traverse each voxel; using CellLocator to find the closest point + vtkGenericCell *cell = vtkGenericCell::New(); + + spacing = outData->GetSpacing(); + origin = outData->GetOrigin(); + + vtkImageProgressIterator outIt(outData, outExt, self, id); + + // so we know how to scale if desired + double scaleFactor = 0; // 0 used to indicate not scaling + double toDoubleScaleFactor = 0; // 0 used to indicate not scaling + double capValue = 0; // 0 used to indicate not clamping (float or double) + if (self->GetOutputScalarType() != VTK_FLOAT && + self->GetOutputScalarType() != VTK_DOUBLE) + { + capValue = self->GetCapValue(); + if (self->GetScaleToMaximumDistance()) + { + scaleFactor = capValue / maxDistance; + toDoubleScaleFactor = maxDistance / capValue; + } + } + + int testIndex = 0; + for (k = outExt[4]; k <= outExt[5]; k++) + { + x[2] = spacing[2] * k + origin[2]; + for (j = outExt[2]; j <= outExt[3]; j++) + { + cellId = -1; + x[1] = spacing[1] * j + origin[1]; + OT* outSI = outIt.BeginSpan(); + for (i = outExt[0]; i <= outExt[1]; i++, testIndex++) + { + x[0] = spacing[0] * i + origin[0]; + ConvertToDoubleDistance(*outSI, prevDistance, prevDistance2, + toDoubleScaleFactor); + betterDistance = -1; + + if (cellId != -1) + { + cell->EvaluatePosition(x, closestPoint, subId, pcoords, + distance2, weights); + if (distance2 <= maxDistance2 && distance2 < prevDistance2) + { + mDist = sqrt(distance2); + betterDistance = mDist; + } + else if (prevDistance2 < maxDistance2) + { + mDist = prevDistance; + } + else + { + mDist = maxDistance; + } + } + else if (prevDistance2 < maxDistance2) + { + mDist = prevDistance; + } + else + { + mDist = maxDistance; + } + + if (locator->FindClosestPointWithinRadius(x, mDist, + closestPoint, cell, cellId, subId, distance2) ) + { + if(distance2 <= prevDistance2) + { + betterDistance = sqrt(distance2); + } + } + else + { + cellId = -1; + } + + if (betterDistance != -1) + { + SetOutputDistance(betterDistance, outSI, capValue, scaleFactor); + } + + outSI++; + } + outIt.NextSpan(); + } + } + cell->Delete(); + delete [] weights; +} + + + + +//---------------------------------------------------------------------------- +// This is the multithreaded piece of the append when doing per voxel +// processing - it is called once for each thread, with each thread +// taking a different slab of the output to work on. The acutal work is done +// in vtkImplicitModellerAppendExecute; here we just setup for the per voxel +// processing. +static VTK_THREAD_RETURN_TYPE vtkImplicitModeller_ThreadedAppend( void *arg ) +{ + int threadCount; + int threadId; + vtkImplicitModellerAppendInfo *userData; + vtkImageData *output; + double maxDistance; + int i; + double *bounds, adjBounds[6]; + double *spacing; + double *origin; + int slabSize, slabMin, slabMax; + int outExt[6]; + + threadId = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + userData = (vtkImplicitModellerAppendInfo *) + (((vtkMultiThreader::ThreadInfo *)(arg))->UserData); + + if (userData->Input[threadId] == NULL) + { + return VTK_THREAD_RETURN_VALUE; + } + + maxDistance = userData->MaximumDistance; + + output = userData->Modeller->GetOutput(); + spacing = output->GetSpacing(); + origin = output->GetOrigin(); + + int *sampleDimensions = userData->Modeller->GetSampleDimensions(); + if (!output->GetPointData()->GetScalars()) + { + vtkGenericWarningMacro("Sanity check failed."); + return VTK_THREAD_RETURN_VALUE; + } + + // break up into slabs based on threadId and threadCount + slabSize = sampleDimensions[2] / threadCount; + if (slabSize == 0) // in case threadCount > sampleDimensions[2] + { + slabSize = 1; + } + slabMin = threadId * slabSize; + if (slabMin >= sampleDimensions[2]) + { + return VTK_THREAD_RETURN_VALUE; + } + slabMax = slabMin + slabSize - 1; + if (threadId == threadCount - 1) + { + slabMax = sampleDimensions[2] - 1; + } + + + bounds = userData->Input[threadId]->GetBounds(); + for (i=0; i<3; i++) + { + adjBounds[2*i] = bounds[2*i] - maxDistance; + adjBounds[2*i+1] = bounds[2*i+1] + maxDistance; + } + + // compute dimensional bounds in data set + for (i = 0; i < 3; i++) + { + outExt[i*2] = (int) ((double)(adjBounds[2*i] - origin[i]) / + spacing[i]); + outExt[i*2+1] = (int) ((double)(adjBounds[2*i+1] - origin[i]) / + spacing[i]); + if (outExt[i*2] < 0) + { + outExt[i*2] = 0; + } + if (outExt[i*2+1] >= sampleDimensions[i]) + { + outExt[i*2+1] = sampleDimensions[i] - 1; + } + } + + // input not close enough to effect this slab + if (outExt[4] > slabMax || outExt[5] < slabMin) + { + return VTK_THREAD_RETURN_VALUE; + } + + // adjust min/max to match slab + if (outExt[4] < slabMin) + { + outExt[4] = slabMin; + } + if (outExt[5] > slabMax) + { + outExt[5] = slabMax; + } + + vtkCellLocator *locator = vtkCellLocator::New(); + + // Set up the cell locator. + // If AutomaticOff, then NumberOfCellsPerBucket only used for allocating + // memory. If AutomaticOn, then NumberOfCellsPerBucket is used to guess + // the depth for the uniform octree required to support + // NumberOfCellsPerBucket (assuming uniform distribution of cells). + locator->SetDataSet( userData->Input[threadId] ); + locator->AutomaticOff(); + locator->SetMaxLevel( userData->Modeller->GetLocatorMaxLevel() ); + locator->SetNumberOfCellsPerBucket( 1 ); + locator->CacheCellBoundsOn(); + locator->BuildLocator(); + + switch (userData->Modeller->GetOutputScalarType()) + { + vtkTemplateMacro( + vtkImplicitModellerAppendExecute( + userData->Modeller, + userData->Input[threadId], output, outExt, + userData->MaximumDistance, locator, threadId, + static_cast(0))); + default: + vtkGenericWarningMacro("Execute: Unknown output ScalarType"); + return VTK_THREAD_RETURN_VALUE; + } + + locator->Delete(); + return VTK_THREAD_RETURN_VALUE; +} + + +//---------------------------------------------------------------------------- +// Templated append for VTK_CELL_MODE process mode and any type of output data +template +void vtkImplicitModellerAppendExecute(vtkImplicitModeller *self, + vtkDataSet *input, vtkImageData *outData, + double maxDistance, OT *) +{ + int i, j, k, updateTime; + vtkIdType cellNum; + double *bounds, adjBounds[6]; + double pcoords[3]; + int outExt[6]; + double x[3], prevDistance2, distance, distance2; + int subId; + double closestPoint[3]; + double *weights=new double[input->GetMaxCellSize()]; + double maxDistance2; + double *spacing, *origin; + + spacing = outData->GetSpacing(); + origin = outData->GetOrigin(); + + maxDistance2 = maxDistance * maxDistance; + int *sampleDimensions = self->GetSampleDimensions(); + + // so we know how to scale if desired + double scaleFactor = 0; // 0 used to indicate not scaling + double toDoubleScaleFactor = 0; // 0 used to indicate not scaling + double capValue = 0; // 0 used to indicate not clamping (float or double) + if (self->GetOutputScalarType() != VTK_FLOAT && + self->GetOutputScalarType() != VTK_DOUBLE) + { + capValue = self->GetCapValue(); + if (self->GetScaleToMaximumDistance()) + { + scaleFactor = capValue / maxDistance; + toDoubleScaleFactor = maxDistance / capValue; + } + } + + // + // Traverse all cells; computing distance function on volume points. + // + vtkCell *cell; + updateTime = input->GetNumberOfCells() / 50; // update every 2% + if (updateTime < 1) + { + updateTime = 1; + } + + for (cellNum=0; cellNum < input->GetNumberOfCells(); cellNum++) + { + cell = input->GetCell(cellNum); + bounds = cell->GetBounds(); + for (i=0; i<3; i++) + { + adjBounds[2*i] = bounds[2*i] - maxDistance; + adjBounds[2*i+1] = bounds[2*i+1] + maxDistance; + } + + // compute dimensional bounds in data set + for (i = 0; i < 3; i++) + { + outExt[i*2] = (int) ((double)(adjBounds[2*i] - origin[i]) / + spacing[i]); + outExt[i*2 + 1] = (int) ((double)(adjBounds[2*i+1] - origin[i]) / + spacing[i]); + if (outExt[i*2] < 0) + { + outExt[i*2] = 0; + } + if (outExt[i*2 + 1] >= sampleDimensions[i]) + { + outExt[i*2 + 1] = sampleDimensions[i] - 1; + } + } + + vtkImageIterator outIt(outData, outExt); + + for (k = outExt[4]; k <= outExt[5]; k++) + { + x[2] = spacing[2] * k + origin[2]; + for (j = outExt[2]; j <= outExt[3]; j++) + { + x[1] = spacing[1] * j + origin[1]; + OT* outSI = outIt.BeginSpan(); + for (i = outExt[0]; i <= outExt[1]; i++) + { + x[0] = spacing[0] * i + origin[0]; + + ConvertToDoubleDistance(*outSI, distance, prevDistance2, + toDoubleScaleFactor); + + // union combination of distances + if ( cell->EvaluatePosition(x, closestPoint, subId, pcoords, + distance2, weights) != -1 && distance2 < prevDistance2 && + distance2 <= maxDistance2 ) + { + distance = sqrt(distance2); + SetOutputDistance(distance, outSI, capValue, scaleFactor); + } + outSI++; + } + outIt.NextSpan(); + } + } + + if (cellNum % updateTime == 0) + { + self->UpdateProgress(double(cellNum + 1) / input->GetNumberOfCells()); + } + } + delete [] weights; +} + + + +// Append a data set to the existing output. To use this function, +// you'll have to invoke the StartAppend() method before doing +// successive appends. It's also a good idea to specify the model +// bounds; otherwise the input model bounds is used. When you've +// finished appending, use the EndAppend() method. +void vtkImplicitModeller::Append(vtkDataSet *input) +{ + vtkDebugMacro(<< "Appending data"); + + vtkImageData *output = this->GetOutput(); + + if ( !this->BoundsComputed ) + { + this->ComputeModelBounds(input); + } + + if (this->ProcessMode == VTK_CELL_MODE) + { + if (!output->GetPointData()->GetScalars()) + { + vtkErrorMacro("Sanity check failed."); + return; + } + + switch (this->OutputScalarType) + { + vtkTemplateMacro( + vtkImplicitModellerAppendExecute( this, + input, + output, + this->InternalMaxDistance, + static_cast(0))); + } + } + else + { + vtkImplicitModellerAppendInfo info; + double minZ, maxZ; + int slabMin, slabMax, slabSize, i; + vtkClipPolyData **minClipper = NULL, **maxClipper = NULL; + vtkPlane ** minPlane = NULL, **maxPlane = NULL; + double *spacing, *origin; + + spacing = output->GetSpacing(); + origin = output->GetOrigin(); + + // Use a MultiThreader here, splitting the volume into slabs to be processed + // by the separate threads + + // Set the number of threads to use, + // then set the execution method and do it. + this->Threader->SetNumberOfThreads( this->NumberOfThreads ); + + // set up the info object for the thread + info.Modeller = this; + info.MaximumDistance = this->InternalMaxDistance; + + info.Input = new vtkDataSet* [this->NumberOfThreads]; + if (this->NumberOfThreads == 1) + { + info.Input[0] = input; + } + else + { + // if not PolyData, then copy the input for each thread + if ( input->GetDataObjectType() != VTK_POLY_DATA ) + { + for (i = 0; i < this->NumberOfThreads; i++) + { + switch( input->GetDataObjectType() ) + { + case VTK_STRUCTURED_GRID: + info.Input[i] = vtkStructuredGrid::New(); + break; + case VTK_IMAGE_DATA: + info.Input[i] = vtkImageData::New(); + break; + case VTK_UNSTRUCTURED_GRID: + info.Input[i] = vtkUnstructuredGrid::New(); + break; + case VTK_RECTILINEAR_GRID: + info.Input[i] = vtkRectilinearGrid::New(); + break; + default: + vtkErrorMacro(<<"Unexpected DataSet type!"); + return; + } + info.Input[i]->CopyStructure(input); + } + } + else // break up the input data into slabs to help ensure thread safety + + { + minClipper = new vtkClipPolyData* [this->NumberOfThreads]; + maxClipper = new vtkClipPolyData* [this->NumberOfThreads]; + minPlane = new vtkPlane* [this->NumberOfThreads]; + maxPlane = new vtkPlane* [this->NumberOfThreads]; + + slabSize = this->SampleDimensions[2] / this->NumberOfThreads; + if (slabSize == 0) // in case threadCount > SampleDimensions[2] + { + slabSize = 1; + } + + for (i = 0; i < this->NumberOfThreads; i++) + { + ////////////////////////////////////////////////// + // do the 1st clip + slabMin = i * slabSize; + if (slabMin >= this->SampleDimensions[2]) + { + break; + } + + // get/clip input cells in this slab + maxDistance+ + minZ = spacing[2] * slabMin + origin[2] - this->InternalMaxDistance*1.00001; + if (minZ < this->ModelBounds[4]) + { + minZ = this->ModelBounds[4]; + } + + minPlane[i] = vtkPlane::New(); + minPlane[i]->SetNormal(0.0, 0.0, -1.0); + minPlane[i]->SetOrigin(0.0, 0.0, minZ); + + minClipper[i] = vtkClipPolyData::New(); + minClipper[i]->SetInput((vtkPolyData *)input); + minClipper[i]->SetClipFunction(minPlane[i]); + minClipper[i]->SetValue( 0.0 ); + minClipper[i]->InsideOutOn(); + minClipper[i]->Update(); + + if ( minClipper[i]->GetOutput()->GetNumberOfCells() == 0 ) + { + info.Input[i] = NULL; + maxPlane[i] = NULL; + continue; + } + minClipper[i]->ReleaseDataFlagOn(); + + ////////////////////////////////////////////////// + // do the 2nd clip + slabMax = slabMin + slabSize - 1; + if (i == this->NumberOfThreads - 1) + { + slabMax = this->SampleDimensions[2] - 1; + } + + maxZ = spacing[2] * slabMax + origin[2] + this->InternalMaxDistance*1.00001; + if (maxZ > this->ModelBounds[5]) + { + maxZ = this->ModelBounds[5]; + } + maxPlane[i] = vtkPlane::New(); + maxPlane[i]->SetNormal(0.0, 0.0, 1.0); + maxPlane[i]->SetOrigin(0.0, 0.0, maxZ); + + maxClipper[i] = vtkClipPolyData::New(); + maxClipper[i]->SetInput(minClipper[i]->GetOutput()); + maxClipper[i]->SetClipFunction(maxPlane[i]); + maxClipper[i]->SetValue( 0.0 ); + maxClipper[i]->InsideOutOn(); + maxClipper[i]->Update(); + + if ( maxClipper[i]->GetOutput()->GetNumberOfCells() == 0 ) + { + info.Input[i] = NULL; + } + else + { + info.Input[i] = maxClipper[i]->GetOutput(); + } + } + } + } + + this->Threader->SetSingleMethod( vtkImplicitModeller_ThreadedAppend, + (void *)&info); + this->Threader->SingleMethodExecute(); + + // cleanup + if (this->NumberOfThreads > 1) + { + if ( input->GetDataObjectType() != VTK_POLY_DATA ) + { + for (i = 0; i < this->NumberOfThreads; i++) + { + info.Input[i]->Delete(); + } + } + else + { + for (i = 0; i < this->NumberOfThreads; i++) + { + minPlane[i]->Delete(); + minClipper[i]->Delete(); + if (maxPlane[i]) + { + maxPlane[i]->Delete(); + maxClipper[i]->Delete(); + } + } + delete [] minPlane; + delete [] maxPlane; + delete [] minClipper; + delete [] maxClipper; + } + } + delete [] info.Input; + } +} + +//---------------------------------------------------------------------------- +// Method completes the append process (does the capping if requested). +void vtkImplicitModeller::EndAppend() +{ + vtkDataArray *newScalars; + vtkDebugMacro(<< "End append"); + + if (!(newScalars =this->GetOutput()->GetPointData()->GetScalars())) + { + vtkErrorMacro("Sanity check failed."); + return; + } + + if ( this->Capping ) + { + this->Cap(newScalars); + } + this->UpdateProgress(1.0); +} + +//---------------------------------------------------------------------------- +int vtkImplicitModeller::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int i; + double ar[3], origin[3]; + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->OutputScalarType, 1); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, this->SampleDimensions[0]-1, + 0, this->SampleDimensions[1]-1, + 0, this->SampleDimensions[2]-1); + + for (i=0; i < 3; i++) + { + origin[i] = this->ModelBounds[2*i]; + if ( this->SampleDimensions[i] <= 1 ) + { + ar[i] = 1; + } + else + { + ar[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + } + } + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + outInfo->Set(vtkDataObject::SPACING(),ar,3); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImplicitModeller::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed( outputVector )) +{ + // get the input + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<< "Executing implicit model"); + + if (input == NULL) + { + // we do not want to release the data because user might + // have called Append ... + return 0; + } + + this->StartAppend(1); + this->Append(input); + this->EndAppend(); + + return 1; +} + +// Compute ModelBounds from input geometry. +double vtkImplicitModeller::ComputeModelBounds(vtkDataSet *input) +{ + double *bounds, maxDist; + int i; + vtkImageData *output=this->GetOutput(); + double tempd[3]; + + // compute model bounds if not set previously + if ( this->ModelBounds[0] >= this->ModelBounds[1] || + this->ModelBounds[2] >= this->ModelBounds[3] || + this->ModelBounds[4] >= this->ModelBounds[5] ) + { + if (input != NULL) + { + bounds = input->GetBounds(); + } + else + { + vtkDataSet *dsInput = vtkDataSet::SafeDownCast(this->GetInput()); + if (dsInput != NULL) + { + bounds = dsInput->GetBounds(); + } + else + { + vtkErrorMacro( + << "An input must be specified to Compute the model bounds."); + return VTK_FLOAT_MAX; + } + } + } + else + { + bounds = this->ModelBounds; + } + + for (maxDist=0.0, i=0; i<3; i++) + { + if ( (bounds[2*i+1] - bounds[2*i]) > maxDist ) + { + maxDist = bounds[2*i+1] - bounds[2*i]; + } + } + + // adjust bounds so model fits strictly inside (only if not set previously) + if ( this->AdjustBounds ) + { + for (i=0; i<3; i++) + { + this->ModelBounds[2*i] = bounds[2*i] - maxDist*this->AdjustDistance; + this->ModelBounds[2*i+1] = bounds[2*i+1] + maxDist*this->AdjustDistance; + } + } + else // to handle problem case where bounds not specified and AdjustBounds + // not on; will be setting ModelBounds to self if previosusly set + { + for (i=0; i<3; i++) + { + this->ModelBounds[2*i] = bounds[2*i]; + this->ModelBounds[2*i+1] = bounds[2*i+1]; + } + } + + maxDist *= this->MaximumDistance; + + // Set volume origin and data spacing + output->SetOrigin(this->ModelBounds[0], + this->ModelBounds[2], + this->ModelBounds[4]); + + for (i=0; i<3; i++) + { + tempd[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + } + output->SetSpacing(tempd); + + vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0); + outInfo->Set(vtkDataObject::ORIGIN(),this->ModelBounds[0], + this->ModelBounds[2], this->ModelBounds[4]); + outInfo->Set(vtkDataObject::SPACING(),tempd,3); + + this->BoundsComputed = 1; + this->InternalMaxDistance = maxDist; + + return maxDist; +} + +//---------------------------------------------------------------------------- +// Set the i-j-k dimensions on which to sample the distance function. +void vtkImplicitModeller::SetSampleDimensions(int i, int j, int k) +{ + int dim[3]; + + dim[0] = i; + dim[1] = j; + dim[2] = k; + + this->SetSampleDimensions(dim); +} + +//---------------------------------------------------------------------------- +void vtkImplicitModeller::SetSampleDimensions(int dim[3]) +{ + int dataDim, i; + + vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")"); + + if ( dim[0] != this->SampleDimensions[0] || + dim[1] != this->SampleDimensions[1] || + dim[2] != this->SampleDimensions[2] ) + { + if ( dim[0]<1 || dim[1]<1 || dim[2]<1 ) + { + vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values"); + return; + } + + for (dataDim=0, i=0; i<3 ; i++) + { + if (dim[i] > 1) + { + dataDim++; + } + } + + if ( dataDim < 3 ) + { + vtkErrorMacro(<<"Sample dimensions must define a volume!"); + return; + } + + for ( i=0; i<3; i++) + { + this->SampleDimensions[i] = dim[i]; + } + + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkImplicitModeller::Cap(vtkDataArray *s) +{ + int i,j,k; + int idx; + int d01=this->SampleDimensions[0]*this->SampleDimensions[1]; + +// i-j planes + k = 0; + for (j=0; jSampleDimensions[1]; j++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetComponent(i+j*this->SampleDimensions[0],0, this->CapValue); + } + } + k = this->SampleDimensions[2] - 1; + idx = k*d01; + for (j=0; jSampleDimensions[1]; j++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetComponent(idx+i+j*this->SampleDimensions[0], 0, this->CapValue); + } + } + // j-k planes + i = 0; + for (k=0; kSampleDimensions[2]; k++) + { + for (j=0; jSampleDimensions[1]; j++) + { + s->SetComponent(j*this->SampleDimensions[0]+k*d01,0,this->CapValue); + } + } + i = this->SampleDimensions[0] - 1; + for (k=0; kSampleDimensions[2]; k++) + { + for (j=0; jSampleDimensions[1]; j++) + { + s->SetComponent(i+j*this->SampleDimensions[0]+k*d01,0, this->CapValue); + } + } + // i-k planes + j = 0; + for (k=0; kSampleDimensions[2]; k++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetComponent(i+k*d01,0, this->CapValue); + } + } + j = this->SampleDimensions[1] - 1; + idx = j*this->SampleDimensions[0]; + for (k=0; kSampleDimensions[2]; k++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetComponent(idx+i+k*d01,0, this->CapValue); + } + } +} + +//---------------------------------------------------------------------------- +const char *vtkImplicitModeller::GetProcessModeAsString() +{ + if (this->ProcessMode == VTK_CELL_MODE) + { + return "PerCell"; + } + else + { + return "PerVoxel"; + } +} + +//---------------------------------------------------------------------------- +int vtkImplicitModeller::FillInputPortInformation( + int vtkNotUsed( port ), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImplicitModeller::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // If we have no input then we will not generate the output because + // the user already called StartAppend/Append/EndAppend. + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_NOT_GENERATED())) + { + if(inputVector[0]->GetNumberOfInformationObjects() == 0) + { + vtkInformation* outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkDemandDrivenPipeline::DATA_NOT_GENERATED(), 1); + } + return 1; + } + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + if(inputVector[0]->GetNumberOfInformationObjects() == 0) + { + return 1; + } + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +void vtkImplicitModeller::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum Distance: " << this->MaximumDistance << "\n"; + os << indent << "OutputScalarType: " << this->OutputScalarType << "\n"; + os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", " + << this->SampleDimensions[1] << ", " + << this->SampleDimensions[2] << ")\n"; + os << indent << "ModelBounds: \n"; + os << indent << " Xmin,Xmax: (" << this->ModelBounds[0] << ", " + << this->ModelBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->ModelBounds[2] << ", " + << this->ModelBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->ModelBounds[4] << ", " + << this->ModelBounds[5] << ")\n"; + + os << indent << "ScaleToMaximumDistance: " << (this->ScaleToMaximumDistance ? "On\n" : "Off\n"); + os << indent << "AdjustBounds: " << (this->AdjustBounds ? "On\n" : "Off\n"); + os << indent << "Adjust Distance: " << this->AdjustDistance << "\n"; + os << indent << "Process Mode: " << this->ProcessMode << "\n"; + os << indent << "Locator Max Level: " << this->LocatorMaxLevel << "\n"; + + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); + os << indent << "Cap Value: " << this->CapValue << "\n"; + os << indent << "Process Mode: " << this->GetProcessModeAsString() << endl; + os << indent << "Number Of Threads (for PerVoxel mode): " << this->NumberOfThreads << endl; +} diff --git a/Hybrid/vtkImplicitModeller.h b/Hybrid/vtkImplicitModeller.h new file mode 100644 index 0000000..bf8ead2 --- /dev/null +++ b/Hybrid/vtkImplicitModeller.h @@ -0,0 +1,286 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitModeller.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitModeller - compute distance from input geometry on structured point dataset +// .SECTION Description +// vtkImplicitModeller is a filter that computes the distance from the input +// geometry to the points of an output structured point set. This distance +// function can then be "contoured" to generate new, offset surfaces from +// the original geometry. An important feature of this object is +// "capping". If capping is turned on, after the implicit model is created, +// the values on the boundary of the structured points dataset are set to +// the cap value. This is used to force closure of the resulting contoured +// surface. Note, however, that large cap values can generate weird surface +// normals in those cells adjacent to the boundary of the dataset. Using +// smaller cap value will reduce this effect. +//

+// Another important ivar is MaximumDistance. This controls how far into the +// volume the distance function is computed from the input geometry. Small +// values give significant increases in performance. However, there can +// strange sampling effects at the extreme range of the MaximumDistance. +//

+// In order to properly execute and sample the input data, a rectangular +// region in space must be defined (this is the ivar ModelBounds). If not +// explicitly defined, the model bounds will be computed. Note that to avoid +// boundary effects, it is possible to adjust the model bounds (i.e., using +// the AdjustBounds and AdjustDistance ivars) to strictly contain the +// sampled data. +//

+// This filter has one other unusual capability: it is possible to append +// data in a sequence of operations to generate a single output. This is +// useful when you have multiple datasets and want to create a +// conglomeration of all the data. However, the user must be careful to +// either specify the ModelBounds or specify the first item such that its +// bounds completely contain all other items. This is because the +// rectangular region of the output can not be changed after the 1st Append. +//

+// The ProcessMode ivar controls the method used within the Append function +// (where the actual work is done regardless if the Append function is +// explicitly called) to compute the implicit model. If set to work in voxel +// mode, each voxel is visited once. If set to cell mode, each cell is visited +// once. Tests have shown once per voxel to be faster when there are a +// lot of cells (at least a thousand?); relative performance improvement +// increases with addition cells. Primitives should not be stripped for best +// performance of the voxel mode. Also, if explicitly using the Append feature +// many times, the cell mode will probably be better because each voxel will be +// visited each Append. Append the data before input if possible when using +// the voxel mode. Do not switch between voxel and cell mode between execution +// of StartAppend and EndAppend. +//

+// Further performance improvement is now possible using the PerVoxel process +// mode on multi-processor machines (the mode is now multithreaded). Each +// thread processes a different "slab" of the output. Also, if the input is +// vtkPolyData, it is appropriately clipped for each thread; that is, each +// thread only considers the input which could affect its slab of the output. +//

+// This filter can now produce output of any type supported by vtkImageData. +// However to support this change, additional sqrts must be executed during the +// Append step. Previously, the output was initialized to the squared CapValue +// in StartAppend, the output was updated with squared distance values during +// the Append, and then the sqrt of the distances was computed in EndAppend. +// To support different scalar types in the output (largely to reduce memory +// requirements as an vtkImageShiftScale and/or vtkImageCast could have +// achieved the same result), we can't "afford" to save squared value in the +// output, because then we could only represent up to the sqrt of the scalar +// max for an integer type in the output; 1 (instead of 255) for an unsigned +// char; 11 for a char (instead of 127). Thus this change may result in a +// minor performance degradation. Non-float output types can be scaled to the +// CapValue by turning ScaleToMaximumDistance On. +// +// .SECTION See Also +// vtkSampleFunction vtkContourFilter + +#ifndef __vtkImplicitModeller_h +#define __vtkImplicitModeller_h + +#include "vtkImageAlgorithm.h" + +#define VTK_VOXEL_MODE 0 +#define VTK_CELL_MODE 1 + +class vtkDataArray; +class vtkExtractGeometry; +class vtkMultiThreader; + +class VTK_HYBRID_EXPORT vtkImplicitModeller : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImplicitModeller,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with sample dimensions=(50,50,50), and so that model bounds are + // automatically computed from the input. Capping is turned on with CapValue + // equal to a large positive number. + static vtkImplicitModeller *New(); + + // Description: + // Compute ModelBounds from input geometry. If input is not specified, the + // input of the filter will be used. + double ComputeModelBounds(vtkDataSet *input = NULL); + + // Description: + // Set/Get the i-j-k dimensions on which to sample distance function. + vtkGetVectorMacro(SampleDimensions,int,3); + void SetSampleDimensions(int i, int j, int k); + void SetSampleDimensions(int dim[3]); + + // Description: + // Set / get the distance away from surface of input geometry to + // sample. Smaller values make large increases in performance. + vtkSetClampMacro(MaximumDistance,double,0.0,1.0); + vtkGetMacro(MaximumDistance,double); + + // Description: + // Set / get the region in space in which to perform the sampling. If + // not specified, it will be computed automatically. + vtkSetVector6Macro(ModelBounds,double); + vtkGetVectorMacro(ModelBounds,double,6); + + // Description: + // Control how the model bounds are computed. If the ivar AdjustBounds + // is set, then the bounds specified (or computed automatically) is modified + // by the fraction given by AdjustDistance. This means that the model + // bounds is expanded in each of the x-y-z directions. + vtkSetMacro(AdjustBounds,int); + vtkGetMacro(AdjustBounds,int); + vtkBooleanMacro(AdjustBounds,int); + + // Description: + // Specify the amount to grow the model bounds (if the ivar AdjustBounds + // is set). The value is a fraction of the maximum length of the sides + // of the box specified by the model bounds. + vtkSetClampMacro(AdjustDistance,double,-1.0,1.0); + vtkGetMacro(AdjustDistance,double); + + // Description: + // The outer boundary of the structured point set can be assigned a + // particular value. This can be used to close or "cap" all surfaces. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + + // Description: + // Specify the capping value to use. The CapValue is also used as an + // initial distance value at each point in the dataset. + void SetCapValue(double value); + vtkGetMacro(CapValue,double); + + // Description: + // If a non-floating output type is specified, the output distances can be + // scaled to use the entire positive scalar range of the output type + // specified (up to the CapValue which is equal to the max for the type + // unless modified by the user). For example, if ScaleToMaximumDistance + // is On and the OutputScalarType is UnsignedChar the distances saved in the + // output would be linearly scaled between 0 (for distances "very close" to + // the surface) and 255 (at the specifed maximum distance)... assuming the + // CapValue is not changed from 255. + vtkSetMacro(ScaleToMaximumDistance, int); + vtkGetMacro(ScaleToMaximumDistance, int); + vtkBooleanMacro(ScaleToMaximumDistance,int); + + // Description: + // Specify whether to visit each cell once per append or each voxel once + // per append. Some tests have shown once per voxel to be faster + // when there are a lot of cells (at least a thousand?); relative + // performance improvement increases with addition cells. Primitives + // should not be stripped for best performance of the voxel mode. + vtkSetClampMacro(ProcessMode, int, 0, 1); + vtkGetMacro(ProcessMode, int); + void SetProcessModeToPerVoxel() {this->SetProcessMode(VTK_VOXEL_MODE);} + void SetProcessModeToPerCell() {this->SetProcessMode(VTK_CELL_MODE);} + const char *GetProcessModeAsString(void); + + // Description: + // Specify the level of the locator to use when using the per voxel + // process mode. + vtkSetMacro(LocatorMaxLevel,int); + vtkGetMacro(LocatorMaxLevel,int); + + // Description: + // Set / Get the number of threads used during Per-Voxel processing mode + vtkSetClampMacro( NumberOfThreads, int, 1, VTK_MAX_THREADS ); + vtkGetMacro( NumberOfThreads, int ); + + // Description: + // Set the desired output scalar type. + void SetOutputScalarType(int type); + vtkGetMacro(OutputScalarType,int); + void SetOutputScalarTypeToFloat(){this->SetOutputScalarType(VTK_FLOAT);}; + void SetOutputScalarTypeToDouble(){this->SetOutputScalarType(VTK_DOUBLE);}; + void SetOutputScalarTypeToInt(){this->SetOutputScalarType(VTK_INT);}; + void SetOutputScalarTypeToUnsignedInt() + {this->SetOutputScalarType(VTK_UNSIGNED_INT);}; + void SetOutputScalarTypeToLong(){this->SetOutputScalarType(VTK_LONG);}; + void SetOutputScalarTypeToUnsignedLong() + {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; + void SetOutputScalarTypeToShort(){this->SetOutputScalarType(VTK_SHORT);}; + void SetOutputScalarTypeToUnsignedShort() + {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);}; + void SetOutputScalarTypeToUnsignedChar() + {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);}; + void SetOutputScalarTypeToChar() + {this->SetOutputScalarType(VTK_CHAR);}; + + // Description: + // Initialize the filter for appending data. You must invoke the + // StartAppend() method before doing successive Appends(). It's also a + // good idea to manually specify the model bounds; otherwise the input + // bounds for the data will be used. + void StartAppend(); + + // Description: + // Append a data set to the existing output. To use this function, + // you'll have to invoke the StartAppend() method before doing + // successive appends. It's also a good idea to specify the model + // bounds; otherwise the input model bounds is used. When you've + // finished appending, use the EndAppend() method. + void Append(vtkDataSet *input); + + // Description: + // Method completes the append process. + void EndAppend(); + + // See the vtkAlgorithm for a desciption of what these do + int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkImplicitModeller(); + ~vtkImplicitModeller(); + + double GetScalarTypeMax(int type); + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData (vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + + void StartAppend(int internal); + void Cap(vtkDataArray *s); + + vtkMultiThreader *Threader; + int NumberOfThreads; + + int SampleDimensions[3]; + double MaximumDistance; + double ModelBounds[6]; + int Capping; + double CapValue; + int DataAppended; + int AdjustBounds; + double AdjustDistance; + int ProcessMode; + int LocatorMaxLevel; + int OutputScalarType; + int ScaleToMaximumDistance; + + // flag to limit to one ComputeModelBounds per StartAppend + int BoundsComputed; + + // the max distance computed during that one call + double InternalMaxDistance; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkImplicitModeller(const vtkImplicitModeller&); // Not implemented. + void operator=(const vtkImplicitModeller&); // Not implemented. +}; + +#endif + + diff --git a/Hybrid/vtkIterativeClosestPointTransform.cxx b/Hybrid/vtkIterativeClosestPointTransform.cxx new file mode 100644 index 0000000..873ba5f --- /dev/null +++ b/Hybrid/vtkIterativeClosestPointTransform.cxx @@ -0,0 +1,515 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIterativeClosestPointTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIterativeClosestPointTransform.h" + +#include "vtkCellLocator.h" +#include "vtkDataSet.h" +#include "vtkLandmarkTransform.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkIterativeClosestPointTransform, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkIterativeClosestPointTransform); + +//---------------------------------------------------------------------------- + +vtkIterativeClosestPointTransform::vtkIterativeClosestPointTransform() + : vtkLinearTransform() +{ + this->Source = NULL; + this->Target = NULL; + this->Locator = NULL; + this->LandmarkTransform = vtkLandmarkTransform::New(); + this->MaximumNumberOfIterations = 50; + this->CheckMeanDistance = 0; + this->MeanDistanceMode = VTK_ICP_MODE_RMS; + this->MaximumMeanDistance = 0.01; + this->MaximumNumberOfLandmarks = 200; + this->StartByMatchingCentroids = 0; + + this->NumberOfIterations = 0; + this->MeanDistance = 0.0; +} + +//---------------------------------------------------------------------------- + +const char *vtkIterativeClosestPointTransform::GetMeanDistanceModeAsString() +{ + if ( this->MeanDistanceMode == VTK_ICP_MODE_RMS ) + { + return "RMS"; + } + else + { + return "AbsoluteValue"; + } +} + +//---------------------------------------------------------------------------- + +vtkIterativeClosestPointTransform::~vtkIterativeClosestPointTransform() +{ + ReleaseSource(); + ReleaseTarget(); + ReleaseLocator(); + this->LandmarkTransform->Delete(); +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::SetSource(vtkDataSet *source) +{ + if (this->Source == source) + { + return; + } + + if (this->Source) + { + this->ReleaseSource(); + } + + if (source) + { + source->Register(this); + } + + this->Source = source; + this->Modified(); +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::ReleaseSource(void) { + if (this->Source) + { + this->Source->UnRegister(this); + this->Source = NULL; + } +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::SetTarget(vtkDataSet *target) +{ + if (this->Target == target) + { + return; + } + + if (this->Target) + { + this->ReleaseTarget(); + } + + if (target) + { + target->Register(this); + } + + this->Target = target; + this->Modified(); +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::ReleaseTarget(void) { + if (this->Target) + { + this->Target->UnRegister(this); + this->Target = NULL; + } +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::SetLocator(vtkCellLocator *locator) +{ + if (this->Locator == locator) + { + return; + } + + if (this->Locator) + { + this->ReleaseLocator(); + } + + if (locator) + { + locator->Register(this); + } + + this->Locator = locator; + this->Modified(); +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::ReleaseLocator(void) { + if (this->Locator) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::CreateDefaultLocator() { + if (this->Locator) + { + this->ReleaseLocator(); + } + + this->Locator = vtkCellLocator::New(); +} + +//------------------------------------------------------------------------ + +unsigned long vtkIterativeClosestPointTransform::GetMTime() +{ + unsigned long result = this->vtkLinearTransform::GetMTime(); + unsigned long mtime; + + if (this->Source) + { + mtime = this->Source->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + + if (this->Target) + { + mtime = this->Target->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + + if (this->Locator) + { + mtime = this->Locator->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + + if (this->LandmarkTransform) + { + mtime = this->LandmarkTransform->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + + return result; +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::Inverse() +{ + vtkDataSet *tmp1 = this->Source; + this->Source = this->Target; + this->Target = tmp1; + this->Modified(); +} + +//---------------------------------------------------------------------------- + +vtkAbstractTransform *vtkIterativeClosestPointTransform::MakeTransform() +{ + return vtkIterativeClosestPointTransform::New(); +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::InternalDeepCopy(vtkAbstractTransform *transform) +{ + vtkIterativeClosestPointTransform *t = (vtkIterativeClosestPointTransform *)transform; + + this->SetSource(t->GetSource()); + this->SetTarget(t->GetTarget()); + this->SetLocator(t->GetLocator()); + this->SetMaximumNumberOfIterations(t->GetMaximumNumberOfIterations()); + this->SetCheckMeanDistance(t->GetCheckMeanDistance()); + this->SetMeanDistanceMode(t->GetMeanDistanceMode()); + this->SetMaximumMeanDistance(t->GetMaximumMeanDistance()); + this->SetMaximumNumberOfLandmarks(t->GetMaximumNumberOfLandmarks()); + + this->Modified(); +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::InternalUpdate() +{ + // Check source, target + + if (this->Source == NULL || !this->Source->GetNumberOfPoints()) + { + vtkErrorMacro(<<"Can't execute with NULL or empty input"); + return; + } + + if (this->Target == NULL || !this->Target->GetNumberOfPoints()) + { + vtkErrorMacro(<<"Can't execute with NULL or empty target"); + return; + } + + // Create locator + + this->CreateDefaultLocator(); + this->Locator->SetDataSet(this->Target); + this->Locator->SetNumberOfCellsPerBucket(1); + this->Locator->BuildLocator(); + + // Create two sets of points to handle iteration + + int step = 1; + if (this->Source->GetNumberOfPoints() > this->MaximumNumberOfLandmarks) + { + step = this->Source->GetNumberOfPoints() / this->MaximumNumberOfLandmarks; + vtkDebugMacro(<< "Landmarks step is now : " << step); + } + + vtkIdType nb_points = this->Source->GetNumberOfPoints() / step; + + // Allocate some points. + // - closestp is used so that the internal state of LandmarkTransform remains + // correct whenever the iteration process is stopped (hence its source + // and landmark points might be used in a vtkThinPlateSplineTransform). + // - points2 could have been avoided, but do not ask me why + // InternalTransformPoint is not working correctly on my computer when + // in and out are the same pointer. + + vtkPoints *points1 = vtkPoints::New(); + points1->SetNumberOfPoints(nb_points); + + vtkPoints *closestp = vtkPoints::New(); + closestp->SetNumberOfPoints(nb_points); + + vtkPoints *points2 = vtkPoints::New(); + points2->SetNumberOfPoints(nb_points); + + // Fill with initial positions (sample dataset using step) + + vtkTransform *accumulate = vtkTransform::New(); + accumulate->PostMultiply(); + + vtkIdType i; + int j; + double p1[3], p2[3]; + + if (StartByMatchingCentroids) + { + double source_centroid[3] = {0,0,0}; + for (i = 0; i < this->Source->GetNumberOfPoints(); i++) + { + this->Source->GetPoint(i, p1); + source_centroid[0] += p1[0]; + source_centroid[1] += p1[1]; + source_centroid[2] += p1[2]; + } + source_centroid[0] /= this->Source->GetNumberOfPoints(); + source_centroid[1] /= this->Source->GetNumberOfPoints(); + source_centroid[2] /= this->Source->GetNumberOfPoints(); + + double target_centroid[3] = {0,0,0}; + for (i = 0; i < this->Target->GetNumberOfPoints(); i++) + { + this->Target->GetPoint(i, p2); + target_centroid[0] += p2[0]; + target_centroid[1] += p2[1]; + target_centroid[2] += p2[2]; + } + target_centroid[0] /= this->Target->GetNumberOfPoints(); + target_centroid[1] /= this->Target->GetNumberOfPoints(); + target_centroid[2] /= this->Target->GetNumberOfPoints(); + + accumulate->Translate(target_centroid[0] - source_centroid[0], + target_centroid[1] - source_centroid[1], + target_centroid[2] - source_centroid[2]); + accumulate->Update(); + + for (i = 0, j = 0; i < nb_points; i++, j += step) + { + double outPoint[3]; + accumulate->InternalTransformPoint(this->Source->GetPoint(j), + outPoint); + points1->SetPoint(i, outPoint); + } + } + else + { + for (i = 0, j = 0; i < nb_points; i++, j += step) + { + points1->SetPoint(i, this->Source->GetPoint(j)); + } + } + + // Go + + vtkIdType cell_id; + int sub_id; + double dist2, totaldist = 0; + double outPoint[3]; + + vtkPoints *temp, *a = points1, *b = points2; + + this->NumberOfIterations = 0; + + do + { + // Fill points with the closest points to each vertex in input + + for(i = 0; i < nb_points; i++) + { + this->Locator->FindClosestPoint(a->GetPoint(i), + outPoint, + cell_id, + sub_id, + dist2); + closestp->SetPoint(i, outPoint); + } + + // Build the landmark transform + + this->LandmarkTransform->SetSourceLandmarks(a); + this->LandmarkTransform->SetTargetLandmarks(closestp); + this->LandmarkTransform->Update(); + + // Concatenate (can't use this->Concatenate directly) + + accumulate->Concatenate(this->LandmarkTransform->GetMatrix()); + + this->NumberOfIterations++; + vtkDebugMacro(<< "Iteration: " << this->NumberOfIterations); + if (this->NumberOfIterations >= this->MaximumNumberOfIterations) + { + break; + } + + // Move mesh and compute mean distance if needed + + if (this->CheckMeanDistance) + { + totaldist = 0.0; + } + + for(i = 0; i < nb_points; i++) + { + a->GetPoint(i, p1); + this->LandmarkTransform->InternalTransformPoint(p1, p2); + b->SetPoint(i, p2); + if (this->CheckMeanDistance) + { + if (this->MeanDistanceMode == VTK_ICP_MODE_RMS) + { + totaldist += vtkMath::Distance2BetweenPoints(p1, p2); + } else { + totaldist += sqrt(vtkMath::Distance2BetweenPoints(p1, p2)); + } + } + } + + if (this->CheckMeanDistance) + { + if (this->MeanDistanceMode == VTK_ICP_MODE_RMS) + { + this->MeanDistance = sqrt(totaldist / (double)nb_points); + } else { + this->MeanDistance = totaldist / (double)nb_points; + } + vtkDebugMacro("Mean distance: " << this->MeanDistance); + if (this->MeanDistance <= this->MaximumMeanDistance) + { + break; + } + } + + temp = a; + a = b; + b = temp; + + } + while (1); + + // Now recover accumulated result + + this->Matrix->DeepCopy(accumulate->GetMatrix()); + + accumulate->Delete(); + points1->Delete(); + closestp->Delete(); + points2->Delete(); +} + +//---------------------------------------------------------------------------- + +void vtkIterativeClosestPointTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Source ) + { + os << indent << "Source: " << this->Source << "\n"; + } + else + { + os << indent << "Source: (none)\n"; + } + + if ( this->Target ) + { + os << indent << "Target: " << this->Target << "\n"; + } + else + { + os << indent << "Target: (none)\n"; + } + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } + + os << indent << "MaximumNumberOfIterations: " << this->MaximumNumberOfIterations << "\n"; + os << indent << "CheckMeanDistance: " << this->CheckMeanDistance << "\n"; + os << indent << "MeanDistanceMode: " << this->GetMeanDistanceModeAsString() << "\n"; + os << indent << "MaximumMeanDistance: " << this->MaximumMeanDistance << "\n"; + os << indent << "MaximumNumberOfLandmarks: " << this->MaximumNumberOfLandmarks << "\n"; + os << indent << "StartByMatchingCentroids: " << this->StartByMatchingCentroids << "\n"; + os << indent << "NumberOfIterations: " << this->NumberOfIterations << "\n"; + os << indent << "MeanDistance: " << this->MeanDistance << "\n"; + if(this->LandmarkTransform) + { + os << indent << "LandmarkTransform:\n"; + this->LandmarkTransform->PrintSelf(os, indent.GetNextIndent()); + } +} diff --git a/Hybrid/vtkIterativeClosestPointTransform.h b/Hybrid/vtkIterativeClosestPointTransform.h new file mode 100644 index 0000000..02e83b2 --- /dev/null +++ b/Hybrid/vtkIterativeClosestPointTransform.h @@ -0,0 +1,182 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIterativeClosestPointTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkIterativeClosestPointTransform - Implementation of the ICP algorithm. +// .SECTION Description +// Match two surfaces using the iterative closest point (ICP) algorithm. +// The core of the algorithm is to match each vertex in one surface with +// the closest surface point on the other, then apply the transformation +// that modify one surface to best match the other (in a least square sense). +// This has to be iterated to get proper convergence of the surfaces. +// .SECTION Note +// Use vtkTransformPolyDataFilter to apply the resulting ICP transform to +// your data. You might also set it to your actor's user transform. +// .SECTION Note +// This class makes use of vtkLandmarkTransform internally to compute the +// best fit. Use the GetLandmarkTransform member to get a pointer to that +// transform and set its parameters. You might, for example, constrain the +// number of degrees of freedom of the solution (i.e. rigid body, similarity, +// etc.) by checking the vtkLandmarkTransform documentation for its SetMode +// member. +// .SECTION see also +// vtkLandmarkTransform + + +#ifndef __vtkIterativeClosestPointTransform_h +#define __vtkIterativeClosestPointTransform_h + +#include "vtkLinearTransform.h" + +#define VTK_ICP_MODE_RMS 0 +#define VTK_ICP_MODE_AV 1 + +class vtkCellLocator; +class vtkLandmarkTransform; +class vtkDataSet; + +class VTK_HYBRID_EXPORT vtkIterativeClosestPointTransform : public vtkLinearTransform +{ +public: + static vtkIterativeClosestPointTransform *New(); + vtkTypeRevisionMacro(vtkIterativeClosestPointTransform,vtkLinearTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the source and target data sets. + void SetSource(vtkDataSet *source); + void SetTarget(vtkDataSet *target); + vtkGetObjectMacro(Source, vtkDataSet); + vtkGetObjectMacro(Target, vtkDataSet); + + // Description: + // Set/Get a spatial locator for speeding up the search process. + // An instance of vtkCellLocator is used by default. + void SetLocator(vtkCellLocator *locator); + vtkGetObjectMacro(Locator,vtkCellLocator); + + // Description: + // Set/Get the maximum number of iterations + vtkSetMacro(MaximumNumberOfIterations, int); + vtkGetMacro(MaximumNumberOfIterations, int); + + // Description: + // Get the number of iterations since the last update + vtkGetMacro(NumberOfIterations, int); + + // Description: + // Force the algorithm to check the mean distance between two iteration. + vtkSetMacro(CheckMeanDistance, int); + vtkGetMacro(CheckMeanDistance, int); + vtkBooleanMacro(CheckMeanDistance, int); + + // Description: + // Specify the mean distance mode. This mode expresses how the mean + // distance is computed. The RMS mode is the square root of the average + // of the sum of squares of the closest point distances. The Absolute + // Value mode is the mean of the sum of absolute values of the closest + // point distances. + vtkSetClampMacro(MeanDistanceMode,int, + VTK_ICP_MODE_RMS,VTK_ICP_MODE_AV); + vtkGetMacro(MeanDistanceMode,int); + void SetMeanDistanceModeToRMS() + {this->SetMeanDistanceMode(VTK_ICP_MODE_RMS);} + void SetMeanDistanceModeToAbsoluteValue() + {this->SetMeanDistanceMode(VTK_ICP_MODE_AV);} + const char *GetMeanDistanceModeAsString(); + + // Description: + // Set/Get the maximum mean distance between two iteration. If the mean + // distance is lower than this, the convergence stops. + vtkSetMacro(MaximumMeanDistance, double); + vtkGetMacro(MaximumMeanDistance, double); + + // Description: + // Get the mean distance between the last two iterations. + vtkGetMacro(MeanDistance, double); + + // Description: + // Set/Get the maximum number of landmarks sampled in your dataset. + // If your dataset is dense, then you will typically not need all the + // points to compute the ICP transform. + vtkSetMacro(MaximumNumberOfLandmarks, int); + vtkGetMacro(MaximumNumberOfLandmarks, int); + + // Description: + // Starts the process by translating source centroid to target centroid. + vtkSetMacro(StartByMatchingCentroids, int); + vtkGetMacro(StartByMatchingCentroids, int); + vtkBooleanMacro(StartByMatchingCentroids, int); + + // Description: + // Get the internal landmark transform. Use it to constrain the number of + // degrees of freedom of the solution (i.e. rigid body, similarity, etc.). + vtkGetObjectMacro(LandmarkTransform,vtkLandmarkTransform); + + // Description: + // Invert the transformation. This is done by switching the + // source and target. + void Inverse(); + + // Description: + // Make another transform of the same type. + vtkAbstractTransform *MakeTransform(); + +protected: + + // Description: + // Release source and target + void ReleaseSource(void); + void ReleaseTarget(void); + + // Description: + // Release locator + void ReleaseLocator(void); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(void); + + // Description: + // Get the MTime of this object also considering the locator. + unsigned long int GetMTime(); + + vtkIterativeClosestPointTransform(); + ~vtkIterativeClosestPointTransform(); + + void InternalUpdate(); + + // Description: + // This method does no type checking, use DeepCopy instead. + void InternalDeepCopy(vtkAbstractTransform *transform); + + vtkDataSet* Source; + vtkDataSet* Target; + vtkCellLocator *Locator; + int MaximumNumberOfIterations; + int CheckMeanDistance; + int MeanDistanceMode; + double MaximumMeanDistance; + int MaximumNumberOfLandmarks; + int StartByMatchingCentroids; + + int NumberOfIterations; + double MeanDistance; + vtkLandmarkTransform *LandmarkTransform; +private: + vtkIterativeClosestPointTransform(const vtkIterativeClosestPointTransform&); // Not implemented. + void operator=(const vtkIterativeClosestPointTransform&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkLandmarkTransform.cxx b/Hybrid/vtkLandmarkTransform.cxx new file mode 100644 index 0000000..c267bec --- /dev/null +++ b/Hybrid/vtkLandmarkTransform.cxx @@ -0,0 +1,463 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLandmarkTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLandmarkTransform.h" + +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkLandmarkTransform, "$Revision: 1.24 $"); +vtkStandardNewMacro(vtkLandmarkTransform); + +//---------------------------------------------------------------------------- +vtkLandmarkTransform::vtkLandmarkTransform() +{ + this->Mode = VTK_LANDMARK_SIMILARITY; + this->SourceLandmarks=NULL; + this->TargetLandmarks=NULL; +} + +//---------------------------------------------------------------------------- +vtkLandmarkTransform::~vtkLandmarkTransform() +{ + if(this->SourceLandmarks) + { + this->SourceLandmarks->Delete(); + } + if(this->TargetLandmarks) + { + this->TargetLandmarks->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkLandmarkTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << "Mode: " << this->GetModeAsString() << "\n"; + os << "SourceLandmarks: " << this->SourceLandmarks << "\n"; + if(this->SourceLandmarks) + { + this->SourceLandmarks->PrintSelf(os,indent.GetNextIndent()); + } + os << "TargetLandmarks: " << this->TargetLandmarks << "\n"; + if(this->TargetLandmarks) + { + this->TargetLandmarks->PrintSelf(os,indent.GetNextIndent()); + } +} + +//---------------------------------------------------------------------------- +// Update the 4x4 matrix. Updates are only done as necessary. + +void vtkLandmarkTransform::InternalUpdate() +{ + vtkIdType i; + int j; + + if (this->SourceLandmarks == NULL || this->TargetLandmarks == NULL) + { + this->Matrix->Identity(); + return; + } + + // --- compute the necessary transform to match the two sets of landmarks --- + + /* + The solution is based on + Berthold K. P. Horn (1987), + "Closed-form solution of absolute orientation using unit quaternions," + Journal of the Optical Society of America A, 4:629-642 + */ + + // Original python implementation by David G. Gobbi + + const vtkIdType N_PTS = this->SourceLandmarks->GetNumberOfPoints(); + if(N_PTS != this->TargetLandmarks->GetNumberOfPoints()) + { + vtkErrorMacro("Update: Source and Target Landmarks contain a different number of points"); + return; + } + + // -- if no points, stop here + + if (N_PTS == 0) + { + this->Matrix->Identity(); + return; + } + + // -- find the centroid of each set -- + + double source_centroid[3]={0,0,0}; + double target_centroid[3]={0,0,0}; + double p[3]; + for(i=0;iSourceLandmarks->GetPoint(i, p); + source_centroid[0] += p[0]; + source_centroid[1] += p[1]; + source_centroid[2] += p[2]; + this->TargetLandmarks->GetPoint(i, p); + target_centroid[0] += p[0]; + target_centroid[1] += p[1]; + target_centroid[2] += p[2]; + } + source_centroid[0] /= N_PTS; + source_centroid[1] /= N_PTS; + source_centroid[2] /= N_PTS; + target_centroid[0] /= N_PTS; + target_centroid[1] /= N_PTS; + target_centroid[2] /= N_PTS; + + // -- if only one point, stop right here + + if (N_PTS == 1) + { + this->Matrix->Identity(); + this->Matrix->Element[0][3] = target_centroid[0] - source_centroid[0]; + this->Matrix->Element[1][3] = target_centroid[1] - source_centroid[1]; + this->Matrix->Element[2][3] = target_centroid[2] - source_centroid[2]; + return; + } + + // -- build the 3x3 matrix M -- + + double M[3][3]; + double AAT[3][3]; + for(i=0;i<3;i++) + { + AAT[i][0] = M[i][0]=0.0F; // fill M with zeros + AAT[i][1] = M[i][1]=0.0F; + AAT[i][2] = M[i][2]=0.0F; + } + vtkIdType pt; + double a[3],b[3]; + double sa=0.0F,sb=0.0F; + for(pt=0;ptSourceLandmarks->GetPoint(pt,a); + a[0] -= source_centroid[0]; + a[1] -= source_centroid[1]; + a[2] -= source_centroid[2]; + // get the origin-centred point (b) in the target set + this->TargetLandmarks->GetPoint(pt,b); + b[0] -= target_centroid[0]; + b[1] -= target_centroid[1]; + b[2] -= target_centroid[2]; + // accumulate the products a*T(b) into the matrix M + for(i=0;i<3;i++) + { + M[i][0] += a[i]*b[0]; + M[i][1] += a[i]*b[1]; + M[i][2] += a[i]*b[2]; + + // for the affine transform, compute ((a.a^t)^-1 . a.b^t)^t. + // a.b^t is already in M. here we put a.a^t in AAT. + if (this->Mode == VTK_LANDMARK_AFFINE) + { + AAT[i][0] += a[i]*a[0]; + AAT[i][1] += a[i]*a[1]; + AAT[i][2] += a[i]*a[2]; + } + } + // accumulate scale factors (if desired) + sa += a[0]*a[0]+a[1]*a[1]+a[2]*a[2]; + sb += b[0]*b[0]+b[1]*b[1]+b[2]*b[2]; + } + + if(this->Mode == VTK_LANDMARK_AFFINE) + { + // AAT = (a.a^t)^-1 + vtkMath::Invert3x3(AAT,AAT); + + // M = (a.a^t)^-1 . a.b^t + vtkMath::Multiply3x3(AAT,M,M); + + // this->Matrix = M^t + for(i=0;i<3;++i) + { + for(j=0;j<3;++j) + { + this->Matrix->Element[i][j] = M[j][i]; + } + } + } + else + { + // compute required scaling factor (if desired) + double scale = (double)sqrt(sb/sa); + + // -- build the 4x4 matrix N -- + + double Ndata[4][4]; + double *N[4]; + for(i=0;i<4;i++) + { + N[i] = Ndata[i]; + N[i][0]=0.0F; // fill N with zeros + N[i][1]=0.0F; + N[i][2]=0.0F; + N[i][3]=0.0F; + } + // on-diagonal elements + N[0][0] = M[0][0]+M[1][1]+M[2][2]; + N[1][1] = M[0][0]-M[1][1]-M[2][2]; + N[2][2] = -M[0][0]+M[1][1]-M[2][2]; + N[3][3] = -M[0][0]-M[1][1]+M[2][2]; + // off-diagonal elements + N[0][1] = N[1][0] = M[1][2]-M[2][1]; + N[0][2] = N[2][0] = M[2][0]-M[0][2]; + N[0][3] = N[3][0] = M[0][1]-M[1][0]; + + N[1][2] = N[2][1] = M[0][1]+M[1][0]; + N[1][3] = N[3][1] = M[2][0]+M[0][2]; + N[2][3] = N[3][2] = M[1][2]+M[2][1]; + + // -- eigen-decompose N (is symmetric) -- + + double eigenvectorData[4][4]; + double *eigenvectors[4],eigenvalues[4]; + + eigenvectors[0] = eigenvectorData[0]; + eigenvectors[1] = eigenvectorData[1]; + eigenvectors[2] = eigenvectorData[2]; + eigenvectors[3] = eigenvectorData[3]; + + vtkMath::JacobiN(N,4,eigenvalues,eigenvectors); + + // the eigenvector with the largest eigenvalue is the quaternion we want + // (they are sorted in decreasing order for us by JacobiN) + double w,x,y,z; + + // first: if points are collinear, choose the quaternion that + // results in the smallest rotation. + if (eigenvalues[0] == eigenvalues[1] || N_PTS == 2) + { + double s0[3],t0[3],s1[3],t1[3]; + this->SourceLandmarks->GetPoint(0,s0); + this->TargetLandmarks->GetPoint(0,t0); + this->SourceLandmarks->GetPoint(1,s1); + this->TargetLandmarks->GetPoint(1,t1); + + double ds[3],dt[3]; + double rs = 0, rt = 0; + for (i = 0; i < 3; i++) + { + ds[i] = s1[i] - s0[i]; // vector between points + rs += ds[i]*ds[i]; + dt[i] = t1[i] - t0[i]; + rt += dt[i]*dt[i]; + } + + // normalize the two vectors + rs = sqrt(rs); + ds[0] /= rs; ds[1] /= rs; ds[2] /= rs; + rt = sqrt(rt); + dt[0] /= rt; dt[1] /= rt; dt[2] /= rt; + + // take dot & cross product + w = ds[0]*dt[0] + ds[1]*dt[1] + ds[2]*dt[2]; + x = ds[1]*dt[2] - ds[2]*dt[1]; + y = ds[2]*dt[0] - ds[0]*dt[2]; + z = ds[0]*dt[1] - ds[1]*dt[0]; + + double r = sqrt(x*x + y*y + z*z); + double theta = atan2(r,w); + + // construct quaternion + w = cos(theta/2); + if (r != 0) + { + r = sin(theta/2)/r; + x = x*r; + y = y*r; + z = z*r; + } + else // rotation by 180 degrees: special case + { + // rotate around a vector perpendicular to ds + vtkMath::Perpendiculars(ds,dt,0,0); + r = sin(theta/2); + x = dt[0]*r; + y = dt[1]*r; + z = dt[2]*r; + } + } + else // points are not collinear + { + w = eigenvectors[0][0]; + x = eigenvectors[1][0]; + y = eigenvectors[2][0]; + z = eigenvectors[3][0]; + } + + // convert quaternion to a rotation matrix + + double ww = w*w; + double wx = w*x; + double wy = w*y; + double wz = w*z; + + double xx = x*x; + double yy = y*y; + double zz = z*z; + + double xy = x*y; + double xz = x*z; + double yz = y*z; + + this->Matrix->Element[0][0] = ww + xx - yy - zz; + this->Matrix->Element[1][0] = 2.0*(wz + xy); + this->Matrix->Element[2][0] = 2.0*(-wy + xz); + + this->Matrix->Element[0][1] = 2.0*(-wz + xy); + this->Matrix->Element[1][1] = ww - xx + yy - zz; + this->Matrix->Element[2][1] = 2.0*(wx + yz); + + this->Matrix->Element[0][2] = 2.0*(wy + xz); + this->Matrix->Element[1][2] = 2.0*(-wx + yz); + this->Matrix->Element[2][2] = ww - xx - yy + zz; + + if (this->Mode != VTK_LANDMARK_RIGIDBODY) + { // add in the scale factor (if desired) + for(i=0;i<3;i++) + { + this->Matrix->Element[i][0] *= scale; + this->Matrix->Element[i][1] *= scale; + this->Matrix->Element[i][2] *= scale; + } + } + } + + // the translation is given by the difference in the transformed source + // centroid and the target centroid + double sx, sy, sz; + + sx = this->Matrix->Element[0][0] * source_centroid[0] + + this->Matrix->Element[0][1] * source_centroid[1] + + this->Matrix->Element[0][2] * source_centroid[2]; + sy = this->Matrix->Element[1][0] * source_centroid[0] + + this->Matrix->Element[1][1] * source_centroid[1] + + this->Matrix->Element[1][2] * source_centroid[2]; + sz = this->Matrix->Element[2][0] * source_centroid[0] + + this->Matrix->Element[2][1] * source_centroid[1] + + this->Matrix->Element[2][2] * source_centroid[2]; + + this->Matrix->Element[0][3] = target_centroid[0] - sx; + this->Matrix->Element[1][3] = target_centroid[1] - sy; + this->Matrix->Element[2][3] = target_centroid[2] - sz; + + // fill the bottom row of the 4x4 matrix + this->Matrix->Element[3][0] = 0.0; + this->Matrix->Element[3][1] = 0.0; + this->Matrix->Element[3][2] = 0.0; + this->Matrix->Element[3][3] = 1.0; + + this->Matrix->Modified(); +} + +//------------------------------------------------------------------------ +unsigned long vtkLandmarkTransform::GetMTime() +{ + unsigned long result = this->vtkLinearTransform::GetMTime(); + unsigned long mtime; + + if (this->SourceLandmarks) + { + mtime = this->SourceLandmarks->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + if (this->TargetLandmarks) + { + mtime = this->TargetLandmarks->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + return result; +} +//------------------------------------------------------------------------ +void vtkLandmarkTransform::SetSourceLandmarks(vtkPoints *source) +{ + if (this->SourceLandmarks == source) + { + return; + } + + if (this->SourceLandmarks) + { + this->SourceLandmarks->Delete(); + } + + source->Register(this); + this->SourceLandmarks = source; + + this->Modified(); +} + +//------------------------------------------------------------------------ +void vtkLandmarkTransform::SetTargetLandmarks(vtkPoints *target) +{ + if (this->TargetLandmarks == target) + { + return; + } + + if (this->TargetLandmarks) + { + this->TargetLandmarks->Delete(); + } + + target->Register(this); + this->TargetLandmarks = target; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkLandmarkTransform::Inverse() +{ + vtkPoints *tmp1 = this->SourceLandmarks; + vtkPoints *tmp2 = this->TargetLandmarks; + this->TargetLandmarks = tmp1; + this->SourceLandmarks = tmp2; + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkLandmarkTransform::MakeTransform() +{ + return vtkLandmarkTransform::New(); +} + +//---------------------------------------------------------------------------- +void vtkLandmarkTransform::InternalDeepCopy(vtkAbstractTransform *transform) +{ + vtkLandmarkTransform *t = (vtkLandmarkTransform *)transform; + + this->SetMode(t->Mode); + this->SetSourceLandmarks(t->SourceLandmarks); + this->SetTargetLandmarks(t->TargetLandmarks); + + this->Modified(); +} + + diff --git a/Hybrid/vtkLandmarkTransform.h b/Hybrid/vtkLandmarkTransform.h new file mode 100644 index 0000000..ea7acbd --- /dev/null +++ b/Hybrid/vtkLandmarkTransform.h @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLandmarkTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLandmarkTransform - a linear transform specified by two corresponding point sets +// .SECTION Description +// A vtkLandmarkTransform is defined by two sets of landmarks, the +// transform computed gives the best fit mapping one onto the other, in a +// least squares sense. The indices are taken to correspond, so point 1 +// in the first set will get mapped close to point 1 in the second set, +// etc. Call SetSourceLandmarks and SetTargetLandmarks to specify the two +// sets of landmarks, ensure they have the same number of points. +// .SECTION Caveats +// Whenever you add, subtract, or set points you must call Modified() +// on the vtkPoints object, or the transformation might not update. +// .SECTION see also +// vtkLinearTransform + +#ifndef __vtkLandmarkTransform_h +#define __vtkLandmarkTransform_h + +#include "vtkLinearTransform.h" + +#define VTK_LANDMARK_RIGIDBODY 6 +#define VTK_LANDMARK_SIMILARITY 7 +#define VTK_LANDMARK_AFFINE 12 + +class VTK_HYBRID_EXPORT vtkLandmarkTransform : public vtkLinearTransform +{ +public: + static vtkLandmarkTransform *New(); + + vtkTypeRevisionMacro(vtkLandmarkTransform,vtkLinearTransform); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the source and target landmark sets. The two sets must have + // the same number of points. If you add or change points in these objects, + // you must call Modified() on them or the transformation might not update. + void SetSourceLandmarks(vtkPoints *points); + void SetTargetLandmarks(vtkPoints *points); + vtkGetObjectMacro(SourceLandmarks, vtkPoints); + vtkGetObjectMacro(TargetLandmarks, vtkPoints); + + // Description: + // Set the number of degrees of freedom to constrain the solution to. + // Rigidbody: rotation and translation only. + // Similarity: rotation, translation and isotropic scaling. + // The default is similarity. + vtkSetMacro(Mode,int); + void SetModeToRigidBody() { this->SetMode(VTK_LANDMARK_RIGIDBODY); }; + void SetModeToSimilarity() { this->SetMode(VTK_LANDMARK_SIMILARITY); }; + void SetModeToAffine() { this->SetMode(VTK_LANDMARK_AFFINE); }; + vtkGetMacro(Mode,int); + const char *GetModeAsString(); + + // Description: + // Invert the transformation. This is done by switching the + // source and target landmarks. + void Inverse(); + + // Description: + // Get the MTime. + unsigned long GetMTime(); + + // Description: + // Make another transform of the same type. + vtkAbstractTransform *MakeTransform(); + +protected: + vtkLandmarkTransform(); + ~vtkLandmarkTransform(); + + // Update the matrix from the quaternion. + void InternalUpdate(); + + // Description: + // This method does no type checking, use DeepCopy instead. + void InternalDeepCopy(vtkAbstractTransform *transform); + + vtkPoints* SourceLandmarks; + vtkPoints* TargetLandmarks; + + int Mode; +private: + vtkLandmarkTransform(const vtkLandmarkTransform&); // Not implemented. + void operator=(const vtkLandmarkTransform&); // Not implemented. +}; + +//BTX +inline const char *vtkLandmarkTransform::GetModeAsString() +{ + switch (this->Mode) + { + case VTK_LANDMARK_RIGIDBODY: + return "RigidBody"; + case VTK_LANDMARK_SIMILARITY: + return "Similarity"; + case VTK_LANDMARK_AFFINE: + return "Affine"; + default: + return "Unrecognized"; + } +} +//ETX +#endif diff --git a/Hybrid/vtkLegendBoxActor.cxx b/Hybrid/vtkLegendBoxActor.cxx new file mode 100644 index 0000000..142208c --- /dev/null +++ b/Hybrid/vtkLegendBoxActor.cxx @@ -0,0 +1,716 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLegendBoxActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLegendBoxActor.h" + +#include "vtkActor.h" +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkProperty2D.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkTransform.h" +#include "vtkTransformPolyDataFilter.h" +#include "vtkViewport.h" + +vtkCxxRevisionMacro(vtkLegendBoxActor, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkLegendBoxActor); + +vtkCxxSetObjectMacro(vtkLegendBoxActor,EntryTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +vtkLegendBoxActor::vtkLegendBoxActor() +{ + // Positioning information + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.75, 0.75); + + this->Position2Coordinate->SetValue(0.2, 0.2); + + this->LockBorder = 0; + this->ScalarVisibility = 1; + + // Control font properties + this->EntryTextProperty = vtkTextProperty::New(); + this->EntryTextProperty->SetBold(0); + this->EntryTextProperty->SetItalic(0); + this->EntryTextProperty->SetShadow(0); + this->EntryTextProperty->SetFontFamily(VTK_ARIAL); + this->EntryTextProperty->SetJustification(VTK_TEXT_LEFT); + this->EntryTextProperty->SetVerticalJustification(VTK_TEXT_CENTERED); + + this->Border = 1; + this->Box = 0; + this->Padding = 3; + + // Symbols and text strings + this->NumberOfEntries = 0; + this->Size = 0; + this->Colors = NULL; + this->Symbol = NULL; + this->Transform = NULL; + this->SymbolTransform = NULL; + this->SymbolMapper = NULL; + this->SymbolActor = NULL; + this->TextMapper = NULL; + this->TextActor = NULL; + + // Construct the border + this->BorderPolyData = vtkPolyData::New(); + vtkPoints *points = vtkPoints::New(); + points->SetNumberOfPoints(4); + this->BorderPolyData->SetPoints(points); points->Delete(); + vtkCellArray *lines = vtkCellArray::New(); + lines->InsertNextCell(5); //points will be updated later + lines->InsertCellPoint(0); + lines->InsertCellPoint(1); + lines->InsertCellPoint(2); + lines->InsertCellPoint(3); + lines->InsertCellPoint(0); + this->BorderPolyData->SetLines(lines); lines->Delete(); + + this->BorderMapper = vtkPolyDataMapper2D::New(); + this->BorderMapper->SetInput(this->BorderPolyData); + + this->BorderActor = vtkActor2D::New(); + this->BorderActor->SetMapper(this->BorderMapper); + + // Construct the box + this->BoxPolyData = vtkPolyData::New(); + this->BoxPolyData->SetPoints(this->BorderPolyData->GetPoints()); + vtkCellArray *polys = vtkCellArray::New(); + polys->InsertNextCell(4); + polys->InsertCellPoint(0); + polys->InsertCellPoint(1); + polys->InsertCellPoint(2); + polys->InsertCellPoint(3); + this->BoxPolyData->SetPolys(polys); polys->Delete(); + + this->BoxMapper = vtkPolyDataMapper2D::New(); + this->BoxMapper->SetInput(this->BoxPolyData); + + this->BoxActor = vtkActor2D::New(); + this->BoxActor->SetMapper(this->BoxMapper); +} + +//---------------------------------------------------------------------------- +vtkLegendBoxActor::~vtkLegendBoxActor() +{ + this->InitializeEntries(); + + if ( this->BorderActor ) + { + this->BorderActor->Delete(); + this->BorderMapper->Delete(); + this->BorderPolyData->Delete(); + } + + if ( this->BoxActor ) + { + this->BoxActor->Delete(); + this->BoxMapper->Delete(); + this->BoxPolyData->Delete(); + } + + this->SetEntryTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::InitializeEntries() +{ + int i; + + if ( this->Size > 0 ) + { + this->Colors->Delete(); + for (i=0; iSize; i++) + { + if ( this->Symbol[i] ) + { + this->Symbol[i]->Delete(); + } + this->Transform[i]->Delete(); + this->SymbolTransform[i]->Delete(); + this->SymbolMapper[i]->Delete(); + this->SymbolActor[i]->Delete(); + if ( this->TextMapper[i] ) + { + this->TextMapper[i]->Delete(); + this->TextActor[i]->Delete(); + } + }//for all entries + delete [] this->Symbol; this->Symbol = NULL; + delete [] this->Transform; this->Transform = NULL; + delete [] this->SymbolTransform; this->SymbolTransform = NULL; + delete [] this->SymbolMapper; this->SymbolMapper = NULL; + delete [] this->SymbolActor; this->SymbolActor = NULL; + delete [] this->TextMapper; this->TextMapper = NULL; + delete [] this->TextActor; this->TextActor = NULL; + }//if entries have been defined +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::SetNumberOfEntries(int num) +{ + if ( num == this->NumberOfEntries ) + { + return; + } + + else if ( num < this->Size ) + { + this->NumberOfEntries = num; + } + + else //allocate space + { + int i; + + //Create internal actors, etc. + vtkDoubleArray *colors = vtkDoubleArray::New(); + colors->SetNumberOfComponents(3); + colors->SetNumberOfTuples(num); + vtkTextMapper **textMapper= new vtkTextMapper* [num]; + vtkActor2D **textActor = new vtkActor2D* [num]; + vtkPolyData **symbol = new vtkPolyData* [num]; + vtkTransform **transform= new vtkTransform* [num]; + vtkTransformPolyDataFilter **symbolTransform = + new vtkTransformPolyDataFilter* [num]; + vtkPolyDataMapper2D **symbolMapper = new vtkPolyDataMapper2D* [num]; + vtkActor2D **symbolActor = new vtkActor2D* [num]; + //copy old values + for (i=0; iNumberOfEntries; i++) + { + colors->SetTuple(i,this->Colors->GetTuple(i)); + textMapper[i] = this->TextMapper[i]; + textMapper[i]->Register(this); + textActor[i] = this->TextActor[i]; + textActor[i]->Register(this); + symbol[i] = this->Symbol[i]; + if ( symbol[i] ) + { + symbol[i]->Register(this); + } + transform[i] = this->Transform[i]; + transform[i]->Register(this); + symbolTransform[i] = this->SymbolTransform[i]; + symbolTransform[i]->Register(this); + symbolMapper[i] = this->SymbolMapper[i]; + symbolMapper[i]->Register(this); + symbolActor[i] = this->SymbolActor[i]; + symbolActor[i]->Register(this); + } + //initialize data values + static double color[3]={-1.0,-1.0,-1.0}; + for (i=this->NumberOfEntries; iSetTuple(i,color); + textMapper[i] = vtkTextMapper::New(); + textActor[i] = vtkActor2D::New(); + textActor[i]->SetMapper(textMapper[i]); + symbol[i] = NULL; + transform[i] = vtkTransform::New(); + symbolTransform[i] = vtkTransformPolyDataFilter::New(); + symbolTransform[i]->SetTransform(transform[i]); + symbolMapper[i] = vtkPolyDataMapper2D::New(); + symbolMapper[i]->SetInput(symbolTransform[i]->GetOutput()); + symbolActor[i] = vtkActor2D::New(); + symbolActor[i]->SetMapper(symbolMapper[i]); + } + + //Clear out the old stuff + this->InitializeEntries(); + + //Bring everything up to date + this->NumberOfEntries = this->Size = num; + this->Colors = colors; + this->TextMapper = textMapper; + this->TextActor = textActor; + this->Symbol = symbol; + this->Transform = transform; + this->SymbolTransform = symbolTransform; + this->SymbolMapper = symbolMapper; + this->SymbolActor = symbolActor; + } + + this->Modified(); + return; +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::SetEntry(int i, vtkPolyData *symbol, const char* string, + double color[3]) +{ + if ( i >= 0 && i < this->NumberOfEntries ) + { + this->SetEntrySymbol(i,symbol); + this->SetEntryString(i,string); + this->SetEntryColor(i,color); + } + + return; +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::SetEntrySymbol(int i, vtkPolyData *symbol) +{ + if ( i >= 0 && i < this->NumberOfEntries ) + { + if ( this->Symbol[i] == symbol ) + { + return; + } + if ( this->Symbol[i] ) + { + this->Symbol[i]->Delete(); + } + this->Symbol[i] = symbol; + if ( this->Symbol[i] ) + { + this->Symbol[i]->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::SetEntryString(int i, const char* string) +{ + if ( i >= 0 && i < this->NumberOfEntries ) + { + if ( this->TextMapper[i]->GetInput() && string + && (!strcmp(this->TextMapper[i]->GetInput(),string))) + { + return; + } + this->TextMapper[i]->SetInput(string); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::SetEntryColor(int i, double color[3]) +{ + if ( i >= 0 && i < this->NumberOfEntries ) + { + double oldColor[3]; + this->Colors->GetTuple(i, oldColor); + + if ( oldColor[0] != color[0] || oldColor[1] != color[1] || + oldColor[2] != color[2] ) + { + this->Colors->SetTuple3(i,color[0],color[1],color[2]); + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::SetEntryColor(int i, double r, double g, double b) +{ + double rgb[3]; + rgb[0] = r; rgb[1] = g; rgb[2] = b; + this->SetEntryColor(i,rgb); +} + +//---------------------------------------------------------------------------- +vtkPolyData *vtkLegendBoxActor::GetEntrySymbol(int i) +{ + if ( i < 0 || i >= this->NumberOfEntries ) + { + return NULL; + } + else + { + return this->Symbol[i]; + } +} + +//---------------------------------------------------------------------------- +const char* vtkLegendBoxActor::GetEntryString(int i) +{ + if ( i < 0 || i >= this->NumberOfEntries ) + { + return NULL; + } + else + { + return this->TextMapper[i]->GetInput(); + } +} + +//---------------------------------------------------------------------------- +double* vtkLegendBoxActor::GetEntryColor(int i) +{ + if ( i < 0 || i >= this->NumberOfEntries ) + { + return NULL; + } + else + { + return vtkDoubleArray::SafeDownCast(this->Colors)->GetPointer(i*3); + } +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkLegendBoxActor::ReleaseGraphicsResources(vtkWindow *win) +{ + if ( this->BorderActor ) + { + this->BorderActor->ReleaseGraphicsResources(win); + } + + if ( this->BoxActor ) + { + this->BoxActor->ReleaseGraphicsResources(win); + } + + for (int i=0; i < this->Size; i++) + { + this->TextActor[i]->ReleaseGraphicsResources(win); + this->SymbolActor[i]->ReleaseGraphicsResources(win); + } +} + +//---------------------------------------------------------------------------- +int vtkLegendBoxActor::RenderOverlay(vtkViewport *viewport) +{ + if ( this->NumberOfEntries <= 0 ) + { + return 0; + } + + int renderedSomething = 0; + if ( this->Border ) + { + renderedSomething += this->BorderActor->RenderOverlay(viewport); + } + + if ( this->Box ) + { + renderedSomething += this->BoxActor->RenderOverlay(viewport); + } + + if ( this->LegendEntriesVisible ) + { + for (int i=0; iNumberOfEntries; i++) + { + if ( this->Symbol[i] ) + { + renderedSomething += this->SymbolActor[i]->RenderOverlay(viewport); + } + renderedSomething += this->TextActor[i]->RenderOverlay(viewport); + } + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +int vtkLegendBoxActor::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int i; + double symbolSize; + + if ( this->NumberOfEntries <= 0 ) + { + return 0; + } + + if (!this->EntryTextProperty) + { + vtkErrorMacro(<<"Need entry text property to render legend box actor"); + return 0; + } + + // Check to see whether we have to rebuild everything + int *vsize = viewport->GetSize(); + if (this->GetMTime() > this->BuildTime || + this->EntryTextProperty->GetMTime() > this->BuildTime || + vsize[0] != this->CachedSize[0] || vsize[1] != this->CachedSize[1] ) + { + vtkDebugMacro(<<"Rebuilding text"); + this->CachedSize[0] = vsize[0]; + this->CachedSize[1] = vsize[1]; + + // If text prop has changed, recopy it to all mappers + // We have to use shallow copy since the color of each text prop + // can be overriden + + if (this->EntryTextProperty->GetMTime() > this->BuildTime) + { + for (i = 0; i < this->NumberOfEntries; i++) + { + this->TextMapper[i]->GetTextProperty()->ShallowCopy( + this->EntryTextProperty); + } + } + + //Get position information + int *x1, *x2; + double p1[3], p2[3]; + x1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + x2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + p1[0] = (double)x1[0]; p1[1] = (double)x1[1]; p1[2] = 0.0; + p2[0] = (double)x2[0]; p2[1] = (double)x2[1]; p2[2] = 0.0; + + //Compute spacing...trying to keep things proportional + // + //Find the longest string and symbol width ratio + int length, maxLength; + int maxTextMapper = 0; + char *str; + int tempi[2], fontSize; + double sf, twr, swr; + double *bounds; + for (swr=0.0, maxLength=i=0; iNumberOfEntries; i++) + { + str = this->TextMapper[i]->GetInput(); + if ( str ) //if there is a string + { + length = static_cast(strlen(str)); + if ( length > maxLength ) + { + maxLength = length; + maxTextMapper = i; + } + }//if string + + if ( this->Symbol[i] ) //if there is a symbol + { + this->Symbol[i]->Update(); + bounds = this->Symbol[i]->GetBounds(); + if ( (bounds[3]-bounds[2]) == 0.0 ) + { + sf = 1.0; + } + else + { + sf = (bounds[1]-bounds[0]) / (bounds[3]-bounds[2]); + } + if ( sf > swr ) + { + swr = sf; + } + }//if symbol defined + } + + //Compute the final proportion (symbol width to text width) + fontSize = 12; + this->TextMapper[maxTextMapper]->GetTextProperty()->SetFontSize(fontSize); + this->TextMapper[maxTextMapper]->GetSize(viewport,tempi); + twr = (double)tempi[0]/tempi[1]; + symbolSize = swr / (swr + twr); + + //Okay, now that the proportions are okay, let's size everything + //First the text + int size[2]; + size[0] = (int)((1.0-symbolSize)*(p2[0] - p1[0] - 2.0*this->Padding)); + size[1] = (int)((p2[1] - p1[1] - 2.0*this->Padding)/this->NumberOfEntries); + + fontSize = this->TextMapper[maxTextMapper]->SetConstrainedFontSize( + viewport, size[0], size[1]); + this->TextMapper[maxTextMapper]->GetSize(viewport,tempi); + + // don't draw anything if it's too small + if ( size[1] > 0 && fontSize > 0) + { + this->LegendEntriesVisible = 1; + } + else + { + this->LegendEntriesVisible = 0; + } + + //Border and box - may adjust spacing based on font size relationship + //to the proportions relative to the border + // + if (this->Border || this->Box) + { + //adjust the border/box placement if too much whitespace + if ( !this->LockBorder && tempi[0] < size[0] ) + { + p2[0] = p1[0] + 2.0*this->Padding + + symbolSize*(p2[0] - p1[0] - 2.0*this->Padding) + tempi[0]; + } + vtkPoints *pts = this->BorderPolyData->GetPoints(); + pts->SetPoint(0, p1); + pts->SetPoint(1, p2[0],p1[1],0.0); + pts->SetPoint(2, p2[0],p2[1],0.0); + pts->SetPoint(3, p1[0],p2[1],0.0); + } + + if (this->Border) + { + this->BorderActor->SetProperty(this->GetProperty()); + } + + //Place text strings + double color[3]; + double posY; + double posX = p1[0] + this->Padding + + symbolSize*(p2[0] - p1[0] - 2.0*this->Padding); + for (i=0; iNumberOfEntries; i++) + { + posY = p2[1] - this->Padding - (double)i*size[1] - 0.5*size[1]; + this->TextActor[i]->SetPosition(posX,posY); + this->TextMapper[i]->GetTextProperty()->SetFontSize(fontSize); + this->TextActor[i]->GetProperty()->DeepCopy(this->GetProperty()); + this->Colors->GetTuple(i, color); + if ( color[0] >= 0.0 && color[1] >= 0.0 && color[2] >= 0.0 ) + { + this->TextMapper[i]->GetTextProperty()->SetColor(color[0], + color[1], + color[2]); + } + } + + //Place symbols + // + //Find the x-y bounds of the symbols...we'll be scaling these as well + size[0] = (int)(symbolSize*(p2[0] - p1[0] - 2.0*this->Padding)); + posX = p1[0] + this->Padding + + 0.5*symbolSize*(p2[0] - p1[0] - 2.0*this->Padding); + for (i=0; iNumberOfEntries; i++) + { + if ( this->Symbol[i] ) + { + this->SymbolTransform[i]->SetInput(this->Symbol[i]); + bounds = this->Symbol[i]->GetBounds(); + + if ( (bounds[1]-bounds[0]) == 0.0 ) + { + sf = VTK_DOUBLE_MAX; + } + else + { + sf = size[0]/(bounds[1]-bounds[0]); + } + + if ( (bounds[3]-bounds[2]) == 0.0 ) + { + if ( sf >= VTK_DOUBLE_MAX ) + { + sf = 1.0; + } + } + else if ( (size[1]/(bounds[3]-bounds[2])) < sf ) + { + sf = size[1]/(bounds[3]-bounds[2]); + } + + posY = p2[1] - this->Padding - (double)i*size[1] - 0.5*size[1] - + 0.25*tempi[1]; + this->Transform[i]->Identity(); + this->Transform[i]->Translate(posX, posY, 0.0); + this->Transform[i]->Scale(0.5*sf, 0.5*sf, 1); + this->SymbolMapper[i]->SetScalarVisibility(this->ScalarVisibility); + this->SymbolActor[i]->GetProperty()->DeepCopy(this->GetProperty()); + this->Colors->GetTuple(i, color); + if ( color[0] >= 0.0 && color[1] >= 0.0 && color[2] >= 0.0 ) + { + this->SymbolActor[i]->GetProperty()->SetColor(color[0], + color[1], + color[2]); + } + }//if symbol defined + }//for all entries + + this->BuildTime.Modified(); + }//rebuild legend box + + //Okay, now we're ready to render something + //Border + int renderedSomething = 0; + if ( this->Border ) + { + renderedSomething += this->BorderActor->RenderOpaqueGeometry(viewport); + } + + if ( this->Box ) + { + renderedSomething += this->BoxActor->RenderOpaqueGeometry(viewport); + } + + if ( this->LegendEntriesVisible ) + { + for (i=0; iNumberOfEntries; i++) + { + if ( this->Symbol[i] ) + { + renderedSomething += this->SymbolActor[i]->RenderOpaqueGeometry(viewport); + } + renderedSomething += this->TextActor[i]->RenderOpaqueGeometry(viewport); + } + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->EntryTextProperty) + { + os << indent << "Entry Text Property:\n"; + this->EntryTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Entry Text Property: (none)\n"; + } + + os << indent << "Number Of Entries: " << this->NumberOfEntries << "\n"; + + os << indent << "Scalar Visibility: " + << (this->ScalarVisibility ? "On\n" : "Off\n"); + os << indent << "Padding: " << this->Padding << "\n"; + os << indent << "Border: " << (this->Border ? "On\n" : "Off\n"); + os << indent << "Box: " << (this->Box ? "On\n" : "Off\n"); + os << indent << "LockBorder: " << (this->LockBorder ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +void vtkLegendBoxActor::ShallowCopy(vtkProp *prop) +{ + vtkLegendBoxActor *a = vtkLegendBoxActor::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetPosition2(a->GetPosition2()); + this->SetEntryTextProperty(a->GetEntryTextProperty()); + this->SetBorder(a->GetBorder()); + this->SetLockBorder(a->GetLockBorder()); + this->SetPadding(a->GetPadding()); + this->SetScalarVisibility(a->GetScalarVisibility()); + this->SetNumberOfEntries(a->GetNumberOfEntries()); + for (int i=0; iNumberOfEntries; i++) + { + this->SetEntrySymbol(i,a->GetEntrySymbol(i)); + this->SetEntryString(i,a->GetEntryString(i)); + this->SetEntryColor(i,a->GetEntryColor(i)); + } + } + + // Now do superclass + this->vtkActor2D::ShallowCopy(prop); +} diff --git a/Hybrid/vtkLegendBoxActor.h b/Hybrid/vtkLegendBoxActor.h new file mode 100644 index 0000000..0993d7a --- /dev/null +++ b/Hybrid/vtkLegendBoxActor.h @@ -0,0 +1,202 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLegendBoxActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLegendBoxActor - draw symbols with text +// .SECTION Description +// vtkLegendBoxActor is used to associate a symbol with a text string. +// The user specifies a vtkPolyData to use as the symbol, and a string +// associated with the symbol. The actor can then be placed in the scene +// in the same way that any other vtkActor2D can be used. +// +// To use this class, you must define the position of the legend box by using +// the superclasses' vtkActor2D::Position coordinate and +// Position2 coordinate. Then define the set of symbols and text strings that +// make up the menu box. The font attributes of the entries can be set through +// the vtkTextProperty associated to this actor. The class will +// scale the symbols and text to fit in the legend box defined by +// (Position,Position2). Optional features like turning on a border line and +// setting the spacing between the border and the symbols/text can also be +// set. + +// .SECTION See Also +// vtkXYPlotActor vtkActor2D vtkGlyphSource2D + +#ifndef __vtkLegendBoxActor_h +#define __vtkLegendBoxActor_h + +#include "vtkActor2D.h" + +class vtkActor; +class vtkDoubleArray; +class vtkPolyData; +class vtkPolyDataMapper2D; +class vtkPolyDataMapper; +class vtkTextMapper; +class vtkTextProperty; +class vtkTransform; +class vtkTransformPolyDataFilter; +class vtkProperty2D; + +class VTK_HYBRID_EXPORT vtkLegendBoxActor : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkLegendBoxActor,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with a rectangle in normaled view coordinates + // of (0.2,0.85, 0.8, 0.95). + static vtkLegendBoxActor *New(); + + // Description: + // Specify the number of entries in the legend box. + void SetNumberOfEntries(int num); + int GetNumberOfEntries() + {return this->NumberOfEntries;} + + // Description: + // Add an entry to the legend box. You must supply a vtkPolyData to be + // used as a symbol (it can be NULL) and a text string (which also can + // be NULL). The vtkPolyData is assumed to be defined in the x-y plane, + // and the text is assumed to be a single line in height. Note that when + // this method is invoked previous entries are deleted. Also supply a text + // string and optionally a color. (If a color is not specified, then the + // entry color is the same as this actor's color.) (Note: use the set + // methods when you use SetNumberOfEntries().) + void SetEntry(int i, vtkPolyData *symbol, const char* string, double color[3]); + void SetEntrySymbol(int i, vtkPolyData *symbol); + void SetEntryString(int i, const char* string); + void SetEntryColor(int i, double color[3]); + void SetEntryColor(int i, double r, double g, double b); + vtkPolyData *GetEntrySymbol(int i); + const char* GetEntryString(int i); + double *GetEntryColor(int i); + + // Description: + // Set/Get the text property. + virtual void SetEntryTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(EntryTextProperty,vtkTextProperty); + + // Description: + // Set/Get the flag that controls whether a border will be drawn + // around the legend box. + vtkSetMacro(Border, int); + vtkGetMacro(Border, int); + vtkBooleanMacro(Border, int); + + // Description: + // Set/Get the flag that controls whether the border and legend + // placement is locked into the rectangle defined by (Position,Position2). + // If off, then the legend box will adjust its size so that the border + // fits nicely around the text and symbols. (The ivar is off by default.) + // Note: the legend box is guaranteed to lie within the original border + // definition. + vtkSetMacro(LockBorder, int); + vtkGetMacro(LockBorder, int); + vtkBooleanMacro(LockBorder, int); + + // Description: + // Set/Get the flag that controls whether a box will be drawn/filled + // corresponding to the legend box. + vtkSetMacro(Box, int); + vtkGetMacro(Box, int); + vtkBooleanMacro(Box, int); + + // Description: + // Get the box vtkProperty2D. + vtkProperty2D* GetBoxProperty() { return this->BoxActor->GetProperty(); }; + + // Description: + // Set/Get the padding between the legend entries and the border. The value + // is specified in pixels. + vtkSetClampMacro(Padding, int, 0, 50); + vtkGetMacro(Padding, int); + + // Description: + // Turn on/off flag to control whether the symbol's scalar data + // is used to color the symbol. If off, the color of the + // vtkLegendBoxActor is used. + vtkSetMacro(ScalarVisibility,int); + vtkGetMacro(ScalarVisibility,int); + vtkBooleanMacro(ScalarVisibility,int); + + // Description: + // Shallow copy of this scaled text actor. Overloads the virtual + // vtkProp method. + void ShallowCopy(vtkProp *prop); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Draw the legend box to the screen. + int RenderOpaqueGeometry(vtkViewport* viewport); + int RenderTranslucentGeometry(vtkViewport* ) {return 0;}; + int RenderOverlay(vtkViewport* viewport); +//ETX + +protected: + vtkLegendBoxActor(); + ~vtkLegendBoxActor(); + + void InitializeEntries(); + + + int Border; + int Box; + int Padding; + int LockBorder; + int ScalarVisibility; + double BoxOpacity; + + // Internal actors, mappers, data to represent the legend + int NumberOfEntries; + int Size; //allocation size + vtkDoubleArray *Colors; + vtkTextMapper **TextMapper; + vtkActor2D **TextActor; + vtkPolyData **Symbol; + vtkTransform **Transform; + vtkTransformPolyDataFilter **SymbolTransform; + vtkPolyDataMapper2D **SymbolMapper; + vtkActor2D **SymbolActor; + vtkPolyData *BorderPolyData; + vtkPolyDataMapper2D *BorderMapper; + vtkActor2D *BorderActor; + vtkPolyData *BoxPolyData; + vtkPolyDataMapper2D *BoxMapper; + vtkActor2D *BoxActor; + vtkTextProperty *EntryTextProperty; + + // Used to control whether the stuff is recomputed + int LegendEntriesVisible; + int CachedSize[2]; + vtkTimeStamp BuildTime; + +private: + vtkLegendBoxActor(const vtkLegendBoxActor&); // Not implemented. + void operator=(const vtkLegendBoxActor&); // Not implemented. +}; + + +#endif + diff --git a/Hybrid/vtkMILVideoSource.cxx b/Hybrid/vtkMILVideoSource.cxx new file mode 100644 index 0000000..4e949c2 --- /dev/null +++ b/Hybrid/vtkMILVideoSource.cxx @@ -0,0 +1,1195 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMILVideoSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMILVideoSource.h" +#include "vtkTimerLog.h" +#include "vtkObjectFactory.h" +#include "vtkCriticalSection.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkMILVideoSource, "$Revision: 1.22.26.2 $"); +vtkStandardNewMacro(vtkMILVideoSource); + +//---------------------------------------------------------------------------- +vtkMILVideoSource::vtkMILVideoSource() +{ + this->Initialized = 0; + + this->FatalMILError = 0; + + this->ContrastLevel = 1.0; + this->BrightnessLevel = 128; + this->HueLevel = 0.0; + this->SaturationLevel = 1.0; + this->BlackLevel = 0.0; + this->WhiteLevel = 255.0; + + this->VideoChannel = 0; + this->VideoInput = VTK_MIL_MONO; + this->VideoInputForColor = VTK_MIL_YC; + this->VideoFormat = VTK_MIL_RS170; + + this->FrameMaxSize[0] = 640; + this->FrameMaxSize[1] = 480; + + this->OldHookFunction = 0; + this->OldUserDataPtr = 0; + + this->MILAppID = 0; + this->MILSysID = 0; + this->MILDigID = 0; + this->MILBufID = 0; + //this->MILDispBufID = 0; + //this->MILDispID = 0; + + this->MILAppInternallyAllocated = 0; + this->MILSysInternallyAllocated = 0; + + this->MILSystemType = VTK_MIL_DEFAULT; + this->MILSystemNumber = M_DEFAULT; + + this->MILDigitizerNumber = M_DEFAULT; + this->MILDigitizerDCF = NULL; + + this->MILErrorMessages = 1; + + this->FlipFrames = 1; //apply vertical flip to each frame + + // for accurate timing + this->LastTimeStamp = 0; + this->LastFrameCount = 0; + this->EstimatedFramePeriod = 0.033; + this->NextFramePeriod = 0.033; +} + +//---------------------------------------------------------------------------- +vtkMILVideoSource::~vtkMILVideoSource() +{ + this->vtkMILVideoSource::ReleaseSystemResources(); + + if (this->MILDigitizerDCF != NULL) + { + delete [] this->MILDigitizerDCF; + this->MILDigitizerDCF = NULL; + } + + this->SetMILSystemType(0); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "VideoChannel: " << this->VideoChannel << "\n"; + + os << indent << "ContrastLevel: " << this->ContrastLevel << "\n"; + + os << indent << "BrightnessLevel: " << this->BrightnessLevel << "\n"; + + os << indent << "HueLevel: " << this->HueLevel << "\n"; + + os << indent << "SaturationLevel: " << this->SaturationLevel << "\n"; + + os << indent << "BlackLevel: " << this->BlackLevel << "\n"; + + os << indent << "WhiteLevel: " << this->WhiteLevel << "\n"; + + os << indent << "VideoInput: "; + switch (this->VideoInput) + { + case VTK_MIL_MONO: + os << "Mono\n"; + break; + case VTK_MIL_COMPOSITE: + os << "Mono\n"; + break; + case VTK_MIL_YC: + os << "Mono\n"; + break; + case VTK_MIL_RGB: + os << "Mono\n"; + break; + case VTK_MIL_DIGITAL: + os << "Mono\n"; + break; + default: + os << "Unrecognized\n"; + break; + } + + os << indent << "VideoFormat: "; + switch (this->VideoFormat) + { + case VTK_MIL_RS170: + os << "RS170\n"; + break; + case VTK_MIL_NTSC: + os << "NTSC\n"; + break; + case VTK_MIL_CCIR: + os << "CCIR\n"; + break; + case VTK_MIL_PAL: + os << "PAL\n"; + break; + case VTK_MIL_SECAM: + os << "SECAM\n"; + break; + default: + os << "Unrecognized\n"; + break; + } + + os << indent << "MILSystemType: " << + (this->MILSystemType ? this->MILSystemType : "Default") << "\n"; + + os << indent << "MILSystemNumber: " << this->MILSystemNumber << "\n"; + + os << indent << "MILDigitizerDCF: " << (this->MILDigitizerDCF ? + this->MILDigitizerDCF : "NULL") << "\n"; + + os << indent << "MILDigitizerNumber: " << this->MILDigitizerNumber << "\n"; + + os << indent << "MILErrorMessages: " << (this->MILErrorMessages ? "On\n" : "Off\n"); + + os << indent << "MILAppID: " << this->MILAppID << "\n"; + os << indent << "MILSysID: " << this->MILSysID << "\n"; + os << indent << "MILDigID: " << this->MILDigID << "\n"; + os << indent << "MILBufID: " << this->MILBufID << "\n"; + // os << indent << "MILDispBufID: " << this->MILDispBufID << "\n"; + // os << indent << "MILDispID: " << this->MILDispID << "\n"; +} + +//---------------------------------------------------------------------------- +// load the DLL for the specified Matrox digitizer, for MIL 5 and MIL 6 +char *vtkMILVideoSource::MILInterpreterForSystem(const char *system) +{ + char *dll_name; + char *func_name; + + if (strcmp(system,VTK_MIL_CORONA) == 0) + { + dll_name = "milcor"; + func_name = "MDCoronaCommandDecoder"; + } + else if (strcmp(system,VTK_MIL_METEOR) == 0) + { + dll_name = "milmet"; + func_name = "MDMeteorCommandDecoder"; + } + else if (strcmp(system,VTK_MIL_METEOR_II) == 0) + { + dll_name = "milmet2"; + func_name = "MDMeteorIICommandDecoder"; + } + else if (strcmp(system,VTK_MIL_METEOR_II_DIG) == 0) + { + dll_name = "milmet2d"; + func_name = "MDMeteorIIDigCommandDecoder"; + } + else if (strcmp(system,VTK_MIL_PULSAR) == 0) + { + dll_name = "milpul"; + func_name = "MDPulsarCommandDecoder"; + } + else if (strcmp(system,VTK_MIL_GENESIS) == 0) + { + dll_name = "milgen"; + func_name = "MDGenesisCommandDecoder"; + } + else if (strcmp(system,VTK_MIL_ORION) == 0) + { + dll_name = "milorion"; + func_name = "MDOrionCommandDecoder"; + } + else + { + dll_name = "unknown"; + func_name = "unknown"; + } + + // first try mil.dll (for later versions of mil) + this->MILInterpreterDLL = "mil"; + HINSTANCE mil_lib = LoadLibrary("mil"); + if (mil_lib == 0) + { + return NULL; + } + void *proc_address = (void *)GetProcAddress(mil_lib,func_name); + if (proc_address) + { + return proc_address; + } + + // then try the device-specific dll + this->MILInterpreterDLL = dll_name; + mil_lib = LoadLibrary(dll_name); + + if (mil_lib == 0) + { + return NULL; + } + + return (char *)GetProcAddress(mil_lib,func_name); +} + +//---------------------------------------------------------------------------- +static void vtkMILVideoSourceSetChannel(long digID, int channel) +{ + if (digID == 0) + { + return; + } + + int mil_channel = M_DEFAULT; + + switch(channel) + { + case 0: + mil_channel = M_CH0; + break; + case 1: + mil_channel = M_CH1; + break; + case 2: + mil_channel = M_CH2; + break; + case 3: + mil_channel = M_CH3; + break; + } + + MdigChannel(digID,mil_channel); +} + +//---------------------------------------------------------------------------- +static void vtkMILVideoSourceSetLevel(long digID, int ref, float level) +{ + if (digID == 0) + { + return; + } + + long int_level = M_MIN_LEVEL + level*(M_MAX_LEVEL-M_MIN_LEVEL); + + if (int_level < M_MIN_LEVEL) + { + int_level = M_MIN_LEVEL; + } + + if (int_level > M_MAX_LEVEL) + { + int_level = M_MAX_LEVEL; + } + + MdigReference(digID,ref,int_level); +} + +//---------------------------------------------------------------------------- +static void vtkMILVideoSourceSetSize(long digID, int size[3], int maxSize[2]) +{ + if (digID == 0) + { + return; + } + + int shrink_x = maxSize[0]/size[0]; + int shrink_y = maxSize[1]/size[1]; + if (shrink_x < 1) + { + shrink_x = 1; + } + if (shrink_y < 1) + { + shrink_y = 1; + } + + // convert shrink_x, shrink_y to power of 2 + int i; + for (i = 0; shrink_x; i++) + { + shrink_x = shrink_x >> 1; + } + shrink_x = 1 << (i-1); + for (i = 0; shrink_y; i++) + { + shrink_y = shrink_y >> 1; + } + shrink_y = 1 << (i-1); + + MdigControl(digID,M_GRAB_SCALE_X,1.0/shrink_x); + MdigControl(digID,M_GRAB_SCALE_Y,1.0/shrink_y); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::Initialize() +{ + static char *system_types[] = { VTK_MIL_METEOR, VTK_MIL_METEOR_II, + VTK_MIL_METEOR_II_DIG, VTK_MIL_METEOR_II_CL, + VTK_MIL_METEOR_II_1394, VTK_MIL_CORONA_II, + VTK_MIL_CORONA, VTK_MIL_PULSAR, + VTK_MIL_GENESIS, VTK_MIL_GENESIS_PLUS, + VTK_MIL_ORION, VTK_MIL_CRONOS, + VTK_MIL_ODYSSEY, 0 }; + + if (this->Initialized || this->FatalMILError) + { + return; + } + + this->Initialized = 1; + + // update the frame buffer now just in case there is an error + this->UpdateFrameBuffer(); + + if (this->MILAppID == 0) + { + this->MILAppID = MappAlloc(M_DEFAULT,M_NULL); + if (this->MILAppID == 0) + { + this->ReleaseSystemResources(); + vtkErrorMacro(<< "Initialize: couldn't open MIL application\n"); + return; + } + this->MILAppInternallyAllocated = 1; + } + + long version = MappInquire(M_VERSION,M_NULL); + + if (this->MILSysID == 0) + { + char *systemType; + if (this->MILSystemType != VTK_MIL_DEFAULT) + { // asked for a particular system by name + if (version >= 7) + { // try MIL 7 style of allocation + char tmptext[256]; + strncpy(tmptext,"\\\\.\\",4); + strncpy(&tmptext[4],this->MILSystemType,252); + this->MILSysID = MsysAlloc(tmptext,this->MILSystemNumber, + M_DEFAULT,M_NULL); + } + else + { // try MIL 5, MIL 6 which requires loading the appropriate DLL + systemType = this->MILInterpreterForSystem(this->MILSystemType); + if (systemType) + { + this->MILSysID = MsysAlloc(systemType, this->MILSystemNumber, + M_DEFAULT,M_NULL); + } + } + + if (this->MILSysID == 0) + { + this->ReleaseSystemResources(); + vtkErrorMacro(<< "Initialize: couldn't find " << this->MILInterpreterDLL << ".dll\n"); + return; + } + } + else + { // try for any known MIL system + MappControl(M_ERROR,M_PRINT_DISABLE); + int i; + for (i = 0; this->MILSysID == 0 && system_types[i] != 0; i++) + { + if (version >= 7) + { + // try MIL 7 style of allocation + char tmptext[256]; + sprintf(tmptext,"\\\\.\\%s",system_types[i]); + this->MILSysID = MsysAlloc(tmptext,this->MILSystemNumber, + M_DEFAULT,M_NULL); + } + else + { // try MIL 5, MIL 6 which requires loading the appropriate DLL + systemType = this->MILInterpreterForSystem(system_types[i]); + if (systemType) + { + this->MILSysID = MsysAlloc(systemType,this->MILSystemNumber, + M_DEFAULT,M_NULL); + } + } + } + if (system_types[i] == 0) + { + this->ReleaseSystemResources(); + vtkErrorMacro(<< "Initialize: Couldn't find a Matrox frame grabber on the system\n"); + return; + } + MappControl(M_ERROR,M_PRINT_ENABLE); + } + this->MILSysInternallyAllocated = 1; + } + + this->AllocateMILBuffer(); + + this->AllocateMILDigitizer(); + + MappControl(M_ERROR, + ( this->MILErrorMessages ? M_PRINT_ENABLE : M_PRINT_DISABLE )); + + // update frame buffer again to reflect any changes + this->UpdateFrameBuffer(); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::ReleaseSystemResources() +{ + if (this->MILAppID != 0) + { + MappControl(M_ERROR, M_PRINT_DISABLE); + } + if (this->MILDigID) + { + if (this->Recording) + { + MdigHalt(this->MILDigID); + } + MdigGrabWait(this->MILDigID,M_GRAB_END); + this->Recording = 0; + } + /* + if (this->MILDispID != 0) + { + MdispDeselect(this->MILDispID,this->MILDispBufID); + MdispFree(this->MILDispID); + this->MILDispID = 0; + } + if (this->MILDispBufID != 0) + { + MbufFree(this->MILDispBufID); + this->MILDispBufID = 0; + } + */ + if (this->MILBufID != 0) + { + MbufFree(this->MILBufID); + this->MILBufID = 0; + } + if (this->MILDigID != 0) + { + // The MdigFree call never returns if it is called by atexit(), + // and it doesn't seem to hurt anything if it isn't called. + MdigFree(this->MILDigID); + this->MILDigID = 0; + } + if (this->MILSysInternallyAllocated && this->MILSysID != 0) + { + MsysFree(this->MILSysID); + this->MILSysID = 0; + } + if (this->MILAppInternallyAllocated && this->MILAppID != 0) + { + MappFree(this->MILAppID); + this->MILAppID = 0; + } + this->Initialized = 0; + this->FatalMILError = 0; +} + +//---------------------------------------------------------------------------- +long MFTYPE vtkMILVideoSourceHook(long HookType, MIL_ID EventID, void *UserPtr) +{ + vtkMILVideoSource *self = (vtkMILVideoSource *)UserPtr; + + if (HookType == M_GRAB_FRAME_END) + { + double time = 1000; + float rate = self->GetFrameRate(); + int format = self->GetVideoFormat(); + int frame_stride; + if (rate > 0) + { + frame_stride = (int)(30/rate); + if (format == VTK_MIL_CCIR || + format == VTK_MIL_PAL || + format == VTK_MIL_SECAM) + { + frame_stride = (int)(25/rate); + } + } + if ((rate > 0 && ++(self->FrameCounter) >= frame_stride) || + self->ForceGrab) + { + self->InternalGrab(); + self->FrameCounter = 0; + self->ForceGrab = 0; + } + } + if (self->OldHookFunction) + { + return ((MDIGHOOKFCTPTR)self->OldHookFunction)(HookType,EventID, + self->OldUserDataPtr); + } + else + { + return M_NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::InternalGrab() +{ + this->FrameBufferMutex->Lock(); + + if (this->AutoAdvance) + { + this->AdvanceFrameBuffer(1); + if (this->FrameIndex + 1 < this->FrameBufferSize) + { + this->FrameIndex++; + } + } + + int index = this->FrameBufferIndex; + + this->FrameBufferTimeStamps[index] = + this->CreateTimeStampForFrame(this->LastFrameCount + 1); + if (this->FrameCount++ == 0) + { + this->StartTimeStamp = this->FrameBufferTimeStamps[index]; + } + + void *ptr = ((reinterpret_cast( \ + this->FrameBuffer[index]))->GetVoidPointer(0)); + int depth = this->FrameBufferBitsPerPixel/8; + + int offsetX = this->FrameBufferExtent[0]; + int offsetY = this->FrameBufferExtent[2]; + + int sizeX = this->FrameBufferExtent[1] - this->FrameBufferExtent[0] + 1; + int sizeY = this->FrameBufferExtent[3] - this->FrameBufferExtent[2] + 1; + + if (sizeX > 0 && sizeY > 0) + { + if (depth == 1) + { + MbufGet2d(this->MILBufID,offsetX,offsetY,sizeX,sizeY,ptr); + } + else if (depth == 3) + { + MbufGetColor2d(this->MILBufID,M_RGB24+M_PACKED,M_ALL_BAND, + offsetX,offsetY,sizeX,sizeY,ptr); + } + else if (depth == 4) + { + MbufGetColor2d(this->MILBufID,M_RGB32+M_PACKED,M_ALL_BAND, + offsetX,offsetY,sizeX,sizeY,ptr); + } + } + + this->Modified(); + + this->FrameBufferMutex->Unlock(); +} + +//---------------------------------------------------------------------------- +// for accurate timing of the transformation: this solves a differential +// equation that works to smooth out the jitter in the times that +// are returned by vtkTimerLog::GetUniversalTime() i.e. the system clock. +double vtkMILVideoSource::CreateTimeStampForFrame(unsigned long framecount) +{ + double timestamp = vtkTimerLog::GetUniversalTime(); + + double frameperiod = ((timestamp - this->LastTimeStamp)/ + (framecount - this->LastFrameCount)); + double deltaperiod = (frameperiod - this->EstimatedFramePeriod)*0.01; + + this->EstimatedFramePeriod += deltaperiod; + this->LastTimeStamp += ((framecount - this->LastFrameCount)* + this->NextFramePeriod); + this->LastFrameCount = framecount; + + double diffperiod = (timestamp - this->LastTimeStamp); + + if (diffperiod < -0.2 || diffperiod > 0.2) + { // time is off by more than 0.2 seconds: reset the clock + this->EstimatedFramePeriod -= deltaperiod; + this->NextFramePeriod = this->EstimatedFramePeriod; + this->LastTimeStamp = timestamp; + return timestamp; + } + + diffperiod *= 0.1; + double maxdiff = 0.001; + if (diffperiod < -maxdiff) + { + diffperiod = -maxdiff; + } + else if (diffperiod > maxdiff) + { + diffperiod = maxdiff; + } + + this->NextFramePeriod = this->EstimatedFramePeriod + diffperiod; + + return this->LastTimeStamp; +} + +//---------------------------------------------------------------------------- +// Circulate the buffer and grab a frame. +// This particular implementation just copies random noise into the frames, +// you will certainly want to override this method (also note that this +// is the only method which you really have to override) +void vtkMILVideoSource::Grab() +{ + // ensure that the hardware is initialized. + this->Initialize(); + if (!this->Initialized) + { + return; + } + + if (!this->Recording) + { + MdigGrab(this->MILDigID,this->MILBufID); + MdigGrabWait(this->MILDigID,M_GRAB_END); + this->InternalGrab(); + } + else + { + this->ForceGrab = 1; + } +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::Play() +{ + vtkVideoSource::Play(); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::Record() +{ + this->Initialize(); + if (!this->Initialized) + { + return; + } + + if (this->Playing) + { + this->Stop(); + } + + if (this->Recording) + { + return; + } + + this->Recording = 1; + this->FrameCount = 0; + + MdigInquire(this->MILDigID,M_GRAB_FRAME_END_HANDLER_PTR, + &this->OldHookFunction); + MdigInquire(this->MILDigID,M_GRAB_FRAME_END_HANDLER_USER_PTR, + &this->OldUserDataPtr); + MdigHookFunction(this->MILDigID,M_GRAB_FRAME_END, + &vtkMILVideoSourceHook, + (void *)this); + this->FrameCounter = 0; + this->ForceGrab = 0; + + // for accurate timing + this->LastTimeStamp = vtkTimerLog::GetUniversalTime(); + + // this will call the hook function on every frame + MdigGrabContinuous(this->MILDigID,this->MILBufID); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::Stop() +{ + if (this->Playing) + { + vtkVideoSource::Stop(); + } + + if (!this->Recording) + { + return; + } + + this->Recording = 0; + + MdigHalt(this->MILDigID); + MdigHookFunction(this->MILDigID,M_GRAB_FRAME_END, + (MDIGHOOKFCTPTR)this->OldHookFunction, + this->OldUserDataPtr); + this->OldHookFunction = 0; + MdigGrabWait(this->MILDigID,M_GRAB_END); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetMILErrorMessages(int yesno) +{ + if (this->MILErrorMessages == yesno) + { + return; + } + + this->MILErrorMessages = yesno; + this->Modified(); + + if (this->Initialized) + { + MappControl(M_ERROR,( yesno ? M_PRINT_ENABLE : M_PRINT_DISABLE )); + } +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetFrameSize(int x, int y, int z) +{ + if (x == this->FrameSize[0] && + y == this->FrameSize[1] && + z == this->FrameSize[2]) + { + return; + } + + if (x < 1 || y < 1 || z != 1) + { + vtkErrorMacro(<< "SetFrameSize: Illegal frame size"); + return; + } + + this->FrameSize[0] = x; + this->FrameSize[1] = y; + this->FrameSize[2] = z; + + if (this->Initialized) + { + this->FrameBufferMutex->Lock(); + this->UpdateFrameBuffer(); + vtkMILVideoSourceSetSize(this->MILDigID, + this->FrameSize,this->FrameMaxSize); + this->AllocateMILBuffer(); + this->FrameBufferMutex->Unlock(); + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetOutputFormat(int format) +{ + if (format == this->OutputFormat) + { + return; + } + + this->OutputFormat = format; + + // convert color format to number of scalar components + int numComponents; + + switch (this->OutputFormat) + { + case VTK_RGBA: + numComponents = 4; + break; + case VTK_RGB: + numComponents = 3; + break; + case VTK_LUMINANCE: + numComponents = 1; + break; + default: + vtkErrorMacro(<< "SetOutputFormat: Unrecognized color format."); + break; + } + this->NumberOfScalarComponents = numComponents; + + if (this->FrameBufferBitsPerPixel != numComponents*8) + { + this->FrameBufferMutex->Lock(); + this->FrameBufferBitsPerPixel = numComponents*8; + if (this->Initialized) + { + this->UpdateFrameBuffer(); + this->AllocateMILBuffer(); + } + this->FrameBufferMutex->Unlock(); + } + + // set video format to match the output format + if (this->OutputFormat == VTK_RGB || this->OutputFormat == VTK_RGBA) + { + if (this->VideoFormat == VTK_MIL_RS170) + { + this->SetVideoFormat(VTK_MIL_NTSC); + } + if (this->VideoFormat == VTK_MIL_CCIR) + { + this->SetVideoFormat(VTK_MIL_PAL); + } + if (this->VideoInput == VTK_MIL_MONO) + { + this->SetVideoInput(this->VideoInputForColor); + } + } + if (this->OutputFormat == VTK_LUMINANCE) + { + if (this->VideoFormat == VTK_MIL_NTSC) + { + this->SetVideoFormat(VTK_MIL_RS170); + } + if (this->VideoFormat == VTK_MIL_PAL) + { + this->SetVideoFormat(VTK_MIL_CCIR); + } + if (this->VideoInput == VTK_MIL_YC || this->VideoInput == VTK_MIL_COMPOSITE) + { + this->VideoInputForColor = this->VideoInput; + this->SetVideoInput(VTK_MIL_MONO); + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetVideoFormat(int format) +{ + if (this->VideoFormat == format) + { + return; + } + + this->VideoFormat = format; + + // don't do anything if the digitizer isn't initialized + if (this->Initialized) + { + this->AllocateMILDigitizer(); + } +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetVideoInput(int input) +{ + if (this->VideoInput == input) + { + return; + } + + this->VideoInput = input; + + // don't do anything if the digitizer isn't initialized + if (this->Initialized) + { + this->AllocateMILDigitizer(); + } +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetVideoChannel(int channel) +{ + if (this->VideoChannel == channel) + { + return; + } + + this->VideoChannel = channel; + this->Modified(); + + vtkMILVideoSourceSetChannel(this->MILDigID,channel); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetBrightnessLevel(float brightness) +{ + if (this->BrightnessLevel == brightness) + { + return; + } + + this->BrightnessLevel = brightness; + this->Modified(); + + vtkMILVideoSourceSetLevel(this->MILDigID,M_BRIGHTNESS_REF,brightness/255.0); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetContrastLevel(float contrast) +{ + if (this->ContrastLevel == contrast) + { + return; + } + + this->ContrastLevel = contrast; + this->Modified(); + + vtkMILVideoSourceSetLevel(this->MILDigID,M_CONTRAST_REF,contrast/2.0); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetHueLevel(float hue) +{ + if (this->HueLevel == hue) + { + return; + } + + this->HueLevel = hue; + this->Modified(); + + vtkMILVideoSourceSetLevel(this->MILDigID,M_HUE_REF,0.5+hue); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetSaturationLevel(float saturation) +{ + if (this->SaturationLevel == saturation) + { + return; + } + + this->SaturationLevel = saturation; + this->Modified(); + + vtkMILVideoSourceSetLevel(this->MILDigID,M_SATURATION_REF,saturation/2.0); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetBlackLevel(float black) +{ + if (this->BlackLevel == black) + { + return; + } + + this->BlackLevel = black; + this->Modified(); + + vtkMILVideoSourceSetLevel(this->MILDigID,M_BLACK_REF,black/255); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::SetWhiteLevel(float white) +{ + if (this->WhiteLevel == white) + { + return; + } + + this->WhiteLevel = white; + this->Modified(); + + vtkMILVideoSourceSetLevel(this->MILDigID,M_WHITE_REF,white/255); +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::AllocateMILDigitizer() +{ + char *format = "M_NTSC"; + int recording = this->Recording; + + if (this->MILDigID) + { + if (recording) + { + this->Stop(); + } + } + + if (this->MILDigID != 0) + { + MdigFree(this->MILDigID); + } + + switch (this->VideoFormat) + { + case VTK_MIL_RS170: + format = "M_RS170"; + if (this->VideoInput == VTK_MIL_RGB) + { + format = "M_RS170_VIA_RGB"; + } + break; + case VTK_MIL_NTSC: + format = "M_NTSC"; + if (this->VideoInput == VTK_MIL_YC) + { + format = "M_NTSC_YC"; + } + if (this->VideoInput == VTK_MIL_RGB) + { + format = "M_NTSC_RGB"; + } + break; + case VTK_MIL_CCIR: + format = "M_CCIR"; + if (this->VideoInput == VTK_MIL_RGB) + { + format = "M_CCIR_VIA_RGB"; + } + this->FrameMaxSize[0] = 768; + this->FrameMaxSize[1] = 576; + break; + case VTK_MIL_PAL: + case VTK_MIL_SECAM: + format = "M_PAL"; + if (this->VideoInput == VTK_MIL_YC) + { + format = "M_PAL_YC"; + } + if (this->VideoInput == VTK_MIL_RGB) + { + format = "M_PAL_RGB"; + } + this->FrameMaxSize[0] = 768; + this->FrameMaxSize[1] = 576; + break; + case VTK_MIL_NONSTANDARD: + this->FrameMaxSize[0] = 0; + this->FrameMaxSize[1] = 0; + break; + default: + vtkWarningMacro(<< "AllocateMILDigitizer: Unknown video format"); + } + + if (this->MILDigitizerDCF) + { + format = this->MILDigitizerDCF; + } + + this->MILDigID = MdigAlloc(this->MILSysID,this->MILDigitizerNumber,format, + M_DEFAULT,M_NULL); + + if (this->MILDigID == 0) + { + vtkErrorMacro(<< "AllocateMILDigitizer: Couldn't allocate MIL Digitizer\n"); + return; + } + + vtkMILVideoSourceSetSize(this->MILDigID,this->FrameSize,this->FrameMaxSize); + + vtkMILVideoSourceSetChannel(this->MILDigID,this->VideoChannel); + + if (this->BrightnessLevel != 128) + { + vtkMILVideoSourceSetLevel(this->MILDigID,M_BRIGHTNESS_REF, + this->BrightnessLevel/255); + } + if (this->ContrastLevel != 1.0) + { + vtkMILVideoSourceSetLevel(this->MILDigID,M_CONTRAST_REF, + this->ContrastLevel/2.0); + } + if (this->HueLevel != 0.0) + { + vtkMILVideoSourceSetLevel(this->MILDigID,M_HUE_REF, + 0.5+this->HueLevel); + } + if (this->SaturationLevel != 1.0) + { + vtkMILVideoSourceSetLevel(this->MILDigID,M_SATURATION_REF, + this->SaturationLevel/2.0); + } + if (this->BlackLevel != 0.0) + { + vtkMILVideoSourceSetLevel(this->MILDigID,M_BLACK_REF, + this->BlackLevel/255); + } + if (this->WhiteLevel != 255.0) + { + vtkMILVideoSourceSetLevel(this->MILDigID,M_WHITE_REF, + this->WhiteLevel/255); + } + + if (this->MILDigID && this->MILBufID) + { + if (recording) + { + this->Record(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkMILVideoSource::AllocateMILBuffer() +{ + int recording = this->Recording; + + if (this->MILDigID != 0) + { + if (recording) + { + this->Stop(); + } + } + + if (this->MILBufID != 0) + { + MbufFree(this->MILBufID); + } + + if (this->OutputFormat != VTK_LUMINANCE && + this->OutputFormat != VTK_RGB && + this->OutputFormat != VTK_RGBA) + { + vtkWarningMacro(<< "Initialize: unsupported OutputFormat"); + this->vtkVideoSource::SetOutputFormat(VTK_LUMINANCE); + } + + if (this->OutputFormat == VTK_LUMINANCE) + { + this->MILBufID = MbufAlloc2d(this->MILSysID,this->FrameSize[0], + this->FrameSize[1], + 8+M_UNSIGNED,M_IMAGE+M_GRAB,M_NULL); + } + else if (this->OutputFormat == VTK_RGB) + { + this->MILBufID = MbufAllocColor(this->MILSysID,3,this->FrameSize[0], + this->FrameSize[1], + 8+M_UNSIGNED,M_IMAGE+M_GRAB+ \ + M_RGB24+M_PACKED, + M_NULL); + } + else if (this->OutputFormat == VTK_RGBA) + { + this->MILBufID = MbufAllocColor(this->MILSysID,3,this->FrameSize[0], + this->FrameSize[1], + 8+M_UNSIGNED,M_IMAGE+M_GRAB+M_RGB32+ \ + M_PACKED, + M_NULL); + } + + if (this->MILBufID == 0) + { + vtkErrorMacro(<< "AllocateMILBuffer: Couldn't allocate MIL Buffer\n"); + return; + } + + if (this->MILDigID != 0 && this->MILBufID != 0) + { + if (recording) + { + this->Record(); + } + } +} + + + diff --git a/Hybrid/vtkMILVideoSource.h b/Hybrid/vtkMILVideoSource.h new file mode 100644 index 0000000..452dba6 --- /dev/null +++ b/Hybrid/vtkMILVideoSource.h @@ -0,0 +1,276 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMILVideoSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMILVideoSource - Matrox Imaging Library frame grabbers +// .SECTION Description +// vtkMILVideoSource provides an interface to Matrox Meteor, MeteorII +// and Corona video digitizers through the Matrox Imaging Library +// interface. In order to use this class, you must link VTK with mil.lib, +// MIL version 5.0 or higher is required. +// .SECTION Caveats +// With some capture cards, if this class is leaked and ReleaseSystemResources +// is not called, you may have to reboot before you can capture again. +// vtkVideoSource used to keep a global list and delete the video sources +// if your program leaked, due to exit crashes that was removed. +// .SECTION See Also +// vtkWin32VideoSource vtkVideoSource + +#ifndef __vtkMILVideoSource_h +#define __vtkMILVideoSource_h + +#include "vtkVideoSource.h" + +// digitizer hardware +#define VTK_MIL_DEFAULT 0 +#define VTK_MIL_METEOR "M_SYSTEM_METEOR" +#define VTK_MIL_METEOR_II "M_SYSTEM_METEOR_II" +#define VTK_MIL_METEOR_II_DIG "M_SYSTEM_METEOR_II_DIG" +#define VTK_MIL_METEOR_II_CL "M_SYSTEM_METEOR_II_CL" +#define VTK_MIL_METEOR_II_1394 "M_SYSTEM_METEOR_II_1394" +#define VTK_MIL_CORONA "M_SYSTEM_CORONA" +#define VTK_MIL_CORONA_II "M_SYSTEM_CORONA_II" +#define VTK_MIL_PULSAR "M_SYSTEM_PULSAR" +#define VTK_MIL_GENESIS "M_SYSTEM_GENESIS" +#define VTK_MIL_GENESIS_PLUS "M_SYSTEM_GENESIS_PLUS" +#define VTK_MIL_ORION "M_SYSTEM_ORION" +#define VTK_MIL_CRONOS "M_SYSTEM_CRONOS" +#define VTK_MIL_ODYSSEY "M_SYSTEM_ODYSSEY" + +// video inputs: +#define VTK_MIL_MONO 0 +#define VTK_MIL_COMPOSITE 1 +#define VTK_MIL_YC 2 +#define VTK_MIL_RGB 3 +#define VTK_MIL_DIGITAL 4 + +// video formats: +#define VTK_MIL_RS170 0 +#define VTK_MIL_NTSC 1 +#define VTK_MIL_CCIR 2 +#define VTK_MIL_PAL 3 +#define VTK_MIL_SECAM 4 +#define VTK_MIL_NONSTANDARD 5 + +class VTK_HYBRID_EXPORT vtkMILVideoSource : public vtkVideoSource +{ +public: + static vtkMILVideoSource *New(); + vtkTypeRevisionMacro(vtkMILVideoSource,vtkVideoSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Standard VCR functionality: Record incoming video. + void Record(); + + // Description: + // Standard VCR functionality: Play recorded video. + void Play(); + + // Description: + // Standard VCR functionality: Stop recording or playing. + void Stop(); + + // Description: + // Grab a single video frame. + void Grab(); + + // Description: + // Request a particular frame size (set the third value to 1). + void SetFrameSize(int x, int y, int z); + + // Description: + // Request a particular output format (default: VTK_RGB). + void SetOutputFormat(int format); + + // Description: + // Set/Get the video channel + virtual void SetVideoChannel(int channel); + vtkGetMacro(VideoChannel, int); + + // Description: + // Set/Get the video format + virtual void SetVideoFormat(int format); + void SetVideoFormatToNTSC() { this->SetVideoFormat(VTK_MIL_NTSC); }; + void SetVideoFormatToPAL() { this->SetVideoFormat(VTK_MIL_PAL); }; + void SetVideoFormatToSECAM() { this->SetVideoFormat(VTK_MIL_SECAM); }; + void SetVideoFormatToRS170() { this->SetVideoFormat(VTK_MIL_RS170); }; + void SetVideoFormatToCCIR() { this->SetVideoFormat(VTK_MIL_CCIR); }; + void SetVideoFormatToNonStandard() { + this->SetVideoFormat(VTK_MIL_NONSTANDARD); }; + vtkGetMacro(VideoFormat,int); + + // Description: + // Set/Get the video input + virtual void SetVideoInput(int input); + void SetVideoInputToMono() { this->SetVideoInput(VTK_MIL_MONO); }; + void SetVideoInputToComposite() {this->SetVideoInput(VTK_MIL_COMPOSITE);}; + void SetVideoInputToYC() { this->SetVideoInput(VTK_MIL_YC); }; + void SetVideoInputToRGB() { this->SetVideoInput(VTK_MIL_RGB); }; + void SetVideoInputToDigital() { this->SetVideoInput(VTK_MIL_DIGITAL); }; + vtkGetMacro(VideoInput,int); + + // Description: + // Set/Get the video levels for composite/SVideo: the valid ranges are: + // Contrast [0.0,2.0] + // Brighness [0.0,255.0] + // Hue [-0.5,0.5] + // Saturation [0.0,2.0] + virtual void SetContrastLevel(float contrast); + vtkGetMacro(ContrastLevel,float); + virtual void SetBrightnessLevel(float brightness); + vtkGetMacro(BrightnessLevel,float); + virtual void SetHueLevel(float hue); + vtkGetMacro(HueLevel,float); + virtual void SetSaturationLevel(float saturation); + vtkGetMacro(SaturationLevel,float); + + // Description: + // Set/Get the video levels for monochrome/RGB: valid values are + // between 0.0 and 255.0. + virtual void SetBlackLevel(float value); + virtual float GetBlackLevel() { + return this->BlackLevel; }; + virtual void SetWhiteLevel(float value); + virtual float GetWhiteLevel() { + return this->WhiteLevel; }; + + // Description: + // Set the system which you want use. If you don't specify a system, + // then your primary digitizer will be autodetected. + vtkSetStringMacro(MILSystemType); + vtkGetStringMacro(MILSystemType); + void SetMILSystemTypeToMeteor() { this->SetMILSystemType(VTK_MIL_METEOR); }; + void SetMILSystemTypeToMeteorII() { this->SetMILSystemType(VTK_MIL_METEOR_II); }; + void SetMILSystemTypeToMeteorIIDig() { this->SetMILSystemType(VTK_MIL_METEOR_II_DIG); }; + void SetMILSystemTypeToMeteorIICL() { this->SetMILSystemType(VTK_MIL_METEOR_II_CL); }; + void SetMILSystemTypeToMeteorII1394() { this->SetMILSystemType(VTK_MIL_METEOR_II_1394); }; + void SetMILSystemTypeToCorona() { this->SetMILSystemType(VTK_MIL_CORONA); }; + void SetMILSystemTypeToCoronaII() { this->SetMILSystemType(VTK_MIL_CORONA_II); }; + void SetMILSystemTypeToPulsar() { this->SetMILSystemType(VTK_MIL_PULSAR); }; + void SetMILSystemTypeToGenesis() { this->SetMILSystemType(VTK_MIL_GENESIS); }; + void SetMILSystemTypeToGenesisPlus() { this->SetMILSystemType(VTK_MIL_GENESIS_PLUS); }; + void SetMILSystemTypeToOrion() { this->SetMILSystemType(VTK_MIL_ORION); }; + void SetMILSystemTypeToCronos() { this->SetMILSystemType(VTK_MIL_CRONOS); }; + void SetMILSystemTypeToOdyssey() { this->SetMILSystemType(VTK_MIL_ODYSSEY); }; + // Description: + // Set the system number if you have multiple systems of the same type + vtkSetMacro(MILSystemNumber,int); + vtkGetMacro(MILSystemNumber,int); + + // Description: + // Set the DCF filename for non-standard video formats + vtkSetStringMacro(MILDigitizerDCF); + vtkGetStringMacro(MILDigitizerDCF); + + // Description: + // Set the digitizer number for systems with multiple digitizers + vtkSetMacro(MILDigitizerNumber,int); + vtkGetMacro(MILDigitizerNumber,int); + + // Description: + // Set whether to display MIL error messages (default on) + virtual void SetMILErrorMessages(int yesno); + vtkBooleanMacro(MILErrorMessages,int); + vtkGetMacro(MILErrorMessages,int); + + // Description: + // Allows fine-grained control + vtkSetMacro(MILAppID,long); + vtkGetMacro(MILAppID,long); + vtkSetMacro(MILSysID,long); + vtkGetMacro(MILSysID,long); + vtkGetMacro(MILDigID,long); + vtkGetMacro(MILBufID,long); + + // Description: + // Initialize the driver (this is called automatically when the + // first grab is done). + void Initialize(); + + // Description: + // Free the driver (this is called automatically inside the + // destructor). + void ReleaseSystemResources(); + + // Description: + // For internal use only + void *OldHookFunction; + void *OldUserDataPtr; + int FrameCounter; + int ForceGrab; + void InternalGrab(); + +protected: + vtkMILVideoSource(); + ~vtkMILVideoSource(); + + virtual void AllocateMILDigitizer(); + virtual void AllocateMILBuffer(); + + virtual char *MILInterpreterForSystem(const char *system); + char *MILInterpreterDLL; + + int VideoChannel; + int VideoInput; + int VideoInputForColor; + int VideoFormat; + + float ContrastLevel; + float BrightnessLevel; + float HueLevel; + float SaturationLevel; + + float BlackLevel; + float WhiteLevel; + + int FrameMaxSize[2]; + + long MILAppID; + long MILSysID; + long MILDigID; + long MILBufID; + // long MILDispBufID; + // long MILDispID; + + char *MILSystemType; + int MILSystemNumber; + + int MILDigitizerNumber; + char *MILDigitizerDCF; + + int MILErrorMessages; + + int MILAppInternallyAllocated; + int MILSysInternallyAllocated; + + int FatalMILError; + + // Description: + // Method for updating the virtual clock that accurately times the + // arrival of each frame, more accurately than is possible with + // the system clock alone because the virtual clock averages out the + // jitter. + double CreateTimeStampForFrame(unsigned long frame); + + double LastTimeStamp; + unsigned long LastFrameCount; + double EstimatedFramePeriod; + double NextFramePeriod; + +private: + vtkMILVideoSource(const vtkMILVideoSource&); // Not implemented. + void operator=(const vtkMILVideoSource&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkPCAAnalysisFilter.cxx b/Hybrid/vtkPCAAnalysisFilter.cxx new file mode 100644 index 0000000..617efd7 --- /dev/null +++ b/Hybrid/vtkPCAAnalysisFilter.cxx @@ -0,0 +1,499 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPCAAnalysisFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPCAAnalysisFilter.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkTransformPolyDataFilter.h" +#include "vtkPolyData.h" +#include "vtkMath.h" +#include "vtkFloatArray.h" + +vtkCxxRevisionMacro(vtkPCAAnalysisFilter, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkPCAAnalysisFilter); + +//------------------------------------------------------------------------ +// Matrix ops. Some taken from vtkThinPlateSplineTransform.cxx +static inline double** NewMatrix(int rows, int cols) +{ + double *matrix = new double[rows*cols]; + double **m = new double *[rows]; + for(int i = 0; i < rows; i++) { + m[i] = &matrix[i*cols]; + } + return m; +} + +//------------------------------------------------------------------------ +static inline void DeleteMatrix(double **m) +{ + delete [] *m; + delete [] m; +} + +//------------------------------------------------------------------------ +static inline void MatrixMultiply(double **a, double **b, double **c, + int arows, int acols, + int brows, int bcols) +{ + if(acols != brows) { + return; // acols must equal br otherwise we can't proceed + } + + // c must have size arows*bcols (we assume this) + + for(int i = 0; i < arows; i++) { + for(int j = 0; j < bcols; j++) { + c[i][j] = 0.0; + for(int k = 0; k < acols; k++) { + c[i][j] += a[i][k]*b[k][j]; + } + } + } +} + +//------------------------------------------------------------------------ +// Subtracting the mean column from the observation matrix is equal +// to subtracting the mean shape from all shapes. +// The mean column is equal to the Procrustes mean (it is also returned) +static inline void SubtractMeanColumn(double **m, double *mean, int rows, int cols) +{ + int r,c; + double csum; + for (r = 0; r < rows; r++) { + csum = 0.0F; + for (c = 0; c < cols; c++) { + csum += m[r][c]; + } + // calculate average value of row + csum /= cols; + + // Mean shape vector is updated + mean[r] = csum; + + // average value is subtracted from all elements in the row + for (c = 0; c < cols; c++) { + m[r][c] -= csum; + } + } +} + +//------------------------------------------------------------------------ +// Normalise all columns to have length 1 +// meaning that all eigenvectors are normalised +static inline void NormaliseColumns(double **m, int rows, int cols) +{ + for (int c = 0; c < cols; c++) { + double cl = 0; + for (int r = 0; r < rows; r++) { + cl += m[r][c] * m[r][c]; + } + cl = sqrt(cl); + + // If cl == 0 something is rotten, dont do anything now + if (cl != 0) { + for (int r = 0; r < rows; r++) { + m[r][c] /= cl; + } + } + } +} + +//------------------------------------------------------------------------ +// Here it is assumed that a rows >> a cols +// Output matrix is [a cols X a cols] +static inline void SmallCovarianceMatrix(double **a, double **c, + int arows, int acols) +{ + const int s = acols; + + // c must have size acols*acols (we assume this) + for(int i = 0; i < acols; i++) { + for(int j = 0; j < acols; j++) { + // Use symmetry + if (i <= j) { + c[i][j] = 0.0; + for(int k = 0; k < arows; k++) { + c[i][j] += a[k][i]*a[k][j]; + } + c[i][j] /= (s-1); + c[j][i] = c[i][j]; + } + } + } +} + +//------------------------------------------------------------------------ +static inline double* NewVector(int length) +{ + double *vec = new double[length]; + return vec; +} + +//------------------------------------------------------------------------ +static inline void DeleteVector(double *v) +{ + delete [] v; +} + + +//---------------------------------------------------------------------------- +// protected +vtkPCAAnalysisFilter::vtkPCAAnalysisFilter() +{ + this->Evals = vtkFloatArray::New(); + this->evecMat2 = NULL; + this->meanshape = NULL; +} + +//---------------------------------------------------------------------------- +// protected +vtkPCAAnalysisFilter::~vtkPCAAnalysisFilter() +{ + if (this->Evals) { + this->Evals->Delete(); + } + if (this->evecMat2) { + DeleteMatrix(this->evecMat2); + this->evecMat2 = NULL; + } + if (this->meanshape) { + DeleteVector(this->meanshape); + this->meanshape = NULL; + } +} + +//---------------------------------------------------------------------------- +// protected +int vtkPCAAnalysisFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Execute()"); + + int i; + + // Clean up from previous computation + if (this->evecMat2) { + DeleteMatrix(this->evecMat2); + this->evecMat2 = NULL; + } + if (this->meanshape) { + DeleteVector(this->meanshape); + this->meanshape = NULL; + } + + const int N_SETS = this->GetNumberOfInputConnections(0); + + vtkInformation *tmpInfo; + vtkPointSet *tmpInput; + // copy the inputs across + output->DeepCopy(input); + for(i=1;iGetInformationObject(i); + tmpInput = 0; + if (tmpInfo) + { + tmpInput = + vtkPointSet::SafeDownCast(tmpInfo->Get(vtkDataObject::DATA_OBJECT())); + } + this->GetOutput(i)->DeepCopy(tmpInput); + } + + // the number of points is determined by the first input (they must all be the same) + const int N_POINTS = input->GetNumberOfPoints(); + + vtkDebugMacro(<<"N_POINTS is " <GetInformationObject(i); + tmpInput = 0; + if (tmpInfo) + { + tmpInput = + vtkPointSet::SafeDownCast(tmpInfo->Get(vtkDataObject::DATA_OBJECT())); + } + else + { + continue; + } + if(tmpInput->GetNumberOfPoints() != N_POINTS) { + vtkErrorMacro(<<"The inputs have different numbers of points!"); + return 1; + } + } + + // Number of shapes + const int s = N_SETS; + + // Number of points in a shape + const int n = N_POINTS; + + // Observation Matrix [number of points * 3 X number of shapes] + double **D = NewMatrix(3*n, s); + + for (i = 0; i < n; i++) + { + for (int j = 0; j < s; j++) + { + tmpInfo = inputVector[0]->GetInformationObject(j); + tmpInput = 0; + if (tmpInfo) + { + tmpInput = vtkPointSet::SafeDownCast( + tmpInfo->Get(vtkDataObject::DATA_OBJECT())); + } + else + { + continue; + } + double p[3]; + tmpInput->GetPoint(i, p); + D[i*3 ][j] = p[0]; + D[i*3+1][j] = p[1]; + D[i*3+2][j] = p[2]; + } + } + + // The mean shape is also calculated + meanshape = NewVector(3*n); + + SubtractMeanColumn(D, meanshape, 3*n, s); + + // Covariance matrix of dim [s x s] + double **T = NewMatrix(s, s); + SmallCovarianceMatrix(D, T, 3*n, s); + + double *ev = NewVector(s); + double **evecMat = NewMatrix(s, s); + + vtkMath::JacobiN(T, s, ev, evecMat); + + // Compute eigenvecs of DD' instead of T which is D'D + // evecMat2 of dim [3*n x s] + evecMat2 = NewMatrix(3*n, s); + MatrixMultiply(D, evecMat, evecMat2, 3*n, s, s, s); + + // Normalise eigenvectors + NormaliseColumns(evecMat2, 3*n, s); + + this->Evals->SetNumberOfValues(s); + + // Copy data to output structures + for (int j = 0; j < s; j++) { + this->Evals->SetValue(j, ev[j]); + + for (i = 0; i < n; i++) { + double x = evecMat2[i*3 ][j]; + double y = evecMat2[i*3+1][j]; + double z = evecMat2[i*3+2][j]; + + this->GetOutput(j)->GetPoints()->SetPoint(i, x, y, z); + } + } + + DeleteMatrix(evecMat); + DeleteVector(ev); + DeleteMatrix(T); + DeleteMatrix(D); + + return 1; +} + + +//---------------------------------------------------------------------------- +// public +void vtkPCAAnalysisFilter::GetParameterisedShape(vtkFloatArray *b, vtkPointSet* shape) +{ + const int bsize = b->GetNumberOfTuples(); + + const int n = this->GetOutput(0)->GetNumberOfPoints(); + + if(shape->GetNumberOfPoints() != n) { + vtkErrorMacro(<<"Input shape does not have the correct number of points"); + return; + } + + double *shapevec = NewVector(n*3); + + int i,j; + + // b is weighted by the eigenvals + // make weigth vector for speed reasons + double *w = NewVector(bsize); + for (i = 0; i < bsize; i++) { + w[i] =sqrt(this->Evals->GetValue(i)) * b->GetValue(i); + } + for (j = 0; j < n*3; j++) { + shapevec[j] = meanshape[j]; + + for (i = 0; i < bsize; i++) { + shapevec[j] += w[i] * evecMat2[j][i]; + } + } + + // Copy shape + for (i = 0; i < n; i++) { + shape->GetPoints()->SetPoint(i,shapevec[i*3 ], shapevec[i*3+1], shapevec[i*3+2]); + } + + DeleteVector(shapevec); + DeleteVector(w); +} + +//---------------------------------------------------------------------------- +// public +void vtkPCAAnalysisFilter::GetShapeParameters(vtkPointSet *shape, vtkFloatArray *b, int bsize) +{ + // Local variant of b for fast access. + double *bloc = NewVector(bsize); + + const int n = this->GetOutput(0)->GetNumberOfPoints(); + int i,j; + + if(shape->GetNumberOfPoints() != n) { + vtkErrorMacro(<<"Input shape does not have the correct number of points"); + return; + } + + double *shapevec = NewVector(n*3); + + // Copy shape and subtract mean shape + for (i = 0; i < n; i++) { + double p[3]; + shape->GetPoint(i, p); + shapevec[i*3 ] = p[0] - meanshape[i*3]; + shapevec[i*3+1] = p[1] - meanshape[i*3+1]; + shapevec[i*3+2] = p[2] - meanshape[i*3+2]; + } + + for (i = 0; i < bsize; i++) { + bloc[i] = 0; + + // Project the shape onto eigenvector i + for (j = 0; j < n*3; j++) { + bloc[i] += shapevec[j] * evecMat2[j][i]; + } + } + + // Return b in number of standard deviations + b->SetNumberOfValues(bsize); + for (i = 0; i < bsize; i++) { + if (this->Evals->GetValue(i)) + b->SetValue(i, bloc[i]/sqrt(this->Evals->GetValue(i))); + else + b->SetValue(i, 0); + } + + DeleteVector(shapevec); + DeleteVector(bloc); +} + +//---------------------------------------------------------------------------- +// public +void vtkPCAAnalysisFilter::SetNumberOfInputs(int n) +{ + this->SetNumberOfInputConnections(0, n); + this->SetNumberOfOutputPorts(n); + + // initialise the outputs + for(int i=0;iSetPoints(points); + points->Delete(); + this->GetExecutive()->SetOutputData(i,ps); + ps->Delete(); + } + + // is this the right thing to be doing here? if we don't initialise the outputs here + // then the filter crashes but vtkPolyData may not be the type of the inputs +} + +//---------------------------------------------------------------------------- +void vtkPCAAnalysisFilter::SetInput(int idx, vtkPointSet *p) +{ + this->SetNthInputConnection(0, idx, p ? p->GetProducerPort() : 0); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkPCAAnalysisFilter::GetInput(int idx) +{ + return vtkPointSet::SafeDownCast( + this->GetExecutive()->GetInputData(0, idx)); +} + +//---------------------------------------------------------------------------- +int vtkPCAAnalysisFilter::FillInputPortInformation(int port, + vtkInformation *info) +{ + int retval = this->Superclass::FillInputPortInformation(port, info); + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return retval; +} + +//---------------------------------------------------------------------------- +// public +void vtkPCAAnalysisFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + this->Evals->PrintSelf(os,indent.GetNextIndent()); +} + +//---------------------------------------------------------------------------- +// public +int vtkPCAAnalysisFilter::GetModesRequiredFor(double proportion) +{ + int i; + + double eigen_total = 0.0F; + for(i=0;iEvals->GetNumberOfTuples();i++) + { + eigen_total += this->Evals->GetValue(i); + } + + double running_total = 0.0F; + for(i=0;iEvals->GetNumberOfTuples();i++) + { + running_total += this->Evals->GetValue(i)/eigen_total; + if(running_total>=proportion) + { + return i+1; + } + } + + return Evals->GetNumberOfTuples(); +} diff --git a/Hybrid/vtkPCAAnalysisFilter.h b/Hybrid/vtkPCAAnalysisFilter.h new file mode 100644 index 0000000..8cf6bfd --- /dev/null +++ b/Hybrid/vtkPCAAnalysisFilter.h @@ -0,0 +1,142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPCAAnalysisFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPCAAnalysisFilter - Performs principal component analysis of a set of aligned pointsets +// .SECTION Description +// +// vtkPCAAnalysisFilter is a filter that takes as input a set of aligned +// pointsets (any object derived from vtkPointSet) and performs +// a principal component analysis of the coordinates. +// This can be used to visualise the major or minor modes of variation +// seen in a set of similar biological objects with corresponding +// landmarks. +// vtkPCAAnalysisFilter is designed to work with the output from +// the vtkProcrustesAnalysisFilter +// +// Call SetNumberOfInputs(n) before calling SetInput(0) ... SetInput(n-1). +// Retrieve the outputs using GetOutput(0) ... GetOutput(n-1). +// +// vtkPCAAnalysisFilter is an implementation of (for example): +// +// T. Cootes et al. : Active Shape Models - their training and application. +// Computer Vision and Image Understanding, 61(1):38-59, 1995. +// +// The material can also be found in Tim Cootes' ever-changing online report +// published at his website: +// http://www.isbe.man.ac.uk/~bim/ +// +// .SECTION Caveats +// All of the input pointsets must have the same number of points. +// +// .SECTION Thanks +// Rasmus Paulsen and Tim Hutton who developed and contributed this class +// +// .SECTION See Also +// vtkProcrustesAlignmentFilter + +#ifndef __vtkPCAAnalysisFilter_h +#define __vtkPCAAnalysisFilter_h + +#include "vtkPointSetAlgorithm.h" + +class vtkFloatArray; +class vtkPointSet; + +class VTK_HYBRID_EXPORT vtkPCAAnalysisFilter : public vtkPointSetAlgorithm +{ + public: + vtkTypeRevisionMacro(vtkPCAAnalysisFilter,vtkPointSetAlgorithm); + + // Description: + // Prints information about the state of the filter. + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates with similarity transform. + static vtkPCAAnalysisFilter *New(); + + // Description: + // Get the vector of eigenvalues sorted in descending order + vtkGetObjectMacro(Evals, vtkFloatArray); + + // Description: + // Specify how many pointsets are going to be given as input. + void SetNumberOfInputs(int n); + + // Description: + // Specify the input pointset with index idx. + // Call SetNumberOfInputs before calling this function. + void SetInput(int idx,vtkPointSet* p); + + // Description: + // Retrieve the input with index idx (usually only used for pipeline + // tracing). + vtkPointSet* GetInput(int idx); + + // Description: + // Fills the shape with: + // + // mean + b[0] * sqrt(eigenvalue[0]) * eigenvector[0] + // + b[1] * sqrt(eigenvalue[1]) * eigenvector[1] + // ... + // + b[sizeb-1] * sqrt(eigenvalue[bsize-1]) * eigenvector[bsize-1] + // + // here b are the parameters expressed in standard deviations + // bsize is the number of parameters in the b vector + // This function assumes that shape is allready allocated + // with the right size, it just moves the points. + void GetParameterisedShape(vtkFloatArray *b, vtkPointSet* shape); + + // Description: + // Return the bsize parameters b that best model the given shape + // (in standard deviations). + // That is that the given shape will be approximated by: + // + // shape ~ mean + b[0] * sqrt(eigenvalue[0]) * eigenvector[0] + // + b[1] * sqrt(eigenvalue[1]) * eigenvector[1] + // ... + // + b[bsize-1] * sqrt(eigenvalue[bsize-1]) * eigenvector[bsize-1] + void GetShapeParameters(vtkPointSet *shape, vtkFloatArray *b, int bsize); + + // Description: + // Retrieve how many modes are necessary to model the given proportion of the variation. + // proportion should be between 0 and 1 + int GetModesRequiredFor(double proportion); + +protected: + vtkPCAAnalysisFilter(); + ~vtkPCAAnalysisFilter(); + + // Description: + // Usual data generation method. + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkPCAAnalysisFilter(const vtkPCAAnalysisFilter&); // Not implemented. + void operator=(const vtkPCAAnalysisFilter&); // Not implemented. + + // Eigenvalues + vtkFloatArray *Evals; + + // Matrix where each column is an eigenvector + double **evecMat2; + + // The mean shape in a vector + double *meanshape; +}; + +#endif + + diff --git a/Hybrid/vtkPExodusReader.cxx b/Hybrid/vtkPExodusReader.cxx new file mode 100644 index 0000000..3c5029f --- /dev/null +++ b/Hybrid/vtkPExodusReader.cxx @@ -0,0 +1,921 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPExodusReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkPExodusReader.h" + +#ifndef MERGE_CELLS +#ifndef APPEND +#define APPEND +#endif +#endif + +#ifdef APPEND +#include "vtkAppendFilter.h" +#else +#include "vtkMergeCells.h" +#endif +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkExodusModel.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include "netcdf.h" +#include "exodusII.h" +#include +#include +#include + +#define DEBUG 0 +#define vtkPExodusReaderMAXPATHLEN 2048 + +vtkCxxRevisionMacro(vtkPExodusReader, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkPExodusReader); + +//---------------------------------------------------------------------------- +// Description: +// Instantiate object with NULL filename. +vtkPExodusReader::vtkPExodusReader() +{ + this->FilePattern = 0; + this->CurrentFilePattern = 0; + this->FilePrefix = 0; + this->CurrentFilePrefix = 0; + this->FileRange[0] = -1; + this->FileRange[1] = -1; + this->CurrentFileRange[0] = 0; + this->CurrentFileRange[1] = 0; + this->NumberOfFiles = 1; + this->FileNames = NULL; + this->NumberOfFileNames = 0; + this->MultiFileName = new char[vtkPExodusReaderMAXPATHLEN]; + this->GenerateFileIdArray = 0; + this->XMLFileName=NULL; +} + +//---------------------------------------------------------------------------- +vtkPExodusReader::~vtkPExodusReader() +{ + this->SetFilePattern(0); + this->SetFilePrefix(0); + + // If we've allocated filenames than delete them + if (this->FileNames) + { + for (int i=0; iNumberOfFileNames; i++) + { + if (this->FileNames[i]) + { + delete [] this->FileNames[i]; + } + } + delete [] this->FileNames; + } + + // Delete all the readers we may have + for(int reader_idx=readerList.size()-1; reader_idx >= 0; --reader_idx) + { + readerList[reader_idx]->Delete(); + readerList.pop_back(); + } + + if (this->CurrentFilePrefix) + { + delete [] this->CurrentFilePrefix; + delete [] this->CurrentFilePattern; + } + + delete [] this->MultiFileName; +} + +//---------------------------------------------------------------------------- +int vtkPExodusReader::RequestInformation( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // Setting maximum number of pieces to -1 indicates to the + // upstream consumer that I can provide the same number of pieces + // as there are number of processors + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + int newName = + (this->FileName && + !vtkExodusReader::StringsEqual(this->FileName, this->CurrentFileName)); + + int newPattern = + ((this->FilePattern && + !vtkExodusReader::StringsEqual(this->FilePattern, this->CurrentFilePattern)) || + (this->FilePrefix && + !vtkExodusReader::StringsEqual(this->FilePrefix, this->CurrentFilePrefix)) || + (this->FilePattern && + ((this->FileRange[0] != this->CurrentFileRange[0]) || + (this->FileRange[1] != this->CurrentFileRange[1])))); + + int sanity = ((this->FilePattern && this->FilePrefix) || this->FileName); + + if (!sanity) + { + vtkErrorMacro(<< "Must SetFilePattern AND SetFilePrefix, or SetFileName(s)"); + return 0; + } + + if (newPattern) + { + char *nm = + new char[strlen(this->FilePattern) + strlen(this->FilePrefix) + 20]; + sprintf(nm, this->FilePattern, this->FilePrefix, this->FileRange[0]); + this->Superclass::SetFileName(nm); + } + else if (newName) + { + if (this->NumberOfFileNames == 1) + { + // A singleton file may actually be a hint to look for + // a series of files with the same base name. Must compute + // this now for ParaView. + + this->DeterminePattern(this->FileNames[0]); + } + } + + int mmd = this->ExodusModelMetadata; + this->SetExodusModelMetadata(0); // turn off for now + + // Read in info based on this->FileName + if (!this->Superclass::RequestInformation(request, inputVector, outputVector)) + { + return 0; + } + + this->SetExodusModelMetadata(mmd); // turn it back, will compute in RequestData + + if (this->CurrentFilePrefix) + { + delete [] this->CurrentFilePrefix; + this->CurrentFilePrefix = NULL; + delete [] this->CurrentFilePattern; + this->CurrentFilePattern = NULL; + this->CurrentFileRange[0] = 0; + this->CurrentFileRange[1] = 0; + } + if (this->FilePrefix) + { + this->CurrentFilePrefix = StrDupWithNew(this->FilePrefix); + this->CurrentFilePattern = StrDupWithNew(this->FilePattern); + this->CurrentFileRange[0] = this->FileRange[0]; + this->CurrentFileRange[1] = this->FileRange[1]; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkPExodusReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + int fileIndex; + int processNumber; + int numProcessors; + int min, max, idx; + unsigned int reader_idx; + + vtkInformation* outInfo = outputVector->GetInformationObject(0); + // get the ouptut + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // The whole notion of pieces for this reader is really + // just a division of files between processors + processNumber = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numProcessors = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + int numFiles = this->NumberOfFileNames; + int start = 0; + + if (numFiles <= 1) + { + start = this->FileRange[0]; // use prefix/pattern/range + numFiles = this->NumberOfFiles; + } + + // Someone has requested a file that is above the number + // of pieces I have. That may have been caused by having + // more processors than files. So I'm going to create an + // empty unstructured grid that contains all the meta + // information but has 0 cells + if (processNumber >= numFiles) + { +#if DEBUG + vtkWarningMacro("Creating empty grid for processor: " << processNumber); +#endif + this->SetUpEmptyGrid(); + return 1; + } + + // Divide the files evenly between processors + int num_files_per_process = numFiles / numProcessors; + + // This if/else logic is for when you don't have a nice even division of files + // Each process computes which sequence of files it needs to read in + int left_over_files = numFiles - (num_files_per_process*numProcessors); + if (processNumber < left_over_files) + { + min = (num_files_per_process+1) * processNumber + start; + max = min + (num_files_per_process+1) - 1; + } + else + { + min = num_files_per_process * processNumber + left_over_files + start; + max = min + num_files_per_process - 1; + } +#if DEBUG + vtkWarningMacro("Processor: " << processNumber << " reading files: " << min <<" " <ExodusModelMetadata) + { + this->NewExodusModel(); + } + + if (readerList.size() < numMyFiles) + { + for(reader_idx=readerList.size(); reader_idx < numMyFiles; ++reader_idx) + { + vtkExodusReader *er = vtkExodusReader::New(); + + + //begin USE_EXO_DSP_FILTERS + if(this->DSPFilteringIsEnabled && this->DSPFilters) + { + int i; + er->DSPFilteringIsEnabled = this->DSPFilteringIsEnabled; + er->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()]; + for(i=0;iGetNumberOfBlockArrays();i++) + { + er->DSPFilters[i] = vtkDSPFilterGroup::New(); + er->DSPFilters[i]->Copy( this->DSPFilters[i] ); + } + } + //end USE_EXO_DSP_FILTERS + + + readerList.push_back(er); + } + } + else if (readerList.size() > numMyFiles) + { + for(reader_idx=readerList.size()-1; reader_idx >= numMyFiles; --reader_idx) + { + readerList[reader_idx]->Delete(); + readerList.pop_back(); + } + } + + // This constructs the filenames + for (fileIndex = min, reader_idx=0; fileIndex <= max; ++fileIndex, ++reader_idx) + { + int fileId = -1; + + if (this->NumberOfFileNames > 1) + { + strcpy(this->MultiFileName, this->FileNames[fileIndex]); + if (this->GenerateFileIdArray) + { + fileId = vtkPExodusReader::DetermineFileId(this->FileNames[fileIndex]); + } + } + else if (this->FilePattern) + { + sprintf(this->MultiFileName, this->FilePattern, this->FilePrefix, fileIndex); + if (this->GenerateFileIdArray) + { + fileId = fileIndex; + } + } + else + { + // hmmm.... shouldn't get here + vtkErrorMacro("Some weird problem with filename/filepattern"); + return 0; + } + + readerList[reader_idx]->SetFileName(this->MultiFileName); + readerList[reader_idx]->SetTimeStep(this->GetTimeStep()); + readerList[reader_idx]->SetGenerateBlockIdCellArray( + this->GetGenerateBlockIdCellArray()); + readerList[reader_idx]->SetGenerateGlobalElementIdArray( + this->GetGenerateGlobalElementIdArray()); + readerList[reader_idx]->SetGenerateGlobalNodeIdArray( + this->GetGenerateGlobalNodeIdArray()); + readerList[reader_idx]->SetApplyDisplacements( + this->GetApplyDisplacements()); + readerList[reader_idx]->SetDisplacementMagnitude( + this->GetDisplacementMagnitude()); + + readerList[reader_idx]->SetExodusModelMetadata(this->ExodusModelMetadata); + readerList[reader_idx]->PackExodusModelOntoOutputOff(); + + readerList[reader_idx]->UpdateInformation(); + + // Copy point requests. + for (idx = 0; idx < this->GetNumberOfPointArrays(); ++idx) + { + readerList[reader_idx]->SetPointArrayStatus( + idx, this->GetPointArrayStatus(idx)); + } + + // Copy cell requests. + for (idx = 0; idx < this->GetNumberOfCellArrays(); ++idx) + { + readerList[reader_idx]->SetCellArrayStatus( + idx, this->GetCellArrayStatus(idx)); + } + + // Copy block requests. + for (idx = 0; idx < this->GetNumberOfBlockArrays(); ++idx) + { + readerList[reader_idx]->SetBlockArrayStatus( + idx, this->GetBlockArrayStatus(idx)); + } + + // Copy nodeset requests. + for (idx = 0; idx < this->GetNumberOfNodeSetArrays(); ++idx) + { + readerList[reader_idx]->SetNodeSetArrayStatus( + idx, this->GetNodeSetArrayStatus(idx)); + } + + // Copy sideset requests. + for (idx = 0; idx < this->GetNumberOfSideSetArrays(); ++idx) + { + readerList[reader_idx]->SetSideSetArrayStatus( + idx, this->GetSideSetArrayStatus(idx)); + } + + readerList[reader_idx]->Update(); + + vtkUnstructuredGrid *subgrid = vtkUnstructuredGrid::New(); + subgrid->ShallowCopy(readerList[reader_idx]->GetOutput()); + + int ncells = subgrid->GetNumberOfCells(); + + if ((ncells > 0) && this->GenerateFileIdArray) + { + vtkIntArray *ia = vtkIntArray::New(); + ia->SetNumberOfValues(ncells); + for (idx=0; idx < ncells; idx++) + { + ia->SetValue(idx, fileId); + } + ia->SetName("vtkFileId"); + subgrid->GetCellData()->AddArray(ia); + ia->Delete(); + } + + // Don't append if you don't have any cells + if (ncells != 0) + { + if (this->ExodusModelMetadata) + { + vtkExodusModel *em = readerList[reader_idx]->GetExodusModel(); + this->ExodusModel->MergeExodusModel(em); + } + +#ifdef APPEND + append->AddInput(subgrid); + subgrid->Delete(); +#else + totalSets++; + totalCells += ncells; + totalPoints += subgrid->GetNumberOfPoints(); + mergeGrid[reader_idx] = subgrid; +#endif + } + } + +#ifdef APPEND + // Append complains/barfs if you update it without any inputs + if (append->GetInput() != NULL) + { + append->Update(); + output->ShallowCopy(append->GetOutput()); + } + + // I've copied append's output to the 'output' so delete append + append->Delete(); + append = NULL; + + if (this->PackExodusModelOntoOutput) + { + // The metadata is written to field arrays and attached + // to the output unstructured grid. (vtkMergeCells does this + // itself, so we only have to do this for vtkAppendFilter.) + + if (this->ExodusModel) + { + vtkModelMetadata::RemoveMetadata(output); + this->ExodusModel->GetModelMetadata()->Pack(output); + } + } +#else + + // Idea: Modify vtkMergeCells to save point Id and cell Id + // maps (these could be compressed quite a bit), and then + // to MergeFieldArraysOnly(int idx, vtkDataSet *set) later + // on if only field arrays have changed. Would save a major + // amount of time, and also leave clues to downstream filters + // like D3 that geometry has not changed. + + vtkMergeCells *mc = vtkMergeCells::New(); + mc->SetUnstructuredGrid(output); + mc->SetTotalNumberOfDataSets(totalSets); + mc->SetTotalNumberOfPoints(totalPoints); + mc->SetTotalNumberOfCells(totalCells); + + if (this->GetGenerateGlobalNodeIdArray()) + { + // merge duplicate points using global IDs + mc->SetGlobalIdArrayName("GlobalNodeId"); + } + else + { + // don't bother trying to merge duplicate points with a locator + mc->MergeDuplicatePointsOff(); + } + + for (reader_idx=0; reader_idx < numMyFiles; ++reader_idx) + { + if (mergeGrid[reader_idx]->GetNumberOfCells() != 0) + { + mc->MergeDataSet(mergeGrid[reader_idx]); + + mergeGrid[reader_idx]->Delete(); + } + } + + delete [] mergeGrid; + + mc->Finish(); + mc->Delete(); +#endif + + + // This should not be necessary. If broken, investigate + // further. + //this->GetOutput()->SetMaximumNumberOfPieces(-1); + return 1; +} + +void vtkPExodusReader::SetUpEmptyGrid() { + + int idx; + vtkUnstructuredGrid *output = this->GetOutput(); + + // Set up an empty unstructured grid + output->Allocate(0); + + // Create new points + vtkPoints *newPoints = vtkPoints::New(); + newPoints->SetNumberOfPoints(0); + output->SetPoints(newPoints); + newPoints->Delete(); + newPoints = NULL; + + // Set up point arrays + vtkFloatArray *array = vtkFloatArray::New(); + for (idx = 0; idx < this->GetNumberOfPointArrays(); ++idx) { + + // If the point array flag in on for this array + // then set up this array + if (this->GetPointArrayStatus(idx)) { + + // How many dimensions is this array + int dim = this->GetPointArrayNumberOfComponents(idx); + array->SetNumberOfComponents(dim); + array->SetName(this->GetPointArrayName(idx)); + output->GetPointData()->AddArray(array); + } + } + + // Set up cell arrays + for (idx = 0; idx < this->GetNumberOfCellArrays(); ++idx) { + + // If the cell array flag in on for this array + // then set up this array + if (this->GetCellArrayStatus(idx)) { + + // How many dimensions is this array + int dim = this->GetCellArrayNumberOfComponents(idx); + array->SetNumberOfComponents(dim); + array->SetName(this->GetCellArrayName(idx)); + output->GetCellData()->AddArray(array); + } + } + // Delete array + array->Delete(); + array = NULL; + + // Set up generated arrays + + vtkIntArray *iarray = vtkIntArray::New(); + + if (this->GenerateBlockIdCellArray) { + iarray->SetName("BlockId"); + iarray->SetNumberOfComponents(1); + output->GetCellData()->AddArray(iarray); + } + if (this->GenerateGlobalNodeIdArray) { + iarray->SetName("GlobalNodeId"); + iarray->SetNumberOfComponents(1); + output->GetPointData()->AddArray(iarray); + } + if (this->GenerateGlobalElementIdArray) { + iarray->SetName("GlobalElementId"); + iarray->SetNumberOfComponents(1); + output->GetCellData()->AddArray(iarray); + } + + // Delete array + iarray->Delete(); + iarray = NULL; +} + +//---------------------------------------------------------------------------- +void vtkPExodusReader::SetFileRange(int min, int max) +{ + if (min == this->FileRange[0] && max == this->FileRange[1]) + { + return; + } + this->FileRange[0] = min; + this->FileRange[1] = max; + this->NumberOfFiles = max-min+1; + this->Modified(); +} +//---------------------------------------------------------------------------- +void vtkPExodusReader::SetFileName(const char *name) +{ + this->SetFileNames(1, &name); +} +void vtkPExodusReader::SetFileNames(int nfiles, const char **names) +{ + // If I have an old list of filename delete them + if (this->FileNames){ + + for (int i=0; iNumberOfFileNames; i++){ + if (this->FileNames[i]) delete [] this->FileNames[i]; + } + delete [] this->FileNames; + this->FileNames = NULL; + } + + // Set the number of files + this->NumberOfFileNames = nfiles; + + // Allocate memory for new filenames + this->FileNames = new char * [this->NumberOfFileNames]; + + // Copy filenames + for (int i=0; iFileNames[i] = StrDupWithNew(names[i]); + } + + vtkExodusReader::SetFileName(names[0]); +} + +//---------------------------------------------------------------------------- +int vtkPExodusReader::DetermineFileId(const char* file) +{ + // Assume the file number is the last digits found in the file name. + int fileId = 0; + const char *start = file; + const char *end = file + strlen(file) - 1; + const char *numString = end; + + if (!isdigit(*numString)) + { + while(numString > start) + { + --numString; + if (isdigit(*numString)) break; + } + + if (numString == start) + { + if (isdigit(*numString)) + { + fileId = atoi(numString); + } + return fileId; // no numbers in file name + } + } + + while(numString > start) + { + --numString; + if (!isdigit(*numString)) break; + } + + if ( (numString == start) && (isdigit(*numString))) + { + fileId = atoi(numString); + } + else + { + fileId = atoi(++numString); + } + + return fileId; +} +int vtkPExodusReader::DeterminePattern(const char* file) +{ + char *prefix = StrDupWithNew(file); + char pattern[20] = "%s"; + int scount = 0; + int cc = 0; + int res =0; + int min=0, max=0; + + + // Check for .ex2 or .ex2v2. If either + // of these extenstions do not look for + // a numbered sequence + char *ex2 = strstr(prefix, ".ex2"); + char *ex2v2 = strstr(prefix, ".ex2v2"); + if (ex2 || ex2v2) + { + // Set my info + this->SetFilePattern(pattern); + this->SetFilePrefix(prefix); + this->SetFileRange(min, max); + delete [] prefix; + return VTK_OK; + } + + + + // Find minimum of range, if any + for ( cc = strlen(file)-1; cc>=0; cc -- ) + { + if ( prefix[cc] >= '0' && prefix[cc] <= '9' ) + { + prefix[cc] = 0; + scount ++; + } + else if ( prefix[cc] == '.' ) + { + prefix[cc] = 0; + break; + } + else + { + break; + } + } + + // Determine the pattern + if ( scount > 0 ) + { + res = sscanf(file + strlen(file)-scount, "%d", &min); + if ( res ) + { + sprintf(pattern, "%%s.%%0%ii", scount); + } + } + + // Count up the files + char buffer[1024]; + struct stat fs; + + // First go every 100 + for (cc = min+100; res; cc+=100 ) + { + sprintf(buffer, pattern, prefix, cc); + + // Stat returns -1 if file NOT found + if ( stat(buffer, &fs) == -1) + break; + + } + // Okay if I'm here than stat has failed so -100 on my cc + cc = cc-100; + for (cc = cc+1; res; cc++ ) + { + sprintf(buffer, pattern, prefix, cc); + + // Stat returns -1 if file NOT found + if ( stat(buffer, &fs) == -1) + break; + + } + // Okay if I'm here than stat has failed so -1 on my cc + max = cc-1; + + // If the user did not specify a range before this, + // than set the range to the min and max + if ((this->FileRange[0]==-1) && (this->FileRange[1]==-1)) + { + this->SetFileRange(min, max); + } + + // Set my info + this->SetFilePattern(pattern); + this->SetFilePrefix(prefix); + delete [] prefix; + + return VTK_OK; +} + +void vtkPExodusReader::SetGenerateFileIdArray(int flag) +{ + this->GenerateFileIdArray = flag; + this->Modified(); +} + + +//---------------------------------------------------------------------------- +void vtkPExodusReader::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkExodusReader::PrintSelf(os,indent); + + if (this->FilePattern) + { + os << indent << "FilePattern: " << this->FilePattern << endl; + } + else + { + os << indent << "FilePattern: NULL\n"; + } + + if (this->FilePattern) + { + os << indent << "FilePrefix: " << this->FilePrefix << endl; + } + else + { + os << indent << "FilePrefix: NULL\n"; + } + + os << indent << "FileRange: " + << this->FileRange[0] << " " << this->FileRange[1] << endl; + + os << indent << "GenerateFileIdArray: " << this->GenerateFileIdArray << endl; + os << indent << "NumberOfFiles: " << this->NumberOfFiles << endl; +} + + +//---------------------------------------------------------------------------- +//begin USE_EXO_DSP_FILTERS +// +int vtkPExodusReader::GetNumberOfVariableArrays() +{ + return this->vtkExodusReader::GetNumberOfVariableArrays(); +} +const char *vtkPExodusReader::GetVariableArrayName(int a_which) +{ + return this->vtkExodusReader::GetVariableArrayName(a_which); +} + +//note: for the rest of these ..... is the this->vtkExodusReader:: part needed? +void vtkPExodusReader::EnableDSPFiltering() +{ + this->vtkExodusReader::EnableDSPFiltering(); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->EnableDSPFiltering(); + } +} +void vtkPExodusReader::AddFilter(vtkDSPFilterDefinition *a_filter) +{ + this->vtkExodusReader::AddFilter(a_filter); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->AddFilter(a_filter); + } +} +void vtkPExodusReader::StartAddingFilter() +{ + this->vtkExodusReader::StartAddingFilter(); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->StartAddingFilter(); + } +} +void vtkPExodusReader::AddFilterInputVar(char *name) +{ + this->vtkExodusReader::AddFilterInputVar(name); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->AddFilterInputVar(name); + } +} +void vtkPExodusReader::AddFilterOutputVar(char *name) +{ + this->vtkExodusReader::AddFilterOutputVar(name); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->AddFilterOutputVar(name); + } +} +void vtkPExodusReader::AddFilterNumeratorWeight(double weight) +{ + this->vtkExodusReader::AddFilterNumeratorWeight(weight); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->AddFilterNumeratorWeight(weight); + } +} +void vtkPExodusReader::AddFilterForwardNumeratorWeight(double weight) +{ + this->vtkExodusReader::AddFilterForwardNumeratorWeight(weight); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->AddFilterForwardNumeratorWeight(weight); + } +} +void vtkPExodusReader::AddFilterDenominatorWeight(double weight) +{ + this->vtkExodusReader::AddFilterDenominatorWeight(weight); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->AddFilterDenominatorWeight(weight); + } +} + void vtkPExodusReader::FinishAddingFilter() +{ + this->vtkExodusReader::FinishAddingFilter(); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->FinishAddingFilter(); + } +} +void vtkPExodusReader::RemoveFilter(char *a_outputVariableName) +{ + this->vtkExodusReader::RemoveFilter(a_outputVariableName); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->RemoveFilter(a_outputVariableName); + } +} +void vtkPExodusReader::GetDSPOutputArrays(int exoid, vtkUnstructuredGrid* output) +{ + this->Superclass::GetDSPOutputArrays(exoid, output); + for(unsigned int i=0;ireaderList.size();i++) + { + this->readerList[i]->GetDSPOutputArrays(exoid, output); + } +} +//end USE_EXO_DSP_FILTERS + + diff --git a/Hybrid/vtkPExodusReader.h b/Hybrid/vtkPExodusReader.h new file mode 100644 index 0000000..10c41c7 --- /dev/null +++ b/Hybrid/vtkPExodusReader.h @@ -0,0 +1,169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPExodusReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkPExodusReader - Read exodus 2 files .ex2 +// .SECTION Description +// vtkPExodusReader is a unstructured grid source object that reads +// PExodusReaderII files. Most of the meta data associated with the +// file is loaded when UpdateInformation is called. This includes +// information like Title, number of blocks, number and names of +// arrays. This data can be retrieved from methods in this +// reader. Separate arrays that are meant to be a single vector, are +// combined internally for convenience. To be combined, the array +// names have to be identical except for a trailing X,Y and Z (or +// x,y,z). By default all cell and point arrays are loaded. However, +// the user can flag arrays not to load with the methods +// "SetPointDataArrayLoadFlag" and "SetCellDataArrayLoadFlag". The +// reader responds to piece requests by loading only a range of the +// possible blocks. Unused points are filtered out internally. + + +#ifndef __vtkPExodusReader_h +#define __vtkPExodusReader_h + +#include "vtkExodusReader.h" + +#include // Required for vector + +class vtkTimerLog; + +class VTK_HYBRID_EXPORT vtkPExodusReader : public vtkExodusReader +{ +public: + static vtkPExodusReader *New(); + vtkTypeRevisionMacro(vtkPExodusReader,vtkExodusReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // These methods tell the reader that the data is ditributed across + // multiple files. This is for distributed execution. It this case, + // pieces are mapped to files. The pattern should have one %d to + // format the file number. FileNumberRange is used to generate file + // numbers. I was thinking of having an arbitrary list of file + // numbers. This may happen in the future. (That is why there is no + // GetFileNumberRange method. + vtkSetStringMacro(FilePattern); + vtkGetStringMacro(FilePattern); + vtkSetStringMacro(FilePrefix); + vtkGetStringMacro(FilePrefix); + + // Description: + // Set the range of files that are being loaded. The range for single + // file should add to 0. + void SetFileRange(int,int); + void SetFileRange(int* r) { this->SetFileRange(r[0], r[1]); } + vtkGetVector2Macro(FileRange, int); + + // Description: + // Provide an arbitrary list of file names instead of a prefix, + // pattern and range. Overrides any prefix, pattern and range + // that is specified. vtkPExodusReader makes it's own copy + // of your file names. + void SetFileNames(int nfiles, const char **names); + + virtual void SetFileName(const char *name); + + // Description: + // Return pointer to list of file names set in SetFileNames + char **GetFileNames(){return this->FileNames;} + + // Description: + // Return number of file names set in SetFileNames + int GetNumberOfFileNames(){return this->NumberOfFileNames;} + + // Description: + // Return the number of files to be read. + vtkGetMacro(NumberOfFiles, int); + + // Description: + // Extra cell data array that can be generated. By default, this array + // is OFF. The value of the array is the integer id which is part of + // the name of the file from which the cell was read. + // The name of the array is "vtkFileId". + + void SetGenerateFileIdArray(int flag); + vtkGetMacro(GenerateFileIdArray, int); + vtkBooleanMacro(GenerateFileIdArray, int); + + +//begin USE_EXO_DSP_FILTERS + int GetNumberOfVariableArrays(); + const char *GetVariableArrayName(int a_which); + void EnableDSPFiltering(); + void AddFilter(vtkDSPFilterDefinition *a_filter); + void StartAddingFilter(); + void AddFilterInputVar(char *name); + void AddFilterOutputVar(char *name); + void AddFilterNumeratorWeight(double weight); + void AddFilterForwardNumeratorWeight(double weight); + void AddFilterDenominatorWeight(double weight); + void FinishAddingFilter(); + void RemoveFilter(char *a_outputVariableName); +//end USE_EXO_DSP_FILTERS + + +protected: + vtkPExodusReader(); + ~vtkPExodusReader(); + +//begin USE_EXO_DSP_FILTERS + void GetDSPOutputArrays(int exoid, vtkUnstructuredGrid* output); +//end USE_EXO_DSP_FILTERS + + // Description: + // Try to "guess" the pattern of files. + int DeterminePattern(const char* file); + static int DetermineFileId(const char* file); + + // This method sets up a ugrid with + // all meta data but zero cells + void SetUpEmptyGrid(); + + // **KEN** Previous discussions concluded with std classes in header + // files is bad. Perhaps we should change readerList. + + char* FilePattern; + char* CurrentFilePattern; + char* FilePrefix; + char* CurrentFilePrefix; + char* MultiFileName; + int FileRange[2]; + int CurrentFileRange[2]; + int NumberOfFiles; + char **FileNames; + int NumberOfFileNames; + int GenerateFileIdArray; +//BTX + vtkstd::vector readerList; +//ETX + + int Timing; + vtkTimerLog *TimerLog; + + int RequestInformation( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkPExodusReader(const vtkPExodusReader&); // Not implemented + void operator=(const vtkPExodusReader&); // Not implemented +}; + +#endif diff --git a/Hybrid/vtkPolyDataToImageStencil.cxx b/Hybrid/vtkPolyDataToImageStencil.cxx new file mode 100644 index 0000000..3e0d372 --- /dev/null +++ b/Hybrid/vtkPolyDataToImageStencil.cxx @@ -0,0 +1,331 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataToImageStencil.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataToImageStencil.h" + +#include "vtkGarbageCollector.h" +#include "vtkImageStencilData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkOBBTree.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkPolyDataToImageStencil, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkPolyDataToImageStencil); + +//---------------------------------------------------------------------------- +vtkPolyDataToImageStencil::vtkPolyDataToImageStencil() +{ + this->OBBTree = NULL; + this->Tolerance = 1e-3; +} + +//---------------------------------------------------------------------------- +vtkPolyDataToImageStencil::~vtkPolyDataToImageStencil() +{ + if (this->OBBTree) + { + this->OBBTree->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkPolyDataToImageStencil::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Input: " << this->GetInput() << "\n"; + os << indent << "Tolerance: " << this->Tolerance << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkPolyDataToImageStencil::SetInput(vtkPolyData *input) +{ + if (input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + this->SetInputConnection(0, 0); + } +} + +//---------------------------------------------------------------------------- +vtkPolyData *vtkPolyDataToImageStencil::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return NULL; + } + + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +//---------------------------------------------------------------------------- +static inline +void vtkAddEntryToList(int *&clist, int &clistlen, int &clistmaxlen, int r) +{ + if (clistlen >= clistmaxlen) + { // need to allocate more space + clistmaxlen *= 2; + int *newclist = new int[clistmaxlen]; + for (int k = 0; k < clistlen; k++) + { + newclist[k] = clist[k]; + } + delete [] clist; + clist = newclist; + } + + if (clistlen > 0 && r <= clist[clistlen-1]) + { // chop out zero-length extents + clistlen--; + } + else + { + clist[clistlen++] = r; + } +} + +//---------------------------------------------------------------------------- +static +void vtkTurnPointsIntoList(vtkPoints *points, int *&clist, int &clistlen, + int extent[6], double origin[3], double spacing[3], + int dim) +{ + int clistmaxlen = 2; + clistlen = 0; + clist = new int[clistmaxlen]; + + int npoints = points->GetNumberOfPoints(); + for (int idP = 0; idP < npoints; idP++) + { + double point[3]; + points->GetPoint(idP, point); + int r = (int)ceil((point[dim] - origin[dim])/spacing[dim]); + if (r < extent[2*dim]) + { + r = extent[2*dim]; + } + if (r > extent[2*dim+1]) + { + break; + } + vtkAddEntryToList(clist, clistlen, clistmaxlen, r); + } +} + +//---------------------------------------------------------------------------- +int vtkPolyDataToImageStencil::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Superclass::RequestData(request, inputVector, outputVector); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // need to build the OBB tree + vtkPolyData *polydata = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageStencilData *data = vtkImageStencilData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (this->OBBTree == NULL) + { + this->OBBTree = vtkOBBTree::New(); + } + this->OBBTree->SetDataSet(polydata); + this->OBBTree->SetTolerance(this->Tolerance); + this->OBBTree->BuildLocator(); + + // for keeping track of progress + unsigned long count = 0; + int extent[6]; + data->GetExtent(extent); + unsigned long target = (unsigned long) + ((extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)/50.0); + target++; + + // if we have no data then return + if (!polydata->GetNumberOfPoints()) + { + return 1; + } + + double *spacing = data->GetSpacing(); + double *origin = data->GetOrigin(); + + vtkOBBTree *tree = this->OBBTree; + vtkPoints *points = vtkPoints::New(); + + double p0[3],p1[3]; + + p1[0] = p0[0] = extent[0]*spacing[0] + origin[0]; + p1[1] = p0[1] = extent[2]*spacing[1] + origin[1]; + p0[2] = extent[4]*spacing[2] + origin[2]; + p1[2] = extent[5]*spacing[2] + origin[2]; + + int zstate = tree->InsideOrOutside(p0); + if (zstate == 0) + { + zstate = -1; + } + int *zlist = 0; + int zlistlen = 0; + int zlistidx = 0; + if (extent[4] < extent[5]) + { + tree->IntersectWithLine(p0, p1, points, 0); + vtkTurnPointsIntoList(points, zlist, zlistlen, + extent, origin, spacing, 2); + } + + for (int idZ = extent[4]; idZ <= extent[5]; idZ++) + { + if (zlistidx < zlistlen && idZ >= zlist[zlistidx]) + { + zstate = -zstate; + zlistidx++; + } + + p1[0] = p0[0] = extent[0]*spacing[0] + origin[0]; + p0[1] = extent[2]*spacing[1] + origin[1]; + p1[1] = extent[3]*spacing[1] + origin[1]; + p1[2] = p0[2] = idZ*spacing[2] + origin[2]; + + int ystate = zstate; + int *ylist = 0; + int ylistlen = 0; + int ylistidx = 0; + if (extent[2] != extent[3]) + { + tree->IntersectWithLine(p0, p1, points, 0); + vtkTurnPointsIntoList(points, ylist, ylistlen, + extent, origin, spacing, 1); + } + + for (int idY = extent[2]; idY <= extent[3]; idY++) + { + if (ylistidx < ylistlen && idY >= ylist[ylistidx]) + { + ystate = -ystate; + ylistidx++; + } + + if (count%target == 0) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + + p0[1] = p1[1] = idY*spacing[1] + origin[1]; + p0[2] = p1[2] = idZ*spacing[2] + origin[2]; + p0[0] = extent[0]*spacing[0] + origin[0]; + p1[0] = extent[1]*spacing[0] + origin[0]; + + int xstate = ystate; + int *xlist = 0; + int xlistlen = 0; + int xlistidx = 0; + tree->IntersectWithLine(p0, p1, points, 0); + vtkTurnPointsIntoList(points, xlist, xlistlen, + extent, origin, spacing, 0); + + // now turn 'xlist' into sub-extents: + int r1 = extent[0]; + int r2 = extent[1]; + for (xlistidx = 0; xlistidx < xlistlen; xlistidx++) + { + xstate = -xstate; + if (xstate < 0) + { // sub extent starts + r1 = xlist[xlistidx]; + } + else + { // sub extent ends + r2 = xlist[xlistidx] - 1; + data->InsertNextExtent(r1, r2, idY, idZ); + } + } + if (xstate < 0) + { // if inside at end, cap off the sub extent + data->InsertNextExtent(r1, extent[1], idY, idZ); + } + + if (xlist) + { + delete [] xlist; + } + + } // for idY + + if (ylist) + { + delete [] ylist; + } + + } // for idZ + + if (zlist) + { + delete [] zlist; + } + points->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPolyDataToImageStencil::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // This filter shares our input and is therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->OBBTree, "OBBTree"); +} + +int vtkPolyDataToImageStencil::RequestInformation( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // this is an odd source that can produce any requested size. so its whole + // extent is essentially infinite. This would not be a great source to + // connect to some sort of writer or viewer. For a sanity check we will + // limit the size produced to something reasonable (depending on your + // definition of reasonable) + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, VTK_LARGE_INTEGER >> 2, + 0, VTK_LARGE_INTEGER >> 2, + 0, VTK_LARGE_INTEGER >> 2); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataToImageStencil::FillInputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} diff --git a/Hybrid/vtkPolyDataToImageStencil.h b/Hybrid/vtkPolyDataToImageStencil.h new file mode 100644 index 0000000..22bbcb5 --- /dev/null +++ b/Hybrid/vtkPolyDataToImageStencil.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataToImageStencil.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataToImageStencil - clip an image with polydata +// .SECTION Description +// vtkPolyDataToImageStencil will convert a vtkPolyData into an image +// that can be used with vtkImageStencil or other vtk classes that apply +// a stencil to an image. +// .SECTION see also +// vtkPolyData vtkImageStencil vtkImplicitFunctionToImageStencil + +#ifndef __vtkPolyDataToImageStencil_h +#define __vtkPolyDataToImageStencil_h + + +#include "vtkImageStencilSource.h" + +class vtkPolyData; +class vtkOBBTree; + +class VTK_HYBRID_EXPORT vtkPolyDataToImageStencil : public vtkImageStencilSource +{ +public: + static vtkPolyDataToImageStencil *New(); + vtkTypeRevisionMacro(vtkPolyDataToImageStencil, vtkImageStencilSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the polydata to convert into a stencil. + void SetInput(vtkPolyData *input); + vtkPolyData *GetInput(); + + // Description: + // Set the tolerance for doing spatial searches of the polydata. + vtkSetMacro(Tolerance, double); + vtkGetMacro(Tolerance, double); + +protected: + vtkPolyDataToImageStencil(); + ~vtkPolyDataToImageStencil(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + double Tolerance; + vtkOBBTree *OBBTree; + + virtual void ReportReferences(vtkGarbageCollector*); + virtual int FillInputPortInformation(int, vtkInformation*); +private: + vtkPolyDataToImageStencil(const vtkPolyDataToImageStencil&); // Not implemented. + void operator=(const vtkPolyDataToImageStencil&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkProcrustesAlignmentFilter.cxx b/Hybrid/vtkProcrustesAlignmentFilter.cxx new file mode 100644 index 0000000..1bba656 --- /dev/null +++ b/Hybrid/vtkProcrustesAlignmentFilter.cxx @@ -0,0 +1,390 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcrustesAlignmentFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProcrustesAlignmentFilter.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkLandmarkTransform.h" +#include "vtkTransformPolyDataFilter.h" +#include "vtkPolyData.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkProcrustesAlignmentFilter, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkProcrustesAlignmentFilter); + +//---------------------------------------------------------------------------- +// protected +vtkProcrustesAlignmentFilter::vtkProcrustesAlignmentFilter() +{ + this->LandmarkTransform = vtkLandmarkTransform::New(); + + this->MeanPoints = vtkPoints::New(); +} + +//---------------------------------------------------------------------------- +// protected +vtkProcrustesAlignmentFilter::~vtkProcrustesAlignmentFilter() +{ + if(this->LandmarkTransform) + { + this->LandmarkTransform->Delete(); + } + if(this->MeanPoints) + { + this->MeanPoints->Delete(); + } +} + +//---------------------------------------------------------------------------- +// Calculate the centroid of a point cloud +static inline void Centroid(vtkPoints* pd, double *cp) +{ + // Center point + cp[0] = 0; cp[1] = 0; cp[2] = 0; + + int np = pd->GetNumberOfPoints(); + + // Calculate center of shape + for (int i = 0; i < np; i++) + { + double p[3]; + pd->GetPoint(i, p); + cp[0] += p[0]; cp[1] += p[1]; cp[2] += p[2]; + } + cp[0] /= np; cp[1] /= np; cp[2] /= np; +} + +//---------------------------------------------------------------------------- +// Calculate the centroid size of a point cloud +static inline double CentroidSize(vtkPoints* pd, double *cp) +{ + Centroid(pd, cp); + + double S = 0; + for (int i = 0; i < pd->GetNumberOfPoints(); i++) + { + double p[3]; + pd->GetPoint(i, p); + S += vtkMath::Distance2BetweenPoints(p,cp); + } + + return sqrt(S); +} + +//---------------------------------------------------------------------------- +// Translation of point cloud. Could be done using transformations +static inline void TranslateShape(vtkPoints* pd, double *tp) +{ + for (int i = 0; i < pd->GetNumberOfPoints(); i++) + { + double p[3]; + pd->GetPoint(i, p); + pd->SetPoint(i, p[0]+tp[0], p[1]+tp[1], p[2]+tp[2]); + } +} + +//---------------------------------------------------------------------------- +// Scaling of point cloud. Could be done using transformations +static inline void ScaleShape(vtkPoints* pd, double S) +{ + for (int i = 0; i < pd->GetNumberOfPoints(); i++) + { + double p[3]; + pd->GetPoint(i, p); + pd->SetPoint(i, p[0]*S, p[1]*S, p[2]*S); + } +} + +//---------------------------------------------------------------------------- +// Normalise a point cloud to have centroid (0,0,0) and centroid size 1 +static inline int NormaliseShape(vtkPoints* pd) +{ + double cp[3]; + double S = CentroidSize(pd, cp); + if (S == 0) + return 0; + + double tp[3]; + tp[0] = -cp[0]; tp[1] = -cp[1]; tp[2] = -cp[2]; + TranslateShape(pd, tp); + ScaleShape(pd, 1/S); + return 1; +} + + +//---------------------------------------------------------------------------- +// protected +int vtkProcrustesAlignmentFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Execute()"); + + int i,v; + + const int N_SETS = this->GetNumberOfInputConnections(0); + + // copy the inputs across + // (really actually only the points need to be deep copied since the rest stays the same) + vtkInformation *tmpInfo; + vtkPointSet *tmpInput; + output->DeepCopy(input); + for(i=1;iGetInformationObject(i); + tmpInput = 0; + if (tmpInfo) + { + tmpInput = + vtkPointSet::SafeDownCast(tmpInfo->Get(vtkDataObject::DATA_OBJECT())); + } + this->GetOutput(i)->DeepCopy(tmpInput); + } + + // the number of points is determined by the first input (they must all be the same) + const int N_POINTS = input->GetNumberOfPoints(); + + vtkDebugMacro(<<"N_POINTS is " <GetInformationObject(i); + tmpInput = 0; + if (tmpInfo) + { + tmpInput = + vtkPointSet::SafeDownCast(tmpInfo->Get(vtkDataObject::DATA_OBJECT())); + } + else + { + continue; + } + if(tmpInput->GetNumberOfPoints() != N_POINTS) + { + vtkErrorMacro(<<"The inputs have different numbers of points!"); + return 1; + } + } + +// vtkPoints *mean_points = vtkPoints::New(); + MeanPoints->DeepCopy(input->GetPoints()); + // our initial estimate of the mean comes from the first example in the set + + // we keep a record of the first mean to fix the orientation and scale + // (which are otherwise undefined and the loop will not converge) + vtkPoints *first_mean = vtkPoints::New(); + first_mean->DeepCopy(MeanPoints); + + + // If the similarity transform is used, the mean shape must be normalised + // to avoid shrinking + if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY) + { + if (!NormaliseShape(MeanPoints)) { + vtkErrorMacro(<<"Centroid size zero"); + return 1; + } + if (!NormaliseShape(first_mean)) { + vtkErrorMacro(<<"Centroid size zero"); + return 1; + } + } + + + // storage for the new mean that is being calculated + vtkPoints *new_mean = vtkPoints::New(); + new_mean->SetNumberOfPoints(N_POINTS); + + // compute mean and align all the shapes to it, until convergence + int converged=0; // bool converged=false + int iterations=0; + const int MAX_ITERATIONS=5; + double difference; + double point[3],p[3],p2[3]; + double outPoint[3]; + do { // (while not converged) + + // align each pointset with the mean + for(i=0;iLandmarkTransform->SetSourceLandmarks(this->GetOutput(i)->GetPoints()); + this->LandmarkTransform->SetTargetLandmarks(MeanPoints); + this->LandmarkTransform->Update(); + for(v=0;vLandmarkTransform->InternalTransformPoint( + this->GetOutput(i)->GetPoint(v), outPoint); + this->GetOutput(i)->GetPoints()->SetPoint(v, outPoint); + } + } + + // compute the new mean (just average the point locations) + for(v=0;vGetOutput(i)->GetPoint(v, p); + point[0]+=p[0]; + point[1]+=p[1]; + point[2]+=p[2]; + } + p[0] = point[0]/(double)N_SETS; + p[1] = point[1]/(double)N_SETS; + p[2] = point[2]/(double)N_SETS; + new_mean->SetPoint(v, p); + } + + // align the new mean with the fixed mean if the transform + // is similarity or rigidbody. It is not yet decided what to do with affine + if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY || + this->LandmarkTransform->GetMode() == VTK_LANDMARK_RIGIDBODY){ + this->LandmarkTransform->SetSourceLandmarks(new_mean); + this->LandmarkTransform->SetTargetLandmarks(first_mean); + this->LandmarkTransform->Update(); + for(v=0;vLandmarkTransform->InternalTransformPoint( + new_mean->GetPoint(v), outPoint); + new_mean->SetPoint(v, outPoint); + } + } + + // If the similarity transform is used, the mean shape must be normalised + // to avoid shrinking + if (this->LandmarkTransform->GetMode() == VTK_LANDMARK_SIMILARITY) { + if (!NormaliseShape(new_mean)) { + vtkErrorMacro(<<"Centroid size zero"); + return 1; + } + } + + + // the new mean becomes our mean + // compute the difference between the two + difference = 0.0F; + for(v=0;vGetPoint(v, p); + MeanPoints->GetPoint(v, p2); + difference += vtkMath::Distance2BetweenPoints(p,p2); + MeanPoints->SetPoint(v, p); + } + + // test for convergence + iterations++; + vtkDebugMacro( << "Difference after " << iterations << " iteration(s) is: " << difference); + if(difference<1e-6 || iterations>=MAX_ITERATIONS) { + converged=1; // true + } + + // The convergence test is that the sum of the distances between the + // points on mean(t) and mean(t-1) is less than a very small number. + // Procrustes shouldn't need more than 2 or 3 iterations but things could go wrong + // so we impose an iteration limit to avoid getting stuck in an infinite loop. + + } while(!converged); + + if(iterations>=MAX_ITERATIONS) { + vtkDebugMacro( << "Procrustes did not converge in " << MAX_ITERATIONS << " iterations! Objects may not be aligned. Difference = " << + difference); + // we don't throw an Error here since the shapes most probably *are* aligned, but the + // numerical precision is worse than our convergence test anticipated. + } + else { + vtkDebugMacro( << "Procrustes required " << iterations << " iterations to converge to " << + difference); + } + + // clean up + first_mean->Delete(); + new_mean->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +// public +void vtkProcrustesAlignmentFilter::SetNumberOfInputs(int n) +{ + this->SetNumberOfInputConnections(0, n); + this->SetNumberOfOutputPorts(n); + + // initialise the outputs + for(int i=0;iSetPoints(points); + points->Delete(); + this->GetExecutive()->SetOutputData(i,ps); + ps->Delete(); + } + + // is this the right thing to be doing here? if we don't initialise the outputs here + // then the filter crashes but vtkPolyData may not be the type of the inputs +} + +//---------------------------------------------------------------------------- +void vtkProcrustesAlignmentFilter::SetInput(int idx, vtkPointSet *p) +{ + this->SetNthInputConnection(0, idx, p ? p->GetProducerPort() : 0); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkProcrustesAlignmentFilter::GetInput(int idx) +{ + return vtkPointSet::SafeDownCast( + this->GetExecutive()->GetInputData(0, idx)); +} + +//---------------------------------------------------------------------------- +int vtkProcrustesAlignmentFilter::FillInputPortInformation( + int port, vtkInformation *info) +{ + int retval = this->Superclass::FillInputPortInformation(port, info); + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return retval; +} + +//---------------------------------------------------------------------------- +// public +void vtkProcrustesAlignmentFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + this->LandmarkTransform->PrintSelf(os,indent.GetNextIndent()); + this->MeanPoints->PrintSelf(os, indent.GetNextIndent()); +} diff --git a/Hybrid/vtkProcrustesAlignmentFilter.h b/Hybrid/vtkProcrustesAlignmentFilter.h new file mode 100644 index 0000000..203346d --- /dev/null +++ b/Hybrid/vtkProcrustesAlignmentFilter.h @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcrustesAlignmentFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProcrustesAlignmentFilter - aligns a set of pointsets together +// .SECTION Description +// +// vtkProcrustesAlignmentFilter is a filter that takes a set of pointsets +// (any object derived from vtkPointSet) and aligns them in a least-squares +// sense to their mutual mean. The algorithm is iterated until convergence, +// as the mean must be recomputed after each alignment. +// +// Call SetNumberOfInputs(n) before calling SetInput(0) ... SetInput(n-1). +// +// Retrieve the outputs using GetOutput(0) ... GetOutput(n-1). +// +// The default (in vtkLandmarkTransform) is for a similarity alignment. +// For a rigid-body alignment (to build a 'size-and-shape' model) use: +// +// GetLandmarkTransform()->SetModeToRigidBody(). +// +// Affine alignments are not normally used but are left in for completeness: +// +// GetLandmarkTransform()->SetModeToAffine(). +// +// vtkProcrustesAlignmentFilter is an implementation of: +// +// J.C. Gower (1975) +// Generalized Procrustes Analysis. Psychometrika, 40:33-51. +// +// .SECTION Caveats +// All of the input pointsets must have the same number of points. +// +// .SECTION Thanks +// Tim Hutton and Rasmus Paulsen who developed and contributed this class +// +// .SECTION See Also +// vtkLandmarkTransform + +#ifndef __vtkProcrustesAlignmentFilter_h +#define __vtkProcrustesAlignmentFilter_h + +#include "vtkPointSetAlgorithm.h" + +class vtkLandmarkTransform; +class vtkPointSet; +class vtkPoints; + +class VTK_HYBRID_EXPORT vtkProcrustesAlignmentFilter : public vtkPointSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkProcrustesAlignmentFilter,vtkPointSetAlgorithm); + + // Description: + // Prints information about the state of the filter. + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates with similarity transform. + static vtkProcrustesAlignmentFilter *New(); + + // Description: + // Get the internal landmark transform. Use it to constrain the number of + // degrees of freedom of the alignment (i.e. rigid body, similarity, etc.). + // The default is a similarity alignment. + vtkGetObjectMacro(LandmarkTransform,vtkLandmarkTransform); + + // Description: + // Get the estimated mean point cloud + vtkGetObjectMacro(MeanPoints,vtkPoints); + + // Description: + // Specify how many pointsets are going to be given as input. + void SetNumberOfInputs(int n); + + // Description: + // Specify the input pointset with index idx. + // Call SetNumberOfInputs before calling this function. + void SetInput(int idx,vtkPointSet* p); + + // Description: + // Retrieve the input point set with index idx (usually only for pipeline + // tracing). + vtkPointSet* GetInput(int idx); + +protected: + vtkProcrustesAlignmentFilter(); + ~vtkProcrustesAlignmentFilter(); + + // Description: + // Usual data generation method. + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkLandmarkTransform *LandmarkTransform; + + vtkPoints *MeanPoints; + +private: + vtkProcrustesAlignmentFilter(const vtkProcrustesAlignmentFilter&); // Not implemented. + void operator=(const vtkProcrustesAlignmentFilter&); // Not implemented. +}; + +#endif + + diff --git a/Hybrid/vtkProjectedTerrainPath.cxx b/Hybrid/vtkProjectedTerrainPath.cxx new file mode 100644 index 0000000..8ff11d8 --- /dev/null +++ b/Hybrid/vtkProjectedTerrainPath.cxx @@ -0,0 +1,544 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProjectedTerrainPath.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProjectedTerrainPath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPriorityQueue.h" +#include "vtkImageData.h" +#include "vtkPolyData.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkExecutive.h" +#include "vtkMath.h" +#include "vtkPixel.h" +#include + +// Define the edge list class-------------------------------------------------- +struct vtkEdge +{ + vtkEdge(vtkIdType v1, vtkIdType v2) : V1(v1), V2(v2), tPos(-1.0), tNeg(-1.0) {} + + vtkIdType V1; + vtkIdType V2; + double tPos; //parametric coordinates where positive maximum error occurs + double tNeg; //parametric coordinates where negative maximum error occurs +}; + +class vtkEdgeList : public vtkstd::vector {}; +typedef vtkEdgeList EdgeListType; +typedef vtkEdgeList::iterator EdgeListIterator; + + +// Begin vtkProjectedTerrainPath class implementation-------------------------- +// +vtkCxxRevisionMacro(vtkProjectedTerrainPath, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkProjectedTerrainPath); + +//----------------------------------------------------------------------------- +vtkProjectedTerrainPath::vtkProjectedTerrainPath() +{ + this->SetNumberOfInputPorts(2); + + this->ProjectionMode = SIMPLE_PROJECTION; + this->HeightOffset = 10.0; + this->HeightTolerance = 10.0; + this->MaximumNumberOfLines = VTK_LARGE_ID; + this->PositiveLineError = NULL; + this->NegativeLineError = NULL; +} + +//----------------------------------------------------------------------------- +vtkProjectedTerrainPath::~vtkProjectedTerrainPath() +{ +} + +//----------------------------------------------------------------------------- +void vtkProjectedTerrainPath::SetSource(vtkImageData *source) +{ + this->SetInput(1, source); +} + +//----------------------------------------------------------------------------- +vtkImageData *vtkProjectedTerrainPath::GetSource() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(1, 0)); +} + +//----------------------------------------------------------------------------- +int vtkProjectedTerrainPath::FillInputPortInformation(int port, + vtkInformation *info) +{ + if (port == 0) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; + } + else if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; + } + return 0; +} + +//----------------------------------------------------------------------------- +// Warning: this method may return negative indices. This is expected behavior +// +inline void vtkProjectedTerrainPath::GetImageIndex(double x[3], + double loc[2], int ij[2]) +{ + loc[0] = (x[0] - this->Origin[0]) / this->Spacing[0]; + ij[0] = (int) (floor(loc[0])); + loc[1] = (x[1] - this->Origin[1]) / this->Spacing[1]; + ij[1] = (int) (floor(loc[1])); +} + +//----------------------------------------------------------------------------- +int vtkProjectedTerrainPath::RequestData(vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the input and output + vtkInformation *linesInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *imageInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkPolyData *lines = vtkPolyData::SafeDownCast( + linesInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *image = vtkImageData::SafeDownCast( + imageInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPoints = lines->GetPoints(); + vtkIdType numPts = inPoints->GetNumberOfPoints(); + vtkCellArray *inLines = lines->GetLines(); + vtkIdType numLines; + if ( ! inLines || (numLines=inLines->GetNumberOfCells()) <= 0 ) + { + vtkErrorMacro("This filter requires lines as input"); + return 1; + } + + if ( ! image ) + { + vtkErrorMacro("This filter requires an image as input"); + return 1; + } + image->GetDimensions(this->Dimensions); + image->GetOrigin(this->Origin); + image->GetSpacing(this->Spacing); + image->GetExtent(this->Extent); + this->Heights = image->GetPointData()->GetScalars(); + + this->Points = vtkPoints::New(); + this->Points->SetDataTypeToDouble(); + this->Points->Allocate(numPts); + output->SetPoints(this->Points); + this->Points->Delete(); //ok reference counting + + vtkPointData *inPD = lines->GetPointData(); + vtkPointData *outPD = output->GetPointData(); + outPD->CopyAllocate(inPD); + + // The algorithm runs in three parts. First, the existing points are + // projected onto the image (with the height offset). Next, if requested + // the edges are checked for occlusion. Finally, if requested, the edges + // are adjusted to hug the terrain. + int ij[2]; + vtkIdType i; + double x[3], z, loc[2]; + for (i=0; iGetPoint(i,x); + this->GetImageIndex(x,loc,ij); + z = this->GetHeight(loc,ij); + this->Points->InsertPoint(i, x[0], x[1], z); + outPD->CopyData(inPD,i,i); + } + + // If mode is simple, then just spit out the original polylines + if ( this->ProjectionMode == SIMPLE_PROJECTION ) + { + output->SetLines(inLines); + return 1; + } + + // If here, we've got to get fancy and start the subdivision process. + // This means creating some fancy data structures: a dynamic list + // for the edges. The structure is implicit: the first two entries + // in the list (i,i+1) form an edge; the next two (i+1,i+2) form the + // next edge, and so on. The list contains point ids referring to + // the this->Points array. + vtkIdType j, npts=0, *pts=NULL; + this->EdgeList = new EdgeListType; + this->PositiveLineError = vtkPriorityQueue::New(); + this->NegativeLineError = vtkPriorityQueue::New(); + this->NumLines = 0; + for ( inLines->InitTraversal(); inLines->GetNextCell(npts,pts); ) + { + for (j=0; j<(npts-1); j++) + { + this->EdgeList->push_back(vtkEdge(pts[j],pts[j+1])); + this->ComputeError(this->EdgeList->size()-1); //puts edges in queues + this->NumLines++; + } + } + + if ( this->ProjectionMode == NONOCCLUDED_PROJECTION ) + { + this->RemoveOcclusions(); + } + else //if ( this->ProjectionMode == HUG_PROJECTION ) + { + this->HugTerrain(); + } + + //Okay now dump out the edges from the edge list into the output polydata + vtkCellArray *outLines = vtkCellArray::New(); + outLines->Allocate(outLines->EstimateSize(this->EdgeList->size(),2)); + for (EdgeListIterator iter=this->EdgeList->begin(); + iter != this->EdgeList->end(); + ++iter) + { + outLines->InsertNextCell(2); + outLines->InsertCellPoint(iter->V1); + outLines->InsertCellPoint(iter->V2); + } + output->SetLines(outLines); + outLines->Delete(); + vtkDebugMacro("Produced " << outLines->GetNumberOfCells() << " lines from " + << numLines << " input polylines"); + + // Clean up + delete this->EdgeList; + this->PositiveLineError->Delete(); + this->NegativeLineError->Delete(); + + return 1; +} + +//----------------------------------------------------------------------------- +// Remove all intersections of the line segments with the terrain +void vtkProjectedTerrainPath::RemoveOcclusions() +{ + double error; + vtkIdType eId; + if ( this->HeightOffset > 0.0 ) //want path above terrain, eliminate negative errors + { + while ( (eId=this->NegativeLineError->Pop(0,error)) >= 0 && + this->NumLines < this->MaximumNumberOfLines ) + { + this->SplitEdge(eId,(*this->EdgeList)[eId].tNeg); + } + } + else //want path below terrain, eliminate positive errors + { + while ( (eId=this->PositiveLineError->Pop(0,error)) >= 0 && + this->NumLines < this->MaximumNumberOfLines ) + { + this->SplitEdge(eId,(*this->EdgeList)[eId].tPos); + } + } +} + +//----------------------------------------------------------------------------- +// Adjust the lines so that they hug the terrain within the tolerance specified +void vtkProjectedTerrainPath::HugTerrain() +{ + // Loop until error meets threshold. + // Remember that the errors in the priority queues are negative. + // Also, splitting an edge can cause the polyline to reintersect the terrain. + // This is the reason for the outer while{} loop. + double error; + vtkIdType eId, stillPopping=1; + + while ( stillPopping ) + { + stillPopping = 0; + while ( (eId=this->PositiveLineError->Pop(0,error)) >= 0 && + this->NumLines < this->MaximumNumberOfLines ) + { + // Have to remove edge (if it exists) from other queue since + // it will be reprocessed + this->NegativeLineError->DeleteId(eId); + if ( (-error) > this->HeightTolerance ) + { + this->SplitEdge(eId,(*this->EdgeList)[eId].tPos); + stillPopping = 1; + } + else + { + break; + } + } + while ( (eId=this->NegativeLineError->Pop(0,error)) >= 0 && + this->NumLines < this->MaximumNumberOfLines ) + { + // Have to remove edge (if it exists) from other queue since + // it will be reprocessed + this->PositiveLineError->DeleteId(eId); + if ( (-error) > this->HeightTolerance ) + { + this->SplitEdge(eId,(*this->EdgeList)[eId].tNeg); + stillPopping = 1; + } + else + { + break; + } + } + } //while still popping +} + + +//----------------------------------------------------------------------------- +// Splits the indicated edge and reinserts the edges back into the EdgeList as +// well as the appropriate priority queues. +void vtkProjectedTerrainPath::SplitEdge(vtkIdType eId, double t) +{ + this->NumLines++; + + // Get the points defining the edge + vtkEdge &e =(*this->EdgeList)[eId]; + double p1[3], p2[3]; + this->Points->GetPoint(e.V1,p1); + this->Points->GetPoint(e.V2,p2); + + // Now generate the split point and add it to the list of points + double x[3], loc[2]; + int ij[2]; + x[0] = p1[0] + t*(p2[0]-p1[0]); + x[1] = p1[1] + t*(p2[1]-p1[1]); + this->GetImageIndex(x,loc,ij); + x[2] = this->GetHeight(loc,ij); + vtkIdType pId = this->Points->InsertNextPoint(x); + + // We will create a new edge and update the old one. + vtkIdType v2 = e.V2; + e.V2 = pId; + this->EdgeList->push_back(vtkEdge(pId,v2)); + vtkIdType eNew = this->EdgeList->size() - 1; + + // Recompute the errors along the edges + this->ComputeError(eId); + this->ComputeError(eNew); +} + +// if the line lies outside of the image. +double vtkProjectedTerrainPath::GetHeight(double loc[2], int ij[2]) +{ + // Compute the ij location (assuming 2D image plane) + // + int i; + double pcoords[2]; + for (i=0; i<2; i++) + { + if ( ij[i] >= this->Extent[i*2] && ij[i] < this->Extent[i*2 + 1] ) + { + pcoords[i] = loc[i] - (double)ij[i]; + } + + else if ( ij[i] < this->Extent[i*2] || ij[i] > this->Extent[i*2+1] ) + { + return this->HeightOffset; + } + + else //if ( ij[i] == this->Extent[i*2+1] ) + { + if (this->Dimensions[i] == 1) + { + pcoords[i] = 0.0; + } + else + { + ij[i] -= 1; + pcoords[i] = 1.0; + } + } + } + + // Interpolate the height + double weights[4], s0, s1, s2, s3; + vtkPixel::InterpolationFunctions(pcoords,weights); + s0 = this->Heights->GetTuple1(ij[0]+ ij[1]*this->Dimensions[0]); + s1 = this->Heights->GetTuple1(ij[0]+1+ ij[1]*this->Dimensions[0]); + s2 = this->Heights->GetTuple1(ij[0]+ (ij[1]+1)*this->Dimensions[0]); + s3 = this->Heights->GetTuple1(ij[0]+1+(ij[1]+1)*this->Dimensions[0]); + + return (this->Origin[2] + this->HeightOffset + s0*weights[0] + s1*weights[1] + + s2*weights[2] + s3*weights[3]); +} + +//----------------------------------------------------------------------------- +//This method has the side effect of inserting the edge into the queues +void vtkProjectedTerrainPath::ComputeError(vtkIdType edgeId) +{ + vtkEdge &e =(*this->EdgeList)[edgeId]; + double p1[3], p2[3]; + this->Points->GetPoint(e.V1,p1); + this->Points->GetPoint(e.V2,p2); + + // Now evaluate the edge as it passes over the pixel cell edges. The + // interpolation functions are such that the maximum values have to + // take place on the boundary of the cell. We process the cell edges in + // two passes: first the x-edges, then the y-edges. + double negError = VTK_LARGE_FLOAT; + double posError = -VTK_LARGE_FLOAT; + double x[3], loc[2], t, zMap, loc1[2], loc2[2], *x1, *x2, error; + int ij[2], ij1[2], ij2[2], numInt, i, flip; + + // Process the x intersections + if ( p2[0] >= p1[0] ) //sort along x-axis + { + x1 = p1; + x2 = p2; + flip = 0; + } + else + { + x1 = p2; + x2 = p1; + flip = 1; + } + this->GetImageIndex(x1,loc1,ij1); + this->GetImageIndex(x2,loc2,ij2); + + if ( (numInt=ij2[0]-ij1[0]) > 0 ) //if there are any x-intersections + { + for (i=1; i<=numInt; i++) + { + if ( (ij1[0]+i) >= this->Extent[0] ) + { + x[0] = this->Origin[0] + (ij1[0]+i)*this->Spacing[0]; + t = (x[0] - x1[0]) / (x2[0] - x1[0]); + x[1] = x1[1] + t*(x2[1]-x1[1]); + x[2] = x1[2] + t*(x2[2]-x1[2]); + this->GetImageIndex(x,loc,ij); + zMap = this->GetHeight(loc,ij); + error = x[2] - zMap; + if ( error >= 0.0 ) + { + if (error > posError) + { + posError = error; + e.tPos = (flip ? (1-t) : t); + } + } + else + { + if (error < negError) + { + negError = error; + e.tNeg = (flip ? (1-t) : t); + } + } + } //if lying on image + } //for all x-intersection points + } //if x-intersections + + // Process the y intersections + if ( p2[1] >= p1[1] ) //sort along y-axis + { + x1 = p1; + x2 = p2; + flip = 0; + } + else + { + x1 = p2; + x2 = p1; + flip = 1; + } + this->GetImageIndex(x1,loc1,ij1); + this->GetImageIndex(x2,loc2,ij2); + + if ( (numInt=ij2[1]-ij1[1]) > 0 ) //if there are any x-intersections + { + for (i=1; i<=numInt; i++) + { + if ( (ij1[1]+i) >= this->Extent[2] ) + { + x[1] = this->Origin[1] + (ij1[1]+i)*this->Spacing[1]; + t = (x[1] - x1[1]) / (x2[1] - x1[1]); + x[0] = x1[0] + t*(x2[0]-x1[0]); + x[2] = x1[2] + t*(x2[2]-x1[2]); + this->GetImageIndex(x,loc,ij); + zMap = this->GetHeight(loc,ij); + error = x[2] - zMap; + if ( error >= 0.0 ) + { + if (error > posError) + { + posError = error; + e.tPos = (flip ? (1-t) : t); + } + } + else + { + if (error < negError) + { + negError = error; + e.tNeg = (flip ? (1-t) : t); + } + } + } //if lying on image + } //for all x-intersection points + } //if x-intersections + + // Okay, insert the maximum errors for this edge in the queues + if ( posError > 0.0 ) + { + this->PositiveLineError->Insert(-posError,edgeId); + } + if ( negError < 0.0 ) + { + this->NegativeLineError->Insert(negError,edgeId); + } +} + + +//----------------------------------------------------------------------------- +void vtkProjectedTerrainPath::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Projection Mode: "; + if ( this->ProjectionMode == SIMPLE_PROJECTION ) + { + os << "Simple Projection\n"; + } + else if ( this->ProjectionMode == NONOCCLUDED_PROJECTION ) + { + os << "Non-occluded Projection\n"; + } + else //if ( this->ProjectionMode == HUG_PROJECTION ) + { + os << "Hug Projection\n"; + } + + os << indent << "Height Offset: " << this->HeightOffset << "\n"; + os << indent << "Height Tolerance: " << this->HeightTolerance << "\n"; + os << indent << "Maximum Number Of Lines: " + << this->MaximumNumberOfLines << "\n"; + +} diff --git a/Hybrid/vtkProjectedTerrainPath.h b/Hybrid/vtkProjectedTerrainPath.h new file mode 100644 index 0000000..7939422 --- /dev/null +++ b/Hybrid/vtkProjectedTerrainPath.h @@ -0,0 +1,177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProjectedTerrainPath.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProjectedTerrainPath - project a polyline onto a terrain +// .SECTION Description +// vtkProjectedTerrainPath projects an input polyline onto a terrain. (The +// terrain is defined by a 2D height image and is the second input to the +// filter.) The polyline projection is controlled via several modes as +// follows. 1) Simple mode projects the polyline points onto the terrain, +// taking into account the height offset instance variable. 2) Non-occluded +// mode insures that no parts of the polyline are occluded by the terrain +// (e.g. a line passes through a mountain). This may require recursive +// subdivision of the polyline. 3) Hug mode insures that the polyine points +// remain within a constant distance from the surface. This may also require +// recursive subdivision of the polyline. Note that both non-occluded mode +// and hug mode also take into account the height offset, so it is possible +// to create paths that hug terrain a certain distance above it. To use this +// filter, define two inputs: 1) a polyline, and 2) an image whose scalar +// values represent a height field. Then specify the mode, and the height +// offset to use. +// +// An description of the algorithm is as follows. The filter begins by +// projecting the polyline points to the image (offset by the specified +// height offset). If the mode is non-occluded or hug, then the maximum +// error along each line segment is computed and placed into a priority +// queue. Each line segment is then split at the point of maximum error, and +// the two new line segments are evaluated for maximum error. This process +// continues until the line is not occluded by the terrain (non-occluded +// mode) or satisfies the error on variation from the surface (hug +// mode). (Note this process is repeated for each polyline in the +// input. Also, the maximum error is computed in two parts: a maximum +// positive error and maximum negative error. If the polyline is above the +// terrain--i.e., the height offset is positive--in non-occluded or hug mode +// all negative errors are eliminated. If the polyline is below the +// terrain--i.e., the height offset is negative--in non-occluded or hug mode +// all positive errors are eliminated.) +// +// .SECTION Caveats +// This algorithm requires the entire input image to be in memory, hence it +// may not work for extremely large images. +// +// The input height image is assumed to be positioned in the x-y plane so the +// scalar value is the z-coordinate, height value. +// +// A priority queue is used so that the 1) the total number of line segments +// can be controlled, and 2) the algorithm can terminate when the errors in +// the queue are less than the specified error tolerance. +// +// .SECTION See Also +// vtkGreedyTerrainDecimation + +#ifndef __vtkProjectedTerrainPath_h +#define __vtkProjectedTerrainPath_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPriorityQueue; +class vtkImageData; +class vtkEdgeList; +class vtkPoints; + +class VTK_HYBRID_EXPORT vtkProjectedTerrainPath : public vtkPolyDataAlgorithm +{ +public: + // Description: + // Standard methids for printing and determining type information. + vtkTypeRevisionMacro(vtkProjectedTerrainPath,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the class. + static vtkProjectedTerrainPath* New(); + + // Description: + // Specify the second input (the terrain) onto which the polyline(s) should + // be projected. + void SetSource(vtkImageData *source); + vtkImageData *GetSource(); + +//BTX + enum {SIMPLE_PROJECTION=0,NONOCCLUDED_PROJECTION,HUG_PROJECTION}; +//ETX + + // Description: + // Determine how to control the projection process. Simple projection + // just projects the original polyline points. Non-occluded projection + // insures that the polyline does not intersect the terrain surface. + // Hug projection is similar to non-occulded projection except that + // produces a path that is nearly parallel to the terrain (within the + // user specified height tolerance). + vtkSetClampMacro(ProjectionMode,int,SIMPLE_PROJECTION,HUG_PROJECTION); + vtkGetMacro(ProjectionMode,int); + void SetProjectionModeToSimple() + {this->SetProjectionMode(SIMPLE_PROJECTION);} + void SetProjectionModeToNonOccluded() + {this->SetProjectionMode(NONOCCLUDED_PROJECTION);} + void SetProjectionModeToHug() + {this->SetProjectionMode(HUG_PROJECTION);} + + // Description: + // This is the height above (or below) the terrain that the projected + // path should be. Positive values indicate distances above the terrain; + // negative values indicate distances below the terrain. + vtkSetMacro(HeightOffset,double); + vtkGetMacro(HeightOffset,double); + + // Description: + // This is the allowable variation in the altitude of the path + // with respect to the variation in the terrain. It only comes + // into play if the hug projection mode is enabled. + vtkSetClampMacro(HeightTolerance,double,0.0,VTK_LARGE_FLOAT); + vtkGetMacro(HeightTolerance,double); + + // Description: + // This instance variable can be used to limit the total number of line + // segments created during subdivision. Note that the number of input line + // segments will be the minimum number that cab be output. + vtkSetClampMacro(MaximumNumberOfLines,vtkIdType,1,VTK_LARGE_ID); + vtkGetMacro(MaximumNumberOfLines,vtkIdType); + +protected: + vtkProjectedTerrainPath(); + ~vtkProjectedTerrainPath(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + // Supporting methods + void GetImageIndex(double x[3], double loc[2], int ij[2]); + double GetHeight(double loc[2], int ij[2]); + void ComputeError(vtkIdType edgeId); + void RemoveOcclusions(); + void HugTerrain(); + void SplitEdge(vtkIdType eId, double t); + + //ivars that the API addresses + int ProjectionMode; + double HeightOffset; + double HeightTolerance; + vtkIdType MaximumNumberOfLines; + + //Bookeeping arrays + int Dimensions[3]; + int Extent[6]; + double Origin[3]; + double Spacing[3]; + vtkDataArray *Heights; + vtkPoints *Points; + vtkIdType NumLines; + + //Errors above/below terrain. In both instances, negative values are + //inserted because the priority queue puts smallest values on top. + vtkPriorityQueue *PositiveLineError; //errors above terrain + vtkPriorityQueue *NegativeLineError; //errors below terrain + + //This is a PIMPL'd vector representing edges + vtkEdgeList *EdgeList; + +private: + vtkProjectedTerrainPath(const vtkProjectedTerrainPath&); // Not implemented. + void operator=(const vtkProjectedTerrainPath&); // Not implemented. + +}; + +#endif diff --git a/Hybrid/vtkRIBExporter.cxx b/Hybrid/vtkRIBExporter.cxx new file mode 100644 index 0000000..84b0b03 --- /dev/null +++ b/Hybrid/vtkRIBExporter.cxx @@ -0,0 +1,1427 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRIBExporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRIBExporter.h" + +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFieldData.h" +#include "vtkGeometryFilter.h" +#include "vtkImageAppendComponents.h" +#include "vtkImageConstantPad.h" +#include "vtkImageExtractComponents.h" +#include "vtkLightCollection.h" +#include "vtkMapper.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkRIBLight.h" +#include "vtkRIBProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRendererCollection.h" +#include "vtkStructuredPoints.h" +#include "vtkTIFFWriter.h" +#include "vtkTexture.h" + +vtkCxxRevisionMacro(vtkRIBExporter, "$Revision: 1.63 $"); +vtkStandardNewMacro(vtkRIBExporter); + +typedef double RtColor[3]; +typedef double RtPoint[3]; +typedef char *RtPointer; +typedef float RtFloat; + +vtkRIBExporter::vtkRIBExporter() +{ + this->FilePrefix = NULL; + this->FilePtr = NULL; + this->TexturePrefix = NULL; + this->Size[0] = this->Size[1] = -1; + this->PixelSamples[0] = this->PixelSamples[1] = 2; + this->Background = 0; + this->ExportArrays = 0; +} + +vtkRIBExporter::~vtkRIBExporter() +{ + if ( this->FilePrefix ) + { + delete [] this->FilePrefix; + } + if ( this->TexturePrefix ) + { + delete [] this->TexturePrefix; + } +} + +void vtkRIBExporter::WriteData() +{ + vtkRenderer *ren; + vtkActorCollection *ac; + vtkLightCollection *lc; + vtkActor *anActor; + vtkCollection *textures = vtkCollection::New(); + vtkLight *aLight; + vtkTexture *aTexture; + + // make sure the user specified a FilePrefix + if ( this->FilePrefix == NULL) + { + vtkErrorMacro(<< "Please specify file name for the rib file"); + return; + } + + // first make sure there is only one renderer in this rendering window + if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1) + { + vtkErrorMacro(<< "RIB files only support one renderer per window."); + return; + } + + // get the renderer + vtkCollectionSimpleIterator sit; + this->RenderWindow->GetRenderers()->InitTraversal(sit); + ren = this->RenderWindow->GetRenderers()->GetNextRenderer(sit); + + // make sure it has at least one actor + if (ren->GetActors()->GetNumberOfItems() < 1) + { + vtkErrorMacro(<< "no actors found for writing .RIB file."); + return; + } + + char *ribFileName = new char [strlen (this->FilePrefix) + strlen (".rib") + 1]; + sprintf (ribFileName, "%s%s", this->FilePrefix, ".rib"); + + this->FilePtr = fopen (ribFileName, "w"); + if (this->FilePtr == NULL) + { + vtkErrorMacro (<< "Cannot open " << ribFileName); + delete [] ribFileName; + return; + } + + delete [] ribFileName; + + // + // Write Header + // + this->WriteHeader (ren); + + // + // All textures must be made first + // + ac = ren->GetActors(); + vtkCollectionSimpleIterator ait; + for ( ac->InitTraversal (ait); (anActor = ac->GetNextActor(ait)); ) + { + // see if the actor has a mapper. it could be an assembly + if (anActor->GetMapper() == NULL) + { + continue; + } + // if it's invisible, don't make the texture + if ( anActor->GetVisibility () ) + { + aTexture = anActor->GetTexture (); + if (aTexture && + textures->IsItemPresent (aTexture) == 0) { + this->WriteTexture (aTexture); + textures->AddItem (aTexture); + } + } + } + + // + // Write viewport + // + this->WriteViewport (ren, this->Size); + + + // + // Write camera + // + this->WriteCamera (ren->GetActiveCamera ()); + + fprintf (this->FilePtr, "WorldBegin\n"); + + // + // Write all lights + // + lc = ren->GetLights(); + + // + // If there is no light defined, create one + // + lc->InitTraversal(sit); + if (lc->GetNextLight(sit) == NULL) + { + vtkWarningMacro(<< "No light defined, creating one at camera position"); + ren->CreateLight(); + } + + // Create an ambient light + this->WriteAmbientLight (1); + int lightCount = 2; + for (lc->InitTraversal(sit); (aLight = lc->GetNextLight(sit)); ) + { + if (aLight->GetSwitch ()) + { + this->WriteLight(aLight, lightCount++); + } + } + + // + // Write all actors + // + vtkAssemblyNode *node; + ac = ren->GetActors(); + vtkAssemblyPath *apath; + for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); ) + { + for (anActor->InitPathTraversal(); (apath=anActor->GetNextPath()); ) + { + node = apath->GetLastNode(); + if ( node->GetViewProp()->GetVisibility () ) + { + if ( node->GetViewProp()->IsA("vtkActor") ) + { + this->WriteActor((vtkActor *)(node->GetViewProp())); + } + } + } + } + + // RiWorldEnd (); + fprintf (this->FilePtr, "WorldEnd\n"); + // + // Write trailer + // + this->WriteTrailer (); + + // RiEnd (); + fclose (this->FilePtr); + + textures->Delete(); +} + +void vtkRIBExporter::WriteHeader (vtkRenderer *aRen) +{ + + // create a FileName to hold the renderered image + char *imageFileName = new char [strlen (this->FilePrefix) + strlen (".tif") + 1]; + sprintf (imageFileName, "%s%s", this->FilePrefix, ".tif"); + + fprintf (this->FilePtr, "FrameBegin %d\n", 1); + fprintf (this->FilePtr, "Display \"%s\" \"file\" \"rgba\"\n", imageFileName); + fprintf (this->FilePtr, "Declare \"bgcolor\" \"uniform color\"\n"); + if (this->Background) + { + double *color = aRen->GetBackground (); + fprintf (this->FilePtr, "Imager \"background\" \"bgcolor\" [%f %f %f]\n", + color[0], color[1], color[2]); + } + fprintf (this->FilePtr, "PixelSamples %d %d\n", + this->PixelSamples[0], + this->PixelSamples[1]); + + delete [] imageFileName; + +} + +void vtkRIBExporter::WriteTrailer () +{ + fprintf (this->FilePtr, "FrameEnd\n"); +} + +void vtkRIBExporter::WriteProperty (vtkProperty *aProperty, + vtkTexture *aTexture) +{ + char *mapName; + double Ambient, Diffuse, Specular; + double Opacity; + double *DiffuseColor, *SpecularColor; + double Roughness; + RtColor opacity; + Opacity = aProperty->GetOpacity(); + + // set the opacity + opacity[0] = Opacity; + opacity[1] = Opacity; + opacity[2] = Opacity; + fprintf (this->FilePtr, "Opacity [%f %f %f]\n", + opacity[0], opacity[1], opacity[2]); + + // set the color of the surface + DiffuseColor = aProperty->GetDiffuseColor(); + fprintf (this->FilePtr, "Color [%f %f %f]\n", + DiffuseColor[0], DiffuseColor[1], DiffuseColor[2]); + + // set the shader parameters + Ambient = aProperty->GetAmbient(); + Diffuse = aProperty->GetDiffuse(); + Specular = aProperty->GetSpecular(); + + SpecularColor = aProperty->GetSpecularColor(); + Roughness = (RtFloat) (1.0 / aProperty->GetSpecularPower ()); + +// +// if there is a texture map we need to declare it +// + mapName = (char *) NULL; + if (aTexture) + { + mapName = this->GetTextureName(aTexture); + if (mapName) + { + fprintf (this->FilePtr, "Declare \"mapname\" \"uniform string\"\n"); + } + } +// +// Now we need to check to see if an RIBProperty has been specified +// + if (strcmp ("vtkRIBProperty", aProperty->GetClassName ()) == 0) + { + vtkRIBProperty *aRIBProperty = (vtkRIBProperty *) aProperty; + if (aRIBProperty->GetDeclarations ()) + { + fprintf (this->FilePtr, "%s", aRIBProperty->GetDeclarations ()); + } + if (aRIBProperty->GetSurfaceShader ()) + { + fprintf (this->FilePtr, "%s \"%s\" ", "Surface", aRIBProperty->GetSurfaceShader ()); + fprintf (this->FilePtr, "\"Ka\" [%f] ", Ambient); + fprintf (this->FilePtr, "\"Kd\" [%f] ", Diffuse); + fprintf (this->FilePtr, "\"Ks\" [%f] ", Specular); + fprintf (this->FilePtr, "\"roughness\" [%f] ", Roughness); + fprintf (this->FilePtr, "\"specularcolor\" [%f %f %f]", + SpecularColor[0], SpecularColor[1], SpecularColor[2]); + if (mapName) + { + fprintf (this->FilePtr, " \"mapname\" [\"%s\"]", mapName); + } + } + if (aRIBProperty->GetParameters ()) + { + fprintf (this->FilePtr, "%s", aRIBProperty->GetParameters ()); + } + fprintf (this->FilePtr, "\n"); + if (aRIBProperty->GetDisplacementShader ()) + { + fprintf (this->FilePtr, "%s \"%s\" ", "Displacement", aRIBProperty->GetDisplacementShader ()); + fprintf (this->FilePtr, "\"Ka\" [%f] ", Ambient); + fprintf (this->FilePtr, "\"Kd\" [%f] ", Diffuse); + fprintf (this->FilePtr, "\"Ks\" [%f] ", Specular); + fprintf (this->FilePtr, "\"roughness\" [%f] ", Roughness); + fprintf (this->FilePtr, "\"specularcolor\" [%f %f %f]", + SpecularColor[0], SpecularColor[1], SpecularColor[2]); + if (mapName) + { + fprintf (this->FilePtr, " \"mapname\" [\"%s\"]", mapName); + } + if (aRIBProperty->GetParameters ()) + { + fprintf (this->FilePtr, "%s", aRIBProperty->GetParameters ()); + } + fprintf (this->FilePtr, "\n"); + } + } +// Normal Property + else + { + fprintf (this->FilePtr, "Surface \"%s\" ", mapName ? "txtplastic" : "plastic"); + fprintf (this->FilePtr, "\"Ka\" [%f] ", Ambient); + fprintf (this->FilePtr, "\"Kd\" [%f] ", Diffuse); + fprintf (this->FilePtr, "\"Ks\" [%f] ", Specular); + fprintf (this->FilePtr, "\"roughness\" [%f] ", Roughness); + fprintf (this->FilePtr, "\"specularcolor\" [%f %f %f] ", + SpecularColor[0], SpecularColor[1], SpecularColor[2]); + if (mapName) + { + fprintf (this->FilePtr, " \"mapname\" [\"%s\"]", mapName); + } + fprintf (this->FilePtr, "\n"); + } +} + + +void vtkRIBExporter::WriteLight (vtkLight *aLight, int count) +{ + double color[4]; + double *Color; + double *Position, *FocalPoint; + double Intensity; + + // get required info from light + Intensity = aLight->GetIntensity(); + Color = aLight->GetColor(); + color[0] = Intensity * Color[0]; + color[1] = Intensity * Color[1]; + color[2] = Intensity * Color[2]; + color[3] = 1.0; + + FocalPoint = aLight->GetFocalPoint(); + Position = aLight->GetPosition(); + + // + // Now we need to check to see if an RIBLight has been specified + // + if (strcmp ("vtkRIBLight", aLight->GetClassName ()) == 0) + { + if (((vtkRIBLight *) aLight)->GetShadows()) + + { + fprintf (this->FilePtr, "Attribute \"light\" \"shadows\" \"on\"\n"); + } + } + // define the light source + if (!aLight->GetPositional()) + { + fprintf (this->FilePtr, "LightSource \"distantlight\" %d ", count); + fprintf (this->FilePtr, "\"intensity\" [%f] ", Intensity); + fprintf (this->FilePtr, "\"lightcolor\" [%f %f %f] ", + color[0], color[1], color[2]); + fprintf (this->FilePtr, "\"from\" [%f %f %f] ", + Position[0], Position[1], Position[2]); + fprintf (this->FilePtr, "\"to\" [%f %f %f]\n", + FocalPoint[0], FocalPoint[1], FocalPoint[2]); + } + else + { + double coneAngle = aLight->GetConeAngle (); + double exponent = aLight->GetExponent (); + fprintf (this->FilePtr, "LightSource \"spotlight\" %d ", count); + fprintf (this->FilePtr, "\"intensity\" [%f] ", Intensity); + fprintf (this->FilePtr, "\"lightcolor\" [%f %f %f] ", + color[0], color[1], color[2]); + fprintf (this->FilePtr, "\"from\" [%f %f %f] ", + Position[0], Position[1], Position[2]); + fprintf (this->FilePtr, "\"to\" [%f %f %f]\n", + FocalPoint[0], FocalPoint[1], FocalPoint[2]); + fprintf (this->FilePtr, "\"coneangle\" [%f]\n", coneAngle); + fprintf (this->FilePtr, "\"beamdistribution\" [%f]\n", exponent); + fprintf (this->FilePtr, "\"conedeltaangle\" [%f]\n", 0.0); + } + if (strcmp ("vtkRIBLight", aLight->GetClassName ()) == 0) + { + if (((vtkRIBLight *) aLight)->GetShadows()) + { + fprintf (this->FilePtr, "Attribute \"light\" \"shadows\" \"off\"\n"); + } + } +} + +void vtkRIBExporter::WriteAmbientLight (int count) +{ + fprintf (this->FilePtr, "LightSource \"ambientlight\" %d\n", count); +} + +void vtkRIBExporter::WriteViewport (vtkRenderer *ren, int size[2]) +{ + double aspect[2]; + double *vport; + int left,right,bottom,top; + + if (size[0] != -1 || size[1] != -1) + { + vport = ren->GetViewport(); + + left = (int)(vport[0]*(size[0] -1)); + right = (int)(vport[2]*(size[0] - 1)); + + bottom = (int)(vport[1]*(size[1] -1)); + top = (int)(vport[3]*(size[1] - 1)); + + fprintf (this->FilePtr, "Format %d %d 1\n", size[0], size[1]); + + fprintf (this->FilePtr, "CropWindow %f %f %f %f\n", + vport[0], vport[2], vport[1], vport[3]); + + aspect[0] = (double)(right-left+1)/(double)(top-bottom+1); + aspect[1] = 1.0; + fprintf (this->FilePtr, "ScreenWindow %f %f %f %f\n", + -aspect[0], aspect[0], -1.0, 1.0); + } +} + +static void PlaceCamera (FILE *filePtr, RtPoint, RtPoint, double); +static void AimZ (FILE *filePtr, RtPoint); + +void vtkRIBExporter::WriteCamera (vtkCamera *aCamera) +{ + RtPoint direction; + double position[3], focalPoint[3]; + + aCamera->GetPosition (position); + aCamera->GetFocalPoint (focalPoint); + + direction[0] = focalPoint[0] - position[0]; + direction[1] = focalPoint[1] - position[1]; + direction[2] = focalPoint[2] - position[2]; + vtkMath::Normalize (direction); + + RtFloat angle = aCamera->GetViewAngle (); + fprintf (this->FilePtr, "Projection \"perspective\" \"fov\" [%f]\n", angle); + PlaceCamera (this->FilePtr, position, direction, aCamera->GetRoll ()); + + fprintf (this->FilePtr, "Orientation \"rh\"\n"); +} + +/* + * PlaceCamera(): establish a viewpoint, viewing direction and orientation + * for a scene. This routine must be called before RiWorldBegin(). + * position: a point giving the camera position + * direction: a point giving the camera direction relative to position + * roll: an optional rotation of the camera about its direction axis + */ + +static double cameraMatrix[4][4] = { + {-1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} +}; + +void PlaceCamera(FILE *filePtr, RtPoint position, RtPoint direction, double roll) +{ + fprintf (filePtr, "Identity\n"); + fprintf (filePtr, "Transform [%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ]\n", + cameraMatrix[0][0], cameraMatrix[0][1], cameraMatrix[0][2], cameraMatrix[0][3], + cameraMatrix[1][0], cameraMatrix[1][1], cameraMatrix[1][2], cameraMatrix[1][3], + cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2], cameraMatrix[2][3], + cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2], cameraMatrix[3][3]); + + fprintf (filePtr, "Rotate %f %f %f %f\n", -roll, 0.0, 0.0, 1.0); + AimZ(filePtr, direction); + fprintf (filePtr, "Translate %f %f %f\n", + -position[0], -position[1], -position[2]); +} + +/* + * AimZ(): rotate the world so the directionvector points in + * positive z by rotating about the y axis, then x. The cosine + * of each rotation is given by components of the normalized + * direction vector. Before the y rotation the direction vector + * might be in negative z, but not afterward. + */ + +static void +AimZ(FILE *filePtr, RtPoint direction) +{ + double xzlen, yzlen, yrot, xrot; + + if (direction[0]==0 && direction[1]==0 && direction[2]==0) + { + return; + } + /* + * The initial rotation about the y axis is given by the projection of + * the direction vector onto the x,z plane: the x and z components + * of the direction. + */ + xzlen = sqrt(direction[0]*direction[0]+direction[2]*direction[2]); + if (xzlen == 0) + { + yrot = (direction[1] < 0) ? 180 : 0; + } + else + { + yrot = 180*acos(direction[2]/xzlen)/vtkMath::Pi(); + } + /* + * The second rotation, about the x axis, is given by the projection on + * the y,z plane of the y-rotated direction vector: the original y + * component, and the rotated x,z vector from above. + */ + yzlen = sqrt(direction[1]*direction[1]+xzlen*xzlen); + xrot = 180*acos(xzlen/yzlen)/vtkMath::Pi(); /* yzlen should never be 0 */ + + if (direction[1] > 0) + { + fprintf (filePtr, "Rotate %f %f %f %f\n", xrot, 1.0, 0.0, 0.0); + } + else + { + fprintf (filePtr, "Rotate %f %f %f %f\n", -xrot, 1.0, 0.0, 0.0); + } + /* The last rotation declared gets performed first */ + if (direction[0] > 0) + { + fprintf (filePtr, "Rotate %f %f %f %f\n", -yrot, 0.0, 1.0, 0.0); + } + else + { + fprintf (filePtr, "Rotate %f %f %f %f\n", yrot, 0.0, 1.0, 0.0); + } +} + +void vtkRIBExporter::WriteActor(vtkActor *anActor) +{ + vtkDataSet *aDataSet; + vtkPolyData *polyData; + vtkGeometryFilter *geometryFilter = NULL; + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + + // see if the actor has a mapper. it could be an assembly + if (anActor->GetMapper() == NULL) + { + return; + } + + fprintf (this->FilePtr, "AttributeBegin\n"); + + fprintf (this->FilePtr, "TransformBegin\n"); + + // write out the property + this->WriteProperty (anActor->GetProperty (), anActor->GetTexture ()); + + // get the mappers input and matrix + aDataSet = anActor->GetMapper()->GetInput(); + anActor->GetMatrix (matrix); + matrix->Transpose(); + + // insert model transformation + fprintf (this->FilePtr, "ConcatTransform [%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ]\n", + matrix->Element[0][0], matrix->Element[0][1], + matrix->Element[0][2], matrix->Element[0][3], + matrix->Element[1][0], matrix->Element[1][1], + matrix->Element[1][2], matrix->Element[1][3], + matrix->Element[2][0], matrix->Element[2][1], + matrix->Element[2][2], matrix->Element[2][3], + matrix->Element[3][0], matrix->Element[3][1], + matrix->Element[3][2], matrix->Element[3][3]); + + // we really want polydata + if ( aDataSet->GetDataObjectType() != VTK_POLY_DATA ) + { + geometryFilter = vtkGeometryFilter::New(); + geometryFilter->SetInput(aDataSet); + geometryFilter->Update(); + polyData = geometryFilter->GetOutput(); + } + else + { + polyData = (vtkPolyData *)aDataSet; + } + + // Let us start with point data and then we can copy to other + if ( this->ExportArrays ) + { + vtkPointData *pointData = polyData->GetPointData(); + if ( pointData && pointData->GetNumberOfArrays() ) + { + int cc; + for ( cc = 0; cc< pointData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = pointData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + fprintf(this->FilePtr, "Declare \"%s\" \"varying double\"\n", + buffer); + } + } + vtkCellData *cellData = polyData->GetCellData(); + if ( cellData && cellData->GetNumberOfArrays() ) + { + int cc; + for ( cc = 0; cc< cellData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = cellData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + fprintf(this->FilePtr, "Declare \"%s\" \"varying double\"\n", + buffer); + } + } + vtkFieldData *fieldData = polyData->GetFieldData(); + if ( fieldData && fieldData->GetNumberOfArrays() ) + { + int cc; + for ( cc = 0; cc< fieldData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = fieldData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + fprintf(this->FilePtr, "Declare \"%s\" \"varying double\"\n", + buffer); + } + } + } + + if (polyData->GetNumberOfPolys ()) + { + this->WritePolygons (polyData, anActor->GetMapper()->MapScalars(1.0), + anActor->GetProperty ()); + } + if (polyData->GetNumberOfStrips ()) + { + this->WriteStrips (polyData, anActor->GetMapper()->MapScalars(1.0), + anActor->GetProperty ()); + } + fprintf (this->FilePtr, "TransformEnd\n"); + fprintf (this->FilePtr, "AttributeEnd\n"); + if (geometryFilter) + { + geometryFilter->Delete(); + } + matrix->Delete(); +} + +void vtkRIBExporter::WritePolygons (vtkPolyData *polyData, + vtkUnsignedCharArray *c, + vtkProperty *aProperty) +{ + double vertexColors[512][3]; + double *TCoords; + double *normals; + double points[3]; + RtPoint vertexNormals[512]; + RtPoint vertexPoints[512]; + double poly_norm[3]; + double vertexTCoords[512][2]; + vtkIdType *pts = 0; + vtkIdType npts = 0; + int k, kk; + int rep, j, interpolation; + int tDim; + unsigned char *colors; + vtkCellArray *polys; + vtkDataArray *n = NULL; + vtkPoints *p; + vtkPolygon *polygon; + vtkDataArray *t; + + // get the representation + rep = aProperty->GetRepresentation(); + + switch (rep) + { + case VTK_SURFACE: + break; + default: + vtkErrorMacro(<< "Bad representation sent\n"); + break; + } + + // get the shading interpolation + interpolation = aProperty->GetInterpolation(); + + // and draw the display list + polygon = vtkPolygon::New(); + p = polyData->GetPoints(); + polys = polyData->GetPolys(); + + t = polyData->GetPointData()->GetTCoords(); + if ( t ) + { + tDim = t->GetNumberOfComponents(); + if (tDim != 2) + { + vtkDebugMacro(<< "Currently only 2d textures are supported.\n"); + t = NULL; + } + } + + // Get point data + vtkPointData *pointData = polyData->GetPointData(); + vtkCellData *cellData = polyData->GetCellData(); + vtkFieldData *fieldData = polyData->GetFieldData(); + + if ( interpolation == VTK_FLAT || !(polyData->GetPointData()) || + !(n=polyData->GetPointData()->GetNormals()) ) + { + n = 0; + } + + for (polys->InitTraversal(); polys->GetNextCell(npts,pts); ) + { + if (!n) + { + polygon->ComputeNormal(p,npts,pts,poly_norm); + } + + for (j = 0; j < npts; j++) + { + k = j; + if (c) + { + colors = c->GetPointer(4*pts[k]); + vertexColors[k][0] = colors[0] / 255.0; + vertexColors[k][1] = colors[1] / 255.0; + vertexColors[k][2] = colors[2] / 255.0; + } + if (t) + { + TCoords = t->GetTuple (pts[k]); + vertexTCoords[k][0] = TCoords[0]; + // Renderman Textures have origin at upper left + vertexTCoords[k][1] = 1.0 - TCoords[1]; + } + if (n) + { + normals = n->GetTuple (pts[k]); + vertexNormals[k][0] = normals[0]; + vertexNormals[k][1] = normals[1]; + vertexNormals[k][2] = normals[2]; + } + else + { + vertexNormals[k][0] = poly_norm[0]; + vertexNormals[k][1] = poly_norm[1]; + vertexNormals[k][2] = poly_norm[2]; + } + + p->GetPoint(pts[k], points); + vertexPoints[k][0] = points[0]; + vertexPoints[k][1] = points[1]; + vertexPoints[k][2] = points[2]; + } + fprintf (this->FilePtr, "Polygon "); + fprintf (this->FilePtr, "\"P\" ["); + for (kk = 0; kk < npts; kk++) + { + fprintf (this->FilePtr, "%f %f %f ", + vertexPoints[kk][0], vertexPoints[kk][1], vertexPoints[kk][2]); + } + fprintf (this->FilePtr, "] "); + + fprintf (this->FilePtr, "\"N\" ["); + for (kk = 0; kk < npts; kk++) + { + fprintf (this->FilePtr, "%f %f %f ", + vertexNormals[kk][0], vertexNormals[kk][1], vertexNormals[kk][2]); + } + fprintf (this->FilePtr, "] "); + + + if (c) + { + fprintf (this->FilePtr, "\"Cs\" ["); + for (kk = 0; kk < npts; kk++) + { + fprintf (this->FilePtr, "%f %f %f ", + vertexColors[kk][0], vertexColors[kk][1], vertexColors[kk][2]); + } + fprintf (this->FilePtr, "] "); + } + if (t) + { + fprintf (this->FilePtr, "\"st\" ["); + for (kk = 0; kk < npts; kk++) + { + fprintf (this->FilePtr, "%f %f ", + vertexTCoords[kk][0], vertexTCoords[kk][1]); + } + fprintf (this->FilePtr, "] "); + } + + if ( this->ExportArrays ) + { + if ( pointData ) + { + int cc, aa; + ostrstream str_with_warning_C4701; + for ( cc = 0; cc < pointData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = pointData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + str_with_warning_C4701 << "\"" << buffer << "\" ["; + for (kk = 0; kk < npts; kk++) + { + double tuple[3]; + array->GetTuple(pts[kk], tuple); + for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ ) + { + str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa]; + } + } + str_with_warning_C4701 << "] "; + } + str_with_warning_C4701 << ends; + fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() ); + str_with_warning_C4701.rdbuf()->freeze(0); + } + + if ( cellData ) + { + int cc, aa; + ostrstream str_with_warning_C4701; + for ( cc = 0; cc < cellData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = cellData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + str_with_warning_C4701 << "\"" << buffer << "\" ["; + for (kk = 0; kk < npts; kk++) + { + double tuple[3]; + array->GetTuple(pts[kk], tuple); + for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ ) + { + str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa]; + } + } + str_with_warning_C4701 << "] "; + } + str_with_warning_C4701 << ends; + fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() ); + str_with_warning_C4701.rdbuf()->freeze(0); + } + + if ( fieldData ) + { + int cc, aa; + ostrstream str_with_warning_C4701; + + for ( cc = 0; cc < fieldData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = fieldData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + str_with_warning_C4701 << "\"" << buffer << "\" ["; + for (kk = 0; kk < npts; kk++) + { + double tuple[3]; + array->GetTuple(pts[kk], tuple); + for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ ) + { + str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa]; + } + } + str_with_warning_C4701 << "] "; + } + str_with_warning_C4701 << ends; + fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() ); + str_with_warning_C4701.rdbuf()->freeze(0); + } + } + + fprintf (this->FilePtr, "\n"); + } + polygon->Delete(); +} + +void vtkRIBExporter::WriteStrips (vtkPolyData *polyData, + vtkUnsignedCharArray *c, + vtkProperty *aProperty) +{ + double vertexColors[512][3]; + double *TCoords; + double *normals; + double points[3]; + RtPoint vertexNormals[512]; + RtPoint vertexPoints[512]; + double poly_norm[3]; + double vertexTCoords[512][2]; + vtkIdType *pts = 0; + vtkIdType npts = 0; + int p1, p2, p3; + int k, kk; + int rep, j, interpolation; + int tDim; + unsigned char *colors; + vtkCellArray *strips; + vtkDataArray *n = NULL; + vtkPoints *p; + vtkDataArray *t; + vtkPolygon *polygon; + vtkIdType idx[3]; + + // get the representation + rep = aProperty->GetRepresentation(); + + switch (rep) + { + case VTK_SURFACE: + break; + default: + vtkErrorMacro(<< "Bad representation sent\n"); + break; + } + + // get the shading interpolation + interpolation = aProperty->GetInterpolation(); + + // and draw the display list + p = polyData->GetPoints(); + strips = polyData->GetStrips(); + polygon = vtkPolygon::New(); + + t = polyData->GetPointData()->GetTCoords(); + if ( t ) + { + tDim = t->GetNumberOfComponents(); + if (tDim != 2) + { + vtkDebugMacro(<< "Currently only 2d textures are supported.\n"); + t = NULL; + } + } + + if ( interpolation == VTK_FLAT || !(polyData->GetPointData()) || + !(n=polyData->GetPointData()->GetNormals()) ) + { + n = 0; + } + + + // Get point data + vtkPointData *pointData = polyData->GetPointData(); + vtkCellData *cellData = polyData->GetCellData(); + vtkFieldData *fieldData = polyData->GetFieldData(); + + // each iteration returns a triangle strip + for (strips->InitTraversal(); strips->GetNextCell(npts,pts); ) + { + // each triangle strip is converted into a bunch of triangles + p1 = pts[0]; + p2 = pts[1]; + p3 = pts[2]; + for (j = 0; j < (npts-2); j++) + { + if (j%2) + { + idx[0] = p2; + idx[1] = p1; + idx[2] = p3; + } + else + { + idx[0] = p1; + idx[1] = p2; + idx[2] = p3; + } + + if (!n) + { + polygon->ComputeNormal (p, 3, idx, poly_norm); + } + + // build colors, texture coordinates and normals for the triangle + for (k = 0; k < 3; k++) + { + if (c) + { + colors = c->GetPointer(4*idx[k]); + vertexColors[k][0] = colors[0] / 255.0; + vertexColors[k][1] = colors[1] / 255.0; + vertexColors[k][2] = colors[2] / 255.0; + } + if (t) + { + TCoords = t->GetTuple (idx[k]); + vertexTCoords[k][0] = TCoords[0]; + // Renderman Textures have origin at upper left + vertexTCoords[k][1] = 1.0 - TCoords[1]; + } + if (n) + { + normals = n->GetTuple (idx[k]); + vertexNormals[k][0] = normals[0]; + vertexNormals[k][1] = normals[1]; + vertexNormals[k][2] = normals[2]; + } + else + { + vertexNormals[k][0] = poly_norm[0]; + vertexNormals[k][1] = poly_norm[1]; + vertexNormals[k][2] = poly_norm[2]; + } + p->GetPoint(idx[k], points); + vertexPoints[k][0] = points[0]; + vertexPoints[k][1] = points[1]; + vertexPoints[k][2] = points[2]; + } + fprintf (this->FilePtr, "Polygon "); + fprintf (this->FilePtr, "\"P\" ["); + for (kk = 0; kk < 3; kk++) + { + fprintf (this->FilePtr, "%f %f %f ", + vertexPoints[kk][0], vertexPoints[kk][1], vertexPoints[kk][2]); + } + fprintf (this->FilePtr, "] "); + + fprintf (this->FilePtr, "\"N\" ["); + for (kk = 0; kk < 3; kk++) + { + fprintf (this->FilePtr, "%f %f %f ", + vertexNormals[kk][0], vertexNormals[kk][1], vertexNormals[kk][2]); + } + fprintf (this->FilePtr, "] "); + + if (c) + { + fprintf (this->FilePtr, "\"Cs\" ["); + for (kk = 0; kk < 3; kk++) + { + fprintf (this->FilePtr, "%f %f %f ", + vertexColors[kk][0], vertexColors[kk][1], vertexColors[kk][2]); + } + fprintf (this->FilePtr, "] "); + } + if (t) + { + fprintf (this->FilePtr, "\"st\" ["); + for (kk = 0; kk < 3; kk++) + { + fprintf (this->FilePtr, "%f %f ", + vertexTCoords[kk][0], vertexTCoords[kk][1]); + } + fprintf (this->FilePtr, "] "); + } + + if ( this->ExportArrays ) + { + if ( pointData ) + { + int cc, aa; + ostrstream str_with_warning_C4701; + for ( cc = 0; cc < pointData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = pointData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + str_with_warning_C4701 << "\"" << buffer << "\" ["; + for (kk = 0; kk < npts; kk++) + { + double tuple[3]; + array->GetTuple(pts[kk], tuple); + for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ ) + { + str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa]; + } + } + str_with_warning_C4701 << "] "; + } + str_with_warning_C4701 << ends; + fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() ); + str_with_warning_C4701.rdbuf()->freeze(0); + } + + if ( cellData ) + { + int cc, aa; + ostrstream str_with_warning_C4701; + for ( cc = 0; cc < cellData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = cellData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + str_with_warning_C4701 << "\"" << buffer << "\" ["; + for (kk = 0; kk < npts; kk++) + { + double tuple[3]; + array->GetTuple(pts[kk], tuple); + for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ ) + { + str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa]; + } + } + str_with_warning_C4701 << "] "; + } + str_with_warning_C4701 << ends; + fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() ); + str_with_warning_C4701.rdbuf()->freeze(0); + } + + if ( fieldData ) + { + int cc, aa; + ostrstream str_with_warning_C4701; + for ( cc = 0; cc < fieldData->GetNumberOfArrays(); cc ++ ) + { + vtkDataArray *array = fieldData->GetArray(cc); + char buffer[1024]; + this->ModifyArrayName(buffer, array->GetName()); + str_with_warning_C4701 << "\"" << buffer << "\" ["; + for (kk = 0; kk < npts; kk++) + { + double tuple[3]; + array->GetTuple(pts[kk], tuple); + for ( aa = 0; aa < array->GetNumberOfComponents(); aa++ ) + { + str_with_warning_C4701 << ((!kk &&!aa) ? "" : " ") << tuple[aa]; + } + } + str_with_warning_C4701 << "] "; + } + str_with_warning_C4701 << ends; + fprintf ( this->FilePtr, "%s", str_with_warning_C4701.str() ); + str_with_warning_C4701.rdbuf()->freeze(0); + } + } + fprintf (this->FilePtr, "\n"); + // Get ready for next triangle + p1 = p2; + p2 = p3; + if (j+3 < npts) + { + p3 = pts[j+3]; + } + } + } + polygon->Delete(); +} + +void vtkRIBExporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->FilePrefix) + { + os << indent << "FilePrefix: " << this->FilePrefix << "\n"; + } + else + { + os << indent << "FilePrefix: (none)\n"; + } + if (this->TexturePrefix) + { + os << indent << "TexturePrefix: " << this->TexturePrefix << "\n"; + } + else + { + os << indent << "TexturePrefix: (none)\n"; + } + os << indent << "Background: " << (this->Background ? "On\n" : "Off\n"); + os << indent << "Size: " << this->Size[0] << " " << this->Size[1] << "\n"; + os << indent << "PixelSamples: " << this->PixelSamples[0] << " " + << this->PixelSamples[1] << "\n"; + os << indent << "Export Arrays: " << (this->ExportArrays ? "On" : "Off") + << "\n"; +} + +void vtkRIBExporter::WriteTexture (vtkTexture *aTexture) +{ + vtkDataArray *scalars; + vtkDataArray *mappedScalars; + int *size; + int xsize, ysize; + unsigned short xs,ys; + +// RtToken wrap = aTexture->GetRepeat () ? RI_PERIODIC : RI_CLAMP; +// RiMakeTexture (this->GetTIFFName (aTexture), +// this->GetTextureName (aTexture), +// wrap, wrap, +// RiBoxFilter, +// 1, 1, +// RI_NULL); + const char *wrap = aTexture->GetRepeat () ? "periodic" : "clamp"; + fprintf (this->FilePtr, "MakeTexture \"%s\" ", this->GetTIFFName (aTexture)); + fprintf (this->FilePtr, "\"%s\" ", this->GetTextureName (aTexture)); + fprintf (this->FilePtr, "\"%s\" \"%s\" ", wrap, wrap); + fprintf (this->FilePtr, "\"%s\" 1 1\n", "box"); + + // do an Update and get some info + if (aTexture->GetInput() == NULL) + { + vtkErrorMacro(<< "texture has no input!\n"); + return; + } + aTexture->GetInput()->Update(); + size = aTexture->GetInput()->GetDimensions(); + scalars = aTexture->GetInput()->GetPointData()->GetScalars(); + + // make sure scalars are non null + if (!scalars) + { + vtkErrorMacro(<< "No scalar values found for texture input!\n"); + return; + } + + // make sure using unsigned char data of color scalars type + if (aTexture->GetMapColorScalarsThroughLookupTable () || + (scalars->GetDataType() != VTK_UNSIGNED_CHAR) ) + { + mappedScalars = aTexture->GetMappedScalars (); + } + else + { + mappedScalars = scalars; + } + + // we only support 2d texture maps right now + // so one of the three sizes must be 1, but it + // could be any of them, so lets find it + if (size[0] == 1) + { + xsize = size[1]; ysize = size[2]; + } + else + { + xsize = size[0]; + if (size[1] == 1) + { + ysize = size[2]; + } + else + { + ysize = size[1]; + if (size[2] != 1) + { + vtkErrorMacro(<< "3D texture maps currently are not supported!\n"); + return; + } + } + } + + // xsize and ysize must be a power of 2 in OpenGL + xs = (unsigned short)xsize; + ys = (unsigned short)ysize; + while (!(xs & 0x01)) + { + xs = xs >> 1; + } + while (!(ys & 0x01)) + { + ys = ys >> 1; + } + if ((xs > 1)||(ys > 1)) + { + vtkWarningMacro(<< "Texture map's width and height must be a power of two in RenderMan\n"); + } + + vtkTIFFWriter *aWriter = vtkTIFFWriter::New(); + vtkImageConstantPad *icp = NULL; + vtkImageExtractComponents *iec = NULL; + vtkImageAppendComponents *iac1 = NULL; + vtkImageAppendComponents *iac2 = NULL; + + vtkStructuredPoints *anImage = vtkStructuredPoints::New(); + anImage->SetDimensions (xsize, ysize, 1); + anImage->SetUpdateExtent(0,xsize-1,0,ysize-1, 0, 0); + anImage->SetScalarType(mappedScalars->GetDataType()); + anImage->GetPointData()->SetScalars (mappedScalars); + int bpp = mappedScalars->GetNumberOfComponents(); + anImage->SetNumberOfScalarComponents (bpp); + + // renderman and bmrt seem to require r,g,b and alpha in all their + // texture maps. So if our tmap doesn't have the right components + // we add them + if (bpp == 1) // needs intensity intensity and alpha + { + iac1 = vtkImageAppendComponents::New(); + iac2 = vtkImageAppendComponents::New(); + icp = vtkImageConstantPad::New(); + + iac1->SetInput(0, anImage); + iac1->SetInput(1, anImage); + iac2->SetInput(0, iac1->GetOutput ()); + iac2->SetInput(1, anImage); + icp->SetInput( iac2->GetOutput ()); + icp->SetConstant(255); + icp->SetOutputNumberOfScalarComponents(4); + + aWriter->SetInput (icp->GetOutput()); + } + else if (bpp == 2) // needs intensity intensity + { + iec = vtkImageExtractComponents::New(); + iac1 = vtkImageAppendComponents::New(); + iac2 = vtkImageAppendComponents::New(); + + iec->SetInput( anImage); + iec->SetComponents (0); + iac1->SetInput(0, iec->GetOutput ()); + iac1->SetInput(1, anImage); + iac2->SetInput(0, iec->GetOutput ()); + iac2->SetInput(1, iac1->GetOutput ()); + + aWriter->SetInput (iac2->GetOutput()); + } + else if (bpp == 3) // needs alpha + { + icp = vtkImageConstantPad::New(); + icp->SetInput( anImage); + icp->SetConstant(255); + icp->SetOutputNumberOfScalarComponents(4); + aWriter->SetInput (icp->GetOutput()); + } + else // needs nothing + { + aWriter->SetInput (anImage); + } + aWriter->SetFileName (this->GetTIFFName (aTexture)); + aWriter->Write (); + + if (bpp == 1) + { + iac1->Delete (); + iac2->Delete (); + icp->Delete (); + } + else if (bpp == 2) + { + iec->Delete (); + iac1->Delete (); + iac2->Delete (); + } + else if (bpp == 3) + { + icp->Delete (); + } + + aWriter->Delete(); + anImage->Delete(); +} + +static char tiffName[4096]; +static char textureName[4096]; + +char *vtkRIBExporter::GetTIFFName (vtkTexture *aTexture) +{ + sprintf (tiffName, "%s_%p_%d.tif", this->TexturePrefix, (void *) aTexture, (int) aTexture->GetMTime ()); + return tiffName; +} + +char *vtkRIBExporter::GetTextureName (vtkTexture *aTexture) +{ + sprintf (textureName, "%s_%p_%d.txt", this->TexturePrefix, (void *) aTexture, (int) aTexture->GetMTime ()); + return textureName; +} + +void vtkRIBExporter::ModifyArrayName(char *newname, const char* name) +{ + if ( !newname ) + { + return; + } + if ( !name ) + { + *newname = 0; + return; + } + int cc = 0; + for ( cc =0; name[cc]; cc++ ) + { + if ( name[cc] >= 'A' && name[cc] <= 'Z' || + name[cc] >= '0' && name[cc] <= '9' || + name[cc] >= 'a' && name[cc] <= 'z' ) + { + newname[cc] = name[cc]; + } + else + { + newname[cc] = '_'; + } + } + newname[cc] = 0; +} diff --git a/Hybrid/vtkRIBExporter.h b/Hybrid/vtkRIBExporter.h new file mode 100644 index 0000000..eae08c8 --- /dev/null +++ b/Hybrid/vtkRIBExporter.h @@ -0,0 +1,166 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRIBExporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRIBExporter - export a scene into RenderMan RIB format. +// .SECTION Description +// vtkRIBExporter is a concrete subclass of vtkExporter that writes a +// Renderman .RIB files. The input specifies a vtkRenderWindow. All +// visible actors and lights will be included in the rib file. The +// following file naming conventions apply: +// rib file - FilePrefix.rib +// image file created by RenderMan - FilePrefix.tif +// texture files - TexturePrefix_0xADDR_MTIME.tif +// This object does NOT generate an image file. The user must run either +// RenderMan or a RenderMan emulator like Blue Moon Ray Tracer (BMRT). +// vtk properties are convert to Renderman shaders as follows: +// Normal property, no texture map - plastic.sl +// Normal property with texture map - txtplastic.sl +// These two shaders must be compiled by the rendering package being +// used. vtkRIBExporter also supports custom shaders. The shaders are +// written using the Renderman Shading Language. See "The Renderman +// Companion", ISBN 0-201-50868, 1989 for details on writing shaders. +// vtkRIBProperty specifies the declarations and parameter settings for +// custom shaders. +// Tcl Example: generate a rib file for the current rendering. +// vtkRIBExporter myRIB +// myRIB SetInput $renWin +// myRIB SetFIlePrefix mine +// myRIB Write +// This will create a file mine.rib. After running this file through +// a Renderman renderer a file mine.tif will contain the rendered image. +// +// .SECTION See Also +// vtkExporter vtkRIBProperty + + +#ifndef __vtkRIBExporter_h +#define __vtkRIBExporter_h + +#include "vtkExporter.h" + +class vtkActor; +class vtkCamera; +class vtkLight; +class vtkPolyData; +class vtkProperty; +class vtkRenderer; +class vtkTexture; +class vtkUnsignedCharArray; + +class VTK_HYBRID_EXPORT vtkRIBExporter : public vtkExporter +{ +public: + static vtkRIBExporter *New(); + vtkTypeRevisionMacro(vtkRIBExporter,vtkExporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description + // Specify the size of the image for RenderMan. If none is specified, the + // size of the render window will be used. + vtkSetVector2Macro(Size,int); + vtkGetVectorMacro(Size,int,2); + + // Description + // Specify the sampling rate for the rendering. Default is 2 2. + vtkSetVector2Macro(PixelSamples,int); + vtkGetVectorMacro(PixelSamples,int,2); + + // Description: + // Specify the prefix of the files to write out. The resulting file names + // will have .RIB appended to them. + vtkSetStringMacro(FilePrefix); + vtkGetStringMacro(FilePrefix); + + // Description: + // Specify the prefix of any generated texture files. + vtkSetStringMacro(TexturePrefix); + vtkGetStringMacro(TexturePrefix); + + // Description: + // Set/Get the background flag. Default is 0 (off). + // If set, the rib file will contain an + // image shader that will use the renderer window's background + // color. Normally, RenderMan does generate backgrounds. Backgrounds are + // composited into the scene with the tiffcomp program that comes with + // Pixar's RenderMan Toolkit. In fact, Pixar's Renderman will accept an + // image shader but only sets the alpha of the background. Images created + // this way will still have a black background but contain an alpha of 1 + // at all pixels and CANNOT be subsequently composited with other images + // using tiffcomp. However, other RenderMan compliant renderers like + // Blue Moon Ray Tracing (BMRT) do allow image shaders and properly set + // the background color. If this sounds too confusing, use the following + // rules: If you are using Pixar's Renderman, leave the Background + // off. Otherwise, try setting BackGroundOn and see if you get the + // desired results. + vtkSetMacro(Background,int); + vtkGetMacro(Background,int); + vtkBooleanMacro(Background,int); + + // Description: + // Set or get the ExportArrays. If ExportArrays is set, then + // all point data, field data, and cell data arrays will get + // exported together with polygons. + vtkSetClampMacro(ExportArrays, int, 0, 1); + vtkBooleanMacro(ExportArrays, int); + vtkGetMacro(ExportArrays, int); + +protected: + vtkRIBExporter(); + ~vtkRIBExporter(); + + int Background; + int Size[2]; + int PixelSamples[2]; + + // Description: + // This variable defines whether the arrays are exported or not. + int ExportArrays; + + // Description: + // Write the RIB header. + void WriteHeader (vtkRenderer *aRen); + void WriteTrailer (); + void WriteTexture (vtkTexture *aTexture); + void WriteViewport (vtkRenderer *aRenderer, int size[2]); + void WriteCamera (vtkCamera *aCamera); + void WriteLight (vtkLight *aLight, int count); + void WriteAmbientLight (int count); + void WriteProperty (vtkProperty *aProperty, vtkTexture *aTexture); + void WritePolygons (vtkPolyData *pd, vtkUnsignedCharArray *colors, + vtkProperty *aProperty); + void WriteStrips (vtkPolyData *pd, vtkUnsignedCharArray *colors, + vtkProperty *aProperty); + + void WriteData(); + void WriteActor(vtkActor *anActor); + + // Description: + // Since additional variables are sent to the shader as + // variables, and their names are used in the shader, these + // names have to follow C naming convention. This method + // modifies array name so that you can use it in shader. + void ModifyArrayName(char *newname, const char* name); + + char *GetTextureName (vtkTexture *aTexture); + char *GetTIFFName (vtkTexture *aTexture); + char *FilePrefix; + FILE *FilePtr; + char *TexturePrefix; +private: + vtkRIBExporter(const vtkRIBExporter&); // Not implemented. + void operator=(const vtkRIBExporter&); // Not implemented. +}; + +#endif + diff --git a/Hybrid/vtkRIBLight.cxx b/Hybrid/vtkRIBLight.cxx new file mode 100644 index 0000000..0d00563 --- /dev/null +++ b/Hybrid/vtkRIBLight.cxx @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRIBLight.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRIBLight.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkRIBLight, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkRIBLight); + +vtkRIBLight::vtkRIBLight () +{ + this->Shadows = 0; + // create a vtkLight that can be rendered + this->Light = vtkLight::New (); +} + +vtkRIBLight::~vtkRIBLight() +{ + if (this->Light) + { + this->Light->Delete(); + } +} + +void vtkRIBLight::Render(vtkRenderer *ren, int index) +{ + int ref; + + // Copy this light's ivars into the light to be rendered + ref = this->Light->GetReferenceCount(); + this->Light->DeepCopy(this); + //this->Light->SetDeleteMethod(NULL); + this->Light->SetReferenceCount(ref); + + // Render the light + this->Light->Render (ren, index); +} + +void vtkRIBLight::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + + os << indent << "Shadows: " << (this->Shadows ? "On\n" : "Off\n"); +} + diff --git a/Hybrid/vtkRIBLight.h b/Hybrid/vtkRIBLight.h new file mode 100644 index 0000000..745aa08 --- /dev/null +++ b/Hybrid/vtkRIBLight.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRIBLight.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRIBLight - RIP Light +// .SECTION Description +// vtkRIBLight is a subclass of vtkLight that allows the user to +// specify light source shaders and shadow casting lights for use with RenderMan. +// +// .SECTION See Also +// vtkRIBExporter + +#ifndef __vtkRIBLight_h +#define __vtkRIBLight_h + +#include "vtkLight.h" + +class vtkRIBRenderer; + +class VTK_HYBRID_EXPORT vtkRIBLight : public vtkLight +{ +public: + static vtkRIBLight *New(); + vtkTypeRevisionMacro(vtkRIBLight,vtkLight); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkBooleanMacro(Shadows,int); + vtkSetMacro(Shadows,int); + vtkGetMacro(Shadows,int); + + void Render(vtkRenderer *ren, int index); +protected: + vtkRIBLight(); + ~vtkRIBLight(); + + vtkLight *Light; + int Shadows; +private: + vtkRIBLight(const vtkRIBLight&); // Not implemented. + void operator=(const vtkRIBLight&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkRIBProperty.cxx b/Hybrid/vtkRIBProperty.cxx new file mode 100644 index 0000000..8d71318 --- /dev/null +++ b/Hybrid/vtkRIBProperty.cxx @@ -0,0 +1,200 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRIBProperty.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRIBProperty.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkRIBProperty, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkRIBProperty); + +vtkRIBProperty::vtkRIBProperty () +{ + this->Declarations = NULL; + this->Parameters = NULL; + this->SurfaceShader = new char[strlen("plastic") + 1]; + strcpy (this->SurfaceShader, "plastic"); + this->DisplacementShader = NULL; + // create a vtkProperty that can be rendered + this->Property = vtkProperty::New (); +} + +vtkRIBProperty::~vtkRIBProperty() +{ + if (this->SurfaceShader) + { + delete [] this->SurfaceShader; + } + if (this->DisplacementShader) + { + delete [] this->DisplacementShader; + } + if (this->Declarations) + { + delete [] this->Declarations; + } + if (this->Property) + { + this->Property->Delete (); + } + if (this->Parameters) + { + delete [] this->Parameters; + } +} + +void vtkRIBProperty::Render(vtkActor *anActor, vtkRenderer *ren) +{ + int ref; + + // Copy this property's ivars into the property to be rendered + ref = this->Property->GetReferenceCount(); + this->Property->DeepCopy(this); + //this->Property->SetDeleteMethod(NULL); + this->Property->SetReferenceCount(ref); + + // Render the property + this->Property->Render (anActor, ren); +} + +void vtkRIBProperty::SetVariable (char *variable, char *value) +{ + if (this->Declarations) + { + delete [] this->Declarations; + } + + // format of line is: Declare "variable" "type"\n + this->Declarations = new char [strlen ("Declare ") + + strlen (variable) + + strlen (value) + + 8]; + + sprintf (this->Declarations, "Declare \"%s\" \"%s\"\n", variable, value); + this->Modified (); +} + +void vtkRIBProperty::AddVariable (char *variable, char *value) +{ + if (this->Declarations == NULL) + { + this->SetVariable (variable, value); + } + else + { + char *newVariable = new char [strlen ("Declare ") + + strlen (variable) + + strlen (value) + + 8]; + + sprintf (newVariable, "Declare \"%s\" \"%s\"\n", variable, value); + char *oldDeclarations = this->Declarations; + + this->Declarations = new char [strlen (oldDeclarations) + strlen (newVariable) + 1]; + strcpy (this->Declarations, oldDeclarations); + strcat (this->Declarations, newVariable); + delete [] oldDeclarations; + delete [] newVariable; + this->Modified (); + } +} + +void vtkRIBProperty::SetParameter (char *parameter, char *value) +{ + if (this->Parameters) + { + delete [] this->Parameters; + } + + // format of line is: "parameter" "value" + this->Parameters = new char [strlen (parameter) + + strlen (value) + + 7]; + + sprintf (this->Parameters, " \"%s\" [%s]", parameter, value); + this->Modified (); +} + +void vtkRIBProperty::AddParameter (char *Parameter, char *value) +{ + if (this->Parameters == NULL) + { + this->SetParameter (Parameter, value); + } + else + { + char *newParameter = new char [strlen (Parameter) + + strlen (value) + + 7]; + + sprintf (newParameter, " \"%s\" [%s]", Parameter, value); + char *oldParameters = this->Parameters; + + this->Parameters = new char [strlen (oldParameters) + strlen (newParameter) + 1]; + strcpy (this->Parameters, oldParameters); + strcat (this->Parameters, newParameter); + delete [] oldParameters; + delete [] newParameter; + this->Modified (); + } +} + +char *vtkRIBProperty::GetParameters () +{ + return this->Parameters; +} + +char *vtkRIBProperty::GetDeclarations () +{ + return this->Declarations; +} + +void vtkRIBProperty::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->SurfaceShader) + { + os << indent << "SurfaceShader: " << this->SurfaceShader << "\n"; + } + else + { + os << indent << "SurfaceShader: (none)\n"; + } + if (this->DisplacementShader) + { + os << indent << "DisplacementShader: " << this->DisplacementShader << "\n"; + } + else + { + os << indent << "DisplacementShader: (none)\n"; + } + if (this->Declarations) + { + os << indent << "Declarations: " << this->Declarations; + } + else + { + os << indent << "Declarations: (none)\n"; + } + if (this->Parameters) + { + os << indent << "Parameters: " << this->Parameters; + } + else + { + os << indent << "Parameters: (none)\n"; + } + +} + diff --git a/Hybrid/vtkRIBProperty.h b/Hybrid/vtkRIBProperty.h new file mode 100644 index 0000000..b763354 --- /dev/null +++ b/Hybrid/vtkRIBProperty.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRIBProperty.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRIBProperty - RIP Property +// .SECTION Description +// vtkRIBProperty is a subclass of vtkProperty that allows the user to +// specify named shaders for use with RenderMan. Both a surface shader +// and displacement shader can be specified. Parameters for the shaders +// can be declared and set. +// +// .SECTION See Also +// vtkRIBExporter + +#ifndef __vtkRIBProperty_h +#define __vtkRIBProperty_h + +#include "vtkProperty.h" + +class vtkRIBRenderer; + +class VTK_HYBRID_EXPORT vtkRIBProperty : public vtkProperty +{ +public: + static vtkRIBProperty *New(); + vtkTypeRevisionMacro(vtkRIBProperty,vtkProperty); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the name of a surface shader. + vtkSetStringMacro(SurfaceShader); + vtkGetStringMacro(SurfaceShader); + + // Description: + // Specify the name of a displacement shader. + vtkSetStringMacro(DisplacementShader); + vtkGetStringMacro(DisplacementShader); + + // Description: + // Specify declarations for variables.. + void SetVariable (char *variable, char *declaration); + void AddVariable (char *variable, char *declaration); + + // Description: + // Get variable declarations + char *GetDeclarations (); + + // Description: + // Specify parameter values for variables. + void SetParameter (char *parameter, char *value); + void AddParameter (char *parameter, char *value); + + // Description: + // Get parameters. + char *GetParameters (); + +protected: + vtkRIBProperty(); + ~vtkRIBProperty(); + + void Render(vtkActor *a, vtkRenderer *ren); + vtkProperty *Property; + char *SurfaceShader; + char *DisplacementShader; + char *Declarations; + char *Parameters; +private: + vtkRIBProperty(const vtkRIBProperty&); // Not implemented. + void operator=(const vtkRIBProperty&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkRenderLargeImage.cxx b/Hybrid/vtkRenderLargeImage.cxx new file mode 100644 index 0000000..01d736e --- /dev/null +++ b/Hybrid/vtkRenderLargeImage.cxx @@ -0,0 +1,435 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderLargeImage.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRenderLargeImage.h" + +#include "vtkCamera.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkRendererCollection.h" +#include "vtkActor2DCollection.h" +#include "vtkActor2D.h" +#include "vtkProp.h" +#include +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkRenderLargeImage, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkRenderLargeImage); + +vtkCxxSetObjectMacro(vtkRenderLargeImage,Input,vtkRenderer); +//---------------------------------------------------------------------------- +// 2D Actors need to be rescaled and shifted about for each tile +// use this helper class to make life easier. +class vtkRenderLargeImage2DHelperClass { +public: + // maintain a list of 2D actors + vtkActor2DCollection *storedActors; + // maintain lists of their vtkCoordinate objects + vtkCollection *coord1s; + vtkCollection *coord2s; + // Store the display coords for adjustment during tiling + vtkstd::vector< vtkstd::pair > coords1; + vtkstd::vector< vtkstd::pair > coords2; + // + vtkRenderLargeImage2DHelperClass() + { + storedActors = vtkActor2DCollection::New(); + coord1s = vtkCollection::New(); + coord2s = vtkCollection::New(); + } + ~vtkRenderLargeImage2DHelperClass() + { + coord1s->RemoveAllItems(); + coord2s->RemoveAllItems(); + storedActors->RemoveAllItems(); + coord1s->Delete(); + coord2s->Delete(); + storedActors->Delete(); + } +}; +//---------------------------------------------------------------------------- +vtkRenderLargeImage::vtkRenderLargeImage() +{ + this->Input = NULL; + this->Magnification = 3; + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); + this->storedData = new vtkRenderLargeImage2DHelperClass(); +} +//---------------------------------------------------------------------------- +vtkRenderLargeImage::~vtkRenderLargeImage() +{ + if (this->Input) + { + this->Input->UnRegister(this); + this->Input = NULL; + } + delete this->storedData; +} + +//---------------------------------------------------------------------------- +void vtkRenderLargeImage::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Input ) + { + os << indent << "Input:\n"; + this->Input->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Input: (none)\n"; + } + + os << indent << "Magnification: " << this->Magnification << "\n"; +} + + +//---------------------------------------------------------------------------- +vtkImageData* vtkRenderLargeImage::GetOutput() +{ + return vtkImageData::SafeDownCast(this->GetOutputDataObject(0)); +} + +//---------------------------------------------------------------------------- +int vtkRenderLargeImage::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->RequestData(request, inputVector, outputVector); + return 1; + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + this->RequestInformation(request, inputVector, outputVector); + return 1; + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +// Description: +// This method returns the largest region that can be generated. +void vtkRenderLargeImage::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + if (this->Input == NULL ) + { + vtkErrorMacro(<<"Please specify a renderer as input!"); + return; + } + + // set the extent, if the VOI has not been set then default to + int wExt[6]; + wExt[0] = 0; wExt[2] = 0; wExt[4] = 0; wExt[5] = 0; + wExt[1] = this->Magnification* + this->Input->GetRenderWindow()->GetSize()[0] - 1; + wExt[3] = this->Magnification* + this->Input->GetRenderWindow()->GetSize()[1] - 1; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExt, 6); + + // set the spacing + outInfo->Set(vtkDataObject::SPACING(),1.0, 1.0, 1.0); + + // set the origin. + outInfo->Set(vtkDataObject::ORIGIN(),0.0, 0.0, 0.0); + + // set the scalar components + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 3); +} + +//---------------------------------------------------------------------------- +// Description: +// This function reads a region from a file. The regions extent/axes +// are assumed to be the same as the file extent/order. +void vtkRenderLargeImage::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *data = + vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + data->SetExtent( + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT())); + data->AllocateScalars(); + int inExtent[6]; + vtkIdType inIncr[3]; + int *size; + int inWindowExtent[4]; + double viewAngle, parallelScale, windowCenter[2]; + vtkCamera *cam; + unsigned char *pixels, *outPtr; + int x, y, row; + int rowSize, rowStart, rowEnd, colStart, colEnd; + int doublebuffer; + int swapbuffers = 0; + + if (this->GetOutput()->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro("mismatch in scalar types!"); + return; + } + + // Get the requested extents. + this->GetOutput()->GetUpdateExtent(inExtent); + + // get and transform the increments + data->GetIncrements(inIncr); + + // get the size of the render window + size = this->Input->GetRenderWindow()->GetSize(); + + // convert the request into windows + inWindowExtent[0] = inExtent[0]/size[0]; + inWindowExtent[1] = inExtent[1]/size[0]; + inWindowExtent[2] = inExtent[2]/size[1]; + inWindowExtent[3] = inExtent[3]/size[1]; + + this->Rescale2DActors(); + + // store the old view angle & set the new + cam = this->Input->GetActiveCamera(); + cam->GetWindowCenter(windowCenter); + viewAngle = cam->GetViewAngle(); + parallelScale = cam->GetParallelScale(); + cam->SetViewAngle(asin(sin(viewAngle*3.1415926/360.0)/this->Magnification) + * 360.0 / 3.1415926); + cam->SetParallelScale(parallelScale/this->Magnification); + + // are we double buffering? If so, read from back buffer .... + doublebuffer = this->Input->GetRenderWindow()->GetDoubleBuffer(); + if (doublebuffer) + { + // save swap buffer state to restore later + swapbuffers = this->Input->GetRenderWindow()->GetSwapBuffers(); + this->Input->GetRenderWindow()->SetSwapBuffers(0); + } + + // render each of the tiles required to fill this request + for (y = inWindowExtent[2]; y <= inWindowExtent[3]; y++) + { + for (x = inWindowExtent[0]; x <= inWindowExtent[1]; x++) + { + cam->SetWindowCenter(x*2 - this->Magnification*(1-windowCenter[0]) + 1, + y*2 - this->Magnification*(1-windowCenter[1]) + 1); + // shift 2D actors to correct origin for this tile + this->Shift2DActors(size[0]*x, size[1]*y); + // Render + this->Input->GetRenderWindow()->Render(); + pixels = this->Input->GetRenderWindow()->GetPixelData(0,0,size[0] - 1, + size[1] - 1, + !doublebuffer); + + // now stuff the pixels into the data row by row + colStart = inExtent[0] - x*size[0]; + if (colStart < 0) + { + colStart = 0; + } + colEnd = size[0] - 1; + if (colEnd > (inExtent[1] - x*size[0])) + { + colEnd = inExtent[1] - x*size[0]; + } + rowSize = colEnd - colStart + 1; + + // get the output pointer and do arith on it if necc + outPtr = + (unsigned char *)data->GetScalarPointer(inExtent[0],inExtent[2],0); + outPtr = outPtr + (x*size[0] - inExtent[0])*inIncr[0] + + (y*size[1] - inExtent[2])*inIncr[1]; + + rowStart = inExtent[2] - y*size[1]; + if (rowStart < 0) + { + rowStart = 0; + } + rowEnd = size[1] - 1; + if (rowEnd > (inExtent[3] - y*size[1])) + { + rowEnd = (inExtent[3] - y*size[1]); + } + for (row = rowStart; row <= rowEnd; row++) + { + memcpy(outPtr + row*inIncr[1] + colStart*inIncr[0], + pixels + row*size[0]*3 + colStart*3, rowSize*3); + } + // free the memory + delete [] pixels; + } + } + + // restore the state of the SwapBuffers bit before we mucked with it. + if (doublebuffer && swapbuffers) + { + this->Input->GetRenderWindow()->SetSwapBuffers(swapbuffers); + } + + cam->SetViewAngle(viewAngle); + cam->SetParallelScale(parallelScale); + cam->SetWindowCenter(windowCenter[0],windowCenter[1]); + this->Restore2DActors(); +} +//---------------------------------------------------------------------------- +int vtkRenderLargeImage::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} +//---------------------------------------------------------------------------- +// This code is designed to handle multiple renders even though +// RenderLargeImage currently only handles one explicitly. +//---------------------------------------------------------------------------- +void vtkRenderLargeImage::Rescale2DActors() +{ + vtkActor2D *actor; + vtkProp *aProp; + vtkRenderer *aren; + vtkPropCollection *pc; + vtkRendererCollection *rc; + vtkCoordinate *c1, *c2; + vtkCoordinate *n1, *n2; + int *p1, *p2; + double d1[3], d2[3]; + // + rc = this->Input->GetRenderWindow()->GetRenderers(); + for (rc->InitTraversal(); (aren = rc->GetNextItem()); ) + { + pc = aren->GetViewProps(); + if (pc) + { + for ( pc->InitTraversal(); (aProp = pc->GetNextProp()); ) + { + actor = vtkActor2D::SafeDownCast((aProp)); + if (actor) + { + // put the actor in our list for retrieval later + this->storedData->storedActors->AddItem(actor); + // Copy all existing coordinate stuff + n1 = actor->GetPositionCoordinate(); + n2 = actor->GetPosition2Coordinate(); + c1 = vtkCoordinate::New(); + c2 = vtkCoordinate::New(); + c1->SetCoordinateSystem(n1->GetCoordinateSystem()); + c1->SetReferenceCoordinate(n1->GetReferenceCoordinate()); + c1->SetReferenceCoordinate(n1->GetReferenceCoordinate()); + c1->SetValue(n1->GetValue()); + c2->SetCoordinateSystem(n2->GetCoordinateSystem()); + c2->SetReferenceCoordinate(n2->GetReferenceCoordinate()); + c2->SetValue(n2->GetValue()); + this->storedData->coord1s->AddItem(c1); + this->storedData->coord2s->AddItem(c2); + c1->Delete(); + c2->Delete(); + // work out the position in new magnified pixels + p1 = n1->GetComputedDisplayValue(aren); + p2 = n2->GetComputedDisplayValue(aren); + d1[0] = p1[0]*this->Magnification; + d1[1] = p1[1]*this->Magnification; + d1[2] = 0.0; + d2[0] = p2[0]*this->Magnification; + d2[1] = p2[1]*this->Magnification; + d2[2] = 0.0; + this->storedData->coords1.push_back( + vtkstd::pair(static_cast(d1[0]), static_cast(d1[1])) ); + this->storedData->coords2.push_back( + vtkstd::pair(static_cast(d2[0]), static_cast(d2[1])) ); + // Make sure they have no dodgy offsets + n1->SetCoordinateSystemToDisplay(); + n2->SetCoordinateSystemToDisplay(); + n1->SetReferenceCoordinate(NULL); + n2->SetReferenceCoordinate(NULL); + n1->SetValue(d1[0], d1[1]); + n2->SetValue(d2[0], d2[1]); + // + } + } + } + } + return; +} +//---------------------------------------------------------------------------- +// On each tile we must subtract the origin of each actor to ensure +// it appears in the correct relative location +void vtkRenderLargeImage::Shift2DActors(int x, int y) +{ + vtkActor2D *actor; + vtkCoordinate *c1, *c2; + double d1[3], d2[3]; + int i; + // + for (this->storedData->storedActors->InitTraversal(), i=0; (actor = this->storedData->storedActors->GetNextItem()); i++) + { + c1 = actor->GetPositionCoordinate(); + c2 = actor->GetPosition2Coordinate(); + c1->GetValue(d1); + c2->GetValue(d2); + d1[0] = this->storedData->coords1[i].first - x; + d1[1] = this->storedData->coords1[i].second - y; + d2[0] = this->storedData->coords2[i].first - x; + d2[1] = this->storedData->coords2[i].second - y; + c1->SetValue(d1); + c2->SetValue(d2); + } + return; +} +//---------------------------------------------------------------------------- +// On each tile we must subtract the origin of each actor to ensure +// it appears in the corrrect relative location +void vtkRenderLargeImage::Restore2DActors() +{ + vtkActor2D *actor; + vtkCoordinate *c1, *c2; + vtkCoordinate *n1, *n2; + int i; + // + for (this->storedData->storedActors->InitTraversal(), i=0; (actor = this->storedData->storedActors->GetNextItem()); i++) + { + c1 = actor->GetPositionCoordinate(); + c2 = actor->GetPosition2Coordinate(); + n1 = vtkCoordinate::SafeDownCast(this->storedData->coord1s->GetItemAsObject(i)); + n2 = vtkCoordinate::SafeDownCast(this->storedData->coord2s->GetItemAsObject(i)); + c1->SetCoordinateSystem(n1->GetCoordinateSystem()); + c1->SetReferenceCoordinate(n1->GetReferenceCoordinate()); + c1->SetReferenceCoordinate(n1->GetReferenceCoordinate()); + c1->SetValue(n1->GetValue()); + c2->SetCoordinateSystem(n2->GetCoordinateSystem()); + c2->SetReferenceCoordinate(n2->GetReferenceCoordinate()); + c2->SetValue(n2->GetValue()); + } + this->storedData->coord1s->RemoveAllItems(); + this->storedData->coord2s->RemoveAllItems(); + this->storedData->storedActors->RemoveAllItems(); +} +//---------------------------------------------------------------------------- diff --git a/Hybrid/vtkRenderLargeImage.h b/Hybrid/vtkRenderLargeImage.h new file mode 100644 index 0000000..54e04e8 --- /dev/null +++ b/Hybrid/vtkRenderLargeImage.h @@ -0,0 +1,90 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderLargeImage.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRenderLargeImage - Use tiling to generate a large rendering +// .SECTION Description +// vtkRenderLargeImage provides methods needed to read a region from a file. + + +#ifndef __vtkRenderLargeImage_h +#define __vtkRenderLargeImage_h + +#include "vtkAlgorithm.h" +#include "vtkImageData.h" // makes things a bit easier + +class vtkRenderer; +class vtkActor2DCollection; +class vtkCollection; +class vtkRenderLargeImage2DHelperClass; + +class VTK_HYBRID_EXPORT vtkRenderLargeImage : public vtkAlgorithm +{ +public: + static vtkRenderLargeImage *New(); + vtkTypeRevisionMacro(vtkRenderLargeImage,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The magnification of the current render window + vtkSetMacro(Magnification,int); + vtkGetMacro(Magnification,int); + + // Description: + // Indicates what renderer to get the pixel data from. + virtual void SetInput(vtkRenderer*); + + // Description: + // Returns which renderer is being used as the source for the pixel data. + vtkGetObjectMacro(Input,vtkRenderer); + + // Description: + // Get the output data object for a port on this algorithm. + vtkImageData* GetOutput(); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkRenderLargeImage(); + ~vtkRenderLargeImage(); + + int Magnification; + vtkRenderer *Input; + void RequestData(vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + void RequestInformation (vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + + // Adjust the coordinates of all 2D actors to fit new window size + void Rescale2DActors(); + // Shift each actor according to the tile we are rendering + void Shift2DActors(int x, int y); + // put them all back to their previous state when finished. + void Restore2DActors(); + // 2D Actors need to be rescaled and shifted about for each tile + // use this helper class to make life easier. + vtkRenderLargeImage2DHelperClass *storedData; + +private: + vtkRenderLargeImage(const vtkRenderLargeImage&); // Not implemented. + void operator=(const vtkRenderLargeImage&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkThinPlateSplineTransform.cxx b/Hybrid/vtkThinPlateSplineTransform.cxx new file mode 100644 index 0000000..42959f3 --- /dev/null +++ b/Hybrid/vtkThinPlateSplineTransform.cxx @@ -0,0 +1,796 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThinPlateSplineTransform.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkThinPlateSplineTransform.h" + +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkThinPlateSplineTransform, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkThinPlateSplineTransform); + +//------------------------------------------------------------------------ +// some dull matrix things + +inline double** vtkNewMatrix(int rows, int cols) +{ + double *matrix = new double[rows*cols]; + double **m = new double *[rows]; + for(int i = 0; i < rows; i++) + { + m[i] = &matrix[i*cols]; + } + return m; +} + +//------------------------------------------------------------------------ +inline void vtkDeleteMatrix(double **m) +{ + delete [] *m; + delete [] m; +} + +//------------------------------------------------------------------------ +inline void vtkZeroMatrix(double **m, int rows, int cols) +{ + for(int i = 0; i < rows; i++) + { + for(int j = 0; j < cols; j++) + { + m[i][j] = 0.0; + } + } +} + +//------------------------------------------------------------------------ +inline void vtkMatrixMultiply(double **a, double **b, double **c, + int arows, int acols, int brows, int bcols) +{ + if(acols != brows) + { + return; // acols must equal br otherwise we can't proceed + } + + // c must have size arows*bcols (we assume this) + + for(int i = 0; i < arows; i++) + { + for(int j = 0; j < bcols; j++) + { + c[i][j] = 0.0; + for(int k = 0; k < acols; k++) + { + c[i][j] += a[i][k]*b[k][j]; + } + } + } +} + +//------------------------------------------------------------------------ +inline void vtkMatrixTranspose(double **a, double **b, int rows, int cols) +{ + for(int i = 0; i < rows; i++) + { + for(int j = 0; j < cols; j++) + { + double tmp = a[i][j]; + b[i][j] = a[j][i]; + b[j][i] = tmp; + } + } +} + +//------------------------------------------------------------------------ +vtkThinPlateSplineTransform::vtkThinPlateSplineTransform() +{ + this->SourceLandmarks=NULL; + this->TargetLandmarks=NULL; + this->Sigma = 1.0; + + // If the InverseFlag is set, then we use an iterative + // method to invert the transformation. + // The InverseTolerance sets the precision to which we want to + // calculate the inverse. + this->InverseTolerance = 0.001; + this->InverseIterations = 500; + + this->Basis = -1; + this->SetBasisToR2LogR(); + + this->NumberOfPoints = 0; + this->MatrixW = NULL; +} + +//------------------------------------------------------------------------ +vtkThinPlateSplineTransform::~vtkThinPlateSplineTransform() +{ + if (this->SourceLandmarks) + { + this->SourceLandmarks->Delete(); + } + if (this->TargetLandmarks) + { + this->TargetLandmarks->Delete(); + } + if (this->MatrixW) + { + vtkDeleteMatrix(this->MatrixW); + this->MatrixW = NULL; + } +} + +//------------------------------------------------------------------------ +void vtkThinPlateSplineTransform::SetSourceLandmarks(vtkPoints *source) +{ + if (this->SourceLandmarks == source) + { + return; + } + + if (this->SourceLandmarks) + { + this->SourceLandmarks->Delete(); + } + + source->Register(this); + this->SourceLandmarks = source; + + this->Modified(); +} + +//------------------------------------------------------------------------ +void vtkThinPlateSplineTransform::SetTargetLandmarks(vtkPoints *target) +{ + if (this->TargetLandmarks == target) + { + return; + } + + if (this->TargetLandmarks) + { + this->TargetLandmarks->Delete(); + } + + target->Register(this); + this->TargetLandmarks = target; + this->Modified(); +} + +//------------------------------------------------------------------------ +unsigned long vtkThinPlateSplineTransform::GetMTime() +{ + unsigned long result = this->vtkWarpTransform::GetMTime(); + unsigned long mtime; + + if (this->SourceLandmarks) + { + mtime = this->SourceLandmarks->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + if (this->TargetLandmarks) + { + mtime = this->TargetLandmarks->GetMTime(); + if (mtime > result) + { + result = mtime; + } + } + return result; +} + +//------------------------------------------------------------------------ +void vtkThinPlateSplineTransform::InternalUpdate() +{ + if (this->SourceLandmarks == NULL || this->TargetLandmarks == NULL) + { + if (this->MatrixW) + { + vtkDeleteMatrix(this->MatrixW); + } + this->MatrixW = NULL; + this->NumberOfPoints = 0; + return; + } + + if (this->SourceLandmarks->GetNumberOfPoints() != + this->TargetLandmarks->GetNumberOfPoints()) + { + vtkErrorMacro("Update: Source and Target Landmarks contain a different number of points"); + return; + } + + const vtkIdType N = this->SourceLandmarks->GetNumberOfPoints(); + const int D = 3; // dimensions + + // the output weights matrix + double **W = vtkNewMatrix(N+D+1,D); + double **A = &W[N+1]; // the linear rotation + scale matrix + double *C = W[N]; // the linear translation + + if (N >= 3) + { + // Notation and inspiration from: + // Fred L. Bookstein (1997) "Shape and the Information in Medical Images: + // A Decade of the Morphometric Synthesis" Computer Vision and Image + // Understanding 66(2):97-118 + // and online work published by Tim Cootes (http://www.wiau.man.ac.uk/~bim) + + // the input matrices + double **L = vtkNewMatrix(N+D+1,N+D+1); + double **X = vtkNewMatrix(N+D+1,D); + + // build L + // will leave the bottom-right corner with zeros + vtkZeroMatrix(L,N+D+1,N+D+1); + + int q,c; + double p[3],p2[3]; + double dx,dy,dz; + double r; + double (*phi)(double) = this->BasisFunction; + + for(q = 0; q < N; q++) + { + this->SourceLandmarks->GetPoint(q,p); + // fill in the top-right and bottom-left corners of L (Q) + L[N][q] = L[q][N] = 1.0; + L[N+1][q] = L[q][N+1] = p[0]; + L[N+2][q] = L[q][N+2] = p[1]; + L[N+3][q] = L[q][N+3] = p[2]; + // fill in the top-left corner of L (K), using symmetry + for(c = 0; c < q; c++) + { + this->SourceLandmarks->GetPoint(c,p2); + dx = p[0]-p2[0]; dy = p[1]-p2[1]; dz = p[2]-p2[2]; + r = sqrt(dx*dx + dy*dy + dz*dz); + L[q][c] = L[c][q] = phi(r/this->Sigma); + } + } + + // build X + vtkZeroMatrix(X,N+D+1,D); + for (q = 0; q < N; q++) + { + this->TargetLandmarks->GetPoint(q,p); + X[q][0] = p[0]; + X[q][1] = p[1]; + X[q][2] = p[2]; + } + + // solve for W, where W = Inverse(L)*X; + + // this is done via eigenvector decomposition so + // that we can avoid singular values + // W = V*Inverse(w)*U*X + + double *values = new double[N+D+1]; + double **V = vtkNewMatrix(N+D+1,N+D+1); + double **w = vtkNewMatrix(N+D+1,N+D+1); + double **U = L; // reuse the space + vtkMath::JacobiN(L,N+D+1,values,V); + vtkMatrixTranspose(V,U,N+D+1,N+D+1); + + vtkIdType i, j; + double maxValue = 0.0; // maximum eigenvalue + for (i = 0; i < N+D+1; i++) + { + double tmp = fabs(values[i]); + if (tmp > maxValue) + { + maxValue = tmp; + } + } + + for (i = 0; i < N+D+1; i++) + { + for (j = 0; j < N+D+1; j++) + { + w[i][j] = 0.0; + } + // here's the trick: don't invert the singular values + if (fabs(values[i]/maxValue) > 1e-16) + { + w[i][i] = 1.0/values[i]; + } + } + delete [] values; + + vtkMatrixMultiply(U,X,W,N+D+1,N+D+1,N+D+1,D); + vtkMatrixMultiply(w,W,X,N+D+1,N+D+1,N+D+1,D); + vtkMatrixMultiply(V,X,W,N+D+1,N+D+1,N+D+1,D); + + vtkDeleteMatrix(V); + vtkDeleteMatrix(w); + vtkDeleteMatrix(U); + vtkDeleteMatrix(X); + + // now the linear portion of the warp must be checked + // (this is a very poor check for now) + if (fabs(vtkMath::Determinant3x3((double (*)[3]) *A)) < 1e-16) + { + for (i = 0; i < 3; i++) + { + if (sqrt(A[0][i]*A[0][i] + A[1][i]*A[1][i] + A[2][i]*A[2][i]) + < 1e-16) + { + A[0][i] = A[1][i] = A[2][i] = A[i][0] = A[i][1] = A[i][2] = 0; + A[i][i] = 1.0; + } + } + } + } + // special cases, I added these to ensure that this class doesn't + // misbehave if the user supplied fewer than 3 landmarks + else // (N < 3) + { + vtkIdType i,j; + // set nonlinear portion of transformation to zero + for (i = 0; i < N; i++) + { + for (j = 0; j < D; j++) + { + W[i][j] = 0; + } + } + + if (N == 2) + { // two landmarks, construct a similarity transformation + double s0[3],t0[3],s1[3],t1[3]; + this->SourceLandmarks->GetPoint(0,s0); + this->TargetLandmarks->GetPoint(0,t0); + this->SourceLandmarks->GetPoint(1,s1); + this->TargetLandmarks->GetPoint(1,t1); + + double ds[3],dt[3],as[3],at[3]; + double rs = 0, rt = 0; + for (i = 0; i < 3; i++) + { + as[i] = (s0[i] + s1[i])/2; // average of endpoints + ds[i] = s1[i] - s0[i]; // vector between points + rs += ds[i]*ds[i]; + at[i] = (t0[i] + t1[i])/2; + dt[i] = t1[i] - t0[i]; + rt += dt[i]*dt[i]; + } + + // normalize the two vectors + rs = sqrt(rs); + ds[0] /= rs; ds[1] /= rs; ds[2] /= rs; + rt = sqrt(rt); + dt[0] /= rt; dt[1] /= rt; dt[2] /= rt; + + double w,x,y,z; + // take dot & cross product + w = ds[0]*dt[0] + ds[1]*dt[1] + ds[2]*dt[2]; + x = ds[1]*dt[2] - ds[2]*dt[1]; + y = ds[2]*dt[0] - ds[0]*dt[2]; + z = ds[0]*dt[1] - ds[1]*dt[0]; + + double r = sqrt(x*x + y*y + z*z); + double theta = atan2(r,w); + + // construct quaternion + w = cos(theta/2); + if (r != 0) + { + r = sin(theta/2)/r; + x = x*r; + y = y*r; + z = z*r; + } + else // rotation by 180 degrees + { + // rotate around a vector perpendicular to ds + vtkMath::Perpendiculars(ds,dt,0,0); + r = sin(theta/2); + x = dt[0]*r; + y = dt[1]*r; + z = dt[2]*r; + } + + // now r is scale factor for matrix + r = rt/rs; + + // build a rotation + scale matrix + A[0][0] = (w*w + x*x - y*y - z*z)*r; + A[0][1] = (x*y + w*z)*2*r; + A[0][2] = (x*z - w*y)*2*r; + + A[1][0] = (x*y - w*z)*2*r; + A[1][1] = (w*w - x*x + y*y - z*z)*r; + A[1][2] = (y*z + w*x)*2*r; + + A[2][0] = (x*z + w*y)*2*r; + A[2][1] = (y*z - w*x)*2*r; + A[2][2] = (w*w - x*x - y*y + z*z)*r; + + // include the translation + C[0] = at[0] - as[0]*A[0][0] - as[1]*A[1][0] - as[2]*A[2][0]; + C[1] = at[1] - as[0]*A[0][1] - as[1]*A[1][1] - as[2]*A[2][1]; + C[2] = at[2] - as[0]*A[0][2] - as[1]*A[1][2] - as[2]*A[2][2]; + } + else if (N == 1) // one landmark, translation only + { + double p[3],p2[3]; + this->SourceLandmarks->GetPoint(0,p); + this->TargetLandmarks->GetPoint(0,p2); + + for (i = 0; i < D; i++) + { + for (j = 0; j < D; j++) + { + A[i][j] = 0; + } + A[i][i] = 1; + C[i] = p2[i] - p[i]; + } + } + + else // if no landmarks, set to identity + { + for (i = 0; i < D; i++) + { + for (j = 0; j < D; j++) + { + A[i][j] = 0; + } + A[i][i] = 1; + C[i] = 0; + } + } + } + + // left in for debug purposes + /* + cerr << "W =\n"; + for (int i = 0; i < N+1+D; i++) + { + cerr << W[i][0] << ' ' << W[i][1] << ' ' << W[i][2] << '\n'; + } + cerr << "\n"; + */ + + if (this->MatrixW) + { + vtkDeleteMatrix(this->MatrixW); + } + this->MatrixW = W; + this->NumberOfPoints = N; +} + +//------------------------------------------------------------------------ +// The matrix W was created by Update. Not much has to be done to +// apply the transform: do an affine transformation, then do +// perturbations based on the landmarks. +template +inline void vtkThinPlateSplineForwardTransformPoint(vtkThinPlateSplineTransform *self, + double **W, int N, + double (*phi)(double), + const T point[3], T output[3]) +{ + if (N == 0) + { + output[0] = point[0]; + output[1] = point[1]; + output[2] = point[2]; + return; + } + + double *C = W[N]; + double **A = &W[N+1]; + + double dx,dy,dz; + double p[3]; + double U,r; + double invSigma = 1.0/self->GetSigma(); + + double x = 0, y = 0, z = 0; + + vtkPoints *sourceLandmarks = self->GetSourceLandmarks(); + + // do the nonlinear stuff + for(vtkIdType i = 0; i < N; i++) + { + sourceLandmarks->GetPoint(i,p); + dx = point[0]-p[0]; dy = point[1]-p[1]; dz = point[2]-p[2]; + r = sqrt(dx*dx + dy*dy + dz*dz); + U = phi(r*invSigma); + x += U*W[i][0]; + y += U*W[i][1]; + z += U*W[i][2]; + } + + // finish off with the affine transformation + x += C[0] + point[0]*A[0][0] + point[1]*A[1][0] + point[2]*A[2][0]; + y += C[1] + point[0]*A[0][1] + point[1]*A[1][1] + point[2]*A[2][1]; + z += C[2] + point[0]*A[0][2] + point[1]*A[1][2] + point[2]*A[2][2]; + + output[0] = x; + output[1] = y; + output[2] = z; +} + +void vtkThinPlateSplineTransform::ForwardTransformPoint(const double point[3], + double output[3]) +{ + vtkThinPlateSplineForwardTransformPoint(this, this->MatrixW, + this->NumberOfPoints, + this->BasisFunction, + point, output); +} + +void vtkThinPlateSplineTransform::ForwardTransformPoint(const float point[3], + float output[3]) +{ + vtkThinPlateSplineForwardTransformPoint(this, this->MatrixW, + this->NumberOfPoints, + this->BasisFunction, + point, output); +} + +//---------------------------------------------------------------------------- +// calculate the thin plate spline as well as the jacobian +template +inline void vtkThinPlateSplineForwardTransformDerivative( + vtkThinPlateSplineTransform *self, + double **W, int N, + double (*phi)(double, double&), + const T point[3], T output[3], + T derivative[3][3]) +{ + if (N == 0) + { + for (int i = 0; i < 3; i++) + { + output[i] = point[i]; + derivative[i][0] = derivative[i][1] = derivative[i][2] = 0.0; + derivative[i][i] = 1.0; + } + return; + } + + double *C = W[N]; + double **A = &W[N+1]; + + double dx,dy,dz; + double p[3]; + double r, U, f, Ux, Uy, Uz; + double x = 0, y = 0, z = 0; + double invSigma = 1.0/self->GetSigma(); + + derivative[0][0] = derivative[0][1] = derivative[0][2] = 0; + derivative[1][0] = derivative[1][1] = derivative[1][2] = 0; + derivative[2][0] = derivative[2][1] = derivative[2][2] = 0; + + vtkPoints *sourceLandmarks = self->GetSourceLandmarks(); + + // do the nonlinear stuff + for(vtkIdType i = 0; i < N; i++) + { + sourceLandmarks->GetPoint(i,p); + dx = point[0]-p[0]; dy = point[1]-p[1]; dz = point[2]-p[2]; + r = sqrt(dx*dx + dy*dy + dz*dz); + + // get both U and its derivative and do the sigma-mangling + U = 0; + f = 0; + if (r != 0) + { + U = phi(r*invSigma,f); + f *= invSigma/r; + } + + Ux = f*dx; + Uy = f*dy; + Uz = f*dz; + + x += U*W[i][0]; + y += U*W[i][1]; + z += U*W[i][2]; + + derivative[0][0] += Ux*W[i][0]; + derivative[0][1] += Uy*W[i][0]; + derivative[0][2] += Uz*W[i][0]; + derivative[1][0] += Ux*W[i][1]; + derivative[1][1] += Uy*W[i][1]; + derivative[1][2] += Uz*W[i][1]; + derivative[2][0] += Ux*W[i][2]; + derivative[2][1] += Uy*W[i][2]; + derivative[2][2] += Uz*W[i][2]; + } + + // finish with the affine transformation + x += C[0] + point[0]*A[0][0] + point[1]*A[1][0] + point[2]*A[2][0]; + y += C[1] + point[0]*A[0][1] + point[1]*A[1][1] + point[2]*A[2][1]; + z += C[2] + point[0]*A[0][2] + point[1]*A[1][2] + point[2]*A[2][2]; + + output[0] = x; + output[1] = y; + output[2] = z; + + derivative[0][0] += A[0][0]; + derivative[0][1] += A[1][0]; + derivative[0][2] += A[2][0]; + derivative[1][0] += A[0][1]; + derivative[1][1] += A[1][1]; + derivative[1][2] += A[2][1]; + derivative[2][0] += A[0][2]; + derivative[2][1] += A[1][2]; + derivative[2][2] += A[2][2]; +} + +void vtkThinPlateSplineTransform::ForwardTransformDerivative( + const double point[3], + double output[3], + double derivative[3][3]) +{ + vtkThinPlateSplineForwardTransformDerivative(this, this->MatrixW, + this->NumberOfPoints, + this->BasisDerivative, + point, output, derivative); +} + +void vtkThinPlateSplineTransform::ForwardTransformDerivative( + const float point[3], + float output[3], + float derivative[3][3]) +{ + vtkThinPlateSplineForwardTransformDerivative(this, this->MatrixW, + this->NumberOfPoints, + this->BasisDerivative, + point, output, derivative); +} + +//------------------------------------------------------------------------ +void vtkThinPlateSplineTransform::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Sigma: " << this->Sigma << "\n"; + os << indent << "Basis: " << this->GetBasisAsString() << "\n"; + os << indent << "Source Landmarks: " << this->SourceLandmarks << "\n"; + if (this->SourceLandmarks) + { + this->SourceLandmarks->PrintSelf(os,indent.GetNextIndent()); + } + os << indent << "Target Landmarks: " << this->TargetLandmarks << "\n"; + if (this->TargetLandmarks) + { + this->TargetLandmarks->PrintSelf(os,indent.GetNextIndent()); + } +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkThinPlateSplineTransform::MakeTransform() +{ + return vtkThinPlateSplineTransform::New(); +} + +//---------------------------------------------------------------------------- +void vtkThinPlateSplineTransform::InternalDeepCopy( + vtkAbstractTransform *transform) +{ + vtkThinPlateSplineTransform *t = (vtkThinPlateSplineTransform *)transform; + + this->SetInverseTolerance(t->InverseTolerance); + this->SetInverseIterations(t->InverseIterations); + this->SetSigma(t->Sigma); + this->SetBasis(t->GetBasis()); + this->SetSourceLandmarks(t->SourceLandmarks); + this->SetTargetLandmarks(t->TargetLandmarks); + + if (this->InverseFlag != t->InverseFlag) + { + this->InverseFlag = t->InverseFlag; + this->Modified(); + } +} + +//------------------------------------------------------------------------ +// a very basic radial basis function +double vtkRBFr(double r) +{ + return r; +} + +// calculate both phi(r) its derivative wrt r +double vtkRBFDRr(double r, double &dUdr) +{ + dUdr = 1; + return r; +} + +//------------------------------------------------------------------------ +// the standard 2D thin plate spline basis function +double vtkRBFr2logr(double r) +{ + if (r) + { + return r*r*log(r); + } + else + { + return 0; + } +} + +// calculate both phi(r) its derivative wrt r +double vtkRBFDRr2logr(double r, double &dUdr) +{ + if (r) + { + double tmp = log(r); + dUdr = r*(1+2*tmp); + return r*r*tmp; + } + else + { + dUdr = 0; + return 0; + } +} + +//------------------------------------------------------------------------ +void vtkThinPlateSplineTransform::SetBasis(int basis) +{ + if (basis == this->Basis) + { + return; + } + + switch (basis) + { + case VTK_RBF_CUSTOM: + break; + case VTK_RBF_R: + this->BasisFunction = &vtkRBFr; + this->BasisDerivative = &vtkRBFDRr; + break; + case VTK_RBF_R2LOGR: + this->BasisFunction = &vtkRBFr2logr; + this->BasisDerivative = &vtkRBFDRr2logr; + break; + default: + vtkErrorMacro(<< "SetBasisFunction: Unrecognized basis function"); + break; + } + + this->Basis = basis; + this->Modified(); +} + +//------------------------------------------------------------------------ +const char *vtkThinPlateSplineTransform::GetBasisAsString() +{ + switch (this->Basis) + { + case VTK_RBF_CUSTOM: + return "Custom"; + case VTK_RBF_R: + return "R"; + case VTK_RBF_R2LOGR: + return "R2LogR"; + } + return "Unknown"; +} + + + + + + diff --git a/Hybrid/vtkThinPlateSplineTransform.h b/Hybrid/vtkThinPlateSplineTransform.h new file mode 100644 index 0000000..f27f06e --- /dev/null +++ b/Hybrid/vtkThinPlateSplineTransform.h @@ -0,0 +1,149 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkThinPlateSplineTransform.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkThinPlateSplineTransform - a nonlinear warp transformation +// .SECTION Description +// vtkThinPlateSplineTransform describes a nonlinear warp transform defined +// by a set of source and target landmarks. Any point on the mesh close to a +// source landmark will be moved to a place close to the corresponding target +// landmark. The points in between are interpolated smoothly using +// Bookstein's Thin Plate Spline algorithm. +// +// To obtain a correct TPS warp, use the R2LogR kernel if your data is 2D, and +// the R kernel if your data is 3D. Or you can specify your own RBF. (Hence this +// class is more general than a pure TPS transform.) +// .SECTION Caveats +// 1) The inverse transform is calculated using an iterative method, +// and is several times more expensive than the forward transform. +// 2) Whenever you add, subtract, or set points you must call Modified() +// on the vtkPoints object, or the transformation might not update. +// 3) Collinear point configurations (except those that lie in the XY plane) +// result in an unstable transformation. +// .SECTION see also +// vtkGridTransform vtkGeneralTransform + + +#ifndef __vtkThinPlateSplineTransform_h +#define __vtkThinPlateSplineTransform_h + +#include "vtkWarpTransform.h" + +#define VTK_RBF_CUSTOM 0 +#define VTK_RBF_R 1 +#define VTK_RBF_R2LOGR 2 + +class VTK_HYBRID_EXPORT vtkThinPlateSplineTransform : public vtkWarpTransform +{ +public: + vtkTypeRevisionMacro(vtkThinPlateSplineTransform,vtkWarpTransform); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkThinPlateSplineTransform *New(); + + // Description: + // Specify the 'stiffness' of the spline. The default is 1.0. + vtkGetMacro(Sigma,double); + vtkSetMacro(Sigma,double); + + // Description: + // Specify the radial basis function to use. The default is + // R2LogR which is appropriate for 2D. Use |R| (SetBasisToR) + // if your data is 3D. Alternatively specify your own basis function, + // however this will mean that the transform will no longer be a true + // thin-plate spline. + void SetBasis(int basis); + vtkGetMacro(Basis,int); + void SetBasisToR() { this->SetBasis(VTK_RBF_R); }; + void SetBasisToR2LogR() { this->SetBasis(VTK_RBF_R2LOGR); }; + const char *GetBasisAsString(); + +//BTX + // Description: + // Set the radial basis function to a custom function. You must + // supply both the function and its derivative with respect to r. + void SetBasisFunction(double (*U)(double r)) { + if (this->BasisFunction == U) { return; } + this->SetBasis(VTK_RBF_CUSTOM); + this->BasisFunction = U; + this->Modified(); }; + void SetBasisDerivative(double (*dUdr)(double r, double &dU)) { + this->BasisDerivative = dUdr; + this->Modified(); }; +//ETX + + // Description: + // Set the source landmarks for the warp. If you add or change the + // vtkPoints object, you must call Modified() on it or the transformation + // might not update. + void SetSourceLandmarks(vtkPoints *source); + vtkGetObjectMacro(SourceLandmarks,vtkPoints); + + // Description: + // Set the target landmarks for the warp. If you add or change the + // vtkPoints object, you must call Modified() on it or the transformation + // might not update. + void SetTargetLandmarks(vtkPoints *target); + vtkGetObjectMacro(TargetLandmarks,vtkPoints); + + // Description: + // Get the MTime. + unsigned long GetMTime(); + + // Description: + // Make another transform of the same type. + vtkAbstractTransform *MakeTransform(); + +protected: + vtkThinPlateSplineTransform(); + ~vtkThinPlateSplineTransform(); + + // Description: + // Prepare the transformation for application. + void InternalUpdate(); + + // Description: + // This method does no type checking, use DeepCopy instead. + void InternalDeepCopy(vtkAbstractTransform *transform); + + void ForwardTransformPoint(const float in[3], float out[3]); + void ForwardTransformPoint(const double in[3], double out[3]); + + void ForwardTransformDerivative(const float in[3], float out[3], + float derivative[3][3]); + void ForwardTransformDerivative(const double in[3], double out[3], + double derivative[3][3]); + + double Sigma; + vtkPoints *SourceLandmarks; + vtkPoints *TargetLandmarks; + +//BTX + // the radial basis function to use + double (*BasisFunction)(double r); + double (*BasisDerivative)(double r, double& dUdr); +//ETX + int Basis; + + int NumberOfPoints; + double **MatrixW; +private: + vtkThinPlateSplineTransform(const vtkThinPlateSplineTransform&); // Not implemented. + void operator=(const vtkThinPlateSplineTransform&); // Not implemented. +}; + +#endif + + + + + diff --git a/Hybrid/vtkTransformToGrid.cxx b/Hybrid/vtkTransformToGrid.cxx new file mode 100644 index 0000000..ca0fd16 --- /dev/null +++ b/Hybrid/vtkTransformToGrid.cxx @@ -0,0 +1,477 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformToGrid.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransformToGrid.h" + +#include "vtkAbstractTransform.h" +#include "vtkIdentityTransform.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkTransformToGrid, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkTransformToGrid); + +vtkCxxSetObjectMacro(vtkTransformToGrid,Input,vtkAbstractTransform); + +//---------------------------------------------------------------------------- +vtkTransformToGrid::vtkTransformToGrid() +{ + this->Input = NULL; + + this->GridScalarType = VTK_DOUBLE; + + for (int i = 0; i < 3; i++) + { + this->GridExtent[2*i] = this->GridExtent[2*i+1] = 0; + this->GridOrigin[i] = 0.0; + this->GridSpacing[i] = 1.0; + } + + this->DisplacementScale = 1.0; + this->DisplacementShift = 0.0; + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkTransformToGrid::~vtkTransformToGrid() +{ + this->SetInput(static_cast(0)); +} + +//---------------------------------------------------------------------------- +void vtkTransformToGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + int i; + + this->Superclass::PrintSelf(os,indent); + + os << indent << "Input: (" << this->Input << ")\n"; + + os << indent << "GridSpacing: (" << this->GridSpacing[0]; + for (i = 1; i < 3; ++i) + { + os << ", " << this->GridSpacing[i]; + } + os << ")\n"; + + os << indent << "GridOrigin: (" << this->GridOrigin[0]; + for (i = 1; i < 3; ++i) + { + os << ", " << this->GridOrigin[i]; + } + os << ")\n"; + + os << indent << "GridExtent: (" << this->GridExtent[0]; + for (i = 1; i < 6; ++i) + { + os << ", " << this->GridExtent[i]; + } + os << ")\n"; + + os << indent << "GridScalarType: " << + vtkImageScalarTypeNameMacro(this->GridScalarType) << "\n"; + + this->UpdateShiftScale(); + + os << indent << "DisplacementScale: " << this->DisplacementScale << "\n"; + os << indent << "DisplacementShift: " << this->DisplacementShift << "\n"; +} + +//---------------------------------------------------------------------------- +// This method returns the largest data that can be generated. +void vtkTransformToGrid::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + + if (this->GetInput() == NULL) + { + vtkErrorMacro("Missing input"); + return; + } + + // update the transform, maybe in the future make transforms part of the + // pipeline + this->Input->Update(); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->GridExtent,6); + outInfo->Set(vtkDataObject::SPACING(),this->GridSpacing,3); + outInfo->Set(vtkDataObject::ORIGIN(),this->GridOrigin,3); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->GridScalarType, 3); +} + +//---------------------------------------------------------------------------- +// Return the maximum absolute displacement of the transform over +// the entire grid extent -- this is extremely robust and extremely +// inefficient, it should be possible to do much better than this. +void vtkTransformToGridMinMax(vtkTransformToGrid *self, int extent[6], + double &minDisplacement, double &maxDisplacement) +{ + vtkAbstractTransform *transform = self->GetInput(); + transform->Update(); + + if (!transform) + { + minDisplacement = -1.0; + maxDisplacement = +1.0; + return; + } + + double *spacing = self->GetGridSpacing(); + double *origin = self->GetGridOrigin(); + + maxDisplacement = -1e37; + minDisplacement = +1e37; + + double point[3],newPoint[3],displacement; + + for (int k = extent[4]; k <= extent[5]; k++) + { + point[2] = k*spacing[2] + origin[2]; + for (int j = extent[2]; j <= extent[3]; j++) + { + point[1] = j*spacing[1] + origin[1]; + for (int i = extent[0]; i <= extent[1]; i++) + { + point[0] = i*spacing[0] + origin[0]; + + transform->InternalTransformPoint(point,newPoint); + + for (int l = 0; l < 3; l++) + { + displacement = newPoint[l] - point[l]; + + if (displacement > maxDisplacement) + { + maxDisplacement = displacement; + } + + if (displacement < minDisplacement) + { + minDisplacement = displacement; + } + } + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkTransformToGrid::UpdateShiftScale() +{ + int gridType = this->GridScalarType; + + // nothing to do for double or double + if (gridType == VTK_DOUBLE || gridType == VTK_DOUBLE) + { + this->DisplacementShift = 0.0; + this->DisplacementScale = 1.0; + vtkDebugMacro(<< "displacement (scale, shift) = (" << + this->DisplacementScale << ", " << + this->DisplacementShift << ")"); + return; + } + + // check mtime + if (this->ShiftScaleTime.GetMTime() > this->GetMTime()) + { + return; + } + + // get the maximum displacement + double minDisplacement, maxDisplacement; + vtkTransformToGridMinMax(this,this->GridExtent, + minDisplacement, + maxDisplacement); + + vtkDebugMacro(<< "displacement (min, max) = (" << + minDisplacement << ", " << maxDisplacement << ")"); + + double typeMin,typeMax; + + switch (gridType) + { + case VTK_SHORT: + typeMin = VTK_SHORT_MIN; + typeMax = VTK_SHORT_MAX; + break; + case VTK_UNSIGNED_SHORT: + typeMin = VTK_UNSIGNED_SHORT_MIN; + typeMax = VTK_UNSIGNED_SHORT_MAX; + break; + case VTK_CHAR: + typeMin = VTK_CHAR_MIN; + typeMax = VTK_CHAR_MAX; + break; + case VTK_UNSIGNED_CHAR: + typeMin = VTK_UNSIGNED_CHAR_MIN; + typeMax = VTK_UNSIGNED_CHAR_MAX; + break; + default: + vtkErrorMacro(<< "UpdateShiftScale: Unknown input ScalarType"); + return; + } + + this->DisplacementScale = ((maxDisplacement - minDisplacement)/ + (typeMax - typeMin)); + this->DisplacementShift = ((typeMax*minDisplacement-typeMin*maxDisplacement)/ + (typeMax - typeMin)); + + if (this->DisplacementScale == 0.0) + { + this->DisplacementScale = 1.0; + } + + vtkDebugMacro(<< "displacement (scale, shift) = (" << + this->DisplacementScale << ", " << + this->DisplacementShift << ")"); + + this->ShiftScaleTime.Modified(); +} + +//---------------------------------------------------------------------------- +// macros to ensure proper round-to-nearest behaviour + +inline void vtkGridRound(double val, unsigned char& rnd) +{ + rnd = (unsigned char)(val+0.5f); +} + +inline void vtkGridRound(double val, char& rnd) +{ + rnd = (char)((val+128.5f)-128); +} + +inline void vtkGridRound(double val, short& rnd) +{ + rnd = (short)((int)(val+32768.5f)-32768); +} + +inline void vtkGridRound(double val, unsigned short& rnd) +{ + rnd = (unsigned short)(val+0.5f); +} + +inline void vtkGridRound(double val, double& rnd) +{ + rnd = (double)(val); +} + +//---------------------------------------------------------------------------- +template +void vtkTransformToGridExecute(vtkTransformToGrid *self, + vtkImageData *grid, T *gridPtr, int extent[6], + double shift, double scale, int id) +{ + vtkAbstractTransform *transform = self->GetInput(); + int isIdentity = 0; + if (transform == 0) + { + transform = vtkIdentityTransform::New(); + isIdentity = 1; + } + + double *spacing = grid->GetSpacing(); + double *origin = grid->GetOrigin(); + vtkIdType *increments = grid->GetIncrements(); + + double invScale = 1.0/scale; + + double point[3]; + double newPoint[3]; + + T *gridPtr0 = gridPtr; + + unsigned long count = 0; + unsigned long target = (unsigned long) + ((extent[5]-extent[4]+1)*(extent[3]-extent[2]+1)/50.0); + target++; + + for (int k = extent[4]; k <= extent[5]; k++) + { + point[2] = k*spacing[2] + origin[2]; + T *gridPtr1 = gridPtr0; + + for (int j = extent[2]; j <= extent[3]; j++) + { + + if (id == 0) + { + if (count % target == 0) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + point[1] = j*spacing[1] + origin[1]; + gridPtr = gridPtr1; + + for (int i = extent[0]; i <= extent[1]; i++) + { + point[0] = i*spacing[0] + origin[0]; + + transform->InternalTransformPoint(point,newPoint); + + vtkGridRound((newPoint[0] - point[0] - shift)*invScale,*gridPtr++); + vtkGridRound((newPoint[1] - point[1] - shift)*invScale,*gridPtr++); + vtkGridRound((newPoint[2] - point[2] - shift)*invScale,*gridPtr++); + } + + gridPtr1 += increments[1]; + } + + gridPtr0 += increments[2]; + } + + if (isIdentity) + { + transform->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransformToGrid::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // get the data object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *grid = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + grid->SetExtent( + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); + grid->AllocateScalars(); + int *extent = grid->GetExtent(); + + double *gridPtr = (double *)grid->GetScalarPointerForExtent(extent); + int gridType = grid->GetScalarType(); + + this->UpdateShiftScale(); + + double scale = this->DisplacementScale; + double shift = this->DisplacementShift; + + int id = 0; + + switch (gridType) + { + case VTK_DOUBLE: + vtkTransformToGridExecute(this, grid, (double *)(gridPtr), extent, + shift,scale,id); + break; + case VTK_SHORT: + vtkTransformToGridExecute(this, grid, (short *)(gridPtr), extent, + shift,scale,id); + break; + case VTK_UNSIGNED_SHORT: + vtkTransformToGridExecute(this, grid, (unsigned short *)(gridPtr),extent, + shift,scale,id); + break; + case VTK_CHAR: + vtkTransformToGridExecute(this, grid, (char *)(gridPtr), extent, + shift,scale,id); + break; + case VTK_UNSIGNED_CHAR: + vtkTransformToGridExecute(this, grid, (unsigned char *)(gridPtr), extent, + shift,scale,id); + break; + default: + vtkErrorMacro(<< "Execute: Unknown input ScalarType"); + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkTransformToGrid::GetMTime() +{ + unsigned long mtime = this->Superclass::GetMTime(); + + if (this->Input) + { + unsigned long mtime2 = this->Input->GetMTime(); + if (mtime2 > mtime) + { + mtime = mtime2; + } + } + + return mtime; +} + +//---------------------------------------------------------------------------- +int vtkTransformToGrid::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->RequestData(request, inputVector, outputVector); + return 1; + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + this->RequestInformation(request, inputVector, outputVector); + // after executing set the origin and spacing from the + // info + int i; + for (i = 0; i < this->GetNumberOfOutputPorts(); ++i) + { + vtkInformation* info = outputVector->GetInformationObject(i); + vtkImageData *output = + vtkImageData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT())); + // if execute info didn't set origin and spacing then we set them + if (!info->Has(vtkDataObject::ORIGIN())) + { + info->Set(vtkDataObject::ORIGIN(),0,0,0); + info->Set(vtkDataObject::SPACING(),1,1,1); + } + if (output) + { + output->SetOrigin(info->Get(vtkDataObject::ORIGIN())); + output->SetSpacing(info->Get(vtkDataObject::SPACING())); + } + } + return 1; + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkTransformToGrid::GetOutput() +{ + return vtkImageData::SafeDownCast(this->GetOutputDataObject(0)); +} + +int vtkTransformToGrid::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} diff --git a/Hybrid/vtkTransformToGrid.h b/Hybrid/vtkTransformToGrid.h new file mode 100644 index 0000000..2b775a2 --- /dev/null +++ b/Hybrid/vtkTransformToGrid.h @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformToGrid.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransformToGrid - create a grid for a vtkGridTransform +// .SECTION Description +// vtkTransformToGrid takes any transform as input and produces a grid +// for use by a vtkGridTransform. This can be used, for example, to +// invert a grid transform, concatenate two grid transforms, or to +// convert a thin plate spline transform into a grid transform. +// .SECTION See Also +// vtkGridTransform vtkThinPlateSplineTransform vtkAbstractTransform + +#ifndef __vtkTransformToGrid_h +#define __vtkTransformToGrid_h + +#include "vtkAlgorithm.h" +#include "vtkImageData.h" // makes things a bit easier + +class vtkAbstractTransform; + +class VTK_HYBRID_EXPORT vtkTransformToGrid : public vtkAlgorithm +{ +public: + static vtkTransformToGrid *New(); + vtkTypeRevisionMacro(vtkTransformToGrid,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the transform which will be converted into a grid. + virtual void SetInput(vtkAbstractTransform*); + vtkGetObjectMacro(Input,vtkAbstractTransform); + + // Description: + // Get/Set the extent of the grid. + vtkSetVector6Macro(GridExtent,int); + vtkGetVector6Macro(GridExtent,int); + + // Description: + // Get/Set the origin of the grid. + vtkSetVector3Macro(GridOrigin,double); + vtkGetVector3Macro(GridOrigin,double); + + // Description: + // Get/Set the spacing between samples in the grid. + vtkSetVector3Macro(GridSpacing,double); + vtkGetVector3Macro(GridSpacing,double); + + // Description: + // Get/Set the scalar type of the grid. The default is + // double. + vtkSetMacro(GridScalarType,int); + vtkGetMacro(GridScalarType,int); + void SetGridScalarTypeToFloat(){this->SetGridScalarType(VTK_DOUBLE);}; + void SetGridScalarTypeToShort(){this->SetGridScalarType(VTK_SHORT);}; + void SetGridScalarTypeToUnsignedShort() + {this->SetGridScalarType(VTK_UNSIGNED_SHORT);}; + void SetGridScalarTypeToUnsignedChar() + {this->SetGridScalarType(VTK_UNSIGNED_CHAR);}; + void SetGridScalarTypeToChar() + {this->SetGridScalarType(VTK_CHAR);}; + + // Description: + // Get the scale and shift to convert integer grid elements into + // real values: dx = scale*di + shift. If the grid is of double type, + // then scale = 1 and shift = 0. + double GetDisplacementScale() { + this->UpdateShiftScale(); return this->DisplacementScale; }; + double GetDisplacementShift() { + this->UpdateShiftScale(); return this->DisplacementShift; }; + + // Description: + // Get the output data object for a port on this algorithm. + vtkImageData* GetOutput(); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkTransformToGrid(); + ~vtkTransformToGrid(); + + void RequestInformation (vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + + void RequestData(vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + + // Description: + // Internal method to calculate the shift and scale values which + // will provide maximum grid precision for a particular integer type. + void UpdateShiftScale(); + + unsigned long GetMTime(); + + vtkAbstractTransform *Input; + + int GridScalarType; + int GridExtent[6]; + double GridOrigin[3]; + double GridSpacing[3]; + + double DisplacementScale; + double DisplacementShift; + vtkTimeStamp ShiftScaleTime; + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + +private: + vtkTransformToGrid(const vtkTransformToGrid&); // Not implemented. + void operator=(const vtkTransformToGrid&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkVRML.h b/Hybrid/vtkVRML.h new file mode 100644 index 0000000..aedff16 --- /dev/null +++ b/Hybrid/vtkVRML.h @@ -0,0 +1,675 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVRML.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* ====================================================================== + + Importer based on BNF Yacc and Lex parser definition from: + + ************************************************** + * VRML 2.0 Parser + * Copyright (C) 1996 Silicon Graphics, Inc. + * + * Author(s) : Gavin Bell + * Daniel Woods (first port) + ************************************************** + + Ported to VTK By: Thomas D. Citriniti + Rensselaer Polytechnic Institute + citrit@rpi.edu + +=======================================================================*/ +#ifndef _VTKVRML_H_ +#define _VTKVRML_H_ + +#define DEFAULTINCREMENT 100 + +#include "vtkHeap.h" + +#ifdef VTK_USE_ANSI_STDLIB +#include +#else +#include +#endif + +#if defined(__BORLANDC__) && (__BORLANDC__<0x0560) +// seems to be missing from new.h and new for borland +void* operator new[](unsigned int,void *v) +{ + return v; +} +#endif + +// Use a user-managed heap to remove memory leaks +// This code must come before "#include vtkVRML.h" because +// it uses the functions below. +struct vtkVRMLAllocator +{ + static void Initialize(); + static void *AllocateMemory(size_t n); + static void CleanUp(); + static char* StrDup(const char *str); + static vtkHeap *Heap; +}; + + + +template +class VTK_HYBRID_EXPORT vtkVRMLVectorType +{ +protected: + T *Data; + int Allocated; + int Used; +public: + void Init() + { + Allocated=DEFAULTINCREMENT; + if (!this->UseNew) + { + vtkVRMLAllocator::Initialize(); + void* mem = vtkVRMLAllocator::AllocateMemory(Allocated*sizeof(T)); + Data=new(mem) T[Allocated]; + } + else + { + Data = new T[Allocated]; + } + Used=0; + } + vtkVRMLVectorType() + { + this->UseNew = 0; + this->Init(); + } + vtkVRMLVectorType(int usenew) : UseNew(usenew) + { + this->Init(); + } + ~vtkVRMLVectorType(void) + { + if (this->UseNew) + { + delete[] Data; + } + } + void Reserve(int newSize) + { + T *temp; + int oldSize; + if(newSize >= Allocated) + { + oldSize=Allocated; + Allocated=newSize+DEFAULTINCREMENT; + temp=Data; + if (!this->UseNew) + { + void* mem = vtkVRMLAllocator::AllocateMemory(Allocated*sizeof(T)); + Data=new(mem) T[Allocated]; + } + else + { + Data=new T[Allocated]; + } + if(Data==(T *)'\0') + { + return; + } + memcpy((void*)Data, (void*)temp, oldSize*sizeof(T)); + if (this->UseNew) + { + delete[] temp; + } + } + } + + void Demand(int newSize) + { + Reserve(newSize); + Used=newSize; + } + int Count(void) const + { + return Used; + } + T& Get(int index) const + { + if (index > Used) + return Data[Used-1]; + return Data[index]; + } + T& operator[](int index) + { + if (index > Used) + Demand(index); + return Data[index]; + } + operator T*() const + { + return Data; + } + vtkVRMLVectorType& operator+=(T datum) + { + Reserve(Used+1); + Data[Used]=datum; + Used++; + return *this; + } + void Push(T datum) + { + Reserve(Used+1); + Data[Used]=datum; + Used++; + } + T& Pop() + { + Used--; + return Data[Used]; + } + T& Top() + { + return Data[Used-1]; + } + + void* operator new(size_t n) + { + return vtkVRMLAllocator::AllocateMemory(n); + } + + void operator delete(void *) + { + } + + int UseNew; +}; + +static const char standardNodes[][2042] = { + "#VRML V2.0 utf8 \n\ +# \n\ +# ************************************************** \n\ +# * VRML 2.0 Parser \n\ +# * Copyright (C) 1996 Silicon Graphics, Inc. \n\ +# * \n\ +# * Author(s) : Gavin Bell \n\ +# * Daniel Woods (first port) \n\ +# ************************************************** \n\ +# \n\ +# Definitions for all of the nodes built-in to the spec. \n\ +# Taken almost directly from the VRML 2.0 final spec: \n\ + \n\ +PROTO Anchor [ \n\ + eventIn MFNode addChildren \n\ + eventIn MFNode removeChildren \n\ + exposedField MFNode children [] \n\ + exposedField SFString description \"\" \n\ + exposedField MFString parameter [] \n\ + exposedField MFString url [] \n\ + field SFVec3f bboxCenter 0.0 0.0 0.0 \n\ + field SFVec3f bboxSize -1.0 -1.0 -1.0 \n\ +] { } \n\ + \n\ +PROTO Appearance [ \n\ + exposedField SFNode material NULL \n\ + exposedField SFNode texture NULL \n\ + exposedField SFNode textureTransform NULL \n\ +] { } \n\ + \n\ +PROTO AudioClip [ \n\ + exposedField SFString description \"\" \n\ + exposedField SFBool loop FALSE \n\ + exposedField SFFloat pitch 1.0 \n\ + exposedField SFTime startTime 0 \n\ + exposedField SFTime stopTime 0 \n\ + exposedField MFString url [] \n\ + eventOut SFTime duration_changed \n\ + eventOut SFBool isActive \n\ +] { } \n\ + \n\ +PROTO Background [ \n\ + eventIn SFBool set_bind \n\ + exposedField MFFloat groundAngle [] \n\ + exposedField MFColor groundColor [] \n\ + exposedField MFString backUrl [] \n\ + exposedField MFString bottomUrl [] \n\ + exposedField MFString frontUrl [] \n\ + exposedField MFString leftUrl [] \n\ + exposedField MFString rightUrl [] \n\ + exposedField MFString topUrl [] \n\ + exposedField MFFloat skyAngle [] \n\ + exposedField MFColor skyColor [ 0 0 0 ] \n\ + eventOut SFBool isBound \n\ +] { }", + "PROTO Billboard [ \n\ + eventIn MFNode addChildren \n\ + eventIn MFNode removeChildren \n\ + exposedField SFVec3f axisOfRotation 0 1 0 \n\ + exposedField MFNode children [] \n\ + field SFVec3f bboxCenter 0 0 0 \n\ + field SFVec3f bboxSize -1 -1 -1 \n\ +] { } \n\ + \n\ +PROTO Box [ \n\ + field SFVec3f size 2 2 2 \n\ +] { } \n\ + \n\ +PROTO Collision [ \n\ + eventIn MFNode addChildren \n\ + eventIn MFNode removeChildren \n\ + exposedField MFNode children [] \n\ + exposedField SFBool collide TRUE \n\ + field SFVec3f bboxCenter 0 0 0 \n\ + field SFVec3f bboxSize -1 -1 -1 \n\ + field SFNode proxy NULL \n\ + eventOut SFTime collideTime \n\ +] { } \n\ + \n\ +PROTO Color [ \n\ + exposedField MFColor color [] \n\ +] { } \n\ + \n\ +PROTO ColorInterpolator [ \n\ + eventIn SFFloat set_fraction \n\ + exposedField MFFloat key [] \n\ + exposedField MFColor keyValue [] \n\ + eventOut SFColor value_changed \n\ +] { } \n\ + \n\ +PROTO Cone [ \n\ + field SFFloat bottomRadius 1 \n\ + field SFFloat height 2 \n\ + field SFBool side TRUE \n\ + field SFBool bottom TRUE \n\ +] { } \n\ + \n\ +PROTO Coordinate [ \n\ + exposedField MFVec3f point [] \n\ +] { } \n\ + \n\ +PROTO CoordinateInterpolator [ \n\ + eventIn SFFloat set_fraction \n\ + exposedField MFFloat key [] \n\ + exposedField MFVec3f keyValue [] \n\ + eventOut MFVec3f value_changed \n\ +] { } \n\ + \n\ +PROTO Cylinder [ \n\ + field SFBool bottom TRUE \n\ + field SFFloat height 2 \n\ + field SFFloat radius 1 \n\ + field SFBool side TRUE \n\ + field SFBool top TRUE \n\ +] { } \n\ + \n\ +PROTO CylinderSensor [ \n\ + exposedField SFBool autoOffset TRUE \n\ + exposedField SFFloat diskAngle 0.262 \n\ + exposedField SFBool enabled TRUE \n\ + exposedField SFFloat maxAngle -1 \n\ + exposedField SFFloat minAngle 0 \n\ + exposedField SFFloat offset 0 \n\ + eventOut SFBool isActive \n\ + eventOut SFRotation rotation_changed \n\ + eventOut SFVec3f trackPoint_changed \n\ +] { }", + "PROTO DirectionalLight [ \n\ + exposedField SFFloat ambientIntensity 0 \n\ + exposedField SFColor color 1 1 1 \n\ + exposedField SFVec3f direction 0 0 -1 \n\ + exposedField SFFloat intensity 1 \n\ + exposedField SFBool on TRUE \n\ +] { } \n\ + \n\ +PROTO ElevationGrid [ \n\ + eventIn MFFloat set_height \n\ + exposedField SFNode color NULL \n\ + exposedField SFNode normal NULL \n\ + exposedField SFNode texCoord NULL \n\ + field SFBool ccw TRUE \n\ + field SFBool colorPerVertex TRUE \n\ + field SFFloat creaseAngle 0 \n\ + field MFFloat height [] \n\ + field SFBool normalPerVertex TRUE \n\ + field SFBool solid TRUE \n\ + field SFInt32 xDimension 0 \n\ + field SFFloat xSpacing 0.0 \n\ + field SFInt32 zDimension 0 \n\ + field SFFloat zSpacing 0.0 \n\ + \n\ +] { } \n\ + \n\ +PROTO Extrusion [ \n\ + eventIn MFVec2f set_crossSection \n\ + eventIn MFRotation set_orientation \n\ + eventIn MFVec2f set_scale \n\ + eventIn MFVec3f set_spine \n\ + field SFBool beginCap TRUE \n\ + field SFBool ccw TRUE \n\ + field SFBool convex TRUE \n\ + field SFFloat creaseAngle 0 \n\ + field MFVec2f crossSection [ 1 1, 1 -1, -1 -1, -1 1, 1 1 ] \n\ + field SFBool endCap TRUE \n\ + field MFRotation orientation 0 0 1 0 \n\ + field MFVec2f scale 1 1 \n\ + field SFBool solid TRUE \n\ + field MFVec3f spine [ 0 0 0, 0 1 0 ] \n\ +] { } \n\ + \n\ +PROTO Fog [ \n\ + exposedField SFColor color 1 1 1 \n\ + exposedField SFString fogType \"LINEAR\" \n\ + exposedField SFFloat visibilityRange 0 \n\ + eventIn SFBool set_bind \n\ + eventOut SFBool isBound \n\ +] { }", + "PROTO FontStyle [ \n\ + field SFString family \"SERIF\" \n\ + field SFBool horizontal TRUE \n\ + field MFString justify \"BEGIN\" \n\ + field SFString language \"\" \n\ + field SFBool leftToRight TRUE \n\ + field SFFloat size 1.0 \n\ + field SFFloat spacing 1.0 \n\ + field SFString style \"PLAIN\" \n\ + field SFBool topToBottom TRUE \n\ +] { } \n\ + \n\ +PROTO Group [ \n\ + eventIn MFNode addChildren \n\ + eventIn MFNode removeChildren \n\ + exposedField MFNode children [] \n\ + field SFVec3f bboxCenter 0 0 0 \n\ + field SFVec3f bboxSize -1 -1 -1 \n\ +] { } \n\ + \n\ +PROTO ImageTexture [ \n\ + exposedField MFString url [] \n\ + field SFBool repeatS TRUE \n\ + field SFBool repeatT TRUE \n\ +] { } \n\ + \n\ +PROTO IndexedFaceSet [ \n\ + eventIn MFInt32 set_colorIndex \n\ + eventIn MFInt32 set_coordIndex \n\ + eventIn MFInt32 set_normalIndex \n\ + eventIn MFInt32 set_texCoordIndex \n\ + exposedField SFNode color NULL \n\ + exposedField SFNode coord NULL \n\ + exposedField SFNode normal NULL \n\ + exposedField SFNode texCoord NULL \n\ + field SFBool ccw TRUE \n\ + field MFInt32 colorIndex [] \n\ + field SFBool colorPerVertex TRUE \n\ + field SFBool convex TRUE \n\ + field MFInt32 coordIndex [] \n\ + field SFFloat creaseAngle 0 \n\ + field MFInt32 normalIndex [] \n\ + field SFBool normalPerVertex TRUE \n\ + field SFBool solid TRUE \n\ + field MFInt32 texCoordIndex [] \n\ +] { } \n\ + \n\ +PROTO IndexedLineSet [ \n\ + eventIn MFInt32 set_colorIndex \n\ + eventIn MFInt32 set_coordIndex \n\ + exposedField SFNode color NULL \n\ + exposedField SFNode coord NULL \n\ + field MFInt32 colorIndex [] \n\ + field SFBool colorPerVertex TRUE \n\ + field MFInt32 coordIndex [] \n\ +] { }", + "PROTO Inline [ \n\ + exposedField MFString url [] \n\ + field SFVec3f bboxCenter 0 0 0 \n\ + field SFVec3f bboxSize -1 -1 -1 \n\ +] { } \n\ +PROTO LOD [ \n\ + exposedField MFNode level [] \n\ + field SFVec3f center 0 0 0 \n\ + field MFFloat range [] \n\ +] { } \n\ + \n\ +PROTO Material [ \n\ + exposedField SFFloat ambientIntensity 0.2 \n\ + exposedField SFColor diffuseColor 0.8 0.8 0.8 \n\ + exposedField SFColor emissiveColor 0 0 0 \n\ + exposedField SFFloat shininess 0.2 \n\ + exposedField SFColor specularColor 0 0 0 \n\ + exposedField SFFloat transparency 0 \n\ +] { } \n\ + \n\ +PROTO MovieTexture [ \n\ + exposedField SFBool loop FALSE \n\ + exposedField SFFloat speed 1 \n\ + exposedField SFTime startTime 0 \n\ + exposedField SFTime stopTime 0 \n\ + exposedField MFString url [] \n\ + field SFBool repeatS TRUE \n\ + field SFBool repeatT TRUE \n\ + eventOut SFFloat duration_changed \n\ + eventOut SFBool isActive \n\ +] { } \n\ + \n\ +PROTO NavigationInfo [ \n\ + eventIn SFBool set_bind \n\ + exposedField MFFloat avatarSize [ 0.25, 1.6, 0.75 ] \n\ + exposedField SFBool headlight TRUE \n\ + exposedField SFFloat speed 1.0 \n\ + exposedField MFString type \"WALK\" \n\ + exposedField SFFloat visibilityLimit 0.0 \n\ + eventOut SFBool isBound \n\ +] { } \n\ + \n\ +PROTO Normal [ \n\ + exposedField MFVec3f vector [] \n\ +] { } \n\ + \n\ +PROTO NormalInterpolator [ \n\ + eventIn SFFloat set_fraction \n\ + exposedField MFFloat key [] \n\ + exposedField MFVec3f keyValue [] \n\ + eventOut MFVec3f value_changed \n\ +] { } \n\ + \n\ +PROTO OrientationInterpolator [ \n\ + eventIn SFFloat set_fraction \n\ + exposedField MFFloat key [] \n\ + exposedField MFRotation keyValue [] \n\ + eventOut SFRotation value_changed \n\ +] { } \n\ + \n\ +PROTO PixelTexture [ \n\ + exposedField SFImage image 0 0 0 \n\ + field SFBool repeatS TRUE \n\ + field SFBool repeatT TRUE \n\ +] { }", + "PROTO PlaneSensor [ \n\ + exposedField SFBool autoOffset TRUE \n\ + exposedField SFBool enabled TRUE \n\ + exposedField SFVec2f maxPosition -1 -1 \n\ + exposedField SFVec2f minPosition 0 0 \n\ + exposedField SFVec3f offset 0 0 0 \n\ + eventOut SFBool isActive \n\ + eventOut SFVec3f trackPoint_changed \n\ + eventOut SFVec3f translation_changed \n\ +] { } \n\ + \n\ +PROTO PointLight [ \n\ + exposedField SFFloat ambientIntensity 0 \n\ + exposedField SFVec3f attenuation 1 0 0 \n\ + exposedField SFColor color 1 1 1 \n\ + exposedField SFFloat intensity 1 \n\ + exposedField SFVec3f location 0 0 0 \n\ + exposedField SFBool on TRUE \n\ + exposedField SFFloat radius 100 \n\ +] { } \n\ + \n\ +PROTO PointSet [ \n\ + exposedField SFNode color NULL \n\ + exposedField SFNode coord NULL \n\ +] { } \n\ + \n\ +PROTO PositionInterpolator [ \n\ + eventIn SFFloat set_fraction \n\ + exposedField MFFloat key [] \n\ + exposedField MFVec3f keyValue [] \n\ + eventOut SFVec3f value_changed \n\ +] { } \n\ + \n\ +PROTO ProximitySensor [ \n\ + exposedField SFVec3f center 0 0 0 \n\ + exposedField SFVec3f size 0 0 0 \n\ + exposedField SFBool enabled TRUE \n\ + eventOut SFBool isActive \n\ + eventOut SFVec3f position_changed \n\ + eventOut SFRotation orientation_changed \n\ + eventOut SFTime enterTime \n\ + eventOut SFTime exitTime \n\ +] { }", + "PROTO ScalarInterpolator [ \n\ + eventIn SFFloat set_fraction \n\ + exposedField MFFloat key [] \n\ + exposedField MFFloat keyValue [] \n\ + eventOut SFFloat value_changed \n\ +] { } \n\ + \n\ +PROTO Script [ \n\ + exposedField MFString url [ ] \n\ + field SFBool directOutput FALSE \n\ + field SFBool mustEvaluate FALSE \n\ +] { } \n\ + \n\ +PROTO Shape [ \n\ + field SFNode appearance NULL \n\ + field SFNode geometry NULL \n\ +] { } \n\ + \n\ +PROTO Sound [ \n\ + exposedField SFVec3f direction 0 0 1 \n\ + exposedField SFFloat intensity 1 \n\ + exposedField SFVec3f location 0 0 0 \n\ + exposedField SFFloat maxBack 10 \n\ + exposedField SFFloat maxFront 10 \n\ + exposedField SFFloat minBack 1 \n\ + exposedField SFFloat minFront 1 \n\ + exposedField SFFloat priority 0 \n\ + exposedField SFNode source NULL \n\ + field SFBool spatialize TRUE \n\ +] { } \n\ + \n\ +PROTO Sphere [ \n\ + field SFFloat radius 1 \n\ +] { } \n\ + \n\ +PROTO SphereSensor [ \n\ + exposedField SFBool autoOffset TRUE \n\ + exposedField SFBool enabled TRUE \n\ + exposedField SFRotation offset 0 1 0 0 \n\ + eventOut SFBool isActive \n\ + eventOut SFRotation rotation_changed \n\ + eventOut SFVec3f trackPoint_changed \n\ +] { } \n\ + \n\ +PROTO SpotLight [ \n\ + exposedField SFFloat ambientIntensity 0 \n\ + exposedField SFVec3f attenuation 1 0 0 \n\ + exposedField SFFloat beamWidth 1.570796 \n\ + exposedField SFColor color 1 1 1 \n\ + exposedField SFFloat cutOffAngle 0.785398 \n\ + exposedField SFVec3f direction 0 0 -1 \n\ + exposedField SFFloat intensity 1 \n\ + exposedField SFVec3f location 0 0 0 \n\ + exposedField SFBool on TRUE \n\ + exposedField SFFloat radius 100 \n\ +] { } \n\ + \n\ +PROTO Switch [ \n\ + exposedField MFNode choice [] \n\ + exposedField SFInt32 whichChoice -1 \n\ +] { } \n\ + \n\ +PROTO Text [ \n\ + exposedField MFString string [] \n\ + field SFNode fontStyle NULL \n\ + field MFFloat length [] \n\ + field SFFloat maxExtent 0.0 \n\ +] { }", + "PROTO TextureCoordinate [ \n\ + exposedField MFVec2f point [] \n\ +] { } \n\ +PROTO TextureTransform [ \n\ + exposedField SFVec2f center 0 0 \n\ + exposedField SFFloat rotation 0 \n\ + exposedField SFVec2f scale 1 1 \n\ + exposedField SFVec2f translation 0 0 \n\ +] { } \n\ + \n\ +PROTO TimeSensor [ \n\ + exposedField SFTime cycleInterval 1 \n\ + exposedField SFBool enabled TRUE \n\ + exposedField SFBool loop FALSE \n\ + exposedField SFTime startTime 0 \n\ + exposedField SFTime stopTime 0 \n\ + eventOut SFTime cycleTime \n\ + eventOut SFFloat fraction_changed \n\ + eventOut SFBool isActive \n\ + eventOut SFTime time \n\ +] { } \n\ + \n\ +PROTO TouchSensor [ \n\ + exposedField SFBool enabled TRUE \n\ + eventOut SFVec3f hitNormal_changed \n\ + eventOut SFVec3f hitPoint_changed \n\ + eventOut SFVec2f hitTexCoord_changed \n\ + eventOut SFBool isActive \n\ + eventOut SFBool isOver \n\ + eventOut SFTime touchTime \n\ +] { } \n\ + \n\ +PROTO Transform [ \n\ + eventIn MFNode addChildren \n\ + eventIn MFNode removeChildren \n\ + exposedField SFVec3f center 0 0 0 \n\ + exposedField MFNode children [] \n\ + exposedField SFRotation rotation 0 0 1 0 \n\ + exposedField SFVec3f scale 1 1 1 \n\ + exposedField SFRotation scaleOrientation 0 0 1 0 \n\ + exposedField SFVec3f translation 0 0 0 \n\ + field SFVec3f bboxCenter 0 0 0 \n\ + field SFVec3f bboxSize -1 -1 -1 \n\ +] { } \n\ + \n\ +PROTO Viewpoint [ \n\ + eventIn SFBool set_bind \n\ + exposedField SFFloat fieldOfView 0.785398 \n\ + exposedField SFBool jump TRUE \n\ + exposedField SFRotation orientation 0 0 1 0 \n\ + exposedField SFVec3f position 0 0 10 \n\ + field SFString description \"\" \n\ + eventOut SFTime bindTime \n\ + eventOut SFBool isBound \n\ +] { }", + "PROTO VisibilitySensor [ \n\ + exposedField SFVec3f center 0 0 0 \n\ + exposedField SFBool enabled TRUE \n\ + exposedField SFVec3f size 0 0 0 \n\ + eventOut SFTime enterTime \n\ + eventOut SFTime exitTime \n\ + eventOut SFBool isActive \n\ +] { } \n\ + \n\ +PROTO WorldInfo [ \n\ + field MFString info [] \n\ + field SFString title \"\" \n\ +] { }","" +}; +#endif diff --git a/Hybrid/vtkVRMLImporter.cxx b/Hybrid/vtkVRMLImporter.cxx new file mode 100644 index 0000000..b40545f --- /dev/null +++ b/Hybrid/vtkVRMLImporter.cxx @@ -0,0 +1,6552 @@ + +#if defined (__digital__) && defined (__unix__) || defined(__IBMCPP__) +#define HAVE_ALLOCA_H 1 +#endif + + +#ifdef __GNUC__ +#undef alloca +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if HAVE_ALLOCA_H +#include +#else /* not HAVE_ALLOCA_H */ +#ifdef _AIX +#pragma alloca +#else /* not _AIX */ +#ifndef alloca +char *alloca (); +#endif +#include +#endif /* not _AIX */ +#endif /* not HAVE_ALLOCA_H */ +#endif /* not __GNUC__ */ + +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVRMLImporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* ====================================================================== + + Importer based on BNF Yacc and Lex parser definition from: + + ************************************************** + * VRML 2.0 Parser + * Copyright (C) 1996 Silicon Graphics, Inc. + * + * Author(s) : Gavin Bell + * Daniel Woods (first port) + ************************************************** + + Ported to VTK By: Thomas D. Citriniti + Rensselaer Polytechnic Institute + citrit@rpi.edu + +=======================================================================*/ +#include "vtkVRMLImporter.h" + +#include "vtkActor.h" +#include "vtkByteSwap.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkConeSource.h" +#include "vtkCubeSource.h" +#include "vtkCylinderSource.h" +#include "vtkFloatArray.h" +#include "vtkIdTypeArray.h" +#include "vtkLight.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyDataNormals.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkStripper.h" +#include "vtkSystemIncludes.h" +#include "vtkTransform.h" +#include "vtkVRML.h" + +#ifdef _MSC_VER +#pragma warning( disable : 4005 ) +#endif + +class vtkVRMLImporterInternal { +public: + vtkVRMLImporterInternal() : Heap(1) {} +//BTX +#ifdef _MSC_VER +#pragma warning( disable : 4251 ) +#endif + + vtkVRMLVectorType Heap; + +#ifdef _MSC_VER +#pragma warning( default : 4251 ) +#endif + +//ETX +}; + +// Heap to manage memory leaks +vtkHeap *vtkVRMLAllocator::Heap=NULL; + +void vtkVRMLAllocator::Initialize() +{ + if ( Heap == NULL ) + { + Heap = vtkHeap::New(); + } +} +void* vtkVRMLAllocator::AllocateMemory(size_t n) +{ + return Heap->AllocateMemory(n); +} + +void vtkVRMLAllocator::CleanUp() +{ + if ( Heap ) + { + Heap->Delete(); + Heap = NULL; + } +} +char* vtkVRMLAllocator::StrDup(const char *str) +{ + return Heap->StringDup(str); +} + + +// Provide isatty prototype for Cygwin. +#ifdef __CYGWIN__ +#include +#endif + +static int memyyInput_i = 0; +static int memyyInput_j = 0; + +// Used during the parsing +static int creatingDEF = 0; +static char *curDEFName; + +// Used by the lex input to get characters. Needed to read in memory structure +static void memyyInput(char *buf, int &result, int max_size); +static void defyyInput(char *buf, int &result, int max_size); + + +/************************************************** + * VRML 2.0 Parser + * Copyright (C) 1996 Silicon Graphics, Inc. + * + * Author(s) : Gavin Bell + * Daniel Woods (first port) + ************************************************** + */ + +// +// The VrmlNodeType class is responsible for storing information about node +// or prototype types. +// + +#ifndef _VRML_NODE_TYPE_ +#define _VRML_NODE_TYPE_ + +#ifdef USE_STD_NAMESPACE +using namespace std; +#endif + +// used to hold the VRML DEF names and assoc vtkObjects +class vtkVRMLUseStruct { +public: + vtkVRMLUseStruct( char *n, vtkObject *o) { defName = n; defObject = o; } + char *defName; + vtkObject *defObject; + + void* operator new(size_t n) + { + return vtkVRMLAllocator::AllocateMemory(n); + } + + void operator delete(void *vtkNotUsed(ptr)) {} +}; + + + +class VrmlNodeType { +public: + // Constructor. Takes name of new type (e.g. "Transform" or "Box") + // Copies the string given as name. + VrmlNodeType(const char *nm); + + // Destructor exists mainly to deallocate storage for name + ~VrmlNodeType(); + + // Namespace management functions. PROTO definitions add node types + // to the namespace. PROTO implementations are a separate node + // namespace, and require that any nested PROTOs NOT be available + // outside the PROTO implementation. + // addToNameSpace will print an error to stderr if the given type + // is already defined. + static void addToNameSpace(VrmlNodeType *); + static void pushNameSpace(); + static void popNameSpace(); + + // Find a node type, given its name. Returns NULL if type is not defined. + static const VrmlNodeType *find(const char *nm); + + // Routines for adding/getting eventIns/Outs/fields + void addEventIn(const char *name, int type); + void addEventOut(const char *name, int type); + void addField(const char *name, int type); + void addExposedField(const char *name, int type); + + int hasEventIn(const char *name) const; + int hasEventOut(const char *name) const; + int hasField(const char *name) const; + int hasExposedField(const char *name) const; + + const char *getName() const { return name; } + + void* operator new(size_t n) + { + return vtkVRMLAllocator::AllocateMemory(n); + } + + void operator delete(void *vtkNotUsed(ptr)) {} + + struct NameTypeRec { + char *name; + int type; + + void* operator new(size_t n) + { + return vtkVRMLAllocator::AllocateMemory(n); + } + + void operator delete(void *vtkNotUsed(ptr)) {} + + }; + +// This is used to keep track of which field in which type of node is being +// parsed. Field are nested (nodes are contained inside MFNode/SFNode fields) +// so a stack of these is needed: + struct FieldRec + { + const VrmlNodeType *nodeType; + const char *fieldName; + }; + + // Node types are stored in this data structure: + static vtkVRMLVectorType* typeList; + static vtkVRMLVectorType* useList; + static vtkVRMLVectorType* currentField; + +private: + void add(vtkVRMLVectorType &,const char *,int); + int has(const vtkVRMLVectorType &,const char *) const; + + char *name; + + vtkVRMLVectorType eventIns; + vtkVRMLVectorType eventOuts; + vtkVRMLVectorType fields; +}; + +#endif +// +// The VrmlNodeType class is responsible for storing information about node +// or prototype types. +// + +#include + +// +// Static list of node types. +// +vtkVRMLVectorType* VrmlNodeType::typeList; +vtkVRMLVectorType* VrmlNodeType::useList; +vtkVRMLVectorType* VrmlNodeType::currentField; + +VrmlNodeType::VrmlNodeType(const char *nm) +{ + assert(nm != NULL); + name = static_cast( + vtkVRMLAllocator::AllocateMemory((strlen(nm)+1)*sizeof(char))); + strcpy(name, nm); +} + +VrmlNodeType::~VrmlNodeType() +{ + // Free strings duplicated when fields/eventIns/eventOuts added: + + int i; + for (i = 0;i < eventIns.Count(); i++) + { + NameTypeRec *r = eventIns[i]; +// free(r->name); + delete r; + } + for (i = 0;i < eventOuts.Count(); i++) + { + NameTypeRec *r = eventOuts[i]; +// free(r->name); + delete r; + } + for (i = 0;i < fields.Count(); i++) + { + NameTypeRec *r = fields[i]; +// free(r->name); + delete r; + } +} + +void +VrmlNodeType::addToNameSpace(VrmlNodeType *_type) +{ + if (find(_type->getName()) != NULL) + { + cerr << "PROTO " << _type->getName() << " already defined\n"; + return; + } + *typeList += _type; +} + +// +// One list is used to store all the node types. Nested namespaces are +// separated by NULL elements. +// This isn't terribly efficient, but it is nice and simple. +// +void +VrmlNodeType::pushNameSpace() +{ + *typeList += (VrmlNodeType *) NULL; +} + +void +VrmlNodeType::popNameSpace() +{ + // Remove everything up to and including the next NULL marker: + for (int i = 0;i < typeList->Count(); i++) + { + VrmlNodeType *nodeType = typeList->Pop(); + + if (nodeType == NULL) + { + break; + } + else + { + // NOTE: Instead of just deleting the VrmlNodeTypes, you will + // probably want to reference count or garbage collect them, since + // any nodes created as part of the PROTO implementation will + // probably point back to their VrmlNodeType structure. + delete nodeType; + } + } +} + +const VrmlNodeType * +VrmlNodeType::find(const char *_name) +{ + // Look through the type stack: + for (int i = 0;i < typeList->Count(); i++) + { + const VrmlNodeType *nt = (*typeList)[i]; + if (nt != NULL && strcmp(nt->getName(),_name) == 0) + { + return nt; + } + } + return NULL; +} + +void +VrmlNodeType::addEventIn(const char *nodeName, int type) +{ + add(eventIns, nodeName, type); +}; +void +VrmlNodeType::addEventOut(const char *nodeName, int type) +{ + add(eventOuts, nodeName, type); +}; +void +VrmlNodeType::addField(const char *nodeName, int type) +{ + add(fields, nodeName, type); +}; +void +VrmlNodeType::addExposedField(const char *nodeName, int type) +{ + char tmp[1000]; + add(fields, nodeName, type); + sprintf(tmp, "set_%s", nodeName); + add(eventIns, tmp, type); + sprintf(tmp, "%s_changed", nodeName); + add(eventOuts, tmp, type); +}; + +void +VrmlNodeType::add(vtkVRMLVectorType &recs, const char *nodeName, int type) +{ + NameTypeRec *r = new NameTypeRec; + r->name = vtkVRMLAllocator::StrDup(nodeName); //strdup(nodeName); + r->type = type; + recs += r; +} + +int +VrmlNodeType::hasEventIn(const char *nodeName) const +{ + return has(eventIns, nodeName); +} +int +VrmlNodeType::hasEventOut(const char *nodeName) const +{ + return has(eventOuts, nodeName); +} +int +VrmlNodeType::hasField(const char *nodeName) const +{ + return has(fields, nodeName); +} +int +VrmlNodeType::hasExposedField(const char *nodeName) const +{ + // Must have field "name", eventIn "set_name", and eventOut + // "name_changed", all with same type: + char tmp[1000]; + int type; + if ( (type = has(fields, nodeName)) == 0) return 0; + + sprintf(tmp, "set_%s\n", nodeName); + if (type != has(eventIns, nodeName)) return 0; + + sprintf(tmp, "%s_changed", nodeName); + if (type != has(eventOuts, nodeName)) return 0; + + return type; +} +int +VrmlNodeType::has(const vtkVRMLVectorType &recs, const char *nodeName) const +{ + for (int i = 0;i < recs.Count(); i++) + { + NameTypeRec *n = recs.Get(i); + if (strcmp(n->name, nodeName) == 0) + return n->type; + } + return 0; +} +// Here comes the parser and lexer. + +// Begin of Auto-generated Parser Code + + +/* A Bison parser, made from parser.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define IDENTIFIER 258 +#define DEF 259 +#define USE 260 +#define PROTO 261 +#define EXTERNPROTO 262 +#define TO 263 +#define IS 264 +#define ROUTE 265 +#define SFN_NULL 266 +#define EVENTIN 267 +#define EVENTOUT 268 +#define FIELD 269 +#define EXPOSEDFIELD 270 +#define SFBOOL 271 +#define SFCOLOR 272 +#define SFFLOAT 273 +#define SFIMAGE 274 +#define SFINT32 275 +#define SFNODE 276 +#define SFROTATION 277 +#define SFSTRING 278 +#define SFTIME 279 +#define SFVEC2F 280 +#define SFVEC3F 281 +#define MFCOLOR 282 +#define MFFLOAT 283 +#define MFINT32 284 +#define MFROTATION 285 +#define MFSTRING 286 +#define MFVEC2F 287 +#define MFVEC3F 288 +#define MFNODE 289 + + + +// +// Parser for VRML 2.0 files. +// This is a minimal parser that does NOT generate an in-memory scene graph. +// + +// The original parser was developed on a Windows 95 PC with +// Borland's C++ 5.0 development tools. This was then ported +// to a Windows 95 PC with Microsoft's MSDEV C++ 4.0 development +// tools. The port introduced the ifdef's for +// USING_BORLAND_CPP_5 : since this provides a "std namespace", +// TWO_ARGUMENTS_FOR_STL_STACK : STL is a moving target. The stack template +// class takes either one or two arguments. + + +#define YYDEBUG 1 + +#ifndef __APPLE__ +#include +#endif + +#ifdef USE_STD_NAMESPACE +using namespace std; +#endif +#undef bool + + +// Currently-being-define proto. Prototypes may be nested, so a stack +// is needed: + +static vtkVRMLVectorType *CurrentProtoStack = NULL; + + +// This is used when the parser knows what kind of token it expects +// to get next-- used when parsing field values (whose types are declared +// and read by the parser) and at certain other places: +extern int expectToken; + +// Current line number (set by lexer) +extern int currentLineNumber; + +// Some helper routines defined below: +static void beginProto(const char *); +static void endProto(); + +static int addField(const char *type, const char *name); +static int addEventIn(const char *type, const char *name); +static int addEventOut(const char *type, const char *name); +static int addExposedField(const char *type, const char *name); +static int add(void (VrmlNodeType::*)(const char *, int), const char *, + const char *); +static int fieldType(const char *type); +static void inScript(); +static void expect(int type); + +void yyerror(const char *); +int yylex(vtkVRMLImporter* self); + + +typedef union { + char *string; + + /* Other types that will be needed by a true VRML implementation + * (but are not defined by this parser due to the complexity): + * Node *node; + * list *nodeList; + */ + + float sffloat; + vtkPoints *vec3f; + vtkFloatArray *vec2f; + vtkIdTypeArray *mfint32; + int sfint; +} YYSTYPE; + +#ifndef YYLTYPE +typedef +struct yyltype +{ + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; +} +yyltype; + +#define YYLTYPE yyltype +#endif + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + +#define YYFINAL 128 +#define YYFLAG -32768 +#define YYNTBASE 40 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 289 ? yytranslate[x] : 68) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 39, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 35, 2, 36, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 37, 2, 38, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 3, 6, 8, 10, 12, 14, 15, 16, + 22, 25, 27, 29, 30, 40, 41, 42, 51, 52, + 55, 59, 63, 64, 70, 71, 77, 78, 81, 85, + 89, 93, 97, 106, 107, 113, 114, 117, 118, 122, + 124, 126, 130, 134, 135, 141, 147, 153, 155, 157, + 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, + 179, 181, 183, 185, 187, 190, 193, 196, 199, 203, + 205, 206 +}; + +static const short yyrhs[] = { 41, + 0, 0, 41, 42, 0, 43, 0, 46, 0, 58, + 0, 59, 0, 0, 0, 4, 44, 3, 45, 59, + 0, 5, 3, 0, 47, 0, 49, 0, 0, 6, + 3, 48, 35, 52, 36, 37, 41, 38, 0, 0, + 0, 7, 3, 50, 35, 56, 36, 51, 65, 0, + 0, 52, 53, 0, 12, 3, 3, 0, 13, 3, + 3, 0, 0, 14, 3, 3, 54, 65, 0, 0, + 15, 3, 3, 55, 65, 0, 0, 56, 57, 0, + 12, 3, 3, 0, 13, 3, 3, 0, 14, 3, + 3, 0, 15, 3, 3, 0, 10, 3, 39, 3, + 8, 3, 39, 3, 0, 0, 3, 60, 37, 61, + 38, 0, 0, 61, 62, 0, 0, 3, 63, 65, + 0, 58, 0, 46, 0, 12, 3, 3, 0, 13, + 3, 3, 0, 0, 14, 3, 3, 64, 65, 0, + 12, 3, 3, 9, 3, 0, 13, 3, 3, 9, + 3, 0, 16, 0, 17, 0, 27, 0, 18, 0, + 28, 0, 19, 0, 20, 0, 29, 0, 22, 0, + 30, 0, 23, 0, 31, 0, 24, 0, 25, 0, + 32, 0, 26, 0, 33, 0, 21, 43, 0, 21, + 11, 0, 34, 66, 0, 9, 3, 0, 35, 67, + 36, 0, 43, 0, 0, 67, 43, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 106, 109, 111, 114, 116, 117, 120, 122, 123, 124, + 125, 128, 130, 133, 135, 139, 141, 143, 145, 147, + 150, 153, 155, 157, 158, 160, 163, 165, 168, 171, + 173, 175, 179, 184, 186, 189, 191, 194, 196, 197, + 198, 201, 202, 203, 206, 207, 209, 213, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 232, 233, 234, 235, 238, 240, + 243, 245 +}; + +static const char * const yytname[] = { "$","error","$undefined.","IDENTIFIER", + "DEF","USE","PROTO","EXTERNPROTO","TO","IS","ROUTE","SFN_NULL","EVENTIN","EVENTOUT", + "FIELD","EXPOSEDFIELD","SFBOOL","SFCOLOR","SFFLOAT","SFIMAGE","SFINT32","SFNODE", + "SFROTATION","SFSTRING","SFTIME","SFVEC2F","SFVEC3F","MFCOLOR","MFFLOAT","MFINT32", + "MFROTATION","MFSTRING","MFVEC2F","MFVEC3F","MFNODE","'['","']'","'{'","'}'", + "'.'","vrmlscene","declarations","declaration","nodeDeclaration","@1","@2","protoDeclaration", + "proto","@3","externproto","@4","@5","interfaceDeclarations","interfaceDeclaration", + "@6","@7","externInterfaceDeclarations","externInterfaceDeclaration","routeDeclaration", + "node","@8","nodeGuts","nodeGut","@9","@10","fieldValue","mfnodeValue","nodes", + "" +}; +#endif + +static const short yyr1[] = { 0, + 40, 41, 41, 42, 42, 42, 43, 44, 45, 43, + 43, 46, 46, 48, 47, 50, 51, 49, 52, 52, + 53, 53, 54, 53, 55, 53, 56, 56, 57, 57, + 57, 57, 58, 60, 59, 61, 61, 63, 62, 62, + 62, 62, 62, 64, 62, 62, 62, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 66, 66, + 67, 67 +}; + +static const short yyr2[] = { 0, + 1, 0, 2, 1, 1, 1, 1, 0, 0, 5, + 2, 1, 1, 0, 9, 0, 0, 8, 0, 2, + 3, 3, 0, 5, 0, 5, 0, 2, 3, 3, + 3, 3, 8, 0, 5, 0, 2, 0, 3, 1, + 1, 3, 3, 0, 5, 5, 5, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 3, 1, + 0, 2 +}; + +static const short yydefact[] = { 2, + 1, 34, 8, 0, 0, 0, 0, 3, 4, 5, + 12, 13, 6, 7, 0, 0, 11, 14, 16, 0, + 36, 9, 0, 0, 0, 0, 0, 19, 27, 0, + 38, 0, 0, 0, 35, 41, 40, 37, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 20, 0, 0, 0, 0, 17, 28, 0, 0, + 48, 49, 51, 53, 54, 0, 56, 58, 60, 61, + 63, 50, 52, 55, 57, 59, 62, 64, 0, 39, + 42, 43, 44, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 68, 66, 65, 71, 70, 67, + 0, 0, 0, 21, 22, 23, 25, 0, 29, 30, + 31, 32, 18, 33, 0, 46, 47, 45, 0, 0, + 15, 69, 72, 24, 26, 0, 0, 0 +}; + +static const short yydefgoto[] = { 126, + 1, 8, 9, 16, 27, 10, 11, 23, 12, 24, + 93, 40, 52, 119, 120, 41, 58, 13, 14, 15, + 26, 38, 43, 103, 80, 100, 115 +}; + +static const short yypact[] = {-32768, + 79,-32768,-32768, -1, 0, 3, 4,-32768,-32768,-32768, + -32768,-32768,-32768,-32768, -28, 11,-32768,-32768,-32768, -18, + -32768,-32768, -6, 5, 32, -2, 38,-32768,-32768, 35, + -32768, 39, 41, 45,-32768,-32768,-32768,-32768,-32768, 19, + 66, 48, 43, 50, 51, 54, 84, 85, 87, 88, + 55,-32768, 90, 91, 92, 93,-32768,-32768, 58, 95, + -32768,-32768,-32768,-32768,-32768, 34,-32768,-32768,-32768,-32768, + -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 23,-32768, + 94, 96,-32768, 97, 98, 101, 103,-32768, 104, 105, + 106, 107, 43, 108,-32768,-32768,-32768,-32768,-32768,-32768, + 109, 110, 43,-32768,-32768,-32768,-32768, 12,-32768,-32768, + -32768,-32768,-32768,-32768, 20,-32768,-32768,-32768, 43, 43, + -32768,-32768,-32768,-32768,-32768, 99, 114,-32768 +}; + +static const short yypgoto[] = {-32768, + 27,-32768, -66,-32768,-32768, 100,-32768,-32768,-32768,-32768, + -32768,-32768,-32768,-32768,-32768,-32768,-32768, 102, 89,-32768, + -32768,-32768,-32768,-32768, -73,-32768,-32768 +}; + + +#define YYLAST 128 + + +static const short yytable[] = { 97, + 31, 17, 18, 5, 6, 19, 20, 7, 21, 32, + 33, 34, 99, 22, 2, 3, 4, 5, 6, 113, + 25, 7, 2, 3, 4, 2, 3, 4, 28, 118, + 47, 48, 49, 50, 30, 35, 2, 3, 4, 29, + 2, 44, 42, 45, 96, 124, 125, 46, 123, 121, + 59, 60, 81, 82, 51, 122, 83, 98, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 53, 54, 55, + 56, 2, 3, 4, 5, 6, 84, 85, 7, 86, + 87, 88, 89, 90, 91, 92, 94, 95, 127, 104, + 105, 57, 101, 106, 102, 107, 109, 110, 111, 112, + 114, 116, 117, 128, 108, 39, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36, 0, 37 +}; + +static const short yycheck[] = { 66, + 3, 3, 3, 6, 7, 3, 3, 10, 37, 12, + 13, 14, 79, 3, 3, 4, 5, 6, 7, 93, + 39, 10, 3, 4, 5, 3, 4, 5, 35, 103, + 12, 13, 14, 15, 3, 38, 3, 4, 5, 35, + 3, 3, 8, 3, 11, 119, 120, 3, 115, 38, + 3, 9, 3, 3, 36, 36, 3, 35, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 12, 13, 14, + 15, 3, 4, 5, 6, 7, 3, 3, 10, 3, + 3, 37, 3, 3, 3, 3, 39, 3, 0, 3, + 3, 36, 9, 3, 9, 3, 3, 3, 3, 3, + 3, 3, 3, 0, 88, 27, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 26, -1, 26 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ + + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +extern int yylex(vtkVRMLImporter* self); +extern void yyerror(); + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include +#pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#include +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (vtkVRMLImporter*); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; +char *to; +int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + + + +int +yyparse(vtkVRMLImporter* self) +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + + /* Push a new state, which is found in yystate . */ + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ + yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + + /* Do appropriate processing given the current state. */ + /* Read a lookahead token if we need one and don't already have one. */ + /* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = yylex(self); + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + /* Do the default action for the current state. */ + yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + + /* Do a reduction. yyn is the number of a rule to reduce with. */ + yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + else + yyval.sfint = 0; + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + // Note: several free() methods are commented out due to the use of + // vtkVRMLAllocator. + switch (yyn) { + + case 8: + { creatingDEF = 1; ; + break;} + case 9: + { curDEFName = yyvsp[0].string; ; + break;} + case 10: + { creatingDEF = 0; ; + break;} + case 11: + { self->useNode(yyvsp[0].string);//free(yyvsp[0].string); ; + break;} + case 14: + { beginProto(yyvsp[0].string); ; + break;} + case 15: + { endProto(); //free(yyvsp[-7].string);; + break;} + case 16: + { beginProto(yyvsp[0].string); ; + break;} + case 17: + { expect(MFSTRING); ; + break;} + case 18: + { endProto(); //free(yyvsp[-6].string); ; + break;} + case 21: + { addEventIn(yyvsp[-1].string, yyvsp[0].string); + //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 22: + { addEventOut(yyvsp[-1].string, yyvsp[0].string); + //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 23: + { int type = addField(yyvsp[-1].string, yyvsp[0].string); + expect(type); ; + break;} + case 24: + { //free(yyvsp[-3].string); free(yyvsp[-2].string); ; + break;} + case 25: + { int type = addExposedField(yyvsp[-1].string, yyvsp[0].string); + expect(type); ; + break;} + case 26: + { //free(yyvsp[-3].string); free(yyvsp[-2].string); ; + break;} + case 29: + { addEventIn(yyvsp[-1].string, yyvsp[0].string); + //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 30: + { addEventOut(yyvsp[-1].string, yyvsp[0].string); + //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 31: + { addField(yyvsp[-1].string, yyvsp[0].string); + //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 32: + { addExposedField(yyvsp[-1].string, yyvsp[0].string); + //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 33: + { //free(yyvsp[-6].string); free(yyvsp[-4].string); free(yyvsp[-2].string); free(yyvsp[0].string); ; + break;} + case 34: + { self->enterNode(yyvsp[0].string); ; + break;} + case 35: + { self->exitNode(); //free(yyvsp[-4].string);; + break;} + case 38: + { self->enterField(yyvsp[0].string); ; + break;} + case 39: + { self->exitField(); //free(yyvsp[-2].string); ; + break;} + case 42: + { inScript(); //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 43: + { inScript(); //free(yyvsp[-1].string); free(yyvsp[0].string); ; + break;} + case 44: + { inScript(); + int type = fieldType(yyvsp[-1].string); + expect(type); ; + break;} + case 45: + { //free(yyvsp[-3].string); free(yyvsp[-2].string); ; + break;} + case 46: + { inScript(); //free(yyvsp[-3].string); free(yyvsp[-2].string); free(yyvsp[0].string); ; + break;} + case 47: + { inScript(); //free(yyvsp[-3].string); free(yyvsp[-2].string); free(yyvsp[0].string); ; + break;} + case 49: + {; + break;} + case 50: + { break;} + case 55: + { break;} + case 63: + { ; + break;} + case 64: + { break;} + case 68: + { //free(yyvsp[0].string); ; + break;} + } + /* the action file gets copied in in place of this dollarsign */ + + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + + yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; + yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + + yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + + yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} + + +void +yyerror(const char *msg) +{ + cerr << "Error near line " << currentLineNumber << ": " << msg << "\n"; + expect(0); +} + +static void +beginProto(const char *protoName) +{ + // Any protos in the implementation are in a local namespace: + VrmlNodeType::pushNameSpace(); + + VrmlNodeType *t = new VrmlNodeType(protoName); + *CurrentProtoStack += t; +} + +static void +endProto() +{ + // Make any protos defined in implementation unavailable: + VrmlNodeType::popNameSpace(); + + // Add this proto definition: + if (CurrentProtoStack->Count() == 0) + { + cerr << "Error: Empty PROTO stack!\n"; + } + else + { + VrmlNodeType *t = CurrentProtoStack->Top(); + CurrentProtoStack->Pop(); + VrmlNodeType::addToNameSpace(t); + } +} + +static int +addField(const char *type, const char *name) +{ + return add(&VrmlNodeType::addField, type, name); +} + +static int +addEventIn(const char *type, const char *name) +{ + return add(&VrmlNodeType::addEventIn, type, name); +} +static int +addEventOut(const char *type, const char *name) +{ + return add(&VrmlNodeType::addEventOut, type, name); +} +static int +addExposedField(const char *type, const char *name) +{ + return add(&VrmlNodeType::addExposedField, type, name); +} + +static int +add(void (VrmlNodeType::*func)(const char *, int), + const char *typeString, const char *name) +{ + int type = fieldType(typeString); + + if (type == 0) + { + cerr << "Error: invalid field type: " << type << "\n"; + } + + // Need to add support for Script nodes: + // if (inScript) ... ??? + + if (CurrentProtoStack->Count() == 0) + { + cerr << "Error: declaration outside of prototype\n"; + return 0; + } + VrmlNodeType *t = CurrentProtoStack->Top(); + (t->*func)(name, type); + + return type; +} + +static int +fieldType(const char *type) +{ + if (strcmp(type, "SFBool") == 0) return SFBOOL; + if (strcmp(type, "SFColor") == 0) return SFCOLOR; + if (strcmp(type, "SFFloat") == 0) return SFFLOAT; + if (strcmp(type, "SFImage") == 0) return SFIMAGE; + if (strcmp(type, "SFInt32") == 0) return SFINT32; + if (strcmp(type, "SFNode") == 0) return SFNODE; + if (strcmp(type, "SFRotation") == 0) return SFROTATION; + if (strcmp(type, "SFString") == 0) return SFSTRING; + if (strcmp(type, "SFTime") == 0) return SFTIME; + if (strcmp(type, "SFVec2f") == 0) return SFVEC2F; + if (strcmp(type, "SFVec3f") == 0) return SFVEC3F; + if (strcmp(type, "MFColor") == 0) return MFCOLOR; + if (strcmp(type, "MFFloat") == 0) return MFFLOAT; + if (strcmp(type, "MFInt32") == 0) return MFINT32; + if (strcmp(type, "MFNode") == 0) return MFNODE; + if (strcmp(type, "MFRotation") == 0) return MFROTATION; + if (strcmp(type, "MFString") == 0) return MFSTRING; + if (strcmp(type, "MFVec2f") == 0) return MFVEC2F; + if (strcmp(type, "MFVec3f") == 0) return MFVEC3F; + + cerr << "Illegal field type: " << type << "\n"; + + return 0; +} + +static void +inScript() +{ + VrmlNodeType::FieldRec *fr = VrmlNodeType::currentField->Top(); + if (fr->nodeType == NULL || + strcmp(fr->nodeType->getName(), "Script") != 0) + { + yyerror("interface declaration outside of Script or prototype"); + } +} + + +static void +expect(int type) +{ + expectToken = type; +} + +// End of Auto-generated Parser Code +// Begin of Auto-generated Lexer Code + +/* A lexical scanner generated by flex */ + + +#define FLEX_SCANNER + +#ifdef WIN32 +#include +#else +#include +#endif + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#ifdef __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + + +#ifdef __TURBOC__ +#define YY_USE_CONST +#endif + + +#ifndef YY_USE_CONST +#ifndef const +#define const +#endif +#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. + */ +#define YY_START ((yy_start - 1) / 2) + +/* 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". Now included + * only for backward compatibility with previous versions of flex. + */ +#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; +extern FILE *yyin, *yyout; + +#ifdef __cplusplus +extern "C" { +#endif + extern int yywrap YY_PROTO(( void )); +#ifdef __cplusplus +} +#endif + +#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_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + + +struct yy_buffer_state +{ + FILE *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. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* 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 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 +}; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* 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 + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* 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 ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); + +static void *yy_flex_alloc YY_PROTO(( unsigned int )); +static void *yy_flex_realloc YY_PROTO(( void *, unsigned int )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define INITIAL 0 +#define NODE 1 +#define SFB 2 +#define SFC 3 +#define SFF 4 +#define SFIMG 5 +#define SFI 6 +#define SFR 7 +#define SFS 8 +#define SFT 9 +#define SFV2 10 +#define SFV3 11 +#define MFC 12 +#define MFF 13 +#define MFI 14 +#define MFR 15 +#define MFS 16 +#define MFV2 17 +#define MFV3 18 +#define IN_SFS 19 +#define IN_MFS 20 +#define IN_SFIMG 21 +typedef unsigned char YY_CHAR; +typedef int yy_state_type; + +#define FLEX_DEBUG +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +extern char *yytext; +#define yytext_ptr yytext + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, const char *, int )); +#endif + +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( const char msg[] )); + +/* 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 = yy_cp - yy_bp; \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_END_OF_BUFFER 50 +static const short int yy_accept[949] = +{ 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 48, 46, 47, 46, 14, + 46, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 48, 48, 48, 48, 48, 48, 48, 48, 25, + 48, 48, 48, 48, 23, 23, 48, 48, 48, 38, + 36, 38, 38, 48, 48, 35, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 19, 20, 48, 48, + + 26, 17, 48, 24, 24, 18, 48, 48, 48, 39, + 37, 39, 39, 48, 48, 48, 48, 48, 48, 41, + 41, 42, 41, 41, 43, 48, 45, 45, 46, 47, + 46, 47, 47, 46, 46, 46, 46, 14, 14, 14, + 7, 14, 14, 14, 6, 14, 14, 14, 14, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 25, + 25, 0, 0, 0, 0, 0, 23, 23, 0, 0, + 0, 0, 0, 0, 38, 38, 38, 15, 0, 35, + 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 16, 0, 26, 26, 0, 24, 24, 0, 0, 0, + 0, 0, 0, 39, 39, 39, 16, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, + 41, 41, 41, 41, 41, 40, 45, 45, 47, 47, + 47, 46, 4, 14, 14, 14, 14, 5, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 25, 0, 44, 44, 0, + 0, 0, 0, 44, 44, 0, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, + 0, 0, 27, 0, 0, 0, 0, 0, 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, 26, 24, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, + 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, + 46, 14, 9, 14, 14, 14, 14, 14, 0, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, + 0, 0, 0, 0, 0, 0, 0, 0, 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, 28, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 46, 14, 2, 8, + 14, 14, 12, 22, 0, 0, 33, 0, 0, 0, + 0, 0, 33, 0, 0, 0, 0, 33, 0, 0, + 0, 33, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 44, 44, 44, 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, 27, 0, 0, 27, 0, 0, 29, + + 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, + 29, 0, 0, 0, 29, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 0, 0, 34, 0, 0, 0, + 0, 0, 34, 0, 0, 0, 0, 34, 0, 0, + 0, 34, 0, 0, 0, 0, 0, 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, 0, 0, 28, + 0, 0, 28, 0, 0, 30, 0, 0, 0, 0, + 0, 30, 0, 0, 0, 0, 30, 0, 0, 0, + + 30, 0, 0, 0, 0, 0, 30, 0, 0, 0, + 46, 14, 14, 14, 14, 33, 0, 0, 33, 0, + 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29, 0, 0, 29, 0, 29, 0, 0, + 34, 0, 0, 34, 0, 34, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, + 30, 0, 30, 0, 0, 46, 14, 10, 14, 14, + 0, 33, 0, 0, 33, 0, 0, 33, 0, 33, + + 0, 0, 33, 0, 0, 31, 0, 0, 0, 0, + 0, 31, 0, 0, 0, 0, 31, 0, 0, 31, + 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, + 0, 31, 0, 0, 0, 31, 0, 0, 0, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 0, 31, + 0, 0, 0, 0, 29, 0, 0, 29, 0, 0, + 29, 0, 29, 0, 0, 29, 0, 34, 0, 0, + 34, 0, 0, 34, 0, 34, 0, 0, 34, 0, + 0, 32, 0, 0, 0, 0, 0, 32, 0, 0, + 0, 0, 32, 0, 0, 32, 0, 0, 0, 0, + + 0, 32, 0, 0, 0, 0, 0, 32, 0, 0, + 0, 32, 0, 0, 0, 0, 0, 32, 0, 0, + 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, + 30, 0, 0, 30, 0, 0, 30, 0, 30, 0, + 0, 30, 46, 14, 11, 14, 31, 0, 0, 31, + 0, 31, 0, 0, 31, 0, 31, 0, 0, 31, + 0, 32, 0, 0, 32, 0, 32, 0, 0, 32, + 0, 32, 0, 0, 32, 0, 46, 14, 14, 0, + 31, 0, 0, 31, 0, 0, 31, 0, 31, 0, + 0, 31, 0, 0, 31, 0, 31, 0, 0, 31, + + 0, 0, 31, 0, 32, 0, 0, 32, 0, 0, + 32, 0, 32, 0, 0, 32, 0, 0, 32, 0, + 32, 0, 0, 32, 0, 0, 32, 46, 14, 14, + 46, 3, 14, 46, 13, 46, 46, 46, 46, 46, + 1, 46, 1, 1, 1, 1, 1, 0 +} ; + +static const int yy_ec[256] = +{ 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 6, 7, 5, 5, 5, 1, 5, + 5, 5, 8, 2, 9, 10, 5, 11, 12, 13, + 12, 12, 12, 12, 12, 14, 12, 5, 5, 5, + 5, 5, 5, 5, 15, 16, 16, 17, 18, 19, + 5, 5, 20, 5, 5, 21, 22, 23, 24, 25, + 5, 26, 27, 28, 29, 30, 5, 31, 5, 5, + 32, 33, 34, 5, 5, 5, 16, 16, 16, 35, + + 36, 37, 5, 5, 38, 5, 5, 39, 5, 40, + 41, 42, 5, 5, 43, 44, 45, 46, 5, 47, + 5, 5, 1, 5, 1, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5 +} ; + +static const int yy_meta[48] = +{ 0, + 1, 2, 3, 2, 4, 5, 6, 4, 4, 1, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 8, 1, 8, 7, 7, 7, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4 +} ; + +static const short int yy_base[1090] = +{ 0, + 0, 6, 13, 0, 59, 65, 92, 0, 104, 110, + 116, 122, 128, 134, 140, 146, 159, 165, 164, 177, + 183, 189, 195, 201, 207, 233, 259, 285, 311, 337, + 363, 389, 422, 455, 481, 507, 533, 559, 222, 228, + 256, 274, 324, 350, 787, 7663, 73, 79, 280, 0, + 247, 768, 753, 751, 745, 726, 725, 719, 715, 18, + 685, 702, 687, 682, 78, 96, 592, 170, 289, 368, + 300, 627, 51, 315, 380, 328, 342, 354, 673, 0, + 7663, 410, 677, 420, 376, 427, 436, 394, 708, 454, + 458, 743, 466, 470, 778, 676, 7663, 7663, 486, 491, + + 496, 7663, 511, 517, 522, 7663, 544, 538, 813, 0, + 7663, 579, 665, 549, 563, 848, 604, 576, 883, 0, + 605, 7663, 617, 672, 7663, 631, 635, 639, 652, 302, + 658, 665, 666, 686, 692, 698, 725, 0, 652, 636, + 0, 636, 613, 607, 0, 617, 597, 590, 591, 605, + 7663, 596, 722, 0, 727, 918, 931, 751, 755, 792, + 759, 821, 0, 944, 957, 805, 786, 0, 825, 0, + 830, 970, 983, 856, 0, 869, 875, 0, 834, 900, + 987, 891, 895, 0, 996, 1022, 1035, 1003, 1007, 0, + 1040, 1053, 1066, 1073, 1077, 0, 1082, 1095, 1108, 1115, + + 7663, 1119, 1124, 1132, 1140, 1144, 0, 1150, 0, 1159, + 1172, 1185, 1192, 0, 1205, 1211, 0, 1208, 0, 1213, + 1244, 1257, 1220, 1261, 1274, 1283, 1309, 1322, 1290, 0, + 1335, 1341, 1347, 1353, 1359, 7663, 1294, 0, 1234, 1365, + 1366, 1372, 0, 604, 580, 572, 569, 0, 552, 537, + 501, 511, 519, 1370, 1374, 1393, 1428, 1441, 0, 0, + 0, 1410, 1378, 1454, 1407, 1411, 1458, 1462, 1466, 1508, + 1521, 1534, 1547, 1560, 191, 1479, 0, 1477, 1483, 1606, + 1641, 1654, 0, 0, 0, 1575, 1487, 1667, 1491, 1572, + 1584, 1576, 1623, 1680, 0, 0, 0, 0, 230, 1588, + + 1693, 1615, 1592, 1706, 1741, 0, 0, 0, 0, 1723, + 1720, 1758, 1725, 1762, 1775, 1810, 0, 0, 0, 0, + 1792, 1789, 1827, 1793, 1831, 0, 1836, 1840, 1853, 1888, + 0, 0, 0, 0, 1870, 1867, 1905, 1872, 1909, 1914, + 1949, 0, 0, 0, 0, 238, 1922, 1962, 1927, 1931, + 1975, 2010, 0, 0, 0, 0, 1992, 1935, 2027, 0, + 2040, 500, 0, 488, 493, 444, 443, 450, 456, 7663, + 1990, 2060, 2073, 2037, 2086, 2099, 2112, 2044, 0, 2116, + 1995, 2162, 2175, 2128, 2188, 2201, 2214, 2227, 2132, 2146, + 2240, 2253, 2288, 2301, 2261, 2314, 2327, 2340, 2353, 2366, + + 2401, 2414, 2268, 2427, 2440, 2453, 2466, 2479, 2514, 2527, + 2374, 2540, 2553, 2566, 2579, 2383, 2487, 2592, 2605, 2640, + 2653, 2494, 2666, 2679, 2692, 2705, 2281, 437, 0, 0, + 50, 386, 0, 7663, 2379, 2498, 2622, 2718, 2731, 0, + 0, 0, 239, 2613, 2744, 2757, 2770, 2783, 2818, 2792, + 2617, 2831, 2866, 0, 0, 0, 0, 272, 2796, 2800, + 2845, 0, 2881, 205, 285, 2840, 2804, 2927, 2962, 2975, + 0, 0, 0, 2944, 2941, 2988, 3001, 3014, 3027, 3062, + 2946, 3035, 3075, 3110, 0, 0, 0, 0, 3092, 3039, + 3043, 3127, 3047, 3089, 3162, 3175, 400, 3094, 3135, 3144, + + 3188, 3201, 0, 0, 0, 417, 3139, 3214, 3227, 3240, + 3253, 3288, 3262, 3266, 3301, 3336, 0, 0, 0, 0, + 437, 3270, 3274, 3315, 3310, 3341, 3346, 3381, 3394, 0, + 0, 0, 548, 3354, 3407, 3420, 3433, 3446, 3481, 3359, + 3363, 3494, 3529, 0, 0, 0, 0, 562, 3367, 3454, + 3463, 3503, 3458, 3542, 3577, 3590, 0, 0, 0, 3559, + 3507, 3603, 3616, 3629, 3642, 3677, 3512, 3556, 3690, 3725, + 0, 0, 0, 0, 3659, 3560, 3656, 3738, 3660, 3698, + 3773, 3786, 645, 3703, 3707, 3755, 3799, 3812, 0, 0, + 0, 661, 3711, 3825, 3838, 3851, 3864, 3899, 3747, 3872, + + 3912, 3947, 0, 0, 0, 0, 680, 3876, 3880, 3926, + 3925, 390, 370, 351, 323, 3952, 3960, 3987, 4000, 4035, + 4048, 3967, 4083, 4096, 4131, 4144, 4008, 4157, 4170, 4183, + 4196, 4209, 4244, 4257, 4270, 4283, 4296, 4331, 4015, 4344, + 4357, 4370, 4065, 4056, 4383, 4396, 4431, 4444, 4104, 4479, + 4113, 4217, 4492, 4505, 4540, 4553, 4224, 4588, 4601, 4636, + 4649, 4304, 4662, 4675, 4688, 4701, 4714, 4749, 4762, 4775, + 4788, 4801, 4836, 4311, 4849, 4862, 4875, 4413, 4404, 4888, + 4901, 4936, 4949, 4452, 4984, 2858, 304, 0, 274, 296, + 3884, 3971, 4997, 5010, 688, 5023, 5036, 4522, 4019, 5049, + + 5062, 5075, 689, 4061, 4108, 4461, 5088, 5101, 0, 0, + 0, 695, 4228, 5114, 5127, 5140, 5153, 4316, 4408, 5188, + 5223, 5236, 0, 0, 0, 712, 4456, 4519, 4570, 5249, + 5262, 5275, 5310, 4524, 4561, 5323, 5358, 0, 0, 0, + 0, 740, 4565, 4609, 4618, 4613, 5371, 5384, 5397, 5410, + 4722, 4726, 4731, 4809, 4813, 5445, 5458, 757, 5471, 5484, + 4918, 4817, 5497, 5510, 5523, 765, 4821, 4915, 5536, 5549, + 838, 5562, 5575, 4966, 4919, 5588, 5601, 5614, 862, 4964, + 4968, 5167, 5627, 5640, 0, 0, 0, 931, 5161, 5653, + 5666, 5679, 5692, 5197, 5201, 5727, 5762, 5775, 0, 0, + + 0, 986, 5205, 5209, 5292, 5788, 5801, 5814, 5849, 5284, + 5331, 5862, 5897, 0, 0, 0, 0, 1022, 5335, 5339, + 5427, 5343, 5910, 5923, 5936, 5949, 5418, 5422, 5706, 5700, + 5735, 5984, 5997, 1023, 6010, 6023, 5831, 5739, 6036, 6049, + 6062, 1025, 5752, 268, 0, 250, 5879, 5828, 6075, 6088, + 6123, 6136, 5870, 6171, 6184, 6219, 6232, 5957, 6267, 6280, + 6315, 5966, 6096, 6103, 5833, 6144, 5875, 6151, 6192, 5962, + 6199, 6108, 6240, 6247, 6156, 6288, 6301, 236, 204, 6203, + 6251, 6328, 0, 1065, 3, 277, 6341, 6340, 6376, 6389, + 0, 1123, 376, 411, 6402, 6344, 6437, 6450, 0, 1129, + + 435, 443, 6463, 6349, 6353, 6357, 6361, 6401, 6410, 6414, + 6464, 6418, 6499, 6422, 6472, 6478, 6504, 6508, 6513, 6521, + 6525, 6529, 6533, 6539, 6547, 6551, 6556, 3328, 213, 194, + 6569, 0, 188, 6575, 0, 6491, 3939, 5180, 5719, 6307, + 6579, 6586, 6592, 6593, 6599, 6600, 6606, 7663, 6619, 6627, + 6635, 6643, 6651, 6656, 6663, 6671, 6679, 6686, 6694, 6702, + 6710, 6718, 6726, 6733, 163, 6740, 6748, 6756, 6764, 157, + 6772, 6780, 6788, 6796, 6804, 104, 6812, 6820, 6825, 6832, + 6840, 6847, 93, 6854, 90, 6862, 6870, 66, 6878, 6886, + 6894, 6902, 6910, 6918, 6926, 6934, 6942, 6950, 6958, 6966, + + 6974, 6982, 6990, 6998, 7006, 7011, 7018, 7026, 7034, 64, + 7042, 7050, 7058, 7066, 7074, 7082, 7090, 7098, 7106, 7114, + 7122, 7130, 7138, 7146, 7154, 7162, 7170, 7178, 7183, 7190, + 7198, 7206, 7214, 7222, 7230, 7238, 7246, 7254, 7262, 7270, + 7278, 7286, 7294, 7302, 7310, 7318, 7326, 7334, 7342, 7350, + 7358, 7366, 7374, 7382, 7387, 7394, 7402, 7410, 7418, 7426, + 7434, 7442, 7450, 7458, 7466, 7474, 7482, 7490, 7498, 7506, + 7514, 7522, 7530, 7538, 7546, 7554, 7562, 7570, 7578, 7586, + 7591, 7598, 7606, 7614, 7622, 7630, 7638, 7646, 7654 +} ; + +static const short int yy_def[1090] = +{ 0, + 949, 949, 948, 3, 949, 949, 949, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 950, 950, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 951, 951, 7, 7, 7, 7, 952, 952, + 952, 952, 7, 7, 948, 948, 948, 948, 953, 954, + 953, 954, 954, 954, 954, 954, 954, 954, 954, 954, + 954, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 72, 948, 948, 948, 948, 948, 948, 955, + 948, 956, 955, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + + 948, 948, 948, 948, 948, 948, 948, 948, 948, 957, + 948, 958, 957, 948, 948, 948, 948, 948, 948, 959, + 959, 948, 960, 959, 948, 948, 948, 948, 948, 948, + 953, 948, 961, 953, 953, 953, 953, 954, 954, 954, + 954, 954, 954, 954, 954, 954, 954, 954, 954, 948, + 948, 948, 948, 67, 67, 948, 962, 948, 948, 948, + 948, 948, 73, 948, 963, 964, 948, 965, 948, 79, + 79, 948, 966, 948, 955, 956, 956, 955, 948, 948, + 948, 948, 948, 89, 89, 948, 967, 948, 948, 92, + 92, 948, 968, 948, 948, 95, 95, 948, 969, 948, + + 948, 948, 948, 948, 948, 948, 970, 948, 109, 109, + 948, 971, 948, 957, 958, 958, 957, 948, 116, 116, + 948, 972, 948, 948, 948, 225, 948, 973, 948, 974, + 974, 975, 975, 975, 975, 948, 948, 976, 977, 977, + 977, 978, 979, 979, 979, 979, 979, 979, 979, 979, + 979, 948, 948, 948, 948, 948, 980, 980, 258, 258, + 258, 258, 948, 948, 948, 948, 948, 948, 948, 981, + 981, 981, 981, 981, 274, 982, 983, 948, 948, 948, + 984, 984, 282, 282, 282, 282, 948, 948, 948, 948, + 948, 948, 948, 967, 294, 294, 294, 294, 294, 948, + + 948, 948, 948, 948, 968, 305, 305, 305, 305, 305, + 948, 948, 948, 948, 948, 969, 316, 316, 316, 316, + 316, 948, 948, 948, 948, 985, 948, 948, 948, 971, + 330, 330, 330, 330, 330, 948, 948, 948, 948, 948, + 972, 341, 341, 341, 341, 341, 948, 948, 948, 948, + 948, 973, 352, 352, 352, 352, 352, 948, 948, 976, + 978, 979, 979, 979, 979, 979, 979, 979, 948, 948, + 256, 948, 986, 948, 258, 948, 987, 258, 988, 274, + 280, 948, 989, 948, 282, 948, 990, 385, 948, 948, + 991, 948, 948, 992, 948, 993, 948, 994, 993, 948, + + 948, 995, 948, 996, 948, 997, 996, 948, 948, 998, + 948, 999, 948, 1000, 999, 948, 948, 1001, 948, 948, + 1002, 948, 1003, 948, 1004, 1003, 1005, 1006, 1006, 1006, + 1006, 1006, 1006, 948, 948, 948, 948, 1007, 1007, 439, + 439, 439, 439, 948, 948, 1008, 1008, 447, 1009, 948, + 948, 948, 1009, 453, 453, 453, 453, 453, 447, 447, + 448, 1010, 948, 463, 463, 948, 948, 948, 1011, 1011, + 470, 470, 470, 470, 948, 948, 1012, 1012, 478, 1013, + 948, 948, 948, 1013, 484, 484, 484, 484, 484, 478, + 478, 478, 948, 948, 1014, 1014, 496, 948, 948, 948, + + 1015, 1015, 502, 502, 502, 502, 948, 948, 1016, 1016, + 510, 1017, 948, 948, 948, 1017, 516, 516, 516, 516, + 516, 510, 510, 511, 948, 948, 948, 1018, 1018, 529, + 529, 529, 529, 948, 948, 1019, 1019, 537, 1020, 948, + 948, 948, 1020, 543, 543, 543, 543, 543, 537, 537, + 538, 948, 948, 948, 1021, 1021, 556, 556, 556, 556, + 948, 948, 1022, 1022, 564, 1023, 948, 948, 948, 1023, + 570, 570, 570, 570, 570, 564, 564, 564, 948, 948, + 1024, 1024, 582, 948, 948, 948, 1025, 1025, 588, 588, + 588, 588, 948, 948, 1026, 1026, 596, 1027, 948, 948, + + 948, 1027, 602, 602, 602, 602, 602, 596, 596, 597, + 1028, 1029, 1029, 1029, 1029, 948, 948, 1030, 1031, 1031, + 948, 948, 1032, 948, 948, 1033, 948, 1034, 948, 1035, + 1034, 1036, 1036, 948, 1037, 1036, 948, 1035, 948, 1038, + 1037, 1038, 948, 948, 1039, 1040, 1040, 948, 948, 1041, + 948, 948, 1042, 1043, 1043, 948, 948, 1044, 948, 948, + 1045, 948, 1046, 948, 1047, 1046, 1048, 1048, 948, 1049, + 1048, 948, 1047, 948, 1050, 1049, 1050, 948, 948, 1051, + 1052, 1052, 948, 948, 1053, 1054, 1055, 1055, 1055, 1055, + 948, 948, 1056, 1056, 694, 1057, 1057, 697, 948, 948, + + 1058, 1058, 702, 948, 948, 948, 1059, 1059, 708, 708, + 708, 708, 948, 948, 1060, 1060, 716, 948, 948, 948, + 1061, 1061, 722, 722, 722, 722, 716, 716, 717, 1062, + 1062, 731, 1063, 948, 948, 948, 1063, 737, 737, 737, + 737, 737, 731, 731, 732, 948, 948, 1064, 1064, 749, + 749, 749, 750, 948, 948, 1065, 1065, 757, 1066, 1066, + 760, 948, 948, 1067, 1067, 765, 948, 948, 1068, 1068, + 770, 1069, 1069, 773, 948, 948, 1070, 1070, 778, 948, + 948, 948, 1071, 1071, 784, 784, 784, 784, 948, 948, + 1072, 1072, 792, 948, 948, 948, 1073, 1073, 798, 798, + + 798, 798, 792, 792, 793, 1074, 1074, 807, 1075, 948, + 948, 948, 1075, 813, 813, 813, 813, 813, 807, 807, + 808, 948, 948, 1076, 1076, 825, 825, 825, 826, 948, + 948, 1077, 1077, 833, 1078, 1078, 836, 948, 948, 1079, + 1079, 841, 1080, 1081, 1081, 1081, 948, 948, 1082, 1083, + 1083, 948, 948, 1084, 1085, 1085, 948, 948, 1086, 1087, + 1087, 948, 948, 784, 793, 792, 796, 948, 798, 808, + 807, 812, 948, 813, 826, 825, 1080, 1081, 1081, 948, + 948, 1082, 882, 882, 851, 851, 851, 948, 948, 1084, + 890, 890, 856, 856, 856, 948, 948, 1086, 898, 898, + + 861, 861, 861, 948, 948, 784, 784, 784, 792, 792, + 793, 948, 948, 798, 798, 798, 807, 807, 808, 948, + 823, 813, 813, 813, 825, 825, 826, 1080, 1081, 1081, + 1080, 1081, 1081, 1080, 1081, 1080, 1080, 1088, 1088, 1088, + 948, 1088, 948, 1089, 1089, 1089, 1089, 0, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948 +} ; + +static const short int yy_nxt[7711] = +{ 0, + 948, 47, 48, 47, 948, 948, 49, 47, 48, 47, + 469, 472, 49, 46, 47, 48, 47, 50, 46, 51, + 46, 46, 46, 46, 46, 46, 46, 50, 50, 52, + 53, 50, 54, 50, 50, 55, 50, 56, 57, 50, + 58, 59, 50, 50, 46, 46, 46, 50, 60, 61, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 47, 48, 47, 147, 148, 51, 47, 48, 47, 613, + 462, 51, 462, 614, 129, 130, 129, 62, 63, 131, + 132, 948, 132, 62, 63, 133, 64, 153, 154, 154, + 154, 154, 64, 47, 48, 47, 326, 948, 51, 277, + + 65, 66, 67, 67, 67, 67, 155, 155, 155, 155, + 360, 63, 68, 69, 70, 70, 70, 70, 68, 69, + 70, 70, 70, 70, 71, 46, 72, 73, 73, 73, + 71, 46, 72, 73, 73, 73, 74, 46, 75, 76, + 76, 76, 74, 46, 75, 76, 76, 76, 77, 78, + 79, 79, 79, 79, 77, 78, 79, 79, 79, 79, + 47, 48, 47, 326, 81, 82, 47, 48, 47, 277, + 81, 82, 84, 85, 86, 86, 86, 86, 83, 159, + 160, 160, 160, 160, 83, 84, 85, 86, 86, 86, + 86, 87, 88, 89, 89, 89, 89, 87, 88, 89, + + 89, 89, 89, 90, 91, 92, 92, 92, 92, 90, + 91, 92, 92, 92, 92, 93, 94, 95, 95, 95, + 95, 270, 935, 121, 48, 121, 96, 122, 123, 121, + 48, 121, 933, 122, 123, 270, 932, 270, 97, 930, + 98, 93, 94, 95, 95, 95, 95, 391, 135, 130, + 135, 270, 96, 136, 124, 418, 618, 121, 48, 121, + 124, 125, 123, 929, 97, 391, 98, 99, 100, 101, + 101, 101, 101, 418, 618, 121, 48, 121, 96, 125, + 123, 135, 130, 135, 469, 472, 136, 879, 124, 623, + 102, 878, 98, 99, 100, 101, 101, 101, 101, 161, + + 161, 161, 161, 132, 96, 132, 124, 623, 133, 137, + 163, 163, 163, 163, 846, 270, 102, 845, 98, 103, + 46, 104, 105, 105, 105, 167, 167, 167, 167, 844, + 96, 270, 126, 46, 127, 128, 128, 128, 167, 167, + 167, 167, 106, 46, 98, 103, 46, 104, 105, 105, + 105, 169, 170, 170, 170, 170, 96, 690, 126, 46, + 127, 128, 128, 128, 171, 171, 171, 171, 106, 46, + 98, 107, 108, 109, 109, 109, 109, 159, 160, 160, + 160, 160, 96, 281, 284, 162, 181, 181, 181, 181, + 167, 167, 167, 167, 102, 689, 98, 107, 108, 109, + + 109, 109, 109, 162, 185, 185, 185, 185, 96, 688, + 168, 135, 130, 135, 687, 134, 177, 391, 281, 284, + 102, 615, 98, 47, 48, 47, 168, 111, 112, 179, + 180, 180, 180, 180, 645, 391, 179, 180, 180, 180, + 180, 113, 484, 487, 182, 183, 184, 184, 184, 184, + 484, 487, 645, 102, 650, 98, 47, 48, 47, 612, + 111, 112, 182, 189, 190, 190, 190, 190, 191, 191, + 191, 191, 650, 434, 113, 195, 196, 196, 196, 196, + 197, 197, 197, 197, 433, 432, 102, 431, 98, 114, + 115, 116, 116, 116, 116, 202, 203, 203, 203, 203, + + 96, 204, 204, 204, 204, 202, 203, 203, 203, 203, + 430, 429, 102, 205, 98, 114, 115, 116, 116, 116, + 116, 206, 206, 206, 206, 428, 96, 206, 206, 206, + 206, 205, 206, 206, 206, 206, 370, 369, 102, 368, + 98, 117, 118, 119, 119, 119, 119, 207, 210, 210, + 210, 210, 96, 208, 209, 209, 209, 209, 218, 219, + 219, 219, 219, 207, 97, 653, 98, 117, 118, 119, + 119, 119, 119, 220, 220, 220, 220, 367, 96, 658, + 135, 130, 135, 653, 134, 216, 226, 226, 226, 226, + 97, 366, 98, 156, 156, 156, 365, 658, 157, 364, + + 363, 153, 154, 154, 154, 154, 231, 130, 231, 158, + 134, 232, 134, 224, 225, 225, 225, 225, 234, 130, + 234, 362, 134, 235, 253, 252, 251, 158, 164, 164, + 164, 250, 249, 165, 248, 247, 246, 163, 163, 163, + 163, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 129, 130, 129, 245, 166, 131, 135, + 130, 135, 418, 244, 136, 238, 132, 240, 132, 240, + 243, 133, 241, 166, 172, 172, 172, 236, 680, 173, + 418, 238, 169, 170, 170, 170, 170, 135, 130, 135, + 174, 217, 136, 135, 130, 135, 680, 685, 136, 135, + + 130, 135, 201, 178, 136, 618, 623, 152, 174, 186, + 186, 186, 849, 151, 187, 685, 150, 183, 184, 184, + 184, 184, 149, 618, 623, 188, 135, 130, 135, 854, + 849, 136, 155, 155, 155, 155, 948, 155, 155, 155, + 155, 146, 145, 188, 192, 192, 192, 854, 144, 193, + 242, 143, 189, 190, 190, 190, 190, 859, 263, 263, + 194, 264, 264, 264, 264, 161, 161, 161, 161, 161, + 161, 161, 161, 142, 645, 859, 162, 141, 194, 198, + 198, 198, 650, 140, 199, 139, 948, 195, 196, 196, + 196, 196, 645, 948, 162, 200, 167, 167, 167, 167, + + 650, 159, 160, 160, 160, 160, 164, 164, 164, 162, + 948, 165, 948, 200, 211, 211, 211, 948, 948, 212, + 948, 948, 208, 209, 209, 209, 209, 162, 265, 265, + 213, 266, 266, 266, 266, 171, 171, 171, 171, 948, + 171, 171, 171, 171, 181, 181, 181, 181, 213, 221, + 221, 221, 948, 948, 222, 653, 948, 218, 219, 219, + 219, 219, 948, 287, 287, 223, 288, 288, 288, 288, + 135, 130, 135, 653, 134, 177, 135, 130, 135, 658, + 134, 177, 948, 223, 227, 227, 227, 948, 948, 228, + 948, 948, 224, 225, 225, 225, 225, 658, 289, 289, + + 229, 290, 290, 290, 290, 185, 185, 185, 185, 179, + 180, 180, 180, 180, 948, 948, 948, 182, 229, 156, + 156, 156, 948, 948, 157, 948, 254, 255, 256, 256, + 256, 256, 258, 156, 258, 182, 948, 259, 948, 260, + 261, 262, 262, 262, 262, 164, 164, 164, 864, 948, + 165, 948, 267, 948, 268, 269, 269, 269, 271, 164, + 271, 948, 948, 272, 948, 273, 864, 274, 275, 275, + 275, 172, 172, 172, 948, 948, 173, 948, 278, 279, + 280, 280, 280, 280, 282, 172, 282, 948, 948, 283, + 948, 284, 285, 286, 286, 286, 286, 181, 181, 181, + + 181, 948, 948, 869, 182, 948, 185, 185, 185, 185, + 300, 300, 948, 301, 301, 301, 301, 191, 191, 191, + 191, 869, 182, 186, 186, 186, 948, 948, 187, 948, + 291, 292, 293, 293, 293, 293, 295, 186, 295, 874, + 680, 296, 685, 297, 298, 299, 299, 299, 299, 948, + 191, 191, 191, 191, 192, 192, 192, 874, 680, 193, + 685, 302, 303, 304, 304, 304, 304, 306, 192, 306, + 948, 948, 307, 948, 308, 309, 310, 310, 310, 310, + 311, 311, 849, 312, 312, 312, 312, 197, 197, 197, + 197, 948, 197, 197, 197, 197, 198, 198, 198, 948, + + 849, 199, 948, 313, 314, 315, 315, 315, 315, 317, + 198, 317, 948, 948, 318, 948, 319, 320, 321, 321, + 321, 321, 322, 322, 948, 323, 323, 323, 323, 204, + 204, 204, 204, 202, 203, 203, 203, 203, 948, 948, + 854, 205, 204, 204, 204, 204, 859, 324, 324, 205, + 325, 325, 325, 325, 206, 206, 206, 206, 854, 205, + 210, 210, 210, 210, 859, 948, 948, 205, 948, 210, + 210, 210, 210, 211, 211, 211, 948, 948, 212, 948, + 327, 328, 329, 329, 329, 329, 331, 211, 331, 948, + 948, 332, 948, 333, 334, 335, 335, 335, 335, 336, + + 336, 948, 337, 337, 337, 337, 135, 130, 135, 948, + 134, 216, 135, 130, 135, 948, 134, 216, 220, 220, + 220, 220, 948, 220, 220, 220, 220, 347, 347, 948, + 348, 348, 348, 348, 948, 240, 134, 240, 134, 948, + 241, 948, 134, 948, 134, 221, 221, 221, 948, 948, + 222, 948, 338, 339, 340, 340, 340, 340, 342, 221, + 342, 948, 948, 343, 948, 344, 345, 346, 346, 346, + 346, 226, 226, 226, 226, 227, 227, 227, 948, 948, + 228, 948, 948, 224, 225, 225, 225, 225, 948, 948, + 948, 229, 948, 226, 226, 226, 226, 358, 358, 948, + + 359, 359, 359, 359, 237, 237, 237, 237, 948, 229, + 227, 227, 227, 948, 948, 228, 948, 349, 350, 351, + 351, 351, 351, 353, 227, 353, 948, 948, 354, 948, + 355, 356, 357, 357, 357, 357, 231, 130, 231, 948, + 948, 232, 234, 130, 234, 948, 134, 235, 234, 130, + 234, 948, 134, 235, 234, 130, 234, 948, 134, 235, + 234, 130, 234, 948, 134, 235, 240, 240, 240, 240, + 948, 241, 241, 135, 130, 135, 948, 948, 136, 255, + 256, 256, 256, 256, 371, 371, 371, 371, 264, 264, + 264, 264, 948, 361, 372, 372, 372, 948, 948, 373, + + 948, 948, 255, 256, 256, 256, 256, 948, 948, 948, + 374, 375, 376, 375, 948, 948, 377, 266, 266, 266, + 266, 266, 266, 266, 266, 948, 948, 378, 374, 258, + 156, 258, 948, 948, 259, 948, 260, 261, 262, 262, + 262, 262, 258, 156, 258, 378, 948, 259, 948, 260, + 261, 262, 262, 262, 262, 156, 156, 156, 948, 948, + 157, 948, 948, 948, 264, 264, 264, 264, 269, 269, + 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, + 164, 164, 164, 948, 948, 165, 279, 280, 280, 280, + 280, 948, 379, 381, 381, 381, 381, 288, 288, 288, + + 288, 290, 290, 290, 290, 948, 948, 948, 379, 271, + 164, 271, 948, 948, 272, 948, 273, 948, 274, 275, + 275, 275, 271, 164, 271, 948, 948, 272, 948, 273, + 948, 274, 275, 275, 275, 271, 164, 271, 948, 948, + 272, 948, 273, 948, 274, 275, 275, 275, 271, 164, + 271, 948, 948, 272, 948, 273, 948, 274, 275, 275, + 275, 271, 164, 271, 948, 948, 272, 948, 273, 948, + 274, 275, 275, 275, 948, 948, 385, 386, 385, 948, + 948, 387, 290, 290, 290, 290, 389, 389, 389, 389, + 380, 948, 388, 292, 293, 293, 293, 293, 301, 301, + + 301, 301, 392, 392, 392, 392, 380, 382, 382, 382, + 388, 948, 383, 948, 948, 279, 280, 280, 280, 280, + 948, 948, 948, 384, 303, 304, 304, 304, 304, 948, + 948, 948, 292, 293, 293, 293, 293, 948, 948, 948, + 390, 384, 282, 172, 282, 948, 948, 283, 948, 284, + 285, 286, 286, 286, 286, 282, 172, 282, 390, 948, + 283, 948, 284, 285, 286, 286, 286, 286, 172, 172, + 172, 948, 948, 173, 948, 948, 948, 288, 288, 288, + 288, 295, 186, 295, 948, 948, 296, 948, 297, 298, + 299, 299, 299, 299, 186, 186, 186, 948, 948, 187, + + 948, 948, 948, 301, 301, 301, 301, 393, 393, 393, + 948, 948, 394, 948, 948, 303, 304, 304, 304, 304, + 948, 948, 948, 395, 396, 397, 396, 948, 948, 398, + 312, 312, 312, 312, 314, 315, 315, 315, 315, 948, + 399, 395, 306, 192, 306, 948, 948, 307, 948, 308, + 309, 310, 310, 310, 310, 948, 948, 948, 399, 192, + 192, 192, 948, 948, 193, 948, 948, 948, 312, 312, + 312, 312, 400, 400, 400, 400, 401, 401, 401, 948, + 948, 402, 948, 948, 314, 315, 315, 315, 315, 948, + 948, 948, 403, 404, 405, 404, 948, 948, 406, 323, + + 323, 323, 323, 325, 325, 325, 325, 948, 948, 407, + 403, 317, 198, 317, 948, 948, 318, 948, 319, 320, + 321, 321, 321, 321, 948, 948, 948, 407, 198, 198, + 198, 948, 948, 199, 948, 948, 948, 323, 323, 323, + 323, 325, 325, 325, 325, 328, 329, 329, 329, 329, + 408, 408, 408, 408, 409, 409, 409, 948, 948, 410, + 948, 948, 328, 329, 329, 329, 329, 948, 948, 948, + 411, 412, 413, 412, 948, 948, 414, 337, 337, 337, + 337, 339, 340, 340, 340, 340, 948, 415, 411, 331, + 211, 331, 948, 948, 332, 948, 333, 334, 335, 335, + + 335, 335, 948, 948, 948, 415, 211, 211, 211, 948, + 948, 212, 948, 948, 948, 337, 337, 337, 337, 416, + 416, 416, 416, 339, 340, 340, 340, 340, 948, 948, + 948, 417, 348, 348, 348, 348, 350, 351, 351, 351, + 351, 419, 419, 419, 419, 359, 359, 359, 359, 417, + 342, 221, 342, 948, 948, 343, 948, 344, 345, 346, + 346, 346, 346, 221, 221, 221, 948, 948, 222, 948, + 948, 948, 348, 348, 348, 348, 420, 420, 420, 948, + 948, 421, 948, 948, 350, 351, 351, 351, 351, 948, + 948, 948, 422, 423, 424, 423, 948, 948, 425, 948, + + 371, 371, 371, 371, 948, 381, 381, 381, 381, 426, + 422, 353, 227, 353, 948, 948, 354, 948, 355, 356, + 357, 357, 357, 357, 948, 948, 948, 426, 227, 227, + 227, 948, 948, 228, 948, 948, 948, 359, 359, 359, + 359, 135, 130, 135, 444, 444, 136, 445, 445, 445, + 445, 459, 460, 948, 461, 461, 461, 461, 948, 948, + 427, 372, 372, 372, 948, 948, 373, 948, 435, 436, + 437, 437, 437, 437, 439, 372, 439, 948, 948, 440, + 948, 441, 442, 443, 443, 443, 443, 375, 376, 375, + 948, 948, 377, 948, 446, 447, 448, 448, 448, 448, + + 376, 376, 376, 948, 948, 449, 948, 450, 451, 452, + 452, 452, 452, 454, 376, 454, 948, 948, 455, 948, + 456, 457, 458, 458, 458, 458, 463, 464, 464, 464, + 465, 465, 465, 465, 465, 475, 475, 948, 476, 476, + 476, 476, 389, 389, 389, 389, 270, 948, 948, 390, + 465, 465, 465, 493, 493, 948, 494, 494, 494, 494, + 948, 948, 270, 382, 382, 382, 948, 390, 383, 948, + 466, 467, 468, 468, 468, 468, 470, 382, 470, 948, + 948, 471, 948, 472, 473, 474, 474, 474, 474, 385, + 386, 385, 948, 948, 387, 948, 477, 478, 479, 479, + + 479, 479, 386, 386, 386, 948, 948, 480, 948, 481, + 482, 483, 483, 483, 483, 485, 386, 485, 948, 948, + 486, 948, 487, 488, 489, 489, 489, 489, 282, 172, + 282, 948, 948, 283, 490, 491, 285, 492, 492, 492, + 492, 295, 186, 295, 948, 948, 296, 495, 496, 298, + 497, 497, 497, 497, 393, 393, 393, 948, 948, 394, + 948, 948, 948, 392, 392, 392, 392, 948, 507, 507, + 395, 508, 508, 508, 508, 534, 534, 948, 535, 535, + 535, 535, 135, 130, 611, 948, 948, 136, 395, 393, + 393, 393, 948, 948, 394, 948, 498, 499, 500, 500, + + 500, 500, 502, 393, 502, 948, 948, 503, 948, 504, + 505, 506, 506, 506, 506, 396, 397, 396, 948, 948, + 398, 948, 509, 510, 511, 511, 511, 511, 397, 397, + 397, 948, 948, 512, 948, 513, 514, 515, 515, 515, + 515, 517, 397, 517, 948, 948, 518, 948, 519, 520, + 521, 521, 521, 521, 306, 192, 306, 948, 948, 307, + 522, 523, 309, 524, 524, 524, 524, 401, 401, 401, + 948, 948, 402, 948, 948, 948, 400, 400, 400, 400, + 948, 561, 561, 403, 562, 562, 562, 562, 436, 437, + 437, 437, 437, 416, 416, 416, 416, 948, 948, 948, + + 417, 403, 401, 401, 401, 948, 948, 402, 948, 525, + 526, 527, 527, 527, 527, 529, 401, 529, 417, 948, + 530, 948, 531, 532, 533, 533, 533, 533, 404, 405, + 404, 948, 948, 406, 948, 536, 537, 538, 538, 538, + 538, 405, 405, 405, 948, 948, 539, 948, 540, 541, + 542, 542, 542, 542, 544, 405, 544, 948, 948, 545, + 948, 546, 547, 548, 548, 548, 548, 317, 198, 317, + 948, 948, 318, 549, 550, 320, 551, 551, 551, 551, + 409, 409, 409, 948, 948, 410, 948, 948, 948, 408, + 408, 408, 408, 948, 579, 579, 411, 580, 580, 580, + + 580, 593, 593, 948, 594, 594, 594, 594, 616, 616, + 616, 616, 948, 948, 411, 409, 409, 409, 948, 948, + 410, 948, 552, 553, 554, 554, 554, 554, 556, 409, + 556, 948, 948, 557, 948, 558, 559, 560, 560, 560, + 560, 412, 413, 412, 948, 948, 414, 948, 563, 564, + 565, 565, 565, 565, 413, 413, 413, 948, 948, 566, + 948, 567, 568, 569, 569, 569, 569, 571, 413, 571, + 948, 948, 572, 948, 573, 574, 575, 575, 575, 575, + 331, 211, 331, 948, 948, 332, 576, 577, 334, 578, + 578, 578, 578, 342, 221, 342, 948, 948, 343, 581, + + 582, 345, 583, 583, 583, 583, 420, 420, 420, 948, + 948, 421, 948, 948, 948, 419, 419, 419, 419, 948, + 948, 948, 422, 445, 445, 445, 445, 621, 621, 621, + 621, 436, 437, 437, 437, 437, 948, 948, 948, 617, + 422, 420, 420, 420, 948, 948, 421, 948, 584, 585, + 586, 586, 586, 586, 588, 420, 588, 617, 948, 589, + 948, 590, 591, 592, 592, 592, 592, 423, 424, 423, + 948, 948, 425, 948, 595, 596, 597, 597, 597, 597, + 424, 424, 424, 948, 948, 598, 948, 599, 600, 601, + 601, 601, 601, 603, 424, 603, 948, 948, 604, 948, + + 605, 606, 607, 607, 607, 607, 353, 227, 353, 948, + 948, 354, 608, 609, 356, 610, 610, 610, 610, 439, + 372, 439, 948, 948, 440, 948, 441, 442, 443, 443, + 443, 443, 439, 372, 439, 948, 948, 440, 948, 441, + 442, 443, 443, 443, 443, 372, 372, 372, 948, 948, + 373, 948, 948, 948, 445, 445, 445, 445, 258, 156, + 258, 948, 948, 259, 948, 260, 447, 448, 448, 448, + 448, 258, 156, 258, 948, 948, 259, 948, 260, 261, + 619, 619, 619, 619, 375, 376, 375, 948, 948, 377, + 948, 948, 447, 448, 448, 448, 448, 948, 948, 948, + + 620, 451, 452, 452, 452, 452, 461, 461, 461, 461, + 461, 461, 461, 461, 624, 624, 624, 624, 620, 454, + 376, 454, 948, 948, 455, 948, 456, 457, 458, 458, + 458, 458, 372, 372, 372, 948, 948, 373, 948, 948, + 451, 452, 452, 452, 452, 948, 948, 948, 622, 467, + 468, 468, 468, 468, 261, 461, 461, 461, 461, 135, + 130, 135, 378, 948, 136, 948, 622, 454, 376, 454, + 843, 948, 455, 948, 456, 457, 458, 458, 458, 458, + 378, 270, 271, 164, 271, 270, 270, 272, 270, 273, + 270, 463, 464, 464, 464, 465, 465, 465, 465, 465, + + 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, + 270, 380, 270, 270, 270, 465, 465, 465, 270, 270, + 270, 270, 270, 270, 270, 270, 270, 380, 625, 625, + 625, 948, 948, 626, 948, 948, 467, 468, 468, 468, + 468, 948, 948, 948, 627, 628, 629, 628, 948, 948, + 630, 476, 476, 476, 476, 482, 483, 483, 483, 483, + 948, 631, 627, 470, 382, 470, 948, 948, 471, 948, + 472, 473, 474, 474, 474, 474, 470, 382, 470, 631, + 948, 471, 948, 472, 473, 474, 474, 474, 474, 382, + 382, 382, 948, 948, 383, 948, 948, 948, 476, 476, + + 476, 476, 282, 172, 282, 948, 948, 283, 948, 284, + 478, 479, 479, 479, 479, 282, 172, 282, 948, 948, + 283, 948, 284, 285, 632, 632, 632, 632, 633, 634, + 633, 948, 948, 635, 948, 948, 478, 479, 479, 479, + 479, 948, 948, 948, 636, 637, 637, 637, 637, 492, + 492, 492, 492, 492, 492, 492, 492, 494, 494, 494, + 494, 948, 636, 485, 386, 485, 948, 948, 486, 948, + 487, 488, 489, 489, 489, 489, 629, 629, 629, 948, + 948, 638, 948, 948, 482, 483, 483, 483, 483, 948, + 948, 948, 639, 640, 634, 640, 948, 948, 641, 494, + + 494, 494, 494, 499, 500, 500, 500, 500, 948, 642, + 639, 485, 386, 485, 948, 948, 486, 948, 487, 488, + 489, 489, 489, 489, 948, 948, 948, 642, 385, 386, + 385, 948, 948, 387, 948, 948, 948, 492, 492, 492, + 492, 948, 948, 948, 388, 643, 643, 643, 643, 508, + 508, 508, 508, 499, 500, 500, 500, 500, 948, 948, + 948, 644, 388, 295, 186, 295, 948, 948, 296, 948, + 297, 298, 497, 497, 497, 497, 295, 186, 295, 644, + 948, 296, 948, 297, 298, 497, 497, 497, 497, 502, + 393, 502, 948, 948, 503, 948, 504, 505, 506, 506, + + 506, 506, 502, 393, 502, 948, 948, 503, 948, 504, + 505, 506, 506, 506, 506, 393, 393, 393, 948, 948, + 394, 948, 948, 948, 508, 508, 508, 508, 306, 192, + 306, 948, 948, 307, 948, 308, 510, 511, 511, 511, + 511, 306, 192, 306, 948, 948, 307, 948, 308, 309, + 646, 646, 646, 646, 396, 397, 396, 948, 948, 398, + 948, 948, 510, 511, 511, 511, 511, 948, 948, 948, + 647, 514, 515, 515, 515, 515, 648, 648, 648, 648, + 524, 524, 524, 524, 524, 524, 524, 524, 647, 517, + 397, 517, 948, 948, 518, 948, 519, 520, 521, 521, + + 521, 521, 393, 393, 393, 948, 948, 394, 948, 948, + 514, 515, 515, 515, 515, 948, 948, 948, 649, 526, + 527, 527, 527, 527, 309, 524, 524, 524, 524, 135, + 130, 931, 399, 948, 136, 948, 649, 517, 397, 517, + 948, 948, 518, 948, 519, 520, 521, 521, 521, 521, + 399, 651, 651, 651, 651, 526, 527, 527, 527, 527, + 948, 948, 948, 652, 535, 535, 535, 535, 541, 542, + 542, 542, 542, 656, 656, 656, 656, 551, 551, 551, + 551, 652, 529, 401, 529, 948, 948, 530, 948, 531, + 532, 533, 533, 533, 533, 529, 401, 529, 948, 948, + + 530, 948, 531, 532, 533, 533, 533, 533, 401, 401, + 401, 948, 948, 402, 948, 948, 948, 535, 535, 535, + 535, 317, 198, 317, 948, 948, 318, 948, 319, 537, + 538, 538, 538, 538, 317, 198, 317, 948, 948, 318, + 948, 319, 320, 654, 654, 654, 654, 404, 405, 404, + 948, 948, 406, 948, 948, 537, 538, 538, 538, 538, + 948, 948, 948, 655, 551, 551, 551, 551, 659, 659, + 659, 659, 320, 551, 551, 551, 551, 948, 948, 948, + 407, 655, 544, 405, 544, 948, 948, 545, 948, 546, + 547, 548, 548, 548, 548, 401, 401, 401, 407, 948, + + 402, 948, 948, 541, 542, 542, 542, 542, 948, 948, + 948, 657, 553, 554, 554, 554, 554, 562, 562, 562, + 562, 568, 569, 569, 569, 569, 948, 948, 948, 657, + 544, 405, 544, 948, 948, 545, 948, 546, 547, 548, + 548, 548, 548, 660, 660, 660, 948, 948, 661, 948, + 948, 553, 554, 554, 554, 554, 948, 948, 948, 662, + 663, 664, 663, 948, 948, 665, 672, 672, 672, 672, + 578, 578, 578, 578, 948, 948, 666, 662, 556, 409, + 556, 948, 948, 557, 948, 558, 559, 560, 560, 560, + 560, 556, 409, 556, 666, 948, 557, 948, 558, 559, + + 560, 560, 560, 560, 409, 409, 409, 948, 948, 410, + 948, 948, 948, 562, 562, 562, 562, 331, 211, 331, + 948, 948, 332, 948, 333, 564, 565, 565, 565, 565, + 331, 211, 331, 948, 948, 332, 948, 333, 334, 667, + 667, 667, 667, 668, 669, 668, 948, 948, 670, 948, + 948, 564, 565, 565, 565, 565, 948, 948, 948, 671, + 675, 669, 675, 948, 948, 676, 578, 578, 578, 578, + 580, 580, 580, 580, 948, 948, 677, 671, 571, 413, + 571, 948, 948, 572, 948, 573, 574, 575, 575, 575, + 575, 664, 664, 664, 677, 948, 673, 948, 948, 568, + + 569, 569, 569, 569, 948, 948, 948, 674, 580, 580, + 580, 580, 585, 586, 586, 586, 586, 678, 678, 678, + 678, 594, 594, 594, 594, 674, 571, 413, 571, 948, + 948, 572, 948, 573, 574, 575, 575, 575, 575, 412, + 413, 412, 948, 948, 414, 948, 948, 948, 578, 578, + 578, 578, 948, 948, 948, 415, 600, 601, 601, 601, + 601, 948, 948, 948, 585, 586, 586, 586, 586, 948, + 948, 948, 679, 415, 342, 221, 342, 948, 948, 343, + 948, 344, 345, 583, 583, 583, 583, 342, 221, 342, + 679, 948, 343, 948, 344, 345, 583, 583, 583, 583, + + 588, 420, 588, 948, 948, 589, 948, 590, 591, 592, + 592, 592, 592, 588, 420, 588, 948, 948, 589, 948, + 590, 591, 592, 592, 592, 592, 420, 420, 420, 948, + 948, 421, 948, 948, 948, 594, 594, 594, 594, 353, + 227, 353, 948, 948, 354, 948, 355, 596, 597, 597, + 597, 597, 353, 227, 353, 948, 948, 354, 948, 355, + 356, 681, 681, 681, 681, 423, 424, 423, 948, 948, + 425, 948, 948, 596, 597, 597, 597, 597, 948, 948, + 948, 682, 683, 683, 683, 683, 610, 610, 610, 610, + 610, 610, 610, 610, 692, 692, 692, 692, 948, 682, + + 603, 424, 603, 948, 948, 604, 948, 605, 606, 607, + 607, 607, 607, 420, 420, 420, 948, 948, 421, 948, + 948, 600, 601, 601, 601, 601, 135, 130, 135, 684, + 948, 136, 948, 948, 948, 356, 610, 610, 610, 610, + 135, 130, 135, 426, 948, 136, 948, 684, 603, 424, + 603, 948, 938, 604, 686, 605, 606, 607, 607, 607, + 607, 426, 616, 616, 616, 616, 948, 691, 691, 617, + 692, 692, 692, 692, 699, 699, 948, 700, 700, 700, + 700, 692, 692, 692, 692, 948, 948, 617, 439, 372, + 439, 948, 948, 440, 693, 694, 442, 695, 695, 695, + + 695, 375, 376, 375, 948, 948, 377, 948, 260, 261, + 619, 619, 619, 619, 948, 713, 713, 620, 714, 714, + 714, 714, 746, 746, 948, 747, 747, 747, 747, 700, + 700, 700, 700, 948, 948, 620, 258, 156, 258, 948, + 948, 259, 696, 697, 261, 698, 698, 698, 698, 372, + 372, 372, 948, 948, 373, 948, 948, 948, 621, 621, + 621, 621, 948, 754, 754, 622, 755, 755, 755, 755, + 705, 706, 706, 706, 706, 643, 643, 643, 643, 948, + 948, 948, 644, 622, 454, 376, 454, 948, 948, 455, + 701, 702, 457, 703, 703, 703, 703, 625, 625, 625, + + 644, 948, 626, 948, 948, 948, 624, 624, 624, 624, + 948, 762, 762, 627, 763, 763, 763, 763, 847, 847, + 847, 847, 948, 651, 651, 651, 651, 948, 948, 948, + 652, 627, 625, 625, 625, 948, 948, 626, 948, 704, + 705, 706, 706, 706, 706, 708, 625, 708, 652, 948, + 709, 948, 710, 711, 712, 712, 712, 712, 628, 629, + 628, 948, 948, 630, 948, 715, 716, 717, 717, 717, + 717, 629, 629, 629, 948, 948, 638, 948, 718, 719, + 720, 720, 720, 720, 722, 629, 722, 948, 948, 723, + 948, 724, 725, 726, 726, 726, 726, 470, 382, 470, + + 948, 948, 471, 727, 728, 473, 729, 729, 729, 729, + 633, 634, 633, 948, 948, 635, 948, 284, 285, 632, + 632, 632, 632, 948, 767, 767, 636, 768, 768, 768, + 768, 775, 775, 948, 776, 776, 776, 776, 714, 714, + 714, 714, 948, 948, 636, 633, 634, 633, 948, 948, + 635, 948, 730, 731, 732, 732, 732, 732, 634, 634, + 634, 948, 948, 733, 948, 734, 735, 736, 736, 736, + 736, 738, 634, 738, 948, 948, 739, 948, 740, 741, + 742, 742, 742, 742, 282, 172, 282, 948, 948, 283, + 743, 744, 285, 745, 745, 745, 745, 629, 629, 629, + + 948, 948, 638, 948, 948, 948, 637, 637, 637, 637, + 948, 789, 789, 639, 790, 790, 790, 790, 822, 822, + 948, 823, 823, 823, 823, 719, 720, 720, 720, 720, + 948, 639, 722, 629, 722, 948, 948, 723, 948, 724, + 725, 726, 726, 726, 726, 640, 634, 640, 948, 948, + 641, 948, 748, 749, 750, 750, 750, 750, 738, 634, + 738, 948, 948, 739, 948, 740, 741, 742, 742, 742, + 742, 485, 386, 485, 948, 948, 486, 751, 752, 488, + 753, 753, 753, 753, 502, 393, 502, 948, 948, 503, + 756, 757, 505, 758, 758, 758, 758, 396, 397, 396, + + 948, 948, 398, 948, 308, 309, 646, 646, 646, 646, + 948, 830, 830, 647, 831, 831, 831, 831, 852, 852, + 852, 852, 948, 678, 678, 678, 678, 948, 948, 948, + 679, 647, 306, 192, 306, 948, 948, 307, 759, 760, + 309, 761, 761, 761, 761, 393, 393, 393, 679, 948, + 394, 948, 948, 948, 648, 648, 648, 648, 948, 838, + 838, 649, 839, 839, 839, 839, 729, 729, 729, 729, + 705, 706, 706, 706, 706, 948, 948, 948, 848, 649, + 517, 397, 517, 948, 948, 518, 764, 765, 520, 766, + 766, 766, 766, 529, 401, 529, 848, 948, 530, 769, + + 770, 532, 771, 771, 771, 771, 404, 405, 404, 948, + 948, 406, 948, 319, 320, 654, 654, 654, 654, 948, + 948, 948, 655, 375, 376, 375, 948, 948, 377, 729, + 729, 729, 729, 735, 736, 736, 736, 736, 948, 378, + 655, 317, 198, 317, 948, 948, 318, 772, 773, 320, + 774, 774, 774, 774, 401, 401, 401, 378, 948, 402, + 948, 948, 948, 656, 656, 656, 656, 948, 948, 948, + 657, 857, 857, 857, 857, 745, 745, 745, 745, 473, + 729, 729, 729, 729, 948, 948, 948, 631, 657, 544, + 405, 544, 948, 948, 545, 777, 778, 547, 779, 779, + + 779, 779, 660, 660, 660, 631, 948, 661, 948, 948, + 948, 659, 659, 659, 659, 948, 948, 948, 662, 745, + 745, 745, 745, 747, 747, 747, 747, 285, 745, 745, + 745, 745, 948, 948, 948, 388, 662, 660, 660, 660, + 948, 948, 661, 948, 780, 781, 782, 782, 782, 782, + 784, 660, 784, 388, 948, 785, 948, 786, 787, 788, + 788, 788, 788, 663, 664, 663, 948, 948, 665, 948, + 791, 792, 793, 793, 793, 793, 664, 664, 664, 948, + 948, 673, 948, 794, 795, 796, 796, 796, 796, 798, + 664, 798, 948, 948, 799, 948, 800, 801, 802, 802, + + 802, 802, 556, 409, 556, 948, 948, 557, 803, 804, + 559, 805, 805, 805, 805, 668, 669, 668, 948, 948, + 670, 948, 333, 334, 667, 667, 667, 667, 948, 948, + 948, 671, 753, 753, 753, 753, 753, 753, 753, 753, + 488, 753, 753, 753, 753, 948, 948, 948, 642, 671, + 668, 669, 668, 948, 948, 670, 948, 806, 807, 808, + 808, 808, 808, 669, 669, 669, 642, 948, 809, 948, + 810, 811, 812, 812, 812, 812, 814, 669, 814, 948, + 948, 815, 948, 816, 817, 818, 818, 818, 818, 331, + 211, 331, 948, 948, 332, 819, 820, 334, 821, 821, + + 821, 821, 664, 664, 664, 948, 948, 673, 948, 948, + 948, 672, 672, 672, 672, 948, 948, 948, 674, 755, + 755, 755, 755, 755, 755, 755, 755, 763, 763, 763, + 763, 768, 768, 768, 768, 948, 674, 798, 664, 798, + 948, 948, 799, 948, 800, 801, 802, 802, 802, 802, + 675, 669, 675, 948, 948, 676, 948, 824, 825, 826, + 826, 826, 826, 814, 669, 814, 948, 948, 815, 948, + 816, 817, 818, 818, 818, 818, 571, 413, 571, 948, + 948, 572, 827, 828, 574, 829, 829, 829, 829, 588, + 420, 588, 948, 948, 589, 832, 833, 591, 834, 834, + + 834, 834, 423, 424, 423, 948, 948, 425, 948, 355, + 356, 681, 681, 681, 681, 948, 948, 948, 682, 396, + 397, 396, 948, 948, 398, 768, 768, 768, 768, 776, + 776, 776, 776, 948, 948, 399, 682, 353, 227, 353, + 948, 948, 354, 835, 836, 356, 837, 837, 837, 837, + 420, 420, 420, 399, 948, 421, 948, 948, 948, 683, + 683, 683, 683, 948, 948, 948, 684, 404, 405, 404, + 948, 948, 406, 781, 782, 782, 782, 782, 862, 862, + 862, 862, 948, 407, 684, 603, 424, 603, 948, 948, + 604, 840, 841, 606, 842, 842, 842, 842, 439, 372, + + 439, 407, 948, 440, 948, 441, 442, 695, 695, 695, + 695, 439, 372, 439, 948, 948, 440, 948, 441, 442, + 695, 695, 695, 695, 258, 156, 258, 948, 948, 259, + 948, 260, 261, 698, 698, 698, 698, 258, 156, 258, + 948, 948, 259, 948, 260, 261, 698, 698, 698, 698, + 372, 372, 372, 948, 948, 373, 948, 948, 948, 700, + 700, 700, 700, 454, 376, 454, 948, 948, 455, 948, + 456, 457, 703, 703, 703, 703, 454, 376, 454, 948, + 948, 455, 948, 456, 457, 703, 703, 703, 703, 708, + 625, 708, 948, 948, 709, 948, 710, 711, 712, 712, + + 712, 712, 708, 625, 708, 948, 948, 709, 948, 710, + 711, 712, 712, 712, 712, 625, 625, 625, 948, 948, + 626, 948, 948, 948, 714, 714, 714, 714, 470, 382, + 470, 948, 948, 471, 948, 472, 716, 717, 717, 717, + 717, 470, 382, 470, 948, 948, 471, 948, 472, 473, + 850, 850, 850, 850, 628, 629, 628, 948, 948, 630, + 948, 948, 716, 717, 717, 717, 717, 948, 948, 948, + 851, 790, 790, 790, 790, 948, 781, 782, 782, 782, + 782, 940, 941, 940, 863, 948, 942, 948, 851, 625, + 625, 625, 948, 948, 626, 948, 948, 719, 720, 720, + + 720, 720, 863, 948, 948, 853, 795, 796, 796, 796, + 796, 867, 867, 867, 867, 805, 805, 805, 805, 805, + 805, 805, 805, 853, 722, 629, 722, 948, 948, 723, + 948, 724, 725, 726, 726, 726, 726, 722, 629, 722, + 948, 948, 723, 948, 724, 725, 726, 726, 726, 726, + 282, 172, 282, 948, 948, 283, 948, 284, 731, 732, + 732, 732, 732, 282, 172, 282, 948, 948, 283, 948, + 284, 285, 855, 855, 855, 855, 633, 634, 633, 948, + 948, 635, 948, 948, 731, 732, 732, 732, 732, 948, + 948, 948, 856, 811, 812, 812, 812, 812, 948, 948, + + 948, 559, 805, 805, 805, 805, 948, 948, 948, 666, + 856, 738, 634, 738, 948, 948, 739, 948, 740, 741, + 742, 742, 742, 742, 629, 629, 629, 666, 948, 638, + 948, 948, 735, 736, 736, 736, 736, 948, 948, 948, + 858, 872, 872, 872, 872, 821, 821, 821, 821, 821, + 821, 821, 821, 823, 823, 823, 823, 948, 858, 738, + 634, 738, 948, 948, 739, 948, 740, 741, 742, 742, + 742, 742, 629, 629, 629, 948, 948, 638, 948, 948, + 948, 747, 747, 747, 747, 485, 386, 485, 948, 948, + 486, 948, 487, 749, 750, 750, 750, 750, 485, 386, + + 485, 948, 948, 486, 948, 487, 488, 860, 860, 860, + 860, 640, 634, 640, 948, 948, 641, 948, 948, 749, + 750, 750, 750, 750, 948, 948, 948, 861, 829, 829, + 829, 829, 829, 829, 829, 829, 334, 821, 821, 821, + 821, 948, 948, 948, 415, 861, 502, 393, 502, 948, + 948, 503, 948, 504, 505, 758, 758, 758, 758, 502, + 393, 502, 415, 948, 503, 948, 504, 505, 758, 758, + 758, 758, 306, 192, 306, 948, 948, 307, 948, 308, + 309, 761, 761, 761, 761, 306, 192, 306, 948, 948, + 307, 948, 308, 309, 761, 761, 761, 761, 393, 393, + + 393, 948, 948, 394, 948, 948, 948, 763, 763, 763, + 763, 517, 397, 517, 948, 948, 518, 948, 519, 520, + 766, 766, 766, 766, 517, 397, 517, 948, 948, 518, + 948, 519, 520, 766, 766, 766, 766, 529, 401, 529, + 948, 948, 530, 948, 531, 532, 771, 771, 771, 771, + 529, 401, 529, 948, 948, 530, 948, 531, 532, 771, + 771, 771, 771, 317, 198, 317, 948, 948, 318, 948, + 319, 320, 774, 774, 774, 774, 317, 198, 317, 948, + 948, 318, 948, 319, 320, 774, 774, 774, 774, 401, + 401, 401, 948, 948, 402, 948, 948, 948, 776, 776, + + 776, 776, 544, 405, 544, 948, 948, 545, 948, 546, + 547, 779, 779, 779, 779, 544, 405, 544, 948, 948, + 545, 948, 546, 547, 779, 779, 779, 779, 784, 660, + 784, 948, 948, 785, 948, 786, 787, 788, 788, 788, + 788, 784, 660, 784, 948, 948, 785, 948, 786, 787, + 788, 788, 788, 788, 660, 660, 660, 948, 948, 661, + 948, 948, 948, 790, 790, 790, 790, 556, 409, 556, + 948, 948, 557, 948, 558, 792, 793, 793, 793, 793, + 556, 409, 556, 948, 948, 557, 948, 558, 559, 865, + 865, 865, 865, 663, 664, 663, 948, 948, 665, 948, + + 948, 792, 793, 793, 793, 793, 948, 948, 948, 866, + 831, 831, 831, 831, 948, 574, 829, 829, 829, 829, + 940, 941, 940, 677, 948, 942, 948, 866, 660, 660, + 660, 948, 948, 661, 948, 948, 795, 796, 796, 796, + 796, 677, 948, 948, 868, 831, 831, 831, 831, 839, + 839, 839, 839, 135, 130, 135, 948, 948, 136, 948, + 948, 877, 868, 798, 664, 798, 948, 948, 799, 948, + 800, 801, 802, 802, 802, 802, 798, 664, 798, 948, + 948, 799, 948, 800, 801, 802, 802, 802, 802, 331, + 211, 331, 948, 948, 332, 948, 333, 807, 808, 808, + + 808, 808, 331, 211, 331, 948, 948, 332, 948, 333, + 334, 870, 870, 870, 870, 668, 669, 668, 948, 948, + 670, 948, 948, 807, 808, 808, 808, 808, 948, 948, + 948, 871, 423, 424, 423, 880, 880, 425, 881, 881, + 881, 881, 559, 865, 865, 865, 865, 948, 426, 871, + 814, 669, 814, 948, 948, 815, 948, 816, 817, 818, + 818, 818, 818, 664, 664, 664, 426, 948, 673, 948, + 948, 811, 812, 812, 812, 812, 948, 888, 888, 873, + 889, 889, 889, 889, 948, 867, 867, 867, 867, 847, + 847, 847, 847, 948, 948, 948, 848, 873, 814, 669, + + 814, 948, 948, 815, 948, 816, 817, 818, 818, 818, + 818, 664, 664, 664, 848, 948, 673, 948, 948, 948, + 823, 823, 823, 823, 571, 413, 571, 948, 948, 572, + 948, 573, 825, 826, 826, 826, 826, 571, 413, 571, + 948, 948, 572, 948, 573, 574, 875, 875, 875, 875, + 675, 669, 675, 948, 948, 676, 948, 948, 825, 826, + 826, 826, 826, 948, 896, 896, 876, 897, 897, 897, + 897, 334, 870, 870, 870, 870, 862, 862, 862, 862, + 948, 948, 948, 863, 876, 588, 420, 588, 948, 948, + 589, 948, 590, 591, 834, 834, 834, 834, 588, 420, + + 588, 863, 948, 589, 948, 590, 591, 834, 834, 834, + 834, 353, 227, 353, 948, 948, 354, 948, 355, 356, + 837, 837, 837, 837, 353, 227, 353, 948, 948, 354, + 948, 355, 356, 837, 837, 837, 837, 420, 420, 420, + 948, 948, 421, 948, 948, 948, 839, 839, 839, 839, + 603, 424, 603, 948, 948, 604, 948, 605, 606, 842, + 842, 842, 842, 603, 424, 603, 948, 948, 604, 948, + 605, 606, 842, 842, 842, 842, 708, 625, 708, 948, + 948, 709, 882, 883, 711, 884, 884, 884, 884, 628, + 629, 628, 948, 948, 630, 948, 472, 473, 850, 850, + + 850, 850, 948, 904, 904, 851, 905, 905, 905, 905, + 906, 907, 948, 908, 908, 908, 908, 948, 872, 872, + 872, 872, 948, 851, 470, 382, 470, 948, 948, 471, + 885, 886, 473, 887, 887, 887, 887, 625, 625, 625, + 948, 948, 626, 948, 948, 948, 852, 852, 852, 852, + 948, 909, 910, 853, 911, 911, 911, 911, 912, 912, + 948, 913, 913, 913, 913, 574, 875, 875, 875, 875, + 948, 853, 722, 629, 722, 948, 948, 723, 890, 891, + 725, 892, 892, 892, 892, 633, 634, 633, 948, 948, + 635, 948, 284, 285, 855, 855, 855, 855, 948, 914, + + 915, 856, 916, 916, 916, 916, 917, 918, 948, 919, + 919, 919, 919, 881, 881, 881, 881, 948, 948, 856, + 282, 172, 282, 948, 948, 283, 893, 894, 285, 895, + 895, 895, 895, 629, 629, 629, 948, 948, 638, 948, + 948, 948, 857, 857, 857, 857, 948, 920, 920, 858, + 921, 921, 921, 921, 922, 923, 948, 924, 924, 924, + 924, 881, 881, 881, 881, 948, 948, 858, 738, 634, + 738, 948, 948, 739, 898, 899, 741, 900, 900, 900, + 900, 640, 634, 640, 948, 948, 641, 948, 487, 488, + 860, 860, 860, 860, 948, 925, 926, 861, 927, 927, + + 927, 927, 135, 130, 135, 948, 948, 136, 940, 941, + 940, 928, 948, 942, 948, 861, 485, 386, 485, 948, + 948, 486, 901, 902, 488, 903, 903, 903, 903, 708, + 625, 708, 948, 948, 709, 948, 710, 711, 884, 884, + 884, 884, 628, 629, 628, 948, 948, 630, 469, 472, + 889, 889, 889, 889, 897, 897, 897, 897, 631, 905, + 905, 905, 905, 905, 905, 905, 905, 908, 908, 908, + 908, 908, 908, 908, 908, 948, 631, 625, 625, 625, + 948, 948, 626, 948, 948, 948, 889, 889, 889, 889, + 722, 629, 722, 948, 948, 723, 948, 724, 725, 892, + + 892, 892, 892, 633, 634, 633, 948, 948, 635, 281, + 284, 908, 908, 908, 908, 948, 948, 948, 864, 388, + 911, 911, 911, 911, 911, 911, 911, 911, 913, 913, + 913, 913, 916, 916, 916, 916, 864, 388, 629, 629, + 629, 948, 948, 638, 948, 948, 948, 897, 897, 897, + 897, 738, 634, 738, 948, 948, 739, 948, 740, 741, + 900, 900, 900, 900, 640, 634, 640, 948, 948, 641, + 484, 487, 948, 559, 911, 911, 911, 911, 948, 948, + 642, 666, 916, 916, 916, 916, 948, 948, 916, 916, + 916, 916, 135, 130, 135, 869, 948, 136, 642, 666, + + 660, 660, 660, 948, 948, 661, 948, 948, 948, 913, + 913, 913, 913, 869, 919, 919, 919, 919, 919, 919, + 919, 919, 334, 919, 919, 919, 919, 937, 948, 948, + 415, 921, 921, 921, 921, 921, 921, 921, 921, 924, + 924, 924, 924, 924, 924, 924, 924, 948, 415, 924, + 924, 924, 924, 948, 948, 948, 874, 927, 927, 927, + 927, 927, 927, 927, 927, 574, 927, 927, 927, 927, + 135, 130, 135, 677, 874, 136, 135, 130, 135, 948, + 943, 136, 943, 948, 948, 944, 948, 940, 941, 940, + 948, 677, 942, 943, 946, 943, 946, 948, 944, 947, + + 946, 946, 946, 946, 948, 947, 947, 946, 948, 946, + 948, 948, 947, 934, 948, 948, 948, 948, 936, 46, + 46, 46, 46, 46, 46, 46, 46, 80, 80, 80, + 80, 80, 80, 80, 80, 110, 110, 110, 110, 110, + 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, + 120, 134, 134, 134, 134, 134, 134, 134, 134, 138, + 948, 948, 138, 175, 948, 948, 175, 948, 175, 175, + 175, 176, 176, 176, 176, 176, 176, 176, 176, 214, + 948, 948, 214, 948, 214, 214, 215, 215, 215, 215, + 215, 215, 215, 215, 230, 230, 948, 230, 948, 230, + + 230, 230, 233, 233, 233, 233, 233, 233, 233, 233, + 239, 239, 948, 239, 239, 239, 239, 239, 257, 257, + 257, 257, 257, 257, 257, 257, 270, 270, 270, 270, + 270, 270, 270, 270, 276, 276, 948, 948, 276, 276, + 281, 281, 281, 281, 281, 281, 281, 281, 294, 294, + 294, 294, 294, 294, 294, 294, 305, 305, 305, 305, + 305, 305, 305, 305, 316, 316, 316, 316, 316, 316, + 316, 316, 330, 330, 330, 330, 330, 330, 330, 330, + 341, 341, 341, 341, 341, 341, 341, 341, 352, 352, + 352, 352, 352, 352, 352, 352, 230, 230, 948, 230, + + 948, 230, 230, 230, 233, 233, 233, 233, 233, 233, + 233, 233, 239, 239, 948, 239, 239, 239, 239, 239, + 134, 134, 134, 134, 134, 134, 134, 134, 138, 948, + 948, 138, 257, 257, 257, 257, 257, 257, 257, 257, + 270, 270, 270, 270, 270, 270, 270, 270, 276, 276, + 948, 948, 276, 276, 281, 281, 281, 281, 281, 281, + 281, 281, 438, 438, 438, 438, 438, 438, 438, 438, + 453, 453, 453, 453, 453, 453, 453, 453, 469, 469, + 469, 469, 469, 469, 469, 469, 484, 484, 484, 484, + 484, 484, 484, 484, 294, 294, 294, 294, 294, 294, + + 294, 294, 501, 501, 501, 501, 501, 501, 501, 501, + 305, 305, 305, 305, 305, 305, 305, 305, 516, 516, + 516, 516, 516, 516, 516, 516, 528, 528, 528, 528, + 528, 528, 528, 528, 316, 316, 316, 316, 316, 316, + 316, 316, 543, 543, 543, 543, 543, 543, 543, 543, + 555, 555, 555, 555, 555, 555, 555, 555, 330, 330, + 330, 330, 330, 330, 330, 330, 570, 570, 570, 570, + 570, 570, 570, 570, 341, 341, 341, 341, 341, 341, + 341, 341, 587, 587, 587, 587, 587, 587, 587, 587, + 352, 352, 352, 352, 352, 352, 352, 352, 602, 602, + + 602, 602, 602, 602, 602, 602, 134, 134, 134, 134, + 134, 134, 134, 134, 138, 948, 948, 138, 438, 438, + 438, 438, 438, 438, 438, 438, 257, 257, 257, 257, + 257, 257, 257, 257, 453, 453, 453, 453, 453, 453, + 453, 453, 469, 469, 469, 469, 469, 469, 469, 469, + 281, 281, 281, 281, 281, 281, 281, 281, 484, 484, + 484, 484, 484, 484, 484, 484, 294, 294, 294, 294, + 294, 294, 294, 294, 501, 501, 501, 501, 501, 501, + 501, 501, 305, 305, 305, 305, 305, 305, 305, 305, + 516, 516, 516, 516, 516, 516, 516, 516, 528, 528, + + 528, 528, 528, 528, 528, 528, 316, 316, 316, 316, + 316, 316, 316, 316, 543, 543, 543, 543, 543, 543, + 543, 543, 555, 555, 555, 555, 555, 555, 555, 555, + 330, 330, 330, 330, 330, 330, 330, 330, 570, 570, + 570, 570, 570, 570, 570, 570, 341, 341, 341, 341, + 341, 341, 341, 341, 587, 587, 587, 587, 587, 587, + 587, 587, 352, 352, 352, 352, 352, 352, 352, 352, + 602, 602, 602, 602, 602, 602, 602, 602, 134, 134, + 134, 134, 134, 134, 134, 134, 138, 948, 948, 138, + 438, 438, 438, 438, 438, 438, 438, 438, 257, 257, + + 257, 257, 257, 257, 257, 257, 453, 453, 453, 453, + 453, 453, 453, 453, 707, 707, 707, 707, 707, 707, + 707, 707, 469, 469, 469, 469, 469, 469, 469, 469, + 721, 721, 721, 721, 721, 721, 721, 721, 281, 281, + 281, 281, 281, 281, 281, 281, 737, 737, 737, 737, + 737, 737, 737, 737, 484, 484, 484, 484, 484, 484, + 484, 484, 501, 501, 501, 501, 501, 501, 501, 501, + 305, 305, 305, 305, 305, 305, 305, 305, 516, 516, + 516, 516, 516, 516, 516, 516, 528, 528, 528, 528, + 528, 528, 528, 528, 316, 316, 316, 316, 316, 316, + + 316, 316, 543, 543, 543, 543, 543, 543, 543, 543, + 783, 783, 783, 783, 783, 783, 783, 783, 555, 555, + 555, 555, 555, 555, 555, 555, 797, 797, 797, 797, + 797, 797, 797, 797, 330, 330, 330, 330, 330, 330, + 330, 330, 813, 813, 813, 813, 813, 813, 813, 813, + 570, 570, 570, 570, 570, 570, 570, 570, 587, 587, + 587, 587, 587, 587, 587, 587, 352, 352, 352, 352, + 352, 352, 352, 352, 602, 602, 602, 602, 602, 602, + 602, 602, 134, 134, 134, 134, 134, 134, 134, 134, + 138, 948, 948, 138, 438, 438, 438, 438, 438, 438, + + 438, 438, 257, 257, 257, 257, 257, 257, 257, 257, + 453, 453, 453, 453, 453, 453, 453, 453, 707, 707, + 707, 707, 707, 707, 707, 707, 469, 469, 469, 469, + 469, 469, 469, 469, 721, 721, 721, 721, 721, 721, + 721, 721, 281, 281, 281, 281, 281, 281, 281, 281, + 737, 737, 737, 737, 737, 737, 737, 737, 484, 484, + 484, 484, 484, 484, 484, 484, 501, 501, 501, 501, + 501, 501, 501, 501, 305, 305, 305, 305, 305, 305, + 305, 305, 516, 516, 516, 516, 516, 516, 516, 516, + 528, 528, 528, 528, 528, 528, 528, 528, 316, 316, + + 316, 316, 316, 316, 316, 316, 543, 543, 543, 543, + 543, 543, 543, 543, 783, 783, 783, 783, 783, 783, + 783, 783, 555, 555, 555, 555, 555, 555, 555, 555, + 797, 797, 797, 797, 797, 797, 797, 797, 330, 330, + 330, 330, 330, 330, 330, 330, 813, 813, 813, 813, + 813, 813, 813, 813, 570, 570, 570, 570, 570, 570, + 570, 570, 587, 587, 587, 587, 587, 587, 587, 587, + 352, 352, 352, 352, 352, 352, 352, 352, 602, 602, + 602, 602, 602, 602, 602, 602, 134, 134, 134, 134, + 134, 134, 134, 134, 138, 948, 948, 138, 707, 707, + + 707, 707, 707, 707, 707, 707, 469, 469, 469, 469, + 469, 469, 469, 469, 721, 721, 721, 721, 721, 721, + 721, 721, 281, 281, 281, 281, 281, 281, 281, 281, + 737, 737, 737, 737, 737, 737, 737, 737, 484, 484, + 484, 484, 484, 484, 484, 484, 939, 939, 939, 939, + 939, 939, 939, 939, 945, 945, 948, 945, 945, 945, + 945, 945, 45, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948 +} ; + +static const short int yy_chk[7711] = +{ 0, + 0, 1, 1, 1, 0, 0, 1, 2, 2, 2, + 885, 885, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 5, 5, 60, 60, 5, 6, 6, 6, 431, + 1010, 6, 988, 431, 47, 47, 47, 5, 5, 47, + 48, 73, 48, 6, 6, 48, 5, 65, 65, 65, + 65, 65, 6, 7, 7, 7, 985, 73, 7, 983, + + 7, 7, 7, 7, 7, 7, 66, 66, 66, 66, + 976, 7, 9, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, + 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, + 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 970, 17, 17, 18, 18, 18, 965, + 18, 18, 19, 19, 19, 19, 19, 19, 17, 68, + 68, 68, 68, 68, 18, 20, 20, 20, 20, 20, + 20, 21, 21, 21, 21, 21, 21, 22, 22, 22, + + 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, + 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, + 25, 275, 933, 39, 39, 39, 25, 39, 39, 40, + 40, 40, 930, 40, 40, 464, 929, 275, 25, 879, + 25, 26, 26, 26, 26, 26, 26, 299, 51, 51, + 51, 464, 26, 51, 39, 346, 443, 41, 41, 41, + 40, 41, 41, 878, 26, 299, 26, 27, 27, 27, + 27, 27, 27, 346, 443, 42, 42, 42, 27, 42, + 42, 49, 49, 49, 886, 886, 49, 846, 41, 458, + 27, 844, 27, 28, 28, 28, 28, 28, 28, 69, + + 69, 69, 69, 130, 28, 130, 42, 458, 130, 49, + 71, 71, 71, 71, 690, 465, 28, 689, 28, 29, + 29, 29, 29, 29, 29, 74, 74, 74, 74, 687, + 29, 465, 43, 43, 43, 43, 43, 43, 76, 76, + 76, 76, 29, 43, 29, 30, 30, 30, 30, 30, + 30, 77, 77, 77, 77, 77, 30, 615, 44, 44, + 44, 44, 44, 44, 78, 78, 78, 78, 30, 44, + 30, 31, 31, 31, 31, 31, 31, 70, 70, 70, + 70, 70, 31, 893, 893, 70, 85, 85, 85, 85, + 75, 75, 75, 75, 31, 614, 31, 32, 32, 32, + + 32, 32, 32, 70, 88, 88, 88, 88, 32, 613, + 75, 82, 82, 82, 612, 82, 82, 497, 894, 894, + 32, 432, 32, 33, 33, 33, 75, 33, 33, 84, + 84, 84, 84, 84, 506, 497, 86, 86, 86, 86, + 86, 33, 901, 901, 86, 87, 87, 87, 87, 87, + 902, 902, 506, 33, 521, 33, 34, 34, 34, 428, + 34, 34, 86, 90, 90, 90, 90, 90, 91, 91, + 91, 91, 521, 369, 34, 93, 93, 93, 93, 93, + 94, 94, 94, 94, 368, 367, 34, 366, 34, 35, + 35, 35, 35, 35, 35, 99, 99, 99, 99, 99, + + 35, 100, 100, 100, 100, 101, 101, 101, 101, 101, + 365, 364, 35, 101, 35, 36, 36, 36, 36, 36, + 36, 103, 103, 103, 103, 362, 36, 104, 104, 104, + 104, 101, 105, 105, 105, 105, 253, 252, 36, 251, + 36, 37, 37, 37, 37, 37, 37, 104, 108, 108, + 108, 108, 37, 107, 107, 107, 107, 107, 114, 114, + 114, 114, 114, 104, 37, 533, 37, 38, 38, 38, + 38, 38, 38, 115, 115, 115, 115, 250, 38, 548, + 112, 112, 112, 533, 112, 112, 118, 118, 118, 118, + 38, 249, 38, 67, 67, 67, 247, 548, 67, 246, + + 245, 67, 67, 67, 67, 67, 121, 121, 121, 67, + 112, 121, 112, 117, 117, 117, 117, 117, 123, 123, + 123, 244, 123, 123, 152, 150, 149, 67, 72, 72, + 72, 148, 147, 72, 146, 144, 143, 72, 72, 72, + 72, 126, 126, 126, 126, 127, 127, 127, 127, 128, + 128, 128, 128, 129, 129, 129, 142, 72, 129, 131, + 131, 131, 583, 140, 131, 127, 132, 133, 132, 133, + 139, 132, 133, 72, 79, 79, 79, 124, 592, 79, + 583, 127, 79, 79, 79, 79, 79, 134, 134, 134, + 79, 113, 134, 135, 135, 135, 592, 607, 135, 136, + + 136, 136, 96, 83, 136, 695, 703, 64, 79, 89, + 89, 89, 712, 63, 89, 607, 62, 89, 89, 89, + 89, 89, 61, 695, 703, 89, 137, 137, 137, 726, + 712, 137, 153, 153, 153, 153, 155, 155, 155, 155, + 155, 59, 58, 89, 92, 92, 92, 726, 57, 92, + 137, 56, 92, 92, 92, 92, 92, 742, 158, 158, + 92, 158, 158, 158, 158, 159, 159, 159, 159, 161, + 161, 161, 161, 55, 758, 742, 161, 54, 92, 95, + 95, 95, 766, 53, 95, 52, 45, 95, 95, 95, + 95, 95, 758, 0, 161, 95, 167, 167, 167, 167, + + 766, 160, 160, 160, 160, 160, 166, 166, 166, 160, + 0, 166, 0, 95, 109, 109, 109, 0, 0, 109, + 0, 0, 109, 109, 109, 109, 109, 160, 162, 162, + 109, 162, 162, 162, 162, 169, 169, 169, 169, 171, + 171, 171, 171, 171, 179, 179, 179, 179, 109, 116, + 116, 116, 0, 0, 116, 771, 0, 116, 116, 116, + 116, 116, 0, 174, 174, 116, 174, 174, 174, 174, + 176, 176, 176, 771, 176, 176, 177, 177, 177, 779, + 177, 177, 0, 116, 119, 119, 119, 0, 0, 119, + 0, 0, 119, 119, 119, 119, 119, 779, 182, 182, + + 119, 182, 182, 182, 182, 183, 183, 183, 183, 180, + 180, 180, 180, 180, 0, 0, 0, 180, 119, 156, + 156, 156, 0, 0, 156, 0, 156, 156, 156, 156, + 156, 156, 157, 157, 157, 180, 0, 157, 0, 157, + 157, 157, 157, 157, 157, 164, 164, 164, 788, 0, + 164, 0, 164, 0, 164, 164, 164, 164, 165, 165, + 165, 0, 0, 165, 0, 165, 788, 165, 165, 165, + 165, 172, 172, 172, 0, 0, 172, 0, 172, 172, + 172, 172, 172, 172, 173, 173, 173, 0, 0, 173, + 0, 173, 173, 173, 173, 173, 173, 181, 181, 181, + + 181, 0, 0, 802, 181, 185, 185, 185, 185, 185, + 188, 188, 0, 188, 188, 188, 188, 189, 189, 189, + 189, 802, 181, 186, 186, 186, 0, 0, 186, 0, + 186, 186, 186, 186, 186, 186, 187, 187, 187, 818, + 834, 187, 842, 187, 187, 187, 187, 187, 187, 191, + 191, 191, 191, 191, 192, 192, 192, 818, 834, 192, + 842, 192, 192, 192, 192, 192, 192, 193, 193, 193, + 0, 0, 193, 0, 193, 193, 193, 193, 193, 193, + 194, 194, 884, 194, 194, 194, 194, 195, 195, 195, + 195, 197, 197, 197, 197, 197, 198, 198, 198, 0, + + 884, 198, 0, 198, 198, 198, 198, 198, 198, 199, + 199, 199, 0, 0, 199, 0, 199, 199, 199, 199, + 199, 199, 200, 200, 0, 200, 200, 200, 200, 202, + 202, 202, 202, 203, 203, 203, 203, 203, 0, 0, + 892, 203, 204, 204, 204, 204, 900, 205, 205, 204, + 205, 205, 205, 205, 206, 206, 206, 206, 892, 203, + 208, 208, 208, 208, 900, 0, 0, 204, 210, 210, + 210, 210, 210, 211, 211, 211, 0, 0, 211, 0, + 211, 211, 211, 211, 211, 211, 212, 212, 212, 0, + 0, 212, 0, 212, 212, 212, 212, 212, 212, 213, + + 213, 0, 213, 213, 213, 213, 215, 215, 215, 0, + 215, 215, 216, 216, 216, 0, 216, 216, 218, 218, + 218, 218, 220, 220, 220, 220, 220, 223, 223, 0, + 223, 223, 223, 223, 0, 239, 215, 239, 215, 0, + 239, 0, 216, 0, 216, 221, 221, 221, 0, 0, + 221, 0, 221, 221, 221, 221, 221, 221, 222, 222, + 222, 0, 0, 222, 0, 222, 222, 222, 222, 222, + 222, 224, 224, 224, 224, 225, 225, 225, 0, 0, + 225, 0, 0, 225, 225, 225, 225, 225, 0, 0, + 0, 225, 226, 226, 226, 226, 226, 229, 229, 0, + + 229, 229, 229, 229, 237, 237, 237, 237, 0, 225, + 227, 227, 227, 0, 0, 227, 0, 227, 227, 227, + 227, 227, 227, 228, 228, 228, 0, 0, 228, 0, + 228, 228, 228, 228, 228, 228, 231, 231, 231, 0, + 0, 231, 232, 232, 232, 0, 232, 232, 233, 233, + 233, 0, 233, 233, 234, 234, 234, 0, 234, 234, + 235, 235, 235, 0, 235, 235, 240, 241, 240, 241, + 0, 240, 241, 242, 242, 242, 0, 0, 242, 254, + 254, 254, 254, 254, 255, 255, 255, 255, 263, 263, + 263, 263, 0, 242, 256, 256, 256, 0, 0, 256, + + 0, 0, 256, 256, 256, 256, 256, 0, 0, 0, + 256, 262, 262, 262, 0, 0, 262, 265, 265, 265, + 265, 266, 266, 266, 266, 0, 0, 262, 256, 257, + 257, 257, 0, 0, 257, 0, 257, 257, 257, 257, + 257, 257, 258, 258, 258, 262, 0, 258, 0, 258, + 258, 258, 258, 258, 258, 264, 264, 264, 0, 0, + 264, 0, 0, 0, 264, 264, 264, 264, 267, 267, + 267, 267, 268, 268, 268, 268, 269, 269, 269, 269, + 276, 276, 276, 0, 0, 276, 278, 278, 278, 278, + 278, 0, 268, 279, 279, 279, 279, 287, 287, 287, + + 287, 289, 289, 289, 289, 0, 0, 0, 268, 270, + 270, 270, 0, 0, 270, 0, 270, 0, 270, 270, + 270, 270, 271, 271, 271, 0, 0, 271, 0, 271, + 0, 271, 271, 271, 271, 272, 272, 272, 0, 0, + 272, 0, 272, 0, 272, 272, 272, 272, 273, 273, + 273, 0, 0, 273, 0, 273, 0, 273, 273, 273, + 273, 274, 274, 274, 0, 0, 274, 0, 274, 0, + 274, 274, 274, 274, 0, 0, 286, 286, 286, 0, + 0, 286, 290, 290, 290, 290, 292, 292, 292, 292, + 274, 0, 286, 291, 291, 291, 291, 291, 300, 300, + + 300, 300, 303, 303, 303, 303, 274, 280, 280, 280, + 286, 0, 280, 0, 0, 280, 280, 280, 280, 280, + 0, 0, 0, 280, 302, 302, 302, 302, 302, 0, + 0, 0, 293, 293, 293, 293, 293, 0, 0, 0, + 293, 280, 281, 281, 281, 0, 0, 281, 0, 281, + 281, 281, 281, 281, 281, 282, 282, 282, 293, 0, + 282, 0, 282, 282, 282, 282, 282, 282, 288, 288, + 288, 0, 0, 288, 0, 0, 0, 288, 288, 288, + 288, 294, 294, 294, 0, 0, 294, 0, 294, 294, + 294, 294, 294, 294, 301, 301, 301, 0, 0, 301, + + 0, 0, 0, 301, 301, 301, 301, 304, 304, 304, + 0, 0, 304, 0, 0, 304, 304, 304, 304, 304, + 0, 0, 0, 304, 310, 310, 310, 0, 0, 310, + 311, 311, 311, 311, 313, 313, 313, 313, 313, 0, + 310, 304, 305, 305, 305, 0, 0, 305, 0, 305, + 305, 305, 305, 305, 305, 0, 0, 0, 310, 312, + 312, 312, 0, 0, 312, 0, 0, 0, 312, 312, + 312, 312, 314, 314, 314, 314, 315, 315, 315, 0, + 0, 315, 0, 0, 315, 315, 315, 315, 315, 0, + 0, 0, 315, 321, 321, 321, 0, 0, 321, 322, + + 322, 322, 322, 324, 324, 324, 324, 0, 0, 321, + 315, 316, 316, 316, 0, 0, 316, 0, 316, 316, + 316, 316, 316, 316, 0, 0, 0, 321, 323, 323, + 323, 0, 0, 323, 0, 0, 0, 323, 323, 323, + 323, 325, 325, 325, 325, 327, 327, 327, 327, 327, + 328, 328, 328, 328, 329, 329, 329, 0, 0, 329, + 0, 0, 329, 329, 329, 329, 329, 0, 0, 0, + 329, 335, 335, 335, 0, 0, 335, 336, 336, 336, + 336, 338, 338, 338, 338, 338, 0, 335, 329, 330, + 330, 330, 0, 0, 330, 0, 330, 330, 330, 330, + + 330, 330, 0, 0, 0, 335, 337, 337, 337, 0, + 0, 337, 0, 0, 0, 337, 337, 337, 337, 339, + 339, 339, 339, 340, 340, 340, 340, 340, 0, 0, + 0, 340, 347, 347, 347, 347, 349, 349, 349, 349, + 349, 350, 350, 350, 350, 358, 358, 358, 358, 340, + 341, 341, 341, 0, 0, 341, 0, 341, 341, 341, + 341, 341, 341, 348, 348, 348, 0, 0, 348, 0, + 0, 0, 348, 348, 348, 348, 351, 351, 351, 0, + 0, 351, 0, 0, 351, 351, 351, 351, 351, 0, + 0, 0, 351, 357, 357, 357, 0, 0, 357, 371, + + 371, 371, 371, 371, 381, 381, 381, 381, 381, 357, + 351, 352, 352, 352, 0, 0, 352, 0, 352, 352, + 352, 352, 352, 352, 0, 0, 0, 357, 359, 359, + 359, 0, 0, 359, 0, 0, 0, 359, 359, 359, + 359, 361, 361, 361, 374, 374, 361, 374, 374, 374, + 374, 378, 378, 0, 378, 378, 378, 378, 0, 0, + 361, 372, 372, 372, 0, 0, 372, 0, 372, 372, + 372, 372, 372, 372, 373, 373, 373, 0, 0, 373, + 0, 373, 373, 373, 373, 373, 373, 375, 375, 375, + 0, 0, 375, 0, 375, 375, 375, 375, 375, 375, + + 376, 376, 376, 0, 0, 376, 0, 376, 376, 376, + 376, 376, 376, 377, 377, 377, 0, 0, 377, 0, + 377, 377, 377, 377, 377, 377, 380, 380, 380, 380, + 380, 380, 380, 380, 380, 384, 384, 0, 384, 384, + 384, 384, 389, 389, 389, 389, 380, 0, 0, 389, + 380, 380, 380, 390, 390, 0, 390, 390, 390, 390, + 0, 0, 380, 382, 382, 382, 0, 389, 382, 0, + 382, 382, 382, 382, 382, 382, 383, 383, 383, 0, + 0, 383, 0, 383, 383, 383, 383, 383, 383, 385, + 385, 385, 0, 0, 385, 0, 385, 385, 385, 385, + + 385, 385, 386, 386, 386, 0, 0, 386, 0, 386, + 386, 386, 386, 386, 386, 387, 387, 387, 0, 0, + 387, 0, 387, 387, 387, 387, 387, 387, 388, 388, + 388, 0, 0, 388, 388, 388, 388, 388, 388, 388, + 388, 391, 391, 391, 0, 0, 391, 391, 391, 391, + 391, 391, 391, 391, 392, 392, 392, 0, 0, 392, + 0, 0, 0, 392, 392, 392, 392, 0, 395, 395, + 392, 395, 395, 395, 395, 403, 403, 0, 403, 403, + 403, 403, 427, 427, 427, 0, 0, 427, 392, 393, + 393, 393, 0, 0, 393, 0, 393, 393, 393, 393, + + 393, 393, 394, 394, 394, 0, 0, 394, 0, 394, + 394, 394, 394, 394, 394, 396, 396, 396, 0, 0, + 396, 0, 396, 396, 396, 396, 396, 396, 397, 397, + 397, 0, 0, 397, 0, 397, 397, 397, 397, 397, + 397, 398, 398, 398, 0, 0, 398, 0, 398, 398, + 398, 398, 398, 398, 399, 399, 399, 0, 0, 399, + 399, 399, 399, 399, 399, 399, 399, 400, 400, 400, + 0, 0, 400, 0, 0, 0, 400, 400, 400, 400, + 0, 411, 411, 400, 411, 411, 411, 411, 435, 435, + 435, 435, 435, 416, 416, 416, 416, 0, 0, 0, + + 416, 400, 401, 401, 401, 0, 0, 401, 0, 401, + 401, 401, 401, 401, 401, 402, 402, 402, 416, 0, + 402, 0, 402, 402, 402, 402, 402, 402, 404, 404, + 404, 0, 0, 404, 0, 404, 404, 404, 404, 404, + 404, 405, 405, 405, 0, 0, 405, 0, 405, 405, + 405, 405, 405, 405, 406, 406, 406, 0, 0, 406, + 0, 406, 406, 406, 406, 406, 406, 407, 407, 407, + 0, 0, 407, 407, 407, 407, 407, 407, 407, 407, + 408, 408, 408, 0, 0, 408, 0, 0, 0, 408, + 408, 408, 408, 0, 417, 417, 408, 417, 417, 417, + + 417, 422, 422, 0, 422, 422, 422, 422, 436, 436, + 436, 436, 0, 0, 408, 409, 409, 409, 0, 0, + 409, 0, 409, 409, 409, 409, 409, 409, 410, 410, + 410, 0, 0, 410, 0, 410, 410, 410, 410, 410, + 410, 412, 412, 412, 0, 0, 412, 0, 412, 412, + 412, 412, 412, 412, 413, 413, 413, 0, 0, 413, + 0, 413, 413, 413, 413, 413, 413, 414, 414, 414, + 0, 0, 414, 0, 414, 414, 414, 414, 414, 414, + 415, 415, 415, 0, 0, 415, 415, 415, 415, 415, + 415, 415, 415, 418, 418, 418, 0, 0, 418, 418, + + 418, 418, 418, 418, 418, 418, 419, 419, 419, 0, + 0, 419, 0, 0, 0, 419, 419, 419, 419, 0, + 0, 0, 419, 444, 444, 444, 444, 451, 451, 451, + 451, 437, 437, 437, 437, 437, 0, 0, 0, 437, + 419, 420, 420, 420, 0, 0, 420, 0, 420, 420, + 420, 420, 420, 420, 421, 421, 421, 437, 0, 421, + 0, 421, 421, 421, 421, 421, 421, 423, 423, 423, + 0, 0, 423, 0, 423, 423, 423, 423, 423, 423, + 424, 424, 424, 0, 0, 424, 0, 424, 424, 424, + 424, 424, 424, 425, 425, 425, 0, 0, 425, 0, + + 425, 425, 425, 425, 425, 425, 426, 426, 426, 0, + 0, 426, 426, 426, 426, 426, 426, 426, 426, 438, + 438, 438, 0, 0, 438, 0, 438, 438, 438, 438, + 438, 438, 439, 439, 439, 0, 0, 439, 0, 439, + 439, 439, 439, 439, 439, 445, 445, 445, 0, 0, + 445, 0, 0, 0, 445, 445, 445, 445, 446, 446, + 446, 0, 0, 446, 0, 446, 446, 446, 446, 446, + 446, 447, 447, 447, 0, 0, 447, 0, 447, 447, + 447, 447, 447, 447, 448, 448, 448, 0, 0, 448, + 0, 0, 448, 448, 448, 448, 448, 0, 0, 0, + + 448, 450, 450, 450, 450, 450, 459, 459, 459, 459, + 460, 460, 460, 460, 467, 467, 467, 467, 448, 449, + 449, 449, 0, 0, 449, 0, 449, 449, 449, 449, + 449, 449, 452, 452, 452, 0, 0, 452, 0, 0, + 452, 452, 452, 452, 452, 0, 0, 0, 452, 466, + 466, 466, 466, 466, 461, 461, 461, 461, 461, 686, + 686, 686, 461, 0, 686, 0, 452, 453, 453, 453, + 686, 0, 453, 0, 453, 453, 453, 453, 453, 453, + 461, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 463, 463, + 463, 463, 463, 463, 463, 463, 463, 463, 468, 468, + 468, 0, 0, 468, 0, 0, 468, 468, 468, 468, + 468, 0, 0, 0, 468, 474, 474, 474, 0, 0, + 474, 475, 475, 475, 475, 481, 481, 481, 481, 481, + 0, 474, 468, 469, 469, 469, 0, 0, 469, 0, + 469, 469, 469, 469, 469, 469, 470, 470, 470, 474, + 0, 470, 0, 470, 470, 470, 470, 470, 470, 476, + 476, 476, 0, 0, 476, 0, 0, 0, 476, 476, + + 476, 476, 477, 477, 477, 0, 0, 477, 0, 477, + 477, 477, 477, 477, 477, 478, 478, 478, 0, 0, + 478, 0, 478, 478, 478, 478, 478, 478, 479, 479, + 479, 0, 0, 479, 0, 0, 479, 479, 479, 479, + 479, 0, 0, 0, 479, 482, 482, 482, 482, 490, + 490, 490, 490, 491, 491, 491, 491, 493, 493, 493, + 493, 0, 479, 480, 480, 480, 0, 0, 480, 0, + 480, 480, 480, 480, 480, 480, 483, 483, 483, 0, + 0, 483, 0, 0, 483, 483, 483, 483, 483, 0, + 0, 0, 483, 489, 489, 489, 0, 0, 489, 494, + + 494, 494, 494, 498, 498, 498, 498, 498, 0, 489, + 483, 484, 484, 484, 0, 0, 484, 0, 484, 484, + 484, 484, 484, 484, 0, 0, 0, 489, 492, 492, + 492, 0, 0, 492, 0, 0, 0, 492, 492, 492, + 492, 0, 0, 0, 492, 499, 499, 499, 499, 507, + 507, 507, 507, 500, 500, 500, 500, 500, 0, 0, + 0, 500, 492, 495, 495, 495, 0, 0, 495, 0, + 495, 495, 495, 495, 495, 495, 496, 496, 496, 500, + 0, 496, 0, 496, 496, 496, 496, 496, 496, 501, + 501, 501, 0, 0, 501, 0, 501, 501, 501, 501, + + 501, 501, 502, 502, 502, 0, 0, 502, 0, 502, + 502, 502, 502, 502, 502, 508, 508, 508, 0, 0, + 508, 0, 0, 0, 508, 508, 508, 508, 509, 509, + 509, 0, 0, 509, 0, 509, 509, 509, 509, 509, + 509, 510, 510, 510, 0, 0, 510, 0, 510, 510, + 510, 510, 510, 510, 511, 511, 511, 0, 0, 511, + 0, 0, 511, 511, 511, 511, 511, 0, 0, 0, + 511, 513, 513, 513, 513, 513, 514, 514, 514, 514, + 522, 522, 522, 522, 523, 523, 523, 523, 511, 512, + 512, 512, 0, 0, 512, 0, 512, 512, 512, 512, + + 512, 512, 515, 515, 515, 0, 0, 515, 0, 0, + 515, 515, 515, 515, 515, 0, 0, 0, 515, 525, + 525, 525, 525, 525, 524, 524, 524, 524, 524, 928, + 928, 928, 524, 0, 928, 0, 515, 516, 516, 516, + 0, 0, 516, 0, 516, 516, 516, 516, 516, 516, + 524, 526, 526, 526, 526, 527, 527, 527, 527, 527, + 0, 0, 0, 527, 534, 534, 534, 534, 540, 540, + 540, 540, 540, 541, 541, 541, 541, 549, 549, 549, + 549, 527, 528, 528, 528, 0, 0, 528, 0, 528, + 528, 528, 528, 528, 528, 529, 529, 529, 0, 0, + + 529, 0, 529, 529, 529, 529, 529, 529, 535, 535, + 535, 0, 0, 535, 0, 0, 0, 535, 535, 535, + 535, 536, 536, 536, 0, 0, 536, 0, 536, 536, + 536, 536, 536, 536, 537, 537, 537, 0, 0, 537, + 0, 537, 537, 537, 537, 537, 537, 538, 538, 538, + 0, 0, 538, 0, 0, 538, 538, 538, 538, 538, + 0, 0, 0, 538, 550, 550, 550, 550, 553, 553, + 553, 553, 551, 551, 551, 551, 551, 0, 0, 0, + 551, 538, 539, 539, 539, 0, 0, 539, 0, 539, + 539, 539, 539, 539, 539, 542, 542, 542, 551, 0, + + 542, 0, 0, 542, 542, 542, 542, 542, 0, 0, + 0, 542, 552, 552, 552, 552, 552, 561, 561, 561, + 561, 567, 567, 567, 567, 567, 0, 0, 0, 542, + 543, 543, 543, 0, 0, 543, 0, 543, 543, 543, + 543, 543, 543, 554, 554, 554, 0, 0, 554, 0, + 0, 554, 554, 554, 554, 554, 0, 0, 0, 554, + 560, 560, 560, 0, 0, 560, 568, 568, 568, 568, + 576, 576, 576, 576, 0, 0, 560, 554, 555, 555, + 555, 0, 0, 555, 0, 555, 555, 555, 555, 555, + 555, 556, 556, 556, 560, 0, 556, 0, 556, 556, + + 556, 556, 556, 556, 562, 562, 562, 0, 0, 562, + 0, 0, 0, 562, 562, 562, 562, 563, 563, 563, + 0, 0, 563, 0, 563, 563, 563, 563, 563, 563, + 564, 564, 564, 0, 0, 564, 0, 564, 564, 564, + 564, 564, 564, 565, 565, 565, 0, 0, 565, 0, + 0, 565, 565, 565, 565, 565, 0, 0, 0, 565, + 575, 575, 575, 0, 0, 575, 577, 577, 577, 577, + 579, 579, 579, 579, 0, 0, 575, 565, 566, 566, + 566, 0, 0, 566, 0, 566, 566, 566, 566, 566, + 566, 569, 569, 569, 575, 0, 569, 0, 0, 569, + + 569, 569, 569, 569, 0, 0, 0, 569, 580, 580, + 580, 580, 584, 584, 584, 584, 584, 585, 585, 585, + 585, 593, 593, 593, 593, 569, 570, 570, 570, 0, + 0, 570, 0, 570, 570, 570, 570, 570, 570, 578, + 578, 578, 0, 0, 578, 0, 0, 0, 578, 578, + 578, 578, 0, 0, 0, 578, 599, 599, 599, 599, + 599, 0, 0, 0, 586, 586, 586, 586, 586, 0, + 0, 0, 586, 578, 581, 581, 581, 0, 0, 581, + 0, 581, 581, 581, 581, 581, 581, 582, 582, 582, + 586, 0, 582, 0, 582, 582, 582, 582, 582, 582, + + 587, 587, 587, 0, 0, 587, 0, 587, 587, 587, + 587, 587, 587, 588, 588, 588, 0, 0, 588, 0, + 588, 588, 588, 588, 588, 588, 594, 594, 594, 0, + 0, 594, 0, 0, 0, 594, 594, 594, 594, 595, + 595, 595, 0, 0, 595, 0, 595, 595, 595, 595, + 595, 595, 596, 596, 596, 0, 0, 596, 0, 596, + 596, 596, 596, 596, 596, 597, 597, 597, 0, 0, + 597, 0, 0, 597, 597, 597, 597, 597, 0, 0, + 0, 597, 600, 600, 600, 600, 608, 608, 608, 608, + 609, 609, 609, 609, 691, 691, 691, 691, 0, 597, + + 598, 598, 598, 0, 0, 598, 0, 598, 598, 598, + 598, 598, 598, 601, 601, 601, 0, 0, 601, 0, + 0, 601, 601, 601, 601, 601, 611, 611, 611, 601, + 0, 611, 0, 0, 0, 610, 610, 610, 610, 610, + 937, 937, 937, 610, 0, 937, 0, 601, 602, 602, + 602, 0, 937, 602, 611, 602, 602, 602, 602, 602, + 602, 610, 616, 616, 616, 616, 0, 617, 617, 616, + 617, 617, 617, 617, 622, 622, 0, 622, 622, 622, + 622, 692, 692, 692, 692, 0, 0, 616, 618, 618, + 618, 0, 0, 618, 618, 618, 618, 618, 618, 618, + + 618, 619, 619, 619, 0, 0, 619, 0, 619, 619, + 619, 619, 619, 619, 0, 627, 627, 619, 627, 627, + 627, 627, 639, 639, 0, 639, 639, 639, 639, 699, + 699, 699, 699, 0, 0, 619, 620, 620, 620, 0, + 0, 620, 620, 620, 620, 620, 620, 620, 620, 621, + 621, 621, 0, 0, 621, 0, 0, 0, 621, 621, + 621, 621, 0, 644, 644, 621, 644, 644, 644, 644, + 704, 704, 704, 704, 704, 643, 643, 643, 643, 0, + 0, 0, 643, 621, 623, 623, 623, 0, 0, 623, + 623, 623, 623, 623, 623, 623, 623, 624, 624, 624, + + 643, 0, 624, 0, 0, 0, 624, 624, 624, 624, + 0, 649, 649, 624, 649, 649, 649, 649, 705, 705, + 705, 705, 0, 651, 651, 651, 651, 0, 0, 0, + 651, 624, 625, 625, 625, 0, 0, 625, 0, 625, + 625, 625, 625, 625, 625, 626, 626, 626, 651, 0, + 626, 0, 626, 626, 626, 626, 626, 626, 628, 628, + 628, 0, 0, 628, 0, 628, 628, 628, 628, 628, + 628, 629, 629, 629, 0, 0, 629, 0, 629, 629, + 629, 629, 629, 629, 630, 630, 630, 0, 0, 630, + 0, 630, 630, 630, 630, 630, 630, 631, 631, 631, + + 0, 0, 631, 631, 631, 631, 631, 631, 631, 631, + 632, 632, 632, 0, 0, 632, 0, 632, 632, 632, + 632, 632, 632, 0, 652, 652, 632, 652, 652, 652, + 652, 657, 657, 0, 657, 657, 657, 657, 713, 713, + 713, 713, 0, 0, 632, 633, 633, 633, 0, 0, + 633, 0, 633, 633, 633, 633, 633, 633, 634, 634, + 634, 0, 0, 634, 0, 634, 634, 634, 634, 634, + 634, 635, 635, 635, 0, 0, 635, 0, 635, 635, + 635, 635, 635, 635, 636, 636, 636, 0, 0, 636, + 636, 636, 636, 636, 636, 636, 636, 637, 637, 637, + + 0, 0, 637, 0, 0, 0, 637, 637, 637, 637, + 0, 662, 662, 637, 662, 662, 662, 662, 674, 674, + 0, 674, 674, 674, 674, 718, 718, 718, 718, 718, + 0, 637, 638, 638, 638, 0, 0, 638, 0, 638, + 638, 638, 638, 638, 638, 640, 640, 640, 0, 0, + 640, 0, 640, 640, 640, 640, 640, 640, 641, 641, + 641, 0, 0, 641, 0, 641, 641, 641, 641, 641, + 641, 642, 642, 642, 0, 0, 642, 642, 642, 642, + 642, 642, 642, 642, 645, 645, 645, 0, 0, 645, + 645, 645, 645, 645, 645, 645, 645, 646, 646, 646, + + 0, 0, 646, 0, 646, 646, 646, 646, 646, 646, + 0, 679, 679, 646, 679, 679, 679, 679, 719, 719, + 719, 719, 0, 678, 678, 678, 678, 0, 0, 0, + 678, 646, 647, 647, 647, 0, 0, 647, 647, 647, + 647, 647, 647, 647, 647, 648, 648, 648, 678, 0, + 648, 0, 0, 0, 648, 648, 648, 648, 0, 684, + 684, 648, 684, 684, 684, 684, 727, 727, 727, 727, + 706, 706, 706, 706, 706, 0, 0, 0, 706, 648, + 650, 650, 650, 0, 0, 650, 650, 650, 650, 650, + 650, 650, 650, 653, 653, 653, 706, 0, 653, 653, + + 653, 653, 653, 653, 653, 653, 654, 654, 654, 0, + 0, 654, 0, 654, 654, 654, 654, 654, 654, 0, + 0, 0, 654, 698, 698, 698, 0, 0, 698, 728, + 728, 728, 728, 734, 734, 734, 734, 734, 0, 698, + 654, 655, 655, 655, 0, 0, 655, 655, 655, 655, + 655, 655, 655, 655, 656, 656, 656, 698, 0, 656, + 0, 0, 0, 656, 656, 656, 656, 0, 0, 0, + 656, 735, 735, 735, 735, 743, 743, 743, 743, 729, + 729, 729, 729, 729, 0, 0, 0, 729, 656, 658, + 658, 658, 0, 0, 658, 658, 658, 658, 658, 658, + + 658, 658, 659, 659, 659, 729, 0, 659, 0, 0, + 0, 659, 659, 659, 659, 0, 0, 0, 659, 744, + 744, 744, 744, 746, 746, 746, 746, 745, 745, 745, + 745, 745, 0, 0, 0, 745, 659, 660, 660, 660, + 0, 0, 660, 0, 660, 660, 660, 660, 660, 660, + 661, 661, 661, 745, 0, 661, 0, 661, 661, 661, + 661, 661, 661, 663, 663, 663, 0, 0, 663, 0, + 663, 663, 663, 663, 663, 663, 664, 664, 664, 0, + 0, 664, 0, 664, 664, 664, 664, 664, 664, 665, + 665, 665, 0, 0, 665, 0, 665, 665, 665, 665, + + 665, 665, 666, 666, 666, 0, 0, 666, 666, 666, + 666, 666, 666, 666, 666, 667, 667, 667, 0, 0, + 667, 0, 667, 667, 667, 667, 667, 667, 0, 0, + 0, 667, 751, 751, 751, 751, 752, 752, 752, 752, + 753, 753, 753, 753, 753, 0, 0, 0, 753, 667, + 668, 668, 668, 0, 0, 668, 0, 668, 668, 668, + 668, 668, 668, 669, 669, 669, 753, 0, 669, 0, + 669, 669, 669, 669, 669, 669, 670, 670, 670, 0, + 0, 670, 0, 670, 670, 670, 670, 670, 670, 671, + 671, 671, 0, 0, 671, 671, 671, 671, 671, 671, + + 671, 671, 672, 672, 672, 0, 0, 672, 0, 0, + 0, 672, 672, 672, 672, 0, 0, 0, 672, 754, + 754, 754, 754, 755, 755, 755, 755, 762, 762, 762, + 762, 767, 767, 767, 767, 0, 672, 673, 673, 673, + 0, 0, 673, 0, 673, 673, 673, 673, 673, 673, + 675, 675, 675, 0, 0, 675, 0, 675, 675, 675, + 675, 675, 675, 676, 676, 676, 0, 0, 676, 0, + 676, 676, 676, 676, 676, 676, 677, 677, 677, 0, + 0, 677, 677, 677, 677, 677, 677, 677, 677, 680, + 680, 680, 0, 0, 680, 680, 680, 680, 680, 680, + + 680, 680, 681, 681, 681, 0, 0, 681, 0, 681, + 681, 681, 681, 681, 681, 0, 0, 0, 681, 761, + 761, 761, 0, 0, 761, 768, 768, 768, 768, 775, + 775, 775, 775, 0, 0, 761, 681, 682, 682, 682, + 0, 0, 682, 682, 682, 682, 682, 682, 682, 682, + 683, 683, 683, 761, 0, 683, 0, 0, 0, 683, + 683, 683, 683, 0, 0, 0, 683, 774, 774, 774, + 0, 0, 774, 780, 780, 780, 780, 780, 781, 781, + 781, 781, 0, 774, 683, 685, 685, 685, 0, 0, + 685, 685, 685, 685, 685, 685, 685, 685, 693, 693, + + 693, 774, 0, 693, 0, 693, 693, 693, 693, 693, + 693, 694, 694, 694, 0, 0, 694, 0, 694, 694, + 694, 694, 694, 694, 696, 696, 696, 0, 0, 696, + 0, 696, 696, 696, 696, 696, 696, 697, 697, 697, + 0, 0, 697, 0, 697, 697, 697, 697, 697, 697, + 700, 700, 700, 0, 0, 700, 0, 0, 0, 700, + 700, 700, 700, 701, 701, 701, 0, 0, 701, 0, + 701, 701, 701, 701, 701, 701, 702, 702, 702, 0, + 0, 702, 0, 702, 702, 702, 702, 702, 702, 707, + 707, 707, 0, 0, 707, 0, 707, 707, 707, 707, + + 707, 707, 708, 708, 708, 0, 0, 708, 0, 708, + 708, 708, 708, 708, 708, 714, 714, 714, 0, 0, + 714, 0, 0, 0, 714, 714, 714, 714, 715, 715, + 715, 0, 0, 715, 0, 715, 715, 715, 715, 715, + 715, 716, 716, 716, 0, 0, 716, 0, 716, 716, + 716, 716, 716, 716, 717, 717, 717, 0, 0, 717, + 0, 0, 717, 717, 717, 717, 717, 0, 0, 0, + 717, 789, 789, 789, 789, 0, 782, 782, 782, 782, + 782, 938, 938, 938, 782, 0, 938, 0, 717, 720, + 720, 720, 0, 0, 720, 0, 0, 720, 720, 720, + + 720, 720, 782, 0, 0, 720, 794, 794, 794, 794, + 794, 795, 795, 795, 795, 803, 803, 803, 803, 804, + 804, 804, 804, 720, 721, 721, 721, 0, 0, 721, + 0, 721, 721, 721, 721, 721, 721, 722, 722, 722, + 0, 0, 722, 0, 722, 722, 722, 722, 722, 722, + 730, 730, 730, 0, 0, 730, 0, 730, 730, 730, + 730, 730, 730, 731, 731, 731, 0, 0, 731, 0, + 731, 731, 731, 731, 731, 731, 732, 732, 732, 0, + 0, 732, 0, 0, 732, 732, 732, 732, 732, 0, + 0, 0, 732, 810, 810, 810, 810, 810, 0, 0, + + 0, 805, 805, 805, 805, 805, 0, 0, 0, 805, + 732, 733, 733, 733, 0, 0, 733, 0, 733, 733, + 733, 733, 733, 733, 736, 736, 736, 805, 0, 736, + 0, 0, 736, 736, 736, 736, 736, 0, 0, 0, + 736, 811, 811, 811, 811, 819, 819, 819, 819, 820, + 820, 820, 820, 822, 822, 822, 822, 0, 736, 737, + 737, 737, 0, 0, 737, 0, 737, 737, 737, 737, + 737, 737, 747, 747, 747, 0, 0, 747, 0, 0, + 0, 747, 747, 747, 747, 748, 748, 748, 0, 0, + 748, 0, 748, 748, 748, 748, 748, 748, 749, 749, + + 749, 0, 0, 749, 0, 749, 749, 749, 749, 749, + 749, 750, 750, 750, 0, 0, 750, 0, 0, 750, + 750, 750, 750, 750, 0, 0, 0, 750, 827, 827, + 827, 827, 828, 828, 828, 828, 821, 821, 821, 821, + 821, 0, 0, 0, 821, 750, 756, 756, 756, 0, + 0, 756, 0, 756, 756, 756, 756, 756, 756, 757, + 757, 757, 821, 0, 757, 0, 757, 757, 757, 757, + 757, 757, 759, 759, 759, 0, 0, 759, 0, 759, + 759, 759, 759, 759, 759, 760, 760, 760, 0, 0, + 760, 0, 760, 760, 760, 760, 760, 760, 763, 763, + + 763, 0, 0, 763, 0, 0, 0, 763, 763, 763, + 763, 764, 764, 764, 0, 0, 764, 0, 764, 764, + 764, 764, 764, 764, 765, 765, 765, 0, 0, 765, + 0, 765, 765, 765, 765, 765, 765, 769, 769, 769, + 0, 0, 769, 0, 769, 769, 769, 769, 769, 769, + 770, 770, 770, 0, 0, 770, 0, 770, 770, 770, + 770, 770, 770, 772, 772, 772, 0, 0, 772, 0, + 772, 772, 772, 772, 772, 772, 773, 773, 773, 0, + 0, 773, 0, 773, 773, 773, 773, 773, 773, 776, + 776, 776, 0, 0, 776, 0, 0, 0, 776, 776, + + 776, 776, 777, 777, 777, 0, 0, 777, 0, 777, + 777, 777, 777, 777, 777, 778, 778, 778, 0, 0, + 778, 0, 778, 778, 778, 778, 778, 778, 783, 783, + 783, 0, 0, 783, 0, 783, 783, 783, 783, 783, + 783, 784, 784, 784, 0, 0, 784, 0, 784, 784, + 784, 784, 784, 784, 790, 790, 790, 0, 0, 790, + 0, 0, 0, 790, 790, 790, 790, 791, 791, 791, + 0, 0, 791, 0, 791, 791, 791, 791, 791, 791, + 792, 792, 792, 0, 0, 792, 0, 792, 792, 792, + 792, 792, 792, 793, 793, 793, 0, 0, 793, 0, + + 0, 793, 793, 793, 793, 793, 0, 0, 0, 793, + 830, 830, 830, 830, 0, 829, 829, 829, 829, 829, + 939, 939, 939, 829, 0, 939, 0, 793, 796, 796, + 796, 0, 0, 796, 0, 0, 796, 796, 796, 796, + 796, 829, 0, 0, 796, 831, 831, 831, 831, 838, + 838, 838, 838, 843, 843, 843, 0, 0, 843, 0, + 0, 843, 796, 797, 797, 797, 0, 0, 797, 0, + 797, 797, 797, 797, 797, 797, 798, 798, 798, 0, + 0, 798, 0, 798, 798, 798, 798, 798, 798, 806, + 806, 806, 0, 0, 806, 0, 806, 806, 806, 806, + + 806, 806, 807, 807, 807, 0, 0, 807, 0, 807, + 807, 807, 807, 807, 807, 808, 808, 808, 0, 0, + 808, 0, 0, 808, 808, 808, 808, 808, 0, 0, + 0, 808, 837, 837, 837, 848, 848, 837, 848, 848, + 848, 848, 865, 865, 865, 865, 865, 0, 837, 808, + 809, 809, 809, 0, 0, 809, 0, 809, 809, 809, + 809, 809, 809, 812, 812, 812, 837, 0, 812, 0, + 0, 812, 812, 812, 812, 812, 0, 853, 853, 812, + 853, 853, 853, 853, 867, 867, 867, 867, 867, 847, + 847, 847, 847, 0, 0, 0, 847, 812, 813, 813, + + 813, 0, 0, 813, 0, 813, 813, 813, 813, 813, + 813, 823, 823, 823, 847, 0, 823, 0, 0, 0, + 823, 823, 823, 823, 824, 824, 824, 0, 0, 824, + 0, 824, 824, 824, 824, 824, 824, 825, 825, 825, + 0, 0, 825, 0, 825, 825, 825, 825, 825, 825, + 826, 826, 826, 0, 0, 826, 0, 0, 826, 826, + 826, 826, 826, 0, 858, 858, 826, 858, 858, 858, + 858, 870, 870, 870, 870, 870, 862, 862, 862, 862, + 0, 0, 0, 862, 826, 832, 832, 832, 0, 0, + 832, 0, 832, 832, 832, 832, 832, 832, 833, 833, + + 833, 862, 0, 833, 0, 833, 833, 833, 833, 833, + 833, 835, 835, 835, 0, 0, 835, 0, 835, 835, + 835, 835, 835, 835, 836, 836, 836, 0, 0, 836, + 0, 836, 836, 836, 836, 836, 836, 839, 839, 839, + 0, 0, 839, 0, 0, 0, 839, 839, 839, 839, + 840, 840, 840, 0, 0, 840, 0, 840, 840, 840, + 840, 840, 840, 841, 841, 841, 0, 0, 841, 0, + 841, 841, 841, 841, 841, 841, 849, 849, 849, 0, + 0, 849, 849, 849, 849, 849, 849, 849, 849, 850, + 850, 850, 0, 0, 850, 0, 850, 850, 850, 850, + + 850, 850, 0, 863, 863, 850, 863, 863, 863, 863, + 864, 864, 0, 864, 864, 864, 864, 872, 872, 872, + 872, 872, 0, 850, 851, 851, 851, 0, 0, 851, + 851, 851, 851, 851, 851, 851, 851, 852, 852, 852, + 0, 0, 852, 0, 0, 0, 852, 852, 852, 852, + 0, 866, 866, 852, 866, 866, 866, 866, 868, 868, + 0, 868, 868, 868, 868, 875, 875, 875, 875, 875, + 0, 852, 854, 854, 854, 0, 0, 854, 854, 854, + 854, 854, 854, 854, 854, 855, 855, 855, 0, 0, + 855, 0, 855, 855, 855, 855, 855, 855, 0, 869, + + 869, 855, 869, 869, 869, 869, 871, 871, 0, 871, + 871, 871, 871, 880, 880, 880, 880, 0, 0, 855, + 856, 856, 856, 0, 0, 856, 856, 856, 856, 856, + 856, 856, 856, 857, 857, 857, 0, 0, 857, 0, + 0, 0, 857, 857, 857, 857, 0, 873, 873, 857, + 873, 873, 873, 873, 874, 874, 0, 874, 874, 874, + 874, 881, 881, 881, 881, 0, 0, 857, 859, 859, + 859, 0, 0, 859, 859, 859, 859, 859, 859, 859, + 859, 860, 860, 860, 0, 0, 860, 0, 860, 860, + 860, 860, 860, 860, 0, 876, 876, 860, 876, 876, + + 876, 876, 877, 877, 877, 0, 0, 877, 940, 940, + 940, 877, 0, 940, 0, 860, 861, 861, 861, 0, + 0, 861, 861, 861, 861, 861, 861, 861, 861, 882, + 882, 882, 0, 0, 882, 0, 882, 882, 882, 882, + 882, 882, 887, 887, 887, 0, 0, 887, 887, 887, + 888, 888, 888, 888, 896, 896, 896, 896, 887, 904, + 904, 904, 904, 905, 905, 905, 905, 906, 906, 906, + 906, 907, 907, 907, 907, 0, 887, 889, 889, 889, + 0, 0, 889, 0, 0, 0, 889, 889, 889, 889, + 890, 890, 890, 0, 0, 890, 0, 890, 890, 890, + + 890, 890, 890, 895, 895, 895, 0, 0, 895, 895, + 895, 908, 908, 908, 908, 0, 0, 0, 908, 895, + 909, 909, 909, 909, 910, 910, 910, 910, 912, 912, + 912, 912, 914, 914, 914, 914, 908, 895, 897, 897, + 897, 0, 0, 897, 0, 0, 0, 897, 897, 897, + 897, 898, 898, 898, 0, 0, 898, 0, 898, 898, + 898, 898, 898, 898, 903, 903, 903, 0, 0, 903, + 903, 903, 0, 911, 911, 911, 911, 911, 0, 0, + 903, 911, 915, 915, 915, 915, 0, 0, 916, 916, + 916, 916, 936, 936, 936, 916, 0, 936, 903, 911, + + 913, 913, 913, 0, 0, 913, 0, 0, 0, 913, + 913, 913, 913, 916, 917, 917, 917, 917, 918, 918, + 918, 918, 919, 919, 919, 919, 919, 936, 0, 0, + 919, 920, 920, 920, 920, 921, 921, 921, 921, 922, + 922, 922, 922, 923, 923, 923, 923, 0, 919, 924, + 924, 924, 924, 0, 0, 0, 924, 925, 925, 925, + 925, 926, 926, 926, 926, 927, 927, 927, 927, 927, + 931, 931, 931, 927, 924, 931, 934, 934, 934, 0, + 941, 934, 941, 0, 0, 941, 0, 942, 942, 942, + 0, 927, 942, 943, 944, 943, 944, 0, 943, 944, + + 945, 946, 945, 946, 0, 945, 946, 947, 0, 947, + 0, 0, 947, 931, 0, 0, 0, 0, 934, 949, + 949, 949, 949, 949, 949, 949, 949, 950, 950, 950, + 950, 950, 950, 950, 950, 951, 951, 951, 951, 951, + 951, 951, 951, 952, 952, 952, 952, 952, 952, 952, + 952, 953, 953, 953, 953, 953, 953, 953, 953, 954, + 0, 0, 954, 955, 0, 0, 955, 0, 955, 955, + 955, 956, 956, 956, 956, 956, 956, 956, 956, 957, + 0, 0, 957, 0, 957, 957, 958, 958, 958, 958, + 958, 958, 958, 958, 959, 959, 0, 959, 0, 959, + + 959, 959, 960, 960, 960, 960, 960, 960, 960, 960, + 961, 961, 0, 961, 961, 961, 961, 961, 962, 962, + 962, 962, 962, 962, 962, 962, 963, 963, 963, 963, + 963, 963, 963, 963, 964, 964, 0, 0, 964, 964, + 966, 966, 966, 966, 966, 966, 966, 966, 967, 967, + 967, 967, 967, 967, 967, 967, 968, 968, 968, 968, + 968, 968, 968, 968, 969, 969, 969, 969, 969, 969, + 969, 969, 971, 971, 971, 971, 971, 971, 971, 971, + 972, 972, 972, 972, 972, 972, 972, 972, 973, 973, + 973, 973, 973, 973, 973, 973, 974, 974, 0, 974, + + 0, 974, 974, 974, 975, 975, 975, 975, 975, 975, + 975, 975, 977, 977, 0, 977, 977, 977, 977, 977, + 978, 978, 978, 978, 978, 978, 978, 978, 979, 0, + 0, 979, 980, 980, 980, 980, 980, 980, 980, 980, + 981, 981, 981, 981, 981, 981, 981, 981, 982, 982, + 0, 0, 982, 982, 984, 984, 984, 984, 984, 984, + 984, 984, 986, 986, 986, 986, 986, 986, 986, 986, + 987, 987, 987, 987, 987, 987, 987, 987, 989, 989, + 989, 989, 989, 989, 989, 989, 990, 990, 990, 990, + 990, 990, 990, 990, 991, 991, 991, 991, 991, 991, + + 991, 991, 992, 992, 992, 992, 992, 992, 992, 992, + 993, 993, 993, 993, 993, 993, 993, 993, 994, 994, + 994, 994, 994, 994, 994, 994, 995, 995, 995, 995, + 995, 995, 995, 995, 996, 996, 996, 996, 996, 996, + 996, 996, 997, 997, 997, 997, 997, 997, 997, 997, + 998, 998, 998, 998, 998, 998, 998, 998, 999, 999, + 999, 999, 999, 999, 999, 999, 1000, 1000, 1000, 1000, + 1000, 1000, 1000, 1000, 1001, 1001, 1001, 1001, 1001, 1001, + 1001, 1001, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002, + 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1004, 1004, + + 1004, 1004, 1004, 1004, 1004, 1004, 1005, 1005, 1005, 1005, + 1005, 1005, 1005, 1005, 1006, 0, 0, 1006, 1007, 1007, + 1007, 1007, 1007, 1007, 1007, 1007, 1008, 1008, 1008, 1008, + 1008, 1008, 1008, 1008, 1009, 1009, 1009, 1009, 1009, 1009, + 1009, 1009, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1013, 1013, + 1013, 1013, 1013, 1013, 1013, 1013, 1014, 1014, 1014, 1014, + 1014, 1014, 1014, 1014, 1015, 1015, 1015, 1015, 1015, 1015, + 1015, 1015, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, + 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1018, 1018, + + 1018, 1018, 1018, 1018, 1018, 1018, 1019, 1019, 1019, 1019, + 1019, 1019, 1019, 1019, 1020, 1020, 1020, 1020, 1020, 1020, + 1020, 1020, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, + 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1022, 1023, 1023, + 1023, 1023, 1023, 1023, 1023, 1023, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 1024, 1025, 1025, 1025, 1025, 1025, 1025, + 1025, 1025, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, + 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1027, 1028, 1028, + 1028, 1028, 1028, 1028, 1028, 1028, 1029, 0, 0, 1029, + 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1030, 1031, 1031, + + 1031, 1031, 1031, 1031, 1031, 1031, 1032, 1032, 1032, 1032, + 1032, 1032, 1032, 1032, 1033, 1033, 1033, 1033, 1033, 1033, + 1033, 1033, 1034, 1034, 1034, 1034, 1034, 1034, 1034, 1034, + 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1035, 1036, 1036, + 1036, 1036, 1036, 1036, 1036, 1036, 1037, 1037, 1037, 1037, + 1037, 1037, 1037, 1037, 1038, 1038, 1038, 1038, 1038, 1038, + 1038, 1038, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1039, + 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1040, 1041, 1041, + 1041, 1041, 1041, 1041, 1041, 1041, 1042, 1042, 1042, 1042, + 1042, 1042, 1042, 1042, 1043, 1043, 1043, 1043, 1043, 1043, + + 1043, 1043, 1044, 1044, 1044, 1044, 1044, 1044, 1044, 1044, + 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1045, 1046, 1046, + 1046, 1046, 1046, 1046, 1046, 1046, 1047, 1047, 1047, 1047, + 1047, 1047, 1047, 1047, 1048, 1048, 1048, 1048, 1048, 1048, + 1048, 1048, 1049, 1049, 1049, 1049, 1049, 1049, 1049, 1049, + 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1051, 1051, + 1051, 1051, 1051, 1051, 1051, 1051, 1052, 1052, 1052, 1052, + 1052, 1052, 1052, 1052, 1053, 1053, 1053, 1053, 1053, 1053, + 1053, 1053, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, + 1055, 0, 0, 1055, 1056, 1056, 1056, 1056, 1056, 1056, + + 1056, 1056, 1057, 1057, 1057, 1057, 1057, 1057, 1057, 1057, + 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1058, 1059, 1059, + 1059, 1059, 1059, 1059, 1059, 1059, 1060, 1060, 1060, 1060, + 1060, 1060, 1060, 1060, 1061, 1061, 1061, 1061, 1061, 1061, + 1061, 1061, 1062, 1062, 1062, 1062, 1062, 1062, 1062, 1062, + 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1063, 1064, 1064, + 1064, 1064, 1064, 1064, 1064, 1064, 1065, 1065, 1065, 1065, + 1065, 1065, 1065, 1065, 1066, 1066, 1066, 1066, 1066, 1066, + 1066, 1066, 1067, 1067, 1067, 1067, 1067, 1067, 1067, 1067, + 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1068, 1069, 1069, + + 1069, 1069, 1069, 1069, 1069, 1069, 1070, 1070, 1070, 1070, + 1070, 1070, 1070, 1070, 1071, 1071, 1071, 1071, 1071, 1071, + 1071, 1071, 1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072, + 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1073, 1074, 1074, + 1074, 1074, 1074, 1074, 1074, 1074, 1075, 1075, 1075, 1075, + 1075, 1075, 1075, 1075, 1076, 1076, 1076, 1076, 1076, 1076, + 1076, 1076, 1077, 1077, 1077, 1077, 1077, 1077, 1077, 1077, + 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1078, 1079, 1079, + 1079, 1079, 1079, 1079, 1079, 1079, 1080, 1080, 1080, 1080, + 1080, 1080, 1080, 1080, 1081, 0, 0, 1081, 1082, 1082, + + 1082, 1082, 1082, 1082, 1082, 1082, 1083, 1083, 1083, 1083, + 1083, 1083, 1083, 1083, 1084, 1084, 1084, 1084, 1084, 1084, + 1084, 1084, 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1086, 1087, 1087, + 1087, 1087, 1087, 1087, 1087, 1087, 1088, 1088, 1088, 1088, + 1088, 1088, 1088, 1088, 1089, 1089, 0, 1089, 1089, 1089, + 1089, 1089, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948, + + 948, 948, 948, 948, 948, 948, 948, 948, 948, 948 +} ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 1; + +static const short int yy_rule_linenum[49] = +{ 0, + 122, 127, 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 141, 145, 149, 157, 160, 164, 169, + 177, 178, 180, 184, 195, 199, 205, 206, 211, 220, + 234, 235, 240, 249, 260, 263, 264, 266, 270, 274, + 279, 281, 282, 289, 295, 302, 305, 309 +} ; + +/* 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 +char *yytext; +/************************************************** + * VRML 2.0 Parser + * Copyright (C) 1996 Silicon Graphics, Inc. + * + * Author(s) : Gavin Bell + * Daniel Woods (first port) + ************************************************** + */ +//#include "tokens.h" +#include + +// used to reset the lexer input after initialization of VRML nodes +void (*theyyInput)(char *, int &, int); + +// We define the YY_INPUT so we an change the input source later +#define YY_INPUT(buf, result, max_size) (*theyyInput)(buf, result, max_size); + +/* Current line number */ +int currentLineNumber = 1; +void yyResetLineNumber() { currentLineNumber = 1; } + +extern void yyerror(const char *); + + /* The YACC parser sets this to a token to direct the lexer */ + /* in cases where just syntax isn't enough: */ +int expectToken = 0; + +/* True when parsing a multiple-valued field: */ +static int parsing_mf = 0; + +/* These are used when parsing SFImage fields: */ +static int sfImageIntsParsed = 0; +static int sfImageIntsExpected = 0; + +#ifdef __cplusplus +extern "C" +#endif +int yywrap() { BEGIN INITIAL; return 1; } + +/* Normal state: parsing nodes. The initial start state is used */ +/* only to recognize the VRML header. */ +/* Start tokens for all of the field types, */ +/* except for MFNode and SFNode, which are almost completely handled */ +/* by the parser: */ +/* Big hairy expression for floating point numbers: */ +/* Ints are decimal or hex (0x##): */ +/* Whitespace. Using this pattern can screw up currentLineNumber, */ +/* so it is only used wherever it is really convenient and it is */ +/* extremely unlikely that the user will put in a carriage return */ +/* (example: between the floats in an SFVec3f) */ +/* And the same pattern without the newline */ +/* Legal characters to start an identifier */ +/* Legal other characters in an identifier */ + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#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 +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#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 ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = getc( yyin ); \ + result = c == EOF ? 0 : 1; \ + buf[0] = (char) c; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + 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) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex ( vtkVRMLImporter* self ) +#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 + +vtkCxxRevisionMacro(vtkVRMLImporter, "$Revision: 1.71 $"); +vtkStandardNewMacro(vtkVRMLImporter); + +vtkPoints* vtkVRMLImporter::PointsNew() +{ + vtkPoints* pts = vtkPoints::New(); + this->Internal->Heap.Push(pts); + return pts; +} + +vtkFloatArray* vtkVRMLImporter::FloatArrayNew() +{ + vtkFloatArray* array = vtkFloatArray::New(); + this->Internal->Heap.Push(array); + return array; +} + +vtkIdTypeArray* vtkVRMLImporter::IdTypeArrayNew() +{ + vtkIdTypeArray* array = vtkIdTypeArray::New(); + this->Internal->Heap.Push(array); + return array; +} + +void vtkVRMLImporter::DeleteObject(vtkObject* obj) +{ + for(int i=0; iInternal->Heap.Count(); i++) + { + if (obj == this->Internal->Heap[i]) + { + this->Internal->Heap[i] = 0; + } + } + obj->Delete(); +} + +int yylex ( vtkVRMLImporter* self ) +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + + + + /* Switch into a new start state if the parser */ + /* just told us that we've read a field name */ + /* and should expect a field value (or IS) */ + if (expectToken != 0) { + if (yy_flex_debug) + fprintf(stderr,"LEX--> Start State %d\n", expectToken); + + /* + * Annoying. This big switch is necessary because + * LEX wants to assign particular numbers to start + * tokens, and YACC wants to define all the tokens + * used, too. Sigh. + */ + switch(expectToken) { + case SFBOOL: BEGIN SFB; break; + case SFCOLOR: BEGIN SFC; break; + case SFFLOAT: BEGIN SFF; break; + case SFIMAGE: BEGIN SFIMG; break; + case SFINT32: BEGIN SFI; break; + case SFROTATION: BEGIN SFR; break; + case SFSTRING: BEGIN SFS; break; + case SFTIME: BEGIN SFT; break; + case SFVEC2F: BEGIN SFV2; break; + case SFVEC3F: BEGIN SFV3; break; + case MFCOLOR: BEGIN MFC; break; + case MFFLOAT: BEGIN MFF; break; + case MFINT32: BEGIN MFI; break; + case MFROTATION: BEGIN MFR; break; + case MFSTRING: BEGIN MFS; break; + case MFVEC2F: BEGIN MFV2; break; + case MFVEC3F: BEGIN MFV3; break; + + /* SFNode and MFNode are special. Here the lexer just returns */ + /* "marker tokens" so the parser knows what type of field is */ + /* being parsed; unlike the other fields, parsing of SFNode/MFNode */ + /* field happens in the parser. */ + case MFNODE: expectToken = 0; return MFNODE; + case SFNODE: expectToken = 0; return SFNODE; + + default: yyerror("ACK: Bad expectToken"); break; + } + } + + + /* This is more complicated than they really need to be because */ + /* I was ambitious and made the whitespace-matching rule aggressive */ + + if ( yy_init ) + { +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( yy_current_buffer ) + yy_init_buffer( yy_current_buffer, yyin ); + else + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + + yy_init = 0; + } + + 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 >= 949 ) + 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] != 7663 ); + + yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + + + do_action: /* This label is used only to access EOF actions. */ + + if ( yy_flex_debug ) + { + if ( yy_act == 0 ) + fprintf( stderr, "--scanner backing up\n" ); + else if ( yy_act < 49 ) + fprintf( stderr, "--accepting rule at line %d (\"%s\")\n", + yy_rule_linenum[yy_act], yytext ); + else if ( yy_act == 49 ) + fprintf( stderr, "--accepting default rule (\"%s\")\n", + yytext ); + else if ( yy_act == 50 ) + fprintf( stderr, "--(end of buffer or a NUL)\n" ); + else + fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); + } + + 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_USER_ACTION + { BEGIN NODE; } + YY_BREAK + /* The lexer is in the NODE state when parsing nodes, either */ + /* top-level nodes in the .wrl file, in a prototype implementation, */ + /* or when parsing the contents of SFNode or MFNode fields. */ + case 2: + YY_USER_ACTION + { return PROTO; } + case 3: + YY_USER_ACTION + { return EXTERNPROTO; } + case 4: + YY_USER_ACTION + { return DEF; } + case 5: + YY_USER_ACTION + { return USE; } + case 6: + YY_USER_ACTION + { return TO; } + case 7: + YY_USER_ACTION + { return IS; } + case 8: + YY_USER_ACTION + { return ROUTE; } + case 9: + YY_USER_ACTION + { return SFN_NULL; } + case 10: + YY_USER_ACTION + { return EVENTIN; } + case 11: + YY_USER_ACTION + { return EVENTOUT; } + case 12: + YY_USER_ACTION + { return FIELD; } + case 13: + YY_USER_ACTION + { return EXPOSEDFIELD; } + /* Legal identifiers: */ + case 14: + YY_USER_ACTION + { + yylval.string = vtkVRMLAllocator::StrDup(yytext); + return IDENTIFIER; } + /* All fields may have an IS declaration: */ + case 15: + YY_USER_ACTION + { BEGIN NODE; + expectToken = 0; + yyless(0); + } + YY_BREAK + case 16: + YY_USER_ACTION + { BEGIN NODE; + expectToken = 0; + yyless(0); /* put back the IS */ + } + YY_BREAK + /* All MF field types other than MFNode are completely parsed here */ + /* in the lexer, and one token is returned to the parser. They all */ + /* share the same rules for open and closing brackets: */ + case 17: + YY_USER_ACTION + { if (parsing_mf) yyerror("Double ["); + parsing_mf = 1; + yylval.vec2f = self->FloatArrayNew(); + yylval.vec2f->SetNumberOfComponents(2); + } + YY_BREAK + case 18: + YY_USER_ACTION + { if (parsing_mf) yyerror("Double ["); + parsing_mf = 1; + yylval.mfint32 = self->IdTypeArrayNew(); + } + YY_BREAK + case 19: + YY_USER_ACTION + { if (parsing_mf) yyerror("Double ["); + parsing_mf = 1; + yylval.vec3f = self->PointsNew(); + } + YY_BREAK + case 20: + YY_USER_ACTION + { if (!parsing_mf) yyerror("Unmatched ]"); + int fieldType = expectToken; + BEGIN NODE; + parsing_mf = 0; + expectToken = 0; + return fieldType; + } + case 21: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; yylval.sfint = 1; return SFBOOL; } + case 22: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; yylval.sfint = 0; return SFBOOL; } + case 23: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; + yylval.sfint = atoi(yytext); + return SFINT32; + } + case 24: + YY_USER_ACTION + { if (parsing_mf) { + int num; + num = atoi(yytext); + yylval.mfint32->InsertNextValue(num); + } + else { + BEGIN NODE; expectToken = 0; return MFINT32; + } + } + YY_BREAK + /* All the floating-point types are pretty similar: */ + case 25: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; float num; + sscanf(yytext, "%f", &num); + yylval.sffloat = num; + return SFFLOAT; } + case 26: + YY_USER_ACTION + { if (parsing_mf) ; /* Add to array... */ + else { + /* No open bracket means a single value: */ + BEGIN NODE; expectToken = 0; return MFFLOAT; + } + } + YY_BREAK + case 27: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; return SFVEC2F; } + case 28: + YY_USER_ACTION + { + if (parsing_mf) + { + // .. add to array... + float num[2]; + num[0] = atof(strtok(yytext, " ")); + num[1] = atof(strtok(NULL, " ")); + // equivalent to: sscanf(yytext, "%f %f", &num[0], &num[1]); + yylval.vec2f->InsertNextTuple(num); + } + else + { + BEGIN NODE; expectToken = 0; + return MFVEC2F; + } + } + YY_BREAK + case 29: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; + float num[3]; + yylval.vec3f = self->PointsNew(); + num[0] = atof(strtok(yytext, " ")); + num[1] = atof(strtok(NULL, " ")); + num[2] = atof(strtok(NULL, " ")); + //sscanf(yytext, "%f %f %f", &num[0], &num[1], &num[2]); + yylval.vec3f->InsertPoint(0, num); + return SFVEC3F; } + case 30: + YY_USER_ACTION + { if (parsing_mf) { /* .. add to array... */ + float num[3]; + num[0] = atof(strtok(yytext, " ")); + num[1] = atof(strtok(NULL, " ")); + num[2] = atof(strtok(NULL, " ")); + //sscanf(yytext, "%f %f %f", &num[0], &num[1], &num[2]); + yylval.vec3f->InsertNextPoint(num); + //return MFVEC3F; + } + else { + BEGIN NODE; expectToken = 0; + return MFVEC3F; + } + } + YY_BREAK + case 31: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; return SFROTATION; } + case 32: + YY_USER_ACTION + { if (parsing_mf) ; /* .. add to array... */ + else { + BEGIN NODE; expectToken = 0; return MFROTATION; + } + } + YY_BREAK + case 33: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; + float num[3]; + yylval.vec3f = self->PointsNew(); + num[0] = atof(strtok(yytext, " ")); + num[1] = atof(strtok(NULL, " ")); + num[2] = atof(strtok(NULL, " ")); + //sscanf(yytext, "%f %f %f", &num[0], &num[1], &num[2]); + yylval.vec3f->InsertPoint(0, num); + return SFCOLOR; } + case 34: + YY_USER_ACTION + { if (parsing_mf) { /* .. add to array... */ + float num[3]; + num[0] = atof(strtok(yytext, " ")); + num[1] = atof(strtok(NULL, " ")); + num[2] = atof(strtok(NULL, " ")); + yylval.vec3f->InsertNextPoint(num); + } + else { + BEGIN NODE; expectToken = 0; return MFCOLOR; + } + } + YY_BREAK + case 35: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; return SFTIME; } + /* SFString/MFString */ + case 36: + YY_USER_ACTION + { BEGIN IN_SFS; } + YY_BREAK + case 37: + YY_USER_ACTION + { BEGIN IN_MFS; } + YY_BREAK + /* Anything besides open-quote (or whitespace) is an error: */ + case 38: + YY_USER_ACTION + { yyerror("String missing open-quote"); + BEGIN NODE; expectToken = 0; return SFSTRING; + } + /* Expect open-quote, open-bracket, or whitespace: */ + case 39: + YY_USER_ACTION + { yyerror("String missing open-quote"); + BEGIN NODE; expectToken = 0; return MFSTRING; + } + /* Backslashed-quotes are OK: */ + case 40: + YY_USER_ACTION + ; + YY_BREAK + /* Gobble up anything besides quotes and newlines. */ + /* Newlines are legal in strings, but we exclude them here so */ + /* that line number are counted correctly by the catch-all newline */ + /* rule that applies to everything. */ + case 41: + YY_USER_ACTION + ; + YY_BREAK + /* Quote ends the string: */ + case 42: + YY_USER_ACTION + { BEGIN NODE; expectToken = 0; return SFSTRING; } + case 43: + YY_USER_ACTION + { if (parsing_mf) BEGIN MFS; /* ... add to array ... */ + else { + BEGIN NODE; expectToken = 0; return MFSTRING; + } + } + YY_BREAK + /* SFImage: width height numComponents then width*height integers: */ + case 44: + YY_USER_ACTION + { int w, h; + sscanf(yytext, "%d %d", &w, &h); + sfImageIntsExpected = 1+w*h; + sfImageIntsParsed = 0; + BEGIN IN_SFIMG; + } + YY_BREAK + case 45: + YY_USER_ACTION + { ++sfImageIntsParsed; + if (sfImageIntsParsed == sfImageIntsExpected) { + BEGIN NODE; expectToken = 0; return SFIMAGE; + } + } + YY_BREAK + /* Whitespace and catch-all rules apply to all start states: */ + case 46: + YY_USER_ACTION + ; + YY_BREAK + /* This is also whitespace, but we'll keep track of line number */ + /* to report in errors: */ + case 47: + YY_USER_ACTION + { ++currentLineNumber; } + YY_BREAK + /* This catch-all rule catches anything not covered by any of */ + /* the above: */ + case 48: + YY_USER_ACTION + { return yytext[0]; } + case 49: + YY_USER_ACTION + YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + case YY_STATE_EOF(INITIAL): + case YY_STATE_EOF(NODE): + case YY_STATE_EOF(SFB): + case YY_STATE_EOF(SFC): + case YY_STATE_EOF(SFF): + case YY_STATE_EOF(SFIMG): + case YY_STATE_EOF(SFI): + case YY_STATE_EOF(SFR): + case YY_STATE_EOF(SFS): + case YY_STATE_EOF(SFT): + case YY_STATE_EOF(SFV2): + case YY_STATE_EOF(SFV3): + case YY_STATE_EOF(MFC): + case YY_STATE_EOF(MFF): + case YY_STATE_EOF(MFI): + case YY_STATE_EOF(MFR): + case YY_STATE_EOF(MFS): + case YY_STATE_EOF(MFV2): + case YY_STATE_EOF(MFV3): + case YY_STATE_EOF(IN_SFS): + case YY_STATE_EOF(IN_MFS): + case YY_STATE_EOF(IN_SFIMG): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = yy_cp - yytext_ptr - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + 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 */ + + +/* 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 + */ + +static int yy_get_next_buffer() +{ + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr - 1; /* copy prev. char, too */ + 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 singled characater, 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 = yy_c_buf_p - yytext_ptr; + + 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_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 = yy_c_buf_p - b->yy_ch_buf; + + b->yy_buf_size *= 2; + b->yy_ch_buf = (char *) + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size ); + + 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 ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move - YY_MORE_ADJ == 1 ) + { + 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 begins at the second character in yy_ch_buf; the first + * character is the one which preceded it before reading in the latest + * buffer; it needs to be kept around in case it's a newline, so + * yy_get_previous_state() will have with '^' rules active. + */ + + yytext_ptr = &yy_current_buffer->yy_ch_buf[1]; + + return ret_val; +} + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type 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 >= 949 ) + 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 ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else + static yy_state_type yy_try_NUL_trans( yy_current_state ) + yy_state_type yy_current_state; +#endif +{ + 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 >= 949 ) + 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 == 948); + + return yy_is_jam ? 0 : yy_current_state; +} + + + +#ifdef __cplusplus +static int yyinput() +#else + static int input() +#endif +{ + 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 */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + 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; +} + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else + void yyrestart( input_file ) + FILE *input_file; +#endif +{ + 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(); +} + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else + void yy_switch_to_buffer( new_buffer ) + YY_BUFFER_STATE new_buffer; +#endif +{ + 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; +} + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else + void yy_load_buffer_state() +#endif +{ + 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; +} + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else + YY_BUFFER_STATE yy_create_buffer( file, size ) + FILE *file; +int size; +#endif +{ + 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()" ); + + yy_init_buffer( b, file ); + + return b; +} + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else + void yy_delete_buffer( b ) + YY_BUFFER_STATE b; +#endif +{ + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + yy_flex_free( (void *) b->yy_ch_buf ); + yy_flex_free( (void *) b ); +} + + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else + void yy_init_buffer( b, file ) + YY_BUFFER_STATE b; +FILE *file; +#endif +{ + b->yy_input_file = file; + + /* We put in the '\n' and start reading from [1] so that an + * initial match-at-newline will be true. + */ + + b->yy_ch_buf[0] = '\n'; + b->yy_n_chars = 1; + + /* 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[1] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[2] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[1]; + + b->yy_is_interactive = file ? isatty( fileno(file) ) : 0; + + b->yy_fill_buffer = 1; + + b->yy_buffer_status = YY_BUFFER_NEW; +} + + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( const char msg[] ) +#else + static void yy_fatal_error( msg ) + char msg[]; +#endif +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( 1 ); +} + + + +/* 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_MORE_ADJ; \ + 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, const char *s2, int n ) +#else + static void yy_flex_strncpy( s1, s2, n ) + char *s1; +const char *s2; +int n; +#endif +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( unsigned int size ) +#else + static void *yy_flex_alloc( size ) + unsigned int size; +#endif +{ + return (void *) malloc( size ); +} + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, unsigned int size ) +#else + static void *yy_flex_realloc( ptr, size ) + void *ptr; +unsigned int size; +#endif +{ + return (void *) realloc( 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 ); +} +// End of Auto-generated Lexer Code + + +vtkVRMLImporter::vtkVRMLImporter () +{ + this->Internal = new vtkVRMLImporterInternal; + this->CurrentActor = NULL; + this->CurrentLight = NULL; + this->CurrentProperty = NULL; + this->CurrentCamera = NULL; + this->CurrentSource = NULL; + this->CurrentPoints = NULL; + this->CurrentScalars = NULL; + this->CurrentNormals = NULL; + this->CurrentTCoords = NULL; + this->CurrentTCoordCells = NULL; + this->CurrentMapper = NULL; + this->CurrentLut = NULL; + this->CurrentTransform = vtkTransform::New(); + this->FileName = NULL; + this->FileFD = NULL; +} + +// Open an import file. Returns zero if error. +int vtkVRMLImporter::OpenImportFile () +{ + vtkDebugMacro(<< "Opening import file"); + + if ( !this->FileName ) + { + vtkErrorMacro(<< "No file specified!"); + return 0; + } + this->FileFD = fopen (this->FileName, "r"); + if (this->FileFD == NULL) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + return 0; + } + return 1; +} + +int vtkVRMLImporter::ImportBegin () +{ + + memyyInput_i = 0; + memyyInput_j = 0; + + vtkVRMLAllocator::Initialize(); + VrmlNodeType::typeList = new vtkVRMLVectorType; + VrmlNodeType::typeList->Init(); + + VrmlNodeType::useList = new vtkVRMLVectorType; + VrmlNodeType::useList->Init(); + + VrmlNodeType::currentField = new vtkVRMLVectorType; + VrmlNodeType::currentField->Init(); + + if (!this->OpenImportFile()) + { + return 0; + } + + // This is acrually where it all takes place, Since VRML is a SG + // And is state based, I need to create actors, cameras, and lights + // as I go. The ImportXXXXXX rotuines are not used. + CurrentProtoStack = new vtkVRMLVectorType; + + // Lets redefine the YY_INPUT macro on Flex and get chars from memory + theyyInput = memyyInput; + // Crank up the yacc parser... + yydebug = 0; + yy_flex_debug = 0; + /*FILE *standardNodes = fopen("standardNodes.wrl", "r"); + if (standardNodes == NULL) { + cerr << "Error, couldn't open standardNodes.wrl file"; + return 0; + } + yyin = standardNodes;*/ + yyparse(this); + yyin = NULL; + yyResetLineNumber(); + //fclose(standardNodes); + + // Not sure why I have to do this but its not working when + // When I use the FileFD file pointer... + // File existance already checked. + yyin = fopen(this->FileName, "r"); + + // reset the lex input routine + theyyInput = defyyInput; + + // For this little test application, pushing and popping the node + // namespace isn't really necessary. But each VRML .wrl file is + // a separate namespace for PROTOs (except for things predefined + // in the spec), and pushing/popping the namespace when reading each + // file is a good habit to get into: + VrmlNodeType::pushNameSpace(); + yyparse(this); + VrmlNodeType::popNameSpace(); + + fclose(yyin); + yyin = NULL; + + delete CurrentProtoStack; + + // In case there was a ViewPoint introduced it usually happens prior + // to any actors being placed in the scene, need to reset the camera + //this->Renderer->UpdateActors(); + return 1; +} + +void vtkVRMLImporter::ImportEnd () +{ + delete VrmlNodeType::typeList; + VrmlNodeType::typeList = 0; + + delete VrmlNodeType::currentField; + VrmlNodeType::currentField = 0; + + vtkDebugMacro(<<"Closing import file"); + if ( this->FileFD != NULL ) + { + fclose (this->FileFD); + } + this->FileFD = NULL; +} + + +vtkVRMLImporter::~vtkVRMLImporter() +{ + if (this->CurrentActor) + { + this->CurrentActor->Delete(); + } + if (this->CurrentLight) + { + this->CurrentLight->Delete(); + } + if (this->CurrentProperty) + { + this->CurrentProperty->Delete(); + } + if (this->CurrentCamera) + { + this->CurrentCamera->Delete(); + } + if (this->CurrentSource) + { + this->CurrentSource->Delete(); + } + if (this->CurrentPoints) + { + this->CurrentPoints->Delete(); + } + if (this->CurrentNormals) + { + this->CurrentNormals->Delete(); + } + if (this->CurrentTCoords) + { + this->CurrentTCoords->Delete(); + } + if (this->CurrentTCoordCells) + { + this->CurrentTCoordCells->Delete(); + } + if (this->CurrentScalars) + { + this->CurrentScalars->Delete(); + } + if (this->CurrentMapper) + { + this->CurrentMapper->Delete(); + } + if (this->CurrentLut) + { + this->CurrentLut->Delete(); + } + this->CurrentTransform->Delete(); + if (this->FileName) + { + delete [] this->FileName; + } + while(this->Internal->Heap.Count() > 0) + { + vtkObject* obj = this->Internal->Heap.Pop(); + if (obj) + { + obj->Delete(); + } + } + delete this->Internal; + + // According to Tom Citriniti the useList must not be deleted until the + // instance is destroyed. The importer was crashing when users asked for a + // DEF node from within the VRML file. This DEF mechanism allows you to + // name a node inside the VRML file and refer to it from other nodes or + // from scripts that can be associated with the VRML file. A vector of + // these is created in the importer and has to live until the class is + // deleted. + delete VrmlNodeType::useList; + VrmlNodeType::useList = 0; + vtkVRMLAllocator::CleanUp(); +} + +void vtkVRMLImporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + os << "Defined names in File:" << endl; + if (VrmlNodeType::useList) + { + for (int i = 0;i < VrmlNodeType::useList->Count();i++) + { + os << "\tName: " << (*VrmlNodeType::useList)[i]->defName + << " is a " << (*VrmlNodeType::useList)[i]->defObject->GetClassName() + << endl; + } + } +} + +// Yacc/lex routines to add stuff to the renderer. + +void +vtkVRMLImporter::enterNode(const char *nodeType) +{ + vtkActor *actor; + vtkPolyDataMapper *pmap; + + const VrmlNodeType *t = VrmlNodeType::find(nodeType); + if (t == NULL) + { + char tmp[1000]; + sprintf(tmp, "Unknown node type '%s'", nodeType); + yyerror(tmp); + exit(99); + } + VrmlNodeType::FieldRec *fr = new VrmlNodeType::FieldRec; + fr->nodeType = t; + fr->fieldName = NULL; + *VrmlNodeType::currentField += fr; + if (strcmp(fr->nodeType->getName(), "Appearance") == 0) + { + if (this->CurrentProperty) + { + this->CurrentProperty->Delete(); + } + this->CurrentProperty = vtkProperty::New(); + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, + this->CurrentProperty); + creatingDEF = 0; + } + } + else if (strcmp(fr->nodeType->getName(), "Box") == 0) + { + pmap = vtkPolyDataMapper::New(); + vtkCubeSource *cube= vtkCubeSource::New(); + pmap->SetInput(cube->GetOutput()); + this->CurrentActor->SetMapper(pmap); + pmap->Delete(); + if (this->CurrentProperty) + { + this->CurrentActor->SetProperty(this->CurrentProperty); + } + if (this->CurrentSource) + { + this->CurrentSource->Delete(); + } + this->CurrentSource = cube; + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, pmap); + creatingDEF = 0; + } + } + else if (strcmp(fr->nodeType->getName(), "Cone") == 0) + { + pmap = vtkPolyDataMapper::New(); + vtkConeSource *cone= vtkConeSource::New(); + cone->SetResolution(12); + pmap->SetInput(cone->GetOutput()); + this->CurrentActor->SetMapper(pmap); + pmap->Delete(); + if (this->CurrentProperty) + { + this->CurrentActor->SetProperty(this->CurrentProperty); + } + if (this->CurrentSource) + { + this->CurrentSource->Delete(); + } + this->CurrentSource = cone; + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, pmap); + creatingDEF = 0; + } + } + else if (strcmp(fr->nodeType->getName(), "Cylinder") == 0) + { + pmap = vtkPolyDataMapper::New(); + vtkCylinderSource *cyl= vtkCylinderSource::New(); + cyl->SetResolution(12); + pmap->SetInput(cyl->GetOutput()); + this->CurrentActor->SetMapper(pmap); + pmap->Delete(); + if (this->CurrentProperty) + { + this->CurrentActor->SetProperty(this->CurrentProperty); + } + if (this->CurrentSource) + { + this->CurrentSource->Delete(); + } + this->CurrentSource = cyl; + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, pmap); + creatingDEF = 0; + + } + } + else if (strcmp(fr->nodeType->getName(), "DirectionalLight") == 0) + { + if (this->CurrentLight) + { + this->CurrentLight->Delete(); + } + this->CurrentLight = vtkLight::New(); + this->Renderer->AddLight(this->CurrentLight); + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, + this->CurrentLight); + creatingDEF = 0; + } + } + else if (strcmp(fr->nodeType->getName(), "IndexedFaceSet") == 0 || + strcmp(fr->nodeType->getName(), "IndexedLineSet") == 0 || + strcmp(fr->nodeType->getName(), "PointSet") == 0) + { + pmap = vtkPolyDataMapper::New(); + pmap->SetScalarVisibility(0); + this->CurrentActor->SetMapper(pmap); + if (this->CurrentProperty) + { + this->CurrentActor->SetProperty(this->CurrentProperty); + } + if (this->CurrentMapper) + { + this->CurrentMapper->Delete(); + } + this->CurrentMapper = pmap; + if (this->CurrentScalars) + { + this->CurrentScalars->Delete(); + } + this->CurrentScalars = vtkFloatArray::New(); + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, pmap); + creatingDEF = 0; + } + } + else if (strcmp(fr->nodeType->getName(), "Shape") == 0) + { + actor = vtkActor::New(); + if (this->CurrentProperty) + { + actor->SetProperty(this->CurrentProperty); + } + actor->SetOrientation(this->CurrentTransform->GetOrientation()); + actor->SetPosition(this->CurrentTransform->GetPosition()); + actor->SetScale(this->CurrentTransform->GetScale()); + if (this->CurrentActor) + { + this->CurrentActor->Delete(); + } + this->CurrentActor = actor; + // Add actor to renderer + this->Renderer->AddActor(actor); + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, actor); + creatingDEF= 0; + } + } + else if (strcmp(fr->nodeType->getName(), "Sphere") == 0) + { + pmap = vtkPolyDataMapper::New(); + vtkSphereSource *sphere = vtkSphereSource::New(); + pmap->SetInput(sphere->GetOutput()); + if (this->CurrentSource) + { + this->CurrentSource->Delete(); + } + this->CurrentSource = sphere; + this->CurrentActor->SetMapper(pmap); + pmap->Delete(); + if (this->CurrentProperty) + { + this->CurrentActor->SetProperty(this->CurrentProperty); + } + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, pmap); + creatingDEF= 0; + } + } + else if (strcmp(fr->nodeType->getName(), "Transform") == 0) + { + this->CurrentTransform->Push(); + } +} + +void +vtkVRMLImporter::exitNode() +{ + VrmlNodeType::FieldRec *fr = VrmlNodeType::currentField->Top(); + assert(fr != NULL); + VrmlNodeType::currentField->Pop(); + + // Exiting this means we need to setup the color mode and + // normals and other fun stuff. + if (strcmp(fr->nodeType->getName(), "IndexedFaceSet") == 0 || + strcmp(fr->nodeType->getName(), "IndexedLineSet") == 0 || + strcmp(fr->nodeType->getName(), "PointSet") == 0) + { + // if tcoords exactly correspond with vertices (or there aren't any) + // then can map straight through as usual + // if not then must rejig using face-correspondence + // (VRML supports per-face tcoords) + // a similar scheme is implemented in vtkOBJReader + + int tcoords_correspond; // (boolean) + if (this->CurrentTCoords==NULL || this->CurrentTCoordCells==NULL) + tcoords_correspond=1; // there aren't any, can proceed + else if (this->CurrentTCoords->GetNumberOfTuples()!=this->CurrentPoints->GetNumberOfPoints()) + tcoords_correspond=0; // false, must rejig + else + { + // the number of polygon faces and texture faces must be equal. + // if they are not then something is wrong + if (this->CurrentTCoordCells->GetNumberOfCells() != + this->CurrentMapper->GetInput()->GetPolys()->GetNumberOfCells()) + { + vtkErrorMacro(<<"Number of faces does not match texture faces, output may not be correct") + tcoords_correspond=1; // don't rejig + } + else + { + // count of tcoords and points is the same, must run through indices to see if they + // correspond by index point-for-point + tcoords_correspond=1; // assume true until found otherwise + vtkIdType DUMMY_WARNING_PREVENTION_MECHANISM; + vtkIdType n_pts=-1,*pts = &DUMMY_WARNING_PREVENTION_MECHANISM; + vtkIdType n_tcoord_pts=-1,*tcoord_pts = &DUMMY_WARNING_PREVENTION_MECHANISM; + this->CurrentMapper->GetInput()->GetPolys()->InitTraversal(); + this->CurrentTCoordCells->InitTraversal(); + int i,j; + for (i=0;iCurrentTCoordCells->GetNumberOfCells();i++) + { + this->CurrentMapper->GetInput()->GetPolys()->GetNextCell(n_pts,pts); + this->CurrentTCoordCells->GetNextCell(n_tcoord_pts,tcoord_pts); + if (n_pts!=n_tcoord_pts) + { + vtkErrorMacro(<<"Face size differs to texture face size, output may not be correct") + break; + } + for (j=0;jCurrentMapper->GetInput())->SetPoints(this->CurrentPoints); + // We always create a scalar object in the enternode method. + ((vtkPolyData *)this->CurrentMapper->GetInput())->GetPointData()->SetScalars(CurrentScalars); + if (this->CurrentNormals) + { + ((vtkPolyData *)this->CurrentMapper->GetInput())->GetPointData()->SetNormals(CurrentNormals); + this->CurrentNormals->Delete(); + this->CurrentNormals = NULL; + } + if (this->CurrentTCoords) + { + ((vtkPolyData *)this->CurrentMapper->GetInput())->GetPointData()->SetTCoords(CurrentTCoords); + this->CurrentTCoords->Delete(); + this->CurrentTCoords = NULL; + } + } + else // must rejig + { + + vtkDebugMacro(<<"Duplicating vertices so that tcoords and normals are correct"); + + vtkPoints *new_points = vtkPoints::New(); + vtkFloatArray *new_scalars = vtkFloatArray::New(); + if (this->CurrentScalars) + new_scalars->SetNumberOfComponents(this->CurrentScalars->GetNumberOfComponents()); + vtkFloatArray *new_tcoords = vtkFloatArray::New(); + new_tcoords->SetNumberOfComponents(2); + vtkFloatArray *new_normals = vtkFloatArray::New(); + new_normals->SetNumberOfComponents(3); + vtkCellArray *new_polys = vtkCellArray::New(); + + // for each poly, copy its vertices into new_points (and point at them) + // also copy its tcoords into new_tcoords + // also copy its normals into new_normals + // also copy its scalar into new_scalars + this->CurrentMapper->GetInput()->GetPolys()->InitTraversal(); + this->CurrentTCoordCells->InitTraversal(); + int i,j; + vtkIdType DUMMY_WARNING_PREVENTION_MECHANISM; + vtkIdType n_pts=-1,*pts = &DUMMY_WARNING_PREVENTION_MECHANISM; + vtkIdType n_tcoord_pts=-1,*tcoord_pts = &DUMMY_WARNING_PREVENTION_MECHANISM; + for (i=0;iCurrentMapper->GetInput()->GetPolys()->GetNumberOfCells();i++) + { + + this->CurrentMapper->GetInput()->GetPolys()->GetNextCell(n_pts,pts); + this->CurrentTCoordCells->GetNextCell(n_tcoord_pts,tcoord_pts); + + // If some vertices have tcoords and not others + // then we must do something else VTK will complain. (crash on render attempt) + // Easiest solution is to delete polys that don't have complete tcoords (if there + // are any tcoords in the dataset) + + if (n_pts!=n_tcoord_pts && this->CurrentTCoords->GetNumberOfTuples()>0) + { + // skip this poly + vtkDebugMacro(<<"Skipping poly "<CurrentTCoords && n_tcoord_pts>0) + new_tcoords->InsertNextTuple(this->CurrentTCoords->GetTuple(tcoord_pts[j])); + // copy the normal for this point across (if any) + if (this->CurrentNormals) + new_normals->InsertNextTuple(this->CurrentNormals->GetTuple(pts[j])); + // copy the scalar for this point across + if (this->CurrentScalars) + new_scalars->InsertNextTuple(this->CurrentScalars->GetTuple(pts[j])); + // copy the vertex into the new structure and update + // the vertex index in the polys structure (pts is a pointer into it) + pts[j] = new_points->InsertNextPoint(this->CurrentPoints->GetPoint(pts[j])); + } + // copy this poly (pointing at the new points) into the new polys list + new_polys->InsertNextCell(n_pts,pts); + } + } + + // use the new structures for the output + this->CurrentMapper->GetInput()->SetPoints(new_points); + this->CurrentMapper->GetInput()->SetPolys(new_polys); + if (this->CurrentTCoords) + this->CurrentMapper->GetInput()->GetPointData()->SetTCoords(new_tcoords); + if (this->CurrentNormals) + this->CurrentMapper->GetInput()->GetPointData()->SetNormals(new_normals); + if (this->CurrentScalars) + this->CurrentMapper->GetInput()->GetPointData()->SetScalars(new_scalars); + this->CurrentMapper->GetInput()->Squeeze(); + + new_points->Delete(); + new_polys->Delete(); + new_tcoords->Delete(); + new_normals->Delete(); + new_scalars->Delete(); + } + + if (this->CurrentLut) + { + this->CurrentScalars->InsertNextValue(this->CurrentLut->GetNumberOfColors()); + this->CurrentMapper->SetLookupTable(CurrentLut); + this->CurrentMapper->SetScalarVisibility(1); + // Set for PerVertex Coloring. + this->CurrentLut->SetTableRange(0.0, + float(this->CurrentLut->GetNumberOfColors() - 1)); + this->CurrentLut->Delete(); + this->CurrentLut = NULL; + } + } + else if (strcmp(fr->nodeType->getName(), "Shape") == 0) + { + if (this->CurrentProperty) + this->CurrentActor->SetProperty(this->CurrentProperty); + } + // simply pop the current transform + else if (strcmp(fr->nodeType->getName(), "Transform") == 0) + { + this->CurrentTransform->Pop(); + } + + delete fr; +} + + + +void +vtkVRMLImporter::enterField(const char *fieldName) +{ + VrmlNodeType::FieldRec *fr = VrmlNodeType::currentField->Top(); + assert(fr != NULL); + + fr->fieldName = fieldName; + if (fr->nodeType != NULL) + { + // enterField is called when parsing eventIn and eventOut IS + // declarations, in which case we don't need to do anything special-- + // the IS IDENTIFIER will be returned from the lexer normally. + if (fr->nodeType->hasEventIn(fieldName) || + fr->nodeType->hasEventOut(fieldName)) + return; + + int type = fr->nodeType->hasField(fieldName); + if (type != 0) + { + // Let the lexer know what field type to expect: + expect(type); + } + else + { + cerr << "Error: Node's of type " << fr->nodeType->getName() << + " do not have fields/eventIn/eventOut named " << + fieldName << "\n"; + // expect(ANY_FIELD); + } + } + // else expect(ANY_FIELD); +} + +void +vtkVRMLImporter::exitField() +{ + VrmlNodeType::FieldRec *fr = VrmlNodeType::currentField->Top(); + assert(fr != NULL); + // For the radius field + if (strcmp(fr->fieldName, "radius") == 0) + { + // Set the Sphere radius + if (strcmp(fr->nodeType->getName(), "Sphere") == 0) + { + ((vtkSphereSource *)(this->CurrentSource))->SetRadius(yylval.sffloat); + } + // Set the Cylinder radius + if (strcmp(fr->nodeType->getName(), "Cylinder") == 0) + { + ((vtkCylinderSource *)this->CurrentSource)->SetRadius(yylval.sffloat); + } + } + // for the ambientIntensity field + else if (strcmp(fr->fieldName, "ambientIntensity") == 0) + { + // Add to the current light + if (strcmp(fr->nodeType->getName(), "DirectionalLight") == 0) + { + this->CurrentLight->SetIntensity(yylval.sffloat); + } + // or the current material + else if (strcmp(fr->nodeType->getName(), "Material") == 0) + { + this->CurrentProperty->SetAmbient(yylval.sffloat); + } + } + // For diffuseColor field, only in material node + else if (strcmp(fr->fieldName, "diffuseColor") == 0) + { + this->CurrentProperty->SetDiffuseColor( + yylval.vec3f->GetPoint(0)[0],yylval.vec3f->GetPoint(0)[1], + yylval.vec3f->GetPoint(0)[2]); + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + yylval.vec3f = NULL; + } + // For emissiveColor field, only in material node + else if (strcmp(fr->fieldName, "emissiveColor") == 0) + { + this->CurrentProperty->SetAmbientColor( + yylval.vec3f->GetPoint(0)[0],yylval.vec3f->GetPoint(0)[1], + yylval.vec3f->GetPoint(0)[2]); + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f);yylval.vec3f = NULL; + } + // For shininess field, only in material node + else if (strcmp(fr->fieldName, "shininess") == 0) + { + this->CurrentProperty->SetSpecularPower(yylval.sffloat); + } + // For specularcolor field, only in material node + else if (strcmp(fr->fieldName, "specularColor") == 0) + { + this->CurrentProperty->SetSpecularColor( + yylval.vec3f->GetPoint(0)[0],yylval.vec3f->GetPoint(0)[1], + yylval.vec3f->GetPoint(0)[2]); + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f);yylval.vec3f = NULL; + } + // For transparency field, only in material node + else if (strcmp(fr->fieldName, "transparency") == 0) + { + this->CurrentProperty->SetOpacity(1.0 - yylval.sffloat); + } + // For the translation field + else if (strcmp(fr->fieldName, "translation") == 0) + { + // in the Transform node. + if (strcmp(fr->nodeType->getName(), "Transform") == 0) + { + double *dtmp = yylval.vec3f->GetPoint(0); + this->CurrentTransform->Translate(dtmp[0],dtmp[1],dtmp[2]); + yylval.vec3f->Reset(); + this->DeleteObject(yylval.vec3f); yylval.vec3f = NULL; + } + } + // For the scale field + else if (strcmp(fr->fieldName, "scale") == 0) + { + // In the transform node + if (strcmp(fr->nodeType->getName(), "Transform") == 0) + { + double *dtmp = yylval.vec3f->GetPoint(0); + this->CurrentTransform->Scale(dtmp[0],dtmp[1],dtmp[2]); + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + yylval.vec3f = NULL; + } + } + // For the size field + else if (strcmp(fr->fieldName, "size") == 0) + { + // set the current source (has to be a CubeSource) + if (strcmp(fr->nodeType->getName(), "Box") == 0) + { + double *dtmp = yylval.vec3f->GetPoint(0); + ((vtkCubeSource *)this->CurrentSource)->SetXLength(dtmp[0]); + ((vtkCubeSource *)this->CurrentSource)->SetYLength(dtmp[1]); + ((vtkCubeSource *)this->CurrentSource)->SetZLength(dtmp[2]); + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + yylval.vec3f = NULL; + } + } + // For the height field + else if (strcmp(fr->fieldName, "height") == 0) + { + // Set the current Cone height + if (strcmp(fr->nodeType->getName(), "Cone") == 0) + { + ((vtkConeSource *)this->CurrentSource)->SetHeight(yylval.sffloat); + } + // or set the current Cylinder height + if (strcmp(fr->nodeType->getName(), "Cylinder") == 0) + { + ((vtkCylinderSource *)this->CurrentSource)->SetHeight(yylval.sffloat); + } + } + // For the bottomRadius field (Only in the Cone object) + else if (strcmp(fr->fieldName, "bottomRadius") == 0) + { + if (strcmp(fr->nodeType->getName(), "Cone") == 0) + { + ((vtkConeSource *)this->CurrentSource)->SetRadius(yylval.sffloat); + } + } + // else if (strcmp(fr->fieldName, "position") == 0) { + // yylval.vec3f->GetPoint(0, vals); + // vtkCamera *acam = vtkCamera::New(); + // acam->SetPosition(vals); + // this->Renderer->SetActiveCamera(acam); + // yylval.vec3f->Delete();yylval.vec3f = NULL; + // } + // Handle coordIndex for Indexed????Sets + else if (strcmp(fr->fieldName, "coordIndex") == 0) + { + vtkCellArray *cells; + int index, i, cnt; + vtkPolyData *pd; + + pd = vtkPolyData::New(); + cells = vtkCellArray::New(); + index = i = cnt = 0; + for (i = 0;i <= yylval.mfint32->GetMaxId();i++) + { + if (yylval.mfint32->GetValue(i) == -1) + { + cells->InsertNextCell(cnt, + (vtkIdType*)yylval.mfint32->GetPointer(index)); + index = i+1; + cnt = 0; + } + else + { + cnt++; + } + } + if (strcmp(fr->nodeType->getName(), "IndexedFaceSet") == 0) + { + pd->SetPolys(cells); + } + else + { + pd->SetLines(cells); + } + + this->CurrentMapper->SetInput(pd); + pd->Delete(); + cells->Delete(); + yylval.mfint32->Reset();this->DeleteObject(yylval.mfint32); + } + // Handle point field + else if (strcmp(fr->fieldName, "point") == 0) + { + // If for a coordinate node, simply used created FloatPoints + if (strcmp(fr->nodeType->getName(), "Coordinate") == 0) + { + if (this->CurrentPoints) + { + this->CurrentPoints->Delete(); + } + this->CurrentPoints = yylval.vec3f; + // Seed the scalars with default values. + this->CurrentScalars->Reset(); + for (int i=0;i < this->CurrentPoints->GetNumberOfPoints();i++) + { + this->CurrentScalars->InsertNextValue(i); + } + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, this->CurrentPoints); + creatingDEF = 0; + } + } + else if (strcmp(fr->nodeType->getName(), "TextureCoordinate") == 0) // TJH + { + if(this->CurrentTCoords) + { + this->CurrentTCoords->Delete(); + } + this->CurrentTCoords = yylval.vec2f; + this->CurrentTCoords->Register(this); + } + } + // Handle coord field, simply set the CurrentPoints + else if (strcmp(fr->fieldName, "coord") == 0) + { + this->CurrentPoints = yylval.vec3f; + this->CurrentPoints->Register(this); + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, this->CurrentPoints); + creatingDEF = 0; + } + + // There is no coordIndex for PointSet data, generate the PolyData here. + if (strcmp(fr->nodeType->getName(), "PointSet") == 0) + { + vtkCellArray *cells; + vtkIdType i; + vtkPolyData *pd; + + pd = vtkPolyData::New(); + cells = vtkCellArray::New(); + for (i=0;i < yylval.vec3f->GetNumberOfPoints();i++) + { + cells->InsertNextCell(1, &i); + } + + pd->SetVerts(cells); + + this->CurrentMapper->SetInput(pd); + pd->Delete(); + cells->Delete(); + } + } + // Handle color field + else if (strcmp(fr->fieldName, "color") == 0) + { + // For the Light nodes + if (strcmp(fr->nodeType->getName(), "DirectionalLight") == 0) + { + this->CurrentLight->SetColor( + yylval.vec3f->GetPoint(0)[0],yylval.vec3f->GetPoint(0)[1], + yylval.vec3f->GetPoint(0)[2]); + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + yylval.vec3f = NULL; + } + // For the Color node, Insert colors into lookup table + // These are associated with the points in the coord field + // and also in the colorIndex field + if (strcmp(fr->nodeType->getName(), "Color") == 0) + { + double vals4[4]; + vals4[3] = 1.0; + vtkLookupTable *lut = vtkLookupTable::New(); + lut->SetNumberOfColors(yylval.vec3f->GetNumberOfPoints()); + lut->Build(); + for (int i=0;i < yylval.vec3f->GetNumberOfPoints();i++) + { + yylval.vec3f->GetPoint(i, vals4); + lut->SetTableValue(i, vals4); + } + if (this->CurrentLut) + { + this->CurrentLut->Delete(); + } + this->CurrentLut = lut; + if (creatingDEF) + { + *VrmlNodeType::useList += new vtkVRMLUseStruct(curDEFName, this->CurrentLut); + creatingDEF = 0; + } + } + } + // Handle colorIndex field, always for a Indexed????Set + else if (strcmp(fr->fieldName, "colorIndex") == 0) + { + vtkCellArray *cells; + int index, j; + vtkIdType *pts=0; + vtkIdType npts; + vtkPolyData *pd = (vtkPolyData *)this->CurrentMapper->GetInput(); + if (pd->GetNumberOfPolys() > 0) + cells = pd->GetPolys(); + else + cells = pd->GetLines(); + cells->InitTraversal(); + index = 0;j = 0; + cells->GetNextCell(npts, pts); + for (int i=0;i <= yylval.mfint32->GetMaxId();i++) + { + if (yylval.mfint32->GetValue(index) == -1) + { + cells->GetNextCell(npts, pts); + // Pass by the -1 + index++; + j = 0; + } + else + { + // Redirect color into scalar position + this->CurrentScalars->SetComponent(pts[j++], 0, + yylval.mfint32->GetValue(index++)); + } + } + } + // Handle direction field + else if (strcmp(fr->fieldName, "direction") == 0) + { + // For Directional light. + if (strcmp(fr->nodeType->getName(), "DirectionalLight") == 0) { + this->CurrentLight->SetFocalPoint(yylval.vec3f->GetPoint(0)); + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f);yylval.vec3f = NULL; + } + // For + } + // Handle intensity field + else if (strcmp(fr->fieldName, "intensity") == 0) + { + // For Directional light. + if (strcmp(fr->nodeType->getName(), "DirectionalLight") == 0) + { + this->CurrentLight->SetIntensity(yylval.sffloat); + } + // For + } + // Handle on field + else if (strcmp(fr->fieldName, "on") == 0) + { + // For Directional light. + if (strcmp(fr->nodeType->getName(), "DirectionalLight") == 0) + { + this->CurrentLight->SetSwitch(yylval.sfint); + } + // For + } + // Handle colorPerVertex field + else if (strcmp(fr->fieldName, "colorPerVertex") == 0) + { + // Same for all geometry nodes. + this->CurrentMapper->SetScalarVisibility(yylval.sfint); + } + // Handle vector field for Normal Node + else if (strcmp(fr->fieldName, "vector") == 0) + { + // For all floats in the vec3f, copy to the normal structure. + if (this->CurrentNormals) + { + this->CurrentNormals->Delete(); + } + this->CurrentNormals = vtkFloatArray::New(); + this->CurrentNormals->SetNumberOfComponents(3); + this->CurrentNormals->SetNumberOfTuples(yylval.vec3f->GetNumberOfPoints()); + for (int i=0;i < yylval.vec3f->GetNumberOfPoints();i++) + { + this->CurrentNormals->InsertTuple(i, yylval.vec3f->GetPoint(i)); + } + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + } + else if (strcmp(fr->fieldName, "location") == 0) + { + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + } + else if (strcmp(fr->fieldName, "position") == 0) + { + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + } + else if (strcmp(fr->fieldName, "center") == 0) + { + yylval.vec3f->Reset();this->DeleteObject(yylval.vec3f); + } + else if (strcmp(fr->fieldName, "texCoordIndex") == 0) + { + if (this->CurrentTCoordCells) { + this->CurrentTCoordCells->Delete(); + } + this->CurrentTCoordCells = vtkCellArray::New(); + + // read the indices of the tcoords and assign accordingly + int index, i, cnt; + index = i = cnt = 0; + for (i = 0;i <= yylval.mfint32->GetMaxId();i++) + { + if (yylval.mfint32->GetValue(i) == -1) + { + this->CurrentTCoordCells->InsertNextCell(cnt, + (vtkIdType*)yylval.mfint32->GetPointer(index)); + index = i+1; + cnt = 0; + } + else + { + cnt++; + } + } + yylval.mfint32->Reset();this->DeleteObject(yylval.mfint32); + } + else + { + } + fr->fieldName = NULL; +} + +void +vtkVRMLImporter::useNode(const char *name) { + + vtkObject *useO; + if ((useO = this->GetVRMLDEFObject(name))) + { + if (strstr(useO->GetClassName(), "Actor")) + { + vtkActor *_act = vtkActor::New(); + _act->ShallowCopy((vtkActor *)useO); + if (this->CurrentProperty) + _act->SetProperty(this->CurrentProperty); + _act->SetOrientation(this->CurrentTransform->GetOrientation()); + _act->SetPosition(this->CurrentTransform->GetPosition()); + _act->SetScale(this->CurrentTransform->GetScale()); + if (this->CurrentActor) + { + this->CurrentActor->Delete(); + } + this->CurrentActor = _act; + this->Renderer->AddActor(_act); + } + else if (strstr(useO->GetClassName(), "PolyDataMapper")) + { + vtkActor *_act = vtkActor::New(); + _act->SetMapper((vtkPolyDataMapper *)useO); + if (this->CurrentProperty) + { + _act->SetProperty(this->CurrentProperty); + } + _act->SetOrientation(this->CurrentTransform->GetOrientation()); + _act->SetPosition(this->CurrentTransform->GetPosition()); + _act->SetScale(this->CurrentTransform->GetScale()); + if (this->CurrentActor) + { + this->CurrentActor->UnRegister(this); + } + this->CurrentActor = _act; + this->Renderer->AddActor(_act); + } + else if (strcmp(useO->GetClassName(), "vtkPoints") == 0) + { + yylval.vec3f = (vtkPoints *) useO; + if (this->CurrentPoints) + { + this->CurrentPoints->Delete(); + } + this->CurrentPoints = (vtkPoints *) useO; + } + else if (strcmp(useO->GetClassName(), "vtkLookupTable") == 0) + { + if (this->CurrentLut) + { + this->CurrentLut->Delete(); + } + this->CurrentLut = (vtkLookupTable *) useO; + // Seed the scalars with default values. + this->CurrentScalars->Reset(); + for (int i=0;i < this->CurrentPoints->GetNumberOfPoints();i++) + { + this->CurrentScalars->InsertNextValue(i); + } + } + } +} + + +// Send in the name from the VRML file, get the VTK object. +vtkObject * +vtkVRMLImporter::GetVRMLDEFObject(const char *name) +{ + // Look through the type stack: + // Need to go from top of stack since last DEF created is most current + for (int i = VrmlNodeType::useList->Count()-1;i >=0 ; i--) + { + const vtkVRMLUseStruct *nt = (*VrmlNodeType::useList)[i]; + if (nt != NULL && strcmp(nt->defName,name) == 0) + { + return nt->defObject; + } + } + return NULL; +} + + +// Used by the lex input to get characters. Needed to read in memory structure + +static void memyyInput(char *buf, int &result, int max_size) { + + result = static_cast( + strlen(strncpy(buf, standardNodes[memyyInput_i], max_size))); + memyyInput_j = result - static_cast( + strlen(standardNodes[memyyInput_i])); + if ( memyyInput_j == 0 ) + { + memyyInput_i++; + } +} + +// Needed to reset the lex input routine to default. +static void defyyInput(char *buf, int &result, int max_size) { + if ( yy_current_buffer->yy_is_interactive ) + { + int c = getc( yyin ); + result = c == EOF ? 0 : 1; + buf[0] = (char) c; + } + else if( ((result = static_cast(fread( buf, 1, max_size, yyin ))) == 0) + && ferror( yyin ) ) + { + YY_FATAL_ERROR( "input in flex scanner failed" ); + } +} + diff --git a/Hybrid/vtkVRMLImporter.h b/Hybrid/vtkVRMLImporter.h new file mode 100644 index 0000000..5d38d06 --- /dev/null +++ b/Hybrid/vtkVRMLImporter.h @@ -0,0 +1,166 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVRMLImporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVRMLImporter - imports VRML 2.0 files. +// .SECTION Description +// +// vtkVRMLImporter imports VRML 2.0 files into vtk. +// .SECTION Caveats +// +// These nodes are currently supported: +// Appearance IndexedFaceSet +// Box IndexedLineSet +// Color Material +// Cone Shape +// Coordinate Sphere +// Cylinder Transform +// DirectionalLight +// +// As you can see this implementation focuses on getting the geometry +// translated. The routes and scripting nodes are ignored since they deal +// with directly accessing a nodes internal structure based on the VRML +// spec. Since this is a translation the internal data structures differ +// greatly from the VRML spec and the External Authoring Interface (see the +// VRML spec). The DEF/USE mechanism does allow the Vtk user to extract +// objects from the scene and directly manipulate them using the native +// language (Tcl, Python, Java, or whatever language Vtk is wrapped +// in). This, in a way, removes the need for the route and script mechanism +// (not completely though). +// +// .SECTION See Also +// vtkImporter + +/* ====================================================================== + + Importer based on BNF Yacc and Lex parser definition from: + + ************************************************** + * VRML 2.0 Parser + * Copyright (C) 1996 Silicon Graphics, Inc. + * + * Author(s) : Gavin Bell + * Daniel Woods (first port) + ************************************************** + + Ported to VTK By: Thomas D. Citriniti + Rensselaer Polytechnic Institute + citrit@rpi.edu + +=======================================================================*/ + +#ifndef __vtkVRMLImporter_h +#define __vtkVRMLImporter_h + +// Includes for the yacc/lex parser +#include "vtkImporter.h" + +class vtkActor; +class vtkAlgorithm; +class vtkProperty; +class vtkCamera; +class vtkLight; +class vtkTransform; +class vtkLookupTable; +class vtkFloatArray; +class vtkPolyDataMapper; +class vtkPoints; +class vtkIdTypeArray; +class vtkVRMLImporterInternal; +class vtkCellArray; + +class VTK_HYBRID_EXPORT vtkVRMLImporter : public vtkImporter +{ +public: + static vtkVRMLImporter *New(); + + vtkTypeRevisionMacro(vtkVRMLImporter,vtkImporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // In the VRML spec you can DEF and USE nodes (name them), + // This routine will return the associated VTK object which + // was created as a result of the DEF mechanism + // Send in the name from the VRML file, get the VTK object. + // You will have to check and correctly cast the object since + // this only returns vtkObjects. + vtkObject *GetVRMLDEFObject(const char *name); + + // Description: + // Needed by the yacc/lex grammar used + void enterNode(const char *); + void exitNode(); + void enterField(const char *); + void exitField(); + void useNode(const char *); + + // Description: + // Specify the name of the file to read. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Return the file pointer to the open file. + FILE *GetFileFD() {return this->FileFD;}; + +//BTX + + friend int yylex ( vtkVRMLImporter* ); + +//ETX + +protected: + vtkVRMLImporter(); + ~vtkVRMLImporter(); + + virtual int ImportBegin (); + virtual void ImportEnd (); + virtual void ImportActors (vtkRenderer *) {}; + virtual void ImportCameras (vtkRenderer *) {}; + virtual void ImportLights (vtkRenderer *) {}; + virtual void ImportProperties (vtkRenderer *) {}; + + int OpenImportFile(); + char *FileName; + FILE *FileFD; + +private: + vtkActor *CurrentActor; + vtkProperty *CurrentProperty; + vtkCamera *CurrentCamera; + vtkLight *CurrentLight; + vtkTransform *CurrentTransform; + vtkAlgorithm *CurrentSource; + vtkPoints *CurrentPoints; + vtkFloatArray *CurrentNormals; + vtkFloatArray *CurrentTCoords; + vtkCellArray *CurrentTCoordCells; + vtkLookupTable *CurrentLut; + vtkFloatArray *CurrentScalars; + vtkPolyDataMapper *CurrentMapper; + + vtkPoints* PointsNew(); + vtkFloatArray* FloatArrayNew(); + vtkIdTypeArray* IdTypeArrayNew(); + + void DeleteObject(vtkObject*); + + vtkVRMLImporterInternal* Internal; + +private: + vtkVRMLImporter(const vtkVRMLImporter&); // Not implemented. + void operator=(const vtkVRMLImporter&); // Not implemented. +}; + +#endif + diff --git a/Hybrid/vtkVectorText.cxx b/Hybrid/vtkVectorText.cxx new file mode 100644 index 0000000..d82ebf1 --- /dev/null +++ b/Hybrid/vtkVectorText.cxx @@ -0,0 +1,1757 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVectorText.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVectorText.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataReader.h" +#include "vtkTransformPolyDataFilter.h" + +vtkCxxRevisionMacro(vtkVectorText, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkVectorText); + +char *VTK_VECTOR_TEXT_33 = (char *) "11 0.438482 " +"0.28000 -0.07186 0.43164 -0.07143 0.27689 0.07714 0.43472 0.07714 0.32000 0.20134 " +"0.40000 0.20243 0.31429 0.20550 0.27277 0.76857 0.43848 0.76857 0.27693 1.02571 " +"0.43429 1.02615 7 2 1 3 2 0 1 7 6 5 6 4 5 8 " +"7 5 7 8 9 10 9 8 " +; + +char *VTK_VECTOR_TEXT_34 = (char *) "21 0.615625 " +"0.25714 0.63563 0.32571 0.63563 0.50286 0.63642 0.25143 0.63946 0.33143 0.63840 " +"0.33462 0.64286 0.49673 0.64286 0.57714 0.63757 0.58093 0.64286 0.21335 0.84286 " +"0.36680 0.84286 0.46177 0.84286 0.61522 0.84286 0.21295 1.02000 0.46134 1.02000 " +"0.61563 1.02000 0.36571 1.02307 0.46550 1.02571 0.21714 1.02615 0.36000 1.02723 " +"0.61143 1.02615 17 3 5 9 7 6 2 4 5 1 6 8 12 0 1 5 6 " +"12 11 3 0 5 7 8 6 11 12 14 13 9 10 10 9 5 15 14 12 19 " +"18 10 18 13 10 17 14 20 14 15 20 16 19 10 " +; + +char *VTK_VECTOR_TEXT_35 = (char *) "43 0.974539 " +"0.22286 -0.09100 0.32571 -0.09236 0.56832 -0.08857 0.67429 -0.09201 0.28193 0.22000 " +"0.39470 0.22000 0.63009 0.22000 0.15385 0.23143 0.27429 0.22723 0.40571 0.22723 " +"0.62286 0.22723 0.74857 0.22680 0.97454 0.23143 0.15385 0.33429 0.97454 0.33429 " +"0.30344 0.34000 0.65201 0.34000 0.77084 0.34000 0.42286 0.34010 0.42034 0.34571 " +"0.36041 0.60286 0.70748 0.60286 0.82034 0.60286 0.47429 0.60626 0.15385 0.61429 " +"0.35429 0.61009 0.70286 0.60951 0.82857 0.61009 0.97454 0.61429 0.15385 0.71714 " +"0.37714 0.72134 0.50286 0.72191 0.72571 0.72134 0.85143 0.72156 0.97143 0.72025 " +"0.38605 0.72857 0.49823 0.72857 0.73335 0.72857 0.84613 0.72857 0.45143 1.04160 " +"0.55735 1.04286 0.80000 1.04243 0.90521 1.04286 43 6 2 3 5 0 1 0 5 4 18 " +"9 10 11 6 3 4 9 8 13 8 15 17 6 11 9 4 5 13 7 8 17 " +"12 14 8 9 15 15 19 20 16 6 17 12 17 11 18 10 16 10 6 16 21 " +"16 17 18 19 9 15 9 19 20 30 25 23 20 19 34 33 28 29 24 25 29 " +"25 30 27 21 22 33 21 27 20 23 30 22 21 17 33 27 28 31 26 32 35 " +"30 23 32 38 37 31 35 23 21 32 26 26 31 23 32 21 38 41 37 38 36 " +"35 31 38 21 33 40 39 36 42 41 38 39 35 36 " +; + +char *VTK_VECTOR_TEXT_36 = (char *) "73 0.921518 " +"0.52571 -0.22882 0.59429 -0.22991 0.52000 -0.09942 0.60571 -0.09385 0.40571 -0.07057 " +"0.72730 -0.06571 0.33143 -0.03465 0.80571 -0.01813 0.51429 0.01891 0.52152 0.02571 " +"0.60571 0.02014 0.84571 0.02168 0.25669 0.04286 0.66857 0.03800 0.44571 0.04535 " +"0.70984 0.06571 0.74535 0.10571 0.74857 0.11079 0.74902 0.11143 0.37057 0.12857 " +"0.90538 0.12857 0.20823 0.15143 0.35748 0.16286 0.77395 0.16857 0.35429 0.17310 " +"0.35177 0.18000 0.78134 0.21429 0.92152 0.21429 0.19580 0.22571 0.33480 0.25429 " +"0.77395 0.29429 0.91177 0.32286 0.76000 0.32921 0.72571 0.36972 0.89355 0.37429 " +"0.64690 0.40857 0.65143 0.40706 0.64000 0.41109 0.60571 0.41986 0.52109 0.43714 " +"0.85714 0.43270 0.38857 0.49216 0.79429 0.48902 0.72571 0.52437 0.30454 0.54571 " +"0.60260 0.56286 0.52043 0.58571 0.26286 0.59570 0.46857 0.59800 0.39429 0.65095 " +"0.22857 0.67295 0.36823 0.70000 0.75429 0.77624 0.21907 0.78571 0.35891 0.78571 " +"0.89184 0.79714 0.37714 0.85001 0.72571 0.86144 0.87470 0.86571 0.24571 0.89016 " +"0.68571 0.90956 0.44000 0.92036 0.60571 0.94469 0.83179 0.94571 0.28000 0.94629 " +"0.51429 0.94891 0.34286 1.00607 0.75429 1.01579 0.38286 1.02784 0.52043 1.06571 " +"0.60260 1.06571 0.52260 1.12286 0.60043 1.12286 75 3 8 2 2 8 4 19 12 6 13 11 15 9 8 10 3 2 1 8 " +"3 10 5 13 10 15 11 16 7 13 5 4 14 6 2 0 1 5 10 3 12 " +"22 21 14 4 8 13 7 11 11 18 16 20 23 18 18 17 16 20 18 11 19 " +"6 14 28 21 29 26 23 20 12 19 22 25 22 24 21 22 25 21 25 29 26 " +"27 30 27 26 20 31 32 30 31 30 27 40 33 32 37 43 38 34 32 31 38 " +"39 9 40 32 34 38 9 10 43 33 42 37 36 43 39 38 43 42 33 40 35 " +"36 37 33 43 36 39 45 46 48 41 39 45 39 43 41 48 44 47 51 50 46 " +"62 65 48 39 46 44 49 47 49 44 48 54 53 50 51 47 49 53 56 59 53 " +"54 56 66 64 56 55 58 52 58 57 52 54 50 51 59 56 64 67 60 63 60 " +"57 63 66 61 68 61 66 56 68 65 69 65 62 69 62 46 45 63 57 58 62 " +"60 67 68 61 65 71 70 72 70 62 67 62 70 69 71 69 70 " +; + +char *VTK_VECTOR_TEXT_37 = (char *) "81 1.409911 " +"0.46713 -0.11143 0.57143 -0.11215 1.19429 -0.11252 1.10286 -0.10252 1.26444 -0.09429 " +"1.05143 -0.07759 1.31429 -0.06384 1.14857 -0.01538 1.18857 -0.01807 0.98857 -0.01364 " +"1.22286 -0.00771 1.36784 -0.00286 1.11302 0.00286 1.26436 0.03143 1.07787 0.04857 " +"0.95748 0.05429 1.39681 0.06571 1.28680 0.09429 1.05866 0.14000 1.40991 0.14571 " +"0.94134 0.15143 0.94134 0.21429 1.29295 0.21429 1.06134 0.23714 1.40723 0.23714 " +"0.95748 0.30000 1.39387 0.30000 1.07787 0.30571 1.27429 0.30371 1.09561 0.33429 " +"1.23429 0.35465 1.36616 0.36286 1.13143 0.36327 1.16571 0.37277 1.20571 0.36899 " +"1.00045 0.38571 1.32000 0.41543 1.06857 0.44498 1.24571 0.45681 0.48000 0.46420 " +"1.15429 0.46723 0.38857 0.47462 0.55016 0.48286 0.60000 0.51330 0.30286 0.52704 " +"0.43429 0.56177 0.47429 0.55907 0.26857 0.57284 0.50857 0.56943 0.65355 0.57429 " +"0.39873 0.58000 0.55007 0.60857 0.24530 0.62571 0.36359 0.62571 0.68252 0.64286 " +"0.56680 0.64857 0.23050 0.69429 0.34437 0.71714 0.57866 0.72286 0.69563 0.72286 " +"0.22705 0.79143 0.34705 0.81429 0.69295 0.81429 0.56891 0.85429 0.67959 0.87714 " +"0.24530 0.88286 0.36359 0.88286 0.38132 0.91143 0.54286 0.90975 0.52000 0.93179 " +"0.65465 0.93429 0.41714 0.94041 0.47429 0.94950 0.29143 0.96914 0.60571 0.99258 " +"0.32000 0.99868 0.38286 1.03395 0.53714 1.03184 1.06857 1.04249 1.17287 1.04286 " +"0.48000 1.04395 79 0 1 78 10 4 6 2 8 3 9 14 15 4 " +"10 8 3 7 5 7 3 8 10 6 13 12 5 7 5 12 9 4 8 2 13 " +"16 17 17 19 22 14 9 12 15 18 20 11 13 6 13 11 16 17 16 19 18 " +"15 14 21 20 18 21 23 25 22 26 28 23 21 18 24 22 19 25 27 35 35 " +"29 37 22 24 26 28 31 30 27 25 23 31 28 26 27 29 35 36 30 31 38 " +"34 30 38 33 34 37 32 40 32 33 40 38 30 36 32 37 29 40 33 38 42 " +"46 39 47 53 52 48 43 51 39 46 41 41 50 44 56 57 60 45 41 46 42 " +"48 46 48 42 43 50 41 45 53 47 44 51 49 55 54 55 49 53 44 50 49 " +"51 43 55 54 58 59 58 54 57 56 52 57 52 53 60 61 65 58 62 63 57 " +"61 60 62 64 63 65 66 73 66 65 61 73 66 75 58 59 62 63 64 68 70 " +"69 68 67 75 66 70 68 64 76 71 72 75 67 76 74 69 70 71 76 67 69 " +"77 72 72 77 80 77 69 74 76 72 80 79 78 1 " +; + +char *VTK_VECTOR_TEXT_38 = (char *) "76 1.126291 " +"0.58857 -0.08966 1.03429 -0.09235 0.48000 -0.08395 0.66286 -0.07673 0.40000 -0.05914 " +"0.72000 -0.05641 0.98286 -0.05473 0.35429 -0.03393 0.78857 -0.01678 1.12629 0.00857 " +"0.29143 0.02168 0.52571 0.02991 0.57714 0.02764 0.62286 0.03756 0.46857 0.04645 " +"0.87429 0.05495 0.69714 0.07393 0.42132 0.08286 1.04571 0.07868 0.24486 0.08857 " +"0.75011 0.11714 0.22327 0.14000 0.37927 0.14571 0.78349 0.16286 0.96893 0.16286 " +"0.96571 0.16717 0.96457 0.16857 0.95937 0.18000 0.35580 0.22571 0.20991 0.25429 " +"0.36319 0.28857 0.86286 0.29600 1.02437 0.31143 0.22645 0.32857 0.40418 0.36286 " +"0.40571 0.36454 0.41330 0.37429 1.05421 0.40857 0.28418 0.42571 0.92000 0.44119 " +"0.53714 0.46770 0.37143 0.50250 0.66758 0.54000 0.46406 0.55714 0.78704 0.62571 " +"0.59429 0.63146 0.37714 0.68444 0.69296 0.70000 0.85355 0.71714 0.35681 0.73429 " +"0.50200 0.75143 0.49756 0.76286 0.49502 0.76857 0.72891 0.76857 0.86966 0.76857 " +"0.34748 0.82000 0.73295 0.82000 0.48764 0.82571 0.87236 0.83143 0.49714 0.86089 " +"0.35849 0.87143 0.71429 0.87650 0.52000 0.89555 0.69714 0.89846 0.37964 0.91714 " +"0.84657 0.91714 0.55429 0.92073 0.65714 0.92498 0.60000 0.93277 0.81868 0.95714 " +"0.42857 0.97582 0.76571 1.00436 0.51429 1.02723 0.72000 1.02723 0.59429 1.04437 " +"0.64571 1.04395 78 7 17 10 3 13 0 " +"2 14 4 6 18 15 17 7 4 9 18 " +"6 9 6 1 8 16 5 0 12 2 " +"17 4 14 2 11 14 12 0 13 13 5 " +"16 15 24 20 16 8 20 13 3 5 " +"2 12 11 10 17 19 21 28 29 15 20 " +"8 20 24 23 40 23 31 24 25 26 " +"19 22 21 31 23 27 22 19 17 18 24 " +"15 28 21 22 29 30 33 31 32 39 " +"23 24 26 30 29 28 23 26 27 33 30 " +"38 32 31 27 38 36 41 38 34 36 " +"34 38 30 36 34 35 39 32 37 42 40 " +"31 40 41 36 42 44 47 45 43 40 " +"40 43 41 50 46 43 50 49 46 45 40 " +"42 48 53 47 45 42 47 49 52 55 " +"53 48 56 50 43 45 57 60 55 52 50 " +"51 49 50 52 48 47 44 54 56 48 " +"56 65 61 60 59 64 59 60 57 65 56 " +"58 52 57 55 64 59 70 58 56 54 " +"59 62 70 68 74 72 65 69 61 70 66 " +"72 63 71 67 63 61 69 70 62 66 " +"67 73 68 71 63 69 73 67 71 68 72 " +"66 74 68 75 75 68 73 " +; + +char *VTK_VECTOR_TEXT_39 = (char *) "10 0.364197 " +"0.25143 0.63563 0.24571 0.63946 0.32571 0.63757 0.32950 0.64286 0.21034 0.83714 " +"0.36379 0.83714 0.20991 1.02000 0.36420 1.02000 0.21408 1.02571 0.36000 1.02615 8 1 0 3 " +"2 3 0 1 3 4 7 6 4 5 4 " +"3 7 4 5 8 6 9 6 7 9 " +; + +char *VTK_VECTOR_TEXT_40 = (char *) "19 0.595731 " +"0.50857 -0.39522 0.59429 -0.39447 0.44000 -0.30784 0.51787 -0.24857 0.32530 -0.09429 " +"0.43748 -0.05429 0.26899 0.06571 0.38134 0.20286 0.23580 0.27714 0.37605 0.38000 " +"0.23848 0.41429 0.39320 0.53429 0.27177 0.59714 0.43748 0.71143 0.47216 0.80286 " +"0.36086 0.82000 0.45714 0.97936 0.59573 1.04286 0.50857 1.04395 17 2 3 4 0 3 2 3 " +"0 1 6 4 5 3 5 4 6 7 8 7 6 5 9 10 8 9 8 7 10 " +"11 12 10 9 11 12 13 15 12 11 13 14 15 13 16 15 14 17 18 16 17 " +"16 14 " +; + +char *VTK_VECTOR_TEXT_41 = (char *) "19 0.598482 " +"0.24000 -0.39447 0.33143 -0.39258 0.40616 -0.28857 0.31641 -0.24857 0.48784 -0.14000 " +"0.39681 -0.05429 0.55538 0.03143 0.45295 0.20286 0.59580 0.23714 0.59848 0.37429 " +"0.45823 0.38000 0.44723 0.49429 0.56252 0.59714 0.41714 0.64134 0.47343 0.82000 " +"0.34857 0.83301 0.37714 0.97936 0.23855 1.04286 0.32571 1.04395 17 0 1 3 2 3 1 3 " +"4 5 3 2 4 5 6 7 6 5 4 7 8 10 8 9 10 11 10 9 8 " +"7 6 11 12 13 13 14 15 12 11 9 14 13 12 15 16 17 16 15 14 16 " +"18 17 " +; + +char *VTK_VECTOR_TEXT_42 = (char *) "34 0.685300 " +"0.33143 0.58250 0.33714 0.58223 0.53714 0.58250 0.54286 0.58194 0.36213 0.61429 " +"0.25587 0.63714 0.25266 0.64286 0.62655 0.64286 0.25393 0.64857 0.43429 0.73293 " +"0.44000 0.73049 0.36715 0.78000 0.50714 0.78000 0.35429 0.78613 0.63429 0.80816 " +"0.19309 0.82571 0.68389 0.82571 0.19177 0.83143 0.68530 0.83143 0.38857 0.86213 " +"0.39523 0.86571 0.48000 0.86242 0.47660 0.86571 0.34657 0.88286 0.58857 0.90823 " +"0.22286 0.92522 0.22857 0.92848 0.64571 0.92816 0.65143 0.92675 0.49295 1.02000 " +"0.38134 1.03714 0.38550 1.04286 0.49143 1.04021 0.48571 1.04437 32 2 12 10 8 4 11 " +"8 5 4 8 6 5 4 0 1 2 3 " +"12 0 4 5 12 9 10 9 11 4 " +"19 11 21 14 24 12 26 25 17 16 18 " +"14 13 23 15 19 21 20 11 19 13 " +"33 31 30 24 21 12 12 21 9 21 11 " +"9 26 17 23 12 3 7 27 24 18 " +"13 19 23 23 17 15 20 21 22 18 24 " +"14 28 27 18 33 30 20 29 20 22 " +"29 33 20 32 33 29 " +; + +char *VTK_VECTOR_TEXT_43 = (char *) "20 0.952768 " +"0.52836 0.10571 0.64878 0.10571 0.52420 0.11143 0.65295 0.11143 0.52420 0.39714 " +"0.65295 0.39714 0.22857 0.40546 0.52000 0.40329 0.66286 0.40437 0.95168 0.40857 " +"0.22437 0.52286 0.95277 0.52286 0.22857 0.52900 0.52311 0.53429 0.65403 0.53429 " +"0.94857 0.52900 0.52528 0.82571 0.65186 0.82571 0.53143 0.82991 0.64571 0.82991 18 1 2 0 1 3 2 " +"4 2 3 5 4 3 12 6 7 14 4 " +"8 9 15 8 8 4 5 9 11 15 " +"12 7 13 6 12 10 7 4 13 14 8 " +"15 17 19 18 14 13 4 17 18 16 " +"17 16 13 17 13 14 " +; + +char *VTK_VECTOR_TEXT_44 = (char *) "23 0.432768 " +"0.30286 -0.28607 0.30857 -0.28726 0.33714 -0.27355 0.36571 -0.25275 0.27329 -0.23714 " +"0.38670 -0.23143 0.30286 -0.21582 0.39914 -0.21429 0.32115 -0.19714 0.41355 -0.18571 " +"0.33800 -0.16857 0.42327 -0.15714 0.34605 -0.14571 0.43277 -0.10000 0.35580 -0.08286 " +"0.35472 -0.07714 0.28571 -0.07295 0.34857 -0.07295 0.28000 -0.06878 0.27957 0.07714 " +"0.43168 0.07714 0.28571 0.08134 0.42857 0.08025 21 0 6 4 0 " +"1 2 0 2 6 3 6 2 8 5 10 5 7 10 6 5 8 5 6 3 10 " +"7 12 9 12 7 12 13 14 11 12 9 12 11 13 18 17 19 17 21 19 15 " +"14 13 15 13 17 21 17 22 17 20 22 18 16 17 20 17 13 " +; + +char *VTK_VECTOR_TEXT_45 = (char *) "8 0.606146 " +"0.19118 0.26000 0.19429 0.25689 0.60000 0.25580 0.60615 0.26000 0.19118 0.38571 " +"0.60615 0.38571 0.19429 0.38882 0.60000 0.38991 6 6 1 2 6 0 " +"1 6 2 7 6 4 0 7 2 3 " +"5 7 3 " +; + +char *VTK_VECTOR_TEXT_46 = (char *) "13 0.432768 " +"0.28571 -0.07295 0.42286 -0.07295 0.42857 -0.07186 0.27848 -0.06571 0.28000 -0.06878 " +"0.43277 -0.06571 0.27848 0.07143 0.43277 0.07143 0.27957 0.07714 0.43168 0.07714 " +"0.28571 0.08134 0.42286 0.08134 0.42857 0.08025 11 0 " +"3 4 3 0 1 8 6 10 5 1 2 3 1 5 6 3 5 6 7 11 6 " +"5 7 10 6 11 9 12 11 9 11 7 " +; + +char *VTK_VECTOR_TEXT_47 = (char *) "5 0.562348 " +"0.14389 -0.08857 0.14857 -0.09256 0.25004 -0.08857 0.56235 1.04286 0.46286 1.04358 3 2 0 1 4 0 2 3 " +"4 2 " +; + +char *VTK_VECTOR_TEXT_48 = (char *) "53 0.926804 " +"0.53714 -0.09009 0.59429 -0.09009 0.66857 -0.07673 0.43429 -0.06723 0.73143 -0.05070 " +"0.34286 -0.00972 0.80571 0.01025 0.54857 0.02152 0.61714 0.02891 0.30241 0.03714 " +"0.65714 0.04645 0.46857 0.05007 0.42473 0.08857 0.70286 0.08454 0.26645 0.10000 " +"0.86943 0.11143 0.39955 0.12286 0.73800 0.13429 0.23748 0.18000 0.37034 0.19714 " +"0.76252 0.20286 0.91236 0.26000 0.21866 0.26571 0.35621 0.26571 0.77823 0.28857 " +"0.34437 0.40286 0.92680 0.40286 0.20420 0.40857 0.78705 0.54000 0.20723 0.58000 " +"0.92420 0.58571 0.35277 0.64286 0.22177 0.69429 0.76571 0.72437 0.89966 0.74000 " +"0.37756 0.76286 0.74498 0.79143 0.26073 0.82571 0.85927 0.84857 0.42473 0.85429 " +"0.70439 0.85429 0.46286 0.88902 0.66286 0.89007 0.30241 0.90000 0.51009 0.91143 " +"0.58286 0.91823 0.80725 0.92857 0.77714 0.95829 0.38350 0.98000 0.71429 0.99927 " +"0.46286 1.01681 0.65714 1.01959 0.53714 1.02991 53 2 8 1 0 7 3 5 16 9 2 10 8 0 " +"1 8 7 0 8 12 16 5 11 3 7 3 12 5 15 20 17 11 12 3 13 " +"6 17 6 13 4 9 16 14 10 4 13 14 19 18 4 10 2 15 17 6 19 " +"14 16 21 24 20 23 18 19 22 25 27 24 26 28 23 22 18 21 20 15 26 " +"24 21 22 23 25 29 27 25 29 31 32 28 30 33 31 29 25 30 28 26 32 " +"35 37 46 40 36 30 34 33 32 31 35 43 39 48 43 37 35 38 36 33 38 " +"33 34 42 40 49 48 41 50 39 43 35 47 40 46 46 36 38 41 44 50 45 " +"52 44 42 51 45 41 48 39 49 40 47 50 44 52 52 45 51 42 49 51 " +; + +char *VTK_VECTOR_TEXT_49 = (char *) "11 0.708571 " +"0.58286 -0.07186 0.70857 -0.07186 0.30857 0.62908 0.31429 0.62657 0.38286 0.65641 " +"0.30785 0.75143 0.57714 0.77731 0.47429 0.85616 0.56384 0.94000 0.62857 1.02915 " +"0.70857 1.02882 9 6 0 1 2 4 5 7 5 4 2 3 4 6 " +"8 7 6 7 4 10 8 6 10 6 1 10 9 8 " +; + +char *VTK_VECTOR_TEXT_50 = (char *) "43 0.914286 " +"0.18857 -0.06878 0.91429 -0.06878 0.18748 -0.04286 0.19849 0.00857 0.91429 0.05164 " +"0.38142 0.06000 0.22943 0.07714 0.46286 0.15868 0.30286 0.17832 0.38286 0.25813 " +"0.58413 0.43143 0.78286 0.44454 0.67543 0.52286 0.85355 0.53429 0.72045 0.58000 " +"0.89756 0.62571 0.75470 0.64286 0.35168 0.70000 0.91236 0.70000 0.77295 0.71143 " +"0.21403 0.71714 0.77295 0.74571 0.22605 0.79143 0.37143 0.79804 0.90244 0.80857 " +"0.75429 0.81228 0.38902 0.83143 0.24359 0.84286 0.73143 0.84689 0.42454 0.87143 " +"0.86607 0.88857 0.68000 0.89070 0.28000 0.90629 0.49143 0.90823 0.58857 0.91866 " +"0.82857 0.93555 0.31597 0.94571 0.37714 0.98784 0.76000 0.98657 0.44571 1.01470 " +"0.69143 1.01470 0.53714 1.02991 0.62857 1.02723 41 3 2 0 3 5 6 1 5 0 5 " +"3 0 1 4 5 6 5 8 7 8 5 9 8 7 9 7 10 11 10 7 10 " +"11 12 12 11 14 16 15 18 16 18 19 13 14 11 14 13 16 21 24 25 15 " +"16 13 21 19 18 23 27 22 17 23 22 24 21 18 27 23 32 17 22 20 31 " +"42 34 30 28 25 26 32 23 40 31 38 35 28 30 36 32 26 29 36 26 34 " +"41 33 33 37 29 36 29 37 33 39 37 30 25 24 28 38 31 38 28 35 39 " +"33 41 31 40 42 41 34 42 " +; + +char *VTK_VECTOR_TEXT_51 = (char *) "68 0.927232 " +"0.52571 -0.09009 0.63429 -0.08395 0.45143 -0.07756 0.37143 -0.04498 0.74286 -0.04771 " +"0.30857 0.00132 0.81714 0.00439 0.54286 0.02152 0.60000 0.02420 0.64661 0.03714 " +"0.27429 0.03952 0.46857 0.04073 0.42857 0.06759 0.70857 0.07561 0.88213 0.08286 " +"0.23429 0.10772 0.38812 0.11714 0.74535 0.11714 0.91109 0.14571 0.77823 0.19143 " +"0.20764 0.20857 0.92723 0.22571 0.34286 0.23215 0.78437 0.27143 0.92723 0.27714 " +"0.75429 0.36430 0.89927 0.38571 0.72571 0.40132 0.86857 0.43270 0.67429 0.43927 " +"0.48000 0.45284 0.48571 0.44966 0.54857 0.46152 0.60000 0.46109 0.83429 0.46686 " +"0.72693 0.52286 0.49034 0.55714 0.49714 0.56395 0.78857 0.56473 0.58286 0.57109 " +"0.82857 0.60921 0.67429 0.61616 0.70400 0.64857 0.85294 0.65429 0.72680 0.70571 " +"0.87009 0.72286 0.35429 0.72298 0.22175 0.74571 0.72991 0.76286 0.72151 0.80286 " +"0.86244 0.80857 0.38857 0.82064 0.69143 0.85832 0.84571 0.85587 0.26241 0.87143 " +"0.43429 0.87829 0.64571 0.89641 0.48571 0.90723 0.29330 0.91714 0.60571 0.91252 " +"0.53143 0.91823 0.80384 0.92286 0.36000 0.97750 0.73143 0.98213 0.44571 1.01681 " +"0.65714 1.01470 0.52000 1.02991 0.60000 1.02723 66 3 11 " +"5 9 8 1 1 8 0 4 9 1 " +"9 4 13 7 0 8 6 13 4 17 13 " +"6 2 11 3 2 0 7 5 16 10 " +"12 5 11 10 16 15 11 2 7 16 5 " +"12 17 14 19 14 17 6 20 15 22 " +"19 18 23 22 15 16 14 18 19 21 23 " +"18 23 26 25 23 21 24 26 28 25 " +"30 32 36 25 34 27 35 32 33 35 29 " +"27 25 28 34 29 35 33 26 23 24 " +"37 36 32 39 32 35 35 27 34 37 32 " +"39 30 31 32 39 35 41 38 41 35 " +"38 42 41 40 42 38 42 40 44 40 43 " +"44 44 43 48 45 48 43 47 46 54 " +"49 48 50 50 48 45 49 53 52 63 52 " +"61 53 49 50 46 51 54 58 54 51 " +"58 55 62 62 55 64 66 57 60 61 52 " +"53 55 58 51 59 67 60 52 63 56 " +"56 65 59 55 57 64 64 57 66 65 56 " +"63 67 66 60 67 59 65 " +; + +char *VTK_VECTOR_TEXT_52 = (char *) "18 0.920000 " +"0.64571 -0.07295 0.64000 -0.06878 0.77143 -0.06878 0.77403 0.18571 0.16265 0.19143 " +"0.63429 0.18882 0.92000 0.19408 0.15891 0.31143 0.91735 0.31143 0.29653 0.31714 " +"0.63740 0.31714 0.77714 0.31403 0.16571 0.32228 0.16616 0.32286 0.63429 0.79380 " +"0.77186 1.02000 0.66857 1.02282 0.76571 1.02420 18 2 1 0 1 3 5 1 2 " +"3 3 10 5 9 4 5 4 9 7 " +"6 11 3 8 11 6 7 9 13 15 16 " +"14 9 5 10 7 13 12 13 14 16 " +"11 10 3 14 13 9 14 10 11 15 17 " +"16 15 14 11 " +; + +char *VTK_VECTOR_TEXT_53 = (char *) "54 0.932946 " +"0.52571 -0.09009 0.61714 -0.08665 0.44571 -0.07673 0.73143 -0.05179 0.35429 -0.03759 " +"0.78914 -0.01429 0.30286 0.00241 0.53714 0.02152 0.62857 0.03184 0.84115 0.03714 " +"0.46857 0.03927 0.66286 0.04645 0.26286 0.04921 0.42286 0.06759 0.71429 0.08439 " +"0.88045 0.09429 0.23343 0.10000 0.38812 0.10571 0.74535 0.12286 0.35748 0.16857 " +"0.77294 0.18000 0.91681 0.18000 0.20420 0.20857 0.34286 0.22376 0.78705 0.23714 " +"0.93295 0.27143 0.79009 0.31714 0.93252 0.33429 0.77714 0.38420 0.91681 0.42000 " +"0.34857 0.43034 0.75641 0.43143 0.23088 0.44857 0.72000 0.47868 0.40000 0.48400 " +"0.68000 0.50784 0.86902 0.51714 0.46857 0.52437 0.53143 0.53848 0.57714 0.53848 " +"0.58857 0.53621 0.60000 0.53580 0.82286 0.56972 0.38494 0.59714 0.77714 0.60535 " +"0.48571 0.64244 0.69714 0.64327 0.56571 0.65848 0.61714 0.65848 0.43891 0.87714 " +"0.44571 0.88395 0.88043 0.88857 0.88043 1.00857 0.33714 1.01182 52 7 1 " +"8 7 0 1 7 2 0 2 10 4 " +"6 13 12 3 8 1 3 11 8 10 2 " +"7 4 13 6 11 3 14 19 16 12 " +"3 5 14 9 14 5 10 13 4 22 19 " +"23 18 15 20 17 12 13 15 14 9 " +"14 15 18 19 12 17 25 26 24 20 21 " +"24 21 20 15 22 16 19 25 24 21 " +"26 25 27 29 28 26 29 26 27 43 37 " +"45 36 31 29 34 32 30 31 36 33 " +"31 28 29 32 34 43 48 47 41 45 38 " +"47 42 33 36 41 39 40 38 39 47 " +"37 38 45 47 39 41 44 33 42 43 34 " +"37 46 33 44 35 46 41 33 46 35 " +"46 48 41 32 43 53 43 49 53 49 50 " +"53 53 50 52 50 51 52 " +; + +char *VTK_VECTOR_TEXT_54 = (char *) "70 0.927232 " +"0.55429 -0.09009 0.66857 -0.08034 0.43429 -0.06213 0.75429 -0.04607 0.34857 -0.00972 " +"0.81143 -0.00439 0.59429 0.02152 0.51339 0.03143 0.85188 0.04286 0.67429 0.04645 " +"0.46286 0.05579 0.27384 0.07714 0.41714 0.09597 0.73143 0.09597 0.89355 0.11714 " +"0.38771 0.14000 0.91177 0.16857 0.77294 0.17429 0.22816 0.18571 0.36530 0.19714 " +"0.78705 0.24857 0.92680 0.25429 0.35320 0.26000 0.78665 0.30571 0.20420 0.31143 " +"0.35320 0.31143 0.92723 0.31714 0.36657 0.37429 0.77395 0.37429 0.75429 0.41841 " +"0.39179 0.42571 0.89756 0.44286 0.72000 0.46418 0.43429 0.47258 0.19891 0.50571 " +"0.33714 0.50495 0.48000 0.50213 0.66857 0.50086 0.86241 0.50571 0.55429 0.52134 " +"0.61143 0.51866 0.80403 0.56857 0.42286 0.58821 0.74286 0.60943 0.34134 0.63143 " +"0.50857 0.62823 0.68000 0.63252 0.57714 0.64134 0.21563 0.66000 0.77714 0.74697 " +"0.37502 0.75714 0.90966 0.76286 0.25673 0.80286 0.41901 0.83143 0.73143 0.85191 " +"0.45143 0.86686 0.87343 0.87714 0.30036 0.88286 0.68000 0.89514 0.50286 0.90086 " +"0.51429 0.90530 0.52000 0.90784 0.60571 0.91866 0.83846 0.92857 0.35429 0.94384 " +"0.40571 0.98150 0.76000 0.99229 0.49143 1.01748 0.68571 1.02041 0.56571 1.02991 70 " +"2 10 4 6 1 9 3 5 13 0 7 " +"2 3 9 1 1 6 0 9 3 13 " +"7 0 6 10 2 7 20 26 23 4 12 " +"11 13 8 17 4 10 12 11 19 18 " +"17 21 20 15 11 12 11 15 19 16 17 " +"14 18 22 24 8 14 17 8 13 5 " +"24 35 34 22 18 19 20 21 26 28 23 " +"26 21 17 16 24 27 35 24 22 25 " +"28 31 29 31 28 26 24 25 27 32 41 " +"37 30 35 27 34 44 48 35 33 42 " +"43 37 41 46 39 40 32 29 38 38 29 " +"31 33 35 30 33 36 42 42 36 45 " +"45 39 47 36 39 45 37 46 40 41 32 " +"38 46 37 43 47 39 46 44 34 35 " +"48 50 52 48 44 50 49 56 54 57 53 " +"64 57 52 50 54 66 58 51 56 49 " +"62 69 61 53 57 50 61 59 60 59 65 " +"55 65 64 55 58 68 62 55 64 53 " +"66 54 63 63 54 56 65 59 67 69 62 " +"68 67 59 61 69 67 61 68 58 66 " +; + +char *VTK_VECTOR_TEXT_55 = (char *) "17 0.923788 " +"0.37143 -0.07186 0.50286 -0.07186 0.36723 -0.06571 0.37335 0.02000 0.52991 0.11143 " +"0.40379 0.18571 0.59787 0.35143 0.47387 0.41429 0.66857 0.51873 0.53355 0.55143 " +"0.63384 0.72857 0.80893 0.76286 0.74359 0.88286 0.21714 0.88546 0.92379 0.91143 " +"0.21403 1.00857 0.92311 1.00857 15 3 0 1 2 0 3 3 4 5 4 3 1 6 7 5 6 5 4 9 " +"7 6 10 9 8 8 9 6 10 11 12 11 10 8 15 13 12 12 14 16 15 " +"12 16 11 14 12 " +; + +char *VTK_VECTOR_TEXT_56 = (char *) "83 0.926804 " +"0.53143 -0.08966 0.62857 -0.08665 0.45143 -0.07605 0.73714 -0.05641 0.38857 -0.05343 " +"0.34286 -0.02616 0.79429 -0.02250 0.28571 0.02445 0.58857 0.02152 0.50857 0.02823 " +"0.85258 0.03143 0.66937 0.04286 0.45143 0.05070 0.71429 0.07296 0.41143 0.07868 " +"0.24000 0.09016 0.89927 0.10571 0.37669 0.12286 0.76613 0.14000 0.21462 0.15714 " +"0.35849 0.16286 0.92109 0.17429 0.78705 0.22000 0.34437 0.22571 0.20420 0.27143 " +"0.92680 0.27143 0.78437 0.28286 0.34748 0.28857 0.77143 0.32947 0.91470 0.33429 " +"0.21714 0.34118 0.37502 0.36286 0.73296 0.39143 0.89057 0.39143 0.24359 0.40286 " +"0.41883 0.41429 0.69143 0.42722 0.27275 0.44286 0.85714 0.43841 0.46286 0.44371 " +"0.50286 0.45748 0.63429 0.45470 0.58286 0.46420 0.80507 0.48286 0.33143 0.49007 " +"0.40456 0.52286 0.72693 0.52286 0.32000 0.57616 0.54857 0.57580 0.62286 0.58319 " +"0.82082 0.58571 0.49714 0.58657 0.66286 0.60073 0.28527 0.61429 0.44571 0.61582 " +"0.70439 0.63714 0.85759 0.63714 0.25756 0.67143 0.72657 0.67143 0.39849 0.68286 " +"0.87470 0.68286 0.74134 0.72857 0.38705 0.73429 0.88109 0.76857 0.24764 0.77429 " +"0.73395 0.79714 0.39470 0.80286 0.87177 0.82000 0.71641 0.83714 0.27216 0.86571 " +"0.44000 0.87296 0.84486 0.88286 0.66286 0.89179 0.48000 0.90086 0.61714 0.91184 " +"0.54286 0.91823 0.31846 0.93429 0.80571 0.93555 0.38286 0.98616 0.72000 0.99800 " +"0.43429 1.01008 0.53143 1.02991 0.61714 1.02723 85 0 " +"9 2 12 4 2 1 8 0 6 11 3 5 14 7 9 0 8 8 1 11 4 " +"12 5 13 11 6 1 3 11 12 2 9 5 12 14 13 10 18 7 17 15 10 " +"13 6 15 20 19 7 14 17 18 16 22 16 18 10 20 15 17 19 23 24 16 " +"21 22 22 25 26 23 19 20 24 27 30 25 22 21 27 24 23 31 34 30 31 " +"37 34 29 28 26 31 30 27 29 26 25 33 28 29 28 33 32 36 32 43 37 " +"31 44 40 45 39 44 39 45 43 32 38 35 44 31 42 48 40 44 35 39 41 " +"46 42 36 46 41 32 33 38 48 42 49 46 36 43 48 45 40 42 46 49 51 " +"45 48 49 46 52 47 54 53 52 46 55 53 59 57 45 54 47 45 51 54 50 " +"55 46 59 53 54 50 58 55 58 50 61 57 62 64 61 63 65 56 61 50 57 " +"59 62 60 61 56 64 66 69 63 67 65 64 62 66 63 61 60 71 68 65 76 " +"69 66 72 68 77 71 65 67 76 70 78 70 76 66 74 82 75 80 78 70 79 " +"72 77 74 72 79 80 73 75 80 75 81 68 71 77 73 80 70 82 81 75 82 " +"74 79 " +; + +char *VTK_VECTOR_TEXT_57 = (char *) "72 0.927232 " +"0.50286 -0.09009 0.56000 -0.09009 0.42857 -0.07673 0.64571 -0.07395 0.36000 -0.04771 " +"0.74286 -0.02616 0.28759 0.01429 0.51429 0.02152 0.57143 0.02420 0.80115 0.02571 " +"0.47429 0.02891 0.42857 0.05007 0.64000 0.04943 0.24930 0.07714 0.39314 0.08286 " +"0.85229 0.10000 0.70902 0.11143 0.37057 0.12286 0.22177 0.17429 0.34857 0.18947 " +"0.75109 0.19714 0.89395 0.20286 0.75429 0.20739 0.75681 0.21429 0.90966 0.27143 " +"0.50286 0.30152 0.42857 0.31605 0.61714 0.31462 0.37714 0.33787 0.70286 0.35759 " +"0.78705 0.37429 0.32000 0.37846 0.58286 0.42152 0.50286 0.42891 0.63429 0.43184 " +"0.78286 0.43630 0.92723 0.43714 0.26286 0.44350 0.45143 0.45107 0.68571 0.45750 " +"0.41587 0.47714 0.23787 0.48857 0.74498 0.52286 0.36359 0.55143 0.21522 0.55714 " +"0.92680 0.56286 0.76571 0.57009 0.34437 0.63143 0.77823 0.63714 0.20462 0.69429 " +"0.77866 0.69429 0.91236 0.70000 0.35429 0.74118 0.76571 0.76404 0.21756 0.77429 " +"0.38286 0.80921 0.87343 0.82571 0.40759 0.84286 0.72571 0.84118 0.24527 0.84857 " +"0.69143 0.87527 0.84000 0.88221 0.47429 0.89641 0.28571 0.90975 0.63429 0.90784 " +"0.54857 0.91866 0.33143 0.95527 0.76000 0.96331 0.39629 0.99714 0.68571 1.00437 " +"0.49714 1.02723 0.57714 1.02991 72 3 8 1 2 11 4 0 7 2 " +"8 3 12 4 14 6 0 1 8 6 17 " +"13 10 2 7 7 0 8 5 12 3 " +"12 5 16 2 10 11 4 11 14 5 9 " +"16 18 13 19 16 15 20 15 23 20 " +"6 14 17 13 17 19 21 23 15 22 20 " +"23 23 24 30 16 9 15 23 21 24 " +"25 32 26 27 32 25 38 28 26 43 41 " +"37 34 29 39 33 26 32 29 34 27 " +"30 36 35 34 32 27 36 30 24 28 38 " +"31 31 38 37 35 39 29 38 26 33 " +"39 35 42 42 35 36 40 37 38 44 41 " +"43 42 36 46 44 47 49 43 37 40 " +"48 46 45 36 45 46 51 50 48 52 54 " +"49 47 44 43 50 51 53 51 48 45 " +"59 54 52 59 55 63 52 49 47 53 61 " +"58 56 53 51 55 59 52 53 56 61 " +"66 63 57 55 57 63 62 68 57 58 67 " +"60 67 58 61 68 66 57 60 69 64 " +"68 62 70 60 67 69 64 71 65 65 70 " +"62 70 65 71 64 69 71 " +; + +char *VTK_VECTOR_TEXT_58 = (char *) "14 0.432768 " +"0.28571 -0.07295 0.42857 -0.07186 0.28000 -0.06878 0.43277 -0.06571 0.27957 0.07714 " +"0.28571 0.08134 0.42857 0.08025 0.27957 0.57429 0.28571 0.57009 0.43168 0.57429 " +"0.27848 0.71714 0.43277 0.71714 0.28265 0.72286 0.42857 0.72329 10 " +"2 5 4 2 0 5 0 3 5 6 5 " +"3 0 1 3 7 8 10 10 11 13 " +"9 10 8 12 10 13 11 10 9 " +; + +char *VTK_VECTOR_TEXT_59 = (char *) "18 0.432768 " +"0.30857 -0.28726 0.36571 -0.25275 0.27323 -0.23714 0.39543 -0.22000 0.32384 -0.19143 " +"0.33756 -0.16857 0.42327 -0.15714 0.43277 -0.10000 0.35472 -0.07714 0.28571 -0.07295 " +"0.34857 -0.07295 0.28000 -0.06878 0.27957 0.07714 0.43168 0.07714 0.27957 0.57429 " +"0.43168 0.57429 0.28265 0.72286 0.42857 0.72329 14 2 1 4 5 4 3 0 1 " +"2 5 6 8 3 4 1 6 5 3 " +"6 7 8 11 10 12 12 10 13 8 7 " +"10 11 9 10 13 10 7 17 16 15 " +"15 16 14 " +; + +char *VTK_VECTOR_TEXT_60 = (char *) "11 0.952690 " +"0.94857 0.09939 0.95269 0.10571 0.95236 0.22571 0.22894 0.40857 0.38919 0.46571 " +"0.38919 0.47143 0.22748 0.52857 0.23192 0.53429 0.95098 0.70571 0.95216 0.83143 " +"0.94857 0.83523 9 4 0 2 5 7 6 4 3 0 0 1 2 7 " +"8 10 4 5 3 5 6 3 8 9 10 7 5 8 " +; + +char *VTK_VECTOR_TEXT_61 = (char *) "12 0.952768 " +"0.22857 0.23975 0.94857 0.23975 0.22437 0.35714 0.95277 0.35714 0.22857 0.36329 " +"0.94857 0.36329 0.22857 0.57385 0.94857 0.57385 0.22437 0.58000 0.95277 0.58000 " +"0.22857 0.69740 0.94857 0.69740 8 0 4 " +"2 0 1 5 4 0 5 3 5 1 " +"11 7 9 10 6 7 10 7 11 8 6 " +"10 " +; + +char *VTK_VECTOR_TEXT_62 = (char *) "11 0.952360 " +"0.23429 0.09914 0.22857 0.10169 0.22748 0.22571 0.23192 0.23143 0.95116 0.40857 " +"0.79073 0.46571 0.79073 0.47143 0.95236 0.52857 0.22897 0.70571 0.22857 0.83287 " +"0.23429 0.83563 9 1 0 2 3 2 0 3 0 5 4 7 5 4 " +"5 0 6 5 7 6 10 8 8 10 9 10 6 7 " +; + +char *VTK_VECTOR_TEXT_63 = (char *) "45 0.918074 " +"0.47429 -0.07186 0.62021 -0.07143 0.47118 0.07714 0.62329 0.07714 0.49979 0.19714 " +"0.62021 0.19714 0.49563 0.20286 0.49563 0.27714 0.63681 0.31714 0.50816 0.34571 " +"0.65714 0.36350 0.53669 0.41429 0.70857 0.42384 0.57868 0.47143 0.82857 0.53597 " +"0.86902 0.58571 0.73258 0.62000 0.90437 0.65429 0.76086 0.66000 0.77522 0.70000 " +"0.91580 0.70000 0.34857 0.71338 0.21034 0.73429 0.77866 0.75143 0.91807 0.76857 " +"0.22605 0.80857 0.76571 0.80375 0.38286 0.82144 0.73714 0.85191 0.25098 0.87143 " +"0.89143 0.86730 0.43597 0.88857 0.86812 0.90571 0.67429 0.90616 0.48571 0.91800 " +"0.62857 0.92538 0.29296 0.93429 0.54857 0.93277 0.81143 0.96670 0.35429 0.98821 " +"0.76571 0.99800 0.44571 1.02891 0.69714 1.02680 0.53143 1.04395 0.60000 1.04437 41 2 1 3 2 0 1 7 6 4 7 4 5 8 9 7 11 10 13 8 " +"7 5 8 10 11 9 8 11 13 12 16 12 13 10 14 16 12 14 15 16 16 " +"15 18 17 18 15 17 23 19 17 19 18 20 23 17 29 27 36 26 32 28 21 " +"25 22 26 23 24 27 29 25 24 23 20 36 31 39 28 40 33 30 26 24 35 " +"44 37 31 36 27 27 25 21 31 34 41 42 33 40 28 38 40 39 31 41 38 " +"28 32 26 30 32 42 35 33 41 34 43 43 37 44 34 37 43 44 35 42 " +; + +char *VTK_VECTOR_TEXT_64 = (char *) "114 1.632597 " +"0.92571 -0.39563 1.16571 -0.38109 0.74857 -0.37236 0.65143 -0.34613 1.33143 -0.33070 " +"0.54286 -0.29914 0.86286 -0.27866 1.06286 -0.28134 1.45650 -0.26000 0.73714 -0.25387 " +"1.21143 -0.25387 0.43429 -0.22384 0.62286 -0.21216 1.32144 -0.20857 1.55582 -0.17429 " +"0.53714 -0.16099 0.52571 -0.15258 0.53143 -0.15669 0.33714 -0.11650 1.45143 -0.11561 " +"0.46286 -0.09260 0.80000 -0.07295 1.20571 -0.07252 1.09714 -0.06891 0.71429 -0.06252 " +"1.49714 -0.06187 1.63260 -0.06000 0.29629 -0.04857 1.29714 -0.04498 0.90857 -0.03629 " +"1.03384 -0.02571 0.62857 -0.01582 0.40486 -0.00857 0.59429 0.01873 1.41143 0.03296 " +"0.82857 0.03907 0.77714 0.04327 1.01143 0.04414 1.20000 0.05050 1.16989 0.06571 " +"1.25143 0.06086 0.90857 0.06821 0.72000 0.07561 0.54771 0.09429 1.15580 0.09429 " +"0.24420 0.10000 0.35748 0.11143 0.96000 0.10725 0.68527 0.11714 1.33841 0.11714 " +"1.51579 0.15714 0.66177 0.17429 1.41355 0.20286 1.03514 0.20857 0.65295 0.23143 " +"0.22437 0.23714 0.51277 0.23714 0.33563 0.24857 1.45355 0.27714 1.07177 0.31143 " +"1.58478 0.31143 0.65966 0.32857 1.48319 0.36857 0.53184 0.39714 0.23277 0.40286 " +"0.34478 0.40857 1.60420 0.42571 1.08420 0.44286 0.71514 0.48857 0.25184 0.49429 " +"1.49295 0.49429 0.57229 0.50000 1.60109 0.52857 1.05714 0.54144 0.75846 0.55143 " +"0.38645 0.55714 1.47681 0.58571 1.01143 0.59527 0.81714 0.60331 1.58605 0.60857 " +"1.12878 0.61429 0.65714 0.62418 0.86286 0.62319 0.96571 0.62151 0.92571 0.62991 " +"0.42857 0.64350 1.44571 0.66730 0.32359 0.67714 1.06048 0.68286 0.74857 0.69641 " +"1.15429 0.71588 1.28235 0.71714 1.00571 0.71800 0.82857 0.73109 0.92000 0.74152 " +"1.52657 0.75143 0.51275 0.75714 0.37669 0.76286 1.38286 0.76132 0.59493 0.82571 " +"1.30857 0.82821 1.45561 0.84857 0.47429 0.87296 0.73143 0.89681 1.18286 0.89580 " +"1.08571 0.92395 1.37143 0.92400 0.92000 0.93580 0.58286 0.95188 1.30857 0.96371 " +"0.71429 1.00899 1.18286 1.01470 0.92000 1.04437 1.01143 1.04395 114 0 6 2 1 7 0 6 0 7 " +"7 1 10 2 9 3 3 12 5 9 2 " +"6 10 4 13 4 10 1 15 5 12 " +"5 15 11 13 8 19 12 3 9 8 13 " +"4 11 20 18 11 15 16 17 16 15 " +"14 19 8 26 25 14 20 11 16 22 38 " +"23 25 19 14 23 39 30 30 39 37 " +"27 46 45 18 32 27 32 18 20 21 36 " +"24 35 29 41 24 42 31 29 35 21 " +"22 28 40 38 22 40 34 49 40 33 31 " +"48 36 21 35 37 47 41 33 48 43 " +"43 51 56 44 37 39 34 40 28 47 37 " +"53 50 52 34 38 39 23 52 49 34 " +"37 44 53 27 32 46 42 24 36 48 31 " +"42 37 41 29 45 57 55 53 44 59 " +"51 54 56 52 50 58 58 60 62 43 48 " +"51 45 46 57 56 61 63 64 55 57 " +"91 80 44 60 58 50 62 66 70 56 54 " +"61 44 80 67 59 44 67 71 63 61 " +"64 65 69 67 80 73 65 64 57 66 62 " +"60 68 71 61 71 68 81 69 75 87 " +"72 70 66 74 81 68 77 73 80 70 79 " +"76 75 69 65 83 77 88 87 85 97 " +"81 74 89 89 78 93 86 76 79 70 72 " +"79 74 78 89 88 77 80 75 85 87 " +"82 84 94 91 90 80 86 95 98 78 82 " +"93 92 83 88 93 82 94 84 83 92 " +"94 84 92 97 96 102 95 86 79 102 99 " +"108 95 101 98 96 97 85 96 99 102 " +"98 101 100 103 108 99 100 109 104 106 100 " +"101 108 103 110 105 113 107 100 106 109 " +"104 111 105 107 112 110 111 104 109 113 105 " +"111 112 107 113 107 110 103 " +; + +char *VTK_VECTOR_TEXT_65 = (char *) "13 1.155731 " +"0.14455 -0.07143 1.00000 -0.07252 1.15573 -0.07143 0.29143 -0.07103 0.40981 0.25429 " +"0.86857 0.25754 0.45714 0.37713 0.82478 0.38000 0.45462 0.38571 0.58538 0.73429 " +"0.63429 0.90068 0.56000 1.02454 0.71429 1.02644 13 5 " +"1 2 0 8 11 6 4 5 12 10 7 0 3 4 0 4 8 6 5 7 6 " +"8 4 7 5 2 8 9 11 9 10 11 12 7 2 11 10 12 " +; + +char *VTK_VECTOR_TEXT_66 = (char *) "48 1.081090 " +"0.25714 -0.07186 0.78286 -0.06723 0.86857 -0.04899 0.93714 -0.02045 1.00725 0.03714 " +"0.39957 0.06000 0.73143 0.05621 0.80571 0.06891 1.04213 0.08857 0.87555 0.10571 " +"1.06437 0.14000 0.91070 0.15143 1.08109 0.22000 0.93295 0.22571 0.93252 0.26571 " +"1.07177 0.32286 0.90857 0.34064 1.04616 0.38571 0.86857 0.38686 0.79429 0.42252 " +"0.39957 0.43143 1.01296 0.43143 0.69714 0.43563 0.97143 0.46686 0.88197 0.51143 " +"0.40571 0.56437 0.72000 0.56705 0.39848 0.57429 0.96956 0.58571 0.80571 0.58930 " +"0.84686 0.62000 0.99641 0.62571 0.86943 0.65429 1.02437 0.70571 0.88420 0.71143 " +"1.02665 0.76857 0.87429 0.79232 1.01673 0.82000 0.84000 0.84984 0.77714 0.88538 " +"0.98607 0.88857 0.39957 0.89429 0.71429 0.89580 0.93143 0.95296 0.85714 0.99756 " +"0.80000 1.01470 0.25714 1.02615 0.70857 1.02680 50 1 6 0 2 7 1 " +"0 20 46 7 2 9 1 7 6 20 27 " +"46 9 4 11 4 9 3 2 3 9 " +"11 10 13 8 11 4 10 11 8 12 13 " +"10 14 17 16 14 15 17 16 21 18 " +"14 13 12 15 14 12 23 18 21 5 0 " +"6 19 26 22 18 24 19 16 17 21 " +"24 18 23 26 19 29 19 24 29 25 22 " +"26 22 25 20 30 29 24 32 28 31 " +"28 32 30 32 31 34 0 5 20 34 35 " +"36 33 34 31 28 30 24 36 40 38 " +"38 44 39 35 37 36 34 33 35 25 27 " +"20 27 41 46 40 36 37 43 38 40 " +"39 45 42 42 47 41 38 43 44 45 39 " +"44 47 46 41 47 42 45 " +; + +char *VTK_VECTOR_TEXT_67 = (char *) "56 1.186046 " +"0.69143 -0.08966 0.80000 -0.08705 0.60000 -0.07823 0.50857 -0.05070 0.93143 -0.05216 " +"0.45714 -0.02486 1.00000 -0.01473 0.39597 0.02000 0.69714 0.03563 0.74857 0.03563 " +"0.62286 0.04899 0.82286 0.04899 1.08000 0.05597 0.57143 0.06784 0.88000 0.07229 " +"0.32571 0.10064 0.93143 0.10759 0.49143 0.11901 1.13800 0.14000 0.45600 0.15714 " +"0.28930 0.16286 0.99641 0.18571 0.41502 0.22571 1.18605 0.27714 0.24319 0.28857 " +"1.04571 0.31105 0.38244 0.32857 0.22748 0.36286 0.36723 0.44286 0.21866 0.52857 " +"0.36991 0.55714 0.22705 0.60857 1.02857 0.69469 0.40657 0.71143 1.16694 0.72857 " +"0.26286 0.74089 0.44187 0.78000 1.13927 0.80857 0.97143 0.80914 0.48000 0.82725 " +"0.31750 0.84286 0.93714 0.85011 0.53143 0.86784 0.89143 0.88331 1.07582 0.90571 " +"0.64000 0.91252 0.64571 0.91335 0.65714 0.91563 0.38286 0.91868 0.78857 0.91823 " +"1.00571 0.96902 0.50286 0.99756 0.93143 1.01070 0.58286 1.02680 0.70286 1.04705 " +"0.80000 1.04437 54 " +"1 9 0 0 8 2 14 6 16 4 14 " +"11 24 20 22 7 17 15 2 10 3 " +"8 10 2 9 1 11 0 9 8 4 11 " +"1 3 13 5 12 16 6 10 13 3 " +"5 13 7 7 13 17 22 20 15 16 12 " +"21 14 4 6 19 15 17 23 25 18 " +"22 15 19 25 21 18 18 21 12 27 28 " +"29 27 24 26 26 24 22 28 27 26 " +"29 30 31 30 29 28 33 35 31 35 33 " +"40 33 31 30 34 37 32 48 42 51 " +"36 40 33 40 36 48 38 44 41 44 38 " +"37 32 37 38 48 39 42 36 39 48 " +"54 53 47 45 51 42 49 43 52 50 41 " +"44 47 45 46 41 50 43 45 53 51 " +"49 54 47 53 45 47 49 55 54 55 49 " +"52 52 43 50 " +; + +char *VTK_VECTOR_TEXT_68 = (char *) "34 1.167232 " +"0.26286 -0.07186 0.70286 -0.07252 0.80000 -0.06109 0.89714 -0.03355 0.99555 0.02571 " +"0.40528 0.06000 0.72571 0.05891 1.03582 0.06571 0.79547 0.07143 0.88000 0.10893 " +"1.08150 0.12857 0.92115 0.14571 0.96657 0.21429 1.13966 0.26571 0.99470 0.28857 " +"1.16420 0.39714 1.01823 0.43714 1.16723 0.52857 1.01823 0.53429 1.15277 0.64286 " +"1.00000 0.65848 0.97714 0.72375 1.11216 0.77429 0.94286 0.78057 0.87429 0.84902 " +"1.06607 0.85429 0.81714 0.87865 0.40528 0.89429 0.69143 0.89807 0.97714 0.94616 " +"0.90857 0.98657 0.81143 1.01580 0.26286 1.02615 0.70286 1.02680 34 2 6 1 5 0 1 " +"8 3 9 3 8 2 0 27 32 6 2 " +"8 5 1 6 4 7 11 4 9 3 " +"9 4 11 11 10 12 11 7 10 13 14 " +"12 14 15 16 13 12 10 16 17 18 " +"14 13 15 18 19 20 17 16 15 18 17 " +"19 22 21 20 21 22 23 29 24 23 " +"22 20 19 26 24 30 0 5 27 25 23 " +"22 29 23 25 30 24 29 26 31 28 " +"31 26 30 33 32 27 28 33 27 33 28 " +"31 " +; + +char *VTK_VECTOR_TEXT_69 = (char *) "15 1.080000 " +"0.26857 -0.07186 1.08000 -0.06878 1.08000 0.05164 0.41100 0.06000 0.41100 0.42571 " +"1.01143 0.43100 1.01563 0.55143 0.41714 0.55866 1.01143 0.55757 0.40991 0.56857 " +"0.41100 0.89429 1.05143 0.89957 1.05563 1.02000 0.26857 1.02615 1.05143 1.02615 13 0 4 13 1 3 0 1 2 3 0 " +"3 4 7 5 8 5 7 4 6 8 5 4 9 13 7 9 4 9 10 13 11 " +"14 10 14 13 10 12 14 11 " +; + +char *VTK_VECTOR_TEXT_70 = (char *) "12 1.005714 " +"0.26857 -0.07186 0.40571 -0.07186 0.40991 0.42000 0.41714 0.42723 0.92615 0.43143 " +"0.92615 0.55143 0.41714 0.55563 0.40991 0.56286 0.41100 0.89429 1.00571 0.90265 " +"1.00571 1.02307 0.26857 1.02615 10 0 2 " +"11 2 7 11 2 0 1 6 4 5 " +"4 6 3 3 6 2 7 2 6 7 8 " +"11 11 8 10 8 9 10 " +; + +char *VTK_VECTOR_TEXT_71 = (char *) "60 1.234286 " +"0.82286 -0.08966 0.65714 -0.07866 0.93143 -0.07335 0.56571 -0.05387 1.05143 -0.03355 " +"0.48000 -0.01514 1.12000 0.00073 0.74286 0.03866 0.83429 0.04177 0.38857 0.05044 " +"0.65143 0.05470 0.92571 0.06319 1.23260 0.07714 0.34857 0.09302 0.54286 0.10150 " +"1.03429 0.11229 0.50286 0.13044 1.09252 0.15714 0.44421 0.19714 0.27429 0.21629 " +"0.24252 0.31143 0.39320 0.31143 0.77714 0.36243 1.09143 0.35773 0.22748 0.39714 " +"0.37605 0.40286 0.77295 0.48286 0.77714 0.48900 1.23429 0.48900 0.22437 0.51143 " +"0.37295 0.51714 0.23320 0.59143 0.39748 0.65429 1.09143 0.68617 1.08571 0.69099 " +"0.42073 0.71714 1.21977 0.72286 0.27387 0.73429 1.06286 0.75301 0.30645 0.80286 " +"0.47616 0.80286 1.02286 0.82127 1.18498 0.82571 0.54286 0.86150 0.34857 0.86629 " +"0.94286 0.88371 1.14857 0.88793 0.61143 0.89580 0.86286 0.91184 0.40168 0.92286 " +"0.70857 0.91866 0.80000 0.92134 1.09714 0.94384 0.45714 0.96436 0.53714 1.00498 " +"1.00000 1.00371 0.93714 1.02613 0.62857 1.03252 0.73714 1.04705 0.84571 1.04395 58 0 7 1 14 5 3 5 14 " +"9 2 8 0 1 10 3 0 8 7 " +"8 2 11 18 13 9 17 6 12 10 1 " +"7 4 11 2 13 18 19 23 17 12 " +"15 6 17 4 6 15 16 9 14 11 4 " +"15 14 3 10 19 21 20 18 9 16 " +"30 31 29 23 27 22 25 24 20 22 27 " +"26 21 19 18 25 20 21 23 28 27 " +"28 23 12 29 24 25 30 29 25 31 32 " +"37 38 33 36 37 32 39 32 31 30 " +"35 39 32 34 33 38 39 40 44 38 46 " +"41 38 42 46 40 39 35 44 40 49 " +"53 43 54 43 49 40 42 38 36 43 47 " +"54 52 41 46 41 52 45 43 53 49 " +"54 47 57 50 57 47 45 56 48 55 45 " +"52 48 59 51 57 50 58 50 51 58 " +"56 45 55 58 51 59 59 48 56 " +; + +char *VTK_VECTOR_TEXT_72 = (char *) "16 1.125714 " +"0.26857 -0.07186 0.40571 -0.07186 0.98857 -0.07295 0.98286 -0.06878 1.12571 -0.06878 " +"0.40991 0.43714 0.41714 0.44437 0.97714 0.44329 0.41714 0.57277 0.97714 0.57385 " +"0.40991 0.58000 0.98550 1.02571 1.12571 1.02307 0.26857 1.02615 0.40571 1.02615 " +"1.12000 1.02723 14 4 9 7 0 5 13 5 10 13 " +"5 0 1 8 7 9 9 4 11 10 5 " +"8 6 8 5 4 3 2 7 8 6 " +"14 13 10 12 15 11 3 4 7 4 12 " +"11 " +; + +char *VTK_VECTOR_TEXT_73 = (char *) "4 0.428571 " +"0.42592 -0.07143 0.28571 -0.06878 0.28836 1.02571 0.42857 1.02307 2 1 3 2 3 1 0 " +; + +char *VTK_VECTOR_TEXT_74 = (char *) "27 0.790089 " +"0.45143 -0.09009 0.50857 -0.09009 0.37714 -0.07756 0.58404 -0.07714 0.33143 -0.06086 " +"0.64000 -0.05641 0.26489 -0.01429 0.71429 -0.00117 0.46286 0.03866 0.53714 0.04706 " +"0.74902 0.04857 0.41714 0.04899 0.57772 0.06571 0.21143 0.06772 0.37016 0.07714 " +"0.34498 0.11143 0.77252 0.11143 0.62371 0.11714 0.18705 0.16286 0.32462 0.17429 " +"0.64420 0.22571 0.79009 0.23143 0.18546 0.23714 0.31472 0.25429 0.64836 1.02571 " +"0.78857 1.02307 0.78286 1.02723 25 10 " +"12 7 4 2 11 0 1 8 3 8 1 11 2 8 0 8 2 8 3 9 9 " +"3 12 4 14 6 7 12 5 3 5 12 6 15 13 12 10 17 14 4 11 13 " +"19 18 6 14 15 22 19 23 17 16 20 13 15 19 16 17 10 22 18 19 21 " +"20 16 20 21 24 25 26 24 21 25 24 " +; + +char *VTK_VECTOR_TEXT_75 = (char *) "17 1.155019 " +"0.25714 -0.07186 0.39429 -0.07186 1.15502 -0.07143 0.97143 -0.07140 0.89527 0.28857 " +"0.89143 0.29371 0.89098 0.29429 0.39848 0.30000 0.57714 0.47913 0.40000 0.49126 " +"0.68956 0.56857 0.68571 0.57371 0.68527 0.57429 1.13216 1.02571 0.25714 1.02615 " +"0.39429 1.02615 0.94857 1.02680 15 0 9 14 0 7 9 3 10 8 3 6 10 9 8 16 4 5 6 7 " +"0 1 3 4 6 16 8 12 10 11 12 4 3 2 8 10 12 9 7 8 13 " +"16 12 15 14 9 " +; + +char *VTK_VECTOR_TEXT_76 = (char *) "7 0.941339 " +"0.25714 -0.07186 0.93714 -0.07186 0.94134 0.04857 0.39957 0.06000 0.93714 0.05472 " +"0.25714 1.02615 0.39429 1.02615 5 3 0 1 0 3 5 2 4 1 3 1 4 6 5 3 " +; + +char *VTK_VECTOR_TEXT_77 = (char *) "19 1.302857 " +"0.39164 -0.07143 0.71429 -0.07186 1.17143 -0.07295 0.25714 -0.06878 0.84000 -0.06947 " +"1.16571 -0.06878 1.30286 -0.06878 0.78286 0.09751 0.78857 0.09751 1.16000 0.83018 " +"0.40000 0.84467 0.52151 0.88286 0.52000 0.88739 0.51748 0.89429 0.47580 1.02000 " +"0.25979 1.02571 1.11429 1.02285 1.30286 1.02307 0.46857 1.02680 17 3 10 15 5 6 9 6 " +"5 2 1 11 10 4 8 1 1 7 11 9 16 8 1 8 7 9 8 4 10 " +"18 15 13 11 12 10 3 0 10 13 18 16 9 17 10 11 13 13 14 18 6 " +"17 9 " +; + +char *VTK_VECTOR_TEXT_78 = (char *) "14 1.125714 " +"0.26286 -0.07186 0.39429 -0.07186 0.98286 -0.07295 1.12571 -0.06878 0.98286 0.17231 " +"0.72045 0.31143 0.71678 0.31714 0.72000 0.31207 0.40000 0.78092 0.99122 1.02571 " +"1.12571 1.02307 0.26286 1.02615 0.40571 1.02644 1.12000 1.02723 12 " +"0 8 11 8 0 1 4 3 9 3 4 " +"2 4 5 2 6 7 5 12 6 4 " +"4 6 5 6 12 8 10 13 9 8 12 " +"11 3 10 9 " +; + +char *VTK_VECTOR_TEXT_79 = (char *) "63 1.267054 " +"0.70286 -0.08966 0.77714 -0.08966 0.61143 -0.07605 0.89714 -0.06823 0.97143 -0.04073 " +"0.49143 -0.03229 1.05650 0.00857 0.42286 0.01107 0.70857 0.03605 0.77143 0.03605 " +"0.63429 0.04899 0.84571 0.04899 1.12725 0.07143 0.35044 0.07714 0.92716 0.08286 " +"0.54857 0.08535 0.49143 0.12704 1.17465 0.13429 1.01296 0.15143 0.28571 0.17016 " +"0.43955 0.18571 1.21184 0.20286 0.40784 0.23714 1.08086 0.26000 1.24613 0.30000 " +"0.23109 0.31143 1.10665 0.34571 0.36764 0.36857 0.21295 0.43143 1.11848 0.43714 " +"1.26705 0.43714 0.36193 0.51143 1.11848 0.51714 0.21563 0.54571 0.36991 0.59143 " +"1.25522 0.61429 1.09966 0.63714 0.23236 0.64857 1.23681 0.68857 1.07070 0.71714 " +"0.41143 0.73016 0.26645 0.75143 1.20486 0.76857 0.45561 0.79714 1.02286 0.79270 " +"0.98857 0.82956 0.31429 0.83650 1.16045 0.84286 0.53143 0.86150 0.92000 0.87800 " +"0.35582 0.88857 0.63429 0.90764 0.85143 0.90613 1.10286 0.90956 0.71429 0.92134 " +"0.79429 0.91866 0.43493 0.95714 1.04000 0.95964 0.52000 1.00498 0.96000 1.00327 " +"0.89714 1.02613 0.63429 1.03866 0.77714 1.04705 63 0 8 2 1 9 0 8 10 2 2 10 5 9 1 11 5 " +"16 7 11 3 14 3 11 1 3 4 14 6 14 4 7 16 13 10 15 5 0 " +"9 8 16 5 15 14 6 18 13 20 19 12 18 6 18 17 23 17 21 23 20 " +"22 19 18 12 17 23 21 26 25 19 22 13 16 20 25 27 28 27 25 22 21 " +"24 26 30 29 26 32 35 36 30 26 24 33 34 37 32 29 30 28 31 33 31 " +"28 27 34 33 31 36 38 39 35 32 30 41 37 34 38 42 39 41 40 46 35 " +"38 36 39 47 44 40 43 46 53 45 44 46 43 50 45 57 49 40 41 34 56 " +"50 43 49 59 52 48 56 43 57 45 53 53 44 47 56 48 58 39 42 47 58 " +"51 61 59 49 57 51 58 48 55 52 60 62 54 55 59 60 52 61 54 62 54 " +"61 51 62 55 60 " +; + +char *VTK_VECTOR_TEXT_80 = (char *) "31 1.098661 " +"0.26286 -0.07186 0.40000 -0.07186 0.40420 0.36857 0.41143 0.37580 0.73714 0.37621 " +"0.88571 0.40034 0.98343 0.44857 0.41143 0.50420 0.72571 0.50420 0.40420 0.51143 " +"1.04045 0.51143 0.82947 0.52286 0.88571 0.55296 0.91678 0.58571 1.08252 0.59714 " +"0.93966 0.63143 1.09866 0.68286 0.94966 0.72857 0.93355 0.79143 1.08530 0.80857 " +"0.90857 0.83270 0.86857 0.86893 1.05927 0.87143 0.40528 0.89429 0.82286 0.88899 " +"0.74857 0.89807 1.02439 0.92286 0.96000 0.97641 0.89143 1.00538 0.26286 1.02615 " +"0.74286 1.02680 31 0 9 29 0 2 9 2 7 9 7 3 8 12 11 5 5 11 4 4 " +"8 3 3 7 2 2 0 1 11 8 4 13 12 6 10 13 6 6 12 5 14 " +"15 10 15 14 17 13 10 15 16 17 14 17 19 18 19 17 16 18 19 20 20 " +"27 21 22 20 19 9 23 29 30 25 24 25 30 23 27 20 26 20 22 26 28 " +"24 21 28 21 27 30 29 23 30 24 28 " +; + +char *VTK_VECTOR_TEXT_81 = (char *) "66 1.276398 " +"1.23429 -0.15444 1.13714 -0.11188 0.76571 -0.09009 0.64571 -0.08437 0.84000 -0.08034 " +"0.58286 -0.07034 1.27640 -0.06000 0.93143 -0.05470 0.46857 -0.02322 1.00000 -0.02293 " +"0.38857 0.03330 0.76000 0.03563 0.68000 0.03866 0.83547 0.04857 1.09814 0.04857 " +"0.61714 0.05177 0.87591 0.06571 0.55429 0.07800 0.80000 0.10784 0.49143 0.12132 " +"0.30857 0.12350 0.74115 0.12857 0.98286 0.13189 1.17355 0.14571 0.42857 0.19207 " +"0.86857 0.19927 0.26286 0.20486 1.05355 0.22000 0.77714 0.23134 0.39277 0.26000 " +"1.23177 0.27714 0.23387 0.28286 1.08823 0.30571 0.36420 0.36286 0.20991 0.40286 " +"0.35580 0.43714 1.25866 0.43714 1.11009 0.44286 0.20723 0.51714 1.25252 0.58000 " +"0.36420 0.59714 1.09823 0.60857 0.23470 0.67714 0.38857 0.68947 1.21184 0.73429 " +"1.05143 0.73841 0.42902 0.76857 0.28821 0.80286 1.00571 0.80413 1.17188 0.81429 " +"0.96000 0.84670 0.51429 0.85473 0.34473 0.88286 1.12000 0.88413 0.57714 0.89070 " +"0.88571 0.89070 0.64571 0.91252 0.76571 0.92093 0.42857 0.95759 1.03429 0.95864 " +"0.50286 0.99927 0.96571 0.99800 0.60000 1.03252 0.86857 1.03184 0.69714 1.04705 " +"0.77143 1.04665 66 0 6 1 " +"13 7 16 14 9 1 9 16 7 3 15 " +"5 16 9 14 11 4 13 11 2 4 " +"7 13 4 12 3 11 2 11 3 15 3 " +"12 5 17 8 8 19 10 10 19 20 " +"14 1 6 5 15 17 20 29 26 19 8 " +"17 21 18 28 22 16 14 16 25 18 " +"22 14 27 24 20 19 16 22 25 26 29 " +"31 18 25 28 14 23 27 27 30 32 " +"30 27 23 31 33 34 20 24 29 37 32 " +"30 33 31 29 34 33 38 36 37 30 " +"35 38 33 37 39 41 38 40 42 37 36 " +"39 41 44 45 40 38 35 42 43 47 " +"44 41 39 46 47 43 43 42 40 47 46 " +"52 45 49 48 59 50 48 52 51 58 " +"53 48 49 61 50 59 50 61 55 58 51 " +"60 51 52 46 49 45 44 59 48 53 " +"57 64 56 60 54 62 55 63 57 51 54 " +"60 54 56 62 62 56 64 63 55 61 " +"63 65 57 57 65 64 " +; + +char *VTK_VECTOR_TEXT_82 = (char *) "46 1.225355 " +"0.26857 -0.07186 0.40571 -0.07186 1.05143 -0.07215 1.22359 -0.07143 1.22535 -0.06571 " +"1.17465 0.01429 1.17143 0.01936 1.17098 0.02000 0.84571 0.24343 1.00571 0.27650 " +"0.76571 0.34698 0.91832 0.37429 0.73143 0.37678 0.40991 0.40857 0.68000 0.40437 " +"0.41714 0.41580 0.62286 0.41538 0.84226 0.42571 0.92571 0.44706 0.99429 0.47502 " +"1.07582 0.54000 0.41714 0.54420 0.40991 0.55143 0.80000 0.54764 0.88000 0.56538 " +"1.11641 0.60286 0.94286 0.60439 0.96784 0.63714 1.13823 0.67714 0.98966 0.69429 " +"0.99277 0.74571 1.14134 0.75143 0.97143 0.81493 1.12823 0.82000 0.93143 0.86115 " +"1.10498 0.87714 0.89143 0.88498 0.40991 0.90000 0.41714 0.90723 0.78857 0.90723 " +"1.07011 0.92857 1.01714 0.97579 0.97143 0.99865 0.87429 1.02109 0.26857 1.02615 " +"0.80571 1.02723 46 2 9 8 3 5 2 0 37 " +"44 5 7 2 5 6 7 3 4 5 " +"2 7 9 18 23 17 11 8 9 8 11 " +"10 0 22 37 11 17 10 21 16 23 " +"21 15 16 23 10 17 19 24 18 23 18 " +"24 23 12 10 15 21 13 0 21 22 " +"16 14 23 23 14 12 20 26 19 26 20 " +"27 24 19 26 27 25 29 28 30 29 " +"31 30 28 25 27 20 30 33 32 28 29 " +"25 33 30 31 32 40 34 35 32 33 " +"0 1 13 0 13 21 41 34 40 43 36 " +"42 38 39 45 32 35 40 42 34 41 " +"34 42 36 36 43 39 44 38 45 43 45 " +"39 37 38 44 " +; + +char *VTK_VECTOR_TEXT_83 = (char *) "69 1.081090 " +"0.71429 -0.08966 0.53714 -0.07866 0.82286 -0.07101 0.46286 -0.05959 0.38857 -0.02616 " +"0.94286 -0.01678 0.33714 0.01044 0.64000 0.03866 0.73143 0.04177 1.00571 0.03883 " +"0.56000 0.05177 0.28527 0.06571 0.50857 0.06930 0.83587 0.07143 1.04086 0.08857 " +"0.88127 0.10000 0.43429 0.11330 0.24486 0.13429 0.92613 0.15714 1.07177 0.16286 " +"0.38771 0.16857 0.94134 0.21429 0.36319 0.22571 0.21563 0.23714 1.08109 0.26571 " +"0.21403 0.27714 0.93294 0.27714 0.34857 0.28916 0.91011 0.31714 1.06816 0.32857 " +"0.84000 0.36943 1.04486 0.38000 0.76571 0.39673 0.98286 0.45241 0.53143 0.45748 " +"0.42857 0.49343 0.92571 0.49070 0.37143 0.52535 0.82857 0.53109 0.31044 0.58000 " +"0.53143 0.60899 0.43429 0.65616 0.26244 0.67143 0.39891 0.71143 0.90857 0.71084 " +"0.25295 0.72286 1.04615 0.72286 0.39320 0.76857 0.40359 0.80857 1.03109 0.81429 " +"0.26327 0.82000 0.87429 0.81493 0.45143 0.86956 0.82286 0.87258 0.28930 0.88286 " +"0.98812 0.90000 0.50857 0.90041 0.76571 0.90151 0.57714 0.91563 0.67429 0.91866 " +"0.95443 0.94000 0.35429 0.96099 0.89143 0.98784 0.40000 0.99188 0.83429 1.01470 " +"0.50286 1.03184 0.74857 1.03823 0.57143 1.04437 0.67429 1.04705 67 2 " +"8 0 0 7 1 6 4 16 6 16 11 0 8 7 7 10 1 8 2 13 5 " +"15 13 1 10 3 10 12 3 9 15 5 4 3 12 15 14 18 5 13 2 14 " +"15 9 16 4 12 21 24 26 18 19 21 11 20 17 20 11 16 17 22 23 19 " +"18 14 22 17 20 25 23 27 23 22 27 24 21 19 26 31 28 28 33 30 24 " +"29 26 30 38 32 26 29 31 34 32 38 33 28 31 34 40 35 33 36 30 39 " +"43 42 38 30 36 41 37 35 40 34 38 37 41 39 41 35 40 50 48 54 39 " +"41 43 44 46 49 45 42 43 45 47 50 48 50 47 60 51 55 47 45 43 51 " +"60 53 54 48 61 44 49 51 55 51 49 48 52 61 56 63 52 57 66 59 61 " +"52 63 63 56 65 62 53 60 53 64 57 53 62 64 59 66 58 65 58 67 58 " +"65 56 66 57 64 67 58 68 68 58 66 " +; + +char *VTK_VECTOR_TEXT_84 = (char *) "8 1.045714 " +"0.54286 -0.07186 0.68000 -0.07186 0.53757 0.89429 0.68528 0.89429 0.17714 0.90265 " +"1.04571 0.90265 0.17979 1.02571 1.04571 1.02307 6 0 3 2 3 0 " +"1 6 4 2 6 3 7 6 2 3 " +"3 5 7 " +; + +char *VTK_VECTOR_TEXT_85 = (char *) "32 1.126804 " +"0.65714 -0.09009 0.77143 -0.08705 0.53143 -0.07034 0.85714 -0.07101 0.47429 -0.05070 " +"0.94286 -0.03629 0.38286 0.00704 1.02286 0.02445 0.65714 0.04437 0.78857 0.05320 " +"0.33669 0.06000 0.58286 0.05748 0.84000 0.06823 0.52000 0.08535 1.07070 0.08857 " +"0.89714 0.10154 0.46857 0.13025 1.09966 0.15714 0.29143 0.15866 0.94899 0.17429 " +"0.43177 0.19714 0.27320 0.24286 0.97252 0.26000 1.12680 0.33429 0.26437 0.34000 " +"0.40991 0.34000 0.98134 0.34571 0.98550 1.02571 1.12571 1.02307 0.26857 1.02615 " +"0.40571 1.02615 1.12000 1.02723 30 3 9 1 10 20 18 8 0 " +"1 0 11 2 7 15 5 0 8 11 " +"8 1 9 9 3 12 13 4 2 5 12 " +"3 15 7 19 16 10 6 12 5 15 " +"4 13 6 13 2 11 21 18 20 13 16 " +"6 19 17 22 17 19 14 7 14 19 " +"10 16 20 25 24 21 23 26 22 23 22 " +"17 25 21 20 24 25 29 30 29 25 " +"28 31 27 26 23 27 23 28 27 " +; + +char *VTK_VECTOR_TEXT_86 = (char *) "8 1.148571 " +"0.57714 -0.07025 0.72571 -0.06947 0.64571 0.06079 0.65143 0.06062 0.15429 1.02560 " +"0.30286 1.02531 1.00571 1.02531 1.14857 1.02560 6 0 2 4 3 2 " +"0 3 7 6 1 3 0 3 1 7 " +"2 5 4 " +; + +char *VTK_VECTOR_TEXT_87 = (char *) "14 1.568063 " +"0.45143 -0.07186 0.60000 -0.07017 1.13143 -0.06912 1.27429 -0.06912 0.52571 0.09707 " +"1.20000 0.09787 1.13673 0.38000 0.86857 0.88103 0.16571 1.02562 0.78286 1.02446 " +"1.42857 1.02446 1.56806 1.02571 0.30857 1.02615 0.95429 1.02615 12 " +"2 6 7 6 2 5 1 4 0 7 9 " +"4 11 10 5 3 5 2 8 0 4 " +"13 7 6 9 7 13 7 4 1 11 5 " +"3 12 8 4 " +; + +char *VTK_VECTOR_TEXT_88 = (char *) "14 1.141168 " +"0.15194 -0.07143 1.14117 -0.07143 0.32000 -0.07106 0.97143 -0.07140 0.65143 0.37795 " +"0.74607 0.49429 0.56517 0.50000 0.74286 0.49909 0.74219 0.50000 0.65714 0.61727 " +"0.20016 1.02571 0.96000 1.02568 1.11260 1.02571 0.36571 1.02644 12 " +"0 2 6 3 5 4 5 6 4 5 8 " +"6 5 3 1 5 7 8 4 6 2 " +"9 6 8 12 11 8 6 13 10 13 6 " +"9 11 9 8 " +; + +char *VTK_VECTOR_TEXT_89 = (char *) "12 1.145205 " +"0.71164 -0.07143 0.57143 -0.06878 0.56891 0.39143 0.71787 0.39714 0.65143 0.51441 " +"0.43179 0.85429 0.42857 0.85936 0.42812 0.86000 0.15284 1.02571 0.32000 1.02535 " +"0.98286 1.02464 1.14521 1.02571 10 3 2 " +"1 3 1 0 4 2 3 2 9 8 " +"11 10 4 5 2 4 5 6 7 2 7 " +"9 2 5 7 11 4 3 " +; + +char *VTK_VECTOR_TEXT_90 = (char *) "11 1.040000 " +"0.17714 -0.07186 1.04000 -0.06878 1.04000 0.05164 0.17395 0.06000 0.34602 0.06000 " +"0.84777 0.89429 0.24000 0.89957 1.02395 0.90000 0.23580 1.02000 1.02286 1.02307 " +"0.24000 1.02615 9 0 4 3 1 4 0 1 2 4 3 4 5 5 " +"7 9 4 7 5 5 10 6 10 5 9 6 10 8 " +; + +char *VTK_VECTOR_TEXT_91 = (char *) "8 0.541339 " +"0.24528 -0.37429 0.54025 -0.37429 0.54025 -0.27143 0.38227 -0.26571 0.38286 0.91454 " +"0.54134 0.92286 0.24836 1.02571 0.53714 1.02615 6 0 4 6 3 1 " +"2 1 3 0 0 3 4 5 7 4 " +"6 4 7 " +; + +char *VTK_VECTOR_TEXT_92 = (char *) "5 0.564685 " +"0.46286 -0.09182 0.56000 -0.09256 0.56469 -0.08857 0.14713 1.04286 0.24571 1.04358 3 0 4 3 0 2 4 0 " +"1 2 " +; + +char *VTK_VECTOR_TEXT_93 = (char *) "9 0.465968 " +"0.17100 -0.37429 0.46597 -0.37429 0.17100 -0.27143 0.32571 -0.26723 0.33295 -0.26000 " +"0.33143 0.91201 0.17143 0.91979 0.16991 1.02000 0.46286 1.02615 7 2 0 3 1 " +"3 0 1 4 3 5 4 1 7 6 8 5 8 6 8 5 1 " +; + +char *VTK_VECTOR_TEXT_94 = (char *) "11 0.817005 " +"0.18389 0.44857 0.18857 0.44458 0.32000 0.44686 0.68571 0.44746 0.81143 0.44445 " +"0.81700 0.44857 0.49714 0.88224 0.50286 0.88224 0.44571 1.04090 0.55429 1.04168 " +"0.45143 1.04437 9 0 2 6 0 6 8 7 3 5 4 5 3 2 " +"0 1 10 7 9 10 8 6 10 6 7 9 7 5 " +; + +char *VTK_VECTOR_TEXT_95 = (char *) "4 1.011860 " +"0.11957 -0.37429 1.01186 -0.37429 0.11957 -0.28857 1.01186 -0.28857 2 2 1 3 2 0 1 " +; + +char *VTK_VECTOR_TEXT_96 = (char *) "11 0.486571 " +"0.38857 0.82420 0.48000 0.82420 0.48403 0.82571 0.37714 0.82989 0.38286 0.82575 " +"0.48657 0.83143 0.21296 1.02571 0.38771 1.02571 0.21412 1.03143 0.38286 1.03106 " +"0.37714 1.03295 9 5 1 2 0 3 4 3 10 6 0 1 5 7 " +"3 0 8 6 10 7 0 5 3 7 10 10 7 9 " +; + +char *VTK_VECTOR_TEXT_97 = (char *) "70 0.929303 " +"0.44000 -0.09009 0.50286 -0.08966 0.36571 -0.07756 0.57143 -0.07907 0.92716 -0.07143 " +"0.79429 -0.07106 0.92930 -0.06571 0.62857 -0.06151 0.30857 -0.05514 0.27429 -0.03258 " +"0.68000 -0.03629 0.90748 -0.00857 0.48000 0.01580 0.53143 0.01621 0.42768 0.02571 " +"0.76571 0.02129 0.22073 0.03143 0.61804 0.03714 0.89866 0.03714 0.37130 0.06000 " +"0.20613 0.06571 0.68000 0.07330 0.34538 0.10000 0.71429 0.10809 0.19580 0.11714 " +"0.89295 0.13429 0.33907 0.15714 0.74538 0.16857 0.20319 0.19714 0.36000 0.20914 " +"0.75580 0.22000 0.40000 0.24371 0.22812 0.25429 0.44571 0.26041 0.66286 0.29891 " +"0.28000 0.31258 0.75848 0.31714 0.75429 0.32399 0.33714 0.34657 0.38857 0.36538 " +"0.68571 0.41320 0.75772 0.43714 0.35289 0.48286 0.22093 0.50000 0.22857 0.49470 " +"0.89252 0.50571 0.75580 0.51143 0.22857 0.53547 0.37800 0.54571 0.74286 0.55301 " +"0.88680 0.56286 0.71429 0.58893 0.41714 0.59330 0.42228 0.59714 0.25800 0.60286 " +"0.42286 0.59759 0.65143 0.61959 0.48000 0.62193 0.86498 0.62571 0.53143 0.62950 " +"0.59429 0.62950 0.28187 0.63714 0.84571 0.65486 0.33714 0.68436 0.80571 0.69007 " +"0.37915 0.70571 0.72571 0.72538 0.45714 0.72966 0.54286 0.74152 0.62286 0.74152 70 " +"3 13 1 5 4 15 4 11 15 19 8 " +"2 13 3 7 13 0 1 14 0 12 " +"20 22 24 0 14 2 12 0 13 13 7 " +"17 11 4 6 19 2 14 17 10 21 " +"7 10 17 11 18 15 16 22 20 8 19 " +"9 15 23 21 15 21 10 23 25 27 " +"9 19 16 19 22 16 23 15 25 24 26 " +"28 27 25 30 25 15 18 30 25 36 " +"32 28 26 26 24 22 29 32 26 39 38 " +"31 38 35 29 32 29 35 31 38 29 " +"39 34 40 33 39 31 39 33 34 36 41 " +"37 40 37 41 37 40 34 41 36 25 " +"41 45 46 43 44 47 47 48 54 48 47 " +"44 50 49 46 41 25 45 50 46 45 " +"42 48 44 49 64 51 52 53 55 52 65 " +"63 65 52 55 52 61 48 52 63 61 " +"58 49 50 49 58 62 69 60 56 49 62 " +"64 54 48 61 57 67 65 57 65 55 " +"51 66 56 69 59 60 66 51 64 68 67 " +"57 59 69 57 69 68 57 69 56 66 " +; + +char *VTK_VECTOR_TEXT_98 = (char *) "49 0.932518 " +"0.61143 -0.09009 0.50286 -0.07823 0.36000 -0.07186 0.24000 -0.06878 0.72000 -0.06213 " +"0.45714 -0.05914 0.77143 -0.03188 0.36571 0.01806 0.59429 0.02193 0.83543 0.02571 " +"0.52000 0.02823 0.66857 0.04645 0.46857 0.05179 0.42704 0.08857 0.72956 0.10000 " +"0.88784 0.10571 0.39216 0.14000 0.75641 0.14000 0.91470 0.18000 0.37462 0.19143 " +"0.78665 0.23714 0.36152 0.28857 0.93252 0.29429 0.79236 0.36857 0.93252 0.37429 " +"0.36420 0.38000 0.77294 0.47714 0.39216 0.50000 0.90899 0.50000 0.42473 0.55143 " +"0.73143 0.55546 0.88657 0.55714 0.45883 0.58571 0.67429 0.60498 0.50857 0.61641 " +"0.63429 0.62252 0.56571 0.62991 0.37714 0.64118 0.83429 0.63841 0.37315 0.64857 " +"0.80571 0.66686 0.74286 0.70784 0.46857 0.71355 0.68571 0.72899 0.56571 0.74109 " +"0.61714 0.74152 0.24265 1.02571 0.37143 1.02307 0.36571 1.02723 49 3 25 46 5 1 10 5 12 7 8 0 4 11 6 14 11 " +"4 6 0 8 1 2 7 3 8 4 11 10 1 8 21 3 19 12 13 7 12 " +"5 10 14 9 17 9 14 6 17 15 20 16 7 13 15 18 20 15 17 9 3 " +"7 19 22 20 18 20 22 23 28 26 23 22 24 23 25 3 21 30 43 33 39 " +"46 25 28 23 24 27 39 25 26 31 30 7 16 19 31 26 28 37 32 42 39 " +"27 37 40 30 38 29 37 27 38 30 31 35 33 43 32 34 42 35 45 36 37 " +"29 32 42 34 36 45 35 43 43 30 41 41 30 40 36 45 44 42 36 44 47 " +"48 46 39 47 46 " +; + +char *VTK_VECTOR_TEXT_99 = (char *) "58 0.894057 " +"0.53143 -0.08966 0.59429 -0.08966 0.45714 -0.07673 0.68000 -0.07294 0.72571 -0.05343 " +"0.37714 -0.04331 0.33714 -0.01543 0.78857 -0.01011 0.58286 0.02152 0.29143 0.03016 " +"0.49625 0.03143 0.62857 0.03034 0.83107 0.03714 0.45714 0.04943 0.69270 0.06571 " +"0.26241 0.07143 0.85714 0.07873 0.40457 0.09429 0.72722 0.10571 0.37629 0.14000 " +"0.74437 0.14000 0.22899 0.14571 0.37184 0.15143 0.36930 0.15714 0.88571 0.15295 " +"0.89406 0.19714 0.76571 0.21540 0.21034 0.22571 0.34705 0.25429 0.20420 0.36286 " +"0.34478 0.36857 0.21673 0.45429 0.36252 0.47143 0.75429 0.47269 0.88058 0.48857 " +"0.88319 0.49429 0.38371 0.52286 0.23849 0.52857 0.72000 0.55200 0.86437 0.55714 " +"0.43025 0.58000 0.69714 0.58127 0.28527 0.61429 0.47429 0.60943 0.48571 0.61387 " +"0.83473 0.61429 0.49143 0.61641 0.63429 0.62041 0.54857 0.62950 0.58857 0.62991 " +"0.81296 0.64286 0.32168 0.65429 0.35429 0.67964 0.76571 0.68535 0.44571 0.72327 " +"0.67429 0.72816 0.53714 0.74109 0.60000 0.74109 56 2 13 5 0 8 2 11 4 14 " +"1 8 0 3 11 1 15 23 21 2 10 " +"13 11 8 1 11 3 4 7 14 4 " +"10 2 8 14 7 18 17 6 13 6 5 " +"13 17 15 9 18 12 20 7 12 18 " +"17 9 6 16 20 12 24 20 16 19 15 " +"17 15 19 23 23 19 22 27 28 29 " +"26 20 24 26 24 25 21 28 27 28 21 " +"23 29 30 31 28 30 29 31 32 37 " +"39 38 33 34 39 33 32 31 30 37 32 " +"36 55 49 47 37 36 42 51 42 36 " +"34 35 39 45 41 38 52 40 43 46 43 " +"44 50 41 45 56 49 57 40 51 36 " +"51 40 52 45 38 39 52 43 54 47 41 " +"53 54 46 48 56 48 49 53 41 50 " +"54 48 56 54 43 46 57 49 55 55 47 " +"53 " +; + +char *VTK_VECTOR_TEXT_100 = (char *) "48 0.885714 " +"0.51429 -0.09009 0.56571 -0.08966 0.62857 -0.07673 0.76571 -0.07186 0.88571 -0.06878 " +"0.41143 -0.06486 0.67429 -0.05641 0.36000 -0.03669 0.30286 0.01025 0.76000 0.01806 " +"0.53714 0.02152 0.49714 0.02891 0.60571 0.02891 0.68127 0.07143 0.41714 0.07561 " +"0.23787 0.10571 0.71579 0.11143 0.38241 0.11714 0.74135 0.16286 0.21395 0.16857 " +"0.74286 0.16739 0.74538 0.17429 0.34605 0.20286 0.76420 0.27714 0.19277 0.28857 " +"0.33295 0.28857 0.19277 0.36286 0.76152 0.38571 0.33563 0.39714 0.73355 0.50000 " +"0.22135 0.51143 0.36784 0.51714 0.69714 0.55841 0.42286 0.58686 0.26857 0.60793 " +"0.63429 0.60943 0.48571 0.62151 0.56571 0.62950 0.74857 0.64048 0.75269 0.64857 " +"0.30857 0.65582 0.65714 0.71355 0.40571 0.71756 0.50286 0.74109 0.55429 0.74152 " +"0.75693 1.02571 0.88571 1.02307 0.88000 1.02723 48 0 11 5 12 6 13 " +"1 2 12 7 14 8 10 0 1 14 7 " +"5 10 1 12 6 12 2 0 10 11 " +"8 17 15 9 16 13 14 5 11 4 9 " +"3 6 9 13 9 4 18 16 9 18 " +"15 22 19 17 8 14 22 15 17 20 18 " +"21 21 18 4 19 25 24 21 4 23 " +"25 19 22 26 24 25 26 28 30 39 27 " +"4 26 25 28 39 38 29 29 38 32 " +"27 39 29 30 31 34 32 38 35 31 30 " +"28 40 34 31 36 42 33 23 4 27 " +"35 41 37 33 40 31 40 33 42 41 35 " +"38 42 36 43 37 43 36 44 37 41 " +"37 44 43 46 47 45 39 4 45 4 46 " +"45 " +; + +char *VTK_VECTOR_TEXT_101 = (char *) "65 0.934539 " +"0.54857 -0.09009 0.61143 -0.09009 0.45714 -0.07462 0.71429 -0.07101 0.40571 -0.05641 " +"0.77714 -0.04331 0.33714 -0.01543 0.82857 -0.00670 0.29714 0.02154 0.56000 0.02152 " +"0.60571 0.02193 0.49714 0.03563 0.68159 0.04286 0.88150 0.05429 0.45714 0.05514 " +"0.26286 0.06636 0.72000 0.06759 0.40457 0.10000 0.91216 0.11143 0.77229 0.13429 " +"0.37057 0.15143 0.22034 0.15714 0.36613 0.16286 0.92834 0.16286 0.36359 0.16857 " +"0.91429 0.16966 0.79429 0.18111 0.35177 0.20286 0.20462 0.22571 0.33866 0.28286 " +"0.34286 0.28900 0.93454 0.29429 0.19848 0.35714 0.93295 0.39714 0.34857 0.40134 " +"0.78857 0.40134 0.34134 0.40857 0.79580 0.40857 0.20462 0.41429 0.35429 0.47261 " +"0.22327 0.49429 0.91429 0.48975 0.77143 0.50661 0.38857 0.54057 0.74857 0.54629 " +"0.40725 0.56286 0.25714 0.57001 0.71429 0.58154 0.87070 0.58571 0.45143 0.59759 " +"0.68000 0.60498 0.29296 0.62000 0.49143 0.61681 0.63429 0.62252 0.54857 0.62950 " +"0.59429 0.62991 0.33311 0.66000 0.81143 0.65543 0.77143 0.68607 0.41143 0.70930 " +"0.72000 0.71355 0.45714 0.72605 0.66857 0.73050 0.54286 0.74152 0.60000 0.74152 65 0 9 11 10 " +"1 3 10 3 12 5 12 3 17 8 6 10 0 1 0 11 2 4 14 6 0 " +"10 9 7 16 5 5 16 12 14 2 11 16 7 19 14 4 2 15 8 17 26 " +"18 25 17 6 14 15 27 21 7 13 19 23 25 18 20 15 17 26 19 18 18 " +"19 13 24 20 22 15 20 24 15 24 27 21 27 28 28 29 32 33 37 35 29 " +"28 27 32 29 38 35 34 30 40 39 46 33 35 30 31 33 30 36 38 29 36 " +"29 34 37 41 42 40 38 36 30 34 29 39 40 36 41 37 33 46 43 51 51 " +"49 56 42 48 44 48 42 41 44 48 47 49 51 45 43 46 39 56 49 59 50 " +"62 53 57 47 48 64 55 53 45 51 43 55 63 54 58 47 57 62 50 60 59 " +"52 61 59 49 52 47 60 50 61 54 63 60 47 58 61 52 54 64 53 62 55 " +"64 63 " +; + +char *VTK_VECTOR_TEXT_102 = (char *) "24 0.617143 " +"0.28000 -0.07186 0.40571 -0.07186 0.27472 0.61429 0.41100 0.61429 0.16571 0.61957 " +"0.56000 0.61957 0.56420 0.71714 0.16571 0.72329 0.27472 0.72857 0.41100 0.72857 " +"0.56000 0.72329 0.41034 0.83143 0.27580 0.86000 0.43429 0.89555 0.28613 0.91714 " +"0.46286 0.91294 0.50286 0.92134 0.60000 0.91830 0.31107 0.96857 0.34286 1.00099 " +"0.38857 1.02784 0.61714 1.03086 0.46286 1.04395 0.52571 1.04437 22 0 3 2 " +"3 0 1 4 8 7 9 3 5 2 3 " +"8 5 6 10 4 2 8 9 8 3 " +"8 11 12 11 8 9 12 11 14 9 5 " +"10 13 19 18 13 18 14 13 14 11 " +"23 15 16 15 23 22 21 23 17 15 20 " +"13 19 13 20 20 15 22 23 16 17 " +; + +char *VTK_VECTOR_TEXT_103 = (char *) "71 0.892518 " +"0.46857 -0.39295 0.56571 -0.39563 0.66286 -0.37959 0.35429 -0.36200 0.74286 -0.34616 " +"0.28571 -0.31868 0.80368 -0.30000 0.50857 -0.28437 0.62286 -0.27395 0.44571 -0.27101 " +"0.23387 -0.24286 0.84657 -0.24286 0.69200 -0.23714 0.38171 -0.23143 0.72150 -0.20286 " +"0.87177 -0.18000 0.34916 -0.15714 0.74899 -0.14000 0.22286 -0.13957 0.50857 -0.07295 " +"0.56000 -0.07295 0.43429 -0.05959 0.65143 -0.05070 0.37143 -0.03355 0.69714 -0.02527 " +"0.89252 -0.00857 0.74857 0.01873 0.75042 0.02000 0.75756 0.02000 0.75429 0.02333 " +"0.29143 0.03381 0.53143 0.03866 0.57143 0.03907 0.47429 0.05216 0.64000 0.05787 " +"0.41714 0.08704 0.68000 0.08439 0.23216 0.12857 0.38036 0.12857 0.72784 0.14000 " +"0.35277 0.18571 0.20530 0.20857 0.75538 0.20857 0.19320 0.28286 0.33295 0.29429 " +"0.76991 0.35714 0.19277 0.37429 0.33563 0.40857 0.75109 0.47143 0.35109 0.47714 " +"0.21143 0.47832 0.72784 0.52286 0.23787 0.55143 0.39044 0.55143 0.69868 0.56286 " +"0.66286 0.59393 0.27107 0.60857 0.45143 0.60498 0.48571 0.62041 0.56571 0.62991 " +"0.57714 0.62764 0.58286 0.62723 0.76571 0.63477 0.32000 0.66384 0.68571 0.70213 " +"0.39429 0.71229 0.77408 0.72286 0.88878 0.72286 0.62857 0.72816 0.46857 0.73580 " +"0.56000 0.74152 71 1 7 0 8 4 12 2 8 1 0 " +"9 3 7 1 8 5 13 10 9 0 7 13 5 3 8 2 4 6 14 12 6 " +"12 4 11 15 17 11 14 6 13 3 9 14 11 17 10 16 18 16 10 13 17 " +"25 28 23 21 33 22 32 20 32 19 20 35 23 33 19 31 21 23 35 30 31 " +"19 32 32 22 34 26 29 36 17 15 25 33 21 31 26 36 24 24 34 22 26 " +"27 29 36 34 24 36 29 39 30 38 37 39 28 25 39 29 28 37 40 41 38 " +"40 37 30 35 38 39 25 42 44 46 43 44 43 41 44 41 40 42 25 45 67 " +"51 48 46 47 50 67 48 45 47 46 44 50 49 52 49 50 47 67 62 51 62 " +"54 51 56 52 49 54 62 55 55 64 61 60 61 59 53 56 49 56 53 63 63 " +"57 65 65 58 69 65 57 58 70 59 61 59 69 58 64 55 62 67 45 25 67 " +"66 62 63 53 57 68 70 61 59 70 69 64 68 61 " +; + +char *VTK_VECTOR_TEXT_104 = (char *) "27 0.889502 " +"0.24571 -0.07186 0.37143 -0.07186 0.76000 -0.07186 0.88571 -0.07186 0.37605 0.40286 " +"0.37756 0.40857 0.75538 0.46000 0.88950 0.47714 0.38899 0.48286 0.74538 0.51714 " +"0.88152 0.54571 0.42439 0.55143 0.72000 0.56914 0.47429 0.59355 0.68000 0.60331 " +"0.85996 0.61429 0.53143 0.61748 0.61143 0.62379 0.37714 0.63983 0.81714 0.67296 " +"0.45714 0.70045 0.77714 0.70213 0.50857 0.72437 0.68571 0.73538 0.58857 0.74152 " +"0.24571 1.02615 0.37143 1.02615 25 0 " +"4 25 4 18 25 6 2 3 9 6 7 7 6 3 18 8 11 18 11 13 9 " +"15 12 12 19 14 10 9 7 18 13 20 8 4 5 15 9 10 4 0 1 18 " +"4 8 17 24 16 19 21 14 14 23 17 20 16 22 16 20 13 19 12 15 17 " +"23 24 23 14 21 24 22 16 18 26 25 " +; + +char *VTK_VECTOR_TEXT_105 = (char *) "8 0.377143 " +"0.25143 -0.07186 0.37714 -0.07186 0.25143 0.72329 0.37714 0.72329 0.25143 0.87403 " +"0.37714 0.87403 0.25143 1.02615 0.37714 1.02615 4 3 2 0 3 0 " +"1 4 5 6 7 6 5 " +; + +char *VTK_VECTOR_TEXT_106 = (char *) "18 0.375625 " +"0.14857 -0.39563 0.22286 -0.39252 0.07383 -0.38000 0.26857 -0.37914 0.31429 -0.34989 " +"0.34036 -0.31714 0.18857 -0.27462 0.10286 -0.26950 0.36109 -0.26571 0.22331 -0.24857 " +"0.37563 -0.16857 0.24152 -0.16286 0.24571 0.72329 0.37143 0.72329 0.24571 0.87403 " +"0.37143 0.87403 0.24571 1.02615 0.37143 1.02615 14 1 6 0 3 6 1 4 6 " +"3 9 10 11 7 0 6 7 2 0 " +"9 5 8 5 9 4 6 4 9 9 8 " +"10 11 10 12 13 12 10 14 15 16 " +"17 16 15 " +; + +char *VTK_VECTOR_TEXT_107 = (char *) "15 0.897876 " +"0.37450 -0.07143 0.89788 -0.07143 0.24571 -0.06878 0.73714 -0.07035 0.38004 0.24286 " +"0.68421 0.25429 0.68045 0.26000 0.68000 0.26064 0.46857 0.32924 0.38286 0.40888 " +"0.57152 0.42571 0.69714 0.72283 0.86359 0.72286 0.24836 1.02571 0.37714 1.02307 13 2 9 13 4 2 0 5 8 3 5 " +"3 1 5 6 7 9 14 13 11 9 10 5 7 8 7 10 8 8 9 4 12 " +"11 10 9 8 10 2 4 9 " +; + +char *VTK_VECTOR_TEXT_108 = (char *) "4 0.371429 " +"0.36878 -0.07143 0.24000 -0.06878 0.24265 1.02571 0.37143 1.02307 2 1 3 2 3 1 0 " +; + +char *VTK_VECTOR_TEXT_109 = (char *) "45 1.318074 " +"0.24571 -0.07186 0.37143 -0.07186 0.72000 -0.07295 1.18857 -0.07186 1.31429 -0.07186 " +"0.71429 -0.06878 0.84571 -0.06878 0.37866 0.37429 0.84723 0.40286 0.85335 0.46000 " +"0.39109 0.48286 0.71277 0.48286 1.18437 0.48286 1.31807 0.52286 0.87787 0.53429 " +"0.41143 0.53493 1.17395 0.54000 0.43582 0.56857 0.68784 0.56857 1.14857 0.58403 " +"0.93143 0.59188 0.66286 0.59829 0.82857 0.60801 0.51009 0.61429 0.36571 0.61924 " +"0.63429 0.61470 1.09714 0.61580 1.29355 0.62000 0.56000 0.62420 1.00571 0.62152 " +"1.06286 0.62379 0.41311 0.67143 0.78857 0.66975 1.25561 0.67714 0.90857 0.68902 " +"0.74286 0.70784 1.20571 0.71355 0.35735 0.72286 0.24571 0.72329 0.50286 0.72498 " +"0.99429 0.73109 1.16000 0.73109 0.67429 0.73470 0.57714 0.74109 1.05143 0.74152 43 6 5 2 0 7 38 8 11 5 7 0 1 8 5 6 12 3 4 12 " +"13 16 9 11 8 15 17 24 11 22 18 22 20 34 11 9 22 14 22 9 13 " +"12 4 24 17 31 7 10 38 10 15 24 16 27 19 32 21 18 24 37 38 20 " +"22 14 10 24 38 27 16 13 31 23 39 26 41 30 30 40 29 32 18 22 41 " +"19 36 34 29 40 19 41 26 36 19 33 23 31 17 35 21 32 29 34 20 39 " +"28 43 33 19 27 43 28 42 25 42 28 28 39 23 42 25 21 42 21 35 44 " +"30 41 30 44 40 " +; + +char *VTK_VECTOR_TEXT_110 = (char *) "38 0.889911 " +"0.24571 -0.07186 0.37143 -0.07186 0.75429 -0.07186 0.88571 -0.07186 0.24152 -0.06571 " +"0.37563 -0.06571 0.75009 -0.06571 0.88991 -0.06571 0.37605 0.40286 0.37866 0.41429 " +"0.38134 0.44857 0.74665 0.48286 0.88950 0.48286 0.39849 0.51143 0.73229 0.54000 " +"0.88420 0.54000 0.43011 0.56286 0.46286 0.58893 0.69714 0.58725 0.87008 0.59143 " +"0.51580 0.61429 0.65143 0.61343 0.36571 0.62031 0.56571 0.62420 0.60571 0.62379 " +"0.61714 0.62152 0.62286 0.62109 0.83955 0.64857 0.40725 0.66571 0.79429 0.69179 " +"0.45714 0.70213 0.24152 0.71714 0.75429 0.71355 0.35735 0.72286 0.24571 0.72329 " +"0.52571 0.73050 0.68571 0.73538 0.58857 0.74152 36 1 4 0 " +"3 6 2 1 5 4 3 7 6 6 12 " +"11 11 15 14 6 7 12 22 16 28 " +"10 8 9 13 22 10 10 22 8 8 4 " +"5 15 11 12 8 22 4 14 15 19 " +"14 19 18 25 26 24 16 22 13 16 17 " +"28 30 28 17 27 18 19 32 23 24 " +"29 18 27 30 20 35 18 32 21 31 4 " +"22 20 30 17 32 26 21 32 24 26 " +"32 18 29 34 31 33 33 31 22 35 23 " +"37 23 35 20 36 23 32 37 23 36 " +; + +char *VTK_VECTOR_TEXT_111 = (char *) "65 0.938661 " +"0.53143 -0.08966 0.59429 -0.09009 0.69143 -0.07101 0.41143 -0.06213 0.76571 -0.03759 " +"0.34857 -0.02821 0.81714 -0.00099 0.29143 0.02154 0.54286 0.02193 0.60571 0.02420 " +"0.50857 0.02823 0.64571 0.03563 0.86331 0.04857 0.45143 0.05216 0.25714 0.06636 " +"0.70857 0.07330 0.89229 0.09429 0.40000 0.09597 0.22771 0.12286 0.38036 0.12286 " +"0.37714 0.12793 0.37669 0.12857 0.75473 0.12857 0.76657 0.15143 0.77101 0.16286 " +"0.77355 0.16857 0.92319 0.18000 0.20764 0.18571 0.34816 0.19714 0.78605 0.20857 " +"0.33563 0.26000 0.19320 0.28286 0.93823 0.28857 0.79848 0.29429 0.33295 0.36286 " +"0.93866 0.37429 0.19580 0.39714 0.79538 0.39714 0.35277 0.47143 0.92319 0.47143 " +"0.21184 0.48286 0.77143 0.48947 0.23216 0.54000 0.38742 0.54000 0.89927 0.54000 " +"0.74286 0.54057 0.71429 0.57275 0.42286 0.57813 0.87678 0.58000 0.27429 0.60984 " +"0.48571 0.61580 0.64571 0.61580 0.54286 0.62950 0.58857 0.62950 0.60000 0.62723 " +"0.60571 0.62680 0.83225 0.63714 0.31025 0.64857 0.34857 0.67864 0.75429 0.69641 " +"0.40000 0.70784 0.45143 0.72605 0.68571 0.72538 0.53714 0.74152 0.60000 0.74109 65 11 4 15 8 " +"0 1 17 7 5 11 2 4 2 9 1 8 1 9 0 8 10 0 10 3 2 " +"11 9 3 13 5 10 13 3 6 12 22 6 15 4 15 6 22 18 28 27 17 " +"5 13 14 19 18 16 23 22 19 7 17 7 19 14 18 19 21 24 23 25 25 " +"23 16 19 20 21 16 22 12 26 29 25 27 30 31 26 25 16 28 18 21 29 " +"26 33 30 27 28 31 34 36 33 32 35 26 32 33 34 31 30 33 35 37 40 " +"36 34 37 39 41 40 38 42 39 37 35 47 57 43 38 40 34 43 49 42 46 " +"45 56 39 44 41 41 48 45 43 57 49 41 44 48 43 42 38 57 47 58 54 " +"55 53 56 45 48 50 60 47 64 63 53 64 55 62 53 63 52 59 62 51 61 " +"60 50 64 53 55 51 62 55 52 61 50 59 46 56 61 52 63 46 59 51 58 " +"47 60 " +; + +char *VTK_VECTOR_TEXT_112 = (char *) "49 0.935625 " +"0.24571 -0.37740 0.37454 -0.37429 0.56000 -0.08966 0.66857 -0.07966 0.47429 -0.06657 " +"0.75429 -0.04331 0.37584 -0.00286 0.80571 -0.00704 0.38286 0.00159 0.59429 0.02152 " +"0.52000 0.02891 0.63429 0.02992 0.85964 0.05429 0.45143 0.06725 0.70857 0.07330 " +"0.39787 0.13429 0.39514 0.14000 0.39216 0.14571 0.76213 0.14571 0.90538 0.14571 " +"0.37462 0.19714 0.78327 0.20857 0.92680 0.22571 0.36379 0.27143 0.36152 0.28286 " +"0.79580 0.29429 0.93563 0.30000 0.36379 0.36857 0.79580 0.36857 0.92680 0.43714 " +"0.78286 0.45547 0.38286 0.47232 0.75429 0.52921 0.41714 0.54057 0.88571 0.56444 " +"0.44571 0.57582 0.69143 0.59964 0.51429 0.62213 0.65143 0.62213 0.36571 0.63051 " +"0.56571 0.63563 0.82704 0.64857 0.45714 0.70784 0.74857 0.70657 0.24571 0.72329 " +"0.36000 0.72329 0.51429 0.73177 0.69143 0.72899 0.62286 0.74152 49 0 1 6 0 24 44 3 9 2 2 10 4 3 11 9 4 " +"13 8 10 2 9 11 5 14 11 3 5 7 14 5 4 10 13 14 12 18 14 " +"7 12 0 20 24 15 8 13 8 15 6 19 18 12 18 19 21 21 22 25 24 " +"27 44 17 15 16 22 21 19 28 25 26 22 26 25 6 15 17 29 30 28 23 " +"24 20 20 6 17 29 28 26 30 34 32 27 31 44 0 6 20 31 39 44 32 " +"41 36 41 32 34 31 33 39 42 37 46 39 35 42 34 30 29 39 33 35 38 " +"47 40 35 37 42 47 38 43 40 46 37 43 36 41 39 45 44 46 40 48 48 " +"40 47 38 36 43 " +; + +char *VTK_VECTOR_TEXT_113 = (char *) "52 0.885714 " +"0.76000 -0.37740 0.88571 -0.37740 0.56571 -0.09009 0.45143 -0.07673 0.65143 -0.06784 " +"0.36000 -0.03188 0.70857 -0.03465 0.75580 -0.00286 0.74857 0.00454 0.29714 0.02418 " +"0.54286 0.02152 0.57714 0.02193 0.58857 0.02420 0.59429 0.02462 0.47429 0.03927 " +"0.64571 0.04371 0.43302 0.06571 0.70670 0.09429 0.23914 0.11143 0.38607 0.11714 " +"0.38286 0.12221 0.38241 0.12286 0.75008 0.17429 0.21101 0.19143 0.34748 0.20857 " +"0.76723 0.25429 0.19848 0.26000 0.76723 0.27143 0.33605 0.28286 0.76991 0.28857 " +"0.19580 0.37429 0.33866 0.40286 0.75429 0.45277 0.21101 0.47143 0.35429 0.47832 " +"0.73143 0.51301 0.39846 0.56286 0.69296 0.56857 0.25669 0.58571 0.45143 0.60902 " +"0.61714 0.62213 0.49143 0.62723 0.76571 0.62602 0.29330 0.63714 0.56571 0.63522 " +"0.72403 0.67143 0.36571 0.69641 0.66286 0.71355 0.77408 0.72286 0.88571 0.72329 " +"0.44571 0.72966 0.56000 0.74152 52 29 27 25 " +"49 42 32 22 7 25 3 13 11 2 13 " +"3 4 13 2 6 15 4 11 13 12 " +"3 14 5 13 4 15 10 3 11 15 6 " +"8 14 3 10 15 8 17 24 23 18 " +"5 16 9 17 8 22 14 16 5 9 19 " +"18 19 20 21 18 19 21 42 35 32 " +"7 22 8 16 19 9 49 48 42 7 0 " +"1 24 18 21 23 24 26 26 28 30 " +"28 26 24 30 31 33 34 33 31 31 30 " +"28 33 34 38 49 29 25 36 43 38 " +"49 25 7 35 42 37 37 45 40 45 37 " +"42 29 49 32 45 47 40 39 43 36 " +"46 39 50 40 47 44 43 39 46 36 38 " +"34 41 44 51 41 50 39 49 7 1 " +"50 41 51 51 44 47 " +; + +char *VTK_VECTOR_TEXT_114 = (char *) "24 0.667686 " +"0.24571 -0.07186 0.37143 -0.07186 0.24152 -0.06571 0.37563 -0.06571 0.37563 0.38000 " +"0.39748 0.50000 0.41964 0.54571 0.44740 0.57429 0.61714 0.57787 0.62286 0.57880 " +"0.48000 0.59294 0.57714 0.59395 0.51429 0.60134 0.36571 0.61385 0.41868 0.68857 " +"0.66769 0.69429 0.66542 0.70000 0.24152 0.71714 0.35735 0.72286 0.24571 0.72329 " +"0.46286 0.72436 0.60000 0.73109 0.51429 0.74109 0.55429 0.74109 22 1 2 0 " +"1 3 2 4 2 3 5 6 13 5 13 " +"17 21 11 15 2 4 17 4 5 17 " +"6 7 13 18 17 13 7 10 14 13 7 " +"14 14 12 20 11 21 12 9 15 11 " +"12 14 10 19 17 18 20 12 22 8 9 " +"11 21 15 16 22 12 23 23 12 21 " +; + +char *VTK_VECTOR_TEXT_115 = (char *) "63 0.849502 " +"0.56000 -0.09009 0.46286 -0.08705 0.65143 -0.07395 0.37143 -0.06723 0.70444 -0.05429 " +"0.33143 -0.04943 0.76057 -0.02000 0.28571 -0.01813 0.79582 0.01429 0.50286 0.02152 " +"0.55429 0.02152 0.56571 0.02379 0.57714 0.02420 0.24571 0.02636 0.64000 0.04200 " +"0.41714 0.04371 0.22200 0.06571 0.38286 0.06725 0.68384 0.07714 0.83580 0.08286 " +"0.69927 0.10000 0.34200 0.12286 0.84950 0.14000 0.71009 0.15714 0.19109 0.16286 " +"0.19370 0.16857 0.32000 0.18615 0.69864 0.19143 0.84723 0.20286 0.65714 0.22784 " +"0.83641 0.24286 0.80956 0.28857 0.34286 0.32371 0.75429 0.33641 0.30286 0.34421 " +"0.69143 0.36327 0.25714 0.38445 0.22645 0.43714 0.41143 0.44538 0.37587 0.46571 " +"0.35885 0.48286 0.21295 0.49429 0.69143 0.50460 0.34478 0.51714 0.81977 0.52286 " +"0.67514 0.55143 0.35216 0.56286 0.22034 0.56857 0.64000 0.59465 0.38286 0.59829 " +"0.79429 0.61016 0.24000 0.61573 0.42857 0.62041 0.58286 0.62252 0.48571 0.62991 " +"0.74689 0.67143 0.28571 0.67258 0.70286 0.70045 0.33714 0.70613 0.38857 0.72538 " +"0.61714 0.73050 0.47429 0.74109 0.54286 0.74109 61 2 12 0 10 1 12 12 2 14 14 4 6 7 17 13 0 " +"12 1 4 14 2 11 10 12 15 3 1 3 15 5 9 1 10 14 6 18 15 " +"1 9 17 5 15 6 8 18 5 17 7 21 16 13 16 21 24 18 8 20 23 " +"28 27 21 13 17 19 22 23 26 25 21 21 25 24 20 19 23 19 20 8 28 " +"23 22 27 33 29 28 30 27 31 27 30 27 31 33 29 38 32 35 29 33 29 " +"35 38 34 38 36 32 38 34 36 40 37 39 36 38 41 43 47 43 41 37 36 " +"39 40 50 45 42 43 37 40 47 46 51 46 47 43 53 60 54 45 57 48 52 " +"58 49 45 55 57 51 49 56 49 51 46 50 42 44 48 57 53 56 49 58 55 " +"45 50 52 59 58 59 52 61 52 54 61 60 53 57 61 54 62 62 54 60 " +; + +char *VTK_VECTOR_TEXT_116 = (char *) "24 0.551972 " +"0.42286 -0.08395 0.48000 -0.08437 0.55197 -0.07143 0.33714 -0.05914 0.29901 -0.02571 " +"0.28041 0.00857 0.44571 0.04816 0.44453 0.04857 0.53714 0.04344 0.44000 0.05008 " +"0.41057 0.07714 0.26748 0.10000 0.40152 0.11714 0.26597 0.61429 0.40260 0.61429 " +"0.17143 0.61957 0.53450 0.62000 0.53866 0.71714 0.53450 0.72286 0.17143 0.72329 " +"0.26597 0.72857 0.40260 0.72857 0.26748 0.91714 0.40000 0.99545 22 10 5 4 " +"6 7 9 10 4 3 10 3 9 8 6 " +"1 6 9 1 5 10 11 8 1 2 " +"0 9 3 11 12 13 0 1 9 10 12 " +"11 17 18 16 14 13 12 21 14 16 " +"18 21 16 22 20 23 20 13 14 15 20 " +"19 15 13 20 20 14 21 23 20 21 " +; + +char *VTK_VECTOR_TEXT_117 = (char *) "38 0.884197 " +"0.48571 -0.09009 0.53714 -0.09009 0.41714 -0.07673 0.77143 -0.07295 0.88000 -0.07186 " +"0.63518 -0.06571 0.76571 -0.06878 0.88420 -0.06571 0.34857 -0.04771 0.70857 -0.01846 " +"0.29901 -0.00857 0.27429 0.02730 0.52000 0.02723 0.56000 0.02764 0.47339 0.03714 " +"0.76000 0.03684 0.61714 0.04135 0.43943 0.05429 0.65143 0.05787 0.41330 0.07714 " +"0.25143 0.08437 0.69143 0.08704 0.39343 0.10571 0.38899 0.11714 0.71473 0.11714 " +"0.38645 0.12286 0.73294 0.15714 0.23848 0.17429 0.37563 0.17429 0.75009 0.26000 " +"0.23848 0.71714 0.37295 0.71714 0.75009 0.71714 0.88420 0.71714 0.24265 0.72286 " +"0.36878 0.72286 0.75429 0.72329 0.88000 0.72329 36 6 3 15 " +"3 7 15 3 4 7 8 17 10 2 14 " +"17 2 17 8 5 13 1 19 11 10 " +"9 16 5 12 1 13 0 12 2 12 0 " +"1 9 18 16 13 5 16 14 2 12 " +"11 22 20 21 18 9 15 21 9 21 15 " +"24 20 28 27 11 19 22 24 7 26 " +"19 10 17 24 15 7 25 22 23 20 22 " +"25 20 25 28 26 7 29 31 30 27 " +"33 29 7 34 31 35 34 30 31 31 27 " +"28 36 33 37 32 29 33 36 32 33 " +; + +char *VTK_VECTOR_TEXT_118 = (char *) "12 0.884203 " +"0.45714 -0.06947 0.58857 -0.07103 0.52000 0.09808 0.52571 0.09808 0.47580 0.23714 " +"0.16151 0.71714 0.88420 0.71714 0.16427 0.72286 0.30286 0.71951 0.74857 0.72090 " +"0.88145 0.72286 0.29714 0.72395 10 4 0 " +"2 0 4 5 3 2 0 1 3 0 " +"3 6 9 8 11 5 9 6 10 7 5 " +"11 8 5 4 3 1 6 " +; + +char *VTK_VECTOR_TEXT_119 = (char *) "14 1.231638 " +"0.39429 -0.07215 0.52571 -0.07215 0.97714 -0.07252 0.84571 -0.06947 0.45714 0.10650 " +"0.46286 0.10650 0.92000 0.12073 0.69143 0.52785 0.15122 0.72286 0.28571 0.72090 " +"0.62857 0.72243 0.76193 0.72286 1.23164 0.72286 1.10857 0.72329 12 " +"2 6 3 0 4 8 3 6 7 5 0 " +"1 12 13 6 5 4 0 7 10 5 " +"11 10 7 7 5 1 11 7 6 4 9 " +"8 12 6 2 " +; + +char *VTK_VECTOR_TEXT_120 = (char *) "17 0.882498 " +"0.15697 -0.07143 0.88073 -0.07143 0.15473 -0.06571 0.31429 -0.07035 0.72571 -0.07140 " +"0.88250 -0.06571 0.52000 0.22529 0.52571 0.22529 0.60332 0.33429 0.43534 0.34000 " +"0.51429 0.45005 0.17188 0.71714 0.86812 0.71714 0.17412 0.72286 0.86588 0.72286 " +"0.32571 0.72395 0.71429 0.72395 15 1 5 4 2 6 9 8 6 7 3 2 0 4 8 7 6 2 3 4 " +"5 8 8 10 6 10 9 6 15 11 9 16 10 8 15 9 10 12 16 8 13 " +"11 15 16 12 14 " +; + +char *VTK_VECTOR_TEXT_121 = (char *) "16 0.888063 " +"0.34286 -0.39563 0.24000 -0.38043 0.41714 -0.37641 0.45714 -0.34956 0.50436 -0.29429 " +"0.32000 -0.26680 0.22286 -0.25766 0.36652 -0.25429 0.54371 -0.22000 0.41293 -0.21429 " +"0.46848 -0.07714 0.53714 0.09292 0.16998 0.72286 0.30857 0.71999 0.76000 0.72246 " +"0.88806 0.72286 14 2 7 0 0 5 1 5 0 7 " +"6 1 5 3 7 2 7 3 9 3 4 " +"9 9 8 10 9 4 8 10 11 12 " +"11 15 14 11 8 15 11 10 8 11 13 " +"12 " +; + +char *VTK_VECTOR_TEXT_122 = (char *) "17 0.872768 " +"0.17714 -0.07295 0.86857 -0.07186 0.17143 -0.06878 0.87277 -0.06571 0.17146 0.03714 " +"0.34212 0.03714 0.87277 0.03714 0.34132 0.04286 0.44000 0.04327 0.86857 0.04329 " +"0.20571 0.61689 0.67062 0.62000 0.84991 0.64286 0.20152 0.71714 0.84991 0.71714 " +"0.20571 0.72329 0.84571 0.72329 15 2 0 4 0 1 9 0 5 4 1 3 9 5 0 8 5 7 4 0 " +"9 8 3 6 9 12 14 11 11 14 16 11 16 10 12 11 7 11 4 7 10 " +"15 13 15 10 16 " +; + +char *VTK_VECTOR_TEXT_123 = (char *) "39 0.611429 " +"0.61143 -0.39454 0.46857 -0.38420 0.40000 -0.34154 0.61143 -0.27975 0.35748 -0.27143 " +"0.52000 -0.26992 0.47787 -0.23143 0.46748 -0.19143 0.34134 -0.18000 0.46395 0.04286 " +"0.33563 0.05429 0.45184 0.14571 0.32109 0.16286 0.29143 0.21832 0.42286 0.22716 " +"0.25143 0.24943 0.18857 0.26528 0.39429 0.26698 0.31413 0.32286 0.18857 0.38615 " +"0.25143 0.40073 0.41188 0.40286 0.29143 0.42775 0.43514 0.44286 0.32823 0.49429 " +"0.45866 0.52286 0.34134 0.60286 0.46705 0.80857 0.34478 0.84857 0.47748 0.87143 " +"0.35748 0.91143 0.50286 0.90821 0.50793 0.91143 0.50857 0.91188 0.61143 0.92814 " +"0.40571 0.99511 0.46857 1.03294 0.53143 1.04437 0.61143 1.04329 37 0 3 5 6 2 5 2 6 4 0 5 1 2 " +"1 5 4 7 8 7 4 6 8 9 10 10 11 12 9 8 7 11 10 9 12 " +"17 13 12 14 17 14 12 11 18 15 13 16 15 20 18 13 17 16 20 19 15 " +"18 20 21 22 18 22 21 24 22 20 18 24 25 26 23 24 21 25 24 23 26 " +"27 28 27 26 25 28 29 30 29 28 27 30 29 35 31 32 33 36 31 33 31 " +"36 29 36 33 37 34 38 37 35 29 36 34 37 33 " +; + +char *VTK_VECTOR_TEXT_124 = (char *) "4 0.388571 " +"0.28571 -0.39454 0.38857 -0.39563 0.28571 1.04329 0.38857 1.04437 2 3 2 0 3 0 1 " +; + +char *VTK_VECTOR_TEXT_125 = (char *) "35 0.606299 " +"0.17714 -0.39454 0.31429 -0.38613 0.39429 -0.33832 0.17714 -0.27975 0.27429 -0.26784 " +"0.43681 -0.26000 0.31070 -0.23714 0.44950 -0.19714 0.32723 -0.15714 0.45295 0.04857 " +"0.33295 0.11714 0.46857 0.16404 0.35387 0.19714 0.51429 0.23258 0.56000 0.25681 " +"0.39429 0.26403 0.60630 0.26571 0.47702 0.32857 0.41714 0.36742 0.60571 0.38615 " +"0.54857 0.39927 0.50171 0.43143 0.36086 0.43714 0.46748 0.50000 0.32991 0.56857 " +"0.45252 0.78571 0.32723 0.80286 0.31748 0.87143 0.29143 0.90893 0.43470 0.91714 " +"0.17714 0.92814 0.41629 0.95714 0.36571 1.01107 0.32000 1.03294 0.17714 1.04329 33 4 3 0 2 4 1 6 7 8 1 4 0 2 6 4 5 " +"6 2 6 5 7 8 9 10 9 8 7 10 11 12 15 13 17 11 10 9 12 " +"11 15 13 14 17 13 15 11 20 17 14 20 14 16 19 20 16 21 17 20 17 " +"21 18 22 23 24 22 18 21 23 22 21 25 26 24 25 24 23 29 27 26 29 " +"26 25 27 31 28 31 27 29 32 28 31 28 33 30 33 34 30 33 28 32 " +; + +char *VTK_VECTOR_TEXT_126 = (char *) "25 0.971429 " +"0.73714 0.34462 0.20759 0.35143 0.21143 0.34662 0.81143 0.34723 0.66857 0.35756 " +"0.86857 0.36135 0.25143 0.38115 0.90857 0.38086 0.52000 0.41580 0.32571 0.42723 " +"0.97140 0.43143 0.37143 0.43866 0.42286 0.44093 0.79429 0.49009 0.21028 0.50000 " +"0.72571 0.49681 0.86286 0.50930 0.25714 0.54115 0.92571 0.54759 0.32571 0.57470 " +"0.50286 0.57621 0.96571 0.58154 0.97143 0.58073 0.38857 0.58680 0.44000 0.58723 23 1 17 14 8 4 15 13 5 7 6 1 2 5 " +"13 3 1 6 17 3 13 0 16 10 18 15 4 0 13 7 16 15 0 13 8 " +"20 12 12 20 11 9 17 6 10 16 7 17 9 19 22 21 18 11 20 24 11 " +"19 9 20 8 15 11 24 23 22 18 10 11 23 19 " +; + + +// Construct object with no string set and backing enabled. +vtkVectorText::vtkVectorText() +{ + this->Text = NULL; + + this->Letters[33] = VTK_VECTOR_TEXT_33; + this->Letters[34] = VTK_VECTOR_TEXT_34; + this->Letters[35] = VTK_VECTOR_TEXT_35; + this->Letters[36] = VTK_VECTOR_TEXT_36; + this->Letters[37] = VTK_VECTOR_TEXT_37; + this->Letters[38] = VTK_VECTOR_TEXT_38; + this->Letters[39] = VTK_VECTOR_TEXT_39; + this->Letters[40] = VTK_VECTOR_TEXT_40; + this->Letters[41] = VTK_VECTOR_TEXT_41; + this->Letters[42] = VTK_VECTOR_TEXT_42; + this->Letters[43] = VTK_VECTOR_TEXT_43; + this->Letters[44] = VTK_VECTOR_TEXT_44; + this->Letters[45] = VTK_VECTOR_TEXT_45; + this->Letters[46] = VTK_VECTOR_TEXT_46; + this->Letters[47] = VTK_VECTOR_TEXT_47; + this->Letters[48] = VTK_VECTOR_TEXT_48; + this->Letters[49] = VTK_VECTOR_TEXT_49; + this->Letters[50] = VTK_VECTOR_TEXT_50; + this->Letters[51] = VTK_VECTOR_TEXT_51; + this->Letters[52] = VTK_VECTOR_TEXT_52; + this->Letters[53] = VTK_VECTOR_TEXT_53; + this->Letters[54] = VTK_VECTOR_TEXT_54; + this->Letters[55] = VTK_VECTOR_TEXT_55; + this->Letters[56] = VTK_VECTOR_TEXT_56; + this->Letters[57] = VTK_VECTOR_TEXT_57; + this->Letters[58] = VTK_VECTOR_TEXT_58; + this->Letters[59] = VTK_VECTOR_TEXT_59; + this->Letters[60] = VTK_VECTOR_TEXT_60; + this->Letters[61] = VTK_VECTOR_TEXT_61; + this->Letters[62] = VTK_VECTOR_TEXT_62; + this->Letters[63] = VTK_VECTOR_TEXT_63; + this->Letters[64] = VTK_VECTOR_TEXT_64; + this->Letters[65] = VTK_VECTOR_TEXT_65; + this->Letters[66] = VTK_VECTOR_TEXT_66; + this->Letters[67] = VTK_VECTOR_TEXT_67; + this->Letters[68] = VTK_VECTOR_TEXT_68; + this->Letters[69] = VTK_VECTOR_TEXT_69; + this->Letters[70] = VTK_VECTOR_TEXT_70; + this->Letters[71] = VTK_VECTOR_TEXT_71; + this->Letters[72] = VTK_VECTOR_TEXT_72; + this->Letters[73] = VTK_VECTOR_TEXT_73; + this->Letters[74] = VTK_VECTOR_TEXT_74; + this->Letters[75] = VTK_VECTOR_TEXT_75; + this->Letters[76] = VTK_VECTOR_TEXT_76; + this->Letters[77] = VTK_VECTOR_TEXT_77; + this->Letters[78] = VTK_VECTOR_TEXT_78; + this->Letters[79] = VTK_VECTOR_TEXT_79; + this->Letters[80] = VTK_VECTOR_TEXT_80; + this->Letters[81] = VTK_VECTOR_TEXT_81; + this->Letters[82] = VTK_VECTOR_TEXT_82; + this->Letters[83] = VTK_VECTOR_TEXT_83; + this->Letters[84] = VTK_VECTOR_TEXT_84; + this->Letters[85] = VTK_VECTOR_TEXT_85; + this->Letters[86] = VTK_VECTOR_TEXT_86; + this->Letters[87] = VTK_VECTOR_TEXT_87; + this->Letters[88] = VTK_VECTOR_TEXT_88; + this->Letters[89] = VTK_VECTOR_TEXT_89; + this->Letters[90] = VTK_VECTOR_TEXT_90; + this->Letters[91] = VTK_VECTOR_TEXT_91; + this->Letters[92] = VTK_VECTOR_TEXT_92; + this->Letters[93] = VTK_VECTOR_TEXT_93; + this->Letters[94] = VTK_VECTOR_TEXT_94; + this->Letters[95] = VTK_VECTOR_TEXT_95; + this->Letters[96] = VTK_VECTOR_TEXT_96; + this->Letters[97] = VTK_VECTOR_TEXT_97; + this->Letters[98] = VTK_VECTOR_TEXT_98; + this->Letters[99] = VTK_VECTOR_TEXT_99; + this->Letters[100] = VTK_VECTOR_TEXT_100; + this->Letters[101] = VTK_VECTOR_TEXT_101; + this->Letters[102] = VTK_VECTOR_TEXT_102; + this->Letters[103] = VTK_VECTOR_TEXT_103; + this->Letters[104] = VTK_VECTOR_TEXT_104; + this->Letters[105] = VTK_VECTOR_TEXT_105; + this->Letters[106] = VTK_VECTOR_TEXT_106; + this->Letters[107] = VTK_VECTOR_TEXT_107; + this->Letters[108] = VTK_VECTOR_TEXT_108; + this->Letters[109] = VTK_VECTOR_TEXT_109; + this->Letters[110] = VTK_VECTOR_TEXT_110; + this->Letters[111] = VTK_VECTOR_TEXT_111; + this->Letters[112] = VTK_VECTOR_TEXT_112; + this->Letters[113] = VTK_VECTOR_TEXT_113; + this->Letters[114] = VTK_VECTOR_TEXT_114; + this->Letters[115] = VTK_VECTOR_TEXT_115; + this->Letters[116] = VTK_VECTOR_TEXT_116; + this->Letters[117] = VTK_VECTOR_TEXT_117; + this->Letters[118] = VTK_VECTOR_TEXT_118; + this->Letters[119] = VTK_VECTOR_TEXT_119; + this->Letters[120] = VTK_VECTOR_TEXT_120; + this->Letters[121] = VTK_VECTOR_TEXT_121; + this->Letters[122] = VTK_VECTOR_TEXT_122; + this->Letters[123] = VTK_VECTOR_TEXT_123; + this->Letters[124] = VTK_VECTOR_TEXT_124; + this->Letters[125] = VTK_VECTOR_TEXT_125; + this->Letters[126] = VTK_VECTOR_TEXT_126; + + this->SetNumberOfInputPorts(0); +} + +int vtkVectorText::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *newPoints; + vtkCellArray *newPolys; + int ptOffset = 0; + int aPoint, i; + int pos = 0; + float xpos = 0; + float ypos = 0; + int ptCount, triCount; + char *aLetter; + float width; + float ftmp[3]; + + if (this->Text == NULL) + { + vtkErrorMacro (<< "Text is not set!"); + return 0; + } + + // Set things up; allocate memory + newPoints = vtkPoints::New(); + newPolys = vtkCellArray::New(); + ftmp[2] = 0.0; + + // Create Text + while (this->Text[pos]) + { + switch (this->Text[pos]) + { + case 32: + xpos += 0.4; + break; + + case 10: + ypos -= 1.4; + xpos = 0; + break; + + default: + // if we have a valid character + if ((this->Text[pos] > 32)&&(this->Text[pos] < 127)) + { + // add the result to our output + aLetter = this->Letters[static_cast(this->Text[pos])]; + ptCount = strtol(aLetter,&aLetter,10); + width = strtod(aLetter,&aLetter); + for (i = 0; i < ptCount; i++) + { + ftmp[0] = strtod(aLetter,&aLetter); + ftmp[1] = strtod(aLetter,&aLetter); + ftmp[0] += xpos; + ftmp[1] += ypos; + newPoints->InsertNextPoint(ftmp); + } + triCount = strtol(aLetter,&aLetter,10); + for (i = 0; i < triCount; i++) + { + newPolys->InsertNextCell(3); + aPoint = strtol(aLetter,&aLetter,10); + newPolys->InsertCellPoint(aPoint + ptOffset); + aPoint = strtol(aLetter,&aLetter,10); + newPolys->InsertCellPoint(aPoint + ptOffset); + aPoint = strtol(aLetter,&aLetter,10); + newPolys->InsertCellPoint(aPoint + ptOffset); + } + ptOffset += ptCount; + xpos += width; + } + break; + } + pos++; + } + + // + // Update ourselves and release memory + // + output->SetPoints(newPoints); + newPoints->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +void vtkVectorText::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Text: " << (this->Text ? this->Text : "(none)") << "\n"; +} + +vtkVectorText::~vtkVectorText() +{ + if (this->Text) + { + delete [] this->Text; + } +} diff --git a/Hybrid/vtkVectorText.h b/Hybrid/vtkVectorText.h new file mode 100644 index 0000000..4248a99 --- /dev/null +++ b/Hybrid/vtkVectorText.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVectorText.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVectorText - create polygonal text +// .SECTION Description + +// vtkVectorText generates vtkPolyData from an input text string. Besides the +// ASCII alphanumeric characters a-z, A-Z, 0-9, vtkVectorText also supports +// ASCII punctuation marks. (The supported ASCII character set are the codes +// (33-126) inclusive.) The only control character supported is the line feed +// character "\n", which advances to a new line. +// +// To use thie class, you normally couple it with a vtkPolyDataMapper and a +// vtkActor. In this case you would use the vtkActor's transformation methods +// to position, orient, and scale the text. You may also wish to use a +// vtkFollower to orient the text so that it always faces the camera. + +// .SECTION See Also +// vtkTextMapper vtkCaptionActor2D + +#ifndef __vtkVectorText_h +#define __vtkVectorText_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_HYBRID_EXPORT vtkVectorText : public vtkPolyDataAlgorithm +{ +public: + static vtkVectorText *New(); + vtkTypeRevisionMacro(vtkVectorText,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the text to be drawn. + vtkSetStringMacro(Text); + vtkGetStringMacro(Text); + +protected: + vtkVectorText(); + ~vtkVectorText(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + char *Text; + char *Letters[127]; + +private: + vtkVectorText(const vtkVectorText&); // Not implemented. + void operator=(const vtkVectorText&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkVideoSource.cxx b/Hybrid/vtkVideoSource.cxx new file mode 100644 index 0000000..5d7cc3a --- /dev/null +++ b/Hybrid/vtkVideoSource.cxx @@ -0,0 +1,1226 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVideoSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVideoSource.h" + +#include "vtkCriticalSection.h" +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkMultiThreader.h" +#include "vtkMutexLock.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTimerLog.h" +#include "vtkUnsignedCharArray.h" +#include "vtkWindows.h" + +#include +#include + +//--------------------------------------------------------------- +// Important FrameBufferMutex rules: +// +// The frame grabs are generally done asynchronously, and it is necessary +// to ensure that when the frame buffer is valid when it is being written +// to or read from +// +// The following information can only be changed within a mutex lock, +// and the lock must not be released until the frame buffer agrees with the +// information. +// +// FrameBuffer +// FrameBufferTimeStamps +// FrameBufferSize +// FrameBufferIndex +// FrameBufferExtent +// FrameBufferBitsPerPixel +// FrameBufferRowAlignment +// +// After one of the above has been changed, and before the mutex is released, +// the following must be called to update the frame buffer: +// +// UpdateFrameBuffer() +// +// Likewise, the following function must only be called from within a +// mutex lock because it modifies FrameBufferIndex: +// +// AdvanceFrameBuffer() +// +// Any methods which might be called asynchronously must lock the +// mutex before reading the above information, and you must be very +// careful when accessing any information except for the above. +// These methods include the following: +// +// InternalGrab() +// +// Finally, when Execute() is reading from the FrameBuffer it must do +// so from within a mutex lock. Otherwise tearing artifacts might result. + +vtkCxxRevisionMacro(vtkVideoSource, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkVideoSource); + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET +#pragma warning ( disable : 4311 ) +#pragma warning ( disable : 4312 ) +#endif + +//---------------------------------------------------------------------------- +vtkVideoSource::vtkVideoSource() +{ + int i; + + this->Initialized = 0; + + this->AutoAdvance = 1; + + this->FrameSize[0] = 320; + this->FrameSize[1] = 240; + this->FrameSize[2] = 1; + + for (i = 0; i < 6; i++) + { + this->FrameBufferExtent[i] = 0; + } + + this->Playing = 0; + this->Recording = 0; + + this->FrameRate = 30; + + this->FrameCount = 0; + this->FrameIndex = -1; + + this->StartTimeStamp = 0; + this->FrameTimeStamp = 0; + + this->OutputNeedsInitialization = 1; + + this->OutputFormat = VTK_LUMINANCE; + this->NumberOfScalarComponents = 1; + + this->NumberOfOutputFrames = 1; + + this->Opacity = 1.0; + + for (i = 0; i < 3; i++) + { + this->ClipRegion[i*2] = 0; + this->ClipRegion[i*2+1] = VTK_INT_MAX; + this->OutputWholeExtent[i*2] = 0; + this->OutputWholeExtent[i*2+1] = -1; + this->DataSpacing[i] = 1.0; + this->DataOrigin[i] = 0.0; + } + + for (i = 0; i < 6; i++) + { + this->LastOutputExtent[i] = 0; + } + this->LastNumberOfScalarComponents = 0; + + this->FlipFrames = 0; + + this->PlayerThreader = vtkMultiThreader::New(); + this->PlayerThreadId = -1; + + this->FrameBufferMutex = vtkCriticalSection::New(); + + this->FrameBufferSize = 0; + this->FrameBuffer = NULL; + this->FrameBufferTimeStamps = NULL; + this->FrameBufferIndex = 0; + this->SetFrameBufferSize(1); + + this->FrameBufferBitsPerPixel = 8; + this->FrameBufferRowAlignment = 1; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkVideoSource::~vtkVideoSource() +{ + // we certainly don't want to access a virtual + // function after the subclass has destructed!! + this->vtkVideoSource::ReleaseSystemResources(); + + this->SetFrameBufferSize(0); + this->FrameBufferMutex->Delete(); + this->PlayerThreader->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkVideoSource::PrintSelf(ostream& os, vtkIndent indent) +{ + int idx; + + this->Superclass::PrintSelf(os,indent); + + os << indent << "FrameSize: (" << this->FrameSize[0] << ", " + << this->FrameSize[1] << ", " << this->FrameSize[2] << ")\n"; + + os << indent << "ClipRegion: (" << this->ClipRegion[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << this->ClipRegion[idx]; + } + os << ")\n"; + + os << indent << "DataSpacing: (" << this->DataSpacing[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->DataSpacing[idx]; + } + os << ")\n"; + + os << indent << "DataOrigin: (" << this->DataOrigin[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->DataOrigin[idx]; + } + os << ")\n"; + + os << indent << "OutputFormat: " << + (this->OutputFormat == VTK_RGBA ? "RGBA" : + (this->OutputFormat == VTK_RGB ? "RGB" : + (this->OutputFormat == VTK_LUMINANCE_ALPHA ? "LuminanceAlpha" : + (this->OutputFormat == VTK_LUMINANCE ? "Luminance" : "Unknown")))) + << "\n"; + + os << indent << "OutputWholeExtent: (" << this->OutputWholeExtent[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << this->OutputWholeExtent[idx]; + } + os << ")\n"; + + os << indent << "FrameRate: " << this->FrameRate << "\n"; + + os << indent << "FrameCount: " << this->FrameCount << "\n"; + + os << indent << "FrameIndex: " << this->FrameIndex << "\n"; + + os << indent << "Recording: " << (this->Recording ? "On\n" : "Off\n"); + + os << indent << "Playing: " << (this->Playing ? "On\n" : "Off\n"); + + os << indent << "FrameBufferSize: " << this->FrameBufferSize << "\n"; + + os << indent << "NumberOfOutputFrames: " << this->NumberOfOutputFrames << "\n"; + os << indent << "AutoAdvance: " << (this->AutoAdvance ? "On\n" : "Off\n"); + + os << indent << "Opacity: " << this->Opacity << "\n"; + + os << indent << "FlipFrames: " << this->FlipFrames << "\n"; + + os << indent << "FrameBufferBitsPerPixel: " << this->FrameBufferBitsPerPixel << "\n"; + + os << indent << "FrameBufferRowAlignment: " << this->FrameBufferRowAlignment << "\n"; +} + +//---------------------------------------------------------------------------- +// Update the FrameBuffers according to any changes in the FrameBuffer* +// information. +// This function should always be called from within a FrameBufferMutex lock +// and should never be called asynchronously. +// It sets up the FrameBufferExtent +void vtkVideoSource::UpdateFrameBuffer() +{ + int i, oldExt; + int ext[3]; + vtkDataArray *buffer; + + // clip the ClipRegion with the FrameSize + for (i = 0; i < 3; i++) + { + oldExt = this->FrameBufferExtent[2*i+1] - this->FrameBufferExtent[2*i] + 1; + this->FrameBufferExtent[2*i] = ((this->ClipRegion[2*i] > 0) + ? this->ClipRegion[2*i] : 0); + this->FrameBufferExtent[2*i+1] = ((this->ClipRegion[2*i+1] < + this->FrameSize[i]-1) + ? this->ClipRegion[2*i+1] : this->FrameSize[i]-1); + + ext[i] = this->FrameBufferExtent[2*i+1] - this->FrameBufferExtent[2*i] + 1; + if (ext[i] < 0) + { + this->FrameBufferExtent[2*i] = 0; + this->FrameBufferExtent[2*i+1] = -1; + ext[i] = 0; + } + + if (oldExt > ext[i]) + { // dimensions of framebuffer changed + this->OutputNeedsInitialization = 1; + } + } + + // total number of bytes required for the framebuffer + int bytesPerRow = (ext[0]*this->FrameBufferBitsPerPixel+7)/8; + bytesPerRow = ((bytesPerRow + this->FrameBufferRowAlignment - 1) / + this->FrameBufferRowAlignment)*this->FrameBufferRowAlignment; + int totalSize = bytesPerRow * ext[1] * ext[2]; + + i = this->FrameBufferSize; + + while (--i >= 0) + { + buffer = reinterpret_cast(this->FrameBuffer[i]); + if (buffer->GetDataType() != VTK_UNSIGNED_CHAR || + buffer->GetNumberOfComponents() != 1 || + buffer->GetNumberOfTuples() != totalSize) + { + buffer->Delete(); + buffer = vtkUnsignedCharArray::New(); + this->FrameBuffer[i] = buffer; + buffer->SetNumberOfComponents(1); + buffer->SetNumberOfTuples(totalSize); + } + } +} + +//---------------------------------------------------------------------------- +// Initialize() should be overridden to initialize the hardware frame grabber +void vtkVideoSource::Initialize() +{ + if (this->Initialized) + { + return; + } + this->Initialized = 1; + + this->UpdateFrameBuffer(); +} + +//---------------------------------------------------------------------------- +// ReleaseSystemResources() should be overridden to release the hardware +void vtkVideoSource::ReleaseSystemResources() +{ + if (this->Playing || this->Recording) + { + this->Stop(); + } + + this->Initialized = 0; +} + +//---------------------------------------------------------------------------- +void vtkVideoSource::SetFrameSize(int x, int y, int z) +{ + if (x == this->FrameSize[0] && + y == this->FrameSize[1] && + z == this->FrameSize[2]) + { + return; + } + + if (x < 1 || y < 1 || z < 1) + { + vtkErrorMacro(<< "SetFrameSize: Illegal frame size"); + return; + } + + if (this->Initialized) + { + this->FrameBufferMutex->Lock(); + this->FrameSize[0] = x; + this->FrameSize[1] = y; + this->FrameSize[2] = z; + this->UpdateFrameBuffer(); + this->FrameBufferMutex->Unlock(); + } + else + { + this->FrameSize[0] = x; + this->FrameSize[1] = y; + this->FrameSize[2] = z; + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkVideoSource::SetFrameRate(float rate) +{ + if (this->FrameRate == rate) + { + return; + } + + this->FrameRate = rate; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkVideoSource::SetClipRegion(int x0, int x1, int y0, int y1, + int z0, int z1) +{ + if (this->ClipRegion[0] != x0 || this->ClipRegion[1] != x1 || + this->ClipRegion[2] != y0 || this->ClipRegion[3] != y1 || + this->ClipRegion[4] != z0 || this->ClipRegion[5] != z1) + { + this->Modified(); + if (this->Initialized) + { // modify the FrameBufferExtent + this->FrameBufferMutex->Lock(); + this->ClipRegion[0] = x0; this->ClipRegion[1] = x1; + this->ClipRegion[2] = y0; this->ClipRegion[3] = y1; + this->ClipRegion[4] = z0; this->ClipRegion[5] = z1; + this->UpdateFrameBuffer(); + this->FrameBufferMutex->Unlock(); + } + else + { + this->ClipRegion[0] = x0; this->ClipRegion[1] = x1; + this->ClipRegion[2] = y0; this->ClipRegion[3] = y1; + this->ClipRegion[4] = z0; this->ClipRegion[5] = z1; + } + } +} + +//---------------------------------------------------------------------------- +// Copy pseudo-random noise into the frames. This function may be called +// asynchronously. +void vtkVideoSource::InternalGrab() +{ + int i,index; + static int randsave = 0; + int randNum; + unsigned char *ptr; + int *lptr; + + // get a thread lock on the frame buffer + this->FrameBufferMutex->Lock(); + + if (this->AutoAdvance) + { + this->AdvanceFrameBuffer(1); + if (this->FrameIndex + 1 < this->FrameBufferSize) + { + this->FrameIndex++; + } + } + + index = this->FrameBufferIndex % this->FrameBufferSize; + while (index < 0) + { + index += this->FrameBufferSize; + } + + int bytesPerRow = ((this->FrameBufferExtent[1]-this->FrameBufferExtent[0]+1)* + this->FrameBufferBitsPerPixel + 7)/8; + bytesPerRow = ((bytesPerRow + this->FrameBufferRowAlignment - 1) / + this->FrameBufferRowAlignment)*this->FrameBufferRowAlignment; + int totalSize = bytesPerRow * + (this->FrameBufferExtent[3]-this->FrameBufferExtent[2]+1) * + (this->FrameBufferExtent[5]-this->FrameBufferExtent[4]+1); + + randNum = randsave; + + // copy 'noise' into the frame buffer + ptr = reinterpret_cast(this->FrameBuffer[index])->GetPointer(0); + + // Somebody should check this: + lptr = (int *)(((((long)ptr) + 3)/4)*4); + i = totalSize/4; + + while (--i >= 0) + { + randNum = 1664525*randNum + 1013904223; + *lptr++ = randNum; + } + unsigned char *ptr1 = ptr + 4; + i = (totalSize-4)/16; + while (--i >= 0) + { + randNum = 1664525*randNum + 1013904223; + *ptr1 = randNum; + ptr1 += 16; + } + randsave = randNum; + + this->FrameBufferTimeStamps[index] = vtkTimerLog::GetUniversalTime(); + + if (this->FrameCount++ == 0) + { + this->StartTimeStamp = this->FrameBufferTimeStamps[index]; + } + + this->Modified(); + + this->FrameBufferMutex->Unlock(); +} + +//---------------------------------------------------------------------------- +// platform-independent sleep function +static inline void vtkSleep(double duration) +{ + duration = duration; // avoid warnings + // sleep according to OS preference +#ifdef _WIN32 + Sleep((int)(1000*duration)); +#elif defined(__FreeBSD__) || defined(__linux__) || defined(sgi) + struct timespec sleep_time, dummy; + sleep_time.tv_sec = (int)duration; + sleep_time.tv_nsec = (int)(1000000000*(duration-sleep_time.tv_sec)); + nanosleep(&sleep_time,&dummy); +#endif +} + +//---------------------------------------------------------------------------- +// Sleep until the specified absolute time has arrived. +// You must pass a handle to the current thread. +// If '0' is returned, then the thread was aborted before or during the wait. +static int vtkThreadSleep(vtkMultiThreader::ThreadInfo *data, double time) +{ + for (int i = 0;; i++) + { + double remaining = time - vtkTimerLog::GetUniversalTime(); + + // check to see if we have reached the specified time + if (remaining <= 0) + { + if (i == 0) + { + vtkGenericWarningMacro("Dropped a video frame."); + } + return 1; + } + // check the ActiveFlag at least every 0.1 seconds + if (remaining > 0.1) + { + remaining = 0.1; + } + + // check to see if we are being told to quit + data->ActiveFlagLock->Lock(); + int activeFlag = *(data->ActiveFlag); + data->ActiveFlagLock->Unlock(); + + if (activeFlag == 0) + { + return 0; + } + + vtkSleep(remaining); + } +} + +//---------------------------------------------------------------------------- +// this function runs in an alternate thread to asyncronously grab frames +static void *vtkVideoSourceRecordThread(vtkMultiThreader::ThreadInfo *data) +{ + vtkVideoSource *self = (vtkVideoSource *)(data->UserData); + + double startTime = vtkTimerLog::GetUniversalTime(); + double rate = self->GetFrameRate(); + int frame = 0; + + do + { + self->InternalGrab(); + frame++; + } + while (vtkThreadSleep(data, startTime + frame/rate)); + + return NULL; +} + +//---------------------------------------------------------------------------- +// Set the source to grab frames continuously. +// You should override this as appropriate for your device. +void vtkVideoSource::Record() +{ + if (this->Playing) + { + this->Stop(); + } + + if (!this->Recording) + { + this->Initialize(); + + this->Recording = 1; + this->FrameCount = 0; + this->Modified(); + this->PlayerThreadId = + this->PlayerThreader->SpawnThread((vtkThreadFunctionType)\ + &vtkVideoSourceRecordThread,this); + } +} + +//---------------------------------------------------------------------------- +// this function runs in an alternate thread to 'play the tape' at the +// specified frame rate. +static void *vtkVideoSourcePlayThread(vtkMultiThreader::ThreadInfo *data) +{ + vtkVideoSource *self = (vtkVideoSource *)(data->UserData); + + double startTime = vtkTimerLog::GetUniversalTime(); + double rate = self->GetFrameRate(); + int frame = 0; + + do + { + self->Seek(1); + frame++; + } + while (vtkThreadSleep(data, startTime + frame/rate)); + + return NULL; +} + +//---------------------------------------------------------------------------- +// Set the source to play back recorded frames. +// You should override this as appropriate for your device. +void vtkVideoSource::Play() +{ + if (this->Recording) + { + this->Stop(); + } + + if (!this->Playing) + { + this->Initialize(); + + this->Playing = 1; + this->Modified(); + this->PlayerThreadId = + this->PlayerThreader->SpawnThread((vtkThreadFunctionType)\ + &vtkVideoSourcePlayThread,this); + } +} + +//---------------------------------------------------------------------------- +// Stop continuous grabbing or playback. You will have to override this +// if your class overrides Play() and Record() +void vtkVideoSource::Stop() +{ + if (this->Playing || this->Recording) + { + this->PlayerThreader->TerminateThread(this->PlayerThreadId); + this->PlayerThreadId = -1; + this->Playing = 0; + this->Recording = 0; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Rewind back to the frame with the earliest timestamp. +void vtkVideoSource::Rewind() +{ + this->FrameBufferMutex->Lock(); + + double *stamp = this->FrameBufferTimeStamps; + double lowest = 0; + int i, j; + + if (this->FrameBufferSize) + { + lowest = stamp[this->FrameBufferIndex]; + } + for (i = 0; i < this->FrameBufferSize; i++) + { + j = (this->FrameBufferIndex + i + 1) % this->FrameBufferSize; + if (stamp[j] != 0.0 && stamp[j] <= lowest) + { + lowest = stamp[j]; + } + else + { + break; + } + } + j = (this->FrameBufferIndex + i) % this->FrameBufferSize; + if (stamp[j] != 0.0 && stamp[j] < 980000000.0) + { + vtkWarningMacro("Rewind: bogus time stamp!"); + } + else + { + this->AdvanceFrameBuffer(-i); + this->FrameIndex = (this->FrameIndex - i) % this->FrameBufferSize; + while (this->FrameIndex < 0) + { + this->FrameIndex += this->FrameBufferSize; + } + } + + this->FrameBufferMutex->Unlock(); +} + +//---------------------------------------------------------------------------- +// Fast-forward to the frame with the latest timestamp. +void vtkVideoSource::FastForward() +{ + this->FrameBufferMutex->Lock(); + + double *stamp = this->FrameBufferTimeStamps; + double highest = 0; + int i, j; + + if (this->FrameBufferSize) + { + highest = stamp[this->FrameBufferIndex]; + } + for (i = 0; i < this->FrameBufferSize; i++) + { + j = (this->FrameBufferIndex - i - 1) % this->FrameBufferSize; + while (j < 0) + { + j += this->FrameBufferSize; + } + if (stamp[j] != 0.0 && stamp[j] >= highest) + { + highest = stamp[j]; + } + else + { + break; + } + } + j = (this->FrameBufferIndex - i) % this->FrameBufferSize; + while (j < 0) + { + j += this->FrameBufferSize; + } + if (stamp[j] != 0.0 && stamp[j] < 980000000.0) + { + vtkWarningMacro("FastForward: bogus time stamp!"); + } + else + { + this->AdvanceFrameBuffer(i); + this->FrameIndex = (this->FrameIndex + i) % this->FrameBufferSize; + while (this->FrameIndex < 0) + { + this->FrameIndex += this->FrameBufferSize; + } + } + + this->FrameBufferMutex->Unlock(); +} + +//---------------------------------------------------------------------------- +// Rotate the buffers +void vtkVideoSource::Seek(int n) +{ + this->FrameBufferMutex->Lock(); + this->AdvanceFrameBuffer(n); + this->FrameIndex = (this->FrameIndex + n) % this->FrameBufferSize; + while (this->FrameIndex < 0) + { + this->FrameIndex += this->FrameBufferSize; + } + this->FrameBufferMutex->Unlock(); + this->Modified(); +} + +//---------------------------------------------------------------------------- +// The grab function, which should (of course) be overridden to do +// the appropriate hardware stuff. This function should never be +// called asynchronously. +void vtkVideoSource::Grab() +{ + // ensure that the hardware is initialized. + this->Initialize(); + + this->InternalGrab(); +} + +//---------------------------------------------------------------------------- +// Override this and provide checks to ensure an appropriate number +// of components was asked for (i.e. 1 for greyscale, 3 for RGB, +// or 4 for RGBA) +void vtkVideoSource::SetOutputFormat(int format) +{ + if (format == this->OutputFormat) + { + return; + } + + this->OutputFormat = format; + + // convert color format to number of scalar components + int numComponents = 1; + + switch (this->OutputFormat) + { + case VTK_RGBA: + numComponents = 4; + break; + case VTK_RGB: + numComponents = 3; + break; + case VTK_LUMINANCE_ALPHA: + numComponents = 2; + break; + case VTK_LUMINANCE: + numComponents = 1; + break; + default: + vtkErrorMacro(<< "SetOutputFormat: Unrecognized color format."); + break; + } + this->NumberOfScalarComponents = numComponents; + + if (this->FrameBufferBitsPerPixel != numComponents*8) + { + this->FrameBufferMutex->Lock(); + this->FrameBufferBitsPerPixel = numComponents*8; + if (this->Initialized) + { + this->UpdateFrameBuffer(); + } + this->FrameBufferMutex->Unlock(); + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// set or change the circular buffer size +// you will have to override this if you want the buffers +// to be device-specific (i.e. something other than vtkDataArray) +void vtkVideoSource::SetFrameBufferSize(int bufsize) +{ + int i; + void **framebuffer; + double *timestamps; + + if (bufsize < 0) + { + vtkErrorMacro(<< "SetFrameBufferSize: There must be at least one framebuffer"); + } + + if (bufsize == this->FrameBufferSize && bufsize != 0) + { + return; + } + + this->FrameBufferMutex->Lock(); + + if (this->FrameBuffer == 0) + { + if (bufsize > 0) + { + this->FrameBufferIndex = 0; + this->FrameIndex = -1; + this->FrameBuffer = new void *[bufsize]; + this->FrameBufferTimeStamps = new double[bufsize]; + for (i = 0; i < bufsize; i++) + { + this->FrameBuffer[i] = vtkUnsignedCharArray::New(); + this->FrameBufferTimeStamps[i] = 0.0; + } + this->FrameBufferSize = bufsize; + this->Modified(); + } + } + else + { + if (bufsize > 0) + { + framebuffer = new void *[bufsize]; + timestamps = new double[bufsize]; + } + else + { + framebuffer = NULL; + timestamps = NULL; + } + + // create new image buffers if necessary + for (i = 0; i < bufsize - this->FrameBufferSize; i++) + { + framebuffer[i] = vtkUnsignedCharArray::New(); + timestamps[i] = 0.0; + } + // copy over old image buffers + for (; i < bufsize; i++) + { + framebuffer[i] = this->FrameBuffer[i-(bufsize-this->FrameBufferSize)]; + } + + // delete image buffers we no longer need + for (i = 0; i < this->FrameBufferSize-bufsize; i++) + { + reinterpret_cast(this->FrameBuffer[i])->Delete(); + } + + if (this->FrameBuffer) + { + delete [] this->FrameBuffer; + } + this->FrameBuffer = framebuffer; + if (this->FrameBufferTimeStamps) + { + delete [] this->FrameBufferTimeStamps; + } + this->FrameBufferTimeStamps = timestamps; + + // make sure that frame buffer index is within the buffer + if (bufsize > 0) + { + this->FrameBufferIndex = this->FrameBufferIndex % bufsize; + if (this->FrameIndex >= bufsize) + { + this->FrameIndex = bufsize - 1; + } + } + else + { + this->FrameBufferIndex = 0; + this->FrameIndex = -1; + } + + this->FrameBufferSize = bufsize; + this->Modified(); + } + + if (this->Initialized) + { + this->UpdateFrameBuffer(); + } + + this->FrameBufferMutex->Unlock(); +} + +//---------------------------------------------------------------------------- +// This function MUST be called only from within a FrameBufferMutex->Lock() +void vtkVideoSource::AdvanceFrameBuffer(int n) +{ + int i = (this->FrameBufferIndex - n) % this->FrameBufferSize; + while (i < 0) + { + i += this->FrameBufferSize; + } + this->FrameBufferIndex = i; +} + +//---------------------------------------------------------------------------- +double vtkVideoSource::GetFrameTimeStamp(int frame) +{ + double timeStamp; + + this->FrameBufferMutex->Lock(); + + if (this->FrameBufferSize <= 0) + { + return 0.0; + } + + timeStamp = this->FrameBufferTimeStamps[(this->FrameBufferIndex + frame) \ + % this->FrameBufferSize]; + this->FrameBufferMutex->Unlock(); + + return timeStamp; +} + +//---------------------------------------------------------------------------- +// This method returns the largest data that can be generated. +int vtkVideoSource::RequestInformation( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int i; + int extent[6]; + + // ensure that the hardware is initialized. + this->Initialize(); + + for (i = 0; i < 3; i++) + { + // initially set extent to the OutputWholeExtent + extent[2*i] = this->OutputWholeExtent[2*i]; + extent[2*i+1] = this->OutputWholeExtent[2*i+1]; + // if 'flag' is set in output extent, use the FrameBufferExtent instead + if (extent[2*i+1] < extent[2*i]) + { + extent[2*i] = 0; + extent[2*i+1] = \ + this->FrameBufferExtent[2*i+1] - this->FrameBufferExtent[2*i]; + } + this->FrameOutputExtent[2*i] = extent[2*i]; + this->FrameOutputExtent[2*i+1] = extent[2*i+1]; + } + + int numFrames = this->NumberOfOutputFrames; + if (numFrames < 1) + { + numFrames = 1; + } + if (numFrames > this->FrameBufferSize) + { + numFrames = this->FrameBufferSize; + } + + // multiply Z extent by number of frames to output + extent[5] = extent[4] + (extent[5]-extent[4]+1) * numFrames - 1; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + + // set the spacing + outInfo->Set(vtkDataObject::SPACING(),this->DataSpacing,3); + + // set the origin. + outInfo->Set(vtkDataObject::ORIGIN(),this->DataOrigin,3); + + // set default data type (8 bit greyscale) + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, + this->NumberOfScalarComponents); + + return 1; +} + +//---------------------------------------------------------------------------- +// The UnpackRasterLine method should be overridden if the framebuffer uses +// unusual pixel packing formats, such as XRGB XBRG BGRX BGR etc. +// The version below assumes that the packing of the framebuffer is +// identical to that of the output. +void vtkVideoSource::UnpackRasterLine(char *outPtr, char *rowPtr, + int start, int count) +{ + char *inPtr = rowPtr + start*this->NumberOfScalarComponents; + memcpy(outPtr,inPtr,count*this->NumberOfScalarComponents); + if (this->OutputFormat == VTK_RGBA) + { // RGBA image: need to copy in the opacity + unsigned char alpha = (unsigned char)(this->Opacity*255); + int k; + outPtr += 3; + for (k = 0; k < count; k++) + { + outPtr[4*k] = alpha; + } + } +} + +//---------------------------------------------------------------------------- +// The Execute method is fairly complex, so I would not recommend overriding +// it unless you have to. Override the UnpackRasterLine() method instead. +// You should only have to override it if you are using something other +// than 8-bit vtkUnsignedCharArray for the frame buffer. +int vtkVideoSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + vtkImageData *data = this->AllocateOutputData(this->GetOutput()); + int i,j; + + int outputExtent[6]; // will later be clipped in Z to a single frame + int saveOutputExtent[6]; // will possibly contain multiple frames + data->GetExtent(outputExtent); + for (i = 0; i < 6; i++) + { + saveOutputExtent[i] = outputExtent[i]; + } + // clip to extent to the Z size of one frame + outputExtent[4] = this->FrameOutputExtent[4]; + outputExtent[5] = this->FrameOutputExtent[5]; + + int frameExtentX = this->FrameBufferExtent[1]-this->FrameBufferExtent[0]+1; + int frameExtentY = this->FrameBufferExtent[3]-this->FrameBufferExtent[2]+1; + int frameExtentZ = this->FrameBufferExtent[5]-this->FrameBufferExtent[4]+1; + + int extentX = outputExtent[1]-outputExtent[0]+1; + int extentY = outputExtent[3]-outputExtent[2]+1; + int extentZ = outputExtent[5]-outputExtent[4]+1; + + // if the output is more than a single frame, + // then the output will cover a partial or full first frame, + // several full frames, and a partial or full last frame + + // index and Z size of the first frame in the output extent + int firstFrame = (saveOutputExtent[4]-outputExtent[4])/extentZ; + int firstOutputExtent4 = saveOutputExtent[4] - extentZ*firstFrame; + + // index and Z size of the final frame in the output extent + int finalFrame = (saveOutputExtent[5]-outputExtent[4])/extentZ; + int finalOutputExtent5 = saveOutputExtent[5] - extentZ*finalFrame; + + char *outPtr = (char *)data->GetScalarPointer(); + char *outPtrTmp; + + int inIncY = (frameExtentX*this->FrameBufferBitsPerPixel + 7)/8; + inIncY = ((inIncY + this->FrameBufferRowAlignment - 1)/ + this->FrameBufferRowAlignment)*this->FrameBufferRowAlignment; + int inIncZ = inIncY*frameExtentY; + + int outIncX = this->NumberOfScalarComponents; + int outIncY = outIncX*extentX; + int outIncZ = outIncY*extentY; + + int inPadX = 0; + int inPadY = 0; + int inPadZ; // do inPadZ later + + int outPadX = -outputExtent[0]; + int outPadY = -outputExtent[2]; + int outPadZ; // do outPadZ later + + if (outPadX < 0) + { + inPadX -= outPadX; + outPadX = 0; + } + + if (outPadY < 0) + { + inPadY -= outPadY; + outPadY = 0; + } + + int outX = frameExtentX - inPadX; + int outY = frameExtentY - inPadY; + int outZ; // do outZ later + + if (outX > extentX - outPadX) + { + outX = extentX - outPadX; + } + if (outY > extentY - outPadY) + { + outY = extentY - outPadY; + } + + // if output extent has changed, need to initialize output to black + for (i = 0; i < 3; i++) + { + if (saveOutputExtent[i] != this->LastOutputExtent[i]) + { + this->LastOutputExtent[i] = saveOutputExtent[i]; + this->OutputNeedsInitialization = 1; + } + } + + // ditto for number of scalar components + if (data->GetNumberOfScalarComponents() != + this->LastNumberOfScalarComponents) + { + this->LastNumberOfScalarComponents = data->GetNumberOfScalarComponents(); + this->OutputNeedsInitialization = 1; + } + + // initialize output to zero only when necessary + if (this->OutputNeedsInitialization) + { + memset(outPtr,0, + (saveOutputExtent[1]-saveOutputExtent[0]+1)* + (saveOutputExtent[3]-saveOutputExtent[2]+1)* + (saveOutputExtent[5]-saveOutputExtent[4]+1)*outIncX); + this->OutputNeedsInitialization = 0; + } + + // we have to modify the outputExtent of the first frame, + // because it might be complete (it will be restored after + // the first frame has been copied to the output) + int saveOutputExtent4 = outputExtent[4]; + outputExtent[4] = firstOutputExtent4; + + this->FrameBufferMutex->Lock(); + + int index = this->FrameBufferIndex; + this->FrameTimeStamp = + this->FrameBufferTimeStamps[index % this->FrameBufferSize]; + + int frame; + for (frame = firstFrame; frame <= finalFrame; frame++) + { + if (frame == finalFrame) + { + outputExtent[5] = finalOutputExtent5; + } + + vtkDataArray *frameBuffer = reinterpret_cast(this->FrameBuffer[(index + frame) % this->FrameBufferSize]); + + char *inPtr = reinterpret_cast(frameBuffer->GetVoidPointer(0)); + char *inPtrTmp ; + + extentZ = outputExtent[5]-outputExtent[4]+1; + inPadZ = 0; + outPadZ = -outputExtent[4]; + + if (outPadZ < 0) + { + inPadZ -= outPadZ; + outPadZ = 0; + } + + outZ = frameExtentZ - inPadZ; + + if (outZ > extentZ - outPadZ) + { + outZ = extentZ - outPadZ; + } + + if (this->FlipFrames) + { // apply a vertical flip while copying to output + outPtr += outIncZ*outPadZ+outIncY*outPadY+outIncX*outPadX; + inPtr += inIncZ*inPadZ+inIncY*(frameExtentY-inPadY-outY); + + for (i = 0; i < outZ; i++) + { + inPtrTmp = inPtr; + outPtrTmp = outPtr + outIncY*outY; + for (j = 0; j < outY; j++) + { + outPtrTmp -= outIncY; + if (outX > 0) + { + this->UnpackRasterLine(outPtrTmp,inPtrTmp,inPadX,outX); + } + inPtrTmp += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } + } + else + { // don't apply a vertical flip + outPtr += outIncZ*outPadZ+outIncY*outPadY+outIncX*outPadX; + inPtr += inIncZ*inPadZ+inIncY*inPadY; + + for (i = 0; i < outZ; i++) + { + inPtrTmp = inPtr; + outPtrTmp = outPtr; + for (j = 0; j < outY; j++) + { + if (outX > 0) + { + this->UnpackRasterLine(outPtrTmp,inPtrTmp,inPadX,outX); + } + outPtrTmp += outIncY; + inPtrTmp += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } + } + // restore the output extent once the first frame is done + outputExtent[4] = saveOutputExtent4; + } + + this->FrameBufferMutex->Unlock(); + + return 1; +} diff --git a/Hybrid/vtkVideoSource.h b/Hybrid/vtkVideoSource.h new file mode 100644 index 0000000..28d5f80 --- /dev/null +++ b/Hybrid/vtkVideoSource.h @@ -0,0 +1,309 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVideoSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVideoSource - Superclass of video input devices for VTK +// .SECTION Description +// vtkVideoSource is a superclass for video input interfaces for VTK. +// The goal is to provide an interface which is very similar to the +// interface of a VCR, where the 'tape' is an internal frame buffer +// capable of holding a preset number of video frames. Specialized +// versions of this class record input from various video input sources. +// This base class records input from a noise source. +// .SECTION Caveats +// You must call the ReleaseSystemResources() method before the application +// exits. Otherwise the application might hang while trying to exit. +// .SECTION See Also +// vtkWin32VideoSource vtkMILVideoSource + +#ifndef __vtkVideoSource_h +#define __vtkVideoSource_h + +#include "vtkImageAlgorithm.h" + +class vtkTimerLog; +class vtkCriticalSection; +class vtkMultiThreader; +class vtkScalarsToColors; + +class VTK_HYBRID_EXPORT vtkVideoSource : public vtkImageAlgorithm +{ +public: + static vtkVideoSource *New(); + vtkTypeRevisionMacro(vtkVideoSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Record incoming video at the specified FrameRate. The recording + // continues indefinitely until Stop() is called. + virtual void Record(); + + // Description: + // Play through the 'tape' sequentially at the specified frame rate. + // If you have just finished Recoding, you should call Rewind() first. + virtual void Play(); + + // Description: + // Stop recording or playing. + virtual void Stop(); + + // Description: + // Rewind to the frame with the earliest timestamp. Record operations + // will start on the following frame, therefore if you want to re-record + // over this frame you must call Seek(-1) before calling Grab() or Record(). + virtual void Rewind(); + + // Description: + // FastForward to the last frame that was recorded (i.e. to the frame + // that has the most recent timestamp). + virtual void FastForward(); + + // Description: + // Seek forwards or backwards by the specified number of frames + // (positive is forward, negative is backward). + virtual void Seek(int n); + + // Description: + // Grab a single video frame. + virtual void Grab(); + + // Description: + // Are we in record mode? (record mode and play mode are mutually + // exclusive). + vtkGetMacro(Recording,int); + + // Description: + // Are we in play mode? (record mode and play mode are mutually + // exclusive). + vtkGetMacro(Playing,int); + + // Description: + // Set the full-frame size. This must be an allowed size for the device, + // the device may either refuse a request for an illegal frame size or + // automatically choose a new frame size. + // The default is usually 320x240x1, but can be device specific. + // The 'depth' should always be 1 (unless you have a device that + // can handle 3D acquisition). + virtual void SetFrameSize(int x, int y, int z); + virtual void SetFrameSize(int dim[3]) { + this->SetFrameSize(dim[0], dim[1], dim[2]); }; + vtkGetVector3Macro(FrameSize,int); + + // Description: + // Request a particular frame rate (default 30 frames per second). + virtual void SetFrameRate(float rate); + vtkGetMacro(FrameRate,float); + + // Description: + // Set the output format. This must be appropriate for device, + // usually only VTK_LUMINANCE, VTK_RGB, and VTK_RGBA are supported. + virtual void SetOutputFormat(int format); + void SetOutputFormatToLuminance() { this->SetOutputFormat(VTK_LUMINANCE); }; + void SetOutputFormatToRGB() { this->SetOutputFormat(VTK_RGB); }; + void SetOutputFormatToRGBA() { this->SetOutputFormat(VTK_RGBA); }; + vtkGetMacro(OutputFormat,int); + + // Description: + // Set size of the frame buffer, i.e. the number of frames that + // the 'tape' can store. + virtual void SetFrameBufferSize(int FrameBufferSize); + vtkGetMacro(FrameBufferSize,int); + + // Description: + // Set the number of frames to copy to the output on each execute. + // The frames will be concatenated along the Z dimension, with the + // most recent frame first. + // Default: 1 + vtkSetMacro(NumberOfOutputFrames,int); + vtkGetMacro(NumberOfOutputFrames,int); + + // Description: + // Set whether to automatically advance the buffer before each grab. + // Default: on + vtkBooleanMacro(AutoAdvance,int); + vtkSetMacro(AutoAdvance,int) + vtkGetMacro(AutoAdvance,int); + + // Description: + // Set the clip rectangle for the frames. The video will be clipped + // before it is copied into the framebuffer. Changing the ClipRegion + // will destroy the current contents of the framebuffer. + // The default ClipRegion is (0,VTK_INT_MAX,0,VTK_INT_MAX,0,VTK_INT_MAX). + virtual void SetClipRegion(int r[6]) { + this->SetClipRegion(r[0],r[1],r[2],r[3],r[4],r[5]); }; + virtual void SetClipRegion(int x0, int x1, int y0, int y1, int z0, int z1); + vtkGetVector6Macro(ClipRegion,int); + + // Description: + // Get/Set the WholeExtent of the output. This can be used to either + // clip or pad the video frame. This clipping/padding is done when + // the frame is copied to the output, and does not change the contents + // of the framebuffer. This is useful e.g. for expanding + // the output size to a power of two for texture mapping. The + // default is (0,-1,0,-1,0,-1) which causes the entire frame to be + // copied to the output. + vtkSetVector6Macro(OutputWholeExtent,int); + vtkGetVector6Macro(OutputWholeExtent,int); + + // Description: + // Set/Get the pixel spacing. + // Default: (1.0,1.0,1.0) + vtkSetVector3Macro(DataSpacing,double); + vtkGetVector3Macro(DataSpacing,double); + + // Description: + // Set/Get the coordinates of the lower, left corner of the frame. + // Default: (0.0,0.0,0.0) + vtkSetVector3Macro(DataOrigin,double); + vtkGetVector3Macro(DataOrigin,double); + + // Description: + // For RGBA output only (4 scalar components), set the opacity. This + // will not modify the existing contents of the framebuffer, only + // subsequently grabbed frames. + vtkSetMacro(Opacity,float); + vtkGetMacro(Opacity,float); + + // Description: + // This value is incremented each time a frame is grabbed. + // reset it to zero (or any other value) at any time. + vtkGetMacro(FrameCount, int); + vtkSetMacro(FrameCount, int); + + // Description: + // Get the frame index relative to the 'beginning of the tape'. This + // value wraps back to zero if it increases past the FrameBufferSize. + vtkGetMacro(FrameIndex, int); + + // Description: + // Get a time stamp in seconds (resolution of milliseconds) for + // a video frame. Time began on Jan 1, 1970. You can specify + // a number (negative or positive) to specify the position of the + // video frame relative to the current frame. + virtual double GetFrameTimeStamp(int frame); + + // Description: + // Get a time stamp in seconds (resolution of milliseconds) for + // the Output. Time began on Jan 1, 1970. This timestamp is only + // valid after the Output has been Updated. + double GetFrameTimeStamp() { return this->FrameTimeStamp; }; + + // Description: + // Initialize the hardware. This is called automatically + // on the first Update or Grab. + virtual void Initialize(); + virtual int GetInitialized() { return this->Initialized; }; + + // Description: + // Release the video driver. This method must be called before + // application exit, or else the application might hang during + // exit. + virtual void ReleaseSystemResources(); + + // Description: + // The internal function which actually does the grab. You will + // definitely want to override this if you develop a vtkVideoSource + // subclass. + virtual void InternalGrab(); + + // Description: + // And internal variable which marks the beginning of a Record session. + // These methods are for internal use only. + void SetStartTimeStamp(double t) { this->StartTimeStamp = t; }; + double GetStartTimeStamp() { return this->StartTimeStamp; }; + +protected: + vtkVideoSource(); + ~vtkVideoSource(); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int Initialized; + + int FrameSize[3]; + int ClipRegion[6]; + int OutputWholeExtent[6]; + double DataSpacing[3]; + double DataOrigin[3]; + int OutputFormat; + // set according to the OutputFormat + int NumberOfScalarComponents; + // The FrameOutputExtent is the WholeExtent for a single output frame. + // It is initialized in ExecuteInformation. + int FrameOutputExtent[6]; + + // save this information from the output so that we can see if the + // output scalars have changed + int LastNumberOfScalarComponents; + int LastOutputExtent[6]; + + int Recording; + int Playing; + float FrameRate; + int FrameCount; + int FrameIndex; + double StartTimeStamp; + double FrameTimeStamp; + + int AutoAdvance; + int NumberOfOutputFrames; + + float Opacity; + + // true if Execute() must apply a vertical flip to each frame + int FlipFrames; + + // set if output needs to be cleared to be cleared before being written + int OutputNeedsInitialization; + + // An example of asynchrony + vtkMultiThreader *PlayerThreader; + int PlayerThreadId; + + // A mutex for the frame buffer: must be applied when any of the + // below data is modified. + vtkCriticalSection *FrameBufferMutex; + + // set according to the needs of the hardware: + // number of bits per framebuffer pixel + int FrameBufferBitsPerPixel; + // byte alignment of each row in the framebuffer + int FrameBufferRowAlignment; + // FrameBufferExtent is the extent of frame after it has been clipped + // with ClipRegion. It is initialized in CheckBuffer(). + int FrameBufferExtent[6]; + + int FrameBufferSize; + int FrameBufferIndex; + void **FrameBuffer; + double *FrameBufferTimeStamps; + + // Description: + // These methods can be overridden in subclasses + virtual void UpdateFrameBuffer(); + virtual void AdvanceFrameBuffer(int n); + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + // if some component conversion is required, it is done here: + virtual void UnpackRasterLine(char *outPtr, char *rowPtr, + int start, int count); + +private: + vtkVideoSource(const vtkVideoSource&); // Not implemented. + void operator=(const vtkVideoSource&); // Not implemented. +}; + +#endif + + + + + diff --git a/Hybrid/vtkWeightedTransformFilter.cxx b/Hybrid/vtkWeightedTransformFilter.cxx new file mode 100644 index 0000000..12edfae --- /dev/null +++ b/Hybrid/vtkWeightedTransformFilter.cxx @@ -0,0 +1,871 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWeightedTransformFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWeightedTransformFilter.h" + +#include "vtkCellData.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLinearTransform.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkUnsignedShortArray.h" + +vtkCxxRevisionMacro(vtkWeightedTransformFilter, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkWeightedTransformFilter); + +// helper functions. Can't easily get to these in Matrix4x4 as written. + +static inline void LinearTransformVector(double matrix[4][4], + double in[3], double out[3]) +{ + out[0] = matrix[0][0]*in[0] + matrix[0][1]*in[1] + matrix[0][2]*in[2]; + out[1] = matrix[1][0]*in[0] + matrix[1][1]*in[1] + matrix[1][2]*in[2]; + out[2] = matrix[2][0]*in[0] + matrix[2][1]*in[1] + matrix[2][2]*in[2]; +} + +static inline void LinearTransformPoint(double mtx[4][4], + double in[3], double out[3]) +{ + out[0] = mtx[0][0]*in[0]+mtx[0][1]*in[1]+mtx[0][2]*in[2]+mtx[0][3]; + out[1] = mtx[1][0]*in[0]+mtx[1][1]*in[1]+mtx[1][2]*in[2]+mtx[1][3]; + out[2] = mtx[2][0]*in[0]+mtx[2][1]*in[1]+mtx[2][2]*in[2]+mtx[2][3]; +} + +//---------------------------------------------------------------------------- +vtkWeightedTransformFilter::vtkWeightedTransformFilter() +{ + this->AddInputValues = 0; + this->Transforms = NULL; + this->NumberOfTransforms = 0; + + this->CellDataWeightArray = NULL; + this->WeightArray = NULL; + this->CellDataTransformIndexArray = NULL; + this->TransformIndexArray = NULL; +} + +//---------------------------------------------------------------------------- +vtkWeightedTransformFilter::~vtkWeightedTransformFilter() +{ + int i; + + if(this->Transforms != NULL) + { + for(i = 0; i < this->NumberOfTransforms; i++) + { + if(this->Transforms[i] != NULL) + { + this->Transforms[i]->UnRegister(this); + } + } + delete [] this->Transforms; + } + + // Setting these strings to NULL has the side-effect of deleting them. + this->SetCellDataWeightArray(NULL); + this->SetWeightArray(NULL); + this->SetCellDataTransformIndexArray(NULL); + this->SetTransformIndexArray(NULL); +} + +//---------------------------------------------------------------------------- +void vtkWeightedTransformFilter::SetNumberOfTransforms(int num) +{ + int i; + vtkAbstractTransform **newTransforms; + + if(num < 0) + { + vtkErrorMacro(<< "Cannot set transform count below zero"); + return; + } + + if(this->Transforms == NULL) + { + // first time + this->Transforms = new vtkAbstractTransform*[num]; + for(i = 0; i < num; i++) + { + this->Transforms[i] = NULL; + } + this->NumberOfTransforms = num; + return; + } + + if(num == this->NumberOfTransforms) + { + return; + } + + if(num < this->NumberOfTransforms) + { + // create a smaller array, free up references to cut-off elements, + // and copy other elements + for(i = num; i < this->NumberOfTransforms; i++) + { + if(this->Transforms[i] != NULL) + { + this->Transforms[i]->UnRegister(this); + this->Transforms[i] = NULL; + } + } + newTransforms = new vtkAbstractTransform*[num]; + for(i = 0; i < num; i++) + { + newTransforms[i] = this->Transforms[i]; + } + delete [] this->Transforms; + this->Transforms = newTransforms; + } + else + { + // create a new array and copy elements, no unregistering needed. + newTransforms = new vtkAbstractTransform*[num]; + for(i = 0; i < this->NumberOfTransforms; i++) { + newTransforms[i] = this->Transforms[i]; + } + + for(i = this->NumberOfTransforms; i < num; i++) + { + newTransforms[i] = NULL; + } + delete [] this->Transforms; + this->Transforms = newTransforms; + } + + this->NumberOfTransforms = num; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkWeightedTransformFilter::SetTransform(vtkAbstractTransform *trans, + int num) +{ + if(num < 0) { + vtkErrorMacro(<<"Transform number must be greater than 0"); + return; + } + + if(num >= this->NumberOfTransforms) + { + vtkErrorMacro(<<"Transform number exceeds maximum of " << + this->NumberOfTransforms); + return; + } + if(this->Transforms[num] != NULL) + { + this->Transforms[num]->UnRegister(this); + } + this->Transforms[num] = trans; + if(trans != NULL) + { + trans->Register(this); + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkAbstractTransform *vtkWeightedTransformFilter::GetTransform(int num) +{ + if(num < 0) + { + vtkErrorMacro(<<"Transform number must be greater than 0"); + return NULL; + } + + if(num >= this->NumberOfTransforms) + { + vtkErrorMacro(<<"Transform number exceeds maximum of " << + this->NumberOfTransforms); + return NULL; + } + + return this->Transforms[num]; +} + +//---------------------------------------------------------------------------- +int vtkWeightedTransformFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPointSet *input = vtkPointSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPointSet *output = vtkPointSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *inPts; + vtkPoints *newPts; + vtkDataArray *inVectors, *inCellVectors; + vtkDataArray *inNormals, *inCellNormals; + vtkFloatArray *newVectors=NULL, *newCellVectors=NULL; + vtkFloatArray *newNormals=NULL, *newCellNormals=NULL; + vtkIdType numPts, numCells, p; + int activeTransforms, allLinear; + int i, c, tidx; + int pdComponents, cdComponents; + double **linearPtMtx; + double **linearNormMtx; + double inVec[3], inPt[3], inNorm[3]; + double xformNorm[3], cumNorm[3]; + double xformPt[3], cumPt[3]; + double xformVec[3], cumVec[3]; + double derivMatrix[3][3]; + float *weights = NULL; + unsigned short *transformIndices = NULL; + double thisWeight; + vtkDataArray *pdArray, *cdArray; + vtkUnsignedShortArray *tiArray, *cdtiArray; + vtkFieldData *fd; + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + vtkLinearTransform *linearTransform; + + vtkDebugMacro(<<"Executing weighted transform filter"); + + // First, copy the input to the output as a starting point + output->CopyStructure( input ); + + // Check input + // + if ( this->Transforms == NULL || this->NumberOfTransforms == 0) + { + vtkErrorMacro(<<"No transform defined!"); + return 1; + } + + activeTransforms = 0; + for(c = 0; c < this->NumberOfTransforms; c++) + { + if(this->Transforms[c] != NULL) + { + activeTransforms++; + } + } + + if(activeTransforms == 0) + { + vtkErrorMacro(<<"No transform defined!"); + return 1; + } + + linearPtMtx = new double*[this->NumberOfTransforms]; + linearNormMtx = new double*[this->NumberOfTransforms]; + allLinear = 1; + for(c = 0; c < this->NumberOfTransforms; c++) + { + if(this->Transforms[c] == NULL) + { + linearPtMtx[c] = NULL; + linearNormMtx[c] = NULL; + continue; + } + + this->Transforms[c]->Update(); + + if(! this->Transforms[c]->IsA("vtkLinearTransform")) + { + linearPtMtx[c] = NULL; + linearNormMtx[c] = NULL; + allLinear = 0; + continue; + } + linearTransform = vtkLinearTransform::SafeDownCast(this->Transforms[c]); + linearPtMtx[c] = (double *)linearTransform->GetMatrix()->Element; + linearNormMtx[c] = new double[16]; + vtkMatrix4x4::DeepCopy(linearNormMtx[c], linearTransform->GetMatrix()); + vtkMatrix4x4::Invert(linearNormMtx[c], linearNormMtx[c]); + vtkMatrix4x4::Transpose(linearNormMtx[c], linearNormMtx[c]); + } + + pdArray = NULL; + pdComponents = 0; + if(this->WeightArray != NULL && this->WeightArray[0] != '\0') + { + fd = pd; + if(fd != NULL) { + pdArray = fd->GetArray(this->WeightArray); + } + if(pdArray == NULL) + { + fd = input->GetFieldData(); + if(fd != NULL) { + pdArray = fd->GetArray(this->WeightArray); + } + } + if(pdArray == NULL) + { + vtkErrorMacro(<<"WeightArray " << this->WeightArray << + " " << "doesn't exist"); + return 1; + } + + pdComponents = pdArray->GetNumberOfComponents(); + if(pdComponents > this->NumberOfTransforms) + { + pdComponents = this->NumberOfTransforms; + } + } + + tiArray = NULL; + if(this->TransformIndexArray!=NULL && this->TransformIndexArray[0]!='\0') + { + fd = pd; + if(fd != NULL) { + tiArray = reinterpret_cast + (fd->GetArray(this->TransformIndexArray)); + } + if(tiArray == NULL) + { + fd = input->GetFieldData(); + if(fd != NULL) { + tiArray = reinterpret_cast + (fd->GetArray(this->TransformIndexArray)); + } + } + if(tiArray == NULL) + { + vtkErrorMacro(<<"TransformIndexArray " << this->TransformIndexArray << + " " << "doesn't exist"); + return 1; + } + + if (pdComponents != tiArray->GetNumberOfComponents()) + { + vtkWarningMacro(<<"TransformIndexArray " << this->TransformIndexArray << + " " << "does not have the same number of components as WeightArray " << + this->WeightArray); + tiArray = NULL; + } + if (tiArray->GetDataType() != VTK_UNSIGNED_SHORT) + { + vtkWarningMacro(<<"TransformIndexArray " << this->TransformIndexArray << + " " << " is not of type unsigned short, ignoring."); + tiArray = NULL; + } + } + + cdArray = NULL; + cdComponents = 0; + if(this->CellDataWeightArray != NULL && + this->CellDataWeightArray[0] != '\0') + { + fd = cd; + if(fd != NULL) + { + cdArray = fd->GetArray(this->CellDataWeightArray); + } + if(cdArray == NULL) + { + fd = input->GetFieldData(); + if(fd != NULL) { + cdArray = fd->GetArray(this->CellDataWeightArray); + } + } + if(cdArray == NULL) + { + vtkErrorMacro(<<"CellDataWeightArray " << this->CellDataWeightArray << + " " << "doesn't exist"); + return 1; + } + cdComponents = cdArray->GetNumberOfComponents(); + if(cdComponents > this->NumberOfTransforms) + { + cdComponents = this->NumberOfTransforms; + } + } + + cdtiArray = NULL; + if(this->CellDataTransformIndexArray != NULL && + this->CellDataTransformIndexArray[0] != '\0') + { + fd = pd; + if(fd != NULL) { + cdtiArray = reinterpret_cast + (fd->GetArray(this->CellDataTransformIndexArray)); + } + if(cdtiArray == NULL) + { + fd = input->GetFieldData(); + if(fd != NULL) { + cdtiArray = reinterpret_cast + (fd->GetArray(this->CellDataTransformIndexArray)); + } + } + if(cdtiArray == NULL) + { + vtkErrorMacro(<<"CellDataTransformIndexArray " << + this->CellDataTransformIndexArray << + " " << "doesn't exist"); + return 1; + } + + if (cdComponents != cdtiArray->GetNumberOfComponents()) + { + vtkWarningMacro(<<"CellDataTransformIndexArray " << + this->CellDataTransformIndexArray << + " " << + "does not have the same number of components as " << + "CellDataWeightArray " << this->WeightArray); + cdtiArray = NULL; + } + if (cdtiArray->GetDataType() != VTK_UNSIGNED_SHORT) + { + vtkWarningMacro(<<"CellDataTransformIndexArray " << + this->CellDataTransformIndexArray << + " " << " is not of type unsigned short, ignoring."); + cdtiArray = NULL; + } + } + + inPts = input->GetPoints(); + inVectors = pd->GetVectors(); + inNormals = pd->GetNormals(); + inCellVectors = cd->GetVectors(); + inCellNormals = cd->GetNormals(); + + if ( !inPts ) + { + vtkErrorMacro(<<"No input data"); + return 1; + } + + numPts = inPts->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + if ( inVectors ) + { + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->Allocate(3*numPts); + } + if ( inNormals ) + { + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + } + + this->UpdateProgress (.2); + // Loop over all points, updating position + // + + // since we may be doing multiple transforms, we must duplicate + // work done in vtkTransform + + // -------------------------- POINT DATA ------------------------------- + if(pdArray != NULL) + { + transformIndices = NULL; + // do points + for(p = 0; p < numPts; p++) + { + // -------- points init --------------- + inPts->GetPoint(p, inPt); + if(this->AddInputValues) + { + cumPt[0] = inPt[0]; + cumPt[1] = inPt[1]; + cumPt[2] = inPt[2]; + } + else + { + cumPt[0] = 0.0; + cumPt[1] = 0.0; + cumPt[2] = 0.0; + } + // -------- vectors init --------------- + if(inVectors) + { + inVectors->GetTuple(p, inVec); + if(this->AddInputValues) + { + cumVec[0] = inVec[0]; + cumVec[1] = inVec[1]; + cumVec[2] = inVec[2]; + } + else + { + cumVec[0] = 0.0; + cumVec[1] = 0.0; + cumVec[2] = 0.0; + } + } + // -------- normals init --------------- + if(inNormals) + { + inNormals->GetTuple(p, inNorm); + if(this->AddInputValues) + { + cumNorm[0] = inNorm[0]; + cumNorm[1] = inNorm[1]; + cumNorm[2] = inNorm[2]; + } + else + { + cumNorm[0] = 0.0; + cumNorm[1] = 0.0; + cumNorm[2] = 0.0; + } + } + + weights = reinterpret_cast + (pdArray)->GetPointer(p*pdComponents); + + if(tiArray != NULL) + { + transformIndices = reinterpret_cast + (tiArray)->GetPointer(p*pdComponents); + } + + // for each transform... + for(c = 0; c < pdComponents; c++) + { + if (transformIndices != NULL) + { + tidx = transformIndices[c]; + } + else + { + tidx = c; + } + if(tidx >= this->NumberOfTransforms || tidx < 0) + { + vtkWarningMacro(<< "transform index " << tidx << + " outside valid range, ignoring"); + continue; + } + thisWeight = weights[c]; + if(this->Transforms[tidx] == NULL || thisWeight == 0.0) + { + continue; + } + + if(linearPtMtx[tidx] != NULL) + { + // -------------------- linear fast path ------------------------ + LinearTransformPoint((double (*)[4])linearPtMtx[tidx], + inPt, xformPt); + + if(inVectors) + { + LinearTransformVector((double (*)[4])linearPtMtx[tidx], + inVec, xformVec); + } + + if(inNormals) + { + LinearTransformVector((double (*)[4])linearNormMtx[tidx], + inNorm, xformNorm); + // normalize below + } + } + else + { + // -------------------- general, slow path ------------------------ + this->Transforms[tidx]->InternalTransformDerivative(inPt, xformPt, + derivMatrix); + if(inVectors) + { + vtkMath::Multiply3x3(derivMatrix, inVec, xformVec); + } + + if(inNormals) + { + vtkMath::Transpose3x3(derivMatrix, derivMatrix); + vtkMath::LinearSolve3x3(derivMatrix, inNorm, xformNorm); + // normalize below + } + } + + // ------ accumulate the results into respective tuples ------- + cumPt[0] += xformPt[0]*thisWeight; + cumPt[1] += xformPt[1]*thisWeight; + cumPt[2] += xformPt[2]*thisWeight; + + if(inVectors) + { + cumVec[0] += xformVec[0]*thisWeight; + cumVec[1] += xformVec[1]*thisWeight; + cumVec[2] += xformVec[2]*thisWeight; + } + + if(inNormals) + { + vtkMath::Normalize(xformNorm); + cumNorm[0] += xformNorm[0]*thisWeight; + cumNorm[1] += xformNorm[1]*thisWeight; + cumNorm[2] += xformNorm[2]*thisWeight; + } + } + + // assign components + newPts->InsertNextPoint(cumPt); + + if (inVectors) + { + newVectors->InsertNextTuple(cumVec); + } + + if (inNormals) + { + // normalize normal again + vtkMath::Normalize(cumNorm); + newNormals->InsertNextTuple(cumNorm); + } + + } + } + + this->UpdateProgress (.6); + + // -------------------------- CELL DATA ------------------------------- + + // can only work on cell data if the transforms are all linear + if(cdArray != NULL && allLinear) + { + if( inCellVectors ) + { + newCellVectors = vtkFloatArray::New(); + newCellVectors->SetNumberOfComponents(3); + newCellVectors->Allocate(3*numCells); + } + if( inCellNormals ) + { + newCellNormals = vtkFloatArray::New(); + newCellNormals->SetNumberOfComponents(3); + newCellNormals->Allocate(3*numCells); + } + transformIndices = NULL; + for(p = 0; p < numCells; p++) + { + // -------- normals init --------------- + if(inCellNormals) + { + inCellNormals->GetTuple(p, inNorm); + if(this->AddInputValues) + { + for(i = 0; i < 3; i++) + { + cumNorm[i] = inNorm[i]; + } + } + else + { + for(i = 0; i < 3; i++) + { + cumNorm[i] = 0.0; + } + } + } + // -------- vectors init --------------- + if(inVectors) + { + inVectors->GetTuple(p, inVec); + if(this->AddInputValues) + { + for(i = 0; i < 3; i++) + { + cumVec[i] = inVec[i]; + } + } + else + { + for(i = 0; i < 3; i++) + { + cumVec[i] = 0.0; + } + } + } + + weights = reinterpret_cast + (cdArray)->GetPointer(p*cdComponents); + if(cdtiArray != NULL) + { + transformIndices = reinterpret_cast + (cdtiArray)->GetPointer(p*cdComponents); + } + + // for each transform... + for(c = 0; c < cdComponents; c++) + { + if (transformIndices != NULL) + { + tidx = transformIndices[c]; + } + else + { + tidx = c; + } + if(tidx >= this->NumberOfTransforms || tidx < 0) + { + vtkWarningMacro(<< "transform index " << tidx << + " outside valid range, ignoring"); + continue; + } + thisWeight = weights[c]; + if(linearPtMtx[tidx] == NULL || thisWeight == 0.0) + { + continue; + } + + if(inCellNormals) + { + LinearTransformVector((double (*)[4])linearNormMtx[tidx], + inNorm, xformNorm); + + vtkMath::Normalize(xformNorm); + cumNorm[0] += xformNorm[0]*thisWeight; + cumNorm[1] += xformNorm[1]*thisWeight; + cumNorm[2] += xformNorm[2]*thisWeight; + } + + if(inVectors) + { + LinearTransformVector((double (*)[4])linearPtMtx[tidx], + inVec, xformVec); + cumVec[0] += xformVec[0]*thisWeight; + cumVec[1] += xformVec[1]*thisWeight; + cumVec[2] += xformVec[2]*thisWeight; + } + } + + if (inCellNormals) + { + // normalize normal again + vtkMath::Normalize(cumNorm); + newCellNormals->InsertNextTuple(cumNorm); + } + + if (inCellVectors) + { + newCellVectors->InsertNextTuple(cumVec); + } + } + } + + // ----- cleanup ------ + for(c = 0; c < this->NumberOfTransforms; c++) + { + if(linearNormMtx[c]) + { + delete [] linearNormMtx[c]; + } + } + delete [] linearNormMtx; + delete [] linearPtMtx; + + // --------------------- + + this->UpdateProgress (0.8); + + // Update ourselves and release memory + // + output->SetPoints(newPts); + newPts->Delete(); + + if (newNormals) + { + outPD->SetNormals(newNormals); + outPD->CopyNormalsOff(); + newNormals->Delete(); + } + + if (newVectors) + { + outPD->SetVectors(newVectors); + outPD->CopyVectorsOff(); + newVectors->Delete(); + } + + if (newCellNormals) + { + outCD->SetNormals(newCellNormals); + outCD->CopyNormalsOff(); + newCellNormals->Delete(); + } + + if (newCellVectors) + { + outCD->SetVectors(newCellVectors); + outCD->CopyVectorsOff(); + newCellVectors->Delete(); + } + + outPD->PassData(pd); + outCD->PassData(cd); + + return 1; +} + +//---------------------------------------------------------------------------- +unsigned long vtkWeightedTransformFilter::GetMTime() +{ + int i; + unsigned long mTime=this->MTime.GetMTime(); + unsigned long transMTime; + + if ( this->Transforms ) + { + for(i = 0; i < this->NumberOfTransforms; i++) + { + if(this->Transforms[i]) + { + transMTime = this->Transforms[i]->GetMTime(); + mTime = ( transMTime > mTime ? transMTime : mTime ); + } + } + } + + return mTime; +} + +//---------------------------------------------------------------------------- +void vtkWeightedTransformFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + int i; + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfTransforms: " << this->NumberOfTransforms << "\n"; + for(i = 0; i < this->NumberOfTransforms; i++) + { + os << indent << "Transform " << i << ": " << this->Transforms[i] << "\n"; + + } + os << indent << "AddInputValues: " << (this->AddInputValues ? "On" : "Off") << "\n"; + os << indent << "WeightArray: " + << (this->WeightArray ? this->WeightArray : "(none)") << "\n"; + os << indent << "CellDataWeightArray: " + << (this->CellDataWeightArray ? this->CellDataWeightArray : "(none)") + << "\n"; + os << indent << "TransformIndexArray: " + << (this->TransformIndexArray ? this->TransformIndexArray : "(none)") + << "\n"; + os << indent << "CellDataTransformIndexArray: " + << (this->CellDataTransformIndexArray ? this->CellDataTransformIndexArray : "(none)") + << "\n"; +} diff --git a/Hybrid/vtkWeightedTransformFilter.h b/Hybrid/vtkWeightedTransformFilter.h new file mode 100644 index 0000000..3def4f3 --- /dev/null +++ b/Hybrid/vtkWeightedTransformFilter.h @@ -0,0 +1,173 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWeightedTransformFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWeightedTransformFilter - transform based on per-point or per-cell weighting functions. +// .SECTION Description + +// vtkWeightedTransformFilter is a filter that can be used to "skin" +// structures and to create new and complex shapes. Unlike a +// traditional transform filter (which has one transform for a data +// set) or an assembly (which has one transform per part or group of +// parts), a weighted transform produces the weighted sum of +// transforms on a per-point or per-cell basis. +// +// Each point or cell in the filter's input has an attached DataArray +// that contains tuples of weighting functions, one per point or cell. +// The filter also has a set of fixed transforms. When the filter +// executes, each input point/cell is transformed by each of the +// transforms. These results are weighted by the point/cell's +// weighting factors to produce final output data. +// +// Linear transforms are performance-optimized. Using arbitrary +// transforms will work, but performance may suffer. +// +// As an example of the utility of weighted transforms, here's how +// this filter can be used for "skinning." Skinning is the process of +// putting a mesh cover over an underlying structure, like skin over +// bone. Joints are difficult to skin because deformation is hard to +// do. Visualize skin over an elbow joint. Part of the skin moves +// with one bone, part of the skin moves with the other bone, and the +// skin in the middle moves a little with each. +// +// Weighted filtering can be used for a simple and efficient kind of +// skinning. Begin with a cylindrical mesh. Create a FloatArray with +// two components per tuple, and one tuple for each point in the mesh. +// Assign transform weights that linear interpolate the distance along +// the cylinder (one component is the distance along the cylinder, the +// other is one minus that distance). Set the filter up to use two +// transforms, the two used to transform the two bones. Now, when the +// transforms change, the mesh will deform so as to, hopefully, +// continue to cover the bones. +// +// vtkWeightedTransformFilter is also useful for creating "strange and +// complex" shapes using pinching, bending, and blending. +// +// .SECTION Caveats +// Weighted combination of normals and vectors are probably not appropriate +// in many cases. Surface normals are treated somewhat specially, but +// in many cases you may need to regenerate the surface normals. +// +// Cell data can only be transformed if all transforms are linear. +// +// +// .SECTION See Also +// vtkAbstractTransform vtkLinearTransform vtkTransformPolyDataFilter vtkActor + +#ifndef __vtkWeightedTransformFilter_h +#define __vtkWeightedTransformFilter_h + +#include "vtkPointSetAlgorithm.h" + +class vtkAbstractTransform; + +class VTK_HYBRID_EXPORT vtkWeightedTransformFilter : public vtkPointSetAlgorithm +{ +public: + static vtkWeightedTransformFilter *New(); + vtkTypeRevisionMacro(vtkWeightedTransformFilter,vtkPointSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the MTime also considering the filter's transforms. + unsigned long GetMTime(); + + // Description: + // WeightArray is the string name of the DataArray in the input's + // FieldData that holds the weighting coefficients for each point. + // The filter will first look for the array in the input's PointData + // FieldData. If the array isn't there, the filter looks in the + // input's FieldData. The WeightArray can have tuples of any length, + // but must have a tuple for every point in the input data set. + // This array transforms points, normals, and vectors. + vtkSetStringMacro(WeightArray); + vtkGetStringMacro(WeightArray); + + // Description: + // TransformIndexArray is the string name of the DataArray in the input's + // FieldData that holds the indices for the transforms for each point. + // These indices are used to select which transforms each weight of + // the DataArray refers. If the TransformIndexArray is not specified, + // the weights of each point are assumed to map directly to a transform. + // This DataArray must be of type UnsignedShort, which effectively + // limits the number of transforms to 65536 if a transform index + // array is used. + // + // The filter will first look for the array in the input's PointData + // FieldData. If the array isn't there, the filter looks in the + // input's FieldData. The TransformIndexArray can have tuples of any + // length, but must have a tuple for every point in the input data set. + // This array transforms points, normals, and vectors. + vtkSetStringMacro(TransformIndexArray); + vtkGetStringMacro(TransformIndexArray); + + // Description: + // The CellDataWeightArray is analogous to the WeightArray, except + // for CellData. The array is searched for first in the CellData + // FieldData, then in the input's FieldData. The data array must have + // a tuple for each cell. This array is used to transform only normals + // and vectors. + vtkSetStringMacro(CellDataWeightArray); + vtkGetStringMacro(CellDataWeightArray); + + //Description: + // The CellDataTransformIndexArray is like a TransformIndexArray, + // except for cell data. The array must have type UnsignedShort. + vtkSetStringMacro(CellDataTransformIndexArray); + vtkGetStringMacro(CellDataTransformIndexArray); + + // Description: + // Set or Get one of the filter's transforms. The transform number must + // be less than the number of transforms allocated for the object. Setting + // a transform slot to NULL is equivalent to assigning an overriding weight + // of zero to that filter slot. + virtual void SetTransform(vtkAbstractTransform *transform, int num); + virtual vtkAbstractTransform *GetTransform(int num); + + // Description: + // Set the number of transforms for the filter. References to non-existent + // filter numbers in the data array is equivalent to a weight of zero + // (i.e., no contribution of that filter or weight). The maximum number of + // transforms is limited to 65536 if transform index arrays are used. + virtual void SetNumberOfTransforms(int num); + vtkGetMacro(NumberOfTransforms, int); + + // Description: + // If AddInputValues is true, the output values of this filter will be + // offset from the input values. The effect is exactly equivalent to + // having an identity transform of weight 1 added into each output point. + vtkBooleanMacro(AddInputValues, int); + vtkSetMacro(AddInputValues, int); + vtkGetMacro(AddInputValues, int); + +protected: + vtkAbstractTransform **Transforms; + int NumberOfTransforms; + int AddInputValues; + + char *CellDataWeightArray; + char *WeightArray; + + char *CellDataTransformIndexArray; + char *TransformIndexArray; + + vtkWeightedTransformFilter(); + ~vtkWeightedTransformFilter(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); +private: + vtkWeightedTransformFilter(const vtkWeightedTransformFilter&); // Not implemented. + void operator=(const vtkWeightedTransformFilter&); // Not implemented. +}; + +#endif diff --git a/Hybrid/vtkWin32VideoSource.cxx b/Hybrid/vtkWin32VideoSource.cxx new file mode 100644 index 0000000..1a54196 --- /dev/null +++ b/Hybrid/vtkWin32VideoSource.cxx @@ -0,0 +1,1190 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32VideoSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWin32VideoSource.h" + +#include "vtkCriticalSection.h" +#include "vtkObjectFactory.h" +#include "vtkTimerLog.h" +#include "vtkUnsignedCharArray.h" + +#include + +// because of warnings in windows header push and pop the warning level +#ifdef _MSC_VER +#pragma warning (push, 3) +#endif + +#include "vtkWindows.h" +#include +#include + +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +class vtkWin32VideoSourceInternal +{ +public: + vtkWin32VideoSourceInternal() {} + HWND CapWnd; + HWND ParentWnd; + CAPSTATUS CapStatus; + CAPDRIVERCAPS CapDriverCaps; + CAPTUREPARMS CaptureParms; + LPBITMAPINFO BitMapPtr; +}; + +// VFW compressed formats are listed at http://www.webartz.com/fourcc/ +#define VTK_BI_UYVY 0x59565955 + +vtkCxxRevisionMacro(vtkWin32VideoSource, "$Revision: 1.27.12.1 $"); +vtkStandardNewMacro(vtkWin32VideoSource); + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET +#pragma warning ( disable : 4311 ) +#pragma warning ( disable : 4312 ) +# define vtkGetWindowLong GetWindowLongPtr +# define vtkSetWindowLong SetWindowLongPtr +# define vtkGWL_USERDATA GWLP_USERDATA +#else // regular Visual studio +# define vtkGetWindowLong GetWindowLong +# define vtkSetWindowLong SetWindowLong +# define vtkGWL_USERDATA GWL_USERDATA +#endif // + +//---------------------------------------------------------------------------- +vtkWin32VideoSource::vtkWin32VideoSource() +{ + this->Internal = new vtkWin32VideoSourceInternal; + this->Initialized = 0; + + this->FrameRate = 30; + this->OutputFormat = VTK_RGB; + this->NumberOfScalarComponents = 3; + this->FrameBufferBitsPerPixel = 24; + this->FlipFrames = 0; + this->FrameBufferRowAlignment = 4; + + this->Internal->CapWnd = NULL; + this->Internal->ParentWnd = NULL; + this->BitMapSize = 0; + this->Internal->BitMapPtr = NULL; + this->WndClassName[0] = '\0'; + + this->Preview = 0; +} + +//---------------------------------------------------------------------------- +vtkWin32VideoSource::~vtkWin32VideoSource() +{ + this->vtkWin32VideoSource::ReleaseSystemResources(); + + if (this->Internal->BitMapPtr != NULL) + { + delete [] (char *)(this->Internal->BitMapPtr); + } + this->Internal->BitMapPtr = NULL; + this->BitMapSize = 0; + delete this->Internal; +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Preview: " << (this->Preview ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +// This is empty for now because we aren't displaying the capture window +LONG FAR PASCAL +vtkWin32VideoSourceWinProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + vtkWin32VideoSource *self = (vtkWin32VideoSource *)\ + (vtkGetWindowLong(hwnd,vtkGWL_USERDATA)); + + switch(message) { + + case WM_MOVE: + //cerr << "WM_MOVE\n"; + break; + + case WM_SIZE: + //cerr << "WM_SIZE\n"; + break; + + case WM_DESTROY: + //cerr << "WM_DESTROY\n"; + self->OnParentWndDestroy(); + break; + + case WM_CLOSE: + //cerr << "WM_CLOSE\n"; + self->PreviewOff(); + return 0; + } + + return(DefWindowProc(hwnd, message, wParam, lParam)); +} + +//---------------------------------------------------------------------------- +LRESULT PASCAL vtkWin32VideoSourceCapControlProc(HWND hwndC, int nState) +{ + vtkWin32VideoSource *self = (vtkWin32VideoSource *)(capGetUserData(hwndC)); + + if (nState == CONTROLCALLBACK_PREROLL) + { + //cerr << "controlcallback preroll\n"; + self->SetStartTimeStamp(vtkTimerLog::GetUniversalTime()); + } + else if (nState == CONTROLCALLBACK_CAPTURING) + { + //cerr << "controlcallback capturing\n"; + } + + return TRUE; +} + +//---------------------------------------------------------------------------- +LRESULT PASCAL vtkWin32VideoSourceCallbackProc(HWND hwndC, LPVIDEOHDR lpVHdr) +{ + vtkWin32VideoSource *self = (vtkWin32VideoSource *)(capGetUserData(hwndC)); + self->LocalInternalGrab(lpVHdr); + + return 0; +} + +//---------------------------------------------------------------------------- +// this callback is left in for debug purposes +LRESULT PASCAL vtkWin32VideoSourceStatusCallbackProc(HWND vtkNotUsed(hwndC), + int nID, + LPCSTR vtkNotUsed(lpsz)) +{ + //vtkWin32VideoSource *self = (vtkWin32VideoSource *)(capGetUserData(hwndC)); + + if (nID == IDS_CAP_BEGIN) + { + //cerr << "start of capture\n"; + } + + if (nID == IDS_CAP_END) + { + //cerr << "end of capture\n"; + } + + return 1; +} + +//---------------------------------------------------------------------------- +LRESULT PASCAL vtkWin32VideoSourceErrorCallbackProc(HWND hwndC, + int ErrID, + LPSTR lpErrorText) +{ + if (ErrID) + { + char buff[84]; + sprintf(buff,"Error# %d",ErrID); + MessageBox(hwndC,lpErrorText, buff, MB_OK | MB_ICONEXCLAMATION); + //vtkGenericWarningMacro(<< buff << ' ' << lpErrorText); + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::Initialize() +{ + int i; + + if (this->Initialized) + { + return; + } + + // Preliminary update of frame buffer, just in case we don't get + // though the initialization but need the framebuffer for Updates + this->UpdateFrameBuffer(); + + // It is necessary to create not one, but two windows in order to + // do frame grabbing under VFW. Why do we need any? + + // get necessary process info + HINSTANCE hinstance = GetModuleHandle(NULL); + + strcpy(this->WndClassName,"VTKVideo"); + + // set up a class for the main window + WNDCLASS wc; + wc.lpszClassName = this->WndClassName; + wc.hInstance = hinstance; + wc.lpfnWndProc = reinterpret_cast(&vtkWin32VideoSourceWinProc); + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hIcon = NULL; + wc.lpszMenuName = NULL; + wc.hbrBackground = NULL; + wc.style = CS_HREDRAW|CS_VREDRAW; + wc.cbClsExtra = sizeof(void *); + wc.cbWndExtra = 0; + + for (i = 1; i <= 10; i++) + { + if (RegisterClass(&wc)) + { + break; + } + // try again with a slightly different name + sprintf(this->WndClassName,"VTKVideo %d",i); + } + + if (i > 32) + { + vtkErrorMacro(<< "Initialize: failed to register VTKVideo class"\ + << " (" << GetLastError() << ")"); + return; + } + + DWORD style = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU| + WS_CLIPCHILDREN|WS_CLIPSIBLINGS; + + if (this->Preview) + { + style |= WS_VISIBLE; + } + + // set up the parent window, but don't show it + this->Internal->ParentWnd = CreateWindow( + this->WndClassName, + "VTK Video Window", + style, + 0, 0, + this->FrameSize[0]+2*GetSystemMetrics(SM_CXFIXEDFRAME), + this->FrameSize[1]+2*GetSystemMetrics(SM_CYFIXEDFRAME) + +GetSystemMetrics(SM_CYBORDER) + +GetSystemMetrics(SM_CYSIZE), + NULL, + NULL, + hinstance, + NULL); + + if (!this->Internal->ParentWnd) + { + vtkErrorMacro(<< "Initialize: failed to create window"\ + << " (" << GetLastError() << ")"); + return; + } + + // set the user data to 'this' + vtkSetWindowLong(this->Internal->ParentWnd,vtkGWL_USERDATA,(LONG)this); + + // Create the capture window + this->Internal->CapWnd = capCreateCaptureWindow("Capture", + WS_CHILD|WS_VISIBLE, 0, 0, + this->FrameSize[0], this->FrameSize[1], + this->Internal->ParentWnd,1); + + if (!this->Internal->CapWnd) + { + vtkErrorMacro(<< "Initialize: failed to create capture window"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + + // connect to the driver + if (!capDriverConnect(this->Internal->CapWnd,0)) + { + vtkErrorMacro(<< "Initialize: couldn't connect to driver"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + + capDriverGetCaps(this->Internal->CapWnd,&this->Internal->CapDriverCaps,sizeof(CAPDRIVERCAPS)); + + // set up the video format + this->DoVFWFormatSetup(); + + // set the capture parameters + capCaptureGetSetup(this->Internal->CapWnd,&this->Internal->CaptureParms,sizeof(CAPTUREPARMS)); + + if (this->FrameRate > 0) + { + this->Internal->CaptureParms.dwRequestMicroSecPerFrame = + int(1000000/this->FrameRate); + } + else + { + this->Internal->CaptureParms.dwRequestMicroSecPerFrame = 0; + } + + this->Internal->CaptureParms.fMakeUserHitOKToCapture = FALSE; + this->Internal->CaptureParms.fYield = 1; + this->Internal->CaptureParms.fCaptureAudio = FALSE; + this->Internal->CaptureParms.vKeyAbort = 0x00; + this->Internal->CaptureParms.fAbortLeftMouse = FALSE; + this->Internal->CaptureParms.fAbortRightMouse = FALSE; + this->Internal->CaptureParms.fLimitEnabled = FALSE; + this->Internal->CaptureParms.wNumAudioRequested = 0; + this->Internal->CaptureParms.wPercentDropForError = 100; + this->Internal->CaptureParms.dwAudioBufferSize = 0; + this->Internal->CaptureParms.AVStreamMaster = AVSTREAMMASTER_NONE; + + if (!capCaptureSetSetup(this->Internal->CapWnd,&this->Internal->CaptureParms, + sizeof(CAPTUREPARMS))) + { + vtkErrorMacro(<< "Initialize: setup of capture parameters failed"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + + // set user data for callbacks + if (!capSetUserData(this->Internal->CapWnd,(long)this)) + { + vtkErrorMacro(<< "Initialize: couldn't set user data for callback"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + + // install the callback to precisely time beginning of grab + if (!capSetCallbackOnCapControl(this->Internal->CapWnd, + &vtkWin32VideoSourceCapControlProc)) + { + vtkErrorMacro(<< "Initialize: couldn't set control callback"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + + // install the callback to copy frames into the buffer on sync grabs + if (!capSetCallbackOnFrame(this->Internal->CapWnd, + &vtkWin32VideoSourceCallbackProc)) + { + vtkErrorMacro(<< "Initialize: couldn't set frame callback"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + // install the callback to copy frames into the buffer on stream grabs + if (!capSetCallbackOnVideoStream(this->Internal->CapWnd, + &vtkWin32VideoSourceCallbackProc)) + { + vtkErrorMacro(<< "Initialize: couldn't set stream callback"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + // install the callback to get info on start/end of streaming + if (!capSetCallbackOnStatus(this->Internal->CapWnd, + &vtkWin32VideoSourceStatusCallbackProc)) + { + vtkErrorMacro(<< "Initialize: couldn't set status callback"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + // install the callback to send messages to user + if (!capSetCallbackOnError(this->Internal->CapWnd, + &vtkWin32VideoSourceErrorCallbackProc)) + { + vtkErrorMacro(<< "Initialize: couldn't set error callback"\ + << " (" << GetLastError() << ")"); + this->ReleaseSystemResources(); + return; + } + + capOverlay(this->Internal->CapWnd,TRUE); + + // update framebuffer again to reflect any changes which + // might have occurred + this->UpdateFrameBuffer(); + + this->Initialized = 1; +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::SetPreview(int p) +{ + if (this->Preview == p) + { + return; + } + + this->Preview = p; + this->Modified(); + + if (this->Internal->CapWnd == NULL || this->Internal->ParentWnd == NULL) + { + return; + } + + if (p) + { + ShowWindow(this->Internal->ParentWnd,SW_SHOWNORMAL); + } + else + { + ShowWindow(this->Internal->ParentWnd,SW_HIDE); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::ReleaseSystemResources() +{ + // destruction of ParentWnd causes OnParentWndDestroy to be called + if (this->Internal->ParentWnd) + { + DestroyWindow(this->Internal->ParentWnd); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::OnParentWndDestroy() +{ + if (this->Playing || this->Recording) + { + this->Stop(); + } + + if (this->Internal->CapWnd) + { + //MessageBox(this->Internal->ParentWnd, "capDriverDisconnect(this->Internal->CapWnd)", "", MB_OK | MB_ICONEXCLAMATION); + capDriverDisconnect(this->Internal->CapWnd); + //MessageBox(this->Internal->ParentWnd, "DestroyWindow(this->Internal->CapWnd)", "", MB_OK | MB_ICONEXCLAMATION); + DestroyWindow(this->Internal->CapWnd); + this->Internal->CapWnd = NULL; + } + if (this->WndClassName[0] != '\0') + { + UnregisterClass(this->WndClassName,GetModuleHandle(NULL)); + this->WndClassName[0] = '\0'; + } + + this->Internal->ParentWnd = NULL; + this->Initialized = 0; +} + +//---------------------------------------------------------------------------- +// copy the Device Independent Bitmap from the VFW framebuffer into the +// vtkVideoSource framebuffer (don't do the unpacking yet) +void vtkWin32VideoSource::LocalInternalGrab(void* lpptr) +{ + LPVIDEOHDR lpVHdr = static_cast(lpptr); + // cerr << "Grabbed\n"; + + // the VIDEOHDR has the following contents, for quick ref: + // + // lpData pointer to locked data buffer + // dwBufferLength Length of data buffer + // dwBytesUsed Bytes actually used + // dwTimeCaptured Milliseconds from start of stream + // dwUser for client's use + // dwFlags assorted flags (see VFW.H) + // dwReserved[4] reserved for driver + + unsigned char *cptrDIB = lpVHdr->lpData; + + // get a thread lock on the frame buffer + this->FrameBufferMutex->Lock(); + + if (this->AutoAdvance) + { + this->AdvanceFrameBuffer(1); + if (this->FrameIndex + 1 < this->FrameBufferSize) + { + this->FrameIndex++; + } + } + + int index = this->FrameBufferIndex; + + this->FrameCount++; + this->FrameBufferTimeStamps[index] = this->StartTimeStamp + \ + 0.001 * lpVHdr->dwTimeCaptured; + + unsigned char *ptr = (unsigned char *) + ((reinterpret_cast(this->FrameBuffer[index])) \ + ->GetPointer(0)); + + // the DIB has rows which are multiples of 4 bytes + int outBytesPerRow = ((this->FrameBufferExtent[1]- + this->FrameBufferExtent[0]+1) + * this->FrameBufferBitsPerPixel + 7)/8; + outBytesPerRow += outBytesPerRow % this->FrameBufferRowAlignment; + int inBytesPerRow = this->FrameSize[0] + * (this->Internal->BitMapPtr->bmiHeader.biBitCount/8); + outBytesPerRow += outBytesPerRow % 4; + int rows = this->FrameBufferExtent[3]-this->FrameBufferExtent[2]+1; + + cptrDIB += this->FrameBufferExtent[0]*\ + (this->Internal->BitMapPtr->bmiHeader.biBitCount/8); + cptrDIB += this->FrameBufferExtent[2]*inBytesPerRow; + + // uncompress or simply copy the DIB + switch (this->Internal->BitMapPtr->bmiHeader.biCompression) + { + case BI_RGB: + case VTK_BI_UYVY: + if (outBytesPerRow == inBytesPerRow) + { + memcpy(ptr,cptrDIB,inBytesPerRow*rows); + } + else + { + while (--rows >= 0) + { + memcpy(ptr,cptrDIB,outBytesPerRow); + ptr += outBytesPerRow; + cptrDIB += inBytesPerRow; + } + } + break; + case BI_RLE8: // not handled + case BI_RLE4: + case BI_BITFIELDS: + break; + } + + this->Modified(); + + this->FrameBufferMutex->Unlock(); +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::Grab() +{ + if (this->Recording) + { + return; + } + + // ensure that the frame buffer is properly initialized + this->Initialize(); + if (!this->Initialized) + { + return; + } + + // just do the grab, the callback does the rest + this->SetStartTimeStamp(vtkTimerLog::GetUniversalTime()); + capGrabFrameNoStop(this->Internal->CapWnd); +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::Record() +{ + this->Initialize(); + if (!this->Initialized) + { + return; + } + + if (this->Playing) + { + this->Stop(); + } + + if (!this->Recording) + { + this->Recording = 1; + this->Modified(); + capCaptureSequenceNoFile(this->Internal->CapWnd); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::Play() +{ + this->vtkVideoSource::Play(); +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::Stop() +{ + if (this->Recording) + { + this->Recording = 0; + this->Modified(); + + capCaptureStop(this->Internal->CapWnd); + } + else if (this->Playing) + { + this->vtkVideoSource::Stop(); + } +} + +//---------------------------------------------------------------------------- +// codecs + +static inline void vtkYUVToRGB(unsigned char *yuv, unsigned char *rgb) +{ + /* // floating point + int Y = yuv[0] - 16; + int U = yuv[1] - 128; + int V = yuv[2] - 128; + + int R = 1.164*Y + 1.596*V + 0.5; + int G = 1.164*Y - 0.813*V - 0.391*U + 0.5; + int B = 1.164*Y + 2.018*U + 0.5; + */ + + // integer math + int Y = (yuv[0] - 16)*76284; + int U = yuv[1] - 128; + int V = yuv[2] - 128; + + int R = Y + 104595*V ; + int G = Y - 53281*V - 25625*U; + int B = Y + 132252*U; + + // round + R += 32768; + G += 32768; + B += 32768; + + // shift + R >>= 16; + G >>= 16; + B >>= 16; + + // clamp + if (R < 0) { R = 0; } + if (G < 0) { G = 0; } + if (B < 0) { B = 0; } + + if (R > 255) { R = 255; }; + if (G > 255) { G = 255; }; + if (B > 255) { B = 255; }; + + // output + rgb[0] = R; + rgb[1] = G; + rgb[2] = B; +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::UnpackRasterLine(char *outptr, char *inptr, + int start, int count) +{ + char alpha = (char)(this->Opacity*255); + int compression = this->Internal->BitMapPtr->bmiHeader.biCompression; + int i; + + switch (this->FrameBufferBitsPerPixel) + { + case 1: + { + int rawBits; + inptr += start/8; + i = start % 8; + while (count >= 0) + { + rawBits = *inptr++; + for (; i < 8 && --count >= 0; i++) + { + *outptr++ = -((rawBits >> i) & 0x01); + } + i = 0; + } + } + break; + case 4: + { + int rawNibbles; + inptr += start/2; + i = start % 2; + while (count >= 0) + { + rawNibbles = *inptr++; + for (; i < 8 && --count >= 0; i += 4) + { + *outptr++ = ((rawNibbles >> i) & 0x0f) << 4; + } + i = 0; + } + } + break; + case 8: + { + inptr += start; + memcpy(outptr,inptr,count); + } + break; + case 16: + { + inptr += 2*start; + if (compression == VTK_BI_UYVY) + { + switch (this->OutputFormat) + { + case VTK_LUMINANCE: + { // unpack UY half-megapixel to one Y pixel + while (--count >= 0) + { + inptr++; + *outptr++ = *inptr++; + } + } + case VTK_RGB: + case VTK_RGBA: + { // unpack UYVY megapixel to two RGB or RGBA pixels + unsigned char YUV[3]; + //int finish = start + count; + int odd = (start % 2 == 1); + if (count > 0) { YUV[1+odd] = inptr[0]; } + if (count > 1) { YUV[0] = inptr[1]; } + if (count > 2) { YUV[2-odd] = inptr[2]; } + while (--count >= 0) + { + YUV[1+odd] = *inptr++; + YUV[0] = *inptr++; + odd = !odd; + vtkYUVToRGB(YUV,(unsigned char *)outptr); + outptr += 3; + if (this->OutputFormat == VTK_RGB) + { + continue; + } + *outptr++ = alpha; + } + } + } + } + else + { + unsigned short rawWord; + unsigned short *shptr = (unsigned short *)inptr; + switch (this->OutputFormat) + { + case VTK_RGB: + { // unpack 16 bits to 24 bits + while (--count >= 0) + { + rawWord = *shptr++; + *outptr++ = (rawWord & 0x7c00) >> 7; + *outptr++ = (rawWord & 0x03e0) >> 2; + *outptr++ = (rawWord & 0x001f) << 3; + } + } + break; + case VTK_RGBA: + { // unpack 16 bits to 32 bits + while (--count >= 0) + { + rawWord = *shptr++; + *outptr++ = (rawWord & 0x7c00) >> 7; + *outptr++ = (rawWord & 0x03e0) >> 2; + *outptr++ = (rawWord & 0x001f) << 3; + *outptr++ = alpha; + } + break; + } + } + } + } + case 24: + { + inptr += 3*start; + switch (this->OutputFormat) + { + case VTK_RGB: + { // must do BGR to RGB conversion + outptr += 3; + while (--count >= 0) + { + *--outptr = *inptr++; + *--outptr = *inptr++; + *--outptr = *inptr++; + outptr += 6; + } + } + break; + case VTK_RGBA: + { // must do BGR to RGBX conversion + outptr += 4; + while (--count >= 0) + { + *--outptr = alpha; + *--outptr = *inptr++; + *--outptr = *inptr++; + *--outptr = *inptr++; + outptr += 8; + } + } + break; + } + } + break; + case 32: + inptr += 4*start; + switch (this->OutputFormat) + { + case VTK_RGB: + { // must do BGRX to RGB conversion + outptr += 3; + while (--count >= 0) + { + *--outptr = *inptr++; + *--outptr = *inptr++; + *--outptr = *inptr++; + inptr++; + outptr += 6; + } + } + break; + case VTK_RGBA: + { + outptr += 4; + while (--count >= 0) + { + *--outptr = alpha; + *--outptr = *inptr++; + *--outptr = *inptr++; + *--outptr = *inptr++; + inptr++; + outptr += 8; + } + } + break; + } + break; + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::VideoFormatDialog() +{ + this->Initialize(); + if (!this->Initialized) + { + return; + } + + //if (!this->Internal->CapDriverCaps.fHasDlgVideoFormat) + // { + // MessageBox(this->Internal->ParentWnd,"The video device has no Format dialog.","", + // MB_OK | MB_ICONEXCLAMATION); + // return; + // } + + capGetStatus(this->Internal->CapWnd,&this->Internal->CapStatus,sizeof(CAPSTATUS)); + if (this->Internal->CapStatus.fCapturingNow) + { + MessageBox(this->Internal->ParentWnd, "Can't alter video format while grabbing.","", + MB_OK | MB_ICONEXCLAMATION); + return; + } + + int success = capDlgVideoFormat(this->Internal->CapWnd); + if (success) + { + this->FrameBufferMutex->Lock(); + this->DoVFWFormatCheck(); + this->FrameBufferMutex->Unlock(); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::VideoSourceDialog() +{ + this->Initialize(); + if (!this->Initialized) + { + return; + } + + //if (!this->Internal->CapDriverCaps.fHasDlgVideoSource) + // { + // MessageBox(this->Internal->ParentWnd,"The video device has no Source dialog.","", + // MB_OK | MB_ICONEXCLAMATION); + // return; + // } + + capGetStatus(this->Internal->CapWnd,&this->Internal->CapStatus,sizeof(CAPSTATUS)); + if (this->Internal->CapStatus.fCapturingNow) + { + MessageBox(this->Internal->ParentWnd, "Can't alter video source while grabbing.","", + MB_OK | MB_ICONEXCLAMATION); + return; + } + + int success = capDlgVideoSource(this->Internal->CapWnd); + if (success) + { + this->FrameBufferMutex->Lock(); + this->DoVFWFormatCheck(); + this->FrameBufferMutex->Unlock(); + } +} + +//---------------------------------------------------------------------------- +// try for the specified frame size +void vtkWin32VideoSource::SetFrameSize(int x, int y, int z) +{ + if (x == this->FrameSize[0] && + y == this->FrameSize[1] && + z == this->FrameSize[2]) + { + return; + } + + if (x < 1 || y < 1 || z != 1) + { + vtkErrorMacro(<< "SetFrameSize: Illegal frame size"); + return; + } + + this->FrameSize[0] = x; + this->FrameSize[1] = y; + this->FrameSize[2] = z; + this->Modified(); + + if (this->Initialized) + { + this->FrameBufferMutex->Lock(); + this->UpdateFrameBuffer(); + this->DoVFWFormatSetup(); + this->FrameBufferMutex->Unlock(); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::SetFrameRate(float rate) +{ + if (rate == this->FrameRate) + { + return; + } + + this->FrameRate = rate; + this->Modified(); + + if (this->Initialized) + { + capCaptureGetSetup(this->Internal->CapWnd,&this->Internal->CaptureParms,sizeof(CAPTUREPARMS)); + if (this->FrameRate > 0) + { + this->Internal->CaptureParms.dwRequestMicroSecPerFrame = + int(1000000/this->FrameRate); + } + else + { + this->Internal->CaptureParms.dwRequestMicroSecPerFrame = 0; + } + capCaptureSetSetup(this->Internal->CapWnd,&this->Internal->CaptureParms,sizeof(CAPTUREPARMS)); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::SetOutputFormat(int format) +{ + if (format == this->OutputFormat) + { + return; + } + + this->OutputFormat = format; + + // convert color format to number of scalar components + int numComponents; + + switch (this->OutputFormat) + { + case VTK_RGBA: + numComponents = 4; + break; + case VTK_RGB: + numComponents = 3; + break; + case VTK_LUMINANCE: + numComponents = 1; + break; + default: + numComponents = 0; + vtkErrorMacro(<< "SetOutputFormat: Unrecognized color format."); + break; + } + this->NumberOfScalarComponents = numComponents; + + if (this->FrameBufferBitsPerPixel != numComponents*8) + { + this->FrameBufferMutex->Lock(); + this->FrameBufferBitsPerPixel = numComponents*8; + if (this->Initialized) + { + this->UpdateFrameBuffer(); + this->DoVFWFormatSetup(); + } + this->FrameBufferMutex->Unlock(); + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// check the current video format and set up the VTK video framebuffer to match +void vtkWin32VideoSource::DoVFWFormatCheck() +{ + // get the real video format + int formatSize = capGetVideoFormatSize(this->Internal->CapWnd); + if (formatSize > this->BitMapSize) + { + if (this->Internal->BitMapPtr) + { + delete [] ((char *)this->Internal->BitMapPtr); + } + this->Internal->BitMapPtr = (LPBITMAPINFO) new char[formatSize]; + this->BitMapSize = formatSize; + } + capGetVideoFormat(this->Internal->CapWnd,this->Internal->BitMapPtr,formatSize); + + int bpp = this->Internal->BitMapPtr->bmiHeader.biBitCount; + int width = this->Internal->BitMapPtr->bmiHeader.biWidth; + int height = this->FrameSize[1] = this->Internal->BitMapPtr->bmiHeader.biHeight; + int compression = this->Internal->BitMapPtr->bmiHeader.biCompression; + + if (compression == VTK_BI_UYVY) + { + this->FlipFrames = 1; + } + else if (compression == BI_RGB) + { + this->FlipFrames = 0; + } + else + { + char fourcchex[16], fourcc[8]; + sprintf(fourcchex,"0x%08x",compression); + for (int i = 0; i < 4; i++) + { + fourcc[i] = (compression >> (8*i)) & 0xff; + if (!isprint(fourcc[i])) + { + fourcc[i] = '?'; + } + } + fourcc[4] = '\0'; + vtkWarningMacro(<< "DoVFWFormatCheck: video compression mode " << + fourcchex << " \"" << fourcc << "\": can't grab"); + } + + if (bpp != this->FrameBufferBitsPerPixel) + { + switch (bpp) + { + case 1: + case 4: + case 8: + this->OutputFormat = VTK_LUMINANCE; + this->NumberOfScalarComponents = 1; + break; + case 16: + if (compression != VTK_BI_UYVY) + { + this->OutputFormat = VTK_RGB; + this->NumberOfScalarComponents = 3; + } + break; + case 24: + case 32: + if (this->OutputFormat != VTK_RGBA) + { + this->OutputFormat = VTK_RGB; + this->NumberOfScalarComponents = 3; + } + break; + } + } + + if (bpp != this->FrameBufferBitsPerPixel || + this->FrameSize[0] != width || + this->FrameSize[1] != height) + { + this->FrameBufferBitsPerPixel = bpp; + this->FrameSize[0] = width; + this->FrameSize[1] = height; + this->Modified(); + this->UpdateFrameBuffer(); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32VideoSource::DoVFWFormatSetup() +{ + static int colorBits[3] = { 24, 32, 16 }; + static int greyBits[3] = { 8, 4, 1 }; + int i, bytesPerRow, bitCount; + + // get the real video format + int formatSize = capGetVideoFormatSize(this->Internal->CapWnd); + if (formatSize > this->BitMapSize) + { + if (this->Internal->BitMapPtr) + { + delete [] ((char *)this->Internal->BitMapPtr); + } + this->Internal->BitMapPtr = (LPBITMAPINFO) new char[formatSize]; + this->BitMapSize = formatSize; + } + capGetVideoFormat(this->Internal->CapWnd,this->Internal->BitMapPtr,formatSize); + + // set the format of the captured frames + this->Internal->BitMapPtr->bmiHeader.biWidth = this->FrameSize[0]; + this->Internal->BitMapPtr->bmiHeader.biHeight = this->FrameSize[1]; + this->Internal->BitMapPtr->bmiHeader.biCompression = BI_RGB; + this->Internal->BitMapPtr->bmiHeader.biClrUsed = 0; + this->Internal->BitMapPtr->bmiHeader.biClrImportant = 0; + + for (i = 0; i < 4; i++) + { // try for a + if (this->OutputFormat == VTK_RGBA || this->OutputFormat == VTK_RGB) + { + bitCount = colorBits[i]; + } + else + { + bitCount = greyBits[i]; + } + bytesPerRow = (this->FrameSize[0]*bitCount+7)/8; + bytesPerRow += bytesPerRow % this->FrameBufferRowAlignment; + this->Internal->BitMapPtr->bmiHeader.biBitCount = bitCount; + this->Internal->BitMapPtr->bmiHeader.biSizeImage = bytesPerRow*this->FrameSize[1]; + if (capSetVideoFormat(this->Internal->CapWnd,this->Internal->BitMapPtr, + sizeof(BITMAPINFOHEADER))) + { + break; + } + } + if (i > 4) + { + vtkWarningMacro(<< "DoVFWFormatSetup: invalid video format for device"\ + << " (" << GetLastError() << ")"); + } + this->DoVFWFormatCheck(); +} + + + + + + + + + + + diff --git a/Hybrid/vtkWin32VideoSource.h b/Hybrid/vtkWin32VideoSource.h new file mode 100644 index 0000000..9514458 --- /dev/null +++ b/Hybrid/vtkWin32VideoSource.h @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32VideoSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWin32VideoSource - Video-for-Windows video digitizer +// .SECTION Description +// vtkWin32VideoSource grabs frames or streaming video from a +// Video for Windows compatible device on the Win32 platform. +// .SECTION Caveats +// With some capture cards, if this class is leaked and ReleaseSystemResources +// is not called, you may have to reboot before you can capture again. +// vtkVideoSource used to keep a global list and delete the video sources +// if your program leaked, due to exit crashes that was removed. +// +// .SECTION See Also +// vtkVideoSource vtkMILVideoSource + +#ifndef __vtkWin32VideoSource_h +#define __vtkWin32VideoSource_h + +#include "vtkVideoSource.h" + +class vtkWin32VideoSourceInternal; + +class VTK_HYBRID_EXPORT vtkWin32VideoSource : public vtkVideoSource +{ +public: + static vtkWin32VideoSource *New(); + vtkTypeRevisionMacro(vtkWin32VideoSource,vtkVideoSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Standard VCR functionality: Record incoming video. + void Record(); + + // Description: + // Standard VCR functionality: Play recorded video. + void Play(); + + // Description: + // Standard VCR functionality: Stop recording or playing. + void Stop(); + + // Description: + // Grab a single video frame. + void Grab(); + + // Description: + // Request a particular frame size (set the third value to 1). + void SetFrameSize(int x, int y, int z); + virtual void SetFrameSize(int dim[3]) { + this->SetFrameSize(dim[0], dim[1], dim[2]); }; + + // Description: + // Request a particular frame rate (default 30 frames per second). + void SetFrameRate(float rate); + + // Description: + // Request a particular output format (default: VTK_RGB). + void SetOutputFormat(int format); + + // Description: + // Turn on/off the preview (overlay) window. + void SetPreview(int p); + vtkBooleanMacro(Preview,int); + vtkGetMacro(Preview,int); + + // Description: + // Bring up a modal dialog box for video format selection. + void VideoFormatDialog(); + + // Description: + // Bring up a modal dialog box for video input selection. + void VideoSourceDialog(); + + // Description: + // Initialize the driver (this is called automatically when the + // first grab is done). + void Initialize(); + + // Description: + // Free the driver (this is called automatically inside the + // destructor). + void ReleaseSystemResources(); + + // Description: + // For internal use only + void LocalInternalGrab(void*); + void OnParentWndDestroy(); + +protected: + vtkWin32VideoSource(); + ~vtkWin32VideoSource(); + + char WndClassName[16]; + int BitMapSize; + int Preview; + + vtkWin32VideoSourceInternal *Internal; + + void CheckBuffer(); + void UnpackRasterLine(char *outptr, char *inptr, + int start, int count); + + void DoVFWFormatSetup(); + void DoVFWFormatCheck(); + +private: + vtkWin32VideoSource(const vtkWin32VideoSource&); // Not implemented. + void operator=(const vtkWin32VideoSource&); // Not implemented. +}; + +#endif + + + + + diff --git a/Hybrid/vtkXYPlotActor.cxx b/Hybrid/vtkXYPlotActor.cxx new file mode 100644 index 0000000..8bfef5c --- /dev/null +++ b/Hybrid/vtkXYPlotActor.cxx @@ -0,0 +1,2148 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXYPlotActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXYPlotActor.h" + +#include "vtkAppendPolyData.h" +#include "vtkAxisActor2D.h" +#include "vtkCellArray.h" +#include "vtkDataObjectCollection.h" +#include "vtkDataSetCollection.h" +#include "vtkFieldData.h" +#include "vtkDoubleArray.h" +#include "vtkGlyph2D.h" +#include "vtkGlyphSource2D.h" +#include "vtkIntArray.h" +#include "vtkLegendBoxActor.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPlanes.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkProperty2D.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" + +#define VTK_MAX_PLOTS 50 + +vtkCxxRevisionMacro(vtkXYPlotActor, "$Revision: 1.59 $"); +vtkStandardNewMacro(vtkXYPlotActor); + +vtkCxxSetObjectMacro(vtkXYPlotActor,TitleTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(vtkXYPlotActor,AxisLabelTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(vtkXYPlotActor,AxisTitleTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Instantiate object +vtkXYPlotActor::vtkXYPlotActor() +{ + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.25,0.25); + this->Position2Coordinate->SetValue(0.5, 0.5); + + this->InputList = vtkDataSetCollection::New(); + this->SelectedInputScalars = NULL; + this->SelectedInputScalarsComponent = vtkIntArray::New(); + this->DataObjectInputList = vtkDataObjectCollection::New(); + + this->Title = NULL; + this->XTitle = new char[7]; + sprintf(this->XTitle,"%s","X Axis"); + this->YTitle = new char[7]; + sprintf(this->YTitle,"%s","Y Axis"); + + this->XValues = VTK_XYPLOT_INDEX; + + this->NumberOfXLabels = 5; + this->NumberOfYLabels = 5; + + this->TitleTextProperty = vtkTextProperty::New(); + this->TitleTextProperty->SetBold(1); + this->TitleTextProperty->SetItalic(1); + this->TitleTextProperty->SetShadow(1); + this->TitleTextProperty->SetFontFamilyToArial(); + + this->AxisLabelTextProperty = vtkTextProperty::New(); + this->AxisLabelTextProperty->ShallowCopy(this->TitleTextProperty); + + this->AxisTitleTextProperty = vtkTextProperty::New(); + this->AxisTitleTextProperty->ShallowCopy(this->AxisLabelTextProperty); + + this->LabelFormat = new char[8]; + sprintf(this->LabelFormat,"%s","%-#6.3g"); + + this->Logx = 0; + + this->XRange[0] = 0.0; + this->XRange[1] = 0.0; + this->YRange[0] = 0.0; + this->YRange[1] = 0.0; + + this->Border = 5; + this->PlotLines = 1; + this->PlotPoints = 0; + this->PlotCurveLines = 0; + this->PlotCurvePoints = 0; + this->ExchangeAxes = 0; + this->ReverseXAxis = 0; + this->ReverseYAxis = 0; + + this->TitleMapper = vtkTextMapper::New(); + this->TitleActor = vtkActor2D::New(); + this->TitleActor->SetMapper(this->TitleMapper); + this->TitleActor->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + + this->XAxis = vtkAxisActor2D::New(); + this->XAxis->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + this->XAxis->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); + this->XAxis->SetProperty(this->GetProperty()); + + this->YAxis = vtkAxisActor2D::New(); + this->YAxis->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + this->YAxis->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); + this->YAxis->SetProperty(this->GetProperty()); + + this->NumberOfInputs = 0; + this->PlotData = NULL; + this->PlotGlyph = NULL; + this->PlotAppend = NULL; + this->PlotMapper = NULL; + this->PlotActor = NULL; + + this->ViewportCoordinate[0] = 0.0; + this->ViewportCoordinate[1] = 0.0; + this->PlotCoordinate[0] = 0.0; + this->PlotCoordinate[1] = 0.0; + + this->DataObjectPlotMode = VTK_XYPLOT_COLUMN; + this->XComponent = vtkIntArray::New(); + this->XComponent->SetNumberOfValues(VTK_MAX_PLOTS); + this->YComponent = vtkIntArray::New(); + this->YComponent->SetNumberOfValues(VTK_MAX_PLOTS); + + this->LinesOn = vtkIntArray::New(); + this->LinesOn->SetNumberOfValues(VTK_MAX_PLOTS); + this->PointsOn = vtkIntArray::New(); + this->PointsOn->SetNumberOfValues(VTK_MAX_PLOTS); + for (int i=0; iXComponent->SetValue(i,0); + this->YComponent->SetValue(i,0); + this->LinesOn->SetValue(i,this->PlotLines); + this->PointsOn->SetValue(i,this->PlotPoints); + } + + this->Legend = 0; + this->LegendPosition[0] = 0.85; + this->LegendPosition[1] = 0.75; + this->LegendPosition2[0] = 0.15; + this->LegendPosition2[1] = 0.20; + this->LegendActor = vtkLegendBoxActor::New(); + this->LegendActor->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + this->LegendActor->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); + this->LegendActor->GetPosition2Coordinate()->SetReferenceCoordinate(NULL); + this->LegendActor->BorderOff(); + this->LegendActor->SetNumberOfEntries(VTK_MAX_PLOTS); //initial allocation + this->GlyphSource = vtkGlyphSource2D::New(); + this->GlyphSource->SetGlyphTypeToNone(); + this->GlyphSource->DashOn(); + this->GlyphSource->FilledOff(); + this->GlyphSize = 0.020; + + this->ClipPlanes = vtkPlanes::New(); + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(4); + this->ClipPlanes->SetPoints(pts); + pts->Delete(); + vtkDoubleArray *n = vtkDoubleArray::New(); + n->SetNumberOfComponents(3); + n->SetNumberOfTuples(4); + this->ClipPlanes->SetNormals(n); + n->Delete(); + + this->CachedSize[0] = 0; + this->CachedSize[1] = 0; +} + +//---------------------------------------------------------------------------- +vtkXYPlotActor::~vtkXYPlotActor() +{ + // Get rid of the list of array names. + int num = this->InputList->GetNumberOfItems(); + if (this->SelectedInputScalars) + { + for (int i = 0; i < num; ++i) + { + if (this->SelectedInputScalars[i]) + { + delete [] this->SelectedInputScalars[i]; + this->SelectedInputScalars[i] = NULL; + } + } + delete [] this->SelectedInputScalars; + this->SelectedInputScalars = NULL; + } + this->SelectedInputScalarsComponent->Delete(); + this->SelectedInputScalarsComponent = NULL; + + // Now we can get rid of the inputs. + this->InputList->Delete(); + this->InputList = NULL; + + this->DataObjectInputList->Delete(); + this->DataObjectInputList = NULL; + + this->TitleMapper->Delete(); + this->TitleMapper = NULL; + this->TitleActor->Delete(); + this->TitleActor = NULL; + + this->SetTitle(0); + this->SetXTitle(0); + this->SetYTitle(0); + this->SetLabelFormat(0); + + this->XAxis->Delete(); + this->YAxis->Delete(); + + this->InitializeEntries(); + + this->LegendActor->Delete(); + this->GlyphSource->Delete(); + this->ClipPlanes->Delete(); + + this->XComponent->Delete(); + this->YComponent->Delete(); + + this->LinesOn->Delete(); + this->PointsOn->Delete(); + + this->SetTitleTextProperty(NULL); + this->SetAxisLabelTextProperty(NULL); + this->SetAxisTitleTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::InitializeEntries() +{ + if ( this->NumberOfInputs > 0 ) + { + for (int i=0; iNumberOfInputs; i++) + { + this->PlotData[i]->Delete(); + this->PlotGlyph[i]->Delete(); + this->PlotAppend[i]->Delete(); + this->PlotMapper[i]->Delete(); + this->PlotActor[i]->Delete(); + }//for all entries + delete [] this->PlotData; this->PlotData = NULL; + delete [] this->PlotGlyph; this->PlotGlyph = NULL; + delete [] this->PlotAppend; this->PlotAppend = NULL; + delete [] this->PlotMapper; this->PlotMapper = NULL; + delete [] this->PlotActor; this->PlotActor = NULL; + this->NumberOfInputs = 0; + }//if entries have been defined +} + +//---------------------------------------------------------------------------- +// Add a dataset and array to the list of data to plot. +void vtkXYPlotActor::AddInput(vtkDataSet *ds, const char *arrayName, int component) +{ + int idx, num; + char** newNames; + + // I cannot change the input list, because the user has direct + // access to the collection. I cannot store the index of the array, + // because the index might change from render to render ... + // I have to store the list of string array names. + + // I believe idx starts at 1 and goes to "NumberOfItems". + idx = this->InputList->IsItemPresent(ds); + if (idx > 0) + { // Return if arrays are the same. + if (arrayName == NULL && this->SelectedInputScalars[idx-1] == NULL && + component == this->SelectedInputScalarsComponent->GetValue(idx-1)) + { + return; + } + if (arrayName != NULL && this->SelectedInputScalars[idx-1] != NULL && + strcmp(arrayName, this->SelectedInputScalars[idx-1]) == 0 && + component == this->SelectedInputScalarsComponent->GetValue(idx-1)) + { + return; + } + } + + // The input/array/component must be a unique combination. Add it to our input list. + + // Now reallocate the list of strings and add the new value. + num = this->InputList->GetNumberOfItems(); + newNames = new char*[num+1]; + for (idx = 0; idx < num; ++idx) + { + newNames[idx] = this->SelectedInputScalars[idx]; + } + if (arrayName == NULL) + { + newNames[num] = NULL; + } + else + { + newNames[num] = new char[strlen(arrayName)+1]; + strcpy(newNames[num],arrayName); + } + delete [] this->SelectedInputScalars; + this->SelectedInputScalars = newNames; + + // Save the component in the int array. + this->SelectedInputScalarsComponent->InsertValue(num, component); + + // Add the data set to the collection + this->InputList->AddItem(ds); + + // In case of multiple use of a XYPlotActor the NumberOfEntries could be set + // to n. Then when a call to SetEntryString(n+1, bla) was done the string was lost + // Need to update the number of entries for the legend actor + this->LegendActor->SetNumberOfEntries(this->LegendActor->GetNumberOfEntries()+1); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::RemoveAllInputs() +{ + int idx, num; + + num = this->InputList->GetNumberOfItems(); + this->InputList->RemoveAllItems(); + + for (idx = 0; idx < num; ++idx) + { + if (this->SelectedInputScalars[idx]) + { + delete [] this->SelectedInputScalars[idx]; + this->SelectedInputScalars[idx] = NULL; + } + } + this->SelectedInputScalarsComponent->Reset(); + + this->DataObjectInputList->RemoveAllItems(); +} + +//---------------------------------------------------------------------------- +// Remove a dataset from the list of data to plot. +void vtkXYPlotActor::RemoveInput(vtkDataSet *ds, const char *arrayName, int component) +{ + int idx, num; + vtkDataSet *input; + int found = -1; + + // This is my own find routine, because the array names have to match also. + num = this->InputList->GetNumberOfItems(); + vtkCollectionSimpleIterator dsit; + this->InputList->InitTraversal(dsit); + for (idx = 0; idx < num && found == -1; ++idx) + { + input = this->InputList->GetNextDataSet(dsit); + if (input == ds) + { + if (arrayName == NULL && this->SelectedInputScalars[idx] == NULL && + component == this->SelectedInputScalarsComponent->GetValue(idx)) + { + found = idx; + } + if (arrayName != NULL && this->SelectedInputScalars[idx] != NULL && + strcmp(arrayName, this->SelectedInputScalars[idx]) == 0 && + component == this->SelectedInputScalarsComponent->GetValue(idx)) + { + found = idx; + } + } + } + + if (found == -1) + { + return; + } + + this->Modified(); + // Collections index their items starting at 1. + this->InputList->RemoveItem(found); + + // Do not bother reallocating the SelectedInputScalars + // string array to make it smaller. + if (this->SelectedInputScalars[found]) + { + delete [] this->SelectedInputScalars[found]; + this->SelectedInputScalars[found] = NULL; + } + for (idx = found+1; idx < num; ++idx) + { + this->SelectedInputScalars[idx-1] = this->SelectedInputScalars[idx]; + this->SelectedInputScalarsComponent->SetValue(idx-1, + this->SelectedInputScalarsComponent->GetValue(idx)); + } + // Reseting the last item is not really necessary, + // but to be clean we do it anyway. + this->SelectedInputScalarsComponent->SetValue(num-1, -1); + this->SelectedInputScalars[num-1] = NULL; +} + +//---------------------------------------------------------------------------- +// Add a data object to the list of data to plot. +void vtkXYPlotActor::AddDataObjectInput(vtkDataObject *in) +{ + if ( ! this->DataObjectInputList->IsItemPresent(in) ) + { + this->Modified(); + this->DataObjectInputList->AddItem(in); + } +} + +//---------------------------------------------------------------------------- +// Remove a data object from the list of data to plot. +void vtkXYPlotActor::RemoveDataObjectInput(vtkDataObject *in) +{ + if ( this->DataObjectInputList->IsItemPresent(in) ) + { + this->Modified(); + this->DataObjectInputList->RemoveItem(in); + } +} + +//---------------------------------------------------------------------------- +// Plot scalar data for each input dataset. +int vtkXYPlotActor::RenderOverlay(vtkViewport *viewport) +{ + int renderedSomething = 0; + + // Make sure input is up to date. + if ( this->InputList->GetNumberOfItems() < 1 && + this->DataObjectInputList->GetNumberOfItems() < 1 ) + { + vtkErrorMacro(<< "Nothing to plot!"); + return 0; + } + + renderedSomething += this->XAxis->RenderOverlay(viewport); + renderedSomething += this->YAxis->RenderOverlay(viewport); + if ( this->Title ) + { + renderedSomething += this->TitleActor->RenderOverlay(viewport); + } + for (int i=0; i < this->NumberOfInputs; i++) + { + renderedSomething += this->PlotActor[i]->RenderOverlay(viewport); + } + if ( this->Legend ) + { + renderedSomething += this->LegendActor->RenderOverlay(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +// Plot scalar data for each input dataset. +int vtkXYPlotActor::RenderOpaqueGeometry(vtkViewport *viewport) +{ + unsigned long mtime, dsMtime; + vtkDataSet *ds; + vtkDataObject *dobj; + int numDS, numDO, renderedSomething=0; + + // Initialize + // Make sure input is up to date. + numDS = this->InputList->GetNumberOfItems(); + numDO = this->DataObjectInputList->GetNumberOfItems(); + if ( numDS > 0 ) + { + vtkDebugMacro(<<"Plotting input data sets"); + vtkCollectionSimpleIterator dsit; + for (mtime=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); ) + { + ds->Update(); + dsMtime = ds->GetMTime(); + if ( dsMtime > mtime ) + { + mtime = dsMtime; + } + } + } + else if ( numDO > 0 ) + { + vtkDebugMacro(<<"Plotting input data objects"); + vtkCollectionSimpleIterator doit; + for (mtime=0, this->DataObjectInputList->InitTraversal(doit); + (dobj = this->DataObjectInputList->GetNextDataObject(doit)); ) + { + dobj->Update(); + dsMtime = dobj->GetMTime(); + if ( dsMtime > mtime ) + { + mtime = dsMtime; + } + } + } + else + { + vtkErrorMacro(<< "Nothing to plot!"); + return 0; + } + + if (this->Title && this->Title[0] && !this->TitleTextProperty) + { + vtkErrorMacro(<< "Need a title text property to render plot title"); + return 0; + } + + // Check modified time to see whether we have to rebuild. + // Pay attention that GetMTime() has been redefined (see below) + + int *size=viewport->GetSize(); + if (mtime > this->BuildTime || + size[0] != this->CachedSize[0] || size[1] != this->CachedSize[1] || + this->GetMTime() > this->BuildTime || + (this->Title && this->Title[0] && + this->TitleTextProperty->GetMTime() > this->BuildTime) || + (this->AxisLabelTextProperty && + this->AxisLabelTextProperty->GetMTime() > this->BuildTime) || + (this->AxisTitleTextProperty && + this->AxisTitleTextProperty->GetMTime() > this->BuildTime)) + { + double range[2], yrange[2], xRange[2], yRange[2], interval, *lengths=NULL; + int pos[2], pos2[2], numTicks; + int stringSize[2]; + int num = ( numDS > 0 ? numDS : numDO ); + + vtkDebugMacro(<<"Rebuilding plot"); + this->CachedSize[0] = size[0]; + this->CachedSize[1] = size[1]; + + // manage legend + vtkDebugMacro(<<"Rebuilding legend"); + if ( this->Legend ) + { + int legPos[2], legPos2[2]; + int *p1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + int *p2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + legPos[0] = (int)(p1[0] + this->LegendPosition[0]*(p2[0]-p1[0])); + legPos2[0] = (int)(legPos[0] + this->LegendPosition2[0]*(p2[0]-p1[0])); + legPos[1] = (int)(p1[1] + this->LegendPosition[1]*(p2[1]-p1[1])); + legPos2[1] = (int)(legPos[1] + this->LegendPosition2[1]*(p2[1]-p1[1])); + + this->LegendActor->GetPositionCoordinate()->SetValue( + (double)legPos[0], (double)legPos[1]); + this->LegendActor->GetPosition2Coordinate()->SetValue( + (double)legPos2[0], (double)legPos2[1]); + this->LegendActor->SetNumberOfEntries(num); + for (int i=0; iLegendActor->GetEntrySymbol(i) ) + { + this->LegendActor->SetEntrySymbol(i,this->GlyphSource->GetOutput()); + } + if ( ! this->LegendActor->GetEntryString(i) ) + { + static char legendString[12]; + sprintf(legendString, "%s%d", "Curve ", i); + this->LegendActor->SetEntryString(i,legendString); + } + } + + this->LegendActor->SetPadding(2); + this->LegendActor->GetProperty()->DeepCopy(this->GetProperty()); + this->LegendActor->ScalarVisibilityOff(); + } + + // Rebuid text props + // Perform shallow copy here since each individual axis can be + // accessed through the class API (i.e. each individual axis text prop + // can be changed). Therefore, we can not just assign pointers otherwise + // each individual axis text prop would point to the same text prop. + + if (this->AxisLabelTextProperty && + this->AxisLabelTextProperty->GetMTime() > this->BuildTime) + { + if (this->XAxis->GetTitleTextProperty()) + { + this->XAxis->GetLabelTextProperty()->ShallowCopy( + this->AxisLabelTextProperty); + } + if (this->YAxis->GetTitleTextProperty()) + { + this->YAxis->GetLabelTextProperty()->ShallowCopy( + this->AxisLabelTextProperty); + } + } + + if (this->AxisTitleTextProperty && + this->AxisTitleTextProperty->GetMTime() > this->BuildTime) + { + if (this->XAxis->GetTitleTextProperty()) + { + this->XAxis->GetTitleTextProperty()->ShallowCopy( + this->AxisTitleTextProperty); + } + if (this->YAxis->GetTitleTextProperty()) + { + this->YAxis->GetTitleTextProperty()->ShallowCopy( + this->AxisTitleTextProperty); + } + } + + // setup x-axis + vtkDebugMacro(<<"Rebuilding x-axis"); + + this->XAxis->SetTitle(this->XTitle); + this->XAxis->SetNumberOfLabels(this->NumberOfXLabels); + this->XAxis->SetProperty(this->GetProperty()); + + lengths = new double[num]; + if ( numDS > 0 ) //plotting data sets + { + this->ComputeXRange(range, lengths); + } + else + { + this->ComputeDORange(range, yrange, lengths); + } + if ( this->XRange[0] < this->XRange[1] ) + { + range[0] = this->XRange[0]; + range[1] = this->XRange[1]; + } + + vtkAxisActor2D::ComputeRange(range, xRange, this->NumberOfXLabels, + numTicks, interval); + if ( !this->ExchangeAxes ) + { + this->XComputedRange[0] = xRange[0]; + this->XComputedRange[1] = xRange[1]; + if ( this->ReverseXAxis ) + { + this->XAxis->SetRange(range[1],range[0]); + } + else + { + this->XAxis->SetRange(range[0],range[1]); + } + } + else + { + this->XComputedRange[1] = xRange[0]; + this->XComputedRange[0] = xRange[1]; + if ( this->ReverseYAxis ) + { + this->XAxis->SetRange(range[0],range[1]); + } + else + { + this->XAxis->SetRange(range[1],range[0]); + } + } + + // setup y-axis + vtkDebugMacro(<<"Rebuilding y-axis"); + this->YAxis->SetTitle(this->YTitle); + this->YAxis->SetNumberOfLabels(this->NumberOfYLabels); + + if ( this->YRange[0] >= this->YRange[1] ) + { + if ( numDS > 0 ) //plotting data sets + { + this->ComputeYRange(yrange); + } + } + else + { + yrange[0] = this->YRange[0]; + yrange[1] = this->YRange[1]; + } + vtkAxisActor2D::ComputeRange(yrange, yRange, this->NumberOfYLabels, + numTicks, interval); + + if ( !this->ExchangeAxes ) + { + this->YComputedRange[0] = yRange[0]; + this->YComputedRange[1] = yRange[1]; + if ( this->ReverseYAxis ) + { + this->YAxis->SetRange(yrange[0],yrange[1]); + } + else + { + this->YAxis->SetRange(yrange[1],yrange[0]); + } + } + else + { + this->YComputedRange[1] = yRange[0]; + this->YComputedRange[0] = yRange[1]; + if ( this->ReverseXAxis ) + { + this->YAxis->SetRange(yrange[1],yrange[0]); + } + else + { + this->YAxis->SetRange(yrange[0],yrange[1]); + } + } + + this->PlaceAxes(viewport, size, pos, pos2); + + // manage title + if (this->Title != NULL && this->Title[0]) + { + this->TitleMapper->SetInput(this->Title); + if (this->TitleTextProperty->GetMTime() > this->BuildTime) + { + this->TitleMapper->GetTextProperty()->ShallowCopy( + this->TitleTextProperty); + } + + vtkAxisActor2D::SetFontSize(viewport, + this->TitleMapper, + size, + 1.0, + stringSize); + + this->TitleActor->GetPositionCoordinate()->SetValue( + pos[0] + 0.5 * (pos2[0] - pos[0]) - stringSize[0] / 2.0, + pos2[1] - stringSize[1] / 2.0); + + this->TitleActor->SetProperty(this->GetProperty()); + } + + vtkDebugMacro(<<"Creating Plot Data"); + // Okay, now create the plot data and set up the pipeline + this->CreatePlotData(pos, pos2, xRange, yRange, lengths, numDS, numDO); + delete [] lengths; + + this->BuildTime.Modified(); + + }//if need to rebuild the plot + + vtkDebugMacro(<<"Rendering Axes"); + renderedSomething += this->XAxis->RenderOpaqueGeometry(viewport); + renderedSomething += this->YAxis->RenderOpaqueGeometry(viewport); + for (int i=0; i < this->NumberOfInputs; i++) + { + vtkDebugMacro(<<"Rendering plotactors"); + renderedSomething += this->PlotActor[i]->RenderOpaqueGeometry(viewport); + } + if ( this->Title ) + { + vtkDebugMacro(<<"Rendering titleactors"); + renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport); + } + if ( this->Legend ) + { + vtkDebugMacro(<<"Rendering legendeactors"); + renderedSomething += this->LegendActor->RenderOpaqueGeometry(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +const char *vtkXYPlotActor::GetXValuesAsString() +{ + switch (this->XValues) + { + case VTK_XYPLOT_INDEX: + return "Index"; + case VTK_XYPLOT_ARC_LENGTH: + return "ArcLength"; + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + return "NormalizedArcLength"; + default: + return "Value"; + } +} + +//---------------------------------------------------------------------------- +const char *vtkXYPlotActor::GetDataObjectPlotModeAsString() +{ + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + return "Plot Rows"; + } + else + { + return "Plot Columns"; + } +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkXYPlotActor::ReleaseGraphicsResources(vtkWindow *win) +{ + this->TitleActor->ReleaseGraphicsResources(win); + this->XAxis->ReleaseGraphicsResources(win); + this->YAxis->ReleaseGraphicsResources(win); + for (int i=0; i < this->NumberOfInputs; i++) + { + this->PlotActor[i]->ReleaseGraphicsResources(win); + } + this->LegendActor->ReleaseGraphicsResources(win); +} + +//---------------------------------------------------------------------------- +unsigned long vtkXYPlotActor::GetMTime() +{ + unsigned long mtime, mtime2; + mtime = this->vtkActor2D::GetMTime(); + + if (this->Legend) + { + mtime2 = this->LegendActor->GetMTime(); + if (mtime2 > mtime) + { + mtime = mtime2; + } + } + + return mtime; +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkIndent i2 = indent.GetNextIndent(); + vtkDataSet *input; + char *array; + int component; + int idx, num; + + this->Superclass::PrintSelf(os,indent); + + vtkCollectionSimpleIterator dsit; + this->InputList->InitTraversal(dsit); + num = this->InputList->GetNumberOfItems(); + os << indent << "DataSetInputs: " << endl; + for (idx = 0; idx < num; ++idx) + { + input = this->InputList->GetNextDataSet(dsit); + array = this->SelectedInputScalars[idx]; + component = this->SelectedInputScalarsComponent->GetValue((vtkIdType)idx); + if (array == NULL) + { + os << i2 << "(" << input << ") Default Scalars, Component = " << component << endl; + } + else + { + os << i2 << "(" << input << ") " << array << ", Component = " << component << endl; + } + } + + os << indent << "Input DataObjects:\n"; + this->DataObjectInputList->PrintSelf(os,indent.GetNextIndent()); + + if (this->TitleTextProperty) + { + os << indent << "Title Text Property:\n"; + this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Title Text Property: (none)\n"; + } + + if (this->AxisTitleTextProperty) + { + os << indent << "Axis Title Text Property:\n"; + this->AxisTitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Axis Title Text Property: (none)\n"; + } + + if (this->AxisLabelTextProperty) + { + os << indent << "Axis Label Text Property:\n"; + this->AxisLabelTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Axis Label Text Property: (none)\n"; + } + + os << indent << "Data Object Plot Mode: " << this->GetDataObjectPlotModeAsString() << endl; + + os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n"; + os << indent << "X Title: " + << (this->XTitle ? this->XTitle : "(none)") << "\n"; + os << indent << "Y Title: " + << (this->YTitle ? this->YTitle : "(none)") << "\n"; + + os << indent << "X Values: " << this->GetXValuesAsString() << endl; + os << indent << "Log X Values: " << (this->Logx ? "On\n" : "Off\n"); + + os << indent << "Plot global-points: " << (this->PlotPoints ? "On\n" : "Off\n"); + os << indent << "Plot global-lines: " << (this->PlotLines ? "On\n" : "Off\n"); + os << indent << "Plot per-curve points: " << (this->PlotCurvePoints ? "On\n" : "Off\n"); + os << indent << "Plot per-curve lines: " << (this->PlotCurveLines ? "On\n" : "Off\n"); + os << indent << "Exchange Axes: " << (this->ExchangeAxes ? "On\n" : "Off\n"); + os << indent << "Reverse X Axis: " << (this->ReverseXAxis ? "On\n" : "Off\n"); + os << indent << "Reverse Y Axis: " << (this->ReverseYAxis ? "On\n" : "Off\n"); + + os << indent << "Number Of X Labels: " << this->NumberOfXLabels << "\n"; + os << indent << "Number Of Y Labels: " << this->NumberOfYLabels << "\n"; + + os << indent << "Label Format: " << this->LabelFormat << "\n"; + os << indent << "Border: " << this->Border << "\n"; + + os << indent << "X Range: "; + if ( this->XRange[0] >= this->XRange[1] ) + { + os << indent << "(Automatically Computed)\n"; + } + else + { + os << "(" << this->XRange[0] << ", " << this->XRange[1] << ")\n"; + } + + os << indent << "Y Range: "; + if ( this->XRange[0] >= this->YRange[1] ) + { + os << indent << "(Automatically Computed)\n"; + } + else + { + os << "(" << this->YRange[0] << ", " << this->YRange[1] << ")\n"; + } + + os << indent << "Viewport Coordinate: (" + << this->ViewportCoordinate[0] << ", " + << this->ViewportCoordinate[1] << ")\n"; + + os << indent << "Plot Coordinate: (" + << this->PlotCoordinate[0] << ", " + << this->PlotCoordinate[1] << ")\n"; + + os << indent << "Legend: " << (this->Legend ? "On\n" : "Off\n"); + os << indent << "Legend Position: (" + << this->LegendPosition[0] << ", " + << this->LegendPosition[1] << ")\n"; + os << indent << "Legend Position2: (" + << this->LegendPosition2[0] << ", " + << this->LegendPosition2[1] << ")\n"; + + os << indent << "Glyph Size: " << this->GlyphSize << endl; + + os << indent << "Legend Actor:"; + this->LegendActor->PrintSelf( os << endl, i2); + os << indent << "Glyph Source:"; + this->GlyphSource->PrintSelf( os << endl, i2); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::ComputeXRange(double range[2], double *lengths) +{ + int dsNum; + vtkIdType numPts, ptId, maxNum; + double maxLength=0.0, xPrev[3], x[3]; + vtkDataSet *ds; + + range[0] = VTK_DOUBLE_MAX, range[1] = VTK_DOUBLE_MIN; + + vtkCollectionSimpleIterator dsit; + for ( dsNum=0, maxNum=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); dsNum++) + { + numPts = ds->GetNumberOfPoints(); + + if ( this->XValues != VTK_XYPLOT_INDEX ) + { + ds->GetPoint(0, xPrev); + for ( lengths[dsNum]=0.0, ptId=0; ptId < numPts; ptId++ ) + { + ds->GetPoint(ptId, x); + switch (this->XValues) + { + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 0) + { + if ( x[this->XComponent->GetValue(dsNum)] < range[0] ) + { + range[0] = x[this->XComponent->GetValue(dsNum)]; + } + if ( x[this->XComponent->GetValue(dsNum)] > range[1] ) + { + range[1] = x[this->XComponent->GetValue(dsNum)]; + } + } + else + { + //ensure range strictly > 0 for log + if ( (x[this->XComponent->GetValue(dsNum)]) < range[0] && + (x[this->XComponent->GetValue(dsNum)] > 0)) + { + range[0] = x[this->XComponent->GetValue(dsNum)]; + } + if ( (x[this->XComponent->GetValue(dsNum)] > range[1]) && + (x[this->XComponent->GetValue(dsNum)] > 0)) + { + range[1] = x[this->XComponent->GetValue(dsNum)]; + } + } + break; + default: + lengths[dsNum] += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xPrev[0] = x[0]; xPrev[1] = x[1]; xPrev[2] = x[2]; + } + }//for all points + if ( lengths[dsNum] > maxLength ) + { + maxLength = lengths[dsNum]; + } + }//if need to visit all points + + else //if ( this->XValues == VTK_XYPLOT_INDEX ) + { + if ( numPts > maxNum ) + { + maxNum = numPts; + } + } + }//over all datasets + + // determine the range + switch (this->XValues) + { + case VTK_XYPLOT_ARC_LENGTH: + range[0] = 0.0; + range[1] = maxLength; + break; + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + range[0] = 0.0; + range[1] = 1.0; + break; + case VTK_XYPLOT_INDEX: + range[0] = 0.0; + range[1] = (double)(maxNum - 1); + break; + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 1) + { + if (range[0] > range[1]) + { + range[0] = 0; + range[1] = 0; + } + else + { + range[0] = log10(range[0]); + range[1] = log10(range[1]); + } + } + break; //range computed in for loop above + default: + vtkErrorMacro(<< "Unkown X-Value option."); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::ComputeYRange(double range[2]) +{ + vtkDataSet *ds; + vtkDataArray *scalars; + double sRange[2]; + int count; + int component; + + range[0]=VTK_DOUBLE_MAX, range[1]=VTK_DOUBLE_MIN; + + vtkCollectionSimpleIterator dsit; + for ( this->InputList->InitTraversal(dsit), count = 0; + (ds = this->InputList->GetNextDataSet(dsit)); ++count) + { + scalars = ds->GetPointData()->GetScalars(this->SelectedInputScalars[count]); + component = this->SelectedInputScalarsComponent->GetValue(count); + if ( !scalars) + { + vtkErrorMacro(<<"No scalar data to plot!"); + continue; + } + if ( component < 0 || component >= scalars->GetNumberOfComponents()) + { + vtkErrorMacro(<<"Bad component!"); + continue; + } + + scalars->GetRange(sRange, component); + if ( sRange[0] < range[0] ) + { + range[0] = sRange[0]; + } + + if ( sRange[1] > range[1] ) + { + range[1] = sRange[1]; + } + }//over all datasets +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::ComputeDORange(double xrange[2], double yrange[2], + double *lengths) +{ + int i; + vtkDataObject *dobj; + vtkFieldData *field; + int doNum, numColumns; + vtkIdType numTuples, numRows, num, ptId, maxNum; + double maxLength=0.0, x, y, xPrev = 0.0; + vtkDataArray *array; + + xrange[0] = yrange[0] = VTK_DOUBLE_MAX; + xrange[1] = yrange[1] = -VTK_DOUBLE_MAX; + vtkCollectionSimpleIterator doit; + for ( doNum=0, maxNum=0, this->DataObjectInputList->InitTraversal(doit); + (dobj = this->DataObjectInputList->GetNextDataObject(doit)); doNum++) + { + lengths[doNum] = 0.0; + field = dobj->GetFieldData(); + numColumns = field->GetNumberOfComponents(); //number of "columns" + for (numRows = VTK_LARGE_ID, i=0; iGetNumberOfArrays(); i++) + { + array = field->GetArray(i); + numTuples = array->GetNumberOfTuples(); + if ( numTuples < numRows ) + { + numRows = numTuples; + } + } + + num = (this->DataObjectPlotMode == VTK_XYPLOT_ROW ? + numColumns : numRows); + + if ( this->XValues != VTK_XYPLOT_INDEX ) + { + // gather the information to form a plot + for ( ptId=0; ptId < num; ptId++ ) + { + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + x = field->GetComponent(this->XComponent->GetValue(doNum), ptId); + } + else //if ( this->DataObjectPlotMode == VTK_XYPLOT_COLUMN ) + { + x = field->GetComponent(ptId, this->XComponent->GetValue(doNum)); + } + if ( ptId == 0 ) + { + xPrev = x; + } + + switch (this->XValues) + { + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 0) + { + if ( x < xrange[0] ) + { + xrange[0] = x; + } + if ( x > xrange[1] ) + { + xrange[1] = x; + } + } + else //ensure positive values + { + if ( (x < xrange[0]) && (x > 0) ) + { + xrange[0] = x; + } + if ( x > xrange[1] && (x > 0) ) + { + xrange[1] = x; + } + } + break; + default: + lengths[doNum] += fabs(x-xPrev); + xPrev = x; + } + }//for all points + if ( lengths[doNum] > maxLength ) + { + maxLength = lengths[doNum]; + } + }//if all data has to be visited + + else //if (this->XValues == VTK_XYPLOT_INDEX) + { + if ( num > maxNum ) + { + maxNum = num; + } + } + + // Get the y-values + for ( ptId=0; ptId < num; ptId++ ) + { + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + y = field->GetComponent(this->YComponent->GetValue(doNum), ptId); + } + else //if ( this->DataObjectPlotMode == VTK_XYPLOT_COLUMN ) + { + y = field->GetComponent(ptId, this->YComponent->GetValue(doNum)); + } + if ( y < yrange[0] ) + { + yrange[0] = y; + } + if ( y > yrange[1] ) + { + yrange[1] = y; + } + }//over all y values + }//over all dataobjects + + // determine the range + switch (this->XValues) + { + case VTK_XYPLOT_ARC_LENGTH: + xrange[0] = 0.0; + xrange[1] = maxLength; + break; + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + xrange[0] = 0.0; + xrange[1] = 1.0; + break; + case VTK_XYPLOT_INDEX: + xrange[0] = 0.0; + xrange[1] = (double)(maxNum - 1); + break; + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 1) + { + xrange[0] = log10(xrange[0]); + xrange[1] = log10(xrange[1]); + } + break; + default: + vtkErrorMacro(<< "Unknown X-Value option"); + return; + } +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::CreatePlotData(int *pos, int *pos2, double xRange[2], + double yRange[2], double *lengths, + int numDS, int numDO) +{ + double xyz[3]; xyz[2] = 0.0; + int i, numLinePts, dsNum, doNum, num; + vtkIdType numPts, ptId, id; + double length, x[3], xPrev[3]; + vtkDataArray *scalars; + int component; + vtkDataSet *ds; + vtkCellArray *lines; + vtkPoints *pts; + int clippingRequired = 0; + + // Allocate resources for the polygonal plots + // + num = (numDS > numDO ? numDS : numDO); + this->InitializeEntries(); + this->NumberOfInputs = num; + this->PlotData = new vtkPolyData* [num]; + this->PlotGlyph = new vtkGlyph2D* [num]; + this->PlotAppend = new vtkAppendPolyData* [num]; + this->PlotMapper = new vtkPolyDataMapper2D* [num]; + this->PlotActor = new vtkActor2D* [num]; + for (i=0; iPlotData[i] = vtkPolyData::New(); + this->PlotGlyph[i] = vtkGlyph2D::New(); + this->PlotGlyph[i]->SetInput(this->PlotData[i]); + this->PlotGlyph[i]->SetScaleModeToDataScalingOff(); + this->PlotAppend[i] = vtkAppendPolyData::New(); + this->PlotAppend[i]->AddInput(this->PlotData[i]); + if ( this->LegendActor->GetEntrySymbol(i) != NULL && + this->LegendActor->GetEntrySymbol(i) != this->GlyphSource->GetOutput() ) + { + this->PlotGlyph[i]->SetSource(this->LegendActor->GetEntrySymbol(i)); + this->PlotGlyph[i]->SetScaleFactor(this->ComputeGlyphScale(i,pos,pos2)); + this->PlotAppend[i]->AddInput(this->PlotGlyph[i]->GetOutput()); + } + this->PlotMapper[i] = vtkPolyDataMapper2D::New(); + this->PlotMapper[i]->SetInput(this->PlotAppend[i]->GetOutput()); + this->PlotMapper[i]->ScalarVisibilityOff(); + this->PlotActor[i] = vtkActor2D::New(); + this->PlotActor[i]->SetMapper(this->PlotMapper[i]); + this->PlotActor[i]->GetProperty()->DeepCopy(this->GetProperty()); + if ( this->LegendActor->GetEntryColor(i)[0] < 0.0 ) + { + this->PlotActor[i]->GetProperty()->SetColor( + this->GetProperty()->GetColor()); + } + else + { + this->PlotActor[i]->GetProperty()->SetColor( + this->LegendActor->GetEntryColor(i)); + } + } + + // Prepare to receive data + this->GenerateClipPlanes(pos,pos2); + for (i=0; iNumberOfInputs; i++) + { + lines = vtkCellArray::New(); + pts = vtkPoints::New(); + + lines->Allocate(10,10); + pts->Allocate(10,10); + this->PlotData[i]->SetPoints(pts); + this->PlotData[i]->SetVerts(lines); + this->PlotData[i]->SetLines(lines); + + pts->Delete(); + lines->Delete(); + } + + // Okay, for each input generate plot data. Depending on the input + // we use either dataset or data object. + // + if ( numDS > 0 ) + { + vtkCollectionSimpleIterator dsit; + for ( dsNum=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); dsNum++ ) + { + clippingRequired = 0; + numPts = ds->GetNumberOfPoints(); + scalars = ds->GetPointData()->GetScalars(this->SelectedInputScalars[dsNum]); + if ( !scalars) + { + continue; + } + component = this->SelectedInputScalarsComponent->GetValue(dsNum); + if ( component < 0 || component >= scalars->GetNumberOfComponents()) + { + continue; + } + + pts = this->PlotData[dsNum]->GetPoints(); + lines = this->PlotData[dsNum]->GetLines(); + lines->InsertNextCell(0); //update the count later + + ds->GetPoint(0, xPrev); + for ( numLinePts=0, length=0.0, ptId=0; ptId < numPts; ptId++ ) + { + xyz[1] = scalars->GetComponent(ptId, component); + ds->GetPoint(ptId, x); + switch (this->XValues) + { + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + length += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xyz[0] = length / lengths[dsNum]; + xPrev[0] = x[0]; xPrev[1] = x[1]; xPrev[2] = x[2]; + break; + case VTK_XYPLOT_INDEX: + xyz[0] = (double)ptId; + break; + case VTK_XYPLOT_ARC_LENGTH: + length += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xyz[0] = length; + xPrev[0] = x[0]; xPrev[1] = x[1]; xPrev[2] = x[2]; + break; + case VTK_XYPLOT_VALUE: + xyz[0] = x[this->XComponent->GetValue(dsNum)]; + break; + default: + vtkErrorMacro(<< "Unknown X-Component option"); + } + + if ( this->GetLogx() == 1 ) + { + if (xyz[0] > 0) + { + xyz[0] = log10(xyz[0]); + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + } + else + { + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + }//for all input points + + lines->UpdateCellCount(numLinePts); + if ( clippingRequired ) + { + this->ClipPlotData(pos,pos2,this->PlotData[dsNum]); + } + }//loop over all input data sets + }//if plotting datasets + + else //plot data from data objects + { + vtkDataObject *dobj; + int numColumns; + vtkIdType numRows, numTuples; + vtkDataArray *array; + vtkFieldData *field; + vtkCollectionSimpleIterator doit; + for ( doNum=0, this->DataObjectInputList->InitTraversal(doit); + (dobj = this->DataObjectInputList->GetNextDataObject(doit)); + doNum++ ) + { + // determine the shape of the field + field = dobj->GetFieldData(); + numColumns = field->GetNumberOfComponents(); //number of "columns" + for (numRows = VTK_LARGE_ID, i=0; iGetNumberOfArrays(); i++) + { + array = field->GetArray(i); + numTuples = array->GetNumberOfTuples(); + if ( numTuples < numRows ) + { + numRows = numTuples; + } + } + + pts = this->PlotData[doNum]->GetPoints(); + lines = this->PlotData[doNum]->GetLines(); + lines->InsertNextCell(0); //update the count later + + numPts = (this->DataObjectPlotMode == VTK_XYPLOT_ROW ? + numColumns : numRows); + + // gather the information to form a plot + for ( numLinePts=0, length=0.0, ptId=0; ptId < numPts; ptId++ ) + { + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + x[0] = field->GetComponent(this->XComponent->GetValue(doNum),ptId); + xyz[1] = field->GetComponent(this->YComponent->GetValue(doNum),ptId); + } + else //if ( this->DataObjectPlotMode == VTK_XYPLOT_COLUMN ) + { + x[0] = field->GetComponent(ptId, this->XComponent->GetValue(doNum)); + xyz[1] = field->GetComponent(ptId, this->YComponent->GetValue(doNum)); + } + + switch (this->XValues) + { + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + length += fabs(x[0]-xPrev[0]); + xyz[0] = length / lengths[doNum]; + xPrev[0] = x[0]; + break; + case VTK_XYPLOT_INDEX: + xyz[0] = (double)ptId; + break; + case VTK_XYPLOT_ARC_LENGTH: + length += fabs(x[0]-xPrev[0]); + xyz[0] = length; + xPrev[0] = x[0]; + break; + case VTK_XYPLOT_VALUE: + xyz[0] = x[0]; + break; + default: + vtkErrorMacro(<< "Unknown X-Value option"); + } + + if ( this->GetLogx() == 1 ) + { + if (xyz[0] > 0) + { + xyz[0] = log10(xyz[0]); + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + } + else + { + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + }//for all input points + + lines->UpdateCellCount(numLinePts); + if ( clippingRequired ) + { + this->ClipPlotData(pos,pos2,this->PlotData[doNum]); + } + }//loop over all input data sets + } + + // Remove points/lines as directed by the user + for ( i = 0; i < num; i++) + { + if (!this->PlotCurveLines) + { + if ( !this->PlotLines ) + { + this->PlotData[i]->SetLines(NULL); + } + } + else + { + if ( this->GetPlotLines(i) == 0) + { + this->PlotData[i]->SetLines(NULL); + } + } + + if (!this->PlotCurvePoints) + { + if ( !this->PlotPoints || (this->LegendActor->GetEntrySymbol(i) && + this->LegendActor->GetEntrySymbol(i) != + this->GlyphSource->GetOutput())) + { + this->PlotData[i]->SetVerts(NULL); + } + } + else + { + if ( this->GetPlotPoints(i) == 0 || + (this->LegendActor->GetEntrySymbol(i) && + this->LegendActor->GetEntrySymbol(i) != + this->GlyphSource->GetOutput())) + { + this->PlotData[i]->SetVerts(NULL); + } + } + } +} + +//---------------------------------------------------------------------------- +// Position the axes taking into account the expected padding due to labels +// and titles. We want the result to fit in the box specified. This method +// knows something about how the vtkAxisActor2D functions, so it may have +// to change if that class changes dramatically. +// +void vtkXYPlotActor::PlaceAxes(vtkViewport *viewport, int *size, + int pos[2], int pos2[2]) +{ + int titleSizeX[2], titleSizeY[2], labelSizeX[2], labelSizeY[2]; + double labelFactorX, labelFactorY; + double fontFactorX, fontFactorY; + double tickOffsetX, tickOffsetY; + double tickLengthX, tickLengthY; + + vtkAxisActor2D *axisX; + vtkAxisActor2D *axisY; + + char str1[512], str2[512]; + + if (this->ExchangeAxes) + { + axisX = this->YAxis; + axisY = this->XAxis; + } + else + { + axisX = this->XAxis; + axisY = this->YAxis; + } + + fontFactorY = axisY->GetFontFactor(); + fontFactorX = axisX->GetFontFactor(); + + labelFactorY = axisY->GetLabelFactor(); + labelFactorX = axisX->GetLabelFactor(); + + // Create a dummy text mapper for getting font sizes + vtkTextMapper *textMapper = vtkTextMapper::New(); + vtkTextProperty *tprop = textMapper->GetTextProperty(); + + // Get the location of the corners of the box + int *p1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + int *p2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + + // Estimate the padding around the X and Y axes + tprop->ShallowCopy(axisX->GetTitleTextProperty()); + textMapper->SetInput(axisX->GetTitle()); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, fontFactorX, titleSizeX); + + tprop->ShallowCopy(axisY->GetTitleTextProperty()); + textMapper->SetInput(axisY->GetTitle()); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, fontFactorY, titleSizeY); + + // At this point the thing to do would be to actually ask the Y axis + // actor to return the largest label. + // In the meantime, let's try with the min and max + sprintf(str1, axisY->GetLabelFormat(), axisY->GetAdjustedRange()[0]); + sprintf(str2, axisY->GetLabelFormat(), axisY->GetAdjustedRange()[1]); + tprop->ShallowCopy(axisY->GetLabelTextProperty()); + textMapper->SetInput(strlen(str1) > strlen(str2) ? str1 : str2); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, labelFactorY * fontFactorY, labelSizeY); + + // We do only care of the height of the label in the X axis, so let's + // use the min for example + sprintf(str1, axisX->GetLabelFormat(), axisX->GetAdjustedRange()[0]); + tprop->ShallowCopy(axisX->GetLabelTextProperty()); + textMapper->SetInput(str1); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, labelFactorX * fontFactorX, labelSizeX); + + tickOffsetX = axisX->GetTickOffset(); + tickOffsetY = axisY->GetTickOffset(); + tickLengthX = axisX->GetTickLength(); + tickLengthY = axisY->GetTickLength(); + + // Okay, estimate the size + pos[0] = (int)(p1[0] + titleSizeY[0] + 2.0 * tickOffsetY + tickLengthY + + labelSizeY[0] + this->Border); + + pos[1] = (int)(p1[1] + titleSizeX[1] + 2.0 * tickOffsetX + tickLengthX + + labelSizeX[1] + this->Border); + + pos2[0] = (int)(p2[0] - labelSizeY[0] / 2 - tickOffsetY - this->Border); + + pos2[1] = (int)(p2[1] - labelSizeX[1] / 2 - tickOffsetX - this->Border); + + // Now specify the location of the axes + axisX->GetPositionCoordinate()->SetValue( + (double)pos[0], (double)pos[1]); + axisX->GetPosition2Coordinate()->SetValue( + (double)pos2[0], (double)pos[1]); + axisY->GetPositionCoordinate()->SetValue( + (double)pos[0], (double)pos2[1]); + axisY->GetPosition2Coordinate()->SetValue( + (double)pos[0], (double)pos[1]); + + textMapper->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::ViewportToPlotCoordinate(vtkViewport *viewport, double &u, double &v) +{ + int *p0, *p1, *p2; + + // XAxis, YAxis are in viewport coordinates already + p0 = this->XAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + p1 = this->XAxis->GetPosition2Coordinate()->GetComputedViewportValue(viewport); + p2 = this->YAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + u = ((u - p0[0]) / (double)(p1[0] - p0[0])) + *(this->XComputedRange[1] - this->XComputedRange[0]) + + this->XComputedRange[0]; + v = ((v - p0[1]) / (double)(p2[1] - p0[1])) + *(this->YComputedRange[1] - this->YComputedRange[0]) + + this->YComputedRange[0]; +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::PlotToViewportCoordinate(vtkViewport *viewport, + double &u, double &v) +{ + int *p0, *p1, *p2; + + // XAxis, YAxis are in viewport coordinates already + p0 = this->XAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + p1 = this->XAxis->GetPosition2Coordinate()->GetComputedViewportValue(viewport); + p2 = this->YAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + u = (((u - this->XComputedRange[0]) + / (this->XComputedRange[1] - this->XComputedRange[0])) + * (double)(p1[0] - p0[0])) + p0[0]; + v = (((v - this->YComputedRange[0]) + / (this->YComputedRange[1] - this->YComputedRange[0])) + * (double)(p2[1] - p0[1])) + p0[1]; +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::ViewportToPlotCoordinate(vtkViewport *viewport) +{ + this->ViewportToPlotCoordinate(viewport, + this->ViewportCoordinate[0], + this->ViewportCoordinate[1]); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::PlotToViewportCoordinate(vtkViewport *viewport) +{ + this->PlotToViewportCoordinate(viewport, + this->PlotCoordinate[0], + this->PlotCoordinate[1]); +} + +//---------------------------------------------------------------------------- +int vtkXYPlotActor::IsInPlot(vtkViewport *viewport, double u, double v) +{ + int *p0, *p1, *p2; + + // Bounds of the plot are based on the axes... + p0 = this->XAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + p1 = this->XAxis->GetPosition2Coordinate()->GetComputedViewportValue(viewport); + p2 = this->YAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + if (u >= p0[0] && u <= p1[0] && v >= p0[1] && v <= p2[1]) + { + return 1; + } + + return 0; +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetPlotLines(int i, int isOn) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val = this->LinesOn->GetValue(i); + if ( val != isOn ) + { + this->Modified(); + this->LinesOn->SetValue(i, isOn); + } +} + +//---------------------------------------------------------------------------- +int vtkXYPlotActor::GetPlotLines(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->LinesOn->GetValue(i); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetPlotPoints(int i, int isOn) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val = this->PointsOn->GetValue(i); + if ( val != isOn ) + { + this->Modified(); + this->PointsOn->SetValue(i, isOn); + } +} + +//---------------------------------------------------------------------------- +int vtkXYPlotActor::GetPlotPoints(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->PointsOn->GetValue(i); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetPlotColor(int i, double r, double g, double b) +{ + this->LegendActor->SetEntryColor(i, r, g, b); +} + +//---------------------------------------------------------------------------- +double *vtkXYPlotActor::GetPlotColor(int i) +{ + return this->LegendActor->GetEntryColor(i); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetPlotSymbol(int i,vtkPolyData *input) +{ + this->LegendActor->SetEntrySymbol(i, input); +} + +//---------------------------------------------------------------------------- +vtkPolyData *vtkXYPlotActor::GetPlotSymbol(int i) +{ + return this->LegendActor->GetEntrySymbol(i); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetPlotLabel(int i, const char *label) +{ + this->LegendActor->SetEntryString(i, label); +} + +//---------------------------------------------------------------------------- +const char *vtkXYPlotActor::GetPlotLabel(int i) +{ + return this->LegendActor->GetEntryString(i); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::GenerateClipPlanes(int *pos, int *pos2) +{ + double n[3], x[3]; + vtkPoints *pts=this->ClipPlanes->GetPoints(); + vtkDataArray *normals=this->ClipPlanes->GetNormals(); + + n[2] = x[2] = 0.0; + + //first + n[0] = 0.0; + n[1] = -1.0; + normals->SetTuple(0,n); + x[0] = (double)0.5*(pos[0]+pos2[0]); + x[1] = (double)pos[1]; + pts->SetPoint(0,x); + + //second + n[0] = 1.0; + n[1] = 0.0; + normals->SetTuple(1,n); + x[0] = (double)pos2[0]; + x[1] = (double)0.5*(pos[1]+pos2[1]); + pts->SetPoint(1,x); + + //third + n[0] = 0.0; + n[1] = 1.0; + normals->SetTuple(2,n); + x[0] = (double)0.5*(pos[0]+pos2[0]); + x[1] = (double)pos2[1]; + pts->SetPoint(2,x); + + //fourth + n[0] = -1.0; + n[1] = 0.0; + normals->SetTuple(3,n); + x[0] = (double)pos[0]; + x[1] = (double)0.5*(pos[1]+pos2[1]); + pts->SetPoint(3,x); +} + +//---------------------------------------------------------------------------- +double vtkXYPlotActor::ComputeGlyphScale(int i, int *pos, int *pos2) +{ + vtkPolyData *pd=this->LegendActor->GetEntrySymbol(i); + pd->Update(); + double length=pd->GetLength(); + double sf = this->GlyphSize * sqrt((double)(pos[0]-pos2[0])*(pos[0]-pos2[0]) + + (pos[1]-pos2[1])*(pos[1]-pos2[1])) / length; + + return sf; +} + +//---------------------------------------------------------------------------- +//This assumes that there are multiple polylines +void vtkXYPlotActor::ClipPlotData(int *pos, int *pos2, vtkPolyData *pd) +{ + vtkPoints *points=pd->GetPoints(); + vtkPoints *newPoints; + vtkCellArray *lines=pd->GetLines(); + vtkCellArray *newLines, *newVerts; + vtkIdType numPts=pd->GetNumberOfPoints(); + vtkIdType npts = 0; + vtkIdType newPts[2]; + vtkIdType *pts=0; + vtkIdType i, id; + int j; + double x1[3], x2[3], px[3], n[3], xint[3], t; + double p1[2], p2[2]; + + p1[0] = (double)pos[0]; p1[1] = (double)pos[1]; + p2[0] = (double)pos2[0]; p2[1] = (double)pos2[1]; + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newVerts = vtkCellArray::New(); + newVerts->Allocate(lines->GetSize()); + newLines = vtkCellArray::New(); + newLines->Allocate(2*lines->GetSize()); + int *pointMap = new int [numPts]; + for (i=0; iInitTraversal(); lines->GetNextCell(npts,pts); ) + { + //loop over verts keeping only those that are not clipped + for (i=0; iGetPoint(pts[i], x1); + + if (x1[0] >= p1[0] && x1[0] <= p2[0] && x1[1] >= p1[1] && x1[1] <= p2[1] ) + { + id = newPoints->InsertNextPoint(x1); + pointMap[i] = id; + newPts[0] = id; + newVerts->InsertNextCell(1,newPts); + } + } + } + + //Loop over polylines clipping each line segment + for ( lines->InitTraversal(); lines->GetNextCell(npts,pts); ) + { + //loop over line segment making up the polyline + for (i=0; i<(npts-1); i++) + { + points->GetPoint(pts[i], x1); + points->GetPoint(pts[i+1], x2); + + //intersect each segment with the four planes + if ( (x1[0] < p1[0] && x2[0] < p1[0]) || (x1[0] > p2[0] && x2[0] > p2[0]) || + (x1[1] < p1[1] && x2[1] < p1[1]) || (x1[1] > p2[1] && x2[1] > p2[1]) ) + { + ;//trivial rejection + } + else if (x1[0] >= p1[0] && x2[0] >= p1[0] && x1[0] <= p2[0] && x2[0] <= p2[0] && + x1[1] >= p1[1] && x2[1] >= p1[1] && x1[1] <= p2[1] && x2[1] <= p2[1] ) + {//trivial acceptance + newPts[0] = pointMap[pts[i]]; + newPts[1] = pointMap[pts[i+1]]; + newLines->InsertNextCell(2,newPts); + } + else + { + if (x1[0] >= p1[0] && x1[0] <= p2[0] && x1[1] >= p1[1] && x1[1] <= p2[1] ) + {//first point in + newPts[0] = pointMap[pts[i]]; + } + else + {//second point in + newPts[0] = pointMap[pts[i+1]]; + } + for (j=0; j<4; j++) + { + this->ClipPlanes->GetPoints()->GetPoint(j, px); + this->ClipPlanes->GetNormals()->GetTuple(j, n); + if ( vtkPlane::IntersectWithLine(x1,x2,n,px,t,xint) && t >= 0 && t <= 1.0 ) + { + newPts[1] = newPoints->InsertNextPoint(xint); + break; + } + } + newLines->InsertNextCell(2,newPts); + } + } + } + delete [] pointMap; + + //Update the lines + pd->SetPoints(newPoints); + pd->SetVerts(newVerts); + pd->SetLines(newLines); + + newPoints->Delete(); + newVerts->Delete(); + newLines->Delete(); + +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetDataObjectXComponent(int i, int comp) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val=this->XComponent->GetValue(i); + if ( val != comp ) + { + this->Modified(); + this->XComponent->SetValue(i,comp); + } +} + +//---------------------------------------------------------------------------- +int vtkXYPlotActor::GetDataObjectXComponent(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->XComponent->GetValue(i); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetDataObjectYComponent(int i, int comp) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val=this->YComponent->GetValue(i); + if ( val != comp ) + { + this->Modified(); + this->YComponent->SetValue(i,comp); + } +} + +//---------------------------------------------------------------------------- +int vtkXYPlotActor::GetDataObjectYComponent(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->YComponent->GetValue(i); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetPointComponent(int i, int comp) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val = this->XComponent->GetValue(i); + if ( val != comp ) + { + this->Modified(); + this->XComponent->SetValue(i,comp); + } +} + +//---------------------------------------------------------------------------- +int vtkXYPlotActor::GetPointComponent(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->XComponent->GetValue(i); +} + +//---------------------------------------------------------------------------- +double *vtkXYPlotActor::TransformPoint(int pos[2], int pos2[2], + double x[3], double xNew[3]) +{ + // First worry about exchanging axes + if ( this->ExchangeAxes ) + { + double sx = (x[0]-pos[0]) / (pos2[0]-pos[0]); + double sy = (x[1]-pos[1]) / (pos2[1]-pos[1]); + xNew[0] = sy*(pos2[0]-pos[0]) + pos[0]; + xNew[1] = sx*(pos2[1]-pos[1]) + pos[1]; + xNew[2] = x[2]; + } + else + { + xNew[0] = x[0]; + xNew[1] = x[1]; + xNew[2] = x[2]; + } + + // Okay, now swap the axes around if reverse is on + if ( this->ReverseXAxis ) + { + xNew[0] = pos[0] + (pos2[0]-xNew[0]); + } + if ( this->ReverseYAxis ) + { + xNew[1] = pos[1] + (pos2[1]-xNew[1]); + } + + return xNew; +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::SetLabelFormat(const char* _arg) +{ + if (this->LabelFormat == NULL && _arg == NULL) + { + return; + } + + if (this->LabelFormat && _arg && (!strcmp(this->LabelFormat,_arg))) + { + return; + } + + if (this->LabelFormat) + { + delete [] this->LabelFormat; + } + + if (_arg) + { + this->LabelFormat = new char[strlen(_arg)+1]; + strcpy(this->LabelFormat,_arg); + } + else + { + this->LabelFormat = NULL; + } + + this->XAxis->SetLabelFormat(this->LabelFormat); + this->YAxis->SetLabelFormat(this->LabelFormat); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkXYPlotActor::PrintAsCSV(ostream &os) +{ + vtkDataArray *scalars; + vtkDataSet *ds; + vtkCollectionSimpleIterator dsit; + double s; + int dsNum,component; + for ( dsNum=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); dsNum++ ) + { + vtkIdType numPts = ds->GetNumberOfPoints(); + scalars = ds->GetPointData()->GetScalars(this->SelectedInputScalars[dsNum]); + component = this->SelectedInputScalarsComponent->GetValue(dsNum); + for ( vtkIdType ptId=0; ptId < numPts; ptId++ ) + { + s = scalars->GetComponent(ptId, component); + if( ptId == 0 ) + { + os << s; + } + else + { + os << "," << s; + } + } + os << endl; + } +} + diff --git a/Hybrid/vtkXYPlotActor.h b/Hybrid/vtkXYPlotActor.h new file mode 100644 index 0000000..ea282c4 --- /dev/null +++ b/Hybrid/vtkXYPlotActor.h @@ -0,0 +1,557 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXYPlotActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXYPlotActor - generate an x-y plot from input dataset(s) or field data +// .SECTION Description +// vtkXYPlotActor creates an x-y plot of data from one or more input data +// sets or field data. The class plots dataset scalar values (y-axis) against +// the points (x-axis). The x-axis values are generated by taking the point +// ids, computing a cumulative arc length, or a normalized arc length. More +// than one input data set can be specified to generate multiple plots. +// Alternatively, if field data is supplied as input, the class plots one +// component against another. (The user must specify which component to use +// as the x-axis and which for the y-axis.) +// +// To use this class to plot dataset(s), you must specify one or more +// input datasets containing scalar and point data. You'll probably also +// want to invoke a method to control how the point coordinates are converted +// into x values (by default point ids are used). +// +// To use this class to plot field data, you must specify one or more input +// data objects with its associated field data. You'll also want to specify +// which component to use as the x-axis and which to use as the y-axis. +// Note that when plotting field data, the x and y values are used directly +// (i.e., there are no options to normalize the components). +// +// Once you've set up the plot, you'll want to position it. The +// PositionCoordinate defines the lower-left location of the x-y plot +// (specified in normalized viewport coordinates) and the Position2Coordinate +// define the upper-right corner. (Note: the Position2Coordinate is relative +// to PositionCoordinate, so you can move the vtkXYPlotActor around the +// viewport by setting just the PositionCoordinate.) The combination of the +// two position coordinates specifies a rectangle in which the plot will lie. +// +// Optional features include the ability to specify axes labels, label +// format and plot title. You can also +// manually specify the x and y plot ranges (by default they are computed +// automatically). The Border instance variable is used to create space +// between the boundary of the plot window (specified by PositionCoordinate +// and Position2Coordinate) and the plot itself. +// +// The font property of the plot title can be modified through the +// TitleTextProperty attribute. +// The font property of the axes titles and labels can be modified through the +// AxisTitleTextProperty and AxisLabelTextProperty attributes. You may also +// use the GetXAxisActor2D or GetYAxisActor2D methods +// to access each individual axis actor to modify their font properties. +// In the same way, the GetLegendBoxActor method can be used to access +// the legend box actor to modify its font properties. +// +// There are several advanced features as well. You can assign per curve +// properties (such as color and a plot symbol). (Note that each input +// dataset and/or data object creates a single curve.) Another option is to +// add a plot legend that graphically indicates the correspondance between +// the curve, curve symbols, and the data source. You can also exchange the +// x and y axes if you prefer you plot orientation that way. + +// .SECTION Caveats +// If you are interested in plotting something other than scalar data, you +// can use the vtk data shuffling filters (e.g., +// vtkAttributeDataToFieldDataFilter and vtkFieldDataToAttributeDataFilter) +// to convert the data into scalar data and/or points. + +// .SECTION See Also +// vtkActor2D vtkTextMapper vtkScalarBarActor vtkAxisActor2D vtkCubeAxesActor2D +// vtkAttributeDataToFieldDataFilter vtkFieldDataToAttributeDataFilter +// vtkTextProperty + +#ifndef __vtkXYPlotActor_h +#define __vtkXYPlotActor_h + +#define VTK_XYPLOT_INDEX 0 +#define VTK_XYPLOT_ARC_LENGTH 1 +#define VTK_XYPLOT_NORMALIZED_ARC_LENGTH 2 +#define VTK_XYPLOT_VALUE 3 + +#define VTK_XYPLOT_ROW 0 +#define VTK_XYPLOT_COLUMN 1 + +#include "vtkActor2D.h" + +class vtkAppendPolyData; +class vtkAxisActor2D; +class vtkDataObject; +class vtkDataObjectCollection; +class vtkDataSet; +class vtkDataSetCollection; +class vtkGlyph2D; +class vtkGlyphSource2D; +class vtkIntArray; +class vtkLegendBoxActor; +class vtkPlanes; +class vtkPolyData; +class vtkPolyDataMapper2D; +class vtkTextMapper; +class vtkTextProperty; + +class VTK_HYBRID_EXPORT vtkXYPlotActor : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkXYPlotActor,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with autorange computation; bold, italic, and shadows + // on; arial font family; the number of labels set to 5 for the x and y + // axes; a label format of "%-#6.3g"; and x coordinates computed from point + // ids. + static vtkXYPlotActor *New(); + + //---Data Set Input---------------------------------------------------------- + // The following methods are used to plot input datasets. Datasets + // will be plotted if set as input; otherwise the input data objects + // will be plotted (if defined). + + // Description: + // Add a dataset to the list of data to append. The array name specifies + // which point array to plot. If the array name is NULL, then the default + // scalars are used. The array can have multiple components, but only the + // first component is ploted. + void AddInput(vtkDataSet *in, const char* arrayName, int component); + void AddInput(vtkDataSet *in) {this->AddInput(in, NULL, 0);} + + // Description: + // Remove a dataset from the list of data to append. + void RemoveInput(vtkDataSet *in, const char* arrayName, int component); + void RemoveInput(vtkDataSet *in) {this->RemoveInput(in, NULL, 0);} + + // Description: + // This removes all of the data set inputs, + // but does not change the data object inputs. + void RemoveAllInputs(); + + // Description: + // Return the list of inputs to this filter. + vtkDataSetCollection *GetInputList() {return this->InputList;} + + // Description: + // If plotting points by value, which component to use to determine the + // value. This sets a value per each input dataset (i.e., the ith dataset). + void SetPointComponent(int i, int comp); + int GetPointComponent(int i); + //---end Data Set Input----------------------------------------------------- + + // Description: + // Specify how the independent (x) variable is computed from the points. + // The independent variable can be the scalar/point index (i.e., point id), + // the accumulated arc length along the points, the normalized arc length, + // or by component value. If plotting datasets (e.g., points), the value + // that is used is specified by the PointComponent ivar. (Note: these + // methods also control how field data is plotted. Field data is usually + // plotted by value or index, if plotting length 1-dimensional length + // measures are used.) + vtkSetClampMacro(XValues,int,VTK_XYPLOT_INDEX,VTK_XYPLOT_VALUE); + vtkGetMacro(XValues,int); + void SetXValuesToIndex(){this->SetXValues(VTK_XYPLOT_INDEX);}; + void SetXValuesToArcLength() {this->SetXValues(VTK_XYPLOT_ARC_LENGTH);}; + void SetXValuesToNormalizedArcLength() + {this->SetXValues(VTK_XYPLOT_NORMALIZED_ARC_LENGTH);}; + void SetXValuesToValue() {this->SetXValues(VTK_XYPLOT_VALUE);}; + const char *GetXValuesAsString(); + + //---Data Object Input------------------------------------------------------ + // The following methods are used to plot input data objects. Datasets will + // be plotted in preference to data objects if set as input; otherwise the + // input data objects will be plotted (if defined). + + // Description: + // Add a dataset to the list of data to append. + void AddDataObjectInput(vtkDataObject *in); + + // Description: + // Remove a dataset from the list of data to append. + void RemoveDataObjectInput(vtkDataObject *in); + + // Description: + // Return the list of inputs to this filter. + vtkDataObjectCollection *GetDataObjectInputList() + {return this->DataObjectInputList;} + + // Description: + // Indicate whether to plot rows or columns. If plotting rows, then + // the dependent variables is taken from a specified row, + // versus rows (y). + vtkSetClampMacro(DataObjectPlotMode,int,VTK_XYPLOT_ROW,VTK_XYPLOT_COLUMN); + vtkGetMacro(DataObjectPlotMode,int); + void SetDataObjectPlotModeToRows() + {this->SetDataObjectPlotMode(VTK_XYPLOT_ROW);} + void SetDataObjectPlotModeToColumns() + {this->SetDataObjectPlotMode(VTK_XYPLOT_COLUMN);} + const char *GetDataObjectPlotModeAsString(); + + // Description: + // Specify which component of the input data object to use as the + // independent variable for the ith input data object. (This ivar is + // ignored if plotting the index.) Note that the value is interpreted + // differently depending on DataObjectPlotMode. If the mode is Rows, then + // the value of DataObjectXComponent is the row number; otherwise it's the + // column number. + void SetDataObjectXComponent(int i, int comp); + int GetDataObjectXComponent(int i); + + // Description: + // Specify which component of the input data object to use as the + // dependent variable for the ith input data object. (This ivar is + // ignored if plotting the index.) Note that the value is interpreted + // differently depending on DataObjectPlotMode. If the mode is Rows, then + // the value of DataObjectYComponent is the row number; otherwise it's the + // column number. + void SetDataObjectYComponent(int i, int comp); + int GetDataObjectYComponent(int i); + //---end Data Object Input-------------------------------------------------- + + //---Per Curve Properties--------------------------------------------------- + // The following methods are used to set properties on each curve that is + // plotted. Each input dataset (or data object) results in one curve. The + // methods that follow have an index i that corresponds to the input dataset + // or data object. + void SetPlotColor(int i, double r, double g, double b); + void SetPlotColor(int i, const double color[3]) { + this->SetPlotColor(i, color[0], color[1], color[2]); }; + double *GetPlotColor(int i); + void SetPlotSymbol(int i,vtkPolyData *input); + vtkPolyData *GetPlotSymbol(int i); + void SetPlotLabel(int i, const char *label); + const char *GetPlotLabel(int i); + + // Allow per-curve specification of line and point rendering. These override + // global settings PlotPoints and PlotLines. If not on, the default behavior + // is governed by PlotPoints and PlotLines ivars. + vtkGetMacro(PlotCurvePoints, int); + vtkSetMacro(PlotCurvePoints, int); + vtkBooleanMacro(PlotCurvePoints, int); + + vtkGetMacro(PlotCurveLines, int); + vtkSetMacro(PlotCurveLines, int); + vtkBooleanMacro(PlotCurveLines, int); + + void SetPlotLines(int i, int); + int GetPlotLines(int i); + + void SetPlotPoints(int i, int); + int GetPlotPoints(int i); + //---end Per Curve Properties----------------------------------------------- + + // Description: + // Enable/Disable exchange of the x-y axes (i.e., what was x becomes y, and + // vice-versa). Exchanging axes affects the labeling as well. + vtkSetMacro(ExchangeAxes, int); + vtkGetMacro(ExchangeAxes, int); + vtkBooleanMacro(ExchangeAxes, int); + + // Description: + // Normally the x-axis is plotted from minimum to maximum. Setting this instance + // variable causes the x-axis to be plotted from maximum to minimum. Note that + // boolean always applies to the x-axis even if ExchangeAxes is set. + vtkSetMacro(ReverseXAxis, int); + vtkGetMacro(ReverseXAxis, int); + vtkBooleanMacro(ReverseXAxis, int); + + // Description: + // Normally the y-axis is plotted from minimum to maximum. Setting this instance + // variable causes the y-axis to be plotted from maximum to minimum. Note that + // boolean always applies to the y-axis even if ExchangeAxes is set. + vtkSetMacro(ReverseYAxis, int); + vtkGetMacro(ReverseYAxis, int); + vtkBooleanMacro(ReverseYAxis, int); + + // Description: + // Retrieve handles to the legend box and glyph source. This is useful + // if you would like to change the default behavior of the legend box + // or glyph source. For example, the default glyph can be changed from + // a line to a vertex plus line, etc.) + vtkGetObjectMacro(LegendActor,vtkLegendBoxActor); + vtkGetObjectMacro(GlyphSource,vtkGlyphSource2D); + + // Description: + // Set/Get the title of the x-y plot, and the title along the + // x and y axes. + vtkSetStringMacro(Title); + vtkGetStringMacro(Title); + vtkSetStringMacro(XTitle); + vtkGetStringMacro(XTitle); + vtkSetStringMacro(YTitle); + vtkGetStringMacro(YTitle); + + // Description: + // Retrieve handles to the X and Y axis (so that you can set their text + // properties for example) + vtkAxisActor2D *GetXAxisActor2D() + {return this->XAxis;} + vtkAxisActor2D *GetYAxisActor2D() + {return this->YAxis;} + + // Description: + // Set the plot range (range of independent and dependent variables) + // to plot. Data outside of the range will be clipped. If the plot + // range of either the x or y variables is set to (v1,v2), where + // v1 == v2, then the range will be computed automatically. Note that + // the x-range values should be consistent with the way the independent + // variable is created (via INDEX, DISTANCE, or ARC_LENGTH). + vtkSetVector2Macro(XRange,double); + vtkGetVectorMacro(XRange,double,2); + vtkSetVector2Macro(YRange,double); + vtkGetVectorMacro(YRange,double,2); + void SetPlotRange(double xmin, double ymin, double xmax, double ymax) + {this->SetXRange(xmin,xmax); this->SetYRange(ymin,ymax);} + + // Description: + // Set/Get the number of annotation labels to show along the x and y axes. + // This values is a suggestion: the number of labels may vary depending + // on the particulars of the data. The convenience method + // SetNumberOfLables() sets the number of x and y labels to the same value. + vtkSetClampMacro(NumberOfXLabels, int, 0, 50); + vtkGetMacro(NumberOfXLabels, int); + vtkSetClampMacro(NumberOfYLabels, int, 0, 50); + vtkGetMacro(NumberOfYLabels, int); + void SetNumberOfLabels(int num) + {this->SetNumberOfXLabels(num); this->SetNumberOfYLabels(num);} + + // Description: + // Enable/Disable the creation of a legend. If on, the legend labels will + // be created automatically unless the per plot legend symbol has been + // set. + vtkSetMacro(Legend, int); + vtkGetMacro(Legend, int); + vtkBooleanMacro(Legend, int); + + // Description: + // Use these methods to control the position of the legend. The variables + // LegendPosition and LegendPosition2 define the lower-left and upper-right + // position of the legend. The coordinates are expressed as normalized + // values with respect to the rectangle defined by PositionCoordinate and + // Position2Coordinate. Note that LegendPosition2 is relative to + // LegendPosition. + vtkSetVector2Macro(LegendPosition,double); + vtkGetVector2Macro(LegendPosition,double); + vtkSetVector2Macro(LegendPosition2,double); + vtkGetVector2Macro(LegendPosition2,double); + + // Description: + // Set/Get the title text property. + virtual void SetTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the title text property of all axes. Note that each axis can + // be controlled individually through the GetX/YAxisActor2D() methods. + virtual void SetAxisTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(AxisTitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the labels text property of all axes. Note that each axis can + // be controlled individually through the GetX/YAxisActor2D() methods. + virtual void SetAxisLabelTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(AxisLabelTextProperty,vtkTextProperty); + + // Description: + // Enable/Disable plotting of Log of x-values. + vtkSetMacro(Logx, int); + vtkGetMacro(Logx, int); + vtkBooleanMacro(Logx, int); + + // Description: + // Set/Get the format with which to print the labels on the scalar + // bar. + virtual void SetLabelFormat (const char* _arg); + vtkGetStringMacro(LabelFormat); + + // Description: + // Set/Get the spacing between the plot window and the plot. The value + // is specified in pixels. + vtkSetClampMacro(Border, int, 0, 50); + vtkGetMacro(Border, int); + + // Description: + // Set/Get whether the points are rendered. The point size can be set in + // the property object. This is a global flag which affects the plot only + // if per curve symbols are not defined. + vtkGetMacro(PlotPoints, int); + vtkSetMacro(PlotPoints, int); + vtkBooleanMacro(PlotPoints, int); + + // Description: + // Set/Get whether the lines are rendered. The line width can be set in + // the property object. + vtkGetMacro(PlotLines, int); + vtkSetMacro(PlotLines, int); + vtkBooleanMacro(PlotLines, int); + + // Description: + // Set/Get the factor that controls how big glyphs are in the plot. + // The number is expressed as a fraction of the length of the diagonal + // of the plot bounding box. + vtkSetClampMacro(GlyphSize, double, 0.0, 0.2); + vtkGetMacro(GlyphSize, double); + + // Description: + // Given a position within the viewport used by the plot, return the + // the plot coordinates (XAxis value, YAxis value) + void ViewportToPlotCoordinate(vtkViewport *viewport, double &u, double &v); + + // Description: + // An alternate form of ViewportToPlotCoordinate() above. This method + // inputs the viewport coordinate pair (defined by the ivar + // ViewportCoordinate)and then stores them in the ivar PlotCoordinate. + void ViewportToPlotCoordinate(vtkViewport *viewport); + vtkSetVector2Macro(PlotCoordinate,double); + vtkGetVector2Macro(PlotCoordinate,double); + + // Description: + // Given a plot coordinate, return the viewpoint position + void PlotToViewportCoordinate(vtkViewport *viewport, double &u, double &v); + + // Description: + // An alternate form of PlotToViewportCoordinate() above. This method + // inputs the plot coordinate pair (defined in the ivar PlotCoordinate) + // and then stores them in the ivar ViewportCoordinate. (This method + // can be wrapped.) + void PlotToViewportCoordinate(vtkViewport *viewport); + vtkSetVector2Macro(ViewportCoordinate,double); + vtkGetVector2Macro(ViewportCoordinate,double); + + // Description: + // Is the specified viewport position within the plot area (as opposed to the + // region used by the plot plus the labels)? + int IsInPlot(vtkViewport *viewport, double u, double v); + + // Description: + // Take into account the modified time of internal helper classes. + unsigned long GetMTime(); + + // Description: + // Write the XY Ploat Actor as a CSV (comma separated value) representation. + void PrintAsCSV(ostream &os); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Draw the x-y plot. + int RenderOpaqueGeometry(vtkViewport*); + int RenderOverlay(vtkViewport*); + int RenderTranslucentGeometry(vtkViewport *) {return 0;} + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); +//ETX + +protected: + vtkXYPlotActor(); + ~vtkXYPlotActor(); + + vtkDataSetCollection *InputList; //list of data sets to plot + char** SelectedInputScalars; // list of data set arrays to plot + vtkIntArray* SelectedInputScalarsComponent; // list of componenents + vtkDataObjectCollection *DataObjectInputList; //list of data objects to plot + char *Title; + char *XTitle; + char *YTitle; + int XValues; + int NumberOfXLabels; + int NumberOfYLabels; + int Logx; + char *LabelFormat; + double XRange[2]; + double YRange[2]; + double XComputedRange[2]; //range actually used by plot + double YComputedRange[2]; //range actually used by plot + int Border; + int PlotLines; + int PlotPoints; + int PlotCurveLines; + int PlotCurvePoints; + int ExchangeAxes; + int ReverseXAxis; + int ReverseYAxis; + + vtkTextMapper *TitleMapper; + vtkActor2D *TitleActor; + vtkTextProperty *TitleTextProperty; + + vtkAxisActor2D *XAxis; + vtkAxisActor2D *YAxis; + + vtkTextProperty *AxisTitleTextProperty; + vtkTextProperty *AxisLabelTextProperty; + + double ViewportCoordinate[2]; + double PlotCoordinate[2]; + + //Handle data objects and datasets + int DataObjectPlotMode; + vtkIntArray *XComponent; + vtkIntArray *YComponent; + vtkIntArray *LinesOn; + vtkIntArray *PointsOn; + + //The data drawn within the axes. Each curve is one polydata. + //color is controlled by scalar data. The curves are appended + //together, possibly glyphed with point symbols. + int NumberOfInputs; + vtkPolyData **PlotData; + vtkGlyph2D **PlotGlyph; + vtkAppendPolyData **PlotAppend; + vtkPolyDataMapper2D **PlotMapper; + vtkActor2D **PlotActor; + void InitializeEntries(); + + // Legends and plot symbols. The legend also keeps track of + // the symbols and such. + int Legend; + double LegendPosition[2]; + double LegendPosition2[2]; + vtkLegendBoxActor *LegendActor; + vtkGlyphSource2D *GlyphSource; + vtkPlanes *ClipPlanes; + double GlyphSize; + + // Keep track of changes. + int CachedSize[2]; + vtkTimeStamp BuildTime; + + void ComputeXRange(double range[2], double *lengths); + void ComputeYRange(double range[2]); + void ComputeDORange(double xrange[2], double yrange[2], double *lengths); + + virtual void CreatePlotData(int *pos, int *pos2, double xRange[2], + double yRange[2], double *norms, + int numDS, int numDO); + void PlaceAxes(vtkViewport *viewport, int *size, int pos[2], int pos2[2]); + void GenerateClipPlanes(int *pos, int *pos2); + double ComputeGlyphScale(int i, int *pos, int *pos2); + void ClipPlotData(int *pos, int *pos2, vtkPolyData *pd); + double *TransformPoint(int pos[2], int pos2[2], double x[3], double xNew[3]); + +private: + vtkXYPlotActor(const vtkXYPlotActor&); // Not implemented. + void operator=(const vtkXYPlotActor&); // Not implemented. +}; + + +#endif + diff --git a/IO/CMakeLists.txt b/IO/CMakeLists.txt new file mode 100644 index 0000000..38f88ce --- /dev/null +++ b/IO/CMakeLists.txt @@ -0,0 +1,199 @@ +SET(KIT IO) +SET(UKIT IO) +SET(KIT_TCL_LIBS vtkFilteringTCL) +SET(KIT_PYTHON_LIBS vtkFilteringPythonD) +SET(KIT_JAVA_LIBS vtkFilteringJava) +SET(KIT_LIBS vtkFiltering vtkDICOMParser + ${VTK_PNG_LIBRARIES} ${VTK_ZLIB_LIBRARIES} ${VTK_JPEG_LIBRARIES} + ${VTK_TIFF_LIBRARIES} ${VTK_EXPAT_LIBRARIES}) + + +SET( Kit_SRCS +vtkAVSucdReader.cxx +vtkBMPReader.cxx +vtkBMPWriter.cxx +vtkBYUReader.cxx +vtkBYUWriter.cxx +vtkBase64InputStream.cxx +vtkBase64OutputStream.cxx +vtkBase64Utilities.cxx +vtkCGMWriter.cxx +vtkChacoReader.cxx +vtkDEMReader.cxx +vtkDICOMImageReader.cxx +vtkDataCompressor.cxx +vtkDataObjectReader.cxx +vtkDataObjectWriter.cxx +vtkDataReader.cxx +vtkDataSetReader.cxx +vtkDataSetWriter.cxx +vtkDataWriter.cxx +vtkEnSight6BinaryReader.cxx +vtkEnSight6Reader.cxx +vtkEnSightGoldBinaryReader.cxx +vtkEnSightGoldReader.cxx +vtkEnSightMasterServerReader.cxx +vtkEnSightReader.cxx +vtkFacetWriter.cxx +vtkGESignaReader.cxx +vtkGAMBITReader.cxx +vtkGaussianCubeReader.cxx +vtkGenericEnSightReader.cxx +vtkGenericMovieWriter.cxx +vtkIVWriter.cxx +vtkImageReader.cxx +vtkImageReader2.cxx +vtkImageReader2Collection.cxx +vtkImageReader2Factory.cxx +vtkImageWriter.cxx +vtkInputStream.cxx +vtkJPEGReader.cxx +vtkJPEGWriter.cxx +vtkMCubesReader.cxx +vtkMCubesWriter.cxx +vtkMedicalImageProperties.cxx +vtkMedicalImageReader2.cxx +vtkMetaImageReader.cxx +vtkMetaImageWriter.cxx +vtkMultiBlockPLOT3DReader.cxx +vtkMoleculeReaderBase.cxx +vtkOBJReader.cxx +vtkOutputStream.cxx +vtkPDBReader.cxx +vtkPLOT3DReader.cxx +vtkPLY.cxx +vtkPLYReader.cxx +vtkPLYWriter.cxx +vtkPNGReader.cxx +vtkPNGWriter.cxx +vtkPNMReader.cxx +vtkPNMWriter.cxx +vtkParticleReader.cxx +vtkPolyDataReader.cxx +vtkPolyDataWriter.cxx +vtkPostScriptWriter.cxx +vtkRectilinearGridReader.cxx +vtkRectilinearGridWriter.cxx +vtkSLCReader.cxx +vtkSTLReader.cxx +vtkSTLWriter.cxx +vtkSimplePointsReader.cxx +vtkStructuredGridReader.cxx +vtkStructuredGridWriter.cxx +vtkStructuredPointsReader.cxx +vtkStructuredPointsWriter.cxx +vtkTIFFReader.cxx +vtkTIFFWriter.cxx +vtkUGFacetReader.cxx +vtkUnstructuredGridReader.cxx +vtkUnstructuredGridWriter.cxx +vtkVolume16Reader.cxx +vtkVolumeReader.cxx +vtkWriter.cxx +vtkXMLDataElement.cxx +vtkXMLDataParser.cxx +vtkXMLDataReader.cxx +vtkXMLDataSetWriter.cxx +vtkXMLFileReadTester.cxx +vtkXMLImageDataReader.cxx +vtkXMLImageDataWriter.cxx +vtkXMLPDataReader.cxx +vtkXMLPDataSetWriter.cxx +vtkXMLPDataWriter.cxx +vtkXMLPImageDataReader.cxx +vtkXMLPImageDataWriter.cxx +vtkXMLPPolyDataReader.cxx +vtkXMLPPolyDataWriter.cxx +vtkXMLPRectilinearGridReader.cxx +vtkXMLPRectilinearGridWriter.cxx +vtkXMLPStructuredDataReader.cxx +vtkXMLPStructuredDataWriter.cxx +vtkXMLPStructuredGridReader.cxx +vtkXMLPStructuredGridWriter.cxx +vtkXMLPUnstructuredDataReader.cxx +vtkXMLPUnstructuredDataWriter.cxx +vtkXMLPUnstructuredGridReader.cxx +vtkXMLPUnstructuredGridWriter.cxx +vtkXMLParser.cxx +vtkXMLPolyDataReader.cxx +vtkXMLPolyDataWriter.cxx +vtkXMLReader.cxx +vtkXMLRectilinearGridReader.cxx +vtkXMLRectilinearGridWriter.cxx +vtkXMLStructuredDataReader.cxx +vtkXMLStructuredDataWriter.cxx +vtkXMLStructuredGridReader.cxx +vtkXMLStructuredGridWriter.cxx +vtkXMLUnstructuredDataReader.cxx +vtkXMLUnstructuredDataWriter.cxx +vtkXMLUnstructuredGridReader.cxx +vtkXMLUnstructuredGridWriter.cxx +vtkXMLUtilities.cxx +vtkXMLWriter.cxx +vtkXMLWriterC.cxx +vtkXYZMolReader.cxx +vtkZLibDataCompressor.cxx +) + +SET_SOURCE_FILES_PROPERTIES( +vtkDataCompressor +vtkEnSightReader +vtkGenericMovieWriter +vtkMoleculeReaderBase +vtkVolumeReader +vtkWriter +vtkXMLDataReader +vtkXMLPDataReader +vtkXMLPDataWriter +vtkXMLPStructuredDataReader +vtkXMLPStructuredDataWriter +vtkXMLPUnstructuredDataReader +vtkXMLPUnstructuredDataWriter +vtkXMLReader +vtkXMLStructuredDataReader +vtkXMLStructuredDataWriter +vtkXMLUnstructuredDataReader +vtkXMLUnstructuredDataWriter +vtkXMLWriter +ABSTRACT +) + +IF(WIN32) + IF(VTK_USE_VIDEO_FOR_WINDOWS) + SET(Kit_SRCS ${Kit_SRCS} vtkAVIWriter.cxx) + SET(KIT_LIBS ${KIT_LIBS} vfw32) + ENDIF(VTK_USE_VIDEO_FOR_WINDOWS) +ENDIF(WIN32) + +#----------------------------------------------------------------------------- +# MPEG2 +# +# Only include the vtkMPEG2Writer if the user has explicitly turned on +# VTK_USE_MPEG2_ENCODER. If so, user should also have set +# vtkMPEG2Encode_INCLUDE_PATH and vtkMPEG2Encode_LIBRARIES. +# +IF (VTK_USE_MPEG2_ENCODER) + INCLUDE_DIRECTORIES(${vtkMPEG2Encode_INCLUDE_PATH}) + SET(Kit_SRCS ${Kit_SRCS} vtkMPEG2Writer.cxx) + SET(KIT_LIBS ${KIT_LIBS} ${vtkMPEG2Encode_LIBRARIES}) +ENDIF (VTK_USE_MPEG2_ENCODER) + +#----------------------------------------------------------------------------- +SET_SOURCE_FILES_PROPERTIES( + vtkPLY + vtkXMLWriterC + WRAP_EXCLUDE +) +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- diff --git a/IO/Testing/CMakeLists.txt b/IO/Testing/CMakeLists.txt new file mode 100644 index 0000000..b12dd14 --- /dev/null +++ b/IO/Testing/CMakeLists.txt @@ -0,0 +1,23 @@ +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +SUBDIRS(Cxx) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-IO ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/IO" + VTK_IO_EXPORT + vtkPLY.h + vtkBase64Utilities.h + vtkXMLUtilities.h + vtkXMLWriterC.h + vtkXMLWriterF.h + vtkOffsetsManagerArray.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/IO/Testing/Cxx/CMakeLists.txt b/IO/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..79f635f --- /dev/null +++ b/IO/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,31 @@ +SET(KIT IO) + +SET(ConditionalTests) +IF(WIN32 AND VTK_USE_VIDEO_FOR_WINDOWS) + SET(ConditionalTests ${ConditionalTests} TestAVIWriter.cxx) +ENDIF(WIN32 AND VTK_USE_VIDEO_FOR_WINDOWS) +IF(VTK_USE_MPEG2_ENCODER) + SET(ConditionalTests ${ConditionalTests} TestMovieWriter.cxx) +ENDIF(VTK_USE_MPEG2_ENCODER) + +CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx + TestXML.cxx + TestCompress.cxx + ${ConditionalTests} + EXTRA_INCLUDE vtkTestDriver.h +) + +ADD_EXECUTABLE(${KIT}CxxTests ${Tests}) +TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkIO vtkImaging vtksys) + +IF (VTK_DATA_ROOT) + ADD_TEST(TestXML ${CXX_TEST_PATH}/${KIT}CxxTests TestXML ${VTK_DATA_ROOT}/Data/sample.xml) + ADD_TEST(TestCompress ${CXX_TEST_PATH}/${KIT}CxxTests TestCompress ${VTK_DATA_ROOT}/Data/sample.xml) +ENDIF (VTK_DATA_ROOT) + +IF(WIN32 AND VTK_USE_VIDEO_FOR_WINDOWS) + ADD_TEST(TestAVIWriter ${CXX_TEST_PATH}/${KIT}CxxTests TestAVIWriter) +ENDIF(WIN32 AND VTK_USE_VIDEO_FOR_WINDOWS) +IF(VTK_USE_MPEG2_ENCODER) + ADD_TEST(TestMovieWriter ${CXX_TEST_PATH}/${KIT}CxxTests TestMovieWriter) +ENDIF(VTK_USE_MPEG2_ENCODER) diff --git a/IO/Testing/Cxx/TestAVIWriter.cxx b/IO/Testing/Cxx/TestAVIWriter.cxx new file mode 100644 index 0000000..8397eba --- /dev/null +++ b/IO/Testing/Cxx/TestAVIWriter.cxx @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestAVIWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME Test of vtkAVIWriter +// .SECTION Description +// + +#include "vtkAVIWriter.h" +#include "vtkImageCast.h" +#include "vtkImageData.h" +#include "vtkImageMandelbrotSource.h" +#include "vtkImageMapToColors.h" +#include "vtkLookupTable.h" +#include "vtksys/SystemTools.hxx" + +int TestAVIWriter(int vtkNotUsed(argc), char* vtkNotUsed(argv)[]) +{ + int err = 0; + int cc = 0; + int exists = 0; + unsigned long length = 0; + vtkImageMandelbrotSource* Fractal0 = vtkImageMandelbrotSource::New(); + Fractal0->SetWholeExtent( 0, 247, 0, 247, 0, 0 ); + Fractal0->SetProjectionAxes( 0, 1, 2 ); + Fractal0->SetOriginCX( -1.75, -1.25, 0, 0 ); + Fractal0->SetSizeCX( 2.5, 2.5, 2, 1.5 ); + Fractal0->SetMaximumNumberOfIterations( 100); + + vtkImageCast* cast = vtkImageCast::New(); + cast->SetInputConnection(Fractal0->GetOutputPort()); + cast->SetOutputScalarTypeToUnsignedChar(); + + vtkLookupTable* table = vtkLookupTable::New(); + table->SetTableRange(0, 100); + table->SetNumberOfColors(100); + table->Build(); + table->SetTableValue(99, 0, 0, 0); + + vtkImageMapToColors* colorize = vtkImageMapToColors::New(); + colorize->SetOutputFormatToRGB(); + colorize->SetLookupTable(table); + colorize->SetInputConnection(cast->GetOutputPort()); + + vtkAVIWriter *w = vtkAVIWriter::New(); + w->SetInputConnection(colorize->GetOutputPort()); + w->SetFileName("TestAVIWriter.avi"); + cout << "Writing file TestAVIWriter.avi..." << endl; + w->Start(); + for ( cc = 2; cc < 99; cc ++ ) + { + cout << "."; + Fractal0->SetMaximumNumberOfIterations(cc); + table->SetTableRange(0, cc); + table->SetNumberOfColors(cc); + table->ForceBuild(); + table->SetTableValue(cc-1, 0, 0, 0); + w->Write(); + } + w->End(); + cout << endl; + cout << "Done writing file TestAVIWriter.avi..." << endl; + w->Delete(); + + exists = (int) vtksys::SystemTools::FileExists("TestAVIWriter.avi"); + length = vtksys::SystemTools::FileLength("TestAVIWriter.avi"); + cout << "TestAVIWriter.avi file exists: " << exists << endl; + cout << "TestAVIWriter.avi file length: " << length << endl; + if (!exists) + { + err = 3; + cerr << "ERROR: 3 - Test failing because TestAVIWriter.avi file doesn't exist..." << endl; + } + if (0==length) + { + err = 4; + cerr << "ERROR: 4 - Test failing because TestAVIWriter.avi file has zero length..." << endl; + } + + colorize->Delete(); + table->Delete(); + cast->Delete(); + Fractal0->Delete(); + + // err == 0 means test passes... + // + return err; +} diff --git a/IO/Testing/Cxx/TestCompress.cxx b/IO/Testing/Cxx/TestCompress.cxx new file mode 100644 index 0000000..af441d2 --- /dev/null +++ b/IO/Testing/Cxx/TestCompress.cxx @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestCompress.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME Test of vtkZLibDataCompressor +// .SECTION Description +// + +#include "vtkZLibDataCompressor.h" +#include "vtkOutputWindow.h" +#include "vtkObjectFactory.h" + + +int TestCompress(int argc, char *argv[]) +{ + int res = 1; + const unsigned int start_size = 100024; + unsigned int cc; + unsigned char buffer[start_size]; + unsigned char* cbuffer; + unsigned char* ucbuffer; + unsigned long nlen; + unsigned long rlen; + + vtkZLibDataCompressor* compressor = vtkZLibDataCompressor::New(); + for ( cc = 0; cc < start_size; cc ++ ) + { + buffer[cc] = cc % sizeof(unsigned char); + } + buffer[0] = 'v'; + buffer[1] = 't'; + buffer[2] = 'k'; + + nlen = compressor->GetMaximumCompressionSpace(start_size); + cbuffer = new unsigned char[ nlen ]; + rlen = compressor->Compress(buffer, start_size, cbuffer, nlen); + if ( rlen > 0 ) + { + ucbuffer = new unsigned char[ start_size ]; + rlen = compressor->Uncompress(cbuffer, rlen, ucbuffer, start_size); + if ( rlen == start_size ) + { + cout << argv[0] << " Works " << argc << endl; + cout << ucbuffer[0] << ucbuffer[1] << ucbuffer[2] << endl; + res = 0; + } + delete [] ucbuffer; + } + delete [] cbuffer; + + compressor->Delete(); + return res; +} diff --git a/IO/Testing/Cxx/TestMovieWriter.cxx b/IO/Testing/Cxx/TestMovieWriter.cxx new file mode 100644 index 0000000..425469b --- /dev/null +++ b/IO/Testing/Cxx/TestMovieWriter.cxx @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestMovieWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME Test of vtkMPEG2Writer +// .SECTION Description +// + +#include "vtkImageCast.h" +#include "vtkImageData.h" +#include "vtkImageMandelbrotSource.h" +#include "vtkImageMapToColors.h" +#include "vtkLookupTable.h" +#include "vtkMPEG2Writer.h" +#include "vtksys/SystemTools.hxx" + +int TestMovieWriter(int vtkNotUsed(argc), char* vtkNotUsed(argv)[]) +{ + int err = 0; + int cc = 0; + int exists = 0; + unsigned long length = 0; + vtkImageMandelbrotSource* Fractal0 = vtkImageMandelbrotSource::New(); + Fractal0->SetWholeExtent( 0, 247, 0, 247, 0, 0 ); + Fractal0->SetProjectionAxes( 0, 1, 2 ); + Fractal0->SetOriginCX( -1.75, -1.25, 0, 0 ); + Fractal0->SetSizeCX( 2.5, 2.5, 2, 1.5 ); + Fractal0->SetMaximumNumberOfIterations( 100); + + vtkImageCast* cast = vtkImageCast::New(); + cast->SetInputConnection(Fractal0->GetOutputPort()); + cast->SetOutputScalarTypeToUnsignedChar(); + + vtkLookupTable* table = vtkLookupTable::New(); + table->SetTableRange(0, 100); + table->SetNumberOfColors(100); + table->Build(); + table->SetTableValue(99, 0, 0, 0); + + vtkImageMapToColors* colorize = vtkImageMapToColors::New(); + colorize->SetOutputFormatToRGB(); + colorize->SetLookupTable(table); + colorize->SetInputConnection(cast->GetOutputPort()); + + vtkMPEG2Writer *w = vtkMPEG2Writer::New(); + w->SetInputConnection(colorize->GetOutputPort()); + w->SetFileName("TestMovieWriter.mpg"); + cout << "Writing file TestMovieWriter.mpg..." << endl; + w->Start(); + for ( cc = 2; cc < 99; cc ++ ) + { + cout << "."; + Fractal0->SetMaximumNumberOfIterations(cc); + table->SetTableRange(0, cc); + table->SetNumberOfColors(cc); + table->ForceBuild(); + table->SetTableValue(cc-1, 0, 0, 0); + w->Write(); + } + w->End(); + cout << endl; + cout << "Done writing file TestMovieWriter.mpg..." << endl; + w->Delete(); + + exists = (int) vtksys::SystemTools::FileExists("TestMovieWriter.mpg"); + length = vtksys::SystemTools::FileLength("TestMovieWriter.mpg"); + cout << "TestMovieWriter.mpg file exists: " << exists << endl; + cout << "TestMovieWriter.mpg file length: " << length << endl; + if (!exists) + { + err = 1; + cerr << "ERROR: 1 - Test failing because TestMovieWriter.mpg file doesn't exist..." << endl; + } + if (0==length) + { + err = 2; + cerr << "ERROR: 2 - Test failing because TestMovieWriter.mpg file has zero length..." << endl; + } + + colorize->Delete(); + table->Delete(); + cast->Delete(); + Fractal0->Delete(); + + // err == 0 means test passes... + // + return err; +} diff --git a/IO/Testing/Cxx/TestXML.cxx b/IO/Testing/Cxx/TestXML.cxx new file mode 100644 index 0000000..5856238 --- /dev/null +++ b/IO/Testing/Cxx/TestXML.cxx @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestXML.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME Test of vtkXMLParser +// .SECTION Description +// + +#include "vtkXMLParser.h" +#include "vtkOutputWindow.h" +#include "vtkObjectFactory.h" + + +class vtkMyXML : public vtkXMLParser +{ +public: + vtkTypeMacro(vtkMyXML, vtkXMLParser); + static vtkMyXML* New(); + +protected: + vtkMyXML() {} + void StartElement(const char*, const char**) {} + void EndElement(const char*) {} + +private: + vtkMyXML(const vtkMyXML&); // Not implemented + void operator=(const vtkMyXML&); // Not implemented +}; + +vtkStandardNewMacro(vtkMyXML); + +int TestXML(int argc, char *argv[]) +{ + int res = 0; + vtkOutputWindow::GetInstance()->PromptUserOn(); + if ( argc <= 1 ) + { + cout << "Usage: " << argv[0] << " " << endl; + return 1; + } + + vtkMyXML *parser = vtkMyXML::New(); + parser->SetFileName(argv[1]); + if ( ! parser->Parse() ) + { + cout << "Cannot parse the file: " << argv[1] << endl; + res = 1; + } + parser->SetFileName(0); + + if( !parser->Parse("This is an XML file") ) + { + cout << "Cannot parse message" << endl; + res = 1; + } + + parser->Delete(); + + return res; +} diff --git a/IO/Testing/Cxx/TestXMLCInterface.c b/IO/Testing/Cxx/TestXMLCInterface.c new file mode 100644 index 0000000..2279911 --- /dev/null +++ b/IO/Testing/Cxx/TestXMLCInterface.c @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestXMLCInterface.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkXMLWriterC.h" + +#define NPOINTS 8 +#define NTIMESTEPS 8 + +int main() +{ + int i,j; + vtkXMLWriterC* writer = vtkXMLWriterC_New(); + const char filename[] = "cube.vtu"; + float points[3*NPOINTS] = {0, 0, 0, + 1, 0, 0, + 1, 1, 0, + 0, 1, 0, + 0, 0, 1, + 1, 0, 1, + 1, 1, 1, + 0, 1, 1 }; + vtkIdType cellarray[] = {8, 0, 1, 2, 3, 4, 5, 6, 7}; + float pointdata[NTIMESTEPS][NPOINTS]; + /* Give different values for the pointdata: */ + for(i=0;i 5 } {set column 1; incr row} +} + +camera SetViewUp 0 1 0 +camera SetFocalPoint 0 0 0 +camera SetPosition 1 0 0 +ren100 ResetCamera +camera Dolly 1.25 +ren100 ResetCameraClippingRange +ren110 ResetCameraClippingRange +ren120 ResetCameraClippingRange +ren130 ResetCameraClippingRange +ren140 ResetCameraClippingRange +ren144 ResetCameraClippingRange +ren153 ResetCameraClippingRange +ren163 ResetCameraClippingRange +ren170 ResetCameraClippingRange +ren184 ResetCameraClippingRange + +eval light SetPosition [camera GetPosition] +eval light SetFocalPoint [camera GetFocalPoint] + +renWin SetSize 600 180 +renWin Render +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/IO/Testing/Tcl/Plot3DVectors.tcl b/IO/Testing/Tcl/Plot3DVectors.tcl new file mode 100644 index 0000000..9e828c7 --- /dev/null +++ b/IO/Testing/Tcl/Plot3DVectors.tcl @@ -0,0 +1,105 @@ +package require vtk +package require vtkinteraction + +# +# All Plot3D vector functions +# + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderWindow renWin +vtkRenderer ren1 + ren1 SetBackground .8 .8 .2 +renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +set vectorLabels "Velocity Vorticity Momentum Pressure_Gradient" +set vectorFunctions "200 201 202 210" +vtkCamera camera +vtkLight light + +# All text actors will share the same text prop + +vtkTextProperty textProp + textProp SetFontSize 10 + textProp SetFontFamilyToArial + textProp SetColor .3 1 1 + +set i 0 +foreach vectorFunction $vectorFunctions { + vtkPLOT3DReader pl3d$vectorFunction + pl3d$vectorFunction SetXYZFileName "$VTK_DATA_ROOT/Data/bluntfinxyz.bin" + pl3d$vectorFunction SetQFileName "$VTK_DATA_ROOT/Data/bluntfinq.bin" + pl3d$vectorFunction SetVectorFunctionNumber [expr int($vectorFunction)] + pl3d$vectorFunction Update +vtkStructuredGridGeometryFilter plane$vectorFunction + plane$vectorFunction SetInputConnection [pl3d$vectorFunction GetOutputPort] + plane$vectorFunction SetExtent 25 25 0 100 0 100 +vtkHedgeHog hog$vectorFunction + hog$vectorFunction SetInputConnection [plane$vectorFunction GetOutputPort] + set maxnorm [[[[pl3d$vectorFunction GetOutput] GetPointData] GetVectors] GetMaxNorm] + hog$vectorFunction SetScaleFactor [expr 1.0 / $maxnorm] +vtkPolyDataMapper mapper$vectorFunction + mapper$vectorFunction SetInputConnection [hog$vectorFunction GetOutputPort] +vtkActor actor$vectorFunction + actor$vectorFunction SetMapper mapper$vectorFunction + +vtkRenderer ren$vectorFunction + ren$vectorFunction SetBackground 0.5 .5 .5 + ren$vectorFunction SetActiveCamera camera + ren$vectorFunction AddLight light + renWin AddRenderer ren$vectorFunction + +ren$vectorFunction AddActor actor$vectorFunction + +vtkTextMapper textMapper$vectorFunction + textMapper$vectorFunction SetInput [lindex $vectorLabels $i] + textMapper$vectorFunction SetTextProperty textProp +vtkActor2D text$vectorFunction + text$vectorFunction SetMapper textMapper$vectorFunction + text$vectorFunction SetPosition 2 5 + + if { [info command "rtExMath"] == ""} { + ren$vectorFunction AddActor2D text$vectorFunction + } +incr i +} +# +# now layout renderers +set column 1 +set row 1 +set deltaX [expr 1.0/2.0] +set deltaY [expr 1.0/2.0] + +foreach vectorFunction $vectorFunctions { + ren${vectorFunction} SetViewport [expr ($column - 1) * $deltaX + ($deltaX * .05)] [expr ($row - 1) * $deltaY + ($deltaY*.05)] [expr $column * $deltaX - ($deltaX * .05)] [expr $row * $deltaY - ($deltaY * .05)] + incr column + if { $column > 2 } {set column 1; incr row} +} + + +camera SetViewUp 1 0 0 +camera SetFocalPoint 0 0 0 +camera SetPosition .4 -.5 -.75 +ren200 ResetCamera +camera Dolly 1.25 +ren200 ResetCameraClippingRange +ren201 ResetCameraClippingRange +ren202 ResetCameraClippingRange +ren210 ResetCameraClippingRange + +eval light SetPosition [camera GetPosition] +eval light SetFocalPoint [camera GetFocalPoint] + +renWin SetSize 350 350 +renWin Render + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/IO/Testing/Tcl/TestAVSucdReader.tcl b/IO/Testing/Tcl/TestAVSucdReader.tcl new file mode 100644 index 0000000..ccd542e --- /dev/null +++ b/IO/Testing/Tcl/TestAVSucdReader.tcl @@ -0,0 +1,42 @@ +package require vtk +package require vtkinteraction + +# Read some AVS UCD data in ASCII form +vtkAVSucdReader r + r SetFileName "$VTK_DATA_ROOT/Data/cellsnd.ascii.inp" +vtkDataSetMapper AVSMapper + AVSMapper SetInputConnection [r GetOutputPort] +vtkActor AVSActor + AVSActor SetMapper AVSMapper + +# Read some AVS UCD data in binary form +vtkAVSucdReader r2 + r2 SetFileName "$VTK_DATA_ROOT/Data/cellsnd.bin.inp" +vtkDataSetMapper AVSMapper2 + AVSMapper2 SetInputConnection [r2 GetOutputPort] +vtkActor AVSActor2 + AVSActor2 SetMapper AVSMapper2 + AVSActor2 AddPosition 5 0 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor AVSActor +ren1 AddActor AVSActor2 + +renWin SetSize 300 150 +iren Initialize +renWin Render +[ren1 GetActiveCamera] Zoom 2 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/IO/Testing/Tcl/TestBMPReader.tcl b/IO/Testing/Tcl/TestBMPReader.tcl new file mode 100644 index 0000000..fedb09f --- /dev/null +++ b/IO/Testing/Tcl/TestBMPReader.tcl @@ -0,0 +1,30 @@ +# this test is designed to check the operation of the 8bit +# export of BMPs + +package require vtk + +# Image pipeline + +vtkBMPReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" +reader SetAllow8BitBMP 1 + +vtkImageMapToColors map +map SetInputConnection [reader GetOutputPort] +map SetLookupTable [reader GetLookupTable] +map SetOutputFormatToRGB + +vtkImageViewer viewer +viewer SetInputConnection [map GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + +#make interface +viewer Render + + + + + + + diff --git a/IO/Testing/Tcl/TestChacoReader.tcl b/IO/Testing/Tcl/TestChacoReader.tcl new file mode 100644 index 0000000..73eb3e5 --- /dev/null +++ b/IO/Testing/Tcl/TestChacoReader.tcl @@ -0,0 +1,45 @@ +package require vtk +package require vtkinteraction + +# read in a Chaco file +vtkChacoReader chReader + chReader SetBaseName "$VTK_DATA_ROOT/Data/vwgt" + chReader SetGenerateGlobalElementIdArray 1 + chReader SetGenerateGlobalNodeIdArray 1 + chReader SetGenerateEdgeWeightArrays 1 + chReader SetGenerateVertexWeightArrays 1 + +vtkGeometryFilter geom + geom SetInputConnection [chReader GetOutputPort] + +vtkPolyDataMapper mapper + mapper SetInputConnection [geom GetOutputPort] + mapper SetColorModeToMapScalars + mapper SetScalarModeToUsePointFieldData + mapper SelectColorArray "VertexWeight1" + mapper SetScalarRange 1 5 + +vtkActor actor0 + actor0 SetMapper mapper + +# Create the RenderWindow, Renderer and interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actor to the renderer, set the background and size +# +ren1 AddActor actor0 +ren1 SetBackground 0 0 0 + +renWin SetSize 300 300 +iren Initialize +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/IO/Testing/Tcl/TestEmptyXML.tcl b/IO/Testing/Tcl/TestEmptyXML.tcl new file mode 100644 index 0000000..a93b4f2 --- /dev/null +++ b/IO/Testing/Tcl/TestEmptyXML.tcl @@ -0,0 +1,130 @@ +package require vtk + +# List of types and corresponding file extensions. +set types { + {ImageData vti} + {RectilinearGrid vtr} + {StructuredGrid vts} + {PolyData vtp} + {UnstructuredGrid vtu} +} + +# We intentionally cause vtkErrorMacro calls to be made below. Dump +# errors to a file to prevent a window from coming up. +vtkFileOutputWindow fow +fow SetFileName "TestEmptyXMLErrors.txt" +fow SetFlush 0 +fow SetInstance fow + +# Prepare some test files. +file delete -force "junkFile.vtk" +file delete -force "emptyFile.vtk" +set f [open "emptyFile.vtk" w] +close $f +set f [open "junkFile.vtk" w] +puts $f "v9np7598mapwcawoiur-,rjpmW9MJV28nun-q38ynq-9 8ugujqvt-8n3-nv8" +close $f + +# Test each writer/reader. +foreach pair $types { + set type [lindex $pair 0] + set ext [lindex $pair 1] + vtk${type} input + vtkXML${type}Writer writer + writer SetFileName "empty${type}.${ext}" + puts "Attempting ${type} write with no input." + catch {writer Write} + puts "Attempting ${type} write with empty input." + writer SetInput input + writer Write + + vtkXML${type}Reader reader + reader SetFileName "empty${type}.${ext}" + puts "Attempting read from file with empty ${type}." + reader Update + + vtkXMLP${type}Writer pwriter + pwriter SetFileName "emptyP${type}.p${ext}" + pwriter SetNumberOfPieces 1 + puts "Attempting P${type} write with no input." + catch {pwriter Write} + puts "Attempting P${type} write with empty input." + pwriter SetInput input + pwriter Write + + vtkXMLP${type}Reader preader + preader SetFileName "emptyP${type}.p${ext}" + puts "Attempting read from file with empty P${type}." + preader Update + + reader SetFileName "emptyFile.vtk" + preader SetFileName "emptyFile.vtk" + + puts "Attempting read ${type} from empty file." + reader Update + puts "Attempting read P${type} from empty file." + preader Update + + reader SetFileName "junkFile.vtk" + preader SetFileName "junkFile.vtk" + + puts "Attempting read ${type} from junk file." + reader Update + puts "Attempting read P${type} from junk file." + preader Update + + input Delete + writer Delete + reader Delete + pwriter Delete + preader Delete +} + +# Test the data set writers. +foreach pair $types { + set type [lindex $pair 0] + set ext [lindex $pair 1] + vtkXMLDataSetWriter writer + vtkXMLPDataSetWriter pwriter + vtk${type} input + + writer SetFileName "empty${type}DataSet.${ext}" + puts "Attempting DataSet ${type} write with no input." + catch {writer Write} + puts "Attempting DataSet ${type} write with empty input." + writer SetInput input + writer Write + + pwriter SetFileName "emptyP${type}DataSet.p${ext}" + pwriter SetNumberOfPieces 1 + puts "Attempting DataSet P${type} write with no input." + catch {pwriter Write} + puts "Attempting DataSet P${type} write with empty input." + pwriter SetInput input + pwriter Write + + input Delete + pwriter Delete + writer Delete +} + +# Done with file output window. +fow SetInstance {} +fow Delete + +# Delete the test files. +foreach pair $types { + set type [lindex $pair 0] + set ext [lindex $pair 1] + file delete -force "empty${type}.${ext}" + file delete -force "empty${type}DataSet.${ext}" + file delete -force "emptyP${type}.p${ext}" + file delete -force "emptyP${type}0.${ext}" + file delete -force "emptyP${type}DataSet.p${ext}" + file delete -force "emptyP${type}DataSet0.${ext}" +} +file delete -force "junkFile.vtk" +file delete -force "emptyFile.vtk" +file delete -force "TestEmptyXMLErrors.txt" + +exit diff --git a/IO/Testing/Tcl/TestGAMBITReader.tcl b/IO/Testing/Tcl/TestGAMBITReader.tcl new file mode 100644 index 0000000..2b89c02 --- /dev/null +++ b/IO/Testing/Tcl/TestGAMBITReader.tcl @@ -0,0 +1,31 @@ +package require vtk +package require vtkinteraction + +# Read some Fluent GAMBIT in ASCII form +vtkGAMBITReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/prism.neu" +vtkDataSetMapper mapper + mapper SetInputConnection [reader GetOutputPort] +vtkActor actor + actor SetMapper mapper + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor + +renWin SetSize 300 300 +iren Initialize +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/IO/Testing/Tcl/TestImageWriters.tcl b/IO/Testing/Tcl/TestImageWriters.tcl new file mode 100644 index 0000000..31d9a16 --- /dev/null +++ b/IO/Testing/Tcl/TestImageWriters.tcl @@ -0,0 +1,112 @@ +package require vtk + +# Image pipeline + +vtkTIFFReader image1 + image1 SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + image1 Update + +vtkStructuredPoints sp +eval sp SetDimensions [[image1 GetOutput] GetDimensions] +eval sp SetExtent [[image1 GetOutput] GetExtent] +sp SetScalarType [[image1 GetOutput] GetScalarType] +sp SetNumberOfScalarComponents [[image1 GetOutput] GetNumberOfScalarComponents] +[sp GetPointData] SetScalars [[[image1 GetOutput] GetPointData] GetScalars] + +vtkImageLuminance luminance + luminance SetInput sp + +# +# write to the temp directory if possible, otherwise use . +# +set dir "." +if {[info commands "rtTester"] == "rtTester"} { + set dir [rtTester GetTempDirectory] +} + +# make sure it is writeable first +if {[catch {set channel [open "$dir/test.tmp" "w"]}] == 0 } { + close $channel + file delete -force "$dir/test.tmp" + + vtkTIFFWriter tiff1 + tiff1 SetInputConnection [image1 GetOutputPort] + tiff1 SetFileName "$dir/tiff1.tif" + + vtkTIFFWriter tiff2 + tiff2 SetInputConnection [luminance GetOutputPort] + tiff2 SetFileName "$dir/tiff2.tif" + + vtkBMPWriter bmp1 + bmp1 SetInputConnection [image1 GetOutputPort] + bmp1 SetFileName "$dir/bmp1.bmp" + + vtkBMPWriter bmp2 + bmp2 SetInputConnection [luminance GetOutputPort] + bmp2 SetFileName "$dir/bmp2.bmp" + + vtkPNMWriter pnm1 + pnm1 SetInputConnection [image1 GetOutputPort] + pnm1 SetFileName "$dir/pnm1.pnm" + + vtkPNMWriter pnm2 + pnm2 SetInputConnection [luminance GetOutputPort] + pnm2 SetFileName "$dir/pnm2.pnm" + + vtkPostScriptWriter psw1 + psw1 SetInputConnection [image1 GetOutputPort] + psw1 SetFileName "$dir/psw1.ps" + + vtkPostScriptWriter psw2 + psw2 SetInputConnection [luminance GetOutputPort] + psw2 SetFileName "$dir/psw2.ps" + + vtkPNGWriter pngw1 + pngw1 SetInputConnection [image1 GetOutputPort] + pngw1 SetFileName "$dir/pngw1.png" + + vtkPNGWriter pngw2 + pngw2 SetInputConnection [luminance GetOutputPort] + pngw2 SetFileName "$dir/pngw2.png" + + vtkJPEGWriter jpgw1 + jpgw1 SetInputConnection [image1 GetOutputPort] + jpgw1 SetFileName "$dir/jpgw1.jpg" + + vtkJPEGWriter jpgw2 + jpgw2 SetInputConnection [luminance GetOutputPort] + jpgw2 SetFileName "$dir/jpgw2.jpg" + + tiff1 Write + tiff2 Write + bmp1 Write + bmp2 Write + pnm1 Write + pnm2 Write + psw1 Write + psw2 Write + pngw1 Write + pngw2 Write + jpgw1 Write + jpgw2 Write + + file delete -force "$dir/tiff1.tif" + file delete -force "$dir/tiff2.tif" + file delete -force "$dir/bmp1.bmp" + file delete -force "$dir/bmp2.bmp" + file delete -force "$dir/pnm1.pnm" + file delete -force "$dir/pnm2.pnm" + file delete -force "$dir/psw1.ps" + file delete -force "$dir/psw2.ps" + file delete -force "$dir/pngw1.png" + file delete -force "$dir/pngw2.png" + file delete -force "$dir/jpgw1.jpg" + file delete -force "$dir/jpgw2.jpg" +} + +vtkImageViewer viewer + viewer SetInputConnection [luminance GetOutputPort] + viewer SetColorWindow 255 + viewer SetColorLevel 127.5 + viewer Render + diff --git a/IO/Testing/Tcl/TestJPEGReader.tcl b/IO/Testing/Tcl/TestJPEGReader.tcl new file mode 100644 index 0000000..db21b83 --- /dev/null +++ b/IO/Testing/Tcl/TestJPEGReader.tcl @@ -0,0 +1,24 @@ +package require vtk + +# Image pipeline + +vtkImageReader2Factory createReader +set reader [createReader CreateImageReader2 "$VTK_DATA_ROOT/Data/beach.jpg"] +$reader SetFileName "$VTK_DATA_ROOT/Data/beach.jpg" + +vtkImageViewer viewer +viewer SetInputConnection [$reader GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + + +#make interface +viewer Render +$reader UnRegister viewer + + + + + + + diff --git a/IO/Testing/Tcl/TestMHD.tcl b/IO/Testing/Tcl/TestMHD.tcl new file mode 100644 index 0000000..ac53c5a --- /dev/null +++ b/IO/Testing/Tcl/TestMHD.tcl @@ -0,0 +1,65 @@ +package require vtk +package require vtkinteraction + +vtkRenderer Ren1 + Ren1 SetBackground 0.33 0.35 0.43 +vtkRenderWindow renWin + renWin AddRenderer Ren1 + renWin SetSize 300 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkImageReader reader + reader SetDataByteOrderToLittleEndian + reader SetDataExtent 0 63 0 63 1 93 + reader SetDataSpacing 3.2 3.2 1.5 + reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + reader SetDataMask 0x7fff + +vtkMetaImageWriter pvTemp200 + pvTemp200 SetFileName "mhdWriter.mhd" + pvTemp200 SetInput [ reader GetOutput ] + pvTemp200 Write +vtkMetaImageReader pvTemp90 + pvTemp90 SetFileName "mhdWriter.mhd" +vtkLookupTable pvTemp109 + pvTemp109 SetNumberOfTableValues 256 + pvTemp109 SetHueRange 0.6667 0 + pvTemp109 SetSaturationRange 1 1 + pvTemp109 SetValueRange 1 1 + pvTemp109 SetTableRange 37.3531 260 + pvTemp109 SetVectorComponent 0 + pvTemp109 Build + +vtkContourFilter pvTemp110 + pvTemp110 SetInput [pvTemp90 GetOutput 0] + pvTemp110 SetValue 0 1150 + pvTemp110 SetComputeNormals 1 + pvTemp110 SetComputeGradients 0 + pvTemp110 SetComputeScalars 0 +vtkPolyDataMapper pvTemp114 + pvTemp114 SetInputConnection [pvTemp110 GetOutputPort] + pvTemp114 SetImmediateModeRendering 1 + pvTemp114 SetScalarRange 0 1 + pvTemp114 UseLookupTableScalarRangeOn + pvTemp114 SetScalarVisibility 1 + pvTemp114 SetScalarModeToUsePointFieldData + pvTemp114 SelectColorArray "ImageFile" +pvTemp114 SetLookupTable pvTemp109 +vtkActor pvTemp115 + pvTemp115 SetMapper pvTemp114 + [ pvTemp115 GetProperty] SetRepresentationToSurface + [pvTemp115 GetProperty] SetInterpolationToGouraud + [pvTemp115 GetProperty] SetAmbient 0 + [pvTemp115 GetProperty] SetDiffuse 1 + [pvTemp115 GetProperty] SetSpecular 0 + [pvTemp115 GetProperty] SetSpecularPower 1 + [pvTemp115 GetProperty] SetSpecularColor 1 1 1 +Ren1 AddActor pvTemp115 + + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/IO/Testing/Tcl/TestPLYReadWrite.tcl b/IO/Testing/Tcl/TestPLYReadWrite.tcl new file mode 100644 index 0000000..66804db --- /dev/null +++ b/IO/Testing/Tcl/TestPLYReadWrite.tcl @@ -0,0 +1,98 @@ +package require vtk +package require vtkinteraction + +vtkSphereSource ss + ss SetPhiResolution 10 + ss SetThetaResolution 20 +vtkSimpleElevationFilter ele + ele SetInputConnection [ss GetOutputPort] +vtkPointDataToCellData pd2cd + pd2cd SetInput [ele GetPolyDataOutput] + +# First way or writing +vtkPLYWriter w + w SetInput [pd2cd GetPolyDataOutput] + w SetFileName "plyWriter.ply" + w SetFileTypeToBinary + w SetDataByteOrderToLittleEndian + w SetColorModeToUniformCellColor + w SetColor 255 0 0 + w Write +vtkPLYReader r + r SetFileName "plyWriter.ply" + r Update +file delete -force "plyWriter.ply" +vtkPolyDataMapper plyMapper + plyMapper SetInputConnection [r GetOutputPort] +vtkActor plyActor + plyActor SetMapper plyMapper + +# Second way or writing - it will map through a lookup table +vtkLookupTable lut + lut Build +vtkPLYWriter w2 + w2 SetInput [pd2cd GetPolyDataOutput] + w2 SetFileName "plyWriter.ply" + w2 SetFileTypeToBinary + w2 SetDataByteOrderToLittleEndian + w2 SetColorModeToDefault + w2 SetLookupTable lut + w2 SetArrayName "Elevation" + w2 SetComponent 0 + w2 Write +vtkPLYReader r2 + r2 SetFileName "plyWriter.ply" + r2 Update +vtkPolyDataMapper plyMapper2 + plyMapper2 SetInputConnection [r2 GetOutputPort] +vtkActor plyActor2 + plyActor2 SetMapper plyMapper2 + plyActor2 AddPosition 1 0 0 + +# Third way or writing - it will read the previous file with rgb cell color +vtkPLYReader r3 + r3 SetFileName "plyWriter.ply" + r3 Update +vtkPLYWriter w3 + w3 SetInputConnection [r3 GetOutputPort] + w3 SetFileName "plyWriter.ply" + w3 SetFileTypeToBinary + w3 SetDataByteOrderToLittleEndian + w3 SetColorModeToDefault + w3 SetArrayName "RGB" + w3 SetComponent 0 + w3 Write +vtkPLYReader r4 + r4 SetFileName "plyWriter.ply" + r4 Update +vtkPolyDataMapper plyMapper3 + plyMapper3 SetInputConnection [r4 GetOutputPort] +vtkActor plyActor3 + plyActor3 SetMapper plyMapper3 + plyActor3 AddPosition 2 0 0 + +file delete -force "plyWriter.ply" + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor plyActor +ren1 AddActor plyActor2 +ren1 AddActor plyActor3 + +renWin SetSize 325 125 +iren Initialize +renWin Render +[ren1 GetActiveCamera] Zoom 3.0 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/IO/Testing/Tcl/TestPolygonWriters.tcl b/IO/Testing/Tcl/TestPolygonWriters.tcl new file mode 100644 index 0000000..b027d03 --- /dev/null +++ b/IO/Testing/Tcl/TestPolygonWriters.tcl @@ -0,0 +1,151 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# read data +# +vtkPolyDataReader input + input SetFileName "$VTK_DATA_ROOT/Data/brainImageSmooth.vtk" + +# +# generate vectors +vtkCleanPolyData clean + clean SetInputConnection [input GetOutputPort] + +vtkWindowedSincPolyDataFilter smooth + smooth SetInputConnection [clean GetOutputPort] + smooth GenerateErrorVectorsOn + smooth GenerateErrorScalarsOn + smooth Update + +vtkPolyDataMapper mapper + mapper SetInputConnection [smooth GetOutputPort] + eval mapper SetScalarRange [[smooth GetOutput] GetScalarRange] + +vtkActor brain + brain SetMapper mapper + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor brain + +renWin SetSize 320 240 + +[ren1 GetActiveCamera] SetPosition 149.653 -65.3464 96.0401 +[ren1 GetActiveCamera] SetFocalPoint 146.003 22.3839 0.260541 +[ren1 GetActiveCamera] SetViewAngle 30 +[ren1 GetActiveCamera] SetViewUp -0.255578 -0.717754 -0.647695 +[ren1 GetActiveCamera] SetClippingRange 79.2526 194.052 + +iren Initialize +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# +# If the current directory is writable, then test the witers +# + +if {[catch {set channel [open "test.tmp" "w"]}] == 0 } { + close $channel + file delete -force "test.tmp" + + # + # + # test the writers + vtkDataSetWriter dsw + dsw SetInputConnection [smooth GetOutputPort] + dsw SetFileName "brain.dsw" + dsw Write + file delete -force "brain.dsw" + + vtkPolyDataWriter pdw + pdw SetInputConnection [smooth GetOutputPort] + pdw SetFileName "brain.pdw" + pdw Write + file delete -force "brain.pdw" + + if { [info command "vtkIVWriter"] != "" } { + vtkIVWriter iv + iv SetInputConnection [smooth GetOutputPort] + iv SetFileName "brain.iv" + iv Write + file delete -force "brain.iv" + } + + # + # the next writers only handle triangles + vtkTriangleFilter triangles + triangles SetInputConnection [smooth GetOutputPort] + + if { [info command "vtkIVWriter"] != "" } { + vtkIVWriter iv2 + iv2 SetInputConnection [triangles GetOutputPort] + iv2 SetFileName "brain2.iv" + iv2 Write + file delete -force "brain2.iv" + } + + if { [info command "vtkIVWriter"] != "" } { + vtkExtractEdges edges + edges SetInputConnection [triangles GetOutputPort] + vtkIVWriter iv3 + iv3 SetInputConnection [edges GetOutputPort] + iv3 SetFileName "brain3.iv" + iv3 Write + file delete -force "brain3.iv" + } + + vtkBYUWriter byu + byu SetGeometryFileName "brain.g" + byu SetScalarFileName "brain.s" + byu SetDisplacementFileName "brain.d" + byu SetInputConnection [triangles GetOutputPort] + byu Write + file delete -force "brain.g" + file delete -force "brain.s" + file delete -force "brain.d" + + vtkMCubesWriter mcubes + mcubes SetInputConnection [triangles GetOutputPort] + mcubes SetFileName "brain.tri" + mcubes SetLimitsFileName "brain.lim" + mcubes Write + file delete -force "brain.lim" + file delete -force "brain.tri" + + vtkSTLWriter stl + stl SetInputConnection [triangles GetOutputPort] + stl SetFileName "brain.stl" + stl Write + file delete -force "brain.stl" + + vtkSTLWriter stlBinary + stlBinary SetInputConnection [triangles GetOutputPort] + stlBinary SetFileName "brainBinary.stl" + stlBinary SetFileType 2 + stlBinary Write + file delete -force "brainBinary.stl" + + vtkCGMWriter cgm + cgm SetInputConnection [triangles GetOutputPort] + cgm SetFileName "brain.cgm" + cgm Write + file delete -force "brain.cgm" +} + + + diff --git a/IO/Testing/Tcl/TestSimplePointsReader.tcl b/IO/Testing/Tcl/TestSimplePointsReader.tcl new file mode 100644 index 0000000..c3d2f08 --- /dev/null +++ b/IO/Testing/Tcl/TestSimplePointsReader.tcl @@ -0,0 +1,26 @@ +package require vtk +package require vtkinteraction + +vtkSimplePointsReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/points.txt" + +vtkPolyDataMapper mapper + mapper SetInputConnection [reader GetOutputPort] + +vtkActor actor + actor SetMapper mapper + [actor GetProperty] SetPointSize 5 + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor actor + +renWin SetSize 300 300 +iren Initialize +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} +wm withdraw . diff --git a/IO/Testing/Tcl/TestTIFFReader.tcl b/IO/Testing/Tcl/TestTIFFReader.tcl new file mode 100644 index 0000000..c6e09a4 --- /dev/null +++ b/IO/Testing/Tcl/TestTIFFReader.tcl @@ -0,0 +1,17 @@ +package require vtk + +# Image pipeline + +vtkImageReader2Factory createReader +set reader [createReader CreateImageReader2 "$VTK_DATA_ROOT/Data/beach.tif"] +$reader SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + +vtkImageViewer viewer +viewer SetInputConnection [$reader GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + + +#make interface +viewer Render +$reader UnRegister viewer diff --git a/IO/Testing/Tcl/TestXMLImageDataIO.tcl b/IO/Testing/Tcl/TestXMLImageDataIO.tcl new file mode 100644 index 0000000..8947e44 --- /dev/null +++ b/IO/Testing/Tcl/TestXMLImageDataIO.tcl @@ -0,0 +1,126 @@ +package require vtk +package require vtkinteraction + +set file0 idFile0.vti +set file1 idFile1.vti +set file2 idFile2.vti + +# read in some image data +vtkImageReader imageReader + imageReader SetDataByteOrderToLittleEndian + imageReader SetDataExtent 0 63 0 63 1 93 + imageReader SetDataSpacing 3.2 3.2 1.5 + imageReader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + imageReader Update + +# extract to reduce extents of grid +vtkExtractVOI extract + extract SetInputConnection [imageReader GetOutputPort] + extract SetVOI 0 63 0 63 0 45 + extract Update + +# write just a piece (extracted piece) as well as the whole thing +vtkXMLImageDataWriter idWriter + idWriter SetFileName $file0 + idWriter SetDataModeToAscii + idWriter SetInputConnection [extract GetOutputPort] + idWriter Write + + idWriter SetFileName $file1 + idWriter SetDataModeToAppended + idWriter SetInputConnection [imageReader GetOutputPort] + idWriter SetNumberOfPieces 2 + idWriter Write + + idWriter SetFileName $file2 + idWriter SetDataModeToBinary + idWriter SetWriteExtent 1 31 4 63 12 92 + idWriter Write + +# read the extracted grid +vtkXMLImageDataReader reader + reader SetFileName $file0 + reader WholeSlicesOff + reader Update + +vtkImageData id0 + id0 DeepCopy [reader GetOutput] + +vtkContourFilter cF0 + cF0 SetInput id0 + cF0 SetValue 0 500 + +vtkPolyDataMapper mapper0 + mapper0 SetInputConnection [cF0 GetOutputPort] + mapper0 ScalarVisibilityOff + +vtkActor actor0 + actor0 SetMapper mapper0 + actor0 SetPosition 180 -60 0 + + +# read the whole image +reader SetFileName $file1 +reader WholeSlicesOn +reader Update + +vtkImageData id1 + id1 DeepCopy [reader GetOutput] + +vtkContourFilter cF1 + cF1 SetInput id1 + cF1 SetValue 0 500 + +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [cF1 GetOutputPort] + mapper1 ScalarVisibilityOff + +vtkActor actor1 + actor1 SetMapper mapper1 + actor1 SetOrientation 90 0 0 + + +# read the paritally written image +reader SetFileName $file2 +reader Update + +vtkContourFilter cF2 + cF2 SetInputConnection [reader GetOutputPort] + cF2 SetValue 0 500 + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [cF2 GetOutputPort] + mapper2 ScalarVisibilityOff + +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetOrientation 0 -90 0 + actor2 SetPosition 180 -30 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor0 +ren1 AddActor actor1 +ren1 AddActor actor2 + +renWin SetSize 300 300 +iren Initialize +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + +file delete -force $file0 +file delete -force $file1 +file delete -force $file2 diff --git a/IO/Testing/Tcl/TestXMLPolyDataIO.tcl b/IO/Testing/Tcl/TestXMLPolyDataIO.tcl new file mode 100644 index 0000000..816045f --- /dev/null +++ b/IO/Testing/Tcl/TestXMLPolyDataIO.tcl @@ -0,0 +1,103 @@ +package require vtk +package require vtkinteraction + +set file0 idFile0.vti +set file1 idFile1.vti +set file2 idFile2.vti + +# read in some poly data +vtkPolyDataReader pdReader + pdReader SetFileName "$VTK_DATA_ROOT/Data/fran_cut.vtk" + pdReader Update + +vtkExtractPolyDataPiece extract + extract SetInputConnection [pdReader GetOutputPort] + +# write various versions +vtkXMLPolyDataWriter pdWriter + pdWriter SetFileName $file0 + pdWriter SetDataModeToAscii + pdWriter SetInputConnection [pdReader GetOutputPort] + pdWriter Write + + pdWriter SetFileName $file1 + pdWriter SetInputConnection [extract GetOutputPort] + pdWriter SetDataModeToAppended + pdWriter SetNumberOfPieces 2 + pdWriter Write + + pdWriter SetFileName $file2 + pdWriter SetDataModeToBinary + pdWriter SetGhostLevel 3 + pdWriter Write + + +# read the ASCII version +vtkXMLPolyDataReader reader + reader SetFileName $file0 + reader Update + +vtkPolyData pd0 + pd0 DeepCopy [reader GetOutput] + +vtkPolyDataMapper mapper0 + mapper0 SetInput pd0 + +vtkActor actor0 + actor0 SetMapper mapper0 + actor0 SetPosition 0 .15 0 + + +# read appended piece 0 +reader SetFileName $file1 + +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [reader GetOutputPort] + mapper1 SetPiece 0 + mapper1 SetNumberOfPieces 2 + +vtkActor actor1 + actor1 SetMapper mapper1 + + +# read binary piece 0 (with ghost level) +vtkXMLPolyDataReader reader2 + reader2 SetFileName $file2 + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [reader2 GetOutputPort] + mapper2 SetPiece 0 + mapper2 SetNumberOfPieces 2 + +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetPosition 0 0 0.1 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor0 +ren1 AddActor actor1 +ren1 AddActor actor2 + +[ren1 GetActiveCamera] SetPosition 0.514096 -0.14323 -0.441177 +[ren1 GetActiveCamera] SetFocalPoint 0.0528 -0.0780001 -0.0379661 +renWin SetSize 300 300 +iren Initialize +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +file delete -force $file0 +file delete -force $file1 +file delete -force $file2 diff --git a/IO/Testing/Tcl/TestXMLRectilinearGridIO.tcl b/IO/Testing/Tcl/TestXMLRectilinearGridIO.tcl new file mode 100644 index 0000000..afcde08 --- /dev/null +++ b/IO/Testing/Tcl/TestXMLRectilinearGridIO.tcl @@ -0,0 +1,109 @@ +package require vtk +package require vtkinteraction + +set file0 rgFile0.vtr +set file1 rgFile1.vtr +set file2 rgFile2.vtr + +# read in some grid data +vtkRectilinearGridReader gridReader + gridReader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" + gridReader Update + +# extract to reduce extents of grid +vtkExtractRectilinearGrid extract + extract SetInputConnection [gridReader GetOutputPort] + extract SetVOI 0 23 0 32 0 10 + extract Update + +# write just a piece (extracted piece) as well as the whole thing +vtkXMLRectilinearGridWriter rgWriter + rgWriter SetFileName $file0 + rgWriter SetInputConnection [extract GetOutputPort] + rgWriter SetDataModeToAscii + rgWriter Write + + rgWriter SetFileName $file1 + rgWriter SetInputConnection [gridReader GetOutputPort] + rgWriter SetDataModeToAppended + rgWriter SetNumberOfPieces 2 + rgWriter Write + + rgWriter SetFileName $file2 + rgWriter SetDataModeToBinary + rgWriter SetWriteExtent 3 46 6 32 1 5 + rgWriter SetCompressor "" + if {[rgWriter GetByteOrder]} { + rgWriter SetByteOrder 0 + } else { + rgWriter SetByteOrder 1 + } + rgWriter Write + +# read the extracted grid +vtkXMLRectilinearGridReader reader + reader SetFileName $file0 + reader WholeSlicesOff + reader Update + +vtkRectilinearGrid rg0 + rg0 DeepCopy [reader GetOutput] + +vtkDataSetMapper mapper0 + mapper0 SetInput rg0 + +vtkActor actor0 + actor0 SetMapper mapper0 + +# read the whole grid +reader SetFileName $file1 +reader WholeSlicesOn +reader Update + +vtkRectilinearGrid rg1 + rg1 DeepCopy [reader GetOutput] + +vtkDataSetMapper mapper1 + mapper1 SetInput rg1 + +vtkActor actor1 + actor1 SetMapper mapper1 + actor1 SetPosition -1.5 3 0 + +# read the partially written grid +reader SetFileName $file2 +reader Update + +vtkDataSetMapper mapper2 + mapper2 SetInputConnection [reader GetOutputPort] + +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetPosition 1.5 3 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor0 +ren1 AddActor actor1 +ren1 AddActor actor2 + +renWin SetSize 300 300 +iren Initialize +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +file delete -force $file0 +file delete -force $file1 +file delete -force $file2 diff --git a/IO/Testing/Tcl/TestXMLStructuredGridIO.tcl b/IO/Testing/Tcl/TestXMLStructuredGridIO.tcl new file mode 100644 index 0000000..c87a46f --- /dev/null +++ b/IO/Testing/Tcl/TestXMLStructuredGridIO.tcl @@ -0,0 +1,122 @@ +package require vtk +package require vtkinteraction + +set file0 sgFile0.vts +set file1 sgFile1.vts +set file2 sgFile2.vts + +# Create a reader and write out the field +vtkPLOT3DReader combReader + combReader SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + combReader SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + combReader SetScalarFunctionNumber 100 + +# extract to reduce extents of grid +vtkExtractGrid extract + extract SetInputConnection [combReader GetOutputPort] + extract SetVOI 0 28 0 32 0 24 + extract Update + +# write just a piece (extracted piece) as well as the whole thing +vtkXMLStructuredGridWriter gridWriter + gridWriter SetFileName $file0 + gridWriter SetInputConnection [extract GetOutputPort] + gridWriter SetDataModeToAscii + gridWriter Write + + gridWriter SetInputConnection [combReader GetOutputPort] + gridWriter SetFileName $file1 + gridWriter SetDataModeToAppended + gridWriter SetNumberOfPieces 2 + gridWriter Write + + gridWriter SetFileName $file2 + gridWriter SetDataModeToBinary + gridWriter SetWriteExtent 8 56 4 16 1 24 + gridWriter Write + +# read the extracted grid +vtkXMLStructuredGridReader reader + reader SetFileName $file0 + reader WholeSlicesOff + reader Update + +vtkStructuredGrid sg + sg DeepCopy [reader GetOutput] + +vtkContourFilter cF0 + cF0 SetInput sg + cF0 SetValue 0 0.38 + +vtkPolyDataMapper mapper0 + mapper0 SetInputConnection [cF0 GetOutputPort] + mapper0 ScalarVisibilityOff + +vtkActor actor0 + actor0 SetMapper mapper0 + + +# read the whole image +reader SetFileName $file1 +reader WholeSlicesOn +reader Update + +vtkStructuredGrid sg1 + sg1 DeepCopy [reader GetOutput] + +vtkContourFilter cF1 + cF1 SetInput sg1 + cF1 SetValue 0 0.38 + +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [cF1 GetOutputPort] + mapper1 ScalarVisibilityOff + +vtkActor actor1 + actor1 SetMapper mapper1 + actor1 SetPosition 0 -10 0 + + +# read the partially written grid +reader SetFileName $file2 +reader Update + +vtkContourFilter cF2 + cF2 SetInputConnection [reader GetOutputPort] + cF2 SetValue 0 0.38 + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [cF2 GetOutputPort] + mapper2 ScalarVisibilityOff + +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetPosition 0 10 0 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor0 +ren1 AddActor actor1 +ren1 AddActor actor2 + +renWin SetSize 300 300 +iren Initialize +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + +file delete -force $file0 +file delete -force $file1 +file delete -force $file2 diff --git a/IO/Testing/Tcl/TestXMLUnstructuredGridIO.tcl b/IO/Testing/Tcl/TestXMLUnstructuredGridIO.tcl new file mode 100644 index 0000000..719035a --- /dev/null +++ b/IO/Testing/Tcl/TestXMLUnstructuredGridIO.tcl @@ -0,0 +1,115 @@ +package require vtk +package require vtkinteraction + +set file0 ugFile0.vtu +set file1 ugFile1.vtu +set file2 ugFile2.vtu + +# read in some unstructured grid data +vtkUnstructuredGridReader ugReader + ugReader SetFileName "$VTK_DATA_ROOT/Data/blow.vtk" + ugReader SetScalarsName "thickness9" + ugReader SetVectorsName "displacement9" + +vtkExtractUnstructuredGridPiece extract + extract SetInputConnection [ugReader GetOutputPort] + +# write various versions +vtkXMLUnstructuredGridWriter ugWriter + ugWriter SetFileName $file0 + ugWriter SetDataModeToAscii + ugWriter SetInputConnection [ugReader GetOutputPort] + ugWriter Write + + ugWriter SetFileName $file1 + ugWriter SetInputConnection [extract GetOutputPort] + ugWriter SetDataModeToAppended + ugWriter SetNumberOfPieces 2 + ugWriter Write + + ugWriter SetFileName $file2 + ugWriter SetDataModeToBinary + ugWriter SetGhostLevel 2 + ugWriter Write + + +# read the ASCII version +vtkXMLUnstructuredGridReader reader + reader SetFileName $file0 + reader Update + +vtkUnstructuredGrid ug0 + ug0 DeepCopy [reader GetOutput] + +vtkDataSetSurfaceFilter sF + sF SetInput ug0 + +vtkPolyDataMapper mapper0 + mapper0 SetInputConnection [sF GetOutputPort] + +vtkActor actor0 + actor0 SetMapper mapper0 + actor0 SetPosition 0 40 20 + + +# read appended piece 0 +reader SetFileName $file1 + +vtkDataSetSurfaceFilter sF1 + sF1 SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [sF1 GetOutputPort] + mapper1 SetPiece 1 + mapper1 SetNumberOfPieces 2 + +vtkActor actor1 + actor1 SetMapper mapper1 + + +# read binary piece 0 (with ghost level) +vtkXMLUnstructuredGridReader reader2 + reader2 SetFileName $file2 + +vtkDataSetSurfaceFilter sF2 + sF2 SetInputConnection [reader2 GetOutputPort] + +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [sF2 GetOutputPort] + mapper2 SetPiece 1 + mapper2 SetNumberOfPieces 2 + mapper2 SetGhostLevel 2 + +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetPosition 0 0 30 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor0 +ren1 AddActor actor1 +ren1 AddActor actor2 + +ren1 ResetCamera +[ren1 GetActiveCamera] SetPosition 180 55 65 +[ren1 GetActiveCamera] SetFocalPoint 3.5 32 15 +renWin SetSize 300 300 +iren Initialize +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +file delete -force $file0 +file delete -force $file1 +file delete -force $file2 diff --git a/IO/Testing/Tcl/TestXYZMol.tcl b/IO/Testing/Tcl/TestXYZMol.tcl new file mode 100644 index 0000000..dc5cc97 --- /dev/null +++ b/IO/Testing/Tcl/TestXYZMol.tcl @@ -0,0 +1,84 @@ +package require vtk +package require vtkinteraction +vtkRenderer ren1 + ren1 SetBackground 0 0 0 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 300 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkXYZMolReader pdb0 + pdb0 SetFileName "$VTK_DATA_ROOT/Data/thio3xx.xyz" + +vtkSphereSource Sphere0 + Sphere0 SetCenter 0 0 0 + Sphere0 SetRadius 1 + Sphere0 SetThetaResolution 8 + Sphere0 SetStartTheta 0 + Sphere0 SetEndTheta 360 + Sphere0 SetPhiResolution 8 + Sphere0 SetStartPhi 0 + Sphere0 SetEndPhi 180 + +vtkGlyph3D Glyph0 + Glyph0 SetInputConnection [pdb0 GetOutputPort] + Glyph0 SetOrient 1 + Glyph0 SetColorMode 1 + #Glyph0 ScalingOn + Glyph0 SetScaleMode 2 + Glyph0 SetScaleFactor .25 + Glyph0 SetSource [Sphere0 GetOutput] + +vtkPolyDataMapper Mapper5 + Mapper5 SetInputConnection [Glyph0 GetOutputPort] + Mapper5 SetImmediateModeRendering 1 + Mapper5 UseLookupTableScalarRangeOff + Mapper5 SetScalarVisibility 1 + Mapper5 SetScalarModeToDefault +vtkLODActor Actor5 + Actor5 SetMapper Mapper5 + [Actor5 GetProperty] SetRepresentationToSurface + [Actor5 GetProperty] SetInterpolationToGouraud + [Actor5 GetProperty] SetAmbient 0.15 + [Actor5 GetProperty] SetDiffuse 0.85 + [Actor5 GetProperty] SetSpecular 0.1 + [Actor5 GetProperty] SetSpecularPower 100 + [Actor5 GetProperty] SetSpecularColor 1 1 1 + [Actor5 GetProperty] SetColor 1 1 1 + Actor5 SetNumberOfCloudPoints 30000 + +ren1 AddActor Actor5 + +vtkTubeFilter Tuber0 + Tuber0 SetInputConnection [pdb0 GetOutputPort] + Tuber0 SetNumberOfSides 8 + Tuber0 SetCapping 0 + Tuber0 SetRadius 0.2 + Tuber0 SetVaryRadius 0 + Tuber0 SetRadiusFactor 10 +vtkPolyDataMapper Mapper7 + Mapper7 SetInputConnection [Tuber0 GetOutputPort] + Mapper7 SetImmediateModeRendering 1 + Mapper7 UseLookupTableScalarRangeOff + Mapper7 SetScalarVisibility 1 + Mapper7 SetScalarModeToDefault +vtkLODActor Actor7 + Actor7 SetMapper Mapper7 + [Actor7 GetProperty] SetRepresentationToSurface + [Actor7 GetProperty] SetInterpolationToGouraud + [Actor7 GetProperty] SetAmbient 0.15 + [Actor7 GetProperty] SetDiffuse 0.85 + [Actor7 GetProperty] SetSpecular 0.1 + [Actor7 GetProperty] SetSpecularPower 100 + [Actor7 GetProperty] SetSpecularColor 1 1 1 + [Actor7 GetProperty] SetColor 1 1 1 + +ren1 AddActor Actor7 + +# enable user interface interactor +#iren SetUserMethod {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/IO/Testing/Tcl/caffeine.tcl b/IO/Testing/Tcl/caffeine.tcl new file mode 100644 index 0000000..7e16ea3 --- /dev/null +++ b/IO/Testing/Tcl/caffeine.tcl @@ -0,0 +1,87 @@ +package require vtk +package require vtkinteraction +vtkRenderer ren1 + ren1 SetBackground 0 0 0 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 300 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPDBReader pdb0 + pdb0 SetFileName "$VTK_DATA_ROOT/Data/caffeine.pdb" + + pdb0 SetHBScale 1.0 + pdb0 SetBScale 1.0 + +vtkSphereSource Sphere0 + Sphere0 SetCenter 0 0 0 + Sphere0 SetRadius 1 + Sphere0 SetThetaResolution 8 + Sphere0 SetStartTheta 0 + Sphere0 SetEndTheta 360 + Sphere0 SetPhiResolution 8 + Sphere0 SetStartPhi 0 + Sphere0 SetEndPhi 180 + +vtkGlyph3D Glyph0 + Glyph0 SetInputConnection [pdb0 GetOutputPort] + Glyph0 SetOrient 1 + Glyph0 SetColorMode 1 + #Glyph0 ScalingOn + Glyph0 SetScaleMode 2 + Glyph0 SetScaleFactor .25 + Glyph0 SetSource [Sphere0 GetOutput] + +vtkPolyDataMapper Mapper5 + Mapper5 SetInputConnection [Glyph0 GetOutputPort] + Mapper5 SetImmediateModeRendering 1 + Mapper5 UseLookupTableScalarRangeOff + Mapper5 SetScalarVisibility 1 + Mapper5 SetScalarModeToDefault +vtkLODActor Actor5 + Actor5 SetMapper Mapper5 + [Actor5 GetProperty] SetRepresentationToSurface + [Actor5 GetProperty] SetInterpolationToGouraud + [Actor5 GetProperty] SetAmbient 0.15 + [Actor5 GetProperty] SetDiffuse 0.85 + [Actor5 GetProperty] SetSpecular 0.1 + [Actor5 GetProperty] SetSpecularPower 100 + [Actor5 GetProperty] SetSpecularColor 1 1 1 + [Actor5 GetProperty] SetColor 1 1 1 + Actor5 SetNumberOfCloudPoints 30000 + +ren1 AddActor Actor5 + +vtkTubeFilter Tuber0 + Tuber0 SetInputConnection [pdb0 GetOutputPort] + Tuber0 SetNumberOfSides 8 + Tuber0 SetCapping 0 + Tuber0 SetRadius 0.2 + Tuber0 SetVaryRadius 0 + Tuber0 SetRadiusFactor 10 +vtkPolyDataMapper Mapper7 + Mapper7 SetInputConnection [Tuber0 GetOutputPort] + Mapper7 SetImmediateModeRendering 1 + Mapper7 UseLookupTableScalarRangeOff + Mapper7 SetScalarVisibility 1 + Mapper7 SetScalarModeToDefault +vtkLODActor Actor7 + Actor7 SetMapper Mapper7 + [Actor7 GetProperty] SetRepresentationToSurface + [Actor7 GetProperty] SetInterpolationToGouraud + [Actor7 GetProperty] SetAmbient 0.15 + [Actor7 GetProperty] SetDiffuse 0.85 + [Actor7 GetProperty] SetSpecular 0.1 + [Actor7 GetProperty] SetSpecularPower 100 + [Actor7 GetProperty] SetSpecularColor 1 1 1 + [Actor7 GetProperty] SetColor 1 1 1 + +ren1 AddActor Actor7 + +# enable user interface interactor +#iren SetUserMethod {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/IO/Testing/Tcl/dem.tcl b/IO/Testing/Tcl/dem.tcl new file mode 100644 index 0000000..558d886 --- /dev/null +++ b/IO/Testing/Tcl/dem.tcl @@ -0,0 +1,98 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +set Scale 5 +vtkLookupTable lut + lut SetHueRange 0.6 0 + lut SetSaturationRange 1.0 0 + lut SetValueRange 0.5 1.0 + +vtkDEMReader demModel + demModel SetFileName "$VTK_DATA_ROOT/Data/SainteHelens.dem" + demModel Update + +catch { demModel Print } + +set lo [expr $Scale * [lindex [demModel GetElevationBounds] 0]] +set hi [expr $Scale * [lindex [demModel GetElevationBounds] 1]] + +vtkLODActor demActor + +# create a pipeline for each lod mapper +set lods "4 8 16" +foreach lod $lods { + vtkImageShrink3D shrink$lod + shrink$lod SetShrinkFactors [expr int($lod)] [expr int($lod)] 1 + shrink$lod SetInputConnection [demModel GetOutputPort] + shrink$lod AveragingOn + + vtkImageDataGeometryFilter geom$lod + geom$lod SetInputConnection [shrink$lod GetOutputPort] + geom$lod ReleaseDataFlagOn + + vtkWarpScalar warp$lod + warp$lod SetInputConnection [geom$lod GetOutputPort] + warp$lod SetNormal 0 0 1 + warp$lod UseNormalOn + warp$lod SetScaleFactor $Scale + warp$lod ReleaseDataFlagOn + + vtkElevationFilter elevation$lod + elevation$lod SetInputConnection [warp$lod GetOutputPort] + elevation$lod SetLowPoint 0 0 $lo + elevation$lod SetHighPoint 0 0 $hi +eval elevation$lod SetScalarRange $lo $hi + elevation$lod ReleaseDataFlagOn + + vtkCastToConcrete toPoly$lod + toPoly$lod SetInputConnection [elevation$lod GetOutputPort] + + vtkPolyDataNormals normals$lod + normals$lod SetInput [toPoly$lod GetPolyDataOutput] + normals$lod SetFeatureAngle 60 + normals$lod ConsistencyOff + normals$lod SplittingOff + normals$lod ReleaseDataFlagOn + + vtkPolyDataMapper demMapper$lod + demMapper$lod SetInputConnection [normals$lod GetOutputPort] +eval demMapper$lod SetScalarRange $lo $hi + demMapper$lod SetLookupTable lut + demMapper$lod ImmediateModeRenderingOn + +demMapper$lod Update + +demActor AddLODMapper demMapper$lod +} + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor demActor +ren1 SetBackground .4 .4 .4 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren SetDesiredUpdateRate 1 + +wm withdraw . +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" {TkCheckAbort} + +[ren1 GetActiveCamera] SetViewUp 0 0 1 +[ren1 GetActiveCamera] SetPosition -99900 -21354 131801 +[ren1 GetActiveCamera] SetFocalPoint 41461 41461 2815 +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +renWin Render diff --git a/IO/vtkAVIWriter.cxx b/IO/vtkAVIWriter.cxx new file mode 100644 index 0000000..963b5e2 --- /dev/null +++ b/IO/vtkAVIWriter.cxx @@ -0,0 +1,253 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAVIWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWindows.h" +#include "vtkAVIWriter.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" + +#ifdef _MSC_VER +#pragma warning (push, 3) +#endif + +#include + +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +class vtkAVIWriterInternal +{ +public: + PAVISTREAM Stream; + PAVISTREAM StreamCompressed; + PAVIFILE AVIFile; + LPBITMAPINFOHEADER lpbi; // pointer to BITMAPINFOHEADER + HANDLE hDIB; // handle to DIB, temp handle +}; + +//--------------------------------------------------------------------------- +vtkStandardNewMacro(vtkAVIWriter); +vtkCxxRevisionMacro(vtkAVIWriter, "$Revision: 1.3 $"); + +//--------------------------------------------------------------------------- +vtkAVIWriter::vtkAVIWriter() +{ + this->Internals = new vtkAVIWriterInternal; + this->Internals->Stream = NULL; + this->Internals->StreamCompressed = NULL; + this->Internals->AVIFile = NULL; + this->Time = 0; + this->Rate = 15; + this->Internals->hDIB = NULL; // handle to DIB, temp handle +} + +//--------------------------------------------------------------------------- +vtkAVIWriter::~vtkAVIWriter() +{ + if (this->Internals->AVIFile) + { + this->End(); + } + delete this->Internals; +} + +//--------------------------------------------------------------------------- +void vtkAVIWriter::Start() +{ + // Error checking + this->Error = 1; + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<<"Write:Please specify an input!"); + return; + } + if (!this->FileName) + { + vtkErrorMacro(<<"Write:Please specify a FileName"); + return; + } + + // Fill in image information. + this->GetInput()->UpdateInformation(); + int *wExtent = this->GetInput()->GetWholeExtent(); + this->GetInput()->SetUpdateExtent(wExtent); + + LONG hr; + AVISTREAMINFO strhdr; + + AVIFileInit(); + // opens AVIFile library + hr = AVIFileOpen(&this->Internals->AVIFile, this->FileName, + OF_WRITE | OF_CREATE, 0L); + if (hr != 0) + { + vtkErrorMacro("Unable to open " << this->FileName); + return; + } + + // Fill in the header for the video stream.... + // The video stream will run in 15ths of a second.... + memset(&strhdr, 0, sizeof(strhdr)); + strhdr.fccType = streamtypeVIDEO;// stream type + strhdr.fccHandler = 0; + strhdr.dwScale = 1; + strhdr.dwRate = this->Rate; + strhdr.dwQuality = (DWORD) -1; + strhdr.dwSuggestedBufferSize = (wExtent[1] - wExtent[0] + 1)* + (wExtent[3] - wExtent[2] + 1)*3; + SetRect(&strhdr.rcFrame, 0, 0, wExtent[1] - wExtent[0] + 1, + wExtent[3] - wExtent[2] + 1); + + // And create the stream; + AVIFileCreateStream(this->Internals->AVIFile, // file pointer + &this->Internals->Stream, // returned stream pointer + &strhdr); // stream header + + // do not want to display this dialog + AVICOMPRESSOPTIONS opts; +// AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts}; + memset(&opts, 0, sizeof(opts)); + + // need to setup opts + opts.fccType = 0; + opts.fccHandler=mmioFOURCC('m','s','v','c'); + opts.dwQuality = 10000; + opts.dwBytesPerSecond = 0; + opts.dwFlags = 8; + +// if (!AVISaveOptions(NULL, 0, +// 1, &this->Internals->Stream, +// (LPAVICOMPRESSOPTIONS FAR *) &aopts)) +// { +// vtkErrorMacro("Unable to save " << this->FileName); +// return; +// } + + + if (AVIMakeCompressedStream(&this->Internals->StreamCompressed, + this->Internals->Stream, + &opts, NULL) != AVIERR_OK) + { + vtkErrorMacro("Unable to compress " << this->FileName); + return; + } + + DWORD dwLen; // size of memory block + int dataWidth = (((wExtent[1] - wExtent[0] + 1)*3+3)/4)*4; + + dwLen = sizeof(BITMAPINFOHEADER) + dataWidth*(wExtent[3] - wExtent[2] + 1); + this->Internals->hDIB = ::GlobalAlloc(GHND, dwLen); + this->Internals->lpbi = (LPBITMAPINFOHEADER) ::GlobalLock(this->Internals->hDIB); + + this->Internals->lpbi->biSize = sizeof(BITMAPINFOHEADER); + this->Internals->lpbi->biWidth = wExtent[1] - wExtent[0] + 1; + this->Internals->lpbi->biHeight = wExtent[3] - wExtent[2] + 1; + this->Internals->lpbi->biPlanes = 1; + this->Internals->lpbi->biBitCount = 24; + this->Internals->lpbi->biCompression = BI_RGB; + this->Internals->lpbi->biClrUsed = 0; + this->Internals->lpbi->biClrImportant = 0; + this->Internals->lpbi->biSizeImage = dataWidth*(wExtent[3] - wExtent[2] + 1); + + if (AVIStreamSetFormat(this->Internals->StreamCompressed, 0, + this->Internals->lpbi, this->Internals->lpbi->biSize)) + { + vtkErrorMacro("Unable to format " << this->FileName << " Most likely this means that the video compression scheme you seleted could not handle the data. Try selecting a different compression scheme." ); + return; + } + + this->Error = 0; + this->Time = 0; +} + +//--------------------------------------------------------------------------- +void vtkAVIWriter::Write() +{ + if (this->Error) + { + return; + } + + // get the data + this->GetInput()->UpdateInformation(); + int *wExtent = this->GetInput()->GetWholeExtent(); + this->GetInput()->SetUpdateExtent(wExtent); + this->GetInput()->Update(); + // get the pointer to the data + unsigned char *ptr = + (unsigned char *)(this->GetInput()->GetScalarPointer()); + + int dataWidth = (((wExtent[1] - wExtent[0] + 1)*3+3)/4)*4; + int srcWidth = (wExtent[1] - wExtent[0] + 1)*3; + + // copy the data to the clipboard + unsigned char *dest + = (unsigned char *)this->Internals->lpbi + this->Internals->lpbi->biSize; + int i,j; + for (i = 0; i < this->Internals->lpbi->biHeight; i++) + { + for (j = 0; j < this->Internals->lpbi->biWidth; j++) + { + *dest++ = ptr[2]; + *dest++ = ptr[1]; + *dest++ = *ptr; + ptr += 3; + } + dest = dest + (dataWidth - srcWidth); + } + + AVIStreamWrite(this->Internals->StreamCompressed, // stream pointer + this->Time, // time of this frame + 1, // number to write + (LPBYTE) this->Internals->lpbi + // pointer to data + this->Internals->lpbi->biSize, + this->Internals->lpbi->biSizeImage, // size of this frame + AVIIF_KEYFRAME, // flags.... + NULL, NULL); + this->Time++; +} + +//--------------------------------------------------------------------------- +void vtkAVIWriter::End() +{ + ::GlobalUnlock(this->Internals->hDIB); + if (this->Internals->Stream) + { + AVIStreamClose(this->Internals->Stream); + this->Internals->Stream = NULL; + } + + if (this->Internals->StreamCompressed) + { + AVIStreamClose(this->Internals->StreamCompressed); + this->Internals->StreamCompressed = NULL; + } + + if (this->Internals->AVIFile) + { + AVIFileClose(this->Internals->AVIFile); + this->Internals->AVIFile = NULL; + } + + AVIFileExit(); // releases AVIFile library +} + +//--------------------------------------------------------------------------- +void vtkAVIWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + diff --git a/IO/vtkAVIWriter.h b/IO/vtkAVIWriter.h new file mode 100644 index 0000000..030a689 --- /dev/null +++ b/IO/vtkAVIWriter.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAVIWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAVIWriter - Writes Windows AVI files. +// .SECTION Description +// vtkAVIWriter writes AVI files. The data type +// of the file is unsigned char regardless of the input type. +// .SECTION See Also +// vtkGenericMovieWriter vtkMPEG2Writer + +#ifndef __vtkAVIWriter_h +#define __vtkAVIWriter_h + +#include "vtkGenericMovieWriter.h" + +class vtkAVIWriterInternal; + +class VTK_IO_EXPORT vtkAVIWriter : public vtkGenericMovieWriter +{ +public: + static vtkAVIWriter *New(); + vtkTypeRevisionMacro(vtkAVIWriter,vtkGenericMovieWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // These methods start writing an AVI file, write a frame to the file + // and then end the writing process. + void Start(); + void Write(); + void End(); + +protected: + vtkAVIWriter(); + ~vtkAVIWriter(); + + vtkAVIWriterInternal *Internals; + + int Rate; + int Time; + +private: + vtkAVIWriter(const vtkAVIWriter&); // Not implemented + void operator=(const vtkAVIWriter&); // Not implemented +}; + +#endif + + + diff --git a/IO/vtkAVSucdReader.cxx b/IO/vtkAVSucdReader.cxx new file mode 100644 index 0000000..08c1d84 --- /dev/null +++ b/IO/vtkAVSucdReader.cxx @@ -0,0 +1,1221 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAVSucdReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Thanks to Guenole Harel and Emmanuel Colin (Supelec engineering school, +// France) and Jean M. Favre (CSCS, Switzerland) who co-developed this class. +// Thanks to Isabelle Surin (isabelle.surin at cea.fr, CEA-DAM, France) who +// supervised the internship of the first two authors. Thanks to Daniel +// Aguilera (daniel.aguilera at cea.fr, CEA-DAM, France) who contributed code +// und advice. Please address all comments to Jean Favre (jfavre at cscs.ch) + +#include "vtkAVSucdReader.h" +#include "vtkDataArraySelection.h" +#include "vtkErrorCode.h" +#include "vtkUnstructuredGrid.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkFieldData.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkByteSwap.h" +#include "vtkIdTypeArray.h" +#include "vtkFloatArray.h" +#include "vtkIntArray.h" +#include "vtkByteSwap.h" +#include "vtkCellArray.h" + +vtkCxxRevisionMacro(vtkAVSucdReader, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkAVSucdReader); + +//---------------------------------------------------------------------------- +vtkAVSucdReader::vtkAVSucdReader() +{ + this->FileName = NULL; + this->ByteOrder = FILE_BIG_ENDIAN; + this->BinaryFile = 0; + this->NumberOfNodeFields = 0; + this->NumberOfCellFields = 0; + this->NumberOfFields = 0; + this->NumberOfNodeComponents = 0; + this->NumberOfCellComponents = 0; + this->FileStream = NULL; + this->DecrementNodeIds = 0; + this->NumberOfNodes = 0; + this->NumberOfCells = 0; + + this->NodeDataInfo = NULL; + this->CellDataInfo = NULL; + this->PointDataArraySelection = vtkDataArraySelection::New(); + this->CellDataArraySelection = vtkDataArraySelection::New(); + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkAVSucdReader::~vtkAVSucdReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } + if (this->NodeDataInfo) + { + delete [] this->NodeDataInfo; + } + if (this->CellDataInfo) + { + delete [] this->CellDataInfo; + } + + this->CellDataArraySelection->Delete(); + this->PointDataArraySelection->Delete(); +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::SetByteOrderToBigEndian() +{ + this->ByteOrder = FILE_BIG_ENDIAN; +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::SetByteOrderToLittleEndian() +{ + this->ByteOrder = FILE_LITTLE_ENDIAN; +} + +//---------------------------------------------------------------------------- +const char *vtkAVSucdReader::GetByteOrderAsString() +{ + if ( this->ByteOrder == FILE_LITTLE_ENDIAN) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +} + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro( << "Reading AVS UCD file"); + + // If ExecuteInformation() failed FileStream will be NULL and + // ExecuteInformation() will have spit out an error. + if ( this->FileStream ) + { + this->ReadFile(output); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + os << indent << "Number Of Nodes: " << this->NumberOfNodes << endl; + os << indent << "Number Of Node Fields: " + << this->NumberOfNodeFields << endl; + os << indent << "Number Of Node Components: " + << this->NumberOfNodeComponents << endl; + + os << indent << "Number Of Cells: " << this->NumberOfCells << endl; + os << indent << "Number Of Cell Fields: " + << this->NumberOfCellFields << endl; + os << indent << "Number Of Cell Components: " + << this->NumberOfCellComponents << endl; + + os << indent << "Byte Order: " << this->ByteOrder << endl; + os << indent << "Binary File: " << (this->BinaryFile ? "True\n" : "False\n"); + os << indent << "Number of Fields: " << this->NumberOfFields << endl; +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::ReadFile(vtkUnstructuredGrid *output) +{ + this->ReadGeometry(output); + + if(this->NumberOfNodeFields) + { + this->ReadNodeData(output); + } + + if(this->NumberOfCellFields) + { + this->ReadCellData(output); + } + + delete this->FileStream; + this->FileStream = NULL; +} + + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + char magic_number='\0'; + long trueFileLength, calculatedFileLength; + int i, j, k, *ncomp_list; + + // first open file in binary mode to check the first byte. + if ( !this->FileName ) + { + vtkErrorMacro("No filename specified"); + return 0; + } + +#ifdef _WIN32 + this->FileStream = new ifstream(this->FileName, ios::in | ios::binary); +#else + this->FileStream = new ifstream(this->FileName, ios::in); +#endif + if (this->FileStream->fail()) + { + this->SetErrorCode(vtkErrorCode::FileNotFoundError); + delete this->FileStream; + this->FileStream = NULL; + vtkErrorMacro("Specified filename not found"); + return 0; + } + + this->FileStream->get(magic_number); + this->FileStream->putback(magic_number); + if(magic_number != 7) + { // most likely an ASCII file + this->BinaryFile = 0; + delete this->FileStream; // close file to reopen it later + this->FileStream = NULL; + + this->FileStream = new ifstream(this->FileName, ios::in); + char c='\0', buf[100]; + while(this->FileStream->get(c) && c == '#') + { + this->FileStream->get(buf, 100, '\n'); this->FileStream->get(c); + } + this->FileStream->putback(c); + + *(this->FileStream) >> this->NumberOfNodes; + *(this->FileStream) >> this->NumberOfCells; + *(this->FileStream) >> this->NumberOfNodeFields; + *(this->FileStream) >> this->NumberOfCellFields; + *(this->FileStream) >> this->NumberOfFields; + } + else + { + this->BinaryFile = 1; + + // Here we first need to check if the file is little-endian or big-endian + // We will read the variable once, with the given endian-ness set up in + // the class constructor. If trueFileLength does not match + // calculatedFileLength, then we will toggle the endian-ness and re-swap + // the variables + this->FileStream->seekg(0L, ios::end); + trueFileLength = this->FileStream->tellg(); + calculatedFileLength = 0; // unknown yet + + while(abs(static_cast(trueFileLength - calculatedFileLength))/ + trueFileLength > 0.01) + { + if(trueFileLength != calculatedFileLength) + { + // switch to opposite of what previously set in constructor + if(this->ByteOrder == FILE_LITTLE_ENDIAN) + { + this->ByteOrder = FILE_BIG_ENDIAN; + } + else if(this->ByteOrder == FILE_BIG_ENDIAN) + { + this->ByteOrder = FILE_LITTLE_ENDIAN; + } + } + // restart at beginning of file + this->FileStream->seekg(0L, ios::beg); + + this->FileStream->read(&magic_number, 1); + + this->ReadIntBlock(1, &this->NumberOfNodes); + this->ReadIntBlock(1, &this->NumberOfCells); + this->ReadIntBlock(1, &this->NumberOfNodeFields); + this->ReadIntBlock(1, &this->NumberOfCellFields); + this->ReadIntBlock(1, &this->NumberOfFields); + this->ReadIntBlock(1, &this->NlistNodes); + + vtkDebugMacro( << this->NumberOfNodes << " " + << this->NumberOfCells << " " + << this->NumberOfNodeFields << " " + << this->NumberOfCellFields << " " + << this->NumberOfFields << " " + << this->NlistNodes << endl); + + calculatedFileLength = 1 + 6*4; + calculatedFileLength += 16 * this->NumberOfCells + 4 * this->NlistNodes; + calculatedFileLength += 3*4 * this->NumberOfNodes; + if(this->NumberOfNodeFields) + { + calculatedFileLength += 2052 + + this->NumberOfNodeFields*(12 + 4 * this->NumberOfNodes + 4); + } + + if(this->NumberOfCellFields) + { + calculatedFileLength += 2052 + + this->NumberOfCellFields*(12 + 4 * this->NumberOfCells + 4); + } + + if(this->NumberOfFields) + { + calculatedFileLength += 2052 + this->NumberOfFields*(4 * 5); + } + + vtkDebugMacro( << "TFL = " << trueFileLength + << "\tCFL = " << calculatedFileLength << endl); + + //trueFileLength = calculatedFileLength; + } // end of while loop + + const long base_offset = 1 + 6*4; + char buffer1[1024], buffer2[1024], label[32]; + + long offset = base_offset + 16 * this->NumberOfCells + + 4 * this->NlistNodes + 3 * 4 * this->NumberOfNodes; + + if(this->NumberOfNodeFields) + { + this->FileStream->seekg(offset,ios::beg); + this->FileStream->read(buffer1, sizeof(buffer1)); + this->FileStream->read(buffer2, sizeof(buffer2)); // read 2nd array of 1024 bytes + this->ReadIntBlock(1, &this->NumberOfNodeComponents); + + ncomp_list = new int[this->NumberOfNodeFields]; + this->ReadIntBlock(this->NumberOfNodeFields, ncomp_list); + + this->NodeDataInfo = new DataInfo[this->NumberOfNodeComponents]; + + float *mx = new float[this->NumberOfNodeFields]; + // read now the minimums for node_data + this->ReadFloatBlock(this->NumberOfNodeFields, mx); + k=0; + for(i=0; i < this->NumberOfNodeComponents; i++) + { + for(j=0; j < ncomp_list[i]; j++) + { + this->NodeDataInfo[i].min[j] = mx[k]; + } + k++; + } + // read now the maximums for node_data + this->ReadFloatBlock(this->NumberOfNodeFields, mx); + k=0; + for(i=0; i < this->NumberOfNodeComponents; i++) + { + for(j=0; j < ncomp_list[i]; j++) + { + this->NodeDataInfo[i].max[j] = mx[k]; + } + k++; + } + delete [] mx; + + offset += 1024 + 1024 + 4 + 3 * 4 * this->NumberOfNodeFields; + + k = 0; + for(i=0; i < this->NumberOfNodeComponents; i++) + { + this->GetLabel(buffer1, i, label); + vtkDebugMacro( << i+1 << " :found ND label = " << label + << " [" << ncomp_list[i] << "]" <PointDataArraySelection->AddArray(label); + this->NodeDataInfo[i].foffset = offset + k * 4 * this->NumberOfNodes; + this->NodeDataInfo[i].veclen = ncomp_list[i]; + k += ncomp_list[i]; + } + delete [] ncomp_list; + } + + if(this->NumberOfCellFields) + { + offset += 4 * this->NumberOfNodes * this->NumberOfNodeFields + + 4 * this->NumberOfNodeFields; + this->FileStream->seekg(offset,ios::beg); + this->FileStream->read(buffer1, sizeof(buffer1)); + + this->FileStream->read(buffer2, sizeof(buffer2)); // read 2nd array of 1024 bytes + this->ReadIntBlock(1, &this->NumberOfCellComponents); + + ncomp_list = new int[this->NumberOfCellFields]; + this->ReadIntBlock(this->NumberOfCellFields, ncomp_list); + + this->CellDataInfo = new DataInfo[this->NumberOfCellComponents]; + + float *mx = new float[this->NumberOfCellFields]; + // read now the minimums for cell_data + this->ReadFloatBlock(this->NumberOfCellFields, mx); + k=0; + for(i=0; i < this->NumberOfCellFields; i++) + { + for(j=0; j < ncomp_list[i]; j++) + { + this->CellDataInfo[i].min[j] = mx[k]; + }; + k++; + } + // read now the maximums for cell_data + this->ReadFloatBlock(this->NumberOfCellFields, mx); + k=0; + for(i=0; i < this->NumberOfCellFields; i++) + { + for(j=0; j < ncomp_list[i]; j++) + { + this->CellDataInfo[i].max[j] = mx[k]; + } + k++; + } + delete [] mx; + + offset += 1024 + 1024 + 4 + 3 * 4 * this->NumberOfCellFields; + + k = 0; + for(i=0; i < this->NumberOfCellComponents; i++) + { + this->GetLabel(buffer1, i, label); + vtkDebugMacro( << i+1 << " :found CD label = " << label << " [" + << ncomp_list[i] << "]" << endl); + this->CellDataArraySelection->AddArray(label); + this->CellDataInfo[i].foffset = offset + k * 4 * this->NumberOfCells; + this->CellDataInfo[i].veclen = ncomp_list[i]; + k += ncomp_list[i]; + } + delete [] ncomp_list; + } + + if(this->NumberOfFields) + { + offset += 4 * this->NumberOfCells * this->NumberOfCellFields + + 4 * this->NumberOfCellFields; + this->FileStream->seekg(offset,ios::beg); + this->FileStream->read(buffer1, sizeof(buffer1)); + vtkDebugMacro(<< buffer1 << endl); + + //offset += 1024 + 1024 + 4 + 3 * 4 * this->NumberOfFields; + + for(i=0; i < this->NumberOfFields; i++) + { + this->GetLabel(buffer1, i, label); + vtkDebugMacro( << "found MD label = " << label << endl); + } + } + } // end of Binary part + for(i=0; i < this->NumberOfNodeComponents; i++) + { + vtkDebugMacro( << endl << this->PointDataArraySelection->GetArrayName(i) + << endl + << "offset = " << this->NodeDataInfo[i].foffset << endl + << "load = " << this->PointDataArraySelection->GetArraySetting(i) << endl + << "veclen = " << this->NodeDataInfo[i].veclen); + } + + for(i=0; i < this->NumberOfCellComponents; i++) + { + vtkDebugMacro( << endl << this->CellDataArraySelection->GetArrayName(i) + << endl + << "offset = " << this->CellDataInfo[i].foffset << endl + << "load = " << this->CellDataArraySelection->GetArraySetting(i) << endl + << "veclen = " << this->CellDataInfo[i].veclen); + } + + vtkDebugMacro( << "end of ExecuteInformation\n"); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::GetCellDataRange(int cellComp, int index, float *min, float *max) +{ + if (index >= this->CellDataInfo[cellComp].veclen || index < 0) + { + index = 0; // if wrong index, set it to zero + } + *min = this->CellDataInfo[cellComp].min[index]; + *max = this->CellDataInfo[cellComp].max[index]; +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::GetNodeDataRange(int nodeComp, int index, float *min, float *max) +{ + if (index >= this->NodeDataInfo[nodeComp].veclen || index < 0) + { + index = 0; // if wrong index, set it to zero + } + *min = this->NodeDataInfo[nodeComp].min[index]; + *max = this->NodeDataInfo[nodeComp].max[index]; +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::ReadGeometry(vtkUnstructuredGrid *output) +{ + // add a material array + vtkIntArray *materials = vtkIntArray::New(); + materials->SetNumberOfTuples(this->NumberOfCells); + materials->SetName("Material Id"); + + vtkFloatArray *coords = vtkFloatArray::New(); + coords->SetNumberOfComponents(3); + coords->SetNumberOfTuples(this->NumberOfNodes); + + if (this->BinaryFile) + { + int *types = new int[this->NumberOfCells]; + if(types == NULL) + { + vtkErrorMacro(<< "Error allocating types memory\n"); + } + + vtkIdTypeArray *listcells = vtkIdTypeArray::New(); + // this array contains a list of NumberOfCells tuples + // each tuple is 1 integer, i.e. the number of indices following it (N) + // followed by these N integers + listcells->SetNumberOfValues(this->NumberOfCells + this->NlistNodes); + + this->ReadBinaryCellTopology(materials, types, listcells); + this->ReadXYZCoords(coords); + + vtkCellArray *cells = vtkCellArray::New(); + cells->SetCells(this->NumberOfCells, listcells); + listcells->Delete(); + + output->SetCells(types, cells); + cells->Delete(); + delete [] types; + } + else + { + this->ReadXYZCoords(coords); + this->ReadASCIICellTopology(materials, output); + } + + vtkPoints *points = vtkPoints::New(); + points->SetData(coords); + coords->Delete(); + + output->SetPoints(points); + points->Delete(); + + // now add the material array + output->GetCellData()->AddArray(materials); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(materials); + } + materials->Delete(); +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::ReadBinaryCellTopology(vtkIntArray *materials, + int *types, + vtkIdTypeArray *listcells) +{ + int i, j, k2=0; + int *mat = materials->GetPointer(0); + vtkIdType *list = listcells->GetPointer(0); + int *ctype = new int[4 * this->NumberOfCells]; + if(ctype == NULL) + { + vtkErrorMacro(<< "Error allocating ctype memory"); + } + + this->FileStream->seekg(6*4 + 1,ios::beg); + this->ReadIntBlock(4 * this->NumberOfCells, ctype); + + int *topology_list = new int[this->NlistNodes]; + if(topology_list == NULL) + { + vtkErrorMacro(<< "Error allocating topology_list memory"); + } + + this->ReadIntBlock(this->NlistNodes, topology_list); + this->UpdateProgress(0.25); + + for(i=0; i < this->NumberOfCells; i++) + { + *list++ = ctype[4*i+2]; + if(ctype[4*i+3] == vtkAVSucdReader::PYR) + { //UCD ordering is 0,1,2,3,4 => VTK ordering is 1,2,3,4,0 + *list++ = topology_list[++k2] - 1; + *list++ = topology_list[++k2] - 1; + *list++ = topology_list[++k2] - 1; + *list++ = topology_list[++k2] - 1; + *list++ = topology_list[k2-4] - 1; + k2++; + } + else + { + for(j=0; j < ctype[4*i+2]; j++) + { + *list++ = topology_list[k2++] - 1; + } + } + } + + delete [] topology_list; + + for(i=0; i < this->NumberOfCells; i++) + { + *mat++ = ctype[4*i+1]; + switch(ctype[4*i+3]) + { + case vtkAVSucdReader::PT: types[i] = VTK_VERTEX; break; + case vtkAVSucdReader::LINE: types[i] = VTK_LINE; break; + case vtkAVSucdReader::TRI: types[i] = VTK_TRIANGLE; break; + case vtkAVSucdReader::QUAD: types[i] = VTK_QUAD; break; + case vtkAVSucdReader::TET: types[i] = VTK_TETRA; break; + case vtkAVSucdReader::PYR: types[i] = VTK_PYRAMID; break; + case vtkAVSucdReader::PRISM: types[i] = VTK_WEDGE; break; + case vtkAVSucdReader::HEX: types[i] = VTK_HEXAHEDRON; break; + default: + vtkErrorMacro( << "cell type: " << ctype[4*i+3] << "not supported\n"); + delete [] ctype; + return; + } + } + delete [] ctype; +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::ReadASCIICellTopology(vtkIntArray *materials, + vtkUnstructuredGrid *output) +{ + int i, k; + vtkIdType list[8]; + int *mat = materials->GetPointer(0); + char ctype[5]; + + output->Allocate(); + for(i=0; i < this->NumberOfCells; i++) + { + int id; // no check is done to see that they are monotonously increasing + *(this->FileStream) >> id; + *(this->FileStream) >> mat[i]; + *(this->FileStream) >> ctype; + vtkDebugMacro( << mat[i] << ", " << ctype ); + if(!strcmp(ctype, "pt")) + { + for(k=0; k < 1; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + output->InsertNextCell(VTK_VERTEX, 1, list); + } + else if(!strcmp(ctype, "line")) + { + for(k=0; k < 2; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + output->InsertNextCell(VTK_LINE, 2, list); + } + else if(!strcmp(ctype, "tri")) + { + for(k=0; k < 3; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + output->InsertNextCell(VTK_TRIANGLE, 3, list); + } + else if(!strcmp(ctype, "quad")) + { + for(k=0; k < 4; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + output->InsertNextCell(VTK_QUAD, 4, list); + } + else if(!strcmp(ctype, "tet")) + { + for(k=0; k < 4; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + output->InsertNextCell(VTK_TETRA, 4, list); + } + else if(!strcmp(ctype, "pyr")) + { + for(k=0; k < 5; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + int tmp; + tmp = list[0]; + list[0] = list[1]; list[1] = list[2]; list[2] = list[3]; + list[3] = list[4]; list[4] = tmp; + output->InsertNextCell(VTK_PYRAMID, 5, list); + } + else if(!strcmp(ctype, "prism")) + { + for(k=0; k < 6; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + output->InsertNextCell(VTK_WEDGE, 6, list); + } + else if(!strcmp(ctype, "hex")) + { + for(k=0; k < 8; k++) + { + *(this->FileStream) >> list[k]; + if(this->DecrementNodeIds) + { + list[k]--; + } + } + output->InsertNextCell(VTK_HEXAHEDRON, 8, list); + } + else + { + vtkErrorMacro( << "cell type: " << ctype << " is not supported\n"); + return; + } + } // for all cell, read the indices +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::ReadXYZCoords(vtkFloatArray *coords) +{ + int i; + float *ptr = coords->GetPointer(0); + if (this->BinaryFile) + { + float *cs = new float[this->NumberOfNodes]; + + // read X coordinates from file and stuff into coordinates array + this->ReadFloatBlock(this->NumberOfNodes, cs); + for(i=0; i < this->NumberOfNodes; i++) + { + ptr[3*i] = cs[i]; + } + + // read Y coordinates from file and stuff into coordinates array + this->ReadFloatBlock(this->NumberOfNodes, cs); + for(i=0; i < this->NumberOfNodes; i++) + { + ptr[3*i+1] = cs[i]; + } + + // read Z coordinates from file and stuff into coordinates array + this->ReadFloatBlock(this->NumberOfNodes, cs); + for(i=0; i < this->NumberOfNodes; i++) + { + ptr[3*i+2] = cs[i]; + } + // end of stuffing all coordinates + delete [] cs; + } // end of binary read + else + { + int id; // no check is done to see that they are monotonously increasing + // read here the first node and check if its id number is 0 + + *(this->FileStream) >> id; + i=0; + *(this->FileStream) >> ptr[3*i] >> ptr[3*i+1] >> ptr[3*i+2]; + if(id) + { + this->DecrementNodeIds = 1; + } + + for(i=1; i < this->NumberOfNodes; i++) + { + *(this->FileStream) >> id; + *(this->FileStream) >> ptr[3*i] >> ptr[3*i+1] >> ptr[3*i+2]; + } + } // end of ASCII read +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::ReadNodeData(vtkUnstructuredGrid *output) +{ + int i, j, n; + float *ptr; + vtkDebugMacro( << "Begin of ReadNodeData()\n"); + if(this->BinaryFile) + { + for (i=0; i < this->NumberOfNodeComponents; i++) + { + if(this->PointDataArraySelection->GetArraySetting(i)) + { + vtkFloatArray *scalars = vtkFloatArray::New(); + scalars->SetNumberOfComponents(this->NodeDataInfo[i].veclen); + scalars->SetNumberOfTuples(this->NumberOfNodes); + scalars->SetName(PointDataArraySelection->GetArrayName(i)); + this->FileStream->seekg(this->NodeDataInfo[i].foffset, ios::beg); + if(1) // this->NodeDataInfo[i].veclen == 1) + { + ptr = scalars->GetPointer(0); + this->ReadFloatBlock(this->NumberOfNodes * + this->NodeDataInfo[i].veclen, ptr); + } + else + { + ptr = new float[this->NodeDataInfo[i].veclen]; + for(n=0; n < this->NumberOfNodes; n++) + { + this->ReadFloatBlock(this->NodeDataInfo[i].veclen, ptr); + for(j=0; j < this->NodeDataInfo[i].veclen; j++) + { + scalars->SetComponent(n, j, ptr[j]); + } + } + delete [] ptr; + } + + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + scalars->Delete(); + } + } + // + // Don't know how to use the information below, so skip reading it + // int *node_active_list = new int[this->NumberOfNodeFields]; + // this->ReadIntArray(node_active_list, this->NumberOfNodeFields); + // delete [] node_active_list; + // + } // end of binary read + else + { + float value; + int id; + char buf1[128], c='\0', buf2[128]; + + *(this->FileStream) >> this->NumberOfNodeComponents; + this->NodeDataInfo = new DataInfo[this->NumberOfNodeComponents]; + for(i=0; i < this->NumberOfNodeComponents; i++) + { + *(this->FileStream) >> this->NodeDataInfo[i].veclen; + } + this->FileStream->get(c); // one more newline to catch + + vtkFloatArray **scalars = new + vtkFloatArray * [this->NumberOfNodeComponents]; + for(i=0; i < this->NumberOfNodeComponents; i++) + { + j=0; + while(this->FileStream->get(c) && c != ',') + { + buf1[j++] = c; + } + buf1[j] = '\0'; + // finish here to read the line + this->FileStream->get(buf2, 128, '\n'); this->FileStream->get(c); + + scalars[i] = vtkFloatArray::New(); + scalars[i]->SetNumberOfComponents(this->NodeDataInfo[i].veclen); + scalars[i]->SetNumberOfTuples(this->NumberOfNodes); + scalars[i]->SetName(buf1); + } + for(n=0; n < this->NumberOfNodes; n++) + { + *(this->FileStream) >> id; + for(i=0; i < this->NumberOfNodeComponents; i++) + { + for(j=0; j < this->NodeDataInfo[i].veclen; j++) + { + *(this->FileStream) >> value; + scalars[i]->SetComponent(n, j, value); + } + } + } + for(i=0; i < this->NumberOfNodeComponents; i++) + { + output->GetPointData()->AddArray(scalars[i]); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars[i]); + } + scalars[i]->Delete(); + } + delete[] scalars; + } // end of ASCII read + vtkDebugMacro( << "End of ReadNodeData()\n"); +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::ReadCellData(vtkUnstructuredGrid *output) +{ + int i, j, n; + float *ptr; + vtkDebugMacro( << "Begin of ReadCellData()\n"); + if(this->BinaryFile) + { + for (i=0; i < this->NumberOfCellComponents; i++) + { + if(this->CellDataArraySelection->GetArraySetting(i)) + { + vtkFloatArray *scalars = vtkFloatArray::New(); + scalars->SetNumberOfComponents(this->CellDataInfo[i].veclen); + scalars->SetNumberOfTuples(this->NumberOfCells); + scalars->SetName(CellDataArraySelection->GetArrayName(i)); + this->FileStream->seekg(this->CellDataInfo[i].foffset, ios::beg); + if(1) // this->CellDataInfo[i].veclen == 1) + { + ptr = scalars->GetPointer(0); + this->ReadFloatBlock(this->NumberOfCells * + this->CellDataInfo[i].veclen, ptr); + } + else + { + ptr = new float[this->NumberOfCells]; + for(j=0; j < this->CellDataInfo[i].veclen; j++) + { + this->FileStream->seekg(this->CellDataInfo[i].foffset + + j*this->NumberOfCells, + ios::beg); + this->ReadFloatBlock(this->NumberOfCells, ptr); + + for(n=0; n < this->NumberOfCells; n++) + { + scalars->SetComponent(n, j, ptr[n]); + } + } + delete [] ptr; + } + + output->GetCellData()->AddArray(scalars); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(scalars); + } + scalars->Delete(); + } + } + } // end of binary read + else + { + float value; + int id; + char buf1[128], c='\0', buf2[128]; + + *(this->FileStream) >> this->NumberOfCellComponents; + this->CellDataInfo = new DataInfo[this->NumberOfCellComponents]; + + for(i=0; i < this->NumberOfCellComponents; i++) + { + *(this->FileStream) >> this->CellDataInfo[i].veclen; + } + this->FileStream->get(c); // one more newline to catch + + vtkFloatArray **scalars = new + vtkFloatArray * [this->NumberOfCellComponents]; + for(i=0; i < this->NumberOfCellComponents; i++) + { + j=0; + while(this->FileStream->get(c) && c != ',') + { + buf1[j++] = c; + } + buf1[j] = '\0'; + // finish here to read the line + this->FileStream->get(buf2, 128, '\n'); this->FileStream->get(c); + + scalars[i] = vtkFloatArray::New(); + scalars[i]->SetNumberOfComponents(this->CellDataInfo[i].veclen); + scalars[i]->SetNumberOfTuples(this->NumberOfCells); + scalars[i]->SetName(buf1); + } + for(n=0; n < this->NumberOfCells; n++) + { + *(this->FileStream) >> id; + for(i=0; i < this->NumberOfCellComponents; i++) + { + for(j=0; j < this->CellDataInfo[i].veclen; j++) + { + *(this->FileStream) >> value; + scalars[i]->SetComponent(n, j, value); + } + } + } + for(i=0; i < this->NumberOfCellComponents; i++) + { + output->GetCellData()->AddArray(scalars[i]); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(scalars[i]); + } + scalars[i]->Delete(); + } + delete[] scalars; + } // end of ASCII read + vtkDebugMacro( << "End of ReadCellData()\n"); +} + +//---------------------------------------------------------------------------- +const char* vtkAVSucdReader::GetPointArrayName(int index) +{ + return this->PointDataArraySelection->GetArrayName(index); +} + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::GetPointArrayStatus(const char* name) +{ + return this->PointDataArraySelection->ArrayIsEnabled(name); +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::SetPointArrayStatus(const char* name, int status) +{ + if(status) + { + this->PointDataArraySelection->EnableArray(name); + } + else + { + this->PointDataArraySelection->DisableArray(name); + } +} + +//---------------------------------------------------------------------------- +const char* vtkAVSucdReader::GetCellArrayName(int index) +{ + return this->CellDataArraySelection->GetArrayName(index); +} + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::GetCellArrayStatus(const char* name) +{ + return this->CellDataArraySelection->ArrayIsEnabled(name); +} + + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::SetCellArrayStatus(const char* name, int status) +{ + if(status) + { + this->CellDataArraySelection->EnableArray(name); + } + else + { + this->CellDataArraySelection->DisableArray(name); + } +} + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::GetNumberOfCellArrays() +{ + return this->CellDataArraySelection->GetNumberOfArrays(); +} + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::GetNumberOfPointArrays() +{ + return this->PointDataArraySelection->GetNumberOfArrays(); +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::EnableAllPointArrays() +{ + this->PointDataArraySelection->EnableAllArrays(); +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::DisableAllPointArrays() +{ + this->PointDataArraySelection->DisableAllArrays(); +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::EnableAllCellArrays() +{ + this->CellDataArraySelection->EnableAllArrays(); +} + +//---------------------------------------------------------------------------- +void vtkAVSucdReader::DisableAllCellArrays() +{ + this->CellDataArraySelection->DisableAllArrays(); +} + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::GetLabel(char *string, int number, char *label) +{ + int i, j, k, len; + char current; + + + // check to make sure that structure is not NULL + if (string == NULL) + { + vtkErrorMacro( << "String is null"); + return 0; + } + + // search for the appropriate label + k = 0; + len = strlen (string); + for(i = 0; i <= number; i++) + { + current = string[k++]; + j = 0; + while (current != '.') + { + // build the label character by character + label[j++] = current; + current = string[k++]; + + // the last character was found + if (k > len) + { + // the nth label was not found, where n = number + if (i < number) + { + return 0; + } + current = '.'; + } + } // end while + label[j] = '\0'; + } + // a valid label was found + return 1; +} + + +//---------------------------------------------------------------------------- +// Read a block of ints (ascii or binary) and return number read. +int vtkAVSucdReader::ReadIntBlock(int n, int *block) +{ + if (this->BinaryFile) + { + this->FileStream->read((char *)block, n * sizeof(int)); + int retVal = this->FileStream->gcount() / sizeof(int); + + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + return retVal; + } + else + { + int count = 0; + for(int i=0; iFileStream) >> block[i]) + { + count++; + } + else + { + return 0; + } + } + return count; + } +} + +//---------------------------------------------------------------------------- +int vtkAVSucdReader::ReadFloatBlock(int n, float* block) +{ + if (this->BinaryFile) + { + this->FileStream->read((char *)block, n * sizeof(float)); + int retVal = this->FileStream->gcount() / sizeof(int); + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + return retVal; + } + else + { + int count = 0; + for(int i=0; iFileStream) >> block[i]) + { + count++; + } + else + { + return 0; + } + } + return count; + } +} diff --git a/IO/vtkAVSucdReader.h b/IO/vtkAVSucdReader.h new file mode 100644 index 0000000..3cd523b --- /dev/null +++ b/IO/vtkAVSucdReader.h @@ -0,0 +1,194 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAVSucdReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAVSucdReader - reads a dataset in AVS "UCD" format +// .SECTION Description +// vtkAVSucdReader creates an unstructured grid dataset. It reads binary or +// ASCII files stored in UCD format, with optional data stored at the nodes +// or at the cells of the model. A cell-based fielddata stores the material +// id. The class can automatically detect the endian-ness of the binary files. + +// .SECTION Thanks +// Thanks to Guenole Harel and Emmanuel Colin (Supelec engineering school, +// France) and Jean M. Favre (CSCS, Switzerland) who co-developed this class. +// Thanks to Isabelle Surin (isabelle.surin at cea.fr, CEA-DAM, France) who +// supervised the internship of the first two authors. Thanks to Daniel +// Aguilera (daniel.aguilera at cea.fr, CEA-DAM, France) who contributed code +// and advice. Please address all comments to Jean Favre (jfavre at cscs.ch) + +// .SECTION See Also +// vtkGAMBITReader + +#ifndef __vtkAVSucdReader_h +#define __vtkAVSucdReader_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkIntArray; +class vtkFloatArray; +class vtkIdTypeArray; +class vtkDataArraySelection; + +class VTK_IO_EXPORT vtkAVSucdReader : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkAVSucdReader *New(); + vtkTypeRevisionMacro(vtkAVSucdReader,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of AVS UCD datafile to read + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Is the file to be read written in binary format (as opposed to ascii). + vtkSetMacro(BinaryFile, int); + vtkGetMacro(BinaryFile, int); + vtkBooleanMacro(BinaryFile, int); + + // Description: + // Get the total number of cells. + vtkGetMacro(NumberOfCells,int); + + // Description: + // Get the total number of nodes. + vtkGetMacro(NumberOfNodes,int); + + // Description: + // Get the number of data fields at the nodes. + vtkGetMacro(NumberOfNodeFields,int); + + // Description: + // Get the number of data fields at the cell centers. + vtkGetMacro(NumberOfCellFields,int); + + // Description: + // Get the number of data fields for the model. Unused because VTK + // has no methods for it. + vtkGetMacro(NumberOfFields,int); + + // Description: + // Get the number of data components at the nodes and cells. + vtkGetMacro(NumberOfNodeComponents,int); + vtkGetMacro(NumberOfCellComponents,int); + + // Description: + // Set/Get the endian-ness of the binary file. + void SetByteOrderToBigEndian(); + void SetByteOrderToLittleEndian(); + const char *GetByteOrderAsString(); + + vtkSetMacro(ByteOrder, int); + vtkGetMacro(ByteOrder, int); + + // Description: + // The following methods allow selective reading of solutions fields. by + // default, ALL data fields are the nodes and cells are read, but this can + // be modified. + int GetNumberOfPointArrays(); + int GetNumberOfCellArrays(); + const char* GetPointArrayName(int index); + const char* GetCellArrayName(int index); + int GetPointArrayStatus(const char* name); + int GetCellArrayStatus(const char* name); + void SetPointArrayStatus(const char* name, int status); + void SetCellArrayStatus(const char* name, int status); + + void DisableAllCellArrays(); + void EnableAllCellArrays(); + void DisableAllPointArrays(); + void EnableAllPointArrays(); + + // get min and max value for the index-th value of a cell component + // index varies from 0 to (veclen - 1) + void GetCellDataRange(int cellComp, int index, float *min, float *max); + + // get min and max value for the index-th value of a node component + // index varies from 0 to (veclen - 1) + void GetNodeDataRange(int nodeComp, int index, float *min, float *max); + +protected: + vtkAVSucdReader(); + ~vtkAVSucdReader(); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char *FileName; + int BinaryFile; + + int NumberOfNodes; + int NumberOfCells; + int NumberOfNodeFields; + int NumberOfNodeComponents; + int NumberOfCellComponents; + int NumberOfCellFields; + int NumberOfFields; + int NlistNodes; + + ifstream *FileStream; + + vtkDataArraySelection* PointDataArraySelection; + vtkDataArraySelection* CellDataArraySelection; + + int DecrementNodeIds; + int ByteOrder; + int GetLabel(char *string, int number, char *label); + //BTX + enum + { + FILE_BIG_ENDIAN=0, + FILE_LITTLE_ENDIAN=1 + }; + enum UCDCell_type + { + PT = 0, + LINE = 1, + TRI = 2, + QUAD = 3, + TET = 4, + PYR = 5, + PRISM = 6, + HEX = 7 + }; + + struct DataInfo { + long foffset; // offset in binary file + int veclen; // number of components in the node or cell variable + float min[3]; // pre-calculated data minima (max size 3 for vectors) + float max[3]; // pre-calculated data maxima (max size 3 for vectors) + }; + //ETX + + DataInfo *NodeDataInfo; + DataInfo *CellDataInfo; + +private: + void ReadFile(vtkUnstructuredGrid *output); + void ReadGeometry(vtkUnstructuredGrid *output); + void ReadNodeData(vtkUnstructuredGrid *output); + void ReadCellData(vtkUnstructuredGrid *output); + + int ReadFloatBlock(int n, float *block); + int ReadIntBlock(int n, int *block); + void ReadXYZCoords(vtkFloatArray *coords); + void ReadBinaryCellTopology(vtkIntArray *material, int *types, + vtkIdTypeArray *listcells); + void ReadASCIICellTopology(vtkIntArray *material, vtkUnstructuredGrid *output); + + vtkAVSucdReader(const vtkAVSucdReader&); // Not implemented. + void operator=(const vtkAVSucdReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkBMPReader.cxx b/IO/vtkBMPReader.cxx new file mode 100644 index 0000000..c277048 --- /dev/null +++ b/IO/vtkBMPReader.cxx @@ -0,0 +1,636 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBMPReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBMPReader.h" + +#include "vtkByteSwap.h" +#include "vtkImageData.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkBMPReader, "$Revision: 1.53 $"); +vtkStandardNewMacro(vtkBMPReader); + +#ifdef read +#undef read +#endif + +#ifdef close +#undef close +#endif + +vtkBMPReader::vtkBMPReader() +{ + this->Colors = NULL; + this->SetDataByteOrderToLittleEndian(); + this->Depth = 0; + // we need to create it now in case its asked for later (pointer must be valid) + this->LookupTable = vtkLookupTable::New(); + this->Allow8BitBMP = 0; +} + +//---------------------------------------------------------------------------- +vtkBMPReader::~vtkBMPReader() +{ + // free any old memory + if (this->Colors) + { + delete [] this->Colors; + this->Colors = NULL; + } + if (this->LookupTable) + { + this->LookupTable->Delete(); + this->LookupTable = NULL; + } +} + +void vtkBMPReader::ExecuteInformation() +{ + int xsize, ysize; + FILE *fp; + long tmp; + short stmp; + long infoSize; + int iinfoSize; // in case we are on a 64bit machine + int itmp; // in case we are on a 64bit machine + + // free any old memory + if (this->Colors) + { + delete [] this->Colors; + this->Colors = NULL; + } + + // if the user has not set the extent, but has set the VOI + // set the zaxis extent to the VOI z axis + if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 && + (this->DataVOI[4] || this->DataVOI[5])) + { + this->DataExtent[4] = this->DataVOI[4]; + this->DataExtent[5] = this->DataVOI[5]; + } + + this->ComputeInternalFileName(this->DataExtent[4]); + if (this->InternalFileName == NULL || this->InternalFileName[0] == '\0') + { + return; + } + // get the magic number by reading in a file + fp = fopen(this->InternalFileName,"rb"); + if (!fp) + { + vtkErrorMacro("Unable to open file " << this->InternalFileName); + return; + } + + // compare magic number to determine file type + if ((fgetc(fp) != 'B')||(fgetc(fp) != 'M')) + { + vtkErrorMacro(<<"Unknown file type! " << this->InternalFileName + <<" is not a Windows BMP file!"); + fclose(fp); + return; + } + + // get the size of the file + int sizeLong = sizeof(long); + if (sizeLong == 4) + { + fread(&tmp,4,1,fp); + // skip 4 bytes + fread(&tmp,4,1,fp); + // read the offset + fread(&tmp,4,1,fp); + } + else + { + fread(&itmp,4,1,fp); + // skip 4 bytes + fread(&itmp,4,1,fp); + // read the offset + fread(&itmp,4,1,fp); + } + + // get size of header + if (sizeLong == 4) // if we are on a 32 bit machine + { + fread(&infoSize,sizeof(long),1,fp); + vtkByteSwap::Swap4LE(&infoSize); + + // error checking + if ((infoSize != 40)&&(infoSize != 12)) + { + vtkErrorMacro(<<"Unknown file type! " << this->InternalFileName + <<" is not a Windows BMP file!"); + fclose(fp); + return; + } + + // there are two different types of BMP files + if (infoSize == 40) + { + // now get the dimensions + fread(&xsize,sizeof(long),1,fp); + vtkByteSwap::Swap4LE(&xsize); + fread(&ysize,sizeof(long),1,fp); + vtkByteSwap::Swap4LE(&ysize); + } + else + { + fread(&stmp,sizeof(short),1,fp); + vtkByteSwap::Swap2LE(&stmp); + xsize = stmp; + fread(&stmp,sizeof(short),1,fp); + vtkByteSwap::Swap2LE(&stmp); + ysize = stmp; + } + } + else // else we are on a 64bit machine + { + fread(&iinfoSize,sizeof(int),1,fp); + vtkByteSwap::Swap4LE(&iinfoSize); + infoSize = iinfoSize; + + // error checking + if ((infoSize != 40)&&(infoSize != 12)) + { + vtkErrorMacro(<<"Unknown file type! " << this->InternalFileName + <<" is not a Windows BMP file!"); + fclose(fp); + return; + } + + // there are two different types of BMP files + if (infoSize == 40) + { + // now get the dimensions + fread(&xsize,sizeof(int),1,fp); + vtkByteSwap::Swap4LE(&xsize); + fread(&ysize,sizeof(int),1,fp); + vtkByteSwap::Swap4LE(&ysize); + } + else + { + fread(&stmp,sizeof(short),1,fp); + vtkByteSwap::Swap2LE(&stmp); + xsize = stmp; + fread(&stmp,sizeof(short),1,fp); + vtkByteSwap::Swap2LE(&stmp); + ysize = stmp; + } + } + + + // is corner in upper left or lower left + if (ysize < 0) + { + ysize = ysize*-1; + this->FileLowerLeft = 0; + } + else + { + this->FileLowerLeft = 1; + } + + // ignore planes + fread(&stmp,sizeof(short),1,fp); + // read depth + fread(&this->Depth,sizeof(short),1,fp); + vtkByteSwap::Swap2LE(&this->Depth); + if ((this->Depth != 8)&&(this->Depth != 24)) + { + vtkErrorMacro(<<"Only BMP depths of (8,24) are supported. Not " << this->Depth); + fclose(fp); + return; + } + + // skip over rest of info for long format + if (infoSize == 40) + { + fread(&tmp,4,1,fp); + fread(&tmp,4,1,fp); + fread(&tmp,4,1,fp); + fread(&tmp,4,1,fp); + fread(&tmp,4,1,fp); + fread(&tmp,4,1,fp); + } + + // read in color table if required + if (this->Depth < 24) + { + int numColors = 256; + this->Colors = new unsigned char [numColors*3]; + for (tmp = 0; tmp < numColors; tmp++) + { + this->Colors[tmp*3+2] = fgetc(fp); + this->Colors[tmp*3+1] = fgetc(fp); + this->Colors[tmp*3] = fgetc(fp); + if (infoSize == 40) + { + fgetc(fp); + } + } + if (this->Allow8BitBMP) + { + if (!this->LookupTable) + { + this->LookupTable = vtkLookupTable::New(); + } + this->LookupTable->SetNumberOfTableValues(numColors); + for (tmp=0; tmpLookupTable->SetTableValue(tmp, + (float)this->Colors[tmp*3+0]/255.0, + (float)this->Colors[tmp*3+1]/255.0, + (float)this->Colors[tmp*3+2]/255.0, + 1); + } + this->LookupTable->SetRange(0,255); + } + } + + if (fclose(fp)) + { + vtkWarningMacro("File close failed on " << this->InternalFileName); + } + + // if the user has set the VOI, just make sure its valid + if (this->DataVOI[0] || this->DataVOI[1] || + this->DataVOI[2] || this->DataVOI[3] || + this->DataVOI[4] || this->DataVOI[5]) + { + if ((this->DataVOI[0] < 0) || + (this->DataVOI[1] >= xsize) || + (this->DataVOI[2] < 0) || + (this->DataVOI[3] >= ysize)) + { + vtkWarningMacro("The requested VOI is larger than the file's (" << this->InternalFileName << ") extent "); + this->DataVOI[0] = 0; + this->DataVOI[1] = xsize - 1; + this->DataVOI[2] = 0; + this->DataVOI[3] = ysize - 1; + } + } + + this->DataExtent[0] = 0; + this->DataExtent[1] = xsize - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = ysize - 1; + + this->SetDataScalarTypeToUnsignedChar(); + if ((this->Depth == 8) && this->Allow8BitBMP) + { + this->SetNumberOfScalarComponents(1); + } + else + { + this->SetNumberOfScalarComponents(3); + } + this->vtkImageReader::ExecuteInformation(); +} + +//---------------------------------------------------------------------------- +// This function opens a file to determine the file size, and to +// automatically determine the header size. +void vtkBMPReader::ComputeDataIncrements() +{ + int idx; + vtkIdType fileDataLength; + + // Determine the expected length of the data ... + switch (this->DataScalarType) + { + case VTK_FLOAT: + fileDataLength = sizeof(float); + break; + case VTK_INT: + fileDataLength = sizeof(int); + break; + case VTK_SHORT: + fileDataLength = sizeof(short); + break; + case VTK_UNSIGNED_SHORT: + fileDataLength = sizeof(unsigned short); + break; + case VTK_UNSIGNED_CHAR: + fileDataLength = sizeof(unsigned char); + break; + default: + vtkErrorMacro(<< "Unknown DataScalarType"); + return; + } + + fileDataLength *= (this->Depth/8); + + // a row must end on a 4 byte boundary + // so update the Increments[1] + this->DataIncrements[0] = fileDataLength; + fileDataLength = fileDataLength * + (this->DataExtent[1] - this->DataExtent[0] + 1); + // move to 4 byte boundary + fileDataLength = fileDataLength + (4 - fileDataLength%4)%4; + + // compute the fileDataLength (in units of bytes) + for (idx = 1; idx < 3; ++idx) + { + this->DataIncrements[idx] = fileDataLength; + fileDataLength = fileDataLength * + (this->DataExtent[idx*2+1] - this->DataExtent[idx*2] + 1); + } +} + +//---------------------------------------------------------------------------- +// This function reads in one data of data. +// templated to handle different data types. +template +void vtkBMPReaderUpdate2(vtkBMPReader *self, vtkImageData *data, OT *outPtr) +{ + vtkIdType inIncr[3], outIncr[3]; + OT *outPtr0, *outPtr1, *outPtr2; + vtkIdType streamSkip0, streamSkip1; + vtkIdType streamRead; + int idx0, idx1, idx2, pixelRead; + unsigned char *buf; + int inExtent[6]; + int dataExtent[6]; + int pixelSkip; + unsigned char *inPtr; + unsigned char *Colors; + unsigned long count = 0; + unsigned long target; + int Keep8bit = 0; + + // Get the requested extents. + data->GetExtent(inExtent); + // Convert them into to the extent needed from the file. + self->ComputeInverseTransformedExtent(inExtent,dataExtent); + + // get and transform the increments + data->GetIncrements(inIncr); + self->ComputeInverseTransformedIncrements(inIncr,outIncr); + + // get the color lut + Colors = self->GetColors(); + + // are we converting to RGB or staying as 8bit + if ((self->GetDepth() == 8) && self->GetAllow8BitBMP()) + { + Keep8bit = 1; + } + + // compute outPtr2 + outPtr2 = outPtr; + if (outIncr[0] < 0) + { + outPtr2 = outPtr2 - outIncr[0]*(dataExtent[1] - dataExtent[0]); + } + if (outIncr[1] < 0) + { + outPtr2 = outPtr2 - outIncr[1]*(dataExtent[3] - dataExtent[2]); + } + if (outIncr[2] < 0) + { + outPtr2 = outPtr2 - outIncr[2]*(dataExtent[5] - dataExtent[4]); + } + + // length of a row, num pixels read at a time + pixelRead = dataExtent[1] - dataExtent[0] + 1; + streamRead = (vtkIdType) (pixelRead * self->GetDataIncrements()[0]); + streamSkip0 = (vtkIdType) (self->GetDataIncrements()[1] - streamRead); + streamSkip1 = (vtkIdType) (self->GetDataIncrements()[2] - + (dataExtent[3] - dataExtent[2] + 1)* self->GetDataIncrements()[1]); + pixelSkip = self->GetDepth()/8; + + // read from the bottom up + if (!self->GetFileLowerLeft()) + { + streamSkip0 = (vtkIdType) (-streamRead - self->GetDataIncrements()[1]); + } + + // create a buffer to hold a row of the data + buf = new unsigned char[streamRead]; + + target = (unsigned long)((dataExtent[5]-dataExtent[4]+1)* + (dataExtent[3]-dataExtent[2]+1)/50.0); + target++; + + // read the data row by row + if (self->GetFileDimensionality() == 3) + { + if (!self->OpenAndSeekFile(dataExtent,0)) + { + return; + } + } + for (idx2 = dataExtent[4]; idx2 <= dataExtent[5]; ++idx2) + { + if (self->GetFileDimensionality() == 2) + { + if (!self->OpenAndSeekFile(dataExtent,idx2)) + { + return; + } + } + outPtr1 = outPtr2; + for (idx1 = dataExtent[2]; + !self->AbortExecute && idx1 <= dataExtent[3]; ++idx1) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + outPtr0 = outPtr1; + + // read the row. + if ( ! self->GetFile()->read((char *)buf, streamRead)) + { + vtkGenericWarningMacro("File operation failed. row = " << idx1 + << ", Read = " << streamRead + << ", Skip0 = " << streamSkip0 + << ", Skip1 = " << streamSkip1 + << ", FilePos = " << static_cast(self->GetFile()->tellg()) + << ", FileName = " << self->GetInternalFileName() + ); + self->GetFile()->close(); + return; + } + + + // copy the bytes into the typed data + inPtr = buf; + for (idx0 = dataExtent[0]; idx0 <= dataExtent[1]; ++idx0) + { + // Copy pixel into the output. + if (self->GetDepth() == 8 && !Keep8bit) + { + outPtr0[0] = (OT)(Colors[inPtr[0]*3]); + outPtr0[1] = (OT)(Colors[inPtr[0]*3+1]); + outPtr0[2] = (OT)(Colors[inPtr[0]*3+2]); + } + else if (self->GetDepth() == 8 && Keep8bit) + { + outPtr0[0] = (OT)(inPtr[0]); + } + else + { + outPtr0[0] = (OT)(inPtr[2]); + outPtr0[1] = (OT)(inPtr[1]); + outPtr0[2] = (OT)(inPtr[0]); + } + // move to next pixel + inPtr += pixelSkip; + outPtr0 += outIncr[0]; + } + // move to the next row in the file and data + self->GetFile()->seekg(static_cast(self->GetFile()->tellg()) + streamSkip0, ios::beg); + outPtr1 += outIncr[1]; + } + // move to the next image in the file and data + self->GetFile()->seekg(static_cast(self->GetFile()->tellg()) + streamSkip1, ios::beg); + outPtr2 += outIncr[2]; + } + + self->GetFile()->close(); + + // delete the temporary buffer + delete [] buf; +} + + +//---------------------------------------------------------------------------- +// This function reads a data from a file. The datas extent/axes +// are assumed to be the same as the file extent/order. +void vtkBMPReader::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + if (this->UpdateExtentIsEmpty(output)) + { + return; + } + if (this->InternalFileName == NULL) + { + vtkErrorMacro(<< "Either a FileName or FilePrefix must be specified."); + return; + } + + data->GetPointData()->GetScalars()->SetName("BMPImage"); + + this->ComputeDataIncrements(); + + // Call the correct templated function for the output + void *outPtr; + + // Call the correct templated function for the input + outPtr = data->GetScalarPointer(); + switch (data->GetScalarType()) + { + vtkTemplateMacro( + vtkBMPReaderUpdate2(this, data, static_cast(outPtr)) + ); + default: + vtkErrorMacro(<< "Execute: Unknown data type"); + } +} + +void vtkBMPReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + // this->Colors is not printed + os << indent << "Depth: " << this->Depth << "\n"; + os << indent << "Allow8BitBMP: " << this->Allow8BitBMP << "\n"; + if (this->LookupTable) + { + os << indent << "LookupTable: " << this->LookupTable << "\n"; + } + else + { + os << indent << "LookupTable: NULL\n"; + } +} + +int vtkBMPReader::CanReadFile(const char* fname) +{ + // get the magic number by reading in a file + FILE* fp = fopen(fname,"rb"); + if (!fp) + { + return 0; + } + + // compare magic number to determine file type + if ((fgetc(fp) != 'B')||(fgetc(fp) != 'M')) + { + fclose(fp); + return 0; + } + + long tmp; + long infoSize; + int iinfoSize; // in case we are on a 64bit machine + int itmp; // in case we are on a 64bit machine + + // get the size of the file + int sizeLong = sizeof(long); + if (sizeLong == 4) + { + fread(&tmp,4,1,fp); + // skip 4 bytes + fread(&tmp,4,1,fp); + // read the offset + fread(&tmp,4,1,fp); + } + else + { + fread(&itmp,4,1,fp); + // skip 4 bytes + fread(&itmp,4,1,fp); + // read the offset + fread(&itmp,4,1,fp); + } + + // get size of header + int res = 3; + if (sizeLong == 4) // if we are on a 32 bit machine + { + fread(&infoSize,sizeof(long),1,fp); + vtkByteSwap::Swap4LE(&infoSize); + + // error checking + if ((infoSize != 40)&&(infoSize != 12)) + { + fclose(fp); + return 0; + } + } + else // else we are on a 64bit machine + { + fread(&iinfoSize,sizeof(int),1,fp); + vtkByteSwap::Swap4LE(&iinfoSize); + infoSize = iinfoSize; + + // error checking + if ((infoSize != 40)&&(infoSize != 12)) + { + fclose(fp); + res = 0; + } + } + fclose(fp); + return res; +} diff --git a/IO/vtkBMPReader.h b/IO/vtkBMPReader.h new file mode 100644 index 0000000..47fdb2d --- /dev/null +++ b/IO/vtkBMPReader.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBMPReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBMPReader - read Windows BMP files +// .SECTION Description +// vtkBMPReader is a source object that reads Windows BMP files. +// This includes indexed and 24bit bitmaps +// Usually, all BMPs are converted to 24bit RGB, but BMPs may be output +// as 8bit images with a LookupTable if the Allow8BitBMP flag is set. +// +// BMPReader creates structured point datasets. The dimension of the +// dataset depends upon the number of files read. Reading a single file +// results in a 2D image, while reading more than one file results in a +// 3D volume. +// +// To read a volume, files must be of the form "FileName." +// (e.g., foo.bmp.0, foo.bmp.1, ...). You must also specify the image +// range. This range specifies the beginning and ending files to read (range +// can be any pair of non-negative numbers). +// +// The default behavior is to read a single file. In this case, the form +// of the file is simply "FileName" (e.g., foo.bmp). + +// .SECTION See Also +// vtkBMPWriter + +#ifndef __vtkBMPReader_h +#define __vtkBMPReader_h + +#include "vtkImageReader.h" +class vtkLookupTable; + +class VTK_IO_EXPORT vtkBMPReader : public vtkImageReader +{ +public: + static vtkBMPReader *New(); + vtkTypeRevisionMacro(vtkBMPReader,vtkImageReader); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Returns the depth of the BMP, either 8 or 24. + vtkGetMacro(Depth,int); + + // Description: is the given file name a BMP file? + virtual int CanReadFile(const char* fname); + // Description: + // Get the file extensions for this format. + // Returns a string with a space separated list of extensions in + // the format .extension + virtual const char* GetFileExtensions() + { + return ".bmp"; + } + + // Description: + // Return a descriptive name for the file format that might be useful in a GUI. + virtual const char* GetDescriptiveName() + { + return "Windows BMP"; + } + + // Description: + // If this flag is set and the BMP reader encounters an 8bit file, + // the data will be kept as unsigned chars and a lookuptable will be + // exported + vtkSetMacro(Allow8BitBMP,int); + vtkGetMacro(Allow8BitBMP,int); + vtkBooleanMacro(Allow8BitBMP,int); + + vtkGetObjectMacro(LookupTable, vtkLookupTable); + +//BTX + // Description: + // Returns the color lut. + vtkGetMacro(Colors,unsigned char *); +//ETX + +protected: + vtkBMPReader(); + ~vtkBMPReader(); + + unsigned char *Colors; + short Depth; + int Allow8BitBMP; + vtkLookupTable *LookupTable; + + virtual void ComputeDataIncrements(); + virtual void ExecuteInformation(); + virtual void ExecuteData(vtkDataObject *out); +private: + vtkBMPReader(const vtkBMPReader&); // Not implemented. + void operator=(const vtkBMPReader&); // Not implemented. +}; +#endif + + diff --git a/IO/vtkBMPWriter.cxx b/IO/vtkBMPWriter.cxx new file mode 100644 index 0000000..7e3dfad --- /dev/null +++ b/IO/vtkBMPWriter.cxx @@ -0,0 +1,186 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBMPWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBMPWriter.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkBMPWriter, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkBMPWriter); + +vtkBMPWriter::vtkBMPWriter() +{ + this->FileLowerLeft = 1; +} + +void vtkBMPWriter::WriteFileHeader(ofstream *file, vtkImageData *cache) +{ + int min0, max0, min1, max1, min2, max2; + long temp; + int width, height, dataWidth; + int row; + + // Find the length of the rows to write. + cache->GetWholeExtent(min0, max0, min1, max1, min2, max2); + width = (max0 - min0 + 1); + height = (max1 - min1 + 1); + + dataWidth = ((width*3+3)/4)*4; + + // spit out the BMP header + file->put((char)66); + file->put((char)77); + temp = (long)(dataWidth*height) + 54L; + file->put((char)(temp%256)); + file->put((char)((temp%65536L)/256)); + file->put((char)(temp/65536L)); + for (row = 0; row < 5; row++) + { + file->put((char)0); + } + file->put((char)54); + file->put((char)0); + file->put((char)0); + file->put((char)0); + + // info header + file->put((char)40); + file->put((char)0); + file->put((char)0); + file->put((char)0); + + file->put((char)(width%256)); + file->put((char)(width/256)); + file->put((char)0); + file->put((char)0); + + file->put((char)(height%256)); + file->put((char)(height/256)); + file->put((char)0); + file->put((char)0); + + file->put((char)1); + file->put((char)0); + file->put((char)24); + for (row = 0; row < 25; row++) + { + file->put((char)0); + } +} + + +void vtkBMPWriter::WriteFile(ofstream *file, vtkImageData *data, + int extent[6]) +{ + int idx1, idx2; + int rowLength, rowAdder, i; // in bytes + unsigned char *ptr; + int bpp; + unsigned long count = 0; + unsigned long target; + float progress = this->Progress; + float area; + int *wExtent; + + bpp = data->GetNumberOfScalarComponents(); + + // Make sure we actually have data. + if ( !data->GetPointData()->GetScalars()) + { + vtkErrorMacro(<< "Could not get data from input."); + return; + } + + // take into consideration the scalar type + if (data->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro("BMPWriter only accepts unsigned char scalars!"); + return; + } + + // Row length of x axis + rowLength = extent[1] - extent[0] + 1; + rowAdder = (4 - ((extent[1]-extent[0] + 1)*3)%4)%4; + + wExtent = this->GetInput()->GetWholeExtent(); + area = ((extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)* + (extent[1] - extent[0] + 1)) / + ((wExtent[5] -wExtent[4] + 1)*(wExtent[3] -wExtent[2] + 1)* + (wExtent[1] -wExtent[0] + 1)); + + target = (unsigned long)((extent[5]-extent[4]+1)* + (extent[3]-extent[2]+1)/(50.0*area)); + target++; + + for (idx2 = extent[4]; idx2 <= extent[5]; ++idx2) + { + for (idx1 = extent[2]; idx1 <= extent[3]; idx1++) + { + if (!(count%target)) + { + this->UpdateProgress(progress + count/(50.0*target)); + } + count++; + ptr = (unsigned char *)data->GetScalarPointer(extent[0], idx1, idx2); + if (bpp == 1) + { + for (i = 0; i < rowLength; i++) + { + file->put(ptr[i]); + file->put(ptr[i]); + file->put(ptr[i]); + } + } + if (bpp == 2) + { + for (i = 0; i < rowLength; i++) + { + file->put(ptr[i*2]); + file->put(ptr[i*2]); + file->put(ptr[i*2]); + } + } + if (bpp == 3) + { + for (i = 0; i < rowLength; i++) + { + file->put(ptr[i*3 + 2]); + file->put(ptr[i*3 + 1]); + file->put(ptr[i*3]); + } + } + if (bpp == 4) + { + for (i = 0; i < rowLength; i++) + { + file->put(ptr[i*4 + 2]); + file->put(ptr[i*4 + 1]); + file->put(ptr[i*4]); + } + } + for (i = 0; i < rowAdder; i++) + { + file->put((char)0); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkBMPWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkBMPWriter.h b/IO/vtkBMPWriter.h new file mode 100644 index 0000000..185b4f9 --- /dev/null +++ b/IO/vtkBMPWriter.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBMPWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBMPWriter - Writes Windows BMP files. +// .SECTION Description +// vtkBMPWriter writes BMP files. The data type +// of the file is unsigned char regardless of the input type. + +// .SECTION See Also +// vtkBMPReader + +#ifndef __vtkBMPWriter_h +#define __vtkBMPWriter_h + +#include "vtkImageWriter.h" + +class VTK_IO_EXPORT vtkBMPWriter : public vtkImageWriter +{ +public: + static vtkBMPWriter *New(); + vtkTypeRevisionMacro(vtkBMPWriter,vtkImageWriter); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkBMPWriter(); + ~vtkBMPWriter() {}; + + virtual void WriteFile(ofstream *file, vtkImageData *data, int ext[6]); + virtual void WriteFileHeader(ofstream *, vtkImageData *); +private: + vtkBMPWriter(const vtkBMPWriter&); // Not implemented. + void operator=(const vtkBMPWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkBYUReader.cxx b/IO/vtkBYUReader.cxx new file mode 100644 index 0000000..3a3f6d7 --- /dev/null +++ b/IO/vtkBYUReader.cxx @@ -0,0 +1,362 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBYUReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBYUReader.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkBYUReader, "$Revision: 1.51 $"); +vtkStandardNewMacro(vtkBYUReader); + +vtkBYUReader::vtkBYUReader() +{ + this->GeometryFileName = NULL; + this->DisplacementFileName = NULL; + this->ScalarFileName = NULL; + this->TextureFileName = NULL; + + this->ReadDisplacement = 1; + this->ReadScalar = 1; + this->ReadTexture = 1; + + this->PartNumber = 0; + + this->SetNumberOfInputPorts(0); +} + +vtkBYUReader::~vtkBYUReader() +{ + if ( this->GeometryFileName ) + { + delete [] this->GeometryFileName; + } + if ( this->DisplacementFileName ) + { + delete [] this->DisplacementFileName; + } + if ( this->ScalarFileName ) + { + delete [] this->ScalarFileName; + } + if ( this->TextureFileName ) + { + delete [] this->TextureFileName; + } +} + +int vtkBYUReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + FILE *geomFp; + int numPts; + + if (this->GeometryFileName == NULL || this->GeometryFileName == '\0') + { + vtkErrorMacro(<< "No GeometryFileName specified!"); + return 0; + } + if ((geomFp = fopen(this->GeometryFileName, "r")) == NULL) + { + vtkErrorMacro(<< "Geometry file: " << this->GeometryFileName << " not found"); + return 0; + } + else + { + this->ReadGeometryFile(geomFp,numPts,outInfo); + fclose(geomFp); + } + + this->ReadDisplacementFile(numPts, outInfo); + this->ReadScalarFile(numPts, outInfo); + this->ReadTextureFile(numPts, outInfo); + this->UpdateProgress(1.0); + + return 1; +} + +void vtkBYUReader::ReadGeometryFile(FILE *geomFile, int &numPts, + vtkInformation *outInfo) +{ + int numParts, numPolys, numEdges; + int partStart, partEnd; + int i; + vtkPoints *newPts; + vtkCellArray *newPolys; + float x[3]; + vtkIdList *pts; + int polyId, pt; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + pts = vtkIdList::New(); + pts->Allocate(VTK_CELL_SIZE); + + // + // Read header (not using fixed format! - potential problem in some files.) + // + fscanf (geomFile, "%d %d %d %d", &numParts, &numPts, &numPolys, &numEdges); + + if ( this->PartNumber > numParts ) + { + vtkWarningMacro(<<"Specified part number > number of parts"); + this->PartNumber = 0; + } + + if ( this->PartNumber > 0 ) // read just part specified + { + vtkDebugMacro(<<"Reading part number: " << this->PartNumber); + for (i=0; i < (this->PartNumber-1); i++) + { + fscanf (geomFile, "%*d %*d"); + } + fscanf (geomFile, "%d %d", &partStart, &partEnd); + for (i=this->PartNumber; i < numParts; i++) + { + fscanf (geomFile, "%*d %*d"); + } + } + else // read all parts + { + vtkDebugMacro(<<"Reading all parts."); + for (i=0; i < numParts; i++) + { + fscanf (geomFile, "%*d %*d"); + } + partStart = 1; + partEnd = VTK_LARGE_INTEGER; + } + + if ( numParts < 1 || numPts < 1 || numPolys < 1 ) + { + vtkErrorMacro(<<"Bad MOVIE.BYU file"); + pts->Delete(); + return; + } + // + // Allocate data objects + // + newPts = vtkPoints::New(); + newPts->Allocate(numPts); + newPolys = vtkCellArray::New(); + newPolys->Allocate(numPolys+numEdges); + // + // Read data + // + // read point coordinates + for (i=0; iInsertPoint(i,x); + } + this->UpdateProgress(0.333); + + // read poly data. Have to fix 1-offset. Only reading part number specified. + for ( polyId=1; polyId <= numPolys; polyId++ ) + { + // read this polygon + for ( pts->Reset(); fscanf(geomFile, "%d", &pt) && pt > 0; ) + { + pts->InsertNextId(pt-1);//convert to vtk 0-offset + } + pts->InsertNextId(-(pt+1)); + + // Insert polygon (if in selected part) + if ( partStart <= polyId && polyId <= partEnd ) + { + newPolys->InsertNextCell(pts); + } + } + this->UpdateProgress(0.6667); + + vtkDebugMacro(<<"Reading:" << numPts << " points, " + << numPolys << " polygons."); + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + pts->Delete(); +} + +void vtkBYUReader::ReadDisplacementFile(int numPts, vtkInformation *outInfo) +{ + FILE *dispFp; + int i; + float v[3]; + vtkFloatArray *newVectors; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if ( this->ReadDisplacement && this->DisplacementFileName ) + { + if ( !(dispFp = fopen(this->DisplacementFileName, "r")) ) + { + vtkErrorMacro (<<"Couldn't open displacement file"); + return; + } + } + else + { + return; + } + // + // Allocate and read data + // + newVectors = vtkFloatArray::New(); + newVectors->SetNumberOfComponents(3); + newVectors->SetNumberOfTuples(numPts); + + for (i=0; iSetTuple(i,v); + } + + fclose(dispFp); + vtkDebugMacro(<<"Read " << numPts << " displacements"); + + output->GetPointData()->SetVectors(newVectors); + newVectors->Delete(); +} + +void vtkBYUReader::ReadScalarFile(int numPts, vtkInformation *outInfo) +{ + FILE *scalarFp; + int i; + float s; + vtkFloatArray *newScalars; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if ( this->ReadScalar && this->ScalarFileName ) + { + if ( !(scalarFp = fopen(this->ScalarFileName, "r")) ) + { + vtkErrorMacro (<<"Couldn't open scalar file"); + return; + } + } + else + { + return; + } + // + // Allocate and read data + // + newScalars = vtkFloatArray::New(); + newScalars->SetNumberOfTuples(numPts); + + for (i=0; iSetTuple(i,&s); + } + + fclose(scalarFp); + vtkDebugMacro(<<"Read " << numPts << " scalars"); + + output->GetPointData()->SetScalars(newScalars); + newScalars->Delete(); +} + +void vtkBYUReader::ReadTextureFile(int numPts, vtkInformation *outInfo) +{ + FILE *textureFp; + int i; + float t[2]; + vtkFloatArray *newTCoords; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if ( this->ReadTexture && this->TextureFileName ) + { + if ( !(textureFp = fopen(this->TextureFileName, "r")) ) + { + vtkErrorMacro (<<"Couldn't open texture file"); + return; + } + } + else + { + return; + } + // + // Allocate and read data + // + newTCoords = vtkFloatArray::New(); + newTCoords->SetNumberOfComponents(3); + newTCoords->SetNumberOfTuples(numPts); + + for (i=0; iSetTuple(i,t); + } + + fclose(textureFp); + vtkDebugMacro(<<"Read " << numPts << " texture coordinates"); + + output->GetPointData()->SetTCoords(newTCoords); + newTCoords->Delete(); +} + +//---------------------------------------------------------------------------- +// This source does not know how to generate pieces yet. +int vtkBYUReader::ComputeDivisionExtents(vtkDataObject *vtkNotUsed(output), + int idx, int numDivisions) +{ + if (idx == 0 && numDivisions == 1) + { + // I will give you the whole thing + return 1; + } + else + { + // I have nothing to give you for this piece. + return 0; + } +} + +void vtkBYUReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Geometry File Name: " + << (this->GeometryFileName ? this->GeometryFileName : "(none)") << "\n"; + os << indent << "Read Displacement: " << (this->ReadDisplacement ? "On\n" : "Off\n"); + os << indent << "Displacement File Name: " + << (this->DisplacementFileName ? this->DisplacementFileName : "(none)") << "\n"; + os << indent << "Part Number: " << this->PartNumber << "\n"; + os << indent << "Read Scalar: " << (this->ReadScalar ? "On\n" : "Off\n"); + os << indent << "Scalar File Name: " + << (this->ScalarFileName ? this->ScalarFileName : "(none)") << "\n"; + os << indent << "Read Texture: " << (this->ReadTexture ? "On\n" : "Off\n"); + os << indent << "Texture File Name: " + << (this->TextureFileName ? this->TextureFileName : "(none)") << "\n"; +} diff --git a/IO/vtkBYUReader.h b/IO/vtkBYUReader.h new file mode 100644 index 0000000..c746c25 --- /dev/null +++ b/IO/vtkBYUReader.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBYUReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBYUReader - read MOVIE.BYU polygon files +// .SECTION Description +// vtkBYUReader is a source object that reads MOVIE.BYU polygon files. +// These files consist of a geometry file (.g), a scalar file (.s), a +// displacement or vector file (.d), and a 2D texture coordinate file +// (.t). + +#ifndef __vtkBYUReader_h +#define __vtkBYUReader_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_IO_EXPORT vtkBYUReader : public vtkPolyDataAlgorithm +{ +public: + static vtkBYUReader *New(); + + vtkTypeRevisionMacro(vtkBYUReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify name of geometry FileName. + vtkSetStringMacro(GeometryFileName); + vtkGetStringMacro(GeometryFileName); + + // Description: + // Specify name of geometry FileName (alias). + virtual void SetFileName(const char* f) { this->SetGeometryFileName(f); } + virtual char* GetFileName() { return this->GetGeometryFileName(); } + + // Description: + // Specify name of displacement FileName. + vtkSetStringMacro(DisplacementFileName); + vtkGetStringMacro(DisplacementFileName); + + // Description: + // Specify name of scalar FileName. + vtkSetStringMacro(ScalarFileName); + vtkGetStringMacro(ScalarFileName); + + // Description: + // Specify name of texture coordinates FileName. + vtkSetStringMacro(TextureFileName); + vtkGetStringMacro(TextureFileName); + + // Description: + // Turn on/off the reading of the displacement file. + vtkSetMacro(ReadDisplacement,int); + vtkGetMacro(ReadDisplacement,int); + vtkBooleanMacro(ReadDisplacement,int); + + // Description: + // Turn on/off the reading of the scalar file. + vtkSetMacro(ReadScalar,int); + vtkGetMacro(ReadScalar,int); + vtkBooleanMacro(ReadScalar,int); + + // Description: + // Turn on/off the reading of the texture coordinate file. + // Specify name of geometry FileName. + vtkSetMacro(ReadTexture,int); + vtkGetMacro(ReadTexture,int); + vtkBooleanMacro(ReadTexture,int); + + // Description: + // Set/Get the part number to be read. + vtkSetClampMacro(PartNumber,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(PartNumber,int); + +protected: + vtkBYUReader(); + ~vtkBYUReader(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + // This source does not know how to generate pieces yet. + int ComputeDivisionExtents(vtkDataObject *output, + int idx, int numDivisions); + + char *GeometryFileName; + char *DisplacementFileName; + char *ScalarFileName; + char *TextureFileName; + int ReadDisplacement; + int ReadScalar; + int ReadTexture; + int PartNumber; + + void ReadGeometryFile(FILE *fp, int &numPts, vtkInformation *outInfo); + void ReadDisplacementFile(int numPts, vtkInformation *outInfo); + void ReadScalarFile(int numPts, vtkInformation *outInfo); + void ReadTextureFile(int numPts, vtkInformation *outInfo); +private: + vtkBYUReader(const vtkBYUReader&); // Not implemented. + void operator=(const vtkBYUReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkBYUWriter.cxx b/IO/vtkBYUWriter.cxx new file mode 100644 index 0000000..da1002c --- /dev/null +++ b/IO/vtkBYUWriter.cxx @@ -0,0 +1,428 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBYUWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBYUWriter.h" + +#include "vtkCellArray.h" +#include "vtkErrorCode.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +#include + +vtkCxxRevisionMacro(vtkBYUWriter, "$Revision: 1.58 $"); +vtkStandardNewMacro(vtkBYUWriter); + +// Create object so that it writes displacement, scalar, and texture files +// (if data is available). +vtkBYUWriter::vtkBYUWriter() +{ + this->GeometryFileName = NULL; + this->DisplacementFileName = NULL; + this->ScalarFileName = NULL; + this->TextureFileName = NULL; + + this->WriteDisplacement = 1; + this->WriteScalar = 1; + this->WriteTexture = 1; +} + +vtkBYUWriter::~vtkBYUWriter() +{ + if ( this->GeometryFileName ) + { + delete [] this->GeometryFileName; + } + if ( this->DisplacementFileName ) + { + delete [] this->DisplacementFileName; + } + if ( this->ScalarFileName ) + { + delete [] this->ScalarFileName; + } + if ( this->TextureFileName ) + { + delete [] this->TextureFileName; + } +} + +// Write out data in MOVIE.BYU format. +void vtkBYUWriter::WriteData() +{ + FILE *geomFp; + vtkPolyData *input= this->GetInput(); + + int numPts=input->GetNumberOfPoints(); + + if ( numPts < 1 ) + { + vtkErrorMacro(<<"No data to write!"); + return; + } + + if ( !this->GeometryFileName ) + { + vtkErrorMacro(<< "Geometry file name was not specified"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return; + } + + if ((geomFp = fopen(this->GeometryFileName, "w")) == NULL) + { + vtkErrorMacro(<< "Couldn't open geometry file: " << this->GeometryFileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + return; + } + else + { + this->WriteGeometryFile(geomFp,numPts); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + fclose(geomFp); + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->GeometryFileName); + unlink(this->GeometryFileName); + return; + } + } + + this->WriteDisplacementFile(numPts); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + fclose(geomFp); + unlink(this->GeometryFileName); + unlink(this->DisplacementFileName); + vtkErrorMacro("Ran out of disk space; deleting files: " + << this->GeometryFileName << " " + << this->DisplacementFileName); + return; + } + this->WriteScalarFile(numPts); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkstd::string errorMessage; + fclose(geomFp); + unlink(this->GeometryFileName); + errorMessage = "Ran out of disk space; deleting files: "; + errorMessage += this->GeometryFileName; + errorMessage += " "; + if (this->DisplacementFileName) + { + unlink(this->DisplacementFileName); + errorMessage += this->DisplacementFileName; + errorMessage += " "; + } + unlink(this->ScalarFileName); + errorMessage += this->ScalarFileName; + vtkErrorMacro( << errorMessage.c_str()); + return; + } + this->WriteTextureFile(numPts); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + fclose(geomFp); + vtkstd::string errorMessage; + unlink(this->GeometryFileName); + errorMessage = "Ran out of disk space; deleting files: "; + errorMessage += this->GeometryFileName; + errorMessage += " "; + if (this->DisplacementFileName) + { + unlink(this->DisplacementFileName); + errorMessage += this->DisplacementFileName; + errorMessage += " "; + } + if (this->ScalarFileName) + { + unlink(this->ScalarFileName); + errorMessage += this->ScalarFileName; + errorMessage += " "; + } + unlink(this->TextureFileName); + errorMessage += this->TextureFileName; + vtkErrorMacro( << errorMessage.c_str()); + return; + } + + // Close the file + fclose (geomFp); +} + +void vtkBYUWriter::WriteGeometryFile(FILE *geomFile, int numPts) +{ + int numPolys, numEdges; + int i; + double *x; + vtkIdType npts = 0; + vtkIdType *pts = 0; + vtkPoints *inPts; + vtkCellArray *inPolys; + vtkPolyData *input= this->GetInput(); + // + // Check input + // + inPolys=input->GetPolys(); + if ( (inPts=input->GetPoints()) == NULL || inPolys == NULL ) + { + vtkErrorMacro(<<"No data to write!"); + return; + } +// +// Write header (not using fixed format! - potential problem in some files.) +// + numPolys = input->GetPolys()->GetNumberOfCells(); + for (numEdges=0, inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + numEdges += npts; + } + + if (fprintf (geomFile, "%d %d %d %d\n", 1, numPts, numPolys, numEdges) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + if (fprintf (geomFile, "%d %d\n", 1, numPolys) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + +// +// Write data +// + // write point coordinates + for (i=0; i < numPts; i++) + { + x = inPts->GetPoint(i); + if (fprintf(geomFile, "%e %e %e ", x[0], x[1], x[2]) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + if ( (i % 2) ) + { + if (fprintf(geomFile, "\n") < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + } + if ( (numPts % 2) ) + { + if (fprintf(geomFile, "\n") < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + + // write poly data. Remember 1-offset. + for (inPolys->InitTraversal(); inPolys->GetNextCell(npts,pts); ) + { + // write this polygon + // treating vtkIdType as int + for (i=0; i < (npts-1); i++) + { + if (fprintf (geomFile, "%d ", (int)(pts[i]+1)) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + if (fprintf (geomFile, "%d\n", (int)(-(pts[npts-1]+1))) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + + vtkDebugMacro(<<"Wrote " << numPts << " points, " << numPolys << " polygons"); +} + +void vtkBYUWriter::WriteDisplacementFile(int numPts) +{ + FILE *dispFp; + int i; + double *v; + vtkDataArray *inVectors; + vtkPolyData *input= this->GetInput(); + + if ( this->WriteDisplacement && this->DisplacementFileName && + (inVectors = input->GetPointData()->GetVectors()) != NULL ) + { + if ( !(dispFp = fopen(this->DisplacementFileName, "w")) ) + { + vtkErrorMacro (<<"Couldn't open displacement file"); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + return; + } + } + else + { + return; + } + // + // Write data + // + for (i=0; i < numPts; i++) + { + v = inVectors->GetTuple(i); + if (fprintf(dispFp, "%e %e %e", v[0], v[1], v[2]) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + fclose(dispFp); + return; + } + if ( (i % 2) ) + { + if (fprintf (dispFp, "\n") < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + fclose(dispFp); + return; + } + } + } + + vtkDebugMacro(<<"Wrote " << numPts << " displacements"); + fclose (dispFp); +} + +void vtkBYUWriter::WriteScalarFile(int numPts) +{ + FILE *scalarFp; + int i; + float s; + vtkDataArray *inScalars; + vtkPolyData *input= this->GetInput(); + + if ( this->WriteScalar && this->ScalarFileName && + (inScalars = input->GetPointData()->GetScalars()) != NULL ) + { + if ( !(scalarFp = fopen(this->ScalarFileName, "w")) ) + { + vtkErrorMacro (<<"Couldn't open scalar file"); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + return; + } + } + else + { + return; + } + // + // Write data + // + for (i=0; i < numPts; i++) + { + s = inScalars->GetComponent(i,0); + if (fprintf(scalarFp, "%e ", s) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + fclose(scalarFp); + return; + } + if ( i != 0 && !(i % 6) ) + { + if (fprintf (scalarFp, "\n") < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + fclose(scalarFp); + return; + } + } + } + + fclose (scalarFp); + vtkDebugMacro(<<"Wrote " << numPts << " scalars"); +} + +void vtkBYUWriter::WriteTextureFile(int numPts) +{ + FILE *textureFp; + int i; + double *t; + vtkDataArray *inTCoords; + vtkPolyData *input= this->GetInput(); + + if ( this->WriteTexture && this->TextureFileName && + (inTCoords = input->GetPointData()->GetTCoords()) != NULL ) + { + if ( !(textureFp = fopen(this->TextureFileName, "w")) ) + { + vtkErrorMacro (<<"Couldn't open texture file"); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + return; + } + } + else + { + return; + } + // + // Write data + // + for (i=0; i < numPts; i++) + { + if ( i != 0 && !(i % 3) ) + { + if (fprintf (textureFp, "\n") < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + fclose(textureFp); + return; + } + } + t = inTCoords->GetTuple(i); + if (fprintf(textureFp, "%e %e", t[0], t[1]) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + fclose(textureFp); + return; + } + } + + fclose (textureFp); + vtkDebugMacro(<<"Wrote " << numPts << " texture coordinates"); +} + +void vtkBYUWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Geometry File Name: " + << (this->GeometryFileName ? this->GeometryFileName : "(none)") << "\n"; + + os << indent << "Write Displacement: " << (this->WriteDisplacement ? "On\n" : "Off\n"); + os << indent << "Displacement File Name: " + << (this->DisplacementFileName ? this->DisplacementFileName : "(none)") << "\n"; + + os << indent << "Write Scalar: " << (this->WriteScalar ? "On\n" : "Off\n"); + os << indent << "Scalar File Name: " + << (this->ScalarFileName ? this->ScalarFileName : "(none)") << "\n"; + + os << indent << "Write Texture: " << (this->WriteTexture ? "On\n" : "Off\n"); + os << indent << "Texture File Name: " + << (this->TextureFileName ? this->TextureFileName : "(none)") << "\n"; +} + diff --git a/IO/vtkBYUWriter.h b/IO/vtkBYUWriter.h new file mode 100644 index 0000000..a869342 --- /dev/null +++ b/IO/vtkBYUWriter.h @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBYUWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBYUWriter - write MOVIE.BYU files +// .SECTION Description +// vtkBYUWriter writes MOVIE.BYU polygonal files. These files consist +// of a geometry file (.g), a scalar file (.s), a displacement or +// vector file (.d), and a 2D texture coordinate file (.t). These files +// must be specified to the object, the appropriate boolean +// variables must be true, and data must be available from the input +// for the files to be written. +// WARNING: this writer does not currently write triangle strips. Use +// vtkTriangleFilter to convert strips to triangles. + +#ifndef __vtkBYUWriter_h +#define __vtkBYUWriter_h + +#include "vtkPolyDataWriter.h" + +class VTK_IO_EXPORT vtkBYUWriter : public vtkPolyDataWriter +{ +public: + static vtkBYUWriter *New(); + + vtkTypeRevisionMacro(vtkBYUWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the name of the geometry file to write. + vtkSetStringMacro(GeometryFileName); + vtkGetStringMacro(GeometryFileName); + + // Description: + // Specify the name of the displacement file to write. + vtkSetStringMacro(DisplacementFileName); + vtkGetStringMacro(DisplacementFileName); + + // Description: + // Specify the name of the scalar file to write. + vtkSetStringMacro(ScalarFileName); + vtkGetStringMacro(ScalarFileName); + + // Description: + // Specify the name of the texture file to write. + vtkSetStringMacro(TextureFileName); + vtkGetStringMacro(TextureFileName); + + // Description: + // Turn on/off writing the displacement file. + vtkSetMacro(WriteDisplacement,int); + vtkGetMacro(WriteDisplacement,int); + vtkBooleanMacro(WriteDisplacement,int); + + // Description: + // Turn on/off writing the scalar file. + vtkSetMacro(WriteScalar,int); + vtkGetMacro(WriteScalar,int); + vtkBooleanMacro(WriteScalar,int); + + // Description: + // Turn on/off writing the texture file. + vtkSetMacro(WriteTexture,int); + vtkGetMacro(WriteTexture,int); + vtkBooleanMacro(WriteTexture,int); + +protected: + vtkBYUWriter(); + ~vtkBYUWriter(); + + void WriteData(); + + char *GeometryFileName; + char *DisplacementFileName; + char *ScalarFileName; + char *TextureFileName; + int WriteDisplacement; + int WriteScalar; + int WriteTexture; + + void WriteGeometryFile(FILE *fp, int numPts); + void WriteDisplacementFile(int numPts); + void WriteScalarFile(int numPts); + void WriteTextureFile(int numPts); +private: + vtkBYUWriter(const vtkBYUWriter&); // Not implemented. + void operator=(const vtkBYUWriter&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkBase64InputStream.cxx b/IO/vtkBase64InputStream.cxx new file mode 100644 index 0000000..7c61eff --- /dev/null +++ b/IO/vtkBase64InputStream.cxx @@ -0,0 +1,156 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBase64InputStream.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBase64InputStream.h" +#include "vtkObjectFactory.h" +#include "vtkBase64Utilities.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkBase64InputStream, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkBase64InputStream); + +//---------------------------------------------------------------------------- +vtkBase64InputStream::vtkBase64InputStream() +{ + this->BufferLength = 0; +} + +//---------------------------------------------------------------------------- +vtkBase64InputStream::~vtkBase64InputStream() +{ +} + +//---------------------------------------------------------------------------- +void vtkBase64InputStream::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +inline int vtkBase64InputStream::DecodeTriplet(unsigned char& c0, + unsigned char& c1, + unsigned char& c2) +{ + // Read the 4 bytes encoding this triplet from the stream. + + unsigned char in[4]; + this->Stream->read(reinterpret_cast(in), 4); + if(this->Stream->gcount() < 4) { return 0; } + + return vtkBase64Utilities::DecodeTriplet(in[0], in[1], in[2], in[3], + &c0, &c1, &c2); +} + +//---------------------------------------------------------------------------- +void vtkBase64InputStream::StartReading() +{ + this->Superclass::StartReading(); + this->BufferLength = 0; +} + +//---------------------------------------------------------------------------- +void vtkBase64InputStream::EndReading() +{ +} + +//---------------------------------------------------------------------------- +int vtkBase64InputStream::Seek(unsigned long offset) +{ + unsigned long triplet = offset/3; + int skipLength = offset%3; + + // Seek to the beginning of the encoded triplet containing the + // offset. + if(!this->Stream->seekg(this->StreamStartPosition+(triplet*4))) + { + return 0; + } + + // Decode the first triplet if it is paritally skipped. + if(skipLength == 0) + { + this->BufferLength = 0; + } + else if(skipLength == 1) + { + unsigned char c; + this->BufferLength = + this->DecodeTriplet(c, this->Buffer[0], this->Buffer[1]) - 1; + } + else + { + unsigned char c[2]; + this->BufferLength = + this->DecodeTriplet(c[0], c[1], this->Buffer[0]) - 2; + } + + // A DecodeTriplet call may have failed to read the stream. + // If so, the current buffer length will be negative. + return ((this->BufferLength >= 0) ? 1:0); +} + +//---------------------------------------------------------------------------- +unsigned long vtkBase64InputStream::Read(unsigned char* data, + unsigned long length) +{ + unsigned char* out = data; + unsigned char* end = data + length; + + // If the previous read ended before filling buffer, don't read + // more. + if(this->BufferLength < 0) { return 0; } + + // Use leftover characters from a previous decode. + if((out != end) && (this->BufferLength == 2)) + { + *out++ = this->Buffer[0]; + this->Buffer[0] = this->Buffer[1]; + this->BufferLength = 1; + } + if((out != end) && (this->BufferLength == 1)) + { + *out++ = this->Buffer[0]; + this->BufferLength = 0; + } + + // Decode all complete triplets. + while((end - out) >= 3) + { + int len = this->DecodeTriplet(out[0], out[1], out[2]); + out += len; + if(len < 3) + { + this->BufferLength = len-3; + return (out-data); + } + } + + // Decode the last triplet and save leftover characters in the buffer. + if((end - out) == 2) + { + int len = this->DecodeTriplet(out[0], out[1], this->Buffer[0]); + this->BufferLength = len-2; + if(len > 2) { out += 2; } + else { out += len; } + } + else if((end - out) == 1) + { + int len = this->DecodeTriplet(out[0], this->Buffer[0], this->Buffer[1]); + this->BufferLength = len-1; + if(len > 1) { out += 1; } + else { out += len; } + } + + return (out-data); +} diff --git a/IO/vtkBase64InputStream.h b/IO/vtkBase64InputStream.h new file mode 100644 index 0000000..bbb2c5f --- /dev/null +++ b/IO/vtkBase64InputStream.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBase64InputStream.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBase64InputStream - Reads base64-encoded input from a stream. +// .SECTION Description +// vtkBase64InputStream implements base64 decoding with the +// vtkInputStream interface. + +#ifndef __vtkBase64InputStream_h +#define __vtkBase64InputStream_h + +#include "vtkInputStream.h" + +class VTK_IO_EXPORT vtkBase64InputStream : public vtkInputStream +{ +public: + vtkTypeRevisionMacro(vtkBase64InputStream,vtkInputStream); + static vtkBase64InputStream *New(); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Called after the stream position has been set by the caller, but + // before any Seek or Read calls. The stream position should not be + // adjusted by the caller until after an EndReading call. + void StartReading(); + + // Description: + // Seek to the given offset in the input data. Returns 1 for + // success, 0 for failure. + int Seek(unsigned long offset); + + // Description: + // Read input data of the given length. Returns amount actually + // read. + unsigned long Read(unsigned char* data, unsigned long length); + + // Description: + // Called after all desired calls to Seek and Read have been made. + // After this call, the caller is free to change the position of the + // stream. Additional reads should not be done until after another + // call to StartReading. + void EndReading(); +protected: + vtkBase64InputStream(); + ~vtkBase64InputStream(); + + // Number of decoded bytes left in Buffer from last call to Read. + int BufferLength; + unsigned char Buffer[2]; + + // Reads 4 bytes from the input stream and decodes them into 3 bytes. + int DecodeTriplet(unsigned char& c0, unsigned char& c1, unsigned char& c2); + +private: + vtkBase64InputStream(const vtkBase64InputStream&); // Not implemented. + void operator=(const vtkBase64InputStream&); // Not implemented. +}; + +#endif diff --git a/IO/vtkBase64OutputStream.cxx b/IO/vtkBase64OutputStream.cxx new file mode 100644 index 0000000..3b6b505 --- /dev/null +++ b/IO/vtkBase64OutputStream.cxx @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBase64OutputStream.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBase64OutputStream.h" +#include "vtkObjectFactory.h" +#include "vtkBase64Utilities.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkBase64OutputStream, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkBase64OutputStream); + +//---------------------------------------------------------------------------- +vtkBase64OutputStream::vtkBase64OutputStream() +{ + this->BufferLength = 0; +} + +//---------------------------------------------------------------------------- +vtkBase64OutputStream::~vtkBase64OutputStream() +{ +} + +//---------------------------------------------------------------------------- +void vtkBase64OutputStream::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +inline int vtkBase64OutputStream::EncodeTriplet(unsigned char c0, + unsigned char c1, + unsigned char c2) +{ + // Encodes 3 bytes into 4 bytes and writes them to the output stream. + unsigned char out[4]; + vtkBase64Utilities::EncodeTriplet(c0, c1, c2, + &out[0], &out[1], &out[2], &out[3]); + return (this->Stream->write(reinterpret_cast(out), 4)? 1:0); +} + +//---------------------------------------------------------------------------- +inline int vtkBase64OutputStream:: EncodeEnding(unsigned char c0, + unsigned char c1) +{ + // Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes. + unsigned char out[4]; + vtkBase64Utilities::EncodePair(c0, c1, + &out[0], &out[1], &out[2], &out[3]); + return (this->Stream->write(reinterpret_cast(out), 4)? 1:0); +} + +//---------------------------------------------------------------------------- +inline int vtkBase64OutputStream::EncodeEnding(unsigned char c0) +{ + // Encodes a 1-byte ending into 2 bytes and 2 pad bytes and writes. + unsigned char out[4]; + vtkBase64Utilities::EncodeSingle(c0, + &out[0], &out[1], &out[2], &out[3]); + return (this->Stream->write(reinterpret_cast(out), 4)? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkBase64OutputStream::StartWriting() +{ + if(!this->Superclass::StartWriting()) + { + return 0; + } + this->BufferLength = 0; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkBase64OutputStream::EndWriting() +{ + if(this->BufferLength == 1) + { + if(!this->EncodeEnding(this->Buffer[0])) { return 0; } + this->BufferLength = 0; + } + else if(this->BufferLength == 2) + { + if(!this->EncodeEnding(this->Buffer[0], this->Buffer[1])) { return 0; } + this->BufferLength = 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkBase64OutputStream::Write(const unsigned char* data, + unsigned long length) +{ + unsigned long totalLength = this->BufferLength + length; + const unsigned char* in = data; + const unsigned char* end = data+length; + + if(totalLength >= 3) + { + if(this->BufferLength == 1) + { + if(!this->EncodeTriplet(this->Buffer[0], in[0], in[1])) { return 0; } + in += 2; + this->BufferLength = 0; + } + else if(this->BufferLength == 2) + { + if(!this->EncodeTriplet(this->Buffer[0], this->Buffer[1], in[0])) + { return 0; } + in += 1; + this->BufferLength = 0; + } + } + + while((end - in) >= 3) + { + if(!this->EncodeTriplet(in[0], in[1], in[2])) { return 0; } + in += 3; + } + + while(in != end) + { + this->Buffer[this->BufferLength++] = *in++; + } + return 1; +} diff --git a/IO/vtkBase64OutputStream.h b/IO/vtkBase64OutputStream.h new file mode 100644 index 0000000..d0ae2e5 --- /dev/null +++ b/IO/vtkBase64OutputStream.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBase64OutputStream.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBase64OutputStream - Writes base64-encoded output to a stream. +// .SECTION Description +// vtkBase64OutputStream implements base64 encoding with the +// vtkOutputStream interface. + +#ifndef __vtkBase64OutputStream_h +#define __vtkBase64OutputStream_h + +#include "vtkOutputStream.h" + +class VTK_IO_EXPORT vtkBase64OutputStream : public vtkOutputStream +{ +public: + vtkTypeRevisionMacro(vtkBase64OutputStream,vtkOutputStream); + static vtkBase64OutputStream *New(); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Called after the stream position has been set by the caller, but + // before any Write calls. The stream position should not be + // adjusted by the caller until after an EndWriting call. + int StartWriting(); + + // Description: + // Write output data of the given length. + int Write(const unsigned char* data, unsigned long length); + + // Description: + // Called after all desired calls to Write have been made. After + // this call, the caller is free to change the position of the + // stream. Additional writes should not be done until after another + // call to StartWriting. + int EndWriting(); + +protected: + vtkBase64OutputStream(); + ~vtkBase64OutputStream(); + + // Number of un-encoded bytes left in Buffer from last call to Write. + unsigned int BufferLength; + unsigned char Buffer[2]; + + // Methods to encode and write data. + int EncodeTriplet(unsigned char c0, unsigned char c1, unsigned char c2); + int EncodeEnding(unsigned char c0, unsigned char c1); + int EncodeEnding(unsigned char c0); + +private: + vtkBase64OutputStream(const vtkBase64OutputStream&); // Not implemented. + void operator=(const vtkBase64OutputStream&); // Not implemented. +}; + +#endif diff --git a/IO/vtkBase64Utilities.cxx b/IO/vtkBase64Utilities.cxx new file mode 100644 index 0000000..9a17180 --- /dev/null +++ b/IO/vtkBase64Utilities.cxx @@ -0,0 +1,278 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBase64Utilities.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBase64Utilities.h" +#include "vtkObjectFactory.h" +#include + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkBase64Utilities, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkBase64Utilities); + +//---------------------------------------------------------------------------- +static const unsigned char vtkBase64UtilitiesEncodeTable[65] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"abcdefghijklmnopqrstuvwxyz" +"0123456789+/"; + +//---------------------------------------------------------------------------- +inline static unsigned char vtkBase64UtilitiesEncodeChar(unsigned char c) +{ + assert( c < 65 ); + return vtkBase64UtilitiesEncodeTable[c]; +} + +//---------------------------------------------------------------------------- +void vtkBase64Utilities::EncodeTriplet(unsigned char i0, + unsigned char i1, + unsigned char i2, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3) +{ + *o0 = vtkBase64UtilitiesEncodeChar((i0 >> 2) & 0x3F); + *o1 = vtkBase64UtilitiesEncodeChar(((i0 << 4) & 0x30)|((i1 >> 4) & 0x0F)); + *o2 = vtkBase64UtilitiesEncodeChar(((i1 << 2) & 0x3C)|((i2 >> 6) & 0x03)); + *o3 = vtkBase64UtilitiesEncodeChar(i2 & 0x3F); +} + +//---------------------------------------------------------------------------- +void vtkBase64Utilities::EncodePair(unsigned char i0, + unsigned char i1, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3) +{ + *o0 = vtkBase64UtilitiesEncodeChar((i0 >> 2) & 0x3F); + *o1 = vtkBase64UtilitiesEncodeChar(((i0 << 4) & 0x30)|((i1 >> 4) & 0x0F)); + *o2 = vtkBase64UtilitiesEncodeChar(((i1 << 2) & 0x3C)); + *o3 = '='; +} + +//---------------------------------------------------------------------------- +void vtkBase64Utilities::EncodeSingle(unsigned char i0, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3) +{ + *o0 = vtkBase64UtilitiesEncodeChar((i0 >> 2) & 0x3F); + *o1 = vtkBase64UtilitiesEncodeChar(((i0 << 4) & 0x30)); + *o2 = '='; + *o3 = '='; +} + +//---------------------------------------------------------------------------- +unsigned long vtkBase64Utilities::Encode(const unsigned char *input, + unsigned long length, + unsigned char *output, + int mark_end) +{ + + const unsigned char *ptr = input; + const unsigned char *end = input + length; + unsigned char *optr = output; + + // Encode complete triplet + + while ((end - ptr) >= 3) + { + vtkBase64Utilities::EncodeTriplet(ptr[0], ptr[1], ptr[2], + &optr[0], &optr[1], &optr[2], &optr[3]); + ptr += 3; + optr += 4; + } + + // Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes. + + if (end - ptr == 2) + { + vtkBase64Utilities::EncodePair(ptr[0], ptr[1], + &optr[0], &optr[1], &optr[2], &optr[3]); + optr += 4; + } + + // Encodes a 1-byte ending into 2 bytes and 2 pad bytes + + else if (end - ptr == 1) + { + vtkBase64Utilities::EncodeSingle(ptr[0], + &optr[0], &optr[1], &optr[2], &optr[3]); + optr += 4; + } + + // Do we need to mark the end + + else if (mark_end) + { + optr[0] = optr[1] = optr[2] = optr[3] = '='; + optr += 4; + } + + return optr - output; +} + +//---------------------------------------------------------------------------- +static const unsigned char vtkBase64UtilitiesDecodeTable[256] = +{ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x3E,0xFF,0xFF,0xFF,0x3F, + 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, + 0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF, + 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, + 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, + 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20, + 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, + 0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30, + 0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF, + //------------------------------------- + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF +}; + +//---------------------------------------------------------------------------- +inline static unsigned char vtkBase64UtilitiesDecodeChar(unsigned char c) +{ + return vtkBase64UtilitiesDecodeTable[c]; +} + +//---------------------------------------------------------------------------- +int vtkBase64Utilities::DecodeTriplet(unsigned char i0, + unsigned char i1, + unsigned char i2, + unsigned char i3, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2) +{ + unsigned char d0, d1, d2, d3; + + d0 = vtkBase64UtilitiesDecodeChar(i0); + d1 = vtkBase64UtilitiesDecodeChar(i1); + d2 = vtkBase64UtilitiesDecodeChar(i2); + d3 = vtkBase64UtilitiesDecodeChar(i3); + + // Make sure all characters were valid + + if (d0 == 0xFF || d1 == 0xFF || d2 == 0xFF || d3 == 0xFF) + { + return 0; + } + + // Decode the 3 bytes + + *o0 = ((d0 << 2) & 0xFC) | ((d1 >> 4) & 0x03); + *o1 = ((d1 << 4) & 0xF0) | ((d2 >> 2) & 0x0F); + *o2 = ((d2 << 6) & 0xC0) | ((d3 >> 0) & 0x3F); + + // Return the number of bytes actually decoded + + if (i2 == '=') + { + return 1; + } + if (i3 == '=') + { + return 2; + } + return 3; +} + +//---------------------------------------------------------------------------- +unsigned long vtkBase64Utilities::Decode(const unsigned char *input, + unsigned long length, + unsigned char *output, + unsigned long max_input_length) +{ + const unsigned char *ptr = input; + unsigned char *optr = output; + + // Decode complete triplet + + if (max_input_length) + { + const unsigned char *end = input + max_input_length; + while (ptr < end) + { + int len = + vtkBase64Utilities::DecodeTriplet(ptr[0], ptr[1], ptr[2], ptr[3], + &optr[0], &optr[1], &optr[2]); + optr += len; + if(len < 3) + { + return optr - output; + } + ptr += 4; + } + } + else + { + unsigned char *oend = output + length; + while ((oend - optr) >= 3) + { + int len = + vtkBase64Utilities::DecodeTriplet(ptr[0], ptr[1], ptr[2], ptr[3], + &optr[0], &optr[1], &optr[2]); + optr += len; + if(len < 3) + { + return optr - output; + } + ptr += 4; + } + + // Decode the last triplet + + unsigned char temp; + if (oend - optr == 2) + { + int len = + vtkBase64Utilities::DecodeTriplet(ptr[0], ptr[1], ptr[2], ptr[3], + &optr[0], &optr[1], &temp); + optr += (len > 2 ? 2 : len); + } + else if (oend - optr == 1) + { + unsigned char temp2; + int len = + vtkBase64Utilities::DecodeTriplet(ptr[0], ptr[1], ptr[2], ptr[3], + &optr[0], &temp, &temp2); + optr += (len > 2 ? 2 : len); + } + } + + return optr - output; +} diff --git a/IO/vtkBase64Utilities.h b/IO/vtkBase64Utilities.h new file mode 100644 index 0000000..ee20dae --- /dev/null +++ b/IO/vtkBase64Utilities.h @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBase64Utilities.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBase64Utilities - base64 encode and decode utilities. +// .SECTION Description +// vtkBase64Utilities implements base64 encoding and decoding. + +#ifndef __vtkBase64Utilities_h +#define __vtkBase64Utilities_h + +#include "vtkObject.h" + +class VTK_IO_EXPORT vtkBase64Utilities : public vtkObject +{ +public: + static vtkBase64Utilities *New(); + vtkTypeRevisionMacro(vtkBase64Utilities,vtkObject); + + // Description: + // Encode 3 bytes into 4 bytes + static void EncodeTriplet(unsigned char i0, + unsigned char i1, + unsigned char i2, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3); + + // Description: + // Encode 2 bytes into 4 bytes + static void EncodePair(unsigned char i0, + unsigned char i1, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3); + + // Description: + // Encode 1 byte into 4 bytes + static void EncodeSingle(unsigned char i0, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2, + unsigned char *o3); + + // Description: + // Encode 'length' bytes from the input buffer and store the + // encoded stream into the output buffer. Return the length of + // the encoded stream. Note that the output buffer must be allocated + // by the caller (length * 1.5 should be a safe estimate). + // If 'mark_end' is true than an extra set of 4 bytes is added + // to the end of the stream if the input is a multiple of 3 bytes. + // These bytes are invalid chars and therefore they will stop the decoder + // thus enabling the caller to decode a stream without actually knowing + // how much data to expect (if the input is not a multiple of 3 bytes then + // the extra padding needed to complete the encode 4 bytes will stop the + // decoding anyway). + static unsigned long Encode(const unsigned char *input, + unsigned long length, + unsigned char *output, + int mark_end = 0); + + + // Description: + // Decode 4 bytes into 3 bytes. + static int DecodeTriplet(unsigned char i0, + unsigned char i1, + unsigned char i2, + unsigned char i3, + unsigned char *o0, + unsigned char *o1, + unsigned char *o2); + + // Description: + // Decode bytes from the input buffer and store the decoded stream + // into the output buffer until 'length' bytes have been decoded. + // Return the real length of the decoded stream (which should be equal to + // 'length'). Note that the output buffer must be allocated by the caller. + // If 'max_input_length' is not null, then it specifies the number of + // encoded bytes that should be at most read from the input buffer. In + // that case the 'length' parameter is ignored. This enables the caller + // to decode a stream without actually knowing how much decoded data to + // expect (of course, the buffer must be large enough). + static unsigned long Decode(const unsigned char *input, + unsigned long length, + unsigned char *output, + unsigned long max_input_length = 0); + +protected: + vtkBase64Utilities() {}; + ~vtkBase64Utilities() {}; + +private: + vtkBase64Utilities(const vtkBase64Utilities&); // Not implemented. + void operator=(const vtkBase64Utilities&); // Not implemented. +}; + +#endif diff --git a/IO/vtkCGMWriter.cxx b/IO/vtkCGMWriter.cxx new file mode 100644 index 0000000..60fe8d2 --- /dev/null +++ b/IO/vtkCGMWriter.cxx @@ -0,0 +1,4483 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCGMWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCGMWriter.h" +#include "vtkMath.h" +#include "vtkUnsignedCharArray.h" + +#include "vtkViewport.h" +#include "vtkIdList.h" +#include "vtkPolyData.h" +#include "vtkCellArray.h" +#include "vtkGenericCell.h" +#include "vtkCellData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCGMWriter, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkCGMWriter); + +vtkCxxSetObjectMacro(vtkCGMWriter, Viewport, vtkViewport); + +vtkCGMWriter::vtkCGMWriter() +{ + this->Viewport = NULL; + this->ColorMode = VTK_COLOR_MODE_DEFAULT; + + this->SpecifiedColor[0] = 1.0; + this->SpecifiedColor[1] = 1.0; + this->SpecifiedColor[2] = 1.0; + + this->Resolution = 10000; + this->Sort = 0; +} + +vtkCGMWriter::~vtkCGMWriter() +{ + if ( this->Viewport != NULL ) + { + this->Viewport->Delete(); + this->Viewport = NULL; + } +} + +//--------------------------#defines and method descriptions for CGM output +//---defines.h +#define b0 01 +#define b1 02 +#define b2 04 +#define b3 010 +#define b4 020 +#define b5 040 +#define b6 0100 +#define b7 0200 +#define b8 0400 +#define b9 01000 +#define b10 02000 +#define b11 04000 +#define b12 010000 +#define b13 020000 +#define b14 040000 +#define b15 0100000 + +// Defines the default values for different attributes. In general, +// these track the CGM specificaition, so changing them is not a good idea. +// however, it is generally ok to set them to -1 (undefined) if you want. +// + +#define CGMLTYPE 1 +#define CGMLWIDTH 0 +#define CGMLCOLOR 1 +#define CGMSHAPESTYLE 0 +#define CGMSHAPECOLOR 1 +#define CGMSHAPEHATCH 1 +#define CGMEDGETYPE 1 +#define CGMEDGECOLOR 1 +#define CGMEDGEWIDTH 1 +#define CGMEDGEVIS 0 +#define CGMTEXTFONT 1 +#define CGMTEXTCOLOR 1 +#define CGMTEXTHEIGHT -1 +#define CGMTEXTPATH 0 +#define CGMMTYPE 1 +#define CGMMSIZE 0 +#define CGMMCOLOR 1 +#define CGMLINESPEC 1 +#define CGMEDGESPEC 1 +#define CGMMARKERSPEC 1 + +//--the include file CGM.h +// This can not be changed to a value larger than 256, though smaller +// values can be used. +// +#define cgmMaxColors 256 + +// If you know you will be working with large pictures, increase the values +// of the next two constants. +// + +// The initial size of the element list. When it fills up, we will just +// make it bigger. Starting with a larger number reduces the frequency of +// the list growing, but increases the memory needed for small pictures +// + +#define CGMSTARTLISTSIZE 4096 + +// How much the element list grows by. When the list fills up, we allocate +// a new larger list. This number is how much larger. using a larger number +// decreases the frequency of the list growing, but if only a small amount +// more is needed, it could waste memory +// + +#define CGMGROWLISTSIZE 2048 + +// Image type. See functions below; you will not need to change +// the elements directly. Use the provided macros to +// access sx, sy, the color table, and colorsTotal for +// read-only purposes. + +typedef struct cgmImageStruct { + // Don't mess with these + unsigned char * elemlist; + short int state; + int red[cgmMaxColors]; + int green[cgmMaxColors]; + int blue[cgmMaxColors]; + int open[cgmMaxColors]; + int colorsTotal; + // You can have multiple pictures in the file, this keeps track + // of which one you are on + int picnum; + // these take effect only when the first picture is created. + // subsequent changes have no effect + unsigned char *desc; + unsigned char *fontlist; + short int numfonts; + FILE *outfile; + // these take effect when a new picture is opened. Subsequent + // changes are for the next picture + int linespec; + int edgespec; + int markerspec; + int sx; + int sy; + // these take effect immediately + // Linetype, line width, line color have a broader scope in CGM + int ltype; + int lwidth; + int lcolor; + // interior style [of filled objects] (for me) can be empty, hollow, + // solid, hatch [don't do pattern, geometric pattern, interpolated + int shapestyle; + // fill color, color used on inside of closed objects, significant + // if interior style is hollow, solid, hatch, or geometric pattern + int shapecolor; + // hatch index, which hatch style to use, 1=horizontal, 2=vertical, + // 3=pos.slope, 4=neg.slope, 5=hor/vert.crosshatch, + // 6=pos/neg.crosshatch + int shapehatch; + // The edges of filled shapes can have line styles too. They + // correspond to the ones for lines. These next few set them. + int edgetype; + int edgewidth; + int edgecolor; + int edgevis; // is the edge visible or invisible + // now for the TEXT related attributes, Text Color, Text Height, + // and Text font index + int textfont; + int textcolor; + int textheight; + int textpath; + // Marker type, Marker size, marker color + int mtype; + int msize; + int mcolor; + // the next three are used for maintaining the element list + long int bytestoend; // number of bytes to end of the element list + long int listlen; // the total length of the element list + unsigned char * curelemlist; // where we curently are in the list +} cgmImage; + +typedef cgmImage* cgmImagePtr; + +// Point type for use in polygon drawing. +typedef struct cgmPointStruct{ + int x, y, e; +} cgmPoint, *cgmPointPtr; + +// Functions to manipulate images. +static cgmImagePtr cgmImageCreate(int sx, int sy); +#ifdef VTK_NOT_DEFINED +static int cgmCgmNewPic(cgmImagePtr im, int sticky); +#endif +static int cgmImageCgm(cgmImagePtr im, FILE *); +static int cgmImageDestroy(cgmImagePtr im); + +#ifdef VTK_NOT_DEFINED +// Use cgmLine, not cgmImageLine +static int cgmLine(cgmImagePtr im, int x1, int y1, int x2, int y2); +// Specify corners (not width and height). Upper left first, lower right second. +static int cgmRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2); +// center x, then center y, then radius of circle +static int cgmCircle(cgmImagePtr im, int cx, int cy, int r); +// start, middle and end of arc +static int cgmArc3Pt(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey); +// cl is 0 for pie closure, 1 for cord closure +static int cgmArc3PtClose(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey, int cl); +static int cgmEllipse(cgmImagePtr im, int cx,int cy, int d1x,int d1y, int d2x,int d2y ); +static int cgmMarker(cgmImagePtr im, int x, int y); +#endif +// polyshapes +static int cgmPolygon(cgmImagePtr im, cgmPointPtr p, int n); +#ifdef VTK_NOT_DEFINED +static int cgmPolygonSet(cgmImagePtr im, cgmPointPtr p, int n); +#endif +static int cgmPolyLine(cgmImagePtr im, cgmPointPtr p, int n); +static int cgmPolyMarker(cgmImagePtr im, cgmPointPtr p, int n); + +// Functions for Compatibility with gd +#ifdef VTK_NOT_DEFINED +static int cgmImageLine(cgmImagePtr im, int x1, int y1, int x2, int y2, int color); +static int cgmImageRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2, int color); +#endif + +#ifdef VTK_NOT_DEFINED +static int cgmImageBoundsSafe(cgmImagePtr im, int x, int y); +// These put characters in the picture. CGM can handle fonts +// (x,y) is the lower left corner of where the text goes +static int cgmText(cgmImagePtr im, int x, int y, const char *); +#endif + +// Functions for allocating colors +static int cgmImageColorAllocate(cgmImagePtr im, int r, int g, int b); +#ifdef VTK_NOT_DEFINED +static int cgmImageColorClosest(cgmImagePtr im, int r, int g, int b); +static int cgmImageColorExact(cgmImagePtr im, int r, int g, int b); +static int cgmImageColorDeallocate(cgmImagePtr im, int color); +#endif +static int cgmImageColorGet(cgmImagePtr im, int cgmIndex, + int& r, int& g, int& b); +#ifdef VTK_NOT_DEFINED +// wogl: the parameter names are commented to avoid compiler warnings +static int cgmImageColor16(cgmImagePtr im); +#endif + +// gej: functions that set style attributes +static int cgmSetLineAttrib(cgmImagePtr im, int lntype, int lnwidth, int lncolor); +static int cgmSetShapeFillAttrib(cgmImagePtr im, int instyle, int incolor, int inhatch); +static int cgmSetShapeEdgeAttrib(cgmImagePtr im, int edtype, int edwidth, int edcolor, int edvis); +static int cgmSetTextAttrib(cgmImagePtr im, int font, int color, int height); +static int cgmSetMarkerAttrib(cgmImagePtr im, int mtype, int msize, int mcolor); +// gej: or if you prefer, set the attributes individually +static int cgmSetLineType(cgmImagePtr im, int lntype); +static int cgmSetLineWidth(cgmImagePtr im, int lnwidth); +static int cgmSetLineColor(cgmImagePtr im, int lncolor); +static int cgmSetFillStyle(cgmImagePtr im, int instyle); +static int cgmSetFillColor(cgmImagePtr im, int incolor); +static int cgmSetFillHatch(cgmImagePtr im, int inhatch); +static int cgmSetEdgeType(cgmImagePtr im, int edtype); +static int cgmSetEdgeWidth(cgmImagePtr im, int edwidth); +static int cgmSetEdgeColor(cgmImagePtr im, int edcolor); +static int cgmSetEdgeVis(cgmImagePtr im, int edvis); +static int cgmSetTextFont(cgmImagePtr im, int font); +static int cgmSetTextColor(cgmImagePtr im, int color); +static int cgmSetTextHeight(cgmImagePtr im, int height); +// geJ: these individual attributes can't be set with a group function +static int cgmSetTextPath(cgmImagePtr im, int tpath); +#ifdef VTK_NOT_DEFINED +static int cgmSetTextOrient(cgmImagePtr im, int xup, int yup, int xbase, int ybase); +#endif +static int cgmSetMarkerType(cgmImagePtr im, int mtype); +static int cgmSetMarkerSize(cgmImagePtr im, int msize); +static int cgmSetMarkerColor(cgmImagePtr im, int mcolor); + +// EJ: Expert Functions, If you just need more control +static int cgmImageSetSize(cgmImagePtr im, int x, int y); +#ifdef VTK_NOT_DEFINED +static int cgmImageSetLineSpec(cgmImagePtr im, int specmode); +static int cgmImageSetMarkerSpec(cgmImagePtr im, int specmode); +static int cgmImageSetEdgeSpec(cgmImagePtr im, int specmode); +#endif +static int cgmImageSetOutput(cgmImagePtr im, FILE *output); +#ifdef VTK_NOT_DEFINED +static int cgmImageAddFont(cgmImagePtr im, const char *fontname); +static int cgmImageClearFonts(cgmImagePtr im); +#endif +static cgmImagePtr cgmImageStartCgm(); +static int cgmCgmHeader(cgmImagePtr); +static int cgmCgmPic(cgmImagePtr, int); +static int cgmImageSetDefaults(cgmImagePtr im); +static int cgmImageEndPic(cgmImagePtr im); +static int cgmImageEndCgm (cgmImagePtr im); + +// Macros to access information about images. READ ONLY. Changing +// these values will NOT have the desired result. +#define cgmImageSX(im) ((im)->sx) +#define cgmImageSY(im) ((im)->sy) +#define cgmImageColorsTotal(im) ((im)->colorsTotal) +#define cgmImageRed(im, c) ((im)->red[(c)]) +#define cgmImageGreen(im, c) ((im)->green[(c)]) +#define cgmImageBlue(im, c) ((im)->blue[(c)]) + +// Source: Independent JPEG Group +// In ANSI C, and indeed any rational implementation, size_t is also the +// type returned by sizeof(). However, it seems there are some irrational +// implementations out there, in which sizeof() returns an int even though +// size_t is defined as long or unsigned long. To ensure consistent results +// we always use this SIZEOF() macro in place of using sizeof() directly. +// + +#define SIZEOF(object) ((size_t) sizeof(object)) + +// GeJ: these are helper functions I use in cgm. That means DON'T call +// them from your program. Yes, that means you. +static int cgmImageColorClear(cgmImagePtr im); + +//-------------------methods vtk uses to write data--------------------------- +// + +// Define class for looking up colors +class vtkColorHash { +public: + vtkColorHash(); + ~vtkColorHash(); + + int InsertUniqueColor(cgmImagePtr im, int r, int g, int b); + int GetColorIndex(cgmImagePtr im, int r, int g, int b); + +protected: + vtkIdList **Table; +}; + +#define VTK_HASH_INDEX 737 +vtkColorHash::vtkColorHash() +{ + int i; + this->Table = new vtkIdList * [VTK_HASH_INDEX]; + for (i=0; iTable[i] = NULL; + } +} + +vtkColorHash::~vtkColorHash() +{ + int i; + for (i=0; iTable[i] != NULL ) + { + this->Table[i]->Delete(); + } + } + delete [] this->Table; +} + +int vtkColorHash::InsertUniqueColor(cgmImagePtr im, int r, int g, int b) +{ + int index = (65536*r + 256*g * b) % VTK_HASH_INDEX; + int cgmIndex=0; //remove warning + + // If no list, just insert the color + if ( this->Table[index] == NULL ) + { + this->Table[index] = vtkIdList::New(); + this->Table[index]->Allocate(3,3); + cgmIndex = cgmImageColorAllocate(im, r, g, b); + this->Table[index]->InsertNextId(cgmIndex); + } + + // otherwise, check to see if color exists + else + { + vtkIdType numIds=this->Table[index]->GetNumberOfIds(); + int red, green, blue; + + vtkIdType i; + for (i=0; iTable[index]->GetId(i); + cgmImageColorGet(im, cgmIndex, red, green, blue); + if ( r == red && g == green && b == blue ) + { + break; + } + } + + if ( i >= numIds ) //means didn't find one + { + cgmIndex = cgmImageColorAllocate(im, r, g, b); + this->Table[index]->InsertNextId(cgmIndex); + } + } + + return cgmIndex; +} + +int vtkColorHash::GetColorIndex(cgmImagePtr im, int r, int g, int b) +{ + int index = (65536*r + 256*g * b) % VTK_HASH_INDEX; + vtkIdType cgmIndex; + vtkIdType numIds=this->Table[index]->GetNumberOfIds(); + int red, green, blue; + int i; + + for (i=0; iTable[index]->GetId(i); + cgmImageColorGet(im, cgmIndex, red, green, blue); + if ( r == red && g == green && b == blue ) + { + return cgmIndex; + } + } + + return 0; +} +#undef VTK_HASH_INDEX + +// ------------------------------end vtkColorHash stuff--------------- + +// Build colors consisting of 3 bits red, 3 bits green, 2 bits blue +// (total of 256 colors) +// +static void DefineColors(cgmImagePtr im, int CGMcolors[256]) +{ + int red, green, blue, idx=0; + + // use 3-3-2 bits for rgb + for (blue=0; blue<256; blue+=64) + { + for (green=0; green<256; green+=32) + { + for (red=0; red<256; red+=32) + { + CGMcolors[idx++] = cgmImageColorAllocate(im, red, green, blue); + } + } + } +} + +// Define CGM colors from the lookup table provided +// +static vtkColorHash *DefineLUTColors(cgmImagePtr im, unsigned char *colors, + int numColors, int bpp) +{ + vtkColorHash *colorHash = new vtkColorHash; + unsigned char *ptr; + int r=0, g=0, b=0; //warnings + int id; + + for (id=0; id < numColors; id++) + { + ptr = colors + bpp*id; + switch (bpp) + { + case 1: case 2: + r = g = b = *ptr; + break; + case 3: case 4: + r = ptr[0]; + g = ptr[1]; + b = ptr[2]; + break; + } + + colorHash->InsertUniqueColor(im, r, g, b); + } + + return colorHash; +} + +// Get a CGM color from the RGB value specified. +// +static int GetColor(int red, int green, int blue, int CGMColors[256]) +{ + // round to nearest value + red = (red + 16) / 32; + red = (red > 7 ? 7 : red); + green =(green + 16) / 32; + green = (green > 7 ? 7 : green); + blue = (blue + 32) / 64; + blue = (blue > 3 ? 3 : blue); + + return CGMColors[red + green*8 + blue*64]; +} + +#ifdef VTK_NOT_DEFINED +static int GetLUTColor(int vtkNotUsed(red), int vtkNotUsed(green), int vtkNotUsed(blue)) +{ + return 0; +} +#endif + +typedef struct _vtkSortValues { + float z; + int cellId; +} vtkSortValues; + +extern "C" +{ +int vtkCGMqsortCompare(const void *val1, const void *val2) +{ + if (((vtkSortValues *)val1)->z > ((vtkSortValues *)val2)->z) + { + return (-1); + } + else if (((vtkSortValues *)val1)->z < ((vtkSortValues *)val2)->z) + { + return (1); + } + else + { + return (0); + } +} +} + +void vtkCGMWriter::WriteData() +{ + FILE *outf; + vtkPolyData *input=this->GetInput(); + + vtkIdType numCells=input->GetNumberOfCells(), cellId; + vtkIdType numPts=input->GetNumberOfPoints(); + + // Check that there is something to write + if ( numPts < 1 || numCells < 1 ) + { + vtkErrorMacro(<<"No data to write"); + return; + } + + // Try opening the file + if ( (outf = fopen(this->FileName, "wb")) == NULL ) + { + vtkErrorMacro(<<"Cannot open CGM file"); + return; + } + + cgmImagePtr im; + vtkPoints *inPts=input->GetPoints(), *pts; + vtkGenericCell *cell=vtkGenericCell::New(); + vtkDataArray *inScalars=input->GetCellData()->GetScalars(); + int i, id, type, npts, size[2]; + vtkIdType *p; + double bounds[6], xRange, yRange, x[3], factor[2]; + int color, bpp=1, colorMode; + unsigned char *ptr, *colors=NULL; + int rgbColor[3], maxCellSize; + cgmPoint *points; + vtkSortValues *depth=NULL; //warnings + + // Figure out the coordinate range of the data. + // Generate the points that will be used for output. + // + if ( this->Viewport == NULL ) //zero-out z values + { + input->GetBounds(bounds); + pts = inPts; + } + else //transform into view coordinates + { + vtkPoints *displayPts = vtkPoints::New(); + displayPts->SetNumberOfPoints(numPts); + for ( i=0; i < numPts; i++ ) + { + inPts->GetPoint(i, x); + this->Viewport->SetWorldPoint(x[0], x[1], x[2], 1.0); + this->Viewport->WorldToDisplay(); + this->Viewport->GetDisplayPoint(x); + displayPts->SetPoint(i, x); + } + displayPts->GetBounds(bounds); + pts = displayPts; + } + + // Get the bounding box of the points + // + xRange = bounds[1] - bounds[0]; + yRange = bounds[3] - bounds[2]; + if ( xRange > yRange ) + { + factor[0] = 1.0; + factor[1] = yRange/xRange; + size[0] = this->Resolution; + size[1] = (int)(factor[1] * this->Resolution); + } + else + { + factor[0] = yRange/xRange; + factor[1] = 1.0; + size[0] = (int)(factor[0] * this->Resolution); + size[1] = this->Resolution; + } + + // Loop over the points again, transforming them into resolution specified + // + vtkPoints *scaledPts = vtkPoints::New(); + scaledPts->SetDataTypeToInt(); + scaledPts->SetNumberOfPoints(numPts); + x[2] = 0.0; + for (i=0; iGetPoint(i,x); + x[0] = (x[0] - bounds[0]) / xRange * this->Resolution * factor[0]; + x[1] = (x[1] - bounds[2]) / yRange * this->Resolution * factor[1]; + scaledPts->SetPoint(i,x); + } + + // Generate the colors according to specified method + // + int CGMColors[256]; + im = cgmImageCreate(size[0], size[1]); + vtkColorHash *colorHash=NULL; + + if ( this->ColorMode == VTK_COLOR_MODE_DEFAULT ) + { + if ( inScalars && inScalars->GetDataType() == VTK_UNSIGNED_CHAR ) + { + colorMode = VTK_COLOR_MODE_DEFAULT; + bpp = inScalars->GetNumberOfComponents(); + colors = static_cast(inScalars)->GetPointer(0); + } + else + { + colorMode = VTK_COLOR_MODE_SPECIFIED_COLOR; + } + } + else + { + colorMode = this->ColorMode; + } + + if ( colorMode == VTK_COLOR_MODE_DEFAULT ) + { + colorHash = DefineLUTColors(im, colors, numCells, bpp); + } + else //random or specified color + { + DefineColors(im, CGMColors); + } + + // Setup creation of the CGM file + // + maxCellSize = input->GetVerts()->GetMaxCellSize(); + maxCellSize = (input->GetLines()->GetMaxCellSize() > maxCellSize ? + input->GetLines()->GetMaxCellSize() : maxCellSize ); + maxCellSize = (input->GetPolys()->GetMaxCellSize() > maxCellSize ? + input->GetPolys()->GetMaxCellSize() : maxCellSize ); + maxCellSize = (input->GetStrips()->GetMaxCellSize() > maxCellSize ? + input->GetStrips()->GetMaxCellSize() : maxCellSize ); + points = new cgmPoint [maxCellSize]; + + // If sorting is turned on, then traverse the cells, generating a depth + // value which is used for sorting. + // + if ( this->Sort ) + { + depth = new vtkSortValues [numCells]; + for ( cellId=0; cellId < numCells; cellId++ ) + { + input->GetCell(cellId, cell); + id = cell->PointIds->GetId(0); + pts->GetPoint(id,x); + + depth[cellId].z = x[2]; + depth[cellId].cellId = cellId; + } + + qsort((void *)depth, numCells, sizeof(vtkSortValues), vtkCGMqsortCompare); + } + + + // Traverse the cells and spit out the appropriate primitives. + cgmSetShapeEdgeAttrib(im, 1, 0, 0, 0); + for ( cellId=0; cellId < numCells; cellId++ ) + { + if ( this->Sort ) + { + id = depth[cellId].cellId; + } + else + { + id = cellId; + } + + input->GetCell(id, cell); + type = cell->GetCellType(); + npts = cell->GetNumberOfPoints(); + p = cell->GetPointIds()->GetPointer(0); + + if ( colorMode == VTK_COLOR_MODE_DEFAULT ) + { + ptr = colors + bpp*id; + switch (bpp) + { + case 1: case 2: + rgbColor[0] = *ptr; + rgbColor[1] = *ptr; + rgbColor[2] = *ptr; + break; + case 3: case 4: + rgbColor[0] = ptr[0]; + rgbColor[1] = ptr[1]; + rgbColor[2] = ptr[2]; + break; + } + + color = colorHash->GetColorIndex(im, rgbColor[0], rgbColor[1], rgbColor[2]); + } + else if ( colorMode == VTK_COLOR_MODE_SPECIFIED_COLOR ) + { + color = GetColor((int)(this->SpecifiedColor[0] * 255.0), + (int)(this->SpecifiedColor[1] * 255.0), + (int)(this->SpecifiedColor[2] * 255.0), CGMColors); + } + else //if ( colorMode == VTK_COLOR_MODE_RANDOM_COLORS ) + { + color = GetColor((int)vtkMath::Random(0,255), + (int)vtkMath::Random(0,255), + (int)vtkMath::Random(0,255), CGMColors); + } + + switch (type) + { + case VTK_VERTEX: case VTK_POLY_VERTEX: + for (i=0; iGetPoint(p[i], x); + points[0].x = (int)x[0]; + points[0].y = (int)x[1]; + } + cgmPolyMarker(im, points, 1); + break; + case VTK_LINE: case VTK_POLY_LINE: + for (i=0; iGetPoint(p[i], x); + points[i].x = (int)x[0]; + points[i].y = (int)x[1]; + } + cgmSetLineColor(im, color); + cgmPolyLine(im, points, npts); + break; + case VTK_TRIANGLE: case VTK_QUAD: case VTK_POLYGON: + for (i=0; iGetPoint(p[i], x); + points[i].x = (int)x[0]; + points[i].y = (int)x[1]; + } + cgmSetShapeFillAttrib(im, 1, color, -1); + cgmPolygon(im, points, npts); + break; + case VTK_TRIANGLE_STRIP: + for (i=0; i<(npts-2); i++) + { + scaledPts->GetPoint(p[i], x); + points[0].x = (int)x[0]; + points[0].y = (int)x[1]; + scaledPts->GetPoint(p[i+1], x); + points[1].x = (int)x[0]; + points[1].y = (int)x[1]; + scaledPts->GetPoint(p[i+2], x); + points[2].x = (int)x[0]; + points[2].y = (int)x[1]; + } + cgmSetShapeFillAttrib(im, 1, color, -1); + cgmPolygon(im, points, 3); + break; + default: + vtkErrorMacro(<<"Unsupported CGM type"); + } + } + if ( colorMode == VTK_COLOR_MODE_DEFAULT ) + { + delete colorHash; + } + + cell->Delete(); + scaledPts->Delete(); + delete [] points; + if ( this->Sort ) + { + delete [] depth; + } + + // Write out the CGM file + cgmImageCgm(im, outf); + + // Clean up and get out + fclose(outf); + cgmImageDestroy(im); //destroys image +} + +void vtkCGMWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Viewport ) + { + os << indent << "Viewport: " + << this->Viewport << "\n"; + this->Viewport->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << indent << "No Viewport defined\n"; + } + + os << indent << "Sort: " << (this->Sort ? "On\n" : "Off\n"); + + os << indent << "Color Mode: "; + if ( this->ColorMode == VTK_COLOR_MODE_DEFAULT ) + { + os << "Default" << endl; + } + else if ( this->ColorMode == VTK_COLOR_MODE_SPECIFIED_COLOR ) + { + os << "Specified Color: (" << this->SpecifiedColor[0] << ", " + << this->SpecifiedColor[1] << ", " << this->SpecifiedColor[2] << ")\n"; + } + else + { + os << "Random Colors"; + } + + os << indent << "Resolution: " << this->Resolution << endl; +} + +//------------------private helper functions--------------------- +//---the CGM functions + +static int cgmImageAddColor(cgmImagePtr im, int si, int ei); + +/* Creates a new image of size (sx,sy). Most people should always + * start by calling this function */ +static cgmImagePtr cgmImageCreate(int sx, int sy) +{ + cgmImagePtr im; + + im = cgmImageStartCgm(); + if (!im) + { + return 0; /* memory allocation failed */ + } + if (!cgmImageSetSize(im, sx,sy)) + { + free (im); + return 0; + } + + if (!cgmCgmHeader(im)) + { + free (im); + return 0; + } + + if (cgmCgmPic(im, 0)) + { + return im; + } + else + { + free(im); + return 0; + } +} + +static int cgmAppNull(unsigned char *es, int x) +{ +/* put x nulls in the string. + * return value is number of octets added (1) */ + int y; + + for(y=0; y> 8; + *es = (unsigned char) temp & 0377; + es++; + *es = (unsigned char) addme & 0377; + return 2; +} + +static int cgmcomhead(unsigned char *es, int elemclass, int id, int len) +{ +/* sets the command header in the first two bytes of string es + * element class is in bits 15-12 + * element id is in bits 11-5 + * parameter list length is in bits 4-0 + */ + int temp; + + if (!es) + { + return 0; /* the string must be allocated first */ + } + + /* set the element class */ + *es = (unsigned char) elemclass << 4; + /* set the element id */ + temp = 0177 & id ; + temp = temp >> 3; + *es = *es | temp; + es++; + id = id << 5; + *es = (unsigned char) id; + *es = *es | (unsigned char) ( 037 & len ); + + return 1; +} + +static int cgmcomheadlong(unsigned char *es, int elemclass, int id, int len) +{ +/* sets the command header for the long form. + * first 16 bits: + * element class is in bits 15-12 + * element id is in bits 11-5 + * parameter list length is in bits 4-0 = 31 + * second 16 bits: + * bit 15 = 0 (for last partition) + * bit 14-0 param list len + */ + + /* I'm lazy, call cgmcomhead to set the first two bytes */ + if (!cgmcomhead(es, elemclass, id, 31)) + { + return 0; + } + + es += 2; + + /* now set the second two bytes */ + cgmAppShort(es, (short int) len); + *es = *es & 0177; /* make bit 15 = 0 */ + es += 2; + + return 1; +} + +static int cgmAddElem(cgmImagePtr im, unsigned char *es, int octet_count) +/* adds a string, which is a CGM element to the elemlist. + * This function is called by other functions in this library and + * should NOT be called by users of the library + * For internal cgm functions only, do not call! + */ +{ + unsigned char *newlist; /* in case memory allocation fails */ + int x; /* counter */ + + while ((octet_count + 1) >= im->bytestoend) + { + /* not enough space, must grow elemlist */ + im->listlen = im->listlen + CGMGROWLISTSIZE; + newlist = (unsigned char *) realloc(im->elemlist, + SIZEOF(unsigned char ) * im->listlen); + if (newlist) + { + /* successfully allocated memory */ + im->elemlist = newlist; + im->bytestoend = im->bytestoend + CGMGROWLISTSIZE; + im->curelemlist = im->elemlist + (im->listlen - im->bytestoend); + } + else + { + /* memory allocation failed, save yurself */ + im->listlen = im->listlen - CGMGROWLISTSIZE; + return 0; + } + } + + /* ok, if we get to here, there is enough space, so add it. */ + for (x=0; x < octet_count; x++) + { + *im->curelemlist = (unsigned char) *es; + im->curelemlist++; + es++; + } + im->bytestoend = im->bytestoend - octet_count; + return 1; +} + +static int cgmCgmHeader(cgmImagePtr im) +{ +/* add the cgm header to the imagepointer's element list + * do it all in a string than call cgmAddElem on it + * For internal cgm functions only, do not call! + */ + unsigned char *headerp; + unsigned char *head; + const unsigned char *buf, *buf2; + int octet_count=0; + int blen; /* length of buf */ + int curly; + int fontlistlen; /* each font in the font list is stored as a string, + with a single octet in front of the string + giving its length, fontlistlen is the sum of + the lengths of all the font strings + the + length octets. */ + + if (im->state != 0) + { + return 0; + } + + headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char )); + if (!headerp) + { + return 0; /* memory allocation failed */ + } + head=headerp; + + /*** Attribute: BegMF; Elem Class 0; Elem ID 1 */ + buf = (const unsigned char *) "vtk: Visualization Toolkit"; + blen = (int)strlen( (const char *) buf); + cgmcomhead(head, 0, 1, blen+1); + head += 2; + head += cgmAppByte(head, (short int) blen); + buf2 = buf; + while (*buf2) + { + *head++ = *buf2++; + } + octet_count += (blen + 3); + curly = 4 - (octet_count % 4); + if (curly % 4) + { + octet_count += curly; + head += cgmAppNull(head, curly); + } + + /*** Attribute: MFVersion; Elem Class 1; Elem ID 1 */ + cgmcomhead(head, 1, 1, 2); + head += 2; + head += cgmAppShort(head, (short int) 1); + octet_count += 4; + + /*** Attribute: MFDesc; Elem Class 1; Elem ID 2 */ + blen = (int)strlen( (char *) im->desc); + cgmcomheadlong(head, 1, 2, blen+1); + head += 4; + head += cgmAppByte(head, (short int) blen); + buf2 = im->desc; + while (*buf2) + { + *head++ = *buf2++; + } + octet_count += (blen + 5); + curly = 4 - (octet_count % 4); + if (curly % 4) + { + octet_count += curly; + head += cgmAppNull(head, curly); + } + + /*** Attribute: ColrPrec; Elem Class 1; Elem ID 7 */ + cgmcomhead(head, 1, 7, 2); + head += 2; + head += cgmAppShort(head, (short int) 8); + octet_count += 4; + + /*** Attribute: ColrIndexPrec; Elem Class 1; Elem ID 8 */ + cgmcomhead(head, 1, 8, 2); + head += 2; + head += cgmAppShort(head, (short int) 8); + octet_count += 4; + + /*** Attribute: MaxColrIndex; Elem Class 1; Elem ID 9 */ + cgmcomhead(head, 1, 9, 1); + head += 2; + head += cgmAppByte(head, (short int) 255); + octet_count += 4; head++; + + /*** Attribute: MFElemList; Elem Class 1; Elem ID 11 */ + /* shorthand here. 1 means 1 element specified, (-1,1) + * means drawing-plus-control set */ + cgmcomhead(head, 1, 11, 6); + head += 2; + head += cgmAppShort(head, (short int) 1); + head += cgmAppShort(head, (short int) -1); + head += cgmAppShort(head, (short int) 1); + octet_count += 8; + + /*** Attribute: FontList; Elem Class 1; Elem ID 13 */ + /* im->fontlist contains a comma separated list of font names + * since we don't need the commas, and every font except one has + * a comma, and we do need a length octet, that means that + * taking the string length will give us one less than the + * correct length. */ + buf = im->fontlist; + if (0) + { /* don't do this if there aren't any fonts */ + // if (buf) /* don't do this if there aren't any fonts */ + fontlistlen = (int)strlen( (const char *) buf) + 1; + cgmcomheadlong(head, 1, 13, fontlistlen); + head +=4; + + while (*buf) + { + blen = 0; + buf2 = buf; + while ((*buf) && (*buf != ',')) + { + buf++; + blen++; + } + head += cgmAppByte(head, (short int) blen); + while (buf2 < buf) + { + *head++ = *buf2++; + } + if (*buf) + { + buf++; + } + } + octet_count += (4 + fontlistlen); + curly = 4 - (octet_count % 4); + if (curly % 4) + { + octet_count += curly; + head += cgmAppNull(head, curly); + } + } /* end of check to see if any fonts */ + + if (cgmAddElem(im, headerp, octet_count)) + { + free(headerp); + return 1; + } + else + { + free(headerp); + return 0; + } +} + + +static int cgmCgmPic(cgmImagePtr im, int sticky) +{ +/* Start the picture. if the sticky bit is set, set and use the defaults + * of the previous picture. Otherwise, reset all defaults. + * Gej: sticky = 0 reset defaults, 1 dont reset anything, 2 only + * reset the color table + */ + unsigned char *headerp; + unsigned char *head; + unsigned char *buf, *buf2; + char *tb; + int octet_count=0; + int blen; /* length of buf */ + int x1,x2,x3,x4; /* needed for setting defaults */ + + if ((im->state != 0) && (im->state != 2)) + { + return 0; + } + + if ((sticky > 2) || (sticky < 0)) + { + return 0; /* invalid sticky bit */ + } + + /* increment the picture number */ + im->picnum++; + tb = (char *) calloc(4*4, SIZEOF(char) ); + headerp = (unsigned char *) calloc(1024, SIZEOF(unsigned char )); + if (!headerp) + { + return 0; /* memory allocation failed */ + } + head=headerp; + + /*** Attribute: BegPic; Elem Class 0; Elem ID 3 */ + sprintf(tb, "picture %d", im->picnum); + buf = (unsigned char*) tb; + /* buf = (unsigned char *) "picture 1"; */ + blen = (int)strlen( (char *) buf); + cgmcomhead(head, 0, 3, blen+1); + head += 2; + head += cgmAppByte(head, (short int) blen); + buf2 = buf; + while (*buf2) + { + *head++ = *buf2++; + } + free(tb); + octet_count += (blen + 3); + if (!(blen % 2)) + { + octet_count++; + head += cgmAppNull(head, 1); + } + if (octet_count % 4) + { + octet_count +=2; + head += cgmAppNull(head, 2); + } + + /*** Attribute: ColrMode; Elem Class 2; Elem ID 2 */ + cgmcomhead(head, 2, 2, 2); + head += 2; + head += cgmAppShort(head, (short int) 0); + octet_count += 4; + /* Picture Descriptor: Line Width Specification Mode; + * Elem Class 2; Elem ID 3*/ + if (sticky && (im->linespec != CGMLINESPEC)) + { + cgmcomhead(head, 2, 3, 2); + head += 2; + head += cgmAppShort(head, (short int) im->linespec); + octet_count += 4; + } + /* Picture Descriptor: Marker Size Specification Mode; + * Elem Class 2; Elem ID 4*/ + if (sticky && (im->markerspec != CGMMARKERSPEC)) + { + cgmcomhead(head, 2, 4, 2); + head += 2; + head += cgmAppShort(head, (short int) im->markerspec); + octet_count += 4; + } + /* Picture Descriptor: Edge Width Specification Mode; + * Elem Class 2; Elem ID 5*/ + if (sticky && (im->edgespec != CGMEDGESPEC)) + { + cgmcomhead(head, 2, 5, 2); + head += 2; + head += cgmAppShort(head, (short int) im->edgespec); + octet_count += 4; + } + + /*** Attribute: VDCExt; Elem Class 2; Elem ID 6 */ + cgmcomhead(head, 2, 6, 8); + head += 2; + head += cgmAppShort(head, (short int) 0); + head += cgmAppShort(head, (short int) 0); + head += cgmAppShort(head, (short int) im->sx); + head += cgmAppShort(head, (short int) im->sy); + octet_count += 10; + + /*** Attribute: Begin Picture Body; Elem Class 0; Elem ID 4 */ + cgmcomhead(head, 0, 4, 0); + head += 2; + octet_count += 2; + + if (cgmAddElem(im, headerp, octet_count)) + { + free(headerp); + } + else + { + free(headerp); + return 0; + } + + if (sticky) + { + /* keep defaults the way they are */ + if (sticky == 1) + { + /* keep the color table */ + if(cgmImageAddColor(im, 0, im->colorsTotal - 1) == -1) + { + /* no colortable */ + return 1; + } + } + else + { + /* Nuke the color table if there is one */ + cgmImageColorClear(im); + } + im->state = 1; + x1=im->ltype; x2=im->lwidth; x3=im->lcolor; + im->ltype=CGMLTYPE; im->lwidth=CGMLWIDTH; im->lcolor=CGMLCOLOR; + if(!cgmSetLineAttrib(im, x1, x2, x3)) + { + return 0; + } + + x1=im->shapestyle; x2=im->shapecolor; x3=im->shapehatch; + im->shapestyle=CGMSHAPESTYLE; im->shapecolor=CGMSHAPECOLOR; + im->shapehatch=CGMSHAPEHATCH; + if (!cgmSetShapeFillAttrib(im, x1, x2, x3)) + { + return 0; + } + + x1=im->edgetype; x2=im->edgewidth; + x3=im->edgecolor; x4=im->edgevis; + im->edgetype=CGMEDGETYPE; im->edgewidth=CGMEDGEWIDTH; + im->edgecolor=CGMEDGECOLOR; im->edgevis=CGMEDGEVIS; + if (!cgmSetShapeEdgeAttrib(im, x1, x2, x3, x4)) + { + return 0; + } + + x1=im->textfont; x2=im->textcolor; x3=im->textheight; + im->textfont=CGMTEXTFONT; im->textcolor=CGMTEXTCOLOR; + im->textheight=CGMTEXTHEIGHT; + if(!cgmSetTextAttrib(im, x1, x2, x3)) + { + return 0; + } + x1=im->textpath; im->textpath = CGMTEXTPATH; + if (!cgmSetTextPath(im, x1)) + { + return 0; + } + + x1=im->mtype; x2=im->msize; x3=im->mcolor; + im->ltype=CGMMTYPE; im->lwidth=CGMMSIZE; im->lcolor=CGMMCOLOR; + if(!cgmSetMarkerAttrib(im, x1, x2, x3)) + { + return 0; + } + } + else + { + /* reset all the defaults */ + cgmImageSetDefaults(im); + /* Nuke the color table if there is one */ + cgmImageColorClear(im); + im->state = 1; /* now we are officially in the picture */ + } + + return 1; +} + +#ifdef VTK_NOT_DEFINED +static int cgmCgmNewPic(cgmImagePtr im, int sticky) +/* The CGM standard allows multiple images in a single file. This function + * will close the current picture, then open a new one. + * if sticky is 0 then all attributes will be reset to the defaults + * if sticky is 1 then all attributes will be inherited from the prevous + * picture. + * if sticky is 2 all attributes except the color table will be inherited + * from the previous picture + */ +{ + /* close the current picture */ + if (!cgmImageEndPic(im)) + { + return 0; + } + + /* now start the new picture */ + return(cgmCgmPic(im, sticky)); +} +#endif + +static int cgmImageCgm(cgmImagePtr im, FILE *out) +/* Gej: Write the image to file *out, which must be open already + * does not close the file */ +{ + cgmImageSetOutput(im, out); + return cgmImageEndCgm(im); +} + + +static int cgmSetLineType(cgmImagePtr im, int lntype) +{ +/* Attribute: Line Type; Elem Class 5; Elem ID 2 + * Set the line type. Possible values are: + * 1=solid, 2=dash, 3=dot, 4=dash-dot, 5=dash-dot-dot + * Even though new ones can be defined, I am limiting lntype to these values + * If you really need more, you can make the proper changes. + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (lntype == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (lntype == im->ltype) + { + return 1; + } + + /* Make sure that lntype is between 1 and 5 */ + if ((lntype < 1) || (lntype > 5)) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomhead(es, 5, 2, 2)) + { + free(esp); + return 0; + } + + es += 2; + /* set Param_List_Len to 2 (signed int at index precision) */ + + /* add in the value of lntype */ + es += cgmAppShort(es, (short int) lntype); + + octet_count = 4; /* we just know this */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->ltype = (short int) lntype; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetLineWidth(cgmImagePtr im, int lnwidth) +{ +/* Attribute: Line Width; Elem Class 5; Elem ID 3 + * sets the line width. with an image of height X with line width 1 + * the displayed width will be 1/X%. as an example, if you image is + * x=5, y=10, and you set line width = 1, and draw a vertical line, the + * resulting line will cover 20% of horizontal area. + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (lnwidth == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (lnwidth == im->lwidth) + { + return 1; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /*gej: line width is 32 bit floating point number, 16 bits before the + * decimal, 16 bits after if Line Spec is default (1, scaled) + * if Line Spec is 0 (0, absolute) then it is 16 bit SI */ + if (im->linespec) + { + if (!cgmcomhead(es, 5, 3, 4)) + { + free(esp); + return 0; + } + es += 2; + octet_count = 2; + es += cgmAppShort(es, (short int) lnwidth); + octet_count += 2; + /* the next two (after decimal point) will always be zero */ + es += cgmAppNull(es, 2); + octet_count += 2; + } + else + { + if (!cgmcomhead(es, 5, 3, 2)) + { + free(esp); + return 0; + } + octet_count = 2; + es += 2; + es += cgmAppShort(es, (short int) lnwidth); + octet_count += 2; + } + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->lwidth = lnwidth; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetLineColor(cgmImagePtr im, int lncolor) +{ +/* Attribute: Line Colour; Elem Class 5; Elem ID 4 + * Sets the line color. lncolor should be an index into the color + * table that you have previously allocated. + */ + unsigned char *es, *esp; + int octet_count; + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (lncolor == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (lncolor == im->lcolor) + { + return 1; + } + + /* Make sure the color they want to use has been allocated. + * also, that color must be non-negative */ + if ((lncolor >= im->colorsTotal ) || (lncolor < 0)) + { + return 0; /* you must allocate a color before you use it */ + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + + if (!cgmcomhead(es, 5, 4, 1)) + { + free (esp); + return 0; + } + es += 2; + + *es = 0377 & lncolor; /* mask off last 8 bits and put in es */ + es++; + + es += cgmAppNull(es, 1); + + octet_count = 4; /* we just know this; 2 octets of header, + * 1 octet of data, 1 octet of null data */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->lcolor = (short int) lncolor; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetFillStyle(cgmImagePtr im, int instyle) +{ +/* set the style of the interior of filled area elements. + * Attribute: Interior Style; Elem Class 5; Elem ID 22 + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Interior Style: (integers 0-6, corresponding to: hollow, solid, + * [not pattern], hatch, empty, [not geometric pattern], + * interpolated.) + * attribute is 16 bit signed int + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (instyle == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (instyle == im->shapestyle) + { + return 1; + } + + /* Make sure that lnhatch is between 0 and 6, but not + * 2, 5, or 6 */ + if ((instyle < 0) || (instyle > 4) || (instyle == 2)) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* set the header to Class 5, ID 22, Length 2 */ + if (!cgmcomhead(es, 5, 22, 2)) + { + free (esp); + return 0; + } + es += 2; + + /* add in the value of inhatch */ + es += cgmAppShort(es, (short int) instyle); + + octet_count = 4; /* we just know this */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->shapestyle = (short int) instyle; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetFillColor(cgmImagePtr im, int incolor) +{ +/* set the color of the interior of filled area elements + * Attribute: Fill Colour; Elem Class 5; Elem ID 23 + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Fill Colour: (index into the color table) + */ + unsigned char *es, *esp; + int octet_count; + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (incolor == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (incolor == im->shapecolor) + { + return 1; + } + + /* Make sure the color they want to use has been allocated. + * also, that color must be non-negative */ + if ((incolor >= im->colorsTotal ) || (incolor < 0)) + { + return 0; /* you must allocate a color before you use it */ + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomhead(es, 5, 23, 1)) + { + free(esp); + return 0; + } + es += 2; + + *es = 0377 & incolor; /* mask off last 8 bits and put in es */ + es++; + es += cgmAppNull(es, 1); + + octet_count = 4; /* we just know this; 2 octets of header, + * 1 octet of data, 1 octet of null data */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->shapecolor = (short int) incolor; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetFillHatch(cgmImagePtr im, int inhatch) +{ +/* Set the hatch pattern for the interior of filled-area elements + * the fill style must be set to hatch for this to have an effect. + * Attribute: Hatch Index; Elem Class 5; Elem ID 24 + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Hatch Index: (integers 1-6, corresponding to: horizontal lines, + * vertical lines, pos. slope parallel lines, + * neg. slope parallel lines, horizontal/vertical + * crosshatch, positive/negative slope crosshatch) + */ + + unsigned char *es, *esp; + int octet_count, temp; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (inhatch == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (inhatch == im->shapehatch) + { + return 1; + } + + /* Make sure that lnhatch is between 1 and 6 */ + if ((inhatch < 1) || (inhatch > 6)) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* set the command header to class 5, id 24, length 2 */ + if (!cgmcomhead (es, 5, 24, 2)) + { + free(esp); + return 0; + } + es += 2; + + /* add in the value of inhatch */ + temp = inhatch >> 8; + *es = *es | (temp & 0377); + es++; + *es = *es | (inhatch & 0377); + es++; + + octet_count = 4; /* we just know this */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->shapehatch = (short int) inhatch; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetEdgeType(cgmImagePtr im, int edtype) +{ +/* set the type of the edge of filled-area elements. + * Attribute: Edge Type; Elem Class 5; Elem ID 27 + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Edge Type (integers 1-5, corresponding to: solid, dash, dot, + * dash-dot, dash-dot-dot. These are the same as those used + * for line type.) + * In Part 3 of the standard (Binary Encoding) on page 47 it says that + * edge type is integer. This is incorrect. Edge type is Index, just + * like line type. + * Even though new ones can be defined, I am limiting lntype to these values + * If you really need more, you can make the proper changes. + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (edtype == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (edtype == im->edgetype) + { + return 1; + } + + /* Make sure that lntype is between 1 and 5 */ + if ((edtype < 1) || (edtype > 5)) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if(!cgmcomhead(es, 5, 27, 2)) {free(esp);return 0;} + es += 2; + + /* add in the value of edtype */ + es += cgmAppShort(es, (short int) edtype); + + octet_count = 4; /* we just know this */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->edgetype = (short int) edtype; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetEdgeWidth(cgmImagePtr im, int edwidth) +{ +/* Set the width of the edge of filled-area elements. + * Attribute: Edge Width; Elem Class 5; Elem ID 28 + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Edge Width (should be the same as line width) + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (edwidth == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (edwidth == im->edgewidth) + { + return 1; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /*gej: edge width is 32 bit floating point number, 16 bits before the + * decimal, 16 bits after for default edge spec (1, scaled) if + * edge spec is absolute (0) then just 16 bit SI */ + if (im->edgespec) + { + if (!cgmcomhead(es, 5, 28, 4)) + { + free(esp); + return 0; + } + es += 2; + octet_count = 2; + es+= cgmAppShort(es, edwidth); + octet_count+=2; + /* the next two (after decimal point) will always be zero */ + es += cgmAppNull(es, 2); + octet_count += 2; + } + else + { + if (!cgmcomhead(es, 5, 28, 2)) {free(esp);return 0;} + es += 2; + octet_count = 2; + es+= cgmAppShort(es, edwidth); + octet_count+=2; + } + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->edgewidth = edwidth; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetEdgeColor(cgmImagePtr im, int edcolor) +{ +/* Set the color of the edge of filled-area elements. + * Attribute: Edge Color; Elem Class 5; Elem ID 29 + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Edge Colour (index into the color table) + */ + unsigned char *es, *esp; + int octet_count; + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (edcolor == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (edcolor == im->edgecolor) + { + return 1; + } + + /* Make sure the color they want to use has been allocated. + * also, that color must be non-negative */ + if ((edcolor >= im->colorsTotal ) || (edcolor < 0)) + { + return 0; /* you must allocate a color before you use it */ + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + if (!cgmcomhead(es, 5, 29, 1)) + { + free(esp); + return 0; + } + es += 2; + + *es = 0377 & edcolor; /* mask off last 8 bits and put in es */ + es++; + es += cgmAppNull(es, 1); + + octet_count = 4; /* we just know this; 2 octets of header, + * 1 octet of data, 1 octet of null data */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->edgecolor = (short int) edcolor; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetEdgeVis(cgmImagePtr im, int edvis) +{ +/* Set the visibility of the edge of filled-area elements. + * Attribute: Edge Visibility; Elem Class 5; Elem ID 30 + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Edge Visibility (integer 0 or 1, corresponding to: Off, On) + * Attribute is 16 bit signed int. + */ + unsigned char *es, *esp; + int octet_count, temp; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (edvis == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (edvis == im->edgevis) + { + return 1; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomhead(es, 5, 30, 2)) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + temp = edvis >> 8; + *es = *es | (temp & 0377); + es++; + *es = *es | (edvis & 0377); + es++; + octet_count += 2; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->edgevis = (short int) edvis; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetTextFont(cgmImagePtr im, int font) +{ +/* Attribute: Text Font Index; Elem Class 5; Elem ID 10 + * font is an index into the font table. it can have one of the following + * values: + * 1 Times Roman + * 2 Times Bold + * 3 Times Italic + * 4 Times Bold Italic + * 5 Helvetica + * 6 Helvetica Bold + * 7 Helvetica Italic + * 8 Helvetica Bold Italic + * 9 Courier + * 10 Courier Bold + * 11 Courier Italic + * 12 Courier Bold Italic + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (font == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (font == im->textfont) + { + return 1; + } + + /* Make sure that font is between 1 and the number of fonts */ + if ((font < 1) || (font > im->numfonts)) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if(!cgmcomhead(es, 5, 10, 2)) + { + free(esp); + return 0; + } + es += 2; + + es += cgmAppShort(es, (short int) font); + + octet_count = 4; /* we just know this */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->textfont = (short int) font; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetTextColor(cgmImagePtr im, int color) +{ +/* Attribute: Text Colour ; Elem Class 5; Elem ID 14 + * set the forground color of text + */ + unsigned char *es, *esp; + int octet_count; + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (color == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (color == im->textcolor) + { + return 1; + } + + /* Make sure the color they want to use has been allocated. + * also, that color must be non-negative */ + if ((color >= im->colorsTotal ) || (color < 0)) + { + return 0; /* you must allocate a color before you use it */ + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if(!cgmcomhead(es, 5, 14, 1)) + { + free(esp); + return 0; + } + es += 2; + + *es = 0377 & color; /* mask off last 8 bits and put in es */ + es++; + + octet_count = 4; /* we just know this; 2 octets of header, + * 1 octet of data, 1 octet of null data */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->textcolor = (short int) color; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetTextHeight(cgmImagePtr im, int height) +{ +/* Attribute: Character Height; Elem Class 5; Elem ID 15 + * the height is in the same units as line width + */ + unsigned char *es, *esp; + int octet_count; + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (height == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (height == im->textheight) + { + return 1; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if(!cgmcomhead(es, 5, 15, 2)) + { + free(esp); + return 0; + } + octet_count = 2; es += 2; + + es += cgmAppShort(es, height); + octet_count += 2; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->textheight = height; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetTextPath(cgmImagePtr im, int tpath) +{ +/* Attribute: Text Path; Elem Class 5; Elem ID 17 + * Is one of: + * 0 right -- Means the direction of the character base vector + * 1 left -- means 180 degrees from the character base vector + * 2 up -- means the direction of the character up vector + * 3 down -- means 180 degrees from the character up vector + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (tpath == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (tpath == im->textpath) + { + return 1; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomhead(es, 5, 17, 2)) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + es += cgmAppShort(es, (short int) tpath); + octet_count += 2; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->textpath = (short int) tpath; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +#ifdef VTK_NOT_DEFINED +static int cgmSetTextOrient(cgmImagePtr im, int xup, int yup, int xbase, int ybase) +{ +/* Attribute: Character Orientation; Elem Class 5; Elem ID 16 + * (xbase,ybase) is the run and the rise of the line that the text is + * written along. For regular text at an angle, set xup = -ybase + * and yup = xbase. Setting it to something different will result in + * skewed text (which may be what you want.) Text written from bottom to + * top at a 90 degree angle would have the following parameters + * xup=-1, yup=0, xbase=0, ybase=1 + * + * This function adds the Orientation to the metafile every time. + * It does not follow the normal -1 for no change, although if you + * put in the same numbers it won't re-add it to the meta file. + */ + unsigned char *es, *esp; + int octet_count; + + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + octet_count = 0; + + if (!cgmcomhead(es, 5, 16, 8)) + { + free(esp); + return 0; + } + es +=2; octet_count += 2; + + /* In the metafile it is a 16 bit signed integer */ + /* add xup */ + es += cgmAppShort(es, (short int) xup); + octet_count += 2; + /* add the rest */ + es += cgmAppShort(es, (short int) yup); + octet_count += 2; + es += cgmAppShort(es, (short int) xbase); + octet_count += 2; + es += cgmAppShort(es, (short int) ybase); + octet_count += 2; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} +#endif + +static int cgmSetMarkerType(cgmImagePtr im, int mtype) +{ +/* Attribute: Marker Type; Elem Class 5; Elem ID 6 + * Set the Marker type. Possible values are: + * 1=dot, 2=plus, 3=asterisk, 4=circle, 5=cross + * Even though new ones can be defined, I am limiting lntype to these values + * If you really need more, you can make the proper changes. + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (mtype == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (mtype == im->mtype) + { + return 1; + } + + /* Make sure that mtype is between 1 and 5 */ + if ((mtype < 1) || (mtype > 5)) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomhead(es, 5, 6, 2)) + { + free(esp); + return 0; + } + es += 2; + /* set Param_List_Len to 2 (signed int at index precision) */ + + /* add in the value of mtype */ + //es += cgmAppShort(es, (short int) mtype); + + octet_count = 4; /* we just know this */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->mtype = (short int) mtype; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetMarkerSize(cgmImagePtr im, int msize) +{ +/* Attribute: Marker Size; Elem Class 5; Elem ID 7 + * sets the marker size. with an image of height X with marker size 1 + * the displayed size will be 1/X%. as an example, if you image is + * x=5, y=10, and you set marker size = 1, and draw a marker, the + * resulting marker will cover 20% of horizontal area. + */ + unsigned char *es, *esp; + int octet_count; + + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (msize == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (msize == im->msize) + { + return 1; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + + /*gej: marker size is 32 bit floating point number, 16 bits before the + * decimal, 16 bits after if marker spec is default (1, scaled) + * for absolute mode (0, absolute) it is 16 bit SI */ + if (im->markerspec) + { + if (!cgmcomhead(es, 5, 7, 4)) {free(esp);return 0;} + octet_count = 2; + es += 2; + es += cgmAppShort(es, (short int) msize); + octet_count += 2; + /* the next two (after decimal point) will always be zero */ + es += cgmAppNull(es, 2); + octet_count += 2; + } + else + { + if (!cgmcomhead(es, 5, 7, 4)) + { + free(esp); + return 0; + } + octet_count = 2; + es += 2; + //es += cgmAppShort(es, (short int) msize); + octet_count += 2; + } + + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->msize = msize; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetMarkerColor(cgmImagePtr im, int mcolor) +{ +/* Attribute: Marker Colour; Elem Class 5; Elem ID 8 + * Sets the marker color. mcolor should be an index into the color + * table that you have previously allocated. + */ + unsigned char *es, *esp; + int octet_count; + /* First check and see if the user doesn't want any changes, + * if so, just return success */ + if (mcolor == -1) + { + return 1; + } + + /* Check and see if the value it is being set to is the current + * value, if so, don't make any changes, just return 1 */ + if (mcolor == im->mcolor) + { + return 1; + } + + /* Make sure the color they want to use has been allocated. + * also, that color must be non-negative */ + if ((mcolor >= im->colorsTotal ) || (mcolor < 0)) + { + return 0; /* you must allocate a color before you use it */ + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + + if (!cgmcomhead(es, 5, 8, 1)) {free (esp);return 0;} + es += 2; + + *es = 0377 & mcolor; /* mask off last 8 bits and put in es */ + es++; + + //es += cgmAppNull(es, 1); + + octet_count = 4; /* we just know this; 2 octets of header, + * 1 octet of data, 1 octet of null data */ + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + im->mcolor = (short int) mcolor; + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmSetLineAttrib(cgmImagePtr im, int lntype, int lnwidth, int lncolor) +{ +/* Spits out the attributes of lines. These attributes stay in effect + * until changed, so you don't have to output them every time. + */ + + if (!cgmSetLineType(im, lntype)) + { + return 0; + } + if (!cgmSetLineWidth(im, lnwidth)) + { + return 0; + } + if (!cgmSetLineColor(im, lncolor)) + { + return 0; + } + + return 1; +} + +static int cgmSetShapeFillAttrib(cgmImagePtr im, int instyle, int incolor, int inhatch) +{ +/* Spits out the attributes for the interior of filled-area elements. + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Set the following attributes: + * Interior Style: (integers 0-6, corresponding to: hollow, solid, + * [not pattern], hatch, empty, [not geometric pattern], + * interpolated.) + * Fill Colour: (index into the color table) + * Hatch Index: (integers 1-6, corresponding to: horizontal lines, + * vertical lines, pos. slope parallel lines, + * neg. slope parallel lines, horizontal/vertical + * crosshatch, positive/negative slope crosshatch) + */ + if (!cgmSetFillStyle(im, instyle)) + { + return 0; + } + if (!cgmSetFillColor(im, incolor)) + { + return 0; + } + if (!cgmSetFillHatch(im, inhatch)) + { + return 0; + } + + return 1; +} + +static int cgmSetShapeEdgeAttrib(cgmImagePtr im, int edtype, int edwidth, int edcolor, int edvis) +{ +/* Spits out the attributes for the edges of filled-area elements. It may + * seem logical that these would be the same as the corresponding line + * attributes, but this is not the case. + * These attributes stay in effect until changed, so you don't have to output + * them every time. + * Set the following attributes: + * Edge Type (integers 1-5, corresponding to: solid, dash, dot, + * dash-dot, dash-dot-dot. These are the same as those used + * for line type.) + * Edge Width (should be the same as line width) + * Edge Colour (index into the color table) + * Edge Visibility (integer 0 or 1, corresponding to: Off, On) + */ + if (!cgmSetEdgeType(im, edtype)) + { + return 0; + } + if (!cgmSetEdgeWidth(im, edwidth)) + { + return 0; + } + if (!cgmSetEdgeColor(im, edcolor)) + { + return 0; + } + if (!cgmSetEdgeVis(im, edvis)) + { + return 0; + } + + return 1; +} + +static int cgmSetTextAttrib(cgmImagePtr im, int font, int color, int height) +{ +/* Set the attributes of text. the font is an integer pointer into the + * font list where: + * 1 Times + * 2 Times Bold + * 3 Times Italic + * 4 Times Bold Italic + * 5 Helvetica + * 6 Helvetica Bold + * 7 Helvetica Italic + * 8 Helvetica Bold Italic + * 9 Courier + * 10 Courier Bold + * 11 Courier Italic + * 12 Courier Bold Italic + * color is an index into the colortable which is the color of the text + * size is the approximate size you want the text written in. + */ + + if(!cgmSetTextFont(im, font)) + { + return 0; + } + if(!cgmSetTextColor(im, color)) + { + return 0; + } + if(!cgmSetTextHeight(im, height)) + { + return 0; + } + + return 1; +} + +static int cgmSetMarkerAttrib(cgmImagePtr im, int mtype, int msize, int mcolor) +{ +/* Spits out the attributes of Markers. These attributes stay in effect + * until changed, so you don't have to output them every time. + */ + + if (!cgmSetMarkerType(im, mtype)) + { + return 0; + } + if (!cgmSetMarkerSize(im, msize)) + { + return 0; + } + if (!cgmSetMarkerColor(im, mcolor)) + { + return 0; + } + + return 1; +} + +static int cgmImageDestroy(cgmImagePtr im) +/* gej: should work, unless I make changes to cgmImage Struct */ +{ + if (im->elemlist) + { + free(im->elemlist); + } + if (im->desc) + { + free(im->desc); + } + if (im->fontlist) + { + free(im->fontlist); + } + free(im); + + return 1; +} + +#ifdef VTK_NOT_DEFINED +static int cgmImageColorClosest(cgmImagePtr im, int r, int g, int b) +/* From gd library, see README file for copyright information */ +/* gej: should work unchanged */ +/* gej: 5/96, changed the colors to use short int */ +{ + short int i; + long rd, gd, bd; + int ct = (-1); + long mindist = 0; + for (i=0; (i<(im->colorsTotal)); i++) + { + long dist; + if (im->open[i]) + { + continue; + } + rd = (im->red[i] - r); + gd = (im->green[i] - g); + bd = (im->blue[i] - b); + dist = rd * rd + gd * gd + bd * bd; + if ((i == 0) || (dist < mindist)) + { + mindist = dist; + ct = i; + } + } + return ct; +} +#endif + +static int cgmImageColorClear(cgmImagePtr im) +{ +/* mark all entries in the color table as open */ + short int i; + for (i=0; (i<(cgmMaxColors)); i++) + { + im->open[i] = 1; + } + return 1; +} + +#ifdef VTK_NOT_DEFINED +static int cgmImageColorExact(cgmImagePtr im, int r, int g, int b) +/* From gd library, see README file for copyright information */ +/* gej: should work unchanged */ +/* gej: 5/96, changed colors to work with short ints */ +{ + short int i; + for (i=0; (i<(im->colorsTotal)); i++) + { + if (im->open[i]) + { + continue; + } + if ((im->red[i] == r) && (im->green[i] == g) && (im->blue[i] == b)) + { + return i; + } + } + return -1; +} +#endif + +static int cgmImageAddColorIndex(cgmImagePtr im, int r, int g, int b) +/* adds the specified color to the colortable in the cgmImagePtr. + * does not add it to the cgm file, cgmImageAddColor does. + * do not use either of these two functions, use cgmImageColorAllocate. + */ +{ + short int i; + short int ct = (-1); + for (i=0; (i<(im->colorsTotal)); i++) + { + if (im->open[i]) + { + ct = i; + break; + } + } + if (ct == (-1)) + { + ct = im->colorsTotal; + if (ct == cgmMaxColors) + { + return -1; + } + im->colorsTotal++; + } + im->red[ct] = (short int) r; + im->green[ct] = (short int) g; + im->blue[ct] = (short int) b; + im->open[ct] = (short int) 0; + + return ct; +} + +static int cgmImageAddColor(cgmImagePtr im, int si, int ei) +/* adds colors to the cgm file, gets values from the color table. + * adds all colors from si to ei inclusive. + * Use cgmImageColorAllocate, not this one. + */ +{ + unsigned char *cts, *ctsp; /* GEJ: color table attribute */ + int octet_count; /* GEJ: octet count */ + int numco, curly; + octet_count = 0; + /* + * Attribute: Colour Table; Elem Class 5; Elem ID 34 + * two parameters P1: Starting colour table index (1 octet, UI) + * P2: list of direct colour values 3-tuples (3 one-octet values) + */ + /* G E J: find out how many values are being added */ + if (ei < 0) + { + return -1; /* no colors being added */ + } + numco = ei - si + 1; + + if (( numco > 0) && (numco < 10)) + { + /* we can use the short form of the command */ + /* allocate sufficent space. Should be 32 bits * 10 to be safe*/ + cts = (unsigned char *) calloc(4*10, SIZEOF(unsigned char ) ); + if (!cts) + { + return -1; /* memory allocation failed */ + } + ctsp=cts; + if (!cgmcomhead(ctsp,5,34,(numco*3)+1)) + { + free(cts); + return -1; + } + ctsp +=2; octet_count += 2; + } + else if ((numco > 9) && (numco < 256)) + { + /* we must use the long form of the command */ + /* allocate sufficent space. Should be 32 bits*256 to be safe*/ + cts = (unsigned char *) calloc(256*4, SIZEOF(unsigned char ) ); + if (!cts) + { + return -1; /* memory allocation failed */ + } + ctsp=cts; + if (!cgmcomheadlong(ctsp,5,34,(numco*3)+1)) + { + free(cts); + return -1; + } + ctsp +=4; octet_count += 4; + } + else + { + return -1; + } + + /*ctsp += cgmAppByte(ctsp, (short int) si);*/ + cgmAppByte(ctsp, (short int) si); + ctsp++; + octet_count++; + for (numco = si; numco <= ei; numco++) + { + ctsp += cgmAppByte(ctsp, im->red[numco]); + ctsp += cgmAppByte(ctsp, im->green[numco]); + ctsp += cgmAppByte(ctsp, im->blue[numco]); + octet_count +=3; + } + + curly = 4 - (octet_count % 4); + if (curly % 4) + { + octet_count += curly; + //ctsp += cgmAppNull(ctsp, curly); + } + /* add it to the buffer */ + if (cgmAddElem(im, cts, octet_count)) + { + free(cts); + return 1; + } + else + { + free(cts); + return -1; + } +} + +static int cgmImageColorAllocate(cgmImagePtr im, int r, int g, int b) +/* From gd library, see README file for copyright information + * gej: modified to allocate the color in the CGM buffer as well + * as the color table */ +/* gej: 5/96, modified to use short ints for colors */ +{ + short int ct; + ct = cgmImageAddColorIndex(im, r, g, b); + if (ct == -1) + { + return -1; + } + /* GEJ: w we have successfully alocated it in the color table + * so let's put it in the CGM as well. + */ + if (cgmImageAddColor(im, ct, ct) == -1 ) + { + return -1; + } + else + { + return ct; + } +} + +#ifdef VTK_NOT_DEFINED +static int cgmImageColor16(cgmImagePtr im) +{ + int si, ei, li; + si = cgmImageAddColorIndex(im, 255, 255, 255); + if (si == -1) + { + return 0; + } + li = -1; ei=si; + ei = cgmImageAddColorIndex(im, 0, 0, 0); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 128, 0, 0); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 0, 128, 0); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 128, 128, 0); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 0, 0, 128); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 128, 0, 128); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 0, 128, 128); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 128, 128, 128); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 192, 192, 192); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 255, 0, 0); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 0, 255, 0); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 255, 255, 0); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 0, 0, 255); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 255, 0, 255); + if (ei != -1) + { + li = ei; + } + ei = cgmImageAddColorIndex(im, 0, 255, 255); + if (ei != -1) + { + li = ei; + } + if (ei == -1) + { + ei = li; + } + if(cgmImageAddColor(im,si,ei) == -1) + { + return -1; + } + else + { + return ei; + } +} + +static int cgmImageColorDeallocate(cgmImagePtr vtkNotUsed(im), int vtkNotUsed(color)) +/* wogl: the parameter names are commented to avoid compiler warnings */ +/* From gd library, see README file for copyright information */ +/* gej: should work unchanged */ +{ + /* Mark it open. */ + /*im->open[color] = 1;*/ + /* gej: really can't work, we are not allowing redefinition + * of color table entries */ + return 0; +} +#endif + +static int cgmImageColorGet(cgmImagePtr im, int cgmIndex, + int& r, int& g, int& b) +{ + cgmIndex = (cgmIndex >= cgmMaxColors ? cgmMaxColors-1 : cgmIndex); + r = im->red[cgmIndex]; + g = im->green[cgmIndex]; + b = im->blue[cgmIndex]; + + return 1; +} + +#ifdef VTK_NOT_DEFINED +static int cgmLine(cgmImagePtr im, int x1, int y1, int x2, int y2) +/* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1 + * Actually generate the line, if you are writing a program to use this + * library, use this function, not cgmImageLine or cgmImageDashedLine, + * those are just in for compatiblilty with gd + * + * This function will draw a line using the current line type, width, and color + */ +{ + unsigned char *es, *esp; + int octet_count; + short int sweet; + short int sour; + + /* check to make sure the line is withing the scope of the picture + * ie. the values you give for drawing the line are within + * the values you created the picture with */ + if (!(cgmImageBoundsSafe(im, x1,y1)) || !(cgmImageBoundsSafe(im, x2,y2))) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomhead(es, 4, 1, 8)) + { + free(esp); + return 0; + } + es += 2; + octet_count = 2; + + /* now we are ready for the parameter data */ + sweet = (short int) x1; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) y1; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) x2; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) y2; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + octet_count++; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmMarker(cgmImagePtr im, int x, int y) +/* Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3 + * puts a marker in the file, it will have characteristics set by + * cgmSetMarkerAttrib + */ +{ + unsigned char *es, *esp; + int octet_count; + + /* check to make sure the line is withing the scope of the picture + * ie. the values you give for drawing the line are within + * the values you created the picture with */ + if (!cgmImageBoundsSafe(im, x,y) ) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomhead(es, 4, 3, 4)) + { + free(esp); + return 0; + } + es += 2; + octet_count = 2; + + octet_count += cgmAppShort(es, (short int) x); + es += 2; + octet_count += cgmAppShort(es, (short int) y); + es += 2; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2) +{ +/* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11 + * Actually generate the rectangle, if you are writing a program to use this + * library, use this function, not cgmImageRectangle, + * those are just in for compatiblilty with gd + * + * This function will draw a Rectangle using the current + * edge type, width, color, and visibility, and the current + * fill style, color, and hatch + */ + unsigned char *es, *esp; + int octet_count; + short int sweet; + short int sour; + + /* check to make sure the line is withing the scope of the picture + * ie. the values you give for drawing the line are within + * the values you created the picture with */ + if (!(cgmImageBoundsSafe(im, x1,y1)) || !(cgmImageBoundsSafe(im, x2,y2))) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* their are four 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 11, 8)) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + /* now we are ready for the parameter data */ + sweet = (short int) x1; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) y1; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) x2; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) y2; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + octet_count++; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmCircle(cgmImagePtr im, int cx, int cy, int r) +{ +/* Graphic Primitive: circle; Elem Class 4; Elem ID 12 + * cx,cy is the center of the circle, r is the radius + * + * This function will draw a Circle using the current + * edge type, width, color, and visibility, and the current + * fill style, color, and hatch + */ + unsigned char *es, *esp; + int octet_count; + short int sweet; + short int sour; + + /* check to make sure the circle is withing the scope of the picture + * ie. the values you give for drawing the circle are within + * the values you created the picture with */ + if (!(cgmImageBoundsSafe(im, cx,cy))) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* their are three 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 12, 6)) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + /* now we are ready for the parameter data */ + sweet = (short int) cx; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) cy; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) r; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + octet_count++; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmArc3Pt(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey) +{ +/* Graphic Primitive: Cicular Arc 3 Point; Elem Class 4; Elem ID 13 + * + * This function will draw a Circular Arc using the current + * Line type, width, and color, + */ + unsigned char *es, *esp; + int octet_count; + short int sweet; + short int sour; + + /* check to make sure the line is withing the scope of the picture + * ie. the values you give for drawing the line are within + * the values you created the picture with */ + if (!(cgmImageBoundsSafe(im, sx,sy)) || !(cgmImageBoundsSafe(im, ix,iy)) || !(cgmImageBoundsSafe(im, ex, ey))) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* their are six 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 13, 12)) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + /* now we are ready for the parameter data */ + sweet = (short int) sx; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) sy; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) ix; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) iy; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) ex; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + es++; octet_count++; + sweet = (short int) ey; + sour = sweet >> 8; + *es = *es | (sour & 0377); + es++; octet_count++; + *es = (unsigned char) sweet; + octet_count++; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmArc3PtClose(cgmImagePtr im, int sx,int sy, int ix,int iy, int ex,int ey, int cl) +{ +/* Graphic Primitive: Cicular Arc 3 Point Close; Elem Class 4; Elem ID 14 + * + * This function will draw a Circle using the current + * edge type, width, color, and visibility, and the current + * fill style, color, and hatch + * + * cgm is the closure type. It can be either 0 for pie closure or + * 1 for chord closure. + */ + unsigned char *es, *esp; + int octet_count; + + /* check to make sure the line is withing the scope of the picture + * ie. the values you give for drawing the line are within + * the values you created the picture with */ + if (!(cgmImageBoundsSafe(im, sx,sy)) || !(cgmImageBoundsSafe(im, ix,iy)) || !(cgmImageBoundsSafe(im, ex, ey))) + { + return 0; + } + + /* make sure that they close the arc either with pie (0) or chord (1) */ + if ((cl != 0) && (cl != 1)) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 6 to be safe */ + es = (unsigned char *) calloc(4*6, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* their are seven 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 14, 14)) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + /* now we are ready for the parameter data */ + octet_count += cgmAppShort(es, (short int) sx); + es +=2; + octet_count += cgmAppShort(es, (short int) sy); + es +=2; + octet_count += cgmAppShort(es, (short int) ix); + es +=2; + octet_count += cgmAppShort(es, (short int) iy); + es +=2; + octet_count += cgmAppShort(es, (short int) ex); + es +=2; + octet_count += cgmAppShort(es, (short int) ey); + es +=2; + octet_count += cgmAppShort(es, (short int) cl); + es +=2; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmEllipse(cgmImagePtr im, int cx,int cy, int d1x,int d1y, int d2x,int d2y ) +{ +/* Graphic Primitive: Ellipse; Elem Class 4; Elem ID 17 + * + * This function will draw an Ellipse using the current + * edge type, width, color, and visibility, and the current + * fill style, color, and hatch + */ + unsigned char *es, *esp; + int octet_count; + + /* check to make sure the line is withing the scope of the picture + * ie. the values you give for drawing the line are within + * the values you created the picture with */ + if (!(cgmImageBoundsSafe(im, cx,cy)) || !(cgmImageBoundsSafe(im, d1x,d1y)) || !(cgmImageBoundsSafe(im, d2x, d2y))) + { + return 0; + } + + /* allocate sufficent space. should be 32 bits * 4 to be safe */ + es = (unsigned char *) calloc(4*4, SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* their are six 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 17, 12)) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + /* now we are ready for the parameter data */ + octet_count += cgmAppShort(es, (short int) cx); + es +=2; + octet_count += cgmAppShort(es, (short int) cy); + es +=2; + octet_count += cgmAppShort(es, (short int) d1x); + es +=2; + octet_count += cgmAppShort(es, (short int) d1y); + es +=2; + octet_count += cgmAppShort(es, (short int) d2x); + es +=2; + octet_count += cgmAppShort(es, (short int) d2y); + es +=2; + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} +#endif + +static int cgmPolygon(cgmImagePtr im, cgmPointPtr p, int n) +{ +/* Graphic Primitive: Polygon; Elem Class 4; Elem ID 7 + * + * cgmPointPtr is defined in cgm.h, basically, it is two arrays of integers + * p[m].x and p[m].y containing the x and y values respectively. n + * is the number of points in this array (not the index of the last point, + * which is n-1). n must be at least 3 (otherwise + * you really don't have much of a polygon, it is closer to a line.) + * + * This function will draw a Polygon using the current + * edge type, width, color, and visibility, and the current + * fill style, color, and hatch + */ + unsigned char *es, *esp; + int octet_count; + int x; /* counter */ + + if (n < 3) + { + return 0; /* it is either a point or a line */ + } + + if (n < 8) + { + /* It fits in the short form of the command, lets us + * add it right now, shall we? */ + /* allocate sufficent space. Should be 32 bits*10 to be safe */ + es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* their are n*2 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 7, (n*4))) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + } + else if (n < 8191) + { + /* there are more than 7 points in it, that sucks */ + /* gej, so basically, for this one, I set the header + * to cgmcomhead(es, 4, 7, 31) then write a function for the long + * form that takes the first 15 bits of n and tags a 0 in front + * of it and puts it in es, than I do the for loop all over again + * that doesn't seem too hard. But I will leave that for another + * day. + * keep in mind that if CGMGROWLISTSIZE is smaller than n*4 + * (at most 32769) then things could fail in a most unsavory fashion. + */ + /* allocate sufficent space. 32 bits*(n+1) to be safe */ + es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomheadlong(es, 4, 7, (n*4))) + { + free(esp); + return 0; + } + es +=4; octet_count = 4; + } + else + { + /* there are more than 8191 points in it, I am not going to implement + * that, if you want it that bad, do it yourself. */ + return 0; + } + + for (x=0; xx); + es += cgmAppShort(es, (short int) p->y); + octet_count += 4; + p++; + } + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +#ifdef VTK_NOT_DEFINED +static int cgmPolygonSet(cgmImagePtr im, cgmPointPtr p, int n) +{ +/* Graphic Primitive: Polygon; Elem Class 4; Elem ID 8 + * + * cgmPointPtr is defined in cgm.h, basically, it is three arrays of integers + * p[m].x and p[m].y containing the x and y values respectively and p[m].e + * the characteristics of the line leaving point n (0=invisible,1=visible, + * 2=close,invisible, 3=close,visible). n is the number of points in this + * array (not the index of the last point, which is n-1). + * n must be at least 3 (otherwise you really don't have much of a polygon, + * it is closer to a line.) + * + * This function will draw a set of Polygons using the current + * edge type, width, color, and the current + * fill style, color, and hatch + */ + unsigned char *es, *esp; + int octet_count; + int x; /* counter */ + + if (n < 3) + { + return 0; /* it is either a point or a line */ + } + + if (n < 6) + { + /* It fits in the short form of the command, lets us + * add it right now, shall we? */ + /* allocate sufficent space. Should be 48 bits*10 to be safe */ + es = (unsigned char *) calloc(6*10,SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + + /* their are n*2 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 8, (n*6))) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + } + else if (n < 5462) + { + /* there are more than 5 points in it, that sucks */ + /* gej, so basically, for this one, I set the header + * to cgmcomhead(es, 4, 7, 31) then write a function for the long + * form that takes the first 15 bits of n and tags a 0 in front + * of it and puts it in es, than I do the for loop all over again + * that doesn't seem too hard. But I will leave that for another + * day. + * keep in mind that if CGMGROWLISTSIZE is smaller than n*6 + * (at most 32769) then things could fail in a most unsavory fashion. + */ + /* allocate sufficent space. 48 bits*(n+1) to be safe */ + es = (unsigned char *) calloc(6*(n+1), SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomheadlong(es, 4, 8, (n*6))) + { + free(esp); + return 0; + } + es +=4; octet_count = 4; + } + else + { + /* there are more than 5462 points in it, I am not going to implement + * that, if you want it that bad, do it yourself. */ + return 0; + } + + for (x=0; xx); + es += cgmAppShort(es, (short int) p->y); + es += cgmAppShort(es, (short int) p->e); + octet_count += 6; + p++; + } + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} +#endif + +static int cgmPolyLine(cgmImagePtr im, cgmPointPtr p, int n) +{ +/* Graphic Primitive: Polyline; Elem Class 4; Elem ID 1 + * + * cgmPointPtr is defined in cgm.h, basically, it is two arrays of integers + * p[m].x and p[m].y containing the x and y values respectively. n + * is the number of points in this array (not the index of the last point, + * which is n-1). if n is 2, it is a regular line, like cgmline + * + * This function will draw a Polyline using the current + * line type, width, color, and visibility, + */ + unsigned char *es, *esp; + int octet_count; + int x; /* counter */ + + if (n < 2) + { + return 0; /* it is a point */ + } + + if (n < 8) + { + /* It fits in the short form of the command, lets us + * add it right now, shall we? */ + /* allocate sufficent space. Should be 32 bits*10 to be safe */ + es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + /* their are n*2 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 1, (n*4))) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + } + else if (n < 8191) + { + /* there are more than 7 points in it, that sucks */ + /* gej, so basically, for this one, I set the header + * using the long version cgmcomheadlong(es, 4, 1, n*4) + * keep in mind that if CGMGROWLISTSIZE is smaller than n*4 + * (at most 32769) then the list may have to grow several times + */ + /* allocate sufficent space. 32 bits*(n+1) to be safe */ + es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomheadlong(es, 4, 1, (n*4))) + { + free(esp); + return 0; + } + es +=4; octet_count = 4; + } + else + { + /* there are more than 8191 points in it, I am not going to implement + * that, if you want it that bad, do it yourself. */ + return 0; + } + + for (x=0; xx); + es += cgmAppShort(es, (short int) p->y); + octet_count += 4; + p++; + } + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmPolyMarker(cgmImagePtr im, cgmPointPtr p, int n) +{ +/* Graphic Primitive: PolyMarker; Elem Class 4; Elem ID 3 + * + * cgmPointPtr is defined in cgm.h, basically, it is two arrays of integers + * p[m].x and p[m].y containing the x and y values respectively. n + * is the number of points in this array (not the index of the last point, + * which is n-1). if n is 2, it is a regular line, like cgmline + * + * This function will insert n markers using the current + * Marker type, width, color, and visibility, + */ + unsigned char *es, *esp; + int octet_count; + int x; /* counter */ + + if (n < 1) + { + return 0; /* it is nothing */ + } + if (n < 8) + { + /* It fits in the short form of the command, lets us + * add it right now, shall we? */ + /* allocate sufficent space. Should be 32 bits*10 to be safe */ + es = (unsigned char *) calloc(4*10,SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + + /* their are n*2 16 bit signed integers as attributes */ + if (!cgmcomhead(es, 4, 3, (n*4))) + { + free(esp); + return 0; + } + es +=2; octet_count = 2; + + } + else if (n < 8191) + { + /* there are more than 7 points in it, that sucks */ + /* gej, so basically, for this one, I set the header + * using the long version cgmcomheadlong(es, 4, 1, n*4) + * keep in mind that if CGMGROWLISTSIZE is smaller than n*4 + * (at most 32769) then the list may have to grow several times + */ + /* allocate sufficent space. 32 bits*(n+1) to be safe */ + es = (unsigned char *) calloc(4*(n+1), SIZEOF(unsigned char )); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomheadlong(es, 4, 3, (n*4))) + { + free(esp); + return 0; + } + es +=4; octet_count = 4; + } + else + { + /* there are more than 8191 points in it, I am not going to implement + * that, if you want it that bad, do it yourself. */ + return 0; + } + + for (x=0; xx); + es += cgmAppShort(es, (short int) p->y); + octet_count += 4; + p++; + } + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +#ifdef VTK_NOT_DEFINED +static int cgmText(cgmImagePtr im, int x, int y, const char *ts) +{ +/* Graphic Primitive: Text; Elem Class 4; Elem ID 4 + * add text to the picture. Start it at the point (x,y) + * this should be the lower left corner of where the text is + * the parameters are point, enumerated(set to 1), string + * + * String encoding in CGM is a little strange. After you have the other + * parameter info, the first octet for the string is either 0..254 which + * is the number of octets of string data, or 255 which signifies a long + * string. if it is 255 then the next 16 bits indicate the length of the + * string. the first bit (bit15) is 0 if this is the last part of the + * string and 1 if another part follows it. the next 15 bits are in the + * range 0..32767 and are the number of octets of string info following. + * so the length stored in the command header is the whole enchelada. + */ + int tslen, curly; + unsigned char *es, *esp; + int octet_count; + + /* check to make sure the Text is within the scope of the picture + * actually, I am only checking the start of it + */ + if (!(cgmImageBoundsSafe(im, x, y))) + { + return 0; + } + + /* allocate sufficent space. should be tslen+ 32 bits * 4 to be safe */ + tslen = strlen(ts); + + /* if there are more than 32700 characters fail + * gej: this could go as high as 32767 I think, but lets + * cut it off at 32700 */ + if ((tslen > 32700) || (tslen < 0)) + { + return 0; + } + + es = (unsigned char *) calloc( ((4*4)+tslen), SIZEOF(unsigned char ) ); + if (!es) + { + return 0; /* memory allocation failed */ + } + esp=es; + + if (!cgmcomheadlong(es, 4, 4, 9+tslen)) + { + free(esp); + return 0; + } + es +=4; octet_count = 4; + + /* add the x position, the y position, then 1, which signifies + * that this is all the text, there is none appended after it */ + es += cgmAppShort(es, (short int) x); + es += cgmAppShort(es, (short int) y); + es += cgmAppShort(es, (short int) 1); + octet_count += 6; + + /* now take care of the string information, for strings 254 bytes + * or less, I could use a short one, but why bother, use the long + * form for everything */ + es += cgmAppByte(es, (short int) 255); + es += cgmAppShort(es, (short int) tslen); + octet_count += 3; + /* gej: I should set bit 15 to 0 because it is the final part of a + * string but I am not going to since I already checked that it was + * a 16 number that was non-negative */ + + while(*ts) + { + *es++ = (unsigned char) *ts++; + } + octet_count +=tslen; + /* now if the octet_count is not divisible by 4 add null padding */ + curly = 4 - (octet_count % 4); + if (curly % 4) + { + octet_count += curly; + es += cgmAppNull(es, curly); + } + + /* add it to the buffer */ + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmImageLine(cgmImagePtr im, int x1, int y1, int x2, int y2, int color) +/* gej: this should be so much easier to do as a cgm + * This is in for compatibility with gd, if you don't need that, use + * cgmLine instead */ +{ + int ltstate; + + /* save the linetype state */ + ltstate = im->ltype; + /* set the attributes of the line */ + if (!cgmSetLineAttrib(im, 1, -1, color)) + { + return 0; + } + if (!cgmLine(im, x1, y1, x2, y2)) + { + return 0;/* draw the line */ + } + /* restore the state If it fails, don't return an error, because + * the line was still drawn */ + cgmSetLineType(im, ltstate); + + return 1; +} + +static int cgmImageDashedLine(cgmImagePtr im, int x1, int y1, int x2, int y2, int color) +/* gej: this should be so much easier to do as a cgm + * in order to really get a dashed line you must call cgmSetLineType first + * This is in for compatibility with gd, if you don't need that, use + * cgmLine instead */ +{ + /* set the attributes of the line */ + if (!cgmSetLineAttrib(im, -1, -1, color)) + { + return 0; + } + /* generate the line */ + if (!cgmLine(im, x1, y1, x2, y2)) + { + return 0; + } + + /* everthing is A-OK */ + return 1; +} + +static int cgmImageBoundsSafe(cgmImagePtr im, int x, int y) +/* From gd library, see README file for copyright information */ +/* gej: this should work unchanged */ +{ + return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx)))); +} + + +static int cgmImageRectangle(cgmImagePtr im, int x1, int y1, int x2, int y2, int color) +/* Graphic Primitive: rectangle; Elem Class 4; Elem ID 11 + */ + +/* gej: but I think I will use the cgm rectangle */ +{ + if(!cgmImageLine(im, x1, y1, x2, y1, color)) + { + return 0; + } + if(!cgmImageLine(im, x1, y2, x2, y2, color)) + { + return 0; + } + if(!cgmImageLine(im, x1, y1, x1, y2, color)) + { + return 0; + } + if(!cgmImageLine(im, x2, y1, x2, y2, color)) + { + return 0; + } + + return 1; +} +#endif + + +/* Expert functions. If you need more control, you can use these + * functions, but you probably won't need to. */ + +static int cgmImageSetSize(cgmImagePtr im, int x, int y) +/* sets the width and height of subsequent pictures. */ +{ + im->sx = x; + im->sy = y; + return 1; +} + +#ifdef VTK_NOT_DEFINED +static int cgmImageSetLineSpec(cgmImagePtr im, int specmode) +/* Picture Descriptor: Line Width Specification Mode; Elem Class 2; Elem ID 3*/ +/* sets the Line Width Specification mode of subsequent pictures. + * 1 is scaled (default), 2 is absolute */ +{ + if ((specmode < 0) || (specmode > 2)) + { + return 0; + } + im->linespec = specmode; + return 1; +} + +static int cgmImageSetMarkerSpec(cgmImagePtr im, int specmode) +/* Picture Descriptor: Marker Size Specification Mode; Elem Class 2; Elem ID 4*/ +/* sets the Marker Width Specification mode of subsequent pictures. + * 1 is scaled (default), 2 is absolute */ +{ + if ((specmode < 0) || (specmode > 2)) + { + return 0; + } + im->linespec = specmode; + return 1; +} + +static int cgmImageSetEdgeSpec(cgmImagePtr im, int specmode) +/* Picture Descriptor: Edge Width Specification Mode; Elem Class 2; Elem ID 5*/ +/* sets the Edge Width Specification mode of subsequent pictures. + * 1 is scaled (default), 2 is absolute */ +{ + if ((specmode < 0) || (specmode > 2)) + { + return 0; + } + im->edgespec = specmode; + return 1; +} +#endif + +static int cgmImageSetOutput(cgmImagePtr im, FILE *output) +/* sets the output file to *output. which must already be open. + * does not close the file + * Useful if you want to write the file as you go along, or if you + * want to write it to a stream + */ +{ + if(output) + { + im->outfile = output; + return 1; + } + else + { + return 0; + } +} + +#ifdef VTK_NOT_DEFINED +static int cgmImageAddFont(cgmImagePtr im, const char *fontname) +/* adds a font to the list of fonts. This only has an effect + * if you are using the expert functions for starting pictures, and + * have not yet opened the first picture. Returns 0 for failure, + * and the font index on success */ +{ + unsigned char *oldfonts; + int listsize; + oldfonts = im->fontlist; + if (oldfonts) + { + listsize = strlen( (char *)oldfonts) + 1 + strlen(fontname) + 1; + } + else + { + listsize = strlen(fontname) +1; + } + im->fontlist=(unsigned char *) calloc(listsize,SIZEOF(unsigned char)); + if (!im->fontlist) + { + return 0; /* memory allocation failed */ + } + if (oldfonts) + { + sprintf((char *)im->fontlist, "%s%s%s", (char *)oldfonts, ",", fontname); + } + else + { + sprintf((char *)im->fontlist, "%s", fontname); + } + im->numfonts++; + if (oldfonts) + { + free(oldfonts); + } + oldfonts = NULL; + return im->numfonts; +} + +static int cgmImageClearFonts(cgmImagePtr im) +/* clears out ALL fonts from the font list, including the ones the + * package has be default. Useful if you want totally different fonts. + */ +{ + free(im->fontlist); + im->fontlist = NULL; + im->numfonts = 0; + return 1; +} +#endif + +static int cgmImageSetDefaults(cgmImagePtr im) +/* resets the defaults to what is in defines.h */ +{ + /* you must be either before any picture has been created, + * or after a picture has closed to call this */ + if ((im->state != 0) && (im->state != 2)) + { + return 0; + } + /* set line_width, line_height, line_color to the defaults */ + im->ltype = CGMLTYPE; + im->lwidth = CGMLWIDTH; + im->lcolor = CGMLCOLOR; + /* interior_style, fill_color, hatch_index */ + im->shapestyle = CGMSHAPESTYLE; + im->shapecolor = CGMSHAPECOLOR; + im->shapehatch = CGMSHAPEHATCH; + /* edge_type, edge_width, edge_color, edge_visibility */ + im->edgetype = CGMEDGETYPE; + im->edgecolor = CGMEDGECOLOR; + im->edgewidth = CGMEDGEWIDTH; + im->edgevis = CGMEDGEVIS; + /* text_color, text_height, text_font */ + im->textcolor = CGMTEXTCOLOR; + im->textheight = CGMTEXTHEIGHT; + im->textfont = CGMTEXTFONT; + im->textpath = CGMTEXTPATH; + /* set marker_width, marker_size, marker_color to the defaults */ + im->ltype = CGMMTYPE; + im->lwidth = CGMMSIZE; + im->lcolor = CGMMCOLOR; + /* this is set by the expert functions. the defaults should be ok */ + im->linespec = CGMLINESPEC; + im->edgespec = CGMEDGESPEC; + im->markerspec = CGMMARKERSPEC; + + return 1; +} + +static cgmImagePtr cgmImageStartCgm() +/* initializes the CGM and sets up the defaults. If you are using + * the "expert" functions, you should call this first. _ge */ +{ + const char *tmps; + int tmpsl; + cgmImagePtr im; + im = (cgmImage *) calloc(SIZEOF(cgmImage), 1); + if (!im) + { + return 0; /* memory allocation failed */ + } + /* elemlist is set to some number, when it is full, make it bigger */ + im->elemlist = (unsigned char *) calloc(CGMSTARTLISTSIZE, SIZEOF(unsigned char ) ); + if (!im->elemlist) + { + free(im); + return 0; + } /* memory allocation failed */ + im->colorsTotal = 0; + /* you can have multiple pictures in a file, keep track of + * which one you are on */ + im->picnum = 0; + im->outfile = NULL; + /* the next three are used for maintaining the element list + * don't change these ever */ + im->bytestoend = CGMSTARTLISTSIZE; + im->listlen = CGMSTARTLISTSIZE; + im->curelemlist = im->elemlist; + + /* don't make this longer than 250 characters */ + tmps = "vtk CGM Output file"; + tmpsl = (int)strlen(tmps); + if (tmpsl >250) + { + tmpsl = 250; + } + im->desc = (unsigned char *) calloc(tmpsl+1, SIZEOF(unsigned char)); + strncpy((char*)im->desc, tmps, tmpsl); + /* The font list can be quite long, but individual font names can + * can only be 250 chars */ + tmps = "TIMES_ROMAN,TIMES_BOLD,TIMES_ITALIC,TIMES_BOLD_ITALIC,HELVETICA,HELVETICA_BOLD,HELVETICA_ITALIC,HELVETICA_BOLD_ITALIC,COURIER,COURIER_BOLD,COURIER_ITALIC,COURIER_BOLD_ITALIC"; + im->numfonts=12; + tmpsl = (int)strlen(tmps); + im->fontlist = (unsigned char *) calloc(tmpsl+1, SIZEOF(unsigned char)); + strcpy((char*)im->fontlist, tmps); + im->outfile = NULL; + + if (!cgmImageSetDefaults(im)) + { + cgmImageDestroy (im); + } + /* set the state */ + im->state = 0; /* 0 no pictures started, 1 in a picture, + * 2 after a picture */ + + return im; +} + +static int cgmImageEndPic(cgmImagePtr im) +/* close the current picture */ +{ + unsigned char *es, *esp; + int octet_count=0; + + /* make sure we are really in a picture before ending it */ + if (im->state != 1) + { + return 0; + } + + esp = (unsigned char *) calloc(1024, SIZEOF(unsigned char )); + if (!esp) + { + return 0; /* memory allocation failed */ + } + es=esp; + + /* Attribute: End Picture; Elem Class 0; Elem ID 5; Length 0 */ + if (!cgmcomhead(es, 0, 5, 0)) + { + free(esp); + return 0; + } + octet_count += 2; + + if (cgmAddElem(im, esp, octet_count)) + { + free(esp); + im->state=2; + return 1; + } + else + { + free(esp); + return 0; + } +} + +static int cgmImageEndCgm (cgmImagePtr im) +/* close the current CGM file. If an output stream is + * defined, write the CGM to it */ +{ + int x; /* counter */ + int used; /* number of bytes used in the list */ + unsigned char *efile, *efilep; /* end of file information */ + + cgmImageEndPic(im); + if (im->state == 2) + { /* We have closed the pic, but not the CGM */ + efile = (unsigned char *) calloc(4*4,SIZEOF(unsigned char )); + if (!efile) + { + return 0; /* memory allocation failed */ + } + efilep=efile; + /* Attribute: End Metafile; Elem Class 0; Elem ID 2 */ + cgmcomhead(efilep, 0, 2, 0); + + if (cgmAddElem(im, efile, 2)) + { + free(efile); + } + else + { + free(efile); + return 0; + } + } + + if (im->outfile) + { + /* now output the CGM, one byte at a time */ + used = im->listlen - im->bytestoend; + for (x=0;x < used; x++) + { + putc((unsigned char) im->elemlist[x], im->outfile); + } + } /* else do nothing */ + + return 1; +} diff --git a/IO/vtkCGMWriter.h b/IO/vtkCGMWriter.h new file mode 100644 index 0000000..ac61648 --- /dev/null +++ b/IO/vtkCGMWriter.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCGMWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCGMWriter - write polygonal data as a CGM file +// .SECTION Description +// vtkCGMWriter writes CGM (Computer Graphics Metafile) output. CGM is a 2D +// graphics vector format typically used by large plotters. This writer can +// handle vertices, lines, polygons, and triangle strips in any combination. +// Colors are specified either 1) from cell scalars (assumed to be RGB or +// RGBA color specification), 2) from a specified color; or 3) randomly +// assigned colors. +// +// Note: During output of the polygonal data, triangle strips are converted +// to triangles, and polylines to lines. Also, due to limitations in the CGM +// color model, only 256 colors are available to the color palette. + +// .SECTION Caveats +// The class vtkImageToPolyDataFilter is convenient for converting a raster +// image into polygons (and color map) suitable for plotting with CGM. + +// .SECTION See Also +// vtkPolyDataWriter vtkPointDataToCellData + + +#ifndef __vtkCGMWriter_h +#define __vtkCGMWriter_h + +#include "vtkPolyDataWriter.h" + +class vtkViewport; + +#define VTK_COLOR_MODE_DEFAULT 0 +#define VTK_COLOR_MODE_SPECIFIED_COLOR 1 +#define VTK_COLOR_MODE_RANDOM_COLORS 2 + +class VTK_IO_EXPORT vtkCGMWriter : public vtkPolyDataWriter +{ +public: + // Description: + // Instantiate with no viewport defined and sorting on. The default + // resolution is 10,000, and the color mode is set to default. + static vtkCGMWriter *New(); + + vtkTypeRevisionMacro(vtkCGMWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify a vtkViewport object to be used to transform the vtkPolyData + // points into 2D coordinates. By default (no vtkViewport specified), the + // point coordinates are generated by ignoring the z values. If a viewport + // is defined, then the points are transformed into viewport coordinates. + virtual void SetViewport(vtkViewport*); + vtkGetObjectMacro(Viewport, vtkViewport); + + // Description: + // Turn on/off the sorting of the cells via depth. If enabled, polygonal + // cells will be sorted from back to front, i.e., a Painter's algorithm + // sort. + vtkSetMacro(Sort,int); + vtkGetMacro(Sort,int); + + // Description: + // Specify the resolution of the CGM file. This number is used to integerize + // the maximum coordinate range of the plot file. + vtkSetClampMacro(Resolution, int, 100, VTK_LARGE_INTEGER); + vtkGetMacro(Resolution, int); + + // Description: + // Control how output polydata is colored. By default (ColorModeToDefault), + // if per cell colors are defined (unsigned chars of 1-4 components), then + // the cells are colored with these values. (If point colors are defined + // and cell colors are not, you can use vtkPointDataToCellData to convert + // the point colors to cell colors.) Otherwise, by default, the cells are + // set to the specified color. If ColorModeToSpecifiedColor is set, then + // the primitives will all be set to this color. If ColorModeToRandomColors + // is set, each cell will be randomly assigned a color. + vtkSetMacro(ColorMode,int); + vtkGetMacro(ColorMode,int); + void SetColorModeToDefault() { + this->SetColorMode(VTK_COLOR_MODE_DEFAULT);}; + void SetColorModeToSpecifiedColor() { + this->SetColorMode(VTK_COLOR_MODE_SPECIFIED_COLOR);}; + void SetColorModeToRandomColors() { + this->SetColorMode(VTK_COLOR_MODE_RANDOM_COLORS);}; + + // Description: + // Set/Get the specified color to color the polydata cells. This + // color is only used when the color mode is set to + // ColorModeToSpecifiedColor, or ColorModeToDefault is set and no + // cell colors are specified. The specified color is specified as RGB + // values ranging from (0,1). (Note: CGM will map this color to the + // closest color it supports.) + vtkSetVector3Macro(SpecifiedColor,float); + vtkGetVectorMacro(SpecifiedColor,float,3); + +protected: + vtkCGMWriter(); + ~vtkCGMWriter(); + void WriteData(); + + vtkViewport *Viewport; + int ColorMode; + float SpecifiedColor[3]; + int Resolution; + int Sort; + +private: + vtkCGMWriter(const vtkCGMWriter&); // Not implemented. + void operator=(const vtkCGMWriter&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkChacoReader.cxx b/IO/vtkChacoReader.cxx new file mode 100644 index 0000000..bf11288 --- /dev/null +++ b/IO/vtkChacoReader.cxx @@ -0,0 +1,1480 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkChacoReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include +#include +#include "vtkChacoReader.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include "vtkDoubleArray.h" +#include "vtkInformation.h" +#include "vtkInformationDoubleVectorKey.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkChacoReader, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkChacoReader); + +//---------------------------------------------------------------------------- +// Description: +// Instantiate object with NULL filename. +vtkChacoReader::vtkChacoReader() +{ + this->BaseName = NULL; + this->GenerateGlobalElementIdArray = 1; + this->GenerateGlobalNodeIdArray = 1; + this->GenerateVertexWeightArrays = 0; + this->GenerateEdgeWeightArrays = 0; + this->EarrayName = NULL; + this->VarrayName = NULL; + this->Dimensionality = -1; + this->NumberOfVertices = 0; + this->NumberOfEdges = 0; + this->NumberOfVertexWeights = 0; + this->NumberOfEdgeWeights = 0; + this->GraphFileHasVertexNumbers = 0; + + this->NumberOfPointWeightArrays = 0; + this->NumberOfCellWeightArrays = 0; + + this->CurrentGeometryFP = NULL; + this->CurrentGraphFP = NULL; + this->CurrentBaseName = NULL; + + this->DataCache = vtkUnstructuredGrid::New(); + this->RemakeDataCacheFlag = 1; + + this->Line_length = 200; + this->Line = new char [200]; + this->Offset = 0; + this->Break_pnt = 200; + this->Save_pnt = 0; + + this->SetNumberOfInputPorts(0); +} +//---------------------------------------------------------------------------- +vtkChacoReader::~vtkChacoReader() +{ + this->SetBaseName(NULL); + this->SetCurrentBaseName(NULL); + + this->ClearWeightArrayNames(); + + this->DataCache->Delete(); + this->DataCache = NULL; + + delete [] this->Line; +} +//---------------------------------------------------------------------------- +void vtkChacoReader::ClearWeightArrayNames() +{ + int i=0; + if (this->VarrayName) + { + for (i=0; iNumberOfVertexWeights; i++) + { + delete [] this->VarrayName[i]; + } + delete [] this->VarrayName; + this->VarrayName = NULL; + } + + if (this->EarrayName) + { + for (i=0; iNumberOfEdgeWeights; i++) + { + delete [] this->EarrayName[i]; + } + delete [] this->EarrayName; + this->EarrayName = NULL; + } +} +void vtkChacoReader::MakeWeightArrayNames(int nv, int ne) +{ + int i=0; + if (nv > 0) + { + this->VarrayName = new char *[nv]; + for (i=0; iVarrayName[i] = new char [64]; + sprintf(this->VarrayName[i], "VertexWeight%d", i+1); + } + } + if (ne > 0) + { + this->EarrayName = new char *[ne]; + for (i=0; iEarrayName[i] = new char [64]; + sprintf(this->EarrayName[i], "EdgeWeight%d", i+1); + } + } +} +char *vtkChacoReader::GetVertexWeightArrayName(int weight) +{ + if (this->GetGenerateVertexWeightArrays() && + (weight > 0) && + (weight <= this->NumberOfVertexWeights)) + { + return this->VarrayName[weight-1]; + } + + return NULL; +} + +char *vtkChacoReader::GetEdgeWeightArrayName(int weight) +{ + if (this->GetGenerateEdgeWeightArrays() && + (weight > 0) && + (weight <= this->NumberOfEdgeWeights)) + { + return this->EarrayName[weight-1]; + } + + return NULL; +} + +//---------------------------------------------------------------------------- +int vtkChacoReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + double x, y, z; + + if (!this->BaseName) + { + vtkErrorMacro(<< "No BaseName specified"); + return 0; + } + + int newFile = + ((this->CurrentBaseName == NULL) || + strcmp(this->CurrentBaseName, this->BaseName)); + + if ( !newFile ) + { + return 1; + } + + if ( this->OpenCurrentFile() != 1 ) + { + return 0; + } + + // Get the dimension of the coordinates from the vertex file + + int rc = this->InputGeom(1, 0, &x, &y, &z); + + this->ResetInputBuffers(); + + if (rc) + { + // Get the number of vertices and edges, and number of + // vertex weights and edge weights from the graph file. + + rc = this->InputGraph1(); + + this->ResetInputBuffers(); + + if (rc) + { + this->MakeWeightArrayNames( + this->NumberOfVertexWeights, this->NumberOfEdgeWeights); + } + } + + // Close the file + this->CloseCurrentFile(); + + this->RemakeDataCacheFlag = 1; + + return rc; +} + +//---------------------------------------------------------------------------- +int vtkChacoReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + if (!this->BaseName) + { + vtkErrorMacro(<< "No BaseName specified"); + return 0; + } + + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int retVal = this->BuildOutputGrid(output); + + return retVal; +} + +//---------------------------------------------------------------------------- +int vtkChacoReader::BuildOutputGrid(vtkUnstructuredGrid *output) +{ + int i=0; + if ( this->OpenCurrentFile() != 1 ) + { + vtkWarningMacro(<< "Can't open file"); + return 0; + } + + int ncells = this->DataCache->GetNumberOfCells(); + int haveVertexWeightArrays = 0; + int haveEdgeWeightArrays = 0; + + if (ncells && (this->NumberOfVertexWeights > 0)) + { + vtkDoubleArray *da = vtkDoubleArray::SafeDownCast( + this->DataCache->GetPointData()->GetArray(this->VarrayName[0])); + + haveVertexWeightArrays = (da != NULL); + } + + if (ncells && (this->NumberOfEdgeWeights > 0)) + { + vtkDoubleArray *da = vtkDoubleArray::SafeDownCast( + this->DataCache->GetCellData()->GetArray(this->EarrayName[0])); + + haveEdgeWeightArrays = (da != NULL); + } + + if (!this->RemakeDataCacheFlag && + ((!haveVertexWeightArrays && this->GenerateVertexWeightArrays) || + (!haveEdgeWeightArrays && this->GenerateEdgeWeightArrays))) + { + this->RemakeDataCacheFlag = 1; + } + + if (this->RemakeDataCacheFlag) + { + output->Initialize(); + int rc = this->ReadFile(output); + + if (rc == 0) + { + this->CloseCurrentFile(); + return 0; + } + + if (this->GenerateGlobalElementIdArray) + { + this->AddElementIds(output); + } + + if (this->GenerateGlobalNodeIdArray) + { + this->AddNodeIds(output); + } + + // Save the output. Next time we execute, it may be simply + // because they turned off vertex or edge weights, or decided they + // do or do not want element or point IDs. For these we can just + // modify the DataCache, rather than reading in the whole file + // and creating a vtkUnstructuredGrid from it. + + this->DataCache->Initialize(); + this->DataCache->ShallowCopy(output); + + this->RemakeDataCacheFlag = 0; + } + else + { + // Just copy the output we calculated last time, after checking + // to see if any parameters have changed + + if (haveVertexWeightArrays && !this->GenerateVertexWeightArrays) + { + for (i=0; iNumberOfVertexWeights; i++) + { + this->DataCache->GetPointData()->RemoveArray(this->VarrayName[i]); + } + + this->NumberOfPointWeightArrays = 0; + } + + if (haveEdgeWeightArrays && !this->GenerateEdgeWeightArrays) + { + for (i=0; iNumberOfEdgeWeights; i++) + { + this->DataCache->GetCellData()->RemoveArray(this->EarrayName[i]); + } + + this->NumberOfCellWeightArrays = 0; + } + + vtkIntArray *ia = vtkIntArray::SafeDownCast( + this->DataCache->GetCellData()->GetArray(this->GetGlobalElementIdArrayName())); + + if (!ia && this->GenerateGlobalElementIdArray) + { + this->AddElementIds(this->DataCache); + } + else if (ia && !this->GenerateGlobalElementIdArray) + { + this->DataCache->GetCellData()->RemoveArray(this->GetGlobalElementIdArrayName()); + } + + ia = vtkIntArray::SafeDownCast( + this->DataCache->GetPointData()->GetArray(this->GetGlobalNodeIdArrayName())); + + if (!ia && this->GenerateGlobalNodeIdArray) + { + this->AddNodeIds(this->DataCache); + } + else if (ia && !this->GenerateGlobalNodeIdArray) + { + this->DataCache->GetPointData()->RemoveArray(this->GetGlobalNodeIdArrayName()); + } + + output->ShallowCopy(this->DataCache); + } + + // This just makes sure the arrays are the same size as the number + // of nodes or cell + output->CheckAttributes(); + + // We may have some mem that can be condensed + output->Squeeze(); + + this->CloseCurrentFile(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkChacoReader::ReadFile(vtkUnstructuredGrid* output) +{ + int i=0; + vtkIdType id=0; + + // Reset the entire unstructured grid + output->Reset(); + + this->NumberOfPointWeightArrays = 0; + this->NumberOfCellWeightArrays = 0; + + // Read in the points. Maintain the order in the original file. + // The order indicates the global node ID. + + vtkPoints *ptarray = vtkPoints::New(); + ptarray->SetNumberOfPoints(this->NumberOfVertices); + ptarray->SetDataTypeToDouble(); + + int memoryOK = 1; + + double *x = new double [this->NumberOfVertices]; + double *y = NULL; + double *z = NULL; + + if (!x) + { + memoryOK = 0; + } + else if (this->Dimensionality > 1) + { + y = new double [this->NumberOfVertices]; + if (!y) + { + memoryOK = 0; + } + else if (this->Dimensionality > 2) + { + z = new double [this->NumberOfVertices]; + if (!z) + { + memoryOK = 0; + } + } + } + + if (!memoryOK) + { + vtkErrorMacro(<< "ReadFile memory allocation failure"); + if (x) delete [] x; + if (y) delete [] y; + return 0; + } + + int rc = this->InputGeom(this->NumberOfVertices, this->Dimensionality, x, y, z); + + this->ResetInputBuffers(); + + if (rc == 0) + { + if (x) delete [] x; + if (y) delete [] y; + if (z) delete [] z; + return 0; + } + + if (this->Dimensionality == 3) + { + for (id=0; idNumberOfVertices; id++) + { + ptarray->InsertNextPoint(x[id], y[id], z[id]); + } + } + else if (this->Dimensionality == 2) + { + for (id=0; idNumberOfVertices; id++) + { + ptarray->InsertNextPoint(x[id], y[id], 0.0); + } + } + else if (this->Dimensionality == 1) + { + for (id=0; idNumberOfVertices; id++) + { + ptarray->InsertNextPoint(x[id], 0.0, 0.0); + } + } + + output->SetPoints(ptarray); + + if (x) delete [] x; + if (y) delete [] y; + if (z) delete [] z; + ptarray->Delete(); + + // Read in cell topology and possibly cell and point weights. + // (The unstructured grid "cells" are the Chaco "edges".) + // + // Note: The order in which point and cell arrays appear in the + // output must be fixed. This is because this reader is called + // by vtkPChacoReader, and all processes must create output + // ugrids with the cell arrays and point arrays in the same + // order. The order we choose for point arrays is: + // vertex weight arrays, if any, in order they appear in file + // global point IDs, if any + // + // The order for cell arrays is: + // edge weight arrays, if any, in order they appear in file + // global element IDs, if any + + int retVal = 1; + + vtkIdType *idx = NULL; + vtkIdType *nbors = NULL; + double *vweights = NULL; + double *eweights = NULL; + + double **vw = NULL; + double **ew = NULL; + + if (this->GetGenerateVertexWeightArrays() && (this->NumberOfVertexWeights > 0)) + { + vw = &vweights; + } + + if (this->GetGenerateEdgeWeightArrays() && (this->NumberOfEdgeWeights > 0)) + { + ew = &eweights; + } + + rc = this->InputGraph2(&idx, &nbors, vw, ew); + + this->ResetInputBuffers(); + + if (rc == 0) + { + return 0; + } + + vtkDoubleArray **varrays = NULL; + vtkDoubleArray **earrays = NULL; + double *vwgt = NULL; + double *ewgt = NULL; + + if (vw) + { + varrays = new vtkDoubleArray * [this->NumberOfVertexWeights]; + for (i=0; iNumberOfVertexWeights; i++) + { + varrays[i] = vtkDoubleArray::New(); + varrays[i]->SetNumberOfValues(this->NumberOfVertices); + varrays[i]->SetName(this->VarrayName[i]); + } + vwgt = vweights; + } + + if (ew) + { + earrays = new vtkDoubleArray * [this->NumberOfEdgeWeights]; + for (i=0; iNumberOfEdgeWeights; i++) + { + earrays[i] = vtkDoubleArray::New(); + earrays[i]->SetNumberOfValues(this->NumberOfEdges); + earrays[i]->SetName(this->EarrayName[i]); + } + ewgt = eweights; + } + + vtkIdTypeArray *ca = vtkIdTypeArray::New(); + + if (idx == NULL) + { + // Special case: there are no edges in this graph. Every + // vertex will be a cell. + + ca->SetNumberOfValues(2*this->NumberOfVertices); + vtkIdType *captr = ca->GetPointer(0); + + for (id=0; idNumberOfVertices; id++) + { + *captr++ = 1; // number of vertices in cell + *captr++ = id; // internal ID of vertex + + if (vw) + { + for (int w=0; wNumberOfVertexWeights; w++) + { + varrays[w]->SetValue(id, *vwgt++); + } + } + } + vtkCellArray *cells = vtkCellArray::New(); + cells->SetCells(this->NumberOfVertices, ca); + output->SetCells(VTK_VERTEX, cells); + cells->Delete(); + } + else + { + // The usual case: most or all vertices are connected to + // other vertices. + + ca->SetNumberOfValues(3 * this->NumberOfEdges); + vtkIdType *captr = ca->GetPointer(0); + + vtkIdType edgeNum = -1; + + for (id=0; id < this->NumberOfVertices; id++) + { + // Each edge in the Chaco file is listed twice, for each + // vertex. We only save the edge once. + + for (int n=idx[id]; n < idx[id+1]; n++) + { + vtkIdType nbor = nbors[n] - 1; // internal id + + // Save each edge connected to this vertex, if it hasn't + // been saved already. + + if (nbor > id) + { + edgeNum++; + + if (edgeNum == this->NumberOfEdges) + { + vtkErrorMacro(<< "Too many edges in Chaco file"); + retVal = 0; + break; + } + + *captr++ = 2; // size of cell + *captr++ = id; // first vertex + *captr++ = nbor; // second vertex + + if (ew) + { + // Save the edge weights associated with this edge + + for (i=0; iNumberOfEdgeWeights; i++) + { + earrays[i]->SetValue(edgeNum, *ewgt++); + } + } + } + else if (ew) + { + ewgt += this->NumberOfEdgeWeights; // Skip duplicate edge weights + } + } + + if (!retVal) break; + + // Save the weights associated with this vertex + + if (vw) + { + for (i=0; iNumberOfVertexWeights; i++) + { + varrays[i]->SetValue(id, *vwgt++); + } + } + } + + if (edgeNum != this->NumberOfEdges - 1) + { + vtkErrorMacro(<< "Too few edges in Chaco file"); + retVal = 0; + } + + delete [] idx; + delete [] nbors; + + if (retVal) + { + vtkCellArray *cells = vtkCellArray::New(); + cells->SetCells(this->NumberOfEdges, ca); + output->SetCells(VTK_LINE, cells); + cells->Delete(); + } + else + { + output->Initialize(); + } + } + + ca->Delete(); + + if (retVal == 1) + { + this->NumberOfPointWeightArrays = this->NumberOfVertexWeights; + this->NumberOfCellWeightArrays = this->NumberOfEdgeWeights; + } + + if (vw) + { + delete [] vweights; + for (i=0; iNumberOfVertexWeights; i++) + { + if (retVal) + { + output->GetPointData()->AddArray(varrays[i]); + } + varrays[i]->Delete(); + } + + delete [] varrays; + } + + if (ew) + { + delete [] eweights; + for (i=0; iNumberOfEdgeWeights; i++) + { + if (retVal) + { + output->GetCellData()->AddArray(earrays[i]); + } + earrays[i]->Delete(); + } + + delete [] earrays; + } + + if (retVal) + { + output->Squeeze(); + } + + return retVal; +} +//---------------------------------------------------------------------------- +void vtkChacoReader::AddElementIds(vtkUnstructuredGrid* output) +{ + // We arbitrarily assign the element ids, since Chaco files do + // not have the notion of Element IDs. + + vtkIdType len = output->GetNumberOfCells(); + + vtkIntArray *ia = vtkIntArray::New(); + ia->SetName(this->GetGlobalElementIdArrayName()); + ia->SetNumberOfValues(len); + + for (vtkIdType i=0; iSetValue(i, i+1); + } + + output->GetCellData()->AddArray(ia); + ia->Delete(); +} +void vtkChacoReader::AddNodeIds(vtkUnstructuredGrid* output) +{ + // The vertex IDs in a Chaco file begin at 1 for the first + // vertex in the .coords file, and increase by 1 thereafter. + + vtkIdType len = output->GetNumberOfPoints(); + + vtkIntArray *ia = vtkIntArray::New(); + ia->SetName(this->GetGlobalNodeIdArrayName()); + ia->SetNumberOfValues(len); + + for (vtkIdType i=0; iSetValue(i, i+1); + } + + output->GetPointData()->AddArray(ia); + ia->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkChacoReader::PrintSelf(ostream& os, vtkIndent indent) +{ + int i=0; + this->Superclass::PrintSelf(os,indent); + + if (this->GenerateGlobalElementIdArray) + { + os << indent << "GenerateGlobalElementIdArray: On\n"; + } + else + { + os << indent << "GenerateGlobalElementIdArray: Off\n"; + } + + if (this->GenerateGlobalNodeIdArray) + { + os << indent << "GenerateGlobalNodeIdArray: On\n"; + } + else + { + os << indent << "GenerateGlobalNodeIdArray: Off\n"; + } + + if (this->GenerateVertexWeightArrays) + { + os << indent << "GenerateVertexWeightArrays: On\n"; + } + else + { + os << indent << "GenerateVertexWeightArrays: Off\n"; + } + + if (this->GenerateEdgeWeightArrays) + { + os << indent << "GenerateEdgeWeightArrays: On\n"; + } + else + { + os << indent << "GenerateEdgeWeightArrays: Off\n"; + } + + os << indent << "Base Name: " + << (this->BaseName ? this->BaseName : "(none)") << "\n"; + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; + os << indent << "NumberOfVertices: " << this->NumberOfVertices << "\n"; + os << indent << "NumberOfEdges: " << this->NumberOfEdges << "\n"; + os << indent << "NumberOfVertexWeights: " << this->NumberOfVertexWeights<< "\n"; + os << indent << "NumberOfEdgeWeights: " << this->NumberOfEdgeWeights<< "\n"; + os << indent << "NumberOfPointWeightArrays: " << this->NumberOfPointWeightArrays<< "\n"; + os << indent << "NumberOfCellWeightArrays: " << this->NumberOfCellWeightArrays<< "\n"; + + for (i=1; i<=this->NumberOfPointWeightArrays; i++) + { + cout << "vertex weight array name: " << this->GetVertexWeightArrayName(i) << endl;; + } + + for (i=1; i<=this->NumberOfCellWeightArrays; i++) + { + cout << "edge weight array name: " << this->GetEdgeWeightArrayName(i) << endl;; + } +} + +void vtkChacoReader::CloseCurrentFile() +{ + if (this->CurrentGeometryFP){ + fclose(this->CurrentGeometryFP); + fclose(this->CurrentGraphFP); + this->CurrentGeometryFP = NULL; + this->CurrentGraphFP = NULL; + } +} + +int vtkChacoReader::OpenCurrentFile() +{ + int result = 0; + + if ( this->CurrentGeometryFP == NULL) + { + int len = strlen(this->BaseName); + char *buf = new char [len+64]; + sprintf(buf, "%s.coords", this->BaseName); + + this->CurrentGeometryFP = fopen(buf, "r"); + + if (this->CurrentGeometryFP == NULL) + { + vtkErrorMacro(<< "Problem opening " << buf); + this->SetCurrentBaseName( NULL ); + } + else + { + sprintf(buf, "%s.graph", this->BaseName); + + this->CurrentGraphFP = fopen(buf, "r"); + + if (this->CurrentGraphFP == NULL) + { + vtkErrorMacro(<< "Problem opening " << buf); + this->SetCurrentBaseName( NULL ); + fclose(this->CurrentGeometryFP); + this->CurrentGeometryFP = NULL; + } + else { + this->SetCurrentBaseName( this->GetBaseName() ); + result = 1; + } + } + delete [] buf; + } + + return result; +} + +//---------------------------------------------------------------------------- +// Code to read Chaco files. +// This software was developed by Bruce Hendrickson and Robert Leland +// at Sandia National Laboratories under US Department of Energy +// contract DE-AC04-76DP00789 and is copyrighted by Sandia Corporation. + +void vtkChacoReader::ResetInputBuffers() +{ + this->Line_length = 200; + this->Offset = 0; + this->Break_pnt = 200; + this->Save_pnt = 0; +} + +int vtkChacoReader::InputGeom( +vtkIdType nvtxs, // Number of vertices to read in +int igeom, // Dimension (1, 2 or 3), or 0 if you don't know +double *x, double *y, double *z) +{ + double xc=0.0, yc=0.0, zc=0.0; + int line_num, end_flag, ndims, i=0; + + rewind(this->CurrentGeometryFP); + + line_num = 0; + end_flag = 1; + while (end_flag == 1) { + xc = this->ReadVal(this->CurrentGeometryFP, &end_flag); + ++line_num; + } + + if (end_flag == -1) { + vtkErrorMacro(<<"No values found in geometry file "<< this->BaseName << ".coords"); + return 0; + } + + if (igeom == 0) + { + ndims = 1; + yc = this->ReadVal(this->CurrentGeometryFP, &end_flag); + if (end_flag == 0) + { + ndims = 2; + zc = this->ReadVal(this->CurrentGeometryFP, &end_flag); + if (end_flag == 0) + { + ndims = 3; + this->ReadVal(this->CurrentGeometryFP, &end_flag); + if (!end_flag) + { + vtkErrorMacro(<< "Invalid geometry file "<< this->BaseName << ".coords"); + return 0; + } + } + } + this->Dimensionality = ndims; + } + else + { + ndims = this->Dimensionality; + if (ndims > 1) + { + yc = this->ReadVal(this->CurrentGeometryFP, &end_flag); + if (ndims > 2) + { + zc = this->ReadVal(this->CurrentGeometryFP, &end_flag); + } + } + this->ReadVal(this->CurrentGeometryFP, &end_flag); + } + + x[0] = xc; + if (ndims > 1) + { + y[0] = yc; + if (ndims > 2) + { + z[0] = zc; + } + } + + if (nvtxs == 1) + { + return 1; + } + + for (int nread = 1; nread < nvtxs; nread++) + { + ++line_num; + if (ndims == 1) + { + i = fscanf(this->CurrentGeometryFP, "%lf", x + nread); + } + else if (ndims == 2) + { + i = fscanf(this->CurrentGeometryFP, "%lf%lf", x + nread, y + nread); + } + else if (ndims == 3) + { + i = fscanf(this->CurrentGeometryFP, "%lf%lf%lf", x+nread, y+nread, z+nread); + } + + if (i == EOF) + { + vtkErrorMacro(<< "Too few lines in "<< this->BaseName << ".coords"); + return 0; + } + else if (i != ndims) + { + vtkErrorMacro(<< "Wrong dimension in "<< this->BaseName << ".coords"); + return 0; + } + } + + return 1; +} +int vtkChacoReader::InputGraph1() +{ + /* Read first line of input (= nvtxs, narcs, option). */ + /* The (decimal) digits of the option variable mean: 1's digit not zero => input + edge weights 10's digit not zero => input vertex weights 100's digit not zero + => include vertex numbers */ + + FILE *fin = this->CurrentGraphFP; + rewind(fin); + + /* Read any leading comment lines */ + int end_flag = 1; + vtkIdType numVertices = 0; + + while (end_flag == 1) { + numVertices = this->ReadInt(fin, &end_flag); + } + if (numVertices <= 0) { + vtkErrorMacro(<< "Invalid file " << this->BaseName << ".graph" ); + return 0; + } + + this->NumberOfVertices = numVertices; + + this->NumberOfEdges = this->ReadInt(fin, &end_flag); + if (this->NumberOfEdges < 0) { + vtkErrorMacro(<< "Invalid file " << this->BaseName << ".graph" ); + return 0; + } + + this->NumberOfVertexWeights = 0; + this->NumberOfEdgeWeights = 0; + this->GraphFileHasVertexNumbers = 0; + + /* Check if vertex or edge weights are used */ + if (!end_flag) { + vtkIdType option = this->ReadInt(fin, &end_flag); + this->NumberOfEdgeWeights = (int)(option - 10 * (option / 10)); + option /= 10; + this->NumberOfVertexWeights = (int)(option - 10 * (option / 10)); + option /= 10; + this->GraphFileHasVertexNumbers = (int)(option - 10 * (option / 10)); + } + + /* Read weight dimensions if they are specified separately */ + if (!end_flag && this->NumberOfVertexWeights == 1){ + vtkIdType j = this->ReadInt(fin, &end_flag); + if (!end_flag) this->NumberOfVertexWeights = (int)j; + } + if (!end_flag && this->NumberOfEdgeWeights == 1){ + vtkIdType j = this->ReadInt(fin, &end_flag); + if (!end_flag) this->NumberOfEdgeWeights = (int)j; + } + + return 1; +} + +int vtkChacoReader::InputGraph2( + vtkIdType **start, // start[i]: location of vertex i in adjacency array + vtkIdType **adjacency, // by vertex by vertex neighbor + double **vweights, // by vertex by weight (or NULL if no weights wanted) + double **eweights ) // edge weights in order in file (or NULL) +{ + vtkIdType *adjptr; + double *ewptr; + vtkIdType vtx, sum_edges, vertex, new_vertex; + double weight, eweight; + vtkIdType neighbor, j; + int retVal = 1; + + vtkIdType nvtxs = this->NumberOfVertices; + vtkIdType narcs = this->NumberOfEdges; + int vwgt_dim = this->NumberOfVertexWeights; + int ewgt_dim = this->NumberOfEdgeWeights; + int vtxnums = this->GraphFileHasVertexNumbers; + + if (nvtxs < 1) + { + vtkErrorMacro(<< "vtkChacoReader::InputGraph2, NumberOfVertices not set"); + return 0; + } + + if (start == NULL) + { + vtkErrorMacro(<< "vtkChacoReader::InputGraph2, parameter list"); + return 0; + } + + *start = NULL; + if (adjacency) + { + *adjacency = NULL; + } + if (vweights) + { + *vweights = NULL; + } + if (eweights) + { + *eweights = NULL; + } + + int line_num = 0; + + FILE *fin = this->CurrentGraphFP; + rewind(fin); + + /* Read past the first line containing the metadata */ + + int end_flag = 1; + while (end_flag == 1) + { + j = this->ReadInt(fin, &end_flag); + ++line_num; + } + while (!end_flag) + { + j = this->ReadInt(fin, &end_flag); + } + ++line_num; + + /* Allocate space for rows and columns. */ + *start = new vtkIdType [nvtxs + 1]; + if (adjacency && (narcs > 0)) + { + *adjacency = new vtkIdType [2 * narcs + 1]; // why +1 ? + } + else + { + *adjacency = NULL; + } + if (vweights && (vwgt_dim > 0)) + { + *vweights = new double [nvtxs * vwgt_dim]; + } + + if (eweights && (ewgt_dim > 0) && (narcs > 0)) + { + *eweights = new double [(2 * narcs + 1) * ewgt_dim]; // why +1 ? + } + + adjptr = (adjacency ? *adjacency : NULL); + ewptr = (eweights ? *eweights : NULL); + + sum_edges = 0; + (*start)[0] = 0; + vertex = 0; + vtx = 0; + new_vertex = 1; + while (((vwgt_dim > 0)|| vtxnums || narcs) && end_flag != -1) + { + ++line_num; + + /* If multiple input lines per vertex, read vertex number. */ + if (vtxnums) + { + j = this->ReadInt(fin, &end_flag); + if (end_flag) + { + if (vertex == nvtxs) + { + break; + } + + vtkErrorMacro(<< + "Missing vertex number " << this->BaseName << ".graph, line " << line_num); + retVal = 0; + goto done; + } + if (j != vertex && j != vertex + 1) + { + vtkErrorMacro(<< + "Out of order vertex " << this->BaseName << ".graph, line " << line_num); + retVal = 0; + goto done; + } + if (j != vertex) + { + new_vertex = 1; + vertex = j; + } + else + { + new_vertex = 0; + } + } + else + { + vertex = ++vtx; + } + + if (vertex > nvtxs) + break; + + /* If vertices are weighted, read vertex weight. */ + if ((vwgt_dim > 0) && new_vertex) + { + for (j=0; j<(vwgt_dim); j++) + { + weight = ReadVal(fin, &end_flag); + if (end_flag) + { + vtkErrorMacro(<< + "Vertex weights " << this->BaseName << ".graph, line " << line_num); + retVal = 0; + goto done; + } + + if (vweights) + { + (*vweights)[(vertex-1)*(vwgt_dim)+j] = weight; + } + } + } + + /* Read number of adjacent vertex. */ + neighbor = this->ReadInt(fin, &end_flag); + + while (!end_flag) + { + if (ewgt_dim > 0) + { + for (j=0; jBaseName << ".graph, line " << line_num); + retVal = 0; + goto done; + } + + if (ewptr) + { + *ewptr++ = eweight; + } + } + } + + /* Add edge to data structure. */ + if (++sum_edges > 2*narcs) + { + vtkErrorMacro(<< + "Too many adjacencies " << this->BaseName << ".graph, line " << line_num); + retVal = 0; + goto done; + } + + if (adjptr) + { + *adjptr++ = neighbor; + } + + /* Read number of next adjacent vertex. */ + neighbor = this->ReadInt(fin, &end_flag); + } + + (*start)[vertex] = sum_edges; + } + +done: + + if ((vertex == 0) || (retVal == 0)) + { + /* Graph was empty */ + delete [] *start; + *start = NULL; + if (adjacency && (*adjacency != NULL)) + { + delete [] *adjacency; + *adjacency = NULL; + } + if (vweights && (*vweights != NULL)) + { + delete [] *vweights; + *vweights = NULL; + } + if (eweights && (*eweights != NULL)) + { + delete [] *eweights; + *eweights = NULL; + } + } + + return retVal; +} + +double vtkChacoReader::ReadVal( FILE *infile, int *end_flag ) +{ + double val; + char *ptr; + char *ptr2; + int length; + int length_left; + int white_seen; + int done; + int i; + + *end_flag = 0; + + if (Offset == 0 ||this->Offset >= this->Break_pnt) + { + if (Offset >= this->Break_pnt) + { + length_left = this->Line_length - this->Save_pnt - 1; + ptr2 = this->Line; + ptr = &Line[Save_pnt]; + for (i=length_left; i; i--) *ptr2++ = *ptr++; + length = this->Save_pnt + 1; + } + else + { + length = this->Line_length; + length_left = 0; + } + + this->Line[this->Line_length - 1] = ' '; + this->Line[this->Line_length - 2] = ' '; + /* Now read next line, or next segment of current one. */ + ptr2 = fgets(&Line[length_left], length, infile); + + if (ptr2 == (char *) NULL) + { + *end_flag = -1; + return((double) 0.0); + } + + if (Line[this->Line_length - 1] == '\0' && this->Line[this->Line_length - 2] != '\0' && + this->Line[this->Line_length - 2] != '\n' && this->Line[this->Line_length - 2] != '\f') + { + /* Line too long. Find last safe place in line. */ + this->Break_pnt = this->Line_length - 1; + this->Save_pnt = this->Break_pnt; + white_seen = 0; + done = 0; + while (!done) + { + --Break_pnt; + if (Line[Break_pnt] != '\0') + { + if (isspace((int)(Line[Break_pnt]))) + { + if (!white_seen) + { + this->Save_pnt = this->Break_pnt + 1; + white_seen = 1; + } + } + else if (white_seen) + { + done= 1; + } + } + } + } + else + { + this->Break_pnt = this->Line_length; + } + + this->Offset = 0; + } + + while (isspace((int)(Line[Offset])) &&this->Offset < this->Line_length)this->Offset++; + if (Line[Offset] == '%' || this->Line[Offset] == '#') + { + *end_flag = 1; + if (Break_pnt < this->Line_length) + { + FlushLine(infile); + } + return((double) 0.0); + } + + ptr = &(Line[Offset]); + val = strtod(ptr, &ptr2); + + if (ptr2 == ptr) + { + this->Offset = 0; + *end_flag = 1; + return((double) 0.0); + } + else + { + this->Offset = (int) (ptr2 - this->Line) / sizeof(char); + } + + return(val); +} + +vtkIdType vtkChacoReader::ReadInt( +FILE *infile, +int *end_flag +) +{ + vtkIdType val; + char *ptr; + char *ptr2; + int length; + int length_left; + int white_seen; + int done; + int i; + + *end_flag = 0; + + if (Offset == 0 ||this->Offset >= this->Break_pnt) + { + if (Offset >= this->Break_pnt) + { + length_left = this->Line_length - this->Save_pnt - 1; + ptr2 = this->Line; + ptr = &Line[Save_pnt]; + for (i=length_left; i; i--) *ptr2++ = *ptr++; + length = this->Save_pnt + 1; + } + else + { + length = this->Line_length; + length_left = 0; + } + + this->Line[this->Line_length - 1] = ' '; + this->Line[this->Line_length - 2] = ' '; + /* Now read next line, or next segment of current one. */ + ptr2 = fgets(&Line[length_left], length, infile); + + if (ptr2 == (char *) NULL) + { + *end_flag = -1; + return(0); + } + + if (this->Line[this->Line_length - 1] == '\0' &&this->Line[this->Line_length - 2] != '\0' && + this->Line[this->Line_length - 2] != '\n' && this->Line[this->Line_length - 2] != '\f') + { + /*Line too long. Find last safe place in line. */ + this->Break_pnt = this->Line_length - 1; + this->Save_pnt = this->Break_pnt; + white_seen = 0; + done = 0; + while (!done) + { + --Break_pnt; + if (Line[Break_pnt] != '\0') + { + if (isspace((int)(Line[Break_pnt]))) + { + if (!white_seen) + { + this->Save_pnt = this->Break_pnt + 1; + white_seen = 1; + } + } + else if (white_seen) + { + done= 1; + } + } + } + } + else + { + this->Break_pnt = this->Line_length; + } + + this->Offset = 0; + } + + while (isspace((int)(Line[Offset])) &&this->Offset < this->Line_length)this->Offset++; + if (Line[Offset] == '%' || this->Line[Offset] == '#') + { + *end_flag = 1; + if (Break_pnt < this->Line_length) + { + FlushLine(infile); + } + return(0); + } + + ptr = &(Line[Offset]); + val = (int) strtol(ptr, &ptr2, 10); + + if (ptr2 == ptr) + { + this->Offset = 0; + *end_flag = 1; + return(0); + } + else + { + this->Offset = (int) (ptr2 - this->Line) / sizeof(char); + } + + return(val); +} +void vtkChacoReader::FlushLine( FILE *infile) +{ + char c; + + c = getc(infile); + while (c != '\n' && c != '\f') + { + c = getc(infile); + } +} + diff --git a/IO/vtkChacoReader.h b/IO/vtkChacoReader.h new file mode 100644 index 0000000..107cf28 --- /dev/null +++ b/IO/vtkChacoReader.h @@ -0,0 +1,235 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkChacoReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkChacoReader - Read a Chaco file and create a vtkUnstructuredGrid. +// .SECTION Description +// vtkChacoReader is an unstructured grid source object that reads Chaco +// files. The reader DOES NOT respond to piece requests. Chaco +// is a graph partitioning package developed at Sandia National Laboratories +// in the early 1990s. (http://www.cs.sandia.gov/~bahendr/chaco.html) +// +// Note that the Chaco "edges" become VTK "cells", and the Chaco +// "vertices" become VTK "points". + +#ifndef __vtkChacoReader_h +#define __vtkChacoReader_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class VTK_IO_EXPORT vtkChacoReader : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkChacoReader *New(); + vtkTypeRevisionMacro(vtkChacoReader,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the base name of the Chaco files. The reader will try to + // open BaseName.coords and BaseName.graph. + + vtkSetStringMacro(BaseName); + vtkGetStringMacro(BaseName); + + // Description: + // Indicate whether this reader should create a cell array containing + // global IDs for the cells in the output vtkUnstructuredGrid. These cells + // represent the edges that were in the Chaco file. Each edge is a vtkLine. + // Default is ON. + + vtkSetMacro(GenerateGlobalElementIdArray, int); + vtkGetMacro(GenerateGlobalElementIdArray, int); + vtkBooleanMacro(GenerateGlobalElementIdArray, int); + + static const char *GetGlobalElementIdArrayName() { return "GlobalElementId"; } + + // Description: + // Indicate whether this reader should create a point array of global IDs for + // the points in the output vtkUnstructuredGrid. These points are the vertices + // that were in the Chaco file. Global point IDs start at "1" for the first + // vertex in BaseName.coords and go up from there. + // Default is ON. + + vtkSetMacro(GenerateGlobalNodeIdArray, int); + vtkGetMacro(GenerateGlobalNodeIdArray, int); + vtkBooleanMacro(GenerateGlobalNodeIdArray, int); + + static const char *GetGlobalNodeIdArrayName() { return "GlobalNodeId"; } + + // Description: + // Indicate whether this reader should create a point array for each + // vertex weight in the Chaco file. + // Default is OFF. + + vtkSetMacro(GenerateVertexWeightArrays, int); + vtkGetMacro(GenerateVertexWeightArrays, int); + vtkBooleanMacro(GenerateVertexWeightArrays, int); + + // Description: + // Returns the number of weights per vertex in the Chaco file, whether or + // not GenerateVertexWeightArrays is ON. + + vtkGetMacro(NumberOfVertexWeights, int); + + // Description: + // This method returns the name of the selected Vertex weight point + // array. If you did not turn on GenerateVertexWeightArrays, or + // if the weight you requested is invalid, it returns NULL. + // Weights begin at one and go up to NumberOfVertexWeights. + // This is a pointer to our copy of the name, so don't "delete" it. + + char *GetVertexWeightArrayName(int weight); + + // Description: + // Each edge in the Chaco file connects two vertices. The file may + // specify one or more weights for each edge. (The weight for an + // edge from vertex A to vertex B equals the weight from B to A.) + // Indicate with the following parameter whether this reader should + // create a cell array for each weight for every edge. + // Default is OFF. + + vtkSetMacro(GenerateEdgeWeightArrays, int); + vtkGetMacro(GenerateEdgeWeightArrays, int); + vtkBooleanMacro(GenerateEdgeWeightArrays, int); + + // Description: + // Returns the number of weights per edge in the Chaco file, whether or + // not GenerateEdgeWeightArrays is ON. + + vtkGetMacro(NumberOfEdgeWeights, int); + + // Description: + // This method returns the name of the selected Edge weight cell + // array. If you did not turn on GenerateEdgeWeightArrays, or + // if the weight you requested is invalid, it returns NULL. + // Weights begin at one and go up to NumberOfEdgeWeights. + // This is a pointer to our copy of the name, so don't "delete" it. + + char *GetEdgeWeightArrayName(int weight); + + // Description: + // Access to meta data generated by RequestInformation. + vtkGetMacro(Dimensionality, int); + vtkGetMacro(NumberOfEdges, vtkIdType); + vtkGetMacro(NumberOfVertices, vtkIdType); + + // Description: + // After this filter executes, this method returns the number of + // cell arrays that were created to hold the edge weights. It + // is equal to NumberOfEdgeWeights if GenerateEdgeWeightArrays was ON. + + vtkGetMacro(NumberOfCellWeightArrays, int); + + // Description: + // After this filter executes, this method returns the number of + // point arrays that were created to hold the vertex weights. It + // is equal to NumberOfVertexWeights if GenerateVertexWeightArrays was ON. + + vtkGetMacro(NumberOfPointWeightArrays, int); + +protected: + vtkChacoReader(); + ~vtkChacoReader(); + + int BuildOutputGrid(vtkUnstructuredGrid *gr); + + // methods for parsing Chaco files + + void CloseCurrentFile(); + int OpenCurrentFile(); + + int InputGeom(vtkIdType nvtxs, int igeom, double *x, double *y, double *z); + int InputGraph1(); + int InputGraph2( vtkIdType **start, vtkIdType **adjacency, double **vweights, + double **eweights); + int GetCoordsMetadata(); + void GetGraphMetadata(); + + // methods for creating vtkUnstructuredGrid from Chaco file data + + int ReadFile(vtkUnstructuredGrid* output); + void AddElementIds(vtkUnstructuredGrid* output); + void AddNodeIds(vtkUnstructuredGrid* output); + + void MakeWeightArrayNames(int nv, int ne); + + // Parameters for controlling what is read in. + char *BaseName; + int GenerateGlobalElementIdArray; + int GenerateGlobalNodeIdArray; + + int GenerateVertexWeightArrays; + int GenerateEdgeWeightArrays; + + FILE *CurrentGeometryFP; + FILE *CurrentGraphFP; + char *CurrentBaseName; + vtkSetStringMacro(CurrentBaseName); + + char **VarrayName; + char **EarrayName; + + //---------------------------------------------------------------------- + // The following metadata is read during RequestInformation. If you + // add new metadata, you must modify vtkPChacoReader::RequestInformation + // to include it when process 0 broadcasts the metadata. + + int Dimensionality; + vtkIdType NumberOfVertices; + vtkIdType NumberOfEdges; + int NumberOfVertexWeights; // in file + int NumberOfEdgeWeights; // in file + int GraphFileHasVertexNumbers; + + //---------------------------------------------------------------------- + + int NumberOfPointWeightArrays; // in output unstuctured grid + int NumberOfCellWeightArrays; // in output unstuctured grid + + // Keep the points and cells + // around so they don't need to be re-read when the + // options change. + vtkUnstructuredGrid *DataCache; + + // Should I re-read in the geometry and topology of the dataset + int RemakeDataCacheFlag; + + int RequestInformation( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkChacoReader(const vtkChacoReader&); // Not implemented + void operator=(const vtkChacoReader&); // Not implemented + + double ReadVal(FILE *infile, int *end_flag); + vtkIdType ReadInt(FILE *infile, int *end_flag); + void FlushLine( FILE *infile); + void ResetInputBuffers(); + + char *Line; + int Line_length; + int Offset; + int Break_pnt; + int Save_pnt; + + void ClearWeightArrayNames(); +}; + +#endif diff --git a/IO/vtkDEMReader.cxx b/IO/vtkDEMReader.cxx new file mode 100644 index 0000000..0bd6f66 --- /dev/null +++ b/IO/vtkDEMReader.cxx @@ -0,0 +1,633 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDEMReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageData.h" +#include "vtkDEMReader.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkDEMReader, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkDEMReader); + +#define VTK_SW 0 +#define VTK_NW 1 +#define VTK_NE 2 +#define VTK_SE 3 +#define VTK_METERS_PER_FEET .305 +#define VTK_METERS_PER_ARC_SECOND 23.111 + +void ConvertDNotationToENotation (char *line); + +vtkDEMReader::vtkDEMReader() +{ + int i, j; + this->NumberOfColumns = 0; + this->NumberOfRows = 0; + for (i = 0; i < 6; i++) + { + this->WholeExtent[i] = 0; + } + this->FileName = NULL; + for (i = 0; i < 145; i++) + { + this->MapLabel[i] = '\0'; + } + this->DEMLevel = 0; + this->ElevationPattern = 0; + this->GroundSystem = 0; + this->ProfileSeekOffset = 0; + this->GroundZone = 0; + for (i = 0; i < 15; i++) + { + this->ProjectionParameters[i] = 0; + } + this->PlaneUnitOfMeasure = 0; + this->ElevationUnitOfMeasure = 0; + this->PolygonSize = 0; + for (i = 0; i < 2; i++) + { + this->ElevationBounds[i] = 0; + this->ProfileDimension[i] = 0; + for (j = 0; j < 4; j++) + { + this->GroundCoords[j][i] = 0; + } + } + this->LocalRotation = 0; + this->AccuracyCode = 0; + for (i = 0; i < 3; i++) + { + this->SpatialResolution[i] = 0; + } + this->ElevationReference = REFERENCE_ELEVATION_BOUNDS; + + this->SetNumberOfInputPorts(0); +} + +vtkDEMReader::~vtkDEMReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } +} + +//---------------------------------------------------------------------------- +int vtkDEMReader::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + double spacing[3], origin[3]; + int extent[6]; + + if (!this->FileName) + { + vtkErrorMacro(<< "A FileName must be specified."); + return 0; + } + + // read the header of the file to determine dimensions, origin and spacing + this->ReadTypeARecord (); + + // compute the extent based on the header information + this->ComputeExtentOriginAndSpacing (extent, origin, spacing); + + // fill in the pertinent stuff from the header + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + + this->GetOutput()->SetNumberOfScalarComponents(1); + this->GetOutput()->SetScalarType(VTK_FLOAT); + + // whole dem must be read + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// Convert to Imaging API +int vtkDEMReader::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + // get the data object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetExtent( + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); + output->AllocateScalars(); + + if (!this->FileName) + { + vtkErrorMacro(<< "A FileName must be specified."); + return 0; + } + + if (output->GetScalarType() != VTK_FLOAT) + { + vtkErrorMacro("Execute: This source only outputs floats."); + return 1; + } + +// +// Read header +// + if (this->ReadTypeARecord () == 0) + { + // + // Read Profiles + // + this->ReadProfiles (output); + } + + // Name the scalars. + output->GetPointData()->GetScalars()->SetName("Elevation"); + + return 1; +} + +int vtkDEMReader::ReadTypeARecord () +{ + char record[1025]; + float elevationConversion; + FILE *fp; + + if (this->GetMTime () < this->ReadHeaderTime) + { + return 0; + } + + if (!this->FileName) + { + vtkErrorMacro(<< "A FileName must be specified."); + return -1; + } + + if ((fp = fopen(this->FileName, "rb")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return -1; + } + + vtkDebugMacro (<< "reading DEM header: type A record"); + + // + // read the record. it is always 1024 characters long + // + fscanf(fp, "%512c", record); + fscanf(fp, "%512c", record+512); + record[1024] = '\0'; + + // + // convert any D+ or D- to E+ or E-. c++ and c i/o cannot read D+/- + // + ConvertDNotationToENotation (record); + + char *current = record; + + this->MapLabel[144] = '\0'; + sscanf(current, "%144c", this->MapLabel); + current += 144; + + sscanf(current, "%6d%6d%6d%6d", + &this->DEMLevel, + &this->ElevationPattern, + &this->GroundSystem, + &this->GroundZone); + current += 24; + sscanf(current, "%24g%24g%24g%24g%24g%24g%24g%24g%24g%24g%24g%24g%24g%24g%24g", + &this->ProjectionParameters[0], + &this->ProjectionParameters[1], + &this->ProjectionParameters[2], + &this->ProjectionParameters[3], + &this->ProjectionParameters[4], + &this->ProjectionParameters[5], + &this->ProjectionParameters[6], + &this->ProjectionParameters[7], + &this->ProjectionParameters[8], + &this->ProjectionParameters[9], + &this->ProjectionParameters[10], + &this->ProjectionParameters[11], + &this->ProjectionParameters[12], + &this->ProjectionParameters[13], + &this->ProjectionParameters[14]); + current += 360; + sscanf(current, "%6d%6d%6d", + &this->PlaneUnitOfMeasure, + &this->ElevationUnitOfMeasure, + &this->PolygonSize); + current += 18; + sscanf(current, "%24g%24g%24g%24g%24g%24g%24g%24g", + &this->GroundCoords[0][0], &this->GroundCoords[0][1], + &this->GroundCoords[1][0], &this->GroundCoords[1][1], + &this->GroundCoords[2][0], &this->GroundCoords[2][1], + &this->GroundCoords[3][0], &this->GroundCoords[3][1]); + current += 192; + sscanf(current, "%24g%24g", + &this->ElevationBounds[0], &this->ElevationBounds[1]); + elevationConversion = 1.0; + if (this->ElevationUnitOfMeasure == 1) // feet + { + elevationConversion = VTK_METERS_PER_FEET; + } + else if (this->ElevationUnitOfMeasure == 3) // arc-seconds + { + elevationConversion = VTK_METERS_PER_ARC_SECOND; + } + this->ElevationBounds[0] *= elevationConversion; + this->ElevationBounds[1] *= elevationConversion; + current += 48; + sscanf(current, "%24g", + &this->LocalRotation); + current += 24; + sscanf(current, "%6d", + &this->AccuracyCode); + current += 6; + char buf[13]; + buf[12] = 0; + strncpy(buf, current, 12); + sscanf(buf, "%12g", &this->SpatialResolution[0]); + strncpy(buf, current+12, 12); + sscanf(buf, "%12g", &this->SpatialResolution[1]); + strncpy(buf, current+24, 12); + sscanf(buf, "%12g", &this->SpatialResolution[2]); + current += 36; + sscanf(current, "%6d%6d", + &this->ProfileDimension[0], + &this->ProfileDimension[1]); + + this->ProfileSeekOffset = ftell (fp); + + this->ReadHeaderTime.Modified(); + fclose (fp); + + return 0; +} + +void vtkDEMReader::ComputeExtentOriginAndSpacing (int extent[6], + double origin[3], + double spacing[3]) +{ + float eastMost, westMost, northMost, southMost; + float planeConversion; + + // + // compute number of samples + // + eastMost = this->GroundCoords[VTK_NE][0]; + if (eastMost < this->GroundCoords[VTK_SE][0]) + { + eastMost = this->GroundCoords[VTK_SE][0]; + } + westMost = this->GroundCoords[VTK_NW][0]; + if (westMost > this->GroundCoords[VTK_SW][0]) + { + westMost = this->GroundCoords[VTK_SW][0]; + } + northMost = this->GroundCoords[VTK_NE][1]; + if (northMost < this->GroundCoords[VTK_NW][1]) + { + northMost = this->GroundCoords[VTK_NW][1]; + } + southMost = this->GroundCoords[VTK_SW][1]; + if (southMost > this->GroundCoords[VTK_SE][1]) + { + southMost = this->GroundCoords[VTK_SE][1]; + } + + // + // compute the number of rows and columns + // + this->NumberOfColumns = (int) ((eastMost - westMost) / this->SpatialResolution[0] + 1.0); + this->NumberOfRows = (int) ((northMost - southMost) / this->SpatialResolution[1] + 1.0); + + // + // convert to extent + // + extent[0] = 0; extent[1] = this->NumberOfColumns - 1; + extent[2] = 0; extent[3] = this->NumberOfRows - 1; + extent[4] = 0; extent[5] = 0;; + + // + // compute the spacing in meters + // + planeConversion = 1.0; + if (this->PlaneUnitOfMeasure == 1) // feet + { + planeConversion = VTK_METERS_PER_FEET; + } + else if (this->PlaneUnitOfMeasure == 3) // arc-seconds + { + planeConversion = VTK_METERS_PER_ARC_SECOND; + } + + // + // get the origin from the ground coordinates + // + origin[0] = this->GroundCoords[VTK_SW][0]; + origin[1] = this->GroundCoords[VTK_SW][1]; + if ( this->ElevationReference == REFERENCE_ELEVATION_BOUNDS ) + { + origin[2] = this->ElevationBounds[0]; + } + else //REFERENCE_SEA_LEVEL + { + origin[2] = 0.0; + } + + spacing[0] = this->SpatialResolution[0] * planeConversion; + spacing[1] = this->SpatialResolution[1] * planeConversion; + spacing[2] = 0; +} + +int vtkDEMReader::ReadProfiles (vtkImageData *data) +{ + char record[145]; + float *outPtr, *ptr; + float elevationExtrema[2]; + float localElevation; + float planCoords[2]; + float units = this->SpatialResolution[2]; + float elevationConversion; + float lowPoint; + int column, row; + int columnCount; + int elevation; + int lastRow; + int numberOfColumns; + int profileId[2], profileSize[2]; + int rowId, columnId; + int updateInterval; + int status = 0; + FILE *fp; + + if (!this->FileName) + { + vtkErrorMacro(<< "A FileName must be specified."); + return -1; + } + + if ((fp = fopen(this->FileName, "rb")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return -1; + } + + vtkDebugMacro (<< "reading profiles"); + + // elevation will always be stored in meters + elevationConversion = 1.0; + if (this->ElevationUnitOfMeasure == 1) // feet + { + elevationConversion = VTK_METERS_PER_FEET; + } + else if (this->ElevationUnitOfMeasure == 3) // arc-seconds + { + elevationConversion = VTK_METERS_PER_ARC_SECOND; + } + + units *= elevationConversion; + // seek to start of profiles + fseek (fp, this->ProfileSeekOffset, SEEK_SET); + record[120] = '\0'; + + // initialize output to the lowest elevation + lowPoint = this->ElevationBounds[0]; + ptr = outPtr = (float *) data->GetScalarPointer(); + for (int i = 0; i < this->NumberOfColumns * this->NumberOfRows; i++) + { + *ptr++ = lowPoint; + } + numberOfColumns = this->NumberOfColumns; + updateInterval = numberOfColumns / 100; + columnCount = this->ProfileDimension[1]; + for (column = 0; column < columnCount; column++) + { + // + // read four int's + // + status = fscanf (fp, "%6d%6d%6d%6d", + &profileId[0], /* 1 */ + &profileId[1], /* 1 */ + &profileSize[0], /* 2 */ + &profileSize[1]); /* 2 */ + if (status == EOF) + { + break; + } + // + // read the doubles as strings so we can convert floating point format + // + (void) fscanf(fp, "%120c", record); + // + // convert any D+ or D- to E+ or E- + // + ConvertDNotationToENotation (record); + sscanf(record, "%24g%24g%24g%24g%24g", + &planCoords[0], /* 3 */ + &planCoords[1], /* 3 */ + &localElevation, /* 4 */ + &elevationExtrema[0], /* 5 */ + &elevationExtrema[1]); /* 5 */ + rowId = profileId[0] - 1; + columnId = profileId[1] - 1; + lastRow = rowId + profileSize[0] - 1; + // report progress at the start of each column + if (column % updateInterval == 0) + { + this->UpdateProgress ((float) column / ((float) columnCount - 1)); + if (this->GetAbortExecute()) + { + break; + } + } + // read a column + for (row = rowId; row <= lastRow; row++) + { + (void) fscanf(fp, "%6d", &elevation); + *(outPtr + columnId + row * numberOfColumns) = elevation * units; + } + } + fclose (fp); + + return status; +} + +// Description: Converts Fortran D notation to C++ e notation +void ConvertDNotationToENotation (char *line) +{ + char *ptr = line; + + // first convert D+ to E+ + while (*ptr && (ptr = strstr (ptr, "D+"))) + { + *ptr = 'e'; ptr++; + *ptr = '+'; ptr++; + } + + // first now D- to E- + ptr = line; + while (*ptr && (ptr = strstr (ptr, "D-"))) + { + *ptr = 'e'; ptr++; + *ptr = '-'; ptr++; + } +} + + +// Return the elevation reference. +const char *vtkDEMReader::GetElevationReferenceAsString(void) +{ + if ( this->ElevationReference == REFERENCE_SEA_LEVEL ) + { + return "Sea Level"; + } + else // REFERENCE_ELEVATION_BOUNDS + { + return "Elevation Bounds"; + } +} + + +void vtkDEMReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + if (this->FileName) + { + this->UpdateInformation (); + os << indent << "MapLabel: " << this->MapLabel << "\n"; + os << indent << "DEMLevel: " << this->DEMLevel << "\n"; + os << indent << "ElevationPattern: " << this->ElevationPattern + << (this->ElevationPattern == 1 ? " (regular)" : " (random)") << "\n"; + os << indent << "GroundSystem: " << this->GroundSystem; + if (this->GroundSystem == 0) + { + os << " (Geographic)\n"; + } + else if (this->GroundSystem == 1) + { + os << " (UTM)\n"; + } + else if (this->GroundSystem == 2) + { + os << " (State plane)\n"; + } + else + { + os << " (unknown)\n"; + } + os << indent << "GroundZone: " << this->GroundZone << "\n"; + os << indent << "ElevationRefernce: " << this->GetElevationReferenceAsString() << "\n"; + os << indent << "ProjectionParameters: all zero" << "\n"; // this->ProjectionParameters + os << indent << "PlaneUnitOfMeasure: " << this->PlaneUnitOfMeasure; + if (this->PlaneUnitOfMeasure == 0) + { + os << indent << " (radians)\n"; + } + else if (this->PlaneUnitOfMeasure == 1) + { + os << indent << " (feet)\n"; + } + else if (this->PlaneUnitOfMeasure == 2) + { + os << indent << " (meters)\n"; + } + else if (this->PlaneUnitOfMeasure == 3) + { + os << indent << " (arc-seconds)\n"; + } + else + { + os << indent << " (unknown)\n"; + } + + os << indent << "ElevationUnitOfMeasure: " << this->ElevationUnitOfMeasure; + if (this->ElevationUnitOfMeasure == 1) + { + os << indent << " (feet)\n"; + } + else if (this->ElevationUnitOfMeasure == 2) + { + os << indent << " (meters)\n"; + } + else + { + os << indent << " (unknown)\n"; + } + os << indent << "PolygonSize: " << this->PolygonSize << "\n"; + os << indent << "GroundCoordinates: \n"; + os << indent << " " << this->GroundCoords[0][0] << ", " << this->GroundCoords[0][1] << "\n"; + os << indent << " " << this->GroundCoords[1][0] << ", " << this->GroundCoords[1][1] << "\n"; + os << indent << " " << this->GroundCoords[2][0] << ", " << this->GroundCoords[2][1] << "\n"; + os << indent << " " << this->GroundCoords[3][0] << ", " << this->GroundCoords[3][1] << "\n"; + + os << indent << "ElevationBounds: " << this->ElevationBounds[0] << ", " + << this->ElevationBounds[1] + << " (meters)\n"; + os << indent << "LocalRotation: " << this->LocalRotation << "\n"; + os << indent << "AccuracyCode: " << this->AccuracyCode << "\n"; + os << indent << "SpatialResolution: " << this->SpatialResolution[0] << ", " + << this->SpatialResolution[1]; + if (this->PlaneUnitOfMeasure == 0) + { + os << indent << "(radians)"; + } + else if (this->PlaneUnitOfMeasure == 1) + { + os << indent << "(feet)"; + } + else if (this->PlaneUnitOfMeasure == 2) + { + os << indent << "(meters)"; + } + else if (this->PlaneUnitOfMeasure == 3) + { + os << indent << "(arc-seconds)"; + } + else + { + os << indent << " (unknown)\n"; + } + + os << indent << this->SpatialResolution[2]; + if (this->ElevationUnitOfMeasure == 1) + { + os << indent << "(feet)\n"; + } + else if (this->ElevationUnitOfMeasure == 2) + { + os << indent << "(meters)\n"; + } + else + { + os << indent << "(unknown)\n"; + } + os << indent << "ProfileDimension: " << this->ProfileDimension[0] << ", " + << this->ProfileDimension[1] << "\n"; + } +} diff --git a/IO/vtkDEMReader.h b/IO/vtkDEMReader.h new file mode 100644 index 0000000..06ecc71 --- /dev/null +++ b/IO/vtkDEMReader.h @@ -0,0 +1,171 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDEMReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDEMReader - read a digital elevation model (DEM) file +// .SECTION Description +// vtkDEMReader reads digital elevation files and creates image data. +// Digital elevation files are produced by the +// US Geological Survey. +// A complete description of the DEM file is located at the USGS site. +// The reader reads the entire dem file and create a vtkImageData that +// contains a single scalar component that is the elevation in meters. +// The spacing is also expressed in meters. A number of get methods +// provide access to fields on the header. +#ifndef __vtkDEMReader_h +#define __vtkDEMReader_h + +#include "vtkImageAlgorithm.h" + +class VTK_IO_EXPORT vtkDEMReader : public vtkImageAlgorithm +{ +public: + static vtkDEMReader *New(); + vtkTypeRevisionMacro(vtkDEMReader,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of Digital Elevation Model (DEM) file + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +//BTX + enum {REFERENCE_SEA_LEVEL=0,REFERENCE_ELEVATION_BOUNDS}; +//ETX + + // Description: + // Specify the elevation origin to use. By default, the elevation origin + // is equal to ElevationBounds[0]. A more convenient origin is to use sea + // level (i.e., a value of 0.0). + vtkSetClampMacro(ElevationReference,int,REFERENCE_SEA_LEVEL, + REFERENCE_ELEVATION_BOUNDS); + vtkGetMacro(ElevationReference,int); + void SetElevationReferenceToSeaLevel() + {this->SetElevationReference(REFERENCE_SEA_LEVEL);} + void SetElevationReferenceToElevationBounds() + {this->SetElevationReference(REFERENCE_ELEVATION_BOUNDS);} + const char *GetElevationReferenceAsString(void); + + // Description: + // An ASCII description of the map + vtkGetStringMacro(MapLabel); + + // Description: + // Code 1=DEM-1, 2=DEM_2, ... + vtkGetMacro(DEMLevel,int); + + // Description: + // Code 1=regular, 2=random, reserved for future use + vtkGetMacro(ElevationPattern, int); + + // Description: + // Ground planimetric reference system + vtkGetMacro(GroundSystem, int); + + // Description: + // Zone in ground planimetric reference system + vtkGetMacro(GroundZone, int); + + // Description: + // Map Projection parameters. All are zero. + vtkGetVectorMacro(ProjectionParameters,float,15); + + // Description: + // Defining unit of measure for ground planimetric coordinates throughout + // the file. 0 = radians, 1 = feet, 2 = meters, 3 = arc-seconds. + vtkGetMacro(PlaneUnitOfMeasure, int); + + // Description: + // Defining unit of measure for elevation coordinates throughout + // the file. 1 = feet, 2 = meters + vtkGetMacro(ElevationUnitOfMeasure, int); + + // Description: + // Number of sides in the polygon which defines the coverage of + // the DEM file. Set to 4. + vtkGetMacro(PolygonSize, int); + + // Description: + // Minimum and maximum elevation for the DEM. The units in the file + // are in ElevationUnitOfMeasure. This class converts them to meters. + vtkGetVectorMacro(ElevationBounds,float,2); + + // Description: + // Counterclockwise angle (in radians) from the primary axis of the planimetric + // reference to the primary axis of the DEM local reference system. + // IGNORED BY THIS IMPLEMENTATION. + vtkGetMacro(LocalRotation, float); + + // Description: + // Accuracy code for elevations. 0=unknown accuracy + vtkGetMacro(AccuracyCode, int); + + // Description: + // DEM spatial resolution for x,y,z. Values are expressed in units of resolution. + // Since elevations are read as integers, this permits fractional elevations. + vtkGetVectorMacro(SpatialResolution,float,3); + + // Description: + // The number of rows and columns in the DEM. + vtkGetVectorMacro(ProfileDimension,int,2); + + // Description: + // Reads the DEM Type A record to compute the extent, origin and + // spacing of the image data. The number of scalar components is set + // to 1 and the output scalar type is VTK_FLOAT. + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + +protected: + vtkDEMReader(); + ~vtkDEMReader(); + + vtkTimeStamp ReadHeaderTime; + int NumberOfColumns; + int NumberOfRows; + int WholeExtent[6]; + char *FileName; + char MapLabel[145]; + int DEMLevel; + int ElevationPattern; + int GroundSystem; + int GroundZone; + float ProjectionParameters[15]; + int PlaneUnitOfMeasure; + int ElevationUnitOfMeasure; + int PolygonSize; + float GroundCoords[4][2]; + float ElevationBounds[2]; + float LocalRotation; + int AccuracyCode; + float SpatialResolution[3]; + int ProfileDimension[2]; + int ProfileSeekOffset; + int ElevationReference; + + void ComputeExtentOriginAndSpacing (int extent[6], + double origin[6], + double spacing[6]); + int ReadTypeARecord (); + int ReadProfiles (vtkImageData *data); + virtual int RequestData( vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +private: + vtkDEMReader(const vtkDEMReader&); // Not implemented. + void operator=(const vtkDEMReader&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkDICOMImageReader.cxx b/IO/vtkDICOMImageReader.cxx new file mode 100644 index 0000000..a73a4ab --- /dev/null +++ b/IO/vtkDICOMImageReader.cxx @@ -0,0 +1,606 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDICOMImageReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDICOMImageReader.h" + +#include "vtkDirectory.h" +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +#include +#include + +#include + +#include "DICOMAppHelper.h" +#include "DICOMParser.h" + +vtkCxxRevisionMacro(vtkDICOMImageReader, "$Revision: 1.32.6.2 $"); +vtkStandardNewMacro(vtkDICOMImageReader); + +class vtkDICOMImageReaderVector : public vtkstd::vector +{ + +}; + +//---------------------------------------------------------------------------- +vtkDICOMImageReader::vtkDICOMImageReader() +{ + this->Parser = new DICOMParser(); + this->AppHelper = new DICOMAppHelper(); + this->DirectoryName = NULL; + this->PatientName = NULL; + this->StudyUID = NULL; + this->StudyID = NULL; + this->TransferSyntaxUID = NULL; + this->DICOMFileNames = new vtkDICOMImageReaderVector(); +} + +//---------------------------------------------------------------------------- +vtkDICOMImageReader::~vtkDICOMImageReader() +{ + delete this->Parser; + delete this->AppHelper; + delete this->DICOMFileNames; + + if (this->DirectoryName) + { + delete [] this->DirectoryName; + } + if (this->PatientName) + { + delete [] this->PatientName; + } + if (this->StudyUID) + { + delete [] this->StudyUID; + } + if (this->StudyID) + { + delete [] this->StudyID; + } + if (this->TransferSyntaxUID) + { + delete [] this->TransferSyntaxUID; + } +} + +//---------------------------------------------------------------------------- +void vtkDICOMImageReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if (this->DirectoryName) + { + os << "DirectoryName : " << this->DirectoryName << "\n"; + } + else + { + os << "DirectoryName : (NULL)" << "\n"; + } + if (this->FileName) + { + os << "FileName : " << this->FileName << "\n"; + } + else + { + os << "FileName : (NULL)" << "\n"; + } + +} + +//---------------------------------------------------------------------------- +int vtkDICOMImageReader::CanReadFile(const char* fname) +{ + bool canOpen = this->Parser->OpenFile((char*) fname); + if (!canOpen) + { + vtkErrorMacro("DICOMParser couldn't open : " << fname); + return 0; + } + bool canRead = this->Parser->IsDICOMFile(); + if (canRead) + { + return 1; + } + else + { + vtkErrorMacro("DICOMParser couldn't parse : " << fname); + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkDICOMImageReader::ExecuteInformation() +{ + if (this->FileName == NULL && this->DirectoryName == NULL) + { + return; + } + + if (this->FileName) + { + struct stat fs; + if ( stat(this->FileName, &fs) ) + { + vtkErrorMacro("Unable to open file " << this->FileName ); + return; + } + + this->DICOMFileNames->clear(); + this->AppHelper->Clear(); + this->Parser->ClearAllDICOMTagCallbacks(); + + this->Parser->OpenFile(this->FileName); + this->AppHelper->RegisterCallbacks(this->Parser); + + this->Parser->ReadHeader(); + this->SetupOutputInformation(1); + } + else if (this->DirectoryName) + { + vtkDirectory* dir = vtkDirectory::New(); + int opened = dir->Open(this->DirectoryName); + if (!opened) + { + vtkErrorMacro("Couldn't open " << this->DirectoryName); + dir->Delete(); + return; + } + int numFiles = dir->GetNumberOfFiles(); + + vtkDebugMacro( << "There are " << numFiles << " files in the directory."); + + this->DICOMFileNames->clear(); + this->AppHelper->Clear(); + + for (int i = 0; i < numFiles; i++) + { + if (strcmp(dir->GetFile(i), ".") == 0 || + strcmp(dir->GetFile(i), "..") == 0) + { + continue; + } + + vtkstd::string fileString = this->DirectoryName; + fileString += "/"; + fileString += dir->GetFile(i); + + int val = this->CanReadFile(fileString.c_str()); + + if (val == 1) + { + vtkDebugMacro( << "Adding " << fileString.c_str() << " to DICOMFileNames."); + this->DICOMFileNames->push_back(fileString); + } + else + { + vtkDebugMacro( << fileString.c_str() << " - DICOMParser CanReadFile returned : " << val); + } + + } + vtkstd::vector::iterator iter; + + for (iter = this->DICOMFileNames->begin(); + iter != this->DICOMFileNames->end(); + iter++) + { + char* fn = (char*) (*iter).c_str(); + vtkDebugMacro( << "Trying : " << fn); + + bool couldOpen = this->Parser->OpenFile(fn); + if (!couldOpen) + { + dir->Delete(); + return; + } + + // + this->Parser->ClearAllDICOMTagCallbacks(); + this->AppHelper->RegisterCallbacks(this->Parser); + + this->Parser->ReadHeader(); + + vtkDebugMacro( << "File name : " << fn ); + vtkDebugMacro( << "Slice number : " << this->AppHelper->GetSliceNumber()); + } + + vtkstd::vector > sortedFiles; + + this->AppHelper->GetImagePositionPatientFilenamePairs(sortedFiles, false); + this->SetupOutputInformation(static_cast(sortedFiles.size())); + + //this->AppHelper->OutputSeries(); + + if (sortedFiles.size() > 0) + { + this->DICOMFileNames->clear(); + vtkstd::vector >::iterator siter; + for (siter = sortedFiles.begin(); + siter != sortedFiles.end(); + siter++) + { + vtkDebugMacro(<< "Sorted filename : " << (*siter).second.c_str()); + vtkDebugMacro(<< "Adding file " << (*siter).second.c_str() << " at slice : " << (*siter).first); + this->DICOMFileNames->push_back((*siter).second); + } + } + else + { + vtkErrorMacro( << "Couldn't get sorted files. Slices may be in wrong order!"); + } + dir->Delete(); + } + +} + +//---------------------------------------------------------------------------- +void vtkDICOMImageReader::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + if (!this->FileName && this->DICOMFileNames->size() == 0) + { + vtkErrorMacro( << "Either a filename was not specified or the specified directory does not contain any DICOM images."); + return; + } + + data->GetPointData()->GetScalars()->SetName("DICOMImage"); + + this->ComputeDataIncrements(); + + if (this->FileName) + { + vtkDebugMacro( << "Single file : " << this->FileName); + this->Parser->ClearAllDICOMTagCallbacks(); + this->Parser->OpenFile(this->FileName); + this->AppHelper->Clear(); + this->AppHelper->RegisterCallbacks(this->Parser); + this->AppHelper->RegisterPixelDataCallback(this->Parser); + + this->Parser->ReadHeader(); + + void* imgData = NULL; + DICOMParser::VRTypes dataType; + unsigned long imageDataLength; + + this->AppHelper->GetImageData(imgData, dataType, imageDataLength); + + void* buffer = data->GetScalarPointer(); + if (buffer == NULL) + { + vtkErrorMacro(<< "No memory allocated for image data!"); + return; + } + // DICOM stores the upper left pixel as the first pixel in an + // image. VTK stores the lower left pixel as the first pixel in + // an image. Need to flip the data. + vtkIdType rowLength; + rowLength = this->DataIncrements[1]; + unsigned char *b = (unsigned char *)buffer; + unsigned char *iData = (unsigned char *)imgData; + iData += (imageDataLength - rowLength); // beginning of last row + for (int i=0; i < this->AppHelper->GetHeight(); ++i) + { + memcpy(b, iData, rowLength); + b += rowLength; + iData -= rowLength; + } + } + else if (this->DICOMFileNames->size() > 0) + { + vtkDebugMacro( << "Multiple files (" << static_cast(this->DICOMFileNames->size()) << ")"); + this->Parser->ClearAllDICOMTagCallbacks(); + this->AppHelper->Clear(); + this->AppHelper->RegisterCallbacks(this->Parser); + this->AppHelper->RegisterPixelDataCallback(this->Parser); + + void* buffer = data->GetScalarPointer(); + if (buffer == NULL) + { + vtkErrorMacro(<< "No memory allocated for image data!"); + return; + } + + vtkstd::vector::iterator fiter; + + int count = 0; + int numFiles = static_cast(this->DICOMFileNames->size()); + + for (fiter = this->DICOMFileNames->begin(); + fiter != this->DICOMFileNames->end(); + fiter++) + { + count++; + vtkDebugMacro( << "File : " << (*fiter).c_str()); + this->Parser->OpenFile((char*)(*fiter).c_str()); + this->Parser->ReadHeader(); + + void* imgData = NULL; + DICOMParser::VRTypes dataType; + unsigned long imageDataLengthInBytes; + + this->AppHelper->GetImageData(imgData, dataType, imageDataLengthInBytes); + + // DICOM stores the upper left pixel as the first pixel in an + // image. VTK stores the lower left pixel as the first pixel in + // an image. Need to flip the data. + vtkIdType rowLength; + rowLength = this->DataIncrements[1]; + unsigned char *b = (unsigned char *)buffer; + unsigned char *iData = (unsigned char *)imgData; + iData += (imageDataLengthInBytes - rowLength); // beginning of last row + for (int i=0; i < this->AppHelper->GetHeight(); ++i) + { + memcpy(b, iData, rowLength); + b += rowLength; + iData -= rowLength; + } + buffer = ((char*) buffer) + imageDataLengthInBytes; + + this->UpdateProgress(float(count)/float(numFiles)); + int len = static_cast (strlen((char*) (*fiter).c_str())); + char* filename = new char[len+1]; + strcpy(filename, (char*) (*fiter).c_str()); + this->SetProgressText(filename); + delete[] filename; + } + } +} + +//---------------------------------------------------------------------------- +void vtkDICOMImageReader::SetupOutputInformation(int num_slices) +{ + int width = this->AppHelper->GetWidth(); + int height = this->AppHelper->GetHeight(); + int bit_depth = this->AppHelper->GetBitsAllocated(); + int num_comp = this->AppHelper->GetNumberOfComponents(); + + this->DataExtent[0] = 0; + this->DataExtent[1] = width - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = height - 1; + this->DataExtent[4] = 0; + this->DataExtent[5] = num_slices - 1; + + bool isFloat = this->AppHelper->RescaledImageDataIsFloat(); + + bool sign = this->AppHelper->RescaledImageDataIsSigned(); + + if (isFloat) + { + this->SetDataScalarTypeToFloat(); + } + else if (bit_depth <= 8) + { + this->SetDataScalarTypeToUnsignedChar(); + } + else + { + if (sign) + { + this->SetDataScalarTypeToShort(); + } + else + { + this->SetDataScalarTypeToUnsignedShort(); + } + } + this->SetNumberOfScalarComponents(num_comp); + + this->GetPixelSpacing(); + + this->vtkImageReader2::ExecuteInformation(); +} + +//---------------------------------------------------------------------------- +void vtkDICOMImageReader::SetDirectoryName(const char* dn) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this << + "): setting DirectoryName to " << (dn ? dn : "(null)") ); + if ( this->DirectoryName == NULL && dn == NULL) + { + return; + } + if (this->FileName) + { + delete [] this->FileName; + this->FileName = NULL; + } + if ( this->DirectoryName && dn && (!strcmp(this->DirectoryName,dn))) + { + return; + } + if (this->DirectoryName) + { + delete [] this->DirectoryName; + } + if (dn) + { + this->DirectoryName = new char[strlen(dn)+1]; + strcpy(this->DirectoryName,dn); + } + else + { + this->DirectoryName = NULL; + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +double* vtkDICOMImageReader::GetPixelSpacing() +{ + vtkstd::vector > sortedFiles; + + this->AppHelper->GetImagePositionPatientFilenamePairs(sortedFiles, false); + + float* spacing = this->AppHelper->GetPixelSpacing(); + this->DataSpacing[0] = spacing[0]; + this->DataSpacing[1] = spacing[1]; + + if (sortedFiles.size() > 1) + { + vtkstd::pair p1 = sortedFiles[0]; + vtkstd::pair p2 = sortedFiles[1]; + this->DataSpacing[2] = fabs(p1.first - p2.first); + } + else + { + this->DataSpacing[2] = spacing[2]; + } + + return this->DataSpacing; +} + +//---------------------------------------------------------------------------- +int vtkDICOMImageReader::GetWidth() +{ + return this->AppHelper->GetWidth(); +} + +//---------------------------------------------------------------------------- +int vtkDICOMImageReader::GetHeight() +{ + return this->AppHelper->GetHeight(); +} + +//---------------------------------------------------------------------------- +float* vtkDICOMImageReader::GetImagePositionPatient() +{ + return this->AppHelper->GetImagePositionPatient(); +} + +//---------------------------------------------------------------------------- +float* vtkDICOMImageReader::GetImageOrientationPatient() +{ + return this->AppHelper->GetImageOrientationPatient(); +} + +//---------------------------------------------------------------------------- +int vtkDICOMImageReader::GetBitsAllocated() +{ + return this->AppHelper->GetBitsAllocated(); +} + +//---------------------------------------------------------------------------- +int vtkDICOMImageReader::GetPixelRepresentation() +{ + return this->AppHelper->GetPixelRepresentation(); +} + +//---------------------------------------------------------------------------- +int vtkDICOMImageReader::GetNumberOfComponents() +{ + return this->AppHelper->GetNumberOfComponents(); +} + +//---------------------------------------------------------------------------- +const char* vtkDICOMImageReader::GetTransferSyntaxUID() +{ + vtkstd::string tmp = this->AppHelper->GetTransferSyntaxUID(); + + if (this->TransferSyntaxUID) + { + delete [] this->TransferSyntaxUID; + } + this->TransferSyntaxUID = new char[tmp.length()+1]; + strcpy(this->TransferSyntaxUID, tmp.c_str()); + this->TransferSyntaxUID[tmp.length()] = '\0'; + + return this->TransferSyntaxUID; +} + +//---------------------------------------------------------------------------- +float vtkDICOMImageReader::GetRescaleSlope() +{ + return this->AppHelper->GetRescaleSlope(); +} + +//---------------------------------------------------------------------------- +float vtkDICOMImageReader::GetRescaleOffset() +{ + return this->AppHelper->GetRescaleOffset(); +} + +//---------------------------------------------------------------------------- +const char* vtkDICOMImageReader::GetPatientName() +{ + vtkstd::string tmp = this->AppHelper->GetPatientName(); + + if (this->PatientName) + { + delete [] this->PatientName; + } + this->PatientName = new char[tmp.length()+1]; + strcpy(this->PatientName, tmp.c_str()); + this->PatientName[tmp.length()] = '\0'; + + return this->PatientName; +} + +//---------------------------------------------------------------------------- +const char* vtkDICOMImageReader::GetStudyUID() +{ + vtkstd::string tmp = this->AppHelper->GetStudyUID(); + + if (this->StudyUID) + { + delete [] this->StudyUID; + } + this->StudyUID = new char[tmp.length()+1]; + strcpy(this->StudyUID, tmp.c_str()); + this->StudyUID[tmp.length()] = '\0'; + + return this->StudyUID; +} + +//---------------------------------------------------------------------------- +const char* vtkDICOMImageReader::GetStudyID() +{ + vtkstd::string tmp = this->AppHelper->GetStudyID(); + + if (this->StudyID) + { + delete [] this->StudyID; + } + this->StudyID = new char[tmp.length()+1]; + strcpy(this->StudyID, tmp.c_str()); + this->StudyID[tmp.length()] = '\0'; + + return this->StudyID; +} + +//---------------------------------------------------------------------------- +float vtkDICOMImageReader::GetGantryAngle() +{ + return this->AppHelper->GetGantryAngle(); +} + +//---------------------------------------------------------------------------- +int vtkDICOMImageReader::GetNumberOfDICOMFileNames() +{ + return static_cast(this->DICOMFileNames->size()); +} + +//---------------------------------------------------------------------------- +const char* vtkDICOMImageReader::GetDICOMFileName(int index) +{ + if(index >= 0 && index < this->GetNumberOfDICOMFileNames()) + { + return (*this->DICOMFileNames)[index].c_str(); + } + return 0; +} + diff --git a/IO/vtkDICOMImageReader.h b/IO/vtkDICOMImageReader.h new file mode 100644 index 0000000..5c4e08f --- /dev/null +++ b/IO/vtkDICOMImageReader.h @@ -0,0 +1,219 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDICOMImageReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDICOMImageReader - Reads some DICOM images +// .SECTION Description +// DICOM (stands for Digital Imaging in COmmunications and Medicine) +// is a medical image file format widely used to exchange data, provided +// by various modalities. +// .SECTION Warnings +// This reader might eventually handle ACR-NEMA file (predecessor of the DICOM +// format for medical images). +// This reader does not handle encapsulated format, only plain raw file are +// handled. This reader also does not handle multi-frames DICOM datasets. +// .SECTION See Also +// vtkBMPReader vtkPNMReader vtkTIFFReader + +#ifndef __vtkDICOMImageReader_h +#define __vtkDICOMImageReader_h + +#include "vtkImageReader2.h" + +//BTX +class vtkDICOMImageReaderVector; +class DICOMParser; +class DICOMAppHelper; +//ETX + +class VTK_IO_EXPORT vtkDICOMImageReader : public vtkImageReader2 +{ + public: + // Description: + // Static method for construction. + static vtkDICOMImageReader *New(); + vtkTypeRevisionMacro(vtkDICOMImageReader,vtkImageReader2); + + // Description: + // Prints the ivars. + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the filename for the file to read. If this method is used, + // the reader will only read a single file. + void SetFileName(const char* fn) + { + if (this->DirectoryName) + { + delete [] this->DirectoryName; + } + if (this->FileName) + { + delete [] this->FileName; + } + this->DirectoryName = NULL; + this->FileName = NULL; + this->vtkImageReader2::SetFileName(fn); + } + + // Description: + // Set the directory name for the reader to look in for DICOM + // files. If this method is used, the reader will try to find + // all the DICOM files in a directory. It will select the subset + // corresponding to the first series UID it stumbles across and + // it will try to build an ordered volume from them based on + // the slice number. The volume building will be upgraded to + // something more sophisticated in the future. + void SetDirectoryName(const char* dn); + + // Description: + // Returns the directory name. + vtkGetStringMacro(DirectoryName); + + // Description: + // Returns the pixel spacing. + double* GetPixelSpacing(); + + // Description: + // Returns the image width. + int GetWidth(); + + // Description: + // Returns the image height. + int GetHeight(); + + // Description: + // Get the (DICOM) x,y,z coordinates of the first pixel in the + // image (upper left hand corner) of the last image processed by the + // DICOMParser + float* GetImagePositionPatient(); + + // Description: + // Get the (DICOM) directions cosines. It consist of the components + // of the first two vectors. The third vector needs to be computed + // to form an orthonormal basis. + float* GetImageOrientationPatient(); + + // Description: + // Get the number of bits allocated for each pixel in the file. + int GetBitsAllocated(); + + // Description: + // Get the pixel representation of the last image processed by the + // DICOMParser. A zero is a unsigned quantity. A one indicates a + // signed quantity + int GetPixelRepresentation(); + + // Description: + // Get the number of components of the image data for the last + // image processed. + int GetNumberOfComponents(); + + // Description: + // Get the transfer syntax UID for the last image processed. + const char* GetTransferSyntaxUID(); + + // Description: + // Get the rescale slope for the pixel data. + float GetRescaleSlope(); + + // Description: + // Get the rescale offset for the pixel data. + float GetRescaleOffset(); + + // Description: + // Get the patient name for the last image processed. + const char* GetPatientName(); + + // Description: + // Get the study uid for the last image processed. + const char* GetStudyUID(); + + // Description: + // Get the Study ID for the last image processed. + const char* GetStudyID(); + + // Description: + // Get the gantry angle for the last image processed. + float GetGantryAngle(); + + // + // Can I read the file? + // + virtual int CanReadFile(const char* fname); + + // + // What file extensions are supported? + // + virtual const char* GetFileExtensions() + { + return ".dcm"; + } + + // Description: + // Return a descriptive name for the file format that might be useful in a GUI. + virtual const char* GetDescriptiveName() + { + return "DICOM"; + } + +protected: + // + // Setup the volume size + // + void SetupOutputInformation(int num_slices); + + virtual void ExecuteInformation(); + virtual void ExecuteData(vtkDataObject *out); + + // + // Constructor + // + vtkDICOMImageReader(); + + // + // Destructor + // + virtual ~vtkDICOMImageReader(); + + // + // Instance of the parser used to parse the file. + // + DICOMParser* Parser; + + // + // Instance of the callbacks that get the data from the file. + // + DICOMAppHelper* AppHelper; + + // + // vtkDICOMImageReaderVector wants to be a PIMPL and it will be, but not quite yet. + // + vtkDICOMImageReaderVector* DICOMFileNames; + char* DirectoryName; + + char* PatientName; + char* StudyUID; + char* StudyID; + char* TransferSyntaxUID; + + // DICOMFileNames accessor methods for subclasses: + int GetNumberOfDICOMFileNames(); + const char* GetDICOMFileName(int index); +private: + vtkDICOMImageReader(const vtkDICOMImageReader&); // Not implemented. + void operator=(const vtkDICOMImageReader&); // Not implemented. + +}; + +#endif diff --git a/IO/vtkDataCompressor.cxx b/IO/vtkDataCompressor.cxx new file mode 100644 index 0000000..cfc131a --- /dev/null +++ b/IO/vtkDataCompressor.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataCompressor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataCompressor.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkDataCompressor, "$Revision: 1.2 $"); + +//---------------------------------------------------------------------------- +vtkDataCompressor::vtkDataCompressor() +{ +} + +//---------------------------------------------------------------------------- +vtkDataCompressor::~vtkDataCompressor() +{ +} + +//---------------------------------------------------------------------------- +void vtkDataCompressor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +unsigned long +vtkDataCompressor::Compress(const unsigned char* uncompressedData, + unsigned long uncompressedSize, + unsigned char* compressedData, + unsigned long compressionSpace) +{ + return this->CompressBuffer(uncompressedData, uncompressedSize, + compressedData, compressionSpace); +} + +//---------------------------------------------------------------------------- +unsigned long +vtkDataCompressor::Uncompress(const unsigned char* compressedData, + unsigned long compressedSize, + unsigned char* uncompressedData, + unsigned long uncompressedSize) +{ + return this->UncompressBuffer(compressedData, compressedSize, + uncompressedData, uncompressedSize); +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray* +vtkDataCompressor::Compress(const unsigned char* uncompressedData, + unsigned long uncompressedSize) +{ + // Get the amount of space needed for compressed data. + unsigned long compressionSpace = + this->GetMaximumCompressionSpace(uncompressedSize); + + // Allocate a buffer. + vtkUnsignedCharArray* outputArray = vtkUnsignedCharArray::New(); + outputArray->SetNumberOfComponents(1); + outputArray->SetNumberOfTuples(compressionSpace); + unsigned char* compressedData = outputArray->GetPointer(0); + + // Compress the data. + unsigned long compressedSize = + this->CompressBuffer(uncompressedData, uncompressedSize, + compressedData, compressionSpace); + + // Make sure compression succeeded. + if(!compressedSize) + { + outputArray->Delete(); + return 0; + } + + // Store the actual size. + outputArray->SetNumberOfTuples(compressedSize); + + return outputArray; +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray* +vtkDataCompressor::Uncompress(const unsigned char* compressedData, + unsigned long compressedSize, + unsigned long uncompressedSize) +{ + // Allocate a buffer. + vtkUnsignedCharArray* outputArray = vtkUnsignedCharArray::New(); + outputArray->SetNumberOfComponents(1); + outputArray->SetNumberOfTuples(uncompressedSize); + unsigned char* uncompressedData = outputArray->GetPointer(0); + + // Decompress the data. + unsigned long decSize = + this->UncompressBuffer(compressedData, compressedSize, + uncompressedData, uncompressedSize); + + // Make sure the decompression succeeded. + if(!decSize) + { + outputArray->Delete(); + return 0; + } + + // Store the actual size. + outputArray->SetNumberOfTuples(decSize); + + return outputArray; +} diff --git a/IO/vtkDataCompressor.h b/IO/vtkDataCompressor.h new file mode 100644 index 0000000..dc14142 --- /dev/null +++ b/IO/vtkDataCompressor.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataCompressor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataCompressor - Abstract interface for data compression classes. +// .SECTION Description +// vtkDataCompressor provides a universal interface for data +// compression. Subclasses provide one compression method and one +// decompression method. The public interface to all compressors +// remains the same, and is defined by this class. + +#ifndef __vtkDataCompressor_h +#define __vtkDataCompressor_h + +#include "vtkObject.h" + +class vtkUnsignedCharArray; + +class VTK_IO_EXPORT vtkDataCompressor : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkDataCompressor,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the maximum space that may be needed to store data of the + // given uncompressed size after compression. This is the minimum + // size of the output buffer that can be passed to the four-argument + // Compress method. + virtual unsigned long GetMaximumCompressionSpace(unsigned long size)=0; + + // Description: + // Compress the given input data buffer into the given output + // buffer. The size of the output buffer must be at least as large + // as the value given by GetMaximumCompressionSpace for the given + // input size. + unsigned long Compress(const unsigned char* uncompressedData, + unsigned long uncompressedSize, + unsigned char* compressedData, + unsigned long compressionSpace); + + // Description: + // Uncompress the given input data into the given output buffer. + // The size of the uncompressed data must be known by the caller. + // It should be transmitted from the compressor by a means outside + // of this class. + unsigned long Uncompress(const unsigned char* compressedData, + unsigned long compressedSize, + unsigned char* uncompressedData, + unsigned long uncompressedSize); + + // Description: + // Compress the given data. A vtkUnsignedCharArray containing the + // compressed data is returned with a reference count of 1. + vtkUnsignedCharArray* Compress(const unsigned char* uncompressedData, + unsigned long uncompressedSize); + + // Description: + // Uncompress the given data. A vtkUnsignedCharArray containing the + // compressed data is returned with a reference count of 1. The + // size of the uncompressed data must be known by the caller. It + // should be transmitted from the compressor by a means outside of + // this class. + vtkUnsignedCharArray* Uncompress(const unsigned char* compressedData, + unsigned long compressedSize, + unsigned long uncompressedSize); +protected: + vtkDataCompressor(); + ~vtkDataCompressor(); + + // Actual compression method. This must be provided by a subclass. + // Must return the size of the compressed data, or zero on error. + virtual unsigned long CompressBuffer(const unsigned char* uncompressedData, + unsigned long uncompressedSize, + unsigned char* compressedData, + unsigned long compressionSpace)=0; + // Actual decompression method. This must be provided by a subclass. + // Must return the size of the uncompressed data, or zero on error. + virtual unsigned long UncompressBuffer(const unsigned char* compressedData, + unsigned long compressedSize, + unsigned char* uncompressedData, + unsigned long uncompressedSize)=0; +private: + vtkDataCompressor(const vtkDataCompressor&); // Not implemented. + void operator=(const vtkDataCompressor&); // Not implemented. +}; + +#endif diff --git a/IO/vtkDataObjectReader.cxx b/IO/vtkDataObjectReader.cxx new file mode 100644 index 0000000..9264096 --- /dev/null +++ b/IO/vtkDataObjectReader.cxx @@ -0,0 +1,121 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataObjectReader.h" + +#include "vtkObjectFactory.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkFieldData.h" +#include "vtkDataObject.h" + +vtkCxxRevisionMacro(vtkDataObjectReader, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkDataObjectReader); + +vtkDataObjectReader::vtkDataObjectReader() +{ + vtkDataObject *output = vtkDataObject::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +vtkDataObjectReader::~vtkDataObjectReader() +{ +} + +//---------------------------------------------------------------------------- +vtkDataObject *vtkDataObjectReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkDataObjectReader::GetOutput(int port) +{ + return vtkDataObject::SafeDownCast(this->GetOutputDataObject(port)); +} + +//---------------------------------------------------------------------------- +void vtkDataObjectReader::SetOutput(vtkDataObject *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +int vtkDataObjectReader::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataObject *output = outInfo->Get(vtkDataObject::DATA_OBJECT()); + + char line[256]; + vtkFieldData *field=NULL; + + vtkDebugMacro(<<"Reading vtk field data..."); + + if ( !(this->OpenVTKFile()) || !this->ReadHeader()) + { + return 1; + } + + // Read field data until end-of-file + // + while (this->ReadString(line) && !field ) + { + if ( !strncmp(this->LowerCase(line),"field",(unsigned long)5) ) + { + field = this->ReadFieldData(); //reads named field (or first found) + if ( field != NULL ) + { + output->SetFieldData(field); + field->Delete(); + } + } + + else if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + vtkErrorMacro(<<"Field reader cannot read datasets"); + this->CloseVTKFile(); + return 1; + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + this->CloseVTKFile(); + return 1; + } + } + //while field not read + + this->CloseVTKFile(); + + return 1; +} + +int vtkDataObjectReader::FillOutputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject"); + return 1; +} + +void vtkDataObjectReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkDataObjectReader.h b/IO/vtkDataObjectReader.h new file mode 100644 index 0000000..98873a2 --- /dev/null +++ b/IO/vtkDataObjectReader.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataObjectReader - read vtk field data file +// .SECTION Description +// vtkDataObjectReader is a source object that reads ASCII or binary field +// data files in vtk format. Fields are general matrix structures used +// represent complex data. (See text for format details). The output of this +// reader is a single vtkDataObject. The superclass of this class, +// vtkDataReader, provides many methods for controlling the reading of the +// data file, see vtkDataReader for more information. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// .SECTION See Also +// vtkFieldData vtkDataObjectWriter + +#ifndef __vtkDataObjectReader_h +#define __vtkDataObjectReader_h + +#include "vtkDataReader.h" + +class vtkDataObject; + +class VTK_IO_EXPORT vtkDataObjectReader : public vtkDataReader +{ +public: + static vtkDataObjectReader *New(); + vtkTypeRevisionMacro(vtkDataObjectReader,vtkDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output field of this reader. + vtkDataObject *GetOutput(); + vtkDataObject *GetOutput(int idx); + void SetOutput(vtkDataObject *); + +protected: + vtkDataObjectReader(); + ~vtkDataObjectReader(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkDataObjectReader(const vtkDataObjectReader&); // Not implemented. + void operator=(const vtkDataObjectReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkDataObjectWriter.cxx b/IO/vtkDataObjectWriter.cxx new file mode 100644 index 0000000..efff2af --- /dev/null +++ b/IO/vtkDataObjectWriter.cxx @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataObjectWriter.h" + +#include "vtkDataObject.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDataObjectWriter, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkDataObjectWriter); + +vtkDataObjectWriter::vtkDataObjectWriter() +{ + this->Writer = vtkDataWriter::New(); +} + +vtkDataObjectWriter::~vtkDataObjectWriter() +{ + this->Writer->Delete(); +} + +// Write FieldData data to file +void vtkDataObjectWriter::WriteData() +{ + ostream *fp; + vtkFieldData *f=this->GetInput()->GetFieldData(); + + vtkDebugMacro(<<"Writing vtk FieldData data..."); + + if ( !(fp=this->Writer->OpenVTKFile()) || !this->Writer->WriteHeader(fp) ) + { + return; + } + // + // Write FieldData data specific stuff + // + this->Writer->WriteFieldData(fp, f); + + this->Writer->CloseVTKFile(fp); +} + +void vtkDataObjectWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->Writer->GetFileName() ? this->Writer->GetFileName() : "(none)") << "\n"; + + if ( this->Writer->GetFileType() == VTK_BINARY ) + { + os << indent << "File Type: BINARY\n"; + } + else + { + os << indent << "File Type: ASCII\n"; + } + + if ( this->Writer->GetHeader() ) + { + os << indent << "Header: " << this->Writer->GetHeader() << "\n"; + } + else + { + os << indent << "Header: (None)\n"; + } + + if ( this->Writer->GetFieldDataName() ) + { + os << indent << "Field Data Name: " << this->Writer->GetFieldDataName() << "\n"; + } + else + { + os << indent << "Field Data Name: (None)\n"; + } +} + +int vtkDataObjectWriter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject"); + return 1; +} diff --git a/IO/vtkDataObjectWriter.h b/IO/vtkDataObjectWriter.h new file mode 100644 index 0000000..5d61374 --- /dev/null +++ b/IO/vtkDataObjectWriter.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataObjectWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataObjectWriter - write vtk field data +// .SECTION Description +// vtkDataObjectWriter is a source object that writes ASCII or binary +// field data files in vtk format. Field data is a general form of data in +// matrix form. + +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. + +// .SECTION See Also +// vtkFieldData vtkFieldDataReader + +#ifndef __vtkDataObjectWriter_h +#define __vtkDataObjectWriter_h + +#include "vtkWriter.h" +#include "vtkDataWriter.h" // Neds data because it calls methods on it + +class VTK_IO_EXPORT vtkDataObjectWriter : public vtkWriter +{ +public: + static vtkDataObjectWriter *New(); + vtkTypeRevisionMacro(vtkDataObjectWriter,vtkWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods delegated to vtkDataWriter, see vtkDataWriter. + void SetFileName(const char *filename) {this->Writer->SetFileName(filename);}; + char *GetFileName() {return this->Writer->GetFileName();}; + void SetHeader(const char *header) {this->Writer->SetHeader(header);}; + char *GetHeader() {return this->Writer->GetHeader();}; + void SetFileType(int type) {this->Writer->SetFileType(type);}; + int GetFileType() {return this->Writer->GetFileType();}; + void SetFileTypeToASCII() {this->Writer->SetFileType(VTK_ASCII);}; + void SetFileTypeToBinary() {this->Writer->SetFileType(VTK_BINARY);}; + void SetFieldDataName(const char *fieldname) {this->Writer->SetFieldDataName(fieldname);}; + char *GetFieldDataName() {return this->Writer->GetFieldDataName();}; + +protected: + vtkDataObjectWriter(); + ~vtkDataObjectWriter(); + + void WriteData(); + vtkDataWriter *Writer; + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkDataObjectWriter(const vtkDataObjectWriter&); // Not implemented. + void operator=(const vtkDataObjectWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkDataReader.cxx b/IO/vtkDataReader.cxx new file mode 100644 index 0000000..9f4fbea --- /dev/null +++ b/IO/vtkDataReader.cxx @@ -0,0 +1,2269 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataReader.h" + +#include "vtkBitArray.h" +#include "vtkByteSwap.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkRectilinearGrid.h" +#include "vtkShortArray.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include +#include + +vtkCxxRevisionMacro(vtkDataReader, "$Revision: 1.133 $"); +vtkStandardNewMacro(vtkDataReader); + +vtkCxxSetObjectMacro(vtkDataReader, InputArray, vtkCharArray); + +// this undef is required on the hp. vtkMutexLock ends up including +// /usr/inclue/dce/cma_ux.h which has the gall to #define read as cma_read + +#ifdef read +#undef read +#endif + +// Construct object. +vtkDataReader::vtkDataReader() +{ + this->FileType = VTK_ASCII; + this->FileName = NULL; + this->ScalarsName = NULL; + this->VectorsName = NULL; + this->TensorsName = NULL; + this->NormalsName = NULL; + this->TCoordsName = NULL; + this->LookupTableName = NULL; + this->FieldDataName = NULL; + this->ScalarLut = NULL; + this->InputString = NULL; + this->InputStringLength = 0; + this->InputStringPos = 0; + this->ReadFromInputString = 0; + this->IS = NULL; + this->Header = NULL; + + this->InputArray = 0; + + this->NumberOfScalarsInFile = 0; + this->ScalarsNameInFile = NULL; + this->ScalarsNameAllocSize = 0; + this->NumberOfVectorsInFile = 0; + this->VectorsNameInFile = NULL; + this->VectorsNameAllocSize = 0; + this->NumberOfTensorsInFile = 0; + this->TensorsNameInFile = NULL; + this->TensorsNameAllocSize = 0; + this->NumberOfTCoordsInFile = 0; + this->TCoordsNameInFile = NULL; + this->TCoordsNameAllocSize = 0; + this->NumberOfNormalsInFile = 0; + this->NormalsNameInFile = NULL; + this->NormalsNameAllocSize = 0; + this->NumberOfFieldDataInFile = 0; + this->FieldDataNameInFile = NULL; + this->FieldDataNameAllocSize = 0; + + this->ReadAllScalars = 0; + this->ReadAllVectors = 0; + this->ReadAllNormals = 0; + this->ReadAllTensors = 0; + this->ReadAllColorScalars = 0; + this->ReadAllTCoords = 0; + this->ReadAllFields = 0; + + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); +} + +vtkDataReader::~vtkDataReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } + if (this->ScalarsName) + { + delete [] this->ScalarsName; + } + if (this->VectorsName) + { + delete [] this->VectorsName; + } + if (this->TensorsName) + { + delete [] this->TensorsName; + } + if (this->NormalsName) + { + delete [] this->NormalsName; + } + if (this->TCoordsName) + { + delete [] this->TCoordsName; + } + if (this->LookupTableName) + { + delete [] this->LookupTableName; + } + if (this->FieldDataName) + { + delete [] this->FieldDataName; + } + if (this->ScalarLut) + { + delete [] this->ScalarLut; + } + if (this->InputString) + { + delete [] this->InputString; + } + if (this->Header) + { + delete [] this->Header; + } + + this->SetInputArray(0); + this->InitializeCharacteristics(); + if ( this->IS ) + { + delete this->IS; + } +} + +void vtkDataReader::SetInputString(const char *in) +{ + if (in != NULL) + { + this->SetInputString(in, static_cast(strlen(in))); + } + else + { + if (this->InputString) + { + delete [] this->InputString; + } + this->InputString = NULL; + } +} + +void vtkDataReader::SetBinaryInputString(const char *in, int len) +{ + this->SetInputString(in,len); +} + +void vtkDataReader::SetInputString(const char *in, int len) +{ + if (this->Debug) + { + vtkDebugMacro(<< "setting InputString to " << in ); + } + + if (this->InputString && in && strncmp(in, this->InputString, len) == 0) + { + return; + } + + if (this->InputString) + { + delete [] this->InputString; + } + if (in) + { + this->InputString = new char[len]; + memcpy(this->InputString,in,len); + this->InputStringLength = len; + } + else + { + this->InputString = NULL; + this->InputStringLength = 0; + } + this->Modified(); +} + +// Internal function to read in a line up to 256 characters. +// Returns zero if there was an error. +int vtkDataReader::ReadLine(char result[256]) +{ + this->IS->getline(result,256); + if (this->IS->fail()) + { + if (this->IS->eof()) + { + return 0; + } + if (this->IS->gcount() == 255) + { + // Read 256 chars; ignoring the rest of the line. + this->IS->clear(); + this->IS->ignore(VTK_INT_MAX, '\n'); + } + } + return 1; +} + +// Internal function to read in a string up to 256 characters. +// Returns zero if there was an error. +int vtkDataReader::ReadString(char result[256]) +{ + this->IS->width(256); + *this->IS >> result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +// Internal function to read in an integer value. +// Returns zero if there was an error. +int vtkDataReader::Read(char *result) +{ + int intData; + *this->IS >> intData; + if (this->IS->fail()) + { + return 0; + } + + *result = (char) intData; + return 1; +} + +int vtkDataReader::Read(unsigned char *result) +{ + int intData; + *this->IS >> intData; + if (this->IS->fail()) + { + return 0; + } + + *result = (unsigned char) intData; + return 1; +} + +int vtkDataReader::Read(short *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +int vtkDataReader::Read(unsigned short *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +int vtkDataReader::Read(int *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +int vtkDataReader::Read(unsigned int *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +int vtkDataReader::Read(long *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +int vtkDataReader::Read(unsigned long *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +int vtkDataReader::Read(float *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + +int vtkDataReader::Read(double *result) +{ + *this->IS >> *result; + if (this->IS->fail()) + { + return 0; + } + return 1; +} + + +// Open a vtk data file. Returns zero if error. +int vtkDataReader::OpenVTKFile() +{ + if (this->ReadFromInputString) + { + if (this->InputArray) + { + vtkDebugMacro(<< "Reading from InputArray"); + this->IS = new istrstream(this->InputArray->GetPointer(0), + this->InputArray->GetNumberOfTuples()* + this->InputArray->GetNumberOfComponents()); + return 1; + } + else if (this->InputString) + { + vtkDebugMacro(<< "Reading from InputString"); + this->IS = new istrstream(this->InputString, this->InputStringLength); + return 1; + } + } + else + { + vtkDebugMacro(<< "Opening vtk file"); + + if ( !this->FileName || (strlen(this->FileName) == 0)) + { + vtkErrorMacro(<< "No file specified!"); + this->SetErrorCode( vtkErrorCode::NoFileNameError ); + return 0; + } + + // first make sure the file exists, this prevents an empty file from + // being created on older compilers + struct stat fs; + if (stat(this->FileName, &fs) != 0) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + this->SetErrorCode( vtkErrorCode::CannotOpenFileError ); + return 0; + } + this->IS = new ifstream(this->FileName, ios::in); + if (this->IS->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + delete this->IS; + this->IS = NULL; + this->SetErrorCode( vtkErrorCode::CannotOpenFileError ); + return 0; + } + return 1; + } + + return 0; +} + +// Read the header of a vtk data file. Returns 0 if error. +int vtkDataReader::ReadHeader() +{ + char line[256]; + + vtkDebugMacro(<< "Reading vtk file header"); + // + // read header + // + if (!this->ReadLine(line)) + { + vtkErrorMacro(<<"Premature EOF reading first line! " << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 0; + } + if ( strncmp ("# vtk DataFile Version", line, 20) ) + { + vtkErrorMacro(<< "Unrecognized file type: "<< line << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + + this->SetErrorCode( vtkErrorCode::UnrecognizedFileTypeError ); + return 0; + } + // + // read title + // + if (!this->ReadLine(line)) + { + vtkErrorMacro(<<"Premature EOF reading title! " << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 0; + } + if (this->Header) + { + delete [] this->Header; + } + this->Header = new char[strlen(line) + 1]; + strcpy (this->Header, line); + + vtkDebugMacro(<< "Reading vtk file entitled: " << line); + // + // read type + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Premature EOF reading file type!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 0; + } + + if ( !strncmp(this->LowerCase(line), "ascii", 5) ) + { + this->FileType = VTK_ASCII; + } + else if ( !strncmp(line, "binary", 6) ) + { + this->FileType = VTK_BINARY; + } + else + { + vtkErrorMacro(<< "Unrecognized file type: "<< line << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + this->FileType = 0; + this->SetErrorCode( vtkErrorCode::UnrecognizedFileTypeError ); + return 0; + } + + // if this is a binary file we need to make sure that we opened it + // as a binary file. + if (this->FileType == VTK_BINARY && this->ReadFromInputString == 0) + { + vtkDebugMacro(<< "Opening vtk file as binary"); + delete this->IS; + this->IS = 0; +#ifdef _WIN32 + this->IS = new ifstream(this->FileName, ios::in | ios::binary); +#else + this->IS = new ifstream(this->FileName, ios::in); +#endif + if (this->IS->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + delete this->IS; + this->IS = NULL; + this->SetErrorCode( vtkErrorCode::CannotOpenFileError ); + return 0; + } + // read up to the same point in the file + this->ReadLine(line); + this->ReadLine(line); + this->ReadString(line); + } + + float progress=this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +int vtkDataReader::IsFileValid(const char *dstype) +{ + char line[1024]; + + if (!dstype) + { + return 0; + } + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 0; + } + + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 0; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 0; + } + if (strncmp(this->LowerCase(line),dstype,strlen(dstype))) + { + this->CloseVTKFile (); + return 0; + } + // everything looks good + this->CloseVTKFile(); + return 1; + } + + return 0; +} + +// Read the cell data of a vtk data file. The number of cells (from the +// dataset) must match the number of cells defined in cell attributes (unless +// no geometry was defined). +int vtkDataReader::ReadCellData(vtkDataSet *ds, int numCells) +{ + char line[256]; + vtkDataSetAttributes *a=ds->GetCellData(); + + vtkDebugMacro(<< "Reading vtk cell data"); + + // + // Read keywords until end-of-file + // + while (this->ReadString(line)) + { + // + // read scalar data + // + if ( ! strncmp(this->LowerCase(line), "scalars", 7) ) + { + if ( ! this->ReadScalarData(a, numCells) ) + { + return 0; + } + } + // + // read vector data + // + else if ( ! strncmp(line, "vectors", 7) ) + { + if ( ! this->ReadVectorData(a, numCells) ) + { + return 0; + } + } + // + // read 3x3 tensor data + // + else if ( ! strncmp(line, "tensors", 7) ) + { + if ( ! this->ReadTensorData(a, numCells) ) + { + return 0; + } + } + // + // read normals data + // + else if ( ! strncmp(line, "normals", 7) ) + { + if ( ! this->ReadNormalData(a, numCells) ) + { + return 0; + } + } + // + // read texture coordinates data + // + else if ( ! strncmp(line, "texture_coordinates", 19) ) + { + if ( ! this->ReadTCoordsData(a, numCells) ) + { + return 0; + } + } + // + // read color scalars data + // + else if ( ! strncmp(line, "color_scalars", 13) ) + { + if ( ! this->ReadCoScalarData(a, numCells) ) + { + return 0; + } + } + // + // read lookup table. Associate with scalar data. + // + else if ( ! strncmp(line, "lookup_table", 12) ) + { + if ( ! this->ReadLutData(a) ) + { + return 0; + } + } + // + // read field of data + // + else if ( ! strncmp(line, "field", 5) ) + { + vtkFieldData *f; + if ( ! (f=this->ReadFieldData()) ) + { + return 0; + } + for(int i=0; iGetNumberOfArrays(); i++) + { + a->AddArray(f->GetArray(i)); + } + f->Delete(); + } + // + // maybe bumped into point data + // + else if ( ! strncmp(line, "point_data", 10) ) + { + int npts; + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + return 0; + } + + this->ReadPointData(ds, npts); + } + + else + { + vtkErrorMacro(<< "Unsupported cell attribute type: " << line + << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + } + + return 1; +} + + +// Read the point data of a vtk data file. The number of points (from the +// dataset) must match the number of points defined in point attributes (unless +// no geometry was defined). +int vtkDataReader::ReadPointData(vtkDataSet *ds, int numPts) +{ + char line[256]; + vtkDataSetAttributes *a=ds->GetPointData(); + + vtkDebugMacro(<< "Reading vtk point data"); + + // + // Read keywords until end-of-file + // + while (this->ReadString(line)) + { + // + // read scalar data + // + if ( ! strncmp(this->LowerCase(line), "scalars", 7) ) + { + if ( ! this->ReadScalarData(a, numPts) ) + { + return 0; + } + } + // + // read vector data + // + else if ( ! strncmp(line, "vectors", 7) ) + { + if ( ! this->ReadVectorData(a, numPts) ) + { + return 0; + } + } + // + // read 3x3 tensor data + // + else if ( ! strncmp(line, "tensors", 7) ) + { + if ( ! this->ReadTensorData(a, numPts) ) + { + return 0; + } + } + // + // read normals data + // + else if ( ! strncmp(line, "normals", 7) ) + { + + if ( ! this->ReadNormalData(a, numPts) ) + { + return 0; + } + } + // + // read texture coordinates data + // + else if ( ! strncmp(line, "texture_coordinates", 19) ) + { + if ( ! this->ReadTCoordsData(a, numPts) ) + { + return 0; + } + } + // + // read color scalars data + // + else if ( ! strncmp(line, "color_scalars", 13) ) + { + if ( ! this->ReadCoScalarData(a, numPts) ) + { + return 0; + } + } + // + // read lookup table. Associate with scalar data. + // + else if ( ! strncmp(line, "lookup_table", 12) ) + { + if ( ! this->ReadLutData(a) ) + { + return 0; + } + } + // + // read field of data + // + else if ( ! strncmp(line, "field", 5) ) + { + vtkFieldData *f; + if ( ! (f=this->ReadFieldData()) ) + { + return 0; + } + for(int i=0; iGetNumberOfArrays(); i++) + { + a->AddArray(f->GetArray(i)); + } + f->Delete(); + } + // + // maybe bumped into cell data + // + else if ( ! strncmp(line, "cell_data", 9) ) + { + int ncells; + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + return 0; + } + + this->ReadCellData(ds, ncells); + } + + else + { + vtkErrorMacro(<< "Unsupported point attribute type: " << line + << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + } + + return 1; +} + +// General templated function to read data of various types. +template +int vtkReadBinaryData(istream *IS, T *data, int numTuples, int numComp) +{ + char line[256]; + + // suck up newline + IS->getline(line,256); + IS->read((char *)data, sizeof(T)*numComp*numTuples); + if (IS->eof()) + { + vtkGenericWarningMacro(<<"Error reading binary data!"); + return 0; + } + return 1; +} + +// General templated function to read data of various types. +template +int vtkReadASCIIData(vtkDataReader *self, T *data, int numTuples, int numComp) +{ + int i, j; + + for (i=0; iRead(data++) ) + { + vtkGenericWarningMacro(<<"Error reading ascii data!"); + return 0; + } + } + } + return 1; +} + +// Decription: +// Read data array. Return pointer to array object if successful read; +// otherwise return NULL. Note: this method instantiates a reference counted +// object with initial count of one; proper protocol is for you to assign +// the data object and then invoke Delete() it to restore proper reference +// count. +vtkDataArray *vtkDataReader::ReadArray(const char *dataType, int numTuples, int numComp) +{ + char *type=strdup(dataType); + type=this->LowerCase(type); + + vtkDataArray *array; + + if ( ! strncmp(type, "bit", 3) ) + { + array = vtkBitArray::New(); + array->SetNumberOfComponents(numComp); + unsigned char *ptr=((vtkBitArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + char line[256]; + this->IS->getline(line,256); + this->IS->read((char *)ptr,sizeof(unsigned char)*(numTuples*numComp+7)/8); + if (this->IS->eof()) + { + vtkErrorMacro(<<"Error reading binary bit array!"); + free(type); + return NULL; + } + } + else + { + int b; + for (int i=0; iRead(&b) ) + { + vtkErrorMacro(<<"Error reading ascii bit array! tuple: " << i << ", component: " << j); + free(type); + return NULL; + } + else + { + ((vtkBitArray *)array)->SetValue(i*numComp+j,b); + } + } + } + } + } + + else if ( ! strncmp(type, "char", 4) ) + { + array = vtkCharArray::New(); + array->SetNumberOfComponents(numComp); + char *ptr = ((vtkCharArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "unsigned_char", 13) ) + { + array = vtkUnsignedCharArray::New(); + array->SetNumberOfComponents(numComp); + unsigned char *ptr = ((vtkUnsignedCharArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "short", 5) ) + { + array = vtkShortArray::New(); + array->SetNumberOfComponents(numComp); + short *ptr = ((vtkShortArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap2BERange(ptr,numTuples*numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "unsigned_short", 14) ) + { + array = vtkUnsignedShortArray::New(); + array->SetNumberOfComponents(numComp); + unsigned short *ptr = ((vtkUnsignedShortArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap2BERange((short *)ptr,numTuples*numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "int", 3) ) + { + array = vtkIntArray::New(); + array->SetNumberOfComponents(numComp); + int *ptr = ((vtkIntArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap4BERange(ptr,numTuples*numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "unsigned_int", 12) ) + { + array = vtkUnsignedIntArray::New(); + array->SetNumberOfComponents(numComp); + unsigned int *ptr = ((vtkUnsignedIntArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap4BERange((int *)ptr,numTuples*numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "long", 4) ) + { + array = vtkLongArray::New(); + array->SetNumberOfComponents(numComp); + long *ptr = ((vtkLongArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap4BERange((int *)ptr,numTuples*numComp); + } + + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "unsigned_long", 13) ) + { + array = vtkUnsignedLongArray::New(); + array->SetNumberOfComponents(numComp); + unsigned long *ptr = ((vtkUnsignedLongArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap4BERange((int *)ptr,numTuples*numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "float", 5) ) + { + array = vtkFloatArray::New(); + array->SetNumberOfComponents(numComp); + float *ptr = ((vtkFloatArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap4BERange(ptr,numTuples*numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else if ( ! strncmp(type, "double", 6) ) + { + array = vtkDoubleArray::New(); + array->SetNumberOfComponents(numComp); + double *ptr = ((vtkDoubleArray *)array)->WritePointer(0,numTuples*numComp); + if ( this->FileType == VTK_BINARY ) + { + vtkReadBinaryData(this->IS, ptr, numTuples, numComp); + vtkByteSwap::Swap8BERange(ptr,numTuples*numComp); + } + else + { + vtkReadASCIIData(this, ptr, numTuples, numComp); + } + } + + else + { + vtkErrorMacro(<< "Unsupported data type: " << type); + free(type); + return NULL; + } + + free(type); + return array; +} + +// Read point coordinates. Return 0 if error. +int vtkDataReader::ReadPoints(vtkPointSet *ps, int numPts) +{ + char line[256]; + vtkDataArray *data; + + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Cannot read points type!" << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + + data = this->ReadArray(line, numPts, 3); + if ( data != NULL ) + { + vtkPoints *points=vtkPoints::New(); + points->SetData(data); + data->Delete(); + ps->SetPoints(points); + points->Delete(); + } + else + { + return 0; + } + + vtkDebugMacro(<<"Read " << ps->GetNumberOfPoints() << " points"); + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +// Read the coordinates for a rectilinear grid. The axes parameter specifies +// which coordinate axes (0,1,2) is being read. +int vtkDataReader::ReadCoordinates(vtkRectilinearGrid *rg, int axes, + int numCoords) +{ + char line[256]; + vtkDataArray *data; + + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Cannot read coordinates type!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + + data = this->ReadArray(line, numCoords, 1); + if ( !data ) + { + return 0; + } + + if ( axes == 0 ) + { + rg->SetXCoordinates(data); + } + else if ( axes == 1 ) + { + rg->SetYCoordinates(data); + } + else + { + rg->SetZCoordinates(data); + } + + vtkDebugMacro(<<"Read " << data->GetNumberOfTuples() << " coordinates"); + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + data->Delete(); + + return 1; +} + +// Read scalar point attributes. Return 0 if error. +int vtkDataReader::ReadScalarData(vtkDataSetAttributes *a, int numPts) +{ + char line[256], name[256], key[256], tableName[256]; + int skipScalar=0; + vtkDataArray *data; + int numComp = 1; + char buffer[1024]; + + if (!(this->ReadString(buffer) && this->ReadString(line))) + { + vtkErrorMacro(<<"Cannot read scalar header!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + + this->DecodeArrayName(name, buffer); + + if (!this->ReadString(key)) + { + vtkErrorMacro(<<"Cannot read scalar header!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + + // the next string could be an integer number of components or a lookup table + if (strcmp(this->LowerCase(key), "lookup_table")) + { + numComp = atoi(key); + if (numComp < 1 || !this->ReadString(key)) + { + vtkErrorMacro(<<"Cannot read scalar header!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + } + + if (strcmp(this->LowerCase(key), "lookup_table")) + { + vtkErrorMacro(<<"Lookup table must be specified with scalar.\n" << + "Use \"LOOKUP_TABLE default\" to use default table."); + return 0; + } + + if (!this->ReadString(tableName)) + { + vtkErrorMacro(<<"Cannot read scalar header!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + + // See whether scalar has been already read or scalar name (if specified) + // matches name in file. + // + if ( a->GetScalars() != NULL || (this->ScalarsName && strcmp(name,this->ScalarsName)) ) + { + skipScalar = 1; + } + else + { + this->SetScalarLut(tableName); //may be "default" + } + + // Read the data + data = this->ReadArray(line, numPts, numComp); + if ( data != NULL ) + { + data->SetName(name); + if ( ! skipScalar ) + { + a->SetScalars(data); + } + else if ( this->ReadAllScalars ) + { + a->AddArray(data); + } data->Delete(); + } + else + { + return 0; + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +// Read vector point attributes. Return 0 if error. +int vtkDataReader::ReadVectorData(vtkDataSetAttributes *a, int numPts) +{ + int skipVector=0; + char line[256], name[256]; + vtkDataArray *data; + char buffer[1024]; + + if (!(this->ReadString(buffer) && this->ReadString(line))) + { + vtkErrorMacro(<<"Cannot read vector data!" << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + this->DecodeArrayName(name, buffer); + + // + // See whether vector has been already read or vector name (if specified) + // matches name in file. + // + if ( a->GetVectors() != NULL || (this->VectorsName && strcmp(name,this->VectorsName)) ) + { + skipVector = 1; + } + + data = this->ReadArray(line, numPts, 3); + if ( data != NULL ) + { + data->SetName(name); + if ( ! skipVector ) + { + a->SetVectors(data); + } + else if ( this->ReadAllVectors ) + { + a->AddArray(data); + } + data->Delete(); + } + else + { + return 0; + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +// Read normal point attributes. Return 0 if error. +int vtkDataReader::ReadNormalData(vtkDataSetAttributes *a, int numPts) +{ + int skipNormal=0; + char line[256], name[256]; + vtkDataArray *data; + char buffer[1024]; + + if (!(this->ReadString(buffer) && this->ReadString(line))) + { + vtkErrorMacro(<<"Cannot read normal data!" << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + this->DecodeArrayName(name, buffer); + + // + // See whether normal has been already read or normal name (if specified) + // matches name in file. + // + if ( a->GetNormals() != NULL || (this->NormalsName && strcmp(name,this->NormalsName)) ) + { + skipNormal = 1; + } + + data = this->ReadArray(line, numPts, 3); + if ( data != NULL ) + { + data->SetName(name); + if ( ! skipNormal ) + { + a->SetNormals(data); + } + else if ( this->ReadAllNormals ) + { + a->AddArray(data); + } + data->Delete(); + } + else + { + return 0; + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +// Read tensor point attributes. Return 0 if error. +int vtkDataReader::ReadTensorData(vtkDataSetAttributes *a, int numPts) +{ + int skipTensor=0; + char line[256], name[256]; + vtkDataArray *data; + char buffer[1024]; + + if (!(this->ReadString(buffer) && this->ReadString(line))) + { + vtkErrorMacro(<<"Cannot read tensor data!" << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + this->DecodeArrayName(name, buffer); + // + // See whether tensor has been already read or tensor name (if specified) + // matches name in file. + // + if ( a->GetTensors() != NULL || (this->TensorsName && strcmp(name,this->TensorsName)) ) + { + skipTensor = 1; + } + + data = this->ReadArray(line, numPts, 9); + if ( data != NULL ) + { + data->SetName(name); + if ( ! skipTensor ) + { + a->SetTensors(data); + } + else if ( this->ReadAllTensors ) + { + a->AddArray(data); + } + data->Delete(); + } + else + { + return 0; + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +// Read color scalar point attributes. Return 0 if error. +int vtkDataReader::ReadCoScalarData(vtkDataSetAttributes *a, int numPts) +{ + int i, j, idx, numComp, skipScalar=0; + char name[256]; + char buffer[1024]; + + if (!(this->ReadString(buffer) && this->Read(&numComp))) + { + vtkErrorMacro(<<"Cannot read color scalar data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + this->DecodeArrayName(name, buffer); + // + // See whether scalar has been already read or scalar name (if specified) + // matches name in file. + // + if ( a->GetScalars() != NULL || + (this->ScalarsName && strcmp(name,this->ScalarsName)) ) + { + skipScalar = 1; + } + + // handle binary different from ASCII since they are stored + // in a different format float versus uchar + if ( this->FileType == VTK_BINARY) + { + vtkUnsignedCharArray *data; + char type[14] = "unsigned_char"; + data = (vtkUnsignedCharArray *)this->ReadArray(type, numPts, numComp); + + if ( data != NULL ) + { + data->SetName(name); + if ( ! skipScalar ) + { + a->SetScalars(data); + } + else if ( this->ReadAllColorScalars ) + { + a->AddArray(data); + } data->Delete(); + } + else + { + return 0; + } + } + else + { + vtkFloatArray *data; + char type[6] = "float"; + data = (vtkFloatArray *)this->ReadArray(type, numPts, numComp); + + if ( data != NULL ) + { + if ( ! skipScalar || this->ReadAllColorScalars ) + { + vtkUnsignedCharArray *scalars=vtkUnsignedCharArray::New(); + scalars->SetNumberOfComponents(numComp); + scalars->SetNumberOfTuples(numPts); + scalars->SetName(name); + for (i=0; iSetValue(idx,(unsigned char)(255.0*data->GetValue(idx))); + } + } + if ( ! skipScalar ) + { + a->SetScalars(scalars); + } + else if ( this->ReadAllColorScalars ) + { + a->AddArray(scalars); + } scalars->Delete(); + } + data->Delete(); + } + else + { + return 0; + } + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +// Read texture coordinates point attributes. Return 0 if error. +int vtkDataReader::ReadTCoordsData(vtkDataSetAttributes *a, int numPts) +{ + int dim; + int skipTCoord = 0; + char line[256], name[256]; + vtkDataArray *data; + char buffer[1024]; + + if (!(this->ReadString(buffer) && this->Read(&dim) && + this->ReadString(line))) + { + vtkErrorMacro(<<"Cannot read texture data!" << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + this->DecodeArrayName(name, buffer); + + if ( dim < 1 || dim > 3 ) + { + vtkErrorMacro(<< "Unsupported texture coordinates dimension: " << dim + << " for file: " << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + + // + // See whether texture coords have been already read or texture coords name + // (if specified) matches name in file. + // + if ( a->GetTCoords() != NULL || + (this->TCoordsName && strcmp(name,this->TCoordsName)) ) + { + skipTCoord = 1; + } + + data = this->ReadArray(line, numPts, dim); + if ( data != NULL ) + { + data->SetName(name); + if ( ! skipTCoord ) + { + a->SetTCoords(data); + } + else if ( this->ReadAllTCoords ) + { + a->AddArray(data); + } + data->Delete(); + } + else + { + return 0; + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +// Read lookup table. Return 0 if error. +int vtkDataReader::ReadLutData(vtkDataSetAttributes *a) +{ + int i; + int size, skipTable=0; + vtkLookupTable *lut; + unsigned char *ptr; + char line[256], name[256]; + + if (!(this->ReadString(name) && this->Read(&size))) + { + vtkErrorMacro(<<"Cannot read lookup table data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + + if ( a->GetScalars() == NULL || + (this->LookupTableName && strcmp(name,this->LookupTableName)) || + (this->ScalarLut && strcmp(name,this->ScalarLut)) ) + { + skipTable = 1; + } + + lut = vtkLookupTable::New(); + lut->Allocate(size); + ptr = lut->WritePointer(0,size); + + if ( this->FileType == VTK_BINARY) + { + // suck up newline + this->IS->getline(line,256); + this->IS->read((char *)ptr,sizeof(unsigned char)*4*size); + if (this->IS->eof()) + { + vtkErrorMacro(<<"Error reading binary lookup table!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + } + else // ascii + { + float rgba[4]; + for (i=0; iRead(rgba) && this->Read(rgba+1) && + this->Read(rgba+2) && this->Read(rgba+3))) + { + vtkErrorMacro(<<"Error reading lookup table!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + lut->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]); + } + } + + if ( ! skipTable ) + { + a->GetScalars()->SetLookupTable(lut); + } + lut->Delete(); + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + + +// Read lookup table. Return 0 if error. +int vtkDataReader::ReadCells(int size, int *data) +{ + char line[256]; + int i; + + if ( this->FileType == VTK_BINARY) + { + // suck up newline + this->IS->getline(line,256); + this->IS->read((char *)data,sizeof(int)*size); + if (this->IS->eof()) + { + vtkErrorMacro(<<"Error reading binary cell data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + vtkByteSwap::Swap4BERange(data,size); + } + else // ascii + { + for (i=0; iRead(data+i)) + { + vtkErrorMacro(<<"Error reading ascii cell data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + } + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +int vtkDataReader::ReadCells(int size, int *data, + int skip1, int read2, int skip3) +{ + char line[256]; + int i, numCellPts, junk, *tmp, *pTmp; + + if ( this->FileType == VTK_BINARY) + { + // suck up newline + this->IS->getline(line,256); + // first read all the cells as one chunk (each cell has different length). + if (skip1 == 0 && skip3 == 0) + { + tmp = data; + } + else + { + tmp = new int[size]; + } + this->IS->read((char *)tmp,sizeof(int)*size); + if (this->IS->eof()) + { + vtkErrorMacro(<<"Error reading binary cell data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + vtkByteSwap::Swap4BERange(tmp,size); + if (tmp == data) + { + return 1; + } + // skip cells before the piece + pTmp = tmp; + while (skip1 > 0) + { + // the first value is the number of point ids + // skip these plus one for the number itself. + pTmp += *pTmp + 1; + --skip1; + } + // copy the cells in the piece + // (ok, I am getting criptic with the loops and increments ...) + while (read2 > 0) + { + // the first value is the number of point ids + *data++ = i = *pTmp++; + while (i-- > 0) + { + *data++ = *pTmp++; + } + --read2; + } + // delete the temporary array + delete [] tmp; + } + else // ascii + { + // skip cells before the piece + for (i=0; iRead(&numCellPts)) + { + vtkErrorMacro(<<"Error reading ascii cell data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + while (numCellPts-- > 0) + { + this->Read(&junk); + } + } + // read the cells in the piece + for (i=0; iRead(data)) + { + vtkErrorMacro(<<"Error reading ascii cell data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + numCellPts = *data++; + while (numCellPts-- > 0) + { + this->Read(data++); + } + } + // skip cells after the piece + for (i=0; iRead(&numCellPts)) + { + vtkErrorMacro(<<"Error reading ascii cell data!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 0; + } + while (numCellPts-- > 0) + { + this->Read(&junk); + } + } + } + + float progress = this->GetProgress(); + this->UpdateProgress(progress + 0.5*(1.0 - progress)); + + return 1; +} + +vtkFieldData *vtkDataReader::ReadFieldData() +{ + int i, numArrays, skipField=0; + vtkFieldData *f; + char name[256], type[256]; + int numComp, numTuples; + vtkDataArray *data; + + if ( !(this->ReadString(name) && this->Read(&numArrays)) ) + { + vtkErrorMacro(<<"Cannot read field header!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return NULL; + } + + // See whether field data name (if specified) + if ( (this->FieldDataName && strcmp(name,this->FieldDataName)) ) + { + skipField = 1; + } + + f = vtkFieldData::New(); + f->AllocateArrays(numArrays); + + // Read the number of arrays specified + for (i=0; iReadString(buffer); + this->DecodeArrayName(name, buffer); + this->Read(&numComp); + this->Read(&numTuples); + this->ReadString(type); + data = this->ReadArray(type, numTuples, numComp); + if ( data != NULL ) + { + data->SetName(name); + if ( ! skipField || this->ReadAllFields ) + { + f->AddArray(data); + } + data->Delete(); + } + else + { + f->Delete(); + return NULL; + } + } + + if ( skipField && ! this->ReadAllFields ) + { + f->Delete(); + return NULL; + } + else + { + return f; + } +} + + +char *vtkDataReader::LowerCase(char *str, const size_t len) +{ + size_t i; + char *s; + + for ( i=0, s=str; *s != '\0' && iIS != NULL ) + { + delete this->IS; + } + this->IS = NULL; +} + +void vtkDataReader::InitializeCharacteristics() +{ + int i; + + // Release any old stuff first + if ( this->ScalarsNameInFile ) + { + for (i=0; iNumberOfScalarsInFile; i++) + { + delete [] this->ScalarsNameInFile[i]; + } + this->NumberOfScalarsInFile = 0; + delete [] this->ScalarsNameInFile; + this->ScalarsNameInFile = NULL; + } + + if ( this->VectorsNameInFile ) + { + for (i=0; iNumberOfVectorsInFile; i++) + { + delete [] this->VectorsNameInFile[i]; + } + this->NumberOfVectorsInFile = 0; + delete [] this->VectorsNameInFile; + this->VectorsNameInFile = NULL; + } + + if ( this->TensorsNameInFile ) + { + for (i=0; iNumberOfTensorsInFile; i++) + { + delete [] this->TensorsNameInFile[i]; + } + this->NumberOfTensorsInFile = 0; + delete [] this->TensorsNameInFile; + this->TensorsNameInFile = NULL; + } + + if ( this->NormalsNameInFile ) + { + for (i=0; iNumberOfNormalsInFile; i++) + { + delete [] this->NormalsNameInFile[i]; + } + this->NumberOfNormalsInFile = 0; + delete [] this->NormalsNameInFile; + this->NormalsNameInFile = NULL; + } + + if ( this->TCoordsNameInFile ) + { + for (i=0; iNumberOfTCoordsInFile; i++) + { + delete [] this->TCoordsNameInFile[i]; + } + this->NumberOfTCoordsInFile = 0; + delete [] this->TCoordsNameInFile; + this->TCoordsNameInFile = NULL; + } + + if ( this->FieldDataNameInFile ) + { + for (i=0; iNumberOfFieldDataInFile; i++) + { + delete [] this->FieldDataNameInFile[i]; + } + this->NumberOfFieldDataInFile = 0; + delete [] this->FieldDataNameInFile; + this->FieldDataNameInFile = NULL; + } + +} + +//read entire file, storing important characteristics +int vtkDataReader::CharacterizeFile() +{ + if ( this->CharacteristicsTime > this->MTime ) + { + return 1; + } + + this->InitializeCharacteristics(); + this->CharacteristicsTime.Modified(); + + // Open the file + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 0; + } + + char line[256]; + while (this->ReadLine(line)) + { + this->CheckFor("scalars", line, this->NumberOfScalarsInFile, + this->ScalarsNameInFile, this->ScalarsNameAllocSize); + this->CheckFor("vectors", line, this->NumberOfVectorsInFile, + this->VectorsNameInFile, this->VectorsNameAllocSize); + this->CheckFor("tensors", line, this->NumberOfTensorsInFile, + this->TensorsNameInFile, this->TensorsNameAllocSize); + this->CheckFor("normals", line, this->NumberOfNormalsInFile, + this->NormalsNameInFile, this->NormalsNameAllocSize); + this->CheckFor("tcoords", line, this->NumberOfTCoordsInFile, + this->TCoordsNameInFile, this->TCoordsNameAllocSize); + this->CheckFor("field", line, this->NumberOfFieldDataInFile, + this->FieldDataNameInFile, this->FieldDataNameAllocSize); + } + + this->CloseVTKFile (); + return 1; +} + +void vtkDataReader::CheckFor(const char* name, char *line, int &num, + char** &array, int &allocSize) +{ + if ( !strncmp(this->LowerCase(line, strlen(name)), name, strlen(name)) ) + { + int i; + int newAllocSize; + char **newArray; + + //update numbers + num++; + + if ( !array ) + { + allocSize = 25; + array = new char* [allocSize]; + for (i=0; i= allocSize ) + { + newAllocSize = 2*num; + newArray = new char* [newAllocSize]; + for (i=0; iCharacterizeFile(); + if ( !this->ScalarsNameInFile || + i < 0 || i >= this->NumberOfScalarsInFile ) + { + return NULL; + } + else + { + return this->ScalarsNameInFile[i]; + } +} + +const char *vtkDataReader::GetVectorsNameInFile(int i) +{ + this->CharacterizeFile(); + if ( !this->VectorsNameInFile || + i < 0 || i >= this->NumberOfVectorsInFile ) + { + return NULL; + } + else + { + return this->VectorsNameInFile[i]; + } +} +const char *vtkDataReader::GetTensorsNameInFile(int i) +{ + this->CharacterizeFile(); + if ( !this->TensorsNameInFile || + i < 0 || i >= this->NumberOfTensorsInFile ) + { + return NULL; + } + else + { + return this->TensorsNameInFile[i]; + } +} +const char *vtkDataReader::GetNormalsNameInFile(int i) +{ + this->CharacterizeFile(); + if ( !this->NormalsNameInFile || + i < 0 || i >= this->NumberOfNormalsInFile ) + { + return NULL; + } + else + { + return this->NormalsNameInFile[i]; + } +} +const char *vtkDataReader::GetTCoordsNameInFile(int i) +{ + this->CharacterizeFile(); + if ( !this->TCoordsNameInFile || + i < 0 || i >= this->NumberOfTCoordsInFile ) + { + return NULL; + } + else + { + return this->TCoordsNameInFile[i]; + } +} +const char *vtkDataReader::GetFieldDataNameInFile(int i) +{ + this->CharacterizeFile(); + if ( !this->FieldDataNameInFile || + i < 0 || i >= this->NumberOfFieldDataInFile ) + { + return NULL; + } + else + { + return this->FieldDataNameInFile[i]; + } +} + +int vtkDataReader::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +void vtkDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + + if ( this->FileType == VTK_BINARY ) + { + os << indent << "File Type: BINARY\n"; + } + else + { + os << indent << "File Type: ASCII\n"; + } + + if ( this->Header ) + { + os << indent << "Header: " << this->Header << "\n"; + } + else + { + os << indent << "Header: (None)\n"; + } + + os << indent << "ReadFromInputString: " << (this->ReadFromInputString ? "On\n" : "Off\n"); + if ( this->InputString ) + { + os << indent << "Input String: " << this->InputString << "\n"; + } + else + { + os << indent << "Input String: (None)\n"; + } + + if ( this->InputArray ) + { + os << indent << "Input Array: " << "\n"; + this->InputArray->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Input String: (None)\n"; + } + + os << indent << "Input String Length: " << this->InputStringLength << endl; + + if ( this->ScalarsName ) + { + os << indent << "Scalars Name: " << this->ScalarsName << "\n"; + } + else + { + os << indent << "Scalars Name: (None)\n"; + } + os << indent << "ReadAllScalars: " + << (this->ReadAllScalars ? "On" : "Off") << "\n"; + + if ( this->VectorsName ) + { + os << indent << "Vectors Name: " << this->VectorsName << "\n"; + } + else + { + os << indent << "Vectors Name: (None)\n"; + } + os << indent << "ReadAllVectors: " + << (this->ReadAllVectors ? "On" : "Off") << "\n"; + + if ( this->NormalsName ) + { + os << indent << "Normals Name: " << this->NormalsName << "\n"; + } + else + { + os << indent << "Normals Name: (None)\n"; + } + os << indent << "ReadAllNormals: " + << (this->ReadAllNormals ? "On" : "Off") << "\n"; + + if ( this->TensorsName ) + { + os << indent << "Tensors Name: " << this->TensorsName << "\n"; + } + else + { + os << indent << "Tensors Name: (None)\n"; + } + os << indent << "ReadAllTensors: " + << (this->ReadAllTensors ? "On" : "Off") << "\n"; + + if ( this->TCoordsName ) + { + os << indent << "Texture Coords Name: " << this->TCoordsName << "\n"; + } + else + { + os << indent << "Texture Coordinates Name: (None)\n"; + } + os << indent << "ReadAllTCoords: " + << (this->ReadAllTCoords ? "On" : "Off") << "\n"; + + if ( this->LookupTableName ) + { + os << indent << "Lookup Table Name: " << this->LookupTableName << "\n"; + } + else + { + os << indent << "Lookup Table Name: (None)\n"; + } + os << indent << "ReadAllColorScalars: " + << (this->ReadAllColorScalars ? "On" : "Off") << "\n"; + + if ( this->FieldDataName ) + { + os << indent << "Field Data Name: " << this->FieldDataName << "\n"; + } + else + { + os << indent << "Field Data Name: (None)\n"; + } + os << indent << "ReadAllFields: " + << (this->ReadAllFields ? "On" : "Off") << "\n"; + + os << indent << "InputStringLength: " << this->InputStringLength << endl; +} + +int vtkDataReader::ReadDataSetData(vtkDataSet *vtkNotUsed(ds)) +{ + return 0; +} + + +void vtkDataReader::DecodeArrayName(char *resname, const char* name) +{ + if ( !resname || !name ) + { + return; + } + //strcpy(resname, name); + ostrstream str; + int cc = 0; + unsigned int ch; + int len = static_cast(strlen(name)); + char buffer[10] = "0x"; + while(name[cc]) + { + if ( name[cc] == '%' ) + { + if ( cc < len - 3 ) + { + buffer[2] = name[cc+1]; + buffer[3] = name[cc+2]; + buffer[4] = 0; + sscanf(buffer, "%x", &ch); + str << static_cast(ch); + cc+=2; + } + } + else + { + str << name[cc]; + } + cc ++; + } + str << ends; + strcpy(resname, str.str()); + str.rdbuf()->freeze(0); +} diff --git a/IO/vtkDataReader.h b/IO/vtkDataReader.h new file mode 100644 index 0000000..4cdc0b5 --- /dev/null +++ b/IO/vtkDataReader.h @@ -0,0 +1,402 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataReader - helper superclass for objects that read vtk data files +// .SECTION Description +// vtkDataReader is a helper superclass that reads the vtk data file header, +// dataset type, and attribute data (point and cell attributes such as +// scalars, vectors, normals, etc.) from a vtk data file. See text for +// the format of the various vtk file types. +// +// .SECTION See Also +// vtkPolyDataReader vtkStructuredPointsReader vtkStructuredGridReader +// vtkUnstructuredGridReader vtkRectilinearGridReader + +#ifndef __vtkDataReader_h +#define __vtkDataReader_h + +#include "vtkAlgorithm.h" + +#define VTK_ASCII 1 +#define VTK_BINARY 2 + +class vtkCharArray; +class vtkDataArray; +class vtkDataSet; +class vtkDataSetAttributes; +class vtkFieldData; +class vtkPointSet; +class vtkRectilinearGrid; + +class VTK_IO_EXPORT vtkDataReader : public vtkAlgorithm +{ +public: + static vtkDataReader *New(); + vtkTypeRevisionMacro(vtkDataReader,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of vtk data file to read. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Is the file a valid vtk file of the passed dataset type ? + // The dataset type is passed as a lower case string. + int IsFileValid(const char *dstype); + int IsFileStructuredPoints() { + return this->IsFileValid("structured_points");}; + int IsFilePolyData() { + return this->IsFileValid("polydata");}; + int IsFileStructuredGrid() { + return this->IsFileValid("structured_grid");}; + int IsFileUnstructuredGrid() { + return this->IsFileValid("unstructured_grid");}; + int IsFileRectilinearGrid() { + return this->IsFileValid("rectilinear_grid");}; + + // Description: + // Specify the InputString for use when reading from a character array. + // Optionally include the length for binary strings. Note that a copy + // of the string is made and stored. If this causes exceedingly large + // memory consumption, consider using InputArray instead. + void SetInputString(const char *in); + vtkGetStringMacro(InputString); + void SetInputString(const char *in, int len); + vtkGetMacro(InputStringLength, int); + void SetBinaryInputString(const char *, int len); + + // Description: + // Specify the vtkCharArray to be used when reading from a string. + // If set, this array has precendence over InputString. + // Use this instead of InputString to avoid the extra memory copy. + // It should be noted that if the underlying char* is owned by the + // user ( vtkCharArray::SetArray(array, 1); ) and is deleted before + // the reader, bad things will happen during a pipeline update. + virtual void SetInputArray(vtkCharArray*); + vtkGetObjectMacro(InputArray, vtkCharArray); + + // Description: + // Get the header from the vtk data file. + vtkGetStringMacro(Header); + + // Description: + // Enable reading from an InputString or InputArray instead of the default, + // a file. + vtkSetMacro(ReadFromInputString,int); + vtkGetMacro(ReadFromInputString,int); + vtkBooleanMacro(ReadFromInputString,int); + + // Description: + // Get the type of file (ASCII or BINARY). Returned value only valid + // after file has been read. + vtkGetMacro(FileType,int); + + // Description: + // How many attributes of various types are in this file? This + // requires reading the file, so the filename must be set prior + // to invoking this operation. (Note: file characteristics are + // cached, so only a single read is necessary to return file + // characteristics.) + int GetNumberOfScalarsInFile() + {this->CharacterizeFile(); return this->NumberOfScalarsInFile;} + int GetNumberOfVectorsInFile() + {this->CharacterizeFile(); return this->NumberOfVectorsInFile;} + int GetNumberOfTensorsInFile() + {this->CharacterizeFile(); return this->NumberOfTensorsInFile;} + int GetNumberOfNormalsInFile() + {this->CharacterizeFile(); return this->NumberOfNormalsInFile;} + int GetNumberOfTCoordsInFile() + {this->CharacterizeFile(); return this->NumberOfTCoordsInFile;} + int GetNumberOfFieldDataInFile() + {this->CharacterizeFile(); return this->NumberOfFieldDataInFile;} + + // Description: + // What is the name of the ith attribute of a certain type + // in this file? This requires reading the file, so the filename + // must be set prior to invoking this operation. + const char *GetScalarsNameInFile(int i); + const char *GetVectorsNameInFile(int i); + const char *GetTensorsNameInFile(int i); + const char *GetNormalsNameInFile(int i); + const char *GetTCoordsNameInFile(int i); + const char *GetFieldDataNameInFile(int i); + + // Description: + // Set the name of the scalar data to extract. If not specified, first + // scalar data encountered is extracted. + vtkSetStringMacro(ScalarsName); + vtkGetStringMacro(ScalarsName); + + // Description: + // Set the name of the vector data to extract. If not specified, first + // vector data encountered is extracted. + vtkSetStringMacro(VectorsName); + vtkGetStringMacro(VectorsName); + + // Description: + // Set the name of the tensor data to extract. If not specified, first + // tensor data encountered is extracted. + vtkSetStringMacro(TensorsName); + vtkGetStringMacro(TensorsName); + + // Description: + // Set the name of the normal data to extract. If not specified, first + // normal data encountered is extracted. + vtkSetStringMacro(NormalsName); + vtkGetStringMacro(NormalsName); + + // Description: + // Set the name of the texture coordinate data to extract. If not specified, + // first texture coordinate data encountered is extracted. + vtkSetStringMacro(TCoordsName); + vtkGetStringMacro(TCoordsName); + + // Description: + // Set the name of the lookup table data to extract. If not specified, uses + // lookup table named by scalar. Otherwise, this specification supersedes. + vtkSetStringMacro(LookupTableName); + vtkGetStringMacro(LookupTableName); + + // Description: + // Set the name of the field data to extract. If not specified, uses + // first field data encountered in file. + vtkSetStringMacro(FieldDataName); + vtkGetStringMacro(FieldDataName); + + // Description: + // Enable reading all scalars. + vtkSetMacro(ReadAllScalars,int); + vtkGetMacro(ReadAllScalars,int); + vtkBooleanMacro(ReadAllScalars,int); + + // Description: + // Enable reading all vectors. + vtkSetMacro(ReadAllVectors,int); + vtkGetMacro(ReadAllVectors,int); + vtkBooleanMacro(ReadAllVectors,int); + + // Description: + // Enable reading all normals. + vtkSetMacro(ReadAllNormals,int); + vtkGetMacro(ReadAllNormals,int); + vtkBooleanMacro(ReadAllNormals,int); + + // Description: + // Enable reading all tensors. + vtkSetMacro(ReadAllTensors,int); + vtkGetMacro(ReadAllTensors,int); + vtkBooleanMacro(ReadAllTensors,int); + + // Description: + // Enable reading all color scalars. + vtkSetMacro(ReadAllColorScalars,int); + vtkGetMacro(ReadAllColorScalars,int); + vtkBooleanMacro(ReadAllColorScalars,int); + + // Description: + // Enable reading all tcoords. + vtkSetMacro(ReadAllTCoords,int); + vtkGetMacro(ReadAllTCoords,int); + vtkBooleanMacro(ReadAllTCoords,int); + + // Description: + // Enable reading all fields. + vtkSetMacro(ReadAllFields,int); + vtkGetMacro(ReadAllFields,int); + vtkBooleanMacro(ReadAllFields,int); + + // Description: + // Open a vtk data file. Returns zero if error. + int OpenVTKFile(); + + // Description: + // Read the header of a vtk data file. Returns 0 if error. + int ReadHeader(); + + // Description: + // Read the cell data of a vtk data file. The number of cells (from the + // dataset) must match the number of cells defined in cell attributes (unless + // no geometry was defined). + int ReadCellData(vtkDataSet *ds, int numCells); + + // Description: + // Read the point data of a vtk data file. The number of points (from the + // dataset) must match the number of points defined in point attributes + // (unless no geometry was defined). + int ReadPointData(vtkDataSet *ds, int numPts); + + // Description: + // Read point coordinates. Return 0 if error. + int ReadPoints(vtkPointSet *ps, int numPts); + + // Description: + // Read a bunch of "cells". Return 0 if error. + int ReadCells(int size, int *data); + + // Description: + // Read a piece of the cells (for streaming compliance) + int ReadCells(int size, int *data, int skip1, int read2, int skip3); + + // Description: + // Read the coordinates for a rectilinear grid. The axes parameter specifies + // which coordinate axes (0,1,2) is being read. + int ReadCoordinates(vtkRectilinearGrid *rg, int axes, int numCoords); + + // Description: + // Helper functions for reading data. + vtkDataArray *ReadArray(const char *dataType, int numTuples, int numComp); + vtkFieldData *ReadFieldData(); + + // Description: + // Internal function to read in a value. Returns zero if there was an + // error. + int Read(char *); + int Read(unsigned char *); + int Read(short *); + int Read(unsigned short *); + int Read(int *); + int Read(unsigned int *); + int Read(long *); + int Read(unsigned long *); + int Read(float *); + int Read(double *); + + // Description: + // Close the vtk file. + void CloseVTKFile(); + +//BTX + // Description: + // Internal function to read in a line up to 256 characters. + // Returns zero if there was an error. + int ReadLine(char result[256]); + + // Description: + // Internal function to read in a string up to 256 characters. + // Returns zero if there was an error. + int ReadString(char result[256]); + + // Description: + // Helper method for reading in data. + char *LowerCase(char *str, const size_t len=256); + + // Description: + // Return the istream being used to read in the data. + istream *GetIStream() {return this->IS;}; +//ETX + + // Description: + // Read the meta information from the file. This needs to be public to it + // can be accessed by vtkDataSetReader. + virtual int ReadMetaData(vtkInformation *) { return 1; } + +protected: + vtkDataReader(); + ~vtkDataReader(); + + char *FileName; + int FileType; + istream *IS; + + char *ScalarsName; + char *VectorsName; + char *TensorsName; + char *TCoordsName; + char *NormalsName; + char *LookupTableName; + char *FieldDataName; + char *ScalarLut; + + int ReadFromInputString; + char *InputString; + int InputStringLength; + int InputStringPos; + + vtkSetStringMacro(ScalarLut); + vtkGetStringMacro(ScalarLut); + + char *Header; + + int ReadScalarData(vtkDataSetAttributes *a, int num); + int ReadVectorData(vtkDataSetAttributes *a, int num); + int ReadNormalData(vtkDataSetAttributes *a, int num); + int ReadTensorData(vtkDataSetAttributes *a, int num); + int ReadCoScalarData(vtkDataSetAttributes *a, int num); + int ReadLutData(vtkDataSetAttributes *a); + int ReadTCoordsData(vtkDataSetAttributes *a, int num); + + int ReadDataSetData(vtkDataSet *ds); + + // This supports getting additional information from vtk files + int NumberOfScalarsInFile; + char **ScalarsNameInFile; + int ScalarsNameAllocSize; + int NumberOfVectorsInFile; + char **VectorsNameInFile; + int VectorsNameAllocSize; + int NumberOfTensorsInFile; + char **TensorsNameInFile; + int TensorsNameAllocSize; + int NumberOfTCoordsInFile; + char **TCoordsNameInFile; + int TCoordsNameAllocSize; + int NumberOfNormalsInFile; + char **NormalsNameInFile; + int NormalsNameAllocSize; + int NumberOfFieldDataInFile; + char **FieldDataNameInFile; + int FieldDataNameAllocSize; + vtkTimeStamp CharacteristicsTime; + + int ReadAllScalars; + int ReadAllVectors; + int ReadAllNormals; + int ReadAllTensors; + int ReadAllColorScalars; + int ReadAllTCoords; + int ReadAllFields; + + void InitializeCharacteristics(); + int CharacterizeFile(); //read entire file, storing important characteristics + void CheckFor(const char* name, char *line, int &num, char** &array, + int& allocSize); + + vtkCharArray* InputArray; + + // Description: + // Decode the name of array. This method is the inverse of + // vtkWriter::EncodeName. + void DecodeArrayName(char *resname, const char* name); + + virtual int ProcessRequest(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *) + { return 1; } + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, + vtkInformationVector *) + { return 1; } + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, + vtkInformationVector *) + { return 1; } + +private: + vtkDataReader(const vtkDataReader&); // Not implemented. + void operator=(const vtkDataReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkDataSetReader.cxx b/IO/vtkDataSetReader.cxx new file mode 100644 index 0000000..d6ae237 --- /dev/null +++ b/IO/vtkDataSetReader.cxx @@ -0,0 +1,485 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetReader.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataReader.h" +#include "vtkRectilinearGrid.h" +#include "vtkRectilinearGridReader.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridReader.h" +#include "vtkStructuredPoints.h" +#include "vtkStructuredPointsReader.h" +#include "vtkUnstructuredGrid.h" +#include "vtkUnstructuredGridReader.h" + +vtkCxxRevisionMacro(vtkDataSetReader, "$Revision: 1.70 $"); +vtkStandardNewMacro(vtkDataSetReader); + +vtkDataSetReader::vtkDataSetReader() +{ +} + +vtkDataSetReader::~vtkDataSetReader() +{ +} + +int vtkDataSetReader::RequestDataObject( + vtkInformation *, + vtkInformationVector** vtkNotUsed(inputVector) , + vtkInformationVector* outputVector) +{ + if (this->GetFileName() == NULL && + (this->GetReadFromInputString() == 0 || + (this->GetInputArray() == NULL && this->GetInputString() == NULL))) + { + vtkWarningMacro(<< "FileName must be set"); + return 0; + } + + int outputType = this->ReadOutputType(); + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + if (output && (output->GetDataObjectType() == outputType)) + { + return 1; + } + + if (!output || output->GetDataObjectType() != outputType) + { + switch (outputType) + { + case VTK_POLY_DATA: + output = vtkPolyData::New(); + break; + case VTK_STRUCTURED_POINTS: + output = vtkStructuredPoints::New(); + break; + case VTK_STRUCTURED_GRID: + output = vtkStructuredGrid::New(); + break; + case VTK_RECTILINEAR_GRID: + output = vtkRectilinearGrid::New(); + break; + case VTK_UNSTRUCTURED_GRID: + output = vtkUnstructuredGrid::New(); + break; + default: + return 0; + } + + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + this->GetOutputPortInformation(0)->Set( + vtkDataObject::DATA_EXTENT_TYPE(), output->GetExtentType()); + } + + return 1; +} + +int vtkDataSetReader::RequestInformation( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + if (this->GetFileName() == NULL && + (this->GetReadFromInputString() == 0 || + (this->GetInputArray() == NULL && this->GetInputString() == NULL))) + { + vtkWarningMacro(<< "FileName must be set"); + return 0; + } + + vtkDataReader *reader = 0; + int retVal; + switch (this->ReadOutputType()) + { + case VTK_POLY_DATA: + reader = vtkPolyDataReader::New(); + break; + case VTK_STRUCTURED_POINTS: + reader = vtkStructuredPointsReader::New(); + break; + case VTK_STRUCTURED_GRID: + reader = vtkStructuredGridReader::New(); + break; + case VTK_RECTILINEAR_GRID: + reader = vtkRectilinearGridReader::New(); + break; + case VTK_UNSTRUCTURED_GRID: + reader = vtkUnstructuredGridReader::New(); + break; + default: + reader = NULL; + } + + if (reader) + { + reader->SetFileName(this->GetFileName()); + reader->SetReadFromInputString(this->GetReadFromInputString()); + reader->SetInputArray(this->GetInputArray()); + reader->SetInputString(this->GetInputString()); + retVal = reader->ReadMetaData(outInfo); + reader->Delete(); + return retVal; + } + return 1; +} + +int vtkDataSetReader::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataObject *output = outInfo->Get(vtkDataObject::DATA_OBJECT()); + + vtkDebugMacro(<<"Reading vtk dataset..."); + + switch (this->ReadOutputType()) + { + case VTK_POLY_DATA: + { + vtkPolyDataReader *preader = vtkPolyDataReader::New(); + preader->SetFileName(this->GetFileName()); + preader->SetInputArray(this->GetInputArray()); + preader->SetInputString(this->GetInputString(), + this->GetInputStringLength()); + preader->SetReadFromInputString(this->GetReadFromInputString()); + preader->SetScalarsName(this->GetScalarsName()); + preader->SetVectorsName(this->GetVectorsName()); + preader->SetNormalsName(this->GetNormalsName()); + preader->SetTensorsName(this->GetTensorsName()); + preader->SetTCoordsName(this->GetTCoordsName()); + preader->SetLookupTableName(this->GetLookupTableName()); + preader->SetFieldDataName(this->GetFieldDataName()); + preader->SetReadAllScalars(this->GetReadAllScalars()); + preader->SetReadAllVectors(this->GetReadAllVectors()); + preader->SetReadAllNormals(this->GetReadAllNormals()); + preader->SetReadAllTensors(this->GetReadAllTensors()); + preader->SetReadAllColorScalars(this->GetReadAllColorScalars()); + preader->SetReadAllTCoords(this->GetReadAllTCoords()); + preader->SetReadAllFields(this->GetReadAllFields()); + preader->Update(); + // Can we use the old output? + if(!(output && strcmp(output->GetClassName(), "vtkPolyData") == 0)) + { + // Hack to make sure that the object is not modified + // with SetNthOutput. Otherwise, extra executions occur. + vtkTimeStamp ts = this->MTime; + output = vtkPolyData::New(); + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + this->MTime = ts; + } + output->ShallowCopy(preader->GetOutput()); + preader->Delete(); + return 1; + } + case VTK_STRUCTURED_POINTS: + { + vtkStructuredPointsReader *preader = vtkStructuredPointsReader::New(); + preader->SetFileName(this->GetFileName()); + preader->SetInputArray(this->GetInputArray()); + preader->SetInputString(this->GetInputString(), + this->GetInputStringLength()); + preader->SetReadFromInputString(this->GetReadFromInputString()); + preader->SetScalarsName(this->GetScalarsName()); + preader->SetVectorsName(this->GetVectorsName()); + preader->SetNormalsName(this->GetNormalsName()); + preader->SetTensorsName(this->GetTensorsName()); + preader->SetTCoordsName(this->GetTCoordsName()); + preader->SetLookupTableName(this->GetLookupTableName()); + preader->SetFieldDataName(this->GetFieldDataName()); + preader->SetReadAllScalars(this->GetReadAllScalars()); + preader->SetReadAllVectors(this->GetReadAllVectors()); + preader->SetReadAllNormals(this->GetReadAllNormals()); + preader->SetReadAllTensors(this->GetReadAllTensors()); + preader->SetReadAllColorScalars(this->GetReadAllColorScalars()); + preader->SetReadAllTCoords(this->GetReadAllTCoords()); + preader->SetReadAllFields(this->GetReadAllFields()); + preader->Update(); + // Can we use the old output? + if(!(output && strcmp(output->GetClassName(), "vtkStructuredPoints") == 0)) + { + // Hack to make sure that the object is not modified + // with SetNthOutput. Otherwise, extra executions occur. + vtkTimeStamp ts = this->MTime; + output = vtkStructuredPoints::New(); + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + this->MTime = ts; + } + output->ShallowCopy(preader->GetOutput()); + output->GetPipelineInformation()->CopyEntry( + preader->GetOutput()->GetPipelineInformation(), + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + preader->Delete(); + return 1; + } + case VTK_STRUCTURED_GRID: + { + vtkStructuredGridReader *preader = vtkStructuredGridReader::New(); + preader->SetFileName(this->GetFileName()); + preader->SetInputArray(this->GetInputArray()); + preader->SetInputString(this->GetInputString(), + this->GetInputStringLength()); + preader->SetReadFromInputString(this->GetReadFromInputString()); + preader->SetScalarsName(this->GetScalarsName()); + preader->SetVectorsName(this->GetVectorsName()); + preader->SetNormalsName(this->GetNormalsName()); + preader->SetTensorsName(this->GetTensorsName()); + preader->SetTCoordsName(this->GetTCoordsName()); + preader->SetLookupTableName(this->GetLookupTableName()); + preader->SetFieldDataName(this->GetFieldDataName()); + preader->SetReadAllScalars(this->GetReadAllScalars()); + preader->SetReadAllVectors(this->GetReadAllVectors()); + preader->SetReadAllNormals(this->GetReadAllNormals()); + preader->SetReadAllTensors(this->GetReadAllTensors()); + preader->SetReadAllColorScalars(this->GetReadAllColorScalars()); + preader->SetReadAllTCoords(this->GetReadAllTCoords()); + preader->SetReadAllFields(this->GetReadAllFields()); + preader->Update(); + // Can we use the old output? + if(!(output && strcmp(output->GetClassName(), "vtkStructuredGrid") == 0)) + { + // Hack to make sure that the object is not modified + // with SetNthOutput. Otherwise, extra executions occur. + vtkTimeStamp ts = this->MTime; + output = vtkStructuredGrid::New(); + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + this->MTime = ts; + } + output->ShallowCopy(preader->GetOutput()); + preader->Delete(); + return 1; + } + case VTK_RECTILINEAR_GRID: + { + vtkRectilinearGridReader *preader = vtkRectilinearGridReader::New(); + preader->SetFileName(this->GetFileName()); + preader->SetInputArray(this->GetInputArray()); + preader->SetInputString(this->GetInputString(), + this->GetInputStringLength()); + preader->SetReadFromInputString(this->GetReadFromInputString()); + preader->SetScalarsName(this->GetScalarsName()); + preader->SetVectorsName(this->GetVectorsName()); + preader->SetNormalsName(this->GetNormalsName()); + preader->SetTensorsName(this->GetTensorsName()); + preader->SetTCoordsName(this->GetTCoordsName()); + preader->SetLookupTableName(this->GetLookupTableName()); + preader->SetFieldDataName(this->GetFieldDataName()); + preader->SetReadAllScalars(this->GetReadAllScalars()); + preader->SetReadAllVectors(this->GetReadAllVectors()); + preader->SetReadAllNormals(this->GetReadAllNormals()); + preader->SetReadAllTensors(this->GetReadAllTensors()); + preader->SetReadAllColorScalars(this->GetReadAllColorScalars()); + preader->SetReadAllTCoords(this->GetReadAllTCoords()); + preader->SetReadAllFields(this->GetReadAllFields()); + preader->Update(); + // Can we use the old output? + if(!(output && strcmp(output->GetClassName(), "vtkRectilinearGrid") == 0)) + { + // Hack to make sure that the object is not modified + // with SetNthOutput. Otherwise, extra executions occur. + vtkTimeStamp ts = this->MTime; + output = vtkRectilinearGrid::New(); + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + this->MTime = ts; + } + output->ShallowCopy(preader->GetOutput()); + preader->Delete(); + return 1; + } + case VTK_UNSTRUCTURED_GRID: + { + vtkUnstructuredGridReader *preader = vtkUnstructuredGridReader::New(); + preader->SetFileName(this->GetFileName()); + preader->SetInputArray(this->GetInputArray()); + preader->SetInputString(this->GetInputString(), + this->GetInputStringLength()); + preader->SetReadFromInputString(this->GetReadFromInputString()); + preader->SetScalarsName(this->GetScalarsName()); + preader->SetVectorsName(this->GetVectorsName()); + preader->SetNormalsName(this->GetNormalsName()); + preader->SetTensorsName(this->GetTensorsName()); + preader->SetTCoordsName(this->GetTCoordsName()); + preader->SetLookupTableName(this->GetLookupTableName()); + preader->SetFieldDataName(this->GetFieldDataName()); + preader->SetReadAllScalars(this->GetReadAllScalars()); + preader->SetReadAllVectors(this->GetReadAllVectors()); + preader->SetReadAllNormals(this->GetReadAllNormals()); + preader->SetReadAllTensors(this->GetReadAllTensors()); + preader->SetReadAllColorScalars(this->GetReadAllColorScalars()); + preader->SetReadAllTCoords(this->GetReadAllTCoords()); + preader->SetReadAllFields(this->GetReadAllFields()); + preader->Update(); + // Can we use the old output? + if(!(output && strcmp(output->GetClassName(), "vtkUnstructuredGrid") == 0)) + { + // Hack to make sure that the object is not modified + // with SetNthOutput. Otherwise, extra executions occur. + vtkTimeStamp ts = this->MTime; + output = vtkUnstructuredGrid::New(); + this->GetExecutive()->SetOutputData(0, output); + output->Delete(); + this->MTime = ts; + } + output->ShallowCopy(preader->GetOutput()); + preader->Delete(); + return 1; + } + default: + vtkErrorMacro("Could not read file " << this->FileName); + } + return 0; +} + +int vtkDataSetReader::ReadOutputType() +{ + char line[256]; + + vtkDebugMacro(<<"Reading vtk dataset..."); + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return -1; + } + + // Determine dataset type + // + if (!this->ReadString(line)) + { + vtkDebugMacro(<< "Premature EOF reading dataset keyword"); + return -1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // See if type is recognized. + // + if (!this->ReadString(line)) + { + vtkDebugMacro(<< "Premature EOF reading type"); + this->CloseVTKFile (); + return -1; + } + + this->CloseVTKFile(); + if ( ! strncmp(this->LowerCase(line),"polydata",8) ) + { + return VTK_POLY_DATA; + } + else if ( ! strncmp(line,"structured_points",17) ) + { + return VTK_STRUCTURED_POINTS; + } + else if ( ! strncmp(line,"structured_grid",15) ) + { + return VTK_STRUCTURED_GRID; + } + else if ( ! strncmp(line,"rectilinear_grid",16) ) + { + return VTK_RECTILINEAR_GRID; + } + else if ( ! strncmp(line,"unstructured_grid",17) ) + { + return VTK_UNSTRUCTURED_GRID; + } + else + { + vtkDebugMacro(<< "Cannot read dataset type: " << line); + return -1; + } + } + else if ( !strncmp(this->LowerCase(line),"field",(unsigned long)5) ) + { + vtkDebugMacro(<<"This object can only read datasets, not fields"); + } + else + { + vtkDebugMacro(<<"Expecting DATASET keyword, got " << line << " instead"); + } + + return -1; +} + +vtkPolyData *vtkDataSetReader::GetPolyDataOutput() +{ + return vtkPolyData::SafeDownCast(this->GetOutput()); +} + +vtkStructuredPoints *vtkDataSetReader::GetStructuredPointsOutput() +{ + return vtkStructuredPoints::SafeDownCast(this->GetOutput()); +} + +vtkStructuredGrid *vtkDataSetReader::GetStructuredGridOutput() +{ + return vtkStructuredGrid::SafeDownCast(this->GetOutput()); +} + +vtkUnstructuredGrid *vtkDataSetReader::GetUnstructuredGridOutput() +{ + return vtkUnstructuredGrid::SafeDownCast(this->GetOutput()); +} + +vtkRectilinearGrid *vtkDataSetReader::GetRectilinearGridOutput() +{ + return vtkRectilinearGrid::SafeDownCast(this->GetOutput()); +} + +void vtkDataSetReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +vtkDataSet *vtkDataSetReader::GetOutput(int idx) +{ + return vtkDataSet::SafeDownCast(this->GetOutputDataObject(idx)); +} + +vtkDataSet *vtkDataSetReader::GetOutput() +{ + return vtkDataSet::SafeDownCast(this->GetOutputDataObject(0)); +} + +int vtkDataSetReader::FillOutputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataSet"); + return 1; +} + +int vtkDataSetReader::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + return this->RequestDataObject(request, inputVector, outputVector); + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} diff --git a/IO/vtkDataSetReader.h b/IO/vtkDataSetReader.h new file mode 100644 index 0000000..3d12337 --- /dev/null +++ b/IO/vtkDataSetReader.h @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetReader - class to read any type of vtk dataset +// .SECTION Description +// vtkDataSetReader is a class that provides instance variables and methods +// to read any type of dataset in Visualization Toolkit (vtk) format. The +// output type of this class will vary depending upon the type of data +// file. Convenience methods are provided to keep the data as a particular +// type. (See text for format description details). +// The superclass of this class, vtkDataReader, provides many methods for +// controlling the reading of the data file, see vtkDataReader for more +// information. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// .SECTION See Also +// vtkDataReader vtkPolyDataReader vtkRectilinearGridReader +// vtkStructuredPointsReader vtkStructuredGridReader vtkUnstructuredGridReader + +#ifndef __vtkDataSetReader_h +#define __vtkDataSetReader_h + +#include "vtkDataReader.h" + +class vtkDataSet; +class vtkPolyData; +class vtkRectilinearGrid; +class vtkStructuredGrid; +class vtkStructuredPoints; +class vtkUnstructuredGrid; + +class VTK_IO_EXPORT vtkDataSetReader : public vtkDataReader +{ +public: + static vtkDataSetReader *New(); + vtkTypeRevisionMacro(vtkDataSetReader,vtkDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this filter + vtkDataSet *GetOutput(); + vtkDataSet *GetOutput(int idx); + + // Description: + // Get the output as various concrete types. This method is typically used + // when you know exactly what type of data is being read. Otherwise, use + // the general GetOutput() method. If the wrong type is used NULL is + // returned. (You must also set the filename of the object prior to + // getting the output.) + vtkPolyData *GetPolyDataOutput(); + vtkStructuredPoints *GetStructuredPointsOutput(); + vtkStructuredGrid *GetStructuredGridOutput(); + vtkUnstructuredGrid *GetUnstructuredGridOutput(); + vtkRectilinearGrid *GetRectilinearGridOutput(); + + // Description: + // This method can be used to find out the type of output expected without + // needing to read the whole file. + virtual int ReadOutputType(); + +protected: + vtkDataSetReader(); + ~vtkDataSetReader(); + + virtual int ProcessRequest(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int RequestDataObject(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int FillOutputPortInformation(int, vtkInformation *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + +private: + vtkDataSetReader(const vtkDataSetReader&); // Not implemented. + void operator=(const vtkDataSetReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkDataSetWriter.cxx b/IO/vtkDataSetWriter.cxx new file mode 100644 index 0000000..20d845f --- /dev/null +++ b/IO/vtkDataSetWriter.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetWriter.h" + +#include "vtkDataSet.h" +#include "vtkErrorCode.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataWriter.h" +#include "vtkRectilinearGrid.h" +#include "vtkRectilinearGridWriter.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridWriter.h" +#include "vtkStructuredPointsWriter.h" +#include "vtkUnstructuredGrid.h" +#include "vtkUnstructuredGridWriter.h" + +vtkCxxRevisionMacro(vtkDataSetWriter, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkDataSetWriter); + +void vtkDataSetWriter::WriteData() +{ + int type; + vtkDataWriter *writer; + vtkDataSet *input = vtkDataSet::SafeDownCast(this->GetInput()); + + vtkDebugMacro(<<"Writing vtk dataset..."); + + type = input->GetDataObjectType(); + if ( type == VTK_POLY_DATA ) + { + vtkPolyDataWriter *pwriter = vtkPolyDataWriter::New(); + pwriter->SetInput(static_cast(input)); + writer = pwriter; + } + + else if ( type == VTK_STRUCTURED_POINTS || type == VTK_IMAGE_DATA) + { + vtkStructuredPointsWriter *spwriter = vtkStructuredPointsWriter::New(); + spwriter->SetInput(static_cast(input)); + writer = spwriter; + } + + else if ( type == VTK_STRUCTURED_GRID ) + { + vtkStructuredGridWriter *sgwriter = vtkStructuredGridWriter::New(); + sgwriter->SetInput(static_cast(input)); + writer = sgwriter; + } + + else if ( type == VTK_UNSTRUCTURED_GRID ) + { + vtkUnstructuredGridWriter *ugwriter = vtkUnstructuredGridWriter::New(); + ugwriter->SetInput(static_cast(input)); + writer = ugwriter; + } + + else if ( type == VTK_RECTILINEAR_GRID ) + { + vtkRectilinearGridWriter *rgwriter = vtkRectilinearGridWriter::New(); + rgwriter->SetInput(static_cast(input)); + writer = rgwriter; + } + + else + { + vtkErrorMacro(<< "Cannot write dataset type: " << type); + return; + } + + writer->SetFileName(this->FileName); + writer->SetScalarsName(this->ScalarsName); + writer->SetVectorsName(this->VectorsName); + writer->SetNormalsName(this->NormalsName); + writer->SetTensorsName(this->TensorsName); + writer->SetTCoordsName(this->TCoordsName); + writer->SetHeader(this->Header); + writer->SetLookupTableName(this->LookupTableName); + writer->SetFieldDataName(this->FieldDataName); + writer->SetFileType(this->FileType); + writer->SetDebug(this->Debug); + writer->SetWriteToOutputString(this->WriteToOutputString); + writer->Write(); + if (writer->GetErrorCode() == vtkErrorCode::OutOfDiskSpaceError) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } + if (this->WriteToOutputString) + { + if (this->OutputString) + { + delete [] this->OutputString; + } + this->OutputStringLength = writer->GetOutputStringLength(); + // should fill something here. + this->OutputStringAllocatedLength = this->OutputStringLength; + this->OutputString = writer->RegisterAndGetOutputString(); + } + writer->Delete(); +} + +int vtkDataSetWriter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +vtkDataSet* vtkDataSetWriter::GetInput() +{ + return vtkDataSet::SafeDownCast(this->Superclass::GetInput()); +} + +vtkDataSet* vtkDataSetWriter::GetInput(int port) +{ + return vtkDataSet::SafeDownCast(this->Superclass::GetInput(port)); +} + +void vtkDataSetWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkDataSetWriter.h b/IO/vtkDataSetWriter.h new file mode 100644 index 0000000..d528922 --- /dev/null +++ b/IO/vtkDataSetWriter.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetWriter - write any type of vtk dataset to file +// .SECTION Description +// vtkDataSetWriter is an abstract class for mapper objects that write their +// data to disk (or into a communications port). The input to this object is +// a dataset of any type. + +#ifndef __vtkDataSetWriter_h +#define __vtkDataSetWriter_h + +#include "vtkDataWriter.h" + +class VTK_IO_EXPORT vtkDataSetWriter : public vtkDataWriter +{ +public: + static vtkDataSetWriter *New(); + vtkTypeRevisionMacro(vtkDataSetWriter,vtkDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the input to this writer. + vtkDataSet* GetInput(); + vtkDataSet* GetInput(int port); + +protected: + vtkDataSetWriter() {}; + ~vtkDataSetWriter() {}; + + void WriteData(); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkDataSetWriter(const vtkDataSetWriter&); // Not implemented. + void operator=(const vtkDataSetWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkDataWriter.cxx b/IO/vtkDataWriter.cxx new file mode 100644 index 0000000..5836d90 --- /dev/null +++ b/IO/vtkDataWriter.cxx @@ -0,0 +1,1228 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataWriter.h" + +#include "vtkBitArray.h" +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkShortArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +vtkCxxRevisionMacro(vtkDataWriter, "$Revision: 1.109 $"); +vtkStandardNewMacro(vtkDataWriter); + +// this undef is required on the hp. vtkMutexLock ends up including +// /usr/inclue/dce/cma_ux.h which has the gall to #define write as cma_write + +#ifdef write +#undef write +#endif + +// Created object with default header, ASCII format, and default names for +// scalars, vectors, tensors, normals, and texture coordinates. +vtkDataWriter::vtkDataWriter() +{ + this->FileName = NULL; + + this->Header = new char[257]; + strcpy(this->Header,"vtk output"); + this->FileType = VTK_ASCII; + + this->ScalarsName = 0; + this->VectorsName = 0; + this->TensorsName = 0; + this->NormalsName = 0; + this->TCoordsName = 0; + + this->LookupTableName = new char[13]; + strcpy(this->LookupTableName,"lookup_table"); + + this->FieldDataName = new char[10]; + strcpy(this->FieldDataName,"FieldData"); + + this->WriteToOutputString = 0; + this->OutputString = NULL; + this->OutputStringAllocatedLength = 0; + this->OutputStringLength = 0; +} + +vtkDataWriter::~vtkDataWriter() +{ + if ( this->FileName ) + { + delete [] this->FileName; + } + if ( this->Header ) + { + delete [] this->Header; + } + if ( this->ScalarsName ) + { + delete [] this->ScalarsName; + } + if ( this->VectorsName ) + { + delete [] this->VectorsName; + } + if ( this->TensorsName ) + { + delete [] this->TensorsName; + } + if ( this->NormalsName ) + { + delete [] this->NormalsName; + } + if ( this->TCoordsName ) + { + delete [] this->TCoordsName; + } + if ( this->LookupTableName ) + { + delete [] this->LookupTableName; + } + if ( this->FieldDataName ) + { + delete [] this->FieldDataName; + } + + if (this->OutputString) + { + delete [] this->OutputString; + this->OutputString = NULL; + this->OutputStringLength = 0; + this->OutputStringAllocatedLength = 0; + } +} + + +// Open a vtk data file. Returns NULL if error. +ostream *vtkDataWriter::OpenVTKFile() +{ + ostream *fptr; + vtkDataObject *input = this->GetInput(); + + if ((!this->WriteToOutputString) && ( !this->FileName )) + { + vtkErrorMacro(<< "No FileName specified! Can't write!"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return NULL; + } + + vtkDebugMacro(<<"Opening vtk file for writing..."); + + if (this->WriteToOutputString) + { + // Get rid of any old output string. + if (this->OutputString) + { + delete [] this->OutputString; + this->OutputString = NULL; + this->OutputStringLength = 0; + this->OutputStringAllocatedLength = 0; + } + // Allocate the new output string. (Note: this will only work with binary). + if (input == NULL) + { + vtkErrorMacro(<< "No input! Can't write!"); + return NULL; + } + input->Update(); + this->OutputStringAllocatedLength = (int) (500 + + 1000 * input->GetActualMemorySize()); + this->OutputString = new char[this->OutputStringAllocatedLength]; + + fptr = new ostrstream(this->OutputString, + this->OutputStringAllocatedLength); + } + else + { + if ( this->FileType == VTK_ASCII ) + { + fptr = new ofstream(this->FileName, ios::out); + } + else + { +#ifdef _WIN32 + fptr = new ofstream(this->FileName, ios::out | ios::binary); +#else + fptr = new ofstream(this->FileName, ios::out); +#endif + } + } + + if (fptr->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + delete fptr; + return NULL; + } + + return fptr; +} + +// Write the header of a vtk data file. Returns 0 if error. +int vtkDataWriter::WriteHeader(ostream *fp) +{ + vtkDebugMacro(<<"Writing header..."); + + *fp << "# vtk DataFile Version 3.0\n"; + *fp << this->Header << "\n"; + + if ( this->FileType == VTK_ASCII ) + { + *fp << "ASCII\n"; + } + else + { + *fp << "BINARY\n"; + } + + fp->flush(); + if (fp->fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + + return 1; +} + +// Write the cell data (e.g., scalars, vectors, ...) of a vtk dataset. +// Returns 0 if error. +int vtkDataWriter::WriteCellData(ostream *fp, vtkDataSet *ds) +{ + int numCells; + vtkDataArray *scalars; + vtkDataArray *vectors; + vtkDataArray *normals; + vtkDataArray *tcoords; + vtkDataArray *tensors; + vtkFieldData *field; + vtkCellData *cd=ds->GetCellData(); + + vtkDebugMacro(<<"Writing cell data..."); + + numCells = ds->GetNumberOfCells(); + scalars = cd->GetScalars(); + vectors = cd->GetVectors(); + normals = cd->GetNormals(); + tcoords = cd->GetTCoords(); + tensors = cd->GetTensors(); + field = cd; + + if ( numCells <= 0 || !(scalars || vectors || normals || tcoords || + tensors || field)) + { + vtkDebugMacro(<<"No cell data to write!"); + return 1; + } + + *fp << "CELL_DATA " << numCells << "\n"; + // + // Write scalar data + // + if ( scalars && scalars->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteScalarData(fp, scalars, numCells) ) + { + return 0; + } + } + // + // Write vector data + // + if ( vectors && vectors->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteVectorData(fp, vectors, numCells) ) + { + return 0; + } + } + // + // Write normals + // + if ( normals && normals->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteNormalData(fp, normals, numCells) ) + { + return 0; + } + } + // + // Write texture coords + // + if ( tcoords && tcoords->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteTCoordData(fp, tcoords, numCells) ) + { + return 0; + } + } + // + // Write tensors + // + if ( tensors && tensors->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteTensorData(fp, tensors, numCells) ) + { + return 0; + } + } + // + // Write field + // + if ( field && field->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteFieldData(fp, field) ) + { + return 0; + } + } + + return 1; +} + +// Write the point data (e.g., scalars, vectors, ...) of a vtk dataset. +// Returns 0 if error. +int vtkDataWriter::WritePointData(ostream *fp, vtkDataSet *ds) +{ + int numPts; + vtkDataArray *scalars; + vtkDataArray *vectors; + vtkDataArray *normals; + vtkDataArray *tcoords; + vtkDataArray *tensors; + vtkFieldData *field; + vtkPointData *pd=ds->GetPointData(); + + vtkDebugMacro(<<"Writing point data..."); + + numPts = ds->GetNumberOfPoints(); + scalars = pd->GetScalars(); + vectors = pd->GetVectors(); + normals = pd->GetNormals(); + tcoords = pd->GetTCoords(); + tensors = pd->GetTensors(); + field = pd; + + if ( numPts <= 0 || !(scalars || vectors || normals || tcoords || + tensors || field)) + { + vtkDebugMacro(<<"No point data to write!"); + return 1; + } + + *fp << "POINT_DATA " << numPts << "\n"; + // + // Write scalar data + // + if ( scalars && scalars->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteScalarData(fp, scalars, numPts) ) + { + return 0; + } + } + // + // Write vector data + // + if ( vectors && vectors->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteVectorData(fp, vectors, numPts) ) + { + return 0; + } + } + // + // Write normals + // + if ( normals && normals->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteNormalData(fp, normals, numPts) ) + { + return 0; + } + } + // + // Write texture coords + // + if ( tcoords && tcoords->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteTCoordData(fp, tcoords, numPts) ) + { + return 0; + } + } + // + // Write tensors + // + if ( tensors && tensors->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteTensorData(fp, tensors, numPts) ) + { + return 0; + } + } + // + // Write field + // + if ( field && field->GetNumberOfTuples() > 0 ) + { + if ( ! this->WriteFieldData(fp, field) ) + { + return 0; + } + } + + return 1; +} + +// Template to handle writing data in ascii or binary +// We could change the format into C++ io standard ... +template +void vtkWriteDataArray(ostream *fp, T *data, int fileType, + const char *format, int num, int numComp) +{ + int i, j, idx, sizeT; + char str[1024]; + + sizeT = sizeof(T); + + if ( fileType == VTK_ASCII ) + { + for (j=0; j 0) + { + // need to byteswap ?? + switch (sizeT) + { + case 2: + // typecast doesn't have to be valid here + vtkByteSwap::SwapWrite2BERange((short *)data,num*numComp, fp); + break; + case 4: + // typecast doesn't have to be valid here + vtkByteSwap::SwapWrite4BERange((float *)data,num*numComp, fp); + break; + case 8: + // typecast doesn't have to be valid here + vtkByteSwap::SwapWrite8BERange((double *)data,num*numComp, fp); + break; + default: + fp->write((char *)data, ( sizeof(T))*( num*numComp)); + + } + } + } + *fp << "\n"; +} + +// Write out data to file specified. +int vtkDataWriter::WriteArray(ostream *fp, int dataType, vtkDataArray *data, + const char *format, int num, int numComp) +{ + int i, j, idx; + char str[1024]; + + switch (dataType) + { + case VTK_BIT: + { + sprintf (str, format, "bit"); *fp << str; + if ( this->FileType == VTK_ASCII ) + { + int s; + for (j=0; jGetValue(idx); + *fp << (s!=0.0?1:0); + if ( !((idx+1)%8) ) + { + *fp << "\n"; + } + else + { + *fp << " "; + } + } + } + } + else + { + unsigned char *cptr=((vtkUnsignedCharArray *)data)->GetPointer(0); + fp->write((char *)cptr, (sizeof(unsigned char))*((num-1)/8+1)); + + } + *fp << "\n"; + } + break; + + case VTK_CHAR: + { + sprintf (str, format, "char"); *fp << str; + char *s=((vtkCharArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%hhd ", num, numComp); + } + break; + + case VTK_UNSIGNED_CHAR: + { + sprintf (str, format, "unsigned_char"); *fp << str; + unsigned char *s=((vtkUnsignedCharArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%hhu ", num, numComp); + } + break; + + case VTK_SHORT: + { + sprintf (str, format, "short"); *fp << str; + short *s=((vtkShortArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%hd ", num, numComp); + } + break; + + case VTK_UNSIGNED_SHORT: + { + sprintf (str, format, "unsigned_short"); *fp << str; + unsigned short *s=((vtkUnsignedShortArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%hu ", num, numComp); + } + break; + + case VTK_INT: + { + sprintf (str, format, "int"); *fp << str; + int *s=((vtkIntArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%d ", num, numComp); + } + break; + + case VTK_UNSIGNED_INT: + { + sprintf (str, format, "unsigned_int"); *fp << str; + unsigned int *s=((vtkUnsignedIntArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%u ", num, numComp); + } + break; + + case VTK_LONG: + { + sprintf (str, format, "long"); *fp << str; + long *s=((vtkLongArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%ld ", num, numComp); + } + break; + + case VTK_UNSIGNED_LONG: + { + sprintf (str, format, "unsigned_long"); *fp << str; + unsigned long *s=((vtkUnsignedLongArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%lu ", num, numComp); + } + break; + + case VTK_FLOAT: + { + sprintf (str, format, "float"); *fp << str; + float *s=((vtkFloatArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%g ", num, numComp); + } + break; + + case VTK_DOUBLE: + { + sprintf (str, format, "double"); *fp << str; + double *s=((vtkDoubleArray *)data)->GetPointer(0); + vtkWriteDataArray(fp, s, this->FileType, "%lg ", num, numComp); + } + break; + + case VTK_ID_TYPE: + { + // currently writing vtkIdType as int. + int size = data->GetNumberOfTuples(); + int *intArray = new int[size*numComp]; + sprintf (str, format, "int"); *fp << str; + vtkIdType *s=((vtkIdTypeArray *)data)->GetPointer(0); + for (i = 0; i < size*numComp; i++) + { + intArray[i] = s[i]; + } + vtkWriteDataArray(fp, intArray, this->FileType, "%d ", num, numComp); + delete [] intArray; + } + break; + + default: + { + vtkErrorMacro(<<"Type currently not supported"); + return 0; + } + } + + fp->flush(); + if (fp->fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + return 1; +} + +int vtkDataWriter::WritePoints(ostream *fp, vtkPoints *points) +{ + int numPts; + + if (points == NULL) + { + *fp << "POINTS 0 float\n"; + return 1; + } + + numPts=points->GetNumberOfPoints(); + *fp << "POINTS " << numPts << " "; + return this->WriteArray(fp, points->GetDataType(), points->GetData(), "%s\n", numPts, 3); +} + +// Write out coordinates for rectilinear grids. +int vtkDataWriter::WriteCoordinates(ostream *fp, vtkDataArray *coords, + int axes) +{ + int ncoords=coords->GetNumberOfTuples(); + + if ( axes == 0 ) + { + *fp << "X_COORDINATES " << ncoords << " "; + } + else if ( axes == 1) + { + *fp << "Y_COORDINATES " << ncoords << " "; + } + else + { + *fp << "Z_COORDINATES " << ncoords << " "; + } + + return this->WriteArray(fp, coords->GetDataType(), coords, "%s\n", ncoords, 1); +} + +// Write out scalar data. +int vtkDataWriter::WriteScalarData(ostream *fp, vtkDataArray *scalars, int num) +{ + int i, j, size=0; + char *name; + vtkLookupTable *lut; + int dataType = scalars->GetDataType(); + int numComp = scalars->GetNumberOfComponents(); + + if ( (lut=scalars->GetLookupTable()) == NULL || + (size = lut->GetNumberOfColors()) <= 0 ) + { + name = (char *) "default"; + } + else + { + name = this->LookupTableName; + } + + char* scalarsName; + // Buffer size is size of array name times four because + // in theory there could be array name consisting of only + // weird symbols. + if (!this->ScalarsName) + { + if (scalars->GetName() && strlen(scalars->GetName())) + { + scalarsName = new char[ strlen(scalars->GetName()) * 4 + 1]; + this->EncodeArrayName(scalarsName, scalars->GetName()); + } + else + { + scalarsName = new char[ strlen("scalars") + 1]; + strcpy(scalarsName, "scalars"); + } + } + else + { + scalarsName = new char[ strlen(this->ScalarsName) * 4 + 1]; + this->EncodeArrayName(scalarsName, this->ScalarsName); + } + + if ( dataType != VTK_UNSIGNED_CHAR ) + { + char format[1024]; + *fp << "SCALARS "; + + + if (numComp == 1) + { + sprintf(format,"%s %%s\nLOOKUP_TABLE %s\n", scalarsName, name); + } + else + { + sprintf(format,"%s %%s %d\nLOOKUP_TABLE %s\n", + scalarsName, numComp, name); + } + delete[] scalarsName; + if (this->WriteArray(fp, scalars->GetDataType(), scalars, format, + num, numComp) == 0) + { + return 0; + } + } + + else //color scalars + { + int nvs = scalars->GetNumberOfComponents(); + unsigned char *data=((vtkUnsignedCharArray *)scalars)->GetPointer(0); + *fp << "COLOR_SCALARS " << scalarsName << " " << nvs << "\n"; + + if ( this->FileType == VTK_ASCII ) + { + for (i=0; iwrite((char *)data, (sizeof(unsigned char))*(nvs*num)); + + } + + *fp << "\n"; + delete[] scalarsName; + + } + + //if lookup table, write it out + if ( lut && size > 0 ) + { + *fp << "LOOKUP_TABLE " << this->LookupTableName << " " << size << "\n"; + if ( this->FileType == VTK_ASCII ) + { + double *c; + for (i=0; iGetTableValue(i); + *fp << c[0] << " " << c[1] << " " << c[2] << " " << c[3] << "\n"; + } + } + else + { + unsigned char *colors=lut->GetPointer(0); + fp->write((char *)colors, (sizeof(unsigned char)*4*size)); + } + *fp << "\n"; + } + + fp->flush(); + if (fp->fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + + return 1; +} + +int vtkDataWriter::WriteVectorData(ostream *fp, vtkDataArray *vectors, int num) +{ + char format[1024]; + + *fp << "VECTORS "; + + char* vectorsName; + // Buffer size is size of array name times four because + // in theory there could be array name consisting of only + // weird symbols. + if (!this->VectorsName) + { + if (vectors->GetName() && strlen(vectors->GetName())) + { + vectorsName = new char[ strlen(vectors->GetName()) * 4 + 1]; + this->EncodeArrayName(vectorsName, vectors->GetName()); + } + else + { + vectorsName = new char[ strlen("vectors") + 1]; + strcpy(vectorsName, "vectors"); + } + } + else + { + vectorsName = new char[ strlen(this->VectorsName) * 4 + 1]; + this->EncodeArrayName(vectorsName, this->VectorsName); + } + + sprintf(format, "%s %s\n", vectorsName, "%s"); + delete[] vectorsName; + + return this->WriteArray(fp, vectors->GetDataType(), vectors, format, num, 3); +} + +int vtkDataWriter::WriteNormalData(ostream *fp, vtkDataArray *normals, int num) +{ + char format[1024]; + + char* normalsName; + // Buffer size is size of array name times four because + // in theory there could be array name consisting of only + // weird symbols. + if (!this->NormalsName) + { + if (normals->GetName() && strlen(normals->GetName()) ) + { + normalsName = new char[ strlen(normals->GetName()) * 4 + 1]; + this->EncodeArrayName(normalsName, normals->GetName()); + } + else + { + normalsName = new char[ strlen("normals") + 1]; + strcpy(normalsName, "normals"); + } + } + else + { + normalsName = new char[ strlen(this->NormalsName) * 4 + 1]; + this->EncodeArrayName(normalsName, this->NormalsName); + } + + *fp << "NORMALS "; + sprintf(format, "%s %s\n", normalsName, "%s"); + delete[] normalsName; + + return this->WriteArray(fp, normals->GetDataType(), normals, format, num, 3); +} + +int vtkDataWriter::WriteTCoordData(ostream *fp, vtkDataArray *tcoords, int num) +{ + int dim=tcoords->GetNumberOfComponents(); + char format[1024]; + + char* tcoordsName; + // Buffer size is size of array name times four because + // in theory there could be array name consisting of only + // weird symbols. + if (!this->TCoordsName) + { + if (tcoords->GetName() && strlen(tcoords->GetName())) + { + tcoordsName = new char[ strlen(tcoords->GetName()) * 4 + 1]; + this->EncodeArrayName(tcoordsName, tcoords->GetName()); + } + else + { + tcoordsName = new char[ strlen("tcoords") + 1]; + strcpy(tcoordsName, "tcoords"); + } + } + else + { + tcoordsName = new char[ strlen(this->TCoordsName) * 4 + 1]; + this->EncodeArrayName(tcoordsName, this->TCoordsName); + } + + + *fp << "TEXTURE_COORDINATES "; + sprintf(format, "%s %d %s\n", tcoordsName, dim, "%s"); + delete[] tcoordsName; + + return this->WriteArray(fp, tcoords->GetDataType(), tcoords, format, num, + dim); +} + +int vtkDataWriter::WriteTensorData(ostream *fp, vtkDataArray *tensors, int num) +{ + char format[1024]; + + char* tensorsName; + // Buffer size is size of array name times four because + // in theory there could be array name consisting of only + // weird symbols. + if (!this->TensorsName) + { + if (tensors->GetName() && strlen(tensors->GetName())) + { + tensorsName = new char[ strlen(tensors->GetName()) * 4 + 1]; + this->EncodeArrayName(tensorsName, tensors->GetName()); + } + else + { + tensorsName = new char[ strlen("tensors") + 1]; + strcpy(tensorsName, "tensors"); + } + } + else + { + tensorsName = new char[ strlen(this->TensorsName) * 4 + 1]; + this->EncodeArrayName(tensorsName, this->TensorsName); + } + + *fp << "TENSORS "; + sprintf(format, "%s %s\n", tensorsName, "%s"); + delete[] tensorsName; + + return this->WriteArray(fp, tensors->GetDataType(), tensors, format, num, 9); +} + +int vtkIsInTheList(int index, int* list, int numElem) +{ + for(int i=0; iGetNumberOfArrays(), actNumArrays=0; + int numComp, numTuples; + int attributeIndices[vtkDataSetAttributes::NUM_ATTRIBUTES]; + vtkDataArray *array; + + for(i=0; iGetAttributeIndices(attributeIndices); + } + + for (i=0; i < numArrays; i++) + { + if (!vtkIsInTheList(i, attributeIndices, + vtkDataSetAttributes::NUM_ATTRIBUTES)) + { + actNumArrays++; + } + } + if ( actNumArrays < 1 ) + { + return 1; + } + *fp << "FIELD " << this->FieldDataName << " " << actNumArrays << "\n"; + + + for (i=0; i < numArrays; i++) + { + if (!vtkIsInTheList(i, attributeIndices, + vtkDataSetAttributes::NUM_ATTRIBUTES)) + { + array = f->GetArray(i); + if ( array != NULL ) + { + numComp = array->GetNumberOfComponents(); + numTuples = array->GetNumberOfTuples(); + + // Buffer size is size of array name times four because + // in theory there could be array name consisting of only + // weird symbols. + char* buffer; + if( !array->GetName() || strlen(array->GetName()) == 0) + { + buffer = strcpy(new char[strlen("unknown")+1], "unknown"); + } + else + { + buffer = new char[ strlen(array->GetName()) * 4 + 1]; + this->EncodeArrayName(buffer, array->GetName()); + } + sprintf(format, "%s %d %d %s\n", buffer, numComp, numTuples, + "%s"); + this->WriteArray(fp, array->GetDataType(), array, format, numTuples, + numComp); + delete [] buffer; + } + else + { + *fp << "NULL_ARRAY"; + } + } + } + + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + return 1; +} + +int vtkDataWriter::WriteCells(ostream *fp, vtkCellArray *cells, const char *label) +{ + if ( ! cells ) + { + return 1; + } + + int ncells=cells->GetNumberOfCells(); + int size=cells->GetNumberOfConnectivityEntries(); + + if ( ncells < 1 ) + { + return 1; + } + + *fp << label << " " << ncells << " " << size << "\n"; + + if ( this->FileType == VTK_ASCII ) + { + int j; + vtkIdType *pts = 0; + vtkIdType npts = 0; + for (cells->InitTraversal(); cells->GetNextCell(npts,pts); ) + { + // currently writing vtkIdType as int + *fp << (int)npts << " "; + for (j=0; jGetPointer(); + int arraySize = cells->GetNumberOfConnectivityEntries(); + int *intArray = new int[arraySize]; + int i; + + for (i = 0; i < arraySize; i++) + { + intArray[i] = tempArray[i]; + } + + vtkByteSwap::SwapWrite4BERange(intArray,size,fp); + delete [] intArray; + } + + *fp << "\n"; + + fp->flush(); + if (fp->fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + + return 1; +} + +void vtkDataWriter::WriteData() +{ + vtkErrorMacro(<<"WriteData() should be implemented in concrete subclass"); +} + +// Close a vtk file. +void vtkDataWriter::CloseVTKFile(ostream *fp) +{ + vtkDebugMacro(<<"Closing vtk file\n"); + + if ( fp != NULL ) + { + if (this->WriteToOutputString) + { + char *tmp; + ostrstream *ostr = (ostrstream*)(fp); + this->OutputStringLength = ostr->pcount(); + + if (this->OutputStringLength == this->OutputStringAllocatedLength) + { + vtkErrorMacro("OutputString was not long enough."); + } + // Sanity check. + tmp = ostr->str(); + if (tmp != this->OutputString) + { + vtkErrorMacro("String mismatch"); + } + this->OutputString = tmp; + } + delete fp; + } + +} + +char *vtkDataWriter::RegisterAndGetOutputString() +{ + char *tmp = this->OutputString; + + this->OutputString = NULL; + this->OutputStringLength = 0; + this->OutputStringAllocatedLength = 0; + + return tmp; +} + + +void vtkDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + if ( this->FileType == VTK_BINARY ) + { + os << indent << "File Type: BINARY\n"; + } + else + { + os << indent << "File Type: ASCII\n"; + } + + if ( this->Header ) + { + os << indent << "Header: " << this->Header << "\n"; + } + else + { + os << indent << "Header: (None)\n"; + } + + os << indent << "Output String Length: " << this->OutputStringLength << "\n"; + os << indent << "Output String (addr): " << ((void *)this->OutputString) << "\n"; + os << indent << "WriteToOutputString: " << (this->WriteToOutputString ? "On\n" : "Off\n"); + + if ( this->ScalarsName ) + { + os << indent << "Scalars Name: " << this->ScalarsName << "\n"; + } + else + { + os << indent << "Scalars Name: (None)\n"; + } + + if ( this->VectorsName ) + { + os << indent << "Vectors Name: " << this->VectorsName << "\n"; + } + else + { + os << indent << "Vectors Name: (None)\n"; + } + + if ( this->NormalsName ) + { + os << indent << "Normals Name: " << this->NormalsName << "\n"; + } + else + { + os << indent << "Normals Name: (None)\n"; + } + + if ( this->TensorsName ) + { + os << indent << "Tensors Name: " << this->TensorsName << "\n"; + } + else + { + os << indent << "Tensors Name: (None)\n"; + } + + if ( this->TCoordsName ) + { + os << indent << "Texture Coords Name: " << this->TCoordsName << "\n"; + } + else + { + os << indent << "Texture Coordinates Name: (None)\n"; + } + + if ( this->LookupTableName ) + { + os << indent << "Lookup Table Name: " << this->LookupTableName << "\n"; + } + else + { + os << indent << "Lookup Table Name: (None)\n"; + } + + if ( this->FieldDataName ) + { + os << indent << "Field Data Name: " << this->FieldDataName << "\n"; + } + else + { + os << indent << "Field Data Name: (None)\n"; + } + +} + +int vtkDataWriter::WriteDataSetData(ostream *fp, vtkDataSet *ds) +{ + vtkFieldData* field = ds->GetFieldData(); + if (field && field->GetNumberOfTuples() > 0) + { + if ( !this->WriteFieldData(fp, field) ) + { + return 0; // we tried to write field data, but we couldn't + } + } + return 1; +} diff --git a/IO/vtkDataWriter.h b/IO/vtkDataWriter.h new file mode 100644 index 0000000..d9c7ac0 --- /dev/null +++ b/IO/vtkDataWriter.h @@ -0,0 +1,208 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataWriter - helper class for objects that write vtk data files +// .SECTION Description +// vtkDataWriter is a helper class that opens and writes the vtk header and +// point data (e.g., scalars, vectors, normals, etc.) from a vtk data file. +// See text for various formats. + +// .SECTION See Also +// vtkDataSetWriter vtkPolyDataWriter vtkStructuredGridWriter +// vtkStructuredPointsWriter vtkUnstructuredGridWriter +// vtkFieldDataWriter vtkRectilinearGridWriter + +#ifndef __vtkDataWriter_h +#define __vtkDataWriter_h + +#include "vtkWriter.h" + +class vtkDataSet; +class vtkPoints; +class vtkCellArray; +class vtkDataArray; +class vtkFieldData; + +class VTK_IO_EXPORT vtkDataWriter : public vtkWriter +{ +public: + vtkTypeRevisionMacro(vtkDataWriter,vtkWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Created object with default header, ASCII format, and default names for + // scalars, vectors, tensors, normals, and texture coordinates. + static vtkDataWriter *New(); + + // Description: + // Specify file name of vtk polygon data file to write. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Enable writing to an OutputString instead of the default, a file. + vtkSetMacro(WriteToOutputString,int); + vtkGetMacro(WriteToOutputString,int); + vtkBooleanMacro(WriteToOutputString,int); + + // Description: + // When WriteToOutputString in on, then a string is allocated, written to, + // and can be retrieved with these methods. The string is deleted during + // the next call to write ... + vtkGetMacro(OutputStringLength, int); + vtkGetStringMacro(OutputString); + unsigned char *GetBinaryOutputString() { + return (unsigned char *)this->OutputString;}; + + // Description: + // This convenience method returns the string, sets the IVAR to NULL, + // so that the user is responsible for deleting the string. + // I am not sure what the name should be, so it may change in the future. + char *RegisterAndGetOutputString(); + + // Description: + // Specify the header for the vtk data file. + vtkSetStringMacro(Header); + vtkGetStringMacro(Header); + + // Description: + // Specify file type (ASCII or BINARY) for vtk data file. + vtkSetClampMacro(FileType,int,VTK_ASCII,VTK_BINARY); + vtkGetMacro(FileType,int); + void SetFileTypeToASCII() {this->SetFileType(VTK_ASCII);}; + void SetFileTypeToBinary() {this->SetFileType(VTK_BINARY);}; + + // Description: + // Give a name to the scalar data. If not specified, uses default + // name "scalars". + vtkSetStringMacro(ScalarsName); + vtkGetStringMacro(ScalarsName); + + // Description: + // Give a name to the vector data. If not specified, uses default + // name "vectors". + vtkSetStringMacro(VectorsName); + vtkGetStringMacro(VectorsName); + + // Description: + // Give a name to the tensors data. If not specified, uses default + // name "tensors". + vtkSetStringMacro(TensorsName); + vtkGetStringMacro(TensorsName); + + // Description: + // Give a name to the normals data. If not specified, uses default + // name "normals". + vtkSetStringMacro(NormalsName); + vtkGetStringMacro(NormalsName); + + // Description: + // Give a name to the texture coordinates data. If not specified, uses + // default name "textureCoords". + vtkSetStringMacro(TCoordsName); + vtkGetStringMacro(TCoordsName); + + // Description: + // Give a name to the lookup table. If not specified, uses default + // name "lookupTable". + vtkSetStringMacro(LookupTableName); + vtkGetStringMacro(LookupTableName); + + // Description: + // Give a name to the field data. If not specified, uses default + // name "field". + vtkSetStringMacro(FieldDataName); + vtkGetStringMacro(FieldDataName); + + // Description: + // Open a vtk data file. Returns NULL if error. + virtual ostream *OpenVTKFile(); + + // Description: + // Write the header of a vtk data file. Returns 0 if error. + int WriteHeader(ostream *fp); + + // Description: + // Write out the points of the data set. + int WritePoints(ostream *fp, vtkPoints *p); + + // Description: + // Write out coordinates for rectilinear grids. + int WriteCoordinates(ostream *fp, vtkDataArray *coords, int axes); + + // Description: + // Write out the cells of the data set. + int WriteCells(ostream *fp, vtkCellArray *cells, const char *label); + + // Description: + // Write the cell data (e.g., scalars, vectors, ...) of a vtk dataset. + // Returns 0 if error. + int WriteCellData(ostream *fp, vtkDataSet *ds); + + // Description: + // Write the point data (e.g., scalars, vectors, ...) of a vtk dataset. + // Returns 0 if error. + int WritePointData(ostream *fp, vtkDataSet *ds); + + // Description: + // Write out the field data. + int WriteFieldData(ostream *fp, vtkFieldData *f); + + // Description: + // Write out the data associated with the dataset (i.e. field data owned by + // the dataset itself - distinct from that owned by the cells or points). + int WriteDataSetData(ostream *fp, vtkDataSet *ds); + + // Description: + // Close a vtk file. + void CloseVTKFile(ostream *fp); + + +protected: + vtkDataWriter(); + ~vtkDataWriter(); + + int WriteToOutputString; + char *OutputString; + int OutputStringLength; + int OutputStringAllocatedLength; + + void WriteData(); //dummy method to allow this class to be instantiated and delegated to + + char *FileName; + char *Header; + int FileType; + + char *ScalarsName; + char *VectorsName; + char *TensorsName; + char *TCoordsName; + char *NormalsName; + char *LookupTableName; + char *FieldDataName; + + int WriteArray(ostream *fp, int dataType, vtkDataArray *data, const char *format, + int num, int numComp); + int WriteScalarData(ostream *fp, vtkDataArray *s, int num); + int WriteVectorData(ostream *fp, vtkDataArray *v, int num); + int WriteNormalData(ostream *fp, vtkDataArray *n, int num); + int WriteTCoordData(ostream *fp, vtkDataArray *tc, int num); + int WriteTensorData(ostream *fp, vtkDataArray *t, int num); + +private: + vtkDataWriter(const vtkDataWriter&); // Not implemented. + void operator=(const vtkDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkEnSight6BinaryReader.cxx b/IO/vtkEnSight6BinaryReader.cxx new file mode 100644 index 0000000..20b2508 --- /dev/null +++ b/IO/vtkEnSight6BinaryReader.cxx @@ -0,0 +1,2946 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSight6BinaryReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEnSight6BinaryReader.h" + +#include "vtkByteSwap.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkEnSight6BinaryReader, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkEnSight6BinaryReader); + +//---------------------------------------------------------------------------- +vtkEnSight6BinaryReader::vtkEnSight6BinaryReader() +{ + this->NumberOfUnstructuredPoints = 0; + this->UnstructuredPoints = vtkPoints::New(); + this->UnstructuredNodeIds = NULL; + + this->IFile = NULL; + + this->FileSize = 0; +} + +//---------------------------------------------------------------------------- +vtkEnSight6BinaryReader::~vtkEnSight6BinaryReader() +{ + if (this->UnstructuredNodeIds) + { + this->UnstructuredNodeIds->Delete(); + this->UnstructuredNodeIds = NULL; + } + this->UnstructuredPoints->Delete(); + this->UnstructuredPoints = NULL; + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::OpenFile(const char* filename) +{ + if (!filename) + { + vtkErrorMacro(<<"Missing filename."); + return 0; + } + + // Close file from any previous image + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + + // Open the new file + vtkDebugMacro(<< "Opening file " << filename); + struct stat fs; + if ( !stat( filename, &fs) ) + { + // Find out how big the file is. + this->FileSize = (int)(fs.st_size); + +#ifdef _WIN32 + this->IFile = new ifstream(filename, ios::in | ios::binary); +#else + this->IFile = new ifstream(filename, ios::in); +#endif + } + else + { + vtkErrorMacro("stat failed."); + return 0; + } + if (! this->IFile || this->IFile->fail()) + { + vtkErrorMacro(<< "Could not open file " << filename); + return 0; + } + return 1; +} + + + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadGeometryFile(const char* fileName, int timeStep) +{ + char line[80], subLine[80]; + int partId, realId; + int lineRead; + float *coordinateArray; + int i; + int pointIdsListed; + int *pointIds; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A GeometryFileName must be specified in the case file."); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to geometry file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + lineRead = this->ReadLine(line); + sscanf(line, " %*s %s", subLine); + if (strcmp(subLine, "Binary") != 0 && + strcmp(subLine, "binary") != 0) + { + vtkErrorMacro("This is not an EnSight6 binary file. Try " + << "vtkEnSight6Reader."); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + if (!this->SkipTimeStep()) + { + return 0; + } + } + while (strncmp(line, "BEGIN TIME STEP", 15) != 0 && lineRead) + { + lineRead = this->ReadLine(line); + } + } + + // Skip the 2 description lines. Using ReadLine instead of ReadLine + // because the description line could be blank. + this->ReadLine(line); + this->ReadLine(line); + + // Read the node id and element id lines. + this->ReadLine(line); // node id * + sscanf(line, " %*s %*s %s", subLine); + if (strcmp(subLine, "given") == 0) + { + this->UnstructuredNodeIds = vtkIdTypeArray::New(); + pointIdsListed = 1; + } + else if (strcmp(subLine, "ignore") == 0) + { + pointIdsListed = 1; + } + else + { + pointIdsListed = 0; + } + + this->ReadLine(line); // element id * + sscanf(line, " %*s %*s %s", subLine); + if (strcmp(subLine, "given") == 0 || strcmp(subLine, "ignore") == 0) + { + this->ElementIdsListed = 1; + } + else + { + this->ElementIdsListed = 0; + } + + this->ReadLine(line); // "coordinates" + this->ReadIntNumber(&this->NumberOfUnstructuredPoints); // number of points + if (this->NumberOfUnstructuredPoints < 0 || + this->NumberOfUnstructuredPoints*(int)sizeof(int) > this->FileSize || + this->NumberOfUnstructuredPoints > this->FileSize) + { + vtkErrorMacro("Invalid number of unstructured points; check that ByteOrder is set correctly."); + return 0; + } + + this->UnstructuredPoints->SetNumberOfPoints( + this->NumberOfUnstructuredPoints); + + if (pointIdsListed) + { + pointIds = new int[this->NumberOfUnstructuredPoints]; + this->ReadIntArray(pointIds, this->NumberOfUnstructuredPoints); + + if (this->UnstructuredNodeIds) + { + int maxId = 0; + for (i = 0; i < this->NumberOfUnstructuredPoints; i++) + { + if (pointIds[i] > maxId) + { + maxId = pointIds[i]; + } + } + + this->UnstructuredNodeIds->Allocate(maxId); + this->UnstructuredNodeIds->FillComponent(0, -1); + + for (i = 0; i < this->NumberOfUnstructuredPoints; i++) + { + this->UnstructuredNodeIds->InsertValue(pointIds[i]-1, i); + } + } + delete [] pointIds; + } + + coordinateArray = (float*)(this->UnstructuredPoints->GetVoidPointer(0)); + this->ReadFloatArray(coordinateArray, this->NumberOfUnstructuredPoints * 3); + + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->NumberOfGeometryParts++; + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing at 1. + realId = this->InsertNewPartId(partId); + + this->ReadLine(line); // part description line + char *name = strdup(line); + this->ReadLine(line); + + if (strncmp(line, "block", 5) == 0) + { + lineRead = this->CreateStructuredGridOutput(realId, line, name); + } + else + { + lineRead = this->CreateUnstructuredGridOutput(realId, line, name); + } + free(name); + } + + if (this->UnstructuredNodeIds) + { + this->UnstructuredNodeIds->Delete(); + this->UnstructuredNodeIds = NULL; + } + // Close file from any previous image + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + if (lineRead < 0) + { + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::SkipTimeStep() +{ + char line[80], subLine[80]; + int lineRead; + int pointIdsListed; + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + + // Skip the 2 description lines. + this->ReadLine(line); + this->ReadLine(line); + + // Read the node id and element id lines. + this->ReadLine(line); // node id * + sscanf(line, " %*s %*s %s", subLine); + if (strcmp(subLine, "given") == 0 || + strcmp(subLine, "ignore") == 0) + { + pointIdsListed = 1; + } + else + { + pointIdsListed = 0; + } + + this->ReadLine(line); // element id * + sscanf(line, " %*s %*s %s", subLine); + if (strcmp(subLine, "given") == 0 || strcmp(subLine, "ignore") == 0) + { + this->ElementIdsListed = 1; + } + else + { + this->ElementIdsListed = 0; + } + + this->ReadLine(line); // "coordinates" + this->ReadIntNumber(&this->NumberOfUnstructuredPoints); // number of points + if (this->NumberOfUnstructuredPoints < 0 || + this->NumberOfUnstructuredPoints*(int)sizeof(int) > this->FileSize || + this->NumberOfUnstructuredPoints > this->FileSize) + { + vtkErrorMacro("Invalid number of unstructured points; check that ByteOrder is set correctly."); + return 0; + } + + if (pointIdsListed) + { // skip point ids. + this->IFile->seekg((sizeof(int)*this->NumberOfUnstructuredPoints), ios::cur); + } + + this->IFile->seekg((sizeof(float)*3*this->NumberOfUnstructuredPoints), ios::cur); + + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadLine(line); // part description line + this->ReadLine(line); + + if (strncmp(line, "block", 5) == 0) + { + lineRead = this->SkipStructuredGrid(line); + } + else + { + lineRead = this->SkipUnstructuredGrid(line); + } + } + if (lineRead < 0) + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::SkipStructuredGrid(char line[256]) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int numPts; + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strcmp(subLine, "iblanked") == 0) + { + iblanked = 1; + } + } + + // Read these separately to get byte order set. + this->ReadIntNumber(dimensions); + this->ReadIntNumber(dimensions+1); + this->ReadIntNumber(dimensions+2); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + numPts < 0 || numPts*(int)sizeof(int) > this->FileSize || + numPts > this->FileSize) + { + vtkErrorMacro("Invalid dimensions read; check that ByteOrder is set correctly."); + return -1; + } + + // Skip coordinates. + this->IFile->seekg((sizeof(float)*3*numPts), ios::cur); + + if (iblanked) + { // skip blanking array. + this->IFile->seekg((sizeof(int)*numPts), ios::cur); + } + + // reading next line to check for EOF + lineRead = this->ReadLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::SkipUnstructuredGrid(char line[256]) +{ + int lineRead = 1; + int numElements; + int cellType; + + while(lineRead && strncmp(line, "part", 4) != 0) + { + if (strncmp(line, "point", 5) == 0) + { + vtkDebugMacro("point"); + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of point cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { // skip element ids. + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + // nodeIdList + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + else if (strncmp(line, "bar2", 4) == 0) + { + vtkDebugMacro("bar2"); + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar2 cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { // skip element ids. + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + // Skip node ids. + this->IFile->seekg((sizeof(int)*2*numElements), ios::cur); + } + else if (strncmp(line, "bar3", 4) == 0) + { + vtkDebugMacro("bar3"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar3 cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + // Skip node ids. + this->IFile->seekg((sizeof(int)*3*numElements), ios::cur); + } + else if (strncmp(line, "tria3", 5) == 0 || + strncmp(line, "tria6", 5) == 0) + { + if (strncmp(line, "tria3", 5) == 0) + { + vtkDebugMacro("tria3"); + cellType = vtkEnSightReader::TRIA3; + } + else + { + vtkDebugMacro("tria6"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TRIA6; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of triangle cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::TRIA3) + { + this->IFile->seekg((sizeof(int)*3*numElements), ios::cur); + } + else + { + this->IFile->seekg((sizeof(int)*6*numElements), ios::cur); + } + } + else if (strncmp(line, "quad4", 5) == 0 || + strncmp(line, "quad8", 5) == 0) + { + if (strncmp(line, "quad8", 5) == 0) + { + vtkDebugMacro("quad8"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::QUAD8; + } + else + { + vtkDebugMacro("quad4"); + cellType = vtkEnSightReader::QUAD4; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of quad cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::QUAD4) + { + this->IFile->seekg((sizeof(int)*4*numElements), ios::cur); + } + else + { + this->IFile->seekg((sizeof(int)*8*numElements), ios::cur); + } + } + else if (strncmp(line, "tetra4", 6) == 0 || + strncmp(line, "tetra10", 7) == 0) + { + if (strncmp(line, "tetra10", 7) == 0) + { + vtkDebugMacro("tetra10"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TETRA10; + } + else + { + vtkDebugMacro("tetra4"); + cellType = vtkEnSightReader::TETRA4; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of tetrahedral cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::TETRA4) + { + this->IFile->seekg((sizeof(int)*4*numElements), ios::cur); + } + else + { + this->IFile->seekg((sizeof(int)*10*numElements), ios::cur); + } + } + else if (strncmp(line, "pyramid5", 8) == 0 || + strncmp(line, "pyramid13", 9) == 0) + { + if (strncmp(line, "pyramid13", 9) == 0) + { + vtkDebugMacro("pyramid13"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PYRAMID13; + } + else + { + vtkDebugMacro("pyramid5"); + cellType = vtkEnSightReader::PYRAMID5; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pyramid cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::PYRAMID5) + { + this->IFile->seekg((sizeof(int)*5*numElements), ios::cur); + } + else + { + this->IFile->seekg((sizeof(int)*13*numElements), ios::cur); + } + } + else if (strncmp(line, "hexa8", 5) == 0 || + strncmp(line, "hexa20", 6) == 0) + { + if (strncmp(line, "hexa20", 6) == 0) + { + vtkDebugMacro("hexa20"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::HEXA20; + } + else + { + vtkDebugMacro("hexa8"); + cellType = vtkEnSightReader::HEXA8; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of hexahedral cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::HEXA8) + { + this->IFile->seekg((sizeof(int)*8*numElements), ios::cur); + } + else + { + this->IFile->seekg((sizeof(int)*20*numElements), ios::cur); + } + } + else if (strncmp(line, "penta6", 6) == 0 || + strncmp(line, "penta15", 7) == 0) + { + if (strncmp(line, "penta15", 7) == 0) + { + vtkDebugMacro("penta15"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PENTA15; + } + else + { + vtkDebugMacro("penta6"); + cellType = vtkEnSightReader::PENTA6; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pentagonal cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::PENTA6) + { + this->IFile->seekg((sizeof(int)*6*numElements), ios::cur); + } + else + { + this->IFile->seekg((sizeof(int)*15*numElements), ios::cur); + } + } + else if (strncmp(line, "END TIME STEP", 13) == 0) + { + break; + } + lineRead = this->ReadLine(line); + } + + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadMeasuredGeometryFile(const char* fileName, + int timeStep) +{ + char line[80], subLine[80]; + int i; + int *pointIds; + float *coords; + vtkPoints *points = vtkPoints::New(); + vtkPolyData *pd = vtkPolyData::New(); + + this->NumberOfNewOutputs++; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A MeasuredFileName must be specified in the case file."); + points->Delete(); + pd->Delete(); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to measured geometry file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + points->Delete(); + pd->Delete(); + return 0; + } + + if (this->GetOutput(this->NumberOfGeometryParts) && + ! this->GetOutput(this->NumberOfGeometryParts)->IsA("vtkPolyData")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + points->Delete(); + pd->Delete(); + return 0; + } + + this->ReadLine(line); + sscanf(line, " %*s %s", subLine); + if (strcmp(subLine, "Binary") != 0) + { + vtkErrorMacro("This is not a binary data set. Try " + << "vtkEnSightGoldReader."); + points->Delete(); + pd->Delete(); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + + // Skip the description line. + this->ReadLine(line); + + this->ReadLine(line); // "particle coordinates" + + this->ReadIntNumber(&this->NumberOfMeasuredPoints); + if (this->NumberOfMeasuredPoints < 0 || + this->NumberOfMeasuredPoints*(int)sizeof(int) > this->FileSize || + this->NumberOfMeasuredPoints > this->FileSize) + { + vtkErrorMacro("Invalid number of measured points; check that ByteOrder is set correctly."); + points->Delete(); + pd->Delete(); + return 0; + } + + pointIds = new int[this->NumberOfMeasuredPoints]; + coords = new float [this->NumberOfMeasuredPoints*3]; + + this->ReadIntArray(pointIds, this->NumberOfMeasuredPoints); + this->ReadFloatArray(coords, this->NumberOfMeasuredPoints*3); + + delete [] pointIds; + delete [] coords; + + this->ReadLine(line); // END TIME STEP + } + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + // Skip the description line. + this->ReadLine(line); + + this->ReadLine(line); // "particle coordinates" + + this->ReadIntNumber(&this->NumberOfMeasuredPoints); + if (this->NumberOfMeasuredPoints < 0 || + this->NumberOfMeasuredPoints*(int)sizeof(int) > this->FileSize || + this->NumberOfMeasuredPoints > this->FileSize) + { + vtkErrorMacro("Invalid number of measured points; check that ByteOrder is set correctly."); + points->Delete(); + pd->Delete(); + return 0; + } + + pointIds = new int[this->NumberOfMeasuredPoints]; + coords = new float [this->NumberOfMeasuredPoints*3]; + points->Allocate(this->NumberOfMeasuredPoints); + pd->Allocate(this->NumberOfMeasuredPoints); + + this->ReadIntArray(pointIds, this->NumberOfMeasuredPoints); + this->ReadFloatArray(coords, this->NumberOfMeasuredPoints*3); + + for (i = 0; i < this->NumberOfMeasuredPoints; i++) + { + points->InsertNextPoint(coords[3*i], coords[3*i+1], coords[3*i+2]); + pd->InsertNextCell(VTK_VERTEX, 1, (vtkIdType*)&pointIds[i]); + } + + pd->SetPoints(points); + this->SetNthOutput(this->NumberOfGeometryParts, pd); + + points->Delete(); + pd->Delete(); + delete [] pointIds; + delete [] coords; + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadScalarsPerNode(const char* fileName, + const char* description, + int timeStep, int measured, + int numberOfComponents, + int component) +{ + char line[80]; + int partId, realId, numPts, numParts, i; + vtkFloatArray *scalars; + float* scalarsRead; + long pos; + vtkDataSet *output; + int lineRead; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalar per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + + pos = this->IFile->tellg(); + this->ReadLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + this->IFile->seekg(pos, ios::beg); + if (!measured) + { + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + } + else + { + numPts = this->GetOutput(this->NumberOfGeometryParts)-> + GetNumberOfPoints(); + } + + // Here I am assuming that we are skiping over data + // we do not need to read. + //scalarsRead = new float[numPts]; + //this->ReadFloatArray(scalarsRead, numPts); + //delete [] scalarsRead; + this->IFile->seekg((long)(numPts)*(long)(sizeof(float)), ios::cur); + if (this->IFile->fail()) + { + vtkErrorMacro("File seek failed."); + } + } + + // scalars for structured parts + while (this->ReadLine(line) && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; + realId = this->InsertNewPartId(partId); + this->ReadLine(line); // block + numPts = this->GetOutput(realId)->GetNumberOfPoints(); + + // Here I am assuming that we are skiping over data + // we do not need to read. + //scalarsRead = new float[numPts]; + //this->ReadFloatArray(scalarsRead, numPts); + //delete [] scalarsRead; + this->IFile->seekg((long)(numPts)*(long)(sizeof(float)), ios::cur); + if (this->IFile->fail()) + { + vtkErrorMacro("File seek failed."); + } + //scalarsRead = new float[numPts]; + //this->ReadFloatArray(scalarsRead, numPts); + //delete [] scalarsRead; + } + } + lineRead = this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0 && lineRead) + { + lineRead = this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + pos = this->IFile->tellg(); + lineRead = this->ReadLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + int allocatedScalars = 0; + this->IFile->seekg(pos, ios::beg); + if (!measured) + { + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + } + else + { + numPts = this->GetOutput(this->NumberOfGeometryParts)-> + GetNumberOfPoints(); + } + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numPts); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numPts * numberOfComponents); + allocatedScalars = 1; + } + else + { + partId = this->UnstructuredPartIds->GetId(0); + scalars = (vtkFloatArray*)(this->GetOutput(partId)->GetPointData()-> + GetArray(description)); + } + scalarsRead = new float[numPts]; + this->ReadFloatArray(scalarsRead, numPts); + for (i = 0; i < numPts; i++) + { + scalars->InsertComponent(i, component, scalarsRead[i]); + } + + if (!measured) + { + numParts = this->UnstructuredPartIds->GetNumberOfIds(); + for (i = 0; i < numParts; i++) + { + partId = this->UnstructuredPartIds->GetId(i); + output = this->GetOutput(partId); + if (component == 0) + { + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + } + else + { + output->GetPointData()->AddArray(scalars); + } + } + } + else + { + scalars->SetName(description); + output = this->GetOutput(this->NumberOfGeometryParts); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + } + delete [] scalarsRead; + if(allocatedScalars) + { + scalars->Delete(); + } + } + + // scalars for structured parts + while (lineRead && strncmp(line, "part", 4) == 0) + { + int allocatedScalars = 0; + sscanf(line, " part %d", &partId); + partId--; + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + if (output == NULL) + { + vtkErrorMacro("Could not get output for part " << partId); + vtkErrorMacro("Got part from line: " << line); + return 0; + } + + this->ReadLine(line); // block + numPts = output->GetNumberOfPoints(); + scalarsRead = new float[numPts]; + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numPts); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numPts * numberOfComponents); + allocatedScalars = 1; + } + else + { + scalars = (vtkFloatArray*)(output->GetPointData()-> + GetArray(description)); + } + this->ReadFloatArray(scalarsRead, numPts); + for (i = 0; i < numPts; i++) + { + scalars->InsertComponent(i, component, scalarsRead[i]); + } + if (component == 0) + { + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + } + else + { + output->GetPointData()->AddArray(scalars); + } + delete [] scalarsRead; + lineRead = this->ReadLine(line); + if(allocatedScalars) + { + scalars->Delete(); + } + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadVectorsPerNode(const char* fileName, + const char* description, + int timeStep, int measured) +{ + char line[80]; + int partId, realId, numPts, i; + vtkFloatArray *vectors; + float vector[3]; + float *vectorsRead; + long pos; + vtkDataSet *output; + int lineRead; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + + pos = this->IFile->tellg(); + this->ReadLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + this->IFile->seekg(pos, ios::beg); + if (!measured) + { + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + } + else + { + numPts = this->GetOutput(this->NumberOfGeometryParts)-> + GetNumberOfPoints(); + } + + vectorsRead = new float[numPts*3]; + this->ReadFloatArray(vectorsRead, numPts*3); + + delete [] vectorsRead; + } + + // vectors for structured parts + while (this->ReadLine(line) && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; + realId = this->InsertNewPartId(partId); + this->ReadLine(line); // block + numPts = this->GetOutput(realId)->GetNumberOfPoints(); + vectorsRead = new float[numPts*3]; + + this->ReadFloatArray(vectorsRead, numPts*3); + + delete [] vectorsRead; + } + } + lineRead = this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0 && lineRead) + { + lineRead = this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + pos = this->IFile->tellg(); + lineRead = this->ReadLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + this->IFile->seekg(pos, ios::beg); + if (!measured) + { + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + } + else + { + numPts = this->GetOutput(this->NumberOfGeometryParts)-> + GetNumberOfPoints(); + } + + vectors = vtkFloatArray::New(); + vectors->SetNumberOfTuples(numPts); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numPts*3); + vectorsRead = new float[numPts*3]; + this->ReadFloatArray(vectorsRead, numPts*3); + for (i = 0; i < numPts; i++) + { + vector[0] = vectorsRead[3*i]; + vector[1] = vectorsRead[3*i+1]; + vector[2] = vectorsRead[3*i+2]; + vectors->InsertTuple(i, vector); + } + + if (!measured) + { + for (i = 0; i < this->UnstructuredPartIds->GetNumberOfIds(); i++) + { + partId = this->UnstructuredPartIds->GetId(i); + output = this->GetOutput(partId); + vectors->SetName(description); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + } + } + else + { + vectors->SetName(description); + output = this->GetOutput(this->NumberOfGeometryParts); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + } + + vectors->Delete(); + delete [] vectorsRead; + } + + // vectors for structured parts + while (lineRead && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + this->ReadLine(line); // block + numPts = output->GetNumberOfPoints(); + vectors = vtkFloatArray::New(); + vectors->SetNumberOfTuples(numPts); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numPts*3); + vectorsRead = new float[numPts*3]; + + this->ReadFloatArray(vectorsRead, numPts*3); + for (i = 0; i < numPts; i++) + { + vector[0] = vectorsRead[3*i]; + vector[1] = vectorsRead[3*i+1]; + vector[2] = vectorsRead[3*i+2]; + vectors->InsertTuple(i, vector); + } + + vectors->SetName(description); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + vectors->Delete(); + delete [] vectorsRead; + lineRead = this->ReadLine(line); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadTensorsPerNode(const char* fileName, + const char* description, + int timeStep) +{ + char line[80]; + int partId, realId, numPts, i; + vtkFloatArray *tensors; + float tensor[6]; + float* tensorsRead; + long pos; + vtkDataSet *output; + int lineRead; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorSymmPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor symm per node file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseTimeSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + + pos = this->IFile->tellg(); + this->ReadLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + this->IFile->seekg(pos, ios::beg); + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + tensorsRead = new float[numPts*6]; + this->ReadFloatArray(tensorsRead, numPts*6); + + delete [] tensorsRead; + } + + // vectors for structured parts + while (this->ReadLine(line) && + strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; + realId = this->InsertNewPartId(partId); + this->ReadLine(line); // block + numPts = this->GetOutput(realId)->GetNumberOfPoints(); + tensorsRead = new float[numPts*6]; + this->ReadFloatArray(tensorsRead, numPts*6); + + delete [] tensorsRead; + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + pos = this->IFile->tellg(); + lineRead = this->ReadLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + this->IFile->seekg(pos, ios::beg); + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + tensors = vtkFloatArray::New(); + tensors->SetNumberOfTuples(numPts); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numPts*6); + tensorsRead = new float[numPts*6]; + this->ReadFloatArray(tensorsRead, numPts*6); + for (i = 0; i < numPts; i++) + { + tensor[0] = tensorsRead[6*i]; + tensor[1] = tensorsRead[6*i+1]; + tensor[2] = tensorsRead[6*i+2]; + tensor[3] = tensorsRead[6*i+3]; + tensor[4] = tensorsRead[6*i+4]; + tensor[5] = tensorsRead[6*i+5]; + tensors->InsertTuple(i, tensor); + } + + for (i = 0; i < this->UnstructuredPartIds->GetNumberOfIds(); i++) + { + partId = this->UnstructuredPartIds->GetId(i); + tensors->SetName(description); + this->GetOutput(partId)->GetPointData()->AddArray(tensors); + } + tensors->Delete(); + delete [] tensorsRead; + } + + // vectors for structured parts + while (lineRead && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + this->ReadLine(line); // block + numPts = output->GetNumberOfPoints(); + tensors = vtkFloatArray::New(); + tensors->SetNumberOfTuples(numPts); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numPts*6); + tensorsRead = new float[numPts*6]; + this->ReadFloatArray(tensorsRead, numPts*6); + + for (i = 0; i < numPts; i++) + { + tensor[0] = tensorsRead[6*i]; + tensor[1] = tensorsRead[6*i+1]; + tensor[2] = tensorsRead[6*i+2]; + tensor[3] = tensorsRead[6*i+3]; + tensor[4] = tensorsRead[6*i+4]; + tensor[5] = tensorsRead[6*i+5]; + tensors->InsertTuple(i, tensor); + } + + tensors->SetName(description); + output->GetPointData()->AddArray(tensors); + tensors->Delete(); + delete [] tensorsRead; + + lineRead = this->ReadLine(line); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadScalarsPerElement(const char* fileName, + const char* description, + int timeStep, + int numberOfComponents, + int component) +{ + char line[80]; + int partId, realId, numCells, numCellsPerElement, i, idx; + vtkFloatArray *scalars; + int elementType; + float* scalarsRead; + int lineRead; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalar per element file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); + + while (lineRead && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + numCells = this->GetOutput(realId)->GetNumberOfCells(); + lineRead = this->ReadLine(line); // element type or "block" + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") != 0) + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)-> + GetNumberOfIds(); + scalarsRead = new float[numCellsPerElement]; + this->ReadFloatArray(scalarsRead, numCellsPerElement); + + delete [] scalarsRead; + lineRead = this->ReadLine(line); + } // end while + } + else + { + scalarsRead = new float[numCells]; + this->ReadFloatArray(scalarsRead, numCells); + + delete [] scalarsRead; + lineRead = this->ReadLine(line); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); + + while (lineRead && strncmp(line, "part", 4) == 0) + { + int allocatedScalars = 0; + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + lineRead = this->ReadLine(line); // element type or "block" + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numCells); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numCells * numberOfComponents); + allocatedScalars = 1; + } + else + { + scalars = (vtkFloatArray*)(output->GetCellData()->GetArray(description)); + } + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") != 0) + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)->GetNumberOfIds(); + scalarsRead = new float[numCellsPerElement]; + this->ReadFloatArray(scalarsRead, numCellsPerElement); + for (i = 0; i < numCellsPerElement; i++) + { + scalars->InsertComponent(this->GetCellIds(idx, elementType)->GetId(i), + component, scalarsRead[i]); + } + delete [] scalarsRead; + lineRead = this->ReadLine(line); + } // end while + } + else + { + scalarsRead = new float[numCells]; + this->ReadFloatArray(scalarsRead, numCells); + for (i = 0; i < numCells; i++) + { + scalars->InsertComponent(i, component, scalarsRead[i]); + } + delete [] scalarsRead; + lineRead = this->ReadLine(line); + } + + if (component == 0) + { + scalars->SetName(description); + output->GetCellData()->AddArray(scalars); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(scalars); + } + } + else + { + output->GetCellData()->AddArray(scalars); + } + if(allocatedScalars) + { + scalars->Delete(); + } + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadVectorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[80]; + int partId, realId, numCells, numCellsPerElement, i, idx; + vtkFloatArray *vectors; + int elementType; + float vector[3]; + float *vectorsRead; + int lineRead; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per element file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); + + while (lineRead && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + numCells = this->GetOutput(realId)->GetNumberOfCells(); + lineRead = this->ReadLine(line); // element type or "block" + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") != 0) + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + delete this->IS; + this->IS = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = + this->GetCellIds(idx, elementType)->GetNumberOfIds(); + vectorsRead = new float[numCellsPerElement*3]; + this->ReadFloatArray(vectorsRead, numCellsPerElement*3); + + delete [] vectorsRead; + lineRead = this->ReadLine(line); + } // end while + } + else + { + vectorsRead = new float[numCells*3]; + this->ReadFloatArray(vectorsRead, numCells*3); + + delete [] vectorsRead; + lineRead = this->ReadLine(line); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); + + while (lineRead && strncmp(line, "part", 4) == 0) + { + vectors = vtkFloatArray::New(); + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + lineRead = this->ReadLine(line); // element type or "block" + vectors->SetNumberOfTuples(numCells); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numCells*3); + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") != 0) + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + delete this->IS; + this->IS = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)->GetNumberOfIds(); + vectorsRead = new float[numCellsPerElement*3]; + this->ReadFloatArray(vectorsRead, numCellsPerElement*3); + + for (i = 0; i < numCellsPerElement; i++) + { + vector[0] = vectorsRead[3*i]; + vector[1] = vectorsRead[3*i+1]; + vector[2] = vectorsRead[3*i+2]; + vectors->InsertTuple(this->GetCellIds(idx, elementType)->GetId(i), + vector); + } + delete [] vectorsRead; + lineRead = this->ReadLine(line); + } // end while + } + else + { + vectorsRead = new float[numCells*3]; + this->ReadFloatArray(vectorsRead, numCells*3); + for (i = 0; i < numCells; i++) + { + vector[0] = vectorsRead[3*i]; + vector[1] = vectorsRead[3*i+1]; + vector[2] = vectorsRead[3*i+2]; + vectors->InsertTuple(i, vector); + } + delete [] vectorsRead; + lineRead = this->ReadLine(line); + } + vectors->SetName(description); + output->GetCellData()->AddArray(vectors); + if (!output->GetCellData()->GetVectors()) + { + output->GetCellData()->SetVectors(vectors); + } + vectors->Delete(); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::ReadTensorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[80]; + int partId, realId, numCells, numCellsPerElement, i, idx; + vtkFloatArray *tensors; + int elementType; + float tensor[6]; + float *tensorsRead; + int lineRead; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor per element file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseTimeSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); + + while (lineRead && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + numCells = this->GetOutput(realId)->GetNumberOfCells(); + lineRead = this->ReadLine(line); // element type or "block" + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") != 0) + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)-> + GetNumberOfIds(); + tensorsRead = new float[numCellsPerElement*6]; + this->ReadFloatArray(tensorsRead, numCellsPerElement*6); + + delete [] tensorsRead; + lineRead = this->ReadLine(line); + } // end while + } + else + { + tensorsRead = new float[numCells*6]; + this->ReadFloatArray(tensorsRead, numCells*6); + + delete [] tensorsRead; + lineRead = this->ReadLine(line); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); + + while (lineRead && strncmp(line, "part", 4) == 0) + { + tensors = vtkFloatArray::New(); + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + lineRead = this->ReadLine(line); // element type or "block" + tensors->SetNumberOfTuples(numCells); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numCells*6); + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") != 0) + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)->GetNumberOfIds(); + tensorsRead = new float[numCellsPerElement*6]; + this->ReadFloatArray(tensorsRead, numCellsPerElement*6); + + for (i = 0; i < numCellsPerElement; i++) + { + tensor[0] = tensorsRead[6*i]; + tensor[1] = tensorsRead[6*i+1]; + tensor[2] = tensorsRead[6*i+2]; + tensor[3] = tensorsRead[6*i+3]; + tensor[4] = tensorsRead[6*i+4]; + tensor[5] = tensorsRead[6*i+5]; + + tensors->InsertTuple(this->GetCellIds(idx, elementType)->GetId(i), + tensor); + } + delete [] tensorsRead; + lineRead = this->ReadLine(line); + } // end while + } + else + { + tensorsRead = new float[numCells*6]; + this->ReadFloatArray(tensorsRead, numCells*6); + + for (i = 0; i < numCells; i++) + { + tensor[0] = tensorsRead[6*i]; + tensor[1] = tensorsRead[6*i+1]; + tensor[2] = tensorsRead[6*i+2]; + tensor[3] = tensorsRead[6*i+3]; + tensor[4] = tensorsRead[6*i+4]; + tensor[5] = tensorsRead[6*i+5]; + tensors->InsertTuple(i, tensor); + } + delete [] tensorsRead; + lineRead = this->ReadLine(line); + } + tensors->SetName(description); + output->GetCellData()->AddArray(tensors); + tensors->Delete(); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::CreateUnstructuredGridOutput(int partId, + char line[80], + const char* name) +{ + int lineRead = 1; + int i, j; + int *nodeIdList; + vtkIdType *nodeIds; + int numElements; + int idx, cellType; + vtkIdType cellId; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new unstructured output"); + vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New(); + this->SetNthOutput(partId, ugrid); + ugrid->Delete(); + + this->UnstructuredPartIds->InsertNextId(partId); + } + else if ( ! this->GetOutput(partId)->IsA("vtkUnstructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + // Clear all cell ids from the last execution, if any. + idx = this->UnstructuredPartIds->IsId(partId); + for (i = 0; i < 16; i++) + { + this->GetCellIds(idx, i)->Reset(); + } + + output->Allocate(1000); + + while(lineRead && strncmp(line, "part", 4) != 0) + { + if (strncmp(line, "point", 5) == 0) + { + vtkDebugMacro("point"); + + this->ReadIntNumber(&numElements); + if (numElements < 0 || + numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of point cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[1]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + nodeIdList = new int[numElements]; + this->ReadIntArray(nodeIdList, numElements); + + for (i = 0; i < numElements; i++) + { + nodeIds[0] = nodeIdList[i] - 1; + if (this->UnstructuredNodeIds) + { + nodeIds[0] = this->UnstructuredNodeIds->GetValue(nodeIds[0]); + } + cellId = output->InsertNextCell(VTK_VERTEX, 1, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::POINT)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "bar2", 4) == 0) + { + vtkDebugMacro("bar2"); + + this->ReadIntNumber(&numElements); + if (numElements < 0 || + numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar2 cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[2]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + nodeIdList = new int[numElements * 2]; + this->ReadIntArray(nodeIdList, numElements*2); + + for (i = 0; i < numElements; i++) + { + for (j = 0; j < 2; j++) + { + nodeIds[j] = nodeIdList[2*i+j] - 1; + } + + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 2; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR2)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "bar3", 4) == 0) + { + vtkDebugMacro("bar3"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar3 cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[2]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + nodeIdList = new int[numElements * 3]; + this->ReadIntArray(nodeIdList, numElements*3); + + for (i = 0; i < numElements; i++) + { + for (j = 0; j < 2; j++) + { + nodeIds[j] = nodeIdList[3*i+2*j] - 1; + } + + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 2; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR3)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "tria3", 5) == 0 || + strncmp(line, "tria6", 5) == 0) + { + if (strncmp(line, "tria3", 5) == 0) + { + vtkDebugMacro("tria3"); + cellType = vtkEnSightReader::TRIA3; + } + else + { + vtkDebugMacro("tria6"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TRIA6; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of triangle cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[3]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::TRIA3) + { + nodeIdList = new int[numElements * 3]; + this->ReadIntArray(nodeIdList, numElements*3); + } + else + { + nodeIdList = new int[numElements * 6]; + this->ReadIntArray(nodeIdList, numElements*6); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::TRIA3) + { + for (j = 0; j < 3; j++) + { + nodeIds[j] = nodeIdList[3*i+j] - 1; + } + } + else + { + for (j = 0; j < 3; j++) + { + nodeIds[j] = nodeIdList[6*i+j] - 1; + } + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 3; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_TRIANGLE, 3, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "quad4", 5) == 0 || + strncmp(line, "quad8", 5) == 0) + { + if (strncmp(line, "quad8", 5) == 0) + { + vtkDebugMacro("quad8"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::QUAD8; + } + else + { + vtkDebugMacro("quad4"); + cellType = vtkEnSightReader::QUAD4; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of quad cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[4]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::QUAD4) + { + nodeIdList = new int[numElements * 4]; + this->ReadIntArray(nodeIdList, numElements*4); + } + else + { + nodeIdList = new int[numElements * 8]; + this->ReadIntArray(nodeIdList, numElements*8); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::QUAD4) + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[4*i+j] - 1; + } + } + else + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[8*i+j] - 1; + } + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_QUAD, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "tetra4", 6) == 0 || + strncmp(line, "tetra10", 7) == 0) + { + if (strncmp(line, "tetra10", 7) == 0) + { + vtkDebugMacro("tetra10"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TETRA10; + } + else + { + vtkDebugMacro("tetra4"); + cellType = vtkEnSightReader::TETRA4; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of tetrahedral cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[4]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::TETRA4) + { + nodeIdList = new int[numElements * 4]; + this->ReadIntArray(nodeIdList, numElements*4); + } + else + { + nodeIdList = new int[numElements * 10]; + this->ReadIntArray(nodeIdList, numElements*10); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::TETRA4) + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[4*i+j] - 1; + } + } + else + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[10*i+j] - 1; + } + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 3; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_TETRA, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "pyramid5", 8) == 0 || + strncmp(line, "pyramid13", 9) == 0) + { + if (strncmp(line, "pyramid13", 9) == 0) + { + vtkDebugMacro("pyramid13"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PYRAMID13; + } + else + { + vtkDebugMacro("pyramid5"); + cellType = vtkEnSightReader::PYRAMID5; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pyramid cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[5]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::PYRAMID5) + { + nodeIdList = new int[numElements * 5]; + this->ReadIntArray(nodeIdList, numElements*5); + } + else + { + nodeIdList = new int[numElements * 13]; + this->ReadIntArray(nodeIdList, numElements*13); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::PYRAMID5) + { + for (j = 0; j < 5; j++) + { + nodeIds[j] = nodeIdList[5*i+j] - 1; + } + } + else + { + for (j = 0; j < 5; j++) + { + nodeIds[j] = nodeIdList[13*i+j] - 1; + } + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 5; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_PYRAMID, 5, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "hexa8", 5) == 0 || + strncmp(line, "hexa20", 6) == 0) + { + if (strncmp(line, "hexa20", 6) == 0) + { + vtkDebugMacro("hexa20"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::HEXA20; + } + else + { + vtkDebugMacro("hexa8"); + cellType = vtkEnSightReader::HEXA8; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of hexahedral cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[8]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::HEXA8) + { + nodeIdList = new int[numElements * 8]; + this->ReadIntArray(nodeIdList, numElements*8); + } + else + { + nodeIdList = new int[numElements * 20]; + this->ReadIntArray(nodeIdList, numElements*20); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::HEXA8) + { + for (j = 0; j < 8; j++) + { + nodeIds[j] = nodeIdList[8*i+j] - 1; + } + } + else + { + for (j = 0; j < 8; j++) + { + nodeIds[j] = nodeIdList[20*i+j] - 1; + } + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 8; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_HEXAHEDRON, 8, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "penta6", 6) == 0 || + strncmp(line, "penta15", 7) == 0) + { + if (strncmp(line, "penta15", 7) == 0) + { + vtkDebugMacro("penta15"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PENTA15; + } + else + { + vtkDebugMacro("penta6"); + cellType = vtkEnSightReader::PENTA6; + } + + this->ReadIntNumber(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pentagonal cells; check that ByteOrder is set correctly."); + return 0; + } + nodeIds = new vtkIdType[6]; + if (this->ElementIdsListed) + { + // skip element ids + this->IFile->seekg((sizeof(int)*numElements), ios::cur); + } + + if (cellType == vtkEnSightReader::PENTA6) + { + nodeIdList = new int[numElements * 6]; + this->ReadIntArray(nodeIdList, numElements*6); + } + else + { + nodeIdList = new int[numElements * 15]; + this->ReadIntArray(nodeIdList, numElements*15); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::PENTA6) + { + for (j = 0; j < 6; j++) + { + nodeIds[j] = nodeIdList[6*i+j] - 1; + } + } + else + { + for (j = 0; j < 6; j++) + { + nodeIds[j] = nodeIdList[15*i+j] - 1; + } + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 6; j++) + { + nodeIds[j] = this->UnstructuredNodeIds->GetValue(nodeIds[j]); + } + } + cellId = output->InsertNextCell(VTK_WEDGE, 6, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + delete [] nodeIds; + delete [] nodeIdList; + } + lineRead = this->ReadLine(line); + } + + ((vtkUnstructuredGrid*)this->GetOutput(partId))-> + SetPoints(this->UnstructuredPoints); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6BinaryReader::CreateStructuredGridOutput(int partId, + char line[80], + const char* name) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int i; + vtkPoints *points = vtkPoints::New(); + int numPts; + float *coordsRead; + int *iblanks; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new structured grid output"); + vtkStructuredGrid* sgrid = vtkStructuredGrid::New(); + this->SetNthOutput(partId, sgrid); + sgrid->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkStructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + points->Delete(); + return 0; + } + + vtkStructuredGrid* output = vtkStructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strcmp(subLine, "iblanked") == 0) + { + iblanked = 1; + } + } + // Read these separately to get the byte order correct. + this->ReadIntNumber(dimensions); + this->ReadIntNumber(dimensions+1); + this->ReadIntNumber(dimensions+2); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + numPts < 0 || numPts*(int)sizeof(int) > this->FileSize || + numPts > this->FileSize) + { + vtkErrorMacro("Invalid dimensions; check that ByteOrder is set correctly."); + points->Delete(); + return -1; + } + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + points->Allocate(numPts); + + coordsRead = new float[numPts*3]; + this->ReadFloatArray(coordsRead, numPts*3); + + for (i = 0; i < numPts; i++) + { + points->InsertNextPoint(coordsRead[i], coordsRead[numPts+i], + coordsRead[2*numPts+i]); + } + + delete [] coordsRead; + + output->SetPoints(points); + if (iblanked) + { + iblanks = new int[numPts]; + this->ReadIntArray(iblanks, numPts); + for (i = 0; i < numPts; i++) + { + if (!iblanks[i]) + { + output->BlankPoint(i); + } + } + delete [] iblanks; + } + + points->Delete(); + // reading next line to check for EOF + lineRead = this->ReadLine(line); + return lineRead; +} + +// Internal function to read in a line up to 80 characters. +// Returns zero if there was an error. +int vtkEnSight6BinaryReader::ReadLine(char result[80]) +{ + if ( ! this->IFile->read(result, sizeof(char)*80)) + { + return 0; + } + + return 1; +} + +// Internal function to read a single integer. +// Returns zero if there was an error. +// This method is used to read the number of points ... +// It also tries to determine the byte order. +// It uses the byte order that produces the largest value that +// is smaller than the file. Although this computation +// assumes only one int array is in the file, +// it should still work fine. +int vtkEnSight6BinaryReader::ReadIntNumber(int *result) +{ + if ( ! this->IFile->read((char*)result, sizeof(int))) + { + vtkErrorMacro("Read failed"); + return 0; + } + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LE(result); + vtkDebugMacro(<<"ByteOrder == FILE_LITTLE_ENDIAN"); + } + else if (this->ByteOrder == FILE_BIG_ENDIAN) + { + vtkByteSwap::Swap4BE(result); + vtkDebugMacro(<<"ByteOrder == FILE_BIG_ENDIAN"); + } + else + { + // Experimental byte swap. + int tmpLE = *result; + int tmpBE = *result; + vtkByteSwap::Swap4LE(&tmpLE); + vtkByteSwap::Swap4BE(&tmpBE); + + // Use negative value as an indication of bad number. + // Compare unmultiplied number to file size in case multiplying by + // sizeof(int) creates a number big enough that it does not fit in an int, + // and so becomes negative. + if ((tmpLE*(int)(sizeof(int))) > this->FileSize || tmpLE > this->FileSize) + { + tmpLE = -1; + } + if ((tmpBE*(int)(sizeof(int))) > this->FileSize || tmpBE > this->FileSize) + { + tmpBE = -1; + } + + // Just a sanity check. (0, 0 occurs often). + // This condition would only occur for some really large files. + if (tmpLE > 0 && tmpBE > 0) + { + vtkWarningMacro("Byte order is ambiguous."); + } + + // If they are both valid, use the larger one. + if (tmpLE > 0) + { + if (tmpBE > tmpLE) + { + this->ByteOrder = FILE_BIG_ENDIAN; + *result = tmpBE; + } + else + { + this->ByteOrder = FILE_LITTLE_ENDIAN; + *result = tmpLE; + } + return 1; + } + if (tmpBE > 0) + { + this->ByteOrder = FILE_BIG_ENDIAN; + *result = tmpBE; + return 1; + } + + if (tmpLE < 0 && tmpBE < 0) + { // both byte swaps are bad. + vtkErrorMacro("Could not find a suitable byte order."); + *result = 0; + return 0; + } + } + + return 1; +} + +// Internal function to read an integer array. +// Returns zero if there was an error. +int vtkEnSight6BinaryReader::ReadIntArray(int *result, + int numInts) +{ + if (numInts <= 0) + { + return 1; + } + + if ( ! this->IFile->read((char*)result, sizeof(int)*numInts)) + { + vtkErrorMacro("Read failed."); + return 0; + } + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(result, numInts); + } + else + { + vtkByteSwap::Swap4BERange(result, numInts); + } + + return 1; +} + +// Internal function to read a float array. +// Returns zero if there was an error. +int vtkEnSight6BinaryReader::ReadFloatArray(float *result, + int numFloats) +{ + if (numFloats <= 0) + { + return 1; + } + + if ( ! this->IFile->read((char*)result, sizeof(float)*numFloats)) + { + vtkErrorMacro("Read failed."); + return 0; + } + + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(result, numFloats); + } + else + { + vtkByteSwap::Swap4BERange(result, numFloats); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkEnSight6BinaryReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkEnSight6BinaryReader.h b/IO/vtkEnSight6BinaryReader.h new file mode 100644 index 0000000..5ddec60 --- /dev/null +++ b/IO/vtkEnSight6BinaryReader.h @@ -0,0 +1,165 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSight6BinaryReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEnSight6BinaryReader - class to read binary EnSight6 files +// .SECTION Description +// vtkEnSight6BinaryReader is a class to read binary EnSight6 files into vtk. +// Because the different parts of the EnSight data can be of various data +// types, this reader produces multiple outputs, one per part in the input +// file. +// All variable information is being stored in field data. The descriptions +// listed in the case file are used as the array names in the field data. +// For complex vector variables, the description is appended with _r (for the +// array of real values) and _i (for the array if imaginary values). Complex +// scalar variables are stored as a single array with 2 components, real and +// imaginary, listed in that order. +// .SECTION Caveats +// You must manually call Update on this reader and then connect the rest +// of the pipeline because (due to the nature of the file format) it is +// not possible to know ahead of time how many outputs you will have or +// what types they will be. +// This reader can only handle static EnSight datasets (both static geometry +// and variables). + +#ifndef __vtkEnSight6BinaryReader_h +#define __vtkEnSight6BinaryReader_h + +#include "vtkEnSightReader.h" + +class vtkIdTypeArray; +class vtkPoints; + +class VTK_IO_EXPORT vtkEnSight6BinaryReader : public vtkEnSightReader +{ +public: + static vtkEnSight6BinaryReader *New(); + vtkTypeRevisionMacro(vtkEnSight6BinaryReader, vtkEnSightReader); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkEnSight6BinaryReader(); + ~vtkEnSight6BinaryReader(); + + // Returns 1 if successful. Sets file size as a side action. + int OpenFile(const char* filename); + + // Description: + // Read the geometry file. If an error occurred, 0 is returned; otherwise 1. + virtual int ReadGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read the measured geometry file. If an error occurred, 0 is returned; + // otherwise 1. + virtual int ReadMeasuredGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read scalars per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one component in + // the scalars array, we assume that 0 is the first component added to the array. + virtual int ReadScalarsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0, + int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0); + + // Description: + // Read tensors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerNode(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read scalars per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one component in the + // scalars array, we assume that 0 is the first component added to the array. + virtual int ReadScalarsPerElement(const char* fileName, const char* description, + int timeStep, int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read tensors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read an unstructured part (partId) from the geometry file and create a + // vtkUnstructuredGrid output. Return 0 if EOF reached. + virtual int CreateUnstructuredGridOutput(int partId, + char line[256], + const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkStructuredGridOutput. Return 0 if EOF reached. + virtual int CreateStructuredGridOutput(int partId, + char line[256], + const char* name); + + // Description: + // Internal function to read in a line up to 80 characters. + // Returns zero if there was an error. + int ReadLine(char result[80]); + + // Description: + // Internal function to read in a single integer. + // Tries to determine the byte order of this file. + // Returns zero if there was an error. + int ReadIntNumber(int *result); + + // Description: + // Internal function to read in an integer array. + // Returns zero if there was an error. + int ReadIntArray(int *result, int numInts); + + // Description: + // Internal function to read in a float array. + // Returns zero if there was an error. + int ReadFloatArray(float *result, int numFloats); + + // Description: + // Read to the next time step in the geometry file. + int SkipTimeStep(); + int SkipStructuredGrid(char line[256]); + int SkipUnstructuredGrid(char line[256]); + + // global list of points for the unstructured parts of the model + int NumberOfUnstructuredPoints; + vtkPoints* UnstructuredPoints; + vtkIdTypeArray* UnstructuredNodeIds; // matching of node ids to point ids + + int ElementIdsListed; + + // The size of the file is used to choose byte order. + int FileSize; + + ifstream *IFile; +private: + vtkEnSight6BinaryReader(const vtkEnSight6BinaryReader&); // Not implemented. + void operator=(const vtkEnSight6BinaryReader&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkEnSight6Reader.cxx b/IO/vtkEnSight6Reader.cxx new file mode 100644 index 0000000..9a16e3b --- /dev/null +++ b/IO/vtkEnSight6Reader.cxx @@ -0,0 +1,2247 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSight6Reader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEnSight6Reader.h" + +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkIdTypeArray.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + + +#include +#include +#include + +vtkCxxRevisionMacro(vtkEnSight6Reader, "$Revision: 1.57 $"); +vtkStandardNewMacro(vtkEnSight6Reader); + +//---------------------------------------------------------------------------- +vtkEnSight6Reader::vtkEnSight6Reader() +{ + this->NumberOfUnstructuredPoints = 0; + this->UnstructuredPoints = vtkPoints::New(); + this->UnstructuredNodeIds = NULL; +} + +//---------------------------------------------------------------------------- +vtkEnSight6Reader::~vtkEnSight6Reader() +{ + if (this->UnstructuredNodeIds) + { + this->UnstructuredNodeIds->Delete(); + this->UnstructuredNodeIds = NULL; + } + this->UnstructuredPoints->Delete(); + this->UnstructuredPoints = NULL; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6ReaderRead1(const char *line, const char *, int *pointId, + float *point1, float *point2, float *point3) +{ + int numEntries; +#ifdef __CYGWIN__ + // most cygwins are busted in sscanf, this is a work around + numEntries = 0; + char *dup = strdup(line); + dup[8] = '\0'; + numEntries += sscanf(dup,"%8d",pointId); + dup[8] = line[8]; + dup[20] = '\0'; + numEntries += sscanf(dup+8,"%12e",point1); + dup[20] = line[20]; + dup[32] = '\0'; + numEntries += sscanf(dup+20,"%12e",point2); + dup[32] = line[32]; + numEntries += sscanf(dup+32,"%12e",point3); + free(dup); +#else + numEntries = sscanf(line, " %8d %12e %12e %12e", pointId, point1, point2, point3); +#endif + return numEntries; +} + +int vtkEnSight6ReaderRead2(const char *line, const char *, + float *point1, float *point2, float *point3) +{ + int numEntries; +#ifdef __CYGWIN__ + // most cygwins are busted in sscanf, this is a work around + numEntries = 0; + char *dup = strdup(line); + dup[12] = '\0'; + numEntries += sscanf(dup,"%12e",point1); + dup[12] = line[12]; + dup[24] = '\0'; + numEntries += sscanf(dup+12,"%12e",point2); + dup[24] = line[24]; + numEntries += sscanf(dup+24,"%12e",point3); + free(dup); +#else + numEntries = sscanf(line, " %12e %12e %12e", point1, point2, point3); +#endif + return numEntries; +} + +int vtkEnSight6ReaderRead3(const char *line, const char *, + float *point1, float *point2, float *point3, + float *point4, float *point5, float *point6) +{ + int numEntries; +#ifdef __CYGWIN__ + // most cygwins are busted in sscanf, this is a work around + numEntries = 0; + char *dup = strdup(line); + dup[12] = '\0'; + numEntries += sscanf(dup,"%12e",point1); + dup[12] = line[12]; + dup[24] = '\0'; + numEntries += sscanf(dup+12,"%12e",point2); + dup[24] = line[24]; + dup[36] = '\0'; + numEntries += sscanf(dup+24,"%12e",point3); + dup[36] = line[36]; + dup[48] = '\0'; + numEntries += sscanf(dup+36,"%12e",point4); + dup[48] = line[48]; + dup[60] = '\0'; + numEntries += sscanf(dup+48,"%12e",point5); + dup[60] = line[60]; + numEntries += sscanf(dup+60,"%12e",point6); + free(dup); +#else + numEntries = sscanf(line, " %12e %12e %12e %12e %12e %12e", + point1, point2, point3, point4, point5, point6); +#endif + return numEntries; +} + +int vtkEnSight6ReaderRead4(const char *line, float *point1) +{ + int numEntries; +#ifdef __CYGWIN__ + // most cygwins are busted in sscanf, this is a work around + numEntries = 0; + char *dup = strdup(line); + dup[12] = '\0'; + numEntries += sscanf(dup,"%12e",point1); + free(dup); +#else + numEntries = sscanf(line,"%12e",point1); +#endif + return numEntries; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadGeometryFile(const char* fileName, int timeStep) +{ + char line[256], subLine[256]; + int partId; + int lineRead; + int pointId; + float point[3]; + int i, j; + int pointIdsListed; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A GeometryFileName must be specified in the case file."); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to geometry file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + this->ReadLine(line); + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strcmp(subLine, "Binary") == 0) + { + vtkErrorMacro("This is a binary data set. Try " + << "vtkEnSight6BinaryReader."); + return 0; + } + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); + } + + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadNextDataLine(line); + } + this->ReadLine(line); + } + + // Skip description line. Using ReadLine instead of + // ReadNextDataLine because the description line could be blank. + this->ReadLine(line); + + // Read the node id and element id lines. + this->ReadLine(line); + sscanf(line, " %*s %*s %s", subLine); + if (strcmp(subLine, "given") == 0) + { + this->UnstructuredNodeIds = vtkIdTypeArray::New(); + pointIdsListed = 1; + } + else if (strcmp(subLine, "ignore") == 0) + { + pointIdsListed = 1; + } + else + { + pointIdsListed = 0; + } + + this->ReadNextDataLine(line); + + this->ReadNextDataLine(line); // "coordinates" + this->ReadNextDataLine(line); + this->NumberOfUnstructuredPoints = atoi(line); + this->UnstructuredPoints->Allocate(this->NumberOfUnstructuredPoints); + int *tmpIds = new int[this->NumberOfUnstructuredPoints]; + + int maxId = 0; + int entries; + for (j = 0; j < this->NumberOfUnstructuredPoints; j++) + { + this->ReadNextDataLine(line); + if (pointIdsListed) + { + // point ids listed + entries = vtkEnSight6ReaderRead1(line, " %8d %12e %12e %12e", + &pointId, &point[0], + &point[1], &point[2]); + assert( entries == 4 ); + if (this->UnstructuredNodeIds) + { + tmpIds[j] = pointId; + if (pointId > maxId) + { + maxId = pointId; + } + } + this->UnstructuredPoints->InsertNextPoint(point); + } + else + { + entries = vtkEnSight6ReaderRead2(line, "%12e%12e%12e", + &point[0], &point[1], &point[2]); + assert( entries == 3 ); + this->UnstructuredPoints->InsertNextPoint(point); + } + } + + if (this->UnstructuredNodeIds) + { + this->UnstructuredNodeIds->SetNumberOfComponents(1); + this->UnstructuredNodeIds->SetNumberOfTuples(maxId); + this->UnstructuredNodeIds->FillComponent(0, -1); + + for (j = 0; j < this->NumberOfUnstructuredPoints; j++) + { + this->UnstructuredNodeIds->InsertValue(tmpIds[j]-1, j); + } + } + delete [] tmpIds; + + lineRead = this->ReadNextDataLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->NumberOfGeometryParts++; + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing at 1. + int realId = this->InsertNewPartId(partId); + + this->ReadLine(line); // part description line + char *name = strdup(line); + this->ReadNextDataLine(line); + + if (strncmp(line, "block", 5) == 0) + { + lineRead = this->CreateStructuredGridOutput(realId, line, name); + } + else + { + lineRead = this->CreateUnstructuredGridOutput(realId, line, name); + } + free(name); + } + + delete this->IS; + this->IS = NULL; + if (this->UnstructuredNodeIds) + { + this->UnstructuredNodeIds->Delete(); + this->UnstructuredNodeIds = NULL; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadMeasuredGeometryFile(const char* fileName, int timeStep) +{ + char line[256], subLine[256]; + vtkPoints *newPoints; + int i; + vtkIdType id; + int tempId; + float coords[3]; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A MeasuredFileName must be specified in the case file."); + return 0; + } + + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to measured geometry file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + + this->ReadLine(line); + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strcmp(subLine, "Binary") == 0) + { + vtkErrorMacro("This is a binary data set. Try " + << "vtkEnSight6BinaryReader."); + return 0; + } + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); + } + + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); + } + + this->ReadLine(line); // "particle coordinates" + this->ReadLine(line); + this->NumberOfMeasuredPoints = atoi(line); + + this->NumberOfNewOutputs++; + + if (this->GetOutput(this->NumberOfGeometryParts) == NULL) + { + vtkDebugMacro("creating new measured geometry output"); + vtkPolyData* pd = vtkPolyData::New(); + this->SetNthOutput(this->NumberOfGeometryParts, pd); + pd->Delete(); + } + else if ( ! this->GetOutput(this->NumberOfGeometryParts)->IsA("vtkPolyData")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkPolyData *pd = vtkPolyData::SafeDownCast( + this->GetOutput( this->NumberOfGeometryParts) ); + pd->Allocate(this->NumberOfMeasuredPoints); + + newPoints = vtkPoints::New(); + newPoints->Allocate(this->NumberOfMeasuredPoints); + + for (i = 0; i < this->NumberOfMeasuredPoints; i++) + { + this->ReadLine(line); +#ifdef NDEBUG + vtkEnSight6ReaderRead1(line, " %8d %12e %12e %12e", + &tempId, &coords[0], + &coords[1], &coords[2]); +#else + int entries = vtkEnSight6ReaderRead1(line, " %8d %12e %12e %12e", + &tempId, &coords[0], + &coords[1], &coords[2]); + assert( entries == 4 ); +#endif + id = tempId; + newPoints->InsertNextPoint(coords); + pd->InsertNextCell(VTK_VERTEX, 1, &id); + } + + pd->SetPoints( newPoints ); + + newPoints->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadScalarsPerNode(const char* fileName, + const char* description, + int timeStep, int measured, + int numberOfComponents, + int component) +{ + char line[256]; + char tempLine[256]; + int partId, numPts, i, j; + vtkFloatArray *scalars; + int numLines, moreScalars; + float scalarsRead[6]; + vtkDataSet *output; + int entries; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalar per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + this->ReadNextDataLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + int allocatedScalars = 0; + // There are 6 values per line, and one scalar per point. + if (!measured) + { + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + } + else + { + numPts = this->GetOutput(this->NumberOfGeometryParts)-> + GetNumberOfPoints(); + } + numLines = numPts / 6; + moreScalars = numPts % 6; + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numPts); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numPts * numberOfComponents); + allocatedScalars = 1; + } + else + { + // It does not matter which unstructured part we get the point data from + // because it is the same for all of them. + partId = this->UnstructuredPartIds->GetId(0); + scalars = static_cast(this->GetOutput(partId)-> + GetPointData()->GetArray(description)); + } + for (i = 0; i < numLines; i++) + { + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", + &scalarsRead[0], &scalarsRead[1], + &scalarsRead[2], &scalarsRead[3], + &scalarsRead[4], &scalarsRead[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + } + this->ReadNextDataLine(line); + } + strcpy(tempLine, ""); + for (j = 0; j < moreScalars; j++) + { + entries = vtkEnSight6ReaderRead4(line+j*12,&scalarsRead[j]); + assert( entries == 1 ); + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + } + if (moreScalars != 0) + { + this->ReadLine(line); + } + if (!measured) + { + for (i = 0; i < this->UnstructuredPartIds->GetNumberOfIds(); i++) + { + partId = this->UnstructuredPartIds->GetId(i); + output = this->GetOutput(partId); + if (component == 0) + { + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + } + else + { + output->GetPointData()->AddArray(scalars); + } + } + } + else + { + scalars->SetName(description); + output = this->GetOutput(this->NumberOfGeometryParts); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + } + if(allocatedScalars) + { + scalars->Delete(); + } + } + + // scalars for structured parts + while (strncmp(line, "part", 4) == 0) + { + int allocatedScalars = 0; + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing at 1. + int realId = this->InsertNewPartId(partId); + + output = this->GetOutput(realId); + this->ReadNextDataLine(line); // block + numPts = output->GetNumberOfPoints(); + numLines = numPts / 6; + moreScalars = numPts % 6; + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numPts); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numPts * numberOfComponents); + allocatedScalars = 1; + } + else + { + scalars = (vtkFloatArray*)(output->GetPointData()-> + GetArray(description)); + } + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &scalarsRead[0], + &scalarsRead[1], &scalarsRead[2], &scalarsRead[3], + &scalarsRead[4], &scalarsRead[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + } + } + this->ReadNextDataLine(line); + strcpy(tempLine, ""); + for (j = 0; j < moreScalars; j++) + { + entries = vtkEnSight6ReaderRead4(line+j*12,&scalarsRead[j]); + assert( entries == 1 ); + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + } + if (component == 0) + { + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + } + else + { + output->GetPointData()->AddArray(scalars); + } + this->ReadNextDataLine(line); + if(allocatedScalars) + { + scalars->Delete(); + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadVectorsPerNode(const char* fileName, + const char* description, + int timeStep, int measured) +{ + char line[256]; + char tempLine[256]; + int partId, numPts, i, j, k; + vtkFloatArray *vectors; + int numLines, moreVectors; + float vector1[3], vector2[3], values[6]; + vtkDataSet *output; + int entries; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + this->ReadNextDataLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + // There are 6 values per line, and 3 values (or 1 vector) per point. + if (!measured) + { + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + } + else + { + numPts = this->GetOutput(this->NumberOfGeometryParts)-> + GetNumberOfPoints(); + } + numLines = numPts / 2; + moreVectors = ((numPts * 3) % 6) / 3; + vectors = vtkFloatArray::New(); + vectors->SetNumberOfTuples(numPts); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numPts*3); + for (i = 0; i < numLines; i++) + { + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", + &vector1[0], &vector1[1], + &vector1[2], &vector2[0], + &vector2[1], &vector2[2]); + assert( entries == 6 ); + vectors->InsertTuple(i*2, vector1); + vectors->InsertTuple(i*2 + 1, vector2); + this->ReadNextDataLine(line); + } + strcpy(tempLine, ""); + for (j = 0; j < moreVectors; j++) + { + entries = vtkEnSight6ReaderRead4(line+j*36,&vector1[0]); + assert( entries == 1 ); + entries = vtkEnSight6ReaderRead4(line+j*36+12,&vector1[1]); + assert( entries == 1 ); + entries = vtkEnSight6ReaderRead4(line+j*36+24,&vector1[2]); + assert( entries == 1 ); + vectors->InsertTuple(i*2 + j, vector1); + } + if (moreVectors != 0) + { + this->ReadLine(line); + } + if (!measured) + { + for (i = 0; i < this->UnstructuredPartIds->GetNumberOfIds(); i++) + { + partId = this->UnstructuredPartIds->GetId(i); + vectors->SetName(description); + output = this->GetOutput(partId); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + } + } + else + { + vectors->SetName(description); + output = this->GetOutput(this->NumberOfGeometryParts); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + } + vectors->Delete(); + } + + // vectors for structured parts + while (strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; + int realId = this->InsertNewPartId(partId); + + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + numLines = numPts / 6; + moreVectors = numPts % 6; + vectors = vtkFloatArray::New(); + vectors->SetNumberOfTuples(numPts); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numPts*3); + + for (k = 0; k < 3; k++) + { + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &values[0], &values[1], + &values[2], &values[3], &values[4], &values[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + vectors->InsertComponent(i*6 + j, k, values[j]); + } + } + + if (moreVectors) + { + this->ReadNextDataLine(line); + strcpy(tempLine, ""); + for (j = 0; j < moreVectors; j++) + { + entries = vtkEnSight6ReaderRead4(line+j*12,&values[j]); + assert( entries == 1 ); + vectors->InsertComponent(i*6 + j, k, values[j]); + } + } + } + vectors->SetName(description); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + vectors->Delete(); + + this->ReadNextDataLine(line); + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadTensorsPerNode(const char* fileName, + const char* description, + int timeStep) +{ + char line[256]; + char tempLine[256]; + int partId, numPts, i, j, k; + vtkFloatArray *tensors; + int numLines, moreTensors; + float tensor[6], values[6]; + int lineRead; + vtkDataSet *output; + int entries; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorSymmPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor symm per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + lineRead = this->ReadNextDataLine(line); // 1st data line or part # + if (strncmp(line, "part", 4) != 0) + { + // There are 6 values per line, and 6 values (or 1 tensor) per point. + numPts = this->UnstructuredPoints->GetNumberOfPoints(); + numLines = numPts; + tensors = vtkFloatArray::New(); + tensors->SetNumberOfTuples(numPts); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numPts*6); + for (i = 0; i < numLines; i++) + { + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &tensor[0], &tensor[1], + &tensor[2], &tensor[3], &tensor[4], &tensor[5]); + assert( entries == 6 ); + tensors->InsertTuple(i, tensor); + lineRead = this->ReadNextDataLine(line); + } + + for (i = 0; i < this->UnstructuredPartIds->GetNumberOfIds(); i++) + { + partId = this->UnstructuredPartIds->GetId(i); + tensors->SetName(description); + this->GetOutput(partId)->GetPointData()->AddArray(tensors); + } + tensors->Delete(); + } + + // vectors for structured parts + while (lineRead && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; + int realId = this->InsertNewPartId(partId); + this->ReadNextDataLine(line); // block + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + numLines = numPts / 6; + moreTensors = numPts % 6; + tensors = vtkFloatArray::New(); + tensors->SetNumberOfTuples(numPts); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numPts*6); + + for (k = 0; k < 6; k++) + { + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &values[0], &values[1], + &values[2], &values[3], &values[4], &values[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + tensors->InsertComponent(i*6 + j, k, values[j]); + } + } + + if (moreTensors) + { + this->ReadNextDataLine(line); + strcpy(tempLine, ""); + for (j = 0; j < moreTensors; j++) + { + entries = vtkEnSight6ReaderRead4(line+j*12,&values[j]); + assert( entries == 1 ); + tensors->InsertComponent(i*6 + j, k, values[j]); + } + } + } + tensors->SetName(description); + output->GetPointData()->AddArray(tensors); + tensors->Delete(); + lineRead = this->ReadNextDataLine(line); + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadScalarsPerElement(const char* fileName, + const char* description, + int timeStep, + int numberOfComponents, + int component) +{ + char line[256]; + int partId, numCells, numCellsPerElement, i, j, idx; + vtkFloatArray *scalars; + int lineRead, elementType; + float scalarsRead[6]; + int numLines, moreScalars; + vtkDataSet *output; + int entries; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalars per element file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadNextDataLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + int realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + this->ReadNextDataLine(line); // element type or "block" + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numCells); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numCells * numberOfComponents); + } + else + { + scalars = (vtkFloatArray*)(output->GetCellData()->GetArray(description)); + } + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") == 0) + { + numLines = numCells / 6; + moreScalars = numCells % 6; + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &scalarsRead[0], + &scalarsRead[1], &scalarsRead[2], &scalarsRead[3], + &scalarsRead[4], &scalarsRead[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + } + } + lineRead = this->ReadNextDataLine(line); + + if (moreScalars) + { + for (j = 0; j < moreScalars; j++) + { + entries = vtkEnSight6ReaderRead4(line+j*12,&scalarsRead[j]); + assert( entries == 1 ); + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + } + } + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + delete this->IS; + this->IS = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(partId); + numCellsPerElement = this->GetCellIds(idx, elementType)->GetNumberOfIds(); + numLines = numCellsPerElement / 6; + moreScalars = numCellsPerElement % 6; + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &scalarsRead[0], + &scalarsRead[1], &scalarsRead[2], &scalarsRead[3], + &scalarsRead[4], &scalarsRead[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + scalars->InsertComponent(this->GetCellIds(idx, elementType)-> + GetId(i*6 + j), component, + scalarsRead[j]); + } + } + if (moreScalars) + { + this->ReadNextDataLine(line); + for (j = 0; j < moreScalars; j++) + { + vtkEnSight6ReaderRead4(line+j*12,&scalarsRead[j]); + scalars->InsertComponent(this->GetCellIds(idx, elementType)-> + GetId(i*6 + j), component, + scalarsRead[j]); + } + } + lineRead = this->ReadNextDataLine(line); + } // end while + } // end else + if (component == 0) + { + scalars->SetName(description); + output->GetCellData()->AddArray(scalars); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(scalars); + } + scalars->Delete(); + } + else + { + output->GetCellData()->AddArray(scalars); + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadVectorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[256]; + int partId, numCells, numCellsPerElement, i, j, k, idx; + vtkFloatArray *vectors; + int lineRead, elementType; + float values[6], vector1[3], vector2[3]; + int numLines, moreVectors; + vtkDataSet *output; + int entries; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per element file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadNextDataLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + vectors = vtkFloatArray::New(); + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + int realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + this->ReadNextDataLine(line); // element type or "block" + vectors->SetNumberOfTuples(numCells); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numCells*3); + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") == 0) + { + numLines = numCells / 6; + moreVectors = numCells % 6; + + for (k = 0; k < 3; k++) + { + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &values[0], + &values[1], &values[2], &values[3], &values[4], &values[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + vectors->InsertComponent(i*6 + j, k, values[j]); + } + } + if (moreVectors) + { + this->ReadNextDataLine(line); + for (j = 0; j < moreVectors; j++) + { + vtkEnSight6ReaderRead4(line+j*12,&values[j]); + vectors->InsertComponent(i*6 + j, k, values[j]); + } + } + } + lineRead = this->ReadNextDataLine(line); + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + delete this->IS; + this->IS = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(partId); + numCellsPerElement = this->GetCellIds(idx, elementType)->GetNumberOfIds(); + numLines = numCellsPerElement / 2; + moreVectors = ((numCellsPerElement*3) % 6) / 3; + + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &vector1[0], + &vector1[1], &vector1[2], &vector2[0], &vector2[1], + &vector2[2]); + assert( entries == 6 ); + vectors->InsertTuple(this->GetCellIds(idx, elementType)->GetId(2*i), + vector1); + vectors->InsertTuple(this->GetCellIds(idx, elementType)->GetId(2*i + 1), + vector2); + } + if (moreVectors) + { + this->ReadNextDataLine(line); + for (j = 0; j < moreVectors; j++) + { + vtkEnSight6ReaderRead4(line+j*36,&vector1[0]); + vtkEnSight6ReaderRead4(line+j*36+12,&vector1[1]); + vtkEnSight6ReaderRead4(line+j*36+24,&vector1[2]); + vectors->InsertTuple(this->GetCellIds(idx, elementType)-> + GetId(2*i + j), vector1); + } + } + lineRead = this->ReadNextDataLine(line); + } // end while + } // end else + vectors->SetName(description); + output->GetCellData()->AddArray(vectors); + if (!output->GetCellData()->GetVectors()) + { + output->GetCellData()->SetVectors(vectors); + } + vectors->Delete(); + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::ReadTensorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[256]; + int partId, numCells, numCellsPerElement, i, j, k, idx; + vtkFloatArray *tensors; + int lineRead, elementType; + float values[6], tensor[6]; + int numLines, moreTensors; + vtkDataSet *output; + int entries; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor per element file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadNextDataLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + tensors = vtkFloatArray::New(); + sscanf(line, " part %d", &partId); + partId--; // EnSight starts #ing with 1. + int realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + this->ReadNextDataLine(line); // element type or "block" + tensors->SetNumberOfTuples(numCells); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numCells*6); + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strcmp(line, "block") == 0) + { + numLines = numCells / 6; + moreTensors = numCells % 6; + + for (k = 0; k < 6; k++) + { + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &values[0], + &values[1], &values[2], &values[3], &values[4], &values[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + tensors->InsertComponent(i*6 + j, k, values[j]); + } + } + if (moreTensors) + { + this->ReadNextDataLine(line); + for (j = 0; j < moreTensors; j++) + { + vtkEnSight6ReaderRead4(line+j*12,&values[j]); + tensors->InsertComponent(i*6 + j, k, values[j]); + } + } + } + lineRead = this->ReadNextDataLine(line); + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0) + { + elementType = this->GetElementType(line); + if (elementType < 0) + { + vtkErrorMacro("invalid element type"); + delete this->IS; + this->IS = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(partId); + numCellsPerElement = this->GetCellIds(idx, elementType)->GetNumberOfIds(); + numLines = numCellsPerElement; + + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &tensor[0], + &tensor[1], &tensor[2], &tensor[3], &tensor[4], &tensor[5]); + assert( entries == 6 ); + tensors->InsertTuple(this->GetCellIds(idx, elementType)->GetId(i), + tensor); + } + lineRead = this->ReadNextDataLine(line); + } // end while + } // end else + tensors->SetName(description); + output->GetCellData()->AddArray(tensors); + tensors->Delete(); + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::CreateUnstructuredGridOutput(int partId, + char line[256], + const char* name) +{ + int lineRead = 1; + char subLine[256]; + int i, j; + vtkIdType *nodeIds; + int *intIds; + int numElements; + int idx, cellId, cellType, testId; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new unstructured output"); + vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New(); + this->SetNthOutput(partId, ugrid); + ugrid->Delete(); + + this->UnstructuredPartIds->InsertNextId(partId); + } + else if ( ! this->GetOutput(partId)->IsA("vtkUnstructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + // Clear all cell ids from the last execution, if any. + idx = this->UnstructuredPartIds->IsId(partId); + for (i = 0; i < 16; i++) + { + this->GetCellIds(idx, i)->Reset(); + } + + output->Allocate(1000); + + while(lineRead && strncmp(line, "part", 4) != 0) + { + if (strncmp(line, "point", 5) == 0) + { + vtkDebugMacro("point"); + + nodeIds = new vtkIdType[1]; + this->ReadNextDataLine(line); + numElements = atoi(line); + + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (sscanf(line, " %*s %s", subLine) == 1) + { + // element ids listed + // EnSight ids start at 1 + if (this->UnstructuredNodeIds) + { + nodeIds[0] = + this->UnstructuredNodeIds->GetValue(atoi(subLine) - 1); + } + else + { + nodeIds[0] = atoi(subLine) - 1; + } + } + else + { + if (this->UnstructuredNodeIds) + { + nodeIds[0] = this->UnstructuredNodeIds->GetValue(atoi(line) - 1); + } + else + { + nodeIds[0] = atoi(line) - 1; + } + } + cellId = output->InsertNextCell(VTK_VERTEX, 1, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::POINT)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + } + else if (strncmp(line, "bar2", 4) == 0) + { + vtkDebugMacro("bar2"); + + nodeIds = new vtkIdType[2]; + intIds = new int[2]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (sscanf(line, " %*d %d %d", &intIds[0], &intIds[1]) != 2) + { + sscanf(line, " %d %d", &intIds[0], &intIds[1]); + } + for (j = 0; j < 2; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 2; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 2; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR2)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "bar3", 4) == 0) + { + vtkDebugMacro("bar3"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + nodeIds = new vtkIdType[2]; + intIds = new int[2]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (sscanf(line, " %*d %d %*d %d", &intIds[0], &intIds[1]) != 2) + { + sscanf(line, " %d %*d %d", &intIds[0], &intIds[1]); + } + for (j = 0; j < 2; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 2; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 2; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR3)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "tria3", 5) == 0 || + strncmp(line, "tria6", 5) == 0) + { + if (strncmp(line, "tria6", 5) == 0) + { + vtkDebugMacro("tria6"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TRIA6; + } + else + { + vtkDebugMacro("tria3"); + cellType = vtkEnSightReader::TRIA3; + } + + nodeIds = new vtkIdType[3]; + intIds = new int[3]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (!(sscanf(line, " %*d %d %d %d", &intIds[0], &intIds[1], + &intIds[2]) == 3 && + cellType == vtkEnSightReader::TRIA3) && + !(sscanf(line, " %*d %d %d %d %*d %*d %d", &intIds[0], &intIds[1], + &intIds[2], &testId) == 4 && + cellType == vtkEnSightReader::TRIA6)) + { + sscanf(line, " %d %d %d", &intIds[0], &intIds[1], &intIds[2]); + } + for (j = 0; j < 3; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 3; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 3; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_TRIANGLE, 3, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "quad4", 5) == 0 || + strncmp(line, "quad8", 5) == 0) + { + if (strncmp(line, "quad8", 5) == 0) + { + vtkDebugMacro("quad8"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::QUAD8; + } + else + { + vtkDebugMacro("quad4"); + cellType = vtkEnSightReader::QUAD4; + } + + nodeIds = new vtkIdType[4]; + intIds = new int[4]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (!(sscanf(line, " %*d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3]) == 4 && + cellType == vtkEnSightReader::QUAD4) && + !(sscanf(line, " %*d %d %d %d %d %*d %*d %*d %d", &intIds[0], + &intIds[1], &intIds[2], &intIds[3], &testId) == 5 && + cellType == vtkEnSightReader::QUAD8)) + { + sscanf(line, " %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3]); + } + for (j = 0; j < 4; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 4; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 4; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_QUAD, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "tetra4", 6) == 0 || + strncmp(line, "tetra10", 7) == 0) + { + if (strncmp(line, "tetra10", 7) == 0) + { + vtkDebugMacro("tetra10"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TETRA10; + } + else + { + vtkDebugMacro("tetra4"); + cellType = vtkEnSightReader::TETRA4; + } + + nodeIds = new vtkIdType[4]; + intIds = new int[4]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (!(sscanf(line, " %*d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3]) == 4 && + cellType == vtkEnSightReader::TETRA4) && + !(sscanf(line, " %*d %d %d %d %d %*d %*d %*d %*d %*d %d", + &intIds[0], &intIds[1], &intIds[2], &intIds[3], + &testId) == 5 && + cellType == vtkEnSightReader::TETRA10)) + { + sscanf(line, " %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3]); + } + for (j = 0; j < 4; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 4; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 4; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_TETRA, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "pyramid5", 8) == 0 || + strncmp(line, "pyramid13", 9) == 0) + { + if (strncmp(line, "pyramid13", 9) == 0) + { + vtkDebugMacro("pyramid13"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PYRAMID13; + } + else + { + vtkDebugMacro("pyramid5"); + cellType = vtkEnSightReader::PYRAMID5; + } + + nodeIds = new vtkIdType[5]; + intIds = new int[5]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (!(sscanf(line, " %*d %d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3], &intIds[4]) == 5 && + cellType == vtkEnSightReader::PYRAMID5) && + !(sscanf(line, " %*d %d %d %d %d %d %*d %*d %*d %*d %*d %*d %*d %d", + &intIds[0], &intIds[1], &intIds[2], &intIds[3], + &intIds[4], &testId) == 6 && + cellType == vtkEnSightReader::PYRAMID13)) + { + sscanf(line, " %d %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3], &intIds[4]); + } + for (j = 0; j < 5; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 5; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 5; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_PYRAMID, 5, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "hexa8", 5) == 0 || + strncmp(line, "hexa20", 6) == 0) + { + if (strncmp(line, "hexa20", 6) == 0) + { + vtkDebugMacro("hexa20"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::HEXA20; + } + else + { + vtkDebugMacro("hexa8"); + cellType = vtkEnSightReader::HEXA8; + } + + nodeIds = new vtkIdType[8]; + intIds = new int[8]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (!(sscanf(line, " %*d %d %d %d %d %d %d %d %d", &intIds[0], + &intIds[1], &intIds[2], &intIds[3], &intIds[4], + &intIds[5], &intIds[6], &intIds[7]) == 8 && + cellType == vtkEnSightReader::HEXA8) && + !(sscanf(line, " %*d %d %d %d %d %d %d %d %d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d", + &intIds[0], &intIds[1], &intIds[2], &intIds[3], + &intIds[4], &intIds[5], &intIds[6], &intIds[7], + &testId) == 9 && + cellType == vtkEnSightReader::HEXA20)) + { + sscanf(line, " %d %d %d %d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3], &intIds[4], &intIds[5], + &intIds[6], &intIds[7]); + } + for (j = 0; j < 8; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 8; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 8; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_HEXAHEDRON, 8, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "penta6", 6) == 0 || + strncmp(line, "penta15", 7) == 0) + { + if (strncmp(line, "penta15", 7) == 0) + { + vtkDebugMacro("penta15"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PENTA15; + } + else + { + vtkDebugMacro("penta6"); + cellType = vtkEnSightReader::PENTA6; + } + + nodeIds = new vtkIdType[6]; + intIds = new int[6]; + this->ReadNextDataLine(line); + numElements = atoi(line); + lineRead = this->ReadNextDataLine(line); + + for (i = 0; i < numElements; i++) + { + if (!(sscanf(line, " %*d %d %d %d %d %d %d", &intIds[0], + &intIds[1], &intIds[2], &intIds[3], &intIds[4], + &intIds[5]) == 6 && + cellType == vtkEnSightReader::PENTA6) && + !(sscanf(line, " %*d %d %d %d %d %d %d %*d %*d %*d %*d %*d %*d %*d %*d %d", + &intIds[0], &intIds[1], &intIds[2], &intIds[3], + &intIds[4], &intIds[5], &testId) == 7 && + cellType == vtkEnSightReader::PENTA15)) + { + sscanf(line, " %d %d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3], &intIds[4], &intIds[5]); + } + for (j = 0; j < 6; j++) + { + intIds[j]--; + } + if (this->UnstructuredNodeIds) + { + for (j = 0; j < 6; j++) + { + intIds[j] = this->UnstructuredNodeIds->GetValue(intIds[j]); + } + } + for (j = 0; j < 6; j++) + { + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_WEDGE, 6, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "END TIME STEP", 13) == 0) + { + break; + } + } + + output->SetPoints(this->UnstructuredPoints); + + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSight6Reader::CreateStructuredGridOutput(int partId, + char line[256], + const char* name) +{ + char subLine[256]; + char formatLine[256], tempLine[256]; + int lineRead = 1; + int iblanked = 0; + int dimensions[3]; + int i, j; + vtkPoints *points = vtkPoints::New(); + double point[3]; + int numPts, numLines, moreCoords, moreBlanking; + float coords[6]; + int iblanks[10]; + int entries; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new structured grid output"); + vtkStructuredGrid* sgrid = vtkStructuredGrid::New(); + this->SetNthOutput(partId, sgrid); + sgrid->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkStructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkStructuredGrid* output = vtkStructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strcmp(subLine, "iblanked") == 0) + { + iblanked = 1; + } + } + + this->ReadNextDataLine(line); + sscanf(line, " %d %d %d", &dimensions[0], &dimensions[1], &dimensions[2]); + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + points->Allocate(numPts); + + numLines = numPts / 6; // integer division + moreCoords = numPts % 6; + + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &coords[0], &coords[1], + &coords[2], &coords[3], &coords[4], &coords[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + points->InsertNextPoint(coords[j], 0.0, 0.0); + } + } + if (moreCoords != 0) + { + this->ReadNextDataLine(line); + for (j = 0; j < moreCoords; j++) + { + vtkEnSight6ReaderRead4(line+j*12,&coords[j]); + points->InsertNextPoint(coords[j], 0.0, 0.0); + } + } + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &coords[0], &coords[1], + &coords[2], &coords[3], &coords[4], &coords[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + points->GetPoint(i*6+j, point); + points->SetPoint(i*6+j, point[0], + static_cast(coords[j]), point[2]); + } + } + if (moreCoords != 0) + { + this->ReadNextDataLine(line); + for (j = 0; j < moreCoords; j++) + { + vtkEnSight6ReaderRead4(line+j*12,&coords[j]); + points->GetPoint(i*6+j, point); + points->SetPoint(i*6+j, point[0], + static_cast(coords[j]), point[2]); + } + } + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + entries = vtkEnSight6ReaderRead3(line, " %12e %12e %12e %12e %12e %12e", &coords[0], &coords[1], + &coords[2], &coords[3], &coords[4], &coords[5]); + assert( entries == 6 ); + for (j = 0; j < 6; j++) + { + points->GetPoint(i*6+j, point); + points->SetPoint(i*6+j, point[0], point[1], + static_cast(coords[j])); + } + } + if (moreCoords != 0) + { + this->ReadNextDataLine(line); + for (j = 0; j < moreCoords; j++) + { + vtkEnSight6ReaderRead4(line+j*12,&coords[j]); + points->GetPoint(i*6+j, point); + points->SetPoint(i*6+j, point[0], point[1], + static_cast(coords[j])); + } + } + + numLines = numPts / 10; + moreBlanking = numPts % 10; + output->SetPoints(points); + if (iblanked) + { + for (i = 0; i < numLines; i++) + { + this->ReadNextDataLine(line); + sscanf(line, " %d %d %d %d %d %d %d %d %d %d", &iblanks[0], &iblanks[1], + &iblanks[2], &iblanks[3], &iblanks[4], &iblanks[5], &iblanks[6], + &iblanks[7], &iblanks[8], &iblanks[9]); + for (j = 0; j < 10; j++) + { + if (!iblanks[j]) + { + output->BlankPoint(i*numLines+j); + } + } + } + if (moreBlanking != 0) + { + this->ReadNextDataLine(line); + strcpy(formatLine, ""); + strcpy(tempLine, ""); + for (j = 0; j < moreBlanking; j++) + { + strcat(formatLine, " %d"); + sscanf(line, formatLine, &iblanks[j]); + if (!iblanks[j]) + { + output->BlankPoint(i*numLines+j); + } + strcat(tempLine, " %*d"); + strcpy(formatLine, tempLine); + } + } + } + + points->Delete(); + // reading next line to check for EOF + lineRead = this->ReadNextDataLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +void vtkEnSight6Reader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkEnSight6Reader.h b/IO/vtkEnSight6Reader.h new file mode 100644 index 0000000..5ddecc2 --- /dev/null +++ b/IO/vtkEnSight6Reader.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSight6Reader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEnSight6Reader - class to read EnSight6 files +// .SECTION Description +// vtkEnSight6Reader is a class to read EnSight6 files into vtk. +// Because the different parts of the EnSight data can be of various data +// types, this reader produces multiple outputs, one per part in the input +// file. +// All variable information is being stored in field data. The descriptions +// listed in the case file are used as the array names in the field data. +// For complex vector variables, the description is appended with _r (for the +// array of real values) and _i (for the array if imaginary values). Complex +// scalar variables are stored as a single array with 2 components, real and +// imaginary, listed in that order. +// .SECTION Caveats +// You must manually call Update on this reader and then connect the rest +// of the pipeline because (due to the nature of the file format) it is +// not possible to know ahead of time how many outputs you will have or +// what types they will be. +// This reader can only handle static EnSight datasets (both static geometry +// and variables). + +#ifndef __vtkEnSight6Reader_h +#define __vtkEnSight6Reader_h + +#include "vtkEnSightReader.h" + +class vtkIdTypeArray; +class vtkPoints; + +class VTK_IO_EXPORT vtkEnSight6Reader : public vtkEnSightReader +{ +public: + static vtkEnSight6Reader *New(); + vtkTypeRevisionMacro(vtkEnSight6Reader, vtkEnSightReader); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkEnSight6Reader(); + ~vtkEnSight6Reader(); + + // Description: + // Read the geometry file. If an error occurred, 0 is returned; otherwise 1. + virtual int ReadGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read the measured geometry file. If an error occurred, 0 is returned; + // otherwise 1. + virtual int ReadMeasuredGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read scalars per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one component in + // the scalars array, we assume that 0 is the first component added to the array. + virtual int ReadScalarsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0, + int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0); + + // Description: + // Read tensors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerNode(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read scalars per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one component in the + // scalars array, we assume that 0 is the first component added to the array. + virtual int ReadScalarsPerElement(const char* fileName, const char* description, + int timeStep, int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read tensors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read an unstructured part (partId) from the geometry file and create a + // vtkUnstructuredGrid output. Return 0 if EOF reached. + virtual int CreateUnstructuredGridOutput(int partId, + char line[256], + const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkStructuredGridOutput. Return 0 if EOF reached. + virtual int CreateStructuredGridOutput(int partId, + char line[256], + const char* name); + + // global list of points for the unstructured parts of the model + int NumberOfUnstructuredPoints; + vtkPoints* UnstructuredPoints; + vtkIdTypeArray* UnstructuredNodeIds; // matching of node ids to point ids +private: + vtkEnSight6Reader(const vtkEnSight6Reader&); // Not implemented. + void operator=(const vtkEnSight6Reader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkEnSightGoldBinaryReader.cxx b/IO/vtkEnSightGoldBinaryReader.cxx new file mode 100644 index 0000000..a0f17d4 --- /dev/null +++ b/IO/vtkEnSightGoldBinaryReader.cxx @@ -0,0 +1,3405 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightGoldBinaryReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEnSightGoldBinaryReader.h" + +#include "vtkByteSwap.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkEnSightGoldBinaryReader, "$Revision: 1.61 $"); +vtkStandardNewMacro(vtkEnSightGoldBinaryReader); + +// This is half the precision of an int. +#define MAXIMUM_PART_ID 65536 + +//---------------------------------------------------------------------------- +vtkEnSightGoldBinaryReader::vtkEnSightGoldBinaryReader() +{ + this->IFile = NULL; + this->FileSize = 0; +} + +//---------------------------------------------------------------------------- +vtkEnSightGoldBinaryReader::~vtkEnSightGoldBinaryReader() +{ + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::OpenFile(const char* filename) +{ + if (!filename) + { + vtkErrorMacro(<<"Missing filename."); + return 0; + } + + // Close file from any previous image + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + + // Open the new file + vtkDebugMacro(<< "Opening file " << filename); + struct stat fs; + if ( !stat( filename, &fs) ) + { + // Find out how big the file is. + this->FileSize = (int)(fs.st_size); + +#ifdef _WIN32 + this->IFile = new ifstream(filename, ios::in | ios::binary); +#else + this->IFile = new ifstream(filename, ios::in); +#endif + } + else + { + vtkErrorMacro("stat failed."); + return 0; + } + if (! this->IFile || this->IFile->fail()) + { + vtkErrorMacro(<< "Could not open file " << filename); + return 0; + } + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadGeometryFile(const char* fileName, int timeStep) +{ + char line[80], subLine[80]; + int partId, realId; + int lineRead, i; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A GeometryFileName must be specified in the case file."); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to geometry file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + this->ReadLine(line); + sscanf(line, " %*s %s", subLine); + if (strncmp(subLine, "Binary", 6) != 0 && + strncmp(subLine, "binary", 6) != 0) + { + vtkErrorMacro("This is not a binary data set. Try " + << "vtkEnSightGoldReader."); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + if (!this->SkipTimeStep()) + { + return 0; + } + } + + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + // Skip the 2 description lines. + this->ReadLine(line); + this->ReadLine(line); + + // Read the node id and element id lines. + this->ReadLine(line); + sscanf(line, " %*s %*s %s", subLine); + if (strncmp(subLine, "given", 5) == 0) + { + this->NodeIdsListed = 1; + } + else if (strncmp(subLine, "ignore", 6) == 0) + { + this->NodeIdsListed = 1; + } + else + { + this->NodeIdsListed = 0; + } + + this->ReadLine(line); + sscanf(line, " %*s %*s %s", subLine); + if (strncmp(subLine, "given", 5) == 0) + { + this->ElementIdsListed = 1; + } + else if (strncmp(subLine, "ignore", 6) == 0) + { + this->ElementIdsListed = 1; + } + else + { + this->ElementIdsListed = 0; + } + + lineRead = this->ReadLine(line); // "extents" or "part" + if (strncmp(line, "extents", 7) == 0) + { + // Skipping the extents. + this->IFile->seekg(6*sizeof(float), ios::cur); + lineRead = this->ReadLine(line); // "part" + } + + while (lineRead > 0 && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing at 1. + if (partId < 0 || partId >= MAXIMUM_PART_ID) + { + vtkErrorMacro("Invalid part id; check that ByteOrder is set correctly."); + return 0; + } + realId = this->InsertNewPartId(partId); + + this->ReadLine(line); // part description line + char *name = strdup(line); + if (strncmp(line, "interface", 9) == 0) + { + return 1; // ignore it and move on + } + this->ReadLine(line); + + if (strncmp(line, "block", 5) == 0) + { + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strncmp(subLine, "rectilinear", 11) == 0) + { + // block rectilinear + lineRead = this->CreateRectilinearGridOutput(realId, line, name); + } + else if (strncmp(subLine, "uniform", 7) == 0) + { + // block uniform + lineRead = this->CreateImageDataOutput(realId, line, name); + } + else + { + // block iblanked + lineRead = this->CreateStructuredGridOutput(realId, line, name); + } + } + else + { + // block + lineRead = this->CreateStructuredGridOutput(realId, line, name); + } + } + else + { + lineRead = this->CreateUnstructuredGridOutput(realId, line, name); + if (lineRead < 0) + { + free(name); + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 0; + } + } + free(name); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + if (lineRead < 0) + { + return 0; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::SkipTimeStep() +{ + char line[80], subLine[80]; + int lineRead; + + line[0] = '\0'; + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + + // Skip the 2 description lines. + this->ReadLine(line); + this->ReadLine(line); + + // Read the node id and element id lines. + this->ReadLine(line); + sscanf(line, " %*s %*s %s", subLine); + if (strncmp(subLine, "given", 5) == 0 || + strncmp(subLine, "ignore", 6) == 0) + { + this->NodeIdsListed = 1; + } + else + { + this->NodeIdsListed = 0; + } + + this->ReadLine(line); + sscanf(line, " %*s %*s %s", subLine); + if (strncmp(subLine, "given", 5) == 0) + { + this->ElementIdsListed = 1; + } + else if (strncmp(subLine, "ignore", 6) == 0) + { + this->ElementIdsListed = 1; + } + else + { + this->ElementIdsListed = 0; + } + + lineRead = this->ReadLine(line); // "extents" or "part" + if (strncmp(line, "extents", 7) == 0) + { + // Skipping the extents. + this->IFile->seekg(6*sizeof(float), ios::cur); + lineRead = this->ReadLine(line); // "part" + } + + while (lineRead > 0 && strncmp(line, "part", 4) == 0) + { + int tmpInt; + this->ReadPartId(&tmpInt); + if (tmpInt < 0 || tmpInt > MAXIMUM_PART_ID) + { + vtkErrorMacro("Invalid part id; check that ByteOrder is set correctly."); + return 0; + } + this->ReadLine(line); // part description line + this->ReadLine(line); + + if (strncmp(line, "block", 5) == 0) + { + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strncmp(subLine, "rectilinear", 11) == 0) + { + // block rectilinear + lineRead = this->SkipRectilinearGrid(line); + } + else if (strncmp(subLine, "uniform,", 7) == 0) + { + // block uniform + lineRead = this->SkipImageData(line); + } + else + { + // block iblanked + lineRead = this->SkipStructuredGrid(line); + } + } + else + { + // block + lineRead = this->SkipStructuredGrid(line); + } + } + else + { + lineRead = this->SkipUnstructuredGrid(line); + } + } + + if (lineRead < 0) + { + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::SkipStructuredGrid(char line[256]) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int numPts; + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked", 8) == 0) + { + iblanked = 1; + } + } + + this->ReadIntArray(dimensions, 3); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + numPts < 0 || numPts*(int)sizeof(int) > this->FileSize || + numPts > this->FileSize) + { + vtkErrorMacro("Invalid dimensions read; check that ByteOrder is set correctly."); + return -1; + } + + // Skip xCoords, yCoords and zCoords. + this->IFile->seekg(sizeof(float)*numPts*3, ios::cur); + + if (iblanked) + { // skip iblank array. + this->IFile->seekg(numPts*sizeof(int), ios::cur); + } + + // reading next line to check for EOF + lineRead = this->ReadLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::SkipUnstructuredGrid(char line[256]) +{ + int lineRead = 1; + int i; + int numElements; + int cellType; + + while(lineRead && strncmp(line, "part", 4) != 0) + { + if (strncmp(line, "coordinates", 11) == 0) + { + vtkDebugMacro("coordinates"); + int numPts; + + this->ReadInt(&numPts); + if (numPts < 0 || numPts*(int)sizeof(int) > this->FileSize || + numPts > this->FileSize) + { + vtkErrorMacro("Invalid number of points; check that ByteOrder is set correctly."); + return -1; + } + + vtkDebugMacro("num. points: " << numPts); + + if (this->NodeIdsListed) + { // skip node ids. + this->IFile->seekg(sizeof(int)*numPts, ios::cur); + } + + // Skip xCoords, yCoords and zCoords. + this->IFile->seekg(sizeof(float)*3*numPts, ios::cur); + } + else if (strncmp(line, "point", 5) == 0) + { + vtkDebugMacro("point"); + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of point cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { // skip element ids. + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + else if (strncmp(line, "bar2", 4) == 0) + { + vtkDebugMacro("bar2"); + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar2 cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*2*numElements, ios::cur); + } + else if (strncmp(line, "bar3", 4) == 0) + { + vtkDebugMacro("bar3"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar3 cells; check that ByteOrder is set correctly."); + return -1; + } + + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*2*numElements, ios::cur); + } + else if (strncmp(line, "nsided", 6) == 0) + { + vtkDebugMacro("nsided"); + int *numNodesPerElement; + int numNodes = 0; + + //cellType = vtkEnSightReader::NSIDED; + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of nsided cells; check that ByteOrder is set correctly."); + return -1; + } + + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + numNodesPerElement = new int[numElements]; + this->ReadIntArray(numNodesPerElement, numElements); + for (i = 0; i < numElements; i++) + { + numNodes += numNodesPerElement[i]; + } + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*numNodes, ios::cur); + delete [] numNodesPerElement; + } + else if (strncmp(line, "tria3", 5) == 0 || + strncmp(line, "tria6", 5) == 0) + { + if (strncmp(line, "tria6", 5) == 0) + { + vtkDebugMacro("tria6"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TRIA6; + } + else + { + vtkDebugMacro("tria3"); + cellType = vtkEnSightReader::TRIA3; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of triangle cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::TRIA6) + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*6*numElements, ios::cur); + } + else + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*3*numElements, ios::cur); + } + } + else if (strncmp(line, "quad4", 5) == 0 || + strncmp(line, "quad8", 5) == 0) + { + if (strncmp(line, "quad8", 5) == 0) + { + vtkDebugMacro("quad8"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::QUAD8; + } + else + { + vtkDebugMacro("quad4"); + cellType = vtkEnSightReader::QUAD4; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of quad cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::QUAD8) + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*8*numElements, ios::cur); + } + else + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*4*numElements, ios::cur); + } + } + else if (strncmp(line, "tetra4", 6) == 0 || + strncmp(line, "tetra10", 7) == 0) + { + if (strncmp(line, "tetra10", 7) == 0) + { + vtkDebugMacro("tetra10"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TETRA10; + } + else + { + vtkDebugMacro("tetra4"); + cellType = vtkEnSightReader::TETRA4; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of tetrahedral cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::TETRA10) + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*10*numElements, ios::cur); + } + else + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*4*numElements, ios::cur); + } + } + else if (strncmp(line, "pyramid5", 8) == 0 || + strncmp(line, "pyramid13", 9) == 0) + { + if (strncmp(line, "pyramid13", 9) == 0) + { + vtkDebugMacro("pyramid13"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PYRAMID13; + } + else + { + vtkDebugMacro("pyramid5"); + cellType = vtkEnSightReader::PYRAMID5; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pyramid cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::PYRAMID13) + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*13*numElements, ios::cur); + } + else + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*5*numElements, ios::cur); + } + } + else if (strncmp(line, "hexa8", 5) == 0 || + strncmp(line, "hexa20", 6) == 0) + { + if (strncmp(line, "hexa20", 6) == 0) + { + vtkDebugMacro("hexa20"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::HEXA20; + } + else + { + vtkDebugMacro("hexa8"); + cellType = vtkEnSightReader::HEXA8; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of hexahedral cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::HEXA20) + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*20*numElements, ios::cur); + } + else + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*8*numElements, ios::cur); + } + } + else if (strncmp(line, "penta6", 6) == 0 || + strncmp(line, "penta15", 7) == 0) + { + if (strncmp(line, "penta15", 7) == 0) + { + vtkDebugMacro("penta15"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PENTA15; + } + else + { + vtkDebugMacro("penta6"); + cellType = vtkEnSightReader::PENTA6; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pentagonal cells; check that ByteOrder is set correctly."); + return -1; + } + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::PENTA15) + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*15*numElements, ios::cur); + } + else + { + // Skip nodeIdList. + this->IFile->seekg(sizeof(int)*6*numElements, ios::cur); + } + } + else if (strncmp(line, "END TIME STEP", 13) == 0) + { + return 1; + } + else + { + vtkErrorMacro("undefined geometry file line"); + return -1; + } + lineRead = this->ReadLine(line); + } + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::SkipRectilinearGrid(char line[256]) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int numPts; + + if (sscanf(line, " %*s %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked", 8) == 0) + { + iblanked = 1; + } + } + + this->ReadIntArray(dimensions, 3); + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + (dimensions[0]+dimensions[1]+dimensions[2]) < 0 || + (dimensions[0]+dimensions[1]+dimensions[2])*(int)sizeof(int) > this->FileSize || + (dimensions[0]+dimensions[1]+dimensions[2]) > this->FileSize) + { + vtkErrorMacro("Invalid dimensions read; check that BytetOrder is set correctly."); + return -1; + } + + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + + // Skip xCoords + this->IFile->seekg(sizeof(float)*dimensions[0], ios::cur); + // Skip yCoords + this->IFile->seekg(sizeof(float)*dimensions[1], ios::cur); + // Skip zCoords + this->IFile->seekg(sizeof(float)*dimensions[2], ios::cur); + + if (iblanked) + { + vtkWarningMacro("VTK does not handle blanking for rectilinear grids."); + this->IFile->seekg(sizeof(int)*numPts, ios::cur); + } + + // reading next line to check for EOF + lineRead = this->ReadLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::SkipImageData(char line[256]) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + float origin[3], delta[3]; + int numPts; + + if (sscanf(line, " %*s %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked", 8) == 0) + { + iblanked = 1; + } + } + + this->ReadIntArray(dimensions, 3); + this->ReadFloatArray(origin, 3); + this->ReadFloatArray(delta, 3); + + if (iblanked) + { + vtkWarningMacro("VTK does not handle blanking for image data."); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + numPts < 0 || numPts*(int)sizeof(int) > this->FileSize || + numPts > this->FileSize) + { + return -1; + } + this->IFile->seekg(sizeof(int)*numPts, ios::cur); + } + + // reading next line to check for EOF + lineRead = this->ReadLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadMeasuredGeometryFile(const char* fileName, + int timeStep) +{ + char line[80], subLine[80]; + int i; + int *pointIds; + float *xCoords, *yCoords, *zCoords; + vtkPoints *points = vtkPoints::New(); + vtkPolyData *pd = vtkPolyData::New(); + + this->NumberOfNewOutputs++; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A MeasuredFileName must be specified in the case file."); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to measured geometry file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->GetOutput(this->NumberOfGeometryParts) && + ! this->GetOutput(this->NumberOfGeometryParts)->IsA("vtkPolyData")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + this->ReadLine(line); + sscanf(line, " %*s %s", subLine); + if (strncmp(subLine, "Binary", 6) != 0) + { + vtkErrorMacro("This is not a binary data set. Try " + << "vtkEnSightGoldReader."); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + // Skip the description line. + this->ReadLine(line); + + this->ReadLine(line); // "particle coordinates" + + this->ReadInt(&this->NumberOfMeasuredPoints); + + // Skip pointIds + //this->IFile->ignore(sizeof(int)*this->NumberOfMeasuredPoints); + // Skip xCoords + //this->IFile->ignore(sizeof(float)*this->NumberOfMeasuredPoints); + // Skip yCoords + //this->IFile->ignore(sizeof(float)*this->NumberOfMeasuredPoints); + // Skip zCoords + //this->IFile->ignore(sizeof(float)*this->NumberOfMeasuredPoints); + this->IFile->seekg( + (sizeof(float)*3 + sizeof(int))*this->NumberOfMeasuredPoints, + ios::cur); + this->ReadLine(line); // END TIME STEP + } + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + // Skip the description line. + this->ReadLine(line); + + this->ReadLine(line); // "particle coordinates" + + this->ReadInt(&this->NumberOfMeasuredPoints); + + pointIds = new int[this->NumberOfMeasuredPoints]; + xCoords = new float [this->NumberOfMeasuredPoints]; + yCoords = new float [this->NumberOfMeasuredPoints]; + zCoords = new float [this->NumberOfMeasuredPoints]; + points->Allocate(this->NumberOfMeasuredPoints); + pd->Allocate(this->NumberOfMeasuredPoints); + + this->ReadIntArray(pointIds, this->NumberOfMeasuredPoints); + this->ReadFloatArray(xCoords, this->NumberOfMeasuredPoints); + this->ReadFloatArray(yCoords, this->NumberOfMeasuredPoints); + this->ReadFloatArray(zCoords, this->NumberOfMeasuredPoints); + + for (i = 0; i < this->NumberOfMeasuredPoints; i++) + { + points->InsertNextPoint(xCoords[i], yCoords[i], zCoords[i]); + pd->InsertNextCell(VTK_VERTEX, 1, (vtkIdType*)&pointIds[i]); + } + + pd->SetPoints(points); + this->SetNthOutput(this->NumberOfGeometryParts, pd); + + points->Delete(); + pd->Delete(); + delete [] pointIds; + delete [] xCoords; + delete [] yCoords; + delete [] zCoords; + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadScalarsPerNode(const char* fileName, + const char* description, + int timeStep, + int measured, + int numberOfComponents, + int component) +{ + char line[80]; + int partId, realId, numPts, i, lineRead; + vtkFloatArray *scalars; + float* scalarsRead; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalar per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + + if (measured) + { + output = this->GetOutput(this->NumberOfGeometryParts); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); + // Skip sclalars + this->IFile->seekg(sizeof(float)*numPts, ios::cur); + } + } + + while (this->ReadLine(line) && + strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); // "coordinates" or "block" + // Skip sclalars + this->IFile->seekg(sizeof(float)*numPts, ios::cur); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + if (measured) + { + output = this->GetOutput(this->NumberOfGeometryParts); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); + scalars = vtkFloatArray::New(); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->SetNumberOfTuples(numPts); + scalarsRead = new float [numPts]; + this->ReadFloatArray(scalarsRead, numPts); + // Why are we setting only one component here? + // Only one component is set because scalars are single-component arrays. + // For complex scalars, there is a file for the real part and another + // file for the imaginary part, but we are storing them as a 2-component + // array. + for (i = 0; i < numPts; i++) + { + scalars->SetComponent(i, component, scalarsRead[i]); + } + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + scalars->Delete(); + delete [] scalarsRead; + } + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; + } + + lineRead = this->ReadLine(line); + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + // If the part has no points, then only the part number is listed in + // the variable file. + if (numPts) + { + this->ReadLine(line); // "coordinates" or "block" + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->SetNumberOfTuples(numPts); + } + else + { + scalars = (vtkFloatArray*)(output->GetPointData()-> + GetArray(description)); + } + + scalarsRead = new float[numPts]; + this->ReadFloatArray(scalarsRead, numPts); + + for (i = 0; i < numPts; i++) + { + scalars->SetComponent(i, component, scalarsRead[i]); + } + if (component == 0) + { + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + scalars->Delete(); + } + else + { + output->GetPointData()->AddArray(scalars); + } + delete [] scalarsRead; + } + + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + continue; + } + lineRead = this->ReadLine(line); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadVectorsPerNode(const char* fileName, + const char* description, + int timeStep, + int measured) +{ + char line[80]; + int partId, realId, numPts, i, lineRead; + vtkFloatArray *vectors; + float tuple[3]; + float *comp1, *comp2, *comp3; + float *vectorsRead; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + + if (measured) + { + output = this->GetOutput(this->NumberOfGeometryParts); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); + // Skip vectors. + this->IFile->seekg(sizeof(float)*3*numPts, ios::cur); + } + } + + while (this->ReadLine(line) && + strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); // "coordinates" or "block" + // Skip comp1, comp2 and comp3 + this->IFile->seekg(sizeof(float)*3*numPts, ios::cur); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + + if (measured) + { + output = this->GetOutput(this->NumberOfGeometryParts); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); + vectors = vtkFloatArray::New(); + vectors->SetNumberOfComponents(3); + vectors->SetNumberOfTuples(numPts); + vectorsRead = vectors->GetPointer(0); + this->ReadFloatArray(vectorsRead, numPts*3); + vectors->SetName(description); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + vectors->Delete(); + } + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; + } + + lineRead = this->ReadLine(line); + while (lineRead && strncmp(line, "part", 4) == 0) + { + vectors = vtkFloatArray::New(); + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); // "coordinates" or "block" + vectors->SetNumberOfComponents(3); + vectors->SetNumberOfTuples(numPts); + comp1 = new float[numPts]; + comp2 = new float[numPts]; + comp3 = new float[numPts]; + this->ReadFloatArray(comp1, numPts); + this->ReadFloatArray(comp2, numPts); + this->ReadFloatArray(comp3, numPts); + for (i = 0; i < numPts; i++) + { + tuple[0] = comp1[i]; + tuple[1] = comp2[i]; + tuple[2] = comp3[i]; + vectors->SetTuple(i, tuple); + } + vectors->SetName(description); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + vectors->Delete(); + delete [] comp1; + delete [] comp2; + delete [] comp3; + } + + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + continue; + } + lineRead = this->ReadLine(line); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadTensorsPerNode(const char* fileName, + const char* description, + int timeStep) +{ + char line[80]; + int partId, realId, numPts, i, lineRead; + vtkFloatArray *tensors; + float *comp1, *comp2, *comp3, *comp4, *comp5, *comp6; + float tuple[6]; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + + while (this->ReadLine(line) && + strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadLine(line); // "coordinates" or "block" + // Skip over comp1, comp2, ... comp6 + this->IFile->seekg(sizeof(float)*6*numPts, ios::cur); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + tensors = vtkFloatArray::New(); + this->ReadLine(line); // "coordinates" or "block" + tensors->SetNumberOfComponents(6); + tensors->SetNumberOfTuples(numPts); + comp1 = new float[numPts]; + comp2 = new float[numPts]; + comp3 = new float[numPts]; + comp4 = new float[numPts]; + comp5 = new float[numPts]; + comp6 = new float[numPts]; + this->ReadFloatArray(comp1, numPts); + this->ReadFloatArray(comp2, numPts); + this->ReadFloatArray(comp3, numPts); + this->ReadFloatArray(comp4, numPts); + this->ReadFloatArray(comp5, numPts); + this->ReadFloatArray(comp6, numPts); + for (i = 0; i < numPts; i++) + { + tuple[0] = comp1[i]; + tuple[1] = comp2[i]; + tuple[2] = comp3[i]; + tuple[3] = comp4[i]; + tuple[4] = comp5[i]; + tuple[5] = comp6[i]; + tensors->InsertTuple(i, tuple); + } + tensors->SetName(description); + output->GetPointData()->AddArray(tensors); + tensors->Delete(); + delete [] comp1; + delete [] comp2; + delete [] comp3; + delete [] comp4; + delete [] comp5; + delete [] comp6; + } + + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + continue; + } + lineRead = this->ReadLine(line); + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadScalarsPerElement(const char* fileName, + const char* description, + int timeStep, + int numberOfComponents, + int component) +{ + char line[80]; + int partId, realId, numCells, numCellsPerElement, i, idx; + vtkFloatArray *scalars; + float *scalarsRead; + int lineRead, elementType; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalar per element file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + this->ReadLine(line); // element type or "block" + + // need to find out from CellIds how many cells we have of this + // element type (and what their ids are) -- IF THIS IS NOT A BLOCK + // SECTION + if (strncmp(line, "block", 5) == 0) + { + // Skip over float scalars. + this->IFile->seekg(sizeof(float)*numCells, ios::cur); + lineRead = this->ReadLine(line); + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)-> + GetNumberOfIds(); + this->IFile->seekg(sizeof(float)*numCellsPerElement, ios::cur); + lineRead = this->ReadLine(line); + } + } // end while + } // end if (numCells) + else + { + lineRead = this->ReadLine(line); + } + } // end while + } // end for + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + this->ReadLine(line); // element type or "block" + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->SetNumberOfTuples(numCells); + } + else + { + scalars = (vtkFloatArray*)(output->GetCellData()->GetArray(description)); + } + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strncmp(line, "block", 5) == 0) + { + scalarsRead = new float[numCells]; + this->ReadFloatArray(scalarsRead, numCells); + for (i = 0; i < numCells; i++) + { + scalars->SetComponent(i, component, scalarsRead[i]); + } + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + delete [] scalarsRead; + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + if (component == 0) + { + scalars->Delete(); + } + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = + this->GetCellIds(idx, elementType)->GetNumberOfIds(); + scalarsRead = new float[numCellsPerElement]; + this->ReadFloatArray(scalarsRead, numCellsPerElement); + for (i = 0; i < numCellsPerElement; i++) + { + scalars->SetComponent(this->GetCellIds(idx, elementType)->GetId(i), + component, scalarsRead[i]); + } + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + delete [] scalarsRead; + } // end while + } // end else + if (component == 0) + { + scalars->SetName(description); + output->GetCellData()->AddArray(scalars); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(scalars); + } + scalars->Delete(); + } + else + { + output->GetCellData()->AddArray(scalars); + } + } + else + { + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + } + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadVectorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[80]; + int partId, realId, numCells, numCellsPerElement, i, idx; + vtkFloatArray *vectors; + float *comp1, *comp2, *comp3; + int lineRead, elementType; + float tuple[3]; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per element file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + this->ReadLine(line); // element type or "block" + + // need to find out from CellIds how many cells we have of this + // element type (and what their ids are) -- IF THIS IS NOT A BLOCK + // SECTION + if (strncmp(line, "block", 5) == 0) + { + // Skip over comp1, comp2 and comp3 + this->IFile->seekg(sizeof(float)*3*numCells, ios::cur); + lineRead = this->ReadLine(line); + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + delete this->IS; + this->IS = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)-> + GetNumberOfIds(); + // Skip over comp1, comp2 and comp3 + this->IFile->seekg(sizeof(float)*3*numCellsPerElement, ios::cur); + lineRead = this->ReadLine(line); + } // end while + } // end else + } + else + { + lineRead = this->ReadLine(line); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + vectors = vtkFloatArray::New(); + this->ReadLine(line); // element type or "block" + vectors->SetNumberOfComponents(3); + vectors->SetNumberOfTuples(numCells); + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strncmp(line, "block", 5) == 0) + { + comp1 = new float[numCells]; + comp2 = new float[numCells]; + comp3 = new float[numCells]; + this->ReadFloatArray(comp1, numCells); + this->ReadFloatArray(comp2, numCells); + this->ReadFloatArray(comp3, numCells); + for (i = 0; i < numCells; i++) + { + tuple[0] = comp1[i]; + tuple[1] = comp2[i]; + tuple[2] = comp3[i]; + vectors->SetTuple(i, tuple); + } + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + delete [] comp1; + delete [] comp2; + delete [] comp3; + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + delete this->IS; + this->IS = NULL; + vectors->Delete(); + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = + this->GetCellIds(idx, elementType)->GetNumberOfIds(); + comp1 = new float[numCellsPerElement]; + comp2 = new float[numCellsPerElement]; + comp3 = new float[numCellsPerElement]; + this->ReadFloatArray(comp1, numCellsPerElement); + this->ReadFloatArray(comp2, numCellsPerElement); + this->ReadFloatArray(comp3, numCellsPerElement); + for (i = 0; i < numCellsPerElement; i++) + { + tuple[0] = comp1[i]; + tuple[1] = comp2[i]; + tuple[2] = comp3[i]; + vectors->SetTuple(this->GetCellIds(idx, elementType)->GetId(i), + tuple); + } + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + delete [] comp1; + delete [] comp2; + delete [] comp3; + } // end while + } // end else + vectors->SetName(description); + output->GetCellData()->AddArray(vectors); + if (!output->GetCellData()->GetVectors()) + { + output->GetCellData()->SetVectors(vectors); + } + vectors->Delete(); + } + else + { + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + } + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::ReadTensorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[80]; + int partId, realId, numCells, numCellsPerElement, i, idx; + vtkFloatArray *tensors; + int lineRead, elementType; + float *comp1, *comp2, *comp3, *comp4, *comp5, *comp6; + float tuple[6]; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor per element file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + if (this->OpenFile(sfilename.c_str()) == 0) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + this->ReadLine(line); // element type or "block" + + // need to find out from CellIds how many cells we have of this + // element type (and what their ids are) -- IF THIS IS NOT A BLOCK + // SECTION + if (strncmp(line, "block", 5) == 0) + { + // Skip comp1 - comp6 + this->IFile->seekg(sizeof(float)*6*numCells, ios::cur); + lineRead = this->ReadLine(line); + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + delete this->IS; + this->IS = NULL; + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = this->GetCellIds(idx, elementType)-> + GetNumberOfIds(); + // Skip over comp1->comp6 + this->IFile->seekg(sizeof(float)*6*numCellsPerElement, ios::cur); + lineRead = this->ReadLine(line); + } // end while + } // end else + } // end if (numCells) + else + { + lineRead = this->ReadLine(line); + } + } + } + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); // skip the description line + lineRead = this->ReadLine(line); // "part" + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->ReadPartId(&partId); + partId--; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + tensors = vtkFloatArray::New(); + this->ReadLine(line); // element type or "block" + tensors->SetNumberOfComponents(6); + tensors->SetNumberOfTuples(numCells); + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strncmp(line, "block", 5) == 0) + { + comp1 = new float[numCells]; + comp2 = new float[numCells]; + comp3 = new float[numCells]; + comp4 = new float[numCells]; + comp5 = new float[numCells]; + comp6 = new float[numCells]; + this->ReadFloatArray(comp1, numCells); + this->ReadFloatArray(comp2, numCells); + this->ReadFloatArray(comp3, numCells); + this->ReadFloatArray(comp4, numCells); + this->ReadFloatArray(comp5, numCells); + this->ReadFloatArray(comp6, numCells); + for (i = 0; i < numCells; i++) + { + tuple[0] = comp1[i]; + tuple[1] = comp2[i]; + tuple[2] = comp3[i]; + tuple[3] = comp4[i]; + tuple[4] = comp5[i]; + tuple[5] = comp6[i]; + tensors->InsertTuple(i, tuple); + } + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + delete [] comp1; + delete [] comp2; + delete [] comp3; + delete [] comp4; + delete [] comp5; + delete [] comp6; + } + else + { + while (lineRead && strncmp(line, "part", 4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + delete this->IS; + this->IS = NULL; + tensors->Delete(); + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = + this->GetCellIds(idx, elementType)->GetNumberOfIds(); + comp1 = new float[numCellsPerElement]; + comp2 = new float[numCellsPerElement]; + comp3 = new float[numCellsPerElement]; + comp4 = new float[numCellsPerElement]; + comp5 = new float[numCellsPerElement]; + comp6 = new float[numCellsPerElement]; + this->ReadFloatArray(comp1, numCellsPerElement); + this->ReadFloatArray(comp2, numCellsPerElement); + this->ReadFloatArray(comp3, numCellsPerElement); + this->ReadFloatArray(comp4, numCellsPerElement); + this->ReadFloatArray(comp5, numCellsPerElement); + this->ReadFloatArray(comp6, numCellsPerElement); + for (i = 0; i < numCellsPerElement; i++) + { + tuple[0] = comp1[i]; + tuple[1] = comp2[i]; + tuple[2] = comp3[i]; + tuple[3] = comp4[i]; + tuple[4] = comp5[i]; + tuple[5] = comp6[i]; + tensors->InsertTuple(this->GetCellIds(idx, elementType)->GetId(i), + tuple); + } + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + delete [] comp1; + delete [] comp2; + delete [] comp3; + delete [] comp4; + delete [] comp5; + delete [] comp6; + } // end while + } // end else + tensors->SetName(description); + output->GetCellData()->AddArray(tensors); + tensors->Delete(); + } + else + { + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + } + } + + if (this->IFile) + { + this->IFile->close(); + delete this->IFile; + this->IFile = NULL; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::CreateUnstructuredGridOutput(int partId, + char line[80], + const char* name) +{ + int lineRead = 1; + int i, j; + vtkIdType *nodeIds; + int *nodeIdList; + int numElements; + int idx, cellId, cellType; + float *xCoords, *yCoords, *zCoords; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new unstructured output"); + vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New(); + this->SetNthOutput(partId, ugrid); + ugrid->Delete(); + + this->UnstructuredPartIds->InsertNextId(partId); + } + else if ( ! this->GetOutput(partId)->IsA("vtkUnstructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + // Clear all cell ids from the last execution, if any. + idx = this->UnstructuredPartIds->IsId(partId); + for (i = 0; i < 16; i++) + { + this->GetCellIds(idx, i)->Reset(); + } + + output->Allocate(1000); + + while(lineRead && strncmp(line, "part", 4) != 0) + { + if (strncmp(line, "coordinates", 11) == 0) + { + vtkDebugMacro("coordinates"); + int numPts; + + this->ReadInt(&numPts); + if (numPts < 0 || numPts > this->FileSize || numPts * (int)sizeof(int) > this->FileSize) + { + vtkErrorMacro("Invalid number of unstructured points read; check that ByteOrder is set correctly."); + return -1; + } + + vtkPoints *points = vtkPoints::New(); + vtkDebugMacro("num. points: " << numPts); + + points->Allocate(numPts); + + if (this->NodeIdsListed) + { + this->IFile->seekg(sizeof(int)*numPts, ios::cur); + } + + xCoords = new float[numPts]; + yCoords = new float[numPts]; + zCoords = new float[numPts]; + this->ReadFloatArray(xCoords, numPts); + this->ReadFloatArray(yCoords, numPts); + this->ReadFloatArray(zCoords, numPts); + + for (i = 0; i < numPts; i++) + { + points->InsertNextPoint(xCoords[i], yCoords[i], zCoords[i]); + } + + output->SetPoints(points); + points->Delete(); + delete [] xCoords; + delete [] yCoords; + delete [] zCoords; + } + else if (strncmp(line, "point", 5) == 0) + { + vtkDebugMacro("point"); + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of point cells; check that ByteOrder is set correctly."); + return -1; + } + + nodeIds = new vtkIdType[1]; + + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + nodeIdList = new int[numElements]; + this->ReadIntArray(nodeIdList, numElements); + + for (i = 0; i < numElements; i++) + { + nodeIds[0] = nodeIdList[i] - 1; + cellId = output->InsertNextCell(VTK_VERTEX, 1, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::POINT)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "bar2", 4) == 0) + { + vtkDebugMacro("bar2"); + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar2 cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[2]; + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + nodeIdList = new int[numElements * 2]; + this->ReadIntArray(nodeIdList, numElements * 2); + + for (i = 0; i < numElements; i++) + { + for (j = 0; j < 2; j++) + { + nodeIds[j] = nodeIdList[2*i+j] - 1; + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR2)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "bar3", 4) == 0) + { + vtkDebugMacro("bar3"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of bar3 cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[2]; + + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + nodeIdList = new int[numElements*3]; + this->ReadIntArray(nodeIdList, numElements*3); + + for (i = 0; i < numElements; i++) + { + for (j = 0; j < 2; j++) + { + nodeIds[j] = nodeIdList[3*i+2*j] - 1; + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR3)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "nsided", 6) == 0) + { + vtkDebugMacro("nsided"); + int *numNodesPerElement; + int numNodes = 0; + int nodeCount = 0; + + cellType = vtkEnSightReader::NSIDED; + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of nsided cells; check that ByteOrder is set correctly."); + return -1; + } + + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + numNodesPerElement = new int[numElements]; + this->ReadIntArray(numNodesPerElement, numElements); + for (i = 0; i < numElements; i++) + { + numNodes += numNodesPerElement[i]; + } + nodeIdList = new int[numNodes]; + this->ReadIntArray(nodeIdList, numNodes); + + for (i = 0; i < numElements; i++) + { + nodeIds = new vtkIdType[numNodesPerElement[i]]; + for (j = 0; j < numNodesPerElement[i]; j++) + { + nodeIds[j] = nodeIdList[nodeCount] - 1; + nodeCount++; + } + cellId = output->InsertNextCell(VTK_POLYGON, + numNodesPerElement[i], + nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + + delete [] nodeIds; + } + + delete [] nodeIdList; + delete [] numNodesPerElement; + } + else if (strncmp(line, "tria3", 5) == 0 || + strncmp(line, "tria6", 5) == 0) + { + if (strncmp(line, "tria6", 5) == 0) + { + vtkDebugMacro("tria6"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TRIA6; + } + else + { + vtkDebugMacro("tria3"); + cellType = vtkEnSightReader::TRIA3; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of triangle cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[3]; + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::TRIA6) + { + nodeIdList = new int[numElements*6]; + this->ReadIntArray(nodeIdList, numElements*6); + } + else + { + nodeIdList = new int[numElements*3]; + this->ReadIntArray(nodeIdList, numElements*3); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::TRIA6) + { + for (j = 0; j < 3; j++) + { + nodeIds[j] = nodeIdList[6*i+j] - 1; + } + } + else + { + for (j = 0; j < 3; j++) + { + nodeIds[j] = nodeIdList[3*i+j] - 1; + } + } + cellId = output->InsertNextCell(VTK_TRIANGLE, 3, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "quad4", 5) == 0 || + strncmp(line, "quad8", 5) == 0) + { + if (strncmp(line, "quad8", 5) == 0) + { + vtkDebugMacro("quad8"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::QUAD8; + } + else + { + vtkDebugMacro("quad4"); + cellType = vtkEnSightReader::QUAD4; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of quad cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[4]; + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::QUAD8) + { + nodeIdList = new int[numElements*8]; + this->ReadIntArray(nodeIdList, numElements*8); + } + else + { + nodeIdList = new int[numElements*4]; + this->ReadIntArray(nodeIdList, numElements*4); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::QUAD8) + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[8*i+j] - 1; + } + } + else + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[4*i+j] - 1; + } + } + cellId = output->InsertNextCell(VTK_QUAD, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "tetra4", 6) == 0 || + strncmp(line, "tetra10", 7) == 0) + { + if (strncmp(line, "tetra10", 7) == 0) + { + vtkDebugMacro("tetra10"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TETRA10; + } + else + { + vtkDebugMacro("tetra4"); + cellType = vtkEnSightReader::TETRA4; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of tetrahedral cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[4]; + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::TETRA10) + { + nodeIdList = new int[numElements*10]; + this->ReadIntArray(nodeIdList, numElements*10); + } + else + { + nodeIdList = new int[numElements*4]; + this->ReadIntArray(nodeIdList, numElements*4); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::TETRA10) + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[10*i+j] - 1; + } + } + else + { + for (j = 0; j < 4; j++) + { + nodeIds[j] = nodeIdList[4*i+j] - 1; + } + } + cellId = output->InsertNextCell(VTK_TETRA, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "pyramid5", 8) == 0 || + strncmp(line, "pyramid13", 9) == 0) + { + if (strncmp(line, "pyramid13", 9) == 0) + { + vtkDebugMacro("pyramid13"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PYRAMID13; + } + else + { + vtkDebugMacro("pyramid5"); + cellType = vtkEnSightReader::PYRAMID5; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pyramid cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[5]; + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::PYRAMID13) + { + nodeIdList = new int[numElements*13]; + this->ReadIntArray(nodeIdList, numElements*13); + } + else + { + nodeIdList = new int[numElements*5]; + this->ReadIntArray(nodeIdList, numElements*5); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::PYRAMID13) + { + for (j = 0; j < 5; j++) + { + nodeIds[j] = nodeIdList[13*i+j] - 1; + } + } + else + { + for (j = 0; j < 5; j++) + { + nodeIds[j] = nodeIdList[5*i+j] - 1; + } + } + cellId = output->InsertNextCell(VTK_PYRAMID, 5, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "hexa8", 5) == 0 || + strncmp(line, "hexa20", 6) == 0) + { + if (strncmp(line, "hexa20", 6) == 0) + { + vtkDebugMacro("hexa20"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::HEXA20; + } + else + { + vtkDebugMacro("hexa8"); + cellType = vtkEnSightReader::HEXA8; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of hexahedral cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[8]; + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::HEXA20) + { + nodeIdList = new int[numElements*20]; + this->ReadIntArray(nodeIdList, numElements*20); + } + else + { + nodeIdList = new int[numElements*8]; + this->ReadIntArray(nodeIdList, numElements*8); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::HEXA20) + { + for (j = 0; j < 8; j++) + { + nodeIds[j] = nodeIdList[20*i+j] - 1; + } + } + else + { + for (j = 0; j < 8; j++) + { + nodeIds[j] = nodeIdList[8*i+j] - 1; + } + } + cellId = output->InsertNextCell(VTK_HEXAHEDRON, 8, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "penta6", 6) == 0 || + strncmp(line, "penta15", 7) == 0) + { + if (strncmp(line, "penta15", 7) == 0) + { + vtkDebugMacro("penta15"); + vtkWarningMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PENTA15; + } + else + { + vtkDebugMacro("penta6"); + cellType = vtkEnSightReader::PENTA6; + } + + this->ReadInt(&numElements); + if (numElements < 0 || numElements*(int)sizeof(int) > this->FileSize || + numElements > this->FileSize) + { + vtkErrorMacro("Invalid number of pentagonal cells; check that ByteOrder is set correctly."); + return -1; + } + nodeIds = new vtkIdType[6]; + if (this->ElementIdsListed) + { + this->IFile->seekg(sizeof(int)*numElements, ios::cur); + } + + if (cellType == vtkEnSightReader::PENTA15) + { + nodeIdList = new int[numElements*15]; + this->ReadIntArray(nodeIdList, numElements*15); + } + else + { + nodeIdList = new int[numElements*6]; + this->ReadIntArray(nodeIdList, numElements*6); + } + + for (i = 0; i < numElements; i++) + { + if (cellType == vtkEnSightReader::PENTA15) + { + for (j = 0; j < 6; j++) + { + nodeIds[j] = nodeIdList[15*i+j] - 1; + } + } + else + { + for (j = 0; j < 6; j++) + { + nodeIds[j] = nodeIdList[6*i+j] - 1; + } + } + cellId = output->InsertNextCell(VTK_WEDGE, 6, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + } + + delete [] nodeIds; + delete [] nodeIdList; + } + else if (strncmp(line, "END TIME STEP", 13) == 0) + { + return 1; + } + else if (this->IS->fail()) + { + //May want consistency check here? + //vtkWarningMacro("EOF on geometry file"); + return 1; + } + else + { + vtkErrorMacro("undefined geometry file line"); + return -1; + } + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + continue; + } + lineRead = this->ReadLine(line); + } + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::CreateStructuredGridOutput(int partId, + char line[80], + const char* name) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int i; + vtkPoints *points = vtkPoints::New(); + int numPts; + float *xCoords, *yCoords, *zCoords; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new structured grid output"); + vtkStructuredGrid* sgrid = vtkStructuredGrid::New(); + this->SetNthOutput(partId, sgrid); + sgrid->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkStructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + points->Delete(); + return 0; + } + + vtkStructuredGrid* output = vtkStructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked", 8) == 0) + { + iblanked = 1; + } + } + + this->ReadIntArray(dimensions, 3); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + numPts < 0 || numPts*(int)sizeof(int) > this->FileSize || + numPts > this->FileSize) + { + vtkErrorMacro("Invalid dimensions read; check that ByteOrder is set correctly."); + points->Delete(); + return -1; + } + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + points->Allocate(numPts); + + xCoords = new float[numPts]; + yCoords = new float[numPts]; + zCoords = new float[numPts]; + this->ReadFloatArray(xCoords, numPts); + this->ReadFloatArray(yCoords, numPts); + this->ReadFloatArray(zCoords, numPts); + + for (i = 0; i < numPts; i++) + { + points->InsertNextPoint(xCoords[i], yCoords[i], zCoords[i]); + } + output->SetPoints(points); + if (iblanked) + { + int *iblanks = new int[numPts]; + this->ReadIntArray(iblanks, numPts); + + for (i = 0; i < numPts; i++) + { + if (!iblanks[i]) + { + output->BlankPoint(i); + } + } + delete [] iblanks; + } + + points->Delete(); + delete [] xCoords; + delete [] yCoords; + delete [] zCoords; + + this->IFile->peek(); + if (this->IFile->eof()) + { + lineRead = 0; + } + else + { + lineRead = this->ReadLine(line); + } + + if (strncmp(line, "node_ids", 8) == 0) + { + int *nodeIds = new int[numPts]; + this->ReadIntArray(nodeIds, numPts); + lineRead = this->ReadLine(line); + delete [] nodeIds; + } + if (strncmp(line, "element_ids", 11) == 0) + { + int numElements = (dimensions[0] - 1) * (dimensions[1] - 1) * + (dimensions[2] - 1); + int *elementIds = new int[numElements]; + this->ReadIntArray(elementIds, numElements); + lineRead = this->ReadLine(line); + delete [] elementIds; + } + + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::CreateRectilinearGridOutput(int partId, + char line[80], + const char* name) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int i; + vtkFloatArray *xCoords = vtkFloatArray::New(); + vtkFloatArray *yCoords = vtkFloatArray::New(); + vtkFloatArray *zCoords = vtkFloatArray::New(); + float *tempCoords; + int numPts; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new rectilinear grid output"); + vtkRectilinearGrid* rgrid = vtkRectilinearGrid::New(); + this->SetNthOutput(partId, rgrid); + rgrid->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkRectilinearGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + xCoords->Delete(); + yCoords->Delete(); + zCoords->Delete(); + return 0; + } + + vtkRectilinearGrid* output = vtkRectilinearGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + if (sscanf(line, " %*s %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked", 8) == 0) + { + iblanked = 1; + } + } + + this->ReadIntArray(dimensions, 3); + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + (dimensions[0]+dimensions[1]+dimensions[2]) < 0 || + (dimensions[0]+dimensions[1]+dimensions[2])*(int)sizeof(int) > this->FileSize || + (dimensions[0]+dimensions[1]+dimensions[2]) > this->FileSize) + { + vtkErrorMacro("Invalid dimensions read; check that BytetOrder is set correctly."); + xCoords->Delete(); + yCoords->Delete(); + zCoords->Delete(); + return -1; + } + + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + xCoords->Allocate(dimensions[0]); + yCoords->Allocate(dimensions[1]); + zCoords->Allocate(dimensions[2]); + + tempCoords = new float[dimensions[0]]; + this->ReadFloatArray(tempCoords, dimensions[0]); + for (i = 0; i < dimensions[0]; i++) + { + xCoords->InsertNextTuple(&tempCoords[i]); + } + delete [] tempCoords; + tempCoords = new float[dimensions[1]]; + this->ReadFloatArray(tempCoords, dimensions[1]); + for (i = 0; i < dimensions[1]; i++) + { + yCoords->InsertNextTuple(&tempCoords[i]); + } + delete [] tempCoords; + tempCoords = new float[dimensions[2]]; + this->ReadFloatArray(tempCoords, dimensions[2]); + for (i = 0; i < dimensions[2]; i++) + { + zCoords->InsertNextTuple(&tempCoords[i]); + } + delete [] tempCoords; + if (iblanked) + { + vtkWarningMacro("VTK does not handle blanking for rectilinear grids."); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + int *tempArray = new int[numPts]; + this->ReadIntArray(tempArray, numPts); + delete [] tempArray; + } + + output->SetXCoordinates(xCoords); + output->SetYCoordinates(yCoords); + output->SetZCoordinates(zCoords); + + xCoords->Delete(); + yCoords->Delete(); + zCoords->Delete(); + + // reading next line to check for EOF + lineRead = this->ReadLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldBinaryReader::CreateImageDataOutput(int partId, + char line[80], + const char* name) +{ + char subLine[80]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + float origin[3], delta[3]; + int numPts; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new image data output"); + vtkImageData* idata = vtkImageData::New(); + this->SetNthOutput(partId, idata); + idata->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkImageData")) + { + vtkErrorMacro("Cannot change output type"); + this->OutputsAreValid = 0; + return 0; + } + + vtkImageData* output = vtkImageData::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + if (sscanf(line, " %*s %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked", 8) == 0) + { + iblanked = 1; + } + } + + this->ReadIntArray(dimensions, 3); + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + this->ReadFloatArray(origin, 3); + output->SetOrigin(origin[0], origin[1], origin[2]); + this->ReadFloatArray(delta, 3); + output->SetSpacing(delta[0], delta[1], delta[2]); + + if (iblanked) + { + vtkWarningMacro("VTK does not handle blanking for image data."); + numPts = dimensions[0]*dimensions[1]*dimensions[2]; + if (dimensions[0] < 0 || dimensions[0]*(int)sizeof(int) > this->FileSize || + dimensions[0] > this->FileSize || + dimensions[1] < 0 || dimensions[1]*(int)sizeof(int) > this->FileSize || + dimensions[1] > this->FileSize || + dimensions[2] < 0 || dimensions[2]*(int)sizeof(int) > this->FileSize || + dimensions[2] > this->FileSize || + numPts < 0 || numPts*(int)sizeof(int) > this->FileSize || + numPts > this->FileSize) + { + return -1; + } + int *tempArray = new int[numPts]; + this->ReadIntArray(tempArray, numPts); + delete [] tempArray; + } + + // reading next line to check for EOF + lineRead = this->ReadLine(line); + return lineRead; +} + +// Internal function to read in a line up to 80 characters. +// Returns zero if there was an error. +int vtkEnSightGoldBinaryReader::ReadLine(char result[80]) +{ + if ( this->IFile->read(result, 80) == 0) + { + // The read fails when reading the last part/array when there are no points. + // I took out the error macro as a tempory fix. + // We need to determine what EnSight does when the part with zero point + // is not the last, and change the read array method. + //int fixme; // I do not a file to test with yet. + vtkDebugMacro("Read failed"); + return 0; + } + + return 1; +} + +// Internal function to read a single integer. +// Returns zero if there was an error. +// Sets byte order so that part id is reasonable. +int vtkEnSightGoldBinaryReader::ReadPartId(int *result) +{ + // first swap like normal. + if (this->ReadInt(result) == 0) + { + vtkErrorMacro("Read failed"); + return 0; + } + + // second: try an experimental byte swap. + // Only experiment if byte order is not set. + if (this->ByteOrder == FILE_UNKNOWN_ENDIAN) + { + int tmpLE = *result; + int tmpBE = *result; + vtkByteSwap::Swap4LE(&tmpLE); + vtkByteSwap::Swap4BE(&tmpBE); + + if (tmpLE >= 0 && tmpLE < MAXIMUM_PART_ID) + { + this->ByteOrder = FILE_LITTLE_ENDIAN; + *result = tmpLE; + return 1; + } + if (tmpBE >= 0 && tmpBE < MAXIMUM_PART_ID) + { + this->ByteOrder = FILE_BIG_ENDIAN; + *result = tmpBE; + return 1; + } + vtkErrorMacro("Byte order could not be determined."); + return 0; + } + + return 1; +} + +// Internal function to read a single integer. +// Returns zero if there was an error. +int vtkEnSightGoldBinaryReader::ReadInt(int *result) +{ + if ( this->IFile->read((char*)result, sizeof(int)) == 0) + { + vtkErrorMacro("Read failed"); + return 0; + } + + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LE(result); + } + else if (this->ByteOrder == FILE_BIG_ENDIAN) + { + vtkByteSwap::Swap4BE(result); + } + + return 1; +} + +// Internal function to read an integer array. +// Returns zero if there was an error. +int vtkEnSightGoldBinaryReader::ReadIntArray(int *result, + int numInts) +{ + if (numInts <= 0) + { + return 1; + } + + if (this->IFile->read((char*)result, sizeof(int)*numInts) == 0) + { + vtkErrorMacro("Read failed."); + return 0; + } + + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(result, numInts); + } + else + { + vtkByteSwap::Swap4BERange(result, numInts); + } + + return 1; +} + +// Internal function to read a float array. +// Returns zero if there was an error. +int vtkEnSightGoldBinaryReader::ReadFloatArray(float *result, + int numFloats) +{ + if (numFloats <= 0) + { + return 1; + } + + if (this->IFile->read((char*)result, sizeof(float)*numFloats) == 0) + { + vtkErrorMacro("Read failed"); + return 0; + } + + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(result, numFloats); + } + else + { + vtkByteSwap::Swap4BERange(result, numFloats); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkEnSightGoldBinaryReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkEnSightGoldBinaryReader.h b/IO/vtkEnSightGoldBinaryReader.h new file mode 100644 index 0000000..ff7be2b --- /dev/null +++ b/IO/vtkEnSightGoldBinaryReader.h @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightGoldBinaryReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEnSightGoldBinaryReader - class to read binary EnSight Gold files +// .SECTION Description +// vtkEnSightGoldBinaryReader is a class to read EnSight Gold files into vtk. +// Because the different parts of the EnSight data can be of various data +// types, this reader produces multiple outputs, one per part in the input +// file. +// All variable information is being stored in field data. The descriptions +// listed in the case file are used as the array names in the field data. +// For complex vector variables, the description is appended with _r (for the +// array of real values) and _i (for the array if imaginary values). Complex +// scalar variables are stored as a single array with 2 components, real and +// imaginary, listed in that order. +// .SECTION Caveats +// You must manually call Update on this reader and then connect the rest +// of the pipeline because (due to the nature of the file format) it is +// not possible to know ahead of time how many outputs you will have or +// what types they will be. +// This reader can only handle static EnSight datasets (both static geometry +// and variables). + +#ifndef __vtkEnSightGoldBinaryReader_h +#define __vtkEnSightGoldBinaryReader_h + +#include "vtkEnSightReader.h" + +class VTK_IO_EXPORT vtkEnSightGoldBinaryReader : public vtkEnSightReader +{ +public: + static vtkEnSightGoldBinaryReader *New(); + vtkTypeRevisionMacro(vtkEnSightGoldBinaryReader, vtkEnSightReader); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkEnSightGoldBinaryReader(); + ~vtkEnSightGoldBinaryReader(); + + // Returns 1 if successful. Sets file size as a side action. + int OpenFile(const char* filename); + + // Description: + // Read the geometry file. If an error occurred, 0 is returned; otherwise 1. + virtual int ReadGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read the measured geometry file. If an error occurred, 0 is returned; + // otherwise 1. + virtual int ReadMeasuredGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read scalars per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one component in + // the data array, it is assumed that 0 is the first component added. + virtual int ReadScalarsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0, + int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0); + + // Description: + // Read tensors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerNode(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read scalars per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one componenet in the + // data array, it is assumed that 0 is the first component added. + virtual int ReadScalarsPerElement(const char* fileName, const char* description, + int timeStep, int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read tensors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read an unstructured part (partId) from the geometry file and create a + // vtkUnstructuredGrid output. Return 0 if EOF reached. Return -1 if + // an error occurred. + virtual int CreateUnstructuredGridOutput(int partId, + char line[80], + const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkStructuredGrid output. Return 0 if EOF reached. + virtual int CreateStructuredGridOutput(int partId, + char line[256], + const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkRectilinearGrid output. Return 0 if EOF reached. + int CreateRectilinearGridOutput(int partId, char line[256], const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkImageData output. Return 0 if EOF reached. + int CreateImageDataOutput(int partId, char line[80], const char* name); + + // Description: + // Internal function to read in a line up to 80 characters. + // Returns zero if there was an error. + int ReadLine(char result[80]); + + // Description: + // Internal function to read in a single integer. + // Returns zero if there was an error. + int ReadInt(int *result); + int ReadPartId(int *result); + + // Description: + // Internal function to read in an integer array. + // Returns zero if there was an error. + int ReadIntArray(int *result, int numInts); + + // Description: + // Internal function to read in a float array. + // Returns zero if there was an error. + int ReadFloatArray(float *result, int numFloats); + + // Description: + // Read to the next time step in the geometry file. + int SkipTimeStep(); + int SkipStructuredGrid(char line[256]); + int SkipUnstructuredGrid(char line[256]); + int SkipRectilinearGrid(char line[256]); + int SkipImageData(char line[256]); + + int NodeIdsListed; + int ElementIdsListed; + + ifstream *IFile; + // The size of the file could be used to choose byte order. + int FileSize; + +private: + vtkEnSightGoldBinaryReader(const vtkEnSightGoldBinaryReader&); // Not implemented. + void operator=(const vtkEnSightGoldBinaryReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkEnSightGoldReader.cxx b/IO/vtkEnSightGoldReader.cxx new file mode 100644 index 0000000..3fb368a --- /dev/null +++ b/IO/vtkEnSightGoldReader.cxx @@ -0,0 +1,2169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightGoldReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEnSightGoldReader.h" + +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkEnSightGoldReader, "$Revision: 1.53 $"); +vtkStandardNewMacro(vtkEnSightGoldReader); + +//BTX +class UndefPartialInternal +{ +public: + double UndefCoordinates; + double UndefBlock; + double UndefElementTypes; + vtkstd::vector PartialCoordinates; + vtkstd::vector PartialBlock; + vtkstd::vector PartialElementTypes; +}; +//ETX + +//---------------------------------------------------------------------------- +vtkEnSightGoldReader::vtkEnSightGoldReader() +{ + this->UndefPartial = new UndefPartialInternal; +} +//---------------------------------------------------------------------------- + +vtkEnSightGoldReader::~vtkEnSightGoldReader() +{ + delete UndefPartial; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadGeometryFile(const char* fileName, int timeStep) +{ + char line[256], subLine[256]; + int partId, realId, i; + int lineRead; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A GeometryFileName must be specified in the case file."); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to geometry file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + this->ReadNextDataLine(line); + sscanf(line, " %*s %s", subLine); + if (strncmp(subLine, "Binary",6) == 0) + { + vtkErrorMacro("This is a binary data set. Try " + <<"vtkEnSightGoldBinaryReader."); + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); + } + + while(strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadNextDataLine(line); + } + this->ReadLine(line); + } + + // Skip description lines. Using ReadLine instead of + // ReadNextDataLine because the description line could be blank. + this->ReadNextDataLine(line); + // Skip the node id and element id lines. + this->ReadNextDataLine(line); + this->ReadNextDataLine(line); + + lineRead = this->ReadNextDataLine(line); // "extents" or "part" + if (strncmp(line, "extents",7) == 0) + { + // Skipping the extent lines for now. + this->ReadNextDataLine(line); + this->ReadNextDataLine(line); + this->ReadNextDataLine(line); + lineRead = this->ReadNextDataLine(line); // "part" + } + + while (lineRead && strncmp(line, "part", 4) == 0) + { + this->NumberOfGeometryParts++; + this->ReadNextDataLine(line); + partId = atoi(line) - 1; // EnSight starts #ing at 1. + realId = this->InsertNewPartId(partId); + + this->ReadNextDataLine(line); // part description line + char *name = strdup(line); + if (strncmp(line, "interface", 9) == 0) + { + return 1; // ignore it and move on + } + + this->ReadNextDataLine(line); + + if (strncmp(line, "block", 5) == 0) + { + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strncmp(subLine, "rectilinear",11) == 0) + { + // block rectilinear + lineRead = this->CreateRectilinearGridOutput(realId, line, name); + } + else if (strncmp(subLine, "uniform",7) == 0) + { + // block uniform + lineRead = this->CreateImageDataOutput(realId, line, name); + } + else + { + // block iblanked + lineRead = this->CreateStructuredGridOutput(realId, line, name); + } + } + else + { + // block + lineRead = this->CreateStructuredGridOutput(realId, line, name); + } + } + else + { + lineRead = this->CreateUnstructuredGridOutput(realId, line, name); + if (lineRead < 0) + { + free(name); + delete this->IS; + this->IS = NULL; + return 0; + } + } + free(name); + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadMeasuredGeometryFile(const char* fileName, + int timeStep) +{ + char line[256], subLine[256]; + vtkPoints *newPoints; + int i; + int tempId; + vtkIdType id; + float coords[3]; + vtkPolyData *geom; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("A MeasuredFileName must be specified in the case file."); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to measured geometry file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + // Skip the description line. Using ReadLine instead of ReadNextDataLine + // because the description line could be blank. + this->ReadLine(line); + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strncmp(subLine, "Binary",6) == 0) + { + vtkErrorMacro("This is a binary data set. Try " + << "vtkEnSight6BinaryReader."); + return 0; + } + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + this->ReadLine(line); + } + + while(strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadNextDataLine(line); + } + this->ReadLine(line); + } + + this->ReadLine(line); // "particle coordinates" + this->ReadLine(line); + this->NumberOfMeasuredPoints = atoi(line); + + if (this->GetOutput(this->NumberOfGeometryParts) == NULL) + { + vtkDebugMacro("creating new measured geometry output"); + vtkPolyData* pd = vtkPolyData::New(); + pd->Allocate(this->NumberOfMeasuredPoints); + this->SetNthOutput(this->NumberOfGeometryParts, pd); + pd->Delete(); + } + else if ( ! this->GetOutput(this->NumberOfGeometryParts)->IsA("vtkPolyData")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + geom = ((vtkPolyData*)this->GetOutput(this->NumberOfGeometryParts)); + + newPoints = vtkPoints::New(); + newPoints->Allocate(this->NumberOfMeasuredPoints); + + for (i = 0; i < this->NumberOfMeasuredPoints; i++) + { + this->ReadLine(line); + sscanf(line, " %8d %12e %12e %12e", &tempId, &coords[0], &coords[1], + &coords[2]); + id = tempId; + newPoints->InsertNextPoint(coords); + geom->InsertNextCell(VTK_VERTEX, 1, &id); + } + + ((vtkPolyData*)this->GetOutput(this->NumberOfGeometryParts))-> + SetPoints(newPoints); + + newPoints->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadScalarsPerNode(const char* fileName, const char* description, + int timeStep, int measured, + int numberOfComponents, + int component) +{ + char line[256], formatLine[256], tempLine[256]; + int partId, realId, numPts, i, j, numLines, moreScalars; + vtkFloatArray *scalars; + float scalarsRead[6]; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalar per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadNextDataLine(line); // skip the description line + + if (measured) + { + output = this->GetOutput(this->NumberOfGeometryParts); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + numLines = numPts / 6; + moreScalars = numPts % 6; + + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numPts); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numPts * numberOfComponents); + + this->ReadNextDataLine(line); + + for (i = 0; i < numLines; i++) + { + sscanf(line, " %12e %12e %12e %12e %12e %12e", &scalarsRead[0], + &scalarsRead[1], &scalarsRead[2], &scalarsRead[3], + &scalarsRead[4], &scalarsRead[5]); + for (j = 0; j < 6; j++) + { + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + } + this->ReadNextDataLine(line); + } + strcpy(formatLine, ""); + strcpy(tempLine, ""); + for (j = 0; j < moreScalars; j++) + { + strcat(formatLine, " %12e"); + sscanf(line, formatLine, &scalarsRead[j]); + scalars->InsertComponent(i*6 + j, component, scalarsRead[j]); + strcat(tempLine, " %*12e"); + strcpy(formatLine, tempLine); + } + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()-> SetScalars(scalars); + } + scalars->Delete(); + } + delete this->IS; + this->IS = NULL; + return 1; + } + + while (this->ReadNextDataLine(line) && + strncmp(line, "part",4) == 0) + { + this->ReadNextDataLine(line); + partId = atoi(line) - 1; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadNextDataLine(line); // "coordinates" or "block" + int partial = this->CheckForUndefOrPartial(line); + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfTuples(numPts); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->Allocate(numPts * numberOfComponents); + } + else + { + scalars = (vtkFloatArray*)(output->GetPointData()-> + GetArray(description)); + } + + // If the keyword 'partial' was found, we should replace unspecified + // coordinate to take the value specified in the 'undef' field + if( partial ) + { + int l = 0; + double val; + for (i = 0; i < numPts; i++) + { + if( i == this->UndefPartial->PartialCoordinates[l] ) + { + this->ReadNextDataLine(line); + val = atof( line ); + } + else + { + val = this->UndefPartial->UndefCoordinates; + l++; + } + scalars->InsertComponent(i, component, val); + } + } + else + { + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + scalars->InsertComponent(i, component, atof(line)); + } + } + + if (component == 0) + { + scalars->SetName(description); + output->GetPointData()->AddArray(scalars); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(scalars); + } + scalars->Delete(); + } + else + { + output->GetPointData()->AddArray(scalars); + } + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadVectorsPerNode(const char* fileName, const char* description, + int timeStep, int measured) +{ + char line[256], formatLine[256], tempLine[256]; + int partId, realId, numPts, i, j, numLines, moreVectors; + vtkFloatArray *vectors; + float vector1[3], vector2[3]; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadNextDataLine(line); // skip the description line + + if (measured) + { + output = this->GetOutput(this->NumberOfGeometryParts); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + this->ReadNextDataLine(line); + numLines = numPts / 2; + moreVectors = ((numPts * 3) % 6) / 3; + vectors = vtkFloatArray::New(); + vectors->SetNumberOfTuples(numPts); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numPts*3); + for (i = 0; i < numLines; i++) + { + sscanf(line, " %12e %12e %12e %12e %12e %12e", &vector1[0], + &vector1[1], &vector1[2], &vector2[0], &vector2[1], + &vector2[2]); + vectors->InsertTuple(i*2, vector1); + vectors->InsertTuple(i*2 + 1, vector2); + this->ReadNextDataLine(line); + } + strcpy(formatLine, ""); + strcpy(tempLine, ""); + for (j = 0; j < moreVectors; j++) + { + strcat(formatLine, " %12e %12e %12e"); + sscanf(line, formatLine, &vector1[0], &vector1[1], &vector1[2]); + vectors->InsertTuple(i*2 + j, vector1); + strcat(tempLine, " %*12e %*12e %*12e"); + strcpy(formatLine, tempLine); + } + vectors->SetName(description); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + vectors->Delete(); + } + delete this->IS; + this->IS = NULL; + return 1; + } + + while (this->ReadNextDataLine(line) && + strncmp(line, "part",4) == 0) + { + this->ReadNextDataLine(line); + partId = atoi(line) - 1; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + vectors = vtkFloatArray::New(); + this->ReadNextDataLine(line); // "coordinates" or "block" + vectors->SetNumberOfTuples(numPts); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numPts*3); + for (i = 0; i < 3; i++) + { + for (j = 0; j < numPts; j++) + { + this->ReadNextDataLine(line); + vectors->InsertComponent(j, i, atof(line)); + } + } + vectors->SetName(description); + output->GetPointData()->AddArray(vectors); + if (!output->GetPointData()->GetVectors()) + { + output->GetPointData()->SetVectors(vectors); + } + vectors->Delete(); + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadTensorsPerNode(const char* fileName, const char* description, + int timeStep) +{ + char line[256]; + int partId, realId, numPts, i, j; + vtkFloatArray *tensors; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorPerNode variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor per node file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadNextDataLine(line); // skip the description line + + while (this->ReadNextDataLine(line) && + strncmp(line, "part",4) == 0) + { + this->ReadNextDataLine(line); + partId = atoi(line) - 1; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numPts = output->GetNumberOfPoints(); + if (numPts) + { + tensors = vtkFloatArray::New(); + this->ReadNextDataLine(line); // "coordinates" or "block" + tensors->SetNumberOfTuples(numPts); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numPts*6); + for (i = 0; i < 6; i++) + { + for (j = 0; j < numPts; j++) + { + this->ReadNextDataLine(line); + tensors->InsertComponent(j, i, atof(line)); + } + } + tensors->SetName(description); + output->GetPointData()->AddArray(tensors); + tensors->Delete(); + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadScalarsPerElement(const char* fileName, + const char* description, + int timeStep, + int numberOfComponents, + int component) +{ + char line[256]; + int partId, realId, numCells, numCellsPerElement, i, idx; + vtkFloatArray *scalars; + int lineRead, elementType; + float scalar; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL ScalarPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to scalar per element file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadNextDataLine(line); // skip the description line + lineRead = this->ReadNextDataLine(line); // "part" + + while (lineRead && strncmp(line, "part",4) == 0) + { + this->ReadNextDataLine(line); + partId = atoi(line) - 1; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + this->ReadNextDataLine(line); // element type or "block" + if (component == 0) + { + scalars = vtkFloatArray::New(); + scalars->SetNumberOfComponents(numberOfComponents); + scalars->SetNumberOfTuples(numCells); + } + else + { + scalars = + (vtkFloatArray*)(output->GetCellData()->GetArray(description)); + } + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strncmp(line, "block",5) == 0) + { + for (i = 0; i < numCells; i++) + { + this->ReadNextDataLine(line); + scalar = atof(line); + scalars->InsertComponent(i, component, scalar); + } + lineRead = this->ReadNextDataLine(line); + } + else + { + while (lineRead && strncmp(line, "part",4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + // Check if line contains either 'partial' or 'undef' keyword + int partial = this->CheckForUndefOrPartial(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + delete this->IS; + this->IS = NULL; + if (component == 0) + { + scalars->Delete(); + } + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = + this->GetCellIds(idx, elementType)->GetNumberOfIds(); + // If the 'partial' keyword was found, we should replace + // unspecified coordinate with value specified in the 'undef' section + if( partial ) + { + int j = 0; + for (i = 0; i < numCellsPerElement; i++) + { + if( i == this->UndefPartial->PartialElementTypes[j] ) + { + this->ReadNextDataLine(line); + scalar = atof(line); + } + else + { + scalar = this->UndefPartial->UndefElementTypes; + j++; //go on to the next value in the partial list + } + scalars->InsertComponent( this->GetCellIds(idx, + elementType)->GetId(i), component, scalar); + } + } + else + { + for (i = 0; i < numCellsPerElement; i++) + { + this->ReadNextDataLine(line); + scalar = atof(line); + scalars->InsertComponent( this->GetCellIds(idx, + elementType)->GetId(i), component, scalar); + } + } + lineRead = this->ReadNextDataLine(line); + } // end while + } // end else + if (component == 0) + { + scalars->SetName(description); + output->GetCellData()->AddArray(scalars); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(scalars); + } + scalars->Delete(); + } + else + { + output->GetCellData()->AddArray(scalars); + } + } + else + { + lineRead = this->ReadNextDataLine(line); + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadVectorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[256]; + int partId, realId, numCells, numCellsPerElement, i, j, idx; + vtkFloatArray *vectors; + int lineRead, elementType; + float value; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL VectorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to vector per element file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadNextDataLine(line); // skip the description line + lineRead = this->ReadNextDataLine(line); // "part" + + while (lineRead && strncmp(line, "part",4) == 0) + { + this->ReadNextDataLine(line); + partId = atoi(line) - 1; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + vectors = vtkFloatArray::New(); + this->ReadNextDataLine(line); // element type or "block" + vectors->SetNumberOfTuples(numCells); + vectors->SetNumberOfComponents(3); + vectors->Allocate(numCells*3); + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strncmp(line, "block",5) == 0) + { + for (i = 0; i < 3; i++) + { + for (j = 0; j < numCells; j++) + { + this->ReadNextDataLine(line); + value = atof(line); + vectors->InsertComponent(j, i, value); + } + } + lineRead = this->ReadNextDataLine(line); + } + else + { + while (lineRead && strncmp(line, "part",4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + delete this->IS; + this->IS = NULL; + vectors->Delete(); + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = + this->GetCellIds(idx, elementType)->GetNumberOfIds(); + for (i = 0; i < 3; i++) + { + for (j = 0; j < numCellsPerElement; j++) + { + this->ReadNextDataLine(line); + value = atof(line); + vectors->InsertComponent(this->GetCellIds(idx, elementType)->GetId(j), + i, value); + } + } + lineRead = this->ReadNextDataLine(line); + } // end while + } // end else + vectors->SetName(description); + output->GetCellData()->AddArray(vectors); + if (!output->GetCellData()->GetVectors()) + { + output->GetCellData()->SetVectors(vectors); + } + vectors->Delete(); + } + else + { + lineRead = this->ReadNextDataLine(line); + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::ReadTensorsPerElement(const char* fileName, + const char* description, + int timeStep) +{ + char line[256]; + int partId, realId, numCells, numCellsPerElement, i, j, idx; + vtkFloatArray *tensors; + int lineRead, elementType; + float value; + vtkDataSet *output; + + // Initialize + // + if (!fileName) + { + vtkErrorMacro("NULL TensorPerElement variable file name"); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to tensor per element file: " << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + if (this->UseFileSets) + { + for (i = 0; i < timeStep - 1; i++) + { + this->ReadLine(line); + while (strncmp(line, "END TIME STEP", 13) != 0) + { + this->ReadLine(line); + } + } + + this->ReadLine(line); + while (strncmp(line, "BEGIN TIME STEP", 15) != 0) + { + this->ReadLine(line); + } + } + + this->ReadNextDataLine(line); // skip the description line + lineRead = this->ReadNextDataLine(line); // "part" + + while (lineRead && strncmp(line, "part",4) == 0) + { + this->ReadNextDataLine(line); + partId = atoi(line) - 1; // EnSight starts #ing with 1. + realId = this->InsertNewPartId(partId); + output = this->GetOutput(realId); + numCells = output->GetNumberOfCells(); + if (numCells) + { + tensors = vtkFloatArray::New(); + this->ReadNextDataLine(line); // element type or "block" + tensors->SetNumberOfTuples(numCells); + tensors->SetNumberOfComponents(6); + tensors->Allocate(numCells*6); + + // need to find out from CellIds how many cells we have of this element + // type (and what their ids are) -- IF THIS IS NOT A BLOCK SECTION + if (strncmp(line, "block",5) == 0) + { + for (i = 0; i < 6; i++) + { + for (j = 0; j < numCells; j++) + { + this->ReadNextDataLine(line); + value = atof(line); + tensors->InsertComponent(j, i, value); + } + } + lineRead = this->ReadNextDataLine(line); + } + else + { + while (lineRead && strncmp(line, "part",4) != 0 && + strncmp(line, "END TIME STEP", 13) != 0) + { + elementType = this->GetElementType(line); + if (elementType == -1) + { + vtkErrorMacro("Unknown element type \"" << line << "\""); + delete [] this->IS; + this->IS = NULL; + tensors->Delete(); + return 0; + } + idx = this->UnstructuredPartIds->IsId(realId); + numCellsPerElement = + this->GetCellIds(idx, elementType)->GetNumberOfIds(); + for (i = 0; i < 6; i++) + { + for (j = 0; j < numCellsPerElement; j++) + { + this->ReadNextDataLine(line); + value = atof(line); + tensors->InsertComponent(this->GetCellIds(idx, elementType)->GetId(j), + i, value); + } + } + lineRead = this->ReadNextDataLine(line); + } // end while + } // end else + tensors->SetName(description); + output->GetCellData()->AddArray(tensors); + tensors->Delete(); + } + else + { + lineRead = this->ReadNextDataLine(line); + } + } + + delete this->IS; + this->IS = NULL; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::CreateUnstructuredGridOutput(int partId, + char line[256], + const char* name) +{ + int lineRead = 1; + char subLine[256]; + int i, j; + vtkIdType *nodeIds; + int *intIds; + int numElements; + int idx, cellType; + vtkIdType cellId; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new unstructured output"); + vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New(); + this->SetNthOutput(partId, ugrid); + ugrid->Delete(); + + this->UnstructuredPartIds->InsertNextId(partId); + } + else if ( ! this->GetOutput(partId)->IsA("vtkUnstructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + // Clear all cell ids from the last execution, if any. + idx = this->UnstructuredPartIds->IsId(partId); + for (i = 0; i < 16; i++) + { + this->GetCellIds(idx, i)->Reset(); + } + + output->Allocate(1000); + + while(lineRead && strncmp(line, "part", 4) != 0) + { + if (strncmp(line, "coordinates", 11) == 0) + { + vtkDebugMacro("coordinates"); + int numPts; + vtkPoints *points = vtkPoints::New(); + double point[3]; + + this->ReadNextDataLine(line); + numPts = atoi(line); + vtkDebugMacro("num. points: " << numPts); + + points->Allocate(numPts); + + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + points->InsertNextPoint(atof(line), 0, 0); + } + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + points->GetPoint(i, point); + points->SetPoint(i, point[0], atof(line), 0); + } + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + points->GetPoint(i, point); + points->SetPoint(i, point[0], point[1], atof(line)); + } + + lineRead = this->ReadNextDataLine(line); + sscanf(line, " %s", subLine); + + char *endptr; + strtod(subLine, &endptr); // Testing is we can convert this string to double + if ( subLine != endptr ) + { // necessary if node ids were listed + for (i = 0; i < numPts; i++) + { + points->GetPoint(i, point); + points->SetPoint(i, point[1], point[2], atof(line)); + lineRead = this->ReadNextDataLine(line); + } + } + output->SetPoints(points); + points->Delete(); + } + else if (strncmp(line, "point", 5) == 0) + { + int *elementIds; + vtkDebugMacro("point"); + + nodeIds = new vtkIdType[1]; + this->ReadNextDataLine(line); + numElements = atoi(line); + elementIds = new int[numElements]; + + for (i = 0; i < numElements; i++) + { + this->ReadNextDataLine(line); + elementIds[i] = atoi(line); + } + lineRead = this->ReadNextDataLine(line); + sscanf(line, " %s", subLine); + if (isdigit(subLine[0])) + { + for (i = 0; i < numElements; i++) + { + nodeIds[0] = atoi(line) - 1; // because EnSight ids start at 1 + cellId = output->InsertNextCell(VTK_VERTEX, 1, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::POINT)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + } + else + { + for (i = 0; i < numElements; i++) + { + nodeIds[0] = elementIds[i] - 1; + cellId = output->InsertNextCell(VTK_VERTEX, 1, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::POINT)->InsertNextId(cellId); + } + } + + delete [] nodeIds; + delete [] elementIds; + } + else if (strncmp(line, "bar2", 4) == 0) + { + vtkDebugMacro("bar2"); + + nodeIds = new vtkIdType[2]; + intIds = new int[2]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %d", &intIds[0], &intIds[1]) != 2) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %d", &intIds[0], &intIds[1]); + for (j = 0; j < 2; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR2)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "bar3", 4) == 0) + { + vtkDebugMacro("bar3"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + nodeIds = new vtkIdType[2]; + intIds = new int[2]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %*d %d", &intIds[0], &intIds[1]) != 2) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %*d %d", &intIds[0], &intIds[1]); + for (j = 0; j < 2; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_LINE, 2, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::BAR3)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "nsided", 6) == 0) + { + int numNodes; + char ** newLines; + char formatLine[256], tempLine[256]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + newLines = new char *[numElements*2]; + for (i = 0; i < numElements*2; i++) + { + newLines[i] = new char[256]; + this->ReadNextDataLine(newLines[i]); + } + lineRead = this->ReadNextDataLine(line); + if (lineRead) + { + sscanf(line, " %s", subLine); + } + if (lineRead && isdigit(subLine[0])) + { + // We still need to read in the node ids for each element. + for (i = 0; i < numElements; i++) + { + numNodes = atoi(newLines[numElements+i]); + nodeIds = new vtkIdType[numNodes]; + intIds = new int[numNodes]; + + strcpy(formatLine, ""); + strcpy(tempLine, ""); + for (j = 0; j < numNodes; j++) + { + strcat(formatLine, " %d"); + sscanf(line, formatLine, &intIds[numNodes-j-1]); + strcat(tempLine, " %*d"); + strcpy(formatLine, tempLine); + intIds[numNodes-j-1]--; + nodeIds[numNodes-j-1] = intIds[numNodes-j-1]; + } + cellId = output->InsertNextCell(VTK_POLYGON, numNodes, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::NSIDED)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + delete [] nodeIds; + delete [] intIds; + } + } + else + { + // We have already read in the lines with node ids into newLines. + for (i = 0; i < numElements; i++) + { + numNodes = atoi(newLines[i]); + nodeIds = new vtkIdType[numNodes]; + intIds = new int[numNodes]; + + strcpy(formatLine, ""); + strcpy(tempLine, ""); + for (j = 0; j < numNodes; j++) + { + strcat(formatLine, " %d"); + sscanf(newLines[numElements+i], formatLine, + &intIds[numNodes-j-1]); + intIds[numNodes-j-1]--; + nodeIds[numNodes-j-1] = intIds[numNodes-j-1]; + strcat(tempLine, " %*d"); + strcpy(formatLine, tempLine); + } + cellId = output->InsertNextCell(VTK_POLYGON, numNodes, nodeIds); + this->GetCellIds(idx, vtkEnSightReader::NSIDED)->InsertNextId(cellId); + delete [] nodeIds; + delete [] intIds; + } + } + for (i = 0; i < numElements*2; i++) + { + delete [] newLines[i]; + newLines[i] = NULL; + } + delete [] newLines; + } + else if (strncmp(line, "tria3", 5) == 0 || + strncmp(line, "tria6", 5) == 0) + { + if (strncmp(line, "tria6", 5) == 0) + { + vtkDebugMacro("tria6"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TRIA6; + } + else + { + vtkDebugMacro("tria3"); + cellType = vtkEnSightReader::TRIA3; + } + + nodeIds = new vtkIdType[3]; + intIds = new int[3]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %d %d", &intIds[0], &intIds[1], + &intIds[2]) != 3) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %d %d", &intIds[0], &intIds[1], &intIds[2]); + for (j = 0; j < 3; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_TRIANGLE, 3, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "quad4", 5) == 0 || + strncmp(line, "quad8", 5) == 0) + { + if (strncmp(line, "quad8", 5) == 0) + { + vtkDebugMacro("quad8"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::QUAD8; + } + else + { + vtkDebugMacro("quad4"); + cellType = vtkEnSightReader::QUAD4; + } + + nodeIds = new vtkIdType[4]; + intIds = new int[4]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3]) != 4) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3]); + for (j = 0; j < 4; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_QUAD, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "tetra4", 6) == 0 || + strncmp(line, "tetra10", 7) == 0) + { + if (strncmp(line, "tetra10", 7) == 0) + { + vtkDebugMacro("tetra10"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::TETRA10; + } + else + { + vtkDebugMacro("tetra4"); + cellType = vtkEnSightReader::TETRA4; + } + + nodeIds = new vtkIdType[4]; + intIds = new int[4]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3]) != 4) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3]); + for (j = 0; j < 4; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_TETRA, 4, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "pyramid5", 8) == 0 || + strncmp(line, "pyramid13", 9) == 0) + { + if (strncmp(line, "pyramid13", 9) == 0) + { + vtkDebugMacro("pyramid13"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PYRAMID13; + } + else + { + vtkDebugMacro("pyramid5"); + cellType = vtkEnSightReader::PYRAMID5; + } + + nodeIds = new vtkIdType[5]; + intIds = new int[5]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3], &intIds[4]) != 5) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3], &intIds[4]); + for (j = 0; j < 5; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_PYRAMID, 5, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "hexa8", 5) == 0 || + strncmp(line, "hexa20", 6) == 0) + { + if (strncmp(line, "hexa20", 6) == 0) + { + vtkDebugMacro("hexa20"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::HEXA20; + } + else + { + vtkDebugMacro("hexa8"); + cellType = vtkEnSightReader::HEXA8; + } + + nodeIds = new vtkIdType[8]; + intIds = new int[8]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %d %d %d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3], &intIds[4], &intIds[5], &intIds[6], + &intIds[7]) != 8) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %d %d %d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3], &intIds[4], &intIds[5], &intIds[6], + &intIds[7]); + for (j = 0; j < 8; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_HEXAHEDRON, 8, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "penta6", 6) == 0 || + strncmp(line, "penta15", 7) == 0) + { + if (strncmp(line, "penta15", 7) == 0) + { + vtkDebugMacro("penta15"); + vtkDebugMacro("Only vertex nodes of this element will be read."); + cellType = vtkEnSightReader::PENTA15; + } + else + { + vtkDebugMacro("penta6"); + cellType = vtkEnSightReader::PENTA6; + } + + nodeIds = new vtkIdType[6]; + intIds = new int[6]; + + this->ReadNextDataLine(line); + numElements = atoi(line); + this->ReadNextDataLine(line); + if (sscanf(line, " %d %d %d %d %d %d", &intIds[0], &intIds[1], + &intIds[2], &intIds[3], &intIds[4], &intIds[5]) != 6) + { + for (i = 0; i < numElements; i++) + { + // Skip the element ids since they are just labels. + this->ReadNextDataLine(line); + } + } + for (i = 0; i < numElements; i++) + { + sscanf(line, " %d %d %d %d %d %d", &intIds[0], &intIds[1], &intIds[2], + &intIds[3], &intIds[4], &intIds[5]); + for (j = 0; j < 6; j++) + { + intIds[j]--; + nodeIds[j] = intIds[j]; + } + cellId = output->InsertNextCell(VTK_WEDGE, 6, nodeIds); + this->GetCellIds(idx, cellType)->InsertNextId(cellId); + lineRead = this->ReadNextDataLine(line); + } + delete [] nodeIds; + delete [] intIds; + } + else if (strncmp(line, "END TIME STEP", 13) == 0) + { + return 1; + } + else if (this->IS->fail()) + { + //May want consistency check here? + //vtkWarningMacro("EOF on geometry file"); + return 1; + } + else + { + vtkErrorMacro("undefined geometry file line"); + return -1; + } + } + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::CreateStructuredGridOutput(int partId, + char line[256], + const char* name) +{ + char subLine[256]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int i; + vtkPoints *points = vtkPoints::New(); + double point[3]; + int numPts; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new structured grid output"); + vtkStructuredGrid* sgrid = vtkStructuredGrid::New(); + this->SetNthOutput(partId, sgrid); + sgrid->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkStructuredGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkStructuredGrid* output = vtkStructuredGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + if (sscanf(line, " %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked",8) == 0) + { + iblanked = 1; + } + } + + this->ReadNextDataLine(line); + sscanf(line, " %d %d %d", &dimensions[0], &dimensions[1], &dimensions[2]); + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + points->Allocate(numPts); + + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + points->InsertNextPoint(atof(line), 0.0, 0.0); + } + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + points->GetPoint(i, point); + points->SetPoint(i, point[0], atof(line), point[2]); + } + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + points->GetPoint(i, point); + points->SetPoint(i, point[0], point[1], atof(line)); + } + output->SetPoints(points); + if (iblanked) + { + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + if (!atoi(line)) + { + output->BlankPoint(i); + } + } + } + + points->Delete(); + // reading next line to check for EOF + lineRead = this->ReadNextDataLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::CreateRectilinearGridOutput(int partId, + char line[256], + const char* name) +{ + char subLine[256]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int i; + vtkFloatArray *xCoords = vtkFloatArray::New(); + vtkFloatArray *yCoords = vtkFloatArray::New(); + vtkFloatArray *zCoords = vtkFloatArray::New(); + int numPts; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new structured grid output"); + vtkRectilinearGrid* rgrid = vtkRectilinearGrid::New(); + this->SetNthOutput(partId, rgrid); + rgrid->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkRectilinearGrid")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkRectilinearGrid* output = vtkRectilinearGrid::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + + if (sscanf(line, " %*s %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked",8) == 0) + { + iblanked = 1; + } + } + + this->ReadNextDataLine(line); + sscanf(line, " %d %d %d", &dimensions[0], &dimensions[1], &dimensions[2]); + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + xCoords->Allocate(dimensions[0]); + yCoords->Allocate(dimensions[1]); + zCoords->Allocate(dimensions[2]); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + + float val; + + for (i = 0; i < dimensions[0]; i++) + { + this->ReadNextDataLine(line); + val = atof(line); + xCoords->InsertNextTuple(&val); + } + for (i = 0; i < dimensions[1]; i++) + { + this->ReadNextDataLine(line); + val = atof(line); + yCoords->InsertNextTuple(&val); + } + for (i = 0; i < dimensions[2]; i++) + { + this->ReadNextDataLine(line); + val = atof(line); + zCoords->InsertNextTuple(&val); + } + if (iblanked) + { + vtkDebugMacro("VTK does not handle blanking for rectilinear grids."); + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + } + } + + output->SetXCoordinates(xCoords); + output->SetYCoordinates(yCoords); + output->SetZCoordinates(zCoords); + + xCoords->Delete(); + yCoords->Delete(); + zCoords->Delete(); + + // reading next line to check for EOF + lineRead = this->ReadNextDataLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::CreateImageDataOutput(int partId, + char line[256], + const char* name) +{ + char subLine[256]; + int lineRead; + int iblanked = 0; + int dimensions[3]; + int i; + float origin[3], delta[3]; + int numPts; + + this->NumberOfNewOutputs++; + + if (this->GetOutput(partId) == NULL) + { + vtkDebugMacro("creating new image data output"); + vtkImageData* idata = vtkImageData::New(); + this->SetNthOutput(partId, idata); + idata->Delete(); + } + else if ( ! this->GetOutput(partId)->IsA("vtkImageData")) + { + vtkErrorMacro("Cannot change type of output"); + this->OutputsAreValid = 0; + return 0; + } + + vtkImageData* output = vtkImageData::SafeDownCast( + this->GetOutput(partId)); + + vtkCharArray* nmArray = vtkCharArray::New(); + nmArray->SetName("Name"); + size_t len = strlen(name); + nmArray->SetNumberOfTuples(static_cast(len)+1); + char* copy = nmArray->GetPointer(0); + memcpy(copy, name, len); + copy[len] = '\0'; + output->GetFieldData()->AddArray(nmArray); + nmArray->Delete(); + + if (sscanf(line, " %*s %*s %s", subLine) == 1) + { + if (strncmp(subLine, "iblanked",8) == 0) + { + iblanked = 1; + } + } + + this->ReadNextDataLine(line); + sscanf(line, " %d %d %d", &dimensions[0], &dimensions[1], &dimensions[2]); + output->SetDimensions(dimensions); + output->SetWholeExtent( + 0, dimensions[0]-1, 0, dimensions[1]-1, 0, dimensions[2]-1); + + for (i = 0; i < 3; i++) + { + this->ReadNextDataLine(line); + sscanf(line, " %f", &origin[i]); + } + output->SetOrigin(origin[0], origin[1], origin[2]); + + for (i = 0; i < 3; i++) + { + this->ReadNextDataLine(line); + sscanf(line, " %f", &delta[i]); + } + + output->SetSpacing(delta[0], delta[1], delta[2]); + + if (iblanked) + { + vtkDebugMacro("VTK does not handle blanking for image data."); + numPts = dimensions[0] * dimensions[1] * dimensions[2]; + for (i = 0; i < numPts; i++) + { + this->ReadNextDataLine(line); + } + } + + // reading next line to check for EOF + lineRead = this->ReadNextDataLine(line); + return lineRead; +} + +//---------------------------------------------------------------------------- +int vtkEnSightGoldReader::CheckForUndefOrPartial(const char *line) +{ + char undefvar[16]; + // Look for keyword 'partial' or 'undef': + int r = sscanf(line, "%*s %s", undefvar); + if( r == 1) + { + char subline[80]; + if( strcmp(undefvar, "undef") == 0 ) + { + vtkDebugMacro( "undef: " << line ); + this->ReadNextDataLine(subline); + double val = atof( subline ); + switch( this->GetSectionType(line) ) + { + case vtkEnSightReader::COORDINATES: + this->UndefPartial->UndefCoordinates = val; + break; + case vtkEnSightReader::BLOCK: + this->UndefPartial->UndefBlock = val; + break; + case vtkEnSightReader::ELEMENT: + this->UndefPartial->UndefElementTypes = val; + break; + default: + vtkErrorMacro( << "Unknow section type: " << subline ); + } + return 0; //meaning 'undef', so no other steps is necesserary + } + else if ( strcmp(undefvar, "partial") == 0 ) + { + vtkDebugMacro( "partial: " << line ); + this->ReadNextDataLine( subline ); + int nLines = atoi(subline); + vtkIdType val; + int i; + switch( this->GetSectionType(line) ) + { + case vtkEnSightReader::COORDINATES: + for(i=0; iReadNextDataLine(subline); + val = atoi(subline) - 1; //EnSight start at 1 + this->UndefPartial->PartialCoordinates.push_back(val); + } + break; + case vtkEnSightReader::BLOCK: + for(i=0; iReadNextDataLine(subline); + val = atoi(subline) - 1; //EnSight start at 1 + this->UndefPartial->PartialBlock.push_back(val); + } + break; + case vtkEnSightReader::ELEMENT: + for(i=0; iReadNextDataLine(subline); + val = atoi(subline) - 1; //EnSight start at 1 + this->UndefPartial->PartialElementTypes.push_back(val); + } + break; + default: + vtkErrorMacro( << "Unknow section type: " << subline ); + } + return 1; //meaning 'partial', so other steps are necesserary + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkEnSightGoldReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkEnSightGoldReader.h b/IO/vtkEnSightGoldReader.h new file mode 100644 index 0000000..a289605 --- /dev/null +++ b/IO/vtkEnSightGoldReader.h @@ -0,0 +1,159 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightGoldReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEnSightGoldReader - class to read EnSight Gold files +// .SECTION Description +// vtkEnSightGoldReader is a class to read EnSight Gold files into vtk. +// Because the different parts of the EnSight data can be of various data +// types, this reader produces multiple outputs, one per part in the input +// file. +// All variable information is being stored in field data. The descriptions +// listed in the case file are used as the array names in the field data. +// For complex vector variables, the description is appended with _r (for the +// array of real values) and _i (for the array if imaginary values). Complex +// scalar variables are stored as a single array with 2 components, real and +// imaginary, listed in that order. +// .SECTION Caveats +// You must manually call Update on this reader and then connect the rest +// of the pipeline because (due to the nature of the file format) it is +// not possible to know ahead of time how many outputs you will have or +// what types they will be. +// This reader can only handle static EnSight datasets (both static geometry +// and variables). + +#ifndef __vtkEnSightGoldReader_h +#define __vtkEnSightGoldReader_h + +#include "vtkEnSightReader.h" + +//BTX +class UndefPartialInternal; +//ETX + +class VTK_IO_EXPORT vtkEnSightGoldReader : public vtkEnSightReader +{ +public: + static vtkEnSightGoldReader *New(); + vtkTypeRevisionMacro(vtkEnSightGoldReader, vtkEnSightReader); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkEnSightGoldReader(); + ~vtkEnSightGoldReader(); + + // Description: + // Read the geometry file. If an error occurred, 0 is returned; otherwise 1. + virtual int ReadGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read the measured geometry file. If an error occurred, 0 is returned; + // otherwise 1. + virtual int ReadMeasuredGeometryFile(const char* fileName, int timeStep); + + // Description: + // Read scalars per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one component in + // the data array, it is assumed that 0 is the first component added. + virtual int ReadScalarsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0, + int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0); + + // Description: + // Read tensors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerNode(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read scalars per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. If there will be more than one componenet in the + // data array, it is assumed that 0 is the first component added. + virtual int ReadScalarsPerElement(const char* fileName, const char* description, + int timeStep, int numberOfComponents = 1, + int component = 0); + + // Description: + // Read vectors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read tensors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerElement(const char* fileName, const char* description, + int timeStep); + + // Description: + // Read an unstructured part (partId) from the geometry file and create a + // vtkUnstructuredGrid output. Return 0 if EOF reached. Return -1 if + // an error occurred. + virtual int CreateUnstructuredGridOutput(int partId, + char line[256], + const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkStructuredGrid output. Return 0 if EOF reached. + virtual int CreateStructuredGridOutput(int partId, + char line[256], + const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkRectilinearGrid output. Return 0 if EOF reached. + int CreateRectilinearGridOutput(int partId, char line[256], const char* name); + + // Description: + // Read a structured part from the geometry file and create a + // vtkImageData output. Return 0 if EOF reached. + int CreateImageDataOutput(int partId, char line[256], const char* name); + + // Description: + // Set/Get the Model file name. + vtkSetStringMacro(GeometryFileName); + vtkGetStringMacro(GeometryFileName); + + // Description: + // Set/Get the Measured file name. + vtkSetStringMacro(MeasuredFileName); + vtkGetStringMacro(MeasuredFileName); + + // Description: + // Set/Get the Match file name. + vtkSetStringMacro(MatchFileName); + vtkGetStringMacro(MatchFileName); + + // Description: + // Skip next line in file if the 'undef' or 'partial' keyword was + // specified after a sectional keyword + int CheckForUndefOrPartial(const char *line); + + // Description: + // Handle the undef / partial support for EnSight gold + UndefPartialInternal* UndefPartial; + +private: + vtkEnSightGoldReader(const vtkEnSightGoldReader&); // Not implemented. + void operator=(const vtkEnSightGoldReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkEnSightMasterServerReader.cxx b/IO/vtkEnSightMasterServerReader.cxx new file mode 100644 index 0000000..77a6d7d --- /dev/null +++ b/IO/vtkEnSightMasterServerReader.cxx @@ -0,0 +1,190 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightMasterServerReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEnSightMasterServerReader.h" + +#include "vtkObjectFactory.h" + +#include + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkEnSightMasterServerReader, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkEnSightMasterServerReader); + +static int vtkEnSightMasterServerReaderStartsWith(const char* str1, const char* str2) +{ + if ( !str1 || !str2 || strlen(str1) < strlen(str2) ) + { + return 0; + } + return !strncmp(str1, str2, strlen(str2)); +} + +//---------------------------------------------------------------------------- +vtkEnSightMasterServerReader::vtkEnSightMasterServerReader() +{ + this->PieceCaseFileName = 0; + this->MaxNumberOfPieces = 0; + this->CurrentPiece = -1; +} + +//---------------------------------------------------------------------------- +vtkEnSightMasterServerReader::~vtkEnSightMasterServerReader() +{ + this->SetPieceCaseFileName(0); +} + +//---------------------------------------------------------------------------- +void vtkEnSightMasterServerReader::Execute() +{ + if ( !this->MaxNumberOfPieces ) + { + vtkErrorMacro("No pieces to read"); + return; + } + + if ( this->CurrentPiece < 0 || + this->CurrentPiece >= this->MaxNumberOfPieces ) + { + vtkErrorMacro("Current piece has to be set before reading the file"); + return; + } + if ( this->DetermineFileName(this->CurrentPiece) != VTK_OK ) + { + vtkErrorMacro("Cannot update piece: " << this->CurrentPiece); + return; + } + if ( !this->Reader ) + { + this->Reader = vtkGenericEnSightReader::New(); + } + this->Reader->SetCaseFileName(this->PieceCaseFileName); + if ( !this->Reader->GetFilePath() ) + { + this->Reader->SetFilePath( this->GetFilePath() ); + } + this->Superclass::Execute(); +} + +//---------------------------------------------------------------------------- +void vtkEnSightMasterServerReader::ExecuteInformation() +{ + if ( this->DetermineFileName(-1) != VTK_OK ) + { + vtkErrorMacro("Problem parsing the case file"); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkEnSightMasterServerReader::DetermineFileName(int piece) +{ + if (!this->CaseFileName) + { + vtkErrorMacro("A case file name must be specified."); + return VTK_ERROR; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += this->CaseFileName; + vtkDebugMacro("full path to case file: " << sfilename.c_str()); + } + else + { + sfilename = this->CaseFileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + char result[1024]; + + int servers = 0; + int numberservers = 0; + int currentserver = 0; + + while ( this->ReadNextDataLine(result) ) + { + if ( strcmp(result, "FORMAT") == 0 ) + { + // Format + } + else if ( strcmp(result, "SERVERS") == 0 ) + { + servers = 1; + } + else if ( servers && + vtkEnSightMasterServerReaderStartsWith(result, "number of servers:") ) + { + sscanf(result, "number of servers: %i", &numberservers); + if ( !numberservers ) + { + vtkErrorMacro("The case file is corrupted"); + break; + } + } + else if ( servers && + vtkEnSightMasterServerReaderStartsWith(result, "casefile:") ) + { + if ( currentserver == piece ) + { + char filename[1024] = ""; + sscanf(result, "casefile: %s", filename); + if ( filename[0] == 0 ) + { + vtkErrorMacro("Problem parsing file name from: " << result); + return VTK_ERROR; + } + this->SetPieceCaseFileName(filename); + break; + } + currentserver ++; + } + } + if ( piece == -1 && currentserver != numberservers ) + { + //cout << "Number of servers (" << numberservers + //<< ") is not equal to the actual number of servers (" + //<< currentserver << ")" << endl; + return VTK_ERROR; + } + + this->MaxNumberOfPieces = numberservers; + delete this->IS; + this->IS = 0; + return VTK_OK; +} + +//---------------------------------------------------------------------------- +void vtkEnSightMasterServerReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Current piece: " << this->CurrentPiece << endl; + os << indent << "Piece Case File name: " + << (this->PieceCaseFileName?this->PieceCaseFileName:"") << endl; + os << indent << "Maximum numbe of pieces: " << this->MaxNumberOfPieces + << endl; +} diff --git a/IO/vtkEnSightMasterServerReader.h b/IO/vtkEnSightMasterServerReader.h new file mode 100644 index 0000000..9f29a47 --- /dev/null +++ b/IO/vtkEnSightMasterServerReader.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightMasterServerReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEnSightMasterServerReader - reader for compund EnSight files + +#ifndef __vtkEnSightMasterServerReader_h +#define __vtkEnSightMasterServerReader_h + +#include "vtkGenericEnSightReader.h" + +class vtkCollection; + +class VTK_IO_EXPORT vtkEnSightMasterServerReader : public vtkGenericEnSightReader +{ +public: + vtkTypeRevisionMacro(vtkEnSightMasterServerReader, vtkGenericEnSightReader); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkEnSightMasterServerReader* New(); + + // Description: + // Determine which file should be read for piece + int DetermineFileName(int piece); + + // Description: + // Get the file name that will be read. + vtkGetStringMacro(PieceCaseFileName); + + // Description: + // Set or get the current piece. + vtkSetMacro(CurrentPiece, int); + vtkGetMacro(CurrentPiece, int); + +protected: + vtkEnSightMasterServerReader(); + ~vtkEnSightMasterServerReader(); + + void Execute(); + void ExecuteInformation(); + + vtkSetStringMacro(PieceCaseFileName); + char* PieceCaseFileName; + int MaxNumberOfPieces; + int CurrentPiece; + +private: + vtkEnSightMasterServerReader(const vtkEnSightMasterServerReader&); // Not implemented. + void operator=(const vtkEnSightMasterServerReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkEnSightReader.cxx b/IO/vtkEnSightReader.cxx new file mode 100644 index 0000000..82e95d4 --- /dev/null +++ b/IO/vtkEnSightReader.cxx @@ -0,0 +1,2045 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEnSightReader.h" + +#include "vtkDataArrayCollection.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkIdListCollection.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" +#include "vtkSmartPointer.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +#include +#include + +vtkCxxRevisionMacro(vtkEnSightReader, "$Revision: 1.58 $"); + +//---------------------------------------------------------------------------- +typedef vtkstd::vector< vtkSmartPointer > vtkEnSightReaderCellIdsTypeBase; +class vtkEnSightReaderCellIdsType: public vtkEnSightReaderCellIdsTypeBase {}; + +//---------------------------------------------------------------------------- +vtkEnSightReader::vtkEnSightReader() +{ + this->MeasuredFileName = NULL; + this->MatchFileName = NULL; + + this->IS = NULL; + + this->VariableMode = -1; + + this->UnstructuredPartIds = vtkIdList::New(); + this->CellIds = NULL; + + this->VariableFileNames = NULL; + this->ComplexVariableFileNames = NULL; + + this->VariableDescriptions = NULL; + this->ComplexVariableDescriptions = NULL; + + this->VariableTimeSetIds = vtkIdList::New(); + this->ComplexVariableTimeSetIds = vtkIdList::New(); + this->VariableFileSetIds = vtkIdList::New(); + this->ComplexVariableFileSetIds = vtkIdList::New(); + + this->TimeSetFileNameNumbers = vtkIdListCollection::New(); + this->TimeSetsWithFilenameNumbers = vtkIdList::New(); + this->TimeSets = vtkDataArrayCollection::New(); + this->FileSetFileNameNumbers = vtkIdListCollection::New(); + this->FileSetsWithFilenameNumbers = vtkIdList::New(); + this->FileSetNumberOfSteps = vtkIdListCollection::New(); + + this->TimeSetIds = vtkIdList::New(); + this->FileSets = vtkIdList::New(); + + this->GeometryTimeSet = 1; + this->GeometryFileSet = 1; + this->MeasuredTimeSet = 1; + this->MeasuredFileSet = 1; + + this->UseTimeSets = 0; + this->UseFileSets = 0; + + this->GeometryTimeValue = -1; + this->MeasuredTimeValue = -1; + + this->NumberOfGeometryParts = 0; + + this->NumberOfMeasuredPoints = 0; + + this->OutputsAreValid = 1; + this->InitialRead = 1; + this->NumberOfNewOutputs = 0; +} + +//---------------------------------------------------------------------------- +vtkEnSightReader::~vtkEnSightReader() +{ + int i; + + if (this->CellIds) + { + delete this->CellIds; + this->CellIds = NULL; + } + + if (this->MeasuredFileName) + { + delete [] this->MeasuredFileName; + this->MeasuredFileName = NULL; + } + if (this->MatchFileName) + { + delete [] this->MatchFileName; + this->MatchFileName = NULL; + } + + if (this->NumberOfVariables > 0) + { + for (i = 0; i < this->NumberOfVariables; i++) + { + delete [] this->VariableFileNames[i]; + } + delete [] this->VariableFileNames; + this->VariableFileNames = NULL; + } + + if (this->NumberOfComplexVariables > 0) + { + for (i = 0; i < this->NumberOfComplexVariables*2; i++) + { + delete [] this->ComplexVariableFileNames[i]; + } + delete [] this->ComplexVariableFileNames; + this->ComplexVariableFileNames = NULL; + } + + this->UnstructuredPartIds->Delete(); + this->UnstructuredPartIds = NULL; + + this->VariableTimeSetIds->Delete(); + this->VariableTimeSetIds = NULL; + this->ComplexVariableTimeSetIds->Delete(); + this->ComplexVariableTimeSetIds = NULL; + this->VariableFileSetIds->Delete(); + this->VariableFileSetIds = NULL; + this->ComplexVariableFileSetIds->Delete(); + this->ComplexVariableFileSetIds = NULL; + + this->TimeSetFileNameNumbers->Delete(); + this->TimeSetFileNameNumbers = NULL; + this->TimeSetsWithFilenameNumbers->Delete(); + this->TimeSetsWithFilenameNumbers = NULL; + this->TimeSets->Delete(); + this->TimeSets = NULL; + this->FileSetFileNameNumbers->Delete(); + this->FileSetFileNameNumbers = NULL; + this->FileSetsWithFilenameNumbers->Delete(); + this->FileSetsWithFilenameNumbers = NULL; + this->FileSetNumberOfSteps->Delete(); + this->FileSetNumberOfSteps = NULL; + + this->TimeSetIds->Delete(); + this->TimeSets = NULL; + this->FileSets->Delete(); + this->FileSets = NULL; +} + +//---------------------------------------------------------------------------- +void vtkEnSightReader::Execute() +{ + vtkDebugMacro("In execute "); + + int i, timeSet, fileSet, timeStep, timeStepInFile, fileNum; + vtkDataArray *times; + vtkIdList *numStepsList, *filenameNumbers; + float newTime; + int numSteps; + char* fileName; + int filenameNum; + + if ( ! this->CaseFileRead) + { + vtkErrorMacro("error reading case file"); + return; + } + + this->OutputsAreValid = 1; + this->NumberOfNewOutputs = 0; + this->NumberOfGeometryParts = 0; + if (this->GeometryFileName) + { + timeStep = timeStepInFile = 1; + fileNum = 1; + fileName = new char[strlen(this->GeometryFileName) + 1]; + strcpy(fileName, this->GeometryFileName); + + if (this->UseTimeSets) + { + timeSet = this->TimeSetIds->IsId(this->GeometryTimeSet); + if (timeSet >= 0) + { + times = this->TimeSets->GetItem(timeSet); + this->GeometryTimeValue = times->GetComponent(0, 0); + for (i = 1; i < times->GetNumberOfTuples(); i++) + { + newTime = times->GetComponent(i, 0); + if (newTime <= this->TimeValue && newTime > this->GeometryTimeValue) + { + this->GeometryTimeValue = newTime; + timeStep++; + timeStepInFile++; + } + } + if (this->TimeSetFileNameNumbers->GetNumberOfItems() > 0) + { + int collectionNum = this->TimeSetsWithFilenameNumbers-> + IsId(this->GeometryTimeSet); + if (collectionNum > -1) + { + filenameNumbers = + this->TimeSetFileNameNumbers->GetItem(collectionNum); + filenameNum = filenameNumbers->GetId(timeStep-1); + this->ReplaceWildcards(fileName, filenameNum); + } + } + + // There can only be file sets if there are also time sets. + if (this->UseFileSets) + { + fileSet = this->FileSets->IsId(this->GeometryFileSet); + numStepsList = (vtkIdList*)this->FileSetNumberOfSteps-> + GetItemAsObject(fileSet); + + if (timeStep > numStepsList->GetId(0)) + { + numSteps = numStepsList->GetId(0); + timeStepInFile -= numSteps; + for (i = 1; i < numStepsList->GetNumberOfIds(); i++) + { + numSteps += numStepsList->GetId(i); + if (timeStep > numSteps) + { + fileNum++; + timeStepInFile -= numStepsList->GetId(i); + } + } + } + if (this->FileSetFileNameNumbers->GetNumberOfItems() > 0) + { + int collectionNum = this->FileSetsWithFilenameNumbers-> + IsId(this->GeometryFileSet); + if (collectionNum > -1) + { + filenameNumbers = this->TimeSetFileNameNumbers-> + GetItem(collectionNum); + filenameNum = filenameNumbers->GetId(fileNum-1); + this->ReplaceWildcards(fileName, filenameNum); + } + } + } + } + } + + if (!this->ReadGeometryFile(fileName, timeStepInFile)) + { + vtkErrorMacro("error reading geometry file"); + delete [] fileName; + return; + } + + delete [] fileName; + } + if (this->MeasuredFileName) + { + timeStep = timeStepInFile = 1; + fileNum = 1; + fileName = new char[strlen(this->MeasuredFileName) + 1]; + strcpy(fileName, this->MeasuredFileName); + + if (this->UseTimeSets) + { + timeSet = this->TimeSetIds->IsId(this->MeasuredTimeSet); + if (timeSet >= 0) + { + times = this->TimeSets->GetItem(timeSet); + this->MeasuredTimeValue = times->GetComponent(0, 0); + for (i = 1; i < times->GetNumberOfTuples(); i++) + { + newTime = times->GetComponent(i, 0); + if (newTime <= this->TimeValue && newTime > this->MeasuredTimeValue) + { + this->MeasuredTimeValue = newTime; + timeStep++; + timeStepInFile++; + } + } + if (this->TimeSetFileNameNumbers->GetNumberOfItems() > 0) + { + int collectionNum = this->TimeSetsWithFilenameNumbers-> + IsId(this->MeasuredTimeSet); + if (collectionNum > -1) + { + filenameNumbers = this->TimeSetFileNameNumbers-> + GetItem(collectionNum); + filenameNum = filenameNumbers->GetId(timeStep-1); + this->ReplaceWildcards(fileName, filenameNum); + } + } + + // There can only be file sets if there are also time sets. + if (this->UseFileSets) + { + fileSet = this->FileSets->IsId(this->MeasuredFileSet); + numStepsList = (vtkIdList*)this->FileSetNumberOfSteps-> + GetItemAsObject(fileSet); + + if (timeStep > numStepsList->GetId(0)) + { + numSteps = numStepsList->GetId(0); + timeStepInFile -= numSteps; + for (i = 1; i < numStepsList->GetNumberOfIds(); i++) + { + numSteps += numStepsList->GetId(i); + if (timeStep > numSteps) + { + fileNum++; + timeStepInFile -= numStepsList->GetId(i); + } + } + } + if (this->FileSetFileNameNumbers->GetNumberOfItems() > 0) + { + int collectionNum = this->FileSetsWithFilenameNumbers-> + IsId(this->MeasuredFileSet); + if (collectionNum > -1) + { + filenameNumbers = this->TimeSetFileNameNumbers-> + GetItem(fileSet); + filenameNum = filenameNumbers->GetId(fileNum-1); + this->ReplaceWildcards(fileName, filenameNum); + } + } + } + } + } + if (!this->ReadMeasuredGeometryFile(fileName, timeStepInFile)) + { + vtkErrorMacro("error reading measured geometry file"); + delete [] fileName; + return; + } + delete [] fileName; + } + if (!this->CheckOutputConsistency()) + { + for (i = 0; i < this->NumberOfOutputs; i++) + { + this->GetOutput(i)->Initialize(); + } + return; + } + + if ((this->NumberOfVariables + this->NumberOfComplexVariables) > 0) + { + if (!this->ReadVariableFiles()) + { + vtkErrorMacro("error reading variable files"); + return; + } + } +} + +//---------------------------------------------------------------------------- +void vtkEnSightReader::Update() +{ + vtkDebugMacro("In update");; + int i; + + this->UpdateInformation(); + this->UpdateData(0); + + for (i = 0; i < this->GetNumberOfOutputs(); i++) + { + if ( this->GetOutput(i) ) + { + this->GetOutput(i)->DataHasBeenGenerated(); + this->GetOutput(i)->SetUpdateExtentToWholeExtent(); + } + } +} +//---------------------------------------------------------------------------- +void vtkEnSightReader::ExecuteInformation() +{ + vtkDebugMacro("In execute information"); + this->CaseFileRead = this->ReadCaseFile(); +} + +//---------------------------------------------------------------------------- +int vtkEnSightReader::ReadCaseFile() +{ + char line[256], formatLine[256]; + char subLine[256], subLine2[256]; + int stringRead; + int timeSet, fileSet, numTimeSteps, i, filenameNum, increment, lineRead; + float timeStep; + + // Initialize + // + if (!this->CaseFileName) + { + vtkErrorMacro("A CaseFileName must be specified."); + return 0; + } + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += this->CaseFileName; + vtkDebugMacro("full path to case file: " << sfilename.c_str()); + } + else + { + sfilename = this->CaseFileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return 0; + } + + this->TimeSets->RemoveAllItems(); + + for (i = 0; i < this->NumberOfVariables; i++) + { + delete [] this->VariableFileNames[i]; + this->VariableFileNames[i] = NULL; + delete [] this->VariableDescriptions[i]; + this->VariableDescriptions[i] = NULL; + } + delete [] this->VariableFileNames; + this->VariableFileNames = NULL; + delete [] this->VariableDescriptions; + this->VariableDescriptions = NULL; + delete [] this->VariableTypes; + this->VariableTypes = NULL; + + for (i = 0; i < this->NumberOfComplexVariables; i++) + { + delete [] this->ComplexVariableFileNames[2*i]; + this->ComplexVariableFileNames[2*i] = NULL; + delete [] this->ComplexVariableFileNames[2*i+1]; + this->ComplexVariableFileNames[2*i+1] = NULL; + delete [] this->ComplexVariableDescriptions[i]; + this->ComplexVariableDescriptions[i] = NULL; + } + delete [] this->ComplexVariableFileNames; + this->ComplexVariableFileNames = NULL; + delete [] this->ComplexVariableDescriptions; + this->ComplexVariableDescriptions = NULL; + delete [] this->ComplexVariableTypes; + this->ComplexVariableTypes = NULL; + + this->NumberOfVariables = 0; + this->NumberOfComplexVariables = 0; + + this->ReadNextDataLine(line); + + if (strncmp(line, "FORMAT", 6) == 0) + { + // found the FORMAT section + vtkDebugMacro("*** FORMAT section"); + this->ReadNextDataLine(line); + + stringRead = sscanf(line, " %*s %*s %s", subLine); + if (stringRead == 1) + { + if (strcmp(subLine, "gold") == 0 && + strcmp(this->GetClassName(), "vtkEnSight6Reader") == 0) + { + // The class is vtkEnSight6Reader, but the case file says "gold". + vtkErrorMacro("This is not an EnSight6 file."); + delete this->IS; + this->IS = NULL; + return 0; + } + } + else + { + if (strcmp(this->GetClassName(), "vtkEnSightGoldReader") == 0) + { + // The class is vtkEnSightGoldReader, but the case file does + // not say "gold". + vtkErrorMacro("This is not an EnSight Gold file."); + delete this->IS; + this->IS = NULL; + return 0; + } + } + } + + // We know how many lines to read in the FORMAT section, so we haven't read + // the "GEOMETRY" line yet. + this->ReadNextDataLine(line); + if (strncmp(line, "GEOMETRY", 8) == 0) + { + // found the GEOMETRY section + vtkDebugMacro("*** GEOMETRY section"); + + // There will definitely be a "model" line. There may also be "measured" + // and "match" lines. + while(this->ReadNextDataLine(line) != 0 && + strncmp(line, "m", 1) == 0) + { + if (strncmp(line, "model:", 6) == 0) + { + if (sscanf(line, " %*s %d%*[ \t]%d%*[ \t]%s", &timeSet, &fileSet, subLine) == 3) + { + this->GeometryTimeSet = timeSet; + this->GeometryFileSet = fileSet; + this->SetGeometryFileName(subLine); + vtkDebugMacro(<GetGeometryFileName()); + } + else if (sscanf(line, " %*s %d%*[ \t]%s", &timeSet, subLine) == 2) + { + this->GeometryTimeSet = timeSet; + this->SetGeometryFileName(subLine); + vtkDebugMacro(<GetGeometryFileName()); + } + else if (sscanf(line, " %*s %s", subLine) == 1) + { + this->SetGeometryFileName(subLine); + vtkDebugMacro(<GetGeometryFileName()); + } + } + else if (strncmp(line, "measured:", 9) == 0) + { + if (sscanf(line, " %*s %d%*[ \t]%d%*[ \t]%s", &timeSet, &fileSet, subLine) == 3) + { + this->MeasuredTimeSet = timeSet; + this->MeasuredFileSet = fileSet; + this->SetMeasuredFileName(subLine); + vtkDebugMacro(<< this->GetMeasuredFileName()); + } + else if (sscanf(line, " %*s %d%*[ \t]%s", &timeSet, subLine) == 2) + { + this->MeasuredTimeSet = timeSet; + this->SetMeasuredFileName(subLine); + vtkDebugMacro(<< this->GetMeasuredFileName()); + } + else if (sscanf(line, " %*s %s", subLine) == 1) + { + this->SetMeasuredFileName(subLine); + vtkDebugMacro(<< this->GetMeasuredFileName()); + } + } + else if (strncmp(line, "match:", 6) == 0) + { + sscanf(line, " %*s %s", subLine); + this->SetMatchFileName(subLine); + vtkDebugMacro(<< this->GetMatchFileName()); + } + } + } + + if (strncmp(line, "VARIABLE", 8) == 0) + { + // found the VARIABLE section + vtkDebugMacro(<< "*** VARIABLE section"); + + this->NumberOfScalarsPerNode = 0; + this->NumberOfVectorsPerNode = 0; + this->NumberOfTensorsSymmPerNode = 0; + this->NumberOfScalarsPerElement = 0; + this->NumberOfVectorsPerElement = 0; + this->NumberOfTensorsSymmPerElement = 0; + this->NumberOfScalarsPerMeasuredNode = 0; + this->NumberOfVectorsPerMeasuredNode = 0; + this->NumberOfComplexScalarsPerNode = 0; + this->NumberOfComplexVectorsPerNode = 0; + this->NumberOfComplexScalarsPerElement = 0; + this->NumberOfComplexVectorsPerElement = 0; + + while(this->ReadNextDataLine(line) != 0 && + strncmp(line, "TIME", 4) != 0 && + strncmp(line, "FILE", 4) != 0) + { + if (strncmp(line, "constant", 8) == 0) + { + vtkDebugMacro(<< line); + } + else if (strncmp(line, "scalar", 6) == 0) + { + sscanf(line, " %*s %*s %s", subLine); + if (strcmp(subLine, "node:") == 0) + { + vtkDebugMacro("scalar per node"); + this->VariableMode = vtkEnSightReader::SCALAR_PER_NODE; + if (sscanf(line, " %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %d %s", &timeSet, subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfScalarsPerNode++; + } + else if (strcmp(subLine, "element:") == 0) + { + vtkDebugMacro("scalar per element"); + this->VariableMode = vtkEnSightReader::SCALAR_PER_ELEMENT; + if (sscanf(line, " %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %d %s", &timeSet, subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfScalarsPerElement++; + } + else if (strcmp(subLine, "measured") == 0) + { + vtkDebugMacro("scalar per measured node"); + this->VariableMode = vtkEnSightReader::SCALAR_PER_MEASURED_NODE; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfScalarsPerMeasuredNode++; + } + this->AddVariableFileName(subLine); + this->NumberOfVariables++; + } + else if (strncmp(line, "vector", 6) == 0) + { + sscanf(line, " %*s %*s %s", subLine); + if (strcmp(subLine, "node:") == 0) + { + vtkDebugMacro("vector per node"); + this->VariableMode = vtkEnSightReader::VECTOR_PER_NODE; + if (sscanf(line, " %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %d %s", &timeSet, subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfVectorsPerNode++; + } + else if (strcmp(subLine, "element:") == 0) + { + vtkDebugMacro("vector per element"); + this->VariableMode = vtkEnSightReader::VECTOR_PER_ELEMENT; + if (sscanf(line, " %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %d %s", &timeSet, subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfVectorsPerElement++; + } + else if (strcmp(subLine, "measured") == 0) + { + vtkDebugMacro("vector per measured node"); + this->VariableMode = vtkEnSightReader::VECTOR_PER_MEASURED_NODE; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfVectorsPerMeasuredNode++; + } + this->AddVariableFileName(subLine); + this->NumberOfVariables++; + } + else if (strncmp(line, "tensor", 6) == 0) + { + // According to EnSight documentation tensor entry should be of the form: + // tensor symm per node/element + // but it seems like you can also find: + // tensor per node/element + // Let handle this case here: + char symm[10]; + char per[10]; + if( sscanf(line, " %*s %s %s %s", symm, per, subLine) != 3 ) + { + vtkErrorMacro( "Error while reading: " << line ); + } + if (!(strcmp(symm, "symm") == 0 && strcmp(per, "per") == 0)) + { + if( sscanf(line, " %*s %s %s", per, subLine) != 2 ) + { + vtkErrorMacro( "Error while reading: " << line ); + } + if (strcmp(per, "per") == 0) + { + //Not valid file but seems alright, only 'symm' is missing + vtkWarningMacro( "Looks almost like a valid case file, continuing" ); + } + else + { + vtkErrorMacro("Trouble reading: " << line ); + } + } + if (strcmp(subLine, "node:") == 0) + { + vtkDebugMacro("tensor symm per node"); + this->VariableMode = vtkEnSightReader::TENSOR_SYMM_PER_NODE; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfTensorsSymmPerNode++; + } + else if (strcmp(subLine, "element:") == 0) + { + vtkDebugMacro("tensor symm per element"); + this->VariableMode = vtkEnSightReader::TENSOR_SYMM_PER_ELEMENT; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->VariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->VariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s", subLine); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->VariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s", subLine); + } + this->AddVariableType(); + this->NumberOfTensorsSymmPerElement++; + } + else + { + vtkErrorMacro("Unknow type, faulty line was:" << line ); + } + this->AddVariableFileName(subLine); + this->NumberOfVariables++; + } + else if (strncmp(line, "complex", 6) == 0) + { + sscanf(line, " %*s %s", subLine); + if (strcmp(subLine, "scalar") == 0) + { + sscanf(line, " %*s %*s %*s %s", subLine); + if (strcmp(subLine, "node:") == 0) + { + vtkDebugMacro("complex scalar per node"); + this->VariableMode = vtkEnSightReader::COMPLEX_SCALAR_PER_NODE; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->ComplexVariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->ComplexVariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s %s", subLine, subLine2); + } + this->AddVariableType(); + this->NumberOfComplexScalarsPerNode++; + } + else if (strcmp(subLine, "element:") == 0) + { + vtkDebugMacro("complex scalar per element"); + this->VariableMode = vtkEnSightReader::COMPLEX_SCALAR_PER_ELEMENT; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->ComplexVariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->ComplexVariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s %s", subLine, subLine2); + } + this->AddVariableType(); + this->NumberOfComplexScalarsPerElement++; + } + } + else if (strcmp(subLine, "vector") == 0) + { + sscanf(line, " %*s %*s %*s %s", subLine); + if (strcmp(subLine, "node:") == 0) + { + vtkDebugMacro("complex vector per node"); + this->VariableMode = vtkEnSightReader::COMPLEX_VECTOR_PER_NODE; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->ComplexVariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->ComplexVariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s %s", subLine, subLine2); + } + this->AddVariableType(); + this->NumberOfComplexVectorsPerNode++; + } + else if (strcmp(subLine, "element:") == 0) + { + vtkDebugMacro("complex vector per element"); + this->VariableMode = vtkEnSightReader::COMPLEX_VECTOR_PER_ELEMENT; + if (sscanf(line, " %*s %*s %*s %*s %d %d %s", &timeSet, &fileSet, + subLine) == 3) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->ComplexVariableFileSetIds->InsertNextId(fileSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %d %s", &timeSet, + subLine) == 2) + { + this->ComplexVariableTimeSetIds->InsertNextId(timeSet); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*d %*s %s %s", subLine, + subLine2); + } + else if (sscanf(line, " %*s %*s %*s %*s %s", subLine) == 1) + { + this->ComplexVariableTimeSetIds->InsertNextId(1); + this->AddVariableDescription(subLine); + sscanf(line, " %*s %*s %*s %*s %*s %s %s", subLine, subLine2); + } + this->AddVariableType(); + this->NumberOfComplexVectorsPerElement++; + } + } + this->AddVariableFileName(subLine, subLine2); + this->NumberOfComplexVariables++; + } + else + { + vtkErrorMacro("invalid VARIABLE line: " << line); + delete this->IS; + this->IS = NULL; + return 0; + } + } + } + + if (strncmp(line, "TIME", 4) == 0) + { + // found TIME section + int firstTimeStep = 1; + + this->UseTimeSetsOn(); + while(this->ReadNextDataLine(line) != 0 && + strncmp(line, "FILE", 4) != 0) + { + sscanf(line, "%*s %*s %d", &timeSet); + this->TimeSetIds->InsertNextId(timeSet); + this->ReadNextDataLine(line); + sscanf(line, "%*s %*s %*s %d", &numTimeSteps); + this->ReadNextDataLine(line); + if (strncmp(line, "filename", 8) == 0) + { + vtkIdList *filenameNumbers = vtkIdList::New(); + this->TimeSetsWithFilenameNumbers->InsertNextId(timeSet); + sscanf(line, "%*s %s", subLine); + if (strncmp(subLine, "numbers", 7) == 0) + { + strcpy(formatLine, "%*s %*s"); + strcpy(subLine, "%*s %*s"); + for (i = 0; i < numTimeSteps; i++) + { + strcat(formatLine, " %d"); + sscanf(line, formatLine, &filenameNum); + filenameNumbers->InsertNextId(filenameNum); + strcat(subLine, " %*d"); + strcpy(formatLine, subLine); + } + } + else + { + sscanf(line, "%*s %*s %*s %d", &filenameNum); + this->ReadNextDataLine(line); + sscanf(line, "%*s %*s %d", &increment); + for (i = 0; i < numTimeSteps; i++) + { + filenameNumbers->InsertNextId(filenameNum + i*increment); + } + } + this->TimeSetFileNameNumbers->AddItem(filenameNumbers); + filenameNumbers->Delete(); + this->ReadLine(line); + } + vtkFloatArray *timeValues = vtkFloatArray::New(); + timeValues->SetNumberOfComponents(1); + timeValues->SetNumberOfTuples(numTimeSteps); + strcpy(formatLine, "%*s %*s"); + strcpy(subLine, "%*s %*s"); + for (i = 0; i < numTimeSteps; i++) + { + strcat(formatLine, " %f"); + if (sscanf(line, formatLine, &timeStep) != 1) + { + this->ReadNextDataLine(line); + strcpy(formatLine, " %f"); + strcpy(subLine, ""); + sscanf(line, formatLine, &timeStep); + } + if (firstTimeStep) + { + this->MinimumTimeValue = timeStep; + this->MaximumTimeValue = timeStep; + firstTimeStep = 0; + // Set this as default TimeValue. + if(!this->TimeValueInitialized) + { + this->SetTimeValue(timeStep); + } + } + else + { + if (timeStep < this->MinimumTimeValue) + { + this->MinimumTimeValue = timeStep; + } + else if (timeStep > this->MaximumTimeValue) + { + this->MaximumTimeValue = timeStep; + } + } + timeValues->SetComponent(i, 0, timeStep); + strcat(subLine, " %*f"); + strcpy(formatLine, subLine); + } + this->TimeSets->AddItem(timeValues); + timeValues->Delete(); + } + } + + if (strncmp(line, "FILE", 4) == 0) + { + // found FILE section + this->UseFileSetsOn(); + lineRead = this->ReadNextDataLine(line); + while (lineRead != 0) + { + vtkIdList *filenameNums = vtkIdList::New(); + vtkIdList *numSteps = vtkIdList::New(); + sscanf(line, "%*s %*s %d", &fileSet); + this->FileSets->InsertNextId(fileSet); + lineRead = this->ReadNextDataLine(line); + if (strncmp(line, "filename", 8) == 0) + { + this->FileSetsWithFilenameNumbers->InsertNextId(fileSet); + while (lineRead != 0 && strncmp(line, "filename", 8) == 0) + { + sscanf(line, "%*s %*s %d", &filenameNum); + filenameNums->InsertNextId(filenameNum); + this->ReadNextDataLine(line); + sscanf(line, "%*s %*s %*s %d", &numTimeSteps); + numSteps->InsertNextId(numTimeSteps); + lineRead = this->ReadNextDataLine(line); + } + this->FileSetFileNameNumbers->AddItem(filenameNums); + } + else + { + sscanf(line, "%*s %*s %*s %d", &numTimeSteps); + numSteps->InsertNextId(numTimeSteps); + lineRead = this->ReadNextDataLine(line); + } + + this->FileSetNumberOfSteps->AddItem(numSteps); + + filenameNums->Delete(); + numSteps->Delete(); + } + } + + delete this->IS; + this->IS = NULL; + + // Fill data array selection objects with these arrays. + this->SetDataArraySelectionSetsFromVariables(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkEnSightReader::ReadVariableFiles() +{ + int i, j; + char description[256]; + int timeSet, fileSet, timeStep, timeStepInFile, numSteps; + vtkDataArray *times; + float newTime; + vtkIdList *numStepsList, *filenameNumbers; + //int fileNum; + int validTime, filenameNum; + char* fileName, *fileName2; + + for (i = 0; i < this->NumberOfVariables; i++) + { + switch (this->VariableTypes[i]) + { + case SCALAR_PER_NODE: + case VECTOR_PER_NODE: + case TENSOR_SYMM_PER_NODE: + case SCALAR_PER_MEASURED_NODE: + case VECTOR_PER_MEASURED_NODE: + if(!this->GetPointArrayStatus(this->VariableDescriptions[i])) + { + continue; + } + break; + case SCALAR_PER_ELEMENT: + case VECTOR_PER_ELEMENT: + case TENSOR_SYMM_PER_ELEMENT: + if(!this->GetCellArrayStatus(this->VariableDescriptions[i])) + { + continue; + } + break; + } + + timeStep = 0; + timeStepInFile = 1; + //fileNum = 1; + validTime = 1; + fileName = new char[strlen(this->VariableFileNames[i]) + 1]; + strcpy(fileName, this->VariableFileNames[i]); + if (this->UseTimeSets) + { + validTime = 0; + timeSet = this->VariableTimeSetIds->GetId(i); + times = this->TimeSets->GetItem(this->TimeSetIds->IsId(timeSet)); + for (j = 0; j < times->GetNumberOfTuples(); j++) + { + newTime = times->GetComponent(j, 0); + if (newTime <= this->TimeValue) + { + timeStep++; + if (this->VariableTypes[i] == SCALAR_PER_MEASURED_NODE || + this->VariableTypes[i] == VECTOR_PER_MEASURED_NODE) + { + if (newTime >= this->MeasuredTimeValue || + this->MeasuredTimeSet == -1) + { + validTime = 1; + } + } + else if (newTime >= this->GeometryTimeValue || + this->GeometryTimeSet == -1) + { + validTime = 1; + } + } + } + if (this->TimeSetFileNameNumbers->GetNumberOfItems() > 0 && + validTime) + { + int collectionNum = this->TimeSetsWithFilenameNumbers->IsId(timeSet); + if (collectionNum > -1) + { + filenameNumbers = this->TimeSetFileNameNumbers-> + GetItem(collectionNum); + filenameNum = filenameNumbers->GetId(timeStep-1); + this->ReplaceWildcards(fileName, filenameNum); + } + } + + // There can only be file sets if there are also time sets. + if (this->UseFileSets) + { + timeStepInFile = timeStep; + fileSet = this->VariableFileSetIds->GetId(i); + numStepsList = (vtkIdList*)this->FileSetNumberOfSteps-> + GetItemAsObject(this->FileSets->IsId(fileSet)); + + if (timeStep > numStepsList->GetId(0)) + { + numSteps = numStepsList->GetId(0); + timeStepInFile -= numSteps; + for (i = 1; i < numStepsList->GetNumberOfIds(); i++) + { + numSteps += numStepsList->GetId(i); + if (timeStep > numSteps) + { + //fileNum++; + timeStepInFile -= numStepsList->GetId(i); + } + } + } + if (this->FileSetFileNameNumbers->GetNumberOfItems() > 0 && + validTime) + { + int collectionNum = this->FileSetsWithFilenameNumbers->IsId(fileSet); + if (collectionNum > -1) + { + filenameNumbers = this->TimeSetFileNameNumbers-> + GetItem(collectionNum); + filenameNum = filenameNumbers->GetId(timeStep-1); + this->ReplaceWildcards(fileName, filenameNum); + } + } + } + } + + if (validTime) + { + switch (this->VariableTypes[i]) + { + case vtkEnSightReader::SCALAR_PER_NODE: + this->ReadScalarsPerNode(fileName, this->VariableDescriptions[i], + timeStepInFile); + break; + case vtkEnSightReader::SCALAR_PER_MEASURED_NODE: + this->ReadScalarsPerNode(fileName, this->VariableDescriptions[i], + timeStepInFile, 1); + break; + case vtkEnSightReader::VECTOR_PER_NODE: + this->ReadVectorsPerNode(fileName, this->VariableDescriptions[i], + timeStepInFile); + break; + case vtkEnSightReader::VECTOR_PER_MEASURED_NODE: + this->ReadVectorsPerNode(fileName, this->VariableDescriptions[i], + timeStepInFile, 1); + break; + case vtkEnSightReader::TENSOR_SYMM_PER_NODE: + this->ReadTensorsPerNode(fileName, this->VariableDescriptions[i], + timeStepInFile); + break; + case vtkEnSightReader::SCALAR_PER_ELEMENT: + this->ReadScalarsPerElement(fileName, this->VariableDescriptions[i], + timeStepInFile); + break; + case vtkEnSightReader::VECTOR_PER_ELEMENT: + this->ReadVectorsPerElement(fileName, this->VariableDescriptions[i], + timeStepInFile); + break; + case vtkEnSightReader::TENSOR_SYMM_PER_ELEMENT: + this->ReadTensorsPerElement(fileName, this->VariableDescriptions[i], + timeStepInFile); + break; + } + } + delete [] fileName; + } + for (i = 0; i < this->NumberOfComplexVariables; i++) + { + switch(this->ComplexVariableTypes[i]) + { + case COMPLEX_SCALAR_PER_NODE: + case COMPLEX_VECTOR_PER_NODE: + if(!this->GetPointArrayStatus(this->ComplexVariableDescriptions[i])) + { + continue; + } + break; + case COMPLEX_SCALAR_PER_ELEMENT: + case COMPLEX_VECTOR_PER_ELEMENT: + if(!this->GetCellArrayStatus(this->ComplexVariableDescriptions[i])) + { + continue; + } + break; + } + timeStep = 0; + timeStepInFile = 1; + //fileNum = 1; + validTime = 1; + fileName = new char[strlen(this->ComplexVariableFileNames[2*i]) + 1]; + strcpy(fileName, this->ComplexVariableFileNames[2*i]); + fileName2 = new char[strlen(this->ComplexVariableFileNames[2*i+1]) + 1]; + strcpy(fileName2, this->ComplexVariableFileNames[2*i+1]); + if (this->UseTimeSets) + { + validTime = 0; + timeSet = this->VariableTimeSetIds->GetId(i); + times = this->TimeSets->GetItem(this->TimeSetIds->IsId(timeSet)); + for (j = 0; j < times->GetNumberOfTuples(); j++) + { + newTime = times->GetComponent(j, 0); + if (newTime <= this->TimeValue) + { + timeStep++; + if (this->VariableTypes[i] == SCALAR_PER_MEASURED_NODE || + this->VariableTypes[i] == VECTOR_PER_MEASURED_NODE) + { + if (newTime >= this->MeasuredTimeValue) + { + validTime = 1; + } + } + else if (newTime >= this->GeometryTimeValue) + { + validTime = 1; + } + } + } + if (this->TimeSetFileNameNumbers->GetNumberOfItems() > 0 && + validTime) + { + int collectionNum = this->TimeSetsWithFilenameNumbers->IsId(timeSet); + if (collectionNum > -1) + { + filenameNumbers = this->TimeSetFileNameNumbers-> + GetItem(collectionNum); + filenameNum = filenameNumbers->GetId(timeStep-1); + this->ReplaceWildcards(fileName, filenameNum); + this->ReplaceWildcards(fileName2, filenameNum); + } + } + + // There can only be file sets if there are also time sets. + if (this->UseFileSets) + { + timeStepInFile = timeStep; + fileSet = this->VariableFileSetIds->GetId(i); + numStepsList = (vtkIdList*)this->FileSetNumberOfSteps-> + GetItemAsObject(this->FileSets->IsId(fileSet)); + + if (timeStep > numStepsList->GetId(0)) + { + numSteps = numStepsList->GetId(0); + timeStepInFile -= numSteps; + for (i = 1; i < numStepsList->GetNumberOfIds(); i++) + { + numSteps += numStepsList->GetId(i); + if (timeStep > numSteps) + { + //fileNum++; + timeStepInFile -= numStepsList->GetId(i); + } + } + } + if (this->FileSetFileNameNumbers->GetNumberOfItems() > 0 && + validTime) + { + int collectionNum = this->FileSetsWithFilenameNumbers->IsId(fileSet); + if (collectionNum > -1) + { + filenameNumbers = this->FileSetFileNameNumbers-> + GetItem(collectionNum); + filenameNum = filenameNumbers->GetId(timeStep-1); + this->ReplaceWildcards(fileName, filenameNum); + this->ReplaceWildcards(fileName2, filenameNum); + } + } + } + } + + if (validTime) + { + switch (this->ComplexVariableTypes[i]) + { + case vtkEnSightReader::COMPLEX_SCALAR_PER_NODE: + this->ReadScalarsPerNode(fileName, + this->ComplexVariableDescriptions[i], + timeStepInFile, 0, 2); + this->ReadScalarsPerNode(fileName2, + this->ComplexVariableDescriptions[i], + timeStepInFile, 0, 2, 1); + break; + case vtkEnSightReader::COMPLEX_VECTOR_PER_NODE: + strcpy(description, this->ComplexVariableDescriptions[i]); + strcat(description, "_r"); + this->ReadVectorsPerNode(fileName, description, timeStepInFile); + strcpy(description, this->ComplexVariableDescriptions[i]); + strcat(description, "_i"); + this->ReadVectorsPerNode(fileName2, description, timeStepInFile); + break; + case vtkEnSightReader::COMPLEX_SCALAR_PER_ELEMENT: + this->ReadScalarsPerElement(fileName, + this->ComplexVariableDescriptions[i], + timeStepInFile, 2); + this->ReadScalarsPerElement(fileName2, + this->ComplexVariableDescriptions[i], + timeStepInFile, 2, 1); + break; + case vtkEnSightReader::COMPLEX_VECTOR_PER_ELEMENT: + strcpy(description, this->ComplexVariableDescriptions[i]); + strcat(description, "_r"); + this->ReadVectorsPerElement(fileName, description, timeStepInFile); + strcpy(description, this->ComplexVariableDescriptions[i]); + strcat(description, "_i"); + this->ReadVectorsPerElement(fileName2, description, timeStepInFile); + break; + } + } + delete [] fileName; + delete [] fileName2; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkEnSightReader::AddVariableFileName(const char* fileName1, + const char* fileName2) +{ + int size; + int i; + + if (this->VariableMode < 8) + { + size = this->NumberOfVariables; + + char** newFileNameList = new char *[size]; // temporary array + + // copy file names to temporary array + for (i = 0; i < size; i++) + { + newFileNameList[i] = new char[strlen(this->VariableFileNames[i]) + 1]; + strcpy(newFileNameList[i], this->VariableFileNames[i]); + delete [] this->VariableFileNames[i]; + } + delete [] this->VariableFileNames; + + // make room for new file name + this->VariableFileNames = new char *[size+1]; + + // copy existing file names back to first array + for (i = 0; i < size; i++) + { + this->VariableFileNames[i] = new char[strlen(newFileNameList[i]) + 1]; + strcpy(this->VariableFileNames[i], newFileNameList[i]); + delete [] newFileNameList[i]; + } + delete [] newFileNameList; + + // add new file name at end of first array + this->VariableFileNames[size] = new char[strlen(fileName1) + 1]; + strcpy(this->VariableFileNames[size], fileName1); + vtkDebugMacro( << "file name: " << this->VariableFileNames[size]); + } + else + { + size = this->NumberOfComplexVariables; + + char** newFileNameList = new char *[2 * size]; // temporary array + + // copy file names to temporary array + for (i = 0; i < 2*size; i++) + { + newFileNameList[i] = + new char[strlen(this->ComplexVariableFileNames[i]) + 1]; + strcpy(newFileNameList[i], this->ComplexVariableFileNames[i]); + delete [] this->ComplexVariableFileNames[i]; + } + delete [] this->ComplexVariableFileNames; + + // make room for new file name + this->ComplexVariableFileNames = new char *[2*(size+1)]; + + // copy existing file names back to first array + for (i = 0; i < 2*size; i++) + { + this->ComplexVariableFileNames[i] = + new char[strlen(newFileNameList[i]) + 1]; + strcpy(this->ComplexVariableFileNames[i], newFileNameList[i]); + delete [] newFileNameList[i]; + } + delete [] newFileNameList; + + // add new file name at end of first array + this->ComplexVariableFileNames[2*size] = new char[strlen(fileName1) + 1]; + strcpy(this->ComplexVariableFileNames[2*size], fileName1); + vtkDebugMacro("real file name: " + << this->ComplexVariableFileNames[2*size]); + this->ComplexVariableFileNames[2*size+1] = new char[strlen(fileName2) + 1]; + strcpy(this->ComplexVariableFileNames[2*size+1], fileName2); + vtkDebugMacro("imag. file name: " + << this->ComplexVariableFileNames[2*size+1]); + } +} + +//---------------------------------------------------------------------------- +void vtkEnSightReader::AddVariableDescription(const char* description) +{ + int size; + int i; + + if (this->VariableMode < 8) + { + size = this->NumberOfVariables; + + char ** newDescriptionList = new char *[size]; // temporary array + + // copy descriptions to temporary array + for (i = 0; i < size; i++) + { + newDescriptionList[i] = + new char[strlen(this->VariableDescriptions[i]) + 1]; + strcpy(newDescriptionList[i], this->VariableDescriptions[i]); + delete [] this->VariableDescriptions[i]; + } + delete [] this->VariableDescriptions; + + // make room for new description + this->VariableDescriptions = new char *[size+1]; + + // copy existing descriptions back to first array + for (i = 0; i < size; i++) + { + this->VariableDescriptions[i] = + new char[strlen(newDescriptionList[i]) + 1]; + strcpy(this->VariableDescriptions[i], newDescriptionList[i]); + delete [] newDescriptionList[i]; + } + delete [] newDescriptionList; + + // add new description at end of first array + this->VariableDescriptions[size] = new char[strlen(description) + 1]; + strcpy(this->VariableDescriptions[size], description); + vtkDebugMacro("description: " << this->VariableDescriptions[size]); + } + else + { + size = this->NumberOfComplexVariables; + + char ** newDescriptionList = new char *[size]; // temporary array + + // copy descriptions to temporary array + for (i = 0; i < size; i++) + { + newDescriptionList[i] = + new char[strlen(this->ComplexVariableDescriptions[i]) + 1]; + strcpy(newDescriptionList[i], this->ComplexVariableDescriptions[i]); + delete [] this->ComplexVariableDescriptions[i]; + } + delete [] this->ComplexVariableDescriptions; + + // make room for new description + this->ComplexVariableDescriptions = new char *[size+1]; + + // copy existing descriptions back to first array + for (i = 0; i < size; i++) + { + this->ComplexVariableDescriptions[i] = + new char[strlen(newDescriptionList[i]) + 1]; + strcpy(this->ComplexVariableDescriptions[i], newDescriptionList[i]); + delete [] newDescriptionList[i]; + } + delete [] newDescriptionList; + + // add new description at end of first array + this->ComplexVariableDescriptions[size] = + new char[strlen(description) + 1]; + strcpy(this->ComplexVariableDescriptions[size], description); + vtkDebugMacro("description: " + << this->ComplexVariableDescriptions[size]); + } +} + +//---------------------------------------------------------------------------- +void vtkEnSightReader::AddVariableType() +{ + int size; + int i; + int *types = NULL; + + // Figure out what the size of the variable type array is. + if (this->VariableMode < 8) + { + size = this->NumberOfVariables; + + types = new int[size]; + + for (i = 0; i < size; i++) + { + types[i] = this->VariableTypes[i]; + } + delete [] this->VariableTypes; + + this->VariableTypes = new int[size+1]; + for (i = 0; i < size; i++) + { + this->VariableTypes[i] = types[i]; + } + delete [] types; + this->VariableTypes[size] = this->VariableMode; + vtkDebugMacro("variable type: " << this->VariableTypes[size]); + } + else + { + size = this->NumberOfComplexVariables; + + if (size > 0) + { + types = new int[size]; + for (i = 0; i < size; i++) + { + types[i] = this->ComplexVariableTypes[i]; + } + delete [] this->ComplexVariableTypes; + } + + this->ComplexVariableTypes = new int[size+1]; + for (i = 0; i < size; i++) + { + this->ComplexVariableTypes[i] = types[i]; + } + + if (size > 0) + { + delete [] types; + } + this->ComplexVariableTypes[size] = this->VariableMode; + vtkDebugMacro("complex variable type: " + << this->ComplexVariableTypes[size]); + } +} + +//---------------------------------------------------------------------------- +int vtkEnSightReader::GetSectionType(const char *line) +{ + if (strncmp(line, "coordinates", 5) == 0) + { + return vtkEnSightReader::COORDINATES; + } + else if (strncmp(line, "block", 4) == 0) + { + return vtkEnSightReader::BLOCK; + } + else if (this->GetElementType(line) != -1) + { + return vtkEnSightReader::ELEMENT; + } + else + { + return -1; + } +} + +//---------------------------------------------------------------------------- +int vtkEnSightReader::GetElementType(const char* line) +{ + if (strncmp(line, "point", 5) == 0) + { + return vtkEnSightReader::POINT; + } + else if (strncmp(line, "bar2", 4) == 0) + { + return vtkEnSightReader::BAR2; + } + else if (strncmp(line, "bar3", 4) == 0) + { + return vtkEnSightReader::BAR3; + } + else if (strncmp(line, "nsided", 6) == 0) + { + return vtkEnSightReader::NSIDED; + } + else if (strncmp(line, "tria3", 5) == 0) + { + return vtkEnSightReader::TRIA3; + } + else if (strncmp(line, "tria6", 5) == 0) + { + return vtkEnSightReader::TRIA6; + } + else if (strncmp(line, "quad4", 5) == 0) + { + return vtkEnSightReader::QUAD4; + } + else if (strncmp(line, "quad8", 5) == 0) + { + return vtkEnSightReader::QUAD8; + } + else if (strncmp(line, "tetra4", 6) == 0) + { + return vtkEnSightReader::TETRA4; + } + else if (strncmp(line, "tetra10", 7) == 0) + { + return vtkEnSightReader::TETRA10; + } + else if (strncmp(line, "pyramid5", 8) == 0) + { + return vtkEnSightReader::PYRAMID5; + } + else if (strncmp(line, "pyramid13", 9) == 0) + { + return vtkEnSightReader::PYRAMID13; + } + else if (strncmp(line, "hexa8", 5) == 0) + { + return vtkEnSightReader::HEXA8; + } + else if (strncmp(line, "hexa20", 6) == 0) + { + return vtkEnSightReader::HEXA20; + } + else if (strncmp(line, "penta6", 6) == 0) + { + return vtkEnSightReader::PENTA6; + } + else if (strncmp(line, "penta15", 7) == 0) + { + return vtkEnSightReader::PENTA15; + } + else + { + return -1; + } +} + +void vtkEnSightReader::ReplaceWildcards(char* filename, int num) +{ + int wildcardPos, numWildcards, numDigits = 1, i; + int tmpNum = num, multTen = 1; + char newChar; + int newNum; + + wildcardPos = static_cast(strcspn(filename, "*")); + numWildcards = static_cast(strspn(filename + wildcardPos, "*")); + + if (numWildcards == 0) + { + return; + } + + tmpNum /= 10; + while (tmpNum >= 1) + { + numDigits++; + multTen *= 10; + tmpNum /= 10; + } + + for (i = 0; i < numWildcards - numDigits; i++) + { + filename[i + wildcardPos] = '0'; + } + + tmpNum = num; + for (i = numWildcards - numDigits; i < numWildcards; i++) + { + newNum = tmpNum / multTen; + switch (newNum) + { + case 0: + newChar = '0'; + break; + case 1: + newChar = '1'; + break; + case 2: + newChar = '2'; + break; + case 3: + newChar = '3'; + break; + case 4: + newChar = '4'; + break; + case 5: + newChar = '5'; + break; + case 6: + newChar = '6'; + break; + case 7: + newChar = '7'; + break; + case 8: + newChar = '8'; + break; + case 9: + newChar = '9'; + break; + default: + // This case should never be reached. + return; + } + + filename[i + wildcardPos] = newChar; + tmpNum -= multTen * newNum; + multTen /= 10; + } +} + +//---------------------------------------------------------------------------- +// Called by constructor to set up output array. +void vtkEnSightReader::SetNumberOfOutputsInternal(int num) +{ + int idx; + vtkDataObject **outputs; + + // in case nothing has changed. + if (num == this->NumberOfOutputs) + { + return; + } + + // Allocate new arrays. + outputs = new vtkDataObject *[num]; + + // Initialize with NULLs. + for (idx = 0; idx < num; ++idx) + { + outputs[idx] = NULL; + } + + // Copy old outputs + for (idx = 0; idx < num && idx < this->NumberOfOutputs; ++idx) + { + outputs[idx] = this->Outputs[idx]; + } + + // delete the previous arrays + if (this->Outputs) + { + delete [] this->Outputs; + this->Outputs = NULL; + this->NumberOfOutputs = 0; + } + + // Set the new arrays + this->Outputs = outputs; + + this->NumberOfOutputs = num; +} + +//---------------------------------------------------------------------------- +void vtkEnSightReader::ReplaceNthOutput(int idx, vtkDataObject* newOutput) +{ + vtkDataObject *oldOutput; + + if (idx < 0) + { + vtkErrorMacro(<< "SetNthOutput: " << idx << ", cannot set output. "); + return; + } + // Expand array if necessary. + if (idx >= this->NumberOfOutputs) + { + this->SetNumberOfOutputsInternal(idx + 1); + } + + // does this change anything? + oldOutput = this->Outputs[idx]; + if (newOutput == oldOutput) + { + return; + } + + if ( !newOutput->IsA(oldOutput->GetClassName()) ) + { + vtkErrorMacro("Can not replace the output with a different type."); + return; + } + + if (newOutput) + { + vtkSource *newOutputOldSource = newOutput->GetSource(); + if (newOutputOldSource) + { + vtkErrorMacro("The new output can not have a source."); + return; + } + } + + // disconnect first existing source-output relationship. + if (oldOutput) + { + oldOutput->SetSource(NULL); + oldOutput->UnRegister(this); + this->Outputs[idx] = NULL; + } + + if (newOutput) + { + // Register the newOutput so it does not get deleted. + // Don't set the link yet until previous links is disconnected. + newOutput->Register(this); + newOutput->SetSource(this); + } + + // now actually make the link that was registered previously. + this->Outputs[idx] = newOutput; + +} + +int vtkEnSightReader::CheckOutputConsistency() +{ + if (this->NumberOfOutputs > this->NumberOfNewOutputs && + ! this->InitialRead) + { + vtkErrorMacro("Cannot decrease number of outputs after initial read"); + this->OutputsAreValid = 0; + } + + if (this->InitialRead) + { + this->InitialRead = 0; + } + + return this->OutputsAreValid; +} + +//---------------------------------------------------------------------------- +vtkIdList* vtkEnSightReader::GetCellIds(int index, int cellType) +{ + // Check argument range. + if(cellType < 0 || cellType > 15) + { + vtkErrorMacro("Cell type " << cellType + << " out of range. Only 16 types exist."); + return 0; + } + if(index < 0 || index > this->UnstructuredPartIds->GetNumberOfIds()) + { + vtkErrorMacro("Index " << index << " out of range. Only " + << this->UnstructuredPartIds->GetNumberOfIds() + << " IDs exist."); + return 0; + } + + // Create the container if necessary. + if(!this->CellIds) + { + this->CellIds = new vtkEnSightReaderCellIdsType; + } + + // Get the index of the actual vtkIdList requested. + unsigned int cellIdsIndex = index*16 + cellType; + + // Make sure the container is large enough for this index. + if(cellIdsIndex+1 > this->CellIds->size()) + { + this->CellIds->resize(cellIdsIndex+1); + } + + // Make sure this vtkIdList exists. + if(!(*this->CellIds)[cellIdsIndex].GetPointer()) + { + vtkIdList* nl = vtkIdList::New(); + (*this->CellIds)[cellIdsIndex] = nl; + nl->Delete(); + } + + // Return the requested vtkIdList. + return (*this->CellIds)[cellIdsIndex].GetPointer(); +} + +//---------------------------------------------------------------------------- +void vtkEnSightReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "CaseFileName: " + << (this->CaseFileName ? this->CaseFileName : "(none)") << endl; + os << indent << "FilePath: " + << (this->FilePath ? this->FilePath : "(none)") << endl; + os << indent << "NumberOfComplexScalarsPerNode: " + << this->NumberOfComplexScalarsPerNode << endl; + os << indent << "NumberOfVectorsPerElement :" + << this->NumberOfVectorsPerElement << endl; + os << indent << "NumberOfTensorsSymmPerElement: " + << this->NumberOfTensorsSymmPerElement << endl; + os << indent << "NumberOfComplexVectorsPerNode: " + << this->NumberOfComplexVectorsPerNode << endl; + os << indent << "NumberOfScalarsPerElement: " + << this->NumberOfScalarsPerElement << endl; + os << indent << "NumberOfComplexVectorsPerElement: " + << this->NumberOfComplexVectorsPerElement << endl; + os << indent << "NumberOfComplexScalarsPerElement: " + << this->NumberOfComplexScalarsPerElement << endl; + os << indent << "NumberOfTensorsSymmPerNode: " + << this->NumberOfTensorsSymmPerNode << endl; + os << indent << "NumberOfScalarsPerMeasuredNode: " + << this->NumberOfScalarsPerMeasuredNode << endl; + os << indent << "NumberOfVectorsPerMeasuredNode: " + << this->NumberOfVectorsPerMeasuredNode << endl; + os << indent << "NumberOfScalarsPerNode: " + << this->NumberOfScalarsPerNode << endl; + os << indent << "NumberOfVectorsPerNode: " + << this->NumberOfVectorsPerNode << endl; + os << indent << "TimeValue: " << this->TimeValue << endl; + os << indent << "MinimumTimeValue: " << this->MinimumTimeValue << endl; + os << indent << "MaximumTimeValue: " << this->MaximumTimeValue << endl; + os << indent << "TimeSets: " << this->TimeSets << endl; + os << indent << "OutputsAreValid: " << this->OutputsAreValid << endl; +} diff --git a/IO/vtkEnSightReader.h b/IO/vtkEnSightReader.h new file mode 100644 index 0000000..6a6c855 --- /dev/null +++ b/IO/vtkEnSightReader.h @@ -0,0 +1,292 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkEnSightReader - superclass for EnSight file readers + +#ifndef __vtkEnSightReader_h +#define __vtkEnSightReader_h + +#include "vtkGenericEnSightReader.h" + +class vtkDataSetCollection; +class vtkIdList; +class vtkEnSightReaderCellIdsType; + +class VTK_IO_EXPORT vtkEnSightReader : public vtkGenericEnSightReader +{ +public: + vtkTypeRevisionMacro(vtkEnSightReader, vtkGenericEnSightReader); + void PrintSelf(ostream& os, vtkIndent indent); + + void Update(); + void ExecuteInformation(); + + //BTX + enum ElementTypesList + { + POINT = 0, + BAR2 = 1, + BAR3 = 2, + NSIDED = 3, + TRIA3 = 4, + TRIA6 = 5, + QUAD4 = 6, + QUAD8 = 7, + TETRA4 = 8, + TETRA10 = 9, + PYRAMID5 = 10, + PYRAMID13 = 11, + HEXA8 = 12, + HEXA20 = 13, + PENTA6 = 14, + PENTA15 = 15 + }; + + enum VariableTypesList + { + SCALAR_PER_NODE = 0, + VECTOR_PER_NODE = 1, + TENSOR_SYMM_PER_NODE = 2, + SCALAR_PER_ELEMENT = 3, + VECTOR_PER_ELEMENT = 4, + TENSOR_SYMM_PER_ELEMENT = 5, + SCALAR_PER_MEASURED_NODE = 6, + VECTOR_PER_MEASURED_NODE = 7, + COMPLEX_SCALAR_PER_NODE = 8, + COMPLEX_VECTOR_PER_NODE = 9, + COMPLEX_SCALAR_PER_ELEMENT = 10, + COMPLEX_VECTOR_PER_ELEMENT = 11 + }; + + enum SectionTypeList + { + COORDINATES = 0, + BLOCK = 1, + ELEMENT = 2 + }; + //ETX + + // Description: + // This method sets/replaces one of the outputs of the + // reader without changing it's modification time. + // Make sure that you pass the right type of data object. + void ReplaceNthOutput(int n, vtkDataObject* output); + + // Description: + // OutputsAreValid indicates whether the outputs from this reader have + // changed in a consistent way. If during re-reading (because of a change in + // time step or data set) the number of outputs becomes less than the current + // number or the type of a particular output changes (e.g., from + // vtkUnstructuredGrid to vtkImageData), then this flag is set to 0. + // Otherwise it is set to 1. + vtkGetMacro(OutputsAreValid, int); + +protected: + vtkEnSightReader(); + ~vtkEnSightReader(); + + void Execute(); + + // Description: + // Read the case file. If an error occurred, 0 is returned; otherwise 1. + int ReadCaseFile(); + + // set in UpdateInformation to value returned from ReadCaseFile + int CaseFileRead; + + // Description: + // Read the geometry file. If an error occurred, 0 is returned; otherwise 1. + virtual int ReadGeometryFile(const char* fileName, int timeStep) = 0; + + // Description: + // Read the measured geometry file. If an error occurred, 0 is returned; + // otherwise 1. + virtual int ReadMeasuredGeometryFile(const char* fileName, int timeStep) = 0; + + // Description: + // Read the variable files. If an error occurred, 0 is returned; otherwise 1. + int ReadVariableFiles(); + + // Description: + // Read scalars per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadScalarsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0, + int numberOfComponents = 1, + int component = 0) = 0; + + // Description: + // Read vectors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerNode(const char* fileName, const char* description, + int timeStep, int measured = 0) = 0; + + // Description: + // Read tensors per node for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerNode(const char* fileName, const char* description, + int timeStep) = 0; + + // Description: + // Read scalars per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadScalarsPerElement(const char* fileName, const char* description, + int timeStep, int numberOfComponents = 1, + int component = 0) = 0; + + // Description: + // Read vectors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadVectorsPerElement(const char* fileName, const char* description, + int timeStep) = 0; + + // Description: + // Read tensors per element for this dataset. If an error occurred, 0 is + // returned; otherwise 1. + virtual int ReadTensorsPerElement(const char* fileName, const char* description, + int timeStep) = 0; + + // Description: + // Read an unstructured part (partId) from the geometry file and create a + // vtkUnstructuredGrid output. Return 0 if EOF reached. + virtual int CreateUnstructuredGridOutput(int partId, + char line[80], + const char* name) = 0; + + // Description: + // Read a structured part from the geometry file and create a + // vtkStructuredGridOutput. Return 0 if EOF reached. + virtual int CreateStructuredGridOutput(int partId, + char line[80], + const char* name) = 0; + + // Description: + // Set/Get the Model file name. + vtkSetStringMacro(GeometryFileName); + vtkGetStringMacro(GeometryFileName); + + // Description: + // Set/Get the Measured file name. + vtkSetStringMacro(MeasuredFileName); + vtkGetStringMacro(MeasuredFileName); + + // Description: + // Set/Get the Match file name. + vtkSetStringMacro(MatchFileName); + vtkGetStringMacro(MatchFileName); + + // Description: + // Add another file name to the list for a particular variable type. + void AddVariableFileName(const char* fileName1, const char* fileName2 = NULL); + + // Description: + // Add another description to the list for a particular variable type. + void AddVariableDescription(const char* description); + + // Description: + // Record the variable type for the variable line just read. + void AddVariableType(); + + // Description: + // Determine the element type from a line read a file. Return -1 for + // invalid element type. + int GetElementType(const char* line); + + // Description: + // Determine the section type from a line read a file. Return -1 for + // invalid section type. + int GetSectionType(const char *line); + + // Description: + // Replace the *'s in the filename with the given filename number. + void ReplaceWildcards(char* filename, int num); + + // Get the vtkIdList for the given output index and cell type. + vtkIdList* GetCellIds(int index, int cellType); + + char* MeasuredFileName; + char* MatchFileName; // may not actually be necessary to read this file + + // pointer to lists of vtkIdLists (cell ids per element type per part) + vtkEnSightReaderCellIdsType* CellIds; + + // part ids of unstructured outputs + vtkIdList* UnstructuredPartIds; + + int VariableMode; + + // pointers to lists of filenames + char** VariableFileNames; // non-complex + char** ComplexVariableFileNames; + + // array of time sets + vtkIdList *VariableTimeSetIds; + vtkIdList *ComplexVariableTimeSetIds; + + // array of file sets + vtkIdList *VariableFileSetIds; + vtkIdList *ComplexVariableFileSetIds; + + // collection of filename numbers per time set + vtkIdListCollection *TimeSetFileNameNumbers; + vtkIdList *TimeSetsWithFilenameNumbers; + + // collection of filename numbers per file set + vtkIdListCollection *FileSetFileNameNumbers; + vtkIdList *FileSetsWithFilenameNumbers; + + // collection of number of steps per file per file set + vtkIdListCollection *FileSetNumberOfSteps; + + // ids of the time and file sets + vtkIdList *TimeSetIds; + vtkIdList *FileSets; + + int GeometryTimeSet; + int GeometryFileSet; + int MeasuredTimeSet; + int MeasuredFileSet; + + float GeometryTimeValue; + float MeasuredTimeValue; + + int UseTimeSets; + vtkSetMacro(UseTimeSets, int); + vtkGetMacro(UseTimeSets, int); + vtkBooleanMacro(UseTimeSets, int); + + int UseFileSets; + vtkSetMacro(UseFileSets, int); + vtkGetMacro(UseFileSets, int); + vtkBooleanMacro(UseFileSets, int); + + int NumberOfGeometryParts; + + void SetNumberOfOutputsInternal(int num); + + // global list of points for measured geometry + int NumberOfMeasuredPoints; + + int NumberOfNewOutputs; + int OutputsAreValid; + int InitialRead; + + int CheckOutputConsistency(); + +private: + vtkEnSightReader(const vtkEnSightReader&); // Not implemented. + void operator=(const vtkEnSightReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkFacetWriter.cxx b/IO/vtkFacetWriter.cxx new file mode 100644 index 0000000..0466997 --- /dev/null +++ b/IO/vtkFacetWriter.cxx @@ -0,0 +1,323 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFacetWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFacetWriter.h" + +#include "vtkUnstructuredGrid.h" +#include "vtkObjectFactory.h" +#include "vtkErrorCode.h" +#include "vtkCellType.h" +#include "vtkCellArray.h" +#include "vtkGarbageCollector.h" +#include "vtkAppendFilter.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkInformationVector.h" +#include "vtkInformation.h" + +#include "vtkUnsignedIntArray.h" +#include "vtkDoubleArray.h" +#include "vtkSmartPointer.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkFacetWriter, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkFacetWriter); + +//---------------------------------------------------------------------------- +vtkFacetWriter::vtkFacetWriter() +{ + this->FileName = NULL; + this->OutputStream = 0; +} + +//---------------------------------------------------------------------------- +vtkFacetWriter::~vtkFacetWriter() +{ + this->SetFileName(0); +} + +//---------------------------------------------------------------------------- +void vtkFacetWriter::Write() +{ + this->WriteToStream(0); +} + +//---------------------------------------------------------------------------- +int vtkFacetWriter::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed( outputVector) ) +{ + this->SetErrorCode(vtkErrorCode::NoError); + + int cleanStream = 0; + if ( !this->OutputStream ) + { + if ( !this->FileName ) + { + vtkErrorMacro("File name not specified"); + return 0; + } + + this->OutputStream = new ofstream(this->FileName); + if ( !this->OutputStream ) + { + vtkErrorMacro("Error opening file: " << this->FileName << " for writing"); + return 0; + } + cleanStream = 1; + } + + if ( !this->OutputStream ) + { + vtkErrorMacro("No output stream"); + return 0; + } + + int cc; + int len = inputVector[0]->GetNumberOfInformationObjects(); + *this->OutputStream << "FACET FILE FROM VTK" << endl + << len << endl; + + for ( cc =0; cc < len; cc ++ ) + { + vtkInformation *inInfo = inputVector[0]->GetInformationObject(cc); + vtkPolyData *input = + vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + if ( !this->WriteDataToStream(this->OutputStream, input) ) + { + if ( cleanStream ) + { + delete this->OutputStream; + this->OutputStream = 0; + } + return 0; + } + } + if ( cleanStream ) + { + delete this->OutputStream; + this->OutputStream = 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkFacetWriter::WriteToStream(ostream* ost) +{ + this->OutputStream = ost; + // we always write, even if nothing has changed, so send a modified + this->Modified(); + this->UpdateInformation(); + this->GetInput()->SetUpdateExtent(this->GetInput()->GetWholeExtent()); + this->Update(); + this->OutputStream = 0; +} + +//---------------------------------------------------------------------------- +int vtkFacetWriter::WriteDataToStream(ostream* ost, vtkPolyData* data) +{ + *ost << "Element" << data << endl + << "0" << endl + << data->GetNumberOfPoints() << " 0 0" << endl; + vtkIdType point; + for ( point = 0; point < data->GetNumberOfPoints(); point ++ ) + { + double xyz[3]; + data->GetPoint(point, xyz); + *ost << xyz[0] << " " << xyz[1] << " " << xyz[2] << endl; + } + *ost << "1" << endl + << "Element" << data << endl; + int written = 0; + vtkCellArray* ca; + vtkIdType numCells; + vtkIdType totalCells = 0; + int material = 0; + int part = 0; + vtkIdType cc; + + if ( data->GetVerts()->GetNumberOfCells() ) + { + // This test is needed if another cell type is written above this + // block. We must remove it here because it produces an + // unreachable code warning. + // + //if ( written ) + // { + // vtkErrorMacro("Multiple different cells in the poly data"); + // return 0; + // } + ca = data->GetVerts(); + numCells = ca->GetNumberOfCells(); + vtkIdType numPts = 0; + vtkIdType *pts = NULL; + ca->InitTraversal(); + while ( ca->GetNextCell( numPts, pts ) ) + { + // Each vertex is one cell + for ( cc = 0; cc < numPts; cc ++ ) + { + totalCells ++; + } + } + *ost << totalCells << " 1" << endl; + ca->InitTraversal(); + while ( ca->GetNextCell( numPts, pts ) ) + { + for ( cc = 0; cc < numPts; cc ++ ) + { + // Indices of point starts with 1 + vtkIdType pointIndex = pts[cc] + 1; + *ost << pointIndex << " " << material << " " << part << endl; + } + } + written = 1; + } + + if ( data->GetLines()->GetNumberOfCells() ) + { + if ( written ) + { + vtkErrorMacro("Multiple different cells in the poly data"); + return 0; + } + ca = data->GetLines(); + numCells = ca->GetNumberOfCells(); + vtkIdType numPts = 0; + vtkIdType *pts = NULL; + ca->InitTraversal(); + while ( ca->GetNextCell( numPts, pts ) ) + { + // One line per cell + for ( cc = 1; cc < numPts; cc ++ ) + { + totalCells ++; + } + } + *ost << totalCells << " 2" << endl; + ca->InitTraversal(); + while ( ca->GetNextCell( numPts, pts ) ) + { + for ( cc = 1; cc < numPts; cc ++ ) + { + vtkIdType point1 = pts[cc-1] + 1; + vtkIdType point2 = pts[cc] + 1; + *ost << point1 << " " << point2 << " " << material << " " << part << endl; + } + } + written = 1; + } + + if ( data->GetPolys()->GetNumberOfCells() ) + { + if ( written ) + { + vtkErrorMacro("Multiple different cells in the poly data"); + return 0; + } + ca = data->GetPolys(); + numCells = ca->GetNumberOfCells(); + vtkIdType numPts = 0; + vtkIdType *pts = NULL; + ca->InitTraversal(); + ca->GetNextCell(numPts, pts); + totalCells ++; + vtkIdType numPoints = numPts; + while ( ca->GetNextCell( numPts, pts ) ) + { + if ( numPts != numPoints ) + { + vtkErrorMacro("Found polygons with different order"); + return 0; + } + totalCells ++; + } + *ost << totalCells << " " << numPoints << endl; + ca->InitTraversal(); + int cnt = 0; + while ( ca->GetNextCell( numPts, pts ) ) + { + for ( cc = 0; cc < numPts; cc ++ ) + { + vtkIdType pointindex = pts[cc] + 1; + *ost << pointindex << " "; + } + *ost << material << " " << part << endl; + cnt ++; + } + cout << "Written: " << cnt << " / " << numCells << " / " << totalCells << endl; + written = 1; + } + + if ( data->GetStrips()->GetNumberOfCells() ) + { + if ( written ) + { + vtkErrorMacro("Multiple different cells in the poly data"); + return 0; + } + ca = data->GetStrips(); + numCells = ca->GetNumberOfCells(); + vtkIdType numPts = 0; + vtkIdType *pts = NULL; + ca->InitTraversal(); + while ( ca->GetNextCell( numPts, pts ) ) + { + // One triangle per cell + for ( cc = 2; cc < numPts; cc ++ ) + { + totalCells ++; + } + } + *ost << totalCells << " 3" << endl; + ca->InitTraversal(); + while ( ca->GetNextCell( numPts, pts ) ) + { + for ( cc = 2; cc < numPts; cc ++ ) + { + vtkIdType point1 = pts[cc-2] + 1; + vtkIdType point2 = pts[cc-1] + 1; + vtkIdType point3 = pts[cc] + 1; + *ost << point1 << " " << point2 << " " << point3 << " " << material << " " << part << endl; + } + } + written = 1; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkFacetWriter::FillInputPortInformation(int port, vtkInformation *info) +{ + if (!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return 1; +} +//---------------------------------------------------------------------------- +void vtkFacetWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; +} + diff --git a/IO/vtkFacetWriter.h b/IO/vtkFacetWriter.h new file mode 100644 index 0000000..ca8e098 --- /dev/null +++ b/IO/vtkFacetWriter.h @@ -0,0 +1,88 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkFacetWriter.h,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFacetWriter - reads a dataset in Facet format +// .SECTION Description +// vtkFacetWriter creates an unstructured grid dataset. It reads ASCII files +// stored in Facet format +// +// The facet format looks like this: +// FACET FILE ... +// nparts +// Part 1 name +// 0 +// npoints 0 0 +// p1x p1y p1z +// p2x p2y p2z +// ... +// 1 +// Part 1 name +// ncells npointspercell +// p1c1 p2c1 p3c1 ... pnc1 materialnum partnum +// p1c2 p2c2 p3c2 ... pnc2 materialnum partnum +// ... + +#ifndef __vtkFacetWriter_h +#define __vtkFacetWriter_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkInformation; + +class VTK_IO_EXPORT vtkFacetWriter : public vtkPolyDataAlgorithm +{ +public: + static vtkFacetWriter *New(); + vtkTypeRevisionMacro(vtkFacetWriter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of Facet datafile to read + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Write data + void Write(); + + // BTX + void WriteToStream(ostream* ost); + // ETX + +protected: + vtkFacetWriter(); + ~vtkFacetWriter(); + + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + virtual int FillInputPortInformation(int, vtkInformation *); + + // BTX + int WriteDataToStream(ostream* ost, vtkPolyData* data); + // ETX + + char *FileName; + ostream *OutputStream; + +private: + vtkFacetWriter(const vtkFacetWriter&); // Not implemented. + void operator=(const vtkFacetWriter&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkGAMBITReader.cxx b/IO/vtkGAMBITReader.cxx new file mode 100644 index 0000000..8335379 --- /dev/null +++ b/IO/vtkGAMBITReader.cxx @@ -0,0 +1,489 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGAMBITReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Thanks to Jean M. Favre (CSCS, Swiss Center for Scientific Computing) who +// developed this class. +// Please address all comments to Jean Favre (jfavre at cscs.ch) + +#include "vtkGAMBITReader.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkErrorCode.h" +#include "vtkUnstructuredGrid.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkDoubleArray.h" +#include "vtkIntArray.h" +#include "vtkCellArray.h" + +vtkCxxRevisionMacro(vtkGAMBITReader, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkGAMBITReader); + +//---------------------------------------------------------------------------- +vtkGAMBITReader::vtkGAMBITReader() +{ + this->FileName = NULL; + this->NumberOfCells = 0; + this->NumberOfNodes = 0; + this->NumberOfNodeFields = 0; + this->NumberOfCellFields = 0; + this->FileStream = NULL; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkGAMBITReader::~vtkGAMBITReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } +} + +//---------------------------------------------------------------------------- +int vtkGAMBITReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro( << "Reading GAMBIT Neutral file"); + + // If ExecuteInformation() failed the FileStream will be NULL and + // ExecuteInformation() will have spit out an error. + if ( this->FileStream == NULL ) + { + return 0; + } + + this->ReadFile(output); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + os << indent << "Number Of Nodes: " << this->NumberOfNodes << endl; + os << indent << "Number Of Node Fields: " + << this->NumberOfNodeFields << endl; + + os << indent << "Number Of Cells: " << this->NumberOfCells << endl; + os << indent << "Number Of Cell Fields: " + << this->NumberOfCellFields << endl; +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadFile(vtkUnstructuredGrid *output) +{ + this->ReadGeometry(output); + + // yes, but, we cannot find any examples containing data. + // GAMBIT users seem to say that they use the Fluent solver and do not + // use Gambit as an output format, thus no data when used as input to solver + if(this->NumberOfNodeFields) + { + this->ReadNodeData(output); + } + + if(this->NumberOfCellFields) + { + this->ReadCellData(output); + } + + delete this->FileStream; + this->FileStream = NULL; +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadNodeData(vtkUnstructuredGrid *vtkNotUsed(output)) +{ + vtkWarningMacro("Not implemented due to lack of examples"); +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadCellData(vtkUnstructuredGrid *vtkNotUsed(output)) +{ + vtkWarningMacro("Not implemented due to lack of examples"); +} + +//---------------------------------------------------------------------------- +int vtkGAMBITReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + if ( !this->FileName ) + { + this->NumberOfNodes = 0; + this->NumberOfCells = 0; + this->NumberOfNodeFields = 0; + this->NumberOfCellFields = 0; + + vtkErrorMacro("No filename specified"); + return 0; + } + + this->FileStream = new ifstream(this->FileName, ios::in); + + if (this->FileStream->fail()) + { + this->SetErrorCode(vtkErrorCode::FileNotFoundError); + delete this->FileStream; + this->FileStream = NULL; + vtkErrorMacro("Specified filename not found"); + return 0; + } + + char c='\0', buf[128]; + + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + + *(this->FileStream) >> this->NumberOfNodes; + *(this->FileStream) >> this->NumberOfCells; + *(this->FileStream) >> this->NumberOfElementGroups; + *(this->FileStream) >> this->NumberOfBoundaryConditionSets; + *(this->FileStream) >> this->NumberOfCoordinateDirections; + *(this->FileStream) >> this->NumberOfVelocityComponents; + this->FileStream->get(c); + + // read here the end of section + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + if(strncmp(buf, "ENDOFSECTION", 12)) + { + vtkErrorMacro(<<"Error reading file"); + } + vtkDebugMacro( + << "\nNumberOfNodes " << this->NumberOfNodes + << "\nNumberOfCells " << this->NumberOfCells + << "\nNumberOfElementGroups " << this->NumberOfElementGroups + << "\nNumberOfBoundaryConditionSets " << this->NumberOfBoundaryConditionSets + << "\nNumberOfCoordinateDirections " << this->NumberOfCoordinateDirections + << "\nNumberOfVelocityComponents " << this->NumberOfVelocityComponents); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadGeometry(vtkUnstructuredGrid *output) +{ + vtkDoubleArray *coords = vtkDoubleArray::New(); + coords->SetNumberOfComponents(3); + // allocate one more pt and store node id=0 + coords->SetNumberOfTuples(this->NumberOfNodes); + + this->ReadXYZCoords(coords); + this->ReadCellConnectivity(output); + if(this->NumberOfElementGroups > 0) + { + this->ReadMaterialTypes(output); + } + if(this->NumberOfBoundaryConditionSets > 0) + { + this->ReadBoundaryConditionSets(output); + } + vtkPoints *points = vtkPoints::New(); + points->SetData(coords); + coords->Delete(); + + output->SetPoints(points); + points->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadBoundaryConditionSets(vtkUnstructuredGrid *output) +{ + int bcs, f, itype, nentry, nvalues; + int isUsable=0; + int node, elt, eltype, facenumber; + char c, buf[128]; + + // no idea about how to treat element/cell, so we allocate a single array + + vtkIntArray *bcscalar = vtkIntArray::New(); + bcscalar->SetNumberOfComponents(1); + bcscalar->SetNumberOfTuples(this->NumberOfNodes); + bcscalar->SetName("Boundary Condition"); + int *ptr = bcscalar->GetPointer(0); + // initialise with null values. When set later, will set to 1 + memset((void*)ptr,0,sizeof(int)*this->NumberOfNodes); + + for(bcs=1; bcs <= this->NumberOfBoundaryConditionSets; bcs++) + { + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + sscanf(&buf[32],"%10d%10d%10d", &itype, &nentry, &nvalues); + vtkDebugMacro( + << "\nitype " << itype + << "\tnentry " << nentry + << "\tnvalues " << nvalues); + // I have no example o how nvalues is used....So no implementation. + if(itype == 0) // nodes + { + isUsable = 1; + for(f=0; f < nentry; f++) + { + *(this->FileStream) >> node; + node--; + if( node >= 0 && node < this->NumberOfNodes) + { + bcscalar->SetValue(node, 1); + } + else + { + vtkErrorMacro(<<"Node value is outside of range"); + } + } + this->FileStream->get(c); + // read here the end of section + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + if(strncmp(buf, "ENDOFSECTION", 12)) + { + vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of group"); + } + } + else // element/cell are parsed but nothing is done with the info read + { + for(f=0; f < nentry; f++) + { + *(this->FileStream) >> elt >> eltype >> facenumber; + } + this->FileStream->get(c); + // read here the end of section + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + if(strncmp(buf, "ENDOFSECTION", 12)) + { + vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of group"); + } + } + } + vtkDebugMacro(<< "All BCS read succesfully"); + if(isUsable) + { + output->GetPointData()->AddArray(bcscalar); + if (!output->GetPointData()->GetScalars()) + { + output->GetPointData()->SetScalars(bcscalar); + } + } + bcscalar->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadMaterialTypes(vtkUnstructuredGrid *output) +{ + int grp, f, flag, id, nbelts, elt, mat, nbflags; + char c, buf[128]; + + vtkIntArray *materials = vtkIntArray::New(); + materials->SetNumberOfComponents(1); + materials->SetNumberOfTuples(this->NumberOfCells); + materials->SetName("Material Type"); + + for(grp=1; grp <= this->NumberOfElementGroups; grp++) + { + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + sscanf(buf,"GROUP:%10d ELEMENTS: %10d MATERIAL: %10d NFLAGS:%10d", &id, &nbelts, &mat, &nbflags); + + vtkDebugMacro( + << "\nid " << id + << "\tnbelts " << nbelts + << "\tmat " << mat + << "\tnbflags " << nbflags); + + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + for(f=0; f < nbflags; f++) + { + *(this->FileStream) >> flag; + } + this->FileStream->get(c); + for(f=0; f < nbelts; f++) + { + *(this->FileStream) >> elt; + materials->SetValue(elt-1, mat); + } + this->FileStream->get(c); + // read here the end of section + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + if(strncmp(buf, "ENDOFSECTION", 12)) + { + vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of group"); + } + } + vtkDebugMacro(<< "All groups read succesfully"); + + output->GetCellData()->AddArray(materials); + if (!output->GetCellData()->GetScalars()) + { + output->GetCellData()->SetScalars(materials); + } + materials->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadCellConnectivity(vtkUnstructuredGrid *output) +{ + int i, k; + vtkIdType list[27]; + char c, buf[128]; + + output->Allocate(); + + this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + + for(i=1; i <= this->NumberOfCells; i++) + { + int id; // no check is done to see that they are monotonously increasing + int ntype, ndp; + *(this->FileStream) >> id >> ntype >> ndp; + + switch(ntype){ + case EDGE: + { + for(k=0; k < 2; k++) + { + *(this->FileStream) >> list[k]; + list[k]--; + } + output->InsertNextCell(VTK_LINE, 2, list); + } + break; + case TRI: + { + for(k=0; k < 3; k++) + { + *(this->FileStream) >> list[k]; + list[k]--; + } + output->InsertNextCell(VTK_TRIANGLE, 3, list); + } + break; + case QUAD: + { + for(k=0; k < 4; k++) + { + *(this->FileStream) >> list[k]; + list[k]--; + } + output->InsertNextCell(VTK_QUAD, 4, list); + } + break; + case TETRA: + { + for(k=0; k < 4; k++) + { + *(this->FileStream) >> list[k]; + list[k]--; + } + output->InsertNextCell(VTK_TETRA, 4, list); + } + break; + case PYRAMID: + { + for(k=0; k < 5; k++) + { + *(this->FileStream) >> list[k]; + list[k]--; + } + output->InsertNextCell(VTK_PYRAMID, 5, list); + } + break; + case PRISM: + { + for(k=0; k < 6; k++) + { + *(this->FileStream) >> list[k]; + list[k]--; + } + output->InsertNextCell(VTK_WEDGE, 6, list); + } + break; + case BRICK: + { + for(k=0; k < 8; k++) + { + *(this->FileStream) >> list[k]; + list[k]--; + } + output->InsertNextCell(VTK_HEXAHEDRON, 8, list); + } + break; + default: + { + vtkErrorMacro( << "cell type: " << ntype << " is not supported\n"); + return; + } + } // for all cell, read the indices + } + // read here the end of section + this->FileStream->get(c); this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + if(strncmp(buf, "ENDOFSECTION", 12)) + { + vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of connectivity"); + } +} + +//---------------------------------------------------------------------------- +void vtkGAMBITReader::ReadXYZCoords(vtkDoubleArray *coords) +{ + int i; + double *ptr = coords->GetPointer(0); + char c, buf[64]; + + int id; // no check is done to see that they are monotonously increasing + this->FileStream->get(buf, 64, '\n'); this->FileStream->get(c); + + if(this->NumberOfCoordinateDirections == 3) + { + for(i=0; i < this->NumberOfNodes; i++) + { + *(this->FileStream) >> id; + *(this->FileStream) >> ptr[3*i] >> ptr[3*i+1] >> ptr[3*i+2]; + } + } + else + { + for(i=0; i < this->NumberOfNodes; i++) + { + *(this->FileStream) >> id; + *(this->FileStream) >> ptr[3*i] >> ptr[3*i+1]; + ptr[3*i+2] = 0.0; + } + } + this->FileStream->get(c); this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c); + if(strncmp(buf, "ENDOFSECTION", 12)) + { + vtkErrorMacro("Error reading ENDOFSECTION tag at end of coordinates section"); + } +} diff --git a/IO/vtkGAMBITReader.h b/IO/vtkGAMBITReader.h new file mode 100644 index 0000000..88865f3 --- /dev/null +++ b/IO/vtkGAMBITReader.h @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGAMBITReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGAMBITReader - reads a dataset in Fluent GAMBIT neutral file format +// .SECTION Description +// vtkGAMBITReader creates an unstructured grid dataset. It reads ASCII files +// stored in GAMBIT neutral format, with optional data stored at the nodes or +// at the cells of the model. A cell-based fielddata stores the material id. + +// .SECTION Thanks +// Thanks to Jean M. Favre (CSCS, Swiss Center for Scientific Computing) who +// developed this class. +// Please address all comments to Jean Favre (jfavre at cscs.ch) + +// .SECTION See Also +// vtkAVSucdReader + +#ifndef __vtkGAMBITReader_h +#define __vtkGAMBITReader_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkDoubleArray; +class VTK_IO_EXPORT vtkGAMBITReader : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkGAMBITReader *New(); + vtkTypeRevisionMacro(vtkGAMBITReader,vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the file name of the GAMBIT data file to read. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Get the total number of cells. The number of cells is only valid after a + // successful read of the data file is performed. + vtkGetMacro(NumberOfCells,int); + + // Description: + // Get the total number of nodes. The number of nodes is only valid after a + // successful read of the data file is performed. + vtkGetMacro(NumberOfNodes,int); + + // Description: + // Get the number of data components at the nodes and cells. + vtkGetMacro(NumberOfNodeFields,int); + vtkGetMacro(NumberOfCellFields,int); + +protected: + vtkGAMBITReader(); + ~vtkGAMBITReader(); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char *FileName; + + int NumberOfNodes; + int NumberOfCells; + int NumberOfNodeFields; + int NumberOfCellFields; + int NumberOfElementGroups; + int NumberOfBoundaryConditionSets; + int NumberOfCoordinateDirections; + int NumberOfVelocityComponents; + ifstream *FileStream; + + //BTX + enum GAMBITCellType + { + EDGE = 1, + QUAD = 2, + TRI = 3, + BRICK = 4, + PRISM = 5, + TETRA = 6, + PYRAMID = 7 + }; + //ETX + +private: + void ReadFile(vtkUnstructuredGrid *output); + void ReadGeometry(vtkUnstructuredGrid *output); + void ReadNodeData(vtkUnstructuredGrid *output); + void ReadCellData(vtkUnstructuredGrid *output); + + void ReadXYZCoords(vtkDoubleArray *coords); + + void ReadCellConnectivity(vtkUnstructuredGrid *output); + void ReadMaterialTypes(vtkUnstructuredGrid *output); + void ReadBoundaryConditionSets(vtkUnstructuredGrid *output); + + vtkGAMBITReader(const vtkGAMBITReader&); // Not implemented. + void operator=(const vtkGAMBITReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkGESignaReader.cxx b/IO/vtkGESignaReader.cxx new file mode 100644 index 0000000..3818080 --- /dev/null +++ b/IO/vtkGESignaReader.cxx @@ -0,0 +1,454 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGESignaReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGESignaReader.h" + +#include "vtkByteSwap.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkGESignaReader, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkGESignaReader); + + +int vtkGESignaReader::CanReadFile(const char* fname) +{ + FILE *fp = fopen(fname, "rb"); + if (!fp) + { + return 0; + } + + int magic; + fread(&magic, 4, 1, fp); + vtkByteSwap::Swap4BE(&magic); + + if (magic != 0x494d4746) + { + fclose(fp); + return 0; + } + return 3; +} + + +void vtkGESignaReader::ExecuteInformation() +{ + this->ComputeInternalFileName(this->DataExtent[4]); + if (this->InternalFileName == NULL) + { + return; + } + + FILE *fp = fopen(this->InternalFileName, "rb"); + if (!fp) + { + vtkErrorMacro("Unable to open file " << this->InternalFileName); + return; + } + + int magic; + fread(&magic, 4, 1, fp); + vtkByteSwap::Swap4BE(&magic); + + if (magic != 0x494d4746) + { + vtkErrorMacro(<<"Unknown file type! Not a GE ximg file!"); + fclose(fp); + return; + } + + // read in the pixel offset from the header + int offset; + fread(&offset, 4, 1, fp); + vtkByteSwap::Swap4BE(&offset); + this->SetHeaderSize(offset); + + int width, height, depth; + fread(&width, 4, 1, fp); + vtkByteSwap::Swap4BE(&width); + fread(&height, 4, 1, fp); + vtkByteSwap::Swap4BE(&height); + // depth in bits + fread(&depth, 4, 1, fp); + vtkByteSwap::Swap4BE(&depth); + + int compression; + fread(&compression, 4, 1, fp); + vtkByteSwap::Swap4BE(&compression); + + // seek to the exam series and image header offsets + fseek(fp, 132, SEEK_SET); + int examHdrOffset; + fread(&examHdrOffset, 4, 1, fp); + vtkByteSwap::Swap4BE(&examHdrOffset); + fseek(fp, 140, SEEK_SET); + int seriesHdrOffset; + fread(&seriesHdrOffset, 4, 1, fp); + vtkByteSwap::Swap4BE(&seriesHdrOffset); + fseek(fp, 148, SEEK_SET); + int imgHdrOffset; + fread(&imgHdrOffset, 4, 1, fp); + vtkByteSwap::Swap4BE(&imgHdrOffset); + + // seek to the exam and read some info + fseek(fp, examHdrOffset + 84, SEEK_SET); + char tmpStr[1024]; + fread(tmpStr,13,1,fp); + tmpStr[13] = 0; + this->SetPatientID(tmpStr); + fread(tmpStr,25,1,fp); + tmpStr[25] = 0; + this->SetPatientName(tmpStr); + + // seek to the series and read some info + fseek(fp, seriesHdrOffset + 10, SEEK_SET); + short series; + fread(&series,2,1,fp); + vtkByteSwap::Swap2BE(&series); + sprintf(tmpStr,"%d",series); + this->SetSeries(tmpStr); + fseek(fp, seriesHdrOffset + 92, SEEK_SET); + fread(tmpStr,25,1,fp); + tmpStr[25] = 0; + this->SetStudy(tmpStr); + + // now seek to the image header and read some values + float tmpX, tmpY, tmpZ; + float spacingX, spacingY, spacingZ; + fseek(fp, imgHdrOffset + 50, SEEK_SET); + fread(&spacingX, 4, 1, fp); + vtkByteSwap::Swap4BE(&spacingX); + fread(&spacingY, 4, 1, fp); + vtkByteSwap::Swap4BE(&spacingY); + fseek(fp, imgHdrOffset + 116, SEEK_SET); + fread(&spacingZ, 4, 1, fp); + vtkByteSwap::Swap4BE(&spacingZ); + fseek(fp, imgHdrOffset + 26, SEEK_SET); + fread(&tmpZ, 4, 1, fp); + vtkByteSwap::Swap4BE(&tmpZ); + spacingZ = spacingZ + tmpZ; + + float origX, origY, origZ; + fseek(fp, imgHdrOffset + 154, SEEK_SET); + // read TLHC + fread(&origX, 4, 1, fp); + vtkByteSwap::Swap4BE(&origX); + fread(&origY, 4, 1, fp); + vtkByteSwap::Swap4BE(&origY); + fread(&origZ, 4, 1, fp); + vtkByteSwap::Swap4BE(&origZ); + + // read TRHC + fread(&tmpX, 4, 1, fp); + vtkByteSwap::Swap4BE(&tmpX); + fread(&tmpY, 4, 1, fp); + vtkByteSwap::Swap4BE(&tmpY); + fread(&tmpZ, 4, 1, fp); + vtkByteSwap::Swap4BE(&tmpZ); + + // compute BLHC = TLHC - TRHC + BRHC + origX = origX - tmpX; + origY = origY - tmpY; + origZ = origZ - tmpZ; + + // read BRHC + fread(&tmpX, 4, 1, fp); + vtkByteSwap::Swap4BE(&tmpX); + fread(&tmpY, 4, 1, fp); + vtkByteSwap::Swap4BE(&tmpY); + fread(&tmpZ, 4, 1, fp); + vtkByteSwap::Swap4BE(&tmpZ); + + // compute BLHC = TLHC - TRHC + BRHC + origX = origX + tmpX; + origY = origY + tmpY; + origZ = origZ + tmpZ; + + this->SetDataOrigin(origX, origY, origZ); + + this->DataExtent[0] = 0; + this->DataExtent[1] = width - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = height - 1; + + this->SetDataScalarTypeToUnsignedShort(); + + this->SetNumberOfScalarComponents(1); + this->SetDataSpacing(spacingX, spacingY, spacingZ); + this->vtkImageReader2::ExecuteInformation(); + + // close the file + fclose(fp); +} + +void vtkcopygenesisimage(FILE *infp, int width, int height, int compress, + short *map_left, short *map_wide, + unsigned short *output) +{ + unsigned short row; + unsigned short last_pixel=0; + for (row=0; rowGetInternalFileName(), "rb"); + if (!fp) + { + return; + } + + int magic; + fread(&magic, 4, 1, fp); + vtkByteSwap::Swap4BE(&magic); + + if (magic != 0x494d4746) + { + vtkGenericWarningMacro(<<"Unknown file type! Not a GE ximg file!"); + fclose(fp); + return; + } + + // read in the pixel offset from the header + int offset; + fread(&offset, 4, 1, fp); + vtkByteSwap::Swap4BE(&offset); + + int width, height, depth; + fread(&width, 4, 1, fp); + vtkByteSwap::Swap4BE(&width); + fread(&height, 4, 1, fp); + vtkByteSwap::Swap4BE(&height); + // depth in bits + fread(&depth, 4, 1, fp); + vtkByteSwap::Swap4BE(&depth); + + int compression; + fread(&compression, 4, 1, fp); + vtkByteSwap::Swap4BE(&compression); + + short *leftMap = 0; + short *widthMap = 0; + + if (compression == 2 || compression == 4) + { // packed/compacked + leftMap = new short [height]; + widthMap = new short [height]; + + fseek(fp, 64, SEEK_SET); + int packHdrOffset; + fread(&packHdrOffset, 4, 1, fp); + vtkByteSwap::Swap4BE(&packHdrOffset); + + // now seek to the pack header and read some values + fseek(fp, packHdrOffset, SEEK_SET); + // read in the maps + int i; + for (i = 0; i < height; i++) + { + fread(leftMap+i, 2, 1, fp); + vtkByteSwap::Swap2BE(leftMap+i); + fread(widthMap+i, 2, 1, fp); + vtkByteSwap::Swap2BE(widthMap+i); + } + } + + // seek to pixel data + fseek(fp, offset, SEEK_SET); + + // read in the pixels + unsigned short *tmp = new unsigned short [width*height]; + int *dext = self->GetDataExtent(); + vtkcopygenesisimage(fp, dext[1] + 1, dext[3] + 1, + compression, leftMap, widthMap, tmp); + + // now copy into desired extent + int yp; + for (yp = outExt[2]; yp <= outExt[3]; ++yp) + { + int ymod = height - yp - 1; + memcpy(outPtr,tmp+ymod*width+outExt[0],2*width); + outPtr = outPtr + width; + } + + delete [] tmp; + if (leftMap) + { + delete [] leftMap; + } + if (widthMap) + { + delete [] widthMap; + } + fclose(fp); +} + +//---------------------------------------------------------------------------- +// This function reads in one data of data. +// templated to handle different data types. +void vtkGESignaReaderUpdate(vtkGESignaReader *self, vtkImageData *data, + unsigned short *outPtr) +{ + vtkIdType outIncr[3]; + int outExtent[6]; + unsigned short *outPtr2; + + data->GetExtent(outExtent); + data->GetIncrements(outIncr); + + outPtr2 = outPtr; + int idx2; + for (idx2 = outExtent[4]; idx2 <= outExtent[5]; ++idx2) + { + self->ComputeInternalFileName(idx2); + // read in a PNG file + vtkGESignaReaderUpdate2(self, outPtr2, outExtent, outIncr); + self->UpdateProgress((idx2 - outExtent[4])/ + (outExtent[5] - outExtent[4] + 1.0)); + outPtr2 += outIncr[2]; + } +} + + +//---------------------------------------------------------------------------- +// This function reads a data from a file. The datas extent/axes +// are assumed to be the same as the file extent/order. +void vtkGESignaReader::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + if (this->InternalFileName == NULL) + { + vtkErrorMacro(<< "Either a FileName or FilePrefix must be specified."); + return; + } + + data->GetPointData()->GetScalars()->SetName("GESignalImage"); + + this->ComputeDataIncrements(); + + // Call the correct templated function for the output + void *outPtr; + + // Call the correct templated function for the input + outPtr = data->GetScalarPointer(); + vtkGESignaReaderUpdate(this, data, (unsigned short *)(outPtr)); +} + +//---------------------------------------------------------------------------- +void vtkGESignaReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkGESignaReader.h b/IO/vtkGESignaReader.h new file mode 100644 index 0000000..0cee7cd --- /dev/null +++ b/IO/vtkGESignaReader.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGESignaReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGESignaReader - read GE Signa ximg files +// .SECTION Description +// vtkGESignaReader is a source object that reads some GE Signa ximg files It +// does support reading in pixel spacing, slice spacing and it computes an +// origin for the image in millimeters. It always produces greyscale unsigned +// short data and it supports reading in rectangular, packed, compressed, and +// packed&compressed. It does not read in slice orientation, or position +// right now. To use it you just need to specify a filename or a file prefix +// and pattern. + +// +// .SECTION See Also +// vtkImageReader2 + +#ifndef __vtkGESignaReader_h +#define __vtkGESignaReader_h + +#include "vtkMedicalImageReader2.h" + +class VTK_IO_EXPORT vtkGESignaReader : public vtkMedicalImageReader2 +{ +public: + static vtkGESignaReader *New(); + vtkTypeRevisionMacro(vtkGESignaReader,vtkMedicalImageReader2); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: is the given file name a GESigna file? + virtual int CanReadFile(const char* fname); + + // Description: + // Valid extentsions + virtual const char* GetFileExtensions() + { + return ".MR .CT"; + } + + // Description: + // A descriptive name for this format + virtual const char* GetDescriptiveName() + { + return "GESigna"; + } + +protected: + vtkGESignaReader() {}; + ~vtkGESignaReader() {}; + + virtual void ExecuteInformation(); + virtual void ExecuteData(vtkDataObject *out); + +private: + vtkGESignaReader(const vtkGESignaReader&); // Not implemented. + void operator=(const vtkGESignaReader&); // Not implemented. +}; +#endif + + diff --git a/IO/vtkGaussianCubeReader.cxx b/IO/vtkGaussianCubeReader.cxx new file mode 100644 index 0000000..a2eddc4 --- /dev/null +++ b/IO/vtkGaussianCubeReader.cxx @@ -0,0 +1,281 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGaussianCubeReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGaussianCubeReader.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkFloatArray.h" +#include "vtkIdTypeArray.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTransform.h" + +#include + +vtkCxxRevisionMacro(vtkGaussianCubeReader, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkGaussianCubeReader); + +//---------------------------------------------------------------------------- +// Construct object with merging set to true. +vtkGaussianCubeReader::vtkGaussianCubeReader() +{ + this->FileName = NULL; + this->Transform = vtkTransform::New(); + // Add the second output for the grid data + + this->SetNumberOfOutputPorts(2); + vtkImageData *grid; + grid = vtkImageData::New(); + grid->ReleaseData(); + this->GetExecutive()->SetOutputData(1, grid); + grid->Delete(); +} + +//---------------------------------------------------------------------------- +vtkGaussianCubeReader::~vtkGaussianCubeReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } + this->Transform->Delete(); + // must delete the second output added +} + +//---------------------------------------------------------------------------- +int vtkGaussianCubeReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + FILE *fp; + char title[256]; + char data_name[256]; + double elements[16]; + int JN1, N1N2, n1, n2, n3, i, j, k; + float tmp, *cubedata; + bool orbitalCubeFile = false; + int numberOfOrbitals; + + // Output 0 (the default is the polydata) + // Output 1 will be the gridded Image data + + vtkImageData *grid = this->GetGridOutput(); + + if (!this->FileName) + { + return 0; + } + + if ((fp = fopen(this->FileName, "r")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return 0; + } + + fgets(title, 256, fp); + if(strtok(title, ":") != NULL) + { + if(strtok(NULL, ":") != NULL) + { + strcpy(data_name, strtok(NULL, ":")); + fprintf(stderr,"label = %s\n", data_name); + } + } + fgets(title, 256, fp); + + // Read in number of atoms, x-origin, y-origin z-origin + // + fscanf(fp, "%d %lf %lf %lf", &(this->NumberOfAtoms), &elements[3], + &elements[7], &elements[11]); + if(this->NumberOfAtoms < 0 ) + { + this->NumberOfAtoms = -this->NumberOfAtoms; + orbitalCubeFile = true; + } + + fscanf(fp, "%d %lf %lf %lf", &n1, &elements[0], &elements[4], &elements[8]); + fscanf(fp, "%d %lf %lf %lf", &n2, &elements[1], &elements[5], &elements[9]); + fscanf(fp, "%d %lf %lf %lf", &n3, &elements[2], &elements[6], &elements[10]); + elements[12] = 0; + elements[13] = 0; + elements[14] = 0; + elements[15] = 1; + + vtkDebugMacro(<< "Grid Size " << n1 << " " << n2 << " " << n3); + + Transform->SetMatrix(elements); + Transform->Inverse(); + + this->ReadMolecule(fp, output); + + if(orbitalCubeFile) + { + fscanf(fp,"%d", &numberOfOrbitals); + for(k = 0; k < numberOfOrbitals; k++) + { + fscanf(fp,"%f", &tmp); + } + } + + vtkInformation *gridInfo = this->GetExecutive()->GetOutputInformation(1); + gridInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, n1-1, 0, n2-1, 0, n3-1); + gridInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + gridInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()), + 6); + grid->SetExtent( + gridInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); + + grid->SetOrigin(0, 0, 0); + grid->SetSpacing(1, 1, 1); + grid->SetScalarTypeToFloat(); + grid->AllocateScalars(); + + grid->GetPointData()->GetScalars()->SetName(title); + + cubedata = (float *)grid->GetPointData()->GetScalars()->GetVoidPointer(0); + N1N2 = n1*n2; + + for(i = 0; i < n1; i++) + { + JN1 = 0; + for(j = 0; j < n2; j++) + { + for(k = 0; k < n3; k++) + { + fscanf(fp,"%f", &tmp); + cubedata[k*N1N2 + JN1 + i] = tmp; + } + JN1 += n1; + } + } + fclose(fp); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkGaussianCubeReader::ReadSpecificMolecule(FILE* fp) +{ + int i, j; + float x[3]; + float dummy; + + for(i = 0; i < this->NumberOfAtoms; i++) + { + fscanf(fp, "%d %f %f %f %f", &j, &dummy, x, x+1, x+2); + this->Transform->TransformPoint(x, x); + this->Points->InsertNextPoint(x); + this->AtomType->InsertNextValue(j-1); + } +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkGaussianCubeReader::GetGridOutput() +{ + if (this->GetNumberOfOutputPorts() < 2) + { + return NULL; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetOutputData(1)); +} + +//---------------------------------------------------------------------------- +void vtkGaussianCubeReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << "Filename: " << (this->FileName?this->FileName:"(none)") << "\n"; + + os << "Tranform: "; + if( this->Transform ) + { + os << endl; + this->Transform->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)\n"; + } +} + +//---------------------------------------------------------------------------- +// Default implementation - copy information from first input to all outputs +int vtkGaussianCubeReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // the set the information for the imagedat output + vtkInformation *gridInfo = this->GetExecutive()->GetOutputInformation(1); + + FILE *fp; + char title[256]; + + if (!this->FileName) + { + return 0; + } + + if ((fp = fopen(this->FileName, "r")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return 0; + } + + fgets(title, 256, fp); + fgets(title, 256, fp); + + // Read in number of atoms, x-origin, y-origin z-origin + double tmpd; + int n1, n2, n3; + fscanf(fp, "%d %lf %lf %lf", &n1, &tmpd, &tmpd, &tmpd); + + fscanf(fp, "%d %lf %lf %lf", &n1, &tmpd, &tmpd, &tmpd); + fscanf(fp, "%d %lf %lf %lf", &n2, &tmpd, &tmpd, &tmpd); + fscanf(fp, "%d %lf %lf %lf", &n3, &tmpd, &tmpd, &tmpd); + + vtkDebugMacro(<< "Grid Size " << n1 << " " << n2 << " " << n3); + gridInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, n1-1, 0, n2-1, 0, n3-1); + gridInfo->Set(vtkDataObject::ORIGIN(), 0, 0, 0); + gridInfo->Set(vtkDataObject::SPACING(), 1, 1, 1); + + fclose(fp); + + vtkDataObject::SetPointDataActiveScalarInfo(gridInfo, VTK_FLOAT, -1); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkGaussianCubeReader::FillOutputPortInformation(int port, + vtkInformation* info) +{ + if(port == 0) + { + return this->Superclass::FillOutputPortInformation(port, info); + } + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} diff --git a/IO/vtkGaussianCubeReader.h b/IO/vtkGaussianCubeReader.h new file mode 100644 index 0000000..3f4665a --- /dev/null +++ b/IO/vtkGaussianCubeReader.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGaussianCubeReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGaussianCubeReader - read ASCII Gaussian Cube Data files +// .SECTION Description +// vtkGaussianCubeReader is a source object that reads ASCII files following +// the description in http://www.gaussian.com/00000430.htm +// The FileName must be specified. +// +// .SECTION Thanks +// Dr. Jean M. Favre who developed and contributed this class. + +#ifndef __vtkGaussianCubeReader_h +#define __vtkGaussianCubeReader_h + +#include "vtkMoleculeReaderBase.h" + +class vtkImageData; +class vtkTransform; + +class VTK_IO_EXPORT vtkGaussianCubeReader : public vtkMoleculeReaderBase +{ +public: + static vtkGaussianCubeReader *New(); + vtkTypeRevisionMacro(vtkGaussianCubeReader,vtkMoleculeReaderBase); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkGetObjectMacro(Transform,vtkTransform); + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + vtkImageData *GetGridOutput(); + +protected: + vtkGaussianCubeReader(); + ~vtkGaussianCubeReader(); + + char *FileName; + vtkTransform *Transform; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ReadSpecificMolecule(FILE* fp); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkGaussianCubeReader(const vtkGaussianCubeReader&); // Not implemented. + void operator=(const vtkGaussianCubeReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkGenericEnSightReader.cxx b/IO/vtkGenericEnSightReader.cxx new file mode 100644 index 0000000..f685a2e --- /dev/null +++ b/IO/vtkGenericEnSightReader.cxx @@ -0,0 +1,1500 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericEnSightReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericEnSightReader.h" + +#include "vtkCallbackCommand.h" +#include "vtkDataArrayCollection.h" +#include "vtkDataArraySelection.h" +#include "vtkDataSet.h" +#include "vtkEnSight6BinaryReader.h" +#include "vtkEnSight6Reader.h" +#include "vtkEnSightGoldBinaryReader.h" +#include "vtkEnSightGoldReader.h" +#include "vtkIdListCollection.h" +#include "vtkObjectFactory.h" + +#include +#include +#include +#include /* isspace */ + +vtkCxxRevisionMacro(vtkGenericEnSightReader, "$Revision: 1.74 $"); +vtkStandardNewMacro(vtkGenericEnSightReader); + +vtkCxxSetObjectMacro(vtkGenericEnSightReader,TimeSets, + vtkDataArrayCollection); + +class TranslationTableType +{ +public: + vtkstd::map PartIdMap; +}; + + +//---------------------------------------------------------------------------- +vtkGenericEnSightReader::vtkGenericEnSightReader() +{ + this->Reader = NULL; + this->IS = NULL; + this->IFile = NULL; + + this->CaseFileName = NULL; + this->GeometryFileName = NULL; + this->FilePath = NULL; + + this->VariableTypes = NULL; + this->ComplexVariableTypes = NULL; + + this->VariableDescriptions = NULL; + this->ComplexVariableDescriptions = NULL; + + this->NumberOfVariables = 0; + this->NumberOfComplexVariables = 0; + + this->NumberOfScalarsPerNode = 0; + this->NumberOfVectorsPerNode = 0; + this->NumberOfTensorsSymmPerNode = 0; + this->NumberOfScalarsPerElement = 0; + this->NumberOfVectorsPerElement = 0; + this->NumberOfTensorsSymmPerElement = 0; + this->NumberOfScalarsPerMeasuredNode = 0; + this->NumberOfVectorsPerMeasuredNode = 0; + this->NumberOfComplexScalarsPerNode = 0; + this->NumberOfComplexVectorsPerNode = 0; + this->NumberOfComplexScalarsPerElement = 0; + this->NumberOfComplexVectorsPerElement = 0; + + this->TimeValue = 0; + this->MinimumTimeValue = 0; + this->MaximumTimeValue = 0; + + this->TimeValueInitialized = 0; + + this->TimeSets = NULL; + + this->ReadAllVariables = 1; + + this->ByteOrder = FILE_UNKNOWN_ENDIAN; + + this->EnSightVersion = -1; + + this->PointDataArraySelection = vtkDataArraySelection::New(); + this->CellDataArraySelection = vtkDataArraySelection::New(); + + // Setup the selection callback to modify this object when an array + // selection is changed. + this->SelectionObserver = vtkCallbackCommand::New(); + this->SelectionObserver->SetCallback( + &vtkGenericEnSightReader::SelectionModifiedCallback); + this->SelectionObserver->SetClientData(this); + this->PointDataArraySelection->AddObserver(vtkCommand::ModifiedEvent, + this->SelectionObserver); + this->CellDataArraySelection->AddObserver(vtkCommand::ModifiedEvent, + this->SelectionObserver); + this->SelectionModifiedDoNotCallModified = 0; + this->TranslationTable = new TranslationTableType; + + this->SetNumberOfOutputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkGenericEnSightReader::~vtkGenericEnSightReader() +{ + int i; + + if (this->Reader) + { + this->Reader->Delete(); + this->Reader = NULL; + } + if (this->IS) + { + delete this->IS; + this->IS = NULL; + } + if (this->CaseFileName) + { + delete [] this->CaseFileName; + this->CaseFileName = NULL; + } + if (this->GeometryFileName) + { + delete [] this->GeometryFileName; + this->GeometryFileName = NULL; + } + if (this->FilePath) + { + delete [] this->FilePath; + this->FilePath = NULL; + } + if (this->NumberOfVariables > 0) + { + for (i = 0; i < this->NumberOfVariables; i++) + { + delete [] this->VariableDescriptions[i]; + } + delete [] this->VariableDescriptions; + delete [] this->VariableTypes; + this->VariableDescriptions = NULL; + this->VariableTypes = NULL; + } + if (this->NumberOfComplexVariables > 0) + { + for (i = 0; i < this->NumberOfComplexVariables; i++) + { + delete [] this->ComplexVariableDescriptions[i]; + } + delete [] this->ComplexVariableDescriptions; + delete [] this->ComplexVariableTypes; + this->ComplexVariableDescriptions = NULL; + this->ComplexVariableTypes = NULL; + } + + this->SetTimeSets(0); + this->CellDataArraySelection->RemoveObserver(this->SelectionObserver); + this->PointDataArraySelection->RemoveObserver(this->SelectionObserver); + this->SelectionObserver->Delete(); + this->CellDataArraySelection->Delete(); + this->PointDataArraySelection->Delete(); + delete this->TranslationTable; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::Execute() +{ + int i; + + if ( !this->Reader ) + { + return; + } + + // Set the real reader's data array selections from ours. + this->SetReaderDataArraySelectionSetsFromSelf(); + + this->Reader->SetTimeValue(this->GetTimeValue()); + this->Reader->Update(); + + this->NumberOfScalarsPerNode = this->Reader->GetNumberOfScalarsPerNode(); + this->NumberOfVectorsPerNode = this->Reader->GetNumberOfVectorsPerNode(); + this->NumberOfTensorsSymmPerNode = + this->Reader->GetNumberOfTensorsSymmPerNode(); + this->NumberOfScalarsPerElement = + this->Reader->GetNumberOfScalarsPerElement(); + this->NumberOfVectorsPerElement = + this->Reader->GetNumberOfVectorsPerElement(); + this->NumberOfTensorsSymmPerElement = + this->Reader->GetNumberOfTensorsSymmPerElement(); + this->NumberOfScalarsPerMeasuredNode = + this->Reader->GetNumberOfScalarsPerMeasuredNode(); + this->NumberOfVectorsPerMeasuredNode = + this->Reader->GetNumberOfVectorsPerMeasuredNode(); + this->NumberOfComplexScalarsPerNode = + this->Reader->GetNumberOfComplexScalarsPerNode(); + this->NumberOfComplexVectorsPerNode = + this->Reader->GetNumberOfComplexVectorsPerNode(); + this->NumberOfComplexScalarsPerElement = + this->Reader->GetNumberOfComplexScalarsPerElement(); + this->NumberOfComplexVectorsPerElement = + this->Reader->GetNumberOfComplexScalarsPerElement(); + + for (i = 0; i < this->Reader->GetNumberOfOutputs(); i++) + { + vtkDataObject* output = this->GetOutput(i); + if ( ! output ) + { + // Copy the output rather than setting directly. + // When we set directly, the internal reader looses its output. + // Next execute, a new output is added, + // and another partid is added too. + vtkDataObject* tmp = this->Reader->GetOutput(i); + if( tmp ) + { + output = tmp->NewInstance(); + this->SetNthOutput(i, output); // law: this causes the extra partid bug + output->ShallowCopy(tmp); + output->CopyInformation(tmp); + output->Delete(); + // Used later. + //output = NULL; + } + else + { + this->SetNthOutput(i, 0); + } + } + else + { + // We don't know the number of outputs or whole extent of the + // internal reader's data until after it executes. Therefore, + // the update extent of the reader is set to empty. Since the + // reader ignores the update extent anyway, it reads correctly, + // but then this shallow copy destroys this reader's update + // extent. Save it and restore. + int tempExtent[6]; + output->GetUpdateExtent(tempExtent); + output->ShallowCopy(this->Reader->GetOutput(i)); + output->SetUpdateExtent(tempExtent); + } + // Since most unstructured filters in VTK generate all their data once, + // make it the default. + // protected: if ( output->GetExtentType() == VTK_PIECES_EXTENT ) + if (output && ( output->IsA("vtkPolyData") || output->IsA("vtkUnstructuredGrid"))) + { + output->SetMaximumNumberOfPieces(1); + } + } + for (i = 0; i < this->Reader->GetNumberOfVariables(); i++) + { + this->AddVariableDescription(this->Reader->GetDescription(i)); + this->AddVariableType(this->Reader->GetVariableType(i)); + this->NumberOfVariables++; + } + for (i = 0; i < this->Reader->GetNumberOfComplexVariables(); i++) + { + this->AddComplexVariableDescription( + this->Reader->GetComplexDescription(i)); + this->AddComplexVariableType(this->Reader->GetComplexVariableType(i)); + this->NumberOfComplexVariables++; + } +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetTimeValue(float value) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting TimeValue to " << value); + if (this->TimeValue != value) + { + this->TimeValue = value; + this->Modified(); + } + this->TimeValueInitialized = 1; +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::DetermineEnSightVersion() +{ + char line[256], subLine[256], subLine1[256], subLine2[256], binaryLine[81]; + int stringRead; + int timeSet = 1, fileSet = 1; + int xtimeSet= 1, xfileSet= 1; + char *fileName = NULL; + + if (!this->CaseFileName) + { + vtkErrorMacro("A case file name must be specified."); + return -1; + } + vtkstd::string sfilename = ""; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += this->CaseFileName; + vtkDebugMacro("full path to case file: " + << sfilename.c_str()); + } + else + { + sfilename = this->CaseFileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + if (this->IS->fail()) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + delete this->IS; + this->IS = NULL; + return -1; + } + + this->ReadNextDataLine(line); + + if (strncmp(line, "FORMAT", 6) == 0) + { + // found the FORMAT section + vtkDebugMacro("*** FORMAT section"); + this->ReadNextDataLine(line); + + stringRead = sscanf(line, " %*s %*s %s", subLine); + if (stringRead == 1) + { + sscanf(line, " %*s %s %s", subLine1, subLine2); + if (strncmp(subLine1,"ensight",7) == 0) + { + if (strncmp(subLine2,"gold",4) == 0) + { + this->ReadNextDataLine(line); + if (strncmp(line, "GEOMETRY", 8) == 0) + { + // found the GEOMETRY section + vtkDebugMacro("*** GEOMETRY section"); + + this->ReadNextDataLine(line); + if (strncmp(line, "model:", 6) == 0) + { + if (sscanf(line, " %*s %d %d %s", &xtimeSet, &fileSet, subLine) == 3) + { + timeSet = xtimeSet; + fileSet = xfileSet; + this->SetGeometryFileName(subLine); + } + else if (sscanf(line, " %*s %d%*[ \t]%s", &xtimeSet, subLine) == 2) + { + timeSet = xtimeSet; + this->SetGeometryFileName(subLine); + } + else if (sscanf(line, " %*s %s", subLine) == 1) + { + this->SetGeometryFileName(subLine); + } + } // geometry file name set + delete this->IS; + this->IS = NULL; + + fileName = new char[strlen(this->GeometryFileName) + 1]; + strcpy(fileName, this->GeometryFileName); + + if (!fileName) + { + vtkErrorMacro( + "A GeometryFileName must be specified in the case file."); + return 0; + } + if (strrchr(fileName, '*') != NULL) + { + // reopen case file; find right time set and fill in + // wildcards from there if possible; if not, then find right + // file set and fill in wildcards from there. + this->ReplaceWildcards(fileName, timeSet, fileSet); + } + sfilename = ""; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to geometry file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + // got full path to geometry file + + this->IFile = fopen(sfilename.c_str(), "rb"); + if (this->IFile == NULL) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + vtkWarningMacro("Assuming binary file."); + this->IFile = NULL; + delete [] fileName; + return vtkGenericEnSightReader::ENSIGHT_GOLD_BINARY; + } // end if IFile == NULL + + this->ReadBinaryLine(binaryLine); + binaryLine[80] = '\0'; + sscanf(binaryLine, " %*s %s", subLine); + // If the file is ascii, there might not be a null + // terminator. This leads to a UMR in sscanf + if (strncmp(subLine,"Binary",6) == 0 || + strncmp(subLine,"binary",6) == 0) + { + fclose(this->IFile); + this->IFile = NULL; + delete [] fileName; + return vtkGenericEnSightReader::ENSIGHT_GOLD_BINARY; + } //end if binary + + fclose(this->IFile); + this->IFile = NULL; + delete [] fileName; + return vtkGenericEnSightReader::ENSIGHT_GOLD; + } // if we found the geometry section in the case file + } // if ensight gold file + } // if regular ensight file (not master_server) + else if (strncmp(subLine1,"master_server",13) == 0) + { + return vtkGenericEnSightReader::ENSIGHT_MASTER_SERVER; + } + } // if the type line is like "type: xxxx xxxx" + else + { + this->ReadNextDataLine(line); + if (strncmp(line, "GEOMETRY", 8) == 0) + { + // found the GEOMETRY section + vtkDebugMacro("*** GEOMETRY section"); + + this->ReadNextDataLine(line); + if (strncmp(line, "model:", 6) == 0) + { + if (sscanf(line, " %*s %d %d %s", &xtimeSet, &fileSet, subLine) == 3) + { + timeSet = xtimeSet; + fileSet = xfileSet; + this->SetGeometryFileName(subLine); + } + else if (sscanf(line, " %*s %d%*[ \t]%s", &xtimeSet, subLine) == 2) + { + timeSet = xtimeSet; + this->SetGeometryFileName(subLine); + } + else if (sscanf(line, " %*s %s", subLine) == 1) + { + this->SetGeometryFileName(subLine); + } + } // geometry file name set + + fileName = new char[strlen(this->GeometryFileName) + 1]; + strcpy(fileName, this->GeometryFileName); + + delete this->IS; + this->IS = NULL; + if (!fileName) + { + vtkErrorMacro( + "A GeometryFileName must be specified in the case file."); + return 0; + } + if (strrchr(fileName, '*') != NULL) + { + // reopen case file; find right time set and fill in wildcards from + // there if possible; if not, then find right file set and fill in + // wildcards from there. + this->ReplaceWildcards(fileName, timeSet, fileSet); + } + sfilename = ""; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += fileName; + vtkDebugMacro("full path to geometry file: " + << sfilename.c_str()); + } + else + { + sfilename = fileName; + } + + // got full path to geometry file + + this->IFile = fopen(sfilename.c_str(), "rb"); + if (this->IFile == NULL) + { + vtkErrorMacro("Unable to open file: " << sfilename.c_str()); + vtkWarningMacro("Assuming binary file."); + this->IFile = NULL; + delete [] fileName; + return vtkGenericEnSightReader::ENSIGHT_6_BINARY; + } // end if IFile == NULL + + this->ReadBinaryLine(binaryLine); + // If the file is ascii, there might not be a null + // terminator. This leads to a UMR in sscanf + binaryLine[80] = '\0'; + sscanf(binaryLine, " %*s %s", subLine); + if (strncmp(subLine,"Binary",6) == 0) + { + fclose(this->IFile); + this->IFile = NULL; + delete [] fileName; + return vtkGenericEnSightReader::ENSIGHT_6_BINARY; + } //end if binary + + fclose(this->IFile); + this->IFile = NULL; + delete [] fileName; + return vtkGenericEnSightReader::ENSIGHT_6; + } // if we found the geometry section in the case file + } // not ensight gold + } // if we found the format section in the case file + + if (fileName) + { + delete [] fileName; + } + + return -1; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetCaseFileName(const char* fileName) +{ + char *endingSlash; + char *path, *newFileName; + int position, numChars; + + if ( this->CaseFileName && fileName && + (!strcmp(this->CaseFileName, fileName))) + { + return; + } + if (this->CaseFileName) + { + delete [] this->CaseFileName; + } + if (fileName) + { + this->CaseFileName = new char[strlen(fileName)+1]; + strcpy(this->CaseFileName, fileName); + } + else + { + this->CaseFileName = NULL; + } + + this->Modified(); + if (!this->CaseFileName) + { + return; + } + + // strip off the path and save it as FilePath if it was included in the + // filename + if ((endingSlash = strrchr(this->CaseFileName, '/'))) + { + position = endingSlash - this->CaseFileName + 1; + path = new char[position + 1]; + numChars = static_cast(strlen(this->CaseFileName)); + newFileName = new char[numChars - position + 1]; + strcpy(path, ""); + strncat(path, this->CaseFileName, position); + this->SetFilePath(path); + strcpy(newFileName, this->CaseFileName + position); + strcpy(this->CaseFileName, newFileName); + delete [] path; + delete [] newFileName; + } + +} + +//---------------------------------------------------------------------------- +// Internal function to read in a line up to 256 characters. +// Returns zero if there was an error. +int vtkGenericEnSightReader::ReadLine(char result[256]) +{ + this->IS->getline(result,256); +// if (this->IS->eof()) + if (this->IS->fail()) + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Internal function to read in a line (from a binary file) up +// to 80 characters. Returns zero if there was an error. +int vtkGenericEnSightReader::ReadBinaryLine(char result[80]) +{ + fread(result, sizeof(char), 80, this->IFile); + + if (feof(this->IFile) || ferror(this->IFile)) + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Internal function that skips blank lines and comment lines +// and reads the next line it finds (up to 256 characters). +// Returns 0 is there was an error. +int vtkGenericEnSightReader::ReadNextDataLine(char result[256]) +{ + int isComment = 1; + int value = 1; + + while( isComment && value ) + { + value = this->ReadLine(result); + if( *result && result[0] != '#' ) + { + size_t len = strlen( result ); + unsigned int i = 0; + while( i < len && isspace( result[i] ) ) + { + ++i; + } + // If there was only space characters this is a comment, thus skip it + if( i != len ) + { + // The line was not empty, not begining by '#' and not composed + // of only white space, this is not a comment + isComment = 0; + } + } + } + + return value; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::Update() +{ + int i; + + this->UpdateInformation(); + this->Execute(); + + for (i = 0; i < this->GetNumberOfOutputs(); i++) + { + if ( this->GetOutput(i) ) + { + this->GetOutput(i)->DataHasBeenGenerated(); + this->GetOutput(i)->SetUpdateExtentToWholeExtent(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::ExecuteInformation() +{ + int version = this->DetermineEnSightVersion(); + int createReader = 1; + if (version == vtkGenericEnSightReader::ENSIGHT_6) + { + vtkDebugMacro("EnSight6"); + if (this->Reader) + { + if (strcmp(this->Reader->GetClassName(), "vtkEnSight6Reader") == 0) + { + createReader = 0; + } + else + { + this->Reader->Delete(); + } + } + if (createReader) + { + this->Reader = vtkEnSight6Reader::New(); + } + } + else if (version == vtkGenericEnSightReader::ENSIGHT_6_BINARY) + { + vtkDebugMacro("EnSight6 binary"); + if (this->Reader) + { + if (strcmp(this->Reader->GetClassName(), "vtkEnSight6BinaryReader") == 0) + { + createReader = 0; + } + else + { + this->Reader->Delete(); + } + } + if (createReader) + { + this->Reader = vtkEnSight6BinaryReader::New(); + } + } + else if (version == vtkGenericEnSightReader::ENSIGHT_GOLD) + { + vtkDebugMacro("EnSightGold"); + if (this->Reader) + { + if (strcmp(this->Reader->GetClassName(), "vtkEnSightGoldReader") == 0) + { + createReader = 0; + } + else + { + this->Reader->Delete(); + } + } + if (createReader) + { + this->Reader = vtkEnSightGoldReader::New(); + } + } + else if (version == vtkGenericEnSightReader::ENSIGHT_GOLD_BINARY) + { + vtkDebugMacro("EnSightGold binary"); + if (this->Reader) + { + if (strcmp(this->Reader->GetClassName(), + "vtkEnSightGoldBinaryReader") == 0) + { + createReader = 0; + } + else + { + this->Reader->Delete(); + } + } + if (createReader) + { + this->Reader = vtkEnSightGoldBinaryReader::New(); + } + } + else + { + vtkErrorMacro("Error determining EnSightVersion"); + this->EnSightVersion = -1; + return; + } + this->EnSightVersion = version; + + // Copy current array selections to internal reader. + this->SetReaderDataArraySelectionSetsFromSelf(); + this->Reader->SetReadAllVariables(this->ReadAllVariables); + this->Reader->SetCaseFileName(this->GetCaseFileName()); + this->Reader->SetFilePath(this->GetFilePath()); + this->Reader->SetByteOrder(this->ByteOrder); + this->Reader->UpdateInformation(); + + this->SetTimeSets(this->Reader->GetTimeSets()); + if(!this->TimeValueInitialized) + { + this->SetTimeValue(this->Reader->GetTimeValue()); + } + this->MinimumTimeValue = this->Reader->GetMinimumTimeValue(); + this->MaximumTimeValue = this->Reader->GetMaximumTimeValue(); + + // Copy new data array selections from internal reader. + this->SetDataArraySelectionSetsFromReader(); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::AddVariableDescription(const char* description) +{ + int size = this->NumberOfVariables; + int i; + + char ** newDescriptionList = new char *[size]; // temporary array + + // copy descriptions to temporary array + for (i = 0; i < size; i++) + { + newDescriptionList[i] = + new char[strlen(this->VariableDescriptions[i]) + 1]; + strcpy(newDescriptionList[i], this->VariableDescriptions[i]); + delete [] this->VariableDescriptions[i]; + } + if (this->VariableDescriptions) + { + delete [] this->VariableDescriptions; + } + + // make room for new description + this->VariableDescriptions = new char *[size+1]; + + // copy existing descriptions back to first array + for (i = 0; i < size; i++) + { + this->VariableDescriptions[i] = + new char[strlen(newDescriptionList[i]) + 1]; + strcpy(this->VariableDescriptions[i], newDescriptionList[i]); + delete [] newDescriptionList[i]; + } + delete [] newDescriptionList; + + // add new description at end of first array + this->VariableDescriptions[size] = new char[strlen(description) + 1]; + strcpy(this->VariableDescriptions[size], description); + vtkDebugMacro("description: " << this->VariableDescriptions[size]); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::AddComplexVariableDescription(const char* description) +{ + int i; + int size = this->NumberOfComplexVariables; + char ** newDescriptionList = new char *[size]; // temporary array + + // copy descriptions to temporary array + for (i = 0; i < size; i++) + { + newDescriptionList[i] = + new char[strlen(this->ComplexVariableDescriptions[i]) + 1]; + strcpy(newDescriptionList[i], this->ComplexVariableDescriptions[i]); + delete [] this->ComplexVariableDescriptions[i]; + } + delete [] this->ComplexVariableDescriptions; + + // make room for new description + this->ComplexVariableDescriptions = new char *[size+1]; + + // copy existing descriptions back to first array + for (i = 0; i < size; i++) + { + this->ComplexVariableDescriptions[i] = + new char[strlen(newDescriptionList[i]) + 1]; + strcpy(this->ComplexVariableDescriptions[i], newDescriptionList[i]); + delete [] newDescriptionList[i]; + } + delete [] newDescriptionList; + + // add new description at end of first array + this->ComplexVariableDescriptions[size] = + new char[strlen(description) + 1]; + strcpy(this->ComplexVariableDescriptions[size], description); + vtkDebugMacro("description: " + << this->ComplexVariableDescriptions[size]); +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::GetNumberOfVariables(int type) +{ + switch (type) + { + case vtkEnSightReader::SCALAR_PER_NODE: + return this->GetNumberOfScalarsPerNode(); + case vtkEnSightReader::VECTOR_PER_NODE: + return this->GetNumberOfVectorsPerNode(); + case vtkEnSightReader::TENSOR_SYMM_PER_NODE: + return this->GetNumberOfTensorsSymmPerNode(); + case vtkEnSightReader::SCALAR_PER_ELEMENT: + return this->GetNumberOfScalarsPerElement(); + case vtkEnSightReader::VECTOR_PER_ELEMENT: + return this->GetNumberOfVectorsPerElement(); + case vtkEnSightReader::TENSOR_SYMM_PER_ELEMENT: + return this->GetNumberOfTensorsSymmPerElement(); + case vtkEnSightReader::SCALAR_PER_MEASURED_NODE: + return this->GetNumberOfScalarsPerMeasuredNode(); + case vtkEnSightReader::VECTOR_PER_MEASURED_NODE: + return this->GetNumberOfVectorsPerMeasuredNode(); + case vtkEnSightReader::COMPLEX_SCALAR_PER_NODE: + return this->GetNumberOfComplexScalarsPerNode(); + case vtkEnSightReader::COMPLEX_VECTOR_PER_NODE: + return this->GetNumberOfComplexVectorsPerNode(); + case vtkEnSightReader::COMPLEX_SCALAR_PER_ELEMENT: + return this->GetNumberOfComplexScalarsPerElement(); + case vtkEnSightReader::COMPLEX_VECTOR_PER_ELEMENT: + return this->GetNumberOfComplexVectorsPerElement(); + default: + vtkWarningMacro("unknow variable type"); + return -1; + } +} + +//---------------------------------------------------------------------------- +const char* vtkGenericEnSightReader::GetDescription(int n) +{ + if (n < this->NumberOfVariables) + { + return this->VariableDescriptions[n]; + } + return NULL; +} + +//---------------------------------------------------------------------------- +const char* vtkGenericEnSightReader::GetComplexDescription(int n) +{ + if (n < this->NumberOfComplexVariables) + { + return this->ComplexVariableDescriptions[n]; + } + return NULL; +} + +//---------------------------------------------------------------------------- +const char* vtkGenericEnSightReader::GetDescription(int n, int type) +{ + int i, numMatches = 0; + + if (type < 8) + { + for (i = 0; i < this->NumberOfVariables; i++) + { + if (this->VariableTypes[i] == type) + { + if (numMatches == n) + { + return this->VariableDescriptions[i]; + } + else + { + numMatches++; + } + } + } + } + else + { + for (i = 0; i < this->NumberOfVariables; i++) + { + if (this->ComplexVariableTypes[i] == type) + { + if (numMatches == n) + { + return this->ComplexVariableDescriptions[i]; + } + else + { + numMatches++; + } + } + } + } + + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::AddVariableType(int variableType) +{ + int size; + int i; + int *types; + + size = this->NumberOfVariables; + + types = new int[size]; + + for (i = 0; i < size; i++) + { + types[i] = this->VariableTypes[i]; + } + delete [] this->VariableTypes; + + this->VariableTypes = new int[size+1]; + for (i = 0; i < size; i++) + { + this->VariableTypes[i] = types[i]; + } + delete [] types; + this->VariableTypes[size] = variableType; + vtkDebugMacro("variable type: " << this->VariableTypes[size]); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::AddComplexVariableType(int variableType) +{ + int i; + int* types = NULL; + int size = this->NumberOfComplexVariables; + + if (size > 0) + { + types = new int[size]; + for (i = 0; i < size; i++) + { + types[i] = this->ComplexVariableTypes[i]; + } + delete [] this->ComplexVariableTypes; + } + + this->ComplexVariableTypes = new int[size+1]; + for (i = 0; i < size; i++) + { + this->ComplexVariableTypes[i] = types[i]; + } + + if (size > 0) + { + delete [] types; + } + this->ComplexVariableTypes[size] = variableType; + vtkDebugMacro("complex variable type: " + << this->ComplexVariableTypes[size]); +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::GetVariableType(int n) +{ + if (n < this->NumberOfVariables) + { + return this->VariableTypes[n]; + } + return -1; +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::GetComplexVariableType(int n) +{ + if (n < this->NumberOfComplexVariables) + { + return this->ComplexVariableTypes[n]; + } + return -1; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::ReplaceWildcards(char* fileName, int timeSet, + int fileSet) +{ + char line[256], subLine[256]; + int cmpTimeSet, cmpFileSet, fileNameNum; + + vtkstd::string sfilename; + if (this->FilePath) + { + sfilename = this->FilePath; + if (sfilename.at(sfilename.length()-1) != '/') + { + sfilename += "/"; + } + sfilename += this->CaseFileName; + vtkDebugMacro("full path to case file: " + << sfilename.c_str()); + } + else + { + sfilename = this->CaseFileName; + } + + this->IS = new ifstream(sfilename.c_str(), ios::in); + + // We already know we have a valid case file if we've gotten to this point. + + this->ReadLine(line); + while (strncmp(line, "TIME", 4) != 0) + { + this->ReadLine(line); + } + + this->ReadNextDataLine(line); + sscanf(line, " %*s %*s %d", &cmpTimeSet); + while (cmpTimeSet != timeSet) + { + this->ReadNextDataLine(line); + this->ReadNextDataLine(line); + sscanf(line, " %s", subLine); + if (strncmp(subLine, "filename", 8) == 0) + { + this->ReadNextDataLine(line); + } + if (strncmp(subLine, "filename", 8) == 0) + { + this->ReadNextDataLine(line); + } + sscanf(line, " %*s %*s %d", &cmpTimeSet); + } + + this->ReadNextDataLine(line); // number of timesteps + this->ReadNextDataLine(line); + sscanf(line, " %s", subLine); + if (strncmp(subLine, "filename", 8) == 0) + { + sscanf(line, " %*s %s", subLine); + if (strncmp(subLine, "start", 5) == 0) + { + sscanf(line, " %*s %*s %*s %d", &fileNameNum); + } + else + { + sscanf(line, " %*s %*s %d", &fileNameNum); + } + this->ReplaceWildcardsHelper(fileName, fileNameNum); + } + else + { + while (strncmp(line, "FILE", 4) != 0) + { + this->ReadLine(line); + } + this->ReadNextDataLine(line); + sscanf(line, " %*s %*s %d", &cmpFileSet); + while (cmpFileSet != fileSet) + { + this->ReadNextDataLine(line); + this->ReadNextDataLine(line); + sscanf(line, " %s", subLine); + if (strncmp(subLine, "filename", 8) == 0) + { + this->ReadNextDataLine(line); + } + sscanf(line, " %*s %*s %d", &cmpFileSet); + } + this->ReadNextDataLine(line); + sscanf(line, " %*s %*s %d", &fileNameNum); + this->ReplaceWildcardsHelper(fileName, fileNameNum); + } + + delete this->IS; + this->IS = NULL; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::ReplaceWildcardsHelper(char* fileName, int num) +{ + int wildcardPos, numWildcards, numDigits = 1, i; + int tmpNum = num, multTen = 1; + char newChar; + int newNum; + + wildcardPos = static_cast(strcspn(fileName, "*")); + numWildcards = static_cast(strspn(fileName + wildcardPos, "*")); + + tmpNum /= 10; + while (tmpNum >= 1) + { + numDigits++; + multTen *= 10; + tmpNum /= 10; + } + + for (i = 0; i < numWildcards - numDigits; i++) + { + fileName[i + wildcardPos] = '0'; + } + + tmpNum = num; + for (i = numWildcards - numDigits; i < numWildcards; i++) + { + newNum = tmpNum / multTen; + switch (newNum) + { + case 0: + newChar = '0'; + break; + case 1: + newChar = '1'; + break; + case 2: + newChar = '2'; + break; + case 3: + newChar = '3'; + break; + case 4: + newChar = '4'; + break; + case 5: + newChar = '5'; + break; + case 6: + newChar = '6'; + break; + case 7: + newChar = '7'; + break; + case 8: + newChar = '8'; + break; + case 9: + newChar = '9'; + break; + default: + // This case should never be reached. + return; + } + assert( newChar == ('0' + newNum) ); + + fileName[i + wildcardPos] = newChar; + tmpNum -= multTen * newNum; + multTen /= 10; + } +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetByteOrderToBigEndian() +{ + this->ByteOrder = FILE_BIG_ENDIAN; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetByteOrderToLittleEndian() +{ + this->ByteOrder = FILE_LITTLE_ENDIAN; +} + +//---------------------------------------------------------------------------- +const char *vtkGenericEnSightReader::GetByteOrderAsString() +{ + if ( this->ByteOrder == FILE_LITTLE_ENDIAN) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "CaseFileName: " + << (this->CaseFileName ? this->CaseFileName : "(none)") << endl; + os << indent << "FilePath: " + << (this->FilePath ? this->FilePath : "(none)") << endl; + os << indent << "NumberOfComplexVariables: " + << this->NumberOfComplexVariables << endl; + os << indent << "NumberOfVariables: " + << this->NumberOfVariables << endl; + os << indent << "NumberOfComplexScalarsPerNode: " + << this->NumberOfComplexScalarsPerNode << endl; + os << indent << "NumberOfVectorsPerElement :" + << this->NumberOfVectorsPerElement << endl; + os << indent << "NumberOfTensorsSymmPerElement: " + << this->NumberOfTensorsSymmPerElement << endl; + os << indent << "NumberOfComplexVectorsPerNode: " + << this->NumberOfComplexVectorsPerNode << endl; + os << indent << "NumberOfScalarsPerElement: " + << this->NumberOfScalarsPerElement << endl; + os << indent << "NumberOfComplexVectorsPerElement: " + << this->NumberOfComplexVectorsPerElement << endl; + os << indent << "NumberOfComplexScalarsPerElement: " + << this->NumberOfComplexScalarsPerElement << endl; + os << indent << "NumberOfTensorsSymmPerNode: " + << this->NumberOfTensorsSymmPerNode << endl; + os << indent << "NumberOfScalarsPerMeasuredNode: " + << this->NumberOfScalarsPerMeasuredNode << endl; + os << indent << "NumberOfVectorsPerMeasuredNode: " + << this->NumberOfVectorsPerMeasuredNode << endl; + os << indent << "NumberOfScalarsPerNode: " + << this->NumberOfScalarsPerNode << endl; + os << indent << "NumberOfVectorsPerNode: " + << this->NumberOfVectorsPerNode << endl; + os << indent << "TimeValue: " << this->TimeValue << endl; + os << indent << "MinimumTimeValue: " << this->MinimumTimeValue << endl; + os << indent << "MaximumTimeValue: " << this->MaximumTimeValue << endl; + os << indent << "TimeSets: " << this->TimeSets << endl; + os << indent << "ReadAllVariables: " << this->ReadAllVariables << endl; + os << indent << "ByteOrder: " << this->ByteOrder << endl; + os << indent << "CellDataArraySelection: " << this->CellDataArraySelection + << endl; + os << indent << "PointDataArraySelection: " << this->PointDataArraySelection + << endl; +} + +//---------------------------------------------------------------------------- +char** vtkGenericEnSightReader::CreateStringArray(int numStrings) +{ + char** strings = new char*[numStrings]; + int i; + for(i=0; i < numStrings; ++i) + { + strings[i] = 0; + } + return strings; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::DestroyStringArray(int numStrings, + char** strings) +{ + int i; + for(i=0; i < numStrings; ++i) + { + if(strings[i]) + { + delete [] strings[i]; + } + } + delete[] strings; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetDataArraySelectionSetsFromVariables() +{ + int numPointArrays = (this->NumberOfScalarsPerNode + + this->NumberOfVectorsPerNode + + this->NumberOfTensorsSymmPerNode + + this->NumberOfScalarsPerMeasuredNode + + this->NumberOfVectorsPerMeasuredNode + + this->NumberOfComplexScalarsPerNode + + this->NumberOfComplexVectorsPerNode); + int numCellArrays = (this->NumberOfScalarsPerElement + + this->NumberOfVectorsPerElement + + this->NumberOfTensorsSymmPerElement + + this->NumberOfComplexScalarsPerElement + + this->NumberOfComplexVectorsPerElement); + + char** pointNames = this->CreateStringArray(numPointArrays); + char** cellNames = this->CreateStringArray(numCellArrays); + int pointArrayCount = 0; + int cellArrayCount = 0; + + int i; + for(i=0; i < this->NumberOfVariables; ++i) + { + switch (this->VariableTypes[i]) + { + case vtkEnSightReader::SCALAR_PER_NODE: + case vtkEnSightReader::VECTOR_PER_NODE: + case vtkEnSightReader::TENSOR_SYMM_PER_NODE: + case vtkEnSightReader::SCALAR_PER_MEASURED_NODE: + case vtkEnSightReader::VECTOR_PER_MEASURED_NODE: + pointNames[pointArrayCount] = + new char[strlen(this->VariableDescriptions[i])+1]; + strcpy(pointNames[pointArrayCount], this->VariableDescriptions[i]); + ++pointArrayCount; + break; + case vtkEnSightReader::SCALAR_PER_ELEMENT: + case vtkEnSightReader::VECTOR_PER_ELEMENT: + case vtkEnSightReader::TENSOR_SYMM_PER_ELEMENT: + cellNames[cellArrayCount] = + new char[strlen(this->VariableDescriptions[i])+1]; + strcpy(cellNames[cellArrayCount], this->VariableDescriptions[i]); + ++cellArrayCount; + break; + } + } + for(i=0; i < this->NumberOfComplexVariables; ++i) + { + switch(this->ComplexVariableTypes[i]) + { + case vtkEnSightReader::COMPLEX_SCALAR_PER_NODE: + case vtkEnSightReader::COMPLEX_VECTOR_PER_NODE: + pointNames[pointArrayCount] = + new char[strlen(this->ComplexVariableDescriptions[i])+1]; + strcpy(pointNames[pointArrayCount], + this->ComplexVariableDescriptions[i]); + ++pointArrayCount; + break; + case vtkEnSightReader::COMPLEX_SCALAR_PER_ELEMENT: + case vtkEnSightReader::COMPLEX_VECTOR_PER_ELEMENT: + cellNames[cellArrayCount] = + new char[strlen(this->ComplexVariableDescriptions[i])+1]; + strcpy(cellNames[cellArrayCount], + this->ComplexVariableDescriptions[i]); + ++cellArrayCount; + break; + } + } + + this->PointDataArraySelection->SetArraysWithDefault(pointNames, + numPointArrays, + this->ReadAllVariables); + this->CellDataArraySelection->SetArraysWithDefault(cellNames, + numCellArrays, + this->ReadAllVariables); + this->DestroyStringArray(numPointArrays, pointNames); + this->DestroyStringArray(numCellArrays, cellNames); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetDataArraySelectionSetsFromReader() +{ + this->SelectionModifiedDoNotCallModified = 1; + this->PointDataArraySelection->CopySelections( + this->Reader->GetPointDataArraySelection()); + this->CellDataArraySelection->CopySelections( + this->Reader->GetCellDataArraySelection()); + this->SelectionModifiedDoNotCallModified = 0; +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetReaderDataArraySelectionSetsFromSelf() +{ + // Set the real reader's data array selections from ours. + this->Reader->GetPointDataArraySelection()->CopySelections( + this->PointDataArraySelection); + this->Reader->GetCellDataArraySelection()->CopySelections( + this->CellDataArraySelection); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SelectionModifiedCallback(vtkObject*, + unsigned long, + void* clientdata, + void*) +{ + static_cast(clientdata)->SelectionModified(); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SelectionModified() +{ + if(!this->SelectionModifiedDoNotCallModified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::GetNumberOfPointArrays() +{ + return this->PointDataArraySelection->GetNumberOfArrays(); +} + +//---------------------------------------------------------------------------- +const char* vtkGenericEnSightReader::GetPointArrayName(int index) +{ + return this->PointDataArraySelection->GetArrayName(index); +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::GetPointArrayStatus(const char* name) +{ + return this->PointDataArraySelection->ArrayIsEnabled(name); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetPointArrayStatus(const char* name, int status) +{ + if(status) + { + this->PointDataArraySelection->EnableArray(name); + } + else + { + this->PointDataArraySelection->DisableArray(name); + } +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::GetNumberOfCellArrays() +{ + return this->CellDataArraySelection->GetNumberOfArrays(); +} + +//---------------------------------------------------------------------------- +const char* vtkGenericEnSightReader::GetCellArrayName(int index) +{ + return this->CellDataArraySelection->GetArrayName(index); +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::GetCellArrayStatus(const char* name) +{ + return this->CellDataArraySelection->ArrayIsEnabled(name); +} + +//---------------------------------------------------------------------------- +void vtkGenericEnSightReader::SetCellArrayStatus(const char* name, int status) +{ + if(status) + { + this->CellDataArraySelection->EnableArray(name); + } + else + { + this->CellDataArraySelection->DisableArray(name); + } +} + +//---------------------------------------------------------------------------- +int vtkGenericEnSightReader::InsertNewPartId(int partId) +{ + int lastId = this->TranslationTable->PartIdMap.size(); + this->TranslationTable->PartIdMap.insert( + vtkstd::map::value_type(partId, lastId)); + lastId = this->TranslationTable->PartIdMap[partId]; + //assert( lastId == this->PartIdTranslationTable[partId] ); + return lastId; +} diff --git a/IO/vtkGenericEnSightReader.h b/IO/vtkGenericEnSightReader.h new file mode 100644 index 0000000..699e75c --- /dev/null +++ b/IO/vtkGenericEnSightReader.h @@ -0,0 +1,320 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericEnSightReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericEnSightReader - class to read any type of EnSight files +// .SECTION Description +// The class vtkGenericEnSightReader allows the user to read an EnSight data +// set without a priori knowledge of what type of EnSight data set it is. + +#ifndef __vtkGenericEnSightReader_h +#define __vtkGenericEnSightReader_h + +#include "vtkDataSetSource.h" + +class vtkCallbackCommand; +class vtkDataArrayCollection; +class vtkDataArraySelection; +class vtkIdListCollection; +//BTX +class TranslationTableType; +//ETX + +class VTK_IO_EXPORT vtkGenericEnSightReader : public vtkDataSetSource +{ +public: + static vtkGenericEnSightReader *New(); + vtkTypeRevisionMacro(vtkGenericEnSightReader, vtkDataSetSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the Case file name. + void SetCaseFileName(const char* fileName); + vtkGetStringMacro(CaseFileName); + + // Description: + // Set/Get the file path. + vtkSetStringMacro(FilePath); + vtkGetStringMacro(FilePath); + + virtual void Update(); + virtual void ExecuteInformation(); + + // Description: + // Get the number of variables listed in the case file. + vtkGetMacro(NumberOfVariables, int); + vtkGetMacro(NumberOfComplexVariables, int); + + // Description: + // Get the number of variables of a particular type. + int GetNumberOfVariables(int type); // returns -1 if unknown type specified + vtkGetMacro(NumberOfScalarsPerNode, int); + vtkGetMacro(NumberOfVectorsPerNode, int); + vtkGetMacro(NumberOfTensorsSymmPerNode, int); + vtkGetMacro(NumberOfScalarsPerElement, int); + vtkGetMacro(NumberOfVectorsPerElement, int); + vtkGetMacro(NumberOfTensorsSymmPerElement, int); + vtkGetMacro(NumberOfScalarsPerMeasuredNode, int); + vtkGetMacro(NumberOfVectorsPerMeasuredNode, int); + vtkGetMacro(NumberOfComplexScalarsPerNode, int); + vtkGetMacro(NumberOfComplexVectorsPerNode, int); + vtkGetMacro(NumberOfComplexScalarsPerElement, int); + vtkGetMacro(NumberOfComplexVectorsPerElement, int); + + // Description: + // Get the nth description for a non-complex variable. + const char* GetDescription(int n); + + // Description: + // Get the nth description for a complex variable. + const char* GetComplexDescription(int n); + + // Description: + // Get the nth description of a particular variable type. Returns NULL if no + // variable of this type exists in this data set. + // SCALAR_PER_NODE = 0; VECTOR_PER_NODE = 1; + // TENSOR_SYMM_PER_NODE = 2; SCALAR_PER_ELEMENT = 3; + // VECTOR_PER_ELEMENT = 4; TENSOR_SYMM_PER_ELEMENT = 5; + // SCALAR_PER_MEASURED_NODE = 6; VECTOR_PER_MEASURED_NODE = 7; + // COMPLEX_SCALAR_PER_NODE = 8; COMPLEX_VECTOR_PER_NODE 9; + // COMPLEX_SCALAR_PER_ELEMENT = 10; COMPLEX_VECTOR_PER_ELEMENT = 11 + const char* GetDescription(int n, int type); + + // Description: + // Get the variable type of variable n. + int GetVariableType(int n); + int GetComplexVariableType(int n); + + // Description: + // Set/Get the time value at which to get the value. + virtual void SetTimeValue(float value); + vtkGetMacro(TimeValue, float); + + // Description: + // Get the minimum or maximum time value for this data set. + vtkGetMacro(MinimumTimeValue, float); + vtkGetMacro(MaximumTimeValue, float); + + // Description: + // Get the time values per time set + vtkGetObjectMacro(TimeSets, vtkDataArrayCollection); + + // Description: + // Reads the FORMAT part of the case file to determine whether this is an + // EnSight6 or EnSightGold data set. Returns 0 if the format is EnSight6, + // 1 if it is EnSightGold, and -1 otherwise (meaning an error occurred). + int DetermineEnSightVersion(); + + // Description: + // Set/get the flag for whether to read all the variables + vtkBooleanMacro(ReadAllVariables, int); + vtkSetMacro(ReadAllVariables, int); + vtkGetMacro(ReadAllVariables, int); + + // Description: + // Get the data array selection tables used to configure which data + // arrays are loaded by the reader. + vtkGetObjectMacro(PointDataArraySelection, vtkDataArraySelection); + vtkGetObjectMacro(CellDataArraySelection, vtkDataArraySelection); + + // Description: + // Get the number of point or cell arrays available in the input. + int GetNumberOfPointArrays(); + int GetNumberOfCellArrays(); + + // Description: + // Get the name of the point or cell array with the given index in + // the input. + const char* GetPointArrayName(int index); + const char* GetCellArrayName(int index); + + // Description: + // Get/Set whether the point or cell array with the given name is to + // be read. + int GetPointArrayStatus(const char* name); + int GetCellArrayStatus(const char* name); + void SetPointArrayStatus(const char* name, int status); + void SetCellArrayStatus(const char* name, int status); + + //BTX + enum FileTypes + { + ENSIGHT_6 = 0, + ENSIGHT_6_BINARY = 1, + ENSIGHT_GOLD = 2, + ENSIGHT_GOLD_BINARY = 3, + ENSIGHT_MASTER_SERVER = 4 + }; + //ETX + + // Description: + // Set the byte order of the file (remember, more Unix workstations + // write big endian whereas PCs write little endian). Default is + // big endian (since most older PLOT3D files were written by + // workstations). + void SetByteOrderToBigEndian(); + void SetByteOrderToLittleEndian(); + vtkSetMacro(ByteOrder, int); + vtkGetMacro(ByteOrder, int); + const char *GetByteOrderAsString(); + +//BTX + enum + { + FILE_BIG_ENDIAN=0, + FILE_LITTLE_ENDIAN=1, + FILE_UNKNOWN_ENDIAN=2 + }; +//ETX + +protected: + vtkGenericEnSightReader(); + ~vtkGenericEnSightReader(); + + void Execute(); + + // Description: + // Internal function to read in a line up to 256 characters. + // Returns zero if there was an error. + int ReadLine(char result[256]); + + // Description: + // Internal function to read up to 80 characters from a binary file. + // Returns zero if there was an error. + int ReadBinaryLine(char result[80]); + + // Internal function that skips blank lines and reads the 1st + // non-blank line it finds (up to 256 characters). + // Returns 0 is there was an error. + int ReadNextDataLine(char result[256]); + + // Description: + // Set/Get the geometry file name. + vtkSetStringMacro(GeometryFileName); + vtkGetStringMacro(GeometryFileName); + + // Description: + // Add a variable description to the appropriate array. + void AddVariableDescription(const char* description); + void AddComplexVariableDescription(const char* description); + + // Description: + // Add a variable type to the appropriate array. + void AddVariableType(int variableType); + void AddComplexVariableType(int variableType); + + // Description: + // Replace the wildcards in the geometry file name with appropriate filename + // numbers as specified in the time set or file set. + void ReplaceWildcards(char* fileName, int timeSet, int fileSet); + void ReplaceWildcardsHelper(char* fileName, int num); + + // Callback registered with the SelectionObserver. + static void SelectionModifiedCallback(vtkObject* caller, unsigned long eid, + void* clientdata, void* calldata); + void SelectionModified(); + + // Utility to create argument for vtkDataArraySelection::SetArrays. + char** CreateStringArray(int numStrings); + void DestroyStringArray(int numStrings, char** strings); + + // Fill the vtkDataArraySelection objects with the current set of + // EnSight variables. + void SetDataArraySelectionSetsFromVariables(); + + // Fill the vtkDataArraySelection objects with the current set of + // arrays in the internal EnSight reader. + void SetDataArraySelectionSetsFromReader(); + + // Fill the internal EnSight reader's vtkDataArraySelection objects + // from those in this object. + void SetReaderDataArraySelectionSetsFromSelf(); + + istream* IS; + FILE *IFile; + vtkGenericEnSightReader *Reader; + + char* CaseFileName; + char* GeometryFileName; + char* FilePath; + + // array of types (one entry per instance of variable type in case file) + int* VariableTypes; + int* ComplexVariableTypes; + + // pointers to lists of descriptions + char** VariableDescriptions; + char** ComplexVariableDescriptions; + + int NumberOfVariables; + int NumberOfComplexVariables; + + // number of file names / descriptions per type + int NumberOfScalarsPerNode; + int NumberOfVectorsPerNode; + int NumberOfTensorsSymmPerNode; + int NumberOfScalarsPerElement; + int NumberOfVectorsPerElement; + int NumberOfTensorsSymmPerElement; + int NumberOfScalarsPerMeasuredNode; + int NumberOfVectorsPerMeasuredNode; + int NumberOfComplexScalarsPerNode; + int NumberOfComplexVectorsPerNode; + int NumberOfComplexScalarsPerElement; + int NumberOfComplexVectorsPerElement; + + float TimeValue; + float MinimumTimeValue; + float MaximumTimeValue; + + // Flag for whether TimeValue has been set. + int TimeValueInitialized; + + vtkDataArrayCollection *TimeSets; + virtual void SetTimeSets(vtkDataArrayCollection*); + + int ReadAllVariables; + + int ByteOrder; + + // The EnSight file version being read. Valid after + // UpdateInformation. Value is -1 for unknown version. + int EnSightVersion; + + // The array selections. These map over the variables and complex + // variables to hide the details of EnSight behind VTK terminology. + vtkDataArraySelection* PointDataArraySelection; + vtkDataArraySelection* CellDataArraySelection; + + // The observer to modify this object when the array selections are + // modified. + vtkCallbackCommand* SelectionObserver; + + // Whether the SelectionModified callback should invoke Modified. + // This is used when we are copying to/from the internal reader. + int SelectionModifiedDoNotCallModified; + + // Insert a partId and return the 'realId' that should be used. + int InsertNewPartId(int partId); + +//BTX + // Wrapper around an stl map + TranslationTableType *TranslationTable; +//ETX + +private: + vtkGenericEnSightReader(const vtkGenericEnSightReader&); // Not implemented. + void operator=(const vtkGenericEnSightReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkGenericMovieWriter.cxx b/IO/vtkGenericMovieWriter.cxx new file mode 100644 index 0000000..9819f2d --- /dev/null +++ b/IO/vtkGenericMovieWriter.cxx @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericMovieWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericMovieWriter.h" + +#include "vtkImageData.h" + +vtkCxxRevisionMacro(vtkGenericMovieWriter, "$Revision: 1.2 $"); + +//--------------------------------------------------------------------------- +vtkGenericMovieWriter::vtkGenericMovieWriter() +{ + this->FileName = NULL; + this->Error = 0; +} + +//--------------------------------------------------------------------------- +vtkGenericMovieWriter::~vtkGenericMovieWriter() +{ + this->SetFileName(0); +} + +//---------------------------------------------------------------------------- +void vtkGenericMovieWriter::SetInput(vtkImageData *input) +{ + this->vtkProcessObject::SetNthInput(0, input); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkGenericMovieWriter::GetInput() +{ + if (this->NumberOfInputs < 1) + { + return NULL; + } + + return (vtkImageData *)(this->Inputs[0]); +} + +//---------------------------------------------------------------------------- +void vtkGenericMovieWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "FileName: " + << (this->FileName ? this->FileName : "(none)") << endl; + os << indent << "Error: " << this->Error << endl; +} diff --git a/IO/vtkGenericMovieWriter.h b/IO/vtkGenericMovieWriter.h new file mode 100644 index 0000000..ea9bf77 --- /dev/null +++ b/IO/vtkGenericMovieWriter.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericMovieWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericMovieWriter - an abstract movie writer class. +// .SECTION Description +// vtkGenericMovieWriter is the abstract base class for several movie +// writers. The input type is a vtkImageData. The Start() method will +// open and create the file, the Write() method will output a frame to +// the file (i.e. the contents of the vtkImageData), End() will finalize +// and close the file. +// .SECTION See Also +// vtkAVIWriter vtkMPEG2Writer + +#ifndef __vtkGenericMovieWriter_h +#define __vtkGenericMovieWriter_h + +#include "vtkProcessObject.h" + +class vtkImageData; + +class VTK_IO_EXPORT vtkGenericMovieWriter : public vtkProcessObject +{ +public: + vtkTypeRevisionMacro(vtkGenericMovieWriter,vtkProcessObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the input object from the image pipeline. + virtual void SetInput(vtkImageData *input); + virtual vtkImageData *GetInput(); + + // Description: + // Specify file name of avi file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // These methods start writing an Movie file, write a frame to the file + // and then end the writing process. + virtual void Start() =0; + virtual void Write() =0; + virtual void End() =0; + + // Description: + // Was there an error on the last read performed? + vtkGetMacro(Error,int); + +protected: + vtkGenericMovieWriter(); + ~vtkGenericMovieWriter(); + + char *FileName; + int Error; + +private: + vtkGenericMovieWriter(const vtkGenericMovieWriter&); // Not implemented + void operator=(const vtkGenericMovieWriter&); // Not implemented +}; + +#endif + + + diff --git a/IO/vtkIVWriter.cxx b/IO/vtkIVWriter.cxx new file mode 100644 index 0000000..8258f9a --- /dev/null +++ b/IO/vtkIVWriter.cxx @@ -0,0 +1,229 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIVWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIVWriter.h" + +#include "vtkAbstractMapper.h" +#include "vtkCellArray.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkIVWriter, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkIVWriter); + +void vtkIVWriter::WriteData() +{ + FILE *fp; + + // make sure the user specified a FileName + if ( this->FileName == NULL) + { + vtkErrorMacro(<< "Please specify FileName to use"); + return; + } + + // try opening the files + fp = fopen(this->FileName,"w"); + if (!fp) + { + vtkErrorMacro(<< "unable to open OpenInventor file: " << this->FileName); + return; + } + + // + // Write header + // + vtkDebugMacro("Writing OpenInventor file"); + fprintf(fp,"#Inventor V2.0 ascii\n"); + fprintf(fp,"# OpenInventor file written by the visualization toolkit\n\n"); + this->WritePolyData(this->GetInput(), fp); + if (fclose(fp)) + { + vtkErrorMacro(<< this->FileName + << " did not close successfully. Check disk space."); + } +} + +void vtkIVWriter::WritePolyData(vtkPolyData *pd, FILE *fp) +{ + vtkPoints *points; + vtkIdType i; + vtkCellArray *cells; + vtkIdType npts = 0; + vtkIdType *indx = 0; + vtkUnsignedCharArray *colors=NULL; + int offset=0; + + points = pd->GetPoints(); + + // create colors for vertices + vtkDataArray *scalars = vtkAbstractMapper:: + GetScalars(pd, VTK_SCALAR_MODE_USE_POINT_DATA, 0, 0, NULL, offset); + + if ( scalars ) + { + vtkLookupTable *lut; + if ( (lut=scalars->GetLookupTable()) == NULL ) + { + lut = vtkLookupTable::New(); + lut->Build(); + } + colors = lut->MapScalars(scalars,VTK_COLOR_MODE_DEFAULT,0); + if ( ! scalars->GetLookupTable() ) + { + lut->Delete(); + } + } + + fprintf(fp,"Separator {\n"); + + // Point data (coordinates) + fprintf(fp,"\tCoordinate3 {\n"); + fprintf(fp,"\t\tpoint [\n"); + fprintf(fp,"\t\t\t"); + for (i=0; iGetNumberOfPoints(); i++) + { + double xyz[3]; + points->GetPoint(i, xyz); + fprintf(fp, "%g %g %g, ", xyz[0], xyz[1], xyz[2]); + if (!((i+1)%2)) + { + fprintf(fp, "\n\t\t\t"); + } + } + fprintf(fp, "\n\t\t]"); + fprintf(fp, "\t}\n"); + + // Per vertex coloring + fprintf(fp,"\tMaterialBinding {\n"); + fprintf(fp,"\t\tvalue PER_VERTEX_INDEXED\n"); + fprintf(fp,"\t}\n"); + + // Colors, if any + if (colors) + { + fprintf(fp,"\tMaterial {\n"); + fprintf(fp,"\t\tdiffuseColor [\n"); + fprintf(fp, "\t\t\t"); + for (i=0; iGetNumberOfTuples(); i++) + { + unsigned char *rgba; + rgba = colors->GetPointer(4*i); + fprintf(fp, "%g %g %g, ", rgba[0]/255.0f, + rgba[1]/255.0f, rgba[2]/255.0f); + if (!((i+1)%2)) + { + fprintf(fp, "\n\t\t\t"); + } + } + fprintf(fp, "\n\t\t]\n"); + fprintf(fp,"\t}\n"); + colors->Delete(); + } + + + // write out polys if any + if (pd->GetNumberOfPolys() > 0) + { + fprintf(fp,"\tIndexedFaceSet {\n"); + fprintf(fp,"\t\tcoordIndex [\n"); + cells = pd->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp, "\t\t\t"); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + } + fprintf(fp,"-1,\n"); + } + fprintf(fp,"\t\t]\n"); + fprintf(fp,"\t}\n"); + } + + // write out lines if any + if (pd->GetNumberOfLines() > 0) + { + fprintf(fp,"\tIndexedLineSet {\n"); + fprintf(fp,"\t\tcoordIndex [\n"); + + cells = pd->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp,"\t\t\t"); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + } + fprintf(fp,"-1,\n"); + } + fprintf(fp,"\t\t]\n"); + fprintf(fp,"\t}\n"); + } + + // write out verts if any + if (pd->GetNumberOfVerts() > 0) + { + fprintf(fp,"\tIndexdedPointSet {\n"); + fprintf(fp,"\t\tcoordIndex ["); + cells = pd->GetVerts(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp,"\t\t\t"); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + } + fprintf(fp,"-1,\n"); + } + fprintf(fp,"\t\t]\n"); + fprintf(fp,"\t}\n"); + } + + + // write out tstrips if any + if (pd->GetNumberOfStrips() > 0) + { + + fprintf(fp,"\tIndexedTriangleStripSet {\n"); + fprintf(fp,"\t\tcoordIndex [\n"); + cells = pd->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp,"\t\t\t"); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + } + fprintf(fp,"-1,\n"); + } + fprintf(fp,"\t\t]\n"); + fprintf(fp,"\t}\n"); + } + + fprintf(fp,"}\n"); // close the Shape + +} + + +//---------------------------------------------------------------------------- +void vtkIVWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkIVWriter.h b/IO/vtkIVWriter.h new file mode 100644 index 0000000..02d9c10 --- /dev/null +++ b/IO/vtkIVWriter.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIVWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIVWriter - export polydata into OpenInventor 2.0 format. +// .SECTION Description +// vtkIVWriter is a concrete subclass of vtkWriter that writes OpenInventor 2.0 +// files. +// +// .SECTION See Also +// vtkPolyDataWriter + + +#ifndef __vtkIVWriter_h +#define __vtkIVWriter_h + +#include "vtkPolyDataWriter.h" + +class VTK_IO_EXPORT vtkIVWriter : public vtkPolyDataWriter +{ +public: + static vtkIVWriter *New(); + vtkTypeRevisionMacro(vtkIVWriter,vtkPolyDataWriter); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkIVWriter() {}; + ~vtkIVWriter() {}; + + void WriteData(); + void WritePolyData(vtkPolyData *polyData, FILE *fp); +private: + vtkIVWriter(const vtkIVWriter&); // Not implemented. + void operator=(const vtkIVWriter&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkImageReader.cxx b/IO/vtkImageReader.cxx new file mode 100644 index 0000000..eda46fe --- /dev/null +++ b/IO/vtkImageReader.cxx @@ -0,0 +1,733 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageReader.h" + +#include "vtkByteSwap.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkImageReader, "$Revision: 1.121 $"); +vtkStandardNewMacro(vtkImageReader); + +vtkCxxSetObjectMacro(vtkImageReader,Transform,vtkTransform); + +#ifdef read +#undef read +#endif + +#ifdef close +#undef close +#endif + +//---------------------------------------------------------------------------- +vtkImageReader::vtkImageReader() +{ + int idx; + + for (idx = 0; idx < 3; ++idx) + { + this->DataVOI[idx*2] = this->DataVOI[idx*2 + 1] = 0; + } + + // Left over from short reader + this->DataMask = 0xffff; + this->Transform = NULL; + + this->ScalarArrayName = NULL; + this->SetScalarArrayName("ImageFile"); +} + +//---------------------------------------------------------------------------- +vtkImageReader::~vtkImageReader() +{ + this->SetTransform(NULL); + this->SetScalarArrayName(NULL); +} + + + + + +//---------------------------------------------------------------------------- +void vtkImageReader::PrintSelf(ostream& os, vtkIndent indent) +{ + int idx; + + this->Superclass::PrintSelf(os,indent); + + os << indent << "Data Mask: " << this->DataMask << "\n"; + os << indent << "DataVOI: (" << this->DataVOI[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << this->DataVOI[idx]; + } + os << ")\n"; + if ( this->Transform ) + { + os << indent << "Transform: " << this->Transform << "\n"; + } + else + { + os << indent << "Transform: (none)\n"; + } + + os << indent << "ScalarArrayName: " + << (this->ScalarArrayName ? this->ScalarArrayName : "(none)") << endl; +} + + +// This method returns the largest data that can be generated. +int vtkImageReader::RequestInformation ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector * outputVector) +{ + // call the old method to help with backwards compatiblity + this->ExecuteInformation(); + + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + double spacing[3]; + int extent[6]; + double origin[3]; + + // set the extent, if the VOI has not been set then default to + // the DataExtent + if (this->DataVOI[0] || this->DataVOI[1] || + this->DataVOI[2] || this->DataVOI[3] || + this->DataVOI[4] || this->DataVOI[5]) + { + this->ComputeTransformedExtent(this->DataVOI,extent); + } + else + { + this->ComputeTransformedExtent(this->DataExtent,extent); + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent, 6); + + // set the spacing + this->ComputeTransformedSpacing(spacing); + outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3); + + // set the origin. + this->ComputeTransformedOrigin(origin); + outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, + this->NumberOfScalarComponents); + return 1; +} + +int vtkImageReader::OpenAndSeekFile(int dataExtent[6], int idx) +{ + unsigned long streamStart; + + if (!this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Either a FileName or FilePattern must be specified."); + return 0; + } + this->ComputeInternalFileName(idx); + this->OpenFile(); + if ( !this->File ) + { + return 0; + } + // convert data extent into constants that can be used to seek. + streamStart = + (dataExtent[0] - this->DataExtent[0]) * this->DataIncrements[0]; + + if (this->FileLowerLeft) + { + streamStart = streamStart + + (dataExtent[2] - this->DataExtent[2]) * this->DataIncrements[1]; + } + else + { + streamStart = streamStart + + (this->DataExtent[3] - this->DataExtent[2] - dataExtent[2]) * + this->DataIncrements[1]; + } + + // handle three and four dimensional files + if (this->GetFileDimensionality() >= 3) + { + streamStart = streamStart + + (dataExtent[4] - this->DataExtent[4]) * this->DataIncrements[2]; + } + + streamStart += this->GetHeaderSize(idx); + + // error checking + this->File->seekg(static_cast(streamStart), ios::beg); + if (this->File->fail()) + { + vtkErrorMacro(<< "File operation failed: " << streamStart << ", ext: " + << dataExtent[0] << ", " << dataExtent[1] << ", " + << dataExtent[2] << ", " << dataExtent[3] << ", " + << dataExtent[4] << ", " << dataExtent[5]); + vtkErrorMacro(<< "Header size: " << this->GetHeaderSize(idx) << ", file ext: " + << this->DataExtent[0] << ", " << this->DataExtent[1] << ", " + << this->DataExtent[2] << ", " << this->DataExtent[3] << ", " + << this->DataExtent[4] << ", " << this->DataExtent[5]); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +// This function reads in one data of data. +// templated to handle different data types. +template +void vtkImageReaderUpdate2(vtkImageReader *self, vtkImageData *data, + IT *inPtr, OT *outPtr) +{ + vtkIdType inIncr[3], outIncr[3]; + OT *outPtr0, *outPtr1, *outPtr2; + long streamSkip0, streamSkip1; + unsigned long streamRead; + int idx0, idx1, idx2, pixelRead; + unsigned char *buf; + int inExtent[6]; + int dataExtent[6]; + int comp, pixelSkip; + long filePos, correction = 0; + unsigned long count = 0; + unsigned short DataMask; + unsigned long target; + + // Get the requested extents. + data->GetExtent(inExtent); + // Convert them into to the extent needed from the file. + self->ComputeInverseTransformedExtent(inExtent,dataExtent); + + // get and transform the increments + data->GetIncrements(inIncr); + self->ComputeInverseTransformedIncrements(inIncr,outIncr); + + DataMask = self->GetDataMask(); + + // compute outPtr2 + outPtr2 = outPtr; + if (outIncr[0] < 0) + { + outPtr2 = outPtr2 - outIncr[0]*(dataExtent[1] - dataExtent[0]); + } + if (outIncr[1] < 0) + { + outPtr2 = outPtr2 - outIncr[1]*(dataExtent[3] - dataExtent[2]); + } + if (outIncr[2] < 0) + { + outPtr2 = outPtr2 - outIncr[2]*(dataExtent[5] - dataExtent[4]); + } + + // length of a row, num pixels read at a time + pixelRead = dataExtent[1] - dataExtent[0] + 1; + streamRead = static_cast(pixelRead * + self->GetDataIncrements()[0]); + streamSkip0 = (long)(self->GetDataIncrements()[1] - streamRead); + streamSkip1 = (long)(self->GetDataIncrements()[2] - + (dataExtent[3] - dataExtent[2] + 1)* self->GetDataIncrements()[1]); + pixelSkip = data->GetNumberOfScalarComponents(); + + // read from the bottom up + if (!self->GetFileLowerLeft()) + { + streamSkip0 = (long)(-static_cast(streamRead) + - self->GetDataIncrements()[1]); + streamSkip1 = (long)(self->GetDataIncrements()[2] + + (dataExtent[3] - dataExtent[2] + 1)* self->GetDataIncrements()[1]); + } + + + // create a buffer to hold a row of the data + buf = new unsigned char[streamRead]; + + target = (unsigned long)((dataExtent[5]-dataExtent[4]+1)* + (dataExtent[3]-dataExtent[2]+1)/50.0); + target++; + + // read the data row by row + if (self->GetFileDimensionality() == 3) + { + if ( !self->OpenAndSeekFile(dataExtent,0) ) + { + delete [] buf; + return; + } + } + for (idx2 = dataExtent[4]; idx2 <= dataExtent[5]; ++idx2) + { + if (self->GetFileDimensionality() == 2) + { + if ( !self->OpenAndSeekFile(dataExtent,idx2) ) + { + delete [] buf; + return; + } + } + outPtr1 = outPtr2; + for (idx1 = dataExtent[2]; + !self->AbortExecute && idx1 <= dataExtent[3]; ++idx1) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + outPtr0 = outPtr1; + + // read the row. + self->GetFile()->read((char *)buf, streamRead); +#ifdef __APPLE_CC__ + if (static_cast(self->GetFile()->gcount()) != streamRead) + // Apple's gcc3 returns fail when reading _to_ eof +#else + if ( static_cast(self->GetFile()->gcount()) != + streamRead || self->GetFile()->fail()) +#endif + { + vtkGenericWarningMacro("File operation failed. row = " << idx1 + << ", Tried to Read = " << streamRead + << ", Read = " << self->GetFile()->gcount() + << ", Skip0 = " << streamSkip0 + << ", Skip1 = " << streamSkip1 + << ", FilePos = " << static_cast(self->GetFile()->tellg())); + delete [] buf; + return; + } + // handle swapping + if (self->GetSwapBytes()) + { + // pixelSkip is the number of components in data + vtkByteSwap::SwapVoidRange(buf, pixelRead*pixelSkip, sizeof(IT)); + } + + // copy the bytes into the typed data + inPtr = (IT *)(buf); + for (idx0 = dataExtent[0]; idx0 <= dataExtent[1]; ++idx0) + { + // Copy pixel into the output. + if (DataMask == 0xffff) + { + for (comp = 0; comp < pixelSkip; comp++) + { + outPtr0[comp] = (OT)(inPtr[comp]); + } + } + else + { + // left over from short reader (what about other types. + for (comp = 0; comp < pixelSkip; comp++) + { + outPtr0[comp] = (OT)((short)(inPtr[comp]) & DataMask); + } + } + // move to next pixel + inPtr += pixelSkip; + outPtr0 += outIncr[0]; + } + + // move to the next row in the file and data + filePos = self->GetFile()->tellg(); + +/* Unfortunately this doesn't work as a fix, but I'll leave it here for a bit + to provoke ideas. + if (filePos == -1) + { + self->GetFile()->clear(self->GetFile()->rdstate() & ~ios::eofbit); + self->GetFile()->clear(self->GetFile()->rdstate() & ~ios::failbit); + filePos = self->GetFile()->tellg(); + } +*/ +#if defined(VTK_USE_ANSI_STDLIB ) && ((defined(__sgi) && !defined(__GNUC__)) \ + || (__BORLANDC__>=0x0560) || defined (__APPLE_CC__)) + // this check is required for SGI's when vtk is build with VTK_USE_ANSI_STDLIB + // seems that after a read that just reaches EOF, tellg reports a -1. + // clear() does not work, so we have to reopen the file. + // NB: Also Borland CBuilder 6 suffers from same trouble + // As does Apple's gcc3 + if (filePos == -1) + { + self->OpenFile(); + self->GetFile()->seekg(0,ios::end); + filePos = self->GetFile()->tellg(); + } +#endif + // watch for case where we might rewind too much + // if that happens, store the value in correction and apply later + if (filePos + streamSkip0 >= 0) + { + self->GetFile()->seekg(static_cast(self->GetFile()->tellg()) + streamSkip0, ios::beg); + correction = 0; + } + else + { + correction = streamSkip0; + } + outPtr1 += outIncr[1]; + } + // move to the next image in the file and data + self->GetFile()->seekg(static_cast(self->GetFile()->tellg()) + streamSkip1 + correction, + ios::beg); + outPtr2 += outIncr[2]; + } + + // delete the temporary buffer + delete [] buf; +} + + +//---------------------------------------------------------------------------- +// This function reads in one data of one slice. +// templated to handle different data types. +template +void vtkImageReaderUpdate1(vtkImageReader *self, vtkImageData *data, T *inPtr) +{ + void *outPtr; + + // Call the correct templated function for the input + outPtr = data->GetScalarPointer(); + switch (data->GetScalarType()) + { + vtkTemplateMacro(vtkImageReaderUpdate2(self, data, inPtr, + (VTK_TT *)(outPtr))); + default: + vtkGenericWarningMacro("Update1: Unknown data type\n"); + } +} +//---------------------------------------------------------------------------- +// This function reads a data from a file. The datas extent/axes +// are assumed to be the same as the file extent/order. +void vtkImageReader::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + void *ptr = NULL; + int *ext; + + if (!this->FileName && !this->FilePattern) + { + vtkErrorMacro("Either a valid FileName or FilePattern must be specified."); + return; + } + + ext = data->GetExtent(); + if (!data->GetPointData()->GetScalars()) + { + return; + } + data->GetPointData()->GetScalars()->SetName(this->ScalarArrayName); + + vtkDebugMacro("Reading extent: " << ext[0] << ", " << ext[1] << ", " + << ext[2] << ", " << ext[3] << ", " << ext[4] << ", " << ext[5]); + + this->ComputeDataIncrements(); + + // Call the correct templated function for the output + switch (this->GetDataScalarType()) + { + vtkTemplateMacro(vtkImageReaderUpdate1(this, data, (VTK_TT *)(ptr))); + default: + vtkErrorMacro(<< "UpdateFromFile: Unknown data type"); + } +} + + + + + +void vtkImageReader::ComputeTransformedSpacing (double Spacing[3]) +{ + if (!this->Transform) + { + memcpy (Spacing, this->DataSpacing, 3 * sizeof (double)); + } + else + { + double transformedSpacing[3]; + memcpy (transformedSpacing, this->DataSpacing, 3 * sizeof (double)); + this->Transform->TransformVector(transformedSpacing, transformedSpacing); + + for (int i = 0; i < 3; i++) + { + Spacing[i] = fabs(transformedSpacing[i]); + } + vtkDebugMacro("Transformed Spacing " << Spacing[0] << ", " << Spacing[1] << ", " << Spacing[2]); + } +} + +// if the spacing is negative we need to tranlate the origin +// basically O' = O + spacing*(dim-1) for any axis that would +// have a negative spaing +void vtkImageReader::ComputeTransformedOrigin (double origin[3]) +{ + if (!this->Transform) + { + memcpy (origin, this->DataOrigin, 3 * sizeof (double)); + } + else + { + double transformedOrigin[3]; + double transformedSpacing[3]; + int transformedExtent[6]; + + memcpy (transformedSpacing, this->DataSpacing, 3 * sizeof (double)); + this->Transform->TransformVector(transformedSpacing, transformedSpacing); + + memcpy (transformedOrigin, this->DataOrigin, 3 * sizeof (double)); + this->Transform->TransformPoint(transformedOrigin, transformedOrigin); + + this->ComputeTransformedExtent(this->DataExtent,transformedExtent); + + for (int i = 0; i < 3; i++) + { + if (transformedSpacing[i] < 0) + { + origin[i] = transformedOrigin[i] + transformedSpacing[i]* + (transformedExtent[i*2+1] - transformedExtent[i*2] + 1); + } + else + { + origin[i] = transformedOrigin[i]; + } + } + vtkDebugMacro("Transformed Origin " << origin[0] << ", " << origin[1] << ", " << origin[2]); + } +} + +void vtkImageReader::ComputeTransformedExtent(int inExtent[6], + int outExtent[6]) +{ + double transformedExtent[3]; + int temp; + int idx; + int dataExtent[6]; + + if (!this->Transform) + { + memcpy (outExtent, inExtent, 6 * sizeof (int)); + memcpy (dataExtent, this->DataExtent, 6 * sizeof(int)); + } + else + { + // need to know how far to translate to start at 000 + // first transform the data extent + transformedExtent[0] = this->DataExtent[0]; + transformedExtent[1] = this->DataExtent[2]; + transformedExtent[2] = this->DataExtent[4]; + this->Transform->TransformPoint(transformedExtent, transformedExtent); + dataExtent[0] = (int) transformedExtent[0]; + dataExtent[2] = (int) transformedExtent[1]; + dataExtent[4] = (int) transformedExtent[2]; + + transformedExtent[0] = this->DataExtent[1]; + transformedExtent[1] = this->DataExtent[3]; + transformedExtent[2] = this->DataExtent[5]; + this->Transform->TransformPoint(transformedExtent, transformedExtent); + dataExtent[1] = (int) transformedExtent[0]; + dataExtent[3] = (int) transformedExtent[1]; + dataExtent[5] = (int) transformedExtent[2]; + + for (idx = 0; idx < 6; idx += 2) + { + if (dataExtent[idx] > dataExtent[idx+1]) + { + temp = dataExtent[idx]; + dataExtent[idx] = dataExtent[idx+1]; + dataExtent[idx+1] = temp; + } + } + + // now transform the inExtent + transformedExtent[0] = inExtent[0]; + transformedExtent[1] = inExtent[2]; + transformedExtent[2] = inExtent[4]; + this->Transform->TransformPoint(transformedExtent, transformedExtent); + outExtent[0] = (int) transformedExtent[0]; + outExtent[2] = (int) transformedExtent[1]; + outExtent[4] = (int) transformedExtent[2]; + + transformedExtent[0] = inExtent[1]; + transformedExtent[1] = inExtent[3]; + transformedExtent[2] = inExtent[5]; + this->Transform->TransformPoint(transformedExtent, transformedExtent); + outExtent[1] = (int) transformedExtent[0]; + outExtent[3] = (int) transformedExtent[1]; + outExtent[5] = (int) transformedExtent[2]; + } + + for (idx = 0; idx < 6; idx += 2) + { + if (outExtent[idx] > outExtent[idx+1]) + { + temp = outExtent[idx]; + outExtent[idx] = outExtent[idx+1]; + outExtent[idx+1] = temp; + } + // do the slide to 000 origin by subtracting the minimum extent + outExtent[idx] -= dataExtent[idx]; + outExtent[idx+1] -= dataExtent[idx]; + } + + vtkDebugMacro(<< "Transformed extent are:" + << outExtent[0] << ", " << outExtent[1] << ", " + << outExtent[2] << ", " << outExtent[3] << ", " + << outExtent[4] << ", " << outExtent[5]); +} + +void vtkImageReader::ComputeInverseTransformedExtent(int inExtent[6], + int outExtent[6]) +{ + double transformedExtent[3]; + int temp; + int idx; + + if (!this->Transform) + { + memcpy (outExtent, inExtent, 6 * sizeof (int)); + for (idx = 0; idx < 6; idx += 2) + { + // do the slide to 000 origin by subtracting the minimum extent + outExtent[idx] += this->DataExtent[idx]; + outExtent[idx+1] += this->DataExtent[idx]; + } + } + else + { + // need to know how far to translate to start at 000 + int dataExtent[6]; + // first transform the data extent + transformedExtent[0] = this->DataExtent[0]; + transformedExtent[1] = this->DataExtent[2]; + transformedExtent[2] = this->DataExtent[4]; + this->Transform->TransformPoint(transformedExtent, transformedExtent); + dataExtent[0] = (int) transformedExtent[0]; + dataExtent[2] = (int) transformedExtent[1]; + dataExtent[4] = (int) transformedExtent[2]; + + transformedExtent[0] = this->DataExtent[1]; + transformedExtent[1] = this->DataExtent[3]; + transformedExtent[2] = this->DataExtent[5]; + this->Transform->TransformPoint(transformedExtent, transformedExtent); + dataExtent[1] = (int) transformedExtent[0]; + dataExtent[3] = (int) transformedExtent[1]; + dataExtent[5] = (int) transformedExtent[2]; + + for (idx = 0; idx < 6; idx += 2) + { + if (dataExtent[idx] > dataExtent[idx+1]) + { + temp = dataExtent[idx]; + dataExtent[idx] = dataExtent[idx+1]; + dataExtent[idx+1] = temp; + } + } + + for (idx = 0; idx < 6; idx += 2) + { + // do the slide to 000 origin by subtracting the minimum extent + inExtent[idx] += dataExtent[idx]; + inExtent[idx+1] += dataExtent[idx]; + } + + transformedExtent[0] = inExtent[0]; + transformedExtent[1] = inExtent[2]; + transformedExtent[2] = inExtent[4]; + this->Transform->GetLinearInverse()->TransformPoint(transformedExtent, + transformedExtent); + outExtent[0] = (int) transformedExtent[0]; + outExtent[2] = (int) transformedExtent[1]; + outExtent[4] = (int) transformedExtent[2]; + + transformedExtent[0] = inExtent[1]; + transformedExtent[1] = inExtent[3]; + transformedExtent[2] = inExtent[5]; + this->Transform->GetLinearInverse()->TransformPoint(transformedExtent, + transformedExtent); + outExtent[1] = (int) transformedExtent[0]; + outExtent[3] = (int) transformedExtent[1]; + outExtent[5] = (int) transformedExtent[2]; + + for (idx = 0; idx < 6; idx += 2) + { + if (outExtent[idx] > outExtent[idx+1]) + { + temp = outExtent[idx]; + outExtent[idx] = outExtent[idx+1]; + outExtent[idx+1] = temp; + } + } + } + + vtkDebugMacro(<< "Inverse Transformed extent are:" + << outExtent[0] << ", " << outExtent[1] << ", " + << outExtent[2] << ", " << outExtent[3] << ", " + << outExtent[4] << ", " << outExtent[5]); +} + +void vtkImageReader::ComputeTransformedIncrements(vtkIdType inIncr[3], + vtkIdType outIncr[3]) +{ + double transformedIncr[3]; + + if (!this->Transform) + { + memcpy (outIncr, inIncr, 3 * sizeof (vtkIdType)); + } + else + { + transformedIncr[0] = inIncr[0]; + transformedIncr[1] = inIncr[1]; + transformedIncr[2] = inIncr[2]; + this->Transform->TransformVector(transformedIncr, transformedIncr); + outIncr[0] = (vtkIdType) transformedIncr[0]; + outIncr[1] = (vtkIdType) transformedIncr[1]; + outIncr[2] = (vtkIdType) transformedIncr[2]; + vtkDebugMacro(<< "Transformed Incr are:" + << outIncr[0] << ", " << outIncr[1] << ", " << outIncr[2]); + } +} + + +void vtkImageReader::ComputeInverseTransformedIncrements(vtkIdType inIncr[3], + vtkIdType outIncr[3]) +{ + double transformedIncr[3]; + + if (!this->Transform) + { + memcpy (outIncr, inIncr, 3 * sizeof (vtkIdType)); + } + else + { + transformedIncr[0] = inIncr[0]; + transformedIncr[1] = inIncr[1]; + transformedIncr[2] = inIncr[2]; + this->Transform->GetLinearInverse()->TransformVector(transformedIncr, + transformedIncr); + outIncr[0] = (vtkIdType) transformedIncr[0]; + outIncr[1] = (vtkIdType) transformedIncr[1]; + outIncr[2] = (vtkIdType) transformedIncr[2]; + vtkDebugMacro(<< "Inverse Transformed Incr are:" + << outIncr[0] << ", " << outIncr[1] << ", " << outIncr[2]); + } +} diff --git a/IO/vtkImageReader.h b/IO/vtkImageReader.h new file mode 100644 index 0000000..a58dec6 --- /dev/null +++ b/IO/vtkImageReader.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageReader - Superclass of transformable binary file readers. +// .SECTION Description +// vtkImageReader provides methods needed to read a region from a file. +// It supports both transforms and masks on the input data, but as a result +// is more complicated and slower than its parent class vtkImageReader2. + +// .SECTION See Also +// vtkBMPReader vtkPNMReader vtkTIFFReader + +#ifndef __vtkImageReader_h +#define __vtkImageReader_h + +#include "vtkImageReader2.h" + +class vtkTransform; + +#define VTK_FILE_BYTE_ORDER_BIG_ENDIAN 0 +#define VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN 1 + +class VTK_IO_EXPORT vtkImageReader : public vtkImageReader2 +{ +public: + static vtkImageReader *New(); + vtkTypeRevisionMacro(vtkImageReader,vtkImageReader2); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/get the data VOI. You can limit the reader to only + // read a subset of the data. + vtkSetVector6Macro(DataVOI,int); + vtkGetVector6Macro(DataVOI,int); + + // Description: + // Set/Get the Data mask. + vtkGetMacro(DataMask,unsigned short); + void SetDataMask(int val) + {if (val == this->DataMask) { return; } + this->DataMask = ((unsigned short)(val)); this->Modified();} + + // Description: + // Set/Get transformation matrix to transform the data from slice space + // into world space. This matrix must be a permutation matrix. To qualify, + // the sums of the rows must be + or - 1. + virtual void SetTransform(vtkTransform*); + vtkGetObjectMacro(Transform,vtkTransform); + + // Warning !!! + // following should only be used by methods or template helpers, not users + void ComputeInverseTransformedExtent(int inExtent[6], + int outExtent[6]); + void ComputeInverseTransformedIncrements(vtkIdType inIncr[3], + vtkIdType outIncr[3]); + + int OpenAndSeekFile(int extent[6], int slice); + + // Description: + // Set/get the scalar array name for this data set. + vtkSetStringMacro(ScalarArrayName); + vtkGetStringMacro(ScalarArrayName); + +protected: + vtkImageReader(); + ~vtkImageReader(); + + unsigned short DataMask; // Mask each pixel with ... + + vtkTransform *Transform; + + void ComputeTransformedSpacing (double Spacing[3]); + void ComputeTransformedOrigin (double origin[3]); + void ComputeTransformedExtent(int inExtent[6], + int outExtent[6]); + void ComputeTransformedIncrements(vtkIdType inIncr[3], + vtkIdType outIncr[3]); + + int DataVOI[6]; + + char *ScalarArrayName; + + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + void ExecuteData(vtkDataObject *data); +private: + vtkImageReader(const vtkImageReader&); // Not implemented. + void operator=(const vtkImageReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkImageReader2.cxx b/IO/vtkImageReader2.cxx new file mode 100644 index 0000000..23c3543 --- /dev/null +++ b/IO/vtkImageReader2.cxx @@ -0,0 +1,740 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageReader2.h" + +#include "vtkByteSwap.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageReader2, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkImageReader2); + +#ifdef read +#undef read +#endif + +#ifdef close +#undef close +#endif + +//---------------------------------------------------------------------------- +vtkImageReader2::vtkImageReader2() +{ + this->FilePrefix = NULL; + this->FilePattern = new char[strlen("%s.%d") + 1]; + strcpy (this->FilePattern, "%s.%d"); + this->File = NULL; + + this->DataScalarType = VTK_SHORT; + this->NumberOfScalarComponents = 1; + + this->DataOrigin[0] = this->DataOrigin[1] = this->DataOrigin[2] = 0.0; + + this->DataSpacing[0] = this->DataSpacing[1] = this->DataSpacing[2] = 1.0; + + this->DataExtent[0] = this->DataExtent[2] = this->DataExtent[4] = 0; + this->DataExtent[1] = this->DataExtent[3] = this->DataExtent[5] = 0; + + this->DataIncrements[0] = this->DataIncrements[1] = + this->DataIncrements[2] = this->DataIncrements[3] = 1; + + this->FileName = NULL; + this->InternalFileName = NULL; + + this->HeaderSize = 0; + this->ManualHeaderSize = 0; + + this->FileNameSliceOffset = 0; + this->FileNameSliceSpacing = 1; + + // Left over from short reader + this->SwapBytes = 0; + this->FileLowerLeft = 0; + this->FileDimensionality = 2; + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkImageReader2::~vtkImageReader2() +{ + if (this->File) + { + this->File->close(); + delete this->File; + this->File = NULL; + } + + if (this->FileName) + { + delete [] this->FileName; + this->FileName = NULL; + } + if (this->FilePrefix) + { + delete [] this->FilePrefix; + this->FilePrefix = NULL; + } + if (this->FilePattern) + { + delete [] this->FilePattern; + this->FilePattern = NULL; + } + if (this->InternalFileName) + { + delete [] this->InternalFileName; + this->InternalFileName = NULL; + } +} + +//---------------------------------------------------------------------------- +// This function sets the name of the file. +void vtkImageReader2::ComputeInternalFileName(int slice) +{ + // delete any old filename + if (this->InternalFileName) + { + delete [] this->InternalFileName; + this->InternalFileName = NULL; + } + + if (!this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Either a FileName or FilePattern must be specified."); + return; + } + + // make sure we figure out a filename to open + if (this->FileName) + { + this->InternalFileName = new char [strlen(this->FileName) + 10]; + sprintf(this->InternalFileName,"%s",this->FileName); + } + else + { + int slicenum = + slice * this->FileNameSliceSpacing + + this->FileNameSliceOffset; + if (this->FilePrefix && this->FilePattern) + { + this->InternalFileName = new char [strlen(this->FilePrefix) + + strlen(this->FilePattern) + 10]; + sprintf (this->InternalFileName, this->FilePattern, + this->FilePrefix, slicenum); + } + else if (this->FilePattern) + { + this->InternalFileName = new char [strlen(this->FilePattern) + 10]; + int len = static_cast(strlen(this->FilePattern)); + int hasPercentS = 0; + for(int i =0; i < len-1; ++i) + { + if(this->FilePattern[i] == '%' && this->FilePattern[i+1] == 's') + { + hasPercentS = 1; + break; + } + } + if(hasPercentS) + { + sprintf (this->InternalFileName, this->FilePattern, "", slicenum); + } + else + { + sprintf (this->InternalFileName, this->FilePattern, slicenum); + } + } + else + { + delete [] this->InternalFileName; + this->InternalFileName = 0; + } + } +} + + +//---------------------------------------------------------------------------- +// This function sets the name of the file. +void vtkImageReader2::SetFileName(const char *name) +{ + if ( this->FileName && name && (!strcmp(this->FileName,name))) + { + return; + } + if (!name && !this->FileName) + { + return; + } + if (this->FileName) + { + delete [] this->FileName; + } + if (this->FilePrefix) + { + delete [] this->FilePrefix; + this->FilePrefix = NULL; + } + if (name) + { + this->FileName = new char[strlen(name) + 1]; + strcpy(this->FileName, name); + } + else + { + this->FileName = NULL; + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// This function sets the prefix of the file name. "image" would be the +// name of a series: image.1, image.2 ... +void vtkImageReader2::SetFilePrefix(const char *prefix) +{ + if ( this->FilePrefix && prefix && (!strcmp(this->FilePrefix,prefix))) + { + return; + } + if (!prefix && !this->FilePrefix) + { + return; + } + if (this->FilePrefix) + { + delete [] this->FilePrefix; + } + if (this->FileName) + { + delete [] this->FileName; + this->FileName = NULL; + } + this->FilePrefix = new char[strlen(prefix) + 1]; + strcpy(this->FilePrefix, prefix); + this->Modified(); +} + +//---------------------------------------------------------------------------- +// This function sets the pattern of the file name which turn a prefix +// into a file name. "%s.%3d" would be the +// pattern of a series: image.001, image.002 ... +void vtkImageReader2::SetFilePattern(const char *pattern) +{ + if ( this->FilePattern && pattern && + (!strcmp(this->FilePattern,pattern))) + { + return; + } + if (!pattern && !this->FilePattern) + { + return; + } + if (this->FilePattern) + { + delete [] this->FilePattern; + } + if (this->FileName) + { + delete [] this->FileName; + this->FileName = NULL; + } + this->FilePattern = new char[strlen(pattern) + 1]; + strcpy(this->FilePattern, pattern); + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageReader2::SetDataByteOrderToBigEndian() +{ +#ifndef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +//---------------------------------------------------------------------------- +void vtkImageReader2::SetDataByteOrderToLittleEndian() +{ +#ifdef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +//---------------------------------------------------------------------------- +void vtkImageReader2::SetDataByteOrder(int byteOrder) +{ + if ( byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN ) + { + this->SetDataByteOrderToBigEndian(); + } + else + { + this->SetDataByteOrderToLittleEndian(); + } +} + +//---------------------------------------------------------------------------- +int vtkImageReader2::GetDataByteOrder() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } +#else + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } +#endif +} + +//---------------------------------------------------------------------------- +const char *vtkImageReader2::GetDataByteOrderAsString() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +#else + if ( this->SwapBytes ) + { + return "BigEndian"; + } + else + { + return "LittleEndian"; + } +#endif +} + + +//---------------------------------------------------------------------------- +void vtkImageReader2::PrintSelf(ostream& os, vtkIndent indent) +{ + int idx; + + this->Superclass::PrintSelf(os,indent); + + // this->File, this->Colors need not be printed + os << indent << "FileName: " << + (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "FilePrefix: " << + (this->FilePrefix ? this->FilePrefix : "(none)") << "\n"; + os << indent << "FilePattern: " << + (this->FilePattern ? this->FilePattern : "(none)") << "\n"; + + os << indent << "FileNameSliceOffset: " + << this->FileNameSliceOffset << "\n"; + os << indent << "FileNameSliceSpacing: " + << this->FileNameSliceSpacing << "\n"; + + os << indent << "DataScalarType: " + << vtkImageScalarTypeNameMacro(this->DataScalarType) << "\n"; + os << indent << "NumberOfScalarComponents: " + << this->NumberOfScalarComponents << "\n"; + + os << indent << "File Dimensionality: " << this->FileDimensionality << "\n"; + + os << indent << "File Lower Left: " << + (this->FileLowerLeft ? "On\n" : "Off\n"); + + os << indent << "Swap Bytes: " << (this->SwapBytes ? "On\n" : "Off\n"); + + os << indent << "DataIncrements: (" << this->DataIncrements[0]; + for (idx = 1; idx < 2; ++idx) + { + os << ", " << this->DataIncrements[idx]; + } + os << ")\n"; + + os << indent << "DataExtent: (" << this->DataExtent[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << this->DataExtent[idx]; + } + os << ")\n"; + + os << indent << "DataSpacing: (" << this->DataSpacing[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->DataSpacing[idx]; + } + os << ")\n"; + + os << indent << "DataOrigin: (" << this->DataOrigin[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->DataOrigin[idx]; + } + os << ")\n"; + + os << indent << "HeaderSize: " << this->HeaderSize << "\n"; + + if ( this->InternalFileName ) + { + os << indent << "Internal File Name: " << this->InternalFileName << "\n"; + } + else + { + os << indent << "Internal File Name: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkImageReader2::ExecuteInformation() +{ + // this is empty, the idea is that converted filters should implement + // RequestInformation. But to help out old filters we will call + // ExecuteInformation and hope that the subclasses correctly set the ivars + // and not the output. +} + +//---------------------------------------------------------------------------- +// This method returns the largest data that can be generated. +int vtkImageReader2::RequestInformation ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector * outputVector) +{ + // call for backwards compatibility + this->ExecuteInformation(); + + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->DataExtent, 6); + outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3); + outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, + this->NumberOfScalarComponents); + return 1; +} + +//---------------------------------------------------------------------------- +// Manual initialization. +void vtkImageReader2::SetHeaderSize(unsigned long size) +{ + if (size != this->HeaderSize) + { + this->HeaderSize = size; + this->Modified(); + } + this->ManualHeaderSize = 1; +} + + +//---------------------------------------------------------------------------- +template +unsigned long vtkImageReader2GetSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +// This function opens a file to determine the file size, and to +// automatically determine the header size. +void vtkImageReader2::ComputeDataIncrements() +{ + int idx; + unsigned long fileDataLength; + + // Determine the expected length of the data ... + switch (this->DataScalarType) + { + vtkTemplateMacro( + fileDataLength = vtkImageReader2GetSize(static_cast(0)) + ); + default: + vtkErrorMacro(<< "Unknown DataScalarType"); + return; + } + + fileDataLength *= this->NumberOfScalarComponents; + + // compute the fileDataLength (in units of bytes) + for (idx = 0; idx < 3; ++idx) + { + this->DataIncrements[idx] = fileDataLength; + fileDataLength = fileDataLength * + (this->DataExtent[idx*2+1] - this->DataExtent[idx*2] + 1); + } + this->DataIncrements[3] = fileDataLength; +} + + +//---------------------------------------------------------------------------- +int vtkImageReader2::OpenFile() +{ + if (!this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Either a FileName or FilePattern must be specified."); + return 0; + } + + // Close file from any previous image + if (this->File) + { + this->File->close(); + delete this->File; + this->File = NULL; + } + + // Open the new file + vtkDebugMacro(<< "Initialize: opening file " << this->InternalFileName); + struct stat fs; + if ( !stat( this->InternalFileName, &fs) ) + { +#ifdef _WIN32 + this->File = new ifstream(this->InternalFileName, ios::in | ios::binary); +#else + this->File = new ifstream(this->InternalFileName, ios::in); +#endif + } + if (! this->File || this->File->fail()) + { + vtkErrorMacro(<< "Initialize: Could not open file " << this->InternalFileName); + return 0; + } + return 1; +} + + +//---------------------------------------------------------------------------- +unsigned long vtkImageReader2::GetHeaderSize() +{ + return this->GetHeaderSize(this->DataExtent[4]); +} + +//---------------------------------------------------------------------------- +unsigned long vtkImageReader2::GetHeaderSize(unsigned long idx) +{ + if (!this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Either a FileName or FilePattern must be specified."); + return 0; + } + if ( ! this->ManualHeaderSize) + { + this->ComputeDataIncrements(); + + // make sure we figure out a filename to open + this->ComputeInternalFileName(idx); + + struct stat statbuf; + if (!stat(this->InternalFileName, &statbuf)) + { + return (int)(statbuf.st_size - + (long)this->DataIncrements[this->GetFileDimensionality()]); + } + } + + return this->HeaderSize; +} + +//---------------------------------------------------------------------------- +void vtkImageReader2::SeekFile(int i, int j, int k) +{ + unsigned long streamStart; + + // convert data extent into constants that can be used to seek. + streamStart = + (i - this->DataExtent[0]) * this->DataIncrements[0]; + + if (this->FileLowerLeft) + { + streamStart = streamStart + + (j - this->DataExtent[2]) * this->DataIncrements[1]; + } + else + { + streamStart = streamStart + + (this->DataExtent[3] - this->DataExtent[2] - j) * + this->DataIncrements[1]; + } + + // handle three and four dimensional files + if (this->GetFileDimensionality() >= 3) + { + streamStart = streamStart + + (k - this->DataExtent[4]) * this->DataIncrements[2]; + } + + streamStart += this->GetHeaderSize(k); + + // error checking + this->File->seekg((long)streamStart, ios::beg); + if (this->File->fail()) + { + vtkWarningMacro("File operation failed."); + return; + } +} + +//---------------------------------------------------------------------------- +// This function reads in one data of data. +// templated to handle different data types. +template +void vtkImageReader2Update(vtkImageReader2 *self, vtkImageData *data, OT *outPtr) +{ + vtkIdType outIncr[3]; + OT *outPtr1, *outPtr2; + long streamRead; + int idx1, idx2, nComponents; + int outExtent[6]; + unsigned long count = 0; + unsigned long target; + + // Get the requested extents and increments + data->GetExtent(outExtent); + data->GetIncrements(outIncr); + nComponents = data->GetNumberOfScalarComponents(); + + // length of a row, num pixels read at a time + int pixelRead = outExtent[1] - outExtent[0] + 1; + streamRead = (long)(pixelRead*nComponents*sizeof(OT)); + + // create a buffer to hold a row of the data + target = (unsigned long)((outExtent[5]-outExtent[4]+1)* + (outExtent[3]-outExtent[2]+1)/50.0); + target++; + + // read the data row by row + if (self->GetFileDimensionality() == 3) + { + self->ComputeInternalFileName(0); + if ( !self->OpenFile() ) + { + return; + } + } + outPtr2 = outPtr; + for (idx2 = outExtent[4]; idx2 <= outExtent[5]; ++idx2) + { + if (self->GetFileDimensionality() == 2) + { + self->ComputeInternalFileName(idx2); + if ( !self->OpenFile() ) + { + return; + } + } + outPtr1 = outPtr2; + for (idx1 = outExtent[2]; + !self->AbortExecute && idx1 <= outExtent[3]; ++idx1) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + + // seek to the correct row + self->SeekFile(outExtent[0],idx1,idx2); + // read the row. + if ( !self->GetFile()->read((char *)outPtr1, streamRead)) + { + vtkGenericWarningMacro("File operation failed. row = " << idx1 + << ", Read = " << streamRead + << ", FilePos = " << static_cast(self->GetFile()->tellg())); + return; + } + // handle swapping + if (self->GetSwapBytes() && sizeof(OT) > 1) + { + vtkByteSwap::SwapVoidRange(outPtr1, pixelRead*nComponents, sizeof(OT)); + } + outPtr1 += outIncr[1]; + } + // move to the next image in the file and data + outPtr2 += outIncr[2]; + } +} + +//---------------------------------------------------------------------------- +// This function reads a data from a file. The datas extent/axes +// are assumed to be the same as the file extent/order. +void vtkImageReader2::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + void *ptr; + int *ext; + + if (!this->FileName && !this->FilePattern) + { + vtkErrorMacro("Either a valid FileName or FilePattern must be specified."); + return; + } + + ext = data->GetExtent(); + + data->GetPointData()->GetScalars()->SetName("ImageFile"); + + vtkDebugMacro("Reading extent: " << ext[0] << ", " << ext[1] << ", " + << ext[2] << ", " << ext[3] << ", " << ext[4] << ", " << ext[5]); + + this->ComputeDataIncrements(); + + // Call the correct templated function for the output + ptr = data->GetScalarPointer(); + switch (this->GetDataScalarType()) + { + vtkTemplateMacro(vtkImageReader2Update(this, data, (VTK_TT *)(ptr))); + default: + vtkErrorMacro(<< "UpdateFromFile: Unknown data type"); + } +} + + +//---------------------------------------------------------------------------- +// Set the data type of pixles in the file. +// If you want the output scalar type to have a different value, set it +// after this method is called. +void vtkImageReader2::SetDataScalarType(int type) +{ + if (type == this->DataScalarType) + { + return; + } + + this->Modified(); + this->DataScalarType = type; + // Set the default output scalar type + this->GetOutput()->SetScalarType(this->DataScalarType); +} diff --git a/IO/vtkImageReader2.h b/IO/vtkImageReader2.h new file mode 100644 index 0000000..37c6f31 --- /dev/null +++ b/IO/vtkImageReader2.h @@ -0,0 +1,237 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader2.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageReader2 - Superclass of binary file readers. +// .SECTION Description +// vtkImageReader2 is the parent class for vtkImageReader. It +// is a good super class for streaming readers that do not require +// a mask or transform on the data. vtkImageReader was implemented +// before vtkImageReader2, vtkImageReader2 is intended to have +// a simpler interface. + +// .SECTION See Also +// vtkJPEGReader vtkPNGReader vtkImageReader vtkGESignaReader + +#ifndef __vtkImageReader2_h +#define __vtkImageReader2_h + +#include "vtkImageAlgorithm.h" + +#define VTK_FILE_BYTE_ORDER_BIG_ENDIAN 0 +#define VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN 1 + +class VTK_IO_EXPORT vtkImageReader2 : public vtkImageAlgorithm +{ +public: + static vtkImageReader2 *New(); + vtkTypeRevisionMacro(vtkImageReader2,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name for the image file. You should specify either + // a FileName or a FilePrefix. Use FilePrefix if the data is stored + // in multiple files. + virtual void SetFileName(const char *); + vtkGetStringMacro(FileName); + + // Description: + // Specify file prefix for the image file(s).You should specify either + // a FileName or FilePrefix. Use FilePrefix if the data is stored + // in multiple files. + virtual void SetFilePrefix(const char *); + vtkGetStringMacro(FilePrefix); + + // Description: + // The sprintf format used to build filename from FilePrefix and number. + virtual void SetFilePattern(const char *); + vtkGetStringMacro(FilePattern); + + // Description: + // Set the data type of pixels in the file. + // If you want the output scalar type to have a different value, set it + // after this method is called. + virtual void SetDataScalarType(int type); + virtual void SetDataScalarTypeToFloat(){this->SetDataScalarType(VTK_FLOAT);} + virtual void SetDataScalarTypeToDouble(){this->SetDataScalarType(VTK_DOUBLE);} + virtual void SetDataScalarTypeToInt(){this->SetDataScalarType(VTK_INT);} + virtual void SetDataScalarTypeToShort(){this->SetDataScalarType(VTK_SHORT);} + virtual void SetDataScalarTypeToUnsignedShort() + {this->SetDataScalarType(VTK_UNSIGNED_SHORT);} + virtual void SetDataScalarTypeToUnsignedChar() + {this->SetDataScalarType(VTK_UNSIGNED_CHAR);} + + // Description: + // Get the file format. Pixels are this type in the file. + vtkGetMacro(DataScalarType, int); + + // Description: + // Set/Get the number of scalar components + vtkSetMacro(NumberOfScalarComponents,int); + vtkGetMacro(NumberOfScalarComponents,int); + + // Description: + // Get/Set the extent of the data on disk. + vtkSetVector6Macro(DataExtent,int); + vtkGetVector6Macro(DataExtent,int); + + // Description: + // The number of dimensions stored in a file. This defaults to two. + vtkSetMacro(FileDimensionality, int); + int GetFileDimensionality() {return this->FileDimensionality;} + + // Description: + // Set/Get the spacing of the data in the file. + vtkSetVector3Macro(DataSpacing,double); + vtkGetVector3Macro(DataSpacing,double); + + // Description: + // Set/Get the origin of the data (location of first pixel in the file). + vtkSetVector3Macro(DataOrigin,double); + vtkGetVector3Macro(DataOrigin,double); + + // Description: + // Get the size of the header computed by this object. + unsigned long GetHeaderSize(); + unsigned long GetHeaderSize(unsigned long slice); + + // Description: + // If there is a tail on the file, you want to explicitly set the + // header size. + virtual void SetHeaderSize(unsigned long size); + + // Description: + // These methods should be used instead of the SwapBytes methods. + // They indicate the byte ordering of the file you are trying + // to read in. These methods will then either swap or not swap + // the bytes depending on the byte ordering of the machine it is + // being run on. For example, reading in a BigEndian file on a + // BigEndian machine will result in no swapping. Trying to read + // the same file on a LittleEndian machine will result in swapping. + // As a quick note most UNIX machines are BigEndian while PC's + // and VAX tend to be LittleEndian. So if the file you are reading + // in was generated on a VAX or PC, SetDataByteOrderToLittleEndian + // otherwise SetDataByteOrderToBigEndian. + virtual void SetDataByteOrderToBigEndian(); + virtual void SetDataByteOrderToLittleEndian(); + virtual int GetDataByteOrder(); + virtual void SetDataByteOrder(int); + virtual const char *GetDataByteOrderAsString(); + + // Description: + // When reading files which start at an unusual index, this can be added + // to the slice number when generating the file name (default = 0) + vtkSetMacro(FileNameSliceOffset,int); + vtkGetMacro(FileNameSliceOffset,int); + + // Description: + // When reading files which have regular, but non contiguous slices + // (eg filename.1,filename.3,filename.5) + // a spacing can be specified to skip missing files (default = 1) + vtkSetMacro(FileNameSliceSpacing,int); + vtkGetMacro(FileNameSliceSpacing,int); + + + // Description: + // Set/Get the byte swapping to explicitly swap the bytes of a file. + vtkSetMacro(SwapBytes,int); + virtual int GetSwapBytes() {return this->SwapBytes;} + vtkBooleanMacro(SwapBytes,int); + +//BTX + ifstream *GetFile() {return this->File;} + vtkGetVectorMacro(DataIncrements,unsigned long,4); +//ETX + + virtual int OpenFile(); + virtual void SeekFile(int i, int j, int k); + + // Description: + // Set/Get whether the data comes from the file starting in the lower left + // corner or upper left corner. + vtkBooleanMacro(FileLowerLeft, int); + vtkGetMacro(FileLowerLeft, int); + vtkSetMacro(FileLowerLeft, int); + + // Description: + // Set/Get the internal file name + virtual void ComputeInternalFileName(int slice); + vtkGetStringMacro(InternalFileName); + + // Description: + // Return non zero if the reader can read the given file name. + // Should be implemented by all sub-classes of vtkImageReader2. + // For non zero return values the following values are to be used + // 1 - I think I can read the file but I cannot prove it + // 2 - I definitely can read the file + // 3 - I can read the file and I have validated that I am the + // correct reader for this file + virtual int CanReadFile(const char* vtkNotUsed(fname)) + { + return 0; + } + + // Description: + // Get the file extensions for this format. + // Returns a string with a space separated list of extensions in + // the format .extension + virtual const char* GetFileExtensions() + { + return 0; + } + + // Description: + // Return a descriptive name for the file format that might be useful in a GUI. + virtual const char* GetDescriptiveName() + { + return 0; + } +protected: + vtkImageReader2(); + ~vtkImageReader2(); + + char *InternalFileName; + char *FileName; + char *FilePrefix; + char *FilePattern; + int NumberOfScalarComponents; + int FileLowerLeft; + + ifstream *File; + unsigned long DataIncrements[4]; + int DataExtent[6]; + int SwapBytes; + + int FileDimensionality; + unsigned long HeaderSize; + int DataScalarType; + unsigned long ManualHeaderSize; + + double DataSpacing[3]; + double DataOrigin[3]; + + int FileNameSliceOffset; + int FileNameSliceSpacing; + + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual void ExecuteInformation(); + virtual void ExecuteData(vtkDataObject *data); + virtual void ComputeDataIncrements(); +private: + vtkImageReader2(const vtkImageReader2&); // Not implemented. + void operator=(const vtkImageReader2&); // Not implemented. +}; + +#endif diff --git a/IO/vtkImageReader2Collection.cxx b/IO/vtkImageReader2Collection.cxx new file mode 100644 index 0000000..17849da --- /dev/null +++ b/IO/vtkImageReader2Collection.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader2Collection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageReader2Collection.h" + +#include "vtkObjectFactory.h" +#include "vtkImageReader2.h" + +vtkCxxRevisionMacro(vtkImageReader2Collection, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkImageReader2Collection); + +void vtkImageReader2Collection::AddItem(vtkImageReader2 *f) +{ + this->vtkCollection::AddItem((vtkObject *)f); +} + +vtkImageReader2 *vtkImageReader2Collection::GetNextItem() +{ + return static_cast(this->GetNextItemAsObject()); +} + +vtkImageReader2 *vtkImageReader2Collection::GetNextImageReader2( + vtkCollectionSimpleIterator &cookie) +{ + return static_cast(this->GetNextItemAsObject(cookie)); +} + +//---------------------------------------------------------------------------- +void vtkImageReader2Collection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkImageReader2Collection.h b/IO/vtkImageReader2Collection.h new file mode 100644 index 0000000..28fc45e --- /dev/null +++ b/IO/vtkImageReader2Collection.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader2Collection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageReader2Collection - maintain a list of implicit functions +// .SECTION Description +// vtkImageReader2Collection is an object that creates and manipulates +// lists of objects of type vtkImplicitFunction. +// .SECTION See Also +// vtkCollection vtkPlaneCollection + +#ifndef __vtkImageReader2Collection_h +#define __vtkImageReader2Collection_h + +#include "vtkCollection.h" + +class vtkImageReader2; + +class VTK_IO_EXPORT vtkImageReader2Collection : public vtkCollection +{ +public: + vtkTypeRevisionMacro(vtkImageReader2Collection,vtkCollection); + static vtkImageReader2Collection *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add an implicit function to the list. + void AddItem(vtkImageReader2 *); + + // Description: + // Get the next implicit function in the list. + vtkImageReader2 *GetNextItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkImageReader2 *GetNextImageReader2(vtkCollectionSimpleIterator &cookie); + //ETX + +protected: + vtkImageReader2Collection() {}; + ~vtkImageReader2Collection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkImageReader2Collection(const vtkImageReader2Collection&); // Not implemented. + void operator=(const vtkImageReader2Collection&); // Not implemented. +}; + +#endif diff --git a/IO/vtkImageReader2Factory.cxx b/IO/vtkImageReader2Factory.cxx new file mode 100644 index 0000000..3d05f0d --- /dev/null +++ b/IO/vtkImageReader2Factory.cxx @@ -0,0 +1,172 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader2Factory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageReader2Factory.h" + +#include "vtkBMPReader.h" +#include "vtkGESignaReader.h" +#include "vtkImageReader2.h" +#include "vtkImageReader2Collection.h" +#include "vtkJPEGReader.h" +#include "vtkObjectFactory.h" +#include "vtkObjectFactoryCollection.h" +#include "vtkPNGReader.h" +#include "vtkPNMReader.h" +#include "vtkSLCReader.h" +#include "vtkTIFFReader.h" + +// Destroying the prototype readers requires information keys. +// Include the manager here to make sure the keys are not destroyed +// until after the AvailableReaders singleton has been destroyed. +#include "vtkFilteringInformationKeyManager.h" + +vtkCxxRevisionMacro(vtkImageReader2Factory, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkImageReader2Factory); + +class vtkImageReader2FactoryCleanup +{ +public: + inline void Use() + { + } + ~vtkImageReader2FactoryCleanup() + { + if(vtkImageReader2Factory::AvailableReaders) + { + vtkImageReader2Factory::AvailableReaders->Delete(); + vtkImageReader2Factory::AvailableReaders = 0; + } + } +}; +static vtkImageReader2FactoryCleanup vtkImageReader2FactoryCleanupGlobal; + +vtkImageReader2Collection* vtkImageReader2Factory::AvailableReaders; + +void vtkImageReader2Factory::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Available Readers : "; + if(AvailableReaders) + { + AvailableReaders->PrintSelf(os, indent); + } + else + { + os << "None."; + } +} + +vtkImageReader2Factory::vtkImageReader2Factory() +{ +} + +vtkImageReader2Factory::~vtkImageReader2Factory() +{ +} + +void vtkImageReader2Factory::RegisterReader(vtkImageReader2* r) +{ + vtkImageReader2Factory::InitializeReaders(); + AvailableReaders->AddItem(r); +} + + +vtkImageReader2* vtkImageReader2Factory::CreateImageReader2(const char* path) +{ + vtkImageReader2Factory::InitializeReaders(); + vtkImageReader2* ret; + vtkCollection* collection = vtkCollection::New(); + vtkObjectFactory::CreateAllInstance("vtkImageReaderObject", + collection); + vtkObject* o; + // first try the current registered object factories to see + // if one of them can + for(collection->InitTraversal(); (o = collection->GetNextItemAsObject()); ) + { + if(o) + { + ret = vtkImageReader2::SafeDownCast(o); + if(ret && ret->CanReadFile(path)) + { + return ret; + } + } + } + // get rid of the collection + collection->Delete(); + vtkCollectionSimpleIterator sit; + for(vtkImageReader2Factory::AvailableReaders->InitTraversal(sit); + (ret = vtkImageReader2Factory::AvailableReaders->GetNextImageReader2(sit));) + { + if(ret->CanReadFile(path)) + { + // like a new call + return ret->NewInstance(); + } + } + return 0; +} + + +void vtkImageReader2Factory::InitializeReaders() +{ + if(vtkImageReader2Factory::AvailableReaders) + { + return; + } + vtkImageReader2FactoryCleanupGlobal.Use(); + vtkImageReader2Factory::AvailableReaders = vtkImageReader2Collection::New(); + vtkImageReader2* reader; + + vtkImageReader2Factory::AvailableReaders-> + AddItem((reader = vtkPNGReader::New())); + reader->Delete(); + vtkImageReader2Factory::AvailableReaders-> + AddItem((reader = vtkPNMReader::New())); + reader->Delete(); + vtkImageReader2Factory::AvailableReaders-> + AddItem((reader = vtkTIFFReader::New())); + reader->Delete(); + vtkImageReader2Factory::AvailableReaders-> + AddItem((reader = vtkBMPReader::New())); + reader->Delete(); + vtkImageReader2Factory::AvailableReaders-> + AddItem((reader = vtkSLCReader::New())); + reader->Delete(); + vtkImageReader2Factory::AvailableReaders-> + AddItem((reader = vtkJPEGReader::New())); + reader->Delete(); + vtkImageReader2Factory::AvailableReaders-> + AddItem((reader = vtkGESignaReader::New())); + reader->Delete(); +} + + +void vtkImageReader2Factory::GetRegisteredReaders(vtkImageReader2Collection* collection) +{ + vtkImageReader2Factory::InitializeReaders(); + // get all dynamic readers + vtkObjectFactory::CreateAllInstance("vtkImageReaderObject", + collection); + // get the current registered readers + vtkImageReader2* ret; + vtkCollectionSimpleIterator sit; + for(vtkImageReader2Factory::AvailableReaders->InitTraversal(sit); + (ret = vtkImageReader2Factory::AvailableReaders->GetNextImageReader2(sit));) + { + collection->AddItem(ret); + } +} + + diff --git a/IO/vtkImageReader2Factory.h b/IO/vtkImageReader2Factory.h new file mode 100644 index 0000000..c7a29fe --- /dev/null +++ b/IO/vtkImageReader2Factory.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReader2Factory.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageReader2Factory - Superclass of binary file readers. +// .SECTION Description +// vtkImageReader2Factory: This class is used to create a vtkImageReader2 +// object given a path name to a file. It calls CanReadFile on all +// availiable readers until one of them returns ture. The availiable reader +// list comes from three places. In the InitializeReaders function of this +// class, built-in VTK classes are added to the list, users can call +// RegisterReader, or users can create a vtkObjectFactory that has +// CreateObject method that returns a new vtkImageReader2 sub class when +// given the string "vtkImageReaderObject". This way applications can be +// extened with new readers via a plugin dll or by calling RegisterReader. +// Of course all of the readers that are part of the vtk release are made +// automatically availiable. +// +// .SECTION See Also +// vtkImageReader2 + +#ifndef __vtkImageReader2Factory_h +#define __vtkImageReader2Factory_h + + +#include "vtkObject.h" + +class vtkImageReader2; +class vtkImageReader2Collection; +class vtkImageReader2FactoryCleanup; + +class VTK_IO_EXPORT vtkImageReader2Factory : public vtkObject +{ +public: + static vtkImageReader2Factory *New(); + vtkTypeRevisionMacro(vtkImageReader2Factory,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + //Description: register a reader with the available readers. + // registered readers will be queried in CreateImageReader2 to + // see if they can load a given file. + static void RegisterReader(vtkImageReader2* r); + + //Description: Given a path to a file find a reader that can + // open the image file, it is the callers responsibility to call + // Delete on the returned object. If no reader is found, null + // is returned. + static vtkImageReader2* CreateImageReader2(const char* path); + + // Description: get a list of the currently registered readers. + // The caller must allocate the vtkImageReader2Collection and pass in the + // pointer to this method. + static void GetRegisteredReaders(vtkImageReader2Collection* ); +protected: + vtkImageReader2Factory(); + ~vtkImageReader2Factory(); + + // Description: Initialize availiable readers list. + static void InitializeReaders(); + +private: + static vtkImageReader2Collection* AvailableReaders; + vtkImageReader2Factory(const vtkImageReader2Factory&); // Not implemented. + void operator=(const vtkImageReader2Factory&); // Not implemented. +//BTX + friend class vtkImageReader2FactoryCleanup; +//ETX +}; + +#endif diff --git a/IO/vtkImageWriter.cxx b/IO/vtkImageWriter.cxx new file mode 100644 index 0000000..65de823 --- /dev/null +++ b/IO/vtkImageWriter.cxx @@ -0,0 +1,539 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageWriter.h" + +#include "vtkCommand.h" +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkImageData.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +vtkCxxRevisionMacro(vtkImageWriter, "$Revision: 1.60 $"); +vtkStandardNewMacro(vtkImageWriter); + +#ifdef write +#undef write +#endif + +#ifdef close +#undef close +#endif + + +//---------------------------------------------------------------------------- +vtkImageWriter::vtkImageWriter() +{ + this->FilePrefix = NULL; + this->FilePattern = NULL; + this->FileName = NULL; + this->InternalFileName = NULL; + this->FileNumber = 0; + this->FileDimensionality = 2; + + this->FilePattern = new char[strlen("%s.%d") + 1]; + strcpy(this->FilePattern, "%s.%d"); + + this->FileLowerLeft = 0; + + this->MinimumFileNumber = this->MaximumFileNumber = 0; + this->FilesDeleted = 0; + this->SetNumberOfOutputPorts(0); +} + + + +//---------------------------------------------------------------------------- +vtkImageWriter::~vtkImageWriter() +{ + // get rid of memory allocated for file names + if (this->FilePrefix) + { + delete [] this->FilePrefix; + this->FilePrefix = NULL; + } + if (this->FilePattern) + { + delete [] this->FilePattern; + this->FilePattern = NULL; + } + if (this->FileName) + { + delete [] this->FileName; + this->FileName = NULL; + } +} + + +//---------------------------------------------------------------------------- +void vtkImageWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "FileName: " << + (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "FilePrefix: " << + (this->FilePrefix ? this->FilePrefix : "(none)") << "\n"; + os << indent << "FilePattern: " << + (this->FilePattern ? this->FilePattern : "(none)") << "\n"; + + os << indent << "FileDimensionality: " << this->FileDimensionality << "\n"; +} + + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageWriter::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} +//---------------------------------------------------------------------------- + +int vtkImageWriter::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed( outputVector) ) +{ + this->SetErrorCode(vtkErrorCode::NoError); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *input = + vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Error checking + if (input == NULL ) + { + vtkErrorMacro(<<"Write:Please specify an input!"); + return 0; + } + if ( !this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Write:Please specify either a FileName or a file prefix and pattern"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return 0; + } + + // Make sure the file name is allocated + this->InternalFileName = + new char[(this->FileName ? strlen(this->FileName) : 1) + + (this->FilePrefix ? strlen(this->FilePrefix) : 1) + + (this->FilePattern ? strlen(this->FilePattern) : 1) + 10]; + + // Fill in image information. + int *wExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + this->FileNumber = wExt[4]; + this->MinimumFileNumber = this->MaximumFileNumber = this->FileNumber; + this->FilesDeleted = 0; + + // Write + this->InvokeEvent(vtkCommand::StartEvent); + this->UpdateProgress(0.0); + this->RecursiveWrite(2, input, NULL); + + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeleteFiles(); + } + + this->UpdateProgress(1.0); + this->InvokeEvent(vtkCommand::EndEvent); + + delete [] this->InternalFileName; + this->InternalFileName = NULL; + + return 1; +} + +//---------------------------------------------------------------------------- +// Writes all the data from the input. +void vtkImageWriter::Write() +{ + // we always write, even if nothing has changed, so send a modified + this->Modified(); + this->UpdateInformation(); + this->GetInput()->SetUpdateExtent(this->GetInput()->GetWholeExtent()); + this->Update(); +} + +//---------------------------------------------------------------------------- +// Breaks region into pieces with correct dimensionality. +void vtkImageWriter::RecursiveWrite(int axis, vtkImageData *cache, + ofstream *file) +{ + vtkImageData *data; + int fileOpenedHere = 0; + int *ext; + + // if we need to open another slice, do it + if (!file && (axis + 1) == this->FileDimensionality) + { + // determine the name + if (this->FileName) + { + sprintf(this->InternalFileName,"%s",this->FileName); + } + else + { + if (this->FilePrefix) + { + sprintf(this->InternalFileName, this->FilePattern, + this->FilePrefix, this->FileNumber); + } + else + { + sprintf(this->InternalFileName, this->FilePattern,this->FileNumber); + } + if (this->FileNumber < this->MinimumFileNumber) + { + this->MinimumFileNumber = this->FileNumber; + } + else if (this->FileNumber > this->MaximumFileNumber) + { + this->MaximumFileNumber = this->FileNumber; + } + } + // Open the file +#ifdef _WIN32 + file = new ofstream(this->InternalFileName, ios::out | ios::binary); +#else + file = new ofstream(this->InternalFileName, ios::out); +#endif + fileOpenedHere = 1; + if (file->fail()) + { + vtkErrorMacro("RecursiveWrite: Could not open file " << + this->InternalFileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + delete file; + return; + } + + // Subclasses can write a header with this method call. + this->WriteFileHeader(file, cache); + file->flush(); + if (file->fail()) + { + file->close(); + delete file; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + ++this->FileNumber; + } + + // Propagate the update extent so we can determine pipeline size + this->GetInput()->PropagateUpdateExtent(); + + // just get the data and write it out + ext = cache->GetUpdateExtent(); + vtkDebugMacro("Getting input extent: " << ext[0] << ", " << + ext[1] << ", " << ext[2] << ", " << ext[3] << ", " << + ext[4] << ", " << ext[5] << endl); + cache->Update(); + data = cache; + this->RecursiveWrite(axis,cache,data,file); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeleteFiles(); + return; + } + if (file && fileOpenedHere) + { + this->WriteFileTrailer(file,cache); + file->flush(); + if (file->fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } + file->close(); + delete file; + } + return; +} + + +//---------------------------------------------------------------------------- +// same idea as the previous method, but it knows that the data is ready +void vtkImageWriter::RecursiveWrite(int axis, vtkImageData *cache, + vtkImageData *data, ofstream *file) +{ + int idx, min, max; + + // if the file is already open then just write to it + if (file) + { + this->WriteFile(file,data,cache->GetUpdateExtent()); + file->flush(); + if (file->fail()) + { + file->close(); + delete file; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } + return; + } + + // if we need to open another slice, do it + if (!file && (axis + 1) == this->FileDimensionality) + { + // determine the name + if (this->FileName) + { + sprintf(this->InternalFileName,"%s",this->FileName); + } + else + { + if (this->FilePrefix) + { + sprintf(this->InternalFileName, this->FilePattern, + this->FilePrefix, this->FileNumber); + } + else + { + sprintf(this->InternalFileName, this->FilePattern,this->FileNumber); + } + if (this->FileNumber < this->MinimumFileNumber) + { + this->MinimumFileNumber = this->FileNumber; + } + else if (this->FileNumber > this->MaximumFileNumber) + { + this->MaximumFileNumber = this->FileNumber; + } + } + // Open the file +#ifdef _WIN32 + file = new ofstream(this->InternalFileName, ios::out | ios::binary); +#else + file = new ofstream(this->InternalFileName, ios::out); +#endif + if (file->fail()) + { + vtkErrorMacro("RecursiveWrite: Could not open file " << + this->InternalFileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + delete file; + return; + } + + // Subclasses can write a header with this method call. + this->WriteFileHeader(file, cache); + file->flush(); + if (file->fail()) + { + file->close(); + delete file; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + this->WriteFile(file,data,cache->GetUpdateExtent()); + file->flush(); + if (file->fail()) + { + file->close(); + delete file; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + ++this->FileNumber; + this->WriteFileTrailer(file,cache); + file->flush(); + if (file->fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } + file->close(); + delete file; + return; + } + + // if the current region is too high a dimension forthe file + // the we will split the current axis + cache->GetAxisUpdateExtent(axis, min, max); + + // if it is the y axis then flip by default + if (axis == 1 && !this->FileLowerLeft) + { + for(idx = max; idx >= min; idx--) + { + cache->SetAxisUpdateExtent(axis, idx, idx); + if (this->ErrorCode != vtkErrorCode::OutOfDiskSpaceError) + { + this->RecursiveWrite(axis - 1, cache, data, file); + } + else + { + this->DeleteFiles(); + } + } + } + else + { + for(idx = min; idx <= max; idx++) + { + cache->SetAxisUpdateExtent(axis, idx, idx); + if (this->ErrorCode != vtkErrorCode::OutOfDiskSpaceError) + { + this->RecursiveWrite(axis - 1, cache, data, file); + } + else + { + this->DeleteFiles(); + } + } + } + + // restore original extent + cache->SetAxisUpdateExtent(axis, min, max); +} + + +//---------------------------------------------------------------------------- +template +unsigned long vtkImageWriterGetSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +// Writes a region in a file. Subclasses can override this method +// to produce a header. This method only hanldes 3d data (plus components). +void vtkImageWriter::WriteFile(ofstream *file, vtkImageData *data, + int extent[6]) +{ + int idxY, idxZ; + int rowLength; // in bytes + void *ptr; + unsigned long count = 0; + unsigned long target; + float progress = this->Progress; + float area; + int *wExtent; + + // Make sure we actually have data. + if ( !data->GetPointData()->GetScalars()) + { + vtkErrorMacro(<< "Could not get data from input."); + return; + } + + // take into consideration the scalar type + switch (data->GetScalarType()) + { + vtkTemplateMacro( + rowLength = vtkImageWriterGetSize(static_cast(0)) + ); + default: + vtkErrorMacro(<< "Execute: Unknown output ScalarType"); + return; + } + rowLength *= data->GetNumberOfScalarComponents(); + rowLength *= (extent[1] - extent[0] + 1); + + wExtent = this->GetInput()->GetWholeExtent(); + area = (float) ((extent[5] - extent[4] + 1)* + (extent[3] - extent[2] + 1)* + (extent[1] - extent[0] + 1)) / + (float) ((wExtent[5] -wExtent[4] + 1)* + (wExtent[3] -wExtent[2] + 1)* + (wExtent[1] -wExtent[0] + 1)); + + target = (unsigned long)((extent[5]-extent[4]+1)* + (extent[3]-extent[2]+1)/(50.0*area)); + target++; + + int ystart = extent[3]; + int yend = extent[2] - 1; + int yinc = -1; + if (this->FileLowerLeft) + { + ystart = extent[2]; + yend = extent[3]+1; + yinc = 1; + } + + for (idxZ = extent[4]; idxZ <= extent[5]; ++idxZ) + { + for (idxY = ystart; idxY != yend; idxY = idxY + yinc) + { + if (!(count%target)) + { + this->UpdateProgress(progress + count/(50.0*target)); + } + count++; + ptr = data->GetScalarPointer(extent[0], idxY, idxZ); + if ( ! file->write((char *)ptr, rowLength)) + { + return; + } + } + } +} + +void vtkImageWriter::DeleteFiles() +{ + if (this->FilesDeleted) + { + return; + } + int i; + char *fileName; + + vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); + + if (this->FileName) + { + unlink(this->FileName); + } + else + { + if (this->FilePrefix) + { + fileName = + new char[strlen(this->FilePrefix) + strlen(this->FilePattern) + 10]; + + for (i = this->MinimumFileNumber; i <= this->MaximumFileNumber; i++) + { + sprintf(fileName, this->FilePattern, this->FilePrefix, i); + unlink(fileName); + } + delete [] fileName; + } + else + { + fileName = new char[strlen(this->FilePattern) + 10]; + + for (i = this->MinimumFileNumber; i <= this->MaximumFileNumber; i++) + { + sprintf(fileName, this->FilePattern, i); + unlink(fileName); + } + delete [] fileName; + } + } + this->FilesDeleted = 1; +} diff --git a/IO/vtkImageWriter.h b/IO/vtkImageWriter.h new file mode 100644 index 0000000..dd34fb2 --- /dev/null +++ b/IO/vtkImageWriter.h @@ -0,0 +1,107 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageWriter - Writes images to files. +// .SECTION Description +// vtkImageWriter writes images to files with any data type. The data type of +// the file is the same scalar type as the input. The dimensionality +// determines whether the data will be written in one or multiple files. +// This class is used as the superclass of most image writing classes +// such as vtkBMPWriter etc. It supports streaming. + +#ifndef __vtkImageWriter_h +#define __vtkImageWriter_h + +#include "vtkImageAlgorithm.h" + +class VTK_IO_EXPORT vtkImageWriter : public vtkImageAlgorithm +{ +public: + static vtkImageWriter *New(); + vtkTypeRevisionMacro(vtkImageWriter,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name for the image file. You should specify either + // a FileName or a FilePrefix. Use FilePrefix if the data is stored + // in multiple files. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Specify file prefix for the image file(s).You should specify either + // a FileName or FilePrefix. Use FilePrefix if the data is stored + // in multiple files. + vtkSetStringMacro(FilePrefix); + vtkGetStringMacro(FilePrefix); + + // Description: + // The sprintf format used to build filename from FilePrefix and number. + vtkSetStringMacro(FilePattern); + vtkGetStringMacro(FilePattern); + + // Description: + // What dimension are the files to be written. Usually this is 2, or 3. + // If it is 2 and the input is a volume then the volume will be + // written as a series of 2d slices. + vtkSetMacro(FileDimensionality, int); + vtkGetMacro(FileDimensionality, int); + +//BTX + // Description: + // Set/Get the input object from the image pipeline. + vtkImageData *GetInput(); +//ETX + + // Description: + // The main interface which triggers the writer to start. + virtual void Write(); + + void DeleteFiles(); + +protected: + vtkImageWriter(); + ~vtkImageWriter(); + + int FileDimensionality; + char *FilePrefix; + char *FilePattern; + char *FileName; + int FileNumber; + int FileLowerLeft; + char *InternalFileName; + + virtual void RecursiveWrite(int dim, vtkImageData *region, ofstream *file); + virtual void RecursiveWrite(int dim, vtkImageData *cache, + vtkImageData *data, ofstream *file); + virtual void WriteFile(ofstream *file, vtkImageData *data, int extent[6]); + virtual void WriteFileHeader(ofstream *, vtkImageData *) {}; + virtual void WriteFileTrailer(ofstream *, vtkImageData *) {}; + + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + int MinimumFileNumber; + int MaximumFileNumber; + int FilesDeleted; + +private: + vtkImageWriter(const vtkImageWriter&); // Not implemented. + void operator=(const vtkImageWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkInputStream.cxx b/IO/vtkInputStream.cxx new file mode 100644 index 0000000..e7c53f1 --- /dev/null +++ b/IO/vtkInputStream.cxx @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInputStream.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInputStream.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkInputStream, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkInputStream); + +//---------------------------------------------------------------------------- +vtkInputStream::vtkInputStream() +{ + this->Stream = 0; +} + +//---------------------------------------------------------------------------- +vtkInputStream::~vtkInputStream() +{ + this->SetStream(0); +} + +//---------------------------------------------------------------------------- +void vtkInputStream::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Stream: " << (this->Stream? "set" : "none") << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkInputStream::StartReading() +{ + if(!this->Stream) + { + vtkErrorMacro("StartReading() called with no Stream set."); + } + this->StreamStartPosition = this->Stream->tellg(); +} + +//---------------------------------------------------------------------------- +void vtkInputStream::EndReading() +{ +} + +//---------------------------------------------------------------------------- +int vtkInputStream::Seek(unsigned long offset) +{ + return (this->Stream->seekg(this->StreamStartPosition+offset)? 1:0); +} + +//---------------------------------------------------------------------------- +unsigned long vtkInputStream::Read(unsigned char* data, unsigned long length) +{ + return this->Read(reinterpret_cast(data), length); +} + +//---------------------------------------------------------------------------- +unsigned long vtkInputStream::Read(char* data, unsigned long length) +{ + this->Stream->read(data, length); + return this->Stream->gcount(); +} diff --git a/IO/vtkInputStream.h b/IO/vtkInputStream.h new file mode 100644 index 0000000..3cf118c --- /dev/null +++ b/IO/vtkInputStream.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInputStream.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInputStream - Wraps a binary input stream with a VTK interface. +// .SECTION Description +// vtkInputStream provides a VTK-style interface wrapping around a +// standard input stream. The access methods are virtual so that +// subclasses can transparently provide decoding of an encoded stream. +// Data lengths for Seek and Read calls refer to the length of the +// input data. The actual length in the stream may differ for +// subclasses that implement an encoding scheme. + +#ifndef __vtkInputStream_h +#define __vtkInputStream_h + +#include "vtkObject.h" + +class VTK_IO_EXPORT vtkInputStream : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkInputStream,vtkObject); + static vtkInputStream *New(); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the real input stream. + vtkSetMacro(Stream, istream*); + vtkGetMacro(Stream, istream*); + //ETX + + // Description: + // Called after the stream position has been set by the caller, but + // before any Seek or Read calls. The stream position should not be + // adjusted by the caller until after an EndReading call. + virtual void StartReading(); + + // Description: + // Seek to the given offset in the input data. Returns 1 for + // success, 0 for failure. + virtual int Seek(unsigned long offset); + + // Description: + // Read input data of the given length. Returns amount actually + // read. + virtual unsigned long Read(unsigned char* data, unsigned long length); + unsigned long Read(char* data, unsigned long length); + + // Description: + // Called after all desired calls to Seek and Read have been made. + // After this call, the caller is free to change the position of the + // stream. Additional reads should not be done until after another + // call to StartReading. + virtual void EndReading(); + +protected: + vtkInputStream(); + ~vtkInputStream(); + + // The real input stream. + istream* Stream; + + // The input stream's position when StartReading was called. + unsigned long StreamStartPosition; + +private: + vtkInputStream(const vtkInputStream&); // Not implemented. + void operator=(const vtkInputStream&); // Not implemented. +}; + +#endif diff --git a/IO/vtkJPEGReader.cxx b/IO/vtkJPEGReader.cxx new file mode 100644 index 0000000..fbaacd7 --- /dev/null +++ b/IO/vtkJPEGReader.cxx @@ -0,0 +1,362 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJPEGReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkJPEGReader.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkToolkits.h" + +extern "C" { +#include "vtk_jpeg.h" +#if defined(__sgi) && !defined(__GNUC__) +# if (_COMPILER_VERSION >= 730) +# pragma set woff 3505 +# endif +#endif +#include +} + + +vtkCxxRevisionMacro(vtkJPEGReader, "$Revision: 1.24 $"); +vtkStandardNewMacro(vtkJPEGReader); + + +// create an error handler for jpeg that +// can longjmp out of the jpeg library +struct vtk_jpeg_error_mgr +{ + struct jpeg_error_mgr pub; /* "public" fields */ + jmp_buf setjmp_buffer; /* for return to caller */ + vtkJPEGReader* JPEGReader; +}; + +// this is called on jpeg error conditions +extern "C" void vtk_jpeg_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + vtk_jpeg_error_mgr * err = reinterpret_cast(cinfo->err); + + /* Return control to the setjmp point */ + longjmp(err->setjmp_buffer, 1); +} + +extern "C" void vtk_jpeg_output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + vtk_jpeg_error_mgr * err = reinterpret_cast(cinfo->err); + vtkWarningWithObjectMacro(err->JPEGReader, + "libjpeg error: " << buffer); +} + +#ifdef _MSC_VER +// Let us get rid of this funny warning on /W4: +// warning C4611: interaction between '_setjmp' and C++ object +// destruction is non-portable +#pragma warning( disable : 4611 ) +#endif + +void vtkJPEGReader::ExecuteInformation() +{ + this->ComputeInternalFileName(this->DataExtent[4]); + if (this->InternalFileName == NULL) + { + return; + } + + FILE *fp = fopen(this->InternalFileName, "rb"); + if (!fp) + { + vtkErrorWithObjectMacro(this, + "Unable to open file " + << this->InternalFileName); + return; + } + + // create jpeg decompression object and error handler + struct jpeg_decompress_struct cinfo; + struct vtk_jpeg_error_mgr jerr; + jerr.JPEGReader = this; + + cinfo.err = jpeg_std_error(&jerr.pub); + // for any jpeg error call vtk_jpeg_error_exit + jerr.pub.error_exit = vtk_jpeg_error_exit; + // for any output message call vtk_jpeg_output_message + jerr.pub.output_message = vtk_jpeg_output_message; + if (setjmp(jerr.setjmp_buffer)) + { + // clean up + jpeg_destroy_decompress(&cinfo); + // close the file + fclose(fp); + // this is not a valid jpeg file + vtkErrorWithObjectMacro(this, "libjpeg could not read file: " + << this->InternalFileName); + return; + } + jpeg_create_decompress(&cinfo); + + // set the source file + jpeg_stdio_src(&cinfo, fp); + + // read the header + jpeg_read_header(&cinfo, TRUE); + + // force the output image size to be calculated (we could have used + // cinfo.image_height etc. but that would preclude using libjpeg's + // ability to scale an image on input). + jpeg_calc_output_dimensions(&cinfo); + + // pull out the width/height, etc. + this->DataExtent[0] = 0; + this->DataExtent[1] = cinfo.output_width - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = cinfo.output_height - 1; + + this->SetDataScalarTypeToUnsignedChar(); + this->SetNumberOfScalarComponents( cinfo.output_components ); + + this->vtkImageReader2::ExecuteInformation(); + + // close the file + jpeg_destroy_decompress(&cinfo); + fclose(fp); +} + +template +int vtkJPEGReaderUpdate2(vtkJPEGReader *self, OT *outPtr, + int *outExt, vtkIdType *outInc, long) +{ + unsigned int ui; + int i; + FILE *fp = fopen(self->GetInternalFileName(), "rb"); + if (!fp) + { + return 1; + } + + // create jpeg decompression object and error handler + struct jpeg_decompress_struct cinfo; + struct vtk_jpeg_error_mgr jerr; + jerr.JPEGReader = self; + + cinfo.err = jpeg_std_error(&jerr.pub); + // for any jpeg error call vtk_jpeg_error_exit + jerr.pub.error_exit = vtk_jpeg_error_exit; + // for any output message call vtk_jpeg_output_message + jerr.pub.output_message = vtk_jpeg_output_message; + if (setjmp(jerr.setjmp_buffer)) + { + // clean up + jpeg_destroy_decompress(&cinfo); + // close the file + fclose(fp); + + // this is not a valid jpeg file + return 2; + } + jpeg_create_decompress(&cinfo); + + // set the source file + jpeg_stdio_src(&cinfo, fp); + + // read the header + jpeg_read_header(&cinfo, TRUE); + + // prepare to read the bulk data + jpeg_start_decompress(&cinfo); + + + int rowbytes = cinfo.output_components * cinfo.output_width; + unsigned char *tempImage = new unsigned char [rowbytes*cinfo.output_height]; + JSAMPROW *row_pointers = new JSAMPROW [cinfo.output_height]; + for (ui = 0; ui < cinfo.output_height; ++ui) + { + row_pointers[ui] = tempImage + rowbytes*ui; + } + + // read the bulk data + unsigned int remainingRows; + while (cinfo.output_scanline < cinfo.output_height) + { + remainingRows = cinfo.output_height - cinfo.output_scanline; + jpeg_read_scanlines(&cinfo, &row_pointers[cinfo.output_scanline], + remainingRows); + } + + // finish the decompression step + jpeg_finish_decompress(&cinfo); + + // destroy the decompression object + jpeg_destroy_decompress(&cinfo); + + // copy the data into the outPtr + OT *outPtr2; + outPtr2 = outPtr; + long outSize = cinfo.output_components*(outExt[1] - outExt[0] + 1); + for (i = outExt[2]; i <= outExt[3]; ++i) + { + memcpy(outPtr2, + row_pointers[cinfo.output_height - i - 1] + + outExt[0]*cinfo.output_components, + outSize); + outPtr2 += outInc[1]; + } + delete [] tempImage; + delete [] row_pointers; + + // close the file + fclose(fp); + return 0; +} + +//---------------------------------------------------------------------------- +// This function reads in one data of data. +// templated to handle different data types. +template +void vtkJPEGReaderUpdate(vtkJPEGReader *self, vtkImageData *data, OT *outPtr) +{ + vtkIdType outIncr[3]; + int outExtent[6]; + OT *outPtr2; + + data->GetExtent(outExtent); + data->GetIncrements(outIncr); + + long pixSize = data->GetNumberOfScalarComponents()*sizeof(OT); + + outPtr2 = outPtr; + int idx2; + for (idx2 = outExtent[4]; idx2 <= outExtent[5]; ++idx2) + { + self->ComputeInternalFileName(idx2); + // read in a JPEG file + if ( vtkJPEGReaderUpdate2(self, outPtr2, outExtent, outIncr, pixSize) == 2 ) + { + const char* fn = self->GetInternalFileName(); + vtkErrorWithObjectMacro(self, "libjpeg could not read file: " << fn); + } + + self->UpdateProgress((idx2 - outExtent[4])/ + (outExtent[5] - outExtent[4] + 1.0)); + outPtr2 += outIncr[2]; + } +} + + +//---------------------------------------------------------------------------- +// This function reads a data from a file. The datas extent/axes +// are assumed to be the same as the file extent/order. +void vtkJPEGReader::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + if (this->InternalFileName == NULL) + { + vtkErrorMacro(<< "Either a FileName or FilePrefix must be specified."); + return; + } + + this->ComputeDataIncrements(); + + data->GetPointData()->GetScalars()->SetName("JPEGImage"); + + // Call the correct templated function for the output + void *outPtr; + + // Call the correct templated function for the input + outPtr = data->GetScalarPointer(); + switch (data->GetScalarType()) + { + vtkTemplateMacro(vtkJPEGReaderUpdate(this, data, (VTK_TT *)(outPtr))); + default: + vtkErrorMacro(<< "UpdateFromFile: Unknown data type"); + } +} + + + +int vtkJPEGReader::CanReadFile(const char* fname) +{ + // open the file + FILE *fp = fopen(fname, "rb"); + if (!fp) + { + return 0; + } + // read the first two bytes + char magic[2]; + int n = static_cast(fread(magic, sizeof(magic), 1, fp)); + if (n != 1) + { + fclose(fp); + return 0; + } + // check for the magic stuff: + // 0xFF followed by 0xD8 + if( ( (static_cast(magic[0]) != 0xFF) || + (static_cast(magic[1]) != 0xD8) ) ) + { + fclose(fp); + return 0; + } + // go back to the start of the file + fseek(fp, 0, SEEK_SET); + // magic number is ok, try and read the header + struct vtk_jpeg_error_mgr jerr; + jerr.JPEGReader = this; + struct jpeg_decompress_struct cinfo; + cinfo.err = jpeg_std_error(&jerr.pub); + // for any jpeg error call vtk_jpeg_error_exit + jerr.pub.error_exit = vtk_jpeg_error_exit; + // for any output message call vtk_jpeg_error_exit + jerr.pub.output_message = vtk_jpeg_error_exit; + // set the jump point, if there is a jpeg error or warning + // this will evaluate to true + if (setjmp(jerr.setjmp_buffer)) + { + // clean up + jpeg_destroy_decompress(&cinfo); + // close the file + fclose(fp); + // this is not a valid jpeg file + return 0; + } + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + /* Step 2: specify data source (eg, a file) */ + jpeg_stdio_src(&cinfo, fp); + /* Step 3: read file parameters with jpeg_read_header() */ + jpeg_read_header(&cinfo, TRUE); + + // if no errors have occurred yet, then it must be jpeg + jpeg_destroy_decompress(&cinfo); + fclose(fp); + return 3; +} +#ifdef _MSC_VER +// Put the warning back +#pragma warning( default : 4611 ) +#endif + + +//---------------------------------------------------------------------------- +void vtkJPEGReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkJPEGReader.h b/IO/vtkJPEGReader.h new file mode 100644 index 0000000..1d84d7f --- /dev/null +++ b/IO/vtkJPEGReader.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJPEGReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkJPEGReader - read JPEG files +// .SECTION Description +// vtkJPEGReader is a source object that reads JPEG files. +// It should be able to read most any JPEG file +// +// .SECTION See Also +// vtkJPEGWriter + +#ifndef __vtkJPEGReader_h +#define __vtkJPEGReader_h + +#include "vtkImageReader2.h" + +class VTK_IO_EXPORT vtkJPEGReader : public vtkImageReader2 +{ +public: + static vtkJPEGReader *New(); + vtkTypeRevisionMacro(vtkJPEGReader,vtkImageReader2); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Is the given file a JPEG file? + int CanReadFile(const char* fname); + + // Description: + // Get the file extensions for this format. + // Returns a string with a space separated list of extensions in + // the format .extension + virtual const char* GetFileExtensions() + { + return ".jpeg .jpg"; + } + + // Description: + // Return a descriptive name for the file format that might be useful in a GUI. + virtual const char* GetDescriptiveName() + { + return "JPEG"; + } +protected: + vtkJPEGReader() {}; + ~vtkJPEGReader() {}; + + virtual void ExecuteInformation(); + virtual void ExecuteData(vtkDataObject *out); +private: + vtkJPEGReader(const vtkJPEGReader&); // Not implemented. + void operator=(const vtkJPEGReader&); // Not implemented. +}; +#endif + + diff --git a/IO/vtkJPEGWriter.cxx b/IO/vtkJPEGWriter.cxx new file mode 100644 index 0000000..9534286 --- /dev/null +++ b/IO/vtkJPEGWriter.cxx @@ -0,0 +1,360 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJPEGWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkJPEGWriter.h" + +#include "vtkErrorCode.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkToolkits.h" +#include "vtkUnsignedCharArray.h" + +extern "C" { +#include "vtk_jpeg.h" +#if defined(__sgi) && !defined(__GNUC__) +# if (_COMPILER_VERSION >= 730) +# pragma set woff 3505 +# endif +#endif +#include +} + +vtkCxxRevisionMacro(vtkJPEGWriter, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkJPEGWriter); + +vtkCxxSetObjectMacro(vtkJPEGWriter,Result,vtkUnsignedCharArray); + +vtkJPEGWriter::vtkJPEGWriter() +{ + this->FileLowerLeft = 1; + this->FileDimensionality = 2; + + this->Quality = 95; + this->Progressive = 1; + this->WriteToMemory = 0; + this->Result = 0; + this->TempFP = 0; +} + +vtkJPEGWriter::~vtkJPEGWriter() +{ + if (this->Result) + { + this->Result->Delete(); + this->Result = 0; + } +} + +//---------------------------------------------------------------------------- +// Writes all the data from the input. +void vtkJPEGWriter::Write() +{ + this->SetErrorCode(vtkErrorCode::NoError); + + // Error checking + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<<"Write:Please specify an input!"); + return; + } + if (!this->WriteToMemory && ! this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Write:Please specify either a FileName or a file prefix and pattern"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return; + } + + // Make sure the file name is allocated + this->InternalFileName = + new char[(this->FileName ? strlen(this->FileName) : 1) + + (this->FilePrefix ? strlen(this->FilePrefix) : 1) + + (this->FilePattern ? strlen(this->FilePattern) : 1) + 10]; + + // Fill in image information. + this->GetInput()->UpdateInformation(); + int *wExtent; + wExtent = this->GetInput()->GetWholeExtent(); + this->FileNumber = this->GetInput()->GetWholeExtent()[4]; + this->MinimumFileNumber = this->MaximumFileNumber = this->FileNumber; + this->FilesDeleted = 0; + this->UpdateProgress(0.0); + // loop over the z axis and write the slices + for (this->FileNumber = wExtent[4]; this->FileNumber <= wExtent[5]; + ++this->FileNumber) + { + this->MaximumFileNumber = this->FileNumber; + this->GetInput()->SetUpdateExtent(wExtent[0], wExtent[1], + wExtent[2], wExtent[3], + this->FileNumber, + this->FileNumber); + // determine the name + if (this->FileName) + { + sprintf(this->InternalFileName,"%s",this->FileName); + } + else + { + if (this->FilePrefix) + { + sprintf(this->InternalFileName, this->FilePattern, + this->FilePrefix, this->FileNumber); + } + else + { + sprintf(this->InternalFileName, this->FilePattern,this->FileNumber); + } + } + this->GetInput()->Update(); + this->WriteSlice(this->GetInput()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); + this->DeleteFiles(); + return; + } + this->UpdateProgress((this->FileNumber - wExtent[4])/ + (wExtent[5] - wExtent[4] + 1.0)); + } + delete [] this->InternalFileName; + this->InternalFileName = NULL; +} + +// these three routines are for wqriting into memory +extern "C" +{ + void vtkJPEGWriteToMemoryInit(j_compress_ptr cinfo) + { + vtkJPEGWriter *self = vtkJPEGWriter::SafeDownCast( + static_cast(cinfo->client_data)); + if (self) + { + vtkUnsignedCharArray *uc = self->GetResult(); + if (!uc || uc->GetReferenceCount() > 1) + { + uc = vtkUnsignedCharArray::New(); + self->SetResult(uc); + uc->Delete(); + // start out with 10K as a guess for the image size + uc->Allocate(10000); + } + cinfo->dest->next_output_byte = uc->GetPointer(0); + cinfo->dest->free_in_buffer = uc->GetSize(); + } + } +} + +extern "C" +{ + boolean vtkJPEGWriteToMemoryEmpty(j_compress_ptr cinfo) + { + vtkJPEGWriter *self = vtkJPEGWriter::SafeDownCast( + static_cast(cinfo->client_data)); + if (self) + { + vtkUnsignedCharArray *uc = self->GetResult(); + // we must grow the array, we grow by 50% each time + int oldSize = uc->GetSize(); + uc->Resize(oldSize + oldSize/2); + cinfo->dest->next_output_byte = uc->GetPointer(oldSize); + cinfo->dest->free_in_buffer = oldSize/2; + } + return TRUE; + } +} + +extern "C" +{ + void vtkJPEGWriteToMemoryTerm(j_compress_ptr cinfo) + { + vtkJPEGWriter *self = vtkJPEGWriter::SafeDownCast( + static_cast(cinfo->client_data)); + if (self) + { + vtkUnsignedCharArray *uc = self->GetResult(); + // we must close the array + vtkIdType oldSize = uc->GetSize(); + uc->SetNumberOfTuples(oldSize - static_cast(cinfo->dest->free_in_buffer)); + } + } +} + +struct VTK_JPEG_ERROR_MANAGER +{ + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +typedef struct VTK_JPEG_ERROR_MANAGER* VTK_JPEG_ERROR_PTR; + +extern "C" +{ + /* The JPEG library does not expect the error function to return. + Therefore we must use this ugly longjmp call. */ + void + VTK_JPEG_ERROR_EXIT (j_common_ptr cinfo) +{ + VTK_JPEG_ERROR_PTR jpegErr = reinterpret_cast(cinfo->err); + longjmp(jpegErr->setjmp_buffer, 1); +} +} + + +// we disable this warning because even though this is a C++ file, between +// the setjmp and resulting longjmp there should not be any C++ constructors +// or destructors. +#if defined(_MSC_VER) && !defined(VTK_DISPLAY_WIN32_WARNINGS) +#pragma warning ( disable : 4611 ) +#endif +void vtkJPEGWriter::WriteSlice(vtkImageData *data) +{ + // Call the correct templated function for the output + unsigned int ui; + + // Call the correct templated function for the input + if (data->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkWarningMacro("JPEGWriter only supports unsigned char input"); + return; + } + + if (data->GetNumberOfScalarComponents() > MAX_COMPONENTS) + { + vtkErrorMacro("Exceed JPEG limits for number of components (" << data->GetNumberOfScalarComponents() << " > " << MAX_COMPONENTS << ")" ); + return; + } + + // overriding jpeg_error_mgr so we don't exit when an error happens + + // Create the jpeg compression object and error handler + struct jpeg_compress_struct cinfo; + struct VTK_JPEG_ERROR_MANAGER jerr; + this->TempFP = 0; + if (!this->WriteToMemory) + { + this->TempFP = fopen(this->InternalFileName, "wb"); + if (!this->TempFP) + { + vtkErrorMacro("Unable to open file " << this->InternalFileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + return; + } + } + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = VTK_JPEG_ERROR_EXIT; + if (setjmp(jerr.setjmp_buffer)) + { + jpeg_destroy_compress(&cinfo); + if (!this->WriteToMemory) + { + fclose(this->TempFP); + } + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + jpeg_create_compress(&cinfo); + + // set the destination file + struct jpeg_destination_mgr compressionDestination; + if (this->WriteToMemory) + { + // setup the compress structure to write to memory + compressionDestination.init_destination = vtkJPEGWriteToMemoryInit; + compressionDestination.empty_output_buffer = vtkJPEGWriteToMemoryEmpty; + compressionDestination.term_destination = vtkJPEGWriteToMemoryTerm; + cinfo.dest = &compressionDestination; + cinfo.client_data = static_cast(this); + } + else + { + jpeg_stdio_dest(&cinfo, this->TempFP); + } + + // set the information about image + int *uExtent = data->GetUpdateExtent(); + unsigned int width, height; + width = uExtent[1] - uExtent[0] + 1; + height = uExtent[3] - uExtent[2] + 1; + + cinfo.image_width = width; /* image width and height, in pixels */ + cinfo.image_height = height; + + cinfo.input_components = data->GetNumberOfScalarComponents(); + switch (cinfo.input_components) + { + case 1: cinfo.in_color_space = JCS_GRAYSCALE; + break; + case 3: cinfo.in_color_space = JCS_RGB; + break; + default: cinfo.in_color_space = JCS_UNKNOWN; + break; + } + + // set the compression parameters + jpeg_set_defaults(&cinfo); // start with reasonable defaults + jpeg_set_quality(&cinfo, this->Quality, TRUE); + if (this->Progressive) + { + jpeg_simple_progression(&cinfo); + } + + // start compression + jpeg_start_compress(&cinfo, TRUE); + + // write the data. in jpeg, the first row is the top row of the image + void *outPtr; + outPtr = data->GetScalarPointer(uExtent[0], uExtent[2], uExtent[4]); + JSAMPROW *row_pointers = new JSAMPROW [height]; + vtkIdType *outInc = data->GetIncrements(); + vtkIdType rowInc = outInc[1]; + for (ui = 0; ui < height; ui++) + { + row_pointers[height - ui - 1] = (JSAMPROW) outPtr; + outPtr = (unsigned char *)outPtr + rowInc; + } + jpeg_write_scanlines(&cinfo, row_pointers, height); + + if (!this->WriteToMemory) + { + if (fflush(this->TempFP) == EOF) + { + this->ErrorCode = vtkErrorCode::OutOfDiskSpaceError; + fclose(this->TempFP); + return; + } + } + + // finish the compression + jpeg_finish_compress(&cinfo); + + // clean up and close the file + delete [] row_pointers; + jpeg_destroy_compress(&cinfo); + + if (!this->WriteToMemory) + { + fclose(this->TempFP); + } +} + +void vtkJPEGWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Quality: " << this->Quality << "\n"; + os << indent << "Progressive: " << (this->Progressive ? "On" : "Off") << "\n"; + os << indent << "Result: " << this->Result << "\n"; + os << indent << "WriteToMemory: " << (this->WriteToMemory ? "On" : "Off") << "\n"; +} diff --git a/IO/vtkJPEGWriter.h b/IO/vtkJPEGWriter.h new file mode 100644 index 0000000..fe22a8a --- /dev/null +++ b/IO/vtkJPEGWriter.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJPEGWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkJPEGWriter - Writes JPEG files. +// .SECTION Description +// vtkJPEGWriter writes JPEG files. It supports 1 and 3 component data of +// unsigned char. It relies on the IJG's libjpeg. Thanks to IJG for +// supplying a public jpeg IO library. + +// .SECTION See Also +// vtkJPEGReader + +#ifndef __vtkJPEGWriter_h +#define __vtkJPEGWriter_h + +#include "vtkImageWriter.h" + +class vtkUnsignedCharArray; +class vtkImageData; + +class VTK_IO_EXPORT vtkJPEGWriter : public vtkImageWriter +{ +public: + static vtkJPEGWriter *New(); + vtkTypeRevisionMacro(vtkJPEGWriter,vtkImageWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The main interface which triggers the writer to start. + virtual void Write(); + + // Description: + // Compression quality. 0 = Low quality, 100 = High quality + vtkSetClampMacro(Quality, int, 0, 100); + vtkGetMacro(Quality, int); + + // Description: + // Progressive JPEG generation. + vtkSetMacro(Progressive, unsigned int); + vtkGetMacro(Progressive, unsigned int); + vtkBooleanMacro(Progressive, unsigned int); + + // Description: + // Write the image to memory (a vtkUnsignedCharArray) + vtkSetMacro(WriteToMemory, unsigned int); + vtkGetMacro(WriteToMemory, unsigned int); + vtkBooleanMacro(WriteToMemory, unsigned int); + + // Description: + // When writing to memory this is the result, it will be NULL until the + // data is written the first time + virtual void SetResult(vtkUnsignedCharArray*); + vtkGetObjectMacro(Result, vtkUnsignedCharArray); + +protected: + vtkJPEGWriter(); + ~vtkJPEGWriter(); + + void WriteSlice(vtkImageData *data); + +private: + int Quality; + unsigned int Progressive; + unsigned int WriteToMemory; + vtkUnsignedCharArray *Result; + FILE *TempFP; + +private: + vtkJPEGWriter(const vtkJPEGWriter&); // Not implemented. + void operator=(const vtkJPEGWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkJavaPanel.cxx b/IO/vtkJavaPanel.cxx new file mode 100644 index 0000000..004c05f --- /dev/null +++ b/IO/vtkJavaPanel.cxx @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkJavaPanel.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkSystemIncludes.h" +#include +#include "vtkJavaUtil.h" + + +// #define VTKJAVADEBUG + +// super hack 9000 +// include the header file as a C code fragment +// include the JAVA C stubs file as a C code fragment +extern "C" { +#include "java/vtk_vtkPanel.h" +#include "java/vtk_vtkPanel.c" + +typedef struct Classsun_awt_motif_MCanvasPeer { + struct Hjava_awt_Component *target; + long pData; +} Classsun_awt_motif_MCanvasPeer; +HandleTo(sun_awt_motif_MCanvasPeer); + +struct ComponentData { + Widget widget; + int repaintPending; + int x1, y1, x2, y2; +}; + +struct CanvasData { + struct ComponentData comp; + Widget shell; + int flags; +}; + +#define PEER_PDATA(T, T2, x) ((struct T *)(unhand((struct T2 *)unhand(x)->peer)->pData)) +} + +#include "vtkRenderWindow.h" + +void vtk_vtkPanel_setWindow(struct Hvtk_vtkPanel *me, + struct Hvtk_vtkRenderWindow *id0) +{ + void *temp; + vtkRenderWindow *op; + + op = (vtkRenderWindow *)vtkJavaGetPointerFromObject(id0,"vtkRenderWindow"); + + struct CanvasData *wdata = + PEER_PDATA(CanvasData, Hsun_awt_motif_MCanvasPeer, me); + Widget wig = wdata->comp.widget; + + // cerr << XtDisplay(wig) << " Display\n"; + // cerr << XtWindowOfObject(wig) << " Window\n"; + + op->SetDisplayId((void *)XtDisplay(wig)); + op->SetWindowId((void *)XtWindowOfObject(wig)); +} + diff --git a/IO/vtkMCubesReader.cxx b/IO/vtkMCubesReader.cxx new file mode 100644 index 0000000..edba42c --- /dev/null +++ b/IO/vtkMCubesReader.cxx @@ -0,0 +1,429 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMCubesReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMCubesReader.h" + +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +#include +#include + +vtkCxxRevisionMacro(vtkMCubesReader, "$Revision: 1.65 $"); +vtkStandardNewMacro(vtkMCubesReader); + +// Construct object with FlipNormals turned off and Normals set to true. +vtkMCubesReader::vtkMCubesReader() +{ + this->FileName = NULL; + this->LimitsFileName = NULL; + + this->Locator = NULL; + +#ifndef VTK_WORDS_BIGENDIAN + this->SwapBytes = 1; +#else + this->SwapBytes = 0; +#endif + this->HeaderSize = 0; + this->FlipNormals = 0; + this->Normals = 1; + + this->SetNumberOfInputPorts(0); +} + +vtkMCubesReader::~vtkMCubesReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } + if (this->LimitsFileName) + { + delete [] this->LimitsFileName; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +int vtkMCubesReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + FILE *fp; + FILE *limitp; + vtkPoints *newPts; + vtkCellArray *newPolys; + vtkFloatArray *newNormals = NULL; + double bounds[6]; + int i, j, k, numPts, numTris; + typedef struct {float x[3], n[3];} pointType; + pointType point; + struct stat buf; + int numDegenerate=0; + vtkIdType nodes[3]; + float direction, n[3], dummy[2]; + int byteOrder = this->GetDataByteOrder(); + + vtkDebugMacro(<<"Reading marching cubes file"); + + // + // Initialize + // + + if ( this->FileName == NULL ) + { + vtkErrorMacro(<< "Please specify input FileName"); + return 0; + } + if ( (fp = fopen(this->FileName, "rb")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return 0; + } + + // Try to read limits file to get bounds. Otherwise, read data. + if ( this->LimitsFileName != NULL && + (limitp = fopen (this->LimitsFileName, "rb")) != NULL && + stat (this->FileName, &buf) == 0 ) + { + // skip first three pairs + float fbounds[6]; + fread (dummy, sizeof(float), 2, limitp); + fread (dummy, sizeof(float), 2, limitp); + fread (dummy, sizeof(float), 2, limitp); + + // next three pairs are x, y, z limits + for (i = 0; i < 6; i++) + { + fread (&fbounds[i], sizeof (float), 1, limitp); + } + // do swapping if necc + if (byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN) + { + vtkByteSwap::Swap4BERange(fbounds,6); + } + else + { + vtkByteSwap::Swap4LERange(fbounds,6); + } + fclose (limitp); + bounds[0] = fbounds[0]; + bounds[1] = fbounds[1]; + bounds[2] = fbounds[2]; + bounds[3] = fbounds[3]; + bounds[4] = fbounds[4]; + bounds[5] = fbounds[5]; + + // calculate the number of triangles and vertices from file size + numTris = buf.st_size / (18*sizeof(float)); //3 points + normals + numPts = numTris * 3; + } + else // read data to get bounds + { + fseek (fp, this->HeaderSize, 0); + // cannot use vtkMath uninitialze bounds for this computation + bounds[0] = bounds[2] = bounds[4] = VTK_FLOAT_MAX; + bounds[1] = bounds[3] = bounds[5] = -VTK_FLOAT_MAX; + for (i=0; fread(&point, sizeof(pointType), 1, fp); i++) + { + // swap bytes if necc + if (byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN) + { + vtkByteSwap::Swap4BERange((float *) (&point),6); + } + else + { + vtkByteSwap::Swap4LERange((float *) (&point),6); + } + for (j=0; j<3; j++) + { + bounds[2*j] = (bounds[2*j] < point.x[j] ? bounds[2*j] : point.x[j]); + bounds[2*j+1] = (bounds[2*j+1] > point.x[j] ? bounds[2*j+1] : point.x[j]); + } + + if ( i && ((i % 10000) == 0) ) + { + vtkDebugMacro(<<"Triangle vertices #" << i); + } + } + numTris = i / 3; + numPts = i; + } +// +// Now re-read and merge +// + rewind (fp); + fseek (fp, this->HeaderSize, 0); + + newPts = vtkPoints::New(); + newPts->Allocate(numPts/3,numPts/3); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numTris,3)); + + if ( this->Normals ) + { + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(numPts,numPts); + } + + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (newPts, bounds); + + direction = this->FlipNormals ? -1.0 : 1.0; + + double dp[3]; + for ( i=0; i( + fread (&point, static_cast(sizeof(pointType)), 1, fp)); + if (val != 1) + { + vtkErrorMacro(<<"Error reading triange " << i + << " (" << numTris << "), point/normal " << j); + } + + // swap bytes if necc + if (byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN) + { + vtkByteSwap::Swap4BERange((float *) (&point),6); + } + else + { + vtkByteSwap::Swap4LERange((float *) (&point),6); + } + dp[0] = point.x[0]; + dp[1] = point.x[1]; + dp[2] = point.x[2]; + if ( this->Locator->InsertUniquePoint(dp, nodes[j]) ) + { + if ( this->Normals ) + { + for (k=0; k<3; k++) + { + n[k] = point.n[k] * direction; + } + newNormals->InsertTuple(nodes[j],n); + } + } + } + if ( nodes[0] != nodes[1] && + nodes[0] != nodes[2] && + nodes[1] != nodes[2] ) + { + newPolys->InsertNextCell(3,nodes); + } + else + { + numDegenerate++; + } + } + vtkDebugMacro(<< "Read: " + << newPts->GetNumberOfPoints() << " points, " + << newPolys->GetNumberOfCells() << " triangles\n" + << "(Removed " << numDegenerate << " degenerate triangles)"); + + fclose(fp); +// +// Update ourselves +// + output->SetPoints(newPts); + newPts->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + if (this->Normals) + { + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + } + output->Squeeze(); // might have merged stuff + + if (this->Locator) + { + this->Locator->Initialize(); //free storage + } + + return 1; +} + +// Specify a spatial locator for merging points. By default, +// an instance of vtkMergePoints is used. +void vtkMCubesReader::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkMCubesReader::SetDataByteOrderToBigEndian() +{ +#ifndef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +void vtkMCubesReader::SetDataByteOrderToLittleEndian() +{ +#ifdef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +void vtkMCubesReader::SetDataByteOrder(int byteOrder) +{ + if ( byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN ) + { + this->SetDataByteOrderToBigEndian(); + } + else + { + this->SetDataByteOrderToLittleEndian(); + } +} + +int vtkMCubesReader::GetDataByteOrder() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } +#else + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } +#endif +} + +const char *vtkMCubesReader::GetDataByteOrderAsString() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +#else + if ( this->SwapBytes ) + { + return "BigEndian"; + } + else + { + return "LittleEndian"; + } +#endif +} + +void vtkMCubesReader::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +void vtkMCubesReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "Limits File Name: " + << (this->LimitsFileName ? this->LimitsFileName : "(none)") << "\n"; + os << indent << "Normals: " << (this->Normals ? "On\n" : "Off\n"); + os << indent << "FlipNormals: " << (this->FlipNormals ? "On\n" : "Off\n"); + os << indent << "HeaderSize: " << this->HeaderSize << "\n"; + os << indent << "Swap Bytes: " << (this->SwapBytes ? "On\n" : "Off\n"); + + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} + +unsigned long int vtkMCubesReader::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Locator != NULL ) + { + time = this->Locator->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} + + + diff --git a/IO/vtkMCubesReader.h b/IO/vtkMCubesReader.h new file mode 100644 index 0000000..36933ab --- /dev/null +++ b/IO/vtkMCubesReader.h @@ -0,0 +1,154 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMCubesReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMCubesReader - read binary marching cubes file +// .SECTION Description +// vtkMCubesReader is a source object that reads binary marching cubes +// files. (Marching cubes is an isosurfacing technique that generates +// many triangles.) The binary format is supported by W. Lorensen's +// marching cubes program (and the vtkSliceCubes object). The format +// repeats point coordinates, so this object will merge the points +// with a vtkLocator object. You can choose to supply the vtkLocator +// or use the default. + +// .SECTION Caveats +// Binary files assumed written in sun/hp/sgi (i.e., Big Endian) form. +// +// Because points are merged when read, degenerate triangles may be removed. +// Thus the number of triangles read may be fewer than the number of triangles +// actually created. +// +// The point merging does not take into account that the same point may have +// different normals. For example, running vtkPolyDataNormals after +// vtkContourFilter may split triangles because of the FeatureAngle +// ivar. Subsequent reading with vtkMCubesReader will merge the points and +// use the first point's normal. For the most part, this is undesirable. +// +// Normals are generated from the gradient of the data scalar values. Hence +// the normals may on occasion point in a direction inconsistent with the +// ordering of the triangle vertices. If this happens, the resulting surface +// may be "black". Reverse the sense of the FlipNormals boolean flag to +// correct this. + +// .SECTION See Also +// vtkContourFilter vtkMarchingCubes vtkSliceCubes vtkLocator + +#ifndef __vtkMCubesReader_h +#define __vtkMCubesReader_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_FILE_BYTE_ORDER_BIG_ENDIAN 0 +#define VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN 1 + +class vtkPointLocator; + +class VTK_IO_EXPORT vtkMCubesReader : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkMCubesReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with FlipNormals turned off and Normals set to true. + static vtkMCubesReader *New(); + + // Description: + // Specify file name of marching cubes file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Set / get the file name of the marching cubes limits file. + vtkSetStringMacro(LimitsFileName); + vtkGetStringMacro(LimitsFileName); + + // Description: + // Specify a header size if one exists. The header is skipped and not used at this time. + vtkSetClampMacro(HeaderSize,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(HeaderSize,int); + + // Description: + // Specify whether to flip normals in opposite direction. Flipping ONLY + // changes the direction of the normal vector. Contrast this with flipping + // in vtkPolyDataNormals which flips both the normal and the cell point + // order. + vtkSetMacro(FlipNormals,int); + vtkGetMacro(FlipNormals,int); + vtkBooleanMacro(FlipNormals,int); + + // Description: + // Specify whether to read normals. + vtkSetMacro(Normals,int); + vtkGetMacro(Normals,int); + vtkBooleanMacro(Normals,int); + + // Description: + // These methods should be used instead of the SwapBytes methods. + // They indicate the byte ordering of the file you are trying + // to read in. These methods will then either swap or not swap + // the bytes depending on the byte ordering of the machine it is + // being run on. For example, reading in a BigEndian file on a + // BigEndian machine will result in no swapping. Trying to read + // the same file on a LittleEndian machine will result in swapping. + // As a quick note most UNIX machines are BigEndian while PC's + // and VAX tend to be LittleEndian. So if the file you are reading + // in was generated on a VAX or PC, SetDataByteOrderToLittleEndian otherwise + // SetDataByteOrderToBigEndian. + void SetDataByteOrderToBigEndian(); + void SetDataByteOrderToLittleEndian(); + int GetDataByteOrder(); + void SetDataByteOrder(int); + const char *GetDataByteOrderAsString(); + + // Description: + // Turn on/off byte swapping. + vtkSetMacro(SwapBytes,int); + vtkGetMacro(SwapBytes,int); + vtkBooleanMacro(SwapBytes,int); + + // Description: + // Set / get a spatial locator for merging points. By default, + // an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + + // Description: + // Return the mtime also considering the locator. + unsigned long GetMTime(); + +protected: + vtkMCubesReader(); + ~vtkMCubesReader(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char *FileName; + char *LimitsFileName; + vtkPointLocator *Locator; + int SwapBytes; + int HeaderSize; + int FlipNormals; + int Normals; + +private: + vtkMCubesReader(const vtkMCubesReader&); // Not implemented. + void operator=(const vtkMCubesReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkMCubesWriter.cxx b/IO/vtkMCubesWriter.cxx new file mode 100644 index 0000000..882fcab --- /dev/null +++ b/IO/vtkMCubesWriter.cxx @@ -0,0 +1,144 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMCubesWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMCubesWriter.h" + +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkMCubesWriter, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkMCubesWriter); + +// Create object. +vtkMCubesWriter::vtkMCubesWriter() +{ + this->LimitsFileName = NULL; +} + +vtkMCubesWriter::~vtkMCubesWriter() +{ + if ( this->LimitsFileName ) + { + delete [] this->LimitsFileName; + } +} +static void WriteMCubes(FILE *fp, vtkPoints *pts, vtkDataArray *normals, + vtkCellArray *polys); +static void WriteLimits(FILE *fp, double *bounds); + +// Write out data in MOVIE.BYU format. +void vtkMCubesWriter::WriteData() +{ + vtkPoints *pts; + vtkDataArray *normals; + vtkCellArray *polys; + vtkPolyData *input=this->GetInput(); + + polys = input->GetPolys(); + pts = input->GetPoints(); + if (pts == NULL || polys == NULL ) + { + vtkErrorMacro(<<"No data to write!"); + return; + } + + normals = input->GetPointData()->GetNormals(); + if (normals == NULL ) + { + vtkErrorMacro(<<"No normals to write!: use vtkPolyDataNormals to generate them"); + return; + } + + if ( this->FileName == NULL) + { + vtkErrorMacro(<< "Please specify FileName to write"); + return; + } + + vtkDebugMacro("Writing MCubes tri file"); + FILE *fp; + if ((fp = fopen(this->FileName, "w")) == NULL) + { + vtkErrorMacro(<< "Couldn't open file: " << this->FileName); + return; + } + WriteMCubes (fp, pts, normals, polys); + fclose (fp); + + if (this->LimitsFileName) + { + vtkDebugMacro("Writing MCubes limits file"); + if ((fp = fopen(this->LimitsFileName, "w")) == NULL) + { + vtkErrorMacro(<< "Couldn't open file: " << this->LimitsFileName); + return; + } + WriteLimits (fp, input->GetBounds ()); + fclose (fp); + } +} + +void WriteMCubes(FILE *fp, vtkPoints *pts, vtkDataArray *normals, + vtkCellArray *polys) +{ + typedef struct {float x[3], n[3];} pointType; + pointType point; + int i; + vtkIdType npts; + vtkIdType *indx = 0; + + // Write out triangle polygons. In not a triangle polygon, create + // triangles. + // + double p[3], n[3]; + for (polys->InitTraversal(); polys->GetNextCell(npts,indx); ) + { + for (i=0; i < 3; i++) + { + pts->GetPoint(indx[i],p); + normals->GetTuple(indx[i],n); + point.x[0] = (float)p[0]; + point.x[1] = (float)p[1]; + point.x[2] = (float)p[2]; + point.n[0] = (float)n[0]; + point.n[1] = (float)n[1]; + point.n[2] = (float)n[2]; + vtkByteSwap::SwapWrite4BERange((float *) (&point),6,fp); + } + } +} +void WriteLimits(FILE *fp, double *bounds) +{ + float fbounds[6]; + fbounds[0] = (float)bounds[0]; + fbounds[1] = (float)bounds[1]; + fbounds[2] = (float)bounds[2]; + fbounds[3] = (float)bounds[3]; + fbounds[4] = (float)bounds[4]; + fbounds[5] = (float)bounds[5]; + vtkByteSwap::SwapWrite4BERange((float *) fbounds,6,fp); + vtkByteSwap::SwapWrite4BERange((float *) fbounds,6,fp); +} + +void vtkMCubesWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Limits File Name: " + << (this->LimitsFileName ? this->LimitsFileName : "(none)") << "\n"; +} + diff --git a/IO/vtkMCubesWriter.h b/IO/vtkMCubesWriter.h new file mode 100644 index 0000000..7107e19 --- /dev/null +++ b/IO/vtkMCubesWriter.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMCubesWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMCubesWriter - write binary marching cubes file +// .SECTION Description +// vtkMCubesWriter is a polydata writer that writes binary marching cubes +// files. (Marching cubes is an isosurfacing technique that generates many +// triangles.) The binary format is supported by W. Lorensen's marching cubes +// program (and the vtkSliceCubes object). Each triangle is represented by +// three records, with each record consisting of six single precision +// floating point numbers representing the a triangle vertex coordinate and +// vertex normal. + +// .SECTION Caveats +// Binary files are written in sun/hp/sgi (i.e., Big Endian) form. + +// .SECTION See Also +// vtkMarchingCubes vtkSliceCubes vtkMCubesReader + +#ifndef __vtkMCubesWriter_h +#define __vtkMCubesWriter_h + +#include "vtkPolyDataWriter.h" + +class VTK_IO_EXPORT vtkMCubesWriter : public vtkPolyDataWriter +{ +public: + static vtkMCubesWriter *New(); + vtkTypeRevisionMacro(vtkMCubesWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/get file name of marching cubes limits file. + vtkSetStringMacro(LimitsFileName); + vtkGetStringMacro(LimitsFileName); + +protected: + vtkMCubesWriter(); + ~vtkMCubesWriter(); + + void WriteData(); + char *LimitsFileName; +private: + vtkMCubesWriter(const vtkMCubesWriter&); // Not implemented. + void operator=(const vtkMCubesWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkMPEG2Writer.cxx b/IO/vtkMPEG2Writer.cxx new file mode 100644 index 0000000..f332b10 --- /dev/null +++ b/IO/vtkMPEG2Writer.cxx @@ -0,0 +1,894 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPEG2Writer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMPEG2Writer.h" + +#include "vtkDirectory.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkSmartPointer.h" + +#include +#include + +#include "mpeg2enc_config.h" +#include "mpeg2enc_global.h" + +/* private prototypes */ + +//--------------------------------------------------------------------------- +class vtkMPEG2WriterInternal +{ +public: + vtkMPEG2WriterInternal(); + ~vtkMPEG2WriterInternal(); + + typedef vtkstd::map > StringToImageMap; + + int StoreImage(const char* name, vtkImageData* id); + unsigned char* GetImagePtr(const char* name); + int RemoveImage(const char* name); + + int Dim[2]; + + void ReadParmFile( ); + void Init(); + void ReadQuantMat(); + + MPEG2_structure* GetMPEG2Structure() { return this->Structure; } + +private: + StringToImageMap ImagesMap; + MPEG2_structure* Structure; +}; + +//--------------------------------------------------------------------------- +extern "C" +{ + void vtkMPEG2WriterReportError( const char *text ) + { + vtkGenericWarningMacro(<< text); + } + + unsigned char* vtkMPEG2WriterInternalGetImagePtr(const char* fname, + void *mpeg2_writer_internal) + { + return (static_cast(mpeg2_writer_internal))->GetImagePtr(fname); + } +} + +//--------------------------------------------------------------------------- +vtkMPEG2WriterInternal::vtkMPEG2WriterInternal() +{ + this->Dim[0] = 0; + this->Dim[1] = 0; + + this->Structure = new MPEG2_structure; +} + +//--------------------------------------------------------------------------- +vtkMPEG2WriterInternal::~vtkMPEG2WriterInternal() +{ + delete this->Structure; + this->Structure = 0; +} + +//--------------------------------------------------------------------------- +int vtkMPEG2WriterInternal::StoreImage(const char* name, vtkImageData* iid) +{ + if ( !name ) + { + return 0; + } + + // We need to flip the image vertically + + vtkImageData* id = vtkImageData::New(); + id->CopyStructure(iid); + id->SetNumberOfScalarComponents(iid->GetNumberOfScalarComponents()); + + int dims[3]; + id->GetDimensions(dims); + + int row_length = dims[0] * id->GetNumberOfScalarComponents(); + + const unsigned char *src_ptr = + (const unsigned char *)iid->GetScalarPointer(); + src_ptr += iid->GetNumberOfPoints() * iid->GetNumberOfScalarComponents() + - row_length; + + unsigned char *dest_ptr = (unsigned char *)id->GetScalarPointer(); + + // We assume there is only one slice + + for (int j = 0; j < dims[1]; j++) + { + memcpy(dest_ptr, src_ptr, row_length); + dest_ptr += row_length; + src_ptr -= row_length; + } + + this->ImagesMap[name] = id; + id->Delete(); + + return 1; +} + +//--------------------------------------------------------------------------- +unsigned char* vtkMPEG2WriterInternal::GetImagePtr(const char* fname) +{ + if ( !fname ) + { + return 0; + } + vtkMPEG2WriterInternal::StringToImageMap::iterator it + = this->ImagesMap.find(fname); + if ( it == this->ImagesMap.end() ) + { + return 0; + } + vtkImageData* id = it->second.GetPointer(); + return static_cast(id->GetScalarPointer()); +} + +//--------------------------------------------------------------------------- +int vtkMPEG2WriterInternal::RemoveImage(const char* fname) +{ + if ( !fname ) + { + return 0; + } + vtkMPEG2WriterInternal::StringToImageMap::iterator it + = this->ImagesMap.find(fname); + if ( it == this->ImagesMap.end() ) + { + return 0; + } + this->ImagesMap.erase(it); + return 0; +} +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +vtkStandardNewMacro(vtkMPEG2Writer); +vtkCxxRevisionMacro(vtkMPEG2Writer, "$Revision: 1.3.4.1 $"); + +//--------------------------------------------------------------------------- +vtkMPEG2Writer::vtkMPEG2Writer() +{ + this->Internals = 0; + this->Time = 0; + this->ActualWrittenTime = 0; +} + +//--------------------------------------------------------------------------- +vtkMPEG2Writer::~vtkMPEG2Writer() +{ + delete this->Internals; +} + +//--------------------------------------------------------------------------- +void vtkMPEG2Writer::Start() +{ + // Error checking + this->Error = 1; + + if ( this->Internals ) + { + vtkErrorMacro("Movie already started"); + return; + } + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<<"Write:Please specify an input!"); + return; + } + if (!this->FileName) + { + vtkErrorMacro(<<"Write:Please specify a FileName"); + return; + } + + this->Internals = new vtkMPEG2WriterInternal; + + this->Error = 0; + this->Time = 0; + this->ActualWrittenTime = 0; + + this->Initialized = 0; +} + +//--------------------------------------------------------------------------- +void vtkMPEG2Writer::Write() +{ + if ( !this->Internals ) + { + vtkErrorMacro("Movie not started"); + this->Error = 1; + return; + } + + // get the data + this->GetInput()->UpdateInformation(); + int *wExtent = this->GetInput()->GetWholeExtent(); + this->GetInput()->SetUpdateExtent(wExtent); + this->GetInput()->Update(); + + int dim[4]; + this->GetInput()->GetDimensions(dim); + if ( this->Internals->Dim[0] == 0 && this->Internals->Dim[1] == 0 ) + { + this->Internals->Dim[0] = dim[0]; + this->Internals->Dim[1] = dim[1]; + } + + if ( this->Internals->Dim[0] != dim[0] || this->Internals->Dim[1] != dim[1] ) + { + vtkErrorMacro("Image not of the same size"); + return; + } + + if ( !this->Initialized ) + { + this->Initialize(); + } + + + MPEG2_structure* str = this->Internals->GetMPEG2Structure(); + char buffer[1024]; + sprintf(buffer, str->tplorg, this->Time + str->frame0); + this->Internals->StoreImage(buffer, this->GetInput()); + + int last = MPEG2_putseq_one(this->ActualWrittenTime, this->Time,str); + if ( last >= 0 ) + { + sprintf(buffer, str->tplorg, last + str->frame0); + this->Internals->RemoveImage(buffer); + this->ActualWrittenTime ++; + } + this->Time++; +} + +//--------------------------------------------------------------------------- +void vtkMPEG2Writer::Initialize() +{ + MPEG2_structure* str = this->Internals->GetMPEG2Structure(); + str->quiet = 1; + + str->report_error = vtkMPEG2WriterReportError; + str->get_image_ptr = vtkMPEG2WriterInternalGetImagePtr; + str->mpeg2_writer_internal = this->Internals; + + /* read parameter file */ + this->Internals->ReadParmFile(); + + + /* read quantization matrices */ + this->Internals->ReadQuantMat(); + + /* open output file */ + if (!(str->outfile=fopen(this->FileName,"wb"))) + { + sprintf(str->errortext,"Couldn't create output file %s",this->FileName); + (*(str->report_error))(str->errortext); + } + + this->Internals->Init(); + + MPEG2_rc_init_seq(str); /* initialize rate control */ + + /* sequence header, sequence extension and sequence display extension */ + MPEG2_putseqhdr(str); + if (!str->mpeg1) + { + MPEG2_putseqext(str); + MPEG2_putseqdispext(str); + } + + /* optionally output some text data (description, copyright or whatever) */ + if (strlen(str->id_string) > 1) + MPEG2_putuserdata(str->id_string,str); + + + this->Initialized = 1; +} + +//--------------------------------------------------------------------------- +void vtkMPEG2Writer::End() +{ + MPEG2_structure* str = this->Internals->GetMPEG2Structure(); + int last; + while ( (last = MPEG2_putseq_one(this->ActualWrittenTime, this->Time-1,str)) >= 0 ) + { + char buffer[1024]; + sprintf(buffer, str->tplorg, last + str->frame0); + this->Internals->RemoveImage(buffer); + this->ActualWrittenTime ++; + } + + MPEG2_putseqend(str); + + fclose(str->outfile); + if ( str->statfile ) + { + fclose(str->statfile); + } + + delete this->Internals; + this->Internals = 0; +} + +//--------------------------------------------------------------------------- +void vtkMPEG2Writer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +void vtkMPEG2WriterInternal::Init() +{ + int i, size; + static int block_count_tab[3] = {6,8,12}; + + MPEG2_initbits(); + MPEG2_init_fdct(); + MPEG2_init_idct(); + + /* round picture dimensions to nearest multiple of 16 or 32 */ + this->Structure->mb_width = (this->Structure->horizontal_size+15)/16; + this->Structure->mb_height = this->Structure->prog_seq ? (this->Structure->vertical_size+15)/16 : 2*((this->Structure->vertical_size+31)/32); + this->Structure->mb_height2 = this->Structure->fieldpic ? this->Structure->mb_height>>1 : this->Structure->mb_height; /* for field pictures */ + this->Structure->width = 16*this->Structure->mb_width; + this->Structure->height = 16*this->Structure->mb_height; + + this->Structure->chrom_width = (this->Structure->chroma_format==CHROMA444) ? this->Structure->width : this->Structure->width>>1; + this->Structure->chrom_height = (this->Structure->chroma_format!=CHROMA420) ? this->Structure->height : this->Structure->height>>1; + + this->Structure->height2 = this->Structure->fieldpic ? this->Structure->height>>1 : this->Structure->height; + this->Structure->width2 = this->Structure->fieldpic ? this->Structure->width<<1 : this->Structure->width; + this->Structure->chrom_width2 = this->Structure->fieldpic ? this->Structure->chrom_width<<1 : this->Structure->chrom_width; + + this->Structure->block_count = block_count_tab[this->Structure->chroma_format-1]; + + /* clip table */ + if (!(this->Structure->clp = (unsigned char *)malloc(1024))) + { + (*(this->Structure->report_error))("malloc failed\n"); + } + this->Structure->clp+= 384; + + for (i=-384; i<640; i++) + { + this->Structure->clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i); + } + + for (i=0; i<3; i++) + { + size = (i==0) ? this->Structure->width*this->Structure->height : + this->Structure->chrom_width*this->Structure->chrom_height; + + if (!(this->Structure->newrefframe[i] = (unsigned char *)malloc(size))) + (*(this->Structure->report_error))("malloc failed\n"); + if (!(this->Structure->oldrefframe[i] = (unsigned char *)malloc(size))) + (*(this->Structure->report_error))("malloc failed\n"); + if (!(this->Structure->auxframe[i] = (unsigned char *)malloc(size))) + (*(this->Structure->report_error))("malloc failed\n"); + if (!(this->Structure->neworgframe[i] = (unsigned char *)malloc(size))) + (*(this->Structure->report_error))("malloc failed\n"); + if (!(this->Structure->oldorgframe[i] = (unsigned char *)malloc(size))) + (*(this->Structure->report_error))("malloc failed\n"); + if (!(this->Structure->auxorgframe[i] = (unsigned char *)malloc(size))) + (*(this->Structure->report_error))("malloc failed\n"); + if (!(this->Structure->predframe[i] = (unsigned char *)malloc(size))) + (*(this->Structure->report_error))("malloc failed\n"); + } + + this->Structure->mbinfo = (struct mbinfo *)malloc(this->Structure->mb_width*this->Structure->mb_height2*sizeof(struct mbinfo)); + + if (!this->Structure->mbinfo) + (*(this->Structure->report_error))("malloc failed\n"); + + this->Structure->blocks = + (short (*)[64])malloc(this->Structure->mb_width*this->Structure->mb_height2*this->Structure->block_count*sizeof(short [64])); + + if (!this->Structure->blocks) + (*(this->Structure->report_error))("malloc failed\n"); + + /* open statistics output file */ + if (this->Structure->statname[0]=='-') + this->Structure->statfile = 0; + else if (!(this->Structure->statfile = fopen(this->Structure->statname,"w"))) + { + sprintf(this->Structure->errortext,"Couldn't create statistics output file %s",this->Structure->statname); + (*(this->Structure->report_error))(this->Structure->errortext); + } +} + +void vtkMPEG2WriterInternal::ReadParmFile( ) +{ + int i; + int h,m,s,f; + //FILE *fd; + //char line[256]; + static double ratetab[8]= + {24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0}; + + /* + if (!(fd = fopen(fname,"r"))) + { + sprintf(this->Structure->errortext,"Couldn't open parameter file %s",fname); + (*(this->Structure->report_error))(this->Structure->errortext); + } + + fgets(this->Structure->id_string,254,fd); + fgets(line,254,fd); sscanf(line,"%s",this->Structure->tplorg); + fgets(line,254,fd); sscanf(line,"%s",this->Structure->tplref); + fgets(line,254,fd); sscanf(line,"%s",this->Structure->iqname); + fgets(line,254,fd); sscanf(line,"%s",this->Structure->niqname); + fgets(line,254,fd); sscanf(line,"%s",this->Structure->statname); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->inputtype); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->nframes); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->frame0); + fgets(line,254,fd); sscanf(line,"%d:%d:%d:%d",&h,&m,&s,&f); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->N_val); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->M_val); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->mpeg1); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->fieldpic); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->horizontal_size); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->vertical_size); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->aspectratio); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->frame_rate_code); + fgets(line,254,fd); sscanf(line,"%lf",&this->Structure->bit_rate); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->vbv_buffer_size); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->low_delay); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->constrparms); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->profile); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->level); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->prog_seq); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->chroma_format); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->video_format); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->color_primaries); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->transfer_characteristics); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->matrix_coefficients); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->display_horizontal_size); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->display_vertical_size); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->dc_prec); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->topfirst); + fgets(line,254,fd); sscanf(line,"%d %d %d", + this->Structure->frame_pred_dct_tab,this->Structure->frame_pred_dct_tab+1,this->Structure->frame_pred_dct_tab+2); + + fgets(line,254,fd); sscanf(line,"%d %d %d", + this->Structure->conceal_tab,this->Structure->conceal_tab+1,this->Structure->conceal_tab+2); + + fgets(line,254,fd); sscanf(line,"%d %d %d", + this->Structure->qscale_tab,this->Structure->qscale_tab+1,this->Structure->qscale_tab+2); + + fgets(line,254,fd); sscanf(line,"%d %d %d", + this->Structure->intravlc_tab,this->Structure->intravlc_tab+1,this->Structure->intravlc_tab+2); + fgets(line,254,fd); sscanf(line,"%d %d %d", + this->Structure->altscan_tab,this->Structure->altscan_tab+1,this->Structure->altscan_tab+2); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->repeatfirst); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->prog_frame); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->P_val); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->reaction); + fgets(line,254,fd); sscanf(line,"%lf",&this->Structure->avg_act); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->Xi); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->Xp); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->Xb); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->d0i); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->d0p); + fgets(line,254,fd); sscanf(line,"%d",&this->Structure->d0b); + */ + + strcpy(this->Structure->tplorg, "%d"); + strcpy(this->Structure->tplref, "-"); + strcpy(this->Structure->iqname, "-"); + strcpy(this->Structure->niqname, "-"); + strcpy(this->Structure->statname, "-"); + this->Structure->inputtype = T_MEMPPM; + this->Structure->nframes = 1000000; + this->Structure->frame0 = 0; + this->Structure->N_val = 21; + this->Structure->M_val = 3; + this->Structure->mpeg1 = 0; + this->Structure->horizontal_size = this->Dim[0]; + this->Structure->vertical_size = this->Dim[1]; + this->Structure->aspectratio = 1; + this->Structure->frame_rate_code = 5; + this->Structure->bit_rate = 5000000.0; + this->Structure->vbv_buffer_size = 112; + this->Structure->low_delay = 0; + this->Structure->constrparms = 0; + this->Structure->profile = 4; + this->Structure->level = 4; + this->Structure->prog_seq = 1; + this->Structure->chroma_format = 1; + this->Structure->video_format = 0; + this->Structure->color_primaries = 5; + this->Structure->transfer_characteristics = 5; + this->Structure->matrix_coefficients = 4; + this->Structure->display_horizontal_size = this->Dim[0]; + this->Structure->display_vertical_size = this->Dim[1]; + this->Structure->dc_prec = 2; + this->Structure->topfirst = 1; + this->Structure->frame_pred_dct_tab[0] = this->Structure->frame_pred_dct_tab[1] = this->Structure->frame_pred_dct_tab[2] = 0; + this->Structure->conceal_tab[0] = this->Structure->conceal_tab[1] = this->Structure->conceal_tab[2] = 0; + this->Structure->qscale_tab[0] = this->Structure->qscale_tab[1] = this->Structure->qscale_tab[2] = 1; + this->Structure->intravlc_tab[0] = 1; + this->Structure->intravlc_tab[1] = this->Structure->intravlc_tab[2] = 1; + this->Structure->altscan_tab[0] = this->Structure->altscan_tab[1] = this->Structure->altscan_tab[2] = 0; + this->Structure->repeatfirst = 0; + this->Structure->prog_frame = 0; + this->Structure->P_val = 0; + this->Structure->reaction = 0; + this->Structure->avg_act = 0; + this->Structure->Xi = 0; + this->Structure->Xp = 0; + this->Structure->Xb = 0; + this->Structure->d0i = 0; + this->Structure->d0p = 0; + this->Structure->d0b = 0; + + if (this->Structure->N_val<1) + (*(this->Structure->report_error))("N must be positive"); + if (this->Structure->M_val<1) + (*(this->Structure->report_error))("M must be positive"); + if (this->Structure->N_val%this->Structure->M_val != 0) + (*(this->Structure->report_error))("N must be an integer multiple of M"); + + this->Structure->motion_data = (struct motion_data *)malloc(this->Structure->M_val*sizeof(struct motion_data)); + if (!this->Structure->motion_data) + (*(this->Structure->report_error))("malloc failed\n"); + + this->Structure->motion_data[0].forw_hor_f_code = 2; + this->Structure->motion_data[0].forw_vert_f_code = 2; + this->Structure->motion_data[0].sxf = 11; + this->Structure->motion_data[0].syf = 11; + + this->Structure->motion_data[1].forw_hor_f_code = 1; + this->Structure->motion_data[1].forw_vert_f_code = 1; + this->Structure->motion_data[1].sxf = 3; + this->Structure->motion_data[1].syf = 3; + + this->Structure->motion_data[1].back_hor_f_code = 1; + this->Structure->motion_data[1].back_vert_f_code = 1; + this->Structure->motion_data[1].sxb = 7; + this->Structure->motion_data[1].syb = 7; + + this->Structure->motion_data[2].forw_hor_f_code = 1; + this->Structure->motion_data[2].forw_vert_f_code = 1; + this->Structure->motion_data[2].sxf = 7; + this->Structure->motion_data[2].syf = 7; + + this->Structure->motion_data[2].back_hor_f_code = 1; + this->Structure->motion_data[2].back_vert_f_code = 1; + this->Structure->motion_data[2].sxb = 3; + this->Structure->motion_data[2].syb = 3; + + /* + for (i=0; iStructure->M_val; i++) + { + fgets(line,254,fd); + sscanf(line,"%d %d %d %d", + &this->Structure->motion_data[i].forw_hor_f_code, &this->Structure->motion_data[i].forw_vert_f_code, + &this->Structure->motion_data[i].sxf, &this->Structure->motion_data[i].syf); + + if (i!=0) + { + fgets(line,254,fd); + sscanf(line,"%d %d %d %d", + &this->Structure->motion_data[i].back_hor_f_code, &this->Structure->motion_data[i].back_vert_f_code, + &this->Structure->motion_data[i].sxb, &this->Structure->motion_data[i].syb); + } + } + + fclose(fd); + */ + + /* make flags boolean (x!=0 -> x=1) */ + this->Structure->mpeg1 = !!this->Structure->mpeg1; + this->Structure->fieldpic = !!this->Structure->fieldpic; + this->Structure->low_delay = !!this->Structure->low_delay; + this->Structure->constrparms = !!this->Structure->constrparms; + this->Structure->prog_seq = !!this->Structure->prog_seq; + this->Structure->topfirst = !!this->Structure->topfirst; + + for (i=0; i<3; i++) + { + this->Structure->frame_pred_dct_tab[i] = !!this->Structure->frame_pred_dct_tab[i]; + this->Structure->conceal_tab[i] = !!this->Structure->conceal_tab[i]; + this->Structure->qscale_tab[i] = !!this->Structure->qscale_tab[i]; + this->Structure->intravlc_tab[i] = !!this->Structure->intravlc_tab[i]; + this->Structure->altscan_tab[i] = !!this->Structure->altscan_tab[i]; + } + this->Structure->repeatfirst = !!this->Structure->repeatfirst; + this->Structure->prog_frame = !!this->Structure->prog_frame; + + /* make sure MPEG specific parameters are valid */ + MPEG2_range_checks(this->Structure); + + this->Structure->frame_rate = ratetab[this->Structure->frame_rate_code-1]; + + /* timecode -> frame number */ + h = m = s = f = 0; + this->Structure->tc0 = h; + this->Structure->tc0 = 60*this->Structure->tc0 + m; + this->Structure->tc0 = 60*this->Structure->tc0 + s; + this->Structure->tc0 = (int)(this->Structure->frame_rate+0.5)*this->Structure->tc0 + f; + + if (!this->Structure->mpeg1) + { + MPEG2_profile_and_level_checks(this->Structure); + } + else + { + /* MPEG-1 */ + if (this->Structure->constrparms) + { + if (this->Structure->horizontal_size>768 + || this->Structure->vertical_size>576 + || ((this->Structure->horizontal_size+15)/16)*((this->Structure->vertical_size+15)/16)>396 + || ((this->Structure->horizontal_size+15)/16)*((this->Structure->vertical_size+15)/16)*this->Structure->frame_rate>396*25.0 + || this->Structure->frame_rate>30.0) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n"); + this->Structure->constrparms = 0; + } + } + + if (this->Structure->constrparms) + { + for (i=0; iStructure->M_val; i++) + { + if (this->Structure->motion_data[i].forw_hor_f_code>4) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n"); + this->Structure->constrparms = 0; + break; + } + + if (this->Structure->motion_data[i].forw_vert_f_code>4) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n"); + this->Structure->constrparms = 0; + break; + } + + if (i!=0) + { + if (this->Structure->motion_data[i].back_hor_f_code>4) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n"); + this->Structure->constrparms = 0; + break; + } + + if (this->Structure->motion_data[i].back_vert_f_code>4) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n"); + this->Structure->constrparms = 0; + break; + } + } + } + } + } + + /* relational checks */ + + if (this->Structure->mpeg1) + { + if (!this->Structure->prog_seq) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting progressive_sequence = 1\n"); + this->Structure->prog_seq = 1; + } + + if (this->Structure->chroma_format!=CHROMA420) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting this->Structure->chroma_format = 1 (4:2:0)\n"); + this->Structure->chroma_format = CHROMA420; + } + + if (this->Structure->dc_prec!=0) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting intra_dc_precision = 0\n"); + this->Structure->dc_prec = 0; + } + + for (i=0; i<3; i++) + if (this->Structure->qscale_tab[i]) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting this->Structure->qscale_tab[%d] = 0\n",i); + this->Structure->qscale_tab[i] = 0; + } + + for (i=0; i<3; i++) + if (this->Structure->intravlc_tab[i]) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting this->Structure->intravlc_tab[%d] = 0\n",i); + this->Structure->intravlc_tab[i] = 0; + } + + for (i=0; i<3; i++) + if (this->Structure->altscan_tab[i]) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting this->Structure->altscan_tab[%d] = 0\n",i); + this->Structure->altscan_tab[i] = 0; + } + } + + if (!this->Structure->mpeg1 && this->Structure->constrparms) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n"); + this->Structure->constrparms = 0; + } + + if (this->Structure->prog_seq && !this->Structure->prog_frame) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting progressive_frame = 1\n"); + this->Structure->prog_frame = 1; + } + + if (this->Structure->prog_frame && this->Structure->fieldpic) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting field_pictures = 0\n"); + this->Structure->fieldpic = 0; + } + + if (!this->Structure->prog_frame && this->Structure->repeatfirst) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting repeat_first_field = 0\n"); + this->Structure->repeatfirst = 0; + } + + if (this->Structure->prog_frame) + { + for (i=0; i<3; i++) + if (!this->Structure->frame_pred_dct_tab[i]) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting frame_pred_frame_dct[%d] = 1\n",i); + this->Structure->frame_pred_dct_tab[i] = 1; + } + } + + if (this->Structure->prog_seq && !this->Structure->repeatfirst && this->Structure->topfirst) + { + if (!this->Structure->quiet) + fprintf(stderr,"Warning: setting top_field_first = 0\n"); + this->Structure->topfirst = 0; + } + + /* search windows */ + for (i=0; iStructure->M_val; i++) + { + if (this->Structure->motion_data[i].sxf > (4<Structure->motion_data[i].forw_hor_f_code)-1) + { + if (!this->Structure->quiet) + fprintf(stderr, + "Warning: reducing forward horizontal search this->Structure->width to %d\n", + (4<Structure->motion_data[i].forw_hor_f_code)-1); + this->Structure->motion_data[i].sxf = (4<Structure->motion_data[i].forw_hor_f_code)-1; + } + + if (this->Structure->motion_data[i].syf > (4<Structure->motion_data[i].forw_vert_f_code)-1) + { + if (!this->Structure->quiet) + fprintf(stderr, + "Warning: reducing forward vertical search this->Structure->width to %d\n", + (4<Structure->motion_data[i].forw_vert_f_code)-1); + this->Structure->motion_data[i].syf = (4<Structure->motion_data[i].forw_vert_f_code)-1; + } + + if (i!=0) + { + if (this->Structure->motion_data[i].sxb > (4<Structure->motion_data[i].back_hor_f_code)-1) + { + if (!this->Structure->quiet) + fprintf(stderr, + "Warning: reducing backward horizontal search this->Structure->width to %d\n", + (4<Structure->motion_data[i].back_hor_f_code)-1); + this->Structure->motion_data[i].sxb = (4<Structure->motion_data[i].back_hor_f_code)-1; + } + + if (this->Structure->motion_data[i].syb > (4<Structure->motion_data[i].back_vert_f_code)-1) + { + if (!this->Structure->quiet) + fprintf(stderr, + "Warning: reducing backward vertical search this->Structure->width to %d\n", + (4<Structure->motion_data[i].back_vert_f_code)-1); + this->Structure->motion_data[i].syb = (4<Structure->motion_data[i].back_vert_f_code)-1; + } + } + } + +} + +void vtkMPEG2WriterInternal::ReadQuantMat() +{ + int i,v; + FILE *fd; + + if (this->Structure->iqname[0]=='-') + { + /* use default intra matrix */ + this->Structure->load_iquant = 0; + for (i=0; i<64; i++) + this->Structure->intra_q[i] = MPEG2_default_intra_quantizer_matrix[i]; + } + else + { + /* read customized intra matrix */ + this->Structure->load_iquant = 1; + if (!(fd = fopen(this->Structure->iqname,"r"))) + { + sprintf(this->Structure->errortext,"Couldn't open quant matrix file %s",this->Structure->iqname); + (*(this->Structure->report_error))(this->Structure->errortext); + } + + for (i=0; i<64; i++) + { + fscanf(fd,"%d",&v); + if (v<1 || v>255) + (*(this->Structure->report_error))("invalid value in quant matrix"); + this->Structure->intra_q[i] = v; + } + + fclose(fd); + } + + if (this->Structure->niqname[0]=='-') + { + /* use default non-intra matrix */ + this->Structure->load_niquant = 0; + for (i=0; i<64; i++) + this->Structure->inter_q[i] = 16; + } + else + { + /* read customized non-intra matrix */ + this->Structure->load_niquant = 1; + if (!(fd = fopen(this->Structure->niqname,"r"))) + { + sprintf(this->Structure->errortext,"Couldn't open quant matrix file %s",this->Structure->niqname); + (*(this->Structure->report_error))(this->Structure->errortext); + } + + for (i=0; i<64; i++) + { + fscanf(fd,"%d",&v); + if (v<1 || v>255) + (*(this->Structure->report_error))("invalid value in quant matrix"); + this->Structure->inter_q[i] = v; + } + + fclose(fd); + } +} diff --git a/IO/vtkMPEG2Writer.h b/IO/vtkMPEG2Writer.h new file mode 100644 index 0000000..ec400b5 --- /dev/null +++ b/IO/vtkMPEG2Writer.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPEG2Writer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMPEG2Writer - Writes MPEG2 Movie files. +// +// .SECTION Description +// vtkMPEG2Writer writes Movie files. The data type +// of the file is unsigned char regardless of the input type. +// +// This class is conditionally compiled into VTK only if VTK's CMake +// option VTK_USE_MPEG2_ENCODER is ON. It is OFF by default. +// +// Portions of the mpeg2 library are patented. VTK does not enable linking to +// this library by default so VTK can remain "patent free". Users who wish to +// link in mpeg2 functionality must build that library separately and then +// turn on VTK_USE_MPEG2_ENCODER when configuring VTK. After turning on +// VTK_USE_MPEG2_ENCODER, you must also set the CMake variables +// vtkMPEG2Encode_INCLUDE_PATH and vtkMPEG2Encode_LIBRARIES. +// +// You are solely responsible for any legal issues associated with using +// patented code in your software. +// +// You can download a "CMake-ified" source tree of the MPEG2 library by +// visiting the download page at http://www.vtk.org and scrolling down to +// the "Download Additional Components" section. +// +// .SECTION See Also +// vtkGenericMovieWriter vtkAVIWriter vtkFFMPEGWriter + +#ifndef __vtkMPEG2Writer_h +#define __vtkMPEG2Writer_h + +#include "vtkGenericMovieWriter.h" + +class vtkMPEG2WriterInternal; +class vtkImageData; +struct MPEG2_structure; + +class VTK_IO_EXPORT vtkMPEG2Writer : public vtkGenericMovieWriter +{ +public: + static vtkMPEG2Writer *New(); + vtkTypeRevisionMacro(vtkMPEG2Writer,vtkGenericMovieWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // These methods start writing an Movie file, write a frame to the file + // and then end the writing process. + void Start(); + void Write(); + void End(); + +protected: + vtkMPEG2Writer(); + ~vtkMPEG2Writer(); + + vtkMPEG2WriterInternal *Internals; + + long Time; + int ActualWrittenTime; + + void Initialize(); + + int Initialized; + + MPEG2_structure* MPEGStructure; + +private: + vtkMPEG2Writer(const vtkMPEG2Writer&); // Not implemented + void operator=(const vtkMPEG2Writer&); // Not implemented +}; + +#endif diff --git a/IO/vtkMedicalImageProperties.cxx b/IO/vtkMedicalImageProperties.cxx new file mode 100644 index 0000000..920233c --- /dev/null +++ b/IO/vtkMedicalImageProperties.cxx @@ -0,0 +1,722 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMedicalImageProperties.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMedicalImageProperties.h" +#include "vtkObjectFactory.h" + +#include +#include +#include // for strftime +#include // for isdigit + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkMedicalImageProperties, "$Revision: 1.3.2.1 $"); +vtkStandardNewMacro(vtkMedicalImageProperties); + +//---------------------------------------------------------------------------- +class vtkMedicalImagePropertiesInternals +{ +public: + class WindowLevelPreset + { + public: + double Window; + double Level; + vtksys_stl::string Comment; + }; + + typedef vtkstd::vector WindowLevelPresetPoolType; + typedef vtkstd::vector::iterator WindowLevelPresetPoolIterator; + + WindowLevelPresetPoolType WindowLevelPresetPool; +}; + +//---------------------------------------------------------------------------- +vtkMedicalImageProperties::vtkMedicalImageProperties() +{ + this->Internals = new vtkMedicalImagePropertiesInternals; + + this->AcquisitionDate = NULL; + this->AcquisitionTime = NULL; + this->ConvolutionKernel = NULL; + this->EchoTime = NULL; + this->EchoTrainLength = NULL; + this->Exposure = NULL; + this->ExposureTime = NULL; + this->GantryTilt = NULL; + this->ImageDate = NULL; + this->ImageNumber = NULL; + this->ImageTime = NULL; + this->InstitutionName = NULL; + this->KVP = NULL; + this->ManufacturerModelName = NULL; + this->Manufacturer = NULL; + this->Modality = NULL; + this->PatientAge = NULL; + this->PatientBirthDate = NULL; + this->PatientID = NULL; + this->PatientName = NULL; + this->PatientSex = NULL; + this->RepetitionTime = NULL; + this->SeriesDescription = NULL; + this->SeriesNumber = NULL; + this->SliceThickness = NULL; + this->StationName = NULL; + this->StudyDescription = NULL; + this->StudyID = NULL; + this->XRayTubeCurrent = NULL; +} + +//---------------------------------------------------------------------------- +vtkMedicalImageProperties::~vtkMedicalImageProperties() +{ + if (this->Internals) + { + delete this->Internals; + this->Internals = NULL; + } + + this->Clear(); +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageProperties::Clear() +{ + this->SetAcquisitionDate(NULL); + this->SetAcquisitionTime(NULL); + this->SetConvolutionKernel(NULL); + this->SetEchoTime(NULL); + this->SetEchoTrainLength(NULL); + this->SetExposure(NULL); + this->SetExposureTime(NULL); + this->SetGantryTilt(NULL); + this->SetImageDate(NULL); + this->SetImageNumber(NULL); + this->SetImageTime(NULL); + this->SetInstitutionName(NULL); + this->SetKVP(NULL); + this->SetManufacturerModelName(NULL); + this->SetManufacturer(NULL); + this->SetModality(NULL); + this->SetPatientAge(NULL); + this->SetPatientBirthDate(NULL); + this->SetPatientID(NULL); + this->SetPatientName(NULL); + this->SetPatientSex(NULL); + this->SetRepetitionTime(NULL); + this->SetSeriesDescription(NULL); + this->SetSeriesNumber(NULL); + this->SetSliceThickness(NULL); + this->SetStationName(NULL); + this->SetStudyDescription(NULL); + this->SetStudyID(NULL); + this->SetXRayTubeCurrent(NULL); + + this->RemoveAllWindowLevelPresets(); +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageProperties::DeepCopy(vtkMedicalImageProperties *p) +{ + if (p == NULL) + { + return; + } + + this->Clear(); + + this->SetAcquisitionDate(p->GetAcquisitionDate()); + this->SetAcquisitionTime(p->GetAcquisitionTime()); + this->SetConvolutionKernel(p->GetConvolutionKernel()); + this->SetEchoTime(p->GetEchoTime()); + this->SetEchoTrainLength(p->GetEchoTrainLength()); + this->SetExposure(p->GetExposure()); + this->SetExposureTime(p->GetExposureTime()); + this->SetGantryTilt(p->GetGantryTilt()); + this->SetImageDate(p->GetImageDate()); + this->SetImageNumber(p->GetImageNumber()); + this->SetImageTime(p->GetImageTime()); + this->SetInstitutionName(p->GetInstitutionName()); + this->SetKVP(p->GetKVP()); + this->SetManufacturerModelName(p->GetManufacturerModelName()); + this->SetManufacturer(p->GetManufacturer()); + this->SetModality(p->GetModality()); + this->SetPatientAge(p->GetPatientAge()); + this->SetPatientBirthDate(p->GetPatientBirthDate()); + this->SetPatientID(p->GetPatientID()); + this->SetPatientName(p->GetPatientName()); + this->SetPatientSex(p->GetPatientSex()); + this->SetRepetitionTime(p->GetRepetitionTime()); + this->SetSeriesDescription(p->GetSeriesDescription()); + this->SetSeriesNumber(p->GetSeriesNumber()); + this->SetSliceThickness(p->GetSliceThickness()); + this->SetStationName(p->GetStationName()); + this->SetStudyDescription(p->GetStudyDescription()); + this->SetStudyID(p->GetStudyID()); + this->SetXRayTubeCurrent(p->GetXRayTubeCurrent()); + + int nb_presets = p->GetNumberOfWindowLevelPresets(); + for (int i = 0; i < nb_presets; i++) + { + double w, l; + p->GetNthWindowLevelPreset(i, &w, &l); + this->AddWindowLevelPreset(w, l); + this->SetNthWindowLevelPresetComment( + this->GetNumberOfWindowLevelPresets() - 1, + p->GetNthWindowLevelPresetComment(i)); + } +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageProperties::AddWindowLevelPreset( + double w, double l) +{ + if (!this->Internals || this->HasWindowLevelPreset(w, l)) + { + return; + } + + vtkMedicalImagePropertiesInternals::WindowLevelPreset preset; + preset.Window = w; + preset.Level = l; + this->Internals->WindowLevelPresetPool.push_back(preset); +} + +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::HasWindowLevelPreset(double w, double l) +{ + if (this->Internals) + { + vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator it = + this->Internals->WindowLevelPresetPool.begin(); + vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator end = + this->Internals->WindowLevelPresetPool.end(); + for (; it != end; ++it) + { + if ((*it).Window == w && (*it).Level == l) + { + return 1; + } + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageProperties::RemoveWindowLevelPreset(double w, double l) +{ + if (this->Internals) + { + vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator it = + this->Internals->WindowLevelPresetPool.begin(); + vtkMedicalImagePropertiesInternals::WindowLevelPresetPoolIterator end = + this->Internals->WindowLevelPresetPool.end(); + for (; it != end; ++it) + { + if ((*it).Window == w && (*it).Level == l) + { + this->Internals->WindowLevelPresetPool.erase(it); + break; + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageProperties::RemoveAllWindowLevelPresets() +{ + if (this->Internals) + { + this->Internals->WindowLevelPresetPool.clear(); + } +} + +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetNumberOfWindowLevelPresets() +{ + return this->Internals ? this->Internals->WindowLevelPresetPool.size() : 0; +} + +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetNthWindowLevelPreset( + int idx, double *w, double *l) +{ + if (this->Internals && + idx >= 0 && idx < this->GetNumberOfWindowLevelPresets()) + { + *w = this->Internals->WindowLevelPresetPool[idx].Window; + *l = this->Internals->WindowLevelPresetPool[idx].Level; + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +double* vtkMedicalImageProperties::GetNthWindowLevelPreset(int idx) + +{ + static double wl[2]; + if (this->GetNthWindowLevelPreset(idx, wl, wl + 1)) + { + return wl; + } + return NULL; +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageProperties::GetNthWindowLevelPresetComment( + int idx) +{ + if (this->Internals && + idx >= 0 && idx < this->GetNumberOfWindowLevelPresets()) + { + return this->Internals->WindowLevelPresetPool[idx].Comment.c_str(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageProperties::SetNthWindowLevelPresetComment( + int idx, const char *comment) +{ + if (this->Internals && + idx >= 0 && idx < this->GetNumberOfWindowLevelPresets()) + { + this->Internals->WindowLevelPresetPool[idx].Comment = + (comment ? comment : ""); + } +} + +//---------------------------------------------------------------------------- +double vtkMedicalImageProperties::GetSliceThicknessAsDouble() +{ + if (this->SliceThickness) + { + return atof(this->SliceThickness); + } + return 0; +} + +//---------------------------------------------------------------------------- +double vtkMedicalImageProperties::GetGantryTiltAsDouble() +{ + if (this->GantryTilt) + { + return atof(this->GantryTilt); + } + return 0; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetAgeAsFields(const char *age, int &year, + int &month, int &week, int &day) +{ + year = month = week = day = -1; + if( !age ) + { + return 0; + } + + size_t len = strlen(age); + if( len == 4 ) + { + // DICOM V3 + unsigned int val; + char type; + if( !isdigit(age[0]) + || !isdigit(age[1]) + || !isdigit(age[2])) + { + return 0; + } + if( sscanf(age, "%3u%c", &val, &type) != 2 ) + { + return 0; + } + switch(type) + { + case 'Y': + year = (int)val; + break; + case 'M': + month = (int)val; + break; + case 'W': + week = (int)val; + break; + case 'D': + day = (int)val; + break; + default: + return 0; + } + } + else + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetPatientAgeYear() +{ + const char *age = this->GetPatientAge(); + int year, month, week, day; + vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); + return year; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetPatientAgeMonth() +{ + const char *age = this->GetPatientAge(); + int year, month, week, day; + vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); + return month; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetPatientAgeWeek() +{ + const char *age = this->GetPatientAge(); + int year, month, week, day; + vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); + return week; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetPatientAgeDay() +{ + const char *age = this->GetPatientAge(); + int year, month, week, day; + vtkMedicalImageProperties::GetAgeAsFields(age, year, month, week, day); + return day; +} + +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetDateAsFields(const char *date, int &year, + int &month, int &day) +{ + if( !date ) + { + return 0; + } + + size_t len = strlen(date); + if( len == 8 ) + { + // DICOM V3 + if( sscanf(date, "%04d%02d%02d", &year, &month, &day) != 3 ) + { + return 0; + } + } + else if( len == 10 ) + { + // Some *very* old ACR-NEMA + if( sscanf(date, "%04d.%02d.%02d", &year, &month, &day) != 3 ) + { + return 0; + } + } + else + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Some buggy versions of gcc complain about the use of %c: warning: `%c' +// yields only last 2 digits of year in some locales. Of course program- +// mers are encouraged to use %c, it gives the preferred date and time +// representation. One meets all kinds of strange obfuscations to circum- +// vent this gcc problem. A relatively clean one is to add an intermediate +// function. This is described as bug #3190 in gcc bugzilla: +// [-Wformat-y2k doesn't belong to -Wall - it's hard to avoid] +inline size_t +my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) +{ + return strftime(s, max, fmt, tm); +} +// Helper function to convert a DICOM iso date format into a locale one +// locale buffer should be typically char locale[200] +int vtkMedicalImageProperties::GetDateAsLocale(const char *iso, char *locale) +{ + int year, month, day; + if( vtkMedicalImageProperties::GetDateAsFields(iso, year, month, day) ) + { + struct tm date; + memset(&date,0, sizeof(date)); + date.tm_mday = day; + // month are expressed in the [0-11] range: + date.tm_mon = month - 1; + // structure is date starting at 1900 + date.tm_year = year - 1900; + my_strftime(locale, 200, "%x", &date); + return 1; + } + return 0; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetPatientBirthDateYear() +{ + const char *date = this->GetPatientBirthDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return year; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetPatientBirthDateMonth() +{ + const char *date = this->GetPatientBirthDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return month; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetPatientBirthDateDay() +{ + const char *date = this->GetPatientBirthDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return day; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetAcquisitionDateYear() +{ + const char *date = this->GetAcquisitionDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return year; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetAcquisitionDateMonth() +{ + const char *date = this->GetAcquisitionDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return month; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetAcquisitionDateDay() +{ + const char *date = this->GetAcquisitionDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return day; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetImageDateYear() +{ + const char *date = this->GetImageDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return year; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetImageDateMonth() +{ + const char *date = this->GetImageDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return month; +} +//---------------------------------------------------------------------------- +int vtkMedicalImageProperties::GetImageDateDay() +{ + const char *date = this->GetImageDate(); + int year, month, day; + vtkMedicalImageProperties::GetDateAsFields(date, year, month, day); + return day; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageProperties::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << "\n" << indent << "PatientName: "; + if (this->PatientName) + { + os << this->PatientName; + } + + os << "\n" << indent << "PatientID: "; + if (this->PatientID) + { + os << this->PatientID; + } + + os << "\n" << indent << "PatientAge: "; + if (this->PatientAge) + { + os << this->PatientAge; + } + + os << "\n" << indent << "PatientSex: "; + if (this->PatientSex) + { + os << this->PatientSex; + } + + os << "\n" << indent << "PatientBirthDate: "; + if (this->PatientBirthDate) + { + os << this->PatientBirthDate; + } + + os << "\n" << indent << "ImageDate: "; + if (this->ImageDate) + { + os << this->ImageDate; + } + + os << "\n" << indent << "ImageTime: "; + if (this->ImageTime) + { + os << this->ImageTime; + } + + os << "\n" << indent << "ImageNumber: "; + if (this->ImageNumber) + { + os << this->ImageNumber; + } + + os << "\n" << indent << "AcquisitionDate: "; + if (this->AcquisitionDate) + { + os << this->AcquisitionDate; + } + + os << "\n" << indent << "AcquisitionTime: "; + if (this->AcquisitionTime) + { + os << this->AcquisitionTime; + } + + os << "\n" << indent << "SeriesNumber: "; + if (this->SeriesNumber) + { + os << this->SeriesNumber; + } + + os << "\n" << indent << "SeriesDescription: "; + if (this->SeriesDescription) + { + os << this->SeriesDescription; + } + + os << "\n" << indent << "StudyDescription: "; + if (this->StudyDescription) + { + os << this->StudyDescription; + } + + os << "\n" << indent << "StudyID: "; + if (this->StudyID) + { + os << this->StudyID; + } + + os << "\n" << indent << "Modality: "; + if (this->Modality) + { + os << this->Modality; + } + + os << "\n" << indent << "ManufacturerModelName: "; + if (this->ManufacturerModelName) + { + os << this->ManufacturerModelName; + } + + os << "\n" << indent << "Manufacturer: "; + if (this->Manufacturer) + { + os << this->Manufacturer; + } + + os << "\n" << indent << "StationName: "; + if (this->StationName) + { + os << this->StationName; + } + + os << "\n" << indent << "InstitutionName: "; + if (this->InstitutionName) + { + os << this->InstitutionName; + } + + os << "\n" << indent << "ConvolutionKernel: "; + if (this->ConvolutionKernel) + { + os << this->ConvolutionKernel; + } + + os << "\n" << indent << "SliceThickness: "; + if (this->SliceThickness) + { + os << this->SliceThickness; + } + + os << "\n" << indent << "KVP: "; + if (this->KVP) + { + os << this->KVP; + } + + os << "\n" << indent << "GantryTilt: "; + if (this->GantryTilt) + { + os << this->GantryTilt; + } + + os << "\n" << indent << "EchoTime: "; + if (this->EchoTime) + { + os << this->EchoTime; + } + + os << "\n" << indent << "EchoTrainLength: "; + if (this->EchoTrainLength) + { + os << this->EchoTrainLength; + } + + os << "\n" << indent << "RepetitionTime: "; + if (this->RepetitionTime) + { + os << this->RepetitionTime; + } + + os << "\n" << indent << "ExposureTime: "; + if (this->ExposureTime) + { + os << this->ExposureTime; + } + + os << "\n" << indent << "XRayTubeCurrent: "; + if (this->XRayTubeCurrent) + { + os << this->XRayTubeCurrent; + } + + os << "\n" << indent << "Exposure: "; + if (this->Exposure) + { + os << this->Exposure; + } +} diff --git a/IO/vtkMedicalImageProperties.h b/IO/vtkMedicalImageProperties.h new file mode 100644 index 0000000..439227b --- /dev/null +++ b/IO/vtkMedicalImageProperties.h @@ -0,0 +1,347 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMedicalImageProperties.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMedicalImageProperties - some medical image properties. +// .SECTION Description +// vtkMedicalImageProperties is a helper class that can be used by medical +// image readers and applications to encapsulate medical image/acquisition +// properties. Later on, this should probably be extended to add +// any user-defined property. +// .SECTION See Also +// vtkMedicalImageReader2 + +#ifndef __vtkMedicalImageProperties_h +#define __vtkMedicalImageProperties_h + +#include "vtkObject.h" + +class vtkMedicalImagePropertiesInternals; + +class VTK_IO_EXPORT vtkMedicalImageProperties : public vtkObject +{ +public: + static vtkMedicalImageProperties *New(); + vtkTypeRevisionMacro(vtkMedicalImageProperties,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Convenience method to reset all fields to an emptry string/value + virtual void Clear(); + + // Description: + // Patient name + // For ex: DICOM (0010,0010) = DOE,JOHN + vtkSetStringMacro(PatientName); + vtkGetStringMacro(PatientName); + + // Description: + // Patient ID + // For ex: DICOM (0010,0020) = 1933197 + vtkSetStringMacro(PatientID); + vtkGetStringMacro(PatientID); + + // Description: + // Patient age + // Format: nnnD, nnW, nnnM or nnnY (eventually nnD, nnW, nnY) + // with D (day), M (month), W (week), Y (year) + // For ex: DICOM (0010,1010) = 031Y + vtkSetStringMacro(PatientAge); + vtkGetStringMacro(PatientAge); + + // Description: + // Take as input a string in VR=AS (DICOM PS3.5) and extract either + // different fields namely: year month week day + // Return 0 on error, 1 on success + // One can test fields if they are different from -1 upon success + static int GetAgeAsFields(const char *age, int &year, int &month, int &week, int &day); + + // For Tcl: + // From C++ use GetPatientAge + GetAgeAsField + // Those function parse a DICOM string, and return the value of the number expressed + // this is either expressed in year, month or days. Thus if a string is expressed in years + // GetPatientAgeDay/GetPatientAgeWeek/GetPatientAgeMonth will return 0 + int GetPatientAgeYear(); + int GetPatientAgeMonth(); + int GetPatientAgeWeek(); + int GetPatientAgeDay(); + + // Description: + // Patient sex + // For ex: DICOM (0010,0040) = M + vtkSetStringMacro(PatientSex); + vtkGetStringMacro(PatientSex); + + // Description: + // Patient birth date + // Format: yyyymmdd + // For ex: DICOM (0010,0030) = 19680427 + vtkSetStringMacro(PatientBirthDate); + vtkGetStringMacro(PatientBirthDate); + + // For Tcl: + // From C++ use GetPatientBirthDate + GetDateAsFields + int GetPatientBirthDateYear(); + int GetPatientBirthDateMonth(); + int GetPatientBirthDateDay(); + + // Description: + // Acquisition Date + // Format: yyyymmdd + // For ex: DICOM (0008,0022) = 20030617 + vtkSetStringMacro(AcquisitionDate); + vtkGetStringMacro(AcquisitionDate); + + // For Tcl: + // From C++ use GetAcquisitionDate + GetDateAsFields + int GetAcquisitionDateYear(); + int GetAcquisitionDateMonth(); + int GetAcquisitionDateDay(); + + // Description: + // Acquisition time + // Format: hhmmss.frac (any trailing component(s) can be ommited) + // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012 + vtkSetStringMacro(AcquisitionTime); + vtkGetStringMacro(AcquisitionTime); + + // Description: + // Image Date + // Format: yyyymmdd + // For ex: DICOM (0008,0023) = 20030617 + vtkSetStringMacro(ImageDate); + vtkGetStringMacro(ImageDate); + + // For Tcl: + // From C++ use GetImageDate + GetDateAsFields + int GetImageDateYear(); + int GetImageDateMonth(); + int GetImageDateDay(); + + // Description: + // Take as input a string in ISO 8601 date (YYYY/MM/DD) and extract the + // different fields namely: year month day + // Return 0 on error, 1 on success + static int GetDateAsFields(const char *date, int &year, int &month, int &day); + + // Description: + // Take as input a string in ISO 8601 date (YYYY/MM/DD) and construct a + // locale date based on the different fields (see GetDateAsFields to extract + // different fields) + // Return 0 on error, 1 on success + static int GetDateAsLocale(const char *date, char *locale); + + // Description: + // Image Time + // Format: hhmmss.frac (any trailing component(s) can be ommited) + // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012 + vtkSetStringMacro(ImageTime); + vtkGetStringMacro(ImageTime); + + // Description: + // Image number + // For ex: DICOM (0020,0013) = 1 + vtkSetStringMacro(ImageNumber); + vtkGetStringMacro(ImageNumber); + + // Description: + // Series number + // For ex: DICOM (0020,0011) = 902 + vtkSetStringMacro(SeriesNumber); + vtkGetStringMacro(SeriesNumber); + + // Description: + // Series Description + // User provided description of the Series + // For ex: DICOM (0008,103e) = SCOUT + vtkSetStringMacro(SeriesDescription); + vtkGetStringMacro(SeriesDescription); + + // Description: + // Study ID + // For ex: DICOM (0020,0010) = 37481 + vtkSetStringMacro(StudyID); + vtkGetStringMacro(StudyID); + + // Description: + // Study description + // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL + vtkSetStringMacro(StudyDescription); + vtkGetStringMacro(StudyDescription); + + // Description: + // Modality + // For ex: DICOM (0008,0060)= CT + vtkSetStringMacro(Modality); + vtkGetStringMacro(Modality); + + // Description: + // Manufacturer + // For ex: DICOM (0008,0070) = Siemens + vtkSetStringMacro(Manufacturer); + vtkGetStringMacro(Manufacturer); + + // Description: + // Manufacturer's Model Name + // For ex: DICOM (0008,1090) = LightSpeed QX/i + vtkSetStringMacro(ManufacturerModelName); + vtkGetStringMacro(ManufacturerModelName); + + // Description: + // Station Name + // For ex: DICOM (0008,1010) = LSPD_OC8 + vtkSetStringMacro(StationName); + vtkGetStringMacro(StationName); + + // Description: + // Institution Name + // For ex: DICOM (0008,0080) = FooCity Medical Center + vtkSetStringMacro(InstitutionName); + vtkGetStringMacro(InstitutionName); + + // Description: + // Convolution Kernel (or algorithm used to reconstruct the data) + // For ex: DICOM (0018,1210) = Bone + vtkSetStringMacro(ConvolutionKernel); + vtkGetStringMacro(ConvolutionKernel); + + // Description: + // Slice Thickness (Nominal reconstructed slice thickness, in mm) + // For ex: DICOM (0018,0050) = 0.273438 + vtkSetStringMacro(SliceThickness); + vtkGetStringMacro(SliceThickness); + virtual double GetSliceThicknessAsDouble(); + + // Description: + // Peak kilo voltage output of the (x-ray) generator used + // For ex: DICOM (0018,0060) = 120 + vtkSetStringMacro(KVP); + vtkGetStringMacro(KVP); + + // Description: + // Gantry/Detector tilt (Nominal angle of tilt in degrees of the scanning + // gantry.) + // For ex: DICOM (0018,1120) = 15 + vtkSetStringMacro(GantryTilt); + vtkGetStringMacro(GantryTilt); + virtual double GetGantryTiltAsDouble(); + + // Description: + // Echo Time + // (Time in ms between the middle of the excitation pulse and the peak of + // the echo produced) + // For ex: DICOM (0018,0081) = 105 + vtkSetStringMacro(EchoTime); + vtkGetStringMacro(EchoTime); + + // Description: + // Echo Train Length + // (Number of lines in k-space acquired per excitation per image) + // For ex: DICOM (0018,0091) = 35 + vtkSetStringMacro(EchoTrainLength); + vtkGetStringMacro(EchoTrainLength); + + // Description: + // Repetition Time + // The period of time in msec between the beginning of a pulse sequence and + // the beginning of the succeeding (essentially identical) pulse sequence. + // For ex: DICOM (0018,0080) = 2040 + vtkSetStringMacro(RepetitionTime); + vtkGetStringMacro(RepetitionTime); + + // Description: + // Exposure time (time of x-ray exposure in msec) + // For ex: DICOM (0018,1150) = 5 + vtkSetStringMacro(ExposureTime); + vtkGetStringMacro(ExposureTime); + + // Description: + // X-ray tube current (in mA) + // For ex: DICOM (0018,1151) = 400 + vtkSetStringMacro(XRayTubeCurrent); + vtkGetStringMacro(XRayTubeCurrent); + + // Description: + // Exposure (The exposure expressed in mAs, for example calculated + // from Exposure Time and X-ray Tube Current) + // For ex: DICOM (0018,1152) = 114 + vtkSetStringMacro(Exposure); + vtkGetStringMacro(Exposure); + + // Description: + // Copy the contents of p to this instance. + virtual void DeepCopy(vtkMedicalImageProperties *p); + + // Description: + // Add/Remove/Query the window/level presets that may have been associated + // to a medical image. Window is also known as 'width', level is also known + // as 'center'. The same window/level pair can not be added twice. + // As a convenience, a comment can be associated to a preset. + // For ex: DICOM Window Center (0028,1050) = 00045\000470 + // DICOM Window Width (0028,1051) = 0106\03412 + virtual void AddWindowLevelPreset(double w, double l); + virtual void RemoveWindowLevelPreset(double w, double l); + virtual void RemoveAllWindowLevelPresets(); + virtual int GetNumberOfWindowLevelPresets(); + virtual int HasWindowLevelPreset(double w, double l); + virtual int GetNthWindowLevelPreset(int idx, double *w, double *l); + virtual double* GetNthWindowLevelPreset(int idx); + virtual void SetNthWindowLevelPresetComment(int idx, const char *comment); + virtual const char* GetNthWindowLevelPresetComment(int idx); + +protected: + vtkMedicalImageProperties(); + ~vtkMedicalImageProperties(); + + char *AcquisitionDate; + char *AcquisitionTime; + char *ConvolutionKernel; + char *EchoTime; + char *EchoTrainLength; + char *Exposure; + char *ExposureTime; + char *GantryTilt; + char *ImageDate; + char *ImageNumber; + char *ImageTime; + char *InstitutionName; + char *KVP; + char *ManufacturerModelName; + char *Manufacturer; + char *Modality; + char *PatientAge; + char *PatientBirthDate; + char *PatientID; + char *PatientName; + char *PatientSex; + char *RepetitionTime; + char *SeriesDescription; + char *SeriesNumber; + char *SliceThickness; + char *StationName; + char *StudyDescription; + char *StudyID; + char *XRayTubeCurrent; + + // Description: + // PIMPL Encapsulation for STL containers + //BTX + vtkMedicalImagePropertiesInternals *Internals; + //ETX + +private: + vtkMedicalImageProperties(const vtkMedicalImageProperties&); // Not implemented. + void operator=(const vtkMedicalImageProperties&); // Not implemented. +}; + +#endif diff --git a/IO/vtkMedicalImageReader2.cxx b/IO/vtkMedicalImageReader2.cxx new file mode 100644 index 0000000..f466b55 --- /dev/null +++ b/IO/vtkMedicalImageReader2.cxx @@ -0,0 +1,187 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMedicalImageReader2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMedicalImageReader2.h" +#include "vtkObjectFactory.h" + +#include "vtkMedicalImageProperties.h" + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkMedicalImageReader2, "$Revision: 1.6.4.1 $"); +vtkStandardNewMacro(vtkMedicalImageReader2); + +//---------------------------------------------------------------------------- +vtkMedicalImageReader2::vtkMedicalImageReader2() +{ + this->MedicalImageProperties = vtkMedicalImageProperties::New(); +} + +//---------------------------------------------------------------------------- +vtkMedicalImageReader2::~vtkMedicalImageReader2() +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->Delete(); + this->MedicalImageProperties = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::SetPatientName(const char *arg) +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->SetPatientName(arg); + } +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageReader2::GetPatientName() +{ + if (this->MedicalImageProperties) + { + return this->MedicalImageProperties->GetPatientName(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::SetPatientID(const char *arg) +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->SetPatientID(arg); + } +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageReader2::GetPatientID() +{ + if (this->MedicalImageProperties) + { + return this->MedicalImageProperties->GetPatientID(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::SetDate(const char *arg) +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->SetImageDate(arg); + } +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageReader2::GetDate() +{ + if (this->MedicalImageProperties) + { + return this->MedicalImageProperties->GetImageDate(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::SetSeries(const char *arg) +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->SetSeriesNumber(arg); + } +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageReader2::GetSeries() +{ + if (this->MedicalImageProperties) + { + return this->MedicalImageProperties->GetSeriesNumber(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::SetStudy(const char *arg) +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->SetStudyID(arg); + } +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageReader2::GetStudy() +{ + if (this->MedicalImageProperties) + { + return this->MedicalImageProperties->GetStudyID(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::SetImageNumber(const char *arg) +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->SetImageNumber(arg); + } +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageReader2::GetImageNumber() +{ + if (this->MedicalImageProperties) + { + return this->MedicalImageProperties->GetImageNumber(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::SetModality(const char *arg) +{ + if (this->MedicalImageProperties) + { + this->MedicalImageProperties->SetModality(arg); + } +} + +//---------------------------------------------------------------------------- +const char* vtkMedicalImageReader2::GetModality() +{ + if (this->MedicalImageProperties) + { + return this->MedicalImageProperties->GetModality(); + } + return NULL; +} + +//---------------------------------------------------------------------------- +void vtkMedicalImageReader2::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + if (this->MedicalImageProperties) + { + os << indent << "Medical Image Properties:\n"; + this->MedicalImageProperties->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << indent << "MedicalImageProperties: (none)\n"; + } +} diff --git a/IO/vtkMedicalImageReader2.h b/IO/vtkMedicalImageReader2.h new file mode 100644 index 0000000..ed21c77 --- /dev/null +++ b/IO/vtkMedicalImageReader2.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMedicalImageReader2.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMedicalImageReader2 - vtkImageReader2 with medical meta data. +// .SECTION Description +// vtkMedicalImageReader2 is a parent class for medical image readers. +// It provides a place to store patient information that may be stored +// in the image header. +// .SECTION See Also +// vtkImageReader2 vtkGESignaReader vtkMedicalImageProperties + +#ifndef __vtkMedicalImageReader2_h +#define __vtkMedicalImageReader2_h + +#include "vtkImageReader2.h" + +class vtkMedicalImageProperties; + +class VTK_IO_EXPORT vtkMedicalImageReader2 : public vtkImageReader2 +{ +public: + static vtkMedicalImageReader2 *New(); + vtkTypeRevisionMacro(vtkMedicalImageReader2,vtkImageReader2); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the medical image properties object + vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties); + + // Description: + // For backward compatibility, propagate calls to the MedicalImageProperties + // object. + virtual void SetPatientName(const char*); + virtual const char* GetPatientName(); + virtual void SetPatientID(const char*); + virtual const char* GetPatientID(); + virtual void SetDate(const char*); + virtual const char* GetDate(); + virtual void SetSeries(const char*); + virtual const char* GetSeries(); + virtual void SetStudy(const char*); + virtual const char* GetStudy(); + virtual void SetImageNumber(const char*); + virtual const char* GetImageNumber(); + virtual void SetModality(const char*); + virtual const char* GetModality(); + +protected: + vtkMedicalImageReader2(); + ~vtkMedicalImageReader2(); + + // Description: + // Medical Image properties + vtkMedicalImageProperties *MedicalImageProperties; + +private: + vtkMedicalImageReader2(const vtkMedicalImageReader2&); // Not implemented. + void operator=(const vtkMedicalImageReader2&); // Not implemented. +}; + +#endif diff --git a/IO/vtkMetaImageReader.cxx b/IO/vtkMetaImageReader.cxx new file mode 100644 index 0000000..31e69e4 --- /dev/null +++ b/IO/vtkMetaImageReader.cxx @@ -0,0 +1,671 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMetaImageReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMetaImageReader.h" + +#include "vtkObjectFactory.h" +#include "vtkImageData.h" +#include "vtkInformationVector.h" + +#include + +#include + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkMetaImageReader, "$Revision: 1.18 $"); +vtkStandardNewMacro(vtkMetaImageReader); + +//---------------------------------------------------------------------------- +vtkMetaImageReader::vtkMetaImageReader() +{ + this->MHDFileName = 0; +} + +//---------------------------------------------------------------------------- +vtkMetaImageReader::~vtkMetaImageReader() +{ + this->SetFileName(0); +} + +//---------------------------------------------------------------------------- +void vtkMetaImageReader::SetFileName(const char* fname) +{ + this->SetMHDFileName(fname); +} + +//---------------------------------------------------------------------------- +class vtkMetaImageReaderInternal +{ +public: + static void ReplaceString(vtkstd::string& source, const char* replace, + const char* with); + static void ConvertToUnixSlashes(vtkstd::string& path); + static vtkstd::string GetFilenamePath(const vtkstd::string& filename); + static int StringEquals(const char* s1, const char* s2, size_t maxlen); + static int StringEqualsCase(const char* s1, const char* s2, size_t maxlen); + static int GetLineFromStream(istream& is, vtkstd::string& line, + bool *has_newline /* = 0 */, size_t maxlen /* = 0 */); +}; + +//---------------------------------------------------------------------------- +// replace replace with with as many times as it shows up in source. +// write the result into source. +void vtkMetaImageReaderInternal::ReplaceString(vtkstd::string& source, + const char* replace, + const char* with) +{ + const char *src = source.c_str(); + char *searchPos = const_cast(strstr(src,replace)); + + // get out quick if string is not found + if (!searchPos) + { + return; + } + + // perform replacements until done + size_t replaceSize = strlen(replace); + char *orig = strdup(src); + char *currentPos = orig; + searchPos = searchPos - src + orig; + + // initialize the result + source.erase(source.begin(),source.end()); + do + { + *searchPos = '\0'; + source += currentPos; + currentPos = searchPos + replaceSize; + // replace + source += with; + searchPos = strstr(currentPos,replace); + } + while (searchPos); + + // copy any trailing text + source += currentPos; + free(orig); +} + +//---------------------------------------------------------------------------- +// convert windows slashes to unix slashes +void vtkMetaImageReaderInternal::ConvertToUnixSlashes(vtkstd::string& path) +{ + vtkstd::string::size_type pos = 0; + while((pos = path.find('\\', pos)) != vtkstd::string::npos) + { + path[pos] = '/'; + pos++; + } + // Remove all // from the path just like most unix shells + int start_find; + +#ifdef _WIN32 + // However, on windows if the first characters are both slashes, + // then keep them that way, so that network paths can be handled. + start_find = 1; +#else + start_find = 0; +#endif + + while((pos = path.find("//", start_find)) != vtkstd::string::npos) + { + vtkMetaImageReaderInternal::ReplaceString(path, "//", "/"); + } + + // remove any trailing slash + if(path.size() && path[path.size()-1] == '/') + { + path = path.substr(0, path.size()-1); + } + + // if there is a tilda ~ then replace it with HOME + if(path.find("~") == 0) + { + if (getenv("HOME")) + { + path = getenv("HOME"); + path += path.substr(1); + } + } + + // if there is a /tmp_mnt in a path get rid of it! + if(path.find("/tmp_mnt") == 0) + { + path = path.substr(8); + } +} + +//---------------------------------------------------------------------------- +/** + * Return path of a full filename (no trailing slashes). + * Warning: returned path is converted to Unix slashes format. + */ +vtkstd::string vtkMetaImageReaderInternal::GetFilenamePath(const vtkstd::string& filename) +{ + vtkstd::string fn = filename; + vtkMetaImageReaderInternal::ConvertToUnixSlashes(fn); + + vtkstd::string::size_type slash_pos = fn.rfind("/"); + if(slash_pos != vtkstd::string::npos) + { + return fn.substr(0, slash_pos); + } + return ""; +} + +//---------------------------------------------------------------------------- +// Due to a buggy stream library on the HP and another on Mac OSX, we +// need this very carefully written version of getline. Returns true +// if any data were read before the end-of-file was reached. +int vtkMetaImageReaderInternal::GetLineFromStream(istream& is, vtkstd::string& line, + bool *has_newline /* = 0 */, size_t maxlen /* = 0 */) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + line = ""; + bool haveData = 0; + if ( has_newline ) + { + *has_newline = 0; + } + + // If no characters are read from the stream, the end of file has + // been reached. + while((is.getline(buffer, bufferSize), is.gcount() > 0)) + { + haveData = 1; + if ( maxlen > 0 && is.gcount() + line.size() > maxlen ) + { + line.append(buffer, maxlen - line.size()); + } + else + { + line.append(buffer); + } + + // If newline character was read, the gcount includes the + // character, but the buffer does not. The end of line has been + // reached. + if(strlen(buffer) < static_cast(is.gcount())) + { + if ( has_newline ) + { + *has_newline = 1; + } + break; + } + + // The fail bit may be set. Clear it. + is.clear(is.rdstate() & ~ios::failbit); + } + return haveData; +} + +#if defined( _WIN32 ) && !defined(__CYGWIN__) +# if defined(__BORLANDC__) +# define STRCASECMP stricmp +# else +# define STRCASECMP _stricmp +# endif +#else +# define STRCASECMP strcasecmp +#endif + +#define MHDMIN(x,y) (((x)<(y))?(x):(y)) + +//---------------------------------------------------------------------------- +int vtkMetaImageReaderInternal::StringEqualsCase(const char* s1, const char* s2, size_t maxlen) +{ + if ( s1 == s2 ) + { + return 1; + } + if ( !s1 || !s2 ) + { + return 0; + } + vtkstd::string ss1(s1, MHDMIN(maxlen, strlen(s1))); + vtkstd::string ss2(s2, MHDMIN(maxlen, strlen(s2))); + + return STRCASECMP(ss1.c_str(), ss2.c_str()) == 0; +} +//---------------------------------------------------------------------------- +int vtkMetaImageReaderInternal::StringEquals(const char* s1, const char* s2, size_t maxlen) +{ + if ( s1 == s2 ) + { + return 1; + } + if ( !s1 || !s2 ) + { + return 0; + } + + return strncmp(s1, s2, maxlen) == 0; +} + +//---------------------------------------------------------------------------- +int vtkMetaImageReader::RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + const char* fname = this->MHDFileName; + if ( !this->GetFileInformation(fname, 1) ) + { + return 0; + } + + vtkDataObject::SetPointDataActiveScalarInfo( outputVector->GetInformationObject(0), + this->DataScalarType, this->NumberOfScalarComponents); + + return this->Superclass::RequestInformation( request, inputVector, outputVector ); +} + + +//---------------------------------------------------------------------------- +int vtkMetaImageReader::GetFileInformation(const char* fname, int populate) +{ + if ( !fname ) + { + return 0; + } + struct stat fs; + if ( stat( fname, &fs) ) + { + if ( populate ) + { + vtkErrorMacro(<< "Initialize: Could not open file " << fname); + } + return 0; + } + + ifstream ifs(fname); + if ( !ifs) + { + return 0; + } + + vtkstd::string path = vtkMetaImageReaderInternal::GetFilenamePath(fname); + int ndims = 0; + int bigendian = 0; + int dims[3] = { 0, 0, 0 }; + double origin[3] = { 0.0, 0.0, 0.0 }; + double spacing[3] = { 1.0, 1.0, 1.0 }; + int data_type = VTK_UNSIGNED_CHAR; + int number_of_channels = 1; + vtkstd::string datafile = ""; + unsigned long headerlen = 0; + int size_type = 1; + + vtkstd::string line; + int count = -1; + while(vtkMetaImageReaderInternal::GetLineFromStream(ifs, line, 0, 0) ) + { + count ++; + vtkstd::string::size_type pos = line.find("="); + if ( pos != vtkstd::string::npos ) + { + vtkstd::string::size_type keylen, valuelen; + const char* key = line.c_str(); + const char* value = line.c_str()+pos+1; + const char* endkey = line.c_str()+pos-1; + const char* endvalue = line.c_str()+line.size(); + while ( *key!= 0 ) + { + if ( *key!= ' ' && *key!= '\t' && *key!= '\r' ) + { + break; + } + key++; + } + + while ( endkey > key ) + { + if ( *endkey != ' ' && *endkey != '\t' && *endkey != '\r' && *endkey != 0 ) + { + break; + } + endkey--; + } + keylen = endkey - key + 1; + + while ( *value != 0 ) + { + if ( *value != ' ' && *value != '\t' && *value != '\r' ) + { + break; + } + value++; + } + while ( endvalue > value ) + { + if ( *endvalue != ' ' && *endvalue != '\t' && *endvalue != '\r' && *endvalue != 0 ) + { + break; + } + endvalue--; + } + valuelen = endvalue - value + 1; + //cout << "Key: ["; + //cout.write(key, keylen); + //cout << "] -- Value: ["; + //cout.write(value, valuelen); + //cout << "]" << endl; + if ( vtkMetaImageReaderInternal::StringEquals(key, "ObjectType", keylen) ) + { + if ( !vtkMetaImageReaderInternal::StringEqualsCase(value, "Image", valuelen) ) + { + if ( populate ) + { + vtkErrorMacro(<<"Only understand image data. This is not an image data"); + } + return 0; + } + vtkDebugMacro(<< "* Have image data"); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, "NDims", keylen) ) + { + sscanf(value, "%d", &ndims); + if ( ndims <= 0 || ndims >= 4) + { + if ( populate ) + { + vtkErrorMacro( + << "Only understands image data of 1, 2, or 3 dimensions. This image has " + << ndims << " dimensions"); + } + return 0; + } + vtkDebugMacro(<< "* This image has " << ndims << " dimensions"); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, "BinaryData", keylen) ) + { + if ( !vtkMetaImageReaderInternal::StringEqualsCase(value, "true", valuelen) ) + { + if ( populate ) + { + vtkErrorMacro( + << "Only understand binary image data. This one has BinaryData set to: " + << value); + } + return 0; + } + vtkDebugMacro(<< "* This image has binary data"); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, + "BinaryDataByteOrderMSB", keylen) ) + { + if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "true", valuelen) ) + { + bigendian = 1; + } + else + { + bigendian = 0; + } + vtkDebugMacro(<< "* This image has data which is " + << (bigendian?"big":"little") << " endian"); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, "DimSize", keylen) ) + { + sscanf(value, "%d %d %d", dims, dims+1, dims+2); + vtkDebugMacro(<< "* This image has dimensions " + << dims[0] << " " << dims[1] << " " << dims[2]); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, "ElementSpacing", keylen) ) + { + sscanf(value, "%lf %lf %lf", spacing, spacing+1, spacing+2); + vtkDebugMacro(<< "* This image has spacing " + << spacing[0] << " " << spacing[1] << " " << spacing[2]); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, "Position", keylen) ) + { + sscanf(value, "%lf %lf %lf", origin, origin+1, origin+2); + vtkDebugMacro(<< "* This image has origin " + << origin[0] << " " << origin[1] << " " << origin[2]); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, + "ElementNumberOfChannels", keylen) ) + { + sscanf(value, "%d", &number_of_channels); + if ( ndims <= 0 ) + { + if ( populate ) + { + vtkErrorMacro( + << "Only understands image data of 1 or more channels. This image has " + << number_of_channels << " dimensions"); + } + return 0; + } + vtkDebugMacro(<< "* This image has " << number_of_channels << " channels"); + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, "ElementType", keylen) ) + { + if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_CHAR", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_CHAR_ARRAY", valuelen) ) + { + data_type = VTK_CHAR; + size_type = sizeof(char); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_UCHAR", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_UCHAR_ARRAY", valuelen) ) + { + data_type = VTK_UNSIGNED_CHAR; + size_type = sizeof(unsigned char); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_SHORT", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_SHORT_ARRAY", valuelen) ) + { + data_type = VTK_SHORT; + size_type = sizeof(short); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_USHORT", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_USHORT_ARRAY", valuelen) ) + { + data_type = VTK_UNSIGNED_SHORT; + size_type = sizeof(unsigned short); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_INT", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_INT_ARRAY", valuelen) ) + { + data_type = VTK_INT; + size_type = sizeof(int); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_UINT", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_UINT_ARRAY", valuelen) ) + { + data_type = VTK_UNSIGNED_INT; + size_type = sizeof(unsigned int); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_LONG", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_LONG_ARRAY", valuelen) ) + { + data_type = VTK_LONG; + size_type = sizeof(long); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_ULONG", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_ULONG_ARRAY", valuelen) ) + { + data_type = VTK_UNSIGNED_LONG; + size_type = sizeof(unsigned long); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_FLOAT", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_FLOAT_ARRAY", valuelen) ) + { + data_type = VTK_FLOAT; + size_type = sizeof(float); + } + else if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_DOUBLE", valuelen) || + vtkMetaImageReaderInternal::StringEqualsCase(value, "MET_DOUBLE_ARRAY", valuelen) ) + { + data_type = VTK_DOUBLE; + size_type = sizeof(double); + } + else + { + if ( populate ) + { + vtkErrorMacro(<< "Unknown data type: " << value); + } + return 0; + } + } + else if ( vtkMetaImageReaderInternal::StringEquals(key, "ElementDataFile", keylen) ) + { + if ( vtkMetaImageReaderInternal::StringEqualsCase(value, "LOCAL", valuelen) ) + { + datafile = fname; + } + else + { + if ( value[0] == '/' || + ( value[1] == ':' && ( value[2] == '/' || value[2] == '\\' ) ) || + ( value[0] == '\\' && value[1] == '\\' ) || + path.size() == 0) + { + datafile = ""; + datafile.append(value, valuelen); + vtkDebugMacro("Use absolute path"); + } + else + { + datafile = path; + datafile += "/"; + datafile.append(value, valuelen); + vtkDebugMacro("Use relative path"); + } + + if ( stat( datafile.c_str(), &fs) ) + { + if ( populate ) + { + vtkErrorMacro(<< "Initialize: Could not open file " << datafile.c_str()); + } + return 0; + } + vtkDebugMacro(<< "* Use data file: " << datafile.c_str()); + } + } + } + else + { + if ( datafile == fname ) + { + break; + } + if ( populate ) + { + vtkErrorMacro(<< "Problem parsing line: " << count << " of file: " << fname); + } + return 0; + } + } + if ( ndims <= 0 ) + { + if ( populate ) + { + vtkErrorMacro(<< "Number of dimensions not specified"); + } + return 0; + } + int cc; + for ( cc = 0; cc < ndims; cc ++ ) + { + if ( dims[cc] <= 0 ) + { + if ( populate ) + { + vtkErrorMacro(<< "Dimension " << cc << " is " << dims[cc]); + } + return 0; + } + if ( spacing[cc] == 0 ) + { + if ( populate ) + { + vtkErrorMacro(<< "Spacing " << cc << " is 0."); + } + return 0; + } + } + for ( cc = ndims; cc < 3; cc ++ ) + { + dims[cc] = 1; + } + + if ( populate ) + { + this->DataScalarType = data_type; + //this->SetDataScalarType(data_type); + + this->SetNumberOfScalarComponents(number_of_channels); + this->SetDataExtent(0, dims[0]-1, 0, dims[1]-1, 0, dims[2]-1); + this->SetFileDimensionality(3); + this->SetDataSpacing(spacing); + this->SetDataOrigin(origin); + this->FileLowerLeftOn(); + + if ( bigendian ) + { + this->SetDataByteOrderToBigEndian(); + } + else + { + this->SetDataByteOrderToLittleEndian(); + } + + this->Superclass::SetFileName(datafile.c_str()); + } + + if ( datafile == fname ) + { + unsigned long datasize = number_of_channels * dims[0] * dims[1] * dims[2] * size_type; + unsigned long filesize = fs.st_size; + if ( filesize < datasize ) + { + if ( populate ) + { + vtkErrorMacro("File size (" << filesize << ") is less than datasize (" + << datasize << ")"); + } + return 0; + } + headerlen = filesize - datasize; + vtkDebugMacro("Read raw data from local file"); + } + else + { + vtkDebugMacro("Read raw file: " << datafile.c_str()); + } + if ( populate ) + { + this->SetHeaderSize(headerlen); + } + return 3; +} + +//---------------------------------------------------------------------------- +int vtkMetaImageReader::CanReadFile(const char* fname) +{ + return this->GetFileInformation(fname, 0); +} + +//---------------------------------------------------------------------------- +void vtkMetaImageReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "MHDFileName: " << (this->MHDFileName?this->MHDFileName:"(none)") << endl; +} diff --git a/IO/vtkMetaImageReader.h b/IO/vtkMetaImageReader.h new file mode 100644 index 0000000..89a79af --- /dev/null +++ b/IO/vtkMetaImageReader.h @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMetaImageReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMetaImageReader - read binary UNC meta image data +// .SECTION Description +// One of the formats for which a reader is already available in the toolkit is +// the MetaImage file format. This is a fairly simple yet powerful format +// consisting of a text header and a binary data section. The following +// instructions describe how you can write a MetaImage header for the data that +// you download from the BrainWeb page. +// +// The minimal structure of the MetaImage header is the following: +// +// NDims = 3 +// DimSize = 181 217 181 +// ElementType = MET_UCHAR +// ElementSpacing = 1.0 1.0 1.0 +// ElementByteOrderMSB = False +// ElementDataFile = brainweb1.raw +// +// * NDims indicate that this is a 3D image. ITK can handle images of +// arbitrary dimension. +// * DimSize indicates the size of the volume in pixels along each +// direction. +// * ElementType indicate the primitive type used for pixels. In this case +// is "unsigned char", implying that the data is digitized in 8 bits / +// pixel. +// * ElementSpacing indicates the physical separation between the center of +// one pixel and the center of the next pixel along each direction in space. +// The units used are millimeters. +// * ElementByteOrderMSB indicates is the data is encoded in little or big +// endian order. You might want to play with this value when moving data +// between different computer platforms. +// * ElementDataFile is the name of the file containing the raw binary data +// of the image. This file must be in the same directory as the header. +// +// MetaImage headers are expected to have extension: ".mha" or ".mhd" +// +// Once you write this header text file, it should be possible to read the +// image into your ITK based application using the itk::FileIOToImageFilter +// class. + +// .SECTION Caveats +// + +// .SECTION See Also +// vtkImageReader + +#ifndef __vtkMetaImageReader_h +#define __vtkMetaImageReader_h + +#include "vtkImageReader.h" + +class VTK_IO_EXPORT vtkMetaImageReader : public vtkImageReader +{ +public: + vtkTypeRevisionMacro(vtkMetaImageReader,vtkImageReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with FlipNormals turned off and Normals set to true. + static vtkMetaImageReader *New(); + + // Description: + // Specify file name of meta file + virtual void SetFileName(const char* fname); + virtual char* GetFileName() { return this->MHDFileName; } + + // Description: + // Test whether the file with the given name can be read by this + // reader. + virtual int CanReadFile(const char* name); + +protected: + vtkMetaImageReader(); + ~vtkMetaImageReader(); + + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + int GetFileInformation(const char* fname, int populate); + + vtkSetStringMacro(MHDFileName); + char* MHDFileName; + +private: + vtkMetaImageReader(const vtkMetaImageReader&); // Not implemented. + void operator=(const vtkMetaImageReader&); // Not implemented. +}; + +#endif + + + diff --git a/IO/vtkMetaImageWriter.cxx b/IO/vtkMetaImageWriter.cxx new file mode 100644 index 0000000..f7322e5 --- /dev/null +++ b/IO/vtkMetaImageWriter.cxx @@ -0,0 +1,214 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMetaImageWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMetaImageWriter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkDataSetAttributes.h" + +#include + +#include + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkMetaImageWriter, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkMetaImageWriter); + +//---------------------------------------------------------------------------- +vtkMetaImageWriter::vtkMetaImageWriter() +{ + this->MHDFileName = 0; + this->FileLowerLeft = 1; +} + +//---------------------------------------------------------------------------- +vtkMetaImageWriter::~vtkMetaImageWriter() +{ + this->SetFileName(0); +} + +//---------------------------------------------------------------------------- +void vtkMetaImageWriter::SetFileName(const char* fname) +{ + this->SetMHDFileName(fname); +} + +//---------------------------------------------------------------------------- +void vtkMetaImageWriter::SetRAWFileName(const char* fname) +{ + this->Superclass::SetFileName(fname); +} + +//---------------------------------------------------------------------------- +char* vtkMetaImageWriter::GetRAWFileName() +{ + return this->Superclass::GetFileName(); +} + +//---------------------------------------------------------------------------- +int vtkMetaImageWriter::RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *input = + vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // Error checking + if (input == NULL ) + { + vtkErrorMacro(<<"Write:Please specify an input!"); + return 0; + } + + if ( !this->MHDFileName ) + { + vtkErrorMacro("Output file name not specified"); + return 0; + } + + if ( !this->GetRAWFileName() ) + { + vtkDebugMacro("Raw file name not specified. Specifying one..."); + // Allocate new file name and leave space for extension + char* rfname = new char [ strlen(this->MHDFileName) + 10 ]; + strcpy(rfname, this->MHDFileName); + size_t cc; + for ( cc = strlen(rfname)-1; cc > 0; cc -- ) + { + if ( rfname[cc] == '.' ) + { + rfname[cc] = 0; + break; + } + if ( rfname[cc] == '/' || rfname[cc] == '\\' ) + { + break; + } + } + strcat(rfname, ".raw"); + if ( strcmp(rfname, this->MHDFileName) == 0 ) + { + strcat(rfname, ".raw"); + } + this->SetRAWFileName(rfname); + delete [] rfname; + } + + ofstream ofs_with_warning_C4701(this->MHDFileName, ios::out); + if ( !ofs_with_warning_C4701 ) + { + vtkErrorMacro("Cannot open file: " << this->MHDFileName << " for writing"); + return 0; + } + + int ndims = 3; + int ext[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext); + if ( ext[4] == ext[5] ) + { + ndims = 2; + if ( ext[2] == ext[3] ) + { + ndims = 1; + } + } + double origin[3]; + double spacing[3]; + inInfo->Get(vtkDataObject::ORIGIN(),origin); + inInfo->Get(vtkDataObject::SPACING(),spacing); + + const char* scalar_type; + vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!scalarInfo) + { + vtkErrorMacro( "No active scalar information!" ); + return 0; + } + switch ( scalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) ) + { + case VTK_CHAR: scalar_type = "MET_CHAR"; break; + case VTK_UNSIGNED_CHAR: scalar_type = "MET_UCHAR"; break; + case VTK_SHORT: scalar_type = "MET_SHORT"; break; + case VTK_UNSIGNED_SHORT: scalar_type = "MET_USHORT"; break; + case VTK_INT: scalar_type = "MET_INT"; break; + case VTK_UNSIGNED_INT: scalar_type = "MET_UINT"; break; + case VTK_LONG: scalar_type = "MET_LONG"; break; + case VTK_UNSIGNED_LONG: scalar_type = "MET_ULONG"; break; + case VTK_FLOAT: scalar_type = "MET_FLOAT"; break; + case VTK_DOUBLE: scalar_type = "MET_DOUBLE"; break; + default: + vtkErrorMacro("Unknown scalar type: " + << scalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE())); + return 1; + } + + origin[0] += ext[0] * spacing[0]; + origin[1] += ext[2] * spacing[1]; + origin[2] += ext[4] * spacing[2]; + + const char* data_file = this->GetRAWFileName(); + int pos = 0; + int cc; + for ( cc = 0; data_file[cc]; cc ++ ) + { + if ( data_file[cc] == '/' || data_file[cc] == '\\' ) + { + pos = cc; + } + } + if ( pos > 0 ) + { + if ( strncmp(data_file, this->GetFileName(), pos) == 0 ) + { + data_file = this->GetRAWFileName() + pos + 1; + } + } + + ofs_with_warning_C4701 + << "ObjectType = Image" << endl + << "NDims = " << ndims << endl + << "BinaryData = True" << endl +#ifdef VTK_WORDS_BIGENDIAN + << "BinaryDataByteOrderMSB = True" << endl +#else + << "BinaryDataByteOrderMSB = False" << endl +#endif + << "ElementSpacing = " + << spacing[0] << " " << spacing[1] << " " << spacing[2] << endl + << "DimSize = " << (ext[1]-ext[0]+1) << " " + << (ext[3]-ext[2]+1) << " " << (ext[5]-ext[4]+1) << endl + << "Position = " + << origin[0] << " " << origin[1] << " " << origin[2] << endl + << "ElementNumberOfChannels = " + << scalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()) << endl + << "ElementType = " << scalar_type + << (scalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()) > 1?"_ARRAY":"") << endl + << "ElementDataFile = " << data_file << endl; + this->SetFileDimensionality(ndims); + return this->Superclass::RequestData(request,inputVector,outputVector); +} + +//---------------------------------------------------------------------------- +void vtkMetaImageWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "MHDFileName: " << (this->MHDFileName?this->MHDFileName:"(none)") << endl; +} diff --git a/IO/vtkMetaImageWriter.h b/IO/vtkMetaImageWriter.h new file mode 100644 index 0000000..1815935 --- /dev/null +++ b/IO/vtkMetaImageWriter.h @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMetaImageWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMetaImageWriter - write a binary UNC meta image data +// .SECTION Description +// One of the formats for which a reader is already available in the toolkit is +// the MetaImage file format. This is a fairly simple yet powerful format +// consisting of a text header and a binary data section. The following +// instructions describe how you can write a MetaImage header for the data that +// you download from the BrainWeb page. +// +// The minimal structure of the MetaImage header is the following: +// +// NDims = 3 +// DimSize = 181 217 181 +// ElementType = MET_UCHAR +// ElementSpacing = 1.0 1.0 1.0 +// ElementByteOrderMSB = False +// ElementDataFile = brainweb1.raw +// +// * NDims indicate that this is a 3D image. ITK can handle images of +// arbitrary dimension. +// * DimSize indicates the size of the volume in pixels along each +// direction. +// * ElementType indicate the primitive type used for pixels. In this case +// is "unsigned char", implying that the data is digitized in 8 bits / +// pixel. +// * ElementSpacing indicates the physical separation between the center of +// one pixel and the center of the next pixel along each direction in space. +// The units used are millimeters. +// * ElementByteOrderMSB indicates is the data is encoded in little or big +// endian order. You might want to play with this value when moving data +// between different computer platforms. +// * ElementDataFile is the name of the file containing the raw binary data +// of the image. This file must be in the same directory as the header. +// +// MetaImage headers are expected to have extension: ".mha" or ".mhd" +// +// Once you write this header text file, it should be possible to read the +// image into your ITK based application using the itk::FileIOToImageFilter +// class. + +// .SECTION Caveats +// + +// .SECTION See Also +// vtkImageWriter vtkMetaImageReader + +#ifndef __vtkMetaImageWriter_h +#define __vtkMetaImageWriter_h + +#include "vtkImageWriter.h" + +class VTK_IO_EXPORT vtkMetaImageWriter : public vtkImageWriter +{ +public: + vtkTypeRevisionMacro(vtkMetaImageWriter,vtkImageWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with FlipNormals turned off and Normals set to true. + static vtkMetaImageWriter *New(); + + // Description: + // Specify file name of meta file + virtual void SetFileName(const char* fname); + virtual char* GetFileName() { return this->MHDFileName; } + + // Description: + // Specify the file name of the raw image data. + virtual void SetRAWFileName(const char* fname); + virtual char* GetRAWFileName(); + + // This is called by the superclass. + // This is the method you should override. + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +protected: + vtkMetaImageWriter(); + ~vtkMetaImageWriter(); + + vtkSetStringMacro(MHDFileName); + char* MHDFileName; + +private: + vtkMetaImageWriter(const vtkMetaImageWriter&); // Not implemented. + void operator=(const vtkMetaImageWriter&); // Not implemented. +}; + +#endif + + + diff --git a/IO/vtkMoleculeReaderBase.cxx b/IO/vtkMoleculeReaderBase.cxx new file mode 100644 index 0000000..9c3a1ec --- /dev/null +++ b/IO/vtkMoleculeReaderBase.cxx @@ -0,0 +1,531 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMoleculeReaderBase.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMoleculeReaderBase.h" + +#include "vtkCellArray.h" +#include "vtkCellType.h" +#include "vtkDataArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkUnsignedCharArray.h" + +#include + +vtkCxxRevisionMacro(vtkMoleculeReaderBase, "$Revision: 1.17 $"); + +static double vtkMoleculeReaderBaseCovRadius[103] = { +0.32 , 1.6 , 0.68 , 0.352 , 0.832 , 0.72 , +0.68 , 0.68 , 0.64 , 1.12 , 0.972 , 1.1 , 1.352 , 1.2 , 1.036 , +1.02 , 1 , 1.568 , 1.328 , 0.992 , 1.44 , 1.472 , 1.328 , 1.352 , +1.352 , 1.34 , 1.328 , 1.62 , 1.52 , 1.448 , 1.22 , 1.168 , 1.208 , +1.22 , 1.208 , 1.6 , 1.472 , 1.12 , 1.78 , 1.56 , 1.48 , 1.472 , +1.352 , 1.4 , 1.448 , 1.5 , 1.592 , 1.688 , 1.632 , 1.46 , 1.46 , +1.472 , 1.4 , 1.7 , 1.672 , 1.34 , 1.872 , 1.832 , 1.82 , 1.808 , +1.8 , 1.8 , 1.992 , 1.792 , 1.76 , 1.752 , 1.74 , 1.728 , 1.72 , +1.94 , 1.72 , 1.568 , 1.432 , 1.368 , 1.352 , 1.368 , 1.32 , 1.5 , +1.5 , 1.7 , 1.552 , 1.54 , 1.54 , 1.68 , 1.208 , 1.9 , 1.8 , +1.432 , 1.18 , 1.02 , 0.888 , 0.968 , 0.952 , 0.928 , 0.92 , 0.912 , +0.9 , 0.888 , 0.88 , 0.872 , 0.86 , 0.848 , 0.84 }; + +static double vtkMoleculeReaderBaseAtomColors[][3] = { + {255, 255, 255}, {127, 0, 127}, {255, 0, 255}, + {127, 127, 127}, {127, 0, 127}, {0, 255, 0}, + {0, 0, 255}, {255, 0, 0}, {0, 255, 255}, + {127, 127, 127}, {127, 127, 127}, {178, 153, 102}, + {127, 127, 127}, {51, 127, 229}, {0, 255, 255}, + {255, 255, 0}, {255, 127, 127}, {255, 255, 127}, + {127, 127, 127}, {51, 204, 204}, {127, 127, 127}, + {0, 178, 178}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {204, 0, 255}, {255, 0, 255}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {229, 102, 51}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 255, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {102, 51, 204}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {51, 127, 51}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127}, {127, 127, 127}, + {127, 127, 127}, {127, 127, 127} +}; + +static double vtkMoleculeReaderBaseRadius[] = { + 1.2, 1.22, 1.75, /* "H " "He" "Li" */ + 1.50, 1.90, 1.80, /* "Be" "B " "C " */ + 1.70, 1.60, 1.35, /* "N " "O " "F " */ + 1.60, 2.31, 1.70, + 2.05, 2.00, 2.70, + 1.85, 1.81, 1.91, + 2.31, 1.74, 1.80, + 1.60, 1.50, 1.40, /* Ti-Cu and Ge are guestimates. */ + 1.40, 1.40, 1.40, + 1.60, 1.40, 1.40, + 1.90, 1.80, 2.00, + 2.00, 1.95, 1.98, + 2.44, 2.40, 2.10, /* Sr-Rh and Ba and La are guestimates. */ + 2.00, 1.80, 1.80, + 1.80, 1.80, 1.80, + 1.60, 1.70, 1.60, + 1.90, 2.20, 2.20, + 2.20, 2.15, 2.20, + 2.62, 2.30, 2.30, + 2.30, 2.30, 2.30, /* All of these are guestimates. */ + 2.30, 2.30, 2.40, + 2.30, 2.30, 2.30, + 2.30, 2.30, 2.30, + 2.40, 2.50, 2.30, + 2.30, 2.30, 2.30, /* All but Pt and Bi are guestimates. */ + 2.30, 2.30, 2.40, + 2.30, 2.40, 2.50, + 2.50, 2.40, 2.40, + 2.40, 2.40, 2.90, + 2.60, 2.30, 2.30, /* These are all guestimates. */ + 2.30, 2.30, 2.30, + 2.30, 2.30, 2.30, + 2.30, 2.30, 2.30, + 2.30, 2.30, 2.30, + 2.30, 1.50 } ; + +vtkMoleculeReaderBase::vtkMoleculeReaderBase() +{ + this->FileName = NULL; + this->BScale = 1.0; + this->HBScale = 1.0; + this->AtomType = NULL; + this->Points = NULL; + this->RGB = NULL; + this->Radii = NULL; + this->NumberOfAtoms = 0; + + this->SetNumberOfInputPorts(0); +} + +vtkMoleculeReaderBase::~vtkMoleculeReaderBase() +{ + if (this->FileName) + { + delete [] this->FileName; + } + if(this->AtomType) + { + this->AtomType->Delete(); + } + if(this->Points) + { + this->Points->Delete(); + } + if(this->RGB) + { + this->RGB->Delete(); + } + if(this->Radii) + { + this->Radii->Delete(); + } +} + +int vtkMoleculeReaderBase::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + FILE *fp; + + if (!this->FileName) + { + return 0; + } + + if ((fp = fopen(this->FileName, "r")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return 0; + } + vtkDebugMacro(<< "opening base file " << this->FileName); + this->ReadMolecule(fp, output); + fclose(fp); + + output->Squeeze(); + + return 1; +} + +int vtkMoleculeReaderBase::ReadMolecule(FILE *fp, vtkPolyData *output) +{ + int i; + vtkCellArray *newBonds; + + vtkDebugMacro(<< "Scanning the Molecule file"); + + if ( !this->AtomType ) + { + this->AtomType = vtkIdTypeArray::New(); + } + else + { + this->AtomType->Reset(); + } + + if ( !this->Points ) + { + this->Points = vtkPoints::New(); + } + else + { + this->Points->Reset(); + } + + this->ReadSpecificMolecule(fp); + + vtkDebugMacro(<< "End of scanning"); + output->SetPoints(this->Points); + + newBonds = vtkCellArray::New(); + newBonds->Allocate(500); + + this->MakeBonds(this->Points, this->AtomType, newBonds); + + output->SetLines(newBonds); + newBonds->Delete(); + + vtkDebugMacro(<< "read " << this->NumberOfAtoms << " atoms and found " + << newBonds->GetNumberOfCells() << " bonds" << endl); + + if ( this->RGB ) + { + this->RGB->Reset(); + } + else + { + this->RGB = vtkUnsignedCharArray::New(); + } + this->RGB->SetNumberOfComponents(3); +// this->RGB->SetNumberOfTuples(this->NumberOfAtoms); + this->RGB->Allocate(3*this->NumberOfAtoms); + this->RGB->SetName("rgb_colors"); + + for(i=0; i < this->NumberOfAtoms; i++) + { + this->RGB->InsertNextTuple( + &vtkMoleculeReaderBaseAtomColors[AtomType->GetValue(i)][0]); + } + + output->GetPointData()->SetScalars(this->RGB); + + if ( this->Radii ) + { + this->Radii->Reset(); + } + else + { + this->Radii = vtkFloatArray::New(); + } + this->Radii->SetNumberOfComponents(3); + // this->Radii->SetNumberOfTuples(this->NumberOfAtoms); + this->Radii->Allocate(3 * this->NumberOfAtoms); + this->Radii->SetName("radius"); + + // We're obliged here to insert the scalars "radius" 3 times to make it a + // vector in order to use Glyph3D to color AND scale at the same time. + + for(i=0; i < this->NumberOfAtoms; i++) + { + this->Radii->InsertNextTuple3( + vtkMoleculeReaderBaseRadius[AtomType->GetValue(i)], + vtkMoleculeReaderBaseRadius[AtomType->GetValue(i)], + vtkMoleculeReaderBaseRadius[AtomType->GetValue(i)]); + } + + output->GetPointData()->SetVectors(this->Radii); + + return 0; +} + +int vtkMoleculeReaderBase::MakeBonds(vtkPoints *newPts, + vtkIdTypeArray *atype, + vtkCellArray *newBonds) +{ + register int i, j; + register int nbonds; + register double dx, dy, dz; + double max, dist; + double X[3], Y[3]; + vtkIdType bond[2]; + + nbonds = 0; + for(i = this->NumberOfAtoms - 1; i > 0; i--) + { + bond[0] = i; + newPts->GetPoint(i, X); + for(j = i - 1; j >= 0 ; j--) + { + /* + * The outer loop index 'i' is AFTER the inner loop 'j': 'i' + * leads 'j' in the list: since hydrogens traditionally follow + * the heavy atom they're bonded to, this makes it easy to quit + * bonding to hydrogens after one bond is made by breaking out of + * the 'j' loop when 'i' is a hydrogen and we make a bond to it. + * Working backwards like this makes it easy to find the heavy + * atom that came 'just before' the Hydrogen. mp + * Base distance criteria on vdw...lb + */ + + /* never bond hydrogens to each other... */ + if (atype->GetValue(i) == 0 && atype->GetValue(j) == 0) + { + continue; + } + + dist = vtkMoleculeReaderBaseCovRadius[atype->GetValue(i)] + + vtkMoleculeReaderBaseCovRadius[atype->GetValue(j)] + 0.56; + max = dist*dist; + + if(atype->GetValue(i) == 0 || atype->GetValue(j) == 0) + { + max *= HBScale; + } + else + { + max *= BScale; + } + + newPts->GetPoint(j, Y); + dx = X[0] - Y[0]; + dist = dx * dx; + + if(dist > max ) + { + continue; + } + + dy = X[1] - Y[1]; + dist += dy * dy; + if(dist > max ) + { + continue; + } + + dz = X[2] - Y[2]; + dist += dz * dz; + if(dist > max ) + { + continue; + } + + bond[1] = j; + newBonds->InsertNextCell(2, bond); + + nbonds++; + } + } + newBonds-> Squeeze(); + return nbonds; +} + +int vtkMoleculeReaderBase::MakeAtomType(const char *atype) +{ + char a, b; + int anum=0; + + a = atype[0]; + if (islower(a)) + { + a = toupper(a); + } + b = atype[1]; + if (islower(b)) + { + b = toupper(b); + } + switch (a) + { + case 'A': + if(b == 'C') anum = 89; + else if(b == 'G') anum = 47; + else if(b == 'L') anum = 13; + else if(b == 'M') anum = 95; + else if(b == 'R') anum = 18; + else if(b == 'S') anum = 33; + else if(b == 'T') anum = 85; + else if(b == 'U') anum = 79; + break; + case 'B': + if(b == 'A') anum = 56; + else if(b == 'E') anum = 4; + else if(b == 'I') anum = 83; + else if(b == 'K') anum = 97; + else if(b == 'R') anum = 35; + else anum = 5; + break; + case 'C': + if(b == 'L') anum = 17; + else if(b == 'O') anum = 27; + else if(b == 'R') anum = 24; + else if(b == 'S') anum = 55; + else if(b == 'U') anum = 29; + else if(b == '0') anum = 6; + else anum = 6; + break; + case 'D': + anum = 66; + break; + case 'E': + if(b == 'R') anum = 68; + else if(b == 'S') anum = 99; + else if(b == 'U') anum = 63; + break; + case 'F': + if(b == 'E') anum = 26; + else if(b == 'M') anum = 100; + else if(b == 'R') anum = 87; + else anum = 9; + break; + case 'G': + if(b == 'A') anum = 31; + else if(b == 'D') anum = 64; + else if(b == 'E') anum = 32; + break; + case 'H': + anum = 1; + break; + case 'I': + if(b == 'N') anum = 49; + else if(b == 'R') anum = 77; + else anum = 53; + break; + case 'K': + if(b == 'R') anum = 36; + else anum = 19; + break; + case 'L': + if(b == 'A') anum = 57; + else if(b == 'I') anum = 3; + else if(b == 'R') anum = 103; + else if(b == 'U') anum = 71; + break; + case 'M': + if(b == 'D') anum = 101; + else if(b == 'G') anum = 12; + else if(b == 'N') anum = 25; + else if(b == 'O') anum = 42; + break; + case 'N': + if(b == 'I') anum = 28; + else anum = 7; + break; + case 'O': + anum = 8; + break; + case 'P': + if(b == 'A') anum = 91; + else if(b == 'B') anum = 82; + else if(b == 'D') anum = 46; + else if(b == 'M') anum = 61; + else if(b == 'O') anum = 84; + else if(b == 'R') anum = 59; + else if(b == 'T') anum = 78; + else if(b == 'U') anum = 94; + else anum = 15; + break; + case 'R': + if(b == 'A') anum = 88; + else if(b == 'B') anum = 37; + else if(b == 'E') anum = 75; + else if(b == 'H') anum = 45; + else if(b == 'N') anum = 86; + else if(b == 'U') anum = 44; + break; + case 'S': + if(b == 'I') anum = 14; + else if(b == 'R') anum = 38; + else anum = 16; + break; + case 'T': + if(b == 'A') anum = 73; + else if(b == 'B') anum = 65; + else if(b == 'C') anum = 43; + else if(b == 'E') anum = 52; + else if(b == 'H') anum = 90; + else if(b == 'I') anum = 22; + else if(b == 'L') anum = 81; + else if(b == 'M') anum = 69; + break; + case 'U': + anum = 92; + break; + case 'V': + anum = 23; + break; + case 'W': + anum = 74; + break; + case 'X': + anum = 54; + break; + case 'Y': + if(b == 'B') anum = 70; + else anum = 39; + break; + case 'Z': + if(b == 'N') anum = 30; + else anum = 40; + break; + case ' ': + anum = 104; + break; + default: + anum = 6; + break; + } + return (anum-1); +} + +void vtkMoleculeReaderBase::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << endl; + os << indent << "NumberOfAtoms: " << this->NumberOfAtoms << endl; + os << indent << "HBScale: " << this->HBScale << endl; + os << indent << "BScale: " << this->BScale << endl; +} diff --git a/IO/vtkMoleculeReaderBase.h b/IO/vtkMoleculeReaderBase.h new file mode 100644 index 0000000..fddc20b --- /dev/null +++ b/IO/vtkMoleculeReaderBase.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMoleculeReaderBase.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMoleculeReaderBase - read Molecular Data files +// .SECTION Description +// vtkMoleculeReaderBase is a source object that reads Molecule files +// The FileName must be specified +// +// .SECTION Thanks +// Dr. Jean M. Favre who developed and contributed this class + +#ifndef __vtkMoleculeReaderBase_h +#define __vtkMoleculeReaderBase_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkFloatArray; +class vtkDataArray; +class vtkIdTypeArray; +class vtkUnsignedCharArray; +class vtkPoints; + +class VTK_IO_EXPORT vtkMoleculeReaderBase : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkMoleculeReaderBase,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + vtkSetMacro(BScale, double); + vtkGetMacro(BScale, double); + + vtkSetMacro(HBScale, double); + vtkGetMacro(HBScale, double); + + vtkGetMacro(NumberOfAtoms, int); + +protected: + vtkMoleculeReaderBase(); + ~vtkMoleculeReaderBase(); + + char *FileName; + double BScale; + // a scaling factor to compute bonds between non-hydrogen atoms + double HBScale; + // a scaling factor to compute bonds with hydrogen atoms + int NumberOfAtoms; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int ReadMolecule(FILE *fp, vtkPolyData *output); + int MakeAtomType(const char *atype); + int MakeBonds(vtkPoints*, vtkIdTypeArray*, vtkCellArray*); + + vtkPoints *Points; + vtkUnsignedCharArray *RGB; + vtkFloatArray *Radii; + vtkIdTypeArray *AtomType; + + virtual void ReadSpecificMolecule(FILE* fp) = 0; + +private: + vtkMoleculeReaderBase(const vtkMoleculeReaderBase&); // Not implemented. + void operator=(const vtkMoleculeReaderBase&); // Not implemented. +}; + +#endif diff --git a/IO/vtkMultiBlockPLOT3DReader.cxx b/IO/vtkMultiBlockPLOT3DReader.cxx new file mode 100644 index 0000000..f608dd8 --- /dev/null +++ b/IO/vtkMultiBlockPLOT3DReader.cxx @@ -0,0 +1,2108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiBlockPLOT3DReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMultiBlockPLOT3DReader.h" + +#include "vtkByteSwap.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkUnsignedCharArray.h" + +#include "vtkSmartPointer.h" +#include + +vtkCxxRevisionMacro(vtkMultiBlockPLOT3DReader, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkMultiBlockPLOT3DReader); + +#define VTK_RHOINF 1.0 +#define VTK_CINF 1.0 +#define VTK_PINF ((VTK_RHOINF*VTK_CINF) * (VTK_RHOINF*VTK_CINF) / this->Gamma) +#define VTK_CV (this->R / (this->Gamma-1.0)) + +struct vtkMultiBlockPLOT3DReaderInternals +{ + vtkstd::vector > Blocks; +}; + +vtkMultiBlockPLOT3DReader::vtkMultiBlockPLOT3DReader() +{ + this->XYZFileName = NULL; + this->QFileName = NULL; + this->BinaryFile = 1; + this->HasByteCount = 0; + this->FileSize = 0; + this->MultiGrid = 0; + this->ForceRead = 0; + this->ByteOrder = FILE_BIG_ENDIAN; + this->IBlanking = 0; + this->TwoDimensionalGeometry = 0; + + this->R = 1.0; + this->Gamma = 1.4; + this->Uvinf = 0.0; + this->Vvinf = 0.0; + this->Wvinf = 0.0; + + this->FunctionList = vtkIntArray::New(); + + this->ScalarFunctionNumber = -1; + this->SetScalarFunctionNumber(100); + this->VectorFunctionNumber = -1; + this->SetVectorFunctionNumber(202); + + this->PointCache = 0; + this->IBlankCache = 0; + + this->SetNumberOfInputPorts(0); + + this->Internal = new vtkMultiBlockPLOT3DReaderInternals; +} + +vtkMultiBlockPLOT3DReader::~vtkMultiBlockPLOT3DReader() +{ + delete [] this->XYZFileName; + delete [] this->QFileName; + this->FunctionList->Delete(); + this->ClearGeometryCache(); + + delete this->Internal; +} + +void vtkMultiBlockPLOT3DReader::ClearGeometryCache() +{ + if ( this->PointCache ) + { + for ( int g=0; this->PointCache[g]; ++g ) + this->PointCache[g]->UnRegister( this ); + + delete [] this->PointCache; + this->PointCache = 0; + } + + if ( this->IBlankCache ) + { + for ( int i=0; this->IBlankCache[i]; ++i ) + this->IBlankCache[i]->UnRegister( this ); + + delete [] this->IBlankCache; + this->IBlankCache = 0; + } +} + +int vtkMultiBlockPLOT3DReader::CheckFile(FILE*& fp, const char* fname) +{ + if (this->BinaryFile) + { + fp = fopen(fname, "rb"); + } + else + { + fp = fopen(fname, "r"); + } + if ( fp == NULL) + { + this->SetErrorCode(vtkErrorCode::FileNotFoundError); + vtkErrorMacro(<< "File: " << fname << " not found."); + return VTK_ERROR; + } + return VTK_OK; +} + +int vtkMultiBlockPLOT3DReader::CheckGeometryFile(FILE*& xyzFp) +{ + if ( this->XYZFileName == NULL || this->XYZFileName[0] == '\0' ) + { + this->SetErrorCode(vtkErrorCode::NoFileNameError); + vtkErrorMacro(<< "Must specify geometry file"); + return VTK_ERROR; + } + return this->CheckFile(xyzFp, this->XYZFileName); +} + +int vtkMultiBlockPLOT3DReader::CheckSolutionFile(FILE*& qFp) +{ + if ( this->QFileName == NULL || this->QFileName[0] == '\0' ) + { + this->SetErrorCode(vtkErrorCode::NoFileNameError); + vtkErrorMacro(<< "Must specify geometry file"); + return VTK_ERROR; + } + return this->CheckFile(qFp, this->QFileName); +} + +// Skip Fortran style byte count. +void vtkMultiBlockPLOT3DReader::SkipByteCount(FILE* fp) +{ + if (this->BinaryFile && this->HasByteCount) + { + int tmp; + fread(&tmp, sizeof(int), 1, fp); + } +} + +// Read a block of ints (ascii or binary) and return number read. +int vtkMultiBlockPLOT3DReader::ReadIntBlock(FILE* fp, int n, int* block) +{ + if (this->BinaryFile) + { + int retVal=static_cast(fread(block, sizeof(int), n, fp)); + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + return retVal; + } + else + { + int count = 0; + for(int i=0; i 0 ) + { + count++; + } + else + { + return 0; + } + } + return count; + } +} + +int vtkMultiBlockPLOT3DReader::ReadFloatBlock(FILE* fp, int n, float* block) +{ + if (this->BinaryFile) + { + int retVal=static_cast(fread(block, sizeof(float), n, fp)); + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + return retVal; + } + else + { + int count = 0; + for(int i=0; i 0 ) + { + count++; + } + else + { + return 0; + } + } + return count; + } +} + +// Read a block of floats (ascii or binary) and return number read. +void vtkMultiBlockPLOT3DReader::CalculateFileSize(FILE* fp) +{ + long curPos = ftell(fp); + fseek(fp, 0, SEEK_END); + this->FileSize = ftell(fp); + fseek(fp, curPos, SEEK_SET); +} + + +// Estimate the size of a grid (binary file only) +long vtkMultiBlockPLOT3DReader::EstimateSize(int ni, int nj, int nk) +{ + long size; // the header portion, 3 ints + if (!this->TwoDimensionalGeometry) + { + size = 3*4; + size += ni*nj*nk*3*4; // x, y, z + } + else + { + size = 2*4; + size += ni*nj*nk*2*4; // x, y, z + } + if (this->HasByteCount) + { + size += 2*4; // the byte counts + } + if (this->IBlanking) + { + size += ni*nj*nk*4; + } + + return size; +} + +int vtkMultiBlockPLOT3DReader::CanReadBinaryFile(const char* fname) +{ + FILE* xyzFp; + + if (!fname || fname[0] == '\0') + { + return 0; + } + + if ( this->CheckFile(xyzFp, fname) != VTK_OK) + { + return 0; + } + + this->CalculateFileSize(xyzFp); + + int numBlocks = this->GetNumberOfBlocksInternal(xyzFp, 1); + fclose(xyzFp); + if (numBlocks != 0) + { + return 1; + } + return 0; +} + +int vtkMultiBlockPLOT3DReader::GetNumberOfBlocks() +{ + FILE* xyzFp; + + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return 0; + } + this->CalculateFileSize(xyzFp); + int numBlocks = this->GetNumberOfBlocksInternal(xyzFp, 1); + fclose(xyzFp); + if (numBlocks != 0) + { + return numBlocks; + } + return 1; +} + +int vtkMultiBlockPLOT3DReader::GenerateDefaultConfiguration() +{ + FILE* xyzFp; + + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return 0; + } + char buf[1024]; + fread(buf, 1, 1024, xyzFp); + int retVal = this->VerifySettings(buf, 1024); + fclose(xyzFp); + return retVal; +} + +void vtkMultiBlockPLOT3DReader::ReadIntBlockV(char** buf, int n, int* block) +{ + memcpy(block, *buf, sizeof(int)*n); + + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + *buf += sizeof(int); +} + +void vtkMultiBlockPLOT3DReader::SkipByteCountV(char** buf) +{ + if (this->HasByteCount) + { + *buf += sizeof(int); + } +} + +int vtkMultiBlockPLOT3DReader::VerifySettings(char* buf, int vtkNotUsed(bufSize)) +{ + int numGrid=0; + + if ( this->MultiGrid ) + { + this->SkipByteCountV(&buf); + this->ReadIntBlockV(&buf, 1, &numGrid); + this->SkipByteCountV(&buf); + } + else + { + numGrid=1; + } + + int retVal=1; + + long fileSize = 0; + // Size of number of grids information. + if ( this->MultiGrid ) + { + fileSize += 4; // numGrids + if (this->HasByteCount) + { + fileSize += 4*4; // byte counts for the header + } + } + + // Add the size of each grid. + this->SkipByteCountV(&buf); + for(int i=0; iReadIntBlockV(&buf, 1, &ni); + this->ReadIntBlockV(&buf, 1, &nj); + if (!this->TwoDimensionalGeometry) + { + this->ReadIntBlockV(&buf, 1, &nk); + } + else + { + nk = 1; + } + fileSize += this->EstimateSize(ni, nj, nk); + // If this number is larger than the file size, there + // is something wrong. + if ( fileSize > this->FileSize ) + { + retVal = 0; + break; + } + } + this->SkipByteCountV(&buf); + // If this number is different than the file size, there + // is something wrong. + if ( fileSize != this->FileSize ) + { + retVal = 0; + } + + return retVal; +} + +// Read the header and return the number of grids. +int vtkMultiBlockPLOT3DReader::GetNumberOfBlocksInternal(FILE* xyzFp, int verify) +{ + int numGrid=0; + int numBlocks; + + if ( this->MultiGrid ) + { + this->SkipByteCount(xyzFp); + this->ReadIntBlock(xyzFp, 1, &numGrid); + this->SkipByteCount(xyzFp); + } + else + { + numGrid=1; + } + + if (!verify) + { + // We were told not the verify the number of grid. Just return it. + numBlocks = numGrid; + } + else + { + // We were told to make sure that the file can really contain + // the number of grid in the header (we can only check this + // if file is binary) + int error=0; + if ( this->BinaryFile ) + { + // Store the beginning of first grid. + long pos = ftell(xyzFp); + + long fileSize = 0; + // Size of number of grids information. + if ( this->MultiGrid ) + { + fileSize += 4; // numGrids + if (this->HasByteCount) + { + fileSize += 4*4; // byte counts for the header + } + } + // Add the size of each grid. + this->SkipByteCount(xyzFp); + for(int i=0; iReadIntBlock(xyzFp, 1, &ni); + this->ReadIntBlock(xyzFp, 1, &nj); + if (!this->TwoDimensionalGeometry) + { + this->ReadIntBlock(xyzFp, 1, &nk); + } + else + { + nk = 1; + } + fileSize += this->EstimateSize(ni, nj, nk); + // If this number is larger than the file size, there + // is something wrong. + if ( fileSize > this->FileSize ) + { + error = 1; + break; + } + } + this->SkipByteCount(xyzFp); + // If this number is different than the file size, there + // is something wrong. + if ( fileSize != this->FileSize && !this->ForceRead) + { + this->SetErrorCode(vtkErrorCode::FileFormatError); + error = 1; + } + + fseek(xyzFp, pos, SEEK_SET); + } + else + { + if (numGrid == 0) + { + this->SetErrorCode(vtkErrorCode::FileFormatError); + } + } + + // Now set the number of blocks. + if (!error && numGrid != 0) + { + if ( numGrid > (int)this->Internal->Blocks.size() ) + { + this->Internal->Blocks.resize(numGrid); + } + for (int i=0; iInternal->Blocks[i]) + { + vtkStructuredGrid* sg = vtkStructuredGrid::New(); + this->Internal->Blocks[i] = sg; + sg->Delete(); + } + } + numBlocks = numGrid; + } + else + { + numBlocks = 0; + } + } + + return numBlocks; +} + +int vtkMultiBlockPLOT3DReader::ReadGeometryHeader(FILE* fp) +{ + int numGrid = this->GetNumberOfBlocksInternal(fp, 1); + int numBlocks = this->Internal->Blocks.size(); + int i; + vtkDebugMacro("Geometry number of grids: " << numGrid); + if ( numGrid == 0 ) + { + // Bad file, set all extents to invalid. + for (i=0; iInternal->Blocks[i]->SetWholeExtent(0, -1, 0, -1, 0, -1); + } + return VTK_ERROR; + } + + // Read and set extents of all blocks. + this->SkipByteCount(fp); + for(i=0; iReadIntBlock(fp, 1, &ni); + this->ReadIntBlock(fp, 1, &nj); + if (!this->TwoDimensionalGeometry) + { + this->ReadIntBlock(fp, 1, &nk); + } + else + { + nk = 1; + } + vtkDebugMacro("Geometry, block " << i << " dimensions: " + << ni << " " << nj << " " << nk); + this->Internal->Blocks[i]->SetWholeExtent( + 0, ni-1, 0, nj-1, 0, nk-1); + } + this->SkipByteCount(fp); + + if ( !this->PointCache ) + { + this->PointCache = new vtkFloatArray*[ numBlocks + 1 ]; + this->IBlankCache = new vtkUnsignedCharArray* [ numBlocks + 1 ]; + for ( int g=0; g < numBlocks+1; ++g ) + { + this->PointCache[g] = 0; + this->IBlankCache[g] = 0; + } + } + return VTK_OK; +} + +int vtkMultiBlockPLOT3DReader::ReadQHeader(FILE* fp) +{ + int numGrid = this->GetNumberOfBlocksInternal(fp, 0); + vtkDebugMacro("Q number of grids: " << numGrid); + if ( numGrid == 0 ) + { + return VTK_ERROR; + } + + this->SkipByteCount(fp); + for(int i=0; iReadIntBlock(fp, 1, &ni); + this->ReadIntBlock(fp, 1, &nj); + this->ReadIntBlock(fp, 1, &nk); + vtkDebugMacro("Q, block " << i << " dimensions: " + << ni << " " << nj << " " << nk); + + int extent[6]; + this->Internal->Blocks[i]->GetWholeExtent(extent); + if ( extent[1] != ni-1 || extent[3] != nj-1 || extent[5] != nk-1) + { + this->SetErrorCode(vtkErrorCode::FileFormatError); + vtkErrorMacro("Geometry and data dimensions do not match. " + "Data file may be corrupt."); + return VTK_ERROR; + } + } + this->SkipByteCount(fp); + return VTK_OK; +} + +void vtkMultiBlockPLOT3DReader::SetXYZFileName( const char* name ) +{ + if ( this->XYZFileName && ! strcmp( this->XYZFileName, name ) ) + { + return; + } + + if ( this->XYZFileName ) + { + delete [] this->XYZFileName; + } + + if ( name ) + { + this->XYZFileName = new char [ strlen( name ) + 1 ]; + strcpy( this->XYZFileName, name ); + } + else + { + this->XYZFileName = 0; + } + + this->ClearGeometryCache(); + this->Modified(); +} + +void vtkMultiBlockPLOT3DReader::SetScalarFunctionNumber(int num) +{ + if ( this->ScalarFunctionNumber == num) + { + return; + } + if (num >= 0) + { + // If this function is not in the list, add it. + int found=0; + for (int i=0; i < this->FunctionList->GetNumberOfTuples(); i++ ) + { + if ( this->FunctionList->GetValue(i) == num ) + { + found=1; + } + } + if (!found) + { + this->AddFunction(num); + } + } + this->ScalarFunctionNumber = num; +} + +void vtkMultiBlockPLOT3DReader::SetVectorFunctionNumber(int num) +{ + if ( this->VectorFunctionNumber == num) + { + return; + } + if (num >= 0) + { + // If this function is not in the list, add it. + int found=0; + for (int i=0; i < this->FunctionList->GetNumberOfTuples(); i++ ) + { + if ( this->FunctionList->GetValue(i) == num ) + { + found=1; + } + } + if (!found) + { + this->AddFunction(num); + } + } + this->VectorFunctionNumber = num; +} + +void vtkMultiBlockPLOT3DReader::RemoveFunction(int fnum) +{ + for (int i=0; i < this->FunctionList->GetNumberOfTuples(); i++ ) + { + if ( this->FunctionList->GetValue(i) == fnum ) + { + this->FunctionList->SetValue(i,-1); + this->Modified(); + } + } +} + +int vtkMultiBlockPLOT3DReader::RequestInformation( + vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + FILE* xyzFp; + + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return 0; + } + + this->CalculateFileSize(xyzFp); + this->ReadGeometryHeader(xyzFp); + + fclose(xyzFp); + + vtkInformation* info = outputVector->GetInformationObject(0); + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1); + + return 1; +} + +int vtkMultiBlockPLOT3DReader::RequestData( + vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + + vtkDataObject* doOutput = + info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET()); + vtkHierarchicalDataSet* mb = + vtkHierarchicalDataSet::SafeDownCast(doOutput); + if (!mb) + { + return 0; + } + + if (!info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) || + !info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())) + { + vtkErrorMacro("Expected information not found. Cannot produce data."); + return 0; + } + + int updatePiece = + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int updateNumPieces = + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + this->SetErrorCode(vtkErrorCode::NoError); + + int i; + int ndim, nx, ny, nz; + int numberOfDims; + vtkIdType index; + + int numBlocks = this->Internal->Blocks.size(); + + // Don't read the geometry if we already have it! + if ( (!this->PointCache) || (!this->PointCache[0]) ) + { + FILE* xyzFp; + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return 0; + } + + if ( this->ReadGeometryHeader(xyzFp) != VTK_OK ) + { + vtkErrorMacro("Error reading geometry file."); + fclose(xyzFp); + return 0; + } + + if (!this->TwoDimensionalGeometry) + { + numberOfDims = 3; + } + else + { + numberOfDims = 2; + } + + for(i=0; iSkipByteCount(xyzFp); + + vtkStructuredGrid* nthOutput = this->Internal->Blocks[i]; + int dims[6]; + nthOutput->GetWholeExtent(dims); + nthOutput->SetExtent(dims); + nthOutput->GetDimensions(dims); + this->PointCache[i] = vtkFloatArray::New(); + this->PointCache[i]->SetNumberOfComponents(3); + this->PointCache[i]->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + + vtkPoints* points = vtkPoints::New(); + points->SetData(this->PointCache[i]); + nthOutput->SetPoints(points); + points->Delete(); + this->PointCache[i]->Register( this ); + this->PointCache[i]->Delete(); + + float coord; + for(ndim=0; ndim < numberOfDims; ndim++) + { + for(nz=0; nz < dims[2]; nz++) + { + for(ny=0; ny < dims[1]; ny++) + { + for(nx=0; nx < dims[0]; nx++) + { + if ( this->ReadFloatBlock(xyzFp, 1, &coord) == 0 ) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the geometry file (or the file is corrupt)."); + this->SetErrorCode(vtkErrorCode::PrematureEndOfFileError); + // We need to generate output (otherwise, this filter will + // keep executing). So we produce all 0's + double nullpt[3] = {0.0, 0.0, 0.0}; + vtkIdType ipts, npts=this->PointCache[i]->GetNumberOfTuples(); + for(ipts=0; ipts < npts; ipts++) + { + this->PointCache[i]->SetTuple(ipts, nullpt); + } + fclose(xyzFp); + return 0; + } + index = nz*dims[0]*dims[1]+ny*dims[0]+nx; + this->PointCache[i]->SetComponent(index, ndim, coord); + } + } + } + } + + if (this->TwoDimensionalGeometry) + { + vtkIdType ipts, npts=this->PointCache[i]->GetNumberOfTuples(); + for(ipts=0; ipts < npts; ipts++) + { + this->PointCache[i]->SetComponent(ipts, 2, 0); + } + } + + if (this->IBlanking) + { + this->IBlankCache[i] = vtkUnsignedCharArray::New(); + this->IBlankCache[i]->SetNumberOfComponents(1); + this->IBlankCache[i]->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + this->IBlankCache[i]->SetName("Visibility"); + int* ib = new int[dims[0]*dims[1]*dims[2]]; + if ( this->ReadIntBlock(xyzFp, dims[0]*dims[1]*dims[2], ib) == 0) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the q file (or the file is corrupt)."); + this->SetErrorCode(vtkErrorCode::PrematureEndOfFileError); + fclose(xyzFp); + return 0; + } + vtkIdType ipts, npts=this->IBlankCache[i]->GetNumberOfTuples(); + unsigned char* ib2 = this->IBlankCache[i]->GetPointer(0); + for (ipts=0; iptsSetPointVisibilityArray(this->IBlankCache[i]); + this->IBlankCache[i]->Register( this ); + this->IBlankCache[i]->Delete(); + } + this->SkipByteCount(xyzFp); + } + + fclose(xyzFp); + } + else + { + numberOfDims = this->TwoDimensionalGeometry ? 2 : 3; + + for(i=0; iInternal->Blocks[i]; + int dims[6]; + nthOutput->GetWholeExtent(dims); + nthOutput->SetExtent(dims); + + vtkPoints* points = vtkPoints::New(); + points->SetData(this->PointCache[i]); + nthOutput->SetPoints(points); + points->Delete(); + + if (this->IBlanking) + { + nthOutput->SetPointVisibilityArray(this->IBlankCache[i]); + } + } + } + + // Now read the solution. + if (this->QFileName && this->QFileName[0] != '\0') + { + FILE* qFp; + if ( this->CheckSolutionFile(qFp) != VTK_OK) + { + return 0; + } + + if ( this->ReadQHeader(qFp) != VTK_OK ) + { + fclose(qFp); + return 0; + } + + for(i=0; iInternal->Blocks[i]; + + float fsmach, alpha, re, time; + + this->SkipByteCount(qFp); + this->ReadFloatBlock(qFp, 1, &fsmach); + this->ReadFloatBlock(qFp, 1, &alpha); + this->ReadFloatBlock(qFp, 1, &re); + this->ReadFloatBlock(qFp, 1, &time); + this->SkipByteCount(qFp); + + // Save the properties first + vtkFloatArray* properties = vtkFloatArray::New(); + properties->SetName("Properties"); + properties->SetNumberOfTuples(4); + properties->SetTuple1(0, fsmach); + properties->SetTuple1(1, alpha); + properties->SetTuple1(2, re); + properties->SetTuple1(3, time); + nthOutput->GetFieldData()->AddArray(properties); + properties->Delete(); + + int dims[6]; + nthOutput->GetWholeExtent(dims); + nthOutput->SetExtent(dims); + nthOutput->GetDimensions(dims); + + this->SkipByteCount(qFp); + + vtkFloatArray* density = vtkFloatArray::New(); + density->SetNumberOfComponents(1); + density->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + density->SetName("Density"); + float* dens = density->GetPointer(0); + if ( this->ReadFloatBlock(qFp, dims[0]*dims[1]*dims[2], dens) == 0) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the q file (or the file is corrupt)."); + this->SetErrorCode(vtkErrorCode::PrematureEndOfFileError); + fclose(qFp); + return 0; + } + nthOutput->GetPointData()->AddArray(density); + density->Delete(); + + vtkFloatArray* momentum = vtkFloatArray::New(); + momentum->SetNumberOfComponents(3); + momentum->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + momentum->SetName("Momentum"); + + float comp; + for(ndim=0; ndim < numberOfDims; ndim++) + { + for(nz=0; nz < dims[2]; nz++) + { + for(ny=0; ny < dims[1]; ny++) + { + for(nx=0; nx < dims[0]; nx++) + { + if ( this->ReadFloatBlock(qFp, 1, &comp) == 0 ) + { + vtkErrorMacro("Encountered premature end-of-file while " + "reading the q file (or the file is corrupt)."); + fclose(qFp); + return 0; + } + index = nz*dims[0]*dims[1]+ny*dims[0]+nx; + momentum->SetComponent(index, ndim, comp); + } + } + } + } + if (this->TwoDimensionalGeometry) + { + vtkIdType ipts, npts=momentum->GetNumberOfTuples(); + for(ipts=0; ipts < npts; ipts++) + { + momentum->SetComponent(ipts, 2, 0); + } + } + + nthOutput->GetPointData()->AddArray(momentum); + momentum->Delete(); + + vtkFloatArray* se = vtkFloatArray::New(); + se->SetNumberOfComponents(1); + se->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + se->SetName("StagnationEnergy"); + float* sen = se->GetPointer(0); + if (this->ReadFloatBlock(qFp, dims[0]*dims[1]*dims[2], sen) == 0) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the q file (or the file is corrupt)."); + fclose(qFp); + return 0; + } + nthOutput->GetPointData()->AddArray(se); + se->Delete(); + + + if ( this->FunctionList->GetNumberOfTuples() > 0 ) + { + int fnum; + for (int tup=0; tup < this->FunctionList->GetNumberOfTuples(); tup++) + { + if ( (fnum=this->FunctionList->GetValue(tup)) >= 0 ) + { + this->MapFunction(fnum, nthOutput); + } + } + } + this->AssignAttribute(this->ScalarFunctionNumber, nthOutput, + vtkDataSetAttributes::SCALARS); + this->AssignAttribute(this->VectorFunctionNumber, nthOutput, + vtkDataSetAttributes::VECTORS); + } + fclose(qFp); + } + + mb->SetNumberOfLevels(1); + mb->SetNumberOfDataSets(0, numBlocks); + + int numBlocksPerPiece = 1; + if (updateNumPieces < numBlocks) + { + numBlocksPerPiece = numBlocks / updateNumPieces; + } + int minBlock = numBlocksPerPiece*updatePiece; + int maxBlock = numBlocksPerPiece*(updatePiece+1); + if (updatePiece == updateNumPieces - 1) + { + maxBlock = numBlocks; + } + if (maxBlock > numBlocks) + { + maxBlock = numBlocks; + } + + for(i=minBlock; iInternal->Blocks[i]; + mb->SetDataSet(0, i, nthOutput); + } + + this->Internal->Blocks.clear(); + return 1; +} + +// Various PLOT3D functions..................... +void vtkMultiBlockPLOT3DReader::MapFunction(int fNumber, vtkStructuredGrid* output) +{ + switch (fNumber) + { + case 100: //Density + break; + + case 110: //Pressure + this->ComputePressure(output); + break; + + case 120: //Temperature + this->ComputeTemperature(output); + break; + + case 130: //Enthalpy + this->ComputeEnthalpy(output); + break; + + case 140: //Internal Energy + break; + + case 144: //Kinetic Energy + this->ComputeKineticEnergy(output); + break; + + case 153: //Velocity Magnitude + this->ComputeVelocityMagnitude(output); + break; + + case 163: //Stagnation energy + break; + + case 170: //Entropy + this->ComputeEntropy(output); + break; + + case 184: //Swirl + this->ComputeSwirl(output); + break; + + case 200: //Velocity + this->ComputeVelocity(output); + break; + + case 201: //Vorticity + this->ComputeVorticity(output); + break; + + case 202: //Momentum + break; + + case 210: //PressureGradient + this->ComputePressureGradient(output); + break; + + default: + vtkErrorMacro(<<"No function number " << fNumber); + } +} + +void vtkMultiBlockPLOT3DReader::AssignAttribute(int fNumber, vtkStructuredGrid* output, + int attributeType) +{ + switch (fNumber) + { + case -1: //empty mapping + output->GetPointData()->SetActiveAttribute(0, + attributeType); + break; + + case 100: //Density + output->GetPointData()->SetActiveAttribute("Density", + attributeType); + break; + + case 110: //Pressure + output->GetPointData()->SetActiveAttribute("Pressure", + attributeType); + break; + + case 120: //Temperature + output->GetPointData()->SetActiveAttribute("Temperature", + attributeType); + break; + + case 130: //Enthalpy + output->GetPointData()->SetActiveAttribute("Enthalpy", + attributeType); + break; + + case 140: //Internal Energy + output->GetPointData()->SetActiveAttribute("StagnationEnergy", + attributeType); + break; + + case 144: //Kinetic Energy + output->GetPointData()->SetActiveAttribute("KineticEnergy", + attributeType); + break; + + case 153: //Velocity Magnitude + output->GetPointData()->SetActiveAttribute("VelocityMagnitude", + attributeType); + break; + + case 163: //Stagnation energy + output->GetPointData()->SetActiveAttribute("StagnationEnergy", + attributeType); + break; + + case 170: //Entropy + output->GetPointData()->SetActiveAttribute("Entropy", + attributeType); + break; + + case 184: //Swirl + output->GetPointData()->SetActiveAttribute("Swirl", + attributeType); + break; + + case 200: //Velocity + output->GetPointData()->SetActiveAttribute("Velocity", + attributeType); + break; + + case 201: //Vorticity + output->GetPointData()->SetActiveAttribute("Vorticity", + attributeType); + break; + + case 202: //Momentum + output->GetPointData()->SetActiveAttribute("Momentum", + attributeType); + break; + + case 210: //PressureGradient + output->GetPointData()->SetActiveAttribute("PressureGradient", + attributeType); + break; + + default: + vtkErrorMacro(<<"No function number " << fNumber); + } +} + +void vtkMultiBlockPLOT3DReader::ComputeTemperature(vtkStructuredGrid* output) +{ + double *m, e, rr, u, v, w, v2, p, d, rrgas; + vtkIdType i; + vtkFloatArray *temperature; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute temperature"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + temperature = vtkFloatArray::New(); + temperature->SetNumberOfTuples(numPts); + + // Compute the temperature + // + rrgas = 1.0 / this->R; + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + p = (this->Gamma-1.) * (e - 0.5 * d * v2); + temperature->SetValue(i, p*rr*rrgas); + } + + temperature->SetName("Temperature"); + outputPD->AddArray(temperature); + + temperature->Delete(); + vtkDebugMacro(<<"Created temperature scalar"); +} + +void vtkMultiBlockPLOT3DReader::ComputePressure(vtkStructuredGrid* output) +{ + double *m, e, u, v, w, v2, p, d, rr; + vtkIdType i; + vtkFloatArray *pressure; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute pressure"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + pressure = vtkFloatArray::New(); + pressure->SetNumberOfTuples(numPts); + + // Compute the pressure + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + p = (this->Gamma-1.) * (e - 0.5 * d * v2); + pressure->SetValue(i, p); + } + + pressure->SetName("Pressure"); + outputPD->AddArray(pressure); + pressure->Delete(); + vtkDebugMacro(<<"Created pressure scalar"); +} + +void vtkMultiBlockPLOT3DReader::ComputeEnthalpy(vtkStructuredGrid* output) +{ + double *m, e, u, v, w, v2, d, rr; + vtkIdType i; + vtkFloatArray *enthalpy; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute enthalpy"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + enthalpy = vtkFloatArray::New(); + enthalpy->SetNumberOfTuples(numPts); + + // Compute the enthalpy + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + enthalpy->SetValue(i, this->Gamma*(e*rr - 0.5*v2)); + } + enthalpy->SetName("Enthalpy"); + outputPD->AddArray(enthalpy); + enthalpy->Delete(); + vtkDebugMacro(<<"Created enthalpy scalar"); +} + +void vtkMultiBlockPLOT3DReader::ComputeKineticEnergy(vtkStructuredGrid* output) +{ + double *m, u, v, w, v2, d, rr; + vtkIdType i; + vtkFloatArray *kineticEnergy; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + if ( density == NULL || momentum == NULL ) + { + vtkErrorMacro(<<"Cannot compute kinetic energy"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + kineticEnergy = vtkFloatArray::New(); + kineticEnergy->SetNumberOfTuples(numPts); + + // Compute the kinetic energy + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + kineticEnergy->SetValue(i, 0.5*v2); + } + kineticEnergy->SetName("KineticEnergy"); + outputPD->AddArray(kineticEnergy); + kineticEnergy->Delete(); + vtkDebugMacro(<<"Created kinetic energy scalar"); +} + +void vtkMultiBlockPLOT3DReader::ComputeVelocityMagnitude(vtkStructuredGrid* output) +{ + double *m, u, v, w, v2, d, rr; + vtkIdType i; + vtkFloatArray *velocityMag; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute velocity magnitude"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + velocityMag = vtkFloatArray::New(); + velocityMag->SetNumberOfTuples(numPts); + + // Compute the velocity magnitude + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + velocityMag->SetValue(i, sqrt((double)v2)); + } + velocityMag->SetName("VelocityMagnitude"); + outputPD->AddArray(velocityMag); + velocityMag->Delete(); + vtkDebugMacro(<<"Created velocity magnitude scalar"); +} + +void vtkMultiBlockPLOT3DReader::ComputeEntropy(vtkStructuredGrid* output) +{ + double *m, u, v, w, v2, d, rr, s, p, e; + vtkIdType i; + vtkFloatArray *entropy; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute entropy"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + entropy = vtkFloatArray::New(); + entropy->SetNumberOfTuples(numPts); + + // Compute the entropy + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + p = (this->Gamma-1.)*(e - 0.5*d*v2); + s = VTK_CV * log((p/VTK_PINF)/pow((double)d/VTK_RHOINF,(double)this->Gamma)); + entropy->SetValue(i,s); + } + entropy->SetName("Entropy"); + outputPD->AddArray(entropy); + entropy->Delete(); + vtkDebugMacro(<<"Created entropy scalar"); +} + +void vtkMultiBlockPLOT3DReader::ComputeSwirl(vtkStructuredGrid* output) +{ + vtkDataArray *vorticity; + double d, rr, *m, u, v, w, v2, *vort, s; + vtkIdType i; + vtkFloatArray *swirl; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute swirl"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + swirl = vtkFloatArray::New(); + swirl->SetNumberOfTuples(numPts); + + this->ComputeVorticity(output); + vorticity = outputPD->GetArray("Vorticity"); +// +// Compute the swirl +// + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + vort = vorticity->GetTuple(i); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + if ( v2 != 0.0 ) + { + s = (vort[0]*m[0] + vort[1]*m[1] + vort[2]*m[2]) / v2; + } + else + { + s = 0.0; + } + + swirl->SetValue(i,s); + } + swirl->SetName("Swirl"); + outputPD->AddArray(swirl); + swirl->Delete(); + vtkDebugMacro(<<"Created swirl scalar"); + +} + +// Vector functions +void vtkMultiBlockPLOT3DReader::ComputeVelocity(vtkStructuredGrid* output) +{ + double *m, v[3], d, rr; + vtkIdType i; + vtkFloatArray *velocity; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute velocity"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + velocity = vtkFloatArray::New(); + velocity->SetNumberOfComponents(3); + velocity->SetNumberOfTuples(numPts); + + // Compute the velocity + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + rr = 1.0 / d; + v[0] = m[0] * rr; + v[1] = m[1] * rr; + v[2] = m[2] * rr; + velocity->SetTuple(i, v); + } + velocity->SetName("Velocity"); + outputPD->AddArray(velocity); + velocity->Delete(); + vtkDebugMacro(<<"Created velocity vector"); +} + +void vtkMultiBlockPLOT3DReader::ComputeVorticity(vtkStructuredGrid* output) +{ + vtkDataArray *velocity; + vtkFloatArray *vorticity; + int dims[3], ijsize; + vtkPoints *points; + int i, j, k, idx, idx2, ii; + double vort[3], xp[3], xm[3], vp[3], vm[3], factor; + double xxi, yxi, zxi, uxi, vxi, wxi; + double xeta, yeta, zeta, ueta, veta, weta; + double xzeta, yzeta, zzeta, uzeta, vzeta, wzeta; + double aj, xix, xiy, xiz, etax, etay, etaz, zetax, zetay, zetaz; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( (points=output->GetPoints()) == NULL || + density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute vorticity"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + vorticity = vtkFloatArray::New(); + vorticity->SetNumberOfComponents(3); + vorticity->SetNumberOfTuples(numPts); + + this->ComputeVelocity(output); + velocity = outputPD->GetArray("Velocity"); + + output->GetDimensions(dims); + ijsize = dims[0]*dims[1]; + + for (k=0; kGetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else if ( i == (dims[0]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i-1 + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else + { + factor = 0.5; + idx = (i+1) + j*dims[0] + k*ijsize; + idx2 = (i-1) + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + + xxi = factor * (xp[0] - xm[0]); + yxi = factor * (xp[1] - xm[1]); + zxi = factor * (xp[2] - xm[2]); + uxi = factor * (vp[0] - vm[0]); + vxi = factor * (vp[1] - vm[1]); + wxi = factor * (vp[2] - vm[2]); + + // Eta derivatives. + if ( dims[1] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + vp[ii] = vm[ii] = xp[ii] = xm[ii] = 0.0; + } + xp[1] = 1.0; + } + else if ( j == 0 ) + { + factor = 1.0; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else if ( j == (dims[1]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else + { + factor = 0.5; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + + + xeta = factor * (xp[0] - xm[0]); + yeta = factor * (xp[1] - xm[1]); + zeta = factor * (xp[2] - xm[2]); + ueta = factor * (vp[0] - vm[0]); + veta = factor * (vp[1] - vm[1]); + weta = factor * (vp[2] - vm[2]); + + // Zeta derivatives. + if ( dims[2] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + vp[ii] = vm[ii] = xp[ii] = xm[ii] = 0.0; + } + xp[2] = 1.0; + } + else if ( k == 0 ) + { + factor = 1.0; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else if ( k == (dims[2]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else + { + factor = 0.5; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + + xzeta = factor * (xp[0] - xm[0]); + yzeta = factor * (xp[1] - xm[1]); + zzeta = factor * (xp[2] - xm[2]); + uzeta = factor * (vp[0] - vm[0]); + vzeta = factor * (vp[1] - vm[1]); + wzeta = factor * (vp[2] - vm[2]); + + // Now calculate the Jacobian. Grids occasionally have + // singularities, or points where the Jacobian is infinite (the + // inverse is zero). For these cases, we'll set the Jacobian to + // zero, which will result in a zero vorticity. + // + aj = xxi*yeta*zzeta+yxi*zeta*xzeta+zxi*xeta*yzeta + -zxi*yeta*xzeta-yxi*xeta*zzeta-xxi*zeta*yzeta; + if (aj != 0.0) + { + aj = 1. / aj; + } + + // Xi metrics. + xix = aj*(yeta*zzeta-zeta*yzeta); + xiy = -aj*(xeta*zzeta-zeta*xzeta); + xiz = aj*(xeta*yzeta-yeta*xzeta); + + // Eta metrics. + etax = -aj*(yxi*zzeta-zxi*yzeta); + etay = aj*(xxi*zzeta-zxi*xzeta); + etaz = -aj*(xxi*yzeta-yxi*xzeta); + + // Zeta metrics. + zetax= aj*(yxi*zeta-zxi*yeta); + zetay= -aj*(xxi*zeta-zxi*xeta); + zetaz= aj*(xxi*yeta-yxi*xeta); + + // Finally, the vorticity components. + // + vort[0]= xiy*wxi+etay*weta+zetay*wzeta - xiz*vxi-etaz*veta-zetaz*vzeta; + vort[1]= xiz*uxi+etaz*ueta+zetaz*uzeta - xix*wxi-etax*weta-zetax*wzeta; + vort[2]= xix*vxi+etax*veta+zetax*vzeta - xiy*uxi-etay*ueta-zetay*uzeta; + idx = i + j*dims[0] + k*ijsize; + vorticity->SetTuple(idx,vort); + } + } + } + vorticity->SetName("Vorticity"); + outputPD->AddArray(vorticity); + vorticity->Delete(); + vtkDebugMacro(<<"Created vorticity vector"); +} + +void vtkMultiBlockPLOT3DReader::ComputePressureGradient(vtkStructuredGrid* output) +{ + vtkDataArray *pressure; + vtkFloatArray *gradient; + int dims[3], ijsize; + vtkPoints *points; + int i, j, k, idx, idx2, ii; + double g[3], xp[3], xm[3], pp, pm, factor; + double xxi, yxi, zxi, pxi; + double xeta, yeta, zeta, peta; + double xzeta, yzeta, zzeta, pzeta; + double aj, xix, xiy, xiz, etax, etay, etaz, zetax, zetay, zetaz; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( (points=output->GetPoints()) == NULL || + density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute pressure gradient"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + gradient = vtkFloatArray::New(); + gradient->SetNumberOfComponents(3); + gradient->SetNumberOfTuples(numPts); + + this->ComputePressure(output); + pressure = outputPD->GetArray("Pressure"); + + output->GetDimensions(dims); + ijsize = dims[0]*dims[1]; + + for (k=0; kGetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else if ( i == (dims[0]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i-1 + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else + { + factor = 0.5; + idx = (i+1) + j*dims[0] + k*ijsize; + idx2 = (i-1) + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + + xxi = factor * (xp[0] - xm[0]); + yxi = factor * (xp[1] - xm[1]); + zxi = factor * (xp[2] - xm[2]); + pxi = factor * (pp - pm); + + // Eta derivatives. + if ( dims[1] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + xp[ii] = xm[ii] = 0.0; + } + xp[1] = 1.0; pp = pm = 0.0; + } + else if ( j == 0 ) + { + factor = 1.0; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else if ( j == (dims[1]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else + { + factor = 0.5; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + + xeta = factor * (xp[0] - xm[0]); + yeta = factor * (xp[1] - xm[1]); + zeta = factor * (xp[2] - xm[2]); + peta = factor * (pp - pm); + + // Zeta derivatives. + if ( dims[2] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + xp[ii] = xm[ii] = 0.0; + } + xp[2] = 1.0; pp = pm = 0.0; + } + else if ( k == 0 ) + { + factor = 1.0; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else if ( k == (dims[2]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else + { + factor = 0.5; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + + xzeta = factor * (xp[0] - xm[0]); + yzeta = factor * (xp[1] - xm[1]); + zzeta = factor * (xp[2] - xm[2]); + pzeta = factor * (pp - pm); + + // Now calculate the Jacobian. Grids occasionally have + // singularities, or points where the Jacobian is infinite (the + // inverse is zero). For these cases, we'll set the Jacobian to + // zero, which will result in a zero vorticity. + // + aj = xxi*yeta*zzeta+yxi*zeta*xzeta+zxi*xeta*yzeta + -zxi*yeta*xzeta-yxi*xeta*zzeta-xxi*zeta*yzeta; + if (aj != 0.0) + { + aj = 1. / aj; + } + + // Xi metrics. + xix = aj*(yeta*zzeta-zeta*yzeta); + xiy = -aj*(xeta*zzeta-zeta*xzeta); + xiz = aj*(xeta*yzeta-yeta*xzeta); + + // Eta metrics. + etax = -aj*(yxi*zzeta-zxi*yzeta); + etay = aj*(xxi*zzeta-zxi*xzeta); + etaz = -aj*(xxi*yzeta-yxi*xzeta); + + // Zeta metrics. + zetax= aj*(yxi*zeta-zxi*yeta); + zetay= -aj*(xxi*zeta-zxi*xeta); + zetaz= aj*(xxi*yeta-yxi*xeta); + + // Finally, the vorticity components. + g[0]= xix*pxi+etax*peta+zetax*pzeta; + g[1]= xiy*pxi+etay*peta+zetay*pzeta; + g[2]= xiz*pxi+etaz*peta+zetaz*pzeta; + + idx = i + j*dims[0] + k*ijsize; + gradient->SetTuple(idx,g); + } + } + } + gradient->SetName("PressureGradient"); + outputPD->AddArray(gradient); + gradient->Delete(); + vtkDebugMacro(<<"Created pressure gradient vector"); +} + +void vtkMultiBlockPLOT3DReader::SetByteOrderToBigEndian() +{ + this->ByteOrder = FILE_BIG_ENDIAN; +} + +void vtkMultiBlockPLOT3DReader::SetByteOrderToLittleEndian() +{ + this->ByteOrder = FILE_LITTLE_ENDIAN; +} + +const char *vtkMultiBlockPLOT3DReader::GetByteOrderAsString() +{ + if ( this->ByteOrder == FILE_LITTLE_ENDIAN) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +} + +void vtkMultiBlockPLOT3DReader::AddFunction(int functionNumber) +{ + this->FunctionList->InsertNextValue(functionNumber); + this->Modified(); +} + +void vtkMultiBlockPLOT3DReader::RemoveAllFunctions() +{ + this->FunctionList->Reset(); + this->Modified(); +} + +int vtkMultiBlockPLOT3DReader::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredGrid"); + info->Set(vtkCompositeDataPipeline::COMPOSITE_DATA_TYPE_NAME(), + "vtkHierarchicalDataSet"); + return 1; +} + +void vtkMultiBlockPLOT3DReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "XYZ File Name: " << + (this->XYZFileName ? this->XYZFileName : "(none)") << "\n"; + os << indent << "Q File Name: " << + (this->QFileName ? this->QFileName : "(none)") << "\n"; + os << indent << "BinaryFile: " << this->BinaryFile << endl; + os << indent << "HasByteCount: " << this->HasByteCount << endl; + os << indent << "Gamma: " << this->Gamma << endl; + os << indent << "R: " << this->R << endl; + os << indent << "Uvinf: " << this->Uvinf << endl; + os << indent << "Vvinf: " << this->Vvinf << endl; + os << indent << "Wvinf: " << this->Wvinf << endl; + os << indent << "ScalarFunctionNumber: " << this->ScalarFunctionNumber << endl; + os << indent << "VectorFunctionNumber: " << this->VectorFunctionNumber << endl; + os << indent << "MultiGrid: " << this->MultiGrid << endl; + os << indent << "TwoDimensionalGeometry: " + << this->TwoDimensionalGeometry << endl; + os << indent << "ForceRead: " << this->ForceRead << endl; + os << indent << "IBlanking: " << this->IBlanking << endl; + os << indent << "ByteOrder: " << this->ByteOrder << endl; + os << indent << "TwoDimensionalGeometry: " << (this->TwoDimensionalGeometry?"on":"off") + << endl; +} + diff --git a/IO/vtkMultiBlockPLOT3DReader.h b/IO/vtkMultiBlockPLOT3DReader.h new file mode 100644 index 0000000..8a6c045 --- /dev/null +++ b/IO/vtkMultiBlockPLOT3DReader.h @@ -0,0 +1,327 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiBlockPLOT3DReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMultiBlockPLOT3DReader - read PLOT3D data files +// .SECTION Description +// vtkMultiBlockPLOT3DReader is a reader object that reads PLOT3D formatted +// files and generates structured grid(s) on output. PLOT3D is a computer +// graphics program designed to visualize the grids and solutions of +// computational fluid dynamics. Please see the "PLOT3D User's Manual" +// available from NASA Ames Research Center, Moffett Field CA. +// +// PLOT3D files consist of a grid file (also known as XYZ file), an +// optional solution file (also known as a Q file), and an optional function +// file that contains user created data (currently unsupported). The Q file +// contains solution information as follows: the four parameters free stream +// mach number (Fsmach), angle of attack (Alpha), Reynolds number (Re), and +// total integration time (Time). This information is stored in an array +// called Properties in the FieldData of each output (tuple 0: fsmach, tuple 1: +// alpha, tuple 2: re, tuple 3: time). In addition, the solution file contains +// the flow density (scalar), flow momentum (vector), and flow energy (scalar). +// +// The reader can generate additional scalars and vectors (or "functions") +// from this information. To use vtkMultiBlockPLOT3DReader, you must specify the +// particular function number for the scalar and vector you want to visualize. +// This implementation of the reader provides the following functions. The +// scalar functions are: +// -1 - don't read or compute any scalars +// 100 - density +// 110 - pressure +// 120 - temperature +// 130 - enthalpy +// 140 - internal energy +// 144 - kinetic energy +// 153 - velocity magnitude +// 163 - stagnation energy +// 170 - entropy +// 184 - swirl. +// +// The vector functions are: +// -1 - don't read or compute any vectors +// 200 - velocity +// 201 - vorticity +// 202 - momentum +// 210 - pressure gradient. +// +// (Other functions are described in the PLOT3D spec, but only those listed are +// implemented here.) Note that by default, this reader creates the density +// scalar (100) and momentum vector (202) as output. (These are just read in +// from the solution file.) Please note that the validity of computation is +// a function of this class's gas constants (R, Gamma) and the equations used. +// They may not be suitable for your computational domain. +// +// Additionally, you can read other data and associate it as a vtkDataArray +// into the output's point attribute data. Use the method AddFunction() +// to list all the functions that you'd like to read. AddFunction() accepts +// an integer parameter that defines the function number. +// +// .SECTION See Also +// vtkStructuredGridSource vtkStructuredGrid + +#ifndef __vtkMultiBlockPLOT3DReader_h +#define __vtkMultiBlockPLOT3DReader_h + +#include "vtkHierarchicalDataSetAlgorithm.h" + +class vtkUnsignedCharArray; +class vtkIntArray; +class vtkFloatArray; +class vtkStructuredGrid; +//BTX +struct vtkMultiBlockPLOT3DReaderInternals; +//ETX +class VTK_IO_EXPORT vtkMultiBlockPLOT3DReader : public vtkHierarchicalDataSetAlgorithm +{ +public: + static vtkMultiBlockPLOT3DReader *New(); + vtkTypeRevisionMacro(vtkMultiBlockPLOT3DReader,vtkHierarchicalDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the PLOT3D geometry filename. + void SetFileName(const char* name) { this->SetXYZFileName(name); } + const char* GetFileName() { return this->GetXYZFileName(); } + virtual void SetXYZFileName( const char* ); + vtkGetStringMacro(XYZFileName); + + // Description: + // Set/Get the PLOT3D solution filename. + vtkSetStringMacro(QFileName); + vtkGetStringMacro(QFileName); + + // Description: + // This returns the number of outputs this reader will produce. + // This number is equal to the number of grids in the current + // file. This method has to be called before getting any output + // if the number of outputs will be greater than 1 (the first + // output is always the same). Note that every time this method + // is invoked, the header file is opened and part of the header + // is read. + int GetNumberOfBlocks(); + int GetNumberOfGrids() { return this->GetNumberOfBlocks(); } + + // Description: + // Is the file to be read written in binary format (as opposed + // to ascii). + vtkSetMacro(BinaryFile, int); + vtkGetMacro(BinaryFile, int); + vtkBooleanMacro(BinaryFile, int); + + // Description: + // Does the file to be read contain information about number of + // grids. In some PLOT3D files, the first value contains the number + // of grids (even if there is only 1). If reading such a file, + // set this to true. + vtkSetMacro(MultiGrid, int); + vtkGetMacro(MultiGrid, int); + vtkBooleanMacro(MultiGrid, int); + + // Description: + // Were the arrays written with leading and trailing byte counts ? + // Usually, files written by a fortran program will contain these + // byte counts whereas the ones written by C/C++ won't. + vtkSetMacro(HasByteCount, int); + vtkGetMacro(HasByteCount, int); + vtkBooleanMacro(HasByteCount, int); + + // Description: + // Is there iblanking (point visibility) information in the file. + // If there is iblanking arrays, these will be read and assigned + // to the PointVisibility array of the output. + vtkSetMacro(IBlanking, int); + vtkGetMacro(IBlanking, int); + vtkBooleanMacro(IBlanking, int); + + // Description: + // If only two-dimensional data was written to the file, + // turn this on. + vtkSetMacro(TwoDimensionalGeometry, int); + vtkGetMacro(TwoDimensionalGeometry, int); + vtkBooleanMacro(TwoDimensionalGeometry, int); + + // Description: + // Try to read a binary file even if the file length seems to be + // inconsistent with the header information. Use this with caution, + // if the file length is not the same as calculated from the header. + // either the file is corrupt or the settings are wrong. + vtkSetMacro(ForceRead, int); + vtkGetMacro(ForceRead, int); + vtkBooleanMacro(ForceRead, int); + + // Description: + // Set the byte order of the file (remember, more Unix workstations + // write big endian whereas PCs write little endian). Default is + // big endian (since most older PLOT3D files were written by + // workstations). + void SetByteOrderToBigEndian(); + void SetByteOrderToLittleEndian(); + vtkSetMacro(ByteOrder, int); + vtkGetMacro(ByteOrder, int); + const char *GetByteOrderAsString(); + + // Description: + // Set/Get the gas constant. Default is 1.0. + vtkSetMacro(R,double); + vtkGetMacro(R,double); + + // Description: + // Set/Get the ratio of specific heats. Default is 1.4. + vtkSetMacro(Gamma,double); + vtkGetMacro(Gamma,double); + + // Description: + // Set/Get the x-component of the free-stream velocity. Default is 1.0. + vtkSetMacro(Uvinf,double); + vtkGetMacro(Uvinf,double); + + // Description: + // Set/Get the y-component of the free-stream velocity. Default is 1.0. + vtkSetMacro(Vvinf,double); + vtkGetMacro(Vvinf,double); + + // Description: + // Set/Get the z-component of the free-stream velocity. Default is 1.0. + vtkSetMacro(Wvinf,double); + vtkGetMacro(Wvinf,double); + + // Description: + // Specify the scalar function to extract. If ==(-1), then no scalar + // function is extracted. + void SetScalarFunctionNumber(int num); + vtkGetMacro(ScalarFunctionNumber,int); + + // Description: + // Specify the vector function to extract. If ==(-1), then no vector + // function is extracted. + void SetVectorFunctionNumber(int num); + vtkGetMacro(VectorFunctionNumber,int); + + // Description: + // Specify additional functions to read. These are placed into the + // point data as data arrays. Later on they can be used by labeling + // them as scalars, etc. + void AddFunction(int functionNumber); + void RemoveFunction(int); + void RemoveAllFunctions(); + + // Description: + // Return 1 if the reader can read the given file name. Only meaningful + // for binary files. + virtual int CanReadBinaryFile(const char* fname); + + // Description: + int GenerateDefaultConfiguration(); + +//BTX + enum + { + FILE_BIG_ENDIAN=0, + FILE_LITTLE_ENDIAN=1 + }; +//ETX + +protected: + vtkMultiBlockPLOT3DReader(); + ~vtkMultiBlockPLOT3DReader(); + + int CheckFile(FILE*& fp, const char* fname); + int CheckGeometryFile(FILE*& xyzFp); + int CheckSolutionFile(FILE*& qFp); + + void SkipByteCount (FILE* fp); + int ReadIntBlock (FILE* fp, int n, int* block); + int ReadFloatBlock(FILE* fp, int n, float* block); + + int GetNumberOfBlocksInternal(FILE* xyzFp, int verify=1); + + int ReadGeometryHeader(FILE* fp); + int ReadQHeader(FILE* fp); + + void CalculateFileSize(FILE* fp); + long EstimateSize(int ni, int nj, int nk); + + void AssignAttribute(int fNumber, vtkStructuredGrid* output, + int attributeType); + void MapFunction(int fNumber, vtkStructuredGrid* output); + void ComputeTemperature(vtkStructuredGrid* output); + void ComputePressure(vtkStructuredGrid* output); + void ComputeEnthalpy(vtkStructuredGrid* output); + void ComputeKineticEnergy(vtkStructuredGrid* output); + void ComputeVelocityMagnitude(vtkStructuredGrid* output); + void ComputeEntropy(vtkStructuredGrid* output); + void ComputeSwirl(vtkStructuredGrid* output); + void ComputeVelocity(vtkStructuredGrid* output); + void ComputeVorticity(vtkStructuredGrid* output); + void ComputePressureGradient(vtkStructuredGrid* output); + + // Delete references to any existing vtkPoints and + // I-blank arrays. The next Update() will (re)read + // the XYZ file. + void ClearGeometryCache(); + + //plot3d FileNames + char *XYZFileName; + char *QFileName; + + int BinaryFile; + int HasByteCount; + int TwoDimensionalGeometry; + int MultiGrid; + int ForceRead; + int ByteOrder; + int IBlanking; + + long FileSize; + + //parameters used in computing derived functions + double R; + double Gamma; + double Uvinf; + double Vvinf; + double Wvinf; + + //functions to read that are not scalars or vectors + vtkIntArray *FunctionList; + + int ScalarFunctionNumber; + int VectorFunctionNumber; + + // Cache of geometry + vtkFloatArray** PointCache; + vtkUnsignedCharArray** IBlankCache; + + int VerifySettings(char* buf, int bufSize); + void ReadIntBlockV(char** buf, int n, int* block); + void SkipByteCountV(char** buf); + + virtual int FillOutputPortInformation(int port, vtkInformation* info); + + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +private: + + vtkMultiBlockPLOT3DReaderInternals* Internal; + + vtkMultiBlockPLOT3DReader(const vtkMultiBlockPLOT3DReader&); // Not implemented. + void operator=(const vtkMultiBlockPLOT3DReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkOBJReader.cxx b/IO/vtkOBJReader.cxx new file mode 100644 index 0000000..b57e7e7 --- /dev/null +++ b/IO/vtkOBJReader.cxx @@ -0,0 +1,415 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBJReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOBJReader.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkOBJReader, "$Revision: 1.27 $"); +vtkStandardNewMacro(vtkOBJReader); + +// Description: +// Instantiate object with NULL filename. +vtkOBJReader::vtkOBJReader() +{ + this->FileName = NULL; + + this->SetNumberOfInputPorts(0); +} + +vtkOBJReader::~vtkOBJReader() +{ + if (this->FileName) + { + delete [] this->FileName; + this->FileName = NULL; + } +} + +/*-------------------------------------------------------- + +This is only partial support for the OBJ format, which is +quite complicated. To find a full specification, +search the net for "OBJ format", eg.: + +http://netghost.narod.ru/gff/graphics/summary/waveobj.htm + +We support the following types: + +v vertex + +vn vertex normal + +vt texture coordinate + +f ... + +polygonal face linking vertices v_a, v_b, v_c, etc. which +are 1-based indices into the vertex list + +f / / ... + +polygonal face as above, but with texture coordinates for +each vertex. t_a etc. are 1-based indices into the texture +coordinates list (from the vt lines) + +f // // ... + +polygonal face as above, with a normal at each vertex, as a +1-based index into the normals list (from the vn lines) + +f // // ... + +polygonal face as above but without texture coordinates. + +Per-face tcoords and normals are supported by duplicating +the vertices on each face as necessary. + +---------------------------------------------------------*/ + +// a replacement for isspace() +int is_whitespace(char c) +{ + if ( c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f') + return 1; + else + return 0; +} + +int vtkOBJReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (!this->FileName) + { + vtkErrorMacro(<< "A FileName must be specified."); + return 0; + } + + FILE *in = fopen(this->FileName,"r"); + + if (in == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return 0; + } + + vtkDebugMacro(<<"Reading file"); + + // intialise some structures to store the file contents in + vtkPoints *points = vtkPoints::New(); + vtkFloatArray *tcoords = vtkFloatArray::New(); + tcoords->SetNumberOfComponents(2); + vtkFloatArray *normals = vtkFloatArray::New(); + normals->SetNumberOfComponents(3); + vtkCellArray *polys = vtkCellArray::New(); + vtkCellArray *tcoord_polys = vtkCellArray::New(); + int hasTCoords=0; // (false) + int tcoords_same_as_verts=1; // (true) + vtkCellArray *normal_polys = vtkCellArray::New(); + int hasNormals=0; // (false) + int normals_same_as_verts=1; // (true) + + int everything_ok = 1; // (true) (use of this flag avoids early return and associated memory leak) + + // -- work through the file line by line, assigning into the above six structures as appropriate -- + + { // (make a local scope section to emphasise that the variables below are only used here) + + const int MAX_LINE=1024; + char line[MAX_LINE],*pChar; + float xyz[3]; + int iVert,iTCoord,iNormal; + while (everything_ok && fgets(line,MAX_LINE,in)!=NULL) + { + + // in the OBJ format the first characters determine how to interpret the line: + if (strncmp(line,"v ",2)==0) + { + // this is a vertex definition, expect three floats, separated by whitespace: + if (sscanf(line, "v %f %f %f", xyz, xyz + 1, xyz + 2)==3) + { + points->InsertNextPoint(xyz); + } + else + { + vtkErrorMacro(<<"Error in reading file"); + everything_ok=0; // (false) + } + } + else if (strncmp(line,"vt ",3)==0) + { + // this is a tcoord, expect two floats, separated by whitespace: + if (sscanf(line, "vt %f %f", xyz, xyz + 1)==2) + { + tcoords->InsertNextTuple(xyz); + } + else + { + vtkErrorMacro(<<"Error in reading file"); + everything_ok=0; // (false) + } + } + else if (strncmp(line,"vn ",3)==0) + { + // this is a normal, expect three floats, separated by whitespace: + if (sscanf(line, "vn %f %f %f", xyz, xyz + 1, xyz + 2)==3) + { + normals->InsertNextTuple(xyz); + } + else + { + vtkErrorMacro(<<"Error in reading file"); + everything_ok=0; // (false) + } + } + else if (strncmp(line,"f ",2)==0 || strncmp(line,"fo ",3)==0) // not sure why "fo" here + { + // this is a face definition, consisting of 1-based indices separated by whitespace and / + + polys->InsertNextCell(0); // we don't yet know how many points are to come + tcoord_polys->InsertNextCell(0); + normal_polys->InsertNextCell(0); + + int nVerts=0,nTCoords=0,nNormals=0; // keep a count of how many of each there are + + pChar = line + 2; + const char *pEnd = line + strlen(line); + + while (everything_ok && pCharInsertCellPoint(iVert-1); // convert to 0-based index + nVerts++; + tcoord_polys->InsertCellPoint(iTCoord-1); + nTCoords++; + if (iTCoord!=iVert && tcoords_same_as_verts) + tcoords_same_as_verts = 0; // (false) + normal_polys->InsertCellPoint(iNormal-1); + nNormals++; + if (iNormal!=iVert && normals_same_as_verts) + normals_same_as_verts = 0; // (false) + } + else if (sscanf(pChar,"%d//%d",&iVert,&iNormal)==2) + { + polys->InsertCellPoint(iVert-1); + nVerts++; + normal_polys->InsertCellPoint(iNormal-1); + nNormals++; + if (iNormal!=iVert && normals_same_as_verts) + normals_same_as_verts = 0; // (false) + } + else if (sscanf(pChar,"%d/%d",&iVert,&iTCoord)==2) + { + polys->InsertCellPoint(iVert-1); + nVerts++; + tcoord_polys->InsertCellPoint(iTCoord-1); + nTCoords++; + if (iTCoord!=iVert && tcoords_same_as_verts) + tcoords_same_as_verts = 0; // (false) + } + else if (sscanf(pChar,"%d",&iVert)==1) + { + polys->InsertCellPoint(iVert-1); + nVerts++; + } + else + { + vtkErrorMacro(<<"Error in reading file"); + everything_ok=0; // (false) + } + // skip over what we just read + // (find the first whitespace character) + while (!is_whitespace(*pChar) && pChar0 && nTCoords!=nVerts) || (nNormals>0 && nNormals!=nVerts)) + { + vtkErrorMacro(<<"Error in reading file"); + everything_ok=0; // (false) + } + + // now we know how many points there were in this cell + polys->UpdateCellCount(nVerts); + tcoord_polys->UpdateCellCount(nTCoords); + normal_polys->UpdateCellCount(nNormals); + + // also make a note of whether any cells have tcoords, and whether any have normals + if (nTCoords>0 && !hasTCoords) { hasTCoords=1; } + if (nNormals>0 && !hasNormals) { hasNormals=1; } + } + else + { + //vtkDebugMacro(<<"Ignoring line: "<SetPoints(points); + output->SetPolys(polys); + + // if there is an exact correspondence between tcoords and vertices then can simply + // assign the tcoords points as point data + if (hasTCoords && tcoords_same_as_verts) + output->GetPointData()->SetTCoords(tcoords); + + // if there is an exact correspondence between normals and vertices then can simply + // assign the normals as point data + if (hasNormals && normals_same_as_verts) + { + output->GetPointData()->SetNormals(normals); + } + output->Squeeze(); + } + // otherwise we can duplicate the vertices as necessary (a bit slower) + else + { + vtkDebugMacro(<<"Duplicating vertices so that tcoords and normals are correct"); + + vtkPoints *new_points = vtkPoints::New(); + vtkFloatArray *new_tcoords = vtkFloatArray::New(); + new_tcoords->SetNumberOfComponents(2); + vtkFloatArray *new_normals = vtkFloatArray::New(); + new_normals->SetNumberOfComponents(3); + vtkCellArray *new_polys = vtkCellArray::New(); + + // for each poly, copy its vertices into new_points (and point at them) + // also copy its tcoords into new_tcoords + // also copy its normals into new_normals + polys->InitTraversal(); + tcoord_polys->InitTraversal(); + normal_polys->InitTraversal(); + int i,j; + vtkIdType dummy_warning_prevention_mechanism[1]; + vtkIdType n_pts=-1,*pts=dummy_warning_prevention_mechanism; + vtkIdType n_tcoord_pts=-1,*tcoord_pts=dummy_warning_prevention_mechanism; + vtkIdType n_normal_pts=-1,*normal_pts=dummy_warning_prevention_mechanism; + for (i=0;iGetNumberOfCells();i++) + { + polys->GetNextCell(n_pts,pts); + tcoord_polys->GetNextCell(n_tcoord_pts,tcoord_pts); + normal_polys->GetNextCell(n_normal_pts,normal_pts); + + // If some vertices have tcoords and not others (likewise normals) + // then we must do something else VTK will complain. (crash on render attempt) + // Easiest solution is to delete polys that don't have complete tcoords (if there + // are any tcoords in the dataset) or normals (if there are any normals in the dataset). + + if ( (n_pts!=n_tcoord_pts && hasTCoords) || (n_pts!=n_normal_pts && hasNormals) ) + { + // skip this poly + vtkDebugMacro(<<"Skipping poly "<0) + { + new_tcoords->InsertNextTuple(tcoords->GetTuple(tcoord_pts[j])); + } + // copy the normal for this point across (if there is one) + if (n_normal_pts>0) + { + new_normals->InsertNextTuple(normals->GetTuple(normal_pts[j])); + } + // copy the vertex into the new structure and update + // the vertex index in the polys structure (pts is a pointer into it) + pts[j] = new_points->InsertNextPoint(points->GetPoint(pts[j])); + } + // copy this poly (pointing at the new points) into the new polys list + new_polys->InsertNextCell(n_pts,pts); + } + } + + // use the new structures for the output + output->SetPoints(new_points); + output->SetPolys(new_polys); + if (hasTCoords) + { + output->GetPointData()->SetTCoords(new_tcoords); + } + if (hasNormals) + { + output->GetPointData()->SetNormals(new_normals); + } + output->Squeeze(); + + new_points->Delete(); + new_polys->Delete(); + new_tcoords->Delete(); + new_normals->Delete(); + } + } + + points->Delete(); + tcoords->Delete(); + normals->Delete(); + polys->Delete(); + tcoord_polys->Delete(); + normal_polys->Delete(); + + return 1; +} + +void vtkOBJReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + +} diff --git a/IO/vtkOBJReader.h b/IO/vtkOBJReader.h new file mode 100644 index 0000000..2562e59 --- /dev/null +++ b/IO/vtkOBJReader.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBJReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOBJReader - read Wavefront .obj files +// .SECTION Description +// vtkOBJReader is a source object that reads Wavefront .obj +// files. The output of this source object is polygonal data. +// .SECTION See Also +// vtkOBJImporter + +#ifndef __vtkOBJReader_h +#define __vtkOBJReader_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_IO_EXPORT vtkOBJReader : public vtkPolyDataAlgorithm +{ +public: + static vtkOBJReader *New(); + vtkTypeRevisionMacro(vtkOBJReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name of Wavefront .obj file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkOBJReader(); + ~vtkOBJReader(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char *FileName; +private: + vtkOBJReader(const vtkOBJReader&); // Not implemented. + void operator=(const vtkOBJReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkOffsetsManagerArray.h b/IO/vtkOffsetsManagerArray.h new file mode 100644 index 0000000..40f2960 --- /dev/null +++ b/IO/vtkOffsetsManagerArray.h @@ -0,0 +1,168 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOffsetsManagerArray.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME OffsetsManager - Helper class due to PIMPL excess +// .SECTION Description +// This class is deisgned to work within vtkXMLWriter. It store a position +// in a file (unsigned long) and associate a offset in the file. This is +// usefull when writting TimeStep XML file when you want to forward the +// same offset from the AppendData section on every entry in let say +// definition +// Example: +// +// +// +// ... +// +// Therefore data is only stored once in the XML file. At read time the +// offset value is stored to determine whenever we need to read data +// (ie when offset different from previously stored offset) + +// .SECTION See Also +// vtkXMLWriter +// .SECTION Warning +// Do not include this file in a header file, it will break PIMPL convention + +#ifndef vtkOffsetsManager_DoNotInclude +#error "do not include unless you know what you are doing" +#endif + +#ifndef __vtkOffsetsManagerArray_h +#define __vtkOffsetsManagerArray_h + +#include "vtkSystemIncludes.h" +#include +#include + +//---------------------------------------------------------------------------- +class OffsetsManager +{ +public: + // Construct with default (unsigned long)-1 MTime + OffsetsManager() + { + this->LastMTime = (unsigned long)-1; //almost invalid state + } + ~OffsetsManager() + { + } + void Allocate(int numTimeStep) + { + assert( numTimeStep > 0); + this->Positions.resize(numTimeStep); + this->OffsetValues.resize(numTimeStep); + } + unsigned long &GetPosition(unsigned int t) + { + assert( t < this->Positions.size()); + return this->Positions[t]; + } + unsigned long &GetOffsetValue(unsigned int t) + { + assert( t < this->OffsetValues.size()); + return this->OffsetValues[t]; + } + unsigned long &GetLastMTime() + { + return this->LastMTime; + } +private: + unsigned long LastMTime; // Previously written dataarray mtime + vtkstd::vector Positions; // Position in the stream to write the offset + vtkstd::vector OffsetValues; // Value of offset +}; + +//---------------------------------------------------------------------------- +class OffsetsManagerGroup +{ +public: + // This is kind of a hack since we need to consider both the case of Points with + // only one array over time and PointData with possibly multiple array over time + // therefore we need to use a OffsetsManagerGroup for representing offset from + // Points but OffsetsManagerArray for PointData. In both case the toplevel structure + // is a container of Pieces... + OffsetsManager &GetPiece(unsigned int index) + { + assert( index < this->Internals.size()); + OffsetsManager &e = this->Internals[index]; + return e; + } + // GetElement should be used when manipulating a OffsetsManagerArray + OffsetsManager &GetElement(unsigned int index) + { + // commenting the following out, this is an heisenbug which only appears on gcc + // when exporting GLIBCPP_NEW=1. If you try to print the value or run through gdb + // it desepears + //assert( index < this->Internals.size()); + OffsetsManager &e = this->Internals[index]; + return e; + } + unsigned int GetNumberOfElements() + { + return this->Internals.size(); + } + void Allocate(int numElements) + { + assert(numElements >= 0); //allow 0 for empty FieldData + this->Internals.resize(numElements); + } + void Allocate(int numElements, int numTimeSteps) + { + assert(numElements > 0); + assert(numTimeSteps > 0); + this->Internals.resize(numElements); + for(int i=0; iInternals[i].Allocate(numTimeSteps); + } + } +private: + vtkstd::vector Internals; +}; + +//---------------------------------------------------------------------------- +class OffsetsManagerArray +{ +public: + OffsetsManagerGroup &GetPiece(unsigned int index) + { + assert( index < this->Internals.size()); + return this->Internals[index]; + } + void Allocate(int numPieces) + { + assert(numPieces > 0); + // Force re-initialization of values. + this->Internals.resize(0); + this->Internals.resize(numPieces); + } + void Allocate(int numPieces, int numElements, int numTimeSteps) + { + assert(numPieces > 0); + assert(numElements > 0); + assert(numTimeSteps > 0); + + // Force re-initialization of values. + this->Internals.resize(0); + this->Internals.resize(numPieces); + for(int i=0; iInternals[i].Allocate(numElements, numTimeSteps); + } + } +private: + vtkstd::vector Internals; +}; + +#endif diff --git a/IO/vtkOutputStream.cxx b/IO/vtkOutputStream.cxx new file mode 100644 index 0000000..80effbb --- /dev/null +++ b/IO/vtkOutputStream.cxx @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutputStream.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOutputStream.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkOutputStream, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkOutputStream); + +//---------------------------------------------------------------------------- +vtkOutputStream::vtkOutputStream() +{ + this->Stream = 0; +} + +//---------------------------------------------------------------------------- +vtkOutputStream::~vtkOutputStream() +{ + this->SetStream(0); +} + +//---------------------------------------------------------------------------- +void vtkOutputStream::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Stream: " << (this->Stream? "set" : "none") << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkOutputStream::StartWriting() +{ + if(!this->Stream) + { + vtkErrorMacro("StartWriting() called with no Stream set."); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkOutputStream::EndWriting() +{ + return 1; +} + +//---------------------------------------------------------------------------- +int vtkOutputStream::Write(const unsigned char* data, unsigned long length) +{ + return this->Write(reinterpret_cast(data), length); +} + +//---------------------------------------------------------------------------- +int vtkOutputStream::Write(const char* data, unsigned long length) +{ + return (this->Stream->write(data, length)? 1:0); +} diff --git a/IO/vtkOutputStream.h b/IO/vtkOutputStream.h new file mode 100644 index 0000000..3705daf --- /dev/null +++ b/IO/vtkOutputStream.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOutputStream.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOutputStream - Wraps a binary output stream with a VTK interface. +// .SECTION Description +// vtkOutputStream provides a VTK-style interface wrapping around a +// standard output stream. The access methods are virtual so that +// subclasses can transparently provide encoding of the output. Data +// lengths for Write calls refer to the length of the data in memory. +// The actual length in the stream may differ for subclasses that +// implement an encoding scheme. + +#ifndef __vtkOutputStream_h +#define __vtkOutputStream_h + +#include "vtkObject.h" + +class VTK_IO_EXPORT vtkOutputStream : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkOutputStream,vtkObject); + static vtkOutputStream *New(); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the real output stream. + vtkSetMacro(Stream, ostream*); + vtkGetMacro(Stream, ostream*); + //ETX + + // Description: + // Called after the stream position has been set by the caller, but + // before any Write calls. The stream position should not be + // adjusted by the caller until after an EndWriting call. + virtual int StartWriting(); + + // Description: + // Write output data of the given length. + virtual int Write(const unsigned char* data, unsigned long length); + int Write(const char* data, unsigned long length); + + // Description: + // Called after all desired calls to Write have been made. After + // this call, the caller is free to change the position of the + // stream. Additional writes should not be done until after another + // call to StartWriting. + virtual int EndWriting(); + +protected: + vtkOutputStream(); + ~vtkOutputStream(); + + // The real output stream. + ostream* Stream; + +private: + vtkOutputStream(const vtkOutputStream&); // Not implemented. + void operator=(const vtkOutputStream&); // Not implemented. +}; + +#endif diff --git a/IO/vtkPDBReader.cxx b/IO/vtkPDBReader.cxx new file mode 100644 index 0000000..c12d3ff --- /dev/null +++ b/IO/vtkPDBReader.cxx @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPDBReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkPDBReader.h" + +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkIdTypeArray.h" + +vtkCxxRevisionMacro(vtkPDBReader, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkPDBReader); + +vtkPDBReader::vtkPDBReader() +{ +} + +vtkPDBReader::~vtkPDBReader() +{ +} + +void vtkPDBReader::ReadSpecificMolecule(FILE* fp) +{ + char linebuf[82], dum1[8], dum2[8]; + char atype[4+1]; + int hydr = 0; + int i, j; + float x[3]; + + this->NumberOfAtoms = 0; + this->Points->Allocate(500); + this->AtomType->Allocate(500); + + vtkDebugMacro( << "PDB File (" << this->HBScale + << ", " << this->BScale << ")"); + while(fgets(linebuf, sizeof linebuf, fp) != NULL && + strncmp("END", linebuf, 3)) + { + if((0==strncmp("ATOM",linebuf,4) || 0==strncmp("atom",linebuf,4)) || + (0==strncmp("HETATM",linebuf,6) || 0==strncmp("hetatm",linebuf,6))) + { + sscanf(&linebuf[12],"%4s", dum1); + sscanf(&linebuf[17],"%3s", dum2); + sscanf(&linebuf[30],"%8f%8f%8f", x, x+1, x+2); + if(hydr == 0) + { + this->Points->InsertNextPoint(x); + + for(j=0, i=static_cast(strspn(dum1, " ")); i < 5; i++) + { + atype[j++] = dum1[i]; + } + + this->NumberOfAtoms++; + } + else if( !(dum1[0]=='H' || dum1[0]=='h') ) + { /* skip hydrogen */ + this->Points->InsertNextPoint(x); + for(j=0, i=static_cast(strspn(dum1, " ")); i < 5; i++) + { + atype[j++] = dum1[i]; + } + + //sprintf(aamin[NumberOfAtoms],"%3s", dum2); + this->NumberOfAtoms++; + } + this->AtomType->InsertNextValue(this->MakeAtomType(atype)); + } + } + this->Points->Squeeze(); +} + +void vtkPDBReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkPDBReader.h b/IO/vtkPDBReader.h new file mode 100644 index 0000000..35a7910 --- /dev/null +++ b/IO/vtkPDBReader.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPDBReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPDBReader - read Molecular Data files +// .SECTION Description +// vtkPDBReader is a source object that reads Molecule files +// The FileName must be specified +// +// .SECTION Thanks +// Dr. Jean M. Favre who developed and contributed this class + +#ifndef __vtkPDBReader_h +#define __vtkPDBReader_h + +#include "vtkMoleculeReaderBase.h" + + +class VTK_IO_EXPORT vtkPDBReader : public vtkMoleculeReaderBase +{ +public: + vtkTypeRevisionMacro(vtkPDBReader,vtkMoleculeReaderBase); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkPDBReader *New(); + +protected: + vtkPDBReader(); + ~vtkPDBReader(); + + void ReadSpecificMolecule(FILE* fp); + +private: + vtkPDBReader(const vtkPDBReader&); // Not implemented. + void operator=(const vtkPDBReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkPLOT3DReader.cxx b/IO/vtkPLOT3DReader.cxx new file mode 100644 index 0000000..feed123 --- /dev/null +++ b/IO/vtkPLOT3DReader.cxx @@ -0,0 +1,2025 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLOT3DReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPLOT3DReader.h" + +#include "vtkByteSwap.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkIntArray.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStructuredGrid.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkPLOT3DReader, "$Revision: 1.84 $"); +vtkStandardNewMacro(vtkPLOT3DReader); + +#define VTK_RHOINF 1.0 +#define VTK_CINF 1.0 +#define VTK_PINF ((VTK_RHOINF*VTK_CINF) * (VTK_RHOINF*VTK_CINF) / this->Gamma) +#define VTK_CV (this->R / (this->Gamma-1.0)) + +vtkPLOT3DReader::vtkPLOT3DReader() +{ + this->XYZFileName = NULL; + this->QFileName = NULL; + this->BinaryFile = 1; + this->HasByteCount = 0; + this->FileSize = 0; + this->MultiGrid = 0; + this->ForceRead = 0; + this->ByteOrder = FILE_BIG_ENDIAN; + this->IBlanking = 0; + this->TwoDimensionalGeometry = 0; + this->DoNotReduceNumberOfOutputs = 1; + + this->R = 1.0; + this->Gamma = 1.4; + this->Uvinf = 0.0; + this->Vvinf = 0.0; + this->Wvinf = 0.0; + + this->FunctionList = vtkIntArray::New(); + + this->ScalarFunctionNumber = -1; + this->SetScalarFunctionNumber(100); + this->VectorFunctionNumber = -1; + this->SetVectorFunctionNumber(202); + + this->PointCache = 0; + this->IBlankCache = 0; +} + +vtkPLOT3DReader::~vtkPLOT3DReader() +{ + delete [] this->XYZFileName; + delete [] this->QFileName; + this->FunctionList->Delete(); + this->ClearGeometryCache(); +} + +void vtkPLOT3DReader::ClearGeometryCache() +{ + if ( this->PointCache ) + { + for ( int g=0; this->PointCache[g]; ++g ) + this->PointCache[g]->UnRegister( this ); + + delete [] this->PointCache; + this->PointCache = 0; + } + + if ( this->IBlankCache ) + { + for ( int i=0; this->IBlankCache[i]; ++i ) + this->IBlankCache[i]->UnRegister( this ); + + delete [] this->IBlankCache; + this->IBlankCache = 0; + } +} + +int vtkPLOT3DReader::CheckFile(FILE*& fp, const char* fname) +{ + if (this->BinaryFile) + { + fp = fopen(fname, "rb"); + } + else + { + fp = fopen(fname, "r"); + } + if ( fp == NULL) + { + this->SetErrorCode(vtkErrorCode::FileNotFoundError); + vtkErrorMacro(<< "File: " << fname << " not found."); + return VTK_ERROR; + } + return VTK_OK; +} + +int vtkPLOT3DReader::CheckGeometryFile(FILE*& xyzFp) +{ + if ( this->XYZFileName == NULL || this->XYZFileName[0] == '\0' ) + { + this->SetErrorCode(vtkErrorCode::NoFileNameError); + vtkErrorMacro(<< "Must specify geometry file"); + return VTK_ERROR; + } + return this->CheckFile(xyzFp, this->XYZFileName); +} + +int vtkPLOT3DReader::CheckSolutionFile(FILE*& qFp) +{ + if ( this->QFileName == NULL || this->QFileName[0] == '\0' ) + { + this->SetErrorCode(vtkErrorCode::NoFileNameError); + vtkErrorMacro(<< "Must specify geometry file"); + return VTK_ERROR; + } + return this->CheckFile(qFp, this->QFileName); +} + +// Skip Fortran style byte count. +void vtkPLOT3DReader::SkipByteCount(FILE* fp) +{ + if (this->BinaryFile && this->HasByteCount) + { + int tmp; + fread(&tmp, sizeof(int), 1, fp); + } +} + +// Read a block of ints (ascii or binary) and return number read. +int vtkPLOT3DReader::ReadIntBlock(FILE* fp, int n, int* block) +{ + if (this->BinaryFile) + { + int retVal=static_cast(fread(block, sizeof(int), n, fp)); + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + return retVal; + } + else + { + int count = 0; + for(int i=0; i 0 ) + { + count++; + } + else + { + return 0; + } + } + return count; + } +} + +int vtkPLOT3DReader::ReadFloatBlock(FILE* fp, int n, float* block) +{ + if (this->BinaryFile) + { + int retVal=static_cast(fread(block, sizeof(float), n, fp)); + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + return retVal; + } + else + { + int count = 0; + for(int i=0; i 0 ) + { + count++; + } + else + { + return 0; + } + } + return count; + } +} + +// Read a block of floats (ascii or binary) and return number read. +void vtkPLOT3DReader::CalculateFileSize(FILE* fp) +{ + long curPos = ftell(fp); + fseek(fp, 0, SEEK_END); + this->FileSize = ftell(fp); + fseek(fp, curPos, SEEK_SET); +} + + +// Estimate the size of a grid (binary file only) +long vtkPLOT3DReader::EstimateSize(int ni, int nj, int nk) +{ + long size; // the header portion, 3 ints + if (!this->TwoDimensionalGeometry) + { + size = 3*4; + size += ni*nj*nk*3*4; // x, y, z + } + else + { + size = 2*4; + size += ni*nj*nk*2*4; // x, y, z + } + if (this->HasByteCount) + { + size += 2*4; // the byte counts + } + if (this->IBlanking) + { + size += ni*nj*nk*4; + } + + return size; +} + +int vtkPLOT3DReader::CanReadBinaryFile(const char* fname) +{ + FILE* xyzFp; + + if (!fname || fname[0] == '\0') + { + return 0; + } + + if ( this->CheckFile(xyzFp, fname) != VTK_OK) + { + return 0; + } + + this->CalculateFileSize(xyzFp); + + int numOutputs = this->GetNumberOfOutputsInternal(xyzFp, 1); + fclose(xyzFp); + if (numOutputs != 0) + { + return 1; + } + return 0; +} + +int vtkPLOT3DReader::GetNumberOfOutputs() +{ + FILE* xyzFp; + + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return 0; + } + this->CalculateFileSize(xyzFp); + int numOutputs = this->GetNumberOfOutputsInternal(xyzFp, 1); + fclose(xyzFp); + if (numOutputs != 0) + { + return numOutputs; + } + return 1; +} + +int vtkPLOT3DReader::GenerateDefaultConfiguration() +{ + FILE* xyzFp; + + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return 0; + } + char buf[1024]; + fread(buf, 1, 1024, xyzFp); + int retVal = this->VerifySettings(buf, 1024); + fclose(xyzFp); + return retVal; +} + +void vtkPLOT3DReader::ReadIntBlockV(char** buf, int n, int* block) +{ + memcpy(block, *buf, sizeof(int)*n); + + if (this->ByteOrder == FILE_LITTLE_ENDIAN) + { + vtkByteSwap::Swap4LERange(block, n); + } + else + { + vtkByteSwap::Swap4BERange(block, n); + } + *buf += sizeof(int); +} + +void vtkPLOT3DReader::SkipByteCountV(char** buf) +{ + if (this->HasByteCount) + { + *buf += sizeof(int); + } +} + +int vtkPLOT3DReader::VerifySettings(char* buf, int vtkNotUsed(bufSize)) +{ + int numGrid=0; + + if ( this->MultiGrid ) + { + this->SkipByteCountV(&buf); + this->ReadIntBlockV(&buf, 1, &numGrid); + this->SkipByteCountV(&buf); + } + else + { + numGrid=1; + } + + int retVal=1; + + long fileSize = 0; + // Size of number of grids information. + if ( this->MultiGrid ) + { + fileSize += 4; // numGrids + if (this->HasByteCount) + { + fileSize += 4*4; // byte counts for the header + } + } + + // Add the size of each grid. + this->SkipByteCountV(&buf); + for(int i=0; iReadIntBlockV(&buf, 1, &ni); + this->ReadIntBlockV(&buf, 1, &nj); + if (!this->TwoDimensionalGeometry) + { + this->ReadIntBlockV(&buf, 1, &nk); + } + else + { + nk = 1; + } + fileSize += this->EstimateSize(ni, nj, nk); + // If this number is larger than the file size, there + // is something wrong. + if ( fileSize > this->FileSize ) + { + retVal = 0; + break; + } + } + this->SkipByteCountV(&buf); + // If this number is different than the file size, there + // is something wrong. + if ( fileSize != this->FileSize ) + { + retVal = 0; + } + + return retVal; +} + +// Read the header and return the number of grids. +int vtkPLOT3DReader::GetNumberOfOutputsInternal(FILE* xyzFp, int verify) +{ + int numGrid=0; + int numOutputs; + + if ( this->MultiGrid ) + { + this->SkipByteCount(xyzFp); + this->ReadIntBlock(xyzFp, 1, &numGrid); + this->SkipByteCount(xyzFp); + } + else + { + numGrid=1; + } + + if (!verify) + { + // We were told not the verify the number of grid. Just return it. + numOutputs = numGrid; + } + else + { + // We were told to make sure that the file can really contain + // the number of grid in the header (we can only check this + // if file is binary) + int error=0; + if ( this->BinaryFile ) + { + // Store the beginning of first grid. + long pos = ftell(xyzFp); + + long fileSize = 0; + // Size of number of grids information. + if ( this->MultiGrid ) + { + fileSize += 4; // numGrids + if (this->HasByteCount) + { + fileSize += 4*4; // byte counts for the header + } + } + // Add the size of each grid. + this->SkipByteCount(xyzFp); + for(int i=0; iReadIntBlock(xyzFp, 1, &ni); + this->ReadIntBlock(xyzFp, 1, &nj); + if (!this->TwoDimensionalGeometry) + { + this->ReadIntBlock(xyzFp, 1, &nk); + } + else + { + nk = 1; + } + fileSize += this->EstimateSize(ni, nj, nk); + // If this number is larger than the file size, there + // is something wrong. + if ( fileSize > this->FileSize ) + { + error = 1; + break; + } + } + this->SkipByteCount(xyzFp); + // If this number is different than the file size, there + // is something wrong. + if ( fileSize != this->FileSize && !this->ForceRead) + { + this->SetErrorCode(vtkErrorCode::FileFormatError); + error = 1; + } + + fseek(xyzFp, pos, SEEK_SET); + } + else + { + if (numGrid == 0) + { + this->SetErrorCode(vtkErrorCode::FileFormatError); + } + } + + // Now set the number of outputs. + if (!error && numGrid != 0) + { + if ( !this->DoNotReduceNumberOfOutputs || + numGrid > this->NumberOfOutputs ) + { + this->SetNumberOfOutputs(numGrid); + } + for (int i=1; iOutputs[i]) + { + vtkStructuredGrid* sg = vtkStructuredGrid::New(); + this->SetNthOutput(i, sg); + sg->Delete(); + } + } + numOutputs = numGrid; + } + else + { + numOutputs = 0; + } + } + + return numOutputs; +} + +int vtkPLOT3DReader::ReadGeometryHeader(FILE* fp) +{ + int numGrid = this->GetNumberOfOutputsInternal(fp, 1); + int i; + vtkDebugMacro("Geometry number of grids: " << numGrid); + if ( numGrid == 0 ) + { + // Bad file, set all extents to invalid. + for (i=0; iNumberOfOutputs; i++) + { + this->GetOutput(i)->SetWholeExtent(0, -1, 0, -1, 0, -1); + } + return VTK_ERROR; + } + + // Read and set extents of all outputs. + this->SkipByteCount(fp); + for(i=0; iReadIntBlock(fp, 1, &ni); + this->ReadIntBlock(fp, 1, &nj); + if (!this->TwoDimensionalGeometry) + { + this->ReadIntBlock(fp, 1, &nk); + } + else + { + nk = 1; + } + vtkDebugMacro("Geometry, block " << i << " dimensions: " + << ni << " " << nj << " " << nk); + this->GetOutput(i)->SetWholeExtent(0, ni-1, 0, nj-1, 0, nk-1); + } + this->SkipByteCount(fp); + + if ( !this->PointCache ) + { + this->PointCache = new vtkFloatArray*[ this->NumberOfOutputs + 1 ]; + this->IBlankCache = new vtkUnsignedCharArray* [ this->NumberOfOutputs + 1 ]; + for ( int g=0; g < this->NumberOfOutputs+1; ++g ) + { + this->PointCache[g] = 0; + this->IBlankCache[g] = 0; + } + } + return VTK_OK; +} + +int vtkPLOT3DReader::ReadQHeader(FILE* fp) +{ + int numGrid = this->GetNumberOfOutputsInternal(fp, 0); + vtkDebugMacro("Q number of grids: " << numGrid); + if ( numGrid == 0 ) + { + return VTK_ERROR; + } + + this->SkipByteCount(fp); + for(int i=0; iReadIntBlock(fp, 1, &ni); + this->ReadIntBlock(fp, 1, &nj); + this->ReadIntBlock(fp, 1, &nk); + vtkDebugMacro("Q, block " << i << " dimensions: " + << ni << " " << nj << " " << nk); + + int extent[6]; + this->GetOutput(i)->GetWholeExtent(extent); + if ( extent[1] != ni-1 || extent[3] != nj-1 || extent[5] != nk-1) + { + this->SetErrorCode(vtkErrorCode::FileFormatError); + vtkErrorMacro("Geometry and data dimensions do not match. " + "Data file may be corrupt."); + return VTK_ERROR; + } + } + this->SkipByteCount(fp); + return VTK_OK; +} + +void vtkPLOT3DReader::SetXYZFileName( const char* name ) +{ + if ( this->XYZFileName && ! strcmp( this->XYZFileName, name ) ) + { + return; + } + + if ( this->XYZFileName ) + { + delete [] this->XYZFileName; + } + + if ( name ) + { + this->XYZFileName = new char [ strlen( name ) + 1 ]; + strcpy( this->XYZFileName, name ); + } + else + { + this->XYZFileName = 0; + } + + this->ClearGeometryCache(); + this->Modified(); +} + +void vtkPLOT3DReader::SetScalarFunctionNumber(int num) +{ + if ( this->ScalarFunctionNumber == num) + { + return; + } + if (num >= 0) + { + // If this function is not in the list, add it. + int found=0; + for (int i=0; i < this->FunctionList->GetNumberOfTuples(); i++ ) + { + if ( this->FunctionList->GetValue(i) == num ) + { + found=1; + } + } + if (!found) + { + this->AddFunction(num); + } + } + this->ScalarFunctionNumber = num; +} + +void vtkPLOT3DReader::SetVectorFunctionNumber(int num) +{ + if ( this->VectorFunctionNumber == num) + { + return; + } + if (num >= 0) + { + // If this function is not in the list, add it. + int found=0; + for (int i=0; i < this->FunctionList->GetNumberOfTuples(); i++ ) + { + if ( this->FunctionList->GetValue(i) == num ) + { + found=1; + } + } + if (!found) + { + this->AddFunction(num); + } + } + this->VectorFunctionNumber = num; +} + +void vtkPLOT3DReader::RemoveFunction(int fnum) +{ + for (int i=0; i < this->FunctionList->GetNumberOfTuples(); i++ ) + { + if ( this->FunctionList->GetValue(i) == fnum ) + { + this->FunctionList->SetValue(i,-1); + this->Modified(); + } + } +} + +void vtkPLOT3DReader::ExecuteInformation() +{ + FILE* xyzFp; + + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return; + } + + this->CalculateFileSize(xyzFp); + this->ReadGeometryHeader(xyzFp); + + fclose(xyzFp); +} + +void vtkPLOT3DReader::Execute() +{ + this->SetErrorCode(vtkErrorCode::NoError); + + int i; + int ndim, nx, ny, nz; + int numberOfDims; + vtkIdType index; + + // Don't read the geometry if we already have it! + if ( (!this->PointCache) || (!this->PointCache[0]) ) + { + FILE* xyzFp; + if ( this->CheckGeometryFile(xyzFp) != VTK_OK) + { + return; + } + + if ( this->ReadGeometryHeader(xyzFp) != VTK_OK ) + { + vtkErrorMacro("Error reading geometry file."); + fclose(xyzFp); + return; + } + + if (!this->TwoDimensionalGeometry) + { + numberOfDims = 3; + } + else + { + numberOfDims = 2; + } + + for(i=0; iNumberOfOutputs; i++) + { + + // Read the geometry of this grid. + this->SkipByteCount(xyzFp); + + vtkStructuredGrid* nthOutput = this->GetOutput(i); + int dims[6]; + nthOutput->GetWholeExtent(dims); + nthOutput->SetExtent(dims); + nthOutput->GetDimensions(dims); + this->PointCache[i] = vtkFloatArray::New(); + this->PointCache[i]->SetNumberOfComponents(3); + this->PointCache[i]->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + + vtkPoints* points = vtkPoints::New(); + points->SetData(this->PointCache[i]); + nthOutput->SetPoints(points); + points->Delete(); + this->PointCache[i]->Register( this ); + this->PointCache[i]->Delete(); + + float coord; + for(ndim=0; ndim < numberOfDims; ndim++) + { + for(nz=0; nz < dims[2]; nz++) + { + for(ny=0; ny < dims[1]; ny++) + { + for(nx=0; nx < dims[0]; nx++) + { + if ( this->ReadFloatBlock(xyzFp, 1, &coord) == 0 ) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the geometry file (or the file is corrupt)."); + this->SetErrorCode(vtkErrorCode::PrematureEndOfFileError); + // We need to generate output (otherwise, this filter will + // keep executing). So we produce all 0's + double nullpt[3] = {0.0, 0.0, 0.0}; + vtkIdType ipts, npts=this->PointCache[i]->GetNumberOfTuples(); + for(ipts=0; ipts < npts; ipts++) + { + this->PointCache[i]->SetTuple(ipts, nullpt); + } + fclose(xyzFp); + return; + } + index = nz*dims[0]*dims[1]+ny*dims[0]+nx; + this->PointCache[i]->SetComponent(index, ndim, coord); + } + } + } + } + + if (this->TwoDimensionalGeometry) + { + vtkIdType ipts, npts=this->PointCache[i]->GetNumberOfTuples(); + for(ipts=0; ipts < npts; ipts++) + { + this->PointCache[i]->SetComponent(ipts, 2, 0); + } + } + + if (this->IBlanking) + { + this->IBlankCache[i] = vtkUnsignedCharArray::New(); + this->IBlankCache[i]->SetNumberOfComponents(1); + this->IBlankCache[i]->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + this->IBlankCache[i]->SetName("Visibility"); + int* ib = new int[dims[0]*dims[1]*dims[2]]; + if ( this->ReadIntBlock(xyzFp, dims[0]*dims[1]*dims[2], ib) == 0) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the q file (or the file is corrupt)."); + this->SetErrorCode(vtkErrorCode::PrematureEndOfFileError); + fclose(xyzFp); + return; + } + vtkIdType ipts, npts=this->IBlankCache[i]->GetNumberOfTuples(); + unsigned char* ib2 = this->IBlankCache[i]->GetPointer(0); + for (ipts=0; iptsSetPointVisibilityArray(this->IBlankCache[i]); + this->IBlankCache[i]->Register( this ); + this->IBlankCache[i]->Delete(); + } + this->SkipByteCount(xyzFp); + } + + fclose(xyzFp); + } + else + { + numberOfDims = this->TwoDimensionalGeometry ? 2 : 3; + + for(i=0; iNumberOfOutputs; i++) + { + vtkStructuredGrid* nthOutput = this->GetOutput(i); + int dims[6]; + nthOutput->GetWholeExtent(dims); + nthOutput->SetExtent(dims); + + vtkPoints* points = vtkPoints::New(); + points->SetData(this->PointCache[i]); + nthOutput->SetPoints(points); + points->Delete(); + + if (this->IBlanking) + { + nthOutput->SetPointVisibilityArray(this->IBlankCache[i]); + } + } + } + + // Now read the solution. + if (this->QFileName && this->QFileName[0] != '\0') + { + FILE* qFp; + if ( this->CheckSolutionFile(qFp) != VTK_OK) + { + return; + } + + if ( this->ReadQHeader(qFp) != VTK_OK ) + { + fclose(qFp); + return; + } + + for(i=0; iNumberOfOutputs; i++) + { + vtkStructuredGrid* nthOutput = this->GetOutput(i); + + float fsmach, alpha, re, time; + + this->SkipByteCount(qFp); + this->ReadFloatBlock(qFp, 1, &fsmach); + this->ReadFloatBlock(qFp, 1, &alpha); + this->ReadFloatBlock(qFp, 1, &re); + this->ReadFloatBlock(qFp, 1, &time); + this->SkipByteCount(qFp); + + // Save the properties first + vtkFloatArray* properties = vtkFloatArray::New(); + properties->SetName("Properties"); + properties->SetNumberOfTuples(4); + properties->SetTuple1(0, fsmach); + properties->SetTuple1(1, alpha); + properties->SetTuple1(2, re); + properties->SetTuple1(3, time); + nthOutput->GetFieldData()->AddArray(properties); + properties->Delete(); + + int dims[6]; + nthOutput->GetWholeExtent(dims); + nthOutput->SetExtent(dims); + nthOutput->GetDimensions(dims); + + this->SkipByteCount(qFp); + + vtkFloatArray* density = vtkFloatArray::New(); + density->SetNumberOfComponents(1); + density->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + density->SetName("Density"); + float* dens = density->GetPointer(0); + if ( this->ReadFloatBlock(qFp, dims[0]*dims[1]*dims[2], dens) == 0) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the q file (or the file is corrupt)."); + this->SetErrorCode(vtkErrorCode::PrematureEndOfFileError); + fclose(qFp); + return; + } + nthOutput->GetPointData()->AddArray(density); + density->Delete(); + + vtkFloatArray* momentum = vtkFloatArray::New(); + momentum->SetNumberOfComponents(3); + momentum->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + momentum->SetName("Momentum"); + + float comp; + for(ndim=0; ndim < numberOfDims; ndim++) + { + for(nz=0; nz < dims[2]; nz++) + { + for(ny=0; ny < dims[1]; ny++) + { + for(nx=0; nx < dims[0]; nx++) + { + if ( this->ReadFloatBlock(qFp, 1, &comp) == 0 ) + { + vtkErrorMacro("Encountered premature end-of-file while " + "reading the q file (or the file is corrupt)."); + fclose(qFp); + return; + } + index = nz*dims[0]*dims[1]+ny*dims[0]+nx; + momentum->SetComponent(index, ndim, comp); + } + } + } + } + if (this->TwoDimensionalGeometry) + { + vtkIdType ipts, npts=momentum->GetNumberOfTuples(); + for(ipts=0; ipts < npts; ipts++) + { + momentum->SetComponent(ipts, 2, 0); + } + } + + nthOutput->GetPointData()->AddArray(momentum); + momentum->Delete(); + + vtkFloatArray* se = vtkFloatArray::New(); + se->SetNumberOfComponents(1); + se->SetNumberOfTuples( dims[0]*dims[1]*dims[2] ); + se->SetName("StagnationEnergy"); + float* sen = se->GetPointer(0); + if (this->ReadFloatBlock(qFp, dims[0]*dims[1]*dims[2], sen) == 0) + { + vtkErrorMacro("Encountered premature end-of-file while reading " + "the q file (or the file is corrupt)."); + fclose(qFp); + return; + } + nthOutput->GetPointData()->AddArray(se); + se->Delete(); + + + if ( this->FunctionList->GetNumberOfTuples() > 0 ) + { + int fnum; + for (int tup=0; tup < this->FunctionList->GetNumberOfTuples(); tup++) + { + if ( (fnum=this->FunctionList->GetValue(tup)) >= 0 ) + { + this->MapFunction(fnum, nthOutput); + } + } + } + this->AssignAttribute(this->ScalarFunctionNumber, nthOutput, + vtkDataSetAttributes::SCALARS); + this->AssignAttribute(this->VectorFunctionNumber, nthOutput, + vtkDataSetAttributes::VECTORS); + } + fclose(qFp); + } + +} + +// Various PLOT3D functions..................... +void vtkPLOT3DReader::MapFunction(int fNumber, vtkStructuredGrid* output) +{ + switch (fNumber) + { + case 100: //Density + break; + + case 110: //Pressure + this->ComputePressure(output); + break; + + case 120: //Temperature + this->ComputeTemperature(output); + break; + + case 130: //Enthalpy + this->ComputeEnthalpy(output); + break; + + case 140: //Internal Energy + break; + + case 144: //Kinetic Energy + this->ComputeKineticEnergy(output); + break; + + case 153: //Velocity Magnitude + this->ComputeVelocityMagnitude(output); + break; + + case 163: //Stagnation energy + break; + + case 170: //Entropy + this->ComputeEntropy(output); + break; + + case 184: //Swirl + this->ComputeSwirl(output); + break; + + case 200: //Velocity + this->ComputeVelocity(output); + break; + + case 201: //Vorticity + this->ComputeVorticity(output); + break; + + case 202: //Momentum + break; + + case 210: //PressureGradient + this->ComputePressureGradient(output); + break; + + default: + vtkErrorMacro(<<"No function number " << fNumber); + } +} + +void vtkPLOT3DReader::AssignAttribute(int fNumber, vtkStructuredGrid* output, + int attributeType) +{ + switch (fNumber) + { + case -1: //empty mapping + output->GetPointData()->SetActiveAttribute(0, + attributeType); + break; + + case 100: //Density + output->GetPointData()->SetActiveAttribute("Density", + attributeType); + break; + + case 110: //Pressure + output->GetPointData()->SetActiveAttribute("Pressure", + attributeType); + break; + + case 120: //Temperature + output->GetPointData()->SetActiveAttribute("Temperature", + attributeType); + break; + + case 130: //Enthalpy + output->GetPointData()->SetActiveAttribute("Enthalpy", + attributeType); + break; + + case 140: //Internal Energy + output->GetPointData()->SetActiveAttribute("StagnationEnergy", + attributeType); + break; + + case 144: //Kinetic Energy + output->GetPointData()->SetActiveAttribute("KineticEnergy", + attributeType); + break; + + case 153: //Velocity Magnitude + output->GetPointData()->SetActiveAttribute("VelocityMagnitude", + attributeType); + break; + + case 163: //Stagnation energy + output->GetPointData()->SetActiveAttribute("StagnationEnergy", + attributeType); + break; + + case 170: //Entropy + output->GetPointData()->SetActiveAttribute("Entropy", + attributeType); + break; + + case 184: //Swirl + output->GetPointData()->SetActiveAttribute("Swirl", + attributeType); + break; + + case 200: //Velocity + output->GetPointData()->SetActiveAttribute("Velocity", + attributeType); + break; + + case 201: //Vorticity + output->GetPointData()->SetActiveAttribute("Vorticity", + attributeType); + break; + + case 202: //Momentum + output->GetPointData()->SetActiveAttribute("Momentum", + attributeType); + break; + + case 210: //PressureGradient + output->GetPointData()->SetActiveAttribute("PressureGradient", + attributeType); + break; + + default: + vtkErrorMacro(<<"No function number " << fNumber); + } +} + +void vtkPLOT3DReader::ComputeTemperature(vtkStructuredGrid* output) +{ + double *m, e, rr, u, v, w, v2, p, d, rrgas; + vtkIdType i; + vtkFloatArray *temperature; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute temperature"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + temperature = vtkFloatArray::New(); + temperature->SetNumberOfTuples(numPts); + + // Compute the temperature + // + rrgas = 1.0 / this->R; + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + p = (this->Gamma-1.) * (e - 0.5 * d * v2); + temperature->SetValue(i, p*rr*rrgas); + } + + temperature->SetName("Temperature"); + outputPD->AddArray(temperature); + + temperature->Delete(); + vtkDebugMacro(<<"Created temperature scalar"); +} + +void vtkPLOT3DReader::ComputePressure(vtkStructuredGrid* output) +{ + double *m, e, u, v, w, v2, p, d, rr; + vtkIdType i; + vtkFloatArray *pressure; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute pressure"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + pressure = vtkFloatArray::New(); + pressure->SetNumberOfTuples(numPts); + + // Compute the pressure + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + p = (this->Gamma-1.) * (e - 0.5 * d * v2); + pressure->SetValue(i, p); + } + + pressure->SetName("Pressure"); + outputPD->AddArray(pressure); + pressure->Delete(); + vtkDebugMacro(<<"Created pressure scalar"); +} + +void vtkPLOT3DReader::ComputeEnthalpy(vtkStructuredGrid* output) +{ + double *m, e, u, v, w, v2, d, rr; + vtkIdType i; + vtkFloatArray *enthalpy; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute enthalpy"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + enthalpy = vtkFloatArray::New(); + enthalpy->SetNumberOfTuples(numPts); + + // Compute the enthalpy + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + enthalpy->SetValue(i, this->Gamma*(e*rr - 0.5*v2)); + } + enthalpy->SetName("Enthalpy"); + outputPD->AddArray(enthalpy); + enthalpy->Delete(); + vtkDebugMacro(<<"Created enthalpy scalar"); +} + +void vtkPLOT3DReader::ComputeKineticEnergy(vtkStructuredGrid* output) +{ + double *m, u, v, w, v2, d, rr; + vtkIdType i; + vtkFloatArray *kineticEnergy; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + if ( density == NULL || momentum == NULL ) + { + vtkErrorMacro(<<"Cannot compute kinetic energy"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + kineticEnergy = vtkFloatArray::New(); + kineticEnergy->SetNumberOfTuples(numPts); + + // Compute the kinetic energy + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + kineticEnergy->SetValue(i, 0.5*v2); + } + kineticEnergy->SetName("KineticEnergy"); + outputPD->AddArray(kineticEnergy); + kineticEnergy->Delete(); + vtkDebugMacro(<<"Created kinetic energy scalar"); +} + +void vtkPLOT3DReader::ComputeVelocityMagnitude(vtkStructuredGrid* output) +{ + double *m, u, v, w, v2, d, rr; + vtkIdType i; + vtkFloatArray *velocityMag; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute velocity magnitude"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + velocityMag = vtkFloatArray::New(); + velocityMag->SetNumberOfTuples(numPts); + + // Compute the velocity magnitude + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + velocityMag->SetValue(i, sqrt((double)v2)); + } + velocityMag->SetName("VelocityMagnitude"); + outputPD->AddArray(velocityMag); + velocityMag->Delete(); + vtkDebugMacro(<<"Created velocity magnitude scalar"); +} + +void vtkPLOT3DReader::ComputeEntropy(vtkStructuredGrid* output) +{ + double *m, u, v, w, v2, d, rr, s, p, e; + vtkIdType i; + vtkFloatArray *entropy; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute entropy"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + entropy = vtkFloatArray::New(); + entropy->SetNumberOfTuples(numPts); + + // Compute the entropy + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + e = energy->GetComponent(i,0); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + p = (this->Gamma-1.)*(e - 0.5*d*v2); + s = VTK_CV * log((p/VTK_PINF)/pow((double)d/VTK_RHOINF,(double)this->Gamma)); + entropy->SetValue(i,s); + } + entropy->SetName("Entropy"); + outputPD->AddArray(entropy); + entropy->Delete(); + vtkDebugMacro(<<"Created entropy scalar"); +} + +void vtkPLOT3DReader::ComputeSwirl(vtkStructuredGrid* output) +{ + vtkDataArray *vorticity; + double d, rr, *m, u, v, w, v2, *vort, s; + vtkIdType i; + vtkFloatArray *swirl; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute swirl"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + swirl = vtkFloatArray::New(); + swirl->SetNumberOfTuples(numPts); + + this->ComputeVorticity(output); + vorticity = outputPD->GetArray("Vorticity"); +// +// Compute the swirl +// + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + vort = vorticity->GetTuple(i); + rr = 1.0 / d; + u = m[0] * rr; + v = m[1] * rr; + w = m[2] * rr; + v2 = u*u + v*v + w*w; + if ( v2 != 0.0 ) + { + s = (vort[0]*m[0] + vort[1]*m[1] + vort[2]*m[2]) / v2; + } + else + { + s = 0.0; + } + + swirl->SetValue(i,s); + } + swirl->SetName("Swirl"); + outputPD->AddArray(swirl); + swirl->Delete(); + vtkDebugMacro(<<"Created swirl scalar"); + +} + +// Vector functions +void vtkPLOT3DReader::ComputeVelocity(vtkStructuredGrid* output) +{ + double *m, v[3], d, rr; + vtkIdType i; + vtkFloatArray *velocity; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute velocity"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + velocity = vtkFloatArray::New(); + velocity->SetNumberOfComponents(3); + velocity->SetNumberOfTuples(numPts); + + // Compute the velocity + // + for (i=0; i < numPts; i++) + { + d = density->GetComponent(i,0); + d = (d != 0.0 ? d : 1.0); + m = momentum->GetTuple(i); + rr = 1.0 / d; + v[0] = m[0] * rr; + v[1] = m[1] * rr; + v[2] = m[2] * rr; + velocity->SetTuple(i, v); + } + velocity->SetName("Velocity"); + outputPD->AddArray(velocity); + velocity->Delete(); + vtkDebugMacro(<<"Created velocity vector"); +} + +void vtkPLOT3DReader::ComputeVorticity(vtkStructuredGrid* output) +{ + vtkDataArray *velocity; + vtkFloatArray *vorticity; + int dims[3], ijsize; + vtkPoints *points; + int i, j, k, idx, idx2, ii; + double vort[3], xp[3], xm[3], vp[3], vm[3], factor; + double xxi, yxi, zxi, uxi, vxi, wxi; + double xeta, yeta, zeta, ueta, veta, weta; + double xzeta, yzeta, zzeta, uzeta, vzeta, wzeta; + double aj, xix, xiy, xiz, etax, etay, etaz, zetax, zetay, zetaz; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( (points=output->GetPoints()) == NULL || + density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute vorticity"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + vorticity = vtkFloatArray::New(); + vorticity->SetNumberOfComponents(3); + vorticity->SetNumberOfTuples(numPts); + + this->ComputeVelocity(output); + velocity = outputPD->GetArray("Velocity"); + + output->GetDimensions(dims); + ijsize = dims[0]*dims[1]; + + for (k=0; kGetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else if ( i == (dims[0]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i-1 + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else + { + factor = 0.5; + idx = (i+1) + j*dims[0] + k*ijsize; + idx2 = (i-1) + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + + xxi = factor * (xp[0] - xm[0]); + yxi = factor * (xp[1] - xm[1]); + zxi = factor * (xp[2] - xm[2]); + uxi = factor * (vp[0] - vm[0]); + vxi = factor * (vp[1] - vm[1]); + wxi = factor * (vp[2] - vm[2]); + + // Eta derivatives. + if ( dims[1] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + vp[ii] = vm[ii] = xp[ii] = xm[ii] = 0.0; + } + xp[1] = 1.0; + } + else if ( j == 0 ) + { + factor = 1.0; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else if ( j == (dims[1]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else + { + factor = 0.5; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + + + xeta = factor * (xp[0] - xm[0]); + yeta = factor * (xp[1] - xm[1]); + zeta = factor * (xp[2] - xm[2]); + ueta = factor * (vp[0] - vm[0]); + veta = factor * (vp[1] - vm[1]); + weta = factor * (vp[2] - vm[2]); + + // Zeta derivatives. + if ( dims[2] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + vp[ii] = vm[ii] = xp[ii] = xm[ii] = 0.0; + } + xp[2] = 1.0; + } + else if ( k == 0 ) + { + factor = 1.0; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else if ( k == (dims[2]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + else + { + factor = 0.5; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + velocity->GetTuple(idx,vp); + velocity->GetTuple(idx2,vm); + } + + xzeta = factor * (xp[0] - xm[0]); + yzeta = factor * (xp[1] - xm[1]); + zzeta = factor * (xp[2] - xm[2]); + uzeta = factor * (vp[0] - vm[0]); + vzeta = factor * (vp[1] - vm[1]); + wzeta = factor * (vp[2] - vm[2]); + + // Now calculate the Jacobian. Grids occasionally have + // singularities, or points where the Jacobian is infinite (the + // inverse is zero). For these cases, we'll set the Jacobian to + // zero, which will result in a zero vorticity. + // + aj = xxi*yeta*zzeta+yxi*zeta*xzeta+zxi*xeta*yzeta + -zxi*yeta*xzeta-yxi*xeta*zzeta-xxi*zeta*yzeta; + if (aj != 0.0) + { + aj = 1. / aj; + } + + // Xi metrics. + xix = aj*(yeta*zzeta-zeta*yzeta); + xiy = -aj*(xeta*zzeta-zeta*xzeta); + xiz = aj*(xeta*yzeta-yeta*xzeta); + + // Eta metrics. + etax = -aj*(yxi*zzeta-zxi*yzeta); + etay = aj*(xxi*zzeta-zxi*xzeta); + etaz = -aj*(xxi*yzeta-yxi*xzeta); + + // Zeta metrics. + zetax= aj*(yxi*zeta-zxi*yeta); + zetay= -aj*(xxi*zeta-zxi*xeta); + zetaz= aj*(xxi*yeta-yxi*xeta); + + // Finally, the vorticity components. + // + vort[0]= xiy*wxi+etay*weta+zetay*wzeta - xiz*vxi-etaz*veta-zetaz*vzeta; + vort[1]= xiz*uxi+etaz*ueta+zetaz*uzeta - xix*wxi-etax*weta-zetax*wzeta; + vort[2]= xix*vxi+etax*veta+zetax*vzeta - xiy*uxi-etay*ueta-zetay*uzeta; + idx = i + j*dims[0] + k*ijsize; + vorticity->SetTuple(idx,vort); + } + } + } + vorticity->SetName("Vorticity"); + outputPD->AddArray(vorticity); + vorticity->Delete(); + vtkDebugMacro(<<"Created vorticity vector"); +} + +void vtkPLOT3DReader::ComputePressureGradient(vtkStructuredGrid* output) +{ + vtkDataArray *pressure; + vtkFloatArray *gradient; + int dims[3], ijsize; + vtkPoints *points; + int i, j, k, idx, idx2, ii; + double g[3], xp[3], xm[3], pp, pm, factor; + double xxi, yxi, zxi, pxi; + double xeta, yeta, zeta, peta; + double xzeta, yzeta, zzeta, pzeta; + double aj, xix, xiy, xiz, etax, etay, etaz, zetax, zetay, zetaz; + + // Check that the required data is available + // + vtkPointData* outputPD = output->GetPointData(); + vtkDataArray* density = outputPD->GetArray("Density"); + vtkDataArray* momentum = outputPD->GetArray("Momentum"); + vtkDataArray* energy = outputPD->GetArray("StagnationEnergy"); + if ( (points=output->GetPoints()) == NULL || + density == NULL || momentum == NULL || + energy == NULL ) + { + vtkErrorMacro(<<"Cannot compute pressure gradient"); + return; + } + + vtkIdType numPts = density->GetNumberOfTuples(); + gradient = vtkFloatArray::New(); + gradient->SetNumberOfComponents(3); + gradient->SetNumberOfTuples(numPts); + + this->ComputePressure(output); + pressure = outputPD->GetArray("Pressure"); + + output->GetDimensions(dims); + ijsize = dims[0]*dims[1]; + + for (k=0; kGetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else if ( i == (dims[0]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i-1 + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else + { + factor = 0.5; + idx = (i+1) + j*dims[0] + k*ijsize; + idx2 = (i-1) + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + + xxi = factor * (xp[0] - xm[0]); + yxi = factor * (xp[1] - xm[1]); + zxi = factor * (xp[2] - xm[2]); + pxi = factor * (pp - pm); + + // Eta derivatives. + if ( dims[1] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + xp[ii] = xm[ii] = 0.0; + } + xp[1] = 1.0; pp = pm = 0.0; + } + else if ( j == 0 ) + { + factor = 1.0; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else if ( j == (dims[1]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else + { + factor = 0.5; + idx = i + (j+1)*dims[0] + k*ijsize; + idx2 = i + (j-1)*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + + xeta = factor * (xp[0] - xm[0]); + yeta = factor * (xp[1] - xm[1]); + zeta = factor * (xp[2] - xm[2]); + peta = factor * (pp - pm); + + // Zeta derivatives. + if ( dims[2] == 1 ) // 2D in this direction + { + factor = 1.0; + for (ii=0; ii<3; ii++) + { + xp[ii] = xm[ii] = 0.0; + } + xp[2] = 1.0; pp = pm = 0.0; + } + else if ( k == 0 ) + { + factor = 1.0; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + k*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else if ( k == (dims[2]-1) ) + { + factor = 1.0; + idx = i + j*dims[0] + k*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + else + { + factor = 0.5; + idx = i + j*dims[0] + (k+1)*ijsize; + idx2 = i + j*dims[0] + (k-1)*ijsize; + points->GetPoint(idx,xp); + points->GetPoint(idx2,xm); + pp = pressure->GetComponent(idx,0); + pm = pressure->GetComponent(idx2,0); + } + + xzeta = factor * (xp[0] - xm[0]); + yzeta = factor * (xp[1] - xm[1]); + zzeta = factor * (xp[2] - xm[2]); + pzeta = factor * (pp - pm); + + // Now calculate the Jacobian. Grids occasionally have + // singularities, or points where the Jacobian is infinite (the + // inverse is zero). For these cases, we'll set the Jacobian to + // zero, which will result in a zero vorticity. + // + aj = xxi*yeta*zzeta+yxi*zeta*xzeta+zxi*xeta*yzeta + -zxi*yeta*xzeta-yxi*xeta*zzeta-xxi*zeta*yzeta; + if (aj != 0.0) + { + aj = 1. / aj; + } + + // Xi metrics. + xix = aj*(yeta*zzeta-zeta*yzeta); + xiy = -aj*(xeta*zzeta-zeta*xzeta); + xiz = aj*(xeta*yzeta-yeta*xzeta); + + // Eta metrics. + etax = -aj*(yxi*zzeta-zxi*yzeta); + etay = aj*(xxi*zzeta-zxi*xzeta); + etaz = -aj*(xxi*yzeta-yxi*xzeta); + + // Zeta metrics. + zetax= aj*(yxi*zeta-zxi*yeta); + zetay= -aj*(xxi*zeta-zxi*xeta); + zetaz= aj*(xxi*yeta-yxi*xeta); + + // Finally, the vorticity components. + g[0]= xix*pxi+etax*peta+zetax*pzeta; + g[1]= xiy*pxi+etay*peta+zetay*pzeta; + g[2]= xiz*pxi+etaz*peta+zetaz*pzeta; + + idx = i + j*dims[0] + k*ijsize; + gradient->SetTuple(idx,g); + } + } + } + gradient->SetName("PressureGradient"); + outputPD->AddArray(gradient); + gradient->Delete(); + vtkDebugMacro(<<"Created pressure gradient vector"); +} + +void vtkPLOT3DReader::SetByteOrderToBigEndian() +{ + this->ByteOrder = FILE_BIG_ENDIAN; +} + +void vtkPLOT3DReader::SetByteOrderToLittleEndian() +{ + this->ByteOrder = FILE_LITTLE_ENDIAN; +} + +const char *vtkPLOT3DReader::GetByteOrderAsString() +{ + if ( this->ByteOrder == FILE_LITTLE_ENDIAN) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +} + +void vtkPLOT3DReader::SetOutput(int idx, vtkStructuredGrid *output) +{ + this->Superclass::SetNthOutput(idx, output); +} + +void vtkPLOT3DReader::AddFunction(int functionNumber) +{ + this->FunctionList->InsertNextValue(functionNumber); + this->Modified(); +} + +void vtkPLOT3DReader::RemoveAllFunctions() +{ + this->FunctionList->Reset(); + this->Modified(); +} + +void vtkPLOT3DReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "XYZ File Name: " << + (this->XYZFileName ? this->XYZFileName : "(none)") << "\n"; + os << indent << "Q File Name: " << + (this->QFileName ? this->QFileName : "(none)") << "\n"; + os << indent << "BinaryFile: " << this->BinaryFile << endl; + os << indent << "HasByteCount: " << this->HasByteCount << endl; + os << indent << "Gamma: " << this->Gamma << endl; + os << indent << "R: " << this->R << endl; + os << indent << "Uvinf: " << this->Uvinf << endl; + os << indent << "Vvinf: " << this->Vvinf << endl; + os << indent << "Wvinf: " << this->Wvinf << endl; + os << indent << "ScalarFunctionNumber: " << this->ScalarFunctionNumber << endl; + os << indent << "VectorFunctionNumber: " << this->VectorFunctionNumber << endl; + os << indent << "MultiGrid: " << this->MultiGrid << endl; + os << indent << "TwoDimensionalGeometry: " + << this->TwoDimensionalGeometry << endl; + os << indent << "DoNotReduceNumberOfOutputs: " + << this->DoNotReduceNumberOfOutputs << endl; + os << indent << "ForceRead: " << this->ForceRead << endl; + os << indent << "IBlanking: " << this->IBlanking << endl; + os << indent << "ByteOrder: " << this->ByteOrder << endl; + os << indent << "TwoDimensionalGeometry: " << (this->TwoDimensionalGeometry?"on":"off") + << endl; +} + diff --git a/IO/vtkPLOT3DReader.h b/IO/vtkPLOT3DReader.h new file mode 100644 index 0000000..35ef469 --- /dev/null +++ b/IO/vtkPLOT3DReader.h @@ -0,0 +1,332 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLOT3DReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPLOT3DReader - read PLOT3D data files +// .SECTION Description +// vtkPLOT3DReader is a reader object that reads PLOT3D formatted files and +// generates structured grid(s) on output. PLOT3D is a computer graphics +// program designed to visualize the grids and solutions of computational +// fluid dynamics. Please see the "PLOT3D User's Manual" available from +// NASA Ames Research Center, Moffett Field CA. +// +// PLOT3D files consist of a grid file (also known as XYZ file), an +// optional solution file (also known as a Q file), and an optional function +// file that contains user created data (currently unsupported). The Q file +// contains solution information as follows: the four parameters free stream +// mach number (Fsmach), angle of attack (Alpha), Reynolds number (Re), and +// total integration time (Time). This information is stored in an array +// called Properties in the FieldData of each output (tuple 0: fsmach, tuple 1: +// alpha, tuple 2: re, tuple 3: time). In addition, the solution file contains +// the flow density (scalar), flow momentum (vector), and flow energy (scalar). +// +// The reader can generate additional scalars and vectors (or "functions") +// from this information. To use vtkPLOT3DReader, you must specify the +// particular function number for the scalar and vector you want to visualize. +// This implementation of the reader provides the following functions. The +// scalar functions are: +// -1 - don't read or compute any scalars +// 100 - density +// 110 - pressure +// 120 - temperature +// 130 - enthalpy +// 140 - internal energy +// 144 - kinetic energy +// 153 - velocity magnitude +// 163 - stagnation energy +// 170 - entropy +// 184 - swirl. +// +// The vector functions are: +// -1 - don't read or compute any vectors +// 200 - velocity +// 201 - vorticity +// 202 - momentum +// 210 - pressure gradient. +// +// (Other functions are described in the PLOT3D spec, but only those listed are +// implemented here.) Note that by default, this reader creates the density +// scalar (100) and momentum vector (202) as output. (These are just read in +// from the solution file.) Please note that the validity of computation is +// a function of this class's gas constants (R, Gamma) and the equations used. +// They may not be suitable for your computational domain. +// +// Additionally, you can read other data and associate it as a vtkDataArray +// into the output's point attribute data. Use the method AddFunction() +// to list all the functions that you'd like to read. AddFunction() accepts +// an integer parameter that defines the function number. +// +// .SECTION See Also +// vtkStructuredGridSource vtkStructuredGrid + +#ifndef __vtkPLOT3DReader_h +#define __vtkPLOT3DReader_h + +#include "vtkStructuredGridSource.h" + +class vtkUnsignedCharArray; +class vtkIntArray; +class vtkFloatArray; +class vtkStructuredGrid; + +class VTK_IO_EXPORT vtkPLOT3DReader : public vtkStructuredGridSource +{ +public: + static vtkPLOT3DReader *New(); + vtkTypeRevisionMacro(vtkPLOT3DReader,vtkStructuredGridSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the PLOT3D geometry filename. + void SetFileName(const char* name) { this->SetXYZFileName(name); } + const char* GetFileName() { return this->GetXYZFileName(); } + virtual void SetXYZFileName( const char* ); + vtkGetStringMacro(XYZFileName); + + // Description: + // Set/Get the PLOT3D solution filename. + vtkSetStringMacro(QFileName); + vtkGetStringMacro(QFileName); + + // Description: + // This returns the number of outputs this reader will produce. + // This number is equal to the number of grids in the current + // file. This method has to be called before getting any output + // if the number of outputs will be greater than 1 (the first + // output is always the same). Note that every time this method + // is invoked, the header file is opened and part of the header + // is read. + int GetNumberOfOutputs(); + int GetNumberOfGrids() { return this->GetNumberOfOutputs(); } + + // Description: + // Replace an output. + void SetOutput(int idx, vtkStructuredGrid *output); + + // Description: + // Is the file to be read written in binary format (as opposed + // to ascii). + vtkSetMacro(BinaryFile, int); + vtkGetMacro(BinaryFile, int); + vtkBooleanMacro(BinaryFile, int); + + // Description: + // Does the file to be read contain information about number of + // grids. In some PLOT3D files, the first value contains the number + // of grids (even if there is only 1). If reading such a file, + // set this to true. + vtkSetMacro(MultiGrid, int); + vtkGetMacro(MultiGrid, int); + vtkBooleanMacro(MultiGrid, int); + + // Description: + // Were the arrays written with leading and trailing byte counts ? + // Usually, files written by a fortran program will contain these + // byte counts whereas the ones written by C/C++ won't. + vtkSetMacro(HasByteCount, int); + vtkGetMacro(HasByteCount, int); + vtkBooleanMacro(HasByteCount, int); + + // Description: + // Is there iblanking (point visibility) information in the file. + // If there is iblanking arrays, these will be read and assigned + // to the PointVisibility array of the output. + vtkSetMacro(IBlanking, int); + vtkGetMacro(IBlanking, int); + vtkBooleanMacro(IBlanking, int); + + // Description: + // If only two-dimensional data was written to the file, + // turn this on. + vtkSetMacro(TwoDimensionalGeometry, int); + vtkGetMacro(TwoDimensionalGeometry, int); + vtkBooleanMacro(TwoDimensionalGeometry, int); + + // Description: + // Try to read a binary file even if the file length seems to be + // inconsistent with the header information. Use this with caution, + // if the file length is not the same as calculated from the header. + // either the file is corrupt or the settings are wrong. + vtkSetMacro(ForceRead, int); + vtkGetMacro(ForceRead, int); + vtkBooleanMacro(ForceRead, int); + + // Description: + // If this is on, the reader will never reduce the number of outputs + // after reading a file with n grids and producing n outputs. If the + // file read afterwards contains fewer grids, the extra outputs will + // be empty. This option can be used by application which rely on + // the initial number of outputs not shrinking. + vtkSetMacro(DoNotReduceNumberOfOutputs, int); + vtkGetMacro(DoNotReduceNumberOfOutputs, int); + vtkBooleanMacro(DoNotReduceNumberOfOutputs, int); + + // Description: + // Set the byte order of the file (remember, more Unix workstations + // write big endian whereas PCs write little endian). Default is + // big endian (since most older PLOT3D files were written by + // workstations). + void SetByteOrderToBigEndian(); + void SetByteOrderToLittleEndian(); + vtkSetMacro(ByteOrder, int); + vtkGetMacro(ByteOrder, int); + const char *GetByteOrderAsString(); + + // Description: + // Set/Get the gas constant. Default is 1.0. + vtkSetMacro(R,double); + vtkGetMacro(R,double); + + // Description: + // Set/Get the ratio of specific heats. Default is 1.4. + vtkSetMacro(Gamma,double); + vtkGetMacro(Gamma,double); + + // Description: + // Set/Get the x-component of the free-stream velocity. Default is 1.0. + vtkSetMacro(Uvinf,double); + vtkGetMacro(Uvinf,double); + + // Description: + // Set/Get the y-component of the free-stream velocity. Default is 1.0. + vtkSetMacro(Vvinf,double); + vtkGetMacro(Vvinf,double); + + // Description: + // Set/Get the z-component of the free-stream velocity. Default is 1.0. + vtkSetMacro(Wvinf,double); + vtkGetMacro(Wvinf,double); + + // Description: + // Specify the scalar function to extract. If ==(-1), then no scalar + // function is extracted. + void SetScalarFunctionNumber(int num); + vtkGetMacro(ScalarFunctionNumber,int); + + // Description: + // Specify the vector function to extract. If ==(-1), then no vector + // function is extracted. + void SetVectorFunctionNumber(int num); + vtkGetMacro(VectorFunctionNumber,int); + + // Description: + // Specify additional functions to read. These are placed into the + // point data as data arrays. Later on they can be used by labeling + // them as scalars, etc. + void AddFunction(int functionNumber); + void RemoveFunction(int); + void RemoveAllFunctions(); + + // Description: + // Return 1 if the reader can read the given file name. Only meaningful + // for binary files. + virtual int CanReadBinaryFile(const char* fname); + + // Description: + int GenerateDefaultConfiguration(); + +//BTX + enum + { + FILE_BIG_ENDIAN=0, + FILE_LITTLE_ENDIAN=1 + }; +//ETX + +protected: + vtkPLOT3DReader(); + ~vtkPLOT3DReader(); + + void ExecuteInformation(); + void Execute(); + + int CheckFile(FILE*& fp, const char* fname); + int CheckGeometryFile(FILE*& xyzFp); + int CheckSolutionFile(FILE*& qFp); + + void SkipByteCount (FILE* fp); + int ReadIntBlock (FILE* fp, int n, int* block); + int ReadFloatBlock(FILE* fp, int n, float* block); + + int GetNumberOfOutputsInternal(FILE* xyzFp, int verify=1); + + int ReadGeometryHeader(FILE* fp); + int ReadQHeader(FILE* fp); + + void CalculateFileSize(FILE* fp); + long EstimateSize(int ni, int nj, int nk); + + void AssignAttribute(int fNumber, vtkStructuredGrid* output, + int attributeType); + void MapFunction(int fNumber, vtkStructuredGrid* output); + void ComputeTemperature(vtkStructuredGrid* output); + void ComputePressure(vtkStructuredGrid* output); + void ComputeEnthalpy(vtkStructuredGrid* output); + void ComputeKineticEnergy(vtkStructuredGrid* output); + void ComputeVelocityMagnitude(vtkStructuredGrid* output); + void ComputeEntropy(vtkStructuredGrid* output); + void ComputeSwirl(vtkStructuredGrid* output); + void ComputeVelocity(vtkStructuredGrid* output); + void ComputeVorticity(vtkStructuredGrid* output); + void ComputePressureGradient(vtkStructuredGrid* output); + + // Delete references to any existing vtkPoints and + // I-blank arrays. The next Update() will (re)read + // the XYZ file. + void ClearGeometryCache(); + + //plot3d FileNames + char *XYZFileName; + char *QFileName; + + int BinaryFile; + int HasByteCount; + int TwoDimensionalGeometry; + int MultiGrid; + int ForceRead; + int ByteOrder; + int IBlanking; + int DoNotReduceNumberOfOutputs; + + long FileSize; + + //parameters used in computing derived functions + double R; + double Gamma; + double Uvinf; + double Vvinf; + double Wvinf; + + //functions to read that are not scalars or vectors + vtkIntArray *FunctionList; + + int ScalarFunctionNumber; + int VectorFunctionNumber; + + // Cache of geometry + vtkFloatArray** PointCache; + vtkUnsignedCharArray** IBlankCache; + + int VerifySettings(char* buf, int bufSize); + void ReadIntBlockV(char** buf, int n, int* block); + void SkipByteCountV(char** buf); + + +private: + vtkPLOT3DReader(const vtkPLOT3DReader&); // Not implemented. + void operator=(const vtkPLOT3DReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkPLY.cxx b/IO/vtkPLY.cxx new file mode 100644 index 0000000..3718847 --- /dev/null +++ b/IO/vtkPLY.cxx @@ -0,0 +1,2571 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLY.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + +The interface routines for reading and writing PLY polygon files. + +Greg Turk, February 1994 + +--------------------------------------------------------------- + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties the floating-point values x,y,z and the three unsigned +chars representing red, green and blue. + +--------------------------------------------------------------- + +Copyright (c) 1994 The Board of Trustees of The Leland Stanford +Junior University. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +#include "vtkPLY.h" +#include "vtkHeap.h" +#include "vtkByteSwap.h" + +#include + +/* memory allocation */ +#define myalloc(mem_size) vtkPLY::my_alloc((mem_size), __LINE__, __FILE__) + +//wjs: added to manage memory leak +static vtkHeap *plyHeap=NULL; +static void plyInitialize() +{ + if ( plyHeap == NULL ) + { + plyHeap = vtkHeap::New(); + } +} +static void plyCleanUp() +{ + if ( plyHeap ) + { + plyHeap->Delete(); + plyHeap = NULL; + } +} +static void *plyAllocateMemory(size_t n) +{ + return plyHeap->AllocateMemory(n); +} + + +const char *type_names[] = { +"invalid", +"char", "short", "int", +"uchar", "ushort", "uint", +"float", "double", +}; + +int ply_type_size[] = { + 0, 1, 2, 4, 1, 2, 4, 4, 8 +}; + +#define NO_OTHER_PROPS -1 + +#define DONT_STORE_PROP 0 +#define STORE_PROP 1 + +#define OTHER_PROP 0 +#define NAMED_PROP 1 + + +/*************/ +/* Writing */ +/*************/ + + +/****************************************************************************** +Given a file pointer, get ready to write PLY data to the file. + +Entry: + fp - the given file pointer + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + +Exit: + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *vtkPLY::ply_write( + FILE *fp, + int nelems, + const char **elem_names, + int file_type +) +{ + int i; + PlyFile *plyfile; + PlyElement *elem; + + /* check for NULL file pointer */ + if (fp == NULL) + return (NULL); + + /* create a record for this object */ + + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); + plyfile->file_type = file_type; + plyfile->num_comments = 0; + plyfile->num_obj_info = 0; + plyfile->nelems = nelems; + plyfile->version = 1.0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + + /* tuck aside the names of the elements */ + + plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems); + for (i = 0; i < nelems; i++) { + elem = (PlyElement *) myalloc (sizeof (PlyElement)); + plyfile->elems[i] = elem; + elem->name = strdup (elem_names[i]); + elem->num = 0; + elem->nprops = 0; + } + + /* return pointer to the file descriptor */ + return (plyfile); +} + + +/****************************************************************************** +Open a polygon file for writing. + +Entry: + filename - name of file to read from + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + +Exit: + version - version number of PLY file + returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *vtkPLY::ply_open_for_writing( + char *filename, + int nelems, + const char **elem_names, + int file_type, + float *version +) +{ + PlyFile *plyfile; + char *name; + FILE *fp; + + //memory leaks + plyInitialize(); + + /* tack on the extension .ply, if necessary */ + name = (char *) myalloc (sizeof (char) * + (static_cast(strlen (filename)) + 5)); + strcpy (name, filename); + if (strlen (name) < 4 || + strcmp (name + strlen (name) - 4, ".ply") != 0) + strcat (name, ".ply"); + + /* open the file for writing */ + + fp = fopen (name, "wb"); + free (name); //wjs remove memory leak// + if (fp == NULL) { + return (NULL); + } + + /* create the actual PlyFile structure */ + + plyfile = vtkPLY::ply_write (fp, nelems, elem_names, file_type); + if (plyfile == NULL) + return (NULL); + + /* say what PLY file version number we're writing */ + *version = plyfile->version; + + /* return pointer to the file descriptor */ + return (plyfile); +} + + +/****************************************************************************** +Describe an element, including its properties and how many will be written +to the file. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + nelems - number of elements of this type to be written + nprops - number of properties contained in the element + prop_list - list of properties +******************************************************************************/ + +void vtkPLY::ply_describe_element( + PlyFile *plyfile, + const char *elem_name, + int nelems, + int nprops, + PlyProperty *prop_list +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name); + exit (-1); + } + + elem->num = nelems; + + /* copy the list of properties */ + + elem->nprops = nprops; + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops); + elem->store_prop = (char *) myalloc (sizeof (char) * nprops); + + for (i = 0; i < nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + elem->props[i] = prop; + elem->store_prop[i] = NAMED_PROP; + copy_property (prop, &prop_list[i]); + } +} + + +/****************************************************************************** +Describe a property of an element. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + prop - the new property +******************************************************************************/ + +void vtkPLY::ply_describe_property( + PlyFile *plyfile, + const char *elem_name, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *elem_prop; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr, "ply_describe_property: can't find element '%s'\n", + elem_name); + return; + } + + /* create room for new property */ + + if (elem->nprops == 0) { + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); + elem->store_prop = (char *) myalloc (sizeof (char)); + elem->nprops = 1; + } + else { + elem->nprops++; + elem->props = (PlyProperty **) + realloc (elem->props, sizeof (PlyProperty *) * elem->nprops); + elem->store_prop = (char *) + realloc (elem->store_prop, sizeof (char) * elem->nprops); + } + + /* copy the new property */ + elem->other_offset = 0; //added by wjs Purify UMR + elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + elem->props[elem->nprops - 1] = elem_prop; + elem->store_prop[elem->nprops - 1] = NAMED_PROP; + copy_property (elem_prop, prop); +} + + +/****************************************************************************** +Describe what the "other" properties are that are to be stored, and where +they are in an element. +******************************************************************************/ + +void vtkPLY::ply_describe_other_properties( + PlyFile *plyfile, + PlyOtherProp *other, + int offset +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + + /* look for appropriate element */ + elem = find_element (plyfile, other->name); + if (elem == NULL) { + fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n", + other->name); + return; + } + + /* create room for other properties */ + + if (elem->nprops == 0) { + elem->props = (PlyProperty **) + myalloc (sizeof (PlyProperty *) * other->nprops); + elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops); + elem->nprops = 0; + } + else { + int newsize; + newsize = elem->nprops + other->nprops; + elem->props = (PlyProperty **) + realloc (elem->props, sizeof (PlyProperty *) * newsize); + elem->store_prop = (char *) + realloc (elem->store_prop, sizeof (char) * newsize); + } + + /* copy the other properties */ + + for (i = 0; i < other->nprops; i++) { + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, other->props[i]); + elem->props[elem->nprops] = prop; + elem->store_prop[elem->nprops] = OTHER_PROP; + elem->nprops++; + } + + /* save other info about other properties */ + elem->other_size = other->size; + elem->other_offset = offset; +} + + +/****************************************************************************** +State how many of a given element will be written. + +Entry: + plyfile - file identifier + elem_name - name of element that information is being specified about + nelems - number of elements of this type to be written +******************************************************************************/ + +void vtkPLY::ply_element_count( + PlyFile *plyfile, + const char *elem_name, + int nelems +) +{ + PlyElement *elem; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name); + exit (-1); + } + + elem->num = nelems; +} + + +/****************************************************************************** +Signal that we've described everything a PLY file's header and that the +header should be written to the file. + +Entry: + plyfile - file identifier +******************************************************************************/ + +void vtkPLY::ply_header_complete(PlyFile *plyfile) +{ + int i,j; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + + fprintf (fp, "ply\n"); + + switch (plyfile->file_type) { + case PLY_ASCII: + fprintf (fp, "format ascii 1.0\n"); + break; + case PLY_BINARY_BE: + fprintf (fp, "format binary_big_endian 1.0\n"); + break; + case PLY_BINARY_LE: + fprintf (fp, "format binary_little_endian 1.0\n"); + break; + default: + fprintf (stderr, "ply_header_complete: bad file type = %d\n", + plyfile->file_type); + exit (-1); + } + + /* write out the comments */ + + for (i = 0; i < plyfile->num_comments; i++) + fprintf (fp, "comment %s\n", plyfile->comments[i]); + + /* write out object information */ + + for (i = 0; i < plyfile->num_obj_info; i++) + fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]); + + /* write out information about each element */ + + for (i = 0; i < plyfile->nelems; i++) { + + elem = plyfile->elems[i]; + fprintf (fp, "element %s %d\n", elem->name, elem->num); + + /* write out each property */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (prop->is_list) { + fprintf (fp, "property list "); + write_scalar_type (fp, prop->count_external); + fprintf (fp, " "); + write_scalar_type (fp, prop->external_type); + fprintf (fp, " %s\n", prop->name); + } + else { + fprintf (fp, "property "); + write_scalar_type (fp, prop->external_type); + fprintf (fp, " %s\n", prop->name); + } + } + } + + fprintf (fp, "end_header\n"); +} + + +/****************************************************************************** +Specify which elements are going to be written. This should be called +before a call to the routine ply_put_element(). + +Entry: + plyfile - file identifier + elem_name - name of element we're talking about +******************************************************************************/ + +void vtkPLY::ply_put_element_setup(PlyFile *plyfile, const char *elem_name) +{ + PlyElement *elem; + + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name); + exit (-1); + } + + plyfile->which_elem = elem; +} + + +/****************************************************************************** +Write an element to the file. This routine assumes that we're +writing the type of element specified in the last call to the routine +ply_put_element_setup(). + +Entry: + plyfile - file identifier + elem_ptr - pointer to the element +******************************************************************************/ + +void vtkPLY::ply_put_element(PlyFile *plyfile, void *elem_ptr) +{ + int j, k; + FILE *fp = plyfile->fp; + PlyElement *elem; + PlyProperty *prop; + char *elem_data,*item; + char **item_ptr; + int list_count; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + char **other_ptr; + + elem = plyfile->which_elem; + other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset); + + /* write out either to an ascii or binary file */ + + if (plyfile->file_type == PLY_ASCII) { + + /* write an ascii file */ + + /* write out each property of the element */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (elem->store_prop[j] == OTHER_PROP) + elem_data = *other_ptr; + else + elem_data = (char *)elem_ptr; + if (prop->is_list) { + item = elem_data + prop->count_offset; + get_stored_item ((void *) item, prop->count_internal, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->count_external); + list_count = uint_val; + item_ptr = (char **) (elem_data + prop->offset); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for (k = 0; k < list_count; k++) { + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->external_type); + item += item_size; + } + } + else { + item = elem_data + prop->offset; + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_ascii_item (fp, int_val, uint_val, double_val, + prop->external_type); + } + } + + fprintf (fp, "\n"); + } + else { + + /* write a binary file */ + + /* write out each property of the element */ + for (j = 0; j < elem->nprops; j++) { + prop = elem->props[j]; + if (elem->store_prop[j] == OTHER_PROP) + elem_data = *other_ptr; + else + elem_data = (char *)elem_ptr; + if (prop->is_list) { + item = elem_data + prop->count_offset; + //item_size = ply_type_size[prop->count_internal]; + get_stored_item ((void *) item, prop->count_internal, + &int_val, &uint_val, &double_val); + write_binary_item (plyfile, int_val, uint_val, double_val, + prop->count_external); + list_count = uint_val; + item_ptr = (char **) (elem_data + prop->offset); + item = item_ptr[0]; + item_size = ply_type_size[prop->internal_type]; + for (k = 0; k < list_count; k++) { + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_binary_item (plyfile, int_val, uint_val, double_val, + prop->external_type); + item += item_size; + } + } + else { + item = elem_data + prop->offset; + get_stored_item ((void *) item, prop->internal_type, + &int_val, &uint_val, &double_val); + write_binary_item (plyfile, int_val, uint_val, double_val, + prop->external_type); + } + } + + } +} + + +/****************************************************************************** +Specify a comment that will be written in the header. + +Entry: + plyfile - file identifier + comment - the comment to be written +******************************************************************************/ + +void vtkPLY::ply_put_comment(PlyFile *plyfile, const char *comment) +{ + /* (re)allocate space for new comment */ + if (plyfile->num_comments == 0) + { + plyfile->comments = (char **) myalloc (sizeof (char *)); + } + else + { + plyfile->comments = (char **) realloc (plyfile->comments, + sizeof (char *) * (plyfile->num_comments + 1)); + } + + /* add comment to list */ + plyfile->comments[plyfile->num_comments] = strdup (comment); + plyfile->num_comments++; +} + + +/****************************************************************************** +Specify a piece of object information (arbitrary text) that will be written +in the header. + +Entry: + plyfile - file identifier + obj_info - the text information to be written +******************************************************************************/ + +void vtkPLY::ply_put_obj_info(PlyFile *plyfile, const char *obj_info) +{ + /* (re)allocate space for new info */ + if (plyfile->num_obj_info == 0) + { + plyfile->obj_info = (char **) myalloc (sizeof (char *)); + } + else + { + plyfile->obj_info = (char **) realloc (plyfile->obj_info, + sizeof (char *) * (plyfile->num_obj_info + 1)); + } + + /* add info to list */ + plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info); + plyfile->num_obj_info++; +} + + + + + + + +/*************/ +/* Reading */ +/*************/ + + + +/****************************************************************************** +Given a file pointer, get ready to read PLY data from the file. + +Entry: + fp - the given file pointer + +Exit: + nelems - number of elements in object + elem_names - list of element names + returns a pointer to a PlyFile, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *vtkPLY::ply_read(FILE *fp, int *nelems, char ***elem_names) +{ + int i,j; + PlyFile *plyfile; + int nwords; + char **words; + char **elist; + PlyElement *elem; + char *orig_line; + + /* check for NULL file pointer */ + if (fp == NULL) + return (NULL); + + /* create record for this object */ + + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); + plyfile->nelems = 0; + plyfile->comments = NULL; + plyfile->num_comments = 0; + plyfile->obj_info = NULL; + plyfile->num_obj_info = 0; + plyfile->fp = fp; + plyfile->other_elems = NULL; + + /* read and parse the file's header */ + + words = get_words (plyfile->fp, &nwords, &orig_line); + if (!words || !equal_strings (words[0], "ply")) + return (NULL); + + while (words) { + + /* parse words */ + + if (equal_strings (words[0], "format")) { + if (nwords != 3) + return (NULL); + if (equal_strings (words[1], "ascii")) + plyfile->file_type = PLY_ASCII; + else if (equal_strings (words[1], "binary_big_endian")) + plyfile->file_type = PLY_BINARY_BE; + else if (equal_strings (words[1], "binary_little_endian")) + plyfile->file_type = PLY_BINARY_LE; + else + { + free (words); + return (NULL); + } + plyfile->version = atof (words[2]); + } + else if (equal_strings (words[0], "element")) + add_element (plyfile, words, nwords); + else if (equal_strings (words[0], "property")) + add_property (plyfile, words, nwords); + else if (equal_strings (words[0], "comment")) + add_comment (plyfile, orig_line); + else if (equal_strings (words[0], "obj_info")) + add_obj_info (plyfile, orig_line); + else if (equal_strings (words[0], "end_header")) + { + free (words); + break; + } + + /* free up words space */ + free (words); + + words = get_words (plyfile->fp, &nwords, &orig_line); + } + + + /* create tags for each property of each element, to be used */ + /* later to say whether or not to store each property for the user */ + + for (i = 0; i < plyfile->nelems; i++) { + elem = plyfile->elems[i]; + elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops); + for (j = 0; j < elem->nprops; j++) + elem->store_prop[j] = DONT_STORE_PROP; + elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ + } + + /* set return values about the elements */ + + elist = (char **) myalloc (sizeof (char *) * plyfile->nelems); + for (i = 0; i < plyfile->nelems; i++) + elist[i] = strdup (plyfile->elems[i]->name); + + *elem_names = elist; + *nelems = plyfile->nelems; + + /* return a pointer to the file's information */ + + return (plyfile); +} + + +/****************************************************************************** +Open a polygon file for reading. + +Entry: + filename - name of file to read from + +Exit: + nelems - number of elements in object + elem_names - list of element names + file_type - file type, either ascii or binary + version - version number of PLY file + returns a file identifier, used to refer to this file, or NULL if error +******************************************************************************/ + +PlyFile *vtkPLY::ply_open_for_reading( + char *filename, + int *nelems, + char ***elem_names, + int *file_type, + float *version +) +{ + FILE *fp; + PlyFile *plyfile; + char *name; + + //memory leaks + plyInitialize(); + + /* tack on the extension .ply, if necessary */ + + name = (char *) myalloc (sizeof (char) * + (static_cast(strlen (filename) + 5))); + strcpy (name, filename); + if (strlen (name) < 4 || + strcmp (name + strlen (name) - 4, ".ply") != 0) + strcat (name, ".ply"); + + /* open the file for reading */ + + fp = fopen (name, "rb"); + free(name); + if (fp == NULL) + return (NULL); + + /* create the PlyFile data structure */ + + plyfile = vtkPLY::ply_read (fp, nelems, elem_names); + + /* determine the file type and version */ + + *file_type = plyfile->file_type; + *version = plyfile->version; + + /* return a pointer to the file's information */ + + return (plyfile); +} + + +/****************************************************************************** +Get information about a particular element. + +Entry: + plyfile - file identifier + elem_name - name of element to get information about + +Exit: + nelems - number of elements of this type in the file + nprops - number of properties + returns a list of properties, or NULL if the file doesn't contain that elem +******************************************************************************/ + +PlyElement *vtkPLY::ply_get_element_description( + PlyFile *plyfile, + char *elem_name, + int *nelems, + int *nprops +) +{ + //wjs: this class has been drastically changed because of memory leaks. + // the return type is different, and the element properties are not + // returned. + PlyElement *elem; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) + return (NULL); + + *nelems = elem->num; + *nprops = elem->nprops; + + return elem; +} + + +/****************************************************************************** +Specify which properties of an element are to be returned. This should be +called before a call to the routine ply_get_element(). + +Entry: + plyfile - file identifier + elem_name - which element we're talking about + nprops - number of properties + prop_list - list of properties +******************************************************************************/ + +void vtkPLY::ply_get_element_setup( + PlyFile *plyfile, + char *elem_name, + int nprops, + PlyProperty *prop_list +) +{ + int i; + PlyElement *elem; + PlyProperty *prop; + int index; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + for (i = 0; i < nprops; i++) { + + /* look for actual property */ + prop = find_property (elem, prop_list[i].name, &index); + if (prop == NULL) { + fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop_list[i].name, elem_name); + continue; + } + + /* store its description */ + prop->internal_type = prop_list[i].internal_type; + prop->offset = prop_list[i].offset; + prop->count_internal = prop_list[i].count_internal; + prop->count_offset = prop_list[i].count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; + } +} + + +/****************************************************************************** +Specify a property of an element that is to be returned. This should be +called (usually multiple times) before a call to the routine ply_get_element(). +This routine should be used in preference to the less flexible old routine +called ply_get_element_setup(). + +Entry: + plyfile - file identifier + elem_name - which element we're talking about + prop - property to add to those that will be returned +******************************************************************************/ + +void vtkPLY::ply_get_property( + PlyFile *plyfile, + char *elem_name, + PlyProperty *prop +) +{ + PlyElement *elem; + PlyProperty *prop_ptr; + int index; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + plyfile->which_elem = elem; + + /* deposit the property information into the element's description */ + + prop_ptr = find_property (elem, prop->name, &index); + if (prop_ptr == NULL) { + fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", + prop->name, elem_name); + return; + } + prop_ptr->internal_type = prop->internal_type; + prop_ptr->offset = prop->offset; + prop_ptr->count_internal = prop->count_internal; + prop_ptr->count_offset = prop->count_offset; + + /* specify that the user wants this property */ + elem->store_prop[index] = STORE_PROP; +} + + +/****************************************************************************** +Read one element from the file. This routine assumes that we're reading +the type of element specified in the last call to the routine +ply_get_element_setup(). + +Entry: + plyfile - file identifier + elem_ptr - pointer to location where the element information should be put +******************************************************************************/ + +void vtkPLY::ply_get_element(PlyFile *plyfile, void *elem_ptr) +{ + if (plyfile->file_type == PLY_ASCII) + ascii_get_element (plyfile, (char *) elem_ptr); + else + binary_get_element (plyfile, (char *) elem_ptr); +} + + +/****************************************************************************** +Extract the comments from the header information of a PLY file. + +Entry: + plyfile - file identifier + +Exit: + num_comments - number of comments returned + returns a pointer to a list of comments +******************************************************************************/ + +char **vtkPLY::ply_get_comments(PlyFile *plyfile, int *num_comments) +{ + *num_comments = plyfile->num_comments; + return (plyfile->comments); +} + + +/****************************************************************************** +Extract the object information (arbitrary text) from the header information +of a PLY file. + +Entry: + plyfile - file identifier + +Exit: + num_obj_info - number of lines of text information returned + returns a pointer to a list of object info lines +******************************************************************************/ + +char **vtkPLY::ply_get_obj_info(PlyFile *plyfile, int *num_obj_info) +{ + *num_obj_info = plyfile->num_obj_info; + return (plyfile->obj_info); +} + + +/****************************************************************************** +Make ready for "other" properties of an element-- those properties that +the user has not explicitly asked for, but that are to be stashed away +in a special structure to be carried along with the element's other +information. + +Entry: + plyfile - file identifier + elem - element for which we want to save away other properties +******************************************************************************/ + +void setup_other_props(PlyFile *, PlyElement *elem) +{ + int i; + PlyProperty *prop; + int size = 0; + int type_size; + + /* Examine each property in decreasing order of size. */ + /* We do this so that all data types will be aligned by */ + /* word, half-word, or whatever within the structure. */ + + for (type_size = 8; type_size > 0; type_size /= 2) { + + /* add up the space taken by each property, and save this information */ + /* away in the property descriptor */ + + for (i = 0; i < elem->nprops; i++) { + + /* don't bother with properties we've been asked to store explicitly */ + if (elem->store_prop[i]) + continue; + + prop = elem->props[i]; + + /* internal types will be same as external */ + prop->internal_type = prop->external_type; + prop->count_internal = prop->count_external; + + /* check list case */ + if (prop->is_list) { + + /* pointer to list */ + if (type_size == sizeof (void *)) { + prop->offset = size; + size += sizeof (void *); /* always use size of a pointer here */ + } + + /* count of number of list elements */ + if (type_size == ply_type_size[prop->count_external]) { + prop->count_offset = size; + size += ply_type_size[prop->count_external]; + } + } + /* not list */ + else if (type_size == ply_type_size[prop->external_type]) { + prop->offset = size; + size += ply_type_size[prop->external_type]; + } + } + + } + + /* save the size for the other_props structure */ + elem->other_size = size; +} + + +/****************************************************************************** +Specify that we want the "other" properties of an element to be tucked +away within the user's structure. The user needn't be concerned for how +these properties are stored. + +Entry: + plyfile - file identifier + elem_name - name of element that we want to store other_props in + offset - offset to where other_props will be stored inside user's structure + +Exit: + returns pointer to structure containing description of other_props +******************************************************************************/ + +PlyOtherProp *vtkPLY::ply_get_other_properties( + PlyFile *plyfile, + char *elem_name, + int offset +) +{ + int i; + PlyElement *elem; + PlyOtherProp *other; + PlyProperty *prop; + int nprops; + + /* find information about the element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n", + elem_name); + return (NULL); + } + + /* remember that this is the "current" element */ + plyfile->which_elem = elem; + + /* save the offset to where to store the other_props */ + elem->other_offset = offset; + + /* place the appropriate pointers, etc. in the element's property list */ + setup_other_props (plyfile, elem); + + /* create structure for describing other_props */ + other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp)); + other->name = strdup (elem_name); +#if 0 + if (elem->other_offset == NO_OTHER_PROPS) { + other->size = 0; + other->props = NULL; + other->nprops = 0; + return (other); + } +#endif + other->size = elem->other_size; + other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops); + + /* save descriptions of each "other" property */ + nprops = 0; + for (i = 0; i < elem->nprops; i++) { + if (elem->store_prop[i]) + continue; + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + copy_property (prop, elem->props[i]); + other->props[nprops] = prop; + nprops++; + } + other->nprops = nprops; + +#if 1 + /* set other_offset pointer appropriately if there are NO other properties */ + if (other->nprops == 0) { + elem->other_offset = NO_OTHER_PROPS; + } +#endif + + /* return structure */ + return (other); +} + + + + +/*************************/ +/* Other Element Stuff */ +/*************************/ + + + + +/****************************************************************************** +Grab all the data for an element that a user does not want to explicitly +read in. + +Entry: + plyfile - pointer to file + elem_name - name of element whose data is to be read in + elem_count - number of instances of this element stored in the file + +Exit: + returns pointer to ALL the "other" element data for this PLY file +******************************************************************************/ + +PlyOtherElems *vtkPLY::ply_get_other_element ( + PlyFile *plyfile, + char *elem_name, + int elem_count +) +{ + int i; + PlyElement *elem; + PlyOtherElems *other_elems; + OtherElem *other; + + /* look for appropriate element */ + elem = find_element (plyfile, elem_name); + if (elem == NULL) { + fprintf (stderr, + "ply_get_other_element: can't find element '%s'\n", elem_name); + exit (-1); + } + + /* create room for the new "other" element, initializing the */ + /* other data structure if necessary */ + + if (plyfile->other_elems == NULL) { + plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems)); + other_elems = plyfile->other_elems; + other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem)); + other = &(other_elems->other_list[0]); + other_elems->num_elems = 1; + } + else { + other_elems = plyfile->other_elems; + other_elems->other_list = (OtherElem *) realloc (other_elems->other_list, + sizeof (OtherElem) * other_elems->num_elems + 1); + other = &(other_elems->other_list[other_elems->num_elems]); + other_elems->num_elems++; + } + + /* count of element instances in file */ + other->elem_count = elem_count; + + /* save name of element */ + other->elem_name = strdup (elem_name); + + /* create a list to hold all the current elements */ + other->other_data = (OtherData **) + malloc (sizeof (OtherData *) * other->elem_count); + + /* set up for getting elements */ + other->other_props = vtkPLY::ply_get_other_properties (plyfile, elem_name, + offsetof(OtherData,other_props)); + + /* grab all these elements */ + for (i = 0; i < other->elem_count; i++) { + /* grab and element from the file */ + other->other_data[i] = (OtherData *) malloc (sizeof (OtherData)); + vtkPLY::ply_get_element (plyfile, (void *) other->other_data[i]); + } + + /* return pointer to the other elements data */ + return (other_elems); +} + + +/****************************************************************************** +Pass along a pointer to "other" elements that we want to save in a given +PLY file. These other elements were presumably read from another PLY file. + +Entry: + plyfile - file pointer in which to store this other element info + other_elems - info about other elements that we want to store +******************************************************************************/ + +void vtkPLY::ply_describe_other_elements ( + PlyFile *plyfile, + PlyOtherElems *other_elems +) +{ + int i; + OtherElem *other; + + /* ignore this call if there is no other element */ + if (other_elems == NULL) + return; + + /* save pointer to this information */ + plyfile->other_elems = other_elems; + + /* describe the other properties of this element */ + + for (i = 0; i < other_elems->num_elems; i++) { + other = &(other_elems->other_list[i]); + vtkPLY::ply_element_count (plyfile, other->elem_name, other->elem_count); + vtkPLY::ply_describe_other_properties (plyfile, other->other_props, + offsetof(OtherData,other_props)); + } +} + + +/****************************************************************************** +Write out the "other" elements specified for this PLY file. + +Entry: + plyfile - pointer to PLY file to write out other elements for +******************************************************************************/ + +void vtkPLY::ply_put_other_elements (PlyFile *plyfile) +{ + int i,j; + OtherElem *other; + + /* make sure we have other elements to write */ + if (plyfile->other_elems == NULL) + return; + + /* write out the data for each "other" element */ + + for (i = 0; i < plyfile->other_elems->num_elems; i++) { + + other = &(plyfile->other_elems->other_list[i]); + vtkPLY::ply_put_element_setup (plyfile, other->elem_name); + + /* write out each instance of the current element */ + for (j = 0; j < other->elem_count; j++) + vtkPLY::ply_put_element (plyfile, (void *) other->other_data[j]); + } +} + + +/****************************************************************************** +Free up storage used by an "other" elements data structure. + +Entry: + other_elems - data structure to free up +******************************************************************************/ + +void vtkPLY::ply_free_other_elements (PlyOtherElems *) +{ + +} + + + +/*******************/ +/* Miscellaneous */ +/*******************/ + + + +/****************************************************************************** +Close a PLY file. + +Entry: + plyfile - identifier of file to close +******************************************************************************/ + +void vtkPLY::ply_close(PlyFile *plyfile) +{ + // Changed by Will Schroeder. Old stuff leaked like a sieve. + + /* free up memory associated with the PLY file */ + fclose (plyfile->fp); + + int i, j; + PlyElement *elem; + for (i=0; inelems; i++) + { + elem = plyfile->elems[i]; + if ( elem->name ) {free(elem->name);} + for (j=0; jnprops; j++) + { + if ( elem->props[j]->name ) {free(const_cast(elem->props[j]->name));} + free (elem->props[j]); + } + free (elem->props); + free (elem->store_prop); + free (elem); + } + free(plyfile->elems); + + for (i=0; inum_comments; i++) + { + free (plyfile->comments[i]); + } + free (plyfile->comments); + + for (i=0; inum_obj_info; i++) + { + free (plyfile->obj_info[i]); + } + free (plyfile->obj_info); + + free (plyfile); + + // memory leaks + plyCleanUp(); +} + + +/****************************************************************************** +Get version number and file type of a PlyFile. + +Entry: + ply - pointer to PLY file + +Exit: + version - version of the file + file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE +******************************************************************************/ + +void vtkPLY::ply_get_info(PlyFile *ply, float *version, int *file_type) +{ + if (ply == NULL) + return; + + *version = ply->version; + *file_type = ply->file_type; +} + + +/****************************************************************************** +Compare two strings. Returns 1 if they are the same, 0 if not. +******************************************************************************/ + +int vtkPLY::equal_strings(const char *s1, const char *s2) +{ + while (*s1 && *s2) + if (*s1++ != *s2++) + return (0); + + if (*s1 != *s2) + return (0); + else + return (1); +} + + +/****************************************************************************** +Find an element from the element list of a given PLY object. + +Entry: + plyfile - file id for PLY file + element - name of element we're looking for + +Exit: + returns the element, or NULL if not found +******************************************************************************/ + +PlyElement *vtkPLY::find_element(PlyFile *plyfile, const char *element) +{ + int i; + + for (i = 0; i < plyfile->nelems; i++) + if (equal_strings (element, plyfile->elems[i]->name)) + return (plyfile->elems[i]); + + return (NULL); +} + + +/****************************************************************************** +Find a property in the list of properties of a given element. + +Entry: + elem - pointer to element in which we want to find the property + prop_name - name of property to find + +Exit: + index - index to position in list + returns a pointer to the property, or NULL if not found +******************************************************************************/ + +PlyProperty *vtkPLY::find_property(PlyElement *elem, const char *prop_name, int *index) +{ + int i; + + for (i = 0; i < elem->nprops; i++) + if (equal_strings (prop_name, elem->props[i]->name)) { + *index = i; + return (elem->props[i]); + } + + *index = -1; + return (NULL); +} + + +/****************************************************************************** +Read an element from an ascii file. + +Entry: + plyfile - file identifier + elem_ptr - pointer to element +******************************************************************************/ + +void vtkPLY::ascii_get_element(PlyFile *plyfile, char *elem_ptr) +{ + int j,k; + PlyElement *elem; + PlyProperty *prop; + char **words; + int nwords; + int which_word; + char *elem_data,*item=0; + char *item_ptr; + int item_size; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char **store_array; + char *orig_line; + char *other_data=0; + int other_flag; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if (elem->other_offset != NO_OTHER_PROPS) { + char **ptr; + other_flag = 1; + /* make room for other_props */ + other_data = (char *) myalloc (elem->other_size); + /* store pointer in user's structure to the other_props */ + ptr = (char **) (elem_ptr + elem->other_offset); + *ptr = other_data; + } + else + other_flag = 0; + + /* read in the element */ + + words = get_words (plyfile->fp, &nwords, &orig_line); + if (words == NULL) { + fprintf (stderr, "ply_get_element: unexpected end of file\n"); + exit (-1); + } + + which_word = 0; + + for (j = 0; j < elem->nprops; j++) { + + prop = elem->props[j]; + store_it = (elem->store_prop[j] | other_flag); + + /* store either in the user's structure or in other_props */ + if (elem->store_prop[j]) + elem_data = elem_ptr; + else + elem_data = other_data; + + if (prop->is_list) { /* a list */ + + /* get and store the number of items in the list */ + get_ascii_item (words[which_word++], prop->count_external, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->count_offset; + store_item(item, prop->count_internal, int_val, uint_val, double_val); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + item_size = ply_type_size[prop->internal_type]; + store_array = (char **) (elem_data + prop->offset); + + if (list_count == 0) { + if (store_it) + *store_array = NULL; + } + else { + if (store_it) { + item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for (k = 0; k < list_count; k++) { + get_ascii_item (words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + store_item (item, prop->internal_type, + int_val, uint_val, double_val); + item += item_size; + } + } + } + + } + else { /* not a list */ + get_ascii_item (words[which_word++], prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->offset; + store_item (item, prop->internal_type, int_val, uint_val, double_val); + } + } + + } + + free (words); +} + + +/****************************************************************************** +Read an element from a binary file. + +Entry: + plyfile - file identifier + elem_ptr - pointer to an element +******************************************************************************/ + +void vtkPLY::binary_get_element(PlyFile *plyfile, char *elem_ptr) +{ + int j,k; + PlyElement *elem; + PlyProperty *prop; + //FILE *fp = plyfile->fp; + char *elem_data,*item=0; + char *item_ptr; + int item_size=0; + int int_val; + unsigned int uint_val; + double double_val; + int list_count; + int store_it; + char **store_array; + char *other_data=0; + int other_flag; + + /* the kind of element we're reading currently */ + elem = plyfile->which_elem; + + /* do we need to setup for other_props? */ + + if (elem->other_offset != NO_OTHER_PROPS) { + char **ptr; + other_flag = 1; + /* make room for other_props */ + other_data = (char *) myalloc (elem->other_size); + /* store pointer in user's structure to the other_props */ + ptr = (char **) (elem_ptr + elem->other_offset); + *ptr = other_data; + } + else + other_flag = 0; + + /* read in a number of elements */ + + for (j = 0; j < elem->nprops; j++) { + + prop = elem->props[j]; + store_it = (elem->store_prop[j] | other_flag); + + /* store either in the user's structure or in other_props */ + if (elem->store_prop[j]) + elem_data = elem_ptr; + else + elem_data = other_data; + + if (prop->is_list) { /* a list */ + + /* get and store the number of items in the list */ + get_binary_item (plyfile, prop->count_external, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->count_offset; + store_item(item, prop->count_internal, int_val, uint_val, double_val); + } + + /* allocate space for an array of items and store a ptr to the array */ + list_count = int_val; + /* The "if" was added by Afra Zomorodian 8/22/95 + * so that zipper won't crash reading plies that have additional + * properties. + */ + if (store_it) { + item_size = ply_type_size[prop->internal_type]; + } + store_array = (char **) (elem_data + prop->offset); + if (list_count == 0) { + if (store_it) + *store_array = NULL; + } + else { + if (store_it) { + item_ptr = (char *) plyAllocateMemory (sizeof (char) * item_size * list_count); + item = item_ptr; + *store_array = item_ptr; + } + + /* read items and store them into the array */ + for (k = 0; k < list_count; k++) { + get_binary_item (plyfile, prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + store_item (item, prop->internal_type, + int_val, uint_val, double_val); + item += item_size; + } + } + } + + } + else { /* not a list */ + get_binary_item (plyfile, prop->external_type, + &int_val, &uint_val, &double_val); + if (store_it) { + item = elem_data + prop->offset; + store_item (item, prop->internal_type, int_val, uint_val, double_val); + } + } + + } +} + + +/****************************************************************************** +Write to a file the word that represents a PLY data type. + +Entry: + fp - file pointer + code - code for type +******************************************************************************/ + +void vtkPLY::write_scalar_type (FILE *fp, int code) +{ + /* make sure this is a valid code */ + + if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) { + fprintf (stderr, "write_scalar_type: bad data code = %d\n", code); + exit (-1); + } + + /* write the code to a file */ + + fprintf (fp, "%s", type_names[code]); +} + + +/****************************************************************************** +Get a text line from a file and break it up into words. + +IMPORTANT: The calling routine call "free" on the returned pointer once +finished with it. + +Entry: + fp - file to read from + +Exit: + nwords - number of words returned + orig_line - the original line of characters + returns a list of words from the line, or NULL if end-of-file +******************************************************************************/ + +char **vtkPLY::get_words(FILE *fp, int *nwords, char **orig_line) +{ +#define BIG_STRING 4096 + static char str[BIG_STRING]; + static char str_copy[BIG_STRING]; + char **words; + int max_words = 10; + int num_words = 0; + char *ptr,*ptr2; + char *result; + + /* read in a line */ + result = fgets (str, BIG_STRING, fp); + if (result == NULL) { + *nwords = 0; + *orig_line = NULL; + return (NULL); + } + + words = (char **) myalloc (sizeof (char *) * max_words); + + /* convert line-feed and tabs into spaces */ + /* (this guarentees that there will be a space before the */ + /* null character at the end of the string) */ + + str[BIG_STRING-2] = ' '; + str[BIG_STRING-1] = '\0'; + + for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) { + *ptr2 = *ptr; + if (*ptr == '\t') { + *ptr = ' '; + *ptr2 = ' '; + } + else if (*ptr == '\n') { + *ptr = ' '; + *ptr2 = '\0'; + break; + } + } + + /* find the words in the line */ + + ptr = str; + while (*ptr != '\0') { + + /* jump over leading spaces */ + while (*ptr == ' ') + ptr++; + + /* break if we reach the end */ + if (*ptr == '\0') + break; + + /* save pointer to beginning of word */ + if (num_words >= max_words) { + max_words += 10; + words = (char **) realloc (words, sizeof (char *) * max_words); + } + words[num_words++] = ptr; + + /* jump over non-spaces */ + while (*ptr != ' ') + ptr++; + + /* place a null character here to mark the end of the word */ + *ptr++ = '\0'; + } + + /* return the list of words */ + *nwords = num_words; + *orig_line = str_copy; + return (words); +} + + +/****************************************************************************** +Return the value of an item, given a pointer to it and its type. + +Entry: + item - pointer to item + type - data type that "item" points to + +Exit: + returns a double-precision float that contains the value of the item +******************************************************************************/ + +double vtkPLY::get_item_value(char *item, int type) +{ + unsigned char *puchar; + char *pchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + int int_value; + unsigned int uint_value; + double double_value; + + switch (type) { + case PLY_CHAR: + pchar = (char *) item; + int_value = *pchar; + return ((double) int_value); + case PLY_UCHAR: + puchar = (unsigned char *) item; + int_value = *puchar; + return ((double) int_value); + case PLY_SHORT: + pshort = (short int *) item; + int_value = *pshort; + return ((double) int_value); + case PLY_USHORT: + pushort = (unsigned short int *) item; + int_value = *pushort; + return ((double) int_value); + case PLY_INT: + pint = (int *) item; + int_value = *pint; + return ((double) int_value); + case PLY_UINT: + puint = (unsigned int *) item; + uint_value = *puint; + return ((double) uint_value); + case PLY_FLOAT: + pfloat = (float *) item; + double_value = *pfloat; + return (double_value); + case PLY_DOUBLE: + pdouble = (double *) item; + double_value = *pdouble; + return (double_value); + } + fprintf (stderr, "get_item_value: bad type = %d\n", type); + return 0; +} + + +/****************************************************************************** +Write out an item to a file as raw binary bytes. + +Entry: + fp - file to write to + int_val - integer version of item + uint_val - unsigned integer version of item + double_val - double-precision float version of item + type - data type to write out +******************************************************************************/ + +void vtkPLY::write_binary_item(PlyFile *plyfile, + int int_val, + unsigned int uint_val, + double double_val, + int type +) +{ + FILE *fp = plyfile->fp; + unsigned char uchar_val; + char char_val; + unsigned short ushort_val; + short short_val; + float float_val; + + switch (type) { + case PLY_CHAR: + char_val = int_val; + fwrite (&char_val, 1, 1, fp); + break; + case PLY_SHORT: + short_val = int_val; + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap2BE(&short_val) : + vtkByteSwap::Swap2LE(&short_val); + fwrite (&short_val, 2, 1, fp); + break; + case PLY_INT: + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap4BE(&int_val) : + vtkByteSwap::Swap4LE(&int_val); + fwrite (&int_val, 4, 1, fp); + break; + case PLY_UCHAR: + uchar_val = uint_val; + fwrite (&uchar_val, 1, 1, fp); + break; + case PLY_USHORT: + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap2BE(&ushort_val) : + vtkByteSwap::Swap2LE(&ushort_val); + ushort_val = uint_val; + fwrite (&ushort_val, 2, 1, fp); + break; + case PLY_UINT: + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap4BE(&uint_val) : + vtkByteSwap::Swap4LE(&uint_val); + fwrite (&uint_val, 4, 1, fp); + break; + case PLY_FLOAT: + float_val = double_val; + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap4BE(&float_val) : + vtkByteSwap::Swap4LE(&float_val); + fwrite (&float_val, 4, 1, fp); + break; + case PLY_DOUBLE: + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap8BE(&double_val) : + vtkByteSwap::Swap8LE(&double_val); + fwrite (&double_val, 8, 1, fp); + break; + default: + fprintf (stderr, "write_binary_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Write out an item to a file as ascii characters. + +Entry: + fp - file to write to + int_val - integer version of item + uint_val - unsigned integer version of item + double_val - double-precision float version of item + type - data type to write out +******************************************************************************/ + +void vtkPLY::write_ascii_item( + FILE *fp, + int int_val, + unsigned int uint_val, + double double_val, + int type +) +{ + switch (type) { + case PLY_CHAR: + case PLY_SHORT: + case PLY_INT: + fprintf (fp, "%d ", int_val); + break; + case PLY_UCHAR: + case PLY_USHORT: + case PLY_UINT: + fprintf (fp, "%u ", uint_val); + break; + case PLY_FLOAT: + case PLY_DOUBLE: + fprintf (fp, "%g ", double_val); + break; + default: + fprintf (stderr, "write_ascii_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Write out an item to a file as ascii characters. + +Entry: + fp - file to write to + item - pointer to item to write + type - data type that "item" points to + +Exit: + returns a double-precision float that contains the value of the written item +******************************************************************************/ + +double vtkPLY::old_write_ascii_item(FILE *fp, char *item, int type) +{ + unsigned char *puchar; + char *pchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + int int_value; + unsigned int uint_value; + double double_value; + + switch (type) { + case PLY_CHAR: + pchar = (char *) item; + int_value = *pchar; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_UCHAR: + puchar = (unsigned char *) item; + int_value = *puchar; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_SHORT: + pshort = (short int *) item; + int_value = *pshort; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_USHORT: + pushort = (unsigned short int *) item; + int_value = *pushort; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_INT: + pint = (int *) item; + int_value = *pint; + fprintf (fp, "%d ", int_value); + return ((double) int_value); + case PLY_UINT: + puint = (unsigned int *) item; + uint_value = *puint; + fprintf (fp, "%u ", uint_value); + return ((double) uint_value); + case PLY_FLOAT: + pfloat = (float *) item; + double_value = *pfloat; + fprintf (fp, "%g ", double_value); + return (double_value); + case PLY_DOUBLE: + pdouble = (double *) item; + double_value = *pdouble; + fprintf (fp, "%g ", double_value); + return (double_value); + } + fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type); + return 0; +} + + +/****************************************************************************** +Get the value of an item that is in memory, and place the result +into an integer, an unsigned integer and a double. + +Entry: + ptr - pointer to the item + type - data type supposedly in the item + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void vtkPLY::get_stored_item( + void *ptr, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + switch (type) { + case PLY_CHAR: + *int_val = *((char *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UCHAR: + *uint_val = *((unsigned char *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_SHORT: + *int_val = *((short int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_USHORT: + *uint_val = *((unsigned short int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_INT: + *int_val = *((int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UINT: + *uint_val = *((unsigned int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_FLOAT: + *double_val = *((float *) ptr); + *int_val = (int) *double_val; + *uint_val = (unsigned int) *double_val; + break; + case PLY_DOUBLE: + *double_val = *((double *) ptr); + *int_val = (int) *double_val; + *uint_val = (unsigned int) *double_val; + break; + default: + fprintf (stderr, "get_stored_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Get the value of an item from a binary file, and place the result +into an integer, an unsigned integer and a double. + +Entry: + fp - file to get item from + type - data type supposedly in the word + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void vtkPLY::get_binary_item( + PlyFile *plyfile, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + char c[8]; + void *ptr; + + ptr = (void *) c; + + switch (type) { + case PLY_CHAR: + fread (ptr, 1, 1, plyfile->fp); + *int_val = *((char *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UCHAR: + fread (ptr, 1, 1, plyfile->fp); + *uint_val = *((unsigned char *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_SHORT: + fread (ptr, 2, 1, plyfile->fp); + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap2BE((short *) ptr) : + vtkByteSwap::Swap2LE((short *) ptr); + *int_val = *((short int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_USHORT: + fread (ptr, 2, 1, plyfile->fp); + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap2BE((unsigned short *) ptr) : + vtkByteSwap::Swap2LE((unsigned short *) ptr); + *uint_val = *((unsigned short int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_INT: + fread (ptr, 4, 1, plyfile->fp); + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap4BE((int *) ptr) : + vtkByteSwap::Swap4LE((int *) ptr); + *int_val = *((int *) ptr); + *uint_val = *int_val; + *double_val = *int_val; + break; + case PLY_UINT: + fread (ptr, 4, 1, plyfile->fp); + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap4BE((int *) ptr) : + vtkByteSwap::Swap4LE((int *) ptr); + *uint_val = *((unsigned int *) ptr); + *int_val = *uint_val; + *double_val = *uint_val; + break; + case PLY_FLOAT: + fread (ptr, 4, 1, plyfile->fp); + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap4BE((float *) ptr) : + vtkByteSwap::Swap4LE((float *) ptr); + *double_val = *((float *) ptr); + *int_val = (int) *double_val; + *uint_val = (unsigned int) *double_val; + break; + case PLY_DOUBLE: + fread (ptr, 8, 1, plyfile->fp); + plyfile->file_type == PLY_BINARY_BE ? + vtkByteSwap::Swap8BE((double *) ptr) : + vtkByteSwap::Swap8LE((double *) ptr); + *double_val = *((double *) ptr); + *int_val = (int) *double_val; + *uint_val = (unsigned int) *double_val; + break; + default: + fprintf (stderr, "get_binary_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Extract the value of an item from an ascii word, and place the result +into an integer, an unsigned integer and a double. + +Entry: + word - word to extract value from + type - data type supposedly in the word + +Exit: + int_val - integer value + uint_val - unsigned integer value + double_val - double-precision floating point value +******************************************************************************/ + +void vtkPLY::get_ascii_item( + char *word, + int type, + int *int_val, + unsigned int *uint_val, + double *double_val +) +{ + switch (type) { + case PLY_CHAR: + case PLY_UCHAR: + case PLY_SHORT: + case PLY_USHORT: + case PLY_INT: + *int_val = atoi (word); + *uint_val = *int_val; + *double_val = *int_val; + break; + + case PLY_UINT: + *uint_val = strtoul (word, (char **) NULL, 10); + *int_val = *uint_val; + *double_val = *uint_val; + break; + + case PLY_FLOAT: + case PLY_DOUBLE: + *double_val = atof (word); + *int_val = (int) *double_val; + *uint_val = (unsigned int) *double_val; + break; + + default: + fprintf (stderr, "get_ascii_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Store a value into a place being pointed to, guided by a data type. + +Entry: + item - place to store value + type - data type + int_val - integer version of value + uint_val - unsigned integer version of value + double_val - double version of value + +Exit: + item - pointer to stored value +******************************************************************************/ + +void vtkPLY::store_item ( + char *item, + int type, + int int_val, + unsigned int uint_val, + double double_val +) +{ + unsigned char *puchar; + short int *pshort; + unsigned short int *pushort; + int *pint; + unsigned int *puint; + float *pfloat; + double *pdouble; + + switch (type) { + case PLY_CHAR: + *item = int_val; + break; + case PLY_UCHAR: + puchar = (unsigned char *) item; + *puchar = uint_val; + break; + case PLY_SHORT: + pshort = (short *) item; + *pshort = int_val; + break; + case PLY_USHORT: + pushort = (unsigned short *) item; + *pushort = uint_val; + break; + case PLY_INT: + pint = (int *) item; + *pint = int_val; + break; + case PLY_UINT: + puint = (unsigned int *) item; + *puint = uint_val; + break; + case PLY_FLOAT: + pfloat = (float *) item; + *pfloat = double_val; + break; + case PLY_DOUBLE: + pdouble = (double *) item; + *pdouble = double_val; + break; + default: + fprintf (stderr, "store_item: bad type = %d\n", type); + exit (-1); + } +} + + +/****************************************************************************** +Add an element to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + words - list of words describing the element + nwords - number of words in the list +******************************************************************************/ + +void vtkPLY::add_element (PlyFile *plyfile, char **words, int) +{ + PlyElement *elem; + + /* create the new element */ + elem = (PlyElement *) myalloc (sizeof (PlyElement)); + elem->name = strdup (words[1]); + elem->num = atoi (words[2]); + elem->nprops = 0; + + /* make room for new element in the object's list of elements */ + if (plyfile->nelems == 0) + plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *)); + else + plyfile->elems = (PlyElement **) realloc (plyfile->elems, + sizeof (PlyElement *) * (plyfile->nelems + 1)); + + /* add the new element to the object's list */ + plyfile->elems[plyfile->nelems] = elem; + plyfile->nelems++; +} + + +/****************************************************************************** +Return the type of a property, given the name of the property. + +Entry: + name - name of property type + +Exit: + returns integer code for property, or 0 if not found +******************************************************************************/ + +int vtkPLY::get_prop_type(char *type_name) +{ + int i; + + for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++) + if (equal_strings (type_name, type_names[i])) + return (i); + + /* if we get here, we didn't find the type */ + return (0); +} + + +/****************************************************************************** +Add a property to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + words - list of words describing the property + nwords - number of words in the list +******************************************************************************/ + +void vtkPLY::add_property (PlyFile *plyfile, char **words, int ) +{ + PlyProperty *prop; + PlyElement *elem; + + /* create the new property */ + + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); + + if (equal_strings (words[1], "list")) { /* is a list */ + prop->count_external = get_prop_type (words[2]); + prop->external_type = get_prop_type (words[3]); + prop->name = strdup (words[4]); + prop->is_list = 1; + } + else { /* not a list */ + prop->external_type = get_prop_type (words[1]); + prop->name = strdup (words[2]); + prop->is_list = 0; + } + + /* add this property to the list of properties of the current element */ + + elem = plyfile->elems[plyfile->nelems - 1]; + + if (elem->nprops == 0) + elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); + else + elem->props = (PlyProperty **) realloc (elem->props, + sizeof (PlyProperty *) * (elem->nprops + 1)); + + elem->props[elem->nprops] = prop; + elem->nprops++; +} + + +/****************************************************************************** +Add a comment to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + line - line containing comment +******************************************************************************/ + +void vtkPLY::add_comment (PlyFile *plyfile, char *line) +{ + int i; + + /* skip over "comment" and leading spaces and tabs */ + i = 7; + while (line[i] == ' ' || line[i] == '\t') + i++; + + vtkPLY::ply_put_comment (plyfile, &line[i]); +} + + +/****************************************************************************** +Add a some object information to a PLY file descriptor. + +Entry: + plyfile - PLY file descriptor + line - line containing text info +******************************************************************************/ + +void vtkPLY::add_obj_info (PlyFile *plyfile, char *line) +{ + int i; + + /* skip over "obj_info" and leading spaces and tabs */ + i = 8; + while (line[i] == ' ' || line[i] == '\t') + i++; + + vtkPLY::ply_put_obj_info (plyfile, &line[i]); +} + + +/****************************************************************************** +Copy a property. +******************************************************************************/ + +void vtkPLY::copy_property(PlyProperty *dest, PlyProperty *src) +{ + dest->name = strdup (src->name); + dest->external_type = src->external_type; + dest->internal_type = src->internal_type; + dest->offset = src->offset; + + dest->is_list = src->is_list; + dest->count_external = src->count_external; + dest->count_internal = src->count_internal; + dest->count_offset = src->count_offset; +} + + +/****************************************************************************** +Allocate some memory. + +Entry: + size - amount of memory requested (in bytes) + lnum - line number from which memory was requested + fname - file name from which memory was requested +******************************************************************************/ + +char *vtkPLY::my_alloc(int size, int lnum, const char *fname) +{ + char *ptr; + + ptr = (char *) malloc (size); + + if (ptr == 0) + { + fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname); + } + + return (ptr); +} + diff --git a/IO/vtkPLY.h b/IO/vtkPLY.h new file mode 100644 index 0000000..77250f0 --- /dev/null +++ b/IO/vtkPLY.h @@ -0,0 +1,213 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLY.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + +The interface routines for reading and writing PLY polygon files. + +Greg Turk, February 1994 + +--------------------------------------------------------------- + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties the floating-point values x,y,z and the three unsigned +chars representing red, green and blue. + +--------------------------------------------------------------- + +Copyright (c) 1994 The Board of Trustees of The Leland Stanford +Junior University. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +// .NAME vtkPLY - a modified version of the PLY 1.1 library +// .SECTION Description +// vtkPLY is a modified version of the PLY 1.1 library. The library +// has been modified by wrapping in a class (to minimize global symbols); +// to take advantage of functionality generally not available through the +// PLY library API; and to correct problems with the PLY library. +// +// The original distribution was taken from the Stanford University PLY +// file format release 1.1 (see http://graphics.stanford.edu/data/3Dscanrep/). + +// .SECTION See Also +// vtkPLYWriter vtkPLYReader + +#ifndef __vtkPLY_h +#define __vtkPLY_h + +#include "vtkObject.h" + +#define PLY_ASCII 1 /* ascii PLY file */ +#define PLY_BINARY_BE 2 /* binary PLY file, big endian */ +#define PLY_BINARY_LE 3 /* binary PLY file, little endian */ + +#define PLY_OKAY 0 /* ply routine worked okay */ +#define PLY_ERROR -1 /* error in ply routine */ + +/* scalar data types supported by PLY format */ + +#define PLY_START_TYPE 0 +#define PLY_CHAR 1 +#define PLY_SHORT 2 +#define PLY_INT 3 +#define PLY_UCHAR 4 +#define PLY_USHORT 5 +#define PLY_UINT 6 +#define PLY_FLOAT 7 +#define PLY_DOUBLE 8 +#define PLY_END_TYPE 9 + +#define PLY_SCALAR 0 +#define PLY_LIST 1 + +typedef struct PlyProperty { /* description of a property */ + + const char *name; /* property name */ + int external_type; /* file's data type */ + int internal_type; /* program's data type */ + int offset; /* offset bytes of prop in a struct */ + + int is_list; /* 1 = list, 0 = scalar */ + int count_external; /* file's count type */ + int count_internal; /* program's count type */ + int count_offset; /* offset byte for list count */ + +} PlyProperty; + +typedef struct PlyElement { /* description of an element */ + char *name; /* element name */ + int num; /* number of elements in this object */ + int size; /* size of element (bytes) or -1 if variable */ + int nprops; /* number of properties for this element */ + PlyProperty **props; /* list of properties in the file */ + char *store_prop; /* flags: property wanted by user? */ + int other_offset; /* offset to un-asked-for props, or -1 if none*/ + int other_size; /* size of other_props structure */ +} PlyElement; + +typedef struct PlyOtherProp { /* describes other properties in an element */ + char *name; /* element name */ + int size; /* size of other_props */ + int nprops; /* number of properties in other_props */ + PlyProperty **props; /* list of properties in other_props */ +} PlyOtherProp; + +typedef struct OtherData { /* for storing other_props for an other element */ + void *other_props; +} OtherData; + +typedef struct OtherElem { /* data for one "other" element */ + char *elem_name; /* names of other elements */ + int elem_count; /* count of instances of each element */ + OtherData **other_data; /* actual property data for the elements */ + PlyOtherProp *other_props; /* description of the property data */ +} OtherElem; + +typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */ + int num_elems; /* number of other elements */ + OtherElem *other_list; /* list of data for other elements */ +} PlyOtherElems; + +typedef struct PlyFile { /* description of PLY file */ + FILE *fp; /* file pointer */ + int file_type; /* ascii or binary */ + float version; /* version number of file */ + int nelems; /* number of elements of object */ + PlyElement **elems; /* list of elements */ + int num_comments; /* number of comments */ + char **comments; /* list of comments */ + int num_obj_info; /* number of items of object information */ + char **obj_info; /* list of object info items */ + PlyElement *which_elem; /* which element we're currently writing */ + PlyOtherElems *other_elems; /* "other" elements from a PLY file */ +} PlyFile; + +class VTK_IO_EXPORT vtkPLY +{ +public: + //standard PLY library interface + static PlyFile *ply_write(FILE *, int, const char **, int); + static PlyFile *ply_open_for_writing(char *, int, const char **, int, float *); + static void ply_describe_element(PlyFile *, const char *, int, int, PlyProperty *); + static void ply_describe_property(PlyFile *, const char *, PlyProperty *); + static void ply_element_count(PlyFile *, const char *, int); + static void ply_header_complete(PlyFile *); + static void ply_put_element_setup(PlyFile *, const char *); + static void ply_put_element(PlyFile *, void *); + static void ply_put_comment(PlyFile *, const char *); + static void ply_put_obj_info(PlyFile *, const char *); + static PlyFile *ply_read(FILE *, int *, char ***); + static PlyFile *ply_open_for_reading( char *, int *, char ***, int *, float *); + static PlyElement *ply_get_element_description(PlyFile *, char *, int*, int*); + static void ply_get_element_setup( PlyFile *, char *, int, PlyProperty *); + static void ply_get_property(PlyFile *, char *, PlyProperty *); + static PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int); + static void ply_get_element(PlyFile *, void *); + static char **ply_get_comments(PlyFile *, int *); + static char **ply_get_obj_info(PlyFile *, int *); + static void ply_close(PlyFile *); + static void ply_get_info(PlyFile *, float *, int *); + static PlyOtherElems *ply_get_other_element (PlyFile *, char *, int); + static void ply_describe_other_elements ( PlyFile *, PlyOtherElems *); + static void ply_put_other_elements (PlyFile *); + static void ply_free_other_elements (PlyOtherElems *); + static void ply_describe_other_properties(PlyFile *, PlyOtherProp *, int); + + // These methods are internal to the PLY library in the normal distribution + // They should be used carefully + static int equal_strings(const char *, const char *); + static PlyElement *find_element(PlyFile *, const char *); + static PlyProperty *find_property(PlyElement *, const char *, int *); + static void write_scalar_type (FILE *, int); + static char **get_words(FILE *, int *, char **); + static char **old_get_words(FILE *, int *); + static void write_binary_item(PlyFile *, int, unsigned int, double, int); + static void write_ascii_item(FILE *, int, unsigned int, double, int); + static double old_write_ascii_item(FILE *, char *, int); + static void add_element(PlyFile *, char **, int); + static void add_property(PlyFile *, char **, int); + static void add_comment(PlyFile *, char *); + static void add_obj_info(PlyFile *, char *); + static void copy_property(PlyProperty *, PlyProperty *); + static void store_item(char *, int, int, unsigned int, double); + static void get_stored_item( void *, int, int *, unsigned int *, double *); + static double get_item_value(char *, int); + static void get_ascii_item(char *, int, int *, unsigned int *, double *); + static void get_binary_item(PlyFile *, int, int *, unsigned int *, double *); + static void ascii_get_element(PlyFile *, char *); + static void binary_get_element(PlyFile *, char *); + static char *my_alloc(int, int, const char *); + static int get_prop_type(char *); + +}; + +#endif + + diff --git a/IO/vtkPLYReader.cxx b/IO/vtkPLYReader.cxx new file mode 100644 index 0000000..694d330 --- /dev/null +++ b/IO/vtkPLYReader.cxx @@ -0,0 +1,302 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLYReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPLYReader.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPLY.h" +#include "vtkPolyData.h" + +#include +#include + +vtkCxxRevisionMacro(vtkPLYReader, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkPLYReader); + +#ifndef true +#define true 1 +#endif +#ifndef false +#define false 0 +#endif + + +// Construct object with merging set to true. +vtkPLYReader::vtkPLYReader() +{ + this->FileName = NULL; + + this->SetNumberOfInputPorts(0); +} + +vtkPLYReader::~vtkPLYReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } +} + +typedef struct _plyVertex { + float x[3]; // the usual 3-space position of a vertex + unsigned char red; + unsigned char green; + unsigned char blue; +} plyVertex; + +typedef struct _plyFace { + unsigned char intensity; // optional face attributes + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned char nverts; // number of vertex indices in list + int *verts; // vertex index list +} plyFace; + +int vtkPLYReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + PlyProperty vertProps[] = { + {"x", PLY_FLOAT, PLY_FLOAT, static_cast(offsetof(plyVertex,x)), + 0, 0, 0, 0}, + {"y", PLY_FLOAT, PLY_FLOAT, static_cast(offsetof(plyVertex,x)+sizeof(float)), + 0, 0, 0, 0}, + {"z", PLY_FLOAT, PLY_FLOAT, static_cast(offsetof(plyVertex,x)+sizeof(float)+sizeof(float)), + 0, 0, 0, 0}, + {"red", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyVertex,red)), 0, 0, 0, 0}, + {"green", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyVertex,green)), 0, 0, 0, 0}, + {"blue", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyVertex,blue)), 0, 0, 0, 0}, + }; + PlyProperty faceProps[] = { + {"vertex_indices", PLY_INT, PLY_INT, + static_cast(offsetof(plyFace,verts)), + 1, PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,nverts))}, + {"intensity", PLY_UCHAR, PLY_UCHAR, + static_cast(offsetof(plyFace,intensity)), 0, 0, 0, 0}, + {"red", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,red)), 0, 0, 0, 0}, + {"green", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,green)), 0, 0, 0, 0}, + {"blue", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,blue)), 0, 0, 0, 0}, + }; + + int i, j, k; + int numPts=0, numPolys=0; + + if (!this->FileName) + { + vtkErrorMacro(<<"A File Name must be specified."); + return 0; + } + + // open a PLY file for reading + PlyFile *ply; + int nelems, fileType, numElems, nprops; + char **elist, *elemName; + float version; + + if ( !(ply = vtkPLY::ply_open_for_reading(this->FileName, &nelems, &elist, + &fileType, &version)) ) + { + vtkErrorMacro(<<"Could not open PLY file"); + return 0; + } + + // Check to make sure that we can read geometry + PlyElement *elem; + int index; + if ( (elem = vtkPLY::find_element (ply, "vertex")) == NULL || + vtkPLY::find_property (elem, "x", &index) == NULL || + vtkPLY::find_property (elem, "y", &index) == NULL || + vtkPLY::find_property (elem, "z", &index) == NULL || + (elem = vtkPLY::find_element (ply, "face")) == NULL || + vtkPLY::find_property (elem, "vertex_indices", &index) == NULL ) + { + vtkErrorMacro(<<"Cannot read geometry"); + vtkPLY::ply_close (ply); + } + + // Check for optional attribute data. We can handle intensity; and the + // triplet red, green, blue. + unsigned char intensityAvailable=false, RGBCellsAvailable=false, RGBPointsAvailable=false; + vtkUnsignedCharArray *intensity=NULL; + vtkUnsignedCharArray *RGBCells=NULL; + vtkUnsignedCharArray *RGBPoints=NULL; + if ( (elem = vtkPLY::find_element (ply, "face")) != NULL && + vtkPLY::find_property (elem, "intensity", &index) != NULL ) + { + intensity = vtkUnsignedCharArray::New(); + intensity->SetName("intensity"); + intensityAvailable = true; + output->GetCellData()->AddArray(intensity); + output->GetCellData()->SetActiveScalars("intensity"); + intensity->Delete(); + } + + if ( (elem = vtkPLY::find_element (ply, "face")) != NULL && + vtkPLY::find_property (elem, "red", &index) != NULL && + vtkPLY::find_property (elem, "green", &index) != NULL && + vtkPLY::find_property (elem, "blue", &index) != NULL ) + { + RGBCells = vtkUnsignedCharArray::New(); + RGBCells->SetName("RGB"); + RGBCellsAvailable = true; + output->GetCellData()->AddArray(RGBCells); + output->GetCellData()->SetActiveScalars("RGB"); + RGBCells->Delete(); + } + + if ( (elem = vtkPLY::find_element (ply, "vertex")) != NULL && + vtkPLY::find_property (elem, "red", &index) != NULL && + vtkPLY::find_property (elem, "green", &index) != NULL && + vtkPLY::find_property (elem, "blue", &index) != NULL ) + { + RGBPoints = vtkUnsignedCharArray::New(); + RGBPointsAvailable = true; + RGBPoints->SetName("RGB"); + output->GetPointData()->SetScalars(RGBPoints); + RGBPoints->Delete(); + } + + // Okay, now we can grab the data + for (i = 0; i < nelems; i++) + { + //get the description of the first element */ + elemName = elist[i]; + vtkPLY::ply_get_element_description (ply, elemName, &numElems, &nprops); + + // if we're on vertex elements, read them in + if ( elemName && !strcmp ("vertex", elemName) ) + { + // Create a list of points + numPts = numElems; + vtkPoints *pts = vtkPoints::New(); + pts->SetDataTypeToFloat(); + pts->SetNumberOfPoints(numPts); + + // Setup to read the PLY elements + vtkPLY::ply_get_property (ply, elemName, &vertProps[0]); + vtkPLY::ply_get_property (ply, elemName, &vertProps[1]); + vtkPLY::ply_get_property (ply, elemName, &vertProps[2]); + + if ( RGBPointsAvailable ) + { + vtkPLY::ply_get_property (ply, elemName, &vertProps[3]); + vtkPLY::ply_get_property (ply, elemName, &vertProps[4]); + vtkPLY::ply_get_property (ply, elemName, &vertProps[5]); + RGBPoints->SetNumberOfComponents(3); + RGBPoints->SetNumberOfTuples(numPts); + } + plyVertex vertex; + for (j=0; j < numPts; j++) + { + vtkPLY::ply_get_element (ply, (void *) &vertex); + pts->SetPoint (j, vertex.x); + if ( RGBPointsAvailable ) + { + RGBPoints->SetTuple3(j,vertex.red,vertex.green,vertex.blue); + } + } + output->SetPoints(pts); + pts->Delete(); + }//if vertex + + else if ( elemName && !strcmp ("face", elemName) ) + { + // Create a polygonal array + numPolys = numElems; + vtkCellArray *polys = vtkCellArray::New(); + polys->Allocate(polys->EstimateSize(numPolys,3),numPolys/2); + plyFace face; + int verts[256]; + vtkIdType vtkVerts[256]; + + // Get the face properties + vtkPLY::ply_get_property (ply, elemName, &faceProps[0]); + if ( intensityAvailable ) + { + vtkPLY::ply_get_property (ply, elemName, &faceProps[1]); + RGBCells->SetNumberOfComponents(1); + RGBCells->SetNumberOfTuples(numPolys); + } + if ( RGBCellsAvailable ) + { + vtkPLY::ply_get_property (ply, elemName, &faceProps[2]); + vtkPLY::ply_get_property (ply, elemName, &faceProps[3]); + vtkPLY::ply_get_property (ply, elemName, &faceProps[4]); + RGBCells->SetNumberOfComponents(3); + RGBCells->SetNumberOfTuples(numPolys); + } + + // grab all the face elements + for (j=0; j < numPolys; j++) + { + //grab and element from the file + face.verts = verts; + vtkPLY::ply_get_element (ply, (void *) &face); + for (k=0; kInsertNextCell(face.nverts,vtkVerts); + if ( intensityAvailable ) + { + intensity->SetValue(j,face.intensity); + } + if ( RGBCellsAvailable ) + { + RGBCells->SetValue(3*j,face.red); + RGBCells->SetValue(3*j+1,face.green); + RGBCells->SetValue(3*j+2,face.blue); + } + } + output->SetPolys(polys); + polys->Delete(); + }//if face + + free(elist[i]); //allocated by ply_open_for_reading + + }//for all elements of the PLY file + free(elist); //allocated by ply_open_for_reading + + vtkDebugMacro( <<"Read: " << numPts << " points, " + << numPolys << " polygons"); + + // close the PLY file + vtkPLY::ply_close (ply); + + return 1; +} + +void vtkPLYReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + +} diff --git a/IO/vtkPLYReader.h b/IO/vtkPLYReader.h new file mode 100644 index 0000000..ecff458 --- /dev/null +++ b/IO/vtkPLYReader.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLYReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPLYReader - read Stanford University PLY polygonal file format +// .SECTION Description +// vtkPLYReader is a source object that reads polygonal data in +// Stanford University PLY file format (see +// http://graphics.stanford.edu/data/3Dscanrep/). It requires that +// the elements "vertex" and "face" are defined. The "vertex" element +// must have the properties "x", "y", and "z". The "face" element must +// have the property "vertex_indices" defined. Optionally, if the "face" +// element has the properties "intensity" and/or the triplet "red", +// "green", and "blue"; these are read and added as scalars to the +// output data. + +// .SECTION See Also +// vtkPLYWriter + +#ifndef __vtkPLYReader_h +#define __vtkPLYReader_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_IO_EXPORT vtkPLYReader : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkPLYReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with merging set to true. + static vtkPLYReader *New(); + + // Description: + // Specify file name of stereo lithography file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkPLYReader(); + ~vtkPLYReader(); + + char *FileName; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); +private: + vtkPLYReader(const vtkPLYReader&); // Not implemented. + void operator=(const vtkPLYReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkPLYWriter.cxx b/IO/vtkPLYWriter.cxx new file mode 100644 index 0000000..95c97f5 --- /dev/null +++ b/IO/vtkPLYWriter.cxx @@ -0,0 +1,361 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLYWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPLYWriter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkObjectFactory.h" +#include "vtkPLY.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkScalarsToColors.h" + +#include + +vtkCxxRevisionMacro(vtkPLYWriter, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkPLYWriter); + +vtkCxxSetObjectMacro(vtkPLYWriter,LookupTable,vtkScalarsToColors); + +vtkPLYWriter::vtkPLYWriter() +{ + this->FileType = VTK_BINARY; + this->DataByteOrder = VTK_LITTLE_ENDIAN; + this->ArrayName = NULL; + this->Component = 0; + this->ColorMode = VTK_COLOR_MODE_DEFAULT; + this->LookupTable = NULL; + this->Color[0] = this->Color[1] = this->Color[2] = 255; +} + +vtkPLYWriter::~vtkPLYWriter() +{ + if ( this->LookupTable ) + { + this->LookupTable->Delete(); + } + if ( this->ArrayName ) + { + delete [] this->ArrayName; + } +} + +typedef struct _plyVertex { + float x[3]; // the usual 3-space position of a vertex + unsigned char red; + unsigned char green; + unsigned char blue; +} plyVertex; + +typedef struct _plyFace { + unsigned char nverts; // number of vertex indices in list + int *verts; // vertex index list + unsigned char red; + unsigned char green; + unsigned char blue; +} plyFace; + +void vtkPLYWriter::WriteData() +{ + vtkIdType i, j, idx; + vtkPoints *inPts; + vtkCellArray *polys; + vtkPolyData *input = this->GetInput(); + + unsigned char *cellColors, *pointColors; + PlyFile *ply; + float version; + static const char *elemNames[] = { "vertex", "face" }; + static PlyProperty vertProps[] = { // property information for a vertex + {"x", PLY_FLOAT, PLY_FLOAT, static_cast(offsetof(plyVertex,x)), + 0, 0, 0, 0}, + {"y", PLY_FLOAT, PLY_FLOAT, static_cast(offsetof(plyVertex,x)+sizeof(float)), + 0, 0, 0, 0}, + {"z", PLY_FLOAT, PLY_FLOAT, static_cast(offsetof(plyVertex,x)+sizeof(float)+sizeof(float)), + 0, 0, 0, 0}, + {"red", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyVertex,red)), + 0, 0, 0, 0}, + {"green", PLY_UCHAR, PLY_UCHAR, + static_cast(offsetof(plyVertex,green)), 0, 0, 0, 0}, + {"blue", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyVertex,blue)), + 0, 0, 0, 0}, + }; + static PlyProperty faceProps[] = { // property information for a face + {"vertex_indices", PLY_INT, PLY_INT, + static_cast(offsetof(plyFace,verts)), + 1, PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,nverts))}, + {"red", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,red)), + 0, 0, 0, 0}, + {"green", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,green)), + 0, 0, 0, 0}, + {"blue", PLY_UCHAR, PLY_UCHAR, static_cast(offsetof(plyFace,blue)), + 0, 0, 0, 0}, + }; + + // Get input and check data + polys = input->GetPolys(); + inPts = input->GetPoints(); + if (inPts == NULL || polys == NULL ) + { + vtkErrorMacro(<<"No data to write!"); + return; + } + + if ( this->FileName == NULL) + { + vtkErrorMacro(<< "Please specify FileName to write"); + return; + } + + // Open the file in appropriate way + if ( this->FileType == VTK_BINARY ) + { + if ( this->DataByteOrder == VTK_LITTLE_ENDIAN ) + { + ply = vtkPLY::ply_open_for_writing(this->FileName, 2, elemNames, + PLY_BINARY_LE, &version); + } + else + { + ply = vtkPLY::ply_open_for_writing(this->FileName, 2, elemNames, + PLY_BINARY_BE, &version); + } + } + else + { + ply = vtkPLY::ply_open_for_writing(this->FileName, 2, elemNames, + PLY_ASCII, &version); + } + + if ( ply == NULL) + { + vtkErrorMacro(<< "Error opening PLY file"); + return; + } + + // compute colors, if any + vtkIdType numPts = inPts->GetNumberOfPoints(); + vtkIdType numPolys = polys->GetNumberOfCells(); + pointColors = this->GetColors(numPts,input->GetPointData()); + cellColors = this->GetColors(numPolys,input->GetCellData()); + + // describe what properties go into the vertex and face elements + vtkPLY::ply_element_count (ply, "vertex", numPts); + vtkPLY::ply_describe_property (ply, "vertex", &vertProps[0]); + vtkPLY::ply_describe_property (ply, "vertex", &vertProps[1]); + vtkPLY::ply_describe_property (ply, "vertex", &vertProps[2]); + if ( pointColors ) + { + vtkPLY::ply_describe_property (ply, "vertex", &vertProps[3]); + vtkPLY::ply_describe_property (ply, "vertex", &vertProps[4]); + vtkPLY::ply_describe_property (ply, "vertex", &vertProps[5]); + } + + vtkPLY::ply_element_count (ply, "face", numPolys); + vtkPLY::ply_describe_property (ply, "face", &faceProps[0]); + if ( cellColors ) + { + vtkPLY::ply_describe_property (ply, "face", &faceProps[1]); + vtkPLY::ply_describe_property (ply, "face", &faceProps[2]); + vtkPLY::ply_describe_property (ply, "face", &faceProps[3]); + } + + // write a comment and an object information field + vtkPLY::ply_put_comment (ply, "VTK generated PLY File"); + vtkPLY::ply_put_obj_info (ply, "vtkPolyData points and polygons: vtk4.0"); + + // complete the header + vtkPLY::ply_header_complete (ply); + + // set up and write the vertex elements + plyVertex vert; + vtkPLY::ply_put_element_setup (ply, "vertex"); + double dpoint[3]; + for (i = 0; i < numPts; i++) + { + inPts->GetPoint(i,dpoint); + vert.x[0] = static_cast(dpoint[0]); + vert.x[1] = static_cast(dpoint[1]); + vert.x[2] = static_cast(dpoint[2]); + if ( pointColors ) + { + idx = 3*i; + vert.red = *(pointColors + idx); + vert.green = *(pointColors + idx + 1); + vert.blue = *(pointColors + idx + 2); + } + vtkPLY::ply_put_element (ply, (void *) &vert); + } + + // set up and write the face elements + plyFace face; + int verts[256]; + face.verts = verts; + vtkPLY::ply_put_element_setup (ply, "face"); + vtkIdType npts = 0; + vtkIdType *pts = 0; + for (polys->InitTraversal(), i = 0; i < numPolys; i++) + { + polys->GetNextCell(npts,pts); + if ( npts > 256 ) + { + vtkErrorMacro(<<"Ply file only supports polygons with <256 points"); + } + else + { + for (j=0; jColorMode == VTK_COLOR_MODE_OFF || + (this->ColorMode == VTK_COLOR_MODE_UNIFORM_CELL_COLOR && + vtkPointData::SafeDownCast(dsa) != NULL) || + (this->ColorMode == VTK_COLOR_MODE_UNIFORM_POINT_COLOR && + vtkCellData::SafeDownCast(dsa) != NULL) ) + { + return NULL; + } + else if ( this->ColorMode == VTK_COLOR_MODE_UNIFORM_COLOR || + this->ColorMode == VTK_COLOR_MODE_UNIFORM_POINT_COLOR || + this->ColorMode == VTK_COLOR_MODE_UNIFORM_CELL_COLOR ) + { + colors = c = new unsigned char[3*num]; + for (i=0; iColor[0]; + *c++ = this->Color[1]; + *c++ = this->Color[2]; + } + return colors; + } + else //we will color based on data + { + double *tuple; + vtkDataArray *da; + unsigned char *rgb; + vtkUnsignedCharArray *rgbArray; + + if ( !this->ArrayName || (da=dsa->GetArray(this->ArrayName)) == NULL || + this->Component >= (numComp=da->GetNumberOfComponents()) ) + { + return NULL; + } + else if ( (rgbArray=vtkUnsignedCharArray::SafeDownCast(da)) != NULL && + numComp == 3 ) + {//have unsigned char array of three components, copy it + colors = c = new unsigned char[3*num]; + rgb = rgbArray->GetPointer(0); + for (i=0; iLookupTable != NULL ) + {//use the data array mapped through lookup table + colors = c = new unsigned char[3*num]; + for (i=0; iGetTuple(i); + rgb = this->LookupTable->MapValue(tuple[this->Component]); + *c++ = rgb[0]; + *c++ = rgb[1]; + *c++ = rgb[2]; + } + return colors; + } + else //no lookup table + { + return NULL; + } + } +} + +void vtkPLYWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Data Byte Order: "; + if ( this->DataByteOrder == VTK_LITTLE_ENDIAN ) + { + os << "Little Endian\n"; + } + else + { + os << "Big Endian\n"; + } + + os << indent << "Color Mode: "; + if ( this->ColorMode == VTK_COLOR_MODE_DEFAULT ) + { + os << "Default\n"; + } + else if ( this->ColorMode == VTK_COLOR_MODE_UNIFORM_CELL_COLOR ) + { + os << "Uniform Cell Color\n"; + } + else if ( this->ColorMode == VTK_COLOR_MODE_UNIFORM_POINT_COLOR ) + { + os << "Uniform Point Color\n"; + } + else if ( this->ColorMode == VTK_COLOR_MODE_UNIFORM_COLOR ) + { + os << "Uniform Color\n"; + } + else //VTK_COLOR_MODE_OFF + { + os << "Off\n"; + } + + os << indent << "Array Name: " + << (this->ArrayName ? this->ArrayName : "(none)") << "\n"; + + os << indent << "Component: " << this->Component << "\n"; + + os << indent << "Lookup Table: " << this->LookupTable << "\n"; + + os << indent << "Color: (" << this->Color[0] << "," + << this->Color[1] << "," << this->Color[2] << ")\n"; + +} + diff --git a/IO/vtkPLYWriter.h b/IO/vtkPLYWriter.h new file mode 100644 index 0000000..75fd9ca --- /dev/null +++ b/IO/vtkPLYWriter.h @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLYWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPLYWriter - write Stanford PLY file format +// .SECTION Description +// vtkPLYWriter writes polygonal data in Stanford University PLY format +// (see http://graphics.stanford.edu/data/3Dscanrep/). The data can be +// written in either binary (little or big endian) or ASCII representation. + +// .SECTION Caveats +// PLY does not handle big endian versus little endian correctly. Also, +// this class is compiled into VTK only if the PLY library is found +// during the make process (using CMake). + +// .SECTION See Also +// vtkPLYReader + +#ifndef __vtkPLYWriter_h +#define __vtkPLYWriter_h + +#include "vtkPolyDataWriter.h" + +class vtkScalarsToColors; +class vtkDataSetAttributes; + +#define VTK_LITTLE_ENDIAN 0 +#define VTK_BIG_ENDIAN 1 + +#define VTK_COLOR_MODE_DEFAULT 0 +#define VTK_COLOR_MODE_UNIFORM_CELL_COLOR 1 +#define VTK_COLOR_MODE_UNIFORM_POINT_COLOR 2 +#define VTK_COLOR_MODE_UNIFORM_COLOR 3 +#define VTK_COLOR_MODE_OFF 4 + + +class VTK_IO_EXPORT vtkPLYWriter : public vtkPolyDataWriter +{ +public: + static vtkPLYWriter *New(); + vtkTypeRevisionMacro(vtkPLYWriter,vtkPolyDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // If the file type is binary, then the user can specify which + // byte order to use (little versus big endian). + vtkSetClampMacro(DataByteOrder,int,VTK_LITTLE_ENDIAN,VTK_BIG_ENDIAN); + vtkGetMacro(DataByteOrder,int); + void SetDataByteOrderToBigEndian() + {this->SetDataByteOrder(VTK_BIG_ENDIAN);} + void SetDataByteOrderToLittleEndian() + {this->SetDataByteOrder(VTK_LITTLE_ENDIAN);} + + // Description: + // These methods enable the user to control how to add color into the PLY + // output file. The default behavior is as follows. The user provides the + // name of an array and a component number. If the type of the array is + // three components, unsigned char, then the data is written as three + // separate "red", "green" and "blue" properties. If the type is not + // unsigned char, and a lookup table is provided, then the array/component + // are mapped through the table to generate three separate "red", "green" + // and "blue" properties in the PLY file. The user can also set the + // ColorMode to specify a uniform color for the whole part (on a vertex + // colors, face colors, or both. (Note: vertex colors or cell colors may be + // written, depending on where the named array is found. If points and + // cells have the arrays with the same name, then both colors will be + // written.) + vtkSetMacro(ColorMode,int); + vtkGetMacro(ColorMode,int); + void SetColorModeToDefault() + {this->SetColorMode(VTK_COLOR_MODE_DEFAULT);} + void SetColorModeToUniformCellColor() + {this->SetColorMode(VTK_COLOR_MODE_UNIFORM_CELL_COLOR);} + void SetColorModeToUniformPointColor() + {this->SetColorMode(VTK_COLOR_MODE_UNIFORM_POINT_COLOR);} + void SetColorModeToUniformColor() //both cells and points are colored + {this->SetColorMode(VTK_COLOR_MODE_UNIFORM_COLOR);} + void SetColorModeToOff() //No color information is written + {this->SetColorMode(VTK_COLOR_MODE_OFF);} + + // Description: + // Specify the array name to use to color the data. + vtkSetStringMacro(ArrayName); + vtkGetStringMacro(ArrayName); + + // Description: + // Specify the array component to use to color the data. + vtkSetClampMacro(Component,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(Component,int); + + // Description: + // A lookup table can be specified in order to convert data arrays to + // RGBA colors. + virtual void SetLookupTable(vtkScalarsToColors*); + vtkGetObjectMacro(LookupTable,vtkScalarsToColors); + + // Description: + // Set the color to use when using a uniform color (either point or cells, + // or both). The color is specified as a triplet of three unsigned chars + // between (0,255). This only takes effect when the ColorMode is set to + // uniform point, uniform cell, or uniform color. + vtkSetVector3Macro(Color,unsigned char); + vtkGetVector3Macro(Color,unsigned char); + +protected: + vtkPLYWriter(); + ~vtkPLYWriter(); + + void WriteData(); + unsigned char *GetColors(vtkIdType num, vtkDataSetAttributes *dsa); + + int DataByteOrder; + char *ArrayName; + int Component; + int ColorMode; + vtkScalarsToColors *LookupTable; + unsigned char Color[3]; + +private: + vtkPLYWriter(const vtkPLYWriter&); // Not implemented. + void operator=(const vtkPLYWriter&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkPNGReader.cxx b/IO/vtkPNGReader.cxx new file mode 100644 index 0000000..813d174 --- /dev/null +++ b/IO/vtkPNGReader.cxx @@ -0,0 +1,388 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNGReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPNGReader.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtk_png.h" + +vtkCxxRevisionMacro(vtkPNGReader, "$Revision: 1.25 $"); +vtkStandardNewMacro(vtkPNGReader); + +#ifdef _MSC_VER +// Let us get rid of this funny warning on /W4: +// warning C4611: interaction between '_setjmp' and C++ object +// destruction is non-portable +#pragma warning( disable : 4611 ) +#endif + +void vtkPNGReader::ExecuteInformation() +{ + this->ComputeInternalFileName(this->DataExtent[4]); + if (this->InternalFileName == NULL) + { + return; + } + + FILE *fp = fopen(this->InternalFileName, "rb"); + if (!fp) + { + vtkErrorMacro("Unable to open file " << this->InternalFileName); + return; + } + unsigned char header[8]; + fread(header, 1, 8, fp); + int is_png = !png_sig_cmp(header, 0, 8); + if (!is_png) + { + vtkErrorMacro(<<"Unknown file type! Not a PNG file!"); + fclose(fp); + return; + } + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + NULL, NULL); + if (!png_ptr) + { + vtkErrorMacro(<< "Out of memory." ); + fclose(fp); + return; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + vtkErrorMacro(<< "Out of memory."); + fclose(fp); + return; + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + vtkErrorMacro(<<"Unable to read PNG file!"); + fclose(fp); + return; + } + + // Set error handling + if (setjmp (png_jmpbuf(png_ptr))) + { + png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); + return; + } + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + int compression_type, filter_method; + // get size and bit-depth of the PNG-image + png_get_IHDR(png_ptr, info_ptr, + &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); + + // set-up the transformations + // convert palettes to RGB + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_set_palette_to_rgb(png_ptr); + } + + // minimum of a byte per pixel + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + { + png_set_gray_1_2_4_to_8(png_ptr); + } + + // add alpha if any alpha found + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + { + png_set_tRNS_to_alpha(png_ptr); + } + + // update the info now that we have defined the filters + png_read_update_info(png_ptr, info_ptr); + + this->DataExtent[0] = 0; + this->DataExtent[1] = width - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = height - 1; + + if (bit_depth <= 8) + { + this->SetDataScalarTypeToUnsignedChar(); + } + else + { + this->SetDataScalarTypeToUnsignedShort(); + } + this->SetNumberOfScalarComponents( + png_get_channels(png_ptr, info_ptr)); + this->vtkImageReader2::ExecuteInformation(); + + // close the file + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); +} + + +template +void vtkPNGReaderUpdate2(vtkPNGReader *self, OT *outPtr, + int *outExt, vtkIdType *outInc, long pixSize) +{ + unsigned int ui; + int i; + FILE *fp = fopen(self->GetInternalFileName(), "rb"); + if (!fp) + { + return; + } + unsigned char header[8]; + fread(header, 1, 8, fp); + int is_png = !png_sig_cmp(header, 0, 8); + if (!is_png) + { + fclose(fp); + return; + } + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); + if (!png_ptr) + { + return; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return; + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return; + } + + // Set error handling + if (setjmp (png_jmpbuf(png_ptr))) + { + png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)NULL); + return; + } + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + int compression_type, filter_method; + // get size and bit-depth of the PNG-image + png_get_IHDR(png_ptr, info_ptr, + &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_method); + + // set-up the transformations + // convert palettes to RGB + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_set_palette_to_rgb(png_ptr); + } + + // minimum of a byte per pixel + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + { + png_set_gray_1_2_4_to_8(png_ptr); + } + + // add alpha if any alpha found + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + { + png_set_tRNS_to_alpha(png_ptr); + } + + if (bit_depth > 8) + { +#ifndef VTK_WORDS_BIGENDIAN + png_set_swap(png_ptr); +#endif + } + + // have libpng handle interlacing + //int number_of_passes = png_set_interlace_handling(png_ptr); + // update the info now that we have defined the filters + png_read_update_info(png_ptr, info_ptr); + + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + unsigned char *tempImage = new unsigned char [rowbytes*height]; + png_bytep *row_pointers = new png_bytep [height]; + for (ui = 0; ui < height; ++ui) + { + row_pointers[ui] = tempImage + rowbytes*ui; + } + png_read_image(png_ptr, row_pointers); + + // copy the data into the outPtr + OT *outPtr2; + outPtr2 = outPtr; + long outSize = pixSize*(outExt[1] - outExt[0] + 1); + for (i = outExt[2]; i <= outExt[3]; ++i) + { + memcpy(outPtr2,row_pointers[height - i - 1] + outExt[0]*pixSize,outSize); + outPtr2 += outInc[1]; + } + delete [] tempImage; + delete [] row_pointers; + + // close the file + png_read_end(png_ptr, NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + fclose(fp); +} + +//---------------------------------------------------------------------------- +// This function reads in one data of data. +// templated to handle different data types. +template +void vtkPNGReaderUpdate(vtkPNGReader *self, vtkImageData *data, OT *outPtr) +{ + vtkIdType outIncr[3]; + int outExtent[6]; + OT *outPtr2; + + data->GetExtent(outExtent); + data->GetIncrements(outIncr); + + long pixSize = data->GetNumberOfScalarComponents()*sizeof(OT); + + outPtr2 = outPtr; + int idx2; + for (idx2 = outExtent[4]; idx2 <= outExtent[5]; ++idx2) + { + self->ComputeInternalFileName(idx2); + // read in a PNG file + vtkPNGReaderUpdate2(self, outPtr2, outExtent, outIncr, pixSize); + self->UpdateProgress((idx2 - outExtent[4])/ + (outExtent[5] - outExtent[4] + 1.0)); + outPtr2 += outIncr[2]; + } +} + + +//---------------------------------------------------------------------------- +// This function reads a data from a file. The datas extent/axes +// are assumed to be the same as the file extent/order. +void vtkPNGReader::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + if (this->InternalFileName == NULL) + { + vtkErrorMacro(<< "Either a FileName or FilePrefix must be specified."); + return; + } + + data->GetPointData()->GetScalars()->SetName("PNGImage"); + + this->ComputeDataIncrements(); + + // Call the correct templated function for the output + void *outPtr; + + // Call the correct templated function for the input + outPtr = data->GetScalarPointer(); + switch (data->GetScalarType()) + { + vtkTemplateMacro(vtkPNGReaderUpdate(this, data, (VTK_TT *)(outPtr))); + default: + vtkErrorMacro(<< "UpdateFromFile: Unknown data type"); + } +} + + +int vtkPNGReader::CanReadFile(const char* fname) +{ + FILE* fp = fopen(fname, "rb"); + if(!fp) + { + return 0; + } + unsigned char header[8]; + fread(header, 1, 8, fp); + int is_png = !png_sig_cmp(header, 0, 8); + if(!is_png) + { + fclose(fp); + return 0; + } + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + NULL, NULL); + if (!png_ptr) + { + fclose(fp); + return 0; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + fclose(fp); + return 0; + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + fclose(fp); + return 0; + } + png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); + + fclose(fp); + return 3; +} +#ifdef _MSC_VER +// Put the warning back +#pragma warning( default : 4611 ) +#endif + +//---------------------------------------------------------------------------- +void vtkPNGReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkPNGReader.h b/IO/vtkPNGReader.h new file mode 100644 index 0000000..b9156af --- /dev/null +++ b/IO/vtkPNGReader.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNGReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPNGReader - read PNG files +// .SECTION Description +// vtkPNGReader is a source object that reads PNG files. +// It should be able to read most any PNG file +// +// .SECTION See Also +// vtkPNGWriter + +#ifndef __vtkPNGReader_h +#define __vtkPNGReader_h + +#include "vtkImageReader2.h" + +class VTK_IO_EXPORT vtkPNGReader : public vtkImageReader2 +{ +public: + static vtkPNGReader *New(); + vtkTypeRevisionMacro(vtkPNGReader,vtkImageReader2); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: is the given file name a png file? + virtual int CanReadFile(const char* fname); + + // Description: + // Get the file extensions for this format. + // Returns a string with a space separated list of extensions in + // the format .extension + virtual const char* GetFileExtensions() + { + return ".png"; + } + + // Description: + // Return a descriptive name for the file format that might be useful in a GUI. + virtual const char* GetDescriptiveName() + { + return "PNG"; + } + +protected: + vtkPNGReader() {}; + ~vtkPNGReader() {}; + + virtual void ExecuteInformation(); + virtual void ExecuteData(vtkDataObject *out); +private: + vtkPNGReader(const vtkPNGReader&); // Not implemented. + void operator=(const vtkPNGReader&); // Not implemented. +}; +#endif + + diff --git a/IO/vtkPNGWriter.cxx b/IO/vtkPNGWriter.cxx new file mode 100644 index 0000000..6881e56 --- /dev/null +++ b/IO/vtkPNGWriter.cxx @@ -0,0 +1,310 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNGWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPNGWriter.h" + +#include "vtkErrorCode.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkUnsignedCharArray.h" +#include "vtk_png.h" + +vtkCxxRevisionMacro(vtkPNGWriter, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkPNGWriter); + +vtkCxxSetObjectMacro(vtkPNGWriter,Result,vtkUnsignedCharArray); + +vtkPNGWriter::vtkPNGWriter() +{ + this->FileLowerLeft = 1; + this->FileDimensionality = 2; + this->WriteToMemory = 0; + this->Result = 0; + this->TempFP = 0; +} + +vtkPNGWriter::~vtkPNGWriter() +{ + if (this->Result) + { + this->Result->Delete(); + this->Result = 0; + } +} + +//---------------------------------------------------------------------------- +// Writes all the data from the input. +void vtkPNGWriter::Write() +{ + this->SetErrorCode(vtkErrorCode::NoError); + + // Error checking + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<<"Write:Please specify an input!"); + return; + } + if (!this->WriteToMemory && !this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Write:Please specify either a FileName or a file prefix and pattern"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return; + } + + // Make sure the file name is allocated + this->InternalFileName = + new char[(this->FileName ? strlen(this->FileName) : 1) + + (this->FilePrefix ? strlen(this->FilePrefix) : 1) + + (this->FilePattern ? strlen(this->FilePattern) : 1) + 10]; + + // Fill in image information. + this->GetInput()->UpdateInformation(); + int *wExtent; + wExtent = this->GetInput()->GetWholeExtent(); + this->FileNumber = this->GetInput()->GetWholeExtent()[4]; + this->MinimumFileNumber = this->MaximumFileNumber = this->FileNumber; + this->FilesDeleted = 0; + this->UpdateProgress(0.0); + // loop over the z axis and write the slices + for (this->FileNumber = wExtent[4]; this->FileNumber <= wExtent[5]; + ++this->FileNumber) + { + this->MaximumFileNumber = this->FileNumber; + this->GetInput()->SetUpdateExtent(wExtent[0], wExtent[1], + wExtent[2], wExtent[3], + this->FileNumber, + this->FileNumber); + // determine the name + if (this->FileName) + { + sprintf(this->InternalFileName,"%s",this->FileName); + } + else + { + if (this->FilePrefix) + { + sprintf(this->InternalFileName, this->FilePattern, + this->FilePrefix, this->FileNumber); + } + else + { + sprintf(this->InternalFileName, this->FilePattern,this->FileNumber); + } + } + this->GetInput()->UpdateData(); + this->WriteSlice(this->GetInput()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeleteFiles(); + break; + } + this->UpdateProgress((this->FileNumber - wExtent[4])/ + (wExtent[5] - wExtent[4] + 1.0)); + } + delete [] this->InternalFileName; + this->InternalFileName = NULL; +} + +extern "C" +{ + void vtkPNGWriteInit(png_structp png_ptr, png_bytep data, + png_size_t sizeToWrite) + { + vtkPNGWriter *self = + vtkPNGWriter::SafeDownCast(static_cast + (png_get_io_ptr(png_ptr))); + if (self) + { + vtkUnsignedCharArray *uc = self->GetResult(); + // write to the uc array + unsigned char *ptr = uc->WritePointer(uc->GetMaxId()+1,sizeToWrite); + memcpy(ptr, data, sizeToWrite); + } + } +} + +extern "C" +{ + void vtkPNGWriteFlush(png_structp vtkNotUsed(png_ptr)) + { + } +} + +extern "C" +{ + /* The PNG library does not expect the error function to return. + Therefore we must use this ugly longjmp call. */ + void vtkPNGWriteErrorFunction(png_structp png_ptr, + png_const_charp vtkNotUsed(error_msg)) + { + longjmp(png_ptr->jmpbuf, 1); + } +} + +extern "C" +{ + void vtkPNGWriteWarningFunction(png_structp vtkNotUsed(png_ptr), + png_const_charp vtkNotUsed(warning_msg)) + { + } +} + +// we disable this warning because even though this is a C++ file, between +// the setjmp and resulting longjmp there should not be any C++ constructors +// or destructors. +#if defined(_MSC_VER) && !defined(VTK_DISPLAY_WIN32_WARNINGS) +#pragma warning ( disable : 4611 ) +#endif +void vtkPNGWriter::WriteSlice(vtkImageData *data) +{ + // Call the correct templated function for the output + unsigned int ui; + + // Call the correct templated function for the input + if (data->GetScalarType() != VTK_UNSIGNED_SHORT && + data->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkWarningMacro("PNGWriter only supports unsigned char and unsigned short inputs"); + return; + } + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); + if (!png_ptr) + { + vtkErrorMacro(<<"Unable to write PNG file!"); + return; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + vtkErrorMacro(<<"Unable to write PNG file!"); + return; + } + + + this->TempFP = 0; + if (this->WriteToMemory) + { + vtkUnsignedCharArray *uc = this->GetResult(); + if (!uc || uc->GetReferenceCount() > 1) + { + uc = vtkUnsignedCharArray::New(); + this->SetResult(uc); + uc->Delete(); + } + // start out with 10K as a guess for the image size + uc->Allocate(10000); + png_set_write_fn(png_ptr, static_cast(this), + vtkPNGWriteInit, vtkPNGWriteFlush); + } + else + { + this->TempFP = fopen(this->InternalFileName, "wb"); + if (!this->TempFP) + { + vtkErrorMacro("Unable to open file " << this->InternalFileName); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + png_init_io(png_ptr, this->TempFP); + png_set_error_fn(png_ptr, png_ptr, + vtkPNGWriteErrorFunction, vtkPNGWriteWarningFunction); + if (setjmp(png_ptr->jmpbuf)) + { + fclose(this->TempFP); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + + + int *uExtent = data->GetUpdateExtent(); + void *outPtr; + outPtr = data->GetScalarPointer(uExtent[0], uExtent[2], uExtent[4]); + png_uint_32 width, height; + width = uExtent[1] - uExtent[0] + 1; + height = uExtent[3] - uExtent[2] + 1; + int bit_depth = 8; + if (data->GetScalarType() == VTK_UNSIGNED_SHORT) + { + bit_depth = 16; + } + int color_type; + switch (data->GetNumberOfScalarComponents()) + { + case 1: color_type = PNG_COLOR_TYPE_GRAY; + break; + case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + break; + case 3: color_type = PNG_COLOR_TYPE_RGB; + break; + default: color_type = PNG_COLOR_TYPE_RGB_ALPHA; + break; + } + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + // interlace_type - PNG_INTERLACE_NONE or + // PNG_INTERLACE_ADAM7 + + png_write_info(png_ptr, info_ptr); + // default is big endian + if (bit_depth > 8) + { +#ifndef VTK_WORDS_BIGENDIAN + png_set_swap(png_ptr); +#endif + } + png_byte **row_pointers = new png_byte *[height]; + vtkIdType *outInc = data->GetIncrements(); + vtkIdType rowInc = outInc[1]*bit_depth/8; + for (ui = 0; ui < height; ui++) + { + row_pointers[height - ui - 1] = (png_byte *)outPtr; + outPtr = (unsigned char *)outPtr + rowInc; + } + png_write_image(png_ptr, row_pointers); + png_write_end(png_ptr, info_ptr); + + delete [] row_pointers; + png_destroy_write_struct(&png_ptr, &info_ptr); + + if (this->TempFP) + { + fflush(this->TempFP); + if (ferror(this->TempFP)) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } + } + + if (this->TempFP) + { + fclose(this->TempFP); + } +} + +void vtkPNGWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Result: " << this->Result << "\n"; + os << indent << "WriteToMemory: " << (this->WriteToMemory ? "On" : "Off") << "\n"; +} diff --git a/IO/vtkPNGWriter.h b/IO/vtkPNGWriter.h new file mode 100644 index 0000000..0075254 --- /dev/null +++ b/IO/vtkPNGWriter.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNGWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPNGWriter - Writes PNG files. +// .SECTION Description +// vtkPNGWriter writes PNG files. It supports 1 to 4 component data of +// unsigned char or unsigned short + +// .SECTION See Also +// vtkPNGReader + +#ifndef __vtkPNGWriter_h +#define __vtkPNGWriter_h + +#include "vtkImageWriter.h" + +class vtkImageData; +class vtkUnsignedCharArray; + +class VTK_IO_EXPORT vtkPNGWriter : public vtkImageWriter +{ +public: + static vtkPNGWriter *New(); + vtkTypeRevisionMacro(vtkPNGWriter,vtkImageWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The main interface which triggers the writer to start. + virtual void Write(); + + // Description: + // Write the image to memory (a vtkUnsignedCharArray) + vtkSetMacro(WriteToMemory, unsigned int); + vtkGetMacro(WriteToMemory, unsigned int); + vtkBooleanMacro(WriteToMemory, unsigned int); + + // Description: + // When writing to memory this is the result, it will be NULL until the + // data is written the first time + virtual void SetResult(vtkUnsignedCharArray*); + vtkGetObjectMacro(Result, vtkUnsignedCharArray); + +protected: + vtkPNGWriter(); + ~vtkPNGWriter(); + + void WriteSlice(vtkImageData *data); + unsigned int WriteToMemory; + vtkUnsignedCharArray *Result; + FILE *TempFP; + +private: + vtkPNGWriter(const vtkPNGWriter&); // Not implemented. + void operator=(const vtkPNGWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkPNMReader.cxx b/IO/vtkPNMReader.cxx new file mode 100644 index 0000000..7c3fe3a --- /dev/null +++ b/IO/vtkPNMReader.cxx @@ -0,0 +1,233 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNMReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPNMReader.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPNMReader, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkPNMReader); + +char vtkPNMReaderGetChar(FILE *fp) +{ + char c; + int result; + + if ((result = getc(fp)) == EOF ) + { + return '\0'; + } + + c = (char)result; + if (c == '#') + { + do + { + if ((result = getc(fp)) == EOF ) + { + return '\0'; + } + c = (char)result; + } + while (c != '\n'); + } + + return c; +} + +int vtkPNMReaderGetInt(FILE *fp) +{ + char c; + int result = 0; + + do + { + c = vtkPNMReaderGetChar(fp); + } + while ((c < '1')||(c > '9')); + do + { + result = result * 10 + (c - '0'); + c = vtkPNMReaderGetChar(fp); + } + while ((c >= '0')&&(c <= '9')); + + // put the CR/LF or whitespace back..... + ungetc(c, fp); + return result; +} + + +void vtkPNMReader::ExecuteInformation() +{ + int xsize, ysize, comp; + char magic[80]; + char c; + FILE *fp; + + // if the user has not set the extent, but has set the VOI + // set the zaxis extent to the VOI z axis + if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 && + (this->DataVOI[4] || this->DataVOI[5])) + { + this->DataExtent[4] = this->DataVOI[4]; + this->DataExtent[5] = this->DataVOI[5]; + } + + if (!this->FileName && !this->FilePattern) + { + vtkErrorMacro(<<"Either a FileName or FilePattern must be specified."); + return; + } + + // Allocate the space for the filename + this->ComputeInternalFileName(this->DataExtent[4]); + + // get the magic number by reading in a file + fp = fopen(this->InternalFileName,"rb"); + if (!fp) + { + vtkErrorMacro("Unable to open file " << this->InternalFileName); + return; + } + + do + { + c = vtkPNMReaderGetChar(fp); + if (c == '\0') + { // Bad file. + this->GetOutput()->SetWholeExtent(0, -1, 0, -1, 0, -1); + fclose(fp); + return; + } + } + while (c != 'P'); + magic[0] = c; + magic[1] = vtkPNMReaderGetChar(fp); + magic[2] = '\0'; + + // now get the dimensions + xsize = vtkPNMReaderGetInt(fp); + ysize = vtkPNMReaderGetInt(fp); + + // read max pixel value into comp for now + vtkPNMReaderGetInt(fp); + // if file is ascii, any amount of whitespace may follow. + // if file is binary, a single whitespace character will follow. + // We only support binary ppm and pgm files right now. So the next + // character IS always ignored. + c = getc(fp); + + // if this file was "written" on the PC, then a CR will have been + // written as a CR/LF combination. So, if this single whitespace + // character is a CR and it is followed by a LF, then swallow the + // linefeed character as well. (Not part of the PPM standard, but a + // a hard fact of life. + if ( c == 0x0d ) + { + c = getc(fp); + if ( c != 0x0a ) + { + ungetc( c, fp ); + } + } + + // Set the header size now that we have parsed it + this->SetHeaderSize(ftell(fp)); + + fclose(fp); + + // compare magic number to determine file type + if ( ! strcmp(magic,"P5") ) + { + comp = 1; + } + else if ( ! strcmp(magic,"P6") ) + { + comp = 3; + } + else + { + vtkErrorMacro(<<"Unknown file type! " << this->InternalFileName + <<" is not a binary PGM or PPM!"); + return; + } + + // if the user has set the VOI, just make sure its valid + if (this->DataVOI[0] || this->DataVOI[1] || + this->DataVOI[2] || this->DataVOI[3] || + this->DataVOI[4] || this->DataVOI[5]) + { + if ((this->DataVOI[0] < 0) || + (this->DataVOI[1] >= xsize) || + (this->DataVOI[2] < 0) || + (this->DataVOI[3] >= ysize)) + { + vtkWarningMacro("The requested VOI is larger than the file's (" << this->InternalFileName << ") extent "); + this->DataVOI[0] = 0; + this->DataVOI[1] = xsize - 1; + this->DataVOI[2] = 0; + this->DataVOI[3] = ysize - 1; + } + } + + this->DataExtent[0] = 0; + this->DataExtent[1] = xsize - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = ysize - 1; + + this->SetDataScalarTypeToUnsignedChar(); + this->SetNumberOfScalarComponents(comp); + + this->vtkImageReader::ExecuteInformation(); +} + + +inline int iseol(int c) +{ + return c == 10 || c == 13; +} + + + +int vtkPNMReader::CanReadFile(const char* fname) +{ + FILE *fp = fopen(fname, "rb"); + if(!fp) + { + return 0; + } + unsigned char magic[3]; + if(fread(magic, 1, 3, fp) != 3) + { + fclose(fp); + return 0; + } + int ok = ((magic[0] == 'P') && + iseol(magic[2]) && + (magic[1] >= '1' && magic[1] <= '6')); + fclose(fp); + if (ok) + { + return 3; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkPNMReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkPNMReader.h b/IO/vtkPNMReader.h new file mode 100644 index 0000000..0751b50 --- /dev/null +++ b/IO/vtkPNMReader.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNMReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPNMReader - read pnm (i.e., portable anymap) files + +// .SECTION Description +// vtkPNMReader is a source object that reads pnm (portable anymap) files. +// This includes .pbm (bitmap), .pgm (grayscale), and .ppm (pixmap) files. +// (Currently this object only reads binary versions of these files.) +// +// PNMReader creates structured point datasets. The dimension of the +// dataset depends upon the number of files read. Reading a single file +// results in a 2D image, while reading more than one file results in a +// 3D volume. +// +// To read a volume, files must be of the form "FileName." (e.g., +// foo.ppm.0, foo.ppm.1, ...). You must also specify the DataExtent. The +// fifth and sixth values of the DataExtent specify the beginning and ending +// files to read. + + +#ifndef __vtkPNMReader_h +#define __vtkPNMReader_h + +#include "vtkImageReader.h" + +class VTK_IO_EXPORT vtkPNMReader : public vtkImageReader +{ +public: + static vtkPNMReader *New(); + vtkTypeRevisionMacro(vtkPNMReader,vtkImageReader); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + int CanReadFile(const char* fname); + // Description: + // .pnm .pgm .ppm + virtual const char* GetFileExtensions() + { + return ".pnm .pgm .ppm"; + } + + // Description: + // PNM + virtual const char* GetDescriptiveName() + { + return "PNM"; + } + +protected: + vtkPNMReader() {}; + ~vtkPNMReader() {}; + void ExecuteInformation(); +private: + vtkPNMReader(const vtkPNMReader&); // Not implemented. + void operator=(const vtkPNMReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkPNMWriter.cxx b/IO/vtkPNMWriter.cxx new file mode 100644 index 0000000..573f84b --- /dev/null +++ b/IO/vtkPNMWriter.cxx @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNMWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPNMWriter.h" + +#include "vtkErrorCode.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkPNMWriter, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkPNMWriter); + +#ifdef write +#undef write +#endif + +#ifdef close +#undef close +#endif + +void vtkPNMWriter::WriteFileHeader(ofstream *file, vtkImageData *cache) +{ + int min1, max1, min2, max2, min3, max3; + int bpp; + + // Find the length of the rows to write. + cache->GetWholeExtent(min1, max1, min2, max2, min3, max3); + bpp = cache->GetNumberOfScalarComponents(); + + // spit out the pnm header + if (bpp == 1) + { + *file << "P5\n"; + *file << "# pgm file written by the visualization toolkit\n"; + *file << (max1 - min1 + 1) << " " << (max2 - min2 + 1) << "\n255\n"; + } + else + { + *file << "P6\n"; + *file << "# ppm file written by the visualization toolkit\n"; + *file << (max1 - min1 + 1) << " " << (max2 - min2 + 1) << "\n255\n"; + } +} + + +void vtkPNMWriter::WriteFile(ofstream *file, vtkImageData *data, + int extent[6]) +{ + int idx0, idx1, idx2; + int rowLength; // in bytes + void *ptr; + unsigned long count = 0; + unsigned long target; + float progress = this->Progress; + float area; + int *wExtent; + + // Make sure we actually have data. + if ( !data->GetPointData()->GetScalars()) + { + vtkErrorMacro(<< "Could not get data from input."); + return; + } + + // take into consideration the scalar type + switch (data->GetScalarType()) + { + case VTK_UNSIGNED_CHAR: + rowLength = sizeof(unsigned char); + break; + default: + vtkErrorMacro("PNMWriter only accepts unsigned char scalars!"); + return; + } + rowLength *= data->GetNumberOfScalarComponents(); + + wExtent = this->GetInput()->GetWholeExtent(); + area = static_cast(((extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)* + (extent[1] - extent[0] + 1))) / + static_cast(((wExtent[5] -wExtent[4] + 1)*(wExtent[3] -wExtent[2] + 1)* + (wExtent[1] -wExtent[0] + 1))); + + target = (unsigned long)((extent[5]-extent[4]+1)* + (extent[3]-extent[2]+1)/(50.0*area)); + target++; + + for (idx2 = extent[4]; idx2 <= extent[5]; ++idx2) + { + for (idx1 = extent[3]; idx1 >= extent[2]; idx1--) + { + if (!(count%target)) + { + this->UpdateProgress(progress + count/(50.0*target)); + } + count++; + for (idx0 = extent[0]; idx0 <= extent[1]; idx0++) + { + ptr = data->GetScalarPointer(idx0, idx1, idx2); + if ( ! file->write((char *)ptr, rowLength)) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkPNMWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkPNMWriter.h b/IO/vtkPNMWriter.h new file mode 100644 index 0000000..3d5b8f1 --- /dev/null +++ b/IO/vtkPNMWriter.h @@ -0,0 +1,46 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPNMWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPNMWriter - Writes PNM (portable any map) files. +// .SECTION Description +// vtkPNMWriter writes PNM file. The data type +// of the file is unsigned char regardless of the input type. + + +#ifndef __vtkPNMWriter_h +#define __vtkPNMWriter_h + +#include "vtkImageWriter.h" + +class VTK_IO_EXPORT vtkPNMWriter : public vtkImageWriter +{ +public: + static vtkPNMWriter *New(); + vtkTypeRevisionMacro(vtkPNMWriter,vtkImageWriter); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkPNMWriter() {}; + ~vtkPNMWriter() {}; + + virtual void WriteFile(ofstream *file, vtkImageData *data, int extent[6]); + virtual void WriteFileHeader(ofstream *, vtkImageData *); +private: + vtkPNMWriter(const vtkPNMWriter&); // Not implemented. + void operator=(const vtkPNMWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkParticleReader.cxx b/IO/vtkParticleReader.cxx new file mode 100644 index 0000000..b9f5782 --- /dev/null +++ b/IO/vtkParticleReader.cxx @@ -0,0 +1,1029 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParticleReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParticleReader.h" + +#include "vtkSmartPointer.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkByteSwap.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkCellArray.h" +#include "vtkDataArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" + +#include +#include +#include + +vtkCxxRevisionMacro(vtkParticleReader, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkParticleReader); + +namespace { + // .NAME ParseLine - Read a line of four values of type T filtering out comments. + // .SECTION Description + // The ParseLine operator scans a string and returns 0 if it finds a + // comment symbol. Otherwise it returns 1 and four values corresponding + // to the position of the particle (x,y,z) and a scalar s asociated with + // the particle. It is a good idea to set the values of val to some + // predefined value before calling the operator. + template < typename T > + class ParseLine + { + public: + ParseLine (): LookForEndString(false) {}; + int operator () (vtkstd::string &s, T val[4]) + { + // Skip over comment lines. + vtkstd::string::iterator itr; + vtkstd::string tgt("/*"); + itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end()); + if ( itr != s.end() ) + { + LookForEndString = true; + //continue; + } + if ( LookForEndString ) + { + tgt = "*/"; + itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end()); + if ( itr != s.end() ) + { + LookForEndString = false; + } + //continue; + return 0; + } + + tgt = "//"; + itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end()); + if ( itr != s.end() ) + { + return 0; + } + tgt = "%"; + itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end()); + if ( itr != s.end() ) + { + return 0; + } + tgt = "#"; + itr = vtkstd::search(s.begin(),s.end(),tgt.begin(),tgt.end()); + if ( itr != s.end() ) + { + return 0; + } + // If comma delimited, replace with tab + vtkstd::replace(s.begin(),s.end(),',','\t'); + + // We have data. + strstream is; + is << s.c_str() << ends;// no istringstream in VTK + is >> val[0] >> val[1] >> val[2] >> val[3]; + + return 1; + } + + private: + bool LookForEndString; + + }; + + // The number of times we output a progress message. + int const quantum = 20; + // The ratio of high ASCII characters to low ASCII characeters. + double hiToLowASCII = 0.1; + +} +//---------------------------------------------------------------------------- +vtkParticleReader::vtkParticleReader() : + FileName(NULL) + , File(NULL) + , HasScalar(1) + , FileType(FILE_TYPE_IS_UNKNOWN) + , DataType(VTK_FLOAT) + , Alliquot(0) + , Count(0) + , SwapBytes(0) + , NumberOfPoints(0) +{ + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkParticleReader::~vtkParticleReader() +{ + if (this->File) + { + this->File->close(); + delete this->File; + this->File = NULL; + } + + if (this->FileName) + { + delete [] this->FileName; + this->FileName = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkParticleReader::OpenFile() +{ + if (!this->FileName) + { + vtkErrorMacro(<<"FileName must be specified."); + return; + } + + // If the file was open close it. + if (this->File) + { + this->File->close(); + delete this->File; + this->File = NULL; + } + + // Open the new file. + vtkDebugMacro(<< "Initialize: opening file " << this->FileName); +#ifdef _WIN32 + this->File = new ifstream(this->FileName, ios::in | ios::binary); +#else + this->File = new ifstream(this->FileName, ios::in); +#endif + if (! this->File || this->File->fail()) + { + vtkErrorMacro(<< "Initialize: Could not open file " << + this->FileName); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkParticleReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkParticleReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + if (!this->FileName) + { + vtkErrorMacro(<<"FileName must be specified."); + return 0; + } + + this->OpenFile(); + int ft = this->FileType; + if ( ft == FILE_TYPE_IS_UNKNOWN ) + { + ft = DetermineFileType(); + if ( ft == FILE_TYPE_IS_UNKNOWN ) + { + vtkErrorMacro(<< "File type cannot be determined."); + return 0; + } + } + + switch ( ft ) + { + case FILE_TYPE_IS_TEXT: + switch ( this->DataType ) + { + case VTK_FLOAT: + return ProduceOutputFromTextFileFloat(outputVector); + break; + case VTK_DOUBLE: + return ProduceOutputFromTextFileDouble(outputVector); + break; + default: + { + vtkErrorMacro(<<"Only float or double data can be processed."); + return 0; + } + } + case FILE_TYPE_IS_BINARY: + switch ( this->DataType ) + { + case VTK_FLOAT: + return ProduceOutputFromBinaryFileFloat(outputVector); + break; + case VTK_DOUBLE: + return ProduceOutputFromBinaryFileDouble(outputVector); + break; + default: + { + vtkErrorMacro(<<"Only float or double data can be processed."); + return 0; + } + } + default: + { + vtkErrorMacro(<<"The file type was not able to be determined."); + return 0; + } + } +} + +//---------------------------------------------------------------------------- +int vtkParticleReader::DetermineFileType() +{ + // This function assumes that the file has been opened. + + this->File->seekg(0,ios::end); + if (this->File->fail()) + { + vtkErrorMacro("Could not seek to end of file."); + return FILE_TYPE_IS_UNKNOWN; + } + size_t fileLength = this->File->tellg(); + if ( fileLength == 0 ) + { + vtkErrorMacro("File is empty."); + return FILE_TYPE_IS_UNKNOWN; + } + + this->File->seekg(0,ios::beg); + if (this->File->fail()) + { + vtkErrorMacro("Could not seek to start of file."); + return FILE_TYPE_IS_UNKNOWN; + } + + size_t sampleSize = fileLength < 5000 ? fileLength: 5000; + // cout << "File length: " << fileLength << " Sample size: " << sampleSize << endl; + vtkstd::vector s; + for ( size_t i = 0; i < sampleSize; ++i ) + { + char c; + this->File->read(&c,sizeof(char)); + s.push_back(c); + } + // If read terminated prematurely then it may have detected + // a premature EOF character in the data. + // Assume that the file type is undetermined in this case. + if ( s.size() != sampleSize ) + { + // cout << "Premature termination" << endl; + return FILE_TYPE_IS_UNKNOWN; + } + + size_t zero = 0; + size_t conventionalASCII = 0; + size_t extendedASCII = 0; + size_t controlASCII = 0; + size_t otherASCII = 0; + for ( size_t j = 0; j < s.size(); ++j ) + { + if ( s[j] == '\0' ) + { + zero++; + continue; + } + // Conventional ASCII characters. + if ( s[j] > 0x1f && s[j] < 0x80 ) + { + conventionalASCII++; + continue; + } + // Extended ASCII characters may have been used. + if ( s[j] > 0x7f ) + { + extendedASCII++; + continue; + } + // Control characters. + if ( s[j] == '\n' || s[j] == '\r' || s[j] == '\t' || s[j] == '\f' ) + { + controlASCII++; + continue; + } + otherASCII++; + } + + // NULL shouldn't ever appear in a text file. + if ( zero != 0 || otherASCII > 0 || conventionalASCII == 0 ) + { + return FILE_TYPE_IS_BINARY; + } + if ( (double)extendedASCII / (double) conventionalASCII < hiToLowASCII ) + { + return FILE_TYPE_IS_TEXT; + } + + return FILE_TYPE_IS_BINARY; +} + +//---------------------------------------------------------------------------- +int vtkParticleReader::ProduceOutputFromTextFileDouble(vtkInformationVector *outputVector) +{ + // Get the size of the file. + this->File->seekg(0,ios::end); + if (this->File->fail()) + { + vtkErrorMacro("Could not seek to end of file."); + return 0; + } + + size_t fileLength = (unsigned long)this->File->tellg(); + size_t bytesRead = 0; + + vtkstd::string s; + + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetDataTypeToDouble(); + points->Reset(); + + vtkSmartPointer scalars = vtkSmartPointer::New(); + scalars->Reset(); + scalars->SetName("Scalar"); + + this->File->seekg(0,ios::beg); + + this->Alliquot = fileLength / quantum; + this->Count = 1; + ParseLine pl; + char buffer[256]; + while ( this->File->getline(buffer,256,'\n') ) + { + s = buffer; + if ( s.size() != 0 ) + { + bytesRead += s.size(); + this->DoProgressUpdate( bytesRead, fileLength ); + double val[4]; + val[0]=val[1]=val[2]=val[3]=0; + if ( pl(s,val) ) + { + points->InsertNextPoint(val[0], val[1], val[2]); + if ( this->HasScalar) + { + scalars->InsertNextValue(val[3]); + } + } + } + } + + vtkSmartPointer vertices = vtkSmartPointer::New(); + vertices->Reset(); + + this->NumberOfPoints = points->GetNumberOfPoints(); + for( vtkIdType j = 0; j < (vtkIdType)this->NumberOfPoints; ++j ) + { + vertices->InsertNextCell( 1 ); + vertices->InsertCellPoint( j ); + } + + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(vertices); + if ( this->HasScalar ) + output->GetPointData()->SetScalars(scalars); + + output->Modified(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkParticleReader::ProduceOutputFromTextFileFloat(vtkInformationVector *outputVector) +{ + // Get the size of the file. + this->File->seekg(0,ios::end); + if (this->File->fail()) + { + vtkErrorMacro("Could not seek to end of file."); + return 0; + } + + size_t fileLength = (unsigned long)this->File->tellg(); + size_t bytesRead = 0; + + vtkstd::string s; + + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetDataTypeToFloat(); + points->Reset(); + + vtkSmartPointer scalars = vtkSmartPointer::New(); + scalars->Reset(); + scalars->SetName("Scalar"); + + this->File->seekg(0,ios::beg); + + this->Alliquot = fileLength / quantum; + this->Count = 1; + ParseLine pl; + char buffer[256]; + while ( this->File->getline(buffer,256,'\n') ) + { + s = buffer; + if ( s.size() != 0 ) + { + bytesRead += s.size(); + this->DoProgressUpdate( bytesRead, fileLength ); + + float val[4]; + val[0]=val[1]=val[2]=val[3]=0; + if ( pl(s,val) ) + { + points->InsertNextPoint(val[0], val[1], val[2]); + if ( this->HasScalar) + { + scalars->InsertNextValue(val[3]); + } + } + } + } + + vtkSmartPointer vertices = vtkSmartPointer::New(); + vertices->Reset(); + + this->NumberOfPoints = points->GetNumberOfPoints(); + for( vtkIdType j = 0; j < (vtkIdType)this->NumberOfPoints; ++j ) + { + vertices->InsertNextCell( 1 ); + vertices->InsertCellPoint( j ); + } + + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(vertices); + if ( this->HasScalar ) + { + output->GetPointData()->SetScalars(scalars); + } + + output->Modified(); + + return 1; +} + + + +//---------------------------------------------------------------------------- +int vtkParticleReader::ProduceOutputFromBinaryFileDouble(vtkInformationVector *outputVector) +{ + + unsigned long fileLength, start, next, length, ptIdx, cellPtIdx; + unsigned long cellLength; + int piece, numPieces; + double *data, *ptr; + + if (!this->FileName) + { + vtkErrorMacro(<<"FileName must be specified."); + return 0; + } + + this->OpenFile(); + + // Get the size of the header from the size of the image + this->File->seekg(0,ios::end); + if (this->File->fail()) + { + vtkErrorMacro("Could not seek to end of file."); + return 0; + } + + fileLength = (unsigned long)this->File->tellg(); + if ( this->HasScalar ) + { + this->NumberOfPoints = fileLength / (4 * sizeof(double)); + } + else + { + this->NumberOfPoints = fileLength / (3 * sizeof(double)); + } + + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + if ((unsigned long)numPieces > this->NumberOfPoints) + { + numPieces = (int)(this->NumberOfPoints); + } + if (numPieces <= 0 || piece < 0 || piece >= numPieces) + { + return 0; + } + + start = piece * this->NumberOfPoints / numPieces; + next = (piece+1) * this->NumberOfPoints / numPieces; + + length = next - start; + + if ( this->HasScalar ) + { + data = new double[length * 4]; + } + else + { + data = new double[length * 3]; + } + + // Seek to the first point in the file. + if ( this->HasScalar ) + { + this->File->seekg(start*4*sizeof(double), ios::beg); + } + else + { + this->File->seekg(start*3*sizeof(double), ios::beg); + } + if (this->File->fail()) + { + vtkErrorMacro(<< "File operation failed: Seeking to " << start*4); + delete [] data; + return 0; + } + + // Read the data. + if ( this->HasScalar ) + { + this->File->read((char *)data, length*4*sizeof(double)); + if ( static_cast(this->File->gcount()) != + static_cast(length*4*sizeof(double)) + // On apple read to eof returns fail +#ifndef __APPLE_CC__ + || this->File->fail() +#endif // __APPLE_CC__ + ) + { + vtkErrorMacro("Could not read points: " << start + << " to " << next-1); + delete [] data; + return 0; + } + } + else + { + this->File->read((char *)data, length*3*sizeof(double)); + if ( static_cast(this->File->gcount()) != + static_cast(length*3*sizeof(double)) + // On apple read to eof returns fail +#ifndef __APPLE_CC__ + || this->File->fail() +#endif // __APPLE_CC__ + ) + { + vtkErrorMacro("Could not read points: " << start + << " to " << next-1); + delete [] data; + return 0; + } + } + + // Swap bytes if necessary. + if (this->GetSwapBytes()) + { + if ( this->HasScalar ) + { + vtkByteSwap::SwapVoidRange(data, length*4, sizeof(double)); + } + else + { + vtkByteSwap::SwapVoidRange(data, length*3, sizeof(double)); + } + } + + this->UpdateProgress(0.5); + + ptr = data; + + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetNumberOfPoints(length); + vtkSmartPointer array = vtkSmartPointer::New(); + array->SetName("Scalar"); + vtkSmartPointer verts = vtkSmartPointer::New(); + + // Each cell will have 1000 points. Leave a little extra space just in case. + // We break up the cell this way so that the render will check for aborts + // at a reasonable rate. + verts->Allocate((int)((float)length * 1.002)); + // Keep adding cells until we run out of points. + ptIdx = 0; + int cnt = 1; + double len = length; + while (length > 0) + { + if ( cnt % 10 == 0 ) + { + this->UpdateProgress(0.5+((cnt * 1000.0)/len)/2.0); + } + cnt++; + cellLength = 1000; + if (cellLength > length) + { + cellLength = length; + } + length = length - cellLength; + verts->InsertNextCell((int)cellLength); + for (cellPtIdx = 0; cellPtIdx < cellLength; ++cellPtIdx) + { + points->SetPoint(ptIdx, ptr[0], ptr[1], ptr[2]); + if ( this->HasScalar ) + { + array->InsertNextValue(ptr[3]); + ptr += 4; + } + else + { + ptr += 3; + } + verts->InsertCellPoint(ptIdx); + ++ptIdx; + } + } + delete [] data; + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(verts); + if ( this->HasScalar ) + { + output->GetPointData()->SetScalars(array); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkParticleReader::ProduceOutputFromBinaryFileFloat(vtkInformationVector *outputVector) +{ + + unsigned long fileLength, start, next, length, ptIdx, cellPtIdx; + unsigned long cellLength; + int piece, numPieces; + float *data, *ptr; + + if (!this->FileName) + { + vtkErrorMacro(<<"FileName must be specified."); + return 0; + } + + this->OpenFile(); + + // Get the size of the header from the size of the image + this->File->seekg(0,ios::end); + if (this->File->fail()) + { + vtkErrorMacro("Could not seek to end of file."); + return 0; + } + + fileLength = (unsigned long)this->File->tellg(); + if ( this->HasScalar ) + { + this->NumberOfPoints = fileLength / (4 * sizeof(float)); + } + else + { + this->NumberOfPoints = fileLength / (3 * sizeof(float)); + } + + + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + if ((unsigned long)numPieces > this->NumberOfPoints) + { + numPieces = (int)(this->NumberOfPoints); + } + if (numPieces <= 0 || piece < 0 || piece >= numPieces) + { + return 0; + } + + start = piece * this->NumberOfPoints / numPieces; + next = (piece+1) * this->NumberOfPoints / numPieces; + + length = next - start; + + if ( this->HasScalar ) + { + data = new float[length * 4]; + } + else + { + data = new float[length * 3]; + } + + + // Seek to the first point in the file. + if ( this->HasScalar ) + { + this->File->seekg(start*4*sizeof(float), ios::beg); + } + else + { + this->File->seekg(start*3*sizeof(float), ios::beg); + } + if (this->File->fail()) + { + vtkErrorMacro(<< "File operation failed: Seeking to " << start*4); + delete [] data; + return 0; + } + + // Read the data. + if ( this->HasScalar ) + { + this->File->read((char *)data, length*4*sizeof(float)); + if ( static_cast(this->File->gcount()) != + static_cast(length*4*sizeof(float)) + // On apple read to eof returns fail +#ifndef __APPLE_CC__ + || this->File->fail() +#endif // __APPLE_CC__ + ) + { + vtkErrorMacro("Could not read points: " << start + << " to " << next-1); + delete [] data; + return 0; + } + } + else + { + this->File->read((char *)data, length*3*sizeof(float)); + if ( static_cast(this->File->gcount()) != + static_cast(length*3*sizeof(float)) + // On apple read to eof returns fail +#ifndef __APPLE_CC__ + || this->File->fail() +#endif // __APPLE_CC__ + ) + { + vtkErrorMacro("Could not read points: " << start + << " to " << next-1); + delete [] data; + return 0; + } + } + + // Swap bytes if necessary. + if (this->GetSwapBytes()) + { + if ( this->HasScalar ) + { + vtkByteSwap::SwapVoidRange(data, length*4, sizeof(float)); + } + else + { + vtkByteSwap::SwapVoidRange(data, length*3, sizeof(float)); + } + } + + this->UpdateProgress(0.5); + + ptr = data; + + vtkSmartPointer points = vtkSmartPointer::New(); + points->SetNumberOfPoints(length); + vtkSmartPointer array = vtkSmartPointer::New(); + array->SetName("Scalar"); + vtkSmartPointer verts = vtkSmartPointer::New(); + + // Each cell will have 1000 points. Leave a little extra space just in case. + // We break up the cell this way so that the render will check for aborts + // at a reasonable rate. + verts->Allocate((int)((float)length * 1.002)); + // Keep adding cells until we run out of points. + ptIdx = 0; + int cnt = 1; + double len = length; + while (length > 0) + { + if ( cnt % 10 == 0 ) + { + this->UpdateProgress(0.5+((cnt * 1000.0)/len)/2.0); + } + cnt++; + cellLength = 1000; + if (cellLength > length) + { + cellLength = length; + } + length = length - cellLength; + verts->InsertNextCell((int)cellLength); + for (cellPtIdx = 0; cellPtIdx < cellLength; ++cellPtIdx) + { + points->SetPoint(ptIdx, ptr[0], ptr[1], ptr[2]); + if ( this->HasScalar ) + { + array->InsertNextValue(ptr[3]); + ptr += 4; + } + else + { + ptr += 3; + } + verts->InsertCellPoint(ptIdx); + ++ptIdx; + } + } + delete [] data; + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetPoints(points); + output->SetVerts(verts); + if ( this->HasScalar ) + { + output->GetPointData()->SetScalars(array); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkParticleReader::DoProgressUpdate( size_t & bytesRead, size_t & fileLength ) +{ + if ( bytesRead > this->Alliquot ) + { + this->UpdateProgress( bytesRead/(double)fileLength ); + this->Count++; + this->Alliquot = fileLength / quantum * this->Count; + } +} + +//---------------------------------------------------------------------------- +void vtkParticleReader::SetDataByteOrderToBigEndian() +{ +#ifndef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +//---------------------------------------------------------------------------- +void vtkParticleReader::SetDataByteOrderToLittleEndian() +{ +#ifdef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +//---------------------------------------------------------------------------- +void vtkParticleReader::SetDataByteOrder(int byteOrder) +{ + if ( byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN ) + { + this->SetDataByteOrderToBigEndian(); + } + else + { + this->SetDataByteOrderToLittleEndian(); + } +} + +//---------------------------------------------------------------------------- +int vtkParticleReader::GetDataByteOrder() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } +#else + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } +#endif +} + +//---------------------------------------------------------------------------- +const char *vtkParticleReader::GetDataByteOrderAsString() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +#else + if ( this->SwapBytes ) + { + return "BigEndian"; + } + else + { + return "LittleEndian"; + } +#endif +} + +//---------------------------------------------------------------------------- +void vtkParticleReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "FileName: " << + (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "Swap Bytes: " << (this->SwapBytes ? "On\n" : "Off\n"); + os << indent << "Has Scalar: " << (this->HasScalar ? "On\n" : "Off\n"); + switch ( this->FileType ) + { + case FILE_TYPE_IS_UNKNOWN: + os << indent << "File type is unknown (The class automatically determines the file type).\n"; + break; + case FILE_TYPE_IS_TEXT: + os << indent << "File type is text.\n"; + break; + case FILE_TYPE_IS_BINARY: + os << indent << "File type is binary.\n"; + break; + default: + os << indent << "File type should never have this value: " << this->FileType << "\n"; + break; + } + switch ( this->DataType ) + { + case VTK_FLOAT: + os << indent << "Data type is float.\n"; + break; + case VTK_DOUBLE: + os << indent << "Data type is double.\n"; + break; + default: + os << indent << "Data type should never have this value: " << this->DataType << "\n"; + break; + } + os << indent << "NumberOfPoints: " << this->NumberOfPoints << "\n"; + os << indent << "Alliquot: " << (unsigned int)this->Alliquot << "\n"; + os << indent << "Count: " << (unsigned int)this->Count << "\n"; + +} diff --git a/IO/vtkParticleReader.h b/IO/vtkParticleReader.h new file mode 100644 index 0000000..5304370 --- /dev/null +++ b/IO/vtkParticleReader.h @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParticleReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParticleReader - Read ASCII or binary particle +// data and (optionally) one scalar +// value associated with each particle. +// .SECTION Description +// vtkParticleReader reads either a binary or a text file of +// particles. Each particle can have associated with it an optional +// scalar value. So the format is: x, y, z, scalar +// (all floats or doubles). The text file can consist of a comma +// delimited set of values. In most cases vtkParticleReader can +// automatically determine whether the file is text or binary. +// The data can be either float or double. +// Progress updates are provided. +// With respect to binary files, random access into the file to read +// pieces is supported. +// + +#ifndef __vtkParticleReader_h +#define __vtkParticleReader_h + +#include "vtkPolyDataAlgorithm.h" + +#define VTK_FILE_BYTE_ORDER_BIG_ENDIAN 0 +#define VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN 1 + + +class VTK_IO_EXPORT vtkParticleReader : public vtkPolyDataAlgorithm +{ +public: + static vtkParticleReader *New(); + vtkTypeRevisionMacro(vtkParticleReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file name. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // These methods should be used instead of the SwapBytes methods. + // They indicate the byte ordering of the file you are trying + // to read in. These methods will then either swap or not swap + // the bytes depending on the byte ordering of the machine it is + // being run on. For example, reading in a BigEndian file on a + // BigEndian machine will result in no swapping. Trying to read + // the same file on a LittleEndian machine will result in swapping. + // As a quick note most UNIX machines are BigEndian while PC's + // and VAX tend to be LittleEndian. So if the file you are reading + // in was generated on a VAX or PC, SetDataByteOrderToLittleEndian + // otherwise SetDataByteOrderToBigEndian. Not used when reading + // text files. + void SetDataByteOrderToBigEndian(); + void SetDataByteOrderToLittleEndian(); + int GetDataByteOrder(); + void SetDataByteOrder(int); + const char *GetDataByteOrderAsString(); + + // Description: + // Set/Get the byte swapping to explicitly swap the bytes of a file. + // Not used when reading text files. + vtkSetMacro(SwapBytes,int); + int GetSwapBytes() {return this->SwapBytes;} + vtkBooleanMacro(SwapBytes,int); + + // Description: + // Default: 1. If 1 then each particle has a value associated with it. + vtkSetMacro(HasScalar,int); + vtkGetMacro(HasScalar,int); + vtkBooleanMacro(HasScalar,int); + + // Description: + // Get/Set the file type. The options are: + // - FILE_TYPE_IS_UNKNOWN (default) the class + // will attempt to determine the file type. + // If this fails then you should set the file type + // yourself. + // - FILE_TYPE_IS_TEXT the file type is text. + // - FILE_TYPE_IS_BINARY the file type is binary. + vtkSetClampMacro(FileType, int, FILE_TYPE_IS_UNKNOWN, FILE_TYPE_IS_BINARY); + vtkGetMacro(FileType, int); + void SetFileTypeToUnknown() {this->SetFileType(FILE_TYPE_IS_UNKNOWN);} + void SetFileTypeToText() {this->SetFileType(FILE_TYPE_IS_TEXT);} + void SetFileTypeToBinary() {this->SetFileType(FILE_TYPE_IS_BINARY);} + + // Description: + // Get/Set the data type. The options are: + // - VTK_FLOAT (default) single precision floating point. + // - VTK_DOUBLE double precision floating point. + vtkSetClampMacro(DataType, int, VTK_FLOAT, VTK_DOUBLE); + vtkGetMacro(DataType, int); + void SetDataTypeToFloat() {this->SetDataType(VTK_FLOAT);} + void SetDataTypeToDouble() {this->SetDataType(VTK_DOUBLE);} + + +protected: + vtkParticleReader(); + ~vtkParticleReader(); + + void OpenFile(); + + char *FileName; + ifstream *File; + + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // Description: + // The format that will be read if the file is a text file is: + // x, y, z, s (where s is some scalar value associated with the particle). + // Each line corresponding to a particle is terminated with a line feed. + // If y, z, or s is missing, zero is substituted for them. + // Comment lines in the file are handled as follows: + // 1) Any line containing "\/\/" "\#" "\%" anywhere in the line is discarded. + // 2) Lines containing "\/\*" are discarded until a "\*\/" is found. The line + // following the "\*\/" will be read. + int ProduceOutputFromTextFileDouble(vtkInformationVector *outputVector); + int ProduceOutputFromTextFileFloat(vtkInformationVector *outputVector); + + // Description: + // This reader assumes that the file is binary and consists of floating + // point values by default. + int ProduceOutputFromBinaryFileDouble(vtkInformationVector *outputVector); + int ProduceOutputFromBinaryFileFloat(vtkInformationVector *outputVector); + + // Description: + // Determine the type of file based on an analysis of its contents. + // Up to 5000 bytes of the file are read and classified. The classification + // of a file as either binary or text is based on the proportions of bytes in + // various classifications. The classification of the file is not infallible + // but should work correctly most of the time. If it fails, use SetFileTypeToText() + // or SetFileTypeToBinary() to set the file type. + // This algorithm probably only identifies ASCII text correctly and will not + // work for UTF-8 UCS-2 (or UTF-16) or UCS-4 or EBCIDIC. + int DetermineFileType(); + + // Description: + // Update of the progress. + void DoProgressUpdate( size_t & bytesRead, size_t & fileLength ); + + //BTX + // Description: + // Enumerate the supported file types. + //

+  // - FILE_TYPE_IS_UNKNOWN, (default) the class will attempt to determine the file type.
+  // - FILE_TYPE_IS_TEXT, the file type is text.
+  // - FILE_TYPE_IS_BINARY, the file type is binary.
+  // 
+ enum FILE_TYPE { FILE_TYPE_IS_UNKNOWN = 0, + FILE_TYPE_IS_TEXT, FILE_TYPE_IS_BINARY }; + //ETX + + int HasScalar; + // Description: + // Used to decide which reader should be used. + int FileType; + // Description: + // Used to specify the data type. + int DataType; + + // Description: + // Set an alliquot of bytes. + size_t Alliquot; + // Description: + // Count of the number of alliquots processed. + size_t Count; + + int SwapBytes; + size_t NumberOfPoints; + +private: + vtkParticleReader(const vtkParticleReader&); // Not implemented. + void operator=(const vtkParticleReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkPolyDataReader.cxx b/IO/vtkPolyDataReader.cxx new file mode 100644 index 0000000..8d01c1f --- /dev/null +++ b/IO/vtkPolyDataReader.cxx @@ -0,0 +1,368 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataReader.h" + +#include "vtkCellArray.h" +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPolyDataReader, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkPolyDataReader); + +vtkPolyDataReader::vtkPolyDataReader() +{ + vtkPolyData *output = vtkPolyData::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); + this->ExecutePiece = this->ExecuteNumberOfPieces = 0; + this->ExecuteGhostLevel = 0; +} + +vtkPolyDataReader::~vtkPolyDataReader() +{ +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkPolyDataReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkPolyDataReader::GetOutput(int idx) +{ + return vtkPolyData::SafeDownCast(this->GetOutputDataObject(idx)); +} + +//---------------------------------------------------------------------------- +void vtkPolyDataReader::SetOutput(vtkPolyData *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + + +//---------------------------------------------------------------------------- +int vtkPolyDataReader::RequestUpdateExtent( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces, ghostLevel; + + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + // make sure piece is valid + if (piece < 0 || piece >= numPieces) + { + return 1; + } + + if (ghostLevel < 0) + { + return 1; + } + + // Save the piece so execute can use this information. + this->ExecutePiece = piece; + this->ExecuteNumberOfPieces = numPieces; + + this->ExecuteGhostLevel = ghostLevel; + + return 1; +} + +int vtkPolyDataReader::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int numPts=0; + char line[256]; + int npts, size, ncells, i; + int done=0; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int *tempArray; + vtkIdType *idArray; + + vtkDebugMacro(<<"Reading vtk polygonal data..."); + + if ( !(this->OpenVTKFile()) || !this->ReadHeader()) + { + return 1; + } +// +// Read polygonal data specific stuff +// + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { +// +// Make sure we're reading right type of geometry +// + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( strncmp(this->LowerCase(line),"polydata",8) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + return 1; + } +// +// Might find points, vertices, lines, polygons, or triangle strips +// + while (!done) + { + if (!this->ReadString(line)) + { + break; + } + + if (! strncmp(this->LowerCase(line), "field", 5)) + { + vtkFieldData* fd = this->ReadFieldData(); + output->SetFieldData(fd); + fd->Delete(); // ? + } + else if ( ! strncmp(line, "points",6) ) + { + if (!this->Read(&numPts)) + { + vtkErrorMacro(<<"Cannot read number of points!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadPoints(output, numPts); + } + + else if ( ! strncmp(line,"vertices",8) ) + { + vtkCellArray *verts = vtkCellArray::New(); + if (!(this->Read(&ncells) && this->Read(&size))) + { + vtkErrorMacro(<<"Cannot read vertices!"); + this->CloseVTKFile (); + return 1; + } + + tempArray = new int[size]; + idArray = verts->WritePointer(ncells, size); + this->ReadCells(size, tempArray); +// this->ReadCells(size, verts->WritePointer(ncells,size)); + for (i = 0; i < size; i++) + { + idArray[i] = tempArray[i]; + } + output->SetVerts(verts); + verts->Delete(); + delete [] tempArray; + vtkDebugMacro(<<"Read " << ncells << " vertices"); + } + + else if ( ! strncmp(line,"lines",5) ) + { + vtkCellArray *lines = vtkCellArray::New(); + if (!(this->Read(&ncells) && this->Read(&size))) + { + vtkErrorMacro(<<"Cannot read lines!"); + this->CloseVTKFile (); + return 1; + } + tempArray = new int[size]; + idArray = lines->WritePointer(ncells, size); + this->ReadCells(size, tempArray); +// this->ReadCells(size, lines->WritePointer(ncells,size)); + for (i = 0; i < size; i++) + { + idArray[i] = tempArray[i]; + } + + output->SetLines(lines); + lines->Delete(); + delete [] tempArray; + vtkDebugMacro(<<"Read " << ncells << " lines"); + } + + else if ( ! strncmp(line,"polygons",8) ) + { + vtkCellArray *polys = vtkCellArray::New(); + if (!(this->Read(&ncells) && this->Read(&size))) + { + vtkErrorMacro(<<"Cannot read polygons!"); + this->CloseVTKFile (); + return 1; + } + + tempArray = new int[size]; + idArray = polys->WritePointer(ncells, size); + this->ReadCells(size, tempArray); +// this->ReadCells(size, polys->WritePointer(ncells,size)); + for (i = 0; i < size; i++) + { + idArray[i] = tempArray[i]; + } + output->SetPolys(polys); + polys->Delete(); + delete [] tempArray; + vtkDebugMacro(<<"Read " << ncells << " polygons"); + } + + else if ( ! strncmp(line,"triangle_strips",15) ) + { + vtkCellArray *tris = vtkCellArray::New(); + if (!(this->Read(&ncells) && this->Read(&size))) + { + vtkErrorMacro(<<"Cannot read triangle strips!"); + this->CloseVTKFile (); + return 1; + } + + tempArray = new int[size]; + idArray = tris->WritePointer(ncells, size); + this->ReadCells(size, tempArray); +// this->ReadCells(size, tris->WritePointer(ncells,size)); + for (i = 0; i < size; i++) + { + idArray[i] = tempArray[i]; + } + output->SetStrips(tris); + tris->Delete(); + delete [] tempArray; + vtkDebugMacro(<<"Read " << ncells << " triangle strips"); + } + + else if ( ! strncmp(line, "cell_data", 9) ) + { + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + return 1; + } + + if ( ncells != output->GetNumberOfCells() ) + { + vtkErrorMacro(<<"Number of cells don't match number data values!"); + return 1; + } + + this->ReadCellData(output, ncells); + break; //out of this loop + } + + else if ( ! strncmp(line, "point_data", 10) ) + { + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + + if ( npts != numPts ) + { + vtkErrorMacro(<<"Number of points don't match number data values!"); + return 1; + } + + this->ReadPointData(output, npts); + break; //out of this loop + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + this->CloseVTKFile (); + return 1; + } + } + + if ( ! output->GetPoints() ) vtkWarningMacro(<<"No points read!"); + if ( !(output->GetVerts() || output->GetLines() || + output->GetPolys() || output->GetStrips()) ) + vtkWarningMacro(<<"No topology read!"); + } + + else if ( !strncmp(line, "cell_data", 9) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadCellData(output, ncells); + } + + else if ( !strncmp(line, "point_data", 10) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&numPts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadPointData(output, numPts); + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + } + this->CloseVTKFile (); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataReader::FillOutputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData"); + return 1; +} + +void vtkPolyDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkPolyDataReader.h b/IO/vtkPolyDataReader.h new file mode 100644 index 0000000..3fa82f3 --- /dev/null +++ b/IO/vtkPolyDataReader.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataReader - read vtk polygonal data file +// .SECTION Description +// vtkPolyDataReader is a source object that reads ASCII or binary +// polygonal data files in vtk format (see text for format details). +// The output of this reader is a single vtkPolyData data object. +// The superclass of this class, vtkDataReader, provides many methods for +// controlling the reading of the data file, see vtkDataReader for more +// information. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// .SECTION See Also +// vtkPolyData vtkDataReader + +#ifndef __vtkPolyDataReader_h +#define __vtkPolyDataReader_h + +#include "vtkDataReader.h" + +class vtkPolyData; + +class VTK_IO_EXPORT vtkPolyDataReader : public vtkDataReader +{ +public: + static vtkPolyDataReader *New(); + vtkTypeRevisionMacro(vtkPolyDataReader,vtkDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this reader. + vtkPolyData *GetOutput(); + vtkPolyData *GetOutput(int idx); + void SetOutput(vtkPolyData *output); + +protected: + vtkPolyDataReader(); + ~vtkPolyDataReader(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + // Update extent of PolyData is specified in pieces. + // Since all DataObjects should be able to set UpdateExent as pieces, + // just copy output->UpdateExtent all Inputs. + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + virtual int FillOutputPortInformation(int, vtkInformation*); + + // Used by streaming: The extent of the output being processed + // by the execute method. Set in the ComputeInputUpdateExtents method. + int ExecutePiece; + int ExecuteNumberOfPieces; + int ExecuteGhostLevel; +private: + vtkPolyDataReader(const vtkPolyDataReader&); // Not implemented. + void operator=(const vtkPolyDataReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkPolyDataWriter.cxx b/IO/vtkPolyDataWriter.cxx new file mode 100644 index 0000000..a553274 --- /dev/null +++ b/IO/vtkPolyDataWriter.cxx @@ -0,0 +1,148 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataWriter.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +vtkCxxRevisionMacro(vtkPolyDataWriter, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkPolyDataWriter); + +void vtkPolyDataWriter::WriteData() +{ + ostream *fp; + vtkPolyData *input = this->GetInput(); + + vtkDebugMacro(<<"Writing vtk polygonal data..."); + + if ( !(fp=this->OpenVTKFile()) || !this->WriteHeader(fp) ) + { + if (fp) + { + if(this->FileName) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + } + else + { + this->CloseVTKFile(fp); + vtkErrorMacro("Could not read memory header. "); + } + } + return; + } + // + // Write polygonal data specific stuff + // + *fp << "DATASET POLYDATA\n"; + + // + // Write data owned by the dataset + int errorOccured = 0; + if (!this->WriteDataSetData(fp, input)) + { + errorOccured = 1; + } + if (!errorOccured && !this->WritePoints(fp, input->GetPoints())) + { + errorOccured = 1; + } + + if (!errorOccured && input->GetVerts()) + { + if (!this->WriteCells(fp, input->GetVerts(),"VERTICES")) + { + errorOccured = 1; + } + } + if (!errorOccured && input->GetLines()) + { + if (!this->WriteCells(fp, input->GetLines(),"LINES")) + { + errorOccured = 1; + } + } + if (!errorOccured && input->GetPolys()) + { + if (!this->WriteCells(fp, input->GetPolys(),"POLYGONS")) + { + errorOccured = 1; + } + } + if (!errorOccured && input->GetStrips()) + { + if (!this->WriteCells(fp, input->GetStrips(),"TRIANGLE_STRIPS")) + { + errorOccured = 1; + } + } + + if (!errorOccured && !this->WriteCellData(fp, input)) + { + errorOccured = 1; + } + if (!errorOccured && !this->WritePointData(fp, input)) + { + errorOccured = 1; + } + + if(errorOccured) + { + if(this->FileName) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + } + else + { + vtkErrorMacro("Error writting data set to memory"); + this->CloseVTKFile(fp); + } + return; + } + this->CloseVTKFile(fp); +} + +int vtkPolyDataWriter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} + +vtkPolyData* vtkPolyDataWriter::GetInput() +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput()); +} + +vtkPolyData* vtkPolyDataWriter::GetInput(int port) +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput(port)); +} + +void vtkPolyDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkPolyDataWriter.h b/IO/vtkPolyDataWriter.h new file mode 100644 index 0000000..a4a7ce4 --- /dev/null +++ b/IO/vtkPolyDataWriter.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataWriter - write vtk polygonal data +// .SECTION Description +// vtkPolyDataWriter is a source object that writes ASCII or binary +// polygonal data files in vtk format. See text for format details. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. + +#ifndef __vtkPolyDataWriter_h +#define __vtkPolyDataWriter_h + +#include "vtkDataWriter.h" + +class vtkPolyData; + +class VTK_IO_EXPORT vtkPolyDataWriter : public vtkDataWriter +{ +public: + static vtkPolyDataWriter *New(); + vtkTypeRevisionMacro(vtkPolyDataWriter,vtkDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the input to this writer. + vtkPolyData* GetInput(); + vtkPolyData* GetInput(int port); + +protected: + vtkPolyDataWriter() {}; + ~vtkPolyDataWriter() {}; + + void WriteData(); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkPolyDataWriter(const vtkPolyDataWriter&); // Not implemented. + void operator=(const vtkPolyDataWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkPostScriptWriter.cxx b/IO/vtkPostScriptWriter.cxx new file mode 100644 index 0000000..6e1e527 --- /dev/null +++ b/IO/vtkPostScriptWriter.cxx @@ -0,0 +1,208 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPostScriptWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPostScriptWriter.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkPostScriptWriter, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkPostScriptWriter); + +#define VTK_MARGIN 0.95 + +void vtkPostScriptWriter::WriteFileTrailer(ofstream *file, + vtkImageData *vtkNotUsed(cache)) +{ + *file << "\ngrestore\nshowpage\n%%%%Trailer\n"; +} + +void vtkPostScriptWriter::WriteFileHeader(ofstream *file, + vtkImageData *cache) +{ + int min1, max1, min2, max2, min3, max3; + int bpp; + int cols, rows, scols, srows; + float scale = 1; + int pagewid = (int) (8.5*72); + int pagehgt = 11*72; + + // Find the length of the rows to write. + cache->GetWholeExtent(min1, max1, min2, max2, min3, max3); + bpp = cache->GetNumberOfScalarComponents(); + + cols = max1 - min1 + 1; + rows = max2 - min2 + 1; + + float pixfac = 0.96; /* 1, approx. */ + scols = (int)(cols * pixfac); + srows = (int)(rows * pixfac); + if ( scols > pagewid * VTK_MARGIN || srows > pagehgt * VTK_MARGIN ) + { + if ( scols > pagewid * VTK_MARGIN ) + { + scale = scale*(pagewid * VTK_MARGIN / scols); + scols = (int)(scale * cols * pixfac); + srows = (int)(scale * rows * pixfac); + } + if ( srows > pagehgt * VTK_MARGIN ) + { + scale = scale * (pagehgt * VTK_MARGIN / srows); + scols = (int)(scale * cols * pixfac); + srows = (int)(scale * rows * pixfac); + } + } + float llx = ( pagewid - scols ) / 2; + float lly = ( pagehgt - srows ) / 2; + + // spit out the PostScript header + *file << "%!PS-Adobe-2.0 EPSF-2.0\n"; + *file << "%%Creator: Visualization Toolkit\n"; + *file << "%%Title: " << this->InternalFileName << endl; + *file << "%%Pages: 1\n"; + *file << "%%BoundingBox: " << (int) llx << " " << (int) lly + << " " << (int) ( llx + scols + 0.5 ) << " " << + (int) ( lly + srows + 0.5 ) << endl; + *file << "%%EndComments\n"; + *file << "/readstring {\n"; + *file << " currentfile exch readhexstring pop\n"; + *file << "} bind def\n"; + + if ( bpp == 3) + { + *file << "/rpicstr " << cols << " string def\n"; + *file << "/gpicstr " << cols << " string def\n"; + *file << "/bpicstr " << cols << " string def\n"; + } + else if (bpp == 1) + { + *file << "/picstr " << cols << " string def\n"; + } + else + { + vtkWarningMacro( " vtkPostScriptWriter only supports 1 and 3 component images"); + } + + *file << "%%EndProlog\n"; + *file << "%%Page: 1 1\n"; + *file << "gsave\n"; + *file << llx << " " << lly << " translate\n"; + *file << scols << " " << srows << " scale\n"; + *file << cols << " " << rows << " 8\n"; + *file << "[ " << cols << " 0 0 " << -rows << " 0 " << rows << " ]\n"; + if (bpp == 3) + { + *file << "{ rpicstr readstring }\n"; + *file << "{ gpicstr readstring }\n"; + *file << "{ bpicstr readstring }\n"; + *file << "true 3\n"; + *file << "colorimage\n"; + } + else + { + *file << "{ picstr readstring }\n"; + *file << "image\n"; + } +} + + +void vtkPostScriptWriter::WriteFile(ofstream *file, vtkImageData *data, + int extent[6]) +{ + int idxC, idx0, idx1, idx2; + unsigned char *ptr; + unsigned long count = 0; + unsigned long target; + float progress = this->Progress; + float area; + int *wExtent; + static int itemsperline = 0; + char* hexits = (char *) "0123456789abcdef"; + + // Make sure we actually have data. + if ( !data->GetPointData()->GetScalars()) + { + vtkErrorMacro(<< "Could not get data from input."); + return; + } + + // take into consideration the scalar type + switch (data->GetScalarType()) + { + case VTK_UNSIGNED_CHAR: + break; + default: + vtkErrorMacro("PostScriptWriter only accepts unsigned char scalars!"); + return; + } + + wExtent = this->GetInput()->GetWholeExtent(); + area = ((extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)* + (extent[1] - extent[0] + 1)) / + ((wExtent[5] -wExtent[4] + 1)*(wExtent[3] -wExtent[2] + 1)* + (wExtent[1] -wExtent[0] + 1)); + + + int numComponents = data->GetNumberOfScalarComponents(); + // ignore alpha + int maxComponent = numComponents; + if (numComponents == 2) + { + maxComponent = 1; + } + if (numComponents == 4) + { + maxComponent = 3; + } + target = (unsigned long)((extent[5]-extent[4]+1)* + (extent[3]-extent[2]+1)/(50.0*area)); + target++; + + for (idx2 = extent[4]; idx2 <= extent[5]; ++idx2) + { + for (idx1 = extent[3]; idx1 >= extent[2]; idx1--) + { + if (!(count%target)) + { + this->UpdateProgress(progress + count/(50.0*target)); + } + count++; + // write out components one at a time because + for (idxC = 0; idxC < maxComponent; idxC++) + { + ptr = (unsigned char*)data->GetScalarPointer(extent[0],idx1, idx2); + ptr += idxC; + for ( idx0 = extent[0]; idx0 <= extent[1]; idx0++ ) + { + if ( itemsperline == 30 ) + { + *file << endl; + itemsperline = 0; + } + *file << hexits[*ptr >> 4] << hexits[*ptr & 15]; + ++itemsperline; + ptr += numComponents; + } + } + } + } + +} + +//---------------------------------------------------------------------------- +void vtkPostScriptWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkPostScriptWriter.h b/IO/vtkPostScriptWriter.h new file mode 100644 index 0000000..407f9b9 --- /dev/null +++ b/IO/vtkPostScriptWriter.h @@ -0,0 +1,49 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPostScriptWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPostScriptWriter - Writes an image as a PostScript file. +// .SECTION Description +// vtkPostScriptWriter writes an image as a PostScript file using some +// reasonable scalings and centered on the page which is assumed to be +// about 8.5 by 11 inches. This is based loosely off of the code from +// pnmtops.c. Right now there aren't any real options. + + +#ifndef __vtkPostScriptWriter_h +#define __vtkPostScriptWriter_h + +#include "vtkImageWriter.h" + +class VTK_IO_EXPORT vtkPostScriptWriter : public vtkImageWriter +{ +public: + static vtkPostScriptWriter *New(); + vtkTypeRevisionMacro(vtkPostScriptWriter,vtkImageWriter); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkPostScriptWriter() {}; + ~vtkPostScriptWriter() {}; + + virtual void WriteFile(ofstream *file, vtkImageData *data, int extent[6]); + virtual void WriteFileHeader(ofstream *, vtkImageData *); + virtual void WriteFileTrailer(ofstream *, vtkImageData *); +private: + vtkPostScriptWriter(const vtkPostScriptWriter&); // Not implemented. + void operator=(const vtkPostScriptWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkRectilinearGridReader.cxx b/IO/vtkRectilinearGridReader.cxx new file mode 100644 index 0000000..3fbb2c0 --- /dev/null +++ b/IO/vtkRectilinearGridReader.cxx @@ -0,0 +1,382 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridReader.h" + +#include "vtkDataArray.h" +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkRectilinearGridReader, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkRectilinearGridReader); + +//---------------------------------------------------------------------------- +vtkRectilinearGridReader::vtkRectilinearGridReader() +{ + vtkRectilinearGrid *output = vtkRectilinearGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGridReader::~vtkRectilinearGridReader() +{ +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkRectilinearGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkRectilinearGridReader::GetOutput(int idx) +{ + return vtkRectilinearGrid::SafeDownCast(this->GetOutputDataObject(idx)); +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridReader::SetOutput(vtkRectilinearGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridReader::RequestInformation( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + return this->ReadMetaData(outInfo); +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridReader::ReadMetaData(vtkInformation *outInfo) +{ + char line[256]; + + vtkDebugMacro(<<"Reading vtk rectilinear grid file info..."); + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 1; + } + + // Read rectilinear grid specific stuff + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // Make sure we're reading right type of geometry + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( strncmp(this->LowerCase(line),"rectilinear_grid",16) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + return 1; + } + + // Read keyword and number of points + // + while (1) + { + if (!this->ReadString(line)) + { + break; + } + + if ( ! strncmp(this->LowerCase(line),"dimensions",10) ) + { + int dim[3]; + if (!(this->Read(dim) && + this->Read(dim+1) && + this->Read(dim+2))) + { + vtkErrorMacro(<<"Error reading dimensions!"); + this->CloseVTKFile (); + return 1; + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); + // We got what we want. Now return. + this->CloseVTKFile (); + return 1; + } + } + } + + this->CloseVTKFile (); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridReader::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int numPts=0, npts, ncoords, numCells=0, ncells; + char line[256]; + int dimsRead=0; + int done=0; + vtkRectilinearGrid *output = vtkRectilinearGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Reading vtk rectilinear grid file..."); + if ( this->Debug ) + { + this->DebugOn(); + } + else + { + this->DebugOff(); + } + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 1; + } + + // Read rectilinear grid specific stuff + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // Make sure we're reading right type of geometry + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( strncmp(this->LowerCase(line),"rectilinear_grid",16) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + return 1; + } + + // Read keyword and number of points + // + while (!done) + { + if (!this->ReadString(line)) + { + break; + } + + if (! strncmp(this->LowerCase(line), "field", 5)) + { + vtkFieldData* fd = this->ReadFieldData(); + output->SetFieldData(fd); + fd->Delete(); // ? + } + else if ( ! strncmp(line,"dimensions",10) ) + { + int dim[3]; + if (!(this->Read(dim) && + this->Read(dim+1) && + this->Read(dim+2))) + { + vtkErrorMacro(<<"Error reading dimensions!"); + this->CloseVTKFile (); + return 1; + } + + numPts = dim[0] * dim[1] * dim[2]; + output->SetDimensions(dim); + numCells = output->GetNumberOfCells(); + dimsRead = 1; + } + + else if ( ! strncmp(line,"x_coordinate",12) ) + { + if (!this->Read(&ncoords)) + { + vtkErrorMacro(<<"Error reading x coordinates!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadCoordinates(output, 0, ncoords); + } + + else if ( ! strncmp(line,"y_coordinate",12) ) + { + if (!this->Read(&ncoords)) + { + vtkErrorMacro(<<"Error reading y coordinates!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadCoordinates(output, 1, ncoords); + } + + else if ( ! strncmp(line,"z_coordinate",12) ) + { + if (!this->Read(&ncoords)) + { + vtkErrorMacro(<<"Error reading z coordinates!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadCoordinates(output, 2, ncoords); + } + + else if ( ! strncmp(line, "cell_data", 9) ) + { + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + return 1; + } + + if ( ncells != numCells ) + { + vtkErrorMacro(<<"Number of cells don't match!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadCellData(output, ncells); + break; //out of this loop + } + + else if ( ! strncmp(line, "point_data", 10) ) + { + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + + if ( npts != numPts ) + { + vtkErrorMacro(<<"Number of points don't match!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadPointData(output, npts); + break; //out of this loop + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + this->CloseVTKFile (); + return 1; + } + } + + if ( !dimsRead ) vtkWarningMacro(<<"No dimensions read."); + if ( !output->GetXCoordinates() || + output->GetXCoordinates()->GetNumberOfTuples() < 1 ) + { + vtkWarningMacro(<<"No x coordinatess read."); + } + if ( !output->GetYCoordinates() || + output->GetYCoordinates()->GetNumberOfTuples() < 1 ) + { + vtkWarningMacro(<<"No y coordinates read."); + } + if ( !output->GetZCoordinates() || + output->GetZCoordinates()->GetNumberOfTuples() < 1 ) + { + vtkWarningMacro(<<"No z coordinates read."); + } + } + + else if ( !strncmp(line, "cell_data", 9) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + return 1; + } + this->ReadCellData(output, ncells); + } + + else if ( !strncmp(line, "point_data", 10) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + this->ReadPointData(output, npts); + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + } + + this->CloseVTKFile (); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkRectilinearGridReader::FillOutputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkRectilinearGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkRectilinearGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkRectilinearGridReader.h b/IO/vtkRectilinearGridReader.h new file mode 100644 index 0000000..dd9d98b --- /dev/null +++ b/IO/vtkRectilinearGridReader.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridReader - read vtk rectilinear grid data file +// .SECTION Description +// vtkRectilinearGridReader is a source object that reads ASCII or binary +// rectilinear grid data files in vtk format (see text for format details). +// The output of this reader is a single vtkRectilinearGrid data object. +// The superclass of this class, vtkDataReader, provides many methods for +// controlling the reading of the data file, see vtkDataReader for more +// information. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// .SECTION See Also +// vtkRectilinearGrid vtkDataReader + +#ifndef __vtkRectilinearGridReader_h +#define __vtkRectilinearGridReader_h + +#include "vtkDataReader.h" + +class vtkRectilinearGrid; + +class VTK_IO_EXPORT vtkRectilinearGridReader : public vtkDataReader +{ +public: + static vtkRectilinearGridReader *New(); + vtkTypeRevisionMacro(vtkRectilinearGridReader,vtkDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get and set the output of this reader. + vtkRectilinearGrid *GetOutput(); + vtkRectilinearGrid *GetOutput(int idx); + void SetOutput(vtkRectilinearGrid *output); + + // Description: + // Read the meta information from the file. This needs to be public to it + // can be accessed by vtkDataSetReader. + virtual int ReadMetaData(vtkInformation *outInfo); + +protected: + vtkRectilinearGridReader(); + ~vtkRectilinearGridReader(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkRectilinearGridReader(const vtkRectilinearGridReader&); // Not implemented. + void operator=(const vtkRectilinearGridReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkRectilinearGridWriter.cxx b/IO/vtkRectilinearGridWriter.cxx new file mode 100644 index 0000000..47990e9 --- /dev/null +++ b/IO/vtkRectilinearGridWriter.cxx @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridWriter.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +vtkCxxRevisionMacro(vtkRectilinearGridWriter, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkRectilinearGridWriter); + +void vtkRectilinearGridWriter::WriteData() +{ + ostream *fp; + vtkRectilinearGrid *input = vtkRectilinearGrid::SafeDownCast( + this->GetInput()); + int dim[3]; + + vtkDebugMacro(<<"Writing vtk rectilinear grid..."); + + if ( !(fp=this->OpenVTKFile()) || !this->WriteHeader(fp) ) + { + if (fp) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + } + return; + } + // + // Write rectilinear grid specific stuff + // + *fp << "DATASET RECTILINEAR_GRID\n"; + + // Write data owned by the dataset + if (!this->WriteDataSetData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + input->GetDimensions(dim); + *fp << "DIMENSIONS " << dim[0] << " " << dim[1] << " " << dim[2] << "\n"; + + if (!this->WriteCoordinates(fp, input->GetXCoordinates(), 0)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + if (!this->WriteCoordinates(fp, input->GetYCoordinates(), 1)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + if (!this->WriteCoordinates(fp, input->GetZCoordinates(), 2)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + if (!this->WriteCellData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + if (!this->WritePointData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + this->CloseVTKFile(fp); +} + +int vtkRectilinearGridWriter::FillInputPortInformation(int, + vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} + +vtkRectilinearGrid* vtkRectilinearGridWriter::GetInput() +{ + return vtkRectilinearGrid::SafeDownCast(this->Superclass::GetInput()); +} + +vtkRectilinearGrid* vtkRectilinearGridWriter::GetInput(int port) +{ + return vtkRectilinearGrid::SafeDownCast(this->Superclass::GetInput(port)); +} + +void vtkRectilinearGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkRectilinearGridWriter.h b/IO/vtkRectilinearGridWriter.h new file mode 100644 index 0000000..962830c --- /dev/null +++ b/IO/vtkRectilinearGridWriter.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridWriter - write vtk rectilinear grid data file +// .SECTION Description +// vtkRectilinearGridWriter is a source object that writes ASCII or binary +// rectilinear grid data files in vtk format. See text for format details. + +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. + +#ifndef __vtkRectilinearGridWriter_h +#define __vtkRectilinearGridWriter_h + +#include "vtkDataWriter.h" + +class vtkRectilinearGrid; + +class VTK_IO_EXPORT vtkRectilinearGridWriter : public vtkDataWriter +{ +public: + static vtkRectilinearGridWriter *New(); + vtkTypeRevisionMacro(vtkRectilinearGridWriter,vtkDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the input to this writer. + vtkRectilinearGrid* GetInput(); + vtkRectilinearGrid* GetInput(int port); + +protected: + vtkRectilinearGridWriter() {}; + ~vtkRectilinearGridWriter() {}; + + void WriteData(); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkRectilinearGridWriter(const vtkRectilinearGridWriter&); // Not implemented. + void operator=(const vtkRectilinearGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkSLCReader.cxx b/IO/vtkSLCReader.cxx new file mode 100644 index 0000000..f798933 --- /dev/null +++ b/IO/vtkSLCReader.cxx @@ -0,0 +1,328 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSLCReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSLCReader.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkSLCReader, "$Revision: 1.53 $"); +vtkStandardNewMacro(vtkSLCReader); + +// Constructor for a vtkSLCReader. +vtkSLCReader::vtkSLCReader() +{ + this->FileName = NULL; + this->Error = 0; +} + +vtkSLCReader::~vtkSLCReader() +{ +} + +// Decodes an array of eight bit run-length encoded data. +unsigned char* vtkSLCReader::Decode8BitData( unsigned char *in_ptr, + int size ) +{ + unsigned char *curr_ptr; + unsigned char *decode_ptr; + unsigned char *return_ptr; + unsigned char current_value; + unsigned char remaining; + int done=0; + + curr_ptr = in_ptr; + + decode_ptr = return_ptr = new unsigned char[size]; + + while( !done ) + { + current_value = *(curr_ptr++); + + if( !(remaining = (current_value & 0x7f)) ) + { + break; + } + + if( current_value & 0x80 ) + { + while( remaining-- ) + { + *(decode_ptr++) = *(curr_ptr++); + } + } + else + { + current_value = *(curr_ptr++); + while ( remaining-- ) + { + *(decode_ptr++) = current_value; + } + } + + } + + return return_ptr; +} + + +// This will be needed when we make this an imaging filter. +int vtkSLCReader::RequestInformation ( + vtkInformation * request, + vtkInformationVector** inputVector, + vtkInformationVector * outputVector) +{ + FILE *fp; + int temp; + double f[3]; + int size[3]; + int magic_num; + + this->Error = 1; + + if (!this->FileName) + { + vtkErrorMacro(<<"A FileName must be specified."); + return 0; + } + + // Initialize + if ((fp = fopen(this->FileName, "rb")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return 0; + } + this->FileDimensionality = 3; + fscanf( fp, "%d", &magic_num ); + if( magic_num != 11111 ) + { + vtkErrorMacro(<< "SLC magic number is not correct"); + return 1; + } + + f[0] = f[1] = f[2] = 0.0; + this->SetDataOrigin(f); + + fscanf( fp, "%d", size ); + fscanf( fp, "%d", size+1 ); + fscanf( fp, "%d", size+2 ); + this->SetDataExtent(0, size[0]-1, 0, size[1]-1, 0, size[2]-1); + + // Skip Over bits_per_voxel Field */ + fscanf( fp, "%d", &temp ); + + fscanf( fp, "%lf", f ); + fscanf( fp, "%lf", f+1 ); + fscanf( fp, "%lf", f+2 ); + this->SetDataSpacing(f); + + // Skip Over unit_type, data_origin, and data_modification + fscanf( fp, "%d", &temp ); + fscanf( fp, "%d", &temp ); + fscanf( fp, "%d", &temp ); + + this->SetDataScalarType(VTK_UNSIGNED_CHAR); + this->SetNumberOfScalarComponents(1); + + fclose( fp ); + return this->Superclass::RequestInformation(request, inputVector, outputVector); +} + +// Reads an SLC file and creates a vtkStructuredPoints dataset. +void vtkSLCReader::ExecuteData(vtkDataObject* ) +{ + vtkImageData *output = this->GetOutput(); + + output->SetExtent(output->GetWholeExtent()); + output->AllocateScalars(); + + if (!output->GetPointData()->GetScalars()) + { + return; + } + output->GetPointData()->GetScalars()->SetName("SLCImage"); + + FILE *fp; + + int temp; + int data_compression; + int plane_size; + int volume_size; + double f[3]; + int size[3]; + int magic_num; + int z_counter; + int icon_width, icon_height; + int compressed_size; + + unsigned char *icon_ptr; + unsigned char *compressed_ptr; + unsigned char *scan_ptr = NULL; + + this->Error = 1; + + if (!this->FileName) + { + vtkErrorMacro(<<"A FileName must be specified."); + return; + } + + // Initialize + if ((fp = fopen(this->FileName, "rb")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return; + } + + fscanf( fp, "%d", &magic_num ); + if( magic_num != 11111 ) + { + vtkErrorMacro(<< "SLC magic number is not correct"); + return; + } + + f[0] = f[1] = f[2] = 0.0; + output->SetOrigin(f); + + fscanf( fp, "%d", size ); + fscanf( fp, "%d", size+1 ); + fscanf( fp, "%d", size+2 ); + output->SetDimensions(size); + + // Skip Over bits_per_voxel Field */ + fscanf( fp, "%d", &temp ); + + fscanf( fp, "%lf", f ); + fscanf( fp, "%lf", f+1 ); + fscanf( fp, "%lf", f+2 ); + output->SetSpacing(f); + + // Skip Over unit_type, data_origin, and data_modification + fscanf( fp, "%d", &temp ); + fscanf( fp, "%d", &temp ); + fscanf( fp, "%d", &temp ); + + fscanf( fp, "%d\n", &data_compression ); + + plane_size = size[0] * size[1]; + volume_size = plane_size * size[2]; + + // Skip Over Icon + fscanf( fp, "%d %d X", &icon_width, &icon_height ); + icon_ptr = new unsigned char[(icon_width*icon_height)]; + + fread( icon_ptr, 1, (icon_width*icon_height), fp ); + fread( icon_ptr, 1, (icon_width*icon_height), fp ); + fread( icon_ptr, 1, (icon_width*icon_height), fp ); + + delete [] icon_ptr; + + // Read In Data Plane By Plane + for( z_counter=0; z_counterUpdateProgress((float)z_counter/size[2]); + } + + // Read a single plane into temp memory + switch( data_compression ) + { + case 0: + + if( !scan_ptr ) + { + scan_ptr = new unsigned char[plane_size]; + } + + if( fread( scan_ptr, 1, plane_size, fp ) != (unsigned int)plane_size ) + { + vtkErrorMacro( << + "Unable to read slice " << z_counter << " from SLC File" ); + return; + } + + break; + + case 1: + + if( scan_ptr ) + { + delete [] scan_ptr; + } + + fscanf( fp, "%d X", &compressed_size ); + + compressed_ptr = new unsigned char[compressed_size]; + + if( fread(compressed_ptr, 1, compressed_size, fp) != + (unsigned int)compressed_size ) + { + vtkErrorMacro( << "Unable to read compressed slice " << + z_counter << " from SLC File" ); + return; + } + + scan_ptr = this->Decode8BitData( compressed_ptr, plane_size ); + delete [] compressed_ptr; + + break; + default: + vtkErrorMacro(<< "Unknown SLC compression type: " << + data_compression ); + break; + } + void* outputSlice = output->GetScalarPointer(0, 0, z_counter); + memcpy(outputSlice, scan_ptr, plane_size); + } + + delete [] scan_ptr; + + vtkDebugMacro(<< "Read " << volume_size << " points"); + + fclose( fp ); + this->Error = 0; +} + +int vtkSLCReader::CanReadFile(const char* fname) +{ + FILE* fp; + int magic_num = 0; + if ((fp = fopen(fname, "rb")) == NULL) + { + return 0; + } + + fscanf( fp, "%d", &magic_num ); + if( magic_num != 11111 ) + { + fclose(fp); + return 0; + } + fclose(fp); + return 3; +} + + +void vtkSLCReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Error: " << this->Error << "\n"; + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; +} diff --git a/IO/vtkSLCReader.h b/IO/vtkSLCReader.h new file mode 100644 index 0000000..06ce86b --- /dev/null +++ b/IO/vtkSLCReader.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSLCReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkSLCReader - read an SLC volume file. +// .SECTION Description +// vtkSLCReader reads an SLC file and creates a structured point dataset. +// The size of the volume and the data spacing is set from the SLC file +// header. + +#ifndef __vtkSLCReader_h +#define __vtkSLCReader_h + +#include "vtkImageReader2.h" + +class VTK_IO_EXPORT vtkSLCReader : public vtkImageReader2 +{ +public: + static vtkSLCReader *New(); + vtkTypeRevisionMacro(vtkSLCReader,vtkImageReader2); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the name of the file to read. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Was there an error on the last read performed? + vtkGetMacro(Error,int); + + // Description: + // Is the given file an SLC file? + int CanReadFile(const char* fname); + // Description: + // .slc + virtual const char* GetFileExtensions() + { + return ".slc"; + } + + // Description: + // SLC + virtual const char* GetDescriptiveName() + { + return "SLC"; + } + +protected: + vtkSLCReader(); + ~vtkSLCReader(); + + // Reads the file name and builds a vtkStructuredPoints dataset. + virtual void ExecuteData(vtkDataObject*); + + virtual int RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Decodes an array of eight bit run-length encoded data. + unsigned char *Decode8BitData( unsigned char *in_ptr, int size ); + int Error; +private: + vtkSLCReader(const vtkSLCReader&); // Not implemented. + void operator=(const vtkSLCReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkSTLReader.cxx b/IO/vtkSTLReader.cxx new file mode 100644 index 0000000..776db9c --- /dev/null +++ b/IO/vtkSTLReader.cxx @@ -0,0 +1,442 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSTLReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSTLReader.h" + +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkSTLReader, "$Revision: 1.71 $"); +vtkStandardNewMacro(vtkSTLReader); + +#define VTK_ASCII 0 +#define VTK_BINARY 1 + +// Construct object with merging set to true. +vtkSTLReader::vtkSTLReader() +{ + this->FileName = NULL; + this->Merging = 1; + this->ScalarTags = 0; + this->Locator = NULL; + + this->SetNumberOfInputPorts(0); +} + +vtkSTLReader::~vtkSTLReader() +{ + if (this->FileName) + { + delete [] this->FileName; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +// Overload standard modified time function. If locator is modified, +// then this object is modified as well. +unsigned long vtkSTLReader::GetMTime() +{ + unsigned long mTime1=this->Superclass::GetMTime(); + unsigned long mTime2; + + if (this->Locator) + { + mTime2 = this->Locator->GetMTime(); + mTime1 = ( mTime1 > mTime2 ? mTime1 : mTime2 ); + } + + return mTime1; +} + +int vtkSTLReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + FILE *fp; + vtkPoints *newPts, *mergedPts; + vtkCellArray *newPolys, *mergedPolys; + vtkFloatArray *newScalars=0, *mergedScalars=0; + + // All of the data in the first piece. + if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) + { + return 0; + } + + if (!this->FileName) + { + vtkErrorMacro(<<"A FileName must be specified."); + return 0; + } + + // Initialize + // + if ((fp = fopen(this->FileName, "r")) == NULL) + { + vtkErrorMacro(<< "File " << this->FileName << " not found"); + return 0; + } + + newPts = vtkPoints::New(); + newPts->Allocate(5000,10000); + newPolys = vtkCellArray::New(); + newPolys->Allocate(10000,20000); + + // Depending upon file type, read differently + // + if ( this->GetSTLFileType(fp) == VTK_ASCII ) + { + if (ScalarTags) + { + newScalars = vtkFloatArray::New(); + newScalars->Allocate(5000,10000); + } + if ( this->ReadASCIISTL(fp,newPts,newPolys,newScalars) ) + { + return 1; + } + } + else + { + fclose(fp); + fp = fopen(this->FileName, "rb"); + if ( this->ReadBinarySTL(fp,newPts,newPolys) ) + { + return 1; + } + } + + vtkDebugMacro(<< "Read: " + << newPts->GetNumberOfPoints() << " points, " + << newPolys->GetNumberOfCells() << " triangles"); + + fclose(fp); + // + // If merging is on, create hash table and merge points/triangles. + // + if ( this->Merging ) + { + int i; + vtkIdType *pts = 0; + vtkIdType nodes[3]; + vtkIdType npts; + double x[3]; + int nextCell=0; + + mergedPts = vtkPoints::New(); + mergedPts->Allocate(newPts->GetNumberOfPoints()/2); + mergedPolys = vtkCellArray::New(); + mergedPolys->Allocate(newPolys->GetSize()); + if (newScalars) + { + mergedScalars = vtkFloatArray::New(); + mergedScalars->Allocate(newPolys->GetSize()); + } + + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (mergedPts, newPts->GetBounds()); + + for (newPolys->InitTraversal(); newPolys->GetNextCell(npts,pts); ) + { + for (i=0; i < 3; i++) + { + newPts->GetPoint(pts[i],x); + this->Locator->InsertUniquePoint(x, nodes[i]); + } + + if ( nodes[0] != nodes[1] && + nodes[0] != nodes[2] && + nodes[1] != nodes[2] ) + { + mergedPolys->InsertNextCell(3,nodes); + if (newScalars) + { + mergedScalars->InsertNextValue(newScalars->GetValue(nextCell)); + } + } + nextCell++; + } + + newPts->Delete(); + newPolys->Delete(); + if (newScalars) + { + newScalars->Delete(); + } + + vtkDebugMacro(<< "Merged to: " + << mergedPts->GetNumberOfPoints() << " points, " + << mergedPolys->GetNumberOfCells() << " triangles"); + } + else + { + mergedPts = newPts; + mergedPolys = newPolys; + mergedScalars = newScalars; + } +// +// Update ourselves +// + output->SetPoints(mergedPts); + mergedPts->Delete(); + + output->SetPolys(mergedPolys); + mergedPolys->Delete(); + + if (mergedScalars) + { + output->GetCellData()->SetScalars(mergedScalars); + mergedScalars->Delete(); + } + + if (this->Locator) + { + this->Locator->Initialize(); //free storage + } + + output->Squeeze(); + + return 1; +} + +int vtkSTLReader::ReadBinarySTL(FILE *fp, vtkPoints *newPts, + vtkCellArray *newPolys) +{ + int i, numTris; + vtkIdType pts[3]; + unsigned long ulint; + unsigned short ibuff2; + char header[81]; + typedef struct {float n[3], v1[3], v2[3], v3[3];} facet_t; + facet_t facet; + + vtkDebugMacro(<< " Reading BINARY STL file"); + + // File is read to obtain raw information as well as bounding box + // + fread (header, 1, 80, fp); + fread (&ulint, 1, 4, fp); + vtkByteSwap::Swap4LE(&ulint); + + // Many .stl files contain bogus count. Hence we will ignore and read + // until end of file. + // + if ( (numTris = (int) ulint) <= 0 ) + { + vtkDebugMacro(<< "Bad binary count: attempting to correct (" + << numTris << ")"); + } + + for ( i=0; fread(&facet,48,1,fp) > 0; i++ ) + { + fread(&ibuff2,2,1,fp); //read extra junk + + vtkByteSwap::Swap4LE (facet.n); + vtkByteSwap::Swap4LE (facet.n+1); + vtkByteSwap::Swap4LE (facet.n+2); + + vtkByteSwap::Swap4LE (facet.v1); + vtkByteSwap::Swap4LE (facet.v1+1); + vtkByteSwap::Swap4LE (facet.v1+2); + pts[0] = newPts->InsertNextPoint(facet.v1); + + vtkByteSwap::Swap4LE (facet.v2); + vtkByteSwap::Swap4LE (facet.v2+1); + vtkByteSwap::Swap4LE (facet.v2+2); + pts[1] = newPts->InsertNextPoint(facet.v2); + + vtkByteSwap::Swap4LE (facet.v3); + vtkByteSwap::Swap4LE (facet.v3+1); + vtkByteSwap::Swap4LE (facet.v3+2); + pts[2] = newPts->InsertNextPoint(facet.v3); + + newPolys->InsertNextCell(3,pts); + + if ( (i % 5000) == 0 && i != 0 ) + { + vtkDebugMacro(<< "triangle# " << i); + this->UpdateProgress((i%50000)/50000.0); + } + } + + return 0; +} + +int vtkSTLReader::ReadASCIISTL(FILE *fp, vtkPoints *newPts, + vtkCellArray *newPolys, vtkFloatArray *scalars) +{ + char line[256]; + float x[3]; + vtkIdType pts[3]; + int done; + int currentSolid = 0; + + vtkDebugMacro(<< " Reading ASCII STL file"); + + // Ingest header and junk to get to first vertex + // + fgets (line, 255, fp); + + done = (fscanf(fp,"%s %*s %f %f %f\n", line, x, x+1, x+2)==EOF); + + // Go into loop, reading facet normal and vertices + // +// while (fscanf(fp,"%*s %*s %f %f %f\n", x, x+1, x+2)!=EOF) + while (!done) + { +//if (ctr>=253840) { +// fprintf(stdout, "Reading record %d\n", ctr); +//} +//ctr += 7; + fgets (line, 255, fp); + fscanf (fp, "%*s %f %f %f\n", x,x+1,x+2); + pts[0] = newPts->InsertNextPoint(x); + fscanf (fp, "%*s %f %f %f\n", x,x+1,x+2); + pts[1] = newPts->InsertNextPoint(x); + fscanf (fp, "%*s %f %f %f\n", x,x+1,x+2); + pts[2] = newPts->InsertNextPoint(x); + fgets (line, 255, fp); // end loop + fgets (line, 255, fp); // end facet + + newPolys->InsertNextCell(3,pts); + if (scalars) + { + scalars->InsertNextValue(currentSolid); + } + + if ( (newPolys->GetNumberOfCells() % 5000) == 0 ) + { + vtkDebugMacro(<< "triangle# " << newPolys->GetNumberOfCells()); + this->UpdateProgress((newPolys->GetNumberOfCells()%50000)/50000.0); + } + done = (fscanf(fp,"%s", line)==EOF); + if ((strcmp(line, "ENDSOLID") == 0) || (strcmp(line, "endsolid") == 0)) + { + currentSolid++; + fgets(line, 255, fp); + done = feof(fp); + while ((strstr(line, "SOLID") == 0) && (strstr(line, "solid") == 0) && !done) + { + fgets(line, 255, fp); + done = feof(fp); + } + + done = (fscanf(fp,"%s", line)==EOF); + } + if (!done) { + done = (fscanf(fp,"%*s %f %f %f\n", x, x+1, x+2)==EOF); + } + } + //fprintf(stdout, "Maximum ctr val %d\n", ctr); + return 0; +} + +int vtkSTLReader::GetSTLFileType(FILE *fp) +{ + unsigned char header[256]; + int type, i; + int numChars; + + // Read a little from the file to figure what type it is. + // + // skip 255 characters so we are past any first line comment */ + numChars = static_cast(fread ((unsigned char *)header, 1, 255, fp)); + for (i = 0, type=VTK_ASCII; i< numChars && type == VTK_ASCII; i++) // don't test \0 + { + if (header[i] > 127) + { + type = VTK_BINARY; + } + } + + // Reset file for reading + // + rewind (fp); + return type; +} + +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkSTLReader::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if ( this->Locator ) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if ( locator ) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkSTLReader::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } +} + +void vtkSTLReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n"); + os << indent << "ScalarTags: " << (this->ScalarTags ? "On\n" : "Off\n"); + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/IO/vtkSTLReader.h b/IO/vtkSTLReader.h new file mode 100644 index 0000000..dd9f25f --- /dev/null +++ b/IO/vtkSTLReader.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSTLReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSTLReader - read ASCII or binary stereo lithography files +// .SECTION Description +// vtkSTLReader is a source object that reads ASCII or binary stereo +// lithography files (.stl files). The FileName must be specified to +// vtkSTLReader. The object automatically detects whether the file is +// ASCII or binary. +// +// .stl files are quite inefficient since they duplicate vertex +// definitions. By setting the Merging boolean you can control whether the +// point data is merged after reading. Merging is performed by default, +// however, merging requires a large amount of temporary storage since a +// 3D hash table must be constructed. + +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// vtkSTLWriter uses VAX or PC byte ordering and swaps bytes on other systems. + +#ifndef __vtkSTLReader_h +#define __vtkSTLReader_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkCellArray; +class vtkFloatArray; +class vtkPointLocator; +class vtkPoints; + +class VTK_IO_EXPORT vtkSTLReader : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSTLReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with merging set to true. + static vtkSTLReader *New(); + + // Description: + // Overload standard modified time function. If locator is modified, + // then this object is modified as well. + unsigned long GetMTime(); + + // Description: + // Specify file name of stereo lithography file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Turn on/off merging of points/triangles. + vtkSetMacro(Merging,int); + vtkGetMacro(Merging,int); + vtkBooleanMacro(Merging,int); + + // Description: + // Turn on/off tagging of solids with scalars. + vtkSetMacro(ScalarTags,int); + vtkGetMacro(ScalarTags,int); + vtkBooleanMacro(ScalarTags,int); + + // Description: + // Specify a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + +protected: + vtkSTLReader(); + ~vtkSTLReader(); + + char *FileName; + int Merging; + int ScalarTags; + vtkPointLocator *Locator; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int ReadBinarySTL(FILE *fp, vtkPoints*, vtkCellArray*); + int ReadASCIISTL(FILE *fp, vtkPoints*, vtkCellArray*, + vtkFloatArray* scalars=0); + int GetSTLFileType(FILE *fp); +private: + vtkSTLReader(const vtkSTLReader&); // Not implemented. + void operator=(const vtkSTLReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkSTLWriter.cxx b/IO/vtkSTLWriter.cxx new file mode 100644 index 0000000..54c0a02 --- /dev/null +++ b/IO/vtkSTLWriter.cxx @@ -0,0 +1,265 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSTLWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSTLWriter.h" + +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkErrorCode.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkTriangle.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +vtkCxxRevisionMacro(vtkSTLWriter, "$Revision: 1.57 $"); +vtkStandardNewMacro(vtkSTLWriter); + +vtkSTLWriter::vtkSTLWriter() +{ + this->FileType = VTK_ASCII; +} + +void vtkSTLWriter::WriteData() +{ + vtkPoints *pts; + vtkCellArray *polys; + vtkPolyData *input = this->GetInput(); + + polys = input->GetPolys(); + pts = input->GetPoints(); + if (pts == NULL || polys == NULL ) + { + vtkErrorMacro(<<"No data to write!"); + return; + } + + if ( this->FileName == NULL) + { + vtkErrorMacro(<< "Please specify FileName to write"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return; + } + + if ( this->FileType == VTK_BINARY ) + { + this->WriteBinarySTL(pts,polys); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + unlink(this->FileName); + } + } + else + { + this->WriteAsciiSTL(pts,polys); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + unlink(this->FileName); + } + } +} + +static char header[]="Visualization Toolkit generated SLA File "; + +void vtkSTLWriter::WriteAsciiSTL(vtkPoints *pts, vtkCellArray *polys) +{ + FILE *fp; + double n[3], v1[3], v2[3], v3[3]; + vtkIdType npts = 0; + vtkIdType *indx = 0; + + if ((fp = fopen(this->FileName, "w")) == NULL) + { + vtkErrorMacro(<< "Couldn't open file: " << this->FileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + return; + } +// +// Write header +// + vtkDebugMacro("Writing ASCII sla file"); + if (fprintf (fp, "solid ascii\n") < 0) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } +// +// Write out triangle polygons. In not a triangle polygon, only first +// three vertices are written. +// + for (polys->InitTraversal(); polys->GetNextCell(npts,indx); ) + { + pts->GetPoint(indx[0],v1); + pts->GetPoint(indx[1],v2); + pts->GetPoint(indx[2],v3); + + vtkTriangle::ComputeNormal(pts, npts, indx, n); + + if (fprintf (fp, " facet normal %.6g %.6g %.6g\n outer loop\n", + n[0], n[1], n[2]) < 0) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + if (fprintf (fp, " vertex %.6g %.6g %.6g\n", v1[0], v1[1], v1[2]) < 0) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + if (fprintf (fp, " vertex %.6g %.6g %.6g\n", v2[0], v2[1], v2[2]) < 0) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + if (fprintf (fp, " vertex %.6g %.6g %.6g\n", v3[0], v3[1], v3[2]) < 0) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + if (fprintf (fp, " endloop\n endfacet\n") < 0) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + if (fprintf (fp, "endsolid\n") < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } + fclose (fp); +} + +void vtkSTLWriter::WriteBinarySTL(vtkPoints *pts, vtkCellArray *polys) +{ + FILE *fp; + double dn[3], v1[3], v2[3], v3[3]; + vtkIdType npts = 0; + vtkIdType *indx = 0; + unsigned long ulint; + unsigned short ibuff2=0; + + if ((fp = fopen(this->FileName, "wb")) == NULL) + { + vtkErrorMacro(<< "Couldn't open file: " << this->FileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + return; + } + + // Write header + // + vtkDebugMacro("Writing Binary STL file"); + if (fwrite (header, 1, 80, fp) < 80) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + ulint = (unsigned long int) polys->GetNumberOfCells(); + vtkByteSwap::Swap4LE(&ulint); + if (fwrite (&ulint, 1, 4, fp) < 4) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + // Write out triangle polygons. In not a triangle polygon, only first + // three vertices are written. + // + for (polys->InitTraversal(); polys->GetNextCell(npts,indx); ) + { + pts->GetPoint(indx[0],v1); + pts->GetPoint(indx[1],v2); + pts->GetPoint(indx[2],v3); + + vtkTriangle::ComputeNormal(pts, npts, indx, dn); + float n[3]; + n[0] = (float)dn[0]; + n[1] = (float)dn[1]; + n[2] = (float)dn[2]; + vtkByteSwap::Swap4LE(n); + vtkByteSwap::Swap4LE(n+1); + vtkByteSwap::Swap4LE(n+2); + if (fwrite (n, 4, 3, fp) < 3) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + n[0] = (float)v1[0]; n[1] = (float)v1[1]; n[2] = (float)v1[2]; + vtkByteSwap::Swap4LE(n); + vtkByteSwap::Swap4LE(n+1); + vtkByteSwap::Swap4LE(n+2); + if (fwrite (n, 4, 3, fp) < 3) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + n[0] = (float)v2[0]; n[1] = (float)v2[1]; n[2] = (float)v2[2]; + vtkByteSwap::Swap4LE(n); + vtkByteSwap::Swap4LE(n+1); + vtkByteSwap::Swap4LE(n+2); + if (fwrite (n, 4, 3, fp) < 3) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + n[0] = (float)v3[0]; n[1] = (float)v3[1]; n[2] = (float)v3[2]; + vtkByteSwap::Swap4LE(n); + vtkByteSwap::Swap4LE(n+1); + vtkByteSwap::Swap4LE(n+2); + if (fwrite (n, 4, 3, fp) < 3) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + + if (fwrite (&ibuff2, 2, 1, fp) < 1) + { + fclose(fp); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + } + fclose (fp); +} + +//---------------------------------------------------------------------------- +void vtkSTLWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkSTLWriter.h b/IO/vtkSTLWriter.h new file mode 100644 index 0000000..8afdb0f --- /dev/null +++ b/IO/vtkSTLWriter.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSTLWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSTLWriter - write stereo lithography files +// .SECTION Description +// vtkSTLWriter writes stereo lithography (.stl) files in either ASCII or +// binary form. Stereo lithography files only contain triangles. If polygons +// with more than 3 vertices are present, only the first 3 vertices are +// written. Use vtkTriangleFilter to convert polygons to triangles. + +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// vtkSTLWriter uses VAX or PC byte ordering and swaps bytes on other systems. + +#ifndef __vtkSTLWriter_h +#define __vtkSTLWriter_h + +#include "vtkPolyDataWriter.h" + +class VTK_IO_EXPORT vtkSTLWriter : public vtkPolyDataWriter +{ +public: + static vtkSTLWriter *New(); + vtkTypeRevisionMacro(vtkSTLWriter,vtkPolyDataWriter); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkSTLWriter(); + ~vtkSTLWriter() {}; + + void WriteData(); + + void WriteBinarySTL(vtkPoints *pts, vtkCellArray *polys); + void WriteAsciiSTL(vtkPoints *pts, vtkCellArray *polys); +private: + vtkSTLWriter(const vtkSTLWriter&); // Not implemented. + void operator=(const vtkSTLWriter&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkSimplePointsReader.cxx b/IO/vtkSimplePointsReader.cxx new file mode 100644 index 0000000..ab5f0b1 --- /dev/null +++ b/IO/vtkSimplePointsReader.cxx @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimplePointsReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSimplePointsReader.h" + +#include "vtkCellArray.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkSmartPointer.h" + +vtkCxxRevisionMacro(vtkSimplePointsReader, "$Revision: 1.1.4.1 $"); +vtkStandardNewMacro(vtkSimplePointsReader); + +//---------------------------------------------------------------------------- +vtkSimplePointsReader::vtkSimplePointsReader() +{ + this->FileName = 0; + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkSimplePointsReader::~vtkSimplePointsReader() +{ + this->SetFileName(0); +} + +//---------------------------------------------------------------------------- +void vtkSimplePointsReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "FileName: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + +} + +//---------------------------------------------------------------------------- +int vtkSimplePointsReader::RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + // Make sure we have a file to read. + if(!this->FileName) + { + vtkErrorMacro("A FileName must be specified."); + return 0; + } + + // Open the input file. + ifstream fin(this->FileName); + if(!fin) + { + vtkErrorMacro("Error opening file " << this->FileName); + return 0; + } + + // Allocate objects to hold points and vertex cells. + vtkSmartPointer points = vtkSmartPointer::New(); + vtkSmartPointer verts = vtkSmartPointer::New(); + + // Read points from the file. + vtkDebugMacro("Reading points from file " << this->FileName); + double x[3]; + while(fin >> x[0] >> x[1] >> x[2]) + { + vtkIdType id = points->InsertNextPoint(x); + verts->InsertNextCell(1, &id); + } + vtkDebugMacro("Read " << points->GetNumberOfPoints() << " points."); + + // Store the points and cells in the output data object. + vtkPolyData* output = vtkPolyData::GetData(outputVector); + output->SetPoints(points); + output->SetVerts(verts); + + return 1; +} diff --git a/IO/vtkSimplePointsReader.h b/IO/vtkSimplePointsReader.h new file mode 100644 index 0000000..144b212 --- /dev/null +++ b/IO/vtkSimplePointsReader.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimplePointsReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSimplePointsReader - Read a list of points from a file. +// .SECTION Description +// vtkSimplePointsReader is a source object that reads a list of +// points from a file. Each point is specified by three +// floating-point values in ASCII format. There is one point per line +// of the file. A vertex cell is created for each point in the +// output. This reader is meant as an example of how to write a +// reader in VTK. + +#ifndef __vtkSimplePointsReader_h +#define __vtkSimplePointsReader_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_IO_EXPORT vtkSimplePointsReader : public vtkPolyDataAlgorithm +{ +public: + static vtkSimplePointsReader* New(); + vtkTypeRevisionMacro(vtkSimplePointsReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the name of the file from which to read points. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkSimplePointsReader(); + ~vtkSimplePointsReader(); + + char* FileName; + + int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); +private: + vtkSimplePointsReader(const vtkSimplePointsReader&); // Not implemented. + void operator=(const vtkSimplePointsReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkStructuredGridReader.cxx b/IO/vtkStructuredGridReader.cxx new file mode 100644 index 0000000..d18837a --- /dev/null +++ b/IO/vtkStructuredGridReader.cxx @@ -0,0 +1,371 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridReader.h" + +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkStructuredGridReader, "$Revision: 1.60 $"); +vtkStandardNewMacro(vtkStructuredGridReader); + +vtkStructuredGridReader::vtkStructuredGridReader() +{ + vtkStructuredGrid *output = vtkStructuredGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +vtkStructuredGridReader::~vtkStructuredGridReader() +{ +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkStructuredGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkStructuredGridReader::GetOutput(int idx) +{ + return vtkStructuredGrid::SafeDownCast(this->GetOutputDataObject(idx)); +} + +//----------------------------------------------------------------------------- +void vtkStructuredGridReader::SetOutput(vtkStructuredGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//----------------------------------------------------------------------------- +// We just need to read the dimensions +int vtkStructuredGridReader::RequestInformation( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + return this->ReadMetaData(outInfo); +} + +//----------------------------------------------------------------------------- +int vtkStructuredGridReader::ReadMetaData(vtkInformation *outInfo) +{ + char line[256]; + int done=0; + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 1; + } + + // Read structured grid specific stuff + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // Make sure we're reading right type of geometry + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( strncmp(this->LowerCase(line),"structured_grid",15) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + return 1; + } + + // Read keyword and dimensions + // + while (!done) + { + if (!this->ReadString(line)) + { + break; + } + + // Have to read field data because it may be binary. + if (! strncmp(this->LowerCase(line), "field", 5)) + { + vtkFieldData* fd = this->ReadFieldData(); + fd->Delete(); + } + + if ( ! strncmp(this->LowerCase(line),"dimensions",10) ) + { + int ext[6]; + if (!(this->Read(ext+1) && + this->Read(ext+3) && + this->Read(ext+5))) + { + vtkErrorMacro(<<"Error reading dimensions!"); + this->CloseVTKFile (); + return 1; + } + // read dimensions, change to extent; + ext[0] = ext[2] = ext[4] = 0; + --ext[1]; + --ext[3]; + --ext[5]; + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + ext, 6); + // That is all we wanted !!!!!!!!!!!!!!! + this->CloseVTKFile(); + return 1; + } + } + } + + vtkErrorMacro("Could not read dimensions"); + this->CloseVTKFile (); + + return 1; +} + +//----------------------------------------------------------------------------- +int vtkStructuredGridReader::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int numPts=0, npts=0, numCells=0, ncells; + char line[256]; + int dimsRead=0; + int done=0; + vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Reading vtk structured grid file..."); + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 1; + } + + // Read structured grid specific stuff + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // Make sure we're reading right type of geometry + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( strncmp(this->LowerCase(line),"structured_grid",15) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + return 1; + } + + // Read keyword and number of points + // + while (!done) + { + if (!this->ReadString(line)) + { + break; + } + + if (! strncmp(this->LowerCase(line), "field", 5)) + { + vtkFieldData* fd = this->ReadFieldData(); + output->SetFieldData(fd); + fd->Delete(); // ? + } + else if ( ! strncmp(line, "dimensions",10) ) + { + int dim[3]; + if (!(this->Read(dim) && + this->Read(dim+1) && + this->Read(dim+2))) + { + vtkErrorMacro(<<"Error reading dimensions!"); + this->CloseVTKFile (); + return 1; + } + + numPts = dim[0] * dim[1] * dim[2]; + output->SetDimensions(dim); + numCells = output->GetNumberOfCells(); + dimsRead = 1; + } + + else if ( ! strncmp(line,"blanking",8) ) + { + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Error reading blanking!"); + this->CloseVTKFile (); + return 1; + } + + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Cannot read blank type!" ); + this->CloseVTKFile (); + return 1; + } + + vtkUnsignedCharArray *data = vtkUnsignedCharArray::SafeDownCast( + this->ReadArray(line, numPts, 1)); + + if ( data != NULL ) + { + output->SetPointVisibilityArray(data); + data->Delete(); + } + } + + else if ( ! strncmp(line,"points",6) ) + { + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Error reading points!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadPoints(output, npts); + } + + else if ( ! strncmp(line, "cell_data", 9) ) + { + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + return 1; + } + + if ( ncells != numCells ) + { + vtkErrorMacro(<<"Number of cells don't match!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadCellData(output, ncells); + break; //out of this loop + } + + else if ( ! strncmp(line, "point_data", 10) ) + { + if (!this->Read(&numPts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + + if ( npts != numPts ) + { + vtkErrorMacro(<<"Number of points don't match!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadPointData(output, npts); + break; //out of this loop + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + this->CloseVTKFile (); + return 1; + } + } + + if ( !dimsRead ) vtkWarningMacro(<<"No dimensions read."); + if ( !output->GetPoints() ) vtkWarningMacro(<<"No points read."); + } + + else if ( !strncmp(line, "cell_data", 9) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + return 1; + } + this->ReadCellData(output, ncells); + } + + else if ( !strncmp(line, "point_data", 10) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + this->ReadPointData(output, npts); + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + } + this->CloseVTKFile (); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkStructuredGridReader::FillOutputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredGrid"); + return 1; +} + +void vtkStructuredGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkStructuredGridReader.h b/IO/vtkStructuredGridReader.h new file mode 100644 index 0000000..d9ad249 --- /dev/null +++ b/IO/vtkStructuredGridReader.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridReader - read vtk structured grid data file +// .SECTION Description +// vtkStructuredGridReader is a source object that reads ASCII or binary +// structured grid data files in vtk format. (see text for format details). +// The output of this reader is a single vtkStructuredGrid data object. +// The superclass of this class, vtkDataReader, provides many methods for +// controlling the reading of the data file, see vtkDataReader for more +// information. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// .SECTION See Also +// vtkStructuredGrid vtkDataReader + +#ifndef __vtkStructuredGridReader_h +#define __vtkStructuredGridReader_h + +#include "vtkDataReader.h" + +class vtkStructuredGrid; + +class VTK_IO_EXPORT vtkStructuredGridReader : public vtkDataReader +{ +public: + static vtkStructuredGridReader *New(); + vtkTypeRevisionMacro(vtkStructuredGridReader,vtkDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this reader. + vtkStructuredGrid *GetOutput(); + vtkStructuredGrid *GetOutput(int idx); + void SetOutput(vtkStructuredGrid *output); + + // Description: + // Read the meta information from the file. This needs to be public to it + // can be accessed by vtkDataSetReader. + virtual int ReadMetaData(vtkInformation *outInfo); + +protected: + vtkStructuredGridReader(); + ~vtkStructuredGridReader(); + + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkStructuredGridReader(const vtkStructuredGridReader&); // Not implemented. + void operator=(const vtkStructuredGridReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkStructuredGridWriter.cxx b/IO/vtkStructuredGridWriter.cxx new file mode 100644 index 0000000..9a97f15 --- /dev/null +++ b/IO/vtkStructuredGridWriter.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredGridWriter.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkStructuredGrid.h" +#include "vtkUnsignedCharArray.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +vtkCxxRevisionMacro(vtkStructuredGridWriter, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkStructuredGridWriter); + +void vtkStructuredGridWriter::WriteData() +{ + ostream *fp; + vtkStructuredGrid *input= vtkStructuredGrid::SafeDownCast(this->GetInput()); + int dim[3]; + + vtkDebugMacro(<<"Writing vtk structured grid..."); + + if ( !(fp=this->OpenVTKFile()) || !this->WriteHeader(fp) ) + { + if (fp) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + } + return; + } + + // Write structured grid specific stuff + // + *fp << "DATASET STRUCTURED_GRID\n"; + + // Write data owned by the dataset + if (!this->WriteDataSetData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + input->GetDimensions(dim); + *fp << "DIMENSIONS " << dim[0] << " " << dim[1] << " " << dim[2] << "\n"; + + if (!this->WritePoints(fp, input->GetPoints())) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + // If blanking, write that information out + if ( input->GetPointBlanking() ) + { + if (!this->WriteBlanking(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + } + + if (!this->WriteCellData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + if (!this->WritePointData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + this->CloseVTKFile(fp); +} + +int vtkStructuredGridWriter::WriteBlanking(ostream *fp, vtkStructuredGrid *grid) +{ + vtkUnsignedCharArray *blanking=grid->GetPointVisibilityArray(); + + int numPts = grid->GetNumberOfPoints(); + *fp << "BLANKING " << numPts; + return this->WriteArray(fp, VTK_UNSIGNED_CHAR, blanking, " %s\n", numPts, 1); +} + +int vtkStructuredGridWriter::FillInputPortInformation(int, + vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} + +vtkStructuredGrid* vtkStructuredGridWriter::GetInput() +{ + return vtkStructuredGrid::SafeDownCast(this->Superclass::GetInput()); +} + +vtkStructuredGrid* vtkStructuredGridWriter::GetInput(int port) +{ + return vtkStructuredGrid::SafeDownCast(this->Superclass::GetInput(port)); +} + +void vtkStructuredGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkStructuredGridWriter.h b/IO/vtkStructuredGridWriter.h new file mode 100644 index 0000000..a0fdfce --- /dev/null +++ b/IO/vtkStructuredGridWriter.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredGridWriter - write vtk structured grid data file +// .SECTION Description +// vtkStructuredGridWriter is a source object that writes ASCII or binary +// structured grid data files in vtk format. See text for format details. + +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. + +#ifndef __vtkStructuredGridWriter_h +#define __vtkStructuredGridWriter_h + +#include "vtkDataWriter.h" + +class vtkStructuredGrid; + +class VTK_IO_EXPORT vtkStructuredGridWriter : public vtkDataWriter +{ +public: + static vtkStructuredGridWriter *New(); + vtkTypeRevisionMacro(vtkStructuredGridWriter,vtkDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the input to this writer. + vtkStructuredGrid* GetInput(); + vtkStructuredGrid* GetInput(int port); + +protected: + vtkStructuredGridWriter() {}; + ~vtkStructuredGridWriter() {}; + + void WriteData(); + int WriteBlanking(ostream *fp, vtkStructuredGrid *ds); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkStructuredGridWriter(const vtkStructuredGridWriter&); // Not implemented. + void operator=(const vtkStructuredGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkStructuredPointsReader.cxx b/IO/vtkStructuredPointsReader.cxx new file mode 100644 index 0000000..d899187 --- /dev/null +++ b/IO/vtkStructuredPointsReader.cxx @@ -0,0 +1,533 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsReader.h" + +#include "vtkDataArray.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredPoints.h" + +vtkCxxRevisionMacro(vtkStructuredPointsReader, "$Revision: 1.64 $"); +vtkStandardNewMacro(vtkStructuredPointsReader); + +vtkStructuredPointsReader::vtkStructuredPointsReader() +{ + vtkStructuredPoints *output = vtkStructuredPoints::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +vtkStructuredPointsReader::~vtkStructuredPointsReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkStructuredPointsReader::SetOutput(vtkStructuredPoints *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkStructuredPoints* vtkStructuredPointsReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkStructuredPoints* vtkStructuredPointsReader::GetOutput(int idx) +{ + return vtkStructuredPoints::SafeDownCast(this->GetOutputDataObject(idx)); +} + +//---------------------------------------------------------------------------- +// Default method performs Update to get information. Not all the old +// structured points sources compute information +int vtkStructuredPointsReader::RequestInformation( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + return this->ReadMetaData(outInfo); +} + +//---------------------------------------------------------------------------- +int vtkStructuredPointsReader::ReadMetaData(vtkInformation *outInfo) +{ + this->SetErrorCode( vtkErrorCode::NoError ); + + char line[256]; + int dimsRead=0, arRead=0, originRead=0; + int done=0; + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 1; + } + + // Read structured points specific stuff + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // Make sure we're reading right type of geometry + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 1; + } + + if ( strncmp(this->LowerCase(line),"structured_points",17) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::UnrecognizedFileTypeError ); + return 1; + } + + // Read keyword and number of points + while (!done) + { + if (!this->ReadString(line)) + { + break; + } + + if ( ! strncmp(this->LowerCase(line), "dimensions",10) ) + { + int dim[3]; + if (!(this->Read(dim) && + this->Read(dim+1) && + this->Read(dim+2))) + { + vtkErrorMacro(<<"Error reading dimensions!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0,dim[0]-1,0,dim[1]-1,0,dim[2]-1); + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + 0,dim[0]-1,0,dim[1]-1,0,dim[2]-1); + dimsRead = 1; + } + + else if ( !strncmp(line,"aspect_ratio",12) || + !strncmp(line,"spacing",7) ) + { + double ar[3]; + if (!(this->Read(ar) && + this->Read(ar+1) && + this->Read(ar+2))) + { + vtkErrorMacro(<<"Error reading spacing!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + outInfo->Set(vtkDataObject::SPACING(), ar, 3); + arRead = 1; + } + + else if ( ! strncmp(line,"origin",6) ) + { + double origin[3]; + if (!(this->Read(origin) && + this->Read(origin+1) && + this->Read(origin+2))) + { + vtkErrorMacro(<<"Error reading origin!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + outInfo->Set(vtkDataObject::ORIGIN(), origin, 3); + originRead = 1; + } + + else if ( ! strncmp(line, "point_data", 10) ) + { + int npts; + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + while (this->ReadString(line)) + { + // read scalar data + // + if ( ! strncmp(this->LowerCase(line), "scalars", 7) ) + { + int scalarType = VTK_DOUBLE; + this->ReadString(line); + this->ReadString(line); + + if ( ! strncmp(line, "bit", 3) ) + { + scalarType = VTK_BIT; + } + else if ( ! strncmp(line, "char", 4) ) + { + scalarType = VTK_CHAR; + } + else if ( ! strncmp(line, "unsigned_char", 13) ) + { + scalarType = VTK_UNSIGNED_CHAR; + } + else if ( ! strncmp(line, "short", 5) ) + { + scalarType = VTK_SHORT; + } + else if ( ! strncmp(line, "unsigned_short", 14) ) + { + scalarType = VTK_UNSIGNED_SHORT; + } + else if ( ! strncmp(line, "int", 3) ) + { + scalarType = VTK_INT; + } + else if ( ! strncmp(line, "unsigned_int", 12) ) + { + scalarType = VTK_UNSIGNED_INT; + } + else if ( ! strncmp(line, "long", 4) ) + { + scalarType = VTK_LONG; + } + else if ( ! strncmp(line, "unsigned_long", 13) ) + { + scalarType = VTK_UNSIGNED_LONG; + } + else if ( ! strncmp(line, "float", 5) ) + { + scalarType = VTK_FLOAT; + } + else if ( ! strncmp(line, "double", 6) ) + { + scalarType = VTK_DOUBLE; + } + + // the next string could be an integer number of components or a + // lookup table + this->ReadString(line); + int numComp; + if (strcmp(this->LowerCase(line), "lookup_table")) + { + numComp = atoi(line); + if (numComp < 1 || !this->ReadString(line)) + { + vtkErrorMacro(<<"Cannot read scalar header!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 1; + } + } + else + { + numComp = 1; + } + + vtkDataObject::SetPointDataActiveScalarInfo( outInfo, scalarType, numComp); + break; + } + else if ( ! strncmp(this->LowerCase(line), "color_scalars", 13) ) + { + this->ReadString(line); + this->ReadString(line); + int numComp = atoi(line); + if (numComp < 1) + { + vtkErrorMacro("Cannot read color_scalar header!" << " for file: " + << (this->FileName?this->FileName:"(Null FileName)")); + return 1; + } + + // Color scalar type is predefined by FileType. + int scalarType; + if(this->FileType == VTK_BINARY) + { + scalarType = VTK_UNSIGNED_CHAR; + } + else + { + scalarType = VTK_FLOAT; + } + + vtkDataObject::SetPointDataActiveScalarInfo( outInfo, scalarType, numComp); + break; + } + } + break; //out of this loop + } + } + + if ( !dimsRead || !arRead || !originRead) + { + vtkWarningMacro(<<"Not all meta data was read form the file."); + } + } + + this->CloseVTKFile (); + + return 1; +} + +int vtkStructuredPointsReader::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + this->SetErrorCode( vtkErrorCode::NoError ); + int numPts=0, numCells=0; + char line[256]; + int npts, ncells; + int dimsRead=0, arRead=0, originRead=0; + int done=0; + vtkStructuredPoints *output = vtkStructuredPoints::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // ImageSource superclass does not do this. + output->ReleaseData(); + + vtkDebugMacro(<<"Reading vtk structured points file..."); + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 1; + } + + // Read structured points specific stuff + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // Make sure we're reading right type of geometry + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::PrematureEndOfFileError ); + return 1; + } + + if ( strncmp(this->LowerCase(line),"structured_points",17) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::UnrecognizedFileTypeError ); + return 1; + } + + // Read keyword and number of points + // + numPts = output->GetNumberOfPoints(); // get default + while (!done) + { + if (!this->ReadString(line)) + { + break; + } + + if (! strncmp(this->LowerCase(line), "field", 5)) + { + vtkFieldData* fd = this->ReadFieldData(); + output->SetFieldData(fd); + fd->Delete(); // ? + } + else if ( ! strncmp(line, "dimensions",10) ) + { + int dim[3]; + if (!(this->Read(dim) && + this->Read(dim+1) && + this->Read(dim+2))) + { + vtkErrorMacro(<<"Error reading dimensions!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + numPts = dim[0] * dim[1] * dim[2]; + output->SetDimensions(dim); + numCells = output->GetNumberOfCells(); + dimsRead = 1; + } + + else if ( !strncmp(line,"aspect_ratio",12) || !strncmp(line,"spacing",7) ) + { + double ar[3]; + if (!(this->Read(ar) && + this->Read(ar+1) && + this->Read(ar+2))) + { + vtkErrorMacro(<<"Error reading spacing!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + output->SetSpacing(ar); + arRead = 1; + } + + else if ( ! strncmp(line,"origin",6) ) + { + double origin[3]; + if (!(this->Read(origin) && + this->Read(origin+1) && + this->Read(origin+2))) + { + vtkErrorMacro(<<"Error reading origin!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + output->SetOrigin(origin); + originRead = 1; + } + + else if ( ! strncmp(line, "cell_data", 9) ) + { + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + if ( ncells != numCells ) + { + vtkErrorMacro(<<"Number of cells don't match data values!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + this->ReadCellData(output, ncells); + break; //out of this loop + } + + else if ( ! strncmp(line, "point_data", 10) ) + { + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + if ( npts != numPts ) + { + vtkErrorMacro(<<"Number of points don't match data values!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + + this->ReadPointData(output, npts); + break; //out of this loop + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + } + + if ( !dimsRead ) vtkWarningMacro(<<"No dimensions read."); + if ( !arRead ) vtkWarningMacro(<<"No spacing read."); + if ( !originRead ) vtkWarningMacro(<<"No origin read."); + } + + else if ( !strncmp(line,"cell_data",9) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + this->ReadCellData(output, numCells); + } + + else if ( !strncmp(line,"point_data",10) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + this->SetErrorCode( vtkErrorCode::FileFormatError ); + return 1; + } + this->ReadPointData(output, numPts); + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + } + this->CloseVTKFile (); + + return 1; +} + +int vtkStructuredPointsReader::FillOutputPortInformation(int, + vtkInformation *info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredPoints"); + return 1; +} + +void vtkStructuredPointsReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkStructuredPointsReader.h b/IO/vtkStructuredPointsReader.h new file mode 100644 index 0000000..b3bf570 --- /dev/null +++ b/IO/vtkStructuredPointsReader.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsReader - read vtk structured points data file +// .SECTION Description +// vtkStructuredPointsReader is a source object that reads ASCII or binary +// structured points data files in vtk format (see text for format details). +// The output of this reader is a single vtkStructuredPoints data object. +// The superclass of this class, vtkDataReader, provides many methods for +// controlling the reading of the data file, see vtkDataReader for more +// information. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// .SECTION See Also +// vtkStructuredPoints vtkDataReader + +#ifndef __vtkStructuredPointsReader_h +#define __vtkStructuredPointsReader_h + +#include "vtkDataReader.h" + +class vtkStructuredPoints; + +class VTK_IO_EXPORT vtkStructuredPointsReader : public vtkDataReader +{ +public: + static vtkStructuredPointsReader *New(); + vtkTypeRevisionMacro(vtkStructuredPointsReader,vtkDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the output of this reader. + void SetOutput(vtkStructuredPoints *output); + vtkStructuredPoints *GetOutput(int idx); + vtkStructuredPoints *GetOutput(); + + // Description: + // Read the meta information from the file. This needs to be public to it + // can be accessed by vtkDataSetReader. + virtual int ReadMetaData(vtkInformation *outInfo); + +protected: + vtkStructuredPointsReader(); + ~vtkStructuredPointsReader(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + // Default method performs Update to get information. Not all the old + // structured points sources compute information + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + virtual int FillOutputPortInformation(int, vtkInformation *); +private: + vtkStructuredPointsReader(const vtkStructuredPointsReader&); // Not implemented. + void operator=(const vtkStructuredPointsReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkStructuredPointsWriter.cxx b/IO/vtkStructuredPointsWriter.cxx new file mode 100644 index 0000000..9742450 --- /dev/null +++ b/IO/vtkStructuredPointsWriter.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkStructuredPointsWriter.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkStructuredPoints.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + + +vtkCxxRevisionMacro(vtkStructuredPointsWriter, "$Revision: 1.42 $"); +vtkStandardNewMacro(vtkStructuredPointsWriter); + +void vtkStructuredPointsWriter::WriteData() +{ + ostream *fp; + vtkImageData *input= vtkImageData::SafeDownCast(this->GetInput()); + int dim[3]; + int *ext; + double spacing[3], origin[3]; + + vtkDebugMacro(<<"Writing vtk structured points..."); + + if ( !(fp=this->OpenVTKFile()) || !this->WriteHeader(fp) ) + { + if (fp) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + } + return; + } + // + // Write structured points specific stuff + // + *fp << "DATASET STRUCTURED_POINTS\n"; + + // Write data owned by the dataset + if (!this->WriteDataSetData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + input->GetDimensions(dim); + *fp << "DIMENSIONS " << dim[0] << " " << dim[1] << " " << dim[2] << "\n"; + + input->GetSpacing(spacing); + *fp << "SPACING " << spacing[0] << " " << spacing[1] << " " << spacing[2] << "\n"; + + input->GetOrigin(origin); + // Do the electric slide. Move origin to min corner of extent. + // The alternative is to change the format to include an extent instead of dimensions. + ext = input->GetExtent(); + origin[0] += ext[0] * spacing[0]; + origin[1] += ext[2] * spacing[1]; + origin[2] += ext[4] * spacing[2]; + *fp << "ORIGIN " << origin[0] << " " << origin[1] << " " << origin[2] << "\n"; + + if (!this->WriteCellData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + if (!this->WritePointData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + this->CloseVTKFile(fp); +} + +int vtkStructuredPointsWriter::FillInputPortInformation(int, + vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +vtkImageData* vtkStructuredPointsWriter::GetInput() +{ + return vtkImageData::SafeDownCast(this->Superclass::GetInput()); +} + +vtkImageData* vtkStructuredPointsWriter::GetInput(int port) +{ + return vtkImageData::SafeDownCast(this->Superclass::GetInput(port)); +} + +void vtkStructuredPointsWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkStructuredPointsWriter.h b/IO/vtkStructuredPointsWriter.h new file mode 100644 index 0000000..b967de9 --- /dev/null +++ b/IO/vtkStructuredPointsWriter.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkStructuredPointsWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkStructuredPointsWriter - write vtk structured points data file +// .SECTION Description +// vtkStructuredPointsWriter is a source object that writes ASCII or binary +// structured points data in vtk file format. See text for format details. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. + +#ifndef __vtkStructuredPointsWriter_h +#define __vtkStructuredPointsWriter_h + +#include "vtkDataWriter.h" + +class vtkImageData; + +class VTK_IO_EXPORT vtkStructuredPointsWriter : public vtkDataWriter +{ +public: + static vtkStructuredPointsWriter *New(); + vtkTypeRevisionMacro(vtkStructuredPointsWriter,vtkDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the input to this writer. + vtkImageData* GetInput(); + vtkImageData* GetInput(int port); + +protected: + vtkStructuredPointsWriter() {}; + ~vtkStructuredPointsWriter() {}; + + void WriteData(); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkStructuredPointsWriter(const vtkStructuredPointsWriter&); // Not implemented. + void operator=(const vtkStructuredPointsWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkTIFFReader.cxx b/IO/vtkTIFFReader.cxx new file mode 100644 index 0000000..86d8442 --- /dev/null +++ b/IO/vtkTIFFReader.cxx @@ -0,0 +1,736 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTIFFReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTIFFReader.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkToolkits.h" + +#include + +extern "C" { +#include "vtk_tiff.h" +} + +//------------------------------------------------------------------------- +vtkStandardNewMacro(vtkTIFFReader); +vtkCxxRevisionMacro(vtkTIFFReader, "$Revision: 1.51 $"); + +class vtkTIFFReaderInternal +{ +public: + vtkTIFFReaderInternal(); + int Initialize(); + void Clean(); + int CanRead(); + int Open( const char *filename ); + TIFF *Image; + unsigned int Width; + unsigned int Height; + unsigned short SamplesPerPixel; + unsigned short Compression; + unsigned short BitsPerSample; + unsigned short Photometrics; + unsigned short PlanarConfig; + unsigned long int TileDepth; + static void ErrorHandler(const char* module, const char* fmt, va_list ap); +}; + + +extern "C" { +void vtkTIFFReaderInternalErrorHandler(const char* vtkNotUsed(module), + const char* vtkNotUsed(fmt), + va_list vtkNotUsed(ap)) +{ + // Do nothing + // Ignore errors +} +} + +//------------------------------------------------------------------------- +int vtkTIFFReaderInternal::Open( const char *filename ) +{ + this->Clean(); + struct stat fs; + if ( stat(filename, &fs) ) + { + return 0; + } + this->Image = TIFFOpen(filename, "r"); + if ( !this->Image) + { + this->Clean(); + return 0; + } + if ( !this->Initialize() ) + { + this->Clean(); + return 0; + } + return 1; +} + +//------------------------------------------------------------------------- +void vtkTIFFReaderInternal::Clean() +{ + if ( this->Image ) + { + TIFFClose(this->Image); + } + this->Image=NULL; + this->Width = 0; + this->Height = 0; + this->SamplesPerPixel = 0; + this->Compression = 0; + this->BitsPerSample = 0; + this->Photometrics = 0; + this->PlanarConfig = 0; + this->TileDepth = 0; +} + +//------------------------------------------------------------------------- +vtkTIFFReaderInternal::vtkTIFFReaderInternal() +{ + this->Image = NULL; + TIFFSetErrorHandler(&vtkTIFFReaderInternalErrorHandler); + TIFFSetWarningHandler(&vtkTIFFReaderInternalErrorHandler); + this->Clean(); +} + +//------------------------------------------------------------------------- +int vtkTIFFReaderInternal::Initialize() +{ + if ( this->Image ) + { + if ( !TIFFGetField(this->Image, TIFFTAG_IMAGEWIDTH, &this->Width) || + !TIFFGetField(this->Image, TIFFTAG_IMAGELENGTH, &this->Height) ) + { + return 0; + } + TIFFGetField(this->Image, TIFFTAG_SAMPLESPERPIXEL, + &this->SamplesPerPixel); + TIFFGetField(this->Image, TIFFTAG_COMPRESSION, &this->Compression); + TIFFGetField(this->Image, TIFFTAG_BITSPERSAMPLE, + &this->BitsPerSample); + TIFFGetField(this->Image, TIFFTAG_PHOTOMETRIC, &this->Photometrics); + TIFFGetField(this->Image, TIFFTAG_PLANARCONFIG, &this->PlanarConfig); + if ( !TIFFGetField(this->Image, TIFFTAG_TILEDEPTH, &this->TileDepth) ) + { + this->TileDepth = 0; + } + } + return 1; +} + +//------------------------------------------------------------------------- +int vtkTIFFReaderInternal::CanRead() +{ + return ( this->Image && ( this->Width > 0 ) && ( this->Height > 0 ) && + ( this->SamplesPerPixel > 0 ) && + ( this->Compression == COMPRESSION_NONE ) && + ( this->Photometrics == PHOTOMETRIC_RGB || + this->Photometrics == PHOTOMETRIC_MINISWHITE || + this->Photometrics == PHOTOMETRIC_MINISBLACK || + this->Photometrics == PHOTOMETRIC_PALETTE ) && + this->PlanarConfig == PLANARCONFIG_CONTIG && + ( !this->TileDepth ) && + ( this->BitsPerSample == 8 ) || this->BitsPerSample == 32 ); +} + +//------------------------------------------------------------------------- +vtkTIFFReader::vtkTIFFReader() +{ + this->InitializeColors(); + this->InternalImage = new vtkTIFFReaderInternal; + this->InternalExtents = 0; +} + +//------------------------------------------------------------------------- +vtkTIFFReader::~vtkTIFFReader() +{ + delete this->InternalImage; +} + +//------------------------------------------------------------------------- +void vtkTIFFReader::ExecuteInformation() +{ + this->InitializeColors(); + this->ComputeInternalFileName(this->DataExtent[4]); + if (this->InternalFileName == NULL) + { + return; + } + + if ( !this->InternalImage->Open(this->InternalFileName) ) + { + vtkErrorMacro("Unable to open file " << this->InternalFileName ); + this->DataExtent[0] = 0; + this->DataExtent[1] = 0; + this->DataExtent[2] = 0; + this->DataExtent[3] = 0; + this->DataExtent[4] = 0; + this->DataExtent[5] = 0; + this->SetNumberOfScalarComponents(1); + this->vtkImageReader2::ExecuteInformation(); + return; + } + + // pull out the width/height, etc. + this->DataExtent[0] = 0; + this->DataExtent[1] = this->GetInternalImage()->Width - 1; + this->DataExtent[2] = 0; + this->DataExtent[3] = this->GetInternalImage()->Height - 1; + + switch (this->GetInternalImage()->BitsPerSample) + { + case 32: + this->SetDataScalarTypeToFloat(); + break; + default: + this->SetDataScalarTypeToUnsignedChar(); + } + + switch ( this->GetFormat() ) + { + case vtkTIFFReader::GRAYSCALE: + case vtkTIFFReader::PALETTE_GRAYSCALE: + this->SetNumberOfScalarComponents( 1 ); + break; + case vtkTIFFReader::RGB: + this->SetNumberOfScalarComponents( + this->GetInternalImage()->SamplesPerPixel ); + break; + case vtkTIFFReader::PALETTE_RGB: + this->SetNumberOfScalarComponents( 3 ); + break; + default: + this->SetNumberOfScalarComponents( 4 ); + } + + if ( !this->GetInternalImage()->CanRead() ) + { + this->SetNumberOfScalarComponents( 4 ); + } + + this->vtkImageReader2::ExecuteInformation(); + + // close the file + this->GetInternalImage()->Clean(); +} + + +//------------------------------------------------------------------------- +template +void vtkTIFFReaderUpdate2(vtkTIFFReader *self, OT *outPtr, + int *outExt, vtkIdType* vtkNotUsed(outInc), long) +{ + if ( !self->GetInternalImage()->Open(self->GetInternalFileName()) ) + { + return; + } + self->InitializeColors(); + self->ReadImageInternal(self->GetInternalImage()->Image, + outPtr, outExt, sizeof(OT) ); + + // close the file + self->GetInternalImage()->Clean(); +} + +//---------------------------------------------------------------------------- +// This function reads in one data of data. +// templated to handle different data types. +template +void vtkTIFFReaderUpdate(vtkTIFFReader *self, vtkImageData *data, OT *outPtr) +{ + vtkIdType outIncr[3]; + int outExtent[6]; + OT *outPtr2; + + data->GetExtent(outExtent); + data->GetIncrements(outIncr); + + long pixSize = data->GetNumberOfScalarComponents()*sizeof(OT); + + outPtr2 = outPtr; + int idx2; + for (idx2 = outExtent[4]; idx2 <= outExtent[5]; ++idx2) + { + self->ComputeInternalFileName(idx2); + // read in a TIFF file + vtkTIFFReaderUpdate2(self, outPtr2, outExtent, outIncr, pixSize); + self->UpdateProgress((idx2 - outExtent[4])/ + (outExtent[5] - outExtent[4] + 1.0)); + outPtr2 += outIncr[2]; + } +} + + +//---------------------------------------------------------------------------- +// This function reads a data from a file. The datas extent/axes +// are assumed to be the same as the file extent/order. +void vtkTIFFReader::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + if (this->InternalFileName == NULL) + { + vtkErrorMacro("Either a FileName or FilePrefix must be specified."); + return; + } + + this->ComputeDataIncrements(); + + // Call the correct templated function for the output + void *outPtr; + + // Call the correct templated function for the input + outPtr = data->GetScalarPointer(); + switch (data->GetScalarType()) + { + vtkTemplateMacro(vtkTIFFReaderUpdate(this, data, (VTK_TT *)(outPtr))); + default: + vtkErrorMacro("UpdateFromFile: Unknown data type"); + } +} + +//---------------------------------------------------------------------------- +unsigned int vtkTIFFReader::GetFormat() +{ + unsigned int cc; + + if ( this->ImageFormat != vtkTIFFReader::NOFORMAT ) + { + return this->ImageFormat; + } + + + switch ( this->GetInternalImage()->Photometrics ) + { + case PHOTOMETRIC_RGB: + case PHOTOMETRIC_YCBCR: + this->ImageFormat = vtkTIFFReader::RGB; + return this->ImageFormat; + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + this->ImageFormat = vtkTIFFReader::GRAYSCALE; + return this->ImageFormat; + case PHOTOMETRIC_PALETTE: + for( cc=0; cc<256; cc++ ) + { + unsigned short red, green, blue; + this->GetColor( cc, &red, &green, &blue ); + if ( red != green || red != blue ) + { + this->ImageFormat = vtkTIFFReader::PALETTE_RGB; + return this->ImageFormat; + } + } + this->ImageFormat = vtkTIFFReader::PALETTE_GRAYSCALE; + return this->ImageFormat; + } + this->ImageFormat = vtkTIFFReader::OTHER; + return this->ImageFormat; +} + +//---------------------------------------------------------------------------- +void vtkTIFFReader::GetColor( int index, unsigned short *red, + unsigned short *green, unsigned short *blue ) +{ + *red = 0; + *green = 0; + *blue = 0; + if ( index < 0 ) + { + vtkErrorMacro("Color index has to be greater than 0"); + return; + } + if ( this->TotalColors > 0 && + this->ColorRed && this->ColorGreen && this->ColorBlue ) + { + if ( index >= this->TotalColors ) + { + vtkErrorMacro("Color index has to be less than number of colors (" + << this->TotalColors << ")"); + return; + } + *red = *(this->ColorRed + index); + *green = *(this->ColorGreen + index); + *blue = *(this->ColorBlue + index); + return; + } + + unsigned short photometric; + + if (!TIFFGetField(this->GetInternalImage()->Image, TIFFTAG_PHOTOMETRIC, &photometric)) + { + if ( this->GetInternalImage()->Photometrics != PHOTOMETRIC_PALETTE ) + { + vtkErrorMacro("You can only access colors for palette images"); + return; + } + } + + unsigned short *red_orig, *green_orig, *blue_orig; + + switch (this->GetInternalImage()->BitsPerSample) + { + case 1: case 2: case 4: + case 8: case 16: + break; + default: + vtkErrorMacro( "Sorry, can not image with " + << this->GetInternalImage()->BitsPerSample + << "-bit samples" ); + return; + } + if (!TIFFGetField(this->GetInternalImage()->Image, TIFFTAG_COLORMAP, + &red_orig, &green_orig, &blue_orig)) + { + vtkErrorMacro("Missing required \"Colormap\" tag"); + return; + } + this->TotalColors = (1L << this->GetInternalImage()->BitsPerSample); + + if ( index >= this->TotalColors ) + { + vtkErrorMacro("Color index has to be less than number of colors (" + << this->TotalColors << ")"); + return; + } + this->ColorRed = red_orig; + this->ColorGreen = green_orig; + this->ColorBlue = blue_orig; + + *red = *(red_orig + index); + *green = *(green_orig + index); + *blue = *(blue_orig + index); +} + +//------------------------------------------------------------------------- +void vtkTIFFReader::InitializeColors() +{ + this->ColorRed = 0; + this->ColorGreen = 0; + this->ColorBlue = 0; + this->TotalColors = -1; + this->ImageFormat = vtkTIFFReader::NOFORMAT; +} + +//------------------------------------------------------------------------- +template +void ReadTiledImage(vtkTIFFReader *self, void *out, + unsigned int width, + unsigned int height, + unsigned int vtkNotUsed(size), + int *internalExtents) +{ + TIFF *tiff; + uint32 tileWidth, tileLength, x, y, yi, rows, cols, tileSize; + int xx,yy; + int pixelDepth = self->GetInternalImage()->SamplesPerPixel; + T *image; + uint32 imagepos; + + image = (T*)out; + tiff = self->GetInternalImage()->Image; + TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tileWidth); + TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tileLength); + tileSize = TIFFTileSize(tiff); + tdata_t buffer = _TIFFmalloc(tileSize); + + for(yi=0;yi width - x) + { + cols = width-x; + } + else + { + cols = tileWidth; + } + if(tileLength > height - y) + { + rows = height - y; + } + else + { + rows = tileLength; + } + for(uint32 j = 0;j< rows;j++) + { + for(uint32 i=0;i= internalExtents[0] && + xx <= internalExtents[1] && + yy >= internalExtents[2] && + yy <= internalExtents[3] ) + { + imagepos = (xx + width*yy)*pixelDepth; + self->EvaluateImageAt(image+imagepos, static_cast(buffer)+tilepos); + } + } + } + } + } + _TIFFfree(buffer); +} + +//------------------------------------------------------------------------- +template +void ReadScanlineImage(vtkTIFFReader *self, void *out, + unsigned int vtkNotUsed(width), + unsigned height, + unsigned int vtkNotUsed(size), + int *internalExtents) +{ + unsigned int isize = TIFFScanlineSize(self->GetInternalImage()->Image); + unsigned int cc; + int row, inc; + int xx=0, yy=0; + tdata_t buf = _TIFFmalloc(isize); + T *image = (T *)out; + unsigned int c_inc = + self->GetInternalImage()->SamplesPerPixel; // * self->GetInternalImage()->BitsPerSample; + if ( self->GetInternalImage()->PlanarConfig == PLANARCONFIG_CONTIG ) + { + for ( row = height-1; row >= 0; row -- ) + { + if (TIFFReadScanline(self->GetInternalImage()->Image, buf, row, 0) <= 0) + { + cout << "Problem reading the row: " << row << endl; + break; + } + + for (cc = 0; cc < isize; cc += c_inc ) + { + if ( xx >= internalExtents[0] && + xx <= internalExtents[1] && + yy >= internalExtents[2] && + yy <= internalExtents[3] ) + { + //unsigned char *c = static_cast(buf)+cc; + inc = self->EvaluateImageAt( image, + static_cast(buf) + cc + ); + image += inc; + } + xx++; + } + xx=0; + yy++; + } + } + else + { + cout << "This reader can only do PLANARCONFIG_CONTIG" << endl; + } + + _TIFFfree(buf); +} + +//------------------------------------------------------------------------- +void vtkTIFFReader::ReadImageInternal( void* vtkNotUsed(in), void* outPtr, + int* outExt, + unsigned int size ) +{ + if ( this->GetInternalImage()->Compression == COMPRESSION_OJPEG ) + { + vtkErrorMacro("This reader cannot read old JPEG compression"); + return; + } + + int width = this->GetInternalImage()->Width; + int height = this->GetInternalImage()->Height; + this->InternalExtents = outExt; + + if ( !this->GetInternalImage()->CanRead() ) + { + uint32 *tempImage = static_cast( outPtr ); + + if ( this->InternalExtents[0] != 0 || + this->InternalExtents[1] != width -1 || + this->InternalExtents[2] != 0 || + this->InternalExtents[3] != height-1 ) + { + tempImage = new uint32[ width * height ]; + } + if ( !TIFFReadRGBAImage(this->GetInternalImage()->Image, + width, height, + tempImage, 0 ) ) + { + vtkErrorMacro("Problem reading RGB image"); + if ( tempImage != outPtr ) + { + delete [] tempImage; + } + + return; + } + int xx, yy; + uint32* ssimage = tempImage; + unsigned char *fimage = (unsigned char *)outPtr; + for ( yy = 0; yy < height; yy ++ ) + { + for ( xx = 0; xx < width; xx++ ) + { + if ( xx >= this->InternalExtents[0] && + xx <= this->InternalExtents[1] && + yy >= this->InternalExtents[2] && + yy <= this->InternalExtents[3] ) + { + unsigned char red = static_cast(TIFFGetR(*ssimage)); + unsigned char green = static_cast(TIFFGetG(*ssimage)); + unsigned char blue = static_cast(TIFFGetB(*ssimage)); + unsigned char alpha = static_cast(TIFFGetA(*ssimage)); + + *(fimage ) = red;//red; + *(fimage+1) = green;//green; + *(fimage+2) = blue;//blue; + *(fimage+3) = alpha;//alpha; + fimage += 4; + } + ssimage ++; + } + } + + if ( tempImage != 0 && tempImage != outPtr ) + { + delete [] tempImage; + } + return; + } + + unsigned int format = this->GetFormat(); + + + if ( this->GetInternalImage()->Compression == COMPRESSION_PACKBITS ) + { + height /= this->GetInternalImage()->BitsPerSample; + } + + switch ( format ) + { + case vtkTIFFReader::GRAYSCALE: + case vtkTIFFReader::RGB: + case vtkTIFFReader::PALETTE_RGB: + case vtkTIFFReader::PALETTE_GRAYSCALE: + if (TIFFIsTiled(this->GetInternalImage()->Image)) + { + switch(this->GetInternalImage()->BitsPerSample) + { + case 32: + ReadTiledImage(this, outPtr, width, height, size, this->InternalExtents); + break; + default: + ReadTiledImage(this, outPtr, width, height, size, this->InternalExtents); + + } + } + else + { + switch(this->GetInternalImage()->BitsPerSample) + { + case 32: + ReadScanlineImage(this, outPtr, width, height, size, this->InternalExtents); + break; + default: + ReadScanlineImage(this, outPtr, width, height, size, this->InternalExtents); + } + } + break; + default: + return; + } +} + +//------------------------------------------------------------------------- +int vtkTIFFReader::EvaluateImageAt( void* out, void* in ) +{ + unsigned char *image = (unsigned char *)out; + unsigned char *source = (unsigned char *)in; + int increment; + unsigned short red, green, blue, alpha; + switch ( this->GetFormat() ) + { + case vtkTIFFReader::GRAYSCALE: + if ( this->GetInternalImage()->Photometrics == PHOTOMETRIC_MINISBLACK ) + { + *image = *source; + } + else + { + *image = ~( *source ); + } + increment = 1; + break; + case vtkTIFFReader::PALETTE_GRAYSCALE: + this->GetColor(*source, &red, &green, &blue); + *image = static_cast(red >> 8); + increment = 1; + break; + case vtkTIFFReader::RGB: + red = *(source); + green = *(source+1); + blue = *(source+2); + *(image) = red; + *(image+1) = green; + *(image+2) = blue; + if ( this->GetInternalImage()->SamplesPerPixel == 4 ) + { + alpha = *(source+3); + *(image+3) = 255-alpha; + } + increment = this->GetInternalImage()->SamplesPerPixel; + break; + case vtkTIFFReader::PALETTE_RGB: + this->GetColor(*source, &red, &green, &blue); + *(image) = static_cast(red >> 8); + *(image+1) = static_cast(green >> 8); + *(image+2) = static_cast(blue >> 8); + increment = 3; + break; + default: + return 0; + } + + return increment; +} + +//------------------------------------------------------------------------- +int vtkTIFFReader::CanReadFile(const char* fname) +{ + vtkTIFFReaderInternal tf; + int res = tf.Open(fname); + tf.Clean(); + if (res) + { + return 3; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkTIFFReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkTIFFReader.h b/IO/vtkTIFFReader.h new file mode 100644 index 0000000..dc522cd --- /dev/null +++ b/IO/vtkTIFFReader.h @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTIFFReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTIFFReader - read TIFF files +// .SECTION Description +// vtkTIFFReader is a source object that reads TIFF files. +// It should be able to read almost any TIFF file +// +// .SECTION See Also +// vtkTIFFWriter + +#ifndef __vtkTIFFReader_h +#define __vtkTIFFReader_h + +#include "vtkImageReader2.h" + +//BTX +class vtkTIFFReaderInternal; +//ETX + +class VTK_IO_EXPORT vtkTIFFReader : public vtkImageReader2 +{ +public: + static vtkTIFFReader *New(); + vtkTypeRevisionMacro(vtkTIFFReader,vtkImageReader2); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Is the given file name a tiff file file? + virtual int CanReadFile(const char* fname); + + // Description: + // Get the file extensions for this format. + // Returns a string with a space separated list of extensions in + // the format .extension + virtual const char* GetFileExtensions() + { + return ".tif .tiff"; + } + + // Description: + // Return a descriptive name for the file format that might be useful + // in a GUI. + virtual const char* GetDescriptiveName() + { + return "TIFF"; + } + + // Description: + // Auxilary methods used by the reader internally. + void InitializeColors(); + + //BTX + enum { NOFORMAT, RGB, GRAYSCALE, PALETTE_RGB, PALETTE_GRAYSCALE, OTHER }; + + void ReadImageInternal( void *, void *outPtr, + int *outExt, unsigned int size ); + + // Description: + // Method to access internal image. Not to be used outside the class. + vtkTIFFReaderInternal *GetInternalImage() { return this->InternalImage; } + + int EvaluateImageAt( void*, void* ); + //ETX + +protected: + vtkTIFFReader(); + ~vtkTIFFReader(); + + void GetColor( int index, + unsigned short *r, unsigned short *g, unsigned short *b ); + unsigned int GetFormat(); + virtual void ExecuteInformation(); + virtual void ExecuteData(vtkDataObject *out); + +private: + vtkTIFFReader(const vtkTIFFReader&); // Not implemented. + void operator=(const vtkTIFFReader&); // Not implemented. + + unsigned short *ColorRed; + unsigned short *ColorGreen; + unsigned short *ColorBlue; + int TotalColors; + unsigned int ImageFormat; + vtkTIFFReaderInternal *InternalImage; + int *InternalExtents; +}; +#endif + + diff --git a/IO/vtkTIFFWriter.cxx b/IO/vtkTIFFWriter.cxx new file mode 100644 index 0000000..8285fc2 --- /dev/null +++ b/IO/vtkTIFFWriter.cxx @@ -0,0 +1,301 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTIFFWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTIFFWriter.h" + +#include "vtkErrorCode.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtk_tiff.h" + +vtkCxxRevisionMacro(vtkTIFFWriter, "$Revision: 1.39.6.1 $"); +vtkStandardNewMacro(vtkTIFFWriter); + +//---------------------------------------------------------------------------- +vtkTIFFWriter::vtkTIFFWriter() +{ + this->TIFFPtr = 0; + this->Compression = vtkTIFFWriter::PackBits; +}; + + +class vtkTIFFWriterIO +{ +public: + // Writing file no reading + static tsize_t TIFFRead(thandle_t, tdata_t, tsize_t) { return 0; } + + // Write data + static tsize_t TIFFWrite(thandle_t fd, tdata_t buf, tsize_t size) + { + ostream *out = reinterpret_cast(fd); + out->write(static_cast(buf), size); + return out->fail() ? static_cast(0) : size; + } + + static toff_t TIFFSeek(thandle_t fd, toff_t off, int whence) + { + ostream *out = reinterpret_cast(fd); + switch (whence) + { + case SEEK_SET: + out->seekp(off, ios::beg); + break; + case SEEK_END: + out->seekp(off, ios::end); + break; + case SEEK_CUR: + out->seekp(off, ios::cur); + break; + default: + return out->tellp(); + } + return out->tellp(); + } + + // File will be closed by the superclass + static int TIFFClose(thandle_t) { return 1; } + + static toff_t TIFFSize(thandle_t fd) + { + ostream *out = reinterpret_cast(fd); + out->seekp(0, ios::end); + return out->tellp(); + } + + static int TIFFMapFile(thandle_t, tdata_t*, toff_t*) { return (0); } + static void TIFFUnmapFile(thandle_t, tdata_t, toff_t) {} +}; + +//---------------------------------------------------------------------------- +void vtkTIFFWriter::WriteFileHeader(ofstream *file, vtkImageData *data) +{ + int dims[3]; + int width, height; + data->GetDimensions(dims); + int scomponents = data->GetNumberOfScalarComponents(); + int stype = data->GetScalarType(); + double resolution = -1; + uint32 rowsperstrip = (uint32) -1; + + int min0, min1, max0, max1, min2, max2; + + int bps; + switch (stype) + { + case VTK_CHAR: + case VTK_SIGNED_CHAR: + case VTK_UNSIGNED_CHAR: + bps = 8; + break; + case VTK_SHORT: + case VTK_UNSIGNED_SHORT: + bps = 16; + break; + case VTK_FLOAT: + bps = 32; + break; + default: + vtkErrorMacro(<< "Unsupported data type: " << data->GetScalarTypeAsString()); + this->SetErrorCode(vtkErrorCode::FileFormatError); + return; + } + + int predictor; + ostream* ost = file; + + // Find the length of the rows to write. + data->GetWholeExtent(min0, max0, min1, max1, min2, max2); + width = (max0 - min0 + 1); + height = (max1 - min1 + 1); + + TIFF* tif = TIFFClientOpen(this->GetFileName(), "w", + (thandle_t) ost, + reinterpret_cast(vtkTIFFWriterIO::TIFFRead), + reinterpret_cast(vtkTIFFWriterIO::TIFFWrite), + reinterpret_cast(vtkTIFFWriterIO::TIFFSeek), + reinterpret_cast(vtkTIFFWriterIO::TIFFClose), + reinterpret_cast(vtkTIFFWriterIO::TIFFSize), + reinterpret_cast(vtkTIFFWriterIO::TIFFMapFile), + reinterpret_cast(vtkTIFFWriterIO::TIFFUnmapFile) + ); + if ( !tif ) + { + this->TIFFPtr = 0; + return; + } + this->TIFFPtr = tif; + + uint32 w = width; + uint32 h = height; + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, w); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, h); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, scomponents); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); // Fix for stype + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + if(stype == VTK_FLOAT) + { + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); + } + + if ( scomponents > 3 ) + { + // if number of scalar components is greater than 3, that means we assume + // there is alpha. + uint16 extra_samples = scomponents-3; + uint16 *sample_info = new uint16[scomponents-3]; + sample_info[0]=EXTRASAMPLE_ASSOCALPHA; + int cc; + for ( cc = 1; cc < scomponents-3; cc ++ ) + { + sample_info[cc] = EXTRASAMPLE_UNSPECIFIED; + } + TIFFSetField(tif,TIFFTAG_EXTRASAMPLES,extra_samples, + sample_info); + delete [] sample_info; + } + + int compression; + switch ( this->Compression ) + { + case vtkTIFFWriter::PackBits: compression = COMPRESSION_PACKBITS; break; + case vtkTIFFWriter::JPEG: compression = COMPRESSION_JPEG; break; + case vtkTIFFWriter::Deflate: compression = COMPRESSION_DEFLATE; break; + case vtkTIFFWriter::LZW: compression = COMPRESSION_LZW; break; + default: compression = COMPRESSION_NONE; + } + //compression = COMPRESSION_JPEG; + TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); // Fix for compression + uint16 photometric = + (scomponents == 1 ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB); + if ( compression == COMPRESSION_JPEG ) + { + TIFFSetField(tif, TIFFTAG_JPEGQUALITY, 75); // Parameter + TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); + photometric = PHOTOMETRIC_YCBCR; + } + else if ( compression == COMPRESSION_LZW ) + { + predictor = 2; + TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor); + vtkErrorMacro("LZW compression is patented outside US so it is disabled"); + } + else if ( compression == COMPRESSION_DEFLATE ) + { + predictor = 2; + TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor); + } + + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric); // Fix for scomponents + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, + TIFFDefaultStripSize(tif, rowsperstrip)); + if (resolution > 0) + { + TIFFSetField(tif, TIFFTAG_XRESOLUTION, resolution); + TIFFSetField(tif, TIFFTAG_YRESOLUTION, resolution); + TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); + } +} + +//---------------------------------------------------------------------------- +void vtkTIFFWriter::WriteFile(ofstream *, vtkImageData *data, + int extent[6]) +{ + int idx1, idx2; + void *ptr; + + + // Make sure we actually have data. + if ( !data->GetPointData()->GetScalars()) + { + vtkErrorMacro(<< "Could not get data from input."); + return; + } + + TIFF* tif = reinterpret_cast(this->TIFFPtr); + if ( !tif ) + { + vtkErrorMacro("Problem writting trailer."); + this->SetErrorCode(vtkErrorCode::FileFormatError); + return; + } + + // take into consideration the scalar type + if( data->GetScalarType() != VTK_UNSIGNED_CHAR + && data->GetScalarType() != VTK_UNSIGNED_SHORT + && data->GetScalarType() != VTK_FLOAT + ) + { + vtkErrorMacro("TIFFWriter only accepts unsigned char/short or float scalars!"); + return; + } + + int row = 0; + for (idx2 = extent[4]; idx2 <= extent[5]; ++idx2) + { + for (idx1 = extent[3]; idx1 >= extent[2]; idx1--) + { + ptr = data->GetScalarPointer(extent[0], idx1, idx2); + if ( TIFFWriteScanline(tif, static_cast(ptr), row, 0) < 0) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + break; + } + row ++; + } + } +} + +//---------------------------------------------------------------------------- +void vtkTIFFWriter::WriteFileTrailer(ofstream *, vtkImageData *) +{ + TIFF* tif = reinterpret_cast(this->TIFFPtr); + if ( !tif ) + { + vtkErrorMacro("Problem writting trailer."); + this->SetErrorCode(vtkErrorCode::FileFormatError); + } + TIFFClose(tif); + this->TIFFPtr = 0; +} + +//---------------------------------------------------------------------------- +void vtkTIFFWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Compression: "; + if ( this->Compression == vtkTIFFWriter::PackBits ) + { + os << "Pack Bits\n"; + } + else if ( this->Compression == vtkTIFFWriter::JPEG ) + { + os << "JPEG\n"; + } + else if ( this->Compression == vtkTIFFWriter::Deflate ) + { + os << "Deflate\n"; + } + else if ( this->Compression == vtkTIFFWriter::LZW ) + { + os << "LZW\n"; + } + else //if ( this->Compression == vtkTIFFWriter::NoCompression ) + { + os << "No Compression\n"; + } +} diff --git a/IO/vtkTIFFWriter.h b/IO/vtkTIFFWriter.h new file mode 100644 index 0000000..c9dd05e --- /dev/null +++ b/IO/vtkTIFFWriter.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTIFFWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTIFFWriter - write out image data as a TIFF file +// .SECTION Description +// vtkTIFFWriter writes image data as a TIFF data file. Data can be written +// uncompressed or compressed. Several forms of compression are supported +// including packed bits, JPEG, deflation, and LZW. (Note: LZW compression +// is currently under patent in the US and is disabled until the patent +// expires. However, the mechanism for supporting this compression is available +// for those with a valid license or to whom the patent does not apply.) + +#ifndef __vtkTIFFWriter_h +#define __vtkTIFFWriter_h + +#include "vtkImageWriter.h" + +class VTK_IO_EXPORT vtkTIFFWriter : public vtkImageWriter +{ +public: + static vtkTIFFWriter *New(); + vtkTypeRevisionMacro(vtkTIFFWriter,vtkImageWriter); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +//BTX + enum { // Compression types + NoCompression, + PackBits, + JPEG, + Deflate, + LZW + }; +//ETX + + // Description: + // Set compression type. Sinze LZW compression is patented outside US, the + // additional work steps have to be taken in order to use that compression. + vtkSetClampMacro(Compression, int, NoCompression, LZW); + vtkGetMacro(Compression, int); + void SetCompressionToNoCompression() { this->SetCompression(NoCompression); } + void SetCompressionToPackBits() { this->SetCompression(PackBits); } + void SetCompressionToJPEG() { this->SetCompression(JPEG); } + void SetCompressionToDeflate() { this->SetCompression(Deflate); } + void SetCompressionToLZW() { this->SetCompression(LZW); } + +protected: + vtkTIFFWriter(); + ~vtkTIFFWriter() {} + + virtual void WriteFile(ofstream *file, vtkImageData *data, int ext[6]); + virtual void WriteFileHeader(ofstream *, vtkImageData *); + virtual void WriteFileTrailer(ofstream *, vtkImageData *); + + void* TIFFPtr; + int Compression; + +private: + vtkTIFFWriter(const vtkTIFFWriter&); // Not implemented. + void operator=(const vtkTIFFWriter&); // Not implemented. +}; + +#endif + diff --git a/IO/vtkUGFacetReader.cxx b/IO/vtkUGFacetReader.cxx new file mode 100644 index 0000000..2c8aacf --- /dev/null +++ b/IO/vtkUGFacetReader.cxx @@ -0,0 +1,388 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUGFacetReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUGFacetReader.h" + +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkMergePoints.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkShortArray.h" + +vtkCxxRevisionMacro(vtkUGFacetReader, "$Revision: 1.47 $"); +vtkStandardNewMacro(vtkUGFacetReader); + +// Construct object to extract all parts, and with point merging +// turned on. +vtkUGFacetReader::vtkUGFacetReader() +{ + this->FileName = NULL; + this->PartColors = NULL; + this->PartNumber = (-1); //extract all parts + + this->Merging = 1; + this->Locator = NULL; + + this->SetNumberOfInputPorts(0); +} + +vtkUGFacetReader::~vtkUGFacetReader() +{ + if ( this->FileName ) + { + delete [] this->FileName; + } + if ( this->PartColors ) + { + this->PartColors->Delete(); + } + if (this->Locator != NULL) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } +} + +// Overload standard modified time function. If locator is modified, +// then this object is modified as well. +unsigned long vtkUGFacetReader::GetMTime() +{ + unsigned long mTime1=this->Superclass::GetMTime(); + unsigned long mTime2; + + if (this->Locator) + { + mTime2 = this->Locator->GetMTime(); + mTime1 = ( mTime1 > mTime2 ? mTime1 : mTime2 ); + } + + return mTime1; +} + + +int vtkUGFacetReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + FILE *fp; + char header[36]; + struct {float v1[3], v2[3], v3[3], n1[3], n2[3], n3[3];} facet; + vtkIdType ptId[3]; + short ugiiColor, direction; + int numberTris, numFacetSets, setNumber, facetNumber; + vtkPoints *newPts, *mergedPts; + vtkFloatArray *newNormals, *mergedNormals; + vtkCellArray *newPolys, *mergedPolys; + fpos_t pos; + int triEstimate; + + vtkDebugMacro(<<"Reading UG facet file..."); + if ( this->FileName == NULL || strlen(this->FileName) == 0) + { + vtkErrorMacro(<<"No FileName specified...please specify one."); + return 0; + } + + // open the file + if ( (fp = fopen(this->FileName, "rb")) == NULL) + { + vtkErrorMacro(<<"Cannot open file specified."); + return 0; + } + + // read the header stuff + if ( fread (header, 1, 2, fp) <= 0 || + fread (&numFacetSets, 4, 1, fp) <= 0 || + fread (header, 1, 36, fp) <= 0 ) + { + vtkErrorMacro(<<"File ended prematurely"); + return 0; + } + + // swap bytes since this is a binary file format + vtkByteSwap::Swap4BE(&numFacetSets); + + // Estimate how much space we need - find out the size of the + // file and divide by 72 bytes per triangle + fgetpos( fp, &pos ); + fseek( fp, 0L, SEEK_END ); + triEstimate = ftell( fp ) / 72; + fsetpos( fp, &pos ); + + // allocate memory + if ( ! this->PartColors ) + { + this->PartColors = vtkShortArray::New(); + this->PartColors->Allocate(100); + } + else + { + this->PartColors->Reset(); + } + + newPts = vtkPoints::New(); + newPts->Allocate(triEstimate,triEstimate); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*triEstimate,3*triEstimate); + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(triEstimate,3),triEstimate); + + // loop over all facet sets, extracting triangles + for (setNumber=0; setNumber < numFacetSets; setNumber++) + { + + if ( fread (&ugiiColor, 2, 1, fp) <= 0 || + fread (&direction, 2, 1, fp) <= 0 || + fread (&numberTris, 4, 1, fp) <= 0 ) + { + vtkErrorMacro(<<"File ended prematurely"); + break; + } + + // swap bytes if necc + vtkByteSwap::Swap4BE(&numberTris); + vtkByteSwap::Swap2BERange(&ugiiColor,1); + vtkByteSwap::Swap2BERange(&direction,1); + + this->PartColors->InsertNextValue(ugiiColor); + + for (facetNumber=0; facetNumber < numberTris; facetNumber++) + { + if ( fread(&facet,72,1,fp) <= 0 ) + { + vtkErrorMacro(<<"File ended prematurely"); + break; + } + + // swap bytes if necc + vtkByteSwap::Swap4BERange((float *)(&facet),18); + + if ( this->PartNumber == -1 || this->PartNumber == setNumber ) + { + ptId[0] = newPts->InsertNextPoint(facet.v1); + ptId[1] = newPts->InsertNextPoint(facet.v2); + ptId[2] = newPts->InsertNextPoint(facet.v3); + + newNormals->InsertTuple(ptId[0],facet.n1); + newNormals->InsertTuple(ptId[1],facet.n2); + newNormals->InsertTuple(ptId[2],facet.n3); + + newPolys->InsertNextCell(3,ptId); + }//if appropriate part + }//for all facets in this set + }//for this facet set + + // update output + vtkDebugMacro(<<"Read " + << newPts->GetNumberOfPoints() << " points, " + << newPolys->GetNumberOfCells() << " triangles."); + + fclose(fp); + + // + // Merge points/triangles if requested + // + if ( this->Merging ) + { + int i; + vtkIdType *pts = 0; + vtkIdType nodes[3]; + vtkIdType npts; + double *x; + + mergedPts = vtkPoints::New(); + mergedPts->Allocate(newPts->GetNumberOfPoints()/3); + mergedNormals = vtkFloatArray::New(); + mergedNormals->SetNumberOfComponents(3); + mergedNormals->Allocate(newNormals->GetNumberOfTuples()); + mergedPolys = vtkCellArray::New(); + mergedPolys->Allocate(newPolys->GetSize()); + + if ( this->Locator == NULL ) + { + this->CreateDefaultLocator(); + } + this->Locator->InitPointInsertion (mergedPts, newPts->GetBounds()); + + for (newPolys->InitTraversal(); newPolys->GetNextCell(npts,pts); ) + { + for (i=0; i < 3; i++) + { + x = newPts->GetPoint(pts[i]); + if ( this->Locator->InsertUniquePoint(x, nodes[i]) ) + { + mergedNormals->InsertTuple(nodes[i],newNormals->GetTuple(pts[i])); + } + } + + if ( nodes[0] != nodes[1] && nodes[0] != nodes[2] && + nodes[1] != nodes[2] ) + { + mergedPolys->InsertNextCell(3,nodes); + } + } + + newPts->Delete(); + newNormals->Delete(); + newPolys->Delete(); + + vtkDebugMacro(<< "Merged to: " + << mergedPts->GetNumberOfPoints() << " points, " + << mergedPolys->GetNumberOfCells() << " triangles"); + } + else + { + mergedPts = newPts; + mergedNormals = newNormals; + mergedPolys = newPolys; + } +// +// Update ourselves +// + output->SetPoints(mergedPts); + mergedPts->Delete(); + + output->GetPointData()->SetNormals(mergedNormals); + mergedNormals->Delete(); + + output->SetPolys(mergedPolys); + mergedPolys->Delete(); + + if (this->Locator) + { + this->Locator->Initialize(); //free storage + } + + output->Squeeze(); + + return 1; +} + +int vtkUGFacetReader::GetNumberOfParts() +{ + char header[36]; + FILE *fp; + int numberOfParts; + + if ( this->FileName == NULL || strlen(this->FileName) == 0) + { + vtkErrorMacro(<<"No FileName specified...please specify one."); + return 0; + } + + // open the file + if ( (fp = fopen(this->FileName, "rb")) == NULL) + { + vtkErrorMacro(<<"Cannot open file specified."); + return 0; + } + + // read the header stuff + if ( fread (header, 1, 2, fp) <= 0 || + fread (&numberOfParts, 4, 1, fp) <= 0 || + fread (header, 1, 36, fp) <= 0 ) + { + vtkErrorMacro(<<"File ended prematurely"); + fclose(fp); + return 0; + } + + // swap bytes if necc + vtkByteSwap::Swap4BE(&numberOfParts); + + fclose(fp); + return numberOfParts; +} + +// Retrieve color index for the parts in the file. +short vtkUGFacetReader::GetPartColorIndex(int partId) +{ + if ( this->PartColors == NULL ) + { + this->Update(); + } + + if ( !this->PartColors || + partId < 0 || partId > this->PartColors->GetMaxId() ) + { + return 0; + } + else + { + return this->PartColors->GetValue(partId); + } +} + +// Specify a spatial locator for merging points. By +// default an instance of vtkMergePoints is used. +void vtkUGFacetReader::SetLocator(vtkPointLocator *locator) +{ + if ( this->Locator == locator ) + { + return; + } + if (this->Locator != NULL) + { + this->Locator->UnRegister(this); + this->Locator = NULL; + } + if (locator != NULL) + { + locator->Register(this); + } + this->Locator = locator; + this->Modified(); +} + +void vtkUGFacetReader::CreateDefaultLocator() +{ + if ( this->Locator == NULL ) + { + this->Locator = vtkMergePoints::New(); + } +} + +void vtkUGFacetReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "File Name: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + + os << indent << "Part Number: " << this->PartNumber << "\n"; + + os << indent << "Merging: " << (this->Merging ? "On\n" : "Off\n"); + if ( this->Locator ) + { + os << indent << "Locator: " << this->Locator << "\n"; + } + else + { + os << indent << "Locator: (none)\n"; + } +} diff --git a/IO/vtkUGFacetReader.h b/IO/vtkUGFacetReader.h new file mode 100644 index 0000000..454c6e7 --- /dev/null +++ b/IO/vtkUGFacetReader.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUGFacetReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUGFacetReader - read EDS Unigraphics facet files +// .SECTION Description +// vtkUGFacetReader is a source object that reads Unigraphics facet files. +// Unigraphics is a solid modeling system; facet files are the polygonal +// plot files it uses to create 3D plots. + +#ifndef __vtkUGFacetReader_h +#define __vtkUGFacetReader_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPointLocator; +class vtkShortArray; + +class VTK_IO_EXPORT vtkUGFacetReader : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkUGFacetReader,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object to extract all parts, and with point merging + // turned on. + static vtkUGFacetReader *New(); + + // Description: + // Overload standard modified time function. If locator is modified, + // then this object is modified as well. + unsigned long GetMTime(); + + // Description: + // Specify Unigraphics file name. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Special methods for interrogating the data file. + int GetNumberOfParts(); + + // Description: + // Retrieve color index for the parts in the file. + short GetPartColorIndex(int partId); + + // Description: + // Specify the desired part to extract. The part number must range between + // [0,NumberOfParts-1]. If the value is =(-1), then all parts will be + // extracted. If the value is <(-1), then no parts will be extracted but + // the part colors will be updated. + vtkSetMacro(PartNumber,int); + vtkGetMacro(PartNumber,int); + + // Description: + // Turn on/off merging of points/triangles. + vtkSetMacro(Merging,int); + vtkGetMacro(Merging,int); + vtkBooleanMacro(Merging,int); + + // Description: + // Specify a spatial locator for merging points. By + // default an instance of vtkMergePoints is used. + void SetLocator(vtkPointLocator *locator); + vtkGetObjectMacro(Locator,vtkPointLocator); + + // Description: + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(); + +protected: + vtkUGFacetReader(); + ~vtkUGFacetReader(); + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + char *FileName; + vtkShortArray *PartColors; + int PartNumber; + int Merging; + vtkPointLocator *Locator; +private: + vtkUGFacetReader(const vtkUGFacetReader&); // Not implemented. + void operator=(const vtkUGFacetReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkUnstructuredGridReader.cxx b/IO/vtkUnstructuredGridReader.cxx new file mode 100644 index 0000000..988e6c0 --- /dev/null +++ b/IO/vtkUnstructuredGridReader.cxx @@ -0,0 +1,403 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridReader.h" + +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridReader, "$Revision: 1.70 $"); +vtkStandardNewMacro(vtkUnstructuredGridReader); + +#ifdef read +#undef read +#endif + +vtkUnstructuredGridReader::vtkUnstructuredGridReader() +{ + vtkUnstructuredGrid *output = vtkUnstructuredGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +vtkUnstructuredGridReader::~vtkUnstructuredGridReader() +{ +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkUnstructuredGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkUnstructuredGridReader::GetOutput(int idx) +{ + return vtkUnstructuredGrid::SafeDownCast(this->GetOutputDataObject(idx)); +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridReader::SetOutput(vtkUnstructuredGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +// I do not think this should be here, but I do not want to remove it now. +int vtkUnstructuredGridReader::RequestUpdateExtent( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int piece, numPieces; + + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + // make sure piece is valid + if (piece < 0 || piece >= numPieces) + { + return 1; + } + + return 1; +} + +int vtkUnstructuredGridReader::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int i, numPts=0, numCells=0; + char line[256]; + int npts, size, ncells=0; + int piece, numPieces, skip1, read2, skip3, tmp; + vtkCellArray *cells=NULL; + int *types=NULL; + int done=0; + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int *tempArray; + vtkIdType *idArray; + + // All of the data in the first piece. + if (outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) + { + return 1; + } + + vtkDebugMacro(<<"Reading vtk unstructured grid..."); + + if (!this->OpenVTKFile() || !this->ReadHeader()) + { + return 1; + } + + // Read unstructured grid specific stuff + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) ) + { + // Make sure we're reading right type of geometry + // + if (!this->ReadString(line)) + { + vtkErrorMacro(<<"Data file ends prematurely!"); + this->CloseVTKFile (); + return 1; + } + + if ( strncmp(this->LowerCase(line),"unstructured_grid",17) ) + { + vtkErrorMacro(<< "Cannot read dataset type: " << line); + this->CloseVTKFile (); + return 1; + } + + // Might find points, cells, and cell types + // + while (!done) + { + if (!this->ReadString(line)) + { + break; + } + + if (! strncmp(this->LowerCase(line), "field", 5)) + { + vtkFieldData* fd = this->ReadFieldData(); + output->SetFieldData(fd); + fd->Delete(); // ? + } + else if ( ! strncmp(line, "points",6) ) + { + if (!this->Read(&numPts)) + { + vtkErrorMacro(<<"Cannot read number of points!"); + this->CloseVTKFile (); + return 1; + } + + if (!this->ReadPoints(output, numPts)) + { + this->CloseVTKFile (); + return 1; + } + } + + else if ( !strncmp(line,"cells",5)) + { + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + if (!(this->Read(&ncells) && this->Read(&size))) + { + vtkErrorMacro(<<"Cannot read cells!"); + this->CloseVTKFile (); + return 1; + } + + // the number of ints to read befor we get to the piece. + skip1 = piece * ncells / numPieces; + // the number of ints to read as part of piece. + read2 = ((piece+1) * ncells / numPieces) - skip1; + // the number of ints after the piece + skip3 = ncells - skip1 - read2; + + cells = vtkCellArray::New(); + + tempArray = new int[size]; + idArray = cells->WritePointer(ncells, size); + +// if (!this->ReadCells(size, cells->WritePointer(read2,size), +// skip1, read2, skip3) ) + if (!this->ReadCells(size, tempArray, skip1, read2, skip3) ) + { + this->CloseVTKFile (); + delete [] tempArray; + return 1; + } + + for (i = 0; i < size; i++) + { + idArray[i] = tempArray[i]; + } + delete [] tempArray; + + if (cells && types) + { + output->SetCells(types, cells); + } + } + + else if (!strncmp(line,"cell_types",10)) + { + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + if (!this->Read(&ncells)) + { + vtkErrorMacro(<<"Cannot read cell types!"); + this->CloseVTKFile (); + return 1; + } + // the number of ints to read befor we get to the piece. + skip1 = piece * ncells / numPieces; + // the number of ints to read as part of piece. + read2 = ((piece+1) * ncells / numPieces) - skip1; + // the number of ints after the piece + skip3 = ncells - skip1 - read2; + + //cerr << skip1 << " --- " << read2 << " --- " << skip3 << endl; + // allocate array for piece cell types + types = new int[read2]; + if (this->GetFileType() == VTK_BINARY) + { + // suck up newline + this->GetIStream()->getline(line,256); + // skip + if (skip1 != 0) + { + this->GetIStream() + ->seekg((long)sizeof(int)*skip1, ios::cur); + } + this->GetIStream()->read((char *)types,sizeof(int)*read2); + // skip + if (skip3 != 0) + { + this->GetIStream() + ->seekg((long)sizeof(int)*skip3, ios::cur); + } + + if (this->GetIStream()->eof()) + { + vtkErrorMacro(<<"Error reading binary cell types!"); + this->CloseVTKFile (); + return 1; + } + vtkByteSwap::Swap4BERange(types,read2); + } + else //ascii + { + // skip types before piece + for (i=0; iRead(&tmp)) + { + vtkErrorMacro(<<"Error reading cell types!"); + this->CloseVTKFile (); + return 1; + } + } + // read types for piece + for (i=0; iRead(types+i)) + { + vtkErrorMacro(<<"Error reading cell types!"); + this->CloseVTKFile (); + return 1; + } + } + // skip types after piece + for (i=0; iRead(&tmp)) + { + vtkErrorMacro(<<"Error reading cell types!"); + this->CloseVTKFile (); + return 1; + } + } + } + if ( cells && types ) + { + output->SetCells(types, cells); + } + } + + else if ( ! strncmp(line, "cell_data", 9) ) + { + if (!this->Read(&numCells)) + { + vtkErrorMacro(<<"Cannot read cell data!"); + this->CloseVTKFile (); + return 1; + } + + if ( ncells != numCells ) + { + vtkErrorMacro(<<"Number of cells don't match!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadCellData(output, ncells); + break; //out of this loop + } + + else if ( ! strncmp(line, "point_data", 10) ) + { + if (!this->Read(&npts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + + if ( npts != numPts ) + { + vtkErrorMacro(<<"Number of points don't match!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadPointData(output, npts); + break; //out of this loop + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + this->CloseVTKFile (); + return 1; + } + } + if ( ! output->GetPoints() ) vtkWarningMacro(<<"No points read!"); + //if ( ! (cells && types) ) vtkWarningMacro(<<"No topology read!"); + } + + else if ( !strncmp(line, "point_data", 10) ) + { + vtkWarningMacro(<<"No geometry defined in data file!"); + if (!this->Read(&numPts)) + { + vtkErrorMacro(<<"Cannot read point data!"); + this->CloseVTKFile (); + return 1; + } + + this->ReadPointData(output, numPts); + } + + else + { + vtkErrorMacro(<< "Unrecognized keyword: " << line); + } + + // Clean-up and get out + // + if (types) + { + delete [] types; + } + if (cells) + { + cells->Delete(); + } + + vtkDebugMacro(<<"Read " <GetNumberOfPoints() <<" points," + <GetNumberOfCells() <<" cells.\n"); + + this->CloseVTKFile (); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridReader::FillOutputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid"); + return 1; +} + +void vtkUnstructuredGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkUnstructuredGridReader.h b/IO/vtkUnstructuredGridReader.h new file mode 100644 index 0000000..af061b0 --- /dev/null +++ b/IO/vtkUnstructuredGridReader.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridReader - read vtk unstructured grid data file +// .SECTION Description +// vtkUnstructuredGridReader is a source object that reads ASCII or binary +// unstructured grid data files in vtk format. (see text for format details). +// The output of this reader is a single vtkUnstructuredGrid data object. +// The superclass of this class, vtkDataReader, provides many methods for +// controlling the reading of the data file, see vtkDataReader for more +// information. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// .SECTION See Also +// vtkUnstructuredGrid vtkDataReader + +#ifndef __vtkUnstructuredGridReader_h +#define __vtkUnstructuredGridReader_h + +#include "vtkDataReader.h" + +class vtkUnstructuredGrid; + +class VTK_IO_EXPORT vtkUnstructuredGridReader : public vtkDataReader +{ +public: + static vtkUnstructuredGridReader *New(); + vtkTypeRevisionMacro(vtkUnstructuredGridReader,vtkDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the output of this reader. + vtkUnstructuredGrid *GetOutput(); + vtkUnstructuredGrid *GetOutput(int idx); + void SetOutput(vtkUnstructuredGrid *output); + +protected: + vtkUnstructuredGridReader(); + ~vtkUnstructuredGridReader(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + // Since the Outputs[0] has the same UpdateExtent format + // as the generic DataObject we can copy the UpdateExtent + // as a default behavior. + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkUnstructuredGridReader(const vtkUnstructuredGridReader&); // Not implemented. + void operator=(const vtkUnstructuredGridReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkUnstructuredGridWriter.cxx b/IO/vtkUnstructuredGridWriter.cxx new file mode 100644 index 0000000..298e5e7 --- /dev/null +++ b/IO/vtkUnstructuredGridWriter.cxx @@ -0,0 +1,148 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridWriter.h" + +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +vtkCxxRevisionMacro(vtkUnstructuredGridWriter, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkUnstructuredGridWriter); + +void vtkUnstructuredGridWriter::WriteData() +{ + ostream *fp; + vtkUnstructuredGrid *input= vtkUnstructuredGrid::SafeDownCast( + this->GetInput()); + int *types, ncells, cellId; + + vtkDebugMacro(<<"Writing vtk unstructured grid data..."); + + if ( !(fp=this->OpenVTKFile()) || !this->WriteHeader(fp) ) + { + if (fp) + { + vtkErrorMacro("Ran out of disk space; deleting file: " + << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + } + return; + } + // + // Write unstructured grid specific stuff + // + *fp << "DATASET UNSTRUCTURED_GRID\n"; + + // Write data owned by the dataset + if (!this->WriteDataSetData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + if (!this->WritePoints(fp, input->GetPoints())) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + if (!this->WriteCells(fp, input->GetCells(),"CELLS")) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + // + // Cell types are a little more work + // + if ( input->GetCells() ) + { + ncells = input->GetCells()->GetNumberOfCells(); + types = new int[ncells]; + for (cellId=0; cellId < ncells; cellId++) + { + types[cellId] = input->GetCellType(cellId); + } + + *fp << "CELL_TYPES " << ncells << "\n"; + if ( this->FileType == VTK_ASCII ) + { + for (cellId=0; cellIdWriteCellData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + if (!this->WritePointData(fp, input)) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->CloseVTKFile(fp); + unlink(this->FileName); + return; + } + + this->CloseVTKFile(fp); +} + +int vtkUnstructuredGridWriter::FillInputPortInformation(int, + vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + +vtkUnstructuredGrid* vtkUnstructuredGridWriter::GetInput() +{ + return vtkUnstructuredGrid::SafeDownCast(this->Superclass::GetInput()); +} + +vtkUnstructuredGrid* vtkUnstructuredGridWriter::GetInput(int port) +{ + return vtkUnstructuredGrid::SafeDownCast(this->Superclass::GetInput(port)); +} + +void vtkUnstructuredGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/IO/vtkUnstructuredGridWriter.h b/IO/vtkUnstructuredGridWriter.h new file mode 100644 index 0000000..57d4692 --- /dev/null +++ b/IO/vtkUnstructuredGridWriter.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridWriter - write vtk unstructured grid data file +// .SECTION Description +// vtkUnstructuredGridWriter is a source object that writes ASCII or binary +// unstructured grid data files in vtk format. See text for format details. +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. + +#ifndef __vtkUnstructuredGridWriter_h +#define __vtkUnstructuredGridWriter_h + +#include "vtkDataWriter.h" +class vtkUnstructuredGrid; + +class VTK_IO_EXPORT vtkUnstructuredGridWriter : public vtkDataWriter +{ +public: + static vtkUnstructuredGridWriter *New(); + vtkTypeRevisionMacro(vtkUnstructuredGridWriter,vtkDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the input to this writer. + vtkUnstructuredGrid* GetInput(); + vtkUnstructuredGrid* GetInput(int port); + +protected: + vtkUnstructuredGridWriter() {}; + ~vtkUnstructuredGridWriter() {}; + + void WriteData(); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkUnstructuredGridWriter(const vtkUnstructuredGridWriter&); // Not implemented. + void operator=(const vtkUnstructuredGridWriter&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkVolume16Reader.cxx b/IO/vtkVolume16Reader.cxx new file mode 100644 index 0000000..aee8422 --- /dev/null +++ b/IO/vtkVolume16Reader.cxx @@ -0,0 +1,617 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolume16Reader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolume16Reader.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTransform.h" +#include "vtkUnsignedShortArray.h" + +vtkCxxRevisionMacro(vtkVolume16Reader, "$Revision: 1.56 $"); +vtkStandardNewMacro(vtkVolume16Reader); + +vtkCxxSetObjectMacro(vtkVolume16Reader,Transform,vtkTransform); + +// Construct object with NULL file prefix; file pattern "%s.%d"; image range +// set to (1,1); data origin (0,0,0); data spacing (1,1,1); no data mask; +// header size 0; and byte swapping turned off. +vtkVolume16Reader::vtkVolume16Reader() +{ + this->DataMask = 0x0000; + this->HeaderSize = 0; + this->SwapBytes = 0; + this->DataDimensions[0] = this->DataDimensions[1] = 0; + this->Transform = NULL; +} + +vtkVolume16Reader::~vtkVolume16Reader() +{ + this->SetTransform(NULL); +} + +void vtkVolume16Reader::SetDataByteOrderToBigEndian() +{ +#ifndef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +void vtkVolume16Reader::SetDataByteOrderToLittleEndian() +{ +#ifdef VTK_WORDS_BIGENDIAN + this->SwapBytesOn(); +#else + this->SwapBytesOff(); +#endif +} + +void vtkVolume16Reader::SetDataByteOrder(int byteOrder) +{ + if ( byteOrder == VTK_FILE_BYTE_ORDER_BIG_ENDIAN ) + { + this->SetDataByteOrderToBigEndian(); + } + else + { + this->SetDataByteOrderToLittleEndian(); + } +} + +int vtkVolume16Reader::GetDataByteOrder() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } +#else + if ( this->SwapBytes ) + { + return VTK_FILE_BYTE_ORDER_BIG_ENDIAN; + } + else + { + return VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN; + } +#endif +} + +const char *vtkVolume16Reader::GetDataByteOrderAsString() +{ +#ifdef VTK_WORDS_BIGENDIAN + if ( this->SwapBytes ) + { + return "LittleEndian"; + } + else + { + return "BigEndian"; + } +#else + if ( this->SwapBytes ) + { + return "BigEndian"; + } + else + { + return "LittleEndian"; + } +#endif +} + + +int vtkVolume16Reader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + int dim[3]; + + this->ComputeTransformedDimensions(dim); + + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_SHORT, 1); + outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3); + outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3); + // spacing and origin ? + + return 1; +} + +int vtkVolume16Reader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector)) +{ + int first, last; + int *dim; + int dimensions[3]; + double Spacing[3]; + double origin[3]; + + vtkImageData *output = this->AllocateOutputData(this->GetOutput()); + vtkUnsignedShortArray *newScalars = + vtkUnsignedShortArray::SafeDownCast(output->GetPointData()->GetScalars()); + + // Validate instance variables + if (this->FilePrefix == NULL) + { + vtkErrorMacro(<< "FilePrefix is NULL"); + return 1; + } + + if (this->HeaderSize < 0) + { + vtkErrorMacro(<< "HeaderSize " << this->HeaderSize << " must be >= 0"); + return 1; + } + + dim = this->DataDimensions; + + if (dim[0] <= 0 || dim[1] <= 0) + { + vtkErrorMacro(<< "x, y dimensions " << dim[0] << ", " << dim[1] + << "must be greater than 0."); + return 1; + } + + if ( (this->ImageRange[1]-this->ImageRange[0]) <= 0 ) + { + this->ReadImage(this->ImageRange[0], newScalars); + } + else + { + first = this->ImageRange[0]; + last = this->ImageRange[1]; + this->ReadVolume(first, last, newScalars); + } + + // calculate dimensions of output from data dimensions and transform + this->ComputeTransformedDimensions (dimensions); + output->SetDimensions(dimensions); + + // calculate spacing of output from data spacing and transform + this->ComputeTransformedSpacing(Spacing); + + // calculate origin of output from data origin and transform + this->ComputeTransformedOrigin(origin); + + // adjust spacing and origin if spacing is negative + this->AdjustSpacingAndOrigin(dimensions, Spacing, origin); + + output->SetSpacing(Spacing); + output->SetOrigin(origin); + + return 1; +} + +vtkImageData *vtkVolume16Reader::GetImage(int ImageNumber) +{ + vtkUnsignedShortArray *newScalars; + int *dim; + int dimensions[3]; + vtkImageData *result; + + // Validate instance variables + if (this->FilePrefix == NULL) + { + vtkErrorMacro(<< "FilePrefix is NULL"); + return NULL; + } + + if (this->HeaderSize < 0) + { + vtkErrorMacro(<< "HeaderSize " << this->HeaderSize << " must be >= 0"); + return NULL; + } + + dim = this->DataDimensions; + + if (dim[0] <= 0 || dim[1] <= 0) + { + vtkErrorMacro(<< "x, y dimensions " << dim[0] << ", " << dim[1] + << "must be greater than 0."); + return NULL; + } + + result = vtkImageData::New(); + newScalars = vtkUnsignedShortArray::New(); + this->ReadImage(ImageNumber, newScalars); + dimensions[0] = dim[0]; dimensions[1] = dim[1]; + dimensions[2] = 1; + result->SetDimensions(dimensions); + result->SetSpacing(this->DataSpacing); + result->SetOrigin(this->DataOrigin); + if ( newScalars ) + { + result->GetPointData()->SetScalars(newScalars); + newScalars->Delete(); + } + return result; +} + +// Read a slice of volume data. +void vtkVolume16Reader::ReadImage(int sliceNumber, + vtkUnsignedShortArray *scalars) +{ + unsigned short *pixels; + FILE *fp; + int numPts; + char filename[1024]; + + // build the file name. if there is no prefix, just use the slice number + if (this->FilePrefix) + { + sprintf (filename, this->FilePattern, this->FilePrefix, sliceNumber); + } + else + { + sprintf (filename, this->FilePattern, sliceNumber); + } + if ( !(fp = fopen(filename,"rb")) ) + { + vtkErrorMacro(<<"Can't open file: " << filename); + return; + } + + numPts = this->DataDimensions[0] * this->DataDimensions[1]; + + // get a pointer to the data + pixels = scalars->WritePointer(0, numPts); + + // read the image data + this->Read16BitImage (fp, pixels, this->DataDimensions[0], + this->DataDimensions[1], this->HeaderSize, + this->SwapBytes); + + // close the file + fclose (fp); +} + +// Read a volume of data. +void vtkVolume16Reader::ReadVolume(int first, int last, + vtkUnsignedShortArray *scalars) +{ + unsigned short *pixels; + unsigned short *slice; + FILE *fp; + int numPts; + int fileNumber; + int status; + int numberSlices = last - first + 1; + char filename[1024]; + int dimensions[3]; + int bounds[6]; + + // calculate the number of points per image + numPts = this->DataDimensions[0] * this->DataDimensions[1]; + + // compute transformed dimensions + this->ComputeTransformedDimensions (dimensions); + + // compute transformed bounds + this->ComputeTransformedBounds (bounds); + + // get memory for slice + slice = new unsigned short[numPts]; + + // get a pointer to the scalar data + pixels = scalars->WritePointer(0, numPts*numberSlices); + + vtkDebugMacro (<< "Creating scalars with " << numPts * numberSlices + << " points."); + + // build each file name and read the data from the file + for (fileNumber = first; fileNumber <= last; fileNumber++) + { + // build the file name. if there is no prefix, just use the slice number + if (this->FilePattern) + { + sprintf (filename, this->FilePattern, this->FilePrefix, fileNumber); + } + else + { + sprintf (filename, this->FilePattern, fileNumber); + } + if ( !(fp = fopen(filename,"rb")) ) + { + vtkErrorMacro(<<"Can't find file: " << filename); + return; + } + + vtkDebugMacro ( << "Reading " << filename ); + + // read the image data + status = this->Read16BitImage (fp, slice, this->DataDimensions[0], + this->DataDimensions[1], this->HeaderSize, this->SwapBytes); + + fclose (fp); + + if (status == 0) + { + break; + } + + // transform slice + this->TransformSlice (slice, pixels, fileNumber - first, dimensions, bounds); + } + + delete []slice; +} + +int vtkVolume16Reader:: Read16BitImage (FILE *fp, unsigned short *pixels, int xsize, + int ysize, int skip, int swapBytes) +{ + unsigned short *shortPtr; + int numShorts = xsize * ysize; + + if (skip) + { + fseek (fp, skip, 0); + } + + shortPtr = pixels; + shortPtr += xsize*(ysize - 1); + for (int j=0; jDataMask != 0x0000 ) + { + unsigned short *dataPtr = pixels; + int i; + for (i = 0; i < numShorts; i++, dataPtr++) + { + *dataPtr &= this->DataMask; + } + } + + return 1; +} + +void vtkVolume16Reader::ComputeTransformedSpacing (double Spacing[3]) +{ + if (!this->Transform) + { + memcpy (Spacing, this->DataSpacing, 3 * sizeof (double)); + } + else + { + double transformedSpacing[4]; + memcpy (transformedSpacing, this->DataSpacing, 3 * sizeof (double)); + transformedSpacing[3] = 1.0; + this->Transform->MultiplyPoint (transformedSpacing, transformedSpacing); + + for (int i = 0; i < 3; i++) + { + Spacing[i] = transformedSpacing[i]; + } + vtkDebugMacro("Transformed Spacing " << Spacing[0] << ", " << Spacing[1] << ", " << Spacing[2]); + } +} + +void vtkVolume16Reader::ComputeTransformedOrigin (double origin[3]) +{ + if (!this->Transform) + { + memcpy (origin, this->DataOrigin, 3 * sizeof (double)); + } + else + { + double transformedOrigin[4]; + memcpy (transformedOrigin, this->DataOrigin, 3 * sizeof (double)); + transformedOrigin[3] = 1.0; + this->Transform->MultiplyPoint (transformedOrigin, transformedOrigin); + + for (int i = 0; i < 3; i++) + { + origin[i] = transformedOrigin[i]; + } + vtkDebugMacro("Transformed Origin " << origin[0] << ", " << origin[1] << ", " << origin[2]); + } +} + +void vtkVolume16Reader::ComputeTransformedDimensions (int dimensions[3]) +{ + double transformedDimensions[4]; + if (!this->Transform) + { + dimensions[0] = this->DataDimensions[0]; + dimensions[1] = this->DataDimensions[1]; + dimensions[2] = this->ImageRange[1] - this->ImageRange[0] + 1; + } + else + { + transformedDimensions[0] = this->DataDimensions[0]; + transformedDimensions[1] = this->DataDimensions[1]; + transformedDimensions[2] = this->ImageRange[1] - this->ImageRange[0] + 1; + transformedDimensions[3] = 1.0; + this->Transform->MultiplyPoint (transformedDimensions, transformedDimensions); + dimensions[0] = (int) transformedDimensions[0]; + dimensions[1] = (int) transformedDimensions[1]; + dimensions[2] = (int) transformedDimensions[2]; + if (dimensions[0] < 0) + { + dimensions[0] = -dimensions[0]; + } + if (dimensions[1] < 0) + { + dimensions[1] = -dimensions[1]; + } + if (dimensions[2] < 0) + { + dimensions[2] = -dimensions[2]; + } + vtkDebugMacro(<< "Transformed dimensions are:" << dimensions[0] << ", " + << dimensions[1] << ", " + << dimensions[2]); + } +} + +void vtkVolume16Reader::ComputeTransformedBounds (int bounds[6]) +{ + double transformedBounds[4]; + + if (!this->Transform) + { + bounds[0] = 0; + bounds[1] = this->DataDimensions[0] - 1; + bounds[2] = 0; + bounds[3] = this->DataDimensions[1] - 1; + bounds[4] = 0; + bounds[5] = this->ImageRange[1] - this->ImageRange[0]; + } + else + { + transformedBounds[0] = 0; + transformedBounds[1] = 0; + transformedBounds[2] = 0; + transformedBounds[3] = 1.0; + this->Transform->MultiplyPoint (transformedBounds, transformedBounds); + bounds[0] = (int) transformedBounds[0]; + bounds[2] = (int) transformedBounds[1]; + bounds[4] = (int) transformedBounds[2]; + transformedBounds[0] = this->DataDimensions[0] - 1; + transformedBounds[1] = this->DataDimensions[1] - 1; + transformedBounds[2] = this->ImageRange[1] - this->ImageRange[0]; + transformedBounds[3] = 1.0; + this->Transform->MultiplyPoint (transformedBounds, transformedBounds); + bounds[1] = (int) transformedBounds[0]; + bounds[3] = (int) transformedBounds[1]; + bounds[5] = (int) transformedBounds[2]; + // put bounds in correct order + int tmp; + for (int i = 0; i < 6; i += 2) + { + if (bounds[i + 1] < bounds[i]) + { + tmp = bounds[i]; + bounds[i] = bounds[i + 1]; + bounds[i + 1] = tmp; + } + } + vtkDebugMacro(<< "Transformed bounds are: " + << bounds[0] << ", " << bounds[1] << ", " + << bounds[2] << ", " << bounds[3] << ", " + << bounds[4] << ", " << bounds[5]); + } +} + +void vtkVolume16Reader::AdjustSpacingAndOrigin (int dimensions[3], double Spacing[3], double origin[3]) +{ + for (int i = 0; i < 3; i++) + { + if (Spacing[i] < 0) + { + origin[i] = origin[i] + Spacing[i] * dimensions[i]; + Spacing[i] = -Spacing[i]; + } + } + vtkDebugMacro("Adjusted Spacing " << Spacing[0] << ", " << Spacing[1] << ", " << Spacing[2]); + vtkDebugMacro("Adjusted origin " << origin[0] << ", " << origin[1] << ", " << origin[2]); +} + +void vtkVolume16Reader::TransformSlice (unsigned short *slice, unsigned short *pixels, int k, int dimensions[3], int bounds[3]) +{ + int iSize = this->DataDimensions[0]; + int jSize = this->DataDimensions[1]; + + if (!this->Transform) + { + memcpy (pixels + iSize * jSize * k, slice, iSize * jSize * sizeof (unsigned short)); + } + else + { + double transformedIjk[4], ijk[4]; + int i, j; + int xyz[3]; + int index; + int xSize = dimensions[0]; + int xySize = dimensions[0] * dimensions[1]; + + // now move slice into pixels + + ijk[2] = k; + ijk[3] = 1.0; + for (j = 0; j < jSize; j++) + { + ijk[1] = j; + for (i = 0; i < iSize; i++, slice++) + { + ijk[0] = i; + this->Transform->MultiplyPoint (ijk, transformedIjk); + xyz[0] = (int) ((double)transformedIjk[0] - bounds[0]); + xyz[1] = (int) ((double)transformedIjk[1] - bounds[2]); + xyz[2] = (int) ((double)transformedIjk[2] - bounds[4]); + index = xyz[0] + + xyz[1] * xSize + + xyz[2] * xySize; + *(pixels + index) = *slice; + } + } + } +} + +void vtkVolume16Reader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "HeaderSize: " << this->HeaderSize << "\n"; + os << indent << "SwapBytes: " << this->SwapBytes << "\n"; + os << indent << "Data Dimensions: (" << this->DataDimensions[0] << ", " + << this->DataDimensions[1] << ")\n"; + os << indent << "Data Mask: " << this->DataMask << "\n"; + + if ( this->Transform ) + { + os << indent << "Transform:\n"; + this->Transform->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Transform: (None)\n"; + } +} diff --git a/IO/vtkVolume16Reader.h b/IO/vtkVolume16Reader.h new file mode 100644 index 0000000..8d83fab --- /dev/null +++ b/IO/vtkVolume16Reader.h @@ -0,0 +1,150 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolume16Reader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolume16Reader - read 16 bit image files +// .SECTION Description +// vtkVolume16Reader is a source object that reads 16 bit image files. +// +// Volume16Reader creates structured point datasets. The dimension of the +// dataset depends upon the number of files read. Reading a single file +// results in a 2D image, while reading more than one file results in a +// 3D volume. +// +// File names are created using FilePattern and FilePrefix as follows: +// sprintf (filename, FilePattern, FilePrefix, number); +// where number is in the range ImageRange[0] to ImageRange[1]. If +// ImageRange[1] <= ImageRange[0], then slice number ImageRange[0] is +// read. Thus to read an image set ImageRange[0] = ImageRange[1] = slice +// number. The default behavior is to read a single file (i.e., image slice 1). +// +// The DataMask instance variable is used to read data files with imbedded +// connectivity or segmentation information. For example, some data has +// the high order bit set to indicate connected surface. The DataMask allows +// you to select this data. Other important ivars include HeaderSize, which +// allows you to skip over initial info, and SwapBytes, which turns on/off +// byte swapping. +// +// The Transform instance variable specifies a permutation transformation +// to map slice space into world space. vtkImageReader has replaced the +// functionality of this class and should be used instead. + +// .SECTION See Also +// vtkSliceCubes vtkMarchingCubes vtkImageReader + +#ifndef __vtkVolume16Reader_h +#define __vtkVolume16Reader_h + +#include "vtkVolumeReader.h" + +class vtkTransform; +class vtkUnsignedCharArray; +class vtkUnsignedShortArray; + +#define VTK_FILE_BYTE_ORDER_BIG_ENDIAN 0 +#define VTK_FILE_BYTE_ORDER_LITTLE_ENDIAN 1 + +class VTK_IO_EXPORT vtkVolume16Reader : public vtkVolumeReader +{ +public: + vtkTypeRevisionMacro(vtkVolume16Reader,vtkVolumeReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with NULL file prefix; file pattern "%s.%d"; image range + // set to (1,1); data origin (0,0,0); data spacing (1,1,1); no data mask; + // header size 0; and byte swapping turned off. + static vtkVolume16Reader *New(); + + // Description: + // Specify the dimensions for the data. + vtkSetVector2Macro(DataDimensions,int); + vtkGetVectorMacro(DataDimensions,int,2); + + // Description: + // Specify a mask used to eliminate data in the data file (e.g., + // connectivity bits). + vtkSetMacro(DataMask,unsigned short); + vtkGetMacro(DataMask,unsigned short); + + // Description: + // Specify the number of bytes to seek over at start of image. + vtkSetMacro(HeaderSize,int); + vtkGetMacro(HeaderSize,int); + + // Description: + // These methods should be used instead of the SwapBytes methods. + // They indicate the byte ordering of the file you are trying + // to read in. These methods will then either swap or not swap + // the bytes depending on the byte ordering of the machine it is + // being run on. For example, reading in a BigEndian file on a + // BigEndian machine will result in no swapping. Trying to read + // the same file on a LittleEndian machine will result in swapping. + // As a quick note most UNIX machines are BigEndian while PC's + // and VAX tend to be LittleEndian. So if the file you are reading + // in was generated on a VAX or PC, SetDataByteOrderToLittleEndian otherwise + // SetDataByteOrderToBigEndian. + void SetDataByteOrderToBigEndian(); + void SetDataByteOrderToLittleEndian(); + int GetDataByteOrder(); + void SetDataByteOrder(int); + const char *GetDataByteOrderAsString(); + + // Description: + // Turn on/off byte swapping. + vtkSetMacro(SwapBytes,int); + vtkGetMacro(SwapBytes,int); + vtkBooleanMacro(SwapBytes,int); + + // Description: + // Set/Get transformation matrix to transform the data from slice space + // into world space. This matrix must be a permutation matrix. To qualify, + // the sums of the rows must be + or - 1. + virtual void SetTransform(vtkTransform*); + vtkGetObjectMacro(Transform,vtkTransform); + + // Description: + // Other objects make use of these methods + vtkImageData *GetImage(int ImageNumber); + +protected: + vtkVolume16Reader(); + ~vtkVolume16Reader(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int DataDimensions[2]; + unsigned short DataMask; + int SwapBytes; + int HeaderSize; + vtkTransform *Transform; + + void TransformSlice (unsigned short *slice, unsigned short *pixels, int k, int dimensions[3], int bounds[3]); + void ComputeTransformedDimensions(int dimensions[3]); + void ComputeTransformedBounds(int bounds[6]); + void ComputeTransformedSpacing(double Spacing[3]); + void ComputeTransformedOrigin(double origin[3]); + void AdjustSpacingAndOrigin(int dimensions[3], double Spacing[3], double origin[3]); + void ReadImage(int ImageNumber, vtkUnsignedShortArray *); + void ReadVolume(int FirstImage, int LastImage, vtkUnsignedShortArray *); + int Read16BitImage(FILE *fp, unsigned short *pixels, int xsize, int ysize, + int skip, int swapBytes); + +private: + vtkVolume16Reader(const vtkVolume16Reader&); // Not implemented. + void operator=(const vtkVolume16Reader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkVolumeReader.cxx b/IO/vtkVolumeReader.cxx new file mode 100644 index 0000000..d47e66e --- /dev/null +++ b/IO/vtkVolumeReader.cxx @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeReader.h" + +vtkCxxRevisionMacro(vtkVolumeReader, "$Revision: 1.22 $"); + +// Construct object with NULL file prefix; file pattern "%s.%d"; image range +// set to (1,1); +vtkVolumeReader::vtkVolumeReader() +{ + this->FilePrefix = NULL; + this->FilePattern = new char[strlen("%s.%d") + 1]; + strcpy (this->FilePattern, "%s.%d"); + this->ImageRange[0] = this->ImageRange[1] = 1; + this->DataOrigin[0] = this->DataOrigin[1] = this->DataOrigin[2] = 0.0; + this->DataSpacing[0] = this->DataSpacing[1] = this->DataSpacing[2] = 1.0; + this->SetNumberOfInputPorts(0); +} + +vtkVolumeReader::~vtkVolumeReader () +{ + if (this->FilePrefix) + { + delete [] this->FilePrefix; + } + + delete [] this->FilePattern; +} + +void vtkVolumeReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Data Origin: (" << this->DataOrigin[0] << ", " + << this->DataOrigin[1] << ", " + << this->DataOrigin[2] << ")\n"; + os << indent << "Data Spacing: (" << this->DataSpacing[0] << ", " + << this->DataSpacing[1] << ", " + << this->DataSpacing[2] << ")\n"; + os << indent << "FilePrefix: " << (this->FilePrefix ? this->FilePrefix : "(none)") << "\n"; + os << indent << "FilePattern: " << (this->FilePattern ? this->FilePattern : "(none)") << "\n"; + os << indent << "Image Range: (" << this->ImageRange[0] << ", " + << this->ImageRange[1] << ")\n"; +} diff --git a/IO/vtkVolumeReader.h b/IO/vtkVolumeReader.h new file mode 100644 index 0000000..012de1b --- /dev/null +++ b/IO/vtkVolumeReader.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeReader - read image files +// .SECTION Description +// vtkVolumeReader is a source object that reads image files. +// +// VolumeReader creates structured point datasets. The dimension of the +// dataset depends upon the number of files read. Reading a single file +// results in a 2D image, while reading more than one file results in a +// 3D volume. +// +// File names are created using FilePattern and FilePrefix as follows: +// sprintf (filename, FilePattern, FilePrefix, number); +// where number is in the range ImageRange[0] to ImageRange[1]. If +// ImageRange[1] <= ImageRange[0], then slice number ImageRange[0] is +// read. Thus to read an image set ImageRange[0] = ImageRange[1] = slice +// number. The default behavior is to read a single file (i.e., image slice 1). +// +// The DataMask instance variable is used to read data files with imbedded +// connectivity or segmentation information. For example, some data has +// the high order bit set to indicate connected surface. The DataMask allows +// you to select this data. Other important ivars include HeaderSize, which +// allows you to skip over initial info, and SwapBytes, which turns on/off +// byte swapping. Consider using vtkImageReader as a replacement. + +// .SECTION See Also +// vtkSliceCubes vtkMarchingCubes vtkPNMReader vtkVolume16Reader +// vtkImageReader + +#ifndef __vtkVolumeReader_h +#define __vtkVolumeReader_h + +#include "vtkImageAlgorithm.h" + +class VTK_IO_EXPORT vtkVolumeReader : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkVolumeReader,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify file prefix for the image file(s). + vtkSetStringMacro(FilePrefix); + vtkGetStringMacro(FilePrefix); + + // Description: + // The sprintf format used to build filename from FilePrefix and number. + vtkSetStringMacro(FilePattern); + vtkGetStringMacro(FilePattern); + + // Description: + // Set the range of files to read. + vtkSetVector2Macro(ImageRange,int); + vtkGetVectorMacro(ImageRange,int,2); + + // Description: + // Specify the spacing for the data. + vtkSetVector3Macro(DataSpacing,double); + vtkGetVectorMacro(DataSpacing,double,3); + + // Description: + // Specify the origin for the data. + vtkSetVector3Macro(DataOrigin,double); + vtkGetVectorMacro(DataOrigin,double,3); + + // Description: + // Other objects make use of this method. + virtual vtkImageData *GetImage(int ImageNumber) = 0; + +protected: + vtkVolumeReader(); + ~vtkVolumeReader(); + + char *FilePrefix; + char *FilePattern; + int ImageRange[2]; + double DataSpacing[3]; + double DataOrigin[3]; +private: + vtkVolumeReader(const vtkVolumeReader&); // Not implemented. + void operator=(const vtkVolumeReader&); // Not implemented. +}; + +#endif + + diff --git a/IO/vtkWriter.cxx b/IO/vtkWriter.cxx new file mode 100644 index 0000000..a0163e1 --- /dev/null +++ b/IO/vtkWriter.cxx @@ -0,0 +1,195 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWriter.h" + +#include "vtkCommand.h" +#include "vtkDataObject.h" +#include "vtkDemandDrivenPipeline.h" +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" + +vtkCxxRevisionMacro(vtkWriter, "$Revision: 1.43 $"); + +// Construct with no start and end write methods or arguments. +vtkWriter::vtkWriter() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(0); +} + +vtkWriter::~vtkWriter() +{ +} + +void vtkWriter::SetInput(vtkDataObject *input) +{ + this->SetInput(0, input); +} + +void vtkWriter::SetInput(int index, vtkDataObject *input) +{ + if (input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input remove the connection. + this->SetInputConnection(index, 0); + } +} + +vtkDataObject *vtkWriter::GetInput() +{ + return this->GetInput(0); +} + +vtkDataObject *vtkWriter::GetInput(int port) +{ + if (this->GetNumberOfInputConnections(port) < 1) + { + return NULL; + } + return this->GetExecutive()->GetInputData(port, 0); +} + + +// Write data to output. Method executes subclasses WriteData() method, as +// well as StartMethod() and EndMethod() methods. +int vtkWriter::Write() +{ + // Make sure we have input. + if (this->GetNumberOfInputConnections(0) < 1) + { + vtkErrorMacro("No input provided!"); + return 0; + } + + // always write even if the data hasn't changed + this->Modified(); + this->UpdateWholeExtent(); + return 1; +} + +int vtkWriter::ProcessRequest(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +int vtkWriter::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *) +{ + this->SetErrorCode(vtkErrorCode::NoError); + + vtkDataObject *input = this->GetInput(); + int idx; + + // make sure input is available + if ( !input ) + { + vtkErrorMacro(<< "No input!"); + return 0; + } + + for (idx = 0; idx < this->GetNumberOfInputPorts(); ++idx) + { + if (this->GetInput(idx) != NULL) + { + this->GetInput(idx)->Update(); + } + } + + unsigned long lastUpdateTime = this->GetInput(0)->GetUpdateTime(); + for (idx = 1; idx < this->GetNumberOfInputPorts(); ++idx) + { + unsigned long updateTime = this->GetInput(idx)->GetUpdateTime(); + if ( updateTime > lastUpdateTime ) + { + lastUpdateTime = updateTime; + } + } + + if (lastUpdateTime < this->WriteTime && this->GetMTime() < this->WriteTime) + { + // we are up to date + return 1; + } + + this->InvokeEvent(vtkCommand::StartEvent,NULL); + this->WriteData(); + this->InvokeEvent(vtkCommand::EndEvent,NULL); + + // Release any inputs if marked for release + for (idx = 0; idx < this->GetNumberOfInputPorts(); ++idx) + { + if (this->GetInput(idx) && this->GetInput(idx)->ShouldIReleaseData()) + { + this->GetInput(idx)->ReleaseData(); + } + } + + this->WriteTime.Modified(); + + return 1; +} + +void vtkWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + +} + +void vtkWriter::EncodeArrayName(char* resname, const char* name) +{ + if ( !name || !resname ) + { + return; + } + int cc = 0; + ostrstream str; + + char buffer[10]; + + while( name[cc] ) + { + // Encode spaces and %'s (and most non-printable ascii characters) + // The reader does not support spaces in array names. + if ( name[cc] < 33 || name[cc] > 126 || + name[cc] == '\"' || name[cc] == '%' ) + { + sprintf(buffer, "%2X", name[cc]); + str << "%%" << buffer; // Two % because it goes through printf format + } + else + { + str << name[cc]; + } + cc++; + } + str << ends; + strcpy(resname, str.str()); + str.rdbuf()->freeze(0); +} diff --git a/IO/vtkWriter.h b/IO/vtkWriter.h new file mode 100644 index 0000000..b914948 --- /dev/null +++ b/IO/vtkWriter.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWriter - abstract class to write data to file(s) +// .SECTION Description +// vtkWriter is an abstract class for mapper objects that write their data +// to disk (or into a communications port). All writers respond to Write() +// method. This method insures that there is input and input is up to date. +// +// Since vtkWriter is a subclass of vtkProcessObject, StartMethod(), +// EndMethod(), and ProgressMethod() are all available to writers. +// These methods are executed before and after execution of the Write() +// method. You can also specify arguments to these methods. + +// .SECTION Caveats +// Every subclass of vtkWriter must implement a WriteData() method. Most likely +// will have to create SetInput() method as well. + +// .SECTION See Also +// vtkBYUWriter vtkDataWriter vtkSTLWriter vtkVoxelWriter vtkMCubesWriter + +#ifndef __vtkWriter_h +#define __vtkWriter_h + +#include "vtkAlgorithm.h" + +class vtkDataObject; + +#define VTK_ASCII 1 +#define VTK_BINARY 2 + +class VTK_IO_EXPORT vtkWriter : public vtkAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkWriter,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Write data to output. Method executes subclasses WriteData() method, as + // well as StartMethod() and EndMethod() methods. + // Returns 1 on success and 0 on failure. + virtual int Write(); + + // Description: + // Encode the name so that the reader will not have problems. + // The resulting string is up to four time the size of the input + // string. + void EncodeArrayName(char* resname, const char* name); + + // Description: + // Set/get the input to this writer. + void SetInput(vtkDataObject *input); + void SetInput(int index, vtkDataObject *input); +//BTX + vtkDataObject *GetInput(); + vtkDataObject *GetInput(int port); +//ETX + +protected: + vtkWriter(); + ~vtkWriter(); + + virtual int ProcessRequest(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + + virtual void WriteData() = 0; //internal method subclasses must respond to + vtkTimeStamp WriteTime; +private: + vtkWriter(const vtkWriter&); // Not implemented. + void operator=(const vtkWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLDataElement.cxx b/IO/vtkXMLDataElement.cxx new file mode 100644 index 0000000..38a8e39 --- /dev/null +++ b/IO/vtkXMLDataElement.cxx @@ -0,0 +1,958 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLDataElement.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLDataElement.h" + +#include "vtkObjectFactory.h" +#include "vtkXMLDataParser.h" +#include "vtkXMLUtilities.h" + +#include + +vtkCxxRevisionMacro(vtkXMLDataElement, "$Revision: 1.24 $"); +vtkStandardNewMacro(vtkXMLDataElement); + +//---------------------------------------------------------------------------- +vtkXMLDataElement::vtkXMLDataElement() +{ + this->Name = 0; + this->Id = 0; + this->Parent = 0; + + this->NumberOfAttributes = 0; + this->AttributesSize = 5; + this->AttributeNames = new char*[this->AttributesSize]; + this->AttributeValues = new char*[this->AttributesSize]; + + this->NumberOfNestedElements = 0; + this->NestedElementsSize = 10; + this->NestedElements = new vtkXMLDataElement*[this->NestedElementsSize]; + + this->InlineDataPosition = 0; + this->XMLByteIndex = 0; + + this->AttributeEncoding = VTK_ENCODING_UTF_8; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement::~vtkXMLDataElement() +{ + this->SetName(0); + this->SetId(0); + + this->RemoveAllAttributes(); + delete [] this->AttributeNames; + delete [] this->AttributeValues; + + this->RemoveAllNestedElements(); + delete [] this->NestedElements; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::RemoveAllAttributes() +{ + for(int i = 0; i < this->NumberOfAttributes; ++i) + { + delete [] this->AttributeNames[i]; + delete [] this->AttributeValues[i]; + } + this->NumberOfAttributes = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::RemoveAllNestedElements() +{ + for(int i = 0; i < this->NumberOfNestedElements; ++i) + { + this->NestedElements[i]->UnRegister(this); + } + this->NumberOfNestedElements = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::ReadXMLAttributes(const char** atts, int encoding) +{ + if(atts) + { + // If the target encoding is VTK_ENCODING_NONE or VTK_ENCODING_UNKNOWN, + // then keep the internal/default encoding, otherwise encode each + // attribute using that new format + + if (encoding != VTK_ENCODING_NONE && encoding != VTK_ENCODING_UNKNOWN) + { + this->SetAttributeEncoding(encoding); + } + + // Process each attributes returned by Expat in UTF-8 encoding, and + // convert them to our encoding + + for (int i = 0; atts[i] && atts[i + 1]; i += 2) + { + if (this->GetAttributeEncoding() == VTK_ENCODING_UTF_8) + { + this->SetAttribute(atts[i], atts[i + 1]); + } + else + { + ostrstream str; + vtkXMLUtilities::EncodeString( + atts[i+1], VTK_ENCODING_UTF_8, str, this->GetAttributeEncoding(), 0); + str << ends; + this->SetAttribute(atts[i], str.str()); + str.rdbuf()->freeze(0); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetAttribute(const char *name, const char *value) +{ + if (!name || !name[0] || !value || !value[0]) + { + return; + } + + int i; + + // Set an existing attribute + + for(i = 0; i < this->NumberOfAttributes; ++i) + { + if(!strcmp(this->AttributeNames[i], name)) + { + delete [] this->AttributeValues[i]; + this->AttributeValues[i] = new char [strlen(value) + 1]; + strcpy(this->AttributeValues[i], value); + return; + } + } + + // Or add an attribute + + if (this->NumberOfAttributes == this->AttributesSize) + { + int newSize = this->AttributesSize * 2; + char **newAttributeNames = new char* [newSize]; + char **newAttributeValues = new char* [newSize]; + for(i = 0; i < this->NumberOfAttributes; ++i) + { + newAttributeNames[i] = new char [strlen(this->AttributeNames[i]) + 1]; + strcpy(newAttributeNames[i], this->AttributeNames[i]); + delete [] this->AttributeNames[i]; + newAttributeValues[i] = new char [strlen(this->AttributeValues[i]) + 1]; + strcpy(newAttributeValues[i], this->AttributeValues[i]); + delete [] this->AttributeValues[i]; + } + delete [] this->AttributeNames; + delete [] this->AttributeValues; + this->AttributeNames = newAttributeNames; + this->AttributeValues = newAttributeValues; + this->AttributesSize = newSize; + } + + i = this->NumberOfAttributes++; + this->AttributeNames[i] = new char [strlen(name) + 1]; + strcpy(this->AttributeNames[i], name); + this->AttributeValues[i] = new char [strlen(value) + 1]; + strcpy(this->AttributeValues[i], value); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::AddNestedElement(vtkXMLDataElement* element) +{ + if (!element) + { + return; + } + + if(this->NumberOfNestedElements == this->NestedElementsSize) + { + int i; + int newSize = this->NestedElementsSize*2; + vtkXMLDataElement** newNestedElements = new vtkXMLDataElement*[newSize]; + for(i=0;i < this->NumberOfNestedElements;++i) + { + newNestedElements[i] = this->NestedElements[i]; + } + delete [] this->NestedElements; + this->NestedElements = newNestedElements; + this->NestedElementsSize = newSize; + } + + int index = this->NumberOfNestedElements++; + this->NestedElements[index] = element; + element->Register(this); + element->SetParent(this); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::RemoveNestedElement(vtkXMLDataElement* element) +{ + if (!element) + { + return; + } + + int i, j; + for(i = 0; i < this->NumberOfNestedElements; ++i) + { + if (this->NestedElements[i] == element) + { + for (j = i; j < this->NumberOfNestedElements - 1; ++j) + { + this->NestedElements[j] = this->NestedElements[j + 1]; + } + element->UnRegister(this); + this->NumberOfNestedElements--; + } + } +} + +//---------------------------------------------------------------------------- +const char* vtkXMLDataElement::GetAttribute(const char* name) +{ + if (!name) + { + return 0; + } + + int i; + for(i=0; i < this->NumberOfAttributes;++i) + { + if(strcmp(this->AttributeNames[i], name) == 0) + { + return this->AttributeValues[i]; + } + } + return 0; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLDataElement::GetAttributeName(int idx) +{ + if (idx < 0 || idx >= this->NumberOfAttributes) + { + return 0; + } + + return this->AttributeNames[idx]; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLDataElement::GetAttributeValue(int idx) +{ + if (idx < 0 || idx >= this->NumberOfAttributes) + { + return 0; + } + + return this->AttributeValues[idx]; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::PrintXML(ostream& os, vtkIndent indent) +{ + os << indent << "<" << this->Name; + int i; + for(i=0;i < this->NumberOfAttributes;++i) + { + os << " " << this->AttributeNames[i] + << "=\"" << this->AttributeValues[i] << "\""; + } + if(this->NumberOfNestedElements > 0) + { + os << ">\n"; + for(i=0;i < this->NumberOfNestedElements;++i) + { + vtkIndent nextIndent = indent.GetNextIndent(); + this->NestedElements[i]->PrintXML(os, nextIndent); + } + os << indent << "Name << ">\n"; + } + else + { + os << "/>\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetParent(vtkXMLDataElement* parent) +{ + this->Parent = parent; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::GetParent() +{ + return this->Parent; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::GetRoot() +{ + if (!this->Parent) + { + return this; + } + return this->Parent->GetRoot(); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetNumberOfNestedElements() +{ + return this->NumberOfNestedElements; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::GetNestedElement(int index) +{ + if (index >=0 && index < this->NumberOfNestedElements) + { + return this->NestedElements[index]; + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::FindNestedElementWithName(const char* name) +{ + if (!name) + { + return 0; + } + + int i; + for(i=0;i < this->NumberOfNestedElements;++i) + { + const char* nname = this->NestedElements[i]->GetName(); + if(nname && (strcmp(nname, name) == 0)) + { + return this->NestedElements[i]; + } + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::FindNestedElementWithNameAndId( + const char* name, const char* id) +{ + if (!name || !id) + { + return 0; + } + + int i; + for(i=0;i < this->NumberOfNestedElements;++i) + { + const char* nname = this->NestedElements[i]->GetName(); + const char* nid = this->NestedElements[i]->GetId(); + if(nname && nid && (strcmp(nname, name) == 0) && (strcmp(nid, id) == 0)) + { + return this->NestedElements[i]; + } + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::FindNestedElementWithNameAndAttribute( + const char* name, const char* att_name, const char* att_value) +{ + if (!name || !att_name || !att_value) + { + return 0; + } + + int i; + for(i=0;i < this->NumberOfNestedElements;++i) + { + const char* nname = this->NestedElements[i]->GetName(); + if(nname && (strcmp(nname, name) == 0)) + { + const char *val = this->NestedElements[i]->GetAttribute(att_name); + if (val && !strcmp(val, att_value)) + { + return this->NestedElements[i]; + } + } + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::LookupElement(const char* id) +{ + return this->LookupElementUpScope(id); +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::FindNestedElement(const char* id) +{ + if (!id) + { + return 0; + } + + int i; + for(i=0;i < this->NumberOfNestedElements;++i) + { + const char* nid = this->NestedElements[i]->GetId(); + if(nid && (strcmp(nid, id) == 0)) + { + return this->NestedElements[i]; + } + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::LookupElementInScope(const char* id) +{ + if (!id) + { + return 0; + } + + // Pull off the first qualifier. + const char* end = id; + while(*end && (*end != '.')) ++end; + int len = end - id; + char* name = new char[len+1]; + strncpy(name, id, len); + name[len] = '\0'; + + // Find the qualifier in this scope. + vtkXMLDataElement* next = this->FindNestedElement(name); + if(next && (*end == '.')) + { + // Lookup rest of qualifiers in nested scope. + next = next->LookupElementInScope(end+1); + } + + delete [] name; + return next; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataElement::LookupElementUpScope(const char* id) +{ + if (!id) + { + return 0; + } + + // Pull off the first qualifier. + const char* end = id; + while(*end && (*end != '.')) ++end; + int len = end - id; + char* name = new char[len+1]; + strncpy(name, id, len); + name[len] = '\0'; + + // Find most closely nested occurrence of first qualifier. + vtkXMLDataElement* curScope = this; + vtkXMLDataElement* start = 0; + while(curScope && !start) + { + start = curScope->FindNestedElement(name); + curScope = curScope->GetParent(); + } + if(start && (*end == '.')) + { + start = start->LookupElementInScope(end+1); + } + + delete [] name; + return start; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetScalarAttribute(const char* name, int& value) +{ + return this->GetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetScalarAttribute(const char* name, float& value) +{ + return this->GetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetScalarAttribute(const char* name, double& value) +{ + return this->GetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetScalarAttribute(const char* name, + unsigned long& value) +{ + return this->GetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +int vtkXMLDataElement::GetScalarAttribute(const char* name, vtkIdType& value) +{ + return this->GetVectorAttribute(name, 1, &value); +} +#endif + +//---------------------------------------------------------------------------- +template +int vtkXMLDataElementVectorAttributeParse(const char* str, int length, T* data) +{ + if(!str || !length || !data) { return 0; } + strstream vstr; + vstr << str << ends; + int i; + for(i=0;i < length;++i) + { + vstr >> data[i]; + if(!vstr) { return i; } + } + return length; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetVectorAttribute(const char* name, int length, + int* data) +{ + return vtkXMLDataElementVectorAttributeParse(this->GetAttribute(name), + length, data); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetVectorAttribute(const char* name, int length, + float* data) +{ + return vtkXMLDataElementVectorAttributeParse(this->GetAttribute(name), + length, data); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetVectorAttribute(const char* name, int length, + double* data) +{ + return vtkXMLDataElementVectorAttributeParse(this->GetAttribute(name), + length, data); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetVectorAttribute(const char* name, int length, + unsigned long* data) +{ + return vtkXMLDataElementVectorAttributeParse(this->GetAttribute(name), + length, data); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +int vtkXMLDataElement::GetVectorAttribute(const char* name, int length, + vtkIdType* data) +{ + return vtkXMLDataElementVectorAttributeParse(this->GetAttribute(name), + length, data); +} +#endif + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::GetWordTypeAttribute(const char* name, int& value) +{ + // These string values must match vtkXMLWriter::GetWordTypeName(). + const char* v = this->GetAttribute(name); + if(!v) + { + vtkErrorMacro("Missing word type attribute \"" << name << "\"."); + return 0; + } + else if(strcmp(v, "Float32") == 0) + { +#if VTK_SIZEOF_FLOAT == 4 + value = VTK_FLOAT; + return 1; +#elif VTK_SIZEOF_DOUBLE == 4 + value = VTK_DOUBLE; + return 1; +#else + vtkErrorMacro("Float32 support not compiled in VTK."); + return 0; +#endif + } + else if(strcmp(v, "Float64") == 0) + { +#if VTK_SIZEOF_FLOAT == 8 + value = VTK_FLOAT; + return 1; +#elif VTK_SIZEOF_DOUBLE == 8 + value = VTK_DOUBLE; + return 1; +#else + vtkErrorMacro("Float64 support not compiled in VTK."); + return 0; +#endif + } + else if(strcmp(v, "Int8") == 0) + { + // For compatibility, use char when it is signed. +#if VTK_TYPE_CHAR_IS_SIGNED + value = VTK_CHAR; +#else + value = VTK_SIGNED_CHAR; +#endif + return 1; + } + else if(strcmp(v, "UInt8") == 0) + { + value = VTK_UNSIGNED_CHAR; + return 1; + } + else if(strcmp(v, "Int16") == 0) + { +#if VTK_SIZEOF_SHORT == 2 + value = VTK_SHORT; + return 1; +#elif VTK_SIZEOF_INT == 2 + value = VTK_INT; + return 1; +#elif VTK_SIZEOF_LONG == 2 + value = VTK_LONG; + return 1; +#else + vtkErrorMacro("Int16 support not compiled in VTK."); + return 0; +#endif + } + else if(strcmp(v, "UInt16") == 0) + { +#if VTK_SIZEOF_SHORT == 2 + value = VTK_UNSIGNED_SHORT; + return 1; +#elif VTK_SIZEOF_INT == 2 + value = VTK_UNSIGNED_INT; + return 1; +#elif VTK_SIZEOF_LONG == 2 + value = VTK_UNSIGNED_LONG; + return 1; +#else + vtkErrorMacro("UInt16 support not compiled in VTK."); + return 0; +#endif + } + else if(strcmp(v, "Int32") == 0) + { +#if VTK_SIZEOF_SHORT == 4 + value = VTK_SHORT; + return 1; +#elif VTK_SIZEOF_INT == 4 + value = VTK_INT; + return 1; +#elif VTK_SIZEOF_LONG == 4 + value = VTK_LONG; + return 1; +#else + vtkErrorMacro("Int32 support not compiled in VTK."); + return 0; +#endif + } + else if(strcmp(v, "UInt32") == 0) + { +#if VTK_SIZEOF_SHORT == 4 + value = VTK_UNSIGNED_SHORT; + return 1; +#elif VTK_SIZEOF_INT == 4 + value = VTK_UNSIGNED_INT; + return 1; +#elif VTK_SIZEOF_LONG == 4 + value = VTK_UNSIGNED_LONG; + return 1; +#else + vtkErrorMacro("UInt32 support not compiled in VTK."); + return 0; +#endif + } + else if(strcmp(v, "Int64") == 0) + { +#if VTK_SIZEOF_SHORT == 8 + value = VTK_SHORT; + return 1; +#elif VTK_SIZEOF_INT == 8 + value = VTK_INT; + return 1; +#elif VTK_SIZEOF_LONG == 8 + value = VTK_LONG; + return 1; +#elif defined(VTK_TYPE_USE_LONG_LONG) && VTK_SIZEOF_LONG_LONG == 8 + value = VTK_LONG_LONG; + return 1; +#elif defined(VTK_TYPE_USE___INT64) && VTK_SIZEOF___INT64 == 8 + value = VTK___INT64; + return 1; +#else + vtkErrorMacro("Int64 support not compiled in VTK."); + return 0; +#endif + } + else if(strcmp(v, "UInt64") == 0) + { +#if VTK_SIZEOF_SHORT == 8 + value = VTK_UNSIGNED_SHORT; + return 1; +#elif VTK_SIZEOF_INT == 8 + value = VTK_UNSIGNED_INT; + return 1; +#elif VTK_SIZEOF_LONG == 8 + value = VTK_UNSIGNED_LONG; + return 1; +#elif defined(VTK_TYPE_USE_LONG_LONG) && VTK_SIZEOF_LONG_LONG == 8 + value = VTK_UNSIGNED_LONG_LONG; + return 1; +#elif defined(VTK_TYPE_USE___INT64) && defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) && VTK_SIZEOF___INT64 == 8 + value = VTK_UNSIGNED___INT64; + return 1; +#else + vtkErrorMacro("UInt64 support not compiled in VTK."); + return 0; +#endif + } + else + { + vtkErrorMacro("Unknown data type \"" << v << "\". Supported types are:\n" + "Int8, Int16, Int32, Int64,\n" + "UInt8, UInt16, UInt32, UInt64,\n" + "Float32, Float64\n"); + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetIntAttribute(const char* name, int value) +{ + this->SetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetFloatAttribute(const char* name, float value) +{ + this->SetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetDoubleAttribute(const char* name, double value) +{ + this->SetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetUnsignedLongAttribute(const char* name, + unsigned long value) +{ + this->SetVectorAttribute(name, 1, &value); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +void vtkXMLDataElement::SetIdTypeAttribute(const char* name, + vtkIdType value) +{ + this->SetVectorAttribute(name, 1, &value); +} +#endif + +//---------------------------------------------------------------------------- +template +void vtkXMLDataElementVectorAttributeSet(vtkXMLDataElement *elem, const char* name, int length, const T* data) +{ + if (!elem || !name || !length) + { + return; + } + strstream vstr; + vstr << data[0]; + for(int i = 1; i < length; ++i) + { + vstr << ' ' << data[i]; + } + vstr << ends; + elem->SetAttribute(name, vstr.str()); + vstr.rdbuf()->freeze(0); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetVectorAttribute(const char* name, int length, + const int* data) +{ + vtkXMLDataElementVectorAttributeSet(this, name, length, data); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetVectorAttribute(const char* name, int length, + const float* data) +{ + vtkXMLDataElementVectorAttributeSet(this, name, length, data); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetVectorAttribute(const char* name, int length, + const double* data) +{ + vtkXMLDataElementVectorAttributeSet(this, name, length, data); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SetVectorAttribute(const char* name, int length, + const unsigned long* data) +{ + vtkXMLDataElementVectorAttributeSet(this, name, length, data); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +void vtkXMLDataElement::SetVectorAttribute(const char* name, int length, + const vtkIdType* data) +{ + vtkXMLDataElementVectorAttributeSet(this, name, length, data); +} +#endif + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::SeekInlineDataPosition(vtkXMLDataParser* parser) +{ + if (!parser) + { + return; + } + + istream* stream = parser->GetStream(); + if(!this->InlineDataPosition) + { + // Scan for the start of the actual inline data. + char c=0; + stream->clear(stream->rdstate() & ~ios::eofbit); + stream->clear(stream->rdstate() & ~ios::failbit); + parser->SeekG(this->GetXMLByteIndex()); + while(stream->get(c) && (c != '>')); + while(stream->get(c) && this->IsSpace(c)); + unsigned long pos = parser->TellG(); + this->InlineDataPosition = pos-1; + } + + // Seek to the data position. + parser->SeekG(this->InlineDataPosition); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::IsSpace(char c) +{ + return isspace(c); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataElement::IsEqualTo(vtkXMLDataElement *elem) +{ + if (this == elem) + { + return 1; + } + + if (!elem) + { + return 0; + } + + if (this->GetNumberOfAttributes() != elem->GetNumberOfAttributes() || + this->GetNumberOfNestedElements() != elem->GetNumberOfNestedElements() || + (this->GetName() != elem->GetName() && + (!this->GetName() || !elem->GetName() || strcmp(this->GetName(), + elem->GetName())))) + { + return 0; + } + + // Compare attributes + + int i; + for (i = 0; i < this->GetNumberOfAttributes(); ++i) + { + const char *value = elem->GetAttribute(this->AttributeNames[i]); + if (!value || strcmp(value, this->AttributeValues[i])) + { + return 0; + } + } + + // Compare nested elements + + for (i = 0; i < this->GetNumberOfNestedElements(); ++i) + { + if (!this->GetNestedElement(i)->IsEqualTo(elem->GetNestedElement(i))) + { + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::DeepCopy(vtkXMLDataElement *elem) +{ + if (!elem) + { + return; + } + + this->SetName(elem->GetName()); + this->SetId(elem->GetId()); + this->SetXMLByteIndex(elem->GetXMLByteIndex()); + this->SetAttributeEncoding(elem->GetAttributeEncoding()); + + // Copy attributes + + this->RemoveAllAttributes(); + + int i; + for (i = 0; i < elem->GetNumberOfAttributes(); ++i) + { + const char *att_name = elem->GetAttributeName(i); + this->SetAttribute(att_name, elem->GetAttribute(att_name)); + } + + // Copy nested elements + + this->RemoveAllNestedElements(); + + for (i = 0; i < elem->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement *nested_elem = vtkXMLDataElement::New(); + nested_elem->DeepCopy(elem->GetNestedElement(i)); + this->AddNestedElement(nested_elem); + nested_elem->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataElement::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "XMLByteIndex: " << this->XMLByteIndex << "\n"; + os << indent << "Name: " << (this->Name? this->Name : "(none)") << "\n"; + os << indent << "Id: " << (this->Id? this->Id : "(none)") << "\n"; + os << indent << "NumberOfAttributes: " << this->NumberOfAttributes << "\n"; + os << indent << "AttributeEncoding: " << this->AttributeEncoding << "\n"; +} + diff --git a/IO/vtkXMLDataElement.h b/IO/vtkXMLDataElement.h new file mode 100644 index 0000000..ccee032 --- /dev/null +++ b/IO/vtkXMLDataElement.h @@ -0,0 +1,246 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLDataElement.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLDataElement - Represents an XML element and those nested inside. +// .SECTION Description +// vtkXMLDataElement is used by vtkXMLDataParser to represent an XML +// element. It provides methods to access the element's attributes +// and nested elements in a convenient manner. This allows easy +// traversal of an input XML file by vtkXMLReader and its subclasses. + +// .SECTION See Also +// vtkXMLDataParser + +#ifndef __vtkXMLDataElement_h +#define __vtkXMLDataElement_h + +#include "vtkObject.h" + +class vtkXMLDataParser; + +class VTK_IO_EXPORT vtkXMLDataElement : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkXMLDataElement,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLDataElement* New(); + + // Description: + // Set/Get the name of the element. This is its XML tag. + vtkGetStringMacro(Name); + vtkSetStringMacro(Name); + + // Description: + // Set/Get the value of the id attribute of the element, if any. + vtkGetStringMacro(Id); + vtkSetStringMacro(Id); + + // Description: + // Get the attribute with the given name. If it doesn't exist, + // returns 0. + const char* GetAttribute(const char* name); + + // Description: + // Set the attribute with the given name and value. If it doesn't exist, + // adds it. + void SetAttribute(const char* name, const char* value); + + // Description: + // Get the attribute with the given name and converted to a scalar + // value. Returns whether value was extracted. + int GetScalarAttribute(const char* name, int& value); + int GetScalarAttribute(const char* name, float& value); + int GetScalarAttribute(const char* name, double& value); + int GetScalarAttribute(const char* name, unsigned long& value); + + // Description: + // Set the attribute with the given name. + // We can not use the same GetScalarAttribute() construct since + // the compiler will not be able to resolve between + // SetAttribute(..., int) and SetAttribute(..., unsigned long). + void SetIntAttribute(const char* name, int value); + void SetFloatAttribute(const char* name, float value); + void SetDoubleAttribute(const char* name, double value); + void SetUnsignedLongAttribute(const char* name, unsigned long value); + + // Description: + // Get the attribute with the given name and converted to a scalar + // value. Returns length of vector read. + int GetVectorAttribute(const char* name, int length, int* value); + int GetVectorAttribute(const char* name, int length, float* value); + int GetVectorAttribute(const char* name, int length, double* value); + int GetVectorAttribute(const char* name, int length, unsigned long* value); + + // Description: + // Set the attribute with the given name. + void SetVectorAttribute(const char* name, int length, const int* value); + void SetVectorAttribute(const char* name, int length, const float* value); + void SetVectorAttribute(const char* name, int length, const double* value); + void SetVectorAttribute(const char* name, int length, const unsigned long* value); + +#ifdef VTK_USE_64BIT_IDS + //BTX + int GetScalarAttribute(const char* name, vtkIdType& value); + void SetIdTypeAttribute(const char* name, vtkIdType value); + int GetVectorAttribute(const char* name, int length, vtkIdType* value); + void SetVectorAttribute(const char* name, int length, const vtkIdType* value); + //ETX +#endif + + // Description: + // Get the attribute with the given name and converted to a word type + // such as VTK_FLOAT or VTK_UNSIGNED_LONG. + int GetWordTypeAttribute(const char* name, int& value); + + // Description: + // Get the number of attributes. + vtkGetMacro(NumberOfAttributes, int); + + // Description: + // Get the n-th attribute name. + // Returns 0 if there is no such attribute. + const char* GetAttributeName(int idx); + + // Description: + // Get the n-th attribute value. + // Returns 0 if there is no such attribute. + const char* GetAttributeValue(int idx); + + // Description: + // Remove all attributes. + virtual void RemoveAllAttributes(); + + // Description: + // Set/Get the parent of this element. + vtkXMLDataElement* GetParent(); + void SetParent(vtkXMLDataElement* parent); + + // Description: + // Get root of the XML tree this element is part of. + virtual vtkXMLDataElement* GetRoot(); + + // Description: + // Get the number of elements nested in this one. + int GetNumberOfNestedElements(); + + // Description: + // Get the element nested in this one at the given index. + vtkXMLDataElement* GetNestedElement(int index); + + // Description: + // Add nested element + void AddNestedElement(vtkXMLDataElement* element); + + // Description: + // Remove nested element. + virtual void RemoveNestedElement(vtkXMLDataElement *); + + // Description: + // Remove all nested elements. + virtual void RemoveAllNestedElements(); + + // Description: + // Find a nested element with the given id, given name, or given name and id. + vtkXMLDataElement* FindNestedElement(const char* id); + vtkXMLDataElement* FindNestedElementWithName(const char* name); + vtkXMLDataElement* FindNestedElementWithNameAndId( + const char* name, const char* id); + vtkXMLDataElement* FindNestedElementWithNameAndAttribute( + const char* name, const char* att_name, const char* att_value); + + // Description: + // Lookup the element with the given id, starting at this scope. + vtkXMLDataElement* LookupElement(const char* id); + + // Description: + // Set/Get the offset from the beginning of the XML document to this element. + vtkGetMacro(XMLByteIndex, unsigned long); + vtkSetMacro(XMLByteIndex, unsigned long); + + // Description: + // Check if the instance has the same name, attributes and nested elements + // contents than the given element (this method is applied recursively + // on the nested elements, and they must be stored in the same order). + // Warning: Id, Parent, XMLByteIndex are ignored. + virtual int IsEqualTo(vtkXMLDataElement *elem); + + // Description: + // Copy this element from another of the same type (elem), recursively. + // Old attributes and nested elements are removed, new ones are created + // given the contents of 'elem'. + // Warning: Parent is ignored. + virtual void DeepCopy(vtkXMLDataElement *elem); + + // Description: + // Get/Set the internal character encoding of the attributes. + // Default type is VTK_ENCODING_UTF_8. + // Note that a vtkXMLDataParser has its own AttributesEncoding ivar. If + // this ivar is set to something other than VTK_ENCODING_NONE, it will be + // used to set the attribute encoding of each vtkXMLDataElement + // created by this vtkXMLDataParser. + vtkSetClampMacro(AttributeEncoding,int,VTK_ENCODING_NONE,VTK_ENCODING_UNKNOWN); + vtkGetMacro(AttributeEncoding, int); + +protected: + vtkXMLDataElement(); + ~vtkXMLDataElement(); + + // The name of the element from the XML file. + char* Name; + + // The value of the "id" attribute, if any was given. + char* Id; + + // The offset into the XML stream where the element begins. + unsigned long XMLByteIndex; + + // The offset into the XML stream where the inline data begins. + unsigned long InlineDataPosition; + + // The raw property name/value pairs read from the XML attributes. + char** AttributeNames; + char** AttributeValues; + int NumberOfAttributes; + int AttributesSize; + int AttributeEncoding; + + // The set of nested elements. + int NumberOfNestedElements; + int NestedElementsSize; + vtkXMLDataElement** NestedElements; + + // The parent of this element. + vtkXMLDataElement* Parent; + + // Method used by vtkXMLFileParser to setup the element. + void ReadXMLAttributes(const char** atts, int encoding); + void SeekInlineDataPosition(vtkXMLDataParser* parser); + + void PrintXML(ostream& os, vtkIndent indent); + + // Internal utility methods. + vtkXMLDataElement* LookupElementInScope(const char* id); + vtkXMLDataElement* LookupElementUpScope(const char* id); + static int IsSpace(char c); + + //BTX + friend class vtkXMLDataParser; + //ETX + +private: + vtkXMLDataElement(const vtkXMLDataElement&); // Not implemented. + void operator=(const vtkXMLDataElement&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLDataParser.cxx b/IO/vtkXMLDataParser.cxx new file mode 100644 index 0000000..c5cab7d --- /dev/null +++ b/IO/vtkXMLDataParser.cxx @@ -0,0 +1,1059 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLDataParser.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLDataParser.h" + +#include "vtkBase64InputStream.h" +#include "vtkByteSwap.h" +#include "vtkCommand.h" +#include "vtkDataCompressor.h" +#include "vtkInputStream.h" +#include "vtkObjectFactory.h" +#include "vtkXMLDataElement.h" + +vtkCxxRevisionMacro(vtkXMLDataParser, "$Revision: 1.29.6.1 $"); +vtkStandardNewMacro(vtkXMLDataParser); +vtkCxxSetObjectMacro(vtkXMLDataParser, Compressor, vtkDataCompressor); + +//---------------------------------------------------------------------------- +vtkXMLDataParser::vtkXMLDataParser() +{ + this->NumberOfOpenElements = 0; + this->OpenElementsSize = 10; + this->OpenElements = new vtkXMLDataElement*[this->OpenElementsSize]; + this->RootElement = 0; + this->AppendedDataPosition = 0; + this->AppendedDataMatched = 0; + this->DataStream = 0; + this->InlineDataStream = vtkBase64InputStream::New(); + this->AppendedDataStream = vtkBase64InputStream::New(); + + this->BlockCompressedSizes = 0; + this->BlockStartOffsets = 0; + this->Compressor = 0; + + this->AsciiDataBuffer = 0; + this->AsciiDataBufferLength = 0; + this->AsciiDataPosition = 0; + + this->Abort = 0; + this->Progress = 0; + + // Default byte order to that of this machine. +#ifdef VTK_WORDS_BIGENDIAN + this->ByteOrder = vtkXMLDataParser::BigEndian; +#else + this->ByteOrder = vtkXMLDataParser::LittleEndian; +#endif + + this->AttributesEncoding = VTK_ENCODING_NONE; +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::~vtkXMLDataParser() +{ + this->FreeAllElements(); + delete [] this->OpenElements; + this->InlineDataStream->Delete(); + this->AppendedDataStream->Delete(); + if(this->BlockCompressedSizes) { delete [] this->BlockCompressedSizes; } + if(this->BlockStartOffsets) { delete [] this->BlockStartOffsets; } + this->SetCompressor(0); + if(this->AsciiDataBuffer) { this->FreeAsciiBuffer(); } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "AppendedDataPosition: " + << this->AppendedDataPosition << "\n"; + if(this->RootElement) + { + this->RootElement->PrintXML(os, indent); + } + if(this->Compressor) + { + os << indent << "Compressor: " << this->Compressor << "\n"; + } + else + { + os << indent << "Compressor: (none)\n"; + } + os << indent << "Progress: " << this->Progress << "\n"; + os << indent << "Abort: " << this->Abort << "\n"; + os << indent << "AttributesEncoding: " << this->AttributesEncoding << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::Parse() +{ + // Delete any elements left from previous parsing. + this->FreeAllElements(); + + // Parse the input from the stream. + int result = this->Superclass::Parse(); + + // Check that the input is okay. + if(result && !this->CheckPrimaryAttributes()) + { + result = 0; + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::Parse(const char*) +{ + vtkErrorMacro("Parsing from a string is not supported."); + return 0; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::Parse(const char*, unsigned int) +{ + vtkErrorMacro("Parsing from a string is not supported."); + return 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::StartElement(const char* name, const char** atts) +{ + vtkXMLDataElement* element = vtkXMLDataElement::New(); + element->SetName(name); + element->SetXMLByteIndex(this->GetXMLByteIndex()); + element->ReadXMLAttributes(atts, this->AttributesEncoding); + const char* id = element->GetAttribute("id"); + if(id) + { + element->SetId(id); + } + this->PushOpenElement(element); + + if(strcmp(name, "AppendedData") == 0) + { + // This is the AppendedData element. + this->FindAppendedDataPosition(); + + // Switch to raw decoder if necessary. + const char* encoding = element->GetAttribute("encoding"); + if(encoding && (strcmp(encoding, "raw") == 0)) + { + this->AppendedDataStream->Delete(); + this->AppendedDataStream = vtkInputStream::New(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::EndElement(const char*) +{ + vtkXMLDataElement* finished = this->PopOpenElement(); + unsigned int numOpen = this->NumberOfOpenElements; + if(numOpen > 0) + { + this->OpenElements[numOpen-1]->AddNestedElement(finished); + finished->Delete(); + } + else + { + this->RootElement = finished; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::ParsingComplete() +{ + // If we have reached the appended data section, we stop parsing. + // This prevents the XML parser from having to walk over the entire + // appended data section. + if(this->AppendedDataPosition) { return 1; } + return this->Superclass::ParsingComplete(); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::CheckPrimaryAttributes() +{ + const char* byte_order = this->RootElement->GetAttribute("byte_order"); + if(byte_order) + { + if(strcmp(byte_order, "BigEndian") == 0) + { + this->ByteOrder = vtkXMLDataParser::BigEndian; + } + else if(strcmp(byte_order, "LittleEndian") == 0) + { + this->ByteOrder = vtkXMLDataParser::LittleEndian; + } + else + { + vtkErrorMacro("Unsupported byte_order=\"" << byte_order << "\""); + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::FindAppendedDataPosition() +{ + // Clear stream fail and eof bits. We may have already read past + // the end of the stream when processing the AppendedData element. + this->Stream->clear(this->Stream->rdstate() & ~ios::failbit); + this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit); + + // Scan for the start of the actual appended data. + char c=0; + long returnPosition = this->TellG(); + this->SeekG(this->GetXMLByteIndex()); + while(this->Stream->get(c) && (c != '>')); + while(this->Stream->get(c) && this->IsSpace(c)); + + // Store the start of the appended data. We skip the first + // character because it is always a "_". + this->AppendedDataPosition = this->TellG(); + + // If first character was not an underscore, assume it is part of + // the data. + if(c != '_') + { + vtkWarningMacro("First character in AppendedData is ASCII value " + << int(c) << ", not '_'. Scan for first character " + << "started from file position " + << this->GetXMLByteIndex() + << ". The return position is " << returnPosition << "."); + --this->AppendedDataPosition; + } + + // Restore the stream position. + this->SeekG(returnPosition); +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::OffsetType +vtkXMLDataParser::FindInlineDataPosition(OffsetType start) +{ + // Scan for the start of the actual inline data. + char c=0; + this->SeekG(start); + while(this->Stream->get(c) && (c != '>')); + while(this->Stream->get(c) && this->IsSpace(c)); + + // Make sure some data were found. + if(c == '<') { return 0; } + OffsetType pos = this->TellG(); + return (pos-1); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::PushOpenElement(vtkXMLDataElement* element) +{ + if(this->NumberOfOpenElements == this->OpenElementsSize) + { + unsigned int newSize = this->OpenElementsSize*2; + vtkXMLDataElement** newOpenElements = new vtkXMLDataElement*[newSize]; + unsigned int i; + for(i=0; i < this->NumberOfOpenElements;++i) + { + newOpenElements[i] = this->OpenElements[i]; + } + delete [] this->OpenElements; + this->OpenElements = newOpenElements; + this->OpenElementsSize = newSize; + } + + unsigned int pos = this->NumberOfOpenElements++; + this->OpenElements[pos] = element; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataParser::PopOpenElement() +{ + if(this->NumberOfOpenElements > 0) + { + --this->NumberOfOpenElements; + return this->OpenElements[this->NumberOfOpenElements]; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::FreeAllElements() +{ + while(this->NumberOfOpenElements > 0) + { + --this->NumberOfOpenElements; + this->OpenElements[this->NumberOfOpenElements]->Delete(); + this->OpenElements[this->NumberOfOpenElements] = 0; + } + if(this->RootElement) + { + this->RootElement->Delete(); + this->RootElement = 0; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::ParseBuffer(const char* buffer, unsigned int count) +{ + // Parsing must stop when "AppendedDataMatched; + while(s != end) + { + char c = *s++; + if(c == pattern[matched]) { if(++matched == length) { break; } } + else { matched = (c == pattern[0])? 1:0; } + } + this->AppendedDataMatched = matched; + + // Parse as much of the buffer as is safe. + if(!this->Superclass::ParseBuffer(buffer, s - buffer)) { return 0; } + + // If we have reached the appended data, artificially finish the + // document. + if(matched == length) + { + // Parse the rest of the element's opening tag. + const char* t = s; + char prev = 0; + while((t != end) && (*t != '>')) { ++t; } + if(!this->Superclass::ParseBuffer(s, t-s)) { return 0; } + if(t > s) { prev = *(t-1); } + + if(t == end) + { + // Scan for the real end of the element's opening tag. + char c=0; + while(this->Stream->get(c) && (c != '>')) + { + prev = c; + if(!this->Superclass::ParseBuffer(&c, 1)) { return 0; } + } + } + + // Artificially end the AppendedData element. + if(prev != '/') + { + if(!this->Superclass::ParseBuffer("/", 1)) { return 0; } + } + if(!this->Superclass::ParseBuffer(">", 1)) { return 0; } + + // Artificially end the VTKFile element. + const char finish[] = "\n\n"; + if(!this->Superclass::ParseBuffer(finish, sizeof(finish)-1)) { return 0; } + } + + return 1; +} + +//---------------------------------------------------------------------------- +template +unsigned long vtkXMLDataParserGetWordTypeSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +unsigned long vtkXMLDataParser::GetWordTypeSize(int wordType) +{ + unsigned long size = 1; + switch (wordType) + { + vtkTemplateMacro( + size = vtkXMLDataParserGetWordTypeSize(static_cast(0)) + ); + default: + { vtkWarningMacro("Unsupported data type: " << wordType); } break; + } + return size; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::PerformByteSwap(void* data, OffsetType numWords, + int wordSize) +{ + char* ptr = static_cast(data); + if(this->ByteOrder == vtkXMLDataParser::BigEndian) + { + switch (wordSize) + { + case 1: break; + case 2: vtkByteSwap::Swap2BERange(ptr, numWords); break; + case 4: vtkByteSwap::Swap4BERange(ptr, numWords); break; + case 8: vtkByteSwap::Swap8BERange(ptr, numWords); break; + default: + vtkErrorMacro("Unsupported data type size " << wordSize); + } + } + else + { + switch (wordSize) + { + case 1: break; + case 2: vtkByteSwap::Swap2LERange(ptr, numWords); break; + case 4: vtkByteSwap::Swap4LERange(ptr, numWords); break; + case 8: vtkByteSwap::Swap8LERange(ptr, numWords); break; + default: + vtkErrorMacro("Unsupported data type size " << wordSize); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::ReadCompressionHeader() +{ + HeaderType headerBuffer[3]; + const int headerSize = sizeof(headerBuffer); + unsigned char* buffer = reinterpret_cast(&headerBuffer[0]); + + this->DataStream->StartReading(); + + // Read the standard part of the header. + int r = this->DataStream->Read(buffer, headerSize); + if(r < headerSize) + { + vtkErrorMacro("Error reading beginning of compression header. Read " + << r << " of " << headerSize << " bytes."); + return; + } + + // Byte swap the header to make sure the values are correct. + this->PerformByteSwap(headerBuffer, 3, sizeof(HeaderType)); + + // Get the standard values. + this->NumberOfBlocks = headerBuffer[0]; + this->BlockUncompressedSize = headerBuffer[1]; + this->PartialLastBlockUncompressedSize = headerBuffer[2]; + + // Allocate the size and offset parts of the header. + if(this->BlockCompressedSizes) + { + delete [] this->BlockCompressedSizes; + this->BlockCompressedSizes = 0; + } + if(this->BlockStartOffsets) + { + delete [] this->BlockStartOffsets; + this->BlockStartOffsets = 0; + } + if(this->NumberOfBlocks > 0) + { + this->BlockCompressedSizes = new HeaderType[this->NumberOfBlocks]; + this->BlockStartOffsets = new OffsetType[this->NumberOfBlocks]; + + buffer = reinterpret_cast(&this->BlockCompressedSizes[0]); + + // Read the compressed block sizes. + unsigned long len = this->NumberOfBlocks*sizeof(HeaderType); + if(this->DataStream->Read(buffer, len) < len) + { + vtkErrorMacro("Error reading compression header."); + return; + } + + // Byte swap the sizes to make sure the values are correct. + this->PerformByteSwap(buffer, this->NumberOfBlocks, sizeof(HeaderType)); + } + + this->DataStream->EndReading(); + + // Use the compressed block sizes to calculate the starting offset + // of each block. + OffsetType offset = 0; + unsigned int i; + for(i=0;i < this->NumberOfBlocks;++i) + { + this->BlockStartOffsets[i] = offset; + offset += this->BlockCompressedSizes[i]; + } +} + +//---------------------------------------------------------------------------- +unsigned int vtkXMLDataParser::FindBlockSize(unsigned int block) +{ + if(block < this->NumberOfBlocks-(this->PartialLastBlockUncompressedSize?1:0)) + { + return this->BlockUncompressedSize; + } + else + { + return this->PartialLastBlockUncompressedSize; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::ReadBlock(unsigned int block, unsigned char* buffer) +{ + OffsetType uncompressedSize = this->FindBlockSize(block); + unsigned int compressedSize = this->BlockCompressedSizes[block]; + unsigned char* readBuffer = new unsigned char[compressedSize]; + + if(!this->DataStream->Seek(this->BlockStartOffsets[block])) + { + return 0; + } + if(this->DataStream->Read(readBuffer, compressedSize) < compressedSize) + { + return 0; + } + + OffsetType result = + this->Compressor->Uncompress(readBuffer, compressedSize, + buffer, uncompressedSize); + + delete [] readBuffer; + return (result > 0)? 1:0; +} + +//---------------------------------------------------------------------------- +unsigned char* vtkXMLDataParser::ReadBlock(unsigned int block) +{ + unsigned char* decompressBuffer = + new unsigned char[this->FindBlockSize(block)]; + if(!this->ReadBlock(block, decompressBuffer)) + { + delete [] decompressBuffer; + return 0; + } + return decompressBuffer; +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::OffsetType +vtkXMLDataParser::ReadUncompressedData(unsigned char* data, + OffsetType startWord, + OffsetType numWords, + int wordSize) +{ + // First read the length of the data. + HeaderType rsize; + const unsigned long len = sizeof(HeaderType); + unsigned char* p = reinterpret_cast(&rsize); + if(this->DataStream->Read(p, len) < len) { return 0; } + this->PerformByteSwap(&rsize, 1, len); + + // Adjust the size to be a multiple of the wordSize by taking + // advantage of integer division. This will only change the value + // when the input file is invalid. + OffsetType size = (rsize/wordSize)*wordSize; + + // Convert the start/length into bytes. + OffsetType offset = startWord*wordSize; + OffsetType length = numWords*wordSize; + + // Make sure the begin/end offsets fall within total size. + if(offset > size) + { + return 0; + } + OffsetType end = offset+length; + if(end > size) + { + end = size; + } + length = end-offset; + + // Read the data. + if(!this->DataStream->Seek(offset+len)) + { + return 0; + } + + // Read data in 32KB blocks and report progress. + const long blockSize = 32768; + long left = length; + p = data; + this->UpdateProgress(0); + while(left > 0 && !this->Abort) + { + // Read this block. + long n = (blockSize < left)? blockSize:left; + if(!this->DataStream->Read(p, n)) + { + return 0; + } + + // Byte swap this block. Note that n will always be an integer + // multiple of the word size. + this->PerformByteSwap(p, n / wordSize, wordSize); + + // Update pointer and counter. + p += n; + left -= n; + + // Report progress. + this->UpdateProgress(float(p-data)/length); + } + this->UpdateProgress(1); + return length/wordSize; +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::OffsetType +vtkXMLDataParser::ReadCompressedData(unsigned char* data, + OffsetType startWord, + OffsetType numWords, + int wordSize) +{ + // Make sure there are data. + if(numWords == 0) + { + return 0; + } + + // Find the begin and end offsets into the data. + OffsetType beginOffset = startWord*wordSize; + OffsetType endOffset = beginOffset+numWords*wordSize; + + // Find the total size of the data. + OffsetType totalSize = this->NumberOfBlocks*this->BlockUncompressedSize; + if(this->PartialLastBlockUncompressedSize) + { + totalSize -= this->BlockUncompressedSize; + totalSize += this->PartialLastBlockUncompressedSize; + } + + // Adjust the size to be a multiple of the wordSize by taking + // advantage of integer division. This will only change the value + // when the input file is invalid. + totalSize = (totalSize/wordSize)*wordSize; + + // Make sure the begin/end offsets fall within the total size. + if(beginOffset > totalSize) + { + return 0; + } + if(endOffset > totalSize) + { + endOffset = totalSize; + } + + // Find the range of compression blocks to read. + unsigned int firstBlock = beginOffset / this->BlockUncompressedSize; + unsigned int lastBlock = endOffset / this->BlockUncompressedSize; + + // Find the offset into the first block where the data begin. + unsigned int beginBlockOffset = + beginOffset - firstBlock*this->BlockUncompressedSize; + + // Find the offset into the last block where the data end. + unsigned int endBlockOffset = + endOffset - lastBlock*this->BlockUncompressedSize; + + this->UpdateProgress(0); + if(firstBlock == lastBlock) + { + // Everything fits in one block. + unsigned char* blockBuffer = this->ReadBlock(firstBlock); + if(!blockBuffer) { return 0; } + long n = endBlockOffset - beginBlockOffset; + memcpy(data, blockBuffer+beginBlockOffset, n); + delete [] blockBuffer; + + // Byte swap this block. Note that n will always be an integer + // multiple of the word size. + this->PerformByteSwap(data, n / wordSize, wordSize); + } + else + { + // Read all the complete blocks first. + OffsetType length = endOffset - beginOffset; + unsigned char* outputPointer = data; + OffsetType blockSize = this->FindBlockSize(firstBlock); + + // Read the first block. + unsigned char* blockBuffer = this->ReadBlock(firstBlock); + if(!blockBuffer) + { + return 0; + } + long n = blockSize-beginBlockOffset; + memcpy(outputPointer, blockBuffer+beginBlockOffset, n); + delete [] blockBuffer; + + // Byte swap the first block. Note that n will always be an + // integer multiple of the word size. + this->PerformByteSwap(outputPointer, n / wordSize, wordSize); + + // Advance the pointer to the beginning of the second block. + outputPointer += blockSize-beginBlockOffset; + + // Report progress. + this->UpdateProgress(float(outputPointer-data)/length); + + unsigned int currentBlock = firstBlock+1; + for(;currentBlock != lastBlock && !this->Abort; ++currentBlock) + { + // Read this block. + if(!this->ReadBlock(currentBlock, outputPointer)) { return 0; } + + // Byte swap this block. Note that blockSize will always be an + // integer multiple of the word size. + this->PerformByteSwap(outputPointer, blockSize / wordSize, wordSize); + + // Advance the pointer to the beginning of the next block. + outputPointer += this->FindBlockSize(currentBlock); + + // Report progress. + this->UpdateProgress(float(outputPointer-data)/length); + } + + // Now read the final block, which is incomplete if it exists. + if(endBlockOffset > 0 && !this->Abort) + { + blockBuffer = this->ReadBlock(lastBlock); + if(!blockBuffer) + { + return 0; + } + memcpy(outputPointer, blockBuffer, endBlockOffset); + delete [] blockBuffer; + + // Byte swap the partial block. Note that endBlockOffset will + // always be an integer multiple of the word size. + this->PerformByteSwap(outputPointer, endBlockOffset / wordSize, wordSize); + } + } + this->UpdateProgress(1); + + // Return the total words actually read. + return (endOffset - beginOffset)/wordSize; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* vtkXMLDataParser::GetRootElement() +{ + return this->RootElement; +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::OffsetType +vtkXMLDataParser::ReadBinaryData(void* in_buffer, + OffsetType startWord, + OffsetType numWords, + int wordType) +{ + // Skip real read if aborting. + if(this->Abort) + { + return 0; + } + + unsigned long wordSize = this->GetWordTypeSize(wordType); + void* buffer = in_buffer; + + // Make sure our streams are setup correctly. + this->DataStream->SetStream(this->Stream); + + // Read the data. + unsigned char* d = reinterpret_cast(buffer); + OffsetType actualWords; + if(this->Compressor) + { + this->ReadCompressionHeader(); + this->DataStream->StartReading(); + actualWords = this->ReadCompressedData(d, startWord, numWords, wordSize); + this->DataStream->EndReading(); + } + else + { + this->DataStream->StartReading(); + actualWords = this->ReadUncompressedData(d, startWord, numWords, wordSize); + this->DataStream->EndReading(); + } + + // Return the actual amount read. + return this->Abort? 0:actualWords; +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::OffsetType +vtkXMLDataParser::ReadAsciiData(void* buffer, + OffsetType startWord, + OffsetType numWords, + int wordType) +{ + // Skip real read if aborting. + if(this->Abort) + { + return 0; + } + + // We assume that ascii data are not very large and parse the entire + // block into memory. + this->UpdateProgress(0); + + // Parse the ascii data from the file. + if(!this->ParseAsciiData(wordType)) { return 0; } + + // Make sure we don't read outside the range of data available. + OffsetType endWord = startWord + numWords; + if(this->AsciiDataBufferLength < startWord) { return 0; } + if(endWord > this->AsciiDataBufferLength) + { + endWord = this->AsciiDataBufferLength; + } + unsigned long wordSize = this->GetWordTypeSize(wordType); + OffsetType actualWords = endWord - startWord; + OffsetType actualBytes = wordSize*actualWords; + OffsetType startByte = wordSize*startWord; + + this->UpdateProgress(0.5); + + // Copy the data from the pre-parsed ascii data buffer. + memcpy(buffer, this->AsciiDataBuffer+startByte, actualBytes); + + this->UpdateProgress(1); + + return this->Abort? 0:actualWords; +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::OffsetType +vtkXMLDataParser::ReadInlineData(vtkXMLDataElement* element, + int isAscii, void* buffer, + OffsetType startWord, + OffsetType numWords, + int wordType) +{ + this->DataStream = this->InlineDataStream; + element->SeekInlineDataPosition(this); + if(isAscii) + { + return this->ReadAsciiData(buffer, startWord, numWords, wordType); + } + else + { + return this->ReadBinaryData(buffer, startWord, numWords, wordType); + } +} + +//---------------------------------------------------------------------------- +vtkXMLDataParser::OffsetType +vtkXMLDataParser::ReadAppendedData(OffsetType offset, + void* buffer, + OffsetType startWord, + OffsetType numWords, + int wordType) +{ + this->DataStream = this->AppendedDataStream; + this->SeekG(this->AppendedDataPosition+offset); + return this->ReadBinaryData(buffer, startWord, numWords, wordType); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// Define a parsing function template. The extra "long" argument is used +// to help broken compilers select the non-templates below for char and +// unsigned char by making them a better conversion than the template. +template +T* vtkXMLParseAsciiData(istream& is, int* length, T*, long) +{ + int dataLength = 0; + int dataBufferSize = 64; + + T* dataBuffer = new T[dataBufferSize]; + T element; + + while(is >> element) + { + if(dataLength == dataBufferSize) + { + int newSize = dataBufferSize*2; + T* newBuffer = new T[newSize]; + memcpy(newBuffer, dataBuffer, dataLength*sizeof(T)); + delete [] dataBuffer; + dataBuffer = newBuffer; + dataBufferSize = newSize; + } + dataBuffer[dataLength++] = element; + } + + if(length) + { + *length = dataLength; + } + + return dataBuffer; +} + +//---------------------------------------------------------------------------- +char* vtkXMLParseAsciiData(istream& is, int* length, char*, int) +{ + int dataLength = 0; + int dataBufferSize = 64; + + char* dataBuffer = new char[dataBufferSize]; + char element; + short inElement; + + while(is >> inElement) + { + element = inElement; + if(dataLength == dataBufferSize) + { + int newSize = dataBufferSize*2; + char* newBuffer = new char[newSize]; + memcpy(newBuffer, dataBuffer, dataLength*sizeof(char)); + delete [] dataBuffer; + dataBuffer = newBuffer; + dataBufferSize = newSize; + } + dataBuffer[dataLength++] = element; + } + + if(length) + { + *length = dataLength; + } + + return dataBuffer; +} + +//---------------------------------------------------------------------------- +unsigned char* vtkXMLParseAsciiData(istream& is, int* length, unsigned char*, + int) +{ + int dataLength = 0; + int dataBufferSize = 64; + + unsigned char* dataBuffer = new unsigned char[dataBufferSize]; + unsigned char element; + short inElement; + + while(is >> inElement) + { + element = inElement; + if(dataLength == dataBufferSize) + { + int newSize = dataBufferSize*2; + unsigned char* newBuffer = new unsigned char[newSize]; + memcpy(newBuffer, dataBuffer, dataLength*sizeof(unsigned char)); + delete [] dataBuffer; + dataBuffer = newBuffer; + dataBufferSize = newSize; + } + dataBuffer[dataLength++] = element; + } + + if(length) + { + *length = dataLength; + } + + return dataBuffer; +} + +//---------------------------------------------------------------------------- +signed char* vtkXMLParseAsciiData(istream& is, int* length, signed char*, + int) +{ + int dataLength = 0; + int dataBufferSize = 64; + + signed char* dataBuffer = new signed char[dataBufferSize]; + signed char element; + short inElement; + + while(is >> inElement) + { + element = inElement; + if(dataLength == dataBufferSize) + { + int newSize = dataBufferSize*2; + signed char* newBuffer = new signed char[newSize]; + memcpy(newBuffer, dataBuffer, dataLength*sizeof(signed char)); + delete [] dataBuffer; + dataBuffer = newBuffer; + dataBufferSize = newSize; + } + dataBuffer[dataLength++] = element; + } + + if(length) + { + *length = dataLength; + } + + return dataBuffer; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataParser::ParseAsciiData(int wordType) +{ + istream& is = *(this->Stream); + + // Don't re-parse the same ascii data. + if(this->AsciiDataPosition == static_cast(this->TellG())) + { + return (this->AsciiDataBuffer? 1:0); + } + + // Prepare for new data. + this->AsciiDataPosition = this->TellG(); + if(this->AsciiDataBuffer) { this->FreeAsciiBuffer(); } + + int length = 0; + void* buffer = 0; + switch (wordType) + { + vtkTemplateMacro( + buffer = vtkXMLParseAsciiData(is, &length, static_cast(0), 1) + ); + } + + // Read terminated from failure. Clear the fail bit so another read + // can take place later. + is.clear(is.rdstate() & ~ios::failbit); + + // Save the buffer. + this->AsciiDataBuffer = reinterpret_cast(buffer); + this->AsciiDataBufferLength = length; + this->AsciiDataWordType = wordType; + return (this->AsciiDataBuffer? 1:0); +} + +//---------------------------------------------------------------------------- +template +void vtkXMLDataParserFreeAsciiBuffer(T* buffer) +{ + delete [] buffer; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::FreeAsciiBuffer() +{ + void* buffer = this->AsciiDataBuffer; + switch (this->AsciiDataWordType) + { + vtkTemplateMacro( + vtkXMLDataParserFreeAsciiBuffer(static_cast(buffer)) + ); + } + this->AsciiDataBuffer = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataParser::UpdateProgress(float progress) +{ + this->Progress = progress; + this->InvokeEvent(vtkCommand::ProgressEvent, &progress); +} diff --git a/IO/vtkXMLDataParser.h b/IO/vtkXMLDataParser.h new file mode 100644 index 0000000..0a6f6ad --- /dev/null +++ b/IO/vtkXMLDataParser.h @@ -0,0 +1,245 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLDataParser.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLDataParser - Used by vtkXMLReader to parse VTK XML files. +// .SECTION Description +// vtkXMLDataParser provides a subclass of vtkXMLParser that +// constructs a representation of an XML data format's file using +// vtkXMLDataElement to represent each XML element. This +// representation is then used by vtkXMLReader and its subclasses to +// traverse the structure of the file and extract data. + +// .SECTION See Also +// vtkXMLDataElement + +#ifndef __vtkXMLDataParser_h +#define __vtkXMLDataParser_h + +#include "vtkXMLParser.h" + +class vtkXMLDataElement; +class vtkInputStream; +class vtkDataCompressor; + +class VTK_IO_EXPORT vtkXMLDataParser : public vtkXMLParser +{ +public: + vtkTypeRevisionMacro(vtkXMLDataParser,vtkXMLParser); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLDataParser* New(); + + // Description: + // Get the root element from the XML document. + vtkXMLDataElement* GetRootElement(); + + //BTX + // Description: + // Enumerate big and little endian byte order settings. + enum { BigEndian, LittleEndian }; + + // Description: + // A type used for data sizes and offsets for stream i/o. Using + // vtkIdType should satisfy most users. This could be streamoff if + // it is deemed portable. It could also be split into OffsetType + // (streamoff) and PositionType (streampos). + typedef vtkIdType OffsetType; + + // Description: + // Read inline data from inside the given element. Returns the + // number of words read. + OffsetType ReadInlineData(vtkXMLDataElement* element, int isAscii, + void* buffer, OffsetType startWord, + OffsetType numWords, int wordType); + OffsetType ReadInlineData(vtkXMLDataElement* element, int isAscii, + char* buffer, OffsetType startWord, + OffsetType numWords) + { return this->ReadInlineData(element, isAscii, buffer, startWord, + numWords, VTK_CHAR); } + + // Description: + // Read from an appended data section starting at the given appended + // data offset. Returns the number of words read. + OffsetType ReadAppendedData(OffsetType offset, void* buffer, + OffsetType startWord, + OffsetType numWords, int wordType); + OffsetType ReadAppendedData(OffsetType offset, char* buffer, + OffsetType startWord, + OffsetType numWords) + { return this->ReadAppendedData(offset, buffer, startWord, numWords, + VTK_CHAR); } + + // Description: + // Read from an ascii data section starting at the current position in + // the stream. Returns the number of words read. + OffsetType ReadAsciiData(void* buffer, OffsetType startWord, + OffsetType numWords, int wordType); + + // Description: + // Read from a data section starting at the current position in the + // stream. Returns the number of words read. + OffsetType ReadBinaryData(void* buffer, OffsetType startWord, + OffsetType maxWords, int wordType); + //ETX + + // Description: + // Get/Set the compressor used to decompress binary and appended data + // after reading from the file. + virtual void SetCompressor(vtkDataCompressor*); + vtkGetObjectMacro(Compressor, vtkDataCompressor); + + // Description: + // Get the size of a word of the given type. + unsigned long GetWordTypeSize(int wordType); + + // Description: + // Parse the XML input and check that the file is safe to read. + // Returns 1 for okay, 0 for error. + virtual int Parse(); + + // Description: + // Get/Set flag to abort reading of data. This may be set by a + // progress event observer. + vtkGetMacro(Abort, int); + vtkSetMacro(Abort, int); + + // Description: + // Get/Set progress of reading data. This may be checked by a + // progress event observer. + vtkGetMacro(Progress, float); + vtkSetMacro(Progress, float); + + // Description: + // Get/Set the character encoding that will be used to set the attributes's + // encoding type of each vtkXMLDataElement created by this parser (i.e., + // the data element attributes will use that encoding internally). + // If set to VTK_ENCODING_NONE (default), the attribute encoding type will + // not be changed and will default to the vtkXMLDataElement default encoding + // type (see vtkXMLDataElement::AttributeEncoding). + vtkSetClampMacro(AttributesEncoding,int,VTK_ENCODING_NONE,VTK_ENCODING_UNKNOWN); + vtkGetMacro(AttributesEncoding, int); + +protected: + vtkXMLDataParser(); + ~vtkXMLDataParser(); + + // This parser does not support parsing from a string. + virtual int Parse(const char*); + virtual int Parse(const char*, unsigned int); + + // Implement parsing methods. + void StartElement(const char* name, const char** atts); + void EndElement(const char*); + int ParsingComplete(); + int CheckPrimaryAttributes(); + void FindAppendedDataPosition(); + OffsetType FindInlineDataPosition(OffsetType start); + int ParseBuffer(const char* buffer, unsigned int count); + + void AddElement(vtkXMLDataElement* element); + void PushOpenElement(vtkXMLDataElement* element); + vtkXMLDataElement* PopOpenElement(); + void FreeAllElements(); + void PerformByteSwap(void* data, OffsetType numWords, int wordSize); + + // Data reading methods. + void ReadCompressionHeader(); + unsigned int FindBlockSize(unsigned int block); + int ReadBlock(unsigned int block, unsigned char* buffer); + unsigned char* ReadBlock(unsigned int block); + OffsetType ReadUncompressedData(unsigned char* data, + OffsetType startWord, + OffsetType numWords, + int wordSize); + OffsetType ReadCompressedData(unsigned char* data, + OffsetType startWord, + OffsetType numWords, + int wordSize); + + // Ascii data reading methods. + int ParseAsciiData(int wordType); + void FreeAsciiBuffer(); + + // Progress update methods. + void UpdateProgress(float progress); + + // The root XML element. + vtkXMLDataElement* RootElement; + + // The stack of elements currently being parsed. + vtkXMLDataElement** OpenElements; + unsigned int NumberOfOpenElements; + unsigned int OpenElementsSize; + + // The position of the appended data section, if found. + OffsetType AppendedDataPosition; + + // How much of the string "NumberOfPieces = 0; + this->PointDataElements = 0; + this->CellDataElements = 0; + this->Piece = 0; + this->NumberOfPointArrays = 0; + this->NumberOfCellArrays = 0; + this->InReadData = 0; + + // Setup a callback for when the XMLParser's data reading routines + // report progress. + this->DataProgressObserver = vtkCallbackCommand::New(); + this->DataProgressObserver->SetCallback(&vtkXMLDataReader::DataProgressCallbackFunction); + this->DataProgressObserver->SetClientData(this); + + this->PointDataTimeStep = NULL; + this->PointDataOffset = NULL; + this->CellDataTimeStep = NULL; + this->CellDataOffset = NULL; +} + +//---------------------------------------------------------------------------- +vtkXMLDataReader::~vtkXMLDataReader() +{ + if(this->XMLParser) + { + this->DestroyXMLParser(); + } + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } + this->DataProgressObserver->Delete(); + if( this->NumberOfPointArrays ) + { + delete[] this->PointDataTimeStep; + delete[] this->PointDataOffset; + } + if( this->NumberOfCellArrays ) + { + delete[] this->CellDataTimeStep; + delete[] this->CellDataOffset; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::CreateXMLParser() +{ + this->Superclass::CreateXMLParser(); + this->XMLParser->AddObserver(vtkCommand::ProgressEvent, + this->DataProgressObserver); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::DestroyXMLParser() +{ + if(this->XMLParser) + { + this->XMLParser->RemoveObserver(this->DataProgressObserver); + } + this->Superclass::DestroyXMLParser(); +} + + + +//---------------------------------------------------------------------------- +// Note that any changes (add or removing information) made to this method +// should be replicated in CopyOutputInformation +void vtkXMLDataReader::SetupOutputInformation(vtkInformation *outInfo) +{ + if (this->InformationError) + { + vtkErrorMacro("Should not still be processing output information if have set InformationError"); + return; + } + + // Initialize DataArraySelections to enable all that are present + this->SetDataArraySelections(this->PointDataElements[0], this->PointDataArraySelection); + this->SetDataArraySelections(this->CellDataElements[0], this->CellDataArraySelection); + + // Setup the Field Information for PointData. We only need the + // information from one piece because all pieces have the same set of arrays. + vtkInformationVector *infoVector = NULL; + if (!this->SetFieldDataInfo(this->PointDataElements[0], + vtkDataObject::FIELD_ASSOCIATION_POINTS, this->GetNumberOfPoints(), infoVector)) + { + return; + } + if (infoVector) + { + outInfo->Set(vtkDataObject::POINT_DATA_VECTOR(), infoVector); + infoVector->Delete(); + } + + // now the Cell data + infoVector = NULL; + if (!this->SetFieldDataInfo(this->CellDataElements[0], + vtkDataObject::FIELD_ASSOCIATION_CELLS, this->GetNumberOfCells(), infoVector)) + { + return; + } + if (infoVector) + { + outInfo->Set(vtkDataObject::CELL_DATA_VECTOR(), infoVector); + infoVector->Delete(); + } +} + + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::CopyOutputInformation(vtkInformation *outInfo, int port) + { + vtkInformation *localInfo = this->GetExecutive()->GetOutputInformation( port ); + if ( localInfo->Has(vtkDataObject::POINT_DATA_VECTOR()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::POINT_DATA_VECTOR() ); + } + if ( localInfo->Has(vtkDataObject::CELL_DATA_VECTOR()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::CELL_DATA_VECTOR() ); + } + } + + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) + { + return 0; + } + + // Count the number of pieces in the file. + int numNested = ePrimary->GetNumberOfNestedElements(); + int numPieces = 0; + int i; + for(i=0; i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if(strcmp(eNested->GetName(), "Piece") == 0) + { + ++numPieces; + } + } + + // Now read each piece. If no "Piece" elements were found, assume + // the primary element itself is a single piece. + if(numPieces) + { + this->SetupPieces(numPieces); + int piece = 0; + for(i=0;i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if(strcmp(eNested->GetName(), "Piece") == 0) + { + if(!this->ReadPiece(eNested, piece++)) + { + return 0; + } + } + } + } + else + { + this->SetupPieces(1); + if(!this->ReadPiece(ePrimary, 0)) + { + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::SetupPieces(int numPieces) +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } + this->NumberOfPieces = numPieces; + if(numPieces > 0) + { + this->PointDataElements = new vtkXMLDataElement*[numPieces]; + this->CellDataElements = new vtkXMLDataElement*[numPieces]; + } + int i; + for(i=0;i < this->NumberOfPieces;++i) + { + this->PointDataElements[i] = 0; + this->CellDataElements[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::DestroyPieces() +{ + delete [] this->PointDataElements; + delete [] this->CellDataElements; + this->PointDataElements = 0; + this->CellDataElements = 0; + this->NumberOfPieces = 0; +} + + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + vtkPointData* pointData = this->GetOutputAsDataSet(0)->GetPointData(); + vtkCellData* cellData = this->GetOutputAsDataSet(0)->GetCellData(); + + // Get the size of the output arrays. + unsigned long pointTuples = this->GetNumberOfPoints(); + unsigned long cellTuples = this->GetNumberOfCells(); + + // Allocate the arrays in the output. We only need the information + // from one piece because all pieces have the same set of arrays. + vtkXMLDataElement* ePointData = this->PointDataElements[0]; + vtkXMLDataElement* eCellData = this->CellDataElements[0]; + this->NumberOfPointArrays = 0; + if (ePointData) + { + for (int i = 0; i < ePointData->GetNumberOfNestedElements(); i++) + { + vtkXMLDataElement* eNested = ePointData->GetNestedElement(i); + if (this->PointDataArrayIsEnabled(eNested) && + !pointData->HasArray(eNested->GetAttribute("Name"))) + { + this->NumberOfPointArrays++; + vtkDataArray* array = this->CreateDataArray(eNested); + if (array) + { + array->SetNumberOfTuples(pointTuples); + pointData->AddArray(array); + array->Delete(); + } + else + { + this->DataError = 1; + } + } + } + } + assert( this->NumberOfPointArrays == this->PointDataArraySelection->GetNumberOfArraysEnabled()); + + this->NumberOfCellArrays = 0; + if (eCellData) + { + for (int i = 0; i < eCellData->GetNumberOfNestedElements(); i++) + { + vtkXMLDataElement* eNested = eCellData->GetNestedElement(i); + if (this->CellDataArrayIsEnabled(eNested) && + !cellData->HasArray(eNested->GetAttribute("Name"))) + { + this->NumberOfCellArrays++; + vtkDataArray* array = this->CreateDataArray(eNested); + if (array) + { + array->SetNumberOfTuples(cellTuples); + cellData->AddArray(array); + array->Delete(); + } + else + { + this->DataError = 1; + } + } + } + } + assert( this->NumberOfCellArrays == this->CellDataArraySelection->GetNumberOfArraysEnabled()); + + // Setup attribute indices for the point data and cell data. + this->ReadAttributeIndices(ePointData, pointData); + this->ReadAttributeIndices(eCellData, cellData); + + // Since NumberOfCellArrays and NumberOfPointArrays are valid + // lets allocate PointDataTimeStep, CellDataTimeStep, PointDataOffset + // CellDataOffset + if( this->NumberOfPointArrays ) + { + this->PointDataTimeStep = new int[this->NumberOfPointArrays]; + this->PointDataOffset = new unsigned long[this->NumberOfPointArrays]; + for(int i=0; iNumberOfPointArrays;i++) + { + this->PointDataTimeStep[i] = -1; + this->PointDataOffset[i] = (unsigned long)-1; + } + } + if( this->NumberOfCellArrays ) + { + this->CellDataTimeStep = new int[this->NumberOfCellArrays]; + this->CellDataOffset = new unsigned long[this->NumberOfCellArrays]; + for(int i=0; iNumberOfCellArrays;i++) + { + this->CellDataTimeStep[i] = -1; + this->CellDataOffset[i] = (unsigned long)-1; + } + } +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadPiece(vtkXMLDataElement* ePiece, int piece) +{ + this->Piece = piece; + return this->ReadPiece(ePiece); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + // Find the PointData and CellData in the piece. + int i; + for(i=0; i < ePiece->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = ePiece->GetNestedElement(i); + if(strcmp(eNested->GetName(), "PointData") == 0) + { + this->PointDataElements[this->Piece] = eNested; + } + else if(strcmp(eNested->GetName(), "CellData") == 0) + { + this->CellDataElements[this->Piece] = eNested; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadPieceData(int piece) +{ + this->Piece = piece; + return this->ReadPieceData(); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadPieceData() +{ + vtkPointData* pointData = this->GetOutputAsDataSet(0)->GetPointData(); + vtkCellData* cellData = this->GetOutputAsDataSet(0)->GetCellData(); + vtkXMLDataElement* ePointData = this->PointDataElements[this->Piece]; + vtkXMLDataElement* eCellData = this->CellDataElements[this->Piece]; + + // Split current progress range over number of arrays. This assumes + // that each array contributes approximately the same amount of data + // within this piece. + float progressRange[2] = {0,0}; + int currentArray=0; + int numArrays = this->NumberOfPointArrays + this->NumberOfCellArrays; + this->GetProgressRange(progressRange); + + // Read the data for this piece from each array. + int i; + if(ePointData) + { + int a=0; + for(i=0;(i < ePointData->GetNumberOfNestedElements() && + !this->AbortExecute);++i) + { + vtkXMLDataElement* eNested = ePointData->GetNestedElement(i); + if (this->PointDataArrayIsEnabled(eNested)) + { + if( strcmp(eNested->GetName(), "DataArray") != 0 ) + { + vtkErrorMacro("Invalid DataArray"); + this->DataError = 1; + return 0; + } + int needToRead = this->PointDataNeedToReadTimeStep(eNested); + if( needToRead ) + { + // Set the range of progress for this array. + this->SetProgressRange(progressRange, currentArray++, numArrays); + + // Read the array. + if(!this->ReadArrayForPoints(eNested, pointData->GetArray(a++))) + { + vtkErrorMacro("Cannot read point data array \"" + << pointData->GetArray(a-1)->GetName() << "\" from " + << ePointData->GetName() << " in piece " << this->Piece + << ". The data array in the element may be too short."); + return 0; + } + } + } + } + } + if(eCellData) + { + int a=0; + for(i=0;(i < eCellData->GetNumberOfNestedElements() && + !this->AbortExecute);++i) + { + vtkXMLDataElement* eNested = eCellData->GetNestedElement(i); + if (this->CellDataArrayIsEnabled(eNested)) + { + if( strcmp(eNested->GetName(), "DataArray") != 0 ) + { + this->DataError = 1; + vtkErrorMacro("Invalid DataArray" ); + return 0; + } + int needToRead = this->CellDataNeedToReadTimeStep(eNested); + if( needToRead ) + { + // Set the range of progress for this array. + this->SetProgressRange(progressRange, currentArray++, numArrays); + + // Read the array. + if(!this->ReadArrayForCells(eNested, cellData->GetArray(a++))) + { + vtkErrorMacro("Cannot read cell data array \"" + << cellData->GetArray(a-1)->GetName() << "\" from " + << ePointData->GetName() << " in piece " << this->Piece + << ". The data array in the element may be too short."); + return 0; + } + } + } + } + } + + if(this->AbortExecute) + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::ReadXMLData() +{ + // Let superclasses read data. This also allocates output data. + this->Superclass::ReadXMLData(); + + if (this->FieldDataElement) // read the field data information + { + int i, numTuples; + vtkFieldData *fieldData = this->GetOutputDataObject(0)->GetFieldData(); + for(i=0; i < this->FieldDataElement->GetNumberOfNestedElements() && + !this->AbortExecute; i++) + { + vtkXMLDataElement* eNested = this->FieldDataElement->GetNestedElement(i); + vtkDataArray* array = this->CreateDataArray(eNested); + if (array) + { + if(eNested->GetScalarAttribute("NumberOfTuples", numTuples)) + { + array->SetNumberOfTuples(numTuples); + } + else + { + numTuples = 0; + } + fieldData->AddArray(array); + array->Delete(); + if (!this->ReadData(eNested, array->GetVoidPointer(0), + array->GetDataType(), 0, numTuples*array->GetNumberOfComponents())) + { + this->DataError = 1; + } + } + } + } +} + + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadArrayForPoints(vtkXMLDataElement* da, + vtkDataArray* outArray) +{ + vtkIdType components = outArray->GetNumberOfComponents(); + vtkIdType numberOfTuples = this->GetNumberOfPoints(); + return this->ReadData(da, outArray->GetVoidPointer(0), + outArray->GetDataType(), + 0, numberOfTuples*components); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadArrayForCells(vtkXMLDataElement* da, + vtkDataArray* outArray) +{ + vtkIdType components = outArray->GetNumberOfComponents(); + vtkIdType numberOfTuples = this->GetNumberOfCells(); + return this->ReadData(da, outArray->GetVoidPointer(0), + outArray->GetDataType(), + 0, numberOfTuples*components); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::ReadData(vtkXMLDataElement* da, void* data, int wordType, + vtkIdType startWord, vtkIdType numWords) +{ + // Skip real read if aborting. + if(this->AbortExecute) + { + return 0; + } + + this->InReadData = 1; + vtkIdType num = numWords; + int result; + if(da->GetAttribute("offset")) + { + int offset = 0; + da->GetScalarAttribute("offset", offset); + result = (this->XMLParser->ReadAppendedData(offset, data, startWord, + numWords, wordType) == num); + } + else + { + int isAscii = 1; + const char* format = da->GetAttribute("format"); + if(format && (strcmp(format, "binary") == 0)) + { + isAscii = 0; + } + result = (this->XMLParser->ReadInlineData(da, isAscii, data, + startWord, numWords, wordType) + == num); + } + this->InReadData = 0; + return result; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::DataProgressCallbackFunction(vtkObject*, unsigned long, + void* clientdata, void*) +{ + reinterpret_cast(clientdata)->DataProgressCallback(); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataReader::DataProgressCallback() +{ + if(this->InReadData) + { + float width = this->ProgressRange[1]-this->ProgressRange[0]; + float dataProgress = this->XMLParser->GetProgress(); + float progress = this->ProgressRange[0] + dataProgress*width; + this->UpdateProgressDiscrete(progress); + if(this->AbortExecute) + { + this->XMLParser->SetAbort(1); + } + } +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::PointDataNeedToReadTimeStep(vtkXMLDataElement *eNested) +{ + // First thing need to find the id of this dataarray from its name: + const char* name = eNested->GetAttribute("Name"); + int idx = this->PointDataArraySelection->GetEnabledArrayIndex(name); + + // Easy case no timestep: + int numTimeSteps = eNested->GetVectorAttribute("TimeStep", + this->NumberOfTimeSteps, this->TimeSteps); + if( !(numTimeSteps <= this->NumberOfTimeSteps) ) + { + vtkErrorMacro("Invalid TimeStep specification"); + this->DataError = 1; + return 0; + } + if (!numTimeSteps && !this->NumberOfTimeSteps) + { + assert( this->PointDataTimeStep[idx] == -1 ); //No timestep in this file + return 1; + } + // else TimeStep was specified but no TimeValues associated were found + assert( this->NumberOfTimeSteps ); + + // case numTimeSteps > 1 + int isCurrentTimeInArray = + vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps); + if( numTimeSteps && !isCurrentTimeInArray) + { + return 0; + } + // we know that time steps are specified and that CurrentTimeStep is in the array + // we need to figure out if we need to read the array or if it was forwarded + // Need to check the current 'offset' + unsigned long offset; + if( eNested->GetScalarAttribute("offset", offset) ) + { + if( this->PointDataOffset[idx] != offset ) + { + // save the pointsOffset + assert( this->PointDataTimeStep[idx] == -1 ); //cannot have mixture of binary and appended + this->PointDataOffset[idx] = offset; + return 1; + } + } + else + { + // No offset is specified this is a binary file + // First thing to check if numTimeSteps == 0: + if( !numTimeSteps && this->NumberOfTimeSteps && this->PointDataTimeStep[idx] == -1) + { + // Update last PointsTimeStep read + this->PointDataTimeStep[idx] = this->CurrentTimeStep; + return 1; + } + int isLastTimeInArray = vtkXMLReader::IsTimeStepInArray( + this->PointDataTimeStep[idx], this->TimeSteps, numTimeSteps); + // If no time is specified or if time is specified and match then read + if (isCurrentTimeInArray && !isLastTimeInArray) + { + // CurrentTimeStep is in TimeSteps but Last is not := need to read + // Update last PointsTimeStep read + this->PointDataTimeStep[idx] = this->CurrentTimeStep; + return 1; + } + } + // all other cases we don't need to read: + return 0; +} + +//---------------------------------------------------------------------------- +int vtkXMLDataReader::CellDataNeedToReadTimeStep(vtkXMLDataElement *eNested) +{ + // First thing need to find the id of this dataarray from its name: + const char* name = eNested->GetAttribute("Name"); + int idx = this->CellDataArraySelection->GetEnabledArrayIndex(name); + + // Easy case no timestep: + int numTimeSteps = eNested->GetVectorAttribute("TimeStep", + this->NumberOfTimeSteps, this->TimeSteps); + if( !(numTimeSteps <= this->NumberOfTimeSteps) ) + { + vtkErrorMacro( "Invalid TimeSteps specification"); + this->DataError = 1; + return 0; + } + if (!numTimeSteps && !this->NumberOfTimeSteps) + { + assert( this->CellDataTimeStep[idx] == -1 ); //No timestep in this file + return 1; + } + // else TimeStep was specified but no TimeValues associated were found + assert( this->NumberOfTimeSteps ); + + // case numTimeSteps > 1 + int isCurrentTimeInArray = + vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps); + if( numTimeSteps && !isCurrentTimeInArray) + { + return 0; + } + // we know that time steps are specified and that CurrentTimeStep is in the array + // we need to figure out if we need to read the array or if it was forwarded + // Need to check the current 'offset' + unsigned long offset; + if( eNested->GetScalarAttribute("offset", offset) ) + { + if( this->CellDataOffset[idx] != offset ) + { + // save the pointsOffset + assert( this->CellDataTimeStep[idx] == -1 ); //cannot have mixture of binary and appended + this->CellDataOffset[idx] = offset; + return 1; + } + } + else + { + // No offset is specified this is a binary file + // First thing to check if numTimeSteps == 0: + if( !numTimeSteps && this->NumberOfTimeSteps && this->CellDataTimeStep[idx] == -1) + { + // Update last CellDataTimeStep read + this->CellDataTimeStep[idx] = this->CurrentTimeStep; + return 1; + } + int isLastTimeInArray = vtkXMLReader::IsTimeStepInArray( + this->CellDataTimeStep[idx], this->TimeSteps, numTimeSteps); + // If no time is specified or if time is specified and match then read + if (isCurrentTimeInArray && !isLastTimeInArray) + { + // CurrentTimeStep is in TimeSteps but Last is not := need to read + // Update last CellsTimeStep read + this->CellDataTimeStep[idx] = this->CurrentTimeStep; + return 1; + } + } + // all other cases we don't need to read: + return 0; +} diff --git a/IO/vtkXMLDataReader.h b/IO/vtkXMLDataReader.h new file mode 100644 index 0000000..f30825c --- /dev/null +++ b/IO/vtkXMLDataReader.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLDataReader - Superclass for VTK XML file readers. +// .SECTION Description +// vtkXMLDataReader provides functionality common to all VTK XML file +// readers. Concrete subclasses call upon this functionality when +// needed. + +// .SECTION See Also +// vtkXMLPDataReader + +#ifndef __vtkXMLDataReader_h +#define __vtkXMLDataReader_h + +#include "vtkXMLReader.h" + +class VTK_IO_EXPORT vtkXMLDataReader : public vtkXMLReader +{ +public: + vtkTypeRevisionMacro(vtkXMLDataReader,vtkXMLReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the number of points in the output. + virtual vtkIdType GetNumberOfPoints()=0; + + // Description: + // Get the number of cells in the output. + virtual vtkIdType GetNumberOfCells()=0; + + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); + +protected: + vtkXMLDataReader(); + ~vtkXMLDataReader(); + + // Add functionality to methods from superclass. + virtual void CreateXMLParser(); + virtual void DestroyXMLParser(); + virtual void SetupOutputInformation(vtkInformation *outInfo); + + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + void SetupOutputData(); + + // Setup the reader for a given number of pieces. + virtual void SetupPieces(int numPieces); + virtual void DestroyPieces(); + + // Read information from the file for the given piece. + int ReadPiece(vtkXMLDataElement* ePiece, int piece); + virtual int ReadPiece(vtkXMLDataElement* ePiece); + + // Read data from the file for the given piece. + int ReadPieceData(int piece); + virtual int ReadPieceData(); + + virtual void ReadXMLData(); + + // Read a data array whose tuples coorrespond to points or cells. + virtual int ReadArrayForPoints(vtkXMLDataElement* da, + vtkDataArray* outArray); + virtual int ReadArrayForCells(vtkXMLDataElement* da, + vtkDataArray* outArray); + + // Read data from a given element. + int ReadData(vtkXMLDataElement* da, void* data, int wordType, + vtkIdType startWord, vtkIdType numWords); + + // Callback registered with the DataProgressObserver. + static void DataProgressCallbackFunction(vtkObject*, unsigned long, void*, + void*); + // Progress callback from XMLParser. + virtual void DataProgressCallback(); + + // The number of Pieces of data found in the file. + int NumberOfPieces; + + // The PointData and CellData element representations for each piece. + vtkXMLDataElement** PointDataElements; + vtkXMLDataElement** CellDataElements; + + // The piece currently being read. + int Piece; + + // The number of point/cell data arrays in the output. Valid after + // SetupOutputData has been called. + int NumberOfPointArrays; + int NumberOfCellArrays; + + // Flag for whether DataProgressCallback should actually update + // progress. + int InReadData; + + // The observer to report progress from reading data from XMLParser. + vtkCallbackCommand* DataProgressObserver; + + // Specify the last time step read, usefull to know if we need to rearead data + // //PointData + int *PointDataTimeStep; + unsigned long *PointDataOffset; + int PointDataNeedToReadTimeStep(vtkXMLDataElement *eNested); + + //CellData + int *CellDataTimeStep; + unsigned long *CellDataOffset; + int CellDataNeedToReadTimeStep(vtkXMLDataElement *eNested); + +private: + vtkXMLDataReader(const vtkXMLDataReader&); // Not implemented. + void operator=(const vtkXMLDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLDataSetWriter.cxx b/IO/vtkXMLDataSetWriter.cxx new file mode 100644 index 0000000..9f25842 --- /dev/null +++ b/IO/vtkXMLDataSetWriter.cxx @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLDataSetWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLDataSetWriter.h" + +#include "vtkCallbackCommand.h" +#include "vtkDataSet.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLImageDataWriter.h" +#include "vtkXMLPolyDataWriter.h" +#include "vtkXMLRectilinearGridWriter.h" +#include "vtkXMLStructuredGridWriter.h" +#include "vtkXMLUnstructuredGridWriter.h" + +vtkCxxRevisionMacro(vtkXMLDataSetWriter, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkXMLDataSetWriter); + +//---------------------------------------------------------------------------- +vtkXMLDataSetWriter::vtkXMLDataSetWriter() +{ + // Setup a callback for the internal writer to report progress. + this->ProgressObserver = vtkCallbackCommand::New(); + this->ProgressObserver->SetCallback(&vtkXMLDataSetWriter::ProgressCallbackFunction); + this->ProgressObserver->SetClientData(this); +} + +//---------------------------------------------------------------------------- +vtkXMLDataSetWriter::~vtkXMLDataSetWriter() +{ + this->ProgressObserver->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLDataSetWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkXMLDataSetWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +int vtkXMLDataSetWriter::WriteInternal() +{ + vtkDataSet* input = vtkDataSet::SafeDownCast(this->GetInput()); + vtkXMLWriter* writer = 0; + + // Create a writer based on the data set type. + switch (input->GetDataObjectType()) + { + case VTK_IMAGE_DATA: + case VTK_STRUCTURED_POINTS: + { + vtkXMLImageDataWriter* w = vtkXMLImageDataWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_STRUCTURED_GRID: + { + vtkXMLStructuredGridWriter* w = vtkXMLStructuredGridWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_RECTILINEAR_GRID: + { + vtkXMLRectilinearGridWriter* w = vtkXMLRectilinearGridWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_UNSTRUCTURED_GRID: + { + vtkXMLUnstructuredGridWriter* w = vtkXMLUnstructuredGridWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_POLY_DATA: + { + vtkXMLPolyDataWriter* w = vtkXMLPolyDataWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + } + + // Make sure we got a valid writer for the data set. + if(!writer) + { + vtkErrorMacro("Cannot write dataset type: " + << input->GetDataObjectType()); + return 0; + } + + // Copy the settings to the writer. + writer->SetDebug(this->GetDebug()); + writer->SetFileName(this->GetFileName()); + writer->SetByteOrder(this->GetByteOrder()); + writer->SetCompressor(this->GetCompressor()); + writer->SetBlockSize(this->GetBlockSize()); + writer->SetDataMode(this->GetDataMode()); + writer->SetEncodeAppendedData(this->GetEncodeAppendedData()); + writer->AddObserver(vtkCommand::ProgressEvent, this->ProgressObserver); + + // Try to write. + int result = writer->Write(); + + // Cleanup. + writer->RemoveObserver(this->ProgressObserver); + writer->Delete(); + return result; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLDataSetWriter::GetDataSetName() +{ + return "DataSet"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLDataSetWriter::GetDefaultFileExtension() +{ + return "vtk"; +} + +//---------------------------------------------------------------------------- +void vtkXMLDataSetWriter::ProgressCallbackFunction(vtkObject* caller, + unsigned long, + void* clientdata, void*) +{ + vtkAlgorithm* w = vtkAlgorithm::SafeDownCast(caller); + if(w) + { + reinterpret_cast(clientdata)->ProgressCallback(w); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLDataSetWriter::ProgressCallback(vtkAlgorithm* w) +{ + float width = this->ProgressRange[1]-this->ProgressRange[0]; + float internalProgress = w->GetProgress(); + float progress = this->ProgressRange[0] + internalProgress*width; + this->UpdateProgressDiscrete(progress); + if(this->AbortExecute) + { + w->SetAbortExecute(1); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLDataSetWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} diff --git a/IO/vtkXMLDataSetWriter.h b/IO/vtkXMLDataSetWriter.h new file mode 100644 index 0000000..5687b85 --- /dev/null +++ b/IO/vtkXMLDataSetWriter.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLDataSetWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLDataSetWriter - Write any type of VTK XML file. +// .SECTION Description +// vtkXMLDataSetWriter is a wrapper around the VTK XML file format +// writers. Given an input vtkDataSet, the correct writer is +// automatically selected based on the type of input. + +// .SECTION See Also +// vtkXMLImageDataWriter vtkXMLStructuredGridWriter +// vtkXMLRectilinearGridWriter vtkXMLPolyDataWriter +// vtkXMLUnstructuredGridWriter + +#ifndef __vtkXMLDataSetWriter_h +#define __vtkXMLDataSetWriter_h + +#include "vtkXMLWriter.h" + +class vtkCallbackCommand; + +class VTK_IO_EXPORT vtkXMLDataSetWriter : public vtkXMLWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLDataSetWriter,vtkXMLWriter); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLDataSetWriter* New(); + + //BTX + // Description: + // Get/Set the writer's input. + vtkDataSet* GetInput(); + //ETX + +protected: + vtkXMLDataSetWriter(); + ~vtkXMLDataSetWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + // Override writing method from superclass. + virtual int WriteInternal(); + + // Dummies to satisfy pure virtuals from superclass. + const char* GetDataSetName(); + const char* GetDefaultFileExtension(); + + // Callback registered with the ProgressObserver. + static void ProgressCallbackFunction(vtkObject*, unsigned long, void*, + void*); + // Progress callback from internal writer. + virtual void ProgressCallback(vtkAlgorithm* w); + + // The observer to report progress from the internal writer. + vtkCallbackCommand* ProgressObserver; + +private: + vtkXMLDataSetWriter(const vtkXMLDataSetWriter&); // Not implemented. + void operator=(const vtkXMLDataSetWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLFileReadTester.cxx b/IO/vtkXMLFileReadTester.cxx new file mode 100644 index 0000000..1f387a2 --- /dev/null +++ b/IO/vtkXMLFileReadTester.cxx @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLFileReadTester.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLFileReadTester.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkXMLFileReadTester, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkXMLFileReadTester); + +//---------------------------------------------------------------------------- +vtkXMLFileReadTester::vtkXMLFileReadTester() +{ + this->FileName = 0; + this->FileDataType = 0; + this->FileVersion = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLFileReadTester::~vtkXMLFileReadTester() +{ + this->SetFileName(0); + this->SetFileDataType(0); + this->SetFileVersion(0); +} + +//---------------------------------------------------------------------------- +void vtkXMLFileReadTester::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "FileName: " + << (this->FileName? this->FileName:"") << "\n"; + os << indent << "FileDataType: " + << (this->FileDataType? this->FileDataType:"") << "\n"; + os << indent << "FileVersion: " + << (this->FileVersion? this->FileVersion:"") << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkXMLFileReadTester::TestReadFile() +{ + if(!this->FileName) + { + return 0; + } + + ifstream inFile(this->FileName); + if(!inFile) + { + return 0; + } + + this->SetStream(&inFile); + this->Done = 0; + + this->Parse(); + + if(this->Done) + { + return 1; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLFileReadTester::StartElement(const char* name, const char** atts) +{ + this->Done = 1; + if(strcmp(name, "VTKFile") == 0) + { + unsigned int i; + for(i=0; atts[i] && atts[i+1]; i+=2) + { + if(strcmp(atts[i], "type") == 0) + { + this->SetFileDataType(atts[i+1]); + } + else if(strcmp(atts[i], "version") == 0) + { + this->SetFileVersion(atts[i+1]); + } + } + } +} + +//---------------------------------------------------------------------------- +int vtkXMLFileReadTester::ParsingComplete() +{ + return (this->Done? 1:0); +} diff --git a/IO/vtkXMLFileReadTester.h b/IO/vtkXMLFileReadTester.h new file mode 100644 index 0000000..62dc1fe --- /dev/null +++ b/IO/vtkXMLFileReadTester.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLFileReadTester.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLFileReadTester - Utility class for vtkXMLReader and subclasses. +// .SECTION Description +// vtkXMLFileReadTester reads the smallest part of a file necessary to +// determine whether it is a VTK XML file. If so, it extracts the +// file type and version number. + +#ifndef __vtkXMLFileReadTester_h +#define __vtkXMLFileReadTester_h + +#include "vtkXMLParser.h" + +class VTK_IO_EXPORT vtkXMLFileReadTester: public vtkXMLParser +{ +public: + vtkTypeRevisionMacro(vtkXMLFileReadTester,vtkXMLParser); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLFileReadTester* New(); + + // Description: + // Try to read the file given by FileName. Returns 1 if the file is + // a VTK XML file, and 0 otherwise. + int TestReadFile(); + + // Description: + // Get/Set the name of the file tested by TestReadFile(). + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Get the data type of the XML file tested. If the file could not + // be read, returns NULL. + vtkGetStringMacro(FileDataType); + + // Description: + // Get the file version of the XML file tested. If the file could not + // be read, returns NULL. + vtkGetStringMacro(FileVersion); + +protected: + vtkXMLFileReadTester(); + ~vtkXMLFileReadTester(); + + void StartElement(const char* name, const char** atts); + int ParsingComplete(); + void ReportStrayAttribute(const char*, const char*, const char*) {} + void ReportMissingAttribute(const char*, const char*) {} + void ReportBadAttribute(const char*, const char*, const char*) {} + void ReportUnknownElement(const char*) {} + void ReportXmlParseError() {} + + char* FileName; + char* FileDataType; + char* FileVersion; + int Done; + + vtkSetStringMacro(FileDataType); + vtkSetStringMacro(FileVersion); + +private: + vtkXMLFileReadTester(const vtkXMLFileReadTester&); // Not implemented. + void operator=(const vtkXMLFileReadTester&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLImageDataReader.cxx b/IO/vtkXMLImageDataReader.cxx new file mode 100644 index 0000000..f4044ac --- /dev/null +++ b/IO/vtkXMLImageDataReader.cxx @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLImageDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLImageDataReader.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkXMLDataElement.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLImageDataReader, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkXMLImageDataReader); + +//---------------------------------------------------------------------------- +vtkXMLImageDataReader::vtkXMLImageDataReader() +{ + vtkImageData *output = vtkImageData::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkXMLImageDataReader::~vtkXMLImageDataReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLImageDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLImageDataReader::SetOutput(vtkImageData *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkXMLImageDataReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkXMLImageDataReader::GetOutput(int idx) +{ + return vtkImageData::SafeDownCast( this->GetOutputDataObject(idx) ); +} + + +//---------------------------------------------------------------------------- +const char* vtkXMLImageDataReader::GetDataSetName() +{ + return "ImageData"; +} + +//---------------------------------------------------------------------------- +void vtkXMLImageDataReader::SetOutputExtent(int* extent) +{ + this->GetOutput()->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +int vtkXMLImageDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; } + + // Get the image's origin. + if(ePrimary->GetVectorAttribute("Origin", 3, this->Origin) != 3) + { + this->Origin[0] = 0; + this->Origin[1] = 0; + this->Origin[2] = 0; + } + + // Get the image's spacing. + if(ePrimary->GetVectorAttribute("Spacing", 3, this->Spacing) != 3) + { + this->Spacing[0] = 1; + this->Spacing[1] = 1; + this->Spacing[2] = 1; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Note that any changes (add or removing information) made to this method +// should be replicated in CopyOutputInformation +void vtkXMLImageDataReader::SetupOutputInformation(vtkInformation *outInfo) +{ + this->Superclass::SetupOutputInformation(outInfo); + + outInfo->Set(vtkDataObject::ORIGIN(), this->Origin, 3); + outInfo->Set(vtkDataObject::SPACING(), this->Spacing, 3); +} + + +//---------------------------------------------------------------------------- +void vtkXMLImageDataReader::CopyOutputInformation(vtkInformation *outInfo, int port) +{ + this->Superclass::CopyOutputInformation(outInfo, port); + vtkInformation *localInfo = this->GetExecutive()->GetOutputInformation( port ); + + if ( localInfo->Has(vtkDataObject::ORIGIN()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::ORIGIN() ); + } + if ( localInfo->Has(vtkDataObject::SPACING()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::SPACING() ); + } +} + + +//---------------------------------------------------------------------------- +int vtkXMLImageDataReader::FillOutputPortInformation(int, vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} + diff --git a/IO/vtkXMLImageDataReader.h b/IO/vtkXMLImageDataReader.h new file mode 100644 index 0000000..9c7a78f --- /dev/null +++ b/IO/vtkXMLImageDataReader.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLImageDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLImageDataReader - Read VTK XML ImageData files. +// .SECTION Description +// vtkXMLImageDataReader reads the VTK XML ImageData file format. One +// image data file can be read to produce one output. Streaming is +// supported. The standard extension for this reader's file format is +// "vti". This reader is also used to read a single piece of the +// parallel file format. + +// .SECTION See Also +// vtkXMLPImageDataReader + +#ifndef __vtkXMLImageDataReader_h +#define __vtkXMLImageDataReader_h + +#include "vtkXMLStructuredDataReader.h" + +class vtkImageData; + +class VTK_IO_EXPORT vtkXMLImageDataReader : public vtkXMLStructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLImageDataReader,vtkXMLStructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLImageDataReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkImageData *output); + vtkImageData *GetOutput(); + vtkImageData *GetOutput(int idx); + + // Description: + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); + +protected: + vtkXMLImageDataReader(); + ~vtkXMLImageDataReader(); + + double Origin[3]; + double Spacing[3]; + + const char* GetDataSetName(); + void SetOutputExtent(int* extent); + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + + // Setup the output's information. + void SetupOutputInformation(vtkInformation *outInfo); + + virtual int FillOutputPortInformation(int, vtkInformation*); + +private: + vtkXMLImageDataReader(const vtkXMLImageDataReader&); // Not implemented. + void operator=(const vtkXMLImageDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLImageDataWriter.cxx b/IO/vtkXMLImageDataWriter.cxx new file mode 100644 index 0000000..e40a90c --- /dev/null +++ b/IO/vtkXMLImageDataWriter.cxx @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLImageDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLImageDataWriter.h" +#include "vtkObjectFactory.h" +#include "vtkImageData.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkXMLImageDataWriter, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkXMLImageDataWriter); + +//---------------------------------------------------------------------------- +vtkXMLImageDataWriter::vtkXMLImageDataWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLImageDataWriter::~vtkXMLImageDataWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLImageDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkXMLImageDataWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +void vtkXMLImageDataWriter::GetInputExtent(int* extent) +{ + this->GetInput()->GetExtent(extent); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLImageDataWriter::GetDataSetName() +{ + return "ImageData"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLImageDataWriter::GetDefaultFileExtension() +{ + return "vti"; +} + +//---------------------------------------------------------------------------- +void vtkXMLImageDataWriter::WritePrimaryElementAttributes(ostream &os, vtkIndent indent) +{ + this->Superclass::WritePrimaryElementAttributes(os, indent); + vtkImageData* input = this->GetInput(); + this->WriteVectorAttribute("Origin", 3, input->GetOrigin()); + this->WriteVectorAttribute("Spacing", 3, input->GetSpacing()); +} + +//---------------------------------------------------------------------------- +int vtkXMLImageDataWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} diff --git a/IO/vtkXMLImageDataWriter.h b/IO/vtkXMLImageDataWriter.h new file mode 100644 index 0000000..0668678 --- /dev/null +++ b/IO/vtkXMLImageDataWriter.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLImageDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLImageDataWriter - Write VTK XML ImageData files. +// .SECTION Description +// vtkXMLImageDataWriter writes the VTK XML ImageData file format. +// One image data input can be written into one file in any number of +// streamed pieces. The standard extension for this writer's file +// format is "vti". This writer is also used to write a single piece +// of the parallel file format. + +// .SECTION See Also +// vtkXMLPImageDataWriter + +#ifndef __vtkXMLImageDataWriter_h +#define __vtkXMLImageDataWriter_h + +#include "vtkXMLStructuredDataWriter.h" + +class vtkImageData; + +class VTK_IO_EXPORT vtkXMLImageDataWriter : public vtkXMLStructuredDataWriter +{ +public: + static vtkXMLImageDataWriter* New(); + vtkTypeRevisionMacro(vtkXMLImageDataWriter,vtkXMLStructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkImageData* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLImageDataWriter(); + ~vtkXMLImageDataWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + void WritePrimaryElementAttributes(ostream &os, vtkIndent indent); + void GetInputExtent(int* extent); + const char* GetDataSetName(); + +private: + vtkXMLImageDataWriter(const vtkXMLImageDataWriter&); // Not implemented. + void operator=(const vtkXMLImageDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPDataReader.cxx b/IO/vtkXMLPDataReader.cxx new file mode 100644 index 0000000..2b3c89b --- /dev/null +++ b/IO/vtkXMLPDataReader.cxx @@ -0,0 +1,511 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPDataReader.h" + +#include "vtkCallbackCommand.h" +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDataArraySelection.h" +#include "vtkDataSet.h" +#include "vtkPointData.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLDataReader.h" +#include "vtkInformationVector.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLPDataReader, "$Revision: 1.17 $"); + +//---------------------------------------------------------------------------- +vtkXMLPDataReader::vtkXMLPDataReader() +{ + this->GhostLevel = 0; + + this->NumberOfPieces = 0; + + this->PieceElements = 0; + this->PieceReaders = 0; + this->CanReadPieceFlag = 0; + + this->PathName = 0; + + // Setup a callback for the internal serial readers to report + // progress. + this->PieceProgressObserver = vtkCallbackCommand::New(); + this->PieceProgressObserver->SetCallback(&vtkXMLPDataReader::PieceProgressCallbackFunction); + this->PieceProgressObserver->SetClientData(this); +} + +//---------------------------------------------------------------------------- +vtkXMLPDataReader::~vtkXMLPDataReader() +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } + if(this->PathName) + { + delete [] this->PathName; + } + this->PieceProgressObserver->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n"; +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkXMLPDataReader::GetPieceInputAsDataSet(int piece) +{ + vtkXMLDataReader* reader = this->PieceReaders[piece]; + if(!reader) + { + return 0; + } + if(reader->GetNumberOfOutputPorts() < 1) + { + return 0; + } + return static_cast(reader->GetExecutive()->GetOutputData(0)); +} + + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + // Setup the output arrays. + vtkXMLDataElement* ePointData = this->PPointDataElement; + vtkXMLDataElement* eCellData = this->PCellDataElement; + vtkPointData* pointData = this->GetOutputAsDataSet(0)->GetPointData(); + vtkCellData* cellData = this->GetOutputAsDataSet(0)->GetCellData(); + + // Get the size of the output arrays. + unsigned long pointTuples = this->GetNumberOfPoints(); + unsigned long cellTuples = this->GetNumberOfCells(); + + // Allocate data in the arrays. + int i; + if(ePointData) + { + for(i=0;i < ePointData->GetNumberOfNestedElements();++i) + { + vtkXMLDataElement* eNested = ePointData->GetNestedElement(i); + if(this->PointDataArrayIsEnabled(eNested)) + { + vtkDataArray* array = this->CreateDataArray(eNested); + if(array) + { + array->SetNumberOfTuples(pointTuples); + pointData->AddArray(array); + array->Delete(); + } + else + { + this->DataError = 1; + } + } + } + } + + if(eCellData) + { + for(i = 0; i < eCellData->GetNumberOfNestedElements(); i++) + { + vtkXMLDataElement* eNested = eCellData->GetNestedElement(i); + if(this->CellDataArrayIsEnabled(eNested)) + { + vtkDataArray* array = this->CreateDataArray(eNested); + if(array) + { + array->SetNumberOfTuples(cellTuples); + cellData->AddArray(array); + array->Delete(); + } + else + { + this->DataError = 1; + } + } + } + } + + // Setup attribute indices for the point data and cell data. + this->ReadAttributeIndices(ePointData, pointData); + this->ReadAttributeIndices(eCellData, cellData); + +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataReader::ReadXMLInformation() +{ + // First setup the filename components. + this->SplitFileName(); + + // Now proceed with reading the information. + return this->Superclass::ReadXMLInformation(); +} + + +//---------------------------------------------------------------------------- +// Note that any changes (add or removing information) made to this method +// should be replicated in CopyOutputInformation +void vtkXMLPDataReader::SetupOutputInformation(vtkInformation *outInfo) +{ + if (this->InformationError) + { + vtkErrorMacro("Should not still be processing output information if have set InformationError"); + return; + } + + // Initialize DataArraySelections to anable all that are present + this->SetDataArraySelections(this->PPointDataElement, this->PointDataArraySelection); + this->SetDataArraySelections(this->PCellDataElement, this->CellDataArraySelection); + + // Setup the Field Information for PointData. We only need the + // information from one piece because all pieces have the same set of arrays. + vtkInformationVector *infoVector = NULL; + if (!this->SetFieldDataInfo(this->PPointDataElement, + vtkDataObject::FIELD_ASSOCIATION_POINTS, this->GetNumberOfPoints(), infoVector)) + { + return; + } + if (infoVector) + { + outInfo->Set(vtkDataObject::POINT_DATA_VECTOR(), infoVector); + infoVector->Delete(); + } + + // now the Cell data + infoVector = NULL; + if (!this->SetFieldDataInfo(this->PCellDataElement, + vtkDataObject::FIELD_ASSOCIATION_CELLS, this->GetNumberOfCells(), infoVector)) + { + return; + } + if (infoVector) + { + outInfo->Set(vtkDataObject::CELL_DATA_VECTOR(), infoVector); + infoVector->Delete(); + } + +} + + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::CopyOutputInformation(vtkInformation *outInfo, int port) + { + vtkInformation *localInfo = this->GetExecutive()->GetOutputInformation( port ); + if ( localInfo->Has(vtkDataObject::POINT_DATA_VECTOR()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::POINT_DATA_VECTOR() ); + } + if ( localInfo->Has(vtkDataObject::CELL_DATA_VECTOR()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::CELL_DATA_VECTOR() ); + } + } + + +//---------------------------------------------------------------------------- +int vtkXMLPDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) + { + return 0; + } + // Read information about the data. + if(!ePrimary->GetScalarAttribute("GhostLevel", this->GhostLevel)) + { + this->GhostLevel = 0; + } + + // Read information about the pieces. + this->PPointDataElement = 0; + this->PCellDataElement = 0; + int i; + int numNested = ePrimary->GetNumberOfNestedElements(); + int numPieces = 0; + for(i=0;i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if(strcmp(eNested->GetName(), "Piece") == 0) + { + ++numPieces; + } + else if(strcmp(eNested->GetName(), "PPointData") == 0) + { + this->PPointDataElement = eNested; + } + else if(strcmp(eNested->GetName(), "PCellData") == 0) + { + this->PCellDataElement = eNested; + } + } + this->SetupPieces(numPieces); + int piece = 0; + for(i=0;i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if(strcmp(eNested->GetName(), "Piece") == 0) + { + if(!this->ReadPiece(eNested, piece++)) + { + return 0; + } + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::SetupPieces(int numPieces) +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } + this->NumberOfPieces = numPieces; + this->PieceElements = new vtkXMLDataElement*[this->NumberOfPieces]; + this->PieceReaders = new vtkXMLDataReader*[this->NumberOfPieces]; + this->CanReadPieceFlag = new int[this->NumberOfPieces]; + int i; + for(i=0;i < this->NumberOfPieces;++i) + { + this->PieceElements[i] = 0; + this->PieceReaders[i] = 0; + this->CanReadPieceFlag[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::DestroyPieces() +{ + int i; + for(i=0;i < this->NumberOfPieces;++i) + { + if(this->PieceReaders[i]) + { + this->PieceReaders[i]->RemoveObserver(this->PieceProgressObserver); + this->PieceReaders[i]->Delete(); + } + } + delete [] this->PieceElements; + delete [] this->CanReadPieceFlag; + delete [] this->PieceReaders; + this->PieceElements = 0; + this->PieceReaders = 0; + this->NumberOfPieces = 0; +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece, int index) +{ + this->Piece = index; + return this->ReadPiece(ePiece); +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + this->PieceElements[this->Piece] = ePiece; + + const char* fileName = ePiece->GetAttribute("Source"); + if(!fileName) + { + vtkErrorMacro("Piece " << this->Piece << " has no Source attribute."); + return 0; + } + + // The file name is relative to the summary file. Convert it to + // something we can use. + char *pieceFileName = this->CreatePieceFileName(fileName); + + vtkXMLDataReader* reader = this->CreatePieceReader(); + this->PieceReaders[this->Piece] = reader; + this->PieceReaders[this->Piece]->AddObserver(vtkCommand::ProgressEvent, + this->PieceProgressObserver); + reader->SetFileName(pieceFileName); + + delete [] pieceFileName; + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataReader::ReadPieceData(int index) +{ + this->Piece = index; + + // We need data, make sure the piece can be read. + if(!this->CanReadPiece(this->Piece)) + { + vtkErrorMacro("File for piece " << this->Piece << " cannot be read."); + return 0; + } + + // Actually read the data. + this->PieceReaders[this->Piece]->SetAbortExecute(0); + vtkDataArraySelection* pds = + this->PieceReaders[this->Piece]->GetPointDataArraySelection(); + vtkDataArraySelection* cds = + this->PieceReaders[this->Piece]->GetCellDataArraySelection(); + pds->CopySelections(this->PointDataArraySelection); + cds->CopySelections(this->CellDataArraySelection); + return this->ReadPieceData(); +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataReader::ReadPieceData() +{ + vtkDataSet* input = this->GetPieceInputAsDataSet(this->Piece); + vtkDataSet* output = this->GetOutputAsDataSet(0); + + // copy any field data + if (input->GetFieldData()) + { + int i; + for (i = 0; i < input->GetFieldData()->GetNumberOfArrays(); i++) + { + output->GetFieldData()->AddArray( input->GetFieldData()->GetArray(i) ); + } + } + + // Copy point data and cell data for this piece. + int i; + for(i=0;i < output->GetPointData()->GetNumberOfArrays();++i) + { + this->CopyArrayForPoints(input->GetPointData()->GetArray(i), + output->GetPointData()->GetArray(i)); + } + for(i=0;i < output->GetCellData()->GetNumberOfArrays();++i) + { + this->CopyArrayForCells(input->GetCellData()->GetArray(i), + output->GetCellData()->GetArray(i)); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataReader::CanReadPiece(int index) +{ + // If necessary, test whether the piece can be read. + vtkXMLDataReader* reader = this->PieceReaders[index]; + if(reader && !this->CanReadPieceFlag[index]) + { + if(reader->CanReadFile(reader->GetFileName())) + { + // We can read the piece. Save result to avoid later repeat of + // test. + this->CanReadPieceFlag[index] = 1; + } + else + { + // We cannot read the piece. Destroy the reader to avoid later + // repeat of test. + this->PieceReaders[index] = 0; + reader->Delete(); + } + } + + return (this->PieceReaders[index]? 1:0); +} + +//---------------------------------------------------------------------------- +char* vtkXMLPDataReader::CreatePieceFileName(const char* fileName) +{ + ostrstream fn_with_warning_C4701; + if(this->PathName) + { + fn_with_warning_C4701 << this->PathName; + } + fn_with_warning_C4701 << fileName << ends; + return fn_with_warning_C4701.str(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::SplitFileName() +{ + if(!this->FileName) + { + vtkErrorMacro( << "Need to specify a filename" ); + return; + } + + // Pull the PathName component out of the FileName. + size_t length = strlen(this->FileName); + char* fileName = new char[length+1]; + strcpy(fileName, this->FileName); + char* begin = fileName; + char* end = fileName + length; + char* s; + +#if defined(_WIN32) + // Convert to UNIX-style slashes. + for(s=begin;s != end;++s) { if(*s == '\\') { *s = '/'; } } +#endif + + // Extract the path name up to the last '/'. + if(this->PathName) + { + delete [] this->PathName; + this->PathName = 0; + } + char* rbegin = end-1; + char* rend = begin-1; + for(s=rbegin;s != rend;--s) + { + if(*s == '/') + { + break; + } + } + if(s >= begin) + { + length = (s-begin)+1; + this->PathName = new char[length+1]; + strncpy(this->PathName, this->FileName, length); + this->PathName[length] = '\0'; + } + + // Cleanup temporary name. + delete [] fileName; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::PieceProgressCallbackFunction(vtkObject*, unsigned long, + void* clientdata, void*) +{ + reinterpret_cast(clientdata)->PieceProgressCallback(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataReader::PieceProgressCallback() +{ + float width = this->ProgressRange[1]-this->ProgressRange[0]; + float pieceProgress = this->PieceReaders[this->Piece]->GetProgress(); + float progress = this->ProgressRange[0] + pieceProgress*width; + this->UpdateProgressDiscrete(progress); + if(this->AbortExecute) + { + this->PieceReaders[this->Piece]->SetAbortExecute(1); + } +} diff --git a/IO/vtkXMLPDataReader.h b/IO/vtkXMLPDataReader.h new file mode 100644 index 0000000..34efb65 --- /dev/null +++ b/IO/vtkXMLPDataReader.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPDataReader - Superclass for PVTK XML file readers. +// .SECTION Description +// vtkXMLPDataReader provides functionality common to all PVTK XML +// file readers. Concrete subclasses call upon this functionality +// when needed. + +// .SECTION See Also +// vtkXMLDataReader + +#ifndef __vtkXMLPDataReader_h +#define __vtkXMLPDataReader_h + +#include "vtkXMLReader.h" + +class vtkDataArray; +class vtkDataSet; +class vtkXMLDataReader; + +class VTK_IO_EXPORT vtkXMLPDataReader : public vtkXMLReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPDataReader,vtkXMLReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the number of pieces from the summary file being read. + vtkGetMacro(NumberOfPieces, int); + + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); + +protected: + vtkXMLPDataReader(); + ~vtkXMLPDataReader(); + + // Pipeline execute information driver. Called by vtkXMLReader. + int ReadXMLInformation(); + virtual void SetupOutputInformation(vtkInformation *outInfo); + + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + + vtkDataSet* GetPieceInputAsDataSet(int piece); + void SetupOutputData(); + + virtual vtkXMLDataReader* CreatePieceReader()=0; + virtual vtkIdType GetNumberOfPoints()=0; + virtual vtkIdType GetNumberOfCells()=0; + virtual void CopyArrayForPoints(vtkDataArray* inArray, + vtkDataArray* outArray)=0; + virtual void CopyArrayForCells(vtkDataArray* inArray, + vtkDataArray* outArray)=0; + + virtual void SetupPieces(int numPieces); + virtual void DestroyPieces(); + int ReadPiece(vtkXMLDataElement* ePiece, int index); + virtual int ReadPiece(vtkXMLDataElement* ePiece); + int ReadPieceData(int index); + virtual int ReadPieceData(); + int CanReadPiece(int index); + + char* CreatePieceFileName(const char* fileName); + void SplitFileName(); + + // Callback registered with the PieceProgressObserver. + static void PieceProgressCallbackFunction(vtkObject*, unsigned long, void*, + void*); + virtual void PieceProgressCallback(); + + // Pieces from the input summary file. + int NumberOfPieces; + + // The ghost level available on each input piece. + int GhostLevel; + + // The piece currently being read. + int Piece; + + // The path to the input file without the file name. + char* PathName; + + // Information per-piece. + vtkXMLDataElement** PieceElements; + vtkXMLDataReader** PieceReaders; + int* CanReadPieceFlag; + + // The PPointData and PCellData element representations. + vtkXMLDataElement* PPointDataElement; + vtkXMLDataElement* PCellDataElement; + + // The observer to report progress from reading serial data in each + // piece. + vtkCallbackCommand* PieceProgressObserver; + +private: + vtkXMLPDataReader(const vtkXMLPDataReader&); // Not implemented. + void operator=(const vtkXMLPDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPDataSetWriter.cxx b/IO/vtkXMLPDataSetWriter.cxx new file mode 100644 index 0000000..a3394bc --- /dev/null +++ b/IO/vtkXMLPDataSetWriter.cxx @@ -0,0 +1,165 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPDataSetWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPDataSetWriter.h" + +#include "vtkCallbackCommand.h" +#include "vtkDataSet.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLPImageDataWriter.h" +#include "vtkXMLPPolyDataWriter.h" +#include "vtkXMLPRectilinearGridWriter.h" +#include "vtkXMLPStructuredGridWriter.h" +#include "vtkXMLPUnstructuredGridWriter.h" + +vtkCxxRevisionMacro(vtkXMLPDataSetWriter, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkXMLPDataSetWriter); + +//---------------------------------------------------------------------------- +vtkXMLPDataSetWriter::vtkXMLPDataSetWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLPDataSetWriter::~vtkXMLPDataSetWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataSetWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkXMLPDataSetWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataSetWriter::WriteInternal() +{ + vtkDataSet* input = this->GetInput(); + vtkXMLPDataWriter* writer = 0; + + // Create a writer based on the data set type. + switch (input->GetDataObjectType()) + { + case VTK_IMAGE_DATA: + case VTK_STRUCTURED_POINTS: + { + vtkXMLPImageDataWriter* w = vtkXMLPImageDataWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_STRUCTURED_GRID: + { + vtkXMLPStructuredGridWriter* w = vtkXMLPStructuredGridWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_RECTILINEAR_GRID: + { + vtkXMLPRectilinearGridWriter* w = vtkXMLPRectilinearGridWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_UNSTRUCTURED_GRID: + { + vtkXMLPUnstructuredGridWriter* w = vtkXMLPUnstructuredGridWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + case VTK_POLY_DATA: + { + vtkXMLPPolyDataWriter* w = vtkXMLPPolyDataWriter::New(); + w->SetInput(static_cast(input)); + writer = w; + } break; + } + + // Make sure we got a valid writer for the data set. + if(!writer) + { + vtkErrorMacro("Cannot write dataset type: " + << input->GetDataObjectType()); + return 0; + } + + // Copy the settings to the writer. + writer->SetDebug(this->GetDebug()); + writer->SetFileName(this->GetFileName()); + writer->SetByteOrder(this->GetByteOrder()); + writer->SetCompressor(this->GetCompressor()); + writer->SetBlockSize(this->GetBlockSize()); + writer->SetDataMode(this->GetDataMode()); + writer->SetEncodeAppendedData(this->GetEncodeAppendedData()); + writer->SetNumberOfPieces(this->GetNumberOfPieces()); + writer->SetGhostLevel(this->GetGhostLevel()); + writer->SetStartPiece(this->GetStartPiece()); + writer->SetEndPiece(this->GetEndPiece()); + writer->AddObserver(vtkCommand::ProgressEvent, this->ProgressObserver); + + // Decide whether to write the summary file. + int writeSummary = 0; + if(this->WriteSummaryFileInitialized) + { + writeSummary = this->WriteSummaryFile; + } + else if(this->StartPiece == 0) + { + writeSummary = 1; + } + writer->SetWriteSummaryFile(writeSummary); + + // Try to write. + int result = writer->Write(); + + // Cleanup. + writer->RemoveObserver(this->ProgressObserver); + writer->Delete(); + return result; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPDataSetWriter::GetDataSetName() +{ + return "DataSet"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPDataSetWriter::GetDefaultFileExtension() +{ + return "vtk"; +} + +//---------------------------------------------------------------------------- +vtkXMLWriter* vtkXMLPDataSetWriter::CreatePieceWriter(int) +{ + return 0; +} +//---------------------------------------------------------------------------- +int vtkXMLPDataSetWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} diff --git a/IO/vtkXMLPDataSetWriter.h b/IO/vtkXMLPDataSetWriter.h new file mode 100644 index 0000000..943f920 --- /dev/null +++ b/IO/vtkXMLPDataSetWriter.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPDataSetWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPDataSetWriter - Write any type of PVTK XML file. +// .SECTION Description +// vtkXMLPDataSetWriter is a wrapper around the PVTK XML file format +// writers. Given an input vtkDataSet, the correct writer is +// automatically selected based on the type of input. + +// .SECTION See Also +// vtkXMLPImageDataWriter vtkXMLPStructuredGridWriter +// vtkXMLPRectilinearGridWriter vtkXMLPPolyDataWriter +// vtkXMLPUnstructuredGridWriter + +#ifndef __vtkXMLPDataSetWriter_h +#define __vtkXMLPDataSetWriter_h + +#include "vtkXMLPDataWriter.h" + +class VTK_IO_EXPORT vtkXMLPDataSetWriter : public vtkXMLPDataWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLPDataSetWriter,vtkXMLPDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPDataSetWriter* New(); + + //BTX + // Description: + // Get/Set the writer's input. + vtkDataSet* GetInput(); + //ETX + +protected: + vtkXMLPDataSetWriter(); + ~vtkXMLPDataSetWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + // Override writing method from superclass. + virtual int WriteInternal(); + + // Dummies to satisfy pure virtuals from superclass. + const char* GetDataSetName(); + const char* GetDefaultFileExtension(); + vtkXMLWriter* CreatePieceWriter(int index); + +private: + vtkXMLPDataSetWriter(const vtkXMLPDataSetWriter&); // Not implemented. + void operator=(const vtkXMLPDataSetWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPDataWriter.cxx b/IO/vtkXMLPDataWriter.cxx new file mode 100644 index 0000000..52a1c64 --- /dev/null +++ b/IO/vtkXMLPDataWriter.cxx @@ -0,0 +1,365 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPDataWriter.h" + +#include "vtkCallbackCommand.h" +#include "vtkDataSet.h" +#include "vtkErrorCode.h" + +vtkCxxRevisionMacro(vtkXMLPDataWriter, "$Revision: 1.15 $"); + +//---------------------------------------------------------------------------- +vtkXMLPDataWriter::vtkXMLPDataWriter() +{ + this->StartPiece = 0; + this->EndPiece = 0; + this->NumberOfPieces = 1; + this->GhostLevel = 0; + this->WriteSummaryFileInitialized = 0; + this->WriteSummaryFile = 0; + + this->PathName = 0; + this->FileNameBase = 0; + this->FileNameExtension = 0; + this->PieceFileNameExtension = 0; + + // Setup a callback for the internal writer to report progress. + this->ProgressObserver = vtkCallbackCommand::New(); + this->ProgressObserver->SetCallback(&vtkXMLPDataWriter::ProgressCallbackFunction); + this->ProgressObserver->SetClientData(this); +} + +//---------------------------------------------------------------------------- +vtkXMLPDataWriter::~vtkXMLPDataWriter() +{ + if(this->PathName) { delete [] this->PathName; } + if(this->FileNameBase) { delete [] this->FileNameBase; } + if(this->FileNameExtension) { delete [] this->FileNameExtension; } + if(this->PieceFileNameExtension) { delete [] this->PieceFileNameExtension; } + this->ProgressObserver->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n"; + os << indent << "StartPiece: " << this->StartPiece << "\n"; + os << indent << "EndPiece: " << this->EndPiece << "\n"; + os << indent << "GhostLevel: " << this->GhostLevel << "\n"; + os << indent << "WriteSummaryFile: " << this->WriteSummaryFile << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::SetWriteSummaryFile(int flag) +{ + this->WriteSummaryFileInitialized = 1; + vtkDebugMacro(<< this->GetClassName() << " (" + << this << "): setting WriteSummaryFile to " << flag); + if(this->WriteSummaryFile != flag) + { + this->WriteSummaryFile = flag; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataWriter::WriteInternal() +{ + // Prepare the file name. + this->SplitFileName(); + + // Write the pieces now so the data are up to date. + int result = this->WritePieces(); + if (!result) + { + return result; + } + + // Decide whether to write the summary file. + int writeSummary = 0; + if(this->WriteSummaryFileInitialized) + { + writeSummary = this->WriteSummaryFile; + } + else if(this->StartPiece == 0) + { + writeSummary = 1; + } + + // Write the summary file if requested. + if(result && writeSummary) + { + if(!this->Superclass::WriteInternal()) + { + int i; + vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); + + for (i = this->StartPiece; i < this->EndPiece; i++) + { + char* fileName = this->CreatePieceFileName(i, this->PathName); + this->DeleteAFile(fileName); + delete [] fileName; + } + return 0; + } + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::WritePrimaryElementAttributes(ostream &, vtkIndent) +{ + this->WriteScalarAttribute("GhostLevel", this->GhostLevel); +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataWriter::WriteData() +{ + // Write the summary file. + ostream& os = *(this->Stream); + vtkIndent indent = vtkIndent().GetNextIndent(); + vtkIndent nextIndent = indent.GetNextIndent(); + + this->StartFile(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + os << indent << "<" << this->GetDataSetName(); + this->WritePrimaryElementAttributes(os, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + os << ">\n"; + + // Write the information needed for a reader to produce the output's + // information during UpdateInformation without reading a piece. + this->WritePData(indent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + // Write the elements referencing each piece and its file. + int i; + for(i=0;i < this->NumberOfPieces; ++i) + { + os << nextIndent << "WritePPieceAttributes(i); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + os << "/>\n"; + } + + os << indent << "GetDataSetName() << ">\n"; + + this->EndFile(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::WritePData(vtkIndent indent) +{ + vtkDataSet* input = this->GetInputAsDataSet(); + this->WritePPointData(input->GetPointData(), indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->WritePCellData(input->GetCellData(), indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::WritePPieceAttributes(int index) +{ + char* fileName = this->CreatePieceFileName(index); + this->WriteStringAttribute("Source", fileName); + delete [] fileName; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::SplitFileName() +{ + // Split the FileName into its PathName, FileNameBase, and + // FileNameExtension components. + size_t length = strlen(this->FileName); + char* fileName = new char[length+1]; + strcpy(fileName, this->FileName); + char* begin = fileName; + char* end = fileName + length; + char* s; + +#if defined(_WIN32) + // Convert to UNIX-style slashes. + for(s=begin;s != end;++s) { if(*s == '\\') { *s = '/'; } } +#endif + + // Extract the path name up to the last '/'. + if(this->PathName) { delete [] this->PathName; this->PathName = 0; } + char* rbegin = end-1; + char* rend = begin-1; + for(s=rbegin;s != rend;--s) { if(*s == '/') { break; } } + if(s >= begin) + { + length = (s-begin)+1; + this->PathName = new char[length+1]; + strncpy(this->PathName, this->FileName, length); + this->PathName[length] = '\0'; + begin = s+1; + } + + // "begin" now points at the beginning of the file name. + // Look for the first "." to pull off the longest extension. + if(this->FileNameExtension) + { delete [] this->FileNameExtension; this->FileNameExtension = 0; } + for(s=begin; s != end; ++s) { if(*s == '.') { break; } } + if(s < end) + { + length = end-s; + this->FileNameExtension = new char[length+1]; + strncpy(this->FileNameExtension, s, length); + this->FileNameExtension[length] = '\0'; + end = s; + } + + // "end" now points to end of the file name. + if(this->FileNameBase) { delete [] this->FileNameBase; } + length = end-begin; + this->FileNameBase = new char[length+1]; + strncpy(this->FileNameBase, begin, length); + this->FileNameBase[length] = '\0'; + + // Cleanup temporary name. + delete [] fileName; +} + +//---------------------------------------------------------------------------- +char* vtkXMLPDataWriter::CreatePieceFileName(int index, const char* path) +{ + ostrstream fn_with_warning_C4701; + if(path) { fn_with_warning_C4701 << path; } + fn_with_warning_C4701 << this->FileNameBase << "_" << index; + if(this->PieceFileNameExtension) + { fn_with_warning_C4701 << this->PieceFileNameExtension; } + //if(this->FileNameExtension) + //{ fn_with_warning_C4701 << this->FileNameExtension; } + fn_with_warning_C4701 << ends; + return fn_with_warning_C4701.str(); +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataWriter::WritePieces() +{ + // Split progress range by piece. Just assume all pieces are the + // same size. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + // Write each piece from StartPiece to EndPiece. + int i; + for(i=this->StartPiece; i <= this->EndPiece; ++i) + { + this->SetProgressRange(progressRange, i-this->StartPiece, + this->EndPiece-this->StartPiece+1); + if(!this->WritePiece(i)) + { + // Writing a piece failed. Delete files for previous pieces and + // abort. + vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); + + for(int j=this->StartPiece; j < i; ++j) + { + char* fileName = this->CreatePieceFileName(j, this->PathName); + this->DeleteAFile(fileName); + delete [] fileName; + } + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataWriter::WritePiece(int index) +{ + // Create the writer for the piece. Its configuration should match + // our own writer. + vtkXMLWriter* pWriter = this->CreatePieceWriter(index); + pWriter->AddObserver(vtkCommand::ProgressEvent, this->ProgressObserver); + + // Set the file name. + if(!this->PieceFileNameExtension) + { + const char* ext = pWriter->GetDefaultFileExtension(); + this->PieceFileNameExtension = new char[strlen(ext)+2]; + this->PieceFileNameExtension[0] = '.'; + strcpy(this->PieceFileNameExtension+1, ext); + } + char* fileName = this->CreatePieceFileName(index, this->PathName); + pWriter->SetFileName(fileName); + delete [] fileName; + + // Copy the writer settings. + pWriter->SetCompressor(this->Compressor); + pWriter->SetDataMode(this->DataMode); + pWriter->SetByteOrder(this->ByteOrder); + pWriter->SetEncodeAppendedData(this->EncodeAppendedData); + + // Write the piece. + int result = pWriter->Write(); + this->SetErrorCode(pWriter->GetErrorCode()); + + // Cleanup. + pWriter->RemoveObserver(this->ProgressObserver); + pWriter->Delete(); + + return result; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::ProgressCallbackFunction(vtkObject* caller, + unsigned long, + void* clientdata, void*) +{ + vtkAlgorithm* w = vtkAlgorithm::SafeDownCast(caller); + if(w) + { + reinterpret_cast(clientdata)->ProgressCallback(w); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataWriter::ProgressCallback(vtkAlgorithm* w) +{ + float width = this->ProgressRange[1]-this->ProgressRange[0]; + float internalProgress = w->GetProgress(); + float progress = this->ProgressRange[0] + internalProgress*width; + this->UpdateProgressDiscrete(progress); + if(this->AbortExecute) + { + w->SetAbortExecute(1); + } +} diff --git a/IO/vtkXMLPDataWriter.h b/IO/vtkXMLPDataWriter.h new file mode 100644 index 0000000..38d9256 --- /dev/null +++ b/IO/vtkXMLPDataWriter.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPDataWriter - Write data in a parallel XML format. +// .SECTION Description +// vtkXMLPDataWriter is the superclass for all XML parallel data set +// writers. It provides functionality needed for writing parallel +// formats, such as the selection of which writer writes the summary +// file and what range of pieces are assigned to each serial writer. + +#ifndef __vtkXMLPDataWriter_h +#define __vtkXMLPDataWriter_h + +#include "vtkXMLWriter.h" + +class vtkCallbackCommand; + +class VTK_IO_EXPORT vtkXMLPDataWriter : public vtkXMLWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLPDataWriter,vtkXMLWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get/Set the number of pieces that are being written in parallel. + vtkSetMacro(NumberOfPieces, int); + vtkGetMacro(NumberOfPieces, int); + + // Description: + // Get/Set the range of pieces assigned to this writer. + vtkSetMacro(StartPiece, int); + vtkGetMacro(StartPiece, int); + vtkSetMacro(EndPiece, int); + vtkGetMacro(EndPiece, int); + + // Description: + // Get/Set the ghost level used for this writer's piece. + vtkSetMacro(GhostLevel, int); + vtkGetMacro(GhostLevel, int); + + // Description: + // Get/Set whether this instance of the writer should write the + // summary file that refers to all of the pieces' individual files. + // Default is yes only for piece 0 writer. + virtual void SetWriteSummaryFile(int flag); + vtkGetMacro(WriteSummaryFile, int); + vtkBooleanMacro(WriteSummaryFile, int); + +protected: + vtkXMLPDataWriter(); + ~vtkXMLPDataWriter(); + + // Override writing method from superclass. + virtual int WriteInternal(); + + virtual vtkXMLWriter* CreatePieceWriter(int index)=0; + + virtual void WritePrimaryElementAttributes(ostream &os, vtkIndent indent); + int WriteData(); + virtual void WritePData(vtkIndent indent); + virtual void WritePPieceAttributes(int index); + + char* CreatePieceFileName(int index, const char* path=0); + void SplitFileName(); + int WritePieces(); + int WritePiece(int index); + + // Callback registered with the ProgressObserver. + static void ProgressCallbackFunction(vtkObject*, unsigned long, void*, + void*); + // Progress callback from internal writer. + virtual void ProgressCallback(vtkAlgorithm* w); + + int StartPiece; + int EndPiece; + int NumberOfPieces; + int GhostLevel; + int WriteSummaryFile; + int WriteSummaryFileInitialized; + + char* PathName; + char* FileNameBase; + char* FileNameExtension; + char* PieceFileNameExtension; + + // The observer to report progress from the internal writer. + vtkCallbackCommand* ProgressObserver; + +private: + vtkXMLPDataWriter(const vtkXMLPDataWriter&); // Not implemented. + void operator=(const vtkXMLPDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPImageDataReader.cxx b/IO/vtkXMLPImageDataReader.cxx new file mode 100644 index 0000000..4681247 --- /dev/null +++ b/IO/vtkXMLPImageDataReader.cxx @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPImageDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPImageDataReader.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLImageDataReader.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLPImageDataReader, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkXMLPImageDataReader); + +//---------------------------------------------------------------------------- +vtkXMLPImageDataReader::vtkXMLPImageDataReader() +{ + vtkImageData *output = vtkImageData::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkXMLPImageDataReader::~vtkXMLPImageDataReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPImageDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPImageDataReader::SetOutput(vtkImageData *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkXMLPImageDataReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkXMLPImageDataReader::GetOutput(int idx) +{ + return vtkImageData::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkXMLPImageDataReader::GetPieceInput(int index) +{ + vtkXMLImageDataReader* reader = + static_cast(this->PieceReaders[index]); + return reader->GetOutput(); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPImageDataReader::GetDataSetName() +{ + return "PImageData"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPImageDataReader::SetOutputExtent(int* extent) +{ + this->GetOutput()->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPImageDataReader::GetPieceInputExtent(int index, int* extent) +{ + this->GetPieceInput(index)->GetExtent(extent); +} + +//---------------------------------------------------------------------------- +int vtkXMLPImageDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; } + + // Get the image's origin. + if(ePrimary->GetVectorAttribute("Origin", 3, this->Origin) != 3) + { + this->Origin[0] = 0; + this->Origin[1] = 0; + this->Origin[2] = 0; + } + + // Get the image's spacing. + if(ePrimary->GetVectorAttribute("Spacing", 3, this->Spacing) != 3) + { + this->Spacing[0] = 1; + this->Spacing[1] = 1; + this->Spacing[2] = 1; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Note that any changes (add or removing information) made to this method +// should be replicated in CopyOutputInformation +void vtkXMLPImageDataReader::SetupOutputInformation(vtkInformation *outInfo) +{ + this->Superclass::SetupOutputInformation(outInfo); + + outInfo->Set(vtkDataObject::ORIGIN(), this->Origin, 3); + outInfo->Set(vtkDataObject::SPACING(), this->Spacing, 3); +} + + +//---------------------------------------------------------------------------- +void vtkXMLPImageDataReader::CopyOutputInformation(vtkInformation *outInfo, int port) + { + this->Superclass::CopyOutputInformation(outInfo, port); + vtkInformation *localInfo = this->GetExecutive()->GetOutputInformation( port ); + + if ( localInfo->Has(vtkDataObject::ORIGIN()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::ORIGIN() ); + } + if ( localInfo->Has(vtkDataObject::SPACING()) ) + { + outInfo->CopyEntry( localInfo, vtkDataObject::SPACING() ); + } + } + + +//---------------------------------------------------------------------------- +vtkXMLDataReader* vtkXMLPImageDataReader::CreatePieceReader() +{ + return vtkXMLImageDataReader::New(); +} + + + +//---------------------------------------------------------------------------- +int vtkXMLPImageDataReader::FillOutputPortInformation(int, vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} + diff --git a/IO/vtkXMLPImageDataReader.h b/IO/vtkXMLPImageDataReader.h new file mode 100644 index 0000000..c4a50a8 --- /dev/null +++ b/IO/vtkXMLPImageDataReader.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPImageDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPImageDataReader - Read PVTK XML ImageData files. +// .SECTION Description +// vtkXMLPImageDataReader reads the PVTK XML ImageData file format. +// This reads the parallel format's summary file and then uses +// vtkXMLImageDataReader to read data from the individual ImageData +// piece files. Streaming is supported. The standard extension for +// this reader's file format is "pvti". + +// .SECTION See Also +// vtkXMLImageDataReader + +#ifndef __vtkXMLPImageDataReader_h +#define __vtkXMLPImageDataReader_h + +#include "vtkXMLPStructuredDataReader.h" + +class vtkImageData; + +class VTK_IO_EXPORT vtkXMLPImageDataReader : public vtkXMLPStructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPImageDataReader,vtkXMLPStructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPImageDataReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkImageData *output); + vtkImageData *GetOutput(); + vtkImageData *GetOutput(int idx); + + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); + +protected: + vtkXMLPImageDataReader(); + ~vtkXMLPImageDataReader(); + + double Origin[3]; + double Spacing[3]; + + vtkImageData* GetPieceInput(int index); + + const char* GetDataSetName(); + void SetOutputExtent(int* extent); + void GetPieceInputExtent(int index, int* extent); + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + + // Setup the output's information. + void SetupOutputInformation(vtkInformation *outInfo); + + vtkXMLDataReader* CreatePieceReader(); + virtual int FillOutputPortInformation(int, vtkInformation*); + +private: + vtkXMLPImageDataReader(const vtkXMLPImageDataReader&); // Not implemented. + void operator=(const vtkXMLPImageDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPImageDataWriter.cxx b/IO/vtkXMLPImageDataWriter.cxx new file mode 100644 index 0000000..28424fa --- /dev/null +++ b/IO/vtkXMLPImageDataWriter.cxx @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPImageDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPImageDataWriter.h" + +#include "vtkErrorCode.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkXMLImageDataWriter.h" + +vtkCxxRevisionMacro(vtkXMLPImageDataWriter, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkXMLPImageDataWriter); + +//---------------------------------------------------------------------------- +vtkXMLPImageDataWriter::vtkXMLPImageDataWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLPImageDataWriter::~vtkXMLPImageDataWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPImageDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkXMLPImageDataWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPImageDataWriter::GetDataSetName() +{ + return "PImageData"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPImageDataWriter::GetDefaultFileExtension() +{ + return "pvti"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPImageDataWriter::WritePrimaryElementAttributes(ostream &os, vtkIndent indent) +{ + this->Superclass::WritePrimaryElementAttributes(os, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + vtkImageData* input = this->GetInput(); + this->WriteVectorAttribute("Origin", 3, input->GetOrigin()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteVectorAttribute("Spacing", 3, input->GetSpacing()); +} + +//---------------------------------------------------------------------------- +vtkXMLStructuredDataWriter* +vtkXMLPImageDataWriter::CreateStructuredPieceWriter() +{ + // Create the writer for the piece. + vtkXMLImageDataWriter* pWriter = vtkXMLImageDataWriter::New(); + pWriter->SetInput(this->GetInput()); + return pWriter; +} + +//---------------------------------------------------------------------------- +int vtkXMLPImageDataWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} diff --git a/IO/vtkXMLPImageDataWriter.h b/IO/vtkXMLPImageDataWriter.h new file mode 100644 index 0000000..2a0b1bd --- /dev/null +++ b/IO/vtkXMLPImageDataWriter.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPImageDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPImageDataWriter - Write PVTK XML ImageData files. +// .SECTION Description +// vtkXMLPImageDataWriter writes the PVTK XML ImageData file format. +// One image data input can be written into a parallel file format +// with any number of pieces spread across files. The standard +// extension for this writer's file format is "pvti". This writer +// uses vtkXMLImageDataWriter to write the individual piece files. + +// .SECTION See Also +// vtkXMLImageDataWriter + +#ifndef __vtkXMLPImageDataWriter_h +#define __vtkXMLPImageDataWriter_h + +#include "vtkXMLPStructuredDataWriter.h" + +class vtkImageData; + +class VTK_IO_EXPORT vtkXMLPImageDataWriter : public vtkXMLPStructuredDataWriter +{ +public: + static vtkXMLPImageDataWriter* New(); + vtkTypeRevisionMacro(vtkXMLPImageDataWriter,vtkXMLPStructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkImageData* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLPImageDataWriter(); + ~vtkXMLPImageDataWriter(); + + const char* GetDataSetName(); + void WritePrimaryElementAttributes(ostream &os, vtkIndent indent); + vtkXMLStructuredDataWriter* CreateStructuredPieceWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkXMLPImageDataWriter(const vtkXMLPImageDataWriter&); // Not implemented. + void operator=(const vtkXMLPImageDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPPolyDataReader.cxx b/IO/vtkXMLPPolyDataReader.cxx new file mode 100644 index 0000000..2735285 --- /dev/null +++ b/IO/vtkXMLPPolyDataReader.cxx @@ -0,0 +1,290 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPPolyDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPPolyDataReader.h" +#include "vtkObjectFactory.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLPolyDataReader.h" +#include "vtkPolyData.h" +#include "vtkUnsignedCharArray.h" +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLPPolyDataReader, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkXMLPPolyDataReader); + +//---------------------------------------------------------------------------- +vtkXMLPPolyDataReader::vtkXMLPPolyDataReader() +{ + // Copied from vtkPolyDataReader constructor: + vtkPolyData *output = vtkPolyData::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkXMLPPolyDataReader::~vtkXMLPPolyDataReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataReader::SetOutput(vtkPolyData *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkXMLPPolyDataReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkXMLPPolyDataReader::GetOutput(int idx) +{ + return vtkPolyData::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPPolyDataReader::GetDataSetName() +{ + return "PPolyData"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataReader::GetOutputUpdateExtent(int& piece, + int& numberOfPieces, + int& ghostLevel) +{ + this->GetOutput()->GetUpdateExtent(piece, numberOfPieces, ghostLevel); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPPolyDataReader::GetNumberOfCellsInPiece(int piece) +{ + if(this->PieceReaders[piece]) + { + return this->PieceReaders[piece]->GetNumberOfCells(); + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPPolyDataReader::GetNumberOfVertsInPiece(int piece) +{ + if(this->PieceReaders[piece]) + { + vtkXMLPolyDataReader* pReader = + static_cast(this->PieceReaders[piece]); + return pReader->GetNumberOfVerts(); + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPPolyDataReader::GetNumberOfLinesInPiece(int piece) +{ + if(this->PieceReaders[piece]) + { + vtkXMLPolyDataReader* pReader = + static_cast(this->PieceReaders[piece]); + return pReader->GetNumberOfLines(); + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPPolyDataReader::GetNumberOfStripsInPiece(int piece) +{ + if(this->PieceReaders[piece]) + { + vtkXMLPolyDataReader* pReader = + static_cast(this->PieceReaders[piece]); + return pReader->GetNumberOfStrips(); + } + return 0; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPPolyDataReader::GetNumberOfPolysInPiece(int piece) +{ + if(this->PieceReaders[piece]) + { + vtkXMLPolyDataReader* pReader = + static_cast(this->PieceReaders[piece]); + return pReader->GetNumberOfPolys(); + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataReader::SetupOutputTotals() +{ + this->Superclass::SetupOutputTotals(); + // Find the total size of the output. + int i; + this->TotalNumberOfCells = 0; + this->TotalNumberOfVerts = 0; + this->TotalNumberOfLines = 0; + this->TotalNumberOfStrips = 0; + this->TotalNumberOfPolys = 0; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + this->TotalNumberOfCells += this->GetNumberOfCellsInPiece(i); + this->TotalNumberOfVerts += this->GetNumberOfVertsInPiece(i); + this->TotalNumberOfLines += this->GetNumberOfLinesInPiece(i); + this->TotalNumberOfStrips += this->GetNumberOfStripsInPiece(i); + this->TotalNumberOfPolys += this->GetNumberOfPolysInPiece(i); + } + + // Data reading will start at the beginning of the output. + this->StartVert = 0; + this->StartLine = 0; + this->StartStrip = 0; + this->StartPoly = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + vtkPolyData* output = this->GetOutput(); + + // Setup the output's cell arrays. + vtkCellArray* outVerts = vtkCellArray::New(); + vtkCellArray* outLines = vtkCellArray::New(); + vtkCellArray* outStrips = vtkCellArray::New(); + vtkCellArray* outPolys = vtkCellArray::New(); + + output->SetVerts(outVerts); + output->SetLines(outLines); + output->SetStrips(outStrips); + output->SetPolys(outPolys); + + outPolys->Delete(); + outStrips->Delete(); + outLines->Delete(); + outVerts->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataReader::SetupNextPiece() +{ + this->Superclass::SetupNextPiece(); + this->StartVert += this->GetNumberOfVertsInPiece(this->Piece); + this->StartLine += this->GetNumberOfLinesInPiece(this->Piece); + this->StartStrip += this->GetNumberOfStripsInPiece(this->Piece); + this->StartPoly += this->GetNumberOfPolysInPiece(this->Piece); +} + +//---------------------------------------------------------------------------- +int vtkXMLPPolyDataReader::ReadPieceData() +{ + if(!this->Superclass::ReadPieceData()) { return 0; } + + vtkPointSet* ips = this->GetPieceInputAsPointSet(this->Piece); + vtkPolyData* input = static_cast(ips); + vtkPolyData* output = this->GetOutput(); + + // Copy the Verts. + this->CopyCellArray(this->TotalNumberOfVerts, input->GetVerts(), + output->GetVerts()); + + // Copy the Lines. + this->CopyCellArray(this->TotalNumberOfLines, input->GetLines(), + output->GetLines()); + + // Copy the Strips. + this->CopyCellArray(this->TotalNumberOfStrips, input->GetStrips(), + output->GetStrips()); + + // Copy the Polys. + this->CopyCellArray(this->TotalNumberOfPolys, input->GetPolys(), + output->GetPolys()); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataReader::CopyArrayForCells(vtkDataArray* inArray, + vtkDataArray* outArray) +{ + if(!this->PieceReaders[this->Piece]) + { + return; + } + if (inArray == NULL || outArray == NULL) + { + return; + } + + vtkIdType components = outArray->GetNumberOfComponents(); + vtkIdType tupleSize = inArray->GetDataTypeSize()*components; + + // Copy the cell data for the Verts in the piece. + vtkIdType inStartCell = 0; + vtkIdType outStartCell = this->StartVert; + vtkIdType numCells = this->GetNumberOfVertsInPiece(this->Piece); + memcpy(outArray->GetVoidPointer(outStartCell*components), + inArray->GetVoidPointer(inStartCell*components), numCells*tupleSize); + + // Copy the cell data for the Lines in the piece. + inStartCell += numCells; + outStartCell = this->TotalNumberOfVerts + this->StartLine; + numCells = this->GetNumberOfLinesInPiece(this->Piece); + memcpy(outArray->GetVoidPointer(outStartCell*components), + inArray->GetVoidPointer(inStartCell*components), numCells*tupleSize); + + // Copy the cell data for the Strips in the piece. + inStartCell += numCells; + outStartCell = (this->TotalNumberOfVerts + this->TotalNumberOfLines + + this->StartStrip); + numCells = this->GetNumberOfStripsInPiece(this->Piece); + memcpy(outArray->GetVoidPointer(outStartCell*components), + inArray->GetVoidPointer(inStartCell*components), numCells*tupleSize); + + // Copy the cell data for the Polys in the piece. + inStartCell += numCells; + outStartCell = (this->TotalNumberOfVerts + this->TotalNumberOfLines + + this->TotalNumberOfStrips + this->StartPoly); + numCells = this->GetNumberOfPolysInPiece(this->Piece); + memcpy(outArray->GetVoidPointer(outStartCell*components), + inArray->GetVoidPointer(inStartCell*components), numCells*tupleSize); +} + +//---------------------------------------------------------------------------- +vtkXMLDataReader* vtkXMLPPolyDataReader::CreatePieceReader() +{ + return vtkXMLPolyDataReader::New(); +} + + +//---------------------------------------------------------------------------- +int vtkXMLPPolyDataReader::FillOutputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData"); + return 1; +} diff --git a/IO/vtkXMLPPolyDataReader.h b/IO/vtkXMLPPolyDataReader.h new file mode 100644 index 0000000..2dd104f --- /dev/null +++ b/IO/vtkXMLPPolyDataReader.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPPolyDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPPolyDataReader - Read PVTK XML PolyData files. +// .SECTION Description +// vtkXMLPPolyDataReader reads the PVTK XML PolyData file format. +// This reads the parallel format's summary file and then uses +// vtkXMLPolyDataReader to read data from the individual PolyData +// piece files. Streaming is supported. The standard extension for +// this reader's file format is "pvtp". + +// .SECTION See Also +// vtkXMLPolyDataReader + +#ifndef __vtkXMLPPolyDataReader_h +#define __vtkXMLPPolyDataReader_h + +#include "vtkXMLPUnstructuredDataReader.h" + +class vtkPolyData; + +class VTK_IO_EXPORT vtkXMLPPolyDataReader : public vtkXMLPUnstructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPPolyDataReader,vtkXMLPUnstructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPPolyDataReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkPolyData *output); + vtkPolyData *GetOutput(); + vtkPolyData *GetOutput(int idx); + +protected: + vtkXMLPPolyDataReader(); + ~vtkXMLPPolyDataReader(); + + const char* GetDataSetName(); + void GetOutputUpdateExtent(int& piece, int& numberOfPieces, int& ghostLevel); + vtkIdType GetNumberOfCellsInPiece(int piece); + vtkIdType GetNumberOfVertsInPiece(int piece); + vtkIdType GetNumberOfLinesInPiece(int piece); + vtkIdType GetNumberOfStripsInPiece(int piece); + vtkIdType GetNumberOfPolysInPiece(int piece); + void SetupOutputTotals(); + + void SetupOutputData(); + void SetupNextPiece(); + int ReadPieceData(); + + void CopyArrayForCells(vtkDataArray* inArray, vtkDataArray* outArray); + vtkXMLDataReader* CreatePieceReader(); + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The size of the UpdatePiece. + vtkIdType TotalNumberOfVerts; + vtkIdType TotalNumberOfLines; + vtkIdType TotalNumberOfStrips; + vtkIdType TotalNumberOfPolys; + vtkIdType StartVert; + vtkIdType StartLine; + vtkIdType StartStrip; + vtkIdType StartPoly; + +private: + vtkXMLPPolyDataReader(const vtkXMLPPolyDataReader&); // Not implemented. + void operator=(const vtkXMLPPolyDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPPolyDataWriter.cxx b/IO/vtkXMLPPolyDataWriter.cxx new file mode 100644 index 0000000..ab54621 --- /dev/null +++ b/IO/vtkXMLPPolyDataWriter.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPPolyDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPPolyDataWriter.h" + +#include "vtkObjectFactory.h" +#include "vtkXMLPolyDataWriter.h" +#include "vtkPolyData.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkXMLPPolyDataWriter, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkXMLPPolyDataWriter); + +//---------------------------------------------------------------------------- +vtkXMLPPolyDataWriter::vtkXMLPPolyDataWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLPPolyDataWriter::~vtkXMLPPolyDataWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPPolyDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkXMLPPolyDataWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPPolyDataWriter::GetDataSetName() +{ + return "PPolyData"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPPolyDataWriter::GetDefaultFileExtension() +{ + return "pvtp"; +} + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredDataWriter* +vtkXMLPPolyDataWriter::CreateUnstructuredPieceWriter() +{ + // Create the writer for the piece. + vtkXMLPolyDataWriter* pWriter = vtkXMLPolyDataWriter::New(); + pWriter->SetInput(this->GetInput()); + return pWriter; +} + +//---------------------------------------------------------------------------- +int vtkXMLPPolyDataWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} diff --git a/IO/vtkXMLPPolyDataWriter.h b/IO/vtkXMLPPolyDataWriter.h new file mode 100644 index 0000000..033378a --- /dev/null +++ b/IO/vtkXMLPPolyDataWriter.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPPolyDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPPolyDataWriter - Write PVTK XML PolyData files. +// .SECTION Description +// vtkXMLPPolyDataWriter writes the PVTK XML PolyData file format. +// One poly data input can be written into a parallel file format with +// any number of pieces spread across files. The standard extension +// for this writer's file format is "pvtp". This writer uses +// vtkXMLPolyDataWriter to write the individual piece files. + +// .SECTION See Also +// vtkXMLPolyDataWriter + +#ifndef __vtkXMLPPolyDataWriter_h +#define __vtkXMLPPolyDataWriter_h + +#include "vtkXMLPUnstructuredDataWriter.h" + +class vtkPolyData; + +class VTK_IO_EXPORT vtkXMLPPolyDataWriter : public vtkXMLPUnstructuredDataWriter +{ +public: + static vtkXMLPPolyDataWriter* New(); + vtkTypeRevisionMacro(vtkXMLPPolyDataWriter,vtkXMLPUnstructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkPolyData* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLPPolyDataWriter(); + ~vtkXMLPPolyDataWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + const char* GetDataSetName(); + vtkXMLUnstructuredDataWriter* CreateUnstructuredPieceWriter(); + +private: + vtkXMLPPolyDataWriter(const vtkXMLPPolyDataWriter&); // Not implemented. + void operator=(const vtkXMLPPolyDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPRectilinearGridReader.cxx b/IO/vtkXMLPRectilinearGridReader.cxx new file mode 100644 index 0000000..436c3ac --- /dev/null +++ b/IO/vtkXMLPRectilinearGridReader.cxx @@ -0,0 +1,228 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPRectilinearGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPRectilinearGridReader.h" + +#include "vtkDataArray.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLRectilinearGridReader.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLPRectilinearGridReader, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkXMLPRectilinearGridReader); + +//---------------------------------------------------------------------------- +vtkXMLPRectilinearGridReader::vtkXMLPRectilinearGridReader() +{ + // Copied from vtkRectilinearGridReader constructor: + vtkRectilinearGrid *output = vtkRectilinearGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkXMLPRectilinearGridReader::~vtkXMLPRectilinearGridReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridReader::SetOutput(vtkRectilinearGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkXMLPRectilinearGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkXMLPRectilinearGridReader::GetOutput(int idx) +{ + return vtkRectilinearGrid::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkXMLPRectilinearGridReader::GetPieceInput(int index) +{ + vtkXMLRectilinearGridReader* reader = + static_cast(this->PieceReaders[index]); + return reader->GetOutput(); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPRectilinearGridReader::GetDataSetName() +{ + return "PRectilinearGrid"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridReader::SetOutputExtent(int* extent) +{ + this->GetOutput()->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridReader::GetPieceInputExtent(int index, int* extent) +{ + this->GetPieceInput(index)->GetExtent(extent); +} + +//---------------------------------------------------------------------------- +int +vtkXMLPRectilinearGridReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; } + + // Find the PCoordinates element. + this->PCoordinatesElement = 0; + int i; + int numNested = ePrimary->GetNumberOfNestedElements(); + for(i=0;i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if((strcmp(eNested->GetName(), "PCoordinates") == 0) && + (eNested->GetNumberOfNestedElements() == 3)) + { + this->PCoordinatesElement = eNested; + } + } + + // If there is any volume, we require a PCoordinates element. + if(!this->PCoordinatesElement) + { + int extent[6]; + this->GetOutput()->GetWholeExtent(extent); + if((extent[0] <= extent[1]) && (extent[2] <= extent[3]) && + (extent[4] <= extent[5])) + { + vtkErrorMacro("Could not find PCoordinates element with 3 arrays."); + return 0; + } + } + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + if(!this->PCoordinatesElement) + { + // Empty volume. + return; + } + + // Allocate the coordinate arrays. + vtkRectilinearGrid* output = this->GetOutput(); + + vtkXMLDataElement* xc = this->PCoordinatesElement->GetNestedElement(0); + vtkXMLDataElement* yc = this->PCoordinatesElement->GetNestedElement(1); + vtkXMLDataElement* zc = this->PCoordinatesElement->GetNestedElement(2); + + // Create the coordinate arrays. + vtkDataArray* x = this->CreateDataArray(xc); + vtkDataArray* y = this->CreateDataArray(yc); + vtkDataArray* z = this->CreateDataArray(zc); + if(x && y && z) + { + x->SetNumberOfTuples(this->PointDimensions[0]); + y->SetNumberOfTuples(this->PointDimensions[1]); + z->SetNumberOfTuples(this->PointDimensions[2]); + output->SetXCoordinates(x); + output->SetYCoordinates(y); + output->SetZCoordinates(z); + x->Delete(); + y->Delete(); + z->Delete(); + } + else + { + if (x) { x->Delete(); } + if (y) { y->Delete(); } + if (z) { z->Delete(); } + this->DataError = 1; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLPRectilinearGridReader::ReadPieceData() +{ + if(!this->Superclass::ReadPieceData()) { return 0; } + + // Copy the coordinates arrays from the input piece. + vtkRectilinearGrid* input = this->GetPieceInput(this->Piece); + vtkRectilinearGrid* output = this->GetOutput(); + this->CopySubCoordinates(this->SubPieceExtent, this->UpdateExtent, + this->SubExtent, input->GetXCoordinates(), + output->GetXCoordinates()); + this->CopySubCoordinates(this->SubPieceExtent+2, this->UpdateExtent+2, + this->SubExtent+2, input->GetYCoordinates(), + output->GetYCoordinates()); + this->CopySubCoordinates(this->SubPieceExtent+4, this->UpdateExtent+4, + this->SubExtent+4, input->GetZCoordinates(), + output->GetZCoordinates()); + + return 1; +} + +//---------------------------------------------------------------------------- +vtkXMLDataReader* vtkXMLPRectilinearGridReader::CreatePieceReader() +{ + return vtkXMLRectilinearGridReader::New(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridReader::CopySubCoordinates(int* inBounds, + int* outBounds, + int* subBounds, + vtkDataArray* inArray, + vtkDataArray* outArray) +{ + unsigned int components = inArray->GetNumberOfComponents(); + unsigned int tupleSize = inArray->GetDataTypeSize()*components; + + int destStartIndex = subBounds[0] - outBounds[0]; + int sourceStartIndex = subBounds[0] - inBounds[0]; + int length = subBounds[1] - subBounds[0] + 1; + + memcpy(outArray->GetVoidPointer(destStartIndex*components), + inArray->GetVoidPointer(sourceStartIndex*components), + length*tupleSize); +} + + +int vtkXMLPRectilinearGridReader::FillOutputPortInformation(int, vtkInformation *info) + { + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkRectilinearGrid"); + return 1; + } + + diff --git a/IO/vtkXMLPRectilinearGridReader.h b/IO/vtkXMLPRectilinearGridReader.h new file mode 100644 index 0000000..037f50e --- /dev/null +++ b/IO/vtkXMLPRectilinearGridReader.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPRectilinearGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPRectilinearGridReader - Read PVTK XML RectilinearGrid files. +// .SECTION Description +// vtkXMLPRectilinearGridReader reads the PVTK XML RectilinearGrid +// file format. This reads the parallel format's summary file and +// then uses vtkXMLRectilinearGridReader to read data from the +// individual RectilinearGrid piece files. Streaming is supported. +// The standard extension for this reader's file format is "pvtr". + +// .SECTION See Also +// vtkXMLRectilinearGridReader + +#ifndef __vtkXMLPRectilinearGridReader_h +#define __vtkXMLPRectilinearGridReader_h + +#include "vtkXMLPStructuredDataReader.h" + +class vtkRectilinearGrid; + +class VTK_IO_EXPORT vtkXMLPRectilinearGridReader : public vtkXMLPStructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPRectilinearGridReader,vtkXMLPStructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPRectilinearGridReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkRectilinearGrid *output); + vtkRectilinearGrid *GetOutput(); + vtkRectilinearGrid *GetOutput(int idx); + +protected: + vtkXMLPRectilinearGridReader(); + ~vtkXMLPRectilinearGridReader(); + + vtkRectilinearGrid* GetPieceInput(int index); + + const char* GetDataSetName(); + void SetOutputExtent(int* extent); + void GetPieceInputExtent(int index, int* extent); + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + void SetupOutputData(); + int ReadPieceData(); + vtkXMLDataReader* CreatePieceReader(); + void CopySubCoordinates(int* inBounds, int* outBounds, int* subBounds, + vtkDataArray* inArray, vtkDataArray* outArray); + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The PCoordinates element with coordinate information. + vtkXMLDataElement* PCoordinatesElement; + +private: + vtkXMLPRectilinearGridReader(const vtkXMLPRectilinearGridReader&); // Not implemented. + void operator=(const vtkXMLPRectilinearGridReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPRectilinearGridWriter.cxx b/IO/vtkXMLPRectilinearGridWriter.cxx new file mode 100644 index 0000000..3ec424f --- /dev/null +++ b/IO/vtkXMLPRectilinearGridWriter.cxx @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPRectilinearGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPRectilinearGridWriter.h" + +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkRectilinearGrid.h" +#include "vtkXMLRectilinearGridWriter.h" + +vtkCxxRevisionMacro(vtkXMLPRectilinearGridWriter, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkXMLPRectilinearGridWriter); + +//---------------------------------------------------------------------------- +vtkXMLPRectilinearGridWriter::vtkXMLPRectilinearGridWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLPRectilinearGridWriter::~vtkXMLPRectilinearGridWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkXMLPRectilinearGridWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPRectilinearGridWriter::GetDataSetName() +{ + return "PRectilinearGrid"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPRectilinearGridWriter::GetDefaultFileExtension() +{ + return "pvtr"; +} + +//---------------------------------------------------------------------------- +vtkXMLStructuredDataWriter* +vtkXMLPRectilinearGridWriter::CreateStructuredPieceWriter() +{ + // Create the writer for the piece. + vtkXMLRectilinearGridWriter* pWriter = vtkXMLRectilinearGridWriter::New(); + pWriter->SetInput(this->GetInput()); + return pWriter; +} + +//---------------------------------------------------------------------------- +void vtkXMLPRectilinearGridWriter::WritePData(vtkIndent indent) +{ + this->Superclass::WritePData(indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + vtkRectilinearGrid* input = this->GetInput(); + this->WritePCoordinates(input->GetXCoordinates(), input->GetYCoordinates(), + input->GetZCoordinates(), indent); +} + +int vtkXMLPRectilinearGridWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} diff --git a/IO/vtkXMLPRectilinearGridWriter.h b/IO/vtkXMLPRectilinearGridWriter.h new file mode 100644 index 0000000..c94ae3e --- /dev/null +++ b/IO/vtkXMLPRectilinearGridWriter.h @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPRectilinearGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPRectilinearGridWriter - Write PVTK XML RectilinearGrid files. +// .SECTION Description +// vtkXMLPRectilinearGridWriter writes the PVTK XML RectilinearGrid +// file format. One rectilinear grid input can be written into a +// parallel file format with any number of pieces spread across files. +// The standard extension for this writer's file format is "pvtr". +// This writer uses vtkXMLRectilinearGridWriter to write the +// individual piece files. + +// .SECTION See Also +// vtkXMLRectilinearGridWriter + +#ifndef __vtkXMLPRectilinearGridWriter_h +#define __vtkXMLPRectilinearGridWriter_h + +#include "vtkXMLPStructuredDataWriter.h" + +class vtkRectilinearGrid; + +class VTK_IO_EXPORT vtkXMLPRectilinearGridWriter : public vtkXMLPStructuredDataWriter +{ +public: + static vtkXMLPRectilinearGridWriter* New(); + vtkTypeRevisionMacro(vtkXMLPRectilinearGridWriter,vtkXMLPStructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkRectilinearGrid* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLPRectilinearGridWriter(); + ~vtkXMLPRectilinearGridWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + const char* GetDataSetName(); + vtkXMLStructuredDataWriter* CreateStructuredPieceWriter(); + void WritePData(vtkIndent indent); + +private: + vtkXMLPRectilinearGridWriter(const vtkXMLPRectilinearGridWriter&); // Not implemented. + void operator=(const vtkXMLPRectilinearGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPStructuredDataReader.cxx b/IO/vtkXMLPStructuredDataReader.cxx new file mode 100644 index 0000000..e5fc5c9 --- /dev/null +++ b/IO/vtkXMLPStructuredDataReader.cxx @@ -0,0 +1,457 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPStructuredDataReader.h" + +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkExtentSplitter.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTableExtentTranslator.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLStructuredDataReader.h" + +vtkCxxRevisionMacro(vtkXMLPStructuredDataReader, "$Revision: 1.22 $"); + +//---------------------------------------------------------------------------- +vtkXMLPStructuredDataReader::vtkXMLPStructuredDataReader() +{ + this->ExtentTranslator = vtkTableExtentTranslator::New(); + this->ExtentSplitter = vtkExtentSplitter::New(); + this->PieceExtents = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLPStructuredDataReader::~vtkXMLPStructuredDataReader() +{ + if(this->NumberOfPieces) { this->DestroyPieces(); } + this->ExtentSplitter->Delete(); + this->ExtentTranslator->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkExtentTranslator* vtkXMLPStructuredDataReader::GetExtentTranslator() +{ + return this->ExtentTranslator; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPStructuredDataReader::GetNumberOfPoints() +{ + return (this->PointDimensions[0]* + this->PointDimensions[1]* + this->PointDimensions[2]); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPStructuredDataReader::GetNumberOfCells() +{ + return (this->CellDimensions[0]* + this->CellDimensions[1]* + this->CellDimensions[2]); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataReader::ReadXMLData() +{ + // Get the requested Update Extent. + this->GetOutputAsDataSet(0)->GetUpdateExtent(this->UpdateExtent); + + vtkDebugMacro("Updating extent " + << this->UpdateExtent[0] << " " << this->UpdateExtent[1] << " " + << this->UpdateExtent[2] << " " << this->UpdateExtent[3] << " " + << this->UpdateExtent[4] << " " << this->UpdateExtent[5] + << "\n"); + + // Prepare increments for the update extent. + this->ComputePointDimensions(this->UpdateExtent, this->PointDimensions); + this->ComputePointIncrements(this->UpdateExtent, this->PointIncrements); + this->ComputeCellDimensions(this->UpdateExtent, this->CellDimensions); + this->ComputeCellIncrements(this->UpdateExtent, this->CellIncrements); + + // Let superclasses read data. This also allocates output data. + this->Superclass::ReadXMLData(); + + // Use the ExtentSplitter to split the update extent into + // sub-extents read by each piece. + if(!this->ComputePieceSubExtents()) + { + // Not all needed data are available. + this->DataError = 1; + return; + } + + // Split current progress range based on fraction contributed by + // each sub-extent. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + // Calculate the cumulative fraction of data contributed by each + // sub-extent (for progress). + int n = this->ExtentSplitter->GetNumberOfSubExtents(); + float* fractions = new float[n+1]; + int i; + fractions[0] = 0; + for(i=0;i < n;++i) + { + // Get this sub-extent. + this->ExtentSplitter->GetSubExtent(i, this->SubExtent); + + // Add this sub-extent's volume to the cumulative volume. + int pieceDims[3] = {0,0,0}; + this->ComputePointDimensions(this->SubExtent, pieceDims); + fractions[i+1] = fractions[i] + pieceDims[0]*pieceDims[1]*pieceDims[2]; + } + if(fractions[n] == 0) + { + fractions[n] = 1; + } + for(i=1;i <= n;++i) + { + fractions[i] = fractions[i] / fractions[n]; + } + + // Read the data needed from each sub-extent. + for(i=0;(i < n && !this->AbortExecute && !this->DataError);++i) + { + // Set the range of progress for this sub-extent. + this->SetProgressRange(progressRange, i, fractions); + + // Get this sub-extent and the piece from which to read it. + int piece = this->ExtentSplitter->GetSubExtentSource(i); + this->ExtentSplitter->GetSubExtent(i, this->SubExtent); + + vtkDebugMacro("Reading extent " + << this->SubExtent[0] << " " << this->SubExtent[1] << " " + << this->SubExtent[2] << " " << this->SubExtent[3] << " " + << this->SubExtent[4] << " " << this->SubExtent[5] + << " from piece " << piece); + + this->ComputePointDimensions(this->SubExtent, this->SubPointDimensions); + this->ComputeCellDimensions(this->SubExtent, this->SubCellDimensions); + + // Read the data from this piece. + if(!this->Superclass::ReadPieceData(piece)) + { + // An error occurred while reading the piece. + this->DataError = 1; + } + } + + delete [] fractions; + + // We filled the exact update extent in the output. + this->SetOutputExtent(this->UpdateExtent); +} + +//---------------------------------------------------------------------------- +int +vtkXMLPStructuredDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; } + vtkDataSet* output = this->GetOutputAsDataSet(0); + + // Get the whole extent attribute. + int extent[6]; + if(ePrimary->GetVectorAttribute("WholeExtent", 6, extent) == 6) + { + // Set the output's whole extent. + output->SetWholeExtent(extent); + + // Check each axis to see if it has cells. + for(int a=0; a < 3; ++a) + { + this->AxesEmpty[a] = (extent[2*a+1] > extent[2*a])? 0 : 1; + } + } + else + { + vtkErrorMacro(<< this->GetDataSetName() << " element has no WholeExtent."); + return 0; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +void +vtkXMLPStructuredDataReader::CopyOutputInformation(vtkInformation* outInfo, + int port) +{ + // Let the superclass copy information first. + this->Superclass::CopyOutputInformation(outInfo, port); + + // All structured data has a whole extent. + vtkInformation* localInfo = this->GetExecutive()->GetOutputInformation(port); + if(localInfo->Has(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())) + { + outInfo->CopyEntry(localInfo, + vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + } +} + +void vtkXMLPStructuredDataReader::SetupOutputData() + { + this->Superclass::SetupOutputData(); + + // Tell the output to use the table extent translator to provide the + // correct piece breakdown for the file layout. + this->GetOutputAsDataSet(0)->SetExtentTranslator(this->ExtentTranslator); + } + + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataReader::SetupEmptyOutput() +{ + // Special extent to indicate no input. + this->GetOutputAsDataSet(0)->SetUpdateExtent(1, 0, 1, 0, 1, 0); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataReader::SetupPieces(int numPieces) +{ + this->Superclass::SetupPieces(numPieces); + this->ExtentTranslator->SetNumberOfPiecesInTable(this->NumberOfPieces); + this->ExtentTranslator->SetMaximumGhostLevel(this->GhostLevel); + this->PieceExtents = new int[6*this->NumberOfPieces]; + int i; + for(i=0;i < this->NumberOfPieces;++i) + { + int* extent = this->PieceExtents+i*6; + extent[0] = 0; extent[1] = -1; + extent[2] = 0; extent[3] = -1; + extent[4] = 0; extent[5] = -1; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataReader::DestroyPieces() +{ + delete [] this->PieceExtents; + this->PieceExtents = 0; + this->Superclass::DestroyPieces(); +} + +//---------------------------------------------------------------------------- +int vtkXMLPStructuredDataReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + // Superclass will create a reader for the piece's file. + if(!this->Superclass::ReadPiece(ePiece)) { return 0; } + + // Get the extent of the piece. + int* pieceExtent = this->PieceExtents+this->Piece*6; + if(ePiece->GetVectorAttribute("Extent", 6, pieceExtent) < 6) + { + vtkErrorMacro("Piece " << this->Piece << " has invalid Extent."); + return 0; + } + + // Set this table entry in the extent translator. + this->ExtentTranslator->SetExtentForPiece(this->Piece, pieceExtent); + this->ExtentTranslator->SetPieceAvailable(this->Piece, + this->CanReadPiece(this->Piece)); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLPStructuredDataReader::ReadPieceData() +{ + // Use the internal reader to read the piece. + vtkDataSet* input = this->GetPieceInputAsDataSet(this->Piece); + input->SetUpdateExtent(this->SubExtent); + input->Update(); + + // Skip rest of read if aborting. + if(this->AbortExecute) + { + return 0; + } + + // Get the actual portion of the piece that was read. + this->GetPieceInputExtent(this->Piece, this->SubPieceExtent); + this->ComputePointDimensions(this->SubPieceExtent, + this->SubPiecePointDimensions); + this->ComputePointIncrements(this->SubPieceExtent, + this->SubPiecePointIncrements); + this->ComputeCellDimensions(this->SubPieceExtent, + this->SubPieceCellDimensions); + this->ComputeCellIncrements(this->SubPieceExtent, + this->SubPieceCellIncrements); + + // Let the superclass read the data it wants. + return this->Superclass::ReadPieceData(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataReader::CopyArrayForPoints(vtkDataArray* inArray, + vtkDataArray* outArray) +{ + if(!inArray || !outArray) + { + return; + } + this->CopySubExtent(this->SubPieceExtent, + this->SubPiecePointDimensions, + this->SubPiecePointIncrements, + this->UpdateExtent, this->PointDimensions, + this->PointIncrements, this->SubExtent, + this->SubPointDimensions, inArray, outArray); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataReader::CopyArrayForCells(vtkDataArray* inArray, + vtkDataArray* outArray) +{ + if(!inArray || !outArray) + { + return; + } + this->CopySubExtent(this->SubPieceExtent, + this->SubPieceCellDimensions, + this->SubPieceCellIncrements, + this->UpdateExtent, this->CellDimensions, + this->CellIncrements, this->SubExtent, + this->SubCellDimensions, inArray, outArray); +} + +//---------------------------------------------------------------------------- +void +vtkXMLPStructuredDataReader +::CopySubExtent(int* inExtent, int* inDimensions, vtkIdType* inIncrements, + int* outExtent, int* outDimensions, vtkIdType* outIncrements, + int* subExtent, int* subDimensions, + vtkDataArray* inArray, vtkDataArray* outArray) +{ + unsigned int components = inArray->GetNumberOfComponents(); + unsigned int tupleSize = inArray->GetDataTypeSize()*components; + + if((inDimensions[0] == outDimensions[0]) && + (inDimensions[1] == outDimensions[1])) + { + if(inDimensions[2] == outDimensions[2]) + { + // Copy the whole volume at once. + unsigned int volumeTuples = (inDimensions[0]* + inDimensions[1]* + inDimensions[2]); + memcpy(outArray->GetVoidPointer(0), inArray->GetVoidPointer(0), + volumeTuples*tupleSize); + } + else + { + // Copy an entire slice at a time. + vtkIdType sliceTuples = inDimensions[0]*inDimensions[1]; + int k; + for(k=0;k < subDimensions[2];++k) + { + vtkIdType sourceTuple = this->GetStartTuple(inExtent, inIncrements, + subExtent[0], + subExtent[2], + subExtent[4]+k); + vtkIdType destTuple = this->GetStartTuple(outExtent, outIncrements, + subExtent[0], + subExtent[2], + subExtent[4]+k); + memcpy(outArray->GetVoidPointer(destTuple*components), + inArray->GetVoidPointer(sourceTuple*components), + sliceTuples*tupleSize); + } + } + } + else + { + // Copy a row at a time. + vtkIdType rowTuples = subDimensions[0]; + int j,k; + for(k=0;k < subDimensions[2];++k) + { + for(j=0;j < subDimensions[1];++j) + { + vtkIdType sourceTuple = this->GetStartTuple(inExtent, inIncrements, + subExtent[0], + subExtent[2]+j, + subExtent[4]+k); + vtkIdType destTuple = this->GetStartTuple(outExtent, outIncrements, + subExtent[0], + subExtent[2]+j, + subExtent[4]+k); + memcpy(outArray->GetVoidPointer(destTuple*components), + inArray->GetVoidPointer(sourceTuple*components), + rowTuples*tupleSize); + } + } + } +} + +//---------------------------------------------------------------------------- +int vtkXMLPStructuredDataReader::ComputePieceSubExtents() +{ + // Reset the extent splitter. + this->ExtentSplitter->RemoveAllExtentSources(); + + // Add each readable piece as an extent source. + int i; + for(i=0;i < this->NumberOfPieces;++i) + { + if(this->CanReadPiece(i)) + { + // Add the exact extent provided by the piece to the splitter. + int extent[6]; + this->PieceReaders[i]->UpdateInformation(); + this->PieceReaders[i]->GetOutputAsDataSet()->GetWholeExtent(extent); + this->ExtentSplitter->AddExtentSource(i, 0, extent); + } + } + + // We want to split the entire update extent across the pieces. + this->ExtentSplitter->AddExtent(this->UpdateExtent); + + // Compute the sub-extents. + if(!this->ExtentSplitter->ComputeSubExtents()) + { + // A portion of the extent is not available. + ostrstream e_with_warning_C4701; + e_with_warning_C4701 + << "No available piece provides data for the following extents:\n"; + for(i=0; i < this->ExtentSplitter->GetNumberOfSubExtents(); ++i) + { + if(this->ExtentSplitter->GetSubExtentSource(i) < 0) + { + int extent[6]; + this->ExtentSplitter->GetSubExtent(i, extent); + e_with_warning_C4701 + << " " + << extent[0] << " " << extent[1] << " " + << extent[2] << " " << extent[3] << " " + << extent[4] << " " << extent[5] << "\n"; + } + } + e_with_warning_C4701 << "The UpdateExtent cannot be filled." << ends; + vtkErrorMacro(<< e_with_warning_C4701.str()); + e_with_warning_C4701.rdbuf()->freeze(0); + return 0; + } + + return 1; +} + diff --git a/IO/vtkXMLPStructuredDataReader.h b/IO/vtkXMLPStructuredDataReader.h new file mode 100644 index 0000000..3fda352 --- /dev/null +++ b/IO/vtkXMLPStructuredDataReader.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPStructuredDataReader - Superclass for parallel structured data XML readers. +// .SECTION Description +// vtkXMLPStructuredDataReader provides functionality common to all +// parallel structured data format readers. + +// .SECTION See Also +// vtkXMLPImageDataReader vtkXMLPStructuredGridReader +// vtkXMLPRectilinearGridReader + +#ifndef __vtkXMLPStructuredDataReader_h +#define __vtkXMLPStructuredDataReader_h + +#include "vtkXMLPDataReader.h" + +class vtkExtentSplitter; +class vtkExtentTranslator; +class vtkTableExtentTranslator; +class vtkXMLStructuredDataReader; + +class VTK_IO_EXPORT vtkXMLPStructuredDataReader : public vtkXMLPDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPStructuredDataReader,vtkXMLPDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get an extent translator that will create pieces matching the + // input file's piece breakdown. This can be used further down the + // pipeline to prevent reading from outside this process's piece. + // The translator is only valid after an UpdateInformation has been + // called. + virtual vtkExtentTranslator* GetExtentTranslator(); + + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); +protected: + vtkXMLPStructuredDataReader(); + ~vtkXMLPStructuredDataReader(); + + vtkIdType GetNumberOfPoints(); + vtkIdType GetNumberOfCells(); + void CopyArrayForPoints(vtkDataArray* inArray, vtkDataArray* outArray); + void CopyArrayForCells(vtkDataArray* inArray, vtkDataArray* outArray); + + virtual void SetOutputExtent(int* extent)=0; + virtual void GetPieceInputExtent(int index, int* extent)=0; + + // Pipeline execute data driver. Called by vtkXMLReader. + void ReadXMLData(); + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + + void SetupOutputData(); + + void SetupEmptyOutput(); + void SetupPieces(int numPieces); + void DestroyPieces(); + int ReadPiece(vtkXMLDataElement* ePiece); + int ReadPieceData(); + void CopySubExtent(int* inExtent, int* inDimensions, vtkIdType* inIncrements, + int* outExtent,int* outDimensions,vtkIdType* outIncrements, + int* subExtent, int* subDimensions, + vtkDataArray* inArray, vtkDataArray* outArray); + int ComputePieceSubExtents(); + + vtkTableExtentTranslator* ExtentTranslator; + vtkExtentSplitter* ExtentSplitter; + + // The extent to be updated in the output. + int UpdateExtent[6]; + int PointDimensions[3]; + vtkIdType PointIncrements[3]; + int CellDimensions[3]; + vtkIdType CellIncrements[3]; + + // The extent currently being read from a piece. + int SubExtent[6]; + int SubPointDimensions[3]; + int SubCellDimensions[3]; + int SubPieceExtent[6]; + int SubPiecePointDimensions[3]; + vtkIdType SubPiecePointIncrements[3]; + int SubPieceCellDimensions[3]; + vtkIdType SubPieceCellIncrements[3]; + + // Information per-piece. + int* PieceExtents; + +private: + vtkXMLPStructuredDataReader(const vtkXMLPStructuredDataReader&); // Not implemented. + void operator=(const vtkXMLPStructuredDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPStructuredDataWriter.cxx b/IO/vtkXMLPStructuredDataWriter.cxx new file mode 100644 index 0000000..96f846c --- /dev/null +++ b/IO/vtkXMLPStructuredDataWriter.cxx @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPStructuredDataWriter.h" +#include "vtkXMLStructuredDataWriter.h" +#include "vtkExtentTranslator.h" +#include "vtkErrorCode.h" +#include "vtkDataSet.h" + +vtkCxxRevisionMacro(vtkXMLPStructuredDataWriter, "$Revision: 1.4 $"); +vtkCxxSetObjectMacro(vtkXMLPStructuredDataWriter, ExtentTranslator, + vtkExtentTranslator); + +//---------------------------------------------------------------------------- +vtkXMLPStructuredDataWriter::vtkXMLPStructuredDataWriter() +{ + this->ExtentTranslator = vtkExtentTranslator::New(); +} + +//---------------------------------------------------------------------------- +vtkXMLPStructuredDataWriter::~vtkXMLPStructuredDataWriter() +{ + this->ExtentTranslator->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if(this->ExtentTranslator) + { + os << indent << "ExtentTranslator: " << this->ExtentTranslator << "\n"; + } + else + { + os << indent << "ExtentTranslator: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataWriter::WritePrimaryElementAttributes(ostream &os, vtkIndent indent) +{ + vtkDataSet* input = this->GetInputAsDataSet(); + this->WriteVectorAttribute("WholeExtent", 6, input->GetWholeExtent()); + this->Superclass::WritePrimaryElementAttributes(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredDataWriter::WritePPieceAttributes(int index) +{ + int extent[6]; + this->ExtentTranslator->SetPiece(index); + this->ExtentTranslator->SetGhostLevel(0); + this->ExtentTranslator->PieceToExtent(); + this->ExtentTranslator->GetExtent(extent); + + this->WriteVectorAttribute("Extent", 6, extent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->Superclass::WritePPieceAttributes(index); +} + +//---------------------------------------------------------------------------- +vtkXMLWriter* vtkXMLPStructuredDataWriter::CreatePieceWriter(int index) +{ + vtkDataSet* input = this->GetInputAsDataSet(); + + this->ExtentTranslator->SetWholeExtent(input->GetWholeExtent()); + this->ExtentTranslator->SetNumberOfPieces(this->NumberOfPieces); + this->ExtentTranslator->SetPiece(index); + this->ExtentTranslator->SetGhostLevel(this->GhostLevel); + this->ExtentTranslator->PieceToExtent(); + + vtkXMLStructuredDataWriter* pWriter = this->CreateStructuredPieceWriter(); + pWriter->SetWriteExtent(this->ExtentTranslator->GetExtent()); + + return pWriter; +} diff --git a/IO/vtkXMLPStructuredDataWriter.h b/IO/vtkXMLPStructuredDataWriter.h new file mode 100644 index 0000000..c8a80d7 --- /dev/null +++ b/IO/vtkXMLPStructuredDataWriter.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPStructuredDataWriter - Superclass for PVTK XML structured data writers. +// .SECTION Description +// vtkXMLPStructuredDataWriter provides PVTK XML writing functionality +// that is common among all the parallel structured data formats. + +#ifndef __vtkXMLPStructuredDataWriter_h +#define __vtkXMLPStructuredDataWriter_h + +#include "vtkXMLPDataWriter.h" + +class vtkXMLStructuredDataWriter; +class vtkExtentTranslator; + +class VTK_IO_EXPORT vtkXMLPStructuredDataWriter : public vtkXMLPDataWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLPStructuredDataWriter,vtkXMLPDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get/Set the extent translator used for creating pieces. + virtual void SetExtentTranslator(vtkExtentTranslator*); + vtkGetObjectMacro(ExtentTranslator, vtkExtentTranslator); + +protected: + vtkXMLPStructuredDataWriter(); + ~vtkXMLPStructuredDataWriter(); + + virtual vtkXMLStructuredDataWriter* CreateStructuredPieceWriter()=0; + void WritePrimaryElementAttributes(ostream &os, vtkIndent indent); + void WritePPieceAttributes(int index); + vtkXMLWriter* CreatePieceWriter(int index); + + vtkExtentTranslator* ExtentTranslator; + +private: + vtkXMLPStructuredDataWriter(const vtkXMLPStructuredDataWriter&); // Not implemented. + void operator=(const vtkXMLPStructuredDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPStructuredGridReader.cxx b/IO/vtkXMLPStructuredGridReader.cxx new file mode 100644 index 0000000..33b0b0f --- /dev/null +++ b/IO/vtkXMLPStructuredGridReader.cxx @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPStructuredGridReader.h" + +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkStructuredGrid.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLStructuredGridReader.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLPStructuredGridReader, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkXMLPStructuredGridReader); + +//---------------------------------------------------------------------------- +vtkXMLPStructuredGridReader::vtkXMLPStructuredGridReader() +{ + // Copied from vtkStructuredGridReader constructor: + vtkStructuredGrid *output = vtkStructuredGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkXMLPStructuredGridReader::~vtkXMLPStructuredGridReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkXMLPStructuredGridReader::GetOutput(int idx) +{ + return vtkStructuredGrid::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredGridReader::SetOutput(vtkStructuredGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkXMLPStructuredGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkXMLPStructuredGridReader::GetPieceInput(int index) +{ + vtkXMLStructuredGridReader* reader = + static_cast(this->PieceReaders[index]); + return reader->GetOutput(); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPStructuredGridReader::GetDataSetName() +{ + return "PStructuredGrid"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredGridReader::SetOutputExtent(int* extent) +{ + this->GetOutput()->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredGridReader::GetPieceInputExtent(int index, int* extent) +{ + this->GetPieceInput(index)->GetExtent(extent); +} + +//---------------------------------------------------------------------------- +int +vtkXMLPStructuredGridReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; } + + // Find the PPoints element. + this->PPointsElement = 0; + int i; + int numNested = ePrimary->GetNumberOfNestedElements(); + for(i=0;i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if((strcmp(eNested->GetName(), "PPoints") == 0) && + (eNested->GetNumberOfNestedElements() == 1)) + { + this->PPointsElement = eNested; + } + } + + if(!this->PPointsElement) + { + int extent[6]; + this->GetOutput()->GetWholeExtent(extent); + if((extent[0] <= extent[1]) && (extent[2] <= extent[3]) && + (extent[4] <= extent[5])) + { + vtkErrorMacro("Could not find PPoints element with 1 array."); + return 0; + } + } + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredGridReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + // Create the points array. + vtkPoints* points = vtkPoints::New(); + if(this->PPointsElement) + { + // Non-zero volume. + vtkDataArray* a = this->CreateDataArray(this->PPointsElement->GetNestedElement(0)); + if(a) + { + a->SetNumberOfTuples(this->GetNumberOfPoints()); + points->SetData(a); + a->Delete(); + } + else + { + this->DataError = 1; + } + } + this->GetOutput()->SetPoints(points); + points->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkXMLPStructuredGridReader::ReadPieceData() +{ + if(!this->Superclass::ReadPieceData()) { return 0; } + + // Copy the points. + vtkStructuredGrid* input = this->GetPieceInput(this->Piece); + vtkStructuredGrid* output = this->GetOutput(); + this->CopyArrayForPoints(input->GetPoints()->GetData(), + output->GetPoints()->GetData()); + + return 1; +} + +//---------------------------------------------------------------------------- +vtkXMLDataReader* vtkXMLPStructuredGridReader::CreatePieceReader() +{ + return vtkXMLStructuredGridReader::New(); +} + + +int vtkXMLPStructuredGridReader::FillOutputPortInformation(int, vtkInformation *info) + { + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredGrid"); + return 1; + } + diff --git a/IO/vtkXMLPStructuredGridReader.h b/IO/vtkXMLPStructuredGridReader.h new file mode 100644 index 0000000..0b5fc59 --- /dev/null +++ b/IO/vtkXMLPStructuredGridReader.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPStructuredGridReader - Read PVTK XML StructuredGrid files. +// .SECTION Description +// vtkXMLPStructuredGridReader reads the PVTK XML StructuredGrid file +// format. This reads the parallel format's summary file and then +// uses vtkXMLStructuredGridReader to read data from the individual +// StructuredGrid piece files. Streaming is supported. The standard +// extension for this reader's file format is "pvts". + +// .SECTION See Also +// vtkXMLStructuredGridReader + +#ifndef __vtkXMLPStructuredGridReader_h +#define __vtkXMLPStructuredGridReader_h + +#include "vtkXMLPStructuredDataReader.h" + +class vtkStructuredGrid; + +class VTK_IO_EXPORT vtkXMLPStructuredGridReader : public vtkXMLPStructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPStructuredGridReader,vtkXMLPStructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPStructuredGridReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkStructuredGrid *output); + vtkStructuredGrid *GetOutput(); + + // Description: + // Needed for ParaView + vtkStructuredGrid* GetOutput(int idx); + +protected: + vtkXMLPStructuredGridReader(); + ~vtkXMLPStructuredGridReader(); + + vtkStructuredGrid* GetPieceInput(int index); + + const char* GetDataSetName(); + void SetOutputExtent(int* extent); + void GetPieceInputExtent(int index, int* extent); + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + void SetupOutputData(); + int ReadPieceData(); + vtkXMLDataReader* CreatePieceReader(); + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The PPoints element with point information. + vtkXMLDataElement* PPointsElement; + +private: + vtkXMLPStructuredGridReader(const vtkXMLPStructuredGridReader&); // Not implemented. + void operator=(const vtkXMLPStructuredGridReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPStructuredGridWriter.cxx b/IO/vtkXMLPStructuredGridWriter.cxx new file mode 100644 index 0000000..ca822dd --- /dev/null +++ b/IO/vtkXMLPStructuredGridWriter.cxx @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPStructuredGridWriter.h" + +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkStructuredGrid.h" +#include "vtkXMLStructuredGridWriter.h" + +vtkCxxRevisionMacro(vtkXMLPStructuredGridWriter, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkXMLPStructuredGridWriter); + +//---------------------------------------------------------------------------- +vtkXMLPStructuredGridWriter::vtkXMLPStructuredGridWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLPStructuredGridWriter::~vtkXMLPStructuredGridWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkXMLPStructuredGridWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPStructuredGridWriter::GetDataSetName() +{ + return "PStructuredGrid"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPStructuredGridWriter::GetDefaultFileExtension() +{ + return "pvts"; +} + +//---------------------------------------------------------------------------- +vtkXMLStructuredDataWriter* +vtkXMLPStructuredGridWriter::CreateStructuredPieceWriter() +{ + // Create the writer for the piece. + vtkXMLStructuredGridWriter* pWriter = vtkXMLStructuredGridWriter::New(); + pWriter->SetInput(this->GetInput()); + return pWriter; +} + +//---------------------------------------------------------------------------- +void vtkXMLPStructuredGridWriter::WritePData(vtkIndent indent) +{ + this->Superclass::WritePData(indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + vtkStructuredGrid* input = this->GetInput(); + this->WritePPoints(input->GetPoints(), indent); +} + +int vtkXMLPStructuredGridWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} diff --git a/IO/vtkXMLPStructuredGridWriter.h b/IO/vtkXMLPStructuredGridWriter.h new file mode 100644 index 0000000..793d2d6 --- /dev/null +++ b/IO/vtkXMLPStructuredGridWriter.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPStructuredGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPStructuredGridWriter - Write PVTK XML StructuredGrid files. +// .SECTION Description +// vtkXMLPStructuredGridWriter writes the PVTK XML StructuredGrid +// file format. One structured grid input can be written into a +// parallel file format with any number of pieces spread across files. +// The standard extension for this writer's file format is "pvts". +// This writer uses vtkXMLStructuredGridWriter to write the individual +// piece files. + +// .SECTION See Also +// vtkXMLStructuredGridWriter + +#ifndef __vtkXMLPStructuredGridWriter_h +#define __vtkXMLPStructuredGridWriter_h + +#include "vtkXMLPStructuredDataWriter.h" + +class vtkStructuredGrid; + +class VTK_IO_EXPORT vtkXMLPStructuredGridWriter : public vtkXMLPStructuredDataWriter +{ +public: + static vtkXMLPStructuredGridWriter* New(); + vtkTypeRevisionMacro(vtkXMLPStructuredGridWriter,vtkXMLPStructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkStructuredGrid* GetInput(); + //ETX + +protected: + vtkXMLPStructuredGridWriter(); + ~vtkXMLPStructuredGridWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + const char* GetDataSetName(); + const char* GetDefaultFileExtension(); + vtkXMLStructuredDataWriter* CreateStructuredPieceWriter(); + void WritePData(vtkIndent indent); + +private: + vtkXMLPStructuredGridWriter(const vtkXMLPStructuredGridWriter&); // Not implemented. + void operator=(const vtkXMLPStructuredGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPUnstructuredDataReader.cxx b/IO/vtkXMLPUnstructuredDataReader.cxx new file mode 100644 index 0000000..9d0c7f8 --- /dev/null +++ b/IO/vtkXMLPUnstructuredDataReader.cxx @@ -0,0 +1,402 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPUnstructuredDataReader.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLUnstructuredDataReader.h" +#include "vtkPointSet.h" +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLPUnstructuredDataReader, "$Revision: 1.18 $"); + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredDataReader::vtkXMLPUnstructuredDataReader() +{ + this->TotalNumberOfPoints = 0; + this->TotalNumberOfCells = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredDataReader::~vtkXMLPUnstructuredDataReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkXMLPUnstructuredDataReader::GetOutputAsPointSet() +{ + return vtkPointSet::SafeDownCast( this->GetOutputDataObject(0) ); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkXMLPUnstructuredDataReader::GetPieceInputAsPointSet(int piece) +{ + vtkXMLDataReader* reader = this->PieceReaders[piece]; + if(!reader) { return 0; } + if(reader->GetNumberOfOutputPorts() < 1) { return 0; } + return static_cast(reader->GetExecutive()->GetOutputData(0)); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::SetupOutputTotals() +{ + int i; + this->TotalNumberOfPoints = 0; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + if(this->PieceReaders[i]) + { + this->TotalNumberOfPoints += this->PieceReaders[i]->GetNumberOfPoints(); + } + } + this->StartPoint = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::SetupNextPiece() +{ + if(this->PieceReaders[this->Piece]) + { + this->StartPoint += this->PieceReaders[this->Piece]->GetNumberOfPoints(); + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfPoints() +{ + return this->TotalNumberOfPoints; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfCells() +{ + return this->TotalNumberOfCells; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfPointsInPiece(int piece) +{ + if(this->PieceReaders[piece]) + { + return this->PieceReaders[piece]->GetNumberOfPoints(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfCellsInPiece(int piece) +{ + if(this->PieceReaders[piece]) + { + return this->PieceReaders[piece]->GetNumberOfCells(); + } + else + { + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::SetupEmptyOutput() +{ + // No pieces means no input. + this->GetOutputAsDataSet(0)->SetUpdateExtent(0, 0); +} + +//---------------------------------------------------------------------------- +// Note that any changes (add or removing information) made to this method +// should be replicated in CopyOutputInformation +void vtkXMLPUnstructuredDataReader::SetupOutputInformation(vtkInformation *outInfo) +{ + this->Superclass::SetupOutputInformation(outInfo); + + // Set the maximum number of pieces that can be provided by this + // reader. + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), this->NumberOfPieces); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::CopyOutputInformation(vtkInformation *outInfo, int port) + { + this->Superclass::CopyOutputInformation(outInfo, port); + outInfo->CopyEntry( this->GetExecutive()->GetOutputInformation( port ), + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES() ); + } + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + // Create the points array. + vtkPoints* points = vtkPoints::New(); + if(this->PPointsElement) + { + vtkDataArray* a = this->CreateDataArray(this->PPointsElement->GetNestedElement(0)); + if(a) + { + a->SetNumberOfTuples(this->GetNumberOfPoints()); + points->SetData(a); + a->Delete(); + } + else + { + this->DataError = 1; + } + } + this->GetOutputAsPointSet()->SetPoints(points); + points->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::SetupUpdateExtent(int piece, + int numberOfPieces, + int ghostLevel) +{ + this->UpdatePiece = piece; + this->UpdateNumberOfPieces = numberOfPieces; + this->UpdateGhostLevel = ghostLevel; + + // If more pieces are requested than available, just return empty + // pieces for the extra ones. + if(this->UpdateNumberOfPieces > this->NumberOfPieces) + { + this->UpdateNumberOfPieces = this->NumberOfPieces; + } + + // Find the range of pieces to read. + if(this->UpdatePiece < this->UpdateNumberOfPieces) + { + this->StartPiece = ((this->UpdatePiece*this->NumberOfPieces) / + this->UpdateNumberOfPieces); + this->EndPiece = (((this->UpdatePiece+1)*this->NumberOfPieces) / + this->UpdateNumberOfPieces); + } + else + { + this->StartPiece = 0; + this->EndPiece = 0; + } + + // Update the information of the pieces we need. + int i; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + if(this->CanReadPiece(i)) + { + this->PieceReaders[i]->UpdateInformation(); + vtkXMLUnstructuredDataReader* pReader = + static_cast(this->PieceReaders[i]); + pReader->SetupUpdateExtent(0, 1, this->UpdateGhostLevel); + } + } + + // Find the total size of the output. + this->SetupOutputTotals(); +} + +//---------------------------------------------------------------------------- +int +vtkXMLPUnstructuredDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; } + + // Find the PPoints element. + this->PPointsElement = 0; + int i; + int numNested = ePrimary->GetNumberOfNestedElements(); + for(i=0;i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if((strcmp(eNested->GetName(), "PPoints") == 0) && + (eNested->GetNumberOfNestedElements() == 1)) + { + this->PPointsElement = eNested; + } + } + + // If PPoints element was not found, we must assume there are 0 + // points. If there are found to be points later, the error will be + // reported by ReadPieceData. + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::ReadXMLData() +{ + // Get the update request. + int piece; + int numberOfPieces; + int ghostLevel; + this->GetOutputUpdateExtent(piece, numberOfPieces, ghostLevel); + + vtkDebugMacro("Updating piece " << piece << " of " << numberOfPieces + << " with ghost level " << ghostLevel); + + // Setup the range of pieces that will be read. + this->SetupUpdateExtent(piece, numberOfPieces, ghostLevel); + + // If there are no data to read, stop now. + if(this->StartPiece == this->EndPiece) + { + return; + } + + vtkDebugMacro("Reading piece range [" << this->StartPiece + << ", " << this->EndPiece << ") from file."); + + // Let superclasses read data. This also allocates output data. + this->Superclass::ReadXMLData(); + + // Split current progress range based on fraction contributed by + // each piece. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + // Calculate the cumulative fraction of data contributed by each + // piece (for progress). + float* fractions = new float[this->EndPiece-this->StartPiece+1]; + int i; + fractions[0] = 0; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + int index = i-this->StartPiece; + fractions[index+1] = (fractions[index] + + this->GetNumberOfPointsInPiece(i) + + this->GetNumberOfCellsInPiece(i)); + } + if(fractions[this->EndPiece-this->StartPiece] == 0) + { + fractions[this->EndPiece-this->StartPiece] = 1; + } + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + int index = i-this->StartPiece; + fractions[index+1] = fractions[index+1] / fractions[this->EndPiece-this->StartPiece]; + } + + // Read the data needed from each piece. + for(i=this->StartPiece; (i < this->EndPiece && !this->AbortExecute && + !this->DataError); ++i) + { + // Set the range of progress for this piece. + this->SetProgressRange(progressRange, i-this->StartPiece, fractions); + + if(!this->Superclass::ReadPieceData(i)) + { + // An error occurred while reading the piece. + this->DataError = 1; + } + this->SetupNextPiece(); + } + + delete [] fractions; +} + +//---------------------------------------------------------------------------- +int vtkXMLPUnstructuredDataReader::ReadPieceData() +{ + // Use the internal reader to read the piece. + vtkPointSet* input = this->GetPieceInputAsPointSet(this->Piece); + input->SetUpdateExtent(0, 1, this->UpdateGhostLevel); + input->Update(); + + vtkPointSet* output = this->GetOutputAsPointSet(); + + // If there are some points, but no PPoints element, report the + // error. + if(!this->PPointsElement && (this->GetNumberOfPoints() > 0)) + { + vtkErrorMacro("Could not find PPoints element with 1 array."); + return 0; + } + + if (!input->GetPoints()) + { + return 0; + } + + // Copy the points array. + this->CopyArrayForPoints(input->GetPoints()->GetData(), + output->GetPoints()->GetData()); + + // Let the superclass read the data it wants. + return this->Superclass::ReadPieceData(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::CopyArrayForPoints(vtkDataArray* inArray, + vtkDataArray* outArray) +{ + if(!this->PieceReaders[this->Piece]) + { + return; + } + if (inArray == NULL || outArray == NULL) + { + return; + } + + vtkIdType numPoints = this->PieceReaders[this->Piece]->GetNumberOfPoints(); + vtkIdType components = outArray->GetNumberOfComponents(); + vtkIdType tupleSize = inArray->GetDataTypeSize()*components; + memcpy(outArray->GetVoidPointer(this->StartPoint*components), + inArray->GetVoidPointer(0), numPoints*tupleSize); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataReader::CopyCellArray(vtkIdType totalNumberOfCells, + vtkCellArray* inCells, + vtkCellArray* outCells) +{ + // Allocate memory in the output connectivity array. + vtkIdType curSize = 0; + if(outCells->GetData()) + { + curSize = outCells->GetData()->GetNumberOfTuples(); + } + vtkIdTypeArray* inData = inCells->GetData(); + vtkIdType newSize = curSize+inData->GetNumberOfTuples(); + vtkIdType* in = inData->GetPointer(0); + vtkIdType* end = inData->GetPointer(inData->GetNumberOfTuples()); + vtkIdType* out = outCells->WritePointer(totalNumberOfCells, newSize); + out += curSize; + + // Copy the connectivity data. + while(in < end) + { + vtkIdType length = *in++; + *out++ = length; + // Copy the point indices, but increment them for the appended + // version's index. + vtkIdType j; + for(j=0;j < length; ++j) + { + out[j] = in[j]+this->StartPoint; + } + in += length; + out += length; + } +} diff --git a/IO/vtkXMLPUnstructuredDataReader.h b/IO/vtkXMLPUnstructuredDataReader.h new file mode 100644 index 0000000..4e9cac1 --- /dev/null +++ b/IO/vtkXMLPUnstructuredDataReader.h @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPUnstructuredDataReader - Superclass for parallel unstructured data XML readers. +// .SECTION Description +// vtkXMLPUnstructuredDataReader provides functionality common to all +// parallel unstructured data format readers. + +// .SECTION See Also +// vtkXMLPPolyDataReader vtkXMLPUnstructuredGridReader + +#ifndef __vtkXMLPUnstructuredDataReader_h +#define __vtkXMLPUnstructuredDataReader_h + +#include "vtkXMLPDataReader.h" + +class vtkPointSet; +class vtkCellArray; +class vtkXMLUnstructuredDataReader; + +class VTK_IO_EXPORT vtkXMLPUnstructuredDataReader : public vtkXMLPDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPUnstructuredDataReader,vtkXMLPDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); + +protected: + vtkXMLPUnstructuredDataReader(); + ~vtkXMLPUnstructuredDataReader(); + + vtkPointSet* GetOutputAsPointSet(); + vtkPointSet* GetPieceInputAsPointSet(int piece); + virtual void SetupOutputTotals(); + virtual void SetupNextPiece(); + vtkIdType GetNumberOfPoints(); + vtkIdType GetNumberOfCells(); + void CopyArrayForPoints(vtkDataArray* inArray, vtkDataArray* outArray); + + void SetupEmptyOutput(); + + // Setup the output's information. + void SetupOutputInformation(vtkInformation *outInfo); + + void SetupOutputData(); + virtual void GetOutputUpdateExtent(int& piece, int& numberOfPieces, + int& ghostLevel)=0; + + // Pipeline execute data driver. Called by vtkXMLReader. + void ReadXMLData(); + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + void SetupUpdateExtent(int piece, int numberOfPieces, int ghostLevel); + + int ReadPieceData(); + void CopyCellArray(vtkIdType totalNumberOfCells, vtkCellArray* inCells, + vtkCellArray* outCells); + + // Get the number of points/cells in the given piece. Valid after + // UpdateInformation. + virtual vtkIdType GetNumberOfPointsInPiece(int piece); + virtual vtkIdType GetNumberOfCellsInPiece(int piece); + + // The update request. + int UpdatePiece; + int UpdateNumberOfPieces; + int UpdateGhostLevel; + + // The range of pieces from the file that will form the UpdatePiece. + int StartPiece; + int EndPiece; + vtkIdType TotalNumberOfPoints; + vtkIdType TotalNumberOfCells; + vtkIdType StartPoint; + + // The PPoints element with point information. + vtkXMLDataElement* PPointsElement; + +private: + vtkXMLPUnstructuredDataReader(const vtkXMLPUnstructuredDataReader&); // Not implemented. + void operator=(const vtkXMLPUnstructuredDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPUnstructuredDataWriter.cxx b/IO/vtkXMLPUnstructuredDataWriter.cxx new file mode 100644 index 0000000..6251523 --- /dev/null +++ b/IO/vtkXMLPUnstructuredDataWriter.cxx @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPUnstructuredDataWriter.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkErrorCode.h" +#include "vtkPointSet.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkXMLUnstructuredDataWriter.h" + +vtkCxxRevisionMacro(vtkXMLPUnstructuredDataWriter, "$Revision: 1.8 $"); + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredDataWriter::vtkXMLPUnstructuredDataWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredDataWriter::~vtkXMLPUnstructuredDataWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkXMLPUnstructuredDataWriter::GetInputAsPointSet() +{ + return static_cast(this->GetInput()); +} + +//---------------------------------------------------------------------------- +int vtkXMLPUnstructuredDataWriter::ProcessRequest( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + this->NumberOfPieces); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), this->StartPiece); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + this->GhostLevel); + return 1; + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +vtkXMLWriter* vtkXMLPUnstructuredDataWriter::CreatePieceWriter(int index) +{ + vtkXMLUnstructuredDataWriter* pWriter = this->CreateUnstructuredPieceWriter(); + pWriter->SetNumberOfPieces(this->NumberOfPieces); + pWriter->SetWritePiece(index); + pWriter->SetGhostLevel(this->GhostLevel); + + return pWriter; +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredDataWriter::WritePData(vtkIndent indent) +{ + this->Superclass::WritePData(indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + vtkPointSet* input = this->GetInputAsPointSet(); + this->WritePPoints(input->GetPoints(), indent); +} diff --git a/IO/vtkXMLPUnstructuredDataWriter.h b/IO/vtkXMLPUnstructuredDataWriter.h new file mode 100644 index 0000000..6399b83 --- /dev/null +++ b/IO/vtkXMLPUnstructuredDataWriter.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPUnstructuredDataWriter - Superclass for PVTK XML unstructured data writers. +// .SECTION Description +// vtkXMLPUnstructuredDataWriter provides PVTK XML writing +// functionality that is common among all the parallel unstructured +// data formats. + +#ifndef __vtkXMLPUnstructuredDataWriter_h +#define __vtkXMLPUnstructuredDataWriter_h + +#include "vtkXMLPDataWriter.h" + +class vtkPointSet; +class vtkXMLUnstructuredDataWriter; + +class VTK_IO_EXPORT vtkXMLPUnstructuredDataWriter : public vtkXMLPDataWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLPUnstructuredDataWriter,vtkXMLPDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // See the vtkAlgorithm for a desciption of what these do + int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkXMLPUnstructuredDataWriter(); + ~vtkXMLPUnstructuredDataWriter(); + + vtkPointSet* GetInputAsPointSet(); + + virtual vtkXMLUnstructuredDataWriter* CreateUnstructuredPieceWriter()=0; + vtkXMLWriter* CreatePieceWriter(int index); + void WritePData(vtkIndent indent); + +private: + vtkXMLPUnstructuredDataWriter(const vtkXMLPUnstructuredDataWriter&); // Not implemented. + void operator=(const vtkXMLPUnstructuredDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPUnstructuredGridReader.cxx b/IO/vtkXMLPUnstructuredGridReader.cxx new file mode 100644 index 0000000..d1952c2 --- /dev/null +++ b/IO/vtkXMLPUnstructuredGridReader.cxx @@ -0,0 +1,211 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPUnstructuredGridReader.h" + +#include "vtkCellArray.h" +#include "vtkIdTypeArray.h" +#include "vtkObjectFactory.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLUnstructuredGridReader.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLPUnstructuredGridReader, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkXMLPUnstructuredGridReader); + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredGridReader::vtkXMLPUnstructuredGridReader() +{ + // Copied from vtkUnstructuredGridReader constructor: + vtkUnstructuredGrid *output = vtkUnstructuredGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredGridReader::~vtkXMLPUnstructuredGridReader() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridReader::SetOutput(vtkUnstructuredGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkXMLPUnstructuredGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkXMLPUnstructuredGridReader::GetOutput(int idx) +{ + return vtkUnstructuredGrid::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPUnstructuredGridReader::GetDataSetName() +{ + return "PUnstructuredGrid"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridReader::GetOutputUpdateExtent(int& piece, + int& numberOfPieces, + int& ghostLevel) +{ + this->GetOutput()->GetUpdateExtent(piece, numberOfPieces, ghostLevel); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridReader::SetupOutputTotals() +{ + this->Superclass::SetupOutputTotals(); + // Find the total size of the output. + int i; + this->TotalNumberOfCells = 0; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + if(this->PieceReaders[i]) + { + this->TotalNumberOfCells += this->PieceReaders[i]->GetNumberOfCells(); + } + } + + // Data reading will start at the beginning of the output. + this->StartCell = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + vtkUnstructuredGrid* output = this->GetOutput(); + + // Setup the output's cell arrays. + vtkUnsignedCharArray* cellTypes = vtkUnsignedCharArray::New(); + cellTypes->SetNumberOfTuples(this->GetNumberOfCells()); + vtkCellArray* outCells = vtkCellArray::New(); + + vtkIdTypeArray* locations = vtkIdTypeArray::New(); + locations->SetNumberOfTuples(this->GetNumberOfCells()); + + output->SetCells(cellTypes, locations, outCells); + + locations->Delete(); + outCells->Delete(); + cellTypes->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridReader::SetupNextPiece() +{ + this->Superclass::SetupNextPiece(); + if(this->PieceReaders[this->Piece]) + { + this->StartCell += this->PieceReaders[this->Piece]->GetNumberOfCells(); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLPUnstructuredGridReader::ReadPieceData() +{ + if(!this->Superclass::ReadPieceData()) { return 0; } + + vtkPointSet* ips = this->GetPieceInputAsPointSet(this->Piece); + vtkUnstructuredGrid* input = static_cast(ips); + vtkUnstructuredGrid* output = this->GetOutput(); + + // Save the start location where the new cell connectivity will be + // appended. + vtkIdType startLoc = 0; + if(output->GetCells()->GetData()) + { + startLoc = output->GetCells()->GetData()->GetNumberOfTuples(); + } + + // Copy the Cells. + this->CopyCellArray(this->TotalNumberOfCells, input->GetCells(), + output->GetCells()); + + // Copy the cell locations with offset adjustment. + vtkIdTypeArray* inLocations = input->GetCellLocationsArray(); + vtkIdTypeArray* outLocations = output->GetCellLocationsArray(); + vtkIdType* inLocs = inLocations->GetPointer(0); + vtkIdType* outLocs = outLocations->GetPointer(this->StartCell); + vtkIdType numCells = inLocations->GetNumberOfTuples(); + vtkIdType i; + for(i=0;i < numCells; ++i) + { + outLocs[i] = inLocs[i] + startLoc; + } + + // Copy the cooresponding cell types. + vtkUnsignedCharArray* inTypes = input->GetCellTypesArray(); + vtkUnsignedCharArray* outTypes = output->GetCellTypesArray(); + vtkIdType components = outTypes->GetNumberOfComponents(); + memcpy(outTypes->GetVoidPointer(this->StartCell*components), + inTypes->GetVoidPointer(0), + inTypes->GetNumberOfTuples()*components*inTypes->GetDataTypeSize()); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridReader::CopyArrayForCells(vtkDataArray* inArray, + vtkDataArray* outArray) +{ + if(!this->PieceReaders[this->Piece]) + { + return; + } + if(!inArray || !outArray) + { + return; + } + + vtkIdType numCells = this->PieceReaders[this->Piece]->GetNumberOfCells(); + vtkIdType components = outArray->GetNumberOfComponents(); + vtkIdType tupleSize = inArray->GetDataTypeSize()*components; + memcpy(outArray->GetVoidPointer(this->StartCell*components), + inArray->GetVoidPointer(0), numCells*tupleSize); +} + +//---------------------------------------------------------------------------- +vtkXMLDataReader* vtkXMLPUnstructuredGridReader::CreatePieceReader() +{ + return vtkXMLUnstructuredGridReader::New(); +} + + +int vtkXMLPUnstructuredGridReader::FillOutputPortInformation(int, vtkInformation *info) + { + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid"); + return 1; + } diff --git a/IO/vtkXMLPUnstructuredGridReader.h b/IO/vtkXMLPUnstructuredGridReader.h new file mode 100644 index 0000000..18f9820 --- /dev/null +++ b/IO/vtkXMLPUnstructuredGridReader.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPUnstructuredGridReader - Read PVTK XML UnstructuredGrid files. +// .SECTION Description +// vtkXMLPUnstructuredGridReader reads the PVTK XML UnstructuredGrid +// file format. This reads the parallel format's summary file and +// then uses vtkXMLUnstructuredGridReader to read data from the +// individual UnstructuredGrid piece files. Streaming is supported. +// The standard extension for this reader's file format is "pvtu". + +// .SECTION See Also +// vtkXMLUnstructuredGridReader + +#ifndef __vtkXMLPUnstructuredGridReader_h +#define __vtkXMLPUnstructuredGridReader_h + +#include "vtkXMLPUnstructuredDataReader.h" + +class vtkUnstructuredGrid; + +class VTK_IO_EXPORT vtkXMLPUnstructuredGridReader : public vtkXMLPUnstructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPUnstructuredGridReader,vtkXMLPUnstructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPUnstructuredGridReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkUnstructuredGrid *output); + vtkUnstructuredGrid *GetOutput(); + vtkUnstructuredGrid *GetOutput(int idx); + +protected: + vtkXMLPUnstructuredGridReader(); + ~vtkXMLPUnstructuredGridReader(); + + const char* GetDataSetName(); + void GetOutputUpdateExtent(int& piece, int& numberOfPieces, int& ghostLevel); + void SetupOutputTotals(); + + void SetupOutputData(); + void SetupNextPiece(); + int ReadPieceData(); + + void CopyArrayForCells(vtkDataArray* inArray, vtkDataArray* outArray); + vtkXMLDataReader* CreatePieceReader(); + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The index of the cell in the output where the current piece + // begins. + vtkIdType StartCell; + +private: + vtkXMLPUnstructuredGridReader(const vtkXMLPUnstructuredGridReader&); // Not implemented. + void operator=(const vtkXMLPUnstructuredGridReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPUnstructuredGridWriter.cxx b/IO/vtkXMLPUnstructuredGridWriter.cxx new file mode 100644 index 0000000..b1c0fbd --- /dev/null +++ b/IO/vtkXMLPUnstructuredGridWriter.cxx @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPUnstructuredGridWriter.h" + +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLUnstructuredGridWriter.h" + +vtkCxxRevisionMacro(vtkXMLPUnstructuredGridWriter, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkXMLPUnstructuredGridWriter); + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredGridWriter::vtkXMLPUnstructuredGridWriter() +{ +} + +//---------------------------------------------------------------------------- +vtkXMLPUnstructuredGridWriter::~vtkXMLPUnstructuredGridWriter() +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLPUnstructuredGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkXMLPUnstructuredGridWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPUnstructuredGridWriter::GetDataSetName() +{ + return "PUnstructuredGrid"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPUnstructuredGridWriter::GetDefaultFileExtension() +{ + return "pvtu"; +} + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredDataWriter* +vtkXMLPUnstructuredGridWriter::CreateUnstructuredPieceWriter() +{ + // Create the writer for the piece. + vtkXMLUnstructuredGridWriter* pWriter = vtkXMLUnstructuredGridWriter::New(); + pWriter->SetInput(this->GetInput()); + return pWriter; +} + +//---------------------------------------------------------------------------- +int vtkXMLPUnstructuredGridWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} diff --git a/IO/vtkXMLPUnstructuredGridWriter.h b/IO/vtkXMLPUnstructuredGridWriter.h new file mode 100644 index 0000000..43d1354 --- /dev/null +++ b/IO/vtkXMLPUnstructuredGridWriter.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPUnstructuredGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPUnstructuredGridWriter - Write PVTK XML UnstructuredGrid files. +// .SECTION Description +// vtkXMLPUnstructuredGridWriter writes the PVTK XML UnstructuredGrid +// file format. One unstructured grid input can be written into a +// parallel file format with any number of pieces spread across files. +// The standard extension for this writer's file format is "pvtu". +// This writer uses vtkXMLUnstructuredGridWriter to write the +// individual piece files. + +// .SECTION See Also +// vtkXMLUnstructuredGridWriter + +#ifndef __vtkXMLPUnstructuredGridWriter_h +#define __vtkXMLPUnstructuredGridWriter_h + +#include "vtkXMLPUnstructuredDataWriter.h" + +class vtkUnstructuredGrid; + +class VTK_IO_EXPORT vtkXMLPUnstructuredGridWriter : public vtkXMLPUnstructuredDataWriter +{ +public: + static vtkXMLPUnstructuredGridWriter* New(); + vtkTypeRevisionMacro(vtkXMLPUnstructuredGridWriter,vtkXMLPUnstructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkUnstructuredGrid* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLPUnstructuredGridWriter(); + ~vtkXMLPUnstructuredGridWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + const char* GetDataSetName(); + vtkXMLUnstructuredDataWriter* CreateUnstructuredPieceWriter(); + +private: + vtkXMLPUnstructuredGridWriter(const vtkXMLPUnstructuredGridWriter&); // Not implemented. + void operator=(const vtkXMLPUnstructuredGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLParser.cxx b/IO/vtkXMLParser.cxx new file mode 100644 index 0000000..7938109 --- /dev/null +++ b/IO/vtkXMLParser.cxx @@ -0,0 +1,501 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLParser.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Hack access to the fstream implementation if necessary. This is +// only needed on a few SGI MIPSpro compiler versions. +#if defined(__sgi) && !defined(__GNUC__) && defined(_COMPILER_VERSION) +# if _COMPILER_VERSION == 730 +# include "vtkConfigure.h" +# if VTK_STREAM_EOF_SEVERITY == 3 +# define protected public +# define private public +# include +# undef private +# undef protected +# endif +# endif +#endif + +#include "vtkXMLParser.h" +#include "vtkObjectFactory.h" +#include "vtk_expat.h" +#include +#include + +vtkCxxRevisionMacro(vtkXMLParser, "$Revision: 1.25 $"); +vtkStandardNewMacro(vtkXMLParser); + +//---------------------------------------------------------------------------- +vtkXMLParser::vtkXMLParser() +{ + this->Stream = 0; + this->Parser = 0; + this->FileName = 0; + this->InputString = 0; + this->InputStringLength = 0; + this->ParseError = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLParser::~vtkXMLParser() +{ + this->SetStream(0); + this->SetFileName(0); +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + if(this->Stream) + { + os << indent << "Stream: " << this->Stream << "\n"; + } + else + { + os << indent << "Stream: (none)\n"; + } + os << indent << "FileName: " << (this->FileName? this->FileName : "(none)") + << "\n"; +} + +//---------------------------------------------------------------------------- +static int vtkXMLParserFail(istream* stream) +{ + // The fail() method returns true if either the failbit or badbit is set. +#if defined(__HP_aCC) + // The HP compiler sets the badbit too often, so we ignore it. + return (stream->rdstate() & ios::failbit)? 1:0; +#else + return stream->fail()? 1:0; +#endif +} + +//---------------------------------------------------------------------------- +long vtkXMLParser::TellG() +{ + // Standard tellg returns -1 if fail() is true. + if(!this->Stream || vtkXMLParserFail(this->Stream)) + { + return -1; + } +#if VTK_STREAM_EOF_SEVERITY == 0 + // No work-around required. Just return the position. + return this->Stream->tellg(); +#else + long pos = this->Stream->tellg(); + if(pos == -1) + { + // Clear the fail bit from failing tellg. + this->Stream->clear(this->Stream->rdstate() & ~ios::failbit); + + // Save the eof bit. + int eof = this->Stream->eof()?1:0; + + // Clear the eof bit. + if(eof) + { + this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit); + } + +# if VTK_STREAM_EOF_SEVERITY == 2 + // Re-seek to the end to escape the buggy stream state. + this->Stream->seekg(0, ios::end); +# elif VTK_STREAM_EOF_SEVERITY == 3 + // Call an internal filebuf method to escape the buggy stream + // state. This is a very ugly hack. + static_cast(this->Stream)->rdbuf()->_M_seek_return(0,0); +# endif + + // Call tellg to get the position. + pos = this->Stream->tellg(); + + // Restore the eof bit. + if(eof) + { + this->Stream->clear(this->Stream->rdstate() | ios::eofbit); + } + } + return pos; +#endif +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::SeekG(long position) +{ + // Standard seekg does nothing if fail() is true. + if(!this->Stream || vtkXMLParserFail(this->Stream)) + { + return; + } +#if VTK_STREAM_EOF_SEVERITY == 0 + // No work-around required. Just seek to the position. + this->Stream->seekg(position); +#else + // Save the eof bit. + int eof = this->Stream->eof()?1:0; + + // Clear the eof bit. + if(eof) + { + this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit); + } + +# if VTK_STREAM_EOF_SEVERITY == 3 + // Check if the stream is in the buggy state. + if(long(this->Stream->tellg()) == -1) + { + // Call an internal filebuf method to escape the buggy stream + // state. This is a very ugly hack. + this->Stream->clear(this->Stream->rdstate() & ~ios::failbit); + this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit); + static_cast(this->Stream)->rdbuf()->_M_seek_return(0,0); + } +# endif + + // Seek to the given position. + this->Stream->seekg(position); + + // Restore the eof bit. + if(eof) + { + this->Stream->clear(this->Stream->rdstate() | ios::eofbit); + } +#endif +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::Parse(const char* inputString) +{ + this->InputString = inputString; + this->InputStringLength = -1; + int result = this->vtkXMLParser::Parse(); + this->InputString = 0; + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::Parse(const char* inputString, unsigned int length) +{ + this->InputString = inputString; + this->InputStringLength = length; + int result = this->vtkXMLParser::Parse(); + this->InputString = 0; + this->InputStringLength = -1; + return result; +} + + +//---------------------------------------------------------------------------- +int vtkXMLParser::Parse() +{ + // Select source of XML + ifstream ifs; + if ( !this->InputString && !this->Stream && this->FileName ) + { + // If it is file, open it and set the appropriate stream + struct stat fs; + if (stat(this->FileName, &fs) != 0) + { + vtkErrorMacro("Cannot open XML file: " << this->FileName); + return 0; + } +#ifdef _WIN32 + ifs.open(this->FileName, ios::binary | ios::in); +#else + ifs.open(this->FileName, ios::in); +#endif + if ( !ifs ) + { + vtkErrorMacro("Cannot open XML file: " << this->FileName); + return 0; + } + this->Stream = &ifs; + } + + // Create the expat XML parser. + this->Parser = XML_ParserCreate(0); + XML_SetElementHandler(static_cast(this->Parser), + &vtkXMLParserStartElement, + &vtkXMLParserEndElement); + XML_SetCharacterDataHandler(static_cast(this->Parser), + &vtkXMLParserCharacterDataHandler); + XML_SetUserData(static_cast(this->Parser), this); + + // Parse the input. + int result = this->ParseXML(); + + if(result) + { + // Tell the expat XML parser about the end-of-input. + if(!XML_Parse(static_cast(this->Parser), "", 0, 1)) + { + this->ReportXmlParseError(); + result = 0; + } + } + + // Clean up the parser. + XML_ParserFree(static_cast(this->Parser)); + this->Parser = 0; + + // If the source was a file, reset the stream + if ( this->Stream == &ifs ) + { + this->Stream = 0; + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::InitializeParser() +{ + if ( this->Parser ) + { + vtkErrorMacro("Parser already initialized"); + this->ParseError = 1; + return 0; + } + // Create the expat XML parser. + this->Parser = XML_ParserCreate(0); + XML_SetElementHandler(static_cast(this->Parser), + &vtkXMLParserStartElement, + &vtkXMLParserEndElement); + XML_SetCharacterDataHandler(static_cast(this->Parser), + &vtkXMLParserCharacterDataHandler); + XML_SetUserData(static_cast(this->Parser), this); + this->ParseError = 0; + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::ParseChunk(const char* inputString, unsigned int length) +{ + if ( !this->Parser ) + { + vtkErrorMacro("Parser not initialized"); + this->ParseError = 1; + return 0; + } + int res; + res = this->ParseBuffer(inputString, length); + if ( res == 0 ) + { + this->ParseError = 1; + } + return res; +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::CleanupParser() +{ + if ( !this->Parser ) + { + vtkErrorMacro("Parser not initialized"); + this->ParseError = 1; + return 0; + } + int result = !this->ParseError; + if(result) + { + // Tell the expat XML parser about the end-of-input. + if(!XML_Parse(static_cast(this->Parser), "", 0, 1)) + { + this->ReportXmlParseError(); + result = 0; + } + } + + // Clean up the parser. + XML_ParserFree(static_cast(this->Parser)); + this->Parser = 0; + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::ParseXML() +{ + // Parsing of message + if ( this->InputString ) + { + if ( this->InputStringLength >= 0 ) + { + return this->ParseBuffer(this->InputString, this->InputStringLength); + } + else + { + return this->ParseBuffer(this->InputString); + } + } + + // Make sure we have input. + if(!this->Stream) + { + vtkErrorMacro("Parse() called with no Stream set."); + return 0; + } + + // Default stream parser just reads a block at a time. + istream& in = *(this->Stream); + const int bufferSize = 4096; + char buffer[bufferSize]; + + // Read in the stream and send its contents to the XML parser. This + // read loop is very sensitive on certain platforms with slightly + // broken stream libraries (like HPUX). Normally, it is incorrect + // to not check the error condition on the fin.read() before using + // the data, but the fin.gcount() will be zero if an error occurred. + // Therefore, the loop should be safe everywhere. + while(!this->ParseError && !this->ParsingComplete() && in) + { + in.read(buffer, bufferSize); + if(in.gcount()) + { + if(!this->ParseBuffer(buffer, in.gcount())) + { + return 0; + } + } + } + + // Clear the fail and eof bits on the input stream so we can later + // seek back to read data. + this->Stream->clear(this->Stream->rdstate() & ~ios::eofbit); + this->Stream->clear(this->Stream->rdstate() & ~ios::failbit); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::ParsingComplete() +{ + // Default behavior is to parse to end of stream. + return 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::StartElement(const char *name, + const char ** vtkNotUsed(atts)) +{ + this->ReportUnknownElement(name); +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::EndElement(const char * vtkNotUsed(name)) +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::CharacterDataHandler(const char* vtkNotUsed(inData), + int vtkNotUsed(inLength)) +{ +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::ReportStrayAttribute(const char* element, const char* attr, + const char* value) +{ + vtkWarningMacro("Stray attribute in XML stream: Element " << element + << " has " << attr << "=\"" << value << "\""); +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::ReportMissingAttribute(const char* element, + const char* attr) +{ + vtkErrorMacro("Missing attribute in XML stream: Element " << element + << " is missing " << attr); +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::ReportBadAttribute(const char* element, const char* attr, + const char* value) +{ + vtkErrorMacro("Bad attribute value in XML stream: Element " << element + << " has " << attr << "=\"" << value << "\""); +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::ReportUnknownElement(const char* element) +{ + vtkErrorMacro("Unknown element in XML stream: " << element); +} + +//---------------------------------------------------------------------------- +void vtkXMLParser::ReportXmlParseError() +{ + vtkErrorMacro("Error parsing XML in stream at line " + << XML_GetCurrentLineNumber(static_cast(this->Parser)) + << ": " << XML_ErrorString(XML_GetErrorCode(static_cast(this->Parser)))); +} + +//---------------------------------------------------------------------------- +unsigned long vtkXMLParser::GetXMLByteIndex() +{ + return XML_GetCurrentByteIndex(static_cast(this->Parser)); +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::ParseBuffer(const char* buffer, unsigned int count) +{ + // Pass the buffer to the expat XML parser. + if(!XML_Parse(static_cast(this->Parser), buffer, count, 0)) + { + this->ReportXmlParseError(); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::ParseBuffer(const char* buffer) +{ + return this->ParseBuffer(buffer, static_cast(strlen(buffer))); +} + +//---------------------------------------------------------------------------- +int vtkXMLParser::IsSpace(char c) +{ + return isspace(c); +} + +//---------------------------------------------------------------------------- +void vtkXMLParserStartElement(void* parser, const char *name, + const char **atts) +{ + // Begin element handler that is registered with the XML_Parser. + // This just casts the user data to a vtkXMLParser and calls + // StartElement. + static_cast(parser)->StartElement(name, atts); +} + +//---------------------------------------------------------------------------- +void vtkXMLParserEndElement(void* parser, const char *name) +{ + // End element handler that is registered with the XML_Parser. This + // just casts the user data to a vtkXMLParser and calls EndElement. + static_cast(parser)->EndElement(name); +} + +//---------------------------------------------------------------------------- +void vtkXMLParserCharacterDataHandler(void* parser, const char* data, + int length) +{ + // Character data handler that is registered with the XML_Parser. + // This just casts the user data to a vtkXMLParser and calls + // CharacterDataHandler. + static_cast(parser)->CharacterDataHandler(data, length); +} diff --git a/IO/vtkXMLParser.h b/IO/vtkXMLParser.h new file mode 100644 index 0000000..e96b6e0 --- /dev/null +++ b/IO/vtkXMLParser.h @@ -0,0 +1,170 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLParser.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLParser - Parse XML to handle element tags and attributes. +// .SECTION Description +// vtkXMLParser reads a stream and parses XML element tags and corresponding +// attributes. Each element begin tag and its attributes are sent to +// the StartElement method. Each element end tag is sent to the +// EndElement method. Subclasses should replace these methods to actually +// use the tags. +// .SECTION ToDo: Add commands for parsing in Tcl. + +#ifndef __vtkXMLParser_h +#define __vtkXMLParser_h + +#include "vtkObject.h" + +extern "C" +{ + void vtkXMLParserStartElement(void*, const char*, const char**); + void vtkXMLParserEndElement(void*, const char*); + void vtkXMLParserCharacterDataHandler(void*, const char*, int); +} + +class VTK_IO_EXPORT vtkXMLParser : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkXMLParser,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkXMLParser* New(); + + //BTX + // Description: + // Get/Set the input stream. + vtkSetMacro(Stream, istream*); + vtkGetMacro(Stream, istream*); + //ETX + + // Description: + // Used by subclasses and their supporting classes. These methods + // wrap around the tellg and seekg methods of the input stream to + // work-around stream bugs on various platforms. + long TellG(); + void SeekG(long position); + + // Description: + // Parse the XML input. + virtual int Parse(); + + // Description: + // Parse the XML message. If length is specified, parse only the + // first "length" characters + virtual int Parse(const char* inputString); + virtual int Parse(const char* inputString, unsigned int length); + + // Description: + // When parsing fragments of XML or streaming XML, use the following + // three methods. InitializeParser method initialize parser but + // does not perform any actual parsing. ParseChunk parses framgent + // of XML. This has to match to what was already + // parsed. CleanupParser finishes parsing. If there were errors, + // CleanupParser will report them. + virtual int InitializeParser(); + virtual int ParseChunk(const char* inputString, unsigned int length); + virtual int CleanupParser(); + + // Description: + // Set and get file name. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkXMLParser(); + ~vtkXMLParser(); + + // Input stream. Set by user. + istream* Stream; + + // File name to parse + char* FileName; + + // This variable is true if there was a parse error while parsing in + // chunks. + int ParseError; + + // Character message to parse + const char* InputString; + int InputStringLength; + + // Expat parser structure. Exists only during call to Parse(). + void* Parser; + + // Called by Parse() to read the stream and call ParseBuffer. Can + // be replaced by subclasses to change how input is read. + virtual int ParseXML(); + + // Called before each block of input is read from the stream to + // check if parsing is complete. Can be replaced by subclasses to + // change the terminating condition for parsing. Parsing always + // stops when the end of file is reached in the stream. + virtual int ParsingComplete(); + + // Called when a new element is opened in the XML source. Should be + // replaced by subclasses to handle each element. + // name = Name of new element. + // atts = Null-terminated array of attribute name/value pairs. + // Even indices are attribute names, and odd indices are values. + virtual void StartElement(const char* name, const char** atts); + + // Called at the end of an element in the XML source opened when + // StartElement was called. + virtual void EndElement(const char* name); + + // Called when there is character data to handle. + virtual void CharacterDataHandler(const char* data, int length); + + // Called by begin handlers to report any stray attribute values. + virtual void ReportStrayAttribute(const char* element, const char* attr, + const char* value); + + // Called by begin handlers to report any missing attribute values. + virtual void ReportMissingAttribute(const char* element, const char* attr); + + // Called by begin handlers to report bad attribute values. + virtual void ReportBadAttribute(const char* element, const char* attr, + const char* value); + + // Called by StartElement to report unknown element type. + virtual void ReportUnknownElement(const char* element); + + // Called by Parse to report an XML syntax error. + virtual void ReportXmlParseError(); + + // Get the current byte index from the beginning of the XML stream. + unsigned long GetXMLByteIndex(); + + // Send the given buffer to the XML parser. + virtual int ParseBuffer(const char* buffer, unsigned int count); + + // Send the given c-style string to the XML parser. + int ParseBuffer(const char* buffer); + + // Utility for convenience of subclasses. Wraps isspace C library + // routine. + static int IsSpace(char c); + + //BTX + friend void vtkXMLParserStartElement(void*, const char*, const char**); + friend void vtkXMLParserEndElement(void*, const char*); + friend void vtkXMLParserCharacterDataHandler(void*, const char*, int); + //ETX + +private: + vtkXMLParser(const vtkXMLParser&); // Not implemented. + void operator=(const vtkXMLParser&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPolyDataReader.cxx b/IO/vtkXMLPolyDataReader.cxx new file mode 100644 index 0000000..b1eaabc --- /dev/null +++ b/IO/vtkXMLPolyDataReader.cxx @@ -0,0 +1,532 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPolyDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPolyDataReader.h" +#include "vtkObjectFactory.h" +#include "vtkXMLDataElement.h" +#include "vtkPolyData.h" +#include "vtkIdTypeArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkXMLPolyDataReader, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkXMLPolyDataReader); + +//---------------------------------------------------------------------------- +vtkXMLPolyDataReader::vtkXMLPolyDataReader() +{ + // Copied from vtkPolyDataReader constructor: + vtkPolyData *output = vtkPolyData::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); + + this->VertElements = 0; + this->LineElements = 0; + this->StripElements = 0; + this->PolyElements = 0; + this->TotalNumberOfVerts = 0; + this->TotalNumberOfLines = 0; + this->TotalNumberOfStrips = 0; + this->TotalNumberOfPolys = 0; + + // TimeStep + this->VertsTimeStep = -1; + this->VertsOffset = (unsigned long)-1; + this->LinesTimeStep = -1; + this->LinesOffset = (unsigned long)-1; + this->StripsTimeStep = -1; + this->StripsOffset = (unsigned long)-1; + this->PolysTimeStep = -1; + this->PolysOffset = (unsigned long)-1; +} + +//---------------------------------------------------------------------------- +vtkXMLPolyDataReader::~vtkXMLPolyDataReader() +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::SetOutput(vtkPolyData *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkXMLPolyDataReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkXMLPolyDataReader::GetOutput(int idx) +{ + return vtkPolyData::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPolyDataReader::GetNumberOfVerts() +{ + return this->TotalNumberOfVerts; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPolyDataReader::GetNumberOfLines() +{ + return this->TotalNumberOfLines; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPolyDataReader::GetNumberOfStrips() +{ + return this->TotalNumberOfStrips; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPolyDataReader::GetNumberOfPolys() +{ + return this->TotalNumberOfPolys; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPolyDataReader::GetDataSetName() +{ + return "PolyData"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::GetOutputUpdateExtent(int& piece, + int& numberOfPieces, + int& ghostLevel) +{ + this->GetOutput()->GetUpdateExtent(piece, numberOfPieces, ghostLevel); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::SetupOutputTotals() +{ + this->Superclass::SetupOutputTotals(); + // Find the total size of the output. + int i; + this->TotalNumberOfCells = 0; + this->TotalNumberOfVerts = 0; + this->TotalNumberOfLines = 0; + this->TotalNumberOfStrips = 0; + this->TotalNumberOfPolys = 0; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + this->TotalNumberOfCells += (this->NumberOfVerts[i] + + this->NumberOfLines[i] + + this->NumberOfStrips[i] + + this->NumberOfPolys[i]); + this->TotalNumberOfVerts += this->NumberOfVerts[i]; + this->TotalNumberOfLines += this->NumberOfLines[i]; + this->TotalNumberOfStrips += this->NumberOfStrips[i]; + this->TotalNumberOfPolys += this->NumberOfPolys[i]; + } + + // Data reading will start at the beginning of the output. + this->StartVert = 0; + this->StartLine = 0; + this->StartStrip = 0; + this->StartPoly = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::SetupPieces(int numPieces) +{ + this->Superclass::SetupPieces(numPieces); + this->NumberOfVerts = new vtkIdType[numPieces]; + this->NumberOfLines = new vtkIdType[numPieces]; + this->NumberOfStrips = new vtkIdType[numPieces]; + this->NumberOfPolys = new vtkIdType[numPieces]; + this->VertElements = new vtkXMLDataElement*[numPieces]; + this->LineElements = new vtkXMLDataElement*[numPieces]; + this->StripElements = new vtkXMLDataElement*[numPieces]; + this->PolyElements = new vtkXMLDataElement*[numPieces]; + for(int i=0;i < numPieces; ++i) + { + this->VertElements[i] = 0; + this->LineElements[i] = 0; + this->StripElements[i] = 0; + this->PolyElements[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::DestroyPieces() +{ + delete [] this->PolyElements; + delete [] this->StripElements; + delete [] this->LineElements; + delete [] this->VertElements; + delete [] this->NumberOfPolys; + delete [] this->NumberOfStrips; + delete [] this->NumberOfLines; + delete [] this->NumberOfVerts; + this->Superclass::DestroyPieces(); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPolyDataReader::GetNumberOfCellsInPiece(int piece) +{ + return (this->NumberOfVerts[piece]+ + this->NumberOfLines[piece]+ + this->NumberOfStrips[piece]+ + this->NumberOfPolys[piece]); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + vtkPolyData* output = this->GetOutput(); + + // Setup the output's cell arrays. + vtkCellArray* outVerts = vtkCellArray::New(); + vtkCellArray* outLines = vtkCellArray::New(); + vtkCellArray* outStrips = vtkCellArray::New(); + vtkCellArray* outPolys = vtkCellArray::New(); + + output->SetVerts(outVerts); + output->SetLines(outLines); + output->SetStrips(outStrips); + output->SetPolys(outPolys); + + outPolys->Delete(); + outStrips->Delete(); + outLines->Delete(); + outVerts->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkXMLPolyDataReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + if(!this->Superclass::ReadPiece(ePiece)) + { + return 0; + } + + if(!ePiece->GetScalarAttribute("NumberOfVerts", + this->NumberOfVerts[this->Piece])) + { + this->NumberOfVerts[this->Piece] = 0; + } + if(!ePiece->GetScalarAttribute("NumberOfLines", + this->NumberOfLines[this->Piece])) + { + this->NumberOfLines[this->Piece] = 0; + } + if(!ePiece->GetScalarAttribute("NumberOfStrips", + this->NumberOfStrips[this->Piece])) + { + this->NumberOfStrips[this->Piece] = 0; + } + if(!ePiece->GetScalarAttribute("NumberOfPolys", + this->NumberOfPolys[this->Piece])) + { + this->NumberOfPolys[this->Piece] = 0; + } + + // Find the cell elements in the piece. + int i; + for(i=0; i < ePiece->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = ePiece->GetNestedElement(i); + if((strcmp(eNested->GetName(), "Verts") == 0) + && (eNested->GetNumberOfNestedElements() > 1)) + { + this->VertElements[this->Piece] = eNested; + } + if((strcmp(eNested->GetName(), "Lines") == 0) + && (eNested->GetNumberOfNestedElements() > 1)) + { + this->LineElements[this->Piece] = eNested; + } + if((strcmp(eNested->GetName(), "Strips") == 0) + && (eNested->GetNumberOfNestedElements() > 1)) + { + this->StripElements[this->Piece] = eNested; + } + if((strcmp(eNested->GetName(), "Polys") == 0) + && (eNested->GetNumberOfNestedElements() > 1)) + { + this->PolyElements[this->Piece] = eNested; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataReader::SetupNextPiece() +{ + this->Superclass::SetupNextPiece(); + this->StartVert += this->NumberOfVerts[this->Piece]; + this->StartLine += this->NumberOfLines[this->Piece]; + this->StartStrip += this->NumberOfStrips[this->Piece]; + this->StartPoly += this->NumberOfPolys[this->Piece]; +} + +//---------------------------------------------------------------------------- +int vtkXMLPolyDataReader::ReadPieceData() +{ + // The amount of data read by the superclass's ReadPieceData comes + // from point/cell data and point specifications (we read cell + // specifications here). + vtkIdType superclassPieceSize = + ((this->NumberOfPointArrays+1)*this->GetNumberOfPointsInPiece(this->Piece)+ + this->NumberOfCellArrays*this->GetNumberOfCellsInPiece(this->Piece)); + + // Total amount of data in this piece comes from point/cell data + // arrays and the point/cell specifications themselves (cell + // specifications for vtkPolyData take two data arrays split across + // cell types). + vtkIdType totalPieceSize = + superclassPieceSize + 2*this->GetNumberOfCellsInPiece(this->Piece); + if(totalPieceSize == 0) + { + totalPieceSize = 1; + } + + // Split the progress range based on the approximate fraction of + // data that will be read by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[6] = + { + 0, + float(superclassPieceSize) / totalPieceSize, + (float(superclassPieceSize)+ + this->NumberOfVerts[this->Piece]) / totalPieceSize, + (float(superclassPieceSize)+ + this->NumberOfVerts[this->Piece]+ + this->NumberOfLines[this->Piece]) / totalPieceSize, + (float(superclassPieceSize)+ + this->NumberOfVerts[this->Piece]+ + this->NumberOfLines[this->Piece]+ + this->NumberOfStrips[this->Piece]) / totalPieceSize, + 1 + }; + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass read its data. + if(!this->Superclass::ReadPieceData()) + { + return 0; + } + + vtkPolyData* output = this->GetOutput(); + + // Set the range of progress for the Verts. + this->SetProgressRange(progressRange, 1, fractions); + + // Read the Verts. + vtkXMLDataElement* eVerts = this->VertElements[this->Piece]; + if(eVerts) + { +// int needToRead = this->CellsNeedToReadTimeStep(eNested, +// this->VertsTimeStep, this->VertsOffset); +// if( needToRead ) + { + // Read the array. + if(!this->ReadCellArray(this->NumberOfVerts[this->Piece], + this->TotalNumberOfVerts, + eVerts, + output->GetVerts())) + { + return 0; + } + } + } + + // Set the range of progress for the Lines. + this->SetProgressRange(progressRange, 2, fractions); + + // Read the Lines. + vtkXMLDataElement* eLines = this->LineElements[this->Piece]; + if(eLines) + { +// int needToRead = this->CellsNeedToReadTimeStep(eNested, +// this->LinesTimeStep, this->LinesOffset); +// if( needToRead ) + { + // Read the array. + if(!this->ReadCellArray(this->NumberOfLines[this->Piece], + this->TotalNumberOfLines, + eLines, + output->GetLines())) + { + return 0; + } + } + } + + // Set the range of progress for the Strips. + this->SetProgressRange(progressRange, 3, fractions); + + // Read the Strips. + vtkXMLDataElement* eStrips = this->StripElements[this->Piece]; + if(eStrips) + { +// int needToRead = this->CellsNeedToReadTimeStep(eNested, +// this->StripsTimeStep, this->StripsOffset); +// if( needToRead ) + { + // Read the array. + if(!this->ReadCellArray(this->NumberOfStrips[this->Piece], + this->TotalNumberOfStrips, + eStrips, + output->GetStrips())) + { + return 0; + } + } + } + + // Set the range of progress for the Polys. + this->SetProgressRange(progressRange, 4, fractions); + + // Read the Polys. + vtkXMLDataElement* ePolys = this->PolyElements[this->Piece]; + if(ePolys) + { +// int needToRead = this->CellsNeedToReadTimeStep(eNested, +// this->PolysTimeStep, this->PolysOffset); +// if( needToRead ) + { + // Read the array. + if(!this->ReadCellArray(this->NumberOfPolys[this->Piece], + this->TotalNumberOfPolys, + ePolys, + output->GetPolys())) + { + return 0; + } + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLPolyDataReader::ReadArrayForCells(vtkXMLDataElement* da, + vtkDataArray* outArray) +{ + // Split progress range according to the fraction of data that will + // be read for each type of cell. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int total = this->TotalNumberOfCells?this->TotalNumberOfCells:1; + float fractions[5] = + { + 0, + float(this->NumberOfVerts[this->Piece])/total, + float(this->NumberOfVerts[this->Piece]+ + this->NumberOfLines[this->Piece])/total, + float(this->NumberOfVerts[this->Piece]+ + this->NumberOfLines[this->Piece]+ + this->NumberOfStrips[this->Piece])/total, + 1 + }; + + vtkIdType components = outArray->GetNumberOfComponents(); + + // Set range of progress for the Verts. + this->SetProgressRange(progressRange, 0, fractions); + + // Read the cell data for the Verts in the piece. + vtkIdType inStartCell = 0; + vtkIdType outStartCell = this->StartVert; + vtkIdType numCells = this->NumberOfVerts[this->Piece]; + if(!this->ReadData(da, outArray->GetVoidPointer(outStartCell*components), + outArray->GetDataType(), inStartCell*components, + numCells*components)) + { + return 0; + } + + // Set range of progress for the Lines. + this->SetProgressRange(progressRange, 1, fractions); + + // Read the cell data for the Lines in the piece. + inStartCell += numCells; + outStartCell = this->TotalNumberOfVerts + this->StartLine; + numCells = this->NumberOfLines[this->Piece]; + if(!this->ReadData(da, outArray->GetVoidPointer(outStartCell*components), + outArray->GetDataType(), inStartCell*components, + numCells*components)) + { + return 0; + } + + // Set range of progress for the Strips. + this->SetProgressRange(progressRange, 2, fractions); + + // Read the cell data for the Strips in the piece. + inStartCell += numCells; + outStartCell = (this->TotalNumberOfVerts + this->TotalNumberOfLines + + this->StartStrip); + numCells = this->NumberOfStrips[this->Piece]; + if(!this->ReadData(da, outArray->GetVoidPointer(outStartCell*components), + outArray->GetDataType(), inStartCell*components, + numCells*components)) + { + return 0; + } + + // Set range of progress for the Polys. + this->SetProgressRange(progressRange, 3, fractions); + + // Read the cell data for the Polys in the piece. + inStartCell += numCells; + outStartCell = (this->TotalNumberOfVerts + this->TotalNumberOfLines + + this->TotalNumberOfStrips + this->StartPoly); + numCells = this->NumberOfPolys[this->Piece]; + if(!this->ReadData(da, outArray->GetVoidPointer(outStartCell*components), + outArray->GetDataType(), inStartCell*components, + numCells*components)) + { + return 0; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkXMLPolyDataReader::FillOutputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData"); + return 1; +} diff --git a/IO/vtkXMLPolyDataReader.h b/IO/vtkXMLPolyDataReader.h new file mode 100644 index 0000000..8d435d7 --- /dev/null +++ b/IO/vtkXMLPolyDataReader.h @@ -0,0 +1,112 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPolyDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPolyDataReader - Read VTK XML PolyData files. +// .SECTION Description +// vtkXMLPolyDataReader reads the VTK XML PolyData file format. One +// polygonal data file can be read to produce one output. Streaming +// is supported. The standard extension for this reader's file format +// is "vtp". This reader is also used to read a single piece of the +// parallel file format. + +// .SECTION See Also +// vtkXMLPPolyDataReader + +#ifndef __vtkXMLPolyDataReader_h +#define __vtkXMLPolyDataReader_h + +#include "vtkXMLUnstructuredDataReader.h" + +class vtkPolyData; + +class VTK_IO_EXPORT vtkXMLPolyDataReader : public vtkXMLUnstructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLPolyDataReader,vtkXMLUnstructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPolyDataReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkPolyData *output); + vtkPolyData *GetOutput(); + vtkPolyData *GetOutput(int idx); + + // Description: + // Get the number of verts/lines/strips/polys in the output. + virtual vtkIdType GetNumberOfVerts(); + virtual vtkIdType GetNumberOfLines(); + virtual vtkIdType GetNumberOfStrips(); + virtual vtkIdType GetNumberOfPolys(); + +protected: + vtkXMLPolyDataReader(); + ~vtkXMLPolyDataReader(); + + const char* GetDataSetName(); + void GetOutputUpdateExtent(int& piece, int& numberOfPieces, int& ghostLevel); + void SetupOutputTotals(); + void SetupNextPiece(); + void SetupPieces(int numPieces); + void DestroyPieces(); + + void SetupOutputData(); + int ReadPiece(vtkXMLDataElement* ePiece); + int ReadPieceData(); + + // Read a data array whose tuples coorrespond to cells. + int ReadArrayForCells(vtkXMLDataElement* da, vtkDataArray* outArray); + + // Get the number of cells in the given piece. Valid after + // UpdateInformation. + virtual vtkIdType GetNumberOfCellsInPiece(int piece); + + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The size of the UpdatePiece. + int TotalNumberOfVerts; + int TotalNumberOfLines; + int TotalNumberOfStrips; + int TotalNumberOfPolys; + vtkIdType StartVert; + vtkIdType StartLine; + vtkIdType StartStrip; + vtkIdType StartPoly; + + // The cell elements for each piece. + vtkXMLDataElement** VertElements; + vtkXMLDataElement** LineElements; + vtkXMLDataElement** StripElements; + vtkXMLDataElement** PolyElements; + vtkIdType* NumberOfVerts; + vtkIdType* NumberOfLines; + vtkIdType* NumberOfStrips; + vtkIdType* NumberOfPolys; + + // For TimeStep support + int VertsTimeStep; + unsigned long VertsOffset; + int LinesTimeStep; + unsigned long LinesOffset; + int StripsTimeStep; + unsigned long StripsOffset; + int PolysTimeStep; + unsigned long PolysOffset; + +private: + vtkXMLPolyDataReader(const vtkXMLPolyDataReader&); // Not implemented. + void operator=(const vtkXMLPolyDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLPolyDataWriter.cxx b/IO/vtkXMLPolyDataWriter.cxx new file mode 100644 index 0000000..10eec8d --- /dev/null +++ b/IO/vtkXMLPolyDataWriter.cxx @@ -0,0 +1,413 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPolyDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLPolyDataWriter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkInformationIntegerKey.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#define vtkOffsetsManager_DoNotInclude +#include "vtkOffsetsManagerArray.h" +#undef vtkOffsetsManager_DoNotInclude + +vtkCxxRevisionMacro(vtkXMLPolyDataWriter, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkXMLPolyDataWriter); + +//---------------------------------------------------------------------------- +vtkXMLPolyDataWriter::vtkXMLPolyDataWriter() +{ + this->VertsOM = new OffsetsManagerArray; + this->LinesOM = new OffsetsManagerArray; + this->StripsOM = new OffsetsManagerArray; + this->PolysOM = new OffsetsManagerArray; +} + +//---------------------------------------------------------------------------- +vtkXMLPolyDataWriter::~vtkXMLPolyDataWriter() +{ + delete this->VertsOM; + delete this->LinesOM; + delete this->StripsOM; + delete this->PolysOM; +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkPolyData* vtkXMLPolyDataWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + + +//---------------------------------------------------------------------------- +const char* vtkXMLPolyDataWriter::GetDataSetName() +{ + return "PolyData"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLPolyDataWriter::GetDefaultFileExtension() +{ + return "vtp"; +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::AllocatePositionArrays() +{ + this->Superclass::AllocatePositionArrays(); + + this->NumberOfVertsPositions = new unsigned long[this->NumberOfPieces]; + this->NumberOfLinesPositions = new unsigned long[this->NumberOfPieces]; + this->NumberOfStripsPositions = new unsigned long[this->NumberOfPieces]; + this->NumberOfPolysPositions = new unsigned long[this->NumberOfPieces]; + + this->VertsOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps); + this->LinesOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps); + this->StripsOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps); + this->PolysOM->Allocate(this->NumberOfPieces, 2, this->NumberOfTimeSteps); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::DeletePositionArrays() +{ + this->Superclass::DeletePositionArrays(); + + delete[] this->NumberOfVertsPositions; + delete[] this->NumberOfLinesPositions; + delete[] this->NumberOfStripsPositions; + delete[] this->NumberOfPolysPositions; +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::WriteInlinePieceAttributes() +{ + this->Superclass::WriteInlinePieceAttributes(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + vtkPolyData* input = this->GetInput(); + this->WriteScalarAttribute("NumberOfVerts", + input->GetVerts()->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->WriteScalarAttribute("NumberOfLines", + input->GetLines()->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->WriteScalarAttribute("NumberOfStrips", + input->GetStrips()->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->WriteScalarAttribute("NumberOfPolys", + input->GetPolys()->GetNumberOfCells()); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::WriteInlinePiece(vtkIndent indent) +{ + // Split progress range by the approximate fraction of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[6]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteInlinePiece(indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + vtkPolyData* input = this->GetInput(); + + // Set the range of progress for Verts. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the Verts. + this->WriteCellsInline("Verts", input->GetVerts(), 0, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for Lines. + this->SetProgressRange(progressRange, 2, fractions); + + // Write the Lines. + this->WriteCellsInline("Lines", input->GetLines(), 0, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for Strips. + this->SetProgressRange(progressRange, 3, fractions); + + // Write the Strips. + this->WriteCellsInline("Strips", input->GetStrips(), 0, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for Polys. + this->SetProgressRange(progressRange, 4, fractions); + + // Write the Polys. + this->WriteCellsInline("Polys", input->GetPolys(), 0, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::WriteAppendedPieceAttributes(int index) +{ + this->Superclass::WriteAppendedPieceAttributes(index); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->NumberOfVertsPositions[index] = + this->ReserveAttributeSpace("NumberOfVerts"); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->NumberOfLinesPositions[index] = + this->ReserveAttributeSpace("NumberOfLines"); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->NumberOfStripsPositions[index] = + this->ReserveAttributeSpace("NumberOfStrips"); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->NumberOfPolysPositions[index] = + this->ReserveAttributeSpace("NumberOfPolys"); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::WriteAppendedPiece(int index, vtkIndent indent) +{ + this->Superclass::WriteAppendedPiece(index, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteCellsAppended("Verts", 0, indent, &this->VertsOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteCellsAppended("Lines", 0, indent , &this->LinesOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteCellsAppended("Strips", 0, indent, &this->StripsOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteCellsAppended("Polys", 0, indent, &this->PolysOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::WriteAppendedPieceData(int index) +{ + ostream& os = *(this->Stream); + vtkPolyData* input = this->GetInput(); + + unsigned long returnPosition = os.tellp(); + os.seekp(this->NumberOfVertsPositions[index]); + this->WriteScalarAttribute("NumberOfVerts", + input->GetVerts()->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + os.seekp(this->NumberOfLinesPositions[index]); + this->WriteScalarAttribute("NumberOfLines", + input->GetLines()->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + os.seekp(this->NumberOfStripsPositions[index]); + this->WriteScalarAttribute("NumberOfStrips", + input->GetStrips()->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + os.seekp(this->NumberOfPolysPositions[index]); + this->WriteScalarAttribute("NumberOfPolys", + input->GetPolys()->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + os.seekp(returnPosition); + + // Split progress range by the approximate fraction of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[6]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteAppendedPieceData(index); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for Verts. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the Verts. + this->WriteCellsAppendedData(input->GetVerts(), 0, + this->CurrentTimeIndex, + &this->VertsOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for Lines. + this->SetProgressRange(progressRange, 2, fractions); + + // Write the Lines. + this->WriteCellsAppendedData(input->GetLines(), 0, + this->CurrentTimeIndex, + &this->LinesOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for Strips. + this->SetProgressRange(progressRange, 3, fractions); + + // Write the Strips. + this->WriteCellsAppendedData(input->GetStrips(), 0, + this->CurrentTimeIndex, + &this->StripsOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for Polys. + this->SetProgressRange(progressRange, 4, fractions); + + // Write the Polys. + this->WriteCellsAppendedData(input->GetPolys(), 0, + this->CurrentTimeIndex, + &this->PolysOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLPolyDataWriter::GetNumberOfInputCells() +{ + vtkPolyData* input = this->GetInput(); + return (input->GetVerts()->GetNumberOfCells()+ + input->GetLines()->GetNumberOfCells()+ + input->GetStrips()->GetNumberOfCells()+ + input->GetPolys()->GetNumberOfCells()); +} + +//---------------------------------------------------------------------------- +void vtkXMLPolyDataWriter::CalculateSuperclassFraction(float* fractions) +{ + vtkPolyData* input = this->GetInput(); + + // The superclass will write point/cell data and point specifications. + int pdArrays = input->GetPointData()->GetNumberOfArrays(); + int cdArrays = input->GetCellData()->GetNumberOfArrays(); + vtkIdType pdSize = pdArrays*this->GetNumberOfInputPoints(); + vtkIdType cdSize = cdArrays*this->GetNumberOfInputCells(); + vtkIdType pointsSize = this->GetNumberOfInputPoints(); + + // This class will write cell specifications. + vtkIdType connectSizeV = (input->GetVerts()->GetData()->GetNumberOfTuples() - + input->GetVerts()->GetNumberOfCells()); + vtkIdType connectSizeL = (input->GetLines()->GetData()->GetNumberOfTuples() - + input->GetLines()->GetNumberOfCells()); + vtkIdType connectSizeS = (input->GetStrips()->GetData()->GetNumberOfTuples() - + input->GetStrips()->GetNumberOfCells()); + vtkIdType connectSizeP = (input->GetPolys()->GetData()->GetNumberOfTuples() - + input->GetPolys()->GetNumberOfCells()); + vtkIdType offsetSizeV = input->GetVerts()->GetNumberOfCells(); + vtkIdType offsetSizeL = input->GetLines()->GetNumberOfCells(); + vtkIdType offsetSizeS = input->GetStrips()->GetNumberOfCells(); + vtkIdType offsetSizeP = input->GetPolys()->GetNumberOfCells(); + fractions[0] = 0; + fractions[1] = fractions[0] + pdSize+cdSize+pointsSize; + fractions[2] = fractions[1] + connectSizeV+offsetSizeV; + fractions[3] = fractions[2] + connectSizeL+offsetSizeL; + fractions[4] = fractions[3] + connectSizeS+offsetSizeS; + fractions[5] = fractions[4] + connectSizeP+offsetSizeP; + if(fractions[5] == 0) + { + fractions[5] = 1; + } + for(int i=0; i < 5;++i) + { + fractions[i+1] = fractions[i+1] / fractions[5]; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLPolyDataWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} diff --git a/IO/vtkXMLPolyDataWriter.h b/IO/vtkXMLPolyDataWriter.h new file mode 100644 index 0000000..4b26c89 --- /dev/null +++ b/IO/vtkXMLPolyDataWriter.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLPolyDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLPolyDataWriter - Write VTK XML PolyData files. +// .SECTION Description +// vtkXMLPolyDataWriter writes the VTK XML PolyData file format. One +// polygonal data input can be written into one file in any number of +// streamed pieces (if supported by the rest of the pipeline). The +// standard extension for this writer's file format is "vtp". This +// writer is also used to write a single piece of the parallel file +// format. + +// .SECTION See Also +// vtkXMLPPolyDataWriter + +#ifndef __vtkXMLPolyDataWriter_h +#define __vtkXMLPolyDataWriter_h + +#include "vtkXMLUnstructuredDataWriter.h" + +class vtkPolyData; + +class VTK_IO_EXPORT vtkXMLPolyDataWriter : public vtkXMLUnstructuredDataWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLPolyDataWriter,vtkXMLUnstructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLPolyDataWriter* New(); + + //BTX + // Description: + // Get/Set the writer's input. + vtkPolyData* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLPolyDataWriter(); + ~vtkXMLPolyDataWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + const char* GetDataSetName(); + + virtual void AllocatePositionArrays(); + virtual void DeletePositionArrays(); + + void WriteInlinePieceAttributes(); + void WriteInlinePiece(vtkIndent indent); + + void WriteAppendedPieceAttributes(int index); + void WriteAppendedPiece(int index, vtkIndent indent); + void WriteAppendedPieceData(int index); + + virtual vtkIdType GetNumberOfInputCells(); + void CalculateSuperclassFraction(float* fractions); + + // Positions of attributes for each piece. + unsigned long* NumberOfVertsPositions; + unsigned long* NumberOfLinesPositions; + unsigned long* NumberOfStripsPositions; + unsigned long* NumberOfPolysPositions; + + OffsetsManagerArray *VertsOM; + OffsetsManagerArray *LinesOM; + OffsetsManagerArray *StripsOM; + OffsetsManagerArray *PolysOM; + +private: + vtkXMLPolyDataWriter(const vtkXMLPolyDataWriter&); // Not implemented. + void operator=(const vtkXMLPolyDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLReader.cxx b/IO/vtkXMLReader.cxx new file mode 100644 index 0000000..501f025 --- /dev/null +++ b/IO/vtkXMLReader.cxx @@ -0,0 +1,1157 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLReader.h" + +#include "vtkCallbackCommand.h" +#include "vtkDataArray.h" +#include "vtkDataArraySelection.h" +#include "vtkDataCompressor.h" +#include "vtkDataSet.h" +#include "vtkDataSetAttributes.h" +#include "vtkInstantiator.h" +#include "vtkObjectFactory.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLDataParser.h" +#include "vtkXMLFileReadTester.h" +#include "vtkZLibDataCompressor.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include +#include + +vtkCxxRevisionMacro(vtkXMLReader, "$Revision: 1.38.4.1 $"); + +//---------------------------------------------------------------------------- +vtkXMLReader::vtkXMLReader() +{ + this->FileName = 0; + this->Stream = 0; + this->FileStream = 0; + this->XMLParser = 0; + this->FieldDataElement = 0; + this->PointDataArraySelection = vtkDataArraySelection::New(); + this->CellDataArraySelection = vtkDataArraySelection::New(); + this->InformationError = 0; + this->DataError = 0; + this->ReadError = 0; + this->CurrentOutput = -1; + this->ProgressRange[0] = 0; + this->ProgressRange[1] = 1; + + // Setup the selection callback to modify this object when an array + // selection is changed. + this->SelectionObserver = vtkCallbackCommand::New(); + this->SelectionObserver->SetCallback(&vtkXMLReader::SelectionModifiedCallback); + this->SelectionObserver->SetClientData(this); + this->PointDataArraySelection->AddObserver(vtkCommand::ModifiedEvent, + this->SelectionObserver); + this->CellDataArraySelection->AddObserver(vtkCommand::ModifiedEvent, + this->SelectionObserver); + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); + + // Lower dimensional cell data support. + this->AxesEmpty[0] = 0; + this->AxesEmpty[1] = 0; + this->AxesEmpty[2] = 0; + + // Time support: + this->TimeStep = 0; // By default the file does not have timestep + this->TimeStepRange[0] = 0; + this->TimeStepRange[1] = 0; + this->NumberOfTimeSteps = 0; + this->TimeSteps = 0; + this->CurrentTimeStep = 0; + this->TimeStepWasReadOnce = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLReader::~vtkXMLReader() +{ + this->SetFileName(0); + if(this->XMLParser) + { + this->DestroyXMLParser(); + } + this->CellDataArraySelection->RemoveObserver(this->SelectionObserver); + this->PointDataArraySelection->RemoveObserver(this->SelectionObserver); + this->SelectionObserver->Delete(); + this->CellDataArraySelection->Delete(); + this->PointDataArraySelection->Delete(); + delete[] this->TimeSteps; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "FileName: " + << (this->FileName? this->FileName:"(none)") << "\n"; + os << indent << "CellDataArraySelection: " << this->CellDataArraySelection + << "\n"; + os << indent << "PointDataArraySelection: " << this->PointDataArraySelection + << "\n"; + if(this->Stream) + { + os << indent << "Stream: " << this->Stream << "\n"; + } + else + { + os << indent << "Stream: (none)\n"; + } + os << indent << "TimeStep:" << this->TimeStep << "\n"; + os << indent << "NumberOfTimeSteps:" << this->NumberOfTimeSteps << "\n"; + os << indent << "TimeStepRange:(" << this->TimeStepRange[0] << "," + << this->TimeStepRange[1] << ")\n"; +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkXMLReader::GetOutputAsDataSet() +{ + return this->GetOutputAsDataSet(0); +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkXMLReader::GetOutputAsDataSet(int index) +{ + return vtkDataSet::SafeDownCast( this->GetOutputDataObject(index) ); +} + +//---------------------------------------------------------------------------- +// Major version should be incremented when older readers can no longer +// read files written for this reader. Minor versions are for added +// functionality that can be safely ignored by older readers. +int vtkXMLReader::CanReadFileVersion(int major, int vtkNotUsed(minor)) +{ + if (major > 0) + { + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::OpenVTKFile() +{ + if(this->FileStream) + { + vtkErrorMacro("File already open."); + return 1; + } + + if(!this->Stream && !this->FileName) + { + vtkErrorMacro("File name not specified"); + return 0; + } + + if(this->Stream) + { + // Use user-provided stream. + return 1; + } + + // Need to open a file. First make sure it exists. This prevents + // an empty file from being created on older compilers. + struct stat fs; + if(stat(this->FileName, &fs) != 0) + { + vtkErrorMacro("Error opening file " << this->FileName); + return 0; + } + +#ifdef _WIN32 + this->FileStream = new ifstream(this->FileName, ios::binary | ios::in); +#else + this->FileStream = new ifstream(this->FileName, ios::in); +#endif + + if(!this->FileStream || !(*this->FileStream)) + { + vtkErrorMacro("Error opening file " << this->FileName); + if(this->FileStream) + { + delete this->FileStream; + this->FileStream = 0; + } + return 0; + } + + // Use the file stream. + this->Stream = this->FileStream; + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::CloseVTKFile() +{ + if(!this->Stream) + { + vtkErrorMacro("File not open."); + return; + } + if(this->Stream == this->FileStream) + { + // We opened the file. Close it. + this->FileStream->close(); + delete this->FileStream; + this->FileStream = 0; + this->Stream = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::CreateXMLParser() +{ + if(this->XMLParser) + { + vtkErrorMacro("CreateXMLParser() called with existing XMLParser."); + this->DestroyXMLParser(); + } + this->XMLParser = vtkXMLDataParser::New(); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::DestroyXMLParser() +{ + if(!this->XMLParser) + { + vtkErrorMacro("DestroyXMLParser() called with no current XMLParser."); + return; + } + this->XMLParser->Delete(); + this->XMLParser = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetupCompressor(const char* type) +{ + // Instantiate a compressor of the given type. + if(!type) + { + vtkErrorMacro("Compressor has no type."); + return; + } + vtkObject* object = vtkInstantiator::CreateInstance(type); + vtkDataCompressor* compressor = vtkDataCompressor::SafeDownCast(object); + + // In static builds, the vtkZLibDataCompressor may not have been + // registered with the vtkInstantiator. Check for it here. + if(!compressor && (strcmp(type, "vtkZLibDataCompressor") == 0)) + { + compressor = vtkZLibDataCompressor::New(); + } + + if(!compressor) + { + vtkErrorMacro("Error creating " << type); + if(object) + { + object->Delete(); + } + return; + } + this->XMLParser->SetCompressor(compressor); + compressor->Delete(); +} + + + +//---------------------------------------------------------------------------- +int vtkXMLReader::ReadXMLInformation() +{ + // only Parse if something has changed + if(this->GetMTime() > this->ReadMTime) + { + // Destroy any old information that was parsed. + if(this->XMLParser) + { + this->DestroyXMLParser(); + } + + // Open the input file. If it fails, the error was already + // reported by OpenVTKFile. + if(!this->OpenVTKFile()) + { + this->SetupEmptyOutput(); + return 0; + } + + // Create the vtkXMLParser instance used to parse the file. + this->CreateXMLParser(); + + // Configure the parser for this file. + this->XMLParser->SetStream(this->Stream); + + // Parse the input file. + if(this->XMLParser->Parse()) + { + // Let the subclasses read the information they want. + if(!this->ReadVTKFile(this->XMLParser->GetRootElement())) + { + // There was an error reading the file. + this->ReadError = 1; + } + else + { + this->ReadError = 0; + } + } + else + { + vtkErrorMacro("Error parsing input file. ReadXMLInformation aborting."); + // The output should be empty to prevent the rest of the pipeline + // from executing. + this->ReadError = 1; + this->SetupEmptyOutput(); + } + + // Close the file to prevent resource leaks. + this->CloseVTKFile(); + + this->ReadMTime.Modified(); + } + return !this->ReadError; +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::RequestInformation(vtkInformation *request, + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + if (this->ReadXMLInformation()) + { + this->InformationError = 0; + // Let the subclasses read the information they want. + int outputPort = request->Get( vtkDemandDrivenPipeline::FROM_OUTPUT_PORT() ); + outputPort = outputPort >= 0 ? outputPort : 0; + this->SetupOutputInformation( outputVector->GetInformationObject(outputPort) ); + + // this->NumberOfTimeSteps has been set during the this->ReadXMLInformation() + int numTimesteps = this->GetNumberOfTimeSteps(); + this->TimeStepRange[0] = 0; + this->TimeStepRange[1] = numTimesteps-1; + if (numTimesteps != 0) + { + double* timeSteps = new double[numTimesteps]; + for (int i=0; iGetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_STEPS(), + timeSteps, + numTimesteps); + } + } + else + { + this->InformationError = 1; + } + + return !this->InformationError; +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::RequestData(vtkInformation *request, + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // Set which output we are updating. If the given object is not one + // of our outputs, just initialize it to empty and return. + this->CurrentOutput = request->Get( vtkDemandDrivenPipeline::FROM_OUTPUT_PORT() ); + if(this->CurrentOutput < 0) + { + this->GetExecutive()->GetOutputData(0)->Initialize(); + return 0; + } + + this->CurrentTimeStep = this->TimeStep; + + // Get the output pipeline information and data object. + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT()); + + // Check if a particular time was requested. + if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_INDEX())) + { + // Get the requested time step. + this->CurrentTimeStep = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_INDEX()); + + // Save the time value in the output data information. + int length = + outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + if(this->CurrentTimeStep >= 0 && this->CurrentTimeStep < length) + { + double* steps = + outInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); + output->GetInformation()->Set(vtkDataObject::DATA_TIME(), + steps[this->CurrentTimeStep]); + } + else + { + vtkErrorMacro("Time index " << this->CurrentTimeStep + << " requested but there are " + << length << " time steps."); + } + + // Clamp the requested time step to be in bounds. + if ( this->CurrentTimeStep < this->TimeStepRange[0] ) + { + this->CurrentTimeStep = this->TimeStepRange[0]; + } + else if ( this->CurrentTimeStep > this->TimeStepRange[1] ) + { + this->CurrentTimeStep = this->TimeStepRange[1]; + } + } + + // Set the time we will store in the output. + output->GetInformation()->Set(vtkDataObject::DATA_TIME_INDEX(), + this->CurrentTimeStep); + + // Re-open the input file. If it fails, the error was already + // reported by OpenVTKFile. + if(!this->OpenVTKFile()) + { + this->SetupEmptyOutput(); + return 0; + } + if(!this->XMLParser) + { + vtkErrorMacro("ExecuteData called with no current XMLParser."); + } + + // Give the vtkXMLParser instance its file back so that data section + // reads will work. + this->XMLParser->SetStream(this->Stream); + + // We are just starting to read. Do not call UpdateProgressDiscrete + // because we want a 0 progress callback the first time. + this->UpdateProgress(0); + + // Initialize progress range to entire 0..1 range. + float wholeProgressRange[2] = {0,1}; + this->SetProgressRange(wholeProgressRange, 0, 1); + + if(!this->InformationError) + { + // We are just starting to execute. No errors have yet occurred. + this->XMLParser->SetAbort(0); + this->DataError = 0; + + // Let the subclasses read the data they want. + this->ReadXMLData(); + + // If we aborted or there was an error, provide empty output. + if(this->DataError || this->AbortExecute) + { + this->GetOutputAsDataSet(this->CurrentOutput)->Initialize(); + } + } + else + { + // There was an error reading the file. Provide empty output. + this->GetOutputAsDataSet(this->CurrentOutput)->Initialize(); + } + + // We have finished reading. + this->UpdateProgressDiscrete(1); + + // Close the file to prevent resource leaks. + this->CloseVTKFile(); + if( this->TimeSteps ) + { + // The SetupOutput should not reallocate this should be done only in a TimeStep case + this->TimeStepWasReadOnce = 1; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkXMLReader::ReadXMLData() +{ + // Initialize the output's data. + if( !this->TimeStepWasReadOnce ) + { + this->SetupOutputData(); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::ReadVTKFile(vtkXMLDataElement* eVTKFile) +{ + // Check if the file version is one we support. + const char* version = eVTKFile->GetAttribute("version"); + if(version && !this->CanReadFileVersionString(version)) + { + vtkErrorMacro("File version: " << version << " is is higher than " + "this reader supports. Cannot read file."); + return 0; + } + + // Setup the compressor if there is one. + const char* compressor = eVTKFile->GetAttribute("compressor"); + if(compressor) + { + this->SetupCompressor(compressor); + } + + // Get the primary element. + const char* name = this->GetDataSetName(); + int i; + vtkXMLDataElement* ePrimary = 0; + for(i=0; i < eVTKFile->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = eVTKFile->GetNestedElement(i); + if(strcmp(eNested->GetName(), name) == 0) + { + ePrimary = eNested; + break; + } + } + if(!ePrimary) + { + vtkErrorMacro("Cannot find " << name << " element in file."); + return 0; + } + + // Read the primary element. + return this->ReadPrimaryElement(ePrimary); +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + // We don't need any information from the primary element here. + // + // + // Let check the "TimeValues" here + const int tsMax = 4096; + double timevalues[tsMax]; + int numTimeSteps = ePrimary->GetVectorAttribute("TimeValues", tsMax, timevalues); + assert( numTimeSteps <= tsMax); + this->SetNumberOfTimeSteps( numTimeSteps ); + + // See if there is a FieldData element + int numNested = ePrimary->GetNumberOfNestedElements(); + for(int i=0; i < numNested; ++i) + { + vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i); + if(strcmp(eNested->GetName(), "FieldData") == 0) + { + this->FieldDataElement = eNested; + return 1; + } + } + + this->FieldDataElement = 0; + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetupOutputData() +{ + // Initialize the output. + int i; + for(i=0; i < this->GetNumberOfOutputPorts(); ++i) + { + this->GetExecutive()->GetOutputData(i)->Initialize(); + } +} + +//---------------------------------------------------------------------------- +vtkDataArray* vtkXMLReader::CreateDataArray(vtkXMLDataElement* da) +{ + int dataType = 0; + if(!da->GetWordTypeAttribute("type", dataType)) + { + return 0; + } + + vtkDataArray* array = vtkDataArray::CreateDataArray(dataType); + + array->SetName(da->GetAttribute("Name")); + + int components; + if(da->GetScalarAttribute("NumberOfComponents", components)) + { + array->SetNumberOfComponents(components); + } + + return array; +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::CanReadFile(const char* name) +{ + // First make sure the file exists. This prevents an empty file + // from being created on older compilers. + struct stat fs; + if(stat(name, &fs) != 0) + { + return 0; + } + + // Test if the file with the given name is a VTKFile with the given + // type. + vtkXMLFileReadTester* tester = vtkXMLFileReadTester::New(); + tester->SetFileName(name); + + int result = 0; + if(tester->TestReadFile() && tester->GetFileDataType()) + { + if(strcmp(tester->GetFileDataType(), this->GetDataSetName()) == 0) + { + const char* version = tester->GetFileVersion(); + if(version) + { + if(this->CanReadFileVersionString(version)) + { + result = 3; + } + } + else + { + result = 3; + } + } + } + + tester->Delete(); + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::CanReadFileVersionString(const char* version) +{ + // Extract the major and minor version numbers. + size_t length = strlen(version); + int major = 0; + int minor = 0; + const char* begin = version; + const char* end = version + length; + const char* s; + + for(s=begin; (s != end) && (*s != '.'); ++s); + + if(s > begin) + { + strstream str; + str.write(begin, s-begin); + str << ends; + str >> major; + if(!str) + { + major = 0; + } + } + if(++s < end) + { + strstream str; + str.write(s, end-s); + str << ends; + str >> minor; + if(!str) + { + minor = 0; + } + } + + return this->CanReadFileVersion(major, minor); +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::IntersectExtents(int* extent1, int* extent2, int* result) +{ + if((extent1[0] > extent2[1]) || (extent1[2] > extent2[3]) || + (extent1[4] > extent2[5]) || (extent1[1] < extent2[0]) || + (extent1[3] < extent2[2]) || (extent1[5] < extent2[4])) + { + // No intersection of extents. + return 0; + } + + // Get the intersection of the extents. + result[0] = this->Max(extent1[0], extent2[0]); + result[1] = this->Min(extent1[1], extent2[1]); + result[2] = this->Max(extent1[2], extent2[2]); + result[3] = this->Min(extent1[3], extent2[3]); + result[4] = this->Max(extent1[4], extent2[4]); + result[5] = this->Min(extent1[5], extent2[5]); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::Min(int a, int b) +{ + return (a < b)? a : b; +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::Max(int a, int b) +{ + return (a > b)? a : b; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::ComputePointDimensions(int* extent, int* dimensions) +{ + dimensions[0] = extent[1] - extent[0] + 1; + dimensions[1] = extent[3] - extent[2] + 1; + dimensions[2] = extent[5] - extent[4] + 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::ComputePointIncrements(int* extent, vtkIdType* increments) +{ + increments[0] = 1; + increments[1] = increments[0] * (extent[1] - extent[0] + 1); + increments[2] = increments[1] * (extent[3] - extent[2] + 1); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::ComputeCellDimensions(int* extent, int* dimensions) +{ + // For structured cells, axes that are empty of cells are treated as + // having one cell when computing cell counts. This allows cell + // dimensions lower than 3. + for(int a=0; a < 3; ++a) + { + if(this->AxesEmpty[a] && extent[2*a+1] == extent[2*a]) + { + dimensions[a] = 1; + } + else + { + dimensions[a] = extent[2*a+1] - extent[2*a]; + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::ComputeCellIncrements(int* extent, vtkIdType* increments) +{ + // For structured cells, axes that are empty of cells do not + // contribute to the memory layout of cell data. + vtkIdType nextIncrement = 1; + for(int a=0; a < 3; ++a) + { + if(this->AxesEmpty[a] && extent[2*a+1] == extent[2*a]) + { + increments[a] = 0; + } + else + { + increments[a] = nextIncrement; + nextIncrement *= extent[2*a+1] - extent[2*a]; + } + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLReader::GetStartTuple(int* extent, vtkIdType* increments, + int i, int j, int k) +{ + vtkIdType offset = (i - extent[0]) * increments[0]; + offset += (j - extent[2]) * increments[1]; + offset += (k - extent[4]) * increments[2]; + return offset; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::ReadAttributeIndices(vtkXMLDataElement* eDSA, + vtkDataSetAttributes* dsa) +{ + // Setup attribute indices. + int i; + for(i=0;i < vtkDataSetAttributes::NUM_ATTRIBUTES;++i) + { + const char* attrName = vtkDataSetAttributes::GetAttributeTypeAsString(i); + if(eDSA && eDSA->GetAttribute(attrName)) + { + dsa->SetActiveAttribute(eDSA->GetAttribute(attrName), i); + } + } +} + +//---------------------------------------------------------------------------- +char** vtkXMLReader::CreateStringArray(int numStrings) +{ + char** strings = new char*[numStrings]; + int i; + for(i=0; i < numStrings; ++i) + { + strings[i] = 0; + } + return strings; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::DestroyStringArray(int numStrings, char** strings) +{ + int i; + for(i=0; i < numStrings; ++i) + { + if(strings[i]) + { + delete [] strings[i]; + } + } + delete [] strings; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetDataArraySelections(vtkXMLDataElement* eDSA, + vtkDataArraySelection* sel) +{ + if(!eDSA) + { + sel->SetArrays(0, 0); + return; + } + int numArrays = eDSA->GetNumberOfNestedElements(); + if(!numArrays) + { + sel->SetArrays(0, 0); + return; + } + + for(int i=0;i < numArrays;++i) + { + vtkXMLDataElement* eNested = eDSA->GetNestedElement(i); + const char* name = eNested->GetAttribute("Name"); + if(name) + { + sel->AddArray( name ); + } + else + { + ostrstream ostr_with_warning_C4701; + ostr_with_warning_C4701 << "Array " << i << ends; + sel->AddArray( ostr_with_warning_C4701.str() ); + ostr_with_warning_C4701.rdbuf()->freeze(0); + } + } +} + + +//---------------------------------------------------------------------------- +int vtkXMLReader::SetFieldDataInfo(vtkXMLDataElement *eDSA, + int association, int numTuples, + vtkInformationVector *(&infoVector)) +{ + if (!eDSA) + { + return 1; + } + + int i, j, components, dataType, activeFlag; + const char *name; + char *(attributeName[vtkDataSetAttributes::NUM_ATTRIBUTES]); + vtkInformation *info = NULL; + + for(i = 0; i < vtkDataSetAttributes::NUM_ATTRIBUTES; i++) + { + const char* attrName = vtkDataSetAttributes::GetAttributeTypeAsString(i); + name = eDSA->GetAttribute(attrName); + if (name) + { + attributeName[i] = new char[strlen(name)+1]; + strcpy(attributeName[i], name); + } + else + { + attributeName[i] = NULL; + } + } + + if (!infoVector) + { + infoVector = vtkInformationVector::New(); + } + + // Cycle through each data array + for(i = 0; i < eDSA->GetNumberOfNestedElements(); i++) + { + vtkXMLDataElement* eNested = eDSA->GetNestedElement(i); + + info = vtkInformation::New(); + activeFlag = 0; + info->Set(vtkDataObject::FIELD_ASSOCIATION(), association); + info->Set(vtkDataObject::FIELD_NUMBER_OF_TUPLES(), numTuples); + + name = eNested->GetAttribute( "Name" ); + if (!name) + { + this->InformationError = 1; + break; + } + info->Set(vtkDataObject::FIELD_NAME(), name); + + // Search for matching attribute name + for (j = 0; j < vtkDataSetAttributes::NUM_ATTRIBUTES; j++) + { + if (attributeName[j] && !strcmp(name, attributeName[j])) + { + // set appropriate bit to indicate an active attribute type + activeFlag |= 1 << j; + break; + } + } + + if (!eNested->GetWordTypeAttribute("type", dataType)) + { + this->InformationError = 1; + break; + } + info->Set(vtkDataObject::FIELD_ARRAY_TYPE(), dataType); + + if (eNested->GetScalarAttribute("NumberOfComponents", components)) + { + info->Set(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS(), components); + } + else + { + info->Set(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS(), 1); + } + + info->Set(vtkDataObject::FIELD_ACTIVE_ATTRIBUTE(), activeFlag); + infoVector->Append( info ); + info->Delete(); + } + + for(i = 0; i < vtkDataSetAttributes::NUM_ATTRIBUTES; i++) + { + if (attributeName[i]) + { + delete [] attributeName[i]; + } + } + + if (this->InformationError) + { + info->Delete(); + infoVector->Delete(); + infoVector = NULL; + return 0; + } + + return 1; + } + + +//---------------------------------------------------------------------------- +int vtkXMLReader::PointDataArrayIsEnabled(vtkXMLDataElement* ePDA) +{ + const char* name = ePDA->GetAttribute("Name"); + return (name && this->PointDataArraySelection->ArrayIsEnabled(name)); +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::CellDataArrayIsEnabled(vtkXMLDataElement* eCDA) +{ + const char* name = eCDA->GetAttribute("Name"); + return (name && this->CellDataArraySelection->ArrayIsEnabled(name)); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SelectionModifiedCallback(vtkObject*, unsigned long, + void* clientdata, void*) +{ + static_cast(clientdata)->Modified(); +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::GetNumberOfPointArrays() +{ + return this->PointDataArraySelection->GetNumberOfArrays(); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLReader::GetPointArrayName(int index) +{ + return this->PointDataArraySelection->GetArrayName(index); +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::GetPointArrayStatus(const char* name) +{ + return this->PointDataArraySelection->ArrayIsEnabled(name); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetPointArrayStatus(const char* name, int status) +{ + if(status) + { + this->PointDataArraySelection->EnableArray(name); + } + else + { + this->PointDataArraySelection->DisableArray(name); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::GetNumberOfCellArrays() +{ + return this->CellDataArraySelection->GetNumberOfArrays(); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLReader::GetCellArrayName(int index) +{ + return this->CellDataArraySelection->GetArrayName(index); +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::GetCellArrayStatus(const char* name) +{ + return this->CellDataArraySelection->ArrayIsEnabled(name); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetCellArrayStatus(const char* name, int status) +{ + if(status) + { + this->CellDataArraySelection->EnableArray(name); + } + else + { + this->CellDataArraySelection->DisableArray(name); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::GetProgressRange(float* range) +{ + range[0] = this->ProgressRange[0]; + range[1] = this->ProgressRange[1]; +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetProgressRange(float* range, int curStep, int numSteps) +{ + float stepSize = (range[1] - range[0])/numSteps; + this->ProgressRange[0] = range[0] + stepSize*curStep; + this->ProgressRange[1] = range[0] + stepSize*(curStep+1); + this->UpdateProgressDiscrete(this->ProgressRange[0]); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetProgressRange(float* range, int curStep, + float* fractions) +{ + float width = range[1] - range[0]; + this->ProgressRange[0] = range[0] + fractions[curStep]*width; + this->ProgressRange[1] = range[0] + fractions[curStep+1]*width; + this->UpdateProgressDiscrete(this->ProgressRange[0]); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::UpdateProgressDiscrete(float progress) +{ + if(!this->AbortExecute) + { + // Round progress to nearest 100th. + float rounded = float(int((progress*100)+0.5))/100; + if(this->GetProgress() != rounded) + { + this->UpdateProgress(rounded); + } + } +} + + +//---------------------------------------------------------------------------- +int vtkXMLReader::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // FIXME This piece of code should be rewritten to handle at the same + // time Pieces and TimeSteps. The REQUEST_DATA_NOT_GENERATED should + // ideally be changed during execution, so that allocation still + // happen when needed but can be skipped in demand (when doing + // timesteps) + if(this->NumberOfTimeSteps && + request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_NOT_GENERATED())) + { + vtkInformation* outInfo = outputVector->GetInformationObject(0); + if ( this->CurrentOutput == 0) + { + outInfo->Set(vtkDemandDrivenPipeline::DATA_NOT_GENERATED(), 1); + } + return 1; + } + // END FIXME + + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + // create the output + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT())) + { + return this->RequestDataObject(request, inputVector, outputVector); + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + return this->RequestInformation(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +void vtkXMLReader::SetNumberOfTimeSteps(int num) +{ + if( num && (this->NumberOfTimeSteps != num) ) + { + this->NumberOfTimeSteps = num; + delete[] this->TimeSteps; + // Reallocate a buffer large enough + this->TimeSteps = new int[num]; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLReader::IsTimeStepInArray(int timestep, int* timesteps, int length) +{ + for(int i=0; iSetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); + this->CoordinateElements = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLRectilinearGridReader::~vtkXMLRectilinearGridReader() +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridReader::SetOutput(vtkRectilinearGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkXMLRectilinearGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkXMLRectilinearGridReader::GetOutput(int idx) +{ + return vtkRectilinearGrid::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLRectilinearGridReader::GetDataSetName() +{ + return "RectilinearGrid"; +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridReader::SetOutputExtent(int* extent) +{ + this->GetOutput()->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridReader::SetupPieces(int numPieces) +{ + this->Superclass::SetupPieces(numPieces); + this->CoordinateElements = new vtkXMLDataElement*[numPieces]; + for(int i=0;i < numPieces; ++i) + { + this->CoordinateElements[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridReader::DestroyPieces() +{ + delete [] this->CoordinateElements; + this->CoordinateElements = 0; + this->Superclass::DestroyPieces(); +} + +//---------------------------------------------------------------------------- +int vtkXMLRectilinearGridReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + if(!this->Superclass::ReadPiece(ePiece)) { return 0; } + + // Find the Coordinates element in the piece. + this->CoordinateElements[this->Piece] = 0; + for(int i=0; i < ePiece->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = ePiece->GetNestedElement(i); + if((strcmp(eNested->GetName(), "Coordinates") == 0) + && (eNested->GetNumberOfNestedElements() == 3)) + { + this->CoordinateElements[this->Piece] = eNested; + } + } + + // If there is any volume, we require a Coordinates element. + int* piecePointDimensions = this->PiecePointDimensions + this->Piece*3; + if(!this->CoordinateElements[this->Piece] && + (piecePointDimensions[0] > 0) && + (piecePointDimensions[1] > 0) && + (piecePointDimensions[2] > 0)) + { + vtkErrorMacro("A piece is missing its Coordinates element."); + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + if(!this->CoordinateElements) + { + // Empty volume. + return; + } + + // Allocate the coordinate arrays. + vtkRectilinearGrid* output = this->GetOutput(); + + vtkXMLDataElement* xc = this->CoordinateElements[0]->GetNestedElement(0); + vtkXMLDataElement* yc = this->CoordinateElements[0]->GetNestedElement(1); + vtkXMLDataElement* zc = this->CoordinateElements[0]->GetNestedElement(2); + + // Create the coordinate arrays. + vtkDataArray* x = this->CreateDataArray(xc); + vtkDataArray* y = this->CreateDataArray(yc); + vtkDataArray* z = this->CreateDataArray(zc); + if(x && y && z) + { + x->SetNumberOfTuples(this->PointDimensions[0]); + y->SetNumberOfTuples(this->PointDimensions[1]); + z->SetNumberOfTuples(this->PointDimensions[2]); + output->SetXCoordinates(x); + output->SetYCoordinates(y); + output->SetZCoordinates(z); + x->Delete(); + y->Delete(); + z->Delete(); + } + else + { + if (x) + { + x->Delete(); + } + if (y) + { + y->Delete(); + } + if (z) + { + z->Delete(); + } + this->DataError = 1; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLRectilinearGridReader::ReadPieceData() +{ + // The amount of data read by the superclass's ReadPieceData comes + // from point/cell data (we read point specifications here). + int dims[3] = {0,0,0}; + this->ComputePointDimensions(this->SubExtent, dims); + vtkIdType superclassPieceSize = + (this->NumberOfPointArrays*dims[0]*dims[1]*dims[2]+ + this->NumberOfCellArrays*(dims[0]-1)*(dims[1]-1)*(dims[2]-1)); + + // Total amount of data in this piece comes from point/cell data + // arrays and the point specifications themselves. + vtkIdType totalPieceSize = + superclassPieceSize + dims[0] + dims[1] + dims[2]; + if(totalPieceSize == 0) + { + totalPieceSize = 1; + } + + // Split the progress range based on the approximate fraction of + // data that will be read by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[5] = + { + 0, + float(superclassPieceSize) / totalPieceSize, + (float(superclassPieceSize)+dims[0]) / totalPieceSize, + (float(superclassPieceSize)+dims[1]+dims[2]) / totalPieceSize, + 1 + }; + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass read its data. + if(!this->Superclass::ReadPieceData()) { return 0; } + + int index=this->Piece; + vtkXMLDataElement* xc = this->CoordinateElements[index]->GetNestedElement(0); + vtkXMLDataElement* yc = this->CoordinateElements[index]->GetNestedElement(1); + vtkXMLDataElement* zc = this->CoordinateElements[index]->GetNestedElement(2); + int* pieceExtent = this->PieceExtents + index*6; + vtkRectilinearGrid* output = this->GetOutput(); + int result = 1; + + // Set the range of progress for the X coordinates array. + this->SetProgressRange(progressRange, 1, fractions); + if(result) + { + this->ReadSubCoordinates(pieceExtent, this->UpdateExtent, + this->SubExtent, xc, + output->GetXCoordinates()); + } + + // Set the range of progress for the Y coordinates array. + this->SetProgressRange(progressRange, 2, fractions); + if(result) + { + this->ReadSubCoordinates(pieceExtent+2, this->UpdateExtent+2, + this->SubExtent+2, yc, + output->GetYCoordinates()); + } + + // Set the range of progress for the Z coordinates array. + this->SetProgressRange(progressRange, 3, fractions); + if(result) + { + this->ReadSubCoordinates(pieceExtent+4, this->UpdateExtent+4, + this->SubExtent+4, zc, + output->GetZCoordinates()); + } + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLRectilinearGridReader::ReadSubCoordinates(int* inBounds, + int* outBounds, + int* subBounds, + vtkXMLDataElement* da, + vtkDataArray* array) +{ + unsigned int components = array->GetNumberOfComponents(); + + int destStartIndex = subBounds[0] - outBounds[0]; + int sourceStartIndex = subBounds[0] - inBounds[0]; + int length = subBounds[1] - subBounds[0] + 1; + + return this->ReadData(da, array->GetVoidPointer(destStartIndex*components), + array->GetDataType(), sourceStartIndex, length); +} + + +//---------------------------------------------------------------------------- +int vtkXMLRectilinearGridReader::FillOutputPortInformation(int, vtkInformation *info) + { + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkRectilinearGrid"); + return 1; + } + diff --git a/IO/vtkXMLRectilinearGridReader.h b/IO/vtkXMLRectilinearGridReader.h new file mode 100644 index 0000000..38ea9b4 --- /dev/null +++ b/IO/vtkXMLRectilinearGridReader.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLRectilinearGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLRectilinearGridReader - Read VTK XML RectilinearGrid files. +// .SECTION Description +// vtkXMLRectilinearGridReader reads the VTK XML RectilinearGrid file +// format. One rectilinear grid file can be read to produce one +// output. Streaming is supported. The standard extension for this +// reader's file format is "vtr". This reader is also used to read a +// single piece of the parallel file format. + +// .SECTION See Also +// vtkXMLPRectilinearGridReader + +#ifndef __vtkXMLRectilinearGridReader_h +#define __vtkXMLRectilinearGridReader_h + +#include "vtkXMLStructuredDataReader.h" + +class vtkRectilinearGrid; + +class VTK_IO_EXPORT vtkXMLRectilinearGridReader : public vtkXMLStructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLRectilinearGridReader,vtkXMLStructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLRectilinearGridReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkRectilinearGrid *output); + vtkRectilinearGrid *GetOutput(); + vtkRectilinearGrid *GetOutput(int idx); + +protected: + vtkXMLRectilinearGridReader(); + ~vtkXMLRectilinearGridReader(); + + const char* GetDataSetName(); + void SetOutputExtent(int* extent); + + void SetupPieces(int numPieces); + void DestroyPieces(); + void SetupOutputData(); + int ReadPiece(vtkXMLDataElement* ePiece); + int ReadPieceData(); + int ReadSubCoordinates(int* inBounds, int* outBounds, int* subBounds, + vtkXMLDataElement* da, vtkDataArray* array); + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The elements representing the coordinate arrays for each piece. + vtkXMLDataElement** CoordinateElements; + +private: + vtkXMLRectilinearGridReader(const vtkXMLRectilinearGridReader&); // Not implemented. + void operator=(const vtkXMLRectilinearGridReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLRectilinearGridWriter.cxx b/IO/vtkXMLRectilinearGridWriter.cxx new file mode 100644 index 0000000..ed1c619 --- /dev/null +++ b/IO/vtkXMLRectilinearGridWriter.cxx @@ -0,0 +1,242 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLRectilinearGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLRectilinearGridWriter.h" + +#include "vtkCellData.h" +#include "vtkErrorCode.h" +#include "vtkExtentTranslator.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkRectilinearGrid.h" +#define vtkOffsetsManager_DoNotInclude +#include "vtkOffsetsManagerArray.h" +#undef vtkOffsetsManager_DoNotInclude + +vtkCxxRevisionMacro(vtkXMLRectilinearGridWriter, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkXMLRectilinearGridWriter); + +//---------------------------------------------------------------------------- +vtkXMLRectilinearGridWriter::vtkXMLRectilinearGridWriter() +{ + this->CoordinateOM = new OffsetsManagerArray; +} + +//---------------------------------------------------------------------------- +vtkXMLRectilinearGridWriter::~vtkXMLRectilinearGridWriter() +{ + delete this->CoordinateOM; +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkRectilinearGrid* vtkXMLRectilinearGridWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::GetInputExtent(int* extent) +{ + this->GetInput()->GetExtent(extent); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLRectilinearGridWriter::GetDataSetName() +{ + return "RectilinearGrid"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLRectilinearGridWriter::GetDefaultFileExtension() +{ + return "vtr"; +} + +//---------------------------------------------------------------------------- +vtkDataArray* +vtkXMLRectilinearGridWriter::CreateExactCoordinates(vtkDataArray* a, int xyz) +{ + int inExtent[6]; + int outExtent[6]; + this->GetInput()->GetExtent(inExtent); + this->ExtentTranslator->SetPiece(this->CurrentPiece); + this->ExtentTranslator->PieceToExtent(); + this->ExtentTranslator->GetExtent(outExtent); + int* inBounds = inExtent+xyz*2; + int* outBounds = outExtent+xyz*2; + + if(!a) + { + // There are no coordinates. This can happen with empty input. + return vtkFloatArray::New(); + } + + if((inBounds[0] == outBounds[0]) && (inBounds[1] == outBounds[1])) + { + // Use the entire coordinates array. + a->Register(0); + return a; + } + else + { + // Create a subset of the coordinates array. + int components = a->GetNumberOfComponents(); + int tupleSize = components*this->GetWordTypeSize(a->GetDataType()); + vtkDataArray* b = a->NewInstance(); + b->SetNumberOfComponents(components); + b->SetName(a->GetName()); + int tuples = outBounds[1] - outBounds[0] + 1; + int offset = outBounds[0] - inBounds[0]; + b->SetNumberOfTuples(tuples); + memcpy(b->GetVoidPointer(0), a->GetVoidPointer(offset), tuples*tupleSize); + return b; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::AllocatePositionArrays() +{ + this->Superclass::AllocatePositionArrays(); + + this->CoordinateOM->Allocate(this->NumberOfPieces); +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::DeletePositionArrays() +{ + this->Superclass::DeletePositionArrays(); +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::WriteAppendedPiece(int index, + vtkIndent indent) +{ + this->Superclass::WriteAppendedPiece(index, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteCoordinatesAppended(this->GetInput()->GetXCoordinates(), + this->GetInput()->GetYCoordinates(), + this->GetInput()->GetZCoordinates(), + indent, &this->CoordinateOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::WriteAppendedPieceData(int index) +{ + // Split progress range by the approximate fractions of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteAppendedPieceData(index); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the coordinates arrays. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the coordinates arrays. + this->WriteCoordinatesAppendedData(this->GetInput()->GetXCoordinates(), + this->GetInput()->GetYCoordinates(), + this->GetInput()->GetZCoordinates(), + this->CurrentTimeIndex, + &this->CoordinateOM->GetPiece(index)); + this->CoordinateOM->GetPiece(index).Allocate(0); //mark it invalid +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::WriteInlinePiece(vtkIndent indent) +{ + // Split progress range by the approximate fractions of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteInlinePiece(indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the coordinates arrays. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the coordinates arrays. + this->WriteCoordinatesInline(this->GetInput()->GetXCoordinates(), + this->GetInput()->GetYCoordinates(), + this->GetInput()->GetZCoordinates(), + indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLRectilinearGridWriter::CalculateSuperclassFraction(float* fractions) +{ + int extent[6]; + this->ExtentTranslator->SetPiece(this->CurrentPiece); + this->ExtentTranslator->PieceToExtent(); + this->ExtentTranslator->GetExtent(extent); + int dims[3] = {extent[1]-extent[0]+1, + extent[3]-extent[2]+1, + extent[5]-extent[4]+1}; + + // The amount of data written by the superclass comes from the + // point/cell data arrays. + vtkIdType superclassPieceSize = + (this->GetInput()->GetPointData()->GetNumberOfArrays()*dims[0]*dims[1]*dims[2]+ + this->GetInput()->GetCellData()->GetNumberOfArrays()*(dims[0]-1)*(dims[1]-1)*(dims[2]-1)); + + // The total data written includes the coordinate arrays. + vtkIdType totalPieceSize = + superclassPieceSize + dims[0] + dims[1] + dims[2]; + if(totalPieceSize == 0) + { + totalPieceSize = 1; + } + fractions[0] = 0; + fractions[1] = fractions[0] + float(superclassPieceSize)/totalPieceSize; + fractions[2] = 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLRectilinearGridWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} diff --git a/IO/vtkXMLRectilinearGridWriter.h b/IO/vtkXMLRectilinearGridWriter.h new file mode 100644 index 0000000..6ddd6cb --- /dev/null +++ b/IO/vtkXMLRectilinearGridWriter.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLRectilinearGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLRectilinearGridWriter - Write VTK XML RectilinearGrid files. +// .SECTION Description +// vtkXMLRectilinearGridWriter writes the VTK XML RectilinearGrid +// file format. One rectilinear grid input can be written into one +// file in any number of streamed pieces. The standard extension for +// this writer's file format is "vtr". This writer is also used to +// write a single piece of the parallel file format. + +// .SECTION See Also +// vtkXMLPRectilinearGridWriter + +#ifndef __vtkXMLRectilinearGridWriter_h +#define __vtkXMLRectilinearGridWriter_h + +#include "vtkXMLStructuredDataWriter.h" + +class vtkRectilinearGrid; + +class VTK_IO_EXPORT vtkXMLRectilinearGridWriter : public vtkXMLStructuredDataWriter +{ +public: + static vtkXMLRectilinearGridWriter* New(); + vtkTypeRevisionMacro(vtkXMLRectilinearGridWriter,vtkXMLStructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkRectilinearGrid* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLRectilinearGridWriter(); + ~vtkXMLRectilinearGridWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + int WriteAppendedMode(vtkIndent indent); + void WriteAppendedPiece(int index, vtkIndent indent); + void WriteAppendedPieceData(int index); + void WriteInlinePiece(vtkIndent indent); + void GetInputExtent(int* extent); + const char* GetDataSetName(); + vtkDataArray* CreateExactCoordinates(vtkDataArray* a, int xyz); + void CalculateSuperclassFraction(float* fractions); + + // Coordinate array appended data positions. + OffsetsManagerArray *CoordinateOM; + + virtual void AllocatePositionArrays(); + virtual void DeletePositionArrays(); + +private: + vtkXMLRectilinearGridWriter(const vtkXMLRectilinearGridWriter&); // Not implemented. + void operator=(const vtkXMLRectilinearGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLStructuredDataReader.cxx b/IO/vtkXMLStructuredDataReader.cxx new file mode 100644 index 0000000..14860b4 --- /dev/null +++ b/IO/vtkXMLStructuredDataReader.cxx @@ -0,0 +1,491 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLStructuredDataReader.h" + +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLDataParser.h" + +vtkCxxRevisionMacro(vtkXMLStructuredDataReader, "$Revision: 1.20 $"); + +//---------------------------------------------------------------------------- +vtkXMLStructuredDataReader::vtkXMLStructuredDataReader() +{ + this->PieceExtents = 0; + this->PiecePointDimensions = 0; + this->PiecePointIncrements = 0; + this->PieceCellDimensions = 0; + this->PieceCellIncrements = 0; + this->WholeSlices = 1; + + // Initialize these in case someone calls GetNumberOfPoints or + // GetNumberOfCells before UpdateInformation is called. + this->PointDimensions[0] = 0; + this->PointDimensions[1] = 0; + this->PointDimensions[2] = 0; + this->CellDimensions[0] = 0; + this->CellDimensions[1] = 0; + this->CellDimensions[2] = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLStructuredDataReader::~vtkXMLStructuredDataReader() +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "WholeSlices: " << this->WholeSlices << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary) +{ + // Get the whole extent attribute. + int extent[6]; + if(ePrimary->GetVectorAttribute("WholeExtent", 6, extent) == 6) + { + // Set the output's whole extent. + this->GetOutputAsDataSet(0)->SetWholeExtent(extent); + + // Check each axis to see if it has cells. + for(int a=0; a < 3; ++a) + { + this->AxesEmpty[a] = (extent[2*a+1] > extent[2*a])? 0 : 1; + } + } + else + { + vtkErrorMacro(<< this->GetDataSetName() << " element has no WholeExtent."); + return 0; + } + + return this->Superclass::ReadPrimaryElement(ePrimary); +} + +//---------------------------------------------------------------------------- +void +vtkXMLStructuredDataReader::CopyOutputInformation(vtkInformation* outInfo, + int port) +{ + // Let the superclass copy information first. + this->Superclass::CopyOutputInformation(outInfo, port); + + // All structured data has a whole extent. + vtkInformation* localInfo = this->GetExecutive()->GetOutputInformation(port); + if(localInfo->Has(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())) + { + outInfo->CopyEntry(localInfo, + vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataReader::SetupEmptyOutput() +{ + // Special extent to indicate no input. + this->GetOutputAsDataSet(0)->SetWholeExtent(0, -1, 0, -1, 0, -1); + this->GetOutputAsDataSet(0)->SetUpdateExtent(0, -1, 0, -1, 0, -1); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataReader::SetupPieces(int numPieces) +{ + this->Superclass::SetupPieces(numPieces); + this->PieceExtents = new int[numPieces*6]; + this->PiecePointDimensions = new int[numPieces*3]; + this->PiecePointIncrements = new vtkIdType[numPieces*3]; + this->PieceCellDimensions = new int[numPieces*3]; + this->PieceCellIncrements = new vtkIdType[numPieces*3]; + int i; + for(i=0; i < numPieces; ++i) + { + int* extent = this->PieceExtents + i*6; + extent[0]=0; extent[1]=-1; + extent[2]=0; extent[3]=-1; + extent[4]=0; extent[5]=-1; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataReader::DestroyPieces() +{ + delete [] this->PieceExtents; + delete [] this->PiecePointDimensions; + delete [] this->PiecePointIncrements; + delete [] this->PieceCellDimensions; + delete [] this->PieceCellIncrements; + this->PieceExtents = 0; + this->PiecePointDimensions = 0; + this->PiecePointIncrements = 0; + this->PieceCellDimensions = 0; + this->PieceCellIncrements = 0; + this->Superclass::DestroyPieces(); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLStructuredDataReader::GetNumberOfPoints() +{ + return (this->PointDimensions[0]* + this->PointDimensions[1]* + this->PointDimensions[2]); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLStructuredDataReader::GetNumberOfCells() +{ + return (this->CellDimensions[0]* + this->CellDimensions[1]* + this->CellDimensions[2]); +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + if(!this->Superclass::ReadPiece(ePiece)) + { + return 0; + } + int* pieceExtent = this->PieceExtents + this->Piece*6; + + // Read the extent of the piece. + if(strcmp(ePiece->GetName(), "Piece") == 0) + { + if(!ePiece->GetAttribute("Extent")) + { + vtkErrorMacro("Piece has no extent."); + } + if(ePiece->GetVectorAttribute("Extent", 6, pieceExtent) < 6) + { + vtkErrorMacro("Extent attribute is not 6 integers."); + return 0; + } + } + else if(ePiece->GetVectorAttribute("WholeExtent", 6, pieceExtent) < 6) + { + vtkErrorMacro("WholeExtent attribute is not 6 integers."); + return 0; + } + + // Compute the dimensions and increments for this piece's extent. + int* piecePointDimensions = this->PiecePointDimensions + this->Piece*3; + vtkIdType* piecePointIncrements = this->PiecePointIncrements + this->Piece*3; + int* pieceCellDimensions = this->PieceCellDimensions + this->Piece*3; + vtkIdType* pieceCellIncrements = this->PieceCellIncrements + this->Piece*3; + this->ComputePointDimensions(pieceExtent, piecePointDimensions); + this->ComputePointIncrements(pieceExtent, piecePointIncrements); + this->ComputeCellDimensions(pieceExtent, pieceCellDimensions); + this->ComputeCellIncrements(pieceExtent, pieceCellIncrements); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataReader::ReadXMLData() +{ + // Get the requested Update Extent. + this->GetOutputAsDataSet(0)->GetUpdateExtent(this->UpdateExtent); + + vtkDebugMacro("Updating extent " + << this->UpdateExtent[0] << " " << this->UpdateExtent[1] << " " + << this->UpdateExtent[2] << " " << this->UpdateExtent[3] << " " + << this->UpdateExtent[4] << " " << this->UpdateExtent[5] + << "\n"); + + // Prepare increments for the update extent. + this->ComputePointDimensions(this->UpdateExtent, this->PointDimensions); + this->ComputePointIncrements(this->UpdateExtent, this->PointIncrements); + this->ComputeCellDimensions(this->UpdateExtent, this->CellDimensions); + this->ComputeCellIncrements(this->UpdateExtent, this->CellIncrements); + + // Let superclasses read data. This also allocates output data. + this->Superclass::ReadXMLData(); + + // Split current progress range based on fraction contributed by + // each piece. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + // Calculate the cumulative fraction of data contributed by each + // piece (for progress). + float* fractions = new float[this->NumberOfPieces+1]; + int i; + fractions[0] = 0; + for(i=0;i < this->NumberOfPieces;++i) + { + int* pieceExtent = this->PieceExtents + i*6; + int pieceDims[3] = {0,0,0}; + // Intersect the extents to get the part we need to read. + if(this->IntersectExtents(pieceExtent, this->UpdateExtent, + this->SubExtent)) + { + this->ComputePointDimensions(this->SubExtent, pieceDims); + fractions[i+1] = fractions[i] + pieceDims[0]*pieceDims[1]*pieceDims[2]; + } + else + { + fractions[i+1] = 0; + } + } + if(fractions[this->NumberOfPieces] == 0) + { + fractions[this->NumberOfPieces] = 1; + } + for(i=1;i <= this->NumberOfPieces;++i) + { + fractions[i] = fractions[i] / fractions[this->NumberOfPieces]; + } + + // Read the data needed from each piece. + for(i=0;(i < this->NumberOfPieces && !this->AbortExecute && + !this->DataError);++i) + { + // Set the range of progress for this piece. + this->SetProgressRange(progressRange, i, fractions); + + // Intersect the extents to get the part we need to read. + int* pieceExtent = this->PieceExtents + i*6; + if(this->IntersectExtents(pieceExtent, this->UpdateExtent, + this->SubExtent)) + { + vtkDebugMacro("Reading extent " + << this->SubExtent[0] << " " << this->SubExtent[1] << " " + << this->SubExtent[2] << " " << this->SubExtent[3] << " " + << this->SubExtent[4] << " " << this->SubExtent[5] + << " from piece " << i); + + this->ComputePointDimensions(this->SubExtent, this->SubPointDimensions); + this->ComputeCellDimensions(this->SubExtent, this->SubCellDimensions); + + // Read the data from this piece. + if(!this->ReadPieceData(i)) + { + // An error occurred while reading the piece. + this->DataError = 1; + } + } + } + + delete [] fractions; + + // We filled the exact update extent in the output. + this->SetOutputExtent(this->UpdateExtent); +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataReader::ReadArrayForPoints(vtkXMLDataElement* da, + vtkDataArray* outArray) +{ + int* pieceExtent = this->PieceExtents + this->Piece*6; + int* piecePointDimensions = this->PiecePointDimensions + this->Piece*3; + vtkIdType* piecePointIncrements = this->PiecePointIncrements + this->Piece*3; + if(!this->ReadSubExtent(pieceExtent, piecePointDimensions, + piecePointIncrements, this->UpdateExtent, + this->PointDimensions, this->PointIncrements, + this->SubExtent, this->SubPointDimensions, + da, outArray)) + { + vtkErrorMacro("Error reading extent " + << this->SubExtent[0] << " " << this->SubExtent[1] << " " + << this->SubExtent[2] << " " << this->SubExtent[3] << " " + << this->SubExtent[4] << " " << this->SubExtent[5] + << " from piece " << this->Piece); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataReader::ReadArrayForCells(vtkXMLDataElement* da, + vtkDataArray* outArray) +{ + int* pieceExtent = this->PieceExtents + this->Piece*6; + int* pieceCellDimensions = this->PieceCellDimensions + this->Piece*3; + vtkIdType* pieceCellIncrements = this->PieceCellIncrements + this->Piece*3; + if(!this->ReadSubExtent(pieceExtent, pieceCellDimensions, + pieceCellIncrements, this->UpdateExtent, + this->CellDimensions, this->CellIncrements, + this->SubExtent, this->SubCellDimensions, + da, outArray)) + { + vtkErrorMacro("Error reading extent " + << this->SubExtent[0] << " " << this->SubExtent[1] << " " + << this->SubExtent[2] << " " << this->SubExtent[3] << " " + << this->SubExtent[4] << " " << this->SubExtent[5] + << " from piece " << this->Piece); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int +vtkXMLStructuredDataReader +::ReadSubExtent(int* inExtent, int* inDimensions, vtkIdType* inIncrements, + int* outExtent, int* outDimensions, vtkIdType* outIncrements, + int* subExtent, int* subDimensions, vtkXMLDataElement* da, + vtkDataArray* array) +{ + int components = array->GetNumberOfComponents(); + + if((inDimensions[0] == outDimensions[0]) && + (inDimensions[1] == outDimensions[1])) + { + if(inDimensions[2] == outDimensions[2]) + { + // Read the whole volume at once. This fills the array's entire + // progress range. + vtkIdType volumeTuples = + (inDimensions[0]*inDimensions[1]*inDimensions[2]); + if(!this->ReadData(da, array->GetVoidPointer(0), array->GetDataType(), + 0, volumeTuples*components)) + { + return 0; + } + } + else + { + // Read an entire slice at a time. Split progress range by + // slice. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + vtkIdType sliceTuples = inDimensions[0]*inDimensions[1]; + int k; + for(k=0;k < subDimensions[2] && !this->AbortExecute;++k) + { + // Calculate the starting tuples for source and destination. + vtkIdType sourceTuple = + this->GetStartTuple(inExtent, inIncrements, + subExtent[0], subExtent[2], subExtent[4]+k); + vtkIdType destTuple = + this->GetStartTuple(outExtent, outIncrements, + subExtent[0], subExtent[2], subExtent[4]+k); + + // Set the range of progress for this slice. + this->SetProgressRange(progressRange, k, subDimensions[2]); + + // Read the slice. + if(!this->ReadData(da, array->GetVoidPointer(destTuple*components), + array->GetDataType(), sourceTuple*components, + sliceTuples*components)) + { + return 0; + } + } + } + } + else + { + if(!this->WholeSlices) + { + // Read a row at a time. Split progress range by row. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + vtkIdType rowTuples = subDimensions[0]; + int j,k; + for(k=0;k < subDimensions[2] && !this->AbortExecute;++k) + { + for(j=0;j < subDimensions[1] && !this->AbortExecute;++j) + { + // Calculate the starting tuples for source and destination. + vtkIdType sourceTuple = + this->GetStartTuple(inExtent, inIncrements, + subExtent[0], subExtent[2]+j, subExtent[4]+k); + vtkIdType destTuple = + this->GetStartTuple(outExtent, outIncrements, + subExtent[0], subExtent[2]+j, subExtent[4]+k); + + // Set the range of progress for this row. + this->SetProgressRange(progressRange, subDimensions[1]*k+j, + subDimensions[2]*subDimensions[1]); + + // Read the row. + if(!this->ReadData(da, array->GetVoidPointer(destTuple*components), + array->GetDataType(), sourceTuple*components, + rowTuples*components)) + { + return 0; + } + } + } + } + else + { + // Read in each slice and copy the needed rows from it. Split + // progress range by slice. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + vtkIdType rowTuples = subDimensions[0]; + vtkIdType partialSliceTuples = inDimensions[0]*subDimensions[1]; + int tupleSize = components*array->GetDataTypeSize(); + vtkDataArray* temp = array->NewInstance(); + temp->SetNumberOfComponents(array->GetNumberOfComponents()); + temp->SetNumberOfTuples(partialSliceTuples); + int k; + for(k=0;k < subDimensions[2] && !this->AbortExecute;++k) + { + // Calculate the starting tuple from the input. + vtkIdType inTuple = + this->GetStartTuple(inExtent, inIncrements, + inExtent[0], subExtent[2], subExtent[4]+k); + int memExtent[6]; + memExtent[0] = inExtent[0]; + memExtent[1] = inExtent[1]; + memExtent[2] = subExtent[2]; + memExtent[3] = subExtent[3]; + memExtent[4] = subExtent[4]+k; + memExtent[5] = subExtent[4]+k; + + // Set the range of progress for this slice. + this->SetProgressRange(progressRange, k, subDimensions[2]); + + // Read the slice. + if(!this->ReadData(da, temp->GetVoidPointer(0), temp->GetDataType(), + inTuple*components, + partialSliceTuples*components)) + { + temp->Delete(); + return 0; + } + + // Copy the portion of the slice we need. + int j; + for(j=0;j < subDimensions[1];++j) + { + vtkIdType sourceTuple = + this->GetStartTuple(memExtent, inIncrements, + subExtent[0], subExtent[2]+j, subExtent[4]+k); + vtkIdType destTuple = + this->GetStartTuple(outExtent, outIncrements, + subExtent[0], subExtent[2]+j, subExtent[4]+k); + memcpy(array->GetVoidPointer(destTuple*components), + temp->GetVoidPointer(sourceTuple*components), + tupleSize*rowTuples); + } + } + temp->Delete(); + } + } + return 1; +} diff --git a/IO/vtkXMLStructuredDataReader.h b/IO/vtkXMLStructuredDataReader.h new file mode 100644 index 0000000..f93dcf8 --- /dev/null +++ b/IO/vtkXMLStructuredDataReader.h @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLStructuredDataReader - Superclass for structured data XML readers. +// .SECTION Description +// vtkXMLStructuredDataReader provides functionality common to all +// structured data format readers. + +// .SECTION See Also +// vtkXMLImageDataReader vtkXMLStructuredGridReader +// vtkXMLRectilinearGridReader + +#ifndef __vtkXMLStructuredDataReader_h +#define __vtkXMLStructuredDataReader_h + +#include "vtkXMLDataReader.h" + + +class VTK_IO_EXPORT vtkXMLStructuredDataReader : public vtkXMLDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLStructuredDataReader,vtkXMLDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the number of points in the output. + virtual vtkIdType GetNumberOfPoints(); + + // Description: + // Get the number of cells in the output. + virtual vtkIdType GetNumberOfCells(); + + // Description: + // Get/Set whether the reader gets a whole slice from disk when only + // a rectangle inside it is needed. This mode reads more data than + // necessary, but prevents many short reads from interacting poorly + // with the compression and encoding schemes. + vtkSetMacro(WholeSlices, int); + vtkGetMacro(WholeSlices, int); + vtkBooleanMacro(WholeSlices, int); + + // Description: + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); +protected: + vtkXMLStructuredDataReader(); + ~vtkXMLStructuredDataReader(); + + virtual void SetOutputExtent(int* extent)=0; + int ReadPrimaryElement(vtkXMLDataElement* ePrimary); + + // Pipeline execute data driver. Called by vtkXMLReader. + void ReadXMLData(); + + // Internal representation of pieces in the file that may have come + // from a streamed write. + int* PieceExtents; + int* PiecePointDimensions; + vtkIdType* PiecePointIncrements; + int* PieceCellDimensions; + vtkIdType* PieceCellIncrements; + + // Whether to read in whole slices mode. + int WholeSlices; + + // The update extent and corresponding increments and dimensions. + int UpdateExtent[6]; + int PointDimensions[3]; + int CellDimensions[3]; + vtkIdType PointIncrements[3]; + vtkIdType CellIncrements[3]; + + // The extent currently being read. + int SubExtent[6]; + int SubPointDimensions[3]; + int SubCellDimensions[3]; + + // Override methods from superclass. + void SetupEmptyOutput(); + void SetupPieces(int numPieces); + void DestroyPieces(); + int ReadArrayForPoints(vtkXMLDataElement* da, vtkDataArray* outArray); + int ReadArrayForCells(vtkXMLDataElement* da, vtkDataArray* outArray); + + // Internal utility methods. + int ReadPiece(vtkXMLDataElement* ePiece); + int ReadSubExtent(int* inExtent, int* inDimensions, vtkIdType* inIncrements, + int* outExtent,int* outDimensions,vtkIdType* outIncrements, + int* subExtent, int* subDimensions, vtkXMLDataElement* da, + vtkDataArray* array); + +private: + vtkXMLStructuredDataReader(const vtkXMLStructuredDataReader&); // Not implemented. + void operator=(const vtkXMLStructuredDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLStructuredDataWriter.cxx b/IO/vtkXMLStructuredDataWriter.cxx new file mode 100644 index 0000000..6304c2d --- /dev/null +++ b/IO/vtkXMLStructuredDataWriter.cxx @@ -0,0 +1,709 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLStructuredDataWriter.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDataCompressor.h" +#include "vtkDataSet.h" +#include "vtkErrorCode.h" +#include "vtkExtentTranslator.h" +#include "vtkInformation.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkInformationVector.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#define vtkOffsetsManager_DoNotInclude +#include "vtkOffsetsManagerArray.h" +#undef vtkOffsetsManager_DoNotInclude + +vtkCxxRevisionMacro(vtkXMLStructuredDataWriter, "$Revision: 1.20 $"); +vtkCxxSetObjectMacro(vtkXMLStructuredDataWriter, ExtentTranslator, + vtkExtentTranslator); + +//---------------------------------------------------------------------------- +vtkXMLStructuredDataWriter::vtkXMLStructuredDataWriter() +{ + this->ExtentTranslator = vtkExtentTranslator::New(); + this->NumberOfPieces = 1; + this->WriteExtent[0] = 0; this->WriteExtent[1] = -1; + this->WriteExtent[2] = 0; this->WriteExtent[3] = -1; + this->WriteExtent[4] = 0; this->WriteExtent[5] = -1; + this->InternalWriteExtent[0] = 0; this->InternalWriteExtent[1] = -1; + this->InternalWriteExtent[2] = 0; this->InternalWriteExtent[3] = -1; + this->InternalWriteExtent[4] = 0; this->InternalWriteExtent[5] = -1; + + this->CurrentPiece = 0; + this->ProgressFractions = 0; + this->FieldDataOM->Allocate(0); + this->PointDataOM = new OffsetsManagerArray; + this->CellDataOM = new OffsetsManagerArray; +} + +//---------------------------------------------------------------------------- +vtkXMLStructuredDataWriter::~vtkXMLStructuredDataWriter() +{ + this->SetExtentTranslator(0); + delete[] this->ProgressFractions; + delete this->PointDataOM; + delete this->CellDataOM; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "WriteExtent: " + << this->WriteExtent[0] << " " << this->WriteExtent[1] << " " + << this->WriteExtent[2] << " " << this->WriteExtent[3] << " " + << this->WriteExtent[4] << " " << this->WriteExtent[5] << "\n"; + os << indent << "InternalWriteExtent: " + << this->InternalWriteExtent[0] << " " + << this->InternalWriteExtent[1] << " " + << this->InternalWriteExtent[2] << " " + << this->InternalWriteExtent[3] << " " + << this->InternalWriteExtent[4] << " " + << this->InternalWriteExtent[5] << "\n"; + if(this->ExtentTranslator) + { + os << indent << "ExtentTranslator: " << this->ExtentTranslator << "\n"; + } + else + { + os << indent << "ExtentTranslator: (none)\n"; + } + os << indent << "NumberOfPieces" << this->NumberOfPieces << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::SetInputUpdateExtent(int piece) +{ + this->ExtentTranslator->SetPiece(piece); + this->ExtentTranslator->PieceToExtent(); + + vtkInformation* inInfo = + this->GetExecutive()->GetInputInformation(0, 0); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + this->ExtentTranslator->GetExtent(), + 6); +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataWriter::ProcessRequest( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + // Prepare the extent translator to create the set of pieces. + this->SetupExtentTranslator(); + this->SetInputUpdateExtent(this->CurrentPiece); + + return 1; + } + + // generate the data + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->SetErrorCode(vtkErrorCode::NoError); + + if(!this->Stream && !this->FileName) + { + this->SetErrorCode(vtkErrorCode::NoFileNameError); + vtkErrorMacro("The FileName or Stream must be set first."); + return 0; + } + + // We are just starting to write. Do not call + // UpdateProgressDiscrete because we want a 0 progress callback the + // first time. + this->UpdateProgress(0); + + // Initialize progress range to entire 0..1 range. + float wholeProgressRange[2] = {0,1}; + this->SetProgressRange(wholeProgressRange, 0, 1); + + int result = 1; + if (this->CurrentPiece == 0 && this->CurrentTimeIndex == 0 ) + { + if (!this->OpenFile()) + { + return 0; + } + // Write the file. + if (!this->StartFile()) + { + return 0; + } + + if (!this->WriteHeader()) + { + return 0; + } + + this->CurrentTimeIndex = 0; + if( this->DataMode == vtkXMLWriter::Appended && this->FieldDataOM->GetNumberOfElements()) + { + // Write the field data arrays. + this->WriteFieldDataAppendedData(this->GetInput()->GetFieldData(), + this->CurrentTimeIndex, this->FieldDataOM); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + } + } + + if( !(this->UserContinueExecuting == 0)) //if user ask to stop do not try to write a piece + { + result = this->WriteAPiece(); + } + + // Tell the pipeline to start looping. + if (this->CurrentPiece == 0) + { + request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); + } + this->CurrentPiece++; + + if (this->CurrentPiece == this->NumberOfPieces) + { + request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); + this->CurrentPiece = 0; + // We are done writting all the pieces, lets loop over time now: + this->CurrentTimeIndex++; + + if( this->UserContinueExecuting != 1) + { + if (!this->WriteFooter()) + { + return 0; + } + + if (!this->EndFile()) + { + return 0; + } + + this->CloseFile(); + this->CurrentTimeIndex = 0; // Reset + } + } + + // We have finished writing. + this->UpdateProgressDiscrete(1); + return result; + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::AllocatePositionArrays() +{ + // Prepare storage for the point and cell data array appended data + // offsets for each piece. + this->PointDataOM->Allocate(this->NumberOfPieces); + this->CellDataOM->Allocate(this->NumberOfPieces); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::DeletePositionArrays() +{ +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataWriter::WriteHeader() +{ + vtkIndent indent = vtkIndent().GetNextIndent(); + + ostream& os = *(this->Stream); + + if(!this->WritePrimaryElement(os, indent)) + { + return 0; + } + + this->WriteFieldData(indent.GetNextIndent()); + + if(this->DataMode == vtkXMLWriter::Appended) + { + vtkIndent nextIndent = indent.GetNextIndent(); + + this->AllocatePositionArrays(); + + int extent[6]; + // Loop over each piece and write its structure. + int i; + for(i=0; i < this->NumberOfPieces; ++i) + { + // Update the piece's extent. + this->ExtentTranslator->SetPiece(i); + this->ExtentTranslator->PieceToExtent(); + this->ExtentTranslator->GetExtent(extent); + + os << nextIndent << "WriteVectorAttribute("Extent", 6, extent); + os << ">\n"; + + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + + this->WriteAppendedPiece(i, nextIndent.GetNextIndent()); + + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + // Close the piece's element. + os << nextIndent << "\n"; + } + + // Close the primary element. + os << indent << "GetDataSetName() << ">\n"; + + os.flush(); + if (os.fail()) + { + this->DeletePositionArrays(); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + + this->StartAppendedData(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + } + + // Split progress of the data write by the fraction contributed by + // each piece. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + this->ProgressFractions = new float[this->NumberOfPieces+1]; + this->CalculatePieceFractions(this->ProgressFractions); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataWriter::WriteAPiece() +{ + vtkIndent indent = vtkIndent().GetNextIndent(); + int result = 1; + + if(this->DataMode == vtkXMLWriter::Appended) + { + vtkDataSet* input = this->GetInputAsDataSet(); + + // Make sure input is valid. + if(input->CheckAttributes() == 0) + { + this->WriteAppendedPieceData(this->CurrentPiece); + + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + } + else + { + vtkErrorMacro("Input is invalid for piece " + << this->CurrentPiece + << ". Aborting."); + result = 0; + } + } + else + { + this->WriteInlineMode(indent); + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataWriter::WriteFooter() +{ + vtkIndent indent = vtkIndent().GetNextIndent(); + + ostream& os = *(this->Stream); + + if(this->DataMode == vtkXMLWriter::Appended) + { + this->DeletePositionArrays(); + this->EndAppendedData(); + } + else + { + // Close the primary element. + os << indent << "GetDataSetName() << ">\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } + } + + delete[] this->ProgressFractions; + this->ProgressFractions = 0; + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredDataWriter::WriteInlineMode(vtkIndent indent) +{ + vtkDataSet* input = this->GetInputAsDataSet(); + ostream& os = *(this->Stream); + + int extent[6]; + vtkInformation* inInfo = this->GetExecutive()->GetInputInformation(0, 0); + inInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent); + + // Split progress of the data write by the fraction contributed by + // each piece. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + // Write each piece's XML and data. + int result = 1; + + // Set the progress range for this piece. + this->SetProgressRange(progressRange, this->CurrentPiece, this->ProgressFractions); + + // Make sure input is valid. + if(input->CheckAttributes() == 0) + { + os << indent << "WriteVectorAttribute("Extent", 6, extent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + os << ">\n"; + + this->WriteInlinePiece(indent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + os << indent << "\n"; + } + else + { + vtkErrorMacro("Input is invalid for piece " << this->CurrentPiece << ". Aborting."); + result = 0; + } + + return result; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::SetupExtentTranslator() +{ + vtkDataSet* input = this->GetInputAsDataSet(); + + // If no write extent has been set, use the whole extent. + if((this->WriteExtent[0] == 0) && (this->WriteExtent[1] == -1) && + (this->WriteExtent[2] == 0) && (this->WriteExtent[3] == -1) && + (this->WriteExtent[4] == 0) && (this->WriteExtent[5] == -1)) + { + this->SetInternalWriteExtent(input->GetWholeExtent()); + } + else + { + this->SetInternalWriteExtent(this->WriteExtent); + } + + // Our WriteExtent becomes the WholeExtent of the file. + this->ExtentTranslator->SetWholeExtent(this->InternalWriteExtent); + this->ExtentTranslator->SetNumberOfPieces(this->NumberOfPieces); + + vtkDebugMacro("Writing Extent: " + << this->InternalWriteExtent[0] << " " + << this->InternalWriteExtent[1] << " " + << this->InternalWriteExtent[2] << " " + << this->InternalWriteExtent[3] << " " + << this->InternalWriteExtent[4] << " " + << this->InternalWriteExtent[5] << " in " + << this->NumberOfPieces << " pieces."); +} + +//---------------------------------------------------------------------------- +vtkDataArray* +vtkXMLStructuredDataWriter +::CreateExactExtent(vtkDataArray* array, int* inExtent, int* outExtent, + int isPoint) +{ + int outDimensions[3]; + outDimensions[0] = outExtent[1]-outExtent[0]+isPoint; + outDimensions[1] = outExtent[3]-outExtent[2]+isPoint; + outDimensions[2] = outExtent[5]-outExtent[4]+isPoint; + + int inDimensions[3]; + inDimensions[0] = inExtent[1]-inExtent[0]+isPoint; + inDimensions[1] = inExtent[3]-inExtent[2]+isPoint; + inDimensions[2] = inExtent[5]-inExtent[4]+isPoint; + + if((inDimensions[0] == outDimensions[0]) && + (inDimensions[1] == outDimensions[1]) && + (inDimensions[2] == outDimensions[2])) + { + array->Register(0); + return array; + } + + int tupleSize = (array->GetDataTypeSize() * + array->GetNumberOfComponents()); + vtkIdType rowTuples = outDimensions[0]; + vtkIdType sliceTuples = rowTuples*outDimensions[1]; + vtkIdType volumeTuples = sliceTuples*outDimensions[2]; + + vtkIdType inIncrements[3]; + inIncrements[0] = 1; + inIncrements[1] = inDimensions[0]*inIncrements[0]; + inIncrements[2] = inDimensions[1]*inIncrements[1]; + + vtkIdType outIncrements[3]; + outIncrements[0] = 1; + outIncrements[1] = outDimensions[0]*outIncrements[0]; + outIncrements[2] = outDimensions[1]*outIncrements[1]; + + vtkDataArray* newArray = array->NewInstance(); + newArray->SetName(array->GetName()); + newArray->SetNumberOfComponents(array->GetNumberOfComponents()); + newArray->SetNumberOfTuples(volumeTuples); + int components = newArray->GetNumberOfComponents(); + + if((inDimensions[0] == outDimensions[0]) && + (inDimensions[1] == outDimensions[1])) + { + // Copy an entire slice at a time. + int k; + for(k=0;k < outDimensions[2];++k) + { + vtkIdType sourceTuple = + this->GetStartTuple(inExtent, inIncrements, + outExtent[0], outExtent[2], outExtent[4]+k); + vtkIdType destTuple = + this->GetStartTuple(outExtent, outIncrements, + outExtent[0], outExtent[2], outExtent[4]+k); + memcpy(newArray->GetVoidPointer(destTuple*components), + array->GetVoidPointer(sourceTuple*components), + sliceTuples*tupleSize); + } + } + else + { + // Copy a row at a time. + int j, k; + for(k=0;k < outDimensions[2];++k) + { + for(j=0;j < outDimensions[1];++j) + { + vtkIdType sourceTuple = + this->GetStartTuple(inExtent, inIncrements, + outExtent[0], outExtent[2]+j, outExtent[4]+k); + vtkIdType destTuple = + this->GetStartTuple(outExtent, outIncrements, + outExtent[0], outExtent[2]+j, outExtent[4]+k); + memcpy(newArray->GetVoidPointer(destTuple*components), + array->GetVoidPointer(sourceTuple*components), + rowTuples*tupleSize); + } + } + } + + return newArray; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::WritePrimaryElementAttributes(ostream &os, + vtkIndent indent) +{ + this->Superclass::WritePrimaryElementAttributes(os, indent); + + this->WriteVectorAttribute("WholeExtent", 6, this->InternalWriteExtent); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::WriteAppendedPiece(int index, + vtkIndent indent) +{ + // Write the point data and cell data arrays. + vtkDataSet* input = this->GetInputAsDataSet(); + this->WritePointDataAppended(input->GetPointData(), indent, + &this->PointDataOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->WriteCellDataAppended(input->GetCellData(), indent, + &this->CellDataOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::WriteAppendedPieceData(int index) +{ + // Write the point data and cell data arrays. + vtkDataSet* input = this->GetInputAsDataSet(); + + // Split progress between point data and cell data arrays. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int pdArrays = input->GetPointData()->GetNumberOfArrays(); + int cdArrays = input->GetCellData()->GetNumberOfArrays(); + int total = (pdArrays+cdArrays)? (pdArrays+cdArrays):1; + float fractions[3] = + { + 0, + float(pdArrays)/total, + 1 + }; + + // Set the range of progress for the point data arrays. + this->SetProgressRange(progressRange, 0, fractions); + this->WritePointDataAppendedData(input->GetPointData(), this->CurrentTimeIndex, + &this->PointDataOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the cell data arrays. + this->SetProgressRange(progressRange, 1, fractions); + this->WriteCellDataAppendedData(input->GetCellData(), this->CurrentTimeIndex, + &this->CellDataOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::WriteInlinePiece(vtkIndent indent) +{ + // Write the point data and cell data arrays. + vtkDataSet* input = this->GetInputAsDataSet(); + + // Split progress between point data and cell data arrays. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int pdArrays = input->GetPointData()->GetNumberOfArrays(); + int cdArrays = input->GetCellData()->GetNumberOfArrays(); + int total = (pdArrays+cdArrays)? (pdArrays+cdArrays):1; + float fractions[3] = + { + 0, + float(pdArrays)/total, + 1 + }; + + // Set the range of progress for the point data arrays. + this->SetProgressRange(progressRange, 0, fractions); + this->WritePointDataInline(input->GetPointData(), indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the cell data arrays. + this->SetProgressRange(progressRange, 1, fractions); + this->WriteCellDataInline(input->GetCellData(), indent); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLStructuredDataWriter::GetStartTuple(int* extent, + vtkIdType* increments, + int i, int j, int k) +{ + return (((i - extent[0]) * increments[0]) + + ((j - extent[2]) * increments[1]) + + ((k - extent[4]) * increments[2])); +} + +//---------------------------------------------------------------------------- +vtkDataArray* +vtkXMLStructuredDataWriter::CreateArrayForPoints(vtkDataArray* inArray) +{ + int inExtent[6]; + int outExtent[6]; + this->GetInputExtent(inExtent); + + vtkInformation* inInfo = this->GetExecutive()->GetInputInformation(0, 0); + inInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExtent); + + return this->CreateExactExtent(inArray, inExtent, outExtent, 1); +} + +//---------------------------------------------------------------------------- +vtkDataArray* +vtkXMLStructuredDataWriter::CreateArrayForCells(vtkDataArray* inArray) +{ + int inExtent[6]; + int outExtent[6]; + this->GetInputExtent(inExtent); + + vtkInformation* inInfo = this->GetExecutive()->GetInputInformation(0, 0); + inInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExtent); + return this->CreateExactExtent(inArray, inExtent, outExtent, 0); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredDataWriter::CalculatePieceFractions(float* fractions) +{ + int i; + int extent[6]; + + // Calculate the fraction of total data contributed by each piece. + fractions[0] = 0; + for(i=0;i < this->NumberOfPieces;++i) + { + // Update the piece's extent. + this->ExtentTranslator->SetPiece(i); + this->ExtentTranslator->PieceToExtent(); + this->ExtentTranslator->GetExtent(extent); + + // Add this piece's size to the cumulative fractions array. + fractions[i+1] = fractions[i] + ((extent[1]-extent[0]+1)* + (extent[3]-extent[2]+1)* + (extent[5]-extent[4]+1)); + } + if(fractions[this->NumberOfPieces] == 0) + { + fractions[this->NumberOfPieces] = 1; + } + for(i=0;i < this->NumberOfPieces;++i) + { + fractions[i+1] = fractions[i+1] / fractions[this->NumberOfPieces]; + } +} diff --git a/IO/vtkXMLStructuredDataWriter.h b/IO/vtkXMLStructuredDataWriter.h new file mode 100644 index 0000000..04f4179 --- /dev/null +++ b/IO/vtkXMLStructuredDataWriter.h @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLStructuredDataWriter - Superclass for VTK XML structured data writers. +// .SECTION Description +// vtkXMLStructuredDataWriter provides VTK XML writing functionality that +// is common among all the structured data formats. + +#ifndef __vtkXMLStructuredDataWriter_h +#define __vtkXMLStructuredDataWriter_h + +#include "vtkXMLWriter.h" + +class vtkExtentTranslator; +class vtkDataArray; +class vtkInformation; +class vtkInformationVector; + +class VTK_IO_EXPORT vtkXMLStructuredDataWriter : public vtkXMLWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLStructuredDataWriter,vtkXMLWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get/Set the number of pieces used to stream the image through the + // pipeline while writing to the file. + vtkSetMacro(NumberOfPieces, int); + vtkGetMacro(NumberOfPieces, int); + + // Description: + // Get/Set the extent of the input that should be treated as the + // WholeExtent in the output file. The default is the WholeExtent + // of the input. + vtkSetVector6Macro(WriteExtent, int); + vtkGetVector6Macro(WriteExtent, int); + + // Description: + // Get/Set the extent translator used for streaming. + virtual void SetExtentTranslator(vtkExtentTranslator*); + vtkGetObjectMacro(ExtentTranslator, vtkExtentTranslator); + +protected: + vtkXMLStructuredDataWriter(); + ~vtkXMLStructuredDataWriter(); + + // Writing drivers defined by subclasses. + virtual void WritePrimaryElementAttributes(ostream &os, vtkIndent indent); + virtual void WriteAppendedPiece(int index, vtkIndent indent); + virtual void WriteAppendedPieceData(int index); + virtual void WriteInlinePiece(vtkIndent indent); + virtual void GetInputExtent(int* extent)=0; + + virtual int WriteHeader(); + virtual int WriteAPiece(); + virtual int WriteFooter(); + + virtual void AllocatePositionArrays(); + virtual void DeletePositionArrays(); + + void SetupExtentTranslator(); + vtkDataArray* CreateExactExtent(vtkDataArray* array, int* inExtent, + int* outExtent, int isPoint); + virtual int WriteInlineMode(vtkIndent indent); + vtkIdType GetStartTuple(int* extent, vtkIdType* increments, + int i, int j, int k); + void CalculatePieceFractions(float* fractions); + + // Define utility methods required by vtkXMLWriter. + vtkDataArray* CreateArrayForPoints(vtkDataArray* inArray); + vtkDataArray* CreateArrayForCells(vtkDataArray* inArray); + + void SetInputUpdateExtent(int piece); + int ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + vtkSetVector6Macro(InternalWriteExtent, int); + + // The extent of the input to write, as specified by user + int WriteExtent[6]; + + // The actual extent of the input to write. + int InternalWriteExtent[6]; + + // Number of pieces used for streaming. + int NumberOfPieces; + + // Translate piece number to extent. + vtkExtentTranslator* ExtentTranslator; + + float* ProgressFractions; + + int CurrentPiece; + + // Appended data offsets of point and cell data arrays. + // Store offset position (add TimeStep support) + OffsetsManagerArray *PointDataOM; + OffsetsManagerArray *CellDataOM; + +private: + vtkXMLStructuredDataWriter(const vtkXMLStructuredDataWriter&); // Not implemented. + void operator=(const vtkXMLStructuredDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLStructuredGridReader.cxx b/IO/vtkXMLStructuredGridReader.cxx new file mode 100644 index 0000000..ce9a4aa --- /dev/null +++ b/IO/vtkXMLStructuredGridReader.cxx @@ -0,0 +1,225 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLStructuredGridReader.h" + +#include "vtkObjectFactory.h" +#include "vtkStructuredGrid.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLDataParser.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkXMLStructuredGridReader, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkXMLStructuredGridReader); + +//---------------------------------------------------------------------------- +vtkXMLStructuredGridReader::vtkXMLStructuredGridReader() +{ + // Copied from vtkStructuredGridReader constructor: + vtkStructuredGrid *output = vtkStructuredGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); + this->PointElements = 0; +} + +//---------------------------------------------------------------------------- +vtkXMLStructuredGridReader::~vtkXMLStructuredGridReader() +{ + if(this->NumberOfPieces) { this->DestroyPieces(); } +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridReader::SetOutput(vtkStructuredGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkXMLStructuredGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkXMLStructuredGridReader::GetOutput(int idx) +{ + return vtkStructuredGrid::SafeDownCast( this->GetOutputDataObject(idx) ); +} + + +//---------------------------------------------------------------------------- +const char* vtkXMLStructuredGridReader::GetDataSetName() +{ + return "StructuredGrid"; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridReader::SetOutputExtent(int* extent) +{ + this->GetOutput()->SetExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridReader::SetupPieces(int numPieces) +{ + this->Superclass::SetupPieces(numPieces); + this->PointElements = new vtkXMLDataElement*[numPieces]; + int i; + for(i=0;i < numPieces; ++i) + { + this->PointElements[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridReader::DestroyPieces() +{ + delete [] this->PointElements; + this->Superclass::DestroyPieces(); +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredGridReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + if(!this->Superclass::ReadPiece(ePiece)) { return 0; } + + // Find the Points element in the piece. + int i; + this->PointElements[this->Piece] = 0; + for(i=0; i < ePiece->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = ePiece->GetNestedElement(i); + if((strcmp(eNested->GetName(), "Points") == 0) + && (eNested->GetNumberOfNestedElements() == 1)) + { + this->PointElements[this->Piece] = eNested; + } + } + + // If there is any volume, we require a Points element. + int* piecePointDimensions = this->PiecePointDimensions + this->Piece*3; + if(!this->PointElements[this->Piece] && + (piecePointDimensions[0] > 0) && + (piecePointDimensions[1] > 0) && + (piecePointDimensions[2] > 0)) + { + vtkErrorMacro("A piece is missing its Points element " + "or element does not have exactly 1 array."); + return 0; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + // Create the points array. + vtkPoints* points = vtkPoints::New(); + + // Use the configuration of the first piece since all are the same. + vtkXMLDataElement* ePoints = this->PointElements[0]; + if (ePoints) + { + // Non-zero volume. + vtkDataArray* a = this->CreateDataArray(ePoints->GetNestedElement(0)); + if (a) + { + // Allocate the points array. + a->SetNumberOfTuples( this->GetNumberOfPoints() ); + points->SetData(a); + a->Delete(); + } + else + { + this->DataError = 1; + } + } + + this->GetOutput()->SetPoints(points); + points->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredGridReader::ReadPieceData() +{ + // The amount of data read by the superclass's ReadPieceData comes + // from point/cell data (we read point specifications here). + int dims[3] = {0,0,0}; + this->ComputePointDimensions(this->SubExtent, dims); + vtkIdType superclassPieceSize = + (this->NumberOfPointArrays*dims[0]*dims[1]*dims[2]+ + this->NumberOfCellArrays*(dims[0]-1)*(dims[1]-1)*(dims[2]-1)); + + // Total amount of data in this piece comes from point/cell data + // arrays and the point specifications themselves. + vtkIdType totalPieceSize = + superclassPieceSize + dims[0]*dims[1]*dims[2]; + if(totalPieceSize == 0) + { + totalPieceSize = 1; + } + + // Split the progress range based on the approximate fraction of + // data that will be read by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3] = + { + 0, + float(superclassPieceSize) / totalPieceSize, + 1 + }; + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass read its data. + if(!this->Superclass::ReadPieceData()) { return 0; } + + if(!this->PointElements[this->Piece]) + { + // Empty volume. + return 1; + } + + // Set the range of progress for the points array. + this->SetProgressRange(progressRange, 1, fractions); + + // Read the points array. + vtkStructuredGrid* output = this->GetOutput(); + vtkXMLDataElement* ePoints = this->PointElements[this->Piece]; + return this->ReadArrayForPoints(ePoints->GetNestedElement(0), + output->GetPoints()->GetData()); +} + + +int vtkXMLStructuredGridReader::FillOutputPortInformation(int, vtkInformation *info) + { + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkStructuredGrid"); + return 1; + } diff --git a/IO/vtkXMLStructuredGridReader.h b/IO/vtkXMLStructuredGridReader.h new file mode 100644 index 0000000..9a7825d --- /dev/null +++ b/IO/vtkXMLStructuredGridReader.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLStructuredGridReader - Read VTK XML StructuredGrid files. +// .SECTION Description +// vtkXMLStructuredGridReader reads the VTK XML StructuredGrid file +// format. One structured grid file can be read to produce one +// output. Streaming is supported. The standard extension for this +// reader's file format is "vts". This reader is also used to read a +// single piece of the parallel file format. + +// .SECTION See Also +// vtkXMLPStructuredGridReader + +#ifndef __vtkXMLStructuredGridReader_h +#define __vtkXMLStructuredGridReader_h + +#include "vtkXMLStructuredDataReader.h" + +class vtkStructuredGrid; + +class VTK_IO_EXPORT vtkXMLStructuredGridReader : public vtkXMLStructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLStructuredGridReader,vtkXMLStructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLStructuredGridReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkStructuredGrid *output); + vtkStructuredGrid *GetOutput(); + vtkStructuredGrid *GetOutput(int idx); + +protected: + vtkXMLStructuredGridReader(); + ~vtkXMLStructuredGridReader(); + + const char* GetDataSetName(); + void SetOutputExtent(int* extent); + + void SetupPieces(int numPieces); + void DestroyPieces(); + void SetupOutputData(); + + int ReadPiece(vtkXMLDataElement* ePiece); + int ReadPieceData(); + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The elements representing the points for each piece. + vtkXMLDataElement** PointElements; + +private: + vtkXMLStructuredGridReader(const vtkXMLStructuredGridReader&); // Not implemented. + void operator=(const vtkXMLStructuredGridReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLStructuredGridWriter.cxx b/IO/vtkXMLStructuredGridWriter.cxx new file mode 100644 index 0000000..94cd458 --- /dev/null +++ b/IO/vtkXMLStructuredGridWriter.cxx @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLStructuredGridWriter.h" + +#include "vtkCellData.h" +#include "vtkErrorCode.h" +#include "vtkExtentTranslator.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStructuredGrid.h" +#define vtkOffsetsManager_DoNotInclude +#include "vtkOffsetsManagerArray.h" +#undef vtkOffsetsManager_DoNotInclude + +vtkCxxRevisionMacro(vtkXMLStructuredGridWriter, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkXMLStructuredGridWriter); + +//---------------------------------------------------------------------------- +vtkXMLStructuredGridWriter::vtkXMLStructuredGridWriter() +{ + this->PointsOM = new OffsetsManagerGroup; +} + +//---------------------------------------------------------------------------- +vtkXMLStructuredGridWriter::~vtkXMLStructuredGridWriter() +{ + delete this->PointsOM; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkStructuredGrid* vtkXMLStructuredGridWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::GetInputExtent(int* extent) +{ + this->GetInput()->GetExtent(extent); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLStructuredGridWriter::GetDataSetName() +{ + return "StructuredGrid"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLStructuredGridWriter::GetDefaultFileExtension() +{ + return "vts"; +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::AllocatePositionArrays() +{ + this->Superclass::AllocatePositionArrays(); + this->PointsOM->Allocate(this->NumberOfPieces,this->NumberOfTimeSteps); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::DeletePositionArrays() +{ + this->Superclass::DeletePositionArrays(); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::WriteAppendedPiece(int index, + vtkIndent indent) +{ + this->Superclass::WriteAppendedPiece(index, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + this->WritePointsAppended(this->GetInput()->GetPoints(), indent, + &this->PointsOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::WriteAppendedPieceData(int index) +{ + // Split progress range by the approximate fractions of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteAppendedPieceData(index); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the points array. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the points array. + this->WritePointsAppendedData(this->GetInput()->GetPoints(), + this->CurrentTimeIndex, + &this->PointsOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::WriteInlinePiece(vtkIndent indent) +{ + // Split progress range by the approximate fractions of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteInlinePiece(indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the points array. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the points array. + this->WritePointsInline(this->GetInput()->GetPoints(), indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLStructuredGridWriter::CalculateSuperclassFraction(float* fractions) +{ + int extent[6]; + this->ExtentTranslator->GetExtent(extent); + int dims[3] = {extent[1]-extent[0], + extent[3]-extent[2], + extent[5]-extent[4]}; + + // The amount of data written by the superclass comes from the + // point/cell data arrays. + vtkIdType superclassPieceSize = + (this->GetInput()->GetPointData()->GetNumberOfArrays()*dims[0]*dims[1]*dims[2]+ + this->GetInput()->GetCellData()->GetNumberOfArrays()*(dims[0]-1)*(dims[1]-1)*(dims[2]-1)); + + // The total data written includes the points array. + vtkIdType totalPieceSize = + superclassPieceSize + (dims[0] * dims[1] * dims[2]); + if(totalPieceSize == 0) + { + totalPieceSize = 1; + } + fractions[0] = 0; + fractions[1] = fractions[0] + float(superclassPieceSize)/totalPieceSize; + fractions[2] = 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLStructuredGridWriter::FillInputPortInformation( + int , vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkStructuredGrid"); + return 1; +} diff --git a/IO/vtkXMLStructuredGridWriter.h b/IO/vtkXMLStructuredGridWriter.h new file mode 100644 index 0000000..1aaa15c --- /dev/null +++ b/IO/vtkXMLStructuredGridWriter.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLStructuredGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLStructuredGridWriter - Write VTK XML StructuredGrid files. +// .SECTION Description +// vtkXMLStructuredGridWriter writes the VTK XML StructuredGrid file +// format. One structured grid input can be written into one file in +// any number of streamed pieces. The standard extension for this +// writer's file format is "vts". This writer is also used to write a +// single piece of the parallel file format. + +// .SECTION See Also +// vtkXMLPStructuredGridWriter + +#ifndef __vtkXMLStructuredGridWriter_h +#define __vtkXMLStructuredGridWriter_h + +#include "vtkXMLStructuredDataWriter.h" + +class vtkStructuredGrid; + +class VTK_IO_EXPORT vtkXMLStructuredGridWriter : public vtkXMLStructuredDataWriter +{ +public: + static vtkXMLStructuredGridWriter* New(); + vtkTypeRevisionMacro(vtkXMLStructuredGridWriter,vtkXMLStructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Get/Set the writer's input. + vtkStructuredGrid* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLStructuredGridWriter(); + ~vtkXMLStructuredGridWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + void WriteAppendedPiece(int index, vtkIndent indent); + void WriteAppendedPieceData(int index); + void WriteInlinePiece(vtkIndent indent); + void GetInputExtent(int* extent); + const char* GetDataSetName(); + void CalculateSuperclassFraction(float* fractions); + + // The position of the appended data offset attribute for the points + // array. + OffsetsManagerGroup *PointsOM; //one per piece + + virtual void AllocatePositionArrays(); + virtual void DeletePositionArrays(); + +private: + vtkXMLStructuredGridWriter(const vtkXMLStructuredGridWriter&); // Not implemented. + void operator=(const vtkXMLStructuredGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLUnstructuredDataReader.cxx b/IO/vtkXMLUnstructuredDataReader.cxx new file mode 100644 index 0000000..9595259 --- /dev/null +++ b/IO/vtkXMLUnstructuredDataReader.cxx @@ -0,0 +1,812 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredDataReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLUnstructuredDataReader.h" +#include "vtkObjectFactory.h" +#include "vtkXMLDataElement.h" +#include "vtkPoints.h" +#include "vtkIdTypeArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkCellArray.h" +#include "vtkPointSet.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkXMLUnstructuredDataReader, "$Revision: 1.27 $"); + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredDataReader::vtkXMLUnstructuredDataReader() +{ + this->PointElements = 0; + this->NumberOfPoints = 0; + this->TotalNumberOfPoints = 0; + this->TotalNumberOfCells = 0; + + this->PointsTimeStep = -1; //invalid state + this->PointsOffset = (unsigned long)-1; +} + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredDataReader::~vtkXMLUnstructuredDataReader() +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkXMLUnstructuredDataReader::GetOutputAsPointSet() +{ + return vtkPointSet::SafeDownCast( this->GetOutputDataObject(0) ); +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* +vtkXMLUnstructuredDataReader +::FindDataArrayWithName(vtkXMLDataElement* eParent, const char* name) +{ + // Find a nested element that represents a data array with the given name. + // and proper TimeStep + int i; + for(i=0;i < eParent->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = eParent->GetNestedElement(i); + if(strcmp(eNested->GetName(), "DataArray") == 0) + { + const char* aName = eNested->GetAttribute("Name"); + if(aName && (strcmp(aName, name) == 0)) + { + int numTimeSteps = eNested->GetVectorAttribute("TimeStep", + this->NumberOfTimeSteps, this->TimeSteps); + assert( numTimeSteps <= this->NumberOfTimeSteps ); + // Check if CurrentTimeStep is in the array and particular field is also: + int isCurrentTimeInArray = + vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps); + // If no time is specified or if time is specified and match then read + if( !numTimeSteps || isCurrentTimeInArray ) + { + return eNested; + } + } + } + } + return 0; +} + +//---------------------------------------------------------------------------- +template +void vtkXMLUnstructuredDataReaderCopyArray(TIn* in, TOut* out, + vtkIdType length) +{ + for(vtkIdType i = 0; i < length; ++i) + { + out[i] = static_cast(in[i]); + } +} + +//---------------------------------------------------------------------------- +vtkIdTypeArray* +vtkXMLUnstructuredDataReader::ConvertToIdTypeArray(vtkDataArray* a) +{ + // If it is already a vtkIdTypeArray, just return it. + vtkIdTypeArray* ida = vtkIdTypeArray::SafeDownCast(a); + if(ida) + { + return ida; + } + + // Need to convert the data. + ida = vtkIdTypeArray::New(); + ida->SetNumberOfComponents(a->GetNumberOfComponents()); + ida->SetNumberOfTuples(a->GetNumberOfTuples()); + vtkIdType length = a->GetNumberOfComponents() * a->GetNumberOfTuples(); + vtkIdType* idBuffer = ida->GetPointer(0); + switch (a->GetDataType()) + { + vtkTemplateMacro( + vtkXMLUnstructuredDataReaderCopyArray( + static_cast(a->GetVoidPointer(0)), + idBuffer, length)); + default: + vtkErrorMacro("Cannot convert vtkDataArray of type " << a->GetDataType() + << " to vtkIdTypeArray."); + ida->Delete(); + ida = 0; + } + a->Delete(); + return ida; +} + +//---------------------------------------------------------------------------- +vtkUnsignedCharArray* +vtkXMLUnstructuredDataReader::ConvertToUnsignedCharArray(vtkDataArray* a) +{ + // If it is already a vtkUnsignedCharArray, just return it. + vtkUnsignedCharArray* uca = vtkUnsignedCharArray::SafeDownCast(a); + if(uca) + { + return uca; + } + + // Need to convert the data. + uca = vtkUnsignedCharArray::New(); + uca->SetNumberOfComponents(a->GetNumberOfComponents()); + uca->SetNumberOfTuples(a->GetNumberOfTuples()); + vtkIdType length = a->GetNumberOfComponents() * a->GetNumberOfTuples(); + unsigned char* ucBuffer = uca->GetPointer(0); + switch (a->GetDataType()) + { + vtkTemplateMacro( + vtkXMLUnstructuredDataReaderCopyArray( + static_cast(a->GetVoidPointer(0)), + ucBuffer, length)); + default: + vtkErrorMacro("Cannot convert vtkDataArray of type " << a->GetDataType() + << " to vtkUnsignedCharArray."); + uca->Delete(); + uca = 0; + } + a->Delete(); + return uca; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::SetupEmptyOutput() +{ + // No pieces means no input. + this->GetOutputAsDataSet(0)->SetUpdateExtent(0, 0); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::SetupOutputTotals() +{ + this->TotalNumberOfPoints = 0; + for(int i=this->StartPiece; i < this->EndPiece; ++i) + { + this->TotalNumberOfPoints += this->NumberOfPoints[i]; + } + this->StartPoint = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::SetupNextPiece() +{ + this->StartPoint += this->NumberOfPoints[this->Piece]; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::SetupUpdateExtent(int piece, + int numberOfPieces, + int ghostLevel) +{ + this->UpdatePiece = piece; + this->UpdateNumberOfPieces = numberOfPieces; + this->UpdateGhostLevel = ghostLevel; + + // If more pieces are requested than available, just return empty + // pieces for the extra ones. + if(this->UpdateNumberOfPieces > this->NumberOfPieces) + { + this->UpdateNumberOfPieces = this->NumberOfPieces; + } + + // Find the range of pieces to read. + if(this->UpdatePiece < this->UpdateNumberOfPieces) + { + this->StartPiece = ((this->UpdatePiece*this->NumberOfPieces) / + this->UpdateNumberOfPieces); + this->EndPiece = (((this->UpdatePiece+1)*this->NumberOfPieces) / + this->UpdateNumberOfPieces); + } + else + { + this->StartPiece = 0; + this->EndPiece = 0; + } + + // Find the total size of the output. + this->SetupOutputTotals(); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::ReadXMLData() +{ + // Get the update request. + int piece; + int numberOfPieces; + int ghostLevel; + this->GetOutputUpdateExtent(piece, numberOfPieces, ghostLevel); + + vtkDebugMacro("Updating piece " << piece << " of " << numberOfPieces + << " with ghost level " << ghostLevel); + + // Setup the range of pieces that will be read. + this->SetupUpdateExtent(piece, numberOfPieces, ghostLevel); + + // If there are no data to read, stop now. + if(this->StartPiece == this->EndPiece) + { + return; + } + + vtkDebugMacro("Reading piece range [" << this->StartPiece + << ", " << this->EndPiece << ") from file."); + + // Let superclasses read data. This also allocates output data. + this->Superclass::ReadXMLData(); + + // Split current progress range based on fraction contributed by + // each piece. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + // Calculate the cumulative fraction of data contributed by each + // piece (for progress). + float* fractions = new float[this->EndPiece-this->StartPiece+1]; + int i; + fractions[0] = 0; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + int index = i-this->StartPiece; + fractions[index+1] = (fractions[index] + + this->GetNumberOfPointsInPiece(i) + + this->GetNumberOfCellsInPiece(i)); + } + if(fractions[this->EndPiece-this->StartPiece] == 0) + { + fractions[this->EndPiece-this->StartPiece] = 1; + } + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + int index = i-this->StartPiece; + fractions[index+1] = fractions[index+1] / fractions[this->EndPiece-this->StartPiece]; + } + + // Read the data needed from each piece. + for(i=this->StartPiece; (i < this->EndPiece && !this->AbortExecute && + !this->DataError); ++i) + { + // Set the range of progress for this piece. + this->SetProgressRange(progressRange, i-this->StartPiece, fractions); + + if(!this->Superclass::ReadPieceData(i)) + { + // An error occurred while reading the piece. + this->DataError = 1; + } + this->SetupNextPiece(); + } + + delete [] fractions; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::SetupPieces(int numPieces) +{ + this->Superclass::SetupPieces(numPieces); + this->NumberOfPoints = new vtkIdType[numPieces]; + this->PointElements = new vtkXMLDataElement*[numPieces]; + for(int i=0;i < numPieces; ++i) + { + this->PointElements[i] = 0; + this->NumberOfPoints[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::DestroyPieces() +{ + delete [] this->PointElements; + delete [] this->NumberOfPoints; + this->PointElements = 0; + this->NumberOfPoints = 0; + this->Superclass::DestroyPieces(); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfPoints() +{ + return this->TotalNumberOfPoints; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfCells() +{ + return this->TotalNumberOfCells; +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfPointsInPiece(int piece) +{ + return this->NumberOfPoints[piece]; +} + +//---------------------------------------------------------------------------- +// Note that any changes (add or removing information) made to this method +// should be replicated in CopyOutputInformation +void vtkXMLUnstructuredDataReader::SetupOutputInformation(vtkInformation *outInfo) +{ + this->Superclass::SetupOutputInformation(outInfo); + + // Set the maximum number of pieces that can be provided by this + // reader. + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + this->NumberOfPieces); +} + + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::CopyOutputInformation(vtkInformation *outInfo, int port) +{ + this->Superclass::CopyOutputInformation(outInfo, port); + outInfo->CopyEntry( this->GetExecutive()->GetOutputInformation( port ), + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES() ); +} + + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + // Create the points array. + vtkPoints* points = vtkPoints::New(); + + // Use the configuration of the first piece since all are the same. + vtkXMLDataElement* ePoints = this->PointElements[0]; + if (ePoints) + { + // Non-zero volume. + vtkDataArray* a = this->CreateDataArray(ePoints->GetNestedElement(0)); + if (a) + { + // Allocate the points array. + a->SetNumberOfTuples( this->GetNumberOfPoints() ); + points->SetData(a); + a->Delete(); + } + else + { + this->DataError = 1; + } + } + + this->GetOutputAsPointSet()->SetPoints(points); + points->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + if(!this->Superclass::ReadPiece(ePiece)) + { + return 0; + } + + if(!ePiece->GetScalarAttribute("NumberOfPoints", + this->NumberOfPoints[this->Piece])) + { + vtkErrorMacro("Piece " << this->Piece + << " is missing its NumberOfPoints attribute."); + this->NumberOfPoints[this->Piece] = 0; + return 0; + } + + // Find the Points element in the piece. + int i; + this->PointElements[this->Piece] = 0; + for(i=0; i < ePiece->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = ePiece->GetNestedElement(i); + if(strcmp(eNested->GetName(), "Points") == 0) + { + // make sure the XML file is somehow valid: + if( (this->NumberOfTimeSteps > 0 && eNested->GetNumberOfNestedElements() >= 1) || + (this->NumberOfTimeSteps == 0 && eNested->GetNumberOfNestedElements() == 1)) + { + this->PointElements[this->Piece] = eNested; + } + } + } + + // If there are some points, we require a Points element. + if(!this->PointElements[this->Piece] && + (this->NumberOfPoints[this->Piece] > 0)) + { + vtkErrorMacro("A piece is missing its Points element " + "or element does not have exactly 1 array."); + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataReader::ReadPieceData() +{ + // The amount of data read by the superclass's ReadPieceData comes + // from point/cell data (we read point specifications here). + vtkIdType superclassPieceSize = + (this->NumberOfPointArrays*this->GetNumberOfPointsInPiece(this->Piece)+ + this->NumberOfCellArrays*this->GetNumberOfCellsInPiece(this->Piece)); + + // Total amount of data in this piece comes from point/cell data + // arrays and the point specifications themselves. + vtkIdType totalPieceSize = + superclassPieceSize + 1*this->GetNumberOfPointsInPiece(this->Piece); + if(totalPieceSize == 0) + { + totalPieceSize = 1; + } + + // Split the progress range based on the approximate fraction of + // data that will be read by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3] = + { + 0, + float(superclassPieceSize)/totalPieceSize, + 1 + }; + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass read its data. + if(!this->Superclass::ReadPieceData()) + { + return 0; + } + + vtkPointSet* output = this->GetOutputAsPointSet(); + + // Set the range of progress for the Points. + this->SetProgressRange(progressRange, 1, fractions); + + // Read the points array. + vtkXMLDataElement* ePoints = this->PointElements[this->Piece]; + if(ePoints) + { + for(int i=0;(i < ePoints->GetNumberOfNestedElements() && + !this->AbortExecute);++i) + { + vtkXMLDataElement* eNested = ePoints->GetNestedElement(i); + assert( strcmp(eNested->GetName(), "DataArray") == 0 ); + int needToRead = this->PointsNeedToReadTimeStep(eNested); + if( needToRead ) + { + // Read the array. + if(!this->ReadArrayForPoints(eNested, output->GetPoints()->GetData())) + { + vtkErrorMacro("Cannot read points array from " << ePoints->GetName() + << " in piece " << this->Piece + << ". The data array in the element may be too short."); + return 0; + } + } + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataReader::ReadCellArray(vtkIdType numberOfCells, + vtkIdType totalNumberOfCells, + vtkXMLDataElement* eCells, + vtkCellArray* outCells) +{ + if(numberOfCells <= 0) + { + return 1; + } + else + { + if(!eCells) + { + return 0; + } + } + + // Split progress range into 1/5 for offsets array and 4/5 for + // connectivity array. This assumes an average of 4 points per + // cell. Unfortunately, we cannot know the length of the + // connectivity array ahead of time to calculate the real fraction. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3] = {0, 0.2, 1}; + + // Set range of progress for offsets array. + this->SetProgressRange(progressRange, 0, fractions); + + // Read the cell offsets. + vtkXMLDataElement* eOffsets = this->FindDataArrayWithName(eCells, "offsets"); + if(!eOffsets) + { + vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"offsets\" array could not be found."); + return 0; + } + vtkDataArray* c1 = this->CreateDataArray(eOffsets); + if(!c1 || (c1->GetNumberOfComponents() != 1)) + { + vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"offsets\" array could not be created" + << " with one component."); + return 0; + } + c1->SetNumberOfTuples(numberOfCells); + if(!this->ReadData(eOffsets, c1->GetVoidPointer(0), c1->GetDataType(), + 0, numberOfCells)) + { + vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"offsets\" array is not long enough."); + return 0; + } + vtkIdTypeArray* cellOffsets = this->ConvertToIdTypeArray(c1); + if(!cellOffsets) + { + vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"offsets\" array could not be" + << " converted to a vtkIdTypeArray."); + return 0; + } + + // Check the contents of the cell offsets array. + vtkIdType* coffset = cellOffsets->GetPointer(0); + vtkIdType lastOffset = 0; + vtkIdType i; + for(i=0; i < numberOfCells; ++i) + { + if(coffset[i] <= lastOffset) + { + vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"offsets\" array is" + << " not monotonically increasing or starts with a" + << " value less than 1."); + cellOffsets->Delete(); + return 0; + } + lastOffset = coffset[i]; + } + + // Set range of progress for connectivity array. + this->SetProgressRange(progressRange, 1, fractions); + + // Read the cell point connectivity array. + vtkIdType cpLength = cellOffsets->GetValue(numberOfCells-1); + vtkXMLDataElement* eConn = this->FindDataArrayWithName(eCells, "connectivity"); + if(!eConn) + { + vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"connectivity\" array could not be found."); + cellOffsets->Delete(); + return 0; + } + vtkDataArray* c0 = this->CreateDataArray(eConn); + if(!c0 || (c0->GetNumberOfComponents() != 1)) + { + vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"connectivity\" array could not be created" + << " with one component."); + cellOffsets->Delete(); + return 0; + } + c0->SetNumberOfTuples(cpLength); + if(!this->ReadData(eConn, c0->GetVoidPointer(0), c0->GetDataType(), + 0, cpLength)) + { + vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"connectivity\" array is not long enough."); + cellOffsets->Delete(); + return 0; + } + vtkIdTypeArray* cellPoints = this->ConvertToIdTypeArray(c0); + if(!cellPoints) + { + vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"connectivity\" array could not be" + << " converted to a vtkIdTypeArray."); + cellOffsets->Delete(); + return 0; + } + + // Allocate memory in the output connectivity array. + vtkIdType curSize = 0; + if(outCells->GetData()) + { + curSize = outCells->GetData()->GetNumberOfTuples(); + } + vtkIdType newSize = curSize+numberOfCells+cellPoints->GetNumberOfTuples(); + vtkIdType* cptr = outCells->WritePointer(totalNumberOfCells, newSize); + cptr += curSize; + + // Copy the connectivity data. + vtkIdType previousOffset = 0; + for(i=0; i < numberOfCells; ++i) + { + vtkIdType length = cellOffsets->GetValue(i)-previousOffset; + *cptr++ = length; + vtkIdType* sptr = cellPoints->GetPointer(previousOffset); + // Copy the point indices, but increment them for the appended + // version's index. + vtkIdType j; + for(j=0;j < length; ++j) + { + cptr[j] = sptr[j]+this->StartPoint; + } + cptr += length; + previousOffset += length; + } + + cellPoints->Delete(); + cellOffsets->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataReader::ReadArrayForPoints(vtkXMLDataElement* da, + vtkDataArray* outArray) +{ + vtkIdType startPoint = this->StartPoint; + vtkIdType numPoints = this->NumberOfPoints[this->Piece]; + vtkIdType components = outArray->GetNumberOfComponents(); + return this->ReadData(da, outArray->GetVoidPointer(startPoint*components), + outArray->GetDataType(), 0, numPoints*components); +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataReader::PointsNeedToReadTimeStep(vtkXMLDataElement *eNested) +{ + // Easy case no timestep: + int numTimeSteps = eNested->GetVectorAttribute("TimeStep", + this->NumberOfTimeSteps, this->TimeSteps); + assert( numTimeSteps <= this->NumberOfTimeSteps ); + if (!numTimeSteps && !this->NumberOfTimeSteps) + { + assert( this->PointsTimeStep == -1 ); //No timestep in this file + return 1; + } + // else TimeStep was specified but no TimeValues associated were found + assert( this->NumberOfTimeSteps ); + + // case numTimeSteps > 1 + int isCurrentTimeInArray = + vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps); + if( !isCurrentTimeInArray && numTimeSteps) + { + return 0; + } + // we know that time steps are specified and that CurrentTimeStep is in the array + // we need to figure out if we need to read the array or if it was forwarded + // Need to check the current 'offset' + unsigned long offset; + if( eNested->GetScalarAttribute("offset", offset) ) + { + if( this->PointsOffset != offset ) + { + // save the pointsOffset we are about to read + assert( this->PointsTimeStep == -1 ); //cannot have mixture of binary and appended + this->PointsOffset = offset; + return 1; + } + } + else + { + // No offset is specified this is a binary file + // First thing to check if numTimeSteps == 0: + if( !numTimeSteps && this->NumberOfTimeSteps && this->PointsTimeStep == -1) + { + // Update last PointsTimeStep read + this->PointsTimeStep = this->CurrentTimeStep; + return 1; + } + int isLastTimeInArray = + vtkXMLReader::IsTimeStepInArray(this->PointsTimeStep, this->TimeSteps, numTimeSteps); + // If no time is specified or if time is specified and match then read + if (isCurrentTimeInArray && !isLastTimeInArray) + { + // CurrentTimeStep is in TimeSteps but Last is not := need to read + // Update last PointsTimeStep read + this->PointsTimeStep = this->CurrentTimeStep; + return 1; + } + } + // all other cases we don't need to read: + return 0; +} + +//---------------------------------------------------------------------------- +// Returns true if we need to read the data for the current time step +int vtkXMLUnstructuredDataReader::CellsNeedToReadTimeStep(vtkXMLDataElement *eNested, + int &cellstimestep, unsigned long &cellsoffset) +{ + // Easy case no timestep: + int numTimeSteps = eNested->GetVectorAttribute("TimeStep", + this->NumberOfTimeSteps, this->TimeSteps); + assert( numTimeSteps <= this->NumberOfTimeSteps ); + if (!numTimeSteps && !this->NumberOfTimeSteps) + { + assert( cellstimestep == -1 ); //No timestep in this file + return 1; + } + // else TimeStep was specified but no TimeValues associated were found + assert( !this->NumberOfTimeSteps ); + + // case numTimeSteps > 1 + int isCurrentTimeInArray = + vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps); + if( !isCurrentTimeInArray && numTimeSteps) + { + return 0; + } + // we know that time steps are specified and that CurrentTimeStep is in the array + // we need to figure out if we need to read the array or if it was forwarded + // Need to check the current 'offset' + unsigned long offset; + if( eNested->GetScalarAttribute("offset", offset) ) + { + if( cellsoffset != offset ) + { + // save the cellsOffset we are about to read + assert( cellstimestep == -1 ); //cannot have mixture of binary and appended + cellsoffset = offset; + return 1; + } + } + else + { + // No offset is specified this is a binary file + // First thing to check if numTimeSteps == 0: + if( !numTimeSteps && this->NumberOfTimeSteps && cellstimestep == -1) + { + // Update last PointsTimeStep read + cellstimestep = this->CurrentTimeStep; + return 1; + } + int isLastTimeInArray = + vtkXMLReader::IsTimeStepInArray(cellstimestep, this->TimeSteps, numTimeSteps); + // If no time is specified or if time is specified and match then read + if (isCurrentTimeInArray && !isLastTimeInArray) + { + // CurrentTimeStep is in TimeSteps but Last is not := need to read + // Update last cellstimestep read + cellstimestep = this->CurrentTimeStep; + return 1; + } + } + // all other cases we don't need to read: + return 0; +} + diff --git a/IO/vtkXMLUnstructuredDataReader.h b/IO/vtkXMLUnstructuredDataReader.h new file mode 100644 index 0000000..274b3af --- /dev/null +++ b/IO/vtkXMLUnstructuredDataReader.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredDataReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLUnstructuredDataReader - Superclass for unstructured data XML readers. +// .SECTION Description +// vtkXMLUnstructuredDataReader provides functionality common to all +// unstructured data format readers. + +// .SECTION See Also +// vtkXMLPolyDataReader vtkXMLUnstructuredGridReader + +#ifndef __vtkXMLUnstructuredDataReader_h +#define __vtkXMLUnstructuredDataReader_h + +#include "vtkXMLDataReader.h" + +class vtkCellArray; +class vtkIdTypeArray; +class vtkPointSet; +class vtkUnsignedCharArray; + +class VTK_IO_EXPORT vtkXMLUnstructuredDataReader : public vtkXMLDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLUnstructuredDataReader,vtkXMLDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the number of points in the output. + virtual vtkIdType GetNumberOfPoints(); + + // Description: + // Get the number of cells in the output. + virtual vtkIdType GetNumberOfCells(); + + // Description: + // Setup the reader as if the given update extent were requested by + // its output. This can be used after an UpdateInformation to + // validate GetNumberOfPoints() and GetNumberOfCells() without + // actually reading data. + void SetupUpdateExtent(int piece, int numberOfPieces, int ghostLevel); + + // For the specified port, copy the information this reader sets up in + // SetupOutputInformation to outInfo + virtual void CopyOutputInformation(vtkInformation *outInfo, int port); + + +protected: + vtkXMLUnstructuredDataReader(); + ~vtkXMLUnstructuredDataReader(); + + vtkPointSet* GetOutputAsPointSet(); + vtkXMLDataElement* FindDataArrayWithName(vtkXMLDataElement* eParent, + const char* name); + vtkIdTypeArray* ConvertToIdTypeArray(vtkDataArray* a); + vtkUnsignedCharArray* ConvertToUnsignedCharArray(vtkDataArray* a); + + // Pipeline execute data driver. Called by vtkXMLReader. + void ReadXMLData(); + + virtual void SetupEmptyOutput(); + virtual void GetOutputUpdateExtent(int& piece, int& numberOfPieces, + int& ghostLevel)=0; + virtual void SetupOutputTotals(); + virtual void SetupNextPiece(); + void SetupPieces(int numPieces); + void DestroyPieces(); + + // Setup the output's information. + void SetupOutputInformation(vtkInformation *outInfo); + + void SetupOutputData(); + int ReadPiece(vtkXMLDataElement* ePiece); + int ReadPieceData(); + int ReadCellArray(vtkIdType numberOfCells, vtkIdType totalNumberOfCells, + vtkXMLDataElement* eCells, vtkCellArray* outCells); + + // Read a data array whose tuples coorrespond to points. + int ReadArrayForPoints(vtkXMLDataElement* da, vtkDataArray* outArray); + + // Get the number of points/cells in the given piece. Valid after + // UpdateInformation. + virtual vtkIdType GetNumberOfPointsInPiece(int piece); + virtual vtkIdType GetNumberOfCellsInPiece(int piece)=0; + + // The update request. + int UpdatePiece; + int UpdateNumberOfPieces; + int UpdateGhostLevel; + + // The range of pieces from the file that will form the UpdatePiece. + int StartPiece; + int EndPiece; + vtkIdType TotalNumberOfPoints; + vtkIdType TotalNumberOfCells; + vtkIdType StartPoint; + + // The Points element for each piece. + vtkXMLDataElement** PointElements; + vtkIdType* NumberOfPoints; + + int PointsTimeStep; + unsigned long PointsOffset; + int PointsNeedToReadTimeStep(vtkXMLDataElement *eNested); + int CellsNeedToReadTimeStep(vtkXMLDataElement *eNested, int &cellstimestep, + unsigned long &cellsoffset); + + +private: + vtkXMLUnstructuredDataReader(const vtkXMLUnstructuredDataReader&); // Not implemented. + void operator=(const vtkXMLUnstructuredDataReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLUnstructuredDataWriter.cxx b/IO/vtkXMLUnstructuredDataWriter.cxx new file mode 100644 index 0000000..bb09915 --- /dev/null +++ b/IO/vtkXMLUnstructuredDataWriter.cxx @@ -0,0 +1,793 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredDataWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLUnstructuredDataWriter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDataCompressor.h" +#include "vtkDataSetAttributes.h" +#include "vtkErrorCode.h" +#include "vtkIdTypeArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPoints.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" +#define vtkOffsetsManager_DoNotInclude +#include "vtkOffsetsManagerArray.h" +#undef vtkOffsetsManager_DoNotInclude + +#include + +vtkCxxRevisionMacro(vtkXMLUnstructuredDataWriter, "$Revision: 1.19 $"); + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredDataWriter::vtkXMLUnstructuredDataWriter() +{ + this->NumberOfPieces = 1; + this->WritePiece = -1; + this->GhostLevel = 0; + this->CellPoints = vtkIdTypeArray::New(); + this->CellOffsets = vtkIdTypeArray::New(); + this->CellPoints->SetName("connectivity"); + this->CellOffsets->SetName("offsets"); + + this->CurrentPiece = 0; + this->FieldDataOM->Allocate(0); + this->PointsOM = new OffsetsManagerGroup; + this->PointDataOM = new OffsetsManagerArray; + this->CellDataOM = new OffsetsManagerArray; +} + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredDataWriter::~vtkXMLUnstructuredDataWriter() +{ + this->CellPoints->Delete(); + this->CellOffsets->Delete(); + delete this->PointsOM; + delete this->PointDataOM; + delete this->CellDataOM; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n"; + os << indent << "WritePiece: " << this->WritePiece << "\n"; + os << indent << "GhostLevel: " << this->GhostLevel << "\n"; +} + +//---------------------------------------------------------------------------- +vtkPointSet* vtkXMLUnstructuredDataWriter::GetInputAsPointSet() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataWriter::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces)) + { + this->SetInputUpdateExtent( + this->CurrentPiece, this->NumberOfPieces, this->GhostLevel); + } + else + { + this->SetInputUpdateExtent( + this->WritePiece, this->NumberOfPieces, this->GhostLevel); + } + return 1; + } + + // generate the data + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->SetErrorCode(vtkErrorCode::NoError); + + if(!this->Stream && !this->FileName) + { + this->SetErrorCode(vtkErrorCode::NoFileNameError); + vtkErrorMacro("The FileName or Stream must be set first."); + return 0; + } + + // We don't want to write more pieces than the pipeline can produce, + // but we need to preserve the user's requested number of pieces in + // case the input changes later. If MaximumNumberOfPieces is lower + // than 1, any number of pieces can be produced by the pipeline. + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + int numPieces = this->NumberOfPieces; + int maxPieces = + inInfo->Get(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES()); + if((maxPieces > 0) && (this->NumberOfPieces > maxPieces)) + { + this->NumberOfPieces = maxPieces; + } + + if (this->WritePiece >= 0) + { + this->CurrentPiece = this->WritePiece; + } + else + { + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + this->SetProgressRange(progressRange, this->CurrentPiece, this->NumberOfPieces); + } + + int result = 1; + if (this->CurrentPiece == 0 && this->CurrentTimeIndex == 0 || this->WritePiece >= 0) + { + // We are just starting to write. Do not call + // UpdateProgressDiscrete because we want a 0 progress callback the + // first time. + this->UpdateProgress(0); + + // Initialize progress range to entire 0..1 range. + float wholeProgressRange[2] = {0,1}; + this->SetProgressRange(wholeProgressRange, 0, 1); + + if (!this->OpenFile()) + { + this->NumberOfPieces = numPieces; + return 0; + } + // Write the file. + if (!this->StartFile()) + { + this->NumberOfPieces = numPieces; + return 0; + } + + if (!this->WriteHeader()) + { + this->NumberOfPieces = numPieces; + return 0; + } + + this->CurrentTimeIndex = 0; + if( this->DataMode == vtkXMLWriter::Appended && this->FieldDataOM->GetNumberOfElements()) + { + // Write the field data arrays. + this->WriteFieldDataAppendedData(this->GetInput()->GetFieldData(), + this->CurrentTimeIndex, this->FieldDataOM); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + } + } + + if( !(this->UserContinueExecuting == 0)) //if user ask to stop do not try to write a piece + { + result = this->WriteAPiece(); + } + + if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces)) + { + // Tell the pipeline to start looping. + if (this->CurrentPiece == 0) + { + request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); + } + this->CurrentPiece++; + } + + if (this->CurrentPiece == this->NumberOfPieces || this->WritePiece >= 0) + { + request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); + this->CurrentPiece = 0; + // We are done writting all the pieces, lets loop over time now: + this->CurrentTimeIndex++; + + if( this->UserContinueExecuting != 1 ) + { + if (!this->WriteFooter()) + { + this->NumberOfPieces = numPieces; + return 0; + } + + if (!this->EndFile()) + { + this->NumberOfPieces = numPieces; + return 0; + } + + this->CloseFile(); + this->CurrentTimeIndex = 0; // Reset + } + } + this->NumberOfPieces = numPieces; + + // We have finished writing. + this->UpdateProgressDiscrete(1); + return result; + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::AllocatePositionArrays() +{ + this->NumberOfPointsPositions = new unsigned long[this->NumberOfPieces]; + + this->PointsOM->Allocate(this->NumberOfPieces, this->NumberOfTimeSteps); + this->PointDataOM->Allocate(this->NumberOfPieces); + this->CellDataOM->Allocate(this->NumberOfPieces); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::DeletePositionArrays() +{ + delete [] this->NumberOfPointsPositions; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataWriter::WriteHeader() +{ + vtkIndent indent = vtkIndent().GetNextIndent(); + + ostream& os = *(this->Stream); + + if(!this->WritePrimaryElement(os, indent)) + { + return 0; + } + + this->WriteFieldData(indent.GetNextIndent()); + + if(this->DataMode == vtkXMLWriter::Appended) + { + vtkIndent nextIndent = indent.GetNextIndent(); + + this->AllocatePositionArrays(); + + if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces)) + { + // Loop over each piece and write its structure. + int i; + for(i=0; i < this->NumberOfPieces; ++i) + { + // Open the piece's element. + os << nextIndent << "WriteAppendedPieceAttributes(i); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + os << ">\n"; + + this->WriteAppendedPiece(i, nextIndent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + + // Close the piece's element. + os << nextIndent << "\n"; + } + } + else + { + // Write just the requested piece. + // Open the piece's element. + os << nextIndent << "WriteAppendedPieceAttributes(this->WritePiece); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + os << ">\n"; + + this->WriteAppendedPiece(this->WritePiece, nextIndent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + + // Close the piece's element. + os << nextIndent << "\n"; + } + + // Close the primary element. + os << indent << "GetDataSetName() << ">\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + this->DeletePositionArrays(); + return 0; + } + + this->StartAppendedData(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + return 0; + } + + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataWriter::WriteAPiece() +{ + vtkIndent indent = vtkIndent().GetNextIndent(); + + int result=1; + + if(this->DataMode == vtkXMLWriter::Appended) + { + this->WriteAppendedPieceData(this->CurrentPiece); + } + else + { + result = this->WriteInlineMode(indent); + } + + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeletePositionArrays(); + result = 0; + } + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataWriter::WriteFooter() +{ + vtkIndent indent = vtkIndent().GetNextIndent(); + + ostream& os = *(this->Stream); + + if(this->DataMode == vtkXMLWriter::Appended) + { + this->DeletePositionArrays(); + this->EndAppendedData(); + } + else + { + // Close the primary element. + os << indent << "GetDataSetName() << ">\n"; + os.flush(); + if (os.fail()) + { + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredDataWriter::WriteInlineMode(vtkIndent indent) +{ + ostream& os = *(this->Stream); + vtkIndent nextIndent = indent.GetNextIndent(); + + // Open the piece's element. + os << nextIndent << "WriteInlinePieceAttributes(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + os << ">\n"; + + this->WriteInlinePiece(nextIndent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + // Close the piece's element. + os << nextIndent << "\n"; + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::WriteInlinePieceAttributes() +{ + vtkPointSet* input = this->GetInputAsPointSet(); + this->WriteScalarAttribute("NumberOfPoints", + input->GetNumberOfPoints()); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::WriteInlinePiece(vtkIndent indent) +{ + vtkPointSet* input = this->GetInputAsPointSet(); + + // Split progress among point data, cell data, and point arrays. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[4]; + this->CalculateDataFractions(fractions); + + // Set the range of progress for the point data arrays. + this->SetProgressRange(progressRange, 0, fractions); + + // Write the point data arrays. + this->WritePointDataInline(input->GetPointData(), indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the cell data arrays. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the cell data arrays. + this->WriteCellDataInline(input->GetCellData(), indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the point specification array. + this->SetProgressRange(progressRange, 2, fractions); + + // Write the point specification array. + this->WritePointsInline(input->GetPoints(), indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::WriteAppendedPieceAttributes(int index) +{ + this->NumberOfPointsPositions[index] = + this->ReserveAttributeSpace("NumberOfPoints"); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::WriteAppendedPiece(int index, + vtkIndent indent) +{ + vtkPointSet* input = this->GetInputAsPointSet(); + + this->WritePointDataAppended(input->GetPointData(), indent, + &this->PointDataOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteCellDataAppended(input->GetCellData(), indent, + &this->CellDataOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WritePointsAppended(input->GetPoints(), indent, + &this->PointsOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::WriteAppendedPieceData(int index) +{ + ostream& os = *(this->Stream); + vtkPointSet* input = this->GetInputAsPointSet(); + + unsigned long returnPosition = os.tellp(); + os.seekp(this->NumberOfPointsPositions[index]); + vtkPoints* points = input->GetPoints(); + this->WriteScalarAttribute("NumberOfPoints", + (points?points->GetNumberOfPoints():0)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + os.seekp(returnPosition); + + // Split progress among point data, cell data, and point arrays. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[4]; + this->CalculateDataFractions(fractions); + + // Set the range of progress for the point data arrays. + this->SetProgressRange(progressRange, 0, fractions); + + // Write the point data arrays. + this->WritePointDataAppendedData(input->GetPointData(), this->CurrentTimeIndex, + &this->PointDataOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the cell data arrays. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the cell data arrays. + this->WriteCellDataAppendedData(input->GetCellData(), this->CurrentTimeIndex, + &this->CellDataOM->GetPiece(index)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the point specification array. + this->SetProgressRange(progressRange, 2, fractions); + + // Write the point specification array. + // Since we are writting the point let save the Modified Time of vtkPoints: + this->WritePointsAppendedData(input->GetPoints(), this->CurrentTimeIndex, + &this->PointsOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::WriteCellsInline(const char* name, + vtkCellArray* cells, + vtkDataArray* types, + vtkIndent indent) +{ + this->ConvertCells(cells); + + ostream& os = *(this->Stream); + os << indent << "<" << name << ">\n"; + + // Split progress by cell connectivity, offset, and type arrays. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[4]; + this->CalculateCellFractions(fractions, types?types->GetNumberOfTuples():0); + + // Set the range of progress for the connectivity array. + this->SetProgressRange(progressRange, 0, fractions); + + // Write the connectivity array. + this->WriteDataArrayInline(this->CellPoints, indent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set the range of progress for the offsets array. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the offsets array. + this->WriteDataArrayInline(this->CellOffsets, indent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + if(types) + { + // Set the range of progress for the types array. + this->SetProgressRange(progressRange, 2, fractions); + + // Write the types array. + this->WriteDataArrayInline(types, indent.GetNextIndent(), "types"); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + } + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::WriteCellsAppended(const char* name, + vtkDataArray* types, + vtkIndent indent, + OffsetsManagerGroup *cellsManager) +{ + ostream& os = *(this->Stream); + os << indent << "<" << name << ">\n"; + + // Helper for the 'for' loop + vtkDataArray *allcells[3]; + allcells[0] = this->CellPoints; + allcells[1] = this->CellOffsets; + allcells[2] = types; + const char *names[] = {NULL, NULL, "types"}; + + for(int t=0; tNumberOfTimeSteps; t++) + { + for(int i=0; i<3; i++) + { + if(allcells[i]) + { + cellsManager->GetElement(i).GetPosition(t) = + this->WriteDataArrayAppended(allcells[i], indent.GetNextIndent(),names[i],0,t); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + } + } + } + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return; + } + +} + +//---------------------------------------------------------------------------- +void +vtkXMLUnstructuredDataWriter::WriteCellsAppendedData(vtkCellArray* cells, + vtkDataArray* types, + int timestep, + OffsetsManagerGroup *cellsManager) +{ + this->ConvertCells(cells); + + // Split progress by cell connectivity, offset, and type arrays. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[4]; + this->CalculateCellFractions(fractions, types?types->GetNumberOfTuples():0); + + // Helper for the 'for' loop + vtkDataArray *allcells[3]; + allcells[0] = this->CellPoints; + allcells[1] = this->CellOffsets; + allcells[2] = types; + + for(int i=0; i<3; i++) + { + if(allcells[i]) + { + // Set the range of progress for the connectivity array. + this->SetProgressRange(progressRange, i, fractions); + + unsigned long mtime = allcells[i]->GetMTime(); + unsigned long &cellsMTime = cellsManager->GetElement(i).GetLastMTime(); + // Only write cells if MTime has changed + if( cellsMTime != mtime ) + { + cellsMTime = mtime; + // Write the connectivity array. + this->WriteDataArrayAppendedData(allcells[i], + cellsManager->GetElement(i).GetPosition(timestep), + cellsManager->GetElement(i).GetOffsetValue(timestep)); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + } + else + { + // One timestep must have already been written or the + // mtime would have changed and we would not be here. + assert( timestep > 0 ); + cellsManager->GetElement(i).GetOffsetValue(timestep) = + cellsManager->GetElement(i).GetOffsetValue(timestep-1); + this->ForwardAppendedDataOffset(cellsManager->GetElement(i).GetPosition(timestep), + cellsManager->GetElement(i).GetOffsetValue(timestep), + "offset" ); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::ConvertCells(vtkCellArray* cells) +{ + vtkIdTypeArray* connectivity = cells->GetData(); + vtkIdType numberOfCells = cells->GetNumberOfCells(); + vtkIdType numberOfTuples = connectivity->GetNumberOfTuples(); + + this->CellPoints->SetNumberOfTuples(numberOfTuples - numberOfCells); + this->CellOffsets->SetNumberOfTuples(numberOfCells); + + vtkIdType* inCell = connectivity->GetPointer(0); + vtkIdType* outCellPointsBase = this->CellPoints->GetPointer(0); + vtkIdType* outCellPoints = outCellPointsBase; + vtkIdType* outCellOffset = this->CellOffsets->GetPointer(0); + + vtkIdType i; + for(i=0;i < numberOfCells; ++i) + { + vtkIdType numberOfPoints = *inCell++; + memcpy(outCellPoints, inCell, sizeof(vtkIdType)*numberOfPoints); + outCellPoints += numberOfPoints; + inCell += numberOfPoints; + *outCellOffset++ = outCellPoints - outCellPointsBase; + } +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLUnstructuredDataWriter::GetNumberOfInputPoints() +{ + vtkPointSet* input = this->GetInputAsPointSet(); + vtkPoints* points = input->GetPoints(); + return points?points->GetNumberOfPoints():0; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::CalculateDataFractions(float* fractions) +{ + // Calculate the fraction of point/cell data and point + // specifications contributed by each component. + vtkPointSet* input = this->GetInputAsPointSet(); + int pdArrays = input->GetPointData()->GetNumberOfArrays(); + int cdArrays = input->GetCellData()->GetNumberOfArrays(); + vtkIdType pdSize = pdArrays*this->GetNumberOfInputPoints(); + vtkIdType cdSize = cdArrays*this->GetNumberOfInputCells(); + int total = (pdSize+cdSize+this->GetNumberOfInputPoints()); + if(total == 0) + { + total = 1; + } + fractions[0] = 0; + fractions[1] = float(pdSize)/total; + fractions[2] = float(pdSize+cdSize)/total; + fractions[3] = 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::CalculateCellFractions(float* fractions, + vtkIdType typesSize) +{ + // Calculate the fraction of cell specification data contributed by + // each of the connectivity, offset, and type arrays. + vtkIdType connectSize = this->CellPoints->GetNumberOfTuples(); + vtkIdType offsetSize = this->CellOffsets->GetNumberOfTuples(); + vtkIdType total = connectSize+offsetSize+typesSize; + if(total == 0) + { + total = 1; + } + fractions[0] = 0; + fractions[1] = float(connectSize)/total; + fractions[2] = float(connectSize+offsetSize)/total; + fractions[3] = 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredDataWriter::SetInputUpdateExtent( + int piece, int numPieces, int ghostLevel) +{ + vtkInformation* inInfo = + this->GetExecutive()->GetInputInformation(0, 0); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), numPieces); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), ghostLevel); +} + diff --git a/IO/vtkXMLUnstructuredDataWriter.h b/IO/vtkXMLUnstructuredDataWriter.h new file mode 100644 index 0000000..959796c --- /dev/null +++ b/IO/vtkXMLUnstructuredDataWriter.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredDataWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLUnstructuredDataWriter - Superclass for VTK XML unstructured data writers. +// .SECTION Description +// vtkXMLUnstructuredDataWriter provides VTK XML writing functionality +// that is common among all the unstructured data formats. + +#ifndef __vtkXMLUnstructuredDataWriter_h +#define __vtkXMLUnstructuredDataWriter_h + +#include "vtkXMLWriter.h" + +class vtkPointSet; +class vtkCellArray; +class vtkDataArray; +class vtkIdTypeArray; + +class VTK_IO_EXPORT vtkXMLUnstructuredDataWriter : public vtkXMLWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLUnstructuredDataWriter,vtkXMLWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get/Set the number of pieces used to stream the image through the + // pipeline while writing to the file. + vtkSetMacro(NumberOfPieces, int); + vtkGetMacro(NumberOfPieces, int); + + // Description: + // Get/Set the piece to write to the file. If this is + // negative or equal to the NumberOfPieces, all pieces will be written. + vtkSetMacro(WritePiece, int); + vtkGetMacro(WritePiece, int); + + // Description: + // Get/Set the ghost level used to pad each piece. + vtkSetMacro(GhostLevel, int); + vtkGetMacro(GhostLevel, int); + + // See the vtkAlgorithm for a desciption of what these do + int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkXMLUnstructuredDataWriter(); + ~vtkXMLUnstructuredDataWriter(); + + vtkPointSet* GetInputAsPointSet(); + virtual const char* GetDataSetName()=0; + virtual void SetInputUpdateExtent(int piece, int numPieces, + int ghostLevel); + + virtual int WriteHeader(); + virtual int WriteAPiece(); + virtual int WriteFooter(); + + virtual void AllocatePositionArrays(); + virtual void DeletePositionArrays(); + + virtual int WriteInlineMode(vtkIndent indent); + virtual void WriteInlinePieceAttributes(); + virtual void WriteInlinePiece(vtkIndent indent); + + virtual void WriteAppendedPieceAttributes(int index); + virtual void WriteAppendedPiece(int index, vtkIndent indent); + virtual void WriteAppendedPieceData(int index); + + void WriteCellsInline(const char* name, vtkCellArray* cells, + vtkDataArray* types, vtkIndent indent); + void WriteCellsAppended(const char* name, vtkDataArray* types, + vtkIndent indent, OffsetsManagerGroup *cellsManager); + void WriteCellsAppendedData(vtkCellArray* cells, vtkDataArray* types, + int timestep, OffsetsManagerGroup *cellsManager); + void ConvertCells(vtkCellArray* cells); + + // Get the number of points/cells. Valid after Update has been + // invoked on the input. + virtual vtkIdType GetNumberOfInputPoints(); + virtual vtkIdType GetNumberOfInputCells()=0; + void CalculateDataFractions(float* fractions); + void CalculateCellFractions(float* fractions, vtkIdType typesSize); + + // Number of pieces used for streaming. + int NumberOfPieces; + + // Which piece to write, if not all. + int WritePiece; + + // The ghost level on each piece. + int GhostLevel; + + // Positions of attributes for each piece. + unsigned long* NumberOfPointsPositions; + + // For TimeStep support + OffsetsManagerGroup *PointsOM; + OffsetsManagerArray *PointDataOM; + OffsetsManagerArray *CellDataOM; + + // Hold the new cell representation arrays while writing a piece. + vtkIdTypeArray* CellPoints; + vtkIdTypeArray* CellOffsets; + + int CurrentPiece; + +private: + vtkXMLUnstructuredDataWriter(const vtkXMLUnstructuredDataWriter&); // Not implemented. + void operator=(const vtkXMLUnstructuredDataWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLUnstructuredGridReader.cxx b/IO/vtkXMLUnstructuredGridReader.cxx new file mode 100644 index 0000000..72f7aa0 --- /dev/null +++ b/IO/vtkXMLUnstructuredGridReader.cxx @@ -0,0 +1,362 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredGridReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLUnstructuredGridReader.h" + +#include "vtkCellArray.h" +#include "vtkIdTypeArray.h" +#include "vtkObjectFactory.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLDataElement.h" +#include "vtkInformation.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkXMLUnstructuredGridReader, "$Revision: 1.12 $"); +vtkStandardNewMacro(vtkXMLUnstructuredGridReader); + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredGridReader::vtkXMLUnstructuredGridReader() +{ + // Copied from vtkUnstructuredGridReader constructor: + vtkUnstructuredGrid *output = vtkUnstructuredGrid::New(); + this->SetOutput(output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); + + this->CellElements = 0; + this->NumberOfCells = 0; + this->CellsTimeStep = -1; + this->CellsOffset = (unsigned long)-1; //almost invalid state +} + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredGridReader::~vtkXMLUnstructuredGridReader() +{ + if(this->NumberOfPieces) + { + this->DestroyPieces(); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::SetOutput(vtkUnstructuredGrid *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkXMLUnstructuredGridReader::GetOutput() +{ + return this->GetOutput(0); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkXMLUnstructuredGridReader::GetOutput(int idx) +{ + return vtkUnstructuredGrid::SafeDownCast( this->GetOutputDataObject(idx) ); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLUnstructuredGridReader::GetDataSetName() +{ + return "UnstructuredGrid"; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::GetOutputUpdateExtent(int& piece, + int& numberOfPieces, + int& ghostLevel) +{ + this->GetOutput()->GetUpdateExtent(piece, numberOfPieces, ghostLevel); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::SetupOutputTotals() +{ + this->Superclass::SetupOutputTotals(); + // Find the total size of the output. + int i; + this->TotalNumberOfCells = 0; + for(i=this->StartPiece; i < this->EndPiece; ++i) + { + this->TotalNumberOfCells += this->NumberOfCells[i]; + } + + // Data reading will start at the beginning of the output. + this->StartCell = 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::SetupPieces(int numPieces) +{ + this->Superclass::SetupPieces(numPieces); + this->NumberOfCells = new vtkIdType[numPieces]; + this->CellElements = new vtkXMLDataElement*[numPieces]; + for(int i=0;i < numPieces; ++i) + { + this->CellElements[i] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::DestroyPieces() +{ + delete [] this->CellElements; + delete [] this->NumberOfCells; + this->Superclass::DestroyPieces(); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLUnstructuredGridReader::GetNumberOfCellsInPiece(int piece) +{ + return this->NumberOfCells[piece]; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::SetupOutputData() +{ + this->Superclass::SetupOutputData(); + + vtkUnstructuredGrid* output = this->GetOutput(); + + // Setup the output's cell arrays. + vtkUnsignedCharArray* cellTypes = vtkUnsignedCharArray::New(); + cellTypes->SetNumberOfTuples(this->GetNumberOfCells()); + vtkCellArray* outCells = vtkCellArray::New(); + + vtkIdTypeArray* locations = vtkIdTypeArray::New(); + locations->SetNumberOfTuples(this->GetNumberOfCells()); + + output->SetCells(cellTypes, locations, outCells); + + locations->Delete(); + outCells->Delete(); + cellTypes->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredGridReader::ReadPiece(vtkXMLDataElement* ePiece) +{ + if(!this->Superclass::ReadPiece(ePiece)) + { + return 0; + } + int i; + + if(!ePiece->GetScalarAttribute("NumberOfCells", + this->NumberOfCells[this->Piece])) + { + vtkErrorMacro("Piece " << this->Piece + << " is missing its NumberOfCells attribute."); + this->NumberOfCells[this->Piece] = 0; + return 0; + } + + // Find the Cells element in the piece. + this->CellElements[this->Piece] = 0; + for(i=0; i < ePiece->GetNumberOfNestedElements(); ++i) + { + vtkXMLDataElement* eNested = ePiece->GetNestedElement(i); + if((strcmp(eNested->GetName(), "Cells") == 0) + && (eNested->GetNumberOfNestedElements() > 0)) + { + this->CellElements[this->Piece] = eNested; + } + } + + if(!this->CellElements[this->Piece]) + { + vtkErrorMacro("A piece is missing its Cells element."); + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridReader::SetupNextPiece() +{ + this->Superclass::SetupNextPiece(); + this->StartCell += this->NumberOfCells[this->Piece]; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredGridReader::ReadPieceData() +{ + // The amount of data read by the superclass's ReadPieceData comes + // from point/cell data and point specifications (we read cell + // specifications here). + vtkIdType superclassPieceSize = + ((this->NumberOfPointArrays+1)*this->GetNumberOfPointsInPiece(this->Piece)+ + this->NumberOfCellArrays*this->GetNumberOfCellsInPiece(this->Piece)); + + // Total amount of data in this piece comes from point/cell data + // arrays and the point/cell specifications themselves (cell + // specifications for vtkUnstructuredGrid take three data arrays). + vtkIdType totalPieceSize = + superclassPieceSize + 3*this->GetNumberOfCellsInPiece(this->Piece); + if(totalPieceSize == 0) + { + totalPieceSize = 1; + } + + // Split the progress range based on the approximate fraction of + // data that will be read by each step in this method. The cell + // specification reads two arrays, and then the cell types array is + // one more. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[4] = + { + 0, + float(superclassPieceSize) / totalPieceSize, + ((float(superclassPieceSize) + + 2*this->GetNumberOfCellsInPiece(this->Piece)) / totalPieceSize), + 1 + }; + + // Set the range of progress for the superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass read its data. + if(!this->Superclass::ReadPieceData()) + { + return 0; + } + + vtkUnstructuredGrid* output = this->GetOutput(); + + // Save the start location where the new cell connectivity will be + // appended. + vtkIdType startLoc = 0; + if(output->GetCells()->GetData()) + { + startLoc = output->GetCells()->GetData()->GetNumberOfTuples(); + } + + // Set the range of progress for the cell specifications. + this->SetProgressRange(progressRange, 1, fractions); + + // Read the Cells. + vtkXMLDataElement* eCells = this->CellElements[this->Piece]; + if(eCells) + { +// int needToRead = this->CellsNeedToReadTimeStep(eNested, +// this->CellsTimeStep, this->CellsOffset); +// if( needToRead ) + { + // Read the array. + if(!this->ReadCellArray(this->NumberOfCells[this->Piece], + this->TotalNumberOfCells, + eCells, + output->GetCells())) + { + return 0; + } + } + } + + // Construct the cell locations. + vtkIdTypeArray* locations = output->GetCellLocationsArray(); + vtkIdType* locs = locations->GetPointer(this->StartCell); + vtkIdType* begin = output->GetCells()->GetData()->GetPointer(startLoc); + vtkIdType* cur = begin; + vtkIdType i; + for(i=0; i < this->NumberOfCells[this->Piece]; ++i) + { + locs[i] = startLoc + cur - begin; + cur += *cur + 1; + } + + // Set the range of progress for the cell types. + this->SetProgressRange(progressRange, 2, fractions); + + // Read the corresponding cell types. + vtkIdType numberOfCells = this->NumberOfCells[this->Piece]; + vtkXMLDataElement* eTypes = this->FindDataArrayWithName(eCells, "types"); + if(!eTypes) + { + vtkErrorMacro("Cannot read cell types from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"types\" array could not be found."); + return 0; + } + vtkDataArray* c2 = this->CreateDataArray(eTypes); + if(!c2 || (c2->GetNumberOfComponents() != 1)) + { + vtkErrorMacro("Cannot read cell types from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"types\" array could not be created" + << " with one component."); + return 0; + } + c2->SetNumberOfTuples(numberOfCells); + if(!this->ReadData(eTypes, c2->GetVoidPointer(0), + c2->GetDataType(), 0, numberOfCells)) + { + vtkErrorMacro("Cannot read cell types from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"types\" array is not long enough."); + return 0; + } + vtkUnsignedCharArray* cellTypes = this->ConvertToUnsignedCharArray(c2); + if(!cellTypes) + { + vtkErrorMacro("Cannot read cell types from " << eCells->GetName() + << " in piece " << this->Piece + << " because the \"types\" array could not be converted" + << " to a vtkUnsignedCharArray."); + return 0; + } + + // Copy the cell type data. + memcpy(output->GetCellTypesArray()->GetPointer(this->StartCell), + cellTypes->GetPointer(0), numberOfCells); + + cellTypes->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredGridReader::ReadArrayForCells(vtkXMLDataElement* da, + vtkDataArray* outArray) +{ + vtkIdType startCell = this->StartCell; + vtkIdType numCells = this->NumberOfCells[this->Piece]; + vtkIdType components = outArray->GetNumberOfComponents(); + return this->ReadData(da, outArray->GetVoidPointer(startCell*components), + outArray->GetDataType(), 0, numCells*components); +} + + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredGridReader::FillOutputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkUnstructuredGrid"); + return 1; +} + + diff --git a/IO/vtkXMLUnstructuredGridReader.h b/IO/vtkXMLUnstructuredGridReader.h new file mode 100644 index 0000000..5e66e86 --- /dev/null +++ b/IO/vtkXMLUnstructuredGridReader.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredGridReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLUnstructuredGridReader - Read VTK XML UnstructuredGrid files. +// .SECTION Description +// vtkXMLUnstructuredGridReader reads the VTK XML UnstructuredGrid +// file format. One unstructured grid file can be read to produce one +// output. Streaming is supported. The standard extension for this +// reader's file format is "vtu". This reader is also used to read a +// single piece of the parallel file format. + +// .SECTION See Also +// vtkXMLPUnstructuredGridReader + +#ifndef __vtkXMLUnstructuredGridReader_h +#define __vtkXMLUnstructuredGridReader_h + +#include "vtkXMLUnstructuredDataReader.h" + +class vtkUnstructuredGrid; + +class VTK_IO_EXPORT vtkXMLUnstructuredGridReader : public vtkXMLUnstructuredDataReader +{ +public: + vtkTypeRevisionMacro(vtkXMLUnstructuredGridReader,vtkXMLUnstructuredDataReader); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLUnstructuredGridReader *New(); + + // Description: + // Get/Set the reader's output. + void SetOutput(vtkUnstructuredGrid *output); + vtkUnstructuredGrid *GetOutput(); + vtkUnstructuredGrid *GetOutput(int idx); + +protected: + vtkXMLUnstructuredGridReader(); + ~vtkXMLUnstructuredGridReader(); + + const char* GetDataSetName(); + void GetOutputUpdateExtent(int& piece, int& numberOfPieces, int& ghostLevel); + void SetupOutputTotals(); + void SetupPieces(int numPieces); + void DestroyPieces(); + + void SetupOutputData(); + int ReadPiece(vtkXMLDataElement* ePiece); + void SetupNextPiece(); + int ReadPieceData(); + + // Read a data array whose tuples correspond to cells. + int ReadArrayForCells(vtkXMLDataElement* da, vtkDataArray* outArray); + + // Get the number of cells in the given piece. Valid after + // UpdateInformation. + virtual vtkIdType GetNumberOfCellsInPiece(int piece); + + virtual int FillOutputPortInformation(int, vtkInformation*); + + // The index of the cell in the output where the current piece + // begins. + vtkIdType StartCell; + + // The Cells element for each piece. + vtkXMLDataElement** CellElements; + vtkIdType* NumberOfCells; + + int CellsTimeStep; + unsigned long CellsOffset; + +private: + vtkXMLUnstructuredGridReader(const vtkXMLUnstructuredGridReader&); // Not implemented. + void operator=(const vtkXMLUnstructuredGridReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLUnstructuredGridWriter.cxx b/IO/vtkXMLUnstructuredGridWriter.cxx new file mode 100644 index 0000000..6f32c87 --- /dev/null +++ b/IO/vtkXMLUnstructuredGridWriter.cxx @@ -0,0 +1,239 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredGridWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLUnstructuredGridWriter.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" +#define vtkOffsetsManager_DoNotInclude +#include "vtkOffsetsManagerArray.h" +#undef vtkOffsetsManager_DoNotInclude + +#include + +vtkCxxRevisionMacro(vtkXMLUnstructuredGridWriter, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkXMLUnstructuredGridWriter); + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredGridWriter::vtkXMLUnstructuredGridWriter() +{ + this->CellsOM = new OffsetsManagerArray; +} + +//---------------------------------------------------------------------------- +vtkXMLUnstructuredGridWriter::~vtkXMLUnstructuredGridWriter() +{ + delete this->CellsOM; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +vtkUnstructuredGrid* vtkXMLUnstructuredGridWriter::GetInput() +{ + return static_cast(this->Superclass::GetInput()); +} + +//---------------------------------------------------------------------------- +const char* vtkXMLUnstructuredGridWriter::GetDataSetName() +{ + return "UnstructuredGrid"; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLUnstructuredGridWriter::GetDefaultFileExtension() +{ + return "vtu"; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::WriteInlinePieceAttributes() +{ + this->Superclass::WriteInlinePieceAttributes(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + vtkUnstructuredGrid* input = this->GetInput(); + this->WriteScalarAttribute("NumberOfCells", input->GetNumberOfCells()); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::WriteInlinePiece(vtkIndent indent) +{ + vtkUnstructuredGrid* input = this->GetInput(); + + // Split progress range by the approximate fraction of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteInlinePiece(indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set range of progress for the cell specifications. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the cell specifications. + this->WriteCellsInline("Cells", input->GetCells(), + input->GetCellTypesArray(), indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::AllocatePositionArrays() +{ + this->Superclass::AllocatePositionArrays(); + + this->NumberOfCellsPositions = new unsigned long[this->NumberOfPieces]; + this->CellsOM->Allocate(this->NumberOfPieces,3,this->NumberOfTimeSteps); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::DeletePositionArrays() +{ + this->Superclass::DeletePositionArrays(); + + delete [] this->NumberOfCellsPositions; + this->NumberOfCellsPositions = NULL; +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::WriteAppendedPieceAttributes(int index) +{ + this->Superclass::WriteAppendedPieceAttributes(index); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->NumberOfCellsPositions[index] = + this->ReserveAttributeSpace("NumberOfCells"); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::WriteAppendedPiece(int index, + vtkIndent indent) +{ + vtkUnstructuredGrid* input = this->GetInput(); + this->Superclass::WriteAppendedPiece(index, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + this->WriteCellsAppended("Cells", input->GetCellTypesArray(), indent, + &this->CellsOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::WriteAppendedPieceData(int index) +{ + ostream& os = *(this->Stream); + vtkUnstructuredGrid* input = this->GetInput(); + + unsigned long returnPosition = os.tellp(); + os.seekp(this->NumberOfCellsPositions[index]); + this->WriteScalarAttribute("NumberOfCells", input->GetNumberOfCells()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + os.seekp(returnPosition); + + // Split progress range by the approximate fraction of data written + // by each step in this method. + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + float fractions[3]; + this->CalculateSuperclassFraction(fractions); + + // Set the range of progress for superclass. + this->SetProgressRange(progressRange, 0, fractions); + + // Let the superclass write its data. + this->Superclass::WriteAppendedPieceData(index); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return; + } + + // Set range of progress for the cell specifications. + this->SetProgressRange(progressRange, 1, fractions); + + // Write the cell specification arrays. + this->WriteCellsAppendedData( input->GetCells(), + input->GetCellTypesArray(), this->CurrentTimeIndex, + &this->CellsOM->GetPiece(index)); +} + +//---------------------------------------------------------------------------- +vtkIdType vtkXMLUnstructuredGridWriter::GetNumberOfInputCells() +{ + return this->GetInput()->GetNumberOfCells(); +} + +//---------------------------------------------------------------------------- +void vtkXMLUnstructuredGridWriter::CalculateSuperclassFraction(float* fractions) +{ + vtkUnstructuredGrid* input = this->GetInput(); + + // The superclass will write point/cell data and point specifications. + int pdArrays = input->GetPointData()->GetNumberOfArrays(); + int cdArrays = input->GetCellData()->GetNumberOfArrays(); + vtkIdType pdSize = pdArrays*this->GetNumberOfInputPoints(); + vtkIdType cdSize = cdArrays*this->GetNumberOfInputCells(); + vtkIdType pointsSize = this->GetNumberOfInputPoints(); + + // This class will write cell specifications. + vtkIdType connectSize = (input->GetCells()->GetData()->GetNumberOfTuples() - + input->GetNumberOfCells()); + vtkIdType offsetSize = input->GetNumberOfCells(); + vtkIdType typesSize = input->GetNumberOfCells(); + int total = (pdSize+cdSize+pointsSize+connectSize+offsetSize+typesSize); + if(total == 0) + { + total = 1; + } + fractions[0] = 0; + fractions[1] = float(pdSize+cdSize+pointsSize)/total; + fractions[2] = 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLUnstructuredGridWriter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} diff --git a/IO/vtkXMLUnstructuredGridWriter.h b/IO/vtkXMLUnstructuredGridWriter.h new file mode 100644 index 0000000..80f4f4b --- /dev/null +++ b/IO/vtkXMLUnstructuredGridWriter.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUnstructuredGridWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLUnstructuredGridWriter - Write VTK XML UnstructuredGrid files. +// .SECTION Description +// vtkXMLUnstructuredGridWriter writes the VTK XML UnstructuredGrid +// file format. One unstructured grid input can be written into one +// file in any number of streamed pieces (if supported by the rest of +// the pipeline). The standard extension for this writer's file +// format is "vtu". This writer is also used to write a single piece +// of the parallel file format. + +// .SECTION See Also +// vtkXMLPUnstructuredGridWriter + +#ifndef __vtkXMLUnstructuredGridWriter_h +#define __vtkXMLUnstructuredGridWriter_h + +#include "vtkXMLUnstructuredDataWriter.h" + + +class vtkUnstructuredGrid; + +class VTK_IO_EXPORT vtkXMLUnstructuredGridWriter : public vtkXMLUnstructuredDataWriter +{ +public: + vtkTypeRevisionMacro(vtkXMLUnstructuredGridWriter,vtkXMLUnstructuredDataWriter); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkXMLUnstructuredGridWriter* New(); + + //BTX + // Description: + // Get/Set the writer's input. + vtkUnstructuredGrid* GetInput(); + //ETX + + // Description: + // Get the default file extension for files written by this writer. + const char* GetDefaultFileExtension(); + +protected: + vtkXMLUnstructuredGridWriter(); + ~vtkXMLUnstructuredGridWriter(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + virtual void AllocatePositionArrays(); + virtual void DeletePositionArrays(); + + const char* GetDataSetName(); + + void WriteInlinePieceAttributes(); + void WriteInlinePiece(vtkIndent indent); + + void WriteAppendedPieceAttributes(int index); + void WriteAppendedPiece(int index, vtkIndent indent); + void WriteAppendedPieceData(int index); + + virtual vtkIdType GetNumberOfInputCells(); + void CalculateSuperclassFraction(float* fractions); + + // Positions of attributes for each piece. + unsigned long* NumberOfCellsPositions; + OffsetsManagerArray *CellsOM; //one per piece + +private: + vtkXMLUnstructuredGridWriter(const vtkXMLUnstructuredGridWriter&); // Not implemented. + void operator=(const vtkXMLUnstructuredGridWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLUtilities.cxx b/IO/vtkXMLUtilities.cxx new file mode 100644 index 0000000..58c3916 --- /dev/null +++ b/IO/vtkXMLUtilities.cxx @@ -0,0 +1,667 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUtilities.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLUtilities.h" + +#include "vtkObjectFactory.h" +#include "vtkXMLDataElement.h" +#include "vtkXMLDataParser.h" + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +#include + +typedef vtkstd::vector vtkXMLUtilitiesDataElementContainer; + +vtkStandardNewMacro(vtkXMLUtilities); +vtkCxxRevisionMacro(vtkXMLUtilities, "$Revision: 1.6 $"); + +#define VTK_XML_UTILITIES_FACTORED_POOL_NAME "FactoredPool" +#define VTK_XML_UTILITIES_FACTORED_NAME "Factored" +#define VTK_XML_UTILITIES_FACTORED_REF_NAME "FactoredRef" + +//---------------------------------------------------------------------------- +inline int vtkXMLUtilitiesEncodeEntities(unsigned char c, ostream &output) +{ + switch (c) + { + case '&': + output << "&"; + return 1; + + case '"': + output << """; + return 1; + + case '\'': + output << "'"; + return 1; + + case '<': + output << "<"; + return 1; + + case '>': + output << ">"; + return 1; + } + + return 0; +} + +//---------------------------------------------------------------------------- +void vtkXMLUtilities::EncodeString(const char *input, int input_encoding, + ostream &output, int output_encoding, + int special_entities) +{ + // No string + + if (!input) + { + return; + } + + // If either the input or output encoding is not specified, + // or they are the same, dump as is (if no entites had to be converted) + + int no_input_encoding = (input_encoding <= VTK_ENCODING_NONE || + input_encoding >= VTK_ENCODING_UNKNOWN); + + int no_output_encoding = (output_encoding <= VTK_ENCODING_NONE || + output_encoding >= VTK_ENCODING_UNKNOWN); + + if (!special_entities && + (no_input_encoding || no_output_encoding || + input_encoding == output_encoding)) + { + output << input; + return; + } + + // Convert + + const unsigned char *str = (const unsigned char*)input; + + // If either the input or output encoding is not specified, just process + // the entities + + if (no_input_encoding || no_output_encoding) + { + while (*str) + { + if (!vtkXMLUtilitiesEncodeEntities(*str, output)) + { + output << *str; + } + str++; + } + return; + } + + // To VTK_UTF_8... + + if (output_encoding == VTK_ENCODING_UTF_8) + { + int from_iso_8859 = (input_encoding >= VTK_ENCODING_ISO_8859_1 && + input_encoding <= VTK_ENCODING_ISO_8859_16); + + // From ISO-8859 or US-ASCII + + if (input_encoding == VTK_ENCODING_US_ASCII || from_iso_8859) + { + while (*str) + { + if (!special_entities || !vtkXMLUtilitiesEncodeEntities(*str, output)) + { + if (*str > 0x7F) + { +#if 0 + // This should be the right implementation, but it seems that + // it just does not work for Expat. Brad and I should dig into + // that later, but it seems weird. In the meantime, just + // output the hex representation. + + output << "&#x" + << hex << (0xC0 | (*str >> 6)) + << hex << (0x80 | (*str & 0x3F)) + << ';'; +#else + output << "&#x" << hex << (int)(*str) << ';'; +#endif + } + else if (*str < 30) + { + output << "&#x" << hex << (int)(*str) << ';'; + } + else + { + output << *str; + } + } + str++; + } + } + + // From VTK_ENCODING_UTF_8 (i.e. just encode the entities) + // To be completed (need the whole &#x) + + else if (input_encoding == VTK_ENCODING_UTF_8) + { + while (*str) + { + if (!vtkXMLUtilitiesEncodeEntities(*str, output)) + { + output << *str; + } + str++; + } + } + + // Unsupported input encoding + + else + { + vtkGenericWarningMacro( + << "Input encoding not supported (" << input_encoding << ")"); + } + } + + // From VTK_ENCODING_UTF_8... + + else if (input_encoding == VTK_ENCODING_UTF_8) + { + int to_iso_8859 = (output_encoding >= VTK_ENCODING_ISO_8859_1 && + output_encoding <=VTK_ENCODING_ISO_8859_16); + + // To US-ASCII or ISO 8859 + + if (output_encoding == VTK_ENCODING_US_ASCII || to_iso_8859) + { + while (*str) + { + if (!special_entities || !vtkXMLUtilitiesEncodeEntities(*str, output)) + { + // Multi-byte 2-chars converted into one char + + if (*str > 0x7F) + { + output << (unsigned char)((*str << 6) | (str[1] & 0x3F)); + str++; + } + else + { + output << *str; + } + } + str++; + } + } + + // Unsupported output encoding + + else + { + vtkGenericWarningMacro( + << "Output encoding not supported (" << input_encoding << ")"); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLUtilities::CollateAttributes(vtkXMLDataElement *elem, + ostream &os, + const char *sep) +{ + if (!elem) + { + return; + } + + int i, nb = elem->GetNumberOfAttributes(); + for (i = 0; i < nb; i++) + { + const char *name = elem->GetAttributeName(i); + if (name) + { + const char *value = elem->GetAttribute(name); + if (value) + { + if (i) + { + os << (sep ? sep : " "); + } + os << name << "=\""; + vtkXMLUtilities::EncodeString( + value, elem->GetAttributeEncoding(), os, VTK_ENCODING_UTF_8, 1); + os << '\"'; + } + } + } + + return; +} + +//---------------------------------------------------------------------------- +void vtkXMLUtilities::FlattenElement(vtkXMLDataElement *elem, + ostream &os, + vtkIndent *indent, + int indent_attributes) +{ + if (!elem) + { + return; + } + + unsigned long pos = os.tellp(); + + // Name + + if (indent) + { + os << *indent; + } + + os << '<' << elem->GetName(); + + // Attributes + + if (elem->GetNumberOfAttributes()) + { + os << ' '; + if (indent && indent_attributes) + { + unsigned long len = (unsigned long)os.tellp() - pos; + if (os.fail()) + { + return; + } + char *sep = new char [1 + len + 1]; + sep[0] = '\n'; + memset(sep + 1, ' ', len); + sep[len + 1] = '\0'; + vtkXMLUtilities::CollateAttributes(elem, os, sep); + delete [] sep; + } + else + { + vtkXMLUtilities::CollateAttributes(elem, os); + } + } + + // Nested elements and close + + int nb_nested = elem->GetNumberOfNestedElements(); + if (!nb_nested) + { + os << "/>"; + } + else + { + os << '>'; + if (indent) + { + os << '\n'; + } + for (int i = 0; i < nb_nested; i++) + { + if (indent) + { + vtkIndent next_indent = indent->GetNextIndent(); + vtkXMLUtilities::FlattenElement(elem->GetNestedElement(i), + os, &next_indent); + } + else + { + vtkXMLUtilities::FlattenElement(elem->GetNestedElement(i), os); + } + } + if (indent) + { + os << *indent; + } + os << "GetName() << '>'; + } + if (indent) + { + os << '\n'; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLUtilities::WriteElementToFile(vtkXMLDataElement *elem, + const char *filename, + vtkIndent *indent) +{ + if (!elem || !filename) + { + return 0; + } + + ofstream os(filename, ios::out); + vtkXMLUtilities::FlattenElement(elem, os, indent); + + os.flush(); + if (os.fail()) + { + os.close(); + unlink(filename); + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* +vtkXMLUtilities::ReadElementFromStream(istream &is, int encoding) +{ + vtkXMLDataElement *res = NULL; + vtkXMLDataParser* xml_parser = vtkXMLDataParser::New(); + xml_parser->SetAttributesEncoding(encoding); + + xml_parser->SetStream(&is); + if (xml_parser->Parse()) + { + res = xml_parser->GetRootElement(); + // Bump up the ref count since we are going to delete the parser + // which actually owns the element + res->SetReferenceCount(res->GetReferenceCount() + 1); + vtkXMLUtilities::UnFactorElements(res); + } + + xml_parser->Delete(); + return res; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* +vtkXMLUtilities::ReadElementFromString(const char *str, int encoding) +{ + if (!str) + { + return 0; + } + + strstream strstr; + strstr << str; + vtkXMLDataElement *res = + vtkXMLUtilities::ReadElementFromStream(strstr, encoding); + strstr.rdbuf()->freeze(0); + return res; +} + +//---------------------------------------------------------------------------- +vtkXMLDataElement* +vtkXMLUtilities::ReadElementFromFile(const char *filename, int encoding) +{ + if (!filename) + { + return NULL; + } + + ifstream is(filename); + return vtkXMLUtilities::ReadElementFromStream(is, encoding); +} + +//---------------------------------------------------------------------------- +void vtkXMLUtilitiesFindSimilarElementsInternal( + vtkXMLDataElement *elem, + vtkXMLDataElement *tree, + vtkXMLUtilitiesDataElementContainer *results) +{ + if (!elem || !tree || !results || elem == tree) + { + return; + } + + // If the element is equal to the current tree, append it to the + // results, otherwise check the sub-trees + + if (elem->IsEqualTo(tree)) + { + results->push_back(tree); + } + else + { + for (int i = 0; i < tree->GetNumberOfNestedElements(); i++) + { + vtkXMLUtilitiesFindSimilarElementsInternal( + elem, tree->GetNestedElement(i), results); + } + } +} + +//---------------------------------------------------------------------------- +int vtkXMLUtilities::FindSimilarElements(vtkXMLDataElement *elem, + vtkXMLDataElement *tree, + vtkXMLDataElement ***results) +{ + if (!elem || ! tree) + { + return 0; + } + + // Create a data element container, and find all similar elements + + vtkXMLUtilitiesDataElementContainer *container = + new vtkXMLUtilitiesDataElementContainer; + + vtkXMLUtilitiesFindSimilarElementsInternal(elem, tree, container); + + // If nothing was found, exit now + + int size = (int)container->size(); + if (size) + { + // Allocate an array of element and copy the contents of the container + // to this flat structure + + *results = new vtkXMLDataElement* [size]; + + size = 0; + for (vtkXMLUtilitiesDataElementContainer::const_iterator + it = container->begin(); it != container->end(); ++it) + { + if (*it) + { + (*results)[size++] = *it; + } + } + } + + delete container; + + return size; +} + +//---------------------------------------------------------------------------- +void vtkXMLUtilities::FactorElements(vtkXMLDataElement *tree) +{ + if (!tree) + { + return; + } + + // Create the factored pool, and add it to the tree so that it can + // factor itself too + + vtkXMLDataElement *pool = vtkXMLDataElement::New(); + pool->SetName(VTK_XML_UTILITIES_FACTORED_POOL_NAME); + pool->SetAttributeEncoding(tree->GetAttributeEncoding()); + tree->AddNestedElement(pool); + + // Factor the tree, as long as some factorization has occured + // (multiple pass might be needed because larger trees are factored + // first) + + while (vtkXMLUtilities::FactorElementsInternal(tree, tree, pool)) {}; + + // Nothing factored, remove the useless pool + + if (!pool->GetNumberOfNestedElements()) + { + tree->RemoveNestedElement(pool); + } + + pool->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkXMLUtilities::FactorElementsInternal(vtkXMLDataElement *tree, + vtkXMLDataElement *root, + vtkXMLDataElement *pool) +{ + if (!tree || !root || !pool) + { + return 0; + } + + // Do not bother factoring something already factored + + if (tree->GetName() && + !strcmp(tree->GetName(), VTK_XML_UTILITIES_FACTORED_REF_NAME)) + { + return 0; + } + + // Try to find all trees similar to the current tree + + vtkXMLDataElement **similar_trees; + int nb_of_similar_trees = vtkXMLUtilities::FindSimilarElements( + tree, root, &similar_trees); + + // None was found, try to factor the sub-trees + + if (!nb_of_similar_trees) + { + int res = 0; + for (int i = 0; i < tree->GetNumberOfNestedElements(); i++) + { + res += vtkXMLUtilities::FactorElementsInternal( + tree->GetNestedElement(i), root, pool); + } + return res ? 1 : 0; + } + + // Otherwise replace those trees with factored refs + + char buffer[5]; + sprintf(buffer, "%02d_", pool->GetNumberOfNestedElements()); + + ostrstream id; + id << buffer << tree->GetName() << ends; + + vtkXMLDataElement *factored = vtkXMLDataElement::New(); + factored->SetName(VTK_XML_UTILITIES_FACTORED_NAME); + factored->SetAttributeEncoding(pool->GetAttributeEncoding()); + factored->SetAttribute("Id", id.str()); + pool->AddNestedElement(factored); + factored->Delete(); + + vtkXMLDataElement *tree_copy = vtkXMLDataElement::New(); + tree_copy->DeepCopy(tree); + factored->AddNestedElement(tree_copy); + tree_copy->Delete(); + + for (int i = 0; i < nb_of_similar_trees; i++) + { + similar_trees[i]->RemoveAllAttributes(); + similar_trees[i]->RemoveAllNestedElements(); + similar_trees[i]->SetName(VTK_XML_UTILITIES_FACTORED_REF_NAME); + similar_trees[i]->SetAttribute("Id", id.str()); + } + + tree->RemoveAllAttributes(); + tree->RemoveAllNestedElements(); + tree->SetName(VTK_XML_UTILITIES_FACTORED_REF_NAME); + tree->SetAttribute("Id", id.str()); + + id.rdbuf()->freeze(0); + + delete [] similar_trees; + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLUtilities::UnFactorElements(vtkXMLDataElement *tree) +{ + if (!tree) + { + return; + } + + // Search for the factored pool, if not found, we are done + + vtkXMLDataElement *pool = tree->FindNestedElementWithName( + VTK_XML_UTILITIES_FACTORED_POOL_NAME); + if (!pool) + { + return; + } + + // Remove the pool from the tree, because it makes no sense + // unfactoring it too + + pool->Register(tree); + tree->RemoveNestedElement(pool); + + // Unfactor the tree + + vtkXMLUtilities::UnFactorElementsInternal(tree, pool); + + // Remove the useless empty pool + + pool->UnRegister(tree); +} + +//---------------------------------------------------------------------------- +int vtkXMLUtilities::UnFactorElementsInternal(vtkXMLDataElement *tree, + vtkXMLDataElement *pool) +{ + if (!tree || !pool) + { + return 0; + } + + int res = 0; + + // We found a factor, replace it with the corresponding sub-tree + + if (tree->GetName() && + !strcmp(tree->GetName(), VTK_XML_UTILITIES_FACTORED_REF_NAME)) + { + vtkXMLDataElement *original_tree = + pool->FindNestedElementWithNameAndAttribute( + VTK_XML_UTILITIES_FACTORED_NAME, "Id", tree->GetAttribute("Id")); + if (original_tree && original_tree->GetNumberOfNestedElements()) + { + tree->DeepCopy(original_tree->GetNestedElement(0)); + res++; + } + } + + // Now try to unfactor the sub-trees + + for (int i = 0; i < tree->GetNumberOfNestedElements(); i++) + { + res += vtkXMLUtilities::UnFactorElementsInternal( + tree->GetNestedElement(i), pool); + } + + return res ? 1 : 0; +} diff --git a/IO/vtkXMLUtilities.h b/IO/vtkXMLUtilities.h new file mode 100644 index 0000000..c8bea1c --- /dev/null +++ b/IO/vtkXMLUtilities.h @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLUtilities.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLUtilities - XML utilities. +// .SECTION Description +// vtkXMLUtilities provides XML-related convenience functions. +// .SECTION See Also +// vtkXMLDataElement + +#ifndef __vtkXMLUtilities_h +#define __vtkXMLUtilities_h + +#include "vtkObject.h" + +class vtkXMLDataElement; + +class VTK_IO_EXPORT vtkXMLUtilities : public vtkObject +{ +public: + static vtkXMLUtilities* New(); + vtkTypeRevisionMacro(vtkXMLUtilities, vtkObject); + + // Description: + // Encode a string from one format to another + // (see VTK_ENCODING_... constants). + // If special_entites is true, convert some characters to their corresponding + // character entities. + static void EncodeString(const char *input, int input_encoding, + ostream &output, int output_encoding, + int special_entities = 0); + + // Description: + // Collate a vtkXMLDataElement's attributes to a stream as a series of + // name="value" pairs (the separator between each pair can be specified, + // if not, it defaults to a space). + // Note that the resulting character-encoding will be UTF-8 (we assume + // that this function is used to create XML files/streams). + static void CollateAttributes(vtkXMLDataElement*, + ostream&, + const char *sep = 0); + + //BTX + // Description: + // Flatten a vtkXMLDataElement to a stream, i.e. output a textual stream + // corresponding to that XML element, its attributes and its + // nested elements. + // If 'indent' is not NULL, it is used to indent the whole tree. + // If 'indent' is not NULL and 'indent_attributes' is true, attributes will + // be indented as well. + // Note that the resulting character-encoding will be UTF-8 (we assume + // that this function is used to create XML files/streams). + static void FlattenElement(vtkXMLDataElement*, + ostream&, + vtkIndent *indent = 0, + int indent_attributes = 1); + + // Description: + // Write a vtkXMLDataElement to a file (in a flattened textual form) + // Note that the resulting character-encoding will be UTF-8. + // Return 1 on success, 0 otherwise. + static int WriteElementToFile(vtkXMLDataElement*, + const char *filename, + vtkIndent *indent = 0); + //ETX + + // Description: + // Read a vtkXMLDataElement from a stream, string or file. + // The 'encoding' parameter will be used to set the internal encoding of the + // attributes of the data elements created by those functions (conversion + // from the XML stream encoding to that new encoding will be performed + // automatically). If set to VTK_ENCODING_NONE, the encoding won't be + // changed and will default to the default vtkXMLDataElement encoding. + // Return the root element on success, NULL otherwise. + // Note that you have to call Delete() on the element returned by that + // function to ensure it is freed properly. + //BTX + static vtkXMLDataElement* ReadElementFromStream( + istream&, int encoding = VTK_ENCODING_NONE); + static vtkXMLDataElement* ReadElementFromString( + const char *str, int encoding = VTK_ENCODING_NONE); + static vtkXMLDataElement* ReadElementFromFile( + const char *filename, int encoding = VTK_ENCODING_NONE); + //ETX + + // Description: + // Find all elements in 'tree' that are similar to 'elem' (using the + // vtkXMLDataElement::IsEqualTo() predicate). + // Return the number of elements found and store those elements in + // 'results' (automatically allocated). + // Warning: the results do not include 'elem' if it was found in the tree ; + // do not forget to deallocate 'results' if something was found. + //BTX + static int FindSimilarElements(vtkXMLDataElement *elem, + vtkXMLDataElement *tree, + vtkXMLDataElement ***results); + //ETX + + // Description: + // Factor and unfactor a tree. This operation looks for duplicate elements + // in the tree, and replace them with references to a pool of elements. + // Unfactoring a non-factored element is harmless. + static void FactorElements(vtkXMLDataElement *tree); + static void UnFactorElements(vtkXMLDataElement *tree); + +protected: + vtkXMLUtilities() {}; + ~vtkXMLUtilities() {}; + + static int FactorElementsInternal(vtkXMLDataElement *tree, + vtkXMLDataElement *root, + vtkXMLDataElement *pool); + static int UnFactorElementsInternal(vtkXMLDataElement *tree, + vtkXMLDataElement *pool); + +private: + vtkXMLUtilities(const vtkXMLUtilities&); // Not implemented + void operator=(const vtkXMLUtilities&); // Not implemented +}; + +#endif + + diff --git a/IO/vtkXMLWriter.cxx b/IO/vtkXMLWriter.cxx new file mode 100644 index 0000000..7bdaec1 --- /dev/null +++ b/IO/vtkXMLWriter.cxx @@ -0,0 +1,2625 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLWriter.h" + +#include "vtkBase64OutputStream.h" +#include "vtkByteSwap.h" +#include "vtkCellData.h" +#include "vtkCommand.h" +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkOutputStream.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" +#include "vtkZLibDataCompressor.h" +#define vtkOffsetsManager_DoNotInclude +#include "vtkOffsetsManagerArray.h" +#undef vtkOffsetsManager_DoNotInclude + +#include + +#include +#include + +#if !defined(_WIN32) || defined(__CYGWIN__) +# include /* unlink */ +#else +# include /* unlink */ +#endif + +vtkCxxRevisionMacro(vtkXMLWriter, "$Revision: 1.58.2.4 $"); +vtkCxxSetObjectMacro(vtkXMLWriter, Compressor, vtkDataCompressor); + +//---------------------------------------------------------------------------- +vtkXMLWriter::vtkXMLWriter() +{ + this->FileName = 0; + this->Stream = 0; + + // Default binary data mode is base-64 encoding. + this->DataStream = vtkBase64OutputStream::New(); + + // Byte order defaults to that of machine. +#ifdef VTK_WORDS_BIGENDIAN + this->ByteOrder = vtkXMLWriter::BigEndian; +#else + this->ByteOrder = vtkXMLWriter::LittleEndian; +#endif + + // Output vtkIdType size defaults to real size. +#ifdef VTK_USE_64BIT_IDS + this->IdType = vtkXMLWriter::Int64; +#else + this->IdType = vtkXMLWriter::Int32; +#endif + + // Initialize compression data. + this->BlockSize = 32768; //2^15 + this->Compressor = vtkZLibDataCompressor::New(); + this->CompressionHeader = 0; + this->Int32IdTypeBuffer = 0; + this->ByteSwapBuffer = 0; + + this->EncodeAppendedData = 1; + this->AppendedDataPosition = 0; + this->DataMode = vtkXMLWriter::Appended; + this->ProgressRange[0] = 0; + this->ProgressRange[1] = 1; + + this->SetNumberOfOutputPorts(0); + this->SetNumberOfInputPorts(1); + + this->OutFile = 0; + + // Time support + this->TimeStep = 0; // By default the file does not have timestep + this->TimeStepRange[0] = 0; + this->TimeStepRange[1] = 0; + this->NumberOfTimeSteps = 1; + this->CurrentTimeIndex = 0; + this->UserContinueExecuting = -1; //invalid state + this->NumberOfTimeValues = NULL; + this->FieldDataOM = new OffsetsManagerGroup; +} + +//---------------------------------------------------------------------------- +vtkXMLWriter::~vtkXMLWriter() +{ + this->SetFileName(0); + this->DataStream->Delete(); + this->SetCompressor(0); + delete this->OutFile; + + delete this->FieldDataOM; + delete[] this->NumberOfTimeValues; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "FileName: " + << (this->FileName? this->FileName:"(none)") << "\n"; + if(this->ByteOrder == vtkXMLWriter::BigEndian) + { + os << indent << "ByteOrder: BigEndian\n"; + } + else + { + os << indent << "ByteOrder: LittleEndian\n"; + } + if(this->IdType == vtkXMLWriter::Int32) + { + os << indent << "IdType: Int32\n"; + } + else + { + os << indent << "IdType: Int64\n"; + } + if(this->DataMode == vtkXMLWriter::Ascii) + { + os << indent << "DataMode: Ascii\n"; + } + else if(this->DataMode == vtkXMLWriter::Binary) + { + os << indent << "DataMode: Binary\n"; + } + else + { + os << indent << "DataMode: Appended\n"; + } + if(this->Compressor) + { + os << indent << "Compressor: " << this->Compressor << "\n"; + } + else + { + os << indent << "Compressor: (none)\n"; + } + os << indent << "EncodeAppendedData: " << this->EncodeAppendedData << "\n"; + os << indent << "BlockSize: " << this->BlockSize << "\n"; + if(this->Stream) + { + os << indent << "Stream: " << this->Stream << "\n"; + } + else + { + os << indent << "Stream: (none)\n"; + } + os << indent << "TimeStep:" << this->TimeStep << "\n"; + os << indent << "NumberOfTimeSteps:" << this->NumberOfTimeSteps << "\n"; + os << indent << "TimeStepRange:(" << this->TimeStepRange[0] << "," + << this->TimeStepRange[1] << ")\n"; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetInput(vtkDataObject* input) +{ + this->SetInput(0, input); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetInput(int index, vtkDataObject* input) +{ + if(input) + { + this->SetInputConnection(index, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(index, 0); + } +} + +//---------------------------------------------------------------------------- +vtkDataObject* vtkXMLWriter::GetInput(int port) +{ + if (this->GetNumberOfInputConnections(port) < 1) + { + return 0; + } + return this->GetExecutive()->GetInputData(port, 0); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetByteOrderToBigEndian() +{ + this->SetByteOrder(vtkXMLWriter::BigEndian); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetByteOrderToLittleEndian() +{ + this->SetByteOrder(vtkXMLWriter::LittleEndian); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetIdType(int t) +{ +#if !defined(VTK_USE_64BIT_IDS) + if(t == vtkXMLWriter::Int64) + { + vtkErrorMacro("Support for Int64 vtkIdType not compiled in VTK."); + return; + } +#endif + vtkDebugMacro(<< this->GetClassName() << " (" << this + << "): setting IdType to " << t); + if(this->IdType != t) + { + this->IdType = t; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetIdTypeToInt32() +{ + this->SetIdType(vtkXMLWriter::Int32); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetIdTypeToInt64() +{ + this->SetIdType(vtkXMLWriter::Int64); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetDataModeToAscii() +{ + this->SetDataMode(vtkXMLWriter::Ascii); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetDataModeToBinary() +{ + this->SetDataMode(vtkXMLWriter::Binary); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetDataModeToAppended() +{ + this->SetDataMode(vtkXMLWriter::Appended); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetBlockSize(unsigned int blockSize) +{ + // Enforce constraints on block size. + unsigned int nbs = blockSize; +#if VTK_SIZEOF_DOUBLE > VTK_SIZEOF_ID_TYPE + typedef double LargestScalarType; +#else + typedef vtkIdType LargestScalarType; +#endif + unsigned int remainder = nbs % sizeof(LargestScalarType); + if(remainder) + { + nbs -= remainder; + if(nbs < sizeof(LargestScalarType)) + { + nbs = sizeof(LargestScalarType); + } + vtkWarningMacro("BlockSize must be a multiple of " + << int(sizeof(LargestScalarType)) + << ". Using " << nbs << " instead of " << blockSize + << "."); + } + vtkDebugMacro(<< this->GetClassName() << " (" << this + << "): setting BlockSize to " << nbs); + if(this->BlockSize != nbs) + { + this->BlockSize = nbs; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + return this->RequestData(request, inputVector, outputVector); + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + if ( inInfo->Has(vtkStreamingDemandDrivenPipeline::TIME_STEPS()) ) + { + this->NumberOfTimeSteps = + inInfo->Length( vtkStreamingDemandDrivenPipeline::TIME_STEPS() ); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::RequestData(vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ) , + vtkInformationVector* vtkNotUsed( outputVector) ) +{ + this->SetErrorCode(vtkErrorCode::NoError); + + // Make sure we have a file to write. + if(!this->Stream && !this->FileName) + { + vtkErrorMacro("Writer called with no FileName set."); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return 0; + } + + // We are just starting to write. Do not call + // UpdateProgressDiscrete because we want a 0 progress callback the + // first time. + this->UpdateProgress(0); + + // Initialize progress range to entire 0..1 range. + float wholeProgressRange[2] = {0,1}; + this->SetProgressRange(wholeProgressRange, 0, 1); + + // Check input validity and call the real writing code. + int result = this->WriteInternal(); + + // If writing failed, delete the file. + if(!result) + { + vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); + this->DeleteAFile(); + } + + // We have finished writing. + this->UpdateProgressDiscrete(1); + + return result; +} +//---------------------------------------------------------------------------- +int vtkXMLWriter::Write() +{ + // Make sure we have input. + if (this->GetNumberOfInputConnections(0) < 1) + { + vtkErrorMacro("No input provided!"); + return 0; + } + + // always write even if the data hasn't changed + this->Modified(); + + this->Update(); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::OpenFile() +{ + this->OutFile = 0; + if(this->Stream) + { + // Rewind stream to the beginning. + this->Stream->seekp(0); + } + else + { + // Try to open the output file for writing. +#ifdef _WIN32 + this->OutFile = new ofstream(this->FileName, ios::out | ios::binary); +#else + this->OutFile = new ofstream(this->FileName, ios::out); +#endif + if(!this->OutFile || !*this->OutFile) + { + vtkErrorMacro("Error opening output file \"" << this->FileName << "\""); + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + vtkErrorMacro("Error code \"" + << vtkErrorCode::GetStringFromErrorCode(this->GetErrorCode()) << "\""); + return 0; + } + this->Stream = this->OutFile; + } + + // Setup the output streams. + this->DataStream->SetStream(this->Stream); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::CloseFile() +{ + // Cleanup the output streams. + this->DataStream->SetStream(0); + + if(this->OutFile) + { + // We opened a file. Close it. + delete this->OutFile; + this->OutFile = 0; + this->Stream = 0; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteInternal() +{ + if (!this->OpenFile()) + { + return 0; + } + + // Tell the subclass to write the data. + int result = this->WriteData(); + + // if user manipulate execution don't try closing file + if( this->UserContinueExecuting != 1 ) + { + this->CloseFile(); + } + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::GetDataSetMajorVersion() +{ + return 0; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::GetDataSetMinorVersion() +{ + return 1; +} + +//---------------------------------------------------------------------------- +vtkDataSet* vtkXMLWriter::GetInputAsDataSet() +{ + return static_cast(this->GetInput()); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::StartFile() +{ + ostream& os = *(this->Stream); + + // If this will really be a valid XML file, put the XML header at + // the top. + if(this->EncodeAppendedData) + { + os << "\n"; + } + + // Open the document-level element. This will contain the rest of + // the elements. + os << "WriteFileAttributes(); + os << ">\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteFileAttributes() +{ + ostream& os = *(this->Stream); + + // Write the file's type. + this->WriteStringAttribute("type", this->GetDataSetName()); + + // Write the version number of the file. + os << " version=\"" + << this->GetDataSetMajorVersion() + << "." + << this->GetDataSetMinorVersion() + << "\""; + + // Write the byte order for the file. + if(this->ByteOrder == vtkXMLWriter::BigEndian) + { + os << " byte_order=\"BigEndian\""; + } + else + { + os << " byte_order=\"LittleEndian\""; + } + + // Write the compressor that will be used for the file. + if(this->Compressor) + { + os << " compressor=\"" << this->Compressor->GetClassName() << "\""; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::EndFile() +{ + ostream& os = *(this->Stream); + + // Close the document-level element. + os << "\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::DeleteAFile() +{ + if(!this->Stream && this->FileName) + { + this->DeleteAFile(this->FileName); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::DeleteAFile(const char* name) +{ + unlink(name); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::StartAppendedData() +{ + ostream& os = *(this->Stream); + os << " EncodeAppendedData? "base64" : "raw") + << "\">\n"; + os << " _"; + this->AppendedDataPosition = os.tellp(); + + // Setup proper output encoding. + if(this->EncodeAppendedData) + { + vtkBase64OutputStream* base64 = vtkBase64OutputStream::New(); + this->SetDataStream(base64); + base64->Delete(); + } + else + { + vtkOutputStream* raw = vtkOutputStream::New(); + this->SetDataStream(raw); + raw->Delete(); + } + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::EndAppendedData() +{ + ostream& os = *(this->Stream); + os << "\n"; + os << " \n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +unsigned long +vtkXMLWriter::ReserveAttributeSpace(const char* attr, int length) +{ + // Save the starting stream position. + ostream& os = *(this->Stream); + unsigned long startPosition = os.tellp(); + + // By default write an empty valid xml: attr="". In most case it + // will be overwritten but we guarantee that the xml produced will + // be valid in case we stop writting too early. + os << " " << attr << "=\"\""; + + // Now reserve space for the value. + for(int i=0; i < length; ++i) + { + os << " "; + } + + // Flush the stream to make sure the system tries to write now and + // test for a write error reported by the system. + os.flush(); + if(os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + + // Return the position at which to write the attribute later. + return startPosition; +} + +//---------------------------------------------------------------------------- +unsigned long vtkXMLWriter::GetAppendedDataOffset() +{ + unsigned long pos = this->Stream->tellp(); + return (pos - this->AppendedDataPosition); +} + +//---------------------------------------------------------------------------- +unsigned long vtkXMLWriter::WriteAppendedDataOffset(unsigned long streamPos, + unsigned long &lastoffset, + const char* attr) +{ + // Write an XML attribute with the given name. The value is the + // current appended data offset. Starts writing at the given stream + // position, and returns the ending position. If attr is 0, writes + // only the double quotes. In all cases, the final stream position + // is left the same as before the call. + ostream& os = *(this->Stream); + unsigned long returnPos = os.tellp(); + unsigned long offset = returnPos - this->AppendedDataPosition; + lastoffset = offset; //saving result + os.seekp(streamPos); + if(attr) + { + os << " " << attr << "="; + } + os << "\"" << offset << "\""; + unsigned long endPos = os.tellp(); + os.seekp(returnPos); + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + + return endPos; +} +//---------------------------------------------------------------------------- +unsigned long vtkXMLWriter::ForwardAppendedDataOffset(unsigned long streamPos, + unsigned long offset, + const char* attr) +{ + ostream& os = *(this->Stream); + unsigned long returnPos = os.tellp(); + os.seekp(streamPos); + if(attr) + { + os << " " << attr << "="; + } + os << "\"" << offset << "\""; + unsigned long endPos = os.tellp(); + os.seekp(returnPos); + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + + return endPos; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteBinaryData(void* data, int numWords, int wordType) +{ + unsigned long outWordSize = this->GetOutputWordTypeSize(wordType); + if(this->Compressor) + { + // Need to compress the data. Create compression header. This + // reserves enough space in the output. + if(!this->CreateCompressionHeader(numWords*outWordSize)) + { + return 0; + } + + // Start writing the data. + int result = this->DataStream->StartWriting(); + + // Process the actual data. + if(result && !this->WriteBinaryDataInternal(data, numWords, wordType)) + { + result = 0; + } + + // Finish writing the data. + if(result && !this->DataStream->EndWriting()) + { + result = 0; + } + + // Go back and write the real compression header in its proper place. + if(result && !this->WriteCompressionHeader()) + { + result = 0; + } + + // Destroy the compression header if it was used. + if(this->CompressionHeader) + { + delete [] this->CompressionHeader; + this->CompressionHeader = 0; + } + + return result; + } + else + { + // No data compression. The header is just the length of the data. + HeaderType length = numWords*outWordSize; + unsigned char* p = reinterpret_cast(&length); + this->PerformByteSwap(p, 1, sizeof(HeaderType)); + + // Start writing the data. + if(!this->DataStream->StartWriting()) + { + return 0; + } + + // Write the header consisting only of the data length. + int writeRes = this->DataStream->Write(p, sizeof(HeaderType)); + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return 0; + } + if(!writeRes) + { + return 0; + } + + // Process the actual data. + if(!this->WriteBinaryDataInternal(data, numWords, wordType)) + { + return 0; + } + + // Finish writing the data. + if(!this->DataStream->EndWriting()) + { + return 0; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteBinaryDataInternal(void* data, int numWords, + int wordType) +{ + // Break into blocks and handle each one separately. This allows + // for better random access when reading compressed data and saves + // memory during writing. + + // The size of the blocks written (before compression) is + // this->BlockSize. We need to support the possibility that the + // size of data in memory and the size on disk are different. This + // is necessary to allow vtkIdType to be converted to UInt32 for + // writing. + unsigned long memWordSize = this->GetWordTypeSize(wordType); + unsigned long outWordSize = this->GetOutputWordTypeSize(wordType); + unsigned long blockWords = this->BlockSize/outWordSize; + unsigned long memBlockSize = blockWords*memWordSize; + +#ifdef VTK_USE_64BIT_IDS + // If the type is vtkIdType, it may need to be converted to the type + // requested for output. + if((wordType == VTK_ID_TYPE) && (this->IdType == vtkXMLWriter::Int32)) + { + this->Int32IdTypeBuffer = new Int32IdType[blockWords]; + } +#endif + + // Decide if we need to byte swap. +#ifdef VTK_WORDS_BIGENDIAN + if(outWordSize > 1 && this->ByteOrder != vtkXMLWriter::BigEndian) +#else + if(outWordSize > 1 && this->ByteOrder != vtkXMLWriter::LittleEndian) +#endif + { + // We need to byte swap. Prepare a buffer large enough for one + // block. + if(this->Int32IdTypeBuffer) + { + // Just swap in-place in the converted id-type buffer. + this->ByteSwapBuffer = + reinterpret_cast(this->Int32IdTypeBuffer); + } + else + { + this->ByteSwapBuffer = new unsigned char[blockWords*outWordSize]; + } + } + + // Prepare a pointer and counter to move through the data. + unsigned char* ptr = reinterpret_cast(data); + unsigned long wordsLeft = numWords; + + // Do the complete blocks. + this->SetProgressPartial(0); + int result = 1; + while(result && (wordsLeft >= blockWords)) + { + if(!this->WriteBinaryDataBlock(ptr, blockWords, wordType)) + { + result = 0; + } + ptr += memBlockSize; + wordsLeft -= blockWords; + this->SetProgressPartial(float(numWords-wordsLeft)/numWords); + } + + // Do the last partial block if any. + if(result && (wordsLeft > 0)) + { + if(!this->WriteBinaryDataBlock(ptr, wordsLeft, wordType)) + { + result = 0; + } + } + this->SetProgressPartial(1); + + // Free the byte swap buffer if it was allocated. + if(this->ByteSwapBuffer && !this->Int32IdTypeBuffer) + { + delete [] this->ByteSwapBuffer; + this->ByteSwapBuffer = 0; + } + +#ifdef VTK_USE_64BIT_IDS + // Free the id-type conversion buffer if it was allocated. + if(this->Int32IdTypeBuffer) + { + delete [] this->Int32IdTypeBuffer; + this->Int32IdTypeBuffer = 0; + } +#endif + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteBinaryDataBlock(unsigned char* in_data, int numWords, + int wordType) +{ + unsigned char* data = in_data; +#ifdef VTK_USE_64BIT_IDS + // If the type is vtkIdType, it may need to be converted to the type + // requested for output. + if((wordType == VTK_ID_TYPE) && (this->IdType == vtkXMLWriter::Int32)) + { + vtkIdType* idBuffer = reinterpret_cast(in_data); + + int i; + for(i=0;i < numWords; ++i) + { + this->Int32IdTypeBuffer[i] = static_cast(idBuffer[i]); + } + + data = reinterpret_cast(this->Int32IdTypeBuffer); + } +#endif + + // Get the word size of the data buffer. This is now the size that + // will be written. + unsigned long wordSize = this->GetOutputWordTypeSize(wordType); + + // If we need to byte swap, do it now. + if(this->ByteSwapBuffer) + { + // If we are converting vtkIdType to 32-bit integer data, the data + // are already in the byte swap buffer because we share the + // conversion buffer. Otherwise, we need to copy the data before + // byte swapping. + if(data != this->ByteSwapBuffer) + { + memcpy(this->ByteSwapBuffer, data, numWords*wordSize); + data = this->ByteSwapBuffer; + } + this->PerformByteSwap(this->ByteSwapBuffer, numWords, wordSize); + } + + // Now pass the data to the next write phase. + if(this->Compressor) + { + int res = this->WriteCompressionBlock(data, numWords*wordSize); + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return 0; + } + return res; + } + else + { + int res = this->DataStream->Write(data, numWords*wordSize); + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return 0; + } + return res; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::PerformByteSwap(void* data, int numWords, int wordSize) +{ + char* ptr = static_cast(data); + if(this->ByteOrder == vtkXMLWriter::BigEndian) + { + switch (wordSize) + { + case 1: break; + case 2: vtkByteSwap::Swap2BERange(ptr, numWords); break; + case 4: vtkByteSwap::Swap4BERange(ptr, numWords); break; + case 8: vtkByteSwap::Swap8BERange(ptr, numWords); break; + default: + vtkErrorMacro("Unsupported data type size " << wordSize); + } + } + else + { + switch (wordSize) + { + case 1: break; + case 2: vtkByteSwap::Swap2LERange(ptr, numWords); break; + case 4: vtkByteSwap::Swap4LERange(ptr, numWords); break; + case 8: vtkByteSwap::Swap8LERange(ptr, numWords); break; + default: + vtkErrorMacro("Unsupported data type size " << wordSize); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetDataStream(vtkOutputStream* arg) +{ + if(this->DataStream != arg) + { + if(this->DataStream != NULL) + { + this->DataStream->UnRegister(this); + } + this->DataStream = arg; + if(this->DataStream != NULL) + { + this->DataStream->Register(this); + this->DataStream->SetStream(this->Stream); + } + } +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::CreateCompressionHeader(unsigned long size) +{ + // Allocate and initialize the compression header. + // The format is this: + // struct header { + // HeaderType number_of_blocks; + // HeaderType uncompressed_block_size; + // HeaderType uncompressed_last_block_size; + // HeaderType compressed_block_sizes[number_of_blocks]; + // } + + // Find the size and number of blocks. + unsigned long numFullBlocks = size / this->BlockSize; + unsigned long lastBlockSize = size % this->BlockSize; + unsigned int numBlocks = numFullBlocks + (lastBlockSize?1:0); + + unsigned int headerLength = numBlocks+3; + this->CompressionHeaderLength = headerLength; + + this->CompressionHeader = new HeaderType[headerLength]; + + // Write out dummy header data. + unsigned int i; + for(i=0; i < headerLength; ++i) { this->CompressionHeader[i] = 0; } + + this->CompressionHeaderPosition = this->Stream->tellp(); + unsigned char* ch = + reinterpret_cast(this->CompressionHeader); + unsigned int chSize = (this->CompressionHeaderLength*sizeof(HeaderType)); + + int result = (this->DataStream->StartWriting() && + this->DataStream->Write(ch, chSize) && + this->DataStream->EndWriting()); + + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return 0; + } + + // Fill in known header data now. + this->CompressionHeader[0] = numBlocks; + this->CompressionHeader[1] = this->BlockSize; + this->CompressionHeader[2] = lastBlockSize; + + // Initialize counter for block writing. + this->CompressionBlockNumber = 0; + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteCompressionBlock(unsigned char* data, + unsigned long size) +{ + // Compress the data. + vtkUnsignedCharArray* outputArray = this->Compressor->Compress(data, size); + + // Find the compressed size. + HeaderType outputSize = outputArray->GetNumberOfTuples(); + unsigned char* outputPointer = outputArray->GetPointer(0); + + // Write the compressed data. + int result = this->DataStream->Write(outputPointer, outputSize); + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + + // Store the resulting compressed size in the compression header. + this->CompressionHeader[3+this->CompressionBlockNumber++] = outputSize; + + outputArray->Delete(); + + return result; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteCompressionHeader() +{ + // Write real compression header back into stream. + unsigned long returnPosition = this->Stream->tellp(); + + // Need to byte-swap header. + this->PerformByteSwap(this->CompressionHeader, this->CompressionHeaderLength, + sizeof(HeaderType)); + + if(!this->Stream->seekp(this->CompressionHeaderPosition)) { return 0; } + unsigned char* ch = + reinterpret_cast(this->CompressionHeader); + unsigned int chSize = (this->CompressionHeaderLength*sizeof(HeaderType)); + int result = (this->DataStream->StartWriting() && + this->DataStream->Write(ch, chSize) && + this->DataStream->EndWriting()); + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return 0; + } + + if(!this->Stream->seekp(returnPosition)) { return 0; } + return result; +} + +//---------------------------------------------------------------------------- +unsigned long vtkXMLWriter::GetOutputWordTypeSize(int dataType) +{ +#ifdef VTK_USE_64BIT_IDS + // If the type is vtkIdType, it may need to be converted to the type + // requested for output. + if((dataType == VTK_ID_TYPE) && (this->IdType == vtkXMLWriter::Int32)) + { + return 4; + } +#endif + return this->GetWordTypeSize(dataType); +} + +//---------------------------------------------------------------------------- +template +unsigned long vtkXMLWriterGetWordTypeSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +unsigned long vtkXMLWriter::GetWordTypeSize(int dataType) +{ + unsigned long size = 1; + switch (dataType) + { + vtkTemplateMacro( + size = vtkXMLWriterGetWordTypeSize(static_cast(0)) + ); + default: + { vtkWarningMacro("Unsupported data type: " << dataType); } break; + } + return size; +} + +//---------------------------------------------------------------------------- +const char* vtkXMLWriter::GetWordTypeName(int dataType) +{ + char isSigned = 0; + int size = 0; + + // These string values must match vtkXMLDataElement::GetWordTypeAttribute(). + switch (dataType) + { + case VTK_FLOAT: return "Float32"; + case VTK_DOUBLE: return "Float64"; + case VTK_ID_TYPE: + { + switch (this->IdType) + { + case vtkXMLWriter::Int32: return "Int32"; + case vtkXMLWriter::Int64: return "Int64"; + default: return 0; + } + } +#if VTK_TYPE_CHAR_IS_SIGNED + case VTK_CHAR: isSigned = 1; size = sizeof(char); break; +#else + case VTK_CHAR: isSigned = 0; size = sizeof(char); break; +#endif + case VTK_INT: isSigned = 1; size = sizeof(int); break; + case VTK_LONG: isSigned = 1; size = sizeof(long); break; + case VTK_SHORT: isSigned = 1; size = sizeof(short); break; + case VTK_SIGNED_CHAR: isSigned = 1; size = sizeof(signed char); break; + case VTK_UNSIGNED_CHAR: isSigned = 0; size = sizeof(unsigned char); break; + case VTK_UNSIGNED_INT: isSigned = 0; size = sizeof(unsigned int); break; + case VTK_UNSIGNED_LONG: isSigned = 0; size = sizeof(unsigned long); break; + case VTK_UNSIGNED_SHORT: isSigned = 0; size = sizeof(unsigned short); break; +#if defined(VTK_TYPE_USE_LONG_LONG) + case VTK_LONG_LONG: isSigned = 1; size = sizeof(long long); break; + case VTK_UNSIGNED_LONG_LONG: isSigned = 0; size = sizeof(unsigned long long); break; +#endif +#if defined(VTK_TYPE_USE___INT64) + case VTK___INT64: isSigned = 1; size = sizeof(__int64); break; +# if defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE) + case VTK_UNSIGNED___INT64: isSigned = 0; size = sizeof(unsigned __int64); break; +# endif +#endif + default: + { + vtkWarningMacro("Unsupported data type: " << dataType); } break; + } + const char* type = 0; + switch (size) + { + case 1: type = isSigned? "Int8" : "UInt8"; break; + case 2: type = isSigned? "Int16" : "UInt16"; break; + case 4: type = isSigned? "Int32" : "UInt32"; break; + case 8: type = isSigned? "Int64" : "UInt64"; break; + default: + { + vtkErrorMacro("Data type size " << size + << " not supported by VTK XML format."); + } + } + return type; +} + +//---------------------------------------------------------------------------- +template +int vtkXMLWriterWriteVectorAttribute(ostream& os, const char* name, + int length, T* data) +{ + os << " " << name << "=\""; + if(length) + { + int i; + os << data[0]; + for(i=1;i < length; ++i) + { + os << " " << data[i]; + } + } + os << "\""; + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteScalarAttribute(const char* name, int data) +{ + return this->WriteVectorAttribute(name, 1, &data); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteScalarAttribute(const char* name, float data) +{ + return this->WriteVectorAttribute(name, 1, &data); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +int vtkXMLWriter::WriteScalarAttribute(const char* name, vtkIdType data) +{ + return this->WriteVectorAttribute(name, 1, &data); +} +#endif + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteVectorAttribute(const char* name, int length, + int* data) +{ + int res = + vtkXMLWriterWriteVectorAttribute(*(this->Stream), name, length, data); + + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + return res; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteVectorAttribute(const char* name, int length, + float* data) +{ + int res = + vtkXMLWriterWriteVectorAttribute(*(this->Stream), name, length, data); + + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + return res; +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteVectorAttribute(const char* name, int length, + double* data) +{ + int res = + vtkXMLWriterWriteVectorAttribute(*(this->Stream), name, length, data); + + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + return res; +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +int vtkXMLWriter::WriteVectorAttribute(const char* name, int length, + vtkIdType* data) +{ + int res = + vtkXMLWriterWriteVectorAttribute(*(this->Stream), name, length, data); + + this->Stream->flush(); + if (this->Stream->fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + return res; +} +#endif + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteDataModeAttribute(const char* name) +{ + ostream& os = *(this->Stream); + os << " " << name << "=\""; + if(this->DataMode == vtkXMLWriter::Appended) + { + os << "appended"; + } + else if(this->DataMode == vtkXMLWriter::Binary) + { + os << "binary"; + } + else + { + os << "ascii"; + } + os << "\""; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteWordTypeAttribute(const char* name, int dataType) +{ + ostream& os = *(this->Stream); + const char* value = this->GetWordTypeName(dataType); + if(!value) + { + return 0; + } + os << " " << name << "=\"" << value << "\""; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteStringAttribute(const char* name, const char* value) +{ + ostream& os = *(this->Stream); + os << " " << name << "=\"" << value << "\""; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +template +int vtkXMLWriteAsciiData(ostream& os, T* data, int length, vtkIndent indent, + long) +{ + int columns = 6; + int rows = length/columns; + int lastRowLength = length%columns; + int r,c; + int pos=0; + for(r=0;r < rows;++r) + { + os << indent << data[pos++]; + for(c=1;c < columns;++c) + { + os << " " << data[pos++]; + } + os << "\n"; + } + if(lastRowLength > 0) + { + os << indent << data[pos++]; + for(c=1;c < lastRowLength;++c) + { + os << " " << data[pos++]; + } + os << "\n"; + } + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriteAsciiData(ostream& os, char* data, int length, vtkIndent indent, + int) +{ + int columns = 6; + int rows = length/columns; + int lastRowLength = length%columns; + int r,c; + int pos=0; + for(r=0;r < rows;++r) + { + os << indent << short(data[pos++]); + for(c=1;c < columns;++c) + { + os << " " << short(data[pos++]); + } + os << "\n"; + } + if(lastRowLength > 0) + { + os << indent << short(data[pos++]); + for(c=1;c < lastRowLength;++c) + { + os << " " << short(data[pos++]); + } + os << "\n"; + } + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriteAsciiData(ostream& os, unsigned char* data, int length, + vtkIndent indent, int) +{ + int columns = 6; + int rows = length/columns; + int lastRowLength = length%columns; + int r,c; + int pos=0; + typedef unsigned short ushort; + for(r=0;r < rows;++r) + { + os << indent << ushort(data[pos++]); + for(c=1;c < columns;++c) + { + os << " " << ushort(data[pos++]); + } + os << "\n"; + } + if(lastRowLength > 0) + { + os << indent << ushort(data[pos++]); + for(c=1;c < lastRowLength;++c) + { + os << " " << ushort(data[pos++]); + } + os << "\n"; + } + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriteAsciiData(ostream& os, signed char* data, int length, + vtkIndent indent, int) +{ + int columns = 6; + int rows = length/columns; + int lastRowLength = length%columns; + int r,c; + int pos=0; + for(r=0;r < rows;++r) + { + os << indent << short(data[pos++]); + for(c=1;c < columns;++c) + { + os << " " << short(data[pos++]); + } + os << "\n"; + } + if(lastRowLength > 0) + { + os << indent << short(data[pos++]); + for(c=1;c < lastRowLength;++c) + { + os << " " << short(data[pos++]); + } + os << "\n"; + } + return (os? 1:0); +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WriteAsciiData(void* data, int numWords, int wordType, + vtkIndent indent) +{ + void* b = data; + int nw = numWords; + vtkIndent i = indent; + this->Stream->precision(11); + ostream& os = *(this->Stream); + switch(wordType) + { + vtkTemplateMacro( + return vtkXMLWriteAsciiData(os, static_cast(b), nw, i, 1) + ); + default: + return 0; + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkXMLWriter::WriteDataArrayAppended(vtkDataArray* a, + vtkIndent indent, + const char* alternateName, + int writeNumTuples, + int timestep) +{ + ostream& os = *(this->Stream); + // Write the header WriteDataArrayHeader(a,indent,alternateName, writeNumTuples, timestep); + unsigned long pos = this->ReserveAttributeSpace("offset"); + // Close the header + os << "/>\n"; + this->WriteDataArrayFooter(os, indent); + + return pos; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteDataArrayAppendedData(vtkDataArray* a, + unsigned long pos, + unsigned long &lastoffset) +{ + this->WriteAppendedDataOffset(pos, lastoffset, "offset"); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + this->WriteBinaryData(a->GetVoidPointer(0), + a->GetNumberOfTuples()*a->GetNumberOfComponents(), + a->GetDataType()); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteDataArrayHeader(vtkDataArray* a, vtkIndent indent, + const char* alternateName, + int writeNumTuples, + int timestep) +{ + ostream& os = *(this->Stream); + os << indent << "WriteWordTypeAttribute("type", a->GetDataType()); + if(alternateName) + { + this->WriteStringAttribute("Name", alternateName); + } + else if(const char* arrayName = a->GetName()) + { + this->WriteStringAttribute("Name", arrayName); + } + else + { + // Generate a name for this array. + vtksys_ios::ostringstream name; + void* p = a; + name << "Array " << p; + this->WriteStringAttribute("Name", name.str().c_str()); + } + if(a->GetNumberOfComponents() > 1) + { + this->WriteScalarAttribute("NumberOfComponents", + a->GetNumberOfComponents()); + } + if(this->NumberOfTimeSteps > 1) + { + this->WriteScalarAttribute("TimeStep", timestep); + } + else + { + //assert( timestep == -1); //FieldData problem + } + if(writeNumTuples) + { + this->WriteScalarAttribute("NumberOfTuples", + a->GetNumberOfTuples()); + } + this->WriteDataModeAttribute("format"); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteDataArrayFooter(ostream &os, vtkIndent ) +{ + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteDataArrayInline(vtkDataArray* a, vtkIndent indent, + const char* alternateName, + int writeNumTuples) +{ + ostream& os = *(this->Stream); + // Write the header WriteDataArrayHeader(a, indent, alternateName, writeNumTuples, -1); + // Close the header + os << ">\n"; + // Write the data + this->WriteInlineData(a->GetVoidPointer(0), + a->GetNumberOfTuples()*a->GetNumberOfComponents(), + a->GetDataType(), indent.GetNextIndent()); + // Close the + os << indent << "\n"; + this->WriteDataArrayFooter(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteInlineData(void* data, int numWords, int wordType, + vtkIndent indent) +{ + if(this->DataMode == vtkXMLWriter::Binary) + { + ostream& os = *(this->Stream); + os << indent; + this->WriteBinaryData(data, numWords, wordType); + os << "\n"; + } + else + { + this->WriteAsciiData(data, numWords, wordType, indent); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteFieldData(vtkIndent indent) +{ + vtkFieldData *fieldData = this->GetInput()->GetFieldData(); + if (!fieldData || !fieldData->GetNumberOfArrays()) + { + return; + } + + if(this->DataMode == vtkXMLWriter::Appended) + { + this->WriteFieldDataAppended(fieldData, indent, this->FieldDataOM); + } + else + { + // Write the point data arrays. + this->WriteFieldDataInline(fieldData, indent); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteFieldDataInline(vtkFieldData* fd, vtkIndent indent) +{ + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(fd->GetNumberOfArrays()); + + os << indent << "\n"; + + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int i; + for(i=0; i < fd->GetNumberOfArrays(); ++i) + { + this->SetProgressRange(progressRange, i, fd->GetNumberOfArrays()); + this->WriteDataArrayInline(fd->GetArray(i), indent.GetNextIndent(), + names[i], 1); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(fd->GetNumberOfArrays(), names); + return; + } + } + + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + this->DestroyStringArray(fd->GetNumberOfArrays(), names); + return; + } + + this->DestroyStringArray(fd->GetNumberOfArrays(), names); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePointDataInline(vtkPointData* pd, vtkIndent indent) +{ + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(pd->GetNumberOfArrays()); + + os << indent << "WriteAttributeIndices(pd, names); + + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(pd->GetNumberOfArrays(), names); + return; + } + + os << ">\n"; + + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int i; + for(i=0; i < pd->GetNumberOfArrays(); ++i) + { + this->SetProgressRange(progressRange, i, pd->GetNumberOfArrays()); + vtkDataArray* a = this->CreateArrayForPoints(pd->GetArray(i)); + this->WriteDataArrayInline(a, indent.GetNextIndent(), names[i]); + a->Delete(); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(pd->GetNumberOfArrays(), names); + return; + } + } + + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + this->DestroyStringArray(pd->GetNumberOfArrays(), names); + return; + } + + this->DestroyStringArray(pd->GetNumberOfArrays(), names); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteCellDataInline(vtkCellData* cd, vtkIndent indent) +{ + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(cd->GetNumberOfArrays()); + + os << indent << "WriteAttributeIndices(cd, names); + + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(cd->GetNumberOfArrays(), names); + return; + } + + os << ">\n"; + + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int i; + for(i=0; i < cd->GetNumberOfArrays(); ++i) + { + this->SetProgressRange(progressRange, i, cd->GetNumberOfArrays()); + vtkDataArray* a = this->CreateArrayForCells(cd->GetArray(i)); + this->WriteDataArrayInline(a, indent.GetNextIndent(), names[i]); + a->Delete(); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(cd->GetNumberOfArrays(), names); + return; + } + } + + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + this->DestroyStringArray(cd->GetNumberOfArrays(), names); + return; + } + + this->DestroyStringArray(cd->GetNumberOfArrays(), names); +} + + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteFieldDataAppended(vtkFieldData* fd, + vtkIndent indent, + OffsetsManagerGroup *fdManager) +{ + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(fd->GetNumberOfArrays()); + + os << indent << "\n"; + + int i; + fdManager->Allocate(fd->GetNumberOfArrays()); + for(i=0; i < fd->GetNumberOfArrays(); ++i) + { + fdManager->GetElement(i).Allocate(1); + fdManager->GetElement(i).GetPosition(0) = + this->WriteDataArrayAppended(fd->GetArray(i), + indent.GetNextIndent(), + names[i], 1 , -1); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(fd->GetNumberOfArrays(), names); + return; + } + } + os << indent << "\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + this->DestroyStringArray(fd->GetNumberOfArrays(), names); +} + + + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteFieldDataAppendedData(vtkFieldData* fd, int timestep, + OffsetsManagerGroup *fdManager) +{ + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int i; + fdManager->Allocate(fd->GetNumberOfArrays()); + for(i=0; i < fd->GetNumberOfArrays(); ++i) + { + fdManager->GetElement(i).Allocate(this->NumberOfTimeSteps); + this->SetProgressRange(progressRange, i, fd->GetNumberOfArrays()); + this->WriteDataArrayAppendedData(fd->GetArray(i), + fdManager->GetElement(i).GetPosition(timestep), + fdManager->GetElement(i).GetOffsetValue(timestep)); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + } +} + + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePointDataAppended(vtkPointData* pd, vtkIndent indent, + OffsetsManagerGroup *pdManager) +{ + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(pd->GetNumberOfArrays()); + + os << indent << "WriteAttributeIndices(pd, names); + + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(pd->GetNumberOfArrays(), names); + return; + } + + os << ">\n"; + + pdManager->Allocate(pd->GetNumberOfArrays()); + for(int i=0; i < pd->GetNumberOfArrays(); ++i) + { + pdManager->GetElement(i).Allocate(this->NumberOfTimeSteps); + for(int t=0; t< this->NumberOfTimeSteps; ++t) + { + pdManager->GetElement(i).GetPosition(t) = + this->WriteDataArrayAppended(pd->GetArray(i), + indent.GetNextIndent(), + names[i],0,t); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(pd->GetNumberOfArrays(), names); + return; + } + } + } + + os << indent << "\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + this->DestroyStringArray(pd->GetNumberOfArrays(), names); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePointDataAppendedData(vtkPointData* pd, int timestep, + OffsetsManagerGroup *pdManager) +{ + float progressRange[2] = {0,0}; + + this->GetProgressRange(progressRange); + for(int i=0; i < pd->GetNumberOfArrays(); ++i) + { + this->SetProgressRange(progressRange, i, pd->GetNumberOfArrays()); + unsigned long mtime = pd->GetMTime(); + // Only write pd if MTime has changed + unsigned long &pdMTime = pdManager->GetElement(i).GetLastMTime(); + if( pdMTime != mtime ) + { + pdMTime = mtime; + vtkDataArray* a = this->CreateArrayForPoints(pd->GetArray(i)); + this->WriteDataArrayAppendedData(a, pdManager->GetElement(i).GetPosition(timestep), + pdManager->GetElement(i).GetOffsetValue(timestep)); + a->Delete(); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + } + else + { + assert( timestep > 0 ); + pdManager->GetElement(i).GetOffsetValue(timestep) = + pdManager->GetElement(i).GetOffsetValue(timestep-1); + this->ForwardAppendedDataOffset(pdManager->GetElement(i).GetPosition(timestep), + pdManager->GetElement(i).GetOffsetValue(timestep), + "offset" ); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteCellDataAppended(vtkCellData* cd, vtkIndent indent, + OffsetsManagerGroup *cdManager) +{ + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(cd->GetNumberOfArrays()); + + os << indent << "WriteAttributeIndices(cd, names); + + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(cd->GetNumberOfArrays(), names); + return; + } + + os << ">\n"; + + cdManager->Allocate(cd->GetNumberOfArrays()); + for(int i=0; i < cd->GetNumberOfArrays(); ++i) + { + cdManager->GetElement(i).Allocate(this->NumberOfTimeSteps); + for(int t=0; t< this->NumberOfTimeSteps; ++t) + { + cdManager->GetElement(i).GetPosition(t) = + this->WriteDataArrayAppended(cd->GetArray(i), + indent.GetNextIndent(), + names[i],0,t); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(cd->GetNumberOfArrays(), names); + return; + } + } + } + + os << indent << "\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + this->DestroyStringArray(cd->GetNumberOfArrays(), names); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteCellDataAppendedData(vtkCellData* cd, int timestep, + OffsetsManagerGroup *cdManager) +{ + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + int i; + for(i=0; i < cd->GetNumberOfArrays(); ++i) + { + this->SetProgressRange(progressRange, i, cd->GetNumberOfArrays()); + unsigned long mtime = cd->GetMTime(); + // Only write pd if MTime has changed + unsigned long &cdMTime = cdManager->GetElement(i).GetLastMTime(); + if( cdMTime != mtime ) + { + cdMTime = mtime; + vtkDataArray* a = this->CreateArrayForCells(cd->GetArray(i)); + this->WriteDataArrayAppendedData(a, cdManager->GetElement(i).GetPosition(timestep), + cdManager->GetElement(i).GetOffsetValue(timestep)); + a->Delete(); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + } + else + { + assert( timestep > 0 ); + cdManager->GetElement(i).GetOffsetValue(timestep) = + cdManager->GetElement(i).GetOffsetValue(timestep-1); + this->ForwardAppendedDataOffset( + cdManager->GetElement(i).GetPosition(timestep), + cdManager->GetElement(i).GetOffsetValue(timestep), + "offset" ); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteAttributeIndices(vtkDataSetAttributes* dsa, + char** names) +{ + int i; + int attributeIndices[vtkDataSetAttributes::NUM_ATTRIBUTES]; + dsa->GetAttributeIndices(attributeIndices); + for(i=0;i < vtkDataSetAttributes::NUM_ATTRIBUTES;++i) + { + if(attributeIndices[i] >= 0) + { + const char* attrName = dsa->GetAttributeTypeAsString(i); + vtkDataArray* a = dsa->GetArray(attributeIndices[i]); + const char* arrayName = a->GetName(); + if(!arrayName) + { + // Assign a name to the array. + names[attributeIndices[i]] = new char[strlen(attrName)+2]; + strcpy(names[attributeIndices[i]], attrName); + strcat(names[attributeIndices[i]], "_"); + arrayName = names[attributeIndices[i]]; + } + this->WriteStringAttribute(attrName, arrayName); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePointsAppended(vtkPoints* points, vtkIndent indent, + OffsetsManager *ptManager) +{ + ostream& os = *(this->Stream); + + // Only write points if they exist. + os << indent << "\n"; + if(points) + { + for(int t=0; t< this->NumberOfTimeSteps; ++t) + { + ptManager->GetPosition(t) = + this->WriteDataArrayAppended(points->GetData(), indent.GetNextIndent(),0,0,t); + } + } + os << indent << "\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePointsAppendedData(vtkPoints* points, int timestep, + OffsetsManager *ptManager) +{ + // Only write points if they exist. + if(points) + { + unsigned long mtime = points->GetMTime(); + // Only write points if MTime has changed + unsigned long &pointsMTime = ptManager->GetLastMTime(); + if( pointsMTime != mtime ) + { + pointsMTime = mtime; + vtkDataArray* outPoints = this->CreateArrayForPoints(points->GetData()); + this->WriteDataArrayAppendedData(outPoints, ptManager->GetPosition(timestep), + ptManager->GetOffsetValue(timestep)); + outPoints->Delete(); + } + else + { + assert( timestep > 0 ); + ptManager->GetOffsetValue(timestep) = ptManager->GetOffsetValue(timestep-1); + this->ForwardAppendedDataOffset( + ptManager->GetPosition(timestep), + ptManager->GetOffsetValue(timestep), "offset"); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePointsInline(vtkPoints* points, vtkIndent indent) +{ + ostream& os = *(this->Stream); + // Only write points if they exist. + os << indent << "\n"; + if(points) + { + vtkDataArray* outPoints = this->CreateArrayForPoints(points->GetData()); + this->WriteDataArrayInline(outPoints, indent.GetNextIndent()); + outPoints->Delete(); + } + os << indent << "\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteCoordinatesInline(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, vtkIndent indent) +{ + ostream& os = *(this->Stream); + + // Only write coordinates if they exist. + os << indent << "\n"; + if(xc && yc && zc) + { + vtkDataArray* oxc = this->CreateExactCoordinates(xc, 0); + vtkDataArray* oyc = this->CreateExactCoordinates(yc, 1); + vtkDataArray* ozc = this->CreateExactCoordinates(zc, 2); + + // Split progress over the three coordinates arrays. + vtkIdType total = (oxc->GetNumberOfTuples()+ + oyc->GetNumberOfTuples()+ + ozc->GetNumberOfTuples()); + if(total == 0) + { + total = 1; + } + float fractions[4] = + { + 0, + float(oxc->GetNumberOfTuples()) / total, + float(oxc->GetNumberOfTuples()+oyc->GetNumberOfTuples()) / total, + 1 + }; + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + this->SetProgressRange(progressRange, 0, fractions); + this->WriteDataArrayInline(oxc, indent.GetNextIndent()); + if (this->ErrorCode != vtkErrorCode::NoError) + { + oxc->Delete(); + oyc->Delete(); + ozc->Delete(); + return; + } + + this->SetProgressRange(progressRange, 1, fractions); + this->WriteDataArrayInline(oyc, indent.GetNextIndent()); + if (this->ErrorCode != vtkErrorCode::NoError) + { + oxc->Delete(); + oyc->Delete(); + ozc->Delete(); + return; + } + + this->SetProgressRange(progressRange, 2, fractions); + this->WriteDataArrayInline(ozc, indent.GetNextIndent()); + if (this->ErrorCode != vtkErrorCode::NoError) + { + oxc->Delete(); + oyc->Delete(); + ozc->Delete(); + return; + } + + oxc->Delete(); + oyc->Delete(); + ozc->Delete(); + } + os << indent << "\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + return; + } +} + +//---------------------------------------------------------------------------- +void +vtkXMLWriter::WriteCoordinatesAppended(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, vtkIndent indent, + OffsetsManagerGroup *coordManager) +{ + ostream& os = *(this->Stream); + + // Helper for the 'for' loop + vtkDataArray *allcoords[3]; + allcoords[0] = xc; + allcoords[1] = yc; + allcoords[2] = zc; + + // Only write coordinates if they exist. + os << indent << "\n"; + coordManager->Allocate(3); + if(xc && yc && zc) + { + for(int i=0; i<3; ++i) + { + coordManager->GetElement(i).Allocate(this->NumberOfTimeSteps); + for(int t=0; tNumberOfTimeSteps; ++t) + { + coordManager->GetElement(i).GetPosition(t) = + this->WriteDataArrayAppended(allcoords[i], indent.GetNextIndent()); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return ; + } + } + } + } + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteCoordinatesAppendedData(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, int timestep, + OffsetsManagerGroup *coordManager) +{ + // Only write coordinates if they exist. + if(xc && yc && zc) + { + vtkDataArray* oxc = this->CreateExactCoordinates(xc, 0); + vtkDataArray* oyc = this->CreateExactCoordinates(yc, 1); + vtkDataArray* ozc = this->CreateExactCoordinates(zc, 2); + + // Split progress over the three coordinates arrays. + vtkIdType total = (oxc->GetNumberOfTuples()+ + oyc->GetNumberOfTuples()+ + ozc->GetNumberOfTuples()); + if(total == 0) + { + total = 1; + } + float fractions[4] = + { + 0, + float(oxc->GetNumberOfTuples()) / total, + float(oxc->GetNumberOfTuples()+oyc->GetNumberOfTuples()) / total, + 1 + }; + float progressRange[2] = {0,0}; + this->GetProgressRange(progressRange); + + // Helper for the 'for' loop + vtkDataArray *allcoords[3]; + allcoords[0] = oxc; + allcoords[1] = oyc; + allcoords[2] = ozc; + + for(int i=0; i<3; ++i) + { + this->SetProgressRange(progressRange, i, fractions); + unsigned long mtime = allcoords[i]->GetMTime(); + // Only write pd if MTime has changed + unsigned long &coordMTime = coordManager->GetElement(i).GetLastMTime(); + if( coordMTime != mtime ) + { + coordMTime = mtime; + this->WriteDataArrayAppendedData(allcoords[i], + coordManager->GetElement(i).GetPosition(timestep), + coordManager->GetElement(i).GetOffsetValue(timestep)); + if (this->ErrorCode != vtkErrorCode::NoError) + { + oxc->Delete(); + oyc->Delete(); + ozc->Delete(); + return; + } + } + else + { + } + } + + oxc->Delete(); + oyc->Delete(); + ozc->Delete(); + } +} + +//---------------------------------------------------------------------------- +vtkDataArray* vtkXMLWriter::CreateArrayForPoints(vtkDataArray* inArray) +{ + // Only some subclasses need to do anything. By default, just + // return the array as given. + inArray->Register(0); + return inArray; +} + +//---------------------------------------------------------------------------- +vtkDataArray* vtkXMLWriter::CreateArrayForCells(vtkDataArray* inArray) +{ + // Only some subclasses need to do anything. By default, just + // return the array as given. + inArray->Register(0); + return inArray; +} + +//---------------------------------------------------------------------------- +vtkDataArray* vtkXMLWriter::CreateExactCoordinates(vtkDataArray* inArray, int) +{ + // This method is just a dummy because we don't want a pure virtual. + // Subclasses that need it should define the real version. + vtkErrorMacro("vtkXMLWriter::CreateExactCoordinates should never be called."); + inArray->Register(0); + return inArray; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePPointData(vtkPointData* pd, vtkIndent indent) +{ + if(pd->GetNumberOfArrays() == 0) + { + return; + } + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(pd->GetNumberOfArrays()); + + os << indent << "WriteAttributeIndices(pd, names); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(pd->GetNumberOfArrays(), names); + return; + } + os << ">\n"; + + int i; + for(i=0; i < pd->GetNumberOfArrays(); ++i) + { + this->WritePDataArray(pd->GetArray(i), indent.GetNextIndent(), names[i]); + if (this->ErrorCode != vtkErrorCode::NoError) + { + this->DestroyStringArray(pd->GetNumberOfArrays(), names); + return; + } + } + + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } + + this->DestroyStringArray(pd->GetNumberOfArrays(), names); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePCellData(vtkCellData* cd, vtkIndent indent) +{ + if(cd->GetNumberOfArrays() == 0) + { + return; + } + ostream& os = *(this->Stream); + char** names = this->CreateStringArray(cd->GetNumberOfArrays()); + + os << indent << "WriteAttributeIndices(cd, names); + os << ">\n"; + + int i; + for(i=0; i < cd->GetNumberOfArrays(); ++i) + { + this->WritePDataArray(cd->GetArray(i), indent.GetNextIndent(), names[i]); + } + + os << indent << "\n"; + + this->DestroyStringArray(cd->GetNumberOfArrays(), names); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePPoints(vtkPoints* points, vtkIndent indent) +{ + ostream& os = *(this->Stream); + // Only write points if they exist. + os << indent << "\n"; + if(points) + { + this->WritePDataArray(points->GetData(), indent.GetNextIndent()); + } + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePDataArray(vtkDataArray* a, vtkIndent indent, + const char* alternateName) +{ + ostream& os = *(this->Stream); + os << indent << "WriteWordTypeAttribute("type", a->GetDataType()); + if(alternateName) + { + this->WriteStringAttribute("Name", alternateName); + } + else + { + const char* arrayName = a->GetName(); + if(arrayName) + { + this->WriteStringAttribute("Name", arrayName); + } + } + if(a->GetNumberOfComponents() > 1) + { + this->WriteScalarAttribute("NumberOfComponents", + a->GetNumberOfComponents()); + } + os << "/>\n"; + + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePCoordinates(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, vtkIndent indent) +{ + ostream& os = *(this->Stream); + + // Only write coordinates if they exist. + os << indent << "\n"; + if(xc && yc && zc) + { + this->WritePDataArray(xc, indent.GetNextIndent()); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + this->WritePDataArray(yc, indent.GetNextIndent()); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + this->WritePDataArray(zc, indent.GetNextIndent()); + if (this->ErrorCode != vtkErrorCode::NoError) + { + return; + } + } + os << indent << "\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::GetLastSystemError()); + } +} + +//---------------------------------------------------------------------------- +char** vtkXMLWriter::CreateStringArray(int numStrings) +{ + char** strings = new char*[numStrings]; + int i; + for(i=0; i < numStrings; ++i) + { + strings[i] = 0; + } + return strings; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::DestroyStringArray(int numStrings, char** strings) +{ + int i; + for(i=0; i < numStrings; ++i) + { + if(strings[i]) + { + delete [] strings[i]; + } + } + delete [] strings; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::GetProgressRange(float* range) +{ + range[0] = this->ProgressRange[0]; + range[1] = this->ProgressRange[1]; +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetProgressRange(float* range, int curStep, int numSteps) +{ + float stepSize = (range[1] - range[0])/numSteps; + this->ProgressRange[0] = range[0] + stepSize*curStep; + this->ProgressRange[1] = range[0] + stepSize*(curStep+1); + this->UpdateProgressDiscrete(this->ProgressRange[0]); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetProgressRange(float* range, int curStep, + float* fractions) +{ + float width = range[1] - range[0]; + this->ProgressRange[0] = range[0] + fractions[curStep]*width; + this->ProgressRange[1] = range[0] + fractions[curStep+1]*width; + this->UpdateProgressDiscrete(this->ProgressRange[0]); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::SetProgressPartial(float fraction) +{ + float width = this->ProgressRange[1] - this->ProgressRange[0]; + this->UpdateProgressDiscrete(this->ProgressRange[0] + fraction*width); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::UpdateProgressDiscrete(float progress) +{ + if(!this->AbortExecute) + { + // Round progress to nearest 100th. + float rounded = float(int((progress*100)+0.5))/100; + if(this->GetProgress() != rounded) + { + this->UpdateProgress(rounded); + } + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WritePrimaryElementAttributes(ostream &os, vtkIndent indent) +{ + // Write the time step if any: + if( this->NumberOfTimeSteps > 1) + { + // First thing allocate NumberOfTimeValues + assert( this->NumberOfTimeValues == NULL ); + this->NumberOfTimeValues = new unsigned long[this->NumberOfTimeSteps]; + os << indent << "TimeValues=\"\n"; + + vtkstd::string blankline = vtkstd::string(40, ' '); //enough room for precision + for(int i=0; iNumberOfTimeSteps; i++) + { + this->NumberOfTimeValues[i] = os.tellp(); + os << blankline.c_str() << "\n"; + } + os << "\""; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLWriter::WritePrimaryElement(ostream &os, vtkIndent indent) +{ + // Open the primary element. + os << indent << "<" << this->GetDataSetName(); + + this->WritePrimaryElementAttributes(os,indent); + + // Close the primary element: + os << ">\n"; + os.flush(); + if (os.fail()) + { + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + return 1; +} + +// The following function are designed to be called outside of the VTK pipeline +// typically from a C interface or when ParaView want to control the writing +//---------------------------------------------------------------------------- +void vtkXMLWriter::Start() +{ + // Make sure we have input. + if (this->GetNumberOfInputConnections(0) < 1) + { + vtkErrorMacro("No input provided!"); + return; + } + this->UserContinueExecuting = 1; +} + +//---------------------------------------------------------------------------- +// The function does not make sense in the general case but we need to handle +// the case where the simulation stop before reaching the number of steps +// specified by the user. Therefore the CurrentTimeIndex is never equal +// to NumberOfTimeStep and thus we need to force closing of the xml file +void vtkXMLWriter::Stop() +{ + this->UserContinueExecuting = 0; + this->Modified(); + this->Update(); + this->UserContinueExecuting = -1; //put back the writer in initial state +} + +//---------------------------------------------------------------------------- +void vtkXMLWriter::WriteNextTime(double time) +{ + this->Modified(); + this->Update(); + + ostream& os = *(this->Stream); + + if (this->NumberOfTimeValues) + { + // Write user specified time value in the TimeValues attribute + unsigned long returnPos = os.tellp(); + os.seekp(this->NumberOfTimeValues[this->CurrentTimeIndex-1]); + os << time; + os.seekp(returnPos); + } +} + + diff --git a/IO/vtkXMLWriter.h b/IO/vtkXMLWriter.h new file mode 100644 index 0000000..75b41b7 --- /dev/null +++ b/IO/vtkXMLWriter.h @@ -0,0 +1,452 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMLWriter - Superclass for VTK's XML file writers. +// .SECTION Description +// vtkXMLWriter provides methods implementing most of the +// functionality needed to write VTK XML file formats. Concrete +// subclasses provide actual writer implementations calling upon this +// functionality. + +#ifndef __vtkXMLWriter_h +#define __vtkXMLWriter_h + +#include "vtkAlgorithm.h" + +class vtkCellData; +class vtkDataArray; +class vtkDataCompressor; +class vtkDataSet; +class vtkDataSetAttributes; +class vtkOutputStream; +class vtkPointData; +class vtkPoints; +class vtkFieldData; +//BTX +class OffsetsManager; // one per piece/per time +class OffsetsManagerGroup; // array of OffsetsManager +class OffsetsManagerArray; // array of OffsetsManagerGroup +//ETX + +class VTK_IO_EXPORT vtkXMLWriter : public vtkAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkXMLWriter,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + // Description: + // Enumerate big and little endian byte order settings. + enum { BigEndian, LittleEndian }; + //ETX + + //BTX + // Description: + // Enumerate the supported data modes. + // Ascii = Inline ascii data. + // Binary = Inline binary data (base64 encoded, possibly compressed). + // Appended = Appended binary data (possibly compressed and/or base64). + enum { Ascii, Binary, Appended }; + //ETX + + //BTX + // Description: + // Enumerate the supported vtkIdType bit lengths. + // Int32 = File stores 32-bit values for vtkIdType. + // Int64 = File stores 64-bit values for vtkIdType. + enum { Int32=32, Int64=64 }; + //ETX + + // Description: + // Get/Set the byte order of data written to the file. The default + // is the machine's hardware byte order. + vtkSetMacro(ByteOrder, int); + vtkGetMacro(ByteOrder, int); + void SetByteOrderToBigEndian(); + void SetByteOrderToLittleEndian(); + + // Description: + // Get/Set the size of the vtkIdType values stored in the file. The + // default is the real size of vtkIdType. + virtual void SetIdType(int); + vtkGetMacro(IdType, int); + void SetIdTypeToInt32(); + void SetIdTypeToInt64(); + + // Description: + // Get/Set the name of the output file. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Get/Set the compressor used to compress binary and appended data + // before writing to the file. Default is no compression. + virtual void SetCompressor(vtkDataCompressor*); + vtkGetObjectMacro(Compressor, vtkDataCompressor); + + // Description: + // Get/Set the block size used in compression. When reading, this + // controls the granularity of how much extra information must be + // read when only part of the data are requested. The value should + // be a multiple of the largest scalar data type. + virtual void SetBlockSize(unsigned int blockSize); + vtkGetMacro(BlockSize, unsigned int); + + // Description: + // Get/Set the data mode used for the file's data. The options are + // vtkXMLWriter::Ascii, vtkXMLWriter::Binary, and + // vtkXMLWriter::Appended. + vtkSetMacro(DataMode, int); + vtkGetMacro(DataMode, int); + void SetDataModeToAscii(); + void SetDataModeToBinary(); + void SetDataModeToAppended(); + + // Description: + // Get/Set whether the appended data section is base64 encoded. If + // encoded, reading and writing will be slower, but the file will be + // fully valid XML and text-only. If not encoded, the XML + // specification will be violated, but reading and writing will be + // fast. The default is to do the encoding. + vtkSetMacro(EncodeAppendedData, int); + vtkGetMacro(EncodeAppendedData, int); + vtkBooleanMacro(EncodeAppendedData, int); + + // Description: + // Set/Get an input of this algorithm. You should not override these + // methods because they are not the only way to connect a pipeline + void SetInput(vtkDataObject *); + void SetInput(int, vtkDataObject*); + vtkDataObject *GetInput(int port); + vtkDataObject *GetInput() { return this->GetInput(0); }; + + // Description: + // Get the default file extension for files written by this writer. + virtual const char* GetDefaultFileExtension()=0; + + // Description: + // Invoke the writer. Returns 1 for success, 0 for failure. + int Write(); + + // See the vtkAlgorithm for a description of what these do + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Description: + // Which TimeStep to write. + vtkSetMacro(TimeStep, int); + vtkGetMacro(TimeStep, int); + + // Description: + // Which TimeStepRange to write. + vtkGetVector2Macro(TimeStepRange, int); + vtkSetVector2Macro(TimeStepRange, int); + + // Description: + // Set the number of time steps + vtkGetMacro(NumberOfTimeSteps,int); + vtkSetMacro(NumberOfTimeSteps,int); + + // Description: + // API to interface an outside the VTK pipeline control + void Start(); + void Stop(); + void WriteNextTime(double time); + +protected: + vtkXMLWriter(); + ~vtkXMLWriter(); + + virtual int RequestInformation( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // The name of the output file. + char* FileName; + + // The output stream to which the XML is written. + ostream* Stream; + + // The output byte order. + int ByteOrder; + + // The output vtkIdType. + int IdType; + + // The form of binary data to write. Used by subclasses to choose + // how to write data. + int DataMode; + + // Whether to base64-encode the appended data section. + int EncodeAppendedData; + + // The stream position at which appended data starts. + unsigned long AppendedDataPosition; + + // appended data offsets for field data + OffsetsManagerGroup *FieldDataOM; //one per array + + //BTX + // We need a 32 bit unsigned integer type for platform-independent + // binary headers. Note that this is duplicated in + // vtkXMLDataParser.h. +#if VTK_SIZEOF_SHORT == 4 + typedef unsigned short HeaderType; +#elif VTK_SIZEOF_INT == 4 + typedef unsigned int HeaderType; +#elif VTK_SIZEOF_LONG == 4 + typedef unsigned long HeaderType; +#else +# error "No native data type can represent an unsigned 32-bit integer." +#endif + //ETX + + //BTX + // We need a 32 bit signed integer type to which vtkIdType will be + // converted if Int32 is specified for the IdType parameter to this + // writer. +# if VTK_SIZEOF_SHORT == 4 + typedef short Int32IdType; +# elif VTK_SIZEOF_INT == 4 + typedef int Int32IdType; +# elif VTK_SIZEOF_LONG == 4 + typedef long Int32IdType; +# else +# error "No native data type can represent a signed 32-bit integer." +# endif + //ETX + + // Buffer for vtkIdType conversion. + Int32IdType* Int32IdTypeBuffer; + + // The byte swapping buffer. + unsigned char* ByteSwapBuffer; + + // Compression information. + vtkDataCompressor* Compressor; + unsigned int BlockSize; + unsigned long CompressionBlockNumber; + HeaderType* CompressionHeader; + unsigned int CompressionHeaderLength; + unsigned long CompressionHeaderPosition; + + // The output stream used to write binary and appended data. May + // transparently encode the data. + vtkOutputStream* DataStream; + + // Allow subclasses to set the data stream. + virtual void SetDataStream(vtkOutputStream*); + vtkGetObjectMacro(DataStream, vtkOutputStream); + + // Method to drive most of actual writing. + virtual int WriteInternal(); + + // Method defined by subclasses to write data. Return 1 for + // success, 0 for failure. + virtual int WriteData() {return 1;}; + + // Method defined by subclasses to specify the data set's type name. + virtual const char* GetDataSetName()=0; + + // Methods to define the file's major and minor version numbers. + virtual int GetDataSetMajorVersion(); + virtual int GetDataSetMinorVersion(); + + // Utility methods for subclasses. + vtkDataSet* GetInputAsDataSet(); + int StartFile(); + virtual void WriteFileAttributes(); + int EndFile(); + void DeleteAFile(); + void DeleteAFile(const char* name); + + virtual int WritePrimaryElement(ostream &os, vtkIndent indent); + virtual void WritePrimaryElementAttributes(ostream &os, vtkIndent indent); + void StartAppendedData(); + void EndAppendedData(); + + // Write enough space to go back and write the given attribute with + // at most "length" characters in the value. Returns the stream + // position at which attribute should be later written. The default + // length of 20 is enough for a 64-bit integer written in decimal or + // a double-precision floating point value written to 13 digits of + // precision (the other 7 come from a minus sign, decimal place, and + // a big exponent like "e+300"). + unsigned long ReserveAttributeSpace(const char* attr, int length=20); + + unsigned long GetAppendedDataOffset(); + unsigned long WriteAppendedDataOffset(unsigned long streamPos, + unsigned long &lastoffset, + const char* attr=0); + unsigned long ForwardAppendedDataOffset(unsigned long streamPos, + unsigned long offset, + const char* attr=0); + int WriteBinaryData(void* data, int numWords, int wordType); + + int WriteBinaryData(char* data) + { return this->WriteBinaryData(data, static_cast(strlen(data)), + VTK_CHAR); } + int WriteBinaryData(char* data, int numWords) + { return this->WriteBinaryData(data, numWords, VTK_CHAR); } + int WriteBinaryData(unsigned char* data, int numWords) + { return this->WriteBinaryData(data, numWords, VTK_UNSIGNED_CHAR); } + int WriteBinaryData(short* data, int numWords) + { return this->WriteBinaryData(data, numWords, VTK_SHORT); } + int WriteBinaryData(unsigned short* data, int numWords) + { return this->WriteBinaryData(data, numWords, VTK_UNSIGNED_SHORT); } + int WriteBinaryData(int* data, int numWords) + { return this->WriteBinaryData(data, numWords, VTK_INT); } + int WriteBinaryData(unsigned int* data, int numWords) + { return this->WriteBinaryData(data, numWords, VTK_UNSIGNED_INT); } + + int WriteAsciiData(void* data, int numWords, int wordType, vtkIndent indent); + + int WriteAsciiData(char* data, vtkIndent indent) + { return this->WriteAsciiData(data, static_cast(strlen(data)), + VTK_CHAR, indent); } + int WriteAsciiData(char* data, int numWords, vtkIndent indent) + { return this->WriteAsciiData(data, numWords, VTK_CHAR, indent); } + int WriteAsciiData(unsigned char* data, int numWords, vtkIndent indent) + { return this->WriteAsciiData(data, numWords, VTK_UNSIGNED_CHAR, indent); } + int WriteAsciiData(short* data, int numWords, vtkIndent indent) + { return this->WriteAsciiData(data, numWords, VTK_SHORT, indent); } + int WriteAsciiData(unsigned short* data, int numWords, vtkIndent indent) + { return this->WriteAsciiData(data, numWords, VTK_UNSIGNED_SHORT, indent); } + int WriteAsciiData(int* data, int numWords, vtkIndent indent) + { return this->WriteAsciiData(data, numWords, VTK_INT, indent); } + int WriteAsciiData(unsigned int* data, int numWords, vtkIndent indent) + { return this->WriteAsciiData(data, numWords, VTK_UNSIGNED_INT, indent); } + + int WriteScalarAttribute(const char* name, int data); + int WriteScalarAttribute(const char* name, float data); +#ifdef VTK_USE_64BIT_IDS + int WriteScalarAttribute(const char* name, vtkIdType data); +#endif + + int WriteVectorAttribute(const char* name, int length, int* data); + int WriteVectorAttribute(const char* name, int length, float* data); + int WriteVectorAttribute(const char* name, int length, double* data); +#ifdef VTK_USE_64BIT_IDS + int WriteVectorAttribute(const char* name, int length, vtkIdType* data); +#endif + + int WriteDataModeAttribute(const char* name); + int WriteWordTypeAttribute(const char* name, int dataType); + int WriteStringAttribute(const char* name, const char* value); + + unsigned long WriteDataArrayAppended(vtkDataArray* a, vtkIndent indent, + const char* alternateName=0, + int writeNumTuples=0, int timestep=-1); + void WriteDataArrayAppendedData(vtkDataArray* a, unsigned long pos, unsigned long &lastoffset); + void WriteDataArrayInline(vtkDataArray* a, vtkIndent indent, + const char* alternateName=0, int writeNumTuples=0); + void WriteInlineData(void* data, int numWords, int wordType, + vtkIndent indent); + + void WriteDataArrayHeader(vtkDataArray* a, vtkIndent indent, + const char* alternateName, int writeNumTuples, int timestep); + void WriteDataArrayFooter(ostream &os, vtkIndent indent); + + // Methods for writing points, point data, and cell data. + void WriteFieldData(vtkIndent indent); + void WriteFieldDataInline(vtkFieldData* fd, vtkIndent indent); + void WritePointDataInline(vtkPointData* pd, vtkIndent indent); + void WriteCellDataInline(vtkCellData* cd, vtkIndent indent); + void WriteFieldDataAppended(vtkFieldData* fd, vtkIndent indent, + OffsetsManagerGroup *fdManager); + void WriteFieldDataAppendedData(vtkFieldData* fd, int timestep, + OffsetsManagerGroup *fdManager); + void WritePointDataAppended(vtkPointData* pd, vtkIndent indent, + OffsetsManagerGroup *pdManager); + void WritePointDataAppendedData(vtkPointData* pd, int timestep, + OffsetsManagerGroup *pdManager); + void WriteCellDataAppended(vtkCellData* cd, vtkIndent indent, + OffsetsManagerGroup *cdManager); + void WriteCellDataAppendedData(vtkCellData* cd, int timestep, + OffsetsManagerGroup *cdManager); + void WriteAttributeIndices(vtkDataSetAttributes* dsa, char** names); + void WritePointsAppended(vtkPoints* points, vtkIndent indent, OffsetsManager *manager); + void WritePointsAppendedData(vtkPoints* points, int timestep, OffsetsManager *pdManager); + void WritePointsInline(vtkPoints* points, vtkIndent indent); + void WriteCoordinatesInline(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, vtkIndent indent); + void WriteCoordinatesAppended(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, vtkIndent indent, + OffsetsManagerGroup *coordManager); + void WriteCoordinatesAppendedData(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, int timestep, + OffsetsManagerGroup *coordManager); + virtual vtkDataArray* CreateArrayForPoints(vtkDataArray* inArray); + virtual vtkDataArray* CreateArrayForCells(vtkDataArray* inArray); + virtual vtkDataArray* CreateExactCoordinates(vtkDataArray* inArray, int xyz); + void WritePPointData(vtkPointData* pd, vtkIndent indent); + void WritePCellData(vtkCellData* cd, vtkIndent indent); + void WritePPoints(vtkPoints* points, vtkIndent indent); + void WritePDataArray(vtkDataArray* a, vtkIndent indent, + const char* alternateName=0); + void WritePCoordinates(vtkDataArray* xc, vtkDataArray* yc, + vtkDataArray* zc, vtkIndent indent); + + // Internal utility methods. + int WriteBinaryDataInternal(void* data, int numWords, int wordType); + int WriteBinaryDataBlock(unsigned char* in_data, int numWords, int wordType); + void PerformByteSwap(void* data, int numWords, int wordSize); + int CreateCompressionHeader(unsigned long size); + int WriteCompressionBlock(unsigned char* data, unsigned long size); + int WriteCompressionHeader(); + unsigned long GetWordTypeSize(int dataType); + const char* GetWordTypeName(int dataType); + unsigned long GetOutputWordTypeSize(int dataType); + + char** CreateStringArray(int numStrings); + void DestroyStringArray(int numStrings, char** strings); + + // The current range over which progress is moving. This allows for + // incrementally fine-tuned progress updates. + virtual void GetProgressRange(float* range); + virtual void SetProgressRange(float* range, int curStep, int numSteps); + virtual void SetProgressRange(float* range, int curStep, float* fractions); + virtual void SetProgressPartial(float fraction); + virtual void UpdateProgressDiscrete(float progress); + float ProgressRange[2]; + + ofstream* OutFile; + + int OpenFile(); + void CloseFile(); + + // The timestep currently being written + int TimeStep; + int CurrentTimeIndex; + int NumberOfTimeSteps; + // Store the range of time steps + int TimeStepRange[2]; + + // Dummy boolean var to start/stop the continue executing: + // when using the Start/Stop/WriteNextTime API + int UserContinueExecuting; //can only be -1 = invalid, 0 = stop, 1 = start + + unsigned long *NumberOfTimeValues; //one per piece / per timestep + +private: + vtkXMLWriter(const vtkXMLWriter&); // Not implemented. + void operator=(const vtkXMLWriter&); // Not implemented. +}; + +#endif diff --git a/IO/vtkXMLWriterC.cxx b/IO/vtkXMLWriterC.cxx new file mode 100644 index 0000000..92c977b --- /dev/null +++ b/IO/vtkXMLWriterC.cxx @@ -0,0 +1,704 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLWriterC.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXMLWriterC.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkDataSetAttributes.h" +#include "vtkImageData.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkSmartPointer.h" +#include "vtkStructuredGrid.h" +#include "vtkUnstructuredGrid.h" +#include "vtkXMLImageDataWriter.h" +#include "vtkXMLPolyDataWriter.h" +#include "vtkXMLRectilinearGridWriter.h" +#include "vtkXMLStructuredGridWriter.h" +#include "vtkXMLUnstructuredGridWriter.h" + +// Function to allocate a vtkDataArray and point it at the given data. +// The data are not copied. +static +vtkSmartPointer +vtkXMLWriterC_NewDataArray(const char* method, const char* name, int dataType, + void* data, vtkIdType numTuples, int numComponents); + +// Function to allocate a vtkCellArray and point it at the given +// cells. The cells are not copied. +static +vtkSmartPointer +vtkXMLWriterC_NewCellArray(const char* method, vtkIdType ncells, + vtkIdType* cells, vtkIdType cellsSize); + +// Function to implement vtkXMLWriterC_SetPointData and +// vtkXMLWriterC_SetCellData without duplicate code. +static +void vtkXMLWriterC_SetDataInternal(vtkXMLWriterC* self, const char* name, + int dataType, void* data, + vtkIdType numTuples, int numComponents, + const char* role, const char* method, + int isPoints); + +extern "C" +{ + +//---------------------------------------------------------------------------- +// Define the interface structure. Note this is a C struct so it has no +// real constructor or destructor. +struct vtkXMLWriterC_s +{ + vtkSmartPointer Writer; + vtkSmartPointer DataObject; + int Writing; +}; + +//---------------------------------------------------------------------------- +vtkXMLWriterC* vtkXMLWriterC_New() +{ + if(vtkXMLWriterC* self = new vtkXMLWriterC) + { + // Initialize the object. + self->Writer = 0; + self->DataObject = 0; + self->Writing = 0; + return self; + } + else + { + vtkGenericWarningMacro("Failed to allocate a vtkXMLWriterC object."); + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_Delete(vtkXMLWriterC* self) +{ + if(self) + { + // Finalize the object. + self->Writer = 0; + self->DataObject = 0; + delete self; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetDataObjectType(vtkXMLWriterC* self, int objType) +{ + if(!self) { return; } + if(!self->DataObject) + { + // Create the writer and data object. + switch(objType) + { + case VTK_POLY_DATA: + { + self->DataObject = vtkSmartPointer::New(); + self->Writer = vtkSmartPointer::New(); + }; break; + case VTK_UNSTRUCTURED_GRID: + { + self->DataObject = vtkSmartPointer::New(); + self->Writer = vtkSmartPointer::New(); + }; break; + case VTK_STRUCTURED_GRID: + { + self->DataObject = vtkSmartPointer::New(); + self->Writer = vtkSmartPointer::New(); + }; break; + case VTK_RECTILINEAR_GRID: + { + self->DataObject = vtkSmartPointer::New(); + self->Writer = vtkSmartPointer::New(); + }; break; + case VTK_IMAGE_DATA: + { + self->DataObject = vtkSmartPointer::New(); + self->Writer = vtkSmartPointer::New(); + }; break; + } + + // Set the data object as input to the writer. + if(self->Writer && self->DataObject) + { + self->Writer->SetInput(self->DataObject); + } + else + { + vtkGenericWarningMacro( + "Failed to allocate data object and writer for type " << objType << "." + ); + } + } + else + { + vtkGenericWarningMacro("vtkXMLWriterC_SetDataObjectType called twice."); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetExtent(vtkXMLWriterC* self, int extent[6]) +{ + if(!self) { return; } + if(vtkImageData* imData = + vtkImageData::SafeDownCast(self->DataObject)) + { + imData->SetExtent(extent); + } + else if(vtkStructuredGrid* sGrid = + vtkStructuredGrid::SafeDownCast(self->DataObject)) + { + sGrid->SetExtent(extent); + } + else if(vtkRectilinearGrid* rGrid = + vtkRectilinearGrid::SafeDownCast(self->DataObject)) + { + rGrid->SetExtent(extent); + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_SetExtent called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetExtent called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetPoints(vtkXMLWriterC* self, int dataType, + void* data, vtkIdType numPoints) +{ + if(!self) { return; } + if(vtkPointSet* dataObject = vtkPointSet::SafeDownCast(self->DataObject)) + { + // Create the vtkDataArray that will reference the points. + if(vtkSmartPointer array = + vtkXMLWriterC_NewDataArray("SetPoints", 0, + dataType, data, numPoints, 3)) + { + // Store the point array in the data object's points. + if(vtkSmartPointer points = vtkSmartPointer::New()) + { + points->SetNumberOfPoints(numPoints); + points->SetData(array); + dataObject->SetPoints(points); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetPoints failed to create a vtkPoints object." + ); + } + } + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_SetPoints called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetPoints called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetOrigin(vtkXMLWriterC* self, double origin[3]) +{ + if(!self) { return; } + if(vtkImageData* dataObject = vtkImageData::SafeDownCast(self->DataObject)) + { + dataObject->SetOrigin(origin); + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_SetOrigin called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetOrigin called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetSpacing(vtkXMLWriterC* self, double spacing[3]) +{ + if(!self) { return; } + if(vtkImageData* dataObject = vtkImageData::SafeDownCast(self->DataObject)) + { + dataObject->SetSpacing(spacing); + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_SetSpacing called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetSpacing called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetCoordinates(vtkXMLWriterC* self, int axis, + int dataType, void* data, + vtkIdType numCoordinates) +{ + if(!self) { return; } + if(vtkRectilinearGrid* dataObject = + vtkRectilinearGrid::SafeDownCast(self->DataObject)) + { + // Check the axis number. + if(axis < 0 || axis > 2) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetCoordinates called with invalid axis " + << axis << ". Use 0 for X, 1 for Y, and 2 for Z." + ); + } + + // Create the vtkDataArray that will reference the coordinates. + if(vtkSmartPointer array = + vtkXMLWriterC_NewDataArray("SetCoordinates", 0, dataType, data, + numCoordinates, 1)) + { + switch(axis) + { + case 0: dataObject->SetXCoordinates(array); + case 1: dataObject->SetYCoordinates(array); + case 2: dataObject->SetZCoordinates(array); + } + } + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_SetCoordinates called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetCoordinates called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetCellsWithType(vtkXMLWriterC* self, + int cellType, vtkIdType ncells, + vtkIdType* cells, vtkIdType cellsSize) +{ + if(!self) { return; } + if(vtkPolyData* dataObject = + vtkPolyData::SafeDownCast(self->DataObject)) + { + // Create a cell array to reference the cells. + if(vtkSmartPointer cellArray = + vtkXMLWriterC_NewCellArray("SetCellsWithType", ncells, cells, + cellsSize)) + { + // Store the cell array in the data object. + if(cellType == VTK_VERTEX || cellType == VTK_POLY_VERTEX) + { + dataObject->SetVerts(cellArray); + } + else if(cellType == VTK_LINE || cellType == VTK_POLY_LINE) + { + dataObject->SetLines(cellArray); + } + else if(cellType == VTK_TRIANGLE || cellType == VTK_TRIANGLE_STRIP) + { + dataObject->SetStrips(cellArray); + } + else // if(cellType == VTK_POLYGON || cellType == VTK_QUAD) + { + dataObject->SetPolys(cellArray); + } + } + } + else if(vtkUnstructuredGrid* uGrid = + vtkUnstructuredGrid::SafeDownCast(self->DataObject)) + { + // Create a cell array to reference the cells. + if(vtkSmartPointer cellArray = + vtkXMLWriterC_NewCellArray("SetCellsWithType", ncells, cells, + cellsSize)) + { + // Store the cell array in the data object. + uGrid->SetCells(cellType, cellArray); + } + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_SetCellsWithType called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetCellsWithType called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetCellsWithTypes(vtkXMLWriterC* self, + int* cellTypes, vtkIdType ncells, + vtkIdType* cells, vtkIdType cellsSize) +{ + if(!self) { return; } + if(vtkUnstructuredGrid* dataObject = + vtkUnstructuredGrid::SafeDownCast(self->DataObject)) + { + // Create a cell array to reference the cells. + if(vtkSmartPointer cellArray = + vtkXMLWriterC_NewCellArray("SetCellsWithType", ncells, cells, + cellsSize)) + { + // Store the cell array in the data object. + dataObject->SetCells(cellTypes, cellArray); + } + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_SetCellsWithTypes called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetCellsWithTypes called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetPointData(vtkXMLWriterC* self, const char* name, + int dataType, void* data, + vtkIdType numTuples, int numComponents, + const char* role) +{ + vtkXMLWriterC_SetDataInternal(self, name, dataType, data, numTuples, + numComponents, role, "SetPointData", 1); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetCellData(vtkXMLWriterC* self, const char* name, + int dataType, void* data, + vtkIdType numTuples, int numComponents, + const char* role) +{ + vtkXMLWriterC_SetDataInternal(self, name, dataType, data, numTuples, + numComponents, role, "SetCellData", 0); +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetFileName(vtkXMLWriterC* self, const char* fileName) +{ + if(!self) { return; } + if(self->Writer) + { + // Store the file name. + self->Writer->SetFileName(fileName); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetFileName called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLWriterC_Write(vtkXMLWriterC* self) +{ + if(!self) { return 0; } + if(self->Writer) + { + // Invoke the writer. + return self->Writer->Write(); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Write called before vtkXMLWriterC_SetDataObjectType." + ); + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_SetNumberOfTimeSteps(vtkXMLWriterC* self, int numTimeSteps) +{ + if(!self) { return; } + if(self->Writer) + { + // Set the number of time steps on the writer. + self->Writer->SetNumberOfTimeSteps(numTimeSteps); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_SetNumberOfTimeSteps called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_Start(vtkXMLWriterC* self) +{ + if(!self) { return; } + if(self->Writing) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Start called multiple times without vtkXMLWriterC_Stop." + ); + } + else if(self->Writer) + { + // Check the conditions. + if(self->Writer->GetNumberOfTimeSteps() == 0) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Start called with no time steps." + ); + } + else if(self->Writer->GetFileName() == 0) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Start called before vtkXMLWriterC_SetFileName." + ); + } + else + { + // Tell the writer to start writing. + self->Writer->Start(); + self->Writing = 1; + } + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Start called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_WriteNextTimeStep(vtkXMLWriterC* self, double timeValue) +{ + if(!self) { return; } + if(!self->Writing) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_WriteNextTimeStep called before vtkXMLWriterC_Start." + ); + } + else if(self->Writer) + { + // Tell the writer to write this time step. + self->Writer->WriteNextTime(timeValue); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Stop called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLWriterC_Stop(vtkXMLWriterC* self) +{ + if(!self) { return; } + if(!self->Writing) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Stop called before vtkXMLWriterC_Start." + ); + } + else if(self->Writer) + { + // Tell the writer to stop writing. + self->Writer->Stop(); + self->Writing = 0; + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_Stop called before vtkXMLWriterC_SetDataObjectType." + ); + } +} + +} /* extern "C" */ + +//---------------------------------------------------------------------------- +static +vtkSmartPointer +vtkXMLWriterC_NewDataArray(const char* method, const char* name, int dataType, + void* data, vtkIdType numTuples, int numComponents) +{ + // Create the vtkDataArray that will reference the data. + vtkSmartPointer array = + vtkDataArray::CreateDataArray(dataType); + if(array) + { + array->Delete(); + } + if(!array || array->GetDataType() != dataType) + { + vtkGenericWarningMacro("vtkXMLWriterC_" << method + << " could not allocate array of type " + << dataType << "."); + return 0; + } + + // Set the number of components. + array->SetNumberOfComponents(numComponents); + + // Set the name if one was given. + array->SetName(name); + + // Point the array at the given data. It is not copied. + array->SetVoidArray(data, numTuples*numComponents, 1); + + // Return the array. + return array; +} + +//---------------------------------------------------------------------------- +static +vtkSmartPointer +vtkXMLWriterC_NewCellArray(const char* method, vtkIdType ncells, + vtkIdType* cells, vtkIdType cellsSize) +{ + // Create a vtkIdTypeArray to reference the cells. + vtkSmartPointer array = + vtkSmartPointer::New(); + if(!array) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_" << method << " failed to allocate a vtkIdTypeArray." + ); + return 0; + } + array->SetArray(cells, ncells*cellsSize, 1); + + // Create the cell array. + vtkSmartPointer cellArray = + vtkSmartPointer::New(); + if(!cellArray) + { + vtkGenericWarningMacro( + "vtkXMLWriterC_" << method << " failed to allocate a vtkCellArray." + ); + return 0; + } + cellArray->SetCells(ncells, array); + return cellArray; +} + +//---------------------------------------------------------------------------- +static +void vtkXMLWriterC_SetDataInternal(vtkXMLWriterC* self, const char* name, + int dataType, void* data, + vtkIdType numTuples, int numComponents, + const char* role, const char* method, + int isPoints) +{ + if(!self) { return; } + if(vtkDataSet* dataObject = vtkDataSet::SafeDownCast(self->DataObject)) + { + if(vtkSmartPointer array = + vtkXMLWriterC_NewDataArray(method, name, dataType, data, numTuples, + numComponents)) + { + // Store either in point data or cell data. + vtkDataSetAttributes* dsa; + if (isPoints) + { + dsa = dataObject->GetPointData(); + } + else + { + dsa = dataObject->GetCellData(); + } + + // Store the data array with the requested role. + if(role && strcmp(role, "SCALARS") == 0) + { + dsa->SetScalars(array); + } + else if(role && strcmp(role, "VECTORS") == 0) + { + dsa->SetVectors(array); + } + else if(role && strcmp(role, "NORMALS") == 0) + { + dsa->SetNormals(array); + } + else if(role && strcmp(role, "TENSORS") == 0) + { + dsa->SetTensors(array); + } + else if(role && strcmp(role, "TCOORDS") == 0) + { + dsa->SetTCoords(array); + } + else + { + dsa->AddArray(array); + } + } + } + else if(self->DataObject) + { + vtkGenericWarningMacro("vtkXMLWriterC_" << method << " called for " + << self->DataObject->GetClassName() + << " data object."); + } + else + { + vtkGenericWarningMacro( + "vtkXMLWriterC_" << method + << " called before vtkXMLWriterC_SetDataObjectType." + ); + } +} diff --git a/IO/vtkXMLWriterC.h b/IO/vtkXMLWriterC.h new file mode 100644 index 0000000..256dc4f --- /dev/null +++ b/IO/vtkXMLWriterC.h @@ -0,0 +1,271 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLWriterC.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkXMLWriterC_h +#define __vtkXMLWriterC_h + +#include "vtkType.h" /* For scalar and vtkDataObject type enumerations. */ + +/* Define the export macro. */ +#if defined(_WIN32) && defined(VTK_BUILD_SHARED_LIBS) +# if defined(vtkIO_EXPORTS) +# define VTK_XML_EXPORT __declspec(dllexport) +# else +# define VTK_XML_EXPORT __declspec(dllimport) +# endif +#else +# define VTK_XML_EXPORT +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /*cplusplus*/ + +/** + * vtkXMLWriterC is an opaque structure holding the state of an + * individual writer object. It can be used to write VTK XML files. + */ +typedef struct vtkXMLWriterC_s vtkXMLWriterC; + +/** + * Create a new instance of vtkXMLWriterC. Returns the object or NULL + * on failure. + */ +VTK_XML_EXPORT +vtkXMLWriterC* vtkXMLWriterC_New(); + +/** + * Delete the writer object. + * + * This should not be called between Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_Delete(vtkXMLWriterC* self); + +/** + * Set the VTK data object type that will be written. This + * initializes an empty data object of the given type. + * + * This must be set before setting geometry or data information can + * can be set only once per writer object. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetDataObjectType(vtkXMLWriterC* self, int objType); + +/** + * Set the extent of a structured data set. + * + * This may be used only after SetDataObjectType has been called with + * a structured data object type. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetExtent(vtkXMLWriterC* self, int extent[6]); + +/** + * Set the points of a point data set. For structured data, the + * number of points must match number of points indicated by the + * extent. + * + * Use dataType to specify the scalar type used in the given array. + * The data array must have numPoints*3 entries specifying 3-D points. + * + * This may not be used for data objects with implicit points. It may + * not be called before SetDataObjectType or between Start and Stop + * calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetPoints(vtkXMLWriterC* self, int dataType, + void* data, vtkIdType numPoints); + +/** + * Set the origin of an image data set. + * + * This may only be used for image data. It may not be called before + * SetDataObjectType or between Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetOrigin(vtkXMLWriterC* self, double origin[3]); + +/** + * Set the spacing of an image data set. + * + * This may only be used for image data. It may not be called before + * SetDataObjectType or between Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetSpacing(vtkXMLWriterC* self, double spacing[3]); + +/** + * Set the coordinates along one axis of a rectilinear grid data set. + * + * Specify axis 0 for X, 1 for Y, and 2 for Z. Use dataType to + * specify the scalar type used in the given data array. Use + * numCoordinates to specify the number of such values in the array. + * The number of values must match that specified by the extent for + * the given axis. + * + * This may only be used for rectilinear grids. It may not be called + * before SetDataObjectType or between Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetCoordinates(vtkXMLWriterC* self, int axis, + int dataType, void* data, + vtkIdType numCoordinates); + +/** + * Set a cell array on the data object to be written. All cells must + * have the same type. + * + * For unstructured grid data objects, the cellType can be any type. + * For polygonal data objects, the cellType must be VTK_VERTEX, + * VTK_POLY_VERTEX, VTK_LINE, VTK_POLY_LINE, VTK_TRIANGLE, + * VTK_TRIANGLE_STRIP, or cyclically connected simple cell type such + * as VTK_POLYGON. + * + * The cells array must have cellsSize entries. Each cell uses N+1 + * entries where N is the number of points in the cell. The layout of + * the array for each cell is "[N,id1,id2,...,idN]". The total number + * of cells must be ncells. + * + * This may only be used for unstructured grid and polygonal data + * types. It may not be called before SetDataObjectType or between + * Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetCellsWithType(vtkXMLWriterC* self, + int cellType, vtkIdType ncells, + vtkIdType* cells, vtkIdType cellsSize); + +/** + * Set a cell array on the data object to be written. Each cell can + * have its own type. + * + * The cellTypes array specifies the type of each cell, and has ncells + * entries. The cells array must have cellsSize entries. Each cell + * uses N+1 entries where N is the number of points in the cell. The + * layout of the array for each cell is "[N,id1,id2,...,idN]". The + * total number of cells must be ncells. + * + * This may only be used for unstructured grid data objects. It may + * not be called before SetDataObjectType or between Start and Stop + * calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetCellsWithTypes(vtkXMLWriterC* self, + int* cellTypes, vtkIdType ncells, + vtkIdType* cells, vtkIdType cellsSize); + +/** + * Set a point or cell data array by name. + * + * The name of the array is required and should describe the purpose + * of the data. Use dataType to specify the scalar type used in the + * given data array. Use numTuples to specify the number of tuples + * and numComponents to specify the number of scalar components in + * each tuple. + * + * The data array must have exactly numTuples*numComponents entries. + * For SetPointData, numTuples must be equal to the number of points + * indicated by SetExtent and/or SetPoints. For SetCellData, + * numTuples must be equal to the total number of cells set by + * SetCells. + * + * The role can be one of "SCALARS", "VECTORS", "NORMALS", "TENSORS", + * or "TCOORDS" and specifies that the array should be designated as + * the active array for the named role. Other values for role are + * ignored. + * + * This may be used for all data types. It may not be called before + * SetDataObjectType but may be called between Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetPointData(vtkXMLWriterC* self, const char* name, + int dataType, void* data, + vtkIdType numTuples, int numComponents, + const char* role); +VTK_XML_EXPORT +void vtkXMLWriterC_SetCellData(vtkXMLWriterC* self, const char* name, + int dataType, void* data, + vtkIdType numTuples, int numComponents, + const char* role); + +/** + * Set the name of the file into which the data are to be written. + * + * This may be used for all data types. It may not be called before + * SetDataObjectType or between Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetFileName(vtkXMLWriterC* self, const char* fileName); + +/** + * Write the data to a file immediately. This is not used when + * writing time-series data. Returns 1 for success and 0 for failure. + * + * This may only be called after SetFileName and SetDataObjectType. + */ +VTK_XML_EXPORT +int vtkXMLWriterC_Write(vtkXMLWriterC* self); + +/** + * Set the number of time steps that will be written between upcoming + * Start and Stop calls. This is used when writing time-series data. + * + * This may be used for all data types. It may not be called before + * SetDataObjectType or between Start and Stop calls. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_SetNumberOfTimeSteps(vtkXMLWriterC* self, int numTimeSteps); + +/** + * Start writing a time-series to the output file. + * + * This may only be called after SetFileName, SetDataObjectType, and + * SetNumberOfTimeSteps. It may not be called a second time until + * after an intervening call to Stop. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_Start(vtkXMLWriterC* self); + +/** + * Write one time step of a time-series to the output file. The + * current data set by SetPointData and SetCellData will be written. + * + * Use timeValue to specify the time associated with the time step + * being written. + * + * This may only be called after Start has been called. It should be + * called NumberOfTimeSteps times before calling Stop. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_WriteNextTimeStep(vtkXMLWriterC* self, double timeValue); + +/** + * Stop writing a time-series to the output file. + * + * This may only be called after Start and NumberOfTimeSteps calls to + * WriteNextTimeStep. + */ +VTK_XML_EXPORT +void vtkXMLWriterC_Stop(vtkXMLWriterC* self); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /*cplusplus*/ + +/* Done with export macro. */ +#undef VTK_XML_EXPORT + +#endif diff --git a/IO/vtkXMLWriterF.h b/IO/vtkXMLWriterF.h new file mode 100644 index 0000000..dec3598 --- /dev/null +++ b/IO/vtkXMLWriterF.h @@ -0,0 +1,489 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMLWriterF.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + * vtkXMLWriterF.h helps fortran programs call the C interface for + * writing VTK XML files. A program can use this by writing one + * vtkXMLWriterF.c file that includes this header. DO NOT INCLUDE + * THIS HEADER ELSEWHERE. The fortran program then compiles + * vtkXMLWriterF.c using a C compiler and links to the resulting + * object file. + */ + +#if defined(__cplusplus) +# error "This should be included only by a .c file." +#endif + +/* Calls will be forwarded to the C interface. */ +#include "vtkXMLWriterC.h" + +#include /* fprintf */ +#include /* malloc, free */ +#include /* memcpy */ + +/* Define a static-storage default-zero-initialized table to store + writer objects for the fortran program. */ +#define VTK_XMLWRITERF_MAX 256 +static vtkXMLWriterC* vtkXMLWriterF_Table[VTK_XMLWRITERF_MAX+1]; + +/* Fortran compilers expect certain symbol names for their calls to C + code. These macros help build the C symbols so that the fortran + program can link to them properly. The definitions here are + reasonable defaults but the source file that includes this can + define them appropriately for a particular compiler and override + these. */ +#if !defined(VTK_FORTRAN_NAME) +# define VTK_FORTRAN_NAME(name, NAME) name##__ +#endif +#if !defined(VTK_FORTRAN_ARG_STRING_POINTER) +# define VTK_FORTRAN_ARG_STRING_POINTER(name) const char* name##_ptr_arg +#endif +#if !defined(VTK_FORTRAN_ARG_STRING_LENGTH) +# define VTK_FORTRAN_ARG_STRING_LENGTH(name) , const long int name##_len_arg +#endif +#if !defined(VTK_FORTRAN_REF_STRING_POINTER) +# define VTK_FORTRAN_REF_STRING_POINTER(name) name##_ptr_arg +#endif +#if !defined(VTK_FORTRAN_REF_STRING_LENGTH) +# define VTK_FORTRAN_REF_STRING_LENGTH(name) ((int)name##_len_arg) +#endif + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_New */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_new, VTKXMLWRITERF_NEW)( + int* self + ) +{ + int i; + + /* Initialize result to failure. */ + *self = 0; + + /* Search for a table entry to use for this object. */ + for(i=1;i <= VTK_XMLWRITERF_MAX; ++i) + { + if(!vtkXMLWriterF_Table[i]) + { + vtkXMLWriterF_Table[i] = vtkXMLWriterC_New(); + if(vtkXMLWriterF_Table[i]) + { + *self = i; + } + return; + } + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_Delete */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_delete, VTKXMLWRITERF_DELETE)( + int* self + ) +{ + /* Check if the writer object exists. */ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + /* Delete this writer object. */ + vtkXMLWriterC_Delete(vtkXMLWriterF_Table[*self]); + + /* Erase the table entry. */ + vtkXMLWriterF_Table[*self] = 0; + } + else + { + fprintf(stderr, + "vtkXMLWriterF_Delete called with invalid id %d.\n", + *self); + } + + /* The writer object no longer exists. Destroy the id. */ + *self = 0; +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetDataObjectType */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setdataobjecttype, VTKXMLWRITERF_SETDATAOBJECTTYPE)( + const int* self, const int* objType + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetDataObjectType(vtkXMLWriterF_Table[*self], *objType); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetDataObjectType called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetExtent */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setextent, VTKXMLWRITERF_SETEXTENT)( + const int* self, int extent[6] + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetExtent(vtkXMLWriterF_Table[*self], extent); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetExtent called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetPoints */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setpoints, VTKXMLWRITERF_SETPOINTS)( + const int* self, const int* dataType, + void* data, const vtkIdType* numPoints + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetPoints(vtkXMLWriterF_Table[*self], *dataType, + data, *numPoints); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetPoints called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetOrigin */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setorigin, VTKXMLWRITERF_SETORIGIN)( + const int* self, double origin[3] + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetOrigin(vtkXMLWriterF_Table[*self], origin); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetOrigin called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetSpacing */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setspacing, VTKXMLWRITERF_SETSPACING)( + const int* self, double spacing[3] + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetSpacing(vtkXMLWriterF_Table[*self], spacing); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetSpacing called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetCoordinates */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setcoordinates, VTKXMLWRITERF_SETCOORDINATES)( + const int* self, const int* axis, const int* dataType, void* data, + const vtkIdType* numCoordinates + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetCoordinates(vtkXMLWriterF_Table[*self], *axis, + *dataType, data, *numCoordinates); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetCoordinates called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetCellsWithType */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setcellswithtype, VTKXMLWRITERF_SETCELLSWITHTYPE)( + const int* self, const int* cellType, const vtkIdType* ncells, + vtkIdType* cells, const vtkIdType* cellsSize + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetCellsWithType(vtkXMLWriterF_Table[*self], *cellType, + *ncells, cells, *cellsSize); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetCellsWithType called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetCellsWithTypes */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setcellswithtypes, VTKXMLWRITERF_SETCELLSWITHTYPES)( + const int* self, int* cellTypes, const vtkIdType* ncells, + vtkIdType* cells, const vtkIdType* cellsSize + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetCellsWithTypes(vtkXMLWriterF_Table[*self], cellTypes, + *ncells, cells, *cellsSize); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetCellsWithTypes called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetPointData */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setpointdata, VTKXMLWRITERF_SETPOINTDATA)( + const int* self, VTK_FORTRAN_ARG_STRING_POINTER(name), + const int* dataType, void* data, const vtkIdType* numTuples, + const int* numComponents, VTK_FORTRAN_ARG_STRING_POINTER(role) + VTK_FORTRAN_ARG_STRING_LENGTH(name) + VTK_FORTRAN_ARG_STRING_LENGTH(role) + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + /* Prepare NULL-terminated strings. */ + const char* name_ptr = VTK_FORTRAN_REF_STRING_POINTER(name); + int name_length = VTK_FORTRAN_REF_STRING_LENGTH(name); + char* name_buffer = malloc(name_length+1); + const char* role_ptr = VTK_FORTRAN_REF_STRING_POINTER(role); + int role_length = VTK_FORTRAN_REF_STRING_LENGTH(role); + char* role_buffer = malloc(role_length+1); + if(!name_buffer || !role_buffer) + { + fprintf(stderr, + "vtkXMLWriterF_SetPointData failed to allocate name or role.\n"); + if(name_buffer) { free(name_buffer); } + if(role_buffer) { free(role_buffer); } + return; + } + memcpy(name_buffer, name_ptr, name_length); + name_buffer[name_length] = 0; + memcpy(role_buffer, role_ptr, role_length); + role_buffer[role_length] = 0; + + /* Forward the call. */ + vtkXMLWriterC_SetPointData(vtkXMLWriterF_Table[*self], name_buffer, + *dataType, data, *numTuples, *numComponents, + role_buffer); + + /* Free the NULL-terminated strings. */ + free(name_buffer); + free(role_buffer); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetPointData called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetCellData */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setcelldata, VTKXMLWRITERF_SETCELLDATA)( + const int* self, VTK_FORTRAN_ARG_STRING_POINTER(name), + const int* dataType, void* data, const vtkIdType* numTuples, + const int* numComponents, VTK_FORTRAN_ARG_STRING_POINTER(role) + VTK_FORTRAN_ARG_STRING_LENGTH(name) + VTK_FORTRAN_ARG_STRING_LENGTH(role) + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + /* Prepare NULL-terminated strings. */ + const char* name_ptr = VTK_FORTRAN_REF_STRING_POINTER(name); + int name_length = VTK_FORTRAN_REF_STRING_LENGTH(name); + char* name_buffer = malloc(name_length+1); + const char* role_ptr = VTK_FORTRAN_REF_STRING_POINTER(role); + int role_length = VTK_FORTRAN_REF_STRING_LENGTH(role); + char* role_buffer = malloc(role_length+1); + if(!name_buffer || !role_buffer) + { + fprintf(stderr, + "vtkXMLWriterF_SetCellData failed to allocate name or role.\n"); + if(name_buffer) { free(name_buffer); } + if(role_buffer) { free(role_buffer); } + return; + } + memcpy(name_buffer, name_ptr, name_length); + name_buffer[name_length] = 0; + memcpy(role_buffer, role_ptr, role_length); + role_buffer[role_length] = 0; + + /* Forward the call. */ + vtkXMLWriterC_SetCellData(vtkXMLWriterF_Table[*self], name_buffer, + *dataType, data, *numTuples, *numComponents, + role_buffer); + + /* Free the NULL-terminated strings. */ + free(name_buffer); + free(role_buffer); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetCellData called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetFileName */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setfilename, VTKXMLWRITERF_SETFILENAME)( + const int* self, VTK_FORTRAN_ARG_STRING_POINTER(name) + VTK_FORTRAN_ARG_STRING_LENGTH(name) + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + /* Prepare NULL-terminated string. */ + const char* name_ptr = VTK_FORTRAN_REF_STRING_POINTER(name); + int name_length = VTK_FORTRAN_REF_STRING_LENGTH(name); + char* name_buffer = malloc(name_length+1); + if(!name_buffer) + { + fprintf(stderr, + "vtkXMLWriterF_SetFileName failed to allocate name.\n"); + return; + } + memcpy(name_buffer, name_ptr, name_length); + name_buffer[name_length] = 0; + + /* Forward the call. */ + vtkXMLWriterC_SetFileName(vtkXMLWriterF_Table[*self], name_buffer); + + /* Free the NULL-terminated string. */ + free(name_buffer); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetFileName called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_Write */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_write, VTKXMLWRITERF_WRITE)( + const int* self, int* success + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + *success = vtkXMLWriterC_Write(vtkXMLWriterF_Table[*self]); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_Write called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_SetNumberOfTimeSteps */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_setnumberoftimesteps, VTKXMLWRITERF_SETNUMBEROFTIMESTEPS)( + const int* self, const int* numTimeSteps + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_SetNumberOfTimeSteps(vtkXMLWriterF_Table[*self], + *numTimeSteps); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_SetNumberOfTimeSteps called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_Start */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_start, VTKXMLWRITERF_START)( + const int* self + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_Start(vtkXMLWriterF_Table[*self]); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_Start called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_WriteNextTimeStep */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_writenexttimestep, VTKXMLWRITERF_WRITENEXTTIMESTEP)( + const int* self, const double* timeValue + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_WriteNextTimeStep(vtkXMLWriterF_Table[*self], *timeValue); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_WriteNextTimeStep called with invalid id %d.\n", + *self); + } +} + +/*--------------------------------------------------------------------------*/ +/* vtkXMLWriterF_Stop */ +void VTK_FORTRAN_NAME(vtkxmlwriterf_stop, VTKXMLWRITERF_STOP)( + const int* self + ) +{ + if(*self > 0 && *self <= VTK_XMLWRITERF_MAX && vtkXMLWriterF_Table[*self]) + { + vtkXMLWriterC_Stop(vtkXMLWriterF_Table[*self]); + } + else + { + fprintf(stderr, + "vtkXMLWriterF_Stop called with invalid id %d.\n", + *self); + } +} diff --git a/IO/vtkXYZMolReader.cxx b/IO/vtkXYZMolReader.cxx new file mode 100644 index 0000000..c7f3261 --- /dev/null +++ b/IO/vtkXYZMolReader.cxx @@ -0,0 +1,346 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXYZMolReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkXYZMolReader.h" + +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkIdTypeArray.h" +#include "vtkPolyData.h" + +#include + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkXYZMolReader, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkXYZMolReader); + +//---------------------------------------------------------------------------- +vtkXYZMolReader::vtkXYZMolReader() +{ + this->TimeStep = 0; + this->MaxTimeStep = 0; +} + +//---------------------------------------------------------------------------- +vtkXYZMolReader::~vtkXYZMolReader() +{ +} + +//---------------------------------------------------------------------------- +char* vtkXYZMolReader::GetNextLine(FILE* fp, char* line, int maxlen) +{ + int cc; + int len; + int comment; + char* ptr; + do + { + comment = 0; + if ( !fgets(line, maxlen, fp) ) + { + //cout << "Problem when reading. EOF?" << endl; + return 0; + } + len = static_cast(strlen(line)); + for ( cc = 0; cc < len; cc ++ ) + { + int ch = line[cc]; + if ( ch == '#' ) + { + comment = 1; + break; + } + else if ( ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' ) + { + break; + } + } + if ( cc == len ) + { + comment = 1; + } + } + while ( comment ); + //cout << "Have line that is not a comment: [" << line << "]" << endl; + len = static_cast(strlen(line)); + int ft = 0; + ptr = line; + for ( cc = 0; cc < len; cc ++ ) + { + int ch = line[cc]; + if ( !ft && ( ch == ' ' || ch == '\t' ) ) + { + ptr++; + } + else if ( ch == '#' || ch == '\n' || ch == '\r' ) + { + line[cc] = 0; + break; + } + else + { + ft = 1; + } + } + if ( strlen(ptr) == 0 ) + { + return 0; + } + return ptr; +} + +//---------------------------------------------------------------------------- +int vtkXYZMolReader::GetLine1(const char* line, int *cnt) +{ + char dummy[1024] = ""; + if ( !line || sscanf(line, "%d%s", cnt, dummy) < 1) + { + return 0; + } + int cc; + for ( cc = 0; cc < static_cast(strlen(dummy)); ++cc ) + { + if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' && + dummy[cc] != '\r' ) + { + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXYZMolReader::GetLine2(const char* line, char *name) +{ + char dummy[1024] = ""; + if ( !line || sscanf(line, "%s%s", name, dummy) < 1) + { + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXYZMolReader::GetAtom(const char* line, char* atom, float *x) +{ + //cout << "Lookinf for atom: " << line << endl; + char dummy[1024] = ""; + if ( !line || sscanf(line, "%s %f %f %f%s", atom, x, x+1, x+2, dummy) < 4) + { + return 0; + } + int cc; + for ( cc = 0; cc < static_cast(strlen(dummy)); ++cc ) + { + if ( dummy[cc] != ' ' && dummy[cc] != '\t' && dummy[cc] != '\n' && + dummy[cc] != '\r' ) + { + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXYZMolReader::InsertAtom(const char* atom, float *pos) +{ + this->Points->InsertNextPoint(pos); + this->AtomType->InsertNextValue(this->MakeAtomType(atom)); +} + + +//---------------------------------------------------------------------------- +int vtkXYZMolReader::CanReadFile(const char* name) +{ + if ( !name ) + { + return 0; + } + + // First make sure the file exists. This prevents an empty file + // from being created on older compilers. + struct stat fs; + if(stat(name, &fs) != 0) + { + return 0; + } + + FILE* fp = fopen(name, "r"); + if ( !fp ) + { + return 0; + } + + int valid = 0; + + const int maxlen = 1024; + char buffer[maxlen]; + char comment[maxlen]; + char atom[maxlen]; + char* lptr; + int num = 0; + float pos[3]; + + lptr = this->GetNextLine(fp, buffer, maxlen); + if ( this->GetLine1(lptr, &num) ) + { + // Have header + lptr = this->GetNextLine(fp, buffer, maxlen); + if ( this->GetLine2(lptr, comment) ) + { + lptr = this->GetNextLine(fp, buffer, maxlen); + if ( this->GetAtom(lptr, atom, pos) ) + { + valid = 3; + } + } + else if ( this->GetAtom(lptr, atom, pos) ) + { + valid = 3; + } + } + else + { + // No header + lptr = this->GetNextLine(fp, buffer, maxlen); + if ( this->GetAtom(lptr, atom, pos) ) + { + valid = 3; + } + } + + fclose(fp); + return valid; +} + +//---------------------------------------------------------------------------- +void vtkXYZMolReader::ReadSpecificMolecule(FILE *fp) +{ + const int maxlen = 1024; + char buffer[maxlen]; + char comment[maxlen]; + char* lptr; + + int have_header = 0; + int num = 0; + int cnt = 0; + int ccnt = 0; + int rcnt = 0; + int timestep = 1; + + int selectstep = this->TimeStep; + + float pos[3]; + char atom[maxlen]; + + this->AtomType->Allocate(1024); + this->Points->Allocate(1024); + + while ( (lptr = this->GetNextLine(fp, buffer, maxlen)) ) + { + if ( ( cnt == 0 || ccnt == num ) && this->GetLine1(lptr, &num) ) + { + have_header = 1; + vtkDebugMacro("Have header. Number of atoms is: " << num); + ccnt = 0; + if ( cnt > 0 ) + { + timestep ++; + } + } + else if ( have_header ) + { + if ( this->GetAtom(lptr, atom, pos) ) + { + //cout << "Found atom: " << atom << endl; + if ( ccnt >= num ) + { + vtkErrorMacro("Expecting " << num << " atoms, found: " << ccnt); + return; + } + else + { + if ( selectstep == timestep -1 ) + { + // Got atom with full signature + //cout << "Insert atom: " << atom << endl; + this->InsertAtom(atom, pos); + rcnt ++; + } + ccnt ++; + } + } + else if ( ccnt == 0 && this->GetLine2(lptr, comment) ) + { + vtkDebugMacro("Have comment"); + } + else + { + vtkErrorMacro("Expecting atom, got: " << lptr); + return; + } + } + else + { + if ( this->GetAtom(lptr, atom, pos) ) + { + // Got atom with simple signature + this->InsertAtom(atom, pos); + rcnt ++; + } + else + { + vtkErrorMacro("Expecting atom, got: " << lptr); + return; + } + } + ++ cnt; + } + + // Just some more checking and cleanups + if ( num == 0 ) + { + num = rcnt; + } + + this->AtomType->Squeeze(); + this->Points->Squeeze(); + + if ( selectstep >= timestep ) + { + this->NumberOfAtoms = 0; + vtkErrorMacro("Only have " << timestep << " time step(s)"); + return; + } + + vtkDebugMacro("Number of atoms: " << num << " (" << rcnt << ")"); + if ( num != rcnt ) + { + this->NumberOfAtoms = 0; + vtkErrorMacro("Expecting " << num << " atoms, got " << rcnt); + return; + } + + this->SetMaxTimeStep(timestep); + this->NumberOfAtoms = num; +} + +//---------------------------------------------------------------------------- +void vtkXYZMolReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "TimeStep: " << this->TimeStep << endl; + os << indent << "MaxTimeStep: " << this->MaxTimeStep; +} diff --git a/IO/vtkXYZMolReader.h b/IO/vtkXYZMolReader.h new file mode 100644 index 0000000..6fb916d --- /dev/null +++ b/IO/vtkXYZMolReader.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXYZMolReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXYZMolReader - read Molecular Data files +// .SECTION Description +// vtkXYZMolReader is a source object that reads Molecule files +// The FileName must be specified +// +// .SECTION Thanks +// Dr. Jean M. Favre who developed and contributed this class + +#ifndef __vtkXYZMolReader_h +#define __vtkXYZMolReader_h + +#include "vtkMoleculeReaderBase.h" + + +class VTK_IO_EXPORT vtkXYZMolReader : public vtkMoleculeReaderBase +{ +public: + vtkTypeRevisionMacro(vtkXYZMolReader,vtkMoleculeReaderBase); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkXYZMolReader *New(); + + // Description: + // Test whether the file with the given name can be read by this + // reader. + virtual int CanReadFile(const char* name); + + // Description: + // Set the current time step. It should be greater than 0 and smaller than + // MaxTimeStep. + vtkSetMacro(TimeStep, int); + vtkGetMacro(TimeStep, int); + + // Description: + // Get the maximum time step. + vtkGetMacro(MaxTimeStep, int); + +protected: + vtkXYZMolReader(); + ~vtkXYZMolReader(); + + void ReadSpecificMolecule(FILE* fp); + + // Description: + // Get next line that is not a comment. It returns the beginning of data on + // line (skips empty spaces) + char* GetNextLine(FILE* fp, char* line, int maxlen); + + int GetLine1(const char* line, int *cnt); + int GetLine2(const char* line, char *name); + int GetAtom(const char* line, char* atom, float *x); + + void InsertAtom(const char* atom, float *pos); + + vtkSetMacro(MaxTimeStep, int); + + int TimeStep; + int MaxTimeStep; + +private: + vtkXYZMolReader(const vtkXYZMolReader&); // Not implemented. + void operator=(const vtkXYZMolReader&); // Not implemented. +}; + +#endif diff --git a/IO/vtkZLibDataCompressor.cxx b/IO/vtkZLibDataCompressor.cxx new file mode 100644 index 0000000..400373b --- /dev/null +++ b/IO/vtkZLibDataCompressor.cxx @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkZLibDataCompressor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkZLibDataCompressor.h" +#include "vtkObjectFactory.h" +#include "vtk_zlib.h" + +vtkCxxRevisionMacro(vtkZLibDataCompressor, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkZLibDataCompressor); + +//---------------------------------------------------------------------------- +vtkZLibDataCompressor::vtkZLibDataCompressor() +{ + this->CompressionLevel = Z_DEFAULT_COMPRESSION; +} + +//---------------------------------------------------------------------------- +vtkZLibDataCompressor::~vtkZLibDataCompressor() +{ +} + +//---------------------------------------------------------------------------- +void vtkZLibDataCompressor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "CompressionLevel: " << this->CompressionLevel << endl; +} + +//---------------------------------------------------------------------------- +unsigned long +vtkZLibDataCompressor::CompressBuffer(const unsigned char* uncompressedData, + unsigned long uncompressedSize, + unsigned char* compressedData, + unsigned long compressionSpace) +{ + unsigned long compressedSize = compressionSpace; + Bytef* cd = reinterpret_cast(compressedData); + const Bytef* ud = reinterpret_cast(uncompressedData); + + // Call zlib's compress function. + if(compress2(cd, &compressedSize, ud, uncompressedSize, this->CompressionLevel) != Z_OK) + { + vtkErrorMacro("Zlib error while compressing data."); + return 0; + } + + return compressedSize; +} + +//---------------------------------------------------------------------------- +unsigned long +vtkZLibDataCompressor::UncompressBuffer(const unsigned char* compressedData, + unsigned long compressedSize, + unsigned char* uncompressedData, + unsigned long uncompressedSize) +{ + unsigned long decSize = uncompressedSize; + Bytef* ud = reinterpret_cast(uncompressedData); + const Bytef* cd = reinterpret_cast(compressedData); + + // Call zlib's uncompress function. + if(uncompress(ud, &decSize, cd, compressedSize) != Z_OK) + { + vtkErrorMacro("Zlib error while uncompressing data."); + return 0; + } + + // Make sure the output size matched that expected. + if(decSize != uncompressedSize) + { + vtkErrorMacro("Decompression produced incorrect size.\n" + "Expected " << uncompressedSize << " and got " << decSize); + return 0; + } + + return decSize; +} + +//---------------------------------------------------------------------------- +unsigned long +vtkZLibDataCompressor::GetMaximumCompressionSpace(unsigned long size) +{ + // ZLib specifies that destination buffer must be 0.1% larger + 12 bytes. + return size + (size+999)/1000 + 12; +} diff --git a/IO/vtkZLibDataCompressor.h b/IO/vtkZLibDataCompressor.h new file mode 100644 index 0000000..e35f9ef --- /dev/null +++ b/IO/vtkZLibDataCompressor.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkZLibDataCompressor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkZLibDataCompressor - Data compression using zlib. +// .SECTION Description +// vtkZLibDataCompressor provides a concrete vtkDataCompressor class +// using zlib for compressing and uncompressing data. + +#ifndef __vtkZLibDataCompressor_h +#define __vtkZLibDataCompressor_h + +#include "vtkDataCompressor.h" + +class VTK_IO_EXPORT vtkZLibDataCompressor : public vtkDataCompressor +{ +public: + vtkTypeRevisionMacro(vtkZLibDataCompressor,vtkDataCompressor); + void PrintSelf(ostream& os, vtkIndent indent); + static vtkZLibDataCompressor* New(); + + // Description: + // Get the maximum space that may be needed to store data of the + // given uncompressed size after compression. This is the minimum + // size of the output buffer that can be passed to the four-argument + // Compress method. + unsigned long GetMaximumCompressionSpace(unsigned long size); + + // Description: + // Get/Set the compression level. + vtkSetClampMacro(CompressionLevel, int, 0, 9); + vtkGetMacro(CompressionLevel, int); + +protected: + vtkZLibDataCompressor(); + ~vtkZLibDataCompressor(); + + int CompressionLevel; + + // Compression method required by vtkDataCompressor. + unsigned long CompressBuffer(const unsigned char* uncompressedData, + unsigned long uncompressedSize, + unsigned char* compressedData, + unsigned long compressionSpace); + // Decompression method required by vtkDataCompressor. + unsigned long UncompressBuffer(const unsigned char* compressedData, + unsigned long compressedSize, + unsigned char* uncompressedData, + unsigned long uncompressedSize); +private: + vtkZLibDataCompressor(const vtkZLibDataCompressor&); // Not implemented. + void operator=(const vtkZLibDataCompressor&); // Not implemented. +}; + +#endif diff --git a/Imaging/CMakeLists.txt b/Imaging/CMakeLists.txt new file mode 100644 index 0000000..5778f87 --- /dev/null +++ b/Imaging/CMakeLists.txt @@ -0,0 +1,152 @@ +SET(KIT Imaging) +SET(UKIT IMAGING) +SET(KIT_TCL_LIBS vtkFilteringTCL) +SET(KIT_PYTHON_LIBS vtkFilteringPythonD) +SET(KIT_JAVA_LIBS vtkFilteringJava) +SET(KIT_LIBS vtkFiltering) + +SET( Kit_SRCS +vtkBooleanTexture.cxx +vtkExtractVOI.cxx +vtkGaussianSplatter.cxx +vtkImageAccumulate.cxx +vtkImageAnisotropicDiffusion2D.cxx +vtkImageAnisotropicDiffusion3D.cxx +vtkImageAppend.cxx +vtkImageAppendComponents.cxx +vtkImageBlend.cxx +vtkImageButterworthHighPass.cxx +vtkImageButterworthLowPass.cxx +vtkImageCacheFilter.cxx +vtkImageCanvasSource2D.cxx +vtkImageCast.cxx +vtkImageChangeInformation.cxx +vtkImageCheckerboard.cxx +vtkImageCityBlockDistance.cxx +vtkImageClip.cxx +vtkImageConnector.cxx +vtkImageConstantPad.cxx +vtkImageContinuousDilate3D.cxx +vtkImageContinuousErode3D.cxx +vtkImageConvolve.cxx +vtkImageCorrelation.cxx +vtkImageCursor3D.cxx +vtkImageDataStreamer.cxx +vtkImageDecomposeFilter.cxx +vtkImageDifference.cxx +vtkImageDilateErode3D.cxx +vtkImageDivergence.cxx +vtkImageDotProduct.cxx +vtkImageEllipsoidSource.cxx +vtkImageEuclideanDistance.cxx +vtkImageEuclideanToPolar.cxx +vtkImageExport.cxx +vtkImageExtractComponents.cxx +vtkImageFFT.cxx +vtkImageFlip.cxx +vtkImageFourierCenter.cxx +vtkImageFourierFilter.cxx +vtkImageGaussianSmooth.cxx +vtkImageGaussianSource.cxx +vtkImageGradient.cxx +vtkImageGradientMagnitude.cxx +vtkImageGridSource.cxx +vtkImageHSIToRGB.cxx +vtkImageHSVToRGB.cxx +vtkImageHybridMedian2D.cxx +vtkImageIdealHighPass.cxx +vtkImageIdealLowPass.cxx +vtkImageImport.cxx +vtkImageImportExecutive.cxx +vtkImageIslandRemoval2D.cxx +vtkImageIterateFilter.cxx +vtkImageLaplacian.cxx +vtkImageLogarithmicScale.cxx +vtkImageLogic.cxx +vtkImageLuminance.cxx +vtkImageMagnify.cxx +vtkImageMagnitude.cxx +vtkImageMandelbrotSource.cxx +vtkImageMapToColors.cxx +vtkImageMapToRGBA.cxx +vtkImageMapToWindowLevelColors.cxx +vtkImageMask.cxx +vtkImageMaskBits.cxx +vtkImageMathematics.cxx +vtkImageMedian3D.cxx +vtkImageMirrorPad.cxx +vtkImageNoiseSource.cxx +vtkImageNonMaximumSuppression.cxx +vtkImageNormalize.cxx +vtkImageOpenClose3D.cxx +vtkImagePadFilter.cxx +vtkImagePermute.cxx +vtkImageQuantizeRGBToIndex.cxx +vtkImageRFFT.cxx +vtkImageRGBToHSI.cxx +vtkImageRGBToHSV.cxx +vtkImageRange3D.cxx +vtkImageRectilinearWipe.cxx +vtkImageResample.cxx +vtkImageReslice.cxx +vtkImageSeedConnectivity.cxx +vtkImageSeparableConvolution.cxx +vtkImageShiftScale.cxx +vtkImageShrink3D.cxx +vtkImageSinusoidSource.cxx +vtkImageSkeleton2D.cxx +vtkImageSobel2D.cxx +vtkImageSobel3D.cxx +vtkImageSpatialAlgorithm.cxx +vtkImageStencil.cxx +vtkImageStencilData.cxx +vtkImageStencilSource.cxx +vtkImageThreshold.cxx +vtkImageToImageStencil.cxx +vtkImageTranslateExtent.cxx +vtkImageVariance3D.cxx +vtkImageWrapPad.cxx +vtkImplicitFunctionToImageStencil.cxx +vtkPointLoad.cxx +vtkSampleFunction.cxx +vtkShepardMethod.cxx +vtkSimpleImageFilterExample.cxx +vtkSurfaceReconstructionFilter.cxx +vtkTriangularTexture.cxx +vtkVoxelModeller.cxx +) + +SET_SOURCE_FILES_PROPERTIES( +vtkImageDecomposeFilter +vtkImageFourierFilter +vtkImageIterateFilter +vtkImagePadFilter +vtkImageSpatialAlgorithm +vtkImageSpatialFilter + ABSTRACT +) + +# conditionally compile legacy classes +IF (NOT VTK_LEGACY_REMOVE) + SET (Kit_SRCS ${Kit_SRCS} + vtkImageSpatialFilter.cxx + ) + SET_SOURCE_FILES_PROPERTIES( + vtkImageSpatialFilter + ABSTRACT + ) +ENDIF (NOT VTK_LEGACY_REMOVE) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- diff --git a/Imaging/Testing/CMakeLists.txt b/Imaging/Testing/CMakeLists.txt new file mode 100644 index 0000000..c246a3f --- /dev/null +++ b/Imaging/Testing/CMakeLists.txt @@ -0,0 +1,33 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Imaging ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Imaging" + VTK_IMAGING_EXPORT + vtkImageAppendComponents.h + vtkImageCityBlockDistance.h + vtkImageDivergence.h + vtkImageDotProduct.h + vtkImageFFT.h + vtkImageFourierCenter.h + vtkImageFourierFilter.h + vtkImageHybridMedian2D.h + vtkImageLuminance.h + vtkImageMagnitude.h + vtkImageMapToRGBA.h + vtkImageMirrorPad.h + vtkImageNormalize.h + vtkImageRFFT.h + vtkImageWrapPad.h + vtkSimpleImageFilterExample.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/Imaging/Testing/Cxx/CMakeLists.txt b/Imaging/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..339add6 --- /dev/null +++ b/Imaging/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,24 @@ +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + SET(KIT Imaging) + CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx + ImportExport.cxx + EXTRA_INCLUDE vtkTestDriver.h + ) + ADD_EXECUTABLE(${KIT}CxxTests ${Tests}) + TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkRendering vtkIO) + SET (TestsToRun ${Tests}) + REMOVE (TestsToRun ${KIT}CxxTests.cxx) + + # + # Add all the executables + FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + IF (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName} + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/${KIT}/${TName}.png) + ENDIF (VTK_DATA_ROOT) + ENDFOREACH (test) +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + diff --git a/Imaging/Testing/Cxx/ImportExport.cxx b/Imaging/Testing/Cxx/ImportExport.cxx new file mode 100644 index 0000000..8778111 --- /dev/null +++ b/Imaging/Testing/Cxx/ImportExport.cxx @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ImportExport.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageViewer.h" +#include "vtkImageReader.h" +#include "vtkImageImport.h" +#include "vtkImageExport.h" +#include "vtkWindowToImageFilter.h" +#include "vtkPNMWriter.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" + +int ImportExport( int argc, char *argv[] ) +{ + int i,j,k; + + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter"); + + vtkImageReader *reader = vtkImageReader::New(); + reader->SetDataByteOrderToLittleEndian(); + reader->SetDataExtent(0,63,0,63,1,93); + reader->SetFilePrefix(fname); + reader->SetDataMask(0x7fff); + delete [] fname; + + // create exporter + vtkImageExport *exporter = vtkImageExport::New(); + exporter->SetInputConnection(reader->GetOutputPort()); + exporter->ImageLowerLeftOn(); + + // get info from exporter and create array to hold data + int memsize = exporter->GetDataMemorySize(); + int *dimensions = exporter->GetDataDimensions(); + + + // export the data into the array + short *data = new short[memsize/sizeof(short)]; + exporter->Export(data); + + // alternative method for getting data + // short *data = exporter->GetPointerToData(); + + // do a little something to the data + + for (i = 0; i < dimensions[2]; i++) + { + for (j = 0; j < dimensions[1]; j++) + { + for (k = 0; k < dimensions[0]; k++) + { + if (k % 10 == 0) + { + data[k + dimensions[0]*(j + dimensions[1]*i)] = 0; + } + if (j % 10 == 0) + { + data[k + dimensions[0]*(j + dimensions[1]*i)] = 1000; + } + } + } + } + + // create an importer to read the data back in + vtkImageImport *importer = vtkImageImport::New(); + importer->SetWholeExtent(1,dimensions[0],1,dimensions[1],1,dimensions[2]); + importer->SetDataExtentToWholeExtent(); + importer->SetDataScalarTypeToShort(); + importer->SetImportVoidPointer(data); + + + vtkImageViewer *viewer = vtkImageViewer::New(); + viewer->SetInputConnection(importer->GetOutputPort()); + viewer->SetZSlice(45); + viewer->SetColorWindow(2000); + viewer->SetColorLevel(1000); + + viewer->Render(); + + int retVal = vtkRegressionTestImage( viewer->GetRenderWindow() ); + + viewer->Delete(); + importer->Delete(); + exporter->Delete(); + reader->Delete(); + + delete [] data; + + return !retVal; +} + + + + diff --git a/Imaging/Testing/Python/CMakeLists.txt b/Imaging/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..be1bf40 --- /dev/null +++ b/Imaging/Testing/Python/CMakeLists.txt @@ -0,0 +1,91 @@ +INCLUDE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake) +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + IF (VTK_PYTHON_EXE) + SET(tests + ContinuousClose2D + IdealHighPass + LaplacianEdgeEnhance + #reconstructSurface -- scanf + resampledTexture + ResliceColorWrap + ResliceInterpolationModes + ResliceInterpolationOblique + ResliceMirrorOblique + ResliceMirrorPad + ResliceOptimizationOff + ReslicePermutations + ReslicePermuteResample + ResliceWrapOblique + ResliceWrapPad + Spectrum + TestAnisotropicDiffusion2D + TestAnisotropicDiffusion3D + TestAccumulate + #TestAllBlends -- complicated string substitutions + #TestAllBlendsFloat -- complicated string substitutions + TestAllFlips + #TestAllLogic -- method call has string substitution + #TestAllMaskBits -- method call has string substitution + #TestAllMathematics -- method call has string substitution + #TestAllShrinks -- method call has string substitution + TestButterworthLowPass + TestButterworthHighPass + TestCache + TestChangeInformation + TestCheckerboard + TestCityBlockDistance + TestConvolve + TestCorrelation + TestDivergence + TestDotProduct + TestEuclideanDistance + TestEuclideanDistanceCached + TestEuclideanToPolar + TestFFTCorrelation + TestGradientMagnitude + TestGradientMagnitude2 + TestHSIToRGB + TestHSVToRGB + TestHybridMedian2D + TestIdealLowPass + TestImageCanvas + TestInPlaceFilter + TestIslandRemoval2D + TestMapToRGBABlockStreaming + TestMapToWindowLevelColors + TestMapToWindowLevelColors2 + TestMask2 + TestMedian3D + TestNormalize + TestOpenClose3D + TestPermute + TestQuantizeTo16Colors + TestRange3D + TestResample + TestSeparableFilter + TestShiftScale + TestShiftScale2 + TestSimpleImageExample + TestSkeleton2D + TestSobel2D + TestSobel3D + TestStencilWithFunction + TestStencilWithImage + #TestThreshold -- uses lists in lists etc... + TestVariance3D + #TestWipe -- method call has string substitution + TestWrapPad + voxelModel + ) + + CONVERT_TCL_TEST_TO_PY ( + tests + Imaging) + + ENDIF (VTK_PYTHON_EXE) + ENDIF (VTK_DATA_ROOT) + ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) diff --git a/Imaging/Testing/Python/TestNumericArrayImageData.py b/Imaging/Testing/Python/TestNumericArrayImageData.py new file mode 100644 index 0000000..7462664 --- /dev/null +++ b/Imaging/Testing/Python/TestNumericArrayImageData.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +""" +This file tests vtk.util.vtkImageExportToArray and +vtk.util.vtkImageImportFromArray. It tests the code by first +exporting a PNG image to a Numeric Array and then converts the array +to an image and compares that image to the original image. It does +this for all PNG images in a particular directory. + +The test naturally requires Numeric Python to be installed: + http://numpy.sf.net + +Run this test like so: +vtkpython TestNumericArrayImageData.py -B $VTK_DATA_ROOT/Baseline/Imaging + +""" + +# This test requires Numeric. +import sys +try: + import Numeric +except ImportError: + print "This test requires Numeric Python: http://numpy.sf.net" + sys.exit(1) + +import os +import glob +import vtk +from vtk.test import Testing +from vtk.util.vtkImageExportToArray import vtkImageExportToArray +from vtk.util.vtkImageImportFromArray import vtkImageImportFromArray + + +class TestNumericArrayImageData(Testing.vtkTest): + def testImportExport(self): + "Testing if images can be imported to and from numeric arrays." + imp = vtkImageImportFromArray() + exp = vtkImageExportToArray() + idiff = vtk.vtkImageDifference() + + img_dir = Testing.getAbsImagePath("") + for i in glob.glob(os.path.join(img_dir, "*.png")): + # Putting the reader outside the loop causes bad problems. + reader = vtk.vtkPNGReader() + reader.SetFileName(i) + reader.Update() + + # convert the image to a Numeric Array and convert it back + # to an image data. + exp.SetInputConnection(reader.GetOutputPort()) + imp.SetArray(exp.GetArray()) + + # ensure there is no difference between orig image and the + # one we converted and un-converted. + idiff.SetInputConnection(imp.GetOutputPort()) + idiff.SetImage(reader.GetOutput()) + idiff.Update() + err = idiff.GetThresholdedError() + + msg = "Test failed on image %s, with threshold "\ + "error: %d"%(i, err) + self.assertEqual(err, 0.0, msg) + + +if __name__ == "__main__": + Testing.main([(TestNumericArrayImageData, 'test')]) diff --git a/Imaging/Testing/Tcl/CMakeLists.txt b/Imaging/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..171884b --- /dev/null +++ b/Imaging/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,104 @@ +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + FOREACH ( tfile + ContinuousClose2D + IdealHighPass + LaplacianEdgeEnhance + reconstructSurface + resampledTexture + ResliceColorWrap + ResliceInterpolationModes + ResliceInterpolationOblique + ResliceMirrorOblique + ResliceMirrorPad + ResliceOptimizationOff + ReslicePermutations + ReslicePermuteResample + ResliceWrapOblique + ResliceWrapPad + Spectrum + TestAnisotropicDiffusion2D + TestAnisotropicDiffusion3D + TestAccumulate + TestAllBlends + TestAllBlendsFloat + TestAllFlips + TestAllLogic + TestAllMaskBits + TestAllMathematics + TestAllShrinks + TestButterworthLowPass + TestButterworthHighPass + TestCache + TestChangeInformation + TestCheckerboard + TestCityBlockDistance + TestConvolve + TestCorrelation + TestDivergence + TestDotProduct + TestEuclideanDistance + TestEuclideanDistanceCached + TestEuclideanToPolar + TestFFTCorrelation + TestGradientMagnitude + TestGradientMagnitude2 + TestHSIToRGB + TestHSVToRGB + TestHybridMedian2D + TestIdealLowPass + TestImageCanvas + TestInPlaceFilter + TestIslandRemoval2D + TestMapToRGBABlockStreaming + TestMapToWindowLevelColors + TestMapToWindowLevelColors2 + TestMask2 + TestMedian3D + TestNormalize + TestOpenClose3D + TestPermute + TestQuantizeTo16Colors + TestRange3D + TestResample + TestSeparableFilter + TestShiftScale + TestShiftScale2 + TestSimpleImageExample + TestSkeleton2D + TestSobel2D + TestSobel3D + TestStencilWithFunction + TestStencilWithImage + TestThreshold + TestVariance3D + TestWipe + TestWrapPad + voxelModel + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Imaging/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Imaging/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl + ) + ENDFOREACH ( tfile ) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + +ADD_TEST(PrintSelf-Imaging ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Imaging) + +ADD_TEST(TestSetObjectMacro-Imaging ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Imaging/vtk\\\\*.h" + "vtkSetObjectMacro" + ) diff --git a/Imaging/Testing/Tcl/ContinuousClose2D.tcl b/Imaging/Testing/Tcl/ContinuousClose2D.tcl new file mode 100644 index 0000000..dac3022 --- /dev/null +++ b/Imaging/Testing/Tcl/ContinuousClose2D.tcl @@ -0,0 +1,28 @@ +package require vtk + + +# Image pipeline + +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageContinuousDilate3D dilate +dilate SetInputConnection [reader GetOutputPort] +dilate SetKernelSize 11 11 1 + +vtkImageContinuousErode3D erode +erode SetInputConnection [dilate GetOutputPort] +erode SetKernelSize 11 11 1 + +vtkImageViewer viewer +viewer SetInputConnection [erode GetOutputPort] +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 + + +viewer Render + + diff --git a/Imaging/Testing/Tcl/IdealHighPass.tcl b/Imaging/Testing/Tcl/IdealHighPass.tcl new file mode 100644 index 0000000..6b8d3fd --- /dev/null +++ b/Imaging/Testing/Tcl/IdealHighPass.tcl @@ -0,0 +1,42 @@ +package require vtk + +# This script shows the result of an ideal highpass filter in spatial domain + + +# Image pipeline +vtkImageReader2Factory createReader +set reader [createReader CreateImageReader2 "$VTK_DATA_ROOT/Data/fullhead15.png"] +$reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageFFT fft +fft SetInputConnection [$reader GetOutputPort] + +vtkImageIdealHighPass highPass +highPass SetInputConnection [fft GetOutputPort] +highPass SetXCutOff 0.1 +highPass SetYCutOff 0.1 +highPass ReleaseDataFlagOff + +vtkImageRFFT rfft +rfft SetInputConnection [highPass GetOutputPort] + +vtkImageExtractComponents real +real SetInputConnection [rfft GetOutputPort] +real SetComponents 0 + + +vtkImageViewer viewer +viewer SetInputConnection [real GetOutputPort] +viewer SetColorWindow 500 +viewer SetColorLevel 0 + + +viewer Render +$reader UnRegister viewer + + + + + + + diff --git a/Imaging/Testing/Tcl/LaplacianEdgeEnhance.tcl b/Imaging/Testing/Tcl/LaplacianEdgeEnhance.tcl new file mode 100644 index 0000000..7adbda5 --- /dev/null +++ b/Imaging/Testing/Tcl/LaplacianEdgeEnhance.tcl @@ -0,0 +1,38 @@ +package require vtk + +# This script subtracts the 2D laplacian from an image to enhance the edges. + + + +# Image pipeline +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageCast cast +cast SetInputConnection [reader GetOutputPort] +cast SetOutputScalarTypeToDouble + +vtkImageLaplacian lap +lap SetInputConnection [cast GetOutputPort] +lap SetDimensionality 2 + +vtkImageMathematics subtract +subtract SetOperationToSubtract +subtract SetInput1 [cast GetOutput] +subtract SetInput2 [lap GetOutput] +subtract ReleaseDataFlagOff +#subtract BypassOn + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [subtract GetOutputPort] +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 + + +viewer Render + + + + + diff --git a/Imaging/Testing/Tcl/ResliceColorWrap.tcl b/Imaging/Testing/Tcl/ResliceColorWrap.tcl new file mode 100644 index 0000000..800aedb --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceColorWrap.tcl @@ -0,0 +1,34 @@ +package require vtk + +# we have to make sure it works with multiple scalar components + +# Image pipeline + +vtkBMPReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + reader SetDataExtent 0 255 0 255 0 0 + reader SetDataSpacing 1 1 1 + reader SetDataOrigin 0 0 0 + reader UpdateWholeExtent + +vtkTransform transform + transform RotateZ 45 + transform Scale 1.414 1.414 1.414 + +vtkImageReslice reslice + reslice SetInputConnection [reader GetOutputPort] + reslice SetResliceTransform transform + reslice InterpolateOn + reslice SetInterpolationModeToCubic + reslice WrapOn + reslice AutoCropOutputOn + +vtkImageViewer viewer + viewer SetInputConnection [reslice GetOutputPort] + viewer SetZSlice 0 + viewer SetColorWindow 256.0 + viewer SetColorLevel 127.5 + viewer Render + + + diff --git a/Imaging/Testing/Tcl/ResliceInterpolationModes.tcl b/Imaging/Testing/Tcl/ResliceInterpolationModes.tcl new file mode 100644 index 0000000..3b8a9dd --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceInterpolationModes.tcl @@ -0,0 +1,104 @@ +package require vtk + +# this script tests vtkImageReslice with different interpolation modes + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 SetInterpolationModeToCubic +reslice1 SetOutputSpacing 0.65 0.65 1.5 +reslice1 SetOutputOrigin 80 120 40 +reslice1 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 SetInterpolationModeToLinear +reslice2 SetOutputSpacing 0.65 0.65 1.5 +reslice2 SetOutputOrigin 80 120 40 +reslice2 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 SetInterpolationModeToNearestNeighbor +reslice3 SetOutputSpacing 0.65 0.65 1.5 +reslice3 SetOutputOrigin 80 120 40 +reslice3 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 SetInterpolationModeToLinear +reslice4 SetOutputSpacing 3.2 3.2 1.5 +reslice4 SetOutputOrigin 0 0 40 +reslice4 SetOutputExtent 0 63 0 63 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.5 0.0 1.0 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.0 0.5 0.5 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.5 0.5 1.0 1.0 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.0 0.5 0.5 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin SetSize 150 128 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/ResliceInterpolationOblique.tcl b/Imaging/Testing/Tcl/ResliceInterpolationOblique.tcl new file mode 100644 index 0000000..5a4dd48 --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceInterpolationOblique.tcl @@ -0,0 +1,115 @@ +package require vtk + +# this script tests vtkImageReslice with different interpolation modes +# and with a rotation + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkTransform transform +# rotate about the center of the image +transform Translate +100.8 +100.8 +69.0 +transform RotateWXYZ 10 1 1 0 +transform Translate -100.8 -100.8 -69.0 + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 SetResliceTransform transform +reslice1 SetInterpolationModeToCubic +reslice1 SetOutputSpacing 0.65 0.65 1.5 +reslice1 SetOutputOrigin 80 120 40 +reslice1 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 SetResliceTransform transform +reslice2 SetInterpolationModeToLinear +reslice2 SetOutputSpacing 0.65 0.65 1.5 +reslice2 SetOutputOrigin 80 120 40 +reslice2 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 SetResliceTransform transform +reslice3 SetInterpolationModeToNearestNeighbor +reslice3 SetOutputSpacing 0.65 0.65 1.5 +reslice3 SetOutputOrigin 80 120 40 +reslice3 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 SetResliceTransform transform +reslice4 SetInterpolationModeToLinear +reslice4 SetOutputSpacing 3.2 3.2 1.5 +reslice4 SetOutputOrigin 0 0 40 +reslice4 SetOutputExtent 0 63 0 63 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.5 0.0 1.0 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.0 0.5 0.5 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.5 0.5 1.0 1.0 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.0 0.5 0.5 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin SetSize 150 128 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/ResliceMirrorOblique.tcl b/Imaging/Testing/Tcl/ResliceMirrorOblique.tcl new file mode 100644 index 0000000..fcb39cf --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceMirrorOblique.tcl @@ -0,0 +1,119 @@ +package require vtk + +# this script tests vtkImageReslice with different interpolation modes, +# with the wrap-pad feature turned on and with a rotation + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkTransform transform +# rotate about the center of the image +transform Translate +100.8 +100.8 +69.0 +transform RotateWXYZ 100 0.1 0.1 1 +transform Translate -100.8 -100.8 -69.0 + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 MirrorOn +reslice1 SetResliceTransform transform +reslice1 SetInterpolationModeToCubic +reslice1 SetOutputSpacing 2.0 2.0 1.5 +reslice1 SetOutputOrigin -32 -32 40 +reslice1 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 MirrorOn +reslice2 SetResliceTransform transform +reslice2 SetInterpolationModeToLinear +reslice2 SetOutputSpacing 2.0 2.0 1.5 +reslice2 SetOutputOrigin -32 -32 40 +reslice2 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 MirrorOn +reslice3 SetResliceTransform transform +reslice3 SetInterpolationModeToNearestNeighbor +reslice3 SetOutputSpacing 2.0 2.0 1.5 +reslice3 SetOutputOrigin -32 -32 40 +reslice3 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 MirrorOn +reslice4 SetResliceTransform transform +reslice4 SetInterpolationModeToLinear +reslice4 SetOutputSpacing 3.2 3.2 1.5 +reslice4 SetOutputOrigin -102.4 -102.4 40 +reslice4 SetOutputExtent 0 127 0 127 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.5 0.0 1.0 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.0 0.5 0.5 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.5 0.5 1.0 1.0 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.0 0.5 0.5 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin SetSize 256 256 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/ResliceMirrorPad.tcl b/Imaging/Testing/Tcl/ResliceMirrorPad.tcl new file mode 100644 index 0000000..171c3cf --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceMirrorPad.tcl @@ -0,0 +1,117 @@ +package require vtk + +# this script tests vtkImageReslice with different interpolation modes, +# with the wrap-pad feature turned on + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 MirrorOn +reslice1 SetInterpolationModeToCubic +reslice1 SetResliceAxesDirectionCosines 0 1 0 -1 0 0 0 0 1 +reslice1 SetResliceAxesOrigin 0 0 40 +reslice1 SetOutputSpacing 2.0 2.0 1.5 +reslice1 SetOutputOrigin -32 -32 0 +reslice1 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 MirrorOn +reslice2 SetResliceAxesDirectionCosines 0 1 0 -1 0 0 0 0 1 +reslice2 SetResliceAxesOrigin 0 0 40 +reslice2 SetInterpolationModeToLinear +reslice2 SetOutputSpacing 2.0 2.0 1.5 +reslice2 SetOutputOrigin -32 -32 0 +reslice2 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 MirrorOn +reslice3 SetResliceAxesDirectionCosines 0 1 0 -1 0 0 0 0 1 +reslice3 SetResliceAxesOrigin 0 0 40 +reslice3 SetInterpolationModeToNearestNeighbor +reslice3 SetOutputSpacing 2.0 2.0 1.5 +reslice3 SetOutputOrigin -32 -32 0 +reslice3 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 MirrorOn +reslice4 SetResliceAxesDirectionCosines 0 1 0 -1 0 0 0 0 1 +reslice4 SetResliceAxesOrigin 0 0 40 +reslice4 SetInterpolationModeToLinear +reslice4 SetOutputSpacing 3.2 3.2 1.5 +reslice4 SetOutputOrigin -102.4 -102.4 0 +reslice4 SetOutputExtent 0 127 0 127 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.5 0.0 1.0 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.0 0.5 0.5 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.5 0.5 1.0 1.0 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.0 0.5 0.5 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin SetSize 256 256 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/ResliceOptimizationOff.tcl b/Imaging/Testing/Tcl/ResliceOptimizationOff.tcl new file mode 100644 index 0000000..400eff8 --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceOptimizationOff.tcl @@ -0,0 +1,120 @@ +package require vtk + +# this script tests the unoptimized code path in vtkImageReslice + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkTransform transform +# rotate about the center of the image +transform Translate +100.8 +100.8 +69.0 +transform RotateWXYZ 10 1 1 0 +transform Translate -100.8 -100.8 -69.0 + +vtkMatrix4x4 matrix + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 OptimizationOff +reslice1 SetInterpolationModeToCubic +reslice1 SetOutputSpacing 0.65 0.65 1.5 +reslice1 SetOutputOrigin 80 120 40 +reslice1 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 OptimizationOff +reslice2 SetResliceAxes [transform GetMatrix] +reslice2 SetInterpolationModeToLinear +reslice2 SetOutputSpacing 0.65 0.65 1.5 +reslice2 SetOutputOrigin 80 120 40 +reslice2 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 OptimizationOff +reslice3 SetResliceTransform transform +reslice3 SetInterpolationModeToNearestNeighbor +reslice3 SetOutputSpacing 0.65 0.65 1.5 +reslice3 SetOutputOrigin 80 120 40 +reslice3 SetOutputExtent 0 63 0 63 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 OptimizationOff +reslice4 SetResliceAxes matrix +reslice4 SetResliceTransform transform +reslice4 SetInterpolationModeToLinear +reslice4 SetOutputSpacing 3.2 3.2 1.5 +reslice4 SetOutputOrigin 0 0 40 +reslice4 SetOutputExtent 0 63 0 63 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.5 0.0 1.0 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.0 0.5 0.5 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.5 0.5 1.0 1.0 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.0 0.5 0.5 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin SetSize 150 128 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/ReslicePermutations.tcl b/Imaging/Testing/Tcl/ReslicePermutations.tcl new file mode 100644 index 0000000..9fd85dd --- /dev/null +++ b/Imaging/Testing/Tcl/ReslicePermutations.tcl @@ -0,0 +1,154 @@ +package require vtk + +# this script tests vtkImageReslice with various axes permutations, +# in order to cover a nasty set of "if" statements that check +# the intersections of the raster lines with the input bounding box. + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkTransform transform +# rotate about the center of the image +transform Translate +100.8 +100.8 +69.0 +transform RotateWXYZ 10 1 1 0 +transform Translate -100.8 -100.8 -69.0 + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 SetResliceAxesDirectionCosines 1 0 0 0 1 0 0 0 1 +reslice1 SetResliceTransform transform +reslice1 SetOutputSpacing 3.2 3.2 3.2 +reslice1 SetOutputExtent 0 74 0 74 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 SetResliceAxesDirectionCosines 0 1 0 0 0 1 1 0 0 +reslice2 SetResliceTransform transform +reslice2 SetOutputSpacing 3.2 3.2 3.2 +reslice2 SetOutputExtent 0 74 0 74 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 SetResliceAxesDirectionCosines 0 0 1 1 0 0 0 1 0 +reslice3 SetResliceTransform transform +reslice3 SetOutputSpacing 3.2 3.2 3.2 +reslice3 SetOutputExtent 0 74 0 74 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 SetResliceAxesDirectionCosines -1 0 0 0 -1 0 0 0 -1 +reslice4 SetResliceTransform transform +reslice4 SetOutputSpacing 3.2 3.2 3.2 +reslice4 SetOutputExtent 0 74 0 74 0 0 + +vtkImageReslice reslice5 +reslice5 SetInputConnection [reader GetOutputPort] +reslice5 SetResliceAxesDirectionCosines 0 -1 0 0 0 -1 -1 0 0 +reslice5 SetResliceTransform transform +reslice5 SetOutputSpacing 3.2 3.2 3.2 +reslice5 SetOutputExtent 0 74 0 74 0 0 + +vtkImageReslice reslice6 +reslice6 SetInputConnection [reader GetOutputPort] +reslice6 SetResliceAxesDirectionCosines 0 0 -1 -1 0 0 0 -1 0 +reslice6 SetResliceTransform transform +reslice6 SetOutputSpacing 3.2 3.2 3.2 +reslice6 SetOutputExtent 0 74 0 74 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkImageMapper mapper5 + mapper5 SetInputConnection [reslice5 GetOutputPort] + mapper5 SetColorWindow 2000 + mapper5 SetColorLevel 1000 + mapper5 SetZSlice 0 + +vtkImageMapper mapper6 + mapper6 SetInputConnection [reslice6 GetOutputPort] + mapper6 SetColorWindow 2000 + mapper6 SetColorLevel 1000 + mapper6 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkActor2D actor5 + actor5 SetMapper mapper5 + +vtkActor2D actor6 + actor6 SetMapper mapper6 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.0 0.0 0.3333 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.5 0.3333 1.0 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.3333 0.0 0.6667 0.5 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.3333 0.5 0.6667 1.0 + +vtkRenderer imager5 + imager5 AddActor2D actor5 + imager5 SetViewport 0.6667 0.0 1.0 0.5 + +vtkRenderer imager6 + imager6 AddActor2D actor6 + imager6 SetViewport 0.6667 0.5 1.0 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin AddRenderer imager5 + imgWin AddRenderer imager6 + imgWin SetSize 225 150 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/ReslicePermuteResample.tcl b/Imaging/Testing/Tcl/ReslicePermuteResample.tcl new file mode 100644 index 0000000..ee7e8eb --- /dev/null +++ b/Imaging/Testing/Tcl/ReslicePermuteResample.tcl @@ -0,0 +1,37 @@ +package require vtk + +# This example demonstrates how to permute an image with vtkImageReslice. +# The advantage of using vtkImageReslice for this (rather than +# vtkImagePermute) is that you can specify negative or even oblique axes, +# and you can resample the image at the same time. + +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageReslice reslice +reslice SetInputConnection [reader GetOutputPort] +# specify the new axes in terms of the original axes +reslice SetResliceAxesDirectionCosines 0 +1 0 0 0 -1 -1 0 0 +# resample the image to enlarge & to get the aspect right +reslice SetOutputSpacing 1.0 1.0 1.0 + +vtkImageViewer viewer +viewer SetInputConnection [reslice GetOutputPort] +viewer SetZSlice 100 +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 +viewer Render + + + + + + + + + diff --git a/Imaging/Testing/Tcl/ResliceWrapOblique.tcl b/Imaging/Testing/Tcl/ResliceWrapOblique.tcl new file mode 100644 index 0000000..480238f --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceWrapOblique.tcl @@ -0,0 +1,119 @@ +package require vtk + +# this script tests vtkImageReslice with different interpolation modes, +# with the wrap-pad feature turned on and with a rotation + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkTransform transform +# rotate about the center of the image +transform Translate +100.8 +100.8 +69.0 +transform RotateWXYZ 10 1 1 0 +transform Translate -100.8 -100.8 -69.0 + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 WrapOn +reslice1 SetResliceTransform transform +reslice1 SetInterpolationModeToCubic +reslice1 SetOutputSpacing 2.0 2.0 1.5 +reslice1 SetOutputOrigin -32 -32 40 +reslice1 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 WrapOn +reslice2 SetResliceTransform transform +reslice2 SetInterpolationModeToLinear +reslice2 SetOutputSpacing 2.0 2.0 1.5 +reslice2 SetOutputOrigin -32 -32 40 +reslice2 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 WrapOn +reslice3 SetResliceTransform transform +reslice3 SetInterpolationModeToNearestNeighbor +reslice3 SetOutputSpacing 2.0 2.0 1.5 +reslice3 SetOutputOrigin -32 -32 40 +reslice3 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 WrapOn +reslice4 SetResliceTransform transform +reslice4 SetInterpolationModeToLinear +reslice4 SetOutputSpacing 3.2 3.2 1.5 +reslice4 SetOutputOrigin -102.4 -102.4 40 +reslice4 SetOutputExtent 0 127 0 127 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.5 0.0 1.0 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.0 0.5 0.5 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.5 0.5 1.0 1.0 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.0 0.5 0.5 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin SetSize 256 256 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/ResliceWrapPad.tcl b/Imaging/Testing/Tcl/ResliceWrapPad.tcl new file mode 100644 index 0000000..1901715 --- /dev/null +++ b/Imaging/Testing/Tcl/ResliceWrapPad.tcl @@ -0,0 +1,109 @@ +package require vtk + +# this script tests vtkImageReslice with different interpolation modes, +# with the wrap-pad feature turned on + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageReslice reslice1 +reslice1 SetInputConnection [reader GetOutputPort] +reslice1 WrapOn +reslice1 SetInterpolationModeToCubic +reslice1 SetOutputSpacing 2.0 2.0 1.5 +reslice1 SetOutputOrigin -32 -32 40 +reslice1 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice2 +reslice2 SetInputConnection [reader GetOutputPort] +reslice2 WrapOn +reslice2 SetInterpolationModeToLinear +reslice2 SetOutputSpacing 2.0 2.0 1.5 +reslice2 SetOutputOrigin -32 -32 40 +reslice2 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice3 +reslice3 SetInputConnection [reader GetOutputPort] +reslice3 WrapOn +reslice3 SetInterpolationModeToNearestNeighbor +reslice3 SetOutputSpacing 2.0 2.0 1.5 +reslice3 SetOutputOrigin -32 -32 40 +reslice3 SetOutputExtent 0 127 0 127 0 0 + +vtkImageReslice reslice4 +reslice4 SetInputConnection [reader GetOutputPort] +reslice4 WrapOn +reslice4 SetInterpolationModeToLinear +reslice4 SetOutputSpacing 3.2 3.2 1.5 +reslice4 SetOutputOrigin -102.4 -102.4 40 +reslice4 SetOutputExtent 0 127 0 127 0 0 + +vtkImageMapper mapper1 + mapper1 SetInputConnection [reslice1 GetOutputPort] + mapper1 SetColorWindow 2000 + mapper1 SetColorLevel 1000 + mapper1 SetZSlice 0 + +vtkImageMapper mapper2 + mapper2 SetInputConnection [reslice2 GetOutputPort] + mapper2 SetColorWindow 2000 + mapper2 SetColorLevel 1000 + mapper2 SetZSlice 0 + +vtkImageMapper mapper3 + mapper3 SetInputConnection [reslice3 GetOutputPort] + mapper3 SetColorWindow 2000 + mapper3 SetColorLevel 1000 + mapper3 SetZSlice 0 + +vtkImageMapper mapper4 + mapper4 SetInputConnection [reslice4 GetOutputPort] + mapper4 SetColorWindow 2000 + mapper4 SetColorLevel 1000 + mapper4 SetZSlice 0 + +vtkActor2D actor1 + actor1 SetMapper mapper1 + +vtkActor2D actor2 + actor2 SetMapper mapper2 + +vtkActor2D actor3 + actor3 SetMapper mapper3 + +vtkActor2D actor4 + actor4 SetMapper mapper4 + +vtkRenderer imager1 + imager1 AddActor2D actor1 + imager1 SetViewport 0.5 0.0 1.0 0.5 + +vtkRenderer imager2 + imager2 AddActor2D actor2 + imager2 SetViewport 0.0 0.0 0.5 0.5 + +vtkRenderer imager3 + imager3 AddActor2D actor3 + imager3 SetViewport 0.5 0.5 1.0 1.0 + +vtkRenderer imager4 + imager4 AddActor2D actor4 + imager4 SetViewport 0.0 0.5 0.5 1.0 + +vtkRenderWindow imgWin + imgWin AddRenderer imager1 + imgWin AddRenderer imager2 + imgWin AddRenderer imager3 + imgWin AddRenderer imager4 + imgWin SetSize 256 256 + +imgWin Render + + + diff --git a/Imaging/Testing/Tcl/Spectrum.tcl b/Imaging/Testing/Tcl/Spectrum.tcl new file mode 100644 index 0000000..5af7722 --- /dev/null +++ b/Imaging/Testing/Tcl/Spectrum.tcl @@ -0,0 +1,43 @@ +package require vtk + +# This scripts shows a compressed spectrum of an image. + + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageFFT fft +fft SetInputConnection [reader GetOutputPort] +fft ReleaseDataFlagOff +#fft DebugOn + +vtkImageMagnitude magnitude +magnitude SetInputConnection [fft GetOutputPort] +magnitude ReleaseDataFlagOff + +vtkImageFourierCenter center +center SetInputConnection [magnitude GetOutputPort] + +vtkImageLogarithmicScale compress +compress SetInputConnection [center GetOutputPort] +compress SetConstant 15 + +vtkImageViewer2 viewer +viewer SetInputConnection [compress GetOutputPort] +viewer SetColorWindow 150 +viewer SetColorLevel 170 + +vtkRenderWindowInteractor viewInt +viewer SetupInteractor viewInt +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestAccumulate.tcl b/Imaging/Testing/Tcl/TestAccumulate.tcl new file mode 100644 index 0000000..06681ff --- /dev/null +++ b/Imaging/Testing/Tcl/TestAccumulate.tcl @@ -0,0 +1,46 @@ +package require vtk + + + + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageGaussianSmooth smooth + smooth SetDimensionality 2 + smooth SetStandardDeviations 1 1 + smooth SetInputConnection [reader GetOutputPort] + +vtkImageAppendComponents imageAppend + imageAppend AddInput [reader GetOutput] + imageAppend AddInput [smooth GetOutput] + +vtkImageClip clip + clip SetInputConnection [imageAppend GetOutputPort] + clip SetOutputWholeExtent 0 255 0 255 20 22 + +vtkImageAccumulate accum + accum SetInputConnection [clip GetOutputPort] + accum SetComponentExtent 0 255 0 255 0 0 + accum SetComponentSpacing 12 12 0.0 + + +vtkImageViewer viewer + viewer SetInputConnection [accum GetOutputPort] + viewer SetColorWindow 4 + viewer SetColorLevel 2 + + +viewer Render + + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestAllBlends.tcl b/Imaging/Testing/Tcl/TestAllBlends.tcl new file mode 100644 index 0000000..21e71c4 --- /dev/null +++ b/Imaging/Testing/Tcl/TestAllBlends.tcl @@ -0,0 +1,103 @@ +package require vtk + +# This script calculates the luminanace of an image + +vtkRenderWindow imgWin +imgWin SetSize 512 256 + +# Image pipeline + +vtkTIFFReader image1 + image1 SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + +vtkBMPReader image2 + image2 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +# shrink the images to a reasonable size + +vtkImageShrink3D color +color SetInputConnection [image1 GetOutputPort] +color SetShrinkFactors 2 2 1 + +vtkImageShrink3D backgroundColor +backgroundColor SetInputConnection [image2 GetOutputPort] +backgroundColor SetShrinkFactors 2 2 1 + +# create a greyscale version + +vtkImageLuminance luminance +luminance SetInputConnection [color GetOutputPort] + +vtkImageLuminance backgroundLuminance +backgroundLuminance SetInputConnection [backgroundColor GetOutputPort] + +# create an alpha mask + +vtkLookupTable table +table SetTableRange 220 255 +table SetValueRange 1 0 +table SetSaturationRange 0 0 +table Build + +vtkImageMapToColors alpha +alpha SetInputConnection [luminance GetOutputPort] +alpha SetLookupTable table +alpha SetOutputFormatToLuminance + +# make luminanceAlpha and colorAlpha versions + +vtkImageAppendComponents luminanceAlpha +luminanceAlpha AddInput [luminance GetOutput] +luminanceAlpha AddInput [alpha GetOutput] + +vtkImageAppendComponents colorAlpha +colorAlpha AddInput [color GetOutput] +colorAlpha AddInput [alpha GetOutput] + +set foregrounds "luminance luminanceAlpha color colorAlpha" +set backgrounds "backgroundColor backgroundLuminance" + +set column 1 +set row 1 +set deltaX [expr 1.0/4.0] +set deltaY [expr 1.0/2.0] + +foreach background $backgrounds { + foreach foreground $foregrounds { + vtkImageBlend blend${row}${column} + blend${row}${column} AddInput [$background GetOutput] + if { $background == "backgroundColor" || $foreground == "luminance" || $foreground == "luminanceAlpha" } { + blend${row}${column} AddInput [$foreground GetOutput] + blend${row}${column} SetOpacity 1 0.8 + } + + vtkImageMapper mapper${row}${column} + mapper${row}${column} SetInputConnection [blend${row}${column} GetOutputPort] + mapper${row}${column} SetColorWindow 255 + mapper${row}${column} SetColorLevel 127.5 + + vtkActor2D actor${row}${column} + actor${row}${column} SetMapper mapper${row}${column} + + vtkRenderer imager${row}${column} + imager${row}${column} AddActor2D actor${row}${column} + + imager${row}${column} SetViewport [expr ($column - 1) * $deltaX] [expr ($row - 1) * $deltaY] [expr $column * $deltaX] [expr $row * $deltaY] + + imgWin AddRenderer imager${row}${column} + + incr column + } + incr row + set column 1 +} + +imgWin Render + +wm withdraw . + + + + + + diff --git a/Imaging/Testing/Tcl/TestAllBlendsFloat.tcl b/Imaging/Testing/Tcl/TestAllBlendsFloat.tcl new file mode 100644 index 0000000..b4efe90 --- /dev/null +++ b/Imaging/Testing/Tcl/TestAllBlendsFloat.tcl @@ -0,0 +1,110 @@ +package require vtk + +# This script blends images that consist of float data + +vtkRenderWindow imgWin +imgWin SetSize 512 256 + +# Image pipeline + +vtkTIFFReader inputImage + inputImage SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + +vtkBMPReader inputImage2 + inputImage2 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +# shrink the images to a reasonable size + +vtkImageShrink3D shrink1 +shrink1 SetInputConnection [inputImage GetOutputPort] +shrink1 SetShrinkFactors 2 2 1 + +vtkImageShrink3D shrink2 +shrink2 SetInputConnection [inputImage2 GetOutputPort] +shrink2 SetShrinkFactors 2 2 1 + +vtkImageShiftScale color +color SetOutputScalarTypeToFloat +color SetShift 0 +color SetScale [expr 1.0/255] +color SetInputConnection [shrink1 GetOutputPort] + +vtkImageShiftScale backgroundColor +backgroundColor SetOutputScalarTypeToFloat +backgroundColor SetShift 0 +backgroundColor SetScale [expr 1.0/255] +backgroundColor SetInputConnection [shrink2 GetOutputPort] + +# create a greyscale version + +vtkImageLuminance luminance +luminance SetInputConnection [color GetOutputPort] + +vtkImageLuminance backgroundLuminance +backgroundLuminance SetInputConnection [backgroundColor GetOutputPort] + +# create an alpha mask + +vtkImageThreshold alpha +alpha SetInputConnection [luminance GetOutputPort] +alpha ThresholdByLower 0.9 +alpha SetInValue 1.0 +alpha SetOutValue 0.0 + +# make luminanceAlpha and colorAlpha versions + +vtkImageAppendComponents luminanceAlpha +luminanceAlpha AddInput [luminance GetOutput] +luminanceAlpha AddInput [alpha GetOutput] + +vtkImageAppendComponents colorAlpha +colorAlpha AddInput [color GetOutput] +colorAlpha AddInput [alpha GetOutput] + +set foregrounds "luminance luminanceAlpha color colorAlpha" +set backgrounds "backgroundColor backgroundLuminance" + +set column 1 +set row 1 +set deltaX [expr 1.0/4.0] +set deltaY [expr 1.0/2.0] + +foreach background $backgrounds { + foreach foreground $foregrounds { + vtkImageBlend blend${row}${column} + blend${row}${column} AddInput [$background GetOutput] + if { $background == "backgroundColor" || $foreground == "luminance" || $foreground == "luminanceAlpha" } { + blend${row}${column} AddInput [$foreground GetOutput] + blend${row}${column} SetOpacity 1 0.8 + } + + vtkImageMapper mapper${row}${column} + mapper${row}${column} SetInputConnection [blend${row}${column} GetOutputPort] + mapper${row}${column} SetColorWindow 1.0 + mapper${row}${column} SetColorLevel 0.5 + + vtkActor2D actor${row}${column} + actor${row}${column} SetMapper mapper${row}${column} + + vtkRenderer imager${row}${column} + imager${row}${column} AddActor2D actor${row}${column} + + imager${row}${column} SetViewport [expr ($column - 1) * $deltaX] [expr ($row - 1) * $deltaY] [expr $column * $deltaX] [expr $row * $deltaY] + + imgWin AddRenderer imager${row}${column} + + incr column + } + incr row + set column 1 +} + +imgWin Render + +wm withdraw . + + + + + + diff --git a/Imaging/Testing/Tcl/TestAllFlips.tcl b/Imaging/Testing/Tcl/TestAllFlips.tcl new file mode 100644 index 0000000..fb8c95d --- /dev/null +++ b/Imaging/Testing/Tcl/TestAllFlips.tcl @@ -0,0 +1,46 @@ +package require vtk + + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageCast imageFloat + imageFloat SetInputConnection [reader GetOutputPort] + imageFloat SetOutputScalarTypeToFloat + +vtkImageFlip flipX + flipX SetInputConnection [imageFloat GetOutputPort] + flipX SetFilteredAxis 0 + +vtkImageFlip flipY + flipY SetInputConnection [imageFloat GetOutputPort] + flipY SetFilteredAxis 1 + flipY FlipAboutOriginOn + +vtkImageAppend imageAppend + imageAppend AddInput [imageFloat GetOutput] + imageAppend AddInput [flipX GetOutput] + imageAppend AddInput [flipY GetOutput] + imageAppend SetAppendAxis 0 + +vtkImageViewer viewer +viewer SetInputConnection [imageAppend GetOutputPort] +viewer SetZSlice 22 +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 + +#make interface +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestAllLogic.tcl b/Imaging/Testing/Tcl/TestAllLogic.tcl new file mode 100644 index 0000000..431aa6a --- /dev/null +++ b/Imaging/Testing/Tcl/TestAllLogic.tcl @@ -0,0 +1,52 @@ +# append multiple displaced spheres into an RGB image. +package require vtk + + +# Image pipeline + +vtkRenderWindow imgWin + +set logics "And Or Xor Nand Nor Not" +set types "Float Double UnsignedInt UnsignedLong UnsignedShort UnsignedChar" +set i 0 +foreach operator $logics { + set ScalarType [lindex $types $i] + + vtkImageEllipsoidSource sphere1${operator} + sphere1${operator} SetCenter 95 100 0 + sphere1${operator} SetRadius 70 70 70 + sphere1${operator} SetOutputScalarTypeTo${ScalarType} + + vtkImageEllipsoidSource sphere2${operator} + sphere2${operator} SetCenter 161 100 0 + sphere2${operator} SetRadius 70 70 70 + sphere2${operator} SetOutputScalarTypeTo${ScalarType} + + vtkImageLogic logic${operator} + logic${operator} SetInput1 [sphere1${operator} GetOutput] + logic${operator} SetInput2 [sphere2${operator} GetOutput] + logic${operator} SetOutputTrueValue 150 + logic${operator} SetOperationTo${operator} + vtkImageMapper mapper${operator} + mapper${operator} SetInputConnection [logic${operator} GetOutputPort] + mapper${operator} SetColorWindow 255 + mapper${operator} SetColorLevel 127.5 + vtkActor2D actor${operator} + actor${operator} SetMapper mapper${operator} + vtkRenderer imager${operator} + imager${operator} AddActor2D actor${operator} + imgWin AddRenderer imager${operator} + incr i +} + +imagerAnd SetViewport 0 .5 .33 1 +imagerOr SetViewport .33 .5 .66 1 +imagerXor SetViewport .66 .5 1 1 +imagerNand SetViewport 0 0 .33 .5 +imagerNor SetViewport .33 0 .66 .5 +imagerNot SetViewport .66 0 1 .5 + +imgWin SetSize 768 512 +imgWin Render + +wm withdraw . diff --git a/Imaging/Testing/Tcl/TestAllMaskBits.tcl b/Imaging/Testing/Tcl/TestAllMaskBits.tcl new file mode 100644 index 0000000..cf0fa01 --- /dev/null +++ b/Imaging/Testing/Tcl/TestAllMaskBits.tcl @@ -0,0 +1,65 @@ +package require vtk + +# This script calculates the luminanace of an image + +vtkRenderWindow imgWin + + +# Image pipeline + +vtkTIFFReader image1 + image1 SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + +vtkImageShrink3D shrink +shrink SetInputConnection [image1 GetOutputPort] +shrink SetShrinkFactors 2 2 1 + +set operators "ByPass And Nand Xor Or Nor" + +foreach operator $operators { + if { $operator != "ByPass" } { + vtkImageMaskBits operator${operator} + operator${operator} SetInputConnection [shrink GetOutputPort] + operator${operator} SetOperationTo${operator} + operator${operator} SetMasks 255 255 0 + } + + vtkImageMapper mapper${operator} + if { $operator != "ByPass" } { + mapper${operator} SetInputConnection [operator${operator} GetOutputPort] + } else { + mapper${operator} SetInputConnection [shrink GetOutputPort] + } + mapper${operator} SetColorWindow 255 + mapper${operator} SetColorLevel 127.5 + + vtkActor2D actor${operator} + actor${operator} SetMapper mapper${operator} + + vtkRenderer imager${operator} + imager${operator} AddActor2D actor${operator} + + imgWin AddRenderer imager${operator} +} + +set column 1 +set row 1 +set deltaX [expr 1.0/3.0] +set deltaY [expr 1.0/2.0] + +foreach operator $operators { + imager${operator} SetViewport [expr ($column - 1) * $deltaX] [expr ($row - 1) * $deltaY] [expr $column * $deltaX] [expr $row * $deltaY] + incr column + if { $column > 3 } {set column 1; incr row} +} + +imgWin SetSize 384 256 +imgWin Render + +wm withdraw . + + + + + + diff --git a/Imaging/Testing/Tcl/TestAllMathematics.tcl b/Imaging/Testing/Tcl/TestAllMathematics.tcl new file mode 100644 index 0000000..045db18 --- /dev/null +++ b/Imaging/Testing/Tcl/TestAllMathematics.tcl @@ -0,0 +1,84 @@ +package require vtk +package require vtkinteraction + +# append multiple displaced spheres into an RGB image. + + +# Image pipeline + +vtkRenderWindow imgWin + +vtkImageEllipsoidSource sphere1 +sphere1 SetCenter 40 20 0 +sphere1 SetRadius 30 30 0 +sphere1 SetInValue .75 +sphere1 SetOutValue .3 +sphere1 SetOutputScalarTypeToFloat +sphere1 SetWholeExtent 0 99 0 74 0 0 + +vtkImageEllipsoidSource sphere2 +sphere2 SetCenter 60 30 0 +sphere2 SetRadius 20 20 20 +sphere2 SetInValue .2 +sphere2 SetOutValue .5 +sphere2 SetOutputScalarTypeToFloat +sphere2 SetWholeExtent 0 99 0 74 0 0 + +set mathematics "\ +Add \ +Subtract \ +Multiply \ +Divide \ +Invert \ +Sin \ +Cos \ +Exp \ +Log \ +AbsoluteValue \ +Square \ +SquareRoot \ +Min \ +Max \ +ATAN \ +ATAN2 \ +MultiplyByK \ +ReplaceCByK \ +AddConstant" + +foreach operator $mathematics { + vtkImageMathematics mathematic${operator} + mathematic${operator} SetInput1 [sphere1 GetOutput] + mathematic${operator} SetInput2 [sphere2 GetOutput] + mathematic${operator} SetOperationTo${operator} + mathematic${operator} SetConstantK .3 + mathematic${operator} SetConstantC .75 + vtkImageMapper mapper${operator} + mapper${operator} SetInputConnection [mathematic${operator} GetOutputPort] + mapper${operator} SetColorWindow 2.0 + mapper${operator} SetColorLevel .75 + vtkActor2D actor${operator} + actor${operator} SetMapper mapper${operator} + vtkRenderer imager${operator} + imager${operator} AddActor2D actor${operator} + imgWin AddRenderer imager${operator} +} + +set column 1 +set row 1 +set deltaX [expr 1.0/6.0] +set deltaY [expr 1.0/4.0] + +foreach operator $mathematics { + imager${operator} SetViewport [expr ($column - 1) * $deltaX] [expr ($row - 1) * $deltaY] [expr $column * $deltaX] [expr $row * $deltaY] + incr column + if { $column > 6 } {set column 1; incr row} +} + +# make the last oerator finish the row +set vp [imager${operator} GetViewport] +imager${operator} SetViewport [lindex $vp 0] [lindex $vp 1] 1 1 + +imgWin SetSize 600 300 +imgWin Render + +wm withdraw . diff --git a/Imaging/Testing/Tcl/TestAllShrinks.tcl b/Imaging/Testing/Tcl/TestAllShrinks.tcl new file mode 100644 index 0000000..aea875b --- /dev/null +++ b/Imaging/Testing/Tcl/TestAllShrinks.tcl @@ -0,0 +1,73 @@ +package require vtk + +set prefix "$VTK_DATA_ROOT/Data/headsq/quarter" + +vtkRenderWindow imgWin + +# Image pipeline +vtkImageReader reader + reader SetDataExtent 0 63 0 63 1 93 + reader SetFilePrefix $prefix + reader SetDataByteOrderToLittleEndian + reader SetDataMask 0x7fff + +set factor 4 +set magFactor 8 + +set ops "Minimum Maximum Mean Median" +foreach operator $ops { + vtkImageShrink3D shrink${operator} + shrink${operator} SetMean 0 + shrink${operator} ${operator}On + eval shrink${operator} SetShrinkFactors $factor $factor $factor + shrink${operator} SetInputConnection [reader GetOutputPort]; + vtkImageMagnify mag${operator} + mag${operator} SetMagnificationFactors $magFactor $magFactor $magFactor; + mag${operator} InterpolateOff + mag${operator} SetInputConnection [shrink${operator} GetOutputPort] + vtkImageMapper mapper${operator} + mapper${operator} SetInputConnection [mag${operator} GetOutputPort] + mapper${operator} SetColorWindow 2000 + mapper${operator} SetColorLevel 1000 + mapper${operator} SetZSlice 45 + vtkActor2D actor${operator} + actor${operator} SetMapper mapper${operator} + vtkRenderer imager${operator} + imager${operator} AddActor2D actor${operator} + imgWin AddRenderer imager${operator} +} + + vtkImageShrink3D shrink + shrink SetMean 0 + eval shrink SetShrinkFactors $factor $factor $factor + shrink SetInputConnection [reader GetOutputPort]; + vtkImageMagnify mag + mag SetMagnificationFactors $magFactor $magFactor $magFactor; + mag InterpolateOff + mag SetInputConnection [shrink GetOutputPort] + vtkImageMapper mapper + mapper SetInputConnection [mag GetOutputPort] + mapper SetColorWindow 2000 + mapper SetColorLevel 1000 + mapper SetZSlice 45 + vtkActor2D actor + actor SetMapper mapper + vtkRenderer imager + imager AddActor2D actor + imgWin AddRenderer imager + +#shrinkMinimum Update +#shrinkMaximum Update +#shrinkMean Update +#shrinkMedian Update + +imagerMinimum SetViewport 0 0 .5 .33 +imagerMaximum SetViewport 0 .33 .5 .667 +imagerMean SetViewport .5 0 1 .33 +imagerMedian SetViewport .5 .33 1 .667 +imager SetViewport 0 .667 1 1 + +imgWin SetSize 256 384 +imgWin Render + +wm withdraw . diff --git a/Imaging/Testing/Tcl/TestAnisotropicDiffusion2D.tcl b/Imaging/Testing/Tcl/TestAnisotropicDiffusion2D.tcl new file mode 100644 index 0000000..cdcd1cd --- /dev/null +++ b/Imaging/Testing/Tcl/TestAnisotropicDiffusion2D.tcl @@ -0,0 +1,27 @@ +package require vtk + + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageAnisotropicDiffusion2D diffusion +diffusion SetInputConnection [reader GetOutputPort] +diffusion SetDiffusionFactor 1.0 +diffusion SetDiffusionThreshold 200.0 +diffusion SetNumberOfIterations 5 +#diffusion DebugOn + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [diffusion GetOutputPort] +viewer SetColorWindow 3000 +viewer SetColorLevel 1500 + + +viewer Render + + + diff --git a/Imaging/Testing/Tcl/TestAnisotropicDiffusion3D.tcl b/Imaging/Testing/Tcl/TestAnisotropicDiffusion3D.tcl new file mode 100644 index 0000000..ef093ed --- /dev/null +++ b/Imaging/Testing/Tcl/TestAnisotropicDiffusion3D.tcl @@ -0,0 +1,40 @@ +package require vtk + +# Diffuses to 26 neighbors if difference is below threshold. + + +# Image pipeline + +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff +reader SetDataSpacing 1 1 2 + + +vtkImageAnisotropicDiffusion3D diffusion +diffusion SetInputConnection [reader GetOutputPort] +diffusion SetDiffusionFactor 1.0 +diffusion SetDiffusionThreshold 100.0 +diffusion SetNumberOfIterations 5 +diffusion ReleaseDataFlagOff + + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [diffusion GetOutputPort] +viewer SetZSlice 22 +viewer SetColorWindow 3000 +viewer SetColorLevel 1500 + + +#make interface +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestBlendStencil.tcl b/Imaging/Testing/Tcl/TestBlendStencil.tcl new file mode 100644 index 0000000..8547371 --- /dev/null +++ b/Imaging/Testing/Tcl/TestBlendStencil.tcl @@ -0,0 +1,51 @@ +package require vtk + +# do alpha-blending of two images, but also clip with stencil + +vtkBMPReader reader1 +reader1 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +vtkPNMReader reader2 +reader2 SetFileName "$VTK_DATA_ROOT/Data/B.pgm" + +vtkLookupTable table +table SetTableRange 0 127 +table SetValueRange 0.0 1.0 +table SetSaturationRange 0.0 0.0 +table SetHueRange 0.0 0.0 +table SetAlphaRange 0.9 0.0 +table Build + +vtkImageTranslateExtent translate +translate SetInputConnection [reader2 GetOutputPort] +translate SetTranslation 60 60 0 + +vtkSphere sphere +sphere SetCenter 121 131 0 +sphere SetRadius 70 + +vtkImplicitFunctionToImageStencil functionToStencil +functionToStencil SetInput sphere +[functionToStencil GetOutput] SetUpdateExtent 0 255 0 255 0 0 +[functionToStencil GetOutput] Update + +vtkImageBlend blend +blend SetInput 0 [reader1 GetOutput] +blend SetInput 1 [translate GetOutput] +blend SetOpacity 1 0.8 +blend SetStencil [functionToStencil GetOutput] + +vtkImageViewer viewer +viewer SetInputConnection [blend GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 0 +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestButterworthHighPass.tcl b/Imaging/Testing/Tcl/TestButterworthHighPass.tcl new file mode 100644 index 0000000..4eee459 --- /dev/null +++ b/Imaging/Testing/Tcl/TestButterworthHighPass.tcl @@ -0,0 +1,33 @@ +package require vtk + +# This script shows the result of an ideal highpass filter in frequency space. + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageFFT fft +fft SetDimensionality 2 +fft SetInputConnection [reader GetOutputPort] +#fft DebugOn + +vtkImageButterworthHighPass highPass +highPass SetInputConnection [fft GetOutputPort] +highPass SetOrder 2 +highPass SetXCutOff 0.2 +highPass SetYCutOff 0.1 +highPass ReleaseDataFlagOff +#highPass DebugOn + +vtkImageViewer viewer +viewer SetInputConnection [highPass GetOutputPort] +viewer SetColorWindow 10000 +viewer SetColorLevel 5000 +#viewer DebugOn + + +viewer Render + + diff --git a/Imaging/Testing/Tcl/TestButterworthLowPass.tcl b/Imaging/Testing/Tcl/TestButterworthLowPass.tcl new file mode 100644 index 0000000..5192260 --- /dev/null +++ b/Imaging/Testing/Tcl/TestButterworthLowPass.tcl @@ -0,0 +1,33 @@ +package require vtk + +# This script shows the result of an ideal lowpass filter in frequency space. + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageFFT fft +fft SetDimensionality 2 +fft SetInputConnection [reader GetOutputPort] +#fft DebugOn + +vtkImageButterworthLowPass lowPass +lowPass SetInputConnection [fft GetOutputPort] +lowPass SetOrder 2 +lowPass SetXCutOff 0.2 +lowPass SetYCutOff 0.1 +lowPass ReleaseDataFlagOff +#lowPass DebugOn + +vtkImageViewer viewer +viewer SetInputConnection [lowPass GetOutputPort] +viewer SetColorWindow 10000 +viewer SetColorLevel 5000 +#viewer DebugOn + + +viewer Render + + diff --git a/Imaging/Testing/Tcl/TestCache.tcl b/Imaging/Testing/Tcl/TestCache.tcl new file mode 100644 index 0000000..d82c369 --- /dev/null +++ b/Imaging/Testing/Tcl/TestCache.tcl @@ -0,0 +1,38 @@ +package require vtk + +# Image pipeline + +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageCacheFilter cache +cache SetInputConnection [reader GetOutputPort] +cache SetCacheSize 20 + +vtkImageViewer viewer +viewer SetInputConnection [cache GetOutputPort] +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 +viewer SetPosition 50 50 + +for {set i 0} {$i < 5} {incr i} { + for {set j 10} {$j < 30} {incr j} { + viewer SetZSlice $j + viewer Render + } +} + + +#make interface +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestChangeInformation.tcl b/Imaging/Testing/Tcl/TestChangeInformation.tcl new file mode 100644 index 0000000..18ebc82 --- /dev/null +++ b/Imaging/Testing/Tcl/TestChangeInformation.tcl @@ -0,0 +1,33 @@ +package require vtk + +# In this example, an image is centered at (0,0,0) before a +# rotation is applied to ensure that the rotation occurs about +# the center of the image. + +vtkPNGReader reader +reader SetDataSpacing 0.8 0.8 1.5 +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +# first center the image at (0,0,0) +vtkImageChangeInformation information +information SetInputConnection [reader GetOutputPort] +information CenterImageOn + +vtkImageReslice reslice +reslice SetInputConnection [information GetOutputPort] +reslice SetResliceAxesDirectionCosines 0.866025 -0.5 0 0.5 0.866025 0 0 0 1 +reslice SetInterpolationModeToCubic + +# reset the image back to the way it was (you don't have +# to do this, it is just put in as an example) +vtkImageChangeInformation information2 +information2 SetInputConnection [reslice GetOutputPort] +information2 SetInformationInput [reader GetOutput] + +vtkImageViewer viewer +viewer SetInputConnection [information2 GetOutputPort] +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 +viewer Render + + diff --git a/Imaging/Testing/Tcl/TestCheckerboard.tcl b/Imaging/Testing/Tcl/TestCheckerboard.tcl new file mode 100644 index 0000000..aa57a18 --- /dev/null +++ b/Imaging/Testing/Tcl/TestCheckerboard.tcl @@ -0,0 +1,40 @@ +package require vtk + +# Image pipeline + +vtkImageCanvasSource2D image1 + image1 SetNumberOfScalarComponents 3 + image1 SetScalarTypeToUnsignedChar + image1 SetExtent 0 511 0 511 0 0 + image1 SetDrawColor 255 255 0 + image1 FillBox 0 511 0 511 + +vtkImageWrapPad pad1 + pad1 SetInputConnection [image1 GetOutputPort] + pad1 SetOutputWholeExtent 0 511 0 511 0 99 + +vtkImageCanvasSource2D image2 + image2 SetNumberOfScalarComponents 3 + image2 SetScalarTypeToUnsignedChar + image2 SetExtent 0 511 0 511 0 0 + image2 SetDrawColor 0 255 255 + image2 FillBox 0 511 0 511 + +vtkImageWrapPad pad2 + pad2 SetInputConnection [image2 GetOutputPort] + pad2 SetOutputWholeExtent 0 511 0 511 0 99 + +vtkImageCheckerboard checkers + checkers SetInput 0 [pad1 GetOutput] + checkers SetInput 1 [pad2 GetOutput] + checkers SetNumberOfDivisions 11 6 2 + +vtkImageViewer viewer + viewer SetInputConnection [checkers GetOutputPort] + viewer SetZSlice 49 + viewer SetColorWindow 255 + viewer SetColorLevel 127.5 + +viewer Render + +wm withdraw . diff --git a/Imaging/Testing/Tcl/TestCityBlockDistance.tcl b/Imaging/Testing/Tcl/TestCityBlockDistance.tcl new file mode 100644 index 0000000..df30712 --- /dev/null +++ b/Imaging/Testing/Tcl/TestCityBlockDistance.tcl @@ -0,0 +1,40 @@ +package require vtk + +# A script to test the threshold filter. +# Values above 2000 are set to 255. +# Values below 2000 are set to 0. + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageCast cast +cast SetOutputScalarTypeToShort +cast SetInputConnection [reader GetOutputPort] + +vtkImageThreshold thresh +thresh SetInputConnection [cast GetOutputPort] +thresh ThresholdByUpper 2000.0 +thresh SetInValue 0 +thresh SetOutValue 200 +thresh ReleaseDataFlagOff + +vtkImageCityBlockDistance dist +dist SetDimensionality 2 +dist SetInputConnection [thresh GetOutputPort] + +vtkImageViewer viewer +viewer SetInputConnection [dist GetOutputPort] +viewer SetColorWindow 117 +viewer SetColorLevel 43 + +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestConvolve.tcl b/Imaging/Testing/Tcl/TestConvolve.tcl new file mode 100644 index 0000000..bddb381 --- /dev/null +++ b/Imaging/Testing/Tcl/TestConvolve.tcl @@ -0,0 +1,27 @@ +# Show the constant kernel. Smooth an impulse function. + +package require vtk + +vtkImageCanvasSource2D s1 +s1 SetScalarTypeToFloat +s1 SetExtent 0 255 0 255 0 0 +s1 SetDrawColor 0 +s1 FillBox 0 255 0 255 +s1 SetDrawColor 1.0 +s1 FillBox 75 175 75 175 + +vtkImageConvolve convolve +convolve SetInputConnection [s1 GetOutputPort] +convolve SetKernel5x5 1 1 1 1 1 5 4 3 2 1 5 4 3 2 1 5 4 3 2 1 1 1 1 1 1 + +vtkImageViewer viewer +viewer SetInputConnection [convolve GetOutputPort] +viewer SetColorWindow 18 +viewer SetColorLevel 9 + +viewer Render + + + + + diff --git a/Imaging/Testing/Tcl/TestCorrelation.tcl b/Imaging/Testing/Tcl/TestCorrelation.tcl new file mode 100644 index 0000000..ce9ca1c --- /dev/null +++ b/Imaging/Testing/Tcl/TestCorrelation.tcl @@ -0,0 +1,40 @@ +# Show the constant kernel. Smooth an impulse function. + +package require vtk + + + +vtkImageCanvasSource2D s1 +s1 SetScalarTypeToFloat +s1 SetExtent 0 255 0 255 0 0 +s1 SetDrawColor 0 +s1 FillBox 0 255 0 255 +s1 SetDrawColor 2.0 +s1 FillTriangle 10 100 190 150 40 250 + +vtkImageCanvasSource2D s2 +s2 SetScalarTypeToFloat +s2 SetExtent 0 31 0 31 0 0 +s2 SetDrawColor 0.0 +s2 FillBox 0 31 0 31 +s2 SetDrawColor 2.0 +s2 FillTriangle 10 1 25 10 1 5 + + +vtkImageCorrelation convolve +convolve SetDimensionality 2 +convolve SetInput1 [s1 GetOutput] +convolve SetInput2 [s2 GetOutput] + +vtkImageViewer viewer +viewer SetInputConnection [convolve GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + + +viewer Render + + + + + diff --git a/Imaging/Testing/Tcl/TestDivergence.tcl b/Imaging/Testing/Tcl/TestDivergence.tcl new file mode 100644 index 0000000..89168ae --- /dev/null +++ b/Imaging/Testing/Tcl/TestDivergence.tcl @@ -0,0 +1,30 @@ +# Divergence measures rate of change of gradient. +package require vtk + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageGradient gradient +gradient SetDimensionality 2 +gradient SetInputConnection [reader GetOutputPort] + +vtkImageDivergence derivative +derivative SetInputConnection [gradient GetOutputPort] + +vtkImageViewer viewer +viewer SetInputConnection [derivative GetOutputPort] +viewer SetColorWindow 1000 +viewer SetColorLevel 0 + + +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestDotProduct.tcl b/Imaging/Testing/Tcl/TestDotProduct.tcl new file mode 100644 index 0000000..9d9f14c --- /dev/null +++ b/Imaging/Testing/Tcl/TestDotProduct.tcl @@ -0,0 +1,50 @@ +package require vtk + +# This script shows the magnitude of an image in frequency domain. + + + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + + + +vtkImageCast cast +cast SetInputConnection [reader GetOutputPort] +cast SetOutputScalarTypeToFloat + +vtkImageShiftScale scale2 +scale2 SetInputConnection [cast GetOutputPort] +scale2 SetScale 0.05 + +vtkImageGradient gradient +gradient SetInputConnection [scale2 GetOutputPort] +gradient SetDimensionality 3 + +vtkBMPReader pnm +pnm SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +vtkImageCast cast2 +cast2 SetInputConnection [pnm GetOutputPort] +cast2 SetOutputScalarTypeToDouble + +vtkImageDotProduct magnitude +magnitude SetInput1 [cast2 GetOutput] +magnitude SetInput2 [gradient GetOutput] + +#vtkImageViewer viewer +vtkImageViewer viewer +viewer SetInputConnection [magnitude GetOutputPort] +viewer SetColorWindow 1000 +viewer SetColorLevel 300 +#viewer DebugOn + +viewer Render + + + + + diff --git a/Imaging/Testing/Tcl/TestEuclideanDistance.tcl b/Imaging/Testing/Tcl/TestEuclideanDistance.tcl new file mode 100644 index 0000000..06bdea7 --- /dev/null +++ b/Imaging/Testing/Tcl/TestEuclideanDistance.tcl @@ -0,0 +1,32 @@ +package require vtk + +# This script shows how to use vtkImageEuclideanDistance + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageCast cast +cast SetOutputScalarTypeToShort +cast SetInputConnection [reader GetOutputPort] + +vtkImageThreshold thresh +thresh SetInputConnection [cast GetOutputPort] +thresh ThresholdByUpper 2000.0 +thresh SetInValue 0 +thresh SetOutValue 200 +thresh ReleaseDataFlagOff + +vtkImageEuclideanDistance dist +dist SetInputConnection [thresh GetOutputPort] +dist SetAlgorithmToSaito + +vtkImageViewer viewer +viewer SetInputConnection [dist GetOutputPort] +viewer SetColorWindow 117 +viewer SetColorLevel 43 + +viewer Render + +source [file join [file dirname [info script]] WindowLevelInterface.tcl] diff --git a/Imaging/Testing/Tcl/TestEuclideanDistanceCached.tcl b/Imaging/Testing/Tcl/TestEuclideanDistanceCached.tcl new file mode 100644 index 0000000..57764cd --- /dev/null +++ b/Imaging/Testing/Tcl/TestEuclideanDistanceCached.tcl @@ -0,0 +1,32 @@ +package require vtk + +# This script shows how to use vtkImageEuclideanDistance + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageCast cast +cast SetOutputScalarTypeToShort +cast SetInputConnection [reader GetOutputPort] + +vtkImageThreshold thresh +thresh SetInputConnection [cast GetOutputPort] +thresh ThresholdByUpper 2000.0 +thresh SetInValue 0 +thresh SetOutValue 200 +thresh ReleaseDataFlagOff + +vtkImageEuclideanDistance dist +dist SetInputConnection [thresh GetOutputPort] +dist SetAlgorithmToSaitoCached + +vtkImageViewer viewer +viewer SetInputConnection [dist GetOutputPort] +viewer SetColorWindow 117 +viewer SetColorLevel 43 + +viewer Render + +source [file join [file dirname [info script]] WindowLevelInterface.tcl] diff --git a/Imaging/Testing/Tcl/TestEuclideanToPolar.tcl b/Imaging/Testing/Tcl/TestEuclideanToPolar.tcl new file mode 100644 index 0000000..3a18d10 --- /dev/null +++ b/Imaging/Testing/Tcl/TestEuclideanToPolar.tcl @@ -0,0 +1,40 @@ +# This Script test the euclidean to polar by coverting 2D vectors +# from a gradient into polar, which is converted into HSV, and then to RGB. +package require vtk + + + + +# Image pipeline + +vtkImageGaussianSource gauss +gauss SetWholeExtent 0 255 0 255 0 44 +gauss SetCenter 127 127 22 +gauss SetStandardDeviation 50.0 +gauss SetMaximum 10000.0 + +vtkImageGradient gradient +gradient SetInputConnection [gauss GetOutputPort] +gradient SetDimensionality 2 + +vtkImageEuclideanToPolar polar +polar SetInputConnection [gradient GetOutputPort] +polar SetThetaMaximum 255 + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [polar GetOutputPort] +viewer SetZSlice 22 +viewer SetColorWindow 255 +viewer SetColorLevel 127.5 + + +#make interface +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestFFTCorrelation.tcl b/Imaging/Testing/Tcl/TestFFTCorrelation.tcl new file mode 100644 index 0000000..5a5ec66 --- /dev/null +++ b/Imaging/Testing/Tcl/TestFFTCorrelation.tcl @@ -0,0 +1,66 @@ +package require vtk +package require vtkinteraction + +# Performs a correlation in frequency domain. + +vtkImageCanvasSource2D s1 +s1 SetScalarTypeToFloat +s1 SetExtent 0 255 0 255 0 0 +s1 SetDrawColor 0 +s1 FillBox 0 255 0 255 +s1 SetDrawColor 2.0 +s1 FillTriangle 10 100 190 150 40 250 + +vtkImageCanvasSource2D s2 +s2 SetScalarTypeToFloat +s2 SetExtent 0 31 0 31 0 0 +s2 SetDrawColor 0.0 +s2 FillBox 0 31 0 31 +s2 SetDrawColor 2.0 +s2 FillTriangle 10 1 25 10 1 5 + + +vtkImageFFT fft1 +fft1 SetDimensionality 2 +fft1 SetInputConnection [s1 GetOutputPort] +fft1 ReleaseDataFlagOff + + +# Pad kernel out to same size as image. + +vtkImageConstantPad pad2 +pad2 SetInputConnection [s2 GetOutputPort] +pad2 SetOutputWholeExtent 0 255 0 255 0 0 + +vtkImageFFT fft2 +fft2 SetDimensionality 2 +fft2 SetInputConnection [pad2 GetOutputPort] +fft2 ReleaseDataFlagOff + +# conjugate is necessary for correlation (not convolution) +vtkImageMathematics conj +conj SetOperationToConjugate +conj SetInput1 [fft2 GetOutput] + +# Corrleation is multiplication in frequencey space. +vtkImageMathematics mult +mult SetOperationToComplexMultiply +mult SetInput1 [fft1 GetOutput] +mult SetInput2 [conj GetOutput] + +vtkImageRFFT rfft +rfft SetDimensionality 2 +rfft SetInputConnection [mult GetOutputPort] + +vtkImageExtractComponents real +real SetInputConnection [rfft GetOutputPort] +real SetComponents 0 + +vtkImageViewer viewer +viewer SetInputConnection [real GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + + +# make interface +source [file join [file dirname [info script]] WindowLevelInterface.tcl] diff --git a/Imaging/Testing/Tcl/TestGradientMagnitude.tcl b/Imaging/Testing/Tcl/TestGradientMagnitude.tcl new file mode 100644 index 0000000..bd8e315 --- /dev/null +++ b/Imaging/Testing/Tcl/TestGradientMagnitude.tcl @@ -0,0 +1,20 @@ +package require vtk + + + +# Image pipeline + +vtkGESignaReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/E07733S002I009.MR" + +vtkImageGradientMagnitude gradient +gradient SetDimensionality 2 +gradient SetInputConnection [reader GetOutputPort] + +vtkImageViewer viewer +viewer SetInputConnection [gradient GetOutputPort] +viewer SetColorWindow 250 +viewer SetColorLevel 125 + + +viewer Render diff --git a/Imaging/Testing/Tcl/TestGradientMagnitude2.tcl b/Imaging/Testing/Tcl/TestGradientMagnitude2.tcl new file mode 100644 index 0000000..f86c5c3 --- /dev/null +++ b/Imaging/Testing/Tcl/TestGradientMagnitude2.tcl @@ -0,0 +1,31 @@ +package require vtk + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageClip clip +clip SetInputConnection [reader GetOutputPort] +clip SetOutputWholeExtent 80 230 80 230 0 0 +clip ClipDataOff + +vtkImageGradientMagnitude gradient +gradient SetDimensionality 2 +gradient SetInputConnection [clip GetOutputPort] +gradient HandleBoundariesOff + + + +vtkImageChangeInformation slide +slide SetInputConnection [gradient GetOutputPort] +slide SetExtentTranslation -100 -100 0 + +vtkImageViewer viewer +viewer SetInputConnection [slide GetOutputPort] +viewer SetColorWindow -1000 +viewer SetColorLevel 500 + +viewer Render + +source [file join [file dirname [info script]] WindowLevelInterface.tcl] diff --git a/Imaging/Testing/Tcl/TestHSIToRGB.tcl b/Imaging/Testing/Tcl/TestHSIToRGB.tcl new file mode 100644 index 0000000..0c02c73 --- /dev/null +++ b/Imaging/Testing/Tcl/TestHSIToRGB.tcl @@ -0,0 +1,80 @@ +# Use the painter to draw using colors. +# This is not a pipeline object. It will support pipeline objects. +# Please do not use this object directly. +package require vtk + + + +vtkImageCanvasSource2D imageCanvas +imageCanvas SetNumberOfScalarComponents 3 +imageCanvas SetScalarTypeToUnsignedChar +imageCanvas SetExtent 0 320 0 320 0 0 +imageCanvas SetDrawColor 0 0 0 +imageCanvas FillBox 0 511 0 511 + +# r, g, b +imageCanvas SetDrawColor 255 0 0 +imageCanvas FillBox 0 50 0 100 +imageCanvas SetDrawColor 128 128 0 +imageCanvas FillBox 50 100 0 100 +imageCanvas SetDrawColor 0 255 0 +imageCanvas FillBox 100 150 0 100 +imageCanvas SetDrawColor 0 128 128 +imageCanvas FillBox 150 200 0 100 +imageCanvas SetDrawColor 0 0 255 +imageCanvas FillBox 200 250 0 100 +imageCanvas SetDrawColor 128 0 128 +imageCanvas FillBox 250 300 0 100 + +# intensity scale +imageCanvas SetDrawColor 5 5 5 +imageCanvas FillBox 0 50 110 210 +imageCanvas SetDrawColor 55 55 55 +imageCanvas FillBox 50 100 110 210 +imageCanvas SetDrawColor 105 105 105 +imageCanvas FillBox 100 150 110 210 +imageCanvas SetDrawColor 155 155 155 +imageCanvas FillBox 150 200 110 210 +imageCanvas SetDrawColor 205 205 205 +imageCanvas FillBox 200 250 110 210 +imageCanvas SetDrawColor 255 255 255 +imageCanvas FillBox 250 300 110 210 + +# saturation scale +imageCanvas SetDrawColor 245 0 0 +imageCanvas FillBox 0 50 220 320 +imageCanvas SetDrawColor 213 16 16 +imageCanvas FillBox 50 100 220 320 +imageCanvas SetDrawColor 181 32 32 +imageCanvas FillBox 100 150 220 320 +imageCanvas SetDrawColor 149 48 48 +imageCanvas FillBox 150 200 220 320 +imageCanvas SetDrawColor 117 64 64 +imageCanvas FillBox 200 250 220 320 +imageCanvas SetDrawColor 85 80 80 +imageCanvas FillBox 250 300 220 320 + + +vtkImageRGBToHSI convert +convert SetInputConnection [imageCanvas GetOutputPort] + +vtkImageHSIToRGB convertBack +convertBack SetInputConnection [convert GetOutputPort] + +vtkImageCast cast +cast SetInputConnection [convertBack GetOutputPort] +cast SetOutputScalarTypeToFloat +cast ReleaseDataFlagOff + +vtkImageViewer viewer +viewer SetInputConnection [convertBack GetOutputPort] +#viewer SetInputConnection [imageCanvas GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + +viewer Render + + + + + diff --git a/Imaging/Testing/Tcl/TestHSVToRGB.tcl b/Imaging/Testing/Tcl/TestHSVToRGB.tcl new file mode 100644 index 0000000..d29c465 --- /dev/null +++ b/Imaging/Testing/Tcl/TestHSVToRGB.tcl @@ -0,0 +1,80 @@ +# Use the painter to draw using colors. +# This is not a pipeline object. It will support pipeline objects. +# Please do not use this object directly. +package require vtk + + + +vtkImageCanvasSource2D imageCanvas +imageCanvas SetNumberOfScalarComponents 3 +imageCanvas SetScalarTypeToUnsignedChar +imageCanvas SetExtent 0 320 0 320 0 0 +imageCanvas SetDrawColor 0 0 0 +imageCanvas FillBox 0 511 0 511 + +# r, g, b +imageCanvas SetDrawColor 255 0 0 +imageCanvas FillBox 0 50 0 100 +imageCanvas SetDrawColor 128 128 0 +imageCanvas FillBox 50 100 0 100 +imageCanvas SetDrawColor 0 255 0 +imageCanvas FillBox 100 150 0 100 +imageCanvas SetDrawColor 0 128 128 +imageCanvas FillBox 150 200 0 100 +imageCanvas SetDrawColor 0 0 255 +imageCanvas FillBox 200 250 0 100 +imageCanvas SetDrawColor 128 0 128 +imageCanvas FillBox 250 300 0 100 + +# intensity scale +imageCanvas SetDrawColor 5 5 5 +imageCanvas FillBox 0 50 110 210 +imageCanvas SetDrawColor 55 55 55 +imageCanvas FillBox 50 100 110 210 +imageCanvas SetDrawColor 105 105 105 +imageCanvas FillBox 100 150 110 210 +imageCanvas SetDrawColor 155 155 155 +imageCanvas FillBox 150 200 110 210 +imageCanvas SetDrawColor 205 205 205 +imageCanvas FillBox 200 250 110 210 +imageCanvas SetDrawColor 255 255 255 +imageCanvas FillBox 250 300 110 210 + +# saturation scale +imageCanvas SetDrawColor 245 0 0 +imageCanvas FillBox 0 50 220 320 +imageCanvas SetDrawColor 213 16 16 +imageCanvas FillBox 50 100 220 320 +imageCanvas SetDrawColor 181 32 32 +imageCanvas FillBox 100 150 220 320 +imageCanvas SetDrawColor 149 48 48 +imageCanvas FillBox 150 200 220 320 +imageCanvas SetDrawColor 117 64 64 +imageCanvas FillBox 200 250 220 320 +imageCanvas SetDrawColor 85 80 80 +imageCanvas FillBox 250 300 220 320 + + +vtkImageRGBToHSV convert +convert SetInputConnection [imageCanvas GetOutputPort] + +vtkImageHSVToRGB convertBack +convertBack SetInputConnection [convert GetOutputPort] + +vtkImageCast cast +cast SetInputConnection [convertBack GetOutputPort] +cast SetOutputScalarTypeToFloat +cast ReleaseDataFlagOff + +vtkImageViewer viewer +viewer SetInputConnection [convertBack GetOutputPort] +#viewer SetInputConnection [imageCanvas GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + +viewer Render + + + + + diff --git a/Imaging/Testing/Tcl/TestHybridMedian2D.tcl b/Imaging/Testing/Tcl/TestHybridMedian2D.tcl new file mode 100644 index 0000000..e64007a --- /dev/null +++ b/Imaging/Testing/Tcl/TestHybridMedian2D.tcl @@ -0,0 +1,95 @@ +# Show the constant kernel. Smooth an impulse function. + +package require vtk + + + +vtkImageCanvasSource2D imageCanvas +imageCanvas SetScalarTypeToDouble +imageCanvas SetExtent 1 256 1 256 0 0 +# back ground zero +imageCanvas SetDrawColor 0 +imageCanvas FillBox 1 256 1 256 + +imageCanvas SetDrawColor 255 +imageCanvas FillBox 30 225 30 225 + +imageCanvas SetDrawColor 0 +imageCanvas FillBox 60 195 60 195 + +imageCanvas SetDrawColor 255 +imageCanvas FillTube 100 100 154 154 40.0 + +imageCanvas SetDrawColor 0 + +imageCanvas DrawSegment 45 45 45 210 +imageCanvas DrawSegment 45 210 210 210 +imageCanvas DrawSegment 210 210 210 45 +imageCanvas DrawSegment 210 45 45 45 + +imageCanvas DrawSegment 100 150 150 100 +imageCanvas DrawSegment 110 160 160 110 +imageCanvas DrawSegment 90 140 140 90 +imageCanvas DrawSegment 120 170 170 120 +imageCanvas DrawSegment 80 130 130 80 + + + + +set shotNoiseAmplitude 255.0 +set shotNoiseFraction 0.1 +#set shotNoiseExtent "1 256 1 256 0 0" + +vtkImageNoiseSource shotNoiseSource +shotNoiseSource SetWholeExtent 1 256 1 256 0 0 ;#$shotNoiseExtent +shotNoiseSource SetMinimum 0.0 +shotNoiseSource SetMaximum 1.0 +shotNoiseSource ReleaseDataFlagOff + +vtkImageThreshold shotNoiseThresh1 +shotNoiseThresh1 SetInputConnection [shotNoiseSource GetOutputPort] +shotNoiseThresh1 ThresholdByLower [expr 1.0 - $shotNoiseFraction] +shotNoiseThresh1 SetInValue 0 +shotNoiseThresh1 SetOutValue $shotNoiseAmplitude + +vtkImageThreshold shotNoiseThresh2 +shotNoiseThresh2 SetInputConnection [shotNoiseSource GetOutputPort] +shotNoiseThresh2 ThresholdByLower $shotNoiseFraction +shotNoiseThresh2 SetInValue [expr - $shotNoiseAmplitude] +shotNoiseThresh2 SetOutValue 0.0 + +vtkImageMathematics shotNoise +shotNoise SetInput1 [shotNoiseThresh1 GetOutput] +shotNoise SetInput2 [shotNoiseThresh2 GetOutput] +shotNoise SetOperationToAdd + + + + +vtkImageMathematics add +add SetInput1 [shotNoise GetOutput] +add SetInput2 [imageCanvas GetOutput] +add SetOperationToAdd + + + + + +vtkImageMedian3D median +median SetInputConnection [add GetOutputPort] +median SetKernelSize 3 3 1 + +vtkImageHybridMedian2D hybrid1 +hybrid1 SetInputConnection [add GetOutputPort] + +vtkImageHybridMedian2D hybrid2 +hybrid2 SetInputConnection [hybrid1 GetOutputPort] + +vtkImageViewer viewer +viewer SetInputConnection [hybrid1 GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127.5 + +viewer Render + + diff --git a/Imaging/Testing/Tcl/TestIdealLowPass.tcl b/Imaging/Testing/Tcl/TestIdealLowPass.tcl new file mode 100644 index 0000000..b51ac12 --- /dev/null +++ b/Imaging/Testing/Tcl/TestIdealLowPass.tcl @@ -0,0 +1,36 @@ +package require vtk + +# This script shows the result of an ideal lowpass filter in frequency space. + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageFFT fft +fft SetInputConnection [reader GetOutputPort] +#fft DebugOn + +vtkImageIdealLowPass lowPass +lowPass SetInputConnection [fft GetOutputPort] +lowPass SetXCutOff 0.2 +lowPass SetYCutOff 0.1 +lowPass ReleaseDataFlagOff +#lowPass DebugOn + +vtkImageViewer viewer +viewer SetInputConnection [lowPass GetOutputPort] +viewer SetColorWindow 10000 +viewer SetColorLevel 5000 +#viewer DebugOn + + +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestImageCanvas.tcl b/Imaging/Testing/Tcl/TestImageCanvas.tcl new file mode 100644 index 0000000..3a75414 --- /dev/null +++ b/Imaging/Testing/Tcl/TestImageCanvas.tcl @@ -0,0 +1,46 @@ +package require vtk + +# A script to test the threshold filter. +# Values above 2000 are set to 255. +# Values below 2000 are set to 0. + +# Image pipeline + +vtkImageCanvasSource2D imageCanvas +imageCanvas SetScalarTypeToUnsignedChar +imageCanvas SetNumberOfScalarComponents 3 +imageCanvas SetExtent 0 300 0 300 0 0 +# background black +imageCanvas SetDrawColor 0 +imageCanvas FillBox 0 511 0 511 + +vtkJPEGReader jreader +jreader SetFileName "$VTK_DATA_ROOT/Data/beach.jpg" +jreader Update + +imageCanvas DrawImage 100 100 [ jreader GetOutput ] 0 0 300 300 +imageCanvas DrawImage 0 100 [ jreader GetOutput ] +imageCanvas DrawImage 100 0 [ jreader GetOutput ] 0 0 300 300 +imageCanvas DrawImage 0 0 [ jreader GetOutput ] 50 50 100 100 +imageCanvas DrawImage 10 10 [ jreader GetOutput ] 50 50 100 100 +imageCanvas DrawImage 20 20 [ jreader GetOutput ] 50 50 100 100 +imageCanvas DrawImage 30 30 [ jreader GetOutput ] 50 50 100 100 +imageCanvas DrawImage 40 40 [ jreader GetOutput ] 50 50 100 100 +imageCanvas DrawImage 50 50 [ jreader GetOutput ] 50 50 100 100 +imageCanvas DrawImage 60 60 [ jreader GetOutput ] 50 50 100 100 +imageCanvas DrawImage 70 70 [ jreader GetOutput ] 50 50 100 100 + +vtkImageViewer viewer +viewer SetInputConnection [imageCanvas GetOutputPort] +viewer SetColorWindow 255 +viewer SetColorLevel 128 + +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestInPlaceFilter.tcl b/Imaging/Testing/Tcl/TestInPlaceFilter.tcl new file mode 100644 index 0000000..dac328b --- /dev/null +++ b/Imaging/Testing/Tcl/TestInPlaceFilter.tcl @@ -0,0 +1,61 @@ +package require vtk + +# Derived from Cursor3D. This script increases the coverage of the +# vtkImageInplaceFilter super class. + + + +# global values +set CURSOR_X 20 +set CURSOR_Y 20 +set CURSOR_Z 20 + +set IMAGE_MAG_X 2 +set IMAGE_MAG_Y 2 +set IMAGE_MAG_Z 1 + + + +# pipeline stuff +vtkSLCReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/nut.slc" + +# make the image a little biger +vtkImageMagnify magnify1 + magnify1 SetInputConnection [reader GetOutputPort] +magnify1 SetMagnificationFactors $IMAGE_MAG_X $IMAGE_MAG_Y $IMAGE_MAG_Z + magnify1 ReleaseDataFlagOn + +vtkImageMagnify magnify2 + magnify2 SetInputConnection [reader GetOutputPort] + magnify2 SetMagnificationFactors $IMAGE_MAG_X $IMAGE_MAG_Y $IMAGE_MAG_Z + magnify2 ReleaseDataFlagOn + +# a filter that does in place processing (magnify ReleaseDataFlagOn) +vtkImageCursor3D cursor +cursor SetInputConnection [magnify1 GetOutputPort] +cursor SetCursorPosition [expr $CURSOR_X * $IMAGE_MAG_X] \ + [expr $CURSOR_Y * $IMAGE_MAG_Y] [expr $CURSOR_Z * $IMAGE_MAG_Z] +cursor SetCursorValue 255 +cursor SetCursorRadius [expr 50 * $IMAGE_MAG_X] +# stream to increase coverage of in place filter. + +# put thge two together in one image +vtkImageAppend imageAppend +imageAppend SetAppendAxis 0 +imageAppend AddInput [magnify2 GetOutput] +imageAppend AddInput [cursor GetOutput] + +vtkImageViewer viewer +viewer SetInputConnection [imageAppend GetOutputPort] +viewer SetZSlice [expr $CURSOR_Z * $IMAGE_MAG_Z] +viewer SetColorWindow 200 +viewer SetColorLevel 80 +#viewer DebugOn +viewer Render + +viewer SetPosition 50 50 + +#make interface +viewer Render + diff --git a/Imaging/Testing/Tcl/TestIslandRemoval2D.tcl b/Imaging/Testing/Tcl/TestIslandRemoval2D.tcl new file mode 100644 index 0000000..517f3a6 --- /dev/null +++ b/Imaging/Testing/Tcl/TestIslandRemoval2D.tcl @@ -0,0 +1,39 @@ +package require vtk + +# A script to test the island removal filter. +# first the image is thresholded, then small islands are removed. + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageThreshold thresh +thresh SetInputConnection [reader GetOutputPort] +thresh ThresholdByUpper 2000.0 +thresh SetInValue 255 +thresh SetOutValue 0 +thresh ReleaseDataFlagOff + +vtkImageIslandRemoval2D island +island SetInputConnection [thresh GetOutputPort] +island SetIslandValue 255 +island SetReplaceValue 128 +island SetAreaThreshold 100 +island SquareNeighborhoodOn + +vtkImageViewer viewer +viewer SetInputConnection [island GetOutputPort] +viewer SetColorWindow 255 +viewer SetColorLevel 127.5 +#viewer DebugOn + +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestMapToRGBABlockStreaming.tcl b/Imaging/Testing/Tcl/TestMapToRGBABlockStreaming.tcl new file mode 100644 index 0000000..4deaaa6 --- /dev/null +++ b/Imaging/Testing/Tcl/TestMapToRGBABlockStreaming.tcl @@ -0,0 +1,64 @@ +package require vtk + + + +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +set rangeStart 0.0 +set rangeEnd 0.2 + +vtkLookupTable LUT +LUT SetTableRange 0 1800 +LUT SetSaturationRange 1 1 +LUT SetHueRange $rangeStart $rangeEnd +LUT SetValueRange 1 1 +LUT SetAlphaRange 1 1 +LUT Build + +# The prototype of this function has +# arguments so that the code can be +# translated to python for testing. +proc changeLUT { { a 0 } { b 0 } } { + global rangeStart rangeEnd + + set rangeStart [expr $rangeStart + 0.1] + set rangeEnd [expr $rangeEnd + 0.1] + if { $rangeEnd > 1.0 } { + set rangeStart 0.0 + set rangeEnd 0.2 + } + + LUT SetHueRange $rangeStart $rangeEnd + LUT Build +} + +vtkImageMapToColors mapToRGBA +mapToRGBA SetInputConnection [reader GetOutputPort] +mapToRGBA SetOutputFormatToRGBA +mapToRGBA SetLookupTable LUT +mapToRGBA AddObserver "EndEvent" changeLUT + +vtkImageDataStreamer imageStreamer +imageStreamer SetInputConnection [mapToRGBA GetOutputPort] +imageStreamer SetNumberOfStreamDivisions 8 +# make sure we get the correct translator. +imageStreamer UpdateInformation +[imageStreamer GetExtentTranslator] SetSplitModeToBlock + +# set the window/level to 255.0/127.5 to view full range +vtkImageViewer viewer +viewer SetInputConnection [imageStreamer GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 50 + +viewer Render + +#make interface +viewer Render + diff --git a/Imaging/Testing/Tcl/TestMapToWindowLevelColors.tcl b/Imaging/Testing/Tcl/TestMapToWindowLevelColors.tcl new file mode 100644 index 0000000..59aa999 --- /dev/null +++ b/Imaging/Testing/Tcl/TestMapToWindowLevelColors.tcl @@ -0,0 +1,39 @@ +package require vtk + + + +set RANGE 150 +set MAX_ITERATIONS_1 $RANGE +set MAX_ITERATIONS_2 $RANGE +set XRAD 200 +set YRAD 200 + +vtkImageMandelbrotSource mandelbrot1 + mandelbrot1 SetMaximumNumberOfIterations 150 + mandelbrot1 SetWholeExtent 0 [expr $XRAD-1] \ + 0 [expr $YRAD-1] 0 0 + mandelbrot1 SetSampleCX [expr 1.3 / $XRAD] [expr 1.3 / $XRAD] \ + [expr 1.3 / $XRAD] [expr 1.3 / $XRAD] + mandelbrot1 SetOriginCX -0.72 0.22 0.0 0.0 + mandelbrot1 SetProjectionAxes 0 1 2 + +vtkImageMapToWindowLevelColors mapToWL +mapToWL SetInputConnection [mandelbrot1 GetOutputPort] +mapToWL SetWindow $RANGE +mapToWL SetLevel [expr $RANGE/3.0] + +# set the window/level to 255.0/127.5 to view full range +vtkImageViewer viewer +viewer SetInputConnection [mapToWL GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 + +viewer Render + +#make interface +viewer Render + +vtkWindowToImageFilter windowToimage + windowToimage SetInput [viewer GetRenderWindow] + + diff --git a/Imaging/Testing/Tcl/TestMapToWindowLevelColors2.tcl b/Imaging/Testing/Tcl/TestMapToWindowLevelColors2.tcl new file mode 100644 index 0000000..84531e6 --- /dev/null +++ b/Imaging/Testing/Tcl/TestMapToWindowLevelColors2.tcl @@ -0,0 +1,20 @@ +package require vtk + +vtkBMPReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +# set the window/level +vtkImageViewer2 viewer +viewer SetInputConnection [reader GetOutputPort] +viewer SetColorWindow 100.0 +viewer SetColorLevel 127.5 + +viewer Render + +#make interface +viewer Render + +vtkWindowToImageFilter windowToimage + windowToimage SetInput [viewer GetRenderWindow] + + diff --git a/Imaging/Testing/Tcl/TestMask2.tcl b/Imaging/Testing/Tcl/TestMask2.tcl new file mode 100644 index 0000000..82b11ee --- /dev/null +++ b/Imaging/Testing/Tcl/TestMask2.tcl @@ -0,0 +1,65 @@ +package require vtk + +# A script to test the mask filter. +# replaces a circle with a color + +wm withdraw . + +# Image pipeline +vtkPNMReader reader +reader ReleaseDataFlagOff +reader SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +vtkImageEllipsoidSource sphere +sphere SetWholeExtent 0 511 0 255 0 0 +sphere SetCenter 128 128 0 +sphere SetRadius 80 80 1 + +vtkImageMask mask +mask SetImageInput [reader GetOutput] +mask SetMaskInput [sphere GetOutput] +mask SetMaskedOutputValue 100 128 200; +mask NotMaskOn; +mask ReleaseDataFlagOff + +vtkImageEllipsoidSource sphere2 +sphere2 SetWholeExtent 0 511 0 255 0 0 +sphere2 SetCenter 328 128 0 +sphere2 SetRadius 80 50 1 + +# Test the wrapping of the output masked value +vtkImageMask mask2 +mask2 SetImageInput [mask GetOutput] +mask2 SetMaskInput [sphere2 GetOutput] +mask2 SetMaskedOutputValue 100; +mask2 NotMaskOn; +mask2 ReleaseDataFlagOff + +vtkImageEllipsoidSource sphere3 +sphere3 SetWholeExtent 0 511 0 255 0 0 +sphere3 SetCenter 228 155 0 +sphere3 SetRadius 80 80 1 + +# Test the wrapping of the output masked value +vtkImageMask mask3 +mask3 SetImageInput [mask2 GetOutput] +mask3 SetMaskInput [sphere3 GetOutput] +mask3 SetMaskedOutputValue 255; +mask3 NotMaskOn; +mask3 SetMaskAlpha 0.5 +mask3 ReleaseDataFlagOff + +vtkImageViewer viewer +viewer SetInputConnection [mask3 GetOutputPort] +viewer SetColorWindow 255 +viewer SetColorLevel 128 +#viewer DebugOn + +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestMedian3D.tcl b/Imaging/Testing/Tcl/TestMedian3D.tcl new file mode 100644 index 0000000..64d5507 --- /dev/null +++ b/Imaging/Testing/Tcl/TestMedian3D.tcl @@ -0,0 +1,35 @@ +package require vtk + +# Test the median filter. + + + + + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageMedian3D median +median SetInputConnection [reader GetOutputPort] +median SetKernelSize 7 7 1 +median ReleaseDataFlagOff + + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [median GetOutputPort] +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 + +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestNormalize.tcl b/Imaging/Testing/Tcl/TestNormalize.tcl new file mode 100644 index 0000000..235520f --- /dev/null +++ b/Imaging/Testing/Tcl/TestNormalize.tcl @@ -0,0 +1,27 @@ +package require vtk + +# This script is for testing the normalize filter. +# Image pipeline + +vtkImageSinusoidSource cos +cos SetWholeExtent 0 225 0 225 0 20 +cos SetAmplitude 250 +cos SetDirection 1 1 1 +cos SetPeriod 20 +cos ReleaseDataFlagOff + +vtkImageGradient gradient +gradient SetInputConnection [cos GetOutputPort] +gradient SetDimensionality 3 + +vtkImageNormalize norm +norm SetInputConnection [gradient GetOutputPort] + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [norm GetOutputPort] +viewer SetZSlice 10 +viewer SetColorWindow 2.0 +viewer SetColorLevel 0 + +viewer Render diff --git a/Imaging/Testing/Tcl/TestOpenClose3D.tcl b/Imaging/Testing/Tcl/TestOpenClose3D.tcl new file mode 100644 index 0000000..0687bdb --- /dev/null +++ b/Imaging/Testing/Tcl/TestOpenClose3D.tcl @@ -0,0 +1,46 @@ +# Tst the OpenClose3D filter. + +package require vtk + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkImageThreshold thresh +thresh SetInputConnection [reader GetOutputPort] +thresh SetOutputScalarTypeToUnsignedChar +thresh ThresholdByUpper 2000.0 +thresh SetInValue 255 +thresh SetOutValue 0 +thresh ReleaseDataFlagOff + +vtkImageOpenClose3D my_close +my_close SetInputConnection [thresh GetOutputPort] +my_close SetOpenValue 0 +my_close SetCloseValue 255 +my_close SetKernelSize 5 5 3 +my_close ReleaseDataFlagOff +# for coverage (we could compare results to see if they are correct). +my_close DebugOn +my_close DebugOff +my_close GetOutput +my_close GetCloseValue +my_close GetOpenValue +#my_close AddObserver ProgressEvent {set pro [my_close GetProgress]; puts "Completed $pro"; flush stdout} + +vtkImageViewer viewer +viewer SetInputConnection [my_close GetOutputPort] +viewer SetColorWindow 255 +viewer SetColorLevel 127.5 + + +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestPermute.tcl b/Imaging/Testing/Tcl/TestPermute.tcl new file mode 100644 index 0000000..1e844b2 --- /dev/null +++ b/Imaging/Testing/Tcl/TestPermute.tcl @@ -0,0 +1,35 @@ +package require vtk + +# Simple viewer for images. + + + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImagePermute permute +permute SetInputConnection [reader GetOutputPort] +permute SetFilteredAxes 1 2 0 + +vtkImageViewer viewer +viewer SetInputConnection [permute GetOutputPort] +viewer SetZSlice 32 +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 +#viewer DebugOn +#viewer Render + +#make interface +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestQuantizeTo16Colors.tcl b/Imaging/Testing/Tcl/TestQuantizeTo16Colors.tcl new file mode 100644 index 0000000..17850d0 --- /dev/null +++ b/Imaging/Testing/Tcl/TestQuantizeTo16Colors.tcl @@ -0,0 +1,37 @@ +package require vtk + +# Make an image larger by repeating the data. Tile. + + + + +# Image pipeline +vtkPNMReader reader +reader ReleaseDataFlagOff +reader SetFileName "$VTK_DATA_ROOT/Data/earth.ppm" + +vtkImageMirrorPad pad +pad SetInputConnection [reader GetOutputPort] +pad SetOutputWholeExtent -120 320 -120 320 0 0 + +vtkImageQuantizeRGBToIndex quant +quant SetInputConnection [pad GetOutputPort] +quant SetNumberOfColors 16 +quant Update + +vtkImageMapToRGBA map +map SetInputConnection [quant GetOutputPort] +map SetLookupTable [quant GetLookupTable] + +vtkImageViewer viewer +viewer SetInputConnection [map GetOutputPort] +viewer SetColorWindow 256 +viewer SetColorLevel 127 +[viewer GetActor2D] SetDisplayPosition 110 110 +viewer Render + + + + + + diff --git a/Imaging/Testing/Tcl/TestRange3D.tcl b/Imaging/Testing/Tcl/TestRange3D.tcl new file mode 100644 index 0000000..70f2f92 --- /dev/null +++ b/Imaging/Testing/Tcl/TestRange3D.tcl @@ -0,0 +1,26 @@ +package require vtk + + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageRange3D range +range SetInputConnection [reader GetOutputPort] +range SetKernelSize 5 5 5 + +vtkImageViewer viewer +viewer SetInputConnection [range GetOutputPort] +viewer SetZSlice 22 +viewer SetColorWindow 1000 +viewer SetColorLevel 500 +#viewer DebugOn + + +viewer Render + + diff --git a/Imaging/Testing/Tcl/TestResample.tcl b/Imaging/Testing/Tcl/TestResample.tcl new file mode 100644 index 0000000..3a48b57 --- /dev/null +++ b/Imaging/Testing/Tcl/TestResample.tcl @@ -0,0 +1,36 @@ +package require vtk + +# Doubles the The number of images (x dimension). + + + + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageResample magnify +magnify SetDimensionality 3 +magnify SetInputConnection [reader GetOutputPort] +magnify SetAxisOutputSpacing 0 0.52 +magnify SetAxisOutputSpacing 1 2.2 +magnify SetAxisOutputSpacing 2 0.8 +magnify ReleaseDataFlagOff + + +vtkImageViewer viewer +viewer SetInputConnection [magnify GetOutputPort] +viewer SetZSlice 30 +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 + +viewer Render + + + + diff --git a/Imaging/Testing/Tcl/TestSeparableFilter.tcl b/Imaging/Testing/Tcl/TestSeparableFilter.tcl new file mode 100644 index 0000000..865635e --- /dev/null +++ b/Imaging/Testing/Tcl/TestSeparableFilter.tcl @@ -0,0 +1,42 @@ +package require vtk + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +# Take the gradient in X, and smooth in Y + +# Create a simple gradient filter +vtkFloatArray kernel +kernel SetNumberOfTuples 3 +kernel InsertValue 0 -1 +kernel InsertValue 1 0 +kernel InsertValue 2 1 + +# Create a gaussian for Y +set sigma 1.5 +set sigma2 [expr $sigma * $sigma] +vtkFloatArray gaussian +gaussian SetNumberOfTuples 31 +for { set i 0 } { $i < 31 } { incr i } { + set x [expr $i - 15] + set g [expr exp ( - ( $x * $x ) / (2.0 * $sigma2) ) / ( sqrt ( 2.0 * 3.1415 ) * $sigma ) ] + gaussian InsertValue $i $g +} + +vtkImageSeparableConvolution convolve +convolve SetInputConnection [reader GetOutputPort] +convolve SetDimensionality 2 +convolve SetXKernel kernel +convolve SetYKernel gaussian + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [convolve GetOutputPort] +viewer SetColorWindow 500 +viewer SetColorLevel 100 + +wm withdraw . + +viewer Render diff --git a/Imaging/Testing/Tcl/TestShiftScale.tcl b/Imaging/Testing/Tcl/TestShiftScale.tcl new file mode 100644 index 0000000..1bc3eda --- /dev/null +++ b/Imaging/Testing/Tcl/TestShiftScale.tcl @@ -0,0 +1,41 @@ +package require vtk + +# Shift and scale an image (in that order) +# This filter is usefull for converting to a lower precision data type. + +vtkImageReader reader +[reader GetOutput] ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageShiftScale shiftScale +shiftScale SetInputConnection [reader GetOutputPort] +shiftScale SetShift 0 +shiftScale SetScale 0.5 +shiftScale SetOutputScalarTypeToDouble + +vtkImageShiftScale shiftScale2 +shiftScale2 SetInputConnection [shiftScale GetOutputPort] +shiftScale2 SetShift 0 +shiftScale2 SetScale 2.0 + +vtkImageMagnify mag + mag SetInputConnection [shiftScale2 GetOutputPort] + mag SetMagnificationFactors 4 4 1 + mag InterpolateOff + +vtkImageViewer viewer +viewer SetInputConnection [mag GetOutputPort] +viewer SetColorWindow 1024 +viewer SetColorLevel 1024 + +#make interface +source [file join [file dirname [info script]] WindowLevelInterface.tcl] + + +#vtkPNMWriter w +#w SetFileName "D:/vtknew/vtk/graphics/examplesTcl/mace2.ppm" +#w SetInputConnection [shiftScale GetOutputPort] +#w Write diff --git a/Imaging/Testing/Tcl/TestShiftScale2.tcl b/Imaging/Testing/Tcl/TestShiftScale2.tcl new file mode 100644 index 0000000..56a8727 --- /dev/null +++ b/Imaging/Testing/Tcl/TestShiftScale2.tcl @@ -0,0 +1,37 @@ +package require vtk + +# Shift and scale an image (in that order) +# This filter is usefull for converting to a lower precision data type. +# This script tests the clamp overflow feature. + +vtkImageReader reader +[reader GetOutput] ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageShiftScale shiftScale + shiftScale SetInputConnection [reader GetOutputPort] + shiftScale SetShift -1000.0 + shiftScale SetScale 4.0 + shiftScale SetOutputScalarTypeToUnsignedShort + shiftScale ClampOverflowOn + +vtkImageShiftScale shiftScale2 + shiftScale2 SetInputConnection [shiftScale GetOutputPort] + shiftScale2 SetShift 0 + shiftScale2 SetScale 2.0 + +vtkImageMagnify mag + mag SetInputConnection [shiftScale2 GetOutputPort] + mag SetMagnificationFactors 4 4 1 + mag InterpolateOff + +vtkImageViewer viewer + viewer SetInputConnection [mag GetOutputPort] + viewer SetColorWindow 1024 + viewer SetColorLevel 512 + +#make interface +source [file join [file dirname [info script]] WindowLevelInterface.tcl] diff --git a/Imaging/Testing/Tcl/TestSimpleImageExample.tcl b/Imaging/Testing/Tcl/TestSimpleImageExample.tcl new file mode 100644 index 0000000..a1dcfa8 --- /dev/null +++ b/Imaging/Testing/Tcl/TestSimpleImageExample.tcl @@ -0,0 +1,20 @@ +package require vtk + + + +# Image pipeline + +vtkPNGReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkSimpleImageFilterExample gradient +gradient SetInputConnection [reader GetOutputPort] + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [gradient GetOutputPort] +viewer SetColorWindow 1000 +viewer SetColorLevel 500 + + +viewer Render diff --git a/Imaging/Testing/Tcl/TestSkeleton2D.tcl b/Imaging/Testing/Tcl/TestSkeleton2D.tcl new file mode 100644 index 0000000..f04f197 --- /dev/null +++ b/Imaging/Testing/Tcl/TestSkeleton2D.tcl @@ -0,0 +1,125 @@ +package require vtk + +# A script to test the threshold filter. +# Values above 2000 are set to 255. +# Values below 2000 are set to 0. + +# Image pipeline + +vtkImageCanvasSource2D imageCanvas +imageCanvas SetScalarTypeToUnsignedChar +imageCanvas SetExtent 0 339 0 339 0 0 +# background black +imageCanvas SetDrawColor 0 +imageCanvas FillBox 0 511 0 511 + +# thick box +imageCanvas SetDrawColor 255 +imageCanvas FillBox 10 110 10 110 +imageCanvas SetDrawColor 0 +imageCanvas FillBox 30 90 30 90 + + +# put a stop sign in the box +imageCanvas SetDrawColor 255 +imageCanvas DrawSegment 52 80 68 80 +imageCanvas DrawSegment 68 80 80 68 +imageCanvas DrawSegment 80 68 80 52 +imageCanvas DrawSegment 80 52 68 40 +imageCanvas DrawSegment 68 40 52 40 +imageCanvas DrawSegment 52 40 40 52 +imageCanvas DrawSegment 40 52 40 68 +imageCanvas DrawSegment 40 68 52 80 +imageCanvas FillPixel 60 60 + +# diamond +imageCanvas SetDrawColor 255 +imageCanvas FillTube 145 145 195 195 34 +imageCanvas SetDrawColor 0 +imageCanvas FillTube 165 165 175 175 7 + +# H +imageCanvas SetDrawColor 255 +imageCanvas FillBox 230 250 230 330 +imageCanvas FillBox 310 330 230 330 +imageCanvas FillBox 230 330 270 290 + +# circle +imageCanvas SetDrawColor 255 +imageCanvas DrawCircle 280 170 50.0 + +# point as center of circle +imageCanvas SetDrawColor 255 +imageCanvas DrawPoint 280 170 + +# lines + +imageCanvas DrawSegment 60 120 60 220 +imageCanvas DrawSegment 10 170 110 170 + +# lines X +imageCanvas DrawSegment 10 230 110 330 +imageCanvas DrawSegment 110 230 10 330 + +# sloped lines +imageCanvas DrawSegment 120 230 220 230 +imageCanvas DrawSegment 120 230 220 250 +imageCanvas DrawSegment 120 230 220 270 +imageCanvas DrawSegment 120 230 220 290 +imageCanvas DrawSegment 120 230 220 310 +imageCanvas DrawSegment 120 230 220 330 +imageCanvas DrawSegment 120 230 200 330 +imageCanvas DrawSegment 120 230 180 330 +imageCanvas DrawSegment 120 230 160 330 +imageCanvas DrawSegment 120 230 140 330 +imageCanvas DrawSegment 120 230 120 330 + +# double thickness lines + +imageCanvas DrawSegment 120 60 220 60 +imageCanvas DrawSegment 120 61 220 61 +imageCanvas DrawSegment 170 10 170 110 +imageCanvas DrawSegment 171 10 171 110 + +# lines X +imageCanvas DrawSegment 230 10 330 110 +imageCanvas DrawSegment 231 10 331 110 +imageCanvas DrawSegment 230 110 330 10 +imageCanvas DrawSegment 231 110 331 10 + + +vtkImageSkeleton2D skeleton1 +#skeleton1 BypassOn +skeleton1 SetInputConnection [imageCanvas GetOutputPort] +skeleton1 SetPrune 0 +skeleton1 SetNumberOfIterations 20 +skeleton1 ReleaseDataFlagOff + +vtkImageClip clip +clip SetInputConnection [skeleton1 GetOutputPort] +clip SetOutputWholeExtent 0 120 0 120 0 0 + +vtkImageMagnify magnify +magnify SetInputConnection [clip GetOutputPort] +magnify SetMagnificationFactors 5 5 1 +magnify InterpolateOff +magnify ReleaseDataFlagOff + +vtkImageViewer viewer1 +viewer1 SetInputConnection [imageCanvas GetOutputPort] +viewer1 SetColorWindow 5 +viewer1 SetColorLevel 1 + +vtkImageViewer viewer +#viewer SetInputConnection [magnify GetOutputPort] +viewer SetInputConnection [skeleton1 GetOutputPort] +viewer SetColorWindow 5 +viewer SetColorLevel 1 + +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestSobel2D.tcl b/Imaging/Testing/Tcl/TestSobel2D.tcl new file mode 100644 index 0000000..b28a188 --- /dev/null +++ b/Imaging/Testing/Tcl/TestSobel2D.tcl @@ -0,0 +1,29 @@ +package require vtk + +# This script is for testing the 3D Sobel filter. +# Displays the 3 components using color. + + +# Image pipeline +vtkDICOMImageReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/mr.001" + +vtkImageSobel2D sobel +sobel SetInputConnection [reader GetOutputPort] +sobel ReleaseDataFlagOff + +vtkImageViewer viewer +viewer SetInputConnection [sobel GetOutputPort] +viewer SetColorWindow 400 +viewer SetColorLevel 0 + + +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestSobel3D.tcl b/Imaging/Testing/Tcl/TestSobel3D.tcl new file mode 100644 index 0000000..b0a29ce --- /dev/null +++ b/Imaging/Testing/Tcl/TestSobel3D.tcl @@ -0,0 +1,38 @@ +package require vtk + + +# This script is for testing the 3D Sobel filter. +# Displays the 3 components using color. + + +# Image pipeline + +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageSobel3D sobel +sobel SetInputConnection [reader GetOutputPort] +sobel ReleaseDataFlagOff + +vtkImageViewer viewer +#viewer DebugOn +viewer SetInputConnection [sobel GetOutputPort] +viewer SetZSlice 22 +viewer SetColorWindow 400 +viewer SetColorLevel 0 + + +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestStencilWithFunction.tcl b/Imaging/Testing/Tcl/TestStencilWithFunction.tcl new file mode 100644 index 0000000..95c0ae8 --- /dev/null +++ b/Imaging/Testing/Tcl/TestStencilWithFunction.tcl @@ -0,0 +1,54 @@ +package require vtk + + +# A script to test the stencil filter. +# removes all but a sphere. + + +vtkPNGReader reader +reader SetDataSpacing 0.8 0.8 1.5 +reader SetDataOrigin 0.0 0.0 0.0 +reader SetFileName "$VTK_DATA_ROOT/Data/fullhead15.png" + +vtkSphere sphere +sphere SetCenter 128 128 0 +sphere SetRadius 80 + +vtkImplicitFunctionToImageStencil functionToStencil +functionToStencil SetInput sphere + +# test manual updating of stencil +set stencilOriginal [functionToStencil GetOutput] +$stencilOriginal SetSpacing 0.8 0.8 1.5 +$stencilOriginal SetOrigin 0.0 0.0 0.0 +$stencilOriginal SetUpdateExtent 0 255 0 255 0 0 +$stencilOriginal Update + +# test making a copying of the stencil (for coverage) +set stencilCopy [$stencilOriginal NewInstance] +$stencilCopy DeepCopy $stencilOriginal + +vtkImageShiftScale shiftScale +shiftScale SetInputConnection [reader GetOutputPort] +shiftScale SetScale 0.2 + +vtkImageStencil stencil +stencil SetInputConnection [reader GetOutputPort] +stencil SetBackgroundInput [shiftScale GetOutput] +stencil SetStencil $stencilCopy +$stencilCopy UnRegister reader + +vtkImageViewer viewer +viewer SetInputConnection [stencil GetOutputPort] +viewer SetZSlice 0 +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 +viewer Render + + + + + + + + diff --git a/Imaging/Testing/Tcl/TestStencilWithImage.tcl b/Imaging/Testing/Tcl/TestStencilWithImage.tcl new file mode 100644 index 0000000..401a664 --- /dev/null +++ b/Imaging/Testing/Tcl/TestStencilWithImage.tcl @@ -0,0 +1,45 @@ +package require vtk + + +# A script to test the stencil filter by using one image +# to stencil another + + +# Image pipeline + +vtkBMPReader reader1 +reader1 SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + +vtkPNMReader reader2 +reader2 SetFileName "$VTK_DATA_ROOT/Data/B.pgm" + +vtkImageTranslateExtent translate +translate SetInputConnection [reader2 GetOutputPort] +translate SetTranslation 60 60 0 + +vtkImageToImageStencil imageToStencil +imageToStencil SetInputConnection [translate GetOutputPort] +imageToStencil ThresholdBetween 0 127 +# silly stuff to increase coverage +imageToStencil SetUpperThreshold [imageToStencil GetUpperThreshold] +imageToStencil SetLowerThreshold [imageToStencil GetLowerThreshold] + +vtkImageStencil stencil +stencil SetInputConnection [reader1 GetOutputPort] +stencil SetBackgroundValue 0 +stencil ReverseStencilOn +stencil SetStencil [imageToStencil GetOutput] + +vtkImageViewer viewer +viewer SetInputConnection [stencil GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 0 +viewer Render + + + + + + + diff --git a/Imaging/Testing/Tcl/TestThreshold.tcl b/Imaging/Testing/Tcl/TestThreshold.tcl new file mode 100644 index 0000000..9de3df5 --- /dev/null +++ b/Imaging/Testing/Tcl/TestThreshold.tcl @@ -0,0 +1,77 @@ +package require vtk + +# This script is for testing the 3D threshold filter. + +# Image pipeline + +vtkRenderWindow imgWin + imgWin SetSize 192 256 + +vtkImageReader reader + reader ReleaseDataFlagOff + reader SetDataByteOrderToLittleEndian + reader SetDataExtent 0 63 0 63 1 93 + reader SetDataSpacing 3.2 3.2 1.5 + reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + reader SetDataMask 0x7fff + +set outputtype(1) SetOutputScalarTypeToSignedChar +set outputtype(2) SetOutputScalarTypeToUnsignedChar +set outputtype(3) SetOutputScalarTypeToLong +set outputtype(4) SetOutputScalarTypeToUnsignedLong +set outputtype(5) SetOutputScalarTypeToInt +set outputtype(6) SetOutputScalarTypeToUnsignedInt +set outputtype(7) SetOutputScalarTypeToShort +set outputtype(8) SetOutputScalarTypeToUnsignedShort +set outputtype(9) SetOutputScalarTypeToDouble +set outputtype(10) SetOutputScalarTypeToFloat +set outputtype(11) SetOutputScalarTypeToDouble +set outputtype(12) SetOutputScalarTypeToFloat + +set replacein "ReplaceInOn ReplaceInOff" +set replaceout "ReplaceOutOn ReplaceOutOff" +set thresholds [list "ThresholdByLower 800" "ThresholdByUpper 1200" "ThresholdBetween 800 1200"] +set k 1 +foreach rin $replacein { + foreach rout $replaceout { + foreach t $thresholds { + vtkImageThreshold thresh$k + thresh$k SetInValue 2000 + thresh$k SetOutValue 0 + thresh$k $rin + thresh$k $rout + thresh$k SetInputConnection [reader GetOutputPort] + eval thresh$k $t + thresh$k $outputtype($k) + vtkImageMapper map$k + map$k SetInputConnection [thresh$k GetOutputPort] + if {$k < 3} { + map$k SetColorWindow 255 + map$k SetColorLevel 127.5 + } else { + map$k SetColorWindow 2000 + map$k SetColorLevel 1000 + } + vtkActor2D act$k + act$k SetMapper map$k + vtkRenderer ren$k + ren$k AddActor2D act$k + imgWin AddRenderer ren$k + incr k + } + } +} +ren1 SetViewport 0 0 .33333 .25 +ren2 SetViewport .33333 0 .66667 .25 +ren3 SetViewport .66667 0 1 .25 +ren4 SetViewport 0 .25 .33333 .5 +ren5 SetViewport .33333 .25 .66667 .5 +ren6 SetViewport .66667 .25 1 .5 +ren7 SetViewport 0 .5 .33333 .75 +ren8 SetViewport .33333 .5 .66667 .75 +ren9 SetViewport .66667 .5 1 .75 +ren10 SetViewport 0 .75 .33333 1 +ren11 SetViewport .33333 .75 .66667 1 +ren12 SetViewport .66667 .75 1 1 + +imgWin Render diff --git a/Imaging/Testing/Tcl/TestVariance3D.tcl b/Imaging/Testing/Tcl/TestVariance3D.tcl new file mode 100644 index 0000000..3a7f804 --- /dev/null +++ b/Imaging/Testing/Tcl/TestVariance3D.tcl @@ -0,0 +1,27 @@ +package require vtk + + + +# Image pipeline +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageVariance3D var +var SetInputConnection [reader GetOutputPort] +var SetKernelSize 3 3 1 + +vtkImageViewer viewer +viewer SetInputConnection [var GetOutputPort] +viewer SetZSlice 22 +viewer SetColorWindow 3000 +viewer SetColorLevel 1000 +#viewer DebugOn + +viewer Render + + diff --git a/Imaging/Testing/Tcl/TestWipe.tcl b/Imaging/Testing/Tcl/TestWipe.tcl new file mode 100644 index 0000000..9856c22 --- /dev/null +++ b/Imaging/Testing/Tcl/TestWipe.tcl @@ -0,0 +1,66 @@ +package require vtk +package require vtkinteraction + +# Image pipeline + +vtkRenderWindow imgWin + +vtkImageCanvasSource2D image1 + image1 SetNumberOfScalarComponents 3 + image1 SetScalarTypeToUnsignedChar + image1 SetExtent 0 79 0 79 0 0 + image1 SetDrawColor 255 255 0 + image1 FillBox 0 79 0 79 + +vtkImageCanvasSource2D image2 + image2 SetNumberOfScalarComponents 3 + image2 SetScalarTypeToUnsignedChar + image2 SetExtent 0 79 0 79 0 0 + image2 SetDrawColor 0 255 255 + image2 FillBox 0 79 0 79 + +vtkImageMapper mapper + mapper SetInputConnection [image1 GetOutputPort] + mapper SetColorWindow 255 + mapper SetColorLevel 127.5 +vtkActor2D actor + actor SetMapper mapper +vtkRenderer imager + imager AddActor2D actor + +imgWin AddRenderer imager + +set wipes "Quad Horizontal Vertical LowerLeft LowerRight UpperLeft UpperRight" + +foreach wipe $wipes { + + vtkImageRectilinearWipe wiper${wipe} + wiper${wipe} SetInput 0 [image1 GetOutput] + wiper${wipe} SetInput 1 [image2 GetOutput] + wiper${wipe} SetPosition 20 20 + wiper${wipe} SetWipeTo${wipe} + + vtkImageMapper mapper${wipe} + mapper${wipe} SetInputConnection [wiper${wipe} GetOutputPort] + mapper${wipe} SetColorWindow 255 + mapper${wipe} SetColorLevel 127.5 + vtkActor2D actor${wipe} + actor${wipe} SetMapper mapper${wipe} + vtkRenderer imager${wipe} + imager${wipe} AddActor2D actor${wipe} + + imgWin AddRenderer imager${wipe} +} +imagerQuad SetViewport 0 .5 .25 1 +imagerHorizontal SetViewport .25 .5 .5 1 +imagerVertical SetViewport .5 .5 .75 1 +imagerLowerLeft SetViewport .75 .5 1 1 +imagerLowerRight SetViewport 0 0 .25 .5 +imagerUpperLeft SetViewport .25 0 .5 .5 +imagerUpperRight SetViewport .5 0 .75 .5 +imager SetViewport .75 0 1 .5 + +imgWin SetSize 400 200 +imgWin Render + +wm withdraw . diff --git a/Imaging/Testing/Tcl/TestWrapPad.tcl b/Imaging/Testing/Tcl/TestWrapPad.tcl new file mode 100644 index 0000000..ba665de --- /dev/null +++ b/Imaging/Testing/Tcl/TestWrapPad.tcl @@ -0,0 +1,33 @@ +package require vtk + + +# Make an image larger by repeating the data. Tile. + + + +# Image pipeline + +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetDataSpacing 3.2 3.2 1.5 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +vtkImageWrapPad pad +pad SetInputConnection [reader GetOutputPort] +pad SetOutputWholeExtent -100 155 -100 170 0 92 +pad ReleaseDataFlagOff + +vtkImageViewer viewer +viewer SetInputConnection [pad GetOutputPort] +viewer SetZSlice 22 +viewer SetColorWindow 2000 +viewer SetColorLevel 1000 +[viewer GetActor2D] SetDisplayPosition 150 150 + +viewer Render + + + diff --git a/Imaging/Testing/Tcl/WindowLevelInterface.tcl b/Imaging/Testing/Tcl/WindowLevelInterface.tcl new file mode 100644 index 0000000..3a2b6e7 --- /dev/null +++ b/Imaging/Testing/Tcl/WindowLevelInterface.tcl @@ -0,0 +1,101 @@ +package require vtkinteraction + +# a simple user interface that manipulates window level. +# places in the tcl top window. Looks for object named viewer + +#only use this interface when not doing regression tests +if {[info commands rtExMath] != "rtExMath"} { + +# Take window level parameters from viewer +proc InitializeWindowLevelInterface {} { + global viewer sliceNumber + + # Get parameters from viewer + set w [viewer GetColorWindow] + set l [viewer GetColorLevel] + set sliceNumber [viewer GetZSlice] + set zMin [viewer GetWholeZMin] + set zMax [viewer GetWholeZMax] +# set zMin 0 +# set zMax 128 + + frame .slice + label .slice.label -text "Slice" + scale .slice.scale -from $zMin -to $zMax -orient horizontal \ + -command SetSlice -variable sliceNumber +# button .slice.up -text "Up" -command SliceUp +# button .slice.down -text "Down" -command SliceDown + + frame .wl + frame .wl.f1 + label .wl.f1.windowLabel -text "Window" + scale .wl.f1.window -from 1 -to [expr $w * 2] -orient horizontal \ + -command SetWindow -variable window + frame .wl.f2 + label .wl.f2.levelLabel -text "Level" + scale .wl.f2.level -from [expr $l - $w] -to [expr $l + $w] \ + -orient horizontal -command SetLevel + checkbutton .wl.video -text "Inverse Video" -command SetInverseVideo + + # resolutions less than 1.0 + if {$w < 10} { + set res [expr 0.05 * $w] + .wl.f1.window configure -resolution $res -from $res -to [expr 2.0 * $w] + .wl.f2.level configure -resolution $res \ + -from [expr 0.0 + $l - $w] -to [expr 0.0 + $l + $w] + } + + .wl.f1.window set $w + .wl.f2.level set $l + + frame .ex + button .ex.exit -text "Exit" -command "exit" + + pack .slice .wl .ex -side top + pack .slice.label .slice.scale -side left + pack .wl.f1 .wl.f2 .wl.video -side top + pack .wl.f1.windowLabel .wl.f1.window -side left + pack .wl.f2.levelLabel .wl.f2.level -side left + pack .ex.exit -side left +} + +proc SetSlice { slice } { + global sliceNumber viewer + + viewer SetZSlice $slice + viewer Render +} + +proc SetWindow window { + global viewer video + if {$video} { + viewer SetColorWindow [expr -$window] + } else { + viewer SetColorWindow $window + } + viewer Render +} + +proc SetLevel level { + global viewer + viewer SetColorLevel $level + viewer Render +} + +proc SetInverseVideo {} { + global viewer video window + if {$video} { + viewer SetColorWindow [expr -$window] + } else { + viewer SetColorWindow $window + } + viewer Render +} + + +InitializeWindowLevelInterface + +} else { + viewer Render +} + diff --git a/Imaging/Testing/Tcl/reconstructSurface.tcl b/Imaging/Testing/Tcl/reconstructSurface.tcl new file mode 100644 index 0000000..e7acac1 --- /dev/null +++ b/Imaging/Testing/Tcl/reconstructSurface.tcl @@ -0,0 +1,83 @@ +package require vtk +package require vtkinteraction + + +proc readPoints {} { +global VTK_DATA_ROOT + set output [pointSource GetPolyDataOutput] + vtkPoints points + $output SetPoints points + + set fp [open "$VTK_DATA_ROOT/Data/cactus.3337.pts" r] + while { [gets $fp line] != -1 } { + scan $line "%s" firstToken + if { $firstToken == "p" } { + scan $line "%s %f %f %f" firstToken x y z + points InsertNextPoint $x $y $z + } + } + points Delete; #okay, reference counting +} + +# Read some points. Use a programmable filter to read them. +# +vtkProgrammableSource pointSource + pointSource SetExecuteMethod readPoints + +# Construct the surface and create isosurface +# +vtkSurfaceReconstructionFilter surf + surf SetInput [pointSource GetPolyDataOutput] + +vtkContourFilter cf + cf SetInputConnection [surf GetOutputPort] + cf SetValue 0 0.0 + +vtkReverseSense reverse + reverse SetInputConnection [cf GetOutputPort] + reverse ReverseCellsOn + reverse ReverseNormalsOn + +vtkPolyDataMapper map + map SetInputConnection [reverse GetOutputPort] + map ScalarVisibilityOff + +vtkActor surfaceActor + surfaceActor SetMapper map + [surfaceActor GetProperty] SetDiffuseColor 1.0000 0.3882 0.2784 + [surfaceActor GetProperty] SetSpecularColor 1 1 1 + [surfaceActor GetProperty] SetSpecular .4 + [surfaceActor GetProperty] SetSpecularPower 50 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor surfaceActor +ren1 SetBackground 1 1 1 +renWin SetSize 300 300 +[ren1 GetActiveCamera] SetFocalPoint 0 0 0 +[ren1 GetActiveCamera] SetPosition 1 0 0 +[ren1 GetActiveCamera] SetViewUp 0 0 1 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 20 +[ren1 GetActiveCamera] Elevation 30 +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Imaging/Testing/Tcl/resampledTexture.tcl b/Imaging/Testing/Tcl/resampledTexture.tcl new file mode 100644 index 0000000..de82718 --- /dev/null +++ b/Imaging/Testing/Tcl/resampledTexture.tcl @@ -0,0 +1,60 @@ +package require vtk +package require vtkinteraction + +# Demonstrate automatic resampling of textures (i.e., OpenGL only handles +# power of two texture maps. This examples exercise's vtk's automatic +# power of two resampling). +# + +# get the interactor ui + +# create pipeline +# +# generate texture map (not power of two) +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 1 93 + v16 SetDataSpacing 3.2 3.2 1.5 +vtkExtractVOI extract + extract SetInputConnection [v16 GetOutputPort] + extract SetVOI 32 32 0 63 0 93 +vtkTexture atext + atext SetInputConnection [extract GetOutputPort] + atext InterpolateOn + +# gnerate plane to map texture on to +vtkPlaneSource plane + plane SetXResolution 1 + plane SetYResolution 1 +vtkPolyDataMapper textureMapper + textureMapper SetInputConnection [plane GetOutputPort] +vtkActor textureActor + textureActor SetMapper textureMapper + textureActor SetTexture atext + +# Create the RenderWindow, Renderer +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor textureActor +renWin SetSize 250 250 +ren1 SetBackground 0.1 0.2 0.4 + +iren Initialize + + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Imaging/Testing/Tcl/voxelModel.tcl b/Imaging/Testing/Tcl/voxelModel.tcl new file mode 100644 index 0000000..7e160c8 --- /dev/null +++ b/Imaging/Testing/Tcl/voxelModel.tcl @@ -0,0 +1,73 @@ +package require vtk +package require vtkinteraction + + +# Now create the RenderWindow, Renderer and Interactor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkSphereSource sphereModel + sphereModel SetThetaResolution 10 + sphereModel SetPhiResolution 10 + +vtkVoxelModeller voxelModel + voxelModel SetInputConnection [sphereModel GetOutputPort] + voxelModel SetSampleDimensions 21 21 21 + voxelModel SetModelBounds -1.5 1.5 -1.5 1.5 -1.5 1.5 + +if {[catch {set channel [open "voxelModel.vtk" "w"]}] == 0 } { + close $channel + file delete -force "voxelModel.vtk" + + vtkDataSetWriter aWriter + aWriter SetFileName "voxelModel.vtk" + aWriter SetInputConnection [voxelModel GetOutputPort] + aWriter Update + + vtkDataSetReader aReader + aReader SetFileName "voxelModel.vtk" + + vtkContourFilter voxelSurface + voxelSurface SetInputConnection [aReader GetOutputPort] + voxelSurface SetValue 0 .999 + + vtkPolyDataMapper voxelMapper + voxelMapper SetInputConnection [voxelSurface GetOutputPort] + + vtkActor voxelActor + voxelActor SetMapper voxelMapper + + vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphereModel GetOutputPort] + + vtkActor sphereActor + sphereActor SetMapper sphereMapper + + ren1 AddActor sphereActor + ren1 AddActor voxelActor + + ren1 SetBackground .1 .2 .4 + renWin SetSize 256 256 + ren1 ResetCamera + [ren1 GetActiveCamera] SetViewUp 0 -1 0; + [ren1 GetActiveCamera] Azimuth 180 + [ren1 GetActiveCamera] Dolly 1.75 + ren1 ResetCameraClippingRange + + iren Initialize; + +# render the image +# + iren AddObserver UserEvent {wm deiconify .vtkInteract}; + + +# prevent the tk window from showing up then start the event loop + wm withdraw . + catch { file delete -force "voxelModel.vtk" } +} + + diff --git a/Imaging/vtkBooleanTexture.cxx b/Imaging/vtkBooleanTexture.cxx new file mode 100644 index 0000000..1cf48b0 --- /dev/null +++ b/Imaging/vtkBooleanTexture.cxx @@ -0,0 +1,175 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBooleanTexture.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBooleanTexture.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkBooleanTexture, "$Revision: 1.44 $"); +vtkStandardNewMacro(vtkBooleanTexture); + +vtkBooleanTexture::vtkBooleanTexture() +{ + this->SetNumberOfInputPorts(0); + this->Thickness = 0; + + this->XSize = this->YSize = 12; + + this->InIn[0] = this->InIn[1] = 255; + this->InOut[0] = this->InOut[1] = 255; + this->OutIn[0] = this->OutIn[1] = 255; + this->OutOut[0] = this->OutOut[1] = 255; + this->OnOn[0] = this->OnOn[1] = 255; + this->OnIn[0] = this->OnIn[1] = 255; + this->OnOut[0] = this->OnOut[1] = 255; + this->InOn[0] = this->InOn[1] = 255; + this->OutOn[0] = this->OutOn[1] = 255; +} + +//---------------------------------------------------------------------------- +int vtkBooleanTexture::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int wExt[6]; + wExt[0] = 0; + wExt[1] = this->XSize - 1; + wExt[2] = 0; + wExt[3] = this->YSize - 1; + wExt[4] = 0; + wExt[5] = 0; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wExt,6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 2); + return 1; +} + +void vtkBooleanTexture::ExecuteData(vtkDataObject *outp) +{ + int i, j; + int midILower, midJLower, midIUpper, midJUpper; + vtkImageData *output = this->AllocateOutputData(outp); + vtkUnsignedCharArray *newScalars = + vtkUnsignedCharArray::SafeDownCast(output->GetPointData()->GetScalars()); + + if (!newScalars || this->XSize*this->YSize < 1 ) + { + vtkErrorMacro(<<"Bad texture (xsize,ysize) specification!"); + return; + } + +// +// Compute size of various regions +// + midILower = (int) ((float)(this->XSize - 1) / 2.0 - this->Thickness / 2.0); + midJLower = (int) ((float)(this->YSize - 1) / 2.0 - this->Thickness / 2.0); + midIUpper = (int) ((float)(this->XSize - 1) / 2.0 + this->Thickness / 2.0); + midJUpper = (int) ((float)(this->YSize - 1) / 2.0 + this->Thickness / 2.0); +// +// Create texture map +// + int count = 0; + for (j = 0; j < this->YSize; j++) + { + for (i = 0; i < this->XSize; i++) + { + if (i < midILower && j < midJLower) + { + newScalars->SetValue(count,this->InIn[0]); + count++; + newScalars->SetValue(count,this->InIn[1]); + } + else if (i > midIUpper && j < midJLower) + { + newScalars->SetValue(count,this->OutIn[0]); + count++; + newScalars->SetValue(count,this->OutIn[1]); + } + else if (i < midILower && j > midJUpper) + { + newScalars->SetValue(count,this->InOut[0]); + count++; + newScalars->SetValue(count,this->InOut[1]); + } + else if (i > midIUpper && j > midJUpper) + { + newScalars->SetValue(count,this->OutOut[0]); + count++; + newScalars->SetValue(count,this->OutOut[1]); + } + else if ((i >= midILower && i <= midIUpper) && (j >= midJLower && j <= midJUpper)) + { + newScalars->SetValue(count,this->OnOn[0]); + count++; + newScalars->SetValue(count,this->OnOn[1]); + } + else if ((i >= midILower && i <= midIUpper) && j < midJLower) + { + newScalars->SetValue(count,this->OnIn[0]); + count++; + newScalars->SetValue(count,this->OnIn[1]); + } + else if ((i >= midILower && i <= midIUpper) && j > midJUpper) + { + newScalars->SetValue(count,this->OnOut[0]); + count++; + newScalars->SetValue(count,this->OnOut[1]); + } + else if (i < midILower && (j >= midJLower && j <= midJUpper)) + { + newScalars->SetValue(count,this->InOn[0]); + count++; + newScalars->SetValue(count,this->InOn[1]); + } + else if (i > midIUpper && (j >= midJLower && j <= midJUpper)) + { + newScalars->SetValue(count,this->OutOn[0]); + count++; + newScalars->SetValue(count,this->OutOn[1]); + } + count++; + } + } + +} + +void vtkBooleanTexture::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "X Size: " << this->XSize << "\n"; + os << indent << "Y Size: " << this->YSize << "\n"; + + os << indent << "Thickness: " << this->Thickness << "\n"; + os << indent << "In/In: (" << this->InIn[0] << "," << this->InIn[1] << ")\n"; + os << indent << "In/Out: (" << this->InOut[0] << "," << this->InOut[1] << ")\n"; + os << indent << "Out/In: (" << this->OutIn[0] << "," << this->OutIn[1] << ")\n"; + os << indent << "Out/Out: (" << this->OutOut[0] << "," << this->OutOut[1] << ")\n"; + os << indent << "On/On: (" << this->OnOn[0] << "," << this->OnOn[1] << ")\n"; + os << indent << "On/In: (" << this->OnIn[0] << "," << this->OnIn[1] << ")\n"; + os << indent << "On/Out: (" << this->OnOut[0] << "," << this->OnOut[1] << ")\n"; + os << indent << "In/On: (" << this->InOn[0] << "," << this->InOn[1] << ")\n"; + os << indent << "Out/On: (" << this->OutOn[0] << "," << this->OutOn[1] << ")\n"; +} + diff --git a/Imaging/vtkBooleanTexture.h b/Imaging/vtkBooleanTexture.h new file mode 100644 index 0000000..78e5229 --- /dev/null +++ b/Imaging/vtkBooleanTexture.h @@ -0,0 +1,142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBooleanTexture.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBooleanTexture - generate 2D texture map based on combinations of inside, outside, and on region boundary + +// .SECTION Description +// vtkBooleanTexture is a filter to generate a 2D texture map based on +// combinations of inside, outside, and on region boundary. The "region" is +// implicitly represented via 2D texture coordinates. These texture +// coordinates are normally generated using a filter like +// vtkImplicitTextureCoords, which generates the texture coordinates for +// any implicit function. +// +// vtkBooleanTexture generates the map according to the s-t texture +// coordinates plus the notion of being in, on, or outside of a +// region. An in region is when the texture coordinate is between +// (0,0.5-thickness/2). An out region is where the texture coordinate +// is (0.5+thickness/2). An on region is between +// (0.5-thickness/2,0.5+thickness/2). The combination in, on, and out +// for each of the s-t texture coordinates results in 16 possible +// combinations (see text). For each combination, a different value of +// intensity and transparency can be assigned. To assign maximum intensity +// and/or opacity use the value 255. A minimum value of 0 results in +// a black region (for intensity) and a fully transparent region (for +// transparency). + +// .SECTION See Also +// vtkImplicitTextureCoords vtkThresholdTextureCoords + +#ifndef __vtkBooleanTexture_h +#define __vtkBooleanTexture_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkBooleanTexture : public vtkImageAlgorithm +{ +public: + static vtkBooleanTexture *New(); + + vtkTypeRevisionMacro(vtkBooleanTexture,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the X texture map dimension. + vtkSetMacro(XSize,int); + vtkGetMacro(XSize,int); + + // Description: + // Set the Y texture map dimension. + vtkSetMacro(YSize,int); + vtkGetMacro(YSize,int); + + // Description: + // Set the thickness of the "on" region. + vtkSetMacro(Thickness,int); + vtkGetMacro(Thickness,int); + + // Description: + // Specify intensity/transparency for "in/in" region. + vtkSetVector2Macro(InIn,unsigned char); + vtkGetVectorMacro(InIn,unsigned char,2); + + // Description: + // Specify intensity/transparency for "in/out" region. + vtkSetVector2Macro(InOut,unsigned char); + vtkGetVectorMacro(InOut,unsigned char,2); + + // Description: + // Specify intensity/transparency for "out/in" region. + vtkSetVector2Macro(OutIn,unsigned char); + vtkGetVectorMacro(OutIn,unsigned char,2); + + // Description: + // Specify intensity/transparency for "out/out" region. + vtkSetVector2Macro(OutOut,unsigned char); + vtkGetVectorMacro(OutOut,unsigned char,2); + + // Description: + // Specify intensity/transparency for "on/on" region. + vtkSetVector2Macro(OnOn,unsigned char); + vtkGetVectorMacro(OnOn,unsigned char,2); + + // Description: + // Specify intensity/transparency for "on/in" region. + vtkSetVector2Macro(OnIn,unsigned char); + vtkGetVectorMacro(OnIn,unsigned char,2); + + // Description: + // Specify intensity/transparency for "on/out" region. + vtkSetVector2Macro(OnOut,unsigned char); + vtkGetVectorMacro(OnOut,unsigned char,2); + + // Description: + // Specify intensity/transparency for "in/on" region. + vtkSetVector2Macro(InOn,unsigned char); + vtkGetVectorMacro(InOn,unsigned char,2); + + // Description: + // Specify intensity/transparency for "out/on" region. + vtkSetVector2Macro(OutOn,unsigned char); + vtkGetVectorMacro(OutOn,unsigned char,2); + +protected: + vtkBooleanTexture(); + ~vtkBooleanTexture() {}; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); + virtual void ExecuteData(vtkDataObject *data); + + int XSize; + int YSize; + + int Thickness; + unsigned char InIn[2]; + unsigned char InOut[2]; + unsigned char OutIn[2]; + unsigned char OutOut[2]; + unsigned char OnOn[2]; + unsigned char OnIn[2]; + unsigned char OnOut[2]; + unsigned char InOn[2]; + unsigned char OutOn[2]; + +private: + vtkBooleanTexture(const vtkBooleanTexture&); // Not implemented. + void operator=(const vtkBooleanTexture&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkExtractVOI.cxx b/Imaging/vtkExtractVOI.cxx new file mode 100644 index 0000000..5264f15 --- /dev/null +++ b/Imaging/vtkExtractVOI.cxx @@ -0,0 +1,326 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractVOI.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractVOI.h" + +#include "vtkCellData.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkExtractVOI, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkExtractVOI); + +//----------------------------------------------------------------------------- +// Construct object to extract all of the input data. +vtkExtractVOI::vtkExtractVOI() +{ + this->VOI[0] = this->VOI[2] = this->VOI[4] = -VTK_LARGE_INTEGER; + this->VOI[1] = this->VOI[3] = this->VOI[5] = VTK_LARGE_INTEGER; + + this->SampleRate[0] = this->SampleRate[1] = this->SampleRate[2] = 1; +} + +//----------------------------------------------------------------------------- +// Get ALL of the input. +int vtkExtractVOI::RequestUpdateExtent ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed( outputVector )) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // request all of the VOI, (note from Ken why are we not looking at the UE?) + int i; + int inExt[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),inExt); + + // no need to go outside the VOI + for (i = 0; i < 3; ++i) + { + if (inExt[i*2] < this->VOI[i*2]) + { + inExt[i*2] = this->VOI[i*2]; + } + if (inExt[i*2+1] > this->VOI[i*2+1]) + { + inExt[i*2+1] = this->VOI[i*2+1]; + } + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + +//----------------------------------------------------------------------------- +int +vtkExtractVOI::RequestInformation ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int i, outDims[3], voi[6]; + int rate[3]; + int wholeExtent[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent ); + + double ar[3], outAR[3]; + inInfo->Get(vtkDataObject::SPACING(), ar ); + + double origin[3], outOrigin[3]; + inInfo->Get(vtkDataObject::ORIGIN(), origin ); + + for ( i=0; i < 6; i++ ) + { + voi[i] = this->VOI[i]; + } + + for ( i=0; i < 3; i++ ) + { + if ( voi[2*i+1] > wholeExtent[2*i+1] ) + { + voi[2*i+1] = wholeExtent[2*i+1]; + } + else if ( voi[2*i+1] < wholeExtent[2*i] ) + { + voi[2*i+1] = wholeExtent[2*i]; + } + if ( voi[2*i] < wholeExtent[2*i] ) + { + voi[2*i] = wholeExtent[2*i]; + } + else if ( voi[2*i] > wholeExtent[2*i+1] ) + { + voi[2*i] = wholeExtent[2*i+1]; + } + + if ( voi[2*i] > voi[2*i+1] ) + { + voi[2*i] = voi[2*i+1]; + } + + if ( (rate[i] = this->SampleRate[i]) < 1 ) + { + rate[i] = 1; + } + + outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1; + if ( outDims[i] < 1 ) + { + outDims[i] = 1; + } + outAR[i] = ar[i] * this->SampleRate[i]; + wholeExtent[i*2] = voi[i*2]; + wholeExtent[i*2+1] = voi[i*2] + outDims[i] - 1; + outOrigin[i] = origin[i] + voi[2*i]*ar[i] - wholeExtent[2*i]*outAR[i]; + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent ,6); + outInfo->Set(vtkDataObject::SPACING(), outAR, 3); + outInfo->Set(vtkDataObject::ORIGIN(), outOrigin, 3); + + return 1; +} + +//----------------------------------------------------------------------------- +int vtkExtractVOI::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the data objects + vtkInformation *outInfo = + outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(); + vtkCellData *cd=input->GetCellData(); + output->SetExtent(output->GetWholeExtent()); + vtkPointData *outPD=output->GetPointData(); + vtkCellData *outCD=output->GetCellData(); + int i, j, k, dims[3], outDims[3], voi[6], dim, idx, newIdx; + int newCellId; + double origin[3], ar[3]; + int sliceSize, outSize, jOffset, kOffset, rate[3]; + int wholeExtent[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent); + int *inExt = input->GetExtent(); + + vtkDebugMacro(<< "Extracting VOI"); + // + // Check VOI and clamp as necessary. Compute output parameters, + // + input->GetDimensions(dims); + input->GetOrigin(origin); + input->GetSpacing(ar); + + for ( i=0; i < 6; i++ ) + { + voi[i] = this->VOI[i]; + } + + for ( outSize=1, dim=0, i=0; i < 3; i++ ) + { + if ( voi[2*i+1] > wholeExtent[2*i+1] ) + { + voi[2*i+1] = wholeExtent[2*i+1]; + } + else if ( voi[2*i+1] < wholeExtent[2*i] ) + { + voi[2*i+1] = wholeExtent[2*i]; + } + if ( voi[2*i] < wholeExtent[2*i] ) + { + voi[2*i] = wholeExtent[2*i]; + } + else if ( voi[2*i] > wholeExtent[2*i+1] ) + { + voi[2*i] = wholeExtent[2*i+1]; + } + + if ( voi[2*i] > voi[2*i+1] ) + { + voi[2*i] = voi[2*i+1]; + } + + if ( (voi[2*i+1]-voi[2*i]) > 0 ) + { + dim++; + } + + if ( (rate[i] = this->SampleRate[i]) < 1 ) + { + rate[i] = 1; + } + + outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1; + if ( outDims[i] < 1 ) + { + outDims[i] = 1; + } + + outSize *= outDims[i]; + } + + // + // If output same as input, just pass data through + // + if ( outDims[0] == dims[0] && outDims[1] == dims[1] && outDims[2] == dims[2] && + rate[0] == 1 && rate[1] == 1 && rate[2] == 1 ) + { + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + vtkDebugMacro(<<"Passed data through because input and output are the same"); + return 1; + } + // + // Allocate necessary objects + // + outPD->CopyAllocate(pd,outSize,outSize); + outCD->CopyAllocate(cd,outSize,outSize); + sliceSize = dims[0]*dims[1]; + + // + // Traverse input data and copy point attributes to output + // + newIdx = 0; + for ( k=voi[4]; k <= voi[5]; k += rate[2] ) + { + kOffset = (k-inExt[4]) * sliceSize; + for ( j=voi[2]; j <= voi[3]; j += rate[1] ) + { + jOffset = (j-inExt[2]) * dims[0]; + for ( i=voi[0]; i <= voi[1]; i += rate[0] ) + { + idx = (i-inExt[0]) + jOffset + kOffset; + outPD->CopyData(pd, idx, newIdx++); + } + } + } + + // + // Traverse input data and copy cell attributes to output + // + // Handle 2D, 1D and 0D degenerate data sets. + if (voi[5] == voi[4]) + { + ++voi[5]; + } + if (voi[3] == voi[2]) + { + ++voi[3]; + } + if (voi[1] == voi[0]) + { + ++voi[1]; + } + + newCellId = 0; + sliceSize = (dims[0]-1)*(dims[1]-1); + for ( k=voi[4]; k < voi[5]; k += rate[2] ) + { + kOffset = (k-inExt[4]) * sliceSize; + for ( j=voi[2]; j < voi[3]; j += rate[1] ) + { + jOffset = (j-inExt[2]) * (dims[0] - 1); + for ( i=voi[0]; i < voi[1]; i += rate[0] ) + { + idx = (i-inExt[0]) + jOffset + kOffset; + outCD->CopyData(cd, idx, newCellId++); + } + } + } + + vtkDebugMacro(<<"Extracted " << newIdx << " point attributes on " + << dim << "-D dataset\n\tDimensions are (" << outDims[0] + << "," << outDims[1] << "," << outDims[2] <<")"); + + return 1; +} + + +//----------------------------------------------------------------------------- +void vtkExtractVOI::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "VOI: \n"; + os << indent << " Imin,Imax: (" << this->VOI[0] + << ", " << this->VOI[1] << ")\n"; + os << indent << " Jmin,Jmax: (" << this->VOI[2] + << ", " << this->VOI[3] << ")\n"; + os << indent << " Kmin,Kmax: (" << this->VOI[4] + << ", " << this->VOI[5] << ")\n"; + + os << indent << "Sample Rate: (" << this->SampleRate[0] << ", " + << this->SampleRate[1] << ", " + << this->SampleRate[2] << ")\n"; +} + + + + diff --git a/Imaging/vtkExtractVOI.h b/Imaging/vtkExtractVOI.h new file mode 100644 index 0000000..62d34b6 --- /dev/null +++ b/Imaging/vtkExtractVOI.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractVOI.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractVOI - select piece (e.g., volume of interest) and/or subsample structured points dataset + +// .SECTION Description +// vtkExtractVOI is a filter that selects a portion of an input structured +// points dataset, or subsamples an input dataset. (The selected portion of +// interested is referred to as the Volume Of Interest, or VOI.) The output of +// this filter is a structured points dataset. The filter treats input data +// of any topological dimension (i.e., point, line, image, or volume) and can +// generate output data of any topological dimension. +// +// To use this filter set the VOI ivar which are i-j-k min/max indices that +// specify a rectangular region in the data. (Note that these are 0-offset.) +// You can also specify a sampling rate to subsample the data. +// +// Typical applications of this filter are to extract a slice from a volume +// for image processing, subsampling large volumes to reduce data size, or +// extracting regions of a volume with interesting data. + +// .SECTION See Also +// vtkGeometryFilter vtkExtractGeometry vtkExtractGrid + +#ifndef __vtkExtractVOI_h +#define __vtkExtractVOI_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkExtractVOI : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkExtractVOI,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object to extract all of the input data. + static vtkExtractVOI *New(); + + // Description: + // Specify i-j-k (min,max) pairs to extract. The resulting structured points + // dataset can be of any topological dimension (i.e., point, line, image, + // or volume). + vtkSetVector6Macro(VOI,int); + vtkGetVectorMacro(VOI,int,6); + + // Description: + // Set the sampling rate in the i, j, and k directions. If the rate is > + // 1, then the resulting VOI will be subsampled representation of the + // input. For example, if the SampleRate=(2,2,2), every other point will + // be selected, resulting in a volume 1/8th the original size. + vtkSetVector3Macro(SampleRate, int); + vtkGetVectorMacro(SampleRate, int, 3); + +protected: + vtkExtractVOI(); + ~vtkExtractVOI() {}; + + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + int VOI[6]; + int SampleRate[3]; +private: + vtkExtractVOI(const vtkExtractVOI&); // Not implemented. + void operator=(const vtkExtractVOI&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkGaussianSplatter.cxx b/Imaging/vtkGaussianSplatter.cxx new file mode 100644 index 0000000..b6c0181 --- /dev/null +++ b/Imaging/vtkGaussianSplatter.cxx @@ -0,0 +1,585 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGaussianSplatter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGaussianSplatter.h" + +#include "vtkDoubleArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkGaussianSplatter, "$Revision: 1.59 $"); +vtkStandardNewMacro(vtkGaussianSplatter); + +// Construct object with dimensions=(50,50,50); automatic computation of +// bounds; a splat radius of 0.1; an exponent factor of -5; and normal and +// scalar warping turned on. +vtkGaussianSplatter::vtkGaussianSplatter() +{ + this->SampleDimensions[0] = 50; + this->SampleDimensions[1] = 50; + this->SampleDimensions[2] = 50; + + this->Radius = 0.1; + this->ExponentFactor = -5.0; + + this->ModelBounds[0] = 0.0; + this->ModelBounds[1] = 0.0; + this->ModelBounds[2] = 0.0; + this->ModelBounds[3] = 0.0; + this->ModelBounds[4] = 0.0; + this->ModelBounds[5] = 0.0; + + this->NormalWarping = 1; + this->Eccentricity = 2.5; + + this->ScalarWarping = 1; + this->ScaleFactor = 1.0; + + this->Capping = 1; + this->CapValue = 0.0; + + this->AccumulationMode = VTK_ACCUMULATION_MODE_MAX; + this->NullValue = 0.0; +} + +int vtkGaussianSplatter::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + // use model bounds if set + this->Origin[0] = 0; + this->Origin[1] = 0; + this->Origin[2] = 0; + if ( this->ModelBounds[0] < this->ModelBounds[1] && + this->ModelBounds[2] < this->ModelBounds[3] && + this->ModelBounds[4] < this->ModelBounds[5] ) + { + this->Origin[0] = this->ModelBounds[0]; + this->Origin[1] = this->ModelBounds[2]; + this->Origin[2] = this->ModelBounds[4]; + } + + outInfo->Set(vtkDataObject::ORIGIN(), this->Origin, 3); + + int i; + for (i=0; i<3; i++) + { + this->Spacing[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + if ( this->Spacing[i] <= 0.0 ) + { + this->Spacing[i] = 1.0; + } + } + outInfo->Set(vtkDataObject::SPACING(),this->Spacing,3); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, this->SampleDimensions[0] - 1, + 0, this->SampleDimensions[1] - 1, + 0, this->SampleDimensions[2] - 1); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 1); + return 1; +} + +int vtkGaussianSplatter::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the data object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->SetExtent( + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); + output->AllocateScalars(); + + vtkIdType numPts, numNewPts, ptId, idx, i; + int j, k; + int min[3], max[3]; + vtkPointData *pd; + vtkDataArray *inNormals=NULL; + vtkDataArray *inScalars=NULL; + double loc[3], dist2, cx[3]; + vtkDoubleArray *newScalars = + vtkDoubleArray::SafeDownCast(output->GetPointData()->GetScalars()); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + int sliceSize=this->SampleDimensions[0]*this->SampleDimensions[1]; + + vtkDebugMacro(<< "Splatting data"); + + // Make sure points are available + // + if ( (numPts=input->GetNumberOfPoints()) < 1 ) + { + vtkErrorMacro(<<"No points to splat!"); + return 1; + } + + // Compute the radius of influence of the points. If an + // automatically generated bounding box has been generated, increase + // its size slightly to acoomodate the radius of influence. + // + this->Eccentricity2 = this->Eccentricity * this->Eccentricity; + + numNewPts = this->SampleDimensions[0] * this->SampleDimensions[1] * + this->SampleDimensions[2]; + for (i=0; iSetTuple(i,&this->NullValue); + } + this->Visited = new char[numNewPts]; + for (i=0; i < numNewPts; i++) + { + this->Visited[i] = 0; + } + + output->SetDimensions(this->GetSampleDimensions()); + this->ComputeModelBounds(input,output, outInfo); + + // Set up function pointers to sample functions + // + pd = input->GetPointData(); + if ( this->NormalWarping && (inNormals=pd->GetNormals()) != NULL ) + { + this->Sample = &vtkGaussianSplatter::EccentricGaussian; + } + else + { + this->Sample = &vtkGaussianSplatter::Gaussian; + } + + if ( this->ScalarWarping && (inScalars=pd->GetScalars()) != NULL ) + { + this->SampleFactor = &vtkGaussianSplatter::ScalarSampling; + } + else + { + this->SampleFactor = &vtkGaussianSplatter::PositionSampling; + this->S = 0.0; //position sampling does not require S to be defined + //but this makes purify happy. + } + + // Traverse all points - splatting each into the volume. + // For each point, determine which voxel it is in. Then determine + // the subvolume that the splat is contained in, and process that. + // + int abortExecute=0; + vtkIdType progressInterval = numPts/20 + 1; + for (ptId=0; ptId < numPts && !abortExecute; ptId++) + { + if ( ! (ptId % progressInterval) ) + { + vtkDebugMacro(<<"Inserting point #" << ptId); + this->UpdateProgress ((double)ptId/numPts); + abortExecute = this->GetAbortExecute(); + } + + this->P = input->GetPoint(ptId); + if ( inNormals != NULL ) + { + this->N = inNormals->GetTuple(ptId); + } + if ( inScalars != NULL ) + { + this->S = inScalars->GetComponent(ptId,0); + } + + // Determine the voxel that the point is in + for (i=0; i<3; i++) + { + loc[i] = (this->P[i] - this->Origin[i]) / this->Spacing[i]; + } + + // Determine splat footprint + for (i=0; i<3; i++) + { + min[i] = (int) floor((double)loc[i]-this->SplatDistance[i]); + max[i] = (int) ceil((double)loc[i]+this->SplatDistance[i]); + if ( min[i] < 0 ) + { + min[i] = 0; + } + if ( max[i] >= this->SampleDimensions[i] ) + { + max[i] = this->SampleDimensions[i] - 1; + } + } + + // Loop over all sample points in volume within footprint and + // evaluate the splat + for (k=min[2]; k<=max[2]; k++) + { + cx[2] = this->Origin[2] + this->Spacing[2]*k; + for (j=min[1]; j<=max[1]; j++) + { + cx[1] = this->Origin[1] + this->Spacing[1]*j; + for (i=min[0]; i<=max[0]; i++) + { + cx[0] = this->Origin[0] + this->Spacing[0]*i; + if ( (dist2=(this->*Sample)(cx)) <= this->Radius2 ) + { + idx = i + j*this->SampleDimensions[0] + k*sliceSize; + this->SetScalar(idx,dist2, newScalars); + }//if within splat radius + } + } + }//within splat footprint + }//for all input points + + // If capping is turned on, set the distances of the outside of the volume + // to the CapValue. + // + if ( this->Capping ) + { + this->Cap(newScalars); + } + + vtkDebugMacro(<< "Splatted " << input->GetNumberOfPoints() << " points"); + + // Update self and release memeory + // + delete [] this->Visited; + + return 1; +} + +// Compute the size of the sample bounding box automatically from the +// input data. +void vtkGaussianSplatter::ComputeModelBounds(vtkDataSet *input, + vtkImageData *output, + vtkInformation *outInfo) +{ + double *bounds, maxDist; + int i, adjustBounds=0; + + // compute model bounds if not set previously + if ( this->ModelBounds[0] >= this->ModelBounds[1] || + this->ModelBounds[2] >= this->ModelBounds[3] || + this->ModelBounds[4] >= this->ModelBounds[5] ) + { + adjustBounds = 1; + bounds = input->GetBounds(); + } + else + { + bounds = this->ModelBounds; + } + + for (maxDist=0.0, i=0; i<3; i++) + { + if ( (bounds[2*i+1] - bounds[2*i]) > maxDist ) + { + maxDist = bounds[2*i+1] - bounds[2*i]; + } + } + maxDist *= this->Radius; + this->Radius2 = maxDist * maxDist; + + // adjust bounds so model fits strictly inside (only if not set previously) + if ( adjustBounds ) + { + for (i=0; i<3; i++) + { + this->ModelBounds[2*i] = bounds[2*i] - maxDist; + this->ModelBounds[2*i+1] = bounds[2*i+1] + maxDist; + } + } + + // Set volume origin and data spacing + outInfo->Set(vtkDataObject::ORIGIN(), + this->ModelBounds[0],this->ModelBounds[2], + this->ModelBounds[4]); + memcpy(this->Origin,outInfo->Get(vtkDataObject::ORIGIN()), sizeof(double)*6); + output->SetOrigin(this->Origin); + + for (i=0; i<3; i++) + { + this->Spacing[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + if ( this->Spacing[i] <= 0.0 ) + { + this->Spacing[i] = 1.0; + } + } + outInfo->Set(vtkDataObject::SPACING(),this->Spacing,3); + output->SetSpacing(this->Spacing); + + // Determine the splat propagation distance...used later + for (i=0; i<3; i++) + { + this->SplatDistance[i] = maxDist / this->Spacing[i]; + } +} + +// Set the dimensions of the sampling structured point set. +void vtkGaussianSplatter::SetSampleDimensions(int i, int j, int k) +{ + int dim[3]; + + dim[0] = i; + dim[1] = j; + dim[2] = k; + + this->SetSampleDimensions(dim); +} + +void vtkGaussianSplatter::SetSampleDimensions(int dim[3]) +{ + int dataDim, i; + + vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," + << dim[1] << "," << dim[2] << ")"); + + if (dim[0] != this->SampleDimensions[0] || + dim[1] != this->SampleDimensions[1] || + dim[2] != this->SampleDimensions[2] ) + { + if ( dim[0]<1 || dim[1]<1 || dim[2]<1 ) + { + vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values"); + return; + } + + for (dataDim=0, i=0; i<3 ; i++) + { + if (dim[i] > 1) + { + dataDim++; + } + } + + if ( dataDim < 3 ) + { + vtkErrorMacro(<<"Sample dimensions must define a volume!"); + return; + } + + for ( i=0; i<3; i++) + { + this->SampleDimensions[i] = dim[i]; + } + + this->Modified(); + } +} + +void vtkGaussianSplatter::Cap(vtkDoubleArray *s) +{ + int i,j,k; + vtkIdType idx; + int d01=this->SampleDimensions[0]*this->SampleDimensions[1]; + + // i-j planes + //k = 0; + for (j=0; jSampleDimensions[1]; j++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetTuple(i+j*this->SampleDimensions[0], &this->CapValue); + } + } + k = this->SampleDimensions[2] - 1; + idx = k*d01; + for (j=0; jSampleDimensions[1]; j++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetTuple(idx+i+j*this->SampleDimensions[0], &this->CapValue); + } + } + // j-k planes + //i = 0; + for (k=0; kSampleDimensions[2]; k++) + { + for (j=0; jSampleDimensions[1]; j++) + { + s->SetTuple(j*this->SampleDimensions[0]+k*d01, &this->CapValue); + } + } + i = this->SampleDimensions[0] - 1; + for (k=0; kSampleDimensions[2]; k++) + { + for (j=0; jSampleDimensions[1]; j++) + { + s->SetTuple(i+j*this->SampleDimensions[0]+k*d01, &this->CapValue); + } + } + // i-k planes + //j = 0; + for (k=0; kSampleDimensions[2]; k++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetTuple(i+k*d01, &this->CapValue); + } + } + j = this->SampleDimensions[1] - 1; + idx = j*this->SampleDimensions[0]; + for (k=0; kSampleDimensions[2]; k++) + { + for (i=0; iSampleDimensions[0]; i++) + { + s->SetTuple(idx+i+k*d01, &this->CapValue); + } + } +} + +// +// Gaussian sampling +// +double vtkGaussianSplatter::Gaussian (double cx[3]) +{ + return ((cx[0]-P[0])*(cx[0]-P[0]) + (cx[1]-P[1])*(cx[1]-P[1]) + + (cx[2]-P[2])*(cx[2]-P[2]) ); +} + +// +// Ellipsoidal Gaussian sampling +// +double vtkGaussianSplatter::EccentricGaussian (double cx[3]) +{ + double v[3], r2, z2, rxy2, mag; + + v[0] = cx[0] - this->P[0]; + v[1] = cx[1] - this->P[1]; + v[2] = cx[2] - this->P[2]; + + r2 = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + + if ( (mag=this->N[0]*this->N[0]+ + this->N[1]*this->N[1]+ + this->N[2]*this->N[2]) != 1.0 ) + { + if ( mag == 0.0 ) + { + mag = 1.0; + } + else + { + mag = sqrt((double)mag); + } + } + + z2 = (v[0]*this->N[0] + v[1]*this->N[1] + v[2]*this->N[2])/mag; + z2 = z2*z2; + + rxy2 = r2 - z2; + + return (rxy2/this->Eccentricity2 + z2); +} + +void vtkGaussianSplatter::SetScalar(int idx, double dist2, + vtkDoubleArray *newScalars) +{ + double v = (this->*SampleFactor)(this->S) * exp((double) + (this->ExponentFactor*(dist2)/(this->Radius2))); + + if ( ! this->Visited[idx] ) + { + this->Visited[idx] = 1; + newScalars->SetTuple(idx,&v); + } + else + { + double s = newScalars->GetValue(idx); + switch (this->AccumulationMode) + { + case VTK_ACCUMULATION_MODE_MIN: + newScalars->SetTuple(idx,(s < v ? &s : &v)); + break; + case VTK_ACCUMULATION_MODE_MAX: + newScalars->SetTuple(idx,(s > v ? &s : &v)); + break; + case VTK_ACCUMULATION_MODE_SUM: + s += v; + newScalars->SetTuple(idx,&s); + break; + } + }//not first visit +} + +const char *vtkGaussianSplatter::GetAccumulationModeAsString() +{ + if ( this->AccumulationMode == VTK_ACCUMULATION_MODE_MIN ) + { + return "Minimum"; + } + else if ( this->AccumulationMode == VTK_ACCUMULATION_MODE_MAX ) + { + return "Maximum"; + } + else //if ( this->AccumulationMode == VTK_ACCUMULATION_MODE_SUM ) + { + return "Sum"; + } +} + +void vtkGaussianSplatter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Sample Dimensions: (" + << this->SampleDimensions[0] << ", " + << this->SampleDimensions[1] << ", " + << this->SampleDimensions[2] << ")\n"; + + os << indent << "Radius: " << this->Radius << "\n"; + os << indent << "Exponent Factor: " << this->ExponentFactor << "\n"; + + os << indent << "ModelBounds: \n"; + os << indent << " Xmin,Xmax: (" << this->ModelBounds[0] + << ", " << this->ModelBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->ModelBounds[2] + << ", " << this->ModelBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->ModelBounds[4] + << ", " << this->ModelBounds[5] << ")\n"; + + os << indent << "Normal Warping: " + << (this->NormalWarping ? "On\n" : "Off\n"); + os << indent << "Eccentricity: " << this->Eccentricity << "\n"; + + os << indent << "Scalar Warping: " + << (this->ScalarWarping ? "On\n" : "Off\n"); + os << indent << "Scale Factor: " << this->ScaleFactor << "\n"; + + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); + os << indent << "Cap Value: " << this->CapValue << "\n"; + + os << indent << "Accumulation Mode: " + << this->GetAccumulationModeAsString() << "\n"; + + os << indent << "Null Value: " << this->NullValue << "\n"; +} + +int vtkGaussianSplatter::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} diff --git a/Imaging/vtkGaussianSplatter.h b/Imaging/vtkGaussianSplatter.h new file mode 100644 index 0000000..810dd89 --- /dev/null +++ b/Imaging/vtkGaussianSplatter.h @@ -0,0 +1,244 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGaussianSplatter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGaussianSplatter - splat points into a volume with an elliptical, Gaussian distribution +// .SECTION Description +// vtkGaussianSplatter is a filter that injects input points into a +// structured points (volume) dataset. As each point is injected, it "splats" +// or distributes values to nearby voxels. Data is distributed using an +// elliptical, Gaussian distribution function. The distribution function is +// modified using scalar values (expands distribution) or normals +// (creates ellipsoidal distribution rather than spherical). +// +// In general, the Gaussian distribution function f(x) around a given +// splat point p is given by +// +// f(x) = ScaleFactor * exp( ExponentFactor*((r/Radius)**2) ) +// +// where x is the current voxel sample point; r is the distance |x-p| +// ExponentFactor <= 0.0, and ScaleFactor can be multiplied by the scalar +// value of the point p that is currently being splatted. +// +// If points normals are present (and NormalWarping is on), then the splat +// function becomes elliptical (as compared to the spherical one described +// by the previous equation). The Gaussian distribution function then +// becomes: +// +// f(x) = ScaleFactor * +// exp( ExponentFactor*( ((rxy/E)**2 + z**2)/R**2) ) +// +// where E is a user-defined eccentricity factor that controls the elliptical +// shape of the splat; z is the distance of the current voxel sample point +// along normal N; and rxy is the distance of x in the direction +// prependicular to N. +// +// This class is typically used to convert point-valued distributions into +// a volume representation. The volume is then usually iso-surfaced or +// volume rendered to generate a visualization. It can be used to create +// surfaces from point distributions, or to create structure (i.e., +// topology) when none exists. + +// .SECTION Caveats +// The input to this filter is any dataset type. This filter can be used +// to resample any form of data, i.e., the input data need not be +// unstructured. +// +// Some voxels may never receive a contribution during the splatting process. +// The final value of these points can be specified with the "NullValue" +// instance variable. + +// .SECTION See Also +// vtkShepardMethod + +#ifndef __vtkGaussianSplatter_h +#define __vtkGaussianSplatter_h + +#include "vtkImageAlgorithm.h" + +#define VTK_ACCUMULATION_MODE_MIN 0 +#define VTK_ACCUMULATION_MODE_MAX 1 +#define VTK_ACCUMULATION_MODE_SUM 2 + +class vtkDoubleArray; + +class VTK_IMAGING_EXPORT vtkGaussianSplatter : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkGaussianSplatter,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with dimensions=(50,50,50); automatic computation of + // bounds; a splat radius of 0.1; an exponent factor of -5; and normal and + // scalar warping turned on. + static vtkGaussianSplatter *New(); + + // Description: + // Set / get the dimensions of the sampling structured point set. Higher + // values produce better results but are much slower. + void SetSampleDimensions(int i, int j, int k); + void SetSampleDimensions(int dim[3]); + vtkGetVectorMacro(SampleDimensions,int,3); + + // Description: + // Set / get the (xmin,xmax, ymin,ymax, zmin,zmax) bounding box in which + // the sampling is performed. If any of the (min,max) bounds values are + // min >= max, then the bounds will be computed automatically from the input + // data. Otherwise, the user-specified bounds will be used. + vtkSetVector6Macro(ModelBounds,double); + vtkGetVectorMacro(ModelBounds,double,6); + + // Description: + // Set / get the radius of propagation of the splat. This value is expressed + // as a percentage of the length of the longest side of the sampling + // volume. Smaller numbers greatly reduce execution time. + vtkSetClampMacro(Radius,double,0.0,1.0); + vtkGetMacro(Radius,double); + + // Description: + // Multiply Gaussian splat distribution by this value. If ScalarWarping + // is on, then the Scalar value will be multiplied by the ScaleFactor + // times the Gaussian function. + vtkSetClampMacro(ScaleFactor,double,0.0,VTK_DOUBLE_MAX); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Set / get the sharpness of decay of the splats. This is the + // exponent constant in the Gaussian equation. Normally this is + // a negative value. + vtkSetMacro(ExponentFactor,double); + vtkGetMacro(ExponentFactor,double); + + // Description: + // Turn on/off the generation of elliptical splats. If normal warping is + // on, then the input normals affect the distribution of the splat. This + // boolean is used in combination with the Eccentricity ivar. + vtkSetMacro(NormalWarping,int); + vtkGetMacro(NormalWarping,int); + vtkBooleanMacro(NormalWarping,int); + + // Description: + // Control the shape of elliptical splatting. Eccentricity is the ratio + // of the major axis (aligned along normal) to the minor (axes) aligned + // along other two axes. So Eccentricity > 1 creates needles with the + // long axis in the direction of the normal; Eccentricity<1 creates + // pancakes perpendicular to the normal vector. + vtkSetClampMacro(Eccentricity,double,0.001,VTK_DOUBLE_MAX); + vtkGetMacro(Eccentricity,double); + + // Description: + // Turn on/off the scaling of splats by scalar value. + vtkSetMacro(ScalarWarping,int); + vtkGetMacro(ScalarWarping,int); + vtkBooleanMacro(ScalarWarping,int); + + // Description: + // Turn on/off the capping of the outer boundary of the volume + // to a specified cap value. This can be used to close surfaces + // (after iso-surfacing) and create other effects. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + + // Description: + // Specify the cap value to use. (This instance variable only has effect + // if the ivar Capping is on.) + vtkSetMacro(CapValue,double); + vtkGetMacro(CapValue,double); + + // Description: + // Specify the scalar accumulation mode. This mode expresses how scalar + // values are combined when splats are overlapped. The Max mode acts + // like a set union operation and is the most commonly used; the Min + // mode acts like a set intersection, and the sum is just weird. + vtkSetClampMacro(AccumulationMode,int, + VTK_ACCUMULATION_MODE_MIN,VTK_ACCUMULATION_MODE_SUM); + vtkGetMacro(AccumulationMode,int); + void SetAccumulationModeToMin() + {this->SetAccumulationMode(VTK_ACCUMULATION_MODE_MIN);} + void SetAccumulationModeToMax() + {this->SetAccumulationMode(VTK_ACCUMULATION_MODE_MAX);} + void SetAccumulationModeToSum() + {this->SetAccumulationMode(VTK_ACCUMULATION_MODE_SUM);} + const char *GetAccumulationModeAsString(); + + // Description: + // Set the Null value for output points not receiving a contribution from the + // input points. (This is the initial value of the voxel samples.) + vtkSetMacro(NullValue,double); + vtkGetMacro(NullValue,double); + + // Description: + // Compute the size of the sample bounding box automatically from the + // input data. This is an internal helper function. + void ComputeModelBounds(vtkDataSet *input, vtkImageData *output, + vtkInformation *outInfo); + +protected: + vtkGaussianSplatter(); + ~vtkGaussianSplatter() {}; + + virtual int FillInputPortInformation(int port, vtkInformation* info); + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + void Cap(vtkDoubleArray *s); + + int SampleDimensions[3]; // dimensions of volume to splat into + double Radius; // maximum distance splat propagates (as fraction 0->1) + double ExponentFactor; // scale exponent of gaussian function + double ModelBounds[6]; // bounding box of splatting dimensions + int NormalWarping; // on/off warping of splat via normal + double Eccentricity;// elliptic distortion due to normals + int ScalarWarping; // on/off warping of splat via scalar + double ScaleFactor; // splat size influenced by scale factor + int Capping; // Cap side of volume to close surfaces + double CapValue; // value to use for capping + int AccumulationMode; // how to combine scalar values + + double Gaussian(double x[3]); + double EccentricGaussian(double x[3]); + double ScalarSampling(double s) + {return this->ScaleFactor * s;} + double PositionSampling(double) + {return this->ScaleFactor;} + void SetScalar(int idx, double dist2, vtkDoubleArray *newScalars); + +//BTX +private: + double Radius2; + double (vtkGaussianSplatter::*Sample)(double x[3]); + double (vtkGaussianSplatter::*SampleFactor)(double s); + char *Visited; + double Eccentricity2; + double *P; + double *N; + double S; + double Origin[3]; + double Spacing[3]; + double SplatDistance[3]; + double NullValue; +//ETX + +private: + vtkGaussianSplatter(const vtkGaussianSplatter&); // Not implemented. + void operator=(const vtkGaussianSplatter&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkImageAccumulate.cxx b/Imaging/vtkImageAccumulate.cxx new file mode 100644 index 0000000..6313de3 --- /dev/null +++ b/Imaging/vtkImageAccumulate.cxx @@ -0,0 +1,457 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAccumulate.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageAccumulate.h" + +#include "vtkImageData.h" +#include "vtkImageStencilData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageAccumulate, "$Revision: 1.64 $"); +vtkStandardNewMacro(vtkImageAccumulate); + +//---------------------------------------------------------------------------- +// Constructor sets default values +vtkImageAccumulate::vtkImageAccumulate() +{ + int idx; + + for (idx = 0; idx < 3; ++idx) + { + this->ComponentSpacing[idx] = 1.0; + this->ComponentOrigin[idx] = 0.0; + this->ComponentExtent[idx*2] = 0; + this->ComponentExtent[idx*2+1] = 0; + } + this->ComponentExtent[1] = 255; + + this->ReverseStencil = 0; + + this->Min[0] = this->Min[1] = this->Min[2] = 0.0; + this->Max[0] = this->Max[1] = this->Max[2] = 0.0; + this->Mean[0] = this->Mean[1] = this->Mean[2] = 0.0; + this->StandardDeviation[0] = this->StandardDeviation[1] = this->StandardDeviation[2] = 0.0; + this->VoxelCount = 0; + + // we have the image input and the optional stencil input + this->SetNumberOfInputPorts(2); +} + + +//---------------------------------------------------------------------------- +vtkImageAccumulate::~vtkImageAccumulate() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageAccumulate::SetComponentExtent(int extent[6]) +{ + int idx, modified = 0; + + for (idx = 0; idx < 6; ++idx) + { + if (this->ComponentExtent[idx] != extent[idx]) + { + this->ComponentExtent[idx] = extent[idx]; + this->Modified(); + } + } + if (modified) + { + this->Modified(); + } +} + + +//---------------------------------------------------------------------------- +void vtkImageAccumulate::SetComponentExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetComponentExtent(extent); +} + + +//---------------------------------------------------------------------------- +void vtkImageAccumulate::GetComponentExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + extent[idx] = this->ComponentExtent[idx]; + } +} + + +//---------------------------------------------------------------------------- +void vtkImageAccumulate::SetStencil(vtkImageStencilData *stencil) +{ + this->SetInput(1, stencil); +} + + +//---------------------------------------------------------------------------- +vtkImageStencilData *vtkImageAccumulate::GetStencil() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return 0; + } + return vtkImageStencilData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageAccumulateExecute(vtkImageAccumulate *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, int *outPtr, + double Min[3], double Max[3], + double Mean[3], + double StandardDeviation[3], + long int *VoxelCount, + int* updateExtent) +{ + int idX, idY, idZ, idxC; + int iter, pmin0, pmax0, min0, max0, min1, max1, min2, max2; + vtkIdType inInc0, inInc1, inInc2; + T *tempPtr; + int *outPtrC; + int numC, outIdx, *outExtent; + vtkIdType *outIncs; + double *origin, *spacing; + unsigned long count = 0; + unsigned long target; + double sumSqr[3], variance; + + // variables used to compute statistics (filter handles max 3 components) + double sum[3]; + sum[0] = sum[1] = sum[2] = 0.0; + Min[0] = Min[1] = Min[2] = VTK_DOUBLE_MAX; + Max[0] = Max[1] = Max[2] = VTK_DOUBLE_MIN; + sumSqr[0] = sumSqr[1] = sumSqr[2] = 0.0; + StandardDeviation[0] = StandardDeviation[1] = StandardDeviation[2] = 0.0; + *VoxelCount = 0; + + vtkImageStencilData *stencil = self->GetStencil(); + + // Zero count in every bin + outData->GetExtent(min0, max0, min1, max1, min2, max2); + memset((void *)outPtr, 0, + (max0-min0+1)*(max1-min1+1)*(max2-min2+1)*sizeof(int)); + + // Get information to march through data + numC = inData->GetNumberOfScalarComponents(); + min0 = updateExtent[0]; + max0 = updateExtent[1]; + min1 = updateExtent[2]; + max1 = updateExtent[3]; + min2 = updateExtent[4]; + max2 = updateExtent[5]; + inData->GetIncrements(inInc0, inInc1, inInc2); + outExtent = outData->GetExtent(); + outIncs = outData->GetIncrements(); + origin = outData->GetOrigin(); + spacing = outData->GetSpacing(); + + target = (unsigned long)((max2 - min2 + 1)*(max1 - min1 +1)/50.0); + target++; + + int reverse = self->GetReverseStencil(); + + // Loop through input pixels + for (idZ = min2; idZ <= max2; idZ++) + { + for (idY = min1; idY <= max1; idY++) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + + // loop over stencil sub-extents, -1 flags + // that we want the complementary extents + iter = reverse ? -1 : 0; + + pmin0 = min0; + pmax0 = max0; + while ((stencil != 0 && + stencil->GetNextExtent(pmin0,pmax0,min0,max0,idY,idZ,iter)) || + (stencil == 0 && iter++ == 0)) + { + // set up pointer for sub extent + tempPtr = inPtr + (inInc2*(idZ - min2) + + inInc1*(idY - min1) + + numC*(pmin0 - min0)); + + // accumulate over the sub extent + for (idX = pmin0; idX <= pmax0; idX++) + { + // find the bin for this pixel. + outPtrC = outPtr; + for (idxC = 0; idxC < numC; ++idxC) + { + // Gather statistics + sum[idxC]+= *tempPtr; + sumSqr[idxC]+= (*tempPtr * *tempPtr); + if (*tempPtr > Max[idxC]) + { + Max[idxC] = *tempPtr; + } + else if (*tempPtr < Min[idxC]) + { + Min[idxC] = *tempPtr; + } + (*VoxelCount)++; + // compute the index + outIdx = (int) floor((((double)*tempPtr++ - origin[idxC]) + / spacing[idxC])); + if (outIdx < outExtent[idxC*2] || outIdx > outExtent[idxC*2+1]) + { + // Out of bin range + outPtrC = NULL; + break; + } + outPtrC += (outIdx - outExtent[idxC*2]) * outIncs[idxC]; + } + if (outPtrC) + { + ++(*outPtrC); + } + } + } + } + } + + if (*VoxelCount) // avoid the div0 + { + Mean[0] = sum[0] / (double)*VoxelCount; + Mean[1] = sum[1] / (double)*VoxelCount; + Mean[2] = sum[2] / (double)*VoxelCount; + + variance = sumSqr[0] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[0] * Mean[0] / (double) (*VoxelCount - 1)); + StandardDeviation[0] = sqrt(variance); + variance = sumSqr[1] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[1] * Mean[1] / (double) (*VoxelCount - 1)); + StandardDeviation[1] = sqrt(variance); + variance = sumSqr[2] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[2] * Mean[2] / (double) (*VoxelCount - 1)); + StandardDeviation[2] = sqrt(variance); + } + else + { + Mean[0] = Mean[1] = Mean[2] = 0.0; + StandardDeviation[0] = StandardDeviation[1] = StandardDeviation[2] = 0.0; + } + +} + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output Data, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the Datas data types. +int vtkImageAccumulate::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + void *inPtr; + void *outPtr; + + // get the input + vtkInformation* in1Info = inputVector[0]->GetInformationObject(0); + vtkImageData *inData = vtkImageData::SafeDownCast( + in1Info->Get(vtkDataObject::DATA_OBJECT())); + int *uExt = in1Info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + // get the output + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDebugMacro(<<"Executing image accumulate"); + + // We need to allocate our own scalars since we are overriding + // the superclasses "Execute()" method. + outData->SetExtent(outData->GetWholeExtent()); + outData->AllocateScalars(); + + vtkDataArray *inArray = this->GetInputArrayToProcess(0,inputVector); + inPtr = inData->GetArrayPointerForExtent(inArray, uExt); + outPtr = outData->GetScalarPointer(); + + // Components turned into x, y and z + if (inData->GetNumberOfScalarComponents() > 3) + { + vtkErrorMacro("This filter can handle upto 3 components"); + return 1; + } + + // this filter expects that output is type int. + if (outData->GetScalarType() != VTK_INT) + { + vtkErrorMacro(<< "Execute: out ScalarType " << outData->GetScalarType() + << " must be int\n"); + return 1; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro(vtkImageAccumulateExecute( this, + inData, (VTK_TT *)(inPtr), + outData, (int *)(outPtr), + this->Min, this->Max, + this->Mean, + this->StandardDeviation, + &this->VoxelCount, + uExt )); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 1; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkImageAccumulate::RequestInformation ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation* inInfo2 = inputVector[1]->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->ComponentExtent,6); + outInfo->Set(vtkDataObject::ORIGIN(),this->ComponentOrigin,3); + outInfo->Set(vtkDataObject::SPACING(),this->ComponentSpacing,3); + + // need to set the spacing and origin of the stencil to match the output + if (inInfo2) + { + inInfo2->Set(vtkDataObject::SPACING(), + inInfo->Get(vtkDataObject::SPACING()),3); + inInfo2->Set(vtkDataObject::ORIGIN(), + inInfo->Get(vtkDataObject::ORIGIN()),3); + } + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_INT, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// Get ALL of the input. +int vtkImageAccumulate::RequestUpdateExtent ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* vtkNotUsed( outputVector )) +{ + // get the info objects + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation* stencilInfo = 0; + if(inputVector[1]->GetNumberOfInformationObjects() > 0) + { + stencilInfo = inputVector[1]->GetInformationObject(0); + } + + // Use the whole extent of the first input as the update extent for + // both inputs. This way the stencil will be the same size as the + // input. + int extent[6] = {0,-1,0,-1,0,-1}; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); + if(stencilInfo) + { + stencilInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + extent, 6); + } + return 1; +} + +int vtkImageAccumulate::FillInputPortInformation( + int port, vtkInformation* info) +{ + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageStencilData"); + // the stencil input is optional + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + else + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + } + return 1; +} + +void vtkImageAccumulate::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Mean: (" + << this->Mean[0] << ", " + << this->Mean[1] << ", " + << this->Mean[2] << ")\n"; + os << indent << "Min: (" + << this->Min[0] << ", " + << this->Min[1] << ", " + << this->Min[2] << ")\n"; + os << indent << "Max: (" + << this->Max[0] << ", " + << this->Max[1] << ", " + << this->Max[2] << ")\n"; + os << indent << "StandardDeviation: (" + << this->StandardDeviation[0] << ", " + << this->StandardDeviation[1] << ", " + << this->StandardDeviation[2] << ")\n"; + os << indent << "VoxelCount: " << this->VoxelCount << "\n"; + os << indent << "Stencil: " << this->GetStencil() << "\n"; + os << indent << "ReverseStencil: " << (this->ReverseStencil ? + "On\n" : "Off\n"); + + os << indent << "ComponentOrigin: ( " + << this->ComponentOrigin[0] << ", " + << this->ComponentOrigin[1] << ", " + << this->ComponentOrigin[2] << " )\n"; + + os << indent << "ComponentSpacing: ( " + << this->ComponentSpacing[0] << ", " + << this->ComponentSpacing[1] << ", " + << this->ComponentSpacing[2] << " )\n"; + + os << indent << "ComponentExtent: ( " + << this->ComponentExtent[0] << "," << this->ComponentExtent[1] << " " + << this->ComponentExtent[2] << "," << this->ComponentExtent[3] << " " + << this->ComponentExtent[4] << "," << this->ComponentExtent[5] << " }\n"; +} + diff --git a/Imaging/vtkImageAccumulate.h b/Imaging/vtkImageAccumulate.h new file mode 100644 index 0000000..b2c532a --- /dev/null +++ b/Imaging/vtkImageAccumulate.h @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAccumulate.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageAccumulate - Generalized histograms up to 4 dimensions. +// .SECTION Description +// vtkImageAccumulate - This filter divides component space into +// discrete bins. It then counts the number of pixels associated +// with each bin. The output is this "scatter plot" (histogram values for 1D). +// The dimensionality of the output depends on how many components the +// input pixels have. Input pixels with one component generate a 1D histogram. +// This filter can only handle images with 1 to 3 scalar components. +// The input can be any type, but the output is always int. +// Some statistics are computed on the pixel values at the same time. +// The SetStencilFunction, SetClippingExtents and ReverseStencil +// functions allow the statistics to be computed on an arbitrary +// portion of the input data. +// See the documentation for vtkImageStencil for more information. + + +#ifndef __vtkImageAccumulate_h +#define __vtkImageAccumulate_h + + +#include "vtkImageAlgorithm.h" + +class vtkImageStencilData; + +class VTK_IMAGING_EXPORT vtkImageAccumulate : public vtkImageAlgorithm +{ +public: + static vtkImageAccumulate *New(); + vtkTypeRevisionMacro(vtkImageAccumulate,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get - The component spacing is the dimension of each bin. + // This ends up being the spacing of the output "image". + // If the number of input scalar components are less than three, + // then some of these spacing values are ignored. + // For a 1D histogram with 10 bins spanning the values 1000 to 2000, + // this spacing should be set to 100, 0, 0 + vtkSetVector3Macro(ComponentSpacing, double); + vtkGetVector3Macro(ComponentSpacing, double); + + // Description: + // Set/Get - The component origin is the location of bin (0, 0, 0). + // Note that if the Component extent does not include the value (0,0,0), + // then this origin bin will not actually be in the output. + // The origin of the output ends up being the same as the componenet origin. + // For a 1D histogram with 10 bins spanning the values 1000 to 2000, + // this origin should be set to 1000, 0, 0 + vtkSetVector3Macro(ComponentOrigin, double); + vtkGetVector3Macro(ComponentOrigin, double); + + // Description: + // Set/Get - The component extent sets the number/extent of the bins. + // For a 1D histogram with 10 bins spanning the values 1000 to 2000, + // this extent should be set to 0, 9, 0, 0, 0, 0. + // The extent specifies inclusive min/max values. + // This implies the the top extent should be set to the number of bins - 1. + void SetComponentExtent(int extent[6]); + void SetComponentExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + void GetComponentExtent(int extent[6]); + int *GetComponentExtent() {return this->ComponentExtent;} + + + // Description: + // Use a stencil to specify which voxels to accumulate. + void SetStencil(vtkImageStencilData *stencil); + vtkImageStencilData *GetStencil(); + + // Description: + // Reverse the stencil. + vtkSetMacro(ReverseStencil, int); + vtkBooleanMacro(ReverseStencil, int); + vtkGetMacro(ReverseStencil, int); + + // Description: + // Get the statistics information for the data. + vtkGetVector3Macro(Min, double); + vtkGetVector3Macro(Max, double); + vtkGetVector3Macro(Mean, double); + vtkGetVector3Macro(StandardDeviation, double); + vtkGetMacro(VoxelCount, long int); + + +protected: + vtkImageAccumulate(); + ~vtkImageAccumulate(); + + double ComponentSpacing[3]; + double ComponentOrigin[3]; + int ComponentExtent[6]; + + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + double Min[3]; + double Max[3]; + double Mean[3]; + double StandardDeviation[3]; + long int VoxelCount; + + int ReverseStencil; + + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkImageAccumulate(const vtkImageAccumulate&); // Not implemented. + void operator=(const vtkImageAccumulate&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageAnisotropicDiffusion2D.cxx b/Imaging/vtkImageAnisotropicDiffusion2D.cxx new file mode 100644 index 0000000..7e1fcbc --- /dev/null +++ b/Imaging/vtkImageAnisotropicDiffusion2D.cxx @@ -0,0 +1,390 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAnisotropicDiffusion2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageAnisotropicDiffusion2D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageAnisotropicDiffusion2D, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkImageAnisotropicDiffusion2D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageAnisotropicDiffusion2D fitler. +vtkImageAnisotropicDiffusion2D::vtkImageAnisotropicDiffusion2D() +{ + this->HandleBoundaries = 1; + this->NumberOfIterations = 0; + this->SetNumberOfIterations(4); + this->DiffusionThreshold = 5.0; + this->DiffusionFactor = 1; + this->Faces = 0; + this->FacesOn(); + this->Edges = 0; + this->EdgesOn(); + this->Corners = 0; + this->CornersOn(); + this->GradientMagnitudeThreshold = 1; + this->GradientMagnitudeThresholdOff(); +} + +//---------------------------------------------------------------------------- +void +vtkImageAnisotropicDiffusion2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "NumberOfIterations: " << this->NumberOfIterations << "\n"; + os << indent << "DiffusionThreshold: " << this->DiffusionThreshold << "\n"; + os << indent << "DiffusionFactor: " << this->DiffusionFactor << "\n"; + + os << indent << "Faces: " << this->Faces << "\n"; + + if (this->Edges) + { + os << indent << "Edges: On\n"; + } + else + { + os << indent << "Edges: Off\n"; + } + + if (this->Corners) + { + os << indent << "Corners: On\n"; + } + else + { + os << indent << "Corners: Off\n"; + } + + if (this->GradientMagnitudeThreshold) + { + os << indent << "GradientMagnitudeThreshold: On\n"; + } + else + { + os << indent << "GradientMagnitudeThreshold: Off\n"; + } +} + +//---------------------------------------------------------------------------- +// This method sets the number of inputs which also affects the +// input neighborhood needed to compute one output pixel. +void vtkImageAnisotropicDiffusion2D::SetNumberOfIterations(int num) +{ + int temp; + + vtkDebugMacro(<< "SetNumberOfIterations: " << num); + if (this->NumberOfIterations == num) + { + return; + } + + this->Modified(); + temp = num*2 + 1; + this->KernelSize[0] = temp; + this->KernelSize[1] = temp; + this->KernelMiddle[0] = num; + this->KernelMiddle[1] = num; + + this->NumberOfIterations = num; +} + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The input and output datas +// must have the same data type. +void vtkImageAnisotropicDiffusion2D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6], wholeExt[6]; + double *ar; + int idx; + vtkImageData *temp; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt,outExt,wholeExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro("Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + ar = inData[0][0]->GetSpacing(); + + // make the temporary regions to iterate over. + vtkImageData *in = vtkImageData::New(); + in->SetExtent(inExt); + in->SetNumberOfScalarComponents(inData[0][0]->GetNumberOfScalarComponents()); + in->SetScalarType(VTK_DOUBLE); + in->CopyAndCastFrom(inData[0][0],inExt); + + vtkImageData *out = vtkImageData::New(); + out->SetExtent(inExt); + out->SetNumberOfScalarComponents( + inData[0][0]->GetNumberOfScalarComponents()); + out->SetScalarType(VTK_DOUBLE); + out->AllocateScalars(); + + // Loop performing the diffusion + // Note: region extent could get smaller as the diffusion progresses + // (but never get smaller than output region). + for (idx = this->NumberOfIterations - 1; + !this->AbortExecute && idx >= 0; --idx) + { + if (!id) + { + this->UpdateProgress((double)(this->NumberOfIterations - idx) + /this->NumberOfIterations); + } + this->Iterate(in, out, ar[0], ar[1], outExt, idx); + temp = in; + in = out; + out = temp; + } + + // copy results into output. + outData[0]->CopyAndCastFrom(in,outExt); + in->Delete(); + out->Delete(); +} + +//---------------------------------------------------------------------------- +// This method performs one pass of the diffusion filter. +// The inData and outData are assumed to have data type double, +// and have the same extent. +void vtkImageAnisotropicDiffusion2D::Iterate(vtkImageData *inData, + vtkImageData *outData, + double ar0, double ar1, + int *coreExtent, int count) +{ + int idx0, idx1, idx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + int inMin0, inMax0, inMin1, inMax1, inMin2, inMax2; + int min0, max0, min1, max1, min2, max2; + double *inPtr0, *inPtr1, *inPtr2; + double *outPtr0, *outPtr1, *outPtr2; + double th0, th1, th01; + double df0, df1, df01; + double temp, sum; + int idxC, maxC; + + maxC = inData->GetNumberOfScalarComponents(); + inData->GetExtent(inMin0, inMax0, inMin1, inMax1, inMin2, inMax2); + inData->GetIncrements(inInc0, inInc1, inInc2); + outData->GetIncrements(outInc0, outInc1, outInc2); + + // Avoid warnings. + th0 = th1 = th01 = df0 = df1 = df01 = 0.0; + + // Compute direction specific diffusion thresholds and factors. + sum = 0.0; + if (this->Edges) + { + th0 = ar0 * this->DiffusionThreshold; + df0 = 1.0 / ar0; + th1 = ar1 * this->DiffusionThreshold; + df1 = 1.0 / ar1; + // two edges per direction. + sum += 2.0 * (df0 + df1); + } + if (this->Corners) + { + temp = sqrt(ar0*ar0 + ar1*ar1); + th01 = temp * this->DiffusionThreshold; + df01 = 1 / temp; + // four corners per plane + sum += 4 * (df01); + } + + if (sum > 0.0) + { + temp = this->DiffusionFactor / sum; + df0 *= temp; + df1 *= temp; + df01 *= temp; + } + else + { + vtkWarningMacro(<< "Iterate: NO NEIGHBORS"); + return; + } + + // Compute the shrinking extent to loop over. + min0 = coreExtent[0] - count; + max0 = coreExtent[1] + count; + min1 = coreExtent[2] - count; + max1 = coreExtent[3] + count; + // intersection + min0 = (min0 > inMin0) ? min0 : inMin0; + max0 = (max0 < inMax0) ? max0 : inMax0; + min1 = (min1 > inMin1) ? min1 : inMin1; + max1 = (max1 < inMax1) ? max1 : inMax1; + + vtkDebugMacro(<< "Iteration count: " << count << " (" + << min0 << ", " << max0 << ", " << min1 << ", " << max1 << ")"); + + // I apologize for explicitely diffusing each neighbor, but it is the easiest + // way to deal with the boundary conditions. Besides it is fast. + // (Are you sure every one is correct?!!!) + min2 = inMin2; + max2 = inMax2; + + for (idxC = 0; idxC < maxC; idxC++) + { + inPtr2 = (double *)(inData->GetScalarPointer(min0, min1, min2)); + outPtr2 = (double *)(outData->GetScalarPointer(min0, min1, min2)); + inPtr2 += idxC; + outPtr2 += idxC; + + for (idx2 = min2; idx2 <= max2; ++idx2, inPtr2+=inInc2, outPtr2+=outInc2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = min1; idx1 <= max1; ++idx1, inPtr1+=inInc1, outPtr1+=outInc1) + { + inPtr0 = inPtr1; + outPtr0 = outPtr1; + for (idx0 = min0; idx0 <= max0; ++idx0, inPtr0+=inInc0, outPtr0+=outInc0) + { + // Copy center + *outPtr0 = *inPtr0; + + // Special case for gradient magnitude threhsold + if (this->GradientMagnitudeThreshold) + { + double d0, d1; + // compute the gradient magnitude (central differences). + d0 = (idx0 != inMax0) ? inPtr0[inInc0] : *inPtr0; + d0 -= (idx0 != inMin0) ? inPtr0[-inInc0] : *inPtr0; + d0 /= ar0; + d1 = (idx1 != inMax1) ? inPtr0[inInc1] : *inPtr0; + d1 -= (idx1 != inMin1) ? inPtr0[-inInc1] : *inPtr0; + d1 /= ar1; + // If magnitude is big, don't diffuse. + d0 = sqrt(d0*d0 + d1*d1); + if (d0 > this->DiffusionThreshold) + { + // hack to not diffuse + th0 = th1 = th01 = 0.0; + } + else + { + // hack to diffuse + th0 = th1 = th01 = VTK_DOUBLE_MAX; + } + } + + // Start diffusing + if (this->Edges) + { + // left + if (idx0 != inMin0) + { + temp = inPtr0[-inInc0] - *inPtr0; + if (fabs(temp) < th0) + { + *outPtr0 += temp * df0; + } + } + // right + if (idx0 != inMax0) + { + temp = inPtr0[inInc0] - *inPtr0; + if (fabs(temp) < th0) + { + *outPtr0 += temp * df0; + } + } + // up + if (idx1 != inMin1) + { + temp = inPtr0[-inInc1] - *inPtr0; + if (fabs(temp) < th1) + { + *outPtr0 += temp * df1; + } + } + // down + if (idx1 != inMax1) + { + temp = inPtr0[inInc1] - *inPtr0; + if (fabs(temp) < th1) + { + *outPtr0 += temp * df1; + } + } + } + + if (this->Corners) + { + // left up + if (idx0 != inMin0 && idx1 != inMin1) + { + temp = inPtr0[-inInc0-inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + // right up + if (idx0 != inMax0 && idx1 != inMin1) + { + temp = inPtr0[inInc0-inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + // left down + if (idx0 != inMin0 && idx1 != inMax1) + { + temp = inPtr0[-inInc0+inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + // right down + if (idx0 != inMax0 && idx1 != inMax1) + { + temp = inPtr0[inInc0+inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + } + } + } + } + } +} diff --git a/Imaging/vtkImageAnisotropicDiffusion2D.h b/Imaging/vtkImageAnisotropicDiffusion2D.h new file mode 100644 index 0000000..97624a2 --- /dev/null +++ b/Imaging/vtkImageAnisotropicDiffusion2D.h @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAnisotropicDiffusion2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageAnisotropicDiffusion2D - edge preserving smoothing. +// +// .SECTION Description +// vtkImageAnisotropicDiffusion2D diffuses a 2d image iteratively. +// The neighborhood of the diffusion is determined by the instance +// flags. If "Edges" is on the 4 edge connected voxels +// are included, and if "Corners" is on, the 4 corner connected voxels +// are included. "DiffusionFactor" determines how far a pixel value +// moves toward its neighbors, and is insensitive to the number of +// neighbors chosen. The diffusion is anisotropic because it only occurs +// when a gradient measure is below "GradientThreshold". Two gradient measures +// exist and are toggled by the "GradientMagnitudeThreshold" flag. +// When "GradientMagnitudeThreshold" is on, the magnitude of the gradient, +// computed by central differences, above "DiffusionThreshold" +// a voxel is not modified. The alternative measure examines each +// neighbor independently. The gradient between the voxel and the neighbor +// must be below the "DiffusionThreshold" for diffusion to occur with +// THAT neighbor. + +// .SECTION See Also +// vtkImageAnisotropicDiffusion3D + +#ifndef __vtkImageAnisotropicDiffusion2D_h +#define __vtkImageAnisotropicDiffusion2D_h + + +#include "vtkImageSpatialAlgorithm.h" +class VTK_IMAGING_EXPORT vtkImageAnisotropicDiffusion2D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageAnisotropicDiffusion2D *New(); + vtkTypeRevisionMacro(vtkImageAnisotropicDiffusion2D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sets the number of interations which also affects the + // input neighborhood needed to compute one output pixel. Each iterations + // requires an extra pixel layer on the neighborhood. This is only relavent + // when you are trying to stream or are requesting a sub extent of the "wholeExtent". + void SetNumberOfIterations(int num); + + // Description: + // Get the number of iterations. + vtkGetMacro(NumberOfIterations,int); + + // Description: + // Set/Get the difference threshold that stops diffusion. + // when the difference between two pixel is greater than this threshold, + // the pixels are not diffused. This causes diffusion to avoid sharp edges. + // If the GradientMagnitudeThreshold is set, then gradient magnitude is used + // for comparison instead of pixel differences. + vtkSetMacro(DiffusionThreshold,double); + vtkGetMacro(DiffusionThreshold,double); + + // Description: + // The diffusion factor specifies how much neighboring pixels effect each other. + // No diffusion occurs with a factor of 0, and a diffusion factor of 1 causes + // the pixel to become the average of all its neighbors. + vtkSetMacro(DiffusionFactor,double); + vtkGetMacro(DiffusionFactor,double); + + // Description: + // Choose neighbors to diffuse (6 faces, 12 edges, 8 corners). + vtkSetMacro(Faces,int); + vtkGetMacro(Faces,int); + vtkBooleanMacro(Faces,int); + vtkSetMacro(Edges,int); + vtkGetMacro(Edges,int); + vtkBooleanMacro(Edges,int); + vtkSetMacro(Corners,int); + vtkGetMacro(Corners,int); + vtkBooleanMacro(Corners,int); + + // Description: + // Switch between gradient magnitude threshold and pixel gradient threshold. + vtkSetMacro(GradientMagnitudeThreshold,int); + vtkGetMacro(GradientMagnitudeThreshold,int); + vtkBooleanMacro(GradientMagnitudeThreshold,int); + +protected: + vtkImageAnisotropicDiffusion2D(); + ~vtkImageAnisotropicDiffusion2D() {}; + + int NumberOfIterations; + double DiffusionThreshold; + double DiffusionFactor; + // to determine which neighbors to diffuse + int Faces; + int Edges; + int Corners; + // What threshold to use + int GradientMagnitudeThreshold; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + void Iterate(vtkImageData *in, vtkImageData *out, + double ar0, double ar1, int *coreExtent, int count); +private: + vtkImageAnisotropicDiffusion2D(const vtkImageAnisotropicDiffusion2D&); // Not implemented. + void operator=(const vtkImageAnisotropicDiffusion2D&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageAnisotropicDiffusion3D.cxx b/Imaging/vtkImageAnisotropicDiffusion3D.cxx new file mode 100644 index 0000000..cb3eff8 --- /dev/null +++ b/Imaging/vtkImageAnisotropicDiffusion3D.cxx @@ -0,0 +1,594 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAnisotropicDiffusion3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageAnisotropicDiffusion3D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageAnisotropicDiffusion3D, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkImageAnisotropicDiffusion3D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageAnisotropicDiffusion3D fitler. +vtkImageAnisotropicDiffusion3D::vtkImageAnisotropicDiffusion3D() +{ + this->HandleBoundaries = 1; + this->NumberOfIterations = 0; + this->SetNumberOfIterations(4); + this->DiffusionThreshold = 5.0; + this->DiffusionFactor = 1; + this->Faces = 0; + this->FacesOn(); + this->Edges = 0; + this->EdgesOn(); + this->Corners = 0; + this->CornersOn(); + this->GradientMagnitudeThreshold = 1; + this->GradientMagnitudeThresholdOff(); +} + +//---------------------------------------------------------------------------- +void +vtkImageAnisotropicDiffusion3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "NumberOfIterations: " << this->NumberOfIterations << "\n"; + os << indent << "DiffusionThreshold: " << this->DiffusionThreshold << "\n"; + os << indent << "DiffusionFactor: " << this->DiffusionFactor << "\n"; + + if (this->Faces) + { + os << indent << "Faces: On\n"; + } + else + { + os << indent << "Faces: Off\n"; + } + + if (this->Edges) + { + os << indent << "Edges: On\n"; + } + else + { + os << indent << "Edges: Off\n"; + } + + if (this->Corners) + { + os << indent << "Corners: On\n"; + } + else + { + os << indent << "Corners: Off\n"; + } + + if (this->GradientMagnitudeThreshold) + { + os << indent << "GradientMagnitudeThreshold: On\n"; + } + else + { + os << indent << "GradientMagnitudeThreshold: Off\n"; + } +} + +//---------------------------------------------------------------------------- +// This method sets the number of inputs which also affects the +// input neighborhood needed to compute one output pixel. +void vtkImageAnisotropicDiffusion3D::SetNumberOfIterations(int num) +{ + int temp; + + vtkDebugMacro(<< "SetNumberOfIterations: " << num); + + if (this->NumberOfIterations == num) + { + return; + } + + this->Modified(); + temp = num*2 + 1; + this->KernelSize[0] = temp; + this->KernelSize[1] = temp; + this->KernelSize[2] = temp; + this->KernelMiddle[0] = num; + this->KernelMiddle[1] = num; + this->KernelMiddle[2] = num; + + this->NumberOfIterations = num; +} + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input region type. The input and output regions +// must have the same data type. +void vtkImageAnisotropicDiffusion3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6], wholeExt[6]; + double *ar; + int idx; + vtkImageData *temp; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt,outExt,wholeExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro("Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + ar = inData[0][0]->GetSpacing(); + + // make the temporary regions to iterate over. + vtkImageData *in = vtkImageData::New(); + in->SetExtent(inExt); + in->SetNumberOfScalarComponents(inData[0][0]->GetNumberOfScalarComponents()); + in->SetScalarType(VTK_DOUBLE); + in->CopyAndCastFrom(inData[0][0],inExt); + + vtkImageData *out = vtkImageData::New(); + out->SetExtent(inExt); + out->SetNumberOfScalarComponents( + inData[0][0]->GetNumberOfScalarComponents()); + out->SetScalarType(VTK_DOUBLE); + out->AllocateScalars(); + + // Loop performing the diffusion + // Note: region extent could get smaller as the diffusion progresses + // (but never get smaller than output region). + for (idx = this->NumberOfIterations - 1; + !this->AbortExecute && idx >= 0; --idx) + { + if (!id) + { + this->UpdateProgress((double)(this->NumberOfIterations - idx) + /this->NumberOfIterations); + } + this->Iterate(in, out, ar[0], ar[1], ar[2], outExt, idx); + temp = in; + in = out; + out = temp; + } + + // copy results into output. + outData[0]->CopyAndCastFrom(in,outExt); + in->Delete(); + out->Delete(); +} + +//---------------------------------------------------------------------------- +// This method performs one pass of the diffusion filter. +// The inData and outData are assumed to have data type double, +// and have the same extent. +void vtkImageAnisotropicDiffusion3D::Iterate(vtkImageData *inData, + vtkImageData *outData, + double ar0, double ar1, double ar2, + int *coreExtent, int count) +{ + int idx0, idx1, idx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + int inMin0, inMax0, inMin1, inMax1, inMin2, inMax2; + int min0, max0, min1, max1, min2, max2; + double *inPtr0, *inPtr1, *inPtr2; + double *outPtr0, *outPtr1, *outPtr2; + double th0, th1, th2, th01, th02, th12, th012; + double df0, df1, df2, df01, df02, df12, df012; + double temp, sum; + int idxC, maxC; + + inData->GetExtent(inMin0, inMax0, inMin1, inMax1, inMin2, inMax2); + inData->GetIncrements(inInc0, inInc1, inInc2); + outData->GetIncrements(outInc0, outInc1, outInc2); + maxC = inData->GetNumberOfScalarComponents(); + + // Avoid the warnings. + th0 = th1 = th2 = th01 = th02 = th12 = th012 = + df0 = df1 = df2 = df01 = df02 = df12 = df012 = 0.0; + + // Compute direction specific diffusion thresholds and factors. + sum = 0.0; + if (this->Faces) + { + th0 = ar0 * this->DiffusionThreshold; + df0 = 1.0 / ar0; + th1 = ar1 * this->DiffusionThreshold; + df1 = 1.0 / ar1; + th2 = ar2 * this->DiffusionThreshold; + df2 = 1.0 / ar2; + // two faces per direction. + sum += 2.0 * (df0 + df1 + df2); + } + if (this->Edges) + { + temp = sqrt(ar0*ar0 + ar1*ar1); + th01 = temp * this->DiffusionThreshold; + df01 = 1 / temp; + temp = sqrt(ar0*ar0 + ar2*ar2); + th02 = temp * this->DiffusionThreshold; + df02 = 1 / temp; + temp = sqrt(ar1*ar1 + ar2*ar2); + th12 = temp * this->DiffusionThreshold; + df12 = 1 / temp; + // four edges per plane + sum += 4 * (df01 + df02 + df12); + } + if (this->Corners) + { + temp = sqrt(ar0*ar0 + ar1*ar1 + ar2*ar2); + th012 = temp * this->DiffusionThreshold; + df012 = 1 / temp; + // eight corners in a cube + sum += 8 * df012; + } + if (sum > 0.0) + { + temp = this->DiffusionFactor / sum; + df0 *= temp; + df1 *= temp; + df2 *= temp; + df01 *= temp; + df02 *= temp; + df12 *= temp; + df012 *= temp; + } + else + { + vtkWarningMacro(<< "Iterate: NO NEIGHBORS"); + return; + } + + // Compute the shrinking extent to loop over. + min0 = coreExtent[0] - count; + max0 = coreExtent[1] + count; + min1 = coreExtent[2] - count; + max1 = coreExtent[3] + count; + min2 = coreExtent[4] - count; + max2 = coreExtent[5] + count; + // intersection + min0 = (min0 > inMin0) ? min0 : inMin0; + max0 = (max0 < inMax0) ? max0 : inMax0; + min1 = (min1 > inMin1) ? min1 : inMin1; + max1 = (max1 < inMax1) ? max1 : inMax1; + min2 = (min2 > inMin2) ? min2 : inMin2; + max2 = (max2 < inMax2) ? max2 : inMax2; + + vtkDebugMacro(<< "Iteration count: " << count << " (" + << min0 << ", " << max0 << ", " << min1 << ", " << max1 << ", " + << min2 << ", " << max2 << ")"); + + // I apologize for explicitely diffusing each neighbor, but it is the easiest + // way to deal with the boundary conditions. Besides it is fast. + // (Are you sure every one is correct?!!!) + + for (idxC = 0; idxC < maxC; idxC++) + { + inPtr2 = (double *)(inData->GetScalarPointer(min0, min1, min2)); + outPtr2 = (double *)(outData->GetScalarPointer(min0, min1, min2)); + inPtr2 += idxC; + outPtr2 += idxC; + + for (idx2 = min2; idx2 <= max2; ++idx2, inPtr2+=inInc2, outPtr2+=outInc2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = min1; idx1 <= max1; ++idx1, inPtr1+=inInc1, outPtr1+=outInc1) + { + inPtr0 = inPtr1; + outPtr0 = outPtr1; + for (idx0 = min0; idx0 <= max0; ++idx0, inPtr0+=inInc0, outPtr0+=outInc0) + { + // Copy center + *outPtr0 = *inPtr0; + + // Special case for gradient magnitude threhsold + if (this->GradientMagnitudeThreshold) + { + double d0, d1, d2; + // compute the gradient magnitude (central differences). + d0 = (idx0 != inMax0) ? inPtr0[inInc0] : *inPtr0; + d0 -= (idx0 != inMin0) ? inPtr0[-inInc0] : *inPtr0; + d0 /= ar0; + d1 = (idx1 != inMax1) ? inPtr0[inInc1] : *inPtr0; + d1 -= (idx1 != inMin1) ? inPtr0[-inInc1] : *inPtr0; + d1 /= ar1; + d2 = (idx2 != inMax2) ? inPtr0[inInc2] : *inPtr0; + d2 -= (idx2 != inMin2) ? inPtr0[-inInc2] : *inPtr0; + d2 /= ar2; + // If magnitude is big, don't diffuse. + d0 = sqrt(d0*d0 + d1*d1 + d2*d2); + if (d0 > this->DiffusionThreshold) + { + // hack to not diffuse + th0 = th1 = th2 = th01 = th02 = th12 = th012 = 0.0; + } + else + { + // hack to diffuse + th0 = th1 = th2 = th01 = th02 = th12 = th012 = VTK_DOUBLE_MAX; + } + } + + // Start diffusing + if (this->Faces) + { + // left + if (idx0 != inMin0) + { + temp = inPtr0[-inInc0] - *inPtr0; + if (fabs(temp) < th0) + { + *outPtr0 += temp * df0; + } + } + // right + if (idx0 != inMax0) + { + temp = inPtr0[inInc0] - *inPtr0; + if (fabs(temp) < th0) + { + *outPtr0 += temp * df0; + } + } + // up + if (idx1 != inMin1) + { + temp = inPtr0[-inInc1] - *inPtr0; + if (fabs(temp) < th1) + { + *outPtr0 += temp * df1; + } + } + // down + if (idx1 != inMax1) + { + temp = inPtr0[inInc1] - *inPtr0; + if (fabs(temp) < th1) + { + *outPtr0 += temp * df1; + } + } + // in + if (idx2 != inMin2) + { + temp = inPtr0[-inInc2] - *inPtr0; + if (fabs(temp) < th2) + { + *outPtr0 += temp * df2; + } + } + // out + if (idx2 != inMax2) + { + temp = inPtr0[inInc2] - *inPtr0; + if (fabs(temp) < th2) + { + *outPtr0 += temp * df2; + } + } + } + + if (this->Edges) + { + // left up + if (idx0 != inMin0 && idx1 != inMin1) + { + temp = inPtr0[-inInc0-inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + // right up + if (idx0 != inMax0 && idx1 != inMin1) + { + temp = inPtr0[inInc0-inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + // left down + if (idx0 != inMin0 && idx1 != inMax1) + { + temp = inPtr0[-inInc0+inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + // right down + if (idx0 != inMax0 && idx1 != inMax1) + { + temp = inPtr0[inInc0+inInc1] - *inPtr0; + if (fabs(temp) < th01) + { + *outPtr0 += temp * df01; + } + } + + // left in + if (idx0 != inMin0 && idx2 != inMin2) + { + temp = inPtr0[-inInc0-inInc2] - *inPtr0; + if (fabs(temp) < th02) + { + *outPtr0 += temp * df02; + } + } + // right in + if (idx0 != inMax0 && idx2 != inMin2) + { + temp = inPtr0[inInc0-inInc2] - *inPtr0; + if (fabs(temp) < th02) + { + *outPtr0 += temp * df02; + } + } + // left out + if (idx0 != inMin0 && idx2 != inMax2) + { + temp = inPtr0[-inInc0+inInc2] - *inPtr0; + if (fabs(temp) < th02) + { + *outPtr0 += temp * df02; + } + } + // right out + if (idx0 != inMax0 && idx2 != inMax2) + { + temp = inPtr0[inInc0+inInc2] - *inPtr0; + if (fabs(temp) < th02) + { + *outPtr0 += temp * df02; + } + } + + // up in + if (idx1 != inMin1 && idx2 != inMin2) + { + temp = inPtr0[-inInc1-inInc2] - *inPtr0; + if (fabs(temp) < th12) + { + *outPtr0 += temp * df12; + } + } + // down in + if (idx1 != inMax1 && idx2 != inMin2) + { + temp = inPtr0[inInc1-inInc2] - *inPtr0; + if (fabs(temp) < th12) + { + *outPtr0 += temp * df12; + } + } + // up out + if (idx1 != inMin1 && idx2 != inMax2) + { + temp = inPtr0[-inInc1+inInc2] - *inPtr0; + if (fabs(temp) < th12) + { + *outPtr0 += temp * df12; + } + } + // down out + if (idx1 != inMax1 && idx2 != inMax2) + { + temp = inPtr0[inInc1+inInc2] - *inPtr0; + if (fabs(temp) < th12) + { + *outPtr0 += temp * df12; + } + } + } + + if (this->Corners) + { + // left up in + if (idx0 != inMin0 && idx1 != inMin1 && idx2 != inMin2) + { + temp = inPtr0[-inInc0-inInc1-inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + // right up in + if (idx0 != inMax0 && idx1 != inMin1 && idx2 != inMin2) + { + temp = inPtr0[inInc0-inInc1-inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + // left down in + if (idx0 != inMin0 && idx1 != inMax1 && idx2 != inMin2) + { + temp = inPtr0[-inInc0+inInc1-inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + // right down in + if (idx0 != inMax0 && idx1 != inMax1 && idx2 != inMin2) + { + temp = inPtr0[inInc0+inInc1-inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + // left up out + if (idx0 != inMin0 && idx1 != inMin1 && idx2 != inMax2) + { + temp = inPtr0[-inInc0-inInc1+inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + // right up out + if (idx0 != inMax0 && idx1 != inMin1 && idx2 != inMax2) + { + temp = inPtr0[inInc0-inInc1+inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + // left down out + if (idx0 != inMin0 && idx1 != inMax1 && idx2 != inMax2) + { + temp = inPtr0[-inInc0+inInc1+inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + // right down out + if (idx0 != inMax0 && idx1 != inMax1 && idx2 != inMax2) + { + temp = inPtr0[inInc0+inInc1+inInc2] - *inPtr0; + if (fabs(temp) < th012) + { + *outPtr0 += temp * df012; + } + } + } + } + } + } + } +} diff --git a/Imaging/vtkImageAnisotropicDiffusion3D.h b/Imaging/vtkImageAnisotropicDiffusion3D.h new file mode 100644 index 0000000..d6515e3 --- /dev/null +++ b/Imaging/vtkImageAnisotropicDiffusion3D.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAnisotropicDiffusion3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageAnisotropicDiffusion3D - edge preserving smoothing. +// +// .SECTION Description +// vtkImageAnisotropicDiffusion3D diffuses an volume iteratively. +// The neighborhood of the diffusion is determined by the instance +// flags. if "Faces" is on, the 6 voxels adjoined by faces are included +// in the neighborhood. If "Edges" is on the 12 edge connected voxels +// are included, and if "Corners" is on, the 8 corner connected voxels +// are included. "DiffusionFactor" determines how far a pixel value +// moves toward its neighbors, and is insensitive to the number of +// neighbors chosen. The diffusion is anisotropic because it only occurs +// when a gradient measure is below "GradientThreshold". Two gradient measures +// exist and are toggled by the "GradientMagnitudeThreshold" flag. +// When "GradientMagnitudeThreshold" is on, the magnitude of the gradient, +// computed by central differences, above "DiffusionThreshold" +// a voxel is not modified. The alternative measure examines each +// neighbor independently. The gradient between the voxel and the neighbor +// must be below the "DiffusionThreshold" for diffusion to occur with +// THAT neighbor. + +// .SECTION See Also +// vtkImageAnisotropicDiffusion2D + +#ifndef __vtkImageAnisotropicDiffusion3D_h +#define __vtkImageAnisotropicDiffusion3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageAnisotropicDiffusion3D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageAnisotropicDiffusion3D *New(); + vtkTypeRevisionMacro(vtkImageAnisotropicDiffusion3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + + // Description: + // This method sets the number of interations which also affects the + // input neighborhood needed to compute one output pixel. Each iterations + // requires an extra pixel layer on the neighborhood. This is only relavent + // when you are trying to stream or are requesting a sub extent of the "wholeExtent". + void SetNumberOfIterations(int num); + + // Description: + // Get the number of iterations. + vtkGetMacro(NumberOfIterations,int); + + // Description: + // Set/Get the difference threshold that stops diffusion. + // when the difference between two pixel is greater than this threshold, + // the pixels are not diffused. This causes diffusion to avoid sharp edges. + // If the GradientMagnitudeThreshold is set, then gradient magnitude is used + // for comparison instead of pixel differences. + vtkSetMacro(DiffusionThreshold,double); + vtkGetMacro(DiffusionThreshold,double); + + // Description: + // Set/Get the difference factor + vtkSetMacro(DiffusionFactor,double); + vtkGetMacro(DiffusionFactor,double); + + // Description: + // Choose neighbors to diffuse (6 faces, 12 edges, 8 corners). + vtkSetMacro(Faces,int); + vtkGetMacro(Faces,int); + vtkBooleanMacro(Faces,int); + vtkSetMacro(Edges,int); + vtkGetMacro(Edges,int); + vtkBooleanMacro(Edges,int); + vtkSetMacro(Corners,int); + vtkGetMacro(Corners,int); + vtkBooleanMacro(Corners,int); + + // Description: + // Switch between gradient magnitude threshold and pixel gradient threshold. + vtkSetMacro(GradientMagnitudeThreshold,int); + vtkGetMacro(GradientMagnitudeThreshold,int); + vtkBooleanMacro(GradientMagnitudeThreshold,int); + +protected: + vtkImageAnisotropicDiffusion3D(); + ~vtkImageAnisotropicDiffusion3D() {}; + + int NumberOfIterations; + double DiffusionThreshold; + double DiffusionFactor; + // to determine which neighbors to diffuse + int Faces; + int Edges; + int Corners; + // What threshold to use + int GradientMagnitudeThreshold; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + void Iterate(vtkImageData *in, vtkImageData *out, + double ar0, double ar1, double ar3, int *coreExtent, int count); +private: + vtkImageAnisotropicDiffusion3D(const vtkImageAnisotropicDiffusion3D&); // Not implemented. + void operator=(const vtkImageAnisotropicDiffusion3D&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageAppend.cxx b/Imaging/vtkImageAppend.cxx new file mode 100644 index 0000000..c944666 --- /dev/null +++ b/Imaging/vtkImageAppend.cxx @@ -0,0 +1,422 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAppend.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageAppend.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageAppend, "$Revision: 1.30.4.1 $"); +vtkStandardNewMacro(vtkImageAppend); + +//---------------------------------------------------------------------------- +vtkImageAppend::vtkImageAppend() +{ + this->AppendAxis = 0; + this->Shifts = NULL; + this->PreserveExtents = 0; +} + +//---------------------------------------------------------------------------- +vtkImageAppend::~vtkImageAppend() +{ + if (this->Shifts != NULL) + { + delete [] this->Shifts; + } +} + +//---------------------------------------------------------------------------- +// The default vtkImageAlgorithm semantics are that SetInput() puts +// each input on a different port, we want all the image inputs to +// go on the first port. +void vtkImageAppend::SetInput(int idx, vtkDataObject *input) +{ + // Ask the superclass to connect the input. + this->SetNthInputConnection(0, idx, (input ? input->GetProducerPort() : 0)); +} + +//---------------------------------------------------------------------------- +vtkDataObject *vtkImageAppend::GetInput(int idx) +{ + if (this->GetNumberOfInputConnections(0) <= idx) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, idx)); +} + +//---------------------------------------------------------------------------- +// This method tells the ouput it will have more components +int vtkImageAppend::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo; + + int idx; + int min, max, size, tmp; + int *inExt, outExt[6]; + int unionExt[6]; + + // Initialize the union. + unionExt[0] = unionExt[2] = unionExt[4] = VTK_LARGE_INTEGER; + unionExt[1] = unionExt[3] = unionExt[5] = -VTK_LARGE_INTEGER; + + // Initialize the shifts. + if (this->Shifts) + { + delete [] this->Shifts; + } + this->Shifts = new int [this->GetNumberOfInputConnections(0)]; + + // Find the outMin/max of the appended axis for this input. + inInfo = inputVector[0]->GetInformationObject(0); + inExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + min = tmp = inExt[this->AppendAxis * 2]; + for (idx = 0; idx < this->GetNumberOfInputConnections(0); ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + inExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + if (this->PreserveExtents) + { + // Compute union for preseving extents. + if (inExt[0] < unionExt[0]) + { + unionExt[0] = inExt[0]; + } + if (inExt[1] > unionExt[1]) + { + unionExt[1] = inExt[1]; + } + if (inExt[2] < unionExt[2]) + { + unionExt[2] = inExt[2]; + } + if (inExt[3] > unionExt[3]) + { + unionExt[3] = inExt[3]; + } + if (inExt[4] < unionExt[4]) + { + unionExt[4] = inExt[4]; + } + if (inExt[5] > unionExt[5]) + { + unionExt[5] = inExt[5]; + } + this->Shifts[idx] = 0; + } + else + { + // Compute shifts if we are not preserving extents. + this->Shifts[idx] = tmp - inExt[this->AppendAxis*2]; + size = inExt[this->AppendAxis*2 + 1] - inExt[this->AppendAxis*2] + 1; + tmp += size; + } + } + + if (this->PreserveExtents) + { + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),unionExt,6); + } + else + { + inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),outExt); + max = tmp - 1; + outExt[this->AppendAxis*2] = min; + outExt[this->AppendAxis*2 + 1] = max; + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),outExt,6); + } + + return 1; +} + +void vtkImageAppend::InternalComputeInputUpdateExtent( + int *inExt, int *outExt, int *inWextent, int whichInput) +{ + int min, max, shift, tmp, idx; + + // default input extent will be that of output extent + memcpy(inExt,outExt,sizeof(int)*6); + + shift = 0; + if ( ! this->PreserveExtents) + { + shift = this->Shifts[whichInput]; + } + min = inWextent[this->AppendAxis*2] + shift; + max = inWextent[this->AppendAxis*2 + 1] + shift; + + // now clip the outExtent against the outExtent for this input (intersect) + tmp = outExt[this->AppendAxis*2]; + if (min < tmp) + { + min = tmp; + } + tmp = outExt[this->AppendAxis*2 + 1]; + if (max > tmp) + { + max = tmp; + } + + // now if min > max, we do not need the input at all. I assume + // the pipeline will interpret this extent this way. + + // convert back into input coordinates. + inExt[this->AppendAxis*2] = min - shift; + inExt[this->AppendAxis*2 + 1] = max - shift; + + // for robustness (in the execute method), + // do not ask for more than the whole extent of the other axes. + for (idx = 0; idx < 3; ++idx) + { + if (inExt[idx*2] < inWextent[idx*2]) + { + inExt[idx*2] = inWextent[idx*2]; + } + if (inExt[idx*2 + 1] > inWextent[idx*2 + 1]) + { + inExt[idx*2 + 1] = inWextent[idx*2 + 1]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkImageAppend::RequestUpdateExtent( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // default input extent will be that of output extent + int inExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt); + int *outExt = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + int whichInput; + for (whichInput = 0; whichInput < this->GetNumberOfInputConnections(0); + whichInput++) + { + int *inWextent; + + // Find the outMin/max of the appended axis for this input. + inInfo = inputVector[0]->GetInformationObject(whichInput); + inWextent = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + this->InternalComputeInputUpdateExtent(inExt, outExt, + inWextent, whichInput); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + } + + return 1; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageAppendExecute(vtkImageAppend *self, int id, + int inExt[6], vtkImageData *inData, T *inPtr, + int outExt[6], vtkImageData *outData, T *outPtr) +{ + int idxR, idxY, idxZ; + int maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int rowLength; + unsigned long count = 0; + unsigned long target; + + // Get increments to march through data + inData->GetContinuousIncrements(inExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // find the region to loop over + rowLength = (inExt[1] - inExt[0]+1)*inData->GetNumberOfScalarComponents(); + maxY = inExt[3] - inExt[2]; + maxZ = inExt[5] - inExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + + // Loop through input pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + for (idxR = 0; idxR < rowLength; idxR++) + { + // Pixel operation + *outPtr = *inPtr; + outPtr++; + inPtr++; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + +//---------------------------------------------------------------------------- +void vtkImageAppend::InitOutput(int outExt[6], vtkImageData *outData) +{ + int idxY, idxZ; + int maxY, maxZ; + vtkIdType outIncX, outIncY, outIncZ; + int rowLength; + int typeSize; + unsigned char *outPtrZ, *outPtrY; + + + typeSize = outData->GetScalarSize(); + outPtrZ = (unsigned char *)(outData->GetScalarPointerForExtent(outExt)); + + // Get increments to march through data + outData->GetIncrements(outIncX, outIncY, outIncZ); + outIncX *= typeSize; + outIncY *= typeSize; + outIncZ *= typeSize; + + // Find the region to loop over + rowLength = (outExt[1] - outExt[0]+1)*outData->GetNumberOfScalarComponents(); + rowLength *= typeSize; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + // Loop through input pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + outPtrY = outPtrZ; + for (idxY = 0; idxY <= maxY; idxY++) + { + memset(outPtrY, 0, rowLength); + outPtrY += outIncY; + } + outPtrZ += outIncZ; + } +} +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageAppend::ThreadedRequestData ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int idx1; + int inExt[6], cOutExt[6]; + void *inPtr; + void *outPtr; + + this->InitOutput(outExt, outData[0]); + + for (idx1 = 0; idx1 < this->GetNumberOfInputConnections(0); ++idx1) + { + if (inData[0][idx1] != NULL) + { + // Get the input extent and output extent + // the real out extent for this input may be clipped. + vtkInformation *inInfo = + inputVector[0]->GetInformationObject(idx1); + int *inWextent = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + this->InternalComputeInputUpdateExtent(inExt, outExt, inWextent, idx1); + memcpy(cOutExt, inExt, 6*sizeof(int)); + cOutExt[this->AppendAxis*2] = + inExt[this->AppendAxis*2] + this->Shifts[idx1]; + cOutExt[this->AppendAxis*2 + 1] = + inExt[this->AppendAxis*2 + 1] + this->Shifts[idx1]; + + // do a quick check to see if the input is used at all. + if (inExt[this->AppendAxis*2] <= inExt[this->AppendAxis*2 + 1]) + { + inPtr = inData[0][idx1]->GetScalarPointerForExtent(inExt); + outPtr = outData[0]->GetScalarPointerForExtent(cOutExt); + + if (inData[0][idx1]->GetNumberOfScalarComponents() != + outData[0]->GetNumberOfScalarComponents()) + { + vtkErrorMacro("Components of the inputs do not match"); + return; + } + + // this filter expects that input is the same type as output. + if (inData[0][idx1]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input" << idx1 << " ScalarType (" + << inData[0][idx1]->GetScalarType() + << "), must match output ScalarType (" + << outData[0]->GetScalarType() << ")"); + return; + } + + switch (inData[0][idx1]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageAppendExecute(this, id, + inExt, inData[0][idx1], (VTK_TT *)(inPtr), + cOutExt, outData[0], (VTK_TT *)(outPtr))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + } + } +} + + +//---------------------------------------------------------------------------- +int vtkImageAppend::FillInputPortInformation(int i, vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return this->Superclass::FillInputPortInformation(i,info); +} + +//---------------------------------------------------------------------------- +void vtkImageAppend::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "AppendAxis: " << this->AppendAxis << endl; + os << indent << "PreserveExtents: " << this->PreserveExtents << endl; +} diff --git a/Imaging/vtkImageAppend.h b/Imaging/vtkImageAppend.h new file mode 100644 index 0000000..3242fbd --- /dev/null +++ b/Imaging/vtkImageAppend.h @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAppend.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageAppend - Collects data from multiple inputs into one image. +// .SECTION Description +// vtkImageAppend takes the components from multiple inputs and merges +// them into one output. The output images are append along the "AppendAxis". +// Except for the append axis, all inputs must have the same extent. +// All inputs must have the same number of scalar components. +// A future extension might be to pad or clip inputs to have the same extent. +// The output has the same origin and spacing as the first input. +// The origin and spacing of all other inputs are ignored. All inputs +// must have the same scalar type. + + +#ifndef __vtkImageAppend_h +#define __vtkImageAppend_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageAppend : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageAppend *New(); + vtkTypeRevisionMacro(vtkImageAppend,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set an Input of this filter. This method is only for support of + // old-style pipeline connections. When writing new code you should + // use vtkAlgorithm::AddInputConnection(0, data). + void SetInput(int num, vtkDataObject *input); + void SetInput(vtkDataObject *input) { this->SetInput(0, input); }; + + // Description: + // Get one input to this filter. This method is only for support of + // old-style pipeline connections. When writing new code you should + // use vtkAlgorithm::GetInputConnection(0, num). + vtkDataObject *GetInput(int num); + vtkDataObject *GetInput() { return this->GetInput(0); }; + + // Description: + // Get the number of inputs to this filter. This method is only for + // support of old-style pipeline connections. When writing new code + // you should use vtkAlgorithm::GetNumberOfInputConnections(0). + int GetNumberOfInputs() { return this->GetNumberOfInputConnections(0); }; + + // Description: + // This axis is expanded to hold the multiple images. + // The default AppendAxis is the X axis. + // If you want to create a volue from a series of XY images, then you should + // set the AppendAxis to 2 (Z axis). + vtkSetMacro(AppendAxis, int); + vtkGetMacro(AppendAxis, int); + + // Description: + // By default "PreserveExtents" is off and the append axis is used. + // When "PreseveExtents" is on, the extent of the inputs is used to + // place the image in the output. The whole extent of the output is + // the union of the input whole extents. Any portion of the + // output not covered by the inputs is set to zero. The origin and + // spacing is taken from the first input. + vtkSetMacro(PreserveExtents, int); + vtkGetMacro(PreserveExtents, int); + vtkBooleanMacro(PreserveExtents, int); + +protected: + vtkImageAppend(); + ~vtkImageAppend(); + + int PreserveExtents; + int AppendAxis; + // Array holds the AppendAxisExtent shift for each input. + int *Shifts; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int RequestUpdateExtent(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + void ThreadedRequestData (vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); + + // see vtkAlgorithm for docs. + virtual int FillInputPortInformation(int, vtkInformation*); + + void InitOutput(int outExt[6], vtkImageData *outData); + + void InternalComputeInputUpdateExtent( + int *inExt, int *outExt, int *inWextent, int whichInput); + +private: + vtkImageAppend(const vtkImageAppend&); // Not implemented. + void operator=(const vtkImageAppend&); // Not implemented. +}; + +#endif + + + + diff --git a/Imaging/vtkImageAppendComponents.cxx b/Imaging/vtkImageAppendComponents.cxx new file mode 100644 index 0000000..6d055e2 --- /dev/null +++ b/Imaging/vtkImageAppendComponents.cxx @@ -0,0 +1,167 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAppendComponents.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageAppendComponents.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkDataSetAttributes.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageAppendComponents, "$Revision: 1.30.4.1 $"); +vtkStandardNewMacro(vtkImageAppendComponents); + +//---------------------------------------------------------------------------- +// The default vtkImageAlgorithm semantics are that SetInput() puts +// each input on a different port, we want all the image inputs to +// go on the first port. +void vtkImageAppendComponents::SetInput(int idx, vtkDataObject *input) +{ + // Ask the superclass to connect the input. + this->SetNthInputConnection(0, idx, (input ? input->GetProducerPort() : 0)); +} + +//---------------------------------------------------------------------------- +vtkDataObject *vtkImageAppendComponents::GetInput(int idx) +{ + if (this->GetNumberOfInputConnections(0) <= idx) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, idx)); +} + +//---------------------------------------------------------------------------- +// This method tells the ouput it will have more components +int vtkImageAppendComponents::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inScalarInfo; + + int idx1, num; + num = 0; + for (idx1 = 0; idx1 < this->GetNumberOfInputConnections(0); ++idx1) + { + inScalarInfo = vtkDataObject::GetActiveFieldInformation( + inputVector[0]->GetInformationObject(idx1), + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (inScalarInfo && + inScalarInfo->Has( vtkDataObject::FIELD_NUMBER_OF_COMPONENTS() ) ) + { + num += inScalarInfo->Get( vtkDataObject::FIELD_NUMBER_OF_COMPONENTS() ); + } + } + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, -1, num); + return 1; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageAppendComponentsExecute(vtkImageAppendComponents *self, + vtkImageData *inData, + vtkImageData *outData, + int outComp, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + int numIn = inData->GetNumberOfScalarComponents(); + int numSkip = outData->GetNumberOfScalarComponents() - numIn; + int i; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan() + outComp; + T* outSIEnd = outIt.EndSpan(); + while (outSI < outSIEnd) + { + // now process the components + for (i = 0; i < numIn; ++i) + { + *outSI = *inSI; + ++outSI; + ++inSI; + } + outSI = outSI + numSkip; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +int vtkImageAppendComponents::FillInputPortInformation(int i, + vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return this->Superclass::FillInputPortInformation(i,info); +} + +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageAppendComponents::ThreadedRequestData ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int idx1, outComp; + + outComp = 0; + for (idx1 = 0; idx1 < this->GetNumberOfInputConnections(0); ++idx1) + { + if (inData[0][idx1] != NULL) + { + // this filter expects that input is the same type as output. + if (inData[0][idx1]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input" << idx1 << " ScalarType (" + << inData[0][idx1]->GetScalarType() + << "), must match output ScalarType (" + << outData[0]->GetScalarType() << ")"); + return; + } + switch (inData[0][idx1]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageAppendComponentsExecute ( this, + inData[0][idx1], outData[0], + outComp, outExt, id, + static_cast(0)) ); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + outComp += inData[0][idx1]->GetNumberOfScalarComponents(); + } + } +} + diff --git a/Imaging/vtkImageAppendComponents.h b/Imaging/vtkImageAppendComponents.h new file mode 100644 index 0000000..4542ab6 --- /dev/null +++ b/Imaging/vtkImageAppendComponents.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageAppendComponents.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageAppendComponents - Collects components from two inputs into +// one output. +// .SECTION Description +// vtkImageAppendComponents takes the components from two inputs and merges +// them into one output. If Input1 has M components, and Input2 has N +// components, the output will have M+N components with input1 +// components coming first. + + +#ifndef __vtkImageAppendComponents_h +#define __vtkImageAppendComponents_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageAppendComponents : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageAppendComponents *New(); + vtkTypeRevisionMacro(vtkImageAppendComponents,vtkThreadedImageAlgorithm); + + // Description: + // Set an Input of this filter. This method is only for support of + // old-style pipeline connections. When writing new code you should + // use vtkAlgorithm::AddInputConnection(0, data). + void SetInput(int num, vtkDataObject *input); + void SetInput(vtkDataObject *input) { this->SetInput(0, input); }; + + // Description: + // Get one input to this filter. This method is only for support of + // old-style pipeline connections. When writing new code you should + // use vtkAlgorithm::GetInputConnection(0, num). + vtkDataObject *GetInput(int num); + vtkDataObject *GetInput() { return this->GetInput(0); }; + + // Description: + // Get the number of inputs to this filter. This method is only for + // support of old-style pipeline connections. When writing new code + // you should use vtkAlgorithm::GetNumberOfInputConnections(0). + int GetNumberOfInputs() { return this->GetNumberOfInputConnections(0); }; + +protected: + vtkImageAppendComponents() {}; + ~vtkImageAppendComponents() {}; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + void ThreadedRequestData (vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); + + // Implement methods required by vtkAlgorithm. + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkImageAppendComponents(const vtkImageAppendComponents&); // Not implemented. + void operator=(const vtkImageAppendComponents&); // Not implemented. +}; + +#endif + + + + diff --git a/Imaging/vtkImageBlend.cxx b/Imaging/vtkImageBlend.cxx new file mode 100644 index 0000000..b2a79ac --- /dev/null +++ b/Imaging/vtkImageBlend.cxx @@ -0,0 +1,1169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageBlend.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageBlend.h" + +#include "vtkImageData.h" +#include "vtkImageStencilData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageBlend, "$Revision: 1.38.4.2 $"); +vtkStandardNewMacro(vtkImageBlend); + +//---------------------------------------------------------------------------- +vtkImageBlend::vtkImageBlend() +{ + this->Opacity = 0; + this->OpacityArrayLength = 0; + this->BlendMode = VTK_IMAGE_BLEND_MODE_NORMAL; + this->CompoundThreshold = 0.0; + this->DataWasPassed = 0; + + // we have the image inputs and the optional stencil input + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +vtkImageBlend::~vtkImageBlend() +{ + if (this->Opacity) + { + delete [] this->Opacity; + } + this->OpacityArrayLength = 0; +} + +//---------------------------------------------------------------------------- +// The default vtkImageAlgorithm semantics are that SetInput() puts +// each input on a different port, we want all the image inputs to +// go on the first port. +void vtkImageBlend::SetInput(int idx, vtkDataObject *input) +{ + // Ask the superclass to connect the input. + this->SetNthInputConnection(0, idx, (input ? input->GetProducerPort() : 0)); +} + +//---------------------------------------------------------------------------- +vtkDataObject *vtkImageBlend::GetInput(int idx) +{ + if (this->GetNumberOfInputConnections(0) <= idx) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, idx)); +} + +//---------------------------------------------------------------------------- +void vtkImageBlend::SetStencil(vtkImageStencilData *stencil) +{ + // if stencil is null, then set the input port to null + this->SetNthInputConnection(1, 0, + (stencil ? stencil->GetProducerPort() : 0)); +} + + +//---------------------------------------------------------------------------- +vtkImageStencilData *vtkImageBlend::GetStencil() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return 0; + } + return vtkImageStencilData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +//---------------------------------------------------------------------------- +void vtkImageBlend::SetOpacity(int idx, double opacity) +{ + int i; + int newLength; + double *newArray; + + if (opacity < 0.0) + { + opacity = 0.0; + } + if (opacity > 1.0) + { + opacity = 1.0; + } + + if (idx >= this->OpacityArrayLength) + { + newLength = idx + 1; + newArray = new double[newLength]; + for (i = 0; i < this->OpacityArrayLength; i++) + { + newArray[i] = this->Opacity[i]; + } + for (; i < newLength; i++) + { + newArray[i] = 1.0; + } + if (this->Opacity) + { + delete [] this->Opacity; + } + this->Opacity = newArray; + this->OpacityArrayLength = newLength; + } + + if (this->Opacity[idx] != opacity) + { + this->Opacity[idx] = opacity; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +double vtkImageBlend::GetOpacity(int idx) +{ + if (idx >= this->OpacityArrayLength) + { + return 1.0; + } + return this->Opacity[idx]; +} + +//---------------------------------------------------------------------------- +int vtkImageBlend::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed( outputVector )) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // this is some scary stuff, propagating info upstream??? - Ken + vtkImageStencilData *stencil = this->GetStencil(); + if (stencil) + { + stencil->SetSpacing(inInfo->Get(vtkDataObject::SPACING())); + stencil->SetOrigin(inInfo->Get(vtkDataObject::ORIGIN())); + } + + return 1; +} + +//---------------------------------------------------------------------------- +// This method computes the extent of the input region necessary to generate +// an output region. Before this method is called "region" should have the +// extent of the output region. After this method finishes, "region" should +// have the extent of the required input region. The default method assumes +// the required input extent are the same as the output extent. +// Note: The splitting methods call this method with outRegion = inRegion. +void vtkImageBlend::InternalComputeInputUpdateExtent(int inExt[6], + int outExt[6], + int wholeExtent[6]) +{ + memcpy(inExt,outExt,sizeof(int)*6); + + int i; + + // clip with the whole extent + for (i = 0; i < 3; i++) + { + if (inExt[2*i] < wholeExtent[2*i]) + { + inExt[2*i] = wholeExtent[2*i]; + } + if (inExt[2*i+1] > wholeExtent[2*i+1]) + { + inExt[2*i+1] = wholeExtent[2*i+1]; + } + } +} + +//---------------------------------------------------------------------------- +int vtkImageBlend::RequestUpdateExtent( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + // default input extent will be that of output extent + int inExt[6]; + int *outExt = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + int whichInput; + for (whichInput = 0; whichInput < this->GetNumberOfInputConnections(0); + whichInput++) + { + int *inWextent; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(whichInput); + inWextent = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + this->InternalComputeInputUpdateExtent(inExt, outExt, inWextent); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + } + + return 1; +} + +int vtkImageBlend::RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // check to see if we have more than one input + if (this->GetNumberOfInputConnections(0) == 1) + { + vtkDebugMacro("RequestData: single input, passing data"); + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkImageData *outData = static_cast( + info->Get(vtkDataObject::DATA_OBJECT())); + info = inputVector[0]->GetInformationObject(0); + vtkImageData *inData = + static_cast(info->Get(vtkDataObject::DATA_OBJECT())); + + outData->SetExtent(inData->GetExtent()); + outData->GetPointData()->PassData(inData->GetPointData()); + this->DataWasPassed = 1; + } + else // multiple inputs + { + vtkInformation* info = outputVector->GetInformationObject(0); + vtkImageData *outData = static_cast( + info->Get(vtkDataObject::DATA_OBJECT())); + if (this->DataWasPassed) + { + outData->GetPointData()->SetScalars(NULL); + this->DataWasPassed = 0; + } + return this->Superclass::RequestData(request,inputVector,outputVector); + } + + return 1; +} + +//---------------------------------------------------------------------------- +// helper function for the stencil +template +inline int vtkBlendGetNextExtent(vtkImageStencilData *stencil, + int &r1, int &r2, int rmin, int rmax, + int yIdx, int zIdx, + T *&outPtr, T *&inPtr, + int outScalars, int inScalars, + int &iter) +{ + // trivial case if stencil is not set + if (!stencil) + { + if (iter++ == 0) + { + r1 = rmin; + r2 = rmax; + return 1; + } + return 0; + } + + // save r2 + int oldr2 = r2; + if (iter == 0) + { // if no 'last time', start just before rmin + oldr2 = rmin - 1; + } + + int rval = stencil->GetNextExtent(r1, r2, rmin, rmax, yIdx, zIdx, iter); + int incr = r1 - oldr2 - 1; + if (rval == 0) + { + incr = rmax - oldr2; + } + + outPtr += incr*outScalars; + inPtr += incr*inScalars; + + return rval; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageBlendExecute(vtkImageBlend *self, int extent[6], + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + double opacity, int id) +{ + int idxX, idxY, idxZ; + int minX = 0; + int maxX = 0; + int iter; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int inC, outC; + double minA, maxA; + double r, f; + unsigned long count = 0; + unsigned long target; + + vtkImageStencilData *stencil = self->GetStencil(); + + if (inData->GetScalarType() == VTK_DOUBLE || + inData->GetScalarType() == VTK_FLOAT) + { + minA = 0.0; + maxA = 1.0; + } + else + { + minA = inData->GetScalarTypeMin(); + maxA = inData->GetScalarTypeMax(); + } + + r = opacity; + f = 1.0 - r; + + opacity = opacity/(maxA-minA); + + inC = inData->GetNumberOfScalarComponents(); + outC = outData->GetNumberOfScalarComponents(); + + target = (unsigned long)((extent[3] - extent[2] + 1)* + (extent[5] - extent[4] + 1)/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(extent, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(extent, outIncX, outIncY, outIncZ); + + // Loop through output pixels + for (idxZ = extent[4]; idxZ <= extent[5]; idxZ++) + { + for (idxY = extent[2]; !self->AbortExecute && idxY <= extent[3]; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + iter = 0; + if (outC >= 3 && inC >= 4) + { // RGB(A) blended with RGBA + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + r = opacity*(inPtr[3]-minA); + f = 1.0-r; + outPtr[0] = T(outPtr[0]*f + inPtr[0]*r); + outPtr[1] = T(outPtr[1]*f + inPtr[1]*r); + outPtr[2] = T(outPtr[2]*f + inPtr[2]*r); + outPtr += outC; + inPtr += inC; + } + } + } + else if (outC >= 3 && inC == 3) + { // RGB(A) blended with RGB + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + outPtr[0] = T(outPtr[0]*f + inPtr[0]*r); + outPtr[1] = T(outPtr[1]*f + inPtr[1]*r); + outPtr[2] = T(outPtr[2]*f + inPtr[2]*r); + outPtr += outC; + inPtr += inC; + } + } + } + else if (outC >= 3 && inC == 2) + { // RGB(A) blended with luminance+alpha + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + r = opacity*(inPtr[1]-minA); + f = 1.0-r; + outPtr[0] = T(outPtr[0]*f + (*inPtr)*r); + outPtr[1] = T(outPtr[1]*f + (*inPtr)*r); + outPtr[2] = T(outPtr[2]*f + (*inPtr)*r); + outPtr += outC; + inPtr += 2; + } + } + } + else if (outC >= 3 && inC == 1) + { // RGB(A) blended with luminance + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + outPtr[0] = T(outPtr[0]*f + (*inPtr)*r); + outPtr[1] = T(outPtr[1]*f + (*inPtr)*r); + outPtr[2] = T(outPtr[2]*f + (*inPtr)*r); + outPtr += outC; + inPtr++; + } + } + } + else if (inC == 2) + { // luminance(+alpha) blended with luminance+alpha + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + r = opacity*(inPtr[1]-minA); + f = 1.0-r; + *outPtr = T((*outPtr)*f + (*inPtr)*r); + outPtr += outC; + inPtr += 2; + } + } + } + else + { // luminance(+alpha) blended with luminance + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + *outPtr = T((*outPtr)*f + (*inPtr)*r); + outPtr += outC; + inPtr++; + } + } + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter specifically for char data +template +void vtkImageBlendExecuteChar(vtkImageBlend *self, int extent[6], + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + double opacity, int id) +{ + int idxX, idxY, idxZ; + int minX = 0; + int maxX = 0; + int iter; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int inC, outC; + unsigned short r, f, o; + int v0, v1, v2; + unsigned long count = 0; + unsigned long target; + + vtkImageStencilData *stencil = self->GetStencil(); + + // round opacity to a value in the range [0,256], because division + // by 256 can be efficiently achieved by bit-shifting by 8 bits + o = (unsigned short)(256*opacity + 0.5); + r = o; + f = 256 - o; + + inC = inData->GetNumberOfScalarComponents(); + outC = outData->GetNumberOfScalarComponents(); + + target = (unsigned long)((extent[3] - extent[2] + 1)* + (extent[5] - extent[4] + 1)/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(extent, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(extent, outIncX, outIncY, outIncZ); + + // Loop through ouput pixels + for (idxZ = extent[4]; idxZ <= extent[5]; idxZ++) + { + for (idxY = extent[2]; !self->AbortExecute && idxY <= extent[3]; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + iter = 0; + if (outC >= 3 && inC >= 4) + { // RGB(A) blended with RGBA + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + // multiply to get a number in the range [0,65280] + // where 65280 = 255*256 = range of inPtr[3] * range of o + r = inPtr[3]*o; + f = 65280 - r; + v0 = outPtr[0]*f + inPtr[0]*r; + v1 = outPtr[1]*f + inPtr[1]*r; + v2 = outPtr[2]*f + inPtr[2]*r; + // do some math tricks to achieve division by 65280: + // this is not an approximation, it gives exactly the + // same result as an integer division by 65280 + outPtr[0] = (v0 + (v0 >> 8) + (v0 >> 16) + 1) >> 16; + outPtr[1] = (v1 + (v1 >> 8) + (v1 >> 16) + 1) >> 16; + outPtr[2] = (v2 + (v2 >> 8) + (v2 >> 16) + 1) >> 16; + inPtr += inC; + outPtr += outC; + } + } + } + else if (outC >= 3 && inC == 3) + { // RGB(A) blended with RGB + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + // the bit-shift achieves a division by 256 + outPtr[0] = (outPtr[0]*f + inPtr[0]*r) >> 8; + outPtr[1] = (outPtr[1]*f + inPtr[1]*r) >> 8; + outPtr[2] = (outPtr[2]*f + inPtr[2]*r) >> 8; + inPtr += 3; + outPtr += outC; + } + } + } + else if (outC >= 3 && inC == 2) + { // RGB(A) blended with luminance+alpha + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + // multiply to get a number in the range [0,65280] + // where 65280 = 255*256 = range of inPtr[1] * range of o + r = inPtr[1]*o; + f = 65280 - r; + v0 = outPtr[0]*f + inPtr[0]*r; + v1 = outPtr[1]*f + inPtr[0]*r; + v2 = outPtr[2]*f + inPtr[0]*r; + // do some math tricks to achieve division by 65280: + // this is not an approximation, it gives exactly the + // same result as an integer division by 65280 + outPtr[0] = (v0 + (v0 >> 8) + (v0 >> 16) + 1) >> 16; + outPtr[1] = (v1 + (v1 >> 8) + (v1 >> 16) + 1) >> 16; + outPtr[2] = (v2 + (v2 >> 8) + (v2 >> 16) + 1) >> 16; + inPtr += 2; + outPtr += outC; + } + } + } + else if (outC >= 3 && inC == 1) + { // RGB(A) blended with luminance + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + // the bit-shift achieves a division by 256 + outPtr[0] = (outPtr[0]*f + inPtr[0]*r) >> 8; + outPtr[1] = (outPtr[1]*f + inPtr[0]*r) >> 8; + outPtr[2] = (outPtr[2]*f + inPtr[0]*r) >> 8; + inPtr++; + outPtr += outC; + } + } + } + else if (inC == 2) + { // luminance(+alpha) blended with luminance+alpha + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + // multiply to get a number in the range [0,65280] + // where 65280 = 255*256 = range of inPtr[1] * range of o + r = inPtr[1]*o; + f = 65280 - r; + v0 = outPtr[0]*f + inPtr[0]*r; + // do some math tricks to achieve division by 65280: + // this is not an approximation, it gives exactly the + // same result as an integer division by 65280 + outPtr[0] = (v0 + (v0 >> 8) + (v0 >> 16) + 1) >> 16; + inPtr += 2; + outPtr += outC; + } + } + } + else + { // luminance(+alpha) blended with luminance + while (vtkBlendGetNextExtent(stencil, minX, maxX, extent[0], extent[1], + idxY, idxZ, + outPtr, inPtr, outC, inC, iter)) + { + for (idxX = minX; idxX <= maxX; idxX++) + { + // the bit-shift achieves a division by 256 + outPtr[0] = (outPtr[0]*f + inPtr[0]*r) >> 8; + inPtr++; + outPtr += outC; + } + } + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This function simply does a copy (for the first input) +//---------------------------------------------------------------------------- +void vtkImageBlendCopyData(vtkImageData *inData, vtkImageData *outData, + int *ext) +{ + int idxY, idxZ, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + int rowLength; + unsigned char *inPtr, *inPtr1, *outPtr; + + inPtr = (unsigned char *) inData->GetScalarPointerForExtent(ext); + outPtr = (unsigned char *) outData->GetScalarPointerForExtent(ext); + + // Get increments to march through inData + inData->GetIncrements(inIncX, inIncY, inIncZ); + + // find the region to loop over + rowLength = (ext[1] - ext[0]+1)*inIncX*inData->GetScalarSize(); + maxY = ext[3] - ext[2]; + maxZ = ext[5] - ext[4]; + + inIncY *= inData->GetScalarSize(); + inIncZ *= inData->GetScalarSize(); + + // Loop through outData pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + inPtr1 = inPtr + idxZ*inIncZ; + for (idxY = 0; idxY <= maxY; idxY++) + { + memcpy(outPtr,inPtr1,rowLength); + inPtr1 += inIncY; + outPtr += rowLength; + } + } +} + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageBlendCompoundExecute(vtkImageBlend *self, + int extent[6], + vtkImageData *inData, + T *inPtr, + vtkImageData *tmpData, + double opacity, + double threshold) +{ + unsigned long count = 0; + unsigned long target; + + target = (unsigned long)((extent[3] - extent[2] + 1)* + (extent[5] - extent[4] + 1)/50.0); + target++; + + // Get increments to march through data + + vtkIdType inIncX, inIncY, inIncZ; + int inC; + + inData->GetContinuousIncrements(extent, inIncX, inIncY, inIncZ); + inC = inData->GetNumberOfScalarComponents(); + + vtkIdType tmpIncX, tmpIncY, tmpIncZ; + int tmpC; + + tmpData->GetContinuousIncrements(extent, tmpIncX, tmpIncY, tmpIncZ); + tmpC = tmpData->GetNumberOfScalarComponents(); + + double* tmpPtr = (double *)tmpData->GetScalarPointerForExtent(extent); + + // Opacity + double minA, maxA; + double r; + + if (inData->GetScalarType() == VTK_DOUBLE || + inData->GetScalarType() == VTK_FLOAT) + { + minA = 0.0; + maxA = 1.0; + } + else + { + minA = (double)inData->GetScalarTypeMin(); + maxA = (double)inData->GetScalarTypeMax(); + } + + r = opacity; + opacity = opacity/(maxA-minA); + + if ((inC == 3 || inC == 1) && r <= threshold) + { + return; + } + + // Loop through output pixels + + for (int idxZ = extent[4]; idxZ <= extent[5]; idxZ++) + { + for (int idxY = extent[2]; !self->AbortExecute && idxY<=extent[3]; idxY++) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + + if (tmpC >= 3) + { + + // RGB(A) blended with RGBA + if (inC >= 4) + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + r = opacity * ((double)inPtr[3] - minA); + if (r > threshold) + { + tmpPtr[0] += (double)inPtr[0] * r; + tmpPtr[1] += (double)inPtr[1] * r; + tmpPtr[2] += (double)inPtr[2] * r; + tmpPtr[3] += r; + } + tmpPtr += 4; + inPtr += inC; + } + } + + // RGB(A) blended with RGB + else if (inC == 3) + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + tmpPtr[0] += (double)inPtr[0] * r; + tmpPtr[1] += (double)inPtr[1] * r; + tmpPtr[2] += (double)inPtr[2] * r; + tmpPtr[3] += r; + tmpPtr += 4; + inPtr += inC; + } + } + + // RGB(A) blended with luminance+alpha + else if (inC == 2) + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + r = opacity * ((double)inPtr[1] - minA); + if (r > threshold) + { + tmpPtr[0] += (double)(*inPtr) * r; + tmpPtr[1] += (double)(*inPtr) * r; + tmpPtr[2] += (double)(*inPtr) * r; + tmpPtr[3] += r; + } + tmpPtr += 4; + inPtr += 2; + } + } + + // RGB(A) blended with luminance + else if (inC == 1) + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + tmpPtr[0] += (double)(*inPtr) * r; + tmpPtr[1] += (double)(*inPtr) * r; + tmpPtr[2] += (double)(*inPtr) * r; + tmpPtr[3] += r; + tmpPtr += 4; + inPtr++; + } + } + } + + // luminance(+alpha) blended with luminance+alpha + else if (inC == 2) + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + r = opacity * ((double)inPtr[1] - minA); + if (r > threshold) + { + tmpPtr[0] = (double)(*inPtr) * r; + tmpPtr[1] += r; + } + tmpPtr += 2; + inPtr += 2; + } + } + + // luminance(+alpha) blended with luminance + else + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + tmpPtr[0] = (double)(*inPtr) * r; + tmpPtr[1] += r; + tmpPtr += 2; + inPtr++; + } + } + + tmpPtr += tmpIncY; + inPtr += inIncY; + } + tmpPtr += tmpIncZ; + inPtr += inIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageBlendCompoundTransferExecute(vtkImageBlend *self, + int extent[6], + vtkImageData *outData, + T *outPtr, + vtkImageData *tmpData) +{ + // Get increments to march through data + + vtkIdType outIncX, outIncY, outIncZ; + int outC; + + outData->GetContinuousIncrements(extent, outIncX, outIncY, outIncZ); + outC = outData->GetNumberOfScalarComponents(); + + vtkIdType tmpIncX, tmpIncY, tmpIncZ; + int tmpC; + + tmpData->GetContinuousIncrements(extent, tmpIncX, tmpIncY, tmpIncZ); + tmpC = tmpData->GetNumberOfScalarComponents(); + + double* tmpPtr = (double *)tmpData->GetScalarPointerForExtent(extent); + + // Loop through output pixels + + for (int idxZ = extent[4]; idxZ <= extent[5]; idxZ++) + { + for (int idxY = extent[2]; !self->AbortExecute && idxY<=extent[3]; idxY++) + { + if (tmpC >= 3) + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + double factor = 0.0; + if (tmpPtr[3] != 0) + { + factor = 1.0/tmpPtr[3]; + } + outPtr[0] = T(tmpPtr[0]*factor); + outPtr[1] = T(tmpPtr[1]*factor); + outPtr[2] = T(tmpPtr[2]*factor); + tmpPtr += 4; + outPtr += outC; + } + } + else + { + for (int idxX = extent[0]; idxX <= extent[1]; idxX++) + { + double factor = 0.0; + if (tmpPtr[1] != 0) + { + factor = 1.0/tmpPtr[1]; + } + outPtr[0] = T(tmpPtr[0]*factor); + tmpPtr += 2; + outPtr += outC; + } + } + + tmpPtr += tmpIncY; + outPtr += outIncY; + } + tmpPtr += tmpIncZ; + outPtr += outIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageBlend::ThreadedRequestData ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int extent[6]; + void *inPtr; + void *outPtr; + + double opacity; + + vtkImageData *tmpData = NULL; + + // check + if (inData[0][0]->GetNumberOfScalarComponents() > 4) + { + vtkErrorMacro("The first input can have a maximum of four components"); + return; + } + + // init + switch (this->BlendMode) + { + case VTK_IMAGE_BLEND_MODE_NORMAL: + // copy the first image directly to the output + vtkDebugMacro("Execute: copy input 0 to the output."); + vtkImageBlendCopyData(inData[0][0], outData[0], outExt); + break; + + case VTK_IMAGE_BLEND_MODE_COMPOUND: + tmpData = vtkImageData::New(); + if (tmpData == NULL) + { + vtkErrorMacro(<< "Execute: Unable to allocate memory"); + return; + } + tmpData->SetExtent(outExt); + tmpData->SetNumberOfScalarComponents( + (outData[0]->GetNumberOfScalarComponents() >= 3 ? 3 : 1) + 1); + tmpData->SetScalarType(VTK_DOUBLE); + tmpData->AllocateScalars(); + memset((void *)tmpData->GetScalarPointer(), 0, + (outExt[1] - outExt[0] + 1) * + (outExt[3] - outExt[2] + 1) * + (outExt[5] - outExt[4] + 1) * + tmpData->GetNumberOfScalarComponents() * + tmpData->GetScalarSize()); + break; + + default: + vtkErrorMacro(<< "Execute: Unknown blending mode"); + } + + // process each input + int first_index = (this->BlendMode == VTK_IMAGE_BLEND_MODE_NORMAL ? 1 : 0); + for (int idx1 = first_index; + idx1 < this->GetNumberOfInputConnections(0); ++idx1) + { + if (inData[0][idx1] != NULL) + { + + // RGB with RGB, greyscale with greyscale + if ((inData[0][idx1]->GetNumberOfScalarComponents()+1)/2 == 2 && + (inData[0][0]->GetNumberOfScalarComponents()+1)/2 == 1) + { + vtkErrorMacro("input has too many components, can't blend RGB data \ + into greyscale data"); + continue; + } + + // this filter expects that input is the same type as output. + if (inData[0][idx1]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input" << idx1 << " ScalarType (" << + inData[0][idx1]->GetScalarType() << + "), must match output ScalarType (" << outData[0]->GetScalarType() + << ")"); + continue; + } + + // input extents + vtkInformation *inInfo = + inputVector[0]->GetInformationObject(idx1); + int *inWextent = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + this->InternalComputeInputUpdateExtent(extent, outExt, inWextent); + + int skip = 0; + for (int i = 0; i < 3; i++) + { + if (outExt[2*i+1] < extent[2*i] || outExt[2*i] > extent[2*i+1]) + { + // extents don't overlap, skip this input + skip = 1; + } + } + + if (skip) + { + vtkDebugMacro("Execute: skipping input."); + continue; + } + + opacity = this->GetOpacity(idx1); + + inPtr = inData[0][idx1]->GetScalarPointerForExtent(extent); + + // vtkDebugMacro("Execute: " << idx1 << "=>" << extent[0] << ", " << extent[1] << " / " << extent[2] << ", " << extent[3] << " / " << extent[4] << ", " << extent[5]); + + switch (this->BlendMode) + { + case VTK_IMAGE_BLEND_MODE_NORMAL: + outPtr = outData[0]->GetScalarPointerForExtent(extent); + // for performance reasons, use a special method for unsigned char + if (inData[0][idx1]->GetScalarType() == VTK_UNSIGNED_CHAR) + { + vtkImageBlendExecuteChar(this, extent, + inData[0][idx1], (unsigned char *)(inPtr), + outData[0], (unsigned char *)(outPtr), + opacity, id); + } + else + { + switch (inData[0][idx1]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageBlendExecute(this, extent, + inData[0][idx1], (VTK_TT *)(inPtr), + outData[0], (VTK_TT *)(outPtr), + opacity, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + break; + + case VTK_IMAGE_BLEND_MODE_COMPOUND: + switch (inData[0][idx1]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageBlendCompoundExecute(this, + extent, + inData[0][idx1], + (VTK_TT *)(inPtr), + tmpData, + opacity, + this->CompoundThreshold)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + break; + + default: + vtkErrorMacro(<< "Execute: Unknown blending mode"); + } + } + } + + // conclude + switch (this->BlendMode) + { + case VTK_IMAGE_BLEND_MODE_NORMAL: + break; + + case VTK_IMAGE_BLEND_MODE_COMPOUND: + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + switch (outData[0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageBlendCompoundTransferExecute(this, + outExt, + outData[0], + (VTK_TT *)(outPtr), + tmpData)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + tmpData->Delete(); + break; + + default: + vtkErrorMacro(<< "Execute: Unknown blending mode"); + } +} + + +//---------------------------------------------------------------------------- +void vtkImageBlend::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + int i; + for (i = 0; i < this->OpacityArrayLength; i++) + { + os << indent << "Opacity(" << i << "): " << this->GetOpacity(i) << endl; + } + os << indent << "Stencil: " << this->GetStencil() << endl; + os << indent << "BlendMode: " << this->GetBlendModeAsString() << endl + << indent << "CompoundThreshold: " << this->CompoundThreshold << endl; +} + +//---------------------------------------------------------------------------- +int vtkImageBlend::FillInputPortInformation(int port, vtkInformation* info) +{ + if (port == 0) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + } + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageStencilData"); + // the stencil input is optional + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + return 1; +} diff --git a/Imaging/vtkImageBlend.h b/Imaging/vtkImageBlend.h new file mode 100644 index 0000000..0396892 --- /dev/null +++ b/Imaging/vtkImageBlend.h @@ -0,0 +1,200 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageBlend.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageBlend - blend images together using alpha or opacity +// .SECTION Description +// vtkImageBlend takes L, LA, RGB, or RGBA images as input and blends them +// according to the alpha values and/or the opacity setting for each input. +// +// The spacing, origin, extent, and number of components of the output are +// the same as those for the first input. If the input has an alpha +// component, then this component is copied unchanged into the output. +// In addition, if the first input has either one component or two +// components i.e. if it is either L (greyscale) or LA (greyscale + alpha) +// then all other inputs must also be L or LA. +// +// Different blending modes are available: +// +// \em Normal (default) : +// This is the standard blending mode used by OpenGL and other graphics +// packages. The output always has the same number of components +// and the same extent as the first input. The alpha value of the first +// input is not used in the blending computation, instead it is copied +// directly to the output. +// +// \code +// output <- input[0] +// foreach input i { +// foreach pixel px { +// r <- input[i](px)(alpha) * opacity[i] +// f <- (255 - r) +// output(px) <- output(px) * f + input(px) * r +// } +// } +// \endcode +// +// \em Compound : +// Images are compounded together and each component is scaled by the sum of +// the alpha/opacity values. Use the CompoundThreshold method to set +// specify a threshold in compound mode. Pixels with opacity*alpha less +// or equal than this threshold are ignored. +// The alpha value of the first input, if present, is NOT copied to the alpha +// value of the output. The output always has the same number of components +// and the same extent as the first input. +// +// \code +// output <- 0 +// foreach pixel px { +// sum <- 0 +// foreach input i { +// r <- input[i](px)(alpha) * opacity(i) +// sum <- sum + r +// if r > threshold { +// output(px) <- output(px) + input(px) * r +// } +// } +// output(px) <- output(px) / sum +// } +// \endcode + +#ifndef __vtkImageBlend_h +#define __vtkImageBlend_h + + +#include "vtkThreadedImageAlgorithm.h" + +class vtkImageStencilData; + +#define VTK_IMAGE_BLEND_MODE_NORMAL 0 +#define VTK_IMAGE_BLEND_MODE_COMPOUND 1 + +class VTK_IMAGING_EXPORT vtkImageBlend : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageBlend *New(); + vtkTypeRevisionMacro(vtkImageBlend,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set an Input of this filter. This method is only for support of + // old-style pipeline connections. When writing new code you should + // use vtkAlgorithm::AddInputConnection(0, data). + void SetInput(int num, vtkDataObject *input); + void SetInput(vtkDataObject *input) { this->SetInput(0, input); }; + + // Description: + // Get one input to this filter. This method is only for support of + // old-style pipeline connections. When writing new code you should + // use vtkAlgorithm::GetInputConnection(0, num). + vtkDataObject *GetInput(int num); + vtkDataObject *GetInput() { return this->GetInput(0); }; + + // Description: + // Get the number of inputs to this filter. This method is only for + // support of old-style pipeline connections. When writing new code + // you should use vtkAlgorithm::GetNumberOfInputConnections(0). + int GetNumberOfInputs() { return this->GetNumberOfInputConnections(0); }; + + // Description: + // Set the opacity of an input image: the alpha values of the image are + // multiplied by the opacity. The opacity of image idx=0 is ignored. + void SetOpacity(int idx, double opacity); + double GetOpacity(int idx); + + // Description: + // Set a stencil to apply when blending the data. + void SetStencil(vtkImageStencilData *stencil); + vtkImageStencilData *GetStencil(); + + // Description: + // Set the blend mode + vtkSetClampMacro(BlendMode,int, + VTK_IMAGE_BLEND_MODE_NORMAL, + VTK_IMAGE_BLEND_MODE_COMPOUND ); + vtkGetMacro(BlendMode,int); + void SetBlendModeToNormal() + {this->SetBlendMode(VTK_IMAGE_BLEND_MODE_NORMAL);}; + void SetBlendModeToCompound() + {this->SetBlendMode(VTK_IMAGE_BLEND_MODE_COMPOUND);}; + const char *GetBlendModeAsString(void); + + // Description: + // Specify a threshold in compound mode. Pixels with opacity*alpha less + // or equal the threshold are ignored. + vtkSetMacro(CompoundThreshold,double); + vtkGetMacro(CompoundThreshold,double); + +protected: + vtkImageBlend(); + ~vtkImageBlend(); + + virtual int RequestUpdateExtent(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + void InternalComputeInputUpdateExtent(int inExt[6], int outExt[6], + int inWExtent[6]); + + + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + void ThreadedRequestData (vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); + + // see vtkAlgorithm for docs. + virtual int FillInputPortInformation(int, vtkInformation*); + + // see vtkAlgorithm for docs. + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + double *Opacity; + int OpacityArrayLength; + int BlendMode; + double CompoundThreshold; + int DataWasPassed; + +private: + vtkImageBlend(const vtkImageBlend&); // Not implemented. + void operator=(const vtkImageBlend&); // Not implemented. +}; + +// Description: +// Get the blending mode as a descriptive string +inline const char *vtkImageBlend::GetBlendModeAsString() +{ + switch (this->BlendMode) + { + case VTK_IMAGE_BLEND_MODE_NORMAL: + return "Normal"; + case VTK_IMAGE_BLEND_MODE_COMPOUND: + return "Compound"; + default: + return "Unknown Blend Mode"; + } +} + + +#endif + + + + diff --git a/Imaging/vtkImageButterworthHighPass.cxx b/Imaging/vtkImageButterworthHighPass.cxx new file mode 100644 index 0000000..c3e27d4 --- /dev/null +++ b/Imaging/vtkImageButterworthHighPass.cxx @@ -0,0 +1,240 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageButterworthHighPass.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageButterworthHighPass.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageButterworthHighPass, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkImageButterworthHighPass); + +//---------------------------------------------------------------------------- +vtkImageButterworthHighPass::vtkImageButterworthHighPass() +{ + this->CutOff[0] = this->CutOff[1] = this->CutOff[2] = VTK_FLOAT_MAX; + this->Order = 1; +} + + +//---------------------------------------------------------------------------- +void vtkImageButterworthHighPass::SetXCutOff(double cutOff) +{ + if (cutOff == this->CutOff[0]) + { + return; + } + this->CutOff[0] = cutOff; + this->Modified(); +} +//---------------------------------------------------------------------------- +void vtkImageButterworthHighPass::SetYCutOff(double cutOff) +{ + if (cutOff == this->CutOff[1]) + { + return; + } + this->CutOff[1] = cutOff; + this->Modified(); +} +//---------------------------------------------------------------------------- +void vtkImageButterworthHighPass::SetZCutOff(double cutOff) +{ + if (cutOff == this->CutOff[2]) + { + return; + } + this->CutOff[2] = cutOff; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageButterworthHighPass::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int ext[6], int id) +{ + int idx0, idx1, idx2; + int min0, max0; + double *inPtr; + double *outPtr; + int wholeExtent[6]; + double spacing[3]; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + double temp0, temp1, temp2, mid0, mid1, mid2; + // normalization factors + double norm0, norm1, norm2; + double sum1, sum0; + unsigned long count = 0; + unsigned long target; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // Error checking + if (inData[0][0]->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro("Expecting 2 components not " + << inData[0][0]->GetNumberOfScalarComponents()); + return; + } + if (inData[0][0]->GetScalarType() != VTK_DOUBLE || + outData[0]->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Expecting input and output to be of type double"); + return; + } + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + inData[0][0]->GetSpacing(spacing); + + inPtr = (double *)(inData[0][0]->GetScalarPointerForExtent(ext)); + outPtr = (double *)(outData[0]->GetScalarPointerForExtent(ext)); + + inData[0][0]->GetContinuousIncrements(ext, inInc0, inInc1, inInc2); + outData[0]->GetContinuousIncrements(ext, outInc0, outInc1, outInc2); + + min0 = ext[0]; + max0 = ext[1]; + mid0 = (double)(wholeExtent[0] + wholeExtent[1] + 1) / 2.0; + mid1 = (double)(wholeExtent[2] + wholeExtent[3] + 1) / 2.0; + mid2 = (double)(wholeExtent[4] + wholeExtent[5] + 1) / 2.0; + if ( this->CutOff[0] == 0.0) + { + norm0 = VTK_FLOAT_MAX; + } + else + { + norm0 = 1.0 / ((spacing[0] * 2.0 * mid0) * this->CutOff[0]); + } + if ( this->CutOff[1] == 0.0) + { + norm1 = VTK_FLOAT_MAX; + } + else + { + norm1 = 1.0 / ((spacing[1] * 2.0 * mid1) * this->CutOff[1]); + } + if ( this->CutOff[2] == 0.0) + { + norm2 = VTK_FLOAT_MAX; + } + else + { + norm2 = 1.0 / ((spacing[2] * 2.0 * mid2) * this->CutOff[2]); + } + + target = (unsigned long)((ext[5]-ext[4]+1)*(ext[3]-ext[2]+1)/50.0); + target++; + + // loop over all the pixels (keeping track of normalized distance to origin. + for (idx2 = ext[4]; idx2 <= ext[5]; ++idx2) + { + // distance to min (this axis' contribution) + temp2 = (double)idx2; + // Wrap back to 0. + if (temp2 > mid2) + { + temp2 = mid2 + mid2 - temp2; + } + // Convert location into normalized cycles/world unit + temp2 = temp2 * norm2; + + for (idx1 = ext[2]; !this->AbortExecute && idx1 <= ext[3]; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + } + // distance to min (this axis' contribution) + temp1 = (double)idx1; + // Wrap back to 0. + if (temp1 > mid1) + { + temp1 = mid1 + mid1 - temp1; + } + // Convert location into cycles / world unit + temp1 = temp1 * norm1; + sum1 = temp2 * temp2 + temp1 * temp1; + + for (idx0 = min0; idx0 <= max0; ++idx0) + { + // distance to min (this axis' contribution) + temp0 = (double)idx0; + // Wrap back to 0. + if (temp0 > mid0) + { + temp0 = mid0 + mid0 - temp0; + } + // Convert location into cycles / world unit + temp0 = temp0 * norm0; + sum0 = sum1 + temp0 * temp0; + + // compute Butterworth1D function from sum = d^2 + if (sum0 == 0.0) + { + sum0 = VTK_FLOAT_MAX; + } + else + { + sum0 = 1.0 / sum0; + } + if (this->Order == 1) + { + sum0 = 1.0 / (1.0 + sum0); + } + else + { + sum0 = 1.0 / (1.0 + pow(sum0, (double)this->Order)); + } + + // real component + *outPtr++ = *inPtr++ * sum0; + // imaginary component + *outPtr++ = *inPtr++ * sum0; + + } + inPtr += inInc1; + outPtr += outInc1; + } + inPtr += inInc2; + outPtr += outInc2; + } +} + +void vtkImageButterworthHighPass::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Order: " << this->Order << "\n"; + + os << indent << "CutOff: ( " + << this->CutOff[0] << ", " + << this->CutOff[1] << ", " + << this->CutOff[2] << " )\n"; + +} + diff --git a/Imaging/vtkImageButterworthHighPass.h b/Imaging/vtkImageButterworthHighPass.h new file mode 100644 index 0000000..9b289de --- /dev/null +++ b/Imaging/vtkImageButterworthHighPass.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageButterworthHighPass.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageButterworthHighPass - Frequency domain high pass. +// .SECTION Description +// This filter only works on an image after it has been converted to +// frequency domain by a vtkImageFFT filter. A vtkImageRFFT filter +// can be used to convert the output back into the spatial domain. +// vtkImageButterworthHighPass the frequency components around 0 are +// attenuated. Input and output are in doubles, with two components +// (complex numbers). +// out(i, j) = 1 / (1 + pow(CutOff/Freq(i,j), 2*Order)); + +// .SECTION See Also +// vtkImageButterworthLowPass + +#ifndef __vtkImageButterworthHighPass_h +#define __vtkImageButterworthHighPass_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageButterworthHighPass : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageButterworthHighPass *New(); + vtkTypeRevisionMacro(vtkImageButterworthHighPass,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the cutoff frequency for each axis. + // The values are specified in the order X, Y, Z, Time. + // Units: Cycles per world unit (as defined by the data spacing). + vtkSetVector3Macro(CutOff,double); + void SetCutOff(double v) {this->SetCutOff(v, v, v);} + void SetXCutOff(double v); + void SetYCutOff(double v); + void SetZCutOff(double v); + vtkGetVector3Macro(CutOff,double); + double GetXCutOff() {return this->CutOff[0];} + double GetYCutOff() {return this->CutOff[1];} + double GetZCutOff() {return this->CutOff[2];} + + // Description: + // The order determines sharpness of the cutoff curve. + vtkSetMacro(Order, int); + vtkGetMacro(Order, int); + +protected: + vtkImageButterworthHighPass(); + ~vtkImageButterworthHighPass() {}; + + int Order; + double CutOff[3]; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); +private: + vtkImageButterworthHighPass(const vtkImageButterworthHighPass&); // Not implemented. + void operator=(const vtkImageButterworthHighPass&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageButterworthLowPass.cxx b/Imaging/vtkImageButterworthLowPass.cxx new file mode 100644 index 0000000..0a479ff --- /dev/null +++ b/Imaging/vtkImageButterworthLowPass.cxx @@ -0,0 +1,231 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageButterworthLowPass.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageButterworthLowPass.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageButterworthLowPass, "$Revision: 1.27 $"); +vtkStandardNewMacro(vtkImageButterworthLowPass); + +//---------------------------------------------------------------------------- +vtkImageButterworthLowPass::vtkImageButterworthLowPass() +{ + this->CutOff[0] = this->CutOff[1] = this->CutOff[2] = VTK_FLOAT_MAX; + this->Order = 1; +} + + +//---------------------------------------------------------------------------- +void vtkImageButterworthLowPass::SetXCutOff(double cutOff) +{ + if (cutOff == this->CutOff[0]) + { + return; + } + this->CutOff[0] = cutOff; + this->Modified(); +} +//---------------------------------------------------------------------------- +void vtkImageButterworthLowPass::SetYCutOff(double cutOff) +{ + if (cutOff == this->CutOff[1]) + { + return; + } + this->CutOff[1] = cutOff; + this->Modified(); +} +//---------------------------------------------------------------------------- +void vtkImageButterworthLowPass::SetZCutOff(double cutOff) +{ + if (cutOff == this->CutOff[2]) + { + return; + } + this->CutOff[2] = cutOff; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageButterworthLowPass::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int ext[6], int id) +{ + int idx0, idx1, idx2; + int min0, max0; + double *inPtr; + double *outPtr; + int wholeExtent[6]; + double spacing[3]; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + double temp0, temp1, temp2, mid0, mid1, mid2; + // normalization factors + double norm0, norm1, norm2; + double sum1, sum0; + unsigned long count = 0; + unsigned long target; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // Error checking + if (inData[0][0]->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro("Expecting 2 components not " + << inData[0][0]->GetNumberOfScalarComponents()); + return; + } + if (inData[0][0]->GetScalarType() != VTK_DOUBLE || + outData[0]->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Expecting input and output to be of type double"); + return; + } + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + inData[0][0]->GetSpacing(spacing); + + inPtr = (double *)(inData[0][0]->GetScalarPointerForExtent(ext)); + outPtr = (double *)(outData[0]->GetScalarPointerForExtent(ext)); + + inData[0][0]->GetContinuousIncrements(ext, inInc0, inInc1, inInc2); + outData[0]->GetContinuousIncrements(ext, outInc0, outInc1, outInc2); + + min0 = ext[0]; + max0 = ext[1]; + mid0 = (double)(wholeExtent[0] + wholeExtent[1] + 1) / 2.0; + mid1 = (double)(wholeExtent[2] + wholeExtent[3] + 1) / 2.0; + mid2 = (double)(wholeExtent[4] + wholeExtent[5] + 1) / 2.0; + if ( this->CutOff[0] == 0.0) + { + norm0 = VTK_FLOAT_MAX; + } + else + { + norm0 = 1.0 / ((spacing[0] * 2.0 * mid0) * this->CutOff[0]); + } + if ( this->CutOff[1] == 0.0) + { + norm1 = VTK_FLOAT_MAX; + } + else + { + norm1 = 1.0 / ((spacing[1] * 2.0 * mid1) * this->CutOff[1]); + } + if ( this->CutOff[2] == 0.0) + { + norm2 = VTK_FLOAT_MAX; + } + else + { + norm2 = 1.0 / ((spacing[2] * 2.0 * mid2) * this->CutOff[2]); + } + + target = (unsigned long)((ext[5]-ext[4]+1)*(ext[3]-ext[2]+1)/50.0); + target++; + + // loop over all the pixels (keeping track of normalized distance to origin. + for (idx2 = ext[4]; idx2 <= ext[5]; ++idx2) + { + // distance to min (this axis' contribution) + temp2 = (double)idx2; + // Wrap back to 0. + if (temp2 > mid2) + { + temp2 = mid2 + mid2 - temp2; + } + // Convert location into normalized cycles/world unit + temp2 = temp2 * norm2; + + for (idx1 = ext[2]; !this->AbortExecute && idx1 <= ext[3]; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + } + // distance to min (this axis' contribution) + temp1 = (double)idx1; + // Wrap back to 0. + if (temp1 > mid1) + { + temp1 = mid1 + mid1 - temp1; + } + // Convert location into cycles / world unit + temp1 = temp1 * norm1; + sum1 = temp2 * temp2 + temp1 * temp1; + + for (idx0 = min0; idx0 <= max0; ++idx0) + { + // distance to min (this axis' contribution) + temp0 = (double)idx0; + // Wrap back to 0. + if (temp0 > mid0) + { + temp0 = mid0 + mid0 - temp0; + } + // Convert location into cycles / world unit + temp0 = temp0 * norm0; + sum0 = sum1 + temp0 * temp0; + + // compute Butterworth1D function from sum = d^2 + if (this->Order == 1) + { + sum0 = 1.0 / (1.0 + sum0); + } + else + { + sum0 = 1.0 / (1.0 + pow(sum0, (double)this->Order)); + } + + // real component + *outPtr++ = *inPtr++ * sum0; + // imaginary component + *outPtr++ = *inPtr++ * sum0; + + } + inPtr += inInc1; + outPtr += outInc1; + } + inPtr += inInc2; + outPtr += outInc2; + } +} + +void vtkImageButterworthLowPass::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Order: " << this->Order << "\n"; + + os << indent << "CutOff: ( " + << this->CutOff[0] << ", " + << this->CutOff[1] << ", " + << this->CutOff[2] << " )\n"; +} + diff --git a/Imaging/vtkImageButterworthLowPass.h b/Imaging/vtkImageButterworthLowPass.h new file mode 100644 index 0000000..8d6e76d --- /dev/null +++ b/Imaging/vtkImageButterworthLowPass.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageButterworthLowPass.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageButterworthLowPass - Frequency domain Low pass. +// .SECTION Description +// This filter only works on an image after it has been converted to +// frequency domain by a vtkImageFFT filter. A vtkImageRFFT filter +// can be used to convert the output back into the spatial domain. +// vtkImageButterworthLowPass the high frequency components are +// attenuated. Input and output are in doubles, with two components +// (complex numbers). +// out(i, j) = (1 + pow(CutOff/Freq(i,j), 2*Order)); + +// .SECTION See Also +// vtkImageButterworthHighPass vtkImageFFT vtkImageRFFT + +#ifndef __vtkImageButterworthLowPass_h +#define __vtkImageButterworthLowPass_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageButterworthLowPass : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageButterworthLowPass *New(); + vtkTypeRevisionMacro(vtkImageButterworthLowPass,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the cutoff frequency for each axis. + // The values are specified in the order X, Y, Z, Time. + // Units: Cycles per world unit (as defined by the data spacing). + vtkSetVector3Macro(CutOff,double); + void SetCutOff(double v) {this->SetCutOff(v, v, v);} + void SetXCutOff(double v); + void SetYCutOff(double v); + void SetZCutOff(double v); + vtkGetVector3Macro(CutOff,double); + double GetXCutOff() {return this->CutOff[0];} + double GetYCutOff() {return this->CutOff[1];} + double GetZCutOff() {return this->CutOff[2];} + + // Description: + // The order determines sharpness of the cutoff curve. + vtkSetMacro(Order, int); + vtkGetMacro(Order, int); + + +protected: + vtkImageButterworthLowPass(); + ~vtkImageButterworthLowPass() {}; + + int Order; + double CutOff[3]; + + void ThreadedRequestData( vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); +private: + vtkImageButterworthLowPass(const vtkImageButterworthLowPass&); // Not implemented. + void operator=(const vtkImageButterworthLowPass&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageCacheFilter.cxx b/Imaging/vtkImageCacheFilter.cxx new file mode 100644 index 0000000..1ad4a26 --- /dev/null +++ b/Imaging/vtkImageCacheFilter.cxx @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCacheFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageCacheFilter.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkCachedStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageCacheFilter, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkImageCacheFilter); + +//---------------------------------------------------------------------------- +vtkImageCacheFilter::vtkImageCacheFilter() +{ + vtkExecutive *exec = this->CreateDefaultExecutive(); + this->SetExecutive(exec); + exec->Delete(); + + this->SetCacheSize(10); +} + +//---------------------------------------------------------------------------- +vtkImageCacheFilter::~vtkImageCacheFilter() +{ +} + +//---------------------------------------------------------------------------- +vtkExecutive* vtkImageCacheFilter::CreateDefaultExecutive() +{ + return vtkCachedStreamingDemandDrivenPipeline::New(); +} + +//---------------------------------------------------------------------------- +void vtkImageCacheFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "CacheSize: " << this->GetCacheSize() << endl; +} + +//---------------------------------------------------------------------------- +void vtkImageCacheFilter::SetCacheSize(int size) +{ + vtkCachedStreamingDemandDrivenPipeline *csddp = + vtkCachedStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); + if (csddp) + { + csddp->SetCacheSize(size); + } +} + +//---------------------------------------------------------------------------- +int vtkImageCacheFilter::GetCacheSize() +{ + vtkCachedStreamingDemandDrivenPipeline *csddp = + vtkCachedStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); + if (csddp) + { + return csddp->GetCacheSize(); + } + return 0; +} + +//---------------------------------------------------------------------------- +// This method simply copies by reference the input data to the output. +void vtkImageCacheFilter::ExecuteData(vtkDataObject *) +{ + // do nothing just override superclass to prevent warning +} diff --git a/Imaging/vtkImageCacheFilter.h b/Imaging/vtkImageCacheFilter.h new file mode 100644 index 0000000..c6f0360 --- /dev/null +++ b/Imaging/vtkImageCacheFilter.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCacheFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageCacheFilter - Caches multiple vtkImageData objects. + +// .SECTION Description +// vtkImageCacheFilter keep a number of vtkImageDataObjects from previous +// updates to satisfy future updates without needing to update the input. It +// does not change the data at all. It just makes the pipeline more +// efficient at the expense of using extra memory. + +#ifndef __vtkImageCacheFilter_h +#define __vtkImageCacheFilter_h + +#include "vtkImageAlgorithm.h" + +class vtkExecutive; + +class VTK_IMAGING_EXPORT vtkImageCacheFilter : public vtkImageAlgorithm +{ +public: + static vtkImageCacheFilter *New(); + vtkTypeRevisionMacro(vtkImageCacheFilter,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is the maximum number of images that can be retained in memory. + // it defaults to 10. + void SetCacheSize(int size); + int GetCacheSize(); + +protected: + vtkImageCacheFilter(); + ~vtkImageCacheFilter(); + + // Create a default executive. + virtual vtkExecutive* CreateDefaultExecutive(); + virtual void ExecuteData(vtkDataObject *); + +private: + vtkImageCacheFilter(const vtkImageCacheFilter&); // Not implemented. + void operator=(const vtkImageCacheFilter&); // Not implemented. +}; + + + +#endif + + + diff --git a/Imaging/vtkImageCanvasSource2D.cxx b/Imaging/vtkImageCanvasSource2D.cxx new file mode 100644 index 0000000..a697848 --- /dev/null +++ b/Imaging/vtkImageCanvasSource2D.cxx @@ -0,0 +1,1617 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCanvasSource2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageCanvasSource2D.h" + +#include "vtkImageCast.h" +#include "vtkImageClip.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkImageData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +// +// Special classes for manipulating data +// +// For the fill functionality (use connector ??) +class vtkImageCanvasSource2DPixel { //;prevent man page generation +public: + static vtkImageCanvasSource2DPixel *New() + { return new vtkImageCanvasSource2DPixel ;} + int X; + int Y; + void *Pointer; + vtkImageCanvasSource2DPixel *Next; +}; + + + +vtkCxxRevisionMacro(vtkImageCanvasSource2D, "$Revision: 1.44.4.1 $"); +vtkStandardNewMacro(vtkImageCanvasSource2D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageCanvasSource2D with no data. +vtkImageCanvasSource2D::vtkImageCanvasSource2D() +{ + this->SetNumberOfInputPorts(0); + + this->ImageData = vtkImageData::New(); + this->ImageData->SetScalarType(VTK_DOUBLE); + + this->WholeExtent[0] = 0; + this->WholeExtent[1] = 0; + this->WholeExtent[2] = 0; + this->WholeExtent[3] = 0; + this->WholeExtent[4] = 0; + this->WholeExtent[5] = 0; + + this->DrawColor[0] = this->DrawColor[1] = + this->DrawColor[2] = this->DrawColor[3] = 0.0; + + this->DefaultZ = 0; + + this->Ratio[0] = this->Ratio[1] = this->Ratio[2] = 1.0; +} + + +//---------------------------------------------------------------------------- +// Destructor: Deleting a vtkImageCanvasSource2D automatically +// deletes the associated +// vtkImageData. However, since the data is reference counted, it may not +// actually be deleted. +vtkImageCanvasSource2D::~vtkImageCanvasSource2D() +{ + this->ImageData->Delete(); +} + + +//---------------------------------------------------------------------------- +void vtkImageCanvasSource2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + + os << indent << "ImageData: (" << this->ImageData << ")\n"; + os << indent << "DefaultZ: " << this->DefaultZ << endl; + os << indent << "DrawColor: (" << this->DrawColor[0]; + for (idx = 1; idx < 4; ++idx) + { + os << ", " << this->DrawColor[idx]; + } + os << ")\n"; + os << indent << "Ratio: (" + << this->Ratio[0] << ", " << this->Ratio[1] << ", " << this->Ratio[2] + << ")\n"; +} + + +#define vtkMAX(x, y) (((x)>(y))?(x):(y)) +#define vtkMIN(x, y) (((x)<(y))?(x):(y)) + +//---------------------------------------------------------------------------- +// Draw a data. Only implentented for 2D extents. +template +void vtkImageCanvasSource2DDrawImage(vtkImageData *image, vtkImageData *simage, + T *ptr, T *sptr, + int min0, int max0, int min1, int max1) +{ + T *ptr0, *ptr1, *ptrV; + T *sptr0, *sptr1, *sptrV; + int idx0, idx1, idxV; + vtkIdType inc0, inc1, inc2; + vtkIdType sinc0, sinc1, sinc2; + int maxV, smaxV; + int sinc; + + image->GetIncrements(inc0, inc1, inc2); + simage->GetIncrements(sinc0, sinc1, sinc2); + + maxV = image->GetNumberOfScalarComponents() - 1; + smaxV = simage->GetNumberOfScalarComponents() - 1; + + ptr1 = ptr; + sptr1 = sptr; + for (idx1 = min1; idx1 <= max1; ++idx1) + { + ptr0 = ptr1; + sptr0 = sptr1; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + ptrV = ptr0; + sptrV = sptr0; + + sinc = 0; + + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = *(sptrV + sinc); + ptrV++; + if ( sinc < smaxV ) + { + sinc++; + } + } + //sptrV += smaxV; + + ptr0 += inc0; + sptr0 += sinc0; + } + ptr1 += inc1; + sptr1 += sinc1; + } +} + +//---------------------------------------------------------------------------- +void vtkImageCanvasSource2D::DrawImage(int x0, int y0, + vtkImageData* image, int sx, int sy, + int width, int height) +{ + if ( !image ) + { + return; + } + + vtkImageClip* clip = vtkImageClip::New(); + clip->SetInput(image); + + int *extent; + int ext[6]; + // int z = this->DefaultZ; + image->GetWholeExtent(ext); + if ( sx < 0 ) + { + sx = ext[0]; + } + if ( sy < 0 ) + { + sy = ext[2]; + } + if ( width < 0 ) + { + width = ext[1] - ext[0] + 1; + } + else + { + width = vtkMIN(width, ext[1] - ext[0] + 1); + } + if ( height < 0 ) + { + height = ext[3] - ext[2] + 1; + } + else + { + height = vtkMIN(height, ext[3] - ext[2] + 1); + } + ext[0] = vtkMAX(sx, ext[0]); + ext[1] = vtkMAX(sx+width-1, ext[1]); + ext[2] = vtkMAX(sy, ext[2]); + ext[3] = vtkMAX(sy+height-1, ext[3]); + clip->SetOutputWholeExtent(ext); + + vtkImageCast* ic = vtkImageCast::New(); + ic->SetInputConnection(clip->GetOutputPort()); + ic->SetOutputScalarType(this->ImageData->GetScalarType()); + ic->Update(); + int min0, max0, min1, max1; + min0 = x0; + min1 = y0; + + max0 = x0 + width -1; + max1 = y0 + height -1; + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + min0 = int(double(min0) * this->Ratio[0]); + max0 = int(double(max0) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + min1 = int(double(min1) * this->Ratio[1]); + max1 = int(double(max1) * this->Ratio[1]); + } +// if (this->Ratio[2] != 1.0) +// { +// z = int(double(z) * this->Ratio[2]); +// } + // Clip the data to keep in in bounds + extent = this->ImageData->GetExtent(); + min0 = (min0 < extent[0]) ? extent[0] : min0; + max0 = (max0 < extent[0]) ? extent[0] : max0; + min0 = (min0 > extent[1]) ? extent[1] : min0; + max0 = (max0 > extent[1]) ? extent[1] : max0; + min1 = (min1 < extent[2]) ? extent[2] : min1; + max1 = (max1 < extent[2]) ? extent[2] : max1; + min1 = (min1 > extent[3]) ? extent[3] : min1; + max1 = (max1 > extent[3]) ? extent[3] : max1; + //z = (z < extent[4]) ? extent[4] : z; + //z = (z > extent[5]) ? extent[5] : z; + void *ptr; + void *sptr; + ptr = this->ImageData->GetScalarPointer(min0, min1, 0); + sptr = ic->GetOutput()->GetScalarPointer(ext[0], ext[2], 0); + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro(vtkImageCanvasSource2DDrawImage(this->ImageData, + ic->GetOutput(), + (VTK_TT *)(ptr), + (VTK_TT *)(sptr), + min0,max0, min1,max1)); + default: + vtkErrorMacro(<< "FillBox: Cannot handle ScalarType."); + } + ic->Delete(); + clip->Delete(); + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Draw a data. Only implentented for 2D extents. +template +void vtkImageCanvasSource2DFillBox(vtkImageData *image, + double *drawColor, T *ptr, + int min0, int max0, int min1, int max1) +{ + T *ptr0, *ptr1, *ptrV; + int idx0, idx1, idxV; + vtkIdType inc0, inc1, inc2; + int maxV; + double *pf; + + image->GetIncrements(inc0, inc1, inc2); + maxV = image->GetNumberOfScalarComponents() - 1; + + ptr1 = ptr; + for (idx1 = min1; idx1 <= max1; ++idx1) + { + ptr0 = ptr1; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + ptrV = ptr0; + pf = drawColor; + + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = (T)(*pf++); + ptrV++; + } + + ptr0 += inc0; + } + ptr1 += inc1; + } +} + +//---------------------------------------------------------------------------- +// Draw a data. Only implentented for 2D extents. +void vtkImageCanvasSource2D::FillBox(int min0, int max0, int min1, int max1) +{ + int *extent; + void *ptr; + int z = this->DefaultZ; + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + min0 = int(double(min0) * this->Ratio[0]); + max0 = int(double(max0) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + min1 = int(double(min1) * this->Ratio[1]); + max1 = int(double(max1) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + z = int(double(z) * this->Ratio[2]); + } + + // Clip the data to keep in in bounds + extent = this->ImageData->GetExtent(); + min0 = (min0 < extent[0]) ? extent[0] : min0; + max0 = (max0 < extent[0]) ? extent[0] : max0; + min0 = (min0 > extent[1]) ? extent[1] : min0; + max0 = (max0 > extent[1]) ? extent[1] : max0; + min1 = (min1 < extent[2]) ? extent[2] : min1; + max1 = (max1 < extent[2]) ? extent[2] : max1; + min1 = (min1 > extent[3]) ? extent[3] : min1; + max1 = (max1 > extent[3]) ? extent[3] : max1; + z = (z < extent[4]) ? extent[4] : z; + z = (z > extent[5]) ? extent[5] : z; + + ptr = this->ImageData->GetScalarPointer(min0, min1, z); + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro(vtkImageCanvasSource2DFillBox(this->ImageData, + this->DrawColor, + (VTK_TT *)(ptr), + min0,max0, min1,max1)); + default: + vtkErrorMacro(<< "FillBox: Cannot handle ScalarType."); + } + this->Modified(); +} + + + +//---------------------------------------------------------------------------- +// Fill a tube (thick line for initial 2D implementation. +template +void vtkImageCanvasSource2DFillTube(vtkImageData *image, + double *drawColor, T *ptr, + int a0, int a1, int b0, int b1, + double radius) +{ + T *ptr0, *ptr1, *ptrV; + int idx0, idx1, idxV; + vtkIdType inc0, inc1, inc2; + int min0, max0, min1, max1, min2, max2, maxV; + double *pf; + int n0, n1; + int ak, bk, k; + double fract; + double v0, v1; + + // Compute vector of tube. + n0 = a0 - b0; + n1 = a1 - b1; + // compute the projects of the two points a and b on this vector. + ak = n0 * a0 + n1 * a1; + bk = n0 * b0 + n1 * b1; + // Make sure the vector is pointing in the correct direction. + if (ak < bk) + { + ak = -ak; + bk = -bk; + n0 = -n0; + n1 = -n1; + } + + image->GetExtent(min0, max0, min1, max1, min2, max2); + maxV = image->GetNumberOfScalarComponents() - 1; + // Loop trough whole extent. + image->GetIncrements(inc0, inc1, inc2); + ptr1 = ptr; + for (idx1 = min1; idx1 <= max1; ++idx1) + { + ptr0 = ptr1; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + // check to see if pixel is in the tube. + // project point onto normal vector. + k = n0 * idx0 + n1 * idx1; + // Check that point is inbetween end points. + if ( k >= bk && k <= ak) + { + // Compute actual projection point. + fract = (double)(k - bk) / (double)(ak - bk); + v0 = b0 + fract * (double)(a0 - b0); + v1 = b1 + fract * (double)(a1 - b1); + // Compute distance to tube + v0 -= (double)(idx0); + v1 -= (double)(idx1); + if (radius >= sqrt(v0*v0 + v1*v1)) + { + ptrV = ptr0; + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = (T)(*pf++); + ptrV++; + } + } + } + + ptr0 += inc0; + } + ptr1 += inc1; + } +} + +//---------------------------------------------------------------------------- +// Fill a tube (thick line for initial 2D implementation). +void vtkImageCanvasSource2D::FillTube(int a0, int a1, + int b0, int b1, double radius) +{ + void *ptr; + int z = this->DefaultZ; + int *extent = this->ImageData->GetExtent(); + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + a0 = int(double(a0) * this->Ratio[0]); + b0 = int(double(b0) * this->Ratio[0]); + radius = int(double(radius) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + a1 = int(double(a1) * this->Ratio[1]); + b1 = int(double(b1) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + z = int(double(z) * this->Ratio[2]); + } + + z = (z < extent[4]) ? extent[4] : z; + z = (z > extent[5]) ? extent[5] : z; + + ptr = this->ImageData->GetScalarPointer(extent[0], extent[2], z); + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCanvasSource2DFillTube(this->ImageData, + this->DrawColor, + (VTK_TT *)(ptr), + a0,a1, b0,b1, + radius)); + default: + vtkErrorMacro(<< "FillTube: Cannot handle ScalarType."); + } + this->Modified(); +} + + + + + +//---------------------------------------------------------------------------- +// Fill a triangle (rasterize) +template +void vtkImageCanvasSource2DFillTriangle(vtkImageData *image, + double *drawColor, T *ptr, + int a0, int a1, int b0, int b1, + int c0, int c1, int z) +{ + int temp; + double longT, shortT; // end points of intersection of trainge and row. + double longStep, shortStep; + int left, right; + int idx0, idx1, idxV; + int min0, max0, min1, max1, min2, max2; + int maxV; + double *pf; + + maxV = image->GetNumberOfScalarComponents() - 1; + + // index1 of b must be between a, and c + if((b1 < a1 && a1 < c1) || (b1 > a1 && a1 > c1)) + { // swap b and a + temp = b0; b0 = a0; a0 = temp; + temp = b1; b1 = a1; a1 = temp; + } + if((b1 < c1 && c1 < a1) || (b1 > c1 && c1 > a1)) + { // swap b and c + temp = b0; b0 = c0; c0 = temp; + temp = b1; b1 = c1; c1 = temp; + } + // Make life easier and order points so that ay < by < cy + if(c1 < a1) + { // swap c and a + temp = a0; a0 = c0; c0 = temp; + temp = a1; a1 = c1; c1 = temp; + } + + image->GetExtent(min0, max0, min1, max1, min2, max2); + z = (z < min2) ? min2 : z; + z = (z > max2) ? max2 : z; + + // for all rows: compute 2 points, intersection of triangle edges and row + longStep = (double)(c0 - a0) / (double)(c1 - a1 + 1); + longT = (double)(a0) + (0.5 * longStep); + shortStep = (double)(b0 - a0) / (double)(b1 - a1 + 1); + shortT = (double)(a0) + (0.5 * shortStep); + for (idx1 = a1; idx1 < b1; ++idx1) + { + // Fill row long to short (y = idx1) + left = (int)(shortT + 0.5); + right = (int)(longT + 0.5); + if (left > right) + { + temp = left; left = right; right = temp; + } + for (idx0 = left; idx0 <= right; ++idx0) + { + if (idx0 >= min0 && idx0 <= max0 && idx1 >= min1 && idx1 <= max1) + { + ptr = (T *)(image->GetScalarPointer(idx0, idx1, z)); + if (ptr) + { + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptr = (T)(*pf++); + ptr++; + } + } + } + } + + longT += longStep; + shortT += shortStep; + } + + // fill the second half of the triangle + shortStep = (double)(c0 - b0) / (double)(c1 - b1 + 1); + shortT = (double)(b0) + (0.5 * shortStep); + for (idx1 = b1; idx1 < c1; ++idx1) + { + // Fill row long to short (y = idx1) + left = (int)(shortT + 0.5); + right = (int)(longT + 0.5); + if (left > right) + { + temp = left; left = right; right = temp; + } + for (idx0 = left; idx0 <= right; ++idx0) + { + if (idx0 >= min0 && idx0 <= max0 && idx1 >= min1 && idx1 <= max1) + { + ptr = (T *)(image->GetScalarPointer(idx0, idx1, z)); + if (ptr) + { + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptr = (T)(*pf++); + ptr++; + } + } + } + } + + longT += longStep; + shortT += shortStep; + } +} + +//---------------------------------------------------------------------------- +// Fill a tube (thick line for initial 2D implementation). +void vtkImageCanvasSource2D::FillTriangle(int a0,int a1, int b0,int b1, + int c0,int c1) +{ + void *ptr; + int z = this->DefaultZ; + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + a0 = int(double(a0) * this->Ratio[0]); + b0 = int(double(b0) * this->Ratio[0]); + c0 = int(double(c0) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + a1 = int(double(a1) * this->Ratio[1]); + b1 = int(double(b1) * this->Ratio[1]); + c1 = int(double(c1) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + z = int(double(z) * this->Ratio[2]); + } + + ptr = this->ImageData->GetScalarPointer(); + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCanvasSource2DFillTriangle(this->ImageData, + this->DrawColor, (VTK_TT *)(ptr), + a0,a1, b0,b1, c0,c1, z)); + default: + vtkErrorMacro(<< "FillTriangle: Cannot handle ScalarType."); + } + this->Modified(); +} + + + + + +//---------------------------------------------------------------------------- +// Draw a point. Only implentented for 2D images. +template +void vtkImageCanvasSource2DDrawPoint(vtkImageData *image, + double *drawColor, T *ptr, + int p0, int p1, int z) +{ + int min0, max0, min1, max1, min2, max2, maxV; + int idxV; + double *pf; + + image->GetExtent(min0, max0, min1, max1, min2, max2); + z = (z < min2) ? min2 : z; + z = (z > max2) ? max2 : z; + maxV = image->GetNumberOfScalarComponents() - 1; + + if (p0 >= min0 && p0 <= max0 && p1 >= min1 && p1 <= max1) + { + ptr = (T *)(image->GetScalarPointer(p0, p1, z)); + + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptr = (T)(*pf++); + ptr++; + } + + } +} + + + +//---------------------------------------------------------------------------- +// Draw a circle +void vtkImageCanvasSource2D::DrawPoint(int p0, int p1) +{ + void *ptr = NULL; + int z = this->DefaultZ; + + vtkDebugMacro(<< "Drawing a point: (" << p0 << ", " << p1 << ")"); + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + p0 = int(double(p0) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + p1 = int(double(p1) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + z = int(double(z) * this->Ratio[2]); + } + + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCanvasSource2DDrawPoint(this->ImageData, + this->DrawColor, + (VTK_TT *)(ptr), + p0, p1, + z)); + default: + vtkErrorMacro(<< "DrawPoint: Cannot handle ScalarType."); + } + this->Modified(); +} + + + +//---------------------------------------------------------------------------- +// Draw a circle. Only implentented for 2D images. +template +void vtkImageCanvasSource2DDrawCircle(vtkImageData *image, + double *drawColor, T *ptr, + int c0, int c1, double radius, int z) +{ + int min0, max0, min1, max1, min2, max2, maxV; + int idxV; + double *pf; + int numberOfSteps; + double thetaCos, thetaSin; + double x, y, temp; + int p0, p1; + int idx; + + radius += 0.1; + image->GetExtent(min0, max0, min1, max1, min2, max2); + z = (z < min2) ? min2 : z; + z = (z > max2) ? max2 : z; + maxV = image->GetNumberOfScalarComponents() - 1; + + numberOfSteps = (int)(ceil(6.2831853 * radius)); + thetaCos = cos(1.0 / radius); + thetaSin = sin(1.0 / radius); + x = radius; + y = 0.0; + + for (idx = 0; idx < numberOfSteps; ++idx) + { + p0 = c0+(int)(x); + p1 = c1+(int)(y); + if (p0 >= min0 && p0 <= max0 && p1 >= min1 && p1 <= max1) + { + ptr = (T *)(image->GetScalarPointer(p0, p1, z)); + + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptr = (T)(*pf++); + ptr++; + } + + } + + // rotate the point + temp = thetaCos * x + thetaSin * y; + y = thetaCos * y - thetaSin * x; + x = temp; + } +} + + +//---------------------------------------------------------------------------- +// Draw a circle +void vtkImageCanvasSource2D::DrawCircle(int c0, int c1, double radius) +{ + void *ptr = NULL; + int z = this->DefaultZ; + + vtkDebugMacro(<< "Drawing a circle: center = (" << c0 << ", " << c1 + << "), radius = " << radius); + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + c0 = int(double(c0) * this->Ratio[0]); + radius = int(double(radius) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + c1 = int(double(c1) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + z = int(double(z) * this->Ratio[2]); + } + + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCanvasSource2DDrawCircle(this->ImageData, + this->DrawColor, + (VTK_TT *)(ptr), + c0, c1, + radius, + z)); + default: + vtkErrorMacro(<< "DrawCircle: Cannot handle ScalarType."); + } + this->Modified(); +} + + + +//---------------------------------------------------------------------------- +// Draw a line. Only implentented for 2D images. +// First point is already shifted to origin. +template +void vtkImageCanvasSource2DDrawSegment(vtkImageData *image, + double *drawColor, T *ptr, + int p0, int p1) +{ + double f0, f1; + double s0, s1; + int numberOfSteps; + int maxV; + int idx, idxV; + vtkIdType inc0, inc1, inc2; + double *pf; + T *ptrV; + + + image->GetIncrements(inc0, inc1, inc2); + maxV = image->GetNumberOfScalarComponents() - 1; + + // make sure we are stepping in the positive direction. + if (p0 < 0) + { + p0 = -p0; + inc0 = -inc0; + } + if (p1 < 0) + { + p1 = -p1; + inc1 = -inc1; + } + + // Compute the number of steps needed. + if (p0 > p1) + { + numberOfSteps = p0; + } + else + { + numberOfSteps = p1; + } + + // Compute the step vector. + s0 = (double)(p0) / (double)(numberOfSteps); + s1 = (double)(p1) / (double)(numberOfSteps); + + f0 = f1 = 0.5; + + ptrV = ptr; + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = (T)(*pf++); + ptrV++; + } + + + for (idx = 0; idx < numberOfSteps; ++idx) + { + f0 += s0; + if (f0 > 1.0) + { + ptr += inc0; + f0 -= 1.0; + } + f1 += s1; + if (f1 > 1.0) + { + ptr += inc1; + f1 -= 1.0; + } + + ptrV = ptr; + pf = drawColor; + + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = (T)(*pf++); + ptrV++; + } + + + } +} + + +//---------------------------------------------------------------------------- +// Draw a Segment from point a to point b. +void vtkImageCanvasSource2D::DrawSegment(int a0, int a1, int b0, int b1) +{ + int *extent; + void *ptr; + int z = this->DefaultZ; + + vtkDebugMacro(<< "Drawing a segment: " << a0 << ", " << a1 << " to " + << b0 << ", " << b1); + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + a0 = int(double(a0) * this->Ratio[0]); + b0 = int(double(b0) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + a1 = int(double(a1) * this->Ratio[1]); + b1 = int(double(b1) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + z = int(double(z) * this->Ratio[2]); + } + + // check to make sure line segment is in bounds. + extent = this->ImageData->GetExtent(); + z = (z < extent[4]) ? extent[4] : z; + z = (z > extent[5]) ? extent[5] : z; + if (a0 < extent[0] || a0 > extent[1] || b0 < extent[0] || b0 > extent[1] || + a1 < extent[2] || a1 > extent[3] || b1 < extent[2] || b1 > extent[3]) + { + if ( ! this->ClipSegment(a0,a1,b0,b1)) + { + // non of the segment is in the data. + return; + } + } + + ptr = this->ImageData->GetScalarPointer(b0, b1, z); + a0 -= b0; + a1 -= b1; + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCanvasSource2DDrawSegment(this->ImageData, + this->DrawColor, + (VTK_TT *)(ptr), + a0, a1)); + default: + vtkErrorMacro(<< "DrawSegment: Cannot handle ScalarType."); + } + this->Modified(); +} + + + +//---------------------------------------------------------------------------- +// Clips a line segment so it will be in bounds. +// If the entire segment is out of bounds, the method returns 0. +int vtkImageCanvasSource2D::ClipSegment(int &a0, int &a1, int &b0, int &b1) +{ + int min0, max0, min1, max1, min2, max2; + double fract; + + + this->ImageData->GetExtent(min0, max0, min1, max1, min2, max2); + + // Check planes + // Both out of bounds + if (a0 < min0 && b0 < min0) + { + return 0; + } + // first out of bounds. + if (a0 < min0 && b0 >= min0) + { + // interpolate to find point on bounding plane. + fract = (double)(b0 - min0) / (double)(b0 - a0); + a0 = min0; + a1 = b1 + (int)(fract * (double)(a1 - b1)); + } + // second out of bounds. + if (b0 < min0 && a0 >= min0) + { + // interpolate to find point on bounding plane. + fract = (double)(a0 - min0) / (double)(a0 - b0); + b0 = min0; + b1 = a1 + (int)(fract * (double)(b1 - a1)); + } + + // Both out of bounds + if (a0 > max0 && b0 > max0) + { + return 0; + } + // first out of bounds. + if (a0 > max0 && b0 <= max0) + { + // interpolate to find point on bounding plane. + fract = (double)(b0 - max0) / (double)(b0 - a0); + a0 = max0; + a1 = b1 + (int)(fract * (double)(a1 - b1)); + } + // second out of bounds. + if (b0 > max0 && a0 <= max0) + { + // interpolate to find point on bounding plane. + fract = (double)(a0 - max0) / (double)(a0 - b0); + b0 = max0; + b1 = a1 + (int)(fract * (double)(b1 - a1)); + } + + + // Both out of bounds + if (a1 < min1 && b1 < min1) + { + return 0; + } + // first out of bounds. + if (a1 < min1 && b1 >= min1) + { + // interpolate to find point on bounding plane. + fract = (double)(b1 - min1) / (double)(b1 - a1); + a1 = min1; + a0 = b0 + (int)(fract * (double)(a0 - b0)); + } + // second out of bounds. + if (b1 < min1 && a1 >= min1) + { + // interpolate to find point on bounding plane. + fract = (double)(a1 - min1) / (double)(a1 - b1); + b1 = min1; + b0 = a0 + (int)(fract * (double)(b0 - a0)); + } + + // Both out of bounds + if (a1 > max1 && b1 > max1) + { + return 0; + } + // first out of bounds. + if (a1 > max1 && b1 <= max1) + { + // interpolate to find point on bounding plane. + fract = (double)(b1 - max1) / (double)(b1 - a1); + a1 = max1; + a0 = b0 + (int)(fract * (double)(a0 - b0)); + } + // second out of bounds. + if (b1 > max1 && a1 <= max1) + { + // interpolate to find point on bounding plane. + fract = (double)(a1 - max1) / (double)(a1 - b1); + b1 = max1; + b0 = a0 + (int)(fract * (double)(b0 - a0)); + } + + this->Modified(); + return 1; +} + + + + + + + + + + + +//---------------------------------------------------------------------------- +// Draw a line. Only implentented for 3D images. +// First point is already shifted to origin. +template +void vtkImageCanvasSource2DDrawSegment3D(vtkImageData *image, + double *drawColor, + T *ptr, int p0, int p1, int p2) +{ + double f0, f1, f2; + double s0, s1, s2; + int numberOfSteps; + int idx, idxV, maxV; + vtkIdType inc0, inc1, inc2; + double *pf; + T *ptrV; + + + image->GetIncrements(inc0, inc1, inc2); + maxV = image->GetNumberOfScalarComponents() - 1; + + // make sure we are stepping in the positive direction. + if (p0 < 0) + { + p0 = -p0; + inc0 = -inc0; + } + if (p1 < 0) + { + p1 = -p1; + inc1 = -inc1; + } + if (p2 < 0) + { + p2 = -p2; + inc2 = -inc2; + } + + // Compute the number of steps needed. + numberOfSteps = (p0 > p1) ? p0 : p1; + numberOfSteps = (numberOfSteps > p2) ? numberOfSteps : p2; + + // Compute the step vector. + s0 = (double)(p0) / (double)(numberOfSteps); + s1 = (double)(p1) / (double)(numberOfSteps); + s2 = (double)(p2) / (double)(numberOfSteps); + + f0 = f1 = f2 = 0.5; + + + ptrV = ptr; + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = (T)(*pf++); + ptrV++; + } + + for (idx = 0; idx < numberOfSteps; ++idx) + { + f0 += s0; + if (f0 > 1.0) + { + ptr += inc0; + f0 -= 1.0; + } + f1 += s1; + if (f1 > 1.0) + { + ptr += inc1; + f1 -= 1.0; + } + f2 += s2; + if (f2 > 1.0) + { + ptr += inc2; + f2 -= 1.0; + } + + ptrV = ptr; + pf = drawColor; + // Assign color to pixel. + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = (T)(*pf++); + ptrV++; + } + } +} + + +//---------------------------------------------------------------------------- +// Draw a Segment from point a to point b. +// No clipping or bounds checking. +void vtkImageCanvasSource2D::DrawSegment3D(double *a, double *b) +{ + void *ptr; + int a0, a1, a2; + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + a[0] = int(double(a[0]) * this->Ratio[0]); + b[0] = int(double(b[0]) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + a[1] = int(double(a[1]) * this->Ratio[1]); + b[1] = int(double(b[1]) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + a[2] = int(double(a[2]) * this->Ratio[2]); + b[2] = int(double(b[2]) * this->Ratio[2]); + } + + ptr = this->ImageData->GetScalarPointer((int)(b[0] + 0.5), + (int)(b[1] + 0.5), + (int)(b[2] + 0.5)); + a0 = (int)(a[0] - b[0] + 0.5); + a1 = (int)(a[1] - b[1] + 0.5); + a2 = (int)(a[2] - b[2] + 0.5); + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCanvasSource2DDrawSegment3D(this->ImageData, + this->DrawColor, + (VTK_TT *)(ptr), + a0, a1, a2)); + default: + vtkErrorMacro(<< "DrawSegment3D: Cannot handle ScalarType."); + } + this->Modified(); +} + + + +//---------------------------------------------------------------------------- +template +void vtkImageCanvasSource2DFill(vtkImageData *image, double *color, + T *ptr, int x, int y) +{ + vtkImageCanvasSource2DPixel *pixel; + vtkImageCanvasSource2DPixel *first, *last; + vtkImageCanvasSource2DPixel *heap = NULL; + int min0, max0, min1, max1, min2, max2, maxV; + int idxV; + vtkIdType inc0, inc1, inc2; + T fillColor[10]; + T drawColor[10]; + T *ptrV, *ptrC; + int temp; + + image->GetExtent(min0, max0, min1, max1, min2, max2); + maxV = image->GetNumberOfScalarComponents() - 1; + image->GetIncrements(inc0, inc1, inc2); + + // Copy the fill color and make sure it differs from drawColor. + ptrV = ptr; + temp = 1; + for (idxV = 0; idxV <= maxV; ++idxV) + { + // Save the fill color + fillColor[idxV] = *ptrV; + drawColor[idxV] = (T)(color[idxV]); + if (*ptrV != drawColor[idxV]) + { + temp = 0; + } + ptrV++; + } + if (temp) + { // fill the same as draw + cerr << "Fill: Cannot handle draw color same as fill color\n"; + return; + } + + // Create the seed + pixel = vtkImageCanvasSource2DPixel::New(); + pixel->X = x; + pixel->Y = y; + pixel->Pointer = (void *)(ptr); + pixel->Next = NULL; + first = last = pixel; + // change the seeds color + ptrV = (T *)(last->Pointer); + ptrC = drawColor; + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = *ptrC++; + ptrV++; + } + + + while (first) + { + ptr = (T *)(first->Pointer); + + // check bounds for -x neighbor + if (first->X > min0) + { + // Get the neighbor + ptrV = ptr - inc0; + // compare color + ptrC = fillColor; + temp = 1; + for (idxV = 0; idxV <= maxV; ++idxV) + { + if (*ptrV != *ptrC++) + { + temp = 0; + break; + } + ptrV++; + } + if (temp) + { // color match add a new seed to end of list + if (heap) + { + pixel = heap; + heap = heap->Next; + } + else + { + pixel = vtkImageCanvasSource2DPixel::New(); + } + pixel->X = first->X-1; + pixel->Y = first->Y; + pixel->Pointer = (void *)(ptr - inc0); + pixel->Next = NULL; + last->Next = pixel; + last = pixel; + // change the seeds color + ptrV = (T *)(last->Pointer); + ptrC = drawColor; + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = *ptrC++; + ptrV++; + } + } + } + + // check bounds for +x neighbor + if (first->X < max0) + { + // Get the neighbor + ptrV = ptr + inc0; + // compare color + ptrC = fillColor; + temp = 1; + for (idxV = 0; idxV <= maxV; ++idxV) + { + if (*ptrV != *ptrC++) + { + temp = 0; + break; + } + ptrV++; + } + if (temp) + { // color match add a new seed to end of list + if (heap) + { + pixel = heap; + heap = heap->Next; + } + else + { + pixel = vtkImageCanvasSource2DPixel::New(); + } + pixel->X = first->X+1; + pixel->Y = first->Y; + pixel->Pointer = (void *)(ptr + inc0); + pixel->Next = NULL; + last->Next = pixel; + last = pixel; + // change the seeds color + ptrV = (T *)(last->Pointer); + ptrC = drawColor; + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = *ptrC++; + ptrV++; + } + } + } + + // check bounds for -y neighbor + if (first->Y > min1) + { + // Get the neighbor + ptrV = ptr - inc1; + // compare color + ptrC = fillColor; + temp = 1; + for (idxV = 0; idxV <= maxV; ++idxV) + { + if (*ptrV != *ptrC++) + { + temp = 0; + break; + } + ptrV++; + } + if (temp) + { // color match add a new seed to end of list + if (heap) + { + pixel = heap; + heap = heap->Next; + } + else + { + pixel = vtkImageCanvasSource2DPixel::New(); + } + pixel->X = first->X; + pixel->Y = first->Y-1; + pixel->Pointer = (void *)(ptr - inc1); + pixel->Next = NULL; + last->Next = pixel; + last = pixel; + // change the seeds color + ptrV = (T *)(last->Pointer); + ptrC = drawColor; + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = *ptrC++; + ptrV++; + } + } + } + + // check bounds for +y neighbor + if (first->Y < max1) + { + // Get the neighbor + ptrV = ptr + inc1; + // compare color + ptrC = fillColor; + temp = 1; + for (idxV = 0; idxV <= maxV; ++idxV) + { + if (*ptrV != *ptrC++) + { + temp = 0; + break; + } + ptrV++; + } + if (temp) + { // color match add a new seed to end of list + if (heap) + { + pixel = heap; + heap = heap->Next; + } + else + { + pixel = vtkImageCanvasSource2DPixel::New(); + } + pixel->X = first->X; + pixel->Y = first->Y+1; + pixel->Pointer = (void *)(ptr + inc1); + pixel->Next = NULL; + last->Next = pixel; + last = pixel; + // change the seeds color + ptrV = (T *)(last->Pointer); + ptrC = drawColor; + for (idxV = 0; idxV <= maxV; ++idxV) + { + *ptrV = *ptrC++; + ptrV++; + } + } + } + + // remove the first from the list. + pixel = first; + first = first->Next; + pixel->Next = heap; + heap = pixel; + } + + // free the heap + while (heap) + { + pixel = heap; + heap = heap->Next; + delete pixel; + } +} + + + + + + + + +//---------------------------------------------------------------------------- +// Fill a colored area with another color. (like connectivity) +// All pixels connected to pixel (x, y) get replaced by draw color. +void vtkImageCanvasSource2D::FillPixel(int x, int y) +{ + void *ptr; + int *ext = this->ImageData->GetExtent(); + int z = this->DefaultZ; + + // Pre-multiply coords if needed + if (this->Ratio[0] != 1.0) + { + x = int(double(x) * this->Ratio[0]); + } + if (this->Ratio[1] != 1.0) + { + y = int(double(y) * this->Ratio[1]); + } + if (this->Ratio[2] != 1.0) + { + z = int(double(z) * this->Ratio[2]); + } + + z = (z < ext[4]) ? ext[4] : z; + z = (z > ext[5]) ? ext[5] : z; + + ptr = this->ImageData->GetScalarPointer(x, y, z); + + switch (this->ImageData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCanvasSource2DFill(this->ImageData, + this->DrawColor, + (VTK_TT *)(ptr), + x, y)); + default: + vtkErrorMacro(<< "Fill: Cannot handle ScalarType."); + } + this->Modified(); +} + + + +//---------------------------------------------------------------------------- +void vtkImageCanvasSource2D::SetExtent(int *extent) +{ + this->SetExtent(extent[0], extent[1], + extent[2], extent[3], + extent[4], extent[5]); +} + +//---------------------------------------------------------------------------- +void vtkImageCanvasSource2D::SetExtent(int xMin, int xMax, + int yMin, int yMax, + int zMin, int zMax) + { + int modified = 0; + + if (this->WholeExtent[0] != xMin) + { + modified = 1; + this->WholeExtent[0] = xMin ; + } + if (this->WholeExtent[1] != xMax) + { + modified = 1; + this->WholeExtent[1] = xMax ; + } + if (this->WholeExtent[2] != yMin) + { + modified = 1; + this->WholeExtent[2] = yMin ; + } + if (this->WholeExtent[3] != yMax) + { + modified = 1; + this->WholeExtent[3] = yMax ; + } + if (this->WholeExtent[4] != zMin) + { + modified = 1; + this->WholeExtent[4] = zMin ; + } + if (this->WholeExtent[5] != zMax) + { + modified = 1; + this->WholeExtent[5] = zMax ; + } + if (modified) + { + this->Modified(); + this->ImageData->SetExtent(this->WholeExtent); + this->ImageData->AllocateScalars(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageCanvasSource2D::SetScalarType(int t) +{ + if (this->ImageData->GetScalarType() != t) + { + this->Modified(); + this->ImageData->SetScalarType(t); + this->ImageData->AllocateScalars(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageCanvasSource2D::SetNumberOfScalarComponents(int t) +{ + if (this->ImageData->GetNumberOfScalarComponents() != t) + { + this->Modified(); + this->ImageData->SetNumberOfScalarComponents(t); + this->ImageData->AllocateScalars(); + } +} + + +//---------------------------------------------------------------------------- +int vtkImageCanvasSource2D::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent,6); + + vtkDataObject::SetPointDataActiveScalarInfo + (outInfo, this->ImageData->GetScalarType(), + this->ImageData->GetNumberOfScalarComponents()); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageCanvasSource2D::RequestData ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the data object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *output = vtkImageData::SafeDownCast + (outInfo->Get(vtkDataObject::DATA_OBJECT()) ); + + output->ShallowCopy(this->ImageData); + + return 1; +} diff --git a/Imaging/vtkImageCanvasSource2D.h b/Imaging/vtkImageCanvasSource2D.h new file mode 100644 index 0000000..398d50c --- /dev/null +++ b/Imaging/vtkImageCanvasSource2D.h @@ -0,0 +1,152 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCanvasSource2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageCanvasSource2D - Paints on a canvas +// .SECTION Description +// vtkImageCanvasSource2D is a source that starts as a blank image. +// you may add to the image with two-dimensional drawing routines. +// It can paint multi-spectral images. + + +#ifndef __vtkImageCanvasSource2D_h +#define __vtkImageCanvasSource2D_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageCanvasSource2D : public vtkImageAlgorithm +{ +public: + // Description: + // Construct an instance of vtkImageCanvasSource2D with no data. + static vtkImageCanvasSource2D *New(); + + vtkTypeRevisionMacro(vtkImageCanvasSource2D,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get DrawValue. This is the value that is used when filling data + // or drawing lines. + vtkSetVector4Macro(DrawColor, double); + vtkGetVector4Macro(DrawColor, double); + void SetDrawColor(double a) {this->SetDrawColor(a, 0.0, 0.0, 0.0);} + void SetDrawColor(double a,double b) {this->SetDrawColor(a, b, 0.0, 0.0);} + void SetDrawColor(double a, double b, double c) { + this->SetDrawColor(a, b, c, 0.0);} + + void FillBox(int min0, int max0, int min1, int max1); + void FillTube(int x0, int y0, int x1, int y1, double radius); + void FillTriangle(int x0, int y0, int x1, int y1, int x2, int y2); + void DrawCircle(int c0, int c1, double radius); + void DrawPoint(int p0, int p1); + void DrawSegment(int x0, int y0, int x1, int y1); + void DrawSegment3D(double *p0, double *p1); + void DrawSegment3D(double x1, double y1, double z1, + double x2, double y2, double z2) + { double p1[3], p2[3]; + p1[0] = x1; p1[1] = y1; p1[2] = z1; p2[0] = x2; p2[1] = y2; p2[2] = z2; + this->DrawSegment3D(p1, p2);} + + // Description: + // Draw subimage of the input image in the canvas at position x0 and + // y0. The subimage is defined with sx, sy, width, and height. + void DrawImage(int x0, int y0, vtkImageData* i) + { this->DrawImage(x0, y0, i, -1, -1, -1, -1); } + void DrawImage(int x0, int y0, vtkImageData*, int sx, int sy, + int width, int height); + + // Description: + // Fill a colored area with another color. (like connectivity) + // All pixels connected (and with the same value) to pixel (x, y) + // get replaced by the current "DrawColor". + void FillPixel(int x, int y); + + // Description: + // These methods set the WholeExtent of the output + // It sets the size of the canvas. + // Extent is a min max 3D box. Minimums and maximums are inclusive. + void SetExtent(int *extent); + void SetExtent(int x1, int x2, int y1, int y2, int z1, int z2); + + // Description: + // The drawing operations can only draw into one 2D XY plane at a time. + // If the canvas is a 3D volume, then this z value is used + // as the default for 2D operations. + vtkSetMacro(DefaultZ, int); + vtkGetMacro(DefaultZ, int); + + // Description: + // Set/Get Ratio. This is the value that is used to pre-multiply each + // (x, y, z) drawing coordinates (including DefaultZ). + vtkSetVector3Macro(Ratio, double); + vtkGetVector3Macro(Ratio, double); + + // Description: + // Set the number of scalar components + virtual void SetNumberOfScalarComponents(int i); + + // Description: + // Set/Get the data scalar type (i.e VTK_DOUBLE). Note that these methods + // are setting and getting the pipeline scalar type. i.e. they are setting + // the type that the image data will be once it has executed. Until the + // REQUEST_DATA pass the actual scalars may be of some other type. This is + // for backwards compatibility + void SetScalarTypeToFloat(){this->SetScalarType(VTK_FLOAT);}; + void SetScalarTypeToDouble(){this->SetScalarType(VTK_DOUBLE);}; + void SetScalarTypeToInt(){this->SetScalarType(VTK_INT);}; + void SetScalarTypeToUnsignedInt() + {this->SetScalarType(VTK_UNSIGNED_INT);}; + void SetScalarTypeToLong(){this->SetScalarType(VTK_LONG);}; + void SetScalarTypeToUnsignedLong() + {this->SetScalarType(VTK_UNSIGNED_LONG);}; + void SetScalarTypeToShort(){this->SetScalarType(VTK_SHORT);}; + void SetScalarTypeToUnsignedShort() + {this->SetScalarType(VTK_UNSIGNED_SHORT);}; + void SetScalarTypeToUnsignedChar() + {this->SetScalarType(VTK_UNSIGNED_CHAR);}; + void SetScalarTypeToChar() + {this->SetScalarType(VTK_CHAR);}; + void SetScalarType(int); + +protected: + vtkImageCanvasSource2D(); + // Destructor: Deleting a vtkImageCanvasSource2D automatically deletes the + // associated vtkImageData. However, since the data is reference counted, + // it may not actually be deleted. + ~vtkImageCanvasSource2D(); + + vtkImageData *ImageData; + int WholeExtent[6]; + double DrawColor[4]; + int DefaultZ; + double Ratio[3]; + + int ClipSegment(int &a0, int &a1, int &b0, int &b1); + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector**, + vtkInformationVector *); + virtual int RequestData (vtkInformation *, + vtkInformationVector**, + vtkInformationVector *); + +private: + vtkImageCanvasSource2D(const vtkImageCanvasSource2D&); // Not implemented. + void operator=(const vtkImageCanvasSource2D&); // Not implemented. +}; + + + +#endif + + diff --git a/Imaging/vtkImageCast.cxx b/Imaging/vtkImageCast.cxx new file mode 100644 index 0000000..aa632c5 --- /dev/null +++ b/Imaging/vtkImageCast.cxx @@ -0,0 +1,169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCast.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageCast.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageCast, "$Revision: 1.51 $"); +vtkStandardNewMacro(vtkImageCast); + +//---------------------------------------------------------------------------- +vtkImageCast::vtkImageCast() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + this->OutputScalarType = VTK_FLOAT; + this->ClampOverflow = 0; +} + + +//---------------------------------------------------------------------------- +// Just change the Image type. +int vtkImageCast::RequestInformation ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector * outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->OutputScalarType, -1); + return 1; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageCastExecute(vtkImageCast *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, IT *, OT *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + + double typeMin, typeMax, val; + int clamp; + + // for preventing overflow + typeMin = outData->GetScalarTypeMin(); + typeMax = outData->GetScalarTypeMax(); + clamp = self->GetClampOverflow(); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + IT* inSI = inIt.BeginSpan(); + OT* outSI = outIt.BeginSpan(); + OT* outSIEnd = outIt.EndSpan(); + if (clamp) + { + while (outSI != outSIEnd) + { + // Pixel operation + val = static_cast(*inSI); + if (val > typeMax) + { + val = typeMax; + } + if (val < typeMin) + { + val = typeMin; + } + *outSI = static_cast(val); + ++outSI; + ++inSI; + } + } + else + { + while (outSI != outSIEnd) + { + // now process the components + *outSI = static_cast(*inSI); + ++outSI; + ++inSI; + } + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + + + +//---------------------------------------------------------------------------- +template +void vtkImageCastExecute(vtkImageCast *self, + vtkImageData *inData, + vtkImageData *outData, int outExt[6], int id, + T *) +{ + switch (outData->GetScalarType()) + { + vtkTemplateMacro(vtkImageCastExecute(self, + inData, outData, outExt, id, + static_cast(0), + static_cast(0))); + default: + vtkGenericWarningMacro("Execute: Unknown output ScalarType"); + return; + } +} + + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output region, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageCast::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCastExecute(this, inData, + outData, outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown input ScalarType"); + return; + } +} + +void vtkImageCast::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "OutputScalarType: " << this->OutputScalarType << "\n"; + os << indent << "ClampOverflow: "; + if (this->ClampOverflow) + { + os << "On\n"; + } + else + { + os << "Off\n"; + } +} + diff --git a/Imaging/vtkImageCast.h b/Imaging/vtkImageCast.h new file mode 100644 index 0000000..9788a33 --- /dev/null +++ b/Imaging/vtkImageCast.h @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCast.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageCast - Image Data type Casting Filter +// .SECTION Description +// vtkImageCast filter casts the input type to match the output type in +// the image processing pipeline. The filter does nothing if the input +// already has the correct type. To specify the "CastTo" type, +// use "SetOutputScalarType" method. + +// .SECTION See Also +// vtkImageThreshold vtkImageShiftScale + +#ifndef __vtkImageCast_h +#define __vtkImageCast_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageCast : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageCast *New(); + vtkTypeRevisionMacro(vtkImageCast,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the desired output scalar type to cast to. + vtkSetMacro(OutputScalarType,int); + vtkGetMacro(OutputScalarType,int); + void SetOutputScalarTypeToFloat(){this->SetOutputScalarType(VTK_FLOAT);}; + void SetOutputScalarTypeToDouble(){this->SetOutputScalarType(VTK_DOUBLE);}; + void SetOutputScalarTypeToInt(){this->SetOutputScalarType(VTK_INT);}; + void SetOutputScalarTypeToUnsignedInt() + {this->SetOutputScalarType(VTK_UNSIGNED_INT);}; + void SetOutputScalarTypeToLong(){this->SetOutputScalarType(VTK_LONG);}; + void SetOutputScalarTypeToUnsignedLong() + {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; + void SetOutputScalarTypeToShort(){this->SetOutputScalarType(VTK_SHORT);}; + void SetOutputScalarTypeToUnsignedShort() + {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);}; + void SetOutputScalarTypeToUnsignedChar() + {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);}; + void SetOutputScalarTypeToChar() + {this->SetOutputScalarType(VTK_CHAR);}; + + // Description: + // When the ClampOverflow flag is on, the data is thresholded so that + // the output value does not exceed the max or min of the data type. + // By default ClampOverflow is off. + vtkSetMacro(ClampOverflow, int); + vtkGetMacro(ClampOverflow, int); + vtkBooleanMacro(ClampOverflow, int); + + +protected: + vtkImageCast(); + ~vtkImageCast() {}; + + int ClampOverflow; + int OutputScalarType; + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); + +private: + vtkImageCast(const vtkImageCast&); // Not implemented. + void operator=(const vtkImageCast&); // Not implemented. +}; + +#endif + + + + diff --git a/Imaging/vtkImageChangeInformation.cxx b/Imaging/vtkImageChangeInformation.cxx new file mode 100644 index 0000000..c19d200 --- /dev/null +++ b/Imaging/vtkImageChangeInformation.cxx @@ -0,0 +1,272 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageChangeInformation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageChangeInformation.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageChangeInformation, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkImageChangeInformation); + +//---------------------------------------------------------------------------- +vtkImageChangeInformation::vtkImageChangeInformation() +{ + this->CenterImage = 0; + + for (int i = 0; i < 3; i++) + { + this->OutputExtentStart[i] = VTK_INT_MAX; + this->ExtentTranslation[i] = 0; + this->FinalExtentTranslation[i] = VTK_INT_MAX; + + this->OutputSpacing[i] = VTK_DOUBLE_MAX; + this->SpacingScale[i] = 1.0; + + this->OutputOrigin[i] = VTK_DOUBLE_MAX; + this->OriginScale[i] = 1.0; + this->OriginTranslation[i] = 0.0; + } + + // There is an optional second input. + this->SetNumberOfInputPorts(2); +} + +// Specify a source object at a specified table location. +void vtkImageChangeInformation::SetInformationInput(vtkImageData *pd) +{ + this->SetInput(1, pd); +} + +// Get a pointer to a source object at a specified table location. +vtkImageData *vtkImageChangeInformation::GetInformationInput() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return 0; + } + return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(1, 0)); +} + +//---------------------------------------------------------------------------- +vtkImageChangeInformation::~vtkImageChangeInformation() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageChangeInformation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "CenterImage : " + << (this->CenterImage ? "On":"Off") << endl; + + os << indent << "OutputExtentStart: (" + << this->OutputExtentStart[0] << "," + << this->OutputExtentStart[1] << "," + << this->OutputExtentStart[2] << ")" << endl; + + os << indent << "ExtentTranslation: (" + << this->ExtentTranslation[0] << "," + << this->ExtentTranslation[1] << "," + << this->ExtentTranslation[2] << ")" << endl; + + os << indent << "OutputSpacing: (" + << this->OutputSpacing[0] << "," + << this->OutputSpacing[1] << "," + << this->OutputSpacing[2] << ")" << endl; + + os << indent << "SpacingScale: (" + << this->SpacingScale[0] << "," + << this->SpacingScale[1] << "," + << this->SpacingScale[2] << ")" << endl; + + os << indent << "OutputOrigin: (" + << this->OutputOrigin[0] << "," + << this->OutputOrigin[1] << "," + << this->OutputOrigin[2] << ")" << endl; + + os << indent << "OriginScale: (" + << this->OriginScale[0] << "," + << this->OriginScale[1] << "," + << this->OriginScale[2] << ")" << endl; + + os << indent << "OriginTranslation: (" + << this->OriginTranslation[0] << "," + << this->OriginTranslation[1] << "," + << this->OriginTranslation[2] << ")" << endl; +} + +//---------------------------------------------------------------------------- +// Change the information +int vtkImageChangeInformation::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int i; + int extent[6], inExtent[6]; + double spacing[3], origin[3]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),inExtent); + + vtkImageData *infoInput = this->GetInformationInput(); + if (infoInput) + { + // If there is an InformationInput, it is set as a second input + vtkInformation *in2Info = inputVector[1]->GetInformationObject(0); + infoInput->GetOrigin(origin); + infoInput->GetSpacing(spacing); + in2Info->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + for (i = 0; i < 3; i++) + { + extent[2*i+1] = extent[2*i] - inExtent[2*i] + inExtent[2*i+1]; + } + } + else + { + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + inInfo->Get(vtkDataObject::ORIGIN(), origin); + inInfo->Get(vtkDataObject::SPACING(), spacing); + } + + for (i = 0; i < 3; i++) + { + if (this->OutputSpacing[i] != VTK_DOUBLE_MAX) + { + spacing[i] = this->OutputSpacing[i]; + } + + if (this->OutputOrigin[i] != VTK_DOUBLE_MAX) + { + origin[i] = this->OutputOrigin[i]; + } + + if (this->OutputExtentStart[i] != VTK_INT_MAX) + { + extent[2*i+1] += this->OutputExtentStart[i] - extent[2*i]; + extent[2*i] = this->OutputExtentStart[i]; + } + } + + if (this->CenterImage) + { + for (i = 0; i < 3; i++) + { + origin[i] = -(extent[2*i] + extent[2*i+1])*spacing[i]/2; + } + } + + for (i = 0; i < 3; i++) + { + spacing[i] = spacing[i]*this->SpacingScale[i]; + origin[i] = origin[i]*this->OriginScale[i] + this->OriginTranslation[i]; + extent[2*i] = extent[2*i] + this->ExtentTranslation[i]; + extent[2*i+1] = extent[2*i+1] + this->ExtentTranslation[i]; + this->FinalExtentTranslation[i] = extent[2*i] - inExtent[2*i]; + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + + return 1; +} + + +//---------------------------------------------------------------------------- +// This method simply copies by reference the input data to the output. +int vtkImageChangeInformation::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + if (this->FinalExtentTranslation[0] == VTK_INT_MAX) + { + vtkErrorMacro("Bug in code, RequestInformation was not called"); + return 0; + } + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int extent[6]; + + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // since inData can be larger than update extent. + inData->GetExtent(extent); + for (int i = 0; i < 3; ++i) + { + extent[i*2] += this->FinalExtentTranslation[i]; + extent[i*2+1] += this->FinalExtentTranslation[i]; + } + outData->SetExtent(extent); + outData->GetPointData()->PassData(inData->GetPointData()); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageChangeInformation::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + if (this->FinalExtentTranslation[0] == VTK_INT_MAX) + { + vtkErrorMacro("Bug in code."); + return 0; + } + + int inExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt); + + inExt[0] -= this->FinalExtentTranslation[0]; + inExt[1] -= this->FinalExtentTranslation[0]; + inExt[2] -= this->FinalExtentTranslation[1]; + inExt[3] -= this->FinalExtentTranslation[1]; + inExt[4] -= this->FinalExtentTranslation[2]; + inExt[5] -= this->FinalExtentTranslation[2]; + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + return 1; +} + +int vtkImageChangeInformation::FillInputPortInformation( + int port, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + + return 1; +} diff --git a/Imaging/vtkImageChangeInformation.h b/Imaging/vtkImageChangeInformation.h new file mode 100644 index 0000000..2dadd0a --- /dev/null +++ b/Imaging/vtkImageChangeInformation.h @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageChangeInformation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageChangeInformation - modify spacing, origin and extent. +// .SECTION Description +// vtkImageChangeInformation modify the spacing, origin, or extent of +// the data without changing the data itself. The data is not resampled +// by this filter, only the information accompanying the data is modified. + +#ifndef __vtkImageChangeInformation_h +#define __vtkImageChangeInformation_h + +#include "vtkImageAlgorithm.h" + +class vtkImageData; + +class VTK_IMAGING_EXPORT vtkImageChangeInformation : public vtkImageAlgorithm +{ +public: + static vtkImageChangeInformation *New(); + vtkTypeRevisionMacro(vtkImageChangeInformation, vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Copy the information from another data set. By default, + // the information is copied from the input. + virtual void SetInformationInput(vtkImageData*); + virtual vtkImageData *GetInformationInput(); + + // Description: + // Specify new starting values for the extent explicitly. + // These values are used as WholeExtent[0], WholeExtent[2] and + // WholeExtent[4] of the output. The default is to the + // use the extent start of the Input, or of the InformationInput + // if InformationInput is set. + vtkSetVector3Macro(OutputExtentStart, int); + vtkGetVector3Macro(OutputExtentStart, int); + + // Description: + // Specify a new data spacing explicitly. The default is to + // use the spacing of the Input, or of the InformationInput + // if InformationInput is set. + vtkSetVector3Macro(OutputSpacing, double); + vtkGetVector3Macro(OutputSpacing, double); + + // Description: + // Specify a new data origin explicitly. The default is to + // use the origin of the Input, or of the InformationInput + // if InformationInput is set. + vtkSetVector3Macro(OutputOrigin, double); + vtkGetVector3Macro(OutputOrigin, double); + + // Description: + // Set the Origin of the output so that image coordinate (0,0,0) + // lies at the Center of the data set. This will override + // SetOutputOrigin. This is often a useful operation to apply + // before using vtkImageReslice to apply a transformation to an image. + vtkSetMacro(CenterImage, int); + vtkBooleanMacro(CenterImage, int); + vtkGetMacro(CenterImage, int); + + // Description: + // Apply a translation to the extent. + vtkSetVector3Macro(ExtentTranslation, int); + vtkGetVector3Macro(ExtentTranslation, int); + + // Description: + // Apply a scale factor to the spacing. + vtkSetVector3Macro(SpacingScale, double); + vtkGetVector3Macro(SpacingScale, double); + + // Description: + // Apply a translation to the origin. + vtkSetVector3Macro(OriginTranslation, double); + vtkGetVector3Macro(OriginTranslation, double); + + // Description: + // Apply a scale to the origin. The scale is applied + // before the translation. + vtkSetVector3Macro(OriginScale, double); + vtkGetVector3Macro(OriginScale, double); + +protected: + vtkImageChangeInformation(); + ~vtkImageChangeInformation(); + + int CenterImage; + + int OutputExtentStart[3]; + int ExtentTranslation[3]; + int FinalExtentTranslation[3]; + + double OutputSpacing[3]; + double SpacingScale[3]; + + double OutputOrigin[3]; + double OriginScale[3]; + double OriginTranslation[3]; + + virtual int RequestUpdateExtent (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkImageChangeInformation(const vtkImageChangeInformation&); // Not implemented. + void operator=(const vtkImageChangeInformation&); // Not implemented. +}; + + + +#endif + + + diff --git a/Imaging/vtkImageCheckerboard.cxx b/Imaging/vtkImageCheckerboard.cxx new file mode 100644 index 0000000..3437643 --- /dev/null +++ b/Imaging/vtkImageCheckerboard.cxx @@ -0,0 +1,230 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCheckerboard.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageCheckerboard.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageCheckerboard, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkImageCheckerboard); + +//---------------------------------------------------------------------------- +vtkImageCheckerboard::vtkImageCheckerboard() +{ + this->NumberOfDivisions[0] = 2; + this->NumberOfDivisions[1] = 2; + this->NumberOfDivisions[2] = 2; + + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the two input operations +template +void vtkImageCheckerboardExecute2(vtkImageCheckerboard *self, + vtkImageData *in1Data, T *in1Ptr, + vtkImageData *in2Data, T *in2Ptr, + vtkImageData *outData, + T *outPtr, + int outExt[6], int id) +{ + int idxR, idxY, idxZ; + int maxY, maxZ; + int dimWholeX, dimWholeY, dimWholeZ; + int divX, divY, divZ; + int nComp; + int selectX, selectY, selectZ; + int which; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType in2IncX, in2IncY, in2IncZ; + vtkIdType outIncX, outIncY, outIncZ; + int wholeExt[6]; + int rowLength; + unsigned long count = 0; + unsigned long target; + int threadOffsetX, threadOffsetY, threadOffsetZ; + int numDivX, numDivY, numDivZ; + + // find the region to loop over + nComp = in1Data->GetNumberOfScalarComponents(); + rowLength = (outExt[1] - outExt[0]+1)*nComp; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + outData->GetWholeExtent(wholeExt); + + dimWholeX = wholeExt[1] - wholeExt[0] + 1; + dimWholeY = wholeExt[3] - wholeExt[2] + 1; + dimWholeZ = wholeExt[5] - wholeExt[4] + 1; + + threadOffsetX = (outExt[0] - wholeExt[0]) * nComp; + threadOffsetY = outExt[2] - wholeExt[2]; + threadOffsetZ = outExt[4] - wholeExt[4]; + + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + in2Data->GetContinuousIncrements(outExt, in2IncX, in2IncY, in2IncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // make sure number of divisions is not 0 + numDivX = (self->GetNumberOfDivisions()[0] == 0) ? 1 : self->GetNumberOfDivisions()[0]; + numDivY = (self->GetNumberOfDivisions()[1] == 0) ? 1 : self->GetNumberOfDivisions()[1]; + numDivZ = (self->GetNumberOfDivisions()[2] == 0) ? 1 : self->GetNumberOfDivisions()[2]; + + divX = dimWholeX / numDivX * nComp; + divY = dimWholeY / numDivY; + divZ = dimWholeZ / numDivZ; + + // Loop through output pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + selectZ = (((idxZ + threadOffsetZ) / divZ) % 2) << 2; + for (idxY = 0; idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + selectY = (((idxY + threadOffsetY) / divY) % 2) << 1; + for (idxR = 0; idxR < rowLength; idxR++) + { + + selectX = ((idxR + threadOffsetX) / divX) % 2; + which = selectZ + selectY + selectX; + switch (which) + { + case 0: + *outPtr = *in1Ptr; + break; + case 1: + *outPtr = *in2Ptr; + break; + case 2: + *outPtr = *in2Ptr; + break; + case 3: + *outPtr = *in1Ptr; + break; + case 4: + *outPtr = *in2Ptr; + break; + case 5: + *outPtr = *in1Ptr; + break; + case 6: + *outPtr = *in1Ptr; + break; + case 7: + *outPtr = *in2Ptr; + break; + } + outPtr++; + in1Ptr++; + in2Ptr++; + } + outPtr += outIncY; + in1Ptr += inIncY; + in2Ptr += in2IncY; + } + outPtr += outIncZ; + in1Ptr += inIncZ; + in2Ptr += in2IncZ; + } +} + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs. +void vtkImageCheckerboard::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *in1Ptr, *in2Ptr; + void *outPtr; + + if (inData[0][0] == NULL) + { + vtkErrorMacro(<< "Input " << 0 << " must be specified."); + return; + } + in1Ptr = inData[0][0]->GetScalarPointerForExtent(outExt); + if (!in1Ptr) + { + vtkErrorMacro(<< "Input " << 0 << " cannot be empty."); + return; + } + + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + if (inData[1][0] == NULL) + { + vtkErrorMacro(<< "Input " << 1 << " must be specified."); + return; + } + in2Ptr = inData[1][0]->GetScalarPointerForExtent(outExt); + if (!in2Ptr) + { + vtkErrorMacro(<< "Input " << 1 << " cannot be empty."); + return; + } + + // this filter expects that inputs that have the same number of components + if (inData[0][0]->GetNumberOfScalarComponents() != + inData[1][0]->GetNumberOfScalarComponents()) + { + vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, " + << inData[0][0]->GetNumberOfScalarComponents() + << ", must match out input2 NumberOfScalarComponents " + << inData[1][0]->GetNumberOfScalarComponents()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCheckerboardExecute2(this, inData[0][0], + (VTK_TT *)(in1Ptr), inData[1][0], + (VTK_TT *)(in2Ptr), + outData[0], + (VTK_TT *)(outPtr), + outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageCheckerboard::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "NumberOfDivisions: (" << this->NumberOfDivisions[0] << ", " + << this->NumberOfDivisions[1] << ", " + << this->NumberOfDivisions[2] << ")\n"; +} + diff --git a/Imaging/vtkImageCheckerboard.h b/Imaging/vtkImageCheckerboard.h new file mode 100644 index 0000000..78a0719 --- /dev/null +++ b/Imaging/vtkImageCheckerboard.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCheckerboard.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageCheckerboard - show two images at once using a checkboard pattern +// .SECTION Description +// vtkImageCheckerboard displays two images as one using a checkerboard +// pattern. This filter can be used to compare two images. The +// checkerboard pattern is controlled by the NumberOfDivisions +// ivar. This controls the number of checkerboard divisions in the whole +// extent of the image. + +#ifndef __vtkImageCheckerboard_h +#define __vtkImageCheckerboard_h + +#include "vtkThreadedImageAlgorithm.h" + + +class VTK_IMAGING_EXPORT vtkImageCheckerboard : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageCheckerboard *New(); + vtkTypeRevisionMacro(vtkImageCheckerboard,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the number of divisions along each axis. + vtkSetVector3Macro(NumberOfDivisions,int); + vtkGetVectorMacro(NumberOfDivisions,int,3); + + // Description: + // Set the two inputs to this filter + virtual void SetInput1(vtkDataObject *in) { this->SetInput(0,in); } + virtual void SetInput2(vtkDataObject *in) { this->SetInput(1,in); } + +protected: + vtkImageCheckerboard(); + ~vtkImageCheckerboard() {}; + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + int NumberOfDivisions[3]; +private: + vtkImageCheckerboard(const vtkImageCheckerboard&); // Not implemented. + void operator=(const vtkImageCheckerboard&); // Not implemented. +}; + +#endif + + + + + + + + + + + + + diff --git a/Imaging/vtkImageCityBlockDistance.cxx b/Imaging/vtkImageCityBlockDistance.cxx new file mode 100644 index 0000000..7307659 --- /dev/null +++ b/Imaging/vtkImageCityBlockDistance.cxx @@ -0,0 +1,229 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCityBlockDistance.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageCityBlockDistance.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageCityBlockDistance, "$Revision: 1.29 $"); +vtkStandardNewMacro(vtkImageCityBlockDistance); + +//---------------------------------------------------------------------------- +vtkImageCityBlockDistance::vtkImageCityBlockDistance() +{ +} + + +//---------------------------------------------------------------------------- +void vtkImageCityBlockDistance::AllocateOutputScalars(vtkImageData *outData, + int* uExt, + int* wholeExtent) +{ + int updateExtent[6], idx; + + memcpy(updateExtent, uExt, 6*sizeof(int)); + for (idx = 0; idx < this->Dimensionality; ++idx) + { + updateExtent[idx*2] = wholeExtent[idx*2]; + updateExtent[idx*2+1] = wholeExtent[idx*2+1]; + } + outData->SetExtent(updateExtent); + outData->AllocateScalars(); +} + + +//---------------------------------------------------------------------------- +// This method tells the superclass that the whole input array is needed +// to compute any output region. +int vtkImageCityBlockDistance::IterativeRequestUpdateExtent( + vtkInformation* input, vtkInformation* output) +{ + int *outExt = output->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + int *wExt = input->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + int inExt[6]; + + memcpy(inExt, outExt, 6 * sizeof(int)); + inExt[this->Iteration * 2] = wExt[this->Iteration * 2]; + inExt[this->Iteration * 2 + 1] = wExt[this->Iteration * 2 + 1]; + input->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + + +//---------------------------------------------------------------------------- +// This is writen as a 1D execute method, but is called several times. +int vtkImageCityBlockDistance::IterativeRequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int *uExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + int *wExt = outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + this->AllocateOutputScalars(outData, uExt, wExt); + + short *inPtr0, *inPtr1, *inPtr2, *inPtrC; + short *outPtr0, *outPtr1, *outPtr2, *outPtrC; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + int min0, max0, min1, max1, min2, max2, numberOfComponents; + int idx0, idx1, idx2, idxC; + short distP, distN; + short big = 2000; + int outExt[6]; + unsigned long count = 0; + unsigned long target; + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),outExt); + + // this filter expects that inputand output are short + if (inData->GetScalarType() != VTK_SHORT || + outData->GetScalarType() != VTK_SHORT) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", and out ScalarType " << outData->GetScalarType() + << " must be short."); + return 1; + } + + + // Reorder axes (the in and out extents are assumed to be the same) + // (see intercept cache update) + this->PermuteExtent(outExt, min0, max0, min1, max1, min2, max2); + this->PermuteIncrements(inData->GetIncrements(), inInc0, inInc1, inInc2); + this->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + numberOfComponents = inData->GetNumberOfScalarComponents(); + + target = (unsigned long)((max2-min2+1)*(max1-min1+1)/50.0); + target++; + + // loop over all the extra axes + inPtr2 = (short *)inData->GetScalarPointerForExtent(outExt); + outPtr2 = (short *)outData->GetScalarPointerForExtent(outExt); + for (idx2 = min2; idx2 <= max2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = min1; !this->AbortExecute && idx1 <= max1; ++idx1) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + inPtrC = inPtr1; + outPtrC = outPtr1; + for (idxC = 0; idxC < numberOfComponents; ++idxC) + { + // execute forward pass + distP = big; + distN = -big; + inPtr0 = inPtrC; + outPtr0 = outPtrC; + for (idx0 = min0; idx0 <= max0; ++idx0) + { // preserve sign + if (*inPtr0 >= 0) + { + distN = 0; + if (distP > *inPtr0) + { + distP = *inPtr0; + } + *outPtr0 = distP; + } + if (*inPtr0 <= 0) + { + distP = 0; + if (distN < *inPtr0) + { + distN = *inPtr0; + } + *outPtr0 = distN; + } + + if (distP < big) + { + ++distP; + } + if (distN > -big) + { + --distN; + } + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + + // backward pass + distP = big; + distN = -big; + // Undo the last increment to put us at the last pixel + // (input is no longer needed) + outPtr0 -= outInc0; + for (idx0 = max0; idx0 >= min0; --idx0) + { + if (*outPtr0 >= 0) + { + if (distP > *outPtr0) + { + distP = *outPtr0; + } + *outPtr0 = distP; + } + if (*outPtr0 <= 0) + { + if (distN < *outPtr0) + { + distN = *outPtr0; + } + *outPtr0 = distN; + } + + if (distP < big) + { + ++distP; + } + if (distN > -big) + { + --distN; + } + + outPtr0 -= outInc0; + } + + inPtrC += 1; + outPtrC += 1; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + + return 1; +} + + diff --git a/Imaging/vtkImageCityBlockDistance.h b/Imaging/vtkImageCityBlockDistance.h new file mode 100644 index 0000000..5203ca2 --- /dev/null +++ b/Imaging/vtkImageCityBlockDistance.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCityBlockDistance.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageCityBlockDistance - 1,2 or 3D distance map. +// .SECTION Description +// vtkImageCityBlockDistance creates a distance map using the city block +// (Manhatten) distance measure. The input is a mask. Zero values are +// considered boundaries. The output pixel is the minimum of the input pixel +// and the distance to a boundary (or neighbor value + 1 unit). +// distance values are calculated in pixels. +// The filter works by taking 6 passes (for 3d distance map): 2 along each +// axis (forward and backward). Each pass keeps a running minimum distance. +// For some reason, I preserve the sign if the distance. If the input +// mask is initially negative, the output distances will be negative. +// Distances maps can have inside (negative regions) +// and outsides (positive regions). + +#ifndef __vtkImageCityBlockDistance_h +#define __vtkImageCityBlockDistance_h + + +#include "vtkImageDecomposeFilter.h" + +class VTK_IMAGING_EXPORT vtkImageCityBlockDistance : public vtkImageDecomposeFilter +{ +public: + static vtkImageCityBlockDistance *New(); + vtkTypeRevisionMacro(vtkImageCityBlockDistance,vtkImageDecomposeFilter); + +protected: + vtkImageCityBlockDistance(); + ~vtkImageCityBlockDistance() {}; + + virtual int IterativeRequestUpdateExtent(vtkInformation* in, + vtkInformation* out); + virtual int IterativeRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + void AllocateOutputScalars(vtkImageData *outData, + int* updateExtent, + int* wholeExtent); + +private: + vtkImageCityBlockDistance(const vtkImageCityBlockDistance&); // Not implemented. + void operator=(const vtkImageCityBlockDistance&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageClip.cxx b/Imaging/vtkImageClip.cxx new file mode 100644 index 0000000..ad16b2a --- /dev/null +++ b/Imaging/vtkImageClip.cxx @@ -0,0 +1,245 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageClip.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageClip.h" + +#include "vtkCellData.h" +#include "vtkExtentTranslator.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageClip, "$Revision: 1.56 $"); +vtkStandardNewMacro(vtkImageClip); + +//---------------------------------------------------------------------------- +vtkImageClip::vtkImageClip() +{ + this->ClipData = 0; + this->Initialized = 0; + + this->OutputWholeExtent[0] = + this->OutputWholeExtent[2] = + this->OutputWholeExtent[4] = -VTK_LARGE_INTEGER; + + this->OutputWholeExtent[1] = + this->OutputWholeExtent[3] = + this->OutputWholeExtent[5] = VTK_LARGE_INTEGER; +} + +//---------------------------------------------------------------------------- +void vtkImageClip::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + + os << indent << "OutputWholeExtent: (" << this->OutputWholeExtent[0] + << "," << this->OutputWholeExtent[1]; + for (idx = 1; idx < 3; ++idx) + { + os << indent << ", " << this->OutputWholeExtent[idx * 2] + << "," << this->OutputWholeExtent[idx*2 + 1]; + } + os << ")\n"; + if (this->ClipData) + { + os << indent << "ClipDataOn\n"; + } + else + { + os << indent << "ClipDataOff\n"; + } +} + +//---------------------------------------------------------------------------- +void vtkImageClip::SetOutputWholeExtent(int extent[6], vtkInformation *outInfo) +{ + int idx; + int modified = 0; + + for (idx = 0; idx < 6; ++idx) + { + if (this->OutputWholeExtent[idx] != extent[idx]) + { + this->OutputWholeExtent[idx] = extent[idx]; + modified = 1; + } + } + this->Initialized = 1; + if (modified) + { + this->Modified(); + if (!outInfo) + { + outInfo = this->GetExecutive()->GetOutputInformation(0); + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); + } +} + +//---------------------------------------------------------------------------- +void vtkImageClip::SetOutputWholeExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetOutputWholeExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkImageClip::GetOutputWholeExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + extent[idx] = this->OutputWholeExtent[idx]; + } +} + +//---------------------------------------------------------------------------- +// Change the WholeExtent +int vtkImageClip::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int idx, extent[6]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + if ( ! this->Initialized) + { + this->SetOutputWholeExtent(extent, outInfo); + } + + // Clip the OutputWholeExtent with the input WholeExtent + for (idx = 0; idx < 3; ++idx) + { + if (this->OutputWholeExtent[idx*2] >= extent[idx*2] && + this->OutputWholeExtent[idx*2] <= extent[idx*2+1]) + { + extent[idx*2] = this->OutputWholeExtent[idx*2]; + } + if (this->OutputWholeExtent[idx*2+1] >= extent[idx*2] && + this->OutputWholeExtent[idx*2+1] <= extent[idx*2+1]) + { + extent[idx*2+1] = this->OutputWholeExtent[idx*2+1]; + } + // make usre the order is correct + if (extent[idx*2] > extent[idx*2+1]) + { + extent[idx*2] = extent[idx*2+1]; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// Sets the output whole extent to be the input whole extent. +void vtkImageClip::ResetOutputWholeExtent() +{ + if ( ! this->GetInput()) + { + vtkWarningMacro("ResetOutputWholeExtent: No input"); + return; + } + + this->GetInput()->UpdateInformation(); + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + this->SetOutputWholeExtent(inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); +} + +//---------------------------------------------------------------------------- +// This method simply copies by reference the input data to the output. +int vtkImageClip::RequestData(vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int *inExt; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + inExt = inData->GetExtent(); + + outData->SetExtent(inExt); + outData->GetPointData()->PassData(inData->GetPointData()); + outData->GetCellData()->PassData(inData->GetCellData()); + + if (this->ClipData) + { + outData->Crop(); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageClip::SetOutputWholeExtent(int piece, int numPieces) +{ + vtkInformation *inInfo = this->GetExecutive()->GetInputInformation(0, 0); + vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0); + vtkImageData *input = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkExtentTranslator *translator; + int ext[6]; + + if (input == NULL) + { + vtkErrorMacro("We must have an input to set the output extent by piece."); + return; + } + if (output == NULL) + { + vtkErrorMacro("We must have an output to set the output extent by piece."); + return; + } + translator = output->GetExtentTranslator(); + if (translator == NULL) + { + vtkErrorMacro("Output does not have an extent translator."); + return; + } + + input->UpdateInformation(); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext); + translator->SetWholeExtent(ext); + translator->SetPiece(piece); + translator->SetNumberOfPieces(numPieces); + translator->SetGhostLevel(0); + translator->PieceToExtent(); + translator->GetExtent(ext); + this->SetOutputWholeExtent(ext); +} diff --git a/Imaging/vtkImageClip.h b/Imaging/vtkImageClip.h new file mode 100644 index 0000000..a26f044 --- /dev/null +++ b/Imaging/vtkImageClip.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageClip.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageClip - Reduces the image extent of the input. +// .SECTION Description +// vtkImageClip will make an image smaller. The output must have +// an image extent which is the subset of the input. The filter has two +// modes of operation: +// 1: By default, the data is not copied in this filter. +// Only the whole extent is modified. +// 2: If ClipDataOn is set, then you will get no more that the clipped +// extent. +#ifndef __vtkImageClip_h +#define __vtkImageClip_h + +// I did not make this a subclass of in place filter because +// the references on the data do not matter. I make no modifications +// to the data. +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageClip : public vtkImageAlgorithm +{ +public: + static vtkImageClip *New(); + vtkTypeRevisionMacro(vtkImageClip,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The whole extent of the output has to be set explicitly. + void SetOutputWholeExtent(int extent[6], vtkInformation *outInfo=0); + void SetOutputWholeExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + void GetOutputWholeExtent(int extent[6]); + int *GetOutputWholeExtent() {return this->OutputWholeExtent;} + + void ResetOutputWholeExtent(); + + // Description: + // By default, ClipData is off, and only the WholeExtent is modified. + // the data's extent may actually be larger. When this flag is on, + // the data extent will be no more than the OutputWholeExtent. + vtkSetMacro(ClipData, int); + vtkGetMacro(ClipData, int); + vtkBooleanMacro(ClipData, int); + + // Description: + // Hack set output by piece + void SetOutputWholeExtent(int piece, int numPieces); + +protected: + vtkImageClip(); + ~vtkImageClip() {}; + + // Time when OutputImageExtent was computed. + vtkTimeStamp CTime; + int Initialized; // Set the OutputImageExtent for the first time. + int OutputWholeExtent[6]; + + int ClipData; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + void CopyData(vtkImageData *inData, vtkImageData *outData, int *ext); + + int SplitExtentTmp(int piece, int numPieces, int *ext); + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + +private: + vtkImageClip(const vtkImageClip&); // Not implemented. + void operator=(const vtkImageClip&); // Not implemented. +}; + + + +#endif + + + diff --git a/Imaging/vtkImageConnector.cxx b/Imaging/vtkImageConnector.cxx new file mode 100644 index 0000000..e0c9d76 --- /dev/null +++ b/Imaging/vtkImageConnector.cxx @@ -0,0 +1,187 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageConnector.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageConnector.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageConnector, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkImageConnector); + +//---------------------------------------------------------------------------- +vtkImageConnector::vtkImageConnector() +{ + this->Seeds = NULL; + this->LastSeed = NULL; + this->ConnectedValue = 255; + this->UnconnectedValue = 128; +} + +//---------------------------------------------------------------------------- +vtkImageConnector::~vtkImageConnector() +{ + this->RemoveAllSeeds(); +} + +//---------------------------------------------------------------------------- +void vtkImageConnector::RemoveAllSeeds() +{ + vtkImageConnectorSeed *temp; + + while (this->Seeds) + { + temp = this->Seeds; + this->Seeds = temp->Next; + delete temp; + } + this->LastSeed = NULL; +} + + +//---------------------------------------------------------------------------- +vtkImageConnectorSeed *vtkImageConnector::NewSeed(int index[3], void *ptr) +{ + vtkImageConnectorSeed *seed = vtkImageConnectorSeed::New(); + int idx; + + for (idx = 0; idx < 3; ++idx) + { + seed->Index[idx] = index[idx]; + } + seed->Pointer = ptr; + seed->Next = NULL; + + return seed; +} + +//---------------------------------------------------------------------------- +// Add a new seed to the end of the seed list. +void vtkImageConnector::AddSeedToEnd(vtkImageConnectorSeed *seed) +{ + // Add the seed to the end of the list + if (this->LastSeed == NULL) + { // no seeds yet + this->LastSeed = this->Seeds = seed; + } + else + { + this->LastSeed->Next = seed; + this->LastSeed = seed; + } +} + +//---------------------------------------------------------------------------- +// Add a new seed to the start of the seed list. +void vtkImageConnector::AddSeed(vtkImageConnectorSeed *seed) +{ + seed->Next = this->Seeds; + this->Seeds = seed; + if ( ! this->LastSeed) + { + this->LastSeed = seed; + } +} + +//---------------------------------------------------------------------------- +// Removes a seed from the start of the seed list, and returns the seed. +vtkImageConnectorSeed *vtkImageConnector::PopSeed() +{ + vtkImageConnectorSeed *seed; + + seed = this->Seeds; + this->Seeds = seed->Next; + if (this->Seeds == NULL) + { + this->LastSeed = NULL; + } + return seed; +} + +//---------------------------------------------------------------------------- +// Input a data of 0's and "UnconnectedValue"s. Seeds of this object are +// used to find connected pixels. +// All pixels connected to seeds are set to ConnectedValue. +// The data has to be unsigned char. +void vtkImageConnector::MarkData(vtkImageData *data, int numberOfAxes, int extent[6]) +{ + vtkIdType *incs, *pIncs; + int *pExtent; + vtkImageConnectorSeed *seed; + unsigned char *ptr; + int newIndex[3], *pIndex, idx; + long count = 0; + + incs = data->GetIncrements(); + while (this->Seeds) + { + ++count; + seed = this->PopSeed(); + // just in case the seed has not been marked visited. + *((unsigned char *)(seed->Pointer)) = this->ConnectedValue; + // Add neighbors + newIndex[0] = seed->Index[0]; + newIndex[1] = seed->Index[1]; + newIndex[2] = seed->Index[2]; + pExtent = extent; + pIncs = incs; + pIndex = newIndex; + for (idx = 0; idx < numberOfAxes; ++idx) + { + // check pixel below + if (*pExtent < *pIndex) + { + ptr = (unsigned char *)(seed->Pointer) - *pIncs; + if (*ptr == this->UnconnectedValue) + { // add a new seed + --(*pIndex); + *ptr = this->ConnectedValue; + this->AddSeedToEnd(this->NewSeed(newIndex, ptr)); + ++(*pIndex); + } + } + ++pExtent; + // check above pixel + if (*pExtent > *pIndex) + { + ptr = (unsigned char *)(seed->Pointer) + *pIncs; + if (*ptr == this->UnconnectedValue) + { // add a new seed + ++(*pIndex); + *ptr = this->ConnectedValue; + this->AddSeedToEnd(this->NewSeed(newIndex, ptr)); + --(*pIndex); + } + } + ++pExtent; + // move to next axis + ++pIncs; + ++pIndex; + } + + // Delete seed + delete seed; + } + vtkDebugMacro("Marked " << count << " pixels"); +} + +void vtkImageConnector::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ConnectedValue: " << this->ConnectedValue << "\n"; + os << indent << "UnconnectedValue: " << this->UnconnectedValue << "\n"; + +} + diff --git a/Imaging/vtkImageConnector.h b/Imaging/vtkImageConnector.h new file mode 100644 index 0000000..3bd75a4 --- /dev/null +++ b/Imaging/vtkImageConnector.h @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageConnector.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageConnector - Create a binary image of a sphere. +// .SECTION Description +// vtkImageConnector is a helper class for connectivity filters. +// It is not meant to be used directly. +// It implements a stack and breadth first search necessary for +// some connectivity filters. Filtered axes sets the dimensionality +// of the neighbor comparison, and +// cannot be more than three dimensions. +// As implemented, only voxels which share faces are considered +// neighbors. + + +#ifndef __vtkImageConnector_h +#define __vtkImageConnector_h + +#include "vtkObject.h" + +class vtkImageData; + +// +// Special classes for manipulating data +// +//BTX - begin tcl exclude +// +// For the breadth first search +class vtkImageConnectorSeed { //;prevent man page generation +public: + static vtkImageConnectorSeed *New() { return new vtkImageConnectorSeed;} + void *Pointer; + int Index[3]; + vtkImageConnectorSeed *Next; +}; +//ETX - end tcl exclude +// + + +class VTK_IMAGING_EXPORT vtkImageConnector : public vtkObject +{ +public: + static vtkImageConnector *New(); + + vtkTypeRevisionMacro(vtkImageConnector,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + vtkImageConnectorSeed *NewSeed(int index[3], void *ptr); + void AddSeed(vtkImageConnectorSeed *seed); + void AddSeedToEnd(vtkImageConnectorSeed *seed); + //ETX + void RemoveAllSeeds(); + + // Description: + // Values used by the MarkRegion method + vtkSetMacro(ConnectedValue, unsigned char); + vtkGetMacro(ConnectedValue, unsigned char); + vtkSetMacro(UnconnectedValue, unsigned char); + vtkGetMacro(UnconnectedValue, unsigned char); + + + // Description: + // Input a data of 0's and "UnconnectedValue"s. Seeds of this object are + // used to find connected pixels. All pixels connected to seeds are set to + // ConnectedValue. The data has to be unsigned char. + void MarkData(vtkImageData *data, int dimensionality, int ext[6]); + + +protected: + vtkImageConnector(); + ~vtkImageConnector(); + + unsigned char ConnectedValue; + unsigned char UnconnectedValue; + + vtkImageConnectorSeed *PopSeed(); + + vtkImageConnectorSeed *Seeds; + vtkImageConnectorSeed *LastSeed; +private: + vtkImageConnector(const vtkImageConnector&); // Not implemented. + void operator=(const vtkImageConnector&); // Not implemented. +}; + + + +#endif + + diff --git a/Imaging/vtkImageConstantPad.cxx b/Imaging/vtkImageConstantPad.cxx new file mode 100644 index 0000000..1f78c42 --- /dev/null +++ b/Imaging/vtkImageConstantPad.cxx @@ -0,0 +1,193 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageConstantPad.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageConstantPad.h" + +#include "vtkObjectFactory.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageConstantPad, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkImageConstantPad); + +//---------------------------------------------------------------------------- +// Constructor sets default values +vtkImageConstantPad::vtkImageConstantPad() +{ + this->Constant = 0.0; +} + + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageConstantPadExecute(vtkImageConstantPad *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int inExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int maxC, maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + T constant; + int inMinX, inMaxX, inMaxC; + constant = (T)(self->GetConstant()); + int state0, state1, state2, state3; + unsigned long count = 0; + unsigned long target; + + // find the region to loop over + maxC = outData->GetNumberOfScalarComponents(); + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + inMaxC = inData->GetNumberOfScalarComponents(); + inMinX = inExt[0] - outExt[0]; + inMaxX = inExt[1] - outExt[0]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(inExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // Loop through ouput pixels + for (idxZ = outExt[4]; idxZ <= outExt[5]; idxZ++) + { + state3 = (idxZ < inExt[4] || idxZ > inExt[5]); + for (idxY = outExt[2]; !self->AbortExecute && idxY <= outExt[3]; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + state2 = (state3 || idxY < inExt[2] || idxY > inExt[3]); + if ((maxC == inMaxC) && (maxC == 1)) + { + for (idxX = 0; idxX <= maxX; idxX++) + { + state1 = (state2 || idxX < inMinX || idxX > inMaxX); + if (state1) + { + *outPtr = constant; + } + else + { + *outPtr = *inPtr; + inPtr++; + } + outPtr++; + } + } + else + { + for (idxX = 0; idxX <= maxX; idxX++) + { + state1 = (state2 || idxX < inMinX || idxX > inMaxX); + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + // Copy Pixel + state0 = (state1 || idxC >= inMaxC); + if (state0) + { + *outPtr = constant; + } + else + { + *outPtr = *inPtr; + inPtr++; + } + outPtr++; + } + } + } + outPtr += outIncY; + if (!state2) + { + inPtr += inIncY; + } + } + outPtr += outIncZ; + if (!state3) + { + inPtr += inIncZ; + } + } +} + + +//---------------------------------------------------------------------------- +// This method is passed a input and output data, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the datas data types. +void vtkImageConstantPad::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + // get the whole extent + int wExt[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wExt); + + // need to get the correct pointer for the input data + int inExt[6]; + this->ComputeInputUpdateExtent(inExt,outExt,wExt); + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageConstantPadExecute(this, + inData[0][0], (VTK_TT *)(inPtr), outData[0], + (VTK_TT *)(outPtr), outExt, inExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown input ScalarType"); + return; + } +} + +void vtkImageConstantPad::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Constant: " << this->Constant << "\n"; + +} + diff --git a/Imaging/vtkImageConstantPad.h b/Imaging/vtkImageConstantPad.h new file mode 100644 index 0000000..fb7988d --- /dev/null +++ b/Imaging/vtkImageConstantPad.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageConstantPad.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageConstantPad - Makes image larger by padding with constant. +// .SECTION Description +// vtkImageConstantPad changes the image extent of its input. +// Any pixels outside of the original image extent are filled with +// a constant value. + +// .SECTION See Also +// vtkImageWrapPad vtkImageMirrorPad + +#ifndef __vtkImageConstantPad_h +#define __vtkImageConstantPad_h + + +#include "vtkImagePadFilter.h" + +class VTK_IMAGING_EXPORT vtkImageConstantPad : public vtkImagePadFilter +{ +public: + static vtkImageConstantPad *New(); + vtkTypeRevisionMacro(vtkImageConstantPad,vtkImagePadFilter); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the pad value. + vtkSetMacro(Constant, double); + vtkGetMacro(Constant, double); + + +protected: + vtkImageConstantPad(); + ~vtkImageConstantPad() {}; + + double Constant; + + void ThreadedRequestData (vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); +private: + vtkImageConstantPad(const vtkImageConstantPad&); // Not implemented. + void operator=(const vtkImageConstantPad&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageContinuousDilate3D.cxx b/Imaging/vtkImageContinuousDilate3D.cxx new file mode 100644 index 0000000..c9635d7 --- /dev/null +++ b/Imaging/vtkImageContinuousDilate3D.cxx @@ -0,0 +1,348 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageContinuousDilate3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageContinuousDilate3D.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkImageEllipsoidSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageContinuousDilate3D, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkImageContinuousDilate3D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageContinuousDilate3D fitler. +// By default zero values are dilated. +vtkImageContinuousDilate3D::vtkImageContinuousDilate3D() +{ + this->HandleBoundaries = 1; + this->KernelSize[0] = 0; + this->KernelSize[1] = 0; + this->KernelSize[2] = 0; + + this->Ellipse = vtkImageEllipsoidSource::New(); + // Setup the Ellipse to default size + this->SetKernelSize(1, 1, 1); +} + +//---------------------------------------------------------------------------- +vtkImageContinuousDilate3D::~vtkImageContinuousDilate3D() +{ + if (this->Ellipse) + { + this->Ellipse->Delete(); + this->Ellipse = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageContinuousDilate3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +// This method sets the size of the neighborhood. It also sets the +// default middle of the neighborhood and computes the elliptical foot print. +void vtkImageContinuousDilate3D::SetKernelSize(int size0, int size1, int size2) +{ + int modified = 0; + + if (this->KernelSize[0] != size0) + { + modified = 1; + this->KernelSize[0] = size0; + this->KernelMiddle[0] = size0 / 2; + } + if (this->KernelSize[1] != size1) + { + modified = 1; + this->KernelSize[1] = size1; + this->KernelMiddle[1] = size1 / 2; + } + if (this->KernelSize[2] != size2) + { + modified = 1; + this->KernelSize[2] = size2; + this->KernelMiddle[2] = size2 / 2; + } + + if (modified) + { + this->Modified(); + this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->SetCenter((float)(this->KernelSize[0]-1)*0.5, + (float)(this->KernelSize[1]-1)*0.5, + (float)(this->KernelSize[2]-1)*0.5); + this->Ellipse->SetRadius((float)(this->KernelSize[0])*0.5, + (float)(this->KernelSize[1])*0.5, + (float)(this->KernelSize[2])*0.5); + + // make sure scalars have been allocated (needed if multithreaded is used) + vtkInformation *ellipseOutInfo = + this->Ellipse->GetExecutive()->GetOutputInformation(0); + ellipseOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + 0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->GetOutput()->Update(); + } +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter on any region, +// whether it needs boundary checking or not. +// If the filter needs to be faster, the function could be duplicated +// for strictly center (no boundary ) processing. +template +void vtkImageContinuousDilate3DExecute(vtkImageContinuousDilate3D *self, + vtkImageData *mask, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, + int *outExt, T *outPtr, int id, + vtkDataArray *inArray, + vtkInformation *inInfo) +{ + int *kernelMiddle, *kernelSize; + // For looping though output (and input) pixels. + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + int outIdx0, outIdx1, outIdx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + T *inPtr0, *inPtr1, *inPtr2; + T *outPtr0, *outPtr1, *outPtr2; + int numComps, outIdxC; + // For looping through hood pixels + int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2; + int hoodIdx0, hoodIdx1, hoodIdx2; + T *hoodPtr0, *hoodPtr1, *hoodPtr2; + // For looping through the mask. + unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2; + vtkIdType maskInc0, maskInc1, maskInc2; + // The extent of the whole input image + int inImageMin0, inImageMin1, inImageMin2; + int inImageMax0, inImageMax1, inImageMax2; + int inImageExt[6]; + // to compute the range + T pixelMax; + unsigned long count = 0; + unsigned long target; + int *inExt; + + inExt = inData->GetExtent(); + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inImageExt); + inImageMin0 = inImageExt[0]; + inImageMax0 = inImageExt[1]; + inImageMin1 = inImageExt[2]; + inImageMax1 = inImageExt[3]; + inImageMin2 = inImageExt[4]; + inImageMax2 = inImageExt[5]; + outData->GetIncrements(outInc0, outInc1, outInc2); + outMin0 = outExt[0]; outMax0 = outExt[1]; + outMin1 = outExt[2]; outMax1 = outExt[3]; + outMin2 = outExt[4]; outMax2 = outExt[5]; + numComps = outData->GetNumberOfScalarComponents(); + + // Get ivars of this object (easier than making friends) + kernelSize = self->GetKernelSize(); + kernelMiddle = self->GetKernelMiddle(); + hoodMin0 = - kernelMiddle[0]; + hoodMin1 = - kernelMiddle[1]; + hoodMin2 = - kernelMiddle[2]; + hoodMax0 = hoodMin0 + kernelSize[0] - 1; + hoodMax1 = hoodMin1 + kernelSize[1] - 1; + hoodMax2 = hoodMin2 + kernelSize[2] - 1; + + // Setup mask info + maskPtr = (unsigned char *)(mask->GetScalarPointer()); + mask->GetIncrements(maskInc0, maskInc1, maskInc2); + + // in and out should be marching through corresponding pixels. + inPtr = (T *)(inArray->GetVoidPointer((outMin0-inExt[0])*inInc0 + + (outMin1-inExt[2])*inInc1 + + (outMin2-inExt[4])*inInc2)); + + target = (unsigned long)(numComps*(outMax2-outMin2+1)* + (outMax1-outMin1+1)/50.0); + target++; + + // loop through components + for (outIdxC = 0; outIdxC < numComps; ++outIdxC) + { + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outMin1; + !self->AbortExecute && outIdx1 <= outMax1; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0) + { + // Find min + pixelMax = *inPtr0; + // loop through neighborhood pixels + // as sort of a hack to handle boundaries, + // input pointer will be marching through data that does not exist. + hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0 + - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2; + maskPtr2 = maskPtr; + for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2) + { + hoodPtr1 = hoodPtr2; + maskPtr1 = maskPtr2; + for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1) + { + hoodPtr0 = hoodPtr1; + maskPtr0 = maskPtr1; + for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0) + { + // A quick but rather expensive way to handle boundaries + if ( outIdx0 + hoodIdx0 >= inImageMin0 && + outIdx0 + hoodIdx0 <= inImageMax0 && + outIdx1 + hoodIdx1 >= inImageMin1 && + outIdx1 + hoodIdx1 <= inImageMax1 && + outIdx2 + hoodIdx2 >= inImageMin2 && + outIdx2 + hoodIdx2 <= inImageMax2) + { + if (*maskPtr0) + { + if (*hoodPtr0 > pixelMax) + { + pixelMax = *hoodPtr0; + } + } + } + + hoodPtr0 += inInc0; + maskPtr0 += maskInc0; + } + hoodPtr1 += inInc1; + maskPtr1 += maskInc1; + } + hoodPtr2 += inInc2; + maskPtr2 += maskInc2; + } + *outPtr0 = pixelMax; + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + ++inPtr; + ++outPtr; + } +} + +//---------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output Data types. +// It handles image boundaries, so the image does not shrink. +void vtkImageContinuousDilate3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + // return if nothing to do + if (outExt[1] < outExt[0] || + outExt[3] < outExt[2] || + outExt[5] < outExt[4]) + { + return; + } + + int inExt[6], wholeExt[6]; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt,outExt,wholeExt); + void *inPtr; + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + vtkImageData *mask; + + vtkDataArray *inArray = this->GetInputArrayToProcess(0,inputVector); + // Reset later. + inPtr = inArray->GetVoidPointer(0); + + // Error checking on mask + mask = this->Ellipse->GetOutput(); + if (mask->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro(<< "Execute: mask has wrong scalar type"); + return; + } + + // this filter expects the output type to be same as input + if (outData[0]->GetScalarType() != inArray->GetDataType()) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << " must match input array data type"); + return; + } + + switch (inArray->GetDataType()) + { + vtkTemplateMacro( + vtkImageContinuousDilate3DExecute(this, + mask, inData[0][0], + (VTK_TT *)(inPtr), + outData[0], outExt, + (VTK_TT *)(outPtr), id, + inArray, inInfo) ); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkImageContinuousDilate3D::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Ellipse->GetOutput()->Update(); + return this->Superclass::RequestData(request, inputVector, outputVector); +} diff --git a/Imaging/vtkImageContinuousDilate3D.h b/Imaging/vtkImageContinuousDilate3D.h new file mode 100644 index 0000000..8c2f723 --- /dev/null +++ b/Imaging/vtkImageContinuousDilate3D.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageContinuousDilate3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageContinuousDilate3D - Dilate implemented as a maximum. +// .SECTION Description +// vtkImageContinuousDilate3D replaces a pixel with the maximum over +// an ellipsoidal neighborhood. If KernelSize of an axis is 1, no processing +// is done on that axis. + + +#ifndef __vtkImageContinuousDilate3D_h +#define __vtkImageContinuousDilate3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class vtkImageEllipsoidSource; + +class VTK_IMAGING_EXPORT vtkImageContinuousDilate3D : public vtkImageSpatialAlgorithm +{ +public: + + // Description: + // Construct an instance of vtkImageContinuousDilate3D filter. + // By default zero values are dilated. + static vtkImageContinuousDilate3D *New(); + vtkTypeRevisionMacro(vtkImageContinuousDilate3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sets the size of the neighborhood. It also sets the + // default middle of the neighborhood and computes the elliptical foot print. + void SetKernelSize(int size0, int size1, int size2); + +protected: + vtkImageContinuousDilate3D(); + ~vtkImageContinuousDilate3D(); + + vtkImageEllipsoidSource *Ellipse; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + +private: + vtkImageContinuousDilate3D(const vtkImageContinuousDilate3D&); // Not implemented. + void operator=(const vtkImageContinuousDilate3D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageContinuousErode3D.cxx b/Imaging/vtkImageContinuousErode3D.cxx new file mode 100644 index 0000000..c033622 --- /dev/null +++ b/Imaging/vtkImageContinuousErode3D.cxx @@ -0,0 +1,345 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageContinuousErode3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageContinuousErode3D.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkImageEllipsoidSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageContinuousErode3D, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkImageContinuousErode3D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageContinuousErode3D fitler. +// By default zero values are eroded. +vtkImageContinuousErode3D::vtkImageContinuousErode3D() +{ + this->HandleBoundaries = 1; + this->KernelSize[0] = 1; + this->KernelSize[1] = 1; + this->KernelSize[2] = 1; + + this->Ellipse = vtkImageEllipsoidSource::New(); + // Setup the Ellipse to default size + this->SetKernelSize(1, 1, 1); +} + +//---------------------------------------------------------------------------- +vtkImageContinuousErode3D::~vtkImageContinuousErode3D() +{ + if (this->Ellipse) + { + this->Ellipse->Delete(); + this->Ellipse = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageContinuousErode3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +// This method sets the size of the neighborhood. It also sets the +// default middle of the neighborhood and computes the eliptical foot print. +void vtkImageContinuousErode3D::SetKernelSize(int size0, int size1, int size2) +{ + int modified = 0; + + if (this->KernelSize[0] != size0) + { + modified = 1; + this->KernelSize[0] = size0; + this->KernelMiddle[0] = size0 / 2; + } + if (this->KernelSize[1] != size1) + { + modified = 1; + this->KernelSize[1] = size1; + this->KernelMiddle[1] = size1 / 2; + } + if (this->KernelSize[2] != size2) + { + modified = 1; + this->KernelSize[2] = size2; + this->KernelMiddle[2] = size2 / 2; + } + + if (modified) + { + this->Modified(); + this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->SetCenter((float)(this->KernelSize[0]-1)*0.5, + (float)(this->KernelSize[1]-1)*0.5, + (float)(this->KernelSize[2]-1)*0.5); + this->Ellipse->SetRadius((float)(this->KernelSize[0])*0.5, + (float)(this->KernelSize[1])*0.5, + (float)(this->KernelSize[2])*0.5); + // make sure scalars have been allocated (needed if multithreaded is used) + vtkInformation *ellipseOutInfo = + this->Ellipse->GetExecutive()->GetOutputInformation(0); + ellipseOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + 0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->GetOutput()->Update(); + } +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter on any region, +// whether it needs boundary checking or not. +// If the filter needs to be faster, the function could be duplicated +// for strictly center (no boundary ) processing. +template +void vtkImageContinuousErode3DExecute(vtkImageContinuousErode3D *self, + vtkImageData *mask, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, + int *outExt, T *outPtr, int id, + vtkDataArray *inArray, + vtkInformation *inInfo) +{ + int *kernelMiddle, *kernelSize; + // For looping though output (and input) pixels. + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + int outIdx0, outIdx1, outIdx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + T *inPtr0, *inPtr1, *inPtr2; + T *outPtr0, *outPtr1, *outPtr2; + int numComps, outIdxC; + // For looping through hood pixels + int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2; + int hoodIdx0, hoodIdx1, hoodIdx2; + T *hoodPtr0, *hoodPtr1, *hoodPtr2; + // For looping through the mask. + unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2; + vtkIdType maskInc0, maskInc1, maskInc2; + // The extent of the whole input image + int inImageMin0, inImageMin1, inImageMin2; + int inImageMax0, inImageMax1, inImageMax2; + int inImageExt[6]; + // to compute the range + T pixelMin; + unsigned long count = 0; + unsigned long target; + int *inExt = inData->GetExtent(); + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inImageExt); + inImageMin0 = inImageExt[0]; + inImageMax0 = inImageExt[1]; + inImageMin1 = inImageExt[2]; + inImageMax1 = inImageExt[3]; + inImageMin2 = inImageExt[4]; + inImageMax2 = inImageExt[5]; + outData->GetIncrements(outInc0, outInc1, outInc2); + outMin0 = outExt[0]; outMax0 = outExt[1]; + outMin1 = outExt[2]; outMax1 = outExt[3]; + outMin2 = outExt[4]; outMax2 = outExt[5]; + numComps = outData->GetNumberOfScalarComponents(); + + // Get ivars of this object (easier than making friends) + kernelSize = self->GetKernelSize(); + kernelMiddle = self->GetKernelMiddle(); + hoodMin0 = - kernelMiddle[0]; + hoodMin1 = - kernelMiddle[1]; + hoodMin2 = - kernelMiddle[2]; + hoodMax0 = hoodMin0 + kernelSize[0] - 1; + hoodMax1 = hoodMin1 + kernelSize[1] - 1; + hoodMax2 = hoodMin2 + kernelSize[2] - 1; + + // Setup mask info + maskPtr = (unsigned char *)(mask->GetScalarPointer()); + mask->GetIncrements(maskInc0, maskInc1, maskInc2); + + // in and out should be marching through corresponding pixels. + inPtr = (T *)(inArray->GetVoidPointer((outMin0-inExt[0])*inInc0 + + (outMin1-inExt[2])*inInc1 + + (outMin2-inExt[4])*inInc2)); + + target = (unsigned long)(numComps*(outMax2-outMin2+1)* + (outMax1-outMin1+1)/50.0); + target++; + + // loop through components + for (outIdxC = 0; outIdxC < numComps; ++outIdxC) + { + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outMin1; + !self->AbortExecute && outIdx1 <= outMax1; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0) + { + + // Find min + pixelMin = *inPtr0; + // loop through neighborhood pixels + // as sort of a hack to handle boundaries, + // input pointer will be marching through data that does not exist. + hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0 + - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2; + maskPtr2 = maskPtr; + for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2) + { + hoodPtr1 = hoodPtr2; + maskPtr1 = maskPtr2; + for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1) + { + hoodPtr0 = hoodPtr1; + maskPtr0 = maskPtr1; + for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0) + { + // A quick but rather expensive way to handle boundaries + if ( outIdx0 + hoodIdx0 >= inImageMin0 && + outIdx0 + hoodIdx0 <= inImageMax0 && + outIdx1 + hoodIdx1 >= inImageMin1 && + outIdx1 + hoodIdx1 <= inImageMax1 && + outIdx2 + hoodIdx2 >= inImageMin2 && + outIdx2 + hoodIdx2 <= inImageMax2) + { + if (*maskPtr0) + { + if (*hoodPtr0 < pixelMin) + { + pixelMin = *hoodPtr0; + } + } + } + + hoodPtr0 += inInc0; + maskPtr0 += maskInc0; + } + hoodPtr1 += inInc1; + maskPtr1 += maskInc1; + } + hoodPtr2 += inInc2; + maskPtr2 += maskInc2; + } + *outPtr0 = pixelMin; + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + ++inPtr; + ++outPtr; + } +} + +//---------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output Data types. +// It hanldes image boundaries, so the image does not shrink. +void vtkImageContinuousErode3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + // return if nothing to do + if (outExt[1] < outExt[0] || + outExt[3] < outExt[2] || + outExt[5] < outExt[4]) + { + return; + } + + int inExt[6], wholeExt[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt,outExt,wholeExt); + void *inPtr; + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + vtkImageData *mask; + + vtkDataArray *inArray = this->GetInputArrayToProcess(0,inputVector); + + // The inPtr is reset anyway, so just get the id 0 pointer. + inPtr = inArray->GetVoidPointer(0); + + // Error checking on mask + mask = this->Ellipse->GetOutput(); + if (mask->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro(<< "Execute: mask has wrong scalar type"); + return; + } + + // this filter expects the output type to be same as input + if (outData[0]->GetScalarType() != inArray->GetDataType()) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << " must match input array data type"); + return; + } + + switch (inArray->GetDataType()) + { + vtkTemplateMacro( + vtkImageContinuousErode3DExecute(this, mask, + inData[0][0], + (VTK_TT *)(inPtr), + outData[0], outExt, + (VTK_TT *)(outPtr),id, inArray, + inInfo)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkImageContinuousErode3D::RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Ellipse->GetOutput()->Update(); + return this->Superclass::RequestData(request, inputVector, outputVector); +} diff --git a/Imaging/vtkImageContinuousErode3D.h b/Imaging/vtkImageContinuousErode3D.h new file mode 100644 index 0000000..3e0b66b --- /dev/null +++ b/Imaging/vtkImageContinuousErode3D.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageContinuousErode3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageContinuousErode3D - Erosion implemented as a minimum. +// .SECTION Description +// vtkImageContinuousErode3D replaces a pixel with the minimum over +// an ellipsoidal neighborhood. If KernelSize of an axis is 1, no processing +// is done on that axis. + + +#ifndef __vtkImageContinuousErode3D_h +#define __vtkImageContinuousErode3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class vtkImageEllipsoidSource; + +class VTK_IMAGING_EXPORT vtkImageContinuousErode3D : public vtkImageSpatialAlgorithm +{ +public: + // Description: + // Construct an instance of vtkImageContinuousErode3D filter. + // By default zero values are eroded. + static vtkImageContinuousErode3D *New(); + vtkTypeRevisionMacro(vtkImageContinuousErode3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sets the size of the neighborhood. It also sets the + // default middle of the neighborhood and computes the elliptical foot print. + void SetKernelSize(int size0, int size1, int size2); + +protected: + vtkImageContinuousErode3D(); + ~vtkImageContinuousErode3D(); + + vtkImageEllipsoidSource *Ellipse; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + +private: + vtkImageContinuousErode3D(const vtkImageContinuousErode3D&); // Not implemented. + void operator=(const vtkImageContinuousErode3D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageConvolve.cxx b/Imaging/vtkImageConvolve.cxx new file mode 100644 index 0000000..395b81c --- /dev/null +++ b/Imaging/vtkImageConvolve.cxx @@ -0,0 +1,479 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageConvolve.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageConvolve.h" +#include "vtkImageData.h" +#include "vtkImageEllipsoidSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageConvolve, "$Revision: 1.18 $"); +vtkStandardNewMacro(vtkImageConvolve); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageConvolve fitler. +// By default zero values are eroded. +vtkImageConvolve::vtkImageConvolve() +{ + int idx; + for (idx = 0; idx < 343; idx++) + { + this->Kernel[idx] = 0.0; + } + + // Construct a primary id function kernel that does nothing at all + double kernel[9]; + for (idx = 0; idx < 9; idx++) + { + kernel[idx] = 0.0; + } + kernel[4] = 1.0; + this->SetKernel3x3(kernel); +} + +//---------------------------------------------------------------------------- +// Destructor +vtkImageConvolve::~vtkImageConvolve() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageConvolve::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "KernelSize: (" << + this->KernelSize[0] << ", " << + this->KernelSize[1] << ", " << + this->KernelSize[2] << ")\n"; + + os << indent << "Kernel: ("; + for (int k = 0; k < this->KernelSize[2]; k++) + { + for (int j = 0; j < this->KernelSize[1]; j++) + { + for (int i = 0; i < this->KernelSize[0]; i++) + { + os << this->Kernel[this->KernelSize[1]*this->KernelSize[0]*k + + this->KernelSize[0]*j + + i]; + + if (i != this->KernelSize[0] - 1) + { + os << ", "; + } + } + if (j != this->KernelSize[1] - 1 || k != this->KernelSize[2] - 1) + { + os << ",\n" << indent << " "; + } + } + } + os << ")\n"; +} + +//---------------------------------------------------------------------------- +// Set a 3x3 kernel +void vtkImageConvolve::SetKernel3x3(const double kernel[9]) +{ + // Fill the kernel + this->SetKernel(kernel, 3, 3, 1); +} + +//---------------------------------------------------------------------------- +// Set a 5x5 kernel +void vtkImageConvolve::SetKernel5x5(const double kernel[25]) +{ + // Fill the kernel + this->SetKernel(kernel, 5, 5, 1); +} + +//---------------------------------------------------------------------------- +// Set a 7x7 kernel +void vtkImageConvolve::SetKernel7x7(double kernel[49]) +{ + // Fill the kernel + this->SetKernel(kernel, 7, 7, 1); +} + +//---------------------------------------------------------------------------- +// Set a 3x3x3 kernel +void vtkImageConvolve::SetKernel3x3x3(const double kernel[27]) +{ + // Fill the kernel + this->SetKernel(kernel, 3, 3, 3); +} + +//---------------------------------------------------------------------------- +// Set a 5x5x5 kernel +void vtkImageConvolve::SetKernel5x5x5(double kernel[125]) +{ + // Fill the kernel + this->SetKernel(kernel, 5, 5, 5); +} + +//---------------------------------------------------------------------------- +// Set a 7x7x7 kernel +void vtkImageConvolve::SetKernel7x7x7(double kernel[343]) +{ + // Fill the kernel + this->SetKernel(kernel, 7, 7, 7); +} + +//---------------------------------------------------------------------------- +// Set a kernel, this is an internal method +void vtkImageConvolve::SetKernel(const double* kernel, + int sizeX, int sizeY, int sizeZ) +{ + int modified=0; + + // Set the correct kernel size + this->KernelSize[0] = sizeX; + this->KernelSize[1] = sizeY; + this->KernelSize[2] = sizeZ; + + int kernelLength = sizeX*sizeY*sizeZ; + + for (int idx = 0; idx < kernelLength; idx++) + { + if ( this->Kernel[idx] != kernel[idx] ) + { + modified = 1; + this->Kernel[idx] = kernel[idx]; + } + } + if (modified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// Get the 3x3 kernel +double* vtkImageConvolve::GetKernel3x3() +{ + return this->GetKernel(); +} + +//---------------------------------------------------------------------------- +// Get the 5x5 kernel +double* vtkImageConvolve::GetKernel5x5() +{ + return this->GetKernel(); +} + +//---------------------------------------------------------------------------- +// Get the 7x7 kernel +double* vtkImageConvolve::GetKernel7x7() +{ + return this->GetKernel(); +} + +//---------------------------------------------------------------------------- +// Get the 3x3x3 kernel +double* vtkImageConvolve::GetKernel3x3x3() +{ + return this->GetKernel(); +} + +//---------------------------------------------------------------------------- +// Get the 5x5x5 kernel +double* vtkImageConvolve::GetKernel5x5x5() +{ + return this->GetKernel(); +} + +//---------------------------------------------------------------------------- +// Get the 7x7x7 kernel +double* vtkImageConvolve::GetKernel7x7x7() +{ + return this->GetKernel(); +} + +//---------------------------------------------------------------------------- +// Get the kernel, this is an internal method +double* vtkImageConvolve::GetKernel() +{ + return this->Kernel; +} + +//---------------------------------------------------------------------------- +// Get the kernel +void vtkImageConvolve::GetKernel3x3(double kernel[9]) +{ + this->GetKernel(kernel); +} + +//---------------------------------------------------------------------------- +// Get the kernel +void vtkImageConvolve::GetKernel5x5(double kernel[25]) +{ + this->GetKernel(kernel); +} + +//---------------------------------------------------------------------------- +// Get the kernel +void vtkImageConvolve::GetKernel7x7(double kernel[49]) +{ + this->GetKernel(kernel); +} + +//---------------------------------------------------------------------------- +// Get the kernel +void vtkImageConvolve::GetKernel3x3x3(double kernel[27]) +{ + this->GetKernel(kernel); +} + +//---------------------------------------------------------------------------- +// Get the kernel +void vtkImageConvolve::GetKernel5x5x5(double kernel[125]) +{ + this->GetKernel(kernel); +} + +//---------------------------------------------------------------------------- +// Get the kernel +void vtkImageConvolve::GetKernel7x7x7(double kernel[343]) +{ + this->GetKernel(kernel); +} + +//---------------------------------------------------------------------------- +// Get the kernel, this is an internal method +void vtkImageConvolve::GetKernel(double *kernel) +{ + int kernelLength = this->KernelSize[0]* + this->KernelSize[1]*this->KernelSize[2]; + + for (int idx = 0; idx < kernelLength; idx++) + { + kernel[idx] = this->Kernel[idx]; + } +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter on any region, +// whether it needs boundary checking or not. +// If the filter needs to be faster, the function could be duplicated +// for strictly center (no boundary) processing. +template +void vtkImageConvolveExecute(vtkImageConvolve *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id, + vtkInformation *inInfo) +{ + int *kernelSize; + int kernelMiddle[3]; + + // For looping though output (and input) pixels. + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + int outIdx0, outIdx1, outIdx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + T *inPtr0, *inPtr1, *inPtr2; + T *outPtr0, *outPtr1, *outPtr2; + int numComps, outIdxC; + + // For looping through hood pixels + int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2; + int hoodIdx0, hoodIdx1, hoodIdx2; + T *hoodPtr0, *hoodPtr1, *hoodPtr2; + + // For looping through the kernel, and compute the kernel result + int kernelIdx; + double sum; + + // The extent of the whole input image + int inImageExt[6]; + + // to compute the range + unsigned long count = 0; + unsigned long target; + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inImageExt); + outData->GetIncrements(outInc0, outInc1, outInc2); + outMin0 = outExt[0]; outMax0 = outExt[1]; + outMin1 = outExt[2]; outMax1 = outExt[3]; + outMin2 = outExt[4]; outMax2 = outExt[5]; + numComps = outData->GetNumberOfScalarComponents(); + + // Get ivars of this object (easier than making friends) + kernelSize = self->GetKernelSize(); + + kernelMiddle[0] = kernelSize[0] / 2; + kernelMiddle[1] = kernelSize[1] / 2; + kernelMiddle[2] = kernelSize[2] / 2; + + hoodMin0 = -kernelMiddle[0]; + hoodMin1 = -kernelMiddle[1]; + hoodMin2 = -kernelMiddle[2]; + + hoodMax0 = hoodMin0 + kernelSize[0] - 1; + hoodMax1 = hoodMin1 + kernelSize[1] - 1; + hoodMax2 = hoodMin2 + kernelSize[2] - 1; + + // Get the kernel, just use GetKernel7x7x7(kernel) if the kernel is smaller + // it still works :) + double kernel[343]; + self->GetKernel7x7x7(kernel); + + // in and out should be marching through corresponding pixels. + inPtr = (T *)(inData->GetScalarPointer(outMin0, outMin1, outMin2)); + + target = (unsigned long)(numComps*(outMax2 - outMin2 + 1)* + (outMax1 - outMin1 + 1)/50.0); + target++; + + // loop through components + for (outIdxC = 0; outIdxC < numComps; ++outIdxC) + { + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outMin1; + outIdx1 <= outMax1 && !self->AbortExecute; + ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + outPtr0 = outPtr1; + inPtr0 = inPtr1; + + for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0) + { + // Inner loop where we compute the kernel + + // Set the sum to zero + sum = 0; + + // loop through neighborhood pixels + // as sort of a hack to handle boundaries, + // input pointer will be marching through data that does not exist. + hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0 + - kernelMiddle[1] * inInc1 + - kernelMiddle[2] * inInc2; + + // Set the kernel index to the starting position + kernelIdx = 0; + + for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2) + { + hoodPtr1 = hoodPtr2; + + for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1) + { + hoodPtr0 = hoodPtr1; + + for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0) + { + // A quick but rather expensive way to handle boundaries + // This assumes the boundary values are zero + if (outIdx0 + hoodIdx0 >= inImageExt[0] && + outIdx0 + hoodIdx0 <= inImageExt[1] && + outIdx1 + hoodIdx1 >= inImageExt[2] && + outIdx1 + hoodIdx1 <= inImageExt[3] && + outIdx2 + hoodIdx2 >= inImageExt[4] && + outIdx2 + hoodIdx2 <= inImageExt[5]) + { + sum += *hoodPtr0 * kernel[kernelIdx]; + + // Take the next postion in the kernel + kernelIdx++; + } + + hoodPtr0 += inInc0; + } + + hoodPtr1 += inInc1; + } + + hoodPtr2 += inInc2; + } + + // Set the output pixel to the correct value + *outPtr0 = (T)sum; + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + + inPtr1 += inInc1; + outPtr1 += outInc1; + } + + inPtr2 += inInc2; + outPtr2 += outInc2; + } + + ++inPtr; + ++outPtr; + } +} + +//---------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output Data types. +// It hanldes image boundaries, so the image does not shrink. +void vtkImageConvolve::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // this filter expects the output type to be same as input + if (outData[0]->GetScalarType() != inData[0][0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << " must match input scalar type"); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageConvolveExecute(this, inData[0][0], + (VTK_TT *)(inPtr), outData[0], + (VTK_TT *)(outPtr), + outExt, id, inInfo)); + + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageConvolve.h b/Imaging/vtkImageConvolve.h new file mode 100644 index 0000000..16dee7d --- /dev/null +++ b/Imaging/vtkImageConvolve.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageConvolve.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageConvolve - Convolution of an image with a kernel. +// .SECTION Description +// vtkImageConvolve convolves the image with a 3D NxNxN kernel or a +// 2D NxN kernal. The output image is cropped to the same size as +// the input. + +#ifndef __vtkImageConvolve_h +#define __vtkImageConvolve_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageConvolve : public vtkThreadedImageAlgorithm +{ +public: + // Description: + // Construct an instance of vtkImageConvolve filter. + static vtkImageConvolve *New(); + vtkTypeRevisionMacro(vtkImageConvolve,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the kernel size + vtkGetVector3Macro(KernelSize, int); + + // Description: + // Set the kernel to be a given 3x3 or 5x5 or 7x7 kernel. + void SetKernel3x3(const double kernel[9]); + void SetKernel5x5(const double kernel[25]); +//BTX + void SetKernel7x7(double kernel[49]); +//ETX + + // Description: + // Return an array that contains the kernel. + double* GetKernel3x3(); + void GetKernel3x3(double kernel[9]); + double* GetKernel5x5(); + void GetKernel5x5(double kernel[25]); +//BTX + double* GetKernel7x7(); + void GetKernel7x7(double kernel[49]); +//ETX + + // Description: + // Set the kernel to be a 3x3x3 or 5x5x5 or 7x7x7 kernel. + void SetKernel3x3x3(const double kernel[27]); +//BTX + void SetKernel5x5x5(double kernel[125]); + void SetKernel7x7x7(double kernel[343]); +//ETX + + // Description: + // Return an array that contains the kernel + double* GetKernel3x3x3(); + void GetKernel3x3x3(double kernel[27]); +//BTX + double* GetKernel5x5x5(); + void GetKernel5x5x5(double kernel[125]); + double* GetKernel7x7x7(); + void GetKernel7x7x7(double kernel[343]); +//ETX + +protected: + vtkImageConvolve(); + ~vtkImageConvolve(); + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); + + void GetKernel(double *kernel); + double* GetKernel(); + void SetKernel(const double* kernel, + int sizeX, int sizeY, int sizeZ); + + + int KernelSize[3]; + double Kernel[343]; +private: + vtkImageConvolve(const vtkImageConvolve&); // Not implemented. + void operator=(const vtkImageConvolve&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageCorrelation.cxx b/Imaging/vtkImageCorrelation.cxx new file mode 100644 index 0000000..a6e5b0e --- /dev/null +++ b/Imaging/vtkImageCorrelation.cxx @@ -0,0 +1,265 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCorrelation.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageCorrelation.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageCorrelation, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkImageCorrelation); + +//---------------------------------------------------------------------------- +vtkImageCorrelation::vtkImageCorrelation() +{ + this->Dimensionality = 2; + this->SetNumberOfInputPorts(2); +} + + +//---------------------------------------------------------------------------- +// Grow the output image +int vtkImageCorrelation::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// Grow +int vtkImageCorrelation::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo1 = inputVector[0]->GetInformationObject(0); + vtkInformation* inInfo2 = inputVector[1]->GetInformationObject(0); + + // get the whole image for input 2 + int inWExt2[6]; + inInfo2->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),inWExt2); + inInfo2->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + inWExt2, 6); + + int inWExt1[6]; + inInfo1->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),inWExt1); + + // try to get all the data required to handle the boundaries + // but limit to the whole extent + int idx; + int inUExt1[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inUExt1); + + for (idx = 0; idx < 3; idx++) + { + inUExt1[idx*2+1] = inUExt1[idx*2+1] + + (inWExt2[idx*2+1] - inWExt2[idx*2]); + + // clip to whole extent + if (inUExt1[idx*2+1] > inWExt1[idx*2+1]) + { + inUExt1[idx*2+1] = inWExt1[idx*2+1]; + } + } + inInfo1->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + inUExt1, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the two input operations +template +void vtkImageCorrelationExecute(vtkImageCorrelation *self, + vtkImageData *in1Data, T *in1Ptr, + vtkImageData *in2Data, T *in2Ptr, + vtkImageData *outData, float *outPtr, + int outExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int maxC, maxX, maxY, maxZ; + vtkIdType in1IncX, in1IncY, in1IncZ; + vtkIdType in1CIncX, in1CIncY, in1CIncZ; + vtkIdType in2IncX, in2IncY, in2IncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int *in2Extent; + T *in2Ptr2, *in1Ptr2; + int kIdxX, kIdxY, kIdxZ; + int xKernMax, yKernMax, zKernMax; + int maxIX, maxIY, maxIZ; + int *wExtent; + + // find the region to loop over + maxC = in1Data->GetNumberOfScalarComponents(); + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // get some other info we need + in2Extent = in2Data->GetWholeExtent(); + + // Get increments to march through data + in1Data->GetContinuousIncrements(outExt, in1CIncX, in1CIncY, in1CIncZ); + in1Data->GetIncrements(in1IncX, in1IncY, in1IncZ); + in2Data->GetIncrements(in2IncX, in2IncY, in2IncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // how far can we gon with input data + // this may be farther that the outExt because of + // subpieces etc. + wExtent = in1Data->GetExtent(); + maxIZ = wExtent[5] - outExt[4]; + maxIY = wExtent[3] - outExt[2]; + maxIX = wExtent[1] - outExt[0]; + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + // how much of kernel to use + zKernMax = maxIZ - idxZ; + if (zKernMax > in2Extent[5]) + { + zKernMax = in2Extent[5]; + } + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + yKernMax = maxIY - idxY; + if (yKernMax > in2Extent[3]) + { + yKernMax = in2Extent[3]; + } + for (idxX = 0; idxX <= maxX; idxX++) + { + // determine the extent of input 1 that contributes to this pixel + *outPtr = 0.0; + xKernMax = maxIX - idxX; + if (xKernMax > in2Extent[1]) + { + xKernMax = in2Extent[1]; + } + + // sumation + for (kIdxZ = 0; kIdxZ <= zKernMax; kIdxZ++) + { + for (kIdxY = 0; kIdxY <= yKernMax; kIdxY++) + { + in1Ptr2 = in1Ptr + kIdxY*in1IncY + kIdxZ*in1IncZ; + in2Ptr2 = in2Ptr + kIdxY*in2IncY + kIdxZ*in2IncZ; + for (kIdxX = 0; kIdxX <= xKernMax; kIdxX++) + { + for (idxC = 0; idxC < maxC; idxC++) + { + *outPtr = *outPtr + (float)((*in1Ptr2) * (*in2Ptr2)); + in1Ptr2++; + in2Ptr2++; + } + } + } + } + in1Ptr += maxC; + outPtr++; + } + in1Ptr += in1CIncY; + outPtr += outIncY; + } + in1Ptr += in1CIncZ; + outPtr += outIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This method is passed a input and output datas, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the datas data types. +void vtkImageCorrelation::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int *in2Extent; + void *in1Ptr; + void *in2Ptr; + float *outPtr; + + in2Extent = inData[1][0]->GetWholeExtent(); + in1Ptr = inData[0][0]->GetScalarPointerForExtent(outExt); + in2Ptr = inData[1][0]->GetScalarPointerForExtent(in2Extent); + outPtr = (float *)outData[0]->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != inData[1][0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << + inData[0][0]->GetScalarType() << " and input2 ScalarType " << + inData[1][0]->GetScalarType() << ", should match"); + return; + } + + // input depths must match + if (inData[0][0]->GetNumberOfScalarComponents() != + inData[1][0]->GetNumberOfScalarComponents()) + { + vtkErrorMacro(<< "Execute: input depths must match"); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCorrelationExecute(this, inData[0][0], + (VTK_TT *)(in1Ptr), + inData[1][0], + (VTK_TT *)(in2Ptr), + outData[0], outPtr, outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageCorrelation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; +} + diff --git a/Imaging/vtkImageCorrelation.h b/Imaging/vtkImageCorrelation.h new file mode 100644 index 0000000..bda2a0b --- /dev/null +++ b/Imaging/vtkImageCorrelation.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCorrelation.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageCorrelation - Correlation imageof the two inputs. +// .SECTION Description +// vtkImageCorrelation finds the correlation between two data sets. +// SetDimensionality determines +// whether the Correlation will be 3D, 2D or 1D. +// The default is a 2D Correlation. The Output type will be double. +// The output size will match the size of the first input. +// The second input is considered the correlation kernel. + +#ifndef __vtkImageCorrelation_h +#define __vtkImageCorrelation_h + + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageCorrelation : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageCorrelation *New(); + vtkTypeRevisionMacro(vtkImageCorrelation,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Determines how the input is interpreted (set of 2d slices ...) + vtkSetClampMacro(Dimensionality,int,2,3); + vtkGetMacro(Dimensionality,int); + + // Description: + // Set the two inputs to this filter + virtual void SetInput1(vtkDataObject *in) { this->SetInput(0,in); } + virtual void SetInput2(vtkDataObject *in) { this->SetInput(1,in); } + +protected: + vtkImageCorrelation(); + ~vtkImageCorrelation() {}; + + int Dimensionality; + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + +private: + vtkImageCorrelation(const vtkImageCorrelation&); // Not implemented. + void operator=(const vtkImageCorrelation&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageCursor3D.cxx b/Imaging/vtkImageCursor3D.cxx new file mode 100644 index 0000000..5cf932f --- /dev/null +++ b/Imaging/vtkImageCursor3D.cxx @@ -0,0 +1,142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCursor3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageCursor3D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageCursor3D, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkImageCursor3D); + +//---------------------------------------------------------------------------- +void vtkImageCursor3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + + os << indent << "Cursor Radius: " << this->CursorRadius << "\n"; + os << indent << "Cursor Value: " << this->CursorValue << "\n"; + os << indent << "Cursor Position: (" << this->CursorPosition[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->CursorPosition[idx]; + } + os << ")\n"; +} + +//---------------------------------------------------------------------------- +vtkImageCursor3D::vtkImageCursor3D() +{ + this->CursorPosition[0] = 0; + this->CursorPosition[1] = 0; + this->CursorPosition[2] = 0; + + this->CursorRadius = 5; + this->CursorValue = 255; +} + + + +template +void vtkImageCursor3DExecute(vtkImageCursor3D *self, + vtkImageData *outData, T *ptr) +{ + int min0, max0, min1, max1, min2, max2; + int c0, c1, c2; + int idx; + double value; + int rad = self->GetCursorRadius(); + + c0 = (int)(self->GetCursorPosition()[0]); + c1 = (int)(self->GetCursorPosition()[1]); + c2 = (int)(self->GetCursorPosition()[2]); + value = self->GetCursorValue(); + + outData->GetExtent(min0, max0, min1, max1, min2, max2); + + if (c1 >= min1 && c1 <= max1 && c2 >= min2 && c2 <= max2) + { + for (idx = c0 - rad; idx <= c0 + rad; ++idx) + { + if (idx >= min0 && idx <= max0) + { + ptr = (T *)(outData->GetScalarPointer(idx, c1, c2)); + *ptr = (T)(value); + } + } + } + + + if (c0 >= min0 && c0 <= max0 && c2 >= min2 && c2 <= max2) + { + for (idx = c1 - rad; idx <= c1 + rad; ++idx) + { + if (idx >= min1 && idx <= max1) + { + ptr = (T *)(outData->GetScalarPointer(c0, idx, c2)); + *ptr = (T)(value); + } + } + } + + + if (c0 >= min0 && c0 <= max0 && c1 >= min1 && c1 <= max1) + { + for (idx = c2 - rad; idx <= c2 + rad; ++idx) + { + if (idx >= min2 && idx <= max2) + { + ptr = (T *)(outData->GetScalarPointer(c0, c1, idx)); + *ptr = (T)(value); + } + } + } +} + +//---------------------------------------------------------------------------- +// Split up into finished and border datas. Fill the border datas. +int vtkImageCursor3D::RequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + void *ptr = NULL; + + // let superclass allocate data + this->Superclass::RequestData(request, inputVector, outputVector); + + // get the data object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *outData = + vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + switch (outData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageCursor3DExecute(this,outData, (VTK_TT *)(ptr))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 1; + } + + return 1; +} + + + + diff --git a/Imaging/vtkImageCursor3D.h b/Imaging/vtkImageCursor3D.h new file mode 100644 index 0000000..dd20571 --- /dev/null +++ b/Imaging/vtkImageCursor3D.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageCursor3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageCursor3D - Paints a cursor on top of an image or volume. +// .SECTION Description +// vtkImageCursor3D will draw a cursor on a 2d image or 3d volume. + +#ifndef __vtkImageCursor3D_h +#define __vtkImageCursor3D_h + +#include "vtkImageInPlaceFilter.h" + +class VTK_IMAGING_EXPORT vtkImageCursor3D : public vtkImageInPlaceFilter +{ +public: + static vtkImageCursor3D *New(); + vtkTypeRevisionMacro(vtkImageCursor3D,vtkImageInPlaceFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + + // Description: + // Sets/Gets the center point of the 3d cursor. + vtkSetVector3Macro(CursorPosition, double); + vtkGetVector3Macro(CursorPosition, double); + + // Description: + // Sets/Gets what pixel value to draw the cursor in. + vtkSetMacro(CursorValue, double); + vtkGetMacro(CursorValue, double); + + // Description: + // Sets/Gets the radius of the cursor. The radius determines + // how far the axis lines project out from the cursors center. + vtkSetMacro(CursorRadius, int); + vtkGetMacro(CursorRadius, int); + + +protected: + vtkImageCursor3D(); + ~vtkImageCursor3D() {}; + + double CursorPosition[3]; + double CursorValue; + int CursorRadius; + + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + +private: + vtkImageCursor3D(const vtkImageCursor3D&); // Not implemented. + void operator=(const vtkImageCursor3D&); // Not implemented. +}; + + + +#endif + + + diff --git a/Imaging/vtkImageDataStreamer.cxx b/Imaging/vtkImageDataStreamer.cxx new file mode 100644 index 0000000..4f8e125 --- /dev/null +++ b/Imaging/vtkImageDataStreamer.cxx @@ -0,0 +1,141 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDataStreamer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageDataStreamer.h" + +#include "vtkCommand.h" +#include "vtkExtentTranslator.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageDataStreamer, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkImageDataStreamer); +vtkCxxSetObjectMacro(vtkImageDataStreamer,ExtentTranslator,vtkExtentTranslator); + +//---------------------------------------------------------------------------- +vtkImageDataStreamer::vtkImageDataStreamer() +{ + // default to 10 divisions + this->NumberOfStreamDivisions = 10; + this->CurrentDivision = 0; + + // create default translator + this->ExtentTranslator = vtkExtentTranslator::New(); + + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +vtkImageDataStreamer::~vtkImageDataStreamer() +{ + if (this->ExtentTranslator) + { + this->ExtentTranslator->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageDataStreamer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfStreamDivisions: " << this->NumberOfStreamDivisions << endl; + if ( this->ExtentTranslator ) + { + os << indent << "ExtentTranslator:\n"; + this->ExtentTranslator->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "ExtentTranslator: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +int vtkImageDataStreamer::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + // we must set the extent on the input + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + // get the requested update extent + int outExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); + + // setup the inputs update extent + int inExt[6] = {0, -1, 0, -1, 0, -1}; + vtkExtentTranslator *translator = this->GetExtentTranslator(); + + translator->SetWholeExtent(outExt); + translator->SetNumberOfPieces(this->NumberOfStreamDivisions); + translator->SetPiece(this->CurrentDivision); + if (translator->PieceToExtentByPoints()) + { + translator->GetExtent(inExt); + } + + inputVector[0]->GetInformationObject(0) + ->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + return 1; + } + + // generate the data + else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + // get the output data object + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = + vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + + // is this the first request + if (!this->CurrentDivision) + { + // Tell the pipeline to start looping. + request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); + this->AllocateOutputData(output); + } + + // actually copy the data + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *input = + vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + + int inExt[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt); + output->CopyAndCastFrom(input, inExt); + + // update the progress + this->UpdateProgress( + (float)(this->CurrentDivision+1.0)/(float)this->NumberOfStreamDivisions); + + this->CurrentDivision++; + if (this->CurrentDivision == this->NumberOfStreamDivisions) + { + // Tell the pipeline to stop looping. + request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); + this->CurrentDivision = 0; + } + + return 1; + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} diff --git a/Imaging/vtkImageDataStreamer.h b/Imaging/vtkImageDataStreamer.h new file mode 100644 index 0000000..11bd70b --- /dev/null +++ b/Imaging/vtkImageDataStreamer.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDataStreamer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageDataStreamer - Initiates streaming on image data. +// .SECTION Description +// To satisfy a request, this filter calls update on its input +// many times with smaller update extents. All processing up stream +// streams smaller pieces. + +#ifndef __vtkImageDataStreamer_h +#define __vtkImageDataStreamer_h + +#include "vtkImageAlgorithm.h" + +class vtkExtentTranslator; + +class VTK_IMAGING_EXPORT vtkImageDataStreamer : public vtkImageAlgorithm +{ +public: + static vtkImageDataStreamer *New(); + vtkTypeRevisionMacro(vtkImageDataStreamer,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set how many pieces to divide the input into. + // void SetNumberOfStreamDivisions(int num); + // int GetNumberOfStreamDivisions(); + vtkSetMacro(NumberOfStreamDivisions,int); + vtkGetMacro(NumberOfStreamDivisions,int); + + virtual void Update() { this->vtkAlgorithm::Update();}; + virtual void UpdateWholeExtent() { + this->vtkAlgorithm::UpdateWholeExtent();}; + + // Description: + // Get the extent translator that will be used to split the requests + virtual void SetExtentTranslator(vtkExtentTranslator*); + vtkGetObjectMacro(ExtentTranslator,vtkExtentTranslator); + + // See the vtkAlgorithm for a desciption of what these do + int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkImageDataStreamer(); + ~vtkImageDataStreamer(); + + vtkExtentTranslator *ExtentTranslator; + int NumberOfStreamDivisions; + int CurrentDivision; +private: + vtkImageDataStreamer(const vtkImageDataStreamer&); // Not implemented. + void operator=(const vtkImageDataStreamer&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageDecomposeFilter.cxx b/Imaging/vtkImageDecomposeFilter.cxx new file mode 100644 index 0000000..9fdc758 --- /dev/null +++ b/Imaging/vtkImageDecomposeFilter.cxx @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDecomposeFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageDecomposeFilter.h" + +#include + +vtkCxxRevisionMacro(vtkImageDecomposeFilter, "$Revision: 1.20 $"); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageDecomposeFilter fitler. +vtkImageDecomposeFilter::vtkImageDecomposeFilter() +{ + this->Dimensionality = 3; + this->SetNumberOfIterations(3); +} + + +//---------------------------------------------------------------------------- +void vtkImageDecomposeFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkImageDecomposeFilter::SetDimensionality(int dim) +{ + if (this->Dimensionality == dim) + { + return; + } + + if (dim < 1 || dim > 3) + { + vtkErrorMacro("SetDimensionality: Bad dim: " << dim); + return; + } + + this->Dimensionality = dim; + this->SetNumberOfIterations(dim); + this->Modified(); +} + + +//---------------------------------------------------------------------------- +void vtkImageDecomposeFilter::PermuteIncrements(vtkIdType *increments, + vtkIdType &inc0, + vtkIdType &inc1, + vtkIdType &inc2) +{ + switch (this->Iteration) + { + case 0: + inc0 = increments[0]; + inc1 = increments[1]; + inc2 = increments[2]; + break; + case 1: + inc1 = increments[0]; + inc0 = increments[1]; + inc2 = increments[2]; + break; + case 2: + inc1 = increments[0]; + inc2 = increments[1]; + inc0 = increments[2]; + break; + } +} + + +//---------------------------------------------------------------------------- +void vtkImageDecomposeFilter::PermuteExtent(int *extent, int &min0, int &max0, + int &min1, int &max1, + int &min2, int &max2) +{ + switch (this->Iteration) + { + case 0: + min0 = extent[0]; max0 = extent[1]; + min1 = extent[2]; max1 = extent[3]; + min2 = extent[4]; max2 = extent[5]; + break; + case 1: + min1 = extent[0]; max1 = extent[1]; + min0 = extent[2]; max0 = extent[3]; + min2 = extent[4]; max2 = extent[5]; + break; + case 2: + min1 = extent[0]; max1 = extent[1]; + min2 = extent[2]; max2 = extent[3]; + min0 = extent[4]; max0 = extent[5]; + break; + } +} + + + + + + + + + + + + + + + + + + diff --git a/Imaging/vtkImageDecomposeFilter.h b/Imaging/vtkImageDecomposeFilter.h new file mode 100644 index 0000000..5b89c05 --- /dev/null +++ b/Imaging/vtkImageDecomposeFilter.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDecomposeFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageDecomposeFilter - Filters that execute axes in series. +// .SECTION Description +// This superclass molds the vtkImageIterateFilter superclass so +// it iterates over the axes. The filter uses dimensionality to +// determine how many axes to execute (starting from x). +// The filter also provides convenience methods for permuting information +// retrieved from input, output and vtkImageData. + +#ifndef __vtkImageDecomposeFilter_h +#define __vtkImageDecomposeFilter_h + + +#include "vtkImageIterateFilter.h" + +class VTK_IMAGING_EXPORT vtkImageDecomposeFilter : public vtkImageIterateFilter +{ +public: + // Description: + // Construct an instance of vtkImageDecomposeFilter filter with default + // dimensionality 3. + vtkTypeRevisionMacro(vtkImageDecomposeFilter,vtkImageIterateFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Dimensionality is the number of axes which are considered during + // execution. To process images dimensionality would be set to 2. + void SetDimensionality(int dim); + vtkGetMacro(Dimensionality,int); + + // Description: + // Private methods kept public for template execute functions. + void PermuteIncrements(vtkIdType *increments, vtkIdType &inc0, + vtkIdType &inc1, vtkIdType &inc2); + void PermuteExtent(int *extent, int &min0, int &max0, int &min1, int &max1, + int &min2, int &max2); + +protected: + vtkImageDecomposeFilter(); + ~vtkImageDecomposeFilter() {}; + + int Dimensionality; + + +private: + vtkImageDecomposeFilter(const vtkImageDecomposeFilter&); // Not implemented. + void operator=(const vtkImageDecomposeFilter&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageDifference.cxx b/Imaging/vtkImageDifference.cxx new file mode 100644 index 0000000..8cb35cc --- /dev/null +++ b/Imaging/vtkImageDifference.cxx @@ -0,0 +1,473 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDifference.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageDifference.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageDifference, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkImageDifference); + +// Construct object to extract all of the input data. +vtkImageDifference::vtkImageDifference() +{ + int i; + for ( i = 0; i < this->NumberOfThreads; i++ ) + { + this->ErrorPerThread[i] = 0; + this->ThresholdedErrorPerThread[i] = 0.0; + } + this->Threshold = 16; + this->AllowShift = 1; + this->Averaging = 1; + this->SetNumberOfInputPorts(2); +} + + + +// not so simple macro for calculating error +#define vtkImageDifferenceComputeError(c1,c2) \ +/* compute the pixel to pixel difference first */ \ +r1 = abs(((int)(c1)[0] - (int)(c2)[0])); \ +g1 = abs(((int)(c1)[1] - (int)(c2)[1])); \ +b1 = abs(((int)(c1)[2] - (int)(c2)[2]));\ +if ((r1+g1+b1) < (tr+tg+tb)) { tr = r1; tg = g1; tb = b1; } \ +/* if averaging is on and we have neighbor info then compute */ \ +/* input1 to avg(input2) */ \ +if (this->Averaging && \ + (idx0 > inMinX + 1) && (idx0 < inMaxX - 1) && \ + (idx1 > inMinY + 1) && (idx1 < inMaxY - 1)) \ + {\ + ar1 = (int)(c1)[0]; \ + ag1 = (int)(c1)[1]; \ + ab1 = (int)(c1)[2]; \ + ar2 = (int)(c2)[0] + (int)(c2 - in2Inc0)[0] + (int)(c2 + in2Inc0)[0] + \ + (int)(c2-in2Inc1)[0] + (int)(c2-in2Inc1-in2Inc0)[0] + (int)(c2-in2Inc1+in2Inc0)[0] + \ + (int)(c2+in2Inc1)[0] + (int)(c2+in2Inc1-in2Inc0)[0] + (int)(c2+in2Inc1+in2Inc0)[0]; \ + ag2 = (int)(c2)[1] + (int)(c2 - in2Inc0)[1] + (int)(c2 + in2Inc0)[1] + \ + (int)(c2-in2Inc1)[1] + (int)(c2-in2Inc1-in2Inc0)[1] + (int)(c2-in2Inc1+in2Inc0)[1] + \ + (int)(c2+in2Inc1)[1] + (int)(c2+in2Inc1-in2Inc0)[1] + (int)(c2+in2Inc1+in2Inc0)[1]; \ + ab2 = (int)(c2)[2] + (int)(c2 - in2Inc0)[2] + (int)(c2 + in2Inc0)[2] + \ + (int)(c2-in2Inc1)[2] + (int)(c2-in2Inc1-in2Inc0)[2] + (int)(c2-in2Inc1+in2Inc0)[2] + \ + (int)(c2+in2Inc1)[2] + (int)(c2+in2Inc1-in2Inc0)[2] + (int)(c2+in2Inc1+in2Inc0)[2]; \ + r1 = abs(ar1 - ar2/9); \ + g1 = abs(ag1 - ag2/9); \ + b1 = abs(ab1 - ab2/9); \ + if ((r1+g1+b1) < (tr+tg+tb)) { tr = r1; tg = g1; tb = b1; } \ + /* Now compute the avg(input1) to avg(input2) comparison */ \ + ar1 = (int)(c1)[0] + (int)(c1 - in1Inc0)[0] + (int)(c1 + in1Inc0)[0] + \ + (int)(c1-in1Inc1)[0] + (int)(c1-in1Inc1-in1Inc0)[0] + (int)(c1-in1Inc1+in1Inc0)[0] + \ + (int)(c1+in1Inc1)[0] + (int)(c1+in1Inc1-in1Inc0)[0] + (int)(c1+in1Inc1+in1Inc0)[0]; \ + ag1 = (int)(int)(c1)[1] + (int)(c1 - in1Inc0)[1] + (int)(c1 + in1Inc0)[1] + \ + (int)(c1-in1Inc1)[1] + (int)(c1-in1Inc1-in1Inc0)[1] + (int)(c1-in1Inc1+in1Inc0)[1] + \ + (int)(c1+in1Inc1)[1] + (int)(c1+in1Inc1-in1Inc0)[1] + (int)(c1+in1Inc1+in1Inc0)[1]; \ + ab1 = (int)(int)(c1)[2] + (int)(c1 - in1Inc0)[2] + (int)(c1 + in1Inc0)[2] + \ + (int)(c1-in1Inc1)[2] + (int)(c1-in1Inc1-in1Inc0)[2] + (int)(c1-in1Inc1+in1Inc0)[2] + \ + (int)(c1+in1Inc1)[2] + (int)(c1+in1Inc1-in1Inc0)[2] + (int)(c1+in1Inc1+in1Inc0)[2]; \ + r1 = abs(ar1/9 - ar2/9); \ + g1 = abs(ag1/9 - ag2/9); \ + b1 = abs(ab1/9 - ab2/9); \ + if ((r1+g1+b1) < (tr+tg+tb)) { tr = r1; tg = g1; tb = b1; } \ + /* finally compute avg(input1) to input2) */ \ + ar2 = (int)(c2)[0]; \ + ag2 = (int)(c2)[1]; \ + ab2 = (int)(c2)[2]; \ + r1 = abs(ar1/9 - ar2); \ + g1 = abs(ag1/9 - ag2); \ + b1 = abs(ab1/9 - ab2); \ + if ((r1+g1+b1) < (tr+tg+tb)) { tr = r1; tg = g1; tb = b1; } \ + } + + + + +//---------------------------------------------------------------------------- +// This method computes the input extent necessary to generate the output. +int vtkImageDifference::RequestUpdateExtent( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int idx; + + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int *wholeExtent = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + int uExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),uExt); + + // grow input whole extent. + for (idx = 0; idx < 2; ++idx) + { + uExt[idx*2] -= 2; + uExt[idx*2+1] += 2; + + // we must clip extent with whole extent is we hanlde boundaries. + if (uExt[idx*2] < wholeExtent[idx*2]) + { + uExt[idx*2] = wholeExtent[idx*2]; + } + if (uExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + uExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),uExt,6); + + // now do the second input + inInfo = inputVector[1]->GetInformationObject(0); + wholeExtent = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),uExt); + + // grow input whole extent. + for (idx = 0; idx < 2; ++idx) + { + uExt[idx*2] -= 2; + uExt[idx*2+1] += 2; + + // we must clip extent with whole extent is we hanlde boundaries. + if (uExt[idx*2] < wholeExtent[idx*2]) + { + uExt[idx*2] = wholeExtent[idx*2]; + } + if (uExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + uExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),uExt,6); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageDifference::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + unsigned char *in1Ptr0, *in1Ptr1, *in1Ptr2; + unsigned char *in2Ptr0, *in2Ptr1, *in2Ptr2; + unsigned char *outPtr0, *outPtr1, *outPtr2; + int min0, max0, min1, max1, min2, max2; + int idx0, idx1, idx2; + vtkIdType in1Inc0, in1Inc1, in1Inc2; + vtkIdType in2Inc0, in2Inc1, in2Inc2; + vtkIdType outInc0, outInc1, outInc2; + int tr, tg, tb, r1, g1, b1; + int ar1, ag1, ab1, ar2, ag2, ab2; + int inMinX, inMaxX, inMinY, inMaxY; + int *inExt; + int matched; + unsigned long count = 0; + unsigned long target; + + this->ErrorPerThread[id] = 0; + this->ThresholdedErrorPerThread[id] = 0; + + if (inData[0] == NULL || inData[1] == NULL || outData == NULL) + { + if (!id) + { + vtkErrorMacro(<< "Execute: Missing data"); + } + this->ErrorPerThread[id] = 1000; + this->ThresholdedErrorPerThread[id] = 1000; + return; + } + + if (inData[0][0]->GetNumberOfScalarComponents() != 3 || + inData[1][0]->GetNumberOfScalarComponents() != 3 || + outData[0]->GetNumberOfScalarComponents() != 3) + { + if (!id) + { + vtkErrorMacro(<< "Execute: Expecting 3 components (RGB)"); + } + this->ErrorPerThread[id] = 1000; + this->ThresholdedErrorPerThread[id] = 1000; + return; + } + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != VTK_UNSIGNED_CHAR || + inData[1][0]->GetScalarType() != VTK_UNSIGNED_CHAR || + outData[0]->GetScalarType() != VTK_UNSIGNED_CHAR) + { + if (!id) + { + vtkErrorMacro(<< "Execute: All ScalarTypes must be unsigned char"); + } + this->ErrorPerThread[id] = 1000; + this->ThresholdedErrorPerThread[id] = 1000; + return; + } + + in1Ptr2 = (unsigned char *) inData[0][0]->GetScalarPointerForExtent(outExt); + in2Ptr2 = (unsigned char *) inData[1][0]->GetScalarPointerForExtent(outExt); + outPtr2 = (unsigned char *) outData[0]->GetScalarPointerForExtent(outExt); + + inData[0][0]->GetIncrements(in1Inc0, in1Inc1, in1Inc2); + inData[1][0]->GetIncrements(in2Inc0, in2Inc1, in2Inc2); + outData[0]->GetIncrements(outInc0, outInc1, outInc2); + + min0 = outExt[0]; max0 = outExt[1]; + min1 = outExt[2]; max1 = outExt[3]; + min2 = outExt[4]; max2 = outExt[5]; + + inExt = inData[0][0]->GetExtent(); + // we set min and Max to be one pixel in from actual values to support + // the 3x3 averaging we do + inMinX = inExt[0]; inMaxX = inExt[1]; + inMinY = inExt[2]; inMaxY = inExt[3]; + + target = (unsigned long)((max2 - min2 +1)*(max1 - min1 + 1)/50.0); + target++; + + for (idx2 = min2; idx2 <= max2; ++idx2) + { + in1Ptr1 = in1Ptr2; + in2Ptr1 = in2Ptr2; + outPtr1 = outPtr2; + for (idx1 = min1; !this->AbortExecute && idx1 <= max1; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + } + in1Ptr0 = in1Ptr1; + in2Ptr0 = in2Ptr1; + outPtr0 = outPtr1; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + tr = 1000; + tg = 1000; + tb = 1000; + + /* check the exact match pixel */ + vtkImageDifferenceComputeError(in1Ptr0,in2Ptr0); + + // do a quick check to see if this match is exact, if so + // we can save some seious time by skipping the eight + // connected neighbors + matched = 0; + if ((tr <= 0)&&(tg <= 0)&&(tb <= 0)) + { + matched = 1; + } + + /* If AllowShift, then we examine neighboring pixels to + find the least difference. This feature is used to + allow images to shift slightly between different graphics + systems, like between opengl and starbase. */ + if (!matched && this->AllowShift) + { + /* lower row */ + if (idx1 > inMinY) + { + vtkImageDifferenceComputeError(in1Ptr0-in1Inc1,in2Ptr0); + if (idx0 > inMinX) + { + vtkImageDifferenceComputeError(in1Ptr0-in1Inc0-in1Inc1,in2Ptr0); + } + if (idx0 < inMaxX) + { + vtkImageDifferenceComputeError(in1Ptr0+in1Inc0-in1Inc1,in2Ptr0); + } + } + /* middle row (center already considered) */ + if (idx0 > inMinX) + { + vtkImageDifferenceComputeError(in1Ptr0-in1Inc0,in2Ptr0); + } + if (idx0 < inMaxX) + { + vtkImageDifferenceComputeError(in1Ptr0+in1Inc0,in2Ptr0); + } + /* upper row */ + if (idx1 < inMaxY) + { + vtkImageDifferenceComputeError(in1Ptr0+in1Inc1,in2Ptr0); + if (idx0 > inMinX) + { + vtkImageDifferenceComputeError(in1Ptr0-in1Inc0+in1Inc1,in2Ptr0); + } + if (idx0 < inMaxX) + { + vtkImageDifferenceComputeError(in1Ptr0+in1Inc0+in1Inc1,in2Ptr0); + } + } + } + + this->ErrorPerThread[id] = this->ErrorPerThread[id] + (tr + tg + tb)/(3.0*255); + tr -= this->Threshold; + if (tr < 0) + { + tr = 0; + } + tg -= this->Threshold; + if (tg < 0) + { + tg = 0; + } + tb -= this->Threshold; + if (tb < 0) + { + tb = 0; + } + *outPtr0++ = (unsigned char)tr; + *outPtr0++ = (unsigned char)tg; + *outPtr0++ = (unsigned char)tb; + this->ThresholdedErrorPerThread[id] += (tr + tg + tb)/(3.0*255.0); + + in1Ptr0 += in1Inc0; + in2Ptr0 += in2Inc0; + } + outPtr1 += outInc1; + in1Ptr1 += in1Inc1; + in2Ptr1 += in2Inc1; + } + outPtr2 += outInc2; + in1Ptr2 += in1Inc2; + in2Ptr2 += in2Inc2; + } +} + +//---------------------------------------------------------------------------- +//Make the output the intersection of the inputs, of course the inputs better +//be the same size +int vtkImageDifference::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo1 = inputVector[0]->GetInformationObject(0); + vtkInformation *inInfo2 = inputVector[1]->GetInformationObject(0); + + int *in1Ext = inInfo1->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + int *in2Ext = inInfo2->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + int i; + if (in1Ext[0] != in2Ext[0] || in1Ext[1] != in2Ext[1] || + in1Ext[2] != in2Ext[2] || in1Ext[3] != in2Ext[3] || + in1Ext[4] != in2Ext[4] || in1Ext[5] != in2Ext[5]) + { + for (i = 0; i < this->NumberOfThreads; i++) + { + this->ErrorPerThread[i] = 1000; + this->ThresholdedErrorPerThread[i] = 1000; + } + vtkErrorMacro("ExecuteInformation: Input are not the same size.\n" + << " Input1 is: " << in1Ext[0] << "," << in1Ext[1] << "," + << in1Ext[2] << "," << in1Ext[3] << "," + << in1Ext[4] << "," << in1Ext[5] << "\n" + << " Input2 is: " << in2Ext[0] << "," << in2Ext[1] << "," + << in2Ext[2] << "," << in2Ext[3] << "," + << in2Ext[4] << "," << in2Ext[5] ); + } + + // We still need to set the whole extent to be the intersection. + // Otherwise the execute may crash. + int ext[6]; + for (i = 0; i < 3; ++i) + { + ext[i*2] = in1Ext[i*2]; + if (ext[i*2] < in2Ext[i*2]) + { + ext[i*2] = in2Ext[i*2]; + } + ext[i*2+1] = in1Ext[i*2+1]; + if (ext[i*2+1] > in2Ext[i*2+1]) + { + ext[i*2+1] = in2Ext[i*2+1]; + } + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext,6); + + return 1; +} + +double vtkImageDifference::GetError() +{ + double error = 0.0; + int i; + + for ( i= 0; i < this->NumberOfThreads; i++ ) + { + error += this->ErrorPerThread[i]; + } + + return error; +} + +double vtkImageDifference::GetThresholdedError() +{ + double error = 0.0; + int i; + + for ( i= 0; i < this->NumberOfThreads; i++ ) + { + error += this->ThresholdedErrorPerThread[i]; + } + + return error; +} + +vtkImageData *vtkImageDifference::GetImage() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + + +void vtkImageDifference::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int i; + + for ( i= 0; i < this->NumberOfThreads; i++ ) + { + os << indent << "Error for thread " << i << ": " << this->ErrorPerThread[i] << "\n"; + os << indent << "ThresholdedError for thread " << i << ": " + << this->ThresholdedErrorPerThread[i] << "\n"; + } + os << indent << "Threshold: " << this->Threshold << "\n"; + os << indent << "AllowShift: " << this->AllowShift << "\n"; + os << indent << "Averaging: " << this->Averaging << "\n"; +} + + diff --git a/Imaging/vtkImageDifference.h b/Imaging/vtkImageDifference.h new file mode 100644 index 0000000..a1985d2 --- /dev/null +++ b/Imaging/vtkImageDifference.h @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDifference.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageDifference - Compares images for regression tests. +// .SECTION Description +// vtkImageDifference takes two rgb unsigned char images and compares them. +// It allows the images to be slightly different. If AllowShift is on, +// then each pixel can be shifted by one pixel. Threshold is the allowable +// error for each pixel. +// +// This is not a symetric filter and the difference computed is not symetric +// when AllowShift is on. Specifically in that case a pixel in SetImage input +// will be compared to the matching pixel in the input as well as to the +// input's eight connected neighbors. BUT... the opposite is not true. So for +// example if a valid image (SetImage) has a single white pixel in it, it +// will not find a match in the input image if the input image is black +// (because none of the nine suspect pixels are white). In contrast, if there +// is a single white pixel in the input image and the valid image (SetImage) +// is all black it will match with no error because all it has to do is find +// black pixels and even though the input image has a white pixel, its +// neighbors are not white. + +#ifndef __vtkImageDifference_h +#define __vtkImageDifference_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageDifference : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageDifference *New(); + vtkTypeRevisionMacro(vtkImageDifference,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the Image to compare the input to. + void SetImage(vtkDataObject *image) {this->SetInput(1,image);} + vtkImageData *GetImage(); + + // Description: + // Return the total error in comparing the two images. + double GetError(void); + void GetError(double *e) { *e = this->GetError(); }; + + // Description: + // Return the total thresholded error in comparing the two images. + // The thresholded error is the error for a given pixel minus the + // threshold and clamped at a minimum of zero. + double GetThresholdedError(void); + void GetThresholdedError(double *e) { *e = this->GetThresholdedError(); }; + + + // Description: + // Specify a threshold tolerance for pixel differences. + vtkSetMacro(Threshold,int); + vtkGetMacro(Threshold,int); + + // Description: + // Specify whether the comparison will allow a shift of one + // pixel between the images. If set, then the minimum difference + // between input images will be used to determine the difference. + // Otherwise, the difference is computed directly between pixels + // of identical row/column values. + vtkSetMacro(AllowShift,int); + vtkGetMacro(AllowShift,int); + vtkBooleanMacro(AllowShift,int); + + // Description: + // Specify whether the comparison will include comparison of + // averaged 3x3 data between the images. For graphics renderings + // you normally would leave this on. For imaging operations it + // should be off. + vtkSetMacro(Averaging,int); + vtkGetMacro(Averaging,int); + vtkBooleanMacro(Averaging,int); + +protected: + vtkImageDifference(); + ~vtkImageDifference() {}; + + double ErrorPerThread[VTK_MAX_THREADS]; + double ThresholdedErrorPerThread[VTK_MAX_THREADS]; + int AllowShift; + int Threshold; + int Averaging; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + +private: + vtkImageDifference(const vtkImageDifference&); // Not implemented. + void operator=(const vtkImageDifference&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkImageDilateErode3D.cxx b/Imaging/vtkImageDilateErode3D.cxx new file mode 100644 index 0000000..8b0d64d --- /dev/null +++ b/Imaging/vtkImageDilateErode3D.cxx @@ -0,0 +1,329 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDilateErode3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageDilateErode3D.h" +#include "vtkImageData.h" +#include "vtkImageEllipsoidSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageDilateErode3D, "$Revision: 1.46 $"); +vtkStandardNewMacro(vtkImageDilateErode3D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageDilateErode3D fitler. +// By default zero values are dilated. +vtkImageDilateErode3D::vtkImageDilateErode3D() +{ + this->HandleBoundaries = 1; + this->KernelSize[0] = 1; + this->KernelSize[1] = 1; + this->KernelSize[2] = 1; + + this->DilateValue = 0.0; + this->ErodeValue = 255.0; + + this->Ellipse = vtkImageEllipsoidSource::New(); + // Setup the Ellipse to default size + this->SetKernelSize(1, 1, 1); +} + +//---------------------------------------------------------------------------- +vtkImageDilateErode3D::~vtkImageDilateErode3D() +{ + if (this->Ellipse) + { + this->Ellipse->Delete(); + this->Ellipse = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageDilateErode3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "DilateValue: " << this->DilateValue << "\n"; + os << indent << "ErodeValue: " << this->ErodeValue << "\n"; +} + +//---------------------------------------------------------------------------- +// This method sets the size of the neighborhood. It also sets the +// default middle of the neighborhood and computes the eliptical foot print. +void vtkImageDilateErode3D::SetKernelSize(int size0, int size1, int size2) +{ + int modified = 0; + + if (this->KernelSize[0] != size0) + { + modified = 1; + this->KernelSize[0] = size0; + this->KernelMiddle[0] = size0 / 2; + } + if (this->KernelSize[1] != size1) + { + modified = 1; + this->KernelSize[1] = size1; + this->KernelMiddle[1] = size1 / 2; + } + if (this->KernelSize[2] != size2) + { + modified = 1; + this->KernelSize[2] = size2; + this->KernelMiddle[2] = size2 / 2; + } + + if (modified) + { + this->Modified(); + this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->SetCenter((double)(this->KernelSize[0]-1)*0.5, + (double)(this->KernelSize[1]-1)*0.5, + (double)(this->KernelSize[2]-1)*0.5); + this->Ellipse->SetRadius((double)(this->KernelSize[0])*0.5, + (double)(this->KernelSize[1])*0.5, + (double)(this->KernelSize[2])*0.5); + // make sure scalars have been allocated (needed if multithreaded is used) + vtkInformation *ellipseOutInfo = + this->Ellipse->GetExecutive()->GetOutputInformation(0); + ellipseOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + 0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->GetOutput()->Update(); + } +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter on any region, +// whether it needs boundary checking or not. +// If the filter needs to be faster, the function could be duplicated +// for strictly center (no boundary ) processing. +template +void vtkImageDilateErode3DExecute(vtkImageDilateErode3D *self, + vtkImageData *mask, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, int *outExt, + T *outPtr, int id, vtkInformation *inInfo) +{ + int *kernelMiddle, *kernelSize; + // For looping though output (and input) pixels. + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + int outIdx0, outIdx1, outIdx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + T *inPtr0, *inPtr1, *inPtr2; + T *outPtr0, *outPtr1, *outPtr2; + int numComps, outIdxC; + // For looping through hood pixels + int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2; + int hoodIdx0, hoodIdx1, hoodIdx2; + T *hoodPtr0, *hoodPtr1, *hoodPtr2; + // For looping through the mask. + unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2; + vtkIdType maskInc0, maskInc1, maskInc2; + // The extent of the whole input image + int inImageMin0, inImageMin1, inImageMin2; + int inImageMax0, inImageMax1, inImageMax2; + int inImageExt[6]; + // dilate/erode + T erodeValue, dilateValue; + unsigned long count = 0; + unsigned long target; + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inImageExt); + inImageMin0 = inImageExt[0]; + inImageMax0 = inImageExt[1]; + inImageMin1 = inImageExt[2]; + inImageMax1 = inImageExt[3]; + inImageMin2 = inImageExt[4]; + inImageMax2 = inImageExt[5]; + outData->GetIncrements(outInc0, outInc1, outInc2); + outMin0 = outExt[0]; outMax0 = outExt[1]; + outMin1 = outExt[2]; outMax1 = outExt[3]; + outMin2 = outExt[4]; outMax2 = outExt[5]; + numComps = outData->GetNumberOfScalarComponents(); + + // Get ivars of this object (easier than making friends) + erodeValue = (T)(self->GetErodeValue()); + dilateValue = (T)(self->GetDilateValue()); + kernelSize = self->GetKernelSize(); + kernelMiddle = self->GetKernelMiddle(); + hoodMin0 = - kernelMiddle[0]; + hoodMin1 = - kernelMiddle[1]; + hoodMin2 = - kernelMiddle[2]; + hoodMax0 = hoodMin0 + kernelSize[0] - 1; + hoodMax1 = hoodMin1 + kernelSize[1] - 1; + hoodMax2 = hoodMin2 + kernelSize[2] - 1; + + // Setup mask info + maskPtr = (unsigned char *)(mask->GetScalarPointer()); + mask->GetIncrements(maskInc0, maskInc1, maskInc2); + + // in and out should be marching through corresponding pixels. + inPtr = (T *)(inData->GetScalarPointer(outMin0, outMin1, outMin2)); + + target = (unsigned long)(numComps*(outMax2-outMin2+1)* + (outMax1-outMin1+1)/50.0); + target++; + + // loop through components + for (outIdxC = 0; outIdxC < numComps; ++outIdxC) + { + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outMin1; + !self->AbortExecute && outIdx1 <= outMax1; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0) + { + + // Default behavior (copy input pixel) + *outPtr0 = *inPtr0; + if (*inPtr0 == erodeValue) + { + // loop through neighborhood pixels + // as sort of a hack to handle boundaries, + // input pointer will be marching through data that does not exist. + hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0 + - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2; + maskPtr2 = maskPtr; + for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2) + { + hoodPtr1 = hoodPtr2; + maskPtr1 = maskPtr2; + for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1) + { + hoodPtr0 = hoodPtr1; + maskPtr0 = maskPtr1; + for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0) + { + // A quick but rather expensive way to handle boundaries + if ( outIdx0 + hoodIdx0 >= inImageMin0 && + outIdx0 + hoodIdx0 <= inImageMax0 && + outIdx1 + hoodIdx1 >= inImageMin1 && + outIdx1 + hoodIdx1 <= inImageMax1 && + outIdx2 + hoodIdx2 >= inImageMin2 && + outIdx2 + hoodIdx2 <= inImageMax2) + { + if (*hoodPtr0 == dilateValue && *maskPtr0) + { + *outPtr0 = dilateValue; + } + } + + hoodPtr0 += inInc0; + maskPtr0 += maskInc0; + } + hoodPtr1 += inInc1; + maskPtr1 += maskInc1; + } + hoodPtr2 += inInc2; + maskPtr2 += maskInc2; + } + } + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + ++inPtr; + ++outPtr; + } +} + +//---------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output Data types. +// It hanldes image boundaries, so the image does not shrink. +void vtkImageDilateErode3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6], wholeExt[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt,outExt,wholeExt); + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + vtkImageData *mask; + + // Error checking on mask + mask = this->Ellipse->GetOutput(); + if (mask->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro(<< "Execute: mask has wrong scalar type"); + return; + } + + // this filter expects the output type to be same as input + if (outData[0]->GetScalarType() != inData[0][0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << " must match input scalar type"); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageDilateErode3DExecute(this, mask, inData[0][0], + (VTK_TT *)(inPtr),outData[0], outExt, + (VTK_TT *)(outPtr),id, inInfo)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkImageDilateErode3D::RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Ellipse->GetOutput()->Update(); + return this->Superclass::RequestData(request, inputVector, outputVector); +} diff --git a/Imaging/vtkImageDilateErode3D.h b/Imaging/vtkImageDilateErode3D.h new file mode 100644 index 0000000..f6ffc6b --- /dev/null +++ b/Imaging/vtkImageDilateErode3D.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDilateErode3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageDilateErode3D - Dilates one value and erodes another. +// .SECTION Description +// vtkImageDilateErode3D will dilate one value and erode another. +// It uses an elliptical foot print, and only erodes/dilates on the +// boundary of the two values. The filter is restricted to the +// X, Y, and Z axes for now. It can degenerate to a 2 or 1 dimensional +// filter by setting the kernel size to 1 for a specific axis. + + +#ifndef __vtkImageDilateErode3D_h +#define __vtkImageDilateErode3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class vtkImageEllipsoidSource; + +class VTK_IMAGING_EXPORT vtkImageDilateErode3D : public vtkImageSpatialAlgorithm +{ +public: + // Description: + // Construct an instance of vtkImageDilateErode3D filter. + // By default zero values are dilated. + static vtkImageDilateErode3D *New(); + vtkTypeRevisionMacro(vtkImageDilateErode3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sets the size of the neighborhood. It also sets the + // default middle of the neighborhood and computes the elliptical foot print. + void SetKernelSize(int size0, int size1, int size2); + + + // Description: + // Set/Get the Dilate and Erode values to be used by this filter. + vtkSetMacro(DilateValue, double); + vtkGetMacro(DilateValue, double); + vtkSetMacro(ErodeValue, double); + vtkGetMacro(ErodeValue, double); + +protected: + vtkImageDilateErode3D(); + ~vtkImageDilateErode3D(); + + vtkImageEllipsoidSource *Ellipse; + double DilateValue; + double ErodeValue; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + +private: + vtkImageDilateErode3D(const vtkImageDilateErode3D&); // Not implemented. + void operator=(const vtkImageDilateErode3D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageDivergence.cxx b/Imaging/vtkImageDivergence.cxx new file mode 100644 index 0000000..9c8c5db --- /dev/null +++ b/Imaging/vtkImageDivergence.cxx @@ -0,0 +1,235 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDivergence.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageDivergence.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkDataSetAttributes.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageDivergence, "$Revision: 1.35 $"); +vtkStandardNewMacro(vtkImageDivergence); + +vtkImageDivergence::vtkImageDivergence() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +// This method tells the superclass that the first axis will collapse. +int vtkImageDivergence::RequestInformation ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* outputVector) +{ + vtkDataObject::SetPointDataActiveScalarInfo( + outputVector->GetInformationObject(0), -1, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// Just clip the request. The subclass may need to overwrite this method. +int vtkImageDivergence::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + + int idx; + int wholeExtent[6]; + + vtkInformation *inScalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!inScalarInfo) + { + vtkErrorMacro("Missing scalar field on input information!"); + return 0; + } + + int dimensionality = + inScalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()); + + if (dimensionality > 3) + { + vtkErrorMacro("Divergence has to have dimensionality <= 3"); + dimensionality = 3; + } + + // handle XYZ + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent); + int inUExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inUExt); + + // update and Clip + for (idx = 0; idx < dimensionality; ++idx) + { + --inUExt[idx*2]; + ++inUExt[idx*2+1]; + if (inUExt[idx*2] < wholeExtent[idx*2]) + { + inUExt[idx*2] = wholeExtent[idx*2]; + } + if (inUExt[idx*2] > wholeExtent[idx*2 + 1]) + { + inUExt[idx*2] = wholeExtent[idx*2 + 1]; + } + if (inUExt[idx*2+1] < wholeExtent[idx*2]) + { + inUExt[idx*2+1] = wholeExtent[idx*2]; + } + if (inUExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + inUExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inUExt,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageDivergenceExecute(vtkImageDivergence *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int maxC, maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int *wholeExtent; + vtkIdType *inIncs; + double r[3], d, sum; + int useMin[3], useMax[3]; + + // find the region to loop over + maxC = inData->GetNumberOfScalarComponents(); + if (maxC > 3) + { + vtkGenericWarningMacro("Dimensionality must be less than or equal to 3"); + maxC = 3; + } + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // The spacing is important for computing the gradient. + // central differences (2 * ratio). + // Negative because below we have (min - max) for dx ... + inData->GetSpacing(r); + r[0] = -0.5 / r[0]; + r[1] = -0.5 / r[1]; + r[2] = -0.5 / r[2]; + + // get some other info we need + inIncs = inData->GetIncrements(); + wholeExtent = inData->GetExtent(); + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + useMin[2] = ((idxZ + outExt[4]) <= wholeExtent[4]) ? 0 : -inIncs[2]; + useMax[2] = ((idxZ + outExt[4]) >= wholeExtent[5]) ? 0 : inIncs[2]; + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + useMin[1] = ((idxY + outExt[2]) <= wholeExtent[2]) ? 0 : -inIncs[1]; + useMax[1] = ((idxY + outExt[2]) >= wholeExtent[3]) ? 0 : inIncs[1]; + for (idxX = 0; idxX <= maxX; idxX++) + { + useMin[0] = ((idxX + outExt[0]) <= wholeExtent[0]) ? 0 : -inIncs[0]; + useMax[0] = ((idxX + outExt[0]) >= wholeExtent[1]) ? 0 : inIncs[0]; + sum = 0.0; + for (idxC = 0; idxC < maxC; idxC++) + { + // do X axis + d = (double)(inPtr[useMin[idxC]]); + d -= (double)(inPtr[useMax[idxC]]); + sum += d * r[idxC]; + inPtr++; + } + *outPtr = (T)sum; + outPtr++; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The output data +// must match input type. This method does handle boundary conditions. +void vtkImageDivergence::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + void *inPtr = inData->GetScalarPointerForExtent(outExt); + void *outPtr = outData->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData->GetScalarType() + << ", must match out ScalarType " + << outData->GetScalarType()); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageDivergenceExecute(this, inData, + (VTK_TT *)(inPtr), outData, + (VTK_TT *)(outPtr), + outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + diff --git a/Imaging/vtkImageDivergence.h b/Imaging/vtkImageDivergence.h new file mode 100644 index 0000000..8d6a223 --- /dev/null +++ b/Imaging/vtkImageDivergence.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDivergence.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageDivergence - Divergence of a vector field. +// .SECTION Description +// vtkImageDivergence takes a 3D vector field +// and creates a scalar field which +// which represents the rate of change of the vector field. +// The definition of Divergence: +// Given V = P(x,y,z), Q(x,y,z), R(x,y,z), +// Divergence = dP/dx + dQ/dy + dR/dz. + +#ifndef __vtkImageDivergence_h +#define __vtkImageDivergence_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageDivergence : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageDivergence *New(); + vtkTypeRevisionMacro(vtkImageDivergence,vtkThreadedImageAlgorithm); + +protected: + vtkImageDivergence(); + ~vtkImageDivergence() {}; + + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); + +private: + vtkImageDivergence(const vtkImageDivergence&); // Not implemented. + void operator=(const vtkImageDivergence&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageDotProduct.cxx b/Imaging/vtkImageDotProduct.cxx new file mode 100644 index 0000000..c397ece --- /dev/null +++ b/Imaging/vtkImageDotProduct.cxx @@ -0,0 +1,159 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDotProduct.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageDotProduct.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageDotProduct, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkImageDotProduct); + +//---------------------------------------------------------------------------- +vtkImageDotProduct::vtkImageDotProduct() +{ + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +// Colapse the first axis +int vtkImageDotProduct::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + vtkDataObject::SetPointDataActiveScalarInfo( + outputVector->GetInformationObject(0), -1, 1); + return 1; +} + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the two input operations +template +void vtkImageDotProductExecute(vtkImageDotProduct *self, + vtkImageData *in1Data, + vtkImageData *in2Data, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt1(in1Data, outExt); + vtkImageIterator inIt2(in2Data, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + float dot; + + // find the region to loop over + int maxC = in1Data->GetNumberOfScalarComponents(); + int idxC; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI1 = inIt1.BeginSpan(); + T* inSI2 = inIt2.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // now process the components + dot = 0.0; + for (idxC = 0; idxC < maxC; idxC++) + { + dot += (float)(*inSI1 * *inSI2); + ++inSI1; + ++inSI2; + } + *outSI = static_cast(dot); + ++outSI; + } + inIt1.NextSpan(); + inIt2.NextSpan(); + outIt.NextSpan(); + } +} + + +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageDotProduct::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input1 ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match output ScalarType " + << outData[0]->GetScalarType()); + return; + } + + if (inData[1][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input2 ScalarType, " + << inData[1][0]->GetScalarType() + << ", must match output ScalarType " + << outData[0]->GetScalarType()); + return; + } + + // this filter expects that inputs that have the same number of components + if (inData[0][0]->GetNumberOfScalarComponents() != + inData[1][0]->GetNumberOfScalarComponents()) + { + vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, " + << inData[0][0]->GetNumberOfScalarComponents() + << ", must match out input2 NumberOfScalarComponents " + << inData[1][0]->GetNumberOfScalarComponents()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageDotProductExecute(this, inData[0][0], + inData[1][0], outData[0], outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + + + + + + + + + + + + diff --git a/Imaging/vtkImageDotProduct.h b/Imaging/vtkImageDotProduct.h new file mode 100644 index 0000000..1cc425e --- /dev/null +++ b/Imaging/vtkImageDotProduct.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageDotProduct.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageDotProduct - Dot product of two vector images. +// .SECTION Description +// vtkImageDotProduct interprets the scalar components of two images +// as vectors and takes the dot product vector by vector (pixel by pixel). + +#ifndef __vtkImageDotProduct_h +#define __vtkImageDotProduct_h + + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageDotProduct : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageDotProduct *New(); + vtkTypeRevisionMacro(vtkImageDotProduct,vtkThreadedImageAlgorithm); + + // Description: + // Set the two inputs to this filter + virtual void SetInput1(vtkDataObject *in) { this->SetInput(0,in); } + virtual void SetInput2(vtkDataObject *in) { this->SetInput(1,in); } + +protected: + vtkImageDotProduct(); + ~vtkImageDotProduct() {}; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + +private: + vtkImageDotProduct(const vtkImageDotProduct&); // Not implemented. + void operator=(const vtkImageDotProduct&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageEllipsoidSource.cxx b/Imaging/vtkImageEllipsoidSource.cxx new file mode 100644 index 0000000..69b2ac7 --- /dev/null +++ b/Imaging/vtkImageEllipsoidSource.cxx @@ -0,0 +1,259 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageEllipsoidSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageEllipsoidSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include "vtkImageData.h" + +vtkCxxRevisionMacro(vtkImageEllipsoidSource, "$Revision: 1.35 $"); +vtkStandardNewMacro(vtkImageEllipsoidSource); + +//---------------------------------------------------------------------------- +vtkImageEllipsoidSource::vtkImageEllipsoidSource() +{ + this->WholeExtent[0] = 0; + this->WholeExtent[1] = 255; + this->WholeExtent[2] = 0; + this->WholeExtent[3] = 255; + this->WholeExtent[4] = 0; + this->WholeExtent[5] = 0; + this->Center[0] = 128.0; + this->Center[1] = 128.0; + this->Center[2] = 0.0; + this->Radius[0] = 70.0; + this->Radius[1] = 70.0; + this->Radius[2] = 70.0; + this->InValue = 255.0; + this->OutValue = 0.0; + + this->OutputScalarType = VTK_UNSIGNED_CHAR; + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkImageEllipsoidSource::~vtkImageEllipsoidSource() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageEllipsoidSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Center: (" << this->Center[0] << ", " + << this->Center[1] << ", " << this->Center[2] << ")\n"; + + os << indent << "Radius: (" << this->Radius[0] << ", " + << this->Radius[1] << ", " << this->Radius[2] << ")\n"; + + os << indent << "InValue: " << this->InValue << "\n"; + os << indent << "OutValue: " << this->OutValue << "\n"; + os << indent << "OutputScalarType: " << this->OutputScalarType << "\n"; +} +//---------------------------------------------------------------------------- +void vtkImageEllipsoidSource::SetWholeExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + if (this->WholeExtent[idx] != extent[idx]) + { + this->WholeExtent[idx] = extent[idx]; + this->Modified(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkImageEllipsoidSource::SetWholeExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetWholeExtent(extent); +} + + +//---------------------------------------------------------------------------- +void vtkImageEllipsoidSource::GetWholeExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + extent[idx] = this->WholeExtent[idx]; + } +} + +//---------------------------------------------------------------------------- +int vtkImageEllipsoidSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent, 6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->OutputScalarType, -1); + return 1; +} + +template +void vtkImageEllipsoidSourceExecute(vtkImageEllipsoidSource *self, + vtkImageData *data, int ext[6], T *ptr) +{ + int min0, max0; + int idx0, idx1, idx2; + vtkIdType inc0, inc1, inc2; + double s0, s1, s2, temp; + T outVal, inVal; + double *center, *radius; + unsigned long count = 0; + unsigned long target; + + outVal = (T)(self->GetOutValue()); + inVal = (T)(self->GetInValue()); + center = self->GetCenter(); + radius = self->GetRadius(); + + min0 = ext[0]; + max0 = ext[1]; + data->GetContinuousIncrements(ext, inc0, inc1, inc2); + + target = (unsigned long)((ext[5]-ext[4]+1)*(ext[3]-ext[2]+1)/50.0); + target++; + + for (idx2 = ext[4]; idx2 <= ext[5]; ++idx2) + { + // handle divide by zero + if (radius[2] != 0.0) + { + temp = ((double)idx2 - (double)(center[2])) / (double)(radius[2]); + } + else + { + if ((double)idx2 - center[2] == 0.0) + { + temp = 0.0; + } + else + { + temp = VTK_DOUBLE_MAX; + } + } + + + s2 = temp * temp; + for (idx1 = ext[2]; !self->AbortExecute && idx1 <= ext[3]; ++idx1) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + + // handle divide by zero + if (radius[1] != 0.0) + { + temp = ((double)idx1 - (double)(center[1])) / (double)(radius[1]); + } + else + { + if ((double)idx1 - center[1] == 0.0) + { + temp = 0.0; + } + else + { + temp = VTK_DOUBLE_MAX; + } + } + + s1 = temp * temp; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + // handle divide by zero + if (radius[0] != 0.0) + { + temp = ((double)idx0 - (double)(center[0])) / (double)(radius[0]); + } + else + { + if ((double)idx0 - center[0] == 0.0) + { + temp = 0.0; + } + else + { + temp = VTK_DOUBLE_MAX; + } + } + + s0 = temp * temp; + if (s0 + s1 + s2 > 1.0) + { + *ptr = outVal; + } + else + { + *ptr = inVal; + } + ++ptr; + // inc0 is 0 + } + ptr += inc1; + } + ptr += inc2; + } +} + +//---------------------------------------------------------------------------- +int vtkImageEllipsoidSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *data = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int extent[6]; + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),extent); + + data->SetExtent(extent); + data->AllocateScalars(); + + void *ptr; + ptr = data->GetScalarPointerForExtent(extent); + + switch (data->GetScalarType()) + { + vtkTemplateMacro( + vtkImageEllipsoidSourceExecute(this, data, extent, (VTK_TT *)ptr)); + default: + vtkErrorMacro("Execute: Unknown output ScalarType"); + } + + return 1; +} diff --git a/Imaging/vtkImageEllipsoidSource.h b/Imaging/vtkImageEllipsoidSource.h new file mode 100644 index 0000000..c3a12aa --- /dev/null +++ b/Imaging/vtkImageEllipsoidSource.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageEllipsoidSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageEllipsoidSource - Create a binary image of an ellipsoid. +// .SECTION Description +// vtkImageEllipsoidSource creates a binary image of a ellipsoid. It was created +// as an example of a simple source, and to test the mask filter. +// It is also used internally in vtkImageDilateErode3D. + + + +#ifndef __vtkImageEllipsoidSource_h +#define __vtkImageEllipsoidSource_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageEllipsoidSource : public vtkImageAlgorithm +{ +public: + static vtkImageEllipsoidSource *New(); + vtkTypeRevisionMacro(vtkImageEllipsoidSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the extent of the whole output image. + void SetWholeExtent(int extent[6]); + void SetWholeExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + void GetWholeExtent(int extent[6]); + int *GetWholeExtent() {return this->WholeExtent;} + + // Description: + // Set/Get the center of the ellipsoid. + vtkSetVector3Macro(Center, double); + vtkGetVector3Macro(Center, double); + + // Description: + // Set/Get the radius of the ellipsoid. + vtkSetVector3Macro(Radius, double); + vtkGetVector3Macro(Radius, double); + + // Description: + // Set/Get the inside pixel values. + vtkSetMacro(InValue,double); + vtkGetMacro(InValue,double); + + // Description: + // Set/Get the outside pixel values. + vtkSetMacro(OutValue,double); + vtkGetMacro(OutValue,double); + + // Description: + // Set what type of scalar data this source should generate. + vtkSetMacro(OutputScalarType,int); + vtkGetMacro(OutputScalarType,int); + void SetOutputScalarTypeToFloat() + {this->SetOutputScalarType(VTK_FLOAT);} + void SetOutputScalarTypeToDouble() + {this->SetOutputScalarType(VTK_DOUBLE);} + void SetOutputScalarTypeToLong() + {this->SetOutputScalarType(VTK_LONG);} + void SetOutputScalarTypeToUnsignedLong() + {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; + void SetOutputScalarTypeToInt() + {this->SetOutputScalarType(VTK_INT);} + void SetOutputScalarTypeToUnsignedInt() + {this->SetOutputScalarType(VTK_UNSIGNED_INT);} + void SetOutputScalarTypeToShort() + {this->SetOutputScalarType(VTK_SHORT);} + void SetOutputScalarTypeToUnsignedShort() + {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);} + void SetOutputScalarTypeToChar() + {this->SetOutputScalarType(VTK_CHAR);} + void SetOutputScalarTypeToUnsignedChar() + {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);} + +protected: + vtkImageEllipsoidSource(); + ~vtkImageEllipsoidSource(); + + int WholeExtent[6]; + double Center[3]; + double Radius[3]; + double InValue; + double OutValue; + int OutputScalarType; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + +private: + vtkImageEllipsoidSource(const vtkImageEllipsoidSource&); // Not implemented. + void operator=(const vtkImageEllipsoidSource&); // Not implemented. +}; + + +#endif + + diff --git a/Imaging/vtkImageEuclideanDistance.cxx b/Imaging/vtkImageEuclideanDistance.cxx new file mode 100644 index 0000000..dff293c --- /dev/null +++ b/Imaging/vtkImageEuclideanDistance.cxx @@ -0,0 +1,769 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageEuclideanDistance.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageEuclideanDistance.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageEuclideanDistance, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkImageEuclideanDistance); + +//---------------------------------------------------------------------------- +// This defines the default values for the EDT parameters +vtkImageEuclideanDistance::vtkImageEuclideanDistance() +{ + this->MaximumDistance = VTK_INT_MAX; + this->Initialize = 1; + this->ConsiderAnisotropy = 1; + this->Algorithm = VTK_EDT_SAITO; +} + +//---------------------------------------------------------------------------- +// This extent of the components changes to real and imaginary values. +int vtkImageEuclideanDistance::IterativeRequestInformation( + vtkInformation* vtkNotUsed(input), vtkInformation* output) +{ + vtkDataObject::SetPointDataActiveScalarInfo(output, VTK_DOUBLE, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// This method tells the superclass that the whole input array is needed +// to compute any output region. +int vtkImageEuclideanDistance::IterativeRequestUpdateExtent( + vtkInformation* input, vtkInformation* vtkNotUsed(output) ) +{ + int *wExt = input->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + input->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),wExt,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This templated execute method handles any type input, but the output +// is always doubles. +template +void vtkImageEuclideanDistanceCopyData(vtkImageEuclideanDistance *self, + vtkImageData *inData, TT *inPtr, + vtkImageData *outData, int outExt[6], + double *outPtr ) +{ + vtkIdType inInc0, inInc1, inInc2; + TT *inPtr0, *inPtr1, *inPtr2; + + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + vtkIdType outInc0, outInc1, outInc2; + double *outPtr0, *outPtr1, *outPtr2; + + int idx0, idx1, idx2; + + // Reorder axes + self->PermuteExtent(outExt, outMin0,outMax0,outMin1,outMax1,outMin2,outMax2); + self->PermuteIncrements(inData->GetIncrements(), inInc0, inInc1, inInc2); + self->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + inPtr2 = inPtr; + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = outMin1; idx1 <= outMax1; ++idx1) + { + inPtr0 = inPtr1; + outPtr0 = outPtr1; + + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + *outPtr0 = *inPtr0 ; + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } +} + +//---------------------------------------------------------------------------- +// This templated execute method handles any type input, but the output +// is always doubles. +template +void vtkImageEuclideanDistanceInitialize(vtkImageEuclideanDistance *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, + int outExt[6], double *outPtr ) +{ + vtkIdType inInc0, inInc1, inInc2; + T *inPtr0, *inPtr1, *inPtr2; + + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + vtkIdType outInc0, outInc1, outInc2; + double *outPtr0, *outPtr1, *outPtr2; + + int idx0, idx1, idx2; + double maxDist; + + // Reorder axes + self->PermuteExtent(outExt, outMin0,outMax0,outMin1,outMax1,outMin2,outMax2); + self->PermuteIncrements(inData->GetIncrements(), inInc0, inInc1, inInc2); + self->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + if ( self->GetInitialize() == 1 ) + // Initialization required. Input image is only used as binary mask, + // so all non-zero values are set to maxDist + // + { + maxDist = self->GetMaximumDistance(); + + inPtr2 = inPtr; + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = outMin1; idx1 <= outMax1; ++idx1) + { + inPtr0 = inPtr1; + outPtr0 = outPtr1; + + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + if( *inPtr0 == 0 ) {*outPtr0 = 0;} + else {*outPtr0 = maxDist;} + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + } + else + // No initialization required. We just copy inData to outData. + { + vtkImageEuclideanDistanceCopyData( self, + inData, (T *)(inPtr), + outData, outExt, (double *)(outPtr) ); + } +} + +//---------------------------------------------------------------------------- +// Execute Saito's algorithm. +// +// T. Saito and J.I. Toriwaki. New algorithms for Euclidean distance +// transformations of an n-dimensional digitised picture with applications. +// Pattern Recognition, 27(11). pp. 1551--1565, 1994. +// +// Notations stay as close as possible to those used in the paper. +// +void vtkImageEuclideanDistanceExecuteSaito(vtkImageEuclideanDistance *self, + vtkImageData *outData, + int outExt[6], double *outPtr ) +{ + + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + vtkIdType outInc0, outInc1, outInc2; + double *outPtr0, *outPtr1, *outPtr2; + int idx0, idx1, idx2, inSize0; + double maxDist; + double *sq; + double *buff,buffer; + int df,a,b,n; + double m; + double spacing; + + // Reorder axes (The outs here are just placeholdes + self->PermuteExtent(outExt, outMin0,outMax0,outMin1,outMax1,outMin2,outMax2); + self->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + inSize0 = outMax0 - outMin0 + 1; + maxDist = self->GetMaximumDistance(); + + buff= (double *)calloc(outMax0+1,sizeof(double)); + + // precompute sq[]. Anisotropy is handled here by using Spacing information + sq = (double *)calloc(inSize0*2+2,sizeof(double)); + for(df=2*inSize0+1;df>inSize0;df--) + { + sq[df]=maxDist; + } + + if ( self->GetConsiderAnisotropy() ) + { + spacing = outData->GetSpacing()[ self->GetIteration() ]; + } + else + { + spacing = 1; + } + + spacing*=spacing; + + for(df=inSize0;df>=0;df--) + { + sq[df]=df*df*spacing; + } + + if ( self->GetIteration() == 0 ) + { + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + outPtr1 = outPtr2; + for (idx1 = outMin1; idx1 <= outMax1; ++idx1) + { + outPtr0 = outPtr1; + df= inSize0 ; + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + if(*outPtr0 != 0) + { + df++ ; + if(sq[df] < *outPtr0) {*outPtr0 = sq[df];} + } + else + { + df=0; + } + outPtr0 += outInc0; + } + + outPtr0 -= outInc0; + df= inSize0 ; + for (idx0 = outMax0; idx0 >= outMin0; --idx0) + { + if(*outPtr0 != 0) + { + df++ ; + if(sq[df] < *outPtr0) {*outPtr0 = sq[df];} + } + else + { + df=0; + } + outPtr0 -= outInc0; + } + + outPtr1 += outInc1; + } + outPtr2 += outInc2; + } + } + else // next iterations are all identical. + { + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + outPtr1 = outPtr2; + for (idx1 = outMin1; idx1 <= outMax1; ++idx1) + { + outPtr0 = outPtr1; + + // Buffer current values + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + buff[idx0]= *outPtr0; + outPtr0 += outInc0; + } + + // forward scan + a=0; buffer=buff[ outMin0 ]; + outPtr0 = outPtr1; + outPtr0 += outInc0; + + for (idx0 = outMin0+1; idx0 <= outMax0; ++idx0) + { + if(a>0) {a--;} + if(buff[idx0]>buffer+sq[1]) + { + b=(int)(floor)((((buff[idx0]-buffer)/spacing)-1)/2); + if((idx0+b)>outMax0) {b=(outMax0)-idx0;} + + for(n=a;n<=b;n++) + { + m=buffer+sq[n+1]; + if(buff[idx0+n]<=m) {n=b;} + else if(m<*(outPtr0+n*outInc0)) {*(outPtr0+n*outInc0)=m;} + } + a=b; + } + else + { + a=0; + } + + buffer=buff[idx0]; + outPtr0 += outInc0; + } + + outPtr0 -= 2*outInc0; + a=0; + buffer=buff[outMax0]; + + for(idx0=outMax0-1;idx0>=outMin0; --idx0) + { + if(a>0) {a--;} + if(buff[idx0]>buffer+sq[1]) + { + b=(int)(floor)((((buff[idx0]-buffer)/spacing)-1)/2); + if((idx0-b)PermuteExtent(outExt, outMin0,outMax0,outMin1,outMax1,outMin2,outMax2); + self->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + inSize0 = outMax0 - outMin0 + 1; + maxDist = self->GetMaximumDistance(); + + buff= (double *)calloc(outMax0+1,sizeof(double)); + temp= (double *)calloc(outMax0+1,sizeof(double)); + + // precompute sq[]. Anisotropy is handled here by using Spacing information + sq = (double *)calloc(inSize0*2+2,sizeof(double)); + for(df=2*inSize0+1;df>inSize0;df--) + { + sq[df]=maxDist; + } + if ( self->GetConsiderAnisotropy() ) + { + spacing = outData->GetSpacing()[ self->GetIteration() ]; + } + else + { + spacing = 1; + } + spacing*=spacing; + + for(df=inSize0;df>=0;df--) + { + sq[df]=df*df*spacing; + } + + if ( self->GetIteration() == 0 ) + { + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + outPtr1 = outPtr2; + for (idx1 = outMin1; idx1 <= outMax1; ++idx1) + { + outPtr0 = outPtr1; + df= inSize0 ; + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + if(*outPtr0 != 0) + { + df++ ; + if(sq[df] < *outPtr0) {*outPtr0 = sq[df];} + } + else + { + df=0; + } + + outPtr0 += outInc0; + } + + outPtr0 -= outInc0; + df= inSize0 ; + for (idx0 = outMax0; idx0 >= outMin0; --idx0) + { + if(*outPtr0 != 0) + { + df++ ; + if(sq[df] < *outPtr0) {*outPtr0 = sq[df];} + } + else + { + df=0; + } + + outPtr0 -= outInc0; + } + + outPtr1 += outInc1; + } + outPtr2 += outInc2; + } + } + else // next iterations are all identical. + { + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + outPtr1 = outPtr2; + for (idx1 = outMin1; idx1 <= outMax1; ++idx1) + { + // Buffer current values + outPtr0 = outPtr1; + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + temp[idx0] = buff[idx0]= *outPtr0; + outPtr0 += outInc0; + } + + // forward scan + a=0; buffer=buff[ outMin0 ]; + outPtr0 = temp ; + outPtr0 ++; + + for (idx0 = outMin0+1; idx0 <= outMax0; ++idx0) + { + if(a>0) {a--;} + + if(buff[idx0]>buffer+sq[1]) + { + b=(int)(floor)((((buff[idx0]-buffer)/spacing)-1)/2); + if((idx0+b)>outMax0) {b=(outMax0)-idx0;} + + for(n=a;n<=b;n++) + { + m=buffer+sq[n+1]; + if(buff[idx0+n]<=m) {n=b;} + else if(m<*(outPtr0+n)) {*(outPtr0+n)=m;} + } + a=b; + } + else + { + a=0; + } + + buffer=buff[idx0]; + outPtr0 ++; + } + + // backward scan + outPtr0 -= 2; + a=0; + buffer=buff[outMax0]; + + for(idx0=outMax0-1;idx0>=outMin0; --idx0) + { + if(a>0) {a--;} + if(buff[idx0]>buffer+sq[1]) + { + b=(int)(floor)((((buff[idx0]-buffer)/spacing)-1)/2); + if((idx0-b)SetExtent(outData->GetWholeExtent()); + outData->AllocateScalars(); +} + +//---------------------------------------------------------------------------- +// This method is passed input and output Datas, and executes the +// EuclideanDistance algorithm to fill the output from the input. +int vtkImageEuclideanDistance::IterativeRequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + this->AllocateOutputScalars(outData); + + void *inPtr; + void *outPtr; + + vtkDebugMacro(<<"Executing image euclidean distance"); + + int outExt[6]; + outData->GetWholeExtent( outExt ); + + inPtr = inData->GetScalarPointerForExtent( + inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT())); + outPtr = outData->GetScalarPointer(); + + if (!inPtr) + { + vtkErrorMacro(<< "Execute: No scalars for update extent.") + return 1; + } + + + // this filter expects that the output be doubles. + if (outData->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "Execute: Output must be be type double."); + return 1; + } + + // this filter expects input to have 1 components + if (outData->GetNumberOfScalarComponents() != 1 ) + { + vtkErrorMacro(<< "Execute: Cannot handle more than 1 components"); + return 1; + } + + if ( this->GetIteration() == 0 ) + { + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageEuclideanDistanceInitialize(this, + inData, (VTK_TT *)(inPtr), + outData, outExt, + (double *)(outPtr) )); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 1; + } + } + else + { + if( inData != outData ) + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageEuclideanDistanceCopyData(this, + inData, (VTK_TT *)(inPtr), + outData, outExt, + (double *)(outPtr) )); + } + } + + // Call the specific algorithms. + switch( this->GetAlgorithm() ) + { + case VTK_EDT_SAITO: + vtkImageEuclideanDistanceExecuteSaito( this, outData, outExt, + (double *)(outPtr) ); + break; + case VTK_EDT_SAITO_CACHED: + vtkImageEuclideanDistanceExecuteSaitoCached( this, outData, outExt, + (double *)(outPtr) ); + break; + default: + vtkErrorMacro(<< "Execute: Unknown Algorithm"); + } + + this->UpdateProgress((this->GetIteration()+1.0)/3.0); + + return 1; +} + + +//---------------------------------------------------------------------------- +// For streaming and threads. Splits output update extent into num pieces. +// This method needs to be called num times. Results must not overlap for +// consistent starting extent. Subclass can override this method. +// This method returns the number of peices resulting from a successful split. +// This can be from 1 to "total". +// If 1 is returned, the extent cannot be split. +int vtkImageEuclideanDistance::SplitExtent(int splitExt[6], int startExt[6], + int num, int total) +{ + int splitAxis; + int min, max; + + vtkDebugMacro("SplitExtent: ( " << startExt[0] << ", " << startExt[1] << ", " + << startExt[2] << ", " << startExt[3] << ", " + << startExt[4] << ", " << startExt[5] << "), " + << num << " of " << total); + + // start with same extent + memcpy(splitExt, startExt, 6 * sizeof(int)); + + splitAxis = 2; + min = startExt[4]; + max = startExt[5]; + while ((splitAxis == this->Iteration) || (min == max)) + { + splitAxis--; + if (splitAxis < 0) + { // cannot split + vtkDebugMacro(" Cannot Split"); + return 1; + } + min = startExt[splitAxis*2]; + max = startExt[splitAxis*2+1]; + } + + // determine the actual number of pieces that will be generated + if ((max - min + 1) < total) + { + total = max - min + 1; + } + + if (num >= total) + { + vtkDebugMacro(" SplitRequest (" << num + << ") larger than total: " << total); + return total; + } + + // determine the extent of the piece + splitExt[splitAxis*2] = min + (max - min + 1)*num/total; + if (num == total - 1) + { + splitExt[splitAxis*2+1] = max; + } + else + { + splitExt[splitAxis*2+1] = (min-1) + (max - min + 1)*(num+1)/total; + } + + vtkDebugMacro(" Split Piece: ( " <Superclass::PrintSelf(os,indent); + + os << indent << "Initialize: " + << (this->Initialize ? "On\n" : "Off\n"); + + os << indent << "Consider Anisotropy: " + << (this->ConsiderAnisotropy ? "On\n" : "Off\n"); + + os << indent << "Initialize: " << this->Initialize << "\n"; + os << indent << "Maximum Distance: " << this->MaximumDistance << "\n"; + + os << indent << "Algorithm: "; + if ( this->Algorithm == VTK_EDT_SAITO ) + { + os << "Saito\n"; + } + else + { + os << "Saito Cached\n"; + } +} + + + + + + + + + + + + + + + + + diff --git a/Imaging/vtkImageEuclideanDistance.h b/Imaging/vtkImageEuclideanDistance.h new file mode 100644 index 0000000..fe54578 --- /dev/null +++ b/Imaging/vtkImageEuclideanDistance.h @@ -0,0 +1,139 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageEuclideanDistance.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageEuclideanDistance - computes 3D Euclidean DT +// .SECTION Description +// vtkImageEuclideanDistance implements the Euclidean DT using +// Saito's algorithm. The distance map produced contains the square of the +// Euclidean distance values. +// +// The algorithm has a o(n^(D+1)) complexity over nxnx...xn images in D +// dimensions. It is very efficient on relatively small images. Cuisenaire's +// algorithms should be used instead if n >> 500. These are not implemented +// yet. +// +// For the special case of images where the slice-size is a multiple of +// 2^N with a large N (typically for 256x256 slices), Saito's algorithm +// encounters a lot of cache conflicts during the 3rd iteration which can +// slow it very significantly. In that case, one should use +// ::SetAlgorithmToSaitoCached() instead for better performance. +// +// References: +// +// T. Saito and J.I. Toriwaki. New algorithms for Euclidean distance +// transformations of an n-dimensional digitised picture with applications. +// Pattern Recognition, 27(11). pp. 1551--1565, 1994. +// +// O. Cuisenaire. Distance Transformation: fast algorithms and applications +// to medical image processing. PhD Thesis, Universite catholique de Louvain, +// October 1999. http://ltswww.epfl.ch/~cuisenai/papers/oc_thesis.pdf + + +#ifndef __vtkImageEuclideanDistance_h +#define __vtkImageEuclideanDistance_h + +#include "vtkImageDecomposeFilter.h" + +#define VTK_EDT_SAITO_CACHED 0 +#define VTK_EDT_SAITO 1 + +class VTK_IMAGING_EXPORT vtkImageEuclideanDistance : public vtkImageDecomposeFilter +{ +public: + static vtkImageEuclideanDistance *New(); + vtkTypeRevisionMacro(vtkImageEuclideanDistance,vtkImageDecomposeFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Used internally for streaming and threads. + // Splits output update extent into num pieces. + // This method needs to be called num times. Results must not overlap for + // consistent starting extent. Subclass can override this method. + // This method returns the number of peices resulting from a + // successful split. This can be from 1 to "total". + // If 1 is returned, the extent cannot be split. + int SplitExtent(int splitExt[6], int startExt[6], + int num, int total); + + // Description: + // Used to set all non-zero voxels to MaximumDistance before starting + // the distance transformation. Setting Initialize off keeps the current + // value in the input image as starting point. This allows to superimpose + // several distance maps. + vtkSetMacro(Initialize, int); + vtkGetMacro(Initialize, int); + vtkBooleanMacro(Initialize, int); + + // Description: + // Used to define whether Spacing should be used in the computation of the + // distances + vtkSetMacro(ConsiderAnisotropy, int); + vtkGetMacro(ConsiderAnisotropy, int); + vtkBooleanMacro(ConsiderAnisotropy, int); + + // Description: + // Any distance bigger than this->MaximumDistance will not ne computed but + // set to this->MaximumDistance instead. + vtkSetMacro(MaximumDistance, double); + vtkGetMacro(MaximumDistance, double); + + // Description: + // Selects a Euclidean DT algorithm. + // 1. Saito + // 2. Saito-cached + // More algorithms will be added later on. + vtkSetMacro(Algorithm, int); + vtkGetMacro(Algorithm, int); + void SetAlgorithmToSaito () + { this->SetAlgorithm(VTK_EDT_SAITO); } + void SetAlgorithmToSaitoCached () + { this->SetAlgorithm(VTK_EDT_SAITO_CACHED); } + + virtual int IterativeRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkImageEuclideanDistance(); + ~vtkImageEuclideanDistance() {} + + double MaximumDistance; + int Initialize; + int ConsiderAnisotropy; + int Algorithm; + + // Replaces "EnlargeOutputUpdateExtent" + virtual void AllocateOutputScalars(vtkImageData *outData); + + virtual int IterativeRequestInformation(vtkInformation* in, + vtkInformation* out); + virtual int IterativeRequestUpdateExtent(vtkInformation* in, + vtkInformation* out); + +private: + vtkImageEuclideanDistance(const vtkImageEuclideanDistance&); // Not implemented. + void operator=(const vtkImageEuclideanDistance&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageEuclideanToPolar.cxx b/Imaging/vtkImageEuclideanToPolar.cxx new file mode 100644 index 0000000..f47b9e4 --- /dev/null +++ b/Imaging/vtkImageEuclideanToPolar.cxx @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageEuclideanToPolar.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageEuclideanToPolar.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImageEuclideanToPolar, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkImageEuclideanToPolar); + +//---------------------------------------------------------------------------- +vtkImageEuclideanToPolar::vtkImageEuclideanToPolar() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + this->ThetaMaximum = 255.0; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageEuclideanToPolarExecute(vtkImageEuclideanToPolar *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + double X, Y, Theta, R; + double thetaMax = self->GetThetaMaximum(); + + // find the region to loop over + int maxC = inData->GetNumberOfScalarComponents(); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // Pixel operation + X = (double)(*inSI); + Y = (double)(inSI[1]); + + if ((X == 0.0) && (Y == 0.0)) + { + Theta = 0.0; + R = 0.0; + } + else + { + Theta = atan2(Y, X) * thetaMax / 6.2831853; + if (Theta < 0.0) + { + Theta += thetaMax; + } + R = sqrt(X*X + Y*Y); + } + + *outSI = (T)(Theta); + outSI[1] = (T)(R); + inSI += maxC; + outSI += maxC; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageEuclideanToPolar::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData->GetScalarType() + << ", must match out ScalarType " + << outData->GetScalarType()); + return; + } + + // input must have at least two components + if (inData->GetNumberOfScalarComponents() < 2) + { + vtkErrorMacro(<< "Execute: input does not have at least two components"); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageEuclideanToPolarExecute( this, + inData, outData, outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageEuclideanToPolar::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum Angle: " << this->ThetaMaximum << "\n"; +} diff --git a/Imaging/vtkImageEuclideanToPolar.h b/Imaging/vtkImageEuclideanToPolar.h new file mode 100644 index 0000000..7c7e5e3 --- /dev/null +++ b/Imaging/vtkImageEuclideanToPolar.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageEuclideanToPolar.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageEuclideanToPolar - Converts 2D Euclidean coordinates to polar. +// .SECTION Description +// For each pixel with vector components x,y, this filter outputs +// theta in component0, and radius in component1. + +#ifndef __vtkImageEuclideanToPolar_h +#define __vtkImageEuclideanToPolar_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageEuclideanToPolar : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageEuclideanToPolar *New(); + vtkTypeRevisionMacro(vtkImageEuclideanToPolar, + vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Theta is an angle. Maximum specifies when it maps back to 0. + // ThetaMaximum defaults to 255 instead of 2PI, because unsigned char + // is expected as input. The output type must be the same as input type. + vtkSetMacro(ThetaMaximum,double); + vtkGetMacro(ThetaMaximum,double); + +protected: + vtkImageEuclideanToPolar(); + ~vtkImageEuclideanToPolar() {}; + + double ThetaMaximum; + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); +private: + vtkImageEuclideanToPolar(const vtkImageEuclideanToPolar&); // Not implemented. + void operator=(const vtkImageEuclideanToPolar&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageExport.cxx b/Imaging/vtkImageExport.cxx new file mode 100644 index 0000000..2307612 --- /dev/null +++ b/Imaging/vtkImageExport.cxx @@ -0,0 +1,543 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageExport.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageExport.h" + +#include "vtkExecutive.h" +#include "vtkObjectFactory.h" +#include "vtkImageData.h" + +#include +#include + +vtkCxxRevisionMacro(vtkImageExport, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkImageExport); + +//---------------------------------------------------------------------------- +vtkImageExport::vtkImageExport() +{ + this->ImageLowerLeft = 1; + this->ExportVoidPointer = 0; + this->DataDimensions[0] = this->DataDimensions[1] = + this->DataDimensions[2] = 0; + this->LastPipelineMTime = 0; + + this->SetNumberOfOutputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkImageExport::~vtkImageExport() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageExport::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ImageLowerLeft: " + << (this->ImageLowerLeft ? "On\n" : "Off\n"); +} + +vtkImageData *vtkImageExport::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +//---------------------------------------------------------------------------- +int vtkImageExport::GetDataMemorySize() +{ + vtkImageData *input = this->GetInput(); + if (input == NULL) + { + return 0; + } + + input->UpdateInformation(); + int *extent = input->GetWholeExtent(); + int size = input->GetScalarSize(); + size *= input->GetNumberOfScalarComponents(); + size *= (extent[1] - extent[0] + 1); + size *= (extent[3] - extent[2] + 1); + size *= (extent[5] - extent[4] + 1); + + return size; +} + + +//---------------------------------------------------------------------------- +void vtkImageExport::GetDataDimensions(int *dims) +{ + vtkImageData *input = this->GetInput(); + if (input == NULL) + { + dims[0] = dims[1] = dims[2] = 0; + return; + } + + input->UpdateInformation(); + int *extent = input->GetWholeExtent(); + dims[0] = extent[1]-extent[0]+1; + dims[1] = extent[3]-extent[2]+1; + dims[2] = extent[5]-extent[4]+1; +} + +//---------------------------------------------------------------------------- +void vtkImageExport::SetExportVoidPointer(void *ptr) +{ + if (this->ExportVoidPointer == ptr) + { + return; + } + this->ExportVoidPointer = ptr; + this->Modified(); +} + +//---------------------------------------------------------------------------- +// This is the superclasses style of Execute method. Convert it into +// an imaging style Execute method. +int vtkImageExport::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* vtkNotUsed( outputVector )) +{ + // we are the end of the pipeline, we do nothing + return 1; +} + +//---------------------------------------------------------------------------- +// Exports all the data from the input. +void vtkImageExport::Export(void *output) +{ + if (!this->GetPointerToData()) + { + // GetPointerToData() outputs an error message. + return; + } + + if (this->ImageLowerLeft) + { + memcpy(output,this->GetPointerToData(),this->GetDataMemorySize()); + } + else + { // flip the image when it is output + void *ptr = this->GetPointerToData(); + int *extent = this->GetInput()->GetWholeExtent(); + int xsize = extent[1]-extent[0]+1; + int ysize = extent[3]-extent[2]+1; + int zsize = extent[5]-extent[4]+1; + int csize = this->GetInput()->GetScalarSize()* \ + this->GetInput()->GetNumberOfScalarComponents(); + + for (int i = 0; i < zsize; i++) + { + ptr = (void *)(((char *)ptr) + ysize*xsize*csize); + for (int j = 0; j < ysize; j++) + { + ptr = (void *)(((char *)ptr) - xsize*csize); + memcpy(output, ptr, xsize*csize); + output = (void *)(((char *)output) + xsize*csize); + } + ptr = (void *)(((char *)ptr) + ysize*xsize*csize); + } + } +} + +//---------------------------------------------------------------------------- +// Provides a valid pointer to the data (only valid until the next +// update, though) + +void *vtkImageExport::GetPointerToData() +{ + // Error checking + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<<"Export: Please specify an input!"); + return 0; + } + + vtkImageData *input = this->GetInput(); + input->UpdateInformation(); + input->SetUpdateExtent(input->GetWholeExtent()); + input->ReleaseDataFlagOff(); + + input->Update(); + this->UpdateProgress(0.0); + this->UpdateProgress(1.0); + + return input->GetScalarPointer(); +} + +//---------------------------------------------------------------------------- +void* vtkImageExport::GetCallbackUserData() +{ + return this; +} + +vtkImageExport::UpdateInformationCallbackType +vtkImageExport::GetUpdateInformationCallback() const +{ + return &vtkImageExport::UpdateInformationCallbackFunction; +} + +vtkImageExport::PipelineModifiedCallbackType +vtkImageExport::GetPipelineModifiedCallback() const +{ + return &vtkImageExport::PipelineModifiedCallbackFunction; +} + +vtkImageExport::WholeExtentCallbackType +vtkImageExport::GetWholeExtentCallback() const +{ + return &vtkImageExport::WholeExtentCallbackFunction; +} + +vtkImageExport::SpacingCallbackType +vtkImageExport::GetSpacingCallback() const +{ + return &vtkImageExport::SpacingCallbackFunction; +} + +vtkImageExport::OriginCallbackType +vtkImageExport::GetOriginCallback() const +{ + return &vtkImageExport::OriginCallbackFunction; +} + +vtkImageExport::ScalarTypeCallbackType +vtkImageExport::GetScalarTypeCallback() const +{ + return &vtkImageExport::ScalarTypeCallbackFunction; +} + +vtkImageExport::NumberOfComponentsCallbackType +vtkImageExport::GetNumberOfComponentsCallback() const +{ + return &vtkImageExport::NumberOfComponentsCallbackFunction; +} + +vtkImageExport::PropagateUpdateExtentCallbackType +vtkImageExport::GetPropagateUpdateExtentCallback() const +{ + return &vtkImageExport::PropagateUpdateExtentCallbackFunction; +} + +vtkImageExport::UpdateDataCallbackType +vtkImageExport::GetUpdateDataCallback() const +{ + return &vtkImageExport::UpdateDataCallbackFunction; +} + +vtkImageExport::DataExtentCallbackType +vtkImageExport::GetDataExtentCallback() const +{ + return &vtkImageExport::DataExtentCallbackFunction; +} + +vtkImageExport::BufferPointerCallbackType +vtkImageExport::GetBufferPointerCallback() const +{ + return &vtkImageExport::BufferPointerCallbackFunction; +} + +//---------------------------------------------------------------------------- +void vtkImageExport::UpdateInformationCallbackFunction(void* userData) +{ + static_cast(userData)-> + UpdateInformationCallback(); +} + +int vtkImageExport::PipelineModifiedCallbackFunction(void* userData) +{ + return static_cast(userData)-> + PipelineModifiedCallback(); +} + +int* vtkImageExport::WholeExtentCallbackFunction(void* userData) +{ + return static_cast(userData)-> + WholeExtentCallback(); +} + +double* vtkImageExport::SpacingCallbackFunction(void* userData) +{ + return static_cast(userData)-> + SpacingCallback(); +} + +double* vtkImageExport::OriginCallbackFunction(void* userData) +{ + return static_cast(userData)-> + OriginCallback(); +} + +const char* vtkImageExport::ScalarTypeCallbackFunction(void* userData) +{ + return static_cast(userData)-> + ScalarTypeCallback(); +} + +int vtkImageExport::NumberOfComponentsCallbackFunction(void* userData) +{ + return static_cast(userData)-> + NumberOfComponentsCallback(); +} + +void vtkImageExport::PropagateUpdateExtentCallbackFunction(void* userData, + int* extent) +{ + static_cast(userData)-> + PropagateUpdateExtentCallback(extent); +} + +void vtkImageExport::UpdateDataCallbackFunction(void* userData) +{ + static_cast(userData)-> + UpdateDataCallback(); +} + +int* vtkImageExport::DataExtentCallbackFunction(void* userData) +{ + return static_cast(userData)-> + DataExtentCallback(); +} + +void* vtkImageExport::BufferPointerCallbackFunction(void* userData) +{ + return static_cast(userData)-> + BufferPointerCallback(); +} + + +//---------------------------------------------------------------------------- +void vtkImageExport::UpdateInformationCallback() +{ + if (this->GetInput()) + { + this->GetInput()->UpdateInformation(); + } +} + +int vtkImageExport::PipelineModifiedCallback() +{ + if (!this->GetInput()) + { + return 0; + } + + unsigned long mtime = this->GetInput()->GetPipelineMTime(); + if(mtime > this->LastPipelineMTime) + { + this->LastPipelineMTime = mtime; + return 1; + } + return 0; +} + +int* vtkImageExport::WholeExtentCallback() +{ + static int defaultextent[6] = {0,0,0,0,0,0}; + if (!this->GetInput()) + { + return defaultextent; + } + else + { + return this->GetInput()->GetWholeExtent(); + } +} + +double* vtkImageExport::SpacingCallback() +{ + static double defaultspacing[6] = {0.0,0.0,0.0}; + if (!this->GetInput()) + { + return defaultspacing; + } + else + { + return this->GetInput()->GetSpacing(); + } +} + +double* vtkImageExport::OriginCallback() +{ + static double defaultorigin[3] = {0.0,0.0,0.0}; + if (!this->GetInput()) + { + return defaultorigin; + } + else + { + return this->GetInput()->GetOrigin(); + } +} + +const char* vtkImageExport::ScalarTypeCallback() +{ + if (!this->GetInput()) + { + return "unsigned char"; + } + + switch (this->GetInput()->GetScalarType()) + { + case VTK_DOUBLE: + { return "double"; } + case VTK_FLOAT: + { return "float"; } + case VTK_LONG: + { return "long"; } + case VTK_UNSIGNED_LONG: + { return "unsigned long"; } + case VTK_INT: + { return "int"; } + case VTK_UNSIGNED_INT: + { return "unsigned int"; } + case VTK_SHORT: + { return "short"; } + case VTK_UNSIGNED_SHORT: + { return "unsigned short"; } + case VTK_CHAR: + { return "char"; } + case VTK_UNSIGNED_CHAR: + { return "unsigned char"; } + default: + { return ""; } + } +} + +int vtkImageExport::NumberOfComponentsCallback() +{ + if (!this->GetInput()) + { + return 1; + } + else + { + return this->GetInput()->GetNumberOfScalarComponents(); + } +} + +void vtkImageExport::PropagateUpdateExtentCallback(int* extent) +{ + if (this->GetInput()) + { + this->GetInput()->SetUpdateExtent(extent); + } +} + +void vtkImageExport::UpdateDataCallback() +{ + if (this->GetInput()) + { + this->GetInput()->Update(); + } +} + +int* vtkImageExport::DataExtentCallback() +{ + static int defaultextent[6] = {0,0,0,0,0,0}; + if (!this->GetInput()) + { + return defaultextent; + } + else + { + return this->GetInput()->GetExtent(); + } +} + +void* vtkImageExport::BufferPointerCallback() +{ + if (!this->GetInput()) + { + return (void*)NULL; + } + else + { + return this->GetInput()->GetScalarPointer(); + } +} + +int vtkImageExport::GetDataNumberOfScalarComponents() +{ + if (this->GetInput() == NULL) + { + return 1; + } + this->GetInput()->UpdateInformation(); + return this->GetInput()->GetNumberOfScalarComponents(); +} + +int vtkImageExport::GetDataScalarType() +{ + if (this->GetInput() == NULL) + { + return VTK_UNSIGNED_CHAR; + } + this->GetInput()->UpdateInformation(); + return this->GetInput()->GetScalarType(); +} + +int *vtkImageExport::GetDataExtent() +{ + static int defaultextent[6] = {0, 0, 0, 0, 0, 0}; + if (this->GetInput() == NULL) { return defaultextent; } + this->GetInput()->UpdateInformation(); + return this->GetInput()->GetWholeExtent(); +} + +void vtkImageExport::GetDataExtent(int *ptr) +{ + if (this->GetInput() == NULL) { + ptr[0] = ptr[1] = ptr[2] = ptr[3] = ptr[4] = ptr[5] = 0; return; } + this->GetInput()->UpdateInformation(); + this->GetInput()->GetWholeExtent(ptr); +} + +double *vtkImageExport::GetDataSpacing() +{ + static double defaultspacing[3] = {1, 1, 1}; + if (this->GetInput() == NULL) { return defaultspacing; } + this->GetInput()->UpdateInformation(); + return this->GetInput()->GetSpacing(); +} + +void vtkImageExport::GetDataSpacing(double *ptr) +{ + if (this->GetInput() == NULL) { ptr[0] = ptr[1] = ptr[2] = 0.0; return; } + this->GetInput()->UpdateInformation(); + this->GetInput()->GetSpacing(ptr); +} + +double *vtkImageExport::GetDataOrigin() +{ + static double defaultorigin[3] = {0, 0, 0}; + if (this->GetInput() == NULL) { return defaultorigin; } + this->GetInput()->UpdateInformation(); + return this->GetInput()->GetOrigin(); +} + +void vtkImageExport::GetDataOrigin(double *ptr) +{ + if (this->GetInput() == NULL) { ptr[0] = ptr[1] = ptr[2] = 0.0; return; } + this->GetInput()->UpdateInformation(); + this->GetInput()->GetOrigin(ptr); +} diff --git a/Imaging/vtkImageExport.h b/Imaging/vtkImageExport.h new file mode 100644 index 0000000..ade7173 --- /dev/null +++ b/Imaging/vtkImageExport.h @@ -0,0 +1,195 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageExport.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageExport - Export VTK images to third-party systems. +// .SECTION Description +// vtkImageExport provides a way of exporting image data at the end +// of a pipeline to a third-party system or to a simple C array. +// Applications can use this to get direct access to the image data +// in memory. A callback interface is provided to allow connection +// of the VTK pipeline to a third-party pipeline. This interface +// conforms to the interface of vtkImageImport. +// In Python it is possible to use this class to write the image data +// into a python string that has been pre-allocated to be the correct +// size. +// .SECTION See Also +// vtkImageImport + +#ifndef __vtkImageExport_h +#define __vtkImageExport_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageExport : public vtkImageAlgorithm +{ +public: + static vtkImageExport *New(); + vtkTypeRevisionMacro(vtkImageExport,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the number of bytes required for the output C array. + int GetDataMemorySize(); + + // Description: + // Get the (x,y,z) index dimensions of the data. Please note + // that C arrays are indexed in decreasing order, i.e. array[z][y][x]. + void GetDataDimensions(int *ptr); + int *GetDataDimensions() { + this->GetDataDimensions(this->DataDimensions); + return this->DataDimensions; } + + // Description: + // Get the number of scalar components of the data. Please note that + // when you index into a C array, the scalar component index comes + // last, i.e. array[z][y][x][c]. + int GetDataNumberOfScalarComponents(); + + // Description: + // Get the scalar type of the data. The scalar type of the C array + // must match the scalar type of the data. + int GetDataScalarType(); + const char *GetDataScalarTypeAsString() { + return vtkImageScalarTypeNameMacro(this->GetDataScalarType()); } + + // Description: + // Get miscellaneous additional information about the data. + int *GetDataExtent(); + void GetDataExtent(int *ptr); + double *GetDataSpacing(); + void GetDataSpacing(double *ptr); + double *GetDataOrigin(); + void GetDataOrigin(double *ptr); + +//BTX + // Description: + // Get the input object from the image pipeline. + vtkImageData *GetInput(); +//ETX + + // Description: + // Set/Get whether the data goes to the exported memory starting + // in the lower left corner or upper left corner. Default: On. + // When this flag is Off, the image will be flipped vertically + // before it is exported. + // WARNING: this flag is used only with the Export() method, + // it is ignored by GetPointerToData(). + vtkBooleanMacro(ImageLowerLeft, int); + vtkGetMacro(ImageLowerLeft, int); + vtkSetMacro(ImageLowerLeft, int); + + // Description: + // Set the void pointer of the C array to export the data to. + // From python, you can specify a pointer to a string that is + // large enough to hold the data. + void SetExportVoidPointer(void *); + void *GetExportVoidPointer() { return this->ExportVoidPointer; }; + + // Description: + // The main interface: update the pipeline and export the image + // to the memory pointed to by SetExportVoidPointer(). You can + // also specify a void pointer when you call Export(). + void Export() { this->Export(this->ExportVoidPointer); }; + virtual void Export(void *); + + // Description: + // An alternative to Export(): Use with caution. Update the + // pipeline and return a pointer to the image memory. The + // pointer is only valid until the next time that the pipeline + // is updated. + // WARNING: This method ignores the ImageLowerLeft flag. + void *GetPointerToData(); + + // Description: + // Get the user data that should be passed to the callback functions. + void* GetCallbackUserData(); + + //BTX + // Description: + // These are function pointer types for the pipeline connection + // callbacks. See furhter documentation in vtkImageImport.h. + typedef void (*UpdateInformationCallbackType)(void*); + typedef int (*PipelineModifiedCallbackType)(void*); + typedef int* (*WholeExtentCallbackType)(void*); + typedef double* (*SpacingCallbackType)(void*); + typedef double* (*OriginCallbackType)(void*); + typedef const char* (*ScalarTypeCallbackType)(void*); + typedef int (*NumberOfComponentsCallbackType)(void*); + typedef void (*PropagateUpdateExtentCallbackType)(void*, int*); + typedef void (*UpdateDataCallbackType)(void*); + typedef int* (*DataExtentCallbackType)(void*); + typedef void* (*BufferPointerCallbackType)(void*); + + // Description: + // Get pointers to the pipeline interface callbacks. + UpdateInformationCallbackType GetUpdateInformationCallback() const; + PipelineModifiedCallbackType GetPipelineModifiedCallback() const; + WholeExtentCallbackType GetWholeExtentCallback() const; + SpacingCallbackType GetSpacingCallback() const; + OriginCallbackType GetOriginCallback() const; + ScalarTypeCallbackType GetScalarTypeCallback() const; + NumberOfComponentsCallbackType GetNumberOfComponentsCallback() const; + PropagateUpdateExtentCallbackType GetPropagateUpdateExtentCallback() const; + UpdateDataCallbackType GetUpdateDataCallback() const; + DataExtentCallbackType GetDataExtentCallback() const; + BufferPointerCallbackType GetBufferPointerCallback() const; + //ETX + +protected: + vtkImageExport(); + ~vtkImageExport(); + + // This is called by the superclass. + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + virtual void UpdateInformationCallback(); + virtual int PipelineModifiedCallback(); + virtual void UpdateDataCallback(); + virtual int* WholeExtentCallback(); + virtual double* SpacingCallback(); + virtual double* OriginCallback(); + virtual const char* ScalarTypeCallback(); + virtual int NumberOfComponentsCallback(); + virtual void PropagateUpdateExtentCallback(int*); + virtual int* DataExtentCallback(); + virtual void* BufferPointerCallback(); + + int ImageLowerLeft; + int DataDimensions[3]; + void *ExportVoidPointer; + + unsigned long LastPipelineMTime; + +private: + vtkImageExport(const vtkImageExport&); // Not implemented. + void operator=(const vtkImageExport&); // Not implemented. + + static void UpdateInformationCallbackFunction(void*); + static int PipelineModifiedCallbackFunction(void*); + static int* WholeExtentCallbackFunction(void*); + static double* SpacingCallbackFunction(void*); + static double* OriginCallbackFunction(void*); + static const char* ScalarTypeCallbackFunction(void*); + static int NumberOfComponentsCallbackFunction(void*); + static void PropagateUpdateExtentCallbackFunction(void*, int*); + static void UpdateDataCallbackFunction(void*); + static int* DataExtentCallbackFunction(void*); + static void* BufferPointerCallbackFunction(void*); +}; + +#endif + + diff --git a/Imaging/vtkImageExtractComponents.cxx b/Imaging/vtkImageExtractComponents.cxx new file mode 100644 index 0000000..beb355a --- /dev/null +++ b/Imaging/vtkImageExtractComponents.cxx @@ -0,0 +1,270 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageExtractComponents.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageExtractComponents.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageExtractComponents, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkImageExtractComponents); + +//---------------------------------------------------------------------------- +vtkImageExtractComponents::vtkImageExtractComponents() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + this->Components[0] = 0; + this->Components[1] = 1; + this->Components[2] = 2; + this->NumberOfComponents = 1; +} + +//---------------------------------------------------------------------------- +void vtkImageExtractComponents::SetComponents(int c1, int c2, int c3) +{ + int modified = 0; + + if (this->Components[0] != c1) + { + this->Components[0] = c1; + modified = 1; + } + if (this->Components[1] != c2) + { + this->Components[1] = c2; + modified = 1; + } + if (this->Components[2] != c3) + { + this->Components[2] = c3; + modified = 1; + } + + if (modified || this->NumberOfComponents != 3) + { + this->NumberOfComponents = 3; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageExtractComponents::SetComponents(int c1, int c2) +{ + int modified = 0; + + if (this->Components[0] != c1) + { + this->Components[0] = c1; + modified = 1; + } + if (this->Components[1] != c2) + { + this->Components[1] = c2; + modified = 1; + } + + if (modified || this->NumberOfComponents != 2) + { + this->NumberOfComponents = 2; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageExtractComponents::SetComponents(int c1) +{ + int modified = 0; + + if (this->Components[0] != c1) + { + this->Components[0] = c1; + modified = 1; + } + + if (modified || this->NumberOfComponents != 1) + { + this->NumberOfComponents = 1; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// This method tells the superclass that only one component will remain. +int vtkImageExtractComponents::RequestInformation ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * outputVector) +{ + vtkDataObject::SetPointDataActiveScalarInfo( + outputVector->GetInformationObject(0), -1, this->NumberOfComponents); + return 1; +} + +//---------------------------------------------------------------------------- +template +void vtkImageExtractComponentsExecute(vtkImageExtractComponents *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxR, idxY, idxZ; + int maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int cnt, inCnt; + int offset1, offset2, offset3; + unsigned long count = 0; + unsigned long target; + + // find the region to loop over + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + cnt = outData->GetNumberOfScalarComponents(); + inCnt = inData->GetNumberOfScalarComponents(); + + // Loop through output pixels + offset1 = self->GetComponents()[0]; + offset2 = self->GetComponents()[1]; + offset3 = self->GetComponents()[2]; + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + // handle inner loop based on number of components extracted + switch (cnt) + { + case 1: + for (idxR = 0; idxR <= maxX; idxR++) + { + // Pixel operation + *outPtr = *(inPtr + offset1); + outPtr++; + inPtr += inCnt; + } + break; + case 2: + for (idxR = 0; idxR <= maxX; idxR++) + { + // Pixel operation + *outPtr = *(inPtr + offset1); + outPtr++; + *outPtr = *(inPtr + offset2); + outPtr++; + inPtr += inCnt; + } + break; + case 3: + for (idxR = 0; idxR <= maxX; idxR++) + { + // Pixel operation + *outPtr = *(inPtr + offset1); + outPtr++; + *outPtr = *(inPtr + offset2); + outPtr++; + *outPtr = *(inPtr + offset3); + outPtr++; + inPtr += inCnt; + } + break; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This method is passed input and output datas, and executes the +// ExtractComponents function on each line. +void vtkImageExtractComponents::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + int max, idx; + void *inPtr = inData->GetScalarPointerForExtent(outExt); + void *outPtr = outData->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData->GetScalarType() + << ", must match out ScalarType " + << outData->GetScalarType()); + return; + } + + // make sure we can get all of the components. + max = inData->GetNumberOfScalarComponents(); + for (idx = 0; idx < this->NumberOfComponents; ++idx) + { + if (this->Components[idx] >= max || this->Components[idx] < 0) + { + vtkErrorMacro("Execute: Component " << this->Components[idx] + << " is not in input."); + return; + } + } + + // choose which templated function to call. + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageExtractComponentsExecute(this, inData, + (VTK_TT *)(inPtr), outData, + (VTK_TT *)(outPtr), + outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageExtractComponents::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfComponents: " << this->NumberOfComponents << endl; + os << indent << "Components: ( " + << this->Components[0] << ", " + << this->Components[1] << ", " + << this->Components[2] << " )\n"; + +} + diff --git a/Imaging/vtkImageExtractComponents.h b/Imaging/vtkImageExtractComponents.h new file mode 100644 index 0000000..be409a9 --- /dev/null +++ b/Imaging/vtkImageExtractComponents.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageExtractComponents.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageExtractComponents - Outputs a single component +// .SECTION Description +// vtkImageExtractComponents takes an input with any number of components +// and outputs some of them. It does involve a copy of the data. + +// .SECTION See Also +// vtkImageAppendComponents + +#ifndef __vtkImageExtractComponents_h +#define __vtkImageExtractComponents_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageExtractComponents : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageExtractComponents *New(); + vtkTypeRevisionMacro(vtkImageExtractComponents,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the components to extract. + void SetComponents(int c1); + void SetComponents(int c1, int c2); + void SetComponents(int c1, int c2, int c3); + vtkGetVector3Macro(Components,int); + + // Description: + // Get the number of components to extract. This is set implicitly by the + // SetComponents() method. + vtkGetMacro(NumberOfComponents,int); + +protected: + vtkImageExtractComponents(); + ~vtkImageExtractComponents() {}; + + int NumberOfComponents; + int Components[3]; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, + vtkInformationVector *); + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); +private: + vtkImageExtractComponents(const vtkImageExtractComponents&); // Not implemented. + void operator=(const vtkImageExtractComponents&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageFFT.cxx b/Imaging/vtkImageFFT.cxx new file mode 100644 index 0000000..a474db7 --- /dev/null +++ b/Imaging/vtkImageFFT.cxx @@ -0,0 +1,298 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFFT.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageFFT.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageFFT, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkImageFFT); + +//---------------------------------------------------------------------------- +// This extent of the components changes to real and imaginary values. +int vtkImageFFT::IterativeRequestInformation( + vtkInformation* vtkNotUsed(input), vtkInformation* output) +{ + vtkDataObject::SetPointDataActiveScalarInfo(output, VTK_DOUBLE, 2); + return 1; +} + +void vtkImageFFTInternalRequestUpdateExtent(int *inExt, int *outExt, int *wExt, + int iteration) +{ + memcpy(inExt, outExt, 6 * sizeof(int)); + inExt[iteration*2] = wExt[iteration*2]; + inExt[iteration*2 + 1] = wExt[iteration*2 + 1]; +} + +//---------------------------------------------------------------------------- +// This method tells the superclass that the whole input array is needed +// to compute any output region. +int vtkImageFFT::IterativeRequestUpdateExtent( + vtkInformation* input, vtkInformation* output) +{ + int *outExt = output->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + int *wExt = input->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + int inExt[6]; + vtkImageFFTInternalRequestUpdateExtent(inExt,outExt,wExt,this->Iteration); + input->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This templated execute method handles any type input, but the output +// is always doubles. +template +void vtkImageFFTExecute(vtkImageFFT *self, + vtkImageData *inData, int inExt[6], T *inPtr, + vtkImageData *outData, int outExt[6], double *outPtr, + int id) +{ + vtkImageComplex *inComplex; + vtkImageComplex *outComplex; + vtkImageComplex *pComplex; + // + int inMin0, inMax0; + vtkIdType inInc0, inInc1, inInc2; + T *inPtr0, *inPtr1, *inPtr2; + // + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + vtkIdType outInc0, outInc1, outInc2; + double *outPtr0, *outPtr1, *outPtr2; + // + int idx0, idx1, idx2, inSize0, numberOfComponents; + unsigned long count = 0; + unsigned long target; + double startProgress; + + startProgress = self->GetIteration()/(double)(self->GetNumberOfIterations()); + + // Reorder axes (The outs here are just placeholdes + self->PermuteExtent(inExt, inMin0, inMax0, outMin1,outMax1,outMin2,outMax2); + self->PermuteExtent(outExt, outMin0,outMax0,outMin1,outMax1,outMin2,outMax2); + self->PermuteIncrements(inData->GetIncrements(), inInc0, inInc1, inInc2); + self->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + inSize0 = inMax0 - inMin0 + 1; + + // Input has to have real components at least. + numberOfComponents = inData->GetNumberOfScalarComponents(); + if (numberOfComponents < 1) + { + vtkGenericWarningMacro("No real components"); + return; + } + + // Allocate the arrays of complex numbers + inComplex = new vtkImageComplex[inSize0]; + outComplex = new vtkImageComplex[inSize0]; + + target = (unsigned long)((outMax2-outMin2+1)*(outMax1-outMin1+1) + * self->GetNumberOfIterations() / 50.0); + target++; + + // loop over other axes + inPtr2 = inPtr; + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = outMin1; !self->AbortExecute && idx1 <= outMax1; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target) + startProgress); + } + count++; + } + // copy into complex numbers + inPtr0 = inPtr1; + pComplex = inComplex; + for (idx0 = inMin0; idx0 <= inMax0; ++idx0) + { + pComplex->Real = (double)(*inPtr0); + pComplex->Imag = 0.0; + if (numberOfComponents > 1) + { // yes we have an imaginary input + pComplex->Imag = (double)(inPtr0[1]);; + } + inPtr0 += inInc0; + ++pComplex; + } + + // Call the method that performs the fft + self->ExecuteFft(inComplex, outComplex, inSize0); + + // copy into output + outPtr0 = outPtr1; + pComplex = outComplex + (outMin0 - inMin0); + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + *outPtr0 = (double)pComplex->Real; + outPtr0[1] = (double)pComplex->Imag; + outPtr0 += outInc0; + ++pComplex; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + + delete [] inComplex; + delete [] outComplex; +} + + + + +//---------------------------------------------------------------------------- +// This method is passed input and output Datas, and executes the fft +// algorithm to fill the output from the input. +// Not threaded yet. +void vtkImageFFT::ThreadedExecute(vtkImageData *inData, vtkImageData *outData, + int outExt[6], int threadId) +{ + void *inPtr, *outPtr; + int inExt[6]; + int *wExt = inData->GetWholeExtent(); + vtkImageFFTInternalRequestUpdateExtent(inExt,outExt,wExt,this->Iteration); + + inPtr = inData->GetScalarPointerForExtent(inExt); + outPtr = outData->GetScalarPointerForExtent(outExt); + + // this filter expects that the output be doubles. + if (outData->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "Execute: Output must be be type double."); + return; + } + + // this filter expects input to have 1 or two components + if (outData->GetNumberOfScalarComponents() != 1 && + outData->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro(<< "Execute: Cannot handle more than 2 components"); + return; + } + + // choose which templated function to call. + switch (inData->GetScalarType()) + { + vtkTemplateMacro(vtkImageFFTExecute(this, inData, inExt, + (VTK_TT *)(inPtr), outData, outExt, + (double *)(outPtr), threadId)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + +//---------------------------------------------------------------------------- +// For streaming and threads. Splits output update extent into num pieces. +// This method needs to be called num times. Results must not overlap for +// consistent starting extent. Subclass can override this method. +// This method returns the number of peices resulting from a successful split. +// This can be from 1 to "total". +// If 1 is returned, the extent cannot be split. +int vtkImageFFT::SplitExtent(int splitExt[6], int startExt[6], + int num, int total) +{ + int splitAxis; + int min, max; + + vtkDebugMacro("SplitExtent: ( " << startExt[0] << ", " << startExt[1] << ", " + << startExt[2] << ", " << startExt[3] << ", " + << startExt[4] << ", " << startExt[5] << "), " + << num << " of " << total); + + // start with same extent + memcpy(splitExt, startExt, 6 * sizeof(int)); + + splitAxis = 2; + min = startExt[4]; + max = startExt[5]; + while ((splitAxis == this->Iteration) || (min == max)) + { + splitAxis--; + if (splitAxis < 0) + { // cannot split + vtkDebugMacro(" Cannot Split"); + return 1; + } + min = startExt[splitAxis*2]; + max = startExt[splitAxis*2+1]; + } + + // determine the actual number of pieces that will be generated + if ((max - min + 1) < total) + { + total = max - min + 1; + } + + if (num >= total) + { + vtkDebugMacro(" SplitRequest (" << num + << ") larger than total: " << total); + return total; + } + + // determine the extent of the piece + splitExt[splitAxis*2] = min + (max - min + 1)*num/total; + if (num == total - 1) + { + splitExt[splitAxis*2+1] = max; + } + else + { + splitExt[splitAxis*2+1] = (min-1) + (max - min + 1)*(num+1)/total; + } + + vtkDebugMacro(" Split Piece: ( " <PreserveImageExtent = 1; + this->FlipAboutOrigin = 0; + this->FilteredAxis = 0; + + if (!this->ResliceAxes) + { + // for consistent register/unregister + this->SetResliceAxes(vtkMatrix4x4::New()); + this->ResliceAxes->Delete(); + } +} + +//---------------------------------------------------------------------------- +int vtkImageFlip::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + double spacing[3]; + double origin[3]; + int wholeExt[6]; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + inInfo->Get(vtkDataObject::SPACING(), spacing); + inInfo->Get(vtkDataObject::ORIGIN(), origin); + + int iflip = this->FilteredAxis; + + // changing the matrix elements directly is ugly, but if the matrix is + // Modified then the MTime of the filter also changes, which would screw + // up the pipeline + if (this->ResliceAxes) + { + // set to identity + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + this->ResliceAxes->Element[i][j] = 0.0; + } + this->ResliceAxes->Element[i][i] = 1.0; + } + // but with a iflip along one axis + this->ResliceAxes->Element[iflip][iflip] = -1.0; + } + + if (!this->FlipAboutOrigin) + { + // set ResliceAxesOrigin so the flip occurs around the correct axis such that + // the Origin of the output data can be left the same as the Origin of the + // input data + if (this->ResliceAxes) + { + this->ResliceAxes->Element[iflip][3] = 2*origin[iflip] + + spacing[iflip]*(wholeExt[2*iflip] + wholeExt[2*iflip+1]); + } + } + else + { + // set the output Origin such that when the image flips about its origin + // (meaning the real origin, not what vtkImageData calls "Origin") the + // transformed output bounds exactly overlay the input bounds. + origin[iflip] = - origin[iflip] + - spacing[iflip]*(wholeExt[2*iflip] + wholeExt[2*iflip+1]); + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt, 6); + outInfo->Set(vtkDataObject::SPACING(), spacing, 3); + outInfo->Set(vtkDataObject::ORIGIN(), origin, 3); + + // This information already copied from input to output in CopyInformationToPipeline? + vtkInformation *inScalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!inScalarInfo) + { + vtkErrorMacro("Missing scalar field on input information!"); + return 0; + } + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, + inScalarInfo->Get( vtkDataObject::FIELD_ARRAY_TYPE() ), + inScalarInfo->Get( vtkDataObject::FIELD_NUMBER_OF_COMPONENTS() ) ); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageFlip::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "FilteredAxis: " << this->FilteredAxis << "\n"; + os << indent << "FlipAboutOrigin: " << (this->FlipAboutOrigin ? "On\n" : "Off\n"); + os << indent << "PreserveImageExtent: " << (this->PreserveImageExtent ? "On\n" : "Off\n"); +} diff --git a/Imaging/vtkImageFlip.h b/Imaging/vtkImageFlip.h new file mode 100644 index 0000000..8d17218 --- /dev/null +++ b/Imaging/vtkImageFlip.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFlip.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageFlip - This flips an axis of an image. Right becomes left ... +// .SECTION Description +// vtkImageFlip will reflect the data along the filtered axis. This filter is +// actually a thin wrapper around vtkImageReslice. + +#ifndef __vtkImageFlip_h +#define __vtkImageFlip_h + + +#include "vtkImageReslice.h" + +class VTK_IMAGING_EXPORT vtkImageFlip : public vtkImageReslice +{ +public: + static vtkImageFlip *New(); + + vtkTypeRevisionMacro(vtkImageFlip,vtkImageReslice); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify which axis will be flipped. This must be an integer + // between 0 (for x) and 2 (for z). + vtkSetMacro(FilteredAxis, int); + vtkGetMacro(FilteredAxis, int); + + // Description: + // By default the image will be flipped about its center, and the + // Origin, Spacing and Extent of the output will be identical to + // the input. However, if you have a coordinate system associated + // with the image and you want to use the flip to convert +ve values + // along one axis to -ve values (and vice versa) then you actually + // want to flip the image about coordinate (0,0,0) instead of about + // the center of the image. This method will adjust the Origin of + // the output such that the flip occurs about (0,0,0). Note that + // this method only changes the Origin (and hence the coordinate system) + // the output data: the actual pixel values are the same whether or not + // this method is used. Also note that the Origin in this method name + // refers to (0,0,0) in the coordinate system associated with the image, + // it does not refer to the Origin ivar that is associated with a + // vtkImageData. + vtkSetMacro(FlipAboutOrigin, int); + vtkGetMacro(FlipAboutOrigin, int); + vtkBooleanMacro(FlipAboutOrigin, int); + + // Description: + // For compatibility with old scripts. + void SetFilteredAxes(int axis) { this->SetFilteredAxis(axis); }; + + // Description: + // PreserveImageExtentOff wasn't covered by test scripts and its + // implementation was broken. It is deprecated now and it has + // no effect (i.e. the ImageExtent is always preserved). + vtkSetMacro(PreserveImageExtent, int); + vtkGetMacro(PreserveImageExtent, int); + vtkBooleanMacro(PreserveImageExtent, int); + +protected: + vtkImageFlip(); + ~vtkImageFlip() {}; + + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int FilteredAxis; + int FlipAboutOrigin; + int PreserveImageExtent; + +private: + vtkImageFlip(const vtkImageFlip&); // Not implemented. + void operator=(const vtkImageFlip&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageFourierCenter.cxx b/Imaging/vtkImageFourierCenter.cxx new file mode 100644 index 0000000..e5501d5 --- /dev/null +++ b/Imaging/vtkImageFourierCenter.cxx @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFourierCenter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageFourierCenter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageFourierCenter, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkImageFourierCenter); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageFourierCenter fitler. +vtkImageFourierCenter::vtkImageFourierCenter() +{ +} + + +//---------------------------------------------------------------------------- +// This method tells the superclass which input extent is needed. +// This gets the whole input (even though it may not be needed). +int vtkImageFourierCenter::IterativeRequestUpdateExtent( + vtkInformation* input, vtkInformation* output) +{ + int *outExt = output->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + int *wExt = input->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + int inExt[6]; + memcpy(inExt, outExt, 6 * sizeof(int)); + inExt[this->Iteration*2] = wExt[this->Iteration*2]; + inExt[this->Iteration*2 + 1] = wExt[this->Iteration*2 + 1]; + input->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This method is passed input and output regions, and executes the fft +// algorithm to fill the output from the input. +void vtkImageFourierCenter::ThreadedExecute(vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int threadId) +{ + double *inPtr0, *inPtr1, *inPtr2; + double *outPtr0, *outPtr1, *outPtr2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + int *wholeExtent, wholeMin0, wholeMax0, mid0; + int inIdx0, outIdx0, idx1, idx2; + int min0, max0, min1, max1, min2, max2; + int numberOfComponents; + int inCoords[3]; + unsigned long count = 0; + unsigned long target; + double startProgress; + + startProgress = this->GetIteration()/(double)(this->GetNumberOfIterations()); + + // this filter expects that the input be doubles. + if (inData->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "Execute: Input must be be type double."); + return; + } + // this filter expects that the output be doubles. + if (outData->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "Execute: Output must be be type double."); + return; + } + // this filter expects input to have 1 or two components + if (outData->GetNumberOfScalarComponents() != 1 && + outData->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro(<< "Execute: Cannot handle more than 2 components"); + return; + } + + // Get stuff needed to loop through the pixel + numberOfComponents = outData->GetNumberOfScalarComponents(); + outPtr0 = (double *)(outData->GetScalarPointerForExtent(outExt)); + wholeExtent = this->GetOutput()->GetWholeExtent(); + // permute to make the filtered axis come first + this->PermuteExtent(outExt, min0, max0, min1, max1, min2, max2); + this->PermuteIncrements(inData->GetIncrements(), inInc0, inInc1, inInc2); + this->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + // Determine the mid for the filtered axis + wholeMin0 = wholeExtent[this->Iteration * 2]; + wholeMax0 = wholeExtent[this->Iteration * 2 + 1]; + mid0 = (wholeMin0 + wholeMax0) / 2; + + // initialize input coordinates + inCoords[0] = outExt[0]; + inCoords[1] = outExt[2]; + inCoords[2] = outExt[4]; + + target = (unsigned long)((max2-min2+1)*(max0-min0+1) + * this->GetNumberOfIterations() / 50.0); + target++; + + // loop over the filtered axis first + for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0) + { + // get the correct input pointer + inIdx0 = outIdx0 + mid0; + if (inIdx0 > wholeMax0) + { + inIdx0 -= (wholeMax0 - wholeMin0 + 1); + } + inCoords[this->Iteration] = inIdx0; + inPtr0 = (double *)(inData->GetScalarPointer(inCoords)); + + // loop over other axes + inPtr2 = inPtr0; + outPtr2 = outPtr0; + for (idx2 = min2; !this->AbortExecute && idx2 <= max2; ++idx2) + { + if (!threadId) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target) + startProgress); + } + count++; + } + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = min1; idx1 <= max1; ++idx1) + { + // handle components (up to 2) explicitly + *outPtr1 = *inPtr1; + if (numberOfComponents == 2) + { + outPtr1[1] = inPtr1[1]; + } + + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + outPtr0 += outInc0; + } +} + + + + + + + + + + + + + + + + + + diff --git a/Imaging/vtkImageFourierCenter.h b/Imaging/vtkImageFourierCenter.h new file mode 100644 index 0000000..040cd20 --- /dev/null +++ b/Imaging/vtkImageFourierCenter.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFourierCenter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageFourierCenter - Shifts constant frequency to center for +// display. +// .SECTION Description +// Is used for dispaying images in frequency space. FFT converts spatial +// images into frequency space, but puts the zero frequency at the origin. +// This filter shifts the zero frequency to the center of the image. +// Input and output are assumed to be doubles. + +#ifndef __vtkImageFourierCenter_h +#define __vtkImageFourierCenter_h + + +#include "vtkImageDecomposeFilter.h" + +class VTK_IMAGING_EXPORT vtkImageFourierCenter : public vtkImageDecomposeFilter +{ +public: + static vtkImageFourierCenter *New(); + vtkTypeRevisionMacro(vtkImageFourierCenter,vtkImageDecomposeFilter); + +protected: + vtkImageFourierCenter(); + ~vtkImageFourierCenter() {}; + + virtual int IterativeRequestUpdateExtent(vtkInformation* in, + vtkInformation* out); + + void ThreadedExecute(vtkImageData *inData, vtkImageData *outData, + int outExt[6], int threadId); +private: + vtkImageFourierCenter(const vtkImageFourierCenter&); // Not implemented. + void operator=(const vtkImageFourierCenter&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageFourierFilter.cxx b/Imaging/vtkImageFourierFilter.cxx new file mode 100644 index 0000000..b0c7265 --- /dev/null +++ b/Imaging/vtkImageFourierFilter.cxx @@ -0,0 +1,233 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFourierFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageFourierFilter.h" + +#include + +vtkCxxRevisionMacro(vtkImageFourierFilter, "$Revision: 1.18 $"); + + +/*========================================================================= + Vectors of complex numbers. +=========================================================================*/ + +//---------------------------------------------------------------------------- +// This function calculates one step of a FFT. +// It is specialized for a factor of 2. +// It is engineered for no decimation. +// (forward: fb = 1, backward: fb = -1) +void vtkImageFourierFilter::ExecuteFftStep2(vtkImageComplex *p_in, + vtkImageComplex *p_out, + int N, int bsize, int fb) +{ + int i1, i2; + vtkImageComplex *p1, *p2, *p3; + vtkImageComplex q, fact1, fact, temp; + + /* Copy the links with no factors. */ + p1 = p_in; + p3 = p_out; + for(i1 = 0; i1 < N / (bsize * 2); ++i1) // loop 0->1 + { + p2 = p1; + for(i2 = 0; i2 < bsize; ++i2) // loop 0->2 + { + *p3 = *p2; // out[0] = in[0]; out[1] = in[1]; + ++p2; + ++p3; + } + p2 = p1; + for(i2 = 0; i2 < bsize; ++i2) + { + *p3 = *p2; // out[2] = in[0]; out[3] = in[1]; + ++p2; + ++p3; + } + p1 = p1 + bsize; + } + + /* Add the links with factors. */ + fact1.Real = 1.0; + fact1.Imag = 0.0; + q.Real = 0.0; + q.Imag = -2.0 * 3.141592654 * (float)(fb) / (float)(bsize * 2); + vtkImageComplexExponential(q, q); + p3 = p_out; + for(i1 = 0; i1 < N / (bsize * 2); ++i1) + { + fact = fact1; + p2 = p1; + for(i2 = 0; i2 < bsize; ++i2) + { + vtkImageComplexMultiply(fact, *p2, temp); + vtkImageComplexAdd(temp, *p3, *p3); + vtkImageComplexMultiply(q, fact, fact); + ++p2; // out[0] += in[2]; out[1] += -i*in[3]; + ++p3; + } + p2 = p1; + for(i2 = 0; i2 < bsize; ++i2) + { + vtkImageComplexMultiply(fact, *p2, temp); + vtkImageComplexAdd(temp, *p3, *p3); + vtkImageComplexMultiply(q, fact, fact); + ++p2; + ++p3; + } + p1 = p1 + bsize; + } +} + +//---------------------------------------------------------------------------- +// This function calculates one step of a FFT (using any factor). +// It is engineered for no decimation. +// N: length of arrays +// bsize: Size of FFT so far (should be scaled by n after this step) +// n: size of this steps butterfly. +// fb: forward: fb = 1, backward: fb = -1 +void vtkImageFourierFilter::ExecuteFftStepN(vtkImageComplex *p_in, + vtkImageComplex *p_out, + int N, int bsize, int n, int fb) +{ + int i0, i1, i2, i3; + vtkImageComplex *p1, *p2, *p3; + vtkImageComplex q, fact, temp; + + p3 = p_out; + for(i0 = 0; i0 < N; ++i0) + { + p3->Real = 0.0; + p3->Imag = 0.0; + ++p3; + } + + p1 = p_in; + for(i0 = 0; i0 < n; ++i0) + { + q.Real = 0.0; + q.Imag = -2.0 * 3.141592654 * (float)(i0) * (float)(fb) / (float)(bsize*n); + vtkImageComplexExponential(q, q); + p3 = p_out; + for(i1 = 0; i1 < N / (bsize * n); ++i1) + { + fact.Real = 1.0; + fact.Imag = 0.0; + for(i3 = 0; i3 < n; ++i3) + { + p2 = p1; + for(i2 = 0; i2 < bsize; ++i2) + { + vtkImageComplexMultiply(fact, *p2, temp); + vtkImageComplexAdd(temp, *p3, *p3); + vtkImageComplexMultiply(q, fact, fact); + ++p2; + ++p3; + } + } + + p1 = p1 + bsize; + } + } +} + + + +//---------------------------------------------------------------------------- +// This function calculates the whole fft (or rfft) of an array. +// The contents of the input array are changed. +// It is engineered for no decimation so input and output cannot be equal. +// (fb = 1) => fft, (fb = -1) => rfft; +void vtkImageFourierFilter::ExecuteFftForwardBackward(vtkImageComplex *in, + vtkImageComplex *out, + int N, int fb) +{ + vtkImageComplex *p1, *p2, *p3; + int block_size = 1; + int rest_size = N; + int n = 2; + int idx; + + // If this is a reverse transform (scale accordingly). + if(fb == -1) + { + p1 = in; + for(idx = 0; idx < N; ++idx) + { + p1->Real = p1->Real / (float)(N); + p1->Imag = p1->Imag / (float)(N); + ++p1; + } + } + p1 = in; + p2 = out; + while(block_size < N && n <= N) + { + if((rest_size % n) == 0) + { + // n is a prime factor, perform one "butterfly" stage of the fft. + if(n == 2) + { + this->ExecuteFftStep2(p1, p2, N, block_size, fb); + } + else + { + this->ExecuteFftStepN(p1, p2, N, block_size, n, fb); + } + block_size = block_size * n; + rest_size = rest_size / n; + // switch input and output. + p3 = p1; + p1 = p2; + p2 = p3; + } + else + { + // n is not a prime factor. increment n to see if n+1 is. + ++n; + } + } + // If the results ended up in the input, copy to output. + if(p1 != out) + { + for(n = 0; n < N; ++n) + { + *out++ = *p1++; + } + } +} + + + +//---------------------------------------------------------------------------- +// This function calculates the whole fft of an array. +// The contents of the input array are changed. +// (It is engineered for no decimation) +void vtkImageFourierFilter::ExecuteFft(vtkImageComplex *in, + vtkImageComplex *out, int N) +{ + this->ExecuteFftForwardBackward(in, out, N, 1); +} + +//---------------------------------------------------------------------------- +// This function calculates the whole fft of an array. +// The contents of the input array are changed. +// (It is engineered for no decimation) +void vtkImageFourierFilter::ExecuteRfft(vtkImageComplex *in, + vtkImageComplex *out, int N) +{ + this->ExecuteFftForwardBackward(in, out, N, -1); +} + + diff --git a/Imaging/vtkImageFourierFilter.h b/Imaging/vtkImageFourierFilter.h new file mode 100644 index 0000000..3ebb179 --- /dev/null +++ b/Imaging/vtkImageFourierFilter.h @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageFourierFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageFourierFilter - Superclass that implements complex numbers. +// .SECTION Description +// vtkImageFourierFilter is a class of filters that use complex numbers +// this superclass is a container for methods that manipulate these structure +// including fast Fourier transforms. Complex numbers may become a class. +// This should really be a helper class. +#ifndef __vtkImageFourierFilter_h +#define __vtkImageFourierFilter_h + + +#include "vtkImageDecomposeFilter.h" + + +//BTX +/******************************************************************* + COMPLEX number stuff +*******************************************************************/ + + +typedef struct{ + double Real; + double Imag; + } vtkImageComplex; + + +#define vtkImageComplexEuclidSet(C, R, I) \ + (C).Real = (R); \ + (C).Imag = (I) + +#define vtkImageComplexPolarSet(C, M, P) \ + (C).Real = (M)*cos(P); \ + (C).Imag = (M)*sin(P) + +#define vtkImageComplexPrint(C) \ + printf("(%.3f, %.3f)", (C).Real, (C).Imag) + +#define vtkImageComplexScale(cOut, S, cIn) \ + (cOut).Real = (cIn).Real * (S); \ + (cOut).Imag = (cIn).Imag * (S) + +#define vtkImageComplexConjugate(cIn, cOut) \ + (cOut).Imag = (cIn).Imag * -1.0; \ + (cOut).Real = (cIn).Real + +#define vtkImageComplexAdd(C1, C2, cOut) \ + (cOut).Real = (C1).Real + (C2).Real; \ + (cOut).Imag = (C1).Imag + (C2).Imag + +#define vtkImageComplexSubtract(C1, C2, cOut) \ + (cOut).Real = (C1).Real - (C2).Real; \ + (cOut).Imag = (C1).Imag - (C2).Imag + +#define vtkImageComplexMultiply(C1, C2, cOut) \ +{ \ + vtkImageComplex _vtkImageComplexMultiplyTemp; \ + _vtkImageComplexMultiplyTemp.Real = (C1).Real*(C2).Real-(C1).Imag*(C2).Imag;\ + _vtkImageComplexMultiplyTemp.Imag = (C1).Real*(C2).Imag+(C1).Imag*(C2).Real;\ + cOut = _vtkImageComplexMultiplyTemp; \ +} + +// This macro calculates exp(cIn) and puts the result in cOut +#define vtkImageComplexExponential(cIn, cOut) \ +{ \ + double tmp = exp(cIn.Real); \ + cOut.Real = tmp * cos(cIn.Imag); \ + cOut.Imag = tmp * sin(cIn.Imag); \ +} + +/******************* End of COMPLEX number stuff ********************/ +//ETX + +class VTK_IMAGING_EXPORT vtkImageFourierFilter : public vtkImageDecomposeFilter +{ +public: + vtkTypeRevisionMacro(vtkImageFourierFilter,vtkImageDecomposeFilter); + + + // public for templated functions of this object + //BTX + + // Description: + // This function calculates the whole fft of an array. + // The contents of the input array are changed. + // (It is engineered for no decimation) + void ExecuteFft(vtkImageComplex *in, vtkImageComplex *out, int N); + + + // Description: + // This function calculates the whole fft of an array. + // The contents of the input array are changed. + // (It is engineered for no decimation) + void ExecuteRfft(vtkImageComplex *in, vtkImageComplex *out, int N); + + //ETX + +protected: + vtkImageFourierFilter() {}; + ~vtkImageFourierFilter() {}; + + //BTX + void ExecuteFftStep2(vtkImageComplex *p_in, vtkImageComplex *p_out, + int N, int bsize, int fb); + void ExecuteFftStepN(vtkImageComplex *p_in, vtkImageComplex *p_out, + int N, int bsize, int n, int fb); + void ExecuteFftForwardBackward(vtkImageComplex *in, vtkImageComplex *out, + int N, int fb); + //ETX +private: + vtkImageFourierFilter(const vtkImageFourierFilter&); // Not implemented. + void operator=(const vtkImageFourierFilter&); // Not implemented. +}; + + + +#endif + + diff --git a/Imaging/vtkImageGaussianSmooth.cxx b/Imaging/vtkImageGaussianSmooth.cxx new file mode 100644 index 0000000..150b575 --- /dev/null +++ b/Imaging/vtkImageGaussianSmooth.cxx @@ -0,0 +1,466 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGaussianSmooth.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageGaussianSmooth.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageGaussianSmooth, "$Revision: 1.46 $"); +vtkStandardNewMacro(vtkImageGaussianSmooth); + +//---------------------------------------------------------------------------- +vtkImageGaussianSmooth::vtkImageGaussianSmooth() +{ + this->Dimensionality = 3; // note: this overrides Standard deviation. + this->StandardDeviations[0] = 2.0; + this->StandardDeviations[1] = 2.0; + this->StandardDeviations[2] = 2.0; + this->RadiusFactors[0] = 1.5; + this->RadiusFactors[1] = 1.5; + this->RadiusFactors[2] = 1.5; +} + +//---------------------------------------------------------------------------- +vtkImageGaussianSmooth::~vtkImageGaussianSmooth() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageGaussianSmooth::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + // int idx; + + //os << indent << "BoundaryRescale: " << this->BoundaryRescale << "\n"; + + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; + + os << indent << "RadiusFactors: ( " + << this->RadiusFactors[0] << ", " + << this->RadiusFactors[1] << ", " + << this->RadiusFactors[2] << " )\n"; + + os << indent << "StandardDeviations: ( " + << this->StandardDeviations[0] << ", " + << this->StandardDeviations[1] << ", " + << this->StandardDeviations[2] << " )\n"; +} + +//---------------------------------------------------------------------------- +void vtkImageGaussianSmooth::ComputeKernel(double *kernel, int min, int max, + double std) +{ + int x; + double sum; + + // handle special case + if (std == 0.0) + { + kernel[0] = 1.0; + return; + } + + // fill in kernel + sum = 0.0; + for (x = min; x <= max; ++x) + { + sum += kernel[x-min] = + exp(- ((double)(x*x)) / (std * std * 2.0)); + } + + // normalize + for (x = min; x <= max; ++x) + { + kernel[x-min] /= sum; + } +} + +//---------------------------------------------------------------------------- +int vtkImageGaussianSmooth::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int wholeExtent[6], inExt[6]; + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt); + + // Expand filtered axes + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + + this->InternalRequestUpdateExtent(inExt, wholeExtent); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageGaussianSmooth::InternalRequestUpdateExtent(int *inExt, + int *wholeExtent) +{ + int idx, radius; + + // Expand filtered axes + for (idx = 0; idx < this->Dimensionality; ++idx) + { + radius = (int)(this->StandardDeviations[idx] * this->RadiusFactors[idx]); + inExt[idx*2] -= radius; + if (inExt[idx*2] < wholeExtent[idx*2]) + { + inExt[idx*2] = wholeExtent[idx*2]; + } + + inExt[idx*2+1] += radius; + if (inExt[idx*2+1] > wholeExtent[idx*2+1]) + { + inExt[idx*2+1] = wholeExtent[idx*2+1]; + } + } +} + +//---------------------------------------------------------------------------- +// For a given position along the convolution axis, this method loops over +// all other axes, and performs the convolution. Boundary conditions handled +// previously. +template +void +vtkImageGaussianSmoothExecute(vtkImageGaussianSmooth *self, int axis, + double *kernel, int kernelSize, + vtkImageData *inData, T *inPtrC, + vtkImageData *outData, int outExt[6], + T *outPtrC, int *pcycle, int target, + int *pcount, int total) +{ + int maxC, max0, max1; + int idxC, idx0, idx1, idxK; + vtkIdType *inIncs, *outIncs; + vtkIdType inInc0, inInc1, inIncK, outInc0, outInc1; + T *outPtr1, *outPtr0; + T *inPtr1, *inPtr0, *inPtrK; + double *ptrK, sum; + + // avoid warnings + self = self; + max0 = max1 = inInc0 = inInc1 = outInc0 = outInc1 = 0; + + // I am counting on the fact that tight loops (component on outside) + // is more important than cache misses from shuffled access. + + // Do the correct shuffling of the axes (increments, extents) + inIncs = inData->GetIncrements(); + outIncs = outData->GetIncrements(); + inIncK = inIncs[axis]; + maxC = outData->GetNumberOfScalarComponents(); + switch (axis) + { + case 0: + inInc0 = inIncs[1]; inInc1 = inIncs[2]; + outInc0 = outIncs[1]; outInc1 = outIncs[2]; + max0 = outExt[3] - outExt[2] + 1; max1 = outExt[5] - outExt[4] + 1; + break; + case 1: + inInc0 = inIncs[0]; inInc1 = inIncs[2]; + outInc0 = outIncs[0]; outInc1 = outIncs[2]; + max0 = outExt[1] - outExt[0] + 1; max1 = outExt[5] - outExt[4] + 1; + break; + case 2: + inInc0 = inIncs[0]; inInc1 = inIncs[1]; + outInc0 = outIncs[0]; outInc1 = outIncs[1]; + max0 = outExt[1] - outExt[0] + 1; max1 = outExt[3] - outExt[2] + 1; + break; + } + + for (idxC = 0; idxC < maxC; ++idxC) + { + inPtr1 = inPtrC; + outPtr1 = outPtrC; + for (idx1 = 0; !self->AbortExecute && idx1 < max1; ++idx1) + { + inPtr0 = inPtr1; + outPtr0 = outPtr1; + for (idx0 = 0; idx0 < max0; ++idx0) + { + inPtrK = inPtr0; + ptrK = kernel; + sum = 0.0; + // too bad this short loop has to be the inner most loop + for (idxK = 0; idxK < kernelSize; ++idxK) + { + sum += *ptrK * (double)(*inPtrK); + ++ptrK; + inPtrK += inIncK; + } + *outPtr0 = (T)(sum); + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + // we finished a row ... do we update ??? + if (total) + { // yes this is the main thread + *pcycle += max0; + if (*pcycle > target) + { // yes + *pcycle -= target; + *pcount += target; + self->UpdateProgress((double)(*pcount) / (double)total); + //fprintf(stderr, "count: %d, total: %d, progress: %f\n", + //*pcount, total, (double)(*pcount) / (double)total); + } + } + } + + ++inPtrC; + ++outPtrC; + } +} + +//---------------------------------------------------------------------------- +template +size_t vtkImageGaussianSmoothGetTypeSize(T*) +{ + return sizeof(T); +} + +//---------------------------------------------------------------------------- +// This method convolves over one axis. It loops over the convolved axis, +// and handles boundary conditions. +void vtkImageGaussianSmooth::ExecuteAxis(int axis, + vtkImageData *inData, int inExt[6], + vtkImageData *outData, int outExt[6], + int *pcycle, int target, + int *pcount, int total, + vtkInformation *inInfo) +{ + int idxA, max; + int wholeExtent[6], wholeMax, wholeMin; + double *kernel; + // previousClip and currentClip rembers that the previous was not clipped + // keeps from recomputing kernels for center pixels. + int kernelSize = 0; + int kernelLeftClip, kernelRightClip; + int previousClipped, currentClipped; + int radius, size; + void *inPtr; + void *outPtr; + int coords[3]; + vtkIdType *outIncs, outIncA; + + // Get the correct starting pointer of the output + outPtr = outData->GetScalarPointerForExtent(outExt); + outIncs = outData->GetIncrements(); + outIncA = outIncs[axis]; + + // trick to account for the scalar type of the output(used to be only float) + switch (outData->GetScalarType()) + { + vtkTemplateMacro( + outIncA *= vtkImageGaussianSmoothGetTypeSize(static_cast(0)) + ); + default: + vtkErrorMacro("Unknown scalar type"); + return; + } + + // Determine default starting position of input + coords[0] = inExt[0]; + coords[1] = inExt[2]; + coords[2] = inExt[4]; + + // get whole extent for boundary checking ... + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + wholeMin = wholeExtent[axis*2]; + wholeMax = wholeExtent[axis*2+1]; + + // allocate memory for the kernel + radius = (int)(this->StandardDeviations[axis] * this->RadiusFactors[axis]); + size = 2*radius + 1; + kernel = new double[size]; + + // loop over the convolution axis + previousClipped = currentClipped = 1; + max = outExt[axis*2+1]; + for (idxA = outExt[axis*2]; idxA <= max; ++idxA) + { + // left boundary condition + coords[axis] = idxA - radius; + kernelLeftClip = wholeMin - coords[axis]; + if (kernelLeftClip > 0) + { // front of kernel is cut off ("kernelStart" samples) + coords[axis] += kernelLeftClip; + } + else + { + kernelLeftClip = 0; + } + // Right boundary condition + kernelRightClip = (idxA + radius) - wholeMax; + if (kernelRightClip < 0) + { + kernelRightClip = 0; + } + + // We can only use previous kernel if it is not clipped and new + // kernel is also not clipped. + currentClipped = kernelLeftClip + kernelRightClip; + if (currentClipped || previousClipped) + { + this->ComputeKernel(kernel, -radius+kernelLeftClip, + radius-kernelRightClip, + (double)(this->StandardDeviations[axis])); + kernelSize = size - kernelLeftClip - kernelRightClip; + } + previousClipped = currentClipped; + + /* now do the convolution on the rest of the axes */ + inPtr = inData->GetScalarPointer(coords); + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageGaussianSmoothExecute(this, axis, kernel, kernelSize, + inData, (VTK_TT*)(inPtr), + outData, outExt, (VTK_TT*)(outPtr), + pcycle, target, pcount, total) + ); + default: + vtkErrorMacro("Unknown scalar type"); + return; + } + outPtr = (void *)((unsigned char *)outPtr + outIncA); + } + + // get rid of temporary kernel + delete [] kernel; +} + +//---------------------------------------------------------------------------- +// This method decomposes the gaussian and smooths along each axis. +void vtkImageGaussianSmooth::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6]; + int target, count, total, cycle; + + // for feed back, determine line target to get 50 progress update + // update is called every target lines. Progress is computed from + // the number of pixels processed so far. + count = 0; target = 0; total = 0; cycle = 0; + if (id == 0) + { + // determine the number of pixels. + total = this->Dimensionality * (outExt[1] - outExt[0] + 1) + * (outExt[3] - outExt[2] + 1) * (outExt[5] - outExt[4] + 1) + * inData[0][0]->GetNumberOfScalarComponents(); + // pixels per update (50 updates) + target = total / 50; + } + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro("Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + // Decompose + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int wholeExt[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt); + this->InternalRequestUpdateExtent(inExt, wholeExt); + + switch (this->Dimensionality) + { + case 1: + this->ExecuteAxis(0, inData[0][0], inExt, outData[0], outExt, + &cycle, target, &count, total, inInfo); + break; + case 2: + int tempExt[6]; + vtkImageData *tempData; + // compute intermediate extent + tempExt[0] = inExt[0]; tempExt[1] = inExt[1]; + tempExt[2] = outExt[2]; tempExt[3] = outExt[3]; + tempExt[4] = inExt[4]; tempExt[5] = inExt[5]; + // create a temp data for intermediate results + tempData = vtkImageData::New(); + tempData->SetExtent(tempExt); + tempData->SetNumberOfScalarComponents( + inData[0][0]->GetNumberOfScalarComponents()); + tempData->SetScalarType(inData[0][0]->GetScalarType()); + this->ExecuteAxis(1, inData[0][0], inExt, tempData, tempExt, + &cycle, target, &count, total, inInfo); + this->ExecuteAxis(0, tempData, tempExt, outData[0], outExt, + &cycle, target, &count, total, inInfo); + // release temporary data + tempData->Delete(); + break; + case 3: + // we do z first because it is most likely smallest + int temp0Ext[6], temp1Ext[6]; + vtkImageData *temp0Data, *temp1Data; + // compute intermediate extents + temp0Ext[0] = inExt[0]; temp0Ext[1] = inExt[1]; + temp0Ext[2] = inExt[2]; temp0Ext[3] = inExt[3]; + temp0Ext[4] = outExt[4]; temp0Ext[5] = outExt[5]; + + temp1Ext[0] = inExt[0]; temp1Ext[1] = inExt[1]; + temp1Ext[2] = outExt[2]; temp1Ext[3] = outExt[3]; + temp1Ext[4] = outExt[4]; temp1Ext[5] = outExt[5]; + + // create a temp data for intermediate results + temp0Data = vtkImageData::New(); + temp0Data->SetExtent(temp0Ext); + temp0Data->SetNumberOfScalarComponents( + inData[0][0]->GetNumberOfScalarComponents()); + temp0Data->SetScalarType(inData[0][0]->GetScalarType()); + + temp1Data = vtkImageData::New(); + temp1Data->SetExtent(temp1Ext); + temp1Data->SetNumberOfScalarComponents( + inData[0][0]->GetNumberOfScalarComponents()); + temp1Data->SetScalarType(inData[0][0]->GetScalarType()); + this->ExecuteAxis(2, inData[0][0], inExt, temp0Data, temp0Ext, + &cycle, target, &count, total, inInfo); + this->ExecuteAxis(1, temp0Data, temp0Ext, temp1Data, temp1Ext, + &cycle, target, &count, total, inInfo); + temp0Data->Delete(); + this->ExecuteAxis(0, temp1Data, temp1Ext, outData[0], outExt, + &cycle, target, &count, total, inInfo); + temp1Data->Delete(); + break; + } +} diff --git a/Imaging/vtkImageGaussianSmooth.h b/Imaging/vtkImageGaussianSmooth.h new file mode 100644 index 0000000..c7335da --- /dev/null +++ b/Imaging/vtkImageGaussianSmooth.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGaussianSmooth.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageGaussianSmooth - Performs a gaussian convolution. +// .SECTION Description +// vtkImageGaussianSmooth implements a convolution of the input image +// with a gaussian. Supports from one to three dimensional convolutions. + +#ifndef __vtkImageGaussianSmooth_h +#define __vtkImageGaussianSmooth_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageGaussianSmooth : public vtkThreadedImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImageGaussianSmooth,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates an instance of vtkImageGaussianSmooth with the following + // defaults: Dimensionality 3, StandardDeviations( 2, 2, 2), + // Radius Factors ( 1.5, 1.5, 1.5) + static vtkImageGaussianSmooth *New(); + + + // Description: + // Sets/Gets the Standard deviation of the gaussian in pixel units. + vtkSetVector3Macro(StandardDeviations, double); + void SetStandardDeviation(double std) + {this->SetStandardDeviations(std,std,std);} + void SetStandardDeviations(double a,double b) + {this->SetStandardDeviations(a,b,0.0);} + vtkGetVector3Macro(StandardDeviations, double); + + // Description: + // Sets/Gets the Standard deviation of the gaussian in pixel units. + // These methods are provided for compatibility with old scripts + void SetStandardDeviation(double a,double b) + {this->SetStandardDeviations(a,b,0.0);} + void SetStandardDeviation(double a,double b,double c) + {this->SetStandardDeviations(a,b,c);} + + // Description: + // Sets/Gets the Radius Factors of the gaussian (no unit). + // The radius factors determine how far out the gaussian kernel will + // go before being clamped to zero. + vtkSetVector3Macro(RadiusFactors, double); + void SetRadiusFactors(double f, double f2) { + this->SetRadiusFactors(f,f2,1.5);} + void SetRadiusFactor(double f) {this->SetRadiusFactors(f, f, f);} + vtkGetVector3Macro(RadiusFactors, double); + + // Description: + // Set/Get the dimensionality of this filter. This determines whether + // a one, two, or three dimensional gaussian is performed. + vtkSetMacro(Dimensionality, int); + vtkGetMacro(Dimensionality, int); + +protected: + vtkImageGaussianSmooth(); + ~vtkImageGaussianSmooth(); + + int Dimensionality; + double StandardDeviations[3]; + double RadiusFactors[3]; + + void ComputeKernel(double *kernel, int min, int max, double std); + virtual int RequestUpdateExtent (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void InternalRequestUpdateExtent(int *, int*); + void ExecuteAxis(int axis, vtkImageData *inData, int inExt[6], + vtkImageData *outData, int outExt[6], + int *pcycle, int target, int *pcount, int total, + vtkInformation *inInfo); + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); + +private: + vtkImageGaussianSmooth(const vtkImageGaussianSmooth&); // Not implemented. + void operator=(const vtkImageGaussianSmooth&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageGaussianSource.cxx b/Imaging/vtkImageGaussianSource.cxx new file mode 100644 index 0000000..a8a6657 --- /dev/null +++ b/Imaging/vtkImageGaussianSource.cxx @@ -0,0 +1,191 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGaussianSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageGaussianSource.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageGaussianSource, "$Revision: 1.32.6.1 $"); +vtkStandardNewMacro(vtkImageGaussianSource); + +//---------------------------------------------------------------------------- +vtkImageGaussianSource::vtkImageGaussianSource() +{ + this->SetNumberOfInputPorts(0); + this->Maximum = 1.0; + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; + + this->WholeExtent[0] = 0; this->WholeExtent[1] = 255; + this->WholeExtent[2] = 0; this->WholeExtent[3] = 255; + this->WholeExtent[4] = 0; this->WholeExtent[5] = 0; + this->StandardDeviation = 100.0; +} + + +//---------------------------------------------------------------------------- +void vtkImageGaussianSource::SetWholeExtent(int xMin, int xMax, + int yMin, int yMax, + int zMin, int zMax) +{ + int modified = 0; + + if (this->WholeExtent[0] != xMin) + { + modified = 1; + this->WholeExtent[0] = xMin ; + } + if (this->WholeExtent[1] != xMax) + { + modified = 1; + this->WholeExtent[1] = xMax ; + } + if (this->WholeExtent[2] != yMin) + { + modified = 1; + this->WholeExtent[2] = yMin ; + } + if (this->WholeExtent[3] != yMax) + { + modified = 1; + this->WholeExtent[3] = yMax ; + } + if (this->WholeExtent[4] != zMin) + { + modified = 1; + this->WholeExtent[4] = zMin ; + } + if (this->WholeExtent[5] != zMax) + { + modified = 1; + this->WholeExtent[5] = zMax ; + } + if (modified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkImageGaussianSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent,6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 1); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageGaussianSource::RequestData( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* outputVector) +{ + double *outPtr; + int idxX, idxY, idxZ; + int maxX, maxY, maxZ; + vtkIdType outIncX, outIncY, outIncZ; + int *outExt; + double sum; + double yContrib, zContrib; + double temp, temp2; + unsigned long count = 0; + unsigned long target; + + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *data = this->AllocateOutputData(output); + + if (data->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Execute: This source only outputs doubles"); + } + + outExt = data->GetExtent(); + + // find the region to loop over + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + // Get increments to march through data + data->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + outPtr = (double *)data->GetScalarPointer(outExt[0],outExt[2],outExt[4]); + + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Loop through ouput pixels + temp2 = 1.0 / (2.0 * this->StandardDeviation * this->StandardDeviation); + + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + zContrib = this->Center[2] - (idxZ + outExt[4]); + zContrib = zContrib*zContrib; + for (idxY = 0; !this->AbortExecute && idxY <= maxY; idxY++) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + yContrib = this->Center[1] - (idxY + outExt[2]); + yContrib = yContrib*yContrib; + for (idxX = 0; idxX <= maxX; idxX++) + { + // Pixel operation + sum = zContrib + yContrib; + temp = this->Center[0] - (idxX + outExt[0]); + sum = sum + (temp * temp); + *outPtr = this->Maximum * exp(-sum * temp2); + outPtr++; + } + outPtr += outIncY; + } + outPtr += outIncZ; + } + + return 1; +} + +void vtkImageGaussianSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum: " << this->Maximum << "\n"; + + os << indent << "StandardDeviation: " << this->StandardDeviation << "\n"; + + os << indent << "Center: ( " + << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << " )\n"; + +} + + diff --git a/Imaging/vtkImageGaussianSource.h b/Imaging/vtkImageGaussianSource.h new file mode 100644 index 0000000..a9bc111 --- /dev/null +++ b/Imaging/vtkImageGaussianSource.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGaussianSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageGaussianSource - Create an image with Gaussian pixel values. +// .SECTION Description +// vtkImageGaussianSource just produces images with pixel values determined +// by a Gaussian. + + +#ifndef __vtkImageGaussianSource_h +#define __vtkImageGaussianSource_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageGaussianSource : public vtkImageAlgorithm +{ +public: + static vtkImageGaussianSource *New(); + vtkTypeRevisionMacro(vtkImageGaussianSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the extent of the whole output image. + void SetWholeExtent(int xMinx, int xMax, int yMin, int yMax, + int zMin, int zMax); + + // Description: + // Set/Get the center of the Gaussian. + vtkSetVector3Macro(Center, double); + vtkGetVector3Macro(Center, double); + + // Description: + // Set/Get the Maximum value of the gaussian + vtkSetMacro(Maximum, double); + vtkGetMacro(Maximum, double); + + // Description: + // Set/Get the standard deviation of the gaussian + vtkSetMacro(StandardDeviation, double); + vtkGetMacro(StandardDeviation, double); + +protected: + vtkImageGaussianSource(); + ~vtkImageGaussianSource() {}; + + double StandardDeviation; + int WholeExtent[6]; + double Center[3]; + double Maximum; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); +private: + vtkImageGaussianSource(const vtkImageGaussianSource&); // Not implemented. + void operator=(const vtkImageGaussianSource&); // Not implemented. +}; + + +#endif diff --git a/Imaging/vtkImageGradient.cxx b/Imaging/vtkImageGradient.cxx new file mode 100644 index 0000000..c717637 --- /dev/null +++ b/Imaging/vtkImageGradient.cxx @@ -0,0 +1,285 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGradient.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageGradient.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageGradient, "$Revision: 1.54.4.1 $"); +vtkStandardNewMacro(vtkImageGradient); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageGradient fitler. +vtkImageGradient::vtkImageGradient() +{ + this->HandleBoundaries = 1; + this->Dimensionality = 2; +} + +//---------------------------------------------------------------------------- +void vtkImageGradient::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "HandleBoundaries: " << this->HandleBoundaries << "\n"; + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkImageGradient::RequestInformation(vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // Get input and output pipeline information. + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + + // Get the input whole extent. + int extent[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + + // Shrink output image extent by one pixel if not handling boundaries. + if(!this->HandleBoundaries) + { + for(int idx = 0; idx < this->Dimensionality; ++idx) + { + extent[idx*2] += 1; + extent[idx*2 + 1] -= 1; + } + } + + // Store the new whole extent for the output. + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6); + + // Set the number of point data componets to the number of + // components in the gradient vector. + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, + this->Dimensionality); + + return 1; +} + +//---------------------------------------------------------------------------- +// This method computes the input extent necessary to generate the output. +int vtkImageGradient::RequestUpdateExtent(vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // Get input and output pipeline information. + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + + // Get the input whole extent. + int wholeExtent[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + + // Get the requested update extent from the output. + int inUExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inUExt); + + // In order to do central differencing we need one more layer of + // input pixels than we are producing output pixels. + for(int idx = 0; idx < this->Dimensionality; ++idx) + { + inUExt[idx*2] -= 1; + inUExt[idx*2+1] += 1; + + // If handling boundaries instead of shrinking the image then we + // must clip the needed extent within the whole extent of the + // input. + if (this->HandleBoundaries) + { + if (inUExt[idx*2] < wholeExtent[idx*2]) + { + inUExt[idx*2] = wholeExtent[idx*2]; + } + if (inUExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + inUExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } + } + + // Store the update extent needed from the intput. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inUExt, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageGradientExecute(vtkImageGradient *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, double *outPtr, + int outExt[6], int id) +{ + int idxX, idxY, idxZ; + int maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int axesNum; + int *inExt = inData->GetExtent(); + int *wholeExtent; + vtkIdType *inIncs; + double r[3], d; + int useZMin, useZMax, useYMin, useYMax, useXMin, useXMax; + + // find the region to loop over + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get the dimensionality of the gradient. + axesNum = self->GetDimensionality(); + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // The data spacing is important for computing the gradient. + // central differences (2 * ratio). + // Negative because below we have (min - max) for dx ... + inData->GetSpacing(r); + r[0] = -0.5 / r[0]; + r[1] = -0.5 / r[1]; + r[2] = -0.5 / r[2]; + + // get some other info we need + inIncs = inData->GetIncrements(); + wholeExtent = inData->GetExtent(); + + // Move the pointer to the correct starting position. + inPtr += (outExt[0]-inExt[0])*inIncs[0] + + (outExt[2]-inExt[2])*inIncs[1] + + (outExt[4]-inExt[4])*inIncs[2]; + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + useZMin = ((idxZ + outExt[4]) <= wholeExtent[4]) ? 0 : -inIncs[2]; + useZMax = ((idxZ + outExt[4]) >= wholeExtent[5]) ? 0 : inIncs[2]; + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + useYMin = ((idxY + outExt[2]) <= wholeExtent[2]) ? 0 : -inIncs[1]; + useYMax = ((idxY + outExt[2]) >= wholeExtent[3]) ? 0 : inIncs[1]; + for (idxX = 0; idxX <= maxX; idxX++) + { + useXMin = ((idxX + outExt[0]) <= wholeExtent[0]) ? 0 : -inIncs[0]; + useXMax = ((idxX + outExt[0]) >= wholeExtent[1]) ? 0 : inIncs[0]; + + // do X axis + d = (double)(inPtr[useXMin]); + d -= (double)(inPtr[useXMax]); + d *= r[0]; // multiply by the data spacing + *outPtr = d; + outPtr++; + + // do y axis + d = (double)(inPtr[useYMin]); + d -= (double)(inPtr[useYMax]); + d *= r[1]; // multiply by the data spacing + *outPtr = d; + outPtr++; + if (axesNum == 3) + { + // do z axis + d = (double)(inPtr[useZMin]); + d -= (double)(inPtr[useZMax]); + d *= r[2]; // multiply by the data spacing + *outPtr = d; + outPtr++; + } + inPtr++; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. This method does handle +// boundary conditions. +void vtkImageGradient::ThreadedRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*, + vtkImageData*** inData, + vtkImageData** outData, + int outExt[6], + int threadId) +{ + // Get the input and output data objects. + vtkImageData* input = inData[0][0]; + vtkImageData* output = outData[0]; + + // The ouptut scalar type must be double to store proper gradients. + if(output->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Execute: output ScalarType is " + << output->GetScalarType() << "but must be double."); + return; + } + + // Gradient makes sense only with one input component. This is not + // a Jacobian filter. + if(input->GetNumberOfScalarComponents() != 1) + { + vtkErrorMacro( + "Execute: input has more than one component. " + "The input to gradient should be a single component image. " + "Think about it. If you insist on using a color image then " + "run it though RGBToHSV then ExtractComponents to get the V " + "components. That's probably what you want anyhow."); + return; + } + + // Dispatch computation for the input scalar type. + void* inPtr = input->GetScalarPointer(); + double* outPtr = (double*)(output->GetScalarPointerForExtent(outExt)); + switch(input->GetScalarType()) + { + vtkTemplateMacro( + vtkImageGradientExecute(this, input, static_cast(inPtr), + output, outPtr, outExt, threadId) + ); + default: + vtkErrorMacro("Execute: Unknown ScalarType " << input->GetScalarType()); + return; + } +} diff --git a/Imaging/vtkImageGradient.h b/Imaging/vtkImageGradient.h new file mode 100644 index 0000000..70125dd --- /dev/null +++ b/Imaging/vtkImageGradient.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGradient.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageGradient - Computes the gradient vector. +// .SECTION Description +// vtkImageGradient computes the gradient vector of an image. The +// vector results are stored as scalar components. The Dimensionality +// determines whether to perform a 2d or 3d gradient. The default is +// two dimensional XY gradient. OutputScalarType is always +// double. Gradient is computed using central differences. + +#ifndef __vtkImageGradient_h +#define __vtkImageGradient_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageGradient : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageGradient *New(); + vtkTypeRevisionMacro(vtkImageGradient,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Determines how the input is interpreted (set of 2d slices ...) + vtkSetClampMacro(Dimensionality,int,2,3); + vtkGetMacro(Dimensionality,int); + + // Description: + // Get/Set whether to handle boundaries. If enabled, boundary + // pixels are treated as duplicated so that central differencing + // works for the boundary pixels. If disabled, the output whole + // extent of the image is reduced by one pixel. + vtkSetMacro(HandleBoundaries, int); + vtkGetMacro(HandleBoundaries, int); + vtkBooleanMacro(HandleBoundaries, int); + +protected: + vtkImageGradient(); + ~vtkImageGradient() {}; + + int HandleBoundaries; + int Dimensionality; + + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + void ThreadedRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*, + vtkImageData*** inData, + vtkImageData** outData, + int outExt[6], + int threadId); +private: + vtkImageGradient(const vtkImageGradient&); // Not implemented. + void operator=(const vtkImageGradient&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageGradientMagnitude.cxx b/Imaging/vtkImageGradientMagnitude.cxx new file mode 100644 index 0000000..9ca6a82 --- /dev/null +++ b/Imaging/vtkImageGradientMagnitude.cxx @@ -0,0 +1,284 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGradientMagnitude.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageGradientMagnitude.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkImageGradientMagnitude, "$Revision: 1.44 $"); +vtkStandardNewMacro(vtkImageGradientMagnitude); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageGradientMagnitude fitler. +vtkImageGradientMagnitude::vtkImageGradientMagnitude() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + this->Dimensionality = 2; + this->HandleBoundaries = 1; +} + + +//---------------------------------------------------------------------------- +void vtkImageGradientMagnitude::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "HandleBoundaries: " << this->HandleBoundaries << "\n"; + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; +} + +//---------------------------------------------------------------------------- +// This method is passed a region that holds the image extent of this filters +// input, and changes the region to hold the image extent of this filters +// output. +int vtkImageGradientMagnitude::RequestInformation ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + int extent[6]; + int idx; + + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + + // invalid setting, it has not been set, so default to whole Extent + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + extent); + + if ( ! this->HandleBoundaries) + { + // shrink output image extent. + for (idx = 0; idx < this->Dimensionality; ++idx) + { + extent[idx*2] += 1; + extent[idx*2 + 1] -= 1; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + extent, 6); + + return 1; +} + + +//---------------------------------------------------------------------------- +// This method computes the input extent necessary to generate the output. +int vtkImageGradientMagnitude::RequestUpdateExtent ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + int wholeExtent[6]; + int idx; + + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // invalid setting, it has not been set, so default to whole Extent + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + wholeExtent); + int inUExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inUExt); + + // grow input whole extent. + for (idx = 0; idx < this->Dimensionality; ++idx) + { + inUExt[idx*2] -= 1; + inUExt[idx*2+1] += 1; + if (this->HandleBoundaries) + { + // we must clip extent with whole extent is we hanlde boundaries. + if (inUExt[idx*2] < wholeExtent[idx*2]) + { + inUExt[idx*2] = wholeExtent[idx*2]; + } + if (inUExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + inUExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inUExt, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageGradientMagnitudeExecute(vtkImageGradientMagnitude *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int maxC, maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int axesNum; + int *wholeExtent; + vtkIdType *inIncs; + double r[3], d, sum; + int useZMin, useZMax, useYMin, useYMax, useXMin, useXMax; + int *inExt = inData->GetExtent(); + + // find the region to loop over + maxC = outData->GetNumberOfScalarComponents(); + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get the dimensionality of the gradient. + axesNum = self->GetDimensionality(); + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // The data spacing is important for computing the gradient. + inData->GetSpacing(r); + r[0] = 0.5 / r[0]; + r[1] = 0.5 / r[1]; + r[2] = 0.5 / r[2]; + + // get some other info we need + inIncs = inData->GetIncrements(); + wholeExtent = inData->GetExtent(); + + // Move the starting pointer to the correct location. + inPtr += (outExt[0]-inExt[0])*inIncs[0] + + (outExt[2]-inExt[2])*inIncs[1] + + (outExt[4]-inExt[4])*inIncs[2]; + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + useZMin = ((idxZ + outExt[4]) <= wholeExtent[4]) ? 0 : -inIncs[2]; + useZMax = ((idxZ + outExt[4]) >= wholeExtent[5]) ? 0 : inIncs[2]; + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + useYMin = ((idxY + outExt[2]) <= wholeExtent[2]) ? 0 : -inIncs[1]; + useYMax = ((idxY + outExt[2]) >= wholeExtent[3]) ? 0 : inIncs[1]; + for (idxX = 0; idxX <= maxX; idxX++) + { + useXMin = ((idxX + outExt[0]) <= wholeExtent[0]) ? 0 : -inIncs[0]; + useXMax = ((idxX + outExt[0]) >= wholeExtent[1]) ? 0 : inIncs[0]; + for (idxC = 0; idxC < maxC; idxC++) + { + // do X axis + d = (double)(inPtr[useXMin]); + d -= (double)(inPtr[useXMax]); + d *= r[0]; // multiply by the data spacing + sum = d * d; + // do y axis + d = (double)(inPtr[useYMin]); + d -= (double)(inPtr[useYMax]); + d *= r[1]; // multiply by the data spacing + sum += (d * d); + if (axesNum == 3) + { + // do z axis + d = (double)(inPtr[useZMin]); + d -= (double)(inPtr[useZMax]); + d *= r[2]; // multiply by the data spacing + sum += (d * d); + } + *outPtr = (T)(sqrt(sum)); + outPtr++; + inPtr++; + } + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The output data +// must match input type. This method does handle boundary conditions. +void vtkImageGradientMagnitude::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + void *inPtr; + void *outPtr = outData->GetScalarPointerForExtent(outExt); + inPtr = inData->GetScalarPointer(); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input data type, " + << inData->GetScalarType() + << ", must match out ScalarType " + << outData->GetScalarType()); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageGradientMagnitudeExecute(this, + inData, (VTK_TT *)(inPtr), outData, + (VTK_TT *)(outPtr), outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + + + + + + + + + + + + + diff --git a/Imaging/vtkImageGradientMagnitude.h b/Imaging/vtkImageGradientMagnitude.h new file mode 100644 index 0000000..8a32ddf --- /dev/null +++ b/Imaging/vtkImageGradientMagnitude.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGradientMagnitude.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageGradientMagnitude - Computes magnitude of the gradient. + +// .SECTION Description +// vtkImageGradientMagnitude computes the gradient magnitude of an image. +// Setting the dimensionality determines whether the gradient is computed on +// 2D images, or 3D volumes. The default is two dimensional XY images. + +// .SECTION See Also +// vtkImageGradient vtkImageMagnitude + +#ifndef __vtkImageGradientMagnitude_h +#define __vtkImageGradientMagnitude_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageGradientMagnitude : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageGradientMagnitude *New(); + vtkTypeRevisionMacro(vtkImageGradientMagnitude,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // If "HandleBoundariesOn" then boundary pixels are duplicated + // So central differences can get values. + vtkSetMacro(HandleBoundaries, int); + vtkGetMacro(HandleBoundaries, int); + vtkBooleanMacro(HandleBoundaries, int); + + // Description: + // Determines how the input is interpreted (set of 2d slices ...) + vtkSetClampMacro(Dimensionality,int,2,3); + vtkGetMacro(Dimensionality,int); + +protected: + vtkImageGradientMagnitude(); + ~vtkImageGradientMagnitude() {}; + + int HandleBoundaries; + int Dimensionality; + + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int extent[6], int id); +private: + vtkImageGradientMagnitude(const vtkImageGradientMagnitude&); // Not implemented. + void operator=(const vtkImageGradientMagnitude&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageGridSource.cxx b/Imaging/vtkImageGridSource.cxx new file mode 100644 index 0000000..fcbda75 --- /dev/null +++ b/Imaging/vtkImageGridSource.cxx @@ -0,0 +1,196 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGridSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageGridSource.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageGridSource, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkImageGridSource); + +//---------------------------------------------------------------------------- +vtkImageGridSource::vtkImageGridSource() +{ + this->DataExtent[0] = 0; this->DataExtent[1] = 255; + this->DataExtent[2] = 0; this->DataExtent[3] = 255; + this->DataExtent[4] = 0; this->DataExtent[5] = 0; + + this->GridSpacing[0] = 10; + this->GridSpacing[1] = 10; + this->GridSpacing[2] = 0; + + this->GridOrigin[0] = 0; + this->GridOrigin[1] = 0; + this->GridOrigin[2] = 0; + + this->DataScalarType = VTK_FLOAT; + + this->DataOrigin[0] = this->DataOrigin[1] = this->DataOrigin[2] = 0.0; + this->DataSpacing[0] = this->DataSpacing[1] = this->DataSpacing[2] = 1.0; + + this->LineValue = 1.0; + this->FillValue = 0.0; + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +int vtkImageGridSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkDataObject::SPACING(),this->DataSpacing,3); + outInfo->Set(vtkDataObject::ORIGIN(),this->DataOrigin,3); + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->DataExtent,6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, 1); + return 1; +} + +//---------------------------------------------------------------------------- +template +void vtkImageGridSourceExecute(vtkImageGridSource *self, + vtkImageData *data, T *outPtr, + int outExt[6], int id) +{ + int idxX, idxY, idxZ; + int xval, yval, zval; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + + int gridSpacing[3], gridOrigin[3]; + self->GetGridSpacing(gridSpacing); + self->GetGridOrigin(gridOrigin); + + T fillValue = T(self->GetFillValue()); + T lineValue = T(self->GetLineValue()); + + // Get increments to march through data + data->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + target = (unsigned long)((outExt[5]-outExt[4]+1)* + (outExt[3]-outExt[2]+1)/50.0); + target++; + + // Loop through ouput pixel + for (idxZ = outExt[4]; idxZ <= outExt[5]; idxZ++) + { + if (gridSpacing[2]) + { + zval = (idxZ % gridSpacing[2] == gridOrigin[2]); + } + else + { + zval = 0; + } + for (idxY = outExt[2]; !self->GetAbortExecute() && idxY<=outExt[3]; idxY++) + { + if (gridSpacing[1]) + { + yval = (idxY % gridSpacing[1] == gridOrigin[1]); + } + else + { + yval = 0; + } + if (id == 0) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + if (gridSpacing[0]) + { + for (idxX = outExt[0]; idxX <= outExt[1]; idxX++) + { + xval = (idxX % gridSpacing[0] == gridOrigin[0]); + + // not very efficient, but it gets the job done + *outPtr++ = ((zval|yval|xval) ? lineValue : fillValue); + } + } + else + { + for (idxX = outExt[0]; idxX <= outExt[1]; idxX++) + { + *outPtr++ = ((zval|yval) ? lineValue : fillValue); + } + } + outPtr += outIncY; + } + outPtr += outIncZ; + } +} + +//---------------------------------------------------------------------------- +void vtkImageGridSource::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + int *outExt = data->GetExtent(); + void *outPtr = data->GetScalarPointerForExtent(outExt); + + // Call the correct templated function for the output + switch (this->GetDataScalarType()) + { + vtkTemplateMacro(vtkImageGridSourceExecute( this, data, + (VTK_TT *)(outPtr), + outExt, 0)); + default: + vtkErrorMacro(<< "Execute: Unknown data type"); + } +} + +//---------------------------------------------------------------------------- +void vtkImageGridSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "GridSpacing: (" << this->GridSpacing[0] << ", " + << this->GridSpacing[1] << ", " + << this->GridSpacing[2] << ")\n"; + os << indent << "GridOrigin: (" << this->GridOrigin[0] << ", " + << this->GridOrigin[1] << ", " + << this->GridOrigin[2] << ")\n"; + os << indent << "LineValue: " << this->LineValue << "\n"; + os << indent << "FillValue: " << this->FillValue << "\n"; + os << indent << "DataScalarType: " << + vtkImageScalarTypeNameMacro(this->DataScalarType) << "\n"; + os << indent << "DataExtent: (" << this->DataExtent[0] << ", " + << this->DataExtent[1] << ", " + << this->DataExtent[2] << ", " + << this->DataExtent[3] << ", " + << this->DataExtent[4] << ", " + << this->DataExtent[5] << ")\n"; + os << indent << "DataSpacing: (" << this->DataSpacing[0] << ", " + << this->DataSpacing[1] << ", " + << this->DataSpacing[2] << ")\n"; + os << indent << "DataOrigin: (" << this->DataOrigin[0] << ", " + << this->DataOrigin[1] << ", " + << this->DataOrigin[2] << ")\n"; +} + + diff --git a/Imaging/vtkImageGridSource.h b/Imaging/vtkImageGridSource.h new file mode 100644 index 0000000..011a52f --- /dev/null +++ b/Imaging/vtkImageGridSource.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageGridSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageGridSource - Create an image of a grid. +// .SECTION Description +// vtkImageGridSource produces an image of a grid. The +// default output type is double. + +#ifndef __vtkImageGridSource_h +#define __vtkImageGridSource_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageGridSource : public vtkImageAlgorithm +{ +public: + static vtkImageGridSource *New(); + vtkTypeRevisionMacro(vtkImageGridSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the grid spacing in pixel units. Default (10,10,0). + // A value of zero means no grid. + vtkSetVector3Macro(GridSpacing,int); + vtkGetVector3Macro(GridSpacing,int); + + // Description: + // Set/Get the grid origin, in ijk integer values. Default (0,0,0). + vtkSetVector3Macro(GridOrigin,int); + vtkGetVector3Macro(GridOrigin,int); + + // Description: + // Set the grey level of the lines. Default 1.0. + vtkSetMacro(LineValue,double); + vtkGetMacro(LineValue,double); + + // Description: + // Set the grey level of the fill. Default 0.0. + vtkSetMacro(FillValue,double); + vtkGetMacro(FillValue,double); + + // Description: + // Set/Get the data type of pixels in the imported data. + // As a convenience, the OutputScalarType is set to the same value. + vtkSetMacro(DataScalarType,int); + void SetDataScalarTypeToDouble(){this->SetDataScalarType(VTK_DOUBLE);} + void SetDataScalarTypeToInt(){this->SetDataScalarType(VTK_INT);} + void SetDataScalarTypeToShort(){this->SetDataScalarType(VTK_SHORT);} + void SetDataScalarTypeToUnsignedShort() + {this->SetDataScalarType(VTK_UNSIGNED_SHORT);} + void SetDataScalarTypeToUnsignedChar() + {this->SetDataScalarType(VTK_UNSIGNED_CHAR);} + vtkGetMacro(DataScalarType, int); + const char *GetDataScalarTypeAsString() { + return vtkImageScalarTypeNameMacro(this->DataScalarType); } + + // Description: + // Set/Get the extent of the whole output image, + // Default: (0,255,0,255,0,0) + vtkSetVector6Macro(DataExtent,int); + vtkGetVector6Macro(DataExtent,int); + + // Description: + // Set/Get the pixel spacing. + vtkSetVector3Macro(DataSpacing,double); + vtkGetVector3Macro(DataSpacing,double); + + // Description: + // Set/Get the origin of the data. + vtkSetVector3Macro(DataOrigin,double); + vtkGetVector3Macro(DataOrigin,double); + +protected: + vtkImageGridSource(); + ~vtkImageGridSource() {}; + + int GridSpacing[3]; + int GridOrigin[3]; + + double LineValue; + double FillValue; + + int DataScalarType; + + int DataExtent[6]; + double DataSpacing[3]; + double DataOrigin[3]; + + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual void ExecuteData(vtkDataObject *data); + +private: + vtkImageGridSource(const vtkImageGridSource&); // Not implemented. + void operator=(const vtkImageGridSource&); // Not implemented. +}; + + +#endif diff --git a/Imaging/vtkImageHSIToRGB.cxx b/Imaging/vtkImageHSIToRGB.cxx new file mode 100644 index 0000000..a4933d4 --- /dev/null +++ b/Imaging/vtkImageHSIToRGB.cxx @@ -0,0 +1,184 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageHSIToRGB.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageHSIToRGB.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImageHSIToRGB, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkImageHSIToRGB); + +//---------------------------------------------------------------------------- +vtkImageHSIToRGB::vtkImageHSIToRGB() +{ + this->Maximum = 255.0; + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageHSIToRGBExecute(vtkImageHSIToRGB *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + double R, G, B, H, S, I; + double max = self->GetMaximum(); + double temp; + double third = max / 3.0; + int idxC; + + // find the region to loop over + int maxC = inData->GetNumberOfScalarComponents()-1; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // Pixel operation + H = (double)(*inSI); ++inSI; + S = (double)(*inSI); ++inSI; + I = (double)(*inSI); ++inSI; + + // compute rgb assuming S = 1.0; + if (H >= 0.0 && H <= third) // red -> green + { + G = H/third; + R = 1.0 - G; + B = 0.0; + } + else if (H >= third && H <= 2.0*third) // green -> blue + { + B = (H - third)/third; + G = 1.0 - B; + R = 0.0; + } + else // blue -> red + { + R = (H - 2.0 * third)/third; + B = 1.0 - R; + G = 0.0; + } + + // add Saturation to the equation. + S = S / max; + //R = S + (1.0 - S)*R; + //G = S + (1.0 - S)*G; + //B = S + (1.0 - S)*B; + // what happend to this? + R = S*R + (1.0 - S); + G = S*G + (1.0 - S); + B = S*B + (1.0 - S); + + // Use intensity to get actual RGB + // normalize RGB first then apply intensity + temp = R + G + B; + //I = 3 * I / (temp * max); + // and what happend to this? + I = 3 * I / (temp); + R = R * I; + G = G * I; + B = B * I; + + // clip below 255 + //if (R > 255.0) R = max; + //if (G > 255.0) G = max; + //if (B > 255.0) B = max; + // mixed constant 255 and max ????? + if (R > max) + { + R = max; + } + if (G > max) + { + G = max; + } + if (B > max) + { + B = max; + } + + // assign output. + *outSI = (T)(R); ++outSI; + *outSI = (T)(G); ++outSI; + *outSI = (T)(B); ++outSI; + + for (idxC = 3; idxC <= maxC; idxC++) + { + *outSI++ = *inSI++; + } + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageHSIToRGB::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", must match out ScalarType " << outData->GetScalarType()); + return; + } + + // need three components for input and output + if (inData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Input has too few components"); + return; + } + if (outData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Output has too few components"); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageHSIToRGBExecute(this, inData, + outData, outExt, id, static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageHSIToRGB::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum: " << this->Maximum << "\n"; +} + diff --git a/Imaging/vtkImageHSIToRGB.h b/Imaging/vtkImageHSIToRGB.h new file mode 100644 index 0000000..6092f33 --- /dev/null +++ b/Imaging/vtkImageHSIToRGB.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageHSIToRGB.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageHSIToRGB - Converts HSI components to RGB. +// .SECTION Description +// For each pixel with hue, saturation and intensity components this filter +// outputs the color coded as red, green, blue. Output type must be the same +// as input type. + +// .SECTION See Also +// vtkImageRGBToHSI + +#ifndef __vtkImageHSIToRGB_h +#define __vtkImageHSIToRGB_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageHSIToRGB : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageHSIToRGB *New(); + vtkTypeRevisionMacro(vtkImageHSIToRGB,vtkThreadedImageAlgorithm); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Hue is an angle. Maximum specifies when it maps back to 0. + // HueMaximum defaults to 255 instead of 2PI, because unsigned char + // is expected as input. + // Maximum also specifies the maximum of the Saturation, and R, G, B. + vtkSetMacro(Maximum,double); + vtkGetMacro(Maximum,double); + +protected: + vtkImageHSIToRGB(); + ~vtkImageHSIToRGB() {}; + + double Maximum; + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); +private: + vtkImageHSIToRGB(const vtkImageHSIToRGB&); // Not implemented. + void operator=(const vtkImageHSIToRGB&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageHSVToRGB.cxx b/Imaging/vtkImageHSVToRGB.cxx new file mode 100644 index 0000000..c18cedb --- /dev/null +++ b/Imaging/vtkImageHSVToRGB.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageHSVToRGB.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageHSVToRGB.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageHSVToRGB, "$Revision: 1.31 $"); +vtkStandardNewMacro(vtkImageHSVToRGB); + +//---------------------------------------------------------------------------- +vtkImageHSVToRGB::vtkImageHSVToRGB() +{ + this->Maximum = 255.0; + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageHSVToRGBExecute(vtkImageHSVToRGB *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + double R, G, B, H, S, V; + double max = self->GetMaximum(); + int idxC; + + // find the region to loop over + int maxC = inData->GetNumberOfScalarComponents()-1; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // Pixel operation + H = (double)(*inSI) / max; ++inSI; + S = (double)(*inSI) / max; ++inSI; + V = (double)(*inSI) / max; ++inSI; + + vtkMath::HSVToRGB(H, S, V, &R, &G, &B); + + R *= max; + G *= max; + B *= max; + + if (R > max) + { + R = max; + } + if (G > max) + { + G = max; + } + if (B > max) + { + B = max; + } + + // assign output. + *outSI = (T)(R); ++outSI; + *outSI = (T)(G); ++outSI; + *outSI = (T)(B); ++outSI; + + for (idxC = 3; idxC <= maxC; idxC++) + { + *outSI++ = *inSI++; + } + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageHSVToRGB::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", must match out ScalarType " << outData->GetScalarType()); + return; + } + + // need three components for input and output + if (inData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Input has too few components"); + return; + } + if (outData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Output has too few components"); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageHSVToRGBExecute(this, inData, + outData, outExt, id, static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageHSVToRGB::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum: " << this->Maximum << "\n"; +} + diff --git a/Imaging/vtkImageHSVToRGB.h b/Imaging/vtkImageHSVToRGB.h new file mode 100644 index 0000000..a0b2071 --- /dev/null +++ b/Imaging/vtkImageHSVToRGB.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageHSVToRGB.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageHSVToRGB - Converts HSV components to RGB. +// .SECTION Description +// For each pixel with hue, saturation and value components this filter +// outputs the color coded as red, green, blue. Output type must be the same +// as input type. + +// .SECTION See Also +// vtkImageRGBToHSV + +#ifndef __vtkImageHSVToRGB_h +#define __vtkImageHSVToRGB_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageHSVToRGB : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageHSVToRGB *New(); + vtkTypeRevisionMacro(vtkImageHSVToRGB,vtkThreadedImageAlgorithm); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Hue is an angle. Maximum specifies when it maps back to 0. + // HueMaximum defaults to 255 instead of 2PI, because unsigned char + // is expected as input. + // Maximum also specifies the maximum of the Saturation, and R, G, B. + vtkSetMacro(Maximum,double); + vtkGetMacro(Maximum,double); + +protected: + vtkImageHSVToRGB(); + ~vtkImageHSVToRGB() {}; + + double Maximum; + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); +private: + vtkImageHSVToRGB(const vtkImageHSVToRGB&); // Not implemented. + void operator=(const vtkImageHSVToRGB&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageHybridMedian2D.cxx b/Imaging/vtkImageHybridMedian2D.cxx new file mode 100644 index 0000000..8a68eb9 --- /dev/null +++ b/Imaging/vtkImageHybridMedian2D.cxx @@ -0,0 +1,288 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageHybridMedian2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageHybridMedian2D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include +#include +#include + +vtkCxxRevisionMacro(vtkImageHybridMedian2D, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkImageHybridMedian2D); + +//---------------------------------------------------------------------------- +vtkImageHybridMedian2D::vtkImageHybridMedian2D() +{ + this->KernelSize[0] = 5; + this->KernelSize[1] = 5; + this->KernelSize[2] = 1; + this->KernelMiddle[0] = 2; + this->KernelMiddle[1] = 2; + this->KernelMiddle[2] = 0; + this->HandleBoundaries = 1; +} + +template +void vtkImageHybridMedian2DExecute(vtkImageHybridMedian2D *self, + vtkImageData *inData, T *inPtr2, + vtkImageData *outData, T *outPtr2, + int outExt[6], int id, + vtkInformation *inInfo) +{ + int idx0, idx1, idx2, idxC; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + int min0, max0, min1, max1, min2, max2, numComps; + int wholeMin0, wholeMax0, wholeMin1, wholeMax1; + int wholeExt[6]; + T *inPtr0, *inPtr1, *inPtrC; + T *outPtr0, *outPtr1, *outPtrC, *ptr; + T median1, median2, temp; + vtkstd::vector array; + unsigned long count = 0; + unsigned long target; + + id = id; + + inData->GetIncrements(inInc0, inInc1, inInc2); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + wholeMin0 = wholeExt[0]; + wholeMax0 = wholeExt[1]; + wholeMin1 = wholeExt[2]; + wholeMax1 = wholeExt[3]; + numComps = inData->GetNumberOfScalarComponents(); + outData->GetIncrements(outInc0, outInc1, outInc2); + min0 = outExt[0]; max0 = outExt[1]; + min1 = outExt[2]; max1 = outExt[3]; + min2 = outExt[4]; max2 = outExt[5]; + + target = (unsigned long)((max2-min2+1)*(max1-min1+1)/50.0); + target++; + + for (idx2 = min2; idx2 <= max2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + + for (idx1 = min1; !self->AbortExecute && idx1 <= max1; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + inPtr0 = inPtr1; + outPtr0 = outPtr1; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + inPtrC = inPtr0; + outPtrC = outPtr0; + for (idxC = 0; idxC < numComps; ++idxC) + { + // compute median of + neighborhood + // note that y axis direction is up in vtk images, not down + // as in screen coordinates + array.clear(); + // Center + ptr = inPtrC; + array.push_back( *ptr ); + // left + ptr = inPtrC; + if (idx0 > wholeMin0) + { + ptr -= inInc0; + array.push_back( *ptr ); + } + if (idx0 - 1 > wholeMin0) + { + ptr -= inInc0; + array.push_back( *ptr ); + } + // right + ptr = inPtrC; + if (idx0 < wholeMax0) + { + ptr += inInc0; + array.push_back( *ptr ); + } + if (idx0 + 1 < wholeMax0) + { + ptr += inInc0; + array.push_back( *ptr ); + } + // down + ptr = inPtrC; + if (idx1 > wholeMin1) + { + ptr -= inInc1; + array.push_back( *ptr ); + } + if (idx1 - 1 > wholeMin1) + { + ptr -= inInc1; + array.push_back( *ptr ); + } + // up + ptr = inPtrC; + if (idx1 < wholeMax1) + { + ptr += inInc1; + array.push_back( *ptr ); + } + if (idx1 + 1 < wholeMax1) + { + ptr += inInc1; + array.push_back( *ptr ); + } + + vtkstd::sort(array.begin(),array.end()); + median1 = array[static_cast(0.5*array.size())]; + + // compute median of x neighborhood + // note that y axis direction is up in vtk images, not down + // as in screen coordinates + array.clear(); + // Center + ptr = inPtrC; + array.push_back( *ptr ); + // lower left + if (idx0 > wholeMin0 && idx1 > wholeMin1) + { + ptr -= inInc0 + inInc1; + array.push_back( *ptr ); + } + if (idx0-1 > wholeMin0 && idx1-1 > wholeMin1) + { + ptr -= inInc0 + inInc1; + array.push_back( *ptr ); + } + // upper right + ptr = inPtrC; + if (idx0 < wholeMax0 && idx1 < wholeMax1) + { + ptr += inInc0 + inInc1; + array.push_back( *ptr ); + } + if (idx0+1 < wholeMax0 && idx1+1 < wholeMax1) + { + ptr += inInc0 + inInc1; + array.push_back( *ptr ); + } + // upper left + ptr = inPtrC; + if (idx0 > wholeMin0 && idx1 < wholeMax1) + { + ptr += -inInc0 + inInc1; + array.push_back( *ptr ); + } + if (idx0-1 > wholeMin0 && idx1+1 < wholeMax1) + { + ptr += -inInc0 + inInc1; + array.push_back( *ptr ); + } + // lower right + ptr = inPtrC; + if (idx0 < wholeMax0 && idx1 > wholeMin1) + { + ptr += inInc0 - inInc1; + array.push_back( *ptr ); + } + if (idx0+1 < wholeMax0 && idx1-1 > wholeMin1) + { + ptr += inInc0 - inInc1; + array.push_back( *ptr ); + } + + vtkstd::sort(array.begin(),array.end()); + median2 = array[static_cast(0.5*array.size())]; + + // Compute the median of the three. (med1, med2 and center) + if (median1 > median2) + { + temp = median1; + median1 = median2; + median2 = temp; + } + if (*inPtrC < median1) + { + *outPtrC = median1; + } + else if (*inPtrC < median2) + { + *outPtrC = *inPtrC; + } + else + { + *outPtrC = median2; + } + ++inPtrC; + ++outPtrC; + } + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } +} + +// This method contains the first switch statement that calls the correct +// templated function for the input and output Data types. +// It hanldes image boundaries, so the image does not shrink. +void vtkImageHybridMedian2D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // this filter expects the output type to be same as input + if (outData[0]->GetScalarType() != inData[0][0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << " must match input scalar type"); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageHybridMedian2DExecute( this, inData[0][0], + (VTK_TT *)(inPtr), outData[0], + (VTK_TT *)(outPtr), + outExt, id, inInfo)); + + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageHybridMedian2D.h b/Imaging/vtkImageHybridMedian2D.h new file mode 100644 index 0000000..4aea779 --- /dev/null +++ b/Imaging/vtkImageHybridMedian2D.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageHybridMedian2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageHybridMedian2D - Median filter that preserves lines and +// corners. +// .SECTION Description +// vtkImageHybridMedian2D is a median filter that preserves thin lines and +// corners. It operates on a 5x5 pixel neighborhood. It computes two values +// initially: the median of the + neighbors and the median of the x +// neighbors. It then computes the median of these two values plus the center +// pixel. This result of this second median is the output pixel value. + + + +#ifndef __vtkImageHybridMedian2D_h +#define __vtkImageHybridMedian2D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageHybridMedian2D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageHybridMedian2D *New(); + vtkTypeRevisionMacro(vtkImageHybridMedian2D,vtkImageSpatialAlgorithm); + +protected: + vtkImageHybridMedian2D(); + ~vtkImageHybridMedian2D() {}; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); +private: + vtkImageHybridMedian2D(const vtkImageHybridMedian2D&); // Not implemented. + void operator=(const vtkImageHybridMedian2D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageIdealHighPass.cxx b/Imaging/vtkImageIdealHighPass.cxx new file mode 100644 index 0000000..4b8925d --- /dev/null +++ b/Imaging/vtkImageIdealHighPass.cxx @@ -0,0 +1,229 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIdealHighPass.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageIdealHighPass.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageIdealHighPass, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkImageIdealHighPass); + +//---------------------------------------------------------------------------- +vtkImageIdealHighPass::vtkImageIdealHighPass() +{ + this->CutOff[0] = this->CutOff[1] = this->CutOff[2] = VTK_DOUBLE_MAX; +} + +//---------------------------------------------------------------------------- +void vtkImageIdealHighPass::SetXCutOff(double cutOff) +{ + if (cutOff == this->CutOff[0]) + { + return; + } + this->CutOff[0] = cutOff; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageIdealHighPass::SetYCutOff(double cutOff) +{ + if (cutOff == this->CutOff[1]) + { + return; + } + this->CutOff[1] = cutOff; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageIdealHighPass::SetZCutOff(double cutOff) +{ + if (cutOff == this->CutOff[2]) + { + return; + } + this->CutOff[2] = cutOff; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageIdealHighPass::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int ext[6], int id) +{ + int idx0, idx1, idx2; + int min0, max0; + double *inPtr; + double *outPtr; + int wholeExtent[6]; + double spacing[3]; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + double temp0, temp1, temp2, mid0, mid1, mid2; + // normalization factors + double norm0, norm1, norm2; + double sum1, sum0; + unsigned long count = 0; + unsigned long target; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // Error checking + if (inData[0][0]->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro("Expecting 2 components not " + << inData[0][0]->GetNumberOfScalarComponents()); + return; + } + if (inData[0][0]->GetScalarType() != VTK_DOUBLE || + outData[0]->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Expecting input and output to be of type double"); + return; + } + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + inData[0][0]->GetSpacing(spacing); + + inPtr = (double *)(inData[0][0]->GetScalarPointerForExtent(ext)); + outPtr = (double *)(outData[0]->GetScalarPointerForExtent(ext)); + + inData[0][0]->GetContinuousIncrements(ext, inInc0, inInc1, inInc2); + outData[0]->GetContinuousIncrements(ext, outInc0, outInc1, outInc2); + + min0 = ext[0]; + max0 = ext[1]; + mid0 = (double)(wholeExtent[0] + wholeExtent[1] + 1) / 2.0; + mid1 = (double)(wholeExtent[2] + wholeExtent[3] + 1) / 2.0; + mid2 = (double)(wholeExtent[4] + wholeExtent[5] + 1) / 2.0; + if ( this->CutOff[0] == 0.0) + { + norm0 = VTK_DOUBLE_MAX; + } + else + { + norm0 = 1.0 / ((spacing[0] * 2.0 * mid0) * this->CutOff[0]); + } + if ( this->CutOff[1] == 0.0) + { + norm1 = VTK_DOUBLE_MAX; + } + else + { + norm1 = 1.0 / ((spacing[1] * 2.0 * mid1) * this->CutOff[1]); + } + if ( this->CutOff[2] == 0.0) + { + norm2 = VTK_DOUBLE_MAX; + } + else + { + norm2 = 1.0 / ((spacing[2] * 2.0 * mid2) * this->CutOff[2]); + } + + target = (unsigned long)((ext[5]-ext[4]+1)*(ext[3]-ext[2]+1)/50.0); + target++; + + // loop over all the pixels (keeping track of normalized distance to origin. + for (idx2 = ext[4]; idx2 <= ext[5]; ++idx2) + { + // distance to min (this axis' contribution) + temp2 = (double)idx2; + // Wrap back to 0. + if (temp2 > mid2) + { + temp2 = mid2 + mid2 - temp2; + } + // Convert location into normalized cycles/world unit + temp2 = temp2 * norm2; + + for (idx1 = ext[2]; !this->AbortExecute && idx1 <= ext[3]; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + } + // distance to min (this axis' contribution) + temp1 = (double)idx1; + // Wrap back to 0. + if (temp1 > mid1) + { + temp1 = mid1 + mid1 - temp1; + } + // Convert location into cycles / world unit + temp1 = temp1 * norm1; + sum1 = temp2 * temp2 + temp1 * temp1; + + for (idx0 = min0; idx0 <= max0; ++idx0) + { + // distance to min (this axis' contribution) + temp0 = (double)idx0; + // Wrap back to 0. + if (temp0 > mid0) + { + temp0 = mid0 + mid0 - temp0; + } + // Convert location into cycles / world unit + temp0 = temp0 * norm0; + sum0 = sum1 + temp0 * temp0; + + if (sum0 > 1.0) + { + // real component + *outPtr++ = *inPtr++; + // imaginary component + *outPtr++ = *inPtr++; + } + else + { + // real component + *outPtr++ = 0.0; + ++inPtr; + // imaginary component + *outPtr++ = 0.0; + ++inPtr; + } + } + inPtr += inInc1; + outPtr += outInc1; + } + inPtr += inInc2; + outPtr += outInc2; + } +} + +void vtkImageIdealHighPass::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "CutOff: ( " + << this->CutOff[0] << ", " + << this->CutOff[1] << ", " + << this->CutOff[2] << " )\n"; +} + diff --git a/Imaging/vtkImageIdealHighPass.h b/Imaging/vtkImageIdealHighPass.h new file mode 100644 index 0000000..55005ac --- /dev/null +++ b/Imaging/vtkImageIdealHighPass.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIdealHighPass.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageIdealHighPass - Simple frequency domain band pass. +// .SECTION Description +// This filter only works on an image after it has been converted to +// frequency domain by a vtkImageFFT filter. A vtkImageRFFT filter +// can be used to convert the output back into the spatial domain. +// vtkImageIdealHighPass just sets a portion of the image to zero. The sharp +// cutoff in the frequence domain produces ringing in the spatial domain. +// Input and Output must be doubles. Dimensionality is set when the axes are +// set. Defaults to 2D on X and Y axes. + +// .SECTION See Also +// vtkImageButterworthHighPass vtkImageIdealLowPass vtkImageFFT vtkImageRFFT + + +#ifndef __vtkImageIdealHighPass_h +#define __vtkImageIdealHighPass_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageIdealHighPass : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageIdealHighPass *New(); + vtkTypeRevisionMacro(vtkImageIdealHighPass,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the cutoff frequency for each axis. + // The values are specified in the order X, Y, Z, Time. + // Units: Cycles per world unit (as defined by the data spacing). + vtkSetVector3Macro(CutOff,double); + void SetCutOff(double v) {this->SetCutOff(v, v, v);} + void SetXCutOff(double v); + void SetYCutOff(double v); + void SetZCutOff(double v); + vtkGetVector3Macro(CutOff,double); + double GetXCutOff() {return this->CutOff[0];} + double GetYCutOff() {return this->CutOff[1];} + double GetZCutOff() {return this->CutOff[2];} + +protected: + vtkImageIdealHighPass(); + ~vtkImageIdealHighPass() {}; + + double CutOff[3]; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); +private: + vtkImageIdealHighPass(const vtkImageIdealHighPass&); // Not implemented. + void operator=(const vtkImageIdealHighPass&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageIdealLowPass.cxx b/Imaging/vtkImageIdealLowPass.cxx new file mode 100644 index 0000000..c2b9897 --- /dev/null +++ b/Imaging/vtkImageIdealLowPass.cxx @@ -0,0 +1,229 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIdealLowPass.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageIdealLowPass.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageIdealLowPass, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkImageIdealLowPass); + +//---------------------------------------------------------------------------- +vtkImageIdealLowPass::vtkImageIdealLowPass() +{ + this->CutOff[0] = this->CutOff[1] = this->CutOff[2] = VTK_DOUBLE_MAX; +} + + +//---------------------------------------------------------------------------- +void vtkImageIdealLowPass::SetXCutOff(double cutOff) +{ + if (cutOff == this->CutOff[0]) + { + return; + } + this->CutOff[0] = cutOff; + this->Modified(); +} +//---------------------------------------------------------------------------- +void vtkImageIdealLowPass::SetYCutOff(double cutOff) +{ + if (cutOff == this->CutOff[1]) + { + return; + } + this->CutOff[1] = cutOff; + this->Modified(); +} +//---------------------------------------------------------------------------- +void vtkImageIdealLowPass::SetZCutOff(double cutOff) +{ + if (cutOff == this->CutOff[2]) + { + return; + } + this->CutOff[2] = cutOff; + this->Modified(); +} + + +//---------------------------------------------------------------------------- +void vtkImageIdealLowPass::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int ext[6], int id) +{ + int idx0, idx1, idx2; + int min0, max0; + double *inPtr; + double *outPtr; + int wholeExtent[6]; + double spacing[3]; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + double temp0, temp1, temp2, mid0, mid1, mid2; + // normalization factors + double norm0, norm1, norm2; + double sum1, sum0; + unsigned long count = 0; + unsigned long target; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // Error checking + if (inData[0][0]->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro("Expecting 2 components not " + << inData[0][0]->GetNumberOfScalarComponents()); + return; + } + if (inData[0][0]->GetScalarType() != VTK_DOUBLE || + outData[0]->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Expecting input and output to be of type double"); + return; + } + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + inData[0][0]->GetSpacing(spacing); + + inPtr = (double *)(inData[0][0]->GetScalarPointerForExtent(ext)); + outPtr = (double *)(outData[0]->GetScalarPointerForExtent(ext)); + + inData[0][0]->GetContinuousIncrements(ext, inInc0, inInc1, inInc2); + outData[0]->GetContinuousIncrements(ext, outInc0, outInc1, outInc2); + + min0 = ext[0]; + max0 = ext[1]; + mid0 = (double)(wholeExtent[0] + wholeExtent[1] + 1) / 2.0; + mid1 = (double)(wholeExtent[2] + wholeExtent[3] + 1) / 2.0; + mid2 = (double)(wholeExtent[4] + wholeExtent[5] + 1) / 2.0; + if ( this->CutOff[0] == 0.0) + { + norm0 = VTK_DOUBLE_MAX; + } + else + { + norm0 = 1.0 / ((spacing[0] * 2.0 * mid0) * this->CutOff[0]); + } + if ( this->CutOff[1] == 0.0) + { + norm1 = VTK_DOUBLE_MAX; + } + else + { + norm1 = 1.0 / ((spacing[1] * 2.0 * mid1) * this->CutOff[1]); + } + if ( this->CutOff[2] == 0.0) + { + norm2 = VTK_DOUBLE_MAX; + } + else + { + norm2 = 1.0 / ((spacing[2] * 2.0 * mid2) * this->CutOff[2]); + } + + target = (unsigned long)((ext[5]-ext[4]+1)*(ext[3]-ext[2]+1)/50.0); + target++; + + // loop over all the pixels (keeping track of normalized distance to origin. + for (idx2 = ext[4]; idx2 <= ext[5]; ++idx2) + { + // distance to min (this axis' contribution) + temp2 = (double)idx2; + // Wrap back to 0. + if (temp2 > mid2) + { + temp2 = mid2 + mid2 - temp2; + } + // Convert location into normalized cycles/world unit + temp2 = temp2 * norm2; + + for (idx1 = ext[2]; !this->AbortExecute && idx1 <= ext[3]; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + } + // distance to min (this axis' contribution) + temp1 = (double)idx1; + // Wrap back to 0. + if (temp1 > mid1) + { + temp1 = mid1 + mid1 - temp1; + } + // Convert location into cycles / world unit + temp1 = temp1 * norm1; + sum1 = temp2 * temp2 + temp1 * temp1; + + for (idx0 = min0; idx0 <= max0; ++idx0) + { + // distance to min (this axis' contribution) + temp0 = (double)idx0; + // Wrap back to 0. + if (temp0 > mid0) + { + temp0 = mid0 + mid0 - temp0; + } + // Convert location into cycles / world unit + temp0 = temp0 * norm0; + sum0 = sum1 + temp0 * temp0; + + if (sum0 > 1.0) + { + // real component + *outPtr++ = 0.0; + ++inPtr; + // imaginary component + *outPtr++ = 0.0; + ++inPtr; + } + else + { + // real component + *outPtr++ = *inPtr++; + // imaginary component + *outPtr++ = *inPtr++; + } + } + inPtr += inInc1; + outPtr += outInc1; + } + inPtr += inInc2; + outPtr += outInc2; + } +} + +void vtkImageIdealLowPass::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "CutOff: ( " + << this->CutOff[0] << ", " + << this->CutOff[1] << ", " + << this->CutOff[2] << " )\n"; +} + diff --git a/Imaging/vtkImageIdealLowPass.h b/Imaging/vtkImageIdealLowPass.h new file mode 100644 index 0000000..8bead31 --- /dev/null +++ b/Imaging/vtkImageIdealLowPass.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIdealLowPass.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageIdealLowPass - Simple frequency domain band pass. +// .SECTION Description +// This filter only works on an image after it has been converted to +// frequency domain by a vtkImageFFT filter. A vtkImageRFFT filter +// can be used to convert the output back into the spatial domain. +// vtkImageIdealLowPass just sets a portion of the image to zero. The result +// is an image with a lot of ringing. Input and Output must be doubles. +// Dimensionality is set when the axes are set. Defaults to 2D on X and Y +// axes. + +// .SECTION See Also +// vtkImageButterworthLowPass vtkImageIdealHighPass vtkImageFFT vtkImageRFFT + + + +#ifndef __vtkImageIdealLowPass_h +#define __vtkImageIdealLowPass_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageIdealLowPass : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageIdealLowPass *New(); + vtkTypeRevisionMacro(vtkImageIdealLowPass,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the cutoff frequency for each axis. + // The values are specified in the order X, Y, Z, Time. + // Units: Cycles per world unit (as defined by the data spacing). + vtkSetVector3Macro(CutOff,double); + void SetCutOff(double v) {this->SetCutOff(v, v, v);} + void SetXCutOff(double v); + void SetYCutOff(double v); + void SetZCutOff(double v); + vtkGetVector3Macro(CutOff,double); + double GetXCutOff() {return this->CutOff[0];} + double GetYCutOff() {return this->CutOff[1];} + double GetZCutOff() {return this->CutOff[2];} + +protected: + vtkImageIdealLowPass(); + ~vtkImageIdealLowPass() {}; + + double CutOff[3]; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); +private: + vtkImageIdealLowPass(const vtkImageIdealLowPass&); // Not implemented. + void operator=(const vtkImageIdealLowPass&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageImport.cxx b/Imaging/vtkImageImport.cxx new file mode 100644 index 0000000..088a231 --- /dev/null +++ b/Imaging/vtkImageImport.cxx @@ -0,0 +1,472 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageImport.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageImport.h" + +#include "vtkByteSwap.h" +#include "vtkImageData.h" +#include "vtkImageImportExecutive.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +#include +#include + +vtkCxxRevisionMacro(vtkImageImport, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkImageImport); + + +#define tryCatchMacro(invocation, messagePrepend)\ + try\ + {\ + invocation;\ + }\ + catch (vtkstd::exception &_e)\ + {\ + vtkErrorMacro(<ImportVoidPointer = 0; + + this->DataScalarType = VTK_SHORT; + this->NumberOfScalarComponents = 1; + + for (idx = 0; idx < 3; ++idx) + { + this->DataExtent[idx*2] = this->DataExtent[idx*2 + 1] = 0; + this->WholeExtent[idx*2] = this->WholeExtent[idx*2 + 1] = 0; + this->DataSpacing[idx] = 1.0; + this->DataOrigin[idx] = 0.0; + } + this->SaveUserArray = 0; + + this->CallbackUserData = 0; + + this->UpdateInformationCallback = 0; + this->PipelineModifiedCallback = 0; + this->WholeExtentCallback = 0; + this->SpacingCallback = 0; + this->OriginCallback = 0; + this->ScalarTypeCallback = 0; + this->NumberOfComponentsCallback = 0; + this->PropagateUpdateExtentCallback = 0; + this->UpdateDataCallback = 0; + this->DataExtentCallback = 0; + this->BufferPointerCallback = 0; + + this->SetNumberOfInputPorts(0); + + vtkExecutive *exec = vtkImageImportExecutive::New(); + this->SetExecutive(exec); + exec->Delete(); +} + +//---------------------------------------------------------------------------- +vtkImageImport::~vtkImageImport() +{ + if ((this->ImportVoidPointer) && (!this->SaveUserArray)) + { + delete [] (char *)this->ImportVoidPointer; + } +} + +//---------------------------------------------------------------------------- +void vtkImageImport::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + + os << indent << "ImportVoidPointer: " << this->ImportVoidPointer << "\n"; + + os << indent << "DataScalarType: " + << vtkImageScalarTypeNameMacro(this->DataScalarType) << "\n"; + + os << indent << "NumberOfScalarComponents: " + << this->NumberOfScalarComponents << "\n"; + + os << indent << "WholeExtent: (" << this->WholeExtent[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << this->WholeExtent[idx]; + } + os << ")\n"; + + os << indent << "DataExtent: (" << this->DataExtent[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << this->DataExtent[idx]; + } + os << ")\n"; + + os << indent << "DataSpacing: (" << this->DataSpacing[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->DataSpacing[idx]; + } + os << ")\n"; + + os << indent << "DataOrigin: (" << this->DataOrigin[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->DataOrigin[idx]; + } + os << ")\n"; + + os << indent << "CallbackUserData: " + << (this->CallbackUserData? "Set" : "Not Set") << "\n"; + + os << indent << "UpdateInformationCallback: " + << (this->UpdateInformationCallback? "Set" : "Not Set") << "\n"; + + os << indent << "PipelineModifiedCallback: " + << (this->PipelineModifiedCallback? "Set" : "Not Set") << "\n"; + + os << indent << "WholeExtentCallback: " + << (this->WholeExtentCallback? "Set" : "Not Set") << "\n"; + + os << indent << "SpacingCallback: " + << (this->SpacingCallback? "Set" : "Not Set") << "\n"; + + os << indent << "OriginCallback: " + << (this->OriginCallback? "Set" : "Not Set") << "\n"; + + os << indent << "ScalarTypeCallback: " + << (this->ScalarTypeCallback? "Set" : "Not Set") << "\n"; + + os << indent << "NumberOfComponentsCallback: " + << (this->NumberOfComponentsCallback? "Set" : "Not Set") << "\n"; + + os << indent << "PropagateUpdateExtentCallback: " + << (this->PropagateUpdateExtentCallback? "Set" : "Not Set") << "\n"; + + os << indent << "UpdateDataCallback: " + << (this->UpdateDataCallback? "Set" : "Not Set") << "\n"; + + os << indent << "DataExtentCallback: " + << (this->DataExtentCallback? "Set" : "Not Set") << "\n"; + + os << indent << "BufferPointerCallback: " + << (this->BufferPointerCallback? "Set" : "Not Set") << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkImageImport::RequestUpdateExtent( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* outputVector) +{ + if (this->PropagateUpdateExtentCallback) + { + int uExt[6]; + + vtkInformation* outInfo = outputVector->GetInformationObject(0); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),uExt); + tryCatchMacro( + (this->PropagateUpdateExtentCallback)(this->CallbackUserData,uExt), + "PropagateUpdateExtentCallback: "); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageImport::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + // If set, use the callbacks to fill in our data members. + this->InvokeExecuteInformationCallbacks(); + + // Legacy support for code that sets only DataExtent. + this->LegacyCheckWholeExtent(); + + // set the whole extent + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent,6); + + // set the spacing + outInfo->Set(vtkDataObject::SPACING(),this->DataSpacing,3); + + // set the origin. + outInfo->Set(vtkDataObject::ORIGIN(),this->DataOrigin,3); + + // set data type + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, + this->NumberOfScalarComponents); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageImport::ExecuteData(vtkDataObject *output) +{ + // If set, use the callbacks to prepare our input data. + this->InvokeExecuteDataCallbacks(); + + vtkImageData *data = vtkImageData::SafeDownCast(output); + data->SetExtent(0,0,0,0,0,0); + data->AllocateScalars(); + void *ptr = this->GetImportVoidPointer(); + int size = + (this->DataExtent[1] - this->DataExtent[0]+1) * + (this->DataExtent[3] - this->DataExtent[2]+1) * + (this->DataExtent[5] - this->DataExtent[4]+1) * + this->NumberOfScalarComponents; + + data->SetExtent(this->DataExtent); + data->GetPointData()->GetScalars()->SetVoidArray(ptr,size,1); +} + +//---------------------------------------------------------------------------- +void vtkImageImport::CopyImportVoidPointer(void *ptr, int size) +{ + unsigned char *mem = new unsigned char [size]; + memcpy(mem,ptr,size); + this->SetImportVoidPointer(mem,0); +} + +//---------------------------------------------------------------------------- +void vtkImageImport::SetImportVoidPointer(void *ptr) +{ + this->SetImportVoidPointer(ptr,1); +} + +//---------------------------------------------------------------------------- +void vtkImageImport::SetImportVoidPointer(void *ptr, int save) +{ + if (ptr != this->ImportVoidPointer) + { + if ((this->ImportVoidPointer) && (!this->SaveUserArray)) + { + vtkDebugMacro (<< "Deleting the array..."); + delete [] (char *)this->ImportVoidPointer; + } + else + { + vtkDebugMacro (<<"Warning, array not deleted, but will point to new array."); + } + this->Modified(); + } + this->SaveUserArray = save; + this->ImportVoidPointer = ptr; +} + +//---------------------------------------------------------------------------- +int vtkImageImport::InvokePipelineModifiedCallbacks() +{ + if (this->PipelineModifiedCallback) + { + int ret; + try + { + ret = (this->PipelineModifiedCallback)(this->CallbackUserData); + } + catch (vtkstd::exception &_e) + { + vtkErrorMacro(<<"Calling PipelineModifiedCallback: " << _e.what()); + // if an error occurred, we don't want the pipeline to run again + // until the error has been rectified. It can be assumed that + // the rectifying actions will set the modified flag. + ret = 0; + } + catch (...) + { + vtkErrorMacro(<<"Unknown exception."); + // same logic as above + ret = 0; + } + + return ret; + } + else + { + // if there's no PipelineModified installed, we return 0 + return 0; + } + +} + +//---------------------------------------------------------------------------- +void vtkImageImport::InvokeUpdateInformationCallbacks() +{ + if (this->UpdateInformationCallback) + { + tryCatchMacro((this->UpdateInformationCallback)(this->CallbackUserData), + "Calling UpdateInformationCallback: "); + } + + if (this->InvokePipelineModifiedCallbacks()) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageImport::InvokeExecuteInformationCallbacks() +{ + if (this->WholeExtentCallback) + { + tryCatchMacro( + this->SetWholeExtent( + (this->WholeExtentCallback)(this->CallbackUserData)), + "Calling WholeExtentCallback: "); + } + if (this->SpacingCallback) + { + tryCatchMacro( + this->SetDataSpacing((this->SpacingCallback)(this->CallbackUserData)), + "Calling SpacingCallback: "); + } + if (this->OriginCallback) + { + tryCatchMacro( + this->SetDataOrigin((this->OriginCallback)(this->CallbackUserData)), + "Calling OriginCallback: "); + } + if (this->NumberOfComponentsCallback) + { + tryCatchMacro( + this->SetNumberOfScalarComponents( + (this->NumberOfComponentsCallback)(this->CallbackUserData)), + "Calling NumberOfComponentsCallback: "); + } + if (this->ScalarTypeCallback) + { + const char* scalarType = "double"; // default + tryCatchMacro( + scalarType = (this->ScalarTypeCallback)(this->CallbackUserData), + "Calling ScalarTypeCallback: "); + + if (strcmp(scalarType, "double")==0) + { + this->SetDataScalarType(VTK_DOUBLE); + } + else if (strcmp(scalarType, "float")==0) + { + this->SetDataScalarType(VTK_FLOAT); + } + else if (strcmp(scalarType, "long")==0) + { + this->SetDataScalarType(VTK_LONG); + } + else if (strcmp(scalarType, "unsigned long")==0) + { + this->SetDataScalarType(VTK_UNSIGNED_LONG); + } + else if (strcmp(scalarType, "int")==0) + { + this->SetDataScalarType(VTK_INT); + } + else if (strcmp(scalarType, "unsigned int")==0) + { + this->SetDataScalarType(VTK_UNSIGNED_INT); + } + else if (strcmp(scalarType, "short")==0) + { + this->SetDataScalarType(VTK_SHORT); + } + else if (strcmp(scalarType, "unsigned short")==0) + { + this->SetDataScalarType(VTK_UNSIGNED_SHORT); + } + else if (strcmp(scalarType, "char")==0) + { + this->SetDataScalarType(VTK_CHAR); + } + else if (strcmp(scalarType, "unsigned char")==0) + { + this->SetDataScalarType(VTK_UNSIGNED_CHAR); + } + } +} + + +//---------------------------------------------------------------------------- +void vtkImageImport::InvokeExecuteDataCallbacks() +{ + if (this->UpdateDataCallback) + { + tryCatchMacro( + (this->UpdateDataCallback)(this->CallbackUserData), + "Calling UpdateDataCallback: "); + } + if (this->DataExtentCallback) + { + tryCatchMacro( + this->SetDataExtent((this->DataExtentCallback)(this->CallbackUserData)), + "Calling DataExtentCallback: "); + } + if (this->BufferPointerCallback) + { + tryCatchMacro( + this->SetImportVoidPointer( + (this->BufferPointerCallback)(this->CallbackUserData)), + "Calling BufferPointerCallback: "); + } +} + +//---------------------------------------------------------------------------- +// In the past, this class made no distinction between whole extent and +// buffered extent, so only SetDataExtent also set the whole extent of +// the output. Now, there is a separate SetWholeExtent which should be +// called as well. +void vtkImageImport::LegacyCheckWholeExtent() +{ + // If the WholeExtentCallback is set, this must not be legacy code. + if (this->WholeExtentCallback) + { + return; + } + int i; + // Check whether the whole extent has been set. + for(i=0; i < 6; ++i) + { + if (this->WholeExtent[i] != 0) + { + return; + } + } + + // The whole extent has not been set. Copy it from the data extent + // and issue a warning. + for(i=0; i < 6; ++i) + { + this->WholeExtent[i] = this->DataExtent[i]; + } + + vtkWarningMacro("\n" + "There is a distinction between the whole extent and the buffered\n" + "extent of an imported image. Use SetWholeExtent to set the extent\n" + "of the entire image. Use SetDataExtent to set the extent of the\n" + "portion of the image that is in the buffer set with\n" + "SetImportVoidPointer. Both should be called even if the extents are\n" + "the same."); +} diff --git a/Imaging/vtkImageImport.h b/Imaging/vtkImageImport.h new file mode 100644 index 0000000..decadc7 --- /dev/null +++ b/Imaging/vtkImageImport.h @@ -0,0 +1,278 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageImport.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageImport - Import data from a C array. +// .SECTION Description +// vtkImageImport provides methods needed to import image data from a source +// independent of VTK, such as a simple C array or a third-party pipeline. +// Note that the VTK convention is for the image voxel index (0,0,0) to be +// the lower-left corner of the image, while most 2D image formats use +// the upper-left corner. You can use vtkImageFlip to correct the +// orientation after the image has been loaded into VTK. +// Note that is also possible to import the raw data from a Python string +// instead of from a C array. +// .SECTION See Also +// vtkImageExport + +#ifndef __vtkImageImport_h +#define __vtkImageImport_h + +#include "vtkImageAlgorithm.h" +//#include "vtkTransform.h" + +class VTK_IMAGING_EXPORT vtkImageImport : public vtkImageAlgorithm +{ +public: + static vtkImageImport *New(); + vtkTypeRevisionMacro(vtkImageImport,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Import data and make an internal copy of it. If you do not want + // VTK to copy the data, then use SetImportVoidPointer instead (do + // not use both). Give the size of the data array in bytes. + void CopyImportVoidPointer(void *ptr, int size); + + // Description: + // Set the pointer from which the image data is imported. VTK will + // not make its own copy of the data, it will access the data directly + // from the supplied array. VTK will not attempt to delete the data + // nor modify the data. + void SetImportVoidPointer(void *ptr); + void *GetImportVoidPointer() {return this->ImportVoidPointer;}; + + // Description: + // Set the pointer from which the image data is imported. Set save to 1 + // (the default) unless you want VTK to delete the array via C++ delete + // when the vtkImageImport object is deallocated. VTK will not make its + // own copy of the data, it will access the data directly from the + // supplied array. + void SetImportVoidPointer(void *ptr, int save); + + // Description: + // Set/Get the data type of pixels in the imported data. This is used + // as the scalar type of the Output. Default: Short. + vtkSetMacro(DataScalarType,int); + void SetDataScalarTypeToDouble(){this->SetDataScalarType(VTK_DOUBLE);} + void SetDataScalarTypeToFloat(){this->SetDataScalarType(VTK_FLOAT);} + void SetDataScalarTypeToInt(){this->SetDataScalarType(VTK_INT);} + void SetDataScalarTypeToShort(){this->SetDataScalarType(VTK_SHORT);} + void SetDataScalarTypeToUnsignedShort() + {this->SetDataScalarType(VTK_UNSIGNED_SHORT);} + void SetDataScalarTypeToUnsignedChar() + {this->SetDataScalarType(VTK_UNSIGNED_CHAR);} + vtkGetMacro(DataScalarType, int); + const char *GetDataScalarTypeAsString() { + return vtkImageScalarTypeNameMacro(this->DataScalarType); } + + // Description: + // Set/Get the number of scalar components, for RGB images this must be 3. + // Default: 1. + vtkSetMacro(NumberOfScalarComponents,int); + vtkGetMacro(NumberOfScalarComponents,int); + + // Description: + // Get/Set the extent of the data buffer. The dimensions of your data + // must be equal to (extent[1]-extent[0]+1) * (extent[3]-extent[2]+1) * + // (extent[5]-DataExtent[4]+1). For example, for a 2D image use + // (0,width-1, 0,height-1, 0,0). + vtkSetVector6Macro(DataExtent,int); + vtkGetVector6Macro(DataExtent,int); + void SetDataExtentToWholeExtent() + {this->SetDataExtent(this->GetWholeExtent());} + + // Description: + // Set/Get the spacing (typically in mm) between image voxels. + // Default: (1.0, 1.0, 1.0). + vtkSetVector3Macro(DataSpacing,double); + vtkGetVector3Macro(DataSpacing,double); + + // Description: + // Set/Get the origin of the data, i.e. the coordinates (usually in mm) + // of voxel (0,0,0). Default: (0.0, 0.0, 0.0). + vtkSetVector3Macro(DataOrigin,double); + vtkGetVector3Macro(DataOrigin,double); + + // Description: + // Get/Set the whole extent of the image. This is the largest possible + // extent. Set the DataExtent to the extent of the image in the buffer + // pointed to by the ImportVoidPointer. + vtkSetVector6Macro(WholeExtent,int); + vtkGetVector6Macro(WholeExtent,int); + + // Description: + // Propagates the update extent through the callback if it is set. + virtual int RequestUpdateExtent( vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + //BTX + // Description: + // These are function pointer types for the pipeline connection + // callbacks. See furhter documentation on each individual callback. + typedef void (*UpdateInformationCallbackType)(void*); + typedef int (*PipelineModifiedCallbackType)(void*); + typedef int* (*WholeExtentCallbackType)(void*); + typedef double* (*SpacingCallbackType)(void*); + typedef double* (*OriginCallbackType)(void*); + typedef const char* (*ScalarTypeCallbackType)(void*); + typedef int (*NumberOfComponentsCallbackType)(void*); + typedef void (*PropagateUpdateExtentCallbackType)(void*, int*); + typedef void (*UpdateDataCallbackType)(void*); + typedef int* (*DataExtentCallbackType)(void*); + typedef void* (*BufferPointerCallbackType)(void*); + + // Description: + // Set/Get the callback for propagating UpdateInformation calls to a + // third-party pipeline. The callback should make sure that the + // third-party pipeline information is up to date. + vtkSetMacro(UpdateInformationCallback, UpdateInformationCallbackType); + vtkGetMacro(UpdateInformationCallback, UpdateInformationCallbackType); + + // Description: + // Set/Get the callback for checking whether the third-party + // pipeline has been modified since the last invocation of the + // callback. The callback should return 1 for modified, and 0 for + // not modified. The first call should always return modified. + vtkSetMacro(PipelineModifiedCallback, PipelineModifiedCallbackType); + vtkGetMacro(PipelineModifiedCallback, PipelineModifiedCallbackType); + + // Description: + // Set/Get the callback for getting the whole extent of the input + // image from a third-party pipeline. The callback should return a + // vector of six integers describing the extent of the whole image + // (x1 x2 y1 y2 z1 z2). + vtkSetMacro(WholeExtentCallback, WholeExtentCallbackType); + vtkGetMacro(WholeExtentCallback, WholeExtentCallbackType); + + // Description: + // Set/Get the callback for getting the spacing of the input image + // from a third-party pipeline. The callback should return a vector + // of three double values describing the spacing (dx dy dz). + vtkSetMacro(SpacingCallback, SpacingCallbackType); + vtkGetMacro(SpacingCallback, SpacingCallbackType); + + // Description: + // Set/Get the callback for getting the origin of the input image + // from a third-party pipeline. The callback should return a vector + // of three double values describing the origin (x0 y0 z0). + vtkSetMacro(OriginCallback, OriginCallbackType); + vtkGetMacro(OriginCallback, OriginCallbackType); + + // Description: + // Set/Get the callback for getting the scalar value type of the + // input image from a third-party pipeline. The callback should + // return a string with the name of the type. + vtkSetMacro(ScalarTypeCallback, ScalarTypeCallbackType); + vtkGetMacro(ScalarTypeCallback, ScalarTypeCallbackType); + + // Description: + // Set/Get the callback for getting the number of components of the + // input image from a third-party pipeline. The callback should + // return an integer with the number of components. + vtkSetMacro(NumberOfComponentsCallback, NumberOfComponentsCallbackType); + vtkGetMacro(NumberOfComponentsCallback, NumberOfComponentsCallbackType); + + // Description: + // Set/Get the callback for propagating the pipeline update extent + // to a third-party pipeline. The callback should take a vector of + // six integers describing the extent. This should cause the + // third-party pipeline to provide data which contains at least this + // extent after the next UpdateData callback. + vtkSetMacro(PropagateUpdateExtentCallback,PropagateUpdateExtentCallbackType); + vtkGetMacro(PropagateUpdateExtentCallback,PropagateUpdateExtentCallbackType); + + // Description: + // Set/Get the callback for propagating UpdateData calls to a + // third-party pipeline. The callback should make sure the + // third-party pipeline is up to date. + vtkSetMacro(UpdateDataCallback, UpdateDataCallbackType); + vtkGetMacro(UpdateDataCallback, UpdateDataCallbackType); + + // Description: + // Set/Get the callback for getting the data extent of the input + // image from a third-party pipeline. The callback should return a + // vector of six integers describing the extent of the buffered + // portion of the image (x1 x2 y1 y2 z1 z2). The buffer location + // should be set with the BufferPointerCallback. + vtkSetMacro(DataExtentCallback, DataExtentCallbackType); + vtkGetMacro(DataExtentCallback, DataExtentCallbackType); + + // Description: + // Set/Get the callback for getting a pointer to the data buffer of + // an image from a third-party pipeline. The callback should return + // a pointer to the beginning of the buffer. The extent of the + // buffer should be set with the DataExtentCallback. + vtkSetMacro(BufferPointerCallback, BufferPointerCallbackType); + vtkGetMacro(BufferPointerCallback, BufferPointerCallbackType); + + // Description: + // Set/Get the user data which will be passed as the first argument + // to all of the third-party pipeline callbacks. + vtkSetMacro(CallbackUserData, void*); + vtkGetMacro(CallbackUserData, void*); + + //ETX + + // Description: + // Invoke the appropriate callbacks + int InvokePipelineModifiedCallbacks(); + void InvokeUpdateInformationCallbacks(); + void InvokeExecuteInformationCallbacks(); + void InvokeExecuteDataCallbacks(); + void LegacyCheckWholeExtent(); + +protected: + vtkImageImport(); + ~vtkImageImport(); + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + + void *ImportVoidPointer; + int SaveUserArray; + + int NumberOfScalarComponents; + int DataScalarType; + + int WholeExtent[6]; + int DataExtent[6]; + double DataSpacing[3]; + double DataOrigin[3]; + + void* CallbackUserData; + + //BTX + UpdateInformationCallbackType UpdateInformationCallback; + PipelineModifiedCallbackType PipelineModifiedCallback; + WholeExtentCallbackType WholeExtentCallback; + SpacingCallbackType SpacingCallback; + OriginCallbackType OriginCallback; + ScalarTypeCallbackType ScalarTypeCallback; + NumberOfComponentsCallbackType NumberOfComponentsCallback; + PropagateUpdateExtentCallbackType PropagateUpdateExtentCallback; + UpdateDataCallbackType UpdateDataCallback; + DataExtentCallbackType DataExtentCallback; + BufferPointerCallbackType BufferPointerCallback; + //ETX + + virtual void ExecuteData(vtkDataObject *d); + +private: + vtkImageImport(const vtkImageImport&); // Not implemented. + void operator=(const vtkImageImport&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageImportExecutive.cxx b/Imaging/vtkImageImportExecutive.cxx new file mode 100644 index 0000000..6fb0cb3 --- /dev/null +++ b/Imaging/vtkImageImportExecutive.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageImportExecutive.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageImportExecutive.h" + +#include "vtkInformationIntegerKey.h" +#include "vtkInformationIntegerVectorKey.h" +#include "vtkObjectFactory.h" + +#include "vtkAlgorithm.h" +#include "vtkAlgorithmOutput.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkImageImport.h" + +vtkCxxRevisionMacro(vtkImageImportExecutive, "$Revision: 1.2.6.1 $"); +vtkStandardNewMacro(vtkImageImportExecutive); + +//---------------------------------------------------------------------------- +int vtkImageImportExecutive::ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + if(this->Algorithm && request->Has(REQUEST_INFORMATION())) + { + // Invoke the callback + vtkImageImport *ii = vtkImageImport::SafeDownCast(this->Algorithm); + ii->InvokeUpdateInformationCallbacks(); + } + + return this->Superclass::ProcessRequest(request, inInfoVec, outInfoVec); +} diff --git a/Imaging/vtkImageImportExecutive.h b/Imaging/vtkImageImportExecutive.h new file mode 100644 index 0000000..5ac3a1b --- /dev/null +++ b/Imaging/vtkImageImportExecutive.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageImportExecutive.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageImportExecutive - +// .SECTION Description +// vtkImageImportExecutive + +#ifndef __vtkImageImportExecutive_h +#define __vtkImageImportExecutive_h + +#include "vtkStreamingDemandDrivenPipeline.h" + +class VTK_IMAGING_EXPORT vtkImageImportExecutive : + public vtkStreamingDemandDrivenPipeline +{ +public: + static vtkImageImportExecutive* New(); + vtkTypeRevisionMacro(vtkImageImportExecutive, + vtkStreamingDemandDrivenPipeline); + + // Description: + // Override to implement some requests with callbacks. + virtual int ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfo, + vtkInformationVector* outInfo); + +protected: + vtkImageImportExecutive() {}; + ~vtkImageImportExecutive() {}; + +private: + vtkImageImportExecutive(const vtkImageImportExecutive&); // Not implemented. + void operator=(const vtkImageImportExecutive&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageIslandRemoval2D.cxx b/Imaging/vtkImageIslandRemoval2D.cxx new file mode 100644 index 0000000..c57b444 --- /dev/null +++ b/Imaging/vtkImageIslandRemoval2D.cxx @@ -0,0 +1,547 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIslandRemoval2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageIslandRemoval2D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageIslandRemoval2D, "$Revision: 1.48 $"); +vtkStandardNewMacro(vtkImageIslandRemoval2D); + +//---------------------------------------------------------------------------- +// Constructor: Sets default filter to be identity. +vtkImageIslandRemoval2D::vtkImageIslandRemoval2D() +{ + this->AreaThreshold = 0; + this->SetAreaThreshold(4); + this->SquareNeighborhood = 1; + this->SquareNeighborhoodOff(); + this->ReplaceValue = 0; + this->SetReplaceValue(255); + this->IslandValue = 255; + this->SetIslandValue(0); +} + +//---------------------------------------------------------------------------- +void vtkImageIslandRemoval2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "AreaThreshold: " << this->AreaThreshold; + if (this->SquareNeighborhood) + { + os << indent << "Neighborhood: Square"; + } + else + { + os << indent << "Neighborhood: Cross"; + } + os << indent << "IslandValue: " << this->IslandValue; + os << indent << "ReplaceValue: " << this->ReplaceValue; + +} + + + + +//---------------------------------------------------------------------------- +// The templated execute function handles all the data types. +// Codes: 0 => unvisited. 1 => visted don't know. +// 2 => visted keep. 3 => visited replace. +// Please excuse the length of this function. The easiest way to choose +// neighborhoods is to check neighbors one by one directly. Also, I did +// not want to break the templated function into pieces. +template +void vtkImageIslandRemoval2DExecute(vtkImageIslandRemoval2D *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6]) +{ + int outIdx0, outIdx1, outIdx2; + vtkIdType outInc0, outInc1, outInc2; + T *outPtr0, *outPtr1, *outPtr2; + vtkIdType inInc0, inInc1, inInc2; + T *inPtr0, *inPtr1, *inPtr2; + vtkImage2DIslandPixel *pixels; // All the pixels visited so far. + int numPixels; // The number of pixels visited so far. + vtkImage2DIslandPixel *newPixel; // The last pixel in the list. + int nextPixelIdx; // The index of the next pixel to grow. + vtkImage2DIslandPixel *nextPixel; // The next pixel to grow. + int keepValue; + int area; + int squareNeighborhood; + T islandValue; + T replaceValue; + T *inNeighborPtr, *outNeighborPtr; + int idxC, maxC; + unsigned long count = 0; + unsigned long target; + + squareNeighborhood = self->GetSquareNeighborhood(); + area = self->GetAreaThreshold(); + islandValue = (T)(self->GetIslandValue()); + replaceValue = (T)(self->GetReplaceValue()); + // In case all 8 neighbors get added before we test the number. + pixels = new vtkImage2DIslandPixel [area + 8]; + + outData->GetIncrements(outInc0, outInc1, outInc2); + inData->GetIncrements(inInc0, inInc1, inInc2); + maxC = outData->GetNumberOfScalarComponents(); + + // Loop through pixels setting all output to 0 (unvisited). + for (idxC = 0; idxC < maxC; idxC++) + { + outPtr2 = outPtr + idxC; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + outPtr1 = outPtr2; + for (outIdx1 = outExt[2]; outIdx1 <= outExt[3]; ++outIdx1) + { + outPtr0 = outPtr1; + for (outIdx0 = outExt[0]; outIdx0 <= outExt[1]; ++outIdx0) + { + *outPtr0 = (T)(0); // Unvisited + outPtr0 += outInc0; + } + outPtr1 += outInc1; + } + outPtr2 += outInc2; + } + } + + // update the progress and possibly abort + self->UpdateProgress(0.1); + if (self->AbortExecute) + { + return; + } + + target = (unsigned long)(maxC*(outExt[5]-outExt[4]+1)* + (outExt[3]-outExt[2]+1)/50.0); + target++; + + // Loop though all pixels looking for islands + for (idxC = 0; idxC < maxC; idxC++) + { + outPtr2 = outPtr + idxC; + inPtr2 = inPtr + idxC; + for (outIdx2 = outExt[4]; + !self->AbortExecute && outIdx2 <= outExt[5]; ++outIdx2) + { + if (!(count%target)) + { + self->UpdateProgress(0.1 + 0.8*count/(50.0*target)); + } + count++; + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outExt[2]; outIdx1 <= outExt[3]; ++outIdx1) + { + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = outExt[0]; outIdx0 <= outExt[1]; ++outIdx0) + { + if (*outPtr0 == 0) + { + if (*inPtr0 != islandValue) + { + // not an island, keep and go on + *outPtr0 = 2; + } + else + { + + // Start an island search + // Save first pixel. + newPixel = pixels; + newPixel->inPtr = (void *)(inPtr0); + newPixel->outPtr = (void *)(outPtr0); + newPixel->idx0 = outIdx0; + newPixel->idx1 = outIdx1; + numPixels = 1; + nextPixelIdx = 0; + nextPixel = pixels; + *outPtr0 = 1; // visited don't know + keepValue = 1; + // breadth first search + while (keepValue == 1) // don't know + { + // Check all the neighbors + // left + if (nextPixel->idx0 > outExt[0]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) - inInc0; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) - outInc0; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0 - 1; + newPixel->idx1 = nextPixel->idx1; + *outNeighborPtr = 1; // visited don't know + } + } + } + // right + if (nextPixel->idx0 < outExt[1]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) + inInc0; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) + outInc0; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0 + 1; + newPixel->idx1 = nextPixel->idx1; + *outNeighborPtr = 1; // visited don't know + } + } + } + // up + if (nextPixel->idx1 > outExt[2]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) - inInc1; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) - outInc1; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0; + newPixel->idx1 = nextPixel->idx1 - 1; + *outNeighborPtr = 1; // visited don't know + } + } + } + // down + if (nextPixel->idx1 < outExt[3]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) + inInc1; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) + outInc1; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0; + newPixel->idx1 = nextPixel->idx1 + 1; + *outNeighborPtr = 1; // visited don't know + } + } + } + // Corners + if (squareNeighborhood) + { + // upper left + if (nextPixel->idx0 > outExt[0] && nextPixel->idx1 > outExt[2]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) - inInc0 - inInc1; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) - outInc0 -outInc1; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0 - 1; + newPixel->idx1 = nextPixel->idx1 - 1; + *outNeighborPtr = 1; // visited don't know + } + } + } + // upper right + if (nextPixel->idx0 < outExt[1] && nextPixel->idx1 > outExt[2]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) + inInc0 - inInc1; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) + outInc0 -outInc1; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0 + 1; + newPixel->idx1 = nextPixel->idx1 - 1; + *outNeighborPtr = 1; // visited don't know + } + } + } + // lower left + if (nextPixel->idx0 > outExt[0] && nextPixel->idx1 < outExt[3]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) - inInc0 + inInc1; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) - outInc0 +outInc1; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0 - 1; + newPixel->idx1 = nextPixel->idx1 + 1; + *outNeighborPtr = 1; // visited don't know + } + } + } + // lower right + if (nextPixel->idx0 < outExt[1] && nextPixel->idx1 < outExt[3]) + { + inNeighborPtr = (T *)(nextPixel->inPtr) + inInc0 + inInc1; + if ( *inNeighborPtr == islandValue) + { + outNeighborPtr = (T *)(nextPixel->outPtr) + outInc0 +outInc1; + if ( *outNeighborPtr == 2) + { + // This is part of a bigger island. + keepValue = 2; + } + if ( *outNeighborPtr == 0) + { + // New pixel to add + ++newPixel; + ++numPixels; + newPixel->inPtr = (void *)(inNeighborPtr); + newPixel->outPtr = (void *)(outNeighborPtr); + newPixel->idx0 = nextPixel->idx0 + 1; + newPixel->idx1 = nextPixel->idx1 + 1; + *outNeighborPtr = 1; // visited don't know + } + } + } + } + + // Move to the next pixel to grow. + ++nextPixel; + ++nextPixelIdx; + + // Have we visted enogh pixels to determine this is a keeper? + if (keepValue == 1 && numPixels >= area) + { + keepValue = 2; + } + + // Have we run out of pixels to grow? + if (keepValue == 1 && nextPixelIdx >= numPixels) + { + // The island is too small. Set island values too replace. + keepValue = 3; + } + } + + // Change "don't knows" to keep value + nextPixel = pixels; + for (nextPixelIdx = 0; nextPixelIdx < numPixels; ++nextPixelIdx) + { + *((T *)(nextPixel->outPtr)) = keepValue; + ++nextPixel; + } + } + } + + outPtr0 += outInc0; + inPtr0 += inInc0; + } + outPtr1 += outInc1; + inPtr1 += inInc1; + } + outPtr2 += outInc2; + inPtr2 += inInc2; + } + } + + delete [] pixels; + + // update the progress and possibly abort + self->UpdateProgress(0.9); + if (self->AbortExecute) + { + return; + } + + // Loop though all pixels actually copying and replacing. + for (idxC = 0; idxC < maxC; idxC++) + { + outPtr2 = outPtr + idxC; + inPtr2 = inPtr + idxC; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outExt[2]; outIdx1 <= outExt[3]; ++outIdx1) + { + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = outExt[0]; outIdx0 <= outExt[1]; ++outIdx0) + { + if (*outPtr0 == 3) + { + *outPtr0 = replaceValue; + } + else + { + *outPtr0 = *inPtr0; + } + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + } +} + + +//---------------------------------------------------------------------------- +// This method uses the input data to fill the output data. +// It can handle any type data, but the two datas must have the same +// data type. Assumes that in and out have the same lower extent. +int vtkImageIslandRemoval2D::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int outExt[6]; + + // get the data object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int wholeExtent[6]; + int extent[6]; + + // We need to allocate our own scalars. + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent); + extent[0] = wholeExtent[0]; + extent[1] = wholeExtent[1]; + extent[2] = wholeExtent[2]; + extent[3] = wholeExtent[3]; + outData->SetExtent(extent); + outData->AllocateScalars(); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << vtkImageScalarTypeNameMacro(inData->GetScalarType()) + << ", must match out ScalarType " + << vtkImageScalarTypeNameMacro(outData->GetScalarType())); + return 1; + } + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); + void *inPtr = inData->GetScalarPointerForExtent(outExt); + void *outPtr = outData->GetScalarPointerForExtent(outExt); + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageIslandRemoval2DExecute( this, inData, + (VTK_TT *)(inPtr), outData, + (VTK_TT *)(outPtr), outExt)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 1; + } + + return 1; +} + + + + + + + + + + + + + + + + diff --git a/Imaging/vtkImageIslandRemoval2D.h b/Imaging/vtkImageIslandRemoval2D.h new file mode 100644 index 0000000..ff324f1 --- /dev/null +++ b/Imaging/vtkImageIslandRemoval2D.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIslandRemoval2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageIslandRemoval2D - Removes small clusters in masks. +// .SECTION Description +// vtkImageIslandRemoval2D computes the area of separate islands in +// a mask image. It removes any island that has less than AreaThreshold +// pixels. Output has the same ScalarType as input. It generates +// the whole 2D output image for any output request. + + +#ifndef __vtkImageIslandRemoval2D_h +#define __vtkImageIslandRemoval2D_h + + +#include "vtkImageAlgorithm.h" + +//BTX +typedef struct{ + void *inPtr; + void *outPtr; + int idx0; + int idx1; + } vtkImage2DIslandPixel; +//ETX + +class VTK_IMAGING_EXPORT vtkImageIslandRemoval2D : public vtkImageAlgorithm +{ +public: + // Description: + // Constructor: Sets default filter to be identity. + static vtkImageIslandRemoval2D *New(); + vtkTypeRevisionMacro(vtkImageIslandRemoval2D,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the cutoff area for removal + vtkSetMacro(AreaThreshold, int); + vtkGetMacro(AreaThreshold, int); + + // Description: + // Set/Get whether to use 4 or 8 neighbors + vtkSetMacro(SquareNeighborhood, int); + vtkGetMacro(SquareNeighborhood, int); + vtkBooleanMacro(SquareNeighborhood, int); + + // Description: + // Set/Get the value to remove. + vtkSetMacro(IslandValue, double); + vtkGetMacro(IslandValue, double); + + // Description: + // Set/Get the value to put in the place of removed pixels. + vtkSetMacro(ReplaceValue, double); + vtkGetMacro(ReplaceValue, double); + +protected: + vtkImageIslandRemoval2D(); + ~vtkImageIslandRemoval2D() {}; + + int AreaThreshold; + int SquareNeighborhood; + double IslandValue; + double ReplaceValue; + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + +private: + vtkImageIslandRemoval2D(const vtkImageIslandRemoval2D&); // Not implemented. + void operator=(const vtkImageIslandRemoval2D&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageIterateFilter.cxx b/Imaging/vtkImageIterateFilter.cxx new file mode 100644 index 0000000..816175e --- /dev/null +++ b/Imaging/vtkImageIterateFilter.cxx @@ -0,0 +1,252 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIterateFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageIterateFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageIterateFilter, "$Revision: 1.39 $"); + +//---------------------------------------------------------------------------- +vtkImageIterateFilter::vtkImageIterateFilter() +{ + // for filters that execute multiple times + this->Iteration = 0; + this->NumberOfIterations = 0; + this->IterationData = NULL; + this->SetNumberOfIterations(1); + this->InputVector = vtkInformationVector::New(); + this->OutputVector = vtkInformationVector::New(); +} + +//---------------------------------------------------------------------------- +vtkImageIterateFilter::~vtkImageIterateFilter() +{ + this->SetNumberOfIterations(0); + this->InputVector->Delete(); + this->OutputVector->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkImageIterateFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "NumberOfIterations: " << this->NumberOfIterations << "\n"; + + // This variable is included here to pass the PrintSelf test. + // The variable is public to get around a compiler issue. + // this->Iteration +} + + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageIterateFilter::GetIterationInput() +{ + if (this->IterationData == NULL || this->Iteration == 0) + { + // error, or return input ??? + return vtkImageData::SafeDownCast(this->GetInput()); + } + return this->IterationData[this->Iteration]; +} + + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageIterateFilter::GetIterationOutput() +{ + if (this->IterationData == NULL || + this->Iteration == this->NumberOfIterations-1) + { + // error, or return output ??? + return this->GetOutput(); + } + return this->IterationData[this->Iteration+1]; +} + +//---------------------------------------------------------------------------- +int +vtkImageIterateFilter +::RequestInformation(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkImageData* input = + vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData* output = + vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + this->IterationData[0] = input; + this->IterationData[this->NumberOfIterations] = output; + + vtkInformation* in = inInfo; + for(int i=0; i < this->NumberOfIterations; ++i) + { + this->Iteration = i; + + vtkInformation* out = this->IterationData[i+1]->GetPipelineInformation(); + vtkDataObject* outData = out->Get(vtkDataObject::DATA_OBJECT()); + outData->CopyInformationToPipeline(request, in); + out->CopyEntry(in, vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + if (!this->IterativeRequestInformation(in, out)) + { + return 0; + } + + in = out; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int +vtkImageIterateFilter +::RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + vtkInformation* out = outputVector->GetInformationObject(0); + for(int i=this->NumberOfIterations-1; i >= 0; --i) + { + this->Iteration = i; + + vtkInformation* in = this->IterationData[i]->GetPipelineInformation(); + in->CopyEntry(out, vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + if (!this->IterativeRequestUpdateExtent(in, out)) + { + return 0; + } + + out = in; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageIterateFilter::RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector*) +{ + vtkInformation* in = inputVector[0]->GetInformationObject(0); + for(int i=0; i < this->NumberOfIterations; ++i) + { + this->Iteration = i; + + vtkInformation* out = this->IterationData[i+1]->GetPipelineInformation(); + vtkDataObject* outData = out->Get(vtkDataObject::DATA_OBJECT()); + outData->CopyInformationFromPipeline(request); + + this->InputVector->SetInformationObject(0, in); + this->OutputVector->SetInformationObject(0, out); + if (!this->IterativeRequestData(request, &this->InputVector, + this->OutputVector)) + { + return 0; + } + + if(in->Get(vtkDemandDrivenPipeline::RELEASE_DATA())) + { + vtkDataObject* inData = in->Get(vtkDataObject::DATA_OBJECT()); + inData->ReleaseData(); + } + + in = out; + } + this->InputVector->SetNumberOfInformationObjects(0); + this->OutputVector->SetNumberOfInformationObjects(0); + + return 1; +} + +//---------------------------------------------------------------------------- +// Called by the above for each decomposition. Subclass can modify +// the defaults by implementing this method. +int vtkImageIterateFilter::IterativeRequestInformation(vtkInformation*, + vtkInformation*) +{ + return 1; +} + +//---------------------------------------------------------------------------- +// Called by the above for each decomposition. Subclass can modify +// the defaults by implementing this method. +int vtkImageIterateFilter::IterativeRequestUpdateExtent(vtkInformation*, + vtkInformation*) +{ + return 1; +} + +//---------------------------------------------------------------------------- +// Called by the above for each decomposition. Subclass can modify +// the defaults by implementing this method. +int +vtkImageIterateFilter::IterativeRequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + return this->Superclass::RequestData(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +// Filters that execute multiple times per update use this internal method. +void vtkImageIterateFilter::SetNumberOfIterations(int num) +{ + int idx; + + if (num == this->NumberOfIterations) + { + return; + } + + // delete previous temporary caches + // (first and last are global input and output) + if (this->IterationData) + { + for (idx = 1; idx < this->NumberOfIterations; ++idx) + { + this->IterationData[idx]->Delete(); + this->IterationData[idx] = NULL; + } + delete [] this->IterationData; + this->IterationData = NULL; + } + + // special case for destructor + if (num == 0) + { + return; + } + + // create new ones (first and last set later to input and output) + this->IterationData = (vtkImageData **) new void *[num + 1]; + this->IterationData[0] = this->IterationData[num] = NULL; + for (idx = 1; idx < num; ++idx) + { + this->IterationData[idx] = vtkImageData::New(); + this->IterationData[idx]->ReleaseDataFlagOn(); + this->IterationData[idx]->GetProducerPort(); + } + + this->NumberOfIterations = num; + this->Modified(); +} diff --git a/Imaging/vtkImageIterateFilter.h b/Imaging/vtkImageIterateFilter.h new file mode 100644 index 0000000..4fb39b5 --- /dev/null +++ b/Imaging/vtkImageIterateFilter.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageIterateFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageIterateFilter - Multiple executes per update. +// .SECTION Description +// vtkImageIterateFilter is a filter superclass that supports calling execute +// multiple times per update. The largest hack/open issue is that the input +// and output caches are temporarily changed to "fool" the subclasses. I +// believe the correct solution is to pass the in and out cache to the +// subclasses methods as arguments. Now the data is passes. Can the caches +// be passed, and data retrieved from the cache? + +#ifndef __vtkImageIterateFilter_h +#define __vtkImageIterateFilter_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageIterateFilter : public vtkThreadedImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkImageIterateFilter,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get which iteration is current being performed. Normally the + // user will not access this method. + vtkGetMacro(Iteration,int); + vtkGetMacro(NumberOfIterations,int); + +protected: + vtkImageIterateFilter(); + ~vtkImageIterateFilter(); + + // Implement standard requests by calling iterative versions the + // specified number of times. + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // Iterative versions of standard requests. These are given the + // pipeline information object for the in/out pair at each + // iteration. + virtual int IterativeRequestInformation(vtkInformation* in, + vtkInformation* out); + virtual int IterativeRequestUpdateExtent(vtkInformation* in, + vtkInformation* out); + virtual int IterativeRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + virtual void SetNumberOfIterations(int num); + + // for filters that execute multiple times. + int NumberOfIterations; + int Iteration; + // A list of intermediate caches that is created when + // is called SetNumberOfIterations() + vtkImageData **IterationData; + + // returns correct vtkImageDatas based on current iteration. + vtkImageData *GetIterationInput(); + vtkImageData *GetIterationOutput(); + + vtkInformationVector* InputVector; + vtkInformationVector* OutputVector; +private: + vtkImageIterateFilter(const vtkImageIterateFilter&); // Not implemented. + void operator=(const vtkImageIterateFilter&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Imaging/vtkImageLaplacian.cxx b/Imaging/vtkImageLaplacian.cxx new file mode 100644 index 0000000..5e0e679 --- /dev/null +++ b/Imaging/vtkImageLaplacian.cxx @@ -0,0 +1,239 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLaplacian.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageLaplacian.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageLaplacian, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkImageLaplacian); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageLaplacian fitler. +vtkImageLaplacian::vtkImageLaplacian() +{ + this->Dimensionality = 2; +} + + +//---------------------------------------------------------------------------- +void vtkImageLaplacian::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Dimensionality: " << this->Dimensionality; +} + + +//---------------------------------------------------------------------------- +// Just clip the request. The subclass may need to overwrite this method. +int vtkImageLaplacian::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int idx; + int wholeExtent[6], inUExt[6]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inUExt); + + // update and Clip + for (idx = 0; idx < 3; ++idx) + { + --inUExt[idx*2]; + ++inUExt[idx*2+1]; + if (inUExt[idx*2] < wholeExtent[idx*2]) + { + inUExt[idx*2] = wholeExtent[idx*2]; + } + if (inUExt[idx*2] > wholeExtent[idx*2 + 1]) + { + inUExt[idx*2] = wholeExtent[idx*2 + 1]; + } + if (inUExt[idx*2+1] < wholeExtent[idx*2]) + { + inUExt[idx*2+1] = wholeExtent[idx*2]; + } + if (inUExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + inUExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inUExt, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageLaplacianExecute(vtkImageLaplacian *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int maxC, maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int axesNum; + int *wholeExtent; + vtkIdType *inIncs; + double r[3], d, sum; + int useZMin, useZMax, useYMin, useYMax, useXMin, useXMax; + + // find the region to loop over + maxC = inData->GetNumberOfScalarComponents(); + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get the dimensionality of the gradient. + axesNum = self->GetDimensionality(); + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // The data spacing is important for computing the Laplacian. + // Divided by dx twice (second derivative). + inData->GetSpacing(r); + r[0] = 1.0 / (r[0] * r[0]); + r[1] = 1.0 / (r[1] * r[1]); + r[2] = 1.0 / (r[2] * r[2]); + + // get some other info we need + inIncs = inData->GetIncrements(); + wholeExtent = inData->GetExtent(); + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + useZMin = ((idxZ + outExt[4]) <= wholeExtent[4]) ? 0 : -inIncs[2]; + useZMax = ((idxZ + outExt[4]) >= wholeExtent[5]) ? 0 : inIncs[2]; + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + useYMin = ((idxY + outExt[2]) <= wholeExtent[2]) ? 0 : -inIncs[1]; + useYMax = ((idxY + outExt[2]) >= wholeExtent[3]) ? 0 : inIncs[1]; + for (idxX = 0; idxX <= maxX; idxX++) + { + useXMin = ((idxX + outExt[0]) <= wholeExtent[0]) ? 0 : -inIncs[0]; + useXMax = ((idxX + outExt[0]) >= wholeExtent[1]) ? 0 : inIncs[0]; + for (idxC = 0; idxC < maxC; idxC++) + { + // do X axis + d = -2.0*(*inPtr); + d += (double)(inPtr[useXMin]); + d += (double)(inPtr[useXMax]); + sum = d * r[0]; + + // do y axis + d = -2.0*(*inPtr); + d += (double)(inPtr[useYMin]); + d += (double)(inPtr[useYMax]); + sum = sum + d * r[1]; + if (axesNum == 3) + { + // do z axis + d = -2.0*(*inPtr); + d += (double)(inPtr[useZMin]); + d += (double)(inPtr[useZMax]); + sum = sum + d * r[2]; + } + *outPtr = (T)sum; + inPtr++; + outPtr++; + } + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The output data +// must match input type. This method does handle boundary conditions. +void vtkImageLaplacian::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != + outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData[0][0]->GetScalarType() << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageLaplacianExecute( this, inData[0][0], + (VTK_TT *)(inPtr), outData[0], + (VTK_TT *)(outPtr), + outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + + + + + + + + + diff --git a/Imaging/vtkImageLaplacian.h b/Imaging/vtkImageLaplacian.h new file mode 100644 index 0000000..d93206e --- /dev/null +++ b/Imaging/vtkImageLaplacian.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLaplacian.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageLaplacian - Computes divergence of gradient. +// .SECTION Description +// vtkimageLaplacian computes the Laplacian (like a second derivative) +// of a scalar image. The operation is the same as taking the +// divergence after a gradient. Boundaries are handled, so the input +// is the same as the output. +// Dimensionality determines how the input regions are interpreted. +// (images, or volumes). The Dimensionality defaults to two. + + + +#ifndef __vtkimageLaplacian_h +#define __vtkimageLaplacian_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageLaplacian : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageLaplacian *New(); + vtkTypeRevisionMacro(vtkImageLaplacian,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Determines how the input is interpreted (set of 2d slices ...) + vtkSetClampMacro(Dimensionality,int,2,3); + vtkGetMacro(Dimensionality,int); + +protected: + vtkImageLaplacian(); + ~vtkImageLaplacian() {}; + + int Dimensionality; + + virtual int RequestUpdateExtent (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); +private: + vtkImageLaplacian(const vtkImageLaplacian&); // Not implemented. + void operator=(const vtkImageLaplacian&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageLogarithmicScale.cxx b/Imaging/vtkImageLogarithmicScale.cxx new file mode 100644 index 0000000..6ad937c --- /dev/null +++ b/Imaging/vtkImageLogarithmicScale.cxx @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLogarithmicScale.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageLogarithmicScale.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImageLogarithmicScale, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkImageLogarithmicScale); + +//---------------------------------------------------------------------------- +// Constructor sets default values +vtkImageLogarithmicScale::vtkImageLogarithmicScale() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + this->Constant = 10.0; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageLogarithmicScaleExecute(vtkImageLogarithmicScale *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + double c; + + c = self->GetConstant(); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // Pixel operation + if (*inSI > 0) + { + *outSI = (T)(c*log((double)(*inSI)+1.0)); + } + else + { + *outSI = (T)(-c*log(1.0-(double)(*inSI))); + } + + outSI++; + inSI++; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + + +//---------------------------------------------------------------------------- +// This method is passed a input and output region, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageLogarithmicScale::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData->GetScalarType() + << ", must match out ScalarType " + << outData->GetScalarType()); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageLogarithmicScaleExecute(this, inData, + outData, outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown input ScalarType"); + return; + } +} + +void vtkImageLogarithmicScale::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Constant: " << this->Constant << "\n"; +} + diff --git a/Imaging/vtkImageLogarithmicScale.h b/Imaging/vtkImageLogarithmicScale.h new file mode 100644 index 0000000..0ec35a7 --- /dev/null +++ b/Imaging/vtkImageLogarithmicScale.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLogarithmicScale.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageLogarithmicScale - Passes each pixel through log function. +// .SECTION Description +// vtkImageLogarithmicScale passes each pixel through the function +// c*log(1+x). It also handles negative values with the function +// -c*log(1-x). + + + +#ifndef __vtkImageLogarithmicScale_h +#define __vtkImageLogarithmicScale_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageLogarithmicScale : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageLogarithmicScale *New(); + vtkTypeRevisionMacro(vtkImageLogarithmicScale,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the scale factor for the logarithmic function. + vtkSetMacro(Constant,double); + vtkGetMacro(Constant,double); + +protected: + vtkImageLogarithmicScale(); + ~vtkImageLogarithmicScale() {}; + + double Constant; + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int outExt[6], int id); +private: + vtkImageLogarithmicScale(const vtkImageLogarithmicScale&); // Not implemented. + void operator=(const vtkImageLogarithmicScale&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageLogic.cxx b/Imaging/vtkImageLogic.cxx new file mode 100644 index 0000000..9d4308e --- /dev/null +++ b/Imaging/vtkImageLogic.cxx @@ -0,0 +1,290 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLogic.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageLogic.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImageLogic, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkImageLogic); + +//---------------------------------------------------------------------------- +vtkImageLogic::vtkImageLogic() +{ + this->SetNumberOfInputPorts(2); + this->SetNumberOfOutputPorts(1); + this->Operation = VTK_AND; + this->OutputTrueValue = 255; +} + + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the one input operations +template +void vtkImageLogicExecute1(vtkImageLogic *self, vtkImageData *inData, + vtkImageData *outData, int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + T trueValue = (T)(self->GetOutputTrueValue()); + int op = self->GetOperation(); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + // Pixel operation + switch (op) + { + case VTK_NOT: + while (outSI != outSIEnd) + { + if ( ! *inSI) + { + *outSI = trueValue; + } + else + { + *outSI = 0; + } + outSI++; + inSI++; + } + break; + case VTK_NOP: + while (outSI != outSIEnd) + { + if (*inSI) + { + *outSI = trueValue; + } + else + { + *outSI = 0; + } + outSI++; + inSI++; + } + break; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the two input operations +template +void vtkImageLogicExecute2(vtkImageLogic *self, vtkImageData *in1Data, + vtkImageData *in2Data, vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt1(in1Data, outExt); + vtkImageIterator inIt2(in2Data, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + T trueValue = (T)(self->GetOutputTrueValue()); + int op = self->GetOperation(); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI1 = inIt1.BeginSpan(); + T* inSI2 = inIt2.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + // Pixel operation + switch (op) + { + case VTK_AND: + while (outSI != outSIEnd) + { + if (*inSI1 && *inSI2) + { + *outSI = trueValue; + } + else + { + *outSI = 0; + } + outSI++; + inSI1++; + inSI2++; + } + break; + case VTK_OR: + while (outSI != outSIEnd) + { + if (*inSI1 || *inSI2) + { + *outSI = trueValue; + } + else + { + *outSI = 0; + } + outSI++; + inSI1++; + inSI2++; + } + break; + case VTK_XOR: + while (outSI != outSIEnd) + { + if (( ! *inSI1 && *inSI2) || (*inSI1 && ! *inSI2)) + { + *outSI = trueValue; + } + else + { + *outSI = 0; + } + outSI++; + inSI1++; + inSI2++; + } + break; + case VTK_NAND: + while (outSI != outSIEnd) + { + if ( ! (*inSI1 && *inSI2)) + { + *outSI = trueValue; + } + else + { + *outSI = 0; + } + outSI++; + inSI1++; + inSI2++; + } + break; + case VTK_NOR: + while (outSI != outSIEnd) + { + if ( ! (*inSI1 || *inSI2)) + { + *outSI = trueValue; + } + else + { + *outSI = 0; + } + outSI++; + inSI1++; + inSI2++; + } + break; + } + inIt1.NextSpan(); + inIt2.NextSpan(); + outIt.NextSpan(); + } +} + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageLogic::ThreadedRequestData ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + if (inData[0][0] == NULL) + { + vtkErrorMacro(<< "Input " << 0 << " must be specified."); + return; + } + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + if (this->Operation == VTK_NOT || this->Operation == VTK_NOP) + { + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageLogicExecute1(this, inData[0][0], + outData[0], outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + else + { + if (inData[1][0] == NULL) + { + vtkErrorMacro(<< "Input " << 1 << " must be specified."); + return; + } + + // this filter expects that inputs that have the same number of components + if (inData[0][0]->GetNumberOfScalarComponents() != + inData[1][0]->GetNumberOfScalarComponents()) + { + vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, " + << inData[0][0]->GetNumberOfScalarComponents() + << ", must match out input2 NumberOfScalarComponents " + << inData[1][0]->GetNumberOfScalarComponents()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageLogicExecute2( this, inData[0][0], + inData[1][0], outData[0], outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } +} + +void vtkImageLogic::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Operation: " << this->Operation << "\n"; + + os << indent << "OutputTrueValue: " << this->OutputTrueValue << "\n"; +} + diff --git a/Imaging/vtkImageLogic.h b/Imaging/vtkImageLogic.h new file mode 100644 index 0000000..81420c8 --- /dev/null +++ b/Imaging/vtkImageLogic.h @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLogic.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageLogic - And, or, xor, nand, nor, not. +// .SECTION Description +// vtkImageLogic implements basic logic operations. +// SetOperation is used to select the filter's behavior. +// The filter can take two or one input. Inputs must have the same type. + + +#ifndef __vtkImageLogic_h +#define __vtkImageLogic_h + + +// Operation options. +#define VTK_AND 0 +#define VTK_OR 1 +#define VTK_XOR 2 +#define VTK_NAND 3 +#define VTK_NOR 4 +#define VTK_NOT 5 +#define VTK_NOP 6 + + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageLogic : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageLogic *New(); + vtkTypeRevisionMacro(vtkImageLogic,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the Operation to perform. + vtkSetMacro(Operation,int); + vtkGetMacro(Operation,int); + void SetOperationToAnd() {this->SetOperation(VTK_AND);}; + void SetOperationToOr() {this->SetOperation(VTK_OR);}; + void SetOperationToXor() {this->SetOperation(VTK_XOR);}; + void SetOperationToNand() {this->SetOperation(VTK_NAND);}; + void SetOperationToNor() {this->SetOperation(VTK_NOR);}; + void SetOperationToNot() {this->SetOperation(VTK_NOT);}; + + // Description: + // Set the value to use for true in the output. + vtkSetMacro(OutputTrueValue, double); + vtkGetMacro(OutputTrueValue, double); + + // Description: + // Set the Input1 of this filter. + virtual void SetInput1(vtkDataObject *input) { this->SetInput(0,input);}; + + // Description: + // Set the Input2 of this filter. + virtual void SetInput2(vtkDataObject *input) { this->SetInput(1,input);}; + +protected: + vtkImageLogic(); + ~vtkImageLogic() {}; + + int Operation; + double OutputTrueValue; + + void ThreadedRequestData (vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); + +private: + vtkImageLogic(const vtkImageLogic&); // Not implemented. + void operator=(const vtkImageLogic&); // Not implemented. +}; + +#endif + + + + + + + + + + + + + diff --git a/Imaging/vtkImageLuminance.cxx b/Imaging/vtkImageLuminance.cxx new file mode 100644 index 0000000..cacb822 --- /dev/null +++ b/Imaging/vtkImageLuminance.cxx @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLuminance.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageLuminance.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageLuminance, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkImageLuminance); + +//---------------------------------------------------------------------------- +vtkImageLuminance::vtkImageLuminance() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +// This method overrides information set by parent's ExecuteInformation. +int vtkImageLuminance::RequestInformation ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector * outputVector) +{ + vtkDataObject::SetPointDataActiveScalarInfo( + outputVector->GetInformationObject(0), -1, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageLuminanceExecute(vtkImageLuminance *self, vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + float luminance; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // now process the components + luminance = 0.30 * *inSI++; + luminance += 0.59 * *inSI++; + luminance += 0.11 * *inSI++; + *outSI = static_cast(luminance); + ++outSI; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The output data +// must match input type. This method does handle boundary conditions. +void vtkImageLuminance::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (inData->GetNumberOfScalarComponents() != 3) + { + vtkErrorMacro(<< "Execute: input must have 3 components, but has " + << inData->GetNumberOfScalarComponents()); + return; + } + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", must match out ScalarType " << outData->GetScalarType()); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageLuminanceExecute( this, inData, outData, + outExt, id, static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + + + + + + + + diff --git a/Imaging/vtkImageLuminance.h b/Imaging/vtkImageLuminance.h new file mode 100644 index 0000000..86539a2 --- /dev/null +++ b/Imaging/vtkImageLuminance.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageLuminance.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageLuminance - Computes the luminance of the input +// .SECTION Description +// vtkImageLuminance calculates luminance from an rgb input. + +#ifndef __vtkImageLuminance_h +#define __vtkImageLuminance_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageLuminance : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageLuminance *New(); + vtkTypeRevisionMacro(vtkImageLuminance,vtkThreadedImageAlgorithm); + +protected: + vtkImageLuminance(); + ~vtkImageLuminance() {}; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, + vtkInformationVector *); + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int outExt[6], int id); + +private: + vtkImageLuminance(const vtkImageLuminance&); // Not implemented. + void operator=(const vtkImageLuminance&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageMagnify.cxx b/Imaging/vtkImageMagnify.cxx new file mode 100644 index 0000000..e47985e --- /dev/null +++ b/Imaging/vtkImageMagnify.cxx @@ -0,0 +1,338 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMagnify.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMagnify.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageMagnify, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkImageMagnify); + +//---------------------------------------------------------------------------- +// Constructor: Sets default filter to be identity. +vtkImageMagnify::vtkImageMagnify() +{ + this->Interpolate = 0; + + this->MagnificationFactors[0] = + this->MagnificationFactors[1] = + this->MagnificationFactors[2] = 1; +} + +//---------------------------------------------------------------------------- +// Computes any global image information associated with regions. +int vtkImageMagnify::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + double spacing[3]; + int idx; + double outSpacing[3]; + int inExt[6], outExt[6]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt); + inInfo->Get(vtkDataObject::SPACING(), spacing); + + for (idx = 0; idx < 3; idx++) + { + // Scale the output extent + outExt[idx*2] = inExt[idx*2] * this->MagnificationFactors[idx]; + outExt[idx*2+1] = outExt[idx*2] + + (inExt[idx*2+1] - inExt[idx*2] + 1)*this->MagnificationFactors[idx] - 1; + + // Change the data spacing + outSpacing[idx] = spacing[idx] / (double)(this->MagnificationFactors[idx]); + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),outExt,6); + outInfo->Set(vtkDataObject::SPACING(),outSpacing,3); + + return 1; +} + +//---------------------------------------------------------------------------- +// This method computes the Region of input necessary to generate outRegion. +// It assumes offset and size are multiples of Magnify Factors. +int vtkImageMagnify::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int outExt[6], inExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); + + this->InternalRequestUpdateExtent(inExt, outExt); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + return 1; +} + +void vtkImageMagnify::InternalRequestUpdateExtent(int *inExt, int *outExt) +{ + int idx; + + for (idx = 0; idx < 3; idx++) + { + // For Min. Round Down + inExt[idx*2] = (int)(floor((double)(outExt[idx*2]) / + (double)(this->MagnificationFactors[idx]))); + inExt[idx*2+1] = (int)(floor((double)(outExt[idx*2+1]) / + (double)(this->MagnificationFactors[idx]))); + } +} + +//---------------------------------------------------------------------------- +// The templated execute function handles all the data types. +// 2d even though operation is 1d. +// Note: Slight misalignment (pixel replication is not nearest neighbor). +template +void vtkImageMagnifyExecute(vtkImageMagnify *self, + vtkImageData *inData, T *inPtr, int inExt[6], + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int inIdxX, inIdxY, inIdxZ; + int inMaxX, inMaxY, inMaxZ; + int maxC, maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int interpolate; + int magXIdx, magX; + int magYIdx, magY; + int magZIdx, magZ; + T *inPtrZ, *inPtrY, *inPtrX, *outPtrC; + double iMag, iMagP = 0.0, iMagPY = 0.0, iMagPZ = 0.0, iMagPYZ = 0.0; + T dataP = 0, dataPX = 0, dataPY = 0, dataPZ = 0; + T dataPXY = 0, dataPXZ = 0, dataPYZ = 0, dataPXYZ = 0; + int interpSetup; + + interpolate = self->GetInterpolate(); + magX = self->GetMagnificationFactors()[0]; + magY = self->GetMagnificationFactors()[1]; + magZ = self->GetMagnificationFactors()[2]; + iMag = 1.0/(magX*magY*magZ); + + // find the region to loop over + maxC = outData->GetNumberOfScalarComponents(); + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)(maxC*(maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + inData->GetIncrements(inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // Now I am putting in my own boundary check because of ABRs and FMRs + // And I do not understand (nor do I care to figure out) what + // Ken is doing with his checks. (Charles) + inMaxX = inExt[1]; + inMaxY = inExt[3]; + inMaxZ = inExt[5]; + inData->GetExtent(idxC, inMaxX, idxC, inMaxY, idxC, inMaxZ); + + // Loop through ouput pixels + for (idxC = 0; idxC < maxC; idxC++) + { + inPtrZ = inPtr + idxC; + inIdxZ = inExt[4]; + outPtrC = outPtr + idxC; + magZIdx = magZ - outExt[4]%magZ - 1; + for (idxZ = 0; idxZ <= maxZ; idxZ++, magZIdx--) + { + inPtrY = inPtrZ; + inIdxY = inExt[2]; + magYIdx = magY - outExt[2]%magY - 1; + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++, magYIdx--) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + if (interpolate) + { + // precompute some values for interpolation + iMagP = (magYIdx + 1)*(magZIdx + 1)*iMag; + iMagPY = (magY - magYIdx - 1)*(magZIdx + 1)*iMag; + iMagPZ = (magYIdx + 1)*(magZ - magZIdx - 1)*iMag; + iMagPYZ = (magY - magYIdx - 1)*(magZ - magZIdx - 1)*iMag; + } + + magXIdx = magX - outExt[0]%magX - 1; + inPtrX = inPtrY; + inIdxX = inExt[0]; + interpSetup = 0; + for (idxX = 0; idxX <= maxX; idxX++, magXIdx--) + { + // Pixel operation + if (!interpolate) + { + *outPtrC = *inPtrX; + } + else + { + // setup data values for interp, overload dataP as an + // indicator of if this has been done yet + if (!interpSetup) + { + int tiX, tiY, tiZ; + + dataP = *inPtrX; + + // Now I am putting in my own boundary check because of + // ABRs and FMRs + // And I do not understand (nor do I care to figure out) what + // Ken was doing with his checks. (Charles) + if (inIdxX < inMaxX) + { + tiX = inIncX; + } + else + { + tiX = 0; + } + if (inIdxY < inMaxY) + { + tiY = inIncY; + } + else + { + tiY = 0; + } + if (inIdxZ < inMaxZ) + { + tiZ = inIncZ; + } + else + { + tiZ = 0; + } + dataPX = *(inPtrX + tiX); + dataPY = *(inPtrX + tiY); + dataPZ = *(inPtrX + tiZ); + dataPXY = *(inPtrX + tiX + tiY); + dataPXZ = *(inPtrX + tiX + tiZ); + dataPYZ = *(inPtrX + tiY + tiZ); + dataPXYZ = *(inPtrX + tiX + tiY + tiZ); + interpSetup = 1; + } + *outPtrC = (T) + ((double)dataP*(magXIdx + 1)*iMagP + + (double)dataPX*(magX - magXIdx - 1)*iMagP + + (double)dataPY*(magXIdx + 1)*iMagPY + + (double)dataPXY*(magX - magXIdx - 1)*iMagPY + + (double)dataPZ*(magXIdx + 1)*iMagPZ + + (double)dataPXZ*(magX - magXIdx - 1)*iMagPZ + + (double)dataPYZ*(magXIdx + 1)*iMagPYZ + + (double)dataPXYZ*(magX - magXIdx - 1)*iMagPYZ); + } + outPtrC += maxC; + if (!magXIdx) + { + inPtrX += inIncX; + ++inIdxX; + magXIdx = magX; + interpSetup = 0; + } + } + outPtrC += outIncY; + if (!magYIdx) + { + inPtrY += inIncY; + ++inIdxY; + magYIdx = magY; + } + } + outPtrC += outIncZ; + if (!magZIdx) + { + inPtrZ += inIncZ; + ++inIdxZ; + magZIdx = magZ; + } + } + } +} + +void vtkImageMagnify::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6]; + this->InternalRequestUpdateExtent(inExt, outExt); + + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro("Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMagnifyExecute( this, inData[0][0], + (VTK_TT *)(inPtr), inExt, outData[0], + (VTK_TT *)(outPtr), + outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageMagnify::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "MagnificationFactors: ( " + << this->MagnificationFactors[0] << ", " + << this->MagnificationFactors[1] << ", " + << this->MagnificationFactors[2] << " )\n"; + + os << indent << "Interpolate: " << (this->Interpolate ? "On\n" : "Off\n"); +} diff --git a/Imaging/vtkImageMagnify.h b/Imaging/vtkImageMagnify.h new file mode 100644 index 0000000..12f2689 --- /dev/null +++ b/Imaging/vtkImageMagnify.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMagnify.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMagnify - magnify an image by an integer value +// .SECTION Description +// vtkImageMagnify maps each pixel of the input onto a nxmx... region +// of the output. Location (0,0,...) remains in the same place. The +// magnification occurs via pixel replication, or if Interpolate is on, +// by bilinear interpolation. + +#ifndef __vtkImageMagnify_h +#define __vtkImageMagnify_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageMagnify : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageMagnify *New(); + vtkTypeRevisionMacro(vtkImageMagnify,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the integer magnification factors in the i-j-k directions. + vtkSetVector3Macro(MagnificationFactors,int); + vtkGetVector3Macro(MagnificationFactors,int); + + // Description: + // Turn interpolation on and off (pixel replication is used when off). + vtkSetMacro(Interpolate,int); + vtkGetMacro(Interpolate,int); + vtkBooleanMacro(Interpolate,int); + + +protected: + vtkImageMagnify(); + ~vtkImageMagnify() {}; + + int MagnificationFactors[3]; + int Interpolate; + virtual int RequestUpdateExtent (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); + + void InternalRequestUpdateExtent(int *inExt, int *outExt); + +private: + vtkImageMagnify(const vtkImageMagnify&); // Not implemented. + void operator=(const vtkImageMagnify&); // Not implemented. +}; + +#endif + + + + diff --git a/Imaging/vtkImageMagnitude.cxx b/Imaging/vtkImageMagnitude.cxx new file mode 100644 index 0000000..819a9d4 --- /dev/null +++ b/Imaging/vtkImageMagnitude.cxx @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMagnitude.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMagnitude.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageMagnitude, "$Revision: 1.42 $"); +vtkStandardNewMacro(vtkImageMagnitude); + +//---------------------------------------------------------------------------- +vtkImageMagnitude::vtkImageMagnitude() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +int vtkImageMagnitude::RequestInformation ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * outputVector) +{ + vtkDataObject::SetPointDataActiveScalarInfo( + outputVector->GetInformationObject(0), -1, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageMagnitudeExecute(vtkImageMagnitude *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + float sum; + + // find the region to loop over + int maxC = inData->GetNumberOfScalarComponents(); + int idxC; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // now process the components + sum = 0.0; + for (idxC = 0; idxC < maxC; idxC++) + { + sum += static_cast(*inSI * *inSI); + ++inSI; + } + *outSI = static_cast(sqrt(sum)); + ++outSI; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The output data +// must match input type. This method does handle boundary conditions. +void vtkImageMagnitude::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + // This is really meta data and should be set in ExecuteInformation, + // but there are some issues to solve first. + if (id == 0 && outData->GetPointData()->GetScalars()) + { + outData->GetPointData()->GetScalars()->SetName("Magnitude"); + } + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", must match out ScalarType " << outData->GetScalarType()); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMagnitudeExecute( this, inData, outData, + outExt, id, static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + + + + + + + + diff --git a/Imaging/vtkImageMagnitude.h b/Imaging/vtkImageMagnitude.h new file mode 100644 index 0000000..3fd9261 --- /dev/null +++ b/Imaging/vtkImageMagnitude.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMagnitude.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMagnitude - Colapses components with magnitude function.. +// .SECTION Description +// vtkImageMagnitude takes the magnitude of the components. + + +#ifndef __vtkImageMagnitude_h +#define __vtkImageMagnitude_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageMagnitude : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageMagnitude *New(); + vtkTypeRevisionMacro(vtkImageMagnitude,vtkThreadedImageAlgorithm); + +protected: + vtkImageMagnitude(); + ~vtkImageMagnitude() {}; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, + vtkInformationVector *); + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int outExt[6], int id); + +private: + vtkImageMagnitude(const vtkImageMagnitude&); // Not implemented. + void operator=(const vtkImageMagnitude&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageMandelbrotSource.cxx b/Imaging/vtkImageMandelbrotSource.cxx new file mode 100644 index 0000000..d710fda --- /dev/null +++ b/Imaging/vtkImageMandelbrotSource.cxx @@ -0,0 +1,460 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMandelbrotSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMandelbrotSource.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageMandelbrotSource, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkImageMandelbrotSource); + +//---------------------------------------------------------------------------- +vtkImageMandelbrotSource::vtkImageMandelbrotSource() +{ + this->MaximumNumberOfIterations = 100; + this->WholeExtent[0] = 0; + this->WholeExtent[1] = 250; + this->WholeExtent[2] = 0; + this->WholeExtent[3] = 250; + this->WholeExtent[4] = 0; + this->WholeExtent[5] = 0; + + this->SampleCX[0] = 0.01; + this->SampleCX[1] = 0.01; + this->SampleCX[2] = 0.01; + this->SampleCX[3] = 0.01; + + this->SizeCX[0] = 2.5; + this->SizeCX[1] = 2.5; + this->SizeCX[2] = 2.0; + this->SizeCX[3] = 1.5; + + this->ConstantSize = 1; + + this->OriginCX[0] = -1.75; + this->OriginCX[1] = -1.25; + this->OriginCX[2] = 0.0; + this->OriginCX[3] = 0.0; + + this->ProjectionAxes[0] = 0; + this->ProjectionAxes[1] = 1; + this->ProjectionAxes[2] = 2; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkImageMandelbrotSource::~vtkImageMandelbrotSource() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageMandelbrotSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "OriginC: (" << this->OriginCX[0] << ", " + << this->OriginCX[1] << ")\n"; + os << indent << "OriginX: (" << this->OriginCX[2] << ", " + << this->OriginCX[3] << ")\n"; + + os << indent << "SampleC: (" << this->SampleCX[0] << ", " + << this->SampleCX[1] << ")\n"; + os << indent << "SampleX: (" << this->SampleCX[2] << ", " + << this->SampleCX[3] << ")\n"; + + double *size = this->GetSizeCX(); + os << indent << "SizeC: (" << size[0] << ", " << size[1] << ")\n"; + os << indent << "SizeX: (" << size[2] << ", " << size[3] << ")\n"; + + if (this->ConstantSize) + { + os << indent << "ConstantSize\n"; + } + else + { + os << indent << "ConstantSpacing\n"; + } + + os << indent << "WholeExtent: (" << this->WholeExtent[0] << ", " + << this->WholeExtent[1] << ", " << this->WholeExtent[2] << ", " + << this->WholeExtent[3] << ", " << this->WholeExtent[4] << ", " + << this->WholeExtent[5] << ")\n"; + os << "MaximumNumberOfIterations: " << this->MaximumNumberOfIterations << endl; + + os << indent << "ProjectionAxes: (" << this->ProjectionAxes[0] << ", " + << this->ProjectionAxes[1] << this->ProjectionAxes[2] << ")\n"; + +} + +//---------------------------------------------------------------------------- +void vtkImageMandelbrotSource::SetWholeExtent(int extent[6]) +{ + int idx, modified = 0; + double saveSize[4]; + + this->GetSizeCX(saveSize); + + + for (idx = 0; idx < 6; ++idx) + { + if (this->WholeExtent[idx] != extent[idx]) + { + this->WholeExtent[idx] = extent[idx]; + modified = 1; + } + } + + if (modified) + { + this->Modified(); + if (this->ConstantSize) + { + this->SetSizeCX(saveSize[0], saveSize[1], saveSize[2], saveSize[3]); + } + } +} + + +//---------------------------------------------------------------------------- +void vtkImageMandelbrotSource::SetProjectionAxes(int x, int y, int z) +{ + double saveSize[4]; + + if (this->ProjectionAxes[0] == x && this->ProjectionAxes[1] == y && + this->ProjectionAxes[2] == z) + { + return; + } + + this->Modified(); + this->GetSizeCX(saveSize); + this->ProjectionAxes[0] = x; + this->ProjectionAxes[1] = y; + this->ProjectionAxes[2] = z; + if (this->ConstantSize) + { + this->SetSizeCX(saveSize[0], saveSize[1], saveSize[2], saveSize[3]); + } +} + + +//---------------------------------------------------------------------------- +void vtkImageMandelbrotSource::SetWholeExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetWholeExtent(extent); +} + +//---------------------------------------------------------------------------- +void vtkImageMandelbrotSource::SetSizeCX(double cReal, double cImag, + double xReal, double xImag) +{ + int axis; + int idx; + int d; + + double *s = this->GetSizeCX(); + if (s[0] == cReal && s[1] == cImag && s[2] == xReal && s[3] == xImag) + { + return; + } + this->Modified(); + + // Set this because information can be carried over for collapsed axes. + this->SizeCX[0] = cReal; + this->SizeCX[1] = cImag; + this->SizeCX[2] = xReal; + this->SizeCX[3] = xImag; + + // Now compute the gold standard (for non collapsed axes. + for (idx = 0; idx < 3; ++idx) + { + d = this->WholeExtent[idx*2+1] - this->WholeExtent[idx*2]; + if (d > 0) + { + axis = this->ProjectionAxes[idx]; + this->SampleCX[axis] = this->SizeCX[axis] / ((double) d); + } + } +} + +//---------------------------------------------------------------------------- +double* vtkImageMandelbrotSource::GetSizeCX() +{ + int axis; + int idx; + int d; + + // Recompute the size for the spacing (gold standard). + for (idx = 0; idx < 3; ++idx) + { + d = this->WholeExtent[idx*2+1] - this->WholeExtent[idx*2]; + if (d > 0) + { + axis = this->ProjectionAxes[idx]; + this->SizeCX[axis] = this->SampleCX[axis] * ((double) d); + } + } + + return this->SizeCX; +} + +//---------------------------------------------------------------------------- +void vtkImageMandelbrotSource::GetSizeCX(double s[4]) +{ + double *p = this->GetSizeCX(); + + s[0] = p[0]; + s[1] = p[1]; + s[2] = p[2]; + s[3] = p[3]; +} + +//---------------------------------------------------------------------------- +int vtkImageMandelbrotSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int idx, axis; + double origin[3]; + double spacing[3]; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent,6); + for (idx = 0; idx < 3; ++idx) + { + axis = this->ProjectionAxes[idx]; + if (axis >= 0 && axis < 4) + { + origin[idx] = this->OriginCX[axis]; + spacing[idx] = this->SampleCX[axis]; + } + else + { + vtkErrorMacro("Bad projection axis."); + origin[idx] = 0.0; + spacing[idx] = 1.0; + } + } + + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// We may want separate zooms for mandelbrot and julia. +void vtkImageMandelbrotSource::Zoom(double factor) +{ + if (factor == 1.0) + { + return; + } + this->Modified(); + this->SampleCX[0] *= factor; + this->SampleCX[1] *= factor; + this->SampleCX[2] *= factor; + this->SampleCX[3] *= factor; +} + +//---------------------------------------------------------------------------- +void vtkImageMandelbrotSource::Pan(double x, double y, double z) +{ + int idx, axis; + double pan[3]; + + if (x == 0.0 && y == 0.0 && z == 0.0) + { + return; + } + + this->Modified(); + pan[0]=x; pan[1]=y; pan[2]=z; + for (idx = 0; idx < 3; ++idx) + { + axis = this->ProjectionAxes[idx]; + if (axis >= 0 && axis < 4) + { + this->OriginCX[axis] += this->SampleCX[axis] * pan[idx]; + } + } +} + +//---------------------------------------------------------------------------- +void +vtkImageMandelbrotSource::CopyOriginAndSample(vtkImageMandelbrotSource *source) +{ + int idx; + + for (idx = 0; idx < 4; ++idx) + { + this->OriginCX[idx] = source->OriginCX[idx]; + this->SampleCX[idx] = source->SampleCX[idx]; + } + + this->Modified(); +} +//---------------------------------------------------------------------------- +int vtkImageMandelbrotSource::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed(inputVector), + vtkInformationVector* outputVector) +{ + // get the output + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *data = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // We need to allocate our own scalars since we are overriding + // the superclasses "Execute()" method. + int *ext = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + data->SetExtent(ext); + data->AllocateScalars(); + + int a0, a1, a2; + float *ptr; + int min0, max0; + int idx0, idx1, idx2; + vtkIdType inc0, inc1, inc2; + double *origin, *sample; + double p[4]; + unsigned long count = 0; + unsigned long target; + + // Name the array appropriately. + data->GetPointData()->GetScalars()->SetName("Iterations"); + + if (data->GetNumberOfPoints() <= 0) + { + return 1; + } + + // Copy origin into pixel + for (idx0 = 0; idx0 < 4; ++idx0) + { + p[idx0] = this->OriginCX[idx0]; + } + + ptr = (float *)(data->GetScalarPointerForExtent(ext)); + + vtkDebugMacro("Generating Extent: " << ext[0] << " -> " << ext[1] << ", " + << ext[2] << " -> " << ext[3]); + + // Get min and max of axis 0 because it is the innermost loop. + min0 = ext[0]; + max0 = ext[1]; + data->GetContinuousIncrements(ext, inc0, inc1, inc2); + + target = (unsigned long)((ext[5]-ext[4]+1)*(ext[3]-ext[2]+1)/50.0); + target++; + + a0 = this->ProjectionAxes[0]; + a1 = this->ProjectionAxes[1]; + a2 = this->ProjectionAxes[2]; + origin = this->OriginCX; + sample = this->SampleCX; + + if (a0<0 || a1<0 || a2<0 || a0>3 || a1>3 || a2>3) + { + vtkErrorMacro("Bad projection axis"); + return 0; + } + for (idx2 = ext[4]; idx2 <= ext[5]; ++idx2) + { + p[a2] = (double)(origin[a2]) + (double)(idx2)*(sample[a2]); + for (idx1 = ext[2]; !this->AbortExecute && idx1 <= ext[3]; ++idx1) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + p[a1] = (double)(origin[a1]) + (double)(idx1)*(sample[a1]); + for (idx0 = min0; idx0 <= max0; ++idx0) + { + p[a0] = (double)(origin[a0]) + (double)(idx0)*(sample[a0]); + + *ptr = (float)(this->EvaluateSet(p)); + + ++ptr; + // inc0 is 0 + } + ptr += inc1; + } + ptr += inc2; + } + + return 1; +} + + +//---------------------------------------------------------------------------- +double vtkImageMandelbrotSource::EvaluateSet(double p[4]) +{ + unsigned short count = 0; + double v0, v1; + double cReal, cImag, zReal, zImag; + double zReal2, zImag2; + + cReal = p[0]; + cImag = p[1]; + zReal = p[2]; + zImag = p[3]; + + zReal2 = zReal * zReal; + zImag2 = zImag * zImag; + v0 = 0.0; + v1 = (zReal2 + zImag2); + while ( v1 < 4.0 && count < this->MaximumNumberOfIterations) + { + zImag = 2.0 * zReal * zImag + cImag; + zReal = zReal2 - zImag2 + cReal; + zReal2 = zReal * zReal; + zImag2 = zImag * zImag; + ++count; + v0 = v1; + v1 = (zReal2 + zImag2); + } + + if (count == this->MaximumNumberOfIterations) + { + return (double)count; + } + + return (double)count + (4.0 - v0)/(v1 - v0); +} + + + + + + + diff --git a/Imaging/vtkImageMandelbrotSource.h b/Imaging/vtkImageMandelbrotSource.h new file mode 100644 index 0000000..5a65701 --- /dev/null +++ b/Imaging/vtkImageMandelbrotSource.h @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMandelbrotSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMandelbrotSource - Mandelbrot image. +// .SECTION Description +// vtkImageMandelbrotSource creates an unsigned char image of the Mandelbrot +// set. The values in the image are the number of iterations it takes for +// the magnitude of the value to get over 2. The equation repeated is +// z = z^2 + C (z and C are complex). Initial value of z is zero, and the +// real value of C is mapped onto the x axis, and the imaginary value of C +// is mapped onto the Y Axis. I was thinking of extending this source +// to generate Julia Sets (initial value of Z varies). This would be 4 +// possible parameters to vary, but there are no more 4d images :( +// The third dimension (z axis) is the imaginary value of the initial value. + +#ifndef __vtkImageMandelbrotSource_h +#define __vtkImageMandelbrotSource_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageMandelbrotSource : public vtkImageAlgorithm +{ +public: + static vtkImageMandelbrotSource *New(); + vtkTypeRevisionMacro(vtkImageMandelbrotSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the extent of the whole output Volume. + void SetWholeExtent(int extent[6]); + void SetWholeExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + vtkGetVector6Macro(WholeExtent,int); + + // Description: + // This flag determines whether the Size or spacing of + // a data set remain constant (when extent is changed). + // By default, size remains constant. + vtkSetMacro(ConstantSize, int); + vtkGetMacro(ConstantSize, int); + vtkBooleanMacro(ConstantSize, int); + + // Description: + // Set the projection from the 4D space (4 parameters / 2 imaginary numbers) + // to the axes of the 3D Volume. + // 0=C_Real, 1=C_Imaginary, 2=X_Real, 4=X_Imaginary + void SetProjectionAxes(int x, int y, int z); + void SetProjectionAxes(int a[3]) {this->SetProjectionAxes(a[0],a[1],a[2]);} + vtkGetVector3Macro(ProjectionAxes, int); + + // Description: + // Imaginary and real value for C (constant in equation) + // and X (initial value). + vtkSetVector4Macro(OriginCX, double); + //void SetOriginCX(double cReal, double cImag, double xReal, double xImag); + vtkGetVector4Macro(OriginCX, double); + + // Description: + // Imaginary and real value for C (constant in equation) + // and X (initial value). + vtkSetVector4Macro(SampleCX, double); + //void SetOriginCX(double cReal, double cImag, double xReal, double xImag); + vtkGetVector4Macro(SampleCX, double); + + // Description: + // Just a different way of setting the sample. + // This sets the size of the 4D volume. + // SampleCX is computed from size and extent. + // Size is ignored when a dimension i 0 (collapsed). + void SetSizeCX(double cReal, double cImag, double xReal, double xImag); + double *GetSizeCX(); + void GetSizeCX(double s[4]); + + // Description: + // The maximum number of cycles run to see if the value goes over 2 + vtkSetClampMacro(MaximumNumberOfIterations, unsigned short, 1, 5000); + vtkGetMacro(MaximumNumberOfIterations, unsigned short); + + // Description: + // Convienence for Viewer. Pan 3D volume relative to spacing. + // Zoom constant factor. + void Zoom(double factor); + void Pan(double x, double y, double z); + + // Description: + // Convienence for Viewer. Copy the OriginCX and the SpacingCX. + // What about other parameters ??? + void CopyOriginAndSample(vtkImageMandelbrotSource *source); + +protected: + vtkImageMandelbrotSource(); + ~vtkImageMandelbrotSource(); + + int ProjectionAxes[3]; + + // WholeExtent in 3 space (after projection). + int WholeExtent[6]; + + // Complex constant/initial-value at origin. + double OriginCX[4]; + // Initial complex value at origin. + double SampleCX[4]; + unsigned short MaximumNumberOfIterations; + + // A temporary vector that is computed as needed. + // It is used to return a vector. + double SizeCX[4]; + + // A flag for keeping size constant (vs. keeping the spacing). + int ConstantSize; + + // see vtkAlgorithm for details + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector**, + vtkInformationVector *); + double EvaluateSet(double p[4]); +private: + vtkImageMandelbrotSource(const vtkImageMandelbrotSource&); // Not implemented. + void operator=(const vtkImageMandelbrotSource&); // Not implemented. +}; + + +#endif + + diff --git a/Imaging/vtkImageMapToColors.cxx b/Imaging/vtkImageMapToColors.cxx new file mode 100644 index 0000000..afc7306 --- /dev/null +++ b/Imaging/vtkImageMapToColors.cxx @@ -0,0 +1,281 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapToColors.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMapToColors.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkScalarsToColors.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageMapToColors, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkImageMapToColors); +vtkCxxSetObjectMacro(vtkImageMapToColors,LookupTable,vtkScalarsToColors); + +//---------------------------------------------------------------------------- +// Constructor sets default values +vtkImageMapToColors::vtkImageMapToColors() +{ + this->OutputFormat = 4; + this->ActiveComponent = 0; + this->PassAlphaToOutput = 0; + this->LookupTable = NULL; + this->DataWasPassed = 0; +} + +vtkImageMapToColors::~vtkImageMapToColors() +{ + if (this->LookupTable != NULL) + { + this->LookupTable->UnRegister(this); + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkImageMapToColors::GetMTime() +{ + unsigned long t1, t2; + + t1 = this->Superclass::GetMTime(); + if (this->LookupTable) + { + t2 = this->LookupTable->GetMTime(); + if (t2 > t1) + { + t1 = t2; + } + } + return t1; +} + +//---------------------------------------------------------------------------- +// This method checks to see if we can simply reference the input data +int vtkImageMapToColors::RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // If LookupTable is null, just pass the data + if (this->LookupTable == NULL) + { + vtkDebugMacro("ExecuteData: LookupTable not set, "\ + "passing input to output."); + + outData->SetExtent(inData->GetExtent()); + outData->GetPointData()->PassData(inData->GetPointData()); + this->DataWasPassed = 1; + } + else // normal behaviour + { + this->LookupTable->Build(); //make sure table is built + + if (this->DataWasPassed) + { + outData->GetPointData()->SetScalars(NULL); + this->DataWasPassed = 0; + } + + return this->Superclass::RequestData(request, inputVector, outputVector); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageMapToColors::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int numComponents = 4; + + switch (this->OutputFormat) + { + case VTK_RGBA: + numComponents = 4; + break; + case VTK_RGB: + numComponents = 3; + break; + case VTK_LUMINANCE_ALPHA: + numComponents = 2; + break; + case VTK_LUMINANCE: + numComponents = 1; + break; + default: + vtkErrorMacro("ExecuteInformation: Unrecognized color format."); + break; + } + + if (this->LookupTable == NULL) + { + vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if ( scalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) != VTK_UNSIGNED_CHAR ) + { + vtkErrorMacro("ExecuteInformation: No LookupTable was set but input data is not VTK_UNSIGNED_CHAR, therefore input can't be passed through!"); + return 1; + } + else if ( numComponents != scalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()) ) + { + vtkErrorMacro("ExecuteInformation: No LookupTable was set but number of components in input doesn't match OutputFormat, therefore input can't be passed through!"); + return 1; + } + } + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, numComponents); + return 1; +} + +//---------------------------------------------------------------------------- +// This non-templated function executes the filter for any type of data. + +void vtkImageMapToColorsExecute(vtkImageMapToColors *self, + vtkImageData *inData, void *inPtr, + vtkImageData *outData, + unsigned char *outPtr, + int outExt[6], int id) +{ + int idxY, idxZ; + int extX, extY, extZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int dataType = inData->GetScalarType(); + int scalarSize = inData->GetScalarSize(); + int numberOfComponents,numberOfOutputComponents,outputFormat; + int rowLength; + vtkScalarsToColors *lookupTable = self->GetLookupTable(); + unsigned char *outPtr1; + void *inPtr1; + + // find the region to loop over + extX = outExt[1] - outExt[0] + 1; + extY = outExt[3] - outExt[2] + 1; + extZ = outExt[5] - outExt[4] + 1; + + target = (unsigned long)(extZ*extY/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + // because we are using void * and char * we must take care + // of the scalar size in the increments + inIncY *= scalarSize; + inIncZ *= scalarSize; + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + numberOfComponents = inData->GetNumberOfScalarComponents(); + numberOfOutputComponents = outData->GetNumberOfScalarComponents(); + outputFormat = self->GetOutputFormat(); + rowLength = extX*scalarSize*numberOfComponents; + + // Loop through output pixels + outPtr1 = outPtr; + inPtr1 = (void *) ((char *) inPtr + self->GetActiveComponent()*scalarSize); + for (idxZ = 0; idxZ < extZ; idxZ++) + { + for (idxY = 0; !self->AbortExecute && idxY < extY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + lookupTable->MapScalarsThroughTable2(inPtr1,outPtr1, + dataType,extX,numberOfComponents, + outputFormat); + if (self->GetPassAlphaToOutput() && + dataType == VTK_UNSIGNED_CHAR && numberOfComponents > 1 && + (outputFormat == VTK_RGBA || outputFormat == VTK_LUMINANCE_ALPHA)) + { + unsigned char *outPtr2 = outPtr1 + numberOfOutputComponents - 1; + unsigned char *inPtr2 = (unsigned char *)inPtr1 + - self->GetActiveComponent()*scalarSize + + numberOfComponents - 1; + for (int i = 0; i < extX; i++) + { + *outPtr2 = (*outPtr2 * *inPtr2)/255; + outPtr2 += numberOfOutputComponents; + inPtr2 += numberOfComponents; + } + } + outPtr1 += outIncY + extX*numberOfOutputComponents; + inPtr1 = (void *) ((char *) inPtr1 + inIncY + rowLength); + } + outPtr1 += outIncZ; + inPtr1 = (void *) ((char *) inPtr1 + inIncZ); + } +} + +//---------------------------------------------------------------------------- +// This method is passed a input and output data, and executes the filter +// algorithm to fill the output from the input. + +void vtkImageMapToColors::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + vtkImageMapToColorsExecute(this, inData[0][0], inPtr, + outData[0], (unsigned char *)outPtr, outExt, id); +} + +void vtkImageMapToColors::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "OutputFormat: " << + (this->OutputFormat == VTK_RGBA ? "RGBA" : + (this->OutputFormat == VTK_RGB ? "RGB" : + (this->OutputFormat == VTK_LUMINANCE_ALPHA ? "LuminanceAlpha" : + (this->OutputFormat == VTK_LUMINANCE ? "Luminance" : "Unknown")))) + << "\n"; + os << indent << "ActiveComponent: " << this->ActiveComponent << "\n"; + os << indent << "PassAlphaToOutput: " << this->PassAlphaToOutput << "\n"; + os << indent << "LookupTable: " << this->LookupTable << "\n"; + if (this->LookupTable) + { + this->LookupTable->PrintSelf(os,indent.GetNextIndent()); + } +} + + + + + diff --git a/Imaging/vtkImageMapToColors.h b/Imaging/vtkImageMapToColors.h new file mode 100644 index 0000000..6b22db6 --- /dev/null +++ b/Imaging/vtkImageMapToColors.h @@ -0,0 +1,106 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapToColors.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMapToColors - map the input image through a lookup table +// .SECTION Description +// The vtkImageMapToColors filter will take an input image of any valid +// scalar type, and map the first component of the image through a +// lookup table. The result is an image of type VTK_UNSIGNED_CHAR. +// If the lookup table is not set, or is set to NULL, then the input +// data will be passed through if it is already of type UNSIGNED_CHAR. + +// .SECTION See Also +// vtkLookupTable vtkScalarsToColors + +#ifndef __vtkImageMapToColors_h +#define __vtkImageMapToColors_h + + +#include "vtkThreadedImageAlgorithm.h" + +class vtkScalarsToColors; + +class VTK_IMAGING_EXPORT vtkImageMapToColors : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageMapToColors *New(); + vtkTypeRevisionMacro(vtkImageMapToColors,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the lookup table. + virtual void SetLookupTable(vtkScalarsToColors*); + vtkGetObjectMacro(LookupTable,vtkScalarsToColors); + + // Description: + // Set the output format, the default is RGBA. + vtkSetMacro(OutputFormat,int); + vtkGetMacro(OutputFormat,int); + void SetOutputFormatToRGBA() { this->OutputFormat = VTK_RGBA; }; + void SetOutputFormatToRGB() { this->OutputFormat = VTK_RGB; }; + void SetOutputFormatToLuminanceAlpha() { this->OutputFormat = VTK_LUMINANCE_ALPHA; }; + void SetOutputFormatToLuminance() { this->OutputFormat = VTK_LUMINANCE; }; + + // Description: + // Set the component to map for multi-component images (default: 0) + vtkSetMacro(ActiveComponent,int); + vtkGetMacro(ActiveComponent,int); + + // Description: + // Use the alpha component of the input when computing the alpha component + // of the output (useful when converting monochrome+alpha data to RGBA) + vtkSetMacro(PassAlphaToOutput,int); + vtkBooleanMacro(PassAlphaToOutput,int); + vtkGetMacro(PassAlphaToOutput,int); + + // Description: + // We need to check the modified time of the lookup table too. + virtual unsigned long GetMTime(); + +protected: + vtkImageMapToColors(); + ~vtkImageMapToColors(); + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + + vtkScalarsToColors *LookupTable; + int OutputFormat; + + int ActiveComponent; + int PassAlphaToOutput; + + int DataWasPassed; +private: + vtkImageMapToColors(const vtkImageMapToColors&); // Not implemented. + void operator=(const vtkImageMapToColors&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Imaging/vtkImageMapToRGBA.cxx b/Imaging/vtkImageMapToRGBA.cxx new file mode 100644 index 0000000..d8a256c --- /dev/null +++ b/Imaging/vtkImageMapToRGBA.cxx @@ -0,0 +1,19 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapToRGBA.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMapToRGBA.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageMapToRGBA, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkImageMapToRGBA); diff --git a/Imaging/vtkImageMapToRGBA.h b/Imaging/vtkImageMapToRGBA.h new file mode 100644 index 0000000..a5c2973 --- /dev/null +++ b/Imaging/vtkImageMapToRGBA.h @@ -0,0 +1,50 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapToRGBA.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMapToRGBA - map the input image through a lookup table +// .SECTION Description +// This filter has been replaced by vtkImageMapToColors, which provided +// additional features. Use vtkImageMapToColors instead. + +// .SECTION See Also +// vtkLookupTable + +#ifndef __vtkImageMapToRGBA_h +#define __vtkImageMapToRGBA_h + + +#include "vtkImageMapToColors.h" + +class VTK_IMAGING_EXPORT vtkImageMapToRGBA : public vtkImageMapToColors +{ +public: + static vtkImageMapToRGBA *New(); + vtkTypeRevisionMacro(vtkImageMapToRGBA,vtkImageMapToColors); + +protected: + vtkImageMapToRGBA() {}; + ~vtkImageMapToRGBA() {}; +private: + vtkImageMapToRGBA(const vtkImageMapToRGBA&); // Not implemented. + void operator=(const vtkImageMapToRGBA&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Imaging/vtkImageMapToWindowLevelColors.cxx b/Imaging/vtkImageMapToWindowLevelColors.cxx new file mode 100644 index 0000000..25bbae2 --- /dev/null +++ b/Imaging/vtkImageMapToWindowLevelColors.cxx @@ -0,0 +1,441 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapToWindowLevelColors.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMapToWindowLevelColors.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkScalarsToColors.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageMapToWindowLevelColors, "$Revision: 1.24 $"); +vtkStandardNewMacro(vtkImageMapToWindowLevelColors); + +// Constructor sets default values +vtkImageMapToWindowLevelColors::vtkImageMapToWindowLevelColors() +{ + this->Window = 255; + this->Level = 127.5; +} + +vtkImageMapToWindowLevelColors::~vtkImageMapToWindowLevelColors() +{ +} + +//---------------------------------------------------------------------------- +// This method checks to see if we can simply reference the input data +int vtkImageMapToWindowLevelColors::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // If LookupTable is null and window / level produces no change, + // then just pass the data + if (this->LookupTable == NULL && + (inData->GetScalarType() == VTK_UNSIGNED_CHAR && + this->Window == 255 && this->Level == 127.5)) + { + vtkDebugMacro("ExecuteData: LookupTable not set, "\ + "Window / Level at default, "\ + "passing input to output."); + + outData->SetExtent(inData->GetExtent()); + outData->GetPointData()->PassData(inData->GetPointData()); + this->DataWasPassed = 1; + } + else + // normal behaviour - skip up a level since we don't want to + // call the superclasses ExecuteData - it would pass the data if there + // is no lookup table even if there is a window / level - wrong + // behavior. + { + if (this->DataWasPassed) + { + outData->GetPointData()->SetScalars(NULL); + this->DataWasPassed = 0; + } + + return this->vtkThreadedImageAlgorithm::RequestData(request, inputVector, + outputVector); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageMapToWindowLevelColors::RequestInformation ( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkInformation *inScalarInfo = + vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!inScalarInfo) + { + vtkErrorMacro("Missing scalar field on input information!"); + return 0; + } + + // If LookupTable is null and window / level produces no change, + // then the data will be passed + if ( this->LookupTable == NULL && + (inScalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) == + VTK_UNSIGNED_CHAR && + this->Window == 255 && this->Level == 127.5) ) + { + if (inScalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()) != + VTK_UNSIGNED_CHAR) + { + vtkErrorMacro("ExecuteInformation: No LookupTable was set and input data is not VTK_UNSIGNED_CHAR!"); + } + else + { + // no lookup table, pass the input if it was UNSIGNED_CHAR + vtkDataObject::SetPointDataActiveScalarInfo + (outInfo, VTK_UNSIGNED_CHAR, + inScalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS())); + } + } + else // the lookup table was set or window / level produces a change + { + int numComponents = 4; + switch (this->OutputFormat) + { + case VTK_RGBA: + numComponents = 4; + break; + case VTK_RGB: + numComponents = 3; + break; + case VTK_LUMINANCE_ALPHA: + numComponents = 2; + break; + case VTK_LUMINANCE: + numComponents = 1; + break; + default: + vtkErrorMacro("ExecuteInformation: Unrecognized color format."); + break; + } + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, numComponents); + } + + return 1; +} + +/* + * This templated routine calculates effective lower and upper limits + * for a window of values of type T, lower and upper. + */ +template +void vtkImageMapToWindowLevelClamps ( vtkImageData *data, double w, + double l, T& lower, T& upper, + unsigned char &lower_val, + unsigned char &upper_val) +{ + double f_lower, f_upper, f_lower_val, f_upper_val; + double adjustedLower, adjustedUpper; + double range[2]; + + data->GetPointData()->GetScalars()->GetDataTypeRange( range ); + + f_lower = l - fabs(w) / 2.0; + f_upper = f_lower + fabs(w); + + // Set the correct lower value + if ( f_lower <= range[1]) + { + if (f_lower >= range[0]) + { + lower = (T) f_lower; + adjustedLower = f_lower; + } + else + { + lower = (T) range[0]; + adjustedLower = range[0]; + } + } + else + { + lower = (T) range[1]; + adjustedLower = range[1]; + } + + // Set the correct upper value + if ( f_upper >= range[0]) + { + if (f_upper <= range[1]) + { + upper = (T) f_upper; + adjustedUpper = f_upper; + } + else + { + upper = (T) range[1]; + adjustedUpper = range[1]; + } + } + else + { + upper = (T) range [0]; + adjustedUpper = range [0]; + } + + // now compute the lower and upper values + if (w >= 0) + { + f_lower_val = 255.0*(adjustedLower - f_lower)/w; + f_upper_val = 255.0*(adjustedUpper - f_lower)/w; + } + else + { + f_lower_val = 255.0 + 255.0*(adjustedLower - f_lower)/w; + f_upper_val = 255.0 + 255.0*(adjustedUpper - f_lower)/w; + } + + if (f_upper_val > 255) + { + upper_val = 255; + } + else if (f_upper_val < 0) + { + upper_val = 0; + } + else + { + upper_val = (unsigned char)(f_upper_val); + } + + if (f_lower_val > 255) + { + lower_val = 255; + } + else if (f_lower_val < 0) + { + lower_val = 0; + } + else + { + lower_val = (unsigned char)(f_lower_val); + } +} + +//---------------------------------------------------------------------------- +// This non-templated function executes the filter for any type of data. +template +void vtkImageMapToWindowLevelColorsExecute( + vtkImageMapToWindowLevelColors *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, + unsigned char *outPtr, + int outExt[6], int id) +{ + int idxX, idxY, idxZ; + int extX, extY, extZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int dataType = inData->GetScalarType(); + int numberOfComponents,numberOfOutputComponents,outputFormat; + int rowLength; + vtkScalarsToColors *lookupTable = self->GetLookupTable(); + unsigned char *outPtr1; + T *inPtr1; + unsigned char *optr; + T *iptr; + double shift = self->GetWindow() / 2.0 - self->GetLevel(); + double scale = 255.0 / self->GetWindow(); + + T lower, upper; + unsigned char lower_val, upper_val, result_val; + unsigned short ushort_val; + vtkImageMapToWindowLevelClamps( inData, self->GetWindow(), + self->GetLevel(), + lower, upper, lower_val, upper_val ); + + // find the region to loop over + extX = outExt[1] - outExt[0] + 1; + extY = outExt[3] - outExt[2] + 1; + extZ = outExt[5] - outExt[4] + 1; + + target = (unsigned long)(extZ*extY/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + numberOfComponents = inData->GetNumberOfScalarComponents(); + numberOfOutputComponents = outData->GetNumberOfScalarComponents(); + outputFormat = self->GetOutputFormat(); + + rowLength = extX*numberOfComponents; + + // Loop through output pixels + outPtr1 = outPtr; + inPtr1 = inPtr; + for (idxZ = 0; idxZ < extZ; idxZ++) + { + for (idxY = 0; !self->AbortExecute && idxY < extY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + iptr = inPtr1; + optr = outPtr1; + + if ( lookupTable ) + { + lookupTable->MapScalarsThroughTable2(inPtr1,(unsigned char *)outPtr1, + dataType,extX,numberOfComponents, + outputFormat); + + for (idxX = 0; idxX < extX; idxX++) + { + if (*iptr <= lower) + { + ushort_val = lower_val; + } + else if (*iptr >= upper) + { + ushort_val = upper_val; + } + else + { + ushort_val = (unsigned char) ((*iptr + shift)*scale); + } + *optr = (unsigned char)((*optr * ushort_val) >> 8); + switch (outputFormat) + { + case VTK_RGBA: + *(optr+1) = (unsigned char)((*(optr+1) * ushort_val) >> 8); + *(optr+2) = (unsigned char)((*(optr+2) * ushort_val) >> 8); + *(optr+3) = 255; + break; + case VTK_RGB: + *(optr+1) = (unsigned char)((*(optr+1) * ushort_val) >> 8); + *(optr+2) = (unsigned char)((*(optr+2) * ushort_val) >> 8); + break; + case VTK_LUMINANCE_ALPHA: + *(optr+1) = 255; + break; + } + iptr += numberOfComponents; + optr += numberOfOutputComponents; + } + } + else + { + for (idxX = 0; idxX < extX; idxX++) + { + if (*iptr <= lower) + { + result_val = lower_val; + } + else if (*iptr >= upper) + { + result_val = upper_val; + } + else + { + result_val = (unsigned char) ((*iptr + shift)*scale); + } + *optr = result_val; + switch (outputFormat) + { + case VTK_RGBA: + *(optr+1) = result_val; + *(optr+2) = result_val; + *(optr+3) = 255; + break; + case VTK_RGB: + *(optr+1) = result_val; + *(optr+2) = result_val; + break; + case VTK_LUMINANCE_ALPHA: + *(optr+1) = 255; + break; + } + iptr += numberOfComponents; + optr += numberOfOutputComponents; + } + } + outPtr1 += outIncY + extX*numberOfOutputComponents; + inPtr1 += inIncY + rowLength; + } + outPtr1 += outIncZ; + inPtr1 += inIncZ; + } +} + +//---------------------------------------------------------------------------- +// This method is passed a input and output data, and executes the filter +// algorithm to fill the output from the input. + +void vtkImageMapToWindowLevelColors::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr = inData[0][0]->GetScalarPointerForExtent(outExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMapToWindowLevelColorsExecute( this, + inData[0][0], + (VTK_TT *)(inPtr), + outData[0], + (unsigned char *)(outPtr), + outExt, + id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageMapToWindowLevelColors::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Window: " << this->Window << endl; + os << indent << "Level: " << this->Level << endl; +} diff --git a/Imaging/vtkImageMapToWindowLevelColors.h b/Imaging/vtkImageMapToWindowLevelColors.h new file mode 100644 index 0000000..bc87c3d --- /dev/null +++ b/Imaging/vtkImageMapToWindowLevelColors.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapToWindowLevelColors.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMapToWindowLevelColors - map the input image through a lookup table and window / level it +// .SECTION Description +// The vtkImageMapToWindowLevelColors filter will take an input image of any +// valid scalar type, and map the first component of the image through a +// lookup table. This resulting color will be modulated with value obtained +// by a window / level operation. The result is an image of type +// VTK_UNSIGNED_CHAR. If the lookup table is not set, or is set to NULL, then +// the input data will be passed through if it is already of type +// UNSIGNED_CHAR. +// +// .SECTION See Also +// vtkLookupTable vtkScalarsToColors + +#ifndef __vtkImageMapToWindowLevelColors_h +#define __vtkImageMapToWindowLevelColors_h + + +#include "vtkImageMapToColors.h" + +class VTK_IMAGING_EXPORT vtkImageMapToWindowLevelColors : public vtkImageMapToColors +{ +public: + static vtkImageMapToWindowLevelColors *New(); + vtkTypeRevisionMacro(vtkImageMapToWindowLevelColors,vtkImageMapToColors); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / Get the Window to use -> modulation will be performed on the + // color based on (S - (L - W/2))/W where S is the scalar value, L is + // the level and W is the window. + vtkSetMacro( Window, double ); + vtkGetMacro( Window, double ); + + // Description: + // Set / Get the Level to use -> modulation will be performed on the + // color based on (S - (L - W/2))/W where S is the scalar value, L is + // the level and W is the window. + vtkSetMacro( Level, double ); + vtkGetMacro( Level, double ); + +protected: + vtkImageMapToWindowLevelColors(); + ~vtkImageMapToWindowLevelColors(); + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + + double Window; + double Level; + +private: + vtkImageMapToWindowLevelColors(const vtkImageMapToWindowLevelColors&); // Not implemented. + void operator=(const vtkImageMapToWindowLevelColors&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Imaging/vtkImageMask.cxx b/Imaging/vtkImageMask.cxx new file mode 100644 index 0000000..6644ebc --- /dev/null +++ b/Imaging/vtkImageMask.cxx @@ -0,0 +1,329 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMask.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMask.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageMask, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkImageMask); + +//---------------------------------------------------------------------------- +vtkImageMask::vtkImageMask() +{ + this->NotMask = 0; + this->MaskedOutputValue = new double[3]; + this->MaskedOutputValueLength = 3; + this->MaskedOutputValue[0] = this->MaskedOutputValue[1] + = this->MaskedOutputValue[2] = 0.0; + this->MaskAlpha = 1.0; + this->SetNumberOfInputPorts(2); +} + +vtkImageMask::~vtkImageMask() +{ + delete [] this->MaskedOutputValue; +} + +//---------------------------------------------------------------------------- +void vtkImageMask::SetImageInput(vtkImageData *in) +{ + this->SetInput1(in); +} + +//---------------------------------------------------------------------------- +void vtkImageMask::SetMaskInput(vtkImageData *in) +{ + this->SetInput2(in); +} + +//---------------------------------------------------------------------------- +void vtkImageMask::SetMaskedOutputValue(int num, double *v) +{ + int idx; + + if (num < 1) + { + vtkErrorMacro("Output value must have length greater than 0"); + return; + } + if (num != this->MaskedOutputValueLength) + { + this->Modified(); + } + + if (num > this->MaskedOutputValueLength) + { + delete [] this->MaskedOutputValue; + this->MaskedOutputValue = new double[num]; + this->MaskedOutputValueLength = num; + } + + this->MaskedOutputValueLength = num; + for (idx = 0; idx < num; ++ idx) + { + if (this->MaskedOutputValue[idx] != v[idx]) + { + this->Modified(); + } + this->MaskedOutputValue[idx] = v[idx]; + } +} + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageMaskExecute(vtkImageMask *self, int ext[6], + vtkImageData *in1Data, T *in1Ptr, + vtkImageData *in2Data, unsigned char *in2Ptr, + vtkImageData *outData, T *outPtr, int id) +{ + int num0, num1, num2, numC, pixSize; + int idx0, idx1, idx2, idxC; + vtkIdType in1Inc0, in1Inc1, in1Inc2; + vtkIdType in2Inc0, in2Inc1, in2Inc2; + vtkIdType outInc0, outInc1, outInc2; + T *maskedValue; + double *v; + int nv; + int maskState; + double maskAlpha, oneMinusMaskAlpha; + unsigned long count = 0; + unsigned long target; + + // create a masked output value with the correct length by cycling + numC = outData->GetNumberOfScalarComponents(); + maskedValue = new T[numC]; + v = self->GetMaskedOutputValue(); + nv = self->GetMaskedOutputValueLength(); + for (idx0 = 0, idx1 = 0; idx0 < numC; ++idx0, ++idx1) + { + if (idx1 >= nv) + { + idx1 = 0; + } + maskedValue[idx0] = (T)(v[idx1]); + } + pixSize = numC * sizeof(T); + maskState = self->GetNotMask(); + maskAlpha = self->GetMaskAlpha(); + oneMinusMaskAlpha = 1.0 - maskAlpha; + + // Get information to march through data + in1Data->GetContinuousIncrements(ext, in1Inc0, in1Inc1, in1Inc2); + in2Data->GetContinuousIncrements(ext, in2Inc0, in2Inc1, in2Inc2); + outData->GetContinuousIncrements(ext, outInc0, outInc1, outInc2); + num0 = ext[1] - ext[0] + 1; + num1 = ext[3] - ext[2] + 1; + num2 = ext[5] - ext[4] + 1; + + target = (unsigned long)(num2*num1/50.0); + target++; + + // Loop through ouput pixels + for (idx2 = 0; idx2 < num2; ++idx2) + { + for (idx1 = 0; !self->AbortExecute && idx1 < num1; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + for (idx0 = 0; idx0 < num0; ++idx0) + { + if ( maskAlpha == 1.0 ) + { + // Pixel operation + if (*in2Ptr && maskState == 1) + { + memcpy(outPtr, maskedValue, pixSize); + } + else if ( ! *in2Ptr && maskState == 0) + { + memcpy(outPtr, maskedValue, pixSize); + } + else + { + memcpy(outPtr, in1Ptr, pixSize); + } + in1Ptr += numC; + outPtr += numC; + } + else + { + // We need to do an over operation + int doMask = 0; + if ( *in2Ptr && maskState == 1 ) + { + doMask = 1; + } + else if ( !*in2Ptr && maskState == 0 ) + { + doMask = 1; + } + if ( doMask ) + { + // Do an over operation + for ( idxC = 0; idxC < numC; ++idxC ) + { + *outPtr = (T) ( oneMinusMaskAlpha * *in1Ptr + maskedValue[idxC] * maskAlpha ); + ++outPtr; + ++in1Ptr; + } + } + else + { + // Copy verbatum + for ( idxC = 0; idxC < numC; ++idxC ) + { + *outPtr = *in1Ptr; + ++outPtr; + ++in1Ptr; + } + } + } + in2Ptr += 1; + } + in1Ptr += in1Inc1; + in2Ptr += in2Inc1; + outPtr += outInc1; + } + in1Ptr += in1Inc2; + in2Ptr += in2Inc2; + outPtr += outInc2; + } + + delete [] maskedValue; +} + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output Datas, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the Datas data types. +void vtkImageMask::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr1; + void *inPtr2; + void *outPtr; + int *tExt; + + inPtr1 = inData[0][0]->GetScalarPointerForExtent(outExt); + inPtr2 = inData[1][0]->GetScalarPointerForExtent(outExt); + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + tExt = inData[1][0]->GetExtent(); + if (tExt[0] > outExt[0] || tExt[1] < outExt[1] || + tExt[2] > outExt[2] || tExt[3] < outExt[3] || + tExt[4] > outExt[4] || tExt[5] < outExt[5]) + { + vtkErrorMacro("Mask extent not large enough"); + return; + } + + if (inData[1][0]->GetNumberOfScalarComponents() != 1) + { + vtkErrorMacro("Maks can have one comenent"); + } + + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType() || + inData[1][0]->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro(<< "Execute: image ScalarType (" + << inData[0][0]->GetScalarType() << ") must match out ScalarType (" + << outData[0]->GetScalarType() << "), and mask scalar type (" + << inData[1][0]->GetScalarType() << ") must be unsigned char."); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMaskExecute(this, outExt, inData[0][0], + (VTK_TT *)(inPtr1), inData[1][0], + (unsigned char *)(inPtr2), + outData[0], (VTK_TT *)(outPtr),id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +// The output extent is the intersection. +int vtkImageMask::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *inInfo2 = inputVector[1]->GetInformationObject(0); + + int ext[6], ext2[6], idx; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext); + inInfo2->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext2); + for (idx = 0; idx < 3; ++idx) + { + if (ext2[idx*2] > ext[idx*2]) + { + ext[idx*2] = ext2[idx*2]; + } + if (ext2[idx*2+1] < ext[idx*2+1]) + { + ext[idx*2+1] = ext2[idx*2+1]; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext,6); + + return 1; +} + +void vtkImageMask::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + int idx; + + os << indent << "MaskedOutputValue: " << this->MaskedOutputValue[0]; + for (idx = 1; idx < this->MaskedOutputValueLength; ++idx) + { + os << ", " << this->MaskedOutputValue[idx]; + } + os << endl; + + os << indent << "NotMask: " << (this->NotMask ? "On\n" : "Off\n"); + os << indent << "MaskAlpha: " << this->MaskAlpha << "\n"; +} + diff --git a/Imaging/vtkImageMask.h b/Imaging/vtkImageMask.h new file mode 100644 index 0000000..3352906 --- /dev/null +++ b/Imaging/vtkImageMask.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMask.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMask - Combines a mask and an image. +// .SECTION Description +// vtkImageMask combines a mask with an image. Non zero mask +// implies the output pixel will be the same as the image. +// If a mask pixel is zero, the the output pixel +// is set to "MaskedValue". The filter also has the option to pass +// the mask through a boolean not operation before processing the image. +// This reverses the passed and replaced pixels. +// The two inputs should have the same "WholeExtent". +// The mask input should be unsigned char, and the image scalar type +// is the same as the output scalar type. + + +#ifndef __vtkImageMask_h +#define __vtkImageMask_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageMask : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageMask *New(); + vtkTypeRevisionMacro(vtkImageMask,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // SetGet the value of the output pixel replaced by mask. + void SetMaskedOutputValue(int num, double *v); + void SetMaskedOutputValue(double v) {this->SetMaskedOutputValue(1, &v);} + void SetMaskedOutputValue(double v1, double v2) + {double v[2]; v[0]=v1; v[1]=v2; this->SetMaskedOutputValue(2, v);} + void SetMaskedOutputValue(double v1, double v2, double v3) + {double v[3]; v[0]=v1; v[1]=v2; v[2]=v3; this->SetMaskedOutputValue(3, v);} + double *GetMaskedOutputValue() {return this->MaskedOutputValue;} + int GetMaskedOutputValueLength() {return this->MaskedOutputValueLength;} + + // Description: + // Set/Get the alpha blending value for the mask + // The input image is assumed to be at alpha = 1.0 + // and the mask image uses this alpha to blend using + // an over operator. + vtkSetClampMacro ( MaskAlpha, double, 0.0, 1.0 ); + vtkGetMacro ( MaskAlpha, double ); + + // Description: + // Set the input to be masked. + void SetImageInput(vtkImageData *in); + + // Description: + // Set the mask to be used. + void SetMaskInput(vtkImageData *in); + + // Description: + // When Not Mask is on, the mask is passed through a boolean not + // before it is used to mask the image. The effect is to pass the + // pixels where the input mask is zero, and replace the pixels + // where the input value is non zero. + vtkSetMacro(NotMask,int); + vtkGetMacro(NotMask,int); + vtkBooleanMacro(NotMask, int); + + // Description: + // Set the two inputs to this filter + virtual void SetInput1(vtkDataObject *in) { this->SetInput(0,in); } + virtual void SetInput2(vtkDataObject *in) { this->SetInput(1,in); } + +protected: + vtkImageMask(); + ~vtkImageMask(); + + double *MaskedOutputValue; + int MaskedOutputValueLength; + int NotMask; + double MaskAlpha; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + +private: + vtkImageMask(const vtkImageMask&); // Not implemented. + void operator=(const vtkImageMask&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageMaskBits.cxx b/Imaging/vtkImageMaskBits.cxx new file mode 100644 index 0000000..6d8f0f9 --- /dev/null +++ b/Imaging/vtkImageMaskBits.cxx @@ -0,0 +1,201 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMaskBits.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMaskBits.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImageMaskBits, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkImageMaskBits); + +vtkImageMaskBits::vtkImageMaskBits() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + this->Operation = VTK_AND; + this->Masks[0] = 0xffffffff; + this->Masks[1] = 0xffffffff; + this->Masks[2] = 0xffffffff; + this->Masks[3] = 0xffffffff; +} + + + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageMaskBitsExecute(vtkImageMaskBits *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + int idxC, maxC; + unsigned int *masks; + int operation; + + // find the region to loop over + maxC = inData->GetNumberOfScalarComponents(); + masks = self->GetMasks(); + operation = self->GetOperation(); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + switch (operation) + { + case VTK_AND: + while (outSI != outSIEnd) + { + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + *outSI++ = *inSI++ & (T) masks[idxC]; + } + } + break; + case VTK_OR: + while (outSI != outSIEnd) + { + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + *outSI++ = *inSI++ | (T) masks[idxC]; + } + } + break; + case VTK_XOR: + while (outSI != outSIEnd) + { + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + *outSI++ = *inSI++ ^ (T) masks[idxC]; + } + } + break; + case VTK_NAND: + while (outSI != outSIEnd) + { + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + *outSI++ = ~(*inSI++ & (T) masks[idxC]); + } + } + break; + case VTK_NOR: + while (outSI != outSIEnd) + { + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + *outSI++ = ~(*inSI++ | (T) masks[idxC]); + } + } + break; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The output data +// must match input type. This method does handle boundary conditions. +void vtkImageMaskBits::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData->GetScalarType() + << ", must match out ScalarType " + << outData->GetScalarType()); + return; + } + + switch (inData->GetScalarType()) + { + case VTK_INT: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + case VTK_UNSIGNED_INT: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + case VTK_LONG: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + case VTK_UNSIGNED_LONG: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + case VTK_SHORT: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + case VTK_UNSIGNED_SHORT: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + case VTK_CHAR: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + case VTK_UNSIGNED_CHAR: + vtkImageMaskBitsExecute(this, inData, outData, outExt, id, + static_cast(0)); + break; + default: + vtkErrorMacro(<< "Execute: ScalarType can only be [unsigned] char, [unsigned] short, " + << "[unsigned] int, or [unsigned] long."); + return; + } +} + + +void vtkImageMaskBits::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Operation: " << this->Operation << "\n"; + os << indent << "Masks: (" + << this->Masks[0] << ", " << this->Masks[1] << ", " + << this->Masks[2] << ", " << this->Masks[3] << ")" << endl; +} + + + + + + + + diff --git a/Imaging/vtkImageMaskBits.h b/Imaging/vtkImageMaskBits.h new file mode 100644 index 0000000..8369a06 --- /dev/null +++ b/Imaging/vtkImageMaskBits.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMaskBits.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMaskBits - applies a bit-mask pattern to each component. +// +// .SECTION Description +// vtkImageMaskBits applies a bit-mask pattern to each component. The +// bit-mask can be applied using a variety of boolean bitwise operators. + + +#ifndef __vtkImageMaskBits_h +#define __vtkImageMaskBits_h + +#include "vtkImageLogic.h" //For VTK_AND, VTK_OR ... +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageMaskBits : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageMaskBits *New(); + vtkTypeRevisionMacro(vtkImageMaskBits,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the bit-masks. Default is 0xffffffff. + vtkSetVector4Macro(Masks, unsigned int); + void SetMask(unsigned int mask) + {this->SetMasks(mask, mask, mask, mask);} + void SetMasks(unsigned int mask1, unsigned int mask2) + {this->SetMasks(mask1, mask2, 0xffffffff, 0xffffffff);} + void SetMasks(unsigned int mask1, unsigned int mask2, unsigned int mask3) + {this->SetMasks(mask1, mask2, mask3, 0xffffffff);} + vtkGetVector4Macro(Masks, unsigned int); + + // Description: + // Set/Get the boolean operator. Default is AND. + vtkSetMacro(Operation,int); + vtkGetMacro(Operation,int); + void SetOperationToAnd() {this->SetOperation(VTK_AND);}; + void SetOperationToOr() {this->SetOperation(VTK_OR);}; + void SetOperationToXor() {this->SetOperation(VTK_XOR);}; + void SetOperationToNand() {this->SetOperation(VTK_NAND);}; + void SetOperationToNor() {this->SetOperation(VTK_NOR);}; + +protected: + vtkImageMaskBits(); + ~vtkImageMaskBits() {}; + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); + + unsigned int Masks[4]; + int Operation; +private: + vtkImageMaskBits(const vtkImageMaskBits&); // Not implemented. + void operator=(const vtkImageMaskBits&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageMathematics.cxx b/Imaging/vtkImageMathematics.cxx new file mode 100644 index 0000000..08fa528 --- /dev/null +++ b/Imaging/vtkImageMathematics.cxx @@ -0,0 +1,516 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMathematics.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMathematics.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageMathematics, "$Revision: 1.53 $"); +vtkStandardNewMacro(vtkImageMathematics); + +//---------------------------------------------------------------------------- +vtkImageMathematics::vtkImageMathematics() +{ + this->Operation = VTK_ADD; + this->ConstantK = 1.0; + this->ConstantC = 0.0; + this->DivideByZeroToC = 0; + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +// The output extent is the intersection. +int vtkImageMathematics::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *inInfo2 = inputVector[1]->GetInformationObject(0); + + int ext[6], ext2[6], idx; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext); + + // two input take intersection + if (this->Operation == VTK_ADD || this->Operation == VTK_SUBTRACT || + this->Operation == VTK_MULTIPLY || this->Operation == VTK_DIVIDE || + this->Operation == VTK_MIN || this->Operation == VTK_MAX || + this->Operation == VTK_ATAN2) + { + if (!inInfo2) + { + vtkErrorMacro(<< "Second input must be specified for this operation."); + return 1; + } + + inInfo2->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext2); + for (idx = 0; idx < 3; ++idx) + { + if (ext2[idx*2] > ext[idx*2]) + { + ext[idx*2] = ext2[idx*2]; + } + if (ext2[idx*2+1] < ext[idx*2+1]) + { + ext[idx*2+1] = ext2[idx*2+1]; + } + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext,6); + + return 1; +} + +template +void vtkImageMathematicsClamp(TValue &value, TIvar ivar, vtkImageData *data) +{ + if (ivar < (TIvar) data->GetScalarTypeMin()) + { + value = (TValue) data->GetScalarTypeMin(); + } + else if (ivar > (TIvar) data->GetScalarTypeMax()) + { + value = (TValue) data->GetScalarTypeMax(); + } + else + { + value = (TValue) ivar; + } +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the one input operations +template +void vtkImageMathematicsExecute1(vtkImageMathematics *self, + vtkImageData *in1Data, T *in1Ptr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxR, idxY, idxZ; + int maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int rowLength; + unsigned long count = 0; + unsigned long target; + int op = self->GetOperation(); + + // find the region to loop over + rowLength = (outExt[1] - outExt[0]+1)*in1Data->GetNumberOfScalarComponents(); + // What a pain. Maybe I should just make another filter. + if (op == VTK_CONJUGATE) + { + rowLength = (outExt[1] - outExt[0] + 1); + } + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + int DivideByZeroToC = self->GetDivideByZeroToC(); + double doubleConstantk = self->GetConstantK(); + + // Avoid casts by making constants the same type as input/output + // Of course they must be clamped to a valid range for the scalar type + T constantk; vtkImageMathematicsClamp(constantk, self->GetConstantK(), in1Data); + T constantc; vtkImageMathematicsClamp(constantc, self->GetConstantC(), in1Data); + + // Loop through output pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + for (idxR = 0; idxR < rowLength; idxR++) + { + // Pixel operaton + switch (op) + { + case VTK_INVERT: + if (*in1Ptr) + { + *outPtr = (T)(1.0 / *in1Ptr); + } + else + { + if ( DivideByZeroToC ) + { + *outPtr = constantc; + } + else + { + *outPtr = (T)outData->GetScalarTypeMax(); + } + } + break; + case VTK_SIN: + *outPtr = (T)(sin((double)*in1Ptr)); + break; + case VTK_COS: + *outPtr = (T)(cos((double)*in1Ptr)); + break; + case VTK_EXP: + *outPtr = (T)(exp((double)*in1Ptr)); + break; + case VTK_LOG: + *outPtr = (T)(log((double)*in1Ptr)); + break; + case VTK_ABS: + *outPtr = (T)(fabs((double)*in1Ptr)); + break; + case VTK_SQR: + *outPtr = (T)(*in1Ptr * *in1Ptr); + break; + case VTK_SQRT: + *outPtr = (T)(sqrt((double)*in1Ptr)); + break; + case VTK_ATAN: + *outPtr = (T)(atan((double)*in1Ptr)); + break; + case VTK_MULTIPLYBYK: + *outPtr = (T)(doubleConstantk * (double) *in1Ptr); + break; + case VTK_ADDC: + *outPtr = constantc + *in1Ptr; + break; + case VTK_REPLACECBYK: + *outPtr = (*in1Ptr == constantc) ? constantk : *in1Ptr; + break; + case VTK_CONJUGATE: + outPtr[0] = in1Ptr[0]; + outPtr[1] = (T)(-1.0*(double)(in1Ptr[1])); + // Why bother trying to figure out the continuous increments. + outPtr++; + in1Ptr++; + break; + } + outPtr++; + in1Ptr++; + } + outPtr += outIncY; + in1Ptr += inIncY; + } + outPtr += outIncZ; + in1Ptr += inIncZ; + } +} + + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the two input operations +template +void vtkImageMathematicsExecute2(vtkImageMathematics *self, + vtkImageData *in1Data, T *in1Ptr, + vtkImageData *in2Data, T *in2Ptr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxR, idxY, idxZ; + int maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType in2IncX, in2IncY, in2IncZ; + vtkIdType outIncX, outIncY, outIncZ; + int rowLength; + unsigned long count = 0; + unsigned long target; + int op = self->GetOperation(); + int DivideByZeroToC = self->GetDivideByZeroToC(); + double constantc = self->GetConstantC(); + + // find the region to loop over + rowLength = (outExt[1] - outExt[0]+1)*in1Data->GetNumberOfScalarComponents(); + // What a pain. Maybe I should just make another filter. + if (op == VTK_COMPLEX_MULTIPLY) + { + rowLength = (outExt[1] - outExt[0]+1); + } + + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + in2Data->GetContinuousIncrements(outExt, in2IncX, in2IncY, in2IncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + for (idxR = 0; idxR < rowLength; idxR++) + { + // Pixel operation + switch (op) + { + case VTK_ADD: + *outPtr = *in1Ptr + *in2Ptr; + break; + case VTK_SUBTRACT: + *outPtr = *in1Ptr - *in2Ptr; + break; + case VTK_MULTIPLY: + *outPtr = *in1Ptr * *in2Ptr; + break; + case VTK_DIVIDE: + if (*in2Ptr) + { + *outPtr = *in1Ptr / *in2Ptr; + } + else + { + if ( DivideByZeroToC ) + { + *outPtr = (T) constantc; + } + else + { + // *outPtr = (T)(*in1Ptr / 0.00001); + *outPtr = (T)outData->GetScalarTypeMax(); + } + } + break; + case VTK_MIN: + if (*in1Ptr < *in2Ptr) + { + *outPtr = *in1Ptr; + } + else + { + *outPtr = *in2Ptr; + } + break; + case VTK_MAX: + if (*in1Ptr > *in2Ptr) + { + *outPtr = *in1Ptr; + } + else + { + *outPtr = *in2Ptr; + } + break; + case VTK_ATAN2: + if (*in1Ptr == 0.0 && *in2Ptr == 0.0) + { + *outPtr = 0; + } + else + { + *outPtr = (T)atan2((double)*in1Ptr,(double)*in2Ptr); + } + break; + case VTK_COMPLEX_MULTIPLY: + outPtr[0] = in1Ptr[0] * in2Ptr[0] - in1Ptr[1] * in2Ptr[1]; + outPtr[1] = in1Ptr[1] * in2Ptr[0] + in1Ptr[0] * in2Ptr[1]; + // Why bother trtying to figure out the continuous increments. + outPtr++; + in1Ptr++; + in2Ptr++; + break; + } + outPtr++; + in1Ptr++; + in2Ptr++; + } + outPtr += outIncY; + in1Ptr += inIncY; + in2Ptr += in2IncY; + } + outPtr += outIncZ; + in1Ptr += inIncZ; + in2Ptr += in2IncZ; + } +} + + +//---------------------------------------------------------------------------- +// This method is passed a input and output datas, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the datas data types. +void vtkImageMathematics::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr1; + void *outPtr; + + inPtr1 = inData[0][0]->GetScalarPointerForExtent(outExt); + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + + if (this->Operation == VTK_ADD || this->Operation == VTK_SUBTRACT || + this->Operation == VTK_MULTIPLY || this->Operation == VTK_DIVIDE || + this->Operation == VTK_MIN || this->Operation == VTK_MAX || + this->Operation == VTK_ATAN2 || this->Operation == VTK_COMPLEX_MULTIPLY) + { + void *inPtr2; + + if ( this->Operation == VTK_COMPLEX_MULTIPLY ) + { + if (inData[0][0]->GetNumberOfScalarComponents() != 2 || + inData[1][0]->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro("Complex inputs must have two components."); + return; + } + } + + if (!inData[1] || ! inData[1][0]) + { + vtkErrorMacro("ImageMathematics requested to perform a two input operation with only one input\n"); + return; + } + + inPtr2 = inData[1][0]->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input1 ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match output ScalarType " + << outData[0]->GetScalarType()); + return; + } + + if (inData[1][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input2 ScalarType, " + << inData[1][0]->GetScalarType() + << ", must match output ScalarType " + << outData[0]->GetScalarType()); + return; + } + + // this filter expects that inputs that have the same number of components + if (inData[0][0]->GetNumberOfScalarComponents() != + inData[1][0]->GetNumberOfScalarComponents()) + { + vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, " + << inData[0][0]->GetNumberOfScalarComponents() + << ", must match out input2 NumberOfScalarComponents " + << inData[1][0]->GetNumberOfScalarComponents()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMathematicsExecute2(this,inData[0][0], (VTK_TT *)(inPtr1), + inData[1][0], (VTK_TT *)(inPtr2), + outData[0], (VTK_TT *)(outPtr), outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + else + { + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData[0][0]->GetScalarType() + << ", must match out ScalarType " << outData[0]->GetScalarType()); + return; + } + + if ( this->Operation == VTK_CONJUGATE ) + { + if (inData[0][0]->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro("Complex inputs must have two components."); + return; + } + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMathematicsExecute1(this, inData[0][0], (VTK_TT *)(inPtr1), + outData[0], (VTK_TT *)(outPtr), outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } +} + +int vtkImageMathematics::FillInputPortInformation( + int port, vtkInformation* info) +{ + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +void vtkImageMathematics::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Operation: " << this->Operation << "\n"; + os << indent << "ConstantK: " << this->ConstantK << "\n"; + os << indent << "ConstantC: " << this->ConstantC << "\n"; + os << indent << "DivideByZeroToC: "; + if ( this->DivideByZeroToC ) + { + os << "On\n"; + } + else + { + os << "Off\n"; + } +} + diff --git a/Imaging/vtkImageMathematics.h b/Imaging/vtkImageMathematics.h new file mode 100644 index 0000000..4179f43 --- /dev/null +++ b/Imaging/vtkImageMathematics.h @@ -0,0 +1,141 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMathematics.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMathematics - Add, subtract, multiply, divide, invert, sin, cos, exp, log. +// .SECTION Description +// vtkImageMathematics implements basic mathematic operations SetOperation is +// used to select the filters behavior. The filter can take two or one +// input. + + +#ifndef __vtkImageMathematics_h +#define __vtkImageMathematics_h + + +// Operation options. +#define VTK_ADD 0 +#define VTK_SUBTRACT 1 +#define VTK_MULTIPLY 2 +#define VTK_DIVIDE 3 +#define VTK_INVERT 4 +#define VTK_SIN 5 +#define VTK_COS 6 +#define VTK_EXP 7 +#define VTK_LOG 8 +#define VTK_ABS 9 +#define VTK_SQR 10 +#define VTK_SQRT 11 +#define VTK_MIN 12 +#define VTK_MAX 13 +#define VTK_ATAN 14 +#define VTK_ATAN2 15 +#define VTK_MULTIPLYBYK 16 +#define VTK_ADDC 17 +#define VTK_CONJUGATE 18 +#define VTK_COMPLEX_MULTIPLY 19 +#define VTK_REPLACECBYK 20 + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageMathematics : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageMathematics *New(); + vtkTypeRevisionMacro(vtkImageMathematics,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the Operation to perform. + vtkSetMacro(Operation,int); + vtkGetMacro(Operation,int); + void SetOperationToAdd() {this->SetOperation(VTK_ADD);}; + void SetOperationToSubtract() {this->SetOperation(VTK_SUBTRACT);}; + void SetOperationToMultiply() {this->SetOperation(VTK_MULTIPLY);}; + void SetOperationToDivide() {this->SetOperation(VTK_DIVIDE);}; + void SetOperationToConjugate() {this->SetOperation(VTK_CONJUGATE);}; + void SetOperationToComplexMultiply() + {this->SetOperation(VTK_COMPLEX_MULTIPLY);}; + + void SetOperationToInvert() {this->SetOperation(VTK_INVERT);}; + void SetOperationToSin() {this->SetOperation(VTK_SIN);}; + void SetOperationToCos() {this->SetOperation(VTK_COS);}; + void SetOperationToExp() {this->SetOperation(VTK_EXP);}; + void SetOperationToLog() {this->SetOperation(VTK_LOG);}; + void SetOperationToAbsoluteValue() {this->SetOperation(VTK_ABS);}; + void SetOperationToSquare() {this->SetOperation(VTK_SQR);}; + void SetOperationToSquareRoot() {this->SetOperation(VTK_SQRT);}; + void SetOperationToMin() {this->SetOperation(VTK_MIN);}; + void SetOperationToMax() {this->SetOperation(VTK_MAX);}; + + void SetOperationToATAN() {this->SetOperation(VTK_ATAN);}; + void SetOperationToATAN2() {this->SetOperation(VTK_ATAN2);}; + void SetOperationToMultiplyByK() {this->SetOperation(VTK_MULTIPLYBYK);}; + void SetOperationToAddConstant() {this->SetOperation(VTK_ADDC);}; + void SetOperationToReplaceCByK() {this->SetOperation(VTK_REPLACECBYK);}; + vtkSetMacro(ConstantK,double); + vtkGetMacro(ConstantK,double); + vtkSetMacro(ConstantC,double); + vtkGetMacro(ConstantC,double); + + // How to handle divide by zero + vtkSetMacro(DivideByZeroToC,int); + vtkGetMacro(DivideByZeroToC,int); + vtkBooleanMacro(DivideByZeroToC,int); + + // Description: + // Set the two inputs to this filter + virtual void SetInput1(vtkDataObject *in) { this->SetInput(0,in); } + virtual void SetInput2(vtkDataObject *in) { this->SetInput(1,in); } + +protected: + vtkImageMathematics(); + ~vtkImageMathematics() {}; + + int Operation; + double ConstantK; + double ConstantC; + int DivideByZeroToC; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkImageMathematics(const vtkImageMathematics&); // Not implemented. + void operator=(const vtkImageMathematics&); // Not implemented. +}; + +#endif + + + + + + + + + + + + + diff --git a/Imaging/vtkImageMedian3D.cxx b/Imaging/vtkImageMedian3D.cxx new file mode 100644 index 0000000..3dedb0f --- /dev/null +++ b/Imaging/vtkImageMedian3D.cxx @@ -0,0 +1,406 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMedian3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMedian3D.h" + +#include "vtkCellData.h" +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageMedian3D, "$Revision: 1.46 $"); +vtkStandardNewMacro(vtkImageMedian3D); + +//----------------------------------------------------------------------------- +// Construct an instance of vtkImageMedian3D fitler. +vtkImageMedian3D::vtkImageMedian3D() +{ + this->NumberOfElements = 0; + this->SetKernelSize(1,1,1); + this->HandleBoundaries = 1; +} + +//----------------------------------------------------------------------------- +vtkImageMedian3D::~vtkImageMedian3D() +{ +} + +//----------------------------------------------------------------------------- +void vtkImageMedian3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "NumberOfElements: " << this->NumberOfElements << endl; +} + +//----------------------------------------------------------------------------- +// This method sets the size of the neighborhood. It also sets the +// default middle of the neighborhood +void vtkImageMedian3D::SetKernelSize(int size0, int size1, int size2) +{ + int volume; + int modified = 1; + + if (this->KernelSize[0] == size0 && this->KernelSize[1] == size1 && + this->KernelSize[2] == size2) + { + modified = 0; + } + + // Set the kernel size and middle + volume = 1; + this->KernelSize[0] = size0; + this->KernelMiddle[0] = size0 / 2; + volume *= size0; + this->KernelSize[1] = size1; + this->KernelMiddle[1] = size1 / 2; + volume *= size1; + this->KernelSize[2] = size2; + this->KernelMiddle[2] = size2 / 2; + volume *= size2; + + this->NumberOfElements = volume; + if ( modified ) + { + this->Modified(); + } +} + +//----------------------------------------------------------------------------- +// Add a sample to the median computation +double *vtkImageMedian3DAccumulateMedian(int &UpNum, int &DownNum, + int &UpMax, int &DownMax, + int &NumNeighborhood, + double *Median, double val) +{ + int idx, max; + double temp, *ptr; + + // special case: no samples yet + if (UpNum == 0) + { + *(Median) = val; + // length of up and down arrays inclusive of current + UpNum = DownNum = 1; + // median is gaurenteed to be in this range (length of array) + DownMax = UpMax = (NumNeighborhood + 1) / 2; + return Median; + } + + // Case: value is above median + if (val >= *(Median)) + { + // move the median if necessary + if (UpNum > DownNum) + { + // Move the median Up one + ++Median; + --UpNum; + ++DownNum; + --UpMax; + ++DownMax; + } + // find the position for val in the sorted array + max = (UpNum < UpMax) ? UpNum : UpMax; + ptr = Median; + idx = 0; + while (idx < max && val >= *ptr) + { + ++ptr; + ++idx; + } + // place val and move all others up + while (idx < max) + { + temp = *ptr; + *ptr = val; + val = temp; + ++ptr; + ++idx; + } + *ptr = val; + // Update counts + ++UpNum; + --DownMax; + return Median; + } + + // Case: value is below median + // If we got here, val < *(Median) + + // move the median if necessary + if (DownNum > UpNum) + { + // Move the median Down one + --Median; + --DownNum; + ++UpNum; + --DownMax; + ++UpMax; + } + // find the position for val in the sorted array + max = (DownNum < DownMax) ? DownNum : DownMax; + ptr = Median; + idx = 0; + while (idx < max && val <= *ptr) + { + --ptr; + ++idx; + } + // place val and move all others up + while (idx < max) + { + temp = *ptr; + *ptr = val; + val = temp; + --ptr; + ++idx; + } + *ptr = val; + // Update counts + ++DownNum; + --UpMax; + + return Median; +} + +//----------------------------------------------------------------------------- +// This method contains the second switch statement that calls the correct +// templated function for the mask types. +template +void vtkImageMedian3DExecute(vtkImageMedian3D *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id, + vtkDataArray *inArray) +{ + int *kernelMiddle, *kernelSize; + int NumberOfElements; + // For looping though output (and input) pixels. + int outIdx0, outIdx1, outIdx2; + vtkIdType inInc0, inInc1, inInc2; + int outIdxC; + vtkIdType outIncX, outIncY, outIncZ; + T *inPtr0, *inPtr1, *inPtr2; + // For looping through hood pixels + int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2; + int hoodStartMin0, hoodStartMax0, hoodStartMin1, hoodStartMax1; + int hoodIdx0, hoodIdx1, hoodIdx2; + T *tmpPtr0, *tmpPtr1, *tmpPtr2; + // The portion of the out image that needs no boundary processing. + int middleMin0, middleMax0, middleMin1, middleMax1, middleMin2, middleMax2; + int numComp; + // variables for the median calc + int UpNum, DownNum, UpMax, DownMax; + double *Median; + double *Sort = new double[(self->GetNumberOfElements() + 8)]; + int *inExt; + unsigned long count = 0; + unsigned long target; + + if (!inArray) + { + return; + } + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + kernelMiddle = self->GetKernelMiddle(); + kernelSize = self->GetKernelSize(); + + numComp = inArray->GetNumberOfComponents(); + + hoodMin0 = outExt[0] - kernelMiddle[0]; + hoodMin1 = outExt[2] - kernelMiddle[1]; + hoodMin2 = outExt[4] - kernelMiddle[2]; + hoodMax0 = kernelSize[0] + hoodMin0 - 1; + hoodMax1 = kernelSize[1] + hoodMin1 - 1; + hoodMax2 = kernelSize[2] + hoodMin2 - 1; + + // Clip by the input image extent + inExt = inData->GetExtent(); + hoodMin0 = (hoodMin0 > inExt[0]) ? hoodMin0 : inExt[0]; + hoodMin1 = (hoodMin1 > inExt[2]) ? hoodMin1 : inExt[2]; + hoodMin2 = (hoodMin2 > inExt[4]) ? hoodMin2 : inExt[4]; + hoodMax0 = (hoodMax0 < inExt[1]) ? hoodMax0 : inExt[1]; + hoodMax1 = (hoodMax1 < inExt[3]) ? hoodMax1 : inExt[3]; + hoodMax2 = (hoodMax2 < inExt[5]) ? hoodMax2 : inExt[5]; + + // Save the starting neighborhood dimensions (2 loops only once) + hoodStartMin0 = hoodMin0; hoodStartMax0 = hoodMax0; + hoodStartMin1 = hoodMin1; hoodStartMax1 = hoodMax1; + + // The portion of the output that needs no boundary computation. + middleMin0 = inExt[0] + kernelMiddle[0]; + middleMax0 = inExt[1] - (kernelSize[0] - 1) + kernelMiddle[0]; + middleMin1 = inExt[2] + kernelMiddle[1]; + middleMax1 = inExt[3] - (kernelSize[1] - 1) + kernelMiddle[1]; + middleMin2 = inExt[4] + kernelMiddle[2]; + middleMax2 = inExt[5] - (kernelSize[2] - 1) + kernelMiddle[2]; + + target = (unsigned long)((outExt[5] - outExt[4] + 1)* + (outExt[3] - outExt[2] + 1)/50.0); + target++; + + NumberOfElements = self->GetNumberOfElements(); + + // loop through pixel of output + inPtr = (T *)inArray->GetVoidPointer((hoodMin0 - inExt[0])* inInc0 + + (hoodMin1 - inExt[2])* inInc1 + + (hoodMin2 - inExt[4])* inInc2); + inPtr2 = inPtr; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + inPtr1 = inPtr2; + hoodMin1 = hoodStartMin1; + hoodMax1 = hoodStartMax1; + for (outIdx1 = outExt[2]; + !self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + inPtr0 = inPtr1; + hoodMin0 = hoodStartMin0; + hoodMax0 = hoodStartMax0; + for (outIdx0 = outExt[0]; outIdx0 <= outExt[1]; ++outIdx0) + { + for (outIdxC = 0; outIdxC < numComp; outIdxC++) + { + // Compute median of neighborhood + // Note: For boundary, NumNeighborhood could be changed for + // a faster sort. + DownNum = UpNum = 0; + Median = Sort + (NumberOfElements / 2) + 4; + // loop through neighborhood pixels + tmpPtr2 = inPtr0 + outIdxC; + for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2) + { + tmpPtr1 = tmpPtr2; + for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1) + { + tmpPtr0 = tmpPtr1; + for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0) + { + // Add this pixel to the median + Median = vtkImageMedian3DAccumulateMedian(UpNum, DownNum, + UpMax, DownMax, + NumberOfElements, + Median, + double(*tmpPtr0)); + + tmpPtr0 += inInc0; + } + tmpPtr1 += inInc1; + } + tmpPtr2 += inInc2; + } + + // Replace this pixel with the hood median + *outPtr = (T)(*Median); + outPtr++; + } + + // shift neighborhood considering boundaries + if (outIdx0 >= middleMin0) + { + inPtr0 += inInc0; + ++hoodMin0; + } + if (outIdx0 < middleMax0) + { + ++hoodMax0; + } + } + // shift neighborhood considering boundaries + if (outIdx1 >= middleMin1) + { + inPtr1 += inInc1; + ++hoodMin1; + } + if (outIdx1 < middleMax1) + { + ++hoodMax1; + } + outPtr += outIncY; + } + // shift neighborhood considering boundaries + if (outIdx2 >= middleMin2) + { + inPtr2 += inInc2; + ++hoodMin2; + } + if (outIdx2 < middleMax2) + { + ++hoodMax2; + } + outPtr += outIncZ; + } + + delete [] Sort; +} + +//----------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output region types. +void vtkImageMedian3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr; + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + vtkDataArray *inArray = this->GetInputArrayToProcess(0,inputVector); + if (id == 0) + { + outData[0]->GetPointData()->GetScalars()->SetName(inArray->GetName()); + } + + inPtr = inArray->GetVoidPointer(0); + + // this filter expects that input is the same type as output. + if (inArray->GetDataType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input data type, " << inArray->GetDataType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + switch (inArray->GetDataType()) + { + vtkTemplateMacro( + vtkImageMedian3DExecute(this,inData[0][0], + (VTK_TT *)(inPtr), + outData[0], (VTK_TT *)(outPtr),outExt, id, + inArray)); + default: + vtkErrorMacro(<< "Execute: Unknown input ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageMedian3D.h b/Imaging/vtkImageMedian3D.h new file mode 100644 index 0000000..2e85c5f --- /dev/null +++ b/Imaging/vtkImageMedian3D.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMedian3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMedian3D - Median Filter +// .SECTION Description +// vtkImageMedian3D a Median filter that replaces each pixel with the +// median value from a rectangular neighborhood around that pixel. +// Neighborhoods can be no more than 3 dimensional. Setting one +// axis of the neighborhood kernelSize to 1 changes the filter +// into a 2D median. + + +#ifndef __vtkImageMedian3D_h +#define __vtkImageMedian3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageMedian3D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageMedian3D *New(); + vtkTypeRevisionMacro(vtkImageMedian3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sets the size of the neighborhood. It also sets the + // default middle of the neighborhood + void SetKernelSize(int size0, int size1, int size2); + + // Description: + // Return the number of elements in the median mask + vtkGetMacro(NumberOfElements,int); + +protected: + vtkImageMedian3D(); + ~vtkImageMedian3D(); + + int NumberOfElements; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + +private: + vtkImageMedian3D(const vtkImageMedian3D&); // Not implemented. + void operator=(const vtkImageMedian3D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageMirrorPad.cxx b/Imaging/vtkImageMirrorPad.cxx new file mode 100644 index 0000000..14d9658 --- /dev/null +++ b/Imaging/vtkImageMirrorPad.cxx @@ -0,0 +1,256 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMirrorPad.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageMirrorPad.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageMirrorPad, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkImageMirrorPad); + +//---------------------------------------------------------------------------- +// Just clip the request. +void vtkImageMirrorPad::ComputeInputUpdateExtent(int inExt[6], + int outExt[6], + int wExtent[6]) +{ + int idx; + + // initialize inExt + memcpy(inExt,wExtent,6*sizeof(int)); + + // a simple approximation to the required extent + // basically get the whole extent for an axis unless a fully + // contained subset is being requested. If so then use that. + for (idx = 0; idx < 3; idx++) + { + if (outExt[idx*2] >= wExtent[idx*2] && + outExt[idx*2+1] <= wExtent[idx*2+1]) + { + inExt[idx*2] = outExt[idx*2]; + inExt[idx*2+1] = outExt[idx*2+1]; + } + } +} + + +//---------------------------------------------------------------------------- +template +void vtkImageMirrorPadExecute(vtkImageMirrorPad *self, + vtkImageData *inData, + int *wExtent, + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int maxX, maxY, maxZ; + vtkIdType inInc[3]; + int inIncStart[3]; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int idx; + int inIdxStart[3]; + int inIdx[3]; + T *inPtr, *inPtrX, *inPtrY, *inPtrZ; + int maxC, inMaxC; + + // find the region to loop over + inMaxC = inData->GetNumberOfScalarComponents(); + maxC = outData->GetNumberOfScalarComponents(); + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + inData->GetIncrements(inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // find the starting point + for (idx = 0; idx < 3; idx++) + { + inIdxStart[idx] = outExt[idx*2]; + inIncStart[idx] = 1; + while (inIdxStart[idx] < wExtent[idx*2]) + { + inIncStart[idx] = -inIncStart[idx]; + inIdxStart[idx] = inIdxStart[idx] + (wExtent[idx*2+1] - wExtent[idx*2] + 1); + } + while (inIdxStart[idx] > wExtent[idx*2+1]) + { + inIncStart[idx] = -inIncStart[idx]; + inIdxStart[idx] = inIdxStart[idx] - (wExtent[idx*2+1] - wExtent[idx*2] + 1); + } + // if we are heading negative then we need to mirror the offset + if (inIncStart[idx] < 0) + { + inIdxStart[idx] = wExtent[idx*2+1] - inIdxStart[idx] + wExtent[idx*2]; + } + } + inPtr = (T *)inData->GetScalarPointer(inIdxStart[0], inIdxStart[1], inIdxStart[2]); + + // Loop through ouput pixels + inPtrZ = inPtr; + inIdx[2] = inIdxStart[2]; + inInc[2] = inIncStart[2]; + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + inPtrY = inPtrZ; + inIdx[1] = inIdxStart[1]; + inInc[1] = inIncStart[1]; + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + inPtrX = inPtrY; + inIdx[0] = inIdxStart[0]; + inInc[0] = inIncStart[0]; + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + // if components are same much faster + if ((maxC == inMaxC) && (maxC == 1)) + { + for (idxX = 0; idxX <= maxX; idxX++) + { + // Pixel operation + *outPtr = *inPtrX; + outPtr++; + inIdx[0] += inInc[0]; + inPtrX = inPtrX + inInc[0]*inIncX; + if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1]) + { + inInc[0] *= -1; + inIdx[0] += inInc[0]; + inPtrX = inPtrX + inInc[0]*inIncX; + } + } + } + else // components are not the same + { + for (idxX = 0; idxX <= maxX; idxX++) + { + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + if (idxC < inMaxC) + { + *outPtr = *(inPtrX + idxC); + } + else + { + *outPtr = *(inPtrX + idxC%inMaxC); + } + outPtr++; + } + inIdx[0] += inInc[0]; + inPtrX = inPtrX + inInc[0]*inIncX; + if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1]) + { + inInc[0] *= -1; + inIdx[0] += inInc[0]; + inPtrX = inPtrX + inInc[0]*inIncX; + } + } + } + + outPtr += outIncY; + inIdx[1] += inInc[1]; + inPtrY = inPtrY + inInc[1]*inIncY; + if (inIdx[1] < wExtent[2] || inIdx[1] > wExtent[3]) + { + inInc[1] *= -1; + inIdx[1] += inInc[1]; + inPtrY = inPtrY + inInc[1]*inIncY; + } + } + outPtr += outIncZ; + inIdx[2] += inInc[2]; + inPtrZ = inPtrZ + inInc[2]*inIncZ; + if (inIdx[2] < wExtent[4] || inIdx[2] > wExtent[5]) + { + inInc[2] *= -1; + inIdx[2] += inInc[2]; + inPtrZ = inPtrZ + inInc[2]*inIncZ; + } + } +} + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output data, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageMirrorPad::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + // return if nothing to do + if (outExt[1] < outExt[0] || + outExt[3] < outExt[2] || + outExt[5] < outExt[4]) + { + return; + } + + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + // get the whole extent + int wExt[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageMirrorPadExecute(this, inData[0][0], wExt, + outData[0], (VTK_TT *)(outPtr), outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + + + + diff --git a/Imaging/vtkImageMirrorPad.h b/Imaging/vtkImageMirrorPad.h new file mode 100644 index 0000000..d869711 --- /dev/null +++ b/Imaging/vtkImageMirrorPad.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMirrorPad.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMirrorPad - Extra pixels are filled by mirror images. +// .SECTION Description +// vtkImageMirrorPad makes an image larger by filling extra pixels with +// a mirror image of the original image (mirror at image boundaries). + + +#ifndef __vtkImageMirrorPad_h +#define __vtkImageMirrorPad_h + + +#include "vtkImagePadFilter.h" + +class VTK_IMAGING_EXPORT vtkImageMirrorPad : public vtkImagePadFilter +{ +public: + static vtkImageMirrorPad *New(); + vtkTypeRevisionMacro(vtkImageMirrorPad,vtkImagePadFilter); + +protected: + vtkImageMirrorPad() {}; + ~vtkImageMirrorPad() {}; + + void ComputeInputUpdateExtent(int inExt[6], int outExt[6], int wExt[6]); + void ThreadedRequestData (vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); +private: + vtkImageMirrorPad(const vtkImageMirrorPad&); // Not implemented. + void operator=(const vtkImageMirrorPad&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageNoiseSource.cxx b/Imaging/vtkImageNoiseSource.cxx new file mode 100644 index 0000000..433223e --- /dev/null +++ b/Imaging/vtkImageNoiseSource.cxx @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageNoiseSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageNoiseSource.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageNoiseSource, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkImageNoiseSource); + +//---------------------------------------------------------------------------- +vtkImageNoiseSource::vtkImageNoiseSource() +{ + this->Minimum = 0.0; + this->Maximum = 10.0; + this->WholeExtent[0] = 0; this->WholeExtent[1] = 255; + this->WholeExtent[2] = 0; this->WholeExtent[3] = 255; + this->WholeExtent[4] = 0; this->WholeExtent[5] = 0; + this->SetNumberOfInputPorts(0); +} + + +//---------------------------------------------------------------------------- +void vtkImageNoiseSource::SetWholeExtent(int xMin, int xMax, + int yMin, int yMax, + int zMin, int zMax) +{ + int modified = 0; + + if (this->WholeExtent[0] != xMin) + { + modified = 1; + this->WholeExtent[0] = xMin ; + } + if (this->WholeExtent[1] != xMax) + { + modified = 1; + this->WholeExtent[1] = xMax ; + } + if (this->WholeExtent[2] != yMin) + { + modified = 1; + this->WholeExtent[2] = yMin ; + } + if (this->WholeExtent[3] != yMax) + { + modified = 1; + this->WholeExtent[3] = yMax ; + } + if (this->WholeExtent[4] != zMin) + { + modified = 1; + this->WholeExtent[4] = zMin ; + } + if (this->WholeExtent[5] != zMax) + { + modified = 1; + this->WholeExtent[5] = zMax ; + } + if (modified) + { + this->Modified(); + } +} +//---------------------------------------------------------------------------- +int vtkImageNoiseSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent,6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 1); + return 1; +} + +void vtkImageNoiseSource::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + + if (data->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Execute: This source only outputs doubles"); + } + + vtkImageProgressIterator outIt(data, data->GetExtent(), this, 0); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + double* outSI = outIt.BeginSpan(); + double* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // now process the components + *outSI = this->Minimum + + (this->Maximum - this->Minimum) * vtkMath::Random(); + outSI++; + } + outIt.NextSpan(); + } +} + +void vtkImageNoiseSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Minimum: " << this->Minimum << "\n"; + os << indent << "Maximum: " << this->Maximum << "\n"; +} + diff --git a/Imaging/vtkImageNoiseSource.h b/Imaging/vtkImageNoiseSource.h new file mode 100644 index 0000000..22c25ce --- /dev/null +++ b/Imaging/vtkImageNoiseSource.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageNoiseSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageNoiseSource - Create an image filled with noise. +// .SECTION Description +// vtkImageNoiseSource just produces images filled with noise. The only +// option now is uniform noise specified by a min and a max. There is one +// major problem with this source. Every time it executes, it will output +// different pixel values. This has important implications when a stream +// requests overlapping regions. The same pixels will have different values +// on different updates. + + +#ifndef __vtkImageNoiseSource_h +#define __vtkImageNoiseSource_h + + +#include "vtkImageAlgorithm.h" + + +class VTK_IMAGING_EXPORT vtkImageNoiseSource : public vtkImageAlgorithm +{ +public: + static vtkImageNoiseSource *New(); + vtkTypeRevisionMacro(vtkImageNoiseSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the minimum and maximum values for the generated noise. + vtkSetMacro(Minimum, double); + vtkGetMacro(Minimum, double); + vtkSetMacro(Maximum, double); + vtkGetMacro(Maximum, double); + + // Description: + // Set how large of an image to generate. + void SetWholeExtent(int xMinx, int xMax, int yMin, int yMax, + int zMin, int zMax); + +protected: + vtkImageNoiseSource(); + ~vtkImageNoiseSource() {}; + + double Minimum; + double Maximum; + int WholeExtent[6]; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); + virtual void ExecuteData(vtkDataObject *data); +private: + vtkImageNoiseSource(const vtkImageNoiseSource&); // Not implemented. + void operator=(const vtkImageNoiseSource&); // Not implemented. +}; + + +#endif + + diff --git a/Imaging/vtkImageNonMaximumSuppression.cxx b/Imaging/vtkImageNonMaximumSuppression.cxx new file mode 100644 index 0000000..e8d8e34 --- /dev/null +++ b/Imaging/vtkImageNonMaximumSuppression.cxx @@ -0,0 +1,341 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageNonMaximumSuppression.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageNonMaximumSuppression.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkImageNonMaximumSuppression, "$Revision: 1.55 $"); +vtkStandardNewMacro(vtkImageNonMaximumSuppression); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageNonMaximumSuppression fitler. +vtkImageNonMaximumSuppression::vtkImageNonMaximumSuppression() +{ + this->Dimensionality= 2; + this->HandleBoundaries = 1; + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +// This method is passed a region that holds the image extent of this filters +// input, and changes the region to hold the image extent of this filters +// output. +int vtkImageNonMaximumSuppression::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int extent[6]; + int idx; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + if ( ! this->HandleBoundaries) + { + // shrink output image extent. + for (idx = 0; idx < this->Dimensionality; ++idx) + { + extent[idx*2] += 1; + extent[idx*2+1] -= 1; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This method computes the input extent necessary to generate the output. +int vtkImageNonMaximumSuppression::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation* inInfo2 = inputVector[1]->GetInformationObject(0); + + int *wholeExtent; + int idx; + + // get the whole image for input 2 + int inExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt); + wholeExtent = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + inInfo2->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + // grow input image extent for input 0 + for (idx = 0; idx < this->Dimensionality; ++idx) + { + inExt[idx*2] -= 1; + inExt[idx*2+1] += 1; + if (this->HandleBoundaries) + { + // we must clip extent with whole extent if we hanlde boundaries. + if (inExt[idx*2] < wholeExtent[idx*2]) + { + inExt[idx*2] = wholeExtent[idx*2]; + } + if (inExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + inExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } + } + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the two input operations +template +void vtkImageNonMaximumSuppressionExecute(vtkImageNonMaximumSuppression *self, + vtkImageData *in1Data, T *in1Ptr, + vtkImageData *in2Data, + T *in2Ptr, + vtkImageData *outData, + T *outPtr, + int outExt[6], int id) +{ + int idxC, idxX, idxY, idxZ; + int maxC, maxX, maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType in2IncX, in2IncY, in2IncZ; + vtkIdType outIncX, outIncY, outIncZ; + unsigned long count = 0; + unsigned long target; + int useZMin, useZMax, useYMin, useYMax, useXMin, useXMax; + double d, normalizeFactor, vector[3], *ratio; + int neighborA, neighborB; + int *wholeExtent; + vtkIdType *inIncs; + int axesNum; + + // find the region to loop over + maxC = outData->GetNumberOfScalarComponents(); + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get the dimensionality of the gradient. + axesNum = self->GetDimensionality(); + // get some other info we need + inIncs = in1Data->GetIncrements(); + wholeExtent = in1Data->GetExtent(); + + // Get increments to march through data + in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + in2Data->GetContinuousIncrements(outExt, in2IncX, in2IncY, in2IncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + + // Gradient is computed with data spacing (world coordinates) + ratio = in2Data->GetSpacing(); + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + useZMin = ((idxZ + outExt[4]) <= wholeExtent[4]) ? 0 : -inIncs[2]; + useZMax = ((idxZ + outExt[4]) >= wholeExtent[5]) ? 0 : inIncs[2]; + for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++) + { + useYMin = ((idxY + outExt[2]) <= wholeExtent[2]) ? 0 : -inIncs[1]; + useYMax = ((idxY + outExt[2]) >= wholeExtent[3]) ? 0 : inIncs[1]; + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + for (idxX = 0; idxX <= maxX; idxX++) + { + useXMin = ((idxX + outExt[0]) <= wholeExtent[0]) ? 0 : -inIncs[0]; + useXMax = ((idxX + outExt[0]) >= wholeExtent[1]) ? 0 : inIncs[0]; + + // calculate the neighbors + d = vector[0] = (double)*in2Ptr * ratio[0]; + normalizeFactor = (d * d); + d = vector[1] = (double)in2Ptr[1] * ratio[1]; + normalizeFactor += (d * d); + if (axesNum == 3) + { + d = vector[2] = (double)in2Ptr[2] * ratio[2]; + normalizeFactor += (d * d); + } + if (normalizeFactor) + { + normalizeFactor = 1.0 / sqrt(normalizeFactor); + } + // Vector points positive along this idx? + // (can point along multiple axes) + d = vector[0] * normalizeFactor; + + if (d > 0.5) + { + neighborA = useXMax; + neighborB = useXMin; + } + else if (d < -0.5) + { + neighborB = useXMax; + neighborA = useXMin; + } + else + { + neighborA = 0; + neighborB = 0; + } + d = vector[1] * normalizeFactor; + if (d > 0.5) + { + neighborA += useYMax; + neighborB += useYMin; + } + else if (d < -0.5) + { + neighborB += useYMax; + neighborA += useYMin; + } + if (axesNum == 3) + { + d = vector[2] * normalizeFactor; + if (d > 0.5) + { + neighborA += useZMax; + neighborB += useZMin; + } + else if (d < -0.5) + { + neighborB += useZMax; + neighborA += useZMin; + } + } + + // now process the components + for (idxC = 0; idxC < maxC; idxC++) + { + // Pixel operation + // Set Output Magnitude + if (in1Ptr[neighborA] > *in1Ptr || in1Ptr[neighborB] > *in1Ptr) + { + *outPtr = 0; + } + else + { + *outPtr = *in1Ptr; + // also check for them being equal is neighbor with larger ptr + if ((neighborA > neighborB)&&(in1Ptr[neighborA] == *in1Ptr)) + { + *outPtr = 0; + } + else if ((neighborB > neighborA)&&(in1Ptr[neighborB] == *in1Ptr)) + { + *outPtr = 0; + } + } + outPtr++; + in1Ptr++; + } + in2Ptr += axesNum; + } + outPtr += outIncY; + in1Ptr += inIncY; + in2Ptr += in2IncY; + } + outPtr += outIncZ; + in1Ptr += inIncZ; + in2Ptr += in2IncZ; + } +} + +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageNonMaximumSuppression::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *in1Ptr; + void *in2Ptr; + void *outPtr; + + if (id == 0) + { + if (outData[0] && outData[0]->GetPointData()->GetScalars()) + { + outData[0]->GetPointData()->GetScalars()->SetName("SuppressedMaximum"); + } + } + + in1Ptr = inData[0][0]->GetScalarPointerForExtent(outExt); + in2Ptr = inData[1][0]->GetScalarPointerForExtent(outExt); + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType() || + inData[1][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << + inData[0][0]->GetScalarType() + << ", must match out ScalarType " << outData[0]->GetScalarType()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageNonMaximumSuppressionExecute(this, inData[0][0], + (VTK_TT *)(in1Ptr),inData[1][0], + (VTK_TT *)(in2Ptr), + outData[0], (VTK_TT *)(outPtr), + outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageNonMaximumSuppression::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; + + os << indent << "HandleBoundaries: " << (this->HandleBoundaries ? "On\n" : "Off\n"); +} diff --git a/Imaging/vtkImageNonMaximumSuppression.h b/Imaging/vtkImageNonMaximumSuppression.h new file mode 100644 index 0000000..264b102 --- /dev/null +++ b/Imaging/vtkImageNonMaximumSuppression.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageNonMaximumSuppression.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageNonMaximumSuppression - Performs non-maximum suppression +// .SECTION Description +// vtkImageNonMaximumSuppression Sets to zero any pixel that is not a peak. +// If a pixel has a neighbor along the vector that has larger magnitude, the +// smaller pixel is set to zero. The filter takes two inputs: a magnitude +// and a vector. Output is magnitude information and is always in doubles. +// Typically this filter is used with vtkImageGradient and +// vtkImageGradientMagnitude as inputs. + + +#ifndef __vtkImageNonMaximumSuppression_h +#define __vtkImageNonMaximumSuppression_h + +#define VTK_IMAGE_NON_MAXIMUM_SUPPRESSION_MAGNITUDE_INPUT 0 +#define VTK_IMAGE_NON_MAXIMUM_SUPPRESSION_VECTOR_INPUT 1 + +#include "vtkThreadedImageAlgorithm.h" +#include "vtkImageData.h" // makes things a bit easier + +class VTK_IMAGING_EXPORT vtkImageNonMaximumSuppression : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageNonMaximumSuppression *New(); + vtkTypeRevisionMacro(vtkImageNonMaximumSuppression,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the magnitude and vector inputs. + void SetMagnitudeInput(vtkImageData *input) {this->SetInput(0,input);}; + void SetVectorInput(vtkImageData *input) {this->SetInput(1,input);}; + + // Description: + // If "HandleBoundariesOn" then boundary pixels are duplicated + // So central differences can get values. + vtkSetMacro(HandleBoundaries, int); + vtkGetMacro(HandleBoundaries, int); + vtkBooleanMacro(HandleBoundaries, int); + + // Description: + // Determines how the input is interpreted (set of 2d slices or a 3D volume) + vtkSetClampMacro(Dimensionality,int,2,3); + vtkGetMacro(Dimensionality,int); + +protected: + vtkImageNonMaximumSuppression(); + ~vtkImageNonMaximumSuppression() {}; + + int HandleBoundaries; + int Dimensionality; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + +private: + vtkImageNonMaximumSuppression(const vtkImageNonMaximumSuppression&); // Not implemented. + void operator=(const vtkImageNonMaximumSuppression&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageNormalize.cxx b/Imaging/vtkImageNormalize.cxx new file mode 100644 index 0000000..c389b2f --- /dev/null +++ b/Imaging/vtkImageNormalize.cxx @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageNormalize.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageNormalize.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageNormalize, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkImageNormalize); + +//---------------------------------------------------------------------------- +vtkImageNormalize::vtkImageNormalize() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +int vtkImageNormalize::RequestInformation ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1); + return 1; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageNormalizeExecute(vtkImageNormalize *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + int idxC, maxC; + float sum; + T *inVect; + + // find the region to loop over + maxC = inData->GetNumberOfScalarComponents(); + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + float *outSI = outIt.BeginSpan(); + float *outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // save the start of the vector + inVect = inSI; + + // compute the magnitude. + sum = 0.0; + for (idxC = 0; idxC < maxC; idxC++) + { + sum += (float)(*inSI) * (float)(*inSI); + inSI++; + } + if (sum > 0.0) + { + sum = 1.0 / sqrt(sum); + } + + // now divide to normalize. + for (idxC = 0; idxC < maxC; idxC++) + { + *outSI = (float)(*inVect) * sum; + inVect++; + outSI++; + } + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input data type. The output data +// must match input type. This method does handle boundary conditions. +void vtkImageNormalize::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (outData->GetScalarType() != VTK_FLOAT) + { + vtkErrorMacro(<< "Execute: output ScalarType, " << outData->GetScalarType() + << ", must be float"); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageNormalizeExecute( this, inData, + outData, outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + diff --git a/Imaging/vtkImageNormalize.h b/Imaging/vtkImageNormalize.h new file mode 100644 index 0000000..af1c686 --- /dev/null +++ b/Imaging/vtkImageNormalize.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageNormalize.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageNormalize - Normalizes that scalar components for each point. +// .SECTION Description +// For each point, vtkImageNormalize normalizes the vector defined by the +// scalar components. If the magnitude of this vector is zero, the output +// vector is zero also. + + +#ifndef __vtkImageNormalize_h +#define __vtkImageNormalize_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageNormalize : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageNormalize *New(); + vtkTypeRevisionMacro(vtkImageNormalize,vtkThreadedImageAlgorithm); + +protected: + vtkImageNormalize(); + ~vtkImageNormalize() {}; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int extent[6], int id); +private: + vtkImageNormalize(const vtkImageNormalize&); // Not implemented. + void operator=(const vtkImageNormalize&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageOpenClose3D.cxx b/Imaging/vtkImageOpenClose3D.cxx new file mode 100644 index 0000000..d26abc7 --- /dev/null +++ b/Imaging/vtkImageOpenClose3D.cxx @@ -0,0 +1,311 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageOpenClose3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageOpenClose3D.h" + +#include "vtkGarbageCollector.h" +#include "vtkImageData.h" +#include "vtkImageDilateErode3D.h" +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkExecutive.h" + +#include + +vtkCxxRevisionMacro(vtkImageOpenClose3D, "$Revision: 1.30.4.2 $"); +vtkStandardNewMacro(vtkImageOpenClose3D); + +//---------------------------------------------------------------------------- +// functions to convert progress calls. +class vtkImageOpenClose3DProgress : public vtkCommand +{ +public: + // generic new method + static vtkImageOpenClose3DProgress *New() + { return new vtkImageOpenClose3DProgress; } + + // the execute + virtual void Execute(vtkObject *caller, + unsigned long event, void* vtkNotUsed(v)) + { + vtkAlgorithm *alg = vtkAlgorithm::SafeDownCast(caller); + if (event == vtkCommand::ProgressEvent && alg) + { + this->Self->UpdateProgress(this->Offset + 0.5 * + alg->GetProgress()); + } + } + + // some ivars that should be set + vtkImageOpenClose3D *Self; + double Offset; +}; + +//---------------------------------------------------------------------------- +vtkImageOpenClose3D::vtkImageOpenClose3D() +{ + // create the filter chain + this->Filter0 = vtkImageDilateErode3D::New(); + vtkImageOpenClose3DProgress *cb = vtkImageOpenClose3DProgress::New(); + cb->Self = this; + cb->Offset = 0; + this->Filter0->AddObserver(vtkCommand::ProgressEvent, cb); + cb->Delete(); + + this->Filter1 = vtkImageDilateErode3D::New(); + cb = vtkImageOpenClose3DProgress::New(); + cb->Self = this; + cb->Offset = 0.5; + this->Filter1->AddObserver(vtkCommand::ProgressEvent, cb); + cb->Delete(); + this->SetOpenValue(0.0); + this->SetCloseValue(255.0); + + // connect up the internal pipeline + this->Filter1->SetInputConnection(this->Filter0->GetOutputPort()); +} + +//---------------------------------------------------------------------------- +// Destructor: Delete the sub filters. +vtkImageOpenClose3D::~vtkImageOpenClose3D() +{ + if (this->Filter0) + { + this->Filter0->Delete(); + } + + if (this->Filter1) + { + this->Filter1->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageOpenClose3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Filter0: \n"; + this->Filter0->PrintSelf(os, indent.GetNextIndent()); + os << indent << "Filter1: \n"; + this->Filter1->PrintSelf(os, indent.GetNextIndent()); +} + +//---------------------------------------------------------------------------- +// Turn debugging output on. (in sub filters also) +void vtkImageOpenClose3D::DebugOn() +{ + this->vtkObject::DebugOn(); + if (this->Filter0) + { + this->Filter0->DebugOn(); + } + if (this->Filter1) + { + this->Filter1->DebugOn(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageOpenClose3D::DebugOff() +{ + this->vtkObject::DebugOff(); + if (this->Filter0) + { + this->Filter0->DebugOff(); + } + if (this->Filter1) + { + this->Filter1->DebugOff(); + } +} + +//---------------------------------------------------------------------------- +// Pass modified message to sub filters. +void vtkImageOpenClose3D::Modified() +{ + this->vtkObject::Modified(); + if (this->Filter0) + { + this->Filter0->Modified(); + } + + if (this->Filter1) + { + this->Filter1->Modified(); + } +} + + +//---------------------------------------------------------------------------- +// This method considers the sub filters MTimes when computing this objects +// MTime +unsigned long int vtkImageOpenClose3D::GetMTime() +{ + unsigned long int t1, t2; + + t1 = this->Superclass::GetMTime(); + if (this->Filter0) + { + t2 = this->Filter0->GetMTime(); + if (t2 > t1) + { + t1 = t2; + } + } + if (this->Filter1) + { + t2 = this->Filter1->GetMTime(); + if (t2 > t1) + { + t1 = t2; + } + } + + return t1; +} + +//---------------------------------------------------------------------------- +int +vtkImageOpenClose3D::ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int requestFromOutputPort, + unsigned long* mtime) +{ + // Process the request on the internal pipeline. Share our input + // information with the first filter and our output information with + // the last filter. + vtkExecutive* exec0 = this->Filter0->GetExecutive(); + vtkExecutive* exec1 = this->Filter1->GetExecutive(); + exec0->SetSharedInputInformation(inInfoVec); + exec1->SetSharedOutputInformation(outInfoVec); + unsigned long mtime1; + if(exec1->ComputePipelineMTime(request, + exec1->GetInputInformation(), + exec1->GetOutputInformation(), + requestFromOutputPort, &mtime1)) + { + // Now run the request in this algorithm. + return this->Superclass::ComputePipelineMTime(request, + inInfoVec, outInfoVec, + requestFromOutputPort, + mtime); + } + else + { + // The internal pipeline failed to process the request. + vtkErrorMacro("Internal pipeline failed to process pipeline modified " + "time request."); + return 0; + } +} + +//---------------------------------------------------------------------------- +int vtkImageOpenClose3D::ProcessRequest(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec) +{ + // Process the request on the internal pipeline. Share our input + // information with the first filter and our output information with + // the last filter. + vtkExecutive* exec0 = this->Filter0->GetExecutive(); + vtkExecutive* exec1 = this->Filter1->GetExecutive(); + exec0->SetSharedInputInformation(inInfoVec); + exec1->SetSharedOutputInformation(outInfoVec); + return exec1->ProcessRequest(request, + exec1->GetInputInformation(), + exec1->GetOutputInformation()); +} + +//---------------------------------------------------------------------------- +// Selects the size of gaps or objects removed. +void vtkImageOpenClose3D::SetKernelSize(int size0, int size1, int size2) +{ + if ( ! this->Filter0 || ! this->Filter1) + { + vtkErrorMacro(<< "SetKernelSize: Sub filter not created yet."); + return; + } + + this->Filter0->SetKernelSize(size0, size1, size2); + this->Filter1->SetKernelSize(size0, size1, size2); + // Sub filters take care of modified. +} + +//---------------------------------------------------------------------------- +// Determines the value that will closed. +// Close value is first dilated, and then eroded +void vtkImageOpenClose3D::SetCloseValue(double value) +{ + if ( ! this->Filter0 || ! this->Filter1) + { + vtkErrorMacro(<< "SetCloseValue: Sub filter not created yet."); + return; + } + + this->Filter0->SetDilateValue(value); + this->Filter1->SetErodeValue(value); +} + +//---------------------------------------------------------------------------- +double vtkImageOpenClose3D::GetCloseValue() +{ + if ( ! this->Filter0) + { + vtkErrorMacro(<< "GetCloseValue: Sub filter not created yet."); + return 0.0; + } + + return this->Filter0->GetDilateValue(); +} + +//---------------------------------------------------------------------------- +// Determines the value that will opened. +// Open value is first eroded, and then dilated. +void vtkImageOpenClose3D::SetOpenValue(double value) +{ + if ( ! this->Filter0 || ! this->Filter1) + { + vtkErrorMacro(<< "SetOpenValue: Sub filter not created yet."); + return; + } + + this->Filter0->SetErodeValue(value); + this->Filter1->SetDilateValue(value); +} + +//---------------------------------------------------------------------------- +double vtkImageOpenClose3D::GetOpenValue() +{ + if ( ! this->Filter0) + { + vtkErrorMacro(<< "GetOpenValue: Sub filter not created yet."); + return 0.0; + } + + return this->Filter0->GetErodeValue(); +} + +//---------------------------------------------------------------------------- +void vtkImageOpenClose3D::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->Filter0, "Filter0"); + vtkGarbageCollectorReport(collector, this->Filter1, "Filter1"); +} diff --git a/Imaging/vtkImageOpenClose3D.h b/Imaging/vtkImageOpenClose3D.h new file mode 100644 index 0000000..177fb99 --- /dev/null +++ b/Imaging/vtkImageOpenClose3D.h @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageOpenClose3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageOpenClose3D - Will perform opening or closing. +// .SECTION Description +// vtkImageOpenClose3D performs opening or closing by having two +// vtkImageErodeDilates in series. The size of operation +// is determined by the method SetKernelSize, and the operator is an ellipse. +// OpenValue and CloseValue determine how the filter behaves. For binary +// images Opening and closing behaves as expected. +// Close value is first dilated, and then eroded. +// Open value is first eroded, and then dilated. +// Degenerate two dimensional opening/closing can be achieved by setting the +// one axis the 3D KernelSize to 1. +// Values other than open value and close value are not touched. +// This enables the filter to processes segmented images containing more than +// two tags. + + +#ifndef __vtkImageOpenClose3D_h +#define __vtkImageOpenClose3D_h + + +#include "vtkImageAlgorithm.h" + +class vtkImageDilateErode3D; + +class VTK_IMAGING_EXPORT vtkImageOpenClose3D : public vtkImageAlgorithm +{ +public: + // Description: + // Default open value is 0, and default close value is 255. + static vtkImageOpenClose3D *New(); + vtkTypeRevisionMacro(vtkImageOpenClose3D,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method considers the sub filters MTimes when computing this objects + // modified time. + unsigned long int GetMTime(); + + // Description: + // Turn debugging output on. (in sub filters also) + void DebugOn(); + void DebugOff(); + + // Description: + // Pass modified message to sub filters. + void Modified(); + + // Foward Source messages to filter1 + + // Description: + // Selects the size of gaps or objects removed. + void SetKernelSize(int size0, int size1, int size2); + + // Description: + // Determines the value that will opened. + // Open value is first eroded, and then dilated. + void SetOpenValue(double value); + double GetOpenValue(); + + // Description: + // Determines the value that will closed. + // Close value is first dilated, and then eroded + void SetCloseValue(double value); + double GetCloseValue(); + + // Description: + // Needed for Progress functions + vtkGetObjectMacro(Filter0, vtkImageDilateErode3D); + vtkGetObjectMacro(Filter1, vtkImageDilateErode3D); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // Description: + // Override to send the request to internal pipeline. + virtual int + ComputePipelineMTime(vtkInformation* request, + vtkInformationVector** inInfoVec, + vtkInformationVector* outInfoVec, + int requestFromOutputPort, + unsigned long* mtime); + +protected: + vtkImageOpenClose3D(); + ~vtkImageOpenClose3D(); + + vtkImageDilateErode3D *Filter0; + vtkImageDilateErode3D *Filter1; + + virtual void ReportReferences(vtkGarbageCollector*); +private: + vtkImageOpenClose3D(const vtkImageOpenClose3D&); // Not implemented. + void operator=(const vtkImageOpenClose3D&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImagePadFilter.cxx b/Imaging/vtkImagePadFilter.cxx new file mode 100644 index 0000000..2fb27a3 --- /dev/null +++ b/Imaging/vtkImagePadFilter.cxx @@ -0,0 +1,189 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagePadFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImagePadFilter.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkDataSetAttributes.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImagePadFilter, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkImagePadFilter); + +//---------------------------------------------------------------------------- +// Constructor sets default values +vtkImagePadFilter::vtkImagePadFilter() +{ + int idx; + + // Initialize output image extent to INVALID + for (idx = 0; idx < 3; ++idx) + { + this->OutputWholeExtent[idx * 2] = 0; + this->OutputWholeExtent[idx * 2 + 1] = -1; + } + // Set Output numberOfScalarComponents to INVALID + this->OutputNumberOfScalarComponents = -1; +} + +//---------------------------------------------------------------------------- +void vtkImagePadFilter::SetOutputWholeExtent(int extent[6]) +{ + int idx, modified = 0; + + for (idx = 0; idx < 6; ++idx) + { + if (this->OutputWholeExtent[idx] != extent[idx]) + { + this->OutputWholeExtent[idx] = extent[idx]; + modified = 1; + } + } + + if (modified) + { + this->Modified(); + } +} +//---------------------------------------------------------------------------- +void vtkImagePadFilter::SetOutputWholeExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetOutputWholeExtent(extent); +} + + +//---------------------------------------------------------------------------- +void vtkImagePadFilter::GetOutputWholeExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + extent[idx] = this->OutputWholeExtent[idx]; + } +} + + +//---------------------------------------------------------------------------- +// Just change the Image extent. +int vtkImagePadFilter::RequestInformation ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + + if (this->OutputWholeExtent[0] > this->OutputWholeExtent[1]) + { + // invalid setting, it has not been set, so default to whole Extent + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->OutputWholeExtent); + } + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->OutputWholeExtent,6); + + if (this->OutputNumberOfScalarComponents < 0) + { + vtkInformation *inScalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!inScalarInfo) + { + vtkErrorMacro("Missing scalar field on input information!"); + return 0; + } + // invalid setting, it has not been set, so default to input. + this->OutputNumberOfScalarComponents + = inScalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()); + } + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, -1, + this->OutputNumberOfScalarComponents); + return 1; +} + +void vtkImagePadFilter::ComputeInputUpdateExtent (int inExt[6], + int outExt[6], + int wholeExtent[6]) +{ + int idx; + + // Clip + for (idx = 0; idx < 3; ++idx) + { + inExt[idx*2] = outExt[idx*2]; + inExt[idx*2+1] = outExt[idx*2+1]; + if (inExt[idx*2] < wholeExtent[idx*2]) + { + inExt[idx*2] = wholeExtent[idx*2]; + } + if (inExt[idx*2] > wholeExtent[idx*2 + 1]) + { + inExt[idx*2] = wholeExtent[idx*2 + 1]; + } + if (inExt[idx*2+1] < wholeExtent[idx*2]) + { + inExt[idx*2+1] = wholeExtent[idx*2]; + } + if (inExt[idx*2 + 1] > wholeExtent[idx*2 + 1]) + { + inExt[idx*2 + 1] = wholeExtent[idx*2 + 1]; + } + } +} + +//---------------------------------------------------------------------------- +// Just clip the request. The subclass may need to overwrite this method. +int vtkImagePadFilter::RequestUpdateExtent ( + vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + + int wholeExtent[6]; + int inExt[6]; + + // handle XYZ + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt); + + this->ComputeInputUpdateExtent(inExt, inExt, wholeExtent); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + +void vtkImagePadFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "OutputNumberOfScalarComponents: " + << this->OutputNumberOfScalarComponents << "\n"; +} + + diff --git a/Imaging/vtkImagePadFilter.h b/Imaging/vtkImagePadFilter.h new file mode 100644 index 0000000..456d2c9 --- /dev/null +++ b/Imaging/vtkImagePadFilter.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagePadFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImagePadFilter - Super class for filters that fill in extra pixels. +// .SECTION Description +// vtkImagePadFilter Changes the image extent of an image. If the image +// extent is larger than the input image extent, the extra pixels are +// filled by an algorithm determined by the subclass. +// The image extent of the output has to be specified. + + +#ifndef __vtkImagePadFilter_h +#define __vtkImagePadFilter_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImagePadFilter : public vtkThreadedImageAlgorithm +{ +public: + static vtkImagePadFilter *New(); + vtkTypeRevisionMacro(vtkImagePadFilter,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The image extent of the output has to be set explicitly. + void SetOutputWholeExtent(int extent[6]); + void SetOutputWholeExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + void GetOutputWholeExtent(int extent[6]); + int *GetOutputWholeExtent() {return this->OutputWholeExtent;} + + // Description: + // Set/Get the number of output scalar components. + vtkSetMacro(OutputNumberOfScalarComponents, int); + vtkGetMacro(OutputNumberOfScalarComponents, int); + +protected: + vtkImagePadFilter(); + ~vtkImagePadFilter() {}; + + int OutputWholeExtent[6]; + int OutputNumberOfScalarComponents; + + virtual int RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + virtual int RequestUpdateExtent(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + virtual void ComputeInputUpdateExtent (int inExt[6], int outExt[6], + int wExt[6]); + +private: + vtkImagePadFilter(const vtkImagePadFilter&); // Not implemented. + void operator=(const vtkImagePadFilter&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImagePermute.cxx b/Imaging/vtkImagePermute.cxx new file mode 100644 index 0000000..58aec08 --- /dev/null +++ b/Imaging/vtkImagePermute.cxx @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagePermute.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImagePermute.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImagePermute, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkImagePermute); + +vtkImagePermute::vtkImagePermute() +{ + this->FilteredAxes[0] = 0; + this->FilteredAxes[1] = 1; + this->FilteredAxes[2] = 2; +} + +void vtkImagePermute::SetFilteredAxes(int newx, int newy, int newz) +{ + static double axes[3][3] = { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }; + + this->SetResliceAxesDirectionCosines(axes[newx], axes[newy], axes[newz]); + + this->FilteredAxes[0] = newx; + this->FilteredAxes[1] = newy; + this->FilteredAxes[2] = newz; +} + +void vtkImagePermute::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "FilteredAxes: ( " + << this->FilteredAxes[0] << ", " + << this->FilteredAxes[1] << ", " + << this->FilteredAxes[2] << " )\n"; +} + diff --git a/Imaging/vtkImagePermute.h b/Imaging/vtkImagePermute.h new file mode 100644 index 0000000..8479928 --- /dev/null +++ b/Imaging/vtkImagePermute.h @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagePermute.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImagePermute - Permutes axes of input. +// .SECTION Description +// vtkImagePermute reorders the axes of the input. Filtered axes specify +// the input axes which become X, Y, Z. The input has to have the +// same scalar type of the output. The filter does copy the +// data when it executes. This filter is actually a very thin wrapper +// around vtkImageReslice. + +#ifndef __vtkImagePermute_h +#define __vtkImagePermute_h + + +#include "vtkImageReslice.h" + +class VTK_IMAGING_EXPORT vtkImagePermute : public vtkImageReslice +{ +public: + static vtkImagePermute *New(); + vtkTypeRevisionMacro(vtkImagePermute,vtkImageReslice); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The filtered axes are the input axes that get relabeled to X,Y,Z. + void SetFilteredAxes(int x, int y, int z); + void SetFilteredAxes(const int xyz[3]) { + this->SetFilteredAxes(xyz[0], xyz[1], xyz[2]); }; + vtkGetVector3Macro(FilteredAxes, int); + +protected: + vtkImagePermute(); + ~vtkImagePermute() {}; + + int FilteredAxes[3]; + +private: + vtkImagePermute(const vtkImagePermute&); // Not implemented. + void operator=(const vtkImagePermute&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageQuantizeRGBToIndex.cxx b/Imaging/vtkImageQuantizeRGBToIndex.cxx new file mode 100644 index 0000000..b9c4afe --- /dev/null +++ b/Imaging/vtkImageQuantizeRGBToIndex.cxx @@ -0,0 +1,677 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageQuantizeRGBToIndex.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageQuantizeRGBToIndex.h" + +#include "vtkImageData.h" +#include "vtkLookupTable.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTimerLog.h" + +#include + +vtkCxxRevisionMacro(vtkImageQuantizeRGBToIndex, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkImageQuantizeRGBToIndex); + +class vtkColorQuantizeNode +{ +public: + vtkColorQuantizeNode() + { this->Axis = -1; this->SplitPoint = -1; this->Index = -1; + this->Child1 = NULL; this->Child2 = NULL; + this->StdDev[0] = this->StdDev[1] = this->StdDev[2] = 0.0; + this->Histogram[0] = this->Histogram[1] = this->Histogram[2] = NULL; + this->Image = NULL; + this->Bounds[0] = 0; this->Bounds[1] = 256; + this->Bounds[2] = 0; this->Bounds[3] = 256; + this->Bounds[4] = 0; this->Bounds[5] = 256; }; + + ~vtkColorQuantizeNode() + { if ( this->Histogram[0] ) { delete []this->Histogram[0]; } + if ( this->Histogram[1] ) { delete []this->Histogram[1]; } + if ( this->Histogram[2] ) { delete []this->Histogram[2]; } + if ( this->Child1 ) { delete this->Child1; } + if ( this->Child2 ) { delete this->Child2; } }; + + void SetImageExtent( int v[6] ) + { memcpy( this->ImageExtent, v, 6*sizeof(int) ); }; + + void SetImageIncrement( vtkIdType v[3] ) + { memcpy( this->ImageIncrement, v, 3*sizeof(vtkIdType) ); }; + + void SetImageType( double type ) { this->ImageType = (int)type; }; + + void SetImage( void *image ) { this->Image = image; }; + + int GetAxis( ) { return this->Axis; }; + void SetAxis( int v ) { this->Axis = v; }; + + int GetSplitPoint( ) { return this->SplitPoint; }; + void SetSplitPoint( int v ) { this->SplitPoint = v; }; + + int *GetBounds( ) { return this->Bounds; }; + void SetBounds( int v[6] ) { memcpy( this->Bounds, v, 6*sizeof(int) ); }; + + int GetIndex( ) { return this->Index; }; + void SetIndex( int v ) { this->Index = v; }; + + double GetStdDev( int axis ) { return this->StdDev[axis]; }; + void ComputeStdDev(); + + int GetCount() { return this->Count; }; + + double GetMean( int axis ) { return this->Mean[axis]; }; + + void Divide( int axis, int nextIndex ); + + vtkColorQuantizeNode *GetChild1() { return this->Child1; }; + void SetChild1( vtkColorQuantizeNode *n ) { this->Child1 = n; }; + + vtkColorQuantizeNode *GetChild2() { return this->Child2; }; + void SetChild2( vtkColorQuantizeNode *n ) { this->Child2 = n; }; + + int GetIndex( int c[3] ) + { if ( this->Index>=0 ) {return this->Index;} + if ( c[this->Axis]>this->SplitPoint ) + {return this->Child2->GetIndex(c);} + return this->Child1->GetIndex(c); }; + + + void GetAverageColor( int c[3] ) + { if ( this->AverageCount ) { + c[0] = (int)(this->AverageColor[0] / this->AverageCount); + c[1] = (int)(this->AverageColor[1] / this->AverageCount); + c[2] = (int)(this->AverageColor[2] / this->AverageCount); } }; + + void StartColorAveraging() + {if (this->Child1) + { + this->Child1->StartColorAveraging(); this->Child2->StartColorAveraging(); + } + else + { + this->AverageCount = 0; + this->AverageColor[0] = + this->AverageColor[1] = this->AverageColor[2] = 0.0; + } + }; + + void AddColor( int c[3] ) + { this->AverageCount++; this->AverageColor[0] += c[0]; + this->AverageColor[1] += c[1]; this->AverageColor[2] += c[2]; }; + +protected: + int Axis; + int SplitPoint; + int Bounds[6]; + int Index; + double StdDev[3]; + double Median[3]; + double Mean[3]; + int Count; + int AverageCount; + double AverageColor[3]; + vtkIdType ImageIncrement[3]; + int ImageExtent[6]; + int ImageType; + void *Image; + int *Histogram[3]; + vtkColorQuantizeNode *Child1, *Child2; +}; + +template +void vtkImageQuantizeRGBToIndexHistogram( T *inPtr, int extent[6], + vtkIdType inIncrement[3], int type, + int bounds[6], int *histogram[3] ) +{ + T *rgbPtr, v[3]; + int x, y, z, c; + int value[3]; + int max[3]; + + max[0] = bounds[1] - bounds[0] + 1; + max[1] = bounds[3] - bounds[2] + 1; + max[2] = bounds[5] - bounds[4] + 1; + + for ( c = 0; c < 3; c++ ) + { + for ( x = 0; x < max[c]; x++ ) + { + histogram[c][x] = 0; + } + } + + // Generate the histogram + rgbPtr = inPtr; + for (z = extent[4]; z <= extent[5]; z++) + { + for (y = extent[2]; y <= extent[3]; y++) + { + for (x = extent[0]; x <= extent[1]; x++) + { + if ( type == VTK_UNSIGNED_CHAR ) + { + v[0] = *(rgbPtr++) - bounds[0]; + v[1] = *(rgbPtr++) - bounds[2]; + v[2] = *(rgbPtr++) - bounds[4]; + if ( (int)v[0] < max[0] && (int)v[1] < max[1] && (int)v[2] < max[2] ) + { + histogram[0][(unsigned char)v[0]]++; + histogram[1][(unsigned char)v[1]]++; + histogram[2][(unsigned char)v[2]]++; + } + } + else if ( type == VTK_UNSIGNED_SHORT ) + { + v[0] = (((unsigned short)(*(rgbPtr++)))>>8) - bounds[0]; + v[1] = (((unsigned short)(*(rgbPtr++)))>>8) - bounds[2]; + v[2] = (((unsigned short)(*(rgbPtr++)))>>8) - bounds[4]; + if ((int)(v[0]) < max[0] && (int)(v[1]) < max[1] && (int)(v[2]) < max[2] ) + { + histogram[0][(unsigned short)v[0]]++; + histogram[1][(unsigned short)v[1]]++; + histogram[2][(unsigned short)v[2]]++; + } + } + else + { + value[0] = (int)( *(rgbPtr++) * 255.5 ) - bounds[0]; + value[1] = (int)( *(rgbPtr++) * 255.5 ) - bounds[2]; + value[2] = (int)( *(rgbPtr++) * 255.5 ) - bounds[4]; + if ( (int)(v[0]) < max[0] && (int)(v[1]) < max[1] && (int)(v[2]) < max[2] ) + { + histogram[0][value[0]]++; + histogram[1][value[1]]++; + histogram[2][value[2]]++; + } + } + rgbPtr += inIncrement[0]; + } + rgbPtr += inIncrement[1]; + } + rgbPtr += inIncrement[2]; + } +} + +// This templated function executes the filter for supported types of data. +template +void vtkImageQuantizeRGBToIndexExecute(vtkImageQuantizeRGBToIndex *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, + unsigned short *outPtr) +{ + int extent[6]; + vtkIdType inIncrement[3], outIncrement[3]; + T *rgbPtr; + unsigned short *indexPtr; + int x, y, z, c; + int type; + vtkColorQuantizeNode *root, *tmp; + vtkColorQuantizeNode *leafNodes[65536]; + int numLeafNodes; + int maxdevAxis = 0, maxdevLeafNode = 0; + double maxdev, dev; + int leaf, axis; + int cannotDivideFurther; + vtkLookupTable *lut; + double color[4]; + int rgb[3]; + vtkTimerLog *timer; + int totalCount; + double weight; + int done=0; + + timer = vtkTimerLog::New(); + timer->StartTimer(); + type = self->GetInputType(); + + // need extent to get increments. + // in and out extents are the same + inData->GetExtent( extent ); + + inData->GetContinuousIncrements(extent, inIncrement[0], + inIncrement[1], inIncrement[2]); + outData->GetContinuousIncrements(extent, outIncrement[0], + outIncrement[1], outIncrement[2]); + + timer->StopTimer(); + + self->SetInitializeExecuteTime( timer->GetElapsedTime() ); + timer->StartTimer(); + + // Build the tree + // Create the root node - it is our only leaf node + root = new vtkColorQuantizeNode; + root->SetIndex( 0 ); + root->SetImageExtent( extent ); + root->SetImageIncrement( inIncrement ); + root->SetImageType( type ); + root->SetImage( inPtr ); + root->ComputeStdDev(); + leafNodes[0] = root; + numLeafNodes = 1; + + cannotDivideFurther = 0; + + totalCount = + (extent[1] - extent[0] + 1) * + (extent[3] - extent[2] + 1) * + (extent[5] - extent[4] + 1); + + // Loop until we've added enough leaf nodes or we can't add any more + while ( numLeafNodes < self->GetNumberOfColors() && !cannotDivideFurther ) + { + // Find leaf node / axis with maximum deviation + maxdev = 0.0; + for ( leaf = 0; leaf < numLeafNodes; leaf++ ) + { + for ( axis = 0; axis < 3; axis++ ) + { + dev = leafNodes[leaf]->GetStdDev( axis ); + weight = (double)(leafNodes[leaf]->GetCount())/(double)(totalCount); + dev *= weight; + if ( dev > maxdev ) + { + maxdevAxis = axis; + maxdevLeafNode = leaf; + maxdev = dev; + } + } + } + if ( maxdev == 0.0 ) + { + cannotDivideFurther = 1; + } + else + { + leafNodes[maxdevLeafNode]->Divide( maxdevAxis, numLeafNodes ); + leafNodes[numLeafNodes] = leafNodes[maxdevLeafNode]->GetChild1(); + leafNodes[maxdevLeafNode] = leafNodes[maxdevLeafNode]->GetChild2(); + numLeafNodes++; + } + + self->UpdateProgress(0.6667*numLeafNodes/self->GetNumberOfColors()); + } + + timer->StopTimer(); + self->SetBuildTreeExecuteTime( timer->GetElapsedTime() ); + timer->StartTimer(); + + root->StartColorAveraging(); + + // Fill in the indices in the output image + indexPtr = outPtr; + rgbPtr = inPtr; + for (z = extent[4]; z <= extent[5]; z++) + { + for (y = extent[2]; !self->AbortExecute && y <= extent[3]; y++) + { + for (x = extent[0]; x <= extent[1]; x++) + { + for (c = 0; c < 3; c++) + { + if ( type == VTK_UNSIGNED_CHAR ) + { + rgb[c] = (int)(*rgbPtr); + } + else if ( type == VTK_UNSIGNED_SHORT ) + { + rgb[c] = ((unsigned short)(*rgbPtr))>>8; + } + else + { + rgb[c] = (int)(*rgbPtr * 255.5); + } + rgbPtr++; + } + tmp = root; + while( !done ) + { + if ( tmp->GetIndex() != -1 ) + { + *indexPtr = tmp->GetIndex(); + break; + } + if ( rgb[tmp->GetAxis()] > tmp->GetSplitPoint() ) + { + tmp = tmp->GetChild2(); + } + else + { + tmp = tmp->GetChild1(); + } + } + tmp->AddColor( rgb ); + indexPtr++; + + rgbPtr += inIncrement[0]; + indexPtr += outIncrement[0]; + } + rgbPtr += inIncrement[1]; + indexPtr += outIncrement[1]; + } + rgbPtr += inIncrement[2]; + indexPtr += outIncrement[2]; + } + + self->UpdateProgress(0.90); + + // Fill in the lookup table + lut = self->GetLookupTable(); + lut->SetNumberOfTableValues( numLeafNodes ); + lut->SetNumberOfColors( numLeafNodes ); + lut->SetTableRange( 0, numLeafNodes-1 ); + color[3] = 1.0; + for ( leaf = 0; leaf < numLeafNodes; leaf++ ) + { + leafNodes[leaf]->GetAverageColor( rgb ); + color[0] = rgb[0] / 255.0; + color[1] = rgb[1] / 255.0; + color[2] = rgb[2] / 255.0; + lut->SetTableValue( leafNodes[leaf]->GetIndex(), color ); + } + + + timer->StopTimer(); + self->SetLookupIndexExecuteTime( timer->GetElapsedTime() ); + timer->Delete(); + + delete root; +} + +void vtkColorQuantizeNode::ComputeStdDev() +{ + int i, j; + double mean; + int count=0; + int medianCount; + + // Create space for histogram + this->Histogram[0] = new int[this->Bounds[1] - this->Bounds[0] + 1]; + this->Histogram[1] = new int[this->Bounds[3] - this->Bounds[2] + 1]; + this->Histogram[2] = new int[this->Bounds[5] - this->Bounds[4] + 1]; + + // Create histogram + switch (this->ImageType) + { + vtkTemplateMacro( + vtkImageQuantizeRGBToIndexHistogram( + (VTK_TT *)this->Image, this->ImageExtent, + this->ImageIncrement, this->ImageType, + this->Bounds, this->Histogram )); + } + + + // Compute for r, g, and b + for ( i = 0; i < 3; i++ ) + { + // Compute the mean + mean = 0; + count = 0; + for ( j = 0; j <= (this->Bounds[i*2 + 1] - this->Bounds[i*2]); j++ ) + { + count += this->Histogram[i][j]; + mean += this->Histogram[i][j] * (j + this->Bounds[i*2]); + } + if (count>0) + { + mean /= (double)count; + } + else + { + mean = 0; + } + this->Mean[i] = mean; + + // Must have some minimum distance to subdivide - if we + // are below this distance limit, don't compute a + // standard deviation since we don't want to subdivide this + // node along this axis. Set the deviation to 0.0 and continue. + if ( this->Bounds[i*2 + 1] == this->Bounds[i*2] ) + { + this->StdDev[i] = 0.0; + continue; + } + + + // Where is the median? + medianCount = count / 2; + + // Initialize the median to unset + this->Median[i] = -1; + + // Compute the standard deviation and the location of the median + this->StdDev[i] = 0; + count = 0; + for ( j = 0; j <= (this->Bounds[i*2 + 1] - this->Bounds[i*2]); j++ ) + { + count += this->Histogram[i][j]; + this->StdDev[i] += (double)this->Histogram[i][j] * + ((double)j+this->Bounds[i*2]-mean) * + ((double)j+this->Bounds[i*2]-mean); + if ( this->Median[i] == -1 && count > medianCount ) + { + this->Median[i] = j + this->Bounds[i*2]; + } + } + + // If our median is at the upper bound, bump down by one. This will + // help in the cases where we have a distance of 2 in this dimension, + // and just over half the entries are in the second bucket. We + // still want to divide - the division needs to be at the first + // bucket. + if ( this->Median[i] == this->Bounds[i*2 + 1] ) + { + this->Median[i]--; + } + + // Do the final division and square root to get the standard deviation + if (count>0) + { + this->StdDev[i] /= (double)count; + } + else + { + this->StdDev[i] = 0; + } + + this->StdDev[i] = sqrt( this->StdDev[i] ); + } + + // Should all be the same - just take the last one + this->Count = count; +} + +void vtkColorQuantizeNode::Divide( int axis, int nextIndex ) +{ + int newBounds[6]; + + this->Child1 = new vtkColorQuantizeNode; + this->Child2 = new vtkColorQuantizeNode; + + memcpy( newBounds, this->Bounds, 6*sizeof(int) ); + + newBounds[axis*2 + 1] = (int)(this->Median[axis]); + this->Child1->SetBounds( newBounds ); + + newBounds[axis*2] = (int)(this->Median[axis] + 1); + newBounds[axis*2 + 1] = (int)(this->Bounds[axis*2 + 1]); + this->Child2->SetBounds( newBounds ); + + this->SplitPoint = (int)(this->Median[axis]); + this->Axis = axis; + + this->Child1->SetIndex( this->Index ); + this->Child2->SetIndex( nextIndex ); + this->Index = -1; + + delete [] this->Histogram[0]; + delete [] this->Histogram[1]; + delete [] this->Histogram[2]; + + this->Histogram[0] = NULL; + this->Histogram[1] = NULL; + this->Histogram[2] = NULL; + + this->Child1->SetImageExtent( this->ImageExtent ); + this->Child1->SetImageIncrement( this->ImageIncrement ); + this->Child1->SetImageType( this->ImageType ); + this->Child1->SetImage( this->Image ); + + this->Child2->SetImageExtent( this->ImageExtent ); + this->Child2->SetImageIncrement( this->ImageIncrement ); + this->Child2->SetImageType( this->ImageType ); + this->Child2->SetImage( this->Image ); + + this->Child1->ComputeStdDev(); + this->Child2->ComputeStdDev(); +} + +// Constructor sets default values +vtkImageQuantizeRGBToIndex::vtkImageQuantizeRGBToIndex() +{ + this->LookupTable = vtkLookupTable::New(); + this->NumberOfColors = 256; + this->InputType = VTK_UNSIGNED_SHORT; + + this->InitializeExecuteTime = 0.0; + this->BuildTreeExecuteTime = 0.0; + this->LookupIndexExecuteTime = 0.0; +} + +// Destructor deletes used resources +vtkImageQuantizeRGBToIndex::~vtkImageQuantizeRGBToIndex() +{ + if ( this->LookupTable ) + { + this->LookupTable->Delete(); + } +} + +// This method is passed an input and output Data, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the Datas data types. +int vtkImageQuantizeRGBToIndex::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + void *inPtr; + void *outPtr; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + outData->SetExtent( + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); + outData->AllocateScalars(); + + int inExt[6]; + inData->GetExtent(inExt); + // if the input extent is empty then exit + if (inExt[1] < inExt[0] || + inExt[3] < inExt[2] || + inExt[5] < inExt[4]) + { + return 1; + } + + inPtr = inData->GetScalarPointer(); + outPtr = outData->GetScalarPointer(); + + // Input must be 3 components (rgb) + if (inData->GetNumberOfScalarComponents() != 3) + { + vtkErrorMacro("This filter can handles only 3 components"); + return 1; + } + + // this filter expects that output is type unsigned short. + if (outData->GetScalarType() != VTK_UNSIGNED_SHORT) + { + vtkErrorMacro(<< "Execute: out ScalarType " << outData->GetScalarType() + << " must be unsigned short\n"); + return 1; + } + + this->InputType = inData->GetScalarType(); + + switch ( this->InputType ) + { + vtkTemplateMacro( + vtkImageQuantizeRGBToIndexExecute( this, + inData, (VTK_TT *)(inPtr), + outData, (unsigned short *)(outPtr))); + default: + vtkErrorMacro(<< "Execute: This ScalarType is not handled"); + return 1; + } + + return 1; +} + +// Change the output type and number of components +int vtkImageQuantizeRGBToIndex::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_SHORT, 1); + return 1; +} + +// Get ALL of the input. +int vtkImageQuantizeRGBToIndex::RequestUpdateExtent( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int inExt[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + return 1; +} + +void vtkImageQuantizeRGBToIndex::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + // Input Type is internal so we dont prit it + //os << indent << "InputType: " << this->InputType << endl; + + os << indent << "Number Of Colors: " << this->NumberOfColors << endl; + os << indent << "Lookup Table: " << endl << *this->LookupTable; + os << indent << "Execute Time (in initialize stage): " << + this->InitializeExecuteTime << endl; + os << indent << "Execute Time (in build tree stage): " << + this->BuildTreeExecuteTime << endl; + os << indent << "Execute Time (in lookup index stage): " << + this->LookupIndexExecuteTime << endl; +} diff --git a/Imaging/vtkImageQuantizeRGBToIndex.h b/Imaging/vtkImageQuantizeRGBToIndex.h new file mode 100644 index 0000000..24b0914 --- /dev/null +++ b/Imaging/vtkImageQuantizeRGBToIndex.h @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageQuantizeRGBToIndex.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageQuantizeRGBToIndex - generalized histograms up to 4 dimensions +// .SECTION Description +// vtkImageQuantizeRGBToIndex takes a 3 component RGB image as +// input and produces a one component index image as output, along with +// a lookup table that contains the color definitions for the index values. +// This filter works on the entire input extent - it does not perform +// streaming, and it does not supported threaded execution (because it has +// to process the entire image). +// +// To use this filter, you typically set the number of colors +// (between 2 and 65536), execute it, and then retrieve the lookup table. +// The colors can then be using the lookup table and the image index. + +#ifndef __vtkImageQuantizeRGBToIndex_h +#define __vtkImageQuantizeRGBToIndex_h + +#include "vtkImageAlgorithm.h" + +class vtkLookupTable; + +class VTK_IMAGING_EXPORT vtkImageQuantizeRGBToIndex : public vtkImageAlgorithm +{ +public: + static vtkImageQuantizeRGBToIndex *New(); + vtkTypeRevisionMacro(vtkImageQuantizeRGBToIndex,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / Get the number of color index values to produce - must be + // a number between 2 and 65536. + vtkSetClampMacro( NumberOfColors, int, 2, 65536 ); + vtkGetMacro( NumberOfColors, int ); + + // Description: + // Get the resulting lookup table that contains the color definitions + // corresponding to the index values in the output image. + vtkGetObjectMacro( LookupTable, vtkLookupTable ); + + vtkGetMacro( InitializeExecuteTime, double ); + vtkGetMacro( BuildTreeExecuteTime, double ); + vtkGetMacro( LookupIndexExecuteTime, double ); + +//BTX + // Description: + // For internal use only - get the type of the image + vtkGetMacro( InputType, int ); + + // Description: + // For internal use only - set the times for execution + vtkSetMacro( InitializeExecuteTime, double ); + vtkSetMacro( BuildTreeExecuteTime, double ); + vtkSetMacro( LookupIndexExecuteTime, double ); +//ETX + +protected: + vtkImageQuantizeRGBToIndex(); + ~vtkImageQuantizeRGBToIndex(); + + vtkLookupTable *LookupTable; + int NumberOfColors; + int InputType; + + double InitializeExecuteTime; + double BuildTreeExecuteTime; + double LookupIndexExecuteTime; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + +private: + vtkImageQuantizeRGBToIndex(const vtkImageQuantizeRGBToIndex&); // Not implemented. + void operator=(const vtkImageQuantizeRGBToIndex&); // Not implemented. +}; + +#endif + + + + + + + + diff --git a/Imaging/vtkImageRFFT.cxx b/Imaging/vtkImageRFFT.cxx new file mode 100644 index 0000000..18c805a --- /dev/null +++ b/Imaging/vtkImageRFFT.cxx @@ -0,0 +1,300 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRFFT.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageRFFT.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageRFFT, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkImageRFFT); + +//---------------------------------------------------------------------------- +// This extent of the components changes to real and imaginary values. +int vtkImageRFFT::IterativeRequestInformation( + vtkInformation* vtkNotUsed(input), vtkInformation* output) +{ + vtkDataObject::SetPointDataActiveScalarInfo(output, VTK_DOUBLE, 2); + return 1; +} + +void vtkImageRFFTInternalRequestUpdateExtent(int *inExt, int *outExt, + int *wExt, + int iteration) +{ + memcpy(inExt, outExt, 6 * sizeof(int)); + inExt[iteration*2] = wExt[iteration*2]; + inExt[iteration*2 + 1] = wExt[iteration*2 + 1]; +} + +//---------------------------------------------------------------------------- +// This method tells the superclass that the whole input array is needed +// to compute any output region. +int vtkImageRFFT::IterativeRequestUpdateExtent( + vtkInformation* input, vtkInformation* output) +{ + int *outExt = output->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + int *wExt = input->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + int inExt[6]; + vtkImageRFFTInternalRequestUpdateExtent(inExt,outExt,wExt,this->Iteration); + input->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This templated execute method handles any type input, but the output +// is always doubles. +template +void vtkImageRFFTExecute(vtkImageRFFT *self, + vtkImageData *inData, int inExt[6], T *inPtr, + vtkImageData *outData, int outExt[6], double *outPtr, + int id) +{ + vtkImageComplex *inComplex; + vtkImageComplex *outComplex; + vtkImageComplex *pComplex; + // + int inMin0, inMax0; + vtkIdType inInc0, inInc1, inInc2; + T *inPtr0, *inPtr1, *inPtr2; + // + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + vtkIdType outInc0, outInc1, outInc2; + double *outPtr0, *outPtr1, *outPtr2; + // + int idx0, idx1, idx2, inSize0, numberOfComponents; + unsigned long count = 0; + unsigned long target; + double startProgress; + + startProgress = self->GetIteration()/(double)(self->GetNumberOfIterations()); + + // Reorder axes (The outs here are just placeholdes + self->PermuteExtent(inExt, inMin0, inMax0, outMin1,outMax1,outMin2,outMax2); + self->PermuteExtent(outExt, outMin0,outMax0,outMin1,outMax1,outMin2,outMax2); + self->PermuteIncrements(inData->GetIncrements(), inInc0, inInc1, inInc2); + self->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + inSize0 = inMax0 - inMin0 + 1; + + // Input has to have real components at least. + numberOfComponents = inData->GetNumberOfScalarComponents(); + if (numberOfComponents < 1) + { + vtkGenericWarningMacro("No real components"); + return; + } + + // Allocate the arrays of complex numbers + inComplex = new vtkImageComplex[inSize0]; + outComplex = new vtkImageComplex[inSize0]; + + target = (unsigned long)((outMax2-outMin2+1)*(outMax1-outMin1+1) + * self->GetNumberOfIterations() / 50.0); + target++; + + // loop over other axes + inPtr2 = inPtr; + outPtr2 = outPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = outMin1; !self->AbortExecute && idx1 <= outMax1; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target) + startProgress); + } + count++; + } + // copy into complex numbers + inPtr0 = inPtr1; + pComplex = inComplex; + for (idx0 = inMin0; idx0 <= inMax0; ++idx0) + { + pComplex->Real = (double)(*inPtr0); + pComplex->Imag = 0.0; + if (numberOfComponents > 1) + { // yes we have an imaginary input + pComplex->Imag = (double)(inPtr0[1]);; + } + inPtr0 += inInc0; + ++pComplex; + } + + // Call the method that performs the RFFT + self->ExecuteRfft(inComplex, outComplex, inSize0); + + // copy into output + outPtr0 = outPtr1; + pComplex = outComplex + (outMin0 - inMin0); + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + *outPtr0 = (double)pComplex->Real; + outPtr0[1] = (double)pComplex->Imag; + outPtr0 += outInc0; + ++pComplex; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + + delete [] inComplex; + delete [] outComplex; +} + + + + +//---------------------------------------------------------------------------- +// This method is passed input and output Datas, and executes the RFFT +// algorithm to fill the output from the input. +// Not threaded yet. +void vtkImageRFFT::ThreadedExecute(vtkImageData *inData, vtkImageData *outData, + int outExt[6], int threadId) +{ + void *inPtr, *outPtr; + int inExt[6]; + + int *wExt = inData->GetWholeExtent(); + vtkImageRFFTInternalRequestUpdateExtent(inExt,outExt,wExt,this->Iteration); + inPtr = inData->GetScalarPointerForExtent(inExt); + outPtr = outData->GetScalarPointerForExtent(outExt); + + // this filter expects that the output be doubles. + if (outData->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "Execute: Output must be be type double."); + return; + } + + // this filter expects input to have 1 or two components + if (outData->GetNumberOfScalarComponents() != 1 && + outData->GetNumberOfScalarComponents() != 2) + { + vtkErrorMacro(<< "Execute: Cannot handle more than 2 components"); + return; + } + + // choose which templated function to call. + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRFFTExecute(this, inData, inExt, + (VTK_TT *)(inPtr), outData, outExt, + (double *)(outPtr), threadId)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + + + +//---------------------------------------------------------------------------- +// For streaming and threads. Splits output update extent into num pieces. +// This method needs to be called num times. Results must not overlap for +// consistent starting extent. Subclass can override this method. +// This method returns the number of peices resulting from a successful split. +// This can be from 1 to "total". +// If 1 is returned, the extent cannot be split. +int vtkImageRFFT::SplitExtent(int splitExt[6], int startExt[6], + int num, int total) +{ + int splitAxis; + int min, max; + + vtkDebugMacro("SplitExtent: ( " << startExt[0] << ", " << startExt[1] << ", " + << startExt[2] << ", " << startExt[3] << ", " + << startExt[4] << ", " << startExt[5] << "), " + << num << " of " << total); + + // start with same extent + memcpy(splitExt, startExt, 6 * sizeof(int)); + + splitAxis = 2; + min = startExt[4]; + max = startExt[5]; + while ((splitAxis == this->Iteration) || (min == max)) + { + splitAxis--; + if (splitAxis < 0) + { // cannot split + vtkDebugMacro(" Cannot Split"); + return 1; + } + min = startExt[splitAxis*2]; + max = startExt[splitAxis*2+1]; + } + + // determine the actual number of pieces that will be generated + if ((max - min + 1) < total) + { + total = max - min + 1; + } + + if (num >= total) + { + vtkDebugMacro(" SplitRequest (" << num + << ") larger than total: " << total); + return total; + } + + // determine the extent of the piece + splitExt[splitAxis*2] = min + (max - min + 1)*num/total; + if (num == total - 1) + { + splitExt[splitAxis*2+1] = max; + } + else + { + splitExt[splitAxis*2+1] = (min-1) + (max - min + 1)*(num+1)/total; + } + + vtkDebugMacro(" Split Piece: ( " < + +vtkCxxRevisionMacro(vtkImageRGBToHSI, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkImageRGBToHSI); + +//---------------------------------------------------------------------------- +vtkImageRGBToHSI::vtkImageRGBToHSI() +{ + this->Maximum = 255.0; + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageRGBToHSIExecute(vtkImageRGBToHSI *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + int idxC, maxC; + double R, G, B, H, S, I; + double max = self->GetMaximum(); + double temp; + + // find the region to loop over + maxC = inData->GetNumberOfScalarComponents()-1; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // Pixel operation + R = (double)(*inSI); inSI++; + G = (double)(*inSI); inSI++; + B = (double)(*inSI); inSI++; + // Saturation + temp = R; + if (G < temp) + { + temp = G; + } + if (B < temp) + { + temp = B; + } + double sumRGB = R+G+B; + if(sumRGB == 0.0) + { + S = 0.0; + } + else + { + S = max * (1.0 - (3.0 * temp / sumRGB)); + } + + temp = (double)(R + G + B); + // Intensity is easy + I = temp / 3.0; + + // Hue + temp = sqrt((R-G)*(R-G) + (R-B)*(G-B)); + if(temp != 0.0) + { + temp = acos((0.5 * ((R-G) + (R-B))) / temp); + } + if (G >= B) + { + H = max * (temp / 6.2831853); + } + else + { + H = max * (1.0 - (temp / 6.2831853)); + } + + // assign output. + *outSI = (T)(H); outSI++; + *outSI = (T)(S); outSI++; + *outSI = (T)(I); outSI++; + + for (idxC = 3; idxC <= maxC; idxC++) + { + *outSI++ = *inSI++; + } + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageRGBToHSI::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", must match out ScalarType " << outData->GetScalarType()); + return; + } + + // need three components for input and output + if (inData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Input has too few components"); + return; + } + if (outData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Output has too few components"); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRGBToHSIExecute( this, inData, + outData, outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageRGBToHSI::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum: " << this->Maximum << "\n"; +} + diff --git a/Imaging/vtkImageRGBToHSI.h b/Imaging/vtkImageRGBToHSI.h new file mode 100644 index 0000000..a88e1d7 --- /dev/null +++ b/Imaging/vtkImageRGBToHSI.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRGBToHSI.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageRGBToHSI - Converts RGB components to HSI. +// .SECTION Description +// For each pixel with red, blue, and green components this +// filter output the color coded as hue, saturation and intensity. +// Output type must be the same as input type. + +#ifndef __vtkImageRGBToHSI_h +#define __vtkImageRGBToHSI_h + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageRGBToHSI : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageRGBToHSI *New(); + vtkTypeRevisionMacro(vtkImageRGBToHSI,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Hue is an angle. Maximum specifies when it maps back to 0. HueMaximum + // defaults to 255 instead of 2PI, because unsigned char is expected as + // input. Maximum also specifies the maximum of the Saturation. + vtkSetMacro(Maximum,double); + vtkGetMacro(Maximum,double); + +protected: + vtkImageRGBToHSI(); + ~vtkImageRGBToHSI() {}; + + double Maximum; + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); + +private: + vtkImageRGBToHSI(const vtkImageRGBToHSI&); // Not implemented. + void operator=(const vtkImageRGBToHSI&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageRGBToHSV.cxx b/Imaging/vtkImageRGBToHSV.cxx new file mode 100644 index 0000000..b23a688 --- /dev/null +++ b/Imaging/vtkImageRGBToHSV.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRGBToHSV.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageRGBToHSV.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkImageRGBToHSV, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkImageRGBToHSV); + +//---------------------------------------------------------------------------- +vtkImageRGBToHSV::vtkImageRGBToHSV() +{ + this->Maximum = 255.0; + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageRGBToHSVExecute(vtkImageRGBToHSV *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + int idxC, maxC; + double R, G, B, H, S, V; + double max = self->GetMaximum(); + + // find the region to loop over + maxC = inData->GetNumberOfScalarComponents()-1; + + // Loop through ouput pixels + while (!outIt.IsAtEnd()) + { + T* inSI = inIt.BeginSpan(); + T* outSI = outIt.BeginSpan(); + T* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // Pixel operation + R = (double)(*inSI) / max; inSI++; + G = (double)(*inSI) / max; inSI++; + B = (double)(*inSI) / max; inSI++; + + vtkMath::RGBToHSV(R, G, B, &H, &S, &V); + + H *= max; + S *= max; + V *= max; + + if (H > max) + { + H = max; + } + if (S > max) + { + S = max; + } + if (V > max) + { + V = max; + } + + // assign output. + *outSI = (T)(H); outSI++; + *outSI = (T)(S); outSI++; + *outSI = (T)(V); outSI++; + + for (idxC = 3; idxC <= maxC; idxC++) + { + *outSI++ = *inSI++; + } + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageRGBToHSV::ThreadedExecute (vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + vtkDebugMacro(<< "Execute: inData = " << inData + << ", outData = " << outData); + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", must match out ScalarType " << outData->GetScalarType()); + return; + } + + // need three components for input and output + if (inData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Input has too few components"); + return; + } + if (outData->GetNumberOfScalarComponents() < 3) + { + vtkErrorMacro("Output has too few components"); + return; + } + + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRGBToHSVExecute( this, inData, + outData, outExt, id, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +void vtkImageRGBToHSV::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum: " << this->Maximum << "\n"; +} + diff --git a/Imaging/vtkImageRGBToHSV.h b/Imaging/vtkImageRGBToHSV.h new file mode 100644 index 0000000..eb28db4 --- /dev/null +++ b/Imaging/vtkImageRGBToHSV.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRGBToHSV.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageRGBToHSV - Converts RGB components to HSV. +// .SECTION Description +// For each pixel with red, blue, and green components this +// filter output the color coded as hue, saturation and value. +// Output type must be the same as input type. + + +#ifndef __vtkImageRGBToHSV_h +#define __vtkImageRGBToHSV_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageRGBToHSV : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageRGBToHSV *New(); + vtkTypeRevisionMacro(vtkImageRGBToHSV,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + + // Hue is an angle. Maximum specifies when it maps back to 0. HueMaximum + // defaults to 255 instead of 2PI, because unsigned char is expected as + // input. Maximum also specifies the maximum of the Saturation. + vtkSetMacro(Maximum,double); + vtkGetMacro(Maximum,double); + +protected: + vtkImageRGBToHSV(); + ~vtkImageRGBToHSV() {}; + + double Maximum; + + void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, + int ext[6], int id); +private: + vtkImageRGBToHSV(const vtkImageRGBToHSV&); // Not implemented. + void operator=(const vtkImageRGBToHSV&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageRange3D.cxx b/Imaging/vtkImageRange3D.cxx new file mode 100644 index 0000000..1f53a1d --- /dev/null +++ b/Imaging/vtkImageRange3D.cxx @@ -0,0 +1,339 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRange3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageRange3D.h" + +#include "vtkImageData.h" +#include "vtkImageEllipsoidSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageRange3D, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkImageRange3D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageRange3D fitler. +// By default zero values are dilated. +vtkImageRange3D::vtkImageRange3D() +{ + this->HandleBoundaries = 1; + this->KernelSize[0] = 1; + this->KernelSize[1] = 1; + this->KernelSize[2] = 1; + + this->Ellipse = vtkImageEllipsoidSource::New(); + // Setup the Ellipse to default size + this->SetKernelSize(1, 1, 1); +} + +//---------------------------------------------------------------------------- +vtkImageRange3D::~vtkImageRange3D() +{ + if (this->Ellipse) + { + this->Ellipse->Delete(); + this->Ellipse = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageRange3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +// This method sets the size of the neighborhood. It also sets the +// default middle of the neighborhood and computes the eliptical foot print. +void vtkImageRange3D::SetKernelSize(int size0, int size1, int size2) +{ + int modified = 0; + + if (this->KernelSize[0] != size0) + { + modified = 1; + this->KernelSize[0] = size0; + this->KernelMiddle[0] = size0 / 2; + } + if (this->KernelSize[1] != size1) + { + modified = 1; + this->KernelSize[1] = size1; + this->KernelMiddle[1] = size1 / 2; + } + if (this->KernelSize[2] != size2) + { + modified = 1; + this->KernelSize[2] = size2; + this->KernelMiddle[2] = size2 / 2; + } + + if (modified) + { + this->Modified(); + this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->SetCenter((float)(this->KernelSize[0]-1)*0.5, + (float)(this->KernelSize[1]-1)*0.5, + (float)(this->KernelSize[2]-1)*0.5); + this->Ellipse->SetRadius((float)(this->KernelSize[0])*0.5, + (float)(this->KernelSize[1])*0.5, + (float)(this->KernelSize[2])*0.5); + // make sure scalars have been allocated (needed if multithreaded is used) + vtkInformation *ellipseOutInfo = + this->Ellipse->GetExecutive()->GetOutputInformation(0); + ellipseOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + 0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->GetOutput()->Update(); + } +} + +//---------------------------------------------------------------------------- +// Output is always float +int vtkImageRange3D::RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Superclass::RequestInformation(request, inputVector, outputVector); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1); + return 1; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter on any region, +// whether it needs boundary checking or not. +// If the filter needs to be faster, the function could be duplicated +// for strictly center (no boundary ) processing. +template +void vtkImageRange3DExecute(vtkImageRange3D *self, + vtkImageData *mask, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, int *outExt, + float *outPtr, int id, + vtkInformation *inInfo) +{ + int *kernelMiddle, *kernelSize; + // For looping though output (and input) pixels. + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + int outIdx0, outIdx1, outIdx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + T *inPtr0, *inPtr1, *inPtr2; + float *outPtr0, *outPtr1, *outPtr2; + int numComps, outIdxC; + // For looping through hood pixels + int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2; + int hoodIdx0, hoodIdx1, hoodIdx2; + T *hoodPtr0, *hoodPtr1, *hoodPtr2; + // For looping through the mask. + unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2; + vtkIdType maskInc0, maskInc1, maskInc2; + // The extent of the whole input image + int inImageMin0, inImageMin1, inImageMin2; + int inImageMax0, inImageMax1, inImageMax2; + int inImageExt[6]; + // to compute the range + T pixelMin, pixelMax; + unsigned long count = 0; + unsigned long target; + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inImageExt); + inImageMin0 = inImageExt[0]; + inImageMax0 = inImageExt[1]; + inImageMin1 = inImageExt[2]; + inImageMax1 = inImageExt[3]; + inImageMin2 = inImageExt[4]; + inImageMax2 = inImageExt[5]; + outData->GetIncrements(outInc0, outInc1, outInc2); + outMin0 = outExt[0]; outMax0 = outExt[1]; + outMin1 = outExt[2]; outMax1 = outExt[3]; + outMin2 = outExt[4]; outMax2 = outExt[5]; + numComps = outData->GetNumberOfScalarComponents(); + + // Get ivars of this object (easier than making friends) + kernelSize = self->GetKernelSize(); + kernelMiddle = self->GetKernelMiddle(); + hoodMin0 = - kernelMiddle[0]; + hoodMin1 = - kernelMiddle[1]; + hoodMin2 = - kernelMiddle[2]; + hoodMax0 = hoodMin0 + kernelSize[0] - 1; + hoodMax1 = hoodMin1 + kernelSize[1] - 1; + hoodMax2 = hoodMin2 + kernelSize[2] - 1; + + // Setup mask info + maskPtr = (unsigned char *)(mask->GetScalarPointer()); + mask->GetIncrements(maskInc0, maskInc1, maskInc2); + + // in and out should be marching through corresponding pixels. + inPtr = (T *)(inData->GetScalarPointer(outMin0, outMin1, outMin2)); + + target = (unsigned long)(numComps*(outMax2-outMin2+1)* + (outMax1-outMin1+1)/50.0); + target++; + + // loop through components + for (outIdxC = 0; outIdxC < numComps; ++outIdxC) + { + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outMin1; + !self->AbortExecute && outIdx1 <= outMax1; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0) + { + // Find min and max + pixelMin = pixelMax = *inPtr0; + // loop through neighborhood pixels + // as sort of a hack to handle boundaries, + // input pointer will be marching through data that does not exist. + hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0 + - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2; + maskPtr2 = maskPtr; + for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2) + { + hoodPtr1 = hoodPtr2; + maskPtr1 = maskPtr2; + for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1) + { + hoodPtr0 = hoodPtr1; + maskPtr0 = maskPtr1; + for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0) + { + // A quick but rather expensive way to handle boundaries + if ( outIdx0 + hoodIdx0 >= inImageMin0 && + outIdx0 + hoodIdx0 <= inImageMax0 && + outIdx1 + hoodIdx1 >= inImageMin1 && + outIdx1 + hoodIdx1 <= inImageMax1 && + outIdx2 + hoodIdx2 >= inImageMin2 && + outIdx2 + hoodIdx2 <= inImageMax2) + { + if (*maskPtr0) + { + if (*hoodPtr0 < pixelMin) + { + pixelMin = *hoodPtr0; + } + if (*hoodPtr0 > pixelMax) + { + pixelMax = *hoodPtr0; + } + } + } + + hoodPtr0 += inInc0; + maskPtr0 += maskInc0; + } + hoodPtr1 += inInc1; + maskPtr1 += maskInc1; + } + hoodPtr2 += inInc2; + maskPtr2 += maskInc2; + } + *outPtr0 = (float)(pixelMax - pixelMin); + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + ++inPtr; + ++outPtr; + } +} + +//---------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output Data types. +// It hanldes image boundaries, so the image does not shrink. +void vtkImageRange3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6], wholeExt[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt,outExt,wholeExt); + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + vtkImageData *mask; + + // Error checking on mask + mask = this->Ellipse->GetOutput(); + if (mask->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro(<< "Execute: mask has wrong scalar type"); + return; + } + + // this filter expects the output to be float + if (outData[0]->GetScalarType() != VTK_FLOAT) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << " must be float"); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRange3DExecute( this, mask, inData[0][0], + (VTK_TT *)(inPtr), outData[0], outExt, + (float *)(outPtr), id, inInfo)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkImageRange3D::RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Ellipse->GetOutput()->Update(); + return this->Superclass::RequestData(request, inputVector, outputVector); +} diff --git a/Imaging/vtkImageRange3D.h b/Imaging/vtkImageRange3D.h new file mode 100644 index 0000000..817e99e --- /dev/null +++ b/Imaging/vtkImageRange3D.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRange3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageRange3D - Max - min of a circular neighborhood. +// .SECTION Description +// vtkImageRange3D replaces a pixel with the maximum minus minimum over +// an ellipsoidal neighborhood. If KernelSize of an axis is 1, no processing +// is done on that axis. + + +#ifndef __vtkImageRange3D_h +#define __vtkImageRange3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class vtkImageEllipsoidSource; + +class VTK_IMAGING_EXPORT vtkImageRange3D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageRange3D *New(); + vtkTypeRevisionMacro(vtkImageRange3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sets the size of the neighborhood. It also sets the + // default middle of the neighborhood and computes the elliptical foot print. + void SetKernelSize(int size0, int size1, int size2); + +protected: + vtkImageRange3D(); + ~vtkImageRange3D(); + + vtkImageEllipsoidSource *Ellipse; + + virtual int RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + +private: + vtkImageRange3D(const vtkImageRange3D&); // Not implemented. + void operator=(const vtkImageRange3D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageRectilinearWipe.cxx b/Imaging/vtkImageRectilinearWipe.cxx new file mode 100644 index 0000000..285099d --- /dev/null +++ b/Imaging/vtkImageRectilinearWipe.cxx @@ -0,0 +1,411 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRectilinearWipe.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageRectilinearWipe.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageRectilinearWipe, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkImageRectilinearWipe); + +//---------------------------------------------------------------------------- +vtkImageRectilinearWipe::vtkImageRectilinearWipe() +{ + this->Position[0] = 0; + this->Position[1] = 0; + this->Wipe = VTK_WIPE_QUAD; + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +// Handles the two input operations +template +void vtkImageRectilinearWipeExecute2(vtkImageRectilinearWipe *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, + T *outPtr, + int outExt[6], int id) +{ + int idxR, idxY, idxZ; + int maxY, maxZ; + vtkIdType inIncX, inIncY, inIncZ; + vtkIdType outIncX, outIncY, outIncZ; + int rowLength; + unsigned long count = 0; + unsigned long target; + + // find the region to loop over + rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents(); + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Get increments to march through data + inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // Loop through output pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + for (idxY = 0; idxY <= maxY; idxY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + for (idxR = 0; idxR < rowLength; idxR++) + { + *outPtr = *inPtr; + outPtr++; + inPtr++; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } +} + + + +//---------------------------------------------------------------------------- +// This function adjusts the extents of the wipe to the output extents. +int vtkImageRectilinearWipeClampExtents(int wipeExt[6], int outExt[6]) +{ + int status = 1; + + for (int i = 0; i < 3; i++) + { + // the lower and upper extents cannot be below the lower output extent + if (wipeExt[2*i] < outExt[2*i]) + { + wipeExt[2*i] = outExt[2*i]; + } + if (wipeExt[2*i + 1] < outExt[2*i]) + { + wipeExt[2*i + 1] = outExt[2*i]; + status = 0; + } + + // the lower and upper extents cannot be above the upper output extent + if (wipeExt[2*i] > outExt[2*i + 1]) + { + wipeExt[2*i] = outExt[2*i + 1]; + status = 0; + } + if (wipeExt[2*i + 1] > outExt[2*i + 1]) + { + wipeExt[2*i + 1] = outExt[2*i + 1]; + } + } + return status; +} +//---------------------------------------------------------------------------- +// This method is passed a input and output regions, and executes the filter +// algorithm to fill the output from the inputs based on the Wipe ivar. +void vtkImageRectilinearWipe::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr; + void *outPtr; + int wipeExt[6]; + int wholeExt[6]; + int whichInput = 0; + + // Make sure the inputs/output are valid + if (inData[0][0] == NULL) + { + vtkErrorMacro(<< "Input " << 0 << " must be specified."); + return; + } + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + if (inData[1][0] == NULL) + { + vtkErrorMacro(<< "Input " << 1 << " must be specified."); + return; + } + + // this filter expects that inputs that have the same number of components + if (inData[0][0]->GetNumberOfScalarComponents() != + inData[1][0]->GetNumberOfScalarComponents()) + { + vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, " + << inData[0][0]->GetNumberOfScalarComponents() + << ", must match out input2 NumberOfScalarComponents " + << inData[1][0]->GetNumberOfScalarComponents()); + return; + } + + // Wipe pattern depends on the whole extent. + outData[0]->GetWholeExtent(wholeExt); + + // Each quadrant is processed separately + // lower left + wipeExt[0] = wholeExt[0]; + wipeExt[1] = wholeExt[0] + this->Position[0]; + wipeExt[2] = wholeExt[2]; + wipeExt[3] = wholeExt[2] + this->Position[1]; + wipeExt[4] = wholeExt[4]; + wipeExt[5] = wholeExt[5]; + if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt)) + { + + outPtr = outData[0]->GetScalarPointerForExtent(wipeExt); + + switch (this->Wipe) + { + case VTK_WIPE_QUAD: + whichInput = 0; + break; + case VTK_WIPE_HORIZONTAL: + whichInput = 0; + break; + case VTK_WIPE_VERTICAL: + whichInput = 0; + break; + case VTK_WIPE_LOWER_LEFT: + whichInput = 0; + break; + case VTK_WIPE_LOWER_RIGHT: + whichInput = 1; + break; + case VTK_WIPE_UPPER_LEFT: + whichInput = 1; + break; + case VTK_WIPE_UPPER_RIGHT: + whichInput = 1; + break; + } + inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt); + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRectilinearWipeExecute2(this, + inData[whichInput][0], (VTK_TT *)(inPtr), + outData[0], (VTK_TT *)(outPtr), + wipeExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + // lower right + wipeExt[0] = wholeExt[0] + this->Position[0] + 1; + wipeExt[1] = wholeExt[1]; + wipeExt[2] = wholeExt[2]; + wipeExt[3] = wholeExt[2] + this->Position[1]; + wipeExt[4] = wholeExt[4]; + wipeExt[5] = wholeExt[5]; + if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt)) + { + switch (this->Wipe) + { + case VTK_WIPE_QUAD: + whichInput = 1; + break; + case VTK_WIPE_HORIZONTAL: + whichInput = 1; + break; + case VTK_WIPE_VERTICAL: + whichInput = 0; + break; + case VTK_WIPE_LOWER_LEFT: + whichInput = 1; + break; + case VTK_WIPE_LOWER_RIGHT: + whichInput = 0; + break; + case VTK_WIPE_UPPER_LEFT: + whichInput = 1; + break; + case VTK_WIPE_UPPER_RIGHT: + whichInput = 1; + break; + } + inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt); + outPtr = outData[0]->GetScalarPointerForExtent(wipeExt); + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRectilinearWipeExecute2( this, + inData[whichInput][0], + (VTK_TT *)(inPtr), + outData[0], + (VTK_TT *)(outPtr), + wipeExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + // upper left + wipeExt[0] = wholeExt[0]; + wipeExt[1] = wholeExt[0] + this->Position[0]; + wipeExt[2] = wholeExt[2] + this->Position[1] + 1; + wipeExt[3] = wholeExt[3]; + wipeExt[4] = wholeExt[4]; + wipeExt[5] = wholeExt[5]; + if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt)) + { + + switch (this->Wipe) + { + case VTK_WIPE_QUAD: + whichInput = 1; + break; + case VTK_WIPE_HORIZONTAL: + whichInput = 0; + break; + case VTK_WIPE_VERTICAL: + whichInput = 1; + break; + case VTK_WIPE_LOWER_LEFT: + whichInput = 1; + break; + case VTK_WIPE_LOWER_RIGHT: + whichInput = 1; + break; + case VTK_WIPE_UPPER_LEFT: + whichInput = 0; + break; + case VTK_WIPE_UPPER_RIGHT: + whichInput = 1; + break; + } + inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt); + outPtr = outData[0]->GetScalarPointerForExtent(wipeExt); + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRectilinearWipeExecute2(this, + inData[whichInput][0], + (VTK_TT *)(inPtr), + outData[0], + (VTK_TT *)(outPtr), + wipeExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + // upper right + wipeExt[0] = wholeExt[0] + this->Position[0] + 1; + wipeExt[1] = wholeExt[1]; + wipeExt[2] = wholeExt[2] + this->Position[1] + 1; + wipeExt[3] = wholeExt[3]; + wipeExt[4] = wholeExt[4]; + wipeExt[5] = wholeExt[5]; + if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt)) + { + switch (this->Wipe) + { + case VTK_WIPE_QUAD: + whichInput = 0; + break; + case VTK_WIPE_HORIZONTAL: + whichInput = 1; + break; + case VTK_WIPE_VERTICAL: + whichInput = 1; + break; + case VTK_WIPE_LOWER_LEFT: + whichInput = 1; + break; + case VTK_WIPE_LOWER_RIGHT: + whichInput = 1; + break; + case VTK_WIPE_UPPER_LEFT: + whichInput = 1; + break; + case VTK_WIPE_UPPER_RIGHT: + whichInput = 0; + break; + } + inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt); + outPtr = outData[0]->GetScalarPointerForExtent(wipeExt); + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageRectilinearWipeExecute2( this, + inData[whichInput][0], + (VTK_TT *)(inPtr), + outData[0], + (VTK_TT *)(outPtr), + wipeExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } +} + +void vtkImageRectilinearWipe::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Position: (" << this->Position[0] << ", " + << this->Position[1] << ")\n"; + os << indent << "Wipe: "; + switch (this->Wipe) + { + case VTK_WIPE_QUAD: + os << "Quad" << endl; + break; + case VTK_WIPE_HORIZONTAL: + os << "Horizontal" << endl; + break; + case VTK_WIPE_VERTICAL: + os << "Vertical" << endl; + break; + case VTK_WIPE_LOWER_LEFT: + os << "LowerLeft" << endl; + break; + case VTK_WIPE_LOWER_RIGHT: + os << "LowerRight" << endl; + break; + case VTK_WIPE_UPPER_LEFT: + os << "UpperLeft" << endl; + break; + case VTK_WIPE_UPPER_RIGHT: + os << "UpperRight" << endl; + break; + } +} + diff --git a/Imaging/vtkImageRectilinearWipe.h b/Imaging/vtkImageRectilinearWipe.h new file mode 100644 index 0000000..cc30eb4 --- /dev/null +++ b/Imaging/vtkImageRectilinearWipe.h @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageRectilinearWipe.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageRectilinearWipe - make a rectilinear combination of two images. +// .SECTION Description +// vtkImageRectilinearWipe makes a rectilinear combination of two +// images. The two input images must correspond in size, scalar type and +// number of components. +// The resulting image has four possible configurations +// called: +// Quad - alternate input 0 and input 1 horizontally and +// vertically. Select this with SetWipeModeToQuad. The Position +// specifies the location of the quad intersection. +// Corner - 3 of one input and 1 of the other. Select the location of +// input 0 with with SetWipeModeToLowerLeft, SetWipeModeToLowerRight, +// SetWipeModeToUpperLeft and SetWipeModeToUpperRight. The Position +// selects the location of the corner. +// Horizontal - alternate input 0 and input 1 with a vertical +// split. Select this with SetWipeModeToHorizontal. Position[0] +// specifies the location of the vertical transition between input 0 +// and input 1. +// Vertical - alternate input 0 and input 1 with a horizontal +// split. Only the y The intersection point of the rectilinear points +// is controlled with the Point ivar. + +// .SECTION Thanks +// This work was supported by PHS Research Grant No. 1 P41 RR13218-01 +// from the National Center for Research Resources. + +// .SECTION See Also +// vtkImageCheckerboard + +#ifndef __vtkImageRectilinearWipe_h +#define __vtkImageRectilinearWipe_h + +#include "vtkThreadedImageAlgorithm.h" + +#define VTK_WIPE_QUAD 0 +#define VTK_WIPE_HORIZONTAL 1 +#define VTK_WIPE_VERTICAL 2 +#define VTK_WIPE_LOWER_LEFT 3 +#define VTK_WIPE_LOWER_RIGHT 4 +#define VTK_WIPE_UPPER_LEFT 5 +#define VTK_WIPE_UPPER_RIGHT 6 + +class VTK_IMAGING_EXPORT vtkImageRectilinearWipe : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageRectilinearWipe *New(); + vtkTypeRevisionMacro(vtkImageRectilinearWipe,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the location of the image transition. Note that position is + // specified in pixels. + vtkSetVector2Macro(Position,int); + vtkGetVectorMacro(Position,int,2); + + // Description: + // Set the two inputs to this filter. + virtual void SetInput1(vtkDataObject *in) { this->SetInput(0,in); } + virtual void SetInput2(vtkDataObject *in) { this->SetInput(1,in); } + + // Description: + // Specify the wipe mode. This mode determnis how input 0 and input + // 1 are combined to produce the output. Each mode uses one or both + // of the values stored in Position. + // SetWipeToQuad - alternate input 0 and input 1 horizontally and + // vertically. The Position specifies the location of the quad + // intersection. + // SetWipeToLowerLeft{LowerRight,UpperLeft.UpperRight} - 3 of one + // input and 1 of the other. Select the location of input 0 to the + // LowerLeft{LowerRight,UpperLeft,UpperRight}. Position + // selects the location of the corner. + // SetWipeToHorizontal - alternate input 0 and input 1 with a vertical + // split. Position[0] specifies the location of the vertical + // transition between input 0 and input 1. + // SetWipeToVertical - alternate input 0 and input 1 with a + // horizontal split. Position[1] specifies the location of the + // horizonal transition between input 0 and input 1. + vtkSetClampMacro(Wipe,int,VTK_WIPE_QUAD,VTK_WIPE_UPPER_RIGHT); + vtkGetMacro(Wipe,int); + void SetWipeToQuad() + {this->SetWipe(VTK_WIPE_QUAD);} + void SetWipeToHorizontal() + {this->SetWipe(VTK_WIPE_HORIZONTAL);} + void SetWipeToVertical() + {this->SetWipe(VTK_WIPE_VERTICAL);} + void SetWipeToLowerLeft() + {this->SetWipe(VTK_WIPE_LOWER_LEFT);} + void SetWipeToLowerRight() + {this->SetWipe(VTK_WIPE_LOWER_RIGHT);} + void SetWipeToUpperLeft() + {this->SetWipe(VTK_WIPE_UPPER_LEFT);} + void SetWipeToUpperRight() + {this->SetWipe(VTK_WIPE_UPPER_RIGHT);} + +protected: + vtkImageRectilinearWipe(); + ~vtkImageRectilinearWipe() {}; + + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int extent[6], int threadId); + + int Position[2]; + int Wipe; + +private: + vtkImageRectilinearWipe(const vtkImageRectilinearWipe&); // Not implemented. + void operator=(const vtkImageRectilinearWipe&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageResample.cxx b/Imaging/vtkImageResample.cxx new file mode 100644 index 0000000..f094d6b --- /dev/null +++ b/Imaging/vtkImageResample.cxx @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageResample.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageResample.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageResample, "$Revision: 1.42 $"); +vtkStandardNewMacro(vtkImageResample); + +//---------------------------------------------------------------------------- +// Constructor: Sets default filter to be identity. +vtkImageResample::vtkImageResample() +{ + this->MagnificationFactors[0] = 1.0; + this->MagnificationFactors[1] = 1.0; + this->MagnificationFactors[2] = 1.0; + this->OutputSpacing[0] = 0.0; // not specified + this->OutputSpacing[1] = 0.0; // not specified + this->OutputSpacing[2] = 0.0; // not specified + this->InterpolationMode = VTK_RESLICE_LINEAR; + this->Dimensionality = 3; +} + +//---------------------------------------------------------------------------- +void vtkImageResample::SetAxisOutputSpacing(int axis, double spacing) +{ + if (axis < 0 || axis > 2) + { + vtkErrorMacro("Bad axis: " << axis); + return; + } + + if (this->OutputSpacing[axis] != spacing) + { + this->OutputSpacing[axis] = spacing; + this->Modified(); + if (spacing != 0.0) + { + // Delay computing the magnification factor. + // Input might not be set yet. + this->MagnificationFactors[axis] = 0.0; // Not computed yet. + } + } +} + +//---------------------------------------------------------------------------- +void vtkImageResample::SetAxisMagnificationFactor(int axis, double factor) +{ + if (axis < 0 || axis > 2) + { + vtkErrorMacro("Bad axis: " << axis); + return; + } + + if (this->MagnificationFactors[axis] == factor) + { + return; + } + this->Modified(); + this->MagnificationFactors[axis] = factor; + // Spacing is no longer valid. + this->OutputSpacing[axis] = 0.0; // Not computed yet. +} + +//---------------------------------------------------------------------------- +double vtkImageResample::GetAxisMagnificationFactor(int axis, + vtkInformation *inInfo) +{ + if (axis < 0 || axis > 2) + { + vtkErrorMacro("Bad axis: " << axis); + return 0.0; + } + + if (this->MagnificationFactors[axis] == 0.0) + { + double *inputSpacing; + if ( ! this->GetInput()) + { + vtkErrorMacro("GetMagnificationFactor: Input not set."); + return 0.0; + } + this->GetInput()->UpdateInformation(); + if (!inInfo) + { + inInfo = this->GetExecutive()->GetInputInformation(0, 0); + } + inputSpacing = inInfo->Get(vtkDataObject::SPACING()); + this->MagnificationFactors[axis] = + inputSpacing[axis] / this->OutputSpacing[axis]; + + } + + vtkDebugMacro("Returning magnification factor " + << this->MagnificationFactors[axis] << " for axis " + << axis); + + return this->MagnificationFactors[axis]; +} + + +//---------------------------------------------------------------------------- +// Computes any global image information associated with regions. +int vtkImageResample::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int wholeMin, wholeMax, axis, ext[6]; + double spacing[3], factor; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext); + inInfo->Get(vtkDataObject::SPACING(), spacing); + + for (axis = 0; axis < 3; axis++) + { + wholeMin = ext[axis*2]; + wholeMax = ext[axis*2+1]; + + // Scale the output extent + factor = 1.0; + if (axis < this->Dimensionality) + { + factor = this->GetAxisMagnificationFactor(axis, inInfo); + } + + wholeMin = (int)(ceil((double)(wholeMin) * factor)); + wholeMax = (int)(floor((double)(wholeMax) * factor)); + + // Change the data spacing + spacing[axis] /= factor; + + ext[axis*2] = wholeMin; + ext[axis*2+1] = wholeMax; + + // just in case the input spacing has changed. + if (this->OutputSpacing[axis] != 0.0) + { + // Cause MagnificationFactor to recompute. + this->MagnificationFactors[axis] = 0.0; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext, 6); + outInfo->Set(vtkDataObject::SPACING(), spacing, 3); + + return 1; +} + +void vtkImageResample::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; + os << indent << "Interpolate: " << (this->GetInterpolate() ? "On\n" : "Off\n"); +} diff --git a/Imaging/vtkImageResample.h b/Imaging/vtkImageResample.h new file mode 100644 index 0000000..63be8f8 --- /dev/null +++ b/Imaging/vtkImageResample.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageResample.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageResample - Resamples an image to be larger or smaller. +// .SECTION Description +// This filter produces an output with different spacing (and extent) +// than the input. Linear interpolation can be used to resample the data. +// The Output spacing can be set explicitly or relative to input spacing +// with the SetAxisMagnificationFactor method. + + +#ifndef __vtkImageResample_h +#define __vtkImageResample_h + + +#include "vtkImageReslice.h" + +class VTK_IMAGING_EXPORT vtkImageResample : public vtkImageReslice +{ +public: + static vtkImageResample *New(); + vtkTypeRevisionMacro(vtkImageResample,vtkImageReslice); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set desired spacing. + // Zero is a reserved value indicating spacing has not been set. + void SetAxisOutputSpacing(int axis, double spacing); + + // Description: + // Set/Get Magnification factors. + // Zero is a reserved value indicating values have not been computed. + void SetAxisMagnificationFactor(int axis, double factor); + double GetAxisMagnificationFactor(int axis, vtkInformation *inInfo=0); + + // Description: + // Dimensionality is the number of axes which are considered during + // execution. To process images dimensionality would be set to 2. + // This has the same effect as setting the magnification of the third + // axis to 1.0 + vtkSetMacro(Dimensionality,int); + vtkGetMacro(Dimensionality,int); + +protected: + vtkImageResample(); + ~vtkImageResample() {}; + + double MagnificationFactors[3]; + double OutputSpacing[3]; + int Dimensionality; + + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkImageResample(const vtkImageResample&); // Not implemented. + void operator=(const vtkImageResample&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageReslice.cxx b/Imaging/vtkImageReslice.cxx new file mode 100644 index 0000000..aef8e18 --- /dev/null +++ b/Imaging/vtkImageReslice.cxx @@ -0,0 +1,3293 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReslice.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageReslice.h" + +#include "vtkImageData.h" +#include "vtkImageStencilData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkTransform.h" +#include "vtkDataSetAttributes.h" + +#include "vtkTemplateAliasMacro.h" +// turn off 64-bit ints when templating over all types +# undef VTK_USE_INT64 +# define VTK_USE_INT64 0 +# undef VTK_USE_UINT64 +# define VTK_USE_UINT64 0 + +#include +#include +#include + +vtkCxxRevisionMacro(vtkImageReslice, "$Revision: 1.63.6.2 $"); +vtkStandardNewMacro(vtkImageReslice); +vtkCxxSetObjectMacro(vtkImageReslice, InformationInput, vtkImageData); +vtkCxxSetObjectMacro(vtkImageReslice,ResliceAxes,vtkMatrix4x4); +vtkCxxSetObjectMacro(vtkImageReslice,ResliceTransform,vtkAbstractTransform); + +//-------------------------------------------------------------------------- +// The 'floor' function on x86 and mips is many times slower than these +// and is used a lot in this code, optimize for different CPU architectures +template +inline int vtkResliceFloor(double x, F &f) +{ +#if defined mips || defined sparc || defined __ppc__ + x += 2147483648.0; + unsigned int i = (unsigned int)(x); + f = x - i; + return (int)(i - 2147483648U); +#elif defined i386 || defined _M_IX86 + union { double d; unsigned short s[4]; unsigned int i[2]; } dual; + dual.d = x + 103079215104.0; // (2**(52-16))*1.5 + f = dual.s[0]*0.0000152587890625; // 2**(-16) + return (int)((dual.i[1]<<16)|((dual.i[0])>>16)); +#elif defined ia64 || defined __ia64__ || defined IA64 + x += 103079215104.0; + long long i = (long long)(x); + f = x - i; + return (int)(i - 103079215104LL); +#else + double y = floor(x); + f = x - y; + return (int)(y); +#endif +} + +inline int vtkResliceRound(double x) +{ +#if defined mips || defined sparc || defined __ppc__ + return (int)((unsigned int)(x + 2147483648.5) - 2147483648U); +#elif defined i386 || defined _M_IX86 + union { double d; unsigned int i[2]; } dual; + dual.d = x + 103079215104.5; // (2**(52-16))*1.5 + return (int)((dual.i[1]<<16)|((dual.i[0])>>16)); +#elif defined ia64 || defined __ia64__ || defined IA64 + x += 103079215104.5; + long long i = (long long)(x); + return (int)(i - 103079215104LL); +#else + return (int)(floor(x+0.5)); +#endif +} + +//---------------------------------------------------------------------------- +vtkImageReslice::vtkImageReslice() +{ + // if NULL, the main Input is used + this->InformationInput = NULL; + this->TransformInputSampling = 1; + this->AutoCropOutput = 0; + this->OutputDimensionality = 3; + + // flag to use default Spacing + this->OutputSpacing[0] = VTK_DOUBLE_MAX; + this->OutputSpacing[1] = VTK_DOUBLE_MAX; + this->OutputSpacing[2] = VTK_DOUBLE_MAX; + + // ditto + this->OutputOrigin[0] = VTK_DOUBLE_MAX; + this->OutputOrigin[1] = VTK_DOUBLE_MAX; + this->OutputOrigin[2] = VTK_DOUBLE_MAX; + + // ditto + this->OutputExtent[0] = VTK_INT_MIN; + this->OutputExtent[2] = VTK_INT_MIN; + this->OutputExtent[4] = VTK_INT_MIN; + + this->OutputExtent[1] = VTK_INT_MAX; + this->OutputExtent[3] = VTK_INT_MAX; + this->OutputExtent[5] = VTK_INT_MAX; + + this->Wrap = 0; // don't wrap + this->Mirror = 0; // don't mirror + this->Border = 1; // apply a border + this->InterpolationMode = VTK_RESLICE_NEAREST; // no interpolation + this->Optimization = 1; // turn off when you're paranoid + + // default black background + this->BackgroundColor[0] = 0; + this->BackgroundColor[1] = 0; + this->BackgroundColor[2] = 0; + this->BackgroundColor[3] = 0; + + // default reslice axes are x, y, z + this->ResliceAxesDirectionCosines[0] = 1.0; + this->ResliceAxesDirectionCosines[1] = 0.0; + this->ResliceAxesDirectionCosines[2] = 0.0; + this->ResliceAxesDirectionCosines[3] = 0.0; + this->ResliceAxesDirectionCosines[4] = 1.0; + this->ResliceAxesDirectionCosines[5] = 0.0; + this->ResliceAxesDirectionCosines[6] = 0.0; + this->ResliceAxesDirectionCosines[7] = 0.0; + this->ResliceAxesDirectionCosines[8] = 1.0; + + // default (0,0,0) axes origin + this->ResliceAxesOrigin[0] = 0.0; + this->ResliceAxesOrigin[1] = 0.0; + this->ResliceAxesOrigin[2] = 0.0; + + // axes and transform are identity if set to NULL + this->ResliceAxes = NULL; + this->ResliceTransform = NULL; + + // cache a matrix that converts output voxel indices -> input voxel indices + this->IndexMatrix = NULL; + this->OptimizedTransform = NULL; + + // set to zero when we completely missed the input extent + this->HitInputExtent = 1; + + // There is an optional second input. + this->SetNumberOfInputPorts(2); +} + +//---------------------------------------------------------------------------- +vtkImageReslice::~vtkImageReslice() +{ + this->SetResliceTransform(NULL); + this->SetResliceAxes(NULL); + if (this->IndexMatrix) + { + this->IndexMatrix->Delete(); + } + if (this->OptimizedTransform) + { + this->OptimizedTransform->Delete(); + } + this->SetInformationInput(NULL); +} + +//---------------------------------------------------------------------------- +void vtkImageReslice::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ResliceAxes: " << this->ResliceAxes << "\n"; + if (this->ResliceAxes) + { + this->ResliceAxes->PrintSelf(os,indent.GetNextIndent()); + } + this->GetResliceAxesDirectionCosines(this->ResliceAxesDirectionCosines); + os << indent << "ResliceAxesDirectionCosines: " << + this->ResliceAxesDirectionCosines[0] << " " << + this->ResliceAxesDirectionCosines[1] << " " << + this->ResliceAxesDirectionCosines[2] << "\n"; + os << indent << " " << + this->ResliceAxesDirectionCosines[3] << " " << + this->ResliceAxesDirectionCosines[4] << " " << + this->ResliceAxesDirectionCosines[5] << "\n"; + os << indent << " " << + this->ResliceAxesDirectionCosines[6] << " " << + this->ResliceAxesDirectionCosines[7] << " " << + this->ResliceAxesDirectionCosines[8] << "\n"; + this->GetResliceAxesOrigin(this->ResliceAxesOrigin); + os << indent << "ResliceAxesOrigin: " << + this->ResliceAxesOrigin[0] << " " << + this->ResliceAxesOrigin[1] << " " << + this->ResliceAxesOrigin[2] << "\n"; + os << indent << "ResliceTransform: " << this->ResliceTransform << "\n"; + if (this->ResliceTransform) + { + this->ResliceTransform->PrintSelf(os,indent.GetNextIndent()); + } + os << indent << "InformationInput: " << this->InformationInput << "\n"; + os << indent << "TransformInputSampling: " << + (this->TransformInputSampling ? "On\n":"Off\n"); + os << indent << "AutoCropOutput: " << + (this->AutoCropOutput ? "On\n":"Off\n"); + os << indent << "OutputSpacing: " << this->OutputSpacing[0] << " " << + this->OutputSpacing[1] << " " << this->OutputSpacing[2] << "\n"; + os << indent << "OutputOrigin: " << this->OutputOrigin[0] << " " << + this->OutputOrigin[1] << " " << this->OutputOrigin[2] << "\n"; + os << indent << "OutputExtent: " << this->OutputExtent[0] << " " << + this->OutputExtent[1] << " " << this->OutputExtent[2] << " " << + this->OutputExtent[3] << " " << this->OutputExtent[4] << " " << + this->OutputExtent[5] << "\n"; + os << indent << "OutputDimensionality: " << + this->OutputDimensionality << "\n"; + os << indent << "Wrap: " << (this->Wrap ? "On\n":"Off\n"); + os << indent << "Mirror: " << (this->Mirror ? "On\n":"Off\n"); + os << indent << "Border: " << (this->Border ? "On\n":"Off\n"); + os << indent << "InterpolationMode: " + << this->GetInterpolationModeAsString() << "\n"; + os << indent << "Optimization: " << (this->Optimization ? "On\n":"Off\n"); + os << indent << "BackgroundColor: " << + this->BackgroundColor[0] << " " << this->BackgroundColor[1] << " " << + this->BackgroundColor[2] << " " << this->BackgroundColor[3] << "\n"; + os << indent << "BackgroundLevel: " << this->BackgroundColor[0] << "\n"; + os << indent << "Stencil: " << this->GetStencil() << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkImageReslice::SetStencil(vtkImageStencilData *stencil) +{ + this->SetInput(1, stencil); +} + +//---------------------------------------------------------------------------- +vtkImageStencilData *vtkImageReslice::GetStencil() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + return vtkImageStencilData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); +} + +//---------------------------------------------------------------------------- +void vtkImageReslice::SetResliceAxesDirectionCosines(double x0, double x1, + double x2, double y0, + double y1, double y2, + double z0, double z1, + double z2) +{ + if (!this->ResliceAxes) + { + // consistent registers/unregisters + this->SetResliceAxes(vtkMatrix4x4::New()); + this->ResliceAxes->Delete(); + this->Modified(); + } + this->ResliceAxes->SetElement(0,0,x0); + this->ResliceAxes->SetElement(1,0,x1); + this->ResliceAxes->SetElement(2,0,x2); + this->ResliceAxes->SetElement(3,0,0); + this->ResliceAxes->SetElement(0,1,y0); + this->ResliceAxes->SetElement(1,1,y1); + this->ResliceAxes->SetElement(2,1,y2); + this->ResliceAxes->SetElement(3,1,0); + this->ResliceAxes->SetElement(0,2,z0); + this->ResliceAxes->SetElement(1,2,z1); + this->ResliceAxes->SetElement(2,2,z2); + this->ResliceAxes->SetElement(3,2,0); +} + +//---------------------------------------------------------------------------- +void vtkImageReslice::GetResliceAxesDirectionCosines(double xdircos[3], + double ydircos[3], + double zdircos[3]) +{ + if (!this->ResliceAxes) + { + xdircos[0] = ydircos[1] = zdircos[2] = 1; + xdircos[1] = ydircos[2] = zdircos[0] = 0; + xdircos[2] = ydircos[0] = zdircos[1] = 0; + return; + } + + for (int i = 0; i < 3; i++) + { + xdircos[i] = this->ResliceAxes->GetElement(i,0); + ydircos[i] = this->ResliceAxes->GetElement(i,1); + zdircos[i] = this->ResliceAxes->GetElement(i,2); + } +} + +//---------------------------------------------------------------------------- +void vtkImageReslice::SetResliceAxesOrigin(double x, double y, double z) +{ + if (!this->ResliceAxes) + { + // consistent registers/unregisters + this->SetResliceAxes(vtkMatrix4x4::New()); + this->ResliceAxes->Delete(); + this->Modified(); + } + + this->ResliceAxes->SetElement(0,3,x); + this->ResliceAxes->SetElement(1,3,y); + this->ResliceAxes->SetElement(2,3,z); + this->ResliceAxes->SetElement(3,3,1); +} + +//---------------------------------------------------------------------------- +void vtkImageReslice::GetResliceAxesOrigin(double origin[3]) +{ + if (!this->ResliceAxes) + { + origin[0] = origin[1] = origin[2] = 0; + return; + } + + for (int i = 0; i < 3; i++) + { + origin[i] = this->ResliceAxes->GetElement(i,3); + } +} + +//---------------------------------------------------------------------------- +// Account for the MTime of the transform and its matrix when determining +// the MTime of the filter +unsigned long int vtkImageReslice::GetMTime() +{ + unsigned long mTime=this->vtkObject::GetMTime(); + unsigned long time; + + if ( this->ResliceTransform != NULL ) + { + time = this->ResliceTransform->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + if (this->ResliceTransform->IsA("vtkHomogeneousTransform")) + { // this is for people who directly modify the transform matrix + time = ((vtkHomogeneousTransform *)this->ResliceTransform) + ->GetMatrix()->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + } + if ( this->ResliceAxes != NULL) + { + time = this->ResliceAxes->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +int vtkImageReslice::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int inExt[6], outExt[6]; + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); + + if (this->ResliceTransform) + { + this->ResliceTransform->Update(); + if (!this->ResliceTransform->IsA("vtkHomogeneousTransform")) + { // update the whole input extent if the transform is nonlinear + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + return 1; + } + } + + int i,j,k; + int idX,idY,idZ; + double xAxis[4], yAxis[4], zAxis[4], origin[4]; + double inPoint0[4]; + double inPoint1[4]; + double point[4],f; + double *inSpacing,*inOrigin,*outSpacing,*outOrigin,inInvSpacing[3]; + + int wrap = this->Wrap || this->Mirror; + + inOrigin = inInfo->Get(vtkDataObject::ORIGIN()); + inSpacing = inInfo->Get(vtkDataObject::SPACING()); + outOrigin = outInfo->Get(vtkDataObject::ORIGIN()); + outSpacing = outInfo->Get(vtkDataObject::SPACING()); + + if (this->Optimization) + { + vtkMatrix4x4 *matrix = this->GetIndexMatrix(inInfo, outInfo); + + // convert matrix from world coordinates to pixel indices + for (i = 0; i < 4; i++) + { + xAxis[i] = matrix->GetElement(i,0); + yAxis[i] = matrix->GetElement(i,1); + zAxis[i] = matrix->GetElement(i,2); + origin[i] = matrix->GetElement(i,3); + } + } + else + { + // save effor later: invert inSpacing + inInvSpacing[0] = 1.0/inSpacing[0]; + inInvSpacing[1] = 1.0/inSpacing[1]; + inInvSpacing[2] = 1.0/inSpacing[2]; + } + + for (i = 0; i < 3; i++) + { + inExt[2*i] = VTK_INT_MAX; + inExt[2*i+1] = VTK_INT_MIN; + } + + // check the coordinates of the 8 corners of the output extent + // (this must be done exactly the same as the calculation in + // vtkImageResliceExecute) + for (i = 0; i < 8; i++) + { + // get output coords + idX = outExt[i%2]; + idY = outExt[2+(i/2)%2]; + idZ = outExt[4+(i/4)%2]; + + if (this->Optimization) + { + inPoint0[0] = origin[0] + idZ*zAxis[0]; // incremental transform + inPoint0[1] = origin[1] + idZ*zAxis[1]; + inPoint0[2] = origin[2] + idZ*zAxis[2]; + inPoint0[3] = origin[3] + idZ*zAxis[3]; + + inPoint1[0] = inPoint0[0] + idY*yAxis[0]; // incremental transform + inPoint1[1] = inPoint0[1] + idY*yAxis[1]; + inPoint1[2] = inPoint0[2] + idY*yAxis[2]; + inPoint1[3] = inPoint0[3] + idY*yAxis[3]; + + point[0] = inPoint1[0] + idX*xAxis[0]; + point[1] = inPoint1[1] + idX*xAxis[1]; + point[2] = inPoint1[2] + idX*xAxis[2]; + point[3] = inPoint1[3] + idX*xAxis[3]; + + if (point[3] != 1.0) + { + f = 1/point[3]; + point[0] *= f; + point[1] *= f; + point[2] *= f; + } + } + else + { + point[0] = idX*outSpacing[0] + outOrigin[0]; + point[1] = idY*outSpacing[1] + outOrigin[1]; + point[2] = idZ*outSpacing[2] + outOrigin[2]; + + if (this->ResliceAxes) + { + point[3] = 1.0; + this->ResliceAxes->MultiplyPoint(point, point); + f = 1.0/point[3]; + point[0] *= f; + point[1] *= f; + point[2] *= f; + } + if (this->ResliceTransform) + { + this->ResliceTransform->TransformPoint(point, point); + } + + point[0] = (point[0] - inOrigin[0])*inInvSpacing[0]; + point[1] = (point[1] - inOrigin[1])*inInvSpacing[1]; + point[2] = (point[2] - inOrigin[2])*inInvSpacing[2]; + } + + // set the extent appropriately according to the interpolation mode + if (this->GetInterpolationMode() != VTK_RESLICE_NEAREST) + { + int extra = (this->GetInterpolationMode() == VTK_RESLICE_CUBIC); + for (j = 0; j < 3; j++) + { + k = vtkResliceFloor(point[j], f); + if (f == 0) + { + if (k < inExt[2*j]) + { + inExt[2*j] = k; + } + if (k > inExt[2*j+1]) + { + inExt[2*j+1] = k; + } + } + else + { + if (k - extra < inExt[2*j]) + { + inExt[2*j] = k - extra; + } + if (k + 1 + extra > inExt[2*j+1]) + { + inExt[2*j+1] = k + 1 + extra; + } + } + } + } + else + { + for (j = 0; j < 3; j++) + { + k = vtkResliceRound(point[j]); + if (k < inExt[2*j]) + { + inExt[2*j] = k; + } + if (k > inExt[2*j+1]) + { + inExt[2*j+1] = k; + } + } + } + } + + // Clip to whole extent, make sure we hit the extent + int wholeExtent[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + this->HitInputExtent = 1; + + for (i = 0; i < 3; i++) + { + if (inExt[2*i] < wholeExtent[2*i]) + { + inExt[2*i] = wholeExtent[2*i]; + if (wrap) + { + inExt[2*i+1] = wholeExtent[2*i+1]; + } + else if (inExt[2*i+1] < wholeExtent[2*i]) + { + // didn't hit any of the input extent + inExt[2*i+1] = wholeExtent[2*i]; + this->HitInputExtent = 0; + } + } + if (inExt[2*i+1] > wholeExtent[2*i+1]) + { + inExt[2*i+1] = wholeExtent[2*i+1]; + if (wrap) + { + inExt[2*i] = wholeExtent[2*i]; + } + else if (inExt[2*i] > wholeExtent[2*i+1]) + { + // didn't hit any of the input extent + inExt[2*i] = wholeExtent[2*i+1]; + // finally, check for null input extent + if (inExt[2*i] < wholeExtent[2*i]) + { + inExt[2*i] = wholeExtent[2*i]; + } + this->HitInputExtent = 0; + } + } + } + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + // need to set the stencil update extent to the output extent + if (this->GetNumberOfInputConnections(1) > 0) + { + vtkInformation *stencilInfo = inputVector[1]->GetInformationObject(0); + stencilInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + outExt, 6); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageReslice::FillInputPortInformation(int port, vtkInformation *info) +{ + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageStencilData"); + // the stencil input is optional + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + else + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageReslice::GetAutoCroppedOutputBounds(vtkInformation *inInfo, + double bounds[6]) +{ + int i, j; + double inSpacing[3], inOrigin[3]; + int inWholeExt[6]; + double f; + double point[4]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inWholeExt); + inInfo->Get(vtkDataObject::SPACING(), inSpacing); + inInfo->Get(vtkDataObject::ORIGIN(), inOrigin); + + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + if (this->ResliceAxes) + { + vtkMatrix4x4::Invert(this->ResliceAxes, matrix); + } + vtkAbstractTransform* transform = NULL; + if (this->ResliceTransform) + { + transform = this->ResliceTransform->GetInverse(); + } + + for (i = 0; i < 3; i++) + { + bounds[2*i] = VTK_DOUBLE_MAX; + bounds[2*i+1] = -VTK_DOUBLE_MAX; + } + + for (i = 0; i < 8; i++) + { + point[0] = inOrigin[0] + inWholeExt[i%2]*inSpacing[0]; + point[1] = inOrigin[1] + inWholeExt[2+(i/2)%2]*inSpacing[1]; + point[2] = inOrigin[2] + inWholeExt[4+(i/4)%2]*inSpacing[2]; + point[3] = 1.0; + + if (this->ResliceTransform) + { + transform->TransformPoint(point,point); + } + matrix->MultiplyPoint(point,point); + + f = 1.0/point[3]; + point[0] *= f; + point[1] *= f; + point[2] *= f; + + for (j = 0; j < 3; j++) + { + if (point[j] > bounds[2*j+1]) + { + bounds[2*j+1] = point[j]; + } + if (point[j] < bounds[2*j]) + { + bounds[2*j] = point[j]; + } + } + } + + matrix->Delete(); +} + +//---------------------------------------------------------------------------- +int vtkImageReslice::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int i,j; + double inSpacing[3], inOrigin[3]; + int inWholeExt[6]; + double outSpacing[3], outOrigin[3]; + int outWholeExt[6]; + double maxBounds[6]; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + if (this->InformationInput) + { + this->InformationInput->UpdateInformation(); + this->InformationInput->GetWholeExtent(inWholeExt); + this->InformationInput->GetSpacing(inSpacing); + this->InformationInput->GetOrigin(inOrigin); + } + else + { + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inWholeExt); + inInfo->Get(vtkDataObject::SPACING(), inSpacing); + inInfo->Get(vtkDataObject::ORIGIN(), inOrigin); + } + + // reslice axes matrix is identity by default + double matrix[4][4]; + double imatrix[4][4]; + for (i = 0; i < 4; i++) + { + matrix[i][0] = matrix[i][1] = matrix[i][2] = matrix[i][3] = 0; + matrix[i][i] = 1; + imatrix[i][0] = imatrix[i][1] = imatrix[i][2] = imatrix[i][3] = 0; + imatrix[i][i] = 1; + } + if (this->ResliceAxes) + { + vtkMatrix4x4::DeepCopy(*matrix, this->ResliceAxes); + vtkMatrix4x4::Invert(*matrix,*imatrix); + } + + if (this->AutoCropOutput) + { + this->GetAutoCroppedOutputBounds(inInfo, maxBounds); + } + + // pass the center of the volume through the inverse of the + // 3x3 direction cosines matrix + double inCenter[3]; + for (i = 0; i < 3; i++) + { + inCenter[i] = inOrigin[i] + \ + 0.5*(inWholeExt[2*i] + inWholeExt[2*i+1])*inSpacing[i]; + } + + // the default spacing, extent and origin are the input spacing, extent + // and origin, transformed by the direction cosines of the ResliceAxes + // if requested (note that the transformed output spacing will always + // be positive) + for (i = 0; i < 3; i++) + { + double s = 0; // default output spacing + double d = 0; // default linear dimension + double e = 0; // default extent start + double c = 0; // transformed center-of-volume + + if (this->TransformInputSampling) + { + double r = 0.0; + for (j = 0; j < 3; j++) + { + c += imatrix[i][j]*(inCenter[j] - matrix[j][3]); + double tmp = matrix[j][i]*matrix[j][i]; + s += tmp*fabs(inSpacing[j]); + d += tmp*(inWholeExt[2*j+1] - inWholeExt[2*j])*fabs(inSpacing[j]); + e += tmp*inWholeExt[2*j]; + r += tmp; + } + s /= r; + d /= r*sqrt(r); + e /= r; + } + else + { + s = inSpacing[i]; + d = (inWholeExt[2*i+1] - inWholeExt[2*i])*s; + e = inWholeExt[2*i]; + } + + if (this->OutputSpacing[i] == VTK_DOUBLE_MAX) + { + outSpacing[i] = s; + } + else + { + outSpacing[i] = this->OutputSpacing[i]; + } + + if (i >= this->OutputDimensionality) + { + outWholeExt[2*i] = 0; + outWholeExt[2*i+1] = 0; + } + else if (this->OutputExtent[2*i] == VTK_INT_MIN || + this->OutputExtent[2*i+1] == VTK_INT_MAX) + { + if (this->AutoCropOutput) + { + d = maxBounds[2*i+1] - maxBounds[2*i]; + } + outWholeExt[2*i] = vtkResliceRound(e); + outWholeExt[2*i+1] = vtkResliceRound(outWholeExt[2*i] + + fabs(d/outSpacing[i])); + } + else + { + outWholeExt[2*i] = this->OutputExtent[2*i]; + outWholeExt[2*i+1] = this->OutputExtent[2*i+1]; + } + + if (i >= this->OutputDimensionality) + { + outOrigin[i] = 0; + } + else if (this->OutputOrigin[i] == VTK_DOUBLE_MAX) + { + if (this->AutoCropOutput) + { // set origin so edge of extent is edge of bounds + outOrigin[i] = maxBounds[2*i] - outWholeExt[2*i]*outSpacing[i]; + } + else + { // center new bounds over center of input bounds + outOrigin[i] = c - \ + 0.5*(outWholeExt[2*i] + outWholeExt[2*i+1])*outSpacing[i]; + } + } + else + { + outOrigin[i] = this->OutputOrigin[i]; + } + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),outWholeExt,6); + outInfo->Set(vtkDataObject::SPACING(), outSpacing, 3); + outInfo->Set(vtkDataObject::ORIGIN(), outOrigin, 3); + + this->GetIndexMatrix(inInfo, outInfo); + + if (this->GetNumberOfInputConnections(1) > 0) + { + vtkInformation *stencilInfo = inputVector[1]->GetInformationObject(0); + stencilInfo->Set(vtkDataObject::SPACING(), + inInfo->Get(vtkDataObject::SPACING()), 3); + stencilInfo->Set(vtkDataObject::ORIGIN(), + inInfo->Get(vtkDataObject::ORIGIN()), 3); + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Interpolation subroutines and associated code +//---------------------------------------------------------------------------- + +// Three interpolation functions are supported: NearestNeighbor, Trilinear, +// and Tricubic. These routines have the following signature: +// +//int interpolate(T *&outPtr, +// const T *inPtr, +// const int inExt[6], +// const vtkIdType inInc[3], +// int numscalars, +// const F point[3], +// int mode, +// const T *background) +// +// where 'T' is any arithmetic type and 'F' is a float type +// +// The result of the interpolation is put in *outPtr, and outPtr is +// incremented. + +//---------------------------------------------------------------------------- +// constants for different boundary-handling modes + +#define VTK_RESLICE_BACKGROUND 0 // use background if out-of-bounds +#define VTK_RESLICE_WRAP 1 // wrap to opposite side of image +#define VTK_RESLICE_MIRROR 2 // mirror off of the boundary +#define VTK_RESLICE_BORDER 3 // use a half-voxel border +#define VTK_RESLICE_NULL 4 // do nothing to *outPtr if out-of-bounds + +//---------------------------------------------------------------------------- +// rounding functions for each type, where 'F' is a floating-point type + +#if (VTK_USE_INT8 != 0) +template +inline void vtkResliceRound(F val, vtkTypeInt8& rnd) +{ + rnd = vtkResliceRound(val); +} +#endif + +#if (VTK_USE_UINT8 != 0) +template +inline void vtkResliceRound(F val, vtkTypeUInt8& rnd) +{ + rnd = vtkResliceRound(val); +} +#endif + +#if (VTK_USE_INT16 != 0) +template +inline void vtkResliceRound(F val, vtkTypeInt16& rnd) +{ + rnd = vtkResliceRound(val); +} +#endif + +#if (VTK_USE_UINT16 != 0) +template +inline void vtkResliceRound(F val, vtkTypeUInt16& rnd) +{ + rnd = vtkResliceRound(val); +} +#endif + +#if (VTK_USE_INT32 != 0) +template +inline void vtkResliceRound(F val, vtkTypeInt32& rnd) +{ + rnd = vtkResliceRound(val); +} +#endif + +#if (VTK_USE_UINT32 != 0) +template +inline void vtkResliceRound(F val, vtkTypeUInt32& rnd) +{ + rnd = vtkResliceRound(val); +} +#endif + +#if (VTK_USE_FLOAT32 != 0) +template +inline void vtkResliceRound(F val, vtkTypeFloat32& rnd) +{ + rnd = val; +} +#endif + +#if (VTK_USE_FLOAT64 != 0) +template +inline void vtkResliceRound(F val, vtkTypeFloat64& rnd) +{ + rnd = val; +} +#endif + +//---------------------------------------------------------------------------- +// clamping functions for each type + +#if (VTK_USE_INT8 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeInt8& clamp) +{ + if (val < -128.0) + { + val = -128.0; + } + if (val > 127.0) + { + val = 127.0; + } + vtkResliceRound(val,clamp); +} +#endif + +#if (VTK_USE_UINT8 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeUInt8& clamp) +{ + if (val < 0) + { + val = 0; + } + if (val > 255.0) + { + val = 255.0; + } + vtkResliceRound(val,clamp); +} +#endif + +#if (VTK_USE_INT16 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeInt16& clamp) +{ + if (val < -32768.0) + { + val = -32768.0; + } + if (val > 32767.0) + { + val = 32767.0; + } + vtkResliceRound(val,clamp); +} +#endif + +#if (VTK_USE_UINT16 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeUInt16& clamp) +{ + if (val < 0) + { + val = 0; + } + if (val > 65535.0) + { + val = 65535.0; + } + vtkResliceRound(val,clamp); +} +#endif + +#if (VTK_USE_INT32 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeInt32& clamp) +{ + if (val < -2147483648.0) + { + val = -2147483648.0; + } + if (val > 2147483647.0) + { + val = 2147483647.0; + } + vtkResliceRound(val,clamp); +} +#endif + +#if (VTK_USE_UINT32 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeUInt32& clamp) +{ + if (val < 0) + { + val = 0; + } + if (val > 4294967295.0) + { + val = 4294967295.0; + } + vtkResliceRound(val,clamp); +} +#endif + +#if (VTK_USE_FLOAT32 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeFloat32& clamp) +{ + clamp = val; +} +#endif + +#if (VTK_USE_FLOAT64 != 0) +template +inline void vtkResliceClamp(F val, vtkTypeFloat64& clamp) +{ + clamp = val; +} +#endif + +//---------------------------------------------------------------------------- +// Perform a wrap to limit an index to [0,range). +// Ensures correct behaviour when the index is negative. + +inline int vtkInterpolateWrap(int num, int range) +{ + if ((num %= range) < 0) + { + num += range; // required for some % implementations + } + return num; +} + +//---------------------------------------------------------------------------- +// Perform a mirror to limit an index to [0,range). + +inline int vtkInterpolateMirror(int num, int range) +{ + if (num < 0) + { + num = -num - 1; + } + int count = num/range; + num %= range; + if (count & 0x1) + { + num = range - num - 1; + } + return num; +} + +//---------------------------------------------------------------------------- +// If the value is within one half voxel of the range [0,inExtX), then +// set it to "0" or "inExtX-1" as appropriate. + +inline int vtkInterpolateBorder(int &inIdX0, int &inIdX1, int inExtX, + double fx) +{ + if (inIdX0 >= 0 && inIdX1 < inExtX) + { + return 0; + } + if (inIdX0 == -1 && fx >= 0.5) + { + inIdX1 = inIdX0 = 0; + return 0; + } + if (inIdX0 == inExtX - 1 && fx < 0.5) + { + inIdX1 = inIdX0; + return 0; + } + + return 1; +} + +inline int vtkInterpolateBorderCheck(int inIdX0, int inIdX1, int inExtX, + double fx) +{ + if ((inIdX0 >= 0 && inIdX1 < inExtX) || + (inIdX0 == -1 && fx >= 0.5) || + (inIdX0 == inExtX - 1 && fx < 0.5)) + { + return 0; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Do nearest-neighbor interpolation of the input data 'inPtr' of extent +// 'inExt' at the 'point'. The result is placed at 'outPtr'. +// If the lookup data is beyond the extent 'inExt', set 'outPtr' to +// the background color 'background'. +// The number of scalar components in the data is 'numscalars' +template +int vtkNearestNeighborInterpolation(T *&outPtr, const T *inPtr, + const int inExt[6], + const vtkIdType inInc[3], + int numscalars, const F point[3], + int mode, const T *background) +{ + int inIdX0 = vtkResliceRound(point[0]) - inExt[0]; + int inIdY0 = vtkResliceRound(point[1]) - inExt[2]; + int inIdZ0 = vtkResliceRound(point[2]) - inExt[4]; + + int inExtX = inExt[1] - inExt[0] + 1; + int inExtY = inExt[3] - inExt[2] + 1; + int inExtZ = inExt[5] - inExt[4] + 1; + + if (inIdX0 < 0 || inIdX0 >= inExtX || + inIdY0 < 0 || inIdY0 >= inExtY || + inIdZ0 < 0 || inIdZ0 >= inExtZ) + { + if (mode == VTK_RESLICE_WRAP) + { + inIdX0 = vtkInterpolateWrap(inIdX0, inExtX); + inIdY0 = vtkInterpolateWrap(inIdY0, inExtY); + inIdZ0 = vtkInterpolateWrap(inIdZ0, inExtZ); + } + else if (mode == VTK_RESLICE_MIRROR) + { + inIdX0 = vtkInterpolateMirror(inIdX0, inExtX); + inIdY0 = vtkInterpolateMirror(inIdY0, inExtY); + inIdZ0 = vtkInterpolateMirror(inIdZ0, inExtZ); + } + else if (mode == VTK_RESLICE_BACKGROUND || + mode == VTK_RESLICE_BORDER) + { + do + { + *outPtr++ = *background++; + } + while (--numscalars); + return 0; + } + else + { + return 0; + } + } + + inPtr += inIdX0*inInc[0]+inIdY0*inInc[1]+inIdZ0*inInc[2]; + do + { + *outPtr++ = *inPtr++; + } + while (--numscalars); + + return 1; +} + +//---------------------------------------------------------------------------- +// Do trilinear interpolation of the input data 'inPtr' of extent 'inExt' +// at the 'point'. The result is placed at 'outPtr'. +// If the lookup data is beyond the extent 'inExt', set 'outPtr' to +// the background color 'background'. +// The number of scalar components in the data is 'numscalars' +template +int vtkTrilinearInterpolation(T *&outPtr, const T *inPtr, + const int inExt[6], const vtkIdType inInc[3], + int numscalars, const F point[3], + int mode, const T *background) +{ + F fx, fy, fz; + int floorX = vtkResliceFloor(point[0], fx); + int floorY = vtkResliceFloor(point[1], fy); + int floorZ = vtkResliceFloor(point[2], fz); + + int inIdX0 = floorX - inExt[0]; + int inIdY0 = floorY - inExt[2]; + int inIdZ0 = floorZ - inExt[4]; + + int inIdX1 = inIdX0 + (fx != 0); + int inIdY1 = inIdY0 + (fy != 0); + int inIdZ1 = inIdZ0 + (fz != 0); + + int inExtX = inExt[1] - inExt[0] + 1; + int inExtY = inExt[3] - inExt[2] + 1; + int inExtZ = inExt[5] - inExt[4] + 1; + + if (inIdX0 < 0 || inIdX1 >= inExtX || + inIdY0 < 0 || inIdY1 >= inExtY || + inIdZ0 < 0 || inIdZ1 >= inExtZ) + { + if (mode == VTK_RESLICE_BORDER) + { + if (vtkInterpolateBorder(inIdX0, inIdX1, inExtX, fx) || + vtkInterpolateBorder(inIdY0, inIdY1, inExtY, fy) || + vtkInterpolateBorder(inIdZ0, inIdZ1, inExtZ, fz)) + { + do + { + *outPtr++ = *background++; + } + while (--numscalars); + return 0; + } + } + else if (mode == VTK_RESLICE_WRAP) + { + inIdX0 = vtkInterpolateWrap(inIdX0, inExtX); + inIdY0 = vtkInterpolateWrap(inIdY0, inExtY); + inIdZ0 = vtkInterpolateWrap(inIdZ0, inExtZ); + + inIdX1 = vtkInterpolateWrap(inIdX1, inExtX); + inIdY1 = vtkInterpolateWrap(inIdY1, inExtY); + inIdZ1 = vtkInterpolateWrap(inIdZ1, inExtZ); + } + else if (mode == VTK_RESLICE_MIRROR) + { + inIdX0 = vtkInterpolateMirror(inIdX0, inExtX); + inIdY0 = vtkInterpolateMirror(inIdY0, inExtY); + inIdZ0 = vtkInterpolateMirror(inIdZ0, inExtZ); + + inIdX1 = vtkInterpolateMirror(inIdX1, inExtX); + inIdY1 = vtkInterpolateMirror(inIdY1, inExtY); + inIdZ1 = vtkInterpolateMirror(inIdZ1, inExtZ); + } + else if (mode == VTK_RESLICE_BACKGROUND) + { + do + { + *outPtr++ = *background++; + } + while (--numscalars); + return 0; + } + else + { + return 0; + } + } + + vtkIdType factX0 = inIdX0*inInc[0]; + vtkIdType factX1 = inIdX1*inInc[0]; + vtkIdType factY0 = inIdY0*inInc[1]; + vtkIdType factY1 = inIdY1*inInc[1]; + vtkIdType factZ0 = inIdZ0*inInc[2]; + vtkIdType factZ1 = inIdZ1*inInc[2]; + + vtkIdType i00 = factY0 + factZ0; + vtkIdType i01 = factY0 + factZ1; + vtkIdType i10 = factY1 + factZ0; + vtkIdType i11 = factY1 + factZ1; + + F rx = 1 - fx; + F ry = 1 - fy; + F rz = 1 - fz; + + F ryrz = ry*rz; + F fyrz = fy*rz; + F ryfz = ry*fz; + F fyfz = fy*fz; + + const T *inPtr0 = inPtr + factX0; + const T *inPtr1 = inPtr + factX1; + + do + { + F result = (rx*(ryrz*inPtr0[i00] + ryfz*inPtr0[i01] + + fyrz*inPtr0[i10] + fyfz*inPtr0[i11]) + + fx*(ryrz*inPtr1[i00] + ryfz*inPtr1[i01] + + fyrz*inPtr1[i10] + fyfz*inPtr1[i11])); + + vtkResliceRound(result, *outPtr++); + inPtr0++; + inPtr1++; + } + while (--numscalars); + + return 1; +} + +//---------------------------------------------------------------------------- +// Do tricubic interpolation of the input data 'inPtr' of extent 'inExt' +// at the 'point'. The result is placed at 'outPtr'. +// The number of scalar components in the data is 'numscalars' +// The tricubic interpolation ensures that both the intensity and +// the first derivative of the intensity are smooth across the +// image. The first derivative is estimated using a +// centered-difference calculation. + + +// helper function: set up the lookup indices and the interpolation +// coefficients + +template +void vtkTricubicInterpCoeffs(T F[4], int l, int h, T f) +{ + static const T half = T(0.5); + + int order = h - l; + + if (order == 0) + { // no interpolation + F[0] = 0; + F[1] = 1; + F[2] = 0; + F[3] = 0; + return; + } + if (order == 3) + { // cubic interpolation + T fm1 = f - 1; + T fd2 = f*half; + T ft3 = f*3; + F[0] = -fd2*fm1*fm1; + F[1] = ((ft3 - 2)*fd2 - 1)*fm1; + F[2] = -((ft3 - 4)*f - 1)*fd2; + F[3] = f*fd2*fm1; + return; + } + if (order == 1) + { // linear interpolation + F[0] = 0; + F[1] = 1 - f; + F[2] = f; + F[3] = 0; + return; + } + if (l == 0) + { // quadratic interpolation + T fp1 = f + 1; + T fm1 = f - 1; + T fd2 = f*half; + F[0] = fd2*fm1; + F[1] = -fp1*fm1; + F[2] = fp1*fd2; + F[3] = 0; + return; + } + // else + { // quadratic interpolation + T fm1 = f - 1; + T fm2 = fm1 - 1; + T fm1d2 = fm1*half; + F[0] = 0; + F[1] = fm1d2*fm2; + F[2] = -f*fm2; + F[3] = f*fm1d2; + return; + } +} + +// tricubic interpolation +template +int vtkTricubicInterpolation(T *&outPtr, const T *inPtr, + const int inExt[6], const vtkIdType inInc[3], + int numscalars, const F point[3], + int mode, const T *background) +{ + F fx, fy, fz; + int floorX = vtkResliceFloor(point[0], fx); + int floorY = vtkResliceFloor(point[1], fy); + int floorZ = vtkResliceFloor(point[2], fz); + + int fxIsNotZero = (fx != 0); + int fyIsNotZero = (fy != 0); + int fzIsNotZero = (fz != 0); + + int inIdX0 = floorX - inExt[0]; + int inIdY0 = floorY - inExt[2]; + int inIdZ0 = floorZ - inExt[4]; + + int inIdX1 = inIdX0 + fxIsNotZero; + int inIdY1 = inIdY0 + fyIsNotZero; + int inIdZ1 = inIdZ0 + fzIsNotZero; + + int inExtX = inExt[1] - inExt[0] + 1; + int inExtY = inExt[3] - inExt[2] + 1; + int inExtZ = inExt[5] - inExt[4] + 1; + + vtkIdType inIncX = inInc[0]; + vtkIdType inIncY = inInc[1]; + vtkIdType inIncZ = inInc[2]; + + vtkIdType factX[4], factY[4], factZ[4]; + + if (inIdX0 < 0 || inIdX1 >= inExtX || + inIdY0 < 0 || inIdY1 >= inExtY || + inIdZ0 < 0 || inIdZ1 >= inExtZ) + { + if (mode == VTK_RESLICE_BORDER) + { + if (vtkInterpolateBorderCheck(inIdX0, inIdX1, inExtX, fx) || + vtkInterpolateBorderCheck(inIdY0, inIdY1, inExtY, fy) || + vtkInterpolateBorderCheck(inIdZ0, inIdZ1, inExtZ, fz)) + { + do + { + *outPtr++ = *background++; + } + while (--numscalars); + return 0; + } + } + else if (mode != VTK_RESLICE_WRAP && mode != VTK_RESLICE_MIRROR) + { + if (mode == VTK_RESLICE_BACKGROUND) + { + do + { + *outPtr++ = *background++; + } + while (--numscalars); + return 0; + } + else + { + return 0; + } + } + } + + F fX[4], fY[4], fZ[4]; + int k1, k2, j1, j2, i1, i2; + + if (mode == VTK_RESLICE_WRAP || mode == VTK_RESLICE_MIRROR) + { + i1 = 0; + i2 = 3; + vtkTricubicInterpCoeffs(fX, i1, i2, fx); + + j1 = 1 - fyIsNotZero; + j2 = 1 + (fyIsNotZero<<1); + vtkTricubicInterpCoeffs(fY, j1, j2, fy); + + k1 = 1 - fzIsNotZero; + k2 = 1 + (fzIsNotZero<<1); + vtkTricubicInterpCoeffs(fZ, k1, k2, fz); + + if (mode == VTK_RESLICE_WRAP) + { + for (int i = 0; i < 4; i++) + { + factX[i] = vtkInterpolateWrap(inIdX0 + i - 1, inExtX)*inIncX; + factY[i] = vtkInterpolateWrap(inIdY0 + i - 1, inExtY)*inIncY; + factZ[i] = vtkInterpolateWrap(inIdZ0 + i - 1, inExtZ)*inIncZ; + } + } + else + { + for (int i = 0; i < 4; i++) + { + factX[i] = vtkInterpolateMirror(inIdX0 + i - 1, inExtX)*inIncX; + factY[i] = vtkInterpolateMirror(inIdY0 + i - 1, inExtY)*inIncY; + factZ[i] = vtkInterpolateMirror(inIdZ0 + i - 1, inExtZ)*inIncZ; + } + } + } + else if (mode == VTK_RESLICE_BORDER) + { + // clamp to the border of the input extent + + i1 = 1 - fxIsNotZero; + j1 = 1 - fyIsNotZero; + k1 = 1 - fzIsNotZero; + + i2 = 1 + 2*fxIsNotZero; + j2 = 1 + 2*fyIsNotZero; + k2 = 1 + 2*fzIsNotZero; + + vtkTricubicInterpCoeffs(fX, i1, i2, fx); + vtkTricubicInterpCoeffs(fY, j1, j2, fy); + vtkTricubicInterpCoeffs(fZ, k1, k2, fz); + + int tmpExt = inExtX - 1; + int tmpId = tmpExt - inIdX0 - 1; + factX[0] = (inIdX0 - 1)*(inIdX0 - 1 >= 0)*inIncX; + factX[1] = (inIdX0)*(inIdX0 >= 0)*inIncX; + factX[2] = (tmpExt - (tmpId)*(tmpId >= 0))*inIncX; + factX[3] = (tmpExt - (tmpId - 1)*(tmpId - 1 >= 0))*inIncX; + + tmpExt = inExtY - 1; + tmpId = tmpExt - inIdY0 - 1; + factY[0] = (inIdY0 - 1)*(inIdY0 - 1 >= 0)*inIncY; + factY[1] = (inIdY0)*(inIdY0 >= 0)*inIncY; + factY[2] = (tmpExt - (tmpId)*(tmpId >= 0))*inIncY; + factY[3] = (tmpExt - (tmpId - 1)*(tmpId - 1 >= 0))*inIncY; + + tmpExt = inExtZ - 1; + tmpId = tmpExt - inIdZ0 - 1; + factZ[0] = (inIdZ0 - 1)*(inIdZ0 - 1 >= 0)*inIncZ; + factZ[1] = (inIdZ0)*(inIdZ0 >= 0)*inIncZ; + factZ[2] = (tmpExt - (tmpId)*(tmpId >= 0))*inIncZ; + factZ[3] = (tmpExt - (tmpId - 1)*(tmpId - 1 >= 0))*inIncZ; + } + else + { + // depending on whether we are at the edge of the + // input extent, choose the appropriate interpolation + // method to use + + i1 = 1 - (inIdX0 > 0)*fxIsNotZero; + j1 = 1 - (inIdY0 > 0)*fyIsNotZero; + k1 = 1 - (inIdZ0 > 0)*fzIsNotZero; + + i2 = 1 + (1 + (inIdX0 + 2 < inExtX))*fxIsNotZero; + j2 = 1 + (1 + (inIdY0 + 2 < inExtY))*fyIsNotZero; + k2 = 1 + (1 + (inIdZ0 + 2 < inExtZ))*fzIsNotZero; + + vtkTricubicInterpCoeffs(fX, i1, i2, fx); + vtkTricubicInterpCoeffs(fY, j1, j2, fy); + vtkTricubicInterpCoeffs(fZ, k1, k2, fz); + + factX[1] = inIdX0*inIncX; + factX[0] = factX[1] - inIncX; + factX[2] = factX[1] + inIncX; + factX[3] = factX[2] + inIncX; + + factY[1] = inIdY0*inIncY; + factY[0] = factY[1] - inIncY; + factY[2] = factY[1] + inIncY; + factY[3] = factY[2] + inIncY; + + factZ[1] = inIdZ0*inIncZ; + factZ[0] = factZ[1] - inIncZ; + factZ[2] = factZ[1] + inIncZ; + factZ[3] = factZ[2] + inIncZ; + + // this little bit of wierdness allows us to unroll the x loop + if (i1 > 0) + { + factX[0] = factX[1]; + } + if (i2 < 3) + { + factX[3] = factX[1]; + if (i2 < 2) + { + factX[2] = factX[1]; + } + } + } + + do // loop over components + { + F val = 0; + int k = k1; + do // loop over z + { + F ifz = fZ[k]; + vtkIdType factz = factZ[k]; + int j = j1; + do // loop over y + { + F ify = fY[j]; + F fzy = ifz*ify; + vtkIdType factzy = factz + factY[j]; + const T *tmpPtr = inPtr + factzy; + // loop over x is unrolled (significant performance boost) + val += fzy*(fX[0]*tmpPtr[factX[0]] + + fX[1]*tmpPtr[factX[1]] + + fX[2]*tmpPtr[factX[2]] + + fX[3]*tmpPtr[factX[3]]); + } + while (++j <= j2); + } + while (++k <= k2); + + vtkResliceClamp(val, *outPtr++); + inPtr++; + } + while (--numscalars); + + return 1; +} + +//-------------------------------------------------------------------------- +// get appropriate interpolation function according to interpolation mode +// and scalar type +template +void vtkGetResliceInterpFunc(vtkImageReslice *self, + int (**interpolate)(void *&outPtr, + const void *inPtr, + const int inExt[6], + const vtkIdType inInc[3], + int numscalars, + const F point[3], + int mode, + const void *background)) +{ + int dataType = self->GetOutput()->GetScalarType(); + int interpolationMode = self->GetInterpolationMode(); + + switch (interpolationMode) + { + case VTK_RESLICE_NEAREST: + switch (dataType) + { + vtkTemplateAliasMacro(*((int (**)(VTK_TT *&outPtr, const VTK_TT *inPtr, + const int inExt[6], + const vtkIdType inInc[3], + int numscalars, const F point[3], + int mode, + const VTK_TT *background))interpolate) = \ + &vtkNearestNeighborInterpolation); + default: + interpolate = 0; + } + break; + case VTK_RESLICE_LINEAR: + switch (dataType) + { + vtkTemplateAliasMacro(*((int (**)(VTK_TT *&outPtr, const VTK_TT *inPtr, + const int inExt[6], + const vtkIdType inInc[3], + int numscalars, const F point[3], + int mode, + const VTK_TT *background))interpolate) = \ + &vtkTrilinearInterpolation); + default: + interpolate = 0; + } + break; + case VTK_RESLICE_CUBIC: + switch (dataType) + { + vtkTemplateAliasMacro(*((int (**)(VTK_TT *&outPtr, const VTK_TT *inPtr, + const int inExt[6], + const vtkIdType inInc[3], + int numscalars, const F point[3], + int mode, + const VTK_TT *background))interpolate) = \ + &vtkTricubicInterpolation); + default: + interpolate = 0; + } + break; + default: + interpolate = 0; + } +} + + +//---------------------------------------------------------------------------- +// Some helper functions for 'RequestData' +//---------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// pixel copy function, templated for different scalar types +template +void vtkSetPixels(T *&outPtr, const T *inPtr, int numscalars, int n) +{ + for (int i = 0; i < n; i++) + { + const T *tmpPtr = inPtr; + int m = numscalars; + do + { + *outPtr++ = *tmpPtr++; + } + while (--m); + } +} + +// optimized for 1 scalar components +template +void vtkSetPixels1(T *&outPtr, const T *inPtr, + int vtkNotUsed(numscalars), int n) +{ + T val = *inPtr; + for (int i = 0; i < n; i++) + { + *outPtr++ = val; + } +} + +// get a pixel copy function that is appropriate for the data type +void vtkGetSetPixelsFunc(vtkImageReslice *self, + void (**setpixels)(void *&out, const void *in, + int numscalars, int n)) +{ + int dataType = self->GetOutput()->GetScalarType(); + int numscalars = self->GetOutput()->GetNumberOfScalarComponents(); + + switch (numscalars) + { + case 1: + switch (dataType) + { + vtkTemplateAliasMacro(*((void (**)(VTK_TT *&out, const VTK_TT *in, + int numscalars, int n))setpixels) = \ + vtkSetPixels1); + default: + setpixels = 0; + } + default: + switch (dataType) + { + vtkTemplateAliasMacro(*((void (**)(VTK_TT *&out, const VTK_TT *in, + int numscalars, int n))setpixels) = \ + vtkSetPixels); + default: + setpixels = 0; + } + } +} + +//---------------------------------------------------------------------------- +// Convert background color from float to appropriate type +template +void vtkAllocBackgroundPixelT(vtkImageReslice *self, + T **background_ptr, int numComponents) +{ + *background_ptr = new T[numComponents]; + T *background = *background_ptr; + + for (int i = 0; i < numComponents; i++) + { + if (i < 4) + { + vtkResliceClamp(self->GetBackgroundColor()[i], background[i]); + } + else + { + background[i] = 0; + } + } +} + +void vtkAllocBackgroundPixel(vtkImageReslice *self, void **rval, + int numComponents) +{ + switch (self->GetOutput()->GetScalarType()) + { + vtkTemplateAliasMacro(vtkAllocBackgroundPixelT(self, (VTK_TT **)rval, + numComponents)); + } +} + +void vtkFreeBackgroundPixel(vtkImageReslice *self, void **rval) +{ + switch (self->GetOutput()->GetScalarType()) + { + vtkTemplateAliasMacro(delete [] *((VTK_TT **)rval)); + } + + *rval = 0; +} + +//---------------------------------------------------------------------------- +// helper function for clipping of the output with a stencil +int vtkResliceGetNextExtent(vtkImageStencilData *stencil, + int &r1, int &r2, int rmin, int rmax, + int yIdx, int zIdx, + void *&outPtr, void *background, + int numscalars, + void (*setpixels)(void *&out, + const void *in, + int numscalars, + int n), + int &iter) +{ + // trivial case if stencil is not set + if (!stencil) + { + if (iter++ == 0) + { + r1 = rmin; + r2 = rmax; + return 1; + } + return 0; + } + + // for clearing, start at last r2 plus 1 + int clear1 = r2 + 1; + if (iter == 0) + { // if no 'last time', start at rmin + clear1 = rmin; + } + + int rval = stencil->GetNextExtent(r1, r2, rmin, rmax, yIdx, zIdx, iter); + int clear2 = r1 - 1; + if (rval == 0) + { + clear2 = rmax; + } + + setpixels(outPtr, background, numscalars, clear2 - clear1 + 1); + + return rval; +} + +//---------------------------------------------------------------------------- +// This function simply clears the entire output to the background color, +// for cases where the transformation places the output extent completely +// outside of the input extent. +void vtkImageResliceClearExecute(vtkImageReslice *self, + vtkImageData *, void *, + vtkImageData *outData, void *outPtr, + int outExt[6], int id) +{ + int numscalars; + int idY, idZ; + vtkIdType outIncX, outIncY, outIncZ; + int scalarSize; + unsigned long count = 0; + unsigned long target; + void *background; + void (*setpixels)(void *&out, const void *in, int numscalars, int n); + + // for the progress meter + target = (unsigned long) + ((outExt[5]-outExt[4]+1)*(outExt[3]-outExt[2]+1)/50.0); + target++; + + // Get Increments to march through data + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + scalarSize = outData->GetScalarSize(); + numscalars = outData->GetNumberOfScalarComponents(); + + // allocate a voxel to copy into the background (out-of-bounds) regions + vtkAllocBackgroundPixel(self, &background, numscalars); + // get the appropriate function for pixel copying + vtkGetSetPixelsFunc(self, &setpixels); + + // Loop through output voxels + for (idZ = outExt[4]; idZ <= outExt[5]; idZ++) + { + for (idY = outExt[2]; idY <= outExt[3]; idY++) + { + if (id == 0) + { // update the progress if this is the main thread + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + // clear the pixels to background color and go to next row + setpixels(outPtr, background, numscalars, outExt[1]-outExt[0]+1); + outPtr = (void *)((char *)outPtr + outIncY*scalarSize); + } + outPtr = (void *)((char *)outPtr + outIncZ*scalarSize); + } + + vtkFreeBackgroundPixel(self, &background); +} + +//---------------------------------------------------------------------------- +// This function executes the filter for any type of data. It is much simpler +// in structure than vtkImageResliceOptimizedExecute. +void vtkImageResliceExecute(vtkImageReslice *self, + vtkImageData *inData, void *inPtr, + vtkImageData *outData, void *outPtr, + int outExt[6], int id) +{ + int numscalars; + int idX, idY, idZ; + int idXmin, idXmax, iter; + vtkIdType outIncX, outIncY, outIncZ; + int scalarSize; + int inExt[6]; + vtkIdType inInc[3]; + unsigned long count = 0; + unsigned long target; + double point[4]; + double f; + double *inSpacing, *inOrigin, *outSpacing, *outOrigin, inInvSpacing[3]; + void *background; + int (*interpolate)(void *&outPtr, const void *inPtr, + const int inExt[6], const vtkIdType inInc[3], + int numscalars, const double point[3], + int mode, const void *background); + void (*setpixels)(void *&out, const void *in, int numscalars, int n); + + // the 'mode' species what to do with the 'pad' (out-of-bounds) area + int mode = VTK_RESLICE_BACKGROUND; + if (self->GetMirror()) + { + mode = VTK_RESLICE_MIRROR; + } + else if (self->GetWrap()) + { + mode = VTK_RESLICE_WRAP; + } + else if (self->GetBorder()) + { + mode = VTK_RESLICE_BORDER; + } + + // the transformation to apply to the data + vtkAbstractTransform *transform = self->GetResliceTransform(); + vtkMatrix4x4 *matrix = self->GetResliceAxes(); + + // for conversion to data coordinates + inOrigin = inData->GetOrigin(); + inSpacing = inData->GetSpacing(); + outOrigin = outData->GetOrigin(); + outSpacing = outData->GetSpacing(); + + // save effor later: invert inSpacing + inInvSpacing[0] = 1.0/inSpacing[0]; + inInvSpacing[1] = 1.0/inSpacing[1]; + inInvSpacing[2] = 1.0/inSpacing[2]; + + // find maximum input range + inData->GetExtent(inExt); + + // for the progress meter + target = (unsigned long) + ((outExt[5]-outExt[4]+1)*(outExt[3]-outExt[2]+1)/50.0); + target++; + + // Get Increments to march through data + inData->GetIncrements(inInc); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + scalarSize = outData->GetScalarSize(); + numscalars = inData->GetNumberOfScalarComponents(); + + // allocate a voxel to copy into the background (out-of-bounds) regions + vtkAllocBackgroundPixel(self, &background, numscalars); + + // get the appropriate functions for interpolation and pixel copying + vtkGetResliceInterpFunc(self, &interpolate); + vtkGetSetPixelsFunc(self, &setpixels); + + // get the stencil + vtkImageStencilData *stencil = self->GetStencil(); + + // Loop through output voxels + for (idZ = outExt[4]; idZ <= outExt[5]; idZ++) + { + for (idY = outExt[2]; idY <= outExt[3]; idY++) + { + if (id == 0) + { // update the progress if this is the main thread + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + iter = 0; // if there is a stencil, it is applied here + while (vtkResliceGetNextExtent(stencil, idXmin, idXmax, + outExt[0], outExt[1], idY, idZ, + outPtr, background, numscalars, + setpixels, iter)) + { + for (idX = idXmin; idX <= idXmax; idX++) + { + // convert to data coordinates + point[0] = idX*outSpacing[0] + outOrigin[0]; + point[1] = idY*outSpacing[1] + outOrigin[1]; + point[2] = idZ*outSpacing[2] + outOrigin[2]; + + // apply ResliceAxes matrix + if (matrix) + { + point[3] = 1.0; + matrix->MultiplyPoint(point, point); + f = 1.0/point[3]; + point[0] *= f; + point[1] *= f; + point[2] *= f; + } + + // apply ResliceTransform + if (transform) + { + transform->InternalTransformPoint(point, point); + } + + // convert back to voxel indices + point[0] = (point[0] - inOrigin[0])*inInvSpacing[0]; + point[1] = (point[1] - inOrigin[1])*inInvSpacing[1]; + point[2] = (point[2] - inOrigin[2])*inInvSpacing[2]; + + // interpolate output voxel from input data set + interpolate(outPtr, inPtr, inExt, inInc, numscalars, + point, mode, background); + } + } + outPtr = (void *)((char *)outPtr + outIncY*scalarSize); + } + outPtr = (void *)((char *)outPtr + outIncZ*scalarSize); + } + + vtkFreeBackgroundPixel(self, &background); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// The remainder of this file is the 'optimized' version of the code. +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +// application of the transform has different forms for fixed-point +// vs. floating-point +template +inline +void vtkResliceApplyTransform(vtkAbstractTransform *newtrans, + F inPoint[3], F inOrigin[3], + F inInvSpacing[3]) +{ + newtrans->InternalTransformPoint(inPoint, inPoint); + inPoint[0] -= inOrigin[0]; + inPoint[1] -= inOrigin[1]; + inPoint[2] -= inOrigin[2]; + inPoint[0] *= inInvSpacing[0]; + inPoint[1] *= inInvSpacing[1]; + inPoint[2] *= inInvSpacing[2]; +} + +// The vtkOptimizedExecute() is like vtkImageResliceExecute, except that +// it provides a few optimizations: +// 1) the ResliceAxes and ResliceTransform are joined to create a +// single 4x4 matrix if possible +// 2) the transformation is calculated incrementally to increase efficiency +// 3) nearest-neighbor interpolation is treated specially in order to +// increase efficiency + +template +void vtkOptimizedExecute(vtkImageReslice *self, + vtkImageData *inData, void *inPtr, + vtkImageData *outData, void *outPtr, + int outExt[6], int id, F newmat[4][4], + vtkAbstractTransform *newtrans) +{ + int i, numscalars; + int idX, idY, idZ; + vtkIdType outIncX, outIncY, outIncZ; + int scalarSize; + int inExt[6]; + vtkIdType inInc[3]; + unsigned long count = 0; + unsigned long target; + int iter, idXmin, idXmax; + double temp[3]; + F inOrigin[3], inInvSpacing[3]; + F xAxis[4], yAxis[4], zAxis[4], origin[4]; + F inPoint0[4]; + F inPoint1[4]; + F inPoint[4], f; + void *background; + int (*interpolate)(void *&outPtr, const void *inPtr, + const int inExt[6], const vtkIdType inInc[3], + int numscalars, const F point[3], + int mode, const void *background); + void (*setpixels)(void *&out, const void *in, int numscalars, int n); + + int mode = VTK_RESLICE_BACKGROUND; + int wrap = 0; + + if (self->GetMirror()) + { + mode = VTK_RESLICE_MIRROR; + wrap = 1; + } + else if (self->GetWrap()) + { + mode = VTK_RESLICE_WRAP; + wrap = 1; + } + else if (self->GetBorder()) + { + mode = VTK_RESLICE_BORDER; + } + + int perspective = 0; + if (newmat[3][0] != 0 || newmat[3][1] != 0 || + newmat[3][2] != 0 || newmat[3][3] != 1) + { + perspective = 1; + } + + int optimizeNearest = 0; + if (self->GetInterpolationMode() == VTK_RESLICE_NEAREST && + !(wrap || newtrans || perspective)) + { + optimizeNearest = 1; + } + + // find maximum input range + inData->GetExtent(inExt); + + target = (unsigned long) + ((outExt[5]-outExt[4]+1)*(outExt[3]-outExt[2]+1)/50.0); + target++; + + // Get Increments to march through data + inData->GetIncrements(inInc); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + scalarSize = outData->GetScalarSize(); + numscalars = inData->GetNumberOfScalarComponents(); + + // break matrix into a set of axes plus an origin + // (this allows us to calculate the transform Incrementally) + for (i = 0; i < 4; i++) + { + xAxis[i] = newmat[i][0]; + yAxis[i] = newmat[i][1]; + zAxis[i] = newmat[i][2]; + origin[i] = newmat[i][3]; + } + + // get the input origin and spacing for conversion purposes + inData->GetOrigin(temp); + inOrigin[0] = F(temp[0]); + inOrigin[1] = F(temp[1]); + inOrigin[2] = F(temp[2]); + + inData->GetSpacing(temp); + inInvSpacing[0] = F(1.0/temp[0]); + inInvSpacing[1] = F(1.0/temp[1]); + inInvSpacing[2] = F(1.0/temp[2]); + + // set color for area outside of input volume extent + vtkAllocBackgroundPixel(self, &background, numscalars); + + // Set interpolation method + vtkGetResliceInterpFunc(self, &interpolate); + vtkGetSetPixelsFunc(self, &setpixels); + + // get the stencil + vtkImageStencilData *stencil = self->GetStencil(); + + // Loop through output pixels + for (idZ = outExt[4]; idZ <= outExt[5]; idZ++) + { + inPoint0[0] = origin[0] + idZ*zAxis[0]; // incremental transform + inPoint0[1] = origin[1] + idZ*zAxis[1]; + inPoint0[2] = origin[2] + idZ*zAxis[2]; + inPoint0[3] = origin[3] + idZ*zAxis[3]; + + for (idY = outExt[2]; idY <= outExt[3]; idY++) + { + inPoint1[0] = inPoint0[0] + idY*yAxis[0]; // incremental transform + inPoint1[1] = inPoint0[1] + idY*yAxis[1]; + inPoint1[2] = inPoint0[2] + idY*yAxis[2]; + inPoint1[3] = inPoint0[3] + idY*yAxis[3]; + + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + iter = 0; + while (vtkResliceGetNextExtent(stencil, idXmin, idXmax, + outExt[0], outExt[1], idY, idZ, + outPtr, background, numscalars, + setpixels, iter)) + { + if (!optimizeNearest) + { + for (idX = idXmin; idX <= idXmax; idX++) + { + inPoint[0] = inPoint1[0] + idX*xAxis[0]; + inPoint[1] = inPoint1[1] + idX*xAxis[1]; + inPoint[2] = inPoint1[2] + idX*xAxis[2]; + if (perspective) + { // only do perspective if necessary + inPoint[3] = inPoint1[3] + idX*xAxis[3]; + f = 1/inPoint[3]; + inPoint[0] *= f; + inPoint[1] *= f; + inPoint[2] *= f; + } + if (newtrans) + { // apply the AbstractTransform if there is one + vtkResliceApplyTransform(newtrans, inPoint, inOrigin, + inInvSpacing); + } + // call the interpolation function + interpolate(outPtr, inPtr, inExt, inInc, numscalars, + inPoint, mode, background); + } + } + else // optimize for nearest-neighbor interpolation + { + int inExtX = inExt[1] - inExt[0] + 1; + int inExtY = inExt[3] - inExt[2] + 1; + int inExtZ = inExt[5] - inExt[4] + 1; + + for (int iidX = idXmin; iidX <= idXmax; iidX++) + { + void *inPtrTmp = background; + + inPoint[0] = inPoint1[0] + iidX*xAxis[0]; + inPoint[1] = inPoint1[1] + iidX*xAxis[1]; + inPoint[2] = inPoint1[2] + iidX*xAxis[2]; + + int inIdX = vtkResliceRound(inPoint[0]) - inExt[0]; + int inIdY = vtkResliceRound(inPoint[1]) - inExt[2]; + int inIdZ = vtkResliceRound(inPoint[2]) - inExt[4]; + + if (inIdX >= 0 && inIdX < inExtX && + inIdY >= 0 && inIdY < inExtY && + inIdZ >= 0 && inIdZ < inExtZ) + { + inPtrTmp = (void *)((char *)inPtr + \ + (inIdX*inInc[0] + + inIdY*inInc[1] + + inIdZ*inInc[2])*scalarSize); + } + + setpixels(outPtr, inPtrTmp, numscalars, 1); + } + } + } + outPtr = (void *)((char *)outPtr + outIncY*scalarSize); + } + outPtr = (void *)((char *)outPtr + outIncZ*scalarSize); + } + + vtkFreeBackgroundPixel(self, &background); +} + +//---------------------------------------------------------------------------- +// vtkReslicePermuteExecute is specifically optimized for +// cases where the IndexMatrix has only one non-zero component +// per row, i.e. when the matrix is permutation+scale+translation. +// All of the interpolation coefficients are calculated ahead +// of time instead of on a pixel-by-pixel basis. + +//---------------------------------------------------------------------------- +// helper function for nearest neighbor interpolation +template +void vtkPermuteNearestSummation(T *&outPtr, const T *inPtr, + int numscalars, int n, + const vtkIdType *iX, const F *, + const vtkIdType *iY, const F *, + const vtkIdType *iZ, const F *, + const int [3]) +{ + const T *inPtr0 = inPtr + iY[0] + iZ[0]; + + for (int i = 0; i < n; i++) + { + const T *tmpPtr = &inPtr0[iX[0]]; + iX++; + int m = numscalars; + do + { + *outPtr++ = *tmpPtr++; + } + while (--m); + } +} + +// ditto, but optimized for numscalars = 1 +template +void vtkPermuteNearestSummation1(T *&outPtr, const T *inPtr, + int, int n, + const vtkIdType *iX, const F *, + const vtkIdType *iY, const F *, + const vtkIdType *iZ, const F *, + const int [3]) +{ + const T *inPtr0 = inPtr + iY[0] + iZ[0]; + + for (int i = 0; i < n; i++) + { + *outPtr++ = inPtr0[iX[0]]; + iX++; + } +} + +//---------------------------------------------------------------------------- +// helper function for linear interpolation +template +void vtkPermuteTrilinearSummation(T *&outPtr, const T *inPtr, + int numscalars, int n, + const vtkIdType *iX, const F *fX, + const vtkIdType *iY, const F *fY, + const vtkIdType *iZ, const F *fZ, + const int useNearestNeighbor[3]) +{ + vtkIdType i00 = iY[0] + iZ[0]; + vtkIdType i01 = iY[0] + iZ[1]; + vtkIdType i10 = iY[1] + iZ[0]; + vtkIdType i11 = iY[1] + iZ[1]; + + F ry = fY[0]; + F fy = fY[1]; + F rz = fZ[0]; + F fz = fZ[1]; + + F ryrz = ry*rz; + F ryfz = ry*fz; + F fyrz = fy*rz; + F fyfz = fy*fz; + + if (useNearestNeighbor[0] && fy == 0 && fz == 0) + { // no interpolation needed at all + for (int i = 0; i < n; i++) + { + vtkIdType t0 = iX[0]; + iX += 2; + + const T *inPtr0 = inPtr + i00 + t0; + int m = numscalars; + do + { + *outPtr++ = *inPtr0++; + } + while (--m); + } + } + else if (useNearestNeighbor[0] && fy == 0) + { // only need linear z interpolation + for (int i = 0; i < n; i++) + { + vtkIdType t0 = iX[0]; + iX += 2; + + const T *inPtr0 = inPtr + t0; + int m = numscalars; + do + { + F result = (rz*inPtr0[i00] + fz*inPtr0[i01]); + vtkResliceRound(result, *outPtr++); + inPtr0++; + } + while (--m); + } + } + else if (fz == 0) + { // bilinear interpolation in x,y + for (int i = 0; i < n; i++) + { + F rx = fX[0]; + F fx = fX[1]; + fX += 2; + + vtkIdType t0 = iX[0]; + vtkIdType t1 = iX[1]; + iX += 2; + + const T *inPtr0 = inPtr + t0; + const T *inPtr1 = inPtr + t1; + int m = numscalars; + do + { + F result = (rx*(ry*inPtr0[i00] + fy*inPtr0[i10]) + + fx*(ry*inPtr1[i00] + fy*inPtr1[i10])); + + vtkResliceRound(result, *outPtr++); + inPtr0++; + inPtr1++; + } + while (--m); + } + } + else + { // do full trilinear interpolation + for (int i = 0; i < n; i++) + { + F rx = fX[0]; + F fx = fX[1]; + fX += 2; + + vtkIdType t0 = iX[0]; + vtkIdType t1 = iX[1]; + iX += 2; + + const T *inPtr0 = inPtr + t0; + const T *inPtr1 = inPtr + t1; + int m = numscalars; + do + { + F result = (rx*(ryrz*inPtr0[i00] + ryfz*inPtr0[i01] + + fyrz*inPtr0[i10] + fyfz*inPtr0[i11]) + + fx*(ryrz*inPtr1[i00] + ryfz*inPtr1[i01] + + fyrz*inPtr1[i10] + fyfz*inPtr1[i11])); + + vtkResliceRound(result, *outPtr++); + inPtr0++; + inPtr1++; + } + while (--m); + } + } +} + +//-------------------------------------------------------------------------- +// helper function for tricubic interpolation +template +void vtkPermuteTricubicSummation(T *&outPtr, const T *inPtr, + int numscalars, int n, + const vtkIdType *iX, const F *fX, + const vtkIdType *iY, const F *fY, + const vtkIdType *iZ, const F *fZ, + const int useNearestNeighbor[3]) +{ + // speed things up a bit for bicubic interpolation + int k1 = 0; + int k2 = 3; + if (useNearestNeighbor[2]) + { + k1 = k2 = 1; + } + + for (int i = 0; i < n; i++) + { + vtkIdType iX0 = iX[0]; + vtkIdType iX1 = iX[1]; + vtkIdType iX2 = iX[2]; + vtkIdType iX3 = iX[3]; + iX += 4; + + F fX0 = fX[0]; + F fX1 = fX[1]; + F fX2 = fX[2]; + F fX3 = fX[3]; + fX += 4; + + const T *inPtr0 = inPtr; + int c = numscalars; + do + { // loop over components + F result = 0; + + int k = k1; + do + { // loop over z + F fz = fZ[k]; + if (fz != 0) + { + vtkIdType iz = iZ[k]; + int j = 0; + do + { // loop over y + F fy = fY[j]; + F fzy = fz*fy; + vtkIdType izy = iz + iY[j]; + const T *tmpPtr = inPtr0 + izy; + // loop over x is unrolled (significant performance boost) + result += fzy*(fX0*tmpPtr[iX0] + + fX1*tmpPtr[iX1] + + fX2*tmpPtr[iX2] + + fX3*tmpPtr[iX3]); + } + while (++j <= 3); + } + } + while (++k <= k2); + + vtkResliceClamp(result, *outPtr++); + inPtr0++; + } + while (--c); + } +} + +//---------------------------------------------------------------------------- +// get approprate summation function for different interpolation modes +// and different scalar types +template +void vtkGetResliceSummationFunc(vtkImageReslice *self, + void (**summation)(void *&out, const void *in, + int numscalars, int n, + const vtkIdType *iX, const F *fX, + const vtkIdType *iY, const F *fY, + const vtkIdType *iZ, const F *fZ, + const int useNearest[3]), + int interpolationMode) +{ + int scalarType = self->GetOutput()->GetScalarType(); + + switch (interpolationMode) + { + case VTK_RESLICE_NEAREST: + switch (scalarType) + { + vtkTemplateAliasMacro(*((void (**)(VTK_TT *&out, const VTK_TT *in, + int numscalars, int n, + const vtkIdType *iX, const F *fX, + const vtkIdType *iY, const F *fY, + const vtkIdType *iZ, const F *fZ, + const int useNearest[3]))summation) = \ + vtkPermuteNearestSummation); + default: + summation = 0; + } + break; + case VTK_RESLICE_LINEAR: + switch (scalarType) + { + vtkTemplateAliasMacro(*((void (**)(VTK_TT *&out, const VTK_TT *in, + int numscalars, int n, + const vtkIdType *iX, const F *fX, + const vtkIdType *iY, const F *fY, + const vtkIdType *iZ, const F *fZ, + const int useNearest[3]))summation) = \ + vtkPermuteTrilinearSummation); + default: + summation = 0; + } + break; + case VTK_RESLICE_CUBIC: + switch (scalarType) + { + vtkTemplateAliasMacro(*((void (**)(VTK_TT *&out, const VTK_TT *in, + int numscalars, int n, + const vtkIdType *iX, const F *fX, + const vtkIdType *iY, const F *fY, + const vtkIdType *iZ, const F *fZ, + const int useNearest[3]))summation) = \ + vtkPermuteTricubicSummation); + default: + summation = 0; + } + break; + default: + summation = 0; + } +} + +//---------------------------------------------------------------------------- +template +void vtkPermuteNearestTable(vtkImageReslice *self, const int outExt[6], + const int inExt[6], const vtkIdType inInc[3], + int clipExt[6], vtkIdType **traversal, + F **vtkNotUsed(constants), + int useNearestNeighbor[3], F newmat[4][4]) +{ + // set up input traversal table for nearest-neighbor interpolation + for (int j = 0; j < 3; j++) + { + int k; + for (k = 0; k < 3; k++) + { // set k to the element which is nonzero + if (newmat[k][j] != 0) + { + break; + } + } + + // this is just for symmetry with Linear and Cubic + useNearestNeighbor[j] = 1; + + int inExtK = inExt[2*k+1] - inExt[2*k] + 1; + + int region = 0; + for (int i = outExt[2*j]; i <= outExt[2*j+1]; i++) + { + int inId = vtkResliceRound((newmat[k][3] + i*newmat[k][j])); + inId -= inExt[2*k]; + if (self->GetMirror()) + { + inId = vtkInterpolateMirror(inId, inExtK); + region = 1; + } + else if (self->GetWrap()) + { + inId = vtkInterpolateWrap(inId, inExtK); + region = 1; + } + else + { + if (inId < 0 || inId >= inExtK) + { + if (region == 1) + { // leaving the input extent + region = 2; + clipExt[2*j+1] = i - 1; + } + } + else + { + if (region == 0) + { // entering the input extent + region = 1; + clipExt[2*j] = i; + } + } + } + traversal[j][i] = inId*inInc[k]; + } + if (region == 0) + { // never entered input extent! + clipExt[2*j] = clipExt[2*j+1] + 1; + } + } +} + +//---------------------------------------------------------------------------- +template +void vtkPermuteLinearTable(vtkImageReslice *self, const int outExt[6], + const int inExt[6], const vtkIdType inInc[3], + int clipExt[6], vtkIdType **traversal, + F **constants, + int useNearestNeighbor[3], F newmat[4][4]) +{ + // set up input traversal table for linear interpolation + for (int j = 0; j < 3; j++) + { + int k; + for (k = 0; k < 3; k++) + { // set k to the element which is nonzero + if (newmat[k][j] != 0) + { + break; + } + } + + // do the output pixels lie exactly on top of the input pixels? + F f1, f2; + vtkResliceFloor(newmat[k][j], f1); + vtkResliceFloor(newmat[k][3], f2); + useNearestNeighbor[j] = (f1 == 0 && f2 == 0); + + int inExtK = inExt[2*k+1] - inExt[2*k] + 1; + + int region = 0; + for (int i = outExt[2*j]; i <= outExt[2*j+1]; i++) + { + F point = newmat[k][3] + i*newmat[k][j]; + F f; + int trunc = vtkResliceFloor(point, f); + constants[j][2*i] = 1 - f; + constants[j][2*i+1] = f; + + int fIsNotZero = (f != 0); + int inId0 = trunc - inExt[2*k]; + int inId1 = inId0 + fIsNotZero; + + if (self->GetMirror()) + { + inId0 = vtkInterpolateMirror(inId0, inExtK); + inId1 = vtkInterpolateMirror(inId1, inExtK); + region = 1; + } + else if (self->GetWrap()) + { + inId0 = vtkInterpolateWrap(inId0, inExtK); + inId1 = vtkInterpolateWrap(inId1, inExtK); + region = 1; + } + else if (self->GetBorder()) + { + if (vtkInterpolateBorder(inId0, inId1, inExtK, f)) + { + if (region == 1) + { // leaving the input extent + region = 2; + clipExt[2*j+1] = i - 1; + } + } + else + { + if (region == 0) + { // entering the input extent + region = 1; + clipExt[2*j] = i; + } + } + } + else // not self->GetBorder() + { + if (inId0 < 0 || inId1 >= inExtK) + { + if (region == 1) + { // leaving the input extent + region = 2; + clipExt[2*j+1] = i - 1; + } + } + else + { + if (region == 0) + { // entering the input extent + region = 1; + clipExt[2*j] = i; + } + } + } + traversal[j][2*i] = inId0*inInc[k]; + traversal[j][2*i+1] = inId1*inInc[k]; + } + if (region == 0) + { // never entered input extent! + clipExt[2*j] = clipExt[2*j+1] + 1; + } + } +} + +//---------------------------------------------------------------------------- +template +void vtkPermuteCubicTable(vtkImageReslice *self, const int outExt[6], + const int inExt[6], const vtkIdType inInc[3], + int clipExt[6], vtkIdType **traversal, + F **constants, + int useNearestNeighbor[3], F newmat[4][4]) +{ + // set up input traversal table for cubic interpolation + for (int j = 0; j < 3; j++) + { + int k; + for (k = 0; k < 3; k++) + { // set k to the element which is nonzero + if (newmat[k][j] != 0) + { + break; + } + } + + // do the output pixels lie exactly on top of the input pixels? + F f1, f2; + vtkResliceFloor(newmat[k][j], f1); + vtkResliceFloor(newmat[k][3], f2); + useNearestNeighbor[j] = (f1 == 0 && f2 == 0); + + int inExtK = inExt[2*k+1] - inExt[2*k] + 1; + + int region = 0; + for (int i = outExt[2*j]; i <= outExt[2*j+1]; i++) + { + F point = newmat[k][3] + i*newmat[k][j]; + F f; + int trunc = vtkResliceFloor(point, f); + int fIsNotZero = (f != 0); + int inId[4]; + inId[1] = trunc - inExt[2*k]; + inId[0] = inId[1] - 1; + inId[2] = inId[1] + 1; + inId[3] = inId[1] + 2; + + int low = 1 - fIsNotZero; + int high = 1 + 2*fIsNotZero; + if (self->GetMirror()) + { + inId[0] = vtkInterpolateMirror(inId[0], inExtK); + inId[1] = vtkInterpolateMirror(inId[1], inExtK); + inId[2] = vtkInterpolateMirror(inId[2], inExtK); + inId[3] = vtkInterpolateMirror(inId[3], inExtK); + region = 1; + } + else if (self->GetWrap()) + { + inId[0] = vtkInterpolateWrap(inId[0], inExtK); + inId[1] = vtkInterpolateWrap(inId[1], inExtK); + inId[2] = vtkInterpolateWrap(inId[2], inExtK); + inId[3] = vtkInterpolateWrap(inId[3], inExtK); + region = 1; + } + else if (self->GetBorder()) + { + if (vtkInterpolateBorderCheck(inId[1], inId[2], inExtK, f)) + { + if (region == 1) + { // leaving the input extent + region = 2; + clipExt[2*j+1] = i - 1; + } + } + else + { + if (region == 0) + { // entering the input extent + region = 1; + clipExt[2*j] = i; + } + } + int tmpExt = inExtK - 1; + inId[0] = (inId[0])*(inId[0] >= 0); + inId[1] = (inId[1])*(inId[1] >= 0); + inId[2] = tmpExt - (tmpExt - inId[2])*(tmpExt - inId[2] >= 0); + inId[3] = tmpExt - (tmpExt - inId[3])*(tmpExt - inId[3] >= 0); + low = 1 - fIsNotZero; + high = 1 + 2*fIsNotZero; + } + else // not self->GetBorder() + { + if (inId[1] < 0 || inId[1] + fIsNotZero >= inExtK) + { + if (region == 1) + { // leaving the input extent + region = 2; + clipExt[2*j+1] = i - 1; + } + } + else + { + if (region == 0) + { // entering the input extent + region = 1; + clipExt[2*j] = i; + } + } + low = 1 - (inId[0] >= 0)*fIsNotZero; + high = 1 + (1 + (inId[3] < inExtK))*fIsNotZero; + } + vtkTricubicInterpCoeffs(&constants[j][4*i], low, high, f); + + // set default values + int l; + for (l = 0; l < 4; l++) + { + traversal[j][4*i+l] = inId[1]*inInc[k]; + } + for (l = low; l <= high; l++) + { + traversal[j][4*i+l] = inId[l]*inInc[k]; + } + } + if (region == 0) + { // never entered input extent! + clipExt[2*j] = clipExt[2*j+1] + 1; + } + } +} + +//---------------------------------------------------------------------------- +// Check to see if we can do nearest-neighbor instead of linear or cubic. +// This check only works on permutation+scale+translation matrices. +template +inline int vtkCanUseNearestNeighbor(F matrix[4][4], int outExt[6]) +{ + // loop through dimensions + for (int i = 0; i < 3; i++) + { + int j; + for (j = 0; j < 3; j++) + { + if (matrix[i][j] != 0) + { + break; + } + } + F x = matrix[i][j]; + F y = matrix[i][3]; + if (outExt[2*j] == outExt[2*j+1]) + { + y += x*outExt[2*i]; + x = 0; + } + F fx, fy; + vtkResliceFloor(x, fx); + vtkResliceFloor(y, fy); + if (fx != 0 || fy != 0) + { + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +// the ReslicePermuteExecute path is taken when the output slices are +// orthogonal to the input slices +template +void vtkReslicePermuteExecute(vtkImageReslice *self, + vtkImageData *inData, void *inPtr, + vtkImageData *outData, void *outPtr, + int outExt[6], int id, F newmat[4][4]) +{ + vtkIdType outInc[3]; + int scalarSize, numscalars; + vtkIdType inInc[3]; + int inExt[6], clipExt[6]; + vtkIdType *traversal[3]; + F *constants[3]; + int useNearestNeighbor[3]; + int i; + + // find maximum input range + inData->GetExtent(inExt); + + // Get Increments to march through data + inData->GetIncrements(inInc); + outData->GetContinuousIncrements(outExt, outInc[0], outInc[1], outInc[2]); + scalarSize = outData->GetScalarSize(); + numscalars = inData->GetNumberOfScalarComponents(); + + for (i = 0; i < 3; i++) + { + clipExt[2*i] = outExt[2*i]; + clipExt[2*i+1] = outExt[2*i+1]; + } + + int interpolationMode = self->GetInterpolationMode(); + if (vtkCanUseNearestNeighbor(newmat, outExt)) + { + interpolationMode = VTK_RESLICE_NEAREST; + } + + // the step size is the number of coefficients per dimension + int step = 1; + switch (interpolationMode) + { + case VTK_RESLICE_NEAREST: + step = 1; + break; + case VTK_RESLICE_LINEAR: + step = 2; + break; + case VTK_RESLICE_CUBIC: + step = 4; + break; + } + + // allocate the interpolation tables + for (i = 0; i < 3; i++) + { + int outExtI = outExt[2*i+1] - outExt[2*i] + 1; + + traversal[i] = new vtkIdType[outExtI*step]; + traversal[i] -= step*outExt[2*i]; + constants[i] = new F[outExtI*step]; + constants[i] -= step*outExt[2*i]; + } + + // fill in the interpolation tables + switch (interpolationMode) + { + case VTK_RESLICE_NEAREST: + vtkPermuteNearestTable(self, outExt, inExt, inInc, clipExt, + traversal, constants, + useNearestNeighbor, newmat); + break; + case VTK_RESLICE_LINEAR: + vtkPermuteLinearTable(self, outExt, inExt, inInc, clipExt, + traversal, constants, + useNearestNeighbor, newmat); + break; + case VTK_RESLICE_CUBIC: + vtkPermuteCubicTable(self, outExt, inExt, inInc, clipExt, + traversal, constants, + useNearestNeighbor, newmat); + break; + } + + // get type-specific functions + void (*summation)(void *&out, const void *in, int numscalars, int n, + const vtkIdType *iX, const F *fX, + const vtkIdType *iY, const F *fY, + const vtkIdType *iZ, const F *fZ, + const int useNearestNeighbor[3]); + void (*setpixels)(void *&out, const void *in, int numscalars, int n); + vtkGetResliceSummationFunc(self, &summation, interpolationMode); + vtkGetSetPixelsFunc(self, &setpixels); + + // set color for area outside of input volume extent + void *background; + vtkAllocBackgroundPixel(self, &background, numscalars); + + // get the stencil + vtkImageStencilData *stencil = self->GetStencil(); + + // for tracking progress + unsigned long count = 0; + unsigned long target = (unsigned long) + ((outExt[5]-outExt[4]+1)*(outExt[3]-outExt[2]+1)/50.0); + target++; + + // Loop through output pixels + for (int idZ = outExt[4]; idZ <= outExt[5]; idZ++) + { + int idZ0 = idZ*step; + + for (int idY = outExt[2]; idY <= outExt[3]; idY++) + { + int idY0 = idY*step; + + if (id == 0) + { // track progress if we are main thread + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + // do extent check + if (idZ < clipExt[4] || idZ > clipExt[5] || + idY < clipExt[2] || idY > clipExt[3]) + { // just clear, we're completely outside + setpixels(outPtr, background, numscalars, outExt[1] - outExt[0] + 1); + } + else + { + // clear pixels to left of input extent + setpixels(outPtr, background, numscalars, clipExt[0] - outExt[0]); + + int iter = 0; + int idXmin, idXmax; + while (vtkResliceGetNextExtent(stencil, idXmin, idXmax, + clipExt[0], clipExt[1], idY, idZ, + outPtr, background, numscalars, + setpixels, iter)) + { + int idX0 = idXmin*step; + + summation(outPtr, inPtr, numscalars, idXmax - idXmin + 1, + &traversal[0][idX0], &constants[0][idX0], + &traversal[1][idY0], &constants[1][idY0], + &traversal[2][idZ0], &constants[2][idZ0], + useNearestNeighbor); + } + + // clear pixels to right of input extent + setpixels(outPtr, background, numscalars, outExt[1] - clipExt[1]); + } + + outPtr = (void *)((char *)outPtr + outInc[1]*scalarSize); + } + outPtr = (void *)((char *)outPtr + outInc[2]*scalarSize); + } + + vtkFreeBackgroundPixel(self, &background); + + for (i = 0; i < 3; i++) + { + traversal[i] += step*outExt[2*i]; + constants[i] += step*outExt[2*i]; + delete [] traversal[i]; + delete [] constants[i]; + } +} + +//---------------------------------------------------------------------------- +// check a matrix to ensure that it is a permutation+scale+translation +// matrix + +template +int vtkIsPermutationMatrix(F matrix[4][4]) +{ + for (int i = 0; i < 3; i++) + { + if (matrix[3][i] != 0) + { + return 0; + } + } + if (matrix[3][3] != 1) + { + return 0; + } + for (int j = 0; j < 3; j++) + { + int k = 0; + for (int i = 0; i < 3; i++) + { + if (matrix[i][j] != 0) + { + k++; + } + } + if (k != 1) + { + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------------- +// check a matrix to see whether it is the identity matrix + +int vtkIsIdentityMatrix(vtkMatrix4x4 *matrix) +{ + static double identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; + int i,j; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + if (matrix->GetElement(i,j) != identity[4*i+j]) + { + return 0; + } + } + } + return 1; +} + +//---------------------------------------------------------------------------- +// The transform matrix supplied by the user converts output coordinates +// to input coordinates. +// To speed up the pixel lookup, the following function provides a +// matrix which converts output pixel indices to input pixel indices. +// +// This will also concatenate the ResliceAxes and the ResliceTransform +// if possible (if the ResliceTransform is a 4x4 matrix transform). +// If it does, this->OptimizedTransform will be set to NULL, otherwise +// this->OptimizedTransform will be equal to this->ResliceTransform. + +vtkMatrix4x4 *vtkImageReslice::GetIndexMatrix(vtkInformation *inInfo, + vtkInformation *outInfo) +{ + // first verify that we have to update the matrix + if (this->IndexMatrix == NULL) + { + this->IndexMatrix = vtkMatrix4x4::New(); + } + + int isIdentity = 0; + double inOrigin[3]; + double inSpacing[3]; + double outOrigin[3]; + double outSpacing[3]; + + inInfo->Get(vtkDataObject::SPACING(), inSpacing); + inInfo->Get(vtkDataObject::ORIGIN(), inOrigin); + outInfo->Get(vtkDataObject::SPACING(), outSpacing); + outInfo->Get(vtkDataObject::ORIGIN(), outOrigin); + + vtkTransform *transform = vtkTransform::New(); + vtkMatrix4x4 *inMatrix = vtkMatrix4x4::New(); + vtkMatrix4x4 *outMatrix = vtkMatrix4x4::New(); + + if (this->OptimizedTransform) + { + this->OptimizedTransform->Delete(); + } + this->OptimizedTransform = NULL; + + if (this->ResliceAxes) + { + transform->SetMatrix(this->GetResliceAxes()); + } + if (this->ResliceTransform) + { + if (this->ResliceTransform->IsA("vtkHomogeneousTransform")) + { + transform->PostMultiply(); + transform->Concatenate(((vtkHomogeneousTransform *) + this->ResliceTransform)->GetMatrix()); + } + else + { + this->ResliceTransform->Register(this); + this->OptimizedTransform = this->ResliceTransform; + } + } + + // check to see if we have an identity matrix + isIdentity = vtkIsIdentityMatrix(transform->GetMatrix()); + + // the outMatrix takes OutputData indices to OutputData coordinates, + // the inMatrix takes InputData coordinates to InputData indices + for (int i = 0; i < 3; i++) + { + if ((this->OptimizedTransform == NULL && + (inSpacing[i] != outSpacing[i] || inOrigin[i] != outOrigin[i])) || + (this->OptimizedTransform != NULL && + (inSpacing[i] != 1.0 || inOrigin[i] != 0.0))) + { + isIdentity = 0; + } + inMatrix->Element[i][i] = 1.0/inSpacing[i]; + inMatrix->Element[i][3] = -inOrigin[i]/inSpacing[i]; + outMatrix->Element[i][i] = outSpacing[i]; + outMatrix->Element[i][3] = outOrigin[i]; + } + outInfo->Get(vtkDataObject::ORIGIN(), outOrigin); + + if (!isIdentity) + { + transform->PreMultiply(); + transform->Concatenate(outMatrix); + if (this->OptimizedTransform == NULL) + { + transform->PostMultiply(); + transform->Concatenate(inMatrix); + } + } + + transform->GetMatrix(this->IndexMatrix); + + transform->Delete(); + inMatrix->Delete(); + outMatrix->Delete(); + + return this->IndexMatrix; +} + +//---------------------------------------------------------------------------- +// This method is passed a input and output region, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageReslice::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + + vtkDebugMacro(<< "Execute: inData = " << inData[0][0] + << ", outData = " << outData[0]); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + int inExt[6]; + inData[0][0]->GetExtent(inExt); + // check for empty input extent + if (inExt[1] < inExt[0] || + inExt[3] < inExt[2] || + inExt[5] < inExt[4]) + { + return; + } + + // Get the output pointer + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + if (this->HitInputExtent == 0) + { + vtkImageResliceClearExecute(this, inData[0][0], 0, outData[0], outPtr, + outExt, id); + return; + } + + // Now that we know that we need the input, get the input pointer + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + + if (this->Optimization) + { + // change transform matrix so that instead of taking + // input coords -> output coords it takes output indices -> input indices + vtkMatrix4x4 *matrix = this->IndexMatrix; + + // get the portion of the transformation that remains apart from + // the IndexMatrix + vtkAbstractTransform *newtrans = this->OptimizedTransform; + + double newmat[4][4]; + for (int i = 0; i < 4; i++) + { + newmat[i][0] = matrix->GetElement(i,0); + newmat[i][1] = matrix->GetElement(i,1); + newmat[i][2] = matrix->GetElement(i,2); + newmat[i][3] = matrix->GetElement(i,3); + } + + if (vtkIsPermutationMatrix(newmat) && newtrans == NULL) + { + vtkReslicePermuteExecute(this, inData[0][0], inPtr, outData[0], outPtr, + outExt, id, newmat); + } + else + { + vtkOptimizedExecute(this, inData[0][0], inPtr, outData[0], outPtr, + outExt, id, newmat, newtrans); + } + } + else + { + vtkImageResliceExecute(this, inData[0][0], inPtr, outData[0], outPtr, + outExt, id); + } +} + diff --git a/Imaging/vtkImageReslice.h b/Imaging/vtkImageReslice.h new file mode 100644 index 0000000..8d4f4d0 --- /dev/null +++ b/Imaging/vtkImageReslice.h @@ -0,0 +1,362 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageReslice.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageReslice - Reslices a volume along a new set of axes. +// .SECTION Description +// vtkImageReslice is the swiss-army-knife of image geometry filters: +// It can permute, rotate, flip, scale, resample, deform, and pad image +// data in any combination with reasonably high efficiency. Simple +// operations such as permutation, resampling and padding are done +// with similar efficiently to the specialized vtkImagePermute, +// vtkImageResample, and vtkImagePad filters. There are a number of +// tasks that vtkImageReslice is well suited for: +//

1) Application of simple rotations, scales, and translations to +// an image. It is often a good idea to use vtkImageChangeInformation +// to center the image first, so that scales and rotations occur around +// the center rather than around the lower-left corner of the image. +//

2) Resampling of one data set to match the voxel sampling of +// a second data set via the SetInformationInput() method, e.g. for +// the purpose of comparing two images or combining two images. +// A transformation, either linear or nonlinear, can be applied +// at the same time via the SetResliceTransform method if the two +// images are not in the same coordinate space. +//

3) Extraction of slices from an image volume. The most convenient +// way to do this is to use SetResliceAxesDirectionCosines() to +// specify the orientation of the slice. The direction cosines give +// the x, y, and z axes for the output volume. The method +// SetOutputDimensionality(2) is used to specify that want to output a +// slice rather than a volume. The SetResliceAxesOrigin() command is +// used to provide an (x,y,z) point that the slice will pass through. +// You can use both the ResliceAxes and the ResliceTransform at the +// same time, in order to extract slices from a volume that you have +// applied a transformation to. +// .SECTION Caveats +// This filter is very inefficient if the output X dimension is 1. +// .SECTION see also +// vtkAbstractTransform vtkMatrix4x4 + + +#ifndef __vtkImageReslice_h +#define __vtkImageReslice_h + + +#include "vtkThreadedImageAlgorithm.h" + +// interpolation mode constants +#define VTK_RESLICE_NEAREST 0 +#define VTK_RESLICE_LINEAR 1 +#define VTK_RESLICE_CUBIC 3 + +class vtkImageData; +class vtkAbstractTransform; +class vtkMatrix4x4; +class vtkImageStencilData; + +class VTK_IMAGING_EXPORT vtkImageReslice : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageReslice *New(); + vtkTypeRevisionMacro(vtkImageReslice, vtkThreadedImageAlgorithm); + + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method is used to set up the axes for the output voxels. + // The output Spacing, Origin, and Extent specify the locations + // of the voxels within the coordinate system defined by the axes. + // The ResliceAxes are used most often to permute the data, e.g. + // to extract ZY or XZ slices of a volume as 2D XY images. + //

The first column of the matrix specifies the x-axis + // vector (the fourth element must be set to zero), the second + // column specifies the y-axis, and the third column the + // z-axis. The fourth column is the origin of the + // axes (the fourth element must be set to one). + //

An alternative to SetResliceAxes() is to use + // SetResliceAxesDirectionCosines() to set the directions of the + // axes and SetResliceAxesOrigin() to set the origin of the axes. + virtual void SetResliceAxes(vtkMatrix4x4*); + vtkGetObjectMacro(ResliceAxes, vtkMatrix4x4); + + // Description: + // Specify the direction cosines for the ResliceAxes (i.e. the + // first three elements of each of the first three columns of + // the ResliceAxes matrix). This will modify the current + // ResliceAxes matrix, or create a new matrix if none exists. + void SetResliceAxesDirectionCosines(double x0, double x1, double x2, + double y0, double y1, double y2, + double z0, double z1, double z2); + void SetResliceAxesDirectionCosines(const double x[3], + const double y[3], + const double z[3]) { + this->SetResliceAxesDirectionCosines(x[0], x[1], x[2], + y[0], y[1], y[2], + z[0], z[1], z[2]); }; + void SetResliceAxesDirectionCosines(const double xyz[9]) { + this->SetResliceAxesDirectionCosines(xyz[0], xyz[1], xyz[2], + xyz[3], xyz[4], xyz[5], + xyz[6], xyz[7], xyz[8]); }; + void GetResliceAxesDirectionCosines(double x[3], double y[3], double z[3]); + void GetResliceAxesDirectionCosines(double xyz[9]) { + this->GetResliceAxesDirectionCosines(&xyz[0], &xyz[3], &xyz[6]); }; + double *GetResliceAxesDirectionCosines() { + this->GetResliceAxesDirectionCosines(this->ResliceAxesDirectionCosines); + return this->ResliceAxesDirectionCosines; }; + + // Description: + // Specify the origin for the ResliceAxes (i.e. the first three + // elements of the final column of the ResliceAxes matrix). + // This will modify the current ResliceAxes matrix, or create + // new matrix if none exists. + void SetResliceAxesOrigin(double x, double y, double z); + void SetResliceAxesOrigin(const double xyz[3]) { + this->SetResliceAxesOrigin(xyz[0], xyz[1], xyz[2]); }; + void GetResliceAxesOrigin(double xyz[3]); + double *GetResliceAxesOrigin() { + this->GetResliceAxesOrigin(this->ResliceAxesOrigin); + return this->ResliceAxesOrigin; }; + + // Description: + // Set a transform to be applied to the resampling grid that has + // been defined via the ResliceAxes and the output Origin, Spacing + // and Extent. Note that applying a transform to the resampling + // grid (which lies in the output coordinate system) is + // equivalent to applying the inverse of that transform to + // the input volume. Nonlinear transforms such as vtkGridTransform + // and vtkThinPlateSplineTransform can be used here. + virtual void SetResliceTransform(vtkAbstractTransform*); + vtkGetObjectMacro(ResliceTransform, vtkAbstractTransform); + + // Description: + // Set a vtkImageData from which the default Spacing, Origin, + // and WholeExtent of the output will be copied. The spacing, + // origin, and extent will be permuted according to the + // ResliceAxes. Any values set via SetOutputSpacing, + // SetOutputOrigin, and SetOutputExtent will override these + // values. By default, the Spacing, Origin, and WholeExtent + // of the Input are used. + virtual void SetInformationInput(vtkImageData*); + vtkGetObjectMacro(InformationInput, vtkImageData); + + // Description: + // Specify whether to transform the spacing, origin and extent + // of the Input (or the InformationInput) according to the + // direction cosines and origin of the ResliceAxes before applying + // them as the default output spacing, origin and extent + // (default: On). + vtkSetMacro(TransformInputSampling, int); + vtkBooleanMacro(TransformInputSampling, int); + vtkGetMacro(TransformInputSampling, int); + + // Description: + // Turn this on if you want to guarantee that the extent of the + // output will be large enough to ensure that none of the + // data will be cropped (default: Off). + vtkSetMacro(AutoCropOutput, int); + vtkBooleanMacro(AutoCropOutput, int); + vtkGetMacro(AutoCropOutput, int); + + // Description: + // Turn on wrap-pad feature (default: Off). + vtkSetMacro(Wrap, int); + vtkGetMacro(Wrap, int); + vtkBooleanMacro(Wrap, int); + + // Description: + // Turn on mirror-pad feature (default: Off). + // This will override the wrap-pad. + vtkSetMacro(Mirror, int); + vtkGetMacro(Mirror, int); + vtkBooleanMacro(Mirror, int); + + // Description: + // Extend the apparent input border by a half voxel (default: On). + // This changes how interpolation is handled at the borders of the + // input image: if the center of an output voxel is beyond the edge + // of the input image, but is within a half voxel width of the edge + // (using the input voxel width), then the value of the output voxel + // is calculated as if the input's edge voxels were duplicated past + // the edges of the input. + // This has no effect if Mirror or Wrap are on. + vtkSetMacro(Border, int); + vtkGetMacro(Border, int); + vtkBooleanMacro(Border, int); + + // Description: + // Set interpolation mode (default: nearest neighbor). + vtkSetMacro(InterpolationMode, int); + vtkGetMacro(InterpolationMode, int); + void SetInterpolationModeToNearestNeighbor() { + this->SetInterpolationMode(VTK_RESLICE_NEAREST); }; + void SetInterpolationModeToLinear() { + this->SetInterpolationMode(VTK_RESLICE_LINEAR); }; + void SetInterpolationModeToCubic() { + this->SetInterpolationMode(VTK_RESLICE_CUBIC); }; + const char *GetInterpolationModeAsString(); + + // Description: + // Turn on and off optimizations (default on, they should only be + // turned off for testing purposes). + vtkSetMacro(Optimization, int); + vtkGetMacro(Optimization, int); + vtkBooleanMacro(Optimization, int); + + // Description: + // Set the background color (for multi-component images). + vtkSetVector4Macro(BackgroundColor, double); + vtkGetVector4Macro(BackgroundColor, double); + + // Description: + // Set background grey level (for single-component images). + void SetBackgroundLevel(double v) { this->SetBackgroundColor(v,v,v,v); }; + double GetBackgroundLevel() { return this->GetBackgroundColor()[0]; }; + + // Description: + // Set the voxel spacing for the output data. The default output + // spacing is the input spacing permuted through the ResliceAxes. + vtkSetVector3Macro(OutputSpacing, double); + vtkGetVector3Macro(OutputSpacing, double); + void SetOutputSpacingToDefault() { + this->SetOutputSpacing(VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX); }; + + // Description: + // Set the origin for the output data. The default output origin + // is the input origin permuted through the ResliceAxes. + vtkSetVector3Macro(OutputOrigin, double); + vtkGetVector3Macro(OutputOrigin, double); + void SetOutputOriginToDefault() { + this->SetOutputOrigin(VTK_DOUBLE_MAX, VTK_DOUBLE_MAX, VTK_DOUBLE_MAX); }; + + // Description: + // Set the extent for the output data. The default output extent + // is the input extent permuted through the ResliceAxes. + vtkSetVector6Macro(OutputExtent, int); + vtkGetVector6Macro(OutputExtent, int); + void SetOutputExtentToDefault() { + this->SetOutputExtent(VTK_INT_MIN, VTK_INT_MAX, + VTK_INT_MIN, VTK_INT_MAX, + VTK_INT_MIN, VTK_INT_MAX); }; + + // Description: + // Force the dimensionality of the output to either 1, 2, + // 3 or 0 (default: 3). If the dimensionality is 2D, then + // the Z extent of the output is forced to (0,0) and the Z + // origin of the output is forced to 0.0 (i.e. the output + // extent is confined to the xy plane). If the dimensionality + // is 1D, the output extent is confined to the x axis. + // For 0D, the output extent consists of a single voxel at + // (0,0,0). + vtkSetMacro(OutputDimensionality, int); + vtkGetMacro(OutputDimensionality, int); + + // Description: + // When determining the modified time of the filter, + // this check the modified time of the transform and matrix. + unsigned long int GetMTime(); + + // Description: + // Convenient methods for switching between nearest-neighbor and linear + // interpolation. + // InterpolateOn() is equivalent to SetInterpolationModeToLinear() and + // InterpolateOff() is equivalent to SetInterpolationModeToNearestNeighbor(). + // You should not use these methods if you use the SetInterpolationMode + // methods. + void SetInterpolate(int t) { + if (t && !this->GetInterpolate()) { + this->SetInterpolationModeToLinear(); } + else if (!t && this->GetInterpolate()) { + this->SetInterpolationModeToNearestNeighbor(); } }; + void InterpolateOn() { + this->SetInterpolate(1); }; + void InterpolateOff() { + this->SetInterpolate(0); }; + int GetInterpolate() { + return (this->GetInterpolationMode() != VTK_RESLICE_NEAREST); }; + + // Description: + // Use a stencil to limit the calculations to a specific region of + // the output. Portions of the output that are 'outside' the stencil + // will be cleared to the background color. + void SetStencil(vtkImageStencilData *stencil); + vtkImageStencilData *GetStencil(); + +protected: + vtkImageReslice(); + ~vtkImageReslice(); + + vtkMatrix4x4 *ResliceAxes; + double ResliceAxesDirectionCosines[9]; + double ResliceAxesOrigin[3]; + vtkAbstractTransform *ResliceTransform; + vtkImageData *InformationInput; + int Wrap; + int Mirror; + int Border; + int InterpolationMode; + int Optimization; + double BackgroundColor[4]; + double OutputOrigin[3]; + double OutputSpacing[3]; + int OutputExtent[6]; + int OutputDimensionality; + int TransformInputSampling; + int AutoCropOutput; + int HitInputExtent; + + vtkMatrix4x4 *IndexMatrix; + vtkAbstractTransform *OptimizedTransform; + + void GetAutoCroppedOutputBounds(vtkInformation *inInfo, double bounds[6]); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, int ext[6], int id); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkMatrix4x4 *GetIndexMatrix(vtkInformation *inInfo, + vtkInformation *outInfo); + vtkAbstractTransform *GetOptimizedTransform() { + return this->OptimizedTransform; }; + +private: + vtkImageReslice(const vtkImageReslice&); // Not implemented. + void operator=(const vtkImageReslice&); // Not implemented. +}; + +//---------------------------------------------------------------------------- +inline const char *vtkImageReslice::GetInterpolationModeAsString() +{ + switch (this->InterpolationMode) + { + case VTK_RESLICE_NEAREST: + return "NearestNeighbor"; + case VTK_RESLICE_LINEAR: + return "Linear"; + case VTK_RESLICE_CUBIC: + return "Cubic"; + default: + return ""; + } +} + +#endif + + + + + diff --git a/Imaging/vtkImageSeedConnectivity.cxx b/Imaging/vtkImageSeedConnectivity.cxx new file mode 100644 index 0000000..95888d9 --- /dev/null +++ b/Imaging/vtkImageSeedConnectivity.cxx @@ -0,0 +1,304 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSeedConnectivity.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSeedConnectivity.h" + +#include "vtkImageConnector.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageSeedConnectivity, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkImageSeedConnectivity); + +//---------------------------------------------------------------------------- +vtkImageSeedConnectivity::vtkImageSeedConnectivity() +{ + this->InputConnectValue = 255; + this->OutputConnectedValue = 255; + this->OutputUnconnectedValue = 0; + this->Seeds = NULL; + this->Connector = vtkImageConnector::New(); + this->Dimensionality = 3; +} + +//---------------------------------------------------------------------------- +vtkImageSeedConnectivity::~vtkImageSeedConnectivity() +{ + this->Connector->Delete(); + this->RemoveAllSeeds(); +} + +//---------------------------------------------------------------------------- +void vtkImageSeedConnectivity::RemoveAllSeeds() +{ + vtkImageConnectorSeed *temp; + while (this->Seeds) + { + temp = this->Seeds; + this->Seeds = temp->Next; + delete temp; + } +} + +//---------------------------------------------------------------------------- +void vtkImageSeedConnectivity::AddSeed(int num, int *index) +{ + int idx, newIndex[3]; + vtkImageConnectorSeed *seed; + + if (num > 3) + { + num = 3; + } + for (idx = 0; idx < num; ++idx) + { + newIndex[idx] = index[idx]; + } + for (idx = num; idx < 3; ++idx) + { + newIndex[idx] = 0; + } + seed = this->Connector->NewSeed(newIndex, NULL); + seed->Next = this->Seeds; + this->Seeds = seed; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageSeedConnectivity::AddSeed(int i0, int i1, int i2) +{ + int index[3]; + + index[0] = i0; + index[1] = i1; + index[2] = i2; + this->AddSeed(3, index); +} + +//---------------------------------------------------------------------------- +void vtkImageSeedConnectivity::AddSeed(int i0, int i1) +{ + int index[2]; + + index[0] = i0; + index[1] = i1; + this->AddSeed(2, index); +} + +//---------------------------------------------------------------------------- +int vtkImageSeedConnectivity::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()), + 6); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageSeedConnectivity::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkImageConnectorSeed *seed; + int idx0, idx1, idx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + int min0, max0, min1, max1, min2, max2; + unsigned char *inPtr0, *inPtr1, *inPtr2; + unsigned char *outPtr0, *outPtr1, *outPtr2; + unsigned char temp1, temp2; + int temp; + + outData->SetExtent( + outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())); + outData->AllocateScalars(); + + if (inData->GetScalarType() != VTK_UNSIGNED_CHAR || + outData->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro("Execute: Both input and output must have scalar type UnsignedChar"); + return 1; + } + + // Pick an intermediate value (In some cases, we could eliminate the last threshold.) + temp1 = 1; + while (temp1 == this->InputConnectValue || + temp1 == this->OutputUnconnectedValue || + temp1 == this->OutputConnectedValue) + { + ++temp1; + } + temp2 = temp1 + 1; + while (temp2 == this->InputConnectValue || + temp2 == this->OutputUnconnectedValue || + temp2 == this->OutputConnectedValue) + { + ++temp2; + } + + //------- + // threshold to eliminate unknown values ( only intermediate and 0) + inData->GetIncrements(inInc0, inInc1, inInc2); + this->GetOutput()->GetExtent(min0, max0, min1, max1, min2, max2); + outData->GetIncrements(outInc0, outInc1, outInc2); + inPtr2 = (unsigned char *)(inData->GetScalarPointer(min0,min1,min2)); + outPtr2 = (unsigned char *)(outData->GetScalarPointer(min0,min1,min2)); + for (idx2 = min2; idx2 <= max2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = min1; idx1 <= max1; ++idx1) + { + inPtr0 = inPtr1; + outPtr0 = outPtr1; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + if (*inPtr0 == this->InputConnectValue) + { + *outPtr0 = temp1; + } + else + { + *outPtr0 = 0; + } + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + + this->UpdateProgress(0.2); + if (this->AbortExecute) + { + return 1; + } + + //------- + // find actual seeds in this image. (only scan along the first axis for now) + this->Connector->RemoveAllSeeds(); + seed = this->Seeds; + while (seed) + { + temp = seed->Index[0]; + // make sure z value of seed is acceptable + if (seed->Index[2] < min2) + { + seed->Index[2] = min2; + } + if (seed->Index[2] > max2) + { + seed->Index[2] = max2; + } + outPtr0 = (unsigned char *)(outData->GetScalarPointer(seed->Index)); + for (idx0 = temp; idx0 <= max0; ++idx0) + { + if (*outPtr0 == temp1) + { // we found our seed + seed->Index[0] = idx0; + this->Connector->AddSeed(this->Connector->NewSeed(seed->Index, outPtr0)); + seed->Index[0] = temp; + break; + } + outPtr0 += outInc0; + } + seed = seed->Next; + } + + this->UpdateProgress(0.5); + if (this->AbortExecute) + { + return 1; + } + + //------- + // connect + this->Connector->SetUnconnectedValue(temp1); + this->Connector->SetConnectedValue(temp2); + this->Connector->MarkData(outData, this->Dimensionality, + this->GetOutput()->GetExtent()); + + this->UpdateProgress(0.9); + if (this->AbortExecute) + { + return 1; + } + + //------- + // Threshold to convert intermediate values into OutputUnconnectedValues + outPtr2 = (unsigned char *)(outData->GetScalarPointer(min0,min1,min2)); + for (idx2 = min2; idx2 <= max2; ++idx2) + { + outPtr1 = outPtr2; + for (idx1 = min1; idx1 <= max1; ++idx1) + { + outPtr0 = outPtr1; + for (idx0 = min0; idx0 <= max0; ++idx0) + { + if (*outPtr0 == temp2) + { + *outPtr0 = this->OutputConnectedValue; + } + else + { + *outPtr0 = this->OutputUnconnectedValue; + } + outPtr0 += outInc0; + } + outPtr1 += outInc1; + } + outPtr2 += outInc2; + } + + return 1; +} + +void vtkImageSeedConnectivity::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Connector ) + { + os << indent << "Connector: " << this->Connector << "\n"; + } + else + { + os << indent << "Connector: (none)\n"; + } + + os << indent << "Dimensionality: " << this->Dimensionality << "\n"; + os << indent << "InputConnectValue: " << this->InputConnectValue << "\n"; + os << indent << "OutputConnectedValue: " << this->OutputConnectedValue << "\n"; + os << indent << "OutputUnconnectedValue: " << this->OutputUnconnectedValue << "\n"; +} diff --git a/Imaging/vtkImageSeedConnectivity.h b/Imaging/vtkImageSeedConnectivity.h new file mode 100644 index 0000000..d7b985d --- /dev/null +++ b/Imaging/vtkImageSeedConnectivity.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSeedConnectivity.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSeedConnectivity - SeedConnectivity with user defined seeds. +// .SECTION Description +// vtkImageSeedConnectivity marks pixels connected to user supplied seeds. +// The input must be unsigned char, and the output is also unsigned char. If +// a seed supplied by the user does not have pixel value "InputTrueValue", +// then the image is scanned +x, +y, +z until a pixel is encountered with +// value "InputTrueValue". This new pixel is used as the seed . Any pixel +// with out value "InputTrueValue" is consider off. The output pixels values +// are 0 for any off pixel in input, "OutputTrueValue" for any pixels +// connected to seeds, and "OutputUnconnectedValue" for any on pixels not +// connected to seeds. The same seeds are used for all images in the image +// set. + +#ifndef __vtkImageSeedConnectivity_h +#define __vtkImageSeedConnectivity_h + +#include "vtkImageAlgorithm.h" + +class vtkImageConnector; +class vtkImageConnectorSeed; + +class VTK_IMAGING_EXPORT vtkImageSeedConnectivity : public vtkImageAlgorithm +{ +public: + static vtkImageSeedConnectivity *New(); + vtkTypeRevisionMacro(vtkImageSeedConnectivity,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods for manipulating the seed pixels. + void RemoveAllSeeds(); + void AddSeed(int num, int *index); + void AddSeed(int i0, int i1, int i2); + void AddSeed(int i0, int i1); + + // Description: + // Set/Get what value is considered as connecting pixels. + vtkSetMacro(InputConnectValue, int); + vtkGetMacro(InputConnectValue, int); + + // Description: + // Set/Get the value to set connected pixels to. + vtkSetMacro(OutputConnectedValue, int); + vtkGetMacro(OutputConnectedValue, int); + + // Description: + // Set/Get the value to set unconnected pixels to. + vtkSetMacro(OutputUnconnectedValue, int); + vtkGetMacro(OutputUnconnectedValue, int); + + // Description: + // Get the vtkImageCOnnector used by this filter. + vtkGetObjectMacro(Connector,vtkImageConnector); + + // Description: + // Set the number of axes to use in connectivity. + vtkSetMacro(Dimensionality,int); + vtkGetMacro(Dimensionality,int); + +protected: + vtkImageSeedConnectivity(); + ~vtkImageSeedConnectivity(); + + unsigned char InputConnectValue; + unsigned char OutputConnectedValue; + unsigned char OutputUnconnectedValue; + vtkImageConnectorSeed *Seeds; + vtkImageConnector *Connector; + int Dimensionality; + + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkImageSeedConnectivity(const vtkImageSeedConnectivity&); // Not implemented. + void operator=(const vtkImageSeedConnectivity&); // Not implemented. +}; + + + +#endif + + + diff --git a/Imaging/vtkImageSeparableConvolution.cxx b/Imaging/vtkImageSeparableConvolution.cxx new file mode 100644 index 0000000..c66d5f5 --- /dev/null +++ b/Imaging/vtkImageSeparableConvolution.cxx @@ -0,0 +1,423 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSeparableConvolution.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSeparableConvolution.h" + +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageSeparableConvolution, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkImageSeparableConvolution); +vtkCxxSetObjectMacro(vtkImageSeparableConvolution,XKernel,vtkFloatArray); +vtkCxxSetObjectMacro(vtkImageSeparableConvolution,YKernel,vtkFloatArray); +vtkCxxSetObjectMacro(vtkImageSeparableConvolution,ZKernel,vtkFloatArray); + + +// Actually do the convolution +void ExecuteConvolve ( float* kernel, int kernelSize, float* image, float* outImage, int imageSize ) +{ + + // Consider the kernel to be centered at (int) ( (kernelSize - 1 ) / 2.0 ) + + int center = (int) ( (kernelSize - 1 ) / 2.0 ); + int i, j, k, kStart, iStart, iEnd, count; + + for ( i = 0; i < imageSize; ++i ) + { + outImage[i] = 0.0; + +// iStart = i - center; +// if ( iStart < 0 ) +// { +// iStart = 0; +// } + +// iEnd = i + center; +// if ( iEnd > imageSize - 1 ) +// { +// iEnd = imageSize - 1; +// } + + // Handle padding + iStart = i - center; + k = kernelSize - 1; + while ( iStart < 0 ) + { + outImage[i] += image[0] * kernel[k]; + ++iStart; + --k; + } + + iEnd = i + center; + k = 0; + while ( iEnd > imageSize - 1 ) + { + outImage[i] += image[imageSize - 1] * kernel[k]; + ++k; + --iEnd; + } + + + kStart = center + i; + if ( kStart > kernelSize - 1 ) + { + kStart = kernelSize - 1; + } + count = iEnd - iStart + 1; + for ( j = 0; j < count; ++j ) + { + outImage[i] += image[j+iStart] * kernel[kStart-j]; + } + } +} + +// Description: +// Overload standard modified time function. If kernel arrays are modified, +// then this object is modified as well. +unsigned long vtkImageSeparableConvolution::GetMTime() +{ + unsigned long mTime=this->vtkImageDecomposeFilter::GetMTime(); + unsigned long kTime; + + if ( this->XKernel ) + { + kTime = this->XKernel->GetMTime(); + mTime = kTime > mTime ? kTime : mTime; + } + if ( this->YKernel ) + { + kTime = this->YKernel->GetMTime(); + mTime = kTime > mTime ? kTime : mTime; + } + if ( this->YKernel ) + { + kTime = this->YKernel->GetMTime(); + mTime = kTime > mTime ? kTime : mTime; + } + return mTime; +} + + +//---------------------------------------------------------------------------- +vtkImageSeparableConvolution::~vtkImageSeparableConvolution() +{ + SetXKernel ( NULL ); + SetYKernel ( NULL ); + SetZKernel ( NULL ); +} + +//---------------------------------------------------------------------------- +vtkImageSeparableConvolution::vtkImageSeparableConvolution() +{ + XKernel = YKernel = ZKernel = NULL; +} + +//---------------------------------------------------------------------------- +// This extent of the components changes to real and imaginary values. +int vtkImageSeparableConvolution::IterativeRequestInformation( + vtkInformation* vtkNotUsed(input), vtkInformation* output) +{ + vtkDataObject::SetPointDataActiveScalarInfo(output, VTK_FLOAT, 1); + return 1; +} + +//---------------------------------------------------------------------------- +// This method tells the superclass that the whole input array is needed +// to compute any output region. + +int vtkImageSeparableConvolution::IterativeRequestUpdateExtent( + vtkInformation* input, vtkInformation* output) +{ + int *wholeExtent = + input->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + vtkFloatArray* KernelArray = NULL; + switch ( this->GetIteration() ) + { + case 0: + KernelArray = this->GetXKernel(); + break; + case 1: + KernelArray = this->GetYKernel(); + break; + case 2: + KernelArray = this->GetZKernel(); + break; + } + int kernelSize = 0; + if ( KernelArray ) + { + kernelSize = KernelArray->GetNumberOfTuples(); + kernelSize = (int) ( ( kernelSize - 1 ) / 2.0 ); + } + + int* outExt = output->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + + // Assumes that the input update extent has been initialized to output ... + int inExt[6]; + memcpy(inExt, outExt, 6 * sizeof(int)); + inExt[this->Iteration * 2] = outExt[this->Iteration * 2] - kernelSize; + if ( inExt[this->Iteration * 2] < wholeExtent[this->Iteration * 2] ) + { + inExt[this->Iteration * 2] = wholeExtent[this->Iteration * 2]; + } + + inExt[this->Iteration * 2 + 1] = + outExt[this->Iteration * 2 + 1] + kernelSize; + if ( inExt[this->Iteration * 2 + 1] > wholeExtent[this->Iteration * 2 + 1] ) + { + inExt[this->Iteration * 2 + 1] = wholeExtent[this->Iteration * 2 + 1]; + } + + input->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt,6); + + return 1; +} + +template +void vtkImageSeparableConvolutionExecute ( vtkImageSeparableConvolution* self, + vtkImageData* inData, + vtkImageData* outData, + T* vtkNotUsed ( dummy ), + int* inExt, + int* outExt) +{ + T *inPtr0, *inPtr1, *inPtr2; + float *outPtr0, *outPtr1, *outPtr2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + int inMin0, inMax0, inMin1, inMax1, inMin2, inMax2; + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + int idx0, idx1, idx2; + int i; + unsigned long count = 0; + unsigned long target; + + // Reorder axes (the in and out extents are assumed to be the same) + // (see intercept cache update) + self->PermuteExtent(outExt, outMin0, outMax0, outMin1, outMax1, outMin2, outMax2); + self->PermuteExtent(inExt, inMin0, inMax0, inMin1, inMax1, inMin2, inMax2); + self->PermuteIncrements(inData->GetIncrements(), inInc0, inInc1, inInc2); + self->PermuteIncrements(outData->GetIncrements(), outInc0, outInc1, outInc2); + + target = (unsigned long)((inMax2-inMin2+1)*(inMax1-inMin1+1)/50.0); + target++; + + vtkFloatArray* KernelArray = NULL; + switch ( self->GetIteration() ) + { + case 0: + KernelArray = self->GetXKernel(); + break; + case 1: + KernelArray = self->GetYKernel(); + break; + case 2: + KernelArray = self->GetZKernel(); + break; + } + int kernelSize = 0; + float* kernel = NULL; + + if ( KernelArray ) + { + // Allocate the arrays + kernelSize = KernelArray->GetNumberOfTuples(); + kernel = new float[kernelSize]; + // Copy the kernel + for ( i = 0; i < kernelSize; i++ ) + { + kernel[i] = KernelArray->GetValue ( i ); + } + } + + int imageSize = inMax0 + 1; + float* image = new float[imageSize]; + float* outImage = new float[imageSize]; + float* imagePtr; + + + // loop over all the extra axes + inPtr2 = (T *)inData->GetScalarPointerForExtent(inExt); + outPtr2 = (float *)outData->GetScalarPointerForExtent(outExt); + for (idx2 = inMin2; idx2 <= inMax2; ++idx2) + { + inPtr1 = inPtr2; + outPtr1 = outPtr2; + for (idx1 = inMin1; !self->AbortExecute && idx1 <= inMax1; ++idx1) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + inPtr0 = inPtr1; + imagePtr = image; + for (idx0 = inMin0; idx0 <= inMax0; ++idx0) + { + *imagePtr = (float)(*inPtr0); + inPtr0 += inInc0; + ++imagePtr; + } + + // Call the method that performs the convolution + if ( kernel ) + { + ExecuteConvolve ( kernel, kernelSize, image, outImage, imageSize ); + imagePtr = outImage; + } + else + { + // If we don't have a kernel, just copy to the output + imagePtr = image; + } + + // Copy to output, be aware that we only copy to the extent that was asked for + outPtr0 = outPtr1; + imagePtr = imagePtr + (outMin0 - inMin0); + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + *outPtr0 = (*imagePtr); + outPtr0 += outInc0; + ++imagePtr; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + + delete [] image; + delete [] outImage; + if ( kernel ) + { + delete [] kernel; + } + +} + + + + +//---------------------------------------------------------------------------- +// This is writen as a 1D execute method, but is called several times. +int vtkImageSeparableConvolution::IterativeRequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + outData->SetExtent(outData->GetWholeExtent()); + outData->AllocateScalars(); + + if ( XKernel ) + { + // Check for a filter of odd length + if ( 1 - ( XKernel->GetNumberOfTuples() % 2 ) ) + { + vtkErrorMacro ( << "Execute: XKernel must have odd length" ); + return 1; + } + } + if ( YKernel ) + { + // Check for a filter of odd length + if ( 1 - ( YKernel->GetNumberOfTuples() % 2 ) ) + { + vtkErrorMacro ( << "Execute: YKernel must have odd length" ); + return 1; + } + } + if ( ZKernel ) + { + // Check for a filter of odd length + if ( 1 - ( ZKernel->GetNumberOfTuples() % 2 ) ) + { + vtkErrorMacro ( << "Execute: ZKernel must have odd length" ); + return 1; + } + } + + if (inData->GetNumberOfScalarComponents() != 1) + { + vtkErrorMacro(<< "ImageSeparableConvolution only works on 1 component input for the moment."); + return 1; + } + + // this filter expects that the output be floats. + if (outData->GetScalarType() != VTK_FLOAT) + { + vtkErrorMacro(<< "Execute: Output must be be type float."); + return 1; + } + + // choose which templated function to call. + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageSeparableConvolutionExecute( + this, inData, outData, static_cast(0), + inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 1; + } + + return 1; +} + +void vtkImageSeparableConvolution::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->XKernel ) + { + os << indent << "XKernel:\n"; + this->XKernel->PrintSelf ( os, indent.GetNextIndent() ); + } + else + { + os << indent << "XKernel: (not defined)\n"; + } + if ( this->YKernel ) + { + os << indent << "YKernel:\n"; + this->YKernel->PrintSelf ( os, indent.GetNextIndent() ); + } + else + { + os << indent << "YKernel: (not defined)\n"; + } + if ( this->ZKernel ) + { + os << indent << "ZKernel:\n"; + this->ZKernel->PrintSelf ( os, indent.GetNextIndent() ); + } + else + { + os << indent << "ZKernel: (not defined)\n"; + } +} diff --git a/Imaging/vtkImageSeparableConvolution.h b/Imaging/vtkImageSeparableConvolution.h new file mode 100644 index 0000000..90b74f6 --- /dev/null +++ b/Imaging/vtkImageSeparableConvolution.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSeparableConvolution.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSeparableConvolution - 3 1D convolutions on an image +// .SECTION Description +// vtkImageSeparableConvolution performs a convolution along the X, Y, +// and Z axes of an image, based on the three different 1D convolution +// kernels. The kernels must be of odd size, and are considered to be +// centered at (int)((kernelsize - 1) / 2.0 ). If a kernel is NULL, +// that dimension is skipped. This filter is designed to efficiently +// convolve separable filters that can be decomposed into 1 or more 1D +// convolutions. It also handles arbitrarly large kernel sizes, and +// uses edge replication to handle boundaries. + +#ifndef __vtkImageSeparableConvolution_h +#define __vtkImageSeparableConvolution_h + + +#include "vtkImageDecomposeFilter.h" + +class vtkFloatArray; + +class VTK_IMAGING_EXPORT vtkImageSeparableConvolution : public vtkImageDecomposeFilter +{ +public: + static vtkImageSeparableConvolution *New(); + vtkTypeRevisionMacro(vtkImageSeparableConvolution,vtkImageDecomposeFilter); + + + // Set the X convolution kernel, a null value indicates no convolution to + // be done. The kernel must be of odd length + virtual void SetXKernel(vtkFloatArray*); + vtkGetObjectMacro ( XKernel, vtkFloatArray ); + + // Set the Y convolution kernel, a null value indicates no convolution to + // be done The kernel must be of odd length + virtual void SetYKernel(vtkFloatArray*); + vtkGetObjectMacro ( YKernel, vtkFloatArray ); + + // Set the Z convolution kernel, a null value indicates no convolution to + // be done The kernel must be of odd length + virtual void SetZKernel(vtkFloatArray*); + vtkGetObjectMacro ( ZKernel, vtkFloatArray ); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Overload standard modified time function. If kernel arrays are modified, + // then this object is modified as well. + unsigned long int GetMTime(); + +protected: + vtkImageSeparableConvolution(); + ~vtkImageSeparableConvolution(); + + vtkFloatArray* XKernel; + vtkFloatArray* YKernel; + vtkFloatArray* ZKernel; + + virtual int IterativeRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + virtual int IterativeRequestInformation(vtkInformation* in, + vtkInformation* out); + virtual int IterativeRequestUpdateExtent(vtkInformation* in, + vtkInformation* out); + +private: + vtkImageSeparableConvolution(const vtkImageSeparableConvolution&); // Not implemented. + void operator=(const vtkImageSeparableConvolution&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageShiftScale.cxx b/Imaging/vtkImageShiftScale.cxx new file mode 100644 index 0000000..67853b9 --- /dev/null +++ b/Imaging/vtkImageShiftScale.cxx @@ -0,0 +1,177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageShiftScale.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageShiftScale.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageShiftScale, "$Revision: 1.52.4.1 $"); +vtkStandardNewMacro(vtkImageShiftScale); + +//---------------------------------------------------------------------------- +vtkImageShiftScale::vtkImageShiftScale() +{ + this->Shift = 0.0; + this->Scale = 1.0; + this->OutputScalarType = -1; + this->ClampOverflow = 0; +} + +//---------------------------------------------------------------------------- +vtkImageShiftScale::~vtkImageShiftScale() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageShiftScale::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Shift: " << this->Shift << "\n"; + os << indent << "Scale: " << this->Scale << "\n"; + os << indent << "Output Scalar Type: " << this->OutputScalarType << "\n"; + os << indent << "ClampOverflow: " << (this->ClampOverflow? "On" : "Off") + << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkImageShiftScale::RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + // Set the image scalar type for the output. + if(this->OutputScalarType != -1) + { + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo( + outInfo, this->OutputScalarType, -1); + } + return 1; +} + +//---------------------------------------------------------------------------- +// This function template implements the filter for any type of data. +// The last two arguments help the vtkTemplateMacro calls below +// instantiate the proper input and output types. +template +void vtkImageShiftScaleExecute(vtkImageShiftScale* self, + vtkImageData* inData, + vtkImageData* outData, + int outExt[6], int id, + IT*, OT*) +{ + // Create iterators for the input and output extents assigned to + // this thread. + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + + // Get the shift and scale parameters values. + double shift = self->GetShift(); + double scale = self->GetScale(); + + // Clamp pixel values within the range of the output type. + double typeMin = outData->GetScalarTypeMin(); + double typeMax = outData->GetScalarTypeMax(); + int clamp = self->GetClampOverflow(); + + // Loop through output pixels. + while (!outIt.IsAtEnd()) + { + IT* inSI = inIt.BeginSpan(); + OT* outSI = outIt.BeginSpan(); + OT* outSIEnd = outIt.EndSpan(); + if (clamp) + { + while (outSI != outSIEnd) + { + // Pixel operation + double val = ((double)(*inSI) + shift) * scale; + if (val > typeMax) + { + val = typeMax; + } + if (val < typeMin) + { + val = typeMin; + } + *outSI = (OT)(val); + ++outSI; + ++inSI; + } + } + else + { + while (outSI != outSIEnd) + { + // Pixel operation + *outSI = (OT)(((double)(*inSI) + shift) * scale); + ++outSI; + ++inSI; + } + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +template +void vtkImageShiftScaleExecute1(vtkImageShiftScale* self, + vtkImageData* inData, + vtkImageData* outData, + int outExt[6], int id, T*) +{ + switch (outData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageShiftScaleExecute(self, inData, + outData, outExt, id, + static_cast(0), + static_cast(0))); + default: + vtkErrorWithObjectMacro( + self, "ThreadedRequestData: Unknown output ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +// This method is passed a input and output data, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the datas data types. +void vtkImageShiftScale::ThreadedRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*, + vtkImageData*** inData, + vtkImageData** outData, + int outExt[6], + int threadId) +{ + vtkImageData* input = inData[0][0]; + vtkImageData* output = outData[0]; + switch(input->GetScalarType()) + { + vtkTemplateMacro( + vtkImageShiftScaleExecute1(this, input, output, outExt, threadId, + static_cast(0))); + default: + vtkErrorMacro("ThreadedRequestData: Unknown input ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageShiftScale.h b/Imaging/vtkImageShiftScale.h new file mode 100644 index 0000000..a40975e --- /dev/null +++ b/Imaging/vtkImageShiftScale.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageShiftScale.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageShiftScale - shift and scale an input image +// .SECTION Description +// With vtkImageShiftScale Pixels are shifted and then scaled. As +// a convenience, this class allows you to set the output scalar type +// similar to vtkImageCast. This is because shift scale operations +// frequently convert data types. + + +#ifndef __vtkImageShiftScale_h +#define __vtkImageShiftScale_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageShiftScale : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageShiftScale *New(); + vtkTypeRevisionMacro(vtkImageShiftScale,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the shift value. + vtkSetMacro(Shift,double); + vtkGetMacro(Shift,double); + + // Description: + // Set/Get the scale value. + vtkSetMacro(Scale,double); + vtkGetMacro(Scale,double); + + // Description: + // Set the desired output scalar type. The result of the shift + // and scale operations is cast to the type specified. + vtkSetMacro(OutputScalarType, int); + vtkGetMacro(OutputScalarType, int); + void SetOutputScalarTypeToDouble() + {this->SetOutputScalarType(VTK_DOUBLE);} + void SetOutputScalarTypeToFloat() + {this->SetOutputScalarType(VTK_FLOAT);} + void SetOutputScalarTypeToLong() + {this->SetOutputScalarType(VTK_LONG);} + void SetOutputScalarTypeToUnsignedLong() + {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; + void SetOutputScalarTypeToInt() + {this->SetOutputScalarType(VTK_INT);} + void SetOutputScalarTypeToUnsignedInt() + {this->SetOutputScalarType(VTK_UNSIGNED_INT);} + void SetOutputScalarTypeToShort() + {this->SetOutputScalarType(VTK_SHORT);} + void SetOutputScalarTypeToUnsignedShort() + {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);} + void SetOutputScalarTypeToChar() + {this->SetOutputScalarType(VTK_CHAR);} + void SetOutputScalarTypeToUnsignedChar() + {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);} + + // Description: + // When the ClampOverflow flag is on, the data is thresholded so that + // the output value does not exceed the max or min of the data type. + // By default, ClampOverflow is off. + vtkSetMacro(ClampOverflow, int); + vtkGetMacro(ClampOverflow, int); + vtkBooleanMacro(ClampOverflow, int); + +protected: + vtkImageShiftScale(); + ~vtkImageShiftScale(); + + double Shift; + double Scale; + int OutputScalarType; + int ClampOverflow; + + virtual int RequestInformation(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + virtual void ThreadedRequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*, + vtkImageData*** inData, + vtkImageData** outData, + int outExt[6], + int threadId); +private: + vtkImageShiftScale(const vtkImageShiftScale&); // Not implemented. + void operator=(const vtkImageShiftScale&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageShrink3D.cxx b/Imaging/vtkImageShrink3D.cxx new file mode 100644 index 0000000..c134376 --- /dev/null +++ b/Imaging/vtkImageShrink3D.cxx @@ -0,0 +1,615 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageShrink3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageShrink3D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageShrink3D, "$Revision: 1.69 $"); +vtkStandardNewMacro(vtkImageShrink3D); + +//---------------------------------------------------------------------------- +// Constructor: Sets default filter to be identity. +vtkImageShrink3D::vtkImageShrink3D() +{ + this->ShrinkFactors[0] = this->ShrinkFactors[1] = this->ShrinkFactors[2] = 1; + this->Shift[0] = this->Shift[1] = this->Shift[2] = 0; + this->Mean = 1; + this->Median = 0; + this->Maximum = 0; + this->Minimum = 0; +} + +void vtkImageShrink3D::SetMean (int value) +{ + if (value != this->Mean) + { + this->Mean = value; + if (value == 1) + { + this->Minimum = 0; + this->Maximum = 0; + this->Median = 0; + } + this->Modified(); + } +} + +void vtkImageShrink3D::SetMinimum (int value) +{ + if (value != this->Minimum) + { + this->Minimum = value; + if (value == 1) + { + this->Mean = 0; + this->Maximum = 0; + this->Median = 0; + } + this->Modified(); + } +} + +void vtkImageShrink3D::SetMaximum (int value) +{ + if (value != this->Maximum) + { + this->Maximum = value; + if (value == 1) + { + this->Minimum = 0; + this->Mean = 0; + this->Median = 0; + } + this->Modified(); + } +} + +void vtkImageShrink3D::SetMedian (int value) +{ + if (value != this->Median) + { + this->Median = value; + if (value == 1) + { + this->Minimum = 0; + this->Maximum = 0; + this->Mean = 0; + } + this->Modified(); + } +} + +void vtkImageShrink3D::SetAveraging (int value) +{ + this->SetMean(value); +} + +//---------------------------------------------------------------------------- +void vtkImageShrink3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ShrinkFactors: (" << this->ShrinkFactors[0] << ", " + << this->ShrinkFactors[1] << ", " << this->ShrinkFactors[2] << ")\n"; + os << indent << "Shift: (" << this->Shift[0] << ", " + << this->Shift[1] << ", " << this->Shift[2] << ")\n"; + + os << indent << "Averaging: " << (this->Mean ? "On\n" : "Off\n"); + os << indent << "Mean: " << (this->Mean ? "On\n" : "Off\n"); + os << indent << "Minimum: " << (this->Minimum ? "On\n" : "Off\n"); + os << indent << "Maximum: " << (this->Maximum ? "On\n" : "Off\n"); + os << indent << "Median: " << (this->Median ? "On\n" : "Off\n"); +} + +void vtkImageShrink3D::InternalRequestUpdateExtent(int *inExt, int *outExt) +{ + int idx; + + for (idx = 0; idx < 3; ++idx) + { + // For Min. + inExt[idx*2] = outExt[idx*2] * this->ShrinkFactors[idx] + + this->Shift[idx]; + // For Max. + inExt[idx*2+1] = outExt[idx*2+1] * this->ShrinkFactors[idx] + + this->Shift[idx]; + // If we are not sub sampling, we need a little more + if (this->Mean || this->Minimum || this->Maximum || this->Median) + { + inExt[idx*2+1] += this->ShrinkFactors[idx] - 1; + } + } +} + + +//---------------------------------------------------------------------------- +// This method computes the Region of input necessary to generate outRegion. +int vtkImageShrink3D::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int outExt[6], inExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); + + this->InternalRequestUpdateExtent(inExt, outExt); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +// Computes any global image information associated with regions. +// Any problems with roundoff or negative numbers ??? +int vtkImageShrink3D::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int idx; + int wholeExtent[6]; + double spacing[3]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent); + inInfo->Get(vtkDataObject::SPACING(), spacing); + + for (idx = 0; idx < 3; ++idx) + { + // Avoid dividing by 0. + if (this->ShrinkFactors[idx] == 0) + { + this->ShrinkFactors[idx] = 1; + } + // Scale the output extent + wholeExtent[2*idx] = + (int)(ceil((double)(wholeExtent[2*idx] - this->Shift[idx]) + / (double)(this->ShrinkFactors[idx]))); + wholeExtent[2*idx+1] = (int)(floor( + (double)(wholeExtent[2*idx+1]-this->Shift[idx]-this->ShrinkFactors[idx]+1) + / (double)(this->ShrinkFactors[idx]))); + // make sure WholeExtent is valid when the ShrinkFactors are set on an + // axis with no Extent beforehand + if (wholeExtent[2*idx+1]ShrinkFactors[idx]); + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6); + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + + return 1; +} + +template +#ifdef _WIN32_WCE +int __cdecl vtkiscompare(const T *y1,const T *y2) +#else +int vtkiscompare(const T *y1,const T *y2) +#endif +{ + if ( *y1 < *y2) + { + return -1; + } + + if ( *y1 == *y2) + { + return 0; + } + + return 1; +} + +extern "C" +{ + typedef int (*vtkCompareFunction)(const void*, const void*); +} + +//---------------------------------------------------------------------------- +// The templated execute function handles all the data types. +template +void vtkImageShrink3DExecute(vtkImageShrink3D *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id, + vtkInformation *inInfo) +{ + int outIdx0, outIdx1, outIdx2, inIdx0, inIdx1, inIdx2; + vtkIdType inInc0, inInc1, inInc2; + T *inPtr0, *inPtr1, *inPtr2; + vtkIdType outInc0, outInc1, outInc2; + vtkIdType tmpInc0, tmpInc1, tmpInc2; + T *tmpPtr0, *tmpPtr1, *tmpPtr2; + int factor0, factor1, factor2; + double sum, norm; + unsigned long count = 0; + unsigned long target; + int idxC, maxC, maxX; + T *outPtr2; + + // black magic to force the correct version of the comparison function + // to be instantiated AND used. +#ifdef _WIN32_WCE + int (__cdecl *compareF1)(const T*, const T*) = vtkiscompare; + int (__cdecl *compareFn)(const void*, const void*) + = (int (__cdecl *)(const void*, const void*)) compareF1; +#else + int (*compareF1)(const T*, const T*) = vtkiscompare; +// int (*compareFn)(const void*, const void*) +// = (int (*)(const void*, const void*)) compareF1; + vtkCompareFunction compareFn = + reinterpret_cast(compareF1); +#endif + + self->GetShrinkFactors(factor0, factor1, factor2); + + // make sure we don't have a 3D shrinkfactor for a 2D image + if (factor2>1 && inData && inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT())[5]==0) + { + factor2=1; + } + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + tmpInc0 = inInc0 * factor0; + tmpInc1 = inInc1 * factor1; + tmpInc2 = inInc2 * factor2; + outData->GetContinuousIncrements(outExt,outInc0, outInc1, outInc2); + + maxX = outExt[1] - outExt[0]; + maxC = inData->GetNumberOfScalarComponents(); + target = (unsigned long)(maxC*(outExt[5] - outExt[4] + 1)* + (outExt[3] - outExt[2] + 1)/50.0); + target++; + + if (self->GetMean()) + { + norm = 1.0 / (double)(factor0 * factor1 * factor2); + // Loop through output pixels + for (idxC = 0; idxC < maxC; idxC++) + { + tmpPtr2 = inPtr + idxC; + outPtr2 = outPtr + idxC; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + tmpPtr1 = tmpPtr2; + for (outIdx1 = outExt[2]; + !self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + tmpPtr0 = tmpPtr1; + for (outIdx0 = 0; outIdx0 <= maxX; ++outIdx0) + { + sum = 0.0; + // Loop through neighborhood pixels + inPtr2 = tmpPtr0; + for (inIdx2 = 0; inIdx2 < factor2; ++inIdx2) + { + inPtr1 = inPtr2; + for (inIdx1 = 0; inIdx1 < factor1; ++inIdx1) + { + inPtr0 = inPtr1; + for (inIdx0 = 0; inIdx0 < factor0; ++inIdx0) + { + sum += (double)(*inPtr0); + inPtr0 += inInc0; + } + inPtr1 += inInc1; + } + inPtr2 += inInc2; + } + *outPtr2 = (T)(sum * norm); + tmpPtr0 += tmpInc0; + outPtr2 += maxC; + } + tmpPtr1 += tmpInc1; + outPtr2 += outInc1; + } + tmpPtr2 += tmpInc2; + outPtr2 += outInc2; + } + } + } + else if (self->GetMinimum()) + { + T minValue; + // Loop through output pixels + for (idxC = 0; idxC < maxC; idxC++) + { + tmpPtr2 = inPtr + idxC; + outPtr2 = outPtr + idxC; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + tmpPtr1 = tmpPtr2; + for (outIdx1 = outExt[2]; + !self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + tmpPtr0 = tmpPtr1; + for (outIdx0 = 0; outIdx0 <= maxX; ++outIdx0) + { + minValue = (T) self->GetOutput()->GetScalarTypeMax(); + // Loop through neighborhood pixels + inPtr2 = tmpPtr0; + for (inIdx2 = 0; inIdx2 < factor2; ++inIdx2) + { + inPtr1 = inPtr2; + for (inIdx1 = 0; inIdx1 < factor1; ++inIdx1) + { + inPtr0 = inPtr1; + for (inIdx0 = 0; inIdx0 < factor0; ++inIdx0) + { + if (*inPtr0 < minValue) + { + minValue = *inPtr0; + } + inPtr0 += inInc0; + } + inPtr1 += inInc1; + } + inPtr2 += inInc2; + } + *outPtr2 = minValue; + tmpPtr0 += tmpInc0; + outPtr2 += maxC; + } + tmpPtr1 += tmpInc1; + outPtr2 += outInc1; + } + tmpPtr2 += tmpInc2; + outPtr2 += outInc2; + } + } + } + else if (self->GetMaximum()) + { + T maxValue; + // Loop through output pixels + for (idxC = 0; idxC < maxC; idxC++) + { + tmpPtr2 = inPtr + idxC; + outPtr2 = outPtr + idxC; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + tmpPtr1 = tmpPtr2; + for (outIdx1 = outExt[2]; + !self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + tmpPtr0 = tmpPtr1; + for (outIdx0 = 0; outIdx0 <= maxX; ++outIdx0) + { + maxValue = (T) self->GetOutput()->GetScalarTypeMin(); + // Loop through neighborhood pixels + inPtr2 = tmpPtr0; + for (inIdx2 = 0; inIdx2 < factor2; ++inIdx2) + { + inPtr1 = inPtr2; + for (inIdx1 = 0; inIdx1 < factor1; ++inIdx1) + { + inPtr0 = inPtr1; + for (inIdx0 = 0; inIdx0 < factor0; ++inIdx0) + { + if (*inPtr0 > maxValue) + { + maxValue = *inPtr0; + } + inPtr0 += inInc0; + } + inPtr1 += inInc1; + } + inPtr2 += inInc2; + } + *outPtr2 = maxValue; + tmpPtr0 += tmpInc0; + outPtr2 += maxC; + } + tmpPtr1 += tmpInc1; + outPtr2 += outInc1; + } + tmpPtr2 += tmpInc2; + outPtr2 += outInc2; + } + } + } + else if (self->GetMedian()) + { + T* kernel = new T [factor0 * factor1 * factor2]; + int index; + + // Loop through output pixels + for (idxC = 0; idxC < maxC; idxC++) + { + tmpPtr2 = inPtr + idxC; + outPtr2 = outPtr + idxC; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + tmpPtr1 = tmpPtr2; + for (outIdx1 = outExt[2]; + !self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + tmpPtr0 = tmpPtr1; + for (outIdx0 = 0; outIdx0 <= maxX; ++outIdx0) + { + // Loop through neighborhood pixels + inPtr2 = tmpPtr0; + index = 0; + for (inIdx2 = 0; inIdx2 < factor2; ++inIdx2) + { + inPtr1 = inPtr2; + for (inIdx1 = 0; inIdx1 < factor1; ++inIdx1) + { + inPtr0 = inPtr1; + for (inIdx0 = 0; inIdx0 < factor0; ++inIdx0) + { + kernel[index++] = *inPtr0; + + inPtr0 += inInc0; + } + inPtr1 += inInc1; + } + inPtr2 += inInc2; + } + qsort(kernel,index,sizeof(T),compareFn); + *outPtr2 = *(kernel + index/2); + + tmpPtr0 += tmpInc0; + outPtr2 += maxC; + } + tmpPtr1 += tmpInc1; + outPtr2 += outInc1; + } + tmpPtr2 += tmpInc2; + outPtr2 += outInc2; + } + } + delete [] kernel; + } + else // Just SubSample + { + // Loop through output pixels + for (idxC = 0; idxC < maxC; idxC++) + { + tmpPtr2 = inPtr + idxC; + outPtr2 = outPtr + idxC; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2) + { + tmpPtr1 = tmpPtr2; + for (outIdx1 = outExt[2]; + !self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + tmpPtr0 = tmpPtr1; + for (outIdx0 = 0; outIdx0 <= maxX; ++outIdx0) + { + *outPtr2 = *tmpPtr0; + + tmpPtr0 += tmpInc0; + outPtr2 += maxC; + } + tmpPtr1 += tmpInc1; + outPtr2 += outInc1; + } + tmpPtr2 += tmpInc2; + outPtr2 += outInc2; + } + } + } +} + +//---------------------------------------------------------------------------- +// This method uses the input data to fill the output data. +// It can handle any type data, but the two datas must have the same +// data type. +void vtkImageShrink3D::ThreadedRequestData( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector **inputVector, + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6]; + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + this->InternalRequestUpdateExtent(inExt, outExt); + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + if (!inPtr) + { + return; + } + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro("Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageShrink3DExecute( this, + inData[0][0], + (VTK_TT *)(inPtr), + outData[0], + (VTK_TT *)(outPtr), + outExt, + id, + inInfo) ); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageShrink3D.h b/Imaging/vtkImageShrink3D.h new file mode 100644 index 0000000..dd919fd --- /dev/null +++ b/Imaging/vtkImageShrink3D.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageShrink3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageShrink3D - Subsamples an image. +// .SECTION Description +// vtkImageShrink3D shrinks an image by sub sampling on a +// uniform grid (integer multiples). + +#ifndef __vtkImageShrink3D_h +#define __vtkImageShrink3D_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageShrink3D : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageShrink3D *New(); + vtkTypeRevisionMacro(vtkImageShrink3D,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the shrink factors + vtkSetVector3Macro(ShrinkFactors,int); + vtkGetVector3Macro(ShrinkFactors,int); + + // Description: + // Set/Get the pixel to use as origin. + vtkSetVector3Macro(Shift,int); + vtkGetVector3Macro(Shift,int); + + // Description: + // Choose Mean, Minimum, Maximum, Median or sub sampling. + // The neighborhood operations are not centered on the sampled pixel. + // This may cause a half pixel shift in your output image. + // You can changed "Shift" to get around this. + // vtkImageGaussianSmooth or vtkImageMean with strides. + void SetAveraging(int); + int GetAveraging() {return this->GetMean();}; + vtkBooleanMacro(Averaging,int); + + void SetMean(int); + vtkGetMacro(Mean,int); + vtkBooleanMacro(Mean,int); + + void SetMinimum(int); + vtkGetMacro(Minimum,int); + vtkBooleanMacro(Minimum,int); + + void SetMaximum(int); + vtkGetMacro(Maximum,int); + vtkBooleanMacro(Maximum,int); + + void SetMedian(int); + vtkGetMacro(Median,int); + vtkBooleanMacro(Median,int); + +protected: + vtkImageShrink3D(); + ~vtkImageShrink3D() {}; + + int ShrinkFactors[3]; + int Shift[3]; + int Mean; + int Minimum; + int Maximum; + int Median; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); + + void InternalRequestUpdateExtent(int *inExt, int *outExt); + +private: + vtkImageShrink3D(const vtkImageShrink3D&); // Not implemented. + void operator=(const vtkImageShrink3D&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageSinusoidSource.cxx b/Imaging/vtkImageSinusoidSource.cxx new file mode 100644 index 0000000..164560f --- /dev/null +++ b/Imaging/vtkImageSinusoidSource.cxx @@ -0,0 +1,213 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSinusoidSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSinusoidSource.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageSinusoidSource, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkImageSinusoidSource); + +//---------------------------------------------------------------------------- +vtkImageSinusoidSource::vtkImageSinusoidSource() +{ + this->Direction[0] = 1.0; + this->Direction[1] = 0.0; + this->Direction[2] = 0.0; + + this->Amplitude = 255.0; + this->Phase = 0.0; + this->Period = 20.0; + + this->WholeExtent[0] = 0; this->WholeExtent[1] = 255; + this->WholeExtent[2] = 0; this->WholeExtent[3] = 255; + this->WholeExtent[4] = 0; this->WholeExtent[5] = 0; + + this->SetNumberOfInputPorts(0); +} + +void vtkImageSinusoidSource::SetDirection(double v[3]) +{ + this->SetDirection(v[0],v[1],v[2]); +} + +void vtkImageSinusoidSource::SetDirection(double v0, double v1, double v2) +{ + double sum; + + sum = v0*v0 + v1*v1 + v2*v2; + + if (sum == 0.0) + { + vtkErrorMacro("Zero direction vector"); + return; + } + + // normalize + sum = 1.0 / sqrt(sum); + v0 *= sum; + v1 *= sum; + v2 *= sum; + + if (this->Direction[0] == v0 && this->Direction[1] == v1 + && this->Direction[2] == v2) + { + return; + } + + this->Direction[0] = v0; + this->Direction[1] = v1; + this->Direction[2] = v2; + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkImageSinusoidSource::SetWholeExtent(int xMin, int xMax, + int yMin, int yMax, + int zMin, int zMax) +{ + int modified = 0; + + if (this->WholeExtent[0] != xMin) + { + modified = 1; + this->WholeExtent[0] = xMin ; + } + if (this->WholeExtent[1] != xMax) + { + modified = 1; + this->WholeExtent[1] = xMax ; + } + if (this->WholeExtent[2] != yMin) + { + modified = 1; + this->WholeExtent[2] = yMin ; + } + if (this->WholeExtent[3] != yMax) + { + modified = 1; + this->WholeExtent[3] = yMax ; + } + if (this->WholeExtent[4] != zMin) + { + modified = 1; + this->WholeExtent[4] = zMin ; + } + if (this->WholeExtent[5] != zMax) + { + modified = 1; + this->WholeExtent[5] = zMax ; + } + if (modified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkImageSinusoidSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent,6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 1); + return 1; +} + +void vtkImageSinusoidSource::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data = this->AllocateOutputData(output); + double *outPtr; + int idxX, idxY, idxZ; + int maxX, maxY, maxZ; + vtkIdType outIncX, outIncY, outIncZ; + int *outExt; + double sum; + double yContrib, zContrib, xContrib; + unsigned long count = 0; + unsigned long target; + + if (data->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro("Execute: This source only outputs doubles"); + } + + outExt = data->GetExtent(); + + // find the region to loop over + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + // Get increments to march through data + data->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + outPtr = (double *) data->GetScalarPointer(outExt[0],outExt[2],outExt[4]); + + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Loop through ouput pixels + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + zContrib = this->Direction[2] * (idxZ + outExt[4]); + for (idxY = 0; !this->AbortExecute && idxY <= maxY; idxY++) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + yContrib = this->Direction[1] * (idxY + outExt[2]); + for (idxX = 0; idxX <= maxX; idxX++) + { + xContrib = this->Direction[0] * (double)(idxX + outExt[0]); + // find dot product + sum = zContrib + yContrib + xContrib; + + *outPtr = this->Amplitude * + cos((6.2831853 * sum / this->Period) - this->Phase); + outPtr++; + } + outPtr += outIncY; + } + outPtr += outIncZ; + } +} + +void vtkImageSinusoidSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Period: " << this->Period << "\n"; + os << indent << "Phase: " << this->Phase << "\n"; + os << indent << "Amplitude: " << this->Amplitude << "\n"; + os << indent << "Direction: ( " + << this->Direction[0] << ", " + << this->Direction[1] << ", " + << this->Direction[2] << " )\n"; + +} + diff --git a/Imaging/vtkImageSinusoidSource.h b/Imaging/vtkImageSinusoidSource.h new file mode 100644 index 0000000..a6ce153 --- /dev/null +++ b/Imaging/vtkImageSinusoidSource.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSinusoidSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSinusoidSource - Create an image with sinusoidal pixel values. +// .SECTION Description +// vtkImageSinusoidSource just produces images with pixel values determined +// by a sinusoid. + + +#ifndef __vtkImageSinusoidSource_h +#define __vtkImageSinusoidSource_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageSinusoidSource : public vtkImageAlgorithm +{ +public: + static vtkImageSinusoidSource *New(); + vtkTypeRevisionMacro(vtkImageSinusoidSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the extent of the whole output image. + void SetWholeExtent(int xMinx, int xMax, int yMin, int yMax, + int zMin, int zMax); + + // Description: + // Set/Get the direction vector which determines the sinusoidal + // orientation. The magnitude is ignored. + void SetDirection(double,double,double); + void SetDirection(double dir[3]); + vtkGetVector3Macro(Direction, double); + + // Description: + // Set/Get the period of the sinusoid in pixels. + vtkSetMacro(Period, double); + vtkGetMacro(Period, double); + + // Description: + // Set/Get the phase: 0->2Pi. 0 => Cosine, pi/2 => Sine. + vtkSetMacro(Phase, double); + vtkGetMacro(Phase, double); + + // Description: + // Set/Get the magnitude of the sinusoid. + vtkSetMacro(Amplitude, double); + vtkGetMacro(Amplitude, double); + +protected: + vtkImageSinusoidSource(); + ~vtkImageSinusoidSource() {}; + + int WholeExtent[6]; + double Direction[3]; + double Period; + double Phase; + double Amplitude; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); + virtual void ExecuteData(vtkDataObject *data); +private: + vtkImageSinusoidSource(const vtkImageSinusoidSource&); // Not implemented. + void operator=(const vtkImageSinusoidSource&); // Not implemented. +}; + + +#endif + + + diff --git a/Imaging/vtkImageSkeleton2D.cxx b/Imaging/vtkImageSkeleton2D.cxx new file mode 100644 index 0000000..5d39611 --- /dev/null +++ b/Imaging/vtkImageSkeleton2D.cxx @@ -0,0 +1,372 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSkeleton2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSkeleton2D.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkDataSetAttributes.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageSkeleton2D, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkImageSkeleton2D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageSkeleton2D fitler. +vtkImageSkeleton2D::vtkImageSkeleton2D() +{ + this->Prune = 0; +} + +//---------------------------------------------------------------------------- +void vtkImageSkeleton2D::SetNumberOfIterations(int num) +{ + this->vtkImageIterateFilter::SetNumberOfIterations(num); +} + +//---------------------------------------------------------------------------- +// This method computes the extent of the input region necessary to generate +// an output region. Before this method is called "region" should have the +// extent of the output region. After this method finishes, "region" should +// have the extent of the required input region. +int vtkImageSkeleton2D::IterativeRequestUpdateExtent(vtkInformation* in, + vtkInformation* out) +{ + int wholeExtent[6]; + int outExt[6]; + in->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + out->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); + + int inExt[6]; + inExt[4] = outExt[4]; + inExt[5] = outExt[5]; + for(int idx=0; idx < 2; ++idx) + { + inExt[idx*2] = outExt[idx*2] - 1; + inExt[idx*2+1] = outExt[idx*2+1] + 1; + + // If the expanded region is out of the IMAGE Extent (grow min) + if (inExt[idx*2] < wholeExtent[idx*2]) + { + inExt[idx*2] = wholeExtent[idx*2]; + } + // If the expanded region is out of the IMAGE Extent (shrink max) + if (inExt[idx*2+1] > wholeExtent[idx*2+1]) + { + // shrink the required region extent + inExt[idx*2+1] = wholeExtent[idx*2+1]; + } + } + + in->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +// This method contains the second switch statement that calls the correct +// templated function for the mask types. +// This is my best attempt at skeleton. The rules are a little hacked up, +// but it is the only way I can think of to get the +// desired results with a 3x3 kernel. +template +void vtkImageSkeleton2DExecute(vtkImageSkeleton2D *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, int *outExt, + T *outPtr, int id) +{ + // For looping though output (and input) pixels. + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2, numComps; + int idx0, idx1, idx2, idxC; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + T *inPtr0, *inPtr1, *inPtr2, *inPtrC; + T *outPtr0, *outPtr1, *outPtr2; + int wholeMin0, wholeMax0, wholeMin1, wholeMax1, wholeMin2, wholeMax2; + int prune = self->GetPrune(); + float n[8]; + int countFaces, countCorners; + unsigned long count = 0; + unsigned long target; + int erodeCase; + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + outData->GetIncrements(outInc0, outInc1, outInc2); + outMin0 = outExt[0]; outMax0 = outExt[1]; + outMin1 = outExt[2]; outMax1 = outExt[3]; + outMin2 = outExt[4]; outMax2 = outExt[5]; + self->GetInput()->GetWholeExtent(wholeMin0, wholeMax0, wholeMin1, wholeMax1, + wholeMin2, wholeMax2); + numComps = inData->GetNumberOfScalarComponents(); + + target = (unsigned long)(numComps*(outMax2-outMin2+1)* + (outMax1-outMin1+1)/50.0); + target++; + + inPtrC = inPtr; + for (idxC = 0; idxC < numComps; ++idxC) + { + inPtr2 = inPtrC; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + // erode input + inPtr1 = inPtr2; + for (idx1 = outMin1; !self->AbortExecute && idx1 <= outMax1; ++idx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(0.9*count/(50.0*target)); + } + count++; + } + inPtr0 = inPtr1; + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + // Center pixel has to be on. + if (*inPtr0) + { + // neighbors independant of boundaries + n[0] = (idx0>wholeMin0) ? (float)*(inPtr0-inInc0) : 0; + n[1] = (idx0>wholeMin0)&&(idx1>wholeMin1) + ? (float)*(inPtr0-inInc0-inInc1) : 0; + n[2] = (idx1>wholeMin1) ? (float)*(inPtr0-inInc1) : 0; + n[3] = (idx1>wholeMin1)&&(idx0wholeMin0) + ? (float)*(inPtr0+inInc1-inInc0) : 0; + + // Lets try a case table. (shifting bits would be faster) + erodeCase = 0; + if (n[7] > 0) {++erodeCase;} + erodeCase *= 2; + if (n[6] > 0) {++erodeCase;} + erodeCase *= 2; + if (n[5] > 0) {++erodeCase;} + erodeCase *= 2; + if (n[4] > 0) {++erodeCase;} + erodeCase *= 2; + if (n[3] > 0) {++erodeCase;} + erodeCase *= 2; + if (n[2] > 0) {++erodeCase;} + erodeCase *= 2; + if (n[1] > 0) {++erodeCase;} + erodeCase *= 2; + if (n[0] > 0) {++erodeCase;} + + if (erodeCase == 54 || erodeCase == 216) + { // erode + // 54 top part of diagonal / double thick line + // 216 bottom part of diagonal \ double thick line + *inPtr0 = 1; + } + else if (erodeCase == 99 || erodeCase == 141) + { // No errosion + // 99 bottom part of diagonal / double thick line + // 141 top part of diagonal \ double thick line + } + else + { + // old heuristic method + countFaces = (n[0]>0)+(n[2]>0)+(n[4]>0)+(n[6]>0); + countCorners = (n[1]>0)+(n[3]>0)+(n[5]>0)+(n[7]>0); + + // special case to void split dependent results. + // (should we just have a case table?) + if (countFaces == 2 && countCorners == 0 && + n[2] > 0 && n[4] > 0) + { + *inPtr0 = 1; + } + + // special case + if (prune > 1 && ((countFaces + countCorners) <= 1)) + { + *inPtr0 = 1; + } + + // one of four face neighbors has to be off + if (n[0] == 0 || n[2] == 0 || + n[4] == 0 || n[6] == 0) + { + // Special condition not to prune diamond corners + if (prune > 1 || countFaces != 1 || countCorners != 2 || + ((n[1]==0 || n[2]==0 || n[3]==0) && + (n[3]==0 || n[4]==0 || n[5]==0) && + (n[5]==0 || n[6]==0 || n[7]==0) && + (n[7]==0 || n[0]==0 || n[1]==0))) + { + // special condition (making another prune level) + // pruning 135 degree corners + if (prune || countFaces != 2 || countCorners != 2 || + ((n[1]==0 || n[2]==0 || n[3]==0 || n[4]) && + (n[0]==0 || n[1]==0 || n[2]==0 || n[3]) && + (n[7]==0 || n[0]==0 || n[1]==0 || n[2]) && + (n[6]==0 || n[7]==0 || n[0]==0 || n[1]) && + (n[5]==0 || n[6]==0 || n[7]==0 || n[0]) && + (n[4]==0 || n[5]==0 || n[6]==0 || n[7]) && + (n[3]==0 || n[4]==0 || n[5]==0 || n[6]) && + (n[2]==0 || n[3]==0 || n[4]==0 || n[5]))) + { + // remaining pixels need to be connected. + // do not break corner connectivity + if ((n[1] == 0 || n[0] > 1 || n[2] > 1) && + (n[3] == 0 || n[2] > 1 || n[4] > 1) && + (n[5] == 0 || n[4] > 1 || n[6] > 1) && + (n[7] == 0 || n[6] > 1 || n[0] > 1)) + { + // opposite faces + // (special condition so double thick lines + // will not be completely eroded) + if ((n[0] == 0 || n[4] == 0 || n[2] > 1 || n[6] > 1) && + (n[2] == 0 || n[6] == 0 || n[0] > 1 || n[4] > 1)) + { + // check to stop pruning (sort of a hack huristic) + if (prune > 1 || (countFaces > 2) || + ((countFaces == 2) && (countCorners > 1))) + { + *inPtr0 = 1; + } + } + } + } + } + } + } + + } + inPtr0 += inInc0; + } + inPtr1 += inInc1; + } + inPtr2 += inInc2; + } + ++inPtrC; + } + + + // copy to output + for (idxC = 0; idxC < numComps; ++idxC) + { + outPtr2 = outPtr; + inPtr2 = inPtr; + for (idx2 = outMin2; idx2 <= outMax2; ++idx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (idx1 = outMin1; idx1 <= outMax1; ++idx1) + { + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (idx0 = outMin0; idx0 <= outMax0; ++idx0) + { + if (*inPtr0 <= 1) + { + *outPtr0 = (T)(0.0); + } + else + { + *outPtr0 = *inPtr0; + } + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + ++inPtr; + ++outPtr; + } +} + + + + + +//---------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output region types. +void vtkImageSkeleton2D::ThreadedExecute(vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id) +{ + void *inPtr; + void *outPtr = outData->GetScalarPointerForExtent(outExt); + vtkImageData *tempData; + int inExt[6]; + + // this filter expects that input is the same type as output. + if (inData->GetScalarType() != outData->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType() + << ", must match out ScalarType " << outData->GetScalarType()); + return; + } + + vtkInformation* inInfo = inData->GetPipelineInformation(); + inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt); + + vtkInformation *inScalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!inScalarInfo) + { + vtkErrorMacro("Missing ActiveScalar info in input information!"); + return; + } + + // Make a temporary copy of the input data + tempData = vtkImageData::New(); + tempData->SetScalarType( inScalarInfo->Get(vtkImageData::FIELD_ARRAY_TYPE()) ); + tempData->SetExtent(inExt); + tempData->SetNumberOfScalarComponents( + inScalarInfo->Get(vtkImageData::FIELD_NUMBER_OF_COMPONENTS()) ); + tempData->CopyAndCastFrom(inData, inExt); + + inPtr = tempData->GetScalarPointerForExtent(outExt); + switch (tempData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageSkeleton2DExecute( this, tempData, + (VTK_TT *)(inPtr), outData, outExt, + (VTK_TT *)(outPtr), id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + tempData->Delete(); + return; + } + + tempData->Delete(); +} + +void vtkImageSkeleton2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Prune: " << (this->Prune ? "On\n" : "Off\n"); + +} + diff --git a/Imaging/vtkImageSkeleton2D.h b/Imaging/vtkImageSkeleton2D.h new file mode 100644 index 0000000..2343bf5 --- /dev/null +++ b/Imaging/vtkImageSkeleton2D.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSkeleton2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSkeleton2D - Skeleton of 2D images. +// .SECTION Description +// vtkImageSkeleton2D should leave only single pixel width lines +// of non-zero-valued pixels (values of 1 are not allowed). +// It works by erosion on a 3x3 neighborhood with special rules. +// The number of iterations determines how far the filter can erode. +// There are three pruning levels: +// prune == 0 will leave traces on all angles... +// prune == 1 will not leave traces on 135 degree angles, but will on 90. +// prune == 2 does not leave traces on any angles leaving only closed loops. +// Prune defaults to zero. The output scalar type is the same as the input. + + + +#ifndef __vtkImageSkeleton2D_h +#define __vtkImageSkeleton2D_h + +#include "vtkImageIterateFilter.h" + +class VTK_IMAGING_EXPORT vtkImageSkeleton2D : public vtkImageIterateFilter +{ +public: + static vtkImageSkeleton2D *New(); + vtkTypeRevisionMacro(vtkImageSkeleton2D,vtkImageIterateFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // When prune is on, only closed loops are left unchanged. + vtkSetMacro(Prune,int); + vtkGetMacro(Prune,int); + vtkBooleanMacro(Prune,int); + + // Description: + // Sets the number of cycles in the erosion. + void SetNumberOfIterations(int num); + +protected: + vtkImageSkeleton2D(); + ~vtkImageSkeleton2D() {}; + + int Prune; + + virtual int IterativeRequestUpdateExtent(vtkInformation* in, + vtkInformation* out); + void ThreadedExecute(vtkImageData *inData, vtkImageData *outData, + int outExt[6], int id); +private: + vtkImageSkeleton2D(const vtkImageSkeleton2D&); // Not implemented. + void operator=(const vtkImageSkeleton2D&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageSobel2D.cxx b/Imaging/vtkImageSobel2D.cxx new file mode 100644 index 0000000..ef44885 --- /dev/null +++ b/Imaging/vtkImageSobel2D.cxx @@ -0,0 +1,221 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSobel2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSobel2D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageSobel2D, "$Revision: 1.37 $"); +vtkStandardNewMacro(vtkImageSobel2D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageSobel2D fitler. +vtkImageSobel2D::vtkImageSobel2D() +{ + this->KernelSize[0] = 3; + this->KernelSize[1] = 3; + this->KernelSize[2] = 1; + this->KernelMiddle[0] = 1; + this->KernelMiddle[1] = 1; + this->KernelMiddle[2] = 0; + this->HandleBoundaries = 1; +} + +//---------------------------------------------------------------------------- +void vtkImageSobel2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +int vtkImageSobel2D::RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int retval = + this->Superclass::RequestInformation(request, inputVector, outputVector); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 2); + return retval; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageSobel2DExecute(vtkImageSobel2D *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, int *outExt, + double *outPtr, int id, + vtkInformation *inInfo) +{ + double r0, r1, *r; + // For looping though output (and input) pixels. + int min0, max0, min1, max1, min2, max2; + int outIdx0, outIdx1, outIdx2; + vtkIdType outInc0, outInc1, outInc2; + double *outPtr0, *outPtr1, *outPtr2, *outPtrV; + vtkIdType inInc0, inInc1, inInc2; + T *inPtr0, *inPtr1, *inPtr2; + // For sobel function convolution (Left Right incs for each axis) + vtkIdType inInc0L, inInc0R, inInc1L, inInc1R; + T *inPtrL, *inPtrR; + double sum; + // Boundary of input image + int inWholeMin0,inWholeMax0; + int inWholeMin1,inWholeMax1; + int inWholeExt[6]; + unsigned long count = 0; + unsigned long target; + + // Get boundary information + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inWholeExt); + inWholeMin0 = inWholeExt[0]; + inWholeMax0 = inWholeExt[1]; + inWholeMin1 = inWholeExt[2]; + inWholeMax1 = inWholeExt[3]; + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + outData->GetIncrements(outInc0, outInc1, outInc2); + min0 = outExt[0]; max0 = outExt[1]; + min1 = outExt[2]; max1 = outExt[3]; + min2 = outExt[4]; max2 = outExt[5]; + + // We want the input pixel to correspond to output + inPtr = (T *)(inData->GetScalarPointer(min0,min1,min2)); + + // The data spacing is important for computing the gradient. + // Scale so it has the same range as gradient. + r = inData->GetSpacing(); + r0 = 0.125 / r[0]; + r1 = 0.125 / r[1]; + // ignore r2 + + target = (unsigned long)((max2-min2+1)*(max1-min1+1)/50.0); + target++; + + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = min2; outIdx2 <= max2; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = min1; !self->AbortExecute && outIdx1 <= max1; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + inInc1L = (outIdx1 == inWholeMin1) ? 0 : -inInc1; + inInc1R = (outIdx1 == inWholeMax1) ? 0 : inInc1; + + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0) + { + inInc0L = (outIdx0 == inWholeMin0) ? 0 : -inInc0; + inInc0R = (outIdx0 == inWholeMax0) ? 0 : inInc0; + + // compute vector. + outPtrV = outPtr0; + // 0 direction + inPtrL = inPtr0 + inInc0L; + inPtrR = inPtr0 + inInc0R; + sum = 2.0 * (*inPtrR - *inPtrL); + sum += (double)(inPtrR[inInc1L] + inPtrR[inInc1R]); + sum -= (double)(inPtrL[inInc1L] + inPtrL[inInc1R]); + + *outPtrV = sum * r0; + ++outPtrV; + // 1 direction + inPtrL = inPtr0 + inInc1L; + inPtrR = inPtr0 + inInc1R; + sum = 2.0 * (*inPtrR - *inPtrL); + sum += (double)(inPtrR[inInc0L] + inPtrR[inInc0R]); + sum -= (double)(inPtrL[inInc0L] + inPtrL[inInc0R]); + *outPtrV = static_cast(sum * r1); + + outPtr0 += outInc0; + inPtr0 += inInc0; + } + outPtr1 += outInc1; + inPtr1 += inInc1; + } + outPtr2 += outInc2; + inPtr2 += inInc2; + } +} + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input region type. The output region +// must be of type double. This method does handle boundary conditions. +// The third axis is the component axis for the output. +void vtkImageSobel2D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr, *outPtr; + int inExt[6], wholeExt[6]; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt, outExt, wholeExt); + + inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + // this filter expects that output is type double. + if (outData[0]->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << ", must be double"); + return; + } + + // this filter cannot handle multi component input. + if (inData[0][0]->GetNumberOfScalarComponents() != 1) + { + vtkWarningMacro("Expecting input with only one compenent.\n"); + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageSobel2DExecute(this, inData[0][0], + (VTK_TT *)(inPtr), outData[0], outExt, + (double *)(outPtr),id, inInfo)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageSobel2D.h b/Imaging/vtkImageSobel2D.h new file mode 100644 index 0000000..e35148c --- /dev/null +++ b/Imaging/vtkImageSobel2D.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSobel2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSobel2D - Computes a vector field using sobel functions. +// .SECTION Description +// vtkImageSobel2D computes a vector field from a scalar field by using +// Sobel functions. The number of vector components is 2 because +// the input is an image. Output is always doubles. + + +#ifndef __vtkImageSobel2D_h +#define __vtkImageSobel2D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageSobel2D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageSobel2D *New(); + vtkTypeRevisionMacro(vtkImageSobel2D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkImageSobel2D(); + ~vtkImageSobel2D() {}; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); + virtual int RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + +private: + vtkImageSobel2D(const vtkImageSobel2D&); // Not implemented. + void operator=(const vtkImageSobel2D&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageSobel3D.cxx b/Imaging/vtkImageSobel3D.cxx new file mode 100644 index 0000000..a9d5a90 --- /dev/null +++ b/Imaging/vtkImageSobel3D.cxx @@ -0,0 +1,251 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSobel3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSobel3D.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageSobel3D, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkImageSobel3D); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageSobel3D fitler. +vtkImageSobel3D::vtkImageSobel3D() +{ + this->KernelSize[0] = 3; + this->KernelSize[1] = 3; + this->KernelSize[2] = 3; + this->KernelMiddle[0] = 1; + this->KernelMiddle[1] = 1; + this->KernelMiddle[2] = 1; + this->HandleBoundaries = 1; +} + +//---------------------------------------------------------------------------- +void vtkImageSobel3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +int vtkImageSobel3D::RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int retval = + this->Superclass::RequestInformation(request, inputVector, outputVector); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 3); + return retval; +} + +//---------------------------------------------------------------------------- +// This execute method handles boundaries. +// it handles boundaries. Pixels are just replicated to get values +// out of extent. +template +void vtkImageSobel3DExecute(vtkImageSobel3D *self, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, int *outExt, + double *outPtr, int id, vtkInformation *inInfo) +{ + double r0, r1, r2, *r; + // For looping though output (and input) pixels. + int min0, max0, min1, max1, min2, max2; + int outIdx0, outIdx1, outIdx2; + vtkIdType outInc0, outInc1, outInc2; + double *outPtr0, *outPtr1, *outPtr2, *outPtrV; + vtkIdType inInc0, inInc1, inInc2; + T *inPtr0, *inPtr1, *inPtr2; + // For sobel function convolution (Left Right incs for each axis) + vtkIdType inInc0L, inInc0R, inInc1L, inInc1R, inInc2L, inInc2R; + T *inPtrL, *inPtrR; + double sum; + // Boundary of input image + int inWholeMin0, inWholeMax0, inWholeMin1, inWholeMax1; + int inWholeMin2, inWholeMax2; + int inWholeExt[6]; + unsigned long count = 0; + unsigned long target; + + // Get boundary information + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inWholeExt); + inWholeMin0 = inWholeExt[0]; + inWholeMax0 = inWholeExt[1]; + inWholeMin1 = inWholeExt[2]; + inWholeMax1 = inWholeExt[3]; + inWholeMin2 = inWholeExt[4]; + inWholeMax2 = inWholeExt[5]; + + // Get information to march through data (skip component) + inData->GetIncrements(inInc0, inInc1, inInc2); + outData->GetIncrements(outInc0, outInc1, outInc2); + min0 = outExt[0]; max0 = outExt[1]; + min1 = outExt[2]; max1 = outExt[3]; + min2 = outExt[4]; max2 = outExt[5]; + + // We want the input pixel to correspond to output + inPtr = (T *)(inData->GetScalarPointer(min0,min1,min2)); + + // The data spacing is important for computing the gradient. + // Scale so it has the same range as gradient. + r = inData->GetSpacing(); + r0 = 0.060445 / r[0]; + r1 = 0.060445 / r[1]; + r2 = 0.060445 / r[2]; + + target = (unsigned long)((max2-min2+1)*(max1-min1+1)/50.0); + target++; + + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = min2; outIdx2 <= max2; ++outIdx2) + { + inInc2L = (outIdx2 == inWholeMin2) ? 0 : -inInc2; + inInc2R = (outIdx2 == inWholeMax2) ? 0 : inInc2; + + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = min1; !self->AbortExecute && outIdx1 <= max1; ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + inInc1L = (outIdx1 == inWholeMin1) ? 0 : -inInc1; + inInc1R = (outIdx1 == inWholeMax1) ? 0 : inInc1; + + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0) + { + inInc0L = (outIdx0 == inWholeMin0) ? 0 : -inInc0; + inInc0R = (outIdx0 == inWholeMax0) ? 0 : inInc0; + + // compute vector. + outPtrV = outPtr0; + // 12 Plane + inPtrL = inPtr0 + inInc0L; + inPtrR = inPtr0 + inInc0R; + sum = 2.0 * (*inPtrR - *inPtrL); + sum += (double)(inPtrR[inInc1L] + inPtrR[inInc1R] + + inPtrR[inInc2L] + inPtrR[inInc2R]); + sum += (double)(0.586 * (inPtrR[inInc1L+inInc2L] + inPtrR[inInc1L+inInc2R] + + inPtrR[inInc1R+inInc2L] + inPtrR[inInc1R+inInc2R])); + sum -= (double)(inPtrL[inInc1L] + inPtrL[inInc1R] + + inPtrL[inInc2L] + inPtrL[inInc2R]); + sum -= (double)(0.586 * (inPtrL[inInc1L+inInc2L] + inPtrL[inInc1L+inInc2R] + + inPtrL[inInc1R+inInc2L] + inPtrL[inInc1R+inInc2R])); + *outPtrV = sum * r0; + ++outPtrV; + // 02 Plane + inPtrL = inPtr0 + inInc1L; + inPtrR = inPtr0 + inInc1R; + sum = 2.0 * (*inPtrR - *inPtrL); + sum += (double)(inPtrR[inInc0L] + inPtrR[inInc0R] + + inPtrR[inInc2L] + inPtrR[inInc2R]); + sum += (double)(0.586 * (inPtrR[inInc0L+inInc2L] + inPtrR[inInc0L+inInc2R] + + inPtrR[inInc0R+inInc2L] + inPtrR[inInc0R+inInc2R])); + sum -= (double)(inPtrL[inInc0L] + inPtrL[inInc0R] + + inPtrL[inInc2L] + inPtrL[inInc2R]); + sum -= (double)(0.586 * (inPtrL[inInc0L+inInc2L] + inPtrL[inInc0L+inInc2R] + + inPtrL[inInc0R+inInc2L] + inPtrL[inInc0R+inInc2R])); + *outPtrV = sum * r1; + ++outPtrV; + // 01 Plane + inPtrL = inPtr0 + inInc2L; + inPtrR = inPtr0 + inInc2R; + sum = 2.0 * (*inPtrR - *inPtrL); + sum += (double)(inPtrR[inInc0L] + inPtrR[inInc0R] + + inPtrR[inInc1L] + inPtrR[inInc1R]); + sum += (double)(0.586 * (inPtrR[inInc0L+inInc1L] + inPtrR[inInc0L+inInc1R] + + inPtrR[inInc0R+inInc1L] + inPtrR[inInc0R+inInc1R])); + sum -= (double)(inPtrL[inInc0L] + inPtrL[inInc0R] + + inPtrL[inInc1L] + inPtrL[inInc1R]); + sum -= (double)(0.586 * (inPtrL[inInc0L+inInc1L] + inPtrL[inInc0L+inInc1R] + + inPtrL[inInc0R+inInc1L] + inPtrL[inInc0R+inInc1R])); + *outPtrV = static_cast(sum * r2); + ++outPtrV; + + outPtr0 += outInc0; + inPtr0 += inInc0; + } + outPtr1 += outInc1; + inPtr1 += inInc1; + } + outPtr2 += outInc2; + inPtr2 += inInc2; + } +} + +//---------------------------------------------------------------------------- +// This method contains a switch statement that calls the correct +// templated function for the input Data type. The output Data +// must be of type double. This method does handle boundary conditions. +// The third axis is the component axis for the output. +void vtkImageSobel3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr, *outPtr; + int inExt[6], wholeExt[6]; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt, outExt, wholeExt); + + inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + // this filter cannot handle multi component input. + if (inData[0][0]->GetNumberOfScalarComponents() != 1) + { + vtkWarningMacro("Expecting input with only one compenent.\n"); + } + + // this filter expects that output is type double. + if (outData[0]->GetScalarType() != VTK_DOUBLE) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << ", must be double"); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageSobel3DExecute( this, inData[0][0], + (VTK_TT *)(inPtr), outData[0], outExt, + (double *)(outPtr),id, inInfo)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageSobel3D.h b/Imaging/vtkImageSobel3D.h new file mode 100644 index 0000000..6bd2ab6 --- /dev/null +++ b/Imaging/vtkImageSobel3D.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSobel3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSobel3D - Computes a vector field using sobel functions. +// .SECTION Description +// vtkImageSobel3D computes a vector field from a scalar field by using +// Sobel functions. The number of vector components is 3 because +// the input is a volume. Output is always doubles. A little creative +// liberty was used to extend the 2D sobel kernels into 3D. + + + + +#ifndef __vtkImageSobel3D_h +#define __vtkImageSobel3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageSobel3D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageSobel3D *New(); + vtkTypeRevisionMacro(vtkImageSobel3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkImageSobel3D(); + ~vtkImageSobel3D() {}; + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int outExt[6], int id); + virtual int RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + +private: + vtkImageSobel3D(const vtkImageSobel3D&); // Not implemented. + void operator=(const vtkImageSobel3D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageSpatialAlgorithm.cxx b/Imaging/vtkImageSpatialAlgorithm.cxx new file mode 100644 index 0000000..db72a7c --- /dev/null +++ b/Imaging/vtkImageSpatialAlgorithm.cxx @@ -0,0 +1,168 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSpatialAlgorithm.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSpatialAlgorithm.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageSpatialAlgorithm, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkImageSpatialAlgorithm); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageSpatialAlgorithm fitler. +vtkImageSpatialAlgorithm::vtkImageSpatialAlgorithm() +{ + this->KernelSize[0] = this->KernelSize[1] = this->KernelSize[2] = 1; + this->KernelMiddle[0] = this->KernelMiddle[1] = this->KernelMiddle[2] = 0; + this->HandleBoundaries = 1; +} + + +//---------------------------------------------------------------------------- +void vtkImageSpatialAlgorithm::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + int idx; + + os << indent << "KernelSize: (" << this->KernelSize[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->KernelSize[idx]; + } + os << ").\n"; + + os << indent << "KernelMiddle: (" << this->KernelMiddle[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->KernelMiddle[idx]; + } + os << ").\n"; + +} + +//---------------------------------------------------------------------------- +int vtkImageSpatialAlgorithm::RequestInformation ( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // Take this opportunity to override the defaults. + int extent[6]; + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent); + this->ComputeOutputWholeExtent(extent, this->HandleBoundaries); + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +// A helper method to compute output image extent +void vtkImageSpatialAlgorithm::ComputeOutputWholeExtent(int extent[6], + int handleBoundaries) +{ + int idx; + + if ( ! handleBoundaries) + { + // Make extent a little smaller because of the kernel size. + for (idx = 0; idx < 3; ++idx) + { + extent[idx*2] += this->KernelMiddle[idx]; + extent[idx*2+1] -= (this->KernelSize[idx]-1) - this->KernelMiddle[idx]; + } + } + +} + +//---------------------------------------------------------------------------- +// This method computes the extent of the input region necessary to generate +// an output region. Before this method is called "region" should have the +// extent of the output region. After this method finishes, "region" should +// have the extent of the required input region. +int vtkImageSpatialAlgorithm::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int wholeExtent[6], extent[6], inExtent[6]; + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExtent); + + this->InternalRequestUpdateExtent(extent, inExtent, wholeExtent); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkImageSpatialAlgorithm::InternalRequestUpdateExtent(int *extent, + int *inExtent, + int *wholeExtent) +{ + int idx; + for (idx = 0; idx < 3; ++idx) + { + // Magnify by strides + extent[idx*2] = inExtent[idx*2]; + extent[idx*2+1] = inExtent[idx*2+1]; + + // Expand to get inRegion Extent + extent[idx*2] -= this->KernelMiddle[idx]; + extent[idx*2+1] += (this->KernelSize[idx]-1) - this->KernelMiddle[idx]; + + // If the expanded region is out of the IMAGE Extent (grow min) + if (extent[idx*2] < wholeExtent[idx*2]) + { + if (this->HandleBoundaries) + { + // shrink the required region extent + extent[idx*2] = wholeExtent[idx*2]; + } + else + { + vtkWarningMacro(<< "Required region is out of the image extent."); + } + } + // If the expanded region is out of the IMAGE Extent (shrink max) + if (extent[idx*2+1] > wholeExtent[idx*2+1]) + { + if (this->HandleBoundaries) + { + // shrink the required region extent + extent[idx*2+1] = wholeExtent[idx*2+1]; + } + else + { + vtkWarningMacro(<< "Required region is out of the image extent."); + } + } + } +} diff --git a/Imaging/vtkImageSpatialAlgorithm.h b/Imaging/vtkImageSpatialAlgorithm.h new file mode 100644 index 0000000..4f72d39 --- /dev/null +++ b/Imaging/vtkImageSpatialAlgorithm.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSpatialAlgorithm.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSpatialAlgorithm - Filters that operate on pixel neighborhoods. +// .SECTION Description +// vtkImageSpatialAlgorithm is a super class for filters that operate on an +// input neighborhood for each output pixel. It handles even sized +// neighborhoods, but their can be a half pixel shift associated with +// processing. This superclass has some logic for handling boundaries. It +// can split regions into boundary and non-boundary pieces and call different +// execute methods. + + +#ifndef __vtkImageSpatialAlgorithm_h +#define __vtkImageSpatialAlgorithm_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageSpatialAlgorithm : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageSpatialAlgorithm *New(); + vtkTypeRevisionMacro(vtkImageSpatialAlgorithm,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the Kernel size. + int *GetKernelSize() {return this->KernelSize;} + + // Description: + // Get the Kernel middle. + int *GetKernelMiddle() {return this->KernelMiddle;} + +protected: + vtkImageSpatialAlgorithm(); + ~vtkImageSpatialAlgorithm() {}; + + int KernelSize[3]; + int KernelMiddle[3]; // Index of kernel origin + int Strides[3]; // Shrink factor + int HandleBoundaries; // Output shrinks if boundaries aren't handled + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ComputeOutputWholeExtent(int extent[6], int handleBoundaries); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void InternalRequestUpdateExtent(int *extent, int *inExtent, int *wholeExtent); + +private: + vtkImageSpatialAlgorithm(const vtkImageSpatialAlgorithm&); // Not implemented. + void operator=(const vtkImageSpatialAlgorithm&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageSpatialFilter.cxx b/Imaging/vtkImageSpatialFilter.cxx new file mode 100644 index 0000000..74614fd --- /dev/null +++ b/Imaging/vtkImageSpatialFilter.cxx @@ -0,0 +1,177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSpatialFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageSpatialFilter.h" + +#include "vtkDataArray.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkImageSpatialFilter, "$Revision: 1.52 $"); +vtkStandardNewMacro(vtkImageSpatialFilter); + +//---------------------------------------------------------------------------- +// Construct an instance of vtkImageSpatialFilter fitler. +vtkImageSpatialFilter::vtkImageSpatialFilter() +{ + this->KernelSize[0] = this->KernelSize[1] = this->KernelSize[2] = 1; + this->KernelMiddle[0] = this->KernelMiddle[1] = this->KernelMiddle[2] = 0; + this->HandleBoundaries = 1; +} + + +//---------------------------------------------------------------------------- +void vtkImageSpatialFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + int idx; + + os << indent << "KernelSize: (" << this->KernelSize[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->KernelSize[idx]; + } + os << ").\n"; + + os << indent << "KernelMiddle: (" << this->KernelMiddle[0]; + for (idx = 1; idx < 3; ++idx) + { + os << ", " << this->KernelMiddle[idx]; + } + os << ").\n"; + +} + + + +//---------------------------------------------------------------------------- +// This method is passed a region that holds the image extent of this filters +// input, and changes the region to hold the image extent of this filters +// output. +void vtkImageSpatialFilter::ExecuteInformation() +{ + vtkImageData *input = this->GetInput(); + vtkImageData *output = this->GetOutput(); + + if (!input) + { + vtkErrorMacro(<< "Input not set."); + return; + } + // Copy the defaults + output->CopyTypeSpecificInformation( input ); + + // Take this opportunity to override the defaults. + int extent[6]; + input->GetWholeExtent(extent); + this->ComputeOutputWholeExtent(extent, this->HandleBoundaries); + output->SetWholeExtent(extent); + this->ExecuteInformation(input, output); + + vtkDataArray *inArray; + inArray = input->GetPointData()->GetScalars(this->InputScalarsSelection); + if (inArray) + { + output->SetScalarType(inArray->GetDataType()); + output->SetNumberOfScalarComponents(inArray->GetNumberOfComponents()); + } +} +//---------------------------------------------------------------------------- +void vtkImageSpatialFilter::ExecuteInformation( + vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)) +{ +} + +//---------------------------------------------------------------------------- +// A helper method to compute output image extent +void vtkImageSpatialFilter::ComputeOutputWholeExtent(int extent[6], + int handleBoundaries) +{ + int idx; + + if ( ! handleBoundaries) + { + // Make extent a little smaller because of the kernel size. + for (idx = 0; idx < 3; ++idx) + { + extent[idx*2] += this->KernelMiddle[idx]; + extent[idx*2+1] -= (this->KernelSize[idx]-1) - this->KernelMiddle[idx]; + } + } + +} + + + +//---------------------------------------------------------------------------- +// This method computes the extent of the input region necessary to generate +// an output region. Before this method is called "region" should have the +// extent of the output region. After this method finishes, "region" should +// have the extent of the required input region. +void vtkImageSpatialFilter::ComputeInputUpdateExtent(int extent[6], + int inExtent[6]) +{ + int idx; + int *wholeExtent; + + if (!this->GetInput()) + { + return; + } + + wholeExtent = this->GetInput()->GetWholeExtent(); + for (idx = 0; idx < 3; ++idx) + { + // Magnify by strides + extent[idx*2] = inExtent[idx*2]; + extent[idx*2+1] = inExtent[idx*2+1]; + + // Expand to get inRegion Extent + extent[idx*2] -= this->KernelMiddle[idx]; + extent[idx*2+1] += (this->KernelSize[idx]-1) - this->KernelMiddle[idx]; + + // If the expanded region is out of the IMAGE Extent (grow min) + if (extent[idx*2] < wholeExtent[idx*2]) + { + if (this->HandleBoundaries) + { + // shrink the required region extent + extent[idx*2] = wholeExtent[idx*2]; + } + else + { + vtkWarningMacro(<< "Required region is out of the image extent."); + } + } + // If the expanded region is out of the IMAGE Extent (shrink max) + if (extent[idx*2+1] > wholeExtent[idx*2+1]) + { + if (this->HandleBoundaries) + { + // shrink the required region extent + extent[idx*2+1] = wholeExtent[idx*2+1]; + } + else + { + vtkWarningMacro(<< "Required region is out of the image extent."); + } + } + } +} + + diff --git a/Imaging/vtkImageSpatialFilter.h b/Imaging/vtkImageSpatialFilter.h new file mode 100644 index 0000000..69bca93 --- /dev/null +++ b/Imaging/vtkImageSpatialFilter.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageSpatialFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageSpatialFilter - Filters that operate on pixel neighborhoods. +// .SECTION Description +// vtkImageSpatialFilter is a super class for filters that operate on an +// input neighborhood for each output pixel. It handles even sized +// neighborhoods, but their can be a half pixel shift associated with +// processing. This superclass has some logic for handling boundaries. It +// can split regions into boundary and non-boundary pieces and call different +// execute methods. + + +#ifndef __vtkImageSpatialFilter_h +#define __vtkImageSpatialFilter_h + + +#include "vtkImageToImageFilter.h" + +class VTK_IMAGING_EXPORT vtkImageSpatialFilter : public vtkImageToImageFilter +{ +public: + static vtkImageSpatialFilter *New(); + vtkTypeRevisionMacro(vtkImageSpatialFilter,vtkImageToImageFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the Kernel size. + int *GetKernelSize() {return this->KernelSize;} + + // Description: + // Get the Kernel middle. + int *GetKernelMiddle() {return this->KernelMiddle;} + +protected: + vtkImageSpatialFilter(); + ~vtkImageSpatialFilter() {}; + + int KernelSize[3]; + int KernelMiddle[3]; // Index of kernel origin + int Strides[3]; // Shrink factor + int HandleBoundaries; // Output shrinks if boundaries aren't handled + + // Called by the superclass + void ExecuteInformation(); + // Override this method if you have to. + virtual void ExecuteInformation(vtkImageData *inData, vtkImageData *outData); + + void ComputeOutputWholeExtent(int extent[6], int handleBoundaries); + void ComputeInputUpdateExtent(int extent[6], int wholeExtent[6]); + +private: + vtkImageSpatialFilter(const vtkImageSpatialFilter&); // Not implemented. + void operator=(const vtkImageSpatialFilter&); // Not implemented. +}; + +#endif + + + + + + + + + + diff --git a/Imaging/vtkImageStencil.cxx b/Imaging/vtkImageStencil.cxx new file mode 100644 index 0000000..af74c28 --- /dev/null +++ b/Imaging/vtkImageStencil.cxx @@ -0,0 +1,408 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageStencil.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageStencil.h" + +#include "vtkImageData.h" +#include "vtkImageStencilData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageStencil, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkImageStencil); + +//---------------------------------------------------------------------------- +vtkImageStencil::vtkImageStencil() +{ + this->ReverseStencil = 0; + + this->BackgroundColor[0] = 1; + this->BackgroundColor[1] = 1; + this->BackgroundColor[2] = 1; + this->BackgroundColor[3] = 1; + this->SetNumberOfInputPorts(3); +} + +//---------------------------------------------------------------------------- +vtkImageStencil::~vtkImageStencil() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageStencil::SetStencil(vtkImageStencilData *stencil) +{ + this->SetInput(2, stencil); +} + +//---------------------------------------------------------------------------- +vtkImageStencilData *vtkImageStencil::GetStencil() +{ + if (this->GetNumberOfInputConnections(2) < 1) + { + return NULL; + } + else + { + return vtkImageStencilData::SafeDownCast( + this->GetExecutive()->GetInputData(2, 0)); + } +} + +//---------------------------------------------------------------------------- +void vtkImageStencil::SetBackgroundInput(vtkImageData *data) +{ + this->SetInput(1, data); +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageStencil::GetBackgroundInput() +{ + if (this->GetNumberOfInputConnections(1) < 1) + { + return NULL; + } + else + { + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(1, 0)); + } +} + +//---------------------------------------------------------------------------- +int vtkImageStencil::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // need to set the spacing and origin of the stencil to match the output + vtkImageStencilData *stencil = this->GetStencil(); + if (stencil) + { + stencil->SetSpacing(inInfo->Get(vtkDataObject::SPACING())); + stencil->SetOrigin(inInfo->Get(vtkDataObject::ORIGIN())); + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Some helper functions for 'ThreadedRequestData' +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// copy a pixel, advance the output pointer but not the input pointer + +template +inline void vtkCopyPixel(T *&out, const T *in, int numscalars) +{ + do + { + *out++ = *in++; + } + while (--numscalars); +} + +//---------------------------------------------------------------------------- +// Convert background color from double to appropriate type + +template +void vtkAllocBackground(vtkImageStencil *self, T *&background, + vtkInformation *outInfo) +{ + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int numComponents = output->GetNumberOfScalarComponents(); + int scalarType = output->GetScalarType(); + + background = new T[numComponents]; + + for (int i = 0; i < numComponents; i++) + { + if (i < 4) + { + if (scalarType == VTK_FLOAT || scalarType == VTK_DOUBLE) + { + background[i] = (T)self->GetBackgroundColor()[i]; + } + else + { // round float to nearest int + background[i] = (T)floor(self->GetBackgroundColor()[i] + 0.5); + } + } + else + { // all values past 4 are set to zero + background[i] = 0; + } + } +} + +//---------------------------------------------------------------------------- +template +void vtkFreeBackground(vtkImageStencil *vtkNotUsed(self), T *&background) +{ + delete [] background; + background = NULL; +} + +//---------------------------------------------------------------------------- +template +void vtkImageStencilExecute(vtkImageStencil *self, + vtkImageData *inData, T *inPtr, + vtkImageData *in2Data,T *in2Ptr, + vtkImageData *outData, T *outPtr, + int outExt[6], int id, + vtkInformation *outInfo) +{ + int numscalars, inIncX; + int idX, idY, idZ; + int r1, r2, cr1, cr2, iter, rval; + vtkIdType outIncX, outIncY, outIncZ; + int inExt[6]; + vtkIdType inInc[3]; + int in2Ext[6]; + vtkIdType in2Inc[3]; + unsigned long count = 0; + unsigned long target; + T *background, *tempPtr; + + // get the clipping extents + vtkImageStencilData *stencil = self->GetStencil(); + + // find maximum input range + inData->GetExtent(inExt); + inData->GetIncrements(inInc); + if (in2Data) + { + in2Data->GetExtent(in2Ext); + in2Data->GetIncrements(in2Inc); + } + + // Get Increments to march through data + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + numscalars = inData->GetNumberOfScalarComponents(); + + target = (unsigned long) + ((outExt[5]-outExt[4]+1)*(outExt[3]-outExt[2]+1)/50.0); + target++; + + // set color for area outside of input volume extent + vtkAllocBackground(self, background, outInfo); + + // Loop through output pixels + for (idZ = outExt[4]; idZ <= outExt[5]; idZ++) + { + for (idY = outExt[2]; idY <= outExt[3]; idY++) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + + iter = 0; + if (self->GetReverseStencil()) + { // flag that we want the complementary extents + iter = -1; + } + + cr1 = outExt[0]; + for (;;) + { + rval = 0; + r1 = outExt[1] + 1; + r2 = outExt[1]; + if (stencil) + { + rval = stencil->GetNextExtent(r1, r2, outExt[0], outExt[1], + idY, idZ, iter); + } + else if (iter < 0) + { + r1 = outExt[0]; + r2 = outExt[1]; + rval = 1; + iter = 1; + } + + tempPtr = background; + inIncX = 0; + if (in2Ptr) + { + tempPtr = in2Ptr + (in2Inc[2]*(idZ - in2Ext[4]) + + in2Inc[1]*(idY - in2Ext[2]) + + numscalars*(cr1 - in2Ext[0])); + inIncX = numscalars; + } + + cr2 = r1 - 1; + for (idX = cr1; idX <= cr2; idX++) + { + vtkCopyPixel(outPtr, tempPtr, numscalars); + tempPtr += inIncX; + } + cr1 = r2 + 1; // for next time 'round + + // break if no foreground extents left + if (rval == 0) + { + break; + } + + tempPtr = inPtr + (inInc[2]*(idZ - inExt[4]) + + inInc[1]*(idY - inExt[2]) + + numscalars*(r1 - inExt[0])); + + for (idX = r1; idX <= r2; idX++) + { + vtkCopyPixel(outPtr, tempPtr, numscalars); + tempPtr += numscalars; + } + } + outPtr += outIncY; + } + outPtr += outIncZ; + } + + vtkFreeBackground(self, background); +} + +//---------------------------------------------------------------------------- +void vtkImageStencil::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + void *inPtr, *inPtr2; + void *outPtr; + vtkImageData *inData2 = this->GetBackgroundInput(); + + inPtr = inData[0][0]->GetScalarPointer(); + outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inPtr2 = NULL; + if (inData2) + { + inPtr2 = inData2->GetScalarPointer(); + if (inData2->GetScalarType() != inData[0][0]->GetScalarType()) + { + if (id == 0) + { + vtkErrorMacro("Execute: BackgroundInput ScalarType " + << inData2->GetScalarType() + << ", must match Input ScalarType " + << inData[0][0]->GetScalarType()); + } + return; + } + else if (inData2->GetNumberOfScalarComponents() + != inData[0][0]->GetNumberOfScalarComponents()) + { + if (id == 0) + { + vtkErrorMacro("Execute: BackgroundInput NumberOfScalarComponents " + << inData2->GetNumberOfScalarComponents() + << ", must match Input NumberOfScalarComponents " + << inData[0][0]->GetNumberOfScalarComponents()); + } + return; + } + int wholeExt1[6], wholeExt2[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *inInfo2 = inputVector[1]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExt1); + inInfo2->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExt2); + + for (int i = 0; i < 6; i++) + { + if (wholeExt1[i] != wholeExt2[i]) + { + if (id == 0) + { + vtkErrorMacro("Execute: BackgroundInput must have the same " + "WholeExtent as the Input"); + } + return; + } + } + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageStencilExecute( this, + inData[0][0], + (VTK_TT *)(inPtr), + inData2, + (VTK_TT *)(inPtr2), + outData[0], + (VTK_TT *)(outPtr), + outExt, + id, + outInfo) ); + default: + vtkErrorMacro("Execute: Unknown ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkImageStencil::FillInputPortInformation(int port, vtkInformation* info) +{ + if (port == 2) + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageStencilData"); + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + else + { + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + if (port == 1) + { + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + } + } + return 1; +} + +void vtkImageStencil::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Stencil: " << this->GetStencil() << "\n"; + os << indent << "ReverseStencil: " << (this->ReverseStencil ? + "On\n" : "Off\n"); + + os << indent << "BackgroundInput: " << this->GetBackgroundInput() << "\n"; + os << indent << "BackgroundValue: " << this->BackgroundColor[0] << "\n"; + + os << indent << "BackgroundColor: (" << this->BackgroundColor[0] << ", " + << this->BackgroundColor[1] << ", " + << this->BackgroundColor[2] << ", " + << this->BackgroundColor[3] << ")\n"; +} diff --git a/Imaging/vtkImageStencil.h b/Imaging/vtkImageStencil.h new file mode 100644 index 0000000..f480d7f --- /dev/null +++ b/Imaging/vtkImageStencil.h @@ -0,0 +1,90 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageStencil.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageStencil - combine images via a cookie-cutter operation +// .SECTION Description +// vtkImageStencil will combine two images together using a stencil. +// The stencil should be provided in the form of a vtkImageStencilData, + + +#ifndef __vtkImageStencil_h +#define __vtkImageStencil_h + +#include "vtkThreadedImageAlgorithm.h" + +class vtkImageStencilData; + +class VTK_IMAGING_EXPORT vtkImageStencil : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageStencil *New(); + vtkTypeRevisionMacro(vtkImageStencil, vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the stencil to use. The stencil can be created + // from a vtkImplicitFunction or a vtkPolyData. + virtual void SetStencil(vtkImageStencilData *stencil); + vtkImageStencilData *GetStencil(); + + // Description: + // Reverse the stencil. + vtkSetMacro(ReverseStencil, int); + vtkBooleanMacro(ReverseStencil, int); + vtkGetMacro(ReverseStencil, int); + + // Description: + // NOTE: Not yet implemented, use SetBackgroundValue instead. + // Set the second input. This image will be used for the 'outside' of the + // stencil. If not set, the output voxels will be filled with + // BackgroundValue instead. + virtual void SetBackgroundInput(vtkImageData *input); + vtkImageData *GetBackgroundInput(); + + // Description: + // Set the default output value to use when the second input is not set. + void SetBackgroundValue(double val) { + this->SetBackgroundColor(val,val,val,val); }; + double GetBackgroundValue() { + return this->BackgroundColor[0]; }; + + // Description: + // Set the default color to use when the second input is not set. + // This is like SetBackgroundValue, but for multi-component images. + vtkSetVector4Macro(BackgroundColor, double); + vtkGetVector4Macro(BackgroundColor, double); + +protected: + vtkImageStencil(); + ~vtkImageStencil(); + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + + int ReverseStencil; + double BackgroundColor[4]; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkImageStencil(const vtkImageStencil&); // Not implemented. + void operator=(const vtkImageStencil&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageStencilData.cxx b/Imaging/vtkImageStencilData.cxx new file mode 100644 index 0000000..88afd8b --- /dev/null +++ b/Imaging/vtkImageStencilData.cxx @@ -0,0 +1,491 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageStencilData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageStencilData.h" + +#include "vtkImageStencilSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkImageStencilData, "$Revision: 1.15.6.1 $"); +vtkStandardNewMacro(vtkImageStencilData); + +//---------------------------------------------------------------------------- +vtkImageStencilData::vtkImageStencilData() +{ + this->Spacing[0] = this->OldSpacing[0] = 1; + this->Spacing[1] = this->OldSpacing[1] = 1; + this->Spacing[2] = this->OldSpacing[2] = 1; + + this->Origin[0] = this->OldOrigin[0] = 0; + this->Origin[1] = this->OldOrigin[1] = 0; + this->Origin[2] = this->OldOrigin[2] = 0; + + this->NumberOfExtentEntries = 0; + this->ExtentLists = NULL; + this->ExtentListLengths = NULL; + + int extent[6] = {0, -1, 0, -1, 0, -1}; + memcpy(this->Extent, extent, 6*sizeof(int)); + this->Information->Set(vtkDataObject::DATA_EXTENT_TYPE(), VTK_3D_EXTENT); + this->Information->Set(vtkDataObject::DATA_EXTENT(), this->Extent, 6); +} + +//---------------------------------------------------------------------------- +vtkImageStencilData::~vtkImageStencilData() +{ + this->Initialize(); +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + int extent[6]; + this->GetExtent(extent); + + os << indent << "Extent: (" + << extent[0] << ", " + << extent[1] << ", " + << extent[2] << ", " + << extent[3] << ", " + << extent[4] << ", " + << extent[5] << ")\n"; + + os << indent << "Spacing: (" + << this->Spacing[0] << ", " + << this->Spacing[1] << ", " + << this->Spacing[2] << ")\n"; + + os << indent << "Origin: (" + << this->Origin[0] << ", " + << this->Origin[1] << ", " + << this->Origin[2] << ")\n"; + + os << indent << "OldSpacing: (" + << this->OldSpacing[0] << ", " + << this->OldSpacing[1] << ", " + << this->OldSpacing[2] << ")\n"; + + os << indent << "OldOrigin: (" + << this->OldOrigin[0] << ", " + << this->OldOrigin[1] << ", " + << this->OldOrigin[2] << ")\n"; +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::Initialize() +{ + if (this->ExtentLists) + { + int n = this->NumberOfExtentEntries; + for (int i = 0; i < n; i++) + { + delete [] this->ExtentLists[i]; + } + delete [] this->ExtentLists; + } + this->ExtentLists = NULL; + this->NumberOfExtentEntries = 0; + + if (this->ExtentListLengths) + { + delete [] this->ExtentListLengths; + } + this->ExtentListLengths = NULL; + + if(this->Information) + { + int extent[6] = {0, -1, 0, -1, 0, -1}; + memcpy(this->Extent, extent, 6*sizeof(int)); + } +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::SetExtent(int* extent) +{ + memcpy(this->Extent, extent, 6*sizeof(int)); +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::SetExtent(int x1, int x2, int y1, int y2, int z1, int z2) +{ + int ext[6]; + ext[0] = x1; + ext[1] = x2; + ext[2] = y1; + ext[3] = y2; + ext[4] = z1; + ext[5] = z2; + this->SetExtent(ext); +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::ShallowCopy(vtkDataObject *o) +{ + vtkImageStencilData *s = vtkImageStencilData::SafeDownCast(o); + + if (s) + { + this->InternalImageStencilDataCopy(s); + } + + vtkDataObject::ShallowCopy(o); +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::DeepCopy(vtkDataObject *o) +{ + vtkImageStencilData *s = vtkImageStencilData::SafeDownCast(o); + + if (s) + { + this->InternalImageStencilDataCopy(s); + } + + vtkDataObject::DeepCopy(o); +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::InternalImageStencilDataCopy(vtkImageStencilData *s) +{ + // copy information that accompanies the data + this->SetSpacing(s->Spacing); + this->SetOrigin(s->Origin); + + // delete old data + if (this->ExtentLists) + { + int n = this->NumberOfExtentEntries; + for (int i = 0; i < n; i++) + { + delete [] this->ExtentLists[i]; + } + delete [] this->ExtentLists; + } + this->ExtentLists = NULL; + this->NumberOfExtentEntries = 0; + + if (this->ExtentListLengths) + { + delete [] this->ExtentListLengths; + } + this->ExtentListLengths = NULL; + + // copy new data + if (s->NumberOfExtentEntries != 0) + { + this->NumberOfExtentEntries = s->NumberOfExtentEntries; + int n = this->NumberOfExtentEntries; + this->ExtentListLengths = new int[n]; + this->ExtentLists = new int *[n]; + for (int i = 0; i < n; i++) + { + this->ExtentListLengths[i] = s->ExtentListLengths[i]; + int m = this->ExtentListLengths[i]; + this->ExtentLists[i] = new int[m]; + for (int j = 0; j < m; j++) + { + this->ExtentLists[i][j] = s->ExtentLists[i][j]; + } + } + } + memcpy(this->Extent, s->GetExtent(), 6*sizeof(int)); +} + +//---------------------------------------------------------------------------- +// Override from vtkDataObject because we have to handle the Spacing +// and Origin as well as the UpdateExtent. +void vtkImageStencilData::PropagateUpdateExtent() +{ +#if 0 + // If we need to update due to PipelineMTime, or the fact that our + // data was released, then propagate the update extent to the source + // if there is one. + if ( this->UpdateTime < this->PipelineMTime || this->DataReleased || + this->UpdateExtentIsOutsideOfTheExtent() || + this->SpacingOrOriginHasChanged() || + this->LastUpdateExtentWasOutsideOfTheExtent) + { + if (this->Source) + { + this->Source->PropagateUpdateExtent(this); + } + } + + // update the value of this ivar + this->LastUpdateExtentWasOutsideOfTheExtent = + this->UpdateExtentIsOutsideOfTheExtent(); +#else + this->Superclass::PropagateUpdateExtent(); +#endif +} + +//---------------------------------------------------------------------------- +// Override from vtkDataObject because we have to handle the Spacing +// and Origin as well as the UpdateExtent. +void vtkImageStencilData::TriggerAsynchronousUpdate() +{ +#if 0 + // If we need to update due to PipelineMTime, or the fact that our + // data was released, then propagate the trigger to the source + // if there is one. + if ( this->UpdateTime < this->PipelineMTime || this->DataReleased || + this->UpdateExtentIsOutsideOfTheExtent() || + this->SpacingOrOriginHasChanged()) + { + if (this->Source) + { + this->Source->TriggerAsynchronousUpdate(); + } + } +#else + this->Superclass::TriggerAsynchronousUpdate(); +#endif +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::UpdateData() +{ +#if 0 + // If we need to update due to PipelineMTime, or the fact that our + // data was released, then propagate the UpdateData to the source + // if there is one. + if (this->UpdateTime < this->PipelineMTime || this->DataReleased || + this->UpdateExtentIsOutsideOfTheExtent() || + this->SpacingOrOriginHasChanged()) + { + if (this->Source) + { + this->Source->UpdateData(this); + } + } +#else + this->Superclass::UpdateData(); +#endif +} + +//---------------------------------------------------------------------------- +int vtkImageStencilData::SpacingOrOriginHasChanged() +{ + double *spacing = this->Spacing; + double *origin = this->Origin; + double *ospacing = this->OldSpacing; + double *oorigin = this->OldOrigin; + + return (spacing[0] != ospacing[0] || origin[0] != oorigin[0] || + spacing[1] != ospacing[1] || origin[1] != oorigin[1] || + spacing[2] != ospacing[2] || origin[2] != oorigin[2]); +} + +//---------------------------------------------------------------------------- +void vtkImageStencilData::AllocateExtents() +{ + int extent[6]; + this->GetExtent(extent); + int numEntries = (extent[3] - extent[2] + 1)*(extent[5] - extent[4] + 1); + + if (numEntries != this->NumberOfExtentEntries) + { + if (this->NumberOfExtentEntries != 0) + { + int n = this->NumberOfExtentEntries; + for (int i = 0; i < n; i++) + { + delete [] this->ExtentLists[i]; + } + delete [] this->ExtentLists; + delete [] this->ExtentListLengths; + } + + this->NumberOfExtentEntries = numEntries; + this->ExtentLists = NULL; + this->ExtentListLengths = NULL; + + if (numEntries) + { + this->ExtentLists = new int *[numEntries]; + this->ExtentListLengths = new int[numEntries]; + for (int i = 0; i < numEntries; i++) + { + this->ExtentListLengths[i] = 0; + this->ExtentLists[i] = NULL; + } + } + } + else + { + for (int i = 0; i < numEntries; i++) + { + if (this->ExtentListLengths[i] != 0) + { + this->ExtentListLengths[i] = 0; + delete this->ExtentLists[i]; + this->ExtentLists[i] = NULL; + } + } + } +} + +//---------------------------------------------------------------------------- +// Given the output x extent [rmin,rmax] and the current y, z indices, +// return the sub extents [r1,r2] for which transformation/interpolation +// are to be done. The variable 'iter' should be initialized to zero +// before the first call. The return value is zero if there are no +// extents remaining. +int vtkImageStencilData::GetNextExtent(int &r1, int &r2, + int rmin, int rmax, + int yIdx, int zIdx, int &iter) +{ + int extent[6]; + this->GetExtent(extent); + int yExt = extent[3] - extent[2] + 1; + int zExt = extent[5] - extent[4] + 1; + yIdx -= extent[2]; + zIdx -= extent[4]; + + // initialize r1, r2 to defaults + r1 = rmax + 1; + r2 = rmax; + + if (yIdx < 0 || yIdx >= yExt || zIdx < 0 || zIdx >= zExt) + { // out-of-bounds in y or z, use null extent + return 0; + } + + // get the ExtentList and ExtentListLength for this yIdx,zIdx + int incr = zIdx*yExt + yIdx; + int *clist = this->ExtentLists[incr]; + int clistlen = this->ExtentListLengths[incr]; + + if (iter <= 0) + { + int state = 1; // start outside + if (iter < 0) // unless iter is negative at start + { + iter = 0; + state = -1; + } + + r1 = VTK_INT_MIN; + for ( ; iter < clistlen; iter++) + { + if (clist[iter] >= rmin) + { + if (state > 0) + { + r1 = clist[iter++]; + } + break; + } + state = -state; + } + if (r1 == VTK_INT_MIN) + { + r1 = rmin; + if (state > 0) + { + r1 = rmax + 1; + } + } + } + else + { + if (iter >= clistlen) + { + return 0; + } + r1 = clist[iter++]; + } + + if (r1 > rmax) + { + r1 = rmax + 1; + return 0; + } + + if (iter >= clistlen) + { + return 1; + } + + r2 = clist[iter++] - 1; + + if (r2 > rmax) + { + r2 = rmax; + } + + return 1; +} + +//---------------------------------------------------------------------------- +// Insert a sub extent [r1,r2] on to the list for the x row at (yIdx,zIdx). +void vtkImageStencilData::InsertNextExtent(int r1, int r2, int yIdx, int zIdx) +{ + // calculate the index into the extent array + int extent[6]; + this->GetExtent(extent); + int yExt = extent[3] - extent[2] + 1; + int incr = (zIdx - extent[4])*yExt + (yIdx - extent[2]); + + int &clistlen = this->ExtentListLengths[incr]; + int *&clist = this->ExtentLists[incr]; + + if (clistlen == 0) + { // no space has been allocated yet + clist = new int[2]; + } + else + { // check whether more space is needed + // the allocated space is always the smallest power of two + // that is not less than the number of stored items, therefore + // we need to allocate space when clistlen is a power of two + int clistmaxlen = 2; + while (clistlen > clistmaxlen) + { + clistmaxlen *= 2; + } + if (clistmaxlen == clistlen) + { // need to allocate more space + clistmaxlen *= 2; + int *newclist = new int[clistmaxlen]; + for (int k = 0; k < clistlen; k++) + { + newclist[k] = clist[k]; + } + delete [] clist; + clist = newclist; + } + } + + clist[clistlen++] = r1; + clist[clistlen++] = r2 + 1; +} + +//---------------------------------------------------------------------------- +vtkImageStencilData* vtkImageStencilData::GetData(vtkInformation* info) +{ + return info? vtkImageStencilData::SafeDownCast(info->Get(DATA_OBJECT())) : 0; +} + +//---------------------------------------------------------------------------- +vtkImageStencilData* vtkImageStencilData::GetData(vtkInformationVector* v, + int i) +{ + return vtkImageStencilData::GetData(v->GetInformationObject(i)); +} diff --git a/Imaging/vtkImageStencilData.h b/Imaging/vtkImageStencilData.h new file mode 100644 index 0000000..59e0ff2 --- /dev/null +++ b/Imaging/vtkImageStencilData.h @@ -0,0 +1,179 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageStencilData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageStencilData - efficient description of an image stencil +// .SECTION Description +// vtkImageStencilData describes an image stencil in a manner which is +// efficient both in terms of speed and storage space. The stencil extents +// are stored for each x-row across the image (multiple extents per row if +// necessary) and can be retrieved via the GetNextExtent() method. +// .SECTION see also +// vtkImageStencilSource vtkImageStencil + +#ifndef __vtkImageStencilData_h +#define __vtkImageStencilData_h + + +#include "vtkDataObject.h" + +class VTK_IMAGING_EXPORT vtkImageStencilData : public vtkDataObject +{ +public: + static vtkImageStencilData *New(); + vtkTypeRevisionMacro(vtkImageStencilData, vtkDataObject); + void PrintSelf(ostream& os, vtkIndent indent); + + void Initialize(); + void DeepCopy(vtkDataObject *o); + void ShallowCopy(vtkDataObject *f); + void InternalImageStencilDataCopy(vtkImageStencilData *s); + + // Description: + // Get the data type as an integer (this will return VTK_DATA_OBJECT + // for now, maybe a proper type constant will be reserved later). + int GetDataObjectType() { return VTK_DATA_OBJECT; } + + // Description: + // The extent type is 3D, just like vtkImageData. + int GetExtentType() { return VTK_3D_EXTENT; }; + + // Description: + // Given the total output x extent [xMin,xMax] and the current y, z indices, + // return each sub-extent [r1,r2] that lies within within the unclipped + // region in sequence. A value of '0' is returned if no more sub-extents + // are available. The variable 'iter' must be initialized to zero before + // the first call, unless you want the complementary sub-extents in which + // case you must initialize 'iter' to -1. The variable 'iter' is used + // internally to keep track of which sub-extent should be returned next. + int GetNextExtent(int &r1, int &r2, int xMin, int xMax, + int yIdx, int zIdx, int &iter); + + // Description: + // This method is used by vtkImageStencilDataSource to add an x + // sub extent [r1,r2] for the x row (yIdx,zIdx). The specified sub + // extent must not intersect any other sub extents along the same x row. + // As well, r1 and r2 must both be within the total x extent + // [Extent[0],Extent[1]]. + void InsertNextExtent(int r1, int r2, int yIdx, int zIdx); + + // Description: + // Set the desired spacing for the stencil. + // This must be called before the stencil is Updated, ideally + // in the ExecuteInformation method of the imaging filter that + // is using the stencil. + vtkSetVector3Macro(Spacing, double); + vtkGetVector3Macro(Spacing, double); + + // Description: + // Set the desired origin for the stencil. + // This must be called before the stencil is Updated, ideally + // in the ExecuteInformation method of the imaging filter that + // is using the stencil. + vtkSetVector3Macro(Origin, double); + vtkGetVector3Macro(Origin, double); + + // Description: + // Set the extent of the data. This is should be called only + // by vtkImageStencilSource, as it is part of the basic pipeline + // functionality. + void SetExtent(int extent[6]); + void SetExtent(int x1, int x2, int y1, int y2, int z1, int z2); + vtkGetVector6Macro(Extent, int); + + // Description: + // Save the previous data spacing. This should be called only by + // vtkImageStencilSource. + vtkSetVector3Macro(OldSpacing, double); + vtkGetVector3Macro(OldSpacing, double); + + // Description: + // Save the previous data origin. This should be called only by + // vtkImageStencilSource. + vtkSetVector3Macro(OldOrigin, double); + vtkGetVector3Macro(OldOrigin, double); + + // Description: + // Allocate space for the sub-extents. This is called by + // vtkImageStencilSource. + void AllocateExtents(); + + // Description: + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE. + // THIS METHOD IS PART OF THE PIPELINE UPDATE FUNCTIONALITY. + // Propagate the update back up the pipeline, and perform the actual + // work of updating on the way down. When the propagate arrives at a + // port, block and wait for the asynchronous update to finish on the + // other side. + // This propagation may early terminate based on the PipelineMTime. + void UpdateData(); + + // Description: + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE. + // THIS METHOD IS PART OF THE PIPELINE UPDATE FUNCTIONALITY. + // The update extent for this object is propagated up the pipeline. + // This propagation may early terminate based on the PipelineMTime. + void PropagateUpdateExtent(); + + // Description: + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE. + // THIS METHOD IS PART OF THE PIPELINE UPDATE FUNCTIONALITY. + // Propagate back up the pipeline for ports and trigger the update on the + // other side of the port to allow for asynchronous parallel processing in + // the pipeline. + // This propagation may early terminate based on the PipelineMTime. + void TriggerAsynchronousUpdate(); + + //BTX + // Description: + // Retrieve an instance of this class from an information object. + static vtkImageStencilData* GetData(vtkInformation* info); + static vtkImageStencilData* GetData(vtkInformationVector* v, int i=0); + //ETX + +protected: + vtkImageStencilData(); + ~vtkImageStencilData(); + + // Description: + // Check to see of the Spacing and Origin are different + // from the OldSpacing and OldOrigin. + int SpacingOrOriginHasChanged(); + + // Description: + // Previous Spacing and Origin values, so that it is possible to + // know when an update is required because they have changed. + double OldSpacing[3]; + double OldOrigin[3]; + + // Description: + // The Spacing and Origin of the data. + double Spacing[3]; + double Origin[3]; + + int Extent[6]; + + // Description: + // The actual 'data' is stored here. + int NumberOfExtentEntries; + int *ExtentListLengths; + int **ExtentLists; +private: + vtkImageStencilData(const vtkImageStencilData&); // Not implemented. + void operator=(const vtkImageStencilData&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageStencilSource.cxx b/Imaging/vtkImageStencilSource.cxx new file mode 100644 index 0000000..aaadf06 --- /dev/null +++ b/Imaging/vtkImageStencilSource.cxx @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageStencilSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageStencilSource.h" + +#include "vtkImageStencilData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageStencilSource, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkImageStencilSource); + +//---------------------------------------------------------------------------- +vtkImageStencilSource::vtkImageStencilSource() +{ + this->SetNumberOfInputPorts(1); + this->SetNumberOfOutputPorts(1); + + vtkImageStencilData *output = vtkImageStencilData::New(); + this->GetExecutive()->SetOutputData(0, output); + // Releasing data for pipeline parallism. + // Filters will know it is empty. + output->ReleaseData(); + output->Delete(); +} + +//---------------------------------------------------------------------------- +vtkImageStencilSource::~vtkImageStencilSource() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageStencilSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +void vtkImageStencilSource::SetOutput(vtkImageStencilData *output) +{ + this->GetExecutive()->SetOutputData(0, output); +} + +//---------------------------------------------------------------------------- +vtkImageStencilData *vtkImageStencilSource::GetOutput() +{ + if (this->GetNumberOfOutputPorts() < 1) + { + return NULL; + } + + return vtkImageStencilData::SafeDownCast( + this->GetExecutive()->GetOutputData(0)); +} + +//---------------------------------------------------------------------------- +vtkImageStencilData * +vtkImageStencilSource::AllocateOutputData(vtkDataObject *out, int* uExt) +{ + vtkImageStencilData *res = vtkImageStencilData::SafeDownCast(out); + if (!res) + { + vtkWarningMacro("Call to AllocateOutputData with non vtkImageStencilData" + " output"); + return NULL; + } + res->SetExtent(uExt); + res->SetOldSpacing(res->GetSpacing()); + res->SetOldOrigin(res->GetOrigin()); + res->AllocateExtents(); + + return res; +} + +//---------------------------------------------------------------------------- +int vtkImageStencilSource::RequestData( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataObject *out = outInfo->Get(vtkDataObject::DATA_OBJECT()); + this->AllocateOutputData( + out, + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT())); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageStencilSource::FillOutputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageStencilData"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageStencilSource::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->RequestData(request, inputVector, outputVector); + return 1; + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + this->RequestInformation(request, inputVector, outputVector); + return 1; + } + + if (request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + this->RequestUpdateExtent(request, inputVector, outputVector); + return 1; + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} diff --git a/Imaging/vtkImageStencilSource.h b/Imaging/vtkImageStencilSource.h new file mode 100644 index 0000000..fe374a7 --- /dev/null +++ b/Imaging/vtkImageStencilSource.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageStencilSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageStencilSource - helper class for clipping images +// .SECTION Description +// vtkImageStencilSource is a helper class for vtkImageToImageFilter +// classes. Given a clipping object such as a vtkImplicitFunction, it +// will set up a list of clipping extents for each x-row through the +// image data. The extents for each x-row can be retrieved via the +// GetNextExtent() method after the extent lists have been built +// with the BuildExtents() method. For large images, using clipping +// extents is much more memory efficient (and slightly more time-efficient) +// than building a mask. This class can be subclassed to allow clipping +// with objects other than vtkImplicitFunction. +// .SECTION see also +// vtkImplicitFunction vtkImageStencil vtkPolyDataToImageStencil + +#ifndef __vtkImageStencilSource_h +#define __vtkImageStencilSource_h + + +#include "vtkAlgorithm.h" + +class vtkImageStencilData; + +class VTK_IMAGING_EXPORT vtkImageStencilSource : public vtkAlgorithm +{ +public: + static vtkImageStencilSource *New(); + vtkTypeRevisionMacro(vtkImageStencilSource, vtkAlgorithm); + + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get or set the output for this source. + void SetOutput(vtkImageStencilData *output); + vtkImageStencilData *GetOutput(); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkImageStencilSource(); + ~vtkImageStencilSource(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, + vtkInformationVector *) { return 1; } + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, + vtkInformationVector *) { return 1; } + vtkImageStencilData *AllocateOutputData(vtkDataObject *out, int* updateExt); + + virtual int FillOutputPortInformation(int, vtkInformation*); +private: + vtkImageStencilSource(const vtkImageStencilSource&); // Not implemented. + void operator=(const vtkImageStencilSource&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageThreshold.cxx b/Imaging/vtkImageThreshold.cxx new file mode 100644 index 0000000..fea0d9d --- /dev/null +++ b/Imaging/vtkImageThreshold.cxx @@ -0,0 +1,316 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageThreshold.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageThreshold.h" + +#include "vtkImageData.h" +#include "vtkImageProgressIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkDataSetAttributes.h" + +vtkCxxRevisionMacro(vtkImageThreshold, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkImageThreshold); + +//---------------------------------------------------------------------------- +// Constructor sets default values +vtkImageThreshold::vtkImageThreshold() +{ + this->UpperThreshold = VTK_LARGE_FLOAT; + this->LowerThreshold = -VTK_LARGE_FLOAT; + this->ReplaceIn = 0; + this->InValue = 0.0; + this->ReplaceOut = 0; + this->OutValue = 0.0; + + this->OutputScalarType = -1; // invalid; output same as input +} + +//---------------------------------------------------------------------------- +void vtkImageThreshold::SetInValue(double val) +{ + if (val != this->InValue || this->ReplaceIn != 1) + { + this->InValue = val; + this->ReplaceIn = 1; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageThreshold::SetOutValue(double val) +{ + if (val != this->OutValue || this->ReplaceOut != 1) + { + this->OutValue = val; + this->ReplaceOut = 1; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// The values greater than or equal to the value match. +void vtkImageThreshold::ThresholdByUpper(double thresh) +{ + if (this->LowerThreshold != thresh || this->UpperThreshold < VTK_LARGE_FLOAT) + { + this->LowerThreshold = thresh; + this->UpperThreshold = VTK_LARGE_FLOAT; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// The values less than or equal to the value match. +void vtkImageThreshold::ThresholdByLower(double thresh) +{ + if (this->UpperThreshold != thresh || this->LowerThreshold > -VTK_LARGE_FLOAT) + { + this->UpperThreshold = thresh; + this->LowerThreshold = -VTK_LARGE_FLOAT; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// The values in a range (inclusive) match +void vtkImageThreshold::ThresholdBetween(double lower, double upper) +{ + if (this->LowerThreshold != lower || this->UpperThreshold != upper) + { + this->LowerThreshold = lower; + this->UpperThreshold = upper; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkImageThreshold::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + if (this->OutputScalarType == -1) + { + // This information already copied from input to output in CopyInformationToPipeline? + vtkInformation *inScalarInfo = vtkDataObject::GetActiveFieldInformation(inInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + if (!inScalarInfo) + { + vtkErrorMacro("Missing scalar field on input information!"); + return 0; + } + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, + inScalarInfo->Get( vtkDataObject::FIELD_ARRAY_TYPE() ), -1 ); + } + else + { + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->OutputScalarType, -1); + } + return 1; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageThresholdExecute(vtkImageThreshold *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, IT *, OT *) +{ + vtkImageIterator inIt(inData, outExt); + vtkImageProgressIterator outIt(outData, outExt, self, id); + IT lowerThreshold; + IT upperThreshold; + int replaceIn = self->GetReplaceIn(); + OT inValue; + int replaceOut = self->GetReplaceOut(); + OT outValue; + IT temp; + + // Make sure the thresholds are valid for the input scalar range + if (static_cast(self->GetLowerThreshold()) < inData->GetScalarTypeMin()) + { + lowerThreshold = (IT) inData->GetScalarTypeMin(); + } + else + { + if (static_cast(self->GetLowerThreshold()) > + inData->GetScalarTypeMax()) + { + lowerThreshold = (IT) inData->GetScalarTypeMax(); + } + else + { + lowerThreshold = (IT) self->GetLowerThreshold(); + } + } + if (static_cast(self->GetUpperThreshold()) + > inData->GetScalarTypeMax()) + { + upperThreshold = (IT) inData->GetScalarTypeMax(); + } + else + { + if (static_cast(self->GetUpperThreshold()) + < inData->GetScalarTypeMin()) + { + upperThreshold = (IT) inData->GetScalarTypeMin(); + } + else + { + upperThreshold = (IT) self->GetUpperThreshold(); + } + } + + // Make sure the replacement values are within the output scalar range + if (static_cast(self->GetInValue()) < outData->GetScalarTypeMin()) + { + inValue = (OT) outData->GetScalarTypeMin(); + } + else + { + if (static_cast(self->GetInValue()) > outData->GetScalarTypeMax()) + { + inValue = (OT) outData->GetScalarTypeMax(); + } + else + { + inValue = (OT) self->GetInValue(); + } + } + if (static_cast(self->GetOutValue()) > outData->GetScalarTypeMax()) + { + outValue = (OT) outData->GetScalarTypeMax(); + } + else + { + if (static_cast(self->GetOutValue()) < outData->GetScalarTypeMin()) + { + outValue = (OT) outData->GetScalarTypeMin(); + } + else + { + outValue = (OT) self->GetOutValue(); + } + } + + // Loop through output pixels + while (!outIt.IsAtEnd()) + { + IT* inSI = inIt.BeginSpan(); + OT* outSI = outIt.BeginSpan(); + OT* outSIEnd = outIt.EndSpan(); + while (outSI != outSIEnd) + { + // Pixel operation + temp = (*inSI); + if (lowerThreshold <= temp && temp <= upperThreshold) + { + // match + if (replaceIn) + { + *outSI = inValue; + } + else + { + *outSI = (OT)(temp); + } + } + else + { + // not match + if (replaceOut) + { + *outSI = outValue; + } + else + { + *outSI = (OT)(temp); + } + } + ++inSI; + ++outSI; + } + inIt.NextSpan(); + outIt.NextSpan(); + } +} + +//---------------------------------------------------------------------------- +template +void vtkImageThresholdExecute1(vtkImageThreshold *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], int id, T *) +{ + switch (outData->GetScalarType()) + { + vtkTemplateMacro( + vtkImageThresholdExecute( self, inData, + outData, outExt, id, + static_cast(0), + static_cast(0))); + default: + vtkGenericWarningMacro("Execute: Unknown input ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +// This method is passed a input and output data, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the datas data types. +void vtkImageThreshold::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageThresholdExecute1( this, + inData[0][0], + outData[0], + outExt, + id, + static_cast(0) )); + default: + vtkErrorMacro(<< "Execute: Unknown input ScalarType"); + return; + } +} + +void vtkImageThreshold::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "OutputScalarType: " << this->OutputScalarType << "\n"; + os << indent << "InValue: " << this->InValue << "\n"; + os << indent << "OutValue: " << this->OutValue << "\n"; + os << indent << "LowerThreshold: " << this->LowerThreshold << "\n"; + os << indent << "UpperThreshold: " << this->UpperThreshold << "\n"; + os << indent << "ReplaceIn: " << this->ReplaceIn << "\n"; + os << indent << "ReplaceOut: " << this->ReplaceOut << "\n"; +} diff --git a/Imaging/vtkImageThreshold.h b/Imaging/vtkImageThreshold.h new file mode 100644 index 0000000..d068fd3 --- /dev/null +++ b/Imaging/vtkImageThreshold.h @@ -0,0 +1,130 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageThreshold.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageThreshold - Flexible threshold +// .SECTION Description +// vtkImageThreshold Can do binary or continuous thresholding for lower, upper +// or a range of data. The output data type may be different than the +// output, but defaults to the same type. + + +#ifndef __vtkImageThreshold_h +#define __vtkImageThreshold_h + + +#include "vtkThreadedImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageThreshold : public vtkThreadedImageAlgorithm +{ +public: + static vtkImageThreshold *New(); + vtkTypeRevisionMacro(vtkImageThreshold,vtkThreadedImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The values greater than or equal to the value match. + void ThresholdByUpper(double thresh); + + // Description: + // The values less than or equal to the value match. + void ThresholdByLower(double thresh); + + // Description: + // The values in a range (inclusive) match + void ThresholdBetween(double lower, double upper); + + // Description: + // Determines whether to replace the pixel in range with InValue + vtkSetMacro(ReplaceIn, int); + vtkGetMacro(ReplaceIn, int); + vtkBooleanMacro(ReplaceIn, int); + + // Description: + // Replace the in range pixels with this value. + void SetInValue(double val); + vtkGetMacro(InValue, double); + + // Description: + // Determines whether to replace the pixel out of range with OutValue + vtkSetMacro(ReplaceOut, int); + vtkGetMacro(ReplaceOut, int); + vtkBooleanMacro(ReplaceOut, int); + + // Description: + // Replace the in range pixels with this value. + void SetOutValue(double val); + vtkGetMacro(OutValue, double); + + // Description: + // Get the Upper and Lower thresholds. + vtkGetMacro(UpperThreshold, double); + vtkGetMacro(LowerThreshold, double); + + // Description: + // Set the desired output scalar type to cast to + vtkSetMacro(OutputScalarType, int); + vtkGetMacro(OutputScalarType, int); + void SetOutputScalarTypeToDouble() + {this->SetOutputScalarType(VTK_DOUBLE);} + void SetOutputScalarTypeToFloat() + {this->SetOutputScalarType(VTK_FLOAT);} + void SetOutputScalarTypeToLong() + {this->SetOutputScalarType(VTK_LONG);} + void SetOutputScalarTypeToUnsignedLong() + {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; + void SetOutputScalarTypeToInt() + {this->SetOutputScalarType(VTK_INT);} + void SetOutputScalarTypeToUnsignedInt() + {this->SetOutputScalarType(VTK_UNSIGNED_INT);} + void SetOutputScalarTypeToShort() + {this->SetOutputScalarType(VTK_SHORT);} + void SetOutputScalarTypeToUnsignedShort() + {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);} + void SetOutputScalarTypeToChar() + {this->SetOutputScalarType(VTK_CHAR);} + void SetOutputScalarTypeToSignedChar() + {this->SetOutputScalarType(VTK_SIGNED_CHAR);} + void SetOutputScalarTypeToUnsignedChar() + {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);} + +protected: + vtkImageThreshold(); + ~vtkImageThreshold() {}; + + double UpperThreshold; + double LowerThreshold; + int ReplaceIn; + double InValue; + int ReplaceOut; + double OutValue; + + int OutputScalarType; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + +private: + vtkImageThreshold(const vtkImageThreshold&); // Not implemented. + void operator=(const vtkImageThreshold&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImageToImageStencil.cxx b/Imaging/vtkImageToImageStencil.cxx new file mode 100644 index 0000000..50fc37a --- /dev/null +++ b/Imaging/vtkImageToImageStencil.cxx @@ -0,0 +1,251 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToImageStencil.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageToImageStencil.h" + +#include "vtkImageData.h" +#include "vtkImageStencilData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImageToImageStencil, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkImageToImageStencil); + +//---------------------------------------------------------------------------- +vtkImageToImageStencil::vtkImageToImageStencil() +{ + this->UpperThreshold = VTK_LARGE_FLOAT; + this->LowerThreshold = -VTK_LARGE_FLOAT; +} + +//---------------------------------------------------------------------------- +vtkImageToImageStencil::~vtkImageToImageStencil() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageToImageStencil::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Input: " << this->GetInput() << "\n"; + os << indent << "UpperThreshold: " << this->UpperThreshold << "\n"; + os << indent << "LowerThreshold: " << this->LowerThreshold << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkImageToImageStencil::SetInput(vtkImageData *input) +{ + if (input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + this->SetInputConnection(0, 0); + } +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageToImageStencil::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return NULL; + } + + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +//---------------------------------------------------------------------------- +// The values greater than or equal to the value match. +void vtkImageToImageStencil::ThresholdByUpper(double thresh) +{ + if (this->LowerThreshold != thresh || this->UpperThreshold < VTK_LARGE_FLOAT) + { + this->LowerThreshold = thresh; + this->UpperThreshold = VTK_LARGE_FLOAT; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// The values less than or equal to the value match. +void vtkImageToImageStencil::ThresholdByLower(double thresh) +{ + if (this->UpperThreshold != thresh || this->LowerThreshold > -VTK_LARGE_FLOAT) + { + this->UpperThreshold = thresh; + this->LowerThreshold = -VTK_LARGE_FLOAT; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +// The values in a range (inclusive) match +void vtkImageToImageStencil::ThresholdBetween(double lower, double upper) +{ + if (this->LowerThreshold != lower || this->UpperThreshold != upper) + { + this->LowerThreshold = lower; + this->UpperThreshold = upper; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkImageToImageStencil::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Superclass::RequestData(request, inputVector, outputVector); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageStencilData *data = vtkImageStencilData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int *inExt = inData->GetExtent(); + int *inWholeExt = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + int outExt[6]; + data->GetExtent(outExt); + vtkDataArray *inScalars = inData->GetPointData()->GetScalars(); + double upperThreshold = this->UpperThreshold; + double lowerThreshold = this->LowerThreshold; + + // clip the extent with the image data extent + int extent[6]; + for (int i = 0; i < 3; i++) + { + int lo = 2*i; + extent[lo] = outExt[lo]; + if (extent[lo] < inWholeExt[lo]) + { + extent[lo] = inWholeExt[lo]; + } + int hi = 2*i + 1; + extent[hi] = outExt[hi]; + if (extent[hi] > inWholeExt[hi]) + { + extent[hi] = inWholeExt[hi]; + } + if (extent[lo] > extent[hi]) + { + return 1; + } + } + + // for keeping track of progress + unsigned long count = 0; + unsigned long target = (unsigned long) + ((extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)/50.0); + target++; + + for (int idZ = extent[4]; idZ <= extent[5]; idZ++) + { + for (int idY = extent[2]; idY <= extent[3]; idY++) + { + if (count%target == 0) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + + int state = 1; // inside or outside, start outside + int r1 = extent[0]; + int r2 = extent[1]; + + // index into scalar array + int idS = ((inExt[1] - inExt[0] + 1)* + ((inExt[3] - inExt[2] + 1)*(idZ - inExt[4]) + + (idY - inExt[2])) + (extent[0] - inExt[0])); + + for (int idX = extent[0]; idX <= extent[1]; idX++) + { + int newstate = 1; + double value = inScalars->GetComponent(idS++,0); + if (value >= lowerThreshold && value <= upperThreshold) + { + newstate = -1; + if (newstate != state) + { // sub extent starts + r1 = idX; + } + } + else if (newstate != state) + { // sub extent ends + r2 = idX - 1; + data->InsertNextExtent(r1, r2, idY, idZ); + } + state = newstate; + } // for idX + if (state < 0) + { // if inside at end, cap off the sub extent + data->InsertNextExtent(r1, extent[1], idY, idZ); + } + } // for idY + } // for idZ + + return 1; +} + +int vtkImageToImageStencil::RequestInformation( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // this is an odd source that can produce any requested size. so its whole + // extent is essentially infinite. This would not be a great source to + // connect to some sort of writer or viewer. For a sanity check we will + // limit the size produced to something reasonable (depending on your + // definition of reasonable) + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, VTK_LARGE_INTEGER >> 2, + 0, VTK_LARGE_INTEGER >> 2, + 0, VTK_LARGE_INTEGER >> 2); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageToImageStencil::FillInputPortInformation(int, + vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageToImageStencil::RequestUpdateExtent( + vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()), + 6); + return 1; +} diff --git a/Imaging/vtkImageToImageStencil.h b/Imaging/vtkImageToImageStencil.h new file mode 100644 index 0000000..605372e --- /dev/null +++ b/Imaging/vtkImageToImageStencil.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageToImageStencil.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageToImageStencil - clip an image with a mask image +// .SECTION Description +// vtkImageToImageStencil will convert a vtkImageData into an stencil +// that can be used with vtkImageStecil or other vtk classes that apply +// a stencil to an image. +// .SECTION see also +// vtkImageStencil vtkImplicitFunctionToImageStencil vtkPolyDataToImageStencil + +#ifndef __vtkImageToImageStencil_h +#define __vtkImageToImageStencil_h + + +#include "vtkImageStencilSource.h" + +class vtkImageData; + +class VTK_IMAGING_EXPORT vtkImageToImageStencil : public vtkImageStencilSource +{ +public: + static vtkImageToImageStencil *New(); + vtkTypeRevisionMacro(vtkImageToImageStencil, vtkImageStencilSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the image data to convert into a stencil. + void SetInput(vtkImageData *input); + vtkImageData *GetInput(); + + // Description: + // The values greater than or equal to the value match. + void ThresholdByUpper(double thresh); + + // Description: + // The values less than or equal to the value match. + void ThresholdByLower(double thresh); + + // Description: + // The values in a range (inclusive) match + void ThresholdBetween(double lower, double upper); + + // Description: + // Get the Upper and Lower thresholds. + vtkSetMacro(UpperThreshold, double); + vtkGetMacro(UpperThreshold, double); + vtkSetMacro(LowerThreshold, double); + vtkGetMacro(LowerThreshold, double); + +protected: + vtkImageToImageStencil(); + ~vtkImageToImageStencil(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int, vtkInformation*); + + double UpperThreshold; + double LowerThreshold; + double Threshold; +private: + vtkImageToImageStencil(const vtkImageToImageStencil&); // Not implemented. + void operator=(const vtkImageToImageStencil&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageTranslateExtent.cxx b/Imaging/vtkImageTranslateExtent.cxx new file mode 100644 index 0000000..80abd3d --- /dev/null +++ b/Imaging/vtkImageTranslateExtent.cxx @@ -0,0 +1,133 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageTranslateExtent.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageTranslateExtent.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkImageTranslateExtent, "$Revision: 1.26 $"); +vtkStandardNewMacro(vtkImageTranslateExtent); + +//---------------------------------------------------------------------------- +vtkImageTranslateExtent::vtkImageTranslateExtent() +{ + int idx; + + for (idx = 0; idx < 3; ++idx) + { + this->Translation[idx] = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkImageTranslateExtent::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Translation: (" << this->Translation[0] + << "," << this->Translation[1] << "," << this->Translation[2] << endl; +} + +//---------------------------------------------------------------------------- +// Change the WholeExtent +int vtkImageTranslateExtent::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int idx, extent[6]; + double spacing[3], origin[3]; + + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent); + inInfo->Get(vtkDataObject::ORIGIN(), origin); + inInfo->Get(vtkDataObject::SPACING(), spacing); + + // TranslateExtent the OutputWholeExtent with the input WholeExtent + for (idx = 0; idx < 3; ++idx) + { + // change extent + extent[2*idx] += this->Translation[idx]; + extent[2*idx+1] += this->Translation[idx]; + // change origin so the data does not shift + origin[idx] -= (double)(this->Translation[idx]) * spacing[idx]; + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6); + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + + return 1; +} + +//---------------------------------------------------------------------------- +// This method simply copies by reference the input data to the output. +int vtkImageTranslateExtent::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkImageData *inData = vtkImageData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImageData *outData = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int extent[6]; + + // since inData can be larger than update extent. + inData->GetExtent(extent); + for (int i = 0; i < 3; ++i) + { + extent[i*2] += this->Translation[i]; + extent[i*2+1] += this->Translation[i]; + } + outData->SetExtent(extent); + outData->GetPointData()->PassData(inData->GetPointData()); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkImageTranslateExtent::RequestUpdateExtent ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + int inExtent[6], extent[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExtent); + + extent[0] = inExtent[0] - this->Translation[0]; + extent[1] = inExtent[1] - this->Translation[0]; + extent[2] = inExtent[2] - this->Translation[1]; + extent[3] = inExtent[3] - this->Translation[1]; + extent[4] = inExtent[4] - this->Translation[2]; + extent[5] = inExtent[5] - this->Translation[2]; + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6); + + return 1; +} diff --git a/Imaging/vtkImageTranslateExtent.h b/Imaging/vtkImageTranslateExtent.h new file mode 100644 index 0000000..6728597 --- /dev/null +++ b/Imaging/vtkImageTranslateExtent.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageTranslateExtent.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageTranslateExtent - Changes extent, nothing else. +// .SECTION Description +// vtkImageTranslateExtent shift the whole extent, but does not +// change the data. + +#ifndef __vtkImageTranslateExtent_h +#define __vtkImageTranslateExtent_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkImageTranslateExtent : public vtkImageAlgorithm +{ +public: + static vtkImageTranslateExtent *New(); + vtkTypeRevisionMacro(vtkImageTranslateExtent,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Delta to change "WholeExtent". -1 changes 0->10 to -1->9. + vtkSetVector3Macro(Translation, int); + vtkGetVector3Macro(Translation, int); + +protected: + vtkImageTranslateExtent(); + ~vtkImageTranslateExtent() {}; + + int Translation[3]; + + virtual int RequestUpdateExtent (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkImageTranslateExtent(const vtkImageTranslateExtent&); // Not implemented. + void operator=(const vtkImageTranslateExtent&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageVariance3D.cxx b/Imaging/vtkImageVariance3D.cxx new file mode 100644 index 0000000..8b115fd --- /dev/null +++ b/Imaging/vtkImageVariance3D.cxx @@ -0,0 +1,336 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageVariance3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageVariance3D.h" + +#include "vtkImageEllipsoidSource.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageVariance3D, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkImageVariance3D); + +//---------------------------------------------------------------------------- +vtkImageVariance3D::vtkImageVariance3D() +{ + this->HandleBoundaries = 1; + this->KernelSize[0] = 1; + this->KernelSize[1] = 1; + this->KernelSize[2] = 1; + + this->Ellipse = vtkImageEllipsoidSource::New(); + // Setup the Ellipse to default size + this->SetKernelSize(1, 1, 1); +} + +//---------------------------------------------------------------------------- +vtkImageVariance3D::~vtkImageVariance3D() +{ + if (this->Ellipse) + { + this->Ellipse->Delete(); + this->Ellipse = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageVariance3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +// This method sets the size of the neighborhood. It also sets the +// default middle of the neighborhood and computes the Elliptical foot print. +void vtkImageVariance3D::SetKernelSize(int size0, int size1, int size2) +{ + int modified = 0; + + if (this->KernelSize[0] != size0) + { + modified = 1; + this->KernelSize[0] = size0; + this->KernelMiddle[0] = size0 / 2; + } + if (this->KernelSize[1] != size1) + { + modified = 1; + this->KernelSize[1] = size1; + this->KernelMiddle[1] = size1 / 2; + } + if (this->KernelSize[2] != size2) + { + modified = 1; + this->KernelSize[2] = size2; + this->KernelMiddle[2] = size2 / 2; + } + + if (modified) + { + this->Modified(); + this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->SetCenter((float)(this->KernelSize[0]-1)*0.5, + (float)(this->KernelSize[1]-1)*0.5, + (float)(this->KernelSize[2]-1)*0.5); + this->Ellipse->SetRadius((float)(this->KernelSize[0])*0.5, + (float)(this->KernelSize[1])*0.5, + (float)(this->KernelSize[2])*0.5); + + // make sure scalars have been allocated (needed if multithreaded is used) + vtkInformation *ellipseOutInfo = + this->Ellipse->GetExecutive()->GetOutputInformation(0); + ellipseOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + 0, this->KernelSize[0]-1, + 0, this->KernelSize[1]-1, + 0, this->KernelSize[2]-1); + this->Ellipse->GetOutput()->Update(); + } +} + +//---------------------------------------------------------------------------- +// Output is always float +int vtkImageVariance3D::RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + int retval = + this->Superclass::RequestInformation(request, inputVector, outputVector); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1); + return retval; +} + +//---------------------------------------------------------------------------- +// This templated function executes the filter on any region, +// whether it needs boundary checking or not. +// If the filter needs to be faster, the function could be duplicated +// for strictly center (no boundary ) processing. +template +void vtkImageVariance3DExecute(vtkImageVariance3D *self, + vtkImageData *mask, + vtkImageData *inData, T *inPtr, + vtkImageData *outData, int *outExt, + float *outPtr, int id, + vtkInformation *inInfo) +{ + int *kernelMiddle, *kernelSize; + // For looping though output (and input) pixels. + int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2; + int outIdx0, outIdx1, outIdx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outInc0, outInc1, outInc2; + T *inPtr0, *inPtr1, *inPtr2; + float *outPtr0, *outPtr1, *outPtr2; + int numComps, outIdxC; + // For looping through hood pixels + int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2; + int hoodIdx0, hoodIdx1, hoodIdx2; + T *hoodPtr0, *hoodPtr1, *hoodPtr2; + // For looping through the mask. + unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2; + vtkIdType maskInc0, maskInc1, maskInc2; + // The extent of the whole input image + int inImageMin0, inImageMin1, inImageMin2; + int inImageMax0, inImageMax1, inImageMax2; + int inImageExt[6]; + // To compute the variance + float diff, sum; + int icount; + unsigned long count = 0; + unsigned long target; + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inImageExt); + inImageMin0 = inImageExt[0]; + inImageMax0 = inImageExt[1]; + inImageMin1 = inImageExt[2]; + inImageMax1 = inImageExt[3]; + inImageMin2 = inImageExt[4]; + inImageMax2 = inImageExt[5]; + outData->GetIncrements(outInc0, outInc1, outInc2); + outMin0 = outExt[0]; outMax0 = outExt[1]; + outMin1 = outExt[2]; outMax1 = outExt[3]; + outMin2 = outExt[4]; outMax2 = outExt[5]; + numComps = outData->GetNumberOfScalarComponents(); + + // Get ivars of this object (easier than making friends) + kernelSize = self->GetKernelSize();; + kernelMiddle = self->GetKernelMiddle(); + hoodMin0 = - kernelMiddle[0]; + hoodMin1 = - kernelMiddle[1]; + hoodMin2 = - kernelMiddle[2]; + hoodMax0 = hoodMin0 + kernelSize[0] - 1; + hoodMax1 = hoodMin1 + kernelSize[1] - 1; + hoodMax2 = hoodMin2 + kernelSize[2] - 1; + + // Setup mask info + maskPtr = (unsigned char *)(mask->GetScalarPointer()); + mask->GetIncrements(maskInc0, maskInc1, maskInc2); + + // in and out should be marching through corresponding pixels. + inPtr = (T *)(inData->GetScalarPointer(outMin0, outMin1, outMin2)); + + target = (unsigned long)(numComps*(outMax2-outMin2+1)* + (outMax1-outMin1+1)/50.0); + target++; + + // loop through components + for (outIdxC = 0; outIdxC < numComps; ++outIdxC) + { + // loop through pixels of output + outPtr2 = outPtr; + inPtr2 = inPtr; + for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2) + { + outPtr1 = outPtr2; + inPtr1 = inPtr2; + for (outIdx1 = outMin1; !self->AbortExecute && outIdx1 <= outMax1; + ++outIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + outPtr0 = outPtr1; + inPtr0 = inPtr1; + for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0) + { + + // Find variance + sum = 0.0; + icount = 0; + // loop through neighborhood pixels + // as sort of a hack to handle boundaries, + // input pointer will be marching through data that does not exist. + hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0 + - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2; + maskPtr2 = maskPtr; + for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2) + { + hoodPtr1 = hoodPtr2; + maskPtr1 = maskPtr2; + for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1) + { + hoodPtr0 = hoodPtr1; + maskPtr0 = maskPtr1; + for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0) + { + // A quick but rather expensive way to handle boundaries + if ( outIdx0 + hoodIdx0 >= inImageMin0 && + outIdx0 + hoodIdx0 <= inImageMax0 && + outIdx1 + hoodIdx1 >= inImageMin1 && + outIdx1 + hoodIdx1 <= inImageMax1 && + outIdx2 + hoodIdx2 >= inImageMin2 && + outIdx2 + hoodIdx2 <= inImageMax2) + { + if (*maskPtr0) + { + diff = (float)(*hoodPtr0) - (float)(*inPtr0); + sum += diff * diff; + ++icount; + } + } + + hoodPtr0 += inInc0; + maskPtr0 += maskInc0; + } + hoodPtr1 += inInc1; + maskPtr1 += maskInc1; + } + hoodPtr2 += inInc2; + maskPtr2 += maskInc2; + } + *outPtr0 = sum / (float)icount; + + inPtr0 += inInc0; + outPtr0 += outInc0; + } + inPtr1 += inInc1; + outPtr1 += outInc1; + } + inPtr2 += inInc2; + outPtr2 += outInc2; + } + ++inPtr; + ++outPtr; + } +} + +//---------------------------------------------------------------------------- +// This method contains the first switch statement that calls the correct +// templated function for the input and output Data types. +// It hanldes image boundaries, so the image does not shrink. +void vtkImageVariance3D::ThreadedRequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + int inExt[6], wholeExt[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt); + this->InternalRequestUpdateExtent(inExt,outExt,wholeExt); + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + vtkImageData *mask; + + // Error checking on mask + mask = this->Ellipse->GetOutput(); + if (mask->GetScalarType() != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro(<< "Execute: mask has wrong scalar type"); + return; + } + + // this filter expects the output to be float + if (outData[0]->GetScalarType() != VTK_FLOAT) + { + vtkErrorMacro(<< "Execute: output ScalarType, " + << vtkImageScalarTypeNameMacro(outData[0]->GetScalarType()) + << " must be float"); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageVariance3DExecute( this, mask, inData[0][0], + (VTK_TT *)(inPtr), outData[0], outExt, + (float *)(outPtr),id, inInfo)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} + +//---------------------------------------------------------------------------- +int vtkImageVariance3D::RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Ellipse->GetOutput()->Update(); + return this->Superclass::RequestData(request, inputVector, outputVector); +} diff --git a/Imaging/vtkImageVariance3D.h b/Imaging/vtkImageVariance3D.h new file mode 100644 index 0000000..50b42dc --- /dev/null +++ b/Imaging/vtkImageVariance3D.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageVariance3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageVariance3D - Variance in a neighborhood. +// .SECTION Description +// vtkImageVariance3D replaces each pixel with a measurement of +// pixel variance in a elliptical neighborhood centered on that pixel. +// The value computed is not exactly the variance. +// The difference between the neighbor values and center value is computed +// and squared for each neighbor. These values are summed and divided by +// the total number of neighbors to produce the output value. + + +#ifndef __vtkImageVariance3D_h +#define __vtkImageVariance3D_h + + +#include "vtkImageSpatialAlgorithm.h" + +class vtkImageEllipsoidSource; + +class VTK_IMAGING_EXPORT vtkImageVariance3D : public vtkImageSpatialAlgorithm +{ +public: + static vtkImageVariance3D *New(); + vtkTypeRevisionMacro(vtkImageVariance3D,vtkImageSpatialAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sets the size of the neighborhood. It also sets the default + // middle of the neighborhood and computes the Elliptical foot print. + void SetKernelSize(int size0, int size1, int size2); + +protected: + vtkImageVariance3D(); + ~vtkImageVariance3D(); + + vtkImageEllipsoidSource *Ellipse; + + virtual int RequestInformation (vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + + void ThreadedRequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector, + vtkImageData ***inData, vtkImageData **outData, + int extent[6], int id); + virtual int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + +private: + vtkImageVariance3D(const vtkImageVariance3D&); // Not implemented. + void operator=(const vtkImageVariance3D&); // Not implemented. +}; + +#endif diff --git a/Imaging/vtkImageWrapPad.cxx b/Imaging/vtkImageWrapPad.cxx new file mode 100644 index 0000000..44e59b2 --- /dev/null +++ b/Imaging/vtkImageWrapPad.cxx @@ -0,0 +1,252 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageWrapPad.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageWrapPad.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkImageWrapPad, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkImageWrapPad); + +//---------------------------------------------------------------------------- +// Just clip the request. +void vtkImageWrapPad::ComputeInputUpdateExtent (int inExt[6], int outExt[6], + int wholeExtent[6]) +{ + int idx; + int min, max, width, imageMin, imageMax, imageWidth; + + // Clip + for (idx = 0; idx < 3; ++idx) + { + min = outExt[idx * 2]; + max = outExt[idx * 2 + 1]; + imageMin = wholeExtent[idx * 2]; + imageMax = wholeExtent[idx * 2 + 1]; + if (min > max || imageMin > imageMax) + { // Empty output request. + inExt[0] = inExt[2] = inExt[4] = 0; + inExt[1] = inExt[3] = inExt[5] = -1; + return; + } + width = max - min + 1; + imageWidth = imageMax - imageMin + 1; + + // convert min max to image extent range. + min = ((min - imageMin) % imageWidth); + if (min < 0) + { // Mod does not handle negative numbers as I think it should. + min += imageWidth; + } + min += imageMin; + max = min + width - 1; + // if request region wraps, we need the whole input + // (unless we make multiple requests! Write Update instead??) + if (max > imageMax) + { + max = imageMax; + min = imageMin; + } + + inExt[idx * 2] = min; + inExt[idx * 2 + 1] = max; + } +} + + + + +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkImageWrapPadExecute(vtkImageWrapPad *self, + vtkImageData *inData, T *vtkNotUsed(inPtr), + vtkImageData *outData, T *outPtr, + int outExt[6], int id) +{ + int min0, max0; + int imageMin0, imageMax0, imageMin1, imageMax1, + imageMin2, imageMax2; + int outIdx0, outIdx1, outIdx2; + int start0, start1, start2; + int inIdx0, inIdx1, inIdx2; + vtkIdType inInc0, inInc1, inInc2; + vtkIdType outIncX, outIncY, outIncZ; + T *inPtr0, *inPtr1, *inPtr2; + unsigned long count = 0; + unsigned long target; + int inMaxC, idxC, maxC; + + // Get information to march through data + inData->GetIncrements(inInc0, inInc1, inInc2); + inData->GetWholeExtent(imageMin0, imageMax0, imageMin1, imageMax1, + imageMin2, imageMax2); + outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + + // initialize pointers to coresponding pixels. + start0 = ((outExt[0] - imageMin0) % (imageMax0-imageMin0+1)) + imageMin0; + if (start0 < 0) + { + start0 += (imageMax0-imageMin0+1); + } + start1 = ((outExt[2] - imageMin1) % (imageMax1-imageMin1+1)) + imageMin1; + if (start1 < 0) + { + start1 += (imageMax1-imageMin1+1); + } + start2 = ((outExt[4] - imageMin2) % (imageMax2-imageMin2+1)) + imageMin2; + if (start2 < 0) + { + start2 += (imageMax2-imageMin2+1); + } + inPtr2 = (T *)(inData->GetScalarPointer(start0, start1, start2)); + + min0 = outExt[0]; + max0 = outExt[1]; + inMaxC = inData->GetNumberOfScalarComponents(); + maxC = outData->GetNumberOfScalarComponents(); + target = (unsigned long)((outExt[5]-outExt[4]+1)* + (outExt[3]-outExt[2]+1)/50.0); + target++; + + inIdx2 = start2; + for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2, ++inIdx2) + { + if (inIdx2 > imageMax2) + { // we need to wrap(rewind) the input on this axis + inIdx2 = imageMin2; + inPtr2 -= (imageMax2-imageMin2+1)*inInc2; + } + inPtr1 = inPtr2; + inIdx1 = start1; + for (outIdx1 = outExt[2]; + !self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1, ++inIdx1) + { + if (!id) + { + if (!(count%target)) + { + self->UpdateProgress(count/(50.0*target)); + } + count++; + } + if (inIdx1 > imageMax1) + { // we need to wrap(rewind) the input on this axis + inIdx1 = imageMin1; + inPtr1 -= (imageMax1-imageMin1+1)*inInc1; + } + inPtr0 = inPtr1; + inIdx0 = start0; + // if components are same much faster + if ((maxC == inMaxC) && (maxC == 1)) + { + for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0, ++inIdx0) + { + if (inIdx0 > imageMax0) + { // we need to wrap(rewind) the input on this axis + inIdx0 = imageMin0; + inPtr0 -= (imageMax0-imageMin0+1)*inInc0; + } + // Copy Pixel + *outPtr = *inPtr0; + outPtr++; inPtr0++; + } + } + else + { + for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0, ++inIdx0) + { + if (inIdx0 > imageMax0) + { // we need to wrap(rewind) the input on this axis + inIdx0 = imageMin0; + inPtr0 -= (imageMax0-imageMin0+1)*inInc0; + } + for (idxC = 0; idxC < maxC; idxC++) + { + // Copy Pixel + *outPtr = inPtr0[idxC%inMaxC]; + outPtr++; + } + inPtr0 += inInc0; + } + } + outPtr += outIncY; + inPtr1 += inInc1; + } + outPtr += outIncZ; + inPtr2 += inInc2; + } +} + + + +//---------------------------------------------------------------------------- +// This method is passed a input and output data, and executes the filter +// algorithm to fill the output from the input. +// It just executes a switch statement to call the correct function for +// the regions data types. +void vtkImageWrapPad::ThreadedRequestData ( + vtkInformation * vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector * vtkNotUsed( outputVector ), + vtkImageData ***inData, + vtkImageData **outData, + int outExt[6], int id) +{ + // return if nothing to do + if (outExt[1] < outExt[0] || + outExt[3] < outExt[2] || + outExt[5] < outExt[4]) + { + return; + } + + int inExt[6]; + + // get the whole extent + int wExt[6]; + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wExt); + this->ComputeInputUpdateExtent(inExt,outExt,wExt); + void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt); + void *outPtr = outData[0]->GetScalarPointerForExtent(outExt); + + vtkDebugMacro(<< "Execute: inData = " << inData[0][0] + << ", outData = " << outData[0]); + + // this filter expects that input is the same type as output. + if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType()) + { + vtkErrorMacro(<< "Execute: input ScalarType, " + << inData[0][0]->GetScalarType() + << ", must match out ScalarType " + << outData[0]->GetScalarType()); + return; + } + + switch (inData[0][0]->GetScalarType()) + { + vtkTemplateMacro( + vtkImageWrapPadExecute( this, inData[0][0], + (VTK_TT *)inPtr, outData[0], + (VTK_TT *)(outPtr), outExt, id)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } +} diff --git a/Imaging/vtkImageWrapPad.h b/Imaging/vtkImageWrapPad.h new file mode 100644 index 0000000..e011f5d --- /dev/null +++ b/Imaging/vtkImageWrapPad.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageWrapPad.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageWrapPad - Makes an image larger by wrapping existing data. +// .SECTION Description +// vtkImageWrapPad performs a modulo operation on the output pixel index +// to determine the source input index. The new image extent of the +// output has to be specified. Input has to be the same scalar type as +// output. + + +#ifndef __vtkImageWrapPad_h +#define __vtkImageWrapPad_h + + +#include "vtkImagePadFilter.h" + +class vtkInformation; +class vtkInformationVector; + +class VTK_IMAGING_EXPORT vtkImageWrapPad : public vtkImagePadFilter +{ +public: + static vtkImageWrapPad *New(); + vtkTypeRevisionMacro(vtkImageWrapPad,vtkImagePadFilter); + +protected: + vtkImageWrapPad() {}; + ~vtkImageWrapPad() {}; + + void ComputeInputUpdateExtent (int inExt[6], int outExt[6], int wExt[6]); + void ThreadedRequestData (vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData ***inData, vtkImageData **outData, + int ext[6], int id); +private: + vtkImageWrapPad(const vtkImageWrapPad&); // Not implemented. + void operator=(const vtkImageWrapPad&); // Not implemented. +}; + +#endif + + + diff --git a/Imaging/vtkImplicitFunctionToImageStencil.cxx b/Imaging/vtkImplicitFunctionToImageStencil.cxx new file mode 100644 index 0000000..704cf00 --- /dev/null +++ b/Imaging/vtkImplicitFunctionToImageStencil.cxx @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitFunctionToImageStencil.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitFunctionToImageStencil.h" + +#include "vtkImageStencilData.h" +#include "vtkImplicitFunction.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkImplicitFunctionToImageStencil, "$Revision: 1.12 $"); +vtkStandardNewMacro(vtkImplicitFunctionToImageStencil); +vtkCxxSetObjectMacro(vtkImplicitFunctionToImageStencil,Input, vtkImplicitFunction); + +//---------------------------------------------------------------------------- +vtkImplicitFunctionToImageStencil::vtkImplicitFunctionToImageStencil() +{ + this->SetNumberOfInputPorts(0); + this->Threshold = 0; + this->Input = NULL; +} + +//---------------------------------------------------------------------------- +vtkImplicitFunctionToImageStencil::~vtkImplicitFunctionToImageStencil() +{ + this->SetInput(NULL); +} + +//---------------------------------------------------------------------------- +void vtkImplicitFunctionToImageStencil::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Input: " << this->Input << "\n"; + os << indent << "Threshold: " << this->Threshold << "\n"; +} + +//---------------------------------------------------------------------------- +// set up the clipping extents from an implicit function by brute force +// (i.e. by evaluating the function at each and every voxel) +int vtkImplicitFunctionToImageStencil::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + this->Superclass::RequestData(request, inputVector, outputVector); + + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageStencilData *data = vtkImageStencilData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkImplicitFunction *function = this->Input; + double *spacing = data->GetSpacing(); + double *origin = data->GetOrigin(); + double threshold = this->Threshold; + + // if the input is not set then punt + if (!function) + { + return 1; + } + + // for conversion of (idX,idY,idZ) into (x,y,z) + double point[3]; + + // for keeping track of progress + unsigned long count = 0; + int extent[6]; + data->GetExtent(extent); + unsigned long target = (unsigned long) + ((extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)/50.0); + target++; + + // loop through all voxels + for (int idZ = extent[4]; idZ <= extent[5]; idZ++) + { + point[2] = idZ*spacing[2] + origin[2]; + + for (int idY = extent[2]; idY <= extent[3]; idY++) + { + point[1] = idY*spacing[1] + origin[1]; + int state = 1; // inside or outside, start outside + int r1 = extent[0]; + int r2 = extent[1]; + + if (count%target == 0) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + + for (int idX = extent[0]; idX <= extent[1]; idX++) + { + point[0] = idX*spacing[0] + origin[0]; + int newstate = 1; + if (function->FunctionValue(point) < threshold) + { + newstate = -1; + if (newstate != state) + { // sub extent starts + r1 = idX; + } + } + else if (newstate != state) + { // sub extent ends + r2 = idX - 1; + data->InsertNextExtent(r1, r2, idY, idZ); + } + state = newstate; + } // for idX + if (state == -1) + { // if inside at end, cap off the sub extent + data->InsertNextExtent(r1, extent[1], idY, idZ); + } + } // for idY + } // for idZ + + return 1; +} + +int vtkImplicitFunctionToImageStencil::RequestInformation( + vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // this is an odd source that can produce any requested size. so its whole + // extent is essentially infinite. This would not be a great source to + // connect to some sort of writer or viewer. For a sanity check we will + // limit the size produced to something reasonable (depending on your + // definition of reasonable) + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, VTK_LARGE_INTEGER >> 2, + 0, VTK_LARGE_INTEGER >> 2, + 0, VTK_LARGE_INTEGER >> 2); + return 1; +} diff --git a/Imaging/vtkImplicitFunctionToImageStencil.h b/Imaging/vtkImplicitFunctionToImageStencil.h new file mode 100644 index 0000000..7b7e439 --- /dev/null +++ b/Imaging/vtkImplicitFunctionToImageStencil.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitFunctionToImageStencil.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitFunctionToImageStencil - clip an image with a function +// .SECTION Description +// vtkImplicitFunctionToImageStencil will convert a vtkImplicitFunction into +// a stencil that can be used with vtkImageStencil or with other classes +// that apply a stencil to an image. +// .SECTION see also +// vtkImplicitFunction vtkImageStencil vtkPolyDataToImageStencil + +#ifndef __vtkImplicitFunctionToImageStencil_h +#define __vtkImplicitFunctionToImageStencil_h + + +#include "vtkImageStencilSource.h" + +class vtkImplicitFunction; + +class VTK_IMAGING_EXPORT vtkImplicitFunctionToImageStencil : public vtkImageStencilSource +{ +public: + static vtkImplicitFunctionToImageStencil *New(); + vtkTypeRevisionMacro(vtkImplicitFunctionToImageStencil, vtkImageStencilSource); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the implicit function to convert into a stencil. + virtual void SetInput(vtkImplicitFunction*); + vtkGetObjectMacro(Input, vtkImplicitFunction); + + // Description: + // Set the threshold value for the implicit function. + vtkSetMacro(Threshold, double); + vtkGetMacro(Threshold, double); + +protected: + vtkImplicitFunctionToImageStencil(); + ~vtkImplicitFunctionToImageStencil(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkImplicitFunction *Input; + double Threshold; +private: + vtkImplicitFunctionToImageStencil(const vtkImplicitFunctionToImageStencil&); // Not implemented. + void operator=(const vtkImplicitFunctionToImageStencil&); // Not implemented. +}; + +#endif + diff --git a/Imaging/vtkPointLoad.cxx b/Imaging/vtkPointLoad.cxx new file mode 100644 index 0000000..9ee2a53 --- /dev/null +++ b/Imaging/vtkPointLoad.cxx @@ -0,0 +1,260 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointLoad.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointLoad.h" + +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkPointLoad, "$Revision: 1.49 $"); +vtkStandardNewMacro(vtkPointLoad); + +// Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50), +// and LoadValue = 1. +vtkPointLoad::vtkPointLoad() +{ + this->LoadValue = 1.0; + + this->ModelBounds[0] = -1.0; + this->ModelBounds[1] = 1.0; + this->ModelBounds[2] = -1.0; + this->ModelBounds[3] = 1.0; + this->ModelBounds[4] = -1.0; + this->ModelBounds[5] = 1.0; + + this->SampleDimensions[0] = 50; + this->SampleDimensions[1] = 50; + this->SampleDimensions[2] = 50; + + this->PoissonsRatio = 0.3; + + this->SetNumberOfInputPorts(0); +} + +// Specify the dimensions of the volume. A stress tensor will be computed for +// each point in the volume. +void vtkPointLoad::SetSampleDimensions(int i, int j, int k) +{ + int dim[3]; + + dim[0] = i; + dim[1] = j; + dim[2] = k; + + this->SetSampleDimensions(dim); +} + +// Specify the dimensions of the volume. A stress tensor will be computed for +// each point in the volume. +void vtkPointLoad::SetSampleDimensions(int dim[3]) +{ + vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")"); + + if ( dim[0] != this->SampleDimensions[0] || + dim[1] != this->SampleDimensions[1] || + dim[2] != this->SampleDimensions[2] ) + { + for ( int i=0; i<3; i++) + { + this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1); + } + this->Modified(); + } +} + +int vtkPointLoad::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + // use model bounds + double origin[3]; + origin[0] = this->ModelBounds[0]; + origin[1] = this->ModelBounds[2]; + origin[2] = this->ModelBounds[4]; + outInfo->Set(vtkDataObject::ORIGIN(), origin, 3); + + // Set volume origin and data spacing + int i; + double spacing[3]; + for (i=0; i<3; i++) + { + spacing[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + if ( spacing[i] <= 0.0 ) + { + spacing[i] = 1.0; + } + } + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + + int wExt[6]; + wExt[0] = 0; wExt[2] = 0; wExt[4] = 0; + wExt[1] = this->SampleDimensions[0] - 1; + wExt[3] = this->SampleDimensions[1] - 1; + wExt[5] = this->SampleDimensions[2] - 1; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExt, 6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1); + return 1; +} + +// +// Generate tensors and scalars for point load on semi-infinite domain. +// +void vtkPointLoad::ExecuteData(vtkDataObject *outp) +{ + int i, j, k; + vtkFloatArray *newTensors; + double tensor[9]; + vtkIdType numPts; + double P, twoPi, xP[3], rho, rho2, rho3, rho5, nu; + double x, x2, y, y2, z, z2, rhoPlusz2, zPlus2rho, txy, txz, tyz; + double sx, sy, sz, seff; + vtkImageData *output = this->AllocateOutputData(outp); + vtkFloatArray *newScalars = + vtkFloatArray::SafeDownCast(output->GetPointData()->GetScalars()); + double *spacing, *origin; + + vtkDebugMacro(<< "Computing point load stress tensors"); + + // + // Initialize self; create output objects + // + numPts = this->SampleDimensions[0] * this->SampleDimensions[1] + * this->SampleDimensions[2]; + spacing = output->GetSpacing(); + origin = output->GetOrigin(); + newTensors = vtkFloatArray::New(); + newTensors->SetNumberOfComponents(9); + newTensors->Allocate(9*numPts); + + // + // Compute the location of the load + // + xP[0] = (this->ModelBounds[0] + this->ModelBounds[1]) / 2.0; //in center + xP[1] = (this->ModelBounds[2] + this->ModelBounds[3]) / 2.0; + xP[2] = this->ModelBounds[5]; // at top of box + // + // Traverse all points evaluating implicit function at each point. Note that + // points are evaluated in local coordinate system of applied force. + // + twoPi = 2.0*vtkMath::Pi(); + P = -this->LoadValue; + int pointCount = 0; + for (k=0; kSampleDimensions[2]; k++) + { + z = xP[2] - (origin[2] + k*spacing[2]); + for (j=0; jSampleDimensions[1]; j++) + { + y = xP[1] - (origin[1] + j*spacing[1]); + for (i=0; iSampleDimensions[0]; i++) + { + x = (origin[0] + i*spacing[0]) - xP[0]; + rho = sqrt(x*x + y*y + z*z);//in local coordinates + if ( rho < 1.0e-10 ) + { + vtkWarningMacro(<<"Attempting to set singularity, resetting"); + tensor[0] = VTK_LARGE_FLOAT; // Component(0,0) + tensor[4] = VTK_LARGE_FLOAT; // Component(1,1); + tensor[8] = VTK_LARGE_FLOAT; // Component(2,2); + tensor[3] = 0.0; // Component(0,1); + tensor[6] = 0.0; // Component(0,2); + tensor[1] = 0.0; // Component(1,0); + tensor[7] = 0.0; // Component(1,2); + tensor[2] = 0.0; // Component(2,0); + tensor[5] = 0.0; // Component(2,1); + newTensors->InsertNextTuple(tensor); + double val = VTK_LARGE_FLOAT; + newScalars->InsertTuple(pointCount,&val); + pointCount++; + continue; + } + + rho2 = rho*rho; + rho3 = rho2*rho; + rho5 = rho2*rho3; + nu = (1.0 - 2.0*this->PoissonsRatio); + x2 = x*x; + y2 = y*y; + z2 = z*z; + rhoPlusz2 = (rho + z) * (rho + z); + zPlus2rho = (2.0*rho + z); + + // normal stresses + sx = P/(twoPi*rho2) * (3.0*z*x2/rho3 - nu*(z/rho - rho/(rho+z) + + x2*(zPlus2rho)/(rho*rhoPlusz2))); + sy = P/(twoPi*rho2) * (3.0*z*y2/rho3 - nu*(z/rho - rho/(rho+z) + + y2*(zPlus2rho)/(rho*rhoPlusz2))); + sz = 3.0*P*z2*z/(twoPi*rho5); + + //shear stresses - negative signs are coordinate transformations + //that is, equations (in text) are in different coordinate system + //than volume is in. + txy = -(P/(twoPi*rho2) * (3.0*x*y*z/rho3 - + nu*x*y*(zPlus2rho)/(rho*rhoPlusz2))); + txz = -(3.0*P*x*z2/(twoPi*rho5)); + tyz = 3.0*P*y*z2/(twoPi*rho5); + + tensor[0] = sx; // Component(0,0); + tensor[4] = sy; // Component(1,1); + tensor[8] = sz; // Component(2,2); + tensor[3] = txy; // Component(0,1); real symmetric matrix + tensor[1] = txy; // Component(1,0); + tensor[6] = txz; // Component(0,2); + tensor[2] = txz; // Component(2,0); + tensor[7] = tyz; // Component(1,2); + tensor[5] = tyz; // Component(2,1); + newTensors->InsertNextTuple(tensor); + + seff = 0.333333* sqrt ((sx-sy)*(sx-sy) + (sy-sz)*(sy-sz) + + (sz-sx)*(sz-sx) + 6.0*txy*txy + 6.0*tyz*tyz + + 6.0*txz*txz); + newScalars->InsertTuple(pointCount,&seff); + pointCount++; + } + } + } + // + // Update self and free memory + // + output->GetPointData()->SetTensors(newTensors); + newTensors->Delete(); +} + + +void vtkPointLoad::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Load Value: " << this->LoadValue << "\n"; + os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", " + << this->SampleDimensions[1] << ", " + << this->SampleDimensions[2] << ")\n"; + os << indent << "ModelBounds: \n"; + os << indent << " Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n"; + os << indent << "Poisson's Ratio: " << this->PoissonsRatio << "\n"; +} + diff --git a/Imaging/vtkPointLoad.h b/Imaging/vtkPointLoad.h new file mode 100644 index 0000000..4e9a1b1 --- /dev/null +++ b/Imaging/vtkPointLoad.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointLoad.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointLoad - compute stress tensors given point load on semi-infinite domain +// .SECTION Description +// vtkPointLoad is a source object that computes stress tensors on a volume. +// The tensors are computed from the application of a point load on a +// semi-infinite domain. (The analytical results are adapted from Saada - see +// text.) It also is possible to compute effective stress scalars if desired. +// This object serves as a specialized data generator for some of the examples +// in the text. + +// .SECTION See Also +// vtkTensorGlyph, vtkHyperStreamline + +#ifndef __vtkPointLoad_h +#define __vtkPointLoad_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkPointLoad : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkPointLoad,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50), + // and LoadValue = 1. + static vtkPointLoad *New(); + + // Description: + // Set/Get value of applied load. + vtkSetMacro(LoadValue,double); + vtkGetMacro(LoadValue,double); + + // Description: + // Specify the dimensions of the volume. A stress tensor will be computed for + // each point in the volume. + void SetSampleDimensions(int i, int j, int k); + + // Description: + // Specify the dimensions of the volume. A stress tensor will be computed for + // each point in the volume. + void SetSampleDimensions(int dim[3]); + vtkGetVectorMacro(SampleDimensions,int,3); + + // Description: + // Specify the region in space over which the tensors are computed. The point + // load is assumed to be applied at top center of the volume. + vtkSetVector6Macro(ModelBounds,double); + vtkGetVectorMacro(ModelBounds,double,6); + + // Description: + // Set/Get Poisson's ratio. + vtkSetMacro(PoissonsRatio,double); + vtkGetMacro(PoissonsRatio,double); + + // Description: + // Turn on/off computation of effective stress scalar. These methods do + // nothing. The effective stress is always computed. + void SetComputeEffectiveStress(int) {}; + int GetComputeEffectiveStress() {return 1;}; + void ComputeEffectiveStressOn() {}; + void ComputeEffectiveStressOff() {}; + +protected: + vtkPointLoad(); + ~vtkPointLoad() {}; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual void ExecuteData(vtkDataObject *); + + double LoadValue; + double PoissonsRatio; + int SampleDimensions[3]; + double ModelBounds[6]; + +private: + vtkPointLoad(const vtkPointLoad&); // Not implemented. + void operator=(const vtkPointLoad&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkSampleFunction.cxx b/Imaging/vtkSampleFunction.cxx new file mode 100644 index 0000000..d8722ea --- /dev/null +++ b/Imaging/vtkSampleFunction.cxx @@ -0,0 +1,355 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSampleFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSampleFunction.h" + +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkGarbageCollector.h" +#include "vtkImageData.h" +#include "vtkImplicitFunction.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkSampleFunction, "$Revision: 1.74 $"); +vtkStandardNewMacro(vtkSampleFunction); +vtkCxxSetObjectMacro(vtkSampleFunction,ImplicitFunction,vtkImplicitFunction); + +// Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50), +// Capping turned off, and normal generation on. +vtkSampleFunction::vtkSampleFunction() +{ + this->ModelBounds[0] = -1.0; + this->ModelBounds[1] = 1.0; + this->ModelBounds[2] = -1.0; + this->ModelBounds[3] = 1.0; + this->ModelBounds[4] = -1.0; + this->ModelBounds[5] = 1.0; + + this->SampleDimensions[0] = 50; + this->SampleDimensions[1] = 50; + this->SampleDimensions[2] = 50; + + this->Capping = 0; + this->CapValue = VTK_LARGE_FLOAT; + + this->ImplicitFunction = NULL; + + this->ComputeNormals = 1; + this->OutputScalarType = VTK_DOUBLE; + + this->SetNumberOfInputPorts(0); +} + +vtkSampleFunction::~vtkSampleFunction() +{ + this->SetImplicitFunction(NULL); +} + + +// Specify the dimensions of the data on which to sample. +void vtkSampleFunction::SetSampleDimensions(int i, int j, int k) +{ + int dim[3]; + + dim[0] = i; + dim[1] = j; + dim[2] = k; + + this->SetSampleDimensions(dim); +} + +// Specify the dimensions of the data on which to sample. +void vtkSampleFunction::SetSampleDimensions(int dim[3]) +{ + vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] << "," << dim[2] << ")"); + + if ( dim[0] != this->SampleDimensions[0] || + dim[1] != this->SampleDimensions[1] || + dim[2] != this->SampleDimensions[2] ) + { + for ( int i=0; i<3; i++) + { + this->SampleDimensions[i] = (dim[i] > 0 ? dim[i] : 1); + } + this->Modified(); + } +} + +int vtkSampleFunction::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int i; + double ar[3], origin[3]; + + int wExt[6]; + wExt[0] = 0; wExt[2] = 0; wExt[4] = 0; + wExt[1] = this->SampleDimensions[0]-1; + wExt[3] = this->SampleDimensions[1]-1; + wExt[5] = this->SampleDimensions[2]-1; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExt, 6); + + for (i=0; i < 3; i++) + { + origin[i] = this->ModelBounds[2*i]; + if ( this->SampleDimensions[i] <= 1 ) + { + ar[i] = 1; + } + else + { + ar[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + } + } + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + outInfo->Set(vtkDataObject::SPACING(),ar,3); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 1); + return 1; +} + + +void vtkSampleFunction::ExecuteData(vtkDataObject *outp) +{ + vtkIdType idx, i, j, k; + vtkFloatArray *newNormals=NULL; + vtkIdType numPts; + double p[3], s; + vtkImageData *output=this->GetOutput(); + + output->SetExtent(output->GetUpdateExtent()); + output = this->AllocateOutputData(outp); + vtkDoubleArray *newScalars = + vtkDoubleArray::SafeDownCast(output->GetPointData()->GetScalars()); + + vtkDebugMacro(<< "Sampling implicit function"); + + // Initialize self; create output objects + // + if ( !this->ImplicitFunction ) + { + vtkErrorMacro(<<"No implicit function specified"); + return; + } + + numPts = newScalars->GetNumberOfTuples(); + + // Traverse all points evaluating implicit function at each point + // + int extent[6]; + output->GetUpdateExtent(extent); + double spacing[3]; + output->GetSpacing(spacing); + + for ( idx=0, k=extent[4]; k <= extent[5]; k++ ) + { + p[2] = this->ModelBounds[4] + k*spacing[2]; + for ( j=extent[2]; j <= extent[3]; j++ ) + { + p[1] = this->ModelBounds[2] + j*spacing[1]; + for ( i=extent[0]; i <= extent[1]; i++ ) + { + p[0] = this->ModelBounds[0] + i*spacing[0]; + s = this->ImplicitFunction->FunctionValue(p); + newScalars->SetTuple1(idx++,s); + } + } + } + + // If normal computation turned on, compute them + // + if ( this->ComputeNormals ) + { + double n[3]; + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->SetNumberOfTuples(numPts); + for ( idx=0, k=extent[4]; k <= extent[5]; k++ ) + { + p[2] = this->ModelBounds[4] + k*spacing[2]; + for ( j=extent[2]; j <= extent[3]; j++ ) + { + p[1] = this->ModelBounds[2] + j*spacing[1]; + for ( i=extent[0]; i <= extent[1]; i++ ) + { + p[0] = this->ModelBounds[0] + i*spacing[0]; + this->ImplicitFunction->FunctionGradient(p, n); + n[0] *= -1; + n[1] *= -1; + n[2] *= -1; + vtkMath::Normalize(n); + newNormals->SetTuple(idx++,n); + } + } + } + } + + // If capping is turned on, set the distances of the outside of the volume + // to the CapValue. + // + if ( this->Capping ) + { + this->Cap(newScalars); + } + + // Update self + // + if (newNormals) + { + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + } +} + + +unsigned long vtkSampleFunction::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long impFuncMTime; + + if ( this->ImplicitFunction != NULL ) + { + impFuncMTime = this->ImplicitFunction->GetMTime(); + mTime = ( impFuncMTime > mTime ? impFuncMTime : mTime ); + } + + return mTime; +} + +void vtkSampleFunction::Cap(vtkDataArray *s) +{ + int i,j,k,extent[6]; + vtkIdType idx; + int d01=this->SampleDimensions[0]*this->SampleDimensions[1]; + vtkImageData *output = this->GetOutput(); + output->GetUpdateExtent(extent); + + // i-j planes + //k = extent[4]; + for (j=extent[2]; j<=extent[3]; j++) + { + for (i=extent[0]; i<=extent[1]; i++) + { + s->SetComponent(i+j*this->SampleDimensions[0], 0, this->CapValue); + } + } + + k = extent[5]; + idx = k*d01; + for (j=extent[2]; j<=extent[3]; j++) + { + for (i=extent[0]; i<=extent[1]; i++) + { + s->SetComponent(idx+i+j*this->SampleDimensions[0], 0, this->CapValue); + } + } + + // j-k planes + //i = extent[0]; + for (k=extent[4]; k<=extent[5]; k++) + { + for (j=extent[2]; j<=extent[3]; j++) + { + s->SetComponent(j*this->SampleDimensions[0]+k*d01, 0, this->CapValue); + } + } + + i = extent[1]; + for (k=extent[4]; k<=extent[5]; k++) + { + for (j=extent[2]; j<=extent[3]; j++) + { + s->SetComponent(i+j*this->SampleDimensions[0]+k*d01, 0, this->CapValue); + } + } + + // i-k planes + //j = extent[2]; + for (k=extent[4]; k<=extent[5]; k++) + { + for (i=extent[0]; i<=extent[1]; i++) + { + s->SetComponent(i+k*d01, 0, this->CapValue); + } + } + + j = extent[3]; + idx = j*this->SampleDimensions[0]; + for (k=extent[4]; k<=extent[5]; k++) + { + for (i=extent[0]; i<=extent[1]; i++) + { + s->SetComponent(idx+i+k*d01, 0, this->CapValue); + } + } +} + +void vtkSampleFunction::SetScalars(vtkDataArray *da) +{ + if (da) + { + this->SetOutputScalarType(da->GetDataType()); + } +} + +void vtkSampleFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", " + << this->SampleDimensions[1] << ", " + << this->SampleDimensions[2] << ")\n"; + os << indent << "ModelBounds: \n"; + os << indent << " Xmin,Xmax: (" << this->ModelBounds[0] + << ", " << this->ModelBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->ModelBounds[2] + << ", " << this->ModelBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->ModelBounds[4] + << ", " << this->ModelBounds[5] << ")\n"; + + os << indent << "OutputScalarType: " << this->OutputScalarType << "\n"; + + if ( this->ImplicitFunction ) + { + os << indent << "Implicit Function: " << this->ImplicitFunction << "\n"; + } + else + { + os << indent << "No Implicit function defined\n"; + } + + os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n"); + os << indent << "Cap Value: " << this->CapValue << "\n"; + + os << indent << "Compute Normals: " << (this->ComputeNormals ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +void vtkSampleFunction::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->ImplicitFunction, + "ImplicitFunction"); +} diff --git a/Imaging/vtkSampleFunction.h b/Imaging/vtkSampleFunction.h new file mode 100644 index 0000000..e6fceaf --- /dev/null +++ b/Imaging/vtkSampleFunction.h @@ -0,0 +1,146 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSampleFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSampleFunction - sample an implicit function over a structured point set +// .SECTION Description +// vtkSampleFunction is a source object that evaluates an implicit function +// and normals at each point in a vtkStructuredPoints. The user can specify +// the sample dimensions and location in space to perform the sampling. To +// create closed surfaces (in conjunction with the vtkContourFilter), capping +// can be turned on to set a particular value on the boundaries of the sample +// space. + +// .SECTION See Also +// vtkImplicitModeller + +#ifndef __vtkSampleFunction_h +#define __vtkSampleFunction_h + +#include "vtkImageAlgorithm.h" + +class vtkImplicitFunction; +class vtkDataArray; + +class VTK_IMAGING_EXPORT vtkSampleFunction : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSampleFunction,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with ModelBounds=(-1,1,-1,1,-1,1), SampleDimensions=(50,50,50), + // Capping turned off, and normal generation on. + static vtkSampleFunction *New(); + + // Description: + // Specify the implicit function to use to generate data. + virtual void SetImplicitFunction(vtkImplicitFunction*); + vtkGetObjectMacro(ImplicitFunction,vtkImplicitFunction); + + // Description: + // Set what type of scalar data this source should generate. + vtkSetMacro(OutputScalarType,int); + vtkGetMacro(OutputScalarType,int); + void SetOutputScalarTypeToDouble() + {this->SetOutputScalarType(VTK_DOUBLE);} + void SetOutputScalarTypeToFloat() + {this->SetOutputScalarType(VTK_FLOAT);} + void SetOutputScalarTypeToLong() + {this->SetOutputScalarType(VTK_LONG);} + void SetOutputScalarTypeToUnsignedLong() + {this->SetOutputScalarType(VTK_UNSIGNED_LONG);}; + void SetOutputScalarTypeToInt() + {this->SetOutputScalarType(VTK_INT);} + void SetOutputScalarTypeToUnsignedInt() + {this->SetOutputScalarType(VTK_UNSIGNED_INT);} + void SetOutputScalarTypeToShort() + {this->SetOutputScalarType(VTK_SHORT);} + void SetOutputScalarTypeToUnsignedShort() + {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);} + void SetOutputScalarTypeToChar() + {this->SetOutputScalarType(VTK_CHAR);} + void SetOutputScalarTypeToUnsignedChar() + {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);} + + // Description: + // Control the type of the scalars object by explicitly providing a scalar + // object. THIS IS DEPRECATED, although it still works!!! Please use + // SetOutputScalarType instead. + virtual void SetScalars(vtkDataArray *da); + + // Description: + // Specify the dimensions of the data on which to sample. + void SetSampleDimensions(int i, int j, int k); + + // Description: + // Specify the dimensions of the data on which to sample. + void SetSampleDimensions(int dim[3]); + vtkGetVectorMacro(SampleDimensions,int,3); + + // Description: + // Specify the region in space over which the sampling occurs. The + // bounds is specified as (xMin,xMax, yMin,yMax, zMin,zMax). + vtkSetVector6Macro(ModelBounds,double); + vtkGetVectorMacro(ModelBounds,double,6); + + // Description: + // Turn on/off capping. If capping is on, then the outer boundaries of the + // structured point set are set to cap value. This can be used to insure + // surfaces are closed. + vtkSetMacro(Capping,int); + vtkGetMacro(Capping,int); + vtkBooleanMacro(Capping,int); + + // Description: + // Set the cap value. + vtkSetMacro(CapValue,double); + vtkGetMacro(CapValue,double); + + // Description: + // Turn on/off the computation of normals. + vtkSetMacro(ComputeNormals,int); + vtkGetMacro(ComputeNormals,int); + vtkBooleanMacro(ComputeNormals,int); + + // Description: + // Return the MTime also considering the implicit function. + unsigned long GetMTime(); + +protected: + vtkSampleFunction(); + ~vtkSampleFunction(); + + virtual void ReportReferences(vtkGarbageCollector*); + + void ExecuteData(vtkDataObject *); + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + void Cap(vtkDataArray *s); + + int OutputScalarType; + int SampleDimensions[3]; + double ModelBounds[6]; + int Capping; + double CapValue; + vtkImplicitFunction *ImplicitFunction; + int ComputeNormals; +private: + vtkSampleFunction(const vtkSampleFunction&); // Not implemented. + void operator=(const vtkSampleFunction&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkShepardMethod.cxx b/Imaging/vtkShepardMethod.cxx new file mode 100644 index 0000000..3f13dac --- /dev/null +++ b/Imaging/vtkShepardMethod.cxx @@ -0,0 +1,392 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShepardMethod.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkShepardMethod.h" + +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkShepardMethod, "$Revision: 1.47 $"); +vtkStandardNewMacro(vtkShepardMethod); + +// Construct with sample dimensions=(50,50,50) and so that model bounds are +// automatically computed from input. Null value for each unvisited output +// point is 0.0. Maximum distance is 0.25. +vtkShepardMethod::vtkShepardMethod() +{ + this->MaximumDistance = 0.25; + + this->ModelBounds[0] = 0.0; + this->ModelBounds[1] = 0.0; + this->ModelBounds[2] = 0.0; + this->ModelBounds[3] = 0.0; + this->ModelBounds[4] = 0.0; + this->ModelBounds[5] = 0.0; + + this->SampleDimensions[0] = 50; + this->SampleDimensions[1] = 50; + this->SampleDimensions[2] = 50; + + this->NullValue = 0.0; +} + +// Compute ModelBounds from input geometry. +double vtkShepardMethod::ComputeModelBounds(double origin[3], + double spacing[3]) +{ + double *bounds, maxDist; + int i, adjustBounds=0; + + // compute model bounds if not set previously + if ( this->ModelBounds[0] >= this->ModelBounds[1] || + this->ModelBounds[2] >= this->ModelBounds[3] || + this->ModelBounds[4] >= this->ModelBounds[5] ) + { + adjustBounds = 1; + vtkDataSet *ds = vtkDataSet::SafeDownCast(this->GetInput()); + // ds better be non null otherwise something is very wrong here + bounds = ds->GetBounds(); + } + else + { + bounds = this->ModelBounds; + } + + for (maxDist=0.0, i=0; i<3; i++) + { + if ( (bounds[2*i+1] - bounds[2*i]) > maxDist ) + { + maxDist = bounds[2*i+1] - bounds[2*i]; + } + } + maxDist *= this->MaximumDistance; + + // adjust bounds so model fits strictly inside (only if not set previously) + if ( adjustBounds ) + { + for (i=0; i<3; i++) + { + this->ModelBounds[2*i] = bounds[2*i] - maxDist; + this->ModelBounds[2*i+1] = bounds[2*i+1] + maxDist; + } + } + + // Set volume origin and data spacing + for (i=0; i<3; i++) + { + origin[i] = this->ModelBounds[2*i]; + spacing[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + } + + return maxDist; +} + +int vtkShepardMethod::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int i; + double ar[3], origin[3]; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, this->SampleDimensions[0]-1, + 0, this->SampleDimensions[1]-1, + 0, this->SampleDimensions[2]-1); + + for (i=0; i < 3; i++) + { + origin[i] = this->ModelBounds[2*i]; + if ( this->SampleDimensions[i] <= 1 ) + { + ar[i] = 1; + } + else + { + ar[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + } + } + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + outInfo->Set(vtkDataObject::SPACING(),ar,3); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1); + return 1; +} + +int vtkShepardMethod::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the input + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // get the output + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // We need to allocate our own scalars since we are overriding + // the superclasses "Execute()" method. + output->SetExtent(output->GetWholeExtent()); + output->AllocateScalars(); + + vtkIdType ptId, i; + int j, k; + double *px, x[3], s, *sum, spacing[3], origin[3]; + + double maxDistance, distance2, inScalar; + vtkDataArray *inScalars; + vtkIdType numPts, numNewPts, idx; + int min[3], max[3]; + int jkFactor; + vtkFloatArray *newScalars = + vtkFloatArray::SafeDownCast(output->GetPointData()->GetScalars()); + + vtkDebugMacro(<< "Executing Shepard method"); + + // Check input + // + if ( (numPts=input->GetNumberOfPoints()) < 1 ) + { + vtkErrorMacro(<<"Points must be defined!"); + return 1; + } + + if ( (inScalars = input->GetPointData()->GetScalars()) == NULL ) + { + vtkErrorMacro(<<"Scalars must be defined!"); + return 1; + } + + // Allocate + // + numNewPts = this->SampleDimensions[0] * this->SampleDimensions[1] + * this->SampleDimensions[2]; + + sum = new double[numNewPts]; + for (i=0; iSetComponent(i,0,0.0); + sum[i] = 0.0; + } + + maxDistance = this->ComputeModelBounds(origin,spacing); + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + + + // Traverse all input points. + // Each input point affects voxels within maxDistance. + // + int abortExecute=0; + for (ptId=0; ptId < numPts && !abortExecute; ptId++) + { + if ( ! (ptId % 1000) ) + { + vtkDebugMacro(<<"Inserting point #" << ptId); + this->UpdateProgress (ptId/numPts); + if (this->GetAbortExecute()) + { + abortExecute = 1; + break; + } + } + + px = input->GetPoint(ptId); + inScalar = inScalars->GetComponent(ptId,0); + + for (i=0; i<3; i++) //compute dimensional bounds in data set + { + double amin = (double)((px[i] - maxDistance) - origin[i]) / spacing[i]; + double amax = (double)((px[i] + maxDistance) - origin[i]) / spacing[i]; + min[i] = (int) amin; + max[i] = (int) amax; + + if (min[i] < amin) + { + min[i]++; // round upward to nearest integer to get min[i] + } + if (max[i] > amax) + { + max[i]--; // round downward to nearest integer to get max[i] + } + + if (min[i] < 0) + { + min[i] = 0; // valid range check + } + if (max[i] >= this->SampleDimensions[i]) + { + max[i] = this->SampleDimensions[i] - 1; + } + } + + for (i=0; i<3; i++) //compute dimensional bounds in data set + { + min[i] = (int) ((double)((px[i] - maxDistance) - origin[i]) / spacing[i]); + max[i] = (int) ((double)((px[i] + maxDistance) - origin[i]) / spacing[i]); + if (min[i] < 0) + { + min[i] = 0; + } + if (max[i] >= this->SampleDimensions[i]) + { + max[i] = this->SampleDimensions[i] - 1; + } + } + + jkFactor = this->SampleDimensions[0]*this->SampleDimensions[1]; + for (k = min[2]; k <= max[2]; k++) + { + x[2] = spacing[2] * k + origin[2]; + for (j = min[1]; j <= max[1]; j++) + { + x[1] = spacing[1] * j + origin[1]; + for (i = min[0]; i <= max[0]; i++) + { + x[0] = spacing[0] * i + origin[0]; + idx = jkFactor*k + this->SampleDimensions[0]*j + i; + + distance2 = vtkMath::Distance2BetweenPoints(x,px); + + if ( distance2 == 0.0 ) + { + sum[idx] = VTK_FLOAT_MAX; + newScalars->SetComponent(idx,0,VTK_FLOAT_MAX); + } + else + { + s = newScalars->GetComponent(idx,0); + sum[idx] += 1.0 / distance2; + newScalars->SetComponent(idx,0,s+(inScalar/distance2)); + } + } + } + } + } + + // Run through scalars and compute final values + // + for (ptId=0; ptIdGetComponent(ptId,0); + if ( sum[ptId] != 0.0 ) + { + newScalars->SetComponent(ptId,0,s/sum[ptId]); + } + else + { + newScalars->SetComponent(ptId,0,this->NullValue); + } + } + + // Update self + // + delete [] sum; + + return 1; +} + +// Set the i-j-k dimensions on which to sample the distance function. +void vtkShepardMethod::SetSampleDimensions(int i, int j, int k) +{ + int dim[3]; + + dim[0] = i; + dim[1] = j; + dim[2] = k; + + this->SetSampleDimensions(dim); +} + +// Set the i-j-k dimensions on which to sample the distance function. +void vtkShepardMethod::SetSampleDimensions(int dim[3]) +{ + int dataDim, i; + + vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," + << dim[1] << "," << dim[2] << ")"); + + if ( dim[0] != this->SampleDimensions[0] || + dim[1] != this->SampleDimensions[1] || + dim[2] != this->SampleDimensions[2] ) + { + if ( dim[0]<1 || dim[1]<1 || dim[2]<1 ) + { + vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values"); + return; + } + + for (dataDim=0, i=0; i<3 ; i++) + { + if (dim[i] > 1) + { + dataDim++; + } + } + + if ( dataDim < 3 ) + { + vtkErrorMacro(<<"Sample dimensions must define a volume!"); + return; + } + + for ( i=0; i<3; i++) + { + this->SampleDimensions[i] = dim[i]; + } + + this->Modified(); + } +} + +int vtkShepardMethod::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkShepardMethod::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum Distance: " << this->MaximumDistance << "\n"; + + os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", " + << this->SampleDimensions[1] << ", " + << this->SampleDimensions[2] << ")\n"; + + os << indent << "ModelBounds: \n"; + os << indent << " Xmin,Xmax: (" << this->ModelBounds[0] << ", " << this->ModelBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->ModelBounds[2] << ", " << this->ModelBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->ModelBounds[4] << ", " << this->ModelBounds[5] << ")\n"; + + os << indent << "Null Value: " << this->NullValue << "\n"; + +} diff --git a/Imaging/vtkShepardMethod.h b/Imaging/vtkShepardMethod.h new file mode 100644 index 0000000..352b31f --- /dev/null +++ b/Imaging/vtkShepardMethod.h @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkShepardMethod.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkShepardMethod - sample unstructured points onto structured points using the method of Shepard +// .SECTION Description +// vtkShepardMethod is a filter used to visualize unstructured point data using +// Shepard's method. The method works by resampling the unstructured points +// onto a structured points set. The influence functions are described as +// "inverse distance weighted". Once the structured points are computed, the +// usual visualization techniques (e.g., iso-contouring or volume rendering) +// can be used visualize the structured points. +// .SECTION Caveats +// The input to this filter is any dataset type. This filter can be used +// to resample any form of data, i.e., the input data need not be +// unstructured. +// +// The bounds of the data (i.e., the sample space) is automatically computed +// if not set by the user. +// +// If you use a maximum distance less than 1.0, some output points may +// never receive a contribution. The final value of these points can be +// specified with the "NullValue" instance variable. + +#ifndef __vtkShepardMethod_h +#define __vtkShepardMethod_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkShepardMethod : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkShepardMethod,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with sample dimensions=(50,50,50) and so that model bounds are + // automatically computed from input. Null value for each unvisited output + // point is 0.0. Maximum distance is 0.25. + static vtkShepardMethod *New(); + + // Description: + // Compute ModelBounds from input geometry. + double ComputeModelBounds(double origin[3], double ar[3]); + + // Description: + // Specify i-j-k dimensions on which to sample input points. + vtkGetVectorMacro(SampleDimensions,int,3); + + // Description: + // Set the i-j-k dimensions on which to sample the distance function. + void SetSampleDimensions(int i, int j, int k); + + // Description: + // Set the i-j-k dimensions on which to sample the distance function. + void SetSampleDimensions(int dim[3]); + + // Description: + // Specify influence distance of each input point. This distance is a + // fraction of the length of the diagonal of the sample space. Thus, values + // of 1.0 will cause each input point to influence all points in the + // structured point dataset. Values less than 1.0 can improve performance + // significantly. + vtkSetClampMacro(MaximumDistance,double,0.0,1.0); + vtkGetMacro(MaximumDistance,double); + + // Description: + // Specify the position in space to perform the sampling. + vtkSetVector6Macro(ModelBounds,double); + vtkGetVectorMacro(ModelBounds,double,6); + + // Description: + // Set the Null value for output points not receiving a contribution from the + // input points. + vtkSetMacro(NullValue,double); + vtkGetMacro(NullValue,double); + +protected: + vtkShepardMethod(); + ~vtkShepardMethod() {}; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + // see vtkAlgorithm for details + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + int SampleDimensions[3]; + double MaximumDistance; + double ModelBounds[6]; + double NullValue; +private: + vtkShepardMethod(const vtkShepardMethod&); // Not implemented. + void operator=(const vtkShepardMethod&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkSimpleImageFilterExample.cxx b/Imaging/vtkSimpleImageFilterExample.cxx new file mode 100644 index 0000000..bd5f741 --- /dev/null +++ b/Imaging/vtkSimpleImageFilterExample.cxx @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleImageFilterExample.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSimpleImageFilterExample.h" + +#include "vtkImageData.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkSimpleImageFilterExample, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkSimpleImageFilterExample); + +// The switch statement in Execute will call this method with +// the appropriate input type (IT). Note that this example assumes +// that the output data type is the same as the input data type. +// This is not always the case. +template +void vtkSimpleImageFilterExampleExecute(vtkImageData* input, + vtkImageData* output, + IT* inPtr, IT* outPtr) +{ + int dims[3]; + input->GetDimensions(dims); + if (input->GetScalarType() != output->GetScalarType()) + { + vtkGenericWarningMacro(<< "Execute: input ScalarType, " << input->GetScalarType() + << ", must match out ScalarType " << output->GetScalarType()); + return; + } + + int size = dims[0]*dims[1]*dims[2]; + + for(int i=0; iGetScalarPointer(); + void* outPtr = output->GetScalarPointer(); + + switch(output->GetScalarType()) + { + // This is simple a #define for a big case list. It handles + // all data types vtk can handle. + vtkTemplateMacro( + vtkSimpleImageFilterExampleExecute( input, output, + (VTK_TT *)(inPtr), + (VTK_TT *)(outPtr))); + default: + vtkGenericWarningMacro("Execute: Unknown input ScalarType"); + return; + } +} diff --git a/Imaging/vtkSimpleImageFilterExample.h b/Imaging/vtkSimpleImageFilterExample.h new file mode 100644 index 0000000..0f89fce --- /dev/null +++ b/Imaging/vtkSimpleImageFilterExample.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSimpleImageFilterExample.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSimpleImageFilterExample - Simple example of an image-image filter. +// .SECTION Description +// This is an example of a simple image-image filter. It copies it's input +// to it's output (point by point). It shows how templates can be used +// to support various data types. +// .SECTION See also +// vtkSimpleImageFilterExample + +#ifndef __vtkSimpleImageFilterExample_h +#define __vtkSimpleImageFilterExample_h + +#include "vtkSimpleImageToImageFilter.h" + +class VTK_IMAGING_EXPORT vtkSimpleImageFilterExample : public vtkSimpleImageToImageFilter +{ +public: + static vtkSimpleImageFilterExample *New(); + vtkTypeRevisionMacro(vtkSimpleImageFilterExample,vtkSimpleImageToImageFilter); + +protected: + + vtkSimpleImageFilterExample() {}; + ~vtkSimpleImageFilterExample() {}; + + virtual void SimpleExecute(vtkImageData* input, vtkImageData* output); +private: + vtkSimpleImageFilterExample(const vtkSimpleImageFilterExample&); // Not implemented. + void operator=(const vtkSimpleImageFilterExample&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/Imaging/vtkSurfaceReconstructionFilter.cxx b/Imaging/vtkSurfaceReconstructionFilter.cxx new file mode 100644 index 0000000..37751e5 --- /dev/null +++ b/Imaging/vtkSurfaceReconstructionFilter.cxx @@ -0,0 +1,593 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSurfaceReconstructionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSurfaceReconstructionFilter.h" + +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" +#include "vtkPointLocator.h" +#include "vtkPoints.h" + +vtkCxxRevisionMacro(vtkSurfaceReconstructionFilter, "$Revision: 1.35 $"); +vtkStandardNewMacro(vtkSurfaceReconstructionFilter); + +vtkSurfaceReconstructionFilter::vtkSurfaceReconstructionFilter() +{ + this->NeighborhoodSize = 20; + // negative values cause the algorithm to make a reasonable guess + this->SampleSpacing = -1.0; +} + +// some simple routines for vector math +void vtkCopyBToA(double* a,double* b) +{ + for(int i=0;i<3;i++) + { + a[i] = b[i]; + } +} +void vtkSubtractBFromA(double* a,double* b) +{ + for(int i=0;i<3;i++) + { + a[i] -= b[i]; + } +} +void vtkAddBToA(double* a,double* b) +{ + for(int i=0;i<3;i++) + { + a[i] += b[i]; + } +} +void vtkMultiplyBy(double* a,double f) +{ + for(int i=0;i<3;i++) + { + a[i] *= f; + } +} +void vtkDivideBy(double* a,double f) +{ + for(int i=0;i<3;i++) + { + a[i] /= f; + } +} + +// Routines for matrix creation +void vtkSRFreeMatrix(double **m, long nrl, long nrh, long ncl, long nch); +double **vtkSRMatrix(long nrl, long nrh, long ncl, long nch); +void vtkSRFreeVector(double *v, long nl, long nh); +double *vtkSRVector(long nl, long nh); + +// set a matrix to zero +void vtkSRMakeZero(double **m,long nrl, long nrh, long ncl, long nch) +{ + int i,j; + for(i=nrl;i<=nrh;i++) + { + for(j=ncl;j<=nch;j++) + { + m[i][j] = 0.0; + } + } +} + +// add v*Transpose(v) to m, where v is 3x1 and m is 3x3 +void vtkSRAddOuterProduct(double **m,double *v); + +// scalar multiply a matrix +void vtkSRMultiply(double **m,double f,long nrl, long nrh, long ncl, long nch) +{ + int i,j; + for(i=nrl;i<=nrh;i++) + { + for(j=ncl;j<=nch;j++) + { + m[i][j] *= f; + } + } +} + +//---------------------------------------------------------------------------- +int vtkSurfaceReconstructionFilter::FillInputPortInformation( + int vtkNotUsed( port ), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +int vtkSurfaceReconstructionFilter::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + // would be nice to compute the whole extent but we need more info to + // compute it. + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),0,1,0,1,0,1); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1); + return 1; +} + +//----------------------------------------------------------------------------- +struct SurfacePoint +{ + double loc[3]; + double o[3],n[3]; // plane centre and normal + vtkIdList *neighbors; // id's of points within LocalRadius of this point + double *costs; // should have same length as neighbors, cost for corresponding points + char isVisited; + + // simple constructor to initialise the members + SurfacePoint() : neighbors(vtkIdList::New()), isVisited(0) {} + ~SurfacePoint() { delete []costs; neighbors->Delete(); } +}; + +//----------------------------------------------------------------------------- +int vtkSurfaceReconstructionFilter::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the input + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // get the output + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + const vtkIdType COUNT = input->GetNumberOfPoints(); + SurfacePoint *surfacePoints; + + vtkIdType i, j; + int k; + + if ( COUNT < 1 ) + { + vtkErrorMacro(<<"No points to reconstruct"); + return 1; + } + surfacePoints = new SurfacePoint[COUNT]; + + vtkDebugMacro(<<"Reconstructing " << COUNT << " points"); + + //time_t start_time,t1,t2,t3,t4; + //time(&start_time); + + // -------------------------------------------------------------------------- + // 1. Build local connectivity graph + // ------------------------------------------------------------------------- + { + vtkPointLocator *locator = vtkPointLocator::New(); + locator->SetDataSet(input); + vtkIdList *locals = vtkIdList::New(); + // if a pair is close, add each one as a neighbor of the other + for(i=0;iloc,input->GetPoint(i)); + locator->FindClosestNPoints(this->NeighborhoodSize,p->loc,locals); + int iNeighbor; + for(j=0;jGetNumberOfIds();j++) + { + iNeighbor = locals->GetId(j); + if(iNeighbor!=i) + { + p->neighbors->InsertNextId(iNeighbor); + surfacePoints[iNeighbor].neighbors->InsertNextId(i); + } + } + } + locator->Delete(); + locals->Delete(); + } + + //time(&t1); + // -------------------------------------------------------------------------- + // 2. Estimate a plane at each point using local points + // -------------------------------------------------------------------------- + { + double *pointi; + double **covar,*v3d,*eigenvalues,**eigenvectors; + covar = vtkSRMatrix(0,2,0,2); + v3d = vtkSRVector(0,2); + eigenvalues = vtkSRVector(0,2); + eigenvectors = vtkSRMatrix(0,2,0,2); + for(i=0;io,p->loc); + int number=1; + vtkIdType neighborIndex; + for(j=0;jneighbors->GetNumberOfIds();j++) + { + neighborIndex = p->neighbors->GetId(j); + pointi = input->GetPoint(neighborIndex); + vtkAddBToA(p->o,pointi); + number++; + } + vtkDivideBy(p->o,number); + // then compute the covariance matrix + vtkSRMakeZero(covar,0,2,0,2); + for(k=0;k<3;k++) + v3d[k] = p->loc[k] - p->o[k]; + vtkSRAddOuterProduct(covar,v3d); + for(j=0;jneighbors->GetNumberOfIds();j++) + { + neighborIndex = p->neighbors->GetId(j); + pointi = input->GetPoint(neighborIndex); + for(k=0;k<3;k++) + { + v3d[k] = pointi[k] - p->o[k]; + } + vtkSRAddOuterProduct(covar,v3d); + } + vtkSRMultiply(covar,1.0/number,0,2,0,2); + // then extract the third eigenvector + vtkMath::Jacobi(covar,eigenvalues,eigenvectors); + // third eigenvector (column 2, ordered by eigenvalue magnitude) is plane normal + for(k=0;k<3;k++) + { + p->n[k] = eigenvectors[k][2]; + } + } + vtkSRFreeMatrix(covar,0,2,0,2); + vtkSRFreeVector(v3d,0,2); + vtkSRFreeVector(eigenvalues,0,2); + vtkSRFreeMatrix(eigenvectors,0,2,0,2); + } + + //time(&t2); + //-------------------------------------------------------------------------- + // 3a. Compute a cost between every pair of neighbors for the MST + // -------------------------------------------------------------------------- + // cost = 1 - |normal1.normal2| + // ie. cost is 0 if planes are parallel, 1 if orthogonal (least parallel) + for(i=0;icosts = new double[p->neighbors->GetNumberOfIds()]; + + // compute cost between all its neighbors + // (bit inefficient to do this for every point, as cost is symmetric) + for(j=0;jneighbors->GetNumberOfIds();j++) + { + p->costs[j] = 1.0 - + fabs(vtkMath::Dot(p->n,surfacePoints[p->neighbors->GetId(j)].n)); + } + } + + // -------------------------------------------------------------------------- + // 3b. Ensure consistency in plane direction between neighbors + // -------------------------------------------------------------------------- + // method: guess first one, then walk through tree along most-parallel + // neighbors MST, flipping the new normal if inconsistent + + // to walk minimal spanning tree, keep record of vertices visited and list + // of those near to any visited point but not themselves visited. Start + // with just one vertex as visited. Pick the vertex in the neighbors list + // that has the lowest cost connection with a visited vertex. Record this + // vertex as visited, add any new neighbors to the neighbors list. + + int orientationPropagation=1; + if(orientationPropagation) + {// set to false if you don't want orientation propagation (for testing) + vtkIdList *nearby = vtkIdList::New(); // list of nearby, unvisited points + + // start with some vertex + int first=0; // index of starting vertex + surfacePoints[first].isVisited = 1; + // add all the neighbors of the starting vertex into nearby + for(j=0;jGetNumberOfIds();j++) + { + nearby->InsertNextId(surfacePoints[first].neighbors->GetId(j)); + } + + double cost,lowestCost; + int cheapestNearby = 0, connectedVisited = 0; + + // repeat until nearby is empty: + while(nearby->GetNumberOfIds()>0) + { + // for each nearby point: + vtkIdType iNearby,iNeighbor; + lowestCost = VTK_FLOAT_MAX; + for(i=0;iGetNumberOfIds();i++) + { + iNearby = nearby->GetId(i); + // test cost against all neighbors that are members of visited + for(j=0;jGetNumberOfIds();j++) + { + iNeighbor = surfacePoints[iNearby].neighbors->GetId(j); + if(surfacePoints[iNeighbor].isVisited) + { + cost = surfacePoints[iNearby].costs[j]; + // pick lowest cost for this nearby point + if(costGetNumberOfIds(); + break; + } + } + } + } + } + if(connectedVisited == cheapestNearby) + { + vtkErrorMacro (<< "Internal error in vtkSurfaceReconstructionFilter"); + return 0; + } + + // correct the orientation of the point if necessary + if(vtkMath::Dot(surfacePoints[cheapestNearby].n, + surfacePoints[connectedVisited].n)<0.0F) + { + // flip this normal + vtkMultiplyBy(surfacePoints[cheapestNearby].n,-1); + } + // add this nearby point to visited + if(surfacePoints[cheapestNearby].isVisited != 0) + { + vtkErrorMacro (<< "Internal error in vtkSurfaceReconstructionFilter"); + return 0; + } + + surfacePoints[cheapestNearby].isVisited = 1; + // remove from nearby + nearby->DeleteId(cheapestNearby); + // add all new nearby points to nearby + for(j=0;jGetNumberOfIds();j++) + { + iNeighbor = surfacePoints[cheapestNearby].neighbors->GetId(j); + if(surfacePoints[iNeighbor].isVisited == 0) + { + nearby->InsertUniqueId(iNeighbor); + } + } + } + + nearby->Delete(); + } + + //time(&t3); + + // -------------------------------------------------------------------------- + // 4. Compute signed distance to surface for every point on a 3D grid + // -------------------------------------------------------------------------- + { + // need to know the bounding rectangle + double bounds[6]; + for(i=0;i<3;i++) + { + bounds[i*2]=input->GetBounds()[i*2]; + bounds[i*2+1]=input->GetBounds()[i*2+1]; + } + + // estimate the spacing if required + if(this->SampleSpacing<=0.0) + { + // spacing guessed as cube root of (volume divided by number of points) + this->SampleSpacing = pow((double)(bounds[1]-bounds[0])* + (bounds[3]-bounds[2])*(bounds[5]-bounds[4]) / + (double)COUNT, (double)(1.0/3.0)); + + vtkDebugMacro(<<"Estimated sample spacing as: " << this->SampleSpacing ); + } + + // allow a border around the volume to allow sampling around the extremes + for(i=0;i<3;i++) + { + bounds[i*2]-=this->SampleSpacing*2; + bounds[i*2+1]+=this->SampleSpacing*2; + } + + double topleft[3] = {bounds[0],bounds[2],bounds[4]}; + double bottomright[3] = {bounds[1],bounds[3],bounds[5]}; + int dim[3]; + for(i=0;i<3;i++) + { + dim[i] = (int)((bottomright[i]-topleft[i])/this->SampleSpacing); + } + + vtkDebugMacro(<<"Created output volume of dimensions: (" + << dim[0] << ", " << dim[1] << ", " << dim[2] << ")" ); + + // initialise the output volume + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); + output->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); + output->AllocateScalars(); + outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), + 0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); + + output->SetUpdateExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1); + + + vtkFloatArray *newScalars = + vtkFloatArray::SafeDownCast(output->GetPointData()->GetScalars()); + outInfo->Set(vtkDataObject::SPACING(), + this->SampleSpacing, this->SampleSpacing, this->SampleSpacing); + outInfo->Set(vtkDataObject::ORIGIN(),topleft,3); + + // initialise the point locator (have to use point insertion because we + // need to set our own bounds, slightly larger than the dataset to allow + // for sampling around the edge) + vtkPointLocator *locator = vtkPointLocator::New(); + vtkPoints *newPts = vtkPoints::New(); + locator->InitPointInsertion(newPts,bounds,(int)COUNT); + for(i=0;iInsertPoint(i,surfacePoints[i].loc); + } + + // go through the array probing the values + int x,y,z; + int iClosestPoint; + int zOffset,yOffset,offset; + double probeValue; + double point[3],temp[3]; + for(z=0;zSampleSpacing; + for(y=0;ySampleSpacing; + for(x=0;xSampleSpacing; + // find the distance from the probe to the plane of the nearest point + iClosestPoint = locator->FindClosestInsertedPoint(point); + if(iClosestPoint==-1) + { + vtkErrorMacro (<< "Internal error"); + return 0; + } + vtkCopyBToA(temp,point); + vtkSubtractBFromA(temp,surfacePoints[iClosestPoint].loc); + probeValue = vtkMath::Dot(temp,surfacePoints[iClosestPoint].n); + newScalars->SetValue(offset,probeValue); + } + } + } + locator->Delete(); + newPts->Delete(); + } + + //time(&t4); + // Clear up everything + delete [] surfacePoints; + + return 1; +} + +void vtkSurfaceReconstructionFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Neighborhood Size:" << this->NeighborhoodSize << "\n"; + os << indent << "Sample Spacing:" << this->SampleSpacing << "\n"; +} + +void vtkSRAddOuterProduct(double **m,double *v) +{ + int i,j; + for(i=0;i<3;i++) + { + for(j=0;j<3;j++) + { + m[i][j] += v[i]*v[j]; + } + } +} + +#define VTK_NR_END 1 +#define VTK_FREE_ARG char* + +// allocate a float vector with subscript range v[nl..nh] +double *vtkSRVector(long nl, long nh) +{ + double *v; + + v = new double [nh-nl+1+VTK_NR_END]; + if (!v) + { + vtkGenericWarningMacro(<<"allocation failure in vector()"); + return NULL; + } + + return (v-nl+VTK_NR_END); +} + +// allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] +double **vtkSRMatrix(long nrl, long nrh, long ncl, long nch) +{ + long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; + double **m; + + // allocate pointers to rows + m = new double * [nrow+VTK_NR_END]; + if (!m) + { + vtkGenericWarningMacro(<<"allocation failure 1 in Matrix()"); + return NULL; + } + + m += VTK_NR_END; + m -= nrl; + + // allocate rows and set pointers to them + m[nrl] = new double[nrow*ncol+VTK_NR_END]; + if (!m[nrl]) + { + vtkGenericWarningMacro("allocation failure 2 in Matrix()"); + return NULL; + } + + m[nrl] += VTK_NR_END; + m[nrl] -= ncl; + for(i=nrl+1;i<=nrh;i++) + { + m[i] = m[i-1]+ncol; + } + + // return pointer to array of pointers to rows + return m; +} + +// free a double vector allocated with SRVector() +void vtkSRFreeVector(double *v, long nl, long vtkNotUsed(nh)) +{ + delete [] (v+nl-VTK_NR_END); +} + +// free a double matrix allocated by Matrix() +void vtkSRFreeMatrix(double **m, long nrl, long vtkNotUsed(nrh), + long ncl, long vtkNotUsed(nch)) + +{ + delete [] (m[nrl]+ncl-VTK_NR_END); + delete [] (m+nrl-VTK_NR_END); +} + +#undef VTK_NR_END +#undef VTK_FREE_ARG + + + diff --git a/Imaging/vtkSurfaceReconstructionFilter.h b/Imaging/vtkSurfaceReconstructionFilter.h new file mode 100644 index 0000000..ee70780 --- /dev/null +++ b/Imaging/vtkSurfaceReconstructionFilter.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSurfaceReconstructionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSurfaceReconstructionFilter - reconstructs a surface from unorganized points +// .SECTION Description +// vtkSurfaceReconstructionFilter takes a list of points assumed to lie on +// the surface of a solid 3D object. A signed measure of the distance to the +// surface is computed and sampled on a regular grid. The grid can then be +// contoured at zero to extract the surface. The default values for +// neighborhood size and sample spacing should give reasonable results for +// most uses but can be set if desired. This procedure is based on the PhD +// work of Hugues Hoppe: http://www.research.microsoft.com/~hoppe + +#ifndef __vtkSurfaceReconstructionFilter_h +#define __vtkSurfaceReconstructionFilter_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkSurfaceReconstructionFilter : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSurfaceReconstructionFilter,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct with NeighborhoodSize=20. + static vtkSurfaceReconstructionFilter* New(); + + // Description: + // Specify the number of neighbors each point has, used for estimating the + // local surface orientation. The default value of 20 should be OK for + // most applications, higher values can be specified if the spread of + // points is uneven. Values as low as 10 may yield adequate results for + // some surfaces. Higher values cause the algorithm to take longer. Higher + // values will cause errors on sharp boundaries. + vtkGetMacro(NeighborhoodSize,int); + vtkSetMacro(NeighborhoodSize,int); + + // Description: + // Specify the spacing of the 3D sampling grid. If not set, a + // reasonable guess will be made. + vtkGetMacro(SampleSpacing,double); + vtkSetMacro(SampleSpacing,double); + +protected: + vtkSurfaceReconstructionFilter(); + ~vtkSurfaceReconstructionFilter() {}; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual int RequestData (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + int NeighborhoodSize; + double SampleSpacing; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkSurfaceReconstructionFilter(const vtkSurfaceReconstructionFilter&); // Not implemented. + void operator=(const vtkSurfaceReconstructionFilter&); // Not implemented. +}; + +#endif + diff --git a/Imaging/vtkTriangularTexture.cxx b/Imaging/vtkTriangularTexture.cxx new file mode 100644 index 0000000..058beea --- /dev/null +++ b/Imaging/vtkTriangularTexture.cxx @@ -0,0 +1,200 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangularTexture.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTriangularTexture.h" + +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkTriangularTexture, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkTriangularTexture); + +// Instantiate object with XSize and YSize = 64; the texture pattern =1 +// (opaque at centroid); and the scale factor set to 1.0. + +vtkTriangularTexture::vtkTriangularTexture() +{ + this->XSize = this->YSize = 64; + this->TexturePattern = 1; + this->ScaleFactor = 1.0; + this->SetNumberOfInputPorts(0); +} + +void vtkOpaqueAtElementCentroid (int XSize, int YSize, double ScaleFactor, + vtkUnsignedCharArray *newScalars) +{ + int i, j; + double opacity; + double point[3]; + double XScale = XSize + 1.0; + double YScale = YSize + 1.0; + unsigned char AGrayValue[2]; + double dist, distToV2, distToV3; + double v1[3] = {0.0, 0.0, 0.0}; + double v2[3] = {1.0, 0.0, 0.0}; + double v3[3] = {0.5, sqrt(3.0)/2.0, 0.0}; + + point[2] = 0.0; + AGrayValue[0] = AGrayValue[1] = 255; + + for (j = 0; j < YSize; j++) + { + for (i = 0; i < XSize; i++) + { + point[0] = i / XScale; + point[1] = j / YScale; + dist = vtkMath::Distance2BetweenPoints (point, v1); + distToV2 = vtkMath::Distance2BetweenPoints (point, v2); + if (distToV2 < dist) + { + dist = distToV2; + } + distToV3 = vtkMath::Distance2BetweenPoints (point, v3); + if (distToV3 < dist) + { + dist = distToV3; + } + + opacity = sqrt(dist) * ScaleFactor; + if (opacity < .5) + { + opacity = 0.0; + } + if (opacity > .5) + { + opacity = 1.0; + } + AGrayValue[1] = (unsigned char) (opacity * 255); + newScalars->SetValue ((XSize*j + i)*2, AGrayValue[0]); + newScalars->SetValue ((XSize*j + i)*2 + 1, AGrayValue[1]); + } + } +} + +void vtkOpaqueAtVertices (int XSize, int YSize, double ScaleFactor, + vtkUnsignedCharArray *newScalars) +{ + int i, j; + double opacity; + double point[3]; + double XScale = XSize + 1.0; + double YScale = YSize + 1.0; + unsigned char AGrayValue[2]; + double dist, distToV2, distToV3; + double v1[3] = {0.0, 0.0, 0.0}; + double v2[3] = {1.0, 0.0, 0.0}; + double v3[3] = {0.5, sqrt(3.0)/2.0, 0.0}; + + point[2] = 0.0; + AGrayValue[0] = AGrayValue[1] = 255; + + for (j = 0; j < YSize; j++) + { + for (i = 0; i < XSize; i++) + { + point[0] = i / XScale; + point[1] = j / YScale; + dist = vtkMath::Distance2BetweenPoints (point, v1); + distToV2 = vtkMath::Distance2BetweenPoints (point, v2); + if (distToV2 < dist) + { + dist = distToV2; + } + distToV3 = vtkMath::Distance2BetweenPoints (point, v3); + if (distToV3 < dist) + { + dist = distToV3; + } + + opacity = sqrt(dist) * ScaleFactor; + if (opacity < .5) + { + opacity = 0.0; + } + if (opacity > .5) + { + opacity = 1.0; + } + opacity = 1.0 - opacity; + AGrayValue[1] = (unsigned char) (opacity * 255); + newScalars->SetValue ((XSize*j + i)*2, AGrayValue[0]); + newScalars->SetValue ((XSize*j + i)*2 + 1, AGrayValue[1]); + } + } +} + +//---------------------------------------------------------------------------- +int vtkTriangularTexture::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int wExt[6] = {0,this->XSize -1, 0, this->YSize - 1, 0,0}; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wExt,6); + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 2); + return 1; +} + +void vtkTriangularTexture::ExecuteData(vtkDataObject *outp) +{ + vtkImageData *output = this->AllocateOutputData(outp); + vtkUnsignedCharArray *newScalars = + vtkUnsignedCharArray::SafeDownCast(output->GetPointData()->GetScalars()); + + if (this->XSize*this->YSize < 1) + { + vtkErrorMacro(<<"Bad texture (xsize,ysize) specification!"); + return; + } + + switch (this->TexturePattern) + { + case 1: // opaque at element vertices + vtkOpaqueAtVertices (this->XSize, this->YSize, + this->ScaleFactor, newScalars); + break; + + case 2: // opaque at element centroid + vtkOpaqueAtElementCentroid (this->XSize, this->YSize, + this->ScaleFactor, newScalars); + break; + + case 3: // opaque in rings around vertices + vtkErrorMacro(<<"Opaque vertex rings not implemented"); + break; + } +} + +void vtkTriangularTexture::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "XSize:" << this->XSize << "\n"; + os << indent << "YSize:" << this->YSize << "\n"; + + os << indent << "Texture Pattern:" << this->TexturePattern << "\n"; + + os << indent << "Scale Factor:" << this->ScaleFactor << "\n"; +} + diff --git a/Imaging/vtkTriangularTexture.h b/Imaging/vtkTriangularTexture.h new file mode 100644 index 0000000..32c5531 --- /dev/null +++ b/Imaging/vtkTriangularTexture.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTriangularTexture.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTriangularTexture - generate 2D triangular texture map +// .SECTION Description +// vtkTriangularTexture is a filter that generates a 2D texture map based on +// the paper "Opacity-modulating Triangular Textures for Irregular Surfaces," +// by Penny Rheingans, IEEE Visualization '96, pp. 219-225. +// The textures assume texture coordinates of (0,0), (1.0) and +// (.5, sqrt(3)/2). The sequence of texture values is the same along each +// edge of the triangular texture map. So, the assignment order of texture +// coordinates is arbitrary. + +// .SECTION See Also +// vtkTriangularTCoords + +#ifndef __vtkTriangularTexture_h +#define __vtkTriangularTexture_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkTriangularTexture : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkTriangularTexture,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with XSize and YSize = 64; the texture pattern =1 + // (opaque at centroid); and the scale factor set to 1.0. + static vtkTriangularTexture *New(); + + // Description: + // Set a Scale Factor. + vtkSetMacro(ScaleFactor,double); + vtkGetMacro(ScaleFactor,double); + + // Description: + // Set the X texture map dimension. Default is 64. + vtkSetMacro(XSize,int); + vtkGetMacro(XSize,int); + + // Description: + // Set the Y texture map dimension. Default is 64. + vtkSetMacro(YSize,int); + vtkGetMacro(YSize,int); + + // Description: + // Set the texture pattern. + // 1 = opaque at centroid (default) + // 2 = opaque at vertices + // 3 = opaque in rings around vertices + vtkSetClampMacro(TexturePattern,int,1,3); + vtkGetMacro(TexturePattern,int); + +protected: + vtkTriangularTexture(); + ~vtkTriangularTexture() {}; + + virtual int RequestInformation (vtkInformation *, vtkInformationVector**, vtkInformationVector *); + virtual void ExecuteData(vtkDataObject *data); + + int XSize; + int YSize; + double ScaleFactor; + + int TexturePattern; +private: + vtkTriangularTexture(const vtkTriangularTexture&); // Not implemented. + void operator=(const vtkTriangularTexture&); // Not implemented. +}; + +#endif + + diff --git a/Imaging/vtkVoxelModeller.cxx b/Imaging/vtkVoxelModeller.cxx new file mode 100644 index 0000000..0fc1eba --- /dev/null +++ b/Imaging/vtkVoxelModeller.cxx @@ -0,0 +1,354 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoxelModeller.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVoxelModeller.h" + +#include "vtkBitArray.h" +#include "vtkCell.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkVoxelModeller, "$Revision: 1.58 $"); +vtkStandardNewMacro(vtkVoxelModeller); + +// Construct an instance of vtkVoxelModeller with its sample dimensions +// set to (50,50,50), and so that the model bounds are +// automatically computed from its input. The maximum distance is set to +// examine the whole grid. This could be made much faster, and probably +// will be in the future. +vtkVoxelModeller::vtkVoxelModeller() +{ + this->MaximumDistance = 1.0; + + this->ModelBounds[0] = 0.0; + this->ModelBounds[1] = 0.0; + this->ModelBounds[2] = 0.0; + this->ModelBounds[3] = 0.0; + this->ModelBounds[4] = 0.0; + this->ModelBounds[5] = 0.0; + + this->SampleDimensions[0] = 50; + this->SampleDimensions[1] = 50; + this->SampleDimensions[2] = 50; +} + +// Specify the position in space to perform the voxelization. +void vtkVoxelModeller::SetModelBounds(double bounds[6]) +{ + vtkVoxelModeller::SetModelBounds(bounds[0], bounds[1], bounds[2], bounds[3], + bounds[4], bounds[5]); +} + +void vtkVoxelModeller::SetModelBounds(double xmin, double xmax, double ymin, + double ymax, double zmin, double zmax) +{ + if (this->ModelBounds[0] != xmin || this->ModelBounds[1] != xmax || + this->ModelBounds[2] != ymin || this->ModelBounds[3] != ymax || + this->ModelBounds[4] != zmin || this->ModelBounds[5] != zmax ) + { + this->Modified(); + this->ModelBounds[0] = xmin; + this->ModelBounds[1] = xmax; + this->ModelBounds[2] = ymin; + this->ModelBounds[3] = ymax; + this->ModelBounds[4] = zmin; + this->ModelBounds[5] = zmax; + } +} + +int vtkVoxelModeller::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + int i; + double ar[3], origin[3]; + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, this->SampleDimensions[0]-1, + 0, this->SampleDimensions[1]-1, + 0, this->SampleDimensions[2]-1); + + for (i=0; i < 3; i++) + { + origin[i] = this->ModelBounds[2*i]; + if ( this->SampleDimensions[i] <= 1 ) + { + ar[i] = 1; + } + else + { + ar[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i]) + / (this->SampleDimensions[i] - 1); + } + } + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + outInfo->Set(vtkDataObject::SPACING(),ar,3); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_BIT, 1); + return 1; +} + +int vtkVoxelModeller::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // get the input + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + // get the output + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // We need to allocate our own scalars since we are overriding + // the superclasses "Execute()" method. + output->SetExtent(output->GetWholeExtent()); + output->AllocateScalars(); + + vtkIdType cellNum, i; + int j, k; + double *bounds, adjBounds[6]; + vtkCell *cell; + double maxDistance, pcoords[3]; + vtkIdType numPts, idx, numCells; + int subId; + int min[3], max[3]; + double x[3], distance2; + int jkFactor; + double *weights=new double[input->GetMaxCellSize()]; + double closestPoint[3]; + double voxelHalfWidth[3], origin[3], spacing[3]; + vtkBitArray *newScalars = + vtkBitArray::SafeDownCast(output->GetPointData()->GetScalars()); + + // + // Initialize self; create output objects + // + vtkDebugMacro(<< "Executing Voxel model"); + + numPts = this->SampleDimensions[0] * this->SampleDimensions[1] * + this->SampleDimensions[2]; + for (i=0; iSetComponent(i,0,0); + } + + maxDistance = this->ComputeModelBounds(origin,spacing); + outInfo->Set(vtkDataObject::SPACING(),spacing,3); + outInfo->Set(vtkDataObject::ORIGIN(),origin,3); + // + // Voxel widths are 1/2 the height, width, length of a voxel + // + for (i=0; i < 3; i++) + { + voxelHalfWidth[i] = spacing[i] / 2.0; + } + // + // Traverse all cells; computing distance function on volume points. + // + numCells = input->GetNumberOfCells(); + for (cellNum=0; cellNum < numCells; cellNum++) + { + cell = input->GetCell(cellNum); + bounds = cell->GetBounds(); + for (i=0; i<3; i++) + { + adjBounds[2*i] = bounds[2*i] - maxDistance; + adjBounds[2*i+1] = bounds[2*i+1] + maxDistance; + } + + // compute dimensional bounds in data set + for (i=0; i<3; i++) + { + min[i] = (int) ((double)(adjBounds[2*i] - origin[i]) / spacing[i]); + max[i] = (int) ((double)(adjBounds[2*i+1] - origin[i]) / spacing[i]); + if (min[i] < 0) + { + min[i] = 0; + } + if (max[i] >= this->SampleDimensions[i]) + { + max[i] = this->SampleDimensions[i] - 1; + } + } + + jkFactor = this->SampleDimensions[0]*this->SampleDimensions[1]; + for (k = min[2]; k <= max[2]; k++) + { + x[2] = spacing[2] * k + origin[2]; + for (j = min[1]; j <= max[1]; j++) + { + x[1] = spacing[1] * j + origin[1]; + for (i = min[0]; i <= max[0]; i++) + { + idx = jkFactor*k + this->SampleDimensions[0]*j + i; + if (!(newScalars->GetComponent(idx,0))) + { + x[0] = spacing[0] * i + origin[0]; + + if ( cell->EvaluatePosition(x, closestPoint, subId, pcoords, + distance2, weights) != -1 && + ((fabs(closestPoint[0] - x[0]) <= voxelHalfWidth[0]) && + (fabs(closestPoint[1] - x[1]) <= voxelHalfWidth[1]) && + (fabs(closestPoint[2] - x[2]) <= voxelHalfWidth[2])) ) + { + newScalars->SetComponent(idx,0,1); + } + } + } + } + } + } + delete [] weights; + + return 1; +} + +// Compute the ModelBounds based on the input geometry. +double vtkVoxelModeller::ComputeModelBounds(double origin[3], + double spacing[3]) +{ + double *bounds, maxDist; + int i, adjustBounds=0; + + // compute model bounds if not set previously + if ( this->ModelBounds[0] >= this->ModelBounds[1] || + this->ModelBounds[2] >= this->ModelBounds[3] || + this->ModelBounds[4] >= this->ModelBounds[5] ) + { + adjustBounds = 1; + vtkDataSet *ds = vtkDataSet::SafeDownCast(this->GetInput()); + // ds better be non null otherwise something is very wrong here + bounds = ds->GetBounds(); + } + else + { + bounds = this->ModelBounds; + } + + for (maxDist=0.0, i=0; i<3; i++) + { + if ( (bounds[2*i+1] - bounds[2*i]) > maxDist ) + { + maxDist = bounds[2*i+1] - bounds[2*i]; + } + } + maxDist *= this->MaximumDistance; + + // adjust bounds so model fits strictly inside (only if not set previously) + if ( adjustBounds ) + { + for (i=0; i<3; i++) + { + this->ModelBounds[2*i] = bounds[2*i] - maxDist; + this->ModelBounds[2*i+1] = bounds[2*i+1] + maxDist; + } + } + + // Set volume origin and data spacing + for (i=0; i<3; i++) + { + origin[i] = this->ModelBounds[2*i]; + spacing[i] = (this->ModelBounds[2*i+1] - this->ModelBounds[2*i])/ + (this->SampleDimensions[i] - 1); + } + + return maxDist; +} + +// Set the i-j-k dimensions on which to sample the distance function. +void vtkVoxelModeller::SetSampleDimensions(int i, int j, int k) +{ + int dim[3]; + + dim[0] = i; + dim[1] = j; + dim[2] = k; + + this->SetSampleDimensions(dim); +} + +void vtkVoxelModeller::SetSampleDimensions(int dim[3]) +{ + int dataDim, i; + + vtkDebugMacro(<< " setting SampleDimensions to (" << dim[0] << "," << dim[1] + << "," << dim[2] << ")"); + + if ( dim[0] != this->SampleDimensions[0] || + dim[1] != this->SampleDimensions[1] || + dim[2] != this->SampleDimensions[2] ) + { + if ( dim[0]<1 || dim[1]<1 || dim[2]<1 ) + { + vtkErrorMacro (<< "Bad Sample Dimensions, retaining previous values"); + return; + } + for (dataDim=0, i=0; i<3 ; i++) + { + if (dim[i] > 1) + { + dataDim++; + } + } + if ( dataDim < 3 ) + { + vtkErrorMacro(<<"Sample dimensions must define a volume!"); + return; + } + + for ( i=0; i<3; i++) + { + this->SampleDimensions[i] = dim[i]; + } + this->Modified(); + } +} + +int vtkVoxelModeller::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkVoxelModeller::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum Distance: " << this->MaximumDistance << "\n"; + os << indent << "Sample Dimensions: (" << this->SampleDimensions[0] << ", " + << this->SampleDimensions[1] << ", " + << this->SampleDimensions[2] << ")\n"; + os << indent << "Model Bounds: \n"; + os << indent << " Xmin,Xmax: (" << this->ModelBounds[0] << ", " + << this->ModelBounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->ModelBounds[2] << ", " + << this->ModelBounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" << this->ModelBounds[4] << ", " + << this->ModelBounds[5] << ")\n"; +} diff --git a/Imaging/vtkVoxelModeller.h b/Imaging/vtkVoxelModeller.h new file mode 100644 index 0000000..5205b1d --- /dev/null +++ b/Imaging/vtkVoxelModeller.h @@ -0,0 +1,94 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVoxelModeller.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVoxelModeller - convert an arbitrary dataset to a voxel representation +// .SECTION Description +// vtkVoxelModeller is a filter that converts an arbitrary data set to a +// structured point (i.e., voxel) representation. It is very similar to +// vtkImplicitModeller, except that it doesn't record distance; instead it +// records occupancy. As such, it stores its results in the more compact +// form of 0/1 bits. +// .SECTION see also +// vtkImplicitModeller + +#ifndef __vtkVoxelModeller_h +#define __vtkVoxelModeller_h + +#include "vtkImageAlgorithm.h" + +class VTK_IMAGING_EXPORT vtkVoxelModeller : public vtkImageAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkVoxelModeller,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct an instance of vtkVoxelModeller with its sample dimensions + // set to (50,50,50), and so that the model bounds are + // automatically computed from its input. The maximum distance is set to + // examine the whole grid. This could be made much faster, and probably + // will be in the future. + static vtkVoxelModeller *New(); + + // Description: + // Compute the ModelBounds based on the input geometry. + double ComputeModelBounds(double origin[3], double ar[3]); + + // Description: + // Set the i-j-k dimensions on which to sample the distance function. + void SetSampleDimensions(int i, int j, int k); + + // Description: + // Set the i-j-k dimensions on which to sample the distance function. + void SetSampleDimensions(int dim[3]); + vtkGetVectorMacro(SampleDimensions,int,3); + + // Description: + // Specify distance away from surface of input geometry to sample. Smaller + // values make large increases in performance. + vtkSetClampMacro(MaximumDistance,double,0.0,1.0); + vtkGetMacro(MaximumDistance,double); + + // Description: + // Specify the position in space to perform the voxelization. + void SetModelBounds(double bounds[6]); + void SetModelBounds(double xmin, double xmax, double ymin, double ymax, double zmin, double zmax); + vtkGetVectorMacro(ModelBounds,double,6); + +protected: + vtkVoxelModeller(); + ~vtkVoxelModeller() {}; + + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + // see vtkAlgorithm for details + virtual int RequestData(vtkInformation *request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + + int SampleDimensions[3]; + double MaximumDistance; + double ModelBounds[6]; +private: + vtkVoxelModeller(const vtkVoxelModeller&); // Not implemented. + void operator=(const vtkVoxelModeller&); // Not implemented. +}; + +#endif diff --git a/Parallel/CMakeLists.txt b/Parallel/CMakeLists.txt new file mode 100644 index 0000000..6c8e554 --- /dev/null +++ b/Parallel/CMakeLists.txt @@ -0,0 +1,117 @@ +SET(KIT Parallel) +SET(UKIT PARALLEL) +SET(KIT_TCL_LIBS vtkRenderingTCL vtkIOTCL ) +SET(KIT_PYTHON_LIBS vtkRenderingPythonD vtkIOPythonD) +SET(KIT_JAVA_LIBS vtkRenderingJava vtkIOJava) +SET(KIT_LIBS vtkRendering vtkIO) +IF(VTK_HAS_EXODUS) + SET(KIT_LIBS ${KIT_LIBS} vtkexoIIc) +ENDIF(VTK_HAS_EXODUS) +IF (WIN32) + IF (NOT BORLAND) + SET(KIT_LIBS ${KIT_LIBS} wsock32) + ENDIF (NOT BORLAND) +ENDIF (WIN32) + +SET ( Kit_SRCS +vtkDuplicatePolyData.cxx +vtkBranchExtentTranslator.cxx +vtkCollectPolyData.cxx +vtkCommunicator.cxx +vtkCompositer.cxx +vtkCompositeRenderManager.cxx +vtkCompressCompositer.cxx +vtkCutMaterial.cxx +vtkDistributedDataFilter.cxx +vtkDistributedStreamTracer.cxx +vtkDummyController.cxx +vtkEnSightWriter.cxx +vtkExtractCTHPart.cxx +vtkExtractPolyDataPiece.cxx +vtkExtractUnstructuredGridPiece.cxx +vtkExtractUserDefinedPiece.cxx +vtkPKdTree.cxx +vtkMemoryLimitImageDataStreamer.cxx +vtkMultiProcessController.cxx +vtkParallelRenderManager.cxx +vtkPassThroughFilter.cxx +vtkPCellDataToPointData.cxx +vtkPChacoReader.cxx +vtkPDataSetReader.cxx +vtkPDataSetWriter.cxx +vtkPImageWriter.cxx +vtkPLinearExtrusionFilter.cxx +vtkPOPReader.cxx +vtkPOutlineFilter.cxx +vtkPOutlineCornerFilter.cxx +vtkPPolyDataNormals.cxx +vtkPProbeFilter.cxx +vtkPSphereSource.cxx +vtkPStreamTracer.cxx +vtkParallelFactory.cxx +vtkPieceScalars.cxx +vtkPipelineSize.cxx +vtkProcessIdScalars.cxx +vtkRTAnalyticSource.cxx +vtkRectilinearGridOutlineFilter.cxx +vtkSocketCommunicator.cxx +vtkSocketController.cxx +vtkSubGroup.cxx +vtkTransmitPolyDataPiece.cxx +vtkTransmitUnstructuredGridPiece.cxx +vtkTreeCompositer.cxx +) + +IF(VTK_HAS_EXODUS) + SET(Kit_SRCS ${Kit_SRCS} + vtkExodusIIWriter.cxx + ) +ENDIF(VTK_HAS_EXODUS) + +SET_SOURCE_FILES_PROPERTIES( +vtkCommunicator +vtkMultiProcessController +vtkParallelRenderManager +vtkPStreamTracer +ABSTRACT +) + +IF (VTK_USE_MPI) + INCLUDE (${CMAKE_ROOT}/Modules/FindMPI.cmake) + SET ( Kit_SRCS + ${Kit_SRCS} + vtkMPICommunicator.cxx + vtkMPIController.cxx + vtkMPIGroup.cxx) +ENDIF (VTK_USE_MPI) + +IF (VTK_USE_MPI) + IF (MPI_LIBRARY) + SET(KIT_LIBS ${KIT_LIBS} "${MPI_LIBRARY}") + ELSE (MPI_LIBRARY) + MESSAGE("Could not find the required MPI libraries") + ENDIF (MPI_LIBRARY) + IF (MPI_EXTRA_LIBRARY) + SET(KIT_LIBS ${KIT_LIBS} "${MPI_EXTRA_LIBRARY}") + ENDIF (MPI_EXTRA_LIBRARY) +ENDIF (VTK_USE_MPI) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- + +IF (VTK_USE_MPI) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} "vtkMPI\\.h") + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF (VTK_USE_MPI) diff --git a/Parallel/Testing/CMakeLists.txt b/Parallel/Testing/CMakeLists.txt new file mode 100644 index 0000000..03b3b87 --- /dev/null +++ b/Parallel/Testing/CMakeLists.txt @@ -0,0 +1,17 @@ +SUBDIRS(Cxx) +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Parallel ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Parallel" + VTK_PARALLEL_EXPORT + vtkMPI.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/Parallel/Testing/Cxx/.NoDartCoverage b/Parallel/Testing/Cxx/.NoDartCoverage new file mode 100644 index 0000000..87269e3 --- /dev/null +++ b/Parallel/Testing/Cxx/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory \ No newline at end of file diff --git a/Parallel/Testing/Cxx/CMakeLists.txt b/Parallel/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..a784703 --- /dev/null +++ b/Parallel/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,95 @@ +IF(VTK_USE_DISPLAY AND VTK_USE_RENDERING) + ADD_EXECUTABLE(SocketServer SocketServer.cxx) + ADD_EXECUTABLE(SocketClient SocketClient.cxx) + TARGET_LINK_LIBRARIES(SocketClient vtkParallel) + TARGET_LINK_LIBRARIES(SocketServer vtkParallel) + + IF (VTK_USE_MPI) + ADD_EXECUTABLE(ParallelIsoTest ParallelIso.cxx) + TARGET_LINK_LIBRARIES(ParallelIsoTest vtkVolumeRendering vtkParallel vtkHybrid vtkWidgets) + + ADD_EXECUTABLE(GenericCommunicator GenericCommunicator.cxx) + TARGET_LINK_LIBRARIES(GenericCommunicator vtkParallel) + + ADD_EXECUTABLE(TestPStream TestPStream.cxx) + TARGET_LINK_LIBRARIES(TestPStream vtkParallel) + + ADD_EXECUTABLE(MPIGroups MPIGroups.cxx) + TARGET_LINK_LIBRARIES(MPIGroups vtkParallel) + + ADD_EXECUTABLE(DistributedData DistributedData.cxx) + TARGET_LINK_LIBRARIES(DistributedData vtkParallel) + + ADD_TEST(GenericCommunicator-image + ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} 2 ${VTK_MPI_PREFLAGS} + ${CXX_TEST_PATH}/GenericCommunicator + ${VTK_MPI_POSTFLAGS}) + + # + # Add tests, with the data + # + + IF (VTK_DATA_ROOT) + IF (VTK_MPIRUN_EXE) + IF(VTK_MPI_MAX_NUMPROCS GREATER 1) + ADD_TEST(ParallelIso-image + ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} 2 ${VTK_MPI_PREFLAGS} + ${CXX_TEST_PATH}/ParallelIsoTest + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/ParallelIso.cxx.png + ${VTK_MPI_POSTFLAGS}) + ADD_TEST(TestPStream-image + ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} 2 ${VTK_MPI_PREFLAGS} + ${CXX_TEST_PATH}/TestPStream + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestPStream.cxx.png + ${VTK_MPI_POSTFLAGS}) + ADD_TEST(DistributedData-image + ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} 2 ${VTK_MPI_PREFLAGS} + ${CXX_TEST_PATH}/DistributedData + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/DistributedData.cxx.png + ${VTK_MPI_POSTFLAGS}) + ENDIF(VTK_MPI_MAX_NUMPROCS GREATER 1) + IF (VTK_MPI_MAX_NUMPROCS GREATER 3) + ADD_TEST(MPIGroups-image + ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} ${VTK_MPI_MAX_NUMPROCS} ${VTK_MPI_PREFLAGS} + ${CXX_TEST_PATH}/MPIGroups + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/MPIGroups.cxx.png + ${VTK_MPI_POSTFLAGS}) + ENDIF (VTK_MPI_MAX_NUMPROCS GREATER 3) + + ENDIF (VTK_MPIRUN_EXE) + # + # If we do not have the data, still run the tests that we can + # + ELSE (VTK_DATA_ROOT) + IF (VTK_MPIRUN_EXE) + ADD_TEST(TestCommunicator + ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} 2 ${VTK_MPI_PREFLAGS} + ${CXX_TEST_PATH}/GenericCommunicator ${VTK_MPI_POSTFLAGS}) + ENDIF(VTK_MPIRUN_EXE) + ENDIF (VTK_DATA_ROOT) + ENDIF (VTK_USE_MPI) + + # For now this test is only available on Unix because + # on Windows, python does not support forking/killing processes + IF (UNIX) + IF (PYTHON_EXECUTABLE) + IF (VTK_DATA_ROOT) + ADD_TEST(Sockets-image ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Parallel/Testing/Cxx/TestSockets.py + ${VTK_EXECUTABLE_DIR}/SocketServer + ${VTK_EXECUTABLE_DIR}/SocketClient + ${VTK_DATA_ROOT} + Baseline/Parallel/SocketClient.cxx.png + ${VTK_BINARY_DIR}/Testing/Temporary) + ENDIF (VTK_DATA_ROOT) + ENDIF (PYTHON_EXECUTABLE) + ENDIF (UNIX) +ENDIF(VTK_USE_DISPLAY AND VTK_USE_RENDERING) diff --git a/Parallel/Testing/Cxx/DistributedData.cxx b/Parallel/Testing/Cxx/DistributedData.cxx new file mode 100644 index 0000000..eb65f78 --- /dev/null +++ b/Parallel/Testing/Cxx/DistributedData.cxx @@ -0,0 +1,292 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: DistributedData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// Test of vtkDistributedDataFilter and supporting classes, covering as much +// code as possible. This test requires 4 MPI processes. +// +// To cover ghost cell creation, use vtkDataSetSurfaceFilter. +// +// To cover clipping code: SetBoundaryModeToSplitBoundaryCells() +// +// To run fast redistribution: SetUseMinimalMemoryOff() (Default) +// To run memory conserving code instead: SetUseMinimalMemoryOn() + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkParallelFactory.h" +#include "vtkCompositeRenderManager.h" +#include "vtkDataSetReader.h" +#include "vtkUnstructuredGrid.h" +#include "vtkDistributedDataFilter.h" +#include "vtkDataSetSurfaceFilter.h" +#include "vtkPieceScalars.h" +#include "vtkMPIController.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkActor.h" +#include "vtkPolyDataMapper.h" +#include "vtkCamera.h" +/* +** This test only builds if MPI is in use +*/ +#include "vtkMPICommunicator.h" + +static int NumProcs, Me; + +struct DDArgs_tmp +{ + int* retVal; + int argc; + char** argv; +}; + +static void Run(vtkMultiProcessController *contr, void *arg) +{ + int i, go; + DDArgs_tmp *args = reinterpret_cast(arg); + + vtkCompositeRenderManager *prm = vtkCompositeRenderManager::New(); + + // READER + + vtkDataSetReader *dsr = vtkDataSetReader::New(); + vtkUnstructuredGrid *ug = vtkUnstructuredGrid::New(); + + vtkDataSet *ds = NULL; + + if (Me == 0) + { + char* fname = + vtkTestUtilities::ExpandDataFileName( + args->argc, args->argv, "Data/tetraMesh.vtk"); + + dsr->SetFileName(fname); + + ds = dsr->GetOutput(); + + dsr->Update(); + go = 1; + + if ((ds == NULL) || (ds->GetNumberOfCells() == 0)) + { + if (ds) cout << "Failure: input file has no cells" << endl; + go = 0; + } + } + else + { + ds = (vtkDataSet *)ug; + } + + vtkMPICommunicator *comm = + vtkMPICommunicator::SafeDownCast(contr->GetCommunicator()); + + comm->Broadcast(&go, 1, 0); + + if (!go){ + dsr->Delete(); + ug->Delete(); + prm->Delete(); + return; + } + + // DATA DISTRIBUTION FILTER + + vtkDistributedDataFilter *dd = vtkDistributedDataFilter::New(); + + dd->SetInput(ds); + dd->SetController(contr); + + dd->SetBoundaryModeToSplitBoundaryCells(); // clipping + dd->UseMinimalMemoryOff(); + + // COLOR BY PROCESS NUMBER + + vtkPieceScalars *ps = vtkPieceScalars::New(); + ps->SetInputConnection(dd->GetOutputPort()); + ps->SetScalarModeToCellData(); + + // MORE FILTERING - this will request ghost cells + + vtkDataSetSurfaceFilter *dss = vtkDataSetSurfaceFilter::New(); + dss->SetInputConnection(ps->GetOutputPort()); + + // COMPOSITE RENDER + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(dss->GetOutputPort()); + + mapper->SetColorModeToMapScalars(); + mapper->SetScalarModeToUseCellFieldData(); + mapper->SelectColorArray("Piece"); + mapper->SetScalarRange(0, NumProcs-1); + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + + vtkRenderer *renderer = prm->MakeRenderer(); + renderer->AddActor(actor); + + vtkRenderWindow *renWin = prm->MakeRenderWindow(); + renWin->AddRenderer(renderer); + + renderer->SetBackground(0,0,0); + renWin->SetSize(300,300); + renWin->SetPosition(0, 360*Me); + + prm->SetRenderWindow(renWin); + prm->SetController(contr); + + prm->InitializeOffScreen(); // Mesa GL only + + // We must update the whole pipeline here, otherwise node 0 + // goes into GetActiveCamera which updates the pipeline, putting + // it into vtkDistributedDataFilter::Execute() which then hangs. + // If it executes here, dd will be up-to-date won't have to + // execute in GetActiveCamera. + + mapper->SetPiece(Me); + mapper->SetNumberOfPieces(NumProcs); + mapper->Update(); + + if (Me == 0) + { + renderer->ResetCamera(); + vtkCamera *camera = renderer->GetActiveCamera(); + camera->UpdateViewport(renderer); + camera->ParallelProjectionOn(); + camera->SetParallelScale(16); + + renWin->Render(); + renWin->Render(); + + *(args->retVal) = vtkRegressionTester::Test(args->argc, args->argv, renWin, 10); + + for (i=1; i < NumProcs; i++) + { + contr->Send(args->retVal, 1, i, 0x11); + } + + prm->StopServices(); + } + else + { + prm->StartServices(); + contr->Receive(args->retVal, 1, 0, 0x11); + } + + if (*(args->retVal) == vtkTesting::PASSED) + { + // Now try using the memory conserving *Lean methods. The + // image produced should be identical + + dd->UseMinimalMemoryOn(); + mapper->SetPiece(Me); + mapper->SetNumberOfPieces(NumProcs); + mapper->Update(); + + if (Me == 0) + { + renderer->ResetCamera(); + vtkCamera *camera = renderer->GetActiveCamera(); + camera->UpdateViewport(renderer); + camera->ParallelProjectionOn(); + camera->SetParallelScale(16); + + renWin->Render(); + renWin->Render(); + + *(args->retVal) = vtkRegressionTester::Test(args->argc, args->argv, renWin, 10); + + for (i=1; i < NumProcs; i++) + { + contr->Send(args->retVal, 1, i, 0x11); + } + + prm->StopServices(); + } + else + { + prm->StartServices(); + contr->Receive(args->retVal, 1, 0, 0x11); + } + } + + // CLEAN UP + + mapper->Delete(); + actor->Delete(); + renderer->Delete(); + renWin->Delete(); + + dd->Delete(); + dsr->Delete(); + ug->Delete(); + + ps->Delete(); + dss->Delete(); + + prm->Delete(); +} + +int main(int argc, char **argv) +{ + int retVal = 1; + + vtkMPIController *contr = vtkMPIController::New(); + contr->Initialize(&argc, &argv); + + vtkMultiProcessController::SetGlobalController(contr); + + NumProcs = contr->GetNumberOfProcesses(); + Me = contr->GetLocalProcessId(); + + if (NumProcs != 2) + { + if (Me == 0) + { + cout << "DistributedData test requires 2 processes" << endl; + } + contr->Delete(); + return retVal; + } + + if (!contr->IsA("vtkMPIController")) + { + if (Me == 0) + { + cout << "DistributedData test requires MPI" << endl; + } + contr->Delete(); + return retVal; // is this the right error val? TODO + } + + // ---------------------------------------------- + DDArgs_tmp args; + args.retVal = &retVal; + args.argc = argc; + args.argv = argv; + // --------------------------------------------- + + contr->SetSingleMethod(Run, &args); + contr->SingleMethodExecute(); + + contr->Finalize(); + contr->Delete(); + + return !retVal; +} + diff --git a/Parallel/Testing/Cxx/GenericCommunicator.cxx b/Parallel/Testing/Cxx/GenericCommunicator.cxx new file mode 100644 index 0000000..5a321c2 --- /dev/null +++ b/Parallel/Testing/Cxx/GenericCommunicator.cxx @@ -0,0 +1,330 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: GenericCommunicator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCharArray.h" +#include "vtkCallbackCommand.h" +#include "vtkContourFilter.h" +#include "vtkDebugLeaks.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIdTypeArray.h" +#include "vtkIntArray.h" +#include "vtkMPIController.h" +#include "vtkParallelFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRTAnalyticSource.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkUnsignedLongArray.h" +#include "vtkImageData.h" + +#include "vtkDebugLeaks.h" +#include "vtkRegressionTestImage.h" + +#include + +static const int scMsgLength = 10; + +struct GenericCommunicatorArgs_tmp +{ + int* retVal; + int argc; + char** argv; +}; + +void Process2(vtkMultiProcessController *contr, void* vtkNotUsed(arg)) +{ + vtkCommunicator* comm = contr->GetCommunicator(); + + int i, retVal=1; + + // Test receiving all supported types of arrays + vtkIntArray* ia = vtkIntArray::New(); + if (!comm->Receive(ia, 0, 11)) + { + cerr << "Server error: Error receiving data." << endl; + retVal = 0; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (ia->GetValue(i) != i) + { + cerr << "Server error: Corrupt integer array." << endl; + retVal = 0; + break; + } + } + ia->Delete(); + + vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New(); + if (!comm->Receive(ula, 0, 22)) + { + cerr << "Server error: Error receiving data." << endl; + retVal = 0; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (ula->GetValue(i) != static_cast(i)) + { + cerr << "Server error: Corrupt unsigned long array." << endl; + retVal = 0; + break; + } + } + ula->Delete(); + + vtkCharArray* ca = vtkCharArray::New(); + if (!comm->Receive(ca, 0, 33)) + { + cerr << "Server error: Error receiving data." << endl; + retVal = 0; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (ca->GetValue(i) != static_cast(i)) + { + cerr << "Server error: Corrupt char array." << endl; + retVal = 0; + break; + } + } + ca->Delete(); + + vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New(); + if (!comm->Receive(uca, 0, 44)) + { + cerr << "Server error: Error receiving data." << endl; + retVal = 0; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (uca->GetValue(i) != static_cast(i)) + { + cerr << "Server error: Corrupt unsigned char array." << endl; + retVal = 0; + break; + } + } + uca->Delete(); + + vtkFloatArray* fa = vtkFloatArray::New(); + if (!comm->Receive(fa, 0, 7)) + { + cerr << "Server error: Error receiving data." << endl; + retVal = 0; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (fa->GetValue(i) != static_cast(i)) + { + cerr << "Server error: Corrupt float array." << endl; + retVal = 0; + break; + } + } + fa->Delete(); + + vtkDoubleArray* da = vtkDoubleArray::New(); + if (!comm->Receive(da, 0, 7)) + { + cerr << "Server error: Error receiving data." << endl; + retVal = 0; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (da->GetValue(i) != static_cast(i)) + { + cerr << "Server error: Corrupt double array." << endl; + retVal = 0; + break; + } + } + da->Delete(); + + vtkIdTypeArray* ita = vtkIdTypeArray::New(); + if (!comm->Receive(ita, 0, 7)) + { + cerr << "Server error: Error receiving data." << endl; + retVal = 0; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (ita->GetValue(i) != static_cast(i)) + { + cerr << "Server error: Corrupt vtkIdType array." << endl; + retVal = 0; + break; + } + } + ita->Delete(); + + comm->Send(&retVal, 1, 0, 11); +} + +void Process1(vtkMultiProcessController *contr, void *arg) +{ + GenericCommunicatorArgs_tmp* args = + reinterpret_cast(arg); + + vtkCommunicator* comm = contr->GetCommunicator(); + + int i; + + // Test sending all supported types of arrays + int datai[scMsgLength]; + for (i=0; iSetArray(datai, 10, 1); + if (!comm->Send(ia, 1, 11)) + { + cerr << "Client error: Error sending data." << endl; + *(args->retVal) = 0; + } + ia->Delete(); + + unsigned long dataul[scMsgLength]; + for (i=0; i(i); + } + vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New(); + ula->SetArray(dataul, 10, 1); + if (!comm->Send(ula, 1, 22)) + { + cerr << "Client error: Error sending data." << endl; + *(args->retVal) = 0; + } + ula->Delete(); + + char datac[scMsgLength]; + for (i=0; i(i); + } + vtkCharArray* ca = vtkCharArray::New(); + ca->SetArray(datac, 10, 1); + if (!comm->Send(ca, 1, 33)) + { + cerr << "Client error: Error sending data." << endl; + *(args->retVal) = 0; + } + ca->Delete(); + + unsigned char datauc[scMsgLength]; + for (i=0; i(i); + } + vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New(); + uca->SetArray(datauc, 10, 1); + if (!comm->Send(uca, 1, 44)) + { + cerr << "Client error: Error sending data." << endl; + *(args->retVal) = 0; + } + uca->Delete(); + + float dataf[scMsgLength]; + for (i=0; i(i); + } + vtkFloatArray* fa = vtkFloatArray::New(); + fa->SetArray(dataf, 10, 1); + if (!comm->Send(fa, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + *(args->retVal) = 0; + } + fa->Delete(); + + + double datad[scMsgLength]; + for (i=0; i(i); + } + vtkDoubleArray* da = vtkDoubleArray::New(); + da->SetArray(datad, 10, 1); + if (!comm->Send(da, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + *(args->retVal) = 0; + } + da->Delete(); + + vtkIdType datait[scMsgLength]; + for (i=0; i(i); + } + vtkIdTypeArray* ita = vtkIdTypeArray::New(); + ita->SetArray(datait, 10, 1); + if (!comm->Send(ita, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + *(args->retVal) = 0; + } + ita->Delete(); + + int remoteRetVal; + comm->Receive(&remoteRetVal, 1, 1, 11); + if (!remoteRetVal) + { + *(args->retVal) = 0; + } + +} + +int main(int argc, char** argv) +{ + // This is here to avoid false leak messages from vtkDebugLeaks when + // using mpich. It appears that the root process which spawns all the + // main processes waits in MPI_Init() and calls exit() when + // the others are done, causing apparent memory leaks for any objects + // created before MPI_Init(). + MPI_Init(&argc, &argv); + + vtkMPIController* contr = vtkMPIController::New(); + contr->Initialize(&argc, &argv,1); + contr->CreateOutputWindow(); + + vtkParallelFactory* pf = vtkParallelFactory::New(); + vtkObjectFactory::RegisterFactory(pf); + pf->Delete(); + + // Added for regression test. + // ---------------------------------------------- + int retVal = 1; + GenericCommunicatorArgs_tmp args; + args.retVal = &retVal; + args.argc = argc; + args.argv = argv; + // ---------------------------------------------- + + contr->SetMultipleMethod(0, Process1, &args); + contr->SetMultipleMethod(1, Process2, 0); + contr->MultipleMethodExecute(); + + contr->Finalize(); + contr->Delete(); + + return !retVal; +} diff --git a/Parallel/Testing/Cxx/MPIGroups.cxx b/Parallel/Testing/Cxx/MPIGroups.cxx new file mode 100644 index 0000000..1d54243 --- /dev/null +++ b/Parallel/Testing/Cxx/MPIGroups.cxx @@ -0,0 +1,315 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: MPIGroups.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMPIController.h" +#include "vtkSphereSource.h" +#include "vtkPolyDataNormals.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyData.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkCompositeRenderManager.h" +#include "vtkDebugLeaks.h" +#include "vtkParallelFactory.h" +#include "vtkRegressionTestImage.h" +#include "vtkMPIGroup.h" + +static const int NUM_PROC_PER_GROUP = 2; + +struct MPIGroupsArgs_tmp +{ + int* retVal; + int argc; + char** argv; +}; + +void proc1( vtkMultiProcessController *controller, void *arg ); +void proc2( vtkMultiProcessController *controller, void *arg ); + +void MyMain( vtkMultiProcessController *controller, void *arg ) +{ + + MPIGroupsArgs_tmp* args = + reinterpret_cast(arg); + + int myId = controller->GetLocalProcessId(); + + vtkMPICommunicator* localComm = vtkMPICommunicator::New(); + vtkMPIGroup* localGroup= vtkMPIGroup::New(); + vtkMPIController* localController = vtkMPIController::New(); + vtkMPICommunicator* worldComm = vtkMPICommunicator::GetWorldCommunicator(); + + int currentGroup = myId / NUM_PROC_PER_GROUP; + + localGroup->Initialize( static_cast(controller) ); + for(int i=0; iAddProcessId(currentGroup*NUM_PROC_PER_GROUP + i); + } + localComm->Initialize(worldComm, localGroup); + localGroup->UnRegister(0); + + // Create a local controller (for the sub-group) + localController->SetCommunicator(localComm); + localComm->UnRegister(0); + + int locRetVal; + if ( currentGroup == 0 ) + { + localController->SetSingleMethod(proc1, arg); + localController->SingleMethodExecute(); + } + else if ( currentGroup == 1 ) + { + localController->SetSingleMethod(proc2, &locRetVal); + localController->SingleMethodExecute(); + } + localController->Delete(); + + if ( myId == 0 ) + { + controller->Receive(&locRetVal, 1, 3, 33); + if (args->retVal && (!locRetVal)) + { + *(args->retVal) = locRetVal; + } + } + else if (myId == 3) + { + controller->Send(&locRetVal, 1, 0, 33); + } +} + +// This will be called by all processes +void proc1( vtkMultiProcessController *controller, void *arg ) +{ + + MPIGroupsArgs_tmp* args = + reinterpret_cast(arg); + + int myid, numProcs; + + // Obtain the id of the running process and the total + // number of processes + myid = controller->GetLocalProcessId(); + numProcs = controller->GetNumberOfProcesses(); + + vtkSphereSource* sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(16); + sphere->SetPhiResolution(16); + + vtkPolyDataNormals* pdn = vtkPolyDataNormals::New(); + pdn->SetInputConnection(sphere->GetOutputPort()); + sphere->UnRegister(0); + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(pdn->GetOutputPort()); + pdn->UnRegister(0); + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + mapper->UnRegister(0); + + vtkRenderer *ren = vtkRenderer::New(); + ren->AddActor(actor); + actor->UnRegister(0); + + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + ren->UnRegister(0); + renWin->SetPosition(0, 360 * myid); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The only thing we have to do to get parallel execution. + vtkCompositeRenderManager* treeComp = vtkCompositeRenderManager::New(); + treeComp->SetController(controller); + treeComp->SetRenderWindow(renWin); + + // Tell the mappers to only update a piece (based on process) of + // their inputs. + treeComp->InitializePieces(); + + if (myid) + { + treeComp->InitializeRMIs(); + controller->ProcessRMIs(); + controller->Receive(args->retVal, 1, 0, 33); + } + else + { + renWin->Render(); + renWin->Render(); + *(args->retVal) = + vtkRegressionTester::Test(args->argc, args->argv, renWin, 10); + for (int i = 1; i < numProcs; i++) + { + controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG); + controller->Send(args->retVal, 1, i, 33); + } + } + + if (!myid) + { + } + + if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR) + { + treeComp->StartInteractor(); + } + + iren->Delete(); + renWin->Delete(); + treeComp->Delete(); +} + +void proc2( vtkMultiProcessController *contr, void *arg ) +{ + vtkMPIController* controller = static_cast(contr); + + if (controller->GetLocalProcessId() == 0) + { + int vali = 12; + vtkMPICommunicator::Request req1; + controller->NoBlockSend(&vali, 1, 1, 95, req1); + int valul = 12; + vtkMPICommunicator::Request req2; + controller->NoBlockSend(&valul, 1, 1, 96, req2); + int valc = 12; + vtkMPICommunicator::Request req3; + controller->NoBlockSend(&valc, 1, 1, 97, req3); + int valf = 12; + vtkMPICommunicator::Request req4; + controller->NoBlockSend(&valf, 1, 1, 98, req4); + } + else if (controller->GetLocalProcessId() == 1) + { + int* retVal = static_cast(arg); + *retVal = 1; + + int vali; + vtkMPICommunicator::Request req1; + controller->NoBlockReceive(&vali, 1, vtkMultiProcessController::ANY_SOURCE, + 95, req1); + req1.Wait(); + if (req1.Test() && (vali == 12)) + { + cout << "Receive (int) succeeded." << endl; + } + else + { + cout << "Receive (int) failed:" << vali << endl; + *retVal = 0; + } + int valul; + vtkMPICommunicator::Request req2; + controller->NoBlockReceive(&valul, 1, vtkMultiProcessController::ANY_SOURCE, + 96, req2); + req2.Wait(); + if (req2.Test() && (valul == 12)) + { + cout << "Receive (unsigned long) succeeded." << endl; + } + else + { + cout << "Receive (unsigned long) failed:" << valul << endl; + *retVal = 0; + } + int valc; + vtkMPICommunicator::Request req3; + controller->NoBlockReceive(&valc, 1, vtkMultiProcessController::ANY_SOURCE, + 97, req3); + req3.Wait(); + if (req3.Test() && (valc == 12)) + { + cout << "Receive (char) succeeded." << endl; + } + else + { + cout << "Receive (char) failed:" << valc << endl; + *retVal = 0; + } + int valf; + vtkMPICommunicator::Request req4; + controller->NoBlockReceive(&valf, 1, vtkMultiProcessController::ANY_SOURCE, + 98, req4); + req4.Wait(); + if (req4.Test() && (valf == 12)) + { + cout << "Receive (float) succeeded." << endl; + } + else + { + cout << "Receive (float) failed:" << valf << endl; + *retVal = 0; + } + } + + // Just for coverage + controller->Barrier(); + +} + +int main( int argc, char* argv[] ) +{ + vtkMPIController *controller; + + // Note that this will create a vtkMPIController if MPI + // is configured, vtkMPIController otherwise. + controller = vtkMPIController::New(); + + controller->Initialize(&argc, &argv); + + int numProcs = controller->GetNumberOfProcesses(); + int myId = controller->GetLocalProcessId(); + if (numProcs != 4) + { + if (!myId) + { + cerr << "This program requires 4 processes." << endl; + } + controller->Finalize(); + controller->Delete(); + return -1; + } + + vtkParallelFactory* pf = vtkParallelFactory::New(); + vtkObjectFactory::RegisterFactory(pf); + pf->Delete(); + + // Added for regression test. + // ---------------------------------------------- + int retVal; + MPIGroupsArgs_tmp args; + args.retVal = &retVal; + args.argc = argc; + args.argv = argv; + // ---------------------------------------------- + + controller->SetSingleMethod(MyMain, &args); + controller->SingleMethodExecute(); + + controller->Finalize(); + controller->Delete(); + + return !retVal; +} + + + + + diff --git a/Parallel/Testing/Cxx/ParallelIso.cxx b/Parallel/Testing/Cxx/ParallelIso.cxx new file mode 100644 index 0000000..2ea312d --- /dev/null +++ b/Parallel/Testing/Cxx/ParallelIso.cxx @@ -0,0 +1,272 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ParallelIso.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This example demonstrates the use of data parallelism in VTK. The +// pipeline ( vtkImageReader -> vtkContourFilter -> vtkElevationFilter ) +// is created in parallel and each process is assigned 1 piece to process. +// All satellite processes send the result to the first process which +// collects and renders them. + +#include "vtkActor.h" +#include "vtkAppendPolyData.h" +#include "vtkCamera.h" +#include "vtkConeSource.h" +#include "vtkContourFilter.h" +#include "vtkDataSet.h" +#include "vtkElevationFilter.h" +#include "vtkImageReader.h" +#include "vtkMath.h" +#include "vtkMPIController.h" +#include "vtkParallelFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkWindowToImageFilter.h" +#include "vtkImageData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkInformation.h" + +#include "vtkDebugLeaks.h" + +#include + +static const float ISO_START=4250.0; +static const float ISO_STEP=-1250.0; +static const int ISO_NUM=3; +// Just pick a tag which is available +static const int ISO_VALUE_RMI_TAG=300; +static const int ISO_OUTPUT_TAG=301; + +struct ParallelIsoArgs_tmp +{ + int* retVal; + int argc; + char** argv; +}; + +struct ParallelIsoRMIArgs_tmp +{ + vtkContourFilter* ContourFilter; + vtkMultiProcessController* Controller; + vtkElevationFilter* Elevation; +}; + +// call back to set the iso surface value. +void SetIsoValueRMI(void *localArg, void* vtkNotUsed(remoteArg), + int vtkNotUsed(remoteArgLen), int vtkNotUsed(id)) +{ + ParallelIsoRMIArgs_tmp* args = (ParallelIsoRMIArgs_tmp*)localArg; + + float val; + + vtkContourFilter *iso = args->ContourFilter; + val = iso->GetValue(0); + iso->SetValue(0, val + ISO_STEP); + args->Elevation->Update(); + + vtkMultiProcessController* contrl = args->Controller; + contrl->Send(args->Elevation->GetOutput(), 0, ISO_OUTPUT_TAG); +} + + +// This will be called by all processes +void MyMain( vtkMultiProcessController *controller, void *arg ) +{ + vtkImageReader *reader; + vtkContourFilter *iso; + vtkElevationFilter *elev; + int myid, numProcs; + float val; + ParallelIsoArgs_tmp* args = reinterpret_cast(arg); + + // Obtain the id of the running process and the total + // number of processes + myid = controller->GetLocalProcessId(); + numProcs = controller->GetNumberOfProcesses(); + + // Create the reader, the data file name might have + // to be changed depending on where the data files are. + char* fname = vtkTestUtilities::ExpandDataFileName(args->argc, args->argv, + "Data/headsq/quarter"); + reader = vtkImageReader::New(); + reader->SetDataByteOrderToLittleEndian(); + reader->SetDataExtent(0, 63, 0, 63, 1, 93); + reader->SetFilePrefix(fname); + reader->SetDataSpacing(3.2, 3.2, 1.5); + delete[] fname; + + // Iso-surface. + iso = vtkContourFilter::New(); + iso->SetInputConnection(reader->GetOutputPort()); + iso->SetValue(0, ISO_START); + iso->ComputeScalarsOff(); + iso->ComputeGradientsOff(); + + // Compute a different color for each process. + elev = vtkElevationFilter::New(); + elev->SetInputConnection(iso->GetOutputPort()); + val = (myid+1) / static_cast(numProcs); + elev->SetScalarRange(val, val+0.001); + + // Tell the pipeline which piece we want to update. + vtkStreamingDemandDrivenPipeline* exec = + vtkStreamingDemandDrivenPipeline::SafeDownCast(elev->GetExecutive()); + exec->SetUpdateNumberOfPieces(exec->GetOutputInformation(0), numProcs); + exec->SetUpdatePiece(exec->GetOutputInformation(0), myid); + + if (myid != 0) + { + // If I am not the root process + ParallelIsoRMIArgs_tmp args; + args.ContourFilter = iso; + args.Controller = controller; + args.Elevation = elev; + + // Last, set up a RMI call back to change the iso surface value. + // This is done so that the root process can let this process + // know that it wants the contour value to change. + controller->AddRMI(SetIsoValueRMI, (void *)&args, ISO_VALUE_RMI_TAG); + controller->ProcessRMIs(); + } + else + { + // Create the rendering part of the pipeline + vtkAppendPolyData *app = vtkAppendPolyData::New(); + vtkRenderer *ren = vtkRenderer::New(); + vtkRenderWindow *renWindow = vtkRenderWindow::New(); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + vtkActor *actor = vtkActor::New(); + vtkCamera *cam = vtkCamera::New(); + renWindow->AddRenderer(ren); + iren->SetRenderWindow(renWindow); + ren->SetBackground(0.9, 0.9, 0.9); + renWindow->SetSize( 400, 400); + mapper->SetInputConnection(app->GetOutputPort()); + actor->SetMapper(mapper); + ren->AddActor(actor); + cam->SetFocalPoint(100, 100, 65); + cam->SetPosition(100, 450, 65); + cam->SetViewUp(0, 0, -1); + cam->SetViewAngle(30); + cam->SetClippingRange(177.0, 536.0); + ren->SetActiveCamera(cam); + + // loop through some iso surface values. + for (int j = 0; j < ISO_NUM; ++j) + { + // set the local value + iso->SetValue(0, iso->GetValue(0) + ISO_STEP); + elev->Update(); + + for (int i = 1; i < numProcs; ++i) + { + // trigger the RMI to change the iso surface value. + controller->TriggerRMI(i, ISO_VALUE_RMI_TAG); + } + for (int i = 1; i < numProcs; ++i) + { + vtkPolyData* pd = vtkPolyData::New(); + controller->Receive(pd, i, ISO_OUTPUT_TAG); + if (j == ISO_NUM - 1) + { + app->AddInput(pd); + } + pd->Delete(); + } + } + + // Tell the other processors to stop processing RMIs. + for (int i = 1; i < numProcs; ++i) + { + controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG); + } + + vtkPolyData* outputCopy = vtkPolyData::New(); + outputCopy->ShallowCopy(elev->GetOutput()); + app->AddInput(outputCopy); + outputCopy->Delete(); + app->Update(); + renWindow->Render(); + + *(args->retVal) = + vtkRegressionTester::Test(args->argc, args->argv, renWindow, 10); + + if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + app->Delete(); + ren->Delete(); + renWindow->Delete(); + iren->Delete(); + mapper->Delete(); + actor->Delete(); + cam->Delete(); + } + + // clean up objects in all processes. + reader->Delete(); + iso->Delete(); + elev->Delete(); +} + + +int main( int argc, char* argv[] ) +{ + // This is here to avoid false leak messages from vtkDebugLeaks when + // using mpich. It appears that the root process which spawns all the + // main processes waits in MPI_Init() and calls exit() when + // the others are done, causing apparent memory leaks for any objects + // created before MPI_Init(). + MPI_Init(&argc, &argv); + + // Note that this will create a vtkMPIController if MPI + // is configured, vtkThreadedController otherwise. + vtkMPIController* controller = vtkMPIController::New(); + + controller->Initialize(&argc, &argv, 1); + + vtkParallelFactory* pf = vtkParallelFactory::New(); + vtkObjectFactory::RegisterFactory(pf); + pf->Delete(); + + // Added for regression test. + // ---------------------------------------------- + int retVal = 1; + ParallelIsoArgs_tmp args; + args.retVal = &retVal; + args.argc = argc; + args.argv = argv; + // ---------------------------------------------- + + controller->SetSingleMethod(MyMain, &args); + controller->SingleMethodExecute(); + + controller->Finalize(); + controller->Delete(); + + return !retVal; +} + + + + + diff --git a/Parallel/Testing/Cxx/SocketClient.cxx b/Parallel/Testing/Cxx/SocketClient.cxx new file mode 100644 index 0000000..3ae3b3c --- /dev/null +++ b/Parallel/Testing/Cxx/SocketClient.cxx @@ -0,0 +1,346 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SocketClient.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkContourFilter.h" +#include "vtkDataSetMapper.h" +#include "vtkDebugLeaks.h" +#include "vtkDoubleArray.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRectilinearGrid.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkSocketCommunicator.h" +#include "vtkSocketController.h" +#include "vtkStructuredGrid.h" +#include "vtkImageData.h" +#include "vtkUnstructuredGrid.h" +#include "vtkCamera.h" +#include "vtkImageActor.h" + +#include "vtkRenderWindowInteractor.h" + +static const int scMsgLength = 10; + +static void CleanUp(vtkSocketCommunicator* comm, vtkSocketController* contr) +{ + // This will close the connection as well as delete + // the communicator + comm->Delete(); + contr->Delete(); +} + +int main(int argc, char** argv) +{ + vtkSocketController* contr = vtkSocketController::New(); + contr->Initialize(); + + vtkSocketCommunicator* comm = vtkSocketCommunicator::New(); + + int i; + + // Get the host name from the command line arguments + char* hostname = new char[30]; + strcpy(hostname, "localhost"); + int dataIndex=-1; + for (i=0; iConnectTo(hostname, port)) + { + cerr << "Client error: Could not connect to the server." + << endl; + comm->Delete(); + contr->Delete(); + delete[] hostname; + return 1; + } + delete[] hostname; + + // Test sending all supported types of arrays + int datai[scMsgLength]; + for (i=0; iSend(datai, scMsgLength, 1, 11)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + unsigned long dataul[scMsgLength]; + for (i=0; i(i); + } + if (!comm->Send(dataul, scMsgLength, 1, 22)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + char datac[scMsgLength]; + for (i=0; i(i); + } + if (!comm->Send(datac, scMsgLength, 1, 33)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + unsigned char datauc[scMsgLength]; + for (i=0; i(i); + } + if (!comm->Send(datauc, scMsgLength, 1, 44)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + float dataf[scMsgLength]; + for (i=0; i(i); + } + if (!comm->Send(dataf, scMsgLength, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + + double datad[scMsgLength]; + for (i=0; i(i); + } + if (!comm->Send(datad, scMsgLength, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + vtkIdType datait[scMsgLength]; + for (i=0; i(i); + } + if (!comm->Send(datait, scMsgLength, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + // Test receiving vtkDataObject + vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New(); + + if (!comm->Receive(ugrid, 1, 9)) + { + cerr << "Client error: Error receiving data." << endl; + CleanUp(comm, contr); + ugrid->Delete(); + return 1; + } + + vtkDataSetMapper* umapper = vtkDataSetMapper::New(); + umapper->SetInput(ugrid); + + vtkActor* uactor = vtkActor::New(); + uactor->SetMapper(umapper); + uactor->SetPosition(5, 0, 0); + uactor->SetScale(0.2, 0.2, 0.2); + umapper->UnRegister(0); + + // Test receiving vtkDataArray + vtkDoubleArray* da = vtkDoubleArray::New(); + if (!comm->Receive(da, 1, 9)) + { + cerr << "Client error: Error receiving data." << endl; + CleanUp(comm, contr); + ugrid->Delete(); + uactor->Delete(); + da->Delete(); + return 1; + } + for (i=0; i<40; i++) + { + if (da->GetValue(i) != static_cast(i)) + { + cerr << "Server error: Corrupt vtkDoubleArray." << endl; + CleanUp(comm, contr); + ugrid->Delete(); + uactor->Delete(); + da->Delete(); + return 1; + } + } + + da->Delete(); + + // Test receiving null vtkDataArray + vtkDoubleArray *da2 = vtkDoubleArray::New(); + if (!comm->Receive(da2, 1, 9)) + { + cerr << "Client error: Error receiving data." << endl; + CleanUp(comm, contr); + ugrid->Delete(); + uactor->Delete(); + da2->Delete(); + return 1; + } + if (da2->GetNumberOfTuples() == 0) + { + cout << "receive null data array successful" << endl; + } + else + { + cout << "receive null data array failed" << endl; + } + da2->Delete(); + + contr->SetCommunicator(comm); + + // The following lines were added for coverage + // These methods have empty implementations + contr->SingleMethodExecute(); + contr->MultipleMethodExecute(); + contr->CreateOutputWindow(); + contr->Barrier(); + contr->Finalize(); + + vtkPolyDataMapper* pmapper = vtkPolyDataMapper::New(); + vtkPolyData* pd = vtkPolyData::New(); + comm->Receive(pd, 1, 11); + pmapper->SetInput(pd); + pd->Delete(); + + vtkActor* pactor = vtkActor::New(); + pactor->SetMapper(pmapper); + pmapper->UnRegister(0); + + vtkDataSetMapper* rgmapper = vtkDataSetMapper::New(); + vtkRectilinearGrid* rg = vtkRectilinearGrid::New(); + comm->Receive(rg, 1, 11); + rgmapper->SetInput(rg); + rg->Delete(); + + vtkActor* rgactor = vtkActor::New(); + rgactor->SetMapper(rgmapper); + rgactor->SetPosition(0, -5, 0); + rgactor->SetScale(2, 2, 2); + rgmapper->UnRegister(0); + + vtkContourFilter* iso2 = vtkContourFilter::New(); + vtkStructuredGrid* sg = vtkStructuredGrid::New(); + comm->Receive(sg, 1, 11); + iso2->SetInput(sg); + sg->Delete(); + iso2->SetValue(0, .205); + + vtkPolyDataMapper* sgmapper = vtkPolyDataMapper::New(); + sgmapper->SetInputConnection(0, iso2->GetOutputPort()); + iso2->UnRegister(0); + + vtkActor* sgactor = vtkActor::New(); + sgactor->SetMapper(sgmapper); + sgactor->SetPosition(10, -5, -40); + sgmapper->UnRegister(0); + + + vtkImageData* id = vtkImageData::New(); + comm->Receive(id, 1, 11); + + vtkImageActor* imactor = vtkImageActor::New(); + imactor->SetInput(id); + id->Delete(); + imactor->SetPosition(10, 0, 10); + imactor->SetScale(0.02, 0.02, 0.02); + + vtkRenderer* ren = vtkRenderer::New(); + ren->AddActor(uactor); + ren->AddActor(pactor); + ren->AddActor(rgactor); + ren->AddActor(sgactor); + ren->AddActor(imactor); + uactor->UnRegister(0); + pactor->UnRegister(0); + rgactor->UnRegister(0); + sgactor->UnRegister(0); + imactor->UnRegister(0); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->SetSize(500,400); + renWin->AddRenderer(ren); + ren->ResetCamera(); + ren->GetActiveCamera()->Zoom(2.2); + ren->UnRegister(0); + + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + + renWin->Delete(); + ugrid->Delete(); + CleanUp(comm, contr); + + return !retVal; +} diff --git a/Parallel/Testing/Cxx/SocketServer.cxx b/Parallel/Testing/Cxx/SocketServer.cxx new file mode 100644 index 0000000..0168628 --- /dev/null +++ b/Parallel/Testing/Cxx/SocketServer.cxx @@ -0,0 +1,292 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: SocketServer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBYUReader.h" +#include "vtkDebugLeaks.h" +#include "vtkDoubleArray.h" +#include "vtkPLOT3DReader.h" +#include "vtkPNMReader.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkRectilinearGridReader.h" +#include "vtkTestUtilities.h" +#include "vtkSocketCommunicator.h" +#include "vtkSocketController.h" +#include "vtkStructuredGrid.h" +#include "vtkImageData.h" +#include "vtkDataSetReader.h" +#include "vtkUnstructuredGrid.h" +#include "vtkUnstructuredGridReader.h" + +static const int scMsgLength = 10; + +static void CleanUp(vtkSocketCommunicator* comm, vtkSocketController* contr) +{ + comm->CloseConnection(); + comm->Delete(); + contr->Delete(); +} + +int main(int argc, char** argv) +{ + vtkSocketController* contr = vtkSocketController::New(); + contr->Initialize(); + + vtkSocketCommunicator* comm = vtkSocketCommunicator::New(); + + int port=11111; + + int i; + + // Get the port from the command line arguments + int dataIndex=-1; + for (i=0; iWaitForConnection(port)) + { + cerr << "Server error: Wait timed out or could not initialize socket." + << endl; + comm->Delete(); + contr->Delete(); + return 1; + } + + + // Test receiving all supported types of arrays + int datai[scMsgLength]; + if (!comm->Receive(datai, scMsgLength, 1, 11)) + { + cerr << "Server error: Error receiving data." << endl; + CleanUp(comm, contr); + return 1; + } + for (i=0; iReceive(dataul, scMsgLength, 1, 22)) + { + cerr << "Server error: Error receiving data." << endl; + CleanUp(comm, contr); + return 1; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt unsigned long array." << endl; + CleanUp(comm, contr); + return 1; + } + } + + char datac[scMsgLength]; + if (!comm->Receive(datac, scMsgLength, 1, 33)) + { + cerr << "Server error: Error receiving data." << endl; + CleanUp(comm, contr); + return 1; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt char array." << endl; + CleanUp(comm, contr); + return 1; + } + } + + unsigned char datauc[scMsgLength]; + if (!comm->Receive(datauc, scMsgLength, 1, 44)) + { + cerr << "Server error: Error receiving data." << endl; + CleanUp(comm, contr); + return 1; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt unsigned char array." << endl; + CleanUp(comm, contr); + return 1; + } + } + + float dataf[scMsgLength]; + if (!comm->Receive(dataf, scMsgLength, 1, 7)) + { + cerr << "Server error: Error receiving data." << endl; + CleanUp(comm, contr); + return 1; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt float array." << endl; + CleanUp(comm, contr); + return 1; + } + } + + + double datad[scMsgLength]; + if (!comm->Receive(datad, scMsgLength, 1, 7)) + { + cerr << "Server error: Error receiving data." << endl; + CleanUp(comm, contr); + return 1; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt double array." << endl; + CleanUp(comm, contr); + return 1; + } + } + + vtkIdType datait[scMsgLength]; + if (!comm->Receive(datait, scMsgLength, 1, 7)) + { + cerr << "Server error: Error receiving data." << endl; + CleanUp(comm, contr); + return 1; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt vtkIdType array." << endl; + CleanUp(comm, contr); + return 1; + } + } + + + // Test sending vtkDataObject + vtkUnstructuredGridReader* ugrid = vtkUnstructuredGridReader::New(); + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, + "Data/blow.vtk"); + ugrid->SetFileName(fname); + delete[] fname; + + ugrid->Update(); + + if (!comm->Send(ugrid->GetOutput(), 1, 9)) + { + cerr << "Server error: Error sending data." << endl; + CleanUp(comm, contr); + ugrid->Delete(); + return 1; + } + ugrid->Delete(); + + // Test receiving vtkDataArray + vtkDoubleArray* da = vtkDoubleArray::New(); + da->SetNumberOfComponents(4); + da->SetNumberOfTuples(10); + for(i=0; i<40; i++) + { + da->SetValue(i,static_cast(i)); + } + if (!comm->Send(da, 1, 9)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + da->Delete(); + return 1; + } + da->Delete(); + + // Test receiving null vtkDataArray + vtkDoubleArray *da2 = NULL; + if (!comm->Send(da2, 1, 9)) + { + cerr << "Client error: Error sending data." << endl; + CleanUp(comm, contr); + return 1; + } + + contr->SetCommunicator(comm); + + vtkBYUReader* pd = vtkBYUReader::New(); + fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/teapot.g"); + pd->SetGeometryFileName(fname); + delete[] fname; + + pd->Update(); + + comm->Send(pd->GetOutput(), 1, 11); + + vtkRectilinearGridReader* rgrid = vtkRectilinearGridReader::New(); + fname = vtkTestUtilities::ExpandDataFileName(argc, argv, + "Data/RectGrid2.vtk"); + rgrid->SetFileName(fname); + delete[] fname; + + rgrid->Update(); + + comm->Send(rgrid->GetOutput(), 1, 11); + + vtkPLOT3DReader* pl3d = vtkPLOT3DReader::New(); + fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combxyz.bin"); + pl3d->SetXYZFileName(fname); + delete[] fname; + fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combq.bin"); + pl3d->SetQFileName(fname); + delete[] fname; + pl3d->SetScalarFunctionNumber(100); + pl3d->SetVectorFunctionNumber(202); + + pl3d->Update(); + + comm->Send(pl3d->GetOutput(), 1, 11); + + vtkPNMReader* imageData = vtkPNMReader::New(); + fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/earth.ppm"); + imageData->SetFileName(fname); + delete[] fname; + + imageData->Update(); + + comm->Send(imageData->GetOutput(), 1, 11); + + CleanUp(comm, contr); + return 0; +} diff --git a/Parallel/Testing/Cxx/TestPStream.cxx b/Parallel/Testing/Cxx/TestPStream.cxx new file mode 100644 index 0000000..ab9b557 --- /dev/null +++ b/Parallel/Testing/Cxx/TestPStream.cxx @@ -0,0 +1,253 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestPStream.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCompositeRenderManager.h" +#include "vtkDebugLeaks.h" +#include "vtkDistributedStreamTracer.h" +#include "vtkLineSource.h" +#include "vtkLookupTable.h" +#include "vtkMPIController.h" +#include "vtkObjectFactory.h" +#include "vtkPLOT3DReader.h" +#include "vtkGeometryFilter.h" +#include "vtkParallelFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridOutlineFilter.h" + +struct PStreamArgs_tmp +{ + int* retVal; + int argc; + char** argv; +}; + +// This will be called by all processes +void MyMain( vtkMultiProcessController *controller, void *arg ) +{ + + PStreamArgs_tmp* args = + reinterpret_cast(arg); + + int myId = controller->GetLocalProcessId(); + int numProcs = controller->GetNumberOfProcesses(); + + vtkRenderer* ren = vtkRenderer::New(); + ren->SetBackground(0.33, 0.35, 0.43); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + renWin->SetSize(400, 300); + renWin->SetPosition(0, 350 * myId); + + //camera parameters + vtkCamera* camera = ren->GetActiveCamera(); + camera->SetPosition(-5.86786, 49.2857, 51.597); + camera->SetFocalPoint(8.255, -3.17482e-16, 29.7631); + camera->SetViewUp(-0.112182, -0.42918, 0.896225); + camera->SetViewAngle(30); + camera->SetClippingRange(10.0, 80.6592); + camera->Dolly(1.5); + + // Create the reader, the data file name might have + // to be changed depending on where the data files are. + char* fname1 = vtkTestUtilities::ExpandDataFileName(args->argc, args->argv, + "Data/combxyz.bin"); + char* fname2 = vtkTestUtilities::ExpandDataFileName(args->argc, args->argv, + "Data/combq.bin"); + vtkPLOT3DReader* Plot3D0 = vtkPLOT3DReader::New(); + Plot3D0->SetFileName(fname1); + Plot3D0->SetQFileName (fname2); + Plot3D0->SetBinaryFile(1); + Plot3D0->SetMultiGrid(0); + Plot3D0->SetHasByteCount(0); + Plot3D0->SetIBlanking(0); + Plot3D0->SetTwoDimensionalGeometry(0); + Plot3D0->SetForceRead(0); + Plot3D0->SetByteOrder(0); + delete[] fname1; + delete[] fname2; + + vtkStructuredGridOutlineFilter* Geometry5 = + vtkStructuredGridOutlineFilter::New(); + Geometry5->SetInputConnection(Plot3D0->GetOutputPort()); + + vtkPolyDataMapper* Mapper5 = vtkPolyDataMapper::New(); + Mapper5->SetInputConnection(Geometry5->GetOutputPort()); + Mapper5->SetImmediateModeRendering(1); + Mapper5->UseLookupTableScalarRangeOn(); + Mapper5->SetScalarVisibility(0); + Mapper5->SetScalarModeToDefault(); + + vtkActor* Actor5 = vtkActor::New(); + Actor5->SetMapper(Mapper5); + vtkProperty* prop = Actor5->GetProperty(); + prop->SetRepresentationToSurface(); + prop->SetInterpolationToGouraud(); + prop->SetAmbient(0.15); + prop->SetDiffuse(0.85); + prop->SetSpecular(0.1); + prop->SetSpecularPower(100); + prop->SetSpecularColor(1, 1, 1); + prop->SetColor(1, 1, 1); + + ren->AddActor(Actor5); + + vtkLineSource* LineSourceWidget0 = vtkLineSource::New(); + LineSourceWidget0->SetPoint1(13.9548, -0.47371, 31.7642); + LineSourceWidget0->SetPoint2(6.3766, -0.5886, 26.6274); + LineSourceWidget0->SetResolution(20); + + vtkDistributedStreamTracer* Stream0 = vtkDistributedStreamTracer::New();; + Stream0->SetInputConnection(Plot3D0->GetOutputPort()); + Stream0->SetSource(LineSourceWidget0->GetOutput()); + Stream0->SetMaximumPropagationUnit(0); + Stream0->SetMaximumPropagation(0.05); + Stream0->SetInitialIntegrationStepUnit(2); + Stream0->SetInitialIntegrationStep(0.5); + Stream0->SetIntegrationDirection(2); + Stream0->SetIntegratorType(0); + Stream0->SetMaximumNumberOfSteps(2000); + Stream0->SetTerminalSpeed(1e-12); + + vtkGeometryFilter* Geometry6 = vtkGeometryFilter::New();; + Geometry6->SetInputConnection(Stream0->GetOutputPort()); + + vtkLookupTable* LookupTable1 = vtkLookupTable::New(); + LookupTable1->SetNumberOfTableValues(256); + LookupTable1->SetHueRange(0, 0.66667); + LookupTable1->SetSaturationRange(1, 1); + LookupTable1->SetValueRange(1, 1); + LookupTable1->SetTableRange(0.197813, 0.710419); + LookupTable1->SetVectorComponent(0); + LookupTable1->Build(); + + vtkPolyDataMapper* Mapper6 = vtkPolyDataMapper::New(); + Mapper6->SetInputConnection(Geometry6->GetOutputPort()); + Mapper6->SetImmediateModeRendering(1); + Mapper6->UseLookupTableScalarRangeOn(); + Mapper6->SetScalarVisibility(1); + Mapper6->SetScalarModeToUsePointFieldData(); + Mapper6->SelectColorArray("Density"); + Mapper6->SetLookupTable(LookupTable1); + + vtkActor* Actor6 = vtkActor::New(); + Actor6->SetMapper(Mapper6); + prop = Actor6->GetProperty(); + prop->SetRepresentationToSurface(); + prop->SetInterpolationToGouraud(); + prop->SetAmbient(0.15); + prop->SetDiffuse(0.85); + prop->SetSpecular(0); + prop->SetSpecularPower(1); + prop->SetSpecularColor(1, 1, 1); + + ren->AddActor(Actor6); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkCompositeRenderManager* compManager = vtkCompositeRenderManager::New(); + compManager->SetRenderWindow(renWin); + compManager->SetController(controller); + compManager->InitializePieces(); + + if (myId) + { + compManager->InitializeRMIs(); + controller->ProcessRMIs(); + controller->Receive(args->retVal, 1, 0, 33); + } + else + { + renWin->Render(); + *(args->retVal) = + vtkRegressionTester::Test(args->argc, args->argv, renWin, 10); + for (int i = 1; i < numProcs; i++) + { + controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG); + controller->Send(args->retVal, 1, i, 33); + } + } + + if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR) + { + compManager->StartInteractor(); + } + renWin->Delete(); + ren->Delete(); + iren->Delete(); + compManager->Delete(); + Plot3D0->Delete(); + Stream0->Delete(); + LookupTable1->Delete(); + LineSourceWidget0->Delete(); + Geometry5->Delete(); + Geometry6->Delete(); + Actor5->Delete(); + Actor6->Delete(); + Mapper5->Delete(); + Mapper6->Delete(); +} + +int main( int argc, char* argv[] ) +{ + vtkMPIController* contr = vtkMPIController::New(); + contr->Initialize(&argc, &argv); + contr->CreateOutputWindow(); + + vtkParallelFactory* pf = vtkParallelFactory::New(); + vtkObjectFactory::RegisterFactory(pf); + pf->Delete(); + + // When using MPI, the number of processes is determined + // by the external program which launches this application. + // However, when using threads, we need to set it ourselves. + if (contr->IsA("vtkThreadedController")) + { + // Set the number of processes to 2 for this example. + contr->SetNumberOfProcesses(2); + } + + // Added for regression test. + // ---------------------------------------------- + int retVal; + PStreamArgs_tmp args; + args.retVal = &retVal; + args.argc = argc; + args.argv = argv; + // ---------------------------------------------- + + contr->SetSingleMethod(MyMain, &args); + contr->SingleMethodExecute(); + + contr->Finalize(); + contr->Delete(); + + return !retVal; +} + + + + + diff --git a/Parallel/Testing/Cxx/TestSockets.py b/Parallel/Testing/Cxx/TestSockets.py new file mode 100644 index 0000000..2fad578 --- /dev/null +++ b/Parallel/Testing/Cxx/TestSockets.py @@ -0,0 +1,29 @@ +""" Driver script for testing sockets + Unix only +""" +import os, sys, time + +# Fork, run server in child, client in parent +pid = os.fork() +if pid == 0: + # exec the parent + os.execv(sys.argv[1], ('-D', sys.argv[3])) +else: + # wait a little to make sure that the server is ready + time.sleep(10) + # run the client + retVal = os.system('"%s" -D "%s" -V "%s" -T "%s"' % + ( sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5] )) + # in case the client fails, we need to kill the server + # or it will stay around + time.sleep(20) + try: + os.kill(pid, 15) + except: + pass + try: + status = os.WEXITSTATUS(retVal) + except: + status = 0 + print "Cannot get exit status" + sys.exit(status) diff --git a/Parallel/Testing/Cxx/ThreadedCommunicator.cxx b/Parallel/Testing/Cxx/ThreadedCommunicator.cxx new file mode 100644 index 0000000..009ae3c --- /dev/null +++ b/Parallel/Testing/Cxx/ThreadedCommunicator.cxx @@ -0,0 +1,362 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ThreadedCommunicator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCharArray.h" +#include "vtkDebugLeaks.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIdTypeArray.h" +#include "vtkInputPort.h" +#include "vtkIntArray.h" +#include "vtkOutputPort.h" +#include "vtkParallelFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkThreadedController.h" +#include "vtkUnsignedLongArray.h" + +#include "vtkDebugLeaks.h" +#include "vtkRegressionTestImage.h" + +static const int scMsgLength = 10; + +struct GenericCommunicatorArgs_tmp +{ + int* retVal; + int argc; + char** argv; +}; + +void TestBarrier(vtkMultiProcessController *contr, void* vtkNotUsed(arg)) +{ + contr->Barrier(); +} + +void Process2(vtkMultiProcessController *contr, void* vtkNotUsed(arg)) +{ + int i; + + // Test receiving all supported types of arrays + int datai[scMsgLength]; + if (!contr->Receive(datai, scMsgLength, 0, 11)) + { + cerr << "Server error: Error receiving data." << endl; + return; + } + for (i=0; iReceive(dataul, scMsgLength, 0, 22)) + { + cerr << "Server error: Error receiving data." << endl; + return; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt unsigned long array." << endl; + } + } + + char datac[scMsgLength]; + if (!contr->Receive(datac, scMsgLength, 0, 33)) + { + cerr << "Server error: Error receiving data." << endl; + return; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt char array." << endl; + } + } + + unsigned char datauc[scMsgLength]; + if (!contr->Receive(datauc, scMsgLength, 0, 44)) + { + cerr << "Server error: Error receiving data." << endl; + return; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt unsigned char array." << endl; + } + } + + float dataf[scMsgLength]; + if (!contr->Receive(dataf, scMsgLength, 0, 7)) + { + cerr << "Server error: Error receiving data." << endl; + return; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt float array." << endl; + } + } + + + double datad[scMsgLength]; + if (!contr->Receive(datad, scMsgLength, 0, 7)) + { + cerr << "Server error: Error receiving data." << endl; + return; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt double array." << endl; + } + } + + vtkIdType datait[scMsgLength]; + if (!contr->Receive(datait, scMsgLength, 0, 7)) + { + cerr << "Server error: Error receiving data." << endl; + return; + } + for (i=0; i(i)) + { + cerr << "Server error: Corrupt vtkIdType array." << endl; + } + } + + // Test receiving all supported types of arrays + vtkIntArray* ia = vtkIntArray::New(); + if (!contr->Receive(ia, 0, 11)) + { + cerr << "Server error: Error receiving data." << endl; + } + for (i=0; iGetNumberOfTuples(); i++) + { + if (ia->GetValue(i) != i) + { + cerr << "Server error: Corrupt integer array." << endl; + } + } + ia->Delete(); + + // Test the ports and sending a data object + vtkOutputPort* op = vtkOutputPort::New(); + op->SetController(contr); + op->SetTag(45); + + // send sphere source + vtkSphereSource* pd = vtkSphereSource::New(); + + op->SetInputConnection(pd->GetOutputPort()); + op->WaitForUpdate(); + pd->Delete(); + + op->Delete(); +} + +void Process1(vtkMultiProcessController *contr, void *arg) +{ + GenericCommunicatorArgs_tmp* args = + reinterpret_cast(arg); + + int i; + + // Test sending all supported types of arrays + int datai[scMsgLength]; + for (i=0; iSend(datai, scMsgLength, 1, 11)) + { + cerr << "Client error: Error sending data." << endl; + return; + } + + unsigned long dataul[scMsgLength]; + for (i=0; i(i); + } + if (!contr->Send(dataul, scMsgLength, 1, 22)) + { + cerr << "Client error: Error sending data." << endl; + return; + } + + char datac[scMsgLength]; + for (i=0; i(i); + } + if (!contr->Send(datac, scMsgLength, 1, 33)) + { + cerr << "Client error: Error sending data." << endl; + return; + } + + unsigned char datauc[scMsgLength]; + for (i=0; i(i); + } + if (!contr->Send(datauc, scMsgLength, 1, 44)) + { + cerr << "Client error: Error sending data." << endl; + return; + } + + float dataf[scMsgLength]; + for (i=0; i(i); + } + if (!contr->Send(dataf, scMsgLength, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + return; + } + + + double datad[scMsgLength]; + for (i=0; i(i); + } + if (!contr->Send(datad, scMsgLength, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + return; + } + + vtkIdType datait[scMsgLength]; + for (i=0; i(i); + } + if (!contr->Send(datait, scMsgLength, 1, 7)) + { + cerr << "Client error: Error sending data." << endl; + return; + } + + // Test sending all supported types of arrays + vtkIntArray* ia = vtkIntArray::New(); + ia->SetArray(datai, 10, 1); + if (!contr->Send(ia, 1, 11)) + { + cerr << "Client error: Error sending data." << endl; + } + ia->Delete(); + + + // Test the ports and sending a data object + vtkInputPort* ip = vtkInputPort::New(); + ip->SetController(contr); + ip->SetTag(45); + ip->SetRemoteProcessId(1); + + // Get polydata + ip->GetPolyDataOutput()->Update(); + + vtkPolyDataMapper* pmapper = vtkPolyDataMapper::New(); + pmapper->SetInput(ip->GetPolyDataOutput()); + + vtkActor* pactor = vtkActor::New(); + pactor->SetMapper(pmapper); + pmapper->UnRegister(0); + + vtkRenderer* ren = vtkRenderer::New(); + ren->AddActor(pactor); + pactor->UnRegister(0); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren); + ren->UnRegister(0); + + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + renWin->Render(); + + *(args->retVal) = + vtkRegressionTester::Test(args->argc, args->argv, renWin, 10); + if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + contr->TriggerRMI(1, vtkMultiProcessController::BREAK_RMI_TAG); + + iren->Delete(); + ip->Delete(); + renWin->Delete(); +} + +int main(int argc, char** argv) +{ + vtkThreadedController* contr = vtkThreadedController::New(); + contr->Initialize(&argc, &argv); + contr->CreateOutputWindow(); + + vtkParallelFactory* pf = vtkParallelFactory::New(); + vtkObjectFactory::RegisterFactory(pf); + pf->Delete(); + + // When using MPI, the number of processes is determined + // by the external program which launches this application. + // However, when using threads, we need to set it ourselves. + if (contr->IsA("vtkThreadedController")) + { + // Set the number of processes to 2 for this example. + contr->SetNumberOfProcesses(2); + } + + // Added for regression test. + // ---------------------------------------------- + int retVal; + GenericCommunicatorArgs_tmp args; + args.retVal = &retVal; + args.argc = argc; + args.argv = argv; + // ---------------------------------------------- + + contr->SetMultipleMethod(0, Process1, &args); + contr->SetMultipleMethod(1, Process2, 0); + contr->MultipleMethodExecute(); + + contr->SetSingleMethod(TestBarrier, 0); + contr->SingleMethodExecute(); + + contr->Finalize(); + contr->Delete(); + + return !retVal; +} diff --git a/Parallel/Testing/Python/CMakeLists.txt b/Parallel/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..a4de62f --- /dev/null +++ b/Parallel/Testing/Python/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Add tests, with the data +# +INCLUDE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake) + +IF (VTK_PYTHON_EXE AND VTK_USE_DISPLAY) + # Add test converted from Tcl + SET (tests) + IF (VTK_DATA_ROOT) + SET( tests ${tests} + RectOutline + TestExtractVOI + TestExtractCTHPart + TestExtrudePiece + TestPolyDataPieces + TestUnstructuredPieces + TestImageStreamer + TestPImageWriter + TestCutMaterial + TestBranchExtentTranslator + TestPDataSetReaderGrid + ) + ELSE (VTK_DATA_ROOT) + SET( tests ${tests} + TestPolyDataPieces + TestCutMaterial + TestBranchExtentTranslator + ) + ENDIF (VTK_DATA_ROOT) + + CONVERT_TCL_TEST_TO_PY ( + tests + Parallel) +ENDIF (VTK_PYTHON_EXE AND VTK_USE_DISPLAY) diff --git a/Parallel/Testing/Tcl/CMakeLists.txt b/Parallel/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..82c4f78 --- /dev/null +++ b/Parallel/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,114 @@ +IF (VTK_USE_DISPLAY) +IF (VTK_DATA_ROOT) + ADD_TEST(RectOutline-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/RectOutline.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/RectOutline.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(ExtractVOI-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestExtractVOI.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestExtractVOI.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(TestExtractCTHPart ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestExtractCTHPart.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestExtractCTHPart.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(ExtrudePiece-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestExtrudePiece.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestExtrudePiece.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(PolyDataPieces-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestPolyDataPieces.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestPolyDataPieces.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(UnstructuredPieces-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestUnstructuredPieces.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestUnstructuredPieces.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(ImageStreamer-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestImageStreamer.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestImageStreamer.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(PImageWriter-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestPImageWriter.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestPImageWriter.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(CutMaterial-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestCutMaterial.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestCutMaterial.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(BranchExtentTranslator-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestBranchExtentTranslator.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestBranchExtentTranslator.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(PDataSetReaderGrid-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestPDataSetReaderGrid.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestPDataSetReaderGrid.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + IF(PVTK_EXECUTABLE AND VTK_MPIRUN_EXE) + ADD_TEST(TestPProbe-image + ${VTK_MPIRUN_EXE} ${VTK_MPI_NUMPROC_FLAG} 2 ${VTK_MPI_PREFLAGS} ${PVTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/prtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestPProbe.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Parallel/TestPProbe.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl + ${VTK_MPI_POSTFLAGS}) + ENDIF(PVTK_EXECUTABLE AND VTK_MPIRUN_EXE) +ELSE (VTK_DATA_ROOT) + ADD_TEST(PolyDataPieces ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestPolyDataPieces.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(CutMaterial-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestCutMaterial.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ADD_TEST(BranchExtentTranslator-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Parallel/Testing/Tcl/TestBranchExtentTranslator.tcl + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) +ENDIF (VTK_DATA_ROOT) +ENDIF (VTK_USE_DISPLAY) + +ADD_TEST(PrintSelf-Parallel ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Parallel) + +ADD_TEST(TestSetObjectMacro-Parallel ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Parallel/vtk\\\\*.h" + "vtkSetObjectMacro") diff --git a/Parallel/Testing/Tcl/RectOutline.tcl b/Parallel/Testing/Tcl/RectOutline.tcl new file mode 100644 index 0000000..9d58459 --- /dev/null +++ b/Parallel/Testing/Tcl/RectOutline.tcl @@ -0,0 +1,59 @@ +package require vtk +package require vtkinteraction +package require vtktesting + + +# create pipeline +# +vtkDataSetReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/RectGrid2.vtk" + reader Update + +# here to force exact extent +vtkElevationFilter elev + elev SetInputConnection [reader GetOutputPort] + +vtkRectilinearGridOutlineFilter outline + outline SetInput [elev GetRectilinearGridOutput] + +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] + outlineMapper SetNumberOfPieces 2 + outlineMapper SetPiece 1 +vtkActor outlineActor + outlineActor SetMapper outlineMapper + eval [outlineActor GetProperty] SetColor $black + +# Graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor + +ren1 SetBackground 1 1 1 +renWin SetSize 400 400 + +set cam1 [ren1 GetActiveCamera] + $cam1 SetClippingRange 3.76213 10.712 + $cam1 SetFocalPoint -0.0842503 -0.136905 0.610234 + $cam1 SetPosition 2.53813 2.2678 -5.22172 + $cam1 SetViewUp -0.241047 0.930635 0.275343 + +iren Initialize + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Parallel/Testing/Tcl/TestBranchExtentTranslator.tcl b/Parallel/Testing/Tcl/TestBranchExtentTranslator.tcl new file mode 100644 index 0000000..ebc5f74 --- /dev/null +++ b/Parallel/Testing/Tcl/TestBranchExtentTranslator.tcl @@ -0,0 +1,95 @@ +package require vtk +package require vtkinteraction + +vtkImageGaussianSource gauss + gauss SetWholeExtent 0 30 0 30 0 2 + gauss SetCenter 18 12 0 + gauss SetMaximum 1.0 + gauss SetStandardDeviation 6.0 + gauss Update + +vtkBranchExtentTranslator translator + translator SetOriginalSource [gauss GetOutput] + [gauss GetOutput] SetExtentTranslator translator + +vtkImageClip clip1 + clip1 SetOutputWholeExtent 7 28 0 15 1 1 + clip1 SetInputConnection [gauss GetOutputPort] +vtkDataSetSurfaceFilter surf1 + surf1 SetInputConnection [clip1 GetOutputPort] +vtkTriangleFilter tf1 + tf1 SetInputConnection [surf1 GetOutputPort] +vtkPolyDataMapper mapper1 + mapper1 SetInputConnection [tf1 GetOutputPort] + mapper1 SetScalarRange 0 1 + mapper1 SetNumberOfPieces 4 + mapper1 SetPiece 1 +vtkActor actor1 + actor1 SetMapper mapper1 + actor1 SetPosition 0 0 0 + + + +# For coverage, a case where all four sides get clipped by the whole extent. +vtkImageClip clip2 + clip2 SetOutputWholeExtent 16 18 3 10 0 0 + clip2 SetInputConnection [gauss GetOutputPort] +vtkDataSetSurfaceFilter surf2 + surf2 SetInputConnection [clip2 GetOutputPort] +vtkTriangleFilter tf2 + tf2 SetInputConnection [surf2 GetOutputPort] +vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [tf2 GetOutputPort] + mapper2 SetScalarRange 0 1 + mapper2 SetNumberOfPieces 4 + mapper2 SetPiece 1 +vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetPosition 15 0 0 + + + +# nothing in intersection (empty case) +vtkImageClip clip3 + clip3 SetOutputWholeExtent 1 10 0 15 0 2 + clip3 SetInputConnection [gauss GetOutputPort] +vtkDataSetSurfaceFilter surf3 + surf3 SetInputConnection [clip3 GetOutputPort] +vtkTriangleFilter tf3 + tf3 SetInputConnection [surf3 GetOutputPort] +vtkPolyDataMapper mapper3 + mapper3 SetInputConnection [tf3 GetOutputPort] + mapper3 SetScalarRange 0 1 + mapper3 SetNumberOfPieces 4 + mapper3 SetPiece 1 +vtkActor actor3 + actor3 SetMapper mapper3 + actor3 SetPosition 30 0 0 + + + +vtkRenderer ren +ren AddActor actor1 +ren AddActor actor2 +ren AddActor actor3 + +vtkRenderWindow renWin +renWin AddRenderer ren + +#set cam [ren GetActiveCamera] +#ren ResetCamera + + + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +wm withdraw . + + +renWin Render + +# break loop to avoid a memory leak. +translator SetOriginalSource {} diff --git a/Parallel/Testing/Tcl/TestCutMaterial.tcl b/Parallel/Testing/Tcl/TestCutMaterial.tcl new file mode 100644 index 0000000..48a0c60 --- /dev/null +++ b/Parallel/Testing/Tcl/TestCutMaterial.tcl @@ -0,0 +1,86 @@ +package require vtk +package require vtkinteraction + + +# Lets create a data set. +vtkImageData data + data SetExtent 0 31 0 31 0 31 + data SetScalarTypeToFloat + +# First the data array: +vtkImageGaussianSource gauss + gauss SetWholeExtent 0 30 0 30 0 30 + gauss SetCenter 18 12 20 + gauss SetMaximum 1.0 + gauss SetStandardDeviation 10.0 + gauss Update + +set a [[[gauss GetOutput] GetPointData] GetScalars] +$a SetName "Gauss" +[data GetCellData] SetScalars $a + +gauss Delete + + +# Now the material array: +vtkImageEllipsoidSource ellipse + ellipse SetWholeExtent 0 30 0 30 0 30 + ellipse SetCenter 11 12 13 + ellipse SetRadius 5 9 13 + ellipse SetInValue 1 + ellipse SetOutValue 0 + ellipse SetOutputScalarTypeToInt + ellipse Update + +set m [[[ellipse GetOutput] GetPointData] GetScalars] +$m SetName "Material" +[data GetCellData] AddArray $m + +ellipse Delete + +vtkCutMaterial cut + cut SetInput data + cut SetMaterialArrayName "Material" + cut SetMaterial 1 + cut SetArrayName "Gauss" + cut SetUpVector 1 0 0 + cut Update + + +vtkPolyDataMapper mapper2 +mapper2 SetInputConnection [cut GetOutputPort] +mapper2 SetScalarRange 0 1 +#apper2 SetScalarModeToUseCellFieldData +#apper2 SetColorModeToMapScalars +#apper2 ColorByArrayComponent "vtkGhostLevels" 0 + +vtkActor actor2 +actor2 SetMapper mapper2 +actor2 SetPosition 1.5 0 0 + +vtkRenderer ren +ren AddActor actor2 + +vtkRenderWindow renWin +renWin AddRenderer ren + +set p [cut GetCenterPoint] +set n [cut GetNormal] +set cam [ren GetActiveCamera] +eval $cam SetFocalPoint $p +eval $cam SetViewUp [cut GetUpVector] +$cam SetPosition [expr [lindex $n 0] + [lindex $p 0]] \ + [expr [lindex $n 1] + [lindex $p 1]] \ + [expr [lindex $n 2] + [lindex $p 2]] +ren ResetCamera + + + + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +wm withdraw . + diff --git a/Parallel/Testing/Tcl/TestExtractCTHPart.tcl b/Parallel/Testing/Tcl/TestExtractCTHPart.tcl new file mode 100644 index 0000000..efc8a27 --- /dev/null +++ b/Parallel/Testing/Tcl/TestExtractCTHPart.tcl @@ -0,0 +1,76 @@ +package require vtk +package require vtkinteraction + + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer Ren1 + Ren1 SetBackground 0.33 0.35 0.43 +vtkRenderWindow renWin + renWin AddRenderer Ren1 + renWin SetSize 300 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkXMLRectilinearGridReader pvTemp59 + pvTemp59 SetFileName "$VTK_DATA_ROOT/Data/cth.vtr" + pvTemp59 UpdateInformation + pvTemp59 SetCellArrayStatus "X Velocity" 0 + pvTemp59 SetCellArrayStatus "Y Velocity" 0 + pvTemp59 SetCellArrayStatus "Z Velocity" 0 + pvTemp59 SetCellArrayStatus "Mass for Armor Plate" 0 + pvTemp59 SetCellArrayStatus "Mass for Body, Nose" 0 + +vtkExtractCTHPart pvTemp79 + pvTemp79 SetInput [pvTemp59 GetOutput 0] + pvTemp79 AddVolumeArrayName "Volume Fraction for Armor Plate" + pvTemp79 AddVolumeArrayName "Volume Fraction for Body, Nose" + pvTemp79 SetClipPlane {} +vtkLookupTable pvTemp104 + pvTemp104 SetNumberOfTableValues 256 + pvTemp104 SetHueRange 0.6667 0 + pvTemp104 SetSaturationRange 1 1 + pvTemp104 SetValueRange 1 1 + pvTemp104 SetTableRange 0 1 + pvTemp104 SetVectorComponent 0 + pvTemp104 Build +vtkPolyDataMapper pvTemp87 + pvTemp87 SetInput [pvTemp79 GetOutput 0] + pvTemp87 SetImmediateModeRendering 1 + pvTemp87 SetScalarRange 0 1 + pvTemp87 UseLookupTableScalarRangeOn + pvTemp87 SetScalarVisibility 1 + pvTemp87 SetScalarModeToUsePointFieldData + pvTemp87 SelectColorArray "Part Index" +pvTemp87 SetLookupTable pvTemp104 +vtkActor pvTemp88 + pvTemp88 SetMapper pvTemp87 + [ pvTemp88 GetProperty] SetRepresentationToSurface + [pvTemp88 GetProperty] SetInterpolationToGouraud + [pvTemp88 GetProperty] SetAmbient 0 + [pvTemp88 GetProperty] SetDiffuse 1 + [pvTemp88 GetProperty] SetSpecular 0 + [pvTemp88 GetProperty] SetSpecularPower 1 + [pvTemp88 GetProperty] SetSpecularColor 1 1 1 +Ren1 AddActor pvTemp88 +vtkPolyDataMapper pvTemp96 + pvTemp96 SetInput [pvTemp79 GetOutput 1] + pvTemp96 SetImmediateModeRendering 1 + pvTemp96 SetScalarRange 0 1 + pvTemp96 UseLookupTableScalarRangeOn + pvTemp96 SetScalarVisibility 1 + pvTemp96 SetScalarModeToUsePointFieldData + pvTemp96 SelectColorArray "Part Index" +pvTemp96 SetLookupTable pvTemp104 +vtkActor pvTemp97 + pvTemp97 SetMapper pvTemp96 + [ pvTemp97 GetProperty] SetRepresentationToSurface + [pvTemp97 GetProperty] SetInterpolationToGouraud + [pvTemp97 GetProperty] SetAmbient 0 + [pvTemp97 GetProperty] SetDiffuse 1 + [pvTemp97 GetProperty] SetSpecular 0 + [pvTemp97 GetProperty] SetSpecularPower 1 + [pvTemp97 GetProperty] SetSpecularColor 1 1 1 +Ren1 AddActor pvTemp97 + +renWin Render diff --git a/Parallel/Testing/Tcl/TestExtractVOI.tcl b/Parallel/Testing/Tcl/TestExtractVOI.tcl new file mode 100644 index 0000000..c3d77be --- /dev/null +++ b/Parallel/Testing/Tcl/TestExtractVOI.tcl @@ -0,0 +1,56 @@ +package require vtk +package require vtkinteraction + +# to mark the origin +vtkSphereSource sphere + sphere SetRadius 2.0 +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper ImmediateModeRenderingOn +vtkActor sphereActor + sphereActor SetMapper sphereMapper + + +vtkRTAnalyticSource rt +rt SetWholeExtent -50 50 -50 50 0 0 + +vtkExtractVOI voi + voi SetInputConnection [rt GetOutputPort] + voi SetVOI -11 39 5 45 0 0 + voi SetSampleRate 5 5 1 + +# Get rid ambiguous triagulation issues. +vtkDataSetSurfaceFilter surf + surf SetInputConnection [voi GetOutputPort] +vtkTriangleFilter tris + tris SetInputConnection [surf GetOutputPort] + +vtkPolyDataMapper mapper + mapper SetInputConnection [tris GetOutputPort] + mapper ImmediateModeRenderingOn + mapper SetScalarRange 130 280 +vtkActor actor + actor SetMapper mapper + + +vtkRenderer ren +ren AddActor actor +ren AddActor sphereActor + +ren ResetCamera +set camera [ren GetActiveCamera] +#$camera SetPosition 68.1939 -23.4323 12.6465 +#$camera SetViewUp 0.46563 0.882375 0.0678508 +#$camera SetFocalPoint 3.65707 11.4552 1.83509 +#$camera SetClippingRange 59.2626 101.825 + +vtkRenderWindow renWin +renWin AddRenderer ren + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +wm withdraw . + diff --git a/Parallel/Testing/Tcl/TestExtrudePiece.tcl b/Parallel/Testing/Tcl/TestExtrudePiece.tcl new file mode 100644 index 0000000..46128d8 --- /dev/null +++ b/Parallel/Testing/Tcl/TestExtrudePiece.tcl @@ -0,0 +1,66 @@ +package require vtk +package require vtkinteraction + + +vtkDiskSource disk + disk SetRadialResolution 2 + disk SetCircumferentialResolution 9 + +vtkCleanPolyData clean + clean SetInputConnection [disk GetOutputPort] + clean SetTolerance 0.01 + +vtkExtractPolyDataPiece piece + piece SetInputConnection [clean GetOutputPort] + +vtkPLinearExtrusionFilter extrude + extrude SetInputConnection [piece GetOutputPort] + extrude PieceInvariantOn + + + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPolyDataMapper mapper + mapper SetInputConnection [extrude GetOutputPort] + mapper SetNumberOfPieces 2 + mapper SetPiece 1 + +vtkProperty bf + bf SetColor 1 0 0 +vtkActor actor + actor SetMapper mapper + [actor GetProperty] SetColor 1 1 0.8 + actor SetBackfaceProperty bf + + + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor actor + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set cam1 [ren1 GetActiveCamera] +$cam1 Azimuth 20 +$cam1 Elevation 40 +ren1 ResetCamera +$cam1 Zoom 1.2 + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Parallel/Testing/Tcl/TestImageStreamer.tcl b/Parallel/Testing/Tcl/TestImageStreamer.tcl new file mode 100644 index 0000000..0bdf31a --- /dev/null +++ b/Parallel/Testing/Tcl/TestImageStreamer.tcl @@ -0,0 +1,57 @@ +package require vtk + +vtkImageReader reader +reader ReleaseDataFlagOff +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff + +set rangeStart 0.0 +set rangeEnd 0.2 + +vtkLookupTable LUT +LUT SetTableRange 0 1800 +LUT SetSaturationRange 1 1 +LUT SetHueRange $rangeStart $rangeEnd +LUT SetValueRange 1 1 +LUT SetAlphaRange 1 1 +LUT Build + +# added these unused default arguments so that the prototype +# matches as required in python. +proc changeLUT { { a 0 } { b 0 } } { + global rangeStart rangeEnd + + set rangeStart [expr $rangeStart + 0.1] + set rangeEnd [expr $rangeEnd + 0.1] + if { $rangeEnd > 1.0 } { + set rangeStart 0.0 + set rangeEnd 0.2 + } + + LUT SetHueRange $rangeStart $rangeEnd + LUT Build +} + +vtkImageMapToColors mapToRGBA +mapToRGBA SetInputConnection [reader GetOutputPort] +mapToRGBA SetOutputFormatToRGBA +mapToRGBA SetLookupTable LUT +mapToRGBA AddObserver "EndEvent" changeLUT + +vtkMemoryLimitImageDataStreamer streamer +streamer SetInputConnection [mapToRGBA GetOutputPort] +streamer SetMemoryLimit 100 +streamer UpdateWholeExtent + +# set the window/level to 255.0/127.5 to view full range +vtkImageViewer viewer +viewer SetInputConnection [streamer GetOutputPort] +viewer SetColorWindow 255.0 +viewer SetColorLevel 127.5 +viewer SetZSlice 50 + +wm withdraw . +viewer Render + diff --git a/Parallel/Testing/Tcl/TestPDataSetReaderGrid.tcl b/Parallel/Testing/Tcl/TestPDataSetReaderGrid.tcl new file mode 100644 index 0000000..26c8200 --- /dev/null +++ b/Parallel/Testing/Tcl/TestPDataSetReaderGrid.tcl @@ -0,0 +1,159 @@ +package require vtk +package require vtkinteraction + + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + + + +# +# If the current directory is writable, then test the witers +# + +if {[catch {set channel [open "test.tmp" "w"]}] == 0 } { + close $channel + file delete -force "test.tmp" + + # ====== Structured Grid ====== + # First save out a grid in parallel form. + vtkPLOT3DReader reader + reader SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + reader SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + vtkPDataSetWriter writer + writer SetFileName "comb.pvtk" + writer SetInputConnection [reader GetOutputPort] + writer SetNumberOfPieces 4 + writer Write + vtkPDataSetReader pReader + pReader SetFileName "comb.pvtk" + vtkDataSetSurfaceFilter surface + surface SetInputConnection [pReader GetOutputPort] + vtkPolyDataMapper mapper + mapper SetInputConnection [surface GetOutputPort] + mapper SetNumberOfPieces 2 + mapper SetPiece 0 + mapper SetGhostLevel 1 + mapper Update + + file delete -force "comb.pvtk" + file delete -force "comb.0.vtk" + file delete -force "comb.1.vtk" + file delete -force "comb.2.vtk" + file delete -force "comb.3.vtk" + + vtkActor actor + actor SetMapper mapper + actor SetPosition -5 0 -29 + + # Add the actors to the renderer, set the background and size + # + ren1 AddActor actor + + + + # ====== ImageData ====== + # First save out a grid in parallel form. + vtkImageMandelbrotSource fractal + fractal SetWholeExtent 0 9 0 9 0 9 + fractal SetSampleCX 0.1 0.1 0.1 0.1 + fractal SetMaximumNumberOfIterations 10 + + vtkPDataSetWriter writer2 + writer SetFileName "fractal.pvtk" + writer SetInputConnection [fractal GetOutputPort] + writer SetNumberOfPieces 4 + writer Write + + vtkPDataSetReader pReader2 + pReader2 SetFileName "fractal.pvtk" + + vtkContourFilter iso + iso SetInputConnection [pReader2 GetOutputPort] + iso SetValue 0 4 + + vtkPolyDataMapper mapper2 + mapper2 SetInputConnection [iso GetOutputPort] + mapper2 SetNumberOfPieces 3 + mapper2 SetPiece 0 + mapper2 SetGhostLevel 0 + mapper2 Update + + file delete -force "fractal.pvtk" + file delete -force "fractal.0.vtk" + file delete -force "fractal.1.vtk" + file delete -force "fractal.2.vtk" + file delete -force "fractal.3.vtk" + + vtkActor actor2 + actor2 SetMapper mapper2 + actor2 SetScale 5 5 5 + actor2 SetPosition 6 6 6 + + # Add the actors to the renderer, set the background and size + # + ren1 AddActor actor2 + + + + # ====== PolyData ====== + # First save out a grid in parallel form. + vtkSphereSource sphere + sphere SetRadius 2 + + vtkPDataSetWriter writer3 + writer3 SetFileName "sphere.pvtk" + writer3 SetInputConnection [sphere GetOutputPort] + writer3 SetNumberOfPieces 4 + writer3 Write + + vtkPDataSetReader pReader3 + pReader3 SetFileName "sphere.pvtk" + + vtkPolyDataMapper mapper3 + mapper3 SetInputConnection [pReader3 GetOutputPort] + mapper3 SetNumberOfPieces 2 + mapper3 SetPiece 0 + mapper3 SetGhostLevel 1 + mapper3 Update + + file delete -force "sphere.pvtk" + file delete -force "sphere.0.vtk" + file delete -force "sphere.1.vtk" + file delete -force "sphere.2.vtk" + file delete -force "sphere.3.vtk" + + vtkActor actor3 + actor3 SetMapper mapper3 + actor3 SetPosition 6 6 6 + + # Add the actors to the renderer, set the background and size + # + ren1 AddActor actor3 +} + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set cam1 [ren1 GetActiveCamera] +$cam1 Azimuth 20 +$cam1 Elevation 40 +ren1 ResetCamera +$cam1 Zoom 1.2 + +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + diff --git a/Parallel/Testing/Tcl/TestPImageWriter.tcl b/Parallel/Testing/Tcl/TestPImageWriter.tcl new file mode 100644 index 0000000..4eb292b --- /dev/null +++ b/Parallel/Testing/Tcl/TestPImageWriter.tcl @@ -0,0 +1,36 @@ +package require vtk + +# Image pipeline + +vtkTIFFReader image1 + image1 SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + image1 Update + +# +# If the current directory is writable, then test the witers +# + +if {[catch {set channel [open test.tmp w]}] == 0 } { + close $channel + file delete -force test.tmp + + vtkPImageWriter piw + piw SetInputConnection [image1 GetOutputPort] + piw SetFileName piw.raw + piw SetMemoryLimit 1 + + piw Write + + file delete -force piw.raw +} + +vtkImageViewer viewer +viewer SetInputConnection [image1 GetOutputPort] +viewer SetColorWindow 255 +viewer SetColorLevel 127.5 + +wm withdraw . + +viewer Render + + diff --git a/Parallel/Testing/Tcl/TestPProbe.tcl b/Parallel/Testing/Tcl/TestPProbe.tcl new file mode 100644 index 0000000..d411496 --- /dev/null +++ b/Parallel/Testing/Tcl/TestPProbe.tcl @@ -0,0 +1,94 @@ +package require vtk + +if { [ info command vtkMesaRenderer ] != "" } { + vtkGraphicsFactory _graphics_fact + _graphics_fact SetUseMesaClasses 1 + _graphics_fact Delete +} + +# create a rendering window and renderer +vtkRenderer Ren1 + Ren1 SetBackground .5 .8 1 +vtkRenderWindow renWin + renWin AddRenderer Ren1 + renWin SetSize 300 300 +puts $myProcId + if { $myProcId > 0 } { + renWin SetPosition [expr $myProcId * 350] 0 + renWin OffScreenRenderingOn + } + +# camera parameters +set camera [Ren1 GetActiveCamera] + $camera SetPosition 199.431 196.879 15.7781 + $camera SetFocalPoint 33.5 33.5 33.5 + $camera SetViewUp 0.703325 -0.702557 0.108384 + $camera SetViewAngle 30 + $camera SetClippingRange 132.14 361.741 + +vtkPDataSetReader ironProt0 + ironProt0 SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +vtkPOutlineFilter Geometry4 + Geometry4 SetInputConnection [ironProt0 GetOutputPort] +vtkPolyDataMapper Mapper4 + Mapper4 SetInputConnection [Geometry4 GetOutputPort] + Mapper4 SetImmediateModeRendering 0 + Mapper4 SetScalarRange 0 1 + Mapper4 SetScalarVisibility 0 + Mapper4 SetScalarModeToDefault +vtkActor Actor4 + Actor4 SetMapper Mapper4 + [Actor4 GetProperty] SetRepresentationToSurface + [Actor4 GetProperty] SetInterpolationToGouraud +[Actor4 GetProperty] SetColor 1 1 1 +Ren1 AddActor Actor4 + +vtkLineSource probeLine + probeLine SetPoint1 0 67 10 + probeLine SetPoint2 67 0 50 + probeLine SetResolution 500 + +vtkMPIController controler + +vtkPProbeFilter Probe0 + Probe0 SetSource [ironProt0 GetOutput] + Probe0 SetInput [ probeLine GetOutput ] + Probe0 SetController controler + +vtkTubeFilter Tuber0 + Tuber0 SetInputConnection [Probe0 GetOutputPort] + Tuber0 SetNumberOfSides 10 + Tuber0 SetCapping 0 + Tuber0 SetRadius 1 + Tuber0 SetVaryRadius 1 + Tuber0 SetRadiusFactor 10 +Tuber0 Update + +vtkPolyDataMapper Mapper6 + Mapper6 SetInputConnection [Tuber0 GetOutputPort] + Mapper6 SetImmediateModeRendering 0 + Mapper6 SetScalarRange 0 228 + Mapper6 SetScalarVisibility 1 + Mapper6 SetScalarModeToUsePointFieldData + Mapper6 ColorByArrayComponent {scalars} -1 + Mapper6 UseLookupTableScalarRangeOn +vtkActor Actor6 + Actor6 SetMapper Mapper6 + [Actor6 GetProperty] SetRepresentationToSurface + [Actor6 GetProperty] SetInterpolationToGouraud +Ren1 AddActor Actor6 + +if { $numProcs > 1 } { + compManager SetRenderWindow renWin + compManager InitializePieces +} + +renWin SetWindowName "Process $myProcId" + +wm withdraw . + +if { $numProcs < 2 } { + renWin Render +} + diff --git a/Parallel/Testing/Tcl/TestPolyDataPieces.tcl b/Parallel/Testing/Tcl/TestPolyDataPieces.tcl new file mode 100644 index 0000000..0fe6325 --- /dev/null +++ b/Parallel/Testing/Tcl/TestPolyDataPieces.tcl @@ -0,0 +1,116 @@ +package require vtk +package require vtkinteraction + +vtkMath math +math RandomSeed 22 + +vtkParallelFactory pf +pf RegisterFactory pf + +vtkSphereSource sphere +sphere SetPhiResolution 32 +sphere SetThetaResolution 32 + +vtkExtractPolyDataPiece extract +extract SetInputConnection [sphere GetOutputPort] + +vtkPolyDataNormals normals +normals SetInputConnection [extract GetOutputPort] + +vtkPieceScalars ps +ps SetInputConnection [normals GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [ps GetOutputPort] +mapper SetNumberOfPieces 2 + +vtkActor actor +actor SetMapper mapper + +vtkSphereSource sphere2 +sphere2 SetPhiResolution 32 +sphere2 SetThetaResolution 32 + +vtkExtractPolyDataPiece extract2 +extract2 SetInputConnection [sphere2 GetOutputPort] + +vtkPolyDataMapper mapper2 +mapper2 SetInputConnection [extract2 GetOutputPort] +mapper2 SetNumberOfPieces 2 +mapper2 SetPiece 1 +mapper2 SetScalarRange 0 4 +mapper2 SetScalarModeToUseCellFieldData +mapper2 SetColorModeToMapScalars +mapper2 ColorByArrayComponent "vtkGhostLevels" 0 +mapper2 SetGhostLevel 4 + +# check the pipeline size +extract2 UpdateInformation +vtkPipelineSize psize +if {[psize GetEstimatedSize extract2 0 0] > 100} { + puts stderr "ERROR: Pipeline Size increased" +} +if {[psize GetNumberOfSubPieces 10 mapper2] != 2} { + puts stderr "ERROR: Number of sub pieces changed" +} + +vtkActor actor2 +actor2 SetMapper mapper2 +actor2 SetPosition 1.5 0 0 + +vtkSphereSource sphere3 +sphere3 SetPhiResolution 32 +sphere3 SetThetaResolution 32 + +vtkExtractPolyDataPiece extract3 +extract3 SetInputConnection [sphere3 GetOutputPort] + +vtkPieceScalars ps3 +ps3 SetInputConnection [extract3 GetOutputPort] + +vtkPolyDataMapper mapper3 +mapper3 SetInputConnection [ps3 GetOutputPort] +mapper3 SetNumberOfSubPieces 8 +mapper3 SetScalarRange 0 8 + +vtkActor actor3 +actor3 SetMapper mapper3 +actor3 SetPosition 0 -1.5 0 + +vtkSphereSource sphere4 +sphere4 SetPhiResolution 32 +sphere4 SetThetaResolution 32 + +vtkExtractPolyDataPiece extract4 +extract4 SetInputConnection [sphere4 GetOutputPort] + +vtkPieceScalars ps4 +ps4 RandomModeOn +ps4 SetScalarModeToCellData +ps4 SetInputConnection [extract4 GetOutputPort] + +vtkPolyDataMapper mapper4 +mapper4 SetInputConnection [ps4 GetOutputPort] +mapper4 SetNumberOfSubPieces 8 +mapper4 SetScalarRange 0 8 + +vtkActor actor4 +actor4 SetMapper mapper4 +actor4 SetPosition 1.5 -1.5 0 + +vtkRenderer ren +ren AddActor actor +ren AddActor actor2 +ren AddActor actor3 +ren AddActor actor4 + +vtkRenderWindow renWin +renWin AddRenderer ren + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +wm withdraw . + diff --git a/Parallel/Testing/Tcl/TestUnstructuredPieces.tcl b/Parallel/Testing/Tcl/TestUnstructuredPieces.tcl new file mode 100644 index 0000000..7a26fe7 --- /dev/null +++ b/Parallel/Testing/Tcl/TestUnstructuredPieces.tcl @@ -0,0 +1,57 @@ +package require vtk +package require vtkinteraction + +vtkMath math +math RandomSeed 22 + +vtkParallelFactory pf +pf RegisterFactory pf + +vtkPLOT3DReader pl3d +pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" +pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" +pl3d SetScalarFunctionNumber 100 + +vtkDataSetTriangleFilter dst +dst SetInputConnection [pl3d GetOutputPort] + +vtkExtractUnstructuredGridPiece extract +extract SetInputConnection [dst GetOutputPort] + +vtkContourFilter cf +cf SetInputConnection [extract GetOutputPort] +cf SetValue 0 0.24 + +vtkPolyDataNormals pdn +pdn SetInputConnection [cf GetOutputPort] + +vtkPieceScalars ps +ps SetInputConnection [pdn GetOutputPort] + +vtkPolyDataMapper mapper +mapper SetInputConnection [ps GetOutputPort] +mapper SetNumberOfPieces 3 + +vtkActor actor +actor SetMapper mapper + +vtkRenderer ren +ren AddActor actor + +ren ResetCamera +set camera [ren GetActiveCamera] +#$camera SetPosition 68.1939 -23.4323 12.6465 +#$camera SetViewUp 0.46563 0.882375 0.0678508 +#$camera SetFocalPoint 3.65707 11.4552 1.83509 +#$camera SetClippingRange 59.2626 101.825 + +vtkRenderWindow renWin +renWin AddRenderer ren + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin +iren Initialize +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +wm withdraw . + diff --git a/Parallel/VTKParallelCMakeTests.cmake b/Parallel/VTKParallelCMakeTests.cmake new file mode 100644 index 0000000..9fff7f0 --- /dev/null +++ b/Parallel/VTKParallelCMakeTests.cmake @@ -0,0 +1,32 @@ +# See if we need to link the socket library +INCLUDE(${CMAKE_ROOT}/Modules/CheckLibraryExists.cmake) +CHECK_LIBRARY_EXISTS("socket" getsockname "" VTK_HAVE_LIBSOCKET) + +IF("VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T" MATCHES "^VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T$") + IF(VTK_HAVE_LIBSOCKET) + SET(VTK_GETSOCKNAME_LIBS "socket") + ELSE(VTK_HAVE_LIBSOCKET) + SET(VTK_GETSOCKNAME_LIBS) + ENDIF(VTK_HAVE_LIBSOCKET) + MESSAGE(STATUS "Checking for getsockname with socklen_t") + TRY_COMPILE(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T + ${VTK_BINARY_DIR}/CMakeTmp/SocklenT + ${VTK_SOURCE_DIR}/CMake/vtkTestSocklenT.cxx + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${VTK_GETSOCKNAME_LIBS}" + OUTPUT_VARIABLE OUTPUT) + IF(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T) + MESSAGE(STATUS "Checking for getsockname with socklen_t -- yes") + SET(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T 1 CACHE INTERNAL "Support for getsockname with socklen_t") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining if getsockname accepts socklen_t type " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T) + MESSAGE(STATUS "Checking for getsockname with socklen_t -- no") + SET(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T 0 CACHE INTERNAL "Support for getsockname with socklen_t") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining if getsockname accepts socklen_t type " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T) +ENDIF("VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T" MATCHES "^VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T$") diff --git a/Parallel/vtkBranchExtentTranslator.cxx b/Parallel/vtkBranchExtentTranslator.cxx new file mode 100644 index 0000000..f305367 --- /dev/null +++ b/Parallel/vtkBranchExtentTranslator.cxx @@ -0,0 +1,146 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBranchExtentTranslator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkBranchExtentTranslator.h" +#include "vtkObjectFactory.h" +#include "vtkSource.h" +#include "vtkImageData.h" + +vtkCxxRevisionMacro(vtkBranchExtentTranslator, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkBranchExtentTranslator); + +vtkCxxSetObjectMacro(vtkBranchExtentTranslator,OriginalSource,vtkImageData); + +//---------------------------------------------------------------------------- +vtkBranchExtentTranslator::vtkBranchExtentTranslator() +{ + this->OriginalSource = NULL; + this->AssignedPiece = 0; + this->AssignedNumberOfPieces = 1; +} + +//---------------------------------------------------------------------------- +vtkBranchExtentTranslator::~vtkBranchExtentTranslator() +{ + this->SetOriginalSource(NULL); +} + +//---------------------------------------------------------------------------- +int vtkBranchExtentTranslator::PieceToExtent() +{ + //cerr << this << " PieceToExtent: " << this->Piece << " of " << this->NumberOfPieces << endl; + //cerr << "OriginalData: " << this->OriginalSource << endl; + //cerr << "OriginalData is of type " << this->OriginalSource->GetClassName() << endl; + //cerr << "OriginalSource: " << this->OriginalSource->GetSource() << endl; + //cerr << "OriginalSource is of type: " << this->OriginalSource->GetSource()->GetClassName() << endl; + + + if (this->OriginalSource == NULL) + { // If the user has not set the original source, then just default + // to the method in the superclass. + return this->vtkExtentTranslator::PieceToExtent(); + } + + this->OriginalSource->UpdateInformation(); + this->OriginalSource->GetWholeExtent(this->Extent); + + //cerr << this << "WholeExtent: " << this->Extent[0] << ", " << this->Extent[1] << ", " + // << this->Extent[2] << ", " << this->Extent[3] << ", " + // << this->Extent[4] << ", " << this->Extent[5] << endl; + + if (this->SplitExtent(this->Piece, this->NumberOfPieces, this->Extent, 3) == 0) + { + //cerr << "Split thinks nothing is in the piece" << endl; + //cerr << this << " Split: " << this->Extent[0] << ", " << this->Extent[1] << ", " + // << this->Extent[2] << ", " << this->Extent[3] << ", " + // << this->Extent[4] << ", " << this->Extent[5] << endl; + // Nothing in this piece. + this->Extent[0] = this->Extent[2] = this->Extent[4] = 0; + this->Extent[1] = this->Extent[3] = this->Extent[5] = -1; + //cerr << this << " Extent: " << this->Extent[0] << ", " << this->Extent[1] << ", " + // << this->Extent[2] << ", " << this->Extent[3] << ", " + // << this->Extent[4] << ", " << this->Extent[5] << endl; + return 0; + } + + //cerr << this << " Split: " << this->Extent[0] << ", " << this->Extent[1] << ", " + // << this->Extent[2] << ", " << this->Extent[3] << ", " + // << this->Extent[4] << ", " << this->Extent[5] << endl; + + // Clip with the whole extent passed in. + if (this->Extent[0] < this->WholeExtent[0]) + { + this->Extent[0] = this->WholeExtent[0]; + } + if (this->Extent[1] > this->WholeExtent[1]) + { + this->Extent[1] = this->WholeExtent[1]; + } + if (this->Extent[2] < this->WholeExtent[2]) + { + this->Extent[2] = this->WholeExtent[2]; + } + if (this->Extent[3] > this->WholeExtent[3]) + { + this->Extent[3] = this->WholeExtent[3]; + } + if (this->Extent[4] < this->WholeExtent[4]) + { + this->Extent[4] = this->WholeExtent[4]; + } + if (this->Extent[5] > this->WholeExtent[5]) + { + this->Extent[5] = this->WholeExtent[5]; + } + + + if (this->Extent[0] > this->Extent[1] || + this->Extent[2] > this->Extent[3] || + this->Extent[4] > this->Extent[5]) + { + this->Extent[0] = this->Extent[2] = this->Extent[4] = 0; + this->Extent[1] = this->Extent[3] = this->Extent[5] = -1; + //cerr << this << " Extent: " << this->Extent[0] << ", " << this->Extent[1] << ", " + // << this->Extent[2] << ", " << this->Extent[3] << ", " + // << this->Extent[4] << ", " << this->Extent[5] << endl; + return 0; + } + + //cerr << this << " Extent: " << this->Extent[0] << ", " << this->Extent[1] << ", " + // << this->Extent[2] << ", " << this->Extent[3] << ", " + // << this->Extent[4] << ", " << this->Extent[5] << endl; + + return 1; +} + + + +//---------------------------------------------------------------------------- +void vtkBranchExtentTranslator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Original Source: (" << this->OriginalSource << ")\n"; + + os << indent << "AssignedPiece: " << this->AssignedPiece << endl; + os << indent << "AssignedNumberOfPieces: " << this->AssignedNumberOfPieces << endl; +} + + + + + + + diff --git a/Parallel/vtkBranchExtentTranslator.h b/Parallel/vtkBranchExtentTranslator.h new file mode 100644 index 0000000..993cbf3 --- /dev/null +++ b/Parallel/vtkBranchExtentTranslator.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBranchExtentTranslator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBranchExtentTranslator - Uses alternative source for whole extent. +// .SECTION Description +// vtkBranchExtentTranslator is like extent translator, but it uses an +// alternative source as a whole extent. The whole extent passed is assumed +// to be a subextent of the original source. we simply take the intersection +// of the split extent and the whole extdent passed in. We are attempting to +// make branching pipelines request consistent extents with the same piece +// requests. + +// .SECTION Caveats +// This object is still under development. + +#ifndef __vtkBranchExtentTranslator_h +#define __vtkBranchExtentTranslator_h + +#include "vtkExtentTranslator.h" + +class vtkImageData; + +class VTK_PARALLEL_EXPORT vtkBranchExtentTranslator : public vtkExtentTranslator +{ +public: + static vtkBranchExtentTranslator *New(); + + vtkTypeRevisionMacro(vtkBranchExtentTranslator,vtkExtentTranslator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is the original upstream image source. + virtual void SetOriginalSource(vtkImageData*); + vtkGetObjectMacro(OriginalSource,vtkImageData); + + // Description: + // Generates the extent from the pieces. + int PieceToExtent(); + + // Description: + // This unstructured extent/piece is store here for the users convenience. + // It is not used internally. The intent was to let an "assignment" be made + // when the translator/first source is created. The translator/assignment + // can be used for any new filter that uses the original source as output. + // Branches will then have the same assignment. + vtkSetMacro(AssignedPiece, int); + vtkGetMacro(AssignedPiece, int); + vtkSetMacro(AssignedNumberOfPieces, int); + vtkGetMacro(AssignedNumberOfPieces, int); + +protected: + vtkBranchExtentTranslator(); + ~vtkBranchExtentTranslator(); + + vtkImageData *OriginalSource; + int AssignedPiece; + int AssignedNumberOfPieces; +private: + vtkBranchExtentTranslator(const vtkBranchExtentTranslator&); // Not implemented. + void operator=(const vtkBranchExtentTranslator&); // Not implemented. +}; + +#endif + diff --git a/Parallel/vtkCollectPolyData.cxx b/Parallel/vtkCollectPolyData.cxx new file mode 100644 index 0000000..7c3c3bb --- /dev/null +++ b/Parallel/vtkCollectPolyData.cxx @@ -0,0 +1,197 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCollectPolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCollectPolyData.h" + +#include "vtkAppendPolyData.h" +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkSocketController.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkCollectPolyData, "$Revision: 1.17 $"); +vtkStandardNewMacro(vtkCollectPolyData); + +vtkCxxSetObjectMacro(vtkCollectPolyData,Controller, vtkMultiProcessController); +vtkCxxSetObjectMacro(vtkCollectPolyData,SocketController, vtkSocketController); + +//---------------------------------------------------------------------------- +vtkCollectPolyData::vtkCollectPolyData() +{ + this->PassThrough = 0; + this->SocketController = NULL; + + // Controller keeps a reference to this object as well. + this->Controller = NULL; + this->SetController(vtkMultiProcessController::GetGlobalController()); +} + +//---------------------------------------------------------------------------- +vtkCollectPolyData::~vtkCollectPolyData() +{ + this->SetController(0); + this->SetSocketController(0); +} + +//---------------------------------------------------------------------------- +int vtkCollectPolyData::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + return 1; +} + +//-------------------------------------------------------------------------- +int vtkCollectPolyData::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkCollectPolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int numProcs, myId; + int idx; + + if (this->Controller == NULL && this->SocketController == NULL) + { // Running as a single process. + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + return 1; + } + + if (this->Controller == NULL && this->SocketController != NULL) + { // This is a client. We assume no data on client for input. + if ( ! this->PassThrough) + { + vtkPolyData *pd = NULL;; + pd = vtkPolyData::New(); + this->SocketController->Receive(pd, 1, 121767); + output->CopyStructure(pd); + output->GetPointData()->PassData(pd->GetPointData()); + output->GetCellData()->PassData(pd->GetCellData()); + pd->Delete(); + pd = NULL; + return 1; + } + // If not collected, output will be empty from initialization. + return 0; + } + + myId = this->Controller->GetLocalProcessId(); + numProcs = this->Controller->GetNumberOfProcesses(); + + if (this->PassThrough) + { + // Just copy and return (no collection). + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + return 1; + } + + // Collect. + vtkAppendPolyData *append = vtkAppendPolyData::New(); + vtkPolyData *pd = NULL;; + + if (myId == 0) + { + pd = vtkPolyData::New(); + pd->CopyStructure(input); + pd->GetPointData()->PassData(input->GetPointData()); + pd->GetCellData()->PassData(input->GetCellData()); + append->AddInput(pd); + pd->Delete(); + for (idx = 1; idx < numProcs; ++idx) + { + pd = vtkPolyData::New(); + this->Controller->Receive(pd, idx, 121767); + append->AddInput(pd); + pd->Delete(); + pd = NULL; + } + append->Update(); + input = append->GetOutput(); + if (this->SocketController) + { // Send collected data onto client. + this->SocketController->Send(input, 1, 121767); + // output will be empty. + } + else + { // No client. Keep the output here. + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + } + append->Delete(); + append = NULL; + } + else + { + this->Controller->Send(input, 0, 121767); + append->Delete(); + append = NULL; + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkCollectPolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PassThough: " << this->PassThrough << endl; + os << indent << "Controller: (" << this->Controller << ")\n"; + os << indent << "SocketController: (" << this->SocketController << ")\n"; +} diff --git a/Parallel/vtkCollectPolyData.h b/Parallel/vtkCollectPolyData.h new file mode 100644 index 0000000..01fdef9 --- /dev/null +++ b/Parallel/vtkCollectPolyData.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCollectPolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCollectPolyData - Collect distributed polydata. +// .SECTION Description +// This filter has code to collect polydat from across processes onto node 0. +// Collection can be turned on or off using the "PassThrough" flag. + + +#ifndef __vtkCollectPolyData_h +#define __vtkCollectPolyData_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkMultiProcessController; +class vtkSocketController; + +class VTK_PARALLEL_EXPORT vtkCollectPolyData : public vtkPolyDataAlgorithm +{ +public: + static vtkCollectPolyData *New(); + vtkTypeRevisionMacro(vtkCollectPolyData, vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // By defualt this filter uses the global controller, + // but this method can be used to set another instead. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + + // Description: + // When this filter is being used in client-server mode, + // this is the controller used to communicate between + // client and server. Client should not set the other controller. + virtual void SetSocketController(vtkSocketController*); + vtkGetObjectMacro(SocketController, vtkSocketController); + + // Description: + // To collect or just copy input to output. Off (collect) by default. + vtkSetMacro(PassThrough, int); + vtkGetMacro(PassThrough, int); + vtkBooleanMacro(PassThrough, int); + +protected: + vtkCollectPolyData(); + ~vtkCollectPolyData(); + + int PassThrough; + + // Data generation method + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkMultiProcessController *Controller; + vtkSocketController *SocketController; + +private: + vtkCollectPolyData(const vtkCollectPolyData&); // Not implemented + void operator=(const vtkCollectPolyData&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkCommunicator.cxx b/Parallel/vtkCommunicator.cxx new file mode 100644 index 0000000..431346a --- /dev/null +++ b/Parallel/vtkCommunicator.cxx @@ -0,0 +1,525 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCommunicator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCommunicator.h" + +#include "vtkCharArray.h" +#include "vtkDataSetReader.h" +#include "vtkDataSetWriter.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIdTypeArray.h" +#include "vtkImageClip.h" +#include "vtkIntArray.h" +#include "vtkStructuredPoints.h" +#include "vtkStructuredPointsReader.h" +#include "vtkStructuredPointsWriter.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedLongArray.h" + +vtkCxxRevisionMacro(vtkCommunicator, "$Revision: 1.28 $"); + +template +int SendDataArray(T* data, int length, int handle, int tag, vtkCommunicator *self) +{ + + self->Send(data, length, handle, tag); + + return 1; +} + + +vtkCommunicator::vtkCommunicator() +{ + this->MarshalString = 0; + this->MarshalStringLength = 0; + this->MarshalDataLength = 0; +} + +vtkCommunicator::~vtkCommunicator() +{ + this->DeleteAndSetMarshalString(0, 0); +} + +int vtkCommunicator::UseCopy = 0; +void vtkCommunicator::SetUseCopy(int useCopy) +{ + vtkCommunicator::UseCopy = useCopy; +} + +void vtkCommunicator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Marshal string: "; + if ( this->MarshalString ) + { + os << this->MarshalString << endl; + } + else + { + os << "(None)" << endl; + } + os << indent << "Marshal string length: " << this->MarshalStringLength + << endl; + os << indent << "Marshal data length: " << this->MarshalDataLength + << endl; +} + +//---------------------------------------------------------------------------- +// Internal method. Assumes responsibility for deleting the string +void vtkCommunicator::DeleteAndSetMarshalString(char *str, int strLength) +{ + // delete any previous string + if (this->MarshalString) + { + delete [] this->MarshalString; + this->MarshalString = 0; + this->MarshalStringLength = 0; + this->MarshalDataLength = 0; + } + + this->MarshalString = str; + this->MarshalStringLength = strLength; +} + +// Need to add better error checking +int vtkCommunicator::Send(vtkDataObject* data, int remoteHandle, + int tag) +{ + + if (data == NULL) + { + this->MarshalDataLength = 0; + this->Send( &this->MarshalDataLength, 1, + remoteHandle, tag); + return 1; + } + if (this->WriteObject(data)) + { + this->Send( &this->MarshalDataLength, 1, + remoteHandle, tag); + // then send the string. + + this->Send( this->MarshalString, this->MarshalDataLength, + remoteHandle, tag); + + return 1; + } + + // could not marshal data + return 0; +} + +int vtkCommunicator::Send(vtkDataArray* data, int remoteHandle, int tag) +{ + + int type = -1; + if (data == NULL) + { + this->MarshalDataLength = 0; + this->Send( &type, 1, remoteHandle, tag); + return 1; + } + + // send array type + type = data->GetDataType(); + this->Send( &type, 1, remoteHandle, tag); + + // send array size + vtkIdType size = data->GetSize(); + this->Send( &size, 1, remoteHandle, tag); + + // send number of components in array + int numComponents = data->GetNumberOfComponents(); + this->Send( &numComponents, 1, remoteHandle, tag); + + + const char* name = data->GetName(); + int len = 0; + if (name) + { + len = static_cast(strlen(name)) + 1; + } + + // send length of name + this->Send( &len, 1, remoteHandle, tag); + + if (len > 0) + { + // send name + this->Send( const_cast(name), len, remoteHandle, tag); + } + + // now send the raw array + switch (type) + { + + case VTK_CHAR: + return SendDataArray(static_cast(data->GetVoidPointer(0)), + size, remoteHandle, tag, this); + + case VTK_UNSIGNED_CHAR: + return SendDataArray(static_cast(data->GetVoidPointer(0)), + size, remoteHandle, tag, this); + + case VTK_INT: + return SendDataArray(static_cast(data->GetVoidPointer(0)), + size, remoteHandle, tag, this); + + case VTK_UNSIGNED_LONG: + return SendDataArray(static_cast(data->GetVoidPointer(0)), + size, remoteHandle, tag, this); + + case VTK_FLOAT: + return SendDataArray(static_cast(data->GetVoidPointer(0)), + size, remoteHandle, tag, this); + + case VTK_DOUBLE: + return SendDataArray(static_cast(data->GetVoidPointer(0)), + size, remoteHandle, tag, this); + + case VTK_ID_TYPE: + return SendDataArray(static_cast(data->GetVoidPointer(0)), + size, remoteHandle, tag, this); + + default: + vtkErrorMacro(<<"Unsupported data type!"); + return 0; // could not marshal data + + } + +} + + +int vtkCommunicator::Receive(vtkDataObject* data, int remoteHandle, + int tag) +{ + int dataLength; + + // First receive the data length. + if (!this->Receive( &dataLength, 1, remoteHandle, tag)) + { + vtkErrorMacro("Could not receive data!"); + return 0; + } + + if (dataLength < 0) + { + vtkErrorMacro("Bad data length"); + return 0; + } + + if (dataLength == 0) + { // This indicates a NULL object was sent. Do nothing. + return 1; + } + + // if we cannot reuse the string, allocate a new one. + if (dataLength > this->MarshalStringLength) + { + char *str = new char[dataLength + 10]; // maybe a little extra? + this->DeleteAndSetMarshalString(str, dataLength + 10); + } + + // Receive the string + this->Receive(this->MarshalString, dataLength, + remoteHandle, tag); + this->MarshalDataLength = dataLength; + + this->ReadObject(data); + + // we should really look at status to determine success + return 1; +} + +int vtkCommunicator::Receive(vtkDataArray* data, int remoteHandle, + int tag) +{ + vtkIdType size; + int type; + int numComponents; + int nameLength; + + char *c = 0; + unsigned char *uc = 0; + int *i = 0; + unsigned long *ul = 0; + float *f = 0; + double *d = 0; + vtkIdType *idt = 0; + + + // First receive the data type. + if (!this->Receive( &type, 1, remoteHandle, tag)) + { + vtkErrorMacro("Could not receive data!"); + return 0; + } + + if (type == -1) + { // This indicates a NULL object was sent. Do nothing. + return 1; + } + + // Next receive the data length. + if (!this->Receive( &size, 1, remoteHandle, tag)) + { + vtkErrorMacro("Could not receive data!"); + return 0; + } + + // Next receive the number of components. + this->Receive( &numComponents, 1, remoteHandle, tag); + + // Next receive the length of the name. + this->Receive( &nameLength, 1, remoteHandle, tag); + + if ( nameLength > 0 ) + { + char *str = new char[nameLength]; + this->DeleteAndSetMarshalString(str, nameLength); + + // Receive the name + this->Receive(this->MarshalString, nameLength, remoteHandle, tag); + this->MarshalDataLength = nameLength; + } + + if (size < 0) + { + vtkErrorMacro("Bad data length"); + return 0; + } + + if (size == 0) + { // This indicates a NULL object was sent. Do nothing. + return 1; + } + + // Receive the raw data array + switch (type) + { + + case VTK_CHAR: + c = new char[size]; + this->Receive(c, size, remoteHandle, tag); + static_cast(data)->SetArray(c, size, 0); + break; + + case VTK_UNSIGNED_CHAR: + uc = new unsigned char[size]; + this->Receive(uc, size, remoteHandle, tag); + static_cast(data)->SetArray(uc, size, 0); + break; + + case VTK_INT: + i = new int[size]; + this->Receive(i, size, remoteHandle, tag); + static_cast(data)->SetArray(i, size, 0); + break; + + case VTK_UNSIGNED_LONG: + ul = new unsigned long[size]; + this->Receive(ul, size, remoteHandle, tag); + static_cast(data)->SetArray(ul, size, 0); + break; + + case VTK_FLOAT: + f = new float[size]; + this->Receive(f, size, remoteHandle, tag); + static_cast(data)->SetArray(f, size, 0); + break; + + case VTK_DOUBLE: + + d = new double[size]; + this->Receive(d, size, remoteHandle, tag); + static_cast(data)->SetArray(d, size, 0); + break; + + case VTK_ID_TYPE: + idt = new vtkIdType[size]; + this->Receive(idt, size, remoteHandle, tag); + static_cast(data)->SetArray(idt, size, 0); + break; + + default: + vtkErrorMacro(<<"Unsupported data type!"); + return 0; // could not marshal data + + } + + if (nameLength > 0) + { + data->SetName(this->MarshalString); + } + else + { + data->SetName(0); + } + data->SetNumberOfComponents(numComponents); + + return 1; + +} + +int vtkCommunicator::WriteObject(vtkDataObject *data) +{ + if (strcmp(data->GetClassName(), "vtkPolyData") == 0 || + strcmp(data->GetClassName(), "vtkUnstructuredGrid") == 0 || + strcmp(data->GetClassName(), "vtkStructuredGrid") == 0 || + strcmp(data->GetClassName(), "vtkRectilinearGrid") == 0 || + strcmp(data->GetClassName(), "vtkStructuredPoints") == 0) + { + return this->WriteDataSet((vtkDataSet*)data); + } + if (strcmp(data->GetClassName(), "vtkImageData") == 0) + { + return this->WriteImageData((vtkImageData*)data); + } + + vtkErrorMacro("Cannot marshal object of type " + << data->GetClassName()); + return 0; +} + +int vtkCommunicator::ReadObject(vtkDataObject *data) +{ + if (strcmp(data->GetClassName(), "vtkPolyData") == 0 || + strcmp(data->GetClassName(), "vtkUnstructuredGrid") == 0 || + strcmp(data->GetClassName(), "vtkStructuredGrid") == 0 || + strcmp(data->GetClassName(), "vtkRectilinearGrid") == 0 || + strcmp(data->GetClassName(), "vtkStructuredPoints") == 0) + { + return this->ReadDataSet((vtkDataSet*)data); + } + if (strcmp(data->GetClassName(), "vtkImageData") == 0) + { + return this->ReadImageData((vtkImageData*)data); + } + + vtkErrorMacro("Cannot marshal object of type " + << data->GetClassName()); + + return 1; +} + + +int vtkCommunicator::WriteImageData(vtkImageData *data) +{ + vtkImageClip *clip; + vtkStructuredPointsWriter *writer; + int size; + + // keep Update from propagating + vtkImageData *tmp = vtkImageData::New(); + tmp->ShallowCopy(data); + + clip = vtkImageClip::New(); + clip->SetInput(tmp); + clip->SetOutputWholeExtent(data->GetExtent()); + writer = vtkStructuredPointsWriter::New(); + writer->SetFileTypeToBinary(); + writer->WriteToOutputStringOn(); + writer->SetInput(clip->GetOutput()); + writer->Write(); + size = writer->GetOutputStringLength(); + + this->DeleteAndSetMarshalString(writer->RegisterAndGetOutputString(), size); + this->MarshalDataLength = size; + clip->Delete(); + writer->Delete(); + tmp->Delete(); + + return 1; +} + +int vtkCommunicator::ReadImageData(vtkImageData *object) +{ + vtkStructuredPointsReader *reader = vtkStructuredPointsReader::New(); + + if (this->MarshalString == NULL || this->MarshalStringLength <= 0) + { + return 0; + } + + reader->ReadFromInputStringOn(); + + vtkCharArray* mystring = vtkCharArray::New(); + // mystring should not delete the string when it's done, + // that's our job. + mystring->SetArray(this->MarshalString, this->MarshalDataLength, 1); + reader->SetInputArray(mystring); + mystring->Delete(); + + reader->GetOutput()->Update(); + + object->ShallowCopy(reader->GetOutput()); + + reader->Delete(); + + return 1; +} + +int vtkCommunicator::WriteDataSet(vtkDataSet *data) +{ + vtkDataSet *copy; + unsigned long size; + vtkDataSetWriter *writer = vtkDataSetWriter::New(); + + copy = data->NewInstance(); + copy->ShallowCopy(data); + + // There is a problem with binary files with no data. + if (copy->GetNumberOfCells() + copy->GetNumberOfPoints() > 0) + { + writer->SetFileTypeToBinary(); + } + writer->WriteToOutputStringOn(); + writer->SetInput(copy); + + writer->Write(); + size = writer->GetOutputStringLength(); + this->DeleteAndSetMarshalString(writer->RegisterAndGetOutputString(), size); + this->MarshalDataLength = size; + writer->Delete(); + copy->Delete(); + + return 1; +} + +int vtkCommunicator::ReadDataSet(vtkDataSet *object) +{ + vtkDataSetReader *reader = vtkDataSetReader::New(); + + if (this->MarshalString == NULL || this->MarshalStringLength <= 0) + { + return 0; + } + + reader->ReadFromInputStringOn(); + + vtkCharArray* mystring = vtkCharArray::New(); + // mystring should not delete the string when it's done, + // that's our job. + mystring->SetArray(this->MarshalString, this->MarshalDataLength, 1); + reader->SetInputArray(mystring); + mystring->Delete(); + + reader->Update(); + object->ShallowCopy(reader->GetOutput()); + + reader->Delete(); + + return 1; +} diff --git a/Parallel/vtkCommunicator.h b/Parallel/vtkCommunicator.h new file mode 100644 index 0000000..1d54b3a --- /dev/null +++ b/Parallel/vtkCommunicator.h @@ -0,0 +1,144 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCommunicator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCommunicator - Used to send/receive messages in a multiprocess environment. +// .SECTION Description +// This is an abstact class which contains functionality for sending +// and receiving inter-process messages. It contains methods for marshaling +// an object into a string (currently used by the MPI communicator but +// not the shared memory communicator). + +// .SECTION Caveats +// Communication between systems with different vtkIdTypes is not +// supported. All machines have to have the same vtkIdType. + +// .SECTION see also +// vtkMPICommunicator + +#ifndef __vtkCommunicator_h +#define __vtkCommunicator_h + +#include "vtkObject.h" + +class vtkDataSet; +class vtkImageData; +class vtkDataObject; +class vtkDataArray; + +class VTK_PARALLEL_EXPORT vtkCommunicator : public vtkObject +{ + +public: + + vtkTypeRevisionMacro(vtkCommunicator, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method sends a data object to a destination. + // Tag eliminates ambiguity + // and is used to match sends to receives. + virtual int Send(vtkDataObject* data, int remoteHandle, int tag); + + // Description: + // This method sends a data array to a destination. + // Tag eliminates ambiguity + // and is used to match sends to receives. + virtual int Send(vtkDataArray* data, int remoteHandle, int tag); + + // Description: + // Subclass have to supply these methods to send various arrays of data. + virtual int Send(int* data, int length, int remoteHandle, int tag) = 0; + virtual int Send(unsigned long* data, int length, int remoteHandle, + int tag) = 0; + virtual int Send(unsigned char* data, int length, int remoteHandle, + int tag) = 0; + virtual int Send(char* data, int length, int remoteHandle, + int tag) = 0; + virtual int Send(float* data, int length, int remoteHandle, + int tag) = 0; + virtual int Send(double* data, int length, int remoteHandle, + int tag) = 0; +#ifdef VTK_USE_64BIT_IDS + virtual int Send(vtkIdType* data, int length, int remoteHandle, + int tag) = 0; +#endif + + + // Description: + // This method receives a data object from a corresponding send. It blocks + // until the receive is finished. + virtual int Receive(vtkDataObject* data, int remoteHandle, int tag); + + // Description: + // This method receives a data array from a corresponding send. It blocks + // until the receive is finished. + virtual int Receive(vtkDataArray* data, int remoteHandle, int tag); + + // Description: + // Subclass have to supply these methods to receive various arrays of data. + virtual int Receive(int* data, int length, int remoteHandle, + int tag) = 0; + virtual int Receive(unsigned long* data, int length, int remoteHandle, + int tag) = 0; + virtual int Receive(unsigned char* data, int length, int remoteHandle, + int tag) = 0; + virtual int Receive(char* data, int length, int remoteHandle, + int tag) = 0; + virtual int Receive(float* data, int length, int remoteHandle, + int tag) = 0; + virtual int Receive(double* data, int length, int remoteHandle, + int tag) = 0; +#ifdef VTK_USE_64BIT_IDS + virtual int Receive(vtkIdType* data, int length, int remoteHandle, + int tag) = 0; +#endif + + static void SetUseCopy(int useCopy); + +protected: + + void DeleteAndSetMarshalString(char *str, int strLength); + + // Write and read from marshal string + // return 1 success, 0 fail + int WriteObject(vtkDataObject *object); + int ReadObject(vtkDataObject *object); + + int WriteDataSet(vtkDataSet *object); + int ReadDataSet(vtkDataSet *object); + + int WriteImageData(vtkImageData *object); + int ReadImageData(vtkImageData *object); + + int WriteDataArray(vtkDataArray *object); + int ReadDataArray(vtkDataArray *object); + + vtkCommunicator(); + ~vtkCommunicator(); + + char *MarshalString; + int MarshalStringLength; + // The data may not take up all of the string. + int MarshalDataLength; + + static int UseCopy; + +private: + vtkCommunicator(const vtkCommunicator&); // Not implemented. + void operator=(const vtkCommunicator&); // Not implemented. +}; + +#endif // __vtkCommunicator_h + + diff --git a/Parallel/vtkCompositeRenderManager.cxx b/Parallel/vtkCompositeRenderManager.cxx new file mode 100644 index 0000000..a750962 --- /dev/null +++ b/Parallel/vtkCompositeRenderManager.cxx @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositeRenderManager.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCompositeRenderManager.h" + +#include "vtkCompressCompositer.h" +#include "vtkFloatArray.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkTimerLog.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkCompositeRenderManager, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkCompositeRenderManager); + +vtkCxxSetObjectMacro(vtkCompositeRenderManager, Compositer, vtkCompositer); + +//---------------------------------------------------------------------------- +vtkCompositeRenderManager::vtkCompositeRenderManager() +{ + this->Compositer = vtkCompressCompositer::New(); + this->Compositer->Register( this ); + this->Compositer->Delete(); + + this->DepthData = vtkFloatArray::New(); + this->TmpPixelData = vtkUnsignedCharArray::New(); + this->TmpDepthData = vtkFloatArray::New(); + + this->DepthData->SetNumberOfComponents(1); + this->TmpPixelData->SetNumberOfComponents(4); + this->TmpDepthData->SetNumberOfComponents(1); +} + +//---------------------------------------------------------------------------- +vtkCompositeRenderManager::~vtkCompositeRenderManager() +{ + this->SetCompositer(NULL); + this->DepthData->Delete(); + this->TmpPixelData->Delete(); + this->TmpDepthData->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkCompositeRenderManager::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "ImageProcessingTime: " << this->ImageProcessingTime << endl; + os << indent << "Compositer: " << endl; + this->Compositer->PrintSelf(os, indent.GetNextIndent()); +} + +//---------------------------------------------------------------------------- +void vtkCompositeRenderManager::PreRenderProcessing() +{ +} + +//---------------------------------------------------------------------------- +void vtkCompositeRenderManager::PostRenderProcessing() +{ + if (this->Controller->GetNumberOfProcesses() > 1) + { + // Read in data. + this->ReadReducedImage(); + this->Timer->StartTimer(); + this->RenderWindow->GetZbufferData(0, 0, this->ReducedImageSize[0]-1, + this->ReducedImageSize[1]-1, + this->DepthData); + + // Set up temporary buffers. + this->TmpPixelData->SetNumberOfComponents + (this->ReducedImage->GetNumberOfComponents()); + this->TmpPixelData->SetNumberOfTuples + (this->ReducedImage->GetNumberOfTuples()); + this->TmpDepthData->SetNumberOfComponents + (this->DepthData->GetNumberOfComponents()); + this->TmpDepthData->SetNumberOfTuples(this->DepthData->GetNumberOfTuples()); + + // Do composite + this->Compositer->SetController(this->Controller); + this->Compositer->CompositeBuffer(this->ReducedImage, this->DepthData, + this->TmpPixelData, this->TmpDepthData); + + this->Timer->StopTimer(); + this->ImageProcessingTime = this->Timer->GetElapsedTime(); + } + + this->WriteFullImage(); +} + + diff --git a/Parallel/vtkCompositeRenderManager.h b/Parallel/vtkCompositeRenderManager.h new file mode 100644 index 0000000..6e9099a --- /dev/null +++ b/Parallel/vtkCompositeRenderManager.h @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositeRenderManager.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCompositeRenderManager - An object to control sort-last parallel rendering. +// +// .SECTION Description: +// vtkCompositeRenderManager is a subclass of vtkParallelRenderManager that +// uses compositing to do parallel rendering. This class has +// replaced vtkCompositeManager. +// + + +#ifndef __vtkCompositeRenderManager_h +#define __vtkCompositeRenderManager_h + +#include "vtkParallelRenderManager.h" + +class vtkCompositer; +class vtkFloatArray; + +class VTK_PARALLEL_EXPORT vtkCompositeRenderManager : public vtkParallelRenderManager +{ +public: + vtkTypeRevisionMacro(vtkCompositeRenderManager, vtkParallelRenderManager); + static vtkCompositeRenderManager *New(); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + // Description: + // Set/Get the composite algorithm. + void SetCompositer(vtkCompositer *c); + vtkGetObjectMacro(Compositer, vtkCompositer); + + // Description: + // Get rendering metrics. + vtkGetMacro(ImageProcessingTime, double); + +protected: + vtkCompositeRenderManager(); + ~vtkCompositeRenderManager(); + + vtkCompositer *Compositer; + + virtual void PreRenderProcessing(); + virtual void PostRenderProcessing(); + + vtkFloatArray *DepthData; + vtkUnsignedCharArray *TmpPixelData; + vtkFloatArray *TmpDepthData; + +private: + vtkCompositeRenderManager(const vtkCompositeRenderManager &);//Not implemented + void operator=(const vtkCompositeRenderManager &); //Not implemented +}; + +#endif //__vtkCompositeRenderManager_h diff --git a/Parallel/vtkCompositer.cxx b/Parallel/vtkCompositer.cxx new file mode 100644 index 0000000..4f81842 --- /dev/null +++ b/Parallel/vtkCompositer.cxx @@ -0,0 +1,158 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkCompositer.h" +#include "vtkObjectFactory.h" +#include "vtkToolkits.h" +#include "vtkDataArray.h" +#include "vtkFloatArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkMultiProcessController.h" + +#ifdef VTK_USE_MPI + #include +#endif + +vtkCxxRevisionMacro(vtkCompositer, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkCompositer); + +//------------------------------------------------------------------------- +vtkCompositer::vtkCompositer() +{ + this->Controller = vtkMultiProcessController::GetGlobalController(); + this->NumberOfProcesses = 1; + if (this->Controller) + { + this->Controller->Register(this); + this->NumberOfProcesses = this->Controller->GetNumberOfProcesses(); + } +} + +//------------------------------------------------------------------------- +vtkCompositer::~vtkCompositer() +{ + this->SetController(NULL); +} + + +//------------------------------------------------------------------------- +void vtkCompositer::SetController(vtkMultiProcessController *mpc) +{ + if (this->Controller == mpc) + { + return; + } + if (mpc) + { + mpc->Register(this); + this->NumberOfProcesses = mpc->GetNumberOfProcesses(); + } + if (this->Controller) + { + this->Controller->UnRegister(this); + } + this->Controller = mpc; +} + +//------------------------------------------------------------------------- +void vtkCompositer::CompositeBuffer(vtkDataArray *pBuf, vtkFloatArray *zBuf, + vtkDataArray *pTmp, vtkFloatArray *zTmp) +{ + pBuf = pBuf; + zBuf = zBuf; + pTmp = pTmp; + zTmp = zTmp; +} + +//------------------------------------------------------------------------- + +void vtkCompositer::ResizeFloatArray(vtkFloatArray* fa, int numComp, + vtkIdType size) +{ + fa->SetNumberOfComponents(numComp); + +#ifdef MPIPROALLOC + vtkIdType fa_size = fa->GetSize(); + if ( fa_size < size*numComp ) + { + float* ptr = fa->GetPointer(0); + if (ptr) + { + MPI_Free_mem(ptr); + } + char* tptr; + MPI_Alloc_mem(size*numComp*sizeof(float), NULL, &tptr); + ptr = (float*)tptr; + fa->SetArray(ptr, size*numComp, 1); + } + else + { + fa->SetNumberOfTuples(size); + } +#else + fa->SetNumberOfTuples(size); +#endif +} + +void vtkCompositer::ResizeUnsignedCharArray(vtkUnsignedCharArray* uca, + int numComp, vtkIdType size) +{ + uca->SetNumberOfComponents(numComp); +#ifdef MPIPROALLOC + vtkIdType uca_size = uca->GetSize(); + + if ( uca_size < size*numComp ) + { + unsigned char* ptr = uca->GetPointer(0); + if (ptr) + { + MPI_Free_mem(ptr); + } + char* tptr; + MPI_Alloc_mem(size*numComp*sizeof(unsigned char), NULL, &tptr); + ptr = (unsigned char*)tptr; + uca->SetArray(ptr, size*numComp, 1); + } + else + { + uca->SetNumberOfTuples(size); + } +#else + uca->SetNumberOfTuples(size); +#endif +} + +void vtkCompositer::DeleteArray(vtkDataArray* da) +{ +#ifdef MPIPROALLOC + void* ptr = da->GetVoidPointer(0); + if (ptr) + { + MPI_Free_mem(ptr); + } +#endif + da->Delete(); +} + +//------------------------------------------------------------------------- +void vtkCompositer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "Controller: (" << this->Controller << ")\n"; + os << indent << "NumberOfProcesses: " << this->NumberOfProcesses << endl; +} + + + diff --git a/Parallel/vtkCompositer.h b/Parallel/vtkCompositer.h new file mode 100644 index 0000000..491dbb7 --- /dev/null +++ b/Parallel/vtkCompositer.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompositer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCompositer - Super class for composite algorthms. +// +// .SECTION Description +// vtkCompositer operates in multiple processes. Each compositer has +// a render window. They use vtkMultiProcessControllers to communicate +// the color and depth buffer to process 0's render window. +// It will not handle transparency well. +// +// .SECTION See Also +// vtkCompositeManager. + +#ifndef __vtkCompositer_h +#define __vtkCompositer_h + +#include "vtkObject.h" + +class vtkMultiProcessController; +class vtkCompositer; +class vtkDataArray; +class vtkFloatArray; +class vtkUnsignedCharArray; + +class VTK_PARALLEL_EXPORT vtkCompositer : public vtkObject +{ +public: + static vtkCompositer *New(); + vtkTypeRevisionMacro(vtkCompositer,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method gets called on every process. The final image gets + // put into pBuf and zBuf. + virtual void CompositeBuffer(vtkDataArray *pBuf, vtkFloatArray *zBuf, + vtkDataArray *pTmp, vtkFloatArray *zTmp); + + // Description: + // Access to the controller. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller,vtkMultiProcessController); + + // Description: + // A hack to get a sub world until I can get communicators working. + vtkSetMacro(NumberOfProcesses, int); + vtkGetMacro(NumberOfProcesses, int); + + // Description: + // Methods that allocate and delete memory with special MPIPro calls. + static void DeleteArray(vtkDataArray* da); + static void ResizeFloatArray(vtkFloatArray* fa, int numComp, + vtkIdType size); + static void ResizeUnsignedCharArray(vtkUnsignedCharArray* uca, + int numComp, vtkIdType size); + +protected: + vtkCompositer(); + ~vtkCompositer(); + + vtkMultiProcessController *Controller; + int NumberOfProcesses; + +private: + vtkCompositer(const vtkCompositer&); // Not implemented + void operator=(const vtkCompositer&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkCompressCompositer.cxx b/Parallel/vtkCompressCompositer.cxx new file mode 100644 index 0000000..bcebc98 --- /dev/null +++ b/Parallel/vtkCompressCompositer.cxx @@ -0,0 +1,710 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompressCompositer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// This software and ancillary information known as vtk_ext (and +// herein called "SOFTWARE") is made available under the terms +// described below. The SOFTWARE has been approved for release with +// associated LA_CC Number 99-44, granted by Los Alamos National +// Laboratory in July 1999. +// +// Unless otherwise indicated, this SOFTWARE has been authored by an +// employee or employees of the University of California, operator of +// the Los Alamos National Laboratory under Contract No. W-7405-ENG-36 +// with the United States Department of Energy. +// +// The United States Government has rights to use, reproduce, and +// distribute this SOFTWARE. The public may copy, distribute, prepare +// derivative works and publicly display this SOFTWARE without charge, +// provided that this Notice and any statement of authorship are +// reproduced on all copies. +// +// Neither the U. S. Government, the University of California, nor the +// Advanced Computing Laboratory makes any warranty, either express or +// implied, nor assumes any liability or responsibility for the use of +// this SOFTWARE. +// +// If SOFTWARE is modified to produce derivative works, such modified +// SOFTWARE should be clearly marked, so as not to confuse it with the +// version available from Los Alamos National Laboratory. + +#ifdef VTK_USE_MPI + #include +#endif + +#include "vtkCompressCompositer.h" +#include "vtkObjectFactory.h" +#include "vtkToolkits.h" +#include "vtkFloatArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkMultiProcessController.h" + +#include "vtkTimerLog.h" + +vtkCxxRevisionMacro(vtkCompressCompositer, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkCompressCompositer); + + +// Different pixel types to template. +typedef struct { + unsigned char r; + unsigned char g; + unsigned char b; +} vtkCharRGBType; + +typedef struct { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; +} vtkCharRGBAType; + +typedef struct { + float r; + float g; + float b; + float a; +} vtkFloatRGBAType; + + + +//------------------------------------------------------------------------- +vtkCompressCompositer::vtkCompressCompositer() +{ + this->InternalPData = NULL; + this->InternalZData = NULL; + this->Timer = vtkTimerLog::New(); +} + + +//------------------------------------------------------------------------- +vtkCompressCompositer::~vtkCompressCompositer() +{ + if (this->InternalPData) + { + this->InternalPData->Delete(); + this->InternalPData = NULL; + } + if (this->InternalZData) + { + this->InternalZData->Delete(); + this->InternalZData = NULL; + } + + this->Timer->Delete(); + this->Timer = NULL; +} + + + +//------------------------------------------------------------------------- +// Compress background pixels with runlength encoding. +// z values above 1.0 mean: Repeat background for that many pixels. +// We could easily compress inplace, but it works out better for buffer +// managment if we do not. zIn == zOut is allowed.... +template +int vtkCompressCompositerCompress(float *zIn, P *pIn, float *zOut, P *pOut, + int numPixels) +{ + float* endZ; + int length = 0; + int compressCount; + + // Do not go past the last pixel (zbuf check/correct) + endZ = zIn+numPixels-1; + if (*zIn < 0.0 || *zIn > 1.0) + { + *zIn = 1.0; + } + while (zIn < endZ) + { + ++length; + // Always copy the first pixel value. + *pOut++ = *pIn++; + // Find the length of any compressed run. + compressCount = 0; + while (*zIn == 1.0 && zIn < endZ) + { + ++compressCount; + ++zIn; + if (*zIn < 0.0 || *zIn > 1.0) + { + *zIn = 1.0; + } + } + + if (compressCount > 0) + { // Only compress runs of 2 or more. + // Move the pixel pointer past compressed region. + pIn += (compressCount-1); + // Set the special z value. + *zOut++ = (float)(compressCount); + } + else + { + *zOut++ = *zIn++; + if (*zIn < 0.0 || *zIn > 1.0) + { + *zIn = 1.0; + } + } + } + // Put the last pixel in. + *pOut = *pIn; + *zOut = *zIn; + + return length; +} + +//------------------------------------------------------------------------- +// Compress background pixels with runlength encoding. +// z values above 1.0 mean: Repeat background for that many pixels. +// We could easily compress inplace, but it works out better for buffer +// managment if we do not. zIn == zOut is allowed.... +void vtkCompressCompositer::Compress(vtkFloatArray *zIn, vtkDataArray *pIn, + vtkFloatArray *zOut, vtkDataArray *pOut) +{ + float* pzf1 = zIn->GetPointer(0); + float* pzf2 = zOut->GetPointer(0); + void* ppv1 = pIn->GetVoidPointer(0); + void* ppv2 = pOut->GetVoidPointer(0); + int totalPixels = zIn->GetNumberOfTuples(); + int length; + + vtkTimerLog::MarkStartEvent("Compress"); + + // This is just a complex switch statment + // to call the correct templated function. + if (pIn->GetDataType() == VTK_UNSIGNED_CHAR) + { + if (pIn->GetNumberOfComponents() == 3) + { + length = vtkCompressCompositerCompress( + pzf1, reinterpret_cast(ppv1), + pzf2, reinterpret_cast(ppv2), + totalPixels); + } + else if (pIn->GetNumberOfComponents() == 4) + { + length = vtkCompressCompositerCompress( + pzf1, reinterpret_cast(ppv1), + pzf2, reinterpret_cast(ppv2), + totalPixels); + } + else + { + vtkGenericWarningMacro("Pixels have unexpected number of components."); + return; + } + } + else if (pIn->GetDataType() == VTK_FLOAT && + pIn->GetNumberOfComponents() == 4) + { + length = vtkCompressCompositerCompress( + pzf1, reinterpret_cast(ppv1), + pzf2, reinterpret_cast(ppv2), + totalPixels); + } + else + { + vtkGenericWarningMacro("Unexpected pixel type."); + return; + } + + zOut->SetNumberOfTuples(length); + pOut->SetNumberOfTuples(length); + + vtkTimerLog::MarkEndEvent("Compress"); +} + +//------------------------------------------------------------------------- +// z values above 1.0 mean: Repeat background for that many pixels. +// Assume that the array has enough allocated space for the uncompressed. +// In place/reverse order. +template +void vtkCompressCompositerUncompress(float *zIn, P *pIn, float *zOut, P *pOut, + int lengthIn) +{ + float* endZ; + int count; + P background; + + endZ = zIn + lengthIn; + + while (zIn < endZ) + { + // Expand any compressed data. + if (*zIn > 1.0) + { + background = *pIn++; + count = (int)(*zIn++); + while (count-- > 0) + { + *pOut++ = background; + *zOut++ = 1.0; + } + } + else + { + *pOut++ = *pIn++; + *zOut++ = *zIn++; + } + } +} + +//------------------------------------------------------------------------- +// Compress background pixels with runlength encoding. +// z values above 1.0 mean: Repeat background for that many pixels. +// We could easily compress inplace, but it works out better for buffer +// managment if we do not. zIn == zOut is allowed.... +void vtkCompressCompositer::Uncompress(vtkFloatArray *zIn, vtkDataArray *pIn, + vtkFloatArray *zOut, vtkDataArray *pOut, + int lengthOut) +{ + float* pzf1 = zIn->GetPointer(0); + float* pzf2 = zOut->GetPointer(0); + void* ppv1 = pIn->GetVoidPointer(0); + void* ppv2 = pOut->GetVoidPointer(0); + int lengthIn = zIn->GetNumberOfTuples(); + + vtkTimerLog::MarkStartEvent("Uncompress"); + + // This is just a complex switch statment + // to call the correct templated function. + if (pIn->GetDataType() == VTK_UNSIGNED_CHAR) + { + if (pIn->GetNumberOfComponents() == 3) + { + vtkCompressCompositerUncompress(pzf1, + reinterpret_cast(ppv1), + pzf2, + reinterpret_cast(ppv2), + lengthIn); + } + else if (pIn->GetNumberOfComponents() == 4) + { + vtkCompressCompositerUncompress(pzf1, + reinterpret_cast(ppv1), + pzf2, + reinterpret_cast(ppv2), + lengthIn); + } + else + { + vtkGenericWarningMacro("Pixels have unexpected number of components."); + return; + } + } + else if (pIn->GetDataType() == VTK_FLOAT && + pIn->GetNumberOfComponents() == 4) + { + vtkCompressCompositerUncompress(pzf1, + reinterpret_cast(ppv1), + pzf2, + reinterpret_cast(ppv2), + lengthIn); + } + else + { + vtkGenericWarningMacro("Unexpected pixel type."); + return; + } + + //zOut->SetNumberOfTuples(lengthOut); + pOut->SetNumberOfTuples(lengthOut); + + vtkTimerLog::MarkEndEvent("Uncompress"); +} + + + + +//------------------------------------------------------------------------- +// Can handle compositing compressed buffers. +// z values above 1.0 mean: Repeat background for that many pixels. +template +int vtkCompressCompositerCompositePair(float *z1, P *p1, float *z2, P *p2, + float *zOut, P *pOut, int length1) +{ + float* startZOut = zOut; + float* endZ1; + // These counts keep track of the length of compressed runs. + // Value -1 means pointer is not on a compression run. + // Value 0 means pointer is on a used up compression run. + int cCount1 = 0; + int cCount2 = 0; + int cCount3; + int length3; + + // This is for the end test. + // We are assuming that the uncompressed buffer length of 1 and 2 + // are the same. + endZ1 = z1 + length1; + + while(z1 != endZ1) + { + // Initialize a new state if necessary. + if (cCount1 == 0 && *z1 > 1.0) + { // Detect a new run in buffer 1. + cCount1 = (int)(*z1); + } + if (cCount2 == 0 && *z2 > 1.0) + { // Detect a new run in buffer 2. + cCount2 = (int)(*z2); + } + + // Case 1: Neither buffer is compressed. + // We could keep the length of uncompressed runs ... + if (cCount1 == 0 && cCount2 == 0) + { + // Loop through buffers doing standard compositing. + while (*z1 <= 1.0 && *z2 <= 1.0 && z1 != endZ1) + { + if (*z1 < *z2) + { + *zOut++ = *z1++; + ++z2; + *pOut++ = *p1++; + ++p2; + } + else + { + *zOut++ = *z2++; + ++z1; + *pOut++ = *p2++; + ++p1; + } + } + // Let the next iteration determine the new state (counts). + } + else if (cCount1 > 0 && cCount2 > 0) + { // segment where both are compressed + // Pick the smaller compressed run an duplicate in output. + cCount3 = (cCount1 < cCount2) ? cCount1 : cCount2; + cCount2 -= cCount3; + cCount1 -= cCount3; + // Set the output pixel. + *zOut++ = (float)(cCount3); + // either pixel will do. + *pOut++ = *p1; + if (cCount1 == 0) + { + ++z1; + ++p1; + } + if (cCount2 == 0) + { + ++z2; + ++p2; + } + } + else if (cCount1 > 0 && cCount2 == 0) + { //1 is in a compressed run but 2 is not. + // Copy from 2 until we hit a compressed region, + // or we run out of the 1 compressed run. + while (cCount1 && *z2 <= 1.0) + { + *zOut++ = *z2++; + *pOut++ = *p2++; + --cCount1; + } + if (cCount1 == 0) + { + ++z1; + ++p1; + } + } + else if (cCount1 == 0 && cCount2 > 0) + { //2 is in a compressed run but 1 is not. + // Copy from 1 until we hit a compressed region, + // or we run out of the 2 compressed run. + while (cCount2 && *z1 <= 1.0) + { + *zOut++ = *z1++; + *pOut++ = *p1++; + --cCount2; + } + if (cCount2 == 0) + { + ++z2; + ++p2; + } + } // end case if. + } // while not finished (process cases). + // Here is a scary way to determine the length of the new buffer. + length3 = zOut - startZOut; + + return length3; +} + +//------------------------------------------------------------------------- +// Can handle compositing compressed buffers. +// z values above 1.0 mean: Repeat background for that many pixels. +void vtkCompressCompositer::CompositeImagePair( + vtkFloatArray *localZ, vtkDataArray *localP, + vtkFloatArray *remoteZ, vtkDataArray *remoteP, + vtkFloatArray *outZ, vtkDataArray *outP) +{ + float* z1 = localZ->GetPointer(0); + float* z2 = remoteZ->GetPointer(0); + float* z3 = outZ->GetPointer(0); + void* p1 = localP->GetVoidPointer(0); + void* p2 = remoteP->GetVoidPointer(0); + void* p3 = outP->GetVoidPointer(0); + int length1 = localZ->GetNumberOfTuples(); + int l3; + + //vtkTimerLog::MarkStartEvent("Coomposite Image Pair"); + + // This is just a complex switch statment + // to call the correct templated function. + if (localP->GetDataType() == VTK_UNSIGNED_CHAR) + { + if (localP->GetNumberOfComponents() == 3) + { + l3 = vtkCompressCompositerCompositePair( + z1, reinterpret_cast(p1), + z2, reinterpret_cast(p2), + z3, reinterpret_cast(p3), + length1); + } + else if (localP->GetNumberOfComponents() == 4) + { + l3 = vtkCompressCompositerCompositePair( + z1, reinterpret_cast(p1), + z2, reinterpret_cast(p2), + z3, reinterpret_cast(p3), + length1); + } + else + { + vtkGenericWarningMacro("Pixels have unexpected number of components."); + return; + } + } + else if (localP->GetDataType() == VTK_FLOAT && + localP->GetNumberOfComponents() == 4) + { + l3 = vtkCompressCompositerCompositePair( + z1, reinterpret_cast(p1), + z2, reinterpret_cast(p2), + z3, reinterpret_cast(p3), + length1); + } + else + { + vtkGenericWarningMacro("Unexpected pixel type."); + return; + } + + outZ->SetNumberOfTuples(l3); + outP->SetNumberOfTuples(l3); + + //vtkTimerLog::MarkEndEvent("Coomposite Image Pair"); +} + + + +#define vtkTCPow2(j) (1 << (j)) + +//---------------------------------------------------------------------------- +inline int vtkTCLog2(int j, int& exact) +{ + int counter=0; + exact = 1; + while(j) + { + if ( ( j & 1 ) && (j >> 1) ) + { + exact = 0; + } + j = j >> 1; + counter++; + } + return counter-1; +} + +//---------------------------------------------------------------------------- +void vtkCompressCompositer::CompositeBuffer(vtkDataArray *pBuf, + vtkFloatArray *zBuf, + vtkDataArray *pTmp, + vtkFloatArray *zTmp) +{ + int myId = this->Controller->GetLocalProcessId(); + int numProcs = this->NumberOfProcesses; + int i, id; + int exactLog; + int logProcs = vtkTCLog2(numProcs,exactLog); + int uncompressedLength = zBuf->GetNumberOfTuples(); + int bufSize=0; + int numComps = pBuf->GetNumberOfComponents(); + vtkDataArray *p1, *p2, *p3; + vtkFloatArray *z1, *z2, *z3; + + //this->Timer->StartTimer(); + + // Make sure we have an internal buffer of the correct length. + if (this->InternalPData == NULL || + this->InternalPData->GetDataType() != pBuf->GetDataType() || + this->InternalPData->GetNumberOfTuples() != pBuf->GetNumberOfTuples() || + this->InternalPData->GetSize() < pBuf->GetSize()) + { + if (this->InternalPData) + { + vtkCompositer::DeleteArray(this->InternalPData); + this->InternalPData = NULL; + } + if (pBuf->GetDataType() == VTK_UNSIGNED_CHAR) + { + this->InternalPData = vtkUnsignedCharArray::New(); + vtkCompositer::ResizeUnsignedCharArray( + static_cast(this->InternalPData), + numComps, pBuf->GetSize()); + } + else + { + this->InternalPData = vtkFloatArray::New(); + vtkCompositer::ResizeFloatArray( + static_cast(this->InternalPData), + numComps, pBuf->GetSize()); + } + } + // Now float array. + if (this->InternalZData == NULL || + this->InternalZData->GetSize() < zBuf->GetSize()) + { + if (this->InternalZData) + { + vtkCompositer::DeleteArray(this->InternalZData); + this->InternalZData = NULL; + } + this->InternalZData = vtkFloatArray::New(); + vtkCompositer::ResizeFloatArray( + static_cast(this->InternalZData), + 1, zBuf->GetSize()); + } + + // Compress the incoming buffers (in place operation). + this->Compress(zBuf, pBuf, zTmp, pTmp); + + // We are going to need to shuffle these around during compositing. + p1 = pTmp; + z1 = zTmp; + p2 = this->InternalPData; + z2 = this->InternalZData; + + // not a power of 2 -- need an additional level + if ( !exactLog ) + { + logProcs++; + } + +#ifdef MPIPROALLOC + vtkCommunicator::SetUseCopy(0); +#endif + for (i = 0; i < logProcs; i++) + { + if ((myId % (int)vtkTCPow2(i)) == 0) + { // Find participants + if ((myId % (int)vtkTCPow2(i+1)) < vtkTCPow2(i)) + { + // receivers + id = myId+vtkTCPow2(i); + + // only send or receive if sender or receiver id is valid + // (handles non-power of 2 cases) + if (id < numProcs) + { + this->Controller->Receive(&bufSize, 1, id, 98); + this->Controller->Receive(zBuf->GetPointer(0), bufSize, id, 99); + this->Controller->Receive(&bufSize, 1, id, 98); + if (pTmp->GetDataType() == VTK_UNSIGNED_CHAR) + { + this->Controller->Receive(reinterpret_cast + (pBuf->GetVoidPointer(0)), + bufSize, id, 99); + } + else + { + this->Controller->Receive(reinterpret_cast + (pBuf->GetVoidPointer(0)), + bufSize, id, 99); + } + + // notice the result is stored as the local data + this->CompositeImagePair(z1, p1, zBuf, pBuf, z2, p2); + // Swap the temp buffers (p3/z3 are just temporary storage). + p3 = p1; + z3 = z1; + p1 = p2; + z1 = z2; + p2 = p3; + z2 = z3; + } + } + else + { // The current data is always in buffer 1. + id = myId-vtkTCPow2(i); + if (id < numProcs) + { + bufSize = z1->GetNumberOfTuples(); + this->Controller->Send(&bufSize, 1, id, 98); + this->Controller->Send(z1->GetPointer(0), bufSize, id, 99); + bufSize = p1->GetNumberOfTuples() * numComps; + this->Controller->Send(&bufSize, 1, id, 98); + if (p1->GetDataType() == VTK_UNSIGNED_CHAR) + { + this->Controller->Send(reinterpret_cast + (p1->GetVoidPointer(0)), + bufSize, id, 99); + } + else + { + this->Controller->Send(reinterpret_cast + (p1->GetVoidPointer(0)), + bufSize, id, 99); + } + } + } + } + } + +#ifdef MPIPROALLOC + vtkCommunicator::SetUseCopy(1); +#endif + + + if (myId == 0) + { + // Now we want to decompress into the original buffers. + this->Uncompress(z1, p1, zBuf, pBuf, uncompressedLength); + } + + //this->Timer->StopTimer(); + //float time = this->Timer->GetElapsedTime(); + //cerr << "Composite " << " took " << time << " seconds.\n"; + +} + + + + +//---------------------------------------------------------------------------- +void vtkCompressCompositer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + + + diff --git a/Parallel/vtkCompressCompositer.h b/Parallel/vtkCompressCompositer.h new file mode 100644 index 0000000..0e152ae --- /dev/null +++ b/Parallel/vtkCompressCompositer.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCompressCompositer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCompressCompositer - Implements compressed tree based compositing. +// +// .SECTION Description +// vtkCompressCompositer operates in multiple processes. Each compositer has +// a render window. They use vtkMultiProcessController to communicate +// the color and depth buffer to process 0's render window. +// It will not handle transparency. Compositing is run length encoding +// of background pixels. +// +// SECTION See Also +// vtkCompositeManager. + +#ifndef __vtkCompressCompositer_h +#define __vtkCompressCompositer_h + +#include "vtkCompositer.h" + +class vtkTimerLog; +class vtkDataArray; +class vtkFloatArray; + +class VTK_PARALLEL_EXPORT vtkCompressCompositer : public vtkCompositer +{ +public: + static vtkCompressCompositer *New(); + vtkTypeRevisionMacro(vtkCompressCompositer,vtkCompositer); + void PrintSelf(ostream& os, vtkIndent indent); + + virtual void CompositeBuffer(vtkDataArray *pBuf, vtkFloatArray *zBuf, + vtkDataArray *pTmp, vtkFloatArray *zTmp); + + // Description: + // I am granting access to these methods and making them static + // So I can create a TileDisplayCompositer which uses compression. + static void Compress(vtkFloatArray *zIn, vtkDataArray *pIn, + vtkFloatArray *zOut, vtkDataArray *pOut); + + static void Uncompress(vtkFloatArray *zIn, vtkDataArray *pIn, + vtkFloatArray *zOut, vtkDataArray *pOut, + int finalLength); + + static void CompositeImagePair(vtkFloatArray *localZ, vtkDataArray *localP, + vtkFloatArray *remoteZ, vtkDataArray *remoteP, + vtkFloatArray *outZ, vtkDataArray *outP); +protected: + vtkCompressCompositer(); + ~vtkCompressCompositer(); + + + vtkDataArray *InternalPData; + vtkFloatArray *InternalZData; + + vtkTimerLog *Timer; + +private: + vtkCompressCompositer(const vtkCompressCompositer&); // Not implemented + void operator=(const vtkCompressCompositer&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkCutMaterial.cxx b/Parallel/vtkCutMaterial.cxx new file mode 100644 index 0000000..02d4189 --- /dev/null +++ b/Parallel/vtkCutMaterial.cxx @@ -0,0 +1,244 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCutMaterial.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCutMaterial.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkCutter.h" +#include "vtkMath.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkThreshold.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkCutMaterial, "$Revision: 1.18 $"); +vtkStandardNewMacro(vtkCutMaterial); + +// Instantiate object with no input and no defined output. +vtkCutMaterial::vtkCutMaterial() +{ + this->MaterialArrayName = NULL; + this->SetMaterialArrayName("material"); + this->Material = 0; + this->ArrayName = NULL; + + this->UpVector[0] = 0.0; + this->UpVector[1] = 0.0; + this->UpVector[2] = 1.0; + + this->MaximumPoint[0] = 0.0; + this->MaximumPoint[1] = 0.0; + this->MaximumPoint[2] = 0.0; + + this->CenterPoint[0] = 0.0; + this->CenterPoint[1] = 0.0; + this->CenterPoint[2] = 0.0; + + this->Normal[0] = 0.0; + this->Normal[1] = 1.0; + this->Normal[2] = 0.0; + + this->PlaneFunction = vtkPlane::New(); +} + +vtkCutMaterial::~vtkCutMaterial() +{ + this->PlaneFunction->Delete(); + this->PlaneFunction = NULL; + + this->SetMaterialArrayName(NULL); + this->SetArrayName(NULL); +} + +int vtkCutMaterial::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkThreshold *thresh; + vtkCutter *cutter; + double *bds; + + // Check to see if we have the required field arrays. + if (this->MaterialArrayName == NULL || this->ArrayName == NULL) + { + vtkErrorMacro("Material and Array names must be set."); + return 0; + } + + if (input->GetCellData()->GetArray(this->MaterialArrayName) == NULL) + { + vtkErrorMacro("Could not find cell array " << this->MaterialArrayName); + return 0; + } + if (input->GetCellData()->GetArray(this->ArrayName) == NULL) + { + vtkErrorMacro("Could not find cell array " << this->ArrayName); + return 0; + } + + // It would be nice to get rid of this in the future. + thresh = vtkThreshold::New(); + thresh->SetInput(input); + thresh->SetInputArrayToProcess(0,0,0,vtkDataObject::FIELD_ASSOCIATION_CELLS, + this->MaterialArrayName); + thresh->ThresholdBetween(this->Material-0.5, this->Material+0.5); + thresh->Update(); + + bds = thresh->GetOutput()->GetBounds(); + this->CenterPoint[0] = 0.5 * (bds[0] + bds[1]); + this->CenterPoint[1] = 0.5 * (bds[2] + bds[3]); + this->CenterPoint[2] = 0.5 * (bds[4] + bds[5]); + + this->ComputeMaximumPoint(thresh->GetOutput()); + this->ComputeNormal(); + + this->PlaneFunction->SetOrigin(this->CenterPoint); + this->PlaneFunction->SetNormal(this->Normal); + + cutter = vtkCutter::New(); + cutter->SetInput(thresh->GetOutput()); + cutter->SetCutFunction(this->PlaneFunction); + cutter->SetValue(0, 0.0); + cutter->Update(); + + output->CopyStructure(cutter->GetOutput()); + output->GetPointData()->PassData( + cutter->GetOutput()->GetPointData()); + output->GetCellData()->PassData( + cutter->GetOutput()->GetCellData()); + + cutter->Delete(); + thresh->Delete(); + + return 1; +} + +void vtkCutMaterial::ComputeNormal() +{ + double tmp[3]; + double mag; + + if (this->UpVector[0] == 0.0 && this->UpVector[1] == 0.0 && this->UpVector[2] == 0.0) + { + vtkErrorMacro("Zero magnitude UpVector."); + this->UpVector[2] = 1.0; + } + + tmp[0] = this->MaximumPoint[0] - this->CenterPoint[0]; + tmp[1] = this->MaximumPoint[1] - this->CenterPoint[1]; + tmp[2] = this->MaximumPoint[2] - this->CenterPoint[2]; + vtkMath::Cross(tmp, this->UpVector, this->Normal); + mag = vtkMath::Normalize(this->Normal); + // Rare singularity + while (mag == 0.0) + { + tmp[0] = vtkMath::Random(); + tmp[1] = vtkMath::Random(); + tmp[2] = vtkMath::Random(); + vtkMath::Cross(tmp, this->UpVector, this->Normal); + mag = vtkMath::Normalize(this->Normal); + } +} + +void vtkCutMaterial::ComputeMaximumPoint(vtkDataSet *input) +{ + vtkDataArray *data; + vtkIdType idx, bestIdx, num; + double comp, best; + vtkCell *cell; + double *bds; + + // Find the maximum value. + data = input->GetCellData()->GetArray(this->ArrayName); + if (data == NULL) + { + vtkErrorMacro("What happened to the array " << this->ArrayName); + return; + } + + num = data->GetNumberOfTuples(); + if (num <= 0) + { + vtkErrorMacro("No values in array " << this->ArrayName); + return; + } + + best = data->GetComponent(0, 0); + bestIdx = 0; + for (idx = 1; idx < num; ++idx) + { + comp = data->GetComponent(idx, 0); + if (comp > best) + { + best = comp; + bestIdx = idx; + } + } + + // Get the cell with the larges value. + cell = input->GetCell(bestIdx); + bds = cell->GetBounds(); + this->MaximumPoint[0] = (bds[0] + bds[1]) * 0.5; + this->MaximumPoint[1] = (bds[2] + bds[3]) * 0.5; + this->MaximumPoint[2] = (bds[4] + bds[5]) * 0.5; +} + +int vtkCutMaterial::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkCutMaterial::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ArrayName: "; + if ( this->ArrayName) + { + os << this->ArrayName << endl; + } + else + { + os << "(None)" << endl; + } + os << indent << "MaterialArrayName: " << this->MaterialArrayName << endl; + os << indent << "Material: " << this->Material << endl; + + os << indent << "UpVector: " << this->UpVector[0] << ", " + << this->UpVector[1] << ", " << this->UpVector[2] << endl; + + os << indent << "MaximumPoint: " << this->MaximumPoint[0] << ", " + << this->MaximumPoint[1] << ", " << this->MaximumPoint[2] << endl; + os << indent << "CenterPoint: " << this->CenterPoint[0] << ", " + << this->CenterPoint[1] << ", " << this->CenterPoint[2] << endl; + os << indent << "Normal: " << this->Normal[0] << ", " + << this->Normal[1] << ", " << this->Normal[2] << endl; +} diff --git a/Parallel/vtkCutMaterial.h b/Parallel/vtkCutMaterial.h new file mode 100644 index 0000000..c2a27af --- /dev/null +++ b/Parallel/vtkCutMaterial.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCutMaterial.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCutMaterial - Automatically computes the cut plane for a material array pair. +// .SECTION Description +// vtkCutMaterial computes a cut plane based on an up vector, center of the bounding box +// and the location of the maximum variable value. +// These computed values are available so that they can be used to set the camera +// for the best view of the plane. + + +#ifndef __vtkCutMaterial_h +#define __vtkCutMaterial_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkPlane; + +class VTK_PARALLEL_EXPORT vtkCutMaterial : public vtkPolyDataAlgorithm +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkCutMaterial,vtkPolyDataAlgorithm); + static vtkCutMaterial *New(); + + // Description: + // Cell array that contains the material values. + vtkSetStringMacro(MaterialArrayName); + vtkGetStringMacro(MaterialArrayName); + + // Description: + // Material to probe. + vtkSetMacro(Material, int); + vtkGetMacro(Material, int); + + // Description: + // For now, we just use the cell values. + // The array name to cut. + vtkSetStringMacro(ArrayName); + vtkGetStringMacro(ArrayName); + + // Description: + // The last piece of information that specifies the plane. + vtkSetVector3Macro(UpVector, double); + vtkGetVector3Macro(UpVector, double); + + // Description: + // Accesses to the values computed during the execute method. They + // could be used to get a good camera view for the resulting plane. + vtkGetVector3Macro(MaximumPoint, double); + vtkGetVector3Macro(CenterPoint, double); + vtkGetVector3Macro(Normal, double); + +protected: + vtkCutMaterial(); + ~vtkCutMaterial(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); //generate output data + virtual int FillInputPortInformation(int port, vtkInformation *info); + void ComputeMaximumPoint(vtkDataSet *input); + void ComputeNormal(); + + char *MaterialArrayName; + int Material; + char *ArrayName; + double UpVector[3]; + double MaximumPoint[3]; + double CenterPoint[3]; + double Normal[3]; + + vtkPlane *PlaneFunction; + +private: + vtkCutMaterial(const vtkCutMaterial&); // Not implemented. + void operator=(const vtkCutMaterial&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkDistributedDataFilter.cxx b/Parallel/vtkDistributedDataFilter.cxx new file mode 100644 index 0000000..e33d6d2 --- /dev/null +++ b/Parallel/vtkDistributedDataFilter.cxx @@ -0,0 +1,4559 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDistributedDataFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkDistributedDataFilter +// +// .SECTION Description +// +// .SECTION See Also + +#include "vtkToolkits.h" +#include "vtkDistributedDataFilter.h" +#include "vtkModelMetadata.h" +#include "vtkExtractCells.h" +#include "vtkMergeCells.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkObjectFactory.h" +#include "vtkPKdTree.h" +#include "vtkUnstructuredGrid.h" +#include "vtkExtractUserDefinedPiece.h" +#include "vtkCellData.h" +#include "vtkCellArray.h" +#include "vtkPointData.h" +#include "vtkIntArray.h" +#include "vtkCharArray.h" +#include "vtkFloatArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkMultiProcessController.h" +#include "vtkSocketController.h" +#include "vtkDataSetWriter.h" +#include "vtkDataSetReader.h" +#include "vtkBoxClipDataSet.h" +#include "vtkClipDataSet.h" +#include "vtkBox.h" +#include "vtkIdList.h" +#include "vtkPointLocator.h" +#include "vtkPlane.h" + +#ifdef VTK_USE_MPI +#include "vtkMPIController.h" +#endif + +vtkCxxRevisionMacro(vtkDistributedDataFilter, "$Revision: 1.28 $") + +vtkStandardNewMacro(vtkDistributedDataFilter) + +#define TEMP_ELEMENT_ID_NAME "___D3___GlobalCellIds" +#define TEMP_INSIDE_BOX_FLAG "___D3___WHERE" +#define TEMP_NODE_ID_NAME "___D3___GlobalNodeIds" + +#include +#include +#include + +class vtkDistributedDataFilterSTLCloak +{ +public: + vtkstd::map IntMap; + vtkstd::multimap IntMultiMap; +}; + +vtkDistributedDataFilter::vtkDistributedDataFilter() +{ + this->Kdtree = NULL; + + this->Controller = NULL; + this->SetController(vtkMultiProcessController::GetGlobalController()); + + this->Target = NULL; + this->Source = NULL; + + this->NumConvexSubRegions = 0; + this->ConvexSubRegionBounds = NULL; + + this->GhostLevel = 0; + + this->GlobalNodeIdArrayName = NULL; + this->GlobalElementIdArrayName = NULL; + + this->RetainKdtree = 1; + this->IncludeAllIntersectingCells = 0; + this->ClipCells = 0; + + this->Timing = 0; + + this->UseMinimalMemory = 0; +} + +vtkDistributedDataFilter::~vtkDistributedDataFilter() +{ + if (this->Kdtree) + { + this->Kdtree->Delete(); + this->Kdtree = NULL; + } + + this->SetController(NULL); + + if (this->Target) + { + delete [] this->Target; + this->Target= NULL; + } + + if (this->Source) + { + delete [] this->Source; + this->Source= NULL; + } + + if (this->ConvexSubRegionBounds) + { + delete [] this->ConvexSubRegionBounds; + this->ConvexSubRegionBounds = NULL; + } + + if (this->GlobalNodeIdArrayName) + { + delete [] this->GlobalNodeIdArrayName; + } + + if (this->GlobalElementIdArrayName) + { + delete [] this->GlobalElementIdArrayName; + } +} +//------------------------------------------------------------------------- +// Global element and node IDs: +// Either the user gives us the names of these arrays, or we find them +// in the input (using the Exodus reader names for them), or we created +// these arrays. +//------------------------------------------------------------------------- + +const char *vtkDistributedDataFilter::GetGlobalElementIdArrayName(vtkDataSet *set) +{ + //------------------------------------------------ + // list common names for global element id arrays here + // + int nnames = 1; + const char *arrayNames[1] = { + "GlobalElementId" // vtkExodusReader name + }; + //------------------------------------------------ + + // ParaView does this... we need to fix it. + if (this->GlobalElementIdArrayName && (!this->GlobalElementIdArrayName[0])) + { + delete [] this->GlobalElementIdArrayName; + this->GlobalElementIdArrayName = NULL; + } + + const char *gidArrayName = NULL; + + if (this->GlobalElementIdArrayName) + { + vtkDataArray *da = set->GetCellData()->GetArray(this->GlobalElementIdArrayName); + + if (da) + { + gidArrayName = this->GlobalElementIdArrayName; + } + else + { + this->SetGlobalElementIdArrayName(NULL); + } + } + + if (!gidArrayName) + { + // Maybe we can find a global element ID array + + for (int nameId=0; nameId < nnames; nameId++) + { + vtkDataArray *da = set->GetCellData()->GetArray(arrayNames[nameId]); + + if (da) + { + this->SetGlobalElementIdArrayName(arrayNames[nameId]); + gidArrayName = arrayNames[nameId]; + break; + } + } + } + + return gidArrayName; +} +int *vtkDistributedDataFilter::GetGlobalElementIds(vtkDataSet *set) +{ + const char *geidName = this->GetGlobalElementIdArrayName(set); + + if (!geidName) + { + return NULL; + } + + vtkDataArray *da = set->GetCellData()->GetArray(geidName); + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + + if (!ia) + { + return NULL; + } + + return ia->GetPointer(0); +} + +const char *vtkDistributedDataFilter::GetGlobalNodeIdArrayName(vtkDataSet *set) +{ + //------------------------------------------------ + // list common names for global node id arrays here + // + int nnames = 1; + const char *arrayNames[1] = { + "GlobalNodeId" // vtkExodusReader name + }; + //------------------------------------------------ + + // ParaView does this... we need to fix it. + if (this->GlobalNodeIdArrayName && (!this->GlobalNodeIdArrayName[0])) + { + delete [] this->GlobalNodeIdArrayName; + this->GlobalNodeIdArrayName = NULL; + } + + const char *gidArrayName = NULL; + + if (this->GlobalNodeIdArrayName) + { + vtkDataArray *da = set->GetPointData()->GetArray(this->GlobalNodeIdArrayName); + + if (da) + { + gidArrayName = this->GlobalNodeIdArrayName; + } + else + { + this->SetGlobalNodeIdArrayName(NULL); + } + } + + if (!gidArrayName) + { + // Maybe we can find a global node ID array + + for (int nameId=0; nameId < nnames; nameId++) + { + vtkDataArray *da = set->GetPointData()->GetArray(arrayNames[nameId]); + + if (da) + { + this->SetGlobalNodeIdArrayName(arrayNames[nameId]); + gidArrayName = arrayNames[nameId]; + break; + } + } + } + + return gidArrayName; +} +int *vtkDistributedDataFilter::GetGlobalNodeIds(vtkDataSet *set) +{ + const char *gnidName = this->GetGlobalNodeIdArrayName(set); + + if (!gnidName) + { + return NULL; + } + + vtkDataArray *da = set->GetPointData()->GetArray(gnidName); + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + + if (!ia) + { + return NULL; + } + + return ia->GetPointer(0); +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- +vtkPKdTree *vtkDistributedDataFilter::GetKdtree() +{ + if (this->Kdtree == NULL) + { + this->Kdtree = vtkPKdTree::New(); + this->Kdtree->AssignRegionsContiguous(); + this->Kdtree->SetTiming(this->GetTiming()); + } + + return this->Kdtree; +} +unsigned long vtkDistributedDataFilter::GetMTime() +{ + unsigned long t1, t2; + + t1 = this->Superclass::GetMTime(); + if (this->Kdtree == NULL) + { + return t1; + } + t2 = this->Kdtree->GetMTime(); + if (t1 > t2) + { + return t1; + } + return t2; +} + +void vtkDistributedDataFilter::SetController(vtkMultiProcessController *c) +{ + if (this->Kdtree) + { + this->Kdtree->SetController(c); + } + + if ((c == NULL) || (c->GetNumberOfProcesses() == 0)) + { + this->NumProcesses = 1; + this->MyId = 0; + } + + if (this->Controller == c) + { + return; + } + + this->Modified(); + + if (this->Controller != NULL) + { + this->Controller->UnRegister(this); + this->Controller = NULL; + } + + if (c == NULL) + { + return; + } + + this->Controller = c; + + c->Register(this); + this->NumProcesses = c->GetNumberOfProcesses(); + this->MyId = c->GetLocalProcessId(); +} + +void vtkDistributedDataFilter::SetBoundaryMode(int mode) +{ + switch (mode) + { + case vtkDistributedDataFilter::ASSIGN_TO_ONE_REGION: + this->AssignBoundaryCellsToOneRegionOn(); + break; + case vtkDistributedDataFilter::ASSIGN_TO_ALL_INTERSECTING_REGIONS: + this->AssignBoundaryCellsToAllIntersectingRegionsOn(); + break; + case vtkDistributedDataFilter::SPLIT_BOUNDARY_CELLS: + this->DivideBoundaryCellsOn(); + break; + } +} + +int vtkDistributedDataFilter::GetBoundaryMode() +{ + if (!this->IncludeAllIntersectingCells && !this->ClipCells) + { + return vtkDistributedDataFilter::ASSIGN_TO_ONE_REGION; + } + if (this->IncludeAllIntersectingCells && !this->ClipCells) + { + return vtkDistributedDataFilter::ASSIGN_TO_ALL_INTERSECTING_REGIONS; + } + if (this->IncludeAllIntersectingCells && this->ClipCells) + { + return vtkDistributedDataFilter::SPLIT_BOUNDARY_CELLS; + } + + return -1; +} + +void vtkDistributedDataFilter::AssignBoundaryCellsToOneRegionOn() +{ + this->SetAssignBoundaryCellsToOneRegion(1); +} +void vtkDistributedDataFilter::AssignBoundaryCellsToOneRegionOff() +{ + this->SetAssignBoundaryCellsToOneRegion(0); +} +void vtkDistributedDataFilter::SetAssignBoundaryCellsToOneRegion(int val) +{ + if (val) + { + this->IncludeAllIntersectingCells = 0; + this->ClipCells = 0; + } +} +void +vtkDistributedDataFilter::AssignBoundaryCellsToAllIntersectingRegionsOn() +{ + this->SetAssignBoundaryCellsToAllIntersectingRegions(1); +} +void +vtkDistributedDataFilter::AssignBoundaryCellsToAllIntersectingRegionsOff() +{ + this->SetAssignBoundaryCellsToAllIntersectingRegions(0); +} +void +vtkDistributedDataFilter::SetAssignBoundaryCellsToAllIntersectingRegions(int val) +{ + if (val) + { + this->IncludeAllIntersectingCells = 1; + this->ClipCells = 0; + } +} +void vtkDistributedDataFilter::DivideBoundaryCellsOn() +{ + this->SetDivideBoundaryCells(1); +} +void vtkDistributedDataFilter::DivideBoundaryCellsOff() +{ + this->SetDivideBoundaryCells(0); +} +void vtkDistributedDataFilter::SetDivideBoundaryCells(int val) +{ + if (val) + { + this->IncludeAllIntersectingCells = 1; + this->ClipCells = 1; + } +} +//------------------------------------------------------------------------- +// Execute +//------------------------------------------------------------------------- + +int vtkDistributedDataFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece, numPieces, ghostLevels; + + // We require preceding filters to refrain from creating ghost cells. + + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevels = 0; + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevels); + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); + + return 1; +} + +int vtkDistributedDataFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()), + 6); + outInfo->Set(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1); + + return 1; +} + +int vtkDistributedDataFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + this->GhostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + this->NextProgressStep = 0; + int progressSteps = 5 + this->GhostLevel; + if (this->ClipCells) + { + progressSteps++; + } + + this->ProgressIncrement = 1.0 / (double)progressSteps; + + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + this->SetProgressText("Begin data redistribution"); + + if (this->NumProcesses == 1) + { + this->SingleProcessExecute(input, output); + this->UpdateProgress(1.0); + return 1; + } + + // This method requires an MPI controller. + + int aok = 0; + +#ifdef VTK_USE_MPI + if (vtkMPIController::SafeDownCast(this->Controller)) + { + aok = 1; + } +#endif + + if (!aok) + { + vtkErrorMacro(<< "vtkDistributedDataFilter multiprocess requires MPI"); + return 1; + } + + // Stage (0) - If any processes have 0 cell input data sets, then + // spread the input data sets around (quickly) before formal + // redistribution. + + vtkDataSet *splitInput = this->TestFixTooFewInputFiles(input); + + if (splitInput == NULL) + { + return 1; // Fewer cells than processes - can't divide input + } + + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + this->SetProgressText("Compute spatial partitioning"); + + if (this->ClipCells && vtkDistributedDataFilter::HasMetadata(splitInput)) + { + // Clipping cells invalidates metadata that is cell based + // Here we should remove the metadata and display a warning + } + + // Stage (1) - use vtkPKdTree to... + // Create a load balanced spatial decomposition in parallel. + // Create a table assigning regions to processes. + // + // Note k-d tree will only be re-built if input or parameters + // have changed on any of the processing nodes. + + int fail = this->PartitionDataAndAssignToProcesses(splitInput); + + if (fail) + { + if (splitInput != input) + { + splitInput->Delete(); + } + vtkErrorMacro(<< "vtkDistributedDataFilter::Execute k-d tree failure"); + return 1; + } + + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + this->SetProgressText("Compute global data array bounds"); + + // Let the vtkPKdTree class compile global bounds for all + // data arrays. These can be accessed by D3 user by getting + // a handle to the vtkPKdTree object and querying it. + + this->Kdtree->CreateGlobalDataArrayBounds(); + + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + this->SetProgressText("Redistribute data"); + + // Stage (2) - Redistribute data, so that each process gets a ugrid + // containing the cells in it's assigned spatial regions. (Note + // that a side effect of merging the grids received from different + // processes is that the final grid has no duplicate points.) + // + // This call will delete splitInput if it's not this->GetInput(). + + vtkUnstructuredGrid *redistributedInput = this->RedistributeDataSet(splitInput, + input); + + if (redistributedInput == NULL) + { + this->Kdtree->Delete(); + this->Kdtree = NULL; + + vtkErrorMacro(<< "vtkDistributedDataFilter::Execute redistribute failure"); + return 1; + } + + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + + // Stage (3) - Add ghost cells to my sub grid. + + vtkUnstructuredGrid *expandedGrid = redistributedInput; + + if (this->GhostLevel > 0) + { + // Create global nodes IDs if we don't have them + + if (this->GetGlobalNodeIdArrayName(redistributedInput) == NULL) + { + this->SetProgressText("Assign global point IDs"); + int rc = this->AssignGlobalNodeIds(redistributedInput); + if (rc) + { + redistributedInput->Delete(); + this->Kdtree->Delete(); + this->Kdtree = NULL; + vtkErrorMacro(<< "vtkDistributedDataFilter::Execute global node id creation"); + return 1; + } + } + + // redistributedInput will be deleted by AcquireGhostCells + + this->SetProgressText("Exchange ghost cells"); + expandedGrid = this->AcquireGhostCells(redistributedInput); + } + + // Stage (4) - Clip cells to the spatial region boundaries + + if (this->ClipCells) + { + this->SetProgressText("Clip boundary cells"); + this->ClipGridCells(expandedGrid); + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + } + + // remove temporary arrays we created + + this->SetProgressText("Clean up and finish"); + + vtkDataArray *da = expandedGrid->GetCellData()->GetArray(TEMP_ELEMENT_ID_NAME); + + if (da) + { + expandedGrid->GetCellData()->RemoveArray(TEMP_ELEMENT_ID_NAME); + } + + da = expandedGrid->GetPointData()->GetArray(TEMP_NODE_ID_NAME); + + if (da) + { + expandedGrid->GetCellData()->RemoveArray(TEMP_NODE_ID_NAME); + } + + output->ShallowCopy(expandedGrid); + + expandedGrid->Delete(); + + if (!this->RetainKdtree) + { + this->Kdtree->Delete(); + this->Kdtree = NULL; + } + else + { + this->Kdtree->SetDataSet(NULL); + } + + this->UpdateProgress(1); + + return 1; +} +vtkUnstructuredGrid *vtkDistributedDataFilter::RedistributeDataSet( + vtkDataSet *set, vtkDataSet *input) +{ + // Create global cell ids before redistributing data. These + // will be necessary if we need ghost cells later on. + + vtkDataSet *inputPlus = set; + + if ((this->GhostLevel > 0) && (this->GetGlobalElementIdArrayName(set) == NULL)) + { + if (set == input) + { + inputPlus = set->NewInstance(); + inputPlus->ShallowCopy(set); + } + + this->AssignGlobalElementIds(inputPlus); + } + + // next call deletes inputPlus at the earliest opportunity + + vtkUnstructuredGrid *finalGrid = this->MPIRedistribute(inputPlus, input); + + return finalGrid; +} + +int vtkDistributedDataFilter::PartitionDataAndAssignToProcesses(vtkDataSet *set) +{ + if (this->Kdtree == NULL) + { + this->Kdtree = vtkPKdTree::New(); + this->Kdtree->AssignRegionsContiguous(); + this->Kdtree->SetTiming(this->GetTiming()); + } + + this->Kdtree->SetController(this->Controller); + this->Kdtree->SetNumberOfRegionsOrMore(this->NumProcesses); + this->Kdtree->SetMinCells(2); + + this->Kdtree->SetDataSet(set); + + // BuildLocator is smart enough to rebuild the k-d tree only if + // the input geometry has changed, or the k-d tree build parameters + // have changed. It will reassign regions if the region assignment + // scheme has changed. + + this->Kdtree->BuildLocator(); + + int nregions = this->Kdtree->GetNumberOfRegions(); + + if (nregions < this->NumProcesses) + { + if (nregions == 0) + { + vtkErrorMacro("Unable to build k-d tree structure"); + } + else + { + vtkErrorMacro("K-d tree must have at least one region per process"); + } + this->Kdtree->Delete(); + this->Kdtree = NULL; + return 1; + } + + return 0; +} +int vtkDistributedDataFilter::ClipGridCells(vtkUnstructuredGrid *grid) +{ + if (grid->GetNumberOfCells() == 0) + { + return 0; + } + + // Global point IDs are meaningless after + // clipping, since this tetrahedralizes the whole data set. + // We remove that array. + + const char *nodeIds = this->GetGlobalNodeIdArrayName(grid); + + if (nodeIds) + { + grid->GetPointData()->RemoveArray(nodeIds); + this->GlobalNodeIdArrayName = NULL; + } + + this->ClipCellsToSpatialRegion(grid); + + return 0; +} +vtkUnstructuredGrid * + vtkDistributedDataFilter::AcquireGhostCells(vtkUnstructuredGrid *grid) +{ + if (this->GhostLevel < 1) + { + return grid; + } + + // Create a search structure mapping global point IDs to local point IDs + + vtkIdType numPoints = grid->GetNumberOfPoints(); + + int *gnids = NULL; + + if (numPoints > 0) + { + gnids = this->GetGlobalNodeIds(grid); + + if (!gnids) + { + vtkWarningMacro(<< "Can't create ghost cells without global node IDs"); + return grid; + } + } + + vtkDistributedDataFilterSTLCloak *globalToLocalMap + = new vtkDistributedDataFilterSTLCloak; + + for (int localPtId = 0; localPtId < numPoints; localPtId++) + { + const int id = gnids[localPtId]; + globalToLocalMap->IntMap.insert(vtkstd::pair(id, localPtId)); + } + + vtkUnstructuredGrid *expandedGrid= NULL; + + if (this->IncludeAllIntersectingCells) + { + expandedGrid = + this->AddGhostCellsDuplicateCellAssignment(grid, globalToLocalMap); + } + else + { + expandedGrid = + this->AddGhostCellsUniqueCellAssignment(grid, globalToLocalMap); + } + + return expandedGrid; +} +void vtkDistributedDataFilter::SingleProcessExecute(vtkDataSet *input, + vtkUnstructuredGrid *output) +{ + vtkDebugMacro(<< "vtkDistributedDataFilter::SingleProcessExecute()"); + + // we run the input through vtkMergeCells which will remove + // duplicate points + + vtkDataSet* tmp = input->NewInstance(); + tmp->ShallowCopy(input); + + float tolerance = 0.0; + + if (this->RetainKdtree) + { + if (this->Kdtree == NULL) + { + this->Kdtree = vtkPKdTree::New(); + this->Kdtree->SetTiming(this->GetTiming()); + } + + this->Kdtree->SetDataSet(tmp); + this->Kdtree->BuildLocator(); + tolerance = (float)this->Kdtree->GetFudgeFactor(); + this->Kdtree->CreateGlobalDataArrayBounds(); + } + else if (this->Kdtree) + { + this->Kdtree->Delete(); + this->Kdtree = NULL; + } + + vtkUnstructuredGrid *clean = + vtkDistributedDataFilter::MergeGrids(&tmp, 1, DeleteYes, + this->GetGlobalNodeIdArrayName(input), tolerance, NULL); + + output->ShallowCopy(clean); + clean->Delete(); + + if (this->GhostLevel > 0) + { + // Add the vtkGhostLevels arrays. We have the whole + // data set, so all cells are level 0. + + vtkDistributedDataFilter::AddConstantUnsignedCharPointArray( + output, "vtkGhostLevels", 0); + vtkDistributedDataFilter::AddConstantUnsignedCharCellArray( + output, "vtkGhostLevels", 0); + } +} +void vtkDistributedDataFilter::ComputeMyRegionBounds() +{ + vtkIntArray *myRegions = vtkIntArray::New(); + + this->Kdtree->GetRegionAssignmentList(this->MyId, myRegions); + + if (myRegions->GetNumberOfTuples() > 0) + { + this->NumConvexSubRegions = + this->Kdtree->MinimalNumberOfConvexSubRegions( + myRegions, &this->ConvexSubRegionBounds); + } + else + { + this->NumConvexSubRegions = 0; + if (this->ConvexSubRegionBounds) + { + delete [] this->ConvexSubRegionBounds; + this->ConvexSubRegionBounds = NULL; + } + } + + myRegions->Delete(); +} +int vtkDistributedDataFilter::CheckFieldArrayTypes(vtkDataSet *set) +{ + int i; + + // problem - vtkIdType arrays are written out as int arrays + // when marshalled with vtkDataWriter. This is a problem + // when receive the array and try to merge it with our own, + // which is a vtkIdType + + vtkPointData *pd = set->GetPointData(); + vtkCellData *cd = set->GetCellData(); + + int npointArrays = pd->GetNumberOfArrays(); + + for (i=0; iGetArray(i)->GetDataType(); + + if (arrayType == VTK_ID_TYPE) + { + return 1; + } + } + + int ncellArrays = cd->GetNumberOfArrays(); + + for (i=0; iGetArray(i)->GetDataType(); + + if (arrayType == VTK_ID_TYPE) + { + return 1; + } + } + + return 0; +} +//------------------------------------------------------------------------- +// Quickly spread input data around if there are more processes than +// input data sets. +//------------------------------------------------------------------------- +extern "C" +{ + int vtkDistributedDataFilterSortSize(const void *s1, const void *s2) + { + struct _procInfo{ int had; int procId; int has; } *a, *b; + + a = (struct _procInfo *)s1; + b = (struct _procInfo *)s2; + + if (a->has < b->has) + { + return 1; + } + else if (a->has == b->has) + { + return 0; + } + else + { + return -1; + } + } +} +vtkDataSet *vtkDistributedDataFilter::TestFixTooFewInputFiles(vtkDataSet *input) +{ + int i, proc; + int me = this->MyId; + int nprocs = this->NumProcesses; + + int numMyCells = input->GetNumberOfCells(); + + // Find out how many input cells each process has. + + vtkIntArray *inputSize = this->ExchangeCounts(numMyCells, 0x0001); + int *sizes = inputSize->GetPointer(0); + + int *nodeType = new int [nprocs]; + const int Producer = 1; + const int Consumer = 2; + int numConsumers = 0; + int numTotalCells = 0; + + for (proc = 0; proc < nprocs ; proc++) + { + numTotalCells += sizes[proc]; + if (sizes[proc] == 0) + { + numConsumers++; + nodeType[proc] = Consumer; + } + else + { + nodeType[proc] = Producer; + } + } + + if (numConsumers == 0) + { + // Nothing to do. Every process has input data. + + delete [] nodeType; + inputSize->Delete(); + return input; + } + + if (numTotalCells < nprocs) + { + vtkErrorMacro(<< "D3 - fewer cells than processes"); + delete [] nodeType; + inputSize->Delete(); + return NULL; + } + + int cellsPerNode = numTotalCells / nprocs; + + vtkIdList **sendCells = new vtkIdList * [ nprocs ]; + memset(sendCells, 0, sizeof(vtkIdList *) * nprocs); + + if (numConsumers == nprocs - 1) + { + // Simple and common case. + // Only one process has data and divides it among the rest. + + inputSize->Delete(); + + if (nodeType[me] == Producer) + { + int sizeLast = numTotalCells - ((nprocs-1) * cellsPerNode); + vtkIdType cellId = 0; + + for (proc=0; procSetNumberOfIds(ncells); + + for (i=0; iSetId(i, cellId++); + } + } + } + } + else + { + // The processes with data send it to processes without data. + // This is not the most balanced decomposition, and it is not the + // fastest. It is somewhere inbetween. + + int minCells = (int)(.8 * cellsPerNode); + + struct _procInfo{ int had; int procId; int has; }; + + struct _procInfo *procInfo = new struct _procInfo [nprocs]; + + for (proc = 0; proc < nprocs ; proc++) + { + procInfo[proc].had = inputSize->GetValue(proc); + procInfo[proc].procId = proc; + procInfo[proc].has = inputSize->GetValue(proc); + } + + inputSize->Delete(); + + qsort(procInfo, nprocs, sizeof(struct _procInfo), + vtkDistributedDataFilterSortSize); + + struct _procInfo *nextProducer = procInfo; + struct _procInfo *nextConsumer = procInfo + (nprocs - 1); + + int numTransferCells = 0; + + int sanityCheck=0; + int nprocsSquared = nprocs * nprocs; + + while (sanityCheck++ < nprocsSquared) + { + int c = nextConsumer->procId; + + if (nodeType[c] == Producer) + { + break; + } + + int cGetMin = minCells - nextConsumer->has; + + if (cGetMin < 1) + { + nextConsumer--; + continue; + } + int cGetMax = cellsPerNode - nextConsumer->has; + + int p = nextProducer->procId; + + int pSendMax = nextProducer->has - minCells; + + if (pSendMax < 1) + { + nextProducer++; + continue; + } + + int transferSize = (pSendMax < cGetMax) ? pSendMax : cGetMax; + + if (me == p) + { + vtkIdType startCellId = nextProducer->had - nextProducer->has; + sendCells[c] = vtkIdList::New(); + sendCells[c]->SetNumberOfIds(transferSize); + for (i=0; iSetId(i, startCellId++); + } + + numTransferCells += transferSize; + } + + nextProducer->has -= transferSize; + nextConsumer->has += transferSize; + + continue; + } + + delete [] procInfo; + + if (sanityCheck > nprocsSquared) + { + vtkErrorMacro(<< "TestFixTooFewInputFiles error"); + for (i=0; iDelete(); + } + } + delete [] sendCells; + delete [] nodeType; + sendCells = NULL; + } + else if (nodeType[me] == Producer) + { + int keepCells = numMyCells - numTransferCells; + vtkIdType startCellId = (vtkIdType)numTransferCells; + sendCells[me] = vtkIdList::New(); + sendCells[me]->SetNumberOfIds(keepCells); + for (i=0; iSetId(i, startCellId++); + } + } + } + + vtkUnstructuredGrid *newGrid = NULL; + + if (sendCells) + { + newGrid = this->ExchangeMergeSubGrids( + sendCells, DeleteYes, input, DeleteNo, + DuplicateCellsNo, GhostCellsNo, 0x0011); + + delete [] sendCells; + delete [] nodeType; + } + + return newGrid; +} +//------------------------------------------------------------------------- +// Communication routines - two versions: +// *Lean version use minimal memory +// *Fast versions use more memory, but are much faster +//------------------------------------------------------------------------- + +void vtkDistributedDataFilter::SetUpPairWiseExchange() +{ + int iam = this->MyId; + int nprocs = this->NumProcesses; + + if (this->Target) + { + delete [] this->Target; + this->Target = NULL; + } + + if (this->Source) + { + delete [] this->Source; + this->Source = NULL; + } + + if (nprocs == 1) + { + return; + } + + this->Target = new int [nprocs - 1]; + this->Source = new int [nprocs - 1]; + + for (int i=1; i< nprocs; i++) + { + this->Target[i-1] = (iam + i) % nprocs; + this->Source[i-1] = (iam + nprocs - i) % nprocs; + } +} +void vtkDistributedDataFilter::FreeIntArrays(vtkIntArray **ar) +{ + for (int i=0; iNumProcesses; i++) + { + if (ar[i]) + { + ar[i]->Delete(); + } + } + + delete [] ar; +} +void vtkDistributedDataFilter::FreeIdLists(vtkIdList**lists, int nlists) +{ + for (int i=0; iDelete(); + lists[i] = NULL; + } + } +} +vtkIdType vtkDistributedDataFilter::GetIdListSize(vtkIdList **lists, int nlists) +{ + vtkIdType numCells = 0; + + for (int i=0; iGetNumberOfIds(); + } + } + + return numCells; +} +vtkUnstructuredGrid * + vtkDistributedDataFilter::ExchangeMergeSubGrids( + vtkIdList **cellIds, int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, int ghostCellFlag, + int tag) +{ + int nprocs = this->NumProcesses; + + int *numLists = new int [nprocs]; + + vtkIdList ***listOfLists = new vtkIdList ** [nprocs]; + + for (int i=0; iUseMinimalMemory) + { + grid = this->ExchangeMergeSubGridsLean(listOfLists, numLists, deleteCellIds, + myGrid, deleteMyGrid, filterOutDuplicateCells, ghostCellFlag, tag); + } + else + { + grid = this->ExchangeMergeSubGridsFast(listOfLists, numLists, deleteCellIds, + myGrid, deleteMyGrid, filterOutDuplicateCells, ghostCellFlag, tag); + } + + delete [] numLists; + delete [] listOfLists; + + return grid; +} +vtkUnstructuredGrid * + vtkDistributedDataFilter::ExchangeMergeSubGrids( + vtkIdList ***cellIds, int *numLists, int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, int ghostCellFlag, + int tag) +{ + vtkUnstructuredGrid *grid = NULL; + + if (this->UseMinimalMemory) + { + grid = this->ExchangeMergeSubGridsLean(cellIds, numLists, deleteCellIds, + myGrid, deleteMyGrid, filterOutDuplicateCells, ghostCellFlag, tag); + } + else + { + grid = this->ExchangeMergeSubGridsFast(cellIds, numLists, deleteCellIds, + myGrid, deleteMyGrid, filterOutDuplicateCells, ghostCellFlag, tag); + } + return grid; +} +vtkIntArray *vtkDistributedDataFilter::ExchangeCounts(int myCount, int tag) +{ + vtkIntArray *ia; + + if (this->UseMinimalMemory) + { + ia = this->ExchangeCountsLean(myCount, tag); + } + else + { + ia = this->ExchangeCountsFast(myCount, tag); + } + return ia; +} +vtkFloatArray **vtkDistributedDataFilter:: + ExchangeFloatArrays(vtkFloatArray **myArray, int deleteSendArrays, int tag) +{ + vtkFloatArray **fa; + + if (this->UseMinimalMemory) + { + fa = this->ExchangeFloatArraysLean(myArray, deleteSendArrays, tag); + } + else + { + fa = this->ExchangeFloatArraysFast(myArray, deleteSendArrays, tag); + } + return fa; +} +vtkIntArray **vtkDistributedDataFilter:: + ExchangeIntArrays(vtkIntArray **myArray, int deleteSendArrays, int tag) +{ + vtkIntArray **ia; + + if (this->UseMinimalMemory) + { + ia = this->ExchangeIntArraysLean(myArray, deleteSendArrays, tag); + } + else + { + ia = this->ExchangeIntArraysFast(myArray, deleteSendArrays, tag); + } + return ia; +} +// ----------------------- Lean versions ----------------------------// +vtkIntArray *vtkDistributedDataFilter::ExchangeCountsLean(int myCount, int tag) +{ + vtkIntArray *countArray = NULL; + +#ifdef VTK_USE_MPI + int i; + int nprocs = this->NumProcesses; + + vtkMPICommunicator::Request req; + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + + int *counts = new int [nprocs]; + counts[this->MyId] = myCount; + + if (!this->Source) + { + this->SetUpPairWiseExchange(); + } + + for (i = 0; i < this->NumProcesses - 1; i++) + { + int source = this->Source[i]; + int target = this->Target[i]; + mpiContr->NoBlockReceive(counts + source, 1, source, tag, req); + mpiContr->Send(&myCount, 1, target, tag); + req.Wait(); + } + + countArray = vtkIntArray::New(); + countArray->SetArray(counts, nprocs, 0); + +#else + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeCounts requires MPI"); + (void)myCount; + (void)tag; +#endif + + return countArray; +} +vtkFloatArray ** + vtkDistributedDataFilter::ExchangeFloatArraysLean(vtkFloatArray **myArray, + int deleteSendArrays, int tag) +{ + vtkFloatArray **remoteArrays = NULL; + +#ifdef VTK_USE_MPI + int i; + int nprocs = this->NumProcesses; + int me = this->MyId; + + vtkMPICommunicator::Request req; + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + + int *recvSize = new int [nprocs]; + int *sendSize = new int [nprocs]; + + if (!this->Source) + { + this->SetUpPairWiseExchange(); + } + + for (i= 0; i< nprocs; i++) + { + sendSize[i] = myArray[i] ? myArray[i]->GetNumberOfTuples() : 0; + recvSize[i] = 0; + } + + // Exchange sizes + + int nothers = nprocs - 1; + + for (i = 0; i < nothers; i++) + { + int source = this->Source[i]; + int target = this->Target[i]; + mpiContr->NoBlockReceive(recvSize + source, 1, source, tag, req); + mpiContr->Send(sendSize + target, 1, target, tag); + req.Wait(); + } + + // Exchange int arrays + + float **recvArrays = new float * [nprocs]; + memset(recvArrays, 0, sizeof(float *) * nprocs); + + if (sendSize[me] > 0) // sent myself an array + { + recvSize[me] = sendSize[me]; + recvArrays[me] = new float [sendSize[me]]; + memcpy(recvArrays[me], myArray[me]->GetPointer(0), sendSize[me] * sizeof(float)); + } + + for (i = 0; i < nothers; i++) + { + int source = this->Source[i]; + int target = this->Target[i]; + recvArrays[source] = NULL; + + if (recvSize[source] > 0) + { + recvArrays[source] = new float [recvSize[source]]; + if (recvArrays[source] == NULL) + { + vtkErrorMacro(<< + "vtkDistributedDataFilter::ExchangeIntArrays memory allocation"); + return NULL; + } + mpiContr->NoBlockReceive(recvArrays[source], recvSize[source], source, tag, req); + } + + if (sendSize[target] > 0) + { + mpiContr->Send(myArray[target]->GetPointer(0), sendSize[target], target, tag); + } + + if (myArray[target] && deleteSendArrays) + { + myArray[target]->Delete(); + } + + if (recvSize[source] > 0) + { + req.Wait(); + } + } + + if (deleteSendArrays) + { + if (myArray[me]) + { + myArray[me]->Delete(); + } + delete [] myArray; + } + + delete [] sendSize; + + remoteArrays = new vtkFloatArray * [nprocs]; + + for (i=0; i 0) + { + remoteArrays[i] = vtkFloatArray::New(); + remoteArrays[i]->SetArray(recvArrays[i], recvSize[i], 0); + } + else + { + remoteArrays[i] = NULL; + } + } + + delete [] recvArrays; + delete [] recvSize; + +#else + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeFloatArrays requires MPI"); + (void)myArray; + (void)deleteSendArrays; + (void)tag; +#endif + + return remoteArrays; +} +vtkIntArray ** + vtkDistributedDataFilter::ExchangeIntArraysLean(vtkIntArray **myArray, + int deleteSendArrays, int tag) +{ + vtkIntArray **remoteArrays = NULL; + +#ifdef VTK_USE_MPI + int i; + int nprocs = this->NumProcesses; + int me = this->MyId; + + vtkMPICommunicator::Request req; + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + + int *recvSize = new int [nprocs]; + int *sendSize = new int [nprocs]; + + if (!this->Source) + { + this->SetUpPairWiseExchange(); + } + + for (i= 0; i< nprocs; i++) + { + sendSize[i] = myArray[i] ? myArray[i]->GetNumberOfTuples() : 0; + recvSize[i] = 0; + } + + // Exchange sizes + + int nothers = nprocs - 1; + + for (i = 0; i < nothers; i++) + { + int source = this->Source[i]; + int target = this->Target[i]; + mpiContr->NoBlockReceive(recvSize + source, 1, source, tag, req); + mpiContr->Send(sendSize + target, 1, target, tag); + req.Wait(); + } + + // Exchange int arrays + + int **recvArrays = new int * [nprocs]; + memset(recvArrays, 0, sizeof(int *) * nprocs); + + if (sendSize[me] > 0) // sent myself an array + { + recvSize[me] = sendSize[me]; + recvArrays[me] = new int [sendSize[me]]; + memcpy(recvArrays[me], myArray[me]->GetPointer(0), sendSize[me] * sizeof(int)); + } + + for (i = 0; i < nothers; i++) + { + int source = this->Source[i]; + int target = this->Target[i]; + recvArrays[source] = NULL; + + if (recvSize[source] > 0) + { + recvArrays[source] = new int [recvSize[source]]; + if (recvArrays[source] == NULL) + { + vtkErrorMacro(<< + "vtkDistributedDataFilter::ExchangeIntArrays memory allocation"); + return NULL; + } + mpiContr->NoBlockReceive(recvArrays[source], recvSize[source], source, tag, req); + } + + if (sendSize[target] > 0) + { + mpiContr->Send(myArray[target]->GetPointer(0), sendSize[target], target, tag); + } + + if (myArray[target] && deleteSendArrays) + { + myArray[target]->Delete(); + } + + if (recvSize[source] > 0) + { + req.Wait(); + } + } + + if (deleteSendArrays) + { + if (myArray[me]) + { + myArray[me]->Delete(); + } + delete [] myArray; + } + + delete [] sendSize; + + remoteArrays = new vtkIntArray * [nprocs]; + + for (i=0; i 0) + { + remoteArrays[i] = vtkIntArray::New(); + remoteArrays[i]->SetArray(recvArrays[i], recvSize[i], 0); + } + else + { + remoteArrays[i] = NULL; + } + } + + delete [] recvArrays; + delete [] recvSize; + +#else + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeIntArrays requires MPI"); + (void)myArray; + (void)deleteSendArrays; + (void)tag; +#endif + + return remoteArrays; +} +vtkUnstructuredGrid * + vtkDistributedDataFilter::ExchangeMergeSubGridsLean( + vtkIdList ***cellIds, int *numLists, int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, // flag if different processes may send same cells + int ghostCellFlag, // flag if these cells are ghost cells + int tag) +{ + vtkUnstructuredGrid *mergedGrid = NULL; +#ifdef VTK_USE_MPI + int i; + int packedGridSendSize=0, packedGridRecvSize=0; + char *packedGridSend=NULL, *packedGridRecv=NULL; + int recvBufSize=0; + int numReceivedGrids = 0; + + int nprocs = this->NumProcesses; + int iam = this->MyId; + + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + vtkMPICommunicator::Request req; + + vtkDataSet *tmpGrid = myGrid->NewInstance(); + tmpGrid->ShallowCopy(myGrid); + + vtkModelMetadata *mmd = NULL; + + if (vtkDistributedDataFilter::HasMetadata(myGrid) && !ghostCellFlag) + { + // Pull metadata out of grid + + mmd = vtkModelMetadata::New(); + mmd->Unpack(tmpGrid, DeleteYes); + } + + vtkDataSet **grids = new vtkDataSet * [nprocs]; + + if (numLists[iam] > 0) + { + // I was extracting/packing/sending/unpacking ugrids of zero cells, + // and this caused corrupted data structures. I don't know why, but + // I am now being careful not to do that. + + vtkIdType numCells = + vtkDistributedDataFilter::GetIdListSize(cellIds[iam], numLists[iam]); + + if (numCells > 0) + { + grids[numReceivedGrids++] = + this->ExtractCells(cellIds[iam], numLists[iam], deleteCellIds, tmpGrid, mmd); + } + else if (deleteCellIds) + { + vtkDistributedDataFilter::FreeIdLists(cellIds[iam], numLists[iam]); + } + } + + if (this->Source == NULL) + { + this->SetUpPairWiseExchange(); + } + + int nothers = nprocs - 1; + + for (i=0; iTarget[i]; + int source = this->Source[i]; + + packedGridSendSize = 0; + + if (cellIds[target] && (numLists[target] > 0)) + { + vtkIdType numCells = vtkDistributedDataFilter::GetIdListSize( + cellIds[target], numLists[target]); + + if (numCells > 0) + { + vtkUnstructuredGrid *sendGrid = + this->ExtractCells(cellIds[target], numLists[target], + deleteCellIds, tmpGrid, mmd); + + packedGridSend = this->MarshallDataSet(sendGrid, packedGridSendSize); + sendGrid->Delete(); + } + else if (deleteCellIds) + { + vtkDistributedDataFilter::FreeIdLists(cellIds[target], numLists[target]); + } + } + + // exchange size of packed grids + + mpiContr->NoBlockReceive(&packedGridRecvSize, 1, source, tag, req); + mpiContr->Send(&packedGridSendSize, 1, target, tag); + req.Wait(); + + if (packedGridRecvSize > recvBufSize) + { + if (packedGridRecv) + { + delete [] packedGridRecv; + } + packedGridRecv = new char [packedGridRecvSize]; + if (!packedGridRecv) + { + vtkErrorMacro(<< + "vtkDistributedDataFilter::ExchangeMergeSubGrids memory allocation"); + return NULL; + } + recvBufSize = packedGridRecvSize; + } + + if (packedGridRecvSize > 0) + { + mpiContr->NoBlockReceive(packedGridRecv, packedGridRecvSize, source, tag, req); + } + + if (packedGridSendSize > 0) + { + mpiContr->Send(packedGridSend, packedGridSendSize, target, tag); + delete [] packedGridSend; + } + + if (packedGridRecvSize > 0) + { + req.Wait(); + + grids[numReceivedGrids++] = + this->UnMarshallDataSet(packedGridRecv, packedGridRecvSize); + } + } + + tmpGrid->Delete(); + + if (recvBufSize > 0) + { + delete [] packedGridRecv; + packedGridRecv = NULL; + } + + if (numReceivedGrids > 1) + { + // Merge received grids + + const char *globalNodeIds = this->GetGlobalNodeIdArrayName(myGrid); + const char *globalElementIds = NULL; + + if (filterOutDuplicateCells) + { + globalElementIds = this->GetGlobalElementIdArrayName(myGrid); + } + + // this call will merge the grids and then delete them + + float tolerance = 0.0; + + if (this->Kdtree) + { + tolerance = (float)this->Kdtree->GetFudgeFactor(); + } + + mergedGrid = + vtkDistributedDataFilter::MergeGrids(grids, numReceivedGrids, DeleteYes, + globalNodeIds, tolerance, globalElementIds); + + } + else if (numReceivedGrids == 1) + { + mergedGrid = vtkUnstructuredGrid::SafeDownCast(grids[0]); + } + else + { + mergedGrid = this->ExtractZeroCellGrid(myGrid, mmd); + } + + if (mmd) + { + mmd->Delete(); + } + + if (deleteMyGrid) + { + myGrid->Delete(); + } + + delete [] grids; + +#else + (void)cellIds; // This is just here for successful compilation, + (void)numLists; // it will never execute. If !VTK_USE_MPI, we + (void)deleteCellIds; // never get this far. + (void)myGrid; + (void)deleteMyGrid; + (void)filterOutDuplicateCells; + (void)tag; + (void)ghostCellFlag; + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeMergeSubGrids requires MPI"); +#endif + + return mergedGrid; +} +// ----------------------- Fast versions ----------------------------// +vtkIntArray *vtkDistributedDataFilter::ExchangeCountsFast(int myCount, int tag) +{ + vtkIntArray *countArray = NULL; + +#ifdef VTK_USE_MPI + int i; + int nprocs = this->NumProcesses; + int me = this->MyId; + + vtkMPICommunicator::Request *req = new vtkMPICommunicator::Request [nprocs]; + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + + int *counts = new int [nprocs]; + counts[me] = myCount; + + for (i = 0; i < nprocs; i++) + { + if (i == me) + { + continue; + } + mpiContr->NoBlockReceive(counts + i, 1, i, tag, req[i]); + } + + mpiContr->Barrier(); + + for (i = 0; i < nprocs; i++) + { + if (i == me) + { + continue; + } + mpiContr->Send(&myCount, 1, i, tag); + } + + countArray = vtkIntArray::New(); + countArray->SetArray(counts, nprocs, 0); + + for (i = 0; i < nprocs; i++) + { + if (i == me) + { + continue; + } + req[i].Wait(); + } + + delete [] req; + +#else + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeCounts requires MPI"); + (void)myCount; + (void)tag; +#endif + + return countArray; +} +vtkFloatArray ** + vtkDistributedDataFilter::ExchangeFloatArraysFast(vtkFloatArray **myArray, + int deleteSendArrays, int tag) +{ + vtkFloatArray **fa = NULL; +#ifdef VTK_USE_MPI + int proc; + int nprocs = this->NumProcesses; + int iam = this->MyId; + + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + + int *sendSize = new int [nprocs]; + int *recvSize = new int [nprocs]; + + for (proc=0; proc < nprocs; proc++) + { + recvSize[proc] = sendSize[proc] = 0; + + if (proc == iam) + { + continue; + } + + if (myArray[proc]) + { + sendSize[proc] = myArray[proc]->GetNumberOfTuples(); + } + } + + // Exchange sizes of arrays to send and receive + + vtkMPICommunicator::Request *reqBuf = new vtkMPICommunicator::Request [nprocs]; + + for (proc=0; procNoBlockReceive(recvSize + proc, 1, proc, tag, reqBuf[proc]); + } + + mpiContr->Barrier(); + + for (proc=0; procSend(sendSize + proc, 1, proc, tag); + } + + for (proc=0; proc 0) + { + recvBufs[proc] = new float [recvSize[proc]]; + mpiContr->NoBlockReceive(recvBufs[proc], recvSize[proc], proc, tag, reqBuf[proc]); + } + else + { + recvBufs[proc] = NULL; + } + } + + mpiContr->Barrier(); + + // Send all arrays + + for (proc=0; proc < nprocs; proc++) + { + if (sendSize[proc] > 0) + { + mpiContr->Send(myArray[proc]->GetPointer(0), sendSize[proc], proc, tag); + } + } + delete [] sendSize; + + // If I want to send an array to myself, place it in output now + + if (myArray[iam]) + { + recvSize[iam] = myArray[iam]->GetNumberOfTuples(); + if (recvSize[iam] > 0) + { + recvBufs[iam] = new float [recvSize[iam]]; + memcpy(recvBufs[iam], myArray[iam]->GetPointer(0), recvSize[iam] * sizeof(float)); + } + } + + if (deleteSendArrays) + { + for (proc=0; proc < nprocs; proc++) + { + if (myArray[proc]) + { + myArray[proc]->Delete(); + } + } + delete [] myArray; + } + + // Await incoming arrays + + fa = new vtkFloatArray * [nprocs]; + for (proc=0; proc < nprocs; proc++) + { + if (recvBufs[proc]) + { + fa[proc] = vtkFloatArray::New(); + fa[proc]->SetArray(recvBufs[proc], recvSize[proc], 0); + } + else + { + fa[proc] = NULL; + } + } + + delete [] recvSize; + + for (proc=0; proc < nprocs; proc++) + { + if (proc == iam) + { + continue; + } + if (recvBufs[proc]) + { + reqBuf[proc].Wait(); + } + } + + delete [] reqBuf; + delete [] recvBufs; + +#else + (void)myArray; + (void)deleteSendArrays; + (void)tag; + + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeFloatArrays requires MPI"); +#endif + + return fa; +} +vtkIntArray ** + vtkDistributedDataFilter::ExchangeIntArraysFast(vtkIntArray **myArray, + int deleteSendArrays, int tag) +{ + vtkIntArray **ia = NULL; +#ifdef VTK_USE_MPI + int proc; + int nprocs = this->NumProcesses; + int iam = this->MyId; + + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + + int *sendSize = new int [nprocs]; + int *recvSize = new int [nprocs]; + + for (proc=0; proc < nprocs; proc++) + { + recvSize[proc] = sendSize[proc] = 0; + + if (proc == iam) + { + continue; + } + + if (myArray[proc]) + { + sendSize[proc] = myArray[proc]->GetNumberOfTuples(); + } + } + + // Exchange sizes of arrays to send and receive + + vtkMPICommunicator::Request *reqBuf = new vtkMPICommunicator::Request [nprocs]; + + for (proc=0; procNoBlockReceive(recvSize + proc, 1, proc, tag, reqBuf[proc]); + } + + mpiContr->Barrier(); + + for (proc=0; procSend(sendSize + proc, 1, proc, tag); + } + + for (proc=0; proc 0) + { + recvBufs[proc] = new int [recvSize[proc]]; + mpiContr->NoBlockReceive(recvBufs[proc], recvSize[proc], proc, tag, reqBuf[proc]); + } + else + { + recvBufs[proc] = NULL; + } + } + + mpiContr->Barrier(); + + // Send all arrays + + for (proc=0; proc < nprocs; proc++) + { + if (sendSize[proc] > 0) + { + mpiContr->Send(myArray[proc]->GetPointer(0), sendSize[proc], proc, tag); + } + } + delete [] sendSize; + + // If I want to send an array to myself, place it in output now + + if (myArray[iam]) + { + recvSize[iam] = myArray[iam]->GetNumberOfTuples(); + if (recvSize[iam] > 0) + { + recvBufs[iam] = new int [recvSize[iam]]; + memcpy(recvBufs[iam], myArray[iam]->GetPointer(0), recvSize[iam] * sizeof(int)); + } + } + + if (deleteSendArrays) + { + for (proc=0; proc < nprocs; proc++) + { + if (myArray[proc]) + { + myArray[proc]->Delete(); + } + } + delete [] myArray; + } + + // Await incoming arrays + + ia = new vtkIntArray * [nprocs]; + for (proc=0; proc < nprocs; proc++) + { + if (recvBufs[proc]) + { + ia[proc] = vtkIntArray::New(); + ia[proc]->SetArray(recvBufs[proc], recvSize[proc], 0); + } + else + { + ia[proc] = NULL; + } + } + + delete [] recvSize; + + for (proc=0; proc < nprocs; proc++) + { + if (proc == iam) + { + continue; + } + if (recvBufs[proc]) + { + reqBuf[proc].Wait(); + } + } + + delete [] reqBuf; + delete [] recvBufs; + +#else + (void)myArray; + (void)deleteSendArrays; + (void)tag; + + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeIntArrays requires MPI"); +#endif + + return ia; +} +vtkUnstructuredGrid * + vtkDistributedDataFilter::ExchangeMergeSubGridsFast( + vtkIdList ***cellIds, int *numLists, int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, // flag if different processes may send same cells + int ghostCellFlag, // flag if these are ghost cells + int tag) +{ + vtkUnstructuredGrid *mergedGrid = NULL; +#ifdef VTK_USE_MPI + int proc; + int nprocs = this->NumProcesses; + int iam = this->MyId; + + vtkMPIController *mpiContr = vtkMPIController::SafeDownCast(this->Controller); + + vtkUnstructuredGrid **grids = new vtkUnstructuredGrid * [nprocs]; + char **sendBufs = new char * [nprocs]; + char **recvBufs = new char * [nprocs]; + int *sendSize = new int [nprocs]; + int *recvSize = new int [nprocs]; + + // create & pack all sub grids + + vtkDataSet *tmpGrid = myGrid->NewInstance(); + tmpGrid->ShallowCopy(myGrid); + + vtkModelMetadata *mmd = NULL; + + if (vtkDistributedDataFilter::HasMetadata(tmpGrid) && !ghostCellFlag) + { + // Pull metadata out of grid + + mmd = vtkModelMetadata::New(); + mmd->Unpack(tmpGrid, DeleteYes); + } + + for (proc=0; proc < nprocs; proc++) + { + recvSize[proc] = sendSize[proc] = 0; + grids[proc] = NULL; + sendBufs[proc] = recvBufs[proc] = NULL; + + if (numLists[proc] > 0) + { + vtkIdType numCells = + vtkDistributedDataFilter::GetIdListSize(cellIds[proc], numLists[proc]); + + if (numCells > 0) + { + grids[proc] = + vtkDistributedDataFilter::ExtractCells(cellIds[proc], numLists[proc], + deleteCellIds, tmpGrid, mmd); + + if (proc != iam) + { + sendBufs[proc] = this->MarshallDataSet(grids[proc], sendSize[proc]); + grids[proc]->Delete(); + grids[proc] = NULL; + } + } + else if (deleteCellIds) + { + vtkDistributedDataFilter::FreeIdLists(cellIds[proc], numLists[proc]); + } + } + } + + tmpGrid->Delete(); + + // Exchange sizes of grids to send and receive + + vtkMPICommunicator::Request *reqBuf = new vtkMPICommunicator::Request [nprocs]; + + for (proc=0; procNoBlockReceive(recvSize + proc, 1, proc, tag, reqBuf[proc]); + } + + mpiContr->Barrier(); + + for (proc=0; procSend(sendSize + proc, 1, proc, tag); + } + + for (proc=0; proc 0) + { + recvBufs[proc] = new char [recvSize[proc]]; + mpiContr->NoBlockReceive(recvBufs[proc], recvSize[proc], proc, tag, reqBuf[proc]); + numReceives++; + } + } + + mpiContr->Barrier(); + + // Send all sub grids, then delete them + + for (proc=0; proc < nprocs; proc++) + { + if (sendSize[proc] > 0) + { + mpiContr->Send(sendBufs[proc], sendSize[proc], proc, tag); + } + } + + for (proc=0; proc < nprocs; proc++) + { + if (sendSize[proc] > 0) + { + delete [] sendBufs[proc]; + } + } + + delete [] sendSize; + delete [] sendBufs; + + // Await incoming sub grids, unpack them + + while (numReceives > 0) + { + for (proc=0; proc < nprocs; proc++) + { + if (recvBufs[proc] && (reqBuf[proc].Test() == 1)) + { + grids[proc] = this->UnMarshallDataSet(recvBufs[proc], recvSize[proc]); + delete [] recvBufs[proc]; + recvBufs[proc] = NULL; + numReceives--; + } + } + } + + delete [] reqBuf; + delete [] recvBufs; + delete [] recvSize; + + // Merge received grids + + float tolerance = 0.0; + + if (this->Kdtree) + { + tolerance = (float)this->Kdtree->GetFudgeFactor(); + } + + int numReceivedGrids = 0; + + vtkDataSet **ds = new vtkDataSet * [nprocs]; + + for (proc=0; proc < nprocs; proc++) + { + if (grids[proc] != NULL) + { + ds[numReceivedGrids++] = static_cast(grids[proc]); + } + } + + delete [] grids; + + if (numReceivedGrids > 1) + { + const char *globalNodeIds = this->GetGlobalNodeIdArrayName(ds[0]); + const char *globalCellIds = NULL; + if (filterOutDuplicateCells) + { + globalCellIds = this->GetGlobalElementIdArrayName(ds[0]); + } + + // this call will merge the grids and then delete them + mergedGrid = + vtkDistributedDataFilter::MergeGrids(ds, numReceivedGrids, DeleteYes, + globalNodeIds, tolerance, globalCellIds); + + } + else if (numReceivedGrids == 1) + { + mergedGrid = vtkUnstructuredGrid::SafeDownCast(ds[0]); + } + else + { + mergedGrid = this->ExtractZeroCellGrid(myGrid, mmd); + } + + if (mmd) + { + mmd->Delete(); + } + + if (deleteMyGrid) + { + myGrid->Delete(); + } + + delete [] ds; + +#else + (void)cellIds; // This is just here for successful compilation, + (void)numLists; // it will never execute. If !VTK_USE_MPI, we + (void)deleteCellIds; // never get this far. + (void)myGrid; + (void)deleteMyGrid; + (void)filterOutDuplicateCells; + (void)tag; + (void)ghostCellFlag; + + vtkErrorMacro(<< "vtkDistributedDataFilter::ExchangeMergeSubGrids requires MPI"); +#endif + + return mergedGrid; +} +void vtkDistributedDataFilter::AddMetadata(vtkUnstructuredGrid *grid, + vtkModelMetadata *mmd) +{ + const char *eltIdName = this->GetGlobalElementIdArrayName(grid); + vtkDataArray *da = grid->GetCellData()->GetArray(eltIdName); + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + + const char *nodeIdName = this->GetGlobalNodeIdArrayName(grid); + + // Extract the metadata for all cells in this grid + + vtkModelMetadata *submmd = + mmd->ExtractModelMetadata(ia, // extract metadata for these cells + grid, // in this grid + eltIdName, // global cell ID array name + nodeIdName); // global node ID array name + + // Pack that metadata into field arrays of the grid + + submmd->Pack(grid); + submmd->Delete(); +} + +vtkUnstructuredGrid *vtkDistributedDataFilter::MPIRedistribute(vtkDataSet *in, + vtkDataSet *input) +{ + int proc; + int nprocs = this->NumProcesses; + + // A cell belongs to a spatial region if it's centroid lies in that + // region. The kdtree object can create a list for each region of the + // IDs of each cell I have read in that belong in that region. If we + // are building subgrids of all cells that intersect a region (a + // superset of all cells that belong to a region) then the kdtree object + // can build another set of lists of all cells that intersect each + // region (but don't have their centroid in that region). + + if (this->IncludeAllIntersectingCells) + { + // TO DO: + // We actually compute whether a cell intersects a spatial region. + // This can be a lengthy calculation. Perhaps it's good enough + // to compute whether a cell's bounding box intersects the region. + // Some of the cells we list will actually not be in the region, but + // if we are clipping later, it doesn't matter. + // + // Is there any rendering algorithm that needs exactly all cells + // which intersect the region, and no more? + + this->Kdtree->IncludeRegionBoundaryCellsOn(); // SLOW!! + } + + this->Kdtree->CreateCellLists(); // required by GetCellIdsForProcess + + vtkIdList ***procCellLists = new vtkIdList ** [nprocs]; + int *numLists = new int [nprocs]; + + for (proc = 0; proc < this->NumProcesses; proc++) + { + procCellLists[proc] = this->GetCellIdsForProcess(proc, numLists + proc); + } + + int deleteDataSet = DeleteNo; + + if (in != input) + { + deleteDataSet = DeleteYes; + } + + vtkUnstructuredGrid *myNewGrid = + this->ExchangeMergeSubGrids(procCellLists, numLists, DeleteNo, + in, deleteDataSet, DuplicateCellsNo, GhostCellsNo, 0x0012); + + for (proc = 0; proc < nprocs; proc++) + { + delete [] procCellLists[proc]; + } + + delete [] procCellLists; + delete [] numLists; + + if (myNewGrid && (this->GhostLevel > 0)) + { + vtkDistributedDataFilter::AddConstantUnsignedCharCellArray( + myNewGrid, "vtkGhostLevels", 0); + vtkDistributedDataFilter::AddConstantUnsignedCharPointArray( + myNewGrid, "vtkGhostLevels", 0); + } + return myNewGrid; +} + +char *vtkDistributedDataFilter::MarshallDataSet(vtkUnstructuredGrid *extractedGrid, int &len) +{ + // taken from vtkCommunicator::WriteDataSet + + vtkUnstructuredGrid *copy; + vtkDataSetWriter *writer = vtkDataSetWriter::New(); + + copy = extractedGrid->NewInstance(); + copy->ShallowCopy(extractedGrid); + + // There is a problem with binary files with no data. + if (copy->GetNumberOfCells() > 0) + { + writer->SetFileTypeToBinary(); + } + writer->WriteToOutputStringOn(); + writer->SetInput(copy); + + writer->Write(); + + len = writer->GetOutputStringLength(); + + char *packedFormat = writer->RegisterAndGetOutputString(); + + writer->Delete(); + + copy->Delete(); + + return packedFormat; +} +vtkUnstructuredGrid *vtkDistributedDataFilter::UnMarshallDataSet(char *buf, int size) +{ + // taken from vtkCommunicator::ReadDataSet + + vtkDataSetReader *reader = vtkDataSetReader::New(); + + reader->ReadFromInputStringOn(); + + vtkCharArray* mystring = vtkCharArray::New(); + + mystring->SetArray(buf, size, 1); + + reader->SetInputArray(mystring); + mystring->Delete(); + + vtkDataSet *output = reader->GetOutput(); + output->Update(); + + vtkUnstructuredGrid *newGrid = vtkUnstructuredGrid::New(); + + newGrid->ShallowCopy(output); + + reader->Delete(); + + return newGrid; +} +vtkUnstructuredGrid + *vtkDistributedDataFilter::ExtractCells(vtkIdList *cells, int deleteCellLists, + vtkDataSet *in, vtkModelMetadata *mmd) +{ + vtkIdList *tempCellList = NULL; + + if (cells == NULL) + { + // We'll get a zero cell unstructured grid which matches the input grid + tempCellList = vtkIdList::New(); + } + else + { + tempCellList = cells; + } + + vtkUnstructuredGrid *subGrid = vtkDistributedDataFilter::ExtractCells( + &tempCellList, 1, deleteCellLists, in, mmd); + + if (tempCellList != cells) + { + tempCellList->Delete(); + } + + return subGrid; +} +vtkUnstructuredGrid + *vtkDistributedDataFilter::ExtractCells(vtkIdList **cells, int nlists, + int deleteCellLists, vtkDataSet *in, vtkModelMetadata *mmd) +{ + vtkDataSet* tmpInput = in->NewInstance(); + tmpInput->ShallowCopy(in); + + vtkExtractCells *extCells = vtkExtractCells::New(); + + extCells->SetInput(tmpInput); + + for (int i=0; iAddCellList(cells[i]); + + if (deleteCellLists) + { + cells[i]->Delete(); + } + } + } + + extCells->Update(); + + // If this process has no cells for these regions, a ugrid gets + // created anyway with field array information + + vtkUnstructuredGrid *keepGrid = vtkUnstructuredGrid::New(); + keepGrid->ShallowCopy(extCells->GetOutput()); + + extCells->Delete(); + + tmpInput->Delete(); + + if (mmd) + { + this->AddMetadata(keepGrid, mmd); + } + + return keepGrid; +} +vtkUnstructuredGrid + *vtkDistributedDataFilter::ExtractZeroCellGrid(vtkDataSet *in, + vtkModelMetadata *mmd) +{ + vtkDataSet* tmpInput = in->NewInstance(); + tmpInput->ShallowCopy(in); + + vtkExtractCells *extCells = vtkExtractCells::New(); + + extCells->SetInput(tmpInput); + + extCells->Update(); // extract no cells + + vtkUnstructuredGrid *keepGrid = vtkUnstructuredGrid::New(); + keepGrid->ShallowCopy(extCells->GetOutput()); + + extCells->Delete(); + + tmpInput->Delete(); + + if (mmd) + { + this->AddMetadata(keepGrid, mmd); + } + + return keepGrid; +} + +// To save on storage, we return actual pointers into the vtkKdTree's lists +// of cell IDs. So don't free the memory they are pointing to. +// vtkKdTree::DeleteCellLists will delete them all when we're done. + +vtkIdList **vtkDistributedDataFilter::GetCellIdsForProcess(int proc, int *nlists) +{ + *nlists = 0; + + vtkIntArray *regions = vtkIntArray::New(); + + int nregions = this->Kdtree->GetRegionAssignmentList(proc, regions); + + if (nregions == 0) + { + return NULL; + } + + *nlists = nregions; + + if (this->IncludeAllIntersectingCells) + { + *nlists *= 2; + } + + vtkIdList **lists = new vtkIdList * [*nlists]; + + int nextList = 0; + + for (int reg=0; reg < nregions; reg++) + { + lists[nextList++] = this->Kdtree->GetCellList(regions->GetValue(reg)); + + if (this->IncludeAllIntersectingCells) + { + lists[nextList++] = this->Kdtree->GetBoundaryCellList(regions->GetValue(reg)); + } + } + + regions->Delete(); + + return lists; +} + +//------------------------------------------------------------------------- +// Code related to clipping cells to the spatial region +//------------------------------------------------------------------------- + +static int insideBoxFunction(vtkIdType cellId, vtkUnstructuredGrid *grid, void *data) +{ + char *arrayName = (char *)data; + + vtkDataArray *da= grid->GetCellData()->GetArray(arrayName); + vtkUnsignedCharArray *inside = vtkUnsignedCharArray::SafeDownCast(da); + + unsigned char where = inside->GetValue(cellId); + + return where; // 1 if cell is inside spatial region, 0 otherwise +} +void vtkDistributedDataFilter::AddConstantUnsignedCharPointArray( + vtkUnstructuredGrid *grid, const char *arrayName, unsigned char val) +{ + vtkIdType npoints = grid->GetNumberOfPoints(); + + unsigned char *vals = new unsigned char [npoints]; + + memset(vals, val, npoints); + + vtkUnsignedCharArray *Array = vtkUnsignedCharArray::New(); + Array->SetName(arrayName); + Array->SetArray(vals, npoints, 0); + + grid->GetPointData()->AddArray(Array); + + Array->Delete(); +} +void vtkDistributedDataFilter::AddConstantUnsignedCharCellArray( + vtkUnstructuredGrid *grid, const char *arrayName, unsigned char val) +{ + vtkIdType ncells = grid->GetNumberOfCells(); + + unsigned char *vals = new unsigned char [ncells]; + + memset(vals, val, ncells); + + vtkUnsignedCharArray *Array = vtkUnsignedCharArray::New(); + Array->SetName(arrayName); + Array->SetArray(vals, ncells, 0); + + grid->GetCellData()->AddArray(Array); + + Array->Delete(); +} + +// this is here temporarily, until vtkBoxClipDataSet is fixed to +// be able to generate the clipped output + +void vtkDistributedDataFilter::ClipWithVtkClipDataSet( + vtkUnstructuredGrid *grid, double *bounds, + vtkUnstructuredGrid **outside, vtkUnstructuredGrid **inside) +{ + vtkUnstructuredGrid *in; + vtkUnstructuredGrid *out ; + + vtkClipDataSet *clipped = vtkClipDataSet::New(); + + vtkBox *box = vtkBox::New(); + box->SetBounds(bounds); + + clipped->SetClipFunction(box); + box->Delete(); + clipped->SetValue(0.0); + clipped->InsideOutOn(); + + clipped->SetInput(grid); + + if (outside) + { + clipped->GenerateClippedOutputOn(); + } + + clipped->Update(); + + if (outside) + { + out = clipped->GetClippedOutput(); + out->Register(this); + *outside = out; + } + + in = clipped->GetOutput(); + in->Register(this); + *inside = in; + + + clipped->Delete(); +} + +// In general, vtkBoxClipDataSet is much faster and makes fewer errors. + +void vtkDistributedDataFilter::ClipWithBoxClipDataSet( + vtkUnstructuredGrid *grid, double *bounds, + vtkUnstructuredGrid **outside, vtkUnstructuredGrid **inside) +{ + vtkUnstructuredGrid *in; + vtkUnstructuredGrid *out ; + + vtkBoxClipDataSet *clipped = vtkBoxClipDataSet::New(); + + clipped->SetBoxClip(bounds[0], bounds[1], + bounds[2], bounds[3], bounds[4], bounds[5]); + + clipped->SetInput(grid); + + if (outside) + { + clipped->GenerateClippedOutputOn(); + } + + clipped->Update(); + + if (outside) + { + out = clipped->GetClippedOutput(); + out->Register(this); + *outside = out; + } + + in = clipped->GetOutput(); + in->Register(this); + *inside = in; + + clipped->Delete(); +} + +void vtkDistributedDataFilter::ClipCellsToSpatialRegion(vtkUnstructuredGrid *grid) +{ + if (this->ConvexSubRegionBounds == NULL) + { + this->ComputeMyRegionBounds(); + } + + if (this->NumConvexSubRegions > 1) + { + // here we would need to divide the grid into a separate grid for + // each convex region, and then do the clipping + + vtkErrorMacro(<< + "vtkDistributedDataFilter::ClipCellsToSpatialRegion - " + "assigned regions do not form a single convex region"); + + return ; + } + + double *bounds = this->ConvexSubRegionBounds; + + if (this->GhostLevel > 0) + { + // We need cells outside the clip box as well. + + vtkUnstructuredGrid *outside; + vtkUnstructuredGrid *inside; + +#if 1 + this->ClipWithBoxClipDataSet(grid, bounds, &outside, &inside); +#else + this->ClipWithVtkClipDataSet(grid, bounds, &outside, &inside); +#endif + + grid->Initialize(); + + // Mark the outside cells with a 0, the inside cells with a 1. + + int arrayNameLen = strlen(TEMP_INSIDE_BOX_FLAG); + char *arrayName = new char [arrayNameLen + 1]; + strcpy(arrayName, TEMP_INSIDE_BOX_FLAG); + vtkDistributedDataFilter::AddConstantUnsignedCharCellArray(outside, arrayName, 0); + vtkDistributedDataFilter::AddConstantUnsignedCharCellArray(inside, arrayName, 1); + + // Combine inside and outside into a single ugrid. + + vtkDataSet *grids[2]; + grids[0] = inside; + grids[1] = outside; + + vtkUnstructuredGrid *combined = + vtkDistributedDataFilter::MergeGrids(grids, 2, DeleteYes, NULL, + (float)this->Kdtree->GetFudgeFactor(), NULL); + + // Extract the piece inside the box (level 0) and the requested + // number of levels of ghost cells. + + vtkExtractUserDefinedPiece *ep = vtkExtractUserDefinedPiece::New(); + + ep->SetConstantData(arrayName, arrayNameLen + 1); + ep->SetPieceFunction(insideBoxFunction); + ep->CreateGhostCellsOn(); + + ep->GetExecutive()->GetOutputInformation(0)->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + this->GhostLevel); + ep->SetInput(combined); + + ep->Update(); + + grid->ShallowCopy(ep->GetOutput()); + grid->GetCellData()->RemoveArray(arrayName); + + ep->Delete(); + combined->Delete(); + + delete [] arrayName; + } + else + { + vtkUnstructuredGrid *inside; + +#if 1 + this->ClipWithBoxClipDataSet(grid, bounds, NULL, &inside); +#else + this->ClipWithVtkClipDataSet(grid, bounds, NULL, &inside); +#endif + + grid->ShallowCopy(inside); + inside->Delete(); + } + + return; +} + +//------------------------------------------------------------------------- +// Code related to assigning global node IDs and cell IDs +//------------------------------------------------------------------------- + +int vtkDistributedDataFilter::AssignGlobalNodeIds(vtkUnstructuredGrid *grid) +{ + int nprocs = this->NumProcesses; + int pid; + int ptId; + vtkIdType nGridPoints = grid->GetNumberOfPoints(); + + int *numPointsOutside = new int [nprocs]; + memset(numPointsOutside, 0, sizeof(int) * nprocs); + + vtkIntArray *globalIds = vtkIntArray::New(); + globalIds->SetNumberOfValues(nGridPoints); + globalIds->SetName(TEMP_NODE_ID_NAME); + + // 1. Count the points in grid which lie within my assigned spatial region + + int myNumPointsInside = 0; + + for (ptId = 0; ptId < nGridPoints; ptId++) + { + double *pt = grid->GetPoints()->GetPoint(ptId); + + if (this->InMySpatialRegion(pt[0], pt[1], pt[2])) + { + globalIds->SetValue(ptId, 0); // flag it as mine + myNumPointsInside++; + } + else + { + // Well, whose region is this point in? + + int regionId = this->Kdtree->GetRegionContainingPoint(pt[0],pt[1],pt[2]); + + pid = this->Kdtree->GetProcessAssignedToRegion(regionId); + + numPointsOutside[pid]++; + + pid += 1; + pid *= -1; + + globalIds->SetValue(ptId, pid); // a flag + } + } + + // 2. Gather and Broadcast this number of "Inside" points for each process. + + vtkIntArray *numPointsInside = this->ExchangeCounts(myNumPointsInside, 0x0013); + + // 3. Assign global Ids to the points inside my spatial region + + int firstId = 0; + int numGlobalIdsSoFar = 0; + + for (pid = 0; pid < nprocs; pid++) + { + if (pid < this->MyId) + { + firstId += numPointsInside->GetValue(pid); + } + numGlobalIdsSoFar += numPointsInside->GetValue(pid); + } + + numPointsInside->Delete(); + + for (ptId = 0; ptId < nGridPoints; ptId++) + { + if (globalIds->GetValue(ptId) == 0) + { + globalIds->SetValue(ptId, firstId++); + } + } + + // ----------------------------------------------------------------- + // All processes have assigned global IDs to the points in their grid + // which lie within their assigned spatial region. + // Now they have to get the IDs for the + // points in their grid which lie outside their region, and which + // are within the spatial region of another process. + // ----------------------------------------------------------------- + + // 4. For every other process, build a list of points I have + // which are in the region of that process. In practice, the + // processes for which I need to request points IDs should be + // a small subset of all the other processes. + + // question: if the vtkPointArray has type double, should we + // send doubles instead of floats to insure we get the right + // global ID back? + + vtkFloatArray **ptarrayOut = new vtkFloatArray * [nprocs]; + memset(ptarrayOut, 0, sizeof(vtkFloatArray *) * nprocs); + + vtkIntArray **localIds = new vtkIntArray * [nprocs]; + memset(localIds, 0, sizeof(vtkIntArray *) * nprocs); + + int *next = new int [nprocs]; + int *next3 = new int [nprocs]; + + for (ptId = 0; ptId < nGridPoints; ptId++) + { + pid = globalIds->GetValue(ptId); + + if (pid >= 0) + { + continue; // that's one of mine + } + + pid *= -1; + pid -= 1; + + if (ptarrayOut[pid] == NULL) + { + int npoints = numPointsOutside[pid]; + + ptarrayOut[pid] = vtkFloatArray::New(); + ptarrayOut[pid]->SetNumberOfValues(npoints * 3); + + localIds[pid] = vtkIntArray::New(); + localIds[pid]->SetNumberOfValues(npoints); + + next[pid] = 0; + next3[pid] = 0; + } + + localIds[pid]->SetValue(next[pid]++, ptId); + + double *dp = grid->GetPoints()->GetPoint(ptId); + + ptarrayOut[pid]->SetValue(next3[pid]++, (float)dp[0]); + ptarrayOut[pid]->SetValue(next3[pid]++, (float)dp[1]); + ptarrayOut[pid]->SetValue(next3[pid]++, (float)dp[2]); + } + + delete [] numPointsOutside; + delete [] next; + delete [] next3; + + // 5. Do pairwise exchanges of the points we want global IDs for, + // and delete outgoing point arrays. + + vtkFloatArray **ptarrayIn = this->ExchangeFloatArrays(ptarrayOut, + DeleteYes, 0x0014); + + // 6. Find the global point IDs that have been requested of me, + // and delete incoming point arrays. Count "missing points": + // the number of unique points I receive which are not in my + // grid (this may happen if IncludeAllIntersectingCells is OFF). + + int myNumMissingPoints = 0; + + vtkIntArray **idarrayOut = + this->FindGlobalPointIds(ptarrayIn, globalIds, grid, myNumMissingPoints); + + vtkIntArray *missingCount = this->ExchangeCounts(myNumMissingPoints, 0x0015); + + if (this->IncludeAllIntersectingCells == 1) + { + // Make sure all points were found + + int aok = 1; + for (pid=0; pidGetValue(pid) > 0) + { + vtkErrorMacro(<< + "vtkDistributedDataFilter::AssignGlobalNodeIds bad point"); + aok = 0; + break; + } + } + if (!aok) + { + this->FreeIntArrays(idarrayOut); + this->FreeIntArrays(localIds); + missingCount->Delete(); + globalIds->Delete(); + + return 1; + } + } + + // 7. Do pairwise exchanges of the global point IDs, and delete the + // outgoing point ID arrays. + + vtkIntArray **idarrayIn = this->ExchangeIntArrays(idarrayOut, + DeleteYes, 0x0016); + + // 8. It's possible (if IncludeAllIntersectingCells is OFF) that some + // processes had "missing points". Process A has a point P in it's + // grid which lies in the spatial region of process B. But P is not + // in process B's grid. We need to assign global IDs to these points + // too. + + int *missingId = new int [nprocs]; + + if (this->IncludeAllIntersectingCells == 0) + { + missingId[0] = numGlobalIdsSoFar; + + for (pid = 1; pid < nprocs; pid++) + { + int prev = pid - 1; + missingId[pid] = missingId[prev] + missingCount->GetValue(prev); + } + } + + missingCount->Delete(); + + // 9. Update my ugrid with these mutually agreed upon global point IDs + + for (pid = 0; pid < nprocs; pid++) + { + if (idarrayIn[pid] == NULL) + { + continue; + } + + int count = idarrayIn[pid]->GetNumberOfTuples(); + + for (ptId = 0; ptId < count; ptId++) + { + int myLocalId = localIds[pid]->GetValue(ptId); + int yourGlobalId = idarrayIn[pid]->GetValue(ptId); + + if (yourGlobalId >= 0) + { + globalIds->SetValue(myLocalId, yourGlobalId); + } + else + { + int ptIdOffset = yourGlobalId * -1; + ptIdOffset -= 1; + + globalIds->SetValue(myLocalId, missingId[pid] + ptIdOffset); + } + } + localIds[pid]->Delete(); + idarrayIn[pid]->Delete(); + } + + delete [] localIds; + delete [] idarrayIn; + delete [] missingId; + + grid->GetPointData()->AddArray(globalIds); + globalIds->Delete(); + + this->SetGlobalNodeIdArrayName(TEMP_NODE_ID_NAME); + + return 0; +} + +// If grids were distributed with IncludeAllIntersectingCells OFF, it's +// possible there are points in my spatial region that are not in my +// grid. They need global Ids, so I will keep track of how many such unique +// points I receive from other processes, and will assign them temporary +// IDs. They will get permanent IDs later on. + +vtkIntArray **vtkDistributedDataFilter::FindGlobalPointIds( + vtkFloatArray **ptarray, vtkIntArray *ids, vtkUnstructuredGrid *grid, + int &numUniqueMissingPoints) +{ + int nprocs = this->NumProcesses; + vtkIntArray **gids = new vtkIntArray * [nprocs]; + + if (grid->GetNumberOfCells() == 0) + { + // There are no cells in my assigned region + + memset(gids, 0, sizeof(vtkIntArray *) * nprocs); + + return gids; + } + + vtkKdTree *kd = vtkKdTree::New(); + + kd->BuildLocatorFromPoints(grid->GetPoints()); + + int procId; + int ptId, localId; + + vtkPointLocator *pl = NULL; + vtkPoints *missingPoints = NULL; + + if (this->IncludeAllIntersectingCells == 0) + { + if (this->ConvexSubRegionBounds == NULL) + { + this->ComputeMyRegionBounds(); + } + pl = vtkPointLocator::New(); + pl->SetTolerance(this->Kdtree->GetFudgeFactor()); + missingPoints = vtkPoints::New(); + pl->InitPointInsertion(missingPoints, this->ConvexSubRegionBounds); + } + + for (procId = 0; procId < nprocs; procId++) + { + if ((ptarray[procId] == NULL) || + (ptarray[procId]->GetNumberOfTuples() == 0)) + { + gids[procId] = NULL; + if (ptarray[procId]) ptarray[procId]->Delete(); + continue; + } + + gids[procId] = vtkIntArray::New(); + + int npoints = ptarray[procId]->GetNumberOfTuples() / 3; + + gids[procId]->SetNumberOfValues(npoints); + int next = 0; + + float *pt = ptarray[procId]->GetPointer(0); + + for (ptId = 0; ptId < npoints; ptId++) + { + localId = kd->FindPoint((double)pt[0], (double)pt[1], (double)pt[2]); + + if (localId >= 0) + { + gids[procId]->SetValue(next++, ids->GetValue(localId)); // global Id + } + else + { + // This point is not in my grid + + if (this->IncludeAllIntersectingCells) + { + // This is an error + gids[procId]->SetValue(next++, -1); + numUniqueMissingPoints++; + } + else + { + // Flag these with a negative point ID. We'll assign + // them real point IDs later. + + vtkIdType nextId; + double dpt[3]; + dpt[0] = pt[0]; dpt[1] = pt[1]; dpt[2] = pt[2]; + pl->InsertUniquePoint(dpt, nextId); + + nextId += 1; + nextId *= -1; + gids[procId]->SetValue(next++, nextId); + } + } + pt += 3; + } + + ptarray[procId]->Delete(); + } + + delete [] ptarray; + + kd->Delete(); + + if (missingPoints) + { + numUniqueMissingPoints = missingPoints->GetNumberOfPoints(); + missingPoints->Delete(); + pl->Delete(); + } + + return gids; +} +int vtkDistributedDataFilter::AssignGlobalElementIds(vtkDataSet *in) +{ + int i; + int myNumCells = in->GetNumberOfCells(); + vtkIntArray *numCells = this->ExchangeCounts(myNumCells, 0x0017); + + vtkIntArray *globalCellIds = vtkIntArray::New(); + globalCellIds->SetNumberOfValues(myNumCells); + globalCellIds->SetName(TEMP_ELEMENT_ID_NAME); + + int StartId = 0; + + for (i=0; i < this->MyId; i++) + { + StartId += numCells->GetValue(i); + } + + numCells->Delete(); + + for (i=0; iSetValue(i, StartId++); + } + + in->GetCellData()->AddArray(globalCellIds); + + globalCellIds->Delete(); + + this->SetGlobalElementIdArrayName(TEMP_ELEMENT_ID_NAME); + + return 0; +} + +//------------------------------------------------------------------------- +// Code related to acquiring ghost cells +//------------------------------------------------------------------------- + +int vtkDistributedDataFilter::InMySpatialRegion(float x, float y, float z) +{ + return this->InMySpatialRegion((double)x, (double)y, (double)z); +} +int vtkDistributedDataFilter::InMySpatialRegion(double x, double y, double z) +{ + if (this->ConvexSubRegionBounds == NULL) + { + this->ComputeMyRegionBounds(); + } + + double *box = this->ConvexSubRegionBounds; + + if (!box) + { + return 0; + } + + // To avoid ambiguity, a point on a boundary is assigned to + // the region for which it is on the upper boundary. Or + // (in one dimension) the region between points A and B + // contains all points p such that A < p <= B. + + if ( (x <= box[0]) || (x > box[1]) || + (y <= box[2]) || (y > box[3]) || + (z <= box[4]) || (z > box[5]) ) + { + return 0; + } + + return 1; +} +int vtkDistributedDataFilter::StrictlyInsideMyBounds(float x, float y, float z) +{ + return this->StrictlyInsideMyBounds((double)x, (double)y, (double)z); +} +int vtkDistributedDataFilter::StrictlyInsideMyBounds(double x, double y, double z) +{ + if (this->ConvexSubRegionBounds == NULL) + { + this->ComputeMyRegionBounds(); + } + + double *box = this->ConvexSubRegionBounds; + + if (!box) + { + return 0; + } + + if ( (x <= box[0]) || (x >= box[1]) || + (y <= box[2]) || (y >= box[3]) || + (z <= box[4]) || (z >= box[5]) ) + { + return 0; + } + + return 1; +} + +vtkIntArray **vtkDistributedDataFilter::MakeProcessLists( + vtkIntArray **pointIds, + vtkDistributedDataFilterSTLCloak *procs) +{ + // Build a list of pointId/processId pairs for each process that + // sent me point IDs. The process Ids are all those processes + // that had the specified point in their ghost level zero grid. + + int nprocs = this->NumProcesses; + + vtkstd::multimap::iterator mapIt; + + vtkIntArray **processList = new vtkIntArray * [nprocs]; + memset(processList, 0, sizeof (vtkIntArray *) * nprocs); + + for (int i=0; iGetNumberOfTuples(); + + if (size > 0) + { + for (int j=0; jGetValue(j); + int ncells = pointIds[i]->GetValue(j+1); + + mapIt = procs->IntMultiMap.find(gid); + + if (mapIt != procs->IntMultiMap.end()) + { + while (mapIt->first == gid) + { + int processId = mapIt->second; + + if (processId != i) + { + // Process "i" needs to know that process + // "processId" also has cells using this point + + if (processList[i] == NULL) + { + processList[i] = vtkIntArray::New(); + } + processList[i]->InsertNextValue(gid); + processList[i]->InsertNextValue(processId); + } + ++mapIt; + } + } + j += (2 + ncells); + } + } + } + + return processList; +} +vtkIntArray *vtkDistributedDataFilter::AddPointAndCells( + int gid, int localId, vtkUnstructuredGrid *grid, + int *gidCells, vtkIntArray *ids) +{ + if (ids == NULL) + { + ids = vtkIntArray::New(); + } + + ids->InsertNextValue(gid); + + vtkIdList *cellList = vtkIdList::New(); + + grid->GetPointCells(localId, cellList); + + vtkIdType numCells = cellList->GetNumberOfIds(); + + ids->InsertNextValue((int)numCells); + + for (int j=0; jGetId(j)]; + ids->InsertNextValue(globalCellId); + } + + cellList->Delete(); + + return ids; +} +vtkIntArray **vtkDistributedDataFilter::GetGhostPointIds( + int ghostLevel, vtkUnstructuredGrid *grid, + int AddCellsIAlreadyHave) +{ + int nprocs = this->NumProcesses; + int me = this->MyId; + vtkIdType numPoints = grid->GetNumberOfPoints(); + + vtkIntArray **ghostPtIds = new vtkIntArray * [nprocs]; + memset(ghostPtIds, 0, sizeof(vtkIntArray *) * nprocs); + + if (numPoints < 1) + { + return ghostPtIds; + } + + int processId = -1; + int regionId = -1; + + vtkPKdTree *kd = this->Kdtree; + + vtkPoints *pts = grid->GetPoints(); + + int *gidsPoint = this->GetGlobalNodeIds(grid); + int *gidsCell = this->GetGlobalElementIds(grid); + + + vtkDataArray *da = grid->GetPointData()->GetArray("vtkGhostLevels"); + vtkUnsignedCharArray *uca = vtkUnsignedCharArray::SafeDownCast(da); + unsigned char *levels = uca->GetPointer(0); + + unsigned char level = (unsigned char)(ghostLevel - 1); + + for (int i=0; iGetPoint(i); + regionId = kd->GetRegionContainingPoint(pt[0], pt[1], pt[2]); + processId = kd->GetProcessAssignedToRegion(regionId); + + if (ghostLevel == 1) + { + // I want all points that are outside my spatial region + + if (processId == me) + { + continue; + } + + // Don't include points that are not part of any cell + + int used = vtkDistributedDataFilter::LocalPointIdIsUsed(grid, i); + + if (!used) + { + continue; + } + } + else if (levels[i] != level) + { + continue; // I want all points having the correct ghost level + } + + int gid = gidsPoint[i]; + + if (AddCellsIAlreadyHave) + { + // To speed up exchange of ghost cells and creation of + // new ghost cell grid, we tell other + // processes which cells we already have, so they don't + // send them to us. + + ghostPtIds[processId] = + vtkDistributedDataFilter::AddPointAndCells(gid, i, grid, gidsCell, + ghostPtIds[processId]); + } + else + { + if (ghostPtIds[processId] == NULL) + { + ghostPtIds[processId] = vtkIntArray::New(); + } + ghostPtIds[processId]->InsertNextValue(gid); + ghostPtIds[processId]->InsertNextValue(0); + } + } + return ghostPtIds; +} +int vtkDistributedDataFilter::LocalPointIdIsUsed( + vtkUnstructuredGrid *grid, int ptId) +{ + int used = 1; + + int numPoints = grid->GetNumberOfPoints(); + + if ((ptId < 0) || (ptId >= numPoints)) + { + used = 0; + } + else + { + vtkIdType id = (vtkIdType)ptId; + vtkIdList *cellList = vtkIdList::New(); + + grid->GetPointCells(id, cellList); + + if (cellList->GetNumberOfIds() == 0) + { + used = 0; + } + + cellList->Delete(); + } + + return used; +} +int vtkDistributedDataFilter::GlobalPointIdIsUsed(vtkUnstructuredGrid *grid, + int ptId, vtkDistributedDataFilterSTLCloak *globalToLocal) +{ + int used = 1; + + vtkstd::map::iterator mapIt; + + mapIt = globalToLocal->IntMap.find(ptId); + + if (mapIt == globalToLocal->IntMap.end()) + { + used = 0; + } + else + { + int id = mapIt->second; + + used = vtkDistributedDataFilter::LocalPointIdIsUsed(grid, id); + } + + return used; +} +int vtkDistributedDataFilter::FindId(vtkIntArray *ids, int gid, int startLoc) +{ + int gidLoc = -1; + + if (ids == NULL) + { + return gidLoc; + } + + int numIds = ids->GetNumberOfTuples(); + + while ((ids->GetValue(startLoc) != gid) && (startLoc < numIds)) + { + int ncells = ids->GetValue(++startLoc); + startLoc += (ncells + 1); + } + + if (startLoc < numIds) + { + gidLoc = startLoc; + } + + return gidLoc; +} + +// We create an expanded grid with the required number of ghost +// cells. This is for the case where IncludeAllIntersectingCells is OFF. +// This means that when the grid was redistributed, each cell was +// uniquely assigned to one process, the process owning the spatial +// region that the cell's centroid lies in. + +vtkUnstructuredGrid * +vtkDistributedDataFilter::AddGhostCellsUniqueCellAssignment( + vtkUnstructuredGrid *myGrid, + vtkDistributedDataFilterSTLCloak *globalToLocalMap) +{ + int i,j,k; + int ncells=0; + int processId=0; + int gid=0; + int size=0; + + int nprocs = this->NumProcesses; + int me = this->MyId; + + int gl = 1; + + // For each ghost level, processes request and send ghost cells + + vtkUnstructuredGrid *newGhostCellGrid = NULL; + vtkIntArray **ghostPointIds = NULL; + + vtkDistributedDataFilterSTLCloak *insidePointMap = + new vtkDistributedDataFilterSTLCloak; + vtkstd::multimap::iterator mapIt; + + while (gl <= this->GhostLevel) + { + // For ghost level 1, create a list for each process (not + // including me) of all points I have in that process' + // assigned region. We use this list for two purposes: + // (1) to build a list on each process of all other processes + // that have cells containing points in our region, (2) + // these are some of the points that we need ghost cells for. + // + // For ghost level above 1, create a list for each process + // (including me) of all my points in that process' assigned + // region for which I need ghost cells. + + if (gl == 1) + { + ghostPointIds = this->GetGhostPointIds(gl, myGrid, 0); + } + else + { + ghostPointIds = this->GetGhostPointIds(gl, newGhostCellGrid, 1); + } + + // Exchange these lists. + + vtkIntArray **insideIds = + this->ExchangeIntArrays(ghostPointIds, DeleteNo, + 0x0018); + + if (gl == 1) + { + // For every point in my region that was sent to me by another process, + // I now know the identity of all processes having cells containing + // that point. Begin by building a mapping from point IDs to the IDs + // of processes that sent me that point. + + for (i=0; iGetNumberOfTuples(); + + if (size > 0) + { + for (j=0; jGetValue(j); + insidePointMap->IntMultiMap.insert(vtkstd::pair(id, i)); + } + } + } + } + + // Build a list of pointId/processId pairs for each process that + // sent me point IDs. To process P, for every point ID sent to me + // by P, I send the ID of every other process (not including myself + // and P) that has cells in it's ghost level 0 grid which use + // this point. + + vtkIntArray **processListSent + = this->MakeProcessLists(insideIds, insidePointMap); + + // Exchange these new lists. + + vtkIntArray **processList = + this->ExchangeIntArrays(processListSent, DeleteYes, + 0x0019); + + // I now know the identity of every process having cells containing + // points I need ghost cells for. Create a request to each process + // for these cells. + + vtkIntArray **ghostCellsPlease = new vtkIntArray * [nprocs]; + for (i=0; iSetNumberOfComponents(1); + } + + for (i=0; iGetNumberOfTuples(); j++) + { + ghostCellsPlease[i]->InsertNextValue(ghostPointIds[i]->GetValue(j)); + } + } + if (processList[i]) // other processes you say that also have + { // cells using those points + size = processList[i]->GetNumberOfTuples(); + int *array = processList[i]->GetPointer(0); + int nextLoc = 0; + + for (j=0; j < size; j += 2) + { + gid = array[j]; + processId = array[j+1]; + + ghostCellsPlease[processId]->InsertNextValue(gid); + + if (gl > 1) + { + // add the list of cells I already have for this point + + int where = + vtkDistributedDataFilter::FindId(ghostPointIds[i], gid, nextLoc); + + if (where < 0) + { + // error really, not sure what to do + nextLoc = 0; + ghostCellsPlease[processId]->InsertNextValue(0); + continue; + } + + ncells = ghostPointIds[i]->GetValue(where + 1); + + ghostCellsPlease[processId]->InsertNextValue(ncells); + + for (k=0; k GetValue(where + 2 + k); + ghostCellsPlease[processId]->InsertNextValue(cellId); + } + + nextLoc = where; + } + else + { + ghostCellsPlease[processId]->InsertNextValue(0); + } + } + } + if ((gl==1) && insideIds[i]) // points you have in my spatial region, + { // which I may need ghost cells for + for (j=0; jGetNumberOfTuples();) + { + gid = insideIds[i]->GetValue(j); + int used = vtkDistributedDataFilter::GlobalPointIdIsUsed( + myGrid, gid, globalToLocalMap); + if (used) + { + ghostCellsPlease[i]->InsertNextValue(gid); + ghostCellsPlease[i]->InsertNextValue(0); + } + + ncells = insideIds[i]->GetValue(j+1); + j += (ncells + 2); + } + } + } + + if (gl > 1) + { + if (ghostPointIds[me]) // these points are actually inside my region + { + size = ghostPointIds[me]->GetNumberOfTuples(); + + for (i=0; iGetValue(i); + ncells = ghostPointIds[me]->GetValue(i+1); + + mapIt = insidePointMap->IntMultiMap.find(gid); + + if (mapIt != insidePointMap->IntMultiMap.end()) + { + while (mapIt->first == gid) + { + processId = mapIt->second; + ghostCellsPlease[processId]->InsertNextValue(gid); + ghostCellsPlease[processId]->InsertNextValue(ncells); + + for (k=0; kGetValue(i+1+k); + ghostCellsPlease[processId]->InsertNextValue(cellId); + } + + ++mapIt; + } + } + i += (ncells + 2); + } + } + } + + this->FreeIntArrays(ghostPointIds); + this->FreeIntArrays(insideIds); + this->FreeIntArrays(processList); + + // Exchange these ghost cell requests. + + vtkIntArray **ghostCellRequest + = this->ExchangeIntArrays(ghostCellsPlease, DeleteYes, + 0x001a); + + // Build a list of cell IDs satisfying each request received. + // Delete request arrays. + + vtkIdList **sendCellList = + this->BuildRequestedGrids(ghostCellRequest, myGrid, globalToLocalMap); + + // Build subgrids and exchange them + + vtkUnstructuredGrid *incomingGhostCells = this->ExchangeMergeSubGrids( + sendCellList, DeleteYes, myGrid, DeleteNo, DuplicateCellsNo, + GhostCellsYes, 0x001b); + + delete [] sendCellList; + + // Set ghost level of new cells, and merge into grid of other + // ghost cells received. + + newGhostCellGrid = this->SetMergeGhostGrid(newGhostCellGrid, + incomingGhostCells, gl, globalToLocalMap); + + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + + gl++; + } + + delete insidePointMap; + + vtkUnstructuredGrid *newGrid = NULL; + + if (newGhostCellGrid && (newGhostCellGrid->GetNumberOfCells() > 0)) + { + vtkDataSet *grids[2]; + + grids[0] = myGrid; + grids[1] = newGhostCellGrid; + + const char *nodeIds = this->GetGlobalNodeIdArrayName(myGrid); + + newGrid = + vtkDistributedDataFilter::MergeGrids(grids, 2, DeleteYes, nodeIds, 0, NULL); + } + else + { + newGrid = myGrid; + } + + return newGrid; +} + +// We create an expanded grid that contains the ghost cells we need. +// This is in the case where IncludeAllIntersectingCells is ON. This +// is easier in some respects because we know if that if a point lies +// in a region owned by a particular process, that process has all +// cells which use that point. So it is easy to find ghost cells. +// On the otherhand, because cells are not uniquely assigned to regions, +// we may get multiple processes sending us the same cell, so we +// need to filter these out. + +vtkUnstructuredGrid * +vtkDistributedDataFilter::AddGhostCellsDuplicateCellAssignment( + vtkUnstructuredGrid *myGrid, + vtkDistributedDataFilterSTLCloak *globalToLocalMap) +{ + int i,j; + + int nprocs = this->NumProcesses; + int me = this->MyId; + + int gl = 1; + + // For each ghost level, processes request and send ghost cells + + vtkUnstructuredGrid *newGhostCellGrid = NULL; + vtkIntArray **ghostPointIds = NULL; + vtkIntArray **extraGhostPointIds = NULL; + + vtkstd::map::iterator mapIt; + + vtkPoints *pts = myGrid->GetPoints(); + + while (gl <= this->GhostLevel) + { + // For ghost level 1, create a list for each process of points + // in my grid which lie in that other process' spatial region. + // This is normally all the points for which I need ghost cells, + // with one EXCEPTION. If a cell is axis-aligned, and a face of + // the cell is on my upper boundary, then the vertices of this + // face are in my spatial region, but I need their ghost cells. + // I can detect this case when the process across the boundary + // sends me a request for ghost cells of these points. + // + // For ghost level above 1, create a list for each process of + // points in my ghost grid which are in that process' spatial + // region and for which I need ghost cells. + + if (gl == 1) + { + ghostPointIds = this->GetGhostPointIds(gl, myGrid, 1); + } + else + { + ghostPointIds = this->GetGhostPointIds(gl, newGhostCellGrid, 1); + } + + // Exchange these lists. + + vtkIntArray **insideIds = + this->ExchangeIntArrays(ghostPointIds, DeleteYes, 0x001c); + + // For ghost level 1, examine the points Ids I received from + // other processes, to see if the exception described above + // applies and I need ghost cells from them for those points. + + if (gl == 1) + { + int *gidsCell = this->GetGlobalElementIds(myGrid); + + extraGhostPointIds = new vtkIntArray * [nprocs]; + + for (i=0; iGetNumberOfTuples(); + + for (j=0; jGetValue(j); + int ncells = insideIds[i]->GetValue(j+1); + j += (ncells + 2); + + mapIt = globalToLocalMap->IntMap.find(gid); + + if (mapIt == globalToLocalMap->IntMap.end()) + { + // This point must be right on my boundary, and + // not connected to any cell intersecting my region. + + continue; + } + int localId = mapIt->second; + + double *pt = pts->GetPoint(localId); + + int interior = this->StrictlyInsideMyBounds(pt[0], pt[1], pt[2]); + + if (!interior) + { + extraGhostPointIds[i] = this->AddPointAndCells(gid, localId, + myGrid, gidsCell, extraGhostPointIds[i]); + } + } + } + + // Exchange these lists. + + vtkIntArray **extraInsideIds = + this->ExchangeIntArrays(extraGhostPointIds, DeleteYes, 0x001d); + + // Add the extra point ids to the previous list + + for (i=0; iGetNumberOfTuples(); + + if (insideIds[i] == NULL) + { + insideIds[i] = vtkIntArray::New(); + } + + for (j=0; jInsertNextValue(extraInsideIds[i]->GetValue(j)); + } + } + } + this->FreeIntArrays(extraInsideIds); + } + + // Build a list of cell IDs satisfying each request received. + + vtkIdList **sendCellList = + this->BuildRequestedGrids(insideIds, myGrid, globalToLocalMap); + + // Build subgrids and exchange them + + vtkUnstructuredGrid *incomingGhostCells = + this->ExchangeMergeSubGrids( sendCellList, DeleteYes, myGrid, DeleteNo, + DuplicateCellsYes, GhostCellsYes, 0x001e); + + delete [] sendCellList; + + // Set ghost level of new cells, and merge into grid of other + // ghost cells received. + + newGhostCellGrid = this->SetMergeGhostGrid(newGhostCellGrid, + incomingGhostCells, gl, globalToLocalMap); + + this->UpdateProgress(this->NextProgressStep++ * this->ProgressIncrement); + + gl++; + } + + vtkUnstructuredGrid *newGrid = NULL; + + if (newGhostCellGrid && (newGhostCellGrid->GetNumberOfCells() > 0)) + { + vtkDataSet *grids[2]; + + grids[0] = myGrid; + grids[1] = newGhostCellGrid; + + const char *nodeIds = this->GetGlobalNodeIdArrayName(myGrid); + + newGrid = + vtkDistributedDataFilter::MergeGrids(grids, 2, DeleteYes, nodeIds, 0, NULL); + } + else + { + newGrid = myGrid; + } + + return newGrid; +} + +// For every process that sent me a list of point IDs, create a list +// of all the cells I have in my original grid containing those points. +// We omit cells the remote process already has. + +vtkIdList **vtkDistributedDataFilter::BuildRequestedGrids( + vtkIntArray **globalPtIds, + vtkUnstructuredGrid *grid, + vtkDistributedDataFilterSTLCloak *ptIdMap) +{ + int id, proc; + int nprocs = this->NumProcesses; + vtkIdType cellId; + vtkIdType nelts; + + // for each process, create a list of the ids of cells I need + // to send to it + + vtkstd::map::iterator imap; + + vtkIdList *cellList = vtkIdList::New(); + + vtkIdList **sendCells = new vtkIdList * [nprocs]; + + for (proc = 0; proc < nprocs; proc++) + { + sendCells[proc] = vtkIdList::New(); + + if (globalPtIds[proc] == NULL) + { + continue; + } + + if ((nelts = globalPtIds[proc]->GetNumberOfTuples()) == 0) + { + globalPtIds[proc]->Delete(); + continue; + } + + int *ptarray = globalPtIds[proc]->GetPointer(0); + + vtkstd::set subGridCellIds; + + int nYourCells = 0; + + for (id = 0; id < nelts; id += (nYourCells + 2)) + { + int ptId = ptarray[id]; + nYourCells = ptarray[id+1]; + + imap = ptIdMap->IntMap.find(ptId); + + if (imap == ptIdMap->IntMap.end()) + { + continue; // I don't have this point + } + + vtkIdType myPtId = (vtkIdType)imap->second; // convert to my local point Id + + grid->GetPointCells(myPtId, cellList); + + vtkIdType nMyCells = cellList->GetNumberOfIds(); + + if (nMyCells == 0) + { + continue; + } + + if (nYourCells > 0) + { + // We don't send cells the remote process tells us it already + // has. This is much faster than removing duplicate cells on + // the receive side. + + int *remoteCells = ptarray + id + 2; + int *gidCells = this->GetGlobalElementIds(grid); + + vtkDistributedDataFilter::RemoveRemoteCellsFromList(cellList, + gidCells, remoteCells, nYourCells); + } + + vtkIdType nSendCells = cellList->GetNumberOfIds(); + + if (nSendCells == 0) + { + continue; + } + + for (cellId = 0; cellId < nSendCells; cellId++) + { + subGridCellIds.insert(cellList->GetId(cellId)); + } + } + + globalPtIds[proc]->Delete(); + + int numUniqueCellIds = subGridCellIds.size(); + + if (numUniqueCellIds == 0) + { + continue; + } + + sendCells[proc]->SetNumberOfIds(numUniqueCellIds); + vtkIdType next = 0; + + vtkstd::set::iterator it; + + for (it = subGridCellIds.begin(); it != subGridCellIds.end(); ++it) + { + sendCells[proc]->SetId(next++, *it); + } + } + + delete [] globalPtIds; + + cellList->Delete(); + + return sendCells; +} +void vtkDistributedDataFilter::RemoveRemoteCellsFromList( + vtkIdList *cellList, int *gidCells, int *remoteCells, int nRemoteCells) +{ + vtkIdType id, nextId; + int id2; + vtkIdType nLocalCells = cellList->GetNumberOfIds(); + + // both lists should be very small, so we just do an n^2 lookup + + for (id = 0, nextId = 0; id < nLocalCells; id++) + { + vtkIdType localCellId = cellList->GetId(id); + int globalCellId = gidCells[localCellId]; + + int found = 0; + + for (id2 = 0; id2 < nRemoteCells; id2++) + { + if (remoteCells[id2] == globalCellId) + { + found = 1; + break; + } + } + + if (!found) + { + cellList->SetId(nextId++, localCellId); + } + } + + cellList->SetNumberOfIds(nextId); +} + +// Set the ghost levels for the points and cells in the received cells. +// Merge the new ghost cells into the supplied grid, and return the new grid. +// Delete all grids except the new merged grid. + +vtkUnstructuredGrid *vtkDistributedDataFilter::SetMergeGhostGrid( + vtkUnstructuredGrid *ghostCellGrid, + vtkUnstructuredGrid *incomingGhostCells, + int ghostLevel, vtkDistributedDataFilterSTLCloak *idMap) + +{ + int i; + + if (incomingGhostCells->GetNumberOfCells() < 1) + { + return ghostCellGrid; + } + + // Set the ghost level of all new cells, and set the ghost level of all + // the points. We know some points in the new grids actually have ghost + // level one lower, because they were on the boundary of the previous + // grid. This is OK if ghostLevel is > 1. When we merge, vtkMergeCells + // will skip these points because they are already in the previous grid. + // But if ghostLevel is 1, those boundary points were in our original + // grid, and we need to use the global ID map to determine if the + // point ghost levels should be set to 0. + + vtkDataArray *da = incomingGhostCells->GetCellData()->GetArray("vtkGhostLevels"); + vtkUnsignedCharArray *cellGL = vtkUnsignedCharArray::SafeDownCast(da); + + da = incomingGhostCells->GetPointData()->GetArray("vtkGhostLevels"); + vtkUnsignedCharArray *ptGL = vtkUnsignedCharArray::SafeDownCast(da); + + unsigned char *ia = cellGL->GetPointer(0); + + for (i=0; i < incomingGhostCells->GetNumberOfCells(); i++) + { + ia[i] = (unsigned char)ghostLevel; + } + + ia = ptGL->GetPointer(0); + + for (i=0; i < incomingGhostCells->GetNumberOfPoints(); i++) + { + ia[i] = (unsigned char)ghostLevel; + } + + // now merge + + vtkUnstructuredGrid *mergedGrid = incomingGhostCells; + + if (ghostCellGrid && (ghostCellGrid->GetNumberOfCells() > 0)) + { + vtkDataSet *sets[2]; + + sets[0] = ghostCellGrid; // both sets will be deleted by MergeGrids + sets[1] = incomingGhostCells; + + const char *nodeIds = this->GetGlobalNodeIdArrayName(ghostCellGrid); + + mergedGrid = + vtkDistributedDataFilter::MergeGrids(sets, 2, DeleteYes, nodeIds, 0.0, NULL); + } + + // If this is ghost level 1, mark any points from our original grid + // as ghost level 0. + + if (ghostLevel == 1) + { + da = mergedGrid->GetPointData()->GetArray("vtkGhostLevels"); + ptGL = vtkUnsignedCharArray::SafeDownCast(da); + + int *gidPoints = this->GetGlobalNodeIds(mergedGrid); + int npoints = mergedGrid->GetNumberOfPoints(); + + vtkstd::map::iterator imap; + + for (i=0; i < npoints; i++) + { + imap = idMap->IntMap.find(gidPoints[i]); + + if (imap != idMap->IntMap.end()) + { + ptGL->SetValue(i,0); // found among my ghost level 0 cells + } + } + } + + return mergedGrid; +} +vtkUnstructuredGrid *vtkDistributedDataFilter::MergeGrids( + vtkDataSet **sets, int nsets, int deleteDataSets, + const char *globalNodeIdArrayName, float pointMergeTolerance, + const char *globalCellIdArrayName) +{ + int i; + + if (nsets == 0) + { + return NULL; + } + + vtkModelMetadata *mmd = NULL; + + for (i=0; iUnpack(sets[i], DeleteYes); + + if (mmd) + { + mmd->MergeModelMetadata(submmd); + submmd->Delete(); + } + else + { + mmd = submmd; + } + } + + vtkUnstructuredGrid *newGrid = vtkUnstructuredGrid::New(); + + vtkMergeCells *mc = vtkMergeCells::New(); + mc->SetUnstructuredGrid(newGrid); + + mc->SetTotalNumberOfDataSets(nsets); + + int totalPoints = 0; + int totalCells = 0; + + for (i=0; iGetNumberOfPoints(); + totalCells += sets[i]->GetNumberOfCells(); + } + + mc->SetTotalNumberOfPoints(totalPoints); + mc->SetTotalNumberOfCells(totalCells); + + if (globalNodeIdArrayName) + { + mc->SetGlobalIdArrayName(globalNodeIdArrayName); + } + else + { + mc->SetPointMergeTolerance(pointMergeTolerance); + } + + if (globalCellIdArrayName) + { + mc->SetGlobalCellIdArrayName(globalCellIdArrayName); + } + + for (i=0; iMergeDataSet(sets[i]); + + if (deleteDataSets) + { + sets[i]->Delete(); + } + } + + mc->Finish(); + mc->Delete(); + + if (mmd) + { + // Pack the metadata onto the new grid and delete it. + + mmd->Pack(newGrid); + mmd->Delete(); + } + + return newGrid; +} +int vtkDistributedDataFilter::HasMetadata(vtkDataSet *s) +{ + return vtkModelMetadata::HasMetadata(vtkUnstructuredGrid::SafeDownCast(s)); +} +//------------------------------------------------------------------------- +int vtkDistributedDataFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//------------------------------------------------------------------------- +void vtkDistributedDataFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Kdtree: " << this->Kdtree << endl; + os << indent << "Controller: " << this->Controller << endl; + os << indent << "NumProcesses: " << this->NumProcesses << endl; + os << indent << "MyId: " << this->MyId << endl; + os << indent << "Target: " << this->Target << endl; + os << indent << "Source: " << this->Source << endl; + if (this->GlobalNodeIdArrayName) + { + os << indent << "GlobalNodeIdArrayName: " << this->GlobalNodeIdArrayName << endl; + } + if (this->GlobalElementIdArrayName) + { + os << indent << "GlobalElementIdArrayName: " << this->GlobalElementIdArrayName << endl; + } + os << indent << "RetainKdtree: " << this->RetainKdtree << endl; + os << indent << "IncludeAllIntersectingCells: " << this->IncludeAllIntersectingCells << endl; + os << indent << "ClipCells: " << this->ClipCells << endl; + + os << indent << "Timing: " << this->Timing << endl; + os << indent << "UseMinimalMemory: " << this->UseMinimalMemory << endl; +} + diff --git a/Parallel/vtkDistributedDataFilter.h b/Parallel/vtkDistributedDataFilter.h new file mode 100644 index 0000000..d89c073 --- /dev/null +++ b/Parallel/vtkDistributedDataFilter.h @@ -0,0 +1,456 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDistributedDataFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkDistributedDataFilter - Distribute data among processors +// +// .SECTION Description +// This filter redistributes data among processors in a parallel +// application into spatially contiguous vtkUnstructuredGrids. +// The execution model anticipated is that all processes read in +// part of a large vtkDataSet. Each process sets the input of +// filter to be that DataSet. When executed, this filter builds +// in parallel a k-d tree, decomposing the space occupied by the +// distributed DataSet into spatial regions. It assigns each +// spatial region to a processor. The data is then redistributed +// and the output is a single vtkUnstructuredGrid containing the +// cells in the process' assigned regions. +// +// This filter is sometimes called "D3" for "distributed data decomposition". +// +// Enhancement: You can set the k-d tree decomposition, rather than +// have D3 compute it. This allows you to divide a dataset using +// the decomposition computed for another dataset. Obtain a description +// of the k-d tree cuts this way: +// +// vtkBSPCuts *cuts = D3Object1->GetKdtree()->GetCuts() +// +// And set it this way: +// +// D3Object2->GetKdtree()->SetCuts(cuts) +// +// .SECTION Caveats +// The Execute() method must be called by all processes in the +// parallel application, or it will hang. If you are not certain +// that your pipeline will execute identically on all processors, +// you may want to use this filter in an explicit execution mode. +// +// .SECTION See Also +// vtkKdTree vtkPKdTree vtkBSPCuts + +#ifndef __vtkDistributedDataFilter_h +#define __vtkDistributedDataFilter_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkUnstructuredGrid; +class vtkPKdTree; +class vtkMultiProcessController; +class vtkDataArray; +class vtkIntArray; +class vtkFloatArray; +class vtkIdList; +class vtkUnstructuredGrid; +class vtkModelMetadata; +class vtkDistributedDataFilterSTLCloak; + +class VTK_PARALLEL_EXPORT vtkDistributedDataFilter: public vtkUnstructuredGridAlgorithm +{ + vtkTypeRevisionMacro(vtkDistributedDataFilter, + vtkUnstructuredGridAlgorithm); + +public: + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkDistributedDataFilter *New(); + + // Description: + // Set/Get the communicator object + void SetController(vtkMultiProcessController *c); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + + // Description: + // It is desirable to have a field array of global node IDs + // for two reasons: + // + // 1. When merging together sub grids that were distributed + // across processors, global node IDs can be used to remove + // duplicate points and significantly reduce the size of the + // resulting output grid. If no such array is available, + // D3 will use a tolerance to merge points, which is much + // slower. + // + // 2. If ghost cells have been requested, D3 requires a + // global node ID array in order to request and transfer + // ghost cells in parallel among the processors. If there + // is no global node ID array, D3 will in parallel create + // a global node ID array, and the time to do this can be + // significant. + // + // If you know the name of a global node ID array in the input + // dataset, set that name with this method. If you leave + // it unset, D3 will search the input data set for certain + // common names of global node ID arrays. If none is found, + // and ghost cells have been requested, D3 will create a + // temporary global node ID array before aquiring ghost cells. + + vtkSetStringMacro(GlobalNodeIdArrayName); + + // Description: + // It is also desirable to have global element IDs. However, + // if they don't exist D3 can create them relatively quickly. + // Set the name of the global element ID array if you have it. + // If it is not set, D3 will search for it using common names. + // If still not found, D3 will create a temporary array of + // global element IDs. + + vtkSetStringMacro(GlobalElementIdArrayName); + + // Description: + // When this filter executes, it creates a vtkPKdTree (K-d tree) + // data structure in parallel which divides the total distributed + // data set into spatial regions. The K-d tree object also creates + // tables describing which processes have data for which + // regions. Only then does this filter redistribute + // the data according to the region assignment scheme. By default, + // the K-d tree structure and it's associated tables are deleted + // after the filter executes. If you anticipate changing only the + // region assignment scheme (input is unchanged) and explicitly + // re-executing, then RetainKdTreeOn, and the K-d tree structure and + // tables will be saved. Then, when you re-execute, this filter will + // skip the k-d tree build phase and go straight to redistributing + // the data according to region assignment. See vtkPKdTree for + // more information about region assignment. + + vtkBooleanMacro(RetainKdtree, int); + vtkGetMacro(RetainKdtree, int); + vtkSetMacro(RetainKdtree, int); + + // Description: + // Get a pointer to the parallel k-d tree object. Required for changing + // default behavior for region assignment, changing default depth of tree, + // or other tree building default parameters. See vtkPKdTree and + // vtkKdTree for more information about these options. + + vtkPKdTree *GetKdtree(); + + // Description: + // Each cell in the data set is associated with one of the + // spatial regions of the k-d tree decomposition. In particular, + // the cell belongs to the region that it's centroid lies in. + // When the new vtkUnstructuredGrid is created, by default it + // is composed of the cells associated with the region(s) + // assigned to this process. If you also want it to contain + // cells that intersect these regions, but have their centroid + // elsewhere, then set this variable on. By default it is off. + + vtkBooleanMacro(IncludeAllIntersectingCells, int); + vtkGetMacro(IncludeAllIntersectingCells, int); + vtkSetMacro(IncludeAllIntersectingCells, int); + + // Description: + // Set this variable if you want the cells of the output + // vtkUnstructuredGrid to be clipped to the spatial region + // boundaries. By default this is off. + + vtkBooleanMacro(ClipCells, int); + vtkGetMacro(ClipCells, int); + vtkSetMacro(ClipCells, int); + +//BTX + enum BoundaryModes { + ASSIGN_TO_ONE_REGION=0, + ASSIGN_TO_ALL_INTERSECTING_REGIONS=1, + SPLIT_BOUNDARY_CELLS=2 + }; +//ETX + + // Description: + // Handling of ClipCells and IncludeAllIntersectingCells. + void SetBoundaryMode(int mode); + void SetBoundaryModeToAssignToOneRegion() + { this->SetBoundaryMode(vtkDistributedDataFilter::ASSIGN_TO_ONE_REGION); } + void SetBoundaryModeToAssignToAllIntersectingRegions() + { this->SetBoundaryMode( + vtkDistributedDataFilter::ASSIGN_TO_ALL_INTERSECTING_REGIONS); + } + void SetBoundaryModeToSplitBoundaryCells() + { this->SetBoundaryMode(vtkDistributedDataFilter::SPLIT_BOUNDARY_CELLS); } + int GetBoundaryMode(); + + // Description: + // Ensure previous filters don't send up ghost cells + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // Description: + // This class does a great deal of all-to-all communication + // when exchanging portions of data sets and building new sub + // grids. + // By default it will do fast communication. It can instead + // use communication routines that use the least possible + // amount of memory, but these are slower. Set this option + // ON to choose these latter routines. + + vtkBooleanMacro(UseMinimalMemory, int); + vtkGetMacro(UseMinimalMemory, int); + vtkSetMacro(UseMinimalMemory, int); + + + // Description: + // Turn on collection of timing data + + vtkBooleanMacro(Timing, int); + vtkSetMacro(Timing, int); + vtkGetMacro(Timing, int); + + // Description: + // Consider the MTime of the KdTree. + unsigned long GetMTime(); + +protected: + vtkDistributedDataFilter(); + ~vtkDistributedDataFilter(); + + // Description: + // Another way to set ClipCells and IncludeAllIntersectingCells. + // AssignBoundaryCellsToOneRegion turns off both ClipCells and + // IncludeAllIntersectingCells. Each cell will be included in + // exactly one process' output unstructured grid. + + void AssignBoundaryCellsToOneRegionOn(); + void AssignBoundaryCellsToOneRegionOff(); + void SetAssignBoundaryCellsToOneRegion(int val); + + // Description: + // Another way to set ClipCells and IncludeAllIntersectingCells. + // AssignBoundaryCellsToAllIntersectingRegions turns off ClipCells + // turns on IncludeAllIntersectingCells. A cell will be included + // in the output unstructured grid built for every region that it + // intersects. If a cell intersects two process' spatial regions, + // both processes will have that cell in their output grid. + + void AssignBoundaryCellsToAllIntersectingRegionsOn(); + void AssignBoundaryCellsToAllIntersectingRegionsOff(); + void SetAssignBoundaryCellsToAllIntersectingRegions(int val); + + // Description: + // Another way to set ClipCells and IncludeAllIntersectingCells. + // DivideBoundaryCells turns on both ClipCells and + // IncludeAllIntersectingCells. A cell that straddles a processor + // boundary will be split along the boundary, with each process + // getting the portion of the cell that lies in it's spatial region. + + void DivideBoundaryCellsOn(); + void DivideBoundaryCellsOff(); + void SetDivideBoundaryCells(int val); + + // Description: + // Build a vtkUnstructuredGrid for a spatial region from the + // data distributed across processes. Execute() must be called + // by all processes, or it will hang. + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void SingleProcessExecute(vtkDataSet *input, vtkUnstructuredGrid *output); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + +//BTX + enum{ + DeleteNo = 0, + DeleteYes = 1 + }; + + enum{ + DuplicateCellsNo = 0, + DuplicateCellsYes = 1 + }; + + enum{ + GhostCellsNo = 0, + GhostCellsYes = 1 + }; + + enum{ + UnsetGhostLevel = 99 + }; +//ETX + int PartitionDataAndAssignToProcesses(vtkDataSet *set); + vtkUnstructuredGrid *RedistributeDataSet(vtkDataSet *set, vtkDataSet *input); + int ClipGridCells(vtkUnstructuredGrid *grid); + vtkUnstructuredGrid * AcquireGhostCells(vtkUnstructuredGrid *grid); + + void ComputeMyRegionBounds(); + + int CheckFieldArrayTypes(vtkDataSet *set); + + vtkDataSet *TestFixTooFewInputFiles(vtkDataSet *input); + + vtkUnstructuredGrid *MPIRedistribute(vtkDataSet *in, vtkDataSet *input); + + vtkIdList **GetCellIdsForProcess(int proc, int *nlists); + + void SetUpPairWiseExchange(); + void FreeIntArrays(vtkIntArray **ar); + vtkIntArray *ExchangeCounts(int myCount, int tag); + vtkIntArray **ExchangeIntArrays(vtkIntArray **arIn, + int deleteSendArrays, int tag); + vtkFloatArray **ExchangeFloatArrays(vtkFloatArray **myArray, + int deleteSendArrays, int tag); + vtkUnstructuredGrid *ExchangeMergeSubGrids(vtkIdList **cellIds, int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, int ghostCellFlag, int tag); + vtkUnstructuredGrid *ExchangeMergeSubGrids(vtkIdList ***cellIds, int *numLists, + int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, int ghostCellFlag, int tag); + vtkIntArray *ExchangeCountsLean(int myCount, int tag); + vtkIntArray **ExchangeIntArraysLean(vtkIntArray **arIn, + int deleteSendArrays, int tag); + vtkFloatArray **ExchangeFloatArraysLean(vtkFloatArray **myArray, + int deleteSendArrays, int tag); + vtkUnstructuredGrid *ExchangeMergeSubGridsLean( + vtkIdList ***cellIds, int *numLists, + int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, int ghostCellFlag, int tag); + vtkIntArray *ExchangeCountsFast(int myCount, int tag); + vtkIntArray **ExchangeIntArraysFast(vtkIntArray **arIn, + int deleteSendArrays, int tag); + vtkFloatArray **ExchangeFloatArraysFast(vtkFloatArray **myArray, + int deleteSendArrays, int tag); + vtkUnstructuredGrid *ExchangeMergeSubGridsFast( + vtkIdList ***cellIds, int *numLists, + int deleteCellIds, + vtkDataSet *myGrid, int deleteMyGrid, + int filterOutDuplicateCells, int ghostCellFlag, int tag); + + + char *MarshallDataSet(vtkUnstructuredGrid *extractedGrid, int &size); + vtkUnstructuredGrid *UnMarshallDataSet(char *buf, int size); + + void ClipCellsToSpatialRegion(vtkUnstructuredGrid *grid); + + void ClipWithVtkClipDataSet(vtkUnstructuredGrid *grid, double *bounds, + vtkUnstructuredGrid **outside, vtkUnstructuredGrid **inside); + void ClipWithBoxClipDataSet(vtkUnstructuredGrid *grid, double *bounds, + vtkUnstructuredGrid **outside, vtkUnstructuredGrid **inside); + + const char *GetGlobalNodeIdArrayName(vtkDataSet *set); + int *GetGlobalNodeIds(vtkDataSet *set); + + const char *GetGlobalElementIdArrayName(vtkDataSet *set); + int *GetGlobalElementIds(vtkDataSet *set); + + int AssignGlobalNodeIds(vtkUnstructuredGrid *grid); + int AssignGlobalElementIds(vtkDataSet *in); + + vtkIntArray **FindGlobalPointIds(vtkFloatArray **ptarray, + vtkIntArray *ids, vtkUnstructuredGrid *grid, int &numUniqueMissingPoints); + + int InMySpatialRegion(float x, float y, float z); + int InMySpatialRegion(double x, double y, double z); + int StrictlyInsideMyBounds(float x, float y, float z); + int StrictlyInsideMyBounds(double x, double y, double z); + + vtkIntArray **GetGhostPointIds(int ghostLevel, vtkUnstructuredGrid *grid, + int AddCellsIAlreadyHave); + vtkIntArray **MakeProcessLists(vtkIntArray **pointIds, + vtkDistributedDataFilterSTLCloak *procs); + vtkUnstructuredGrid *AddGhostCellsUniqueCellAssignment( + vtkUnstructuredGrid *myGrid, + vtkDistributedDataFilterSTLCloak *globalToLocalMap); + vtkUnstructuredGrid *AddGhostCellsDuplicateCellAssignment( + vtkUnstructuredGrid *myGrid, + vtkDistributedDataFilterSTLCloak *globalToLocalMap); + vtkIdList **BuildRequestedGrids( vtkIntArray **globalPtIds, + vtkUnstructuredGrid *grid, + vtkDistributedDataFilterSTLCloak *ptIdMap); + vtkUnstructuredGrid *SetMergeGhostGrid( + vtkUnstructuredGrid *ghostCellGrid, + vtkUnstructuredGrid *incomingGhostCells, + int ghostLevel, vtkDistributedDataFilterSTLCloak *idMap); + + vtkUnstructuredGrid *ExtractCells(vtkIdList *list, + int deleteCellLists, vtkDataSet *in, vtkModelMetadata *mmd); + vtkUnstructuredGrid *ExtractCells(vtkIdList **lists, int nlists, + int deleteCellLists, vtkDataSet *in, vtkModelMetadata *mmd); + vtkUnstructuredGrid *ExtractZeroCellGrid(vtkDataSet *in, + vtkModelMetadata *mmd); + + void AddMetadata(vtkUnstructuredGrid *grid, vtkModelMetadata *mmd); + + static int GlobalPointIdIsUsed(vtkUnstructuredGrid *grid, + int ptId, vtkDistributedDataFilterSTLCloak *globalToLocal); + + static int LocalPointIdIsUsed(vtkUnstructuredGrid *grid, int ptId); + static int FindId(vtkIntArray *ids, int gid, int startLoc); + static vtkIntArray *AddPointAndCells(int gid, int localId, + vtkUnstructuredGrid *grid, int *gidCells, vtkIntArray *ids); + + static void AddConstantUnsignedCharPointArray(vtkUnstructuredGrid *grid, + const char *arrayName, unsigned char val); + static void AddConstantUnsignedCharCellArray(vtkUnstructuredGrid *grid, + const char *arrayName, unsigned char val); + static void RemoveRemoteCellsFromList(vtkIdList *cellList, int *gidCells, + int *remoteCells, int nRemoteCells); + static vtkUnstructuredGrid *MergeGrids(vtkDataSet **sets, int nsets, + int deleteDataSets, + const char *globalNodeIdArrayName, float pointMergeTolerance, + const char *globalCellIdArrayName); + + static void FreeIdLists(vtkIdList**lists, int nlists); + static vtkIdType GetIdListSize(vtkIdList**lists, int nlists); + static int HasMetadata(vtkDataSet *s); + + vtkPKdTree *Kdtree; + vtkMultiProcessController *Controller; + + int NumProcesses; + int MyId; + + int *Target; + int *Source; + + int NumConvexSubRegions; + double *ConvexSubRegionBounds; + + int GhostLevel; + + char *GlobalElementIdArrayName; + char *GlobalNodeIdArrayName; + + int RetainKdtree; + int IncludeAllIntersectingCells; + int ClipCells; + int AssignBoundaryCellsToOneRegion; + int AssignBoundaryCellsToAllIntersectingRegions; + int DivideBoundaryCells; + + int Timing; + + int NextProgressStep; + double ProgressIncrement; + + int UseMinimalMemory; + + vtkDistributedDataFilter(const vtkDistributedDataFilter&); // Not implemented + void operator=(const vtkDistributedDataFilter&); // Not implemented +}; +#endif diff --git a/Parallel/vtkDistributedStreamTracer.cxx b/Parallel/vtkDistributedStreamTracer.cxx new file mode 100644 index 0000000..9d4d3b2 --- /dev/null +++ b/Parallel/vtkDistributedStreamTracer.cxx @@ -0,0 +1,351 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDistributedStreamTracer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDistributedStreamTracer.h" + +#include "vtkCellData.h" +#include "vtkFloatArray.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkInterpolatedVelocityField.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkRungeKutta2.h" + +vtkCxxRevisionMacro(vtkDistributedStreamTracer, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkDistributedStreamTracer); + +vtkDistributedStreamTracer::vtkDistributedStreamTracer() +{ +} + +vtkDistributedStreamTracer::~vtkDistributedStreamTracer() +{ +} + +void vtkDistributedStreamTracer::ForwardTask(double seed[3], + int direction, + int isNewSeed, + int lastId, + int lastCellId, + int currentLine, + double* firstNormal) +{ + int myid = this->Controller->GetLocalProcessId(); + int numProcs = this->Controller->GetNumberOfProcesses(); + int nextid; + if (myid == numProcs-1) + { + nextid = 0; + } + else + { + nextid = myid+1; + } + + this->Controller->Send(&isNewSeed, 1, nextid, 311); + this->Controller->Send(&lastId, 1, nextid, 322); + if (isNewSeed != 2) + { + this->Controller->Send(&lastCellId, 1, nextid, 322); + this->Controller->Send(seed, 3, nextid, 333); + this->Controller->Send(&direction, 1, nextid, 344); + this->Controller->Send(¤tLine, 1, nextid, 355); + double tmpNormal[4]; + if (firstNormal) + { + tmpNormal[0] = 1; + memcpy(tmpNormal+1, firstNormal, 3*sizeof(double)); + } + else + { + tmpNormal[0] = 0; + } + this->Controller->Send(tmpNormal, 4, nextid, 366); + } +} + +int vtkDistributedStreamTracer::ReceiveAndProcessTask( + vtkInformationVector **inputVector) +{ + int isNewSeed = 0; + int lastId = 0; + int lastCellId = 0; + int currentLine = 0; + int direction=FORWARD; + double seed[3] = {0.0, 0.0, 0.0}; + int myid = this->Controller->GetLocalProcessId(); + int numProcs = this->Controller->GetNumberOfProcesses(); + + this->Controller->Receive(&isNewSeed, + 1, + vtkMultiProcessController::ANY_SOURCE, + 311); + this->Controller->Receive(&lastId, + 1, + vtkMultiProcessController::ANY_SOURCE, + 322); + + // isNewSeed == 2 means that we were to stop. + if ( isNewSeed == 2 ) + { + if ( (( myid == numProcs-1 && lastId == 0 ) || + ( myid != numProcs-1 && lastId == myid + 1) )) + { + // All processes have been already told to stop. No need to tell + // the next one. + return 0; + } + this->ForwardTask(seed, direction, 2, lastId, lastCellId, 0, 0); + return 0; + } + this->Controller->Receive(&lastCellId, + 1, + vtkMultiProcessController::ANY_SOURCE, + 322); + this->Controller->Receive(seed, + 3, + vtkMultiProcessController::ANY_SOURCE, + 333); + this->Controller->Receive(&direction, + 1, + vtkMultiProcessController::ANY_SOURCE, + 344); + this->Controller->Receive(¤tLine, + 1, + vtkMultiProcessController::ANY_SOURCE, + 355); + double tmpNormal[4]; + this->Controller->Receive(tmpNormal, + 4, + vtkMultiProcessController::ANY_SOURCE, + 366); + double* firstNormal=0; + if (tmpNormal[0] != 0) + { + firstNormal = &(tmpNormal[1]); + } + return this->ProcessTask( + seed, direction, isNewSeed, lastId, lastCellId, currentLine, firstNormal, + inputVector); +} + +int vtkDistributedStreamTracer::ProcessNextLine( + int currentLine, vtkInformationVector **inputVector) +{ + int myid = this->Controller->GetLocalProcessId(); + + vtkIdType numLines = this->SeedIds->GetNumberOfIds(); + currentLine++; + if ( currentLine < numLines ) + { + return this->ProcessTask( + this->Seeds->GetTuple(this->SeedIds->GetId(currentLine)), + this->IntegrationDirections->GetValue(currentLine), + 1, myid, -1, currentLine, 0, inputVector); + } + + // All done. Tell everybody to stop. + double seed[3] = {0.0, 0.0, 0.0}; + this->ForwardTask(seed, 0, 2, myid, 0, 0, 0); + return 0; + +} + +// Integrate a streamline +int vtkDistributedStreamTracer::ProcessTask(double seed[3], + int direction, + int isNewSeed, + int lastId, + int lastCellId, + int currentLine, + double* firstNormal, + vtkInformationVector **inputVector) +{ + int myid = this->Controller->GetLocalProcessId(); + + // This seed was visited by everybody and nobody had it. + // Must be out of domain. + if (isNewSeed == 0 && lastId == myid) + { + return this->ProcessNextLine(currentLine, inputVector); + } + + double velocity[3]; + // We don't have it, let's forward it to the next guy + this->Interpolator->ClearLastCellId(); + int retVal = this->Interpolator->FunctionValues(seed, velocity); + if (!retVal) + { + this->ForwardTask( + seed, direction, 0, lastId, lastCellId, currentLine, firstNormal); + return 1; + } + + // We have it, let's integrate + double lastPoint[3]; + + vtkFloatArray* seeds = vtkFloatArray::New(); + seeds->SetNumberOfComponents(3); + seeds->InsertNextTuple(seed); + + vtkIdList* seedIds = vtkIdList::New(); + seedIds->InsertNextId(0); + + vtkIntArray* integrationDirections = vtkIntArray::New(); + integrationDirections->InsertNextValue(direction); + + // Keep track of all streamlines by adding them to TmpOutputs. + // They will be appended together after all the integration is done. + vtkPolyData* tmpOutput = vtkPolyData::New(); + this->TmpOutputs.push_back(tmpOutput); + + vtkInterpolatedVelocityField* func; + int maxCellSize = 0; + this->CheckInputs(func, &maxCellSize, inputVector); + + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkDataArray *vectors = this->GetInputArrayToProcess(0,inputVector); + const char *vecName = vectors->GetName(); + this->Integrate(vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())), + tmpOutput, + seeds, + seedIds, + integrationDirections, + lastPoint, + func, + maxCellSize, vecName); + this->GenerateNormals(tmpOutput, firstNormal, vecName); + + // These are used to keep track of where the seed came from + // and where it will go. Used later to fill the gaps between + // streamlines. + vtkIntArray* strOrigin = vtkIntArray::New(); + strOrigin->SetNumberOfComponents(2); + strOrigin->SetNumberOfTuples(1); + strOrigin->SetName("Streamline Origin"); + strOrigin->SetValue(0, lastId); + strOrigin->SetValue(1, lastCellId); + tmpOutput->GetCellData()->AddArray(strOrigin); + strOrigin->Delete(); + + vtkIntArray* streamIds = vtkIntArray::New(); + streamIds->SetNumberOfTuples(1); + streamIds->SetName("Streamline Ids"); + lastCellId = static_cast(this->TmpOutputs.size()) - 1; + streamIds->SetComponent(0, 0, lastCellId); + tmpOutput->GetCellData()->AddArray(streamIds); + streamIds->Delete(); + + // We have to know why the integration terminated + vtkIntArray* resTermArray = vtkIntArray::SafeDownCast( + tmpOutput->GetCellData()->GetArray("ReasonForTermination")); + int resTerm=vtkStreamTracer::OUT_OF_DOMAIN; + if (resTermArray) + { + resTerm = resTermArray->GetValue(0); + } + + int numPoints = tmpOutput->GetNumberOfPoints(); + // If the interation terminated due to something other than + // moving outside the domain, move to the next seed. + if (numPoints == 0 || resTerm != vtkStreamTracer::OUT_OF_DOMAIN) + { + retVal = this->ProcessNextLine(currentLine, inputVector); + seeds->Delete(); + seedIds->Delete(); + integrationDirections->Delete(); + tmpOutput->Delete(); + func->Delete(); + return retVal; + } + + // Continue the integration a bit further to obtain a point + // outside. The main integration step can not always be used + // for this, specially if the integration is not 2nd order. + tmpOutput->GetPoint(numPoints-1, lastPoint); + + vtkInitialValueProblemSolver* ivp = this->Integrator; + ivp->Register(this); + + vtkRungeKutta2* tmpSolver = vtkRungeKutta2::New(); + this->SetIntegrator(tmpSolver); + tmpSolver->Delete(); + + double tmpseed[3]; + memcpy(tmpseed, lastPoint, 3*sizeof(double)); + this->SimpleIntegrate(tmpseed, lastPoint, this->LastUsedTimeStep, func); + func->Delete(); + + this->SetIntegrator(ivp); + ivp->UnRegister(this); + + double* lastNormal = 0; + vtkDataArray* normals = tmpOutput->GetPointData()->GetArray("Normals"); + if (normals) + { + lastNormal = new double[3]; + normals->GetTuple(normals->GetNumberOfTuples()-1, lastNormal); + } + + tmpOutput->GetPoints()->SetPoint(numPoints-1, lastPoint); + tmpOutput->Delete(); + + // New seed, send it to the next guy + this->ForwardTask(lastPoint, direction, 1, myid, lastCellId, + currentLine, lastNormal); + + delete[] lastNormal; + + seeds->Delete(); + seedIds->Delete(); + integrationDirections->Delete(); + + return 1; +} + +void vtkDistributedStreamTracer::ParallelIntegrate( + vtkInformationVector **inputVector) +{ + + int myid = this->Controller->GetLocalProcessId(); + if (this->Seeds) + { + int doLoop = 1; + // First process starts by integrating the first point + if (myid == 0) + { + int currentLine = 0; + doLoop = this->ProcessTask( + this->Seeds->GetTuple(this->SeedIds->GetId(currentLine)), + this->IntegrationDirections->GetValue(currentLine), + 1, myid, -1,currentLine, 0, inputVector); + } + // Wait for someone to send us a seed to start from. + while(doLoop) + { + if (!this->ReceiveAndProcessTask(inputVector)) { break; } + } + } +} + +void vtkDistributedStreamTracer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Parallel/vtkDistributedStreamTracer.h b/Parallel/vtkDistributedStreamTracer.h new file mode 100644 index 0000000..91bc2ab --- /dev/null +++ b/Parallel/vtkDistributedStreamTracer.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDistributedStreamTracer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDistributedStreamTracer - Distributed streamline generator +// .SECTION Description +// This filter integrates streamlines on a distributed dataset. It is +// essentially a serial algorithm: only one process is active at one +// time and it is not more efficient than a single process integration. +// It is useful when the data is too large to be on one process and +// has to be kept distributed. +// .SECTION See Also +// vtkStreamTracer vtkPStreamTracer + +#ifndef __vtkDistributedStreamTracer_h +#define __vtkDistributedStreamTracer_h + +#include "vtkPStreamTracer.h" + +class VTK_PARALLEL_EXPORT vtkDistributedStreamTracer : public vtkPStreamTracer +{ +public: + vtkTypeRevisionMacro(vtkDistributedStreamTracer,vtkPStreamTracer); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + static vtkDistributedStreamTracer *New(); + +protected: + + vtkDistributedStreamTracer(); + ~vtkDistributedStreamTracer(); + + void ForwardTask(double seed[3], + int direction, + int isNewSeed, + int lastid, + int lastCellId, + int currentLine, + double* firstNormal); + int ProcessTask(double seed[3], + int direction, + int isNewSeed, + int lastid, + int lastCellId, + int currentLine, + double* firstNormal, + vtkInformationVector **inputVector); + int ProcessNextLine(int currentLine, vtkInformationVector **inputVector); + int ReceiveAndProcessTask(vtkInformationVector **inputVector); + + virtual void ParallelIntegrate(vtkInformationVector **inputVector); + +private: + vtkDistributedStreamTracer(const vtkDistributedStreamTracer&); // Not implemented. + void operator=(const vtkDistributedStreamTracer&); // Not implemented. +}; + + +#endif + + diff --git a/Parallel/vtkDummyController.cxx b/Parallel/vtkDummyController.cxx new file mode 100644 index 0000000..49ea079 --- /dev/null +++ b/Parallel/vtkDummyController.cxx @@ -0,0 +1,27 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDummyController.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDummyController.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkDummyController, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkDummyController); + + +//---------------------------------------------------------------------------- +void vtkDummyController::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Parallel/vtkDummyController.h b/Parallel/vtkDummyController.h new file mode 100644 index 0000000..393563d --- /dev/null +++ b/Parallel/vtkDummyController.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDummyController.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDummyController - Dummy controller for single process applications +// .SECTION Description +// This is a dummy controller which can be used by applications which always +// require a controller but are also compile on systems without threads +// or mpi. +// .SECTION see also +// vtkMultiProcessController + +#ifndef __vtkDummyController_h +#define __vtkDummyController_h + +#include "vtkMultiProcessController.h" + +class VTK_PARALLEL_EXPORT vtkDummyController : public vtkMultiProcessController +{ +public: + static vtkDummyController *New(); + vtkTypeRevisionMacro(vtkDummyController,vtkMultiProcessController); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method is for setting up the processes. + virtual void Initialize(int*, char***, int) {} + virtual void Initialize(int*, char***) {} + virtual void Finalize() {} + virtual void Finalize(int) {} + + // Description: + // This method always returns 0. + int GetLocalProcessId() { return 0; } + + // Description: + // Does nothing. + virtual void SingleMethodExecute() {} + + // Description: + // Does nothing. + virtual void MultipleMethodExecute() {} + + // Description: + // Does nothing. + virtual void Barrier() {} + + // Description: + // Does nothing. + virtual void CreateOutputWindow() {} + +protected: + vtkDummyController() {} + ~vtkDummyController() {} + +private: + vtkDummyController(const vtkDummyController&); // Not implemented. + void operator=(const vtkDummyController&); // Not implemented. +}; + +#endif + + diff --git a/Parallel/vtkDuplicatePolyData.cxx b/Parallel/vtkDuplicatePolyData.cxx new file mode 100644 index 0000000..cc54c1b --- /dev/null +++ b/Parallel/vtkDuplicatePolyData.cxx @@ -0,0 +1,364 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDuplicatePolyData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDuplicatePolyData.h" + +#include "vtkAppendPolyData.h" +#include "vtkCellData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkSocketController.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkDuplicatePolyData, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkDuplicatePolyData); + +vtkCxxSetObjectMacro(vtkDuplicatePolyData,Controller, vtkMultiProcessController); +vtkCxxSetObjectMacro(vtkDuplicatePolyData,SocketController, vtkSocketController); + +//---------------------------------------------------------------------------- +vtkDuplicatePolyData::vtkDuplicatePolyData() +{ + // Controller keeps a reference to this object as well. + this->Controller = NULL; + this->SetController(vtkMultiProcessController::GetGlobalController()); + this->Synchronous = 1; + + this->Schedule = NULL; + this->ScheduleLength = 0; + this->NumberOfProcesses = 0; + + this->SocketController = NULL; + this->ClientFlag = 0; + this->MemorySize = 0; +} + +//---------------------------------------------------------------------------- +vtkDuplicatePolyData::~vtkDuplicatePolyData() +{ + this->SetController(0); + // Free the schedule memory. + this->InitializeSchedule(0); +} + + +#define vtkDPDPow2(j) (1 << (j)) +static inline int vtkDPDLog2(int j, int& exact) +{ + int counter=0; + exact = 1; + while(j) + { + if ( ( j & 1 ) && (j >> 1) ) + { + exact = 0; + } + j = j >> 1; + counter++; + } + return counter-1; +} + +//---------------------------------------------------------------------------- +void vtkDuplicatePolyData::InitializeSchedule(int numProcs) +{ + int i, j, k, exact; + int *procFlags = NULL; + + if (this->NumberOfProcesses == numProcs) + { + return; + } + + // Free old schedule. + for (i = 0; i < this->NumberOfProcesses; ++i) + { + delete [] this->Schedule[i]; + this->Schedule[i] = NULL; + } + if (this->Schedule) + { + delete [] this->Schedule; + this->Schedule = NULL; + } + + this->NumberOfProcesses = numProcs; + if (numProcs == 0) + { + return; + } + + i = vtkDPDLog2(numProcs, exact); + if (!exact) + { + ++i; + } + this->ScheduleLength = vtkDPDPow2(i) - 1; + this->Schedule = new int*[numProcs]; + for (i = 0; i < numProcs; ++i) + { + this->Schedule[i] = new int[this->ScheduleLength]; + for (j = 0; j < this->ScheduleLength; ++j) + { + this->Schedule[i][j] = -1; + } + } + + // Temporary array to record which processes have been used. + procFlags = new int[numProcs]; + + for (j = 0; j < this->ScheduleLength; ++j) + { + for (i = 0; i < numProcs; ++i) + { + if (this->Schedule[i][j] == -1) + { + // Try to find a available process that we have not paired with yet. + for (k = 0; k < numProcs; ++k) + { + procFlags[k] = 0; + } + // Eliminate this process as a candidate. + procFlags[i] = 1; + // Eliminate procs already communicating durring this cycle. + for (k = 0; k < numProcs; ++k) + { + if (this->Schedule[k][j] != -1) + { + procFlags[this->Schedule[k][j]] = 1; + } + } + // Eliminate proces we have already paired with. + for (k = 0; k < j; ++k) + { + if (this->Schedule[i][k] != -1) + { + procFlags[this->Schedule[i][k]] = 1; + } + } + // Look for the first appropriate process. + for (k = 0; k < numProcs; ++k) + { + if (procFlags[k] == 0) + { + // Set the pair in the schedule for communication. + this->Schedule[i][j] = k; + this->Schedule[k][j] = i; + // Break the loop. + k = numProcs; + } + } + } + } + } + + delete [] procFlags; + procFlags = NULL; +} + +//---------------------------------------------------------------------------- +int vtkDuplicatePolyData::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + return 1; +} + +//-------------------------------------------------------------------------- +int vtkDuplicatePolyData::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkDuplicatePolyData::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int myId, partner; + int idx; + + if (this->SocketController && this->ClientFlag) + { + this->ClientExecute(output); + return 1; + } + + if (this->Controller == NULL) + { + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + if (this->SocketController && ! this->ClientFlag) + { + this->SocketController->Send(output, 1, 18732); + } + return 1; + } + + myId = this->Controller->GetLocalProcessId(); + + // Collect. + vtkPolyData *pd = NULL;; + + vtkAppendPolyData *append = vtkAppendPolyData::New(); + // First append the input from this process. + pd = vtkPolyData::New(); + pd->CopyStructure(input); + pd->GetPointData()->PassData(input->GetPointData()); + pd->GetCellData()->PassData(input->GetCellData()); + append->AddInput(pd); + pd->Delete(); + + for (idx = 0; idx < this->ScheduleLength; ++idx) + { + partner = this->Schedule[myId][idx]; + if (partner >= 0) + { + // Matching the order may not be necessary and may slow things down, + // but it is a reasonable precaution. + if (partner > myId || ! this->Synchronous) + { + this->Controller->Send(input, partner, 131767); + + pd = vtkPolyData::New(); + this->Controller->Receive(pd, partner, 131767); + append->AddInput(pd); + pd->Delete(); + pd = NULL; + } + else + { + pd = vtkPolyData::New(); + this->Controller->Receive(pd, partner, 131767); + append->AddInput(pd); + pd->Delete(); + pd = NULL; + + this->Controller->Send(input, partner, 131767); + } + } + } + append->Update(); + input = append->GetOutput(); + + // Copy to output. + output->CopyStructure(input); + output->GetPointData()->PassData(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + append->Delete(); + append = NULL; + + if (this->SocketController && ! this->ClientFlag) + { + this->SocketController->Send(output, 1, 18732); + } + + this->MemorySize = output->GetActualMemorySize(); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDuplicatePolyData::ClientExecute(vtkPolyData *output) +{ + vtkPolyData *tmp = vtkPolyData::New(); + + // No data is on the client, so we just have to get the data + // from node 0 of the server. + this->SocketController->Receive(tmp, 1, 18732); + output->CopyStructure(tmp); + output->GetPointData()->PassData(tmp->GetPointData()); + output->GetCellData()->PassData(tmp->GetCellData()); +} + +//---------------------------------------------------------------------------- +void vtkDuplicatePolyData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + int i, j; + + os << indent << "Controller: (" << this->Controller << ")\n"; + if (this->SocketController) + { + os << indent << "SocketController: (" << this->SocketController << ")\n"; + os << indent << "ClientFlag: " << this->ClientFlag << endl; + } + os << indent << "Synchronous: " << this->Synchronous << endl; + + os << indent << "Schedule:\n"; + indent = indent.GetNextIndent(); + for (i = 0; i < this->NumberOfProcesses; ++i) + { + os << indent << i << ": "; + if (this->Schedule[i][0] >= 0) + { + os << this->Schedule[i][0]; + } + else + { + os << "X"; + } + for (j = 1; j < this->ScheduleLength; ++j) + { + os << ", "; + if (this->Schedule[i][j] >= 0) + { + os << this->Schedule[i][j]; + } + else + { + os << "X"; + } + } + os << endl; + } + + os << indent << "MemorySize: " << this->MemorySize << endl; +} diff --git a/Parallel/vtkDuplicatePolyData.h b/Parallel/vtkDuplicatePolyData.h new file mode 100644 index 0000000..562abe6 --- /dev/null +++ b/Parallel/vtkDuplicatePolyData.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDuplicatePolyData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDuplicatePolyData - For distributed tiled displays. +// .SECTION Description +// This filter collects poly data and duplicates it on every node. +// Converts data parallel so every node has a complete copy of the data. +// The filter is used at the end of a pipeline for driving a tiled +// display. + + +#ifndef __vtkDuplicatePolyData_h +#define __vtkDuplicatePolyData_h + +#include "vtkPolyDataAlgorithm.h" +class vtkSocketController; +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkDuplicatePolyData : public vtkPolyDataAlgorithm +{ +public: + static vtkDuplicatePolyData *New(); + vtkTypeRevisionMacro(vtkDuplicatePolyData, vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // By defualt this filter uses the global controller, + // but this method can be used to set another instead. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + + void InitializeSchedule(int numProcs); + + // Description: + // This flag causes sends and receives to be matched. + // When this flag is off, two sends occur then two receives. + // I want to see if it makes a difference in performance. + // The flag is on by default. + vtkSetMacro(Synchronous, int); + vtkGetMacro(Synchronous, int); + vtkBooleanMacro(Synchronous, int); + + // Description: + // This duplicate filter works in client server mode when this + // controller is set. We have a client flag to diferentiate the + // client and server because the socket controller is odd: + // Proth processes think their id is 0. + vtkSocketController *GetSocketController() {return this->SocketController;} + void SetSocketController (vtkSocketController *controller); + vtkSetMacro(ClientFlag,int); + vtkGetMacro(ClientFlag,int); + + // Description: + // This returns to size of the output (on this process). + // This method is not really used. It is needed to have + // the same API as vtkCollectPolyData. + vtkGetMacro(MemorySize, unsigned long); + +protected: + vtkDuplicatePolyData(); + ~vtkDuplicatePolyData(); + + // Data generation method + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void ClientExecute(vtkPolyData *output); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkMultiProcessController *Controller; + int Synchronous; + + int NumberOfProcesses; + int ScheduleLength; + int **Schedule; + + // For client server mode. + vtkSocketController *SocketController; + int ClientFlag; + + unsigned long MemorySize; + +private: + vtkDuplicatePolyData(const vtkDuplicatePolyData&); // Not implemented + void operator=(const vtkDuplicatePolyData&); // Not implemented +}; + +#endif + diff --git a/Parallel/vtkEnSightWriter.cxx b/Parallel/vtkEnSightWriter.cxx new file mode 100644 index 0000000..929b820 --- /dev/null +++ b/Parallel/vtkEnSightWriter.cxx @@ -0,0 +1,1245 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +/* TODO + * + * + * check that data was written + * + */ + +#include "vtkEnSightWriter.h" + +#include "vtkToolkits.h" // for VTK_USE_PARALLEL +#ifdef VTK_USE_PARALLEL +# include "vtkMultiProcessController.h" +#endif + +#include "vtkBitArray.h" +#include "vtkByteSwap.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCharArray.h" +#include "vtkDataSet.h" +#include "vtkDoubleArray.h" +#include "vtkErrorCode.h" +#include "vtkFieldData.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkShortArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include "vtkPriorityQueue.h" + +#include "vtkUnstructuredGrid.h" +#include "vtkModelMetadata.h" + +#include +#include +#include + +#include +#include +#include +#include + +// If we are building against a slightly older VTK version, +// these cell types are not defined, and won't occur in the input + +#ifndef VTK_QUADRATIC_WEDGE +# define VTK_QUADRATIC_WEDGE 26 +# define VTK_QUADRATIC_PYRAMID 27 +#endif + +// this undef is required on the hp. vtkMutexLock ends up including +// /usr/inclue/dce/cma_ux.h which has the gall to #define write as cma_write + +#ifdef write +# undef write +#endif + +//---------------------------------------------------------------------------- +vtkStandardNewMacro(vtkEnSightWriter); +vtkCxxRevisionMacro(vtkEnSightWriter, "$Revision: 1.3 $"); + +vtkCxxSetObjectMacro(vtkEnSightWriter, ModelMetadata, vtkModelMetadata); + +//---------------------------------------------------------------------------- +// Created object with no filename and timestep 0 +vtkEnSightWriter::vtkEnSightWriter() +{ + + this->BaseName = NULL; + this->FileName = NULL; + this->TimeStep = 0; + this->ModelMetadata = NULL; + this->Path=NULL; + this->GhostLevelMultiplier=10000; + this->GhostLevel = 0; + this->TransientGeometry=false; + this->ProcessNumber=0; + this->NumberOfProcesses=1; + this->NumberOfBlocks=0; + this->BlockIDs=0; + this->TmpInput = NULL; +} + +//---------------------------------------------------------------------------- +vtkEnSightWriter::~vtkEnSightWriter() +{ + if (this->ModelMetadata) + { + this->ModelMetadata->Delete(); + this->ModelMetadata = NULL; + } + + this->SetBaseName(NULL); + this->SetFileName(NULL); + this->SetPath(NULL); +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "FileName: " + << (this->FileName ? this->FileName : "(none)") << "\n"; + os << indent << "Path: " + << (this->Path ? this->Path : "(none)") << "\n"; + os << indent << "BaseName: " + << (this->BaseName ? this->BaseName : "(none)") << "\n"; + + if (this->ModelMetadata !=NULL) + { + this->ModelMetadata->PrintSelf(os,indent.GetNextIndent()); + } + else + { + cout << indent << "ModelMetadata: (none)" << "\n"; + } + + os << indent << "TimeStep: " << this->TimeStep << "\n"; + os << indent << "TransientGeometry: " << this->TransientGeometry << "\n"; + os << indent << "ProcessNumber: " << this->ProcessNumber << endl; + os << indent << "NumberOfProcesses: " << this->NumberOfProcesses << endl; + os << indent << "NumberOfBlocks: " << this->NumberOfBlocks << endl; + os << indent << "BlockIDs: " << this->BlockIDs << endl; + os << indent << "GhostLevel: " << this->GhostLevel << endl; +} + +int vtkEnSightWriter::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info ) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +void vtkEnSightWriter::SetInput(vtkUnstructuredGrid *input) +{ + this->Superclass::SetInput(0, input); +} + + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkUnstructuredGrid *vtkEnSightWriter::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return NULL; + } + else if (this->TmpInput) + { + return this->TmpInput; + } + else + { + return (vtkUnstructuredGrid *)(this->Superclass::GetInput()); + } +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteData() +{ + int i; + unsigned int ui; + int blockCount=0; + vtkstd::list::iterator iter; + + if (this->TmpInput) + { + this->TmpInput->Delete(); + this->TmpInput = NULL; + } + + //figure out process ID + + this->ProcessNumber = 0; + this->NumberOfProcesses = 1; + +#ifdef VTK_USE_PARALLEL + vtkMultiProcessController *c = vtkMultiProcessController::GetGlobalController(); + + if (c != NULL) + { + this->ProcessNumber=c->GetLocalProcessId(); + this->NumberOfProcesses = c->GetNumberOfProcesses(); + } +#endif + + vtkUnstructuredGrid *input=this->GetInput(); + + if (this->GhostLevel > input->GetUpdateGhostLevel()) + { + // re-execute pipeline if necessary to obtain ghost cells + + input->SetUpdateGhostLevel(this->GhostLevel); + input->Update(); + } + + int deletemmd = 0; + + if (this->ModelMetadata == NULL) + { + vtkDataSet *in = static_cast(input); + int hasMetadata = vtkModelMetadata::HasMetadata(in); + + if (hasMetadata) + { + vtkModelMetadata *mmd = vtkModelMetadata::New(); + mmd->Unpack(in, 0); + this->ModelMetadata = mmd; + deletemmd = 1; + } + } + + //get the BlockID Cell Array + vtkDataArray *BlockData=input->GetCellData()->GetScalars("BlockId"); + + if (BlockData==NULL || strcmp(BlockData->GetName(),"BlockId")) + { + BlockData=NULL; + } + + if (this->ModelMetadata) + { + // Remove special ID arrays created by Exodus reader, required for + // interpreting metadata attached to input. + + this->TmpInput = vtkUnstructuredGrid::New(); + this->TmpInput->ShallowCopy(input); + + vtkDataArray *da = this->TmpInput->GetCellData()->GetArray("GlobalElementId"); + if (da) + { + this->TmpInput->GetCellData()->RemoveArray("GlobalElementId"); + } + da = this->TmpInput->GetPointData()->GetArray("GlobalNodeId"); + if (da) + { + this->TmpInput->GetPointData()->RemoveArray("GlobalNodeId"); + } + da = this->TmpInput->GetCellData()->GetArray("BlockId"); + if (da) + { + this->TmpInput->GetCellData()->RemoveArray("BlockId"); + } + + input = this->TmpInput; + } + + this->ComputeNames(); + + if (!this->BaseName) + { + vtkErrorMacro("A FileName or Path/BaseName must be specified."); + return; + } + + this->SanitizeFileName(this->BaseName); + + char** blockNames=NULL; + int * elementIDs=NULL; + char charBuffer[512]; + char fileBuffer[512]; + sprintf(charBuffer,"%s/%s.%d.%05d.geo", + this->Path,this->BaseName,this->ProcessNumber, + this->TimeStep); + + //open the geometry file + //only if timestep 0 and not transient geometry or transient geometry + FILE *fd=NULL; + if (this->ShouldWriteGeometry()) + { + if (!(fd=OpenFile(charBuffer))) + return; + } + + //Get the FILE's for Point Data Fields + vtkstd::vector pointArrayFiles; + int NumPointArrays=input->GetPointData()->GetNumberOfArrays(); + for (i=0;iGetPointData()->GetArray(i)->GetName()); + this->SanitizeFileName(fileBuffer); + sprintf(charBuffer,"%s/%s.%d.%05d_n.%s",this->Path,this->BaseName,this->ProcessNumber, + this->TimeStep,fileBuffer); + FILE* ftemp=OpenFile(charBuffer); + if (!ftemp) + return; + pointArrayFiles.push_back(ftemp); + + //write the description line to the file + WriteStringToFile(fileBuffer,ftemp); + } + + //Get the FILE's for Cell Data Fields + vtkstd::vector cellArrayFiles; + int NumCellArrays=input->GetCellData()->GetNumberOfArrays(); + for (i=0;iGetCellData()->GetArray(i)->GetName()); + this->SanitizeFileName(fileBuffer); + sprintf(charBuffer,"%s/%s.%d.%05d_c.%s",this->Path,this->BaseName,this->ProcessNumber, + this->TimeStep,fileBuffer); + FILE* ftemp=OpenFile(charBuffer); + if (!ftemp) + return; + cellArrayFiles.push_back(ftemp); + + //write the description line to the file + WriteStringToFile(fileBuffer,ftemp); + } + + //write the header information + if (this->ShouldWriteGeometry()) + { + this->WriteStringToFile("C Binary",fd); + this->WriteStringToFile("Written by VTK EnSight Writer",fd); + //if (this->Title) + // this->WriteStringToFile(this->Title,fd); + //else + if (this->ModelMetadata) + { + this->WriteStringToFile(this->ModelMetadata->GetTitle(),fd); + } + else + { + this->WriteStringToFile("No Title was Specified",fd); + } + //we will specify node and element ID's + this->WriteStringToFile("node id given\n",fd); + this->WriteStringToFile("element id given\n",fd); + } + + //get the Ghost Cell Array if it exists + vtkDataArray *GhostData=input->GetCellData()->GetScalars("vtkGhostLevels"); + //if the strings are not the same then we did not get the ghostData array + if (GhostData==NULL || strcmp(GhostData->GetName(),"vtkGhostLevels")) + { + GhostData=NULL; + } + + + //data structure to get all the cells for a certain part + //basically sort by part# and cell type + vtkstd::map > CellsByPart; + + //just a list of part numbers + vtkstd::list partNumbers; + + //get all the part numbers in the unstructured grid and sort the cells + //by part number + for (i=0;iGetNumberOfCells();i++) + { + int key=1; + if (BlockData) + key=(int)(BlockData->GetTuple(i)[0]); + else + cout << "No BlockID was found\n"; + if (CellsByPart.count(key)==0) + { + CellsByPart[key]=vtkstd::vector < int >() ; + } + CellsByPart[key].push_back(i); + partNumbers.push_back(key); + + } + + //remove the duplicates from the partNumbers + partNumbers.sort(); + partNumbers.unique(); + + //get the block names from the exodus model if they exist + if (this->ModelMetadata) + { + blockNames=this->ModelMetadata->GetBlockElementType(); + elementIDs=this->ModelMetadata->GetBlockIds(); + } + + //write out each part + for (iter=partNumbers.begin();iter!=partNumbers.end();iter++) + { + unsigned int j; + vtkstd::list::iterator iter2; + int part=*iter; + + //write the part Header + if (this->ShouldWriteGeometry()) + { + blockCount+=1; + this->WriteStringToFile("part",fd); + this->WriteIntToFile(part,fd); + //cout << "part is " << part << endl; + int exodusIndex=-1; + if (elementIDs) + { + exodusIndex=this->GetExodusModelIndex(elementIDs, + (int)this->ModelMetadata->GetNumberOfBlocks(),part); + } + if (exodusIndex!=-1) + { + sprintf(charBuffer,"Exodus-%s-%d",blockNames[exodusIndex],part); + this->WriteStringToFile(charBuffer,fd); + } + else + { + this->WriteStringToFile("VTK Part",fd); + } + this->WriteStringToFile("coordinates",fd); + } + + //write the part header for data files + for (j=0;jWriteStringToFile("part",pointArrayFiles[j]); + this->WriteIntToFile(part,pointArrayFiles[j]); + this->WriteStringToFile("coordinates",pointArrayFiles[j]); + } + for (j=0;jWriteStringToFile("part",cellArrayFiles[j]); + this->WriteIntToFile(part,cellArrayFiles[j]); + } + + //list of VTK Node Indices per part + vtkstd::list NodesPerPart; + + //map that goes from NodeID to the order, used for element connectivity + vtkstd::map NodeIdToOrder; + + //get a list of all the nodes used for a particular part + for (j=0;jGetCell(CellsByPart[part][j]); + vtkIdList* points=cell->GetPointIds(); + for (int k=0;kGetNumberOfIds();k++) + { + NodesPerPart.push_back(points->GetId(k)); + } + } + + //remove the duplicate Node ID's + NodesPerPart.sort(); + NodesPerPart.unique(); + + //write the number of nodes + if (this->ShouldWriteGeometry()) + { + this->WriteIntToFile(NodesPerPart.size(),fd); + + + //write the Node ID's to the file + //also set up the NodeID->order map + int NodeCount=0; + for (iter2=NodesPerPart.begin();iter2!=NodesPerPart.end();iter2++) + { + this->WriteIntToFile(*iter2,fd); + NodeIdToOrder[*iter2]=NodeCount+1; + NodeCount++; + } + + + //EnSight format requires all the X's, then all the Y's, then all the Z's + //write the X Coordinates + + vtkPoints* inputPoints=input->GetPoints(); + for (iter2=NodesPerPart.begin();iter2!=NodesPerPart.end();iter2++) + { + this->WriteFloatToFile((float)(inputPoints->GetPoint(*iter2)[0]),fd); + } + for (iter2=NodesPerPart.begin();iter2!=NodesPerPart.end();iter2++) + { + this->WriteFloatToFile((float)(inputPoints->GetPoint(*iter2)[1]),fd); + } + for (iter2=NodesPerPart.begin();iter2!=NodesPerPart.end();iter2++) + { + this->WriteFloatToFile((float)(inputPoints->GetPoint(*iter2)[2]),fd); + } + + } + + //write the Node Data for this part + for (j=0;jGetPointData()->GetArray(j); + //figure out what type of data it is + int DataSize=DataArray->GetNumberOfComponents(); + + for (int CurrentDimension=0; + CurrentDimension::iterator k=NodesPerPart.begin(); + k!=NodesPerPart.end();k++) + { + this->WriteFloatToFile((float) + (DataArray-> + GetTuple(*k)[CurrentDimension]), + pointArrayFiles[j]); + } + } + } + + + + //now we need to sort the cell list by element type + //map is indexed by cell type has a vector of cell ID's + vtkstd::map > CellsByElement; + for (j=0;jGetCell(CellsByPart[part][j])->GetCellType(); + int ghostLevel=0; + if (GhostData) + { + ghostLevel=(int)(GhostData->GetTuple(CellsByPart[part][j])[0]); + if (ghostLevel>1) ghostLevel=1; + } + //we want to sort out the ghost cells from the normal cells + //so the element type will be ghostMultiplier*ghostLevel+elementType + CellType+=ghostLevel*GhostLevelMultiplier; + if (CellsByElement.count(CellType)==0) + { + CellsByElement[CellType]=vtkstd::vector < int >() ; + } + CellsByElement[CellType].push_back(CellsByPart[part][j]); + } + + //now we need to go through each element type that EnSight understands + vtkstd::vector elementTypes; + + //list the types that EnSight understands + //the noticeable absences are the ones without a fixed number of Nodes + //for the ghost cell types + elementTypes.push_back(VTK_VERTEX); + elementTypes.push_back(VTK_LINE); + elementTypes.push_back(VTK_TRIANGLE); + elementTypes.push_back(VTK_QUAD); + elementTypes.push_back(VTK_TETRA); + elementTypes.push_back(VTK_HEXAHEDRON); + elementTypes.push_back(VTK_PYRAMID); + elementTypes.push_back(VTK_QUADRATIC_EDGE); + elementTypes.push_back(VTK_QUADRATIC_TRIANGLE); + elementTypes.push_back(VTK_QUADRATIC_QUAD); + elementTypes.push_back(VTK_QUADRATIC_TETRA); + elementTypes.push_back(VTK_QUADRATIC_HEXAHEDRON); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_VERTEX); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_LINE); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_TRIANGLE); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_QUAD); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_TETRA); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_HEXAHEDRON); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_PYRAMID); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_QUADRATIC_EDGE); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_QUADRATIC_TRIANGLE); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_QUADRATIC_QUAD); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_QUADRATIC_TETRA); + elementTypes.push_back(this->GhostLevelMultiplier+VTK_QUADRATIC_HEXAHEDRON); + + //write out each type of element + if (this->ShouldWriteGeometry()) + { + for (j=0;j0) + { + //switch on element type to write correct type to file + this->WriteElementTypeToFile(elementType,fd); + + //number of elements + this->WriteIntToFile(CellsByElement[elementType].size(),fd); + + //element ID's + for (k=0;kWriteIntToFile(CellId,fd); + } + + //element conenctivity information + for (k=0;kGetCell(CellId)->GetPointIds(); + for (int m=0;mGetNumberOfIds();m++) + { + int PointId=PointIds->GetId(m); + this->WriteIntToFile(NodeIdToOrder[PointId],fd); + } + } + } + } + } + + //write the Cell Data for this part + for (j=0;jGetCellData()->GetArray(j); + //figure out what type of data it is + int DataSize=DataArray->GetNumberOfComponents(); + + for (int CurrentDimension=0; + CurrentDimension0) + { + this->WriteElementTypeToFile(elementTypes[k], + cellArrayFiles[j]); + for (unsigned int m=0;mWriteFloatToFile + ((float)(DataArray->GetTuple(CellsByElement[elementTypes[k]] + [m])[CurrentDimension]), + cellArrayFiles[j]); + } + } + } + } + } + + + } + + //now write the empty blocks + //use the block list in the exodus model if it exists, otherwise + //use the BlockID list if that exists. + + if (this->ModelMetadata) + { + blockNames=this->ModelMetadata->GetBlockElementType(); + elementIDs=this->ModelMetadata->GetBlockIds(); + this->NumberOfBlocks=(int)this->ModelMetadata->GetNumberOfBlocks(); + } + else if (this->BlockIDs) + { + elementIDs=this->BlockIDs; + } + + if (elementIDs) + { + //cout << "have " << this->NumberOfBlocks << " blocks " << endl; + for (i=0;iNumberOfBlocks;i++) + { + unsigned int j; + //figure out if the part was already written + int part=elementIDs[i]; + if ( vtkstd::find(partNumbers.begin(), partNumbers.end(), part) + == partNumbers.end() ) + { + //no information about the part was written to the output files + //so write some empty information + if (this->ShouldWriteGeometry()) + { + blockCount+=1; + this->WriteStringToFile("part",fd); + this->WriteIntToFile(part,fd); + + int exodusIndex = + this->GetExodusModelIndex(elementIDs,this->NumberOfBlocks,part); + + if (exodusIndex!=-1 && blockNames) + { + sprintf(charBuffer,"Exodus-%s-%d",blockNames[exodusIndex],part); + this->WriteStringToFile(charBuffer,fd); + } + else + { + this->WriteStringToFile("VTK Part",fd); + } + } + + //write the part header for data files + for (j=0;jWriteStringToFile("part",pointArrayFiles[j]); + this->WriteIntToFile(part,pointArrayFiles[j]); + } + for (j=0;jWriteStringToFile("part",cellArrayFiles[j]); + this->WriteIntToFile(part,cellArrayFiles[j]); + } + } + } + } + //cout << "wrote " << blockCount << "parts\n"; + if (this->TmpInput) + { + this->TmpInput->Delete(); + this->TmpInput = NULL; + } + + //close all the files + if (fd) + { + fclose(fd); + } + + for (ui=0;uiModelMetadata->Delete(); + this->ModelMetadata = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteCaseFile(int TotalTimeSteps) +{ + + vtkUnstructuredGrid *input=this->GetInput(); + int i; + + this->ComputeNames(); + + if (!this->BaseName) + { + vtkErrorMacro("A FileName or Path/BaseName must be specified."); + return; + } + + char charBuffer[512]; + sprintf(charBuffer,"%s/%s.%d.case",this->Path,this->BaseName,this->ProcessNumber); + + //open the geometry file + FILE *fd=NULL; + if (!(fd=OpenFile(charBuffer))) + { + return; + } + + this->WriteTerminatedStringToFile("FORMAT\n",fd); + this->WriteTerminatedStringToFile("type: ensight gold\n\n",fd); + this->WriteTerminatedStringToFile("\nGEOMETRY\n",fd); + + //write the geometry file + if (!this->TransientGeometry) + { + sprintf(charBuffer,"model: %s.%d.00000.geo\n",this->BaseName,this->ProcessNumber); + this->WriteTerminatedStringToFile(charBuffer,fd); + } + else + { + sprintf(charBuffer,"model: 1 %s.%d.*****.geo\n",this->BaseName,this->ProcessNumber); + this->WriteTerminatedStringToFile(charBuffer,fd); + } + + this->WriteTerminatedStringToFile("\nVARIABLE\n",fd); + + char fileBuffer[512]; + + //write the Node variable files + for (i=0;iGetPointData()->GetNumberOfArrays();i++) + { + + strcpy(fileBuffer,input->GetPointData()->GetArray(i)->GetName()); + // skip arrays that were not written + if (strcmp(fileBuffer,"GlobalElementId")==0) + { + continue; + } + if (strcmp(fileBuffer,"GlobalNodeId")==0) + { + continue; + } + if (strcmp(fileBuffer,"BlockId")==0) + { + continue; + } + this->SanitizeFileName(fileBuffer); + //figure out what kind of data it is + char SmallBuffer[16]; + switch(input->GetPointData()->GetArray(i)->GetNumberOfComponents()) + { + case(1): + strcpy(SmallBuffer,"scalar"); + break; + case(3): + strcpy(SmallBuffer,"vector"); + break; + case(6): + strcpy(SmallBuffer,"tensor"); + break; + case(9): + strcpy(SmallBuffer,"tensor9"); + break; + } + if (TotalTimeSteps<=1) + { + sprintf(charBuffer,"%s per node: %s_n %s.%d.00000_n.%s\n", + SmallBuffer, + fileBuffer, + this->BaseName, + this->ProcessNumber, + fileBuffer); + } + else + { + sprintf(charBuffer,"%s per node: 1 %s_n %s.%d.*****_n.%s\n", + SmallBuffer, + fileBuffer, + this->BaseName, + this->ProcessNumber, + fileBuffer); + + + } + this->WriteTerminatedStringToFile(charBuffer,fd); + } + + //write the cell variable files + for (i=0;iGetCellData()->GetNumberOfArrays();i++) + { + //figure out what kind of data it is + char SmallBuffer[16]; + + strcpy(fileBuffer,input->GetCellData()->GetArray(i)->GetName()); + // skip arrays that were not written + if (strcmp(fileBuffer,"GlobalElementId")==0) + { + continue; + } + if (strcmp(fileBuffer,"GlobalNodeId")==0) + { + continue; + } + if (strcmp(fileBuffer,"BlockId")==0) + { + continue; + } + this->SanitizeFileName(fileBuffer); + switch(input->GetCellData()->GetArray(i)->GetNumberOfComponents()) + { + case(1): + strcpy(SmallBuffer,"scalar"); + break; + case(3): + strcpy(SmallBuffer,"vector"); + break; + case(6): + strcpy(SmallBuffer,"tensor"); + break; + case(9): + strcpy(SmallBuffer,"tensor9"); + break; + } + if (TotalTimeSteps<=1) + { + sprintf(charBuffer,"%s per element: %s_c %s.%d.00000_c.%s\n", + SmallBuffer, + fileBuffer, + this->BaseName, + this->ProcessNumber, + fileBuffer); + } + else + { + sprintf(charBuffer,"%s per element: 1 %s_c %s.%d.*****_c.%s\n", + SmallBuffer, + fileBuffer, + this->BaseName, + this->ProcessNumber, + fileBuffer); + } + this->WriteTerminatedStringToFile(charBuffer,fd); + } + + //write time information if we have multiple timesteps + if (TotalTimeSteps>1) + { + this->WriteTerminatedStringToFile("\nTIME\n",fd); + this->WriteTerminatedStringToFile("time set: 1\n",fd); + sprintf(charBuffer,"number of steps: %d\n",TotalTimeSteps); + this->WriteTerminatedStringToFile(charBuffer,fd); + this->WriteTerminatedStringToFile("filename start number: 00000\n",fd); + this->WriteTerminatedStringToFile("filename increment: 00001\n",fd); + this->WriteTerminatedStringToFile("time values: \n",fd); + for (i=0;iModelMetadata) + { + timestep=this->ModelMetadata->GetTimeStepValues()[i]; + } + + sprintf(charBuffer,"%f ",timestep); + this->WriteTerminatedStringToFile(charBuffer,fd); + if (i%6==0 && i>0) + { + this->WriteTerminatedStringToFile("\n",fd); + } + } + } + + +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteSOSCaseFile(int numProcs) +{ + this->ComputeNames(); + + if (!this->BaseName) + { + vtkErrorMacro("A FileName or Path/BaseName must be specified."); + return; + } + + this->SanitizeFileName(this->BaseName); + + char charBuffer[512]; + sprintf(charBuffer,"%s/%s.case.sos",this->Path,this->BaseName); + + FILE *fd=NULL; + if (!(fd=OpenFile(charBuffer))) + return; + + this->WriteTerminatedStringToFile("FORMAT\n",fd); + this->WriteTerminatedStringToFile("type: master_server gold\n\n",fd); + + this->WriteTerminatedStringToFile("SERVERS\n",fd); + sprintf(charBuffer,"number of servers: %d\n\n",numProcs); + this->WriteTerminatedStringToFile(charBuffer,fd); + + //write the servers section with placeholders for the ensight server + //location and server name + int i=0; + for (i=0;iWriteTerminatedStringToFile(charBuffer,fd); + this->WriteTerminatedStringToFile("#-------\n",fd); + sprintf(charBuffer, "machine id: MID%05d\n",i); + this->WriteTerminatedStringToFile(charBuffer,fd); + + this->WriteTerminatedStringToFile("executable: MEX\n",fd); + sprintf(charBuffer, "data_path: %s\n",this->Path); + this->WriteTerminatedStringToFile(charBuffer,fd); + sprintf(charBuffer,"casefile: %s.%d.case\n\n",this->BaseName,i); + this->WriteTerminatedStringToFile(charBuffer,fd); + } + + +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteStringToFile(const char* cstring, FILE* file) +{ + char cbuffer[80]; + strncpy(cbuffer,cstring,80); + fwrite(cbuffer, sizeof(char),80,file); +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteTerminatedStringToFile(const char* cstring, FILE* file) +{ + char cbuffer[512]; + strncpy(cbuffer,cstring,512); + fwrite(cbuffer, sizeof(char),strlen(cbuffer),file); +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteIntToFile(const int i,FILE* file) +{ + //char cbuffer[80]; + //sprintf(cbuffer,"%d",i); + fwrite(&i, sizeof(int),1,file); +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteFloatToFile(const float f,FILE* file) +{ + //char cbuffer[80]; + //sprintf(cbuffer,"%d",i); + fwrite(&f, sizeof(float),1,file); +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::WriteElementTypeToFile(int elementType,FILE* fd) +{ + int ghostLevel=elementType/GhostLevelMultiplier; + elementType=elementType%GhostLevelMultiplier; + if (ghostLevel==0) + { + switch(elementType) + { + case(VTK_VERTEX): + this->WriteStringToFile("point",fd); + break; + case(VTK_LINE): + this->WriteStringToFile("bar2",fd); + break; + case(VTK_TRIANGLE): + this->WriteStringToFile("tria3",fd); + break; + case(VTK_QUAD): + this->WriteStringToFile("quad4",fd); + break; + case(VTK_TETRA): + this->WriteStringToFile("tetra4",fd); + break; + case(VTK_HEXAHEDRON): + this->WriteStringToFile("hexa8",fd); + break; + case(VTK_PYRAMID): + this->WriteStringToFile("pyramid5",fd); + break; + case(VTK_QUADRATIC_EDGE): + this->WriteStringToFile("bar3",fd); + break; + case(VTK_QUADRATIC_TRIANGLE): + this->WriteStringToFile("tria6",fd); + break; + case(VTK_QUADRATIC_QUAD): + this->WriteStringToFile("quad8",fd); + break; + case(VTK_QUADRATIC_TETRA): + this->WriteStringToFile("tetra10",fd); + break; + case(VTK_QUADRATIC_HEXAHEDRON): + this->WriteStringToFile("hexa20",fd); + break; + case(VTK_QUADRATIC_PYRAMID): + this->WriteStringToFile("pyramid13",fd); + break; + } + } + else + { + switch(elementType) + { + case(VTK_VERTEX): + this->WriteStringToFile("g_point",fd); + break; + case(VTK_LINE): + this->WriteStringToFile("g_bar2",fd); + break; + case(VTK_TRIANGLE): + this->WriteStringToFile("g_tria3",fd); + break; + case(VTK_QUAD): + this->WriteStringToFile("g_quad4",fd); + break; + case(VTK_TETRA): + this->WriteStringToFile("g_tetra4",fd); + break; + case(VTK_HEXAHEDRON): + this->WriteStringToFile("g_hexa8",fd); + break; + case(VTK_PYRAMID): + this->WriteStringToFile("g_pyramid5",fd); + break; + case(VTK_QUADRATIC_EDGE): + this->WriteStringToFile("g_bar3",fd); + break; + case(VTK_QUADRATIC_TRIANGLE): + this->WriteStringToFile("g_tria6",fd); + break; + case(VTK_QUADRATIC_QUAD): + this->WriteStringToFile("g_quad8",fd); + break; + case(VTK_QUADRATIC_TETRA): + this->WriteStringToFile("g_tetra10",fd); + break; + case(VTK_QUADRATIC_HEXAHEDRON): + this->WriteStringToFile("g_hexa20",fd); + break; + case(VTK_QUADRATIC_PYRAMID): + this->WriteStringToFile("g_pyramid13",fd); + break; + } + } +} + +//---------------------------------------------------------------------------- +bool vtkEnSightWriter::ShouldWriteGeometry() +{ + return ((this->TransientGeometry || (!this->TransientGeometry && this->TimeStep==0))); +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::SanitizeFileName(char* name) +{ + + char buffer[512]; + unsigned int i; + int BufferPosition=0; + for (i=0;iSetPath(path); + this->SetBaseName(base); +} + +//---------------------------------------------------------------------------- +void vtkEnSightWriter::ComputeNames() +{ + if (this->Path && this->BaseName) + { + return; + } + + if (!this->FileName) + { + this->DefaultNames(); + return; + } + + // FileName = Path/BaseName.digits.digits + + char *path = NULL; + char *base = NULL; + + char *f = this->FileName; + + while (!isgraph(*f)) f++; // find first printable character + + if (!*f) + { + // FileName is garbage + DefaultNames(); + return; + } + + char *buf = new char [strlen(f) + 1]; + strcpy(buf, f); + + char *slash = strrchr(buf, '/'); // final slash + + if (slash) + { + *slash = 0; + path = new char [strlen(buf) + 1]; + strcpy(path, buf); + f = slash + 1; + } + else + { + path = new char [4]; + strcpy(path, "./"); + + f = buf; + } + + char *firstChar = f; + while (*f && (*f != '.')) f++; + *f = 0; + + base = new char [strlen(firstChar) + 1]; + strcpy(base, firstChar); + + this->SetPath(path); + this->SetBaseName(base); + + delete [] buf; +} diff --git a/Parallel/vtkEnSightWriter.h b/Parallel/vtkEnSightWriter.h new file mode 100644 index 0000000..6f84692 --- /dev/null +++ b/Parallel/vtkEnSightWriter.h @@ -0,0 +1,163 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEnSightWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkEnSightWriter - write vtk unstructured grid data as an EnSight file +// .SECTION Description +// vtkEnSightWriter is a source object that writes binary +// unstructured grid data files in EnSight format. See EnSight Manual for +// format details + +// .SECTION Caveats +// Binary files written on one system may not be readable on other systems. +// Be sure to specify the endian-ness of the file when reading it into EnSight + +#ifndef __vtkEnSightWriter_h +#define __vtkEnSightWriter_h + +#include "vtkWriter.h" + +class vtkUnstructuredGrid; +class vtkModelMetadata; + +class VTK_PARALLEL_EXPORT vtkEnSightWriter : public vtkWriter +{ + +public: + vtkTypeRevisionMacro(vtkEnSightWriter,vtkWriter); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // + static vtkEnSightWriter *New(); + + //Description + //Specify which process this writer is + vtkSetMacro(ProcessNumber,int); + vtkGetMacro(ProcessNumber,int); + + // Description: + // Specify path of EnSight data files to write. + vtkSetStringMacro(Path); + vtkGetStringMacro(Path); + + // Description: + // Specify base name of EnSight data files to write. + vtkSetStringMacro(BaseName); + vtkGetStringMacro(BaseName); + + // Description: + // Specify the path and base name of the output files. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description + // Specify the Timestep that this data is for + vtkSetMacro(TimeStep,int); + vtkGetMacro(TimeStep,int); + + // Description + // Specify the number of ghost levels to include in output files + vtkSetMacro(GhostLevel,int); + vtkGetMacro(GhostLevel,int); + + // Description + // Specify whether the geoemtry changes each timestep + // if false, geometry is only written at timestep 0 + vtkSetMacro(TransientGeometry,bool); + vtkGetMacro(TransientGeometry,bool); + + //Description + //set the number of block ID's + vtkSetMacro(NumberOfBlocks,int); + vtkGetMacro(NumberOfBlocks,int); + + //Description + //set the array of Block ID's + //this class keeps a reference to the array and will not delete it + virtual void SetBlockIDs(int* val) + { + BlockIDs=val; + } + virtual int* GetBlockIDs() + { + return BlockIDs; + } + + // Description: + // Specify the input data or filter. + virtual void SetInput(vtkUnstructuredGrid *input); + virtual vtkUnstructuredGrid* GetInput(); + + // Description + // Writes the case file that EnSight is capable of reading + // The other data files must be written before the case file + // and the input must be one of the time steps + // variables must be the same for all time steps or the case file will be + // missing variables + virtual void WriteCaseFile(int TotalTimeSteps); + virtual void WriteSOSCaseFile(int NumProcs); + + // Description + // sets and gets the metadata + virtual void SetModelMetadata(vtkModelMetadata* model); + vtkGetObjectMacro(ModelMetadata, vtkModelMetadata); + +protected: + vtkEnSightWriter(); + virtual ~vtkEnSightWriter(); + + virtual int FillInputPortInformation(int port, vtkInformation* info); + + virtual void WriteData(); // method to allow this class to be instantiated and delegated to + + virtual void WriteStringToFile(const char* string, FILE* file); + virtual void WriteTerminatedStringToFile(const char* string, FILE* file); + virtual void WriteIntToFile(const int i,FILE* file); + virtual void WriteFloatToFile(const float f,FILE* file); + virtual void WriteElementTypeToFile(int ElementType, FILE* fd); + + virtual bool ShouldWriteGeometry(); + virtual void SanitizeFileName(char* name); + virtual FILE* OpenFile(char* name); + + void ComputeNames(); + void DefaultNames(); + + int GetExodusModelIndex(int *ElementArray,int NumberElements,int PartID); + + char *Path; + char *BaseName; + char *FileName; + int TimeStep; + int GhostLevelMultiplier; + int ProcessNumber; + int NumberOfProcesses; + int NumberOfBlocks; + int * BlockIDs; + bool TransientGeometry; + int GhostLevel; + vtkUnstructuredGrid* TmpInput; + vtkModelMetadata* ModelMetadata; + + vtkEnSightWriter(const vtkEnSightWriter&); // Not implemented. + void operator=(const vtkEnSightWriter&); // Not implemented. + +}; + +#endif diff --git a/Parallel/vtkExodusIIWriter.cxx b/Parallel/vtkExodusIIWriter.cxx new file mode 100644 index 0000000..9980bf5 --- /dev/null +++ b/Parallel/vtkExodusIIWriter.cxx @@ -0,0 +1,3418 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExodusIIWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkToolkits.h" +#include "vtkObjectFactory.h" +#include "vtkExodusIIWriter.h" +#include "vtkThreshold.h" +#include "vtkModelMetadata.h" +#include "vtkUnstructuredGrid.h" +#include "vtkDataArray.h" +#include "vtkFloatArray.h" +#include "vtkDoubleArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkLongArray.h" +#include "vtkUnsignedShortArray.h" +#include "vtkShortArray.h" +#include "vtkIdTypeArray.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include "vtkCellArray.h" +#include "vtkInformationVector.h" +#include "vtkInformation.h" +#ifdef VTK_USE_PARALLEL +#include "vtkMultiProcessController.h" +#endif +#include "vtkstd/map" + +#include +#include +#include + +// TODO - check for errors when there are no element or node variables + +// TODO - maybe check for ghost cells and omit them, or include them if +// the user says to do so + +// If we are building against a slightly older VTK version, +// these cell types are not defined, and won't occur in the input + +#ifndef VTK_QUADRATIC_WEDGE + #define VTK_PENTAGONAL_PRISM 15 + #define VTK_HEXAGONAL_PRISM 16 + #define VTK_QUADRATIC_WEDGE 26 + #define VTK_QUADRATIC_PYRAMID 27 +#endif + +#define FREE(x) if (x) {delete [] x; x = NULL;} +#define FREELIST(x, len) \ +{ \ + if (x) \ + { \ + for (i=0; iDelete(); \ + } \ + delete [] x; \ + } \ + x = NULL; \ +} + +vtkCxxRevisionMacro(vtkExodusIIWriter, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkExodusIIWriter); +vtkCxxSetObjectMacro(vtkExodusIIWriter, ModelMetadata, vtkModelMetadata); + +//---------------------------------------------------------------------------- + +vtkExodusIIWriter::vtkExodusIIWriter() +{ + this->FileName = NULL; + this->MyFileName = NULL; + this->ModelMetadata = NULL; + + this->PassDoubles = 0; + this->StoreDoubles = -1; // flag that this is not set + this->fid = -1; + + this->InputBlockIdsLength = 0; + this->InputBlockIds = NULL; + + this->InputNumberOfTimeSteps = 0; + this->InputCurrentTimeStep = -1; + this->InputTimeStepValues = NULL; + this->LastTimeStepWritten = -1; + + this->BlockIdArrayName = NULL; + this->GlobalElementIdArrayName = NULL; + this->GlobalNodeIdArrayName = NULL; + + this->BlockIdList = NULL; + this->GlobalElementIdList = NULL; + this->GlobalNodeIdList = NULL; + + this->LocalBlockIndexMap = NULL; + this->LocalElementIdMap = NULL; + this->LocalNodeIdMap = NULL; + + this->WriteOutBlockIdArray = 0; + this->WriteOutGlobalElementIdArray = 0; + this->WriteOutGlobalNodeIdArray = 0; + + this->InitializeBlockLists(); + this->InitializeVariableArrayNames(); + + this->BlockElementVariableTruthTable = NULL; + this->AllVariablesDefinedInAllBlocks = 0; + + this->NumberOfProcesses = 1; + this->MyRank = 0; + this->MyInput = NULL; + + this->GhostLevel = 0; + this->ErrorStatus = 0; +} +vtkExodusIIWriter::~vtkExodusIIWriter() +{ + if (!this->BlockIdArrayName && this->BlockIdList) + { + FREE(this->BlockIdList); // I created this + } + + this->SetFileName(NULL); + this->SetMyFileName(NULL); + this->SetModelMetadata(NULL); + this->SetBlockIdArrayName(NULL); + this->SetGlobalElementIdArrayName(NULL); + this->SetGlobalNodeIdArrayName(NULL); + + this->SetTimeStepValues(0, NULL); + + this->SetAllBlockIds(0, NULL); + + if (this->LocalElementIdMap) delete this->LocalElementIdMap; + if (this->LocalNodeIdMap) delete this->LocalNodeIdMap; + + this->ClearBlockLists(); + this->ClearVariableArrayNames(); + + FREE(this->BlockElementVariableTruthTable); + + if (this->MyInput) + { + this->MyInput->UnRegister(this); + this->MyInput->Delete(); + } +} + +int vtkExodusIIWriter::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info ) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + +//---------------------------------------------------------------------------- +// Input vtkUnstructuredGrid +//---------------------------------------------------------------------------- +vtkUnstructuredGrid *vtkExodusIIWriter::GetInput() +{ + vtkUnstructuredGrid *ug = NULL; + + if (this->MyInput) + { + ug = this->MyInput; + } + else + { + ug = vtkUnstructuredGrid::SafeDownCast(this->Superclass::GetInput()); + } + + return ug; +} +void vtkExodusIIWriter::SetInput(vtkUnstructuredGrid *ug) +{ + this->Superclass::SetInput(ug); +} +void vtkExodusIIWriter::SetPassDoubles() +{ + int i; + vtkUnstructuredGrid *ug = this->GetInput(); + if (!ug) return; + + // Determine whether we should pass single or double precision + // floats to the Exodus Library. We'll look through the arrays + // and points in the input and pick the precision of the + // first float we see. + + int da = -1; + + vtkCellData *cd = ug->GetCellData(); + if (cd) + { + int numCellArrays = cd->GetNumberOfArrays(); + for (i=0; iGetArray(i); + int type = a->GetDataType(); + + if (type == VTK_DOUBLE) + { + da = 1; + break; + } + else if (type == VTK_FLOAT) + { + da = 0; + break; + } + } + } + + if (da < 0) + { + vtkPointData *pd = ug->GetPointData(); + if (pd) + { + int numPtArrays = pd->GetNumberOfArrays(); + for (i=0; iGetArray(i); + int type = a->GetDataType(); + + if (type == VTK_DOUBLE) + { + da = 1; + break; + } + else if (type == VTK_FLOAT) + { + da = 0; + break; + } + } + } + } + + if (da < 0) + { + vtkPoints *pts = ug->GetPoints(); + + if (pts) + { + int type = pts->GetDataType(); + if (type == VTK_DOUBLE) + { + da = 1; + } + else if (type == VTK_FLOAT) + { + da = 0; + } + } + } + + this->PassDoubles = 0; + + if (da == 1) + { + this->PassDoubles = 1; + } + + if (this->StoreDoubles < 0) + { + // The default is to store in the + // same precision that appears in the input. + + this->StoreDoubles = this->PassDoubles; + } +} +void vtkExodusIIWriter::RemoveGhostCells() +{ + if (this->MyInput) + { + this->MyInput->UnRegister(this); + this->MyInput->Delete(); + this->MyInput = NULL; + } + + vtkUnstructuredGrid *ug = vtkUnstructuredGrid::New(); + ug->ShallowCopy(this->GetInput()); + + vtkDataArray *da = ug->GetCellData()->GetArray("vtkGhostLevels"); + + if (da) + { + vtkThreshold *t = vtkThreshold::New(); + t->SetInput(ug); + t->ThresholdByLower(0); + t->SetInputArrayToProcess( + 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_CELLS, "vtkGhostLevels"); + + t->Update(); + + this->MyInput = t->GetOutput(); + this->MyInput->Register(this); + t->Delete(); + + this->MyInput->GetCellData()->RemoveArray("vtkGhostLevels"); + this->MyInput->GetPointData()->RemoveArray("vtkGhostLevels"); + + this->GhostLevel = 1; + } + else + { + this->GhostLevel = 0; + } + + ug->Delete(); +} +//---------------------------------------------------------------------------- +// Values that can be set if there is no metadata +//---------------------------------------------------------------------------- +void vtkExodusIIWriter::SetTimeStepValues(int n, float *f) +{ + if (this->InputTimeStepValues) + { + delete [] this->InputTimeStepValues; + this->InputTimeStepValues = NULL; + } + + this->InputNumberOfTimeSteps = 0; + + if (n < 1) return; + + this->InputNumberOfTimeSteps = n; + + this->InputTimeStepValues = new float [n]; + + if (f) + { + memcpy(this->InputTimeStepValues, f, n * sizeof(float)); + } +} +void vtkExodusIIWriter::SetCurrentTimeStep(int ts) +{ + this->InputCurrentTimeStep = ts; +} +void vtkExodusIIWriter::SetAllBlockIds(int numEntries, int *blockIds) +{ + if (this->InputBlockIds) + { + delete [] this->InputBlockIds; + this->InputBlockIds = NULL; + this->InputBlockIdsLength = 0; + } + + if (numEntries <= 0) return; + + this->InputBlockIdsLength = numEntries; + this->InputBlockIds = new int [numEntries]; + + if (blockIds) + { + memcpy(this->InputBlockIds, blockIds, numEntries * sizeof(int)); + } +} +//------------------------------------------------------------------ +//------------------------------------------------------------------ + +void vtkExodusIIWriter::WriteData() +{ + int rc = 0; + if ( !this->FileName ) + { + vtkErrorMacro("No FileName specified."); + return; + } + + this->SetPassDoubles(); // does input contain floats or doubles + + this->RemoveGhostCells(); + + // Make sure we have all necessary information. If there is no + // vtkModelMetadata object, create one with reasonable defaults if + // that is possible. + + rc = this->CheckParameters(); + + if (rc) + { + return; + } + + if (this->LastTimeStepWritten >= 0) + { + this->OpenExodusFile(); + + rc = this->WriteNextTimeStep(); + + if (rc) + { + goto doneError; + } + + goto done; + } + + rc = this->CreateNewExodusFile(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData can't create exodus file"); + goto doneError; + } + + rc = this->WriteInitializationParameters(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData init params"); + goto doneError; + } + + rc = this->WriteQARecords(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData QA records"); + goto doneError; + } + + rc = this->WriteInformationRecords(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData information records"); + goto doneError; + } + + rc = this->WritePoints(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData points"); + goto doneError; + } + + rc = this->WriteCoordinateNames(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData coordinate names"); + goto doneError; + } + + rc = this->WriteGlobalPointIds(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData global point IDs"); + goto doneError; + } + + rc = this->WriteBlockInformation(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData block information"); + goto doneError; + } + + rc = this->WriteGlobalElementIds(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData global element IDs"); + goto doneError; + } + + + rc = this->WriteVariableArrayNames(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData variable array names"); + goto doneError; + } + + rc = this->WriteNodeSetInformation(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData can't node sets"); + goto doneError; + } + + rc = this->WriteSideSetInformation(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData can't side sets"); + goto doneError; + } + + rc = this->WriteProperties(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData can't properties"); + goto doneError; + } + + rc = this->WriteNextTimeStep(); + + if (rc) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteData results"); + goto doneError; + } + + goto done; + +doneError: + + this->SetErrorStatus(1); + +done: + this->SetModelMetadata(NULL); + this->CloseExodusFile(); +} + +//------------------------------------------------------------------ +// Check input parameters and set reasonable defaults +//------------------------------------------------------------------ +int vtkExodusIIWriter::CheckParameters() +{ + vtkUnstructuredGrid *input = this->GetInput(); + + // need input + + if (input == NULL) + { + vtkErrorMacro(<< "vtkExodusIIWriter, no input"); + return 1; + } + + this->NumberOfProcesses = 1; + this->MyRank = 0; + +#ifdef VTK_USE_PARALLEL + vtkMultiProcessController *c = vtkMultiProcessController::GetGlobalController(); + if (c) + { + this->NumberOfProcesses = c->GetNumberOfProcesses(); + this->MyRank = c->GetLocalProcessId(); + } + + if (this->GhostLevel > 0) + { + vtkWarningMacro(<< "ExodusIIWriter ignores ghost level request"); + } +#endif + + // What id arrays do we have + + int HaveGlobalElementIdArray = 0; + int HaveGlobalNodeIdArray = 0; + int HaveBlockIdArray = 0; + + vtkDataArray *da = NULL; + vtkCellData *cd = input->GetCellData(); + + if (this->BlockIdArrayName) + { + da = cd->GetArray(this->BlockIdArrayName); + + if (da) + { + HaveBlockIdArray = 1; + } + else + { + this->SetBlockIdArrayName(NULL); + } + } + + if (!HaveBlockIdArray) + { + da = cd->GetArray("BlockId"); + + if (da) + { + this->SetBlockIdArrayName("BlockId"); + HaveBlockIdArray = 1; + } + } + + if (HaveBlockIdArray) + { + da = cd->GetArray(this->BlockIdArrayName); + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + if (!ia) + { + vtkErrorMacro(<< "vtkExodusIIWriter, block ID array is not an integer array"); + return 1; + } + this->BlockIdList = ia->GetPointer(0); + } + + if (this->GlobalElementIdArrayName) + { + da = cd->GetArray(this->GlobalElementIdArrayName); + + if (da) + { + HaveGlobalElementIdArray = 1; + } + else + { + this->SetGlobalElementIdArrayName(NULL); + } + } + + if (!HaveGlobalElementIdArray) + { + da = cd->GetArray("GlobalElementId"); + + if (da) + { + this->SetGlobalElementIdArrayName("GlobalElementId"); + HaveGlobalElementIdArray = 1; + } + } + + if (HaveGlobalElementIdArray) + { + da = cd->GetArray(this->GlobalElementIdArrayName); + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + if (!ia) + { + vtkWarningMacro(<< + "vtkExodusIIWriter, element ID array is not an integer array, ignoring it"); + this->GlobalElementIdList = NULL; + HaveGlobalElementIdArray = 0; + } + else + { + this->GlobalElementIdList = ia->GetPointer(0); + } + } + + vtkPointData *pd = input->GetPointData(); + + if (this->GlobalNodeIdArrayName) + { + da = pd->GetArray(this->GlobalNodeIdArrayName); + + if (da) + { + HaveGlobalNodeIdArray = 1; + } + else + { + this->SetGlobalNodeIdArrayName(NULL); + } + } + + if (!HaveGlobalNodeIdArray) + { + da = pd->GetArray("GlobalNodeId"); + + if (da) + { + this->SetGlobalNodeIdArrayName("GlobalNodeId"); + HaveGlobalNodeIdArray = 1; + } + } + + if (HaveGlobalNodeIdArray) + { + da = pd->GetArray(this->GlobalNodeIdArrayName); + vtkIntArray *ia = vtkIntArray::SafeDownCast(da); + if (!ia) + { + vtkWarningMacro(<< + "vtkExodusIIWriter, node ID array is not an integer array, ignoring it"); + this->GlobalNodeIdList = 0; + HaveGlobalNodeIdArray = 0; + } + this->GlobalNodeIdList = ia->GetPointer(0); + } + + if (this->GetModelMetadata()) + { + // All of the information we'll need is in the ModelMetadata + + return 0; + } + + int hasPackedMetadata = vtkModelMetadata::HasMetadata(input); + + if (hasPackedMetadata) + { + // All the metadata has been packed into field arrays of the ugrid, + // probably by the vtkExodusReader or vtkPExodusReader. + + vtkModelMetadata *mmd = vtkModelMetadata::New(); + mmd->Unpack(input, 1); + + this->SetModelMetadata(mmd); + mmd->Delete(); + + return 0; + } + + int rc = this->CreateExodusModel(); // use sensible defaults + + if (rc) + { + return 1; + } + + return 0; +} + +vtkModelMetadata* vtkExodusIIWriter::GetOrCreateModelMetadata() +{ + this->CheckParameters(); + return this->GetModelMetadata(); +} + +int vtkExodusIIWriter::CreateExodusModel() +{ + // There is no metadata associated with this input. If we have enough + // information, we create reasonable defaults. + + int i, rc; + + if ((this->NumberOfProcesses > 1) && + ((!this->InputBlockIds) || (!this->BlockIdList))) + { + // Parallel apps must have a global list of all block IDs, plus a + // list of block IDs for each cell. + + vtkErrorMacro(<< "Can't proceed without metadata. Go back and request metadata from reader."); + return 1; + } + + vtkModelMetadata *em = vtkModelMetadata::New(); + + char *title = new char [MAX_LINE_LENGTH + 1]; + time_t currentTime = time(NULL); + struct tm *td = localtime(¤tTime); + char *stime = asctime(td); + + sprintf(title, "Created by vtkExodusIIWriter, %s", stime); + + em->SetTitle(title); + + char **dimNames = new char * [3]; + dimNames[0] = vtkExodusIIWriter::StrDupWithNew("X"); + dimNames[1] = vtkExodusIIWriter::StrDupWithNew("Y"); + dimNames[2] = vtkExodusIIWriter::StrDupWithNew("Z"); + em->SetCoordinateNames(3, dimNames); + + if (this->InputTimeStepValues) + { + em->SetTimeSteps(this->InputNumberOfTimeSteps, this->InputTimeStepValues); + } + + if (this->InputBlockIds && this->BlockIdList) + { + rc = this->CreateBlockIdInformation(em); + } + else + { + rc = this->CreateBlockIdInformationFromCellTypes(em); // single process only + } + + if (rc) + { + return 1; + } + + vtkUnstructuredGrid *ug = this->GetInput(); + + vtkCellData *cd = ug->GetCellData(); + int narrays = cd->GetNumberOfArrays(); + int nflattened = 0; + char **nms = NULL; + char **flattenedNames = NULL; + + if (narrays > 0) + { + nms = new char * [narrays]; + int *numComponents = new int [narrays]; + int *mapToOriginal = new int [narrays]; + nflattened = 0; + + for (i=0; iGetArray(i)->GetName()); + numComponents[i] = cd->GetArray(i)->GetNumberOfComponents(); + mapToOriginal[i] = nflattened; + nflattened += numComponents[i]; + } + + flattenedNames = vtkExodusIIWriter::FlattenOutVariableNames(narrays, + nflattened, nms, numComponents); + + em->SetElementVariableInfo(nflattened, flattenedNames, + narrays, nms, numComponents, mapToOriginal); + + int nblocks = em->GetNumberOfBlocks(); // computed in CreateBlockIdInfo* + int *blockSize = em->GetBlockNumberOfElements(); + + int *tt = new int [nblocks * nflattened]; + + + int index = 0; + for (int blockNum=0; blockNum 0) + { + tt[index++] = 1; // truth table, all ON by default + } + else + { + tt[index++] = 0; + } + } + } + em->SetElementVariableTruthTable(tt); + } + + vtkPointData *pd = ug->GetPointData(); + narrays = pd->GetNumberOfArrays(); + nflattened = 0; + nms = NULL; + flattenedNames = NULL; + + if (narrays > 0) + { + nms = new char * [narrays]; + int *numComponents = new int [narrays]; + int *mapToOriginal = new int [narrays]; + nflattened = 0; + + for (i=0; iGetArray(i)->GetName()); + numComponents[i] = pd->GetArray(i)->GetNumberOfComponents(); + mapToOriginal[i] = nflattened; + nflattened += numComponents[i]; + } + + flattenedNames = vtkExodusIIWriter::FlattenOutVariableNames(narrays, + nflattened, nms, numComponents); + + em->SetNodeVariableInfo(nflattened, flattenedNames, + narrays, nms, numComponents, mapToOriginal); + } + + this->SetModelMetadata(em); + em->Delete(); + + return 0; +} +char **vtkExodusIIWriter::FlattenOutVariableNames( + int narrays, int nScalarArrays, char **nms, int *numComponents) +{ + int i; + char **newNames = new char * [nScalarArrays]; + char **nextName = newNames; + + for (i=0; i MAX_STR_LENGTH-2) + { + nms[i][MAX_STR_LENGTH-2] = '\0'; + } + + vtkExodusIIWriter::CreateNamesForScalarArrays(nms[i], nextName, numComponents[i]); + + nextName += numComponents[i]; + } + + return newNames; +} +void vtkExodusIIWriter::CreateNamesForScalarArrays(const char *root, char **nms, int numComponents) +{ + int next = 0; + + if (numComponents == 1) + { + nms[next++] = vtkExodusIIWriter::StrDupWithNew(root); + } + else if (numComponents <= 3) + { + char *n = new char [MAX_STR_LENGTH + 1]; + sprintf(n, "%s_X", root); + nms[next++] = n; + + n = new char [MAX_STR_LENGTH + 1]; + sprintf(n, "%s_Y", root); + nms[next++] = n; + + if (numComponents == 3) + { + n = new char [MAX_STR_LENGTH + 1]; + sprintf(n, "%s_Z", root); + nms[next++] = n; + } + } + else + { + for (int j=0; jGetInput(); + vtkUnsignedCharArray *cellTypes = ug->GetCellTypesArray(); + vtkIdType ncells = ug->GetNumberOfCells(); + + int nblocks = this->InputBlockIdsLength; + int i; + + if (nblocks < 1) return 1; + + em->SetNumberOfBlocks(nblocks); + em->SetBlockIds(this->InputBlockIds); + + char **blockNames = new char * [nblocks]; + int *numElements = new int [nblocks]; + int *numNodesPerElement = new int [nblocks]; + int *numAttributes = new int [nblocks]; + + vtkstd::map idxMap; + vtkstd::map::iterator it; + + for (i=0; iInputBlockIds[i]; + + idxMap.insert(vtkstd::map::value_type(id, i)); + + int cellType = + vtkExodusIIWriter::FindCellType(id, this->BlockIdList, + cellTypes->GetPointer(0), ncells); + + blockNames[i] = vtkExodusIIWriter::GetCellTypeName(cellType); + numElements[i] = 0; + numNodesPerElement[i] = 0; + numAttributes[i] = 0; + } + + int *bids = this->BlockIdList; + + int err=0; + + for (i=0; isecond; + + int numNodes = ug->GetCell(i)->GetNumberOfPoints(); + + if (numElements[idx] == 0) + { + numNodesPerElement[idx] = numNodes; + } + else if (numNodes != numNodesPerElement[idx]) + { + err=1; + vtkErrorMacro(<< + "Each cell in a block must have the same number of points"); + break; + } + + numElements[idx]++; + } + + if (err) + { + FREELIST(blockNames, nblocks); + delete [] numElements; + delete [] numNodesPerElement; + delete [] numAttributes; + } + else + { + em->SetBlockElementType(blockNames); + em->SetBlockNumberOfElements(numElements); + em->SetBlockNodesPerElement(numNodesPerElement); + em->SetBlockNumberOfAttributesPerElement(numAttributes); + } + + return err; +} +int vtkExodusIIWriter::CreateBlockIdInformationFromCellTypes(vtkModelMetadata *em) +{ + int i; + vtkUnstructuredGrid *ug = this->GetInput(); + int ncells = ug->GetNumberOfCells(); + vtkUnsignedCharArray *cellTypes = ug->GetCellTypesArray(); + unsigned char *ct = cellTypes->GetPointer(0); + int nTypes = 0; + + vtkstd::map idxMap; + vtkstd::map::iterator it; + + for (i=0; i::iterator, bool> inserted = + idxMap.insert(vtkstd::map::value_type((int)ct[i], nTypes)); + + if (inserted.second) + { + nTypes++; + } + } + + int *types = new int [nTypes]; + + int min = 1; + + for (it = idxMap.begin(); it != idxMap.end(); ++it) + { + int typeNum = (int)it->first; + int idx = it->second; + + types[idx] = typeNum; + + if (typeNum < min) + { + min = typeNum; + } + } + + // slight problem - block IDs must be 1 or greater + + int offset = 0; + + if (min < 1) + { + offset = (min * -1) + 1; + } + + char **blockNames = new char * [nTypes]; + int *numElements = new int [nTypes]; + int *numNodesPerElement = new int [nTypes]; + int *numAttributes = new int [nTypes]; + + for (i=0; iSetNumberOfBlocks(nTypes); + em->SetBlockIds(types); + + this->BlockIdList = new int [ncells]; + + int err = 0; + + for (i=0; isecond; + + int numNodes = ug->GetCell(i)->GetNumberOfPoints(); + + if (numElements[idx] == 0) + { + numNodesPerElement[idx] = numNodes; + } + else if (numNodes != numNodesPerElement[idx]) + { + vtkErrorMacro(<< + "Exodus writer fails when same cell types have different number of nodes"); + err = 1; + break; + } + + this->BlockIdList[i] = cellType + offset; + numElements[idx]++; + } + + if (err) + { + FREELIST(blockNames, nTypes); + delete [] numElements; + delete [] numNodesPerElement; + delete [] numAttributes; + } + else + { + em->SetBlockElementType(blockNames); + em->SetBlockNumberOfElements(numElements); + em->SetBlockNodesPerElement(numNodesPerElement); + em->SetBlockNumberOfAttributesPerElement(numAttributes); + } + + return err; +} +char *vtkExodusIIWriter::GetCellTypeName(int t) +{ + if (MAX_STR_LENGTH < 32) return NULL; + char *nm = new char [MAX_STR_LENGTH + 1]; + + switch (t) + { + case VTK_EMPTY_CELL: + strcpy(nm, "empty cell"); + break; + case VTK_VERTEX: + strcpy(nm, "vertex"); + break; + case VTK_POLY_VERTEX: + strcpy(nm, "polyvertex"); + break; + case VTK_LINE: + strcpy(nm, "line"); + break; + case VTK_POLY_LINE: + strcpy(nm, "polyline"); + break; + case VTK_TRIANGLE: + strcpy(nm, "TRIANGLE"); + break; + case VTK_TRIANGLE_STRIP: + strcpy(nm, "triangle strip"); + break; + case VTK_POLYGON: + strcpy(nm, "polygon"); + break; + case VTK_PIXEL: + strcpy(nm, "pixel"); + break; + case VTK_QUAD: + strcpy(nm, "quad"); + break; + case VTK_TETRA: + strcpy(nm, "TETRA"); + break; + case VTK_VOXEL : + strcpy(nm, "voxel"); + break; + case VTK_HEXAHEDRON: + strcpy(nm, "HEX"); + break; + case VTK_WEDGE: + strcpy(nm, "wedge"); + break; + case VTK_PYRAMID: + strcpy(nm, "pyramid"); + break; + case VTK_PENTAGONAL_PRISM: + strcpy(nm, "pentagonal prism"); + break; + case VTK_HEXAGONAL_PRISM: + strcpy(nm, "hexagonal prism"); + break; + case VTK_QUADRATIC_EDGE: + strcpy(nm, "quadratic edge"); + break; + case VTK_QUADRATIC_TRIANGLE: + strcpy(nm, "quadratic triangle"); + break; + case VTK_QUADRATIC_QUAD: + strcpy(nm, "quadratic quad"); + break; + case VTK_QUADRATIC_TETRA: + strcpy(nm, "quadratic tetra"); + break; + case VTK_QUADRATIC_HEXAHEDRON: + strcpy(nm, "quadratic hexahedron"); + break; + case VTK_QUADRATIC_WEDGE: + strcpy(nm, "quadratic wedge"); + break; + case VTK_QUADRATIC_PYRAMID: + strcpy(nm, "quadratic pyramid"); + break; + case VTK_CONVEX_POINT_SET: + strcpy(nm, "convex point set"); + break; + case VTK_PARAMETRIC_CURVE: + strcpy(nm, "parametric curve"); + break; + case VTK_PARAMETRIC_SURFACE: + strcpy(nm, "parametric surface"); + break; + case VTK_PARAMETRIC_TRI_SURFACE: + strcpy(nm, "parametric tri surface"); + break; + case VTK_PARAMETRIC_QUAD_SURFACE: + strcpy(nm, "parametric quad surface"); + break; + case VTK_PARAMETRIC_TETRA_REGION: + strcpy(nm, "parametric tetra region"); + break; + case VTK_PARAMETRIC_HEX_REGION: + strcpy(nm, "paramertric hex region"); + break; + default: + strcpy(nm, "unknown cell type"); + break; + } + + return nm; +} +//------------------------------------------------------------------ +// Open or create an Exodus II file +//------------------------------------------------------------------ +void vtkExodusIIWriter::CloseExodusFile() +{ + if (this->fid >= 0) + { + ex_close(this->fid); + this->fid = -1; + return; + } +} +int vtkExodusIIWriter::OpenExodusFile() +{ + this->CloseExodusFile(); + + int compWordSize= (this->PassDoubles ? sizeof(double) : sizeof(float)); + int IOWordSize = (this->StoreDoubles ? sizeof(double) : sizeof(float)); + float version = 0.0; + + this->fid = ex_open(this->MyFileName, EX_WRITE, &compWordSize, &IOWordSize, + &version); + + int fail = (this->fid < 0); + + return fail; +} +int vtkExodusIIWriter::CreateNewExodusFile() +{ + if (this->NumberOfProcesses == 1) + { + if (this->FileName) + { + this->SetMyFileName(this->GetFileName()); + } + else + { + this->SetMyFileName("./ExodusIIWriter.out.exo"); + } + } + else + { + char *nm = new char [1024]; + if (this->FileName == NULL) + { + sprintf(nm, "./ExodusIIWriter.exo.%04d.%04d", + this->NumberOfProcesses, this->MyRank); + } + else + { + sprintf(nm, "%s.%04d.%04d", this->FileName, + this->NumberOfProcesses, this->MyRank); + } + this->SetMyFileName(nm); + delete [] nm; + } + + int compWordSize= (this->PassDoubles ? sizeof(double) : sizeof(float)); + int IOWordSize = (this->StoreDoubles ? sizeof(double) : sizeof(float)); + + this->fid = ex_create(this->MyFileName, EX_CLOBBER, &compWordSize, &IOWordSize); + + int fail = (this->fid < 0); + + return fail; +} +//======================================================================== +// MAPPINGS +// Convert local to global IDs and vice versa +//======================================================================== + +int vtkExodusIIWriter::GetBlockLocalIndex(int id) +{ + if (!this->LocalBlockIndexMap) + { + this->LocalBlockIndexMap = new vtkstd::map; + + for (int i=0; iNumberOfElementBlocks; i++) + { + int gid = this->BlockIds[i]; + + this->LocalBlockIndexMap->insert(vtkstd::map::value_type(gid, i)); + } + } + + vtkstd::map::iterator mapit = this->LocalBlockIndexMap->find(id); + + if (mapit == this->LocalBlockIndexMap->end()) + { + return -1; + } + else + { + return mapit->second; + } +} +int vtkExodusIIWriter::GetElementLocalId(int id) +{ + if (!this->LocalElementIdMap) + { + vtkUnstructuredGrid *ug = this->GetInput(); + int ncells = ug->GetNumberOfCells(); + + this->LocalElementIdMap = new vtkstd::map; + + for (int i=0; iGlobalElementIdList[i]; + + this->LocalElementIdMap->insert(vtkstd::map::value_type(gid, i)); + } + } + + vtkstd::map::iterator mapit = this->LocalElementIdMap->find(id); + + if (mapit == this->LocalElementIdMap->end()) + { + return -1; + } + else + { + return mapit->second; + } +} +int vtkExodusIIWriter::GetNodeLocalId(int id) +{ + if (!this->LocalNodeIdMap) + { + vtkUnstructuredGrid *ug = this->GetInput(); + int npoints = ug->GetNumberOfPoints(); + + this->LocalNodeIdMap = new vtkstd::map; + + for (int i=0; iGlobalNodeIdList[i]; + + this->LocalNodeIdMap->insert(vtkstd::map::value_type(gid, i)); + } + } + + vtkstd::map::iterator mapit = this->LocalNodeIdMap->find(id); + + if (mapit == this->LocalNodeIdMap->end()) + { + return -1; + } + else + { + return mapit->second; + } +} +//======================================================================== +// VARIABLE ARRAYS: +// CONVERT VECTOR ARRAYS TO APPROPRIATELY NAMED SCALAR ARRAYS +//======================================================================== + +void vtkExodusIIWriter::InitializeVariableArrayNames() +{ + this->InputElementArrayNames = NULL; + this->OutputElementArrayNames = NULL; + this->InputElementArrayComponent = NULL; + this->NumberOfScalarElementArrays = 0; + + this->InputNodeArrayNames = NULL; + this->OutputNodeArrayNames = NULL; + this->InputNodeArrayComponent = NULL; + this->NumberOfScalarNodeArrays = 0; +} +void vtkExodusIIWriter::ClearVariableArrayNames() +{ + int i; + int n = this->NumberOfScalarElementArrays; + + FREELIST(this->InputElementArrayNames, n); + FREELIST(this->OutputElementArrayNames, n); + FREE(this->InputElementArrayComponent); + this->NumberOfScalarElementArrays = 0; + + n = this->NumberOfScalarNodeArrays; + + FREELIST(this->InputNodeArrayNames, n); + FREELIST(this->OutputNodeArrayNames, n); + FREE(this->InputNodeArrayComponent); + this->NumberOfScalarNodeArrays = 0; +} + +int vtkExodusIIWriter::WriteVariableArrayNames() +{ + int i, j; + int rc = 0; + + this->ClearVariableArrayNames(); + + vtkUnstructuredGrid *ug = this->GetInput(); + vtkModelMetadata *mmd = this->GetModelMetadata(); + + // 1. We convert vector arrays to individual scalar arrays, using + // their original names if we have those. + // 2. For the element variables, create the element/block truth table. + + int checkAndSkipEltIds = 0; + int checkAndSkipNodeIds = 0; + int checkAndSkipBlockIds = 0; + + if (this->GlobalElementIdArrayName && !this->WriteOutGlobalElementIdArray) + { + checkAndSkipEltIds = 1; + } + if (this->GlobalNodeIdArrayName && !this->WriteOutGlobalNodeIdArray) + { + checkAndSkipNodeIds = 1; + } + if (this->BlockIdArrayName && !this->WriteOutBlockIdArray) + { + checkAndSkipBlockIds = 1; + } + + // CELL (ELEMENT) VARIABLES + + vtkCellData *cd = ug->GetCellData(); + int numCellArrays = cd->GetNumberOfArrays(); + int numCellScalars = 0; + int *skipCellArray = NULL; + + if (numCellArrays > 0) + { + skipCellArray = new int [numCellArrays]; + memset(skipCellArray, 0, sizeof(int) * numCellArrays); + + for (i=0; iGetArray(i)->GetName(); + if (!strcmp(nm, this->GlobalElementIdArrayName)) + { + skipCellArray[i] = 1; + continue; + } + } + if (checkAndSkipBlockIds) + { + const char *nm = cd->GetArray(i)->GetName(); + if (!strcmp(nm, this->BlockIdArrayName)) + { + skipCellArray[i] = 1; + continue; + } + } + + int numComponents = cd->GetArray(i)->GetNumberOfComponents(); + numCellScalars += numComponents; + } + + if (numCellScalars > 0) + { + this->InputElementArrayNames = new char * [numCellScalars]; + this->OutputElementArrayNames = new char * [numCellScalars]; + this->InputElementArrayComponent = new int [numCellScalars]; + + char **tempNames = new char * [numCellScalars]; + + int nextScalar = 0; + + for (i=0; iGetArray(i); + + this->SetNewElementVariableNames(da, tempNames); + + int numComponents = da->GetNumberOfComponents(); + const char *arrayName = da->GetName(); + + for (j=0; jInputElementArrayComponent[nextScalar] = j; + this->InputElementArrayNames[nextScalar] = + vtkExodusIIWriter::StrDupWithNew(arrayName); + this->OutputElementArrayNames[nextScalar] = tempNames[j]; + + nextScalar++; + } + } + delete [] tempNames; + } + delete [] skipCellArray; + } + + this->NumberOfScalarElementArrays = numCellScalars; + + // BLOCK/ELEMENT TRUTH TABLE + + int nblocks = mmd->GetNumberOfBlocks(); + int nelementVars = this->NumberOfScalarElementArrays; + int ttsize = nblocks * nelementVars; + int allDefined = 1; + int ttValue = 0; + + if (ttsize > 0) + { + this->BlockElementVariableTruthTable = new int [ttsize]; + int *tt = this->BlockElementVariableTruthTable; + + for (i=0; iNumberOfElementsPerBlock[i] == 0) + { + ttValue = 0; + } + else + { + ttValue = mmd->ElementVariableIsDefinedInBlock( + this->OutputElementArrayNames[j], this->BlockIds[i]); + } + + *tt++ = ttValue; + + if (allDefined && (ttValue == 0)) + { + allDefined = 0; + } + } + } + } + + this->AllVariablesDefinedInAllBlocks = allDefined; + + if (numCellScalars > 0) + { + rc = ex_put_var_param(this->fid, "E", numCellScalars); + + if (rc == 0) + { + rc = ex_put_var_names(this->fid, "E", numCellScalars, + this->OutputElementArrayNames); + + if (rc == 0) + { + rc = ex_put_elem_var_tab(this->fid, this->NumberOfElementBlocks, + numCellScalars, this->BlockElementVariableTruthTable); + } + } + + if (rc < 0) + { + vtkErrorMacro(<< + "vtkExodusIIWriter::WriteVariableArrayNames cell variables"); + return 1; + } + } + + // POINT (NODE) VARIABLES + + vtkPointData *pd = ug->GetPointData(); + int numPointArrays = pd->GetNumberOfArrays(); + int numPointScalars = 0; + int *skipPointArray = NULL; + + if (numPointArrays > 0) + { + skipPointArray = new int [numPointArrays]; + memset(skipPointArray, 0, sizeof(int) * numPointArrays); + + for (i=0; iGetArray(i)->GetName(); + if (!strcmp(nm, this->GlobalNodeIdArrayName)) + { + skipPointArray[i] = 1; + continue; + } + } + + int numComponents = pd->GetArray(i)->GetNumberOfComponents(); + numPointScalars += numComponents; + } + + if (numPointScalars > 0) + { + this->InputNodeArrayNames = new char * [numPointScalars]; + this->OutputNodeArrayNames = new char * [numPointScalars]; + this->InputNodeArrayComponent = new int [numPointScalars]; + + char **tempNames = new char * [numPointScalars]; + + int nextScalar = 0; + + for (i=0; iGetArray(i); + + this->SetNewNodeVariableNames(da, tempNames); + + int numComponents = da->GetNumberOfComponents(); + const char *arrayName = da->GetName(); + + for (j=0; jInputNodeArrayComponent[nextScalar] = j; + this->InputNodeArrayNames[nextScalar] = + vtkExodusIIWriter::StrDupWithNew(arrayName); + this->OutputNodeArrayNames[nextScalar] = tempNames[j]; + + nextScalar++; + } + } + + delete [] tempNames; + } + + delete [] skipPointArray; + } + + this->NumberOfScalarNodeArrays = numPointScalars; + + if (numPointScalars > 0) + { + rc = ex_put_var_param(this->fid, "N", numPointScalars); + + if (rc == 0) + { + rc = ex_put_var_names(this->fid, "N", numPointScalars, + this->OutputNodeArrayNames); + } + + if (rc < 0) + { + vtkErrorMacro(<< + "vtkExodusIIWriter::WriteVariableArrayNames point variables"); + return 1; + } + } + + // GLOBAL VARIABLES + + int ngvars = mmd->GetNumberOfGlobalVariables(); + + if (ngvars > 0) + { + char **names = mmd->GetGlobalVariableNames(); + + rc = ex_put_var_param(this->fid, "G", ngvars); + + if (rc == 0) + { + rc = ex_put_var_names(this->fid, "G", ngvars, names); + } + + if (rc < 0) + { + vtkErrorMacro(<< + "vtkExodusIIWriter::WriteVariableArrayNames global variables"); + return 1; + } + } + + return 0; +} +void vtkExodusIIWriter::SetNewNodeVariableNames(vtkDataArray *da, char **nm) +{ + int i; + int numComp = da->GetNumberOfComponents(); + + vtkModelMetadata *em = this->GetModelMetadata(); + + const char *arrayName = da->GetName(); + + if (numComp == 1) + { + nm[0] = vtkExodusIIWriter::StrDupWithNew(arrayName); + return; + } + + char *orig = em->FindOriginalNodeVariableName(arrayName, 0); + + if (!orig) + { + // just make up sensible names for the component arrays + vtkExodusIIWriter::CreateNamesForScalarArrays(arrayName, nm, numComp); + return; + } + + int err = 0; + + for (i=0; iFindOriginalNodeVariableName(arrayName, comp); + + if (!orig ) + { + err = 1; // we'll just have to make up names + break; + } + nm[comp] = vtkExodusIIWriter::StrDupWithNew(orig); + } + } + + if (err) + { + for (i=0; iGetNumberOfComponents(); + + vtkModelMetadata *em = this->GetModelMetadata(); + + const char *arrayName = da->GetName(); + + if (numComp == 1) + { + nm[0] = vtkExodusIIWriter::StrDupWithNew(arrayName); + return; + } + + char *orig = em->FindOriginalElementVariableName(arrayName, 0); + + if (!orig) + { + // just make up sensible names for the component arrays + vtkExodusIIWriter::CreateNamesForScalarArrays(arrayName, nm, numComp); + return; + } + + int err = 0; + + for (i=0; iFindOriginalElementVariableName(arrayName, comp); + + if (!orig ) + { + err = 1; // we'll just have to make up names + break; + } + nm[comp] = vtkExodusIIWriter::StrDupWithNew(orig); + } + } + + if (err) + { + for (i=0; iGetPointer(0); \ + if (idx == NULL) \ + { \ + p += comp; \ + for (i=0; iGetNumberOfComponents(); + if (numComp <= comp) return NULL; + + int nvals = da->GetNumberOfTuples(); + + if (nvals < 1) return NULL; + + int type = da->GetDataType(); + + if ((type == VTK_DOUBLE) && (numComp == 1) && (idx == NULL)) + { + vtkDoubleArray *a = vtkDoubleArray::SafeDownCast(da); + return a->GetPointer(0); + } + + // converting to native type is much faster than doing GetTuple + + double *val = new double [nvals]; + + switch (type) + { + case VTK_DOUBLE: + COPY_COMPONENT(vtkDoubleArray, double, double) + break; + + case VTK_CHAR: + COPY_COMPONENT(vtkCharArray, char, double) + break; + + case VTK_UNSIGNED_CHAR: + COPY_COMPONENT(vtkUnsignedCharArray, unsigned char, double) + break; + + case VTK_SHORT: + COPY_COMPONENT(vtkShortArray, short, double) + break; + + case VTK_UNSIGNED_SHORT: + COPY_COMPONENT(vtkUnsignedShortArray, unsigned short, double) + break; + + case VTK_INT: + COPY_COMPONENT(vtkIntArray, int, double) + break; + + case VTK_UNSIGNED_INT: + COPY_COMPONENT(vtkUnsignedIntArray, unsigned int, double) + break; + + case VTK_LONG: + COPY_COMPONENT(vtkLongArray, long, double) + break; + + case VTK_UNSIGNED_LONG: + COPY_COMPONENT(vtkUnsignedLongArray, unsigned long, double) + break; + + case VTK_FLOAT: + COPY_COMPONENT(vtkFloatArray, float, double) + break; + + case VTK_ID_TYPE: + COPY_COMPONENT(vtkIdTypeArray, vtkIdType, double) + break; + + default: + vtkErrorMacro(<< "vtkExodusIIWriter::ExtractComponentD bad type"); + break; + } + + return val; +} +float *vtkExodusIIWriter::ExtractComponentF(vtkDataArray *da, int comp, int *idx) +{ + int i; + int numComp = da->GetNumberOfComponents(); + if (numComp < comp) return NULL; + + int nvals = da->GetNumberOfTuples(); + + if (nvals < 1) return NULL; + + float *val = new float [nvals]; + + int type = da->GetDataType(); + + if ((type == VTK_FLOAT) && (numComp == 1) && (idx == NULL)) + { + vtkFloatArray *a = vtkFloatArray::SafeDownCast(da); + return a->GetPointer(0); + } + + // converting to native type is much faster than doing GetTuple + + switch (type) + { + case VTK_FLOAT: + COPY_COMPONENT(vtkFloatArray, float, float) + break; + + case VTK_CHAR: + COPY_COMPONENT(vtkCharArray, char, float) + break; + + case VTK_UNSIGNED_CHAR: + COPY_COMPONENT(vtkUnsignedCharArray, unsigned char, float) + break; + + case VTK_SHORT: + COPY_COMPONENT(vtkShortArray, short, float) + break; + + case VTK_UNSIGNED_SHORT: + COPY_COMPONENT(vtkUnsignedShortArray, unsigned short, float) + break; + + case VTK_INT: + COPY_COMPONENT(vtkIntArray, int, float) + break; + + case VTK_UNSIGNED_INT: + COPY_COMPONENT(vtkUnsignedIntArray, unsigned int, float) + break; + + case VTK_LONG: + COPY_COMPONENT(vtkLongArray, long, float) + break; + + case VTK_UNSIGNED_LONG: + COPY_COMPONENT(vtkUnsignedLongArray, unsigned long, float) + break; + + case VTK_DOUBLE: + COPY_COMPONENT(vtkDoubleArray, double, float) + break; + + case VTK_ID_TYPE: + COPY_COMPONENT(vtkIdTypeArray, vtkIdType, float) + break; + + default: + vtkErrorMacro(<< "vtkExodusIIWriter::ExtractComponentF bad type"); + break; + } + + return val; +} +int vtkExodusIIWriter::GetTimeStepIndex() +{ + int ts = -1; + + if (this->InputCurrentTimeStep >= 0) + { + // User told writer which time step to call this results + // data when we write it out. + + ts = this->InputCurrentTimeStep; + } + else if (this->GetModelMetadata()->GetTimeStepValues()) + { + // The time step index is in the metadata, the same index as + // when the file was read in. + + ts = this->GetModelMetadata()->GetTimeStepIndex(); + } + + if (ts < 0) + { + // We don't have metadata and the user didn't specify anything + // to the writer. We just start at 1 and go up by 1 for each + // write. + + ts = this->LastTimeStepWritten + 1; + } + + this->LastTimeStepWritten = ts; + + return ts; +} + +float vtkExodusIIWriter::GetTimeStepValue(int ts) +{ + float val = (float)ts; // default + + vtkModelMetadata *mmd = this->GetModelMetadata(); + + float *tsv = mmd->GetTimeStepValues(); + int numts = mmd->GetNumberOfTimeSteps(); + int realTimeStep = mmd->GetTimeStepIndex(); + + if (numts > 0) + { + if (realTimeStep >= 0) + { + // It doesn't matter what time step we are saying it is + // in the output file, this is the actual time stamp + // associated with this results data. + + val = tsv[realTimeStep]; + } + else if ((ts >= 0) && (ts < numts)) + { + // We didn't have vtkModelMetadata, but the user of this writer + // input a list of time values. Here's the value for this time + // step index. + + val = tsv[ts]; + } + else if (ts >= numts) + { + // We didn't have vtkModelMetadata, but the user of this writer + // input a list of 1 or more time values. Here's the value for + // this time step index if we extrapolate from the last value. + + int extra = ts - numts + 1; + float endOfTime = tsv[numts - 1]; + float diff = endOfTime; + if (numts >= 2) + { + diff -= tsv[numts - 2]; + } + + val = endOfTime + (extra * diff); + } + } + + return val; +} + +int vtkExodusIIWriter::WriteNextTimeStep() +{ + int i, idIdx; + int rc = 0; + + vtkModelMetadata *mmd = this->GetModelMetadata(); + + int ts = this->GetTimeStepIndex(); + float tsv = this->GetTimeStepValue(ts); + + if (this->PassDoubles) + { + double dtsv = (double)tsv; + rc = ex_put_time(this->fid, ts + 1, &dtsv); + } + else + { + rc = ex_put_time(this->fid, ts + 1, &tsv); + } + + if (rc < 0) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteNextTimeStep time step values"); + return 1; + } + + vtkUnstructuredGrid *ug = this->GetInput(); + int nblocks = this->NumberOfElementBlocks; + int npoints = ug->GetNumberOfPoints(); + int nCellArrays = this->NumberOfScalarElementArrays; + int nPointArrays = this->NumberOfScalarNodeArrays; + int nGlobalVariables = mmd->GetNumberOfGlobalVariables(); + + // CELL VARIABLES + + for (i=0; iInputElementArrayNames[i]; + int component = this->InputElementArrayComponent[i]; + + vtkDataArray *da = ug->GetCellData()->GetArray(nameIn); + + int type = da->GetDataType(); + int size = da->GetNumberOfComponents(); + + // We may be able to pass the Exodus library a pointer right into + // the input's variable arrays. If not (we had to massage the arrays + // in some way) then deleteIt is TRUE, meaning we created a copy to + // be deleted. + + int deleteIt = ((size > 1) || + ((type != VTK_DOUBLE) && this->PassDoubles) || + ((type != VTK_FLOAT) && !this->PassDoubles) || + (this->ElementIndex != NULL)); + + if (this->PassDoubles) + { + double *vars = this->ExtractComponentD(da, component, this->ElementIndex); + + for (idIdx=0; idIdx < nblocks; idIdx++) + { + int numElts = this->NumberOfElementsPerBlock[idIdx]; + if (numElts < 1) continue; // no cells in this block + + int defined = this->BlockVariableTruthValue(idIdx, i); + if (!defined) continue; // var undefined in this block + + int id = this->BlockIds[idIdx]; + int first = this->BlockElementStart[idIdx]; + + rc = ex_put_elem_var(this->fid, ts + 1, i + 1, id, numElts, vars + first); + + if (rc < 0) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteNextTimeStep ex_put_elem_var"); + return 1; + } + } + if (deleteIt) + { + delete [] vars; + } + } + else + { + float *vars = this->ExtractComponentF(da, component, this->ElementIndex); + + for (idIdx=0; idIdx < nblocks; idIdx++) + { + int numElts = this->NumberOfElementsPerBlock[idIdx]; + if (numElts < 1) continue; // no cells in this block + + int defined = this->BlockVariableTruthValue(idIdx, i); + if (!defined) continue; // var undefined in this block + + int id = this->BlockIds[idIdx]; + int first = this->BlockElementStart[idIdx]; + + rc = ex_put_elem_var(this->fid, ts + 1, i + 1, id, numElts, vars + first); + + if (rc < 0) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteNextTimeStep ex_put_elem_var"); + return 1; + } + } + if (deleteIt) + { + delete [] vars; + } + } + } + + // POINT VARIABLES + + for (i=0; iInputNodeArrayNames[i]; + int component = this->InputNodeArrayComponent[i]; + + vtkDataArray *da = ug->GetPointData()->GetArray(nameIn); + + int type = da->GetDataType(); + int size = da->GetNumberOfComponents(); + + int deleteIt = ((size > 1) || + ((type != VTK_DOUBLE) && this->PassDoubles) || + ((type != VTK_FLOAT) && !this->PassDoubles)); + + if (this->PassDoubles) + { + double *vars = this->ExtractComponentD(da, component, NULL); + + rc = ex_put_nodal_var(this->fid, ts + 1, i + 1, npoints, vars); + if (deleteIt) + { + delete [] vars; + } + } + else + { + float *vars = this->ExtractComponentF(da, component, NULL); + + rc = ex_put_nodal_var(this->fid, ts + 1, i + 1, npoints, vars); + if (deleteIt) + { + delete [] vars; + } + } + + if (rc < 0) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteNextTimeStep ex_put_nodal_var"); + return 1; + } + } + + // GLOBAL VARIABLES + + if (nGlobalVariables > 0) + { + float *vals = mmd->GetGlobalVariableValue(); + + if (this->PassDoubles) + { + double *dvals = new double [nGlobalVariables]; + for (int ii=0; iifid, ts + 1, nGlobalVariables, dvals); + + delete [] dvals; + } + else + { + rc = ex_put_glob_vars(this->fid, ts + 1, nGlobalVariables, vals); + } + + if (rc < 0) + { + vtkErrorMacro(<< "vtkExodusIIWriter::WriteNextTimeStep ex_put_glob_vars"); + return 1; + } + } + + return 0; +} +int vtkExodusIIWriter::BlockVariableTruthValue(int blockIdx, int varIdx) +{ + int tt=0; + int nvars = this->NumberOfScalarElementArrays; + int nblocks = this->NumberOfElementBlocks; + + if (this->AllVariablesDefinedInAllBlocks) + { + tt = 1; + } + else if ( (blockIdx >= 0) && (blockIdx < nblocks) && + (varIdx >= 0) && (varIdx < nvars)) + { + tt = this->BlockElementVariableTruthTable[(blockIdx * nvars) + varIdx]; + } + else + { + vtkErrorMacro(<< "vtkExodusIIWriter::BlockVariableTruthValue invalid index"); + } + + return tt; +} + +//----------------------------------------------------------------------- +// Properties +//----------------------------------------------------------------------- +int vtkExodusIIWriter::WriteProperties() +{ + int rc = 0; + int i; + + vtkModelMetadata *em = this->GetModelMetadata(); + + int nbprop = em->GetNumberOfBlockProperties(); + int nnsprop = em->GetNumberOfNodeSetProperties(); + int nssprop = em->GetNumberOfSideSetProperties(); + + if (nbprop) + { + char **names = em->GetBlockPropertyNames(); + + // Exodus library "feature". By convention there is a property + // array called "ID", the value of which is the ID of the block, + // node set or side set. This property is special. For example, + // if you change the property value for a block, that block's + // block ID is changed. I had no idea *how* special this property + // was, however. If you use ex_put_prop_names to tell the library + // what your property names are, and "ID" happens to be one of those + // names, then the library fills out the whole property array for + // you. Then if you follow this call with ex_put_prop_array for + // each property array, including "ID", you get *two* arrays named + // "ID". This is not documented, and totally unexpected. + // + // ex_put_prop_names is not required, it's just more efficient to + // call it before all the ex_put_prop_array calls. So we are + // not going to call it. + // + // rc = ex_put_prop_names(this->fid, EX_ELEM_BLOCK, nbprop, names); + + if (rc >= 0) + { + int *values = em->GetBlockPropertyValue(); + + for (i=0; ifid, EX_ELEM_BLOCK, names[i], values); + if (rc) break; + values += this->NumberOfElementBlocks; + } + } + } + + if (!rc && nnsprop) + { + char **names = em->GetNodeSetPropertyNames(); + int nnsets = em->GetNumberOfNodeSets(); + + // rc = ex_put_prop_names(this->fid, EX_NODE_SET, nnsprop, names); + + if (rc >= 0) + { + int *values = em->GetNodeSetPropertyValue(); + + for (i=0; ifid, EX_NODE_SET, names[i], values); + if (rc) break; + values += nnsets; + } + } + } + + if (!rc && nssprop) + { + char **names = em->GetSideSetPropertyNames(); + int nssets = em->GetNumberOfSideSets(); + + // rc = ex_put_prop_names(this->fid, EX_SIDE_SET, nssprop, names); + + if (rc >= 0) + { + int *values = em->GetSideSetPropertyValue(); + + for (i=0; ifid, EX_SIDE_SET, names[i], values); + if (rc) break; + values += nssets; + } + } + } + + int fail = (rc < 0); + + return fail; +} +//----------------------------------------------------------------------- +// Side sets and node sets +//----------------------------------------------------------------------- +int vtkExodusIIWriter::WriteSideSetInformation() +{ + int rc= 0; + int i, j, k; + + vtkModelMetadata *em = this->GetModelMetadata(); + + int nssets = em->GetNumberOfSideSets(); + + if (nssets < 1) return 0; + + // If cells are written out to file in a different order than + // they appear in the input, we need a mapping from their internal + // id in the input to their internal id in the output. + + vtkstd::map newElementId; + vtkstd::map::iterator idIt; + + if (this->ElementIndex) + { + vtkUnstructuredGrid *ug = this->GetInput(); + int ncells = ug->GetNumberOfCells(); + + for (i=0; i::value_type(this->ElementIndex[i], i)); + } + } + + int nids = em->GetSumSidesPerSideSet(); + + if (nids < 1) + { + int *buf = new int [nssets]; + + memset(buf, 0, sizeof(int) * nssets); + + rc = ex_put_concat_side_sets(this->fid, em->GetSideSetIds(), + buf, buf, buf, buf, NULL, NULL, NULL); + + delete [] buf; + + return (rc < 0); + } + + int *ssSize = new int [nssets]; + int *ssNumDF = new int [nssets]; + int *ssIdIdx = new int [nssets]; + int *ssDFIdx = new int [nssets]; + + int ndf = em->GetSumDistFactPerSideSet(); + + int *idBuf = new int [nids]; + int *sideBuf = new int [nids]; + float *dfBuf = NULL; + double *dfBufD = NULL; + + if (ndf) + { + if (this->PassDoubles) + { + dfBufD = new double [ndf]; + } + else + { + dfBuf = new float [ndf]; + } + } + + int *emSsSize = em->GetSideSetSize(); + int *emIdIdx = em->GetSideSetListIndex(); + int *emDFIdx = em->GetSideSetDistributionFactorIndex(); + + int nextId = 0; + int nextDF = 0; + int outputInternalId = 0; + + for (i=0; iGetSideSetElementList() + emIdIdx[i]; + int *sides = em->GetSideSetSideList() + emIdIdx[i]; + + int *numDFPerSide = em->GetSideSetNumDFPerSide() + emIdIdx[i]; + float *df = NULL; + + if (ndf > 0) + { + df = em->GetSideSetDistributionFactors() + emDFIdx[i]; + } + + for (j=0; j< emSsSize[i]; j++) + { + // Have to check if this element is still in the ugrid. + // It may have been deleted since the ExodusModel was created. + + int lid = this->GetElementLocalId(ids[j]); + + if (lid >= 0) + { + ssSize[i]++; + + if (this->ElementIndex) + { + idIt = newElementId.find(lid); + outputInternalId = idIt->second + 1; + } + else + { + outputInternalId = lid + 1; + } + + idBuf[nextId] = outputInternalId; + sideBuf[nextId] = sides[j]; + + nextId++; + + if (numDFPerSide[j] > 0) + { + ssNumDF[i] += numDFPerSide[j]; + + if (this->PassDoubles) + { + for (k=0; k < numDFPerSide[j]; k++) + { + dfBufD[nextDF++] = (double)df[k]; + } + } + else + { + for (k=0; k < numDFPerSide[j]; k++) + { + dfBuf[nextDF++] = df[k]; + } + } + } + } + + if (df) df += numDFPerSide[j]; + } + } + + if (this->PassDoubles) + { + rc = ex_put_concat_side_sets(this->fid, em->GetSideSetIds(), + ssSize, ssNumDF, ssIdIdx, ssDFIdx, idBuf, sideBuf, dfBufD); + } + else + { + rc = ex_put_concat_side_sets(this->fid, em->GetSideSetIds(), + ssSize, ssNumDF, ssIdIdx, ssDFIdx, idBuf, sideBuf, dfBuf); + } + + delete [] ssSize; + delete [] ssNumDF; + delete [] ssIdIdx; + delete [] ssDFIdx; + delete [] idBuf; + delete [] sideBuf; + if (dfBuf) delete [] dfBuf; + else if (dfBufD) delete [] dfBufD; + + int fail = (rc < 0); + + return fail; +} +int vtkExodusIIWriter::WriteNodeSetInformation() +{ + int rc = 0; + int i, j; + + vtkModelMetadata *em = this->GetModelMetadata(); + + int nnsets = em->GetNumberOfNodeSets(); + + if (nnsets < 1) return 0; + + int nids = em->GetSumNodesPerNodeSet(); + + if (nids < 1) + { + int *buf = new int [nnsets]; + + memset(buf, 0, sizeof(int) * nnsets); + + rc = ex_put_concat_node_sets(this->fid, em->GetNodeSetIds(), + buf, buf, buf, buf, NULL, NULL); + + delete [] buf; + + return (rc < 0); + } + + int *nsSize = new int [nnsets]; + int *nsNumDF = new int [nnsets]; + int *nsIdIdx = new int [nnsets]; + int *nsDFIdx = new int [nnsets]; + + int ndf = em->GetSumDistFactPerNodeSet(); + + int *idBuf = new int [nids]; + float *dfBuf = NULL; + double *dfBufD = NULL; + + if (ndf) + { + if (this->PassDoubles) + { + dfBufD = new double [ndf]; + } + else + { + dfBuf = new float [ndf]; + } + } + + int *emNsSize = em->GetNodeSetSize(); + int *emNumDF = em->GetNodeSetNumberOfDistributionFactors(); + int *emIdIdx = em->GetNodeSetNodeIdListIndex(); + int *emDFIdx = em->GetNodeSetDistributionFactorIndex(); + + int nextId = 0; + int nextDF = 0; + + for (i=0; iGetNodeSetNodeIdList() + emIdIdx[i]; + float *df = em->GetNodeSetDistributionFactors() + emDFIdx[i]; + + for (j=0; j< emNsSize[i]; j++) + { + // Have to check if this node is still in the ugrid. + // It may have been deleted since the ExodusModel was created. + + int lid = this->GetNodeLocalId(ids[j]); + + if (lid < 0) continue; + + nsSize[i]++; + idBuf[nextId++] = lid + 1; + + if (emNumDF[i] > 0) + { + nsNumDF[i]++; + + if (this->PassDoubles) + { + dfBufD[nextDF++] = (double)df[j]; + } + else + { + dfBuf[nextDF++] = df[j]; + } + } + } + } + + if (this->PassDoubles) + { + rc = ex_put_concat_node_sets(this->fid, em->GetNodeSetIds(), + nsSize, nsNumDF, nsIdIdx, nsDFIdx, idBuf, dfBufD); + } + else + { + rc = ex_put_concat_node_sets(this->fid, em->GetNodeSetIds(), + nsSize, nsNumDF, nsIdIdx, nsDFIdx, idBuf, dfBuf); + } + + delete [] nsSize; + delete [] nsNumDF; + delete [] nsIdIdx; + delete [] nsDFIdx; + delete [] idBuf; + if (dfBuf) delete [] dfBuf; + else if (dfBufD) delete [] dfBufD; + + int fail = (rc < 0); + + return fail; +} + +//--------------------------------------------------------- +// Points and point IDs, element IDs +//--------------------------------------------------------- +int vtkExodusIIWriter::WriteCoordinateNames() +{ + vtkModelMetadata *em = this->GetModelMetadata(); + + int rc = ex_put_coord_names(this->fid, em->GetCoordinateNames()); + + int fail = (rc < 0); + + return fail; +} +int vtkExodusIIWriter::WriteGlobalPointIds() +{ + int rc = 0; + + if (this->GlobalNodeIdList) + { + rc = ex_put_node_num_map(this->fid, this->GlobalNodeIdList); + } + + int fail = ( rc < 0); + + return fail; +} +int vtkExodusIIWriter::WriteGlobalElementIds() +{ + int rc = 0; + + int *ids = this->GlobalElementIdList; + + if (ids) + { + if (this->ElementIndex) + { + vtkUnstructuredGrid *ug = this->GetInput(); + int ncells = ug->GetNumberOfCells(); + + int *newIds = new int [ncells]; + + for (int i=0; iElementIndex[i]]; + } + + ids = newIds; + } + + rc = ex_put_elem_num_map(this->fid, ids); + + if (ids != this->GlobalElementIdList) + { + delete [] ids; + } + } + + int fail = ( rc < 0); + + return fail; +} +int vtkExodusIIWriter::WritePoints() +{ + vtkUnstructuredGrid *ug = this->GetInput(); + if (!ug) return 1; + + vtkPoints *pts = ug->GetPoints(); + int npts = pts->GetNumberOfPoints(); + vtkDataArray *da = pts->GetData(); + + int type = pts->GetDataType(); + + int i = 0; + int fail = 0; + + if (this->PassDoubles) + { + double *px = new double [npts]; + double *py = new double [npts]; + double *pz = new double [npts]; + + if (type == VTK_DOUBLE) + { + vtkDoubleArray *a = vtkDoubleArray::SafeDownCast(da); + double *p = a->GetPointer(0); + + for (i=0; iGetComponent(i, 0); + py[i] = da->GetComponent(i, 1); + pz[i] = da->GetComponent(i, 2); + } + } + + int rc = ex_put_coord(this->fid, px, py, pz); + + fail = (rc < 0); + + delete [] px; + delete [] py; + delete [] pz; + } + else + { + float *px = new float [npts]; + float *py = new float [npts]; + float *pz = new float [npts]; + + if (type == VTK_FLOAT) + { + vtkFloatArray *a = vtkFloatArray::SafeDownCast(da); + float *p = a->GetPointer(0); + + for (i=0; iGetPointer(0); + + for (i=0; ifid, px, py, pz); + + fail = (rc < 0); + + delete [] px; + delete [] py; + delete [] pz; + } + + return fail; +} + +//--------------------------------------------------------- +// Initialization, QA, Title, information records +//--------------------------------------------------------- +int vtkExodusIIWriter::WriteQARecords() +{ + vtkModelMetadata *em = this->GetModelMetadata(); + + int nrecs = em->GetNumberOfQARecords(); + + if (nrecs > 0) + { + typedef char *p4[4]; + + p4 *qarecs = new p4 [nrecs]; + + for (int i=0; iGetQARecord(i, &qarecs[i][0], &qarecs[i][1], &qarecs[i][2], &qarecs[i][3]); + } + ex_put_qa(this->fid, nrecs, qarecs); + + delete [] qarecs; + } + + return 0; +} +int vtkExodusIIWriter::WriteInformationRecords() +{ + vtkModelMetadata *em = this->GetModelMetadata(); + + int nlines = em->GetNumberOfInformationLines(); + + if (nlines > 0) + { + char **lines = NULL; + + em->GetInformationLines(&lines); + + ex_put_info(this->fid, nlines, lines); + } + + return 0; +} + +int vtkExodusIIWriter::WriteInitializationParameters() +{ + vtkUnstructuredGrid *ug = this->GetInput(); + if (!ug) return 1; + + vtkModelMetadata *em = this->GetModelMetadata(); + + int dim = em->GetDimension(); + int nnodes = ug->GetNumberOfPoints(); + int ncells = ug->GetNumberOfCells(); + int nnsets = em->GetNumberOfNodeSets(); + int nssets = em->GetNumberOfSideSets(); + char *title = em->GetTitle(); + int numBlocks = em->GetNumberOfBlocks(); + + int rc = ex_put_init(this->fid, title, dim, nnodes, ncells, + numBlocks, nnsets, nssets); + + int fail = (rc < 0); + + return fail; +} +//======================================================================== +// BLOCKS +//======================================================================== +void vtkExodusIIWriter::InitializeBlockLists() +{ + this->NumberOfElementBlocks = 0; + this->BlockIds = NULL; + this->BlockElementType = NULL; + this->BlockElementStart = NULL; + this->ElementIndex = NULL; + this->NumberOfElementsPerBlock = NULL; + this->NumberOfNodesPerElementInBlock = NULL; + this->NumberOfAttributesPerElementInBlock = NULL; + this->BlockElementAttributesF = NULL; + this->BlockElementAttributesD = NULL; + this->BlockElementConnectivity = NULL; +} +void vtkExodusIIWriter::ClearBlockLists() +{ + int i; + int len = this->NumberOfElementBlocks; + + if (len == 0) return; + + FREELIST(this->BlockElementType, len); + FREELIST(this->BlockElementAttributesF, len); + FREELIST(this->BlockElementAttributesD, len); + FREELIST(this->BlockElementConnectivity, len); + + FREE(this->BlockIds); + FREE(this->BlockElementStart); + FREE(this->ElementIndex); + FREE(this->NumberOfElementsPerBlock); + FREE(this->NumberOfNodesPerElementInBlock); + FREE(this->NumberOfAttributesPerElementInBlock); + + if (this->LocalBlockIndexMap) + { + delete this->LocalBlockIndexMap; + this->LocalBlockIndexMap = NULL; + } + + this->NumberOfElementBlocks = 0; +} +int vtkExodusIIWriter::WriteBlockInformation() +{ + int i, j, rc; + vtkUnstructuredGrid *ug = this->GetInput(); + vtkModelMetadata *em = this->GetModelMetadata(); + + this->ClearBlockLists(); + + int nblocks = em->GetNumberOfBlocks(); + int ncells = ug->GetNumberOfCells(); + + int *ids = em->GetBlockIds(); + char **blockNames = em->GetBlockElementType(); + int *nodesPerElement = em->GetBlockNodesPerElement(); + int *numAttributes = em->GetBlockNumberOfAttributesPerElement(); + + this->NumberOfElementBlocks = nblocks; + + this->BlockIds = new int [nblocks]; + this->BlockElementType = new char * [nblocks]; + this->BlockElementStart = new int [nblocks]; + this->NumberOfElementsPerBlock = new int [nblocks]; + this->NumberOfNodesPerElementInBlock = new int [nblocks]; + this->NumberOfAttributesPerElementInBlock = new int [nblocks]; + + this->BlockElementConnectivity = new int * [nblocks]; + + if (this->PassDoubles) + { + this->BlockElementAttributesD = new double * [nblocks]; + } + else + { + this->BlockElementAttributesF = new float * [nblocks]; + } + + for (i=0; iNumberOfElementsPerBlock[i] = 0; + this->BlockElementStart[i] = -1; + + this->BlockIds[i] = (int)ids[i]; + this->BlockElementType[i] = vtkExodusIIWriter::StrDupWithNew(blockNames[i]); + this->NumberOfNodesPerElementInBlock[i] = nodesPerElement[i]; + this->NumberOfAttributesPerElementInBlock[i] = numAttributes[i]; + + this->BlockElementConnectivity[i] = NULL; + + if (this->PassDoubles) + { + this->BlockElementAttributesD[i] = NULL; + } + else + { + this->BlockElementAttributesF[i] = NULL; + } + } + + // Count the number of elements in each block - it's not necessarily + // the number in the ExodusModel because some cells may have been + // deleted. + // + // The elements in the input may not be in order by block, but we must + // write element IDs and element variables out to the Exodus file in + // order by block. Create a mapping if necessary, for an ordering by + // block to the ordering found in the input unstructured grid. + + int lastId = -1; + int idx = -1; + int needMapping = 0; + + for (i=0; iBlockIdList[i]; + + if (blockId != lastId) + { + idx = this->GetBlockLocalIndex(blockId); + } + + this->NumberOfElementsPerBlock[idx]++; + + if (!needMapping) + { + if (blockId != lastId) + { + int start = this->BlockElementStart[idx]; + if (start == -1) + { + this->BlockElementStart[idx] = i; + } + else + { + needMapping = 1; + } + } + } + lastId = blockId; + } + + if (needMapping) + { + // Element variables and global IDs are mixed up, not grouped + // by block as they must be when written out. + + this->ElementIndex = new int [ncells]; + + this->BlockElementStart[0] = 0; + + for (i=1; iBlockElementStart[i] = + this->BlockElementStart[i-1] + this->NumberOfElementsPerBlock[i-1]; + } + + int *blockCount = new int [nblocks]; + memset(blockCount, 0, sizeof(int) * nblocks); + + lastId = -1; + idx = -1; + + for (i=0; iBlockIdList[i]; + + if (blockId != lastId) + { + idx = this->GetBlockLocalIndex(blockId); + } + + int which = this->BlockElementStart[idx] + blockCount[idx]++; + + this->ElementIndex[which] = i; + + lastId = blockId; + } + + delete [] blockCount; + } + + // Write out the connectivity array and the attribute array. + + int *nodeCount = new int [nblocks]; + int *attCount = new int [nblocks]; + + // For each block, a map from element global ID to it's location + // within it's block in the ExodusModel object. + + vtkstd::map **eltIdx = new vtkstd::map * [nblocks]; + vtkstd::map::iterator eltIt; + + for (i=0; iNumberOfElementsPerBlock[i]; + int numAtts = this->NumberOfAttributesPerElementInBlock[i]; + int numNodes = this->NumberOfNodesPerElementInBlock[i]; + + if (numElts > 0) + { + this->BlockElementConnectivity[i] = new int [numElts * numNodes]; + + if (numAtts > 0) + { + if (this->PassDoubles) + { + this->BlockElementAttributesD[i] = new double [numElts * numAtts]; + } + else + { + this->BlockElementAttributesF[i] = new float [numElts * numAtts]; + } + + eltIdx[i] = this->BuildBlockElementSearchStructure(i); + } + } + } + + vtkCellArray *ca = ug->GetCells(); + vtkIdType *ptIds = ca->GetPointer(); + vtkIdTypeArray *loca = ug->GetCellLocationsArray(); + vtkIdType *loc = loca->GetPointer(0); + + float *att = em->GetBlockAttributes(); + int *attIdx = em->GetBlockAttributesIndex(); + + int skipAttributes=0; + lastId = -1; + idx = -1; + + for (i=0; iElementIndex ? this->ElementIndex[i] : i); + + int blockId = this->BlockIdList[nextIdx]; + + if (blockId != lastId) + { + idx = this->GetBlockLocalIndex(blockId); + lastId = blockId; + } + + // the block connectivity array + + vtkIdType ptListIdx = loc[nextIdx]; + + vtkIdType npts = ptIds[ptListIdx++]; + + for (vtkIdType p=0; pBlockElementConnectivity[idx][nodeCount[idx]++] = ExodusPointId; + } + + // the block element attributes + + int numAtts = this->NumberOfAttributesPerElementInBlock[idx]; + + if ((numAtts == 0) || skipAttributes) continue; + + if (!this->GlobalElementIdList) + { + vtkWarningMacro(<< + "Exodus writer must omit element block attributes, because there are no global element IDs"); + skipAttributes = 1; + break; + } + + int globalId = this->GlobalElementIdList[nextIdx]; + eltIt = eltIdx[idx]->find(globalId); + + if (eltIt == eltIdx[idx]->end()) + { + vtkWarningMacro(<< + "Exodus writer must omit element block attributes, because new elements were added"); + skipAttributes = 1; + break; + } + + int where = eltIt->second; + + float *eltAtt = att + // list of all blocks attribute values + attIdx[idx] + // location for this block + (where * numAtts); // location for the element in the block + + if (this->PassDoubles) + { + for (j=0; jBlockElementAttributesD[idx][attCount[idx]++] = (double)eltAtt[j]; + } + } + else + { + for (j=0; jBlockElementAttributesF[idx][attCount[idx]++] = eltAtt[j]; + } + } + } + + for (i=0; iNumberOfAttributesPerElementInBlock[i] = 0; + FREELIST(this->BlockElementAttributesD, nblocks); + FREELIST(this->BlockElementAttributesF, nblocks); + } + } + + // Now, finally, write out the block information + + int fail = 0; + + for (i=0; ifid, this->BlockIds[i], + this->BlockElementType[i], this->NumberOfElementsPerBlock[i], + this->NumberOfNodesPerElementInBlock[i], + this->NumberOfAttributesPerElementInBlock[i]); + + if (rc < 0) + { + fail = 1; + break; + } + } + + if (fail) + { + return 1; + } + + for (i=0; iNumberOfElementsPerBlock[i] > 0) + { + rc = ex_put_elem_conn(this->fid, this->BlockIds[i], + this->BlockElementConnectivity[i]); + + if (rc < 0) + { + fail = 1; + break; + } + + if (this->NumberOfAttributesPerElementInBlock[i] > 0) + { + if (this->PassDoubles) + { + rc = ex_put_elem_attr(this->fid, this->BlockIds[i], + this->BlockElementAttributesD[i]); + } + else + { + rc = ex_put_elem_attr(this->fid, this->BlockIds[i], + this->BlockElementAttributesF[i]); + } + + if (rc < 0) + { + fail = 1; + break; + } + } + } + } + + return fail; +} +vtkstd::map *vtkExodusIIWriter::BuildBlockElementSearchStructure(int block) +{ + // Create a map from an element global ID to it's location in + // the block array in the ExodusModel object. + + vtkModelMetadata *em = this->GetModelMetadata(); + + int *blockElts = em->GetBlockElementIdList(); + int *numElts = em->GetBlockNumberOfElements(); + int *listIdx = em->GetBlockElementIdListIndex(); + + vtkstd::map *eltMap = new vtkstd::map; + + int blockSize = numElts[block]; + + int *eltIds = blockElts + listIdx[block]; + + for (int i=0; iinsert(vtkstd::map::value_type(eltIds[i], i)); + } + + return eltMap; +} + +//---------------------------------------------------------------------------- +char *vtkExodusIIWriter::StrDupWithNew(const char *s) +{ + char *newstr = NULL; + + if (s) + { + int len = strlen(s); + if (len == 0) + { + newstr = new char [1]; + newstr[0] = '\0'; + } + else + { + newstr = new char [len + 1]; + strcpy(newstr, s); + } + } + + return newstr; +} +//---------------------------------------------------------------------------- +void vtkExodusIIWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkWriter::PrintSelf(os,indent); + + if (this->FileName) + { + os << indent << "FileName " << this->FileName << "\n"; + } + if (this->MyFileName) + { + os << indent << "MyFileName " << this->MyFileName << "\n"; + } + os << indent << "ErrorStatus " << this->ErrorStatus << endl; + os << indent << "StoreDoubles " << this->StoreDoubles << endl; + os << indent << "GhostLevel " << this->GhostLevel << endl; + + if (this->BlockIdArrayName) + { + os << indent << "BlockIdArrayName " << this->BlockIdArrayName << endl; + } + if (this->GlobalNodeIdArrayName) + { + os << indent << "GlobalNodeIdArrayName " << this->GlobalNodeIdArrayName << endl; + } + if (this->GlobalElementIdArrayName) + { + os << indent << "GlobalNodeIdArrayName " << this->GlobalNodeIdArrayName << endl; + } + + os << indent << "WriteOutBlockIdArray " << this->WriteOutBlockIdArray << endl; + os << indent << "WriteOutGlobalNodeIdArray " << this->WriteOutGlobalNodeIdArray << endl; + os << indent << "WriteOutGlobalElementIdArray " << this->WriteOutGlobalElementIdArray << endl; + + os << indent << "ModelMetadata " << this->ModelMetadata << endl; +} diff --git a/Parallel/vtkExodusIIWriter.h b/Parallel/vtkExodusIIWriter.h new file mode 100644 index 0000000..295c6dd --- /dev/null +++ b/Parallel/vtkExodusIIWriter.h @@ -0,0 +1,427 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExodusIIWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkExodusIIWriter - Write Exodus II files +// .SECTION Description +// This is a vtkWriter that writes it's vtkUnstructuredGrid +// input out to an Exodus II file. Go to http://endo.sandia.gov/SEACAS/ +// for more information about the Exodus II format. +// +// Exodus files contain much information that is not captured +// in a vtkUnstructuredGrid, such as time steps, information +// lines, node sets, and side sets. This information can be +// stored in a vtkModelMetadata object. +// +// The vtkExodusReader and vtkPExodusReader can create +// a vtkModelMetadata object and embed it in a vtkUnstructuredGrid +// in a series of field arrays. This writer searches for these +// field arrays and will use the metadata contained in them +// when creating the new Exodus II file. +// +// You can also explicitly give the vtkExodusIIWriter a +// vtkModelMetadata object to use when writing the file. +// +// In the absence of the information provided by vtkModelMetadata, +// if this writer is not part of a parallel application, we will use +// reasonable defaults for all the values in the output Exodus file. +// If you don't provide a block ID element array, we'll create a +// block for each cell type that appears in the unstructured grid. +// +// However if this writer is part of a parallel application (hence +// writing out a distributed Exodus file), then we need at the very +// least a list of all the block IDs that appear in the file. And +// we need the element array of block IDs for the input unstructured grid. +// +// In the absense of a vtkModelMetadata object, you can also provide +// time step information which we will include in the output Exodus +// file. +// +// .SECTION Caveats +// If the input floating point field arrays and point locations are all +// floats or all doubles, this class will operate more efficiently. +// Mixing floats and doubles will slow you down, because Exodus II +// requires that we write only floats or only doubles. +// +// We use the terms "point" and "node" interchangeably. +// Also, we use the terms "element" and "cell" interchangeably. +// + +#ifndef __vtkExodusIIWriter_h +#define __vtkExodusIIWriter_h + + +#include "vtkWriter.h" + +#include // For the map + +class vtkUnstructuredGrid; +class vtkFloatArray; +class vtkDoubleArray; +class vtkDataArray; +class vtkUnsignedCharArray; +class vtkIntArray; +class vtkModelMetadata; + +class VTK_PARALLEL_EXPORT vtkExodusIIWriter : public vtkWriter +{ +public: + static vtkExodusIIWriter *New(); + vtkTypeRevisionMacro(vtkExodusIIWriter,vtkWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify input which will be written out to the Exodus II file. + + void SetInput(vtkUnstructuredGrid *ug); + vtkUnstructuredGrid *GetInput(); + + // Description: + // Specify the vtkModelMetadata object which contains the Exodus file + // model information (metadata) absent in the vtkUnstructuredGrid. If you + // have this object, you don't need to set any other values before writing. + // (Just the FileName and the Input.) + // Note that the vtkExodusReader can create and attach a vtkModelMetadata + // object to it's output. If this has happened, the ExodusIIWriter will + // find it and use it. + + virtual void SetModelMetadata(vtkModelMetadata*); + vtkGetObjectMacro(ModelMetadata, vtkModelMetadata); + + // Description: + // By default, ModelMetadata is NULL until the Write() method is called, + // at which point the vtkExodusIIWriter will create a default metadata + // object. If you would like to obtain the metadata and modify it, rather + // than creating it yourself, you may call this function. If the + // metadata already exists (because it has been set by a call to SetModelMetadata + // or because it has been packed into the FieldData of the input mesh), + // that metadata will be returned. Otherwise, the vtkExodusIIWriter will + // create metadata using the input mesh as needed, set the metadata to + // that object, and return it. + vtkModelMetadata* GetOrCreateModelMetadata(); + + // Description: + // Name for the output file. If writing in parallel, the number + // of processes and the process rank will be appended to the name, + // so each process is writing out a separate file. + // If not set, this class will make up a file name. + + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // If StoreDoubles is ON, the floating point fields in the Exodus file + // will be double precision fields. The default is determined by the + // input vtkUnstructuredGrid. If the field data appears to be doubles, + // then StoreDoubles will be ON, otherwise StoreDoubles will be OFF. + + vtkSetMacro(StoreDoubles, int); + vtkGetMacro(StoreDoubles, int); + + // Description: + // We never write out ghost cells. This variable is here to satisfy + // the behavior of ParaView on invoking a parallel writer. + + vtkSetMacro(GhostLevel, int); + vtkGetMacro(GhostLevel, int); + + // Description: + // Exodus files group cells into blocks. There are no blocks in a + // vtkUnstructuredGrid, but you may have stored block IDs in a + // cell array. If so provide that name here. If you don't provide + // it, we'll look for an array named "BlockId", and we'll assume + // it's a vtkIntArray. If we find no block ID array, and this is not + // a multi-process application, we will create + // one Exodus block for every cell type found in the vtkUnstructuredGrid. + + vtkSetStringMacro(BlockIdArrayName); + vtkGetStringMacro(BlockIdArrayName); + + // Description: + // By default, the integer array containing the global Block Ids of the + // cells is not included when the new Exodus II file is written out. If + // you do want to include this array, set WriteOutBlockIdArray to ON. + + vtkSetMacro(WriteOutBlockIdArray, int); + vtkGetMacro(WriteOutBlockIdArray, int); + vtkBooleanMacro(WriteOutBlockIdArray, int); + + // Description: + // The name of a point array that gives the global node IDs. + // We will look for an array called "GlobalNodeId" if you + // don't provide a different name here. It must be an integer + // array. This array is optional. + + vtkSetStringMacro(GlobalNodeIdArrayName); + vtkGetStringMacro(GlobalNodeIdArrayName); + + // Description: + // By default, the integer array containing the global Node Ids + // is not included when the new Exodus II file is written out. If + // you do want to include this array, set WriteOutGlobalNodeIdArray to ON. + + vtkSetMacro(WriteOutGlobalNodeIdArray, int); + vtkGetMacro(WriteOutGlobalNodeIdArray, int); + vtkBooleanMacro(WriteOutGlobalNodeIdArray, int); + + // Description: + // The name of a cell array that gives the global cell IDs. + // We will look for an array called "GlobalElementId" if you + // don't provide a different name here. It must be an integer array. + // This array is optional. + + vtkSetStringMacro(GlobalElementIdArrayName); + vtkGetStringMacro(GlobalElementIdArrayName); + + // Description: + // By default, the integer array containing the global Element Ids + // is not included when the new Exodus II file is written out. If you + // do want to include this array, set WriteOutGlobalElementIdArray to ON. + + vtkSetMacro(WriteOutGlobalElementIdArray, int); + vtkGetMacro(WriteOutGlobalElementIdArray, int); + vtkBooleanMacro(WriteOutGlobalElementIdArray, int); + + // Description: + // If there is no vtkModelMetadata object, then you can + // input time step values here. We copy your array. This is + // not required, the writer can use sensible defaults. If you + // only give one time step value (say 1.0), we'll increment + // each successive time step by that amount (2.0, 3.0, ...). + + void SetTimeStepValues(int NumberOfTimeSteps, float *v); + float *GetTimeStepValues(){return this->InputTimeStepValues;} + int GetNumberOfTimeSteps(){return this->InputNumberOfTimeSteps;} + + // Description: + // You can set the time step index for the next write with + // SetCurrentTimeStep. If this is not set, the writer will + // use the time step index found in the vtkModelMetadata object, + // or else a sensible default (one more than the last time step + // written). (You may want to set a different + // time step index when you have a vtkModelMetadata object if, + // for example, you are writing out only every tenth time + // step. The input to the writer may be time step 10, but you + // want it written out as time step 1.) + // The first index is 0. + + void SetCurrentTimeStep(int ts); + int GetCurrentTimeStep(){return this->InputCurrentTimeStep;} + + // Description: + // Provide a list of all blockIds that appear in the file. If + // this is a distributed file, and there is no vtkModelMetadata, + // we need all block Ids that appear in any of the files. + // + // We make a copy of your array of IDs. + + void SetAllBlockIds(int numEntries, int *blockIds); + + // Description: + // The writer will set the ErrorStatus to a non-zero value + // each time a serious error occurs. Usually this would be + // a problem with memory allocation, invalid values in the + // input file's metadata, or an inability to write the output + // file. + + vtkSetMacro(ErrorStatus, int); + vtkGetMacro(ErrorStatus, int); + +protected: + + vtkExodusIIWriter(); + ~vtkExodusIIWriter(); + + virtual int FillInputPortInformation(int port, vtkInformation* info); + + void WriteData(); + + vtkExodusIIWriter(const vtkExodusIIWriter&); // Not implemented + void operator=(const vtkExodusIIWriter&); // Not implemented + + vtkSetStringMacro(MyFileName); + vtkGetStringMacro(MyFileName); + + // Description: + // Get/Set the rank of the writer in a set of parallel processes + // so that it may determine which piece of the dataset it is + // responsible for writing. + vtkSetMacro(MyRank, int); + vtkGetMacro(MyRank, int); + +private: + static char *StrDupWithNew(const char *s); + + void RemoveGhostCells(); + + void SetPassDoubles(); + + int CheckParameters(); + int CreateExodusModel(); + int CreateBlockIdInformationFromCellTypes(vtkModelMetadata *em); + int CreateBlockIdInformation(vtkModelMetadata *em); + + static char **FlattenOutVariableNames(int narrays, int nScalarArrays, + char **nms, int *numComponents); + static void CreateNamesForScalarArrays(const char *root, char **nms, + int numComponents); + static char *GetCellTypeName(int t); + static int FindCellType(int blockId, int *blockIdList, unsigned char *cellTypeList, + int nCells); + + int CreateNewExodusFile(); + int OpenExodusFile(); + void CloseExodusFile(); + + void InitializeVariableArrayNames(); + void ClearVariableArrayNames(); + void SetNewNodeVariableNames(vtkDataArray *da, char **nm); + void SetNewElementVariableNames(vtkDataArray *da, char **nm); + + void InitializeBlockLists(); + void ClearBlockLists(); + int WriteBlockVariables(); +//BTX + vtkstd::map *BuildBlockElementSearchStructure(int block); +//ETX + + int WriteInitializationParameters(); + int WriteQARecords(); + int WriteInformationRecords(); + int WritePoints(); + int WriteCoordinateNames(); + int WriteGlobalPointIds(); + int WriteGlobalElementIds(); + int WriteBlockInformation(); + int WriteVariableArrayNames(); + int WriteNodeSetInformation(); + int WriteSideSetInformation(); + int WriteProperties(); + + int GetTimeStepIndex(); + float GetTimeStepValue(int timeStepIndex); + int WriteNextTimeStep(); + float *ExtractComponentF(vtkDataArray *da, int comp, int *idx); + double *ExtractComponentD(vtkDataArray *da, int comp, int *idx); + + vtkModelMetadata *ModelMetadata; + + int PassDoubles; // If set, we have to pass doubles to exodus library. + // If not set, we have to pass floats. + int StoreDoubles;// If set, Exodus library will store doubles. + // If not set, Exodus library will store floats. + int fid; + + char *FileName; // base file name + char *MyFileName; // base plus number of processes and my rank + + // The block IDs, the time step values, and the current time step index + // may be provided if there is not vtkModelMetadata object. The time + // step may also be provided if only a subset (like every other one) + // of the time steps are being written out. + + int *InputBlockIds; + int InputBlockIdsLength; + + int InputNumberOfTimeSteps; + float *InputTimeStepValues; + int InputCurrentTimeStep; + int LastTimeStepWritten; + + // List of the global element ID of each cell in input + + char *GlobalElementIdArrayName; + int *GlobalElementIdList; +//BTX + vtkstd::map *LocalElementIdMap; +//ETX + int GetElementLocalId(int i); + int WriteOutGlobalElementIdArray; + + // List of the global node ID of each cell in input + + char *GlobalNodeIdArrayName; + int *GlobalNodeIdList; +//BTX + vtkstd::map *LocalNodeIdMap; +//ETX + int GetNodeLocalId(int i); + int WriteOutGlobalNodeIdArray; + + // Exodus II element blocks + + char *BlockIdArrayName; // List of block ID of each cell in input + int *BlockIdList; + int WriteOutBlockIdArray; + + int NumberOfElementBlocks; + int *BlockIds; // list of every block ID in dataset +//BTX + vtkstd::map *LocalBlockIndexMap; // block ID -> block index +//ETX + int GetBlockLocalIndex(int i); + int *BlockElementStart; + int *ElementIndex; + + char **BlockElementType; + int *NumberOfElementsPerBlock; + int *NumberOfNodesPerElementInBlock; + int *NumberOfAttributesPerElementInBlock; + float **BlockElementAttributesF; + double **BlockElementAttributesD; + int **BlockElementConnectivity; + + // By BlockId, and within block ID by element variable, with variables + // appearing in the same order in which they appear in OutputElementArrayNames + + int *BlockElementVariableTruthTable; + int AllVariablesDefinedInAllBlocks; + + int BlockVariableTruthValue(int blockIdx, int varIdx); + + // Element variable arrays + + int NumberOfScalarElementArrays; + char **InputElementArrayNames; // input names (including vectors) + char **OutputElementArrayNames; // output names (all scalars) + int *InputElementArrayComponent; + + // Point variable arrays + + int NumberOfScalarNodeArrays; + char **InputNodeArrayNames; + char **OutputNodeArrayNames; + int *InputNodeArrayComponent; + + // Global application information + + int NumberOfProcesses; + int MyRank; + + // The input less ghost cells + + vtkUnstructuredGrid *MyInput; + + // we don't use this variable - it's for ParaView + + int GhostLevel; + + int ErrorStatus; +}; + +#endif diff --git a/Parallel/vtkExtractCTHPart.cxx b/Parallel/vtkExtractCTHPart.cxx new file mode 100644 index 0000000..22cad75 --- /dev/null +++ b/Parallel/vtkExtractCTHPart.cxx @@ -0,0 +1,1875 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractCTHPart.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractCTHPart.h" + +#include "vtkToolkits.h" +#include "vtkAppendPolyData.h" +#include "vtkCellData.h" +#include "vtkClipPolyData.h" +#include "vtkContourFilter.h" +#include "vtkCutter.h" +#include "vtkDataSetSurfaceFilter.h" +#include "vtkDoubleArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkCharArray.h" +#include "vtkTimerLog.h" + +#include "vtkExecutive.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkUniformGrid.h" +#include "vtkGarbageCollector.h" +#include "vtkImageData.h" + +#include "vtkCellArray.h" + +#include "vtkInformationDoubleVectorKey.h" +#include "vtkMultiProcessController.h" + +#include +#include +#include +#include + +vtkCxxRevisionMacro(vtkExtractCTHPart, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkExtractCTHPart); +vtkCxxSetObjectMacro(vtkExtractCTHPart,ClipPlane,vtkPlane); +vtkCxxSetObjectMacro(vtkExtractCTHPart,Controller,vtkMultiProcessController); + +vtkInformationKeyMacro(vtkExtractCTHPart,BOUNDS, DoubleVector); + +const double CTH_AMR_SURFACE_VALUE=0.499; + +//----------------------------------------------------------------------------- +//============================================================================= +class vtkExtractCTHPartInternal +{ +public: + vtkstd::vector VolumeArrayNames; + +}; +//============================================================================= +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +vtkExtractCTHPart::vtkExtractCTHPart() +{ + this->Internals = new vtkExtractCTHPartInternal; + this->ClipPlane = 0; + this->SetNumberOfOutputPorts(0); + + this->PointVolumeFraction=0; + + this->Data=0; + this->Contour=0; + this->Append2=0; + this->Clip1=0; + this->Cut=0; + this->Clip2=0; + + this->PolyData=0; + this->SurfacePolyData=0; + this->RPolyData=0; + + this->RData=0; + this->RContour=0; + this->RAppend2=0; + this->RClip1=0; + this->RCut=0; + this->RClip2=0; + + this->Controller = 0; + this->SetController(vtkMultiProcessController::GetGlobalController()); +} + +//----------------------------------------------------------------------------- +vtkExtractCTHPart::~vtkExtractCTHPart() +{ + this->SetClipPlane(NULL); + delete this->Internals; + this->Internals = 0; + this->DeleteInternalPipeline(); + this->SetController(0); +} + +//----------------------------------------------------------------------------- +// Overload standard modified time function. If clip plane is modified, +// then this object is modified as well. +unsigned long vtkExtractCTHPart::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if (this->ClipPlane) + { + time = this->ClipPlane->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::RemoveAllVolumeArrayNames() +{ + this->SetNumberOfOutputPorts(0); + + this->Internals->VolumeArrayNames.erase( + this->Internals->VolumeArrayNames.begin(), + this->Internals->VolumeArrayNames.end()); + this->Modified(); +} + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::AddVolumeArrayName(char* arrayName) +{ + if(arrayName==0) + { + return; + } + + vtkPolyData *d=vtkPolyData::New(); + this->Internals->VolumeArrayNames.push_back(arrayName); + int num = this->GetNumberOfOutputPorts(); + this->SetNumberOfOutputPorts(num+1); + this->SetOutputData(num, d); + d->FastDelete(); + this->Modified(); +} + +//----------------------------------------------------------------------------- +int vtkExtractCTHPart::GetNumberOfVolumeArrayNames() +{ + return this->Internals->VolumeArrayNames.size(); +} + +//----------------------------------------------------------------------------- +const char* vtkExtractCTHPart::GetVolumeArrayName(int idx) +{ + if ( idx < 0 || + idx > static_cast(this->Internals->VolumeArrayNames.size()) ) + { + return 0; + } + return this->Internals->VolumeArrayNames[idx].c_str(); +} + + +//---------------------------------------------------------------------------- +int vtkExtractCTHPart::FillInputPortInformation(int port, + vtkInformation *info) +{ + if(!this->Superclass::FillInputPortInformation(port,info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + info->Set(vtkCompositeDataPipeline::INPUT_REQUIRED_COMPOSITE_DATA_TYPE(), + "vtkCompositeDataSet"); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkExtractCTHPart::SetOutputData(int idx, vtkPolyData* d) +{ + this->GetExecutive()->SetOutputData(idx, d); +} + +//---------------------------------------------------------------------------- +int vtkExtractCTHPart::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation* outInfo; + + int num=this->GetNumberOfOutputPorts(); + int port=0; + while(portGetInformationObject(port); + // RequestData() synchronizes (communicates among processes), so we need + // all procs to call RequestData(). + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + ++port; + } + return 1; +} + +//----------------------------------------------------------------------------- +int vtkExtractCTHPart::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // get the input and output + vtkHierarchicalDataSet *input=vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + vtkRectilinearGrid *rg=0; + + if(input!=0) + { + if(input->GetNumberOfLevels()==0) + { + // empty input, do nothing. + return 1; + } + if(inInfo->Has(vtkExtractCTHPart::BOUNDS())) + { + inInfo->Get(vtkExtractCTHPart::BOUNDS(),this->Bounds); + } + else + { + // compute the bounds + if(this->GetNumberOfOutputPorts()>0) // + { + vtkInformation *info=outputVector->GetInformationObject(0); + int processNumber = info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int numProcessors =info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + if(this->Controller==0) + { + processNumber=0; + numProcessors=1; + } + this->ComputeBounds(input,processNumber,numProcessors); + } + else + { + return 1; // no output port, means no part to extract, that's OK. + } + } + } + else + { + rg=vtkRectilinearGrid::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + if(rg==0) + { + vtkErrorMacro(<<"No input."); + return 0; + } + rg->GetBounds(this->Bounds); + } + + // Here, either input or rg is not null. + + int idx, num; + const char* arrayName; + vtkPolyData *output; + + num = this->GetNumberOfVolumeArrayNames(); + + // Create an append for each part (one part per output). + vtkAppendPolyData **appendSurface=new vtkAppendPolyData *[num]; + vtkAppendPolyData **tmps=new vtkAppendPolyData *[num]; + for (idx = 0; idx < num; ++idx) + { + appendSurface[idx]= vtkAppendPolyData::New(); + tmps[idx]=vtkAppendPolyData::New(); + } + int needPartIndex=num>1; + + vtkGarbageCollector::DeferredCollectionPush(); + this->CreateInternalPipeline(); + + if(input!=0) + { + for (idx = 0; idx < num; ++idx) + { + arrayName = this->GetVolumeArrayName(idx); + output = this->GetOutput(idx); + if(output==0) + { + vtkErrorMacro(<<"No output."); + return 0; + } + this->ExecutePart(arrayName,input,appendSurface[idx],tmps[idx]); + } + } + else // rg!=0 + { + for (idx = 0; idx < num; ++idx) + { + arrayName = this->GetVolumeArrayName(idx); + output = this->GetOutput(idx); + if(output==0) + { + vtkErrorMacro(<<"No output."); + return 0; + } + this->ExecutePartOnRectilinearGrid(arrayName,rg,appendSurface[idx], + tmps[idx]); + } + } + + vtkClipPolyData* clip = vtkClipPolyData::New(); + clip->SetValue(CTH_AMR_SURFACE_VALUE); + vtkClipPolyData *clip2=clip; + if (this->ClipPlane) + { + // We need another clip for the plane. Sneak it in. + clip2 = vtkClipPolyData::New(); + clip2->SetInput(clip->GetOutput()); + clip->Delete(); + clip2->SetClipFunction(this->ClipPlane); + } + + for (idx = 0; idx < num; ++idx) + { + arrayName=this->GetVolumeArrayName(idx); + + // we have to update the output before get its point data. + appendSurface[idx]->Update(); + clip->SetInput(appendSurface[idx]->GetOutput()); +#ifndef NDEBUG + int checkIndex=appendSurface[idx]->GetOutput()->GetPointData()->SetActiveScalars(arrayName); + assert("check: SetActiveScalar succeeded" && checkIndex>=0); +#else + appendSurface[idx]->GetOutput()->GetPointData()->SetActiveScalars(arrayName); +#endif + clip2->Update(); +#if 1 + tmps[idx]->AddInput(clip2->GetOutput()); +#else + tmps[idx]->AddInput(appendSurface[idx]->GetOutput()); +#endif + + output = this->GetOutput(idx); + vtkTimerLog::MarkStartEvent("BlockAppend"); + tmps[idx]->Update(); + vtkTimerLog::MarkEndEvent("BlockAppend"); + + + vtkPolyData* tmpOut = tmps[idx]->GetOutput(); + output->CopyStructure(tmpOut); + output->GetPointData()->PassData(tmpOut->GetPointData()); + output->GetCellData()->PassData(tmpOut->GetCellData()); + output->GetFieldData()->PassData(tmpOut->GetFieldData()); + // Hopping to avoid some garbage collection time. + tmps[idx]->RemoveAllInputs(); + tmps[idx]->Delete(); + appendSurface[idx]->Delete(); + tmps[idx] = 0; + + // In the future we might be able to select the rgb color here. + if (needPartIndex) + { + // Add scalars to color this part. + int numPts = output->GetNumberOfPoints(); + vtkDoubleArray *partArray = vtkDoubleArray::New(); + partArray->SetName("Part Index"); + double *p = partArray->WritePointer(0, numPts); + for (int idx2 = 0; idx2 < numPts; ++idx2) + { + p[idx2] = static_cast(idx); + } + output->GetPointData()->SetScalars(partArray); + partArray->Delete(); + } + + // Add a name for this part. + vtkCharArray *nameArray = vtkCharArray::New(); + nameArray->SetName("Name"); + char *str = nameArray->WritePointer(0, (int)(strlen(arrayName))+1); + sprintf(str, "%s", arrayName); + output->GetFieldData()->AddArray(nameArray); + nameArray->Delete(); + } + delete[] tmps; + delete[] appendSurface; + clip2->Delete(); + this->DeleteInternalPipeline(); + vtkGarbageCollector::DeferredCollectionPop(); + + return 1; +} + +// Magic number that encode the message ids for parallel communication +enum +{ + VTK_MSG_EXTRACT_CTH_PART_HAS_BOUNDS=288402, + VTK_MSG_EXTRACT_CTH_PART_LOCAL_BOUNDS, + VTK_MSG_EXTRACT_CTH_PART_GLOBAL_BOUNDS +}; + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::ComputeBounds(vtkHierarchicalDataSet *input, + int processNumber, + int numProcessors) +{ + assert("pre: input_exists" && input!=0); + assert("pre: positive_numProcessors" && numProcessors>0); + assert("pre: valid_processNumber" && processNumber>=0 && + processNumberGetNumberOfLevels(); + int level=0; + while(levelGetNumberOfDataSets(level); + int dataset=0; + while(datasetGetDataSet(level,dataset); + if(dataObj!=0)// can be null if on another processor + { + vtkDataSet *ds=vtkDataSet::SafeDownCast(dataObj); + ds->GetBounds(realBounds); + + if(firstBlock) + { + int c=0; + while(c<6) + { + this->Bounds[c]=realBounds[c]; + ++c; + } + firstBlock=0; + } + else + { + int c=0; + while(c<3) + { + if(realBounds[2*c]Bounds[2*c]) + { + this->Bounds[2*c]=realBounds[2*c]; + } + if(realBounds[2*c+1]>this->Bounds[2*c+1]) + { + this->Bounds[2*c+1]=realBounds[2*c+1]; + } + ++c; + } + } + } + ++dataset; + } + ++level; + } + // Here we have the bounds according to our local datasets. + + int parent; + int left=GetLeftChildProcessor(processNumber); + int right=left+1; + if(processNumber>0) // not root (nothing to do if root) + { + parent=this->GetParentProcessor(processNumber); + } + else + { + parent=0; // just to remove warnings, never used + } + + double otherBounds[6]; + int leftHasBounds=0; // init is not useful, just for compiler warnings + int rightHasBounds=0; // init is not useful, just for compiler warnings + + if(leftController->Receive(&leftHasBounds, 1, left, + VTK_MSG_EXTRACT_CTH_PART_HAS_BOUNDS); + + if(leftHasBounds) + { + this->Controller->Receive(otherBounds, 6, left, + VTK_MSG_EXTRACT_CTH_PART_LOCAL_BOUNDS); + + if(firstBlock) // impossible the current processor is not a leaf + { + int cc=0; + while(cc<6) + { + this->Bounds[cc]=otherBounds[cc]; + ++cc; + } + firstBlock=0; + } + else + { + int cc=0; + while(cc<3) + { + if(otherBounds[2*cc]Bounds[2*cc]) + { + this->Bounds[2*cc]=otherBounds[2*cc]; + } + if(otherBounds[2*cc+1]>this->Bounds[2*cc+1]) + { + this->Bounds[2*cc+1]=otherBounds[2*cc+1]; + } + ++cc; + } + } + } + + if(rightController->Receive(&rightHasBounds, 1, right, + VTK_MSG_EXTRACT_CTH_PART_HAS_BOUNDS); + if(rightHasBounds) + { + this->Controller->Receive(otherBounds, 6, right, + VTK_MSG_EXTRACT_CTH_PART_LOCAL_BOUNDS); + if(firstBlock)// impossible the current processor is not a leaf + { + int cc=0; + while(cc<6) + { + this->Bounds[cc]=otherBounds[cc]; + ++cc; + } + firstBlock=0; + } + else + { + int cc=0; + while(cc<3) + { + if(otherBounds[2*cc]Bounds[2*cc]) + { + this->Bounds[2*cc]=otherBounds[2*cc]; + } + if(otherBounds[2*cc+1]>this->Bounds[2*cc+1]) + { + this->Bounds[2*cc+1]=otherBounds[2*cc+1]; + } + ++cc; + } + } + } + } + } + + // Send local to parent, Receive global from the parent. + if(processNumber>0) // not root (nothing to do if root) + { + int hasBounds=!firstBlock; + this->Controller->Send(&hasBounds, 1, parent, + VTK_MSG_EXTRACT_CTH_PART_HAS_BOUNDS); + if(hasBounds) + { + this->Controller->Send(this->Bounds, 6, parent, + VTK_MSG_EXTRACT_CTH_PART_LOCAL_BOUNDS); + + this->Controller->Receive(this->Bounds, 6, parent, + VTK_MSG_EXTRACT_CTH_PART_GLOBAL_BOUNDS); + } + } + + if(firstBlock) // empty, no bounds, nothing to do + { + return; + } + + // Send it to children. + if(leftController->Send(this->Bounds, 6, left, + VTK_MSG_EXTRACT_CTH_PART_GLOBAL_BOUNDS); + } + if(rightController->Send(this->Bounds, 6, right, + VTK_MSG_EXTRACT_CTH_PART_GLOBAL_BOUNDS); + } + } + } + + // At this point, the global bounds is set in each processor. + + cout<Bounds[1]<<"; "<Bounds[2]<<"; "<Bounds[3]<<"; "<Bounds[4]<<"; "<Bounds[5]<>1; // /2 + } + else + { + result=(proc-1)>>1; // /2 + } + return result; +} + +int vtkExtractCTHPart::GetLeftChildProcessor(int proc) +{ + return (proc<<1)+1; // *2+1 +} + +//----------------------------------------------------------------------------- +// the input is a hierarchy of vtkUniformGrid or one level of +// vtkRectilinearGrid. The output is a hierarchy of vtkPolyData. +void vtkExtractCTHPart::ExecutePart(const char *arrayName, + vtkHierarchicalDataSet *input, + vtkAppendPolyData *appendSurface, + vtkAppendPolyData *append) +{ + int numberOfLevels=input->GetNumberOfLevels(); + int level=0; + while(levelGetNumberOfDataSets(level); + + int dataset=0; + while(datasetGetDataSet(level,dataset); + if(dataObj!=0)// can be null if on another processor + { + vtkRectilinearGrid *rg=vtkRectilinearGrid::SafeDownCast(dataObj); + if(rg!=0) + { + this->ExecutePartOnRectilinearGrid(arrayName,rg,appendSurface, + append); + } + else + { +#ifdef EXTRACT_USE_IMAGE_DATA + vtkImageData *ug=vtkImageData::SafeDownCast(dataObj); +#else + vtkUniformGrid *ug=vtkUniformGrid::SafeDownCast(dataObj); +#endif + if(ug!=0) + { + this->ExecutePartOnUniformGrid(arrayName,ug,appendSurface, + append); + } + else + { + vtkErrorMacro(<<" cannot handle a block of this type."); + } + } + } + ++dataset; + } + ++level; + } +} + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::ExecutePartOnUniformGrid( + const char *arrayName, +#ifdef EXTRACT_USE_IMAGE_DATA + vtkImageData *input, +#else + vtkUniformGrid *input, +#endif + vtkAppendPolyData *appendSurface, + vtkAppendPolyData *append) +{ + vtkPolyData* tmp; + vtkDataArray* cellVolumeFraction; + int* dims; + + vtkTimerLog::MarkStartEvent("Execute Part"); + + // First things first. + // Convert Cell data array to point data array. + // Pass cell data. + + // Only convert single volume fraction array to point data. + // Other attributes will have to be viewed as cell data. + cellVolumeFraction = input->GetCellData()->GetArray(arrayName); + if (cellVolumeFraction == NULL) + { + vtkErrorMacro("Could not find cell array " << arrayName); + return; + } + if (cellVolumeFraction->GetDataType() != VTK_DOUBLE && + cellVolumeFraction->GetDataType() != VTK_FLOAT) + { + vtkErrorMacro("Expecting volume fraction to be of type float or double."); + return; + } + + this->Data->CopyStructure(input); + + // Do not pass cell volume fraction data. + this->Data->GetCellData()->CopyFieldOff(arrayName); + + vtkDataArray* scalars = input->GetCellData()->GetScalars(); + if (scalars && strcmp(arrayName, scalars->GetName()) == 0) + { // I do not know why the reader sets attributes, but .... + this->Data->GetCellData()->CopyScalarsOff(); + } + + this->Data->GetCellData()->PassData(input->GetCellData()); + dims = input->GetDimensions(); + this->PointVolumeFraction->SetNumberOfTuples(dims[0]*dims[1]*dims[2]); + this->ExecuteCellDataToPointData(cellVolumeFraction, + this->PointVolumeFraction, dims); + + + this->Data->GetPointData()->SetScalars(this->PointVolumeFraction); + + int isNotEmpty=this->ExtractUniformGridSurface(this->Data,this->SurfacePolyData); + if(isNotEmpty) + { + tmp=vtkPolyData::New(); + tmp->ShallowCopy(this->SurfacePolyData); + appendSurface->AddInput(tmp); + tmp->Delete(); + } + + // All outside never has any polydata. + // Be sure to to that only after the surface filter. + double range[2]; + cellVolumeFraction->GetRange(range); + if (range[1] < CTH_AMR_SURFACE_VALUE) + { + vtkTimerLog::MarkEndEvent("Execute Part"); + return; + } + if (this->ClipPlane == 0 && range[0] > CTH_AMR_SURFACE_VALUE) + { + vtkTimerLog::MarkEndEvent("Execute Part"); + return; + } + + this->PolyData->Update(); + + tmp=vtkPolyData::New(); + tmp->ShallowCopy(this->PolyData); + append->AddInput(tmp); + tmp->Delete(); + + vtkTimerLog::MarkEndEvent("Execute Part"); +} + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::CreateInternalPipeline() +{ + // Objects common to both pipelines + this->PointVolumeFraction=vtkDoubleArray::New(); + this->SurfacePolyData=vtkPolyData::New(); + + // Uniform grid case pipeline + +#ifdef EXTRACT_USE_IMAGE_DATA + this->Data = vtkImageData::New(); +#else + this->Data = vtkUniformGrid::New(); +#endif + + this->Contour=vtkContourFilter::New(); + this->Contour->SetInput(this->Data); + this->Contour->SetValue(0, CTH_AMR_SURFACE_VALUE); + + + if(this->ClipPlane) + { + // We need to append iso and capped surfaces. + this->Append2 = vtkAppendPolyData::New(); + // Clip the volume fraction iso surface. + this->Clip1=vtkClipPolyData::New(); + this->Clip1->SetInput(this->Contour->GetOutput()); + this->Clip1->SetClipFunction(this->ClipPlane); + this->Append2->AddInput(this->Clip1->GetOutput()); + + // We need to create a capping surface. + this->Cut = vtkCutter::New(); + this->Cut->SetCutFunction(this->ClipPlane); + this->Cut->SetValue(0, 0.0); + this->Cut->SetInput(this->Data); + this->Clip2 = vtkClipPolyData::New(); + this->Clip2->SetInput(this->Cut->GetOutput()); + this->Clip2->SetValue(CTH_AMR_SURFACE_VALUE); + this->Append2->AddInput(this->Clip2->GetOutput()); + this->PolyData = this->Append2->GetOutput(); + } + else + { + this->PolyData = this->Contour->GetOutput(); + } + + // Rectilinear grid case pipeline + + this->RData = vtkRectilinearGrid::New(); + + this->RContour=vtkContourFilter::New(); + this->RContour->SetInput(this->RData); + this->RContour->SetValue(0,CTH_AMR_SURFACE_VALUE); + + if(this->ClipPlane) + { + // We need to append iso and capped surfaces. + this->RAppend2 = vtkAppendPolyData::New(); + // Clip the volume fraction iso surface. + this->RClip1=vtkClipPolyData::New(); + this->RClip1->SetInput(this->RContour->GetOutput()); + this->RClip1->SetClipFunction(this->ClipPlane); + this->RAppend2->AddInput(this->RClip1->GetOutput()); + + // We need to create a capping surface. + this->RCut = vtkCutter::New(); + this->RCut->SetInput(this->RData); + this->RCut->SetCutFunction(this->ClipPlane); + this->RCut->SetValue(0, 0.0); + this->RClip2 = vtkClipPolyData::New(); + this->RClip2->SetInput(this->RCut->GetOutput()); + this->RClip2->SetValue(CTH_AMR_SURFACE_VALUE); + this->RAppend2->AddInput(this->RClip2->GetOutput()); + this->RPolyData = this->RAppend2->GetOutput(); + } + else + { + this->RPolyData = this->RContour->GetOutput(); + } +} + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::DeleteInternalPipeline() +{ + if(this->PointVolumeFraction!=0) + { + this->PointVolumeFraction->Delete(); + this->PointVolumeFraction=0; + } + + if(this->SurfacePolyData!=0) + { + this->SurfacePolyData->Delete(); + this->SurfacePolyData=0; + } + + // Uniform grid + if(this->Data!=0) + { + this->Data->Delete(); + this->Data=0; + } + + if(this->Contour!=0) + { + this->Contour->Delete(); + this->Contour=0; + } + + if(this->Append2!=0) + { + this->Append2->Delete(); + this->Append2=0; + } + if(this->Cut!=0) + { + this->Cut->Delete(); + this->Cut=0; + } + if(this->Clip1!=0) + { + this->Clip1->Delete(); + this->Clip1=0; + } + if(this->Clip2!=0) + { + this->Clip2->Delete(); + this->Clip2=0; + } + + + // Rectilinear grid + if(this->RData!=0) + { + this->RData->Delete(); + this->RData=0; + } + if(this->RContour!=0) + { + this->RContour->Delete(); + this->RContour=0; + } + + if(this->RAppend2!=0) + { + this->RAppend2->Delete(); + this->RAppend2=0; + } + if(this->RCut!=0) + { + this->RCut->Delete(); + this->RCut=0; + } + if(this->RClip1!=0) + { + this->RClip1->Delete(); + this->RClip1=0; + } + if(this->RClip2!=0) + { + this->RClip2->Delete(); + this->RClip2=0; + } +} + +//----------------------------------------------------------------------------- +// the input is either a vtkRectilinearGrid or a vtkUniformGrid +void vtkExtractCTHPart::ExecutePartOnRectilinearGrid( + const char *arrayName, + vtkRectilinearGrid *input, + vtkAppendPolyData *appendSurface, + vtkAppendPolyData *append) +{ + assert("pre: valid_input" && input->CheckAttributes()==0); + + vtkPolyData* tmp; + vtkDataArray* cellVolumeFraction; + int* dims; + + vtkTimerLog::MarkStartEvent("Execute Part"); + + // First things first. + // Convert Cell data array to point data array. + // Pass cell data. + + // Only convert single volume fraction array to point data. + // Other attributes will have to be viewed as cell data. + cellVolumeFraction = input->GetCellData()->GetArray(arrayName); + if (cellVolumeFraction == NULL) + { + vtkErrorMacro("Could not find cell array " << arrayName); + return; + } + if (cellVolumeFraction->GetDataType() != VTK_DOUBLE && + cellVolumeFraction->GetDataType() != VTK_FLOAT) + { + vtkErrorMacro("Expecting volume fraction to be of type float or double."); + return; + } + + this->RData->CopyStructure(input); + + // Do not pass cell volume fraction data. + this->RData->GetCellData()->CopyFieldOff(arrayName); + + vtkDataArray* scalars = input->GetCellData()->GetScalars(); + if (scalars && strcmp(arrayName, scalars->GetName()) == 0) + { // I do not know why the reader sets attributes, but .... + this->RData->GetCellData()->CopyScalarsOff(); + } + + this->RData->GetCellData()->PassData(input->GetCellData()); + dims = input->GetDimensions(); + this->PointVolumeFraction->SetNumberOfTuples(dims[0]*dims[1]*dims[2]); + this->ExecuteCellDataToPointData(cellVolumeFraction, + this->PointVolumeFraction, dims); + + + this->RData->GetPointData()->SetScalars(this->PointVolumeFraction); + + assert("check: valid_rdata" && this->RData->CheckAttributes()==0); + + int isNotEmpty=this->ExtractRectilinearGridSurface(this->RData,this->SurfacePolyData); + if(isNotEmpty) + { + tmp=vtkPolyData::New(); + tmp->ShallowCopy(this->SurfacePolyData); + assert("check: valid_copy" && tmp->CheckAttributes()==0); + appendSurface->AddInput(tmp); + tmp->Delete(); + } + + // All outside never has any polydata. + // Be sure to to that only after the surface filter. + double range[2]; + cellVolumeFraction->GetRange(range); + if (range[1] < CTH_AMR_SURFACE_VALUE) + { + vtkTimerLog::MarkEndEvent("Execute Part"); + return; + } + if (this->ClipPlane == 0 && range[0] > CTH_AMR_SURFACE_VALUE) + { + vtkTimerLog::MarkEndEvent("Execute Part"); + return; + } + + this->RPolyData->Update(); + tmp=vtkPolyData::New(); + tmp->ShallowCopy(this->RPolyData); + append->AddInput(tmp); + tmp->Delete(); + + vtkTimerLog::MarkEndEvent("Execute Part"); +} +//----------------------------------------------------------------------------- +// Description: +// Append quads for faces of the block that actually on the bounds +// of the hierarchical dataset. Deals with ghost cells. +// Return true if the output is not empty. +int vtkExtractCTHPart::ExtractRectilinearGridSurface( + vtkRectilinearGrid *input, + vtkPolyData *output + ) +{ + assert("pre: valid_input" && input!=0 && input->CheckAttributes()==0); + assert("pre: output_exists" && output!=0); + + int result=0; +#if 1 + int dims[3]; + input->GetDimensions(dims); + int ext[6]; + int originalExtents[6]; + input->GetExtent(ext); + input->GetExtent(originalExtents); + +// vtkUnsignedCharArray *ghostArray=static_cast(input->GetCellData()->GetArray("vtkGhostLevels")); + + + + // bounds without taking ghost cells into account + double bounds[6]; + + input->GetBounds(bounds); + +#if 0 + // block face min x + if(this->IsGhostFace(0,0,dims,ghostArray)) + { + // downsize this! + bounds[0]+=spacing[0]; + ++ext[0]; + } + if(this->IsGhostFace(0,1,dims,ghostArray)) + { + // downsize this! + bounds[1]-=spacing[0]; + --ext[1]; + } + if(this->IsGhostFace(1,0,dims,ghostArray)) + { + // downsize this! + bounds[2]+=spacing[1]; + ++ext[2]; + } + if(this->IsGhostFace(1,1,dims,ghostArray)) + { + // downsize this! + bounds[3]-=spacing[1]; + --ext[3]; + } + if(this->IsGhostFace(2,0,dims,ghostArray)) + { + // downsize this! + bounds[4]+=spacing[2]; + ++ext[4]; + } + if(this->IsGhostFace(2,1,dims,ghostArray)) + { + // downsize this! + bounds[5]-=spacing[2]; + --ext[5]; + } +#endif + // here, bounds are real block bounds without ghostcells. + +#if 0 + const double epsilon=0.001; + int doFaceMinX=fabs(bounds[0]-this->Bounds[0])Bounds[1])Bounds[2])Bounds[3])Bounds[4])Bounds[5])Bounds[0]; + int doFaceMaxX=bounds[1]>=this->Bounds[1]; + int doFaceMinY=bounds[2]<=this->Bounds[2]; + int doFaceMaxY=bounds[3]>=this->Bounds[3]; + int doFaceMinZ=bounds[4]<=this->Bounds[4]; + int doFaceMaxZ=bounds[5]>=this->Bounds[5]; +#endif +#if 0 + int doFaceMinX=1; + int doFaceMaxX=1; + int doFaceMinY=1; + int doFaceMaxY=1; + int doFaceMinZ=1; + int doFaceMaxZ=1; +#endif +#if 0 + int doFaceMinX=0; + int doFaceMaxX=0; + int doFaceMinY=0; + int doFaceMaxY=0; + int doFaceMinZ=0; + int doFaceMaxZ=0; +#endif +#if 0 + doFaceMaxX=0; + doFaceMaxY=0; + doFaceMaxZ=0; +#endif + + result=doFaceMinX||doFaceMaxX||doFaceMinY||doFaceMaxY||doFaceMinZ + ||doFaceMaxZ; + + if(result) + { + output->Initialize(); + + vtkIdType numPoints=0; + vtkIdType cellArraySize=0; + +// input->GetExtent(ext); + + // Compute an upper bound for the number of points and cells. + // xMin face + if (doFaceMinX && ext[2] != ext[3] && ext[4] != ext[5] && ext[0] != ext[1]) + { + cellArraySize += 2*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + } + // xMax face + if (doFaceMaxX && ext[2] != ext[3] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + } + // yMin face + if (doFaceMinY && ext[0] != ext[1] && ext[4] != ext[5] && ext[2] != ext[3]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + } + // yMax face + if (doFaceMaxY && ext[0] != ext[1] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + } + // zMin face + if (doFaceMinZ && ext[0] != ext[1] && ext[2] != ext[3] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + } + // zMax face + if (doFaceMaxZ && ext[0] != ext[1] && ext[2] != ext[3]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + } + + vtkCellArray *outPolys = vtkCellArray::New(); + outPolys->Allocate(cellArraySize); + output->SetPolys(outPolys); + outPolys->Delete(); + + vtkPoints *outPoints = vtkPoints::New(); + outPoints->Allocate(numPoints); + output->SetPoints(outPoints); + outPoints->Delete(); + + // Allocate attributes for copying. + output->GetPointData()->CopyAllocate(input->GetPointData()); + output->GetCellData()->CopyAllocate(input->GetCellData()); + + // Extents are already corrected for ghostcells. + + // make each face that is actually on the ds boundary + if(doFaceMinX) + { + this->ExecuteFaceQuads(input,output,0,originalExtents,ext,0,1,2); + } + if(doFaceMaxX) + { + this->ExecuteFaceQuads(input,output,1,originalExtents,ext,0,2,1); + } + if(doFaceMinY) + { + this->ExecuteFaceQuads(input,output,0,originalExtents,ext,1,2,0); + } + if(doFaceMaxY) + { + this->ExecuteFaceQuads(input,output,1,originalExtents,ext,1,0,2); + } + if(doFaceMinZ) + { + this->ExecuteFaceQuads(input,output,0,originalExtents,ext,2,0,1); + } + if(doFaceMaxZ) + { + this->ExecuteFaceQuads(input,output,1,originalExtents,ext,2,1,0); + } + + output->Squeeze(); + } +#endif +// result=>valid_surface: A=>B !A||B + assert("post: valid_surface" && (!result || output->CheckAttributes()==0)); + return result; +} + +//----------------------------------------------------------------------------- +// Description: +// Append quads for faces of the block that actually on the bounds +// of the hierarchical dataset. Deals with ghost cells. +// Return true if the output is not empty. +int vtkExtractCTHPart::ExtractUniformGridSurface( +#ifdef EXTRACT_USE_IMAGE_DATA + vtkImageData *input, +#else + vtkUniformGrid *input, +#endif + vtkPolyData *output + ) +{ + assert("pre: valid_input" && input!=0 && input->CheckAttributes()==0); + assert("pre: output_exists" && output!=0); + + int result=0; +#if 1 + double origin[3]; + input->GetOrigin(origin); + double spacing[3]; + input->GetSpacing(spacing); + int dims[3]; + input->GetDimensions(dims); + int ext[6]; + int originalExtents[6]; + input->GetExtent(ext); + input->GetExtent(originalExtents); + +//vtkUnsignedCharArray *ghostArray=static_cast(input->GetCellData()->GetArray("vtkGhostLevels")); + + // bounds without taking ghost cells into account + double bounds[6]; + + int i=0; + while(i<3) + { + bounds[2*i]=origin[i]; + bounds[2*i+1]=bounds[2*i]+spacing[i]*(dims[i]-1); + ++i; + } + +#if 0 + // block face min x + if(this->IsGhostFace(0,0,dims,ghostArray)) + { + // downsize this! + bounds[0]+=spacing[0]; + ++ext[0]; + } + if(this->IsGhostFace(0,1,dims,ghostArray)) + { + // downsize this! + bounds[1]-=spacing[0]; + --ext[1]; + } + if(this->IsGhostFace(1,0,dims,ghostArray)) + { + // downsize this! + bounds[2]+=spacing[1]; + ++ext[2]; + } + if(this->IsGhostFace(1,1,dims,ghostArray)) + { + // downsize this! + bounds[3]-=spacing[1]; + --ext[3]; + } + if(this->IsGhostFace(2,0,dims,ghostArray)) + { + // downsize this! + bounds[4]+=spacing[2]; + ++ext[4]; + } + if(this->IsGhostFace(2,1,dims,ghostArray)) + { + // downsize this! + bounds[5]-=spacing[2]; + --ext[5]; + } +#endif + // here, bounds are real block bounds without ghostcells. + +#if 0 + const double epsilon=0.001; + int doFaceMinX=fabs(bounds[0]-this->Bounds[0])Bounds[1])Bounds[2])Bounds[3])Bounds[4])Bounds[5])Bounds[0]; + int doFaceMaxX=bounds[1]>=this->Bounds[1]; + int doFaceMinY=bounds[2]<=this->Bounds[2]; + int doFaceMaxY=bounds[3]>=this->Bounds[3]; + int doFaceMinZ=bounds[4]<=this->Bounds[4]; + int doFaceMaxZ=bounds[5]>=this->Bounds[5]; +#endif +#if 0 + int doFaceMinX=1; + int doFaceMaxX=1; + int doFaceMinY=1; + int doFaceMaxY=1; + int doFaceMinZ=1; + int doFaceMaxZ=1; +#endif +#if 0 + int doFaceMinX=0; + int doFaceMaxX=0; + int doFaceMinY=0; + int doFaceMaxY=0; + int doFaceMinZ=0; + int doFaceMaxZ=0; +#endif +#if 0 + doFaceMaxX=0; + doFaceMaxY=0; + doFaceMaxZ=0; +#endif + + result=doFaceMinX||doFaceMaxX||doFaceMinY||doFaceMaxY||doFaceMinZ + ||doFaceMaxZ; + + if(result) + { + output->Initialize(); + vtkIdType numPoints=0; + vtkIdType cellArraySize=0; + +// input->GetExtent(ext); + + // Compute an upper bound for the number of points and cells. + // xMin face + if (doFaceMinX && ext[2] != ext[3] && ext[4] != ext[5] && ext[0] != ext[1]) + { + cellArraySize += 2*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + } + // xMax face + if (doFaceMaxX && ext[2] != ext[3] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[3]-ext[2]+1)*(ext[5]-ext[4]+1); + } + // yMin face + if (doFaceMinY && ext[0] != ext[1] && ext[4] != ext[5] && ext[2] != ext[3]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + } + // yMax face + if (doFaceMaxY && ext[0] != ext[1] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[5]-ext[4]+1); + } + // zMin face + if (doFaceMinZ && ext[0] != ext[1] && ext[2] != ext[3] && ext[4] != ext[5]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + } + // zMax face + if (doFaceMaxZ && ext[0] != ext[1] && ext[2] != ext[3]) + { + cellArraySize += 2*(ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + numPoints += (ext[1]-ext[0]+1)*(ext[3]-ext[2]+1); + } + + vtkCellArray *outPolys = vtkCellArray::New(); + outPolys->Allocate(cellArraySize); + output->SetPolys(outPolys); + outPolys->Delete(); + + vtkPoints *outPoints = vtkPoints::New(); + outPoints->Allocate(numPoints); + output->SetPoints(outPoints); + outPoints->Delete(); + + // Allocate attributes for copying. + output->GetPointData()->CopyAllocate(input->GetPointData()); + output->GetCellData()->CopyAllocate(input->GetCellData()); + + // Extents are already corrected for ghostcells. + + // make each face that is actually on the ds boundary + if(doFaceMinX) + { + this->ExecuteFaceQuads(input,output,0,originalExtents,ext,0,1,2); + } + if(doFaceMaxX) + { + this->ExecuteFaceQuads(input,output,1,originalExtents,ext,0,2,1); + } + if(doFaceMinY) + { + this->ExecuteFaceQuads(input,output,0,originalExtents,ext,1,2,0); + } + if(doFaceMaxY) + { + this->ExecuteFaceQuads(input,output,1,originalExtents,ext,1,0,2); + } + if(doFaceMinZ) + { + this->ExecuteFaceQuads(input,output,0,originalExtents,ext,2,0,1); + } + if(doFaceMaxZ) + { + this->ExecuteFaceQuads(input,output,1,originalExtents,ext,2,1,0); + } + + output->Squeeze(); + } +#endif + // result=>valid_surface: A=>B !A||B + assert("post: valid_surface" && (!result || output->CheckAttributes()==0)); + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Is block face on axis0 (either min or max depending on the maxFlag) +// composed of only ghost cells? +int vtkExtractCTHPart::IsGhostFace(int axis0, + int maxFlag, + int dims[3], + vtkUnsignedCharArray *ghostArray) +{ + assert("pre: valid_axis0" && axis0>=0 && axis0<=2); + + int axis1=axis0+1; + if(axis1>2) + { + axis1=0; + } + int axis2=axis0+2; + if(axis2>2) + { + axis2=0; + } + + int ijk[3]; // index of the cell. + + if(maxFlag) + { + ijk[axis0]=dims[axis0]-2; + } + else + { + ijk[axis0]=0; + } + + // We test the center cell of the block face. + // in the worst case (2x2 cells), we need to know if at least + // three cells are ghost to say that the face is a ghost face. + + ijk[axis1]=dims[axis1]/2-1; // (dims[axis1]-2)/2 + ijk[axis2]=dims[axis2]/2-1; // (dims[axis2]-2)/2 + int result=ghostArray->GetValue(vtkStructuredData::ComputeCellId(dims,ijk)); + + if(dims[axis1]==3) + { + // axis1 requires 2 cells to be tested. + // if so, axis1index=0 and axis1index+1=1 + ijk[axis1]=1; + result=result && + ghostArray->GetValue(vtkStructuredData::ComputeCellId(dims,ijk)); + } + + if(dims[axis2]==3) + { + // herem axis1 may have moved from the previous test. + // axis2 requires 2 cells to be tested. + // if so, axis2index=0 and axis2index+1=1 + ijk[axis2]=1; + result=result && + ghostArray->GetValue(vtkStructuredData::ComputeCellId(dims,ijk)); + } + return result; +} + +//---------------------------------------------------------------------------- +// Description: +// Merly the same implementation than in vtkDataSetSurfaceFilter, without +// dealing with the whole extents. +void vtkExtractCTHPart::ExecuteFaceQuads(vtkDataSet *input, + vtkPolyData *output, + int maxFlag, + int originalExtents[6], + int ext[6], + int aAxis, + int bAxis, + int cAxis) +{ + assert("pre: input_exists" && input!=0); + assert("pre: output_exists" && output!=0); + assert("pre: originalExtents_exists" && originalExtents!=0); + assert("pre: ext_exists" && ext!=0); + assert("pre: valid_axes" + && aAxis>=0 && aAxis<=2 + && bAxis>=0 && bAxis<=2 + && cAxis>=0 && cAxis<=2 + && aAxis!=bAxis + && aAxis!=cAxis + && bAxis!=cAxis); + + vtkPoints *outPts; + vtkCellArray *outPolys; + vtkPointData *inPD, *outPD; + vtkCellData *inCD, *outCD; + int pInc[3]; + int qInc[3]; + int cOutInc; + double pt[3]; + vtkIdType inStartPtId; + vtkIdType inStartCellId; + vtkIdType outStartPtId; + vtkIdType outPtId; + vtkIdType inId, outId; + int ib, ic; + int aA2, bA2, cA2; + + outPts = output->GetPoints(); + outPD = output->GetPointData(); + inPD = input->GetPointData(); + outCD = output->GetCellData(); + inCD = input->GetCellData(); + + pInc[0] = 1; + pInc[1] = (originalExtents[1]-originalExtents[0]+1); + pInc[2] = (originalExtents[3]-originalExtents[2]+1) * pInc[1]; + // quad increments (cell incraments, but cInc could be confused with c axis). + qInc[0] = 1; + qInc[1] = originalExtents[1]-originalExtents[0]; + // The conditions are for when we have one or more degenerate axes (2d or 1d cells). + if (qInc[1] == 0) + { + qInc[1] = 1; + } + qInc[2] = (originalExtents[3]-originalExtents[2]) * qInc[1]; + if (qInc[2] == 0) + { + qInc[2] = qInc[1]; + } + + // Temporary variables to avoid many multiplications. + aA2 = aAxis<<1; // * 2; + bA2 = bAxis<<1; // * 2; + cA2 = cAxis<<1; // * 2; + + // We might as well put the test for this face here. + if (ext[bA2] == ext[bA2+1] || ext[cA2] == ext[cA2+1]) + { + return; + } +#if 0 + if (maxFlag) + { + if (ext[aA2+1] < wholeExt[aA2+1]) + { + return; + } + } + else + { // min faces have a slightly different condition to avoid coincident faces. + if (ext[aA2] == ext[aA2+1] || ext[aA2] > wholeExt[aA2]) + { + return; + } + } +#endif + + if(!maxFlag) + { + if (ext[aA2] == ext[aA2+1]) + { + return; + } + } + + // Assuming no ghost cells ... +// inStartPtId = inStartCellId = 0; + inStartPtId=0; //ext[aA2]; + inStartCellId=0; //ext[aA2]; + + + // I put this confusing conditional to fix a regression test. + // If we are creating a maximum face, then we indeed have to offset the input cell Ids. + // However, vtkGeometryFilter created a 2d image as a max face, but the cells are copied + // as a min face (no offset). Hence maxFlag = 1 and there should be no offset. + if (maxFlag && ext[aA2] < ext[1+aA2]) + { + inStartPtId = pInc[aAxis]*(ext[aA2+1]-originalExtents[aA2]); // -ext[aA2] + inStartCellId = qInc[aAxis]*(ext[aA2+1]-originalExtents[aA2]-1); // -ext[aA2] + } + + outStartPtId = outPts->GetNumberOfPoints(); + // Make the points for this face. + for (ic = ext[cA2]; ic <= ext[cA2+1]; ++ic) + { + for (ib = ext[bA2]; ib <= ext[bA2+1]; ++ib) + { +// inId = inStartPtId + (ib-ext[bA2]+originExtents[bAxis])*pInc[bAxis] +// + (ic-ext[cA2]+originExtents[cAxis])*pInc[cAxis]; + + inId = inStartPtId + (ib-originalExtents[bA2])*pInc[bAxis] + + (ic-originalExtents[cA2])*pInc[cAxis]; + + input->GetPoint(inId, pt); + outId = outPts->InsertNextPoint(pt); + // Copy point data. + outPD->CopyData(inPD,inId,outId); + } + } + + // Do the cells. + cOutInc = ext[bA2+1] - ext[bA2] + 1; + + outPolys = output->GetPolys(); + + // Old method for creating quads (needed for cell data.). + for (ic = ext[cA2]; ic < ext[cA2+1]; ++ic) + { + for (ib = ext[bA2]; ib < ext[bA2+1]; ++ib) + { + outPtId = outStartPtId + (ib-ext[bA2]) + (ic-ext[cA2])*cOutInc; +// inId = inStartCellId + (ib-ext[bA2]+originExtents[bAxis])*qInc[bAxis] + (ic-ext[cA2]+originExtents[cAxis])*qInc[cAxis]; + + inId = inStartCellId + (ib-originalExtents[bA2])*qInc[bAxis] + (ic-originalExtents[cA2])*qInc[cAxis]; + + outId = outPolys->InsertNextCell(4); + outPolys->InsertCellPoint(outPtId); + outPolys->InsertCellPoint(outPtId+cOutInc); + outPolys->InsertCellPoint(outPtId+cOutInc+1); + outPolys->InsertCellPoint(outPtId+1); + + // Copy cell data. + outCD->CopyData(inCD,inId,outId); + } + } +} + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::ExecuteCellDataToPointData( + vtkDataArray *cellVolumeFraction, + vtkDoubleArray *pointVolumeFraction, + int *dims) +{ + int count; + int i, j, k; + int iEnd, jEnd, kEnd; + int jInc, kInc; + double *pPoint; + + pointVolumeFraction->SetName(cellVolumeFraction->GetName()); + + iEnd = dims[0]-1; + jEnd = dims[1]-1; + kEnd = dims[2]-1; + + // Deals with none 3D images, otherwise it will never enter into the loop. + // And then the data will be not initialized and the output of the contour + // will be empty. + + int dimensionality=3; + + if(kEnd==0) + { + --dimensionality; + kEnd=1; + } + + // Increments are for the point array. + jInc = dims[0]; + kInc = (dims[1]) * jInc; + + pPoint = pointVolumeFraction->GetPointer(0); +// pCell = static_cast(cellVolumeFraction->GetVoidPointer(0)); + + // Initialize the point data to 0. + memset(pPoint, 0, dims[0]*dims[1]*dims[2]*sizeof(double)); + +#ifndef NDEBUG + // for debugging and check out of range. + double *endPtr=pPoint+dims[0]*dims[1]*dims[2]; +#endif + + int index=0; + // Loop thorugh the cells. + for (k = 0; k < kEnd; ++k) + { + for (j = 0; j < jEnd; ++j) + { + for (i = 0; i < iEnd; ++i) + { + // Add cell value to all points of cell. + double value=cellVolumeFraction->GetTuple1(index); + + assert("check: valid_range" && pPointGetPointer(0); + + // because we eventually modified iEnd, jEnd, kEnd to handle the + // 2D image case, we have to recompute them. + iEnd = dims[0]-1; + jEnd = dims[1]-1; + kEnd = dims[2]-1; + + for (k = 0; k <= kEnd; ++k) + { + // Just a fancy fast way to compute the number of cell neighbors of a + // point. + if (k == 1) + { + count = count << 1; + } + if (k == kEnd && kEnd>0) + { + // only in 3D case, otherwise count may become zero + // and be involved in a division by zero later on + count = count >> 1; + } + for (j = 0; j <= jEnd; ++j) + { + // Just a fancy fast way to compute the number of cell neighbors of a + // point. + if (j == 1) + { + count = count << 1; + } + if (j == jEnd) + { + count = count >> 1; + } + for (i = 0; i <= iEnd; ++i) + { + // Just a fancy fast way to compute the number of cell neighbors of a + // point. + if (i == 1) + { + count = count << 1; + } + if (i == iEnd) + { + count = count >> 1; + } + assert("check: valid_range" && pPoint0); + *pPoint = *pPoint / static_cast(count); + ++pPoint; + } + } + } +} + + +//----------------------------------------------------------------------------- +void vtkExtractCTHPart::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "VolumeArrayNames: \n"; + vtkIndent i2 = indent.GetNextIndent(); + vtkstd::vector::iterator it; + for ( it = this->Internals->VolumeArrayNames.begin(); + it != this->Internals->VolumeArrayNames.end(); + ++ it ) + { + os << i2 << it->c_str() << endl; + } + if (this->ClipPlane) + { + os << indent << "ClipPlane:\n"; + this->ClipPlane->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << indent << "ClipPlane: NULL\n"; + } + + if ( this->Controller!=0) + { + os << "Controller:" << endl; + this->Controller->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "No Controller." << endl; + } +} + diff --git a/Parallel/vtkExtractCTHPart.h b/Parallel/vtkExtractCTHPart.h new file mode 100644 index 0000000..4e2eeaa --- /dev/null +++ b/Parallel/vtkExtractCTHPart.h @@ -0,0 +1,221 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractCTHPart.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractCTHPart - Generates surface of an CTH volume fraction. +// .SECTION Description +// vtkExtractCTHPart is a filter that is specialized for creating +// visualization of a CTH simulation. First it converts the cell data +// to point data. It contours the selected volume fraction at a value +// of 0.5. The user has the option of clipping the part with a plane. +// Clipped surfaces of the part are generated. + +#ifndef __vtkExtractCTHPart_h +#define __vtkExtractCTHPart_h + +#include "vtkPolyDataAlgorithm.h" +class vtkPlane; +class vtkDataArray; +class vtkDoubleArray; +class vtkRectilinearGrid; + +class vtkExtractCTHPartInternal; +class vtkHierarchicalDataSet; +class vtkPolyData; +class vtkUniformGrid; +class vtkImageData; +class vtkDataSet; + +class vtkContourFilter; +class vtkAppendPolyData; +class vtkDataSetSurfaceFilter; +class vtkClipPolyData; +class vtkCutter; + +class vtkMultiProcessController; + +//#define EXTRACT_USE_IMAGE_DATA 1 + +class VTK_PARALLEL_EXPORT vtkExtractCTHPart : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkExtractCTHPart,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // key to record the bounds of the hierarchical dataset. + static vtkInformationDoubleVectorKey *BOUNDS(); + + // Description: + // Construct object with initial range (0,1) and single contour value + // of 0.0. + static vtkExtractCTHPart *New(); + + // Description: + // Names of cell volume fraction arrays to extract. + void RemoveAllVolumeArrayNames(); + void AddVolumeArrayName(char* arrayName); + int GetNumberOfVolumeArrayNames(); + const char* GetVolumeArrayName(int idx); + + // Description: + // Set, get or maninpulate the implicit clipping plane. + void SetClipPlane(vtkPlane *clipPlane); + vtkGetObjectMacro(ClipPlane, vtkPlane); + + // Description: + // Look at clip plane to compute MTime. + unsigned long GetMTime(); + + // Description: + // Set the controller used to coordinate parallel processing. + void SetController(vtkMultiProcessController* controller); + + // Return the controller used to coordinate parallel processing. By default, + // it is the global controller. + vtkGetObjectMacro(Controller,vtkMultiProcessController); + +protected: + vtkExtractCTHPart(); + ~vtkExtractCTHPart(); + + void SetOutputData(int idx, vtkPolyData* d); + + int RequestInformation(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector); + + int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + // Description: + // the input is a hierarchy of vtkUniformGrid or one level of + // vtkRectilinearGrid. The output is a hierarchy of vtkPolyData. + + + // Description: + // Compute the bounds over the composite dataset, some sub-dataset + // can be on other processors. + void ComputeBounds(vtkHierarchicalDataSet *input, + int processNumber, + int numProcessors); + + // Description: + // The processors are views as a heap tree. The root is the processor of + // id 0. + int GetParentProcessor(int proc); + int GetLeftChildProcessor(int proc); + + void ExecutePart(const char *arrayName, + vtkHierarchicalDataSet *input, + vtkAppendPolyData *appendSurface, + vtkAppendPolyData *append); + + void ExecutePartOnUniformGrid(const char *arrayName, +#ifdef EXTRACT_USE_IMAGE_DATA + vtkImageData *input, +#else + vtkUniformGrid *input, +#endif + vtkAppendPolyData *appendSurface, + vtkAppendPolyData *append); + + void ExecutePartOnRectilinearGrid( const char *arrayName, + vtkRectilinearGrid *input, + vtkAppendPolyData *appendSurface, + vtkAppendPolyData *append); + + void ExecuteCellDataToPointData(vtkDataArray *cellVolumeFraction, + vtkDoubleArray *pointVolumeFraction, + int *dims); + + int FillInputPortInformation(int port, + vtkInformation *info); + + void CreateInternalPipeline(); + void DeleteInternalPipeline(); + + // Description: + // Append quads for faces of the block that actually on the bounds + // of the hierarchical dataset. Deals with ghost cells. + // Return true if the output is not empty. + int ExtractUniformGridSurface( +#ifdef EXTRACT_USE_IMAGE_DATA + vtkImageData *input, +#else + vtkUniformGrid *input, +#endif + vtkPolyData *output); + + // Description: + // Append quads for faces of the block that actually on the bounds + // of the hierarchical dataset. Deals with ghost cells. + // Return true if the output is not empty. + int ExtractRectilinearGridSurface(vtkRectilinearGrid *input, + vtkPolyData *output); + + void ExecuteFaceQuads(vtkDataSet *input, + vtkPolyData *output, + int maxFlag, + int originExtents[3], + int ext[6], + int aAxis, + int bAxis, + int cAxis); + + // Description: + // Is block face on axis0 (either min or max depending on the maxFlag) + // composed of only ghost cells? + // \pre valid_axis0: axis0>=0 && axis0<=2 + int IsGhostFace(int axis0, + int maxFlag, + int dims[3], + vtkUnsignedCharArray *ghostArray); + + vtkPlane *ClipPlane; + vtkExtractCTHPartInternal* Internals; + + // Internal Pipeline elements + vtkDoubleArray *PointVolumeFraction; + +#ifdef EXTRACT_USE_IMAGE_DATA + vtkImageData *Data; +#else + vtkUniformGrid *Data; +#endif + + vtkContourFilter *Contour; + vtkAppendPolyData *Append2; + vtkClipPolyData *Clip1; + vtkCutter *Cut; + vtkClipPolyData *Clip2; + + vtkPolyData *PolyData; + vtkPolyData *RPolyData; + vtkPolyData *SurfacePolyData; + + vtkRectilinearGrid *RData; + vtkContourFilter *RContour; + vtkAppendPolyData *RAppend2; + vtkClipPolyData *RClip1; + vtkCutter *RCut; + vtkClipPolyData *RClip2; + + double Bounds[6]; // Whole bounds (dataset over all the processors) + + vtkMultiProcessController *Controller; +private: + vtkExtractCTHPart(const vtkExtractCTHPart&); // Not implemented. + void operator=(const vtkExtractCTHPart&); // Not implemented. +}; +#endif diff --git a/Parallel/vtkExtractPolyDataPiece.cxx b/Parallel/vtkExtractPolyDataPiece.cxx new file mode 100644 index 0000000..94abc80 --- /dev/null +++ b/Parallel/vtkExtractPolyDataPiece.cxx @@ -0,0 +1,369 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractPolyDataPiece.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractPolyDataPiece.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkOBBDicer.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkExtractPolyDataPiece, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkExtractPolyDataPiece); + +//============================================================================= +vtkExtractPolyDataPiece::vtkExtractPolyDataPiece() +{ + this->CreateGhostCells = 1; +} + +//============================================================================= +int vtkExtractPolyDataPiece::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), 0); + + return 1; +} + +//============================================================================= +int vtkExtractPolyDataPiece::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + return 1; +} + +//============================================================================= +void vtkExtractPolyDataPiece::ComputeCellTags(vtkIntArray *tags, + vtkIdList *pointOwnership, + int piece, int numPieces, + vtkPolyData *input) +{ + vtkIdType idx, j, numCells, ptId; + vtkIdList *cellPtIds; + + numCells = input->GetNumberOfCells(); + + cellPtIds = vtkIdList::New(); + // Clear Point ownership. + for (idx = 0; idx < input->GetNumberOfPoints(); ++idx) + { + pointOwnership->SetId(idx, -1); + } + + // Brute force division. + // The first N cells go to piece 0 ... + for (idx = 0; idx < numCells; ++idx) + { + if ((idx * numPieces / numCells) == piece) + { + tags->SetValue(idx, 0); + } + else + { + tags->SetValue(idx, -1); + } + // Fill in point ownership mapping. + input->GetCellPoints(idx, cellPtIds); + for (j = 0; j < cellPtIds->GetNumberOfIds(); ++j) + { + ptId = cellPtIds->GetId(j); + if (pointOwnership->GetId(ptId) == -1) + { + pointOwnership->SetId(ptId, idx); + } + } + } + + cellPtIds->Delete(); + + //dicer->SetInput(input); + //dicer->SetDiceModeToSpecifiedNumberOfPieces(); + //dicer->SetNumberOfPieces(numPieces); + //dicer->Update(); + + //intermediate->ShallowCopy(dicer->GetOutput()); + //intermediate->BuildLinks(); + //pointScalars = intermediate->GetPointData()->GetScalars(); +} + +//============================================================================= +int vtkExtractPolyDataPiece::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + vtkIntArray *cellTags; + int ghostLevel, piece, numPieces; + vtkIdType cellId, newCellId; + vtkIdList *cellPts, *pointMap; + vtkIdList *newCellPts = vtkIdList::New(); + vtkIdList *pointOwnership; + vtkCell *cell; + vtkPoints *newPoints; + vtkUnsignedCharArray* cellGhostLevels = 0; + vtkUnsignedCharArray* pointGhostLevels = 0; + vtkIdType ptId=0, newId, numPts, i; + int numCellPts; + double *x=NULL; + + // Pipeline update piece will tell us what to generate. + ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + outPD->CopyAllocate(pd); + outCD->CopyAllocate(cd); + + if (ghostLevel > 0 && this->CreateGhostCells) + { + cellGhostLevels = vtkUnsignedCharArray::New(); + pointGhostLevels = vtkUnsignedCharArray::New(); + cellGhostLevels->Allocate(input->GetNumberOfCells()); + pointGhostLevels->Allocate(input->GetNumberOfPoints()); + } + + // Break up cells based on which piece they belong to. + cellTags = vtkIntArray::New(); + cellTags->Allocate(input->GetNumberOfCells(), 1000); + pointOwnership = vtkIdList::New(); + pointOwnership->Allocate(input->GetNumberOfPoints()); + // Cell tags end up being 0 for cells in piece and -1 for all others. + // Point ownership is the cell that owns the point. + this->ComputeCellTags(cellTags, pointOwnership, piece, numPieces, input); + + // Find the layers of ghost cells. + if (this->CreateGhostCells) + { + for (i = 0; i < ghostLevel; i++) + { + this->AddGhostLevel(input, cellTags, i+1); + } + } + + // Filter the cells. + + numPts = input->GetNumberOfPoints(); + output->Allocate(input->GetNumberOfCells()); + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + + pointMap = vtkIdList::New(); //maps old point ids into new + pointMap->SetNumberOfIds(numPts); + for (i=0; i < numPts; i++) + { + pointMap->SetId(i,-1); + } + + // Filter the cells + for (cellId=0; cellId < input->GetNumberOfCells(); cellId++) + { + if ( cellTags->GetValue(cellId) != -1) // satisfied thresholding + { + if (cellGhostLevels) + { + cellGhostLevels->InsertNextValue( + (unsigned char)(cellTags->GetValue(cellId))); + } + + cell = input->GetCell(cellId); + cellPts = cell->GetPointIds(); + numCellPts = cell->GetNumberOfPoints(); + + for (i=0; i < numCellPts; i++) + { + ptId = cellPts->GetId(i); + if ( (newId = pointMap->GetId(ptId)) < 0 ) + { + x = input->GetPoint(ptId); + newId = newPoints->InsertNextPoint(x); + if (pointGhostLevels) + { + pointGhostLevels->InsertNextValue( + cellTags->GetValue(pointOwnership->GetId(ptId))); + } + pointMap->SetId(ptId,newId); + outPD->CopyData(pd,ptId,newId); + } + newCellPts->InsertId(i,newId); + } + newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts); + outCD->CopyData(cd,cellId,newCellId); + newCellPts->Reset(); + } // satisfied thresholding + } // for all cells + + + // Split up points that are not used by cells, + // and have not been assigned to any piece. + // Count the number of unassigned points. This is an extra pass through + // the points, but the pieces will be better load balanced and + // more spatially coherent. + vtkIdType count = 0; + vtkIdType idx; + for (idx = 0; idx < input->GetNumberOfPoints(); ++idx) + { + if (pointOwnership->GetId(idx) == -1) + { + ++count; + } + } + vtkIdType count2 = 0; + for (idx = 0; idx < input->GetNumberOfPoints(); ++idx) + { + if (pointOwnership->GetId(idx) == -1) + { + if ((count2 * numPieces / count) == piece) + { + x = input->GetPoint(idx); + newId = newPoints->InsertNextPoint(x); + if (pointGhostLevels) + { + pointGhostLevels->InsertNextValue(0); + } + outPD->CopyData(pd,idx,newId); + } + } + } + + vtkDebugMacro(<< "Extracted " << output->GetNumberOfCells() + << " number of cells."); + + // now clean up / update ourselves + pointMap->Delete(); + newCellPts->Delete(); + + if (cellGhostLevels) + { + cellGhostLevels->SetName("vtkGhostLevels"); + output->GetCellData()->AddArray(cellGhostLevels); + cellGhostLevels->Delete(); + cellGhostLevels = 0; + } + if (pointGhostLevels) + { + pointGhostLevels->SetName("vtkGhostLevels"); + output->GetPointData()->AddArray(pointGhostLevels); + pointGhostLevels->Delete(); + pointGhostLevels = 0; + } + output->SetPoints(newPoints); + newPoints->Delete(); + + output->Squeeze(); + cellTags->Delete(); + pointOwnership->Delete(); + + return 1; +} + +//============================================================================= +void vtkExtractPolyDataPiece::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Create Ghost Cells: " << (this->CreateGhostCells ? "On\n" : "Off\n"); +} + +//============================================================================= +void vtkExtractPolyDataPiece::AddGhostLevel(vtkPolyData *input, + vtkIntArray *cellTags, + int level) +{ + vtkIdType numCells, pointId, cellId, i; + int j, k; + vtkGenericCell *cell1 = vtkGenericCell::New(); + vtkGenericCell *cell2 = vtkGenericCell::New(); + vtkIdList *cellIds = vtkIdList::New(); + + numCells = input->GetNumberOfCells(); + + for (i = 0; i < numCells; i++) + { + if (cellTags->GetValue(i) == level - 1) + { + input->GetCell(i, cell1); + for (j = 0; j < cell1->GetNumberOfPoints(); j++) + { + pointId = cell1->GetPointId(j); + input->GetPointCells(pointId, cellIds); + for (k = 0; k < cellIds->GetNumberOfIds(); k++) + { + cellId = cellIds->GetId(k); + if (cellTags->GetValue(cellId) == -1) + { + input->GetCell(cellId, cell2); + cellTags->SetValue(cellId, level); + } + } + } + } + } + cell1->Delete(); + cell2->Delete(); + cellIds->Delete(); +} + + + + + + + + + + + + + + + + + + diff --git a/Parallel/vtkExtractPolyDataPiece.h b/Parallel/vtkExtractPolyDataPiece.h new file mode 100644 index 0000000..072bb4e --- /dev/null +++ b/Parallel/vtkExtractPolyDataPiece.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractPolyDataPiece.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractPolyDataPiece - Return specified piece, including specified +// number of ghost levels. + +#ifndef __vtkExtractPolyDataPiece_h +#define __vtkExtractPolyDataPiece_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkIdList; +class vtkIntArray; + +class VTK_PARALLEL_EXPORT vtkExtractPolyDataPiece : public vtkPolyDataAlgorithm +{ +public: + static vtkExtractPolyDataPiece *New(); + vtkTypeRevisionMacro(vtkExtractPolyDataPiece, vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Turn on/off creating ghost cells (on by default). + vtkSetMacro(CreateGhostCells, int); + vtkGetMacro(CreateGhostCells, int); + vtkBooleanMacro(CreateGhostCells, int); + +protected: + vtkExtractPolyDataPiece(); + ~vtkExtractPolyDataPiece() {}; + + // Usual data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // A method for labeling which piece the cells belong to. + void ComputeCellTags(vtkIntArray *cellTags, vtkIdList *pointOwnership, + int piece, int numPieces, vtkPolyData *input); + + void AddGhostLevel(vtkPolyData *input, vtkIntArray *cellTags, int ghostLevel); + + int CreateGhostCells; +private: + vtkExtractPolyDataPiece(const vtkExtractPolyDataPiece&); // Not implemented. + void operator=(const vtkExtractPolyDataPiece&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkExtractUnstructuredGridPiece.cxx b/Parallel/vtkExtractUnstructuredGridPiece.cxx new file mode 100644 index 0000000..3307a46 --- /dev/null +++ b/Parallel/vtkExtractUnstructuredGridPiece.cxx @@ -0,0 +1,369 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractUnstructuredGridPiece.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExtractUnstructuredGridPiece.h" + +#include "vtkCell.h" +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkGenericCell.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkExtractUnstructuredGridPiece, "$Revision: 1.19 $"); +vtkStandardNewMacro(vtkExtractUnstructuredGridPiece); + +vtkExtractUnstructuredGridPiece::vtkExtractUnstructuredGridPiece() +{ + this->CreateGhostCells = 1; +} + +int vtkExtractUnstructuredGridPiece::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + return 1; +} + +int vtkExtractUnstructuredGridPiece::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + return 1; +} + +void vtkExtractUnstructuredGridPiece::ComputeCellTags(vtkIntArray *tags, + vtkIdList *pointOwnership, + int piece, int numPieces, + vtkUnstructuredGrid *input) +{ + int j; + vtkIdType idx, numCells, ptId; + vtkIdType* cellPointer; + vtkIdType* ids; + vtkIdType numCellPts; + + numCells = input->GetNumberOfCells(); + + // Clear Point ownership. This is only necessary if we + // Are creating ghost points. + if (pointOwnership) + { + for (idx = 0; idx < input->GetNumberOfPoints(); ++idx) + { + pointOwnership->SetId(idx, -1); + } + } + + // Brute force division. + cellPointer = (input->GetCells() ? input->GetCells()->GetPointer() : 0); + for (idx = 0; idx < numCells; ++idx) + { + if ((idx * numPieces / numCells) == piece) + { + tags->SetValue(idx, 0); + } + else + { + tags->SetValue(idx, -1); + } + // Fill in point ownership mapping. + if (pointOwnership) + { + numCellPts = cellPointer[0]; + ids = cellPointer+1; + // Move to the next cell. + cellPointer += (1 + numCellPts); + for (j = 0; j < numCellPts; ++j) + { + ptId = ids[j]; + if (pointOwnership->GetId(ptId) == -1) + { + pointOwnership->SetId(ptId, idx); + } + } + } + } +} + +int vtkExtractUnstructuredGridPiece::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + unsigned char* cellTypes = (input->GetCellTypesArray() ? input->GetCellTypesArray()->GetPointer(0) : 0); + int cellType; + vtkIntArray *cellTags; + int ghostLevel, piece, numPieces; + vtkIdType cellId, newCellId; + vtkIdList *pointMap; + vtkIdList *newCellPts = vtkIdList::New(); + vtkPoints *newPoints; + vtkUnsignedCharArray* cellGhostLevels = 0; + vtkIdList *pointOwnership = 0; + vtkUnsignedCharArray* pointGhostLevels = 0; + vtkIdType i, ptId, newId, numPts, numCells; + int numCellPts; + vtkIdType *cellPointer; + vtkIdType *ids; + double *x; + + // Pipeline update piece will tell us what to generate. + ghostLevel = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + piece = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + outPD->CopyAllocate(pd); + outCD->CopyAllocate(cd); + + numPts = input->GetNumberOfPoints(); + numCells = input->GetNumberOfCells(); + + if (ghostLevel > 0 && this->CreateGhostCells) + { + cellGhostLevels = vtkUnsignedCharArray::New(); + cellGhostLevels->Allocate(numCells); + // We may want to create point ghost levels even + // if there are no ghost cells. Since it cost extra, + // and no filter really uses it, and the filter did not + // create a point ghost level array for this case before, + // I will leave it the way it was. + pointOwnership = vtkIdList::New(); + pointOwnership->Allocate(numPts); + pointGhostLevels = vtkUnsignedCharArray::New(); + pointGhostLevels->Allocate(numPts); + } + + // Break up cells based on which piece they belong to. + cellTags = vtkIntArray::New(); + cellTags->Allocate(input->GetNumberOfCells(), 1000); + // Cell tags end up being 0 for cells in piece and -1 for all others. + // Point ownership is the cell that owns the point. + this->ComputeCellTags(cellTags, pointOwnership, piece, numPieces, input); + + // Find the layers of ghost cells. + if (this->CreateGhostCells) + { + for (i = 0; i < ghostLevel; i++) + { + this->AddGhostLevel(input, cellTags, i+1); + } + } + + // Filter the cells. + + output->Allocate(input->GetNumberOfCells()); + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + + pointMap = vtkIdList::New(); //maps old point ids into new + pointMap->SetNumberOfIds(numPts); + for (i=0; i < numPts; i++) + { + pointMap->SetId(i,-1); + } + + // Filter the cells + cellPointer = (input->GetCells() ? input->GetCells()->GetPointer() : 0); + for (cellId=0; cellId < numCells; cellId++) + { + // Direct access to cells. + cellType = cellTypes[cellId]; + numCellPts = cellPointer[0]; + ids = cellPointer+1; + // Move to the next cell. + cellPointer += (1 + *cellPointer); + + if ( cellTags->GetValue(cellId) != -1) // satisfied thresholding + { + if (cellGhostLevels) + { + cellGhostLevels->InsertNextValue( + (unsigned char)(cellTags->GetValue(cellId))); + } + + for (i=0; i < numCellPts; i++) + { + ptId = ids[i]; + if ( (newId = pointMap->GetId(ptId)) < 0 ) + { + x = input->GetPoint(ptId); + newId = newPoints->InsertNextPoint(x); + if (pointGhostLevels && pointOwnership) + { + pointGhostLevels->InsertNextValue( + cellTags->GetValue(pointOwnership->GetId(ptId))); + } + pointMap->SetId(ptId,newId); + outPD->CopyData(pd,ptId,newId); + } + newCellPts->InsertId(i,newId); + } + newCellId = output->InsertNextCell(cellType,newCellPts); + outCD->CopyData(cd,cellId,newCellId); + newCellPts->Reset(); + } // satisfied thresholding + } // for all cells + + // Split up points that are not used by cells, + // and have not been assigned to any piece. + // Count the number of unassigned points. This is an extra pass through + // the points, but the pieces will be better load balanced and + // more spatially coherent. + vtkIdType count = 0; + vtkIdType idx; + for (idx = 0; idx < input->GetNumberOfPoints(); ++idx) + { + if (pointMap->GetId(idx) == -1) + { + ++count; + } + } + vtkIdType count2 = 0; + for (idx = 0; idx < input->GetNumberOfPoints(); ++idx) + { + if (pointMap->GetId(idx) == -1) + { + if ((count2++ * numPieces / count) == piece) + { + x = input->GetPoint(idx); + newId = newPoints->InsertNextPoint(x); + if (pointGhostLevels) + { + pointGhostLevels->InsertNextValue(0); + } + outPD->CopyData(pd,idx,newId); + } + } + } + + vtkDebugMacro(<< "Extracted " << output->GetNumberOfCells() + << " number of cells."); + + // now clean up / update ourselves + pointMap->Delete(); + newCellPts->Delete(); + + if (cellGhostLevels) + { + cellGhostLevels->SetName("vtkGhostLevels"); + output->GetCellData()->AddArray(cellGhostLevels); + cellGhostLevels->Delete(); + cellGhostLevels = 0; + } + if (pointGhostLevels) + { + pointGhostLevels->SetName("vtkGhostLevels"); + output->GetPointData()->AddArray(pointGhostLevels); + pointGhostLevels->Delete(); + pointGhostLevels = 0; + } + output->SetPoints(newPoints); + newPoints->Delete(); + + output->Squeeze(); + cellTags->Delete(); + if (pointOwnership) + { + pointOwnership->Delete(); + pointOwnership = 0; + } + + return 1; +} + +void vtkExtractUnstructuredGridPiece::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Create Ghost Cells: " + << (this->CreateGhostCells ? "On\n" : "Off\n"); +} + + +// This method is still slow... +void vtkExtractUnstructuredGridPiece::AddGhostLevel(vtkUnstructuredGrid *input, + vtkIntArray *cellTags, + int level) +{ + vtkIdType numCells, pointId, cellId, i; + int j, k; + vtkGenericCell *cell1 = vtkGenericCell::New(); + vtkGenericCell *cell2 = vtkGenericCell::New(); + vtkIdList *cellIds = vtkIdList::New(); + + numCells = input->GetNumberOfCells(); + + for (i = 0; i < numCells; i++) + { + if (cellTags->GetValue(i) == level - 1) + { + input->GetCell(i, cell1); + for (j = 0; j < cell1->GetNumberOfPoints(); j++) + { + pointId = cell1->GetPointId(j); + input->GetPointCells(pointId, cellIds); + for (k = 0; k < cellIds->GetNumberOfIds(); k++) + { + cellId = cellIds->GetId(k); + if (cellTags->GetValue(cellId) == -1) + { + input->GetCell(cellId, cell2); + cellTags->SetValue(cellId, level); + } + } + } + } + } + cell1->Delete(); + cell2->Delete(); + cellIds->Delete(); +} diff --git a/Parallel/vtkExtractUnstructuredGridPiece.h b/Parallel/vtkExtractUnstructuredGridPiece.h new file mode 100644 index 0000000..6d00912 --- /dev/null +++ b/Parallel/vtkExtractUnstructuredGridPiece.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractUnstructuredGridPiece.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExtractUnstructuredGridPiece - Return specified piece, including specified +// number of ghost levels. + +#ifndef __vtkExtractUnstructuredGridPiece_h +#define __vtkExtractUnstructuredGridPiece_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkIdList; +class vtkIntArray; + +class VTK_PARALLEL_EXPORT vtkExtractUnstructuredGridPiece : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkExtractUnstructuredGridPiece *New(); + vtkTypeRevisionMacro(vtkExtractUnstructuredGridPiece, vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Turn on/off creating ghost cells (on by default). + vtkSetMacro(CreateGhostCells, int); + vtkGetMacro(CreateGhostCells, int); + vtkBooleanMacro(CreateGhostCells, int); + +protected: + vtkExtractUnstructuredGridPiece(); + ~vtkExtractUnstructuredGridPiece() {}; + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + // A method for labeling which piece the cells belong to. + void ComputeCellTags(vtkIntArray *cellTags, vtkIdList *pointOwnership, + int piece, int numPieces, vtkUnstructuredGrid *input); + + void AddGhostLevel(vtkUnstructuredGrid *input, vtkIntArray *cellTags, int ghostLevel); + + int CreateGhostCells; +private: + vtkExtractUnstructuredGridPiece(const vtkExtractUnstructuredGridPiece&); // Not implemented. + void operator=(const vtkExtractUnstructuredGridPiece&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkExtractUserDefinedPiece.cxx b/Parallel/vtkExtractUserDefinedPiece.cxx new file mode 100644 index 0000000..2cf6c72 --- /dev/null +++ b/Parallel/vtkExtractUserDefinedPiece.cxx @@ -0,0 +1,271 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractUserDefinedPiece.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkExtractUserDefinedPiece.h" + +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkIntArray.h" +#include "vtkIdList.h" +#include "vtkCell.h" +#include "vtkPoints.h" +#include "vtkUnsignedCharArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkExtractUserDefinedPiece, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkExtractUserDefinedPiece); + +vtkExtractUserDefinedPiece::vtkExtractUserDefinedPiece() +{ + this->ConstantData = NULL; + this->ConstantDataLen = 0; + this->InPiece = NULL; +} +vtkExtractUserDefinedPiece::~vtkExtractUserDefinedPiece() +{ + if (this->ConstantData){ + delete [] (char *)this->ConstantData; + this->ConstantData = NULL; + } +} +void vtkExtractUserDefinedPiece::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf( os, indent ); + os << indent << "ConstantData: " << this->ConstantData + << indent << "ConstantDataLen: " << this->ConstantDataLen + << indent << "InPiece: " << this->InPiece + << "\n"; +} +void vtkExtractUserDefinedPiece::SetConstantData(void *data, int len) +{ + this->ConstantData = new char [len]; + this->ConstantDataLen = len; + + memcpy(this->ConstantData, data, len); + + this->Modified(); +} + +int vtkExtractUserDefinedPiece::GetConstantData(void **data) +{ + *data = this->ConstantData; + return this->ConstantDataLen; +} + + +// This is exactly vtkExtractUnstructuredGridPiece::Execute(), with +// the exception that we call ComputeCellTagsWithFunction rather +// than ComputeCellTags. If ComputeCellTags were virtual, we could +// just override it here. + +int vtkExtractUserDefinedPiece::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData(); + vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData(); + vtkIntArray *cellTags; + int ghostLevel; + vtkIdType cellId, newCellId; + vtkIdList *cellPts, *pointMap; + vtkIdList *newCellPts = vtkIdList::New(); + vtkIdList *pointOwnership; + vtkCell *cell; + vtkPoints *newPoints; + vtkUnsignedCharArray* cellGhostLevels = 0; + vtkUnsignedCharArray* pointGhostLevels = 0; + vtkIdType i, ptId, newId, numPts; + int numCellPts; + double *x; + + // Pipeline update piece will tell us what to generate. + ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + outPD->CopyAllocate(pd); + outCD->CopyAllocate(cd); + + if (ghostLevel > 0 && this->CreateGhostCells) + { + cellGhostLevels = vtkUnsignedCharArray::New(); + pointGhostLevels = vtkUnsignedCharArray::New(); + cellGhostLevels->Allocate(input->GetNumberOfCells()); + pointGhostLevels->Allocate(input->GetNumberOfPoints()); + } + + // Break up cells based on which piece they belong to. + cellTags = vtkIntArray::New(); + cellTags->Allocate(input->GetNumberOfCells(), 1000); + pointOwnership = vtkIdList::New(); + pointOwnership->Allocate(input->GetNumberOfPoints()); + + // Cell tags end up being 0 for cells in piece and -1 for all others. + // Point ownership is the cell that owns the point. + + this->ComputeCellTagsWithFunction(cellTags, pointOwnership, input); + + // Find the layers of ghost cells. + if (this->CreateGhostCells) + { + for (i = 0; i < ghostLevel; i++) + { + this->AddGhostLevel(input, cellTags, i+1); + } + } + + // Filter the cells. + + numPts = input->GetNumberOfPoints(); + output->Allocate(input->GetNumberOfCells()); + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + + pointMap = vtkIdList::New(); //maps old point ids into new + pointMap->SetNumberOfIds(numPts); + for (i=0; i < numPts; i++) + { + pointMap->SetId(i,-1); + } + + // Filter the cells + for (cellId=0; cellId < input->GetNumberOfCells(); cellId++) + { + if ( cellTags->GetValue(cellId) != -1) // satisfied thresholding + { + if (cellGhostLevels) + { + cellGhostLevels->InsertNextValue( + (unsigned char)(cellTags->GetValue(cellId))); + } + + cell = input->GetCell(cellId); + cellPts = cell->GetPointIds(); + numCellPts = cell->GetNumberOfPoints(); + + for (i=0; i < numCellPts; i++) + { + ptId = cellPts->GetId(i); + if ( (newId = pointMap->GetId(ptId)) < 0 ) + { + x = input->GetPoint(ptId); + newId = newPoints->InsertNextPoint(x); + if (pointGhostLevels) + { + pointGhostLevels->InsertNextValue( + cellTags->GetValue(pointOwnership->GetId(ptId))); + } + pointMap->SetId(ptId,newId); + outPD->CopyData(pd,ptId,newId); + } + newCellPts->InsertId(i,newId); + } + newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts); + outCD->CopyData(cd,cellId,newCellId); + newCellPts->Reset(); + } // satisfied thresholding + } // for all cells + + vtkDebugMacro(<< "Extracted " << output->GetNumberOfCells() + << " number of cells."); + + // now clean up / update ourselves + pointMap->Delete(); + newCellPts->Delete(); + + if (cellGhostLevels) + { + cellGhostLevels->SetName("vtkGhostLevels"); + output->GetCellData()->AddArray(cellGhostLevels); + cellGhostLevels->Delete(); + cellGhostLevels = 0; + } + if (pointGhostLevels) + { + pointGhostLevels->SetName("vtkGhostLevels"); + output->GetPointData()->AddArray(pointGhostLevels); + pointGhostLevels->Delete(); + pointGhostLevels = 0; + } + output->SetPoints(newPoints); + newPoints->Delete(); + + output->Squeeze(); + cellTags->Delete(); + pointOwnership->Delete(); + + return 1; +} +void vtkExtractUserDefinedPiece:: +ComputeCellTagsWithFunction(vtkIntArray *tags, + vtkIdList *pointOwnership, + vtkUnstructuredGrid *input) +{ + int j; + vtkIdType idx, numCells, ptId; + vtkIdList *cellPtIds; + + numCells = input->GetNumberOfCells(); + + cellPtIds = vtkIdList::New(); + // Clear Point ownership. + for (idx = 0; idx < input->GetNumberOfPoints(); ++idx) + { + pointOwnership->SetId(idx, -1); + } + + // Brute force division. + for (idx = 0; idx < numCells; ++idx) + { + if (this->InPiece(idx, input, this->ConstantData)) + { + tags->SetValue(idx, 0); + } + else + { + tags->SetValue(idx, -1); + } + // Fill in point ownership mapping. + input->GetCellPoints(idx, cellPtIds); + for (j = 0; j < cellPtIds->GetNumberOfIds(); ++j) + { + ptId = cellPtIds->GetId(j); + if (pointOwnership->GetId(ptId) == -1) + { + pointOwnership->SetId(ptId, idx); + } + } + } + + cellPtIds->Delete(); +} + diff --git a/Parallel/vtkExtractUserDefinedPiece.h b/Parallel/vtkExtractUserDefinedPiece.h new file mode 100644 index 0000000..cd5a1ed --- /dev/null +++ b/Parallel/vtkExtractUserDefinedPiece.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExtractUserDefinedPiece.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkExtractUserDefinedPiece - Return user specified piece with ghost cells +// +// .SECTION Description +// Provided a function that determines which cells are zero-level +// cells ("the piece"), this class outputs the piece with the +// requested number of ghost levels. The only difference between +// this class and the class it is derived from is that the +// zero-level cells are specified by a function you provide, +// instead of determined by dividing up the cells based on cell Id. +// +// .SECTION See Also +// vtkExtractUnstructuredGridPiece + +#ifndef __vtkExtractUserDefinedPiece_h +#define __vtkExtractUserDefinedPiece_h + +#include "vtkExtractUnstructuredGridPiece.h" + +class VTK_PARALLEL_EXPORT vtkExtractUserDefinedPiece : public vtkExtractUnstructuredGridPiece +{ +public: + vtkTypeRevisionMacro(vtkExtractUserDefinedPiece, vtkExtractUnstructuredGridPiece); + static vtkExtractUserDefinedPiece *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +//BTX + typedef int (*UserDefFunc)(vtkIdType cellID, vtkUnstructuredGrid *grid, void *constantData); +//ETX + + // Set the function used to identify the piece. The function should + // return 1 if the cell is in the piece, and 0 otherwise. + void SetPieceFunction(UserDefFunc func) {this->InPiece = func; this->Modified();} + + // Set constant data to be used by the piece identifying function. + void SetConstantData(void *data, int len); + + // Get constant data to be used by the piece identifying function. + // Return the length of the data buffer. + int GetConstantData(void **data); + + // The function should return 1 if the cell + // is in the piece, and 0 otherwise. + +protected: + + vtkExtractUserDefinedPiece(); + ~vtkExtractUserDefinedPiece(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ComputeCellTagsWithFunction(vtkIntArray *tags, vtkIdList *pointOwnership, + vtkUnstructuredGrid *input); + +private: + vtkExtractUserDefinedPiece(const vtkExtractUserDefinedPiece&); // Not implemented + void operator=(const vtkExtractUserDefinedPiece&); // Not implemented + + void *ConstantData; + int ConstantDataLen; + + UserDefFunc InPiece; +}; +#endif diff --git a/Parallel/vtkMPI.h b/Parallel/vtkMPI.h new file mode 100644 index 0000000..924d17e --- /dev/null +++ b/Parallel/vtkMPI.h @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPI.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __vtkMPI_h +#define __vtkMPI_h + +#include "mpi.h" +#include "vtkSystemIncludes.h" + +class VTK_PARALLEL_EXPORT vtkMPICommunicatorOpaqueComm +{ +public: + vtkMPICommunicatorOpaqueComm(); + + MPI_Comm* GetHandle(); + + friend class vtkMPICommunicator; + friend class vtkMPIController; + +protected: + MPI_Comm* Handle; +}; + + +#endif // __vtkMPI_h diff --git a/Parallel/vtkMPICommunicator.cxx b/Parallel/vtkMPICommunicator.cxx new file mode 100644 index 0000000..123901a --- /dev/null +++ b/Parallel/vtkMPICommunicator.cxx @@ -0,0 +1,1297 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPICommunicator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkMPICommunicator.h" + +#include "vtkMPIController.h" +#include "vtkMPIGroup.h" +#include "vtkMPIGroup.h" +#include "vtkObjectFactory.h" +#include "vtkToolkits.h" + +#include "vtkMPI.h" + +vtkCxxRevisionMacro(vtkMPICommunicator, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkMPICommunicator); + +vtkCxxSetObjectMacro(vtkMPICommunicator,Group,vtkMPIGroup); + +vtkMPICommunicator* vtkMPICommunicator::WorldCommunicator = 0; + +class vtkMPICommunicatorOpaqueRequest +{ +public: + MPI_Request Handle; +}; + +vtkMPICommunicatorOpaqueComm::vtkMPICommunicatorOpaqueComm() +{ + this->Handle = 0; +} + +MPI_Comm* vtkMPICommunicatorOpaqueComm::GetHandle() +{ + return this->Handle; +} + +//---------------------------------------------------------------------------- +// overloaded functions for vtkIdType +#ifdef VTK_HAS_ID_TYPE +# ifdef VTK_USE_64BIT_IDS +MPI_Datatype vtkMPICommunicatorGetMPIType() +{ +#if VTK_SIZEOF_LONG == 8 + return MPI_LONG; +#elif defined(MPI_LONG_LONG) + return MPI_LONG_LONG; +#elif defined(MPI_LONG_LONG_INT) + // lampi only has MPI_LONG_LONG_INT, not MPI_LONG_LONG + return MPI_LONG_LONG_INT; +#else + vtkGenericWarningMacro("This systems MPI doesnt seem to support 64 bit ids and you have 64 bit IDs turned on. Please contact VTK mailing list."); + return MPI_INT; +#endif +} +# endif +#else +MPI_Datatype vtkMPICommunicatorGetMPIType() +{ + return MPI_INT; +} +#endif + +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorSendData(T* data, int length, int sizeoftype, + int remoteProcessId, int tag, + MPI_Datatype datatype, MPI_Comm *Handle, + int useCopy) +{ + if (useCopy) + { + int retVal; + + char* tmpData = vtkMPICommunicator::Allocate(length*sizeoftype); + memcpy(tmpData, data, length*sizeoftype); + retVal = MPI_Send(tmpData, length, datatype, remoteProcessId, tag, + *(Handle)); + vtkMPICommunicator::Free(tmpData); + return retVal; + } + else + { + return MPI_Send(data, length, datatype, remoteProcessId, tag, *(Handle)); + } +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorReceiveData(T* data, int length, int sizeoftype, + int remoteProcessId, int tag, + MPI_Datatype datatype, MPI_Comm *Handle, + int useCopy) +{ + MPI_Status status; + + if (remoteProcessId == vtkMultiProcessController::ANY_SOURCE) + { + remoteProcessId = MPI_ANY_SOURCE; + } + + if (useCopy) + { + int retVal; + char* tmpData = vtkMPICommunicator::Allocate(length*sizeoftype); + retVal = MPI_Recv(tmpData, length, datatype, remoteProcessId, tag, + *(Handle), &status); + memcpy(data, tmpData, length*sizeoftype); + vtkMPICommunicator::Free(tmpData); + return retVal; + } + else + { + return MPI_Recv(data, length, datatype, remoteProcessId, tag, + *(Handle), &status); + } +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorNoBlockSendData(T* data, int length, + int remoteProcessId, int tag, + MPI_Datatype datatype, + vtkMPICommunicator::Request& req, + MPI_Comm *Handle) +{ + return MPI_Isend(data, length, datatype, remoteProcessId, tag, + *(Handle), &req.Req->Handle); +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorNoBlockReceiveData(T* data, int length, + int remoteProcessId, int tag, + MPI_Datatype datatype, + vtkMPICommunicator::Request& req, + MPI_Comm *Handle) +{ + if (remoteProcessId == vtkMultiProcessController::ANY_SOURCE) + { + remoteProcessId = MPI_ANY_SOURCE; + } + + return MPI_Irecv(data, length, datatype, remoteProcessId, tag, + *(Handle), &req.Req->Handle); +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorBroadcastData(T* data, int length, + int root, MPI_Datatype datatype, + MPI_Comm *Handle) +{ + return MPI_Bcast(data, length, datatype, root, *(Handle)); +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorGatherData(T* data, T* to, + int sendlength, int root, + MPI_Datatype datatype, + MPI_Comm *Handle) +{ + + return MPI_Gather(data, sendlength, datatype, to, + sendlength, datatype, root, *(Handle)); +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorGatherVData(T* data, T* to, + int sendlength, int* recvlengths, + int* offsets, int root, + MPI_Datatype datatype, + MPI_Comm *Handle) +{ + return MPI_Gatherv(data, sendlength, datatype, + to, recvlengths, offsets, datatype, + root, *(Handle)); +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorAllGatherData(T* data, T* to, + int sendlength, + MPI_Datatype datatype, + MPI_Comm *Handle) +{ + return MPI_Allgather(data, sendlength, datatype, to, + sendlength, datatype, *(Handle)); +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorAllGatherVData(T* data, T* to, + int sendlength, int* recvlengths, + int* offsets, + MPI_Datatype datatype, + MPI_Comm *Handle) +{ + return MPI_Allgatherv(data, sendlength, datatype, + to, recvlengths, offsets, datatype, + *(Handle)); +} +//---------------------------------------------------------------------------- +template +int vtkMPICommunicatorReduceData(T* data, T* to, int root, + int sendlength, MPI_Datatype datatype, + MPI_Op op, MPI_Comm *Handle) +{ + return MPI_Reduce(data, to, sendlength, datatype, + op, root, *(Handle)); +} + +//---------------------------------------------------------------------------- +// Return the world communicator (i.e. MPI_COMM_WORLD). +// Create one if necessary (singleton). +vtkMPICommunicator* vtkMPICommunicator::GetWorldCommunicator() +{ + int err, size; + + if (vtkMPICommunicator::WorldCommunicator == 0) + { + vtkMPICommunicator* comm = vtkMPICommunicator::New(); + vtkMPIGroup* group = vtkMPIGroup::New(); + comm->MPIComm->Handle = new MPI_Comm; + *(comm->MPIComm->Handle) = MPI_COMM_WORLD; + comm->SetGroup(group); + group->Delete(); + group = NULL; + if ( (err = MPI_Comm_size(MPI_COMM_WORLD, &size)) != MPI_SUCCESS ) + { + char *msg = vtkMPIController::ErrorString(err); + vtkGenericWarningMacro("MPI error occured: " << msg); + delete[] msg; + delete comm->MPIComm->Handle; + comm->MPIComm = 0; + comm->Delete(); + return 0; + } + comm->Group->Initialize(size); + for(int i=0; iGroup->AddProcessId(i); + } + comm->Initialized = 1; + comm->KeepHandleOn(); + vtkMPICommunicator::WorldCommunicator = comm; + } + return vtkMPICommunicator::WorldCommunicator; +} + +//---------------------------------------------------------------------------- +void vtkMPICommunicator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Group: "; + if (this->Group) + { + os << endl; + this->Group->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)\n"; + } + os << indent << "MPI Communicator handler: " ; + if (this->MPIComm->Handle) + { + os << this->MPIComm->Handle << endl; + } + else + { + os << "(none)\n"; + } + os << indent << "Initialized: " << (this->Initialized ? "On\n" : "Off\n"); + os << indent << "Keep handle: " << (this->KeepHandle ? "On\n" : "Off\n"); + if ( this != vtkMPICommunicator::WorldCommunicator ) + { + os << indent << "World communicator: "; + if (vtkMPICommunicator::WorldCommunicator) + { + os << endl; + vtkMPICommunicator::WorldCommunicator->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)"; + } + os << endl; + } + return; +} + +//---------------------------------------------------------------------------- +vtkMPICommunicator::vtkMPICommunicator() +{ + this->MPIComm = new vtkMPICommunicatorOpaqueComm; + this->Group = 0; + this->Initialized = 0; + this->KeepHandle = 0; +} + +//---------------------------------------------------------------------------- +vtkMPICommunicator::~vtkMPICommunicator() +{ + // Free the handle if required and asked for. + if (this->MPIComm) + { + if (this->MPIComm->Handle && !this->KeepHandle ) + { + if (*(this->MPIComm->Handle) != MPI_COMM_NULL) + { + MPI_Comm_free(this->MPIComm->Handle); + } + } + delete this->MPIComm->Handle; + delete this->MPIComm; + } + this->SetGroup(0); +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Initialize(vtkMPICommunicator* mpiComm, + vtkMPIGroup* group) +{ + if (this->Initialized) + { + return 0; + } + + // If mpiComm has been initialized, it is guaranteed (unless + // the MPI calls return an error somewhere) to have valid + // Communicator and Group + if (!mpiComm->Initialized) + { + vtkWarningMacro("The communicator passed has not been initialized!"); + return 0; + } + + this->KeepHandleOff(); + + int nProcIds = group->GetNumberOfProcessIds(); + // The new group has to be a sub-class + if ( ( nProcIds <= 0) || + ( mpiComm->Group == 0 ) || + ( nProcIds > mpiComm->Group->GetNumberOfProcessIds() ) ) + { + vtkWarningMacro("The group or the communicator has " + << "invalid number of ids."); + return 0; + } + + + // Select the new processes + int* ranks = new int[nProcIds]; + for(int i=0; iGetProcessId(i); + } + + MPI_Group superGroup; + MPI_Group subGroup; + + // Get the group from the argument + int err; + if ( (err = MPI_Comm_group(*(mpiComm->MPIComm->Handle), &superGroup)) + != MPI_SUCCESS ) + { + delete[] ranks; + MPI_Group_free(&superGroup); + + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + + return 0; + } + + // Create a new group by including the process ids in group + if ( (err = MPI_Group_incl(superGroup, nProcIds, ranks, &subGroup)) + != MPI_SUCCESS ) + { + delete[] ranks; + MPI_Group_free(&superGroup); + MPI_Group_free(&subGroup); + + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + + return 0; + } + + delete[] ranks; + MPI_Group_free(&superGroup); + + this->MPIComm->Handle = new MPI_Comm; + // Create the communicator from the group + if ( (err = MPI_Comm_create(*(mpiComm->MPIComm->Handle), subGroup, + this->MPIComm->Handle) ) + != MPI_SUCCESS ) + { + MPI_Group_free(&subGroup); + delete this->MPIComm->Handle; + this->MPIComm->Handle = 0; + + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + + return 0; + } + + MPI_Group_free(&subGroup); + + this->Initialized = 1; + + // Store the group so that this communicator can be used + // to create new ones + this->SetGroup(group); + + this->Modified(); + + return 1; + +} + +//---------------------------------------------------------------------------- +// Start the copying process +void vtkMPICommunicator::InitializeCopy(vtkMPICommunicator* source) +{ + if(!source) + { + return; + } + + this->SetGroup(0); + vtkMPIGroup* group = vtkMPIGroup::New(); + this->SetGroup(group); + group->Delete(); + group = 0; + this->Group->CopyFrom(source->Group); + + if (this->MPIComm->Handle && !this->KeepHandle) + { + MPI_Comm_free(this->MPIComm->Handle); + } + delete this->MPIComm->Handle; + this->MPIComm->Handle = 0; + + this->Initialized = source->Initialized; + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Copy the MPI handle +void vtkMPICommunicator::CopyFrom(vtkMPICommunicator* source) +{ + this->InitializeCopy(source); + + if (source->MPIComm->Handle) + { + this->KeepHandleOn(); + this->MPIComm->Handle = new MPI_Comm; + *(this->MPIComm->Handle) = *(source->MPIComm->Handle); + } +} + +//---------------------------------------------------------------------------- +// Duplicate the MPI handle +void vtkMPICommunicator::Duplicate(vtkMPICommunicator* source) +{ + this->InitializeCopy(source); + + this->KeepHandleOff(); + + if (source->MPIComm->Handle) + { + this->MPIComm->Handle = new MPI_Comm; + int err; + if ( (err = MPI_Comm_dup(*(source->MPIComm->Handle), this->MPIComm->Handle)) + != MPI_SUCCESS ) + { + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + } + } +} + +//---------------------------------------------------------------------------- +char* vtkMPICommunicator::Allocate(size_t size) +{ +#ifdef MPIPROALLOC + char* ptr; + MPI_Alloc_mem(size, NULL, &ptr); + return ptr; +#else + return new char[size]; +#endif +} + +//---------------------------------------------------------------------------- +void vtkMPICommunicator::Free(char* ptr) +{ +#ifdef MPIPROALLOC + MPI_Free_mem(ptr); +#else + delete[] ptr; +#endif +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::CheckForMPIError(int err) +{ + + if ( err == MPI_SUCCESS ) + { + return 1; + } + else + { + char *msg = vtkMPIController::ErrorString(err); + vtkGenericWarningMacro("MPI error occured: " << msg); + delete[] msg; + return 0; + } + +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Send(int* data, int length, int remoteProcessId, + int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorSendData(data, length, + sizeof(int), remoteProcessId, tag, + MPI_INT, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Send(unsigned long* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorSendData(data, length, + sizeof(unsigned long), remoteProcessId, tag, + MPI_UNSIGNED_LONG, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Send(char* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorSendData(data, length, + sizeof(char), remoteProcessId, tag, + MPI_CHAR, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Send(unsigned char* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorSendData(data, length, + sizeof(unsigned char), remoteProcessId, tag, + MPI_UNSIGNED_CHAR, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Send(float* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorSendData(data, length, + sizeof(float), remoteProcessId, tag, + MPI_FLOAT, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Send(double* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorSendData(data, length, + sizeof(double), remoteProcessId, tag, + MPI_DOUBLE, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +int vtkMPICommunicator::Send(vtkIdType* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorSendData(data, length, + sizeof(vtkIdType), remoteProcessId, tag, + vtkMPICommunicatorGetMPIType(), + this->MPIComm->Handle, vtkCommunicator::UseCopy)); +} +#endif + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockSend(int* data, int length, + int remoteProcessId, int tag, + Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockSendData(data, + length, remoteProcessId, + tag, MPI_INT, req, this->MPIComm->Handle)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockSend(unsigned long* data, int length, + int remoteProcessId, int tag, + Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockSendData(data, + length, remoteProcessId, + tag, MPI_UNSIGNED_LONG, req, + this->MPIComm->Handle)); + + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockSend(char* data, int length, + int remoteProcessId, int tag, Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockSendData(data, + length, remoteProcessId, + tag, MPI_CHAR, req, this->MPIComm->Handle)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockSend(float* data, int length, + int remoteProcessId, int tag, Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockSendData(data, + length, remoteProcessId, + tag, MPI_FLOAT, req, + this->MPIComm->Handle)); +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Receive(int* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorReceiveData(data, length, + sizeof(int), remoteProcessId, tag, + MPI_INT, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Receive(unsigned long* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorReceiveData(data, length, + sizeof(unsigned long), + remoteProcessId, tag, + MPI_UNSIGNED_LONG, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Receive(char* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorReceiveData(data, length, + sizeof(char), remoteProcessId, tag, + MPI_CHAR, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Receive(unsigned char* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorReceiveData(data, length, + sizeof(unsigned char), remoteProcessId, + tag, MPI_UNSIGNED_CHAR, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Receive(float* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorReceiveData(data, length, + sizeof(float), remoteProcessId, tag, + MPI_FLOAT, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); + +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Receive(double* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorReceiveData(data, length, + sizeof(double), remoteProcessId, tag, + MPI_DOUBLE, this->MPIComm->Handle, + vtkCommunicator::UseCopy)); + +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +int vtkMPICommunicator::Receive(vtkIdType* data, int length, + int remoteProcessId, int tag) +{ + + return CheckForMPIError( + vtkMPICommunicatorReceiveData(data, length, + sizeof(vtkIdType), remoteProcessId, tag, + vtkMPICommunicatorGetMPIType(), + this->MPIComm->Handle, vtkCommunicator::UseCopy)); +} +#endif + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockReceive(int* data, int length, + int remoteProcessId, int tag, + Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockReceiveData(data, + length, remoteProcessId, + tag, MPI_INT, req, + this->MPIComm->Handle)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockReceive(unsigned long* data, int length, + int remoteProcessId, int tag, + Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockReceiveData(data, + length, remoteProcessId, + tag, MPI_UNSIGNED_LONG, req, + this->MPIComm->Handle)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockReceive(char* data, int length, + int remoteProcessId, int tag, + Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockReceiveData(data, + length, remoteProcessId, + tag, MPI_CHAR, req, + this->MPIComm->Handle)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::NoBlockReceive(float* data, int length, + int remoteProcessId, int tag, + Request& req) +{ + + return CheckForMPIError( + vtkMPICommunicatorNoBlockReceiveData(data, + length, remoteProcessId, + tag, MPI_FLOAT, req, + this->MPIComm->Handle)); + +} + +//---------------------------------------------------------------------------- +vtkMPICommunicator::Request::Request() +{ + this->Req = new vtkMPICommunicatorOpaqueRequest; +} + +//---------------------------------------------------------------------------- +vtkMPICommunicator::Request::~Request() +{ + delete this->Req; +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Request::Test() +{ + MPI_Status status; + int retVal; + + int err = MPI_Test(&this->Req->Handle, &retVal, &status); + + if ( err == MPI_SUCCESS ) + { + return retVal; + } + else + { + char *msg = vtkMPIController::ErrorString(err); + vtkGenericWarningMacro("MPI error occured: " << msg); + delete[] msg; + return 0; + } +} + +//---------------------------------------------------------------------------- +void vtkMPICommunicator::Request::Wait() +{ + MPI_Status status; + + int err = MPI_Wait(&this->Req->Handle, &status); + + if ( err != MPI_SUCCESS ) + { + char *msg = vtkMPIController::ErrorString(err); + vtkGenericWarningMacro("MPI error occured: " << msg); + delete[] msg; + } +} + +//---------------------------------------------------------------------------- +void vtkMPICommunicator::Request::Cancel() +{ + int err = MPI_Cancel(&this->Req->Handle); + + if ( err != MPI_SUCCESS ) + { + char *msg = vtkMPIController::ErrorString(err); + vtkGenericWarningMacro("MPI error occured: " << msg); + delete[] msg; + } + + err = MPI_Request_free(&this->Req->Handle); + + if ( err != MPI_SUCCESS ) + { + char *msg = vtkMPIController::ErrorString(err); + vtkGenericWarningMacro("MPI error occured: " << msg); + delete[] msg; + } +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Broadcast(int* data, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorBroadcastData(data, length, root, MPI_INT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Broadcast(unsigned long* data, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorBroadcastData(data, length, root, MPI_UNSIGNED_LONG, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Broadcast(char* data, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorBroadcastData(data, length, root, MPI_CHAR, + this->MPIComm->Handle)); + +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Broadcast(float* data, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorBroadcastData(data, length, root, MPI_FLOAT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Broadcast(double* data, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorBroadcastData(data, length, root, MPI_DOUBLE, + this->MPIComm->Handle)); +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Gather(int* data, int* to, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherData(data, to, length, root, MPI_INT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Gather(unsigned long* data, unsigned long* to, + int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherData(data, to, length, root, MPI_UNSIGNED_LONG, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Gather(char* data, char* to, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherData(data, to, length, root, MPI_CHAR, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Gather(float* data, float* to, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherData(data, to, length, root, MPI_FLOAT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::Gather(double* data, double* to, int length, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherData(data, to, length, root, MPI_DOUBLE, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::GatherV(int* data, int* to, + int sendlength, int* recvlengths, + int* offsets, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherVData(data, to, + sendlength, recvlengths, offsets, + root, MPI_INT, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::GatherV(unsigned long* data, unsigned long* to, + int sendlength, int* recvlengths, + int* offsets, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherVData(data, to, + sendlength, recvlengths, offsets, + root, MPI_UNSIGNED_LONG, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::GatherV(char* data, char* to, + int sendlength, int* recvlengths, + int* offsets, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherVData(data, to, + sendlength, recvlengths, offsets, + root, MPI_CHAR, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::GatherV(float* data, float* to, + int sendlength, int* recvlengths, + int* offsets, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherVData(data, to, + sendlength, recvlengths, offsets, + root, MPI_FLOAT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::GatherV(double* data, double* to, + int sendlength, int* recvlengths, + int* offsets, int root) +{ + + return CheckForMPIError( + vtkMPICommunicatorGatherVData(data, to, + sendlength, recvlengths, offsets, + root, MPI_DOUBLE, + this->MPIComm->Handle)); +} + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGather(int* data, int* to, int length) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherData(data, to, length, MPI_INT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGather(unsigned long* data, unsigned long* to, + int length) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherData(data, to, length, MPI_UNSIGNED_LONG, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGather(char* data, char* to, int length) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherData(data, to, length, MPI_CHAR, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGather(float* data, float* to, int length) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherData(data, to, length, MPI_FLOAT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGather(double* data, double* to, int length) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherData(data, to, length, MPI_DOUBLE, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGatherV(int* data, int* to, + int sendlength, int* recvlengths, + int* offsets) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherVData(data, to, + sendlength, recvlengths, offsets, + MPI_INT, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGatherV(unsigned long* data, unsigned long* to, + int sendlength, int* recvlengths, + int* offsets) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherVData(data, to, + sendlength, recvlengths, offsets, + MPI_UNSIGNED_LONG, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGatherV(char* data, char* to, + int sendlength, int* recvlengths, + int* offsets) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherVData(data, to, + sendlength, recvlengths, offsets, + MPI_CHAR, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGatherV(float* data, float* to, + int sendlength, int* recvlengths, + int* offsets) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherVData(data, to, + sendlength, recvlengths, offsets, + MPI_FLOAT, + this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::AllGatherV(double* data, double* to, + int sendlength, int* recvlengths, + int* offsets) +{ + + return CheckForMPIError( + vtkMPICommunicatorAllGatherVData(data, to, + sendlength, recvlengths, offsets, + MPI_DOUBLE, + this->MPIComm->Handle)); +} + + + +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMax(int* data, int* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_INT, + MPI_MAX, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMax(unsigned long* data, unsigned long* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_LONG, + MPI_MAX, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMax(float* data, float* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_FLOAT, + MPI_MAX, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMax(double* data, double* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_DOUBLE, + MPI_MAX, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMin(int* data, int* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_INT, + MPI_MIN, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMin(unsigned long* data, unsigned long* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_LONG, + MPI_MIN, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMin(float* data, float* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_FLOAT, + MPI_MIN, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceMin(double* data, double* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_DOUBLE, + MPI_MIN, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceSum(int* data, int* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_INT, + MPI_SUM, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceSum(unsigned long* data, unsigned long* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_LONG, + MPI_SUM, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceSum(float* data, float* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_FLOAT, + MPI_SUM, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceSum(double* data, double* to, + int sendlength, int root) +{ + return CheckForMPIError( + vtkMPICommunicatorReduceData(data, to, + root, sendlength, MPI_DOUBLE, + MPI_SUM, this->MPIComm->Handle)); +} +//---------------------------------------------------------------------------- +// There is no MPI data type bool in the C binding of MPI +// -> convert to int! +int vtkMPICommunicator::ReduceAnd(bool* data, bool* to, + int size, int root) +{ + int i; + + int *intsbuffer; + int *intrbuffer; + + intsbuffer = new int[size]; + intrbuffer = new int[size]; + + for (i = 0; i < size; ++i) + { + intsbuffer[i] = (data[i] ? 1 : 0); + } + + int err = CheckForMPIError( + vtkMPICommunicatorReduceData(intsbuffer, intrbuffer, + root, size, MPI_INT, + MPI_LAND, this->MPIComm->Handle)); + + for (i = 0; i < size; ++i) + { + to[i] = (intrbuffer[i] == 1); + } + + delete [] intsbuffer; + delete [] intrbuffer; + + return err; +} +//---------------------------------------------------------------------------- +int vtkMPICommunicator::ReduceOr(bool* data, bool* to, + int size, int root) +{ + int *intsbuffer; + int *intrbuffer; + int i; + + intsbuffer = new int[size]; + intrbuffer = new int[size]; + + for (i = 0; i < size; ++i) + { + intsbuffer[i] = (data[i] ? 1 : 0); + } + + int err = CheckForMPIError( + vtkMPICommunicatorReduceData(intsbuffer, intrbuffer, + root, size, MPI_INT, + MPI_LOR, this->MPIComm->Handle)); + + for (i = 0; i < size; ++i) + { + to[i] = (intrbuffer[i] == 1); + } + + delete [] intsbuffer; + delete [] intrbuffer; + + return err; +} +//---------------------------------------------------------------------------- diff --git a/Parallel/vtkMPICommunicator.h b/Parallel/vtkMPICommunicator.h new file mode 100644 index 0000000..4f904ad --- /dev/null +++ b/Parallel/vtkMPICommunicator.h @@ -0,0 +1,313 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPICommunicator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMPICommunicator - Class for creating user defined MPI communicators. + +// .SECTION Description +// This class can be used to create user defined MPI communicators. +// The actual creation (with MPI_Comm_create) occurs in Initialize +// which takes as arguments a super-communicator and a group of +// process ids. The new communicator is created by including the +// processes contained in the group. The global communicator +// (equivalent to MPI_COMM_WORLD) can be obtained using the class +// method GetWorldCommunicator. It is important to note that +// this communicator should not be used on the processes not contained +// in the group. For example, if the group contains processes 0 and 1, +// controller->SetCommunicator(communicator) would cause an MPI error +// on any other process. + +// .SECTION See Also +// vtkMPIController vtkMPIGroup + +#ifndef __vtkMPICommunicator_h +#define __vtkMPICommunicator_h + +#include "vtkCommunicator.h" + +class vtkMPIController; +class vtkMPIGroup; + +class vtkMPICommunicatorOpaqueRequest; +class vtkMPICommunicatorOpaqueComm; + +class VTK_PARALLEL_EXPORT vtkMPICommunicator : public vtkCommunicator +{ +public: + vtkTypeRevisionMacro( vtkMPICommunicator,vtkCommunicator); + + // Description: + // Creates an empty communicator. + static vtkMPICommunicator* New(); + + // Description: + // Returns the singleton which behaves as the global + // communicator (MPI_COMM_WORLD) + static vtkMPICommunicator* GetWorldCommunicator(); + + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Used to initialize (i.e. create the underlying MPI_Comm) + // the communicator. Note that group is also stored in + // an instance variable (the reference count of group + // is increased by 1). group->Delete() can be safely invoked after + // this. + int Initialize(vtkMPICommunicator* mpiComm, vtkMPIGroup* group); + + // Description: + // This method sends data to another process. Tag eliminates ambiguity + // when multiple sends or receives exist in the same process. + virtual int Send(int* data, int length, int remoteProcessId, int tag); + virtual int Send(unsigned long* data, int length, int remoteProcessId, + int tag); + virtual int Send(char* data, int length, int remoteProcessId, int tag); + virtual int Send(unsigned char* data, int length, int remoteProcessId, + int tag); + virtual int Send(float* data, int length, int remoteProcessId, + int tag); + virtual int Send(double* data, int length, int remoteProcessId, + int tag); +#ifdef VTK_USE_64BIT_IDS + virtual int Send(vtkIdType* data, int length, int remoteProcessId, + int tag); +#endif + virtual int Send(vtkDataObject* data, int remoteProcessId, int tag) + { return this->vtkCommunicator::Send(data, remoteProcessId, tag); } + virtual int Send(vtkDataArray* data, int remoteProcessId, int tag) + { return this->vtkCommunicator::Send(data, remoteProcessId, tag); } + +//BTX + + class VTK_PARALLEL_EXPORT Request + { + public: + Request(); + ~Request(); + int Test(); + void Cancel(); + void Wait(); + vtkMPICommunicatorOpaqueRequest* Req; + }; + +//ETX + + // Description: + // This method sends data to another process (non-blocking). + // Tag eliminates ambiguity when multiple sends or receives + // exist in the same process. The last argument, + // vtkMPICommunicator::Request& req can later be used (with + // req.Test() ) to test the success of the message. + int NoBlockSend(int* data, int length, int remoteProcessId, int tag, + Request& req); + int NoBlockSend(unsigned long* data, int length, int remoteProcessId, + int tag, Request& req); + int NoBlockSend(char* data, int length, int remoteProcessId, + int tag, Request& req); + int NoBlockSend(float* data, int length, int remoteProcessId, + int tag, Request& req); + + // Description: + // This method receives data from a corresponding send. It blocks + // until the receive is finished. + virtual int Receive(int* data, int length, int remoteProcessId, + int tag); + virtual int Receive(unsigned long* data, int length, + int remoteProcessId, int tag); + virtual int Receive(char* data, int length, int remoteProcessId, + int tag); + virtual int Receive(unsigned char* data, int length, int remoteProcessId, + int tag); + virtual int Receive(float* data, int length, int remoteProcessId, + int tag); + virtual int Receive(double* data, int length, int remoteProcessId, + int tag); +#ifdef VTK_USE_64BIT_IDS + virtual int Receive(vtkIdType* data, int length, int remoteProcessId, + int tag); +#endif + virtual int Receive(vtkDataObject* data, int remoteProcessId, int tag) + { return this->vtkCommunicator::Receive(data, remoteProcessId, tag); } + virtual int Receive(vtkDataArray* data, int remoteProcessId, int tag) + { return this->vtkCommunicator::Receive(data, remoteProcessId, tag); } + + // Description: + // This method receives data from a corresponding send (non-blocking). + // The last argument, + // vtkMPICommunicator::Request& req can later be used (with + // req.Test() ) to test the success of the message. + int NoBlockReceive(int* data, int length, int remoteProcessId, + int tag, Request& req); + int NoBlockReceive(unsigned long* data, int length, + int remoteProcessId, int tag, Request& req); + int NoBlockReceive(char* data, int length, int remoteProcessId, + int tag, Request& req); + int NoBlockReceive(float* data, int length, int remoteProcessId, + int tag, Request& req); + + + // Description: + // Broadcast an array from the given root process. + int Broadcast(int* data , int length, int root); + int Broadcast(unsigned long* data, int length, int root); + int Broadcast(char* data , int length, int root); + int Broadcast(float* data , int length, int root); + int Broadcast(double* data , int length, int root); + + + // Description: + // Gather an array to the given root process (the "to" pointer + // must point to an array of length length*numProcesses + int Gather(int* data , int* to , int length, int root); + int Gather(unsigned long* data, unsigned long* to, int length, int root); + int Gather(char* data , char* to , int length, int root); + int Gather(float* data , float* to , int length, int root); + int Gather(double* data , double* to , int length, int root); + + // Description: + // Gather an array to the given root process. This method + // allows for arrays of different sizes on all processes + // to be gathered into a single array on the root process. For the + // root process, all arguments are significant, on non-root + // processes, only data, sendlength, and root are significant + // (all other args can be NULL). The argument offsets is an array + // of integers describing offset for each sent array. + int GatherV(int* data, int* to, + int sendlength, int* recvlengths, int* offsets, int root); + int GatherV(unsigned long* data, unsigned long* to, + int sendlength, int* recvlengths, int* offsets, int root); + int GatherV(char* data, char* to, + int sendlength, int* recvlengths, int* offsets, int root); + int GatherV(float* data, float* to, + int sendlength, int* recvlengths, int* offsets, int root); + int GatherV(double* data, double* to, + int sendlength, int* recvlengths, int* offsets, int root); + + + // Description: + // Same as Gather, but result ends up on all processes. + // Length is the length of the data array (input). This length + // has to be the same on all processes. The recv/output array 'to' + // has to be length (length*numprocs). + int AllGather(int* data , int* to , int length); + int AllGather(unsigned long* data, unsigned long* to, int length); + int AllGather(char* data , char* to , int length); + int AllGather(float* data , float* to , int length); + int AllGather(double* data , double* to , int length); + + // Description: + // same as gather, but the arrays can be different lengths on + // different processes. ProcId is the index into recvLengths + // and recvOffsets. These arrays determine how all the the arrays + // are packed into the received arra 'to'. + int AllGatherV(int* data, int* to, + int sendlength, int* recvlengths, int* recvOffsets); + int AllGatherV(unsigned long* data, unsigned long* to, + int sendlength, int* recvlengths, int* recvOffsets); + int AllGatherV(char* data, char* to, + int sendlength, int* recvlengths, int* recvOffsets); + int AllGatherV(float* data, float* to, + int sendlength, int* recvlengths, int* recvOffsets); + int AllGatherV(double* data, double* to, + int sendlength, int* recvlengths, int* recvOffsets); + +// Description: + // Reduce an array to the given root process. + int ReduceMax(int* data, int* to, int size, int root); + int ReduceMax(unsigned long* data, unsigned long* to, int size, int root); + int ReduceMax(float* data, float* to, int size, int root); + int ReduceMax(double* data, double* to, int size, int root); + + int ReduceMin(int* data, int* to, int size, int root); + int ReduceMin(unsigned long* data, unsigned long* to, int size, int root); + int ReduceMin(float* data, float* to, int size, int root); + int ReduceMin(double* data, double* to, int size, int root); + + int ReduceSum(int* data, int* to, int size, int root); + int ReduceSum(unsigned long* data, unsigned long* to, int size, int root); + int ReduceSum(float* data, float* to, int size, int root); + int ReduceSum(double* data, double* to, int size, int root); + + int ReduceAnd(bool* data, bool* to, int size, int root); + int ReduceOr(bool* data, bool* to, int size, int root); + + +//BTX + + friend class vtkMPIController; + + vtkMPICommunicatorOpaqueComm *GetMPIComm() + { + return this->MPIComm; + } +//ETX + + static char* Allocate(size_t size); + static void Free(char* ptr); + + +protected: + vtkMPICommunicator(); + ~vtkMPICommunicator(); + + virtual void SetGroup(vtkMPIGroup*); + + // Description: + // KeepHandle is normally off. This means that the MPI + // communicator handle will be freed at the destruction + // of the object. However, if the handle was copied from + // another object (via CopyFrom() not Duplicate()), this + // has to be turned on otherwise the handle will be freed + // multiple times causing MPI failure. The alternative to + // this is using reference counting but it is unnecessarily + // complicated for this case. + vtkSetMacro(KeepHandle, int); + vtkBooleanMacro(KeepHandle, int); + + + static vtkMPICommunicator* WorldCommunicator; + + void InitializeCopy(vtkMPICommunicator* source); + + // Description: + // Copies all the attributes of source, deleting previously + // stored data. The MPI communicator handle is also copied. + // Normally, this should not be needed. It is used during + // the construction of a new communicator for copying the + // world communicator, keeping the same context. + void CopyFrom(vtkMPICommunicator* source); + + // Description: + // Copies all the attributes of source, deleting previously + // stored data EXCEPT the MPI communicator handle which is + // duplicated with MPI_Comm_dup(). Therefore, although the + // processes in the communicator remain the same, a new context + // is created. This prevents the two communicators from + // intefering with each other during message send/receives even + // if the tags are the same. + void Duplicate(vtkMPICommunicator* source); + + vtkMPICommunicatorOpaqueComm* MPIComm; + vtkMPIGroup* Group; + + int Initialized; + int KeepHandle; + + static int CheckForMPIError(int err); + +private: + vtkMPICommunicator(const vtkMPICommunicator&); // Not implemented. + void operator=(const vtkMPICommunicator&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkMPIController.cxx b/Parallel/vtkMPIController.cxx new file mode 100644 index 0000000..d421ae6 --- /dev/null +++ b/Parallel/vtkMPIController.cxx @@ -0,0 +1,334 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkMPIController.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMPIController.h" + +#include "vtkObjectFactory.h" +#include "vtkOutputWindow.h" + +#include "vtkMPI.h" + +int vtkMPIController::Initialized = 0; +char vtkMPIController::ProcessorName[MPI_MAX_PROCESSOR_NAME] = ""; + +// Output window which prints out the process id +// with the error or warning messages +class VTK_PARALLEL_EXPORT vtkMPIOutputWindow : public vtkOutputWindow +{ +public: + vtkTypeRevisionMacro(vtkMPIOutputWindow,vtkOutputWindow); + + void DisplayText(const char* t) + { + if (this->Controller) + { + cout << "Process id: " << this->Controller->GetLocalProcessId() + << " >> "; + } + cout << t; + } + + vtkMPIOutputWindow() + { + vtkObject* ret = vtkObjectFactory::CreateInstance("vtkMPIOutputWindow"); + if (ret) + ret->Delete(); + this->Controller = 0; + } + + friend class vtkMPIController; + +protected: + + vtkMPIController* Controller; + vtkMPIOutputWindow(const vtkMPIOutputWindow&); + void operator=(const vtkMPIOutputWindow&); + +}; + +void vtkMPIController::CreateOutputWindow() +{ + vtkMPIOutputWindow* window = new vtkMPIOutputWindow; + window->Controller = this; + this->OutputWindow = window; + vtkOutputWindow::SetInstance(this->OutputWindow); +} + +vtkCxxRevisionMacro(vtkMPIOutputWindow, "$Revision: 1.20 $"); + +vtkCxxRevisionMacro(vtkMPIController, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkMPIController); + +//---------------------------------------------------------------------------- +vtkMPIController::vtkMPIController() +{ + // If MPI was already initialized obtain rank and size. + if (vtkMPIController::Initialized) + { + this->InitializeCommunicator(vtkMPICommunicator::GetWorldCommunicator()); + // Copy vtkMPIController::WorldRMICommunicataor which is created when + // MPI is initialized + vtkMPICommunicator* comm = vtkMPICommunicator::New(); + comm->CopyFrom(vtkMPIController::WorldRMICommunicator); + this->RMICommunicator = comm; + } + + this->OutputWindow = 0; +} + +//---------------------------------------------------------------------------- +vtkMPIController::~vtkMPIController() +{ + this->SetCommunicator(0); + if (this->RMICommunicator) + { + this->RMICommunicator->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkMPIController::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Initialized: " << ( vtkMPIController::Initialized ? "(yes)" : "(no)" ) << endl; +} + +// Set the number of processes and maximum number of processes +// to the size obtained from MPI. +int vtkMPIController::InitializeNumberOfProcesses() +{ + int err; + + this->Modified(); + + vtkMPICommunicator* comm = (vtkMPICommunicator*)this->Communicator; + if ( (err = MPI_Comm_size(*(comm->MPIComm->Handle), + &(this->MaximumNumberOfProcesses))) + != MPI_SUCCESS ) + { + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + return 0; + } + + if (this->MaximumNumberOfProcesses > MAX_PROCESSES) + { + vtkWarningMacro("Maximum of " << MAX_PROCESSES); + this->MaximumNumberOfProcesses = MAX_PROCESSES; + } + + this->NumberOfProcesses = this->MaximumNumberOfProcesses; + + if ( (err = MPI_Comm_rank(*(comm->MPIComm->Handle),&(this->LocalProcessId))) + != MPI_SUCCESS) + { + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + return 0; + } + return 1; +} + +vtkMPICommunicator* vtkMPIController::WorldRMICommunicator=0; + +//---------------------------------------------------------------------------- +void vtkMPIController::Initialize(int* argc, char*** argv, + int initializedExternally) +{ + if (vtkMPIController::Initialized) + { + vtkWarningMacro("Already initialized."); + return; + } + + // Can be done once in the program. + vtkMPIController::Initialized = 1; + if (initializedExternally == 0) + { + MPI_Init(argc, argv); + } + this->InitializeCommunicator(vtkMPICommunicator::GetWorldCommunicator()); + this->InitializeNumberOfProcesses(); + + int tmp; + MPI_Get_processor_name(ProcessorName, &tmp); + // Make a copy of MPI_COMM_WORLD creating a new context. + // This is used in the creating of the communicators after + // Initialize() has been called. It has to be done here + // because for this to work, all processes have to call + // MPI_Comm_dup and this is the only method which is + // guaranteed to be called by all processes. + vtkMPIController::WorldRMICommunicator = vtkMPICommunicator::New(); + vtkMPIController::WorldRMICommunicator->Duplicate((vtkMPICommunicator*)this->Communicator); + this->RMICommunicator = vtkMPIController::WorldRMICommunicator; + // Since we use Delete to get rid of the reference, we should use NULL to register. + this->RMICommunicator->Register(NULL); + + this->Modified(); +} + +const char* vtkMPIController::GetProcessorName() +{ + return ProcessorName; +} + +// Good-bye world +// There should be no MPI calls after this. +// (Except maybe MPI_XXX_free()) unless finalized externally. +void vtkMPIController::Finalize(int finalizedExternally) +{ + if (vtkMPIController::Initialized) + { + vtkMPIController::WorldRMICommunicator->Delete(); + vtkMPIController::WorldRMICommunicator = 0; + vtkMPICommunicator::WorldCommunicator->Delete(); + this->SetCommunicator(0); + if (this->RMICommunicator) + { + this->RMICommunicator->Delete(); + this->RMICommunicator = 0; + } + if (finalizedExternally == 0) + { + MPI_Finalize(); + } + vtkMPIController::Initialized = 0; + this->Modified(); + } + +} + +// Called by SetCommunicator and constructor. It frees but does +// not set RMIHandle (which should not be set by using MPI_Comm_dup +// during construction). +void vtkMPIController::InitializeCommunicator(vtkMPICommunicator* comm) +{ + if (this->Communicator != comm) + { + if (this->Communicator != 0) + { + this->Communicator->UnRegister(this); + } + this->Communicator = comm; + if (this->Communicator != 0) + { + this->Communicator->Register(this); + } + + if (comm && comm->MPIComm->Handle) + { + this->InitializeNumberOfProcesses(); + } + this->Modified(); + } + + +} + +// Delete the previous RMI communicator and creates a new one +// by duplicating the user communicator. +void vtkMPIController::InitializeRMICommunicator() +{ + if ( this->RMICommunicator ) + { + this->RMICommunicator->Delete(); + this->RMICommunicator = 0; + } + if (this->Communicator) + { + this->RMICommunicator = vtkMPICommunicator::New(); + ((vtkMPICommunicator*)this->RMICommunicator)->Duplicate((vtkMPICommunicator*)this->Communicator); + } +} + +void vtkMPIController::SetCommunicator(vtkMPICommunicator* comm) +{ + this->InitializeCommunicator(comm); + this->InitializeRMICommunicator(); +} + + +void vtkMPIController::Barrier() +{ + vtkMPICommunicator* comm = (vtkMPICommunicator*)this->Communicator; + int err; + if ( (err = MPI_Barrier(*(comm->MPIComm->Handle)) ) + != MPI_SUCCESS ) + { + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + } +} + +//---------------------------------------------------------------------------- +// Execute the method set as the SingleMethod. +void vtkMPIController::SingleMethodExecute() +{ + if(!vtkMPIController::Initialized) + { + vtkWarningMacro("MPI has to be initialized first."); + return; + } + + if (this->LocalProcessId < this->NumberOfProcesses) + { + if (this->SingleMethod) + { + vtkMultiProcessController::SetGlobalController(this); + (this->SingleMethod)(this, this->SingleData); + } + else + { + vtkWarningMacro("SingleMethod not set."); + } + } +} + +//---------------------------------------------------------------------------- +// Execute the methods set as the MultipleMethods. +void vtkMPIController::MultipleMethodExecute() +{ + if(!vtkMPIController::Initialized) + { + vtkWarningMacro("MPI has to be initialized first."); + return; + } + + int i = this->LocalProcessId; + + if (this->LocalProcessId < this->NumberOfProcesses) + { + if (this->MultipleMethod[i]) + { + vtkMultiProcessController::SetGlobalController(this); + (this->MultipleMethod[i])(this, this->MultipleData[i]); + } + else + { + vtkWarningMacro("MultipleMethod " << i << " not set."); + } + } +} + +char* vtkMPIController::ErrorString(int err) +{ + char* buffer = new char[MPI_MAX_ERROR_STRING]; + int resLen; + MPI_Error_string(err, buffer, &resLen); + return buffer; +} + diff --git a/Parallel/vtkMPIController.h b/Parallel/vtkMPIController.h new file mode 100644 index 0000000..297004c --- /dev/null +++ b/Parallel/vtkMPIController.h @@ -0,0 +1,210 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPIController.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMPIController - Process communication using MPI +// .SECTION Description +// vtkMPIController is a concrete class which implements the +// abstract multi-process control methods defined in vtkMultiProcessController +// using MPI (Message Passing Interface) +// cf. Using MPI / Portable Parallel Programming with the Message-Passing +// Interface, Gropp et al, MIT Press. +// It also provide functionality specific to MPI and not present in +// vtkMultiProcessController. +// Before any MPI communication can occur Initialize() must be called +// by all processes. It is required to be called once, controllers +// created after this need not call Initialize(). +// At the end of the program Finalize() must be called by all +// processes. +// The use of user-defined communicators are supported with +// vtkMPICommunicator and vtkMPIGroup. Note that a duplicate of +// the user defined communicator is used for internal communications (RMIs). +// This communicator has the same properties as the user one except that +// it has a new context which prevents the two communicators from +// interfering with each other. + +// .SECTION see also +// vtkOutputPort vtkInputPort vtkMultiProcessController +// vtkMPICommunicator vtkMPIGroup + +#ifndef __vtkMPIController_h +#define __vtkMPIController_h + +#include "vtkMultiProcessController.h" +// Do not remove this header file. This class contains methods +// which take arguments defined in vtkMPICommunicator.h by +// reference. +#include "vtkMPICommunicator.h" // Needed for direct access to communicator + +class VTK_PARALLEL_EXPORT vtkMPIController : public vtkMultiProcessController +{ + +public: + + static vtkMPIController *New(); + vtkTypeRevisionMacro(vtkMPIController,vtkMultiProcessController); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method is for setting up the processes. + // It needs to be called only once during program execution. + // Calling it more than once will have no effect. Controllers + // created after this call will be initialized automatically + // (i.e. they will have the proper LocalProcessId and NumberOfProcesses). + // The addresses of argc and argv should be passed to this method + // otherwise command line arguments will not be correct (because + // usually MPI implementations add their own arguments during + // startup). + virtual void Initialize(int* argc, char*** argv) + { this->Initialize(argc, argv, 0); } + + virtual void Initialize(int* vtkNotUsed(argc), char*** vtkNotUsed(argv), + int initializedExternally); + + // Description: + // This method is for cleaning up and has to be called before + // the end of the program if MPI was initialized with + //Initialize() + virtual void Finalize() { this->Finalize(0); } + + virtual void Finalize(int finalizedExternally); + + // Description: + // Execute the SingleMethod (as define by SetSingleMethod) using + // this->NumberOfProcesses processes. + virtual void SingleMethodExecute(); + + // Description: + // Execute the MultipleMethods (as define by calling SetMultipleMethod + // for each of the required this->NumberOfProcesses methods) using + // this->NumberOfProcesses processes. + virtual void MultipleMethodExecute(); + + // Description: + // This method can be used to synchronize MPI processes in the + // current communicator. This uses the user communicator. + void Barrier(); + + // Description: + // This method can be used to tell the controller to create + // a special output window in which all messages are preceded + // by the process id. + virtual void CreateOutputWindow(); + + // Description: + // Given an MPI error code, return a string which contains + // an error message. This string has to be freed by the user. + static char* ErrorString(int err); + + + // Description: + // MPIController uses this communicator in all sends and + // receives. By default, MPI_COMM_WORLD is used. + // THIS SHOULD ONLY BE CALLED ON THE PROCESSES INCLUDED + // IN THE COMMUNICATOR. FOR EXAMPLE, IF THE COMMUNICATOR + // CONTAINES PROCESSES 0 AND 1, INVOKING THIS METHOD ON + // ANY OTHER PROCESS WILL CAUSE AN MPI ERROR AND POSSIBLY + // LEAD TO A CRASH. + void SetCommunicator(vtkMPICommunicator* comm); + +//BTX + + // Description: + // This method sends data to another process (non-blocking). + // Tag eliminates ambiguity when multiple sends or receives + // exist in the same process. The last argument, + // vtkMPICommunicator::Request& req can later be used (with + // req.Test() ) to test the success of the message. + // Note: These methods delegate to the communicator + int NoBlockSend(int* data, int length, int remoteProcessId, int tag, + vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockSend + (data ,length, remoteProcessId, tag, req); } + int NoBlockSend(unsigned long* data, int length, int remoteProcessId, + int tag, vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockSend + (data, length, remoteProcessId, tag, req); } + int NoBlockSend(char* data, int length, int remoteProcessId, + int tag, vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockSend + (data, length, remoteProcessId, tag, req); } + int NoBlockSend(float* data, int length, int remoteProcessId, + int tag, vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockSend + (data, length, remoteProcessId, tag, req); } + + // Description: + // This method receives data from a corresponding send (non-blocking). + // The last argument, + // vtkMPICommunicator::Request& req can later be used (with + // req.Test() ) to test the success of the message. + // Note: These methods delegate to the communicator + int NoBlockReceive(int* data, int length, int remoteProcessId, + int tag, vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockReceive + (data, length, remoteProcessId, tag, req); } + int NoBlockReceive(unsigned long* data, int length, + int remoteProcessId, int tag, + vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockReceive + (data, length, remoteProcessId, tag, req); } + int NoBlockReceive(char* data, int length, int remoteProcessId, + int tag, vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockReceive + (data, length, remoteProcessId, tag, req); } + int NoBlockReceive(float* data, int length, int remoteProcessId, + int tag, vtkMPICommunicator::Request& req) + { return ((vtkMPICommunicator*)this->Communicator)->NoBlockReceive + (data, length, remoteProcessId, tag, req); } + +//ETX + + static const char* GetProcessorName(); + +protected: + vtkMPIController(); + ~vtkMPIController(); + + // Given a communicator, obtain size and rank + // setting NumberOfProcesses and LocalProcessId + // Should not be called if the current communicator + // does not include this process + int InitializeNumberOfProcesses(); + + // Set the communicator to comm and call InitializeNumberOfProcesses() + void InitializeCommunicator(vtkMPICommunicator* comm); + + // Duplicate the current communicator, creating RMICommunicator + void InitializeRMICommunicator(); + + // MPI communicator created when Initialize() called. + // This is a copy of MPI_COMM_WORLD but uses a new + // context, i.e. even if the tags are the same, the + // RMI messages will not interfere with user level + // messages. + static vtkMPICommunicator* WorldRMICommunicator; + + // Initialize only once. + static int Initialized; + + static char ProcessorName[]; + +private: + vtkMPIController(const vtkMPIController&); // Not implemented. + void operator=(const vtkMPIController&); // Not implemented. +}; + + +#endif + + diff --git a/Parallel/vtkMPIEventLog.cxx b/Parallel/vtkMPIEventLog.cxx new file mode 100644 index 0000000..1bde748 --- /dev/null +++ b/Parallel/vtkMPIEventLog.cxx @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPIEventLog.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkMPIEventLog.h" +#include "vtkMPIController.h" +#include "vtkObjectFactory.h" +#include "mpe.h" + +int vtkMPIEventLog::LastEventId = 0; + +vtkCxxRevisionMacro(vtkMPIEventLog, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkMPIEventLog); + +void vtkMPIEventLog::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +vtkMPIEventLog::vtkMPIEventLog() +{ + + this->Active = 0; + +} + +void vtkMPIEventLog::InitializeLogging() +{ + MPE_Init_log(); +} + +void vtkMPIEventLog::FinalizeLogging(const char* fname) +{ + MPE_Finish_log(const_cast(fname)); +} + +int vtkMPIEventLog::SetDescription(const char* name, const char* desc) +{ + int err, processId; + if ( (err = MPI_Comm_rank(MPI_COMM_WORLD,&processId)) + != MPI_SUCCESS) + { + char *msg = vtkMPIController::ErrorString(err); + vtkErrorMacro("MPI error occured: " << msg); + delete[] msg; + return 0; + } + + this->Active = 1; + if (processId == 0) + { + this->BeginId = MPE_Log_get_event_number(); + this->EndId = MPE_Log_get_event_number(); + MPE_Describe_state(this->BeginId, this->EndId, const_cast(name), + const_cast(desc)); + } + MPI_Bcast(&this->BeginId, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&this->EndId, 1, MPI_INT, 0, MPI_COMM_WORLD); + + return 1; +} + +void vtkMPIEventLog::StartLogging() +{ + if (!this->Active) + { + vtkWarningMacro("This vtkMPIEventLog has not been initialized. Can not log event."); + return; + } + + MPE_Log_event(this->BeginId, 0, "begin"); +} + +void vtkMPIEventLog::StopLogging() +{ + if (!this->Active) + { + vtkWarningMacro("This vtkMPIEventLog has not been initialized. Can not log event."); + return; + } + MPE_Log_event(this->EndId, 0, "end"); +} + +vtkMPIEventLog::~vtkMPIEventLog() +{ +} + diff --git a/Parallel/vtkMPIEventLog.h b/Parallel/vtkMPIEventLog.h new file mode 100644 index 0000000..27d7863 --- /dev/null +++ b/Parallel/vtkMPIEventLog.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPIEventLog.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMPIEventLog - Class for logging and timing. + +// .SECTION Description +// This class is wrapper around MPE event logging functions +// (available from Argonne National Lab/Missippi State +// University). It allows users to create events with names +// and log them. Different log file formats can be generated +// by changing MPE's configuration. Some of these formats are +// binary (for examples SLOG and CLOG) and can be analyzed with +// viewers from ANL. ALOG is particularly useful since it is +// text based and can be processed with simple scripts. + +// .SECTION See Also +// vtkTimerLog vtkMPIController vtkMPICommunicator + +#ifndef __vtkMPIEventLog_h +#define __vtkMPIEventLog_h + +#include "vtkObject.h" + +class VTK_PARALLEL_EXPORT vtkMPIEventLog : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkMPIEventLog,vtkObject); + + // Description: + // Construct a vtkMPIEventLog with the following initial state: + // Processes = 0, MaximumNumberOfProcesses = 0. + static vtkMPIEventLog* New(); + + // Description: + // Used to initialize the underlying mpe event. + // HAS TO BE CALLED BY ALL PROCESSES before any event + // logging is done. + // It takes a name and a description for the graphical + // representation, for example, "red:vlines3". See + // mpe documentation for details. + // Returns 0 on MPI failure (or aborts depending on + // MPI error handlers) + int SetDescription(const char* name, const char* desc); + + // Description: + // These methods have to be called once on all processors + // before and after invoking any logging events. + // The name of the logfile is given by fileName. + // See mpe documentation for file formats. + static void InitializeLogging(); + static void FinalizeLogging(const char* fileName); + + // Description: + // Issue start and stop events for this log entry. + void StartLogging(); + void StopLogging(); + + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + + vtkMPIEventLog(); + ~vtkMPIEventLog(); + + static int LastEventId; + int Active; + int BeginId; + int EndId; +private: + vtkMPIEventLog(const vtkMPIEventLog&); // Not implemented. + void operator=(const vtkMPIEventLog&); // Not implemented. +}; + +#endif + + + + diff --git a/Parallel/vtkMPIGroup.cxx b/Parallel/vtkMPIGroup.cxx new file mode 100644 index 0000000..78737c3 --- /dev/null +++ b/Parallel/vtkMPIGroup.cxx @@ -0,0 +1,191 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPIGroup.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkMPIGroup.h" +#include "vtkMPIController.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkMPIGroup, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkMPIGroup); + +void vtkMPIGroup::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Initialized : "; + if (this->Initialized) + { + os << "(yes)" << endl; + } + else + { + os << "(no)" << endl; + } + os << indent << "Maximum number of processe ids: " + << this->MaximumNumberOfProcessIds << endl; + os << indent << "First available position: " + << this->CurrentPosition << endl; + for(int i=0; i < this->CurrentPosition; i++) + { + os << indent << "Process id at " << i << " is " + << this->ProcessIds[i] << endl; + } + return; +} + +vtkMPIGroup::vtkMPIGroup() +{ + this->ProcessIds = 0; + this->MaximumNumberOfProcessIds = 0; + this->CurrentPosition = 0; + this->Initialized = 0; +} + +vtkMPIGroup::~vtkMPIGroup() +{ + delete[] this->ProcessIds; + this->MaximumNumberOfProcessIds = 0; +} + +void vtkMPIGroup::Initialize(int numProcIds) +{ + if (this->Initialized) + { + return; + } + + if (this->ProcessIds) + { + delete[] this->ProcessIds; + } + + this->MaximumNumberOfProcessIds = numProcIds; + if ( this->MaximumNumberOfProcessIds > 0 ) + { + this->ProcessIds = new int[this->MaximumNumberOfProcessIds]; + } + else + { + return; + } + + this->Initialized = 1; + this->Modified(); + return; +} + +void vtkMPIGroup::Initialize(vtkMPIController* controller) +{ + this->Initialize(controller->GetNumberOfProcesses()); + return; +} + +int vtkMPIGroup::AddProcessId(int processId) +{ + if ( this->CurrentPosition >= this->MaximumNumberOfProcessIds ) + { + vtkWarningMacro("Can not add any more process ids. The group is full."); + return 0; + } + if ( processId >= this->MaximumNumberOfProcessIds ) + { + vtkWarningMacro("Process id " << processId << " is not valid."); + return 0; + } + if ( this->FindProcessId(processId) >= 0 ) + { + vtkWarningMacro("This process id is already in the group."); + return 0; + } + + this->ProcessIds[this->CurrentPosition] = processId; + this->Modified(); + return ++this->CurrentPosition; +} + +void vtkMPIGroup::RemoveProcessId(int processId) +{ + int pos = this->FindProcessId(processId); + if ( pos >= 0 ) + { + for(int i=pos; i < this->CurrentPosition - 1; i++) + { + this->ProcessIds[i] = this->ProcessIds[i+1]; + } + this->CurrentPosition--; + this->Modified(); + } + return; +} + +int vtkMPIGroup::FindProcessId(int processId) +{ + for (int i=0; i < this->CurrentPosition; i++) + { + if ( this->ProcessIds[i] == processId ) + { + return i; + } + } + return -1; +} + +int vtkMPIGroup::GetProcessId(int pos) +{ + if ( pos >= this->CurrentPosition) + { + return -1; + } + return this->ProcessIds[pos]; +} + +void vtkMPIGroup::CopyProcessIdsFrom(vtkMPIGroup* group) +{ + int max; + // Find which MaximumNumberOfProcessIds is smallest and use that. + if ( this->MaximumNumberOfProcessIds > group->MaximumNumberOfProcessIds ) + { + max = group->MaximumNumberOfProcessIds; + } + else + { + max = this->MaximumNumberOfProcessIds; + } + // Copy. + for(int i=0; i < max; i++) + { + this->ProcessIds[i] = group->ProcessIds[i]; + } + + // If the current position of group is smaller than + // this->MaximumNumberOfProcessIds use it. + if ( group->CurrentPosition <= this->MaximumNumberOfProcessIds) + { + this->CurrentPosition = group->CurrentPosition; + } + else + { + this->CurrentPosition = this->MaximumNumberOfProcessIds; + } + + this->Modified(); + return; +} + +void vtkMPIGroup::CopyFrom(vtkMPIGroup* source) +{ + this->Initialized = 0; + this->Initialize(source->MaximumNumberOfProcessIds); + this->CopyProcessIdsFrom(source); +} diff --git a/Parallel/vtkMPIGroup.h b/Parallel/vtkMPIGroup.h new file mode 100644 index 0000000..3471333 --- /dev/null +++ b/Parallel/vtkMPIGroup.h @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMPIGroup.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMPIGroup - Class for creating MPI groups. + +// .SECTION Description +// This class is used to create MPI groups. A vtkMPIGroup object +// has to be initialized by passing the controller. Then the +// group can be modified by adding, removing ids and copying the contents +// of another group. + +// .SECTION See Also +// vtkMPIController vtkMPICommunicator + +#ifndef __vtkMPIGroup_h +#define __vtkMPIGroup_h + +#include "vtkObject.h" + +class vtkMPIController; +class vtkMPICommunicator; + +class VTK_PARALLEL_EXPORT vtkMPIGroup : public vtkObject +{ + +public: + + vtkTypeRevisionMacro( vtkMPIGroup,vtkObject); + + // Description: + // Construct a vtkMPIGroup with the following initial state: + // Processes = 0, MaximumNumberOfProcesses = 0. + static vtkMPIGroup* New(); + + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Allocate memory for N process ids where + // N = controller->NumberOfProcesses + void Initialize(vtkMPIController* controller); + + // Description: + // Add a process id to the end of the list (if it is not already + // in the group). Returns non-zero on success. + // This will not add a process id >= MaximumNumberOfProcessIds. + int AddProcessId(int processId); + + // Description: + // Remove the given process id from the list and + // shift all ids, starting from the position of the removed + // id, left by one. + void RemoveProcessId(int processId); + + // Description: + // Find the location of a process id in the group. + // Returns -1 if the process id is not on the list. + int FindProcessId(int processId); + + // Description: + // Get the process id at position pos. + // Returns -1 if pos >= max. available pos. + int GetProcessId(int pos); + + // Description: + // Copy the process ids from a given group. + // This will copy N ids, where N is the smallest + // MaximumNumberOfProcessIds. + void CopyProcessIdsFrom(vtkMPIGroup* group); + + // Description: + // Returns the number of ids currently stored. + int GetNumberOfProcessIds() + { + return this->CurrentPosition; + } + +//BTX + + friend class vtkMPICommunicator; + +//ETX + +protected: + + // Description: + // Copies all the information from group, erasing + // previously stored data. Similar to copy constructor + void CopyFrom(vtkMPIGroup* group); + + // Description: + // Allocate memory for numProcIds process ids + void Initialize(int numProcIds); + + int* ProcessIds; + int MaximumNumberOfProcessIds; + int Initialized; + int CurrentPosition; + + vtkMPIGroup(); + ~vtkMPIGroup(); + +private: + vtkMPIGroup(const vtkMPIGroup&); // Not implemented. + void operator=(const vtkMPIGroup&); // Not implemented. +}; + +#endif + + + + diff --git a/Parallel/vtkMemoryLimitImageDataStreamer.cxx b/Parallel/vtkMemoryLimitImageDataStreamer.cxx new file mode 100644 index 0000000..e6f02ca --- /dev/null +++ b/Parallel/vtkMemoryLimitImageDataStreamer.cxx @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMemoryLimitImageDataStreamer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMemoryLimitImageDataStreamer.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkCommand.h" +#include "vtkExtentTranslator.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPipelineSize.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkMemoryLimitImageDataStreamer, "$Revision: 1.12 $"); +vtkStandardNewMacro(vtkMemoryLimitImageDataStreamer); + +//---------------------------------------------------------------------------- +vtkMemoryLimitImageDataStreamer::vtkMemoryLimitImageDataStreamer() +{ + // Set a default memory limit of 50 Megabytes + this->MemoryLimit = 50000; +} + + +//---------------------------------------------------------------------------- +void vtkMemoryLimitImageDataStreamer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "MemoryLimit (in kb): " << this->MemoryLimit << endl; +} + +//---------------------------------------------------------------------------- +int +vtkMemoryLimitImageDataStreamer +::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + if (this->CurrentDivision == 0) + { + // we must set the extent on the input + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + // get the requested update extent + int outExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt); + + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkImageData *input = + vtkImageData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkExtentTranslator *translator = this->GetExtentTranslator(); + translator->SetWholeExtent(outExt); + + vtkPipelineSize *sizer = vtkPipelineSize::New(); + this->NumberOfStreamDivisions = 1; + unsigned long oldSize, size = 0; + float ratio; + translator->SetPiece(0); + + // watch for the limiting case where the size is the maximum size + // represented by an unsigned long. In that case we do not want to do + // the ratio test. We actual test for size < 0.5 of the max unsigned + // long which would indicate that oldSize is about at max unsigned + // long. + unsigned long maxSize; + maxSize = (((unsigned long)0x1) << (8*sizeof(unsigned long) - 1)); + + // we also have to watch how many pieces we are creating. Since + // NumberOfStreamDivisions is an int, it cannot be more that say 2^31 + // (which is a bit much anyhow) so we also stop if the number of pieces + // is too large. + int count = 0; + + + // double the number of pieces until the size fits in memory + // or the reduction in size falls to 20% + do + { + oldSize = size; + translator->SetNumberOfPieces(this->NumberOfStreamDivisions); + translator->PieceToExtentByPoints(); + + int inExt[6]; + translator->GetExtent(inExt); + // set the update extent + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6); + + // then propagate it + vtkAlgorithm *alg = input->GetProducerPort()->GetProducer(); + int index = input->GetProducerPort()->GetIndex(); + vtkStreamingDemandDrivenPipeline *exec = + vtkStreamingDemandDrivenPipeline::SafeDownCast(alg->GetExecutive()); + exec->PropagateUpdateExtent(index); + + size = sizer->GetEstimatedSize(this,0,0); + // watch for the first time through + if (!oldSize) + { + ratio = 0.5; + } + // otherwise the normal ratio calculation + else + { + ratio = size/(float)oldSize; + } + this->NumberOfStreamDivisions = this->NumberOfStreamDivisions*2; + count++; + } + while (size > this->MemoryLimit && + (size < maxSize && ratio < 0.8) && count < 29); + + // undo the last *2 + this->NumberOfStreamDivisions = this->NumberOfStreamDivisions/2; + sizer->Delete(); + } + return + this->Superclass::ProcessRequest(request, inputVector, outputVector); + } + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} diff --git a/Parallel/vtkMemoryLimitImageDataStreamer.h b/Parallel/vtkMemoryLimitImageDataStreamer.h new file mode 100644 index 0000000..985c09f --- /dev/null +++ b/Parallel/vtkMemoryLimitImageDataStreamer.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMemoryLimitImageDataStreamer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMemoryLimitImageDataStreamer - Initiates streaming on image data. +// .SECTION Description +// To satisfy a request, this filter calls update on its input +// many times with smaller update extents. All processing up stream +// streams smaller pieces. + +#ifndef __vtkMemoryLimitImageDataStreamer_h +#define __vtkMemoryLimitImageDataStreamer_h + +#include "vtkImageDataStreamer.h" + + +class VTK_PARALLEL_EXPORT vtkMemoryLimitImageDataStreamer : public vtkImageDataStreamer +{ +public: + static vtkMemoryLimitImageDataStreamer *New(); + vtkTypeRevisionMacro(vtkMemoryLimitImageDataStreamer,vtkImageDataStreamer); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / Get the memory limit in kilobytes. + vtkSetMacro(MemoryLimit, unsigned long); + vtkGetMacro(MemoryLimit, unsigned long); + + // See the vtkAlgorithm for a desciption of what these do + int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkMemoryLimitImageDataStreamer(); + ~vtkMemoryLimitImageDataStreamer() {}; + + unsigned long MemoryLimit; +private: + vtkMemoryLimitImageDataStreamer(const vtkMemoryLimitImageDataStreamer&); // Not implemented. + void operator=(const vtkMemoryLimitImageDataStreamer&); // Not implemented. +}; + + + + +#endif + + + diff --git a/Parallel/vtkMultiProcessController.cxx b/Parallel/vtkMultiProcessController.cxx new file mode 100644 index 0000000..37d01a8 --- /dev/null +++ b/Parallel/vtkMultiProcessController.cxx @@ -0,0 +1,427 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiProcessController.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This will be the default. +#include "vtkMultiProcessController.h" +#include "vtkDummyController.h" +#include "vtkToolkits.h" + +#ifdef VTK_USE_MPI +#include "vtkMPIController.h" +#endif + +#include "vtkCollection.h" +#include "vtkObjectFactory.h" +#include "vtkOutputWindow.h" + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkMultiProcessController); + +//---------------------------------------------------------------------------- + +// Helper class to contain the RMI information. +// A subclass of vtkObject so that I can keep them in a collection. +class VTK_PARALLEL_EXPORT vtkMultiProcessControllerRMI : public vtkObject +{ +public: + static vtkMultiProcessControllerRMI *New(); + vtkTypeRevisionMacro(vtkMultiProcessControllerRMI, vtkObject); + + int Tag; + vtkRMIFunctionType Function; + void *LocalArgument; + +protected: + vtkMultiProcessControllerRMI() {}; + vtkMultiProcessControllerRMI(const vtkMultiProcessControllerRMI&); + void operator=(const vtkMultiProcessControllerRMI&); +}; + +vtkCxxRevisionMacro(vtkMultiProcessControllerRMI, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkMultiProcessControllerRMI); + +vtkCxxRevisionMacro(vtkMultiProcessController, "$Revision: 1.23 $"); + +//---------------------------------------------------------------------------- +// An RMI function that will break the "ProcessRMIs" loop. +void vtkMultiProcessControllerBreakRMI(void *localArg, + void *remoteArg, int remoteArgLength, + int vtkNotUsed(remoteId)) +{ + vtkMultiProcessController *controller; + remoteArg = remoteArg; + remoteArgLength = remoteArgLength; + controller = (vtkMultiProcessController*)(localArg); + controller->SetBreakFlag(1); +} + + + +//---------------------------------------------------------------------------- +vtkMultiProcessController::vtkMultiProcessController() +{ + int i; + + this->LocalProcessId = 0; + this->NumberOfProcesses = 1; + this->MaximumNumberOfProcesses = MAX_PROCESSES; + + this->RMIs = vtkCollection::New(); + + this->SingleMethod = 0; + this->SingleData = 0; + + this->Communicator = 0; + this->RMICommunicator = 0; + + for ( i = 0; i < VTK_MAX_THREADS; i++ ) + { + this->MultipleMethod[i] = NULL; + this->MultipleData[i] = NULL; + } + + this->BreakFlag = 0; + this->ForceDeepCopy = 1; + + this->OutputWindow = 0; + + // Define an rmi internally to exit from the processing loop. + this->AddRMI(vtkMultiProcessControllerBreakRMI, this, BREAK_RMI_TAG); +} + +//---------------------------------------------------------------------------- +// This is an old comment that I do not know is true: +// (We need to have a "GetNetReferenceCount" to avoid memory leaks.) +vtkMultiProcessController::~vtkMultiProcessController() +{ + if ( this->OutputWindow && + (this->OutputWindow == vtkOutputWindow::GetInstance()) ) + { + vtkOutputWindow::SetInstance(0); + } + + if (this->OutputWindow) + { + this->OutputWindow->Delete(); + } + + this->RMIs->Delete(); + this->RMIs = NULL; +} + + +//---------------------------------------------------------------------------- +void vtkMultiProcessController::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + vtkMultiProcessControllerRMI *rmi; + vtkIndent nextIndent = indent.GetNextIndent(); + + os << indent << "MaximumNumberOfProcesses: " + << this->MaximumNumberOfProcesses << endl; + os << indent << "NumberOfProcesses: " << this->NumberOfProcesses << endl; + os << indent << "LocalProcessId: " << this->LocalProcessId << endl; + os << indent << "Break flag: " << (this->BreakFlag ? "(yes)" : "(no)") + << endl; + os << indent << "Force deep copy: " << (this->ForceDeepCopy ? "(yes)" : "(no)") + << endl; + os << indent << "Output window: "; + if (this->OutputWindow) + { + os << endl; + this->OutputWindow->PrintSelf(os, nextIndent); + } + else + { + os << "(none)" << endl; + } + os << indent << "Communicator: "; + if (this->Communicator) + { + os << endl; + this->Communicator->PrintSelf(os, nextIndent); + } + else + { + os << "(none)" << endl; + } + os << indent << "RMI communicator: "; + if (this->RMICommunicator) + { + os << endl; + this->RMICommunicator->PrintSelf(os, nextIndent); + } + else + { + os << "(none)" << endl; + } + os << indent << "RMIs: \n"; + + this->RMIs->InitTraversal(); + while ( (rmi = (vtkMultiProcessControllerRMI*)(this->RMIs->GetNextItemAsObject())) ) + { + os << nextIndent << rmi->Tag << endl; + } + +} + +//---------------------------------------------------------------------------- +void vtkMultiProcessController::SetNumberOfProcesses(int num) +{ + if (num == this->NumberOfProcesses) + { + return; + } + + if (num < 1 || num > this->MaximumNumberOfProcesses) + { + vtkErrorMacro( << num + << " is an invalid number of processes try a number from 1 to " + << this->NumberOfProcesses ); + return; + } + + this->NumberOfProcesses = num; + this->Modified(); +} + + +//---------------------------------------------------------------------------- +void vtkMultiProcessController::SetSingleMethod( vtkProcessFunctionType f, + void *data ) +{ + this->SingleMethod = f; + this->SingleData = data; +} + +//---------------------------------------------------------------------------- +// Set one of the user defined methods that will be run on NumberOfProcesses +// processes when MultipleMethodExecute is called. This method should be +// called with index = 0, 1, .., NumberOfProcesses-1 to set up all the +// required user defined methods +void vtkMultiProcessController::SetMultipleMethod( int index, + vtkProcessFunctionType f, void *data ) +{ + // You can only set the method for 0 through NumberOfProcesses-1 + if ( index >= this->NumberOfProcesses ) + { + vtkErrorMacro( << "Can't set method " << index << + " with a processes count of " << this->NumberOfProcesses ); + } + else + { + this->MultipleMethod[index] = f; + this->MultipleData[index] = data; + } +} + +//---------------------------------------------------------------------------- +int vtkMultiProcessController::RemoveFirstRMI(int tag) +{ + vtkMultiProcessControllerRMI *rmi = NULL; + this->RMIs->InitTraversal(); + while ( (rmi = (vtkMultiProcessControllerRMI*)(this->RMIs->GetNextItemAsObject())) ) + { + if (rmi->Tag == tag) + { + this->RMIs->RemoveItem(rmi); + return 1; + } + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkMultiProcessController::AddRMI(vtkRMIFunctionType f, + void *localArg, int tag) +{ + vtkMultiProcessControllerRMI *rmi = vtkMultiProcessControllerRMI::New(); + + rmi->Tag = tag; + rmi->Function = f; + rmi->LocalArgument = localArg; + this->RMIs->AddItem(rmi); + rmi->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkMultiProcessController::TriggerRMI(int remoteProcessId, + void *arg, int argLength, + int rmiTag) +{ + int triggerMessage[3]; + + // Deal with sending RMI to ourself here for now. + if (remoteProcessId == this->GetLocalProcessId()) + { + this->ProcessRMI(remoteProcessId, arg, argLength, rmiTag); + return; + } + + triggerMessage[0] = rmiTag; + triggerMessage[1] = argLength; + + // It is important for the remote process to know what process invoked it. + // Multiple processes might try to invoke the method at the same time. + // The remote method will know where to get additional args. + triggerMessage[2] = this->GetLocalProcessId(); + + this->RMICommunicator->Send(triggerMessage, 3, remoteProcessId, RMI_TAG); + if (argLength > 0) + { + this->RMICommunicator->Send((char*)arg, argLength, remoteProcessId, + RMI_ARG_TAG); + } +} + +//---------------------------------------------------------------------------- +void vtkMultiProcessController::TriggerBreakRMIs() +{ + int idx, num; + + if (this->GetLocalProcessId() != 0) + { + vtkErrorMacro("Break should be triggered from process 0."); + return; + } + + num = this->GetNumberOfProcesses(); + for (idx = 1; idx < num; ++idx) + { + this->TriggerRMI(idx, NULL, 0, BREAK_RMI_TAG); + } +} + +//---------------------------------------------------------------------------- +int vtkMultiProcessController::ProcessRMIs() +{ + return this->ProcessRMIs(1); +} + +//---------------------------------------------------------------------------- +int vtkMultiProcessController::ProcessRMIs(int reportErrors) +{ + int triggerMessage[3]; + unsigned char *arg = NULL; + int error = RMI_NO_ERROR; + + while (1) + { + if (!this->RMICommunicator->Receive(triggerMessage, 3, ANY_SOURCE, RMI_TAG)) + { + if (reportErrors) + { + vtkErrorMacro("Could not receive RMI trigger message."); + } + error = RMI_TAG_ERROR; + break; + } + if (triggerMessage[1] > 0) + { + arg = new unsigned char[triggerMessage[1]]; + if (!this->RMICommunicator->Receive((char*)(arg), triggerMessage[1], + triggerMessage[2], RMI_ARG_TAG)) + { + if (reportErrors) + { + vtkErrorMacro("Could not receive RMI argument."); + } + error = RMI_ARG_ERROR; + break; + } + } + this->ProcessRMI(triggerMessage[2], arg, triggerMessage[1], + triggerMessage[0]); + if (arg) + { + delete [] arg; + arg = NULL; + } + + // check for break + if (this->BreakFlag) + { + this->BreakFlag = 0; + return error; + } + } + + return error; +} + + +//---------------------------------------------------------------------------- +void vtkMultiProcessController::ProcessRMI(int remoteProcessId, + void *arg, int argLength, + int rmiTag) +{ + vtkMultiProcessControllerRMI *rmi = NULL; + int found = 0; + + // find the rmi + this->RMIs->InitTraversal(); + while ( !found && + (rmi = (vtkMultiProcessControllerRMI*)(this->RMIs->GetNextItemAsObject())) ) + { + if (rmi->Tag == rmiTag) + { + found = 1; + } + } + + if ( ! found) + { + vtkErrorMacro("Process " << this->GetLocalProcessId() << + " Could not find RMI with tag " << rmiTag); + } + else + { + if ( rmi->Function ) + { + (*rmi->Function)(rmi->LocalArgument, arg, argLength, remoteProcessId); + } + } +} + + +//============================================================================ +// The intent is to give access to a processes controller from a static method. + +vtkMultiProcessController *VTK_GLOBAL_MULTI_PROCESS_CONTROLLER = NULL; +//---------------------------------------------------------------------------- +vtkMultiProcessController *vtkMultiProcessController::GetGlobalController() +{ + if (VTK_GLOBAL_MULTI_PROCESS_CONTROLLER == NULL) + { + return NULL; + } + + return VTK_GLOBAL_MULTI_PROCESS_CONTROLLER->GetLocalController(); +} +//---------------------------------------------------------------------------- +// This can be overridden in the subclass to translate controllers. +vtkMultiProcessController *vtkMultiProcessController::GetLocalController() +{ + return VTK_GLOBAL_MULTI_PROCESS_CONTROLLER; +} +//---------------------------------------------------------------------------- +// This can be overridden in the subclass to translate controllers. +void vtkMultiProcessController::SetGlobalController( + vtkMultiProcessController *controller) +{ + VTK_GLOBAL_MULTI_PROCESS_CONTROLLER = controller; +} + + diff --git a/Parallel/vtkMultiProcessController.h b/Parallel/vtkMultiProcessController.h new file mode 100644 index 0000000..179e602 --- /dev/null +++ b/Parallel/vtkMultiProcessController.h @@ -0,0 +1,560 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMultiProcessController.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMultiProcessController - Multiprocessing communication superclass +// .SECTION Description +// vtkMultiProcessController is used to control multiple processes +// in a distributed computing environment. It has +// methods for executing single/multiple method(s) on multiple processors, +// triggering registered callbacks (Remote Methods) (AddRMI(), TriggerRMI()) +// and communication. Please note that the communication is done using +// the communicator which is accessible to the user. Therefore it is +// possible to get the communicator with GetCommunicator() and use +// it to send and receive data. This is the encoured communication method. +// The internal (RMI) communications are done using a second internal +// communicator (called RMICommunicator). +// +// .SECTION see also +// vtkMPIController +// vtkCommunicator vtkMPICommunicator + +#ifndef __vtkMultiProcessController_h +#define __vtkMultiProcessController_h + +#include "vtkObject.h" + +#include "vtkCommunicator.h" // Needed for direct access to communicator + +class vtkDataSet; +class vtkImageData; +class vtkCollection; +class vtkOutputWindow; +class vtkDataObject; +class vtkMultiProcessController; + +//BTX +// The type of function that gets called when new processes are initiated. +typedef void (*vtkProcessFunctionType)(vtkMultiProcessController *controller, + void *userData); + +// The type of function that gets called when an RMI is triggered. +typedef void (*vtkRMIFunctionType)(void *localArg, + void *remoteArg, int remoteArgLength, + int remoteProcessId); +//ETX + + +class VTK_PARALLEL_EXPORT vtkMultiProcessController : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkMultiProcessController,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method is for setting up the processes. + // If a subclass needs to initialize process communication (i.e. MPI) + // it would over ride this method. + virtual void Initialize(int* vtkNotUsed(argc), char*** vtkNotUsed(argv))=0; + + // Description: + // This method is for setting up the processes. + // If a subclass needs to initialize process communication (i.e. MPI) + // it would over ride this method. Provided for initialization outside vtk. + virtual void Initialize(int* vtkNotUsed(argc), char*** vtkNotUsed(argv), + int initializedExternally)=0; + + // Description: + // This method is for cleaning up. + // If a subclass needs to clean up process communication (i.e. MPI) + // it would over ride this method. + virtual void Finalize()=0; + + // Description: + // This method is for cleaning up. + // If a subclass needs to clean up process communication (i.e. MPI) + // it would over ride this method. Provided for finalization outside vtk. + virtual void Finalize(int finalizedExternally)=0; + + // Description: + // Set the number of processes you will be using. This defaults + // to the maximum number available. If you set this to a value + // higher than the default, you will get an error. + virtual void SetNumberOfProcesses(int num); + vtkGetMacro( NumberOfProcesses, int ); + + //BTX + // Description: + // Set the SingleMethod to f() and the UserData of the + // for the method to be executed by all of the processes + // when SingleMethodExecute is called. All the processes will + // start by calling this function. + void SetSingleMethod(vtkProcessFunctionType, void *data); + //ETX + + // Description: + // Execute the SingleMethod (as define by SetSingleMethod) using + // this->NumberOfProcesses processes. This will only return when + // all the processes finish executing their methods. + virtual void SingleMethodExecute() = 0; + + //BTX + // Description: + // Set the MultipleMethod to f() and the UserData of the + // for the method to be executed by the process index + // when MultipleMethodExecute is called. This is for having each + // process start with a different function and data argument. + void SetMultipleMethod(int index, vtkProcessFunctionType, void *data); + //ETX + + // Description: + // Execute the MultipleMethods (as define by calling SetMultipleMethod + // for each of the required this->NumberOfProcesses methods) using + // this->NumberOfProcesses processes. + virtual void MultipleMethodExecute() = 0; + + // Description: + // Tells you which process [0, NumProcess) you are in. + vtkGetMacro(LocalProcessId, int); + + // Description: + // This convenience method returns the controller associated with the + // local process. It returns NULL until the processes are spawned. + // It is better if you hang on to the controller passed as an argument to the + // SingleMethod or MultipleMethod functions. + static vtkMultiProcessController *GetGlobalController(); + + // Description: + // This method can be used to tell the controller to create + // a special output window in which all messages are preceded + // by the process id. + virtual void CreateOutputWindow() = 0; + + //------------------ RMIs -------------------- + //BTX + // Description: + // Register remote method invocation in the receiving process + // which makes the call. It must have a unique tag as an RMI id. + // The vtkRMIFunctionType has several arguments: localArg (same as passed in), + // remoteArg, remoteArgLength (memory passed by process triggering the RMI), + // remoteProcessId. + void AddRMI(vtkRMIFunctionType, void *localArg, int tag); + + // Description: + // Remove the first RMI matching the tag. + int RemoveFirstRMI(int tag); + + // Description: + // Take an RMI away. + void RemoveRMI(vtkRMIFunctionType f, void *arg, int tag) + {f = f; arg = arg; tag = tag; vtkErrorMacro("RemoveRMI Not Implemented Yet");}; + //ETX + + // Description: + // A method to trigger a method invocation in another process. + void TriggerRMI(int remoteProcessId, void *arg, int argLength, int tag); + + // Description: + // A conveniance method. Called on process 0 to break "ProcessRMIs" loop + // on all other processes. + void TriggerBreakRMIs(); + + // Description: + // Convenience method when the arg is a string. + void TriggerRMI(int remoteProcessId, const char *arg, int tag) + { this->TriggerRMI(remoteProcessId, (void*)arg, + static_cast(strlen(arg))+1, tag); } + + // Description: + // Convenience method when there is no argument. + void TriggerRMI(int remoteProcessId, int tag) + { this->TriggerRMI(remoteProcessId, NULL, 0, tag); } + + // Description: + // Calling this method gives control to the controller to start + // processing RMIs. Possible return values are: + // RMI_NO_ERROR, + // RMI_TAG_ERROR : rmi tag could not be received, + // RMI_ARG_ERROR : rmi arg could not be received. + // If reportErrors is false, no vtkErrorMacro is called. + // ProcessRMIs() calls ProcessRMIs(int) with reportErrors = 0. + int ProcessRMIs(int reportErrors); + int ProcessRMIs(); + + // Description: + // Setting this flag to 1 will cause the ProcessRMIs loop to return. + // This also causes vtkUpStreamPorts to return from + // their WaitForUpdate loops. + vtkSetMacro(BreakFlag, int); + vtkGetMacro(BreakFlag, int); + + // Description: + vtkGetObjectMacro(Communicator, vtkCommunicator); + +//BTX + + enum Errors + { + RMI_NO_ERROR, + RMI_TAG_ERROR, + RMI_ARG_ERROR + }; + + enum Consts + { + MAX_PROCESSES = 8192, + ANY_SOURCE = -1, + INVALID_SOURCE = -2, + RMI_TAG = 315167, + RMI_ARG_TAG = 315168, + BREAK_RMI_TAG = 239954 + }; + +//ETX + + // Description: + // This method can be used to synchronize processes. + virtual void Barrier() = 0; + + static void SetGlobalController(vtkMultiProcessController *controller); + + //------------------ Communication -------------------- + + // Description: + // This method sends data to another process. Tag eliminates ambiguity + // when multiple sends or receives exist in the same process. + int Send(int* data, int length, int remoteProcessId, int tag); + int Send(unsigned long* data, int length, int remoteProcessId, + int tag); + int Send(char* data, int length, int remoteProcessId, int tag); + int Send(unsigned char* data, int length, int remoteProcessId, int tag); + int Send(float* data, int length, int remoteProcessId, int tag); + int Send(double* data, int length, int remoteProcessId, int tag); +#ifdef VTK_USE_64BIT_IDS + int Send(vtkIdType* data, int length, int remoteProcessId, int tag); +#endif + int Send(vtkDataObject *data, int remoteId, int tag); + int Send(vtkDataArray *data, int remoteId, int tag); + + // Description: + // This method receives data from a corresponding send. It blocks + // until the receive is finished. It calls methods in "data" + // to communicate the sending data. + int Receive(int* data, int length, int remoteProcessId, int tag); + int Receive(unsigned long* data, int length, int remoteProcessId, + int tag); + int Receive(char* data, int length, int remoteProcessId, int tag); + int Receive(unsigned char* data, int length, int remoteProcessId, int tag); + int Receive(float* data, int length, int remoteProcessId, int tag); + int Receive(double* data, int length, int remoteProcessId, int tag); +#ifdef VTK_USE_64BIT_IDS + int Receive(vtkIdType* data, int length, int remoteProcessId, int tag); +#endif + int Receive(vtkDataObject* data, int remoteId, int tag); + int Receive(vtkDataArray* data, int remoteId, int tag); + +// Internally implemented RMI to break the process loop. + +protected: + vtkMultiProcessController(); + ~vtkMultiProcessController(); + + int MaximumNumberOfProcesses; + int NumberOfProcesses; + + int LocalProcessId; + + vtkProcessFunctionType SingleMethod; + void *SingleData; + vtkProcessFunctionType MultipleMethod[MAX_PROCESSES]; + void *MultipleData[MAX_PROCESSES]; + + vtkCollection *RMIs; + + // This is a flag that can be used by the ports to break + // their update loop. (same as ProcessRMIs) + int BreakFlag; + + void ProcessRMI(int remoteProcessId, void *arg, int argLength, int rmiTag); + + // This method implements "GetGlobalController". + // It needs to be virtual and static. + virtual vtkMultiProcessController *GetLocalController(); + + + // This flag can force deep copies during send. + int ForceDeepCopy; + + vtkOutputWindow* OutputWindow; + + // Note that since the communicators can be created differently + // depending on the type of controller, the subclasses are + // responsible of deleting them. + vtkCommunicator* Communicator; + + // Communicator which is a copy of the current user + // level communicator except the context; i.e. even if the tags + // are the same, the RMI messages will not interfere with user + // level messages. + // Note that since the communicators can be created differently + // depending on the type of controller, the subclasses are + // responsible of deleting them. + vtkCommunicator* RMICommunicator; + +private: + vtkMultiProcessController(const vtkMultiProcessController&); // Not implemented. + void operator=(const vtkMultiProcessController&); // Not implemented. +}; + + +inline int vtkMultiProcessController::Send(vtkDataObject *data, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Send(vtkDataArray *data, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Send(int* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Send(unsigned long* data, + int length, int remoteProcessId, + int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Send(char* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Send(unsigned char* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Send(float* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Send(double* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +#ifdef VTK_USE_64BIT_IDS +inline int vtkMultiProcessController::Send(vtkIdType* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Send(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} +#endif + +inline int vtkMultiProcessController::Receive(vtkDataObject* data, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Receive(vtkDataArray* data, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Receive(int* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Receive(unsigned long* data, + int length,int remoteProcessId, + int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Receive(char* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Receive(unsigned char* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Receive(float* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +inline int vtkMultiProcessController::Receive(double* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} + +#ifdef VTK_USE_64BIT_IDS +inline int vtkMultiProcessController::Receive(vtkIdType* data, int length, + int remoteProcessId, int tag) +{ + if (this->Communicator) + { + return this->Communicator->Receive(data, length, remoteProcessId, tag); + } + else + { + return 0; + } +} +#endif + +#endif diff --git a/Parallel/vtkPCellDataToPointData.cxx b/Parallel/vtkPCellDataToPointData.cxx new file mode 100644 index 0000000..2965ecd --- /dev/null +++ b/Parallel/vtkPCellDataToPointData.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPCellDataToPointData.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPCellDataToPointData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnstructuredGrid.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPCellDataToPointData, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkPCellDataToPointData); + +//---------------------------------------------------------------------------- +vtkPCellDataToPointData::vtkPCellDataToPointData() +{ + this->PieceInvariant = 1; +} + +//---------------------------------------------------------------------------- +int vtkPCellDataToPointData::RequestData( + vtkInformation* request, + vtkInformationVector** inputVector , + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + if (!output) {return 0;} + + if ( !this->Superclass::RequestData(request, inputVector, outputVector) ) + { + return 0; + } + + // Remove the extra (now ivalid) ghost cells. + // This is only necessary fro unstructured data. + if (this->PieceInvariant) + { + vtkInformation* outInfo = outputVector->GetInformationObject(0); + int ghostLevel = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + vtkPolyData *pd = vtkPolyData::SafeDownCast(output); + vtkUnstructuredGrid *ug = vtkUnstructuredGrid::SafeDownCast(output); + if (pd) + { + pd->RemoveGhostCells(ghostLevel+1); + } + if (ug) + { + ug->RemoveGhostCells(ghostLevel+1); + } + } + return 1; +} + +//-------------------------------------------------------------------------- +int vtkPCellDataToPointData::ComputeInputUpdateExtent( + vtkInformation*, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + if (this->PieceInvariant == 0) + { + // I believe the default input update extent + // is set to the input update extent. + return 1; + } + + vtkInformation* opInfo = this->GetOutputPortInformation(0); + int extentType = opInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()); + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + + int piece, numPieces, ghostLevel; + int* wholeExt; + int* upExt; + int ext[6]; + switch (extentType) + { + case VTK_PIECES_EXTENT: + piece = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + numPieces = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ghostLevel = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()) + 1; + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), numPieces); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel); + return 1; + break; + case VTK_3D_EXTENT: + wholeExt = inInfo->Get( + vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + upExt = outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + memcpy(ext, upExt, 6*sizeof(int)); + for (int i = 0; i < 3; ++i) + { + --ext[i*2]; + if (ext[i*2] < wholeExt[i*2]) + { + ext[i*2] = wholeExt[i*2]; + } + ++ext[i*2+1]; + if (ext[i*2+1] > wholeExt[i*2+1]) + { + ext[i*2+1] = wholeExt[i*2+1]; + } + } + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext, 6); + return 1; + break; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkPCellDataToPointData::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PieceInvariant: " + << this->PieceInvariant << "\n"; +} diff --git a/Parallel/vtkPCellDataToPointData.h b/Parallel/vtkPCellDataToPointData.h new file mode 100644 index 0000000..5a434a1 --- /dev/null +++ b/Parallel/vtkPCellDataToPointData.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPCellDataToPointData.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPCellDataToPointData - Compute point arrays from cell arrays. +// .SECTION Description +// Like it super class, this filter averages the cell data around +// a point to get new point data. This subclass requests a layer of +// ghost cells to make the results invariant to pieces. There is a +// "PieceInvariant" flag that lets the user change the behavior +// of the filter to that of its superclass. + +#ifndef __vtkPCellDataToPointData_h +#define __vtkPCellDataToPointData_h + +#include "vtkCellDataToPointData.h" + +class VTK_PARALLEL_EXPORT vtkPCellDataToPointData : public vtkCellDataToPointData +{ +public: + vtkTypeRevisionMacro(vtkPCellDataToPointData,vtkCellDataToPointData); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + static vtkPCellDataToPointData *New(); + + // Description: + // To get piece invariance, this filter has to request an + // extra ghost level. By default piece invariance is on. + vtkSetMacro(PieceInvariant, int); + vtkGetMacro(PieceInvariant, int); + vtkBooleanMacro(PieceInvariant, int); + +protected: + vtkPCellDataToPointData(); + ~vtkPCellDataToPointData() {}; + + // Usual data generation method + virtual int RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual int ComputeInputUpdateExtent(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + int PieceInvariant; +private: + vtkPCellDataToPointData(const vtkPCellDataToPointData&); // Not implemented. + void operator=(const vtkPCellDataToPointData&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPChacoReader.cxx b/Parallel/vtkPChacoReader.cxx new file mode 100644 index 0000000..7cad71f --- /dev/null +++ b/Parallel/vtkPChacoReader.cxx @@ -0,0 +1,642 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPChacoReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkToolkits.h" +#include "vtkPChacoReader.h" +#include "vtkDataSetWriter.h" +#include "vtkDataSetReader.h" +#include "vtkExtractCells.h" +#include "vtkPKdTree.h" +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" +#include "vtkDoubleArray.h" +#include "vtkCharArray.h" +#include "vtkIntArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkMultiProcessController.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#ifdef VTK_USE_MPI +#include "vtkMPIController.h" +#include "vtkMPIGroup.h" +#endif + +vtkCxxRevisionMacro(vtkPChacoReader, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkPChacoReader); + +//---------------------------------------------------------------------------- +vtkPChacoReader::vtkPChacoReader() +{ + this->Controller = NULL; + this->SetController(vtkMultiProcessController::GetGlobalController()); +} + +//---------------------------------------------------------------------------- +vtkPChacoReader::~vtkPChacoReader() +{ + this->SetController(NULL); +} +//---------------------------------------------------------------------------- +void vtkPChacoReader::SetController(vtkMultiProcessController *c) +{ + if ((c == NULL) || (c->GetNumberOfProcesses() == 0)) + { + this->NumProcesses = 1; + this->MyId = 0; + } + + if (this->Controller == c) + { + return; + } + + this->Modified(); + + if (this->Controller != NULL) + { + this->Controller->UnRegister(this); + this->Controller = NULL; + } + + if (c == NULL) + { + return; + } + + this->Controller = c; + + c->Register(this); + this->NumProcesses = c->GetNumberOfProcesses(); + this->MyId = c->GetLocalProcessId(); +} + +//---------------------------------------------------------------------------- +int vtkPChacoReader::RequestInformation( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + if (!this->BaseName) + { + vtkErrorMacro(<< "No BaseName specified"); + return 0; + } + + // Setting maximum number of pieces to -1 indicates to the + // upstream consumer that I can provide the same number of pieces + // as there are number of processors + // get the info object + + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + if (!this->Controller->IsA("vtkMPIController")) + { + vtkErrorMacro(<< "parallel vtkPChacoReader requires MPI"); + return 0; + } + + int retVal = 1; + + if (this->MyId == 0) + { + retVal = + this->Superclass::RequestInformation(request, inputVector, outputVector); + } + + if (this->NumProcesses == 1) + { + return retVal; + } + + unsigned long metadata[8]; + + if (this->MyId == 0) + { + metadata[0] = static_cast(retVal); + + if (retVal) + { + metadata[1] = static_cast(this->RemakeDataCacheFlag); + if (this->RemakeDataCacheFlag) + { + metadata[2] = static_cast(this->Dimensionality); + metadata[3] = static_cast(this->NumberOfVertices); + metadata[4] = static_cast(this->NumberOfEdges); + metadata[5] = static_cast(this->NumberOfVertexWeights); + metadata[6] = static_cast(this->NumberOfEdgeWeights); + metadata[7] = static_cast(this->GraphFileHasVertexNumbers); + } + } + } + +#ifdef VTK_USE_MPI + vtkMPICommunicator *comm = + vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator()); + + comm->Broadcast(metadata, 8, 0); +#endif + + if (this->MyId > 0) + { + retVal = metadata[0]; + if (retVal) + { + this->RemakeDataCacheFlag = static_cast(metadata[1]); + if (this->RemakeDataCacheFlag) + { + this->Dimensionality = static_cast(metadata[2]); + this->NumberOfVertices = static_cast(metadata[3]); + this->NumberOfEdges = static_cast(metadata[4]); + this->NumberOfVertexWeights = static_cast(metadata[5]); + this->NumberOfEdgeWeights = static_cast(metadata[6]); + this->GraphFileHasVertexNumbers = static_cast(metadata[7]); + + this->MakeWeightArrayNames(this->NumberOfVertexWeights, + this->NumberOfEdgeWeights); + + this->SetCurrentBaseName(this->BaseName); + } + } + } + return retVal; +} + + +//---------------------------------------------------------------------------- +int vtkPChacoReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + if (!this->BaseName) + { + vtkErrorMacro(<< "No BaseName specified"); + return 0; + } + + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + int pieceZeroProc = 0; + + vtkMultiProcessController *contr = this->Controller; + +#ifdef VTK_USE_MPI + int i=0; + vtkMPICommunicator *comm = + vtkMPICommunicator::SafeDownCast(contr->GetCommunicator()); + + int oops = ((piece != this->MyId) || (numPieces != this->NumProcesses)); + int sum = 0; + + comm->ReduceSum(&oops, &sum, 1, 0); + comm->Broadcast(&sum, 1, 0); + + if (sum > 0) + { + // I don't know if this situation can occur, but we'll try to handle it. + + int *myPiece = new int [this->NumProcesses]; + + comm->AllGather(&piece, myPiece, 1); + + vtkMPICommunicator *subComm = vtkMPICommunicator::New(); + vtkMPIGroup *group = vtkMPIGroup::New(); + vtkMPIController *subController = NULL; + + group->Initialize(vtkMPIController::SafeDownCast(contr)); + + int nparticipants = 0; + + for (i=0; iNumProcesses; i++) + { + if ((myPiece[i] >= 0) && (myPiece[i] < numPieces)) + { + group->AddProcessId(i); + if (i == this->MyId) + { + subController = vtkMPIController::New(); + } + if (myPiece[i] == 0) + { + pieceZeroProc = nparticipants; + } + nparticipants++; + } + } + + delete [] myPiece; + + if (nparticipants < numPieces) // Can this happen? + { + subComm->Delete(); + group->Delete(); + if (subController) + { + subController->Delete(); + } + output->Initialize(); + vtkErrorMacro("<Initialize(comm, group); + group->Delete(); + + if (subController) + { + subController->SetCommunicator(subComm); + + contr = subController; + comm = subComm; + } + else + { + subComm->Delete(); + contr = NULL; + comm = NULL; + } + } +#endif + + if ( !contr) + { + // This process doesn't participate (can this happen?) + + this->SetUpEmptyGrid(output); + return 1; + } + + int retVal = 1; + + if (piece == 0) + { + // "piece" 0 reads in the entire mesh + + retVal = this->BuildOutputGrid(output); + } + + if (numPieces > 1) + { +#ifdef VTK_USE_MPI + comm->Broadcast(&retVal, 1, pieceZeroProc); +#endif + + if (retVal == 1) + { + retVal = this->DivideCells(contr, output, pieceZeroProc); + } + } + + if (contr != this->Controller) + { +#ifdef VTK_USE_MPI + comm->Delete(); +#endif + contr->Delete(); + } + + return retVal; +} +//---------------------------------------------------------------------------- +void vtkPChacoReader::SetUpEmptyGrid(vtkUnstructuredGrid *output) +{ + int i; + // Note: The cell and point arrays should be added in the same order in + // which they are added in vtkChacoReader::BuildOutputGrid. See "Note" in + // vtkChacoReader.cxx. + + output->Initialize(); + + if (this->GetGenerateVertexWeightArrays()) + { + for (i=0; i < this->NumberOfVertexWeights; i++) + { + vtkDoubleArray *da = vtkDoubleArray::New(); + da->SetNumberOfTuples(0); + da->SetNumberOfComponents(1); + da->SetName(this->GetVertexWeightArrayName(i+1)); + output->GetPointData()->AddArray(da); + da->Delete(); + } + + this->NumberOfPointWeightArrays = this->NumberOfVertexWeights; + } + + if (this->GetGenerateEdgeWeightArrays()) + { + for (i=0; i < this->NumberOfEdgeWeights; i++) + { + vtkDoubleArray *da = vtkDoubleArray::New(); + da->SetNumberOfTuples(0); + da->SetNumberOfComponents(1); + da->SetName(this->GetEdgeWeightArrayName(i+1)); + output->GetCellData()->AddArray(da); + da->Delete(); + } + + this->NumberOfCellWeightArrays = this->NumberOfEdgeWeights; + } + + if (this->GetGenerateGlobalElementIdArray()) + { + vtkIntArray *ia = vtkIntArray::New(); + ia->SetNumberOfTuples(0); + ia->SetNumberOfComponents(1); + ia->SetName(this->GetGlobalElementIdArrayName()); + output->GetCellData()->AddArray(ia); + } + + if (this->GetGenerateGlobalNodeIdArray()) + { + vtkIntArray *ia = vtkIntArray::New(); + ia->SetNumberOfTuples(0); + ia->SetNumberOfComponents(1); + ia->SetName(this->GetGlobalNodeIdArrayName()); + output->GetPointData()->AddArray(ia); + } +} +//---------------------------------------------------------------------------- +int vtkPChacoReader::DivideCells(vtkMultiProcessController *contr, + vtkUnstructuredGrid *output, int source) +{ + int retVal = 1; + +#ifdef VTK_USE_MPI + int i=0; + vtkMPICommunicator *comm = + vtkMPICommunicator::SafeDownCast(contr->GetCommunicator()); + + int nprocs = contr->GetNumberOfProcesses(); + int myrank = contr->GetLocalProcessId(); + + vtkUnstructuredGrid *mygrid = NULL; + + if (source == myrank) + { + vtkIdType ntotalcells = output->GetNumberOfCells(); + vtkIdType nshare = ntotalcells / nprocs; + vtkIdType leftover = ntotalcells - (nprocs * nshare); + + vtkIdType startId = 0; + + for (i=0; i < nprocs; i++) + { + if (!retVal && (i != myrank)) + { + this->SendGrid(contr, i, NULL); // we failed + continue; + } + + vtkIdType ncells = ((i < leftover) ? nshare + 1 : nshare); + + vtkIdType endId = startId + ncells - 1; + + vtkUnstructuredGrid *ug = this->SubGrid(output, startId, endId); + + if (i != myrank) + { + retVal = this->SendGrid(contr, i, ug); + ug->Delete(); + } + else + { + mygrid = ug; + } + startId += ncells; + } + } + else + { + mygrid = this->GetGrid(contr, source); + if (mygrid == NULL) + { + retVal = 0; + } + } + + int vote = 0; + comm->ReduceSum(&retVal, &vote, 1, 0); + comm->Broadcast(&vote, 1, 0); + + if (vote < nprocs) + { + retVal = 0; + } + + output->Initialize(); + + if (retVal) + { + output->ShallowCopy(mygrid); + } + else if (mygrid) + { + mygrid->Delete(); + } + +#else + vtkErrorMacro(<< "vtkPChacoReader::DivideCells requires MPI"); + (void)source; + (void)contr; + (void)output; +#endif + return retVal; +} +int vtkPChacoReader::SendGrid(vtkMultiProcessController *c, + int to, vtkUnstructuredGrid *grid) +{ + int retVal = 1; + +#ifdef VTK_USE_MPI + vtkMPIController *contr = vtkMPIController::SafeDownCast(c); + int bufsize=0, ack = 0; + + if (!grid) + { + // sending notice of a failure + + contr->Send(&bufsize, 1, to, 0x11); + return retVal; + } + + char *buf = this->MarshallDataSet(grid, bufsize); + + contr->Send(&bufsize, 1, to, 0x11); + + contr->Receive(&ack, 1, to, 0x12); + + if (!ack) + { + retVal = 0; + } + else + { + contr->Send(buf, bufsize, to, 0x13); + } + + delete [] buf; +#else + vtkErrorMacro(<< "vtkPChacoReader::SendGrid requires MPI"); + (void)c; + (void)to; + (void)grid; +#endif + return retVal; +} +vtkUnstructuredGrid *vtkPChacoReader::GetGrid(vtkMultiProcessController *c, int from) +{ + vtkUnstructuredGrid *grid = NULL; + +#ifdef VTK_USE_MPI + vtkMPIController *contr = vtkMPIController::SafeDownCast(c); + int bufsize=0, ack=1; + + contr->Receive(&bufsize, 1, from, 0x11); + + if (bufsize == 0) + { + // Node zero is reporting an error + return NULL; + } + + char *buf = new char [bufsize]; + + if (buf) + { + contr->Send(&ack, 1, from, 0x12); + contr->Receive(buf, bufsize, from, 0x13); + grid = this->UnMarshallDataSet(buf, bufsize); + delete [] buf; + } + else + { + ack = 0; + contr->Send(&ack, 1, 0, 0x12); + } +#else + vtkErrorMacro(<< "vtkPChacoReader::GetGrid requires MPI"); + (void)c; + (void)from; +#endif + return grid; +} + +vtkUnstructuredGrid * + vtkPChacoReader::SubGrid(vtkUnstructuredGrid *ug, vtkIdType from, vtkIdType to) +{ + vtkUnstructuredGrid *tmp = vtkUnstructuredGrid::New(); + + if (from > to) + { + this->SetUpEmptyGrid(tmp); + } + else + { + tmp->ShallowCopy(ug); + + vtkExtractCells *ec = vtkExtractCells::New(); + ec->AddCellRange(from, to); + ec->SetInput(tmp); + ec->Update(); + + tmp->Initialize(); + tmp->ShallowCopy(ec->GetOutput()); + ec->Delete(); + } + + return tmp; +} +char *vtkPChacoReader::MarshallDataSet(vtkUnstructuredGrid *extractedGrid, int &len) +{ + // taken from vtkCommunicator::WriteDataSet + + vtkUnstructuredGrid *copy; + vtkDataSetWriter *writer = vtkDataSetWriter::New(); + + copy = extractedGrid->NewInstance(); + copy->ShallowCopy(extractedGrid); + + // There is a problem with binary files with no data. + if (copy->GetNumberOfCells() > 0) + { + writer->SetFileTypeToBinary(); + } + writer->WriteToOutputStringOn(); + writer->SetInput(copy); + + writer->Write(); + + len = writer->GetOutputStringLength(); + + char *packedFormat = writer->RegisterAndGetOutputString(); + + writer->Delete(); + + copy->Delete(); + + return packedFormat; +} +vtkUnstructuredGrid *vtkPChacoReader::UnMarshallDataSet(char *buf, int size) +{ + // taken from vtkCommunicator::ReadDataSet + + vtkDataSetReader *reader = vtkDataSetReader::New(); + + reader->ReadFromInputStringOn(); + + vtkCharArray* mystring = vtkCharArray::New(); + + mystring->SetArray(buf, size, 1); + + reader->SetInputArray(mystring); + mystring->Delete(); + + vtkDataSet *output = reader->GetOutput(); + output->Update(); + + vtkUnstructuredGrid *newGrid = vtkUnstructuredGrid::New(); + + newGrid->ShallowCopy(output); + + reader->Delete(); + + return newGrid; +} +//---------------------------------------------------------------------------- +void vtkPChacoReader::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkChacoReader::PrintSelf(os,indent); + os << indent << "MyId: " << this->MyId << endl; + os << indent << "NumProcesses: " << this->NumProcesses << endl; + os << indent << "Controller: " << this->Controller << endl; +} + diff --git a/Parallel/vtkPChacoReader.h b/Parallel/vtkPChacoReader.h new file mode 100644 index 0000000..a056fa9 --- /dev/null +++ b/Parallel/vtkPChacoReader.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPChacoReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkPChacoReader - Read Chaco files +// .SECTION Description +// vtkPChacoReader is a unstructured grid source object that reads +// Chaco files. The file is read by process 0 and converted into +// a vtkUnstructuredGrid. The vtkDistributedDataFilter is invoked +// to divide the grid among the processes. + +#ifndef __vtkPChacoReader_h +#define __vtkPChacoReader_h + +#include "vtkChacoReader.h" + +class vtkTimerLog; +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkPChacoReader : public vtkChacoReader +{ +public: + static vtkPChacoReader *New(); + vtkTypeRevisionMacro(vtkPChacoReader,vtkChacoReader); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the communicator object (we'll use global World controller + // if you don't set a different one). + + void SetController(vtkMultiProcessController *c); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + +protected: + vtkPChacoReader(); + ~vtkPChacoReader(); + + int RequestInformation( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestData( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkPChacoReader(const vtkPChacoReader&); // Not implemented + void operator=(const vtkPChacoReader&); // Not implemented + + void SetUpEmptyGrid(vtkUnstructuredGrid *output); + int DivideCells(vtkMultiProcessController *contr, vtkUnstructuredGrid *output, + int source); + int SendGrid(vtkMultiProcessController *c, int to, vtkUnstructuredGrid *grid); + vtkUnstructuredGrid *GetGrid(vtkMultiProcessController *c, int from); + vtkUnstructuredGrid *SubGrid(vtkUnstructuredGrid *ug, vtkIdType from, vtkIdType to); + char *MarshallDataSet(vtkUnstructuredGrid *extractedGrid, int &len); + vtkUnstructuredGrid *UnMarshallDataSet(char *buf, int size); + + int NumProcesses; + int MyId; + + vtkMultiProcessController *Controller; +}; + +#endif diff --git a/Parallel/vtkPDataSetReader.cxx b/Parallel/vtkPDataSetReader.cxx new file mode 100644 index 0000000..ea28b48 --- /dev/null +++ b/Parallel/vtkPDataSetReader.cxx @@ -0,0 +1,1483 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPDataSetReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPDataSetReader.h" + +#include "vtkAppendFilter.h" +#include "vtkAppendPolyData.h" +#include "vtkCellData.h" +#include "vtkDataSetReader.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkSource.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridReader.h" +#include "vtkStructuredPoints.h" +#include "vtkStructuredPointsReader.h" +#include "vtkUnstructuredGrid.h" +#include "vtkExtentTranslator.h" + +vtkCxxRevisionMacro(vtkPDataSetReader, "$Revision: 1.37 $"); +vtkStandardNewMacro(vtkPDataSetReader); + +//---------------------------------------------------------------------------- +vtkPDataSetReader::vtkPDataSetReader() +{ + this->FileName = NULL; + this->VTKFileFlag = 0; + this->StructuredFlag = 0; + this->NumberOfPieces = 0; + this->DataType = -1; + this->PieceFileNames = NULL; + this->PieceExtents = NULL; + this->SetNumberOfOutputPorts(1); + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkPDataSetReader::~vtkPDataSetReader() +{ + delete[] this->FileName; + this->SetNumberOfPieces(0); +} + + +//---------------------------------------------------------------------------- +void vtkPDataSetReader::SetNumberOfPieces(int num) +{ + int i; + + if (this->NumberOfPieces == num) + { + return; + } + + // Delete the previous file names/extents. + for (i = 0; i < this->NumberOfPieces; ++i) + { + if (this->PieceFileNames[i]) + { + delete [] this->PieceFileNames[i]; + this->PieceFileNames[i] = NULL; + } + if (this->PieceExtents && this->PieceExtents[i]) + { + delete [] this->PieceExtents[i]; + this->PieceExtents[i] = NULL; + } + } + if (this->PieceFileNames) + { + delete [] this->PieceFileNames; + this->PieceFileNames = NULL; + } + if (this->PieceExtents) + { + delete [] this->PieceExtents; + this->PieceExtents = NULL; + } + this->NumberOfPieces = 0; + + + if (num <= 0) + { + return; + } + + // Allocate new arrays + this->PieceFileNames = new char*[num]; + for (i = 0; i < num; ++i) + { + this->PieceFileNames[i] = new char[512]; + } + // Allocate piece extents even for unstructured data. + this->PieceExtents = new int*[num]; + for (i = 0; i < num; ++i) + { + this->PieceExtents[i] = new int[6]; + } + + + this->NumberOfPieces = num; +} + + +//---------------------------------------------------------------------------- +int vtkPDataSetReader::RequestDataObject( + vtkInformation* request, + vtkInformationVector** inputVector , + vtkInformationVector* outputVector) +{ + + ifstream *file; + char* block; + char* param; + char* value; + int type; + + // Start reading the meta-data pvtk file. + file = this->OpenFile(this->FileName); + if (file == NULL) + { + return 0; + } + + type = this->ReadXML(file, &block, ¶m, &value); + if (type == 1 && strcmp(block, "File") == 0) + { + this->ReadPVTKFileInformation(file, request, inputVector, outputVector); + this->VTKFileFlag = 0; + } + else if (type == 4 && strncmp(value, "# vtk DataFile Version", 22) == 0) + { + // This is a vtk file not a PVTK file. + this->ReadVTKFileInformation(file, request, inputVector, outputVector); + this->VTKFileFlag = 1; + } + else + { + vtkErrorMacro("This does not look like a VTK file: " << this->FileName); + } + file->close(); + delete file; + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + if (output && output->GetDataObjectType() == this->DataType) + { + return 1; + } + + vtkDataSet* newOutput=0; + switch (this->DataType) + { + case VTK_POLY_DATA: + newOutput = vtkPolyData::New(); + break; + case VTK_UNSTRUCTURED_GRID: + newOutput = vtkUnstructuredGrid::New(); + break; + case VTK_STRUCTURED_GRID: + newOutput = vtkStructuredGrid::New(); + break; + case VTK_RECTILINEAR_GRID: + newOutput = vtkRectilinearGrid::New(); + break; + case VTK_IMAGE_DATA: + newOutput = vtkImageData::New(); + break; + case VTK_STRUCTURED_POINTS: + newOutput = vtkImageData::New(); + break; + default: + vtkErrorMacro("Unknown data type."); + return 0; + } + + if (output) + { + vtkWarningMacro("Creating a new output of type " + << newOutput->GetClassName()); + } + + newOutput->SetPipelineInformation(info); + this->GetOutputPortInformation(0)->Set( + vtkDataObject::DATA_EXTENT_TYPE(), newOutput->GetExtentType()); + newOutput->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +// Returns 0 for end of file. +// Returns 1 for start block, +// Returns 2 for parameter-value pair (occurs after 1 but before 3). +// Returns 3 for termination of start block. +// Returns 4 for string inside block. Puts string in retVal. (param = NULL) +// Returns 5 for end block. +// ======= +// The statics should be instance variables ... +int vtkPDataSetReader::ReadXML(ifstream *file, + char **retBlock, char **retParam, char **retVal) +{ + static char str[1024]; + static char* ptr = NULL; + static char block[256]; + static char param[256]; + static char value[512]; + // I could keep track of the blocks on a stack, but I don't need to. + static int inStartBlock = 0; + char *tmp; + + // Initialize the strings. + if (ptr == NULL) + { + block[0] = param[0] = value[0] = '\0'; + } + + // Skip white space + // We could do this with a get char ... + while (ptr == NULL || *ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\0') + { + if (ptr == NULL || *ptr == '\0') + { // At the end of a line. Read another. + file->getline(str, 1024); + if (file->fail()) + { + *retBlock = NULL; + *retParam = NULL; + *retVal = NULL; + return 0; + } + str[1023] = '\0'; + ptr = str; + } + else + { + ++ptr; + } + } + + // Handle normal end block. + if (!inStartBlock && ptr[0] == '<' && ptr[1] == '/') + { // Assumes no spaces + ptr += 2; + // We could check to see if the block name matches the start block... + // Copy block name into block var. + tmp = block; + while (*ptr != '>' && *ptr != ' ' && *ptr != '\0') + { + *tmp++ = *ptr++; + } + *tmp = '\0'; + // Now scan to the end of the end block. + while (*ptr != '>' && *ptr != '\0') + { + *tmp++ = *ptr++; + } + *retBlock = block; + *retParam = NULL; + *retVal = NULL; + if (*ptr == '\0') + { + vtkErrorMacro("Newline in end block."); + return 0; + } + return 5; + } + + // Handle start block. + if (!inStartBlock && ptr[0] == '<') + { // Assumes no spaces + ptr += 1; + // Copy block name from read string. + tmp = block; + while (*ptr != '>' && *ptr != ' ' && *ptr != '\0') + { + *tmp++ = *ptr++; + } + *tmp = '\0'; + inStartBlock = 1; + *retBlock = block; + *retParam = NULL; + *retVal = NULL; + return 1; + } + + // Handle the termination of a start block. + if (inStartBlock && *ptr == '>') + { + ++ptr; + inStartBlock = 0; + *retBlock = block; + *retParam = NULL; + *retVal = NULL; + return 3; + } + + // Handle short version of end block. + // Now we want to return twice. + // First for termination of the start block, + // and second for ending of the block. + // This implementation uses in start block as a state variable ... + if (inStartBlock && ptr[0] == '/' && ptr[1] == '>') + { + if (inStartBlock == 2) + { // Second pass: Return end block. + ptr += 2; + inStartBlock = 0; + *retBlock = block; + *retParam = NULL; + *retVal = NULL; + return 5; + } + // First pass: inStartBlock == 1. Return Terminate start block. + // Uses block name saved from start block. + // Do not skip over the '/>' characters. + inStartBlock = 2; + *retBlock = block; + *retParam = NULL; + *retVal = NULL; + return 3; + } + + // If we are not in a start block, we will just return the string verbatim. + if (!inStartBlock) + { + // Copy string to value string. + tmp = value; + while (*ptr != '\0') + { + *tmp++ = *ptr++; + } + *tmp = '\0'; + // We do not return the block because we do not have a block stack, + // so cannot be sure what the block is. + *retBlock = NULL; + *retParam = NULL; + *retVal = value; + return 4; + } + + // Must be a parameter + tmp = param; + while (*ptr != '=' && *ptr != '\0') + { + *tmp++ = *ptr++; + } + // Terminate the parameter string. + *tmp = '\0'; + // Expect an equals sign imediately after parameter string (no spaces). + if (*ptr != '=') + { + vtkErrorMacro("Reached end of line before ="); + return 0; + } + // skip over = sign. + ++ptr; + if (*ptr != '"') + { + vtkErrorMacro("Expecting parameter value to be in quotes."); + return 0; + } + ++ptr; + tmp = value; + while (*ptr != '"' && *ptr != '\0') + { + *tmp++ = *ptr++; + } + // Terminate the value string + *tmp = '\0'; + if (*ptr != '"') + { + vtkErrorMacro("Newline found in parameter string."); + return 0; + } + // Skip over the last quote + ++ptr; + + *retBlock = block; + *retParam = param; + *retVal = value; + return 2; +} + + + +//---------------------------------------------------------------------------- +int vtkPDataSetReader::CanReadFile(const char* filename) +{ + ifstream *file; + char* block; + char* param; + char* value; + int type; + int flag = 0; + + // Start reading the meta-data pvtk file. + file = this->OpenFile(filename); + if (file == NULL) + { + return 0; + } + + type = this->ReadXML(file, &block, ¶m, &value); + if (type == 1 && strcmp(block, "File") == 0) + { + // We cannot leave the XML parser in a bad state. + // As a quick fix, read to the end of the file block. + // A better solution would be to move statics + // to ivars and initialize them as needed. + while (this->ReadXML(file, &block, ¶m, &value) != 5) {} + flag = 1; + } + + if (type == 4 && strncmp(value, "# vtk DataFile Version", 22) == 0) + { + // This is a vtk file. + vtkDataSetReader* tmp = vtkDataSetReader::New(); + tmp->SetFileName(filename); + type = tmp->ReadOutputType(); + if (type != -1) + { + flag = 1; + } + tmp->Delete(); + } + + + file->close(); + delete file; + return flag; +} + + + +//---------------------------------------------------------------------------- +void vtkPDataSetReader::ReadPVTKFileInformation( + ifstream *file, + vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + char* block; + char* param; + char* val; + int type; + int ext[6]; + double vect[3]; + int i; + char *pfn, *pdir; + int count, dirLength; + char dir[512]; + + vtkInformation* info = outputVector->GetInformationObject(0); + + // The file block should have a version parameter. + type = this->ReadXML(file, &block, ¶m, &val); + if (type != 2 || strcmp(param,"version")) + { + vtkErrorMacro("Could not find file version."); + return; + } + if (strcmp(val,"pvtk-1.0") != 0) + { + vtkDebugMacro("Unexpected Version."); + } + + // Extract the directory form the filename so we can complete relative paths. + count = dirLength = 0; + pfn = this->FileName; + pdir = dir; + // Copy filename to dir, and keep track of the last slash. + while (*pfn != '\0' && count < 512) + { + *pdir++ = *pfn++; + ++count; + if (*pfn == '/' || *pfn == '\\') + { + // The extra +1 is to keep the last slash. + dirLength = count+1; + } + } + // This trims off every thing after the last slash. + dir[dirLength] = '\0'; + + // We are in the start file block. + // Read parameters until we terminate the start block. + while ( (type = this->ReadXML(file, &block, ¶m, &val)) != 3) + { + if (type == 0) + { + vtkErrorMacro("Early termination of pvtk file."); + return; + } + if (type != 2) + { // There should be no other possibility. Param will not be NULL. + vtkErrorMacro("Expecting a parameter."); + return; + } + + // Handle parameter: numberOfPieces. + if (strcmp(param, "numberOfPieces") == 0) + { + this->SetNumberOfPieces(atoi(val)); + if (! this->StructuredFlag) + { + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + this->NumberOfPieces); + } + } + + // Handle parameter: wholeExtent. + if (strcmp(param, "wholeExtent") == 0) + { + if (! this->StructuredFlag) + { + vtkWarningMacro("Extent mismatch."); + } + sscanf(val, "%d %d %d %d %d %d", ext, ext+1, ext+2, ext+3, ext+4, ext+5); + info->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext, 6); + } + + // Handle parameter: scalarType. + if (strcmp(param, "scalarType") == 0) + { + vtkDataObject::SetPointDataActiveScalarInfo(info, atoi(val), -1); + } + + // Handle parameter: spacing. + if (strcmp(param, "spacing") == 0) + { + sscanf(val, "%lf %lf %lf", vect, vect+1, vect+2); + info->Set(vtkDataObject::SPACING(), vect, 3); + } + + // Handle parameter: origin. + if (strcmp(param, "origin") == 0) + { + sscanf(val, "%lf %lf %lf", vect, vect+1, vect+2); + info->Set(vtkDataObject::ORIGIN(), vect, 3); + } + + // Handle parameter: dataType. + if (strcmp(param, "dataType") == 0) + { + if (strcmp(val, "vtkPolyData") == 0) + { + this->DataType = VTK_POLY_DATA; + this->StructuredFlag = 0; + } + else if (strcmp(val, "vtkUnstructuredGrid") == 0) + { + this->DataType = VTK_UNSTRUCTURED_GRID; + this->StructuredFlag = 0; + } + else if (strcmp(val, "vtkStructuredGrid") == 0) + { + this->DataType = VTK_STRUCTURED_GRID; + this->StructuredFlag = 1; + } + else if (strcmp(val, "vtkRectilinearGrid") == 0) + { + this->DataType = VTK_RECTILINEAR_GRID; + this->StructuredFlag = 1; + } + else if (strcmp(val, "vtkImageData") == 0 || strcmp(val, "vtkStructuredPoints") == 0) + { + this->DataType = VTK_IMAGE_DATA; + this->StructuredFlag = 1; + } + else + { + vtkErrorMacro("Unknown data type " << val); + return; + } + } + } + + // Read the filename and extents for each piece. + for (i = 0; i < this->NumberOfPieces; ++i) + { + int *pi = this->PieceExtents[i]; + // Initialize extent to nothing. + pi[0] = pi[2] = pi[4] = 0; + pi[1] = pi[3] = pi[5] = -1; + + // Read the start tag of the Piece block. + type = this->ReadXML(file, &block, ¶m, &val); + if ( type != 1 || strcmp(block,"Piece") != 0) + { + vtkErrorMacro("Expecting the start of a 'Piece' block"); + return; + } + while ( (type = this->ReadXML(file, &block, ¶m, &val)) != 3) + { + if (type != 2) + { // There should be no other possibility. Param will not be NULL. + vtkErrorMacro("Expecting a parameter."); + return; + } + + // Handle the file name parameter. + if (strcmp(param,"fileName") == 0) + { + // Copy filename (relative path?) + if (val[0] != '/' && val[1] != ':' && dirLength > 0) + { // Must be a relative path. + sprintf(this->PieceFileNames[i], "%s%s", dir, val); + } + else + { + strcpy(this->PieceFileNames[i], val); + } + } + + // Handle the extent parameter. + if (strcmp(param,"extent") == 0) + { + if ( ! this->StructuredFlag) + { + vtkWarningMacro("Found extent parameter for unstructured data."); + } + sscanf(val, "%d %d %d %d %d %d", pi, pi+1, pi+2, pi+3, pi+4, pi+5); + } + } + // Start termination was consumed by while loop. + + // Now read the ending piece block. + type = this->ReadXML(file, &block, ¶m, &val); + if ( type != 5 || strcmp(block,"Piece") != 0) + { + vtkErrorMacro("Expecting termination of the Piece block."); + return; + } + } +} + + +//---------------------------------------------------------------------------- +void vtkPDataSetReader::ReadVTKFileInformation( + ifstream *file, + vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + int i; + int dx, dy, dz; + float x, y, z; + char str[1024]; + + vtkInformation* info = outputVector->GetInformationObject(0); + + // To avoid UMR in the first string comparison + strcpy(str, " "); + + // Try to find the line that specifies the dataset type. + i = 0; + while (strncmp(str, "DATASET", 7) != 0 && i < 6) + { + file->getline(str, 1024); + ++i; + } + + if (strncmp(str, "DATASET POLYDATA", 16) == 0) + { + this->DataType = VTK_POLY_DATA; + } + else if (strncmp(str, "DATASET UNSTRUCTURED_GRID", 25) == 0) + { + this->DataType = VTK_UNSTRUCTURED_GRID; + } + else if (strncmp(str, "DATASET STRUCTURED_GRID", 23) == 0) + { + this->DataType = VTK_STRUCTURED_GRID; + file->getline(str, 1024, ' '); + + if (! strncmp(str, "FIELD", 5)) + { + this->SkipFieldData(file); + file->getline(str, 1024, ' '); + vtkErrorMacro(<< str); + } + if (strncmp(str, "DIMENSIONS", 10) != 0) + { + vtkErrorMacro("Expecting 'DIMENSIONS' insted of: " << str); + return; + } + + *file >> dx; + *file >> dy; + *file >> dz; + info->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, dx-1, 0, dy-1, 0, dz-1); + } + else if (strncmp(str, "DATASET RECTILINEAR_GRID", 24) == 0) + { + this->DataType = VTK_RECTILINEAR_GRID; + file->getline(str, 1024, ' '); + if (strncmp(str, "DIMENSIONS", 10) != 0) + { + vtkErrorMacro("Expecting 'DIMENSIONS' insted of: " << str); + return; + } + *file >> dx; + *file >> dy; + *file >> dz; + info->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, dx-1, 0, dy-1, 0, dz-1); + } + else if (strncmp(str, "DATASET STRUCTURED_POINTS", 25) == 0) + { + this->DataType = VTK_IMAGE_DATA; + file->getline(str, 1024, ' '); + // hack to stop reading. + while (strlen(str) > 5) + { + if (strncmp(str, "DIMENSIONS", 10) == 0) + { + *file >> dx; + *file >> dy; + *file >> dz; + info->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + 0, dx-1, 0, dy-1, 0, dz-1); + } + if (strncmp(str, "SPACING", 7) == 0 || strncmp(str, "ASPECT_RATIO", 12) == 0) + { + *file >> x; + *file >> y; + *file >> z; + info->Set(vtkDataObject::SPACING(), x, y, z); + } + if (strncmp(str, "ORIGIN", 6) == 0) + { + *file >> x; + *file >> y; + *file >> z; + info->Set(vtkDataObject::ORIGIN(), x, y, z); + } + file->getline(str, 1024); + file->getline(str, 1024, ' '); + } + } + else + { + vtkErrorMacro("I can not figure out what type of data set this is: " << str); + return; + } + if (this->DataType == VTK_POLY_DATA || this->DataType == VTK_UNSTRUCTURED_GRID) + { + info->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), 1); + } +} + +void vtkPDataSetReader::SkipFieldData(ifstream *file) +{ + int i, numArrays; + char name[256], type[256]; + int numComp, numTuples; + + file->width(256); + *file >> name; + *file >> numArrays; + + if (file->fail()) + { + vtkErrorMacro("Could not read field."); + return; + } + + // Read the number of arrays specified + for (i=0; i> buffer; + *file >> numComp; + *file >> numTuples; + *file >> type; + // What a pain. + if (strcmp(type, "double") == 0) + { + length = sizeof(double) * numComp * numTuples; + } + if (strcmp(type, "float") == 0) + { + length = sizeof(float) * numComp * numTuples; + } + if (strcmp(type, "long") == 0) + { + length = sizeof(long) * numComp * numTuples; + } + if (strcmp(type, "unsigned long") == 0) + { + length = sizeof(unsigned long) * numComp * numTuples; + } + if (strcmp(type, "int") == 0) + { + length = sizeof(int) * numComp * numTuples; + } + if (strcmp(type, "unsigned int") == 0) + { + length = sizeof(unsigned int) * numComp * numTuples; + } + if (strcmp(type, "short") == 0) + { + length = sizeof(short) * numComp * numTuples; + } + if (strcmp(type, "unsigned short") == 0) + { + length = sizeof(unsigned short) * numComp * numTuples; + } + if (strcmp(type, "char") == 0) + { + length = sizeof(char) * numComp * numTuples; + } + if (strcmp(type, "unsigned char") == 0) + { + length = sizeof(unsigned char) * numComp * numTuples; + } + + // suckup new line. + file->getline(name,256); + + char *buf = new char[length]; + + //int t = file->tellg(); + // this seek did not work for some reason. + // it passed too many characters. + //file->seekg(length, ios::cur); + file->read(buf, length); + + delete [] buf; + + // suckup new line. + file->getline(name,256); + if (file->fail()) + { + vtkErrorMacro("Could not seek past field."); + return; + } + } +} + +//---------------------------------------------------------------------------- +ifstream *vtkPDataSetReader::OpenFile(const char* filename) +{ + ifstream *file; + + if (!filename || filename[0] == '\0') + { + vtkDebugMacro(<<"A FileName must be specified."); + return NULL; + } + + // Open the new file + file = new ifstream(filename, ios::in); + + if (! file || file->fail()) + { + if (file) + { + delete file; + } + vtkErrorMacro(<< "Initialize: Could not open file " << filename); + return NULL; + } + + return file; +} + +//---------------------------------------------------------------------------- +int vtkPDataSetReader::RequestData(vtkInformation* request, + vtkInformationVector** inputVector , + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + if (this->VTKFileFlag) + { + vtkDataSetReader *reader = vtkDataSetReader::New(); + reader->ReadAllScalarsOn(); + reader->ReadAllVectorsOn(); + reader->ReadAllNormalsOn(); + reader->ReadAllTensorsOn(); + reader->ReadAllColorScalarsOn(); + reader->ReadAllTCoordsOn(); + reader->ReadAllFieldsOn(); + reader->SetFileName(this->FileName); + reader->Update(); + vtkDataSet *data = reader->GetOutput(); + + if (data == NULL) + { + vtkErrorMacro("Could not read file: " << this->FileName); + return 0; + } +// data->Update(); + + if (data->CheckAttributes()) + { + vtkErrorMacro("Attribute Mismatch."); + return 0; + } + + // Do not copy the ExtentTranslator (hack) + // reader should probably set the extent translator + // not paraview. + vtkExtentTranslator *tmp = output->GetExtentTranslator(); + tmp->Register(this); + output->CopyStructure(data); + output->SetExtentTranslator(tmp); + tmp->UnRegister(tmp); + output->GetCellData()->PassData(data->GetCellData()); + output->GetPointData()->PassData(data->GetPointData()); + this->SetNumberOfPieces(0); + + reader->Delete(); + return 1; + } + + switch (this->DataType) + { + case VTK_POLY_DATA: + return this->PolyDataExecute(request, inputVector, outputVector); + break; + case VTK_UNSTRUCTURED_GRID: + return this->UnstructuredGridExecute(request, inputVector, outputVector); + break; + case VTK_IMAGE_DATA: + return this->ImageDataExecute(request, inputVector, outputVector); + break; + case VTK_STRUCTURED_GRID: + return this->StructuredGridExecute(request, inputVector, outputVector); + break; + default: + vtkErrorMacro("We do not handle vtkRectilinear yet."); + return 0; + } +} + + + +//---------------------------------------------------------------------------- +int vtkPDataSetReader::PolyDataExecute(vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkPolyData *output = vtkPolyData::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + int updatePiece, updateNumberOfPieces; + int startPiece, endPiece; + int idx; + + updatePiece = output->GetUpdatePiece(); + updateNumberOfPieces = output->GetUpdateNumberOfPieces(); + + // Only the first N pieces have anything in them. + if (updateNumberOfPieces > this->NumberOfPieces) + { + updateNumberOfPieces = this->NumberOfPieces; + } + if (updatePiece >= updateNumberOfPieces) + { // This duplicates functionality of the pipeline super classes ... + return 1; + } + + startPiece = updatePiece * this->NumberOfPieces / updateNumberOfPieces; + endPiece = ((updatePiece+1) * this->NumberOfPieces / updateNumberOfPieces) - 1; + + if (endPiece < startPiece) + { + return 1; + } + + vtkDataSetReader *reader; + vtkAppendPolyData *append = vtkAppendPolyData::New(); + for (idx = startPiece; idx <= endPiece; ++idx) + { + vtkPolyData *tmp; + reader = vtkDataSetReader::New(); + reader->ReadAllScalarsOn(); + reader->ReadAllVectorsOn(); + reader->ReadAllNormalsOn(); + reader->ReadAllTensorsOn(); + reader->ReadAllColorScalarsOn(); + reader->ReadAllTCoordsOn(); + reader->ReadAllFieldsOn(); + reader->SetFileName(this->PieceFileNames[idx]); + tmp = reader->GetPolyDataOutput(); + if (tmp && tmp->GetDataObjectType() != VTK_POLY_DATA) + { + vtkWarningMacro("Expecting PolyData in file: " << this->PieceFileNames[idx]); + } + else + { + append->AddInput(tmp); + } + reader->Delete(); + } + + append->Update(); + output->CopyStructure(append->GetOutput()); + output->GetCellData()->PassData(append->GetOutput()->GetCellData()); + output->GetPointData()->PassData(append->GetOutput()->GetPointData()); + + append->Delete(); + + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkPDataSetReader::UnstructuredGridExecute( + vtkInformation*, + vtkInformationVector** , + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + int updatePiece, updateNumberOfPieces; + int startPiece, endPiece; + int idx; + + updatePiece = output->GetUpdatePiece(); + updateNumberOfPieces = output->GetUpdateNumberOfPieces(); + + // Only the first N pieces have anything in them. + if (updateNumberOfPieces > this->NumberOfPieces) + { + updateNumberOfPieces = this->NumberOfPieces; + } + if (updatePiece >= updateNumberOfPieces) + { // This duplicates functionality of the pipeline super classes ... + return 1; + } + startPiece = updatePiece * this->NumberOfPieces / updateNumberOfPieces; + endPiece = ((updatePiece+1) * this->NumberOfPieces / updateNumberOfPieces) - 1; + + vtkDataSetReader *reader; + vtkAppendFilter *append = vtkAppendFilter::New(); + for (idx = startPiece; idx <= endPiece; ++idx) + { + reader = vtkDataSetReader::New(); + reader->ReadAllScalarsOn(); + reader->ReadAllVectorsOn(); + reader->ReadAllNormalsOn(); + reader->ReadAllTensorsOn(); + reader->ReadAllColorScalarsOn(); + reader->ReadAllTCoordsOn(); + reader->ReadAllFieldsOn(); + reader->SetFileName(this->PieceFileNames[idx]); + reader->Update(); + if (reader->GetOutput()->GetDataObjectType() != VTK_UNSTRUCTURED_GRID) + { + vtkErrorMacro("Expecting unstructured grid."); + } + else + { + append->AddInput(reader->GetUnstructuredGridOutput()); + } + reader->Delete(); + } + + append->Update(); + output->CopyStructure(append->GetOutput()); + output->GetCellData()->PassData(append->GetOutput()->GetCellData()); + output->GetPointData()->PassData(append->GetOutput()->GetPointData()); + + append->Delete(); + + return 1; +} + + +//---------------------------------------------------------------------------- +// Structured data is trickier. Which files to load? +int vtkPDataSetReader::ImageDataExecute( + vtkInformation*, + vtkInformationVector** , + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkImageData *output = vtkImageData::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + vtkStructuredPointsReader *reader; + int uExt[6]; + int ext[6]; + int *pieceMask; + int i, j; + + // Allocate the data object. + output->GetUpdateExtent(uExt); + output->SetExtent(uExt); + output->AllocateScalars(); + + // Get the pieces that will be read. + pieceMask = new int[this->NumberOfPieces]; + for (i = 0; i < this->NumberOfPieces; ++i) + { + pieceMask[i] = 0; + } + this->CoverExtent(uExt, pieceMask); + + // Now read and append + reader = vtkStructuredPointsReader::New(); + reader->ReadAllScalarsOn(); + reader->ReadAllVectorsOn(); + reader->ReadAllNormalsOn(); + reader->ReadAllTensorsOn(); + reader->ReadAllColorScalarsOn(); + reader->ReadAllTCoordsOn(); + reader->ReadAllFieldsOn(); + for (i = 0; i < this->NumberOfPieces; ++i) + { + if (pieceMask[i]) + { + reader->SetFileName(this->PieceFileNames[i]); + reader->Update(); + // Sanity check: extent is correct. Ignore electric slide. + reader->GetOutput()->GetExtent(ext); + if (ext[1] - ext[0] != this->PieceExtents[i][1] - this->PieceExtents[i][0] || + ext[3] - ext[2] != this->PieceExtents[i][3] - this->PieceExtents[i][2] || + ext[5] - ext[4] != this->PieceExtents[i][5] - this->PieceExtents[i][4]) + { + vtkErrorMacro("Unexpected extent in VTK file: " << this->PieceFileNames[i]); + } + else + { + // Reverse the electric slide. + reader->GetOutput()->SetExtent(this->PieceExtents[i]); + // Intersect extent and output extent + reader->GetOutput()->GetExtent(ext); + for (j = 0; j < 3; ++j) + { + if (ext[j*2] < uExt[j*2]) + { + ext[j*2] = uExt[j*2]; + } + if (ext[j*2+1] > uExt[j*2+1]) + { + ext[j*2+1] = uExt[j*2+1]; + } + } + output->CopyAndCastFrom(reader->GetOutput(), ext); + vtkDataArray *scalars = reader->GetOutput()->GetPointData()->GetScalars(); + if (scalars && scalars->GetName()) + { + output->GetPointData()->GetScalars()->SetName(scalars->GetName()); + } + } + } + } + + delete [] pieceMask; + reader->Delete(); + + return 1; +} + + +//---------------------------------------------------------------------------- +// Structured data is trickier. Which files to load? +int vtkPDataSetReader::StructuredGridExecute( + vtkInformation*, + vtkInformationVector** , + vtkInformationVector* outputVector) +{ + vtkInformation* info = outputVector->GetInformationObject(0); + vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast( + info->Get(vtkDataObject::DATA_OBJECT())); + + vtkStructuredGrid *tmp; + vtkStructuredGrid **pieces; + int count = 0; + vtkStructuredGridReader *reader; + vtkPoints *newPts; + int uExt[6]; + int ext[6]; + int *pieceMask; + int i; + int pIncY, pIncZ, cIncY, cIncZ; + int ix, iy, iz; + double *pt; + vtkIdType inId, outId; + vtkIdType numPts, numCells; + + // Get the pieces that will be read. + pieceMask = new int[this->NumberOfPieces]; + for (i = 0; i < this->NumberOfPieces; ++i) + { + pieceMask[i] = 0; + } + output->GetUpdateExtent(uExt); + this->CoverExtent(uExt, pieceMask); + + // Now read the pieces. + pieces = new vtkStructuredGrid*[this->NumberOfPieces]; + reader = vtkStructuredGridReader::New(); + reader->ReadAllScalarsOn(); + reader->ReadAllVectorsOn(); + reader->ReadAllNormalsOn(); + reader->ReadAllTensorsOn(); + reader->ReadAllColorScalarsOn(); + reader->ReadAllTCoordsOn(); + reader->ReadAllFieldsOn(); + for (i = 0; i < this->NumberOfPieces; ++i) + { + if (pieceMask[i]) + { + reader->SetOutput(0); + reader->SetFileName(this->PieceFileNames[i]); + reader->Update(); + tmp = reader->GetOutput(); + if (tmp->GetNumberOfCells() > 0) + { + pieces[count] = tmp; + tmp->Register(this); + // Sanity check: extent is correct. Ignore electric slide. + tmp->GetExtent(ext); + if (ext[1] - ext[0] != + this->PieceExtents[i][1] - this->PieceExtents[i][0] || + ext[3] - ext[2] != + this->PieceExtents[i][3] - this->PieceExtents[i][2] || + ext[5] - ext[4] != + this->PieceExtents[i][5] - this->PieceExtents[i][4]) + { + vtkErrorMacro("Unexpected extent in VTK file: " << + this->PieceFileNames[i]); + } + else + { + // Reverse the electric slide. + tmp->SetExtent(this->PieceExtents[i]); + } + ++count; + } + } + } + + // Anything could happen with files. + if (count <= 0) + { + delete [] pieces; + delete [] pieceMask; + reader->Delete(); + return 1; + } + + // Allocate the points. + cIncY = uExt[1]-uExt[0]; + pIncY = cIncY+1; + cIncZ = cIncY*(uExt[3]-uExt[2]); + pIncZ = pIncY*(uExt[3]-uExt[2]+1); + numPts = pIncZ * (uExt[5]-uExt[4]+1); + numCells = cIncY * (uExt[5]-uExt[4]); + output->SetExtent(uExt); + newPts = vtkPoints::New(); + newPts->SetNumberOfPoints(numPts); + // Copy allocate gymnastics. + vtkDataSetAttributes::FieldList ptList(count); + vtkDataSetAttributes::FieldList cellList(count); + ptList.InitializeFieldList(pieces[0]->GetPointData()); + cellList.InitializeFieldList(pieces[0]->GetCellData()); + for (i = 1; i < count; ++i) + { + ptList.IntersectFieldList(pieces[i]->GetPointData()); + cellList.IntersectFieldList(pieces[i]->GetCellData()); + } + output->GetPointData()->CopyAllocate(ptList,numPts); + output->GetCellData()->CopyAllocate(cellList,numCells); + // Now append the pieces. + for (i = 0; i < count; ++i) + { + pieces[i]->GetExtent(ext); + + // Copy point data first. + inId = 0; + for (iz = ext[4]; iz <= ext[5]; ++iz) + { + for (iy = ext[2]; iy <= ext[3]; ++iy) + { + for (ix = ext[0]; ix <= ext[1]; ++ix) + { + // For clipping. I know it is bad to have this condition + // in the inner most loop, but we had to read the data ... + if (iz <= uExt[5] && iz >= uExt[4] && + iy <= uExt[3] && iy >= uExt[2] && + ix <= uExt[1] && ix >= uExt[0]) + { + outId = (ix-uExt[0]) + pIncY*(iy-uExt[2]) + pIncZ*(iz-uExt[4]); + pt = pieces[i]->GetPoint(inId); + newPts->SetPoint(outId, pt); + output->GetPointData()->CopyData(ptList, + pieces[i]->GetPointData(), i, + inId, outId); + } + ++inId; + } + } + } + // Copy cell data now. + inId = 0; + for (iz = ext[4]; iz < ext[5]; ++iz) + { + for (iy = ext[2]; iy < ext[3]; ++iy) + { + for (ix = ext[0]; ix < ext[1]; ++ix) + { + outId = (ix-uExt[0]) + cIncY*(iy-uExt[2]) + cIncZ*(iz-uExt[4]); + output->GetCellData()->CopyData(cellList, pieces[i]->GetCellData(), i, + inId, outId); + ++inId; + } + } + } + } + output->SetPoints(newPts); + newPts->Delete(); + + for (i = 0; i < count; ++i) + { + pieces[i]->Delete(); + pieces[i] = NULL; + } + delete [] pieces; + delete [] pieceMask; + + reader->Delete(); + return 1; +} + + +//---------------------------------------------------------------------------- +void vtkPDataSetReader::CoverExtent(int ext[6], int *pieceMask) +{ + int bestArea; + int area; + int best; + int cExt[6]; // Covered + int rExt[6]; // Remainder piece + int i, j; + + // Pick the piece with the largest coverage. + // Greedy search should be good enough. + best = -1; + bestArea = 0; + for (i = 0; i < this->NumberOfPieces; ++i) + { + // Compute coverage. + area = 1; + for (j = 0; j < 3; ++j) + { // Intersection of piece and extent to cover. + cExt[j*2] = ext[j*2]; + if (this->PieceExtents[i][j*2] > ext[j*2]) + { + cExt[j*2] = this->PieceExtents[i][j*2]; + } + cExt[j*2+1] = ext[j*2+1]; + if (this->PieceExtents[i][j*2+1] < ext[j*2+1]) + { + cExt[j*2+1] = this->PieceExtents[i][j*2+1]; + } + // Compute the area for cells. + if (cExt[j*2] >= cExt[j*2+1]) + { + area = 0; + } + else + { + area *= (cExt[j*2+1] - cExt[j*2]); + } + } + if (area > bestArea) + { + bestArea = area; + best = i; + } + } + + // It could happen if pieces do not have complete coverage. + if (bestArea <= 0) + { + vtkErrorMacro("Incomplete coverage."); + return; + } + + // Mark the choosen piece in the mask. + pieceMask[best] = 1; + + // Now recompute the coverage for the choosen piece. + i = best; + for (j = 0; j < 3; ++j) + { // Intersection of piece and extent to cover. + cExt[j*2] = ext[j*2]; + if (this->PieceExtents[i][j*2] > ext[j*2]) + { + cExt[j*2] = this->PieceExtents[i][j*2]; + } + cExt[j*2+1] = ext[j*2+1]; + if (this->PieceExtents[i][j*2+1] < ext[j*2+1]) + { + cExt[j*2+1] = this->PieceExtents[i][j*2+1]; + } + } + + // Compute and recursively cover remaining pieces. + for (i = 0; i < 3; ++i) + { + if (ext[i*2] < cExt[i*2]) + { + // This extends covered extent to minimum. + for (j = 0; j < 6; ++j) + { + rExt[j] = cExt[j]; + } + rExt[i*2+1] = rExt[i*2]; + rExt[i*2] = ext[i*2]; + this->CoverExtent(rExt, pieceMask); + cExt[i*2] = ext[i*2]; + } + if (ext[i*2+1] > cExt[i*2+1]) + { + // This extends covered extent to maximum. + for (j = 0; j < 6; ++j) + { + rExt[j] = cExt[j]; + } + rExt[i*2] = rExt[i*2+1]; + rExt[i*2+1] = ext[i*2+1]; + this->CoverExtent(rExt, pieceMask); + cExt[i*2+1] = ext[i*2+1]; + } + } +} + +//---------------------------------------------------------------------------- +void vtkPDataSetReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->FileName) + { + os << indent << "FileName: " << this->FileName << endl; + } + else + { + os << indent << "FileName: NULL\n"; + } + os << indent << "DataType: " << this->DataType << endl; +} + + + + + + + diff --git a/Parallel/vtkPDataSetReader.h b/Parallel/vtkPDataSetReader.h new file mode 100644 index 0000000..3248a68 --- /dev/null +++ b/Parallel/vtkPDataSetReader.h @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPDataSetReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPDataSetReader - Manages reading pieces of a data set. +// .SECTION Description +// vtkPDataSetReader will read a piece of a file, it takes as input +// a metadata file that lists all of the files in a data set. + + +#ifndef __vtkPDataSetReader_h +#define __vtkPDataSetReader_h + +#include "vtkDataSetAlgorithm.h" + +class vtkDataSet; + +class VTK_PARALLEL_EXPORT vtkPDataSetReader : public vtkDataSetAlgorithm +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkPDataSetReader,vtkDataSetAlgorithm); + static vtkPDataSetReader *New(); + + // Description: + // This file to open and read. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // This is set when UpdateInformation is called. + // It shows the type of the output. + vtkGetMacro(DataType, int); + + // Description: + // Called to determine if the file can be read by the reader. + int CanReadFile(const char* filename); + +protected: + vtkPDataSetReader(); + ~vtkPDataSetReader(); + + virtual int RequestDataObject(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + void ReadPVTKFileInformation(ifstream *fp, + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + void ReadVTKFileInformation(ifstream *fp, + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + virtual int RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + int PolyDataExecute(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + int UnstructuredGridExecute(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + int ImageDataExecute(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + int StructuredGridExecute(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + void CoverExtent(int ext[6], int *pieceMask); + + vtkDataSet *CheckOutput(); + void SetNumberOfPieces(int num); + +//BTX + ifstream *OpenFile(const char *); +//ETX + int ReadXML(ifstream *file, char **block, char **param, char **value); + void SkipFieldData(ifstream *file); + + int VTKFileFlag; + int StructuredFlag; + char *FileName; + int DataType; + int NumberOfPieces; + char **PieceFileNames; + int **PieceExtents; + +private: + vtkPDataSetReader(const vtkPDataSetReader&); // Not implemented + void operator=(const vtkPDataSetReader&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkPDataSetWriter.cxx b/Parallel/vtkPDataSetWriter.cxx new file mode 100644 index 0000000..056fd36 --- /dev/null +++ b/Parallel/vtkPDataSetWriter.cxx @@ -0,0 +1,511 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPDataSetWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkPDataSetWriter.h" +#include "vtkDataSet.h" +#include "vtkObjectFactory.h" +#include "vtkSource.h" +#include "vtkImageData.h" +#include "vtkStructuredGrid.h" +#include "vtkRectilinearGrid.h" +#include "vtkErrorCode.h" + +vtkCxxRevisionMacro(vtkPDataSetWriter, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkPDataSetWriter); + +//---------------------------------------------------------------------------- +vtkPDataSetWriter::vtkPDataSetWriter() +{ + this->StartPiece = 0; + this->EndPiece = 0; + this->NumberOfPieces = 1; + this->GhostLevel = 0; + + this->FilePattern = NULL; + this->SetFilePattern("%s.%d.vtk"); + this->UseRelativeFileNames = 1; +} + +//---------------------------------------------------------------------------- +vtkPDataSetWriter::~vtkPDataSetWriter() +{ + this->SetFilePattern(NULL); +} + + +//---------------------------------------------------------------------------- +void vtkPDataSetWriter::SetNumberOfPieces(int num) +{ + if (num == this->NumberOfPieces) + { + return; + } + + this->Modified(); + this->NumberOfPieces = num; + + // Default behavior is for the single process to stream the pieces. + this->StartPiece = 0; + this->EndPiece = num-1; +} + +//---------------------------------------------------------------------------- +int vtkPDataSetWriter::Write() +{ + int i; + int length; + char *fileRoot; + char *fileName; + + ostream *fptr; + vtkDataSet *input = this->GetInput(); + + if (this->FileName == NULL) + { + vtkErrorMacro("No file name."); + return 0; + } + + if (this->StartPiece < 0) + { + this->StartPiece = 0; + } + if (this->NumberOfPieces < 0 || this->EndPiece < this->StartPiece) + { + vtkWarningMacro("No pieces to write."); + return 1; + } + + // Only one piece? The just write one vtk file. + if (this->StartPiece == 0 && this->NumberOfPieces == 1) + { + return this->vtkDataSetWriter::Write(); + } + + // Lets compute the file root from the file name supplied by the user. + length = static_cast(strlen(this->FileName)); + fileRoot = new char [length+1]; + fileName = new char [length+strlen(this->FilePattern)+20]; + strncpy(fileRoot, this->FileName, length); + fileRoot[length] = '\0'; + // Trim off the pvtk extension. + if (strncmp(fileRoot+length-5, ".pvtk", 5) == 0) + { + fileRoot[length-5] = '\0'; + } + if (strncmp(fileRoot+length-4, ".vtk", 4) == 0) + { + fileRoot[length-4] = '\0'; + } + // If we are using relative file names, trim off the directory path. + if (this->UseRelativeFileNames) + { + char *tmp, *slash; + // Find the last / or \ in the file name. + slash = NULL; + tmp = fileRoot; + while (*tmp != '\0') + { + if (*tmp == '/' || *tmp == '\\') + { + slash = tmp; + } + ++tmp; + } + // Copy just the filename into root. + if (slash) + { + ++slash; + tmp = fileRoot; + while (*slash != '\0') + { + *tmp++ = *slash++; + } + *tmp = '\0'; + } + } + + // Lets write the toplevel file. + if (this->StartPiece == 0) + { + fptr = this->OpenFile(); + if (fptr == NULL) + { + delete [] fileRoot; + delete [] fileName; + return 0; + } + // Write a tag so that we know this file type. + *fptr << "flush(); + if (fptr->fail()) + { + vtkErrorMacro(<< "Unable to write to file: "<< this->FileName); + this->CloseVTKFile(fptr); + remove(this->FileName); + delete [] fileRoot; + delete [] fileName; + delete fptr; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + + input->UpdateInformation(); + switch (input->GetDataObjectType()) + { + case VTK_POLY_DATA: + case VTK_UNSTRUCTURED_GRID: + if (!this->WriteUnstructuredMetaData(input, fileRoot, fileName, fptr)) + { + this->CloseVTKFile(fptr); + remove(this->FileName); + delete [] fileRoot; + delete [] fileName; + delete fptr; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + break; + case VTK_IMAGE_DATA: + case VTK_STRUCTURED_POINTS: + if (!this->WriteImageMetaData((vtkImageData*)input, fileRoot, + fileName, fptr)) + { + this->CloseVTKFile(fptr); + remove(this->FileName); + delete [] fileRoot; + delete [] fileName; + delete fptr; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + break; + case VTK_RECTILINEAR_GRID: + if (!this->WriteRectilinearGridMetaData((vtkRectilinearGrid*)input, + fileRoot, fileName, fptr)) + { + this->CloseVTKFile(fptr); + remove(this->FileName); + delete [] fileRoot; + delete [] fileName; + delete fptr; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + break; + case VTK_STRUCTURED_GRID: + if (!this->WriteStructuredGridMetaData((vtkStructuredGrid*)input, + fileRoot, fileName, fptr)) + { + this->CloseVTKFile(fptr); + remove(this->FileName); + delete [] fileRoot; + delete [] fileName; + delete fptr; + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + return 0; + } + break; + } + + //fptr->close(); + delete fptr; + } + + // Restore the fileRoot to the full path. + strncpy(fileRoot, this->FileName, length); + fileRoot[length] = '\0'; + // Trim off the pvtk extension. + if (strncmp(fileRoot+length-5, ".pvtk", 5) == 0) + { + fileRoot[length-5] = '\0'; + } + if (strncmp(fileRoot+length-4, ".vtk", 4) == 0) + { + fileRoot[length-4] = '\0'; + } + + // Now write the pieces assigned to this writer. + vtkDataSetWriter *writer = vtkDataSetWriter::New(); + writer->SetFileTypeToBinary(); + vtkDataObject *copy; + for (i = this->StartPiece; i <= this->EndPiece; ++i) + { + sprintf(fileName, this->FilePattern, fileRoot, i); + writer->SetFileName(fileName); + input->SetUpdateExtent(i, this->NumberOfPieces, this->GhostLevel); + input->Update(); + copy = input->NewInstance(); + copy->ShallowCopy(input); + // I am putting this in here because shallow copy does not copy the + // UpdateExtentInitializedFlag, and I do not want to touch ShallowCopy + // in ParaViews release. + copy->SetUpdateExtent(0,1,0); + copy->SetUpdateExtent(input->GetUpdateExtent()); + copy->Crop(); + writer->SetInput(vtkDataSet::SafeDownCast(copy)); + writer->Write(); + copy->Delete(); + copy = NULL; + if (writer->GetErrorCode() == vtkErrorCode::OutOfDiskSpaceError) + { + this->DeleteFiles(); + this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); + break; + } + } + writer->Delete(); + writer = NULL; + delete [] fileName; + delete [] fileRoot; + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPDataSetWriter::WriteUnstructuredMetaData(vtkDataSet *input, + char *root, char *str, ostream *fptr) +{ + int i; + + // We should indicate the type of data that is being saved. + *fptr << " dataType=\"" << input->GetClassName() << "\"" << endl; + // This is making the assumption that all the files will be written out by + // some processes. + *fptr << " numberOfPieces=\"" << this->NumberOfPieces << "\" >" << endl; + for (i = 0; i < this->NumberOfPieces; ++i) + { + sprintf(str, this->FilePattern, root, i); + *fptr << " " << endl; + } + *fptr << "" << endl; + fptr->flush(); + if (fptr->fail()) + { + return 0; + } + return 1; +} + + +//---------------------------------------------------------------------------- +int vtkPDataSetWriter::WriteImageMetaData(vtkImageData *input, + char *root, char *str, ostream *fptr) +{ + int i; + int *pi; + double *pf; + + // We should indicate the type of data that is being saved. + *fptr << " dataType=\"" << input->GetClassName() << "\"" << endl; + // Image data has a buch of meta data. + *fptr << " scalarType=\"" << input->GetScalarType() << "\"" << endl; + pf = input->GetOrigin(); + *fptr << " origin=\"" + << pf[0] << " " << pf[1] << " " << pf[2] << "\"" << endl; + pf = input->GetSpacing(); + *fptr << " spacing=\"" + << pf[0] << " " << pf[1] << " " << pf[2] << "\"" << endl; + pi = input->GetWholeExtent(); + *fptr << " wholeExtent=\"" + << pi[0] << " " << pi[1] << " " << pi[2] << " " + << pi[3] << " " << pi[4] << " " << pi[5] << "\"" << endl; + + // This is making the assumption that all the files will be written out by + // some processes. + *fptr << " numberOfPieces=\"" << this->NumberOfPieces << "\" >" << endl; + + for (i = 0; i < this->NumberOfPieces; ++i) + { + input->SetUpdateExtent(i, this->NumberOfPieces, this->GhostLevel); + pi = input->GetUpdateExtent(); + sprintf(str, this->FilePattern, root, i); + *fptr << " " << endl; + } + *fptr << "" << endl; + fptr->flush(); + if (fptr->fail()) + { + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPDataSetWriter::WriteRectilinearGridMetaData(vtkRectilinearGrid *input, + char *root, char *str, ostream *fptr) +{ + int i; + int *pi; + + // We should indicate the type of data that is being saved. + *fptr << " dataType=\"" << input->GetClassName() << "\"" << endl; + + pi = input->GetWholeExtent(); + *fptr << " wholeExtent=\"" << pi[0] << " " << pi[1] << " " << pi[2] << " " + << pi[3] << " " << pi[4] << " " << pi[5] << "\"" << endl; + + + // This is making the assumption that all the files will be written out by + // some processes. + *fptr << " numberOfPieces=\"" << this->NumberOfPieces << "\" >" << endl; + for (i = 0; i < this->NumberOfPieces; ++i) + { + input->SetUpdateExtent(i, this->NumberOfPieces, this->GhostLevel); + pi = input->GetUpdateExtent(); + sprintf(str, this->FilePattern, root, i); + *fptr << " " << endl; + } + *fptr << "" << endl; + + fptr->flush(); + if (fptr->fail()) + { + return 0; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPDataSetWriter::WriteStructuredGridMetaData(vtkStructuredGrid *input, + char *root, char *str, ostream *fptr) +{ + int i; + int *pi; + + // We should indicate the type of data that is being saved. + *fptr << " dataType=\"" << input->GetClassName() << "\"" << endl; + + pi = input->GetWholeExtent(); + *fptr << " wholeExtent=\"" << pi[0] << " " << pi[1] << " " << pi[2] << " " + << pi[3] << " " << pi[4] << " " << pi[5] << "\"" << endl; + + + // This is making the assumption that all the files will be written out by + // some processes. + *fptr << " numberOfPieces=\"" << this->NumberOfPieces << "\" >" << endl; + for (i = 0; i < this->NumberOfPieces; ++i) + { + input->SetUpdateExtent(i, this->NumberOfPieces, this->GhostLevel); + pi = input->GetUpdateExtent(); + sprintf(str, this->FilePattern, root, i); + *fptr << " " << endl; + } + *fptr << "" << endl; + + fptr->flush(); + if (fptr->fail()) + { + return 0; + } + return 1; +} + + +//---------------------------------------------------------------------------- +// Open a vtk data file. Returns NULL if error. +ostream *vtkPDataSetWriter::OpenFile() +{ + ostream *fptr; + + fptr = new ofstream(this->FileName, ios::out); + + if (fptr->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + delete fptr; + return NULL; + } + + return fptr; +} + +void vtkPDataSetWriter::DeleteFiles() +{ + int i; + int length = static_cast(strlen(this->FileName)); + char *fileRoot = new char[length+1]; + char *fileName = new char[length+strlen(this->FilePattern)+20]; + + strncpy(fileRoot, this->FileName, length); + fileRoot[length] = '\0'; + // Trim off the pvtk extension. + if (strncmp(fileRoot+length-5, ".pvtk", 5) == 0) + { + fileRoot[length-5] = '\0'; + } + if (strncmp(fileRoot+length-4, ".vtk", 4) == 0) + { + fileRoot[length-4] = '\0'; + } + // If we are using relative file names, trim off the directory path. + if (this->UseRelativeFileNames) + { + char *tmp, *slash; + // Find the last / or \ in the file name. + slash = NULL; + tmp = fileRoot; + while (*tmp != '\0') + { + if (*tmp == '/' || *tmp == '\\') + { + slash = tmp; + } + ++tmp; + } + // Copy just the filename into root. + if (slash) + { + ++slash; + tmp = fileRoot; + while (*slash != '\0') + { + *tmp++ = *slash++; + } + *tmp = '\0'; + } + } + + for (i = this->StartPiece; i <= this->EndPiece; i++) + { + sprintf(fileName, this->FilePattern, fileRoot, i); + remove(fileName); + } + + remove(this->FileName); + + delete [] fileName; + delete [] fileRoot; +} + +//---------------------------------------------------------------------------- +void vtkPDataSetWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + + os << indent << "StartPiece: " << this->StartPiece << endl; + os << indent << "EndPiece: " << this->EndPiece << endl; + os << indent << "NumberOfPieces: " << this->NumberOfPieces << endl; + os << indent << "GhostLevel: " << this->GhostLevel << endl; + os << indent << "FilePattern: " << this->FilePattern << endl; + os << indent << "UseRelativeFileNames: " << this->UseRelativeFileNames << endl; +} diff --git a/Parallel/vtkPDataSetWriter.h b/Parallel/vtkPDataSetWriter.h new file mode 100644 index 0000000..5bbb1af --- /dev/null +++ b/Parallel/vtkPDataSetWriter.h @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPDataSetWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPDataSetWriter - Manages writing pieces of a data set. +// .SECTION Description +// vtkPDataSetWriter will write a piece of a file, and will also create +// a metadata file that lists all of the files in a data set. + + +#ifndef __vtkPDataSetWriter_h +#define __vtkPDataSetWriter_h + +#include "vtkDataSetWriter.h" + +class vtkImageData; +class vtkRectilinearGrid; +class vtkStructuredGrid; + +class VTK_PARALLEL_EXPORT vtkPDataSetWriter : public vtkDataSetWriter +{ +public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkPDataSetWriter,vtkDataSetWriter); + static vtkPDataSetWriter *New(); + + // Description: + // Write the pvtk file and cooresponding vtk files. + virtual int Write(); + + // Description: + // This is how many pieces the whole data set will be divided into. + void SetNumberOfPieces(int num); + vtkGetMacro(NumberOfPieces, int); + + // Description: + // Extra ghost cells will be written out to each piece file + // if this value is larger than 0. + vtkSetMacro(GhostLevel, int); + vtkGetMacro(GhostLevel, int); + + // Description: + // This is the range of pieces that that this writer is + // responsible for writing. All pieces must be written + // by some process. The process that writes piece 0 also + // writes the pvtk file that lists all the piece file names. + vtkSetMacro(StartPiece, int); + vtkGetMacro(StartPiece, int); + vtkSetMacro(EndPiece, int); + vtkGetMacro(EndPiece, int); + + // Description: + // This file pattern uses the file name and piece number + // to contruct a file name for the piece file. + vtkSetStringMacro(FilePattern); + vtkGetStringMacro(FilePattern); + + // Description: + // This flag determines whether to use absolute paths for the piece files. + // By default the pieces are put in the main directory, and the piece file + // names in the meta data pvtk file are relative to this directory. + // This should make moving the whole lot to another directory, an easier task. + vtkSetMacro(UseRelativeFileNames, int); + vtkGetMacro(UseRelativeFileNames, int); + vtkBooleanMacro(UseRelativeFileNames, int); + +protected: + vtkPDataSetWriter(); + ~vtkPDataSetWriter(); + +//BTX + ostream *OpenFile(); + int WriteUnstructuredMetaData(vtkDataSet *input, + char *root, char *str, ostream *fptr); + int WriteImageMetaData(vtkImageData *input, + char *root, char *str, ostream *fptr); + int WriteRectilinearGridMetaData(vtkRectilinearGrid *input, + char *root, char *str, ostream *fptr); + int WriteStructuredGridMetaData(vtkStructuredGrid *input, + char *root, char *str, ostream *fptr); +//ETX + + int StartPiece; + int EndPiece; + int NumberOfPieces; + int GhostLevel; + + int UseRelativeFileNames; + + char *FilePattern; + + void DeleteFiles(); + +private: + vtkPDataSetWriter(const vtkPDataSetWriter&); // Not implemented + void operator=(const vtkPDataSetWriter&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkPImageWriter.cxx b/Parallel/vtkPImageWriter.cxx new file mode 100644 index 0000000..77ad4e1 --- /dev/null +++ b/Parallel/vtkPImageWriter.cxx @@ -0,0 +1,196 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPImageWriter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPImageWriter.h" + +#include "vtkObjectFactory.h" +#include "vtkPipelineSize.h" +#include "vtkImageData.h" + +#define vtkPIWCloseFile \ + if (file && fileOpenedHere) \ + { \ + this->WriteFileTrailer(file,cache); \ + file->close(); \ + delete file; \ + file = NULL; \ + } \ + +vtkCxxRevisionMacro(vtkPImageWriter, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkPImageWriter); + +#ifdef write +#undef write +#endif + +#ifdef close +#undef close +#endif + + +//---------------------------------------------------------------------------- +vtkPImageWriter::vtkPImageWriter() +{ + // Set a default memory limit of a gigabyte + this->MemoryLimit = 1000000; + + this->SizeEstimator = vtkPipelineSize::New(); +} + + + +//---------------------------------------------------------------------------- +vtkPImageWriter::~vtkPImageWriter() +{ + if (this->SizeEstimator) + { + this->SizeEstimator->Delete(); + } +} + + +//---------------------------------------------------------------------------- +void vtkPImageWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "MemoryLimit: " << this->MemoryLimit << "\n"; +} + + +//---------------------------------------------------------------------------- +// Breaks region into pieces with correct dimensionality. +void vtkPImageWriter::RecursiveWrite(int axis, vtkImageData *cache, + ofstream *file) +{ + int min, max, mid; + vtkImageData *data; + int fileOpenedHere = 0; + int *ext; + unsigned long inputMemorySize; + + // if we need to open another slice, do it + if (!file && (axis + 1) == this->FileDimensionality) + { + // determine the name + if (this->FileName) + { + sprintf(this->InternalFileName,"%s",this->FileName); + } + else + { + if (this->FilePrefix) + { + sprintf(this->InternalFileName, this->FilePattern, + this->FilePrefix, this->FileNumber); + } + else + { + sprintf(this->InternalFileName, this->FilePattern,this->FileNumber); + } + } + // Open the file +#ifdef _WIN32 + file = new ofstream(this->InternalFileName, ios::out | ios::binary); +#else + file = new ofstream(this->InternalFileName, ios::out); +#endif + fileOpenedHere = 1; + if (file->fail()) + { + vtkErrorMacro("RecursiveWrite: Could not open file " << + this->InternalFileName); + delete file; + return; + } + + // Subclasses can write a header with this method call. + this->WriteFileHeader(file, cache); + ++this->FileNumber; + } + + // Propagate the update extent so we can determine pipeline size + this->GetInput()->PropagateUpdateExtent(); + + // Now we can ask how big the pipeline will be + inputMemorySize = this->SizeEstimator->GetEstimatedSize(this,0,0); + + // will the current request fit into memory + // if so the just get the data and write it out + if ( inputMemorySize < this->MemoryLimit ) + { + ext = cache->GetUpdateExtent(); + vtkDebugMacro("Getting input extent: " << ext[0] << ", " << ext[1] << ", " << ext[2] << ", " << ext[3] << ", " << ext[4] << ", " << ext[5] << endl); + cache->Update(); + data = cache; + this->RecursiveWrite(axis,cache,data,file); + vtkPIWCloseFile; + return; + } + + // if the current request did not fit into memory + // the we will split the current axis + this->GetInput()->GetAxisUpdateExtent(axis, min, max); + + vtkDebugMacro("Axes: " << axis << "(" << min << ", " << max + << "), UpdateMemory: " << inputMemorySize + << ", Limit: " << this->MemoryLimit << endl); + + if (min == max) + { + if (axis > 0) + { + this->RecursiveWrite(axis - 1,cache, file); + } + else + { + vtkWarningMacro("MemoryLimit too small for one pixel of information!!"); + } + vtkPIWCloseFile; + return; + } + + mid = (min + max) / 2; + + // if it is the y axis then flip by default + if (axis == 1 && !this->FileLowerLeft) + { + // first half + cache->SetAxisUpdateExtent(axis, mid+1, max); + this->RecursiveWrite(axis,cache,file); + + // second half + cache->SetAxisUpdateExtent(axis, min, mid); + this->RecursiveWrite(axis,cache,file); + } + else + { + // first half + cache->SetAxisUpdateExtent(axis, min, mid); + this->RecursiveWrite(axis,cache,file); + + // second half + cache->SetAxisUpdateExtent(axis, mid+1, max); + this->RecursiveWrite(axis,cache,file); + } + + // restore original extent + cache->SetAxisUpdateExtent(axis, min, max); + + // if we opened the file here, then we need to close it up + vtkPIWCloseFile; +} + + + diff --git a/Parallel/vtkPImageWriter.h b/Parallel/vtkPImageWriter.h new file mode 100644 index 0000000..c76c615 --- /dev/null +++ b/Parallel/vtkPImageWriter.h @@ -0,0 +1,61 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPImageWriter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPImageWriter - Writes images to files. +// .SECTION Description +// vtkPImageWriter writes images to files with any data type. The data type of +// the file is the same scalar type as the input. The dimensionality +// determines whether the data will be written in one or multiple files. +// This class is used as the superclass of most image writing classes +// such as vtkBMPWriter etc. It supports streaming. + +#ifndef __vtkPImageWriter_h +#define __vtkPImageWriter_h + +#include "vtkImageWriter.h" +class vtkPipelineSize; + +class VTK_PARALLEL_EXPORT vtkPImageWriter : public vtkImageWriter +{ +public: + static vtkPImageWriter *New(); + vtkTypeRevisionMacro(vtkPImageWriter,vtkImageWriter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set / Get the memory limit in kilobytes. The writer will + // stream to attempt to keep the pipeline size within this limit + vtkSetMacro(MemoryLimit, unsigned long); + vtkGetMacro(MemoryLimit, unsigned long); + +protected: + vtkPImageWriter(); + ~vtkPImageWriter(); + + unsigned long MemoryLimit; + + virtual void RecursiveWrite(int dim, vtkImageData *region, ofstream *file); + virtual void RecursiveWrite(int dim, vtkImageData *cache, + vtkImageData *data, ofstream *file) + {this->vtkImageWriter::RecursiveWrite(dim,cache,data,file);}; + + vtkPipelineSize *SizeEstimator; +private: + vtkPImageWriter(const vtkPImageWriter&); // Not implemented. + void operator=(const vtkPImageWriter&); // Not implemented. +}; + +#endif + + diff --git a/Parallel/vtkPKdTree.cxx b/Parallel/vtkPKdTree.cxx new file mode 100644 index 0000000..977927c --- /dev/null +++ b/Parallel/vtkPKdTree.cxx @@ -0,0 +1,3649 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPKdTree.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkPKdTree.h" +#include "vtkKdNode.h" +#include "vtkDataSet.h" +#include "vtkCellCenters.h" +#include "vtkPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkObjectFactory.h" +#include "vtkMultiProcessController.h" +#include "vtkSocketController.h" +#include "vtkTimerLog.h" +#include "vtkCellData.h" +#include "vtkPointData.h" +#include "vtkIntArray.h" +#include "vtkIdList.h" +#include "vtkSubGroup.h" +#include +#include + +// Timing data --------------------------------------------- + +#if 0 +#define MSGSIZE 60 + +static char dots[MSGSIZE] = "..........................................................."; +static char msg[MSGSIZE]; + +static char * makeEntry(const char *s) +{ + memcpy(msg, dots, MSGSIZE); + int len = strlen(s); + len = (len >= MSGSIZE) ? MSGSIZE-1 : len; + + memcpy(msg, s, len); + + return msg; +} + +#define TIMER(s) \ + if (this->GetTiming()) \ + { \ + char *s2 = makeEntry(s); \ + if (this->TimerLog == NULL) \ + { \ + this->TimerLog = vtkTimerLog::New(); \ + } \ + this->TimerLog->MarkStartEvent(s2); \ + } + +#define TIMERDONE(s) \ + if (this->GetTiming())\ + { char *s2 = makeEntry(s); this->TimerLog->MarkEndEvent(s2); } + +#else +#define TIMER(s) +#define TIMERDONE(s) +#endif + +// Timing data --------------------------------------------- + +vtkCxxRevisionMacro(vtkPKdTree, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkPKdTree); + +const int vtkPKdTree::NoRegionAssignment = 0; // default +const int vtkPKdTree::ContiguousAssignment = 1; // default if RegionAssignmentOn +const int vtkPKdTree::UserDefinedAssignment = 2; +const int vtkPKdTree::RoundRobinAssignment = 3; + +#define FreeList(list) if (list) {delete [] list; list = NULL;} +#define FreeItem(item) if (item) {delete item; item = NULL;} +#define FreeObject(item) if (item) {item->Delete(); item = NULL;} + +static char errstr[256]; + +#define VTKERROR(s) \ +{ \ + sprintf(errstr,"(process %d) %s",this->MyId,s); \ + vtkErrorMacro(<< errstr); \ +} +#define VTKWARNING(s) \ +{ \ + sprintf(errstr,"(process %d) %s",this->MyId,s); \ + vtkWarningMacro(<< errstr); \ +} + +vtkPKdTree::vtkPKdTree() +{ + this->RegionAssignment = NoRegionAssignment; + + this->Controller = NULL; + this->SubGroup = NULL; + + this->NumProcesses = 1; + this->MyId = 0; + + this->InitializeRegionAssignmentLists(); + this->InitializeProcessDataLists(); + this->InitializeFieldArrayMinMax(); + this->InitializeGlobalIndexLists(); + + this->TotalNumCells = 0; + + this->PtArray = NULL; + this->PtArray2 = NULL; + this->CurrentPtArray = NULL; + this->NextPtArray = NULL; + + this->SelectBuffer = NULL; +} +vtkPKdTree::~vtkPKdTree() +{ + this->SetController(NULL); + this->FreeSelectBuffer(); + this->FreeDoubleBuffer(); + + this->FreeGlobalIndexLists(); + this->FreeRegionAssignmentLists(); + this->FreeProcessDataLists(); + this->FreeFieldArrayMinMax(); +} +void vtkPKdTree::SetController(vtkMultiProcessController *c) +{ + if (this->Controller == c) + { + return; + } + + if ((c == NULL) || (c->GetNumberOfProcesses() == 0)) + { + this->NumProcesses = 1; + this->MyId = 0; + } + + this->Modified(); + + if (this->Controller != NULL) + { + this->Controller->UnRegister(this); + this->Controller = NULL; + } + + if (c == NULL) + { + return; + } + + vtkSocketController *sc = vtkSocketController::SafeDownCast(c); + + if (sc) + { + vtkErrorMacro(<< + "vtkPKdTree communication will fail with a socket controller"); + + return; + } + + this->NumProcesses = c->GetNumberOfProcesses(); + + this->Controller = c; + this->MyId = c->GetLocalProcessId(); + c->Register(this); +} +//-------------------------------------------------------------------- +// Parallel k-d tree build, Floyd and Rivest (1975) select algorithm +// for median finding. +//-------------------------------------------------------------------- + +int vtkPKdTree::AllCheckForFailure(int rc, const char *where, const char *how) +{ + int vote; + char errmsg[256]; + + if (this->NumProcesses > 1){ + this->SubGroup->ReduceSum(&rc, &vote, 1, 0); + this->SubGroup->Broadcast(&vote, 1, 0); + } + else{ + vote = rc; + } + + if (vote) + { + if (rc) + { + sprintf(errmsg,"%s on my node (%s)",how, where); + } + else + { + sprintf(errmsg,"%s on a remote node (%s)",how, where); + } + VTKWARNING(errmsg); + + return 1; + } + return 0; +} + +void vtkPKdTree::AllCheckParameters() +{ + int param[10]; + int param0[10]; + + // All the parameters that determine how k-d tree is built and + // what tables get created afterward - there's no point in + // trying to build unless these match on all processes. + + param[0] = this->ValidDirections; + param[1] = this->GetMinCells(); + param[2] = this->GetNumberOfRegionsOrLess(); + param[3] = this->GetNumberOfRegionsOrMore(); + param[4] = this->RegionAssignment; + param[5] = 0; + param[6] = 0; + param[7] = 0; + param[8] = 0; + param[9] = 0; + + if (this->MyId == 0) + { + this->SubGroup->Broadcast(param, 10, 0); + return; + } + + this->SubGroup->Broadcast(param0, 10, 0); + + int diff = 0; + + for (int i=0; i < 10; i++) + { + if (param0[i] != param[i]) + { + diff = 1; + break; + } + } + if (diff) + { + VTKWARNING("Changing my runtime parameters to match process 0"); + + this->ValidDirections = param0[0]; + this->SetMinCells(param0[1]); + this->SetNumberOfRegionsOrLess(param0[2]); + this->SetNumberOfRegionsOrMore(param0[3]); + this->RegionAssignment = param0[4]; + } + return; +} + +#define BoundsToMinMax(bounds,min,max) \ +{ \ + min[0] = bounds[0]; min[1] = bounds[2]; min[2] = bounds[4]; \ + max[0] = bounds[1]; max[1] = bounds[3]; max[2] = bounds[5]; \ +} +#define MinMaxToBounds(bounds,min,max) \ +{ \ + bounds[0] = min[0]; bounds[2] = min[1]; bounds[4] = min[2]; \ + bounds[1] = max[0]; bounds[3] = max[1]; bounds[5] = max[2]; \ +} +#define BoundsToMinMaxUpdate(bounds,min,max) \ +{ \ + min[0] = (bounds[0] < min[0] ? bounds[0] : min[0]); \ + min[1] = (bounds[2] < min[1] ? bounds[2] : min[1]); \ + min[2] = (bounds[4] < min[2] ? bounds[4] : min[2]); \ + max[0] = (bounds[1] > max[0] ? bounds[1] : max[0]); \ + max[1] = (bounds[3] > max[1] ? bounds[3] : max[1]); \ + max[2] = (bounds[5] > max[2] ? bounds[5] : max[2]); \ +} + +double *vtkPKdTree::VolumeBounds() +{ + int i; + + // Get the spatial bounds of the whole volume + + double *volBounds = new double [6]; + double localMin[3], localMax[3], globalMin[3], globalMax[3]; + + for (i=0; iGetNumberOfDataSets(); i++) + { + this->GetDataSet(i)->GetBounds(volBounds); + + if (i==0) + { + BoundsToMinMax(volBounds, localMin, localMax); + } + else + { + BoundsToMinMaxUpdate(volBounds, localMin, localMax); + } + } + + this->SubGroup->ReduceMin(localMin, globalMin, 3, 0); + this->SubGroup->Broadcast(globalMin, 3, 0); + + this->SubGroup->ReduceMax(localMax, globalMax, 3, 0); + this->SubGroup->Broadcast(globalMax, 3, 0); + + MinMaxToBounds(volBounds, globalMin, globalMax); + + // push out a little if flat + + double diff[3], aLittle = 0.0; + + for (i=0; i<3; i++) + { + diff[i] = volBounds[2*i+1] - volBounds[2*i]; + aLittle = (diff[i] > aLittle) ? diff[i] : aLittle; + } + if ((aLittle /= 100.0) <= 0.0) + { + VTKERROR("VolumeBounds - degenerate volume"); + return NULL; + } + + this->SetFudgeFactor(aLittle * 10e-4); + + for (i=0; i<3; i++) + { + if (diff[i] <= 0) + { + volBounds[2*i] -= aLittle; + volBounds[2*i+1] += aLittle; + } + else // need lower bound to be strictly less than any point in decomposition + { + volBounds[2*i] -= this->GetFudgeFactor(); + } + } + return volBounds; +} + +// BuildLocator must be called by all processes in the parallel application + +void vtkPKdTree::BuildLocator() +{ + int fail = 0; + int rebuildLocator = 0; + + if ((this->Top == NULL) || + (this->BuildTime < this->GetMTime()) || + this->NewGeometry()) + { + // We don't have a k-d tree, or parameters that affect the + // build of the tree have changed, or input geometry has changed. + + rebuildLocator = 1; + } + + if (this->NumProcesses == 1) + { + if (rebuildLocator) + { + this->SingleProcessBuildLocator(); + } + return; + } + + TIMER("Determine if we need to rebuild"); + + this->SubGroup = vtkSubGroup::New(); + this->SubGroup->Initialize(0, this->NumProcesses-1, + this->MyId, 0x00001000, this->Controller->GetCommunicator()); + + int vote; + this->SubGroup->ReduceSum(&rebuildLocator, &vote, 1, 0); + this->SubGroup->Broadcast(&vote, 1, 0); + + rebuildLocator = (vote > 0); + + TIMERDONE("Determine if we need to rebuild"); + + if (rebuildLocator) + { + TIMER("Build k-d tree"); + + this->FreeSearchStructure(); + this->ReleaseTables(); + + // Make sure input is up to date. + for (int i = 0; i < this->GetNumberOfDataSets(); i++) + { + this->GetDataSet(i)->Update(); + } + + this->AllCheckParameters(); // global operation to ensure same parameters + + double *volBounds = this->VolumeBounds(); // global operation to get bounds + + if (volBounds == NULL) + { + goto doneError; + } + + if (this->UserDefinedCuts) + { + fail = this->ProcessUserDefinedCuts(volBounds); + } + else + { + fail = this->MultiProcessBuildLocator(volBounds); + } + + FreeList(volBounds); + + if (fail) goto doneError; + + this->SetActualLevel(); + this->BuildRegionList(); + + TIMERDONE("Build k-d tree"); + } + + // Even if locator is not rebuilt, we should update + // region assignments since they may have changed. + + this->UpdateRegionAssignment(); + + goto done; + +doneError: + + this->FreeRegionAssignmentLists(); + this->FreeSearchStructure(); + +done: + + FreeObject(this->SubGroup); + + this->UpdateBuildTime(); + + this->SetCalculator(this->Top); + + return; +} +int vtkPKdTree::MultiProcessBuildLocator(double *volBounds) +{ + int retVal = 0; + + vtkDebugMacro( << "Creating Kdtree in parallel" ); + + if (this->GetTiming()) + { + if (this->TimerLog == NULL) this->TimerLog = vtkTimerLog::New(); + } + + // Locally, create a single list of the coordinates of the centers of the + // cells of my data sets + + TIMER("Compute cell centers"); + + this->PtArray = NULL; + + this->PtArray = this->ComputeCellCenters(); + int totalPts = this->GetNumberOfCells(); // total on local node + this->CurrentPtArray = this->PtArray; + + int fail = (this->PtArray == NULL); + + if (this->AllCheckForFailure(fail, + "MultiProcessBuildLocator", "memory allocation")) + { + goto doneError6; + } + + TIMERDONE("Compute cell centers"); + + // Get total number of cells across all processes, assign global indices + // for select operation + + TIMER("Build index lists"); + + fail = this->BuildGlobalIndexLists(totalPts); + + TIMERDONE("Build index lists"); + + if (fail) + { + goto doneError6; + } + + // In parallel, build the k-d tree structure, partitioning all + // the points into spatial regions. Sub-groups of processors + // will form vtkSubGroups to divide sub-regions of space. + + FreeObject(this->SubGroup); + + TIMER("Compute tree"); + + fail = this->BreadthFirstDivide(volBounds); + + TIMERDONE("Compute tree"); + + this->SubGroup = vtkSubGroup::New(); + this->SubGroup->Initialize(0, this->NumProcesses-1, + this->MyId, 0x00002000, this->Controller->GetCommunicator()); + + if (this->AllCheckForFailure(fail, "BreadthFirstDivide", "memory allocation")) + { + goto doneError6; + } + + FreeObject(this->SubGroup); + + // I only have a partial tree at this point, the regions in which + // I participated. Now collect the entire tree. + + this->SubGroup = vtkSubGroup::New(); + this->SubGroup->Initialize(0, this->NumProcesses-1, + this->MyId, 0x00003000, this->Controller->GetCommunicator()); + + TIMER("Complete tree"); + + fail = this->CompleteTree(); + + TIMERDONE("Complete tree"); + + if (fail) + { + goto doneError6; + } + + goto done6; + +doneError6: + + this->FreeSearchStructure(); + retVal = 1; + +done6: + // no longer valid, we overwrote them during k-d tree parallel build + delete [] this->PtArray; + this->CurrentPtArray = this->PtArray = NULL; + + FreeObject(this->SubGroup); + + this->FreeGlobalIndexLists(); + + return retVal; +} + +void vtkPKdTree::SingleProcessBuildLocator() +{ + vtkKdTree::BuildLocator(); + + this->TotalNumCells = this->GetNumberOfCells(); + + if (this->RegionAssignment != vtkPKdTree::NoRegionAssignment) + { + this->UpdateRegionAssignment(); + } + + return; +} +typedef struct _vtkNodeInfo{ + vtkKdNode *kd; + int L; + int level; + int tag; +} *vtkNodeInfo; + +#define ENQUEUE(a, b, c, d) \ +{ \ + vtkNodeInfo rec = new struct _vtkNodeInfo; \ + rec->kd = a; \ + rec->L = b; \ + rec->level = c; \ + rec->tag = d; \ + Queue.push(rec); \ +} + +int vtkPKdTree::BreadthFirstDivide(double *volBounds) +{ + int returnVal = 0; + + vtkstd::queue Queue; + + if (this->AllocateDoubleBuffer()) + { + VTKERROR("memory allocation for double buffering"); + return 1; + } + + if (this->AllocateSelectBuffer()) + { + this->FreeDoubleBuffer(); + + VTKERROR("memory allocation for select buffers"); + return 1; + } + + vtkKdNode *kd = this->Top = vtkKdNode::New(); + + kd->SetBounds(volBounds[0], volBounds[1], + volBounds[2], volBounds[3], + volBounds[4], volBounds[5]); + + kd->SetNumberOfPoints(this->TotalNumCells); + + kd->SetDataBounds(volBounds[0], volBounds[1], + volBounds[2], volBounds[3], + volBounds[4], volBounds[5]); + + int midpt = this->DivideRegion(kd, 0, 0, 0x00000001); + + if (midpt > 0) + { + ENQUEUE(kd->GetLeft(), 0, 1, 0x00000002); + ENQUEUE(kd->GetRight(), midpt, 1, 0x00000003); + } + else if (midpt < 0) + { + this->FreeSelectBuffer(); + this->FreeDoubleBuffer(); + + return 1; + } + + while (!Queue.empty()) + { + vtkNodeInfo info = Queue.front(); + Queue.pop(); + + kd = info->kd; + int L = info->L; + int level = info->level; + int tag = info->tag; + + midpt = this->DivideRegion(kd, L, level, tag); + + if (midpt > 0) + { + ENQUEUE(kd->GetLeft(), L, level+1, tag << 1); + + ENQUEUE(kd->GetRight(), midpt, level+1, (tag << 1) | 1); + } + else if (midpt < 0) + { + returnVal = 1; // have to keep going, or remote ops may hang + } + delete info; + } + + this->FreeSelectBuffer(); + + if (this->CurrentPtArray == this->PtArray2) + { + memcpy(this->PtArray, this->PtArray2, this->PtArraySize * sizeof(float)); + } + + this->FreeDoubleBuffer(); + + return returnVal; +} +int vtkPKdTree::DivideRegion(vtkKdNode *kd, int L, int level, int tag) +{ + if (!this->DivideTest(kd->GetNumberOfPoints(), level)) return 0; + + int R = L + kd->GetNumberOfPoints() - 1; + + int p1 = this->WhoHas(L); + int p2 = this->WhoHas(R); + + if ((this->MyId < p1) || (this->MyId > p2)) return 0; + + this->SubGroup = vtkSubGroup::New(); + this->SubGroup->Initialize(p1, p2, this->MyId, tag, + this->Controller->GetCommunicator()); + + int maxdim = this->SelectCutDirection(kd); + + kd->SetDim(maxdim); + + int midpt = this->Select(maxdim, L, R); + + if (midpt < L + 1) + { + // couldn't divide along maxdim - all points we're at same location + // should probably try a different direction + + kd->SetDim(3); // indicates region is not divided + FreeObject(this->SubGroup); + return 0; + } + + float *newDataBounds = this->DataBounds(L, midpt, R); + vtkKdNode *left = vtkKdNode::New(); + vtkKdNode *right = vtkKdNode::New(); + + int fail = ( (newDataBounds == NULL) || (left == NULL) || (right == NULL) ); + + if (this->AllCheckForFailure(fail, "Divide Region", "memory allocation")) + { + FreeList(newDataBounds); + left->Delete(); + right->Delete(); + FreeObject(this->SubGroup); + return -1; + } + + double coord = (newDataBounds[maxdim*2 + 1] + // max on left side + newDataBounds[6 + maxdim*2] )* // min on right side + 0.5; + + kd->AddChildNodes(left, right); + + double bounds[6]; + kd->GetBounds(bounds); + + left->SetBounds( + bounds[0], ((maxdim == XDIM) ? coord : bounds[1]), + bounds[2], ((maxdim == YDIM) ? coord : bounds[3]), + bounds[4], ((maxdim == ZDIM) ? coord : bounds[5])); + + left->SetNumberOfPoints(midpt - L); + + right->SetBounds( + ((maxdim == XDIM) ? coord : bounds[0]), bounds[1], + ((maxdim == YDIM) ? coord : bounds[2]), bounds[3], + ((maxdim == ZDIM) ? coord : bounds[4]), bounds[5]); + + right->SetNumberOfPoints(R - midpt + 1); + + left->SetDataBounds(newDataBounds[0], newDataBounds[1], + newDataBounds[2], newDataBounds[3], + newDataBounds[4], newDataBounds[5]); + + right->SetDataBounds(newDataBounds[6], newDataBounds[7], + newDataBounds[8], newDataBounds[9], + newDataBounds[10], newDataBounds[11]); + + delete [] newDataBounds; + + FreeObject(this->SubGroup); + + return midpt; +} + +void vtkPKdTree::ExchangeVals(int pos1, int pos2) +{ + vtkCommunicator *comm = this->Controller->GetCommunicator(); + + float *myval; + float otherval[3]; + + int player1 = this->WhoHas(pos1); + int player2 = this->WhoHas(pos2); + + if ((player1 == this->MyId) && (player2 == this->MyId)) + { + this->ExchangeLocalVals(pos1, pos2); + } + + else if (player1 == this->MyId) + { + myval = this->GetLocalVal(pos1); + + comm->Send(myval, 3, player2, this->SubGroup->tag); + + comm->Receive(otherval, 3, player2, this->SubGroup->tag); + + this->SetLocalVal(pos1, otherval); + } + else if (player2 == this->MyId) + { + myval = this->GetLocalVal(pos2); + + comm->Receive(otherval, 3, player1, this->SubGroup->tag); + + comm->Send(myval, 3, player1, this->SubGroup->tag); + + this->SetLocalVal(pos2, otherval); + } + return; +} + +// Given an array X with element indices ranging from L to R, and +// a K such that L <= K <= R, rearrange the elements such that +// X[K] contains the ith sorted element, where i = K - L + 1, and +// all the elements X[j], j < k satisfy X[j] <= X[K], and all the +// elements X[j], j > k satisfy X[j] >= X[K]. + +#define sign(x) ((x<0) ? (-1) : (1)) +#ifndef max +#define max(x,y) ((x>y) ? (x) : (y)) +#endif +#ifndef min +#define min(x,y) ((x L) + { + if ( R - L > 600) + { + // "Recurse on a sample of size S to get an estimate for the + // (K-L+1)-th smallest element into X[K], biased slightly so + // that the (K-L+1)-th element is expected to lie in the + // smaller set after partitioning" + + N = R - L + 1; + I = K - L + 1; + Z = static_cast(log(float(N))); + S = static_cast(.5 * exp(2*Z/3)); + SD = static_cast(.5 * sqrt(Z*S*((float)(N-S)/N)) * sign(I - N/2)); + LL = max(L, K - static_cast((I*((float)S/N))) + SD); + RR = min(R, K + static_cast((N-I) * ((float)S/N)) + SD); + this->_select(LL, RR, K, dim); + } + + int p1 = this->WhoHas(L); + int p2 = this->WhoHas(R); + + // "now adjust L,R so they surround the subset containing + // the (K-L+1)-th smallest element" + + // Due to very severe worst case behavior when the + // value at K (call it "T") is repeated many times in the array, we + // rearrange the array into three intervals: the leftmost being values + // less than T, the center being values equal to T, and the rightmost + // being values greater than T. Two integers are returned. This first + // is the global index of the start of the second interval. The second + // is the global index of the start of the third interval. (If there + // are no values greater than "T", the second integer will be R+1.) + // + // The original Floyd&Rivest arranged the array into two intervals, + // one less than "T", one greater than (or equal to) "T". + + int *idx = this->PartitionSubArray(L, R, K, dim, p1, p2); + + I = idx[0]; + J = idx[1]; + + if (K >= J) + { + L = J; + } + else if (K >= I) + { + L = R; // partitioning is done, K is in the interval of T's + } + else + { + R = I-1; + } + } +} +int vtkPKdTree::Select(int dim, int L, int R) +{ + int K = ((R + L) / 2) + 1; + + this->_select(L, R, K, dim); + + if (K == L) return K; + + // The global array is now re-ordered, partitioned around X[K]. + // (In particular, for all i, i K, X[i] >= X[K].) + // However the value at X[K] may occur more than once, and by + // construction of the reordered array, there is a J <= K such that + // for all i < J, X[i] < X[K] and for all J <= i < K X[i] = X[K]. + // + // We want to roll K back to this value J, so that all points are + // unambiguously assigned to one region or the other. + + int hasK = this->WhoHas(K); + int hasKrank = this->SubGroup->getLocalRank(hasK); + + int hasKleft = this->WhoHas(K-1); + int hasKleftrank = this->SubGroup->getLocalRank(hasKleft); + + float Kval; + float Kleftval; + float *pt; + + if (hasK == this->MyId) + { + pt = this->GetLocalVal(K) + dim; + Kval = *pt; + } + + this->SubGroup->Broadcast(&Kval, 1, hasKrank); + + if (hasKleft == this->MyId) + { + pt = this->GetLocalVal(K-1) + dim; + Kleftval = *pt; + } + + this->SubGroup->Broadcast(&Kleftval, 1, hasKleftrank); + + if (Kleftval != Kval) return K; + + int firstKval = this->TotalNumCells; // greater than any valid index + + if (this->MyId <= hasKleft) + { + int start = this->EndVal[this->MyId]; + if (start > K-1) start = K-1; + + pt = this->GetLocalVal(start) + dim; + + if (*pt == Kval) + { + firstKval = start; + + int finish = this->StartVal[this->MyId]; + + for (int idx=start-1; idx >= finish; idx--) + { + pt -= 3; + if (*pt < Kval) break; + + firstKval--; + } + } + } + + int newK; + + this->SubGroup->ReduceMin(&firstKval, &newK, 1, hasKrank); + this->SubGroup->Broadcast(&newK, 1, hasKrank); + + return newK; +} + +int vtkPKdTree::_whoHas(int L, int R, int pos) +{ + if (L == R) return L; + + int M = (L + R) >> 1; + + if ( pos < this->StartVal[M]) + { + return _whoHas(L, M-1, pos); + } + else if (pos < this->StartVal[M+1]) + { + return M; + } + else + { + return _whoHas(M+1, R, pos); + } +} +int vtkPKdTree::WhoHas(int pos) +{ + if ( (pos < 0) || (pos >= this->TotalNumCells)) + { + return -1; + } + return _whoHas(0, this->NumProcesses-1, pos); +} +float *vtkPKdTree::GetLocalVal(int pos) +{ + if ( (pos < this->StartVal[this->MyId]) || (pos > this->EndVal[this->MyId])) + { + return NULL; + } + int localPos = pos - this->StartVal[this->MyId]; + + return this->CurrentPtArray + (3*localPos); +} +float *vtkPKdTree::GetLocalValNext(int pos) +{ + if ( (pos < this->StartVal[this->MyId]) || (pos > this->EndVal[this->MyId])) + { + return NULL; + } + int localPos = pos - this->StartVal[this->MyId]; + + return this->NextPtArray + (3*localPos); +} +void vtkPKdTree::SetLocalVal(int pos, float *val) +{ + if ( (pos < this->StartVal[this->MyId]) || (pos > this->EndVal[this->MyId])) + { + VTKERROR("SetLocalVal - bad index"); + return; + } + + int localOffset = (pos - this->StartVal[this->MyId]) * 3; + + this->CurrentPtArray[localOffset] = val[0]; + this->CurrentPtArray[localOffset+1] = val[1]; + this->CurrentPtArray[localOffset+2] = val[2]; + + return; +} +void vtkPKdTree::ExchangeLocalVals(int pos1, int pos2) +{ + float temp[3]; + + float *pt1 = this->GetLocalVal(pos1); + float *pt2 = this->GetLocalVal(pos2); + + if (!pt1 || !pt2) + { + VTKERROR("ExchangeLocalVal - bad index"); + return; + } + + temp[0] = pt1[0]; + temp[1] = pt1[1]; + temp[2] = pt1[2]; + + pt1[0] = pt2[0]; + pt1[1] = pt2[1]; + pt1[2] = pt2[2]; + + pt2[0] = temp[0]; + pt2[1] = temp[1]; + pt2[2] = temp[2]; + + return; +} + +void vtkPKdTree::DoTransfer(int from, int to, int fromIndex, int toIndex, int count) +{ +float *fromPt, *toPt; + + vtkCommunicator *comm = this->Controller->GetCommunicator(); + + int nitems = count * 3; + + int me = this->MyId; + + int tag = this->SubGroup->tag; + + if ( (from==me) && (to==me)) + { + fromPt = this->GetLocalVal(fromIndex); + toPt = this->GetLocalValNext(toIndex); + + memcpy(toPt, fromPt, nitems * sizeof(float)); + } + else if (from == me) + { + fromPt = this->GetLocalVal(fromIndex); + + comm->Send(fromPt, nitems, to, tag); + } + else if (to == me) + { + toPt = this->GetLocalValNext(toIndex); + + comm->Receive(toPt, nitems, from, tag); + } +} + +// Partition global array into three intervals, the first all values < T, +// the second all values = T, the third all values > T. Return two +// global indices: The index to the begining of the second interval, and +// the index to the beginning of the third interval. "T" is the value +// at array index K. +// +// If there is no third interval, the second index returned will be R+1. + +int *vtkPKdTree::PartitionSubArray(int L, int R, int K, int dim, int p1, int p2) +{ + int rootrank = this->SubGroup->getLocalRank(p1); + + int me = this->MyId; + + if ( (me < p1) || (me > p2)) + { + this->SubGroup->Broadcast(this->SelectBuffer, 2, rootrank); + return this->SelectBuffer; + } + + if (p1 == p2) + { + int *idx = this->PartitionAboutMyValue(L, R, K, dim); + + this->SubGroup->Broadcast(idx, 2, rootrank); + + return idx; + } + + // Each process will rearrange their subarray myL-myR into a left region + // of values less than X[K], a center region of values equal to X[K], and + // a right region of values greater than X[K]. "I" will be the index + // of the first value in the center region, or it will equal "J" if there + // is no center region. "J" will be the index to the start of the + // right region, or it will be R+1 if there is no right region. + + int tag = this->SubGroup->tag; + + vtkSubGroup *sg = vtkSubGroup::New(); + sg->Initialize(p1, p2, me, tag, this->Controller->GetCommunicator()); + + int hasK = this->WhoHas(K); + + int Krank = sg->getLocalRank(hasK); + + int myL = this->StartVal[me]; + int myR = this->EndVal[me]; + + if (myL < L) myL = L; + if (myR > R) myR = R; + + // Get Kth element + + float T; + + if (hasK == me) + { + T = this->GetLocalVal(K)[dim]; + } + + sg->Broadcast(&T, 1, Krank); + + int *idx; // dividing points in rearranged sub array + + if (hasK == me) + { + idx = this->PartitionAboutMyValue(myL, myR, K, dim); + } + else + { + idx = this->PartitionAboutOtherValue(myL, myR, T, dim); + } + + // Copy these right away. Implementation uses SelectBuffer + // which is about to be overwritten. + + int I = idx[0]; + int J = idx[1]; + + // Now the ugly part. The processes redistribute the array so that + // globally the interval [L:R] is partitioned into an interval of values + // less than T, and interval of values equal to T, and an interval of + // values greater than T. + + int nprocs = p2 - p1 + 1; + + int *buf = this->SelectBuffer; + + int *left = buf; buf += nprocs; // global index of my leftmost + int *right = buf; buf += nprocs; // global index of my rightmost + int *Ival = buf; buf += nprocs; // global index of my first val = T + int *Jval = buf; buf += nprocs; // global index of my first val > T + + int *leftArray = buf; buf += nprocs; // number of my vals < T + int *leftUsed = buf; buf += nprocs; // how many scheduled to be sent so far + + int *centerArray = buf; buf += nprocs; // number of my vals = T + int *centerUsed = buf; buf += nprocs; // how many scheduled to be sent so far + + int *rightArray = buf; buf += nprocs; // number of my vals > T + int *rightUsed = buf; buf += nprocs; // how many scheduled to be sent so far + + rootrank = sg->getLocalRank(p1); + + sg->Gather(&myL, left, 1, rootrank); + sg->Broadcast(left, nprocs, rootrank); + + sg->Gather(&myR, right, 1, rootrank); + sg->Broadcast(right, nprocs, rootrank); + + sg->Gather(&I, Ival, 1, rootrank); + sg->Broadcast(Ival, nprocs, rootrank); + + sg->Gather(&J, Jval, 1, rootrank); + sg->Broadcast(Jval, nprocs, rootrank); + + sg->Delete(); + + int leftRemaining = 0; + int centerRemaining = 0; + + int p, sndr, recvr; + + for (p = 0; p < nprocs; p++) + { + leftArray[p] = Ival[p] - left[p]; + centerArray[p] = Jval[p] - Ival[p]; + rightArray[p] = right[p] - Jval[p] + 1; + + leftRemaining += leftArray[p]; + centerRemaining += centerArray[p]; + + leftUsed[p] = 0; + centerUsed[p] = 0; + rightUsed[p] = 0; + } + + int FirstCenter = left[0] + leftRemaining; + int FirstRight = FirstCenter + centerRemaining; + + int nextLeftProc = 0; + int nextCenterProc = 0; + int nextRightProc = 0; + + int need, have, take; + + if ( (myL > this->StartVal[me]) || (myR < this->EndVal[me])) + { + memcpy(this->NextPtArray, this->CurrentPtArray, this->PtArraySize * sizeof(float)); + } + + for (recvr = 0; recvr < nprocs; recvr++) + { + need = leftArray[recvr] + centerArray[recvr] + rightArray[recvr]; + have = 0; + + if (leftRemaining >= 0) + { + for (sndr = nextLeftProc; sndr < nprocs; sndr++) + { + take = leftArray[sndr] - leftUsed[sndr]; + + if (take == 0) continue; + + take = (take > need) ? need : take; + + this->DoTransfer(sndr + p1, recvr + p1, + left[sndr] + leftUsed[sndr], left[recvr] + have, take); + + have += take; + need -= take; + leftRemaining -= take; + + leftUsed[sndr] += take; + + if (need == 0) break; + } + + if (leftUsed[sndr] == leftArray[sndr]) + { + nextLeftProc = sndr+1; + } + else + { + nextLeftProc = sndr; + } + } + + if (need == 0) continue; + + if (centerRemaining >= 0) + { + for (sndr = nextCenterProc; sndr < nprocs; sndr++) + { + take = centerArray[sndr] - centerUsed[sndr]; + + if (take == 0) continue; + + take = (take > need) ? need : take; + + // Just copy the values, since we know what they are + this->DoTransfer(sndr + p1, recvr + p1, + left[sndr] + leftArray[sndr] + centerUsed[sndr], + left[recvr] + have, take); + + have += take; + need -= take; + centerRemaining -= take; + + centerUsed[sndr] += take; + + if (need == 0) break; + } + + if (centerUsed[sndr] == centerArray[sndr]) + { + nextCenterProc = sndr+1; + } + else + { + nextCenterProc = sndr; + } + } + + if (need == 0) continue; + + for (sndr = nextRightProc; sndr < nprocs; sndr++) + { + take = rightArray[sndr] - rightUsed[sndr]; + + if (take == 0) continue; + + take = (take > need) ? need : take; + + this->DoTransfer(sndr + p1, recvr + p1, + left[sndr] + leftArray[sndr] + centerArray[sndr] + rightUsed[sndr], + left[recvr] + have, take); + + have += take; + need -= take; + + rightUsed[sndr] += take; + + if (need == 0) break; + } + + if (rightUsed[sndr] == rightArray[sndr]) + { + nextRightProc = sndr+1; + } + else + { + nextRightProc = sndr; + } + } + + this->SwitchDoubleBuffer(); + + this->SelectBuffer[0] = FirstCenter; + this->SelectBuffer[1] = FirstRight; + + rootrank = this->SubGroup->getLocalRank(p1); + + this->SubGroup->Broadcast(this->SelectBuffer, 2, rootrank); + + return this->SelectBuffer; +} + +// This routine partitions the array from element L through element +// R into three segments. This first contains values less than T, the +// next contains values equal to T, the last has values greater than T. +// +// This routine returns two values. The first is the index of the +// first value equal to T, the second is the index of the first value +// greater than T. If there is no value equal to T, the first value +// will equal the second value. If there is no value greater than T, +// the second value returned will be R+1. +// +// This function is different than PartitionAboutMyValue, because in +// that functin we know that "T" appears in the array. In this +// function, "T" may or may not appear in the array. + +int *vtkPKdTree::PartitionAboutOtherValue(int L, int R, float T, int dim) +{ + float *Ipt, *Jpt, Lval, Rval; + int *vals = this->SelectBuffer; + int numTValues = 0; + int numGreater = 0; + int numLess = 0; + int totalVals = R - L + 1; + + Ipt = this->GetLocalVal(L) + dim; + Lval = *Ipt; + + if (Lval == T) numTValues++; + else if (Lval > T) numGreater++; + else numLess++; + + Jpt = this->GetLocalVal(R) + dim; + Rval = *Jpt; + + if (Rval == T) numTValues++; + else if (Rval > T) numGreater++; + else numLess++; + + int I = L; + int J = R; + + if ((Lval >= T) && (Rval >= T)) + { + while (--J > I) + { + Jpt -= 3; + if (*Jpt < T) break; + if (*Jpt == T) numTValues++; + else numGreater++; + } + } + else if ((Lval < T) && (Rval < T)) + { + Ipt = this->GetLocalVal(I) + dim; + + while (++I < J) + { + Ipt += 3; + if (*Ipt >= T) + { + if (*Ipt == T) numTValues++; + break; + } + numLess++; + } + } + else if ((Lval < T) && (Rval >= T)) + { + this->ExchangeLocalVals(I, J); + } + else if ((Lval >= T) && (Rval < T)) + { + // first loop will fix this + } + + if (numLess == totalVals) + { + vals[0] = vals[1] = R+1; // special case - all less than T + return vals; + } + else if (numTValues == totalVals) + { + vals[0] = L; // special case - all equal to T + vals[1] = R+1; + return vals; + } + else if (numGreater == totalVals) + { + vals[0] = vals[1] = L; // special case - all greater than T + return vals; + } + + while (I < J) + { + // By design, I < J and value at I is >= T, and value + // at J is < T, hence the exchange. + + this->ExchangeLocalVals(I, J); + + while (++I < J) + { + Ipt += 3; + if (*Ipt >= T) + { + if (*Ipt == T) numTValues++; + break; + } + } + if (I == J) break; + + while (--J > I) + { + Jpt -= 3; + if (*Jpt < T) break; + if (*Jpt == T) numTValues++; + } + } + + // I and J are at the first value that is >= T. + + if (numTValues == 0) + { + vals[0] = I; + vals[1] = I; + return vals; + } + + // Move all T's to the center interval + + vals[0] = I; // the first T will be here when we're done + + Ipt = this->GetLocalVal(I) + dim; + I = I-1; + Ipt -= 3; + + J = R+1; + Jpt = this->GetLocalVal(R) + dim; + Jpt += 3; + + while (I < J) + { + while (++I < J) + { + Ipt += 3; + if (*Ipt != T) break; + } + if (I == J) break; + + while (--J > I) + { + Jpt -= 3; + if (*Jpt == T) break; + } + + if (I < J) + { + this->ExchangeLocalVals(I, J); + } + } + + // Now I and J are at the first value that is > T, and the T's are + // to the left. + + vals[1] = I; // the first > T + + return vals; +} + +// This routine partitions the array from element L through element +// R into three segments. This first contains values less than T, the +// next contains values equal to T, the last has values greater than T. +// T is the element at K, where L <= K <= R. +// +// This routine returns two integers. The first is the index of the +// first value equal to T, the second is the index of the first value +// greater than T. If there is no value greater than T, the second +// value returned will be R+1. + +int *vtkPKdTree::PartitionAboutMyValue(int L, int R, int K, int dim) +{ + float *Ipt, *Jpt; + float T; + int I, J; + int manyTValues = 0; + int *vals = this->SelectBuffer; + + // Set up so after first exchange in the loop, we have either + // X[L] = T and X[R] >= T + // or + // X[L] < T and X[R] = T + // + + float *pt = this->GetLocalVal(K); + + T = pt[dim]; + + this->ExchangeLocalVals(L, K); + + pt = this->GetLocalVal(R); + + if (pt[dim] >= T) + { + if (pt[dim] == T) + { + manyTValues = 1; + } + else + { + this->ExchangeLocalVals(R, L); + } + } + + I = L; + J = R; + + Ipt = this->GetLocalVal(I) + dim; + Jpt = this->GetLocalVal(J) + dim; + + while (I < J) + { + this->ExchangeLocalVals(I, J); + + while (--J > I) + { + Jpt -= 3; + if (*Jpt < T) break; + + if (!manyTValues && (J > L) && (*Jpt == T)) manyTValues = 1; + } + + if (I == J) break; + + while (++I < J) + { + Ipt += 3; + + if (*Ipt >= T) + { + if (!manyTValues && (*Ipt == T)) manyTValues = 1; + break; + } + } + } + + // I and J are at the rightmost value < T ( or at L if all values + // are >= T) + + pt = this->GetLocalVal(L); + + float Lval = pt[dim]; + + if (Lval == T) + { + this->ExchangeLocalVals(L, J); + } + else + { + this->ExchangeLocalVals(++J, R); + } + + // Now J is at the leftmost value >= T. (It is at a T value.) + + vals[0] = J; + vals[1] = J+1; + + // Arrange array so all values equal to T are together + + if (manyTValues) + { + I = J; + Ipt = this->GetLocalVal(I) + dim; + + J = R+1; + Jpt = this->GetLocalVal(R) + dim; + Jpt += 3; + + while (I < J) + { + while (++I < J) + { + Ipt += 3; + if (*Ipt != T) break; + } + if (I == J) break; + + while (--J > I) + { + Jpt -= 3; + if (*Jpt == T) break; + } + + if (I < J) + { + this->ExchangeLocalVals(I, J); + } + } + // I and J are at the first value that is > T + + vals[1] = I; + } + + return vals; +} + +//-------------------------------------------------------------------- +// Compute the bounds for the data in a region +//-------------------------------------------------------------------- + +void vtkPKdTree::GetLocalMinMax(int L, int R, int me, + float *min, float *max) +{ + int i, d; + int from = this->StartVal[me]; + int to = this->EndVal[me]; + + if (L > from) + { + from = L; + } + if (R < to) + { + to = R; + } + + if (from <= to) + { + from -= this->StartVal[me]; + to -= this->StartVal[me]; + + float *val = this->CurrentPtArray + from*3; + + for (d=0; d<3; d++) + { + min[d] = max[d] = val[d]; + } + + for (i= from+1; i<=to; i++) + { + val += 3; + + for (d=0; d<3; d++) + { + if (val[d] < min[d]) + { + min[d] = val[d]; + } + else if (val[d] > max[d]) + { + max[d] = val[d]; + } + } + } + } + else + { + // this guy has none of the data, but still must participate + // in ReduceMax and ReduceMin + + double *regionMin = this->Top->GetMinBounds(); + double *regionMax = this->Top->GetMaxBounds(); + + for (d=0; d<3; d++) + { + min[d] = (float)regionMax[d]; + max[d] = (float)regionMin[d]; + } + } +} +float *vtkPKdTree::DataBounds(int L, int K, int R) +{ + float localMinLeft[3]; // Left region is L through K-1 + float localMaxLeft[3]; + float globalMinLeft[3]; + float globalMaxLeft[3]; + float localMinRight[3]; // Right region is K through R + float localMaxRight[3]; + float globalMinRight[3]; + float globalMaxRight[3]; + + float *globalBounds = new float [12]; + + int fail = (globalBounds == NULL); + + if (this->AllCheckForFailure(fail, "DataBounds", "memory allocation")) + { + return NULL; + } + + this->GetLocalMinMax(L, K-1, this->MyId, localMinLeft, localMaxLeft); + + this->GetLocalMinMax(K, R, this->MyId, localMinRight, localMaxRight); + + this->SubGroup->ReduceMin(localMinLeft, globalMinLeft, 3, 0); + this->SubGroup->Broadcast(globalMinLeft, 3, 0); + + this->SubGroup->ReduceMax(localMaxLeft, globalMaxLeft, 3, 0); + this->SubGroup->Broadcast(globalMaxLeft, 3, 0); + + this->SubGroup->ReduceMin(localMinRight, globalMinRight, 3, 0); + this->SubGroup->Broadcast(globalMinRight, 3, 0); + + this->SubGroup->ReduceMax(localMaxRight, globalMaxRight, 3, 0); + this->SubGroup->Broadcast(globalMaxRight, 3, 0); + + float *left = globalBounds; + float *right = globalBounds + 6; + + MinMaxToBounds(left, globalMinLeft, globalMaxLeft); + + MinMaxToBounds(right, globalMinRight, globalMaxRight); + + return globalBounds; +} + +//-------------------------------------------------------------------- +// Complete the tree - Different nodes of tree were computed by different +// processors. Now put it together. +//-------------------------------------------------------------------- + +int vtkPKdTree::CompleteTree() +{ + // calculate depth of entire tree + + int depth; + int myDepth = vtkPKdTree::ComputeDepth(this->Top); + + this->SubGroup->ReduceMax(&myDepth, &depth, 1, 0); + this->SubGroup->Broadcast(&depth, 1, 0); + + // fill out nodes of tree + + int fail = vtkPKdTree::FillOutTree(this->Top, depth); + + if (this->AllCheckForFailure(fail, "CompleteTree", "memory allocation")) + { + return 1; + } + + // Processor 0 collects all the nodes of the k-d tree, and then + // processes the tree to ensure region boundaries are + // consistent. The completed tree is then broadcast. + + int *buf = new int [this->NumProcesses]; + + fail = (buf == NULL); + + if (this->AllCheckForFailure(fail, "CompleteTree", "memory allocation")) + { + if (buf) delete [] buf; + return 1; + } + +#ifdef YIELDS_INCONSISTENT_REGION_BOUNDARIES + + this->RetrieveData(this->Top, buf); + +#else + + this->ReduceData(this->Top, buf); + + if (this->MyId == 0) + { + CheckFixRegionBoundaries(this->Top); + } + + this->BroadcastData(this->Top); +#endif + + delete [] buf; + + return 0; +} + +void vtkPKdTree::PackData(vtkKdNode *kd, double *data) +{ + int i, v; + + data[0] = (double)kd->GetDim(); + data[1] = (double)kd->GetLeft()->GetNumberOfPoints(); + data[2] = (double)kd->GetRight()->GetNumberOfPoints(); + + double *lmin = kd->GetLeft()->GetMinBounds(); + double *lmax = kd->GetLeft()->GetMaxBounds(); + double *lminData = kd->GetLeft()->GetMinDataBounds(); + double *lmaxData = kd->GetLeft()->GetMaxDataBounds(); + double *rmin = kd->GetRight()->GetMinBounds(); + double *rmax = kd->GetRight()->GetMaxBounds(); + double *rminData = kd->GetRight()->GetMinDataBounds(); + double *rmaxData = kd->GetRight()->GetMaxDataBounds(); + + v = 3; + for (i=0; i<3; i++) + { + data[v++] = lmin[i]; + data[v++] = lmax[i]; + data[v++] = lminData[i]; + data[v++] = lmaxData[i]; + data[v++] = rmin[i]; + data[v++] = rmax[i]; + data[v++] = rminData[i]; + data[v++] = rmaxData[i]; + } +} +void vtkPKdTree::UnpackData(vtkKdNode *kd, double *data) +{ + int i, v; + + kd->SetDim((int)data[0]); + kd->GetLeft()->SetNumberOfPoints((int)data[1]); + kd->GetRight()->SetNumberOfPoints((int)data[2]); + + double lmin[3], rmin[3], lmax[3], rmax[3]; + double lminData[3], rminData[3], lmaxData[3], rmaxData[3]; + + v = 3; + for (i=0; i<3; i++) + { + lmin[i] = data[v++]; + lmax[i] = data[v++]; + lminData[i] = data[v++]; + lmaxData[i] = data[v++]; + rmin[i] = data[v++]; + rmax[i] = data[v++]; + rminData[i] = data[v++]; + rmaxData[i] = data[v++]; + } + + kd->GetLeft()->SetBounds(lmin[0], lmax[0], lmin[1], lmax[1], lmin[2], lmax[2]); + kd->GetLeft()->SetDataBounds(lminData[0], lmaxData[0], + lminData[1], lmaxData[1], lminData[2], lmaxData[2]); + + kd->GetRight()->SetBounds(rmin[0], rmax[0], rmin[1], rmax[1], rmin[2], rmax[2]); + kd->GetRight()->SetDataBounds(rminData[0], rmaxData[0], + rminData[1], rmaxData[1], rminData[2], rmaxData[2]); +} +void vtkPKdTree::ReduceData(vtkKdNode *kd, int *sources) +{ + int i; + double data[27]; + vtkCommunicator *comm = this->Controller->GetCommunicator(); + + if (kd->GetLeft() == NULL) return; + + int ihave = (kd->GetDim() < 3); + + this->SubGroup->Gather(&ihave, sources, 1, 0); + this->SubGroup->Broadcast(sources, this->NumProcesses, 0); + + // a contiguous group of process IDs built this node, the first + // in the group sends it to node 0 if node 0 doesn't have it + + if (sources[0] == 0) + { + int root = -1; + + for (i=1; iNumProcesses; i++) + { + if (sources[i]) + { + root = i; + break; + } + } + if (root == -1) + { + + // Normally BuildLocator will create a complete tree, but + // it may refuse to divide a region if all the data is at + // the same point along the axis it wishes to divide. In + // that case, this region was not divided, so just return. + + vtkKdTree::DeleteAllDescendants(kd); + + return; + } + + if (root == this->MyId) + { + vtkPKdTree::PackData(kd, data); + + comm->Send(data, 27, 0, 0x1111); + } + else if (0 == this->MyId) + { + comm->Receive(data, 27, root, 0x1111); + + vtkPKdTree::UnpackData(kd, data); + } + } + + this->ReduceData(kd->GetLeft(), sources); + + this->ReduceData(kd->GetRight(), sources); + + return; +} +void vtkPKdTree::BroadcastData(vtkKdNode *kd) +{ + double data[27]; + + if (kd->GetLeft() == NULL) return; + + if (0 == this->MyId) + { + vtkPKdTree::PackData(kd, data); + } + + this->SubGroup->Broadcast(data, 27, 0); + + if (this->MyId > 0) + { + vtkPKdTree::UnpackData(kd, data); + } + + this->BroadcastData(kd->GetLeft()); + + this->BroadcastData(kd->GetRight()); + + return; +} +void vtkPKdTree::CheckFixRegionBoundaries(vtkKdNode *tree) +{ + if (tree->GetLeft() == NULL) return; + + int nextDim = tree->GetDim(); + + vtkKdNode *left = tree->GetLeft(); + vtkKdNode *right = tree->GetRight(); + + double *min = tree->GetMinBounds(); + double *max = tree->GetMaxBounds(); + double *lmin = left->GetMinBounds(); + double *lmax = left->GetMaxBounds(); + double *rmin = right->GetMinBounds(); + double *rmax = right->GetMaxBounds(); + + for (int dim=0; dim<3; dim++) + { + if ((lmin[dim] - min[dim]) != 0.0) lmin[dim] = min[dim]; + if ((rmax[dim] - max[dim]) != 0.0) rmax[dim] = max[dim]; + + if (dim != nextDim) // the dimension I did *not* divide along + { + if ((lmax[dim] - max[dim]) != 0.0) lmax[dim] = max[dim]; + if ((rmin[dim] - min[dim]) != 0.0) rmin[dim] = min[dim]; + } + else + { + if ((lmax[dim] - rmin[dim]) != 0.0) lmax[dim] = rmin[dim]; + } + } + + CheckFixRegionBoundaries(left); + CheckFixRegionBoundaries(right); +} +#ifdef YIELDS_INCONSISTENT_REGION_BOUNDARIES + +void vtkPKdTree::RetrieveData(vtkKdNode *kd, int *sources) +{ + int i; + double data[27]; + + if (kd->GetLeft() == NULL) return; + + int ihave = (kd->GetDim() < 3); + + this->SubGroup->Gather(&ihave, sources, 1, 0); + this->SubGroup->Broadcast(sources, this->NumProcesses, 0); + + // a contiguous group of process IDs built this node, the first + // in the group broadcasts the results to everyone else + + int root = -1; + + for (i=0; iNumProcesses; i++) + { + if (sources[i]) + { + root = i; + break; + } + } + if (root == -1) + { + // Normally BuildLocator will create a complete tree, but + // it may refuse to divide a region if all the data is at + // the same point along the axis it wishes to divide. In + // that case, this region was not divided, so just return. + + vtkKdTree::DeleteAllDescendants(kd); + + return; + } + + if (root == this->MyId) + { + vtkPKdTree::PackData(kd, data); + } + + this->SubGroup->Broadcast(data, 27, root); + + if (!ihave) + { + vtkPKdTree::UnpackData(kd, data); + } + + this->RetrieveData(kd->GetLeft(), sources); + + this->RetrieveData(kd->GetRight(), sources); + + return; +} +#endif + +int vtkPKdTree::FillOutTree(vtkKdNode *kd, int level) +{ + if (level == 0) return 0; + + if (kd->GetLeft() == NULL) + { + vtkKdNode *left = vtkKdNode::New(); + + if (!left) goto doneError2; + + left->SetBounds(-1,-1,-1,-1,-1,-1); + left->SetDataBounds(-1,-1,-1,-1,-1,-1); + left->SetNumberOfPoints(-1); + + vtkKdNode *right = vtkKdNode::New(); + + if (!right) goto doneError2; + + right->SetBounds(-1,-1,-1,-1,-1,-1); + right->SetDataBounds(-1,-1,-1,-1,-1,-1); + right->SetNumberOfPoints(-1); + + kd->AddChildNodes(left, right); + } + + if (vtkPKdTree::FillOutTree(kd->GetLeft(), level-1)) goto doneError2; + + if (vtkPKdTree::FillOutTree(kd->GetRight(), level-1)) goto doneError2; + + return 0; + +doneError2: + + return 1; +} + +int vtkPKdTree::ComputeDepth(vtkKdNode *kd) +{ + int leftDepth = 0; + int rightDepth = 0; + + if ((kd->GetLeft() == NULL) && (kd->GetRight() == NULL)) return 0; + + if (kd->GetLeft()) + { + leftDepth = vtkPKdTree::ComputeDepth(kd->GetLeft()); + } + if (kd->GetRight()) + { + rightDepth = vtkPKdTree::ComputeDepth(kd->GetRight()); + } + + if (leftDepth > rightDepth) return leftDepth + 1; + else return rightDepth + 1; +} + +//-------------------------------------------------------------------- +// lists, lists, lists +//-------------------------------------------------------------------- + +int vtkPKdTree::AllocateDoubleBuffer() +{ + this->FreeDoubleBuffer(); + + this->PtArraySize = this->NumCells[this->MyId] * 3; + + this->PtArray2 = new float [this->PtArraySize]; + + this->CurrentPtArray = this->PtArray; + this->NextPtArray = this->PtArray2; + + return (this->PtArray2 == NULL); +} +void vtkPKdTree::SwitchDoubleBuffer() +{ + float *temp = this->CurrentPtArray; + + this->CurrentPtArray = this->NextPtArray; + this->NextPtArray = temp; +} +void vtkPKdTree::FreeDoubleBuffer() +{ + FreeList(this->PtArray2); + this->CurrentPtArray = this->PtArray; + this->NextPtArray = NULL; +} + +int vtkPKdTree::AllocateSelectBuffer() +{ + this->FreeSelectBuffer(); + + this->SelectBuffer = new int [this->NumProcesses * 10]; + + return (this->SelectBuffer == NULL); +} +void vtkPKdTree::FreeSelectBuffer() +{ + if (this->SelectBuffer) + { + delete [] this->SelectBuffer; + this->SelectBuffer = NULL; + } +} + +#define FreeListOfLists(list, len) \ +{ \ + int i; \ + if (list) \ + { \ + for (i=0; iStartVal = NULL; + this->EndVal = NULL; + this->NumCells = NULL; +} +int vtkPKdTree::AllocateAndZeroGlobalIndexLists() +{ + this->FreeGlobalIndexLists(); + + MakeList(this->StartVal, int, this->NumProcesses); + MakeList(this->EndVal, int, this->NumProcesses); + MakeList(this->NumCells, int, this->NumProcesses); + + int defined = ((this->StartVal != NULL) && + (this->EndVal != NULL) && + (this->NumCells != NULL)); + + if (!defined) this->FreeGlobalIndexLists(); + + return !defined; +} +void vtkPKdTree::FreeGlobalIndexLists() +{ + FreeList(StartVal); + FreeList(EndVal); + FreeList(NumCells); +} +int vtkPKdTree::BuildGlobalIndexLists(int numMyCells) +{ + int fail = this->AllocateAndZeroGlobalIndexLists(); + + if (this->AllCheckForFailure(fail, "BuildGlobalIndexLists", "memory allocation")) + { + this->FreeGlobalIndexLists(); + return 1; + } + + this->SubGroup->Gather(&numMyCells, this->NumCells, 1, 0); + + this->SubGroup->Broadcast(this->NumCells, this->NumProcesses, 0); + + this->StartVal[0] = 0; + this->EndVal[0] = this->NumCells[0] - 1; + + this->TotalNumCells = this->NumCells[0]; + + for (int i=1; iNumProcesses; i++) + { + this->StartVal[i] = this->EndVal[i-1] + 1; + this->EndVal[i] = this->EndVal[i-1] + this->NumCells[i]; + + this->TotalNumCells += this->NumCells[i]; + } + + return 0; +} + +// Region assignment lists --------------------------------------------- + +void vtkPKdTree::InitializeRegionAssignmentLists() +{ + this->RegionAssignmentMap = NULL; + this->ProcessAssignmentMap = NULL; + this->NumRegionsAssigned = NULL; +} +int vtkPKdTree::AllocateAndZeroRegionAssignmentLists() +{ + this->FreeRegionAssignmentLists(); + + this->RegionAssignmentMapLength = this->GetNumberOfRegions(); + + MakeList(this->RegionAssignmentMap, int , this->GetNumberOfRegions()); + MakeList(this->NumRegionsAssigned, int, this->NumProcesses); + + MakeList(this->ProcessAssignmentMap, int *, this->NumProcesses); + + int defined = ((this->RegionAssignmentMap != NULL) && + (this->ProcessAssignmentMap != NULL) && + (this->NumRegionsAssigned != NULL) ); + + if (!defined) this->FreeRegionAssignmentLists(); + + return !defined; +} +void vtkPKdTree::FreeRegionAssignmentLists() +{ + FreeList(this->RegionAssignmentMap); + FreeList(this->NumRegionsAssigned); + FreeListOfLists(this->ProcessAssignmentMap, this->NumProcesses); + + this->RegionAssignmentMapLength = 0; +} + +// Process data tables ------------------------------------------------ + +void vtkPKdTree::InitializeProcessDataLists() +{ + this->DataLocationMap = NULL; + + this->NumProcessesInRegion = NULL; + this->ProcessList = NULL; + + this->NumRegionsInProcess = NULL; + this->RegionList = NULL; + + this->CellCountList = NULL; +} + +int vtkPKdTree::AllocateAndZeroProcessDataLists() +{ + int nRegions = this->GetNumberOfRegions(); + int nProcesses = this->NumProcesses; + + this->FreeProcessDataLists(); + + MakeList(this->DataLocationMap, char, nRegions * nProcesses); + + if (this->DataLocationMap == NULL) goto doneError3; + + MakeList(this->NumProcessesInRegion, int ,nRegions); + + if (this->NumProcessesInRegion == NULL) goto doneError3; + + MakeList(this->ProcessList, int * ,nRegions); + + if (this->ProcessList == NULL) goto doneError3; + + MakeList(this->NumRegionsInProcess, int ,nProcesses); + + if (this->NumRegionsInProcess == NULL) goto doneError3; + + MakeList(this->RegionList, int * ,nProcesses); + + if (this->RegionList == NULL) goto doneError3; + + MakeList(this->CellCountList, int * ,nRegions); + + if (this->CellCountList == NULL) goto doneError3; + + return 0; + +doneError3: + this->FreeProcessDataLists(); + return 1; +} +void vtkPKdTree::FreeProcessDataLists() +{ + int nRegions = this->GetNumberOfRegions(); + int nProcesses = this->NumProcesses; + + FreeListOfLists(this->CellCountList, nRegions); + + FreeListOfLists(this->RegionList, nProcesses); + + FreeList(this->NumRegionsInProcess); + + FreeListOfLists(this->ProcessList, nRegions); + + FreeList(this->NumProcessesInRegion); + + FreeList(this->DataLocationMap); +} + +// Field array global min and max ----------------------------------- + +void vtkPKdTree::InitializeFieldArrayMinMax() +{ + this->NumCellArrays = this->NumPointArrays = 0; + this->CellDataMin = this->CellDataMax = NULL; + this->PointDataMin = this->PointDataMax = NULL; + this->CellDataName = NULL; + this->PointDataName = NULL; +} + +int vtkPKdTree::AllocateAndZeroFieldArrayMinMax() +{ + int iNumCellArrays = 0; + int iNumPointArrays = 0; + + for (int set=0; set < this->GetNumberOfDataSets(); set++) + { + iNumCellArrays += this->GetDataSet(set)->GetCellData()->GetNumberOfArrays(); + iNumPointArrays += this->GetDataSet(set)->GetPointData()->GetNumberOfArrays(); + } + + this->FreeFieldArrayMinMax(); + + if (iNumCellArrays > 0) + { + MakeList(this->CellDataMin, double, iNumCellArrays); + if (this->CellDataMin == NULL) goto doneError5; + + MakeList(this->CellDataMax, double, iNumCellArrays); + if (this->CellDataMax == NULL) goto doneError5; + + MakeList(this->CellDataName, char *, iNumCellArrays); + if (this->CellDataName == NULL) goto doneError5; + } + + this->NumCellArrays = iNumCellArrays; + + if (iNumPointArrays > 0) + { + MakeList(this->PointDataMin, double, iNumPointArrays); + if (this->PointDataMin == NULL) goto doneError5; + + MakeList(this->PointDataMax, double, iNumPointArrays); + if (this->PointDataMax == NULL) goto doneError5; + + MakeList(this->PointDataName, char *, iNumPointArrays); + if (this->PointDataName == NULL) goto doneError5; + } + + this->NumPointArrays = iNumPointArrays; + + return 0; + +doneError5: + this->FreeFieldArrayMinMax(); + return 1; +} +void vtkPKdTree::FreeFieldArrayMinMax() +{ + FreeList(this->CellDataMin); + FreeList(this->CellDataMax); + FreeList(this->PointDataMin); + FreeList(this->PointDataMax); + + FreeListOfLists(this->CellDataName, this->NumCellArrays); + FreeListOfLists(this->PointDataName, this->NumPointArrays); + + this->NumCellArrays = this->NumPointArrays = 0; +} + +void vtkPKdTree::ReleaseTables() +{ + this->FreeRegionAssignmentLists(); + this->FreeProcessDataLists(); + this->FreeFieldArrayMinMax(); +} + +//-------------------------------------------------------------------- +// Create tables indicating which processes have data for which +// regions. +//-------------------------------------------------------------------- + +int vtkPKdTree::CreateProcessCellCountData() +{ + int proc, reg; + int retval = 0; + int *cellCounts = NULL; + int *tempbuf; + char *procData, *myData; + + tempbuf = NULL; + procData = myData = NULL; + + this->SubGroup = vtkSubGroup::New(); + this->SubGroup->Initialize(0, this->NumProcesses-1, + this->MyId, 0x0000f000, this->Controller->GetCommunicator()); + + int fail = this->AllocateAndZeroProcessDataLists(); + + if (!fail && !this->Top) fail = 1; + + if (this->AllCheckForFailure(fail, "BuildRegionProcessTables", "memory allocation")) + { + this->FreeProcessDataLists(); + this->SubGroup->Delete(); + this->SubGroup = NULL; + return 1; + } + + // Build table indicating which processes have data for which regions + + cellCounts = this->CollectLocalRegionProcessData(); + + fail = (cellCounts == NULL); + + if (this->AllCheckForFailure(fail,"BuildRegionProcessTables","error")) + { + goto doneError4; + } + + myData = this->DataLocationMap + (this->MyId * this->GetNumberOfRegions()); + + for (reg=0; reg < this->GetNumberOfRegions(); reg++) + { + if (cellCounts[reg] > 0) myData[reg] = 1; + } + + if (this->NumProcesses > 1) + { + this->SubGroup->Gather(myData, this->DataLocationMap, + this->GetNumberOfRegions(), 0); + this->SubGroup->Broadcast(this->DataLocationMap, + this->GetNumberOfRegions() * this->NumProcesses, 0); + } + + // Other helpful tables - not the fastest way to create this + // information, but it uses the least memory + + procData = this->DataLocationMap; + + for (proc=0; procNumProcesses; proc++) + { + for (reg=0; reg < this->GetNumberOfRegions(); reg++) + { + if (*procData) + { + this->NumProcessesInRegion[reg]++; + this->NumRegionsInProcess[proc]++; + } + procData++; + } + } + for (reg=0; reg < this->GetNumberOfRegions(); reg++) + { + int nprocs = this->NumProcessesInRegion[reg]; + + if (nprocs > 0) + { + this->ProcessList[reg] = new int [nprocs]; + this->ProcessList[reg][0] = -1; + this->CellCountList[reg] = new int [nprocs]; + this->CellCountList[reg][0] = -1; + } + } + for (proc=0; proc < this->NumProcesses; proc++) + { + int nregs = this->NumRegionsInProcess[proc]; + + if (nregs > 0) + { + this->RegionList[proc] = new int [nregs]; + this->RegionList[proc][0] = -1; + } + } + + procData = this->DataLocationMap; + + for (proc=0; procNumProcesses; proc++) + { + + for (reg=0; reg < this->GetNumberOfRegions(); reg++) + { + if (*procData) + { + this->AddEntry(this->ProcessList[reg], + this->NumProcessesInRegion[reg], proc); + + this->AddEntry(this->RegionList[proc], + this->NumRegionsInProcess[proc], reg); + } + procData++; + } + } + + // Cell counts per process per region + + if (this->NumProcesses > 1) + { + tempbuf = new int [this->GetNumberOfRegions() * this->NumProcesses]; + + fail = (tempbuf == NULL); + + if (this->AllCheckForFailure(fail,"BuildRegionProcessTables","memory allocation")) + { + goto doneError4; + } + + this->SubGroup->Gather(cellCounts, tempbuf, this->GetNumberOfRegions(), 0); + this->SubGroup->Broadcast(tempbuf, this->NumProcesses*this->GetNumberOfRegions(), 0); + } + else + { + tempbuf = cellCounts; + } + + for (proc=0; procNumProcesses; proc++) + { + int *procCount = tempbuf + (proc * this->GetNumberOfRegions()); + + for (reg=0; reg < this->GetNumberOfRegions(); reg++) + { + if (procCount[reg]> 0) + { + this->AddEntry(this->CellCountList[reg], + this->NumProcessesInRegion[reg], + procCount[reg]); + } + } + } + + goto done4; + +doneError4: + + this->FreeProcessDataLists(); + retval = 1; + +done4: + + if (tempbuf != cellCounts) + { + FreeList(tempbuf); + } + + FreeList(cellCounts); + this->SubGroup->Delete(); + this->SubGroup = NULL; + + return retval; +} + +//-------------------------------------------------------------------- +// Create list of global min and max for cell and point field arrays +//-------------------------------------------------------------------- + +int vtkPKdTree::CreateGlobalDataArrayBounds() +{ + int set = 0; + this->SubGroup = NULL; + + if (this->NumProcesses > 1) + { + this->SubGroup = vtkSubGroup::New(); + this->SubGroup->Initialize(0, this->NumProcesses-1, + this->MyId, 0x0000f000, this->Controller->GetCommunicator()); + } + + int fail = this->AllocateAndZeroFieldArrayMinMax(); + + if (this->AllCheckForFailure(fail, "BuildFieldArrayMinMax", "memory allocation")) + { + this->FreeFieldArrayMinMax(); + FreeObject(this->SubGroup); + return 1; + } + + TIMER("Get global ranges"); + + int ar; + double range[2]; + int nc = 0; + int np = 0; + + // This code assumes that if more than one dataset was input to vtkPKdTree, + // each process input the datasets in the same order. + + if (this->NumCellArrays > 0) + { + for (set=0; set < this->GetNumberOfDataSets(); set++) + { + int ncellarrays = this->GetDataSet(set)->GetCellData()->GetNumberOfArrays(); + + for (ar=0; arGetDataSet(set)->GetCellData()->GetArray(ar); + + array->GetRange(range); + + this->CellDataMin[nc] = range[0]; + this->CellDataMax[nc] = range[1]; + + this->CellDataName[nc] = vtkPKdTree::StrDupWithNew(array->GetName()); + nc++; + } + } + + if (this->NumProcesses > 1) + { + this->SubGroup->ReduceMin(this->CellDataMin, this->CellDataMin, nc, 0); + this->SubGroup->Broadcast(this->CellDataMin, nc, 0); + + this->SubGroup->ReduceMax(this->CellDataMax, this->CellDataMax, nc, 0); + this->SubGroup->Broadcast(this->CellDataMax, nc, 0); + } + } + + if (this->NumPointArrays > 0) + { + for (set=0; set < this->GetNumberOfDataSets(); set++) + { + int npointarrays = this->GetDataSet(set)->GetPointData()->GetNumberOfArrays(); + + for (ar=0; arGetDataSet(set)->GetPointData()->GetArray(ar); + + array->GetRange(range); + + this->PointDataMin[np] = range[0]; + this->PointDataMax[np] = range[1]; + + this->PointDataName[np] = StrDupWithNew(array->GetName()); + np++; + } + } + + if (this->NumProcesses > 1) + { + this->SubGroup->ReduceMin(this->PointDataMin, this->PointDataMin, np, 0); + this->SubGroup->Broadcast(this->PointDataMin, np, 0); + + this->SubGroup->ReduceMax(this->PointDataMax, this->PointDataMax, np, 0); + this->SubGroup->Broadcast(this->PointDataMax, np, 0); + } + } + + TIMERDONE("Get global ranges"); + + FreeObject(this->SubGroup); + + return 0; +} +int *vtkPKdTree::CollectLocalRegionProcessData() +{ + int *cellCounts; + + int numRegions = this->GetNumberOfRegions(); + + MakeList(cellCounts, int, numRegions); + + if (!cellCounts) + { + VTKERROR("CollectLocalRegionProcessData - memory allocation"); + return NULL; + } + + TIMER("Get cell regions"); + + int *IDs = this->AllGetRegionContainingCell(); + + TIMERDONE("Get cell regions"); + + for (int set=0; set < this->GetNumberOfDataSets(); set++) + { + int ncells = this->GetDataSet(set)->GetNumberOfCells(); + + TIMER("Increment cell counts"); + + for (int i=0; i= numRegions)) + { + VTKERROR("CollectLocalRegionProcessData - corrupt data"); + return NULL; + } + cellCounts[regionId]++; + } + + IDs += ncells; + + TIMERDONE("Increment cell counts"); + } + + return cellCounts; +} +void vtkPKdTree::AddEntry(int *list, int len, int id) +{ + int i=0; + + while ((i < len) && (list[i] != -1)) i++; + + if (i == len) return; // error + + list[i++] = id; + + if (i < len) list[i] = -1; +} +int vtkPKdTree::BinarySearch(int *list, int len, int which) +{ +int mid, left, right; + + mid = -1; + + if (len <= 3) + { + for (int i=0; i> 1; + left = 0; + right = len-1; + + while (list[mid] != which) + { + if (list[mid] < which) + { + left = mid+1; + } + else + { + right = mid-1; + } + + if (right > left+1) + { + mid = (left + right) >> 1; + } + else + { + if (list[left] == which) mid = left; + else if (list[right] == which) mid = right; + else mid = -1; + break; + } + } + } + return mid; +} +//-------------------------------------------------------------------- +// Assign responsibility for each spatial region to one process +//-------------------------------------------------------------------- + +int vtkPKdTree::UpdateRegionAssignment() +{ + int returnVal = 0; + + if (this->RegionAssignment== ContiguousAssignment) + { + returnVal = this->AssignRegionsContiguous(); + } + else if (this->RegionAssignment== RoundRobinAssignment) + { + returnVal = this->AssignRegionsRoundRobin(); + } + + return returnVal; +} +int vtkPKdTree::AssignRegionsRoundRobin() +{ + this->RegionAssignment = RoundRobinAssignment; + + if (this->Top == NULL) + { + return 0; + } + + int nProcesses = this->NumProcesses; + int nRegions = this->GetNumberOfRegions(); + + int fail = this->AllocateAndZeroRegionAssignmentLists(); + + if (fail) + { + return 1; + } + + for (int i=0, procID=0; iRegionAssignmentMap[i] = procID; + this->NumRegionsAssigned[procID]++; + + procID = ( (procID == nProcesses-1) ? 0 : procID+1); + } + this->BuildRegionListsForProcesses(); + + return 0; +} +int vtkPKdTree::AssignRegions(int *map, int len) +{ + int fail = this->AllocateAndZeroRegionAssignmentLists(); + + if (fail) + { + return 1; + } + + this->RegionAssignmentMapLength = len; + + this->RegionAssignment = UserDefinedAssignment; + + for (int i=0; i= this->NumProcesses)) + { + this->FreeRegionAssignmentLists(); + VTKERROR("AssignRegions - invalid process id in map"); + return 1; + } + + this->RegionAssignmentMap[i] = map[i]; + this->NumRegionsAssigned[map[i]]++; + } + + this->BuildRegionListsForProcesses(); + + return 0; +} +void vtkPKdTree::AddProcessRegions(int procId, vtkKdNode *kd) +{ + vtkIntArray *leafNodeIds = vtkIntArray::New(); + + vtkKdTree::GetLeafNodeIds(kd, leafNodeIds); + + int nLeafNodes = leafNodeIds->GetNumberOfTuples(); + + for (int n=0; nRegionAssignmentMap[leafNodeIds->GetValue(n)] = procId; + this->NumRegionsAssigned[procId]++; + } + + leafNodeIds->Delete(); +} + +int vtkPKdTree::AssignRegionsContiguous() +{ + int p; + + this->RegionAssignment = ContiguousAssignment; + + if (this->Top == NULL) + { + return 0; + } + + int nProcesses = this->NumProcesses; + int nRegions = this->GetNumberOfRegions(); + + if (nRegions <= nProcesses) + { + this->AssignRegionsRoundRobin(); + return 0; + } + + int fail = this->AllocateAndZeroRegionAssignmentLists(); + + if (fail) + { + return 1; + } + + int floorLogP, ceilLogP; + + for (floorLogP = 0; (nProcesses >> floorLogP) > 0; floorLogP++); + floorLogP--; + + int P = 1 << floorLogP; + + if (nProcesses == P) ceilLogP = floorLogP; + else ceilLogP = floorLogP + 1; + + vtkKdNode **nodes = new vtkKdNode* [P]; + + this->GetRegionsAtLevel(floorLogP, nodes); + + if (floorLogP == ceilLogP) + { + for (p=0; pAddProcessRegions(p, nodes[p]); + } + } + else + { + int nodesLeft = 1 << ceilLogP; + int procsLeft = nProcesses; + int procId = 0; + + for (int i=0; i procsLeft) + { + this->AddProcessRegions(procId, nodes[i]); + + procsLeft -= 1; + procId += 1; + } + else + { + this->AddProcessRegions(procId, nodes[i]->GetLeft()); + this->AddProcessRegions(procId+1, nodes[i]->GetRight()); + + procsLeft -= 2; + procId += 2; + } + nodesLeft -= 2; + } + } + + delete [] nodes; + + this->BuildRegionListsForProcesses(); + + return 0; +} +void vtkPKdTree::BuildRegionListsForProcesses() +{ + int *count = new int [this->NumProcesses]; + + for (int p=0; pNumProcesses; p++) + { + int nregions = this->NumRegionsAssigned[p]; + + if (nregions > 0) + { + this->ProcessAssignmentMap[p] = new int [nregions]; + } + else + { + this->ProcessAssignmentMap[p] = NULL; + } + + count[p] = 0; + } + + for (int r=0; rRegionAssignmentMapLength; r++) + { + int proc = this->RegionAssignmentMap[r]; + int next = count[proc]; + + this->ProcessAssignmentMap[proc][next] = r; + + count[proc] = next + 1; + } + + delete [] count; +} + +//-------------------------------------------------------------------- +// Queries +//-------------------------------------------------------------------- +int vtkPKdTree::FindNextLocalArrayIndex(const char *n, + const char **names, int len, int start) +{ + int index = -1; + int nsize = strlen(n); + + // normally a very small list, maybe 1 to 5 names + + for (int i=start; iCellDataName, this->NumCellArrays, start); + + if (index >= 0) + { + if (first) + { + this->GetCellArrayGlobalRange(index, range); + first = 0; + } + else + { + this->GetCellArrayGlobalRange(index, tmp); + range[0] = (tmp[0] < range[0]) ? tmp[0] : range[0]; + range[1] = (tmp[1] > range[1]) ? tmp[1] : range[1]; + } + start = index + 1; + } + else + { + break; + } + } + + int fail = (first != 0); + + return fail; +} +int vtkPKdTree::GetCellArrayGlobalRange(const char *n, float range[2]) +{ + double tmp[2]; + + int fail = this->GetCellArrayGlobalRange(n, tmp); + + if (!fail) + { + range[0] = (float)tmp[0]; + range[1] = (float)tmp[1]; + } + + return fail; +} +int vtkPKdTree::GetPointArrayGlobalRange(const char *n, double range[2]) +{ + int first = 1; + double tmp[2]; + int start = 0; + + while (1) + { + // Point array name may appear more than once if multiple datasets + // were processed. + + int index = vtkPKdTree::FindNextLocalArrayIndex(n, + (const char **)this->PointDataName, this->NumPointArrays, start); + + if (index >= 0) + { + if (first) + { + this->GetPointArrayGlobalRange(index, range); + first = 0; + } + else + { + this->GetPointArrayGlobalRange(index, tmp); + range[0] = (tmp[0] < range[0]) ? tmp[0] : range[0]; + range[1] = (tmp[1] > range[1]) ? tmp[1] : range[1]; + } + start = index + 1; + } + else + { + break; + } + } + + int fail = (first != 0); + + return fail; +} +int vtkPKdTree::GetPointArrayGlobalRange(const char *n, float range[2]) +{ + double tmp[2]; + + int fail = this->GetPointArrayGlobalRange(n, tmp); + + if (!fail) + { + range[0] = (float)tmp[0]; + range[1] = (float)tmp[1]; + } + + return fail; +} +int vtkPKdTree::GetCellArrayGlobalRange(int arrayIndex, float range[2]) +{ + double tmp[2]; + int fail = this->GetCellArrayGlobalRange(arrayIndex, tmp); + if (!fail) + { + range[0] = (float)tmp[0]; + range[1] = (float)tmp[1]; + } + return fail; +} +int vtkPKdTree::GetCellArrayGlobalRange(int arrayIndex, double range[2]) +{ + if ((arrayIndex < 0) || (arrayIndex >= this->NumCellArrays)) + { + return 1; + } + if (this->CellDataMin == NULL) return 1; + + range[0] = this->CellDataMin[arrayIndex]; + range[1] = this->CellDataMax[arrayIndex]; + + return 0; +} +int vtkPKdTree::GetPointArrayGlobalRange(int arrayIndex, float range[2]) +{ + double tmp[2]; + int fail = this->GetPointArrayGlobalRange(arrayIndex, tmp); + if (!fail) + { + range[0] = (float)tmp[0]; + range[1] = (float)tmp[1]; + } + return fail; +} +int vtkPKdTree::GetPointArrayGlobalRange(int arrayIndex, double range[2]) +{ + if ((arrayIndex < 0) || (arrayIndex >= this->NumPointArrays)) + { + return 1; + } + if (this->PointDataMin == NULL) return 1; + + range[0] = this->PointDataMin[arrayIndex]; + range[1] = this->PointDataMax[arrayIndex]; + + return 0; +} +int vtkPKdTree::DepthOrderAllProcesses(double *dop, vtkIntArray *orderedList) +{ + vtkIntArray *regionList = vtkIntArray::New(); + + this->DepthOrderAllRegions(dop, regionList); + + orderedList->SetNumberOfValues(this->NumProcesses); + + int nextId = 0; + + // if regions were not assigned contiguously, this + // produces the wrong result + + for (int r=0; rGetNumberOfRegions(); ) + { + int procId = this->RegionAssignmentMap[regionList->GetValue(r)]; + + orderedList->SetValue(nextId++, procId); + + int nregions = this->NumRegionsAssigned[procId]; + + r += nregions; + } + + regionList->Delete(); + + return this->NumProcesses; +} + +int vtkPKdTree::GetRegionAssignmentList(int procId, vtkIntArray *list) +{ + if ( (procId < 0) || (procId >= this->NumProcesses)) + { + VTKERROR("GetRegionAssignmentList - invalid process id"); + return 0; + } + + if (!this->RegionAssignmentMap) + { + this->UpdateRegionAssignment(); + + if (!this->RegionAssignmentMap) + { + return 0; + } + } + + int nregions = this->NumRegionsAssigned[procId]; + int *regionIds = this->ProcessAssignmentMap[procId]; + + list->Initialize(); + list->SetNumberOfValues(nregions); + + for (int i=0; iSetValue(i, regionIds[i]); + } + + return nregions; +} +void vtkPKdTree::GetAllProcessesBorderingOnPoint(float x, float y, float z, + vtkIntArray *list) +{ + vtkIntArray *regions = vtkIntArray::New(); + double *subRegionBounds; + list->Initialize(); + + for (int procId = 0; procId < this->NumProcesses; procId++) + { + this->GetRegionAssignmentList(procId, regions); + + int nSubRegions = this->MinimalNumberOfConvexSubRegions( + regions, &subRegionBounds); + + double *b = subRegionBounds; + + for (int r=0; r= b[2]) && (y <= b[3]) && (z >= b[4]) && (z <= b[5]))) || + (((y == b[2]) || (y == b[3])) && + ((x >= b[0]) && (x <= b[1]) && (z >= b[4]) && (z <= b[5]))) || + (((z == b[4]) || (z == b[5])) && + ((x >= b[0]) && (x <= b[1]) && (y >= b[2]) && (y <= b[3]))) ) + { + list->InsertNextValue(procId); + break; + } + + b += 6; + } + } + + regions->Delete(); +} + +int vtkPKdTree::GetProcessAssignedToRegion(int regionId) +{ + if ( !this->RegionAssignmentMap || + (regionId < 0) || (regionId >= this->GetNumberOfRegions())) + { + return -1; + } + + return this->RegionAssignmentMap[regionId]; +} +int vtkPKdTree::HasData(int processId, int regionId) +{ + if ((!this->DataLocationMap) || + (processId < 0) || (processId >= this->NumProcesses) || + (regionId < 0) || (regionId >= this->GetNumberOfRegions()) ) + { + VTKERROR("HasData - invalid request"); + return 0; + } + + int where = this->GetNumberOfRegions() * processId + regionId; + + return this->DataLocationMap[where]; +} + +int vtkPKdTree::GetTotalProcessesInRegion(int regionId) +{ + if (!this->NumProcessesInRegion || + (regionId < 0) || (regionId >= this->GetNumberOfRegions()) ) + { + VTKERROR("GetTotalProcessesInRegion - invalid request"); + return 0; + } + + return this->NumProcessesInRegion[regionId]; +} + +int vtkPKdTree::GetProcessListForRegion(int regionId, vtkIntArray *processes) +{ + if (!this->ProcessList || + (regionId < 0) || (regionId >= this->GetNumberOfRegions()) ) + { + VTKERROR("GetProcessListForRegion - invalid request"); + return 0; + } + + int nProcesses = this->NumProcessesInRegion[regionId]; + + for (int i=0; iInsertNextValue(this->ProcessList[regionId][i]); + } + + return nProcesses; +} + +int vtkPKdTree::GetProcessesCellCountForRegion(int regionId, int *count, int len) +{ + if (!this->CellCountList || + (regionId < 0) || (regionId >= this->GetNumberOfRegions()) ) + { + VTKERROR("GetProcessesCellCountForRegion - invalid request"); + return 0; + } + + int nProcesses = this->NumProcessesInRegion[regionId]; + + nProcesses = (len < nProcesses) ? len : nProcesses; + + for (int i=0; iCellCountList[regionId][i]; + } + + return nProcesses; +} + +int vtkPKdTree::GetProcessCellCountForRegion(int processId, int regionId) +{ + int nCells; + + if (!this->CellCountList || + (regionId < 0) || (regionId >= this->GetNumberOfRegions()) || + (processId < 0) || (processId >= this->NumProcesses)) + { + VTKERROR("GetProcessCellCountForRegion - invalid request"); + return 0; + } + + int nProcesses = this->NumProcessesInRegion[regionId]; + + int which = -1; + + for (int i=0; iProcessList[regionId][i] == processId) + { + which = i; + break; + } + } + + if (which == -1) nCells = 0; + else nCells = this->CellCountList[regionId][which]; + + return nCells; +} + +int vtkPKdTree::GetTotalRegionsForProcess(int processId) +{ + if ((!this->NumRegionsInProcess) || + (processId < 0) || (processId >= this->NumProcesses)) + { + VTKERROR("GetTotalRegionsForProcess - invalid request"); + return 0; + } + + return this->NumRegionsInProcess[processId]; +} + +int vtkPKdTree::GetRegionListForProcess(int processId, vtkIntArray *regions) +{ + if (!this->RegionList || + (processId < 0) || (processId >= this->NumProcesses)) + { + VTKERROR("GetRegionListForProcess - invalid request"); + return 0; + } + + int nRegions = this->NumRegionsInProcess[processId]; + + for (int i=0; iInsertNextValue(this->RegionList[processId][i]); + } + + return nRegions; +} +int vtkPKdTree::GetRegionsCellCountForProcess(int processId, int *count, int len) +{ + if (!this->CellCountList || + (processId < 0) || (processId >= this->NumProcesses)) + { + VTKERROR("GetRegionsCellCountForProcess - invalid request"); + return 0; + } + + int nRegions = this->NumRegionsInProcess[processId]; + + nRegions = (len < nRegions) ? len : nRegions; + + for (int i=0; iRegionList[processId][i]; + int iam; + + for (iam = 0; iam < this->NumProcessesInRegion[regionId]; iam++) + { + if (this->ProcessList[regionId][iam] == processId) break; + } + + count[i] = this->CellCountList[regionId][iam]; + } + return nRegions; +} +vtkIdType vtkPKdTree::GetCellListsForProcessRegions(int processId, + int set, vtkIdList *inRegionCells, vtkIdList *onBoundaryCells) +{ + if ( (set < 0) || (set >= this->GetNumberOfDataSets())) + { + vtkErrorMacro(<<"vtkPKdTree::GetCellListsForProcessRegions no such data set"); + return 0; + } + return this->GetCellListsForProcessRegions(processId, + this->GetDataSet(set), inRegionCells, onBoundaryCells); +} +vtkIdType vtkPKdTree::GetCellListsForProcessRegions(int processId, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells) +{ + return this->GetCellListsForProcessRegions(processId, + this->GetDataSet(0), inRegionCells, onBoundaryCells); +} +vtkIdType vtkPKdTree::GetCellListsForProcessRegions(int processId, + vtkDataSet *set, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells) +{ + vtkIdType totalCells = 0; + + if ( (inRegionCells == NULL) && (onBoundaryCells == NULL)) + { + return totalCells; + } + + // Get the list of regions owned by this process + + vtkIntArray *regions = vtkIntArray::New(); + + int nregions = this->GetRegionAssignmentList(processId, regions); + + if (nregions == 0){ + if (inRegionCells) + { + inRegionCells->Initialize(); + } + if (onBoundaryCells) + { + onBoundaryCells->Initialize(); + } + regions->Delete(); + return totalCells; + } + + totalCells = this->GetCellLists(regions, set, inRegionCells, onBoundaryCells); + + regions->Delete(); + + return totalCells; +} +void vtkPKdTree::PrintTiming(ostream& os, vtkIndent indent) +{ + os << indent << "Total cells in distributed data: " << this->TotalNumCells << endl; + + if (this->NumProcesses) + { + os << indent << "Average cells per processor: " ; + os << this->TotalNumCells / this->NumProcesses << endl; + } + vtkTimerLog::DumpLogWithIndents(&os, (float)0.0); +} +void vtkPKdTree::PrintTables(ostream & os, vtkIndent indent) +{ + int nregions = this->GetNumberOfRegions(); + int nprocs =this->NumProcesses; + int r,p,n; + + if (this->RegionAssignmentMap) + { + int *map = this->RegionAssignmentMap; + int *num = this->NumRegionsAssigned; + int halfr = this->RegionAssignmentMapLength/2; + int halfp = nprocs/2; + + os << indent << "Region assignments:" << endl; + for (r=0; r < halfr; r++) + { + os << indent << " region " << r << " to process " << map[r] ; + os << " region " << r+halfr << " to process " << map[r+halfr] ; + os << endl; + } + for (p=0; p < halfp; p++) + { + os << indent << " " << num[p] << " regions to process " << p ; + os << " " << num[p+halfp] << " regions to process " << p+ halfp ; + os << endl; + } + if (nprocs > halfp*2) + { + os << indent << " " << num[nprocs-1]; + os << " regions to process " << nprocs-1 << endl ; + } + } + + if (this->ProcessList) + { + os << indent << "Processes holding data for each region:" << endl; + for (r=0; rNumProcessesInRegion[r]; + + os << indent << " region " << r << " (" << n << " processes): "; + + for (p=0; pProcessList[r][p] << " " ; + } + os << endl; + } + } + if (this->RegionList) + { + os << indent << "Regions held by each process:" << endl; + for (p=0; pNumRegionsInProcess[p]; + + os << indent << " process " << p << " (" << n << " regions): "; + + for (r=0; rRegionList[p][r] << " " ; + } + os << endl; + } + } + if (this->CellCountList) + { + os << indent << "Number of cells per process per region:" << endl; + for (r=0; rNumProcessesInRegion[r]; + + os << indent << " region: " << r << " "; + for (p=0; pProcessList[r][p] << " - "; + os << this->CellCountList[r][p] << " cells, "; + } + os << endl; + } + } +} +char *vtkPKdTree::StrDupWithNew(const char *s) +{ + char *newstr = NULL; + + if (s) + { + int len = strlen(s); + if (len == 0) + { + newstr = new char [1]; + newstr[0] = '\0'; + } + else + { + newstr = new char [len + 1]; + strcpy(newstr, s); + } + } + + return newstr; +} + +void vtkPKdTree::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "RegionAssignment: " << this->RegionAssignment << endl; + + os << indent << "Controller: " << this->Controller << endl; + os << indent << "SubGroup: " << this->SubGroup<< endl; + os << indent << "NumProcesses: " << this->NumProcesses << endl; + os << indent << "MyId: " << this->MyId << endl; + + os << indent << "RegionAssignmentMap: " << this->RegionAssignmentMap << endl; + os << indent << "NumRegionsAssigned: " << this->NumRegionsAssigned << endl; + os << indent << "NumProcessesInRegion: " << this->NumProcessesInRegion << endl; + os << indent << "ProcessList: " << this->ProcessList << endl; + os << indent << "NumRegionsInProcess: " << this->NumRegionsInProcess << endl; + os << indent << "RegionList: " << this->RegionList << endl; + os << indent << "CellCountList: " << this->CellCountList << endl; + + os << indent << "StartVal: " << this->StartVal << endl; + os << indent << "EndVal: " << this->EndVal << endl; + os << indent << "NumCells: " << this->NumCells << endl; + os << indent << "TotalNumCells: " << this->TotalNumCells << endl; + + os << indent << "PtArray: " << this->PtArray << endl; + os << indent << "PtArray2: " << this->PtArray2 << endl; + os << indent << "CurrentPtArray: " << this->CurrentPtArray << endl; + os << indent << "NextPtArray: " << this->NextPtArray << endl; + os << indent << "SelectBuffer: " << this->SelectBuffer << endl; +} + diff --git a/Parallel/vtkPKdTree.h b/Parallel/vtkPKdTree.h new file mode 100644 index 0000000..2d91964 --- /dev/null +++ b/Parallel/vtkPKdTree.h @@ -0,0 +1,434 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPKdTree.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkPKdTree - Build a k-d tree decomposition of a list of points. +// +// .SECTION Description +// Build, in parallel, a k-d tree decomposition of one or more +// vtkDataSets distributed across processors. We assume each +// process has read in one portion of a large distributed data set. +// When done, each process has access to the k-d tree structure, +// can obtain information about which process contains +// data for each spatial region, and can depth sort the spatial +// regions. +// +// This class can also assign spatial regions to processors, based +// on one of several region assignment schemes. By default +// a contiguous, convex region is assigned to each process. Several +// queries return information about how many and what cells I have +// that lie in a region assigned to another process. +// +// .SECTION See Also +// vtkKdTree + +#ifndef __vtkPKdTree_h +#define __vtkPKdTree_h + +#include "vtkKdTree.h" + +class vtkMultiProcessController; +class vtkCommunicator; +class vtkSubGroup; +class vtkIntArray; +class vtkKdNode; + +class VTK_PARALLEL_EXPORT vtkPKdTree : public vtkKdTree +{ +public: + vtkTypeRevisionMacro(vtkPKdTree, vtkKdTree); + + + void PrintSelf(ostream& os, vtkIndent indent); + void PrintTiming(ostream& os, vtkIndent indent); + void PrintTables(ostream& os, vtkIndent indent); + + static vtkPKdTree *New(); + + // Description: + // Build the spatial decomposition. Call this explicitly + // after changing any parameters affecting the build of the + // tree. It must be called by all processes in the parallel + // application, or it will hang. + + void BuildLocator(); + + // Description: + // Get the total number of cells distributed across the data + // files read by all processes. You must have called BuildLocator + // before calling this method. + + int GetTotalNumberOfCells(){return this->TotalNumCells;} + + // Description: + // Create tables of counts of cells per process per region. + // These tables can be accessed with queries like + // "HasData", "GetProcessCellCountForRegion", and so on. + // You must have called BuildLocator() beforehand. This + // method must be called by all processes or it will hang. + // Returns 1 on error, 0 when no error. + + int CreateProcessCellCountData(); + + // Description: + // A convenience function which compiles the global + // bounds of the data arrays across processes. + // These bounds can be accessed with + // "GetCellArrayGlobalRange" and "GetPointArrayGlobalRange". + // This method must be called by all processes or it will hang. + // Returns 1 on error, 0 when no error. + + int CreateGlobalDataArrayBounds(); + + // Description: + // Set/Get the communicator object + + void SetController(vtkMultiProcessController *c); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + + // Description: + // The PKdTree class can assign spatial regions to processors after + // building the k-d tree, using one of several partitioning criteria. + // These functions Set/Get whether this assignment is computed. + // The default is "Off", no assignment is computed. If "On", and + // no assignment scheme is specified, contiguous assignment will be + // computed. Specifying an assignment scheme (with AssignRegions*()) + // automatically turns on RegionAssignment. + + vtkGetMacro(RegionAssignment, int); + + static const int NoRegionAssignment; + static const int ContiguousAssignment; + static const int UserDefinedAssignment; + static const int RoundRobinAssignment; + + // Description: + // Assign spatial regions to processes via a user defined map. + // The user-supplied map is indexed by region ID, and provides a + // process ID for each region. + + int AssignRegions(int *map, int numRegions); + + // Description: + // Let the PKdTree class assign a process to each region in a + // round robin fashion. If the k-d tree has not yet been + // built, the regions will be assigned after BuildLocator executes. + + int AssignRegionsRoundRobin(); + + // Description: + // Let the PKdTree class assign a process to each region + // by assigning contiguous sets of spatial regions to each + // process. The set of regions assigned to each process will + // always have a union that is a convex space (a box). + // If the k-d tree has not yet been built, the regions + // will be assigned after BuildLocator executes. + + int AssignRegionsContiguous(); + + // Description: + // Writes the list of region IDs assigned to the specified + // process. Regions IDs start at 0 and increase by 1 from there. + // Returns the number of regions in the list. + + int GetRegionAssignmentList(int procId, vtkIntArray *list); + + // Description: + // The k-d tree spatial regions have been assigned to processes. + // Given a point on the boundary of one of the regions, this + // method creates a list of all processes whose region + // boundaries include that point. This may be required when + // looking for processes that have cells adjacent to the cells + // of a given process. + + void GetAllProcessesBorderingOnPoint(float x, float y, float z, + vtkIntArray *list); + + // Description: + // Returns the ID of the process assigned to the region. + + int GetProcessAssignedToRegion(int regionId); + + // Description: + // Returns 1 if the process has data for the given region, + // 0 otherwise. + + int HasData(int processId, int regionId); + + // Description: + // Returns the number of cells the specified process has in the + // specified region. + + int GetProcessCellCountForRegion(int processId, int regionId); + + // Description: + // Returns the total number of processes that have data + // falling within this spatial region. + + int GetTotalProcessesInRegion(int regionId); + + // Description: + // Adds the list of processes having data for the given + // region to the supplied list, returns the number of + // processes added. + + int GetProcessListForRegion(int regionId, vtkIntArray *processes); + + // Description: + // Writes the number of cells each process has for the region + // to the supplied list of length len. Returns the number of + // cell counts written. The order of the cell counts corresponds + // to the order of process IDs in the process list returned by + // GetProcessListForRegion. + + int GetProcessesCellCountForRegion(int regionId, int *count, int len); + + // Description: + // Returns the total number of spatial regions that a given + // process has data for. + + int GetTotalRegionsForProcess(int processId); + + // Description: + // Adds the region IDs for which this process has data to + // the supplied vtkIntArray. Retruns the number of regions. + + int GetRegionListForProcess(int processId, vtkIntArray *regions); + + // Description: + // Writes to the supplied integer array the number of cells this + // process has for each region. Returns the number of + // cell counts written. The order of the cell counts corresponds + // to the order of region IDs in the region list returned by + // GetRegionListForProcess. + + int GetRegionsCellCountForProcess(int ProcessId, int *count, int len); + + // Description: + // After regions have been assigned to processes, I may want to know + // which cells I have that are in the regions assigned to a particular + // process. + // + // This method takes a process ID and two vtkIdLists. It + // writes to the first list the IDs of the cells + // contained in the process' regions. (That is, their cell + // centroid is contained in the region.) To the second list it + // write the IDs of the cells which intersect the process' regions + // but whose cell centroid lies elsewhere. + // + // The total number of cell IDs written to both lists is returned. + // Either list pointer passed in can be NULL, and it will be ignored. + // If there are multiple data sets, you must specify which data set + // you wish cell IDs for. + // + // The caller should delete these two lists when done. This method + // uses the cell lists created in vtkKdTree::CreateCellLists(). + // If the cell lists for the process' regions do not exist, this + // method will first build the cell lists for all regions by calling + // CreateCellLists(). You must remember to DeleteCellLists() when + // done with all calls to this method, as cell lists can require a + // great deal of memory. + + vtkIdType GetCellListsForProcessRegions(int ProcessId, int set, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells); + vtkIdType GetCellListsForProcessRegions(int ProcessId, vtkDataSet *set, + vtkIdList *inRegionCells, vtkIdList *onBoundaryCells); + vtkIdType GetCellListsForProcessRegions(int ProcessId, vtkIdList *inRegionCells, + vtkIdList *onBoundaryCells); + + // Description: + // Return a list of all processes in order from front to + // back, given a vector direction of projection. + + int DepthOrderAllProcesses(double *directionOfProjection, + vtkIntArray *orderedList); + + // Description: + // An added feature of vtkPKdTree is that it will calculate the + // the global range of field arrays across all processes. You + // call CreateGlobalDataArrayBounds() to do this calculation. + // Then the following methods return the ranges. + // Returns 1 on error, 0 otherwise. + + int GetCellArrayGlobalRange(const char *name, float range[2]); + int GetPointArrayGlobalRange(const char *name, float range[2]); + int GetCellArrayGlobalRange(const char *name, double range[2]); + int GetPointArrayGlobalRange(const char *name, double range[2]); + + int GetCellArrayGlobalRange(int arrayIndex, double range[2]); + int GetPointArrayGlobalRange(int arrayIndex, double range[2]); + int GetCellArrayGlobalRange(int arrayIndex, float range[2]); + int GetPointArrayGlobalRange(int arrayIndex, float range[2]); + +protected: + + vtkPKdTree(); + ~vtkPKdTree(); + + void SingleProcessBuildLocator(); + int MultiProcessBuildLocator(double *bounds); + +private: + + int RegionAssignment; + + vtkMultiProcessController *Controller; + + vtkSubGroup *SubGroup; + + static char *StrDupWithNew(const char *s); + + int NumProcesses; + int MyId; + + // basic tables - each region is the responsibility of one process, but + // one process may be assigned many regions + + int *RegionAssignmentMap; // indexed by region ID + int RegionAssignmentMapLength; + int **ProcessAssignmentMap; // indexed by process ID + int *NumRegionsAssigned; // indexed by process ID + + int UpdateRegionAssignment(); + + // basic tables reflecting the data that was read from disk + // by each process + + char *DataLocationMap; // by process, by region + + int *NumProcessesInRegion; // indexed by region ID + int **ProcessList; // indexed by region ID + + int *NumRegionsInProcess; // indexed by process ID + int **RegionList; // indexed by process ID + + int **CellCountList; // indexed by region ID + + double *CellDataMin; // global range for data arrays + double *CellDataMax; + double *PointDataMin; + double *PointDataMax; + char **CellDataName; + char **PointDataName; + int NumCellArrays; + int NumPointArrays; + + // distribution of indices for select operation + + int BuildGlobalIndexLists(int ncells); + + int *StartVal; + int *EndVal; + int *NumCells; + int TotalNumCells; + + // local share of points to be partitioned, and local cache + + int WhoHas(int pos); + int _whoHas(int L, int R, int pos); + float *GetLocalVal(int pos); + float *GetLocalValNext(int pos); + void SetLocalVal(int pos, float *val); + void ExchangeVals(int pos1, int pos2); + void ExchangeLocalVals(int pos1, int pos2); + + float *PtArray; + float *PtArray2; + float *CurrentPtArray; + float *NextPtArray; + int PtArraySize; + + int *SelectBuffer; + + // Parallel build of k-d tree + + int AllCheckForFailure(int rc, const char *where, const char *how); + void AllCheckParameters(); + double *VolumeBounds(); + int DivideRegion(vtkKdNode *kd, int L, int level, int tag); + int BreadthFirstDivide(double *bounds); + void enQueueNode(vtkKdNode *kd, int L, int level, int tag); + + int Select(int dim, int L, int R); + void _select(int L, int R, int K, int dim); + void DoTransfer(int from, int to, int fromIndex, int toIndex, int count); + + int *PartitionAboutMyValue(int L, int R, int K, int dim); + int *PartitionAboutOtherValue(int L, int R, float T, int dim); + int *PartitionSubArray(int L, int R, int K, int dim, int p1, int p2); + + int CompleteTree(); +#ifdef YIELDS_INCONSISTENT_REGION_BOUNDARIES + void RetrieveData(vtkKdNode *kd, int *buf); +#else + void ReduceData(vtkKdNode *kd, int *sources); + void BroadcastData(vtkKdNode *kd); +#endif + + float *DataBounds(int L, int K, int R); + void GetLocalMinMax(int L, int R, int me, float *min, float *max); + + static int FillOutTree(vtkKdNode *kd, int level); + static int ComputeDepth(vtkKdNode *kd); + static void PackData(vtkKdNode *kd, double *data); + static void UnpackData(vtkKdNode *kd, double *data); + static void CheckFixRegionBoundaries(vtkKdNode *tree); + + // list management + + int AllocateDoubleBuffer(); + void FreeDoubleBuffer(); + void SwitchDoubleBuffer(); + int AllocateSelectBuffer(); + void FreeSelectBuffer(); + + void InitializeGlobalIndexLists(); + int AllocateAndZeroGlobalIndexLists(); + void FreeGlobalIndexLists(); + void InitializeRegionAssignmentLists(); + int AllocateAndZeroRegionAssignmentLists(); + void FreeRegionAssignmentLists(); + void InitializeProcessDataLists(); + int AllocateAndZeroProcessDataLists(); + void FreeProcessDataLists(); + void InitializeFieldArrayMinMax(); + int AllocateAndZeroFieldArrayMinMax(); + void FreeFieldArrayMinMax(); + + void ReleaseTables(); + + // Assigning regions to processors + + void AddProcessRegions(int procId, vtkKdNode *kd); + void BuildRegionListsForProcesses(); + + // Gather process/region data totals + + int *CollectLocalRegionProcessData(); + int BuildRegionProcessTables(); + int BuildFieldArrayMinMax(); + void AddEntry(int *list, int len, int id); + static int BinarySearch(int *list, int len, int which); + + static int FindNextLocalArrayIndex(const char *n, const char **names, int len, int start=0); + + vtkPKdTree(const vtkPKdTree&); // Not implemented + void operator=(const vtkPKdTree&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkPLinearExtrusionFilter.cxx b/Parallel/vtkPLinearExtrusionFilter.cxx new file mode 100644 index 0000000..6b64c9f --- /dev/null +++ b/Parallel/vtkPLinearExtrusionFilter.cxx @@ -0,0 +1,101 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLinearExtrusionFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPLinearExtrusionFilter.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPLinearExtrusionFilter, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkPLinearExtrusionFilter); + +//---------------------------------------------------------------------------- +vtkPLinearExtrusionFilter::vtkPLinearExtrusionFilter() +{ + // Since I do not thing the visual impact of invariance is significant, + // we will default to not spend the extra effort to get the + // extra layer of ghost cells. + this->PieceInvariant = 0; +} + +//---------------------------------------------------------------------------- +int vtkPLinearExtrusionFilter::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (!this->vtkLinearExtrusionFilter::RequestData(request, + inputVector, outputVector)) + { + return 0; + } + + if (this->PieceInvariant) + { + output->RemoveGhostCells( + outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())+1); + } + + return 1; +} + +//-------------------------------------------------------------------------- +int vtkPLinearExtrusionFilter::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + + int ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + if (this->PieceInvariant) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel + 1); + } + else + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPLinearExtrusionFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PieceInvariant: " + << this->PieceInvariant << "\n"; +} diff --git a/Parallel/vtkPLinearExtrusionFilter.h b/Parallel/vtkPLinearExtrusionFilter.h new file mode 100644 index 0000000..fb4b8f5 --- /dev/null +++ b/Parallel/vtkPLinearExtrusionFilter.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPLinearExtrusionFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPLinearExtrusionFilter - Subclass that handles piece invariance. +// .SECTION Description +// vtkPLinearExtrusionFilter is a parallel version of vtkLinearExtrusionFilter. + +// .SECTION See Also +// vtkLinearExtrusionFilter + +#ifndef __vtkPLinearExtrusionFilter_h +#define __vtkPLinearExtrusionFilter_h + +#include "vtkLinearExtrusionFilter.h" + +class VTK_PARALLEL_EXPORT vtkPLinearExtrusionFilter : public vtkLinearExtrusionFilter +{ +public: + vtkTypeRevisionMacro(vtkPLinearExtrusionFilter,vtkLinearExtrusionFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create an object with PieceInvariant off. + static vtkPLinearExtrusionFilter *New(); + + // To get piece invariance, this filter has to request an + // extra ghost level. Since piece invariance is not very + // important for this filter, it is optional. Without invariance, + // Internal surfaces will be generated. These surface + // Are hidden by the normal surface generated by this filter. + // By default, PieceInvariance is off. + vtkSetMacro(PieceInvariant, int); + vtkGetMacro(PieceInvariant, int); + vtkBooleanMacro(PieceInvariant, int); + +protected: + vtkPLinearExtrusionFilter(); + ~vtkPLinearExtrusionFilter() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int PieceInvariant; +private: + vtkPLinearExtrusionFilter(const vtkPLinearExtrusionFilter&); // Not implemented. + void operator=(const vtkPLinearExtrusionFilter&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPOPReader.cxx b/Parallel/vtkPOPReader.cxx new file mode 100644 index 0000000..424218a --- /dev/null +++ b/Parallel/vtkPOPReader.cxx @@ -0,0 +1,991 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPOPReader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPOPReader.h" + +#include "vtkExtentTranslator.h" +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkImageReader.h" +#include "vtkImageWrapPad.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkSmartPointer.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkStructuredGrid.h" + +#include +#include + +vtkCxxRevisionMacro(vtkPOPReader, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkPOPReader); + +//---------------------------------------------------------------------------- +vtkPOPReader::vtkPOPReader() +{ + this->Radius = 60000.0; + + this->Dimensions[0] = 3600; + this->Dimensions[1] = 2400; + + this->GridFileName = NULL; + this->FileName = NULL; + + this->NumberOfArrays = 0; + this->MaximumNumberOfArrays = 0; + this->ArrayNames = NULL; + this->ArrayFileNames = NULL; + this->ArrayOffsets = NULL; + this->ArrayFileDimensionality = 3; + + this->UFlowFileName = NULL; + this->UFlowFileOffset = 0; + this->VFlowFileName = NULL; + this->VFlowFileOffset = 0; + + this->DepthValues = vtkFloatArray::New(); + + this->ClipExtent[0] = -VTK_LARGE_INTEGER; + this->ClipExtent[1] = VTK_LARGE_INTEGER; + this->ClipExtent[2] = -VTK_LARGE_INTEGER; + this->ClipExtent[3] = VTK_LARGE_INTEGER; + this->ClipExtent[4] = -VTK_LARGE_INTEGER; + this->ClipExtent[5] = VTK_LARGE_INTEGER; + + this->NumberOfGhostLevels = 1; + + this->SetNumberOfInputPorts(0); +} + +//---------------------------------------------------------------------------- +vtkPOPReader::~vtkPOPReader() +{ + this->SetFileName(NULL); + this->SetGridFileName(NULL); + this->DeleteArrays(); + + this->DepthValues->Delete(); + this->DepthValues = NULL; +} + +//---------------------------------------------------------------------------- +void vtkPOPReader::DeleteArrays() +{ + int i; + + for (i = 0; i < this->NumberOfArrays; ++i) + { + if (this->ArrayNames && this->ArrayNames[i]) + { + delete [] this->ArrayNames[i]; + this->ArrayNames[i] = NULL; + } + if (this->ArrayFileNames && this->ArrayFileNames[i]) + { + delete [] this->ArrayFileNames[i]; + this->ArrayFileNames[i] = NULL; + } + } + if (this->ArrayNames) + { + delete [] this->ArrayNames; + this->ArrayNames = NULL; + } + if (this->ArrayFileNames) + { + delete [] this->ArrayFileNames; + this->ArrayFileNames = NULL; + } + if (this->ArrayOffsets) + { + delete [] this->ArrayOffsets; + this->ArrayOffsets = NULL; + } + + this->NumberOfArrays = 0; + this->MaximumNumberOfArrays = 0; +} + +//---------------------------------------------------------------------------- +void vtkPOPReader::AddArray(char *arrayName, char *fileName, unsigned long offset) +{ + if (this->NumberOfArrays == this->MaximumNumberOfArrays) + { + int idx; + char **tmp1, **tmp2; + unsigned long *tmp3; + + this->MaximumNumberOfArrays += 20; + tmp1 = new char*[this->MaximumNumberOfArrays]; + tmp2 = new char*[this->MaximumNumberOfArrays]; + tmp3 = new unsigned long[this->MaximumNumberOfArrays]; + for (idx = 0; idx < this->NumberOfArrays; ++idx) + { + tmp1[idx] = this->ArrayNames[idx]; + tmp2[idx] = this->ArrayFileNames[idx]; + tmp3[idx] = this->ArrayOffsets[idx]; + } + delete [] this->ArrayNames; + this->ArrayNames = tmp1; + delete [] this->ArrayFileNames; + this->ArrayFileNames = tmp2; + delete [] this->ArrayOffsets; + this->ArrayOffsets = tmp3; + } + + this->ArrayNames[this->NumberOfArrays] = new char[strlen(arrayName)+1]; + strcpy(this->ArrayNames[this->NumberOfArrays], arrayName); + + this->ArrayFileNames[this->NumberOfArrays] = new char[strlen(fileName)+1]; + strcpy(this->ArrayFileNames[this->NumberOfArrays], fileName); + + this->ArrayOffsets[this->NumberOfArrays] = offset; + + ++this->NumberOfArrays; +} + +//---------------------------------------------------------------------------- +int vtkPOPReader::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int xDim, yDim, zDim; + + this->ReadInformationFile(); + + xDim = this->Dimensions[0]+1; + yDim = this->Dimensions[1]; + zDim = this->DepthValues->GetNumberOfTuples(); + + // Clip should be no larger than the whole extent. + if (this->ClipExtent[0] < 0 || + this->ClipExtent[0] - this->NumberOfGhostLevels < 0) + { + this->ClipExtent[0] = 0; + } + else + { + this->ClipExtent[0] -= this->NumberOfGhostLevels; + } + if (this->ClipExtent[2] < this->NumberOfGhostLevels) + { + this->ClipExtent[2] = 0; + } + else + { + this->ClipExtent[2] -= this->NumberOfGhostLevels; + } + if (this->ClipExtent[4] < this->NumberOfGhostLevels) + { + this->ClipExtent[4] = 0; + } + else + { + this->ClipExtent[4] -= this->NumberOfGhostLevels; + } + if (this->ClipExtent[1] > xDim-1 - this->NumberOfGhostLevels) + { + this->ClipExtent[1] = xDim-1; + } + else + { + this->ClipExtent[1] += this->NumberOfGhostLevels; + } + if (this->ClipExtent[3] > yDim-1 - this->NumberOfGhostLevels) + { + this->ClipExtent[3] = yDim-1; + } + else + { + this->ClipExtent[3] += this->NumberOfGhostLevels; + } + if (this->ClipExtent[5] > zDim-1 - this->NumberOfGhostLevels) + { + this->ClipExtent[5] = zDim-1; + } + else + { + this->ClipExtent[5] += this->NumberOfGhostLevels; + } + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->ClipExtent, 6); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPOPReader::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkPoints *points; + vtkImageData *image; + vtkDataArray *array; + int ext[6]; + int i; + + // the input file is not set then return + if (!this->GridFileName || this->GridFileName[0] == '\0') + { + return 0; + } + + // Set up the extent of the grid image. + ext[0] = ext[2] = ext[4] = 0; + ext[1] = this->Dimensions[0]-1; + ext[3] = this->Dimensions[1]-1; + ext[5] = 1; + + vtkImageReader *reader = vtkImageReader::New(); + reader->SetFileDimensionality(3); + reader->SetDataExtent(ext); + reader->SetFileName(this->GridFileName); + reader->SetDataByteOrderToBigEndian(); + reader->SetNumberOfScalarComponents(1); + reader->SetDataScalarTypeToDouble(); + reader->SetHeaderSize(0); + vtkImageWrapPad *wrap = vtkImageWrapPad::New(); + wrap->SetInput(reader->GetOutput()); + ++ext[1]; + wrap->SetOutputWholeExtent(ext); + + image = wrap->GetOutput(); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext); + output->SetExtent(ext); + ext[4] = 0; + ext[5] = 1; + image->SetUpdateExtent(ext); + image->Update(); + + // Create the grid points from the grid image. + points = this->ReadPoints(image, outInfo); + output->SetPoints(points); + points->Delete(); + points = NULL; + + // Now read in the arrays. + // Set up the extent of the grid image. + ext[0] = ext[2] = ext[4] = 0; + ext[1] = this->Dimensions[0]-1; + ext[3] = this->Dimensions[1]-1; + ext[5] = this->DepthValues->GetNumberOfTuples()-1; + reader->SetDataExtent(ext); + reader->SetDataScalarTypeToFloat(); + reader->SetFileDimensionality(this->ArrayFileDimensionality); + ++ext[1]; + wrap->SetOutputWholeExtent(ext); + for (i = 0; i < this->NumberOfArrays; ++i) + { + if (this->ArrayFileNames[i] && this->ArrayNames[i]) + { + if (this->ArrayFileDimensionality == 3) + { + reader->SetFileName(this->ArrayFileNames[i]); + } + else if (this->ArrayFileDimensionality == 2) + { + reader->SetFilePattern("%s.%02d"); + reader->SetFilePrefix(this->ArrayFileNames[i]); + } + else + { + vtkErrorMacro("FileDimensionality can only be 2 or 3."); + reader->Delete(); + wrap->Delete(); + return 1; + } + reader->SetHeaderSize(this->ArrayOffsets[i] * 4 + * this->Dimensions[0] * this->Dimensions[1]); + // Just in case. + //reader->SetHeaderSize(0); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext); + image = wrap->GetOutput(); + image->SetUpdateExtent(ext); + image->Update(); + array = image->GetPointData()->GetScalars(); + array->SetName(this->ArrayNames[i]); + + output->GetPointData()->AddArray(array); + image->ReleaseData(); + } + } + reader->Delete(); + reader = NULL; + wrap->Delete(); + wrap = NULL; + + // If there is flow defined. + this->ReadFlow(output, outInfo); + + return 1; +} + +//---------------------------------------------------------------------------- +vtkPoints *vtkPOPReader::GeneratePoints() +{ + /* + vtkPoints *points; + vtkImageData *temp; + double x, y, z, radius; + double theta, phi; + int i, j; + int *wholeExt; + int xDim, yDim; + int *ext; + int id; + + //temp = this->GetInput(); + wholeExt = temp->GetWholeExtent(); + if (wholeExt[0] != 0 || wholeExt[2] != 0 || wholeExt[4] != 0) + { + vtkErrorMacro("Expecting whole extent to start at 0."); + return NULL; + } + xDim = wholeExt[1]+1; + yDim = wholeExt[3]+1; + ext = temp->GetExtent(); + + points = vtkPoints::New(); + points->Allocate(xDim*yDim); + id = 0; + radius = 20000.0; + for (j = ext[2]; j <= ext[3]; ++j) + { + phi = (double)j * vtkMath::Pi() / (double)(yDim); + for (i = ext[0]; i <= ext[1]; ++i) + { + theta = (double)i * 2.0 * vtkMath::Pi() / (double)(xDim); + y = cos(phi)*radius; + x = sin(theta)*sin(phi)*radius; + z = cos(theta)*sin(phi)*radius; + points->SetPoint(id, x, y, z); + ++id; + } + } + + return points; + */ + return NULL; +} + + + + +//---------------------------------------------------------------------------- +vtkPoints *vtkPOPReader::ReadPoints(vtkImageData *image, + vtkInformation *outInfo) +{ + vtkPoints *points; + double x, y, z, depth, radius; + double theta, phi; + int i, j, k; + int id, num; + + // The only different between these two is the z extent. We should + // probably ditch ext and user update extent to make things simpler. + int *updateExt = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT()); + int *ext = image->GetExtent(); + + points = vtkPoints::New(); + num = (ext[1]-ext[0]+1)*(ext[3]-ext[2]+1)*(updateExt[5]-updateExt[4]+1); + points->Allocate(num); + points->SetNumberOfPoints(num); + + id = 0; + for (k = updateExt[4]; k <= updateExt[5]; ++k) + { + depth = this->DepthValues->GetValue(k); + radius = this->Radius - depth; + for (j = ext[2]; j <= ext[3]; ++j) + { + for (i = ext[0]; i <= ext[1]; ++i) + { + phi = image->GetScalarComponentAsDouble(i, j, 0, 0); + theta = image->GetScalarComponentAsDouble(i, j, 1, 0); + phi += vtkMath::Pi()/2.0; + y = -cos(phi)*radius; + x = sin(theta)*sin(phi)*radius; + z = cos(theta)*sin(phi)*radius; + points->SetPoint(id, x, y, z); + ++id; + } + } + } + + return points; +} + + +//==================== Stuff for reading the pop file ======================== + + + +//---------------------------------------------------------------------------- +void vtkPOPReader::ReadInformationFile() +{ + ifstream *file; + int i=0, num; + float tempf; + char str[256]; + + this->DeleteArrays(); + this->DepthValues->Reset(); + this->SetUFlowFileName(NULL); + this->SetVFlowFileName(NULL); + this->UFlowFileOffset = this->VFlowFileOffset = 0; + if(!this->FileName) + { + return; + } + file = new ifstream(this->FileName, ios::in); + + while (1) + { + // Read Key + *file >> str; + if (file->fail()) + { + file->close(); + delete file; + return; + } + + if (strcmp(str, "Dimensions") == 0) + { + *file >> num; + this->Dimensions[0] = num; + *file >> num; + this->Dimensions[1] = num; + } + + else if (strcmp(str, "GridFileName") == 0) + { + *file >> str; + this->SetGridName(str); + } + + else if (strcmp(str, "NumberOfArrays") == 0) + { + char str2[256]; + unsigned long offset; + *file >> num; + for (i = 0; i < num; ++i) + { + *file >> str; + *file >> str2; + *file >> offset; + if (file->fail()) + { + vtkErrorMacro("Error reading array name " << i); + delete file; + return; + } + this->AddArrayName(str, str2, offset); + } + } + + else if (strcmp(str, "ArrayFileDimensionality") == 0) + { + *file >> num; + if (file->fail()) + { + vtkErrorMacro("Error reading array name " << i); + delete file; + return; + } + this->ArrayFileDimensionality = num; + } + + else if (strcmp(str, "Flow") == 0) + { + char *tmp = NULL; + char str2[256]; + unsigned long offset; + *file >> num; + for (i = 0; i < num; ++i) + { + *file >> str; + *file >> str2; + *file >> offset; + + if (file->fail()) + { + vtkErrorMacro("Error reading flow component " << i); + delete file; + return; + } + + if (strcmp(str,"u") == 0) + { + if (str2[0] != '/' && str2[1] != ':') + { + tmp = this->MakeFileName(str2); + this->SetUFlowFileName(tmp); + delete [] tmp; + } + else + { + this->SetUFlowFileName(str2); + } + this->UFlowFileOffset = offset; + } + else if (strcmp(str,"v") == 0) + { + if (str2[0] != '/' && str2[1] != ':') + { + tmp = this->MakeFileName(str2); + this->SetVFlowFileName(tmp); + delete [] tmp; + } + else + { + this->SetVFlowFileName(str2); + } + this->VFlowFileOffset = offset; + } + } + } + + else if (strcmp(str, "NumberOfDepthValues") == 0) + { + *file >> num; + for (i = 0; i < num; ++i) + { + *file >> str; + if (file->fail()) + { + vtkErrorMacro("Error reading depth value " << i); + delete file; + return; + } + tempf = atof(str); + this->DepthValues->InsertNextValue(tempf); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkPOPReader::SetGridName(char *name) +{ + if (name[0] == '/' || name[1] == ':') + { + this->SetGridFileName(name); + return; + } + + char *tmp; + + tmp = this->MakeFileName(name); + this->SetGridFileName(tmp); + delete [] tmp; +} + +//---------------------------------------------------------------------------- +// This will append the full path onto the file name. (using the grid path/ +void vtkPOPReader::AddArrayName(char *name, char *fileName, unsigned long offset) +{ + char *tmp; + + if (fileName[0] == '/' || fileName[1] == ':') + { + this->AddArray(name, fileName, offset); + return; + } + + tmp = this->MakeFileName(fileName); + this->AddArray(name, tmp, offset); + delete [] tmp; +} + +//---------------------------------------------------------------------------- +int vtkPOPReader::IsFileName(char *name) +{ + while (name && *name) + { + if (*name == '/') + { + return 1; + } + ++name; + } + + return 0; +} + +//---------------------------------------------------------------------------- +char *vtkPOPReader::MakeFileName(char *name) +{ + char *fileName; + char *tmp1; + char *tmp2; + char *start; + + if (name == NULL) + { + vtkErrorMacro("No name."); + return NULL; + } + + if (this->FileName == NULL) + { + fileName = new char[strlen(name) + 1]; + strcpy(fileName, name); + return fileName; + } + + fileName = new char[strlen(this->FileName) + strlen(name) + 1]; + tmp1 = this->FileName; + tmp2 = fileName; + start = fileName; + while (tmp1 && *tmp1) + { + *tmp2 = *tmp1; + if (*tmp1 == '/') + { + start = tmp2+1; + } + ++tmp1; + ++tmp2; + } + + strcpy(start, name); + + return fileName; +} + + + +//---------------------------------------------------------------------------- +void vtkPOPReader::ReadFlow(vtkStructuredGrid *output, + vtkInformation *outInfo) +{ + vtkDataArray *array; + vtkImageData *fImage; + int updateExt[6], wholeExt[6], ext[6]; + int idx, u, v, w; + float *pf, *pu, *pv; + float v0, v2, w0, u0, u2; + float du, dv, dw; + int uvInc0, uvInc1, uvInc2; + int vMin, vMax; + vtkPoints *pts; + float *pp; + int pfInc1, pfInc2; + float nv[3], axisW[3], axisV[3], axisU[3]; + float tmp; + + if (this->UFlowFileName == NULL || this->VFlowFileName == NULL) + { + return; + } + + pts = output->GetPoints(); + + ext[0] = ext[2] = ext[4] = 0; + ext[1] = this->Dimensions[0]-1; + ext[3] = this->Dimensions[1]-1; + ext[5] = this->DepthValues->GetNumberOfTuples()-1; + + vtkImageReader *reader = vtkImageReader::New(); + reader->SetFileDimensionality(this->ArrayFileDimensionality); + reader->SetDataExtent(ext); + reader->SetDataByteOrderToBigEndian(); + reader->SetNumberOfScalarComponents(1); + reader->SetDataScalarTypeToFloat(); + reader->SetHeaderSize(0); + vtkImageWrapPad *wrap = vtkImageWrapPad::New(); + wrap->SetInput(reader->GetOutput()); + // To complete the last row (shared with the first row). + ++ext[1]; + // We will need ghost cells. Poles are discontinuities. + // U is cyclical + --ext[0]; + ++ext[1]; + wrap->SetOutputWholeExtent(ext); + + // Figure out what extent we need for the request. + wrap->GetOutputWholeExtent(wholeExt); + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), updateExt); + if (wholeExt[5] != updateExt[5]) + { + vtkErrorMacro("Requested extent does not have bottom slice required for correct completion of the flow vectors."); + } + + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), ext); + for (idx = 0; idx < 3; ++idx) + { + --ext[idx*2]; + ++ext[idx*2+1]; + if (ext[idx*2] < wholeExt[idx*2]) + { + ext[idx*2] = wholeExt[idx*2]; + } + if (ext[idx*2+1] > wholeExt[idx*2+1]) + { + ext[idx*2+1] = wholeExt[idx*2+1]; + } + } + + // Set up the reader with the appropriate filename. + if (this->ArrayFileDimensionality == 3) + { + reader->SetFileName(this->UFlowFileName); + } + else if (this->ArrayFileDimensionality == 2) + { + reader->SetFilePattern("%s.%02d"); + reader->SetFilePrefix(this->UFlowFileName); + } + else + { + vtkErrorMacro("FileDimensionality can only be 2 or 3."); + reader->Delete(); + wrap->Delete(); + return; + } + reader->SetHeaderSize(this->UFlowFileOffset * 4 + * this->Dimensions[0] * this->Dimensions[1]); + + wrap->GetOutput()->SetSource(0); + vtkSmartPointer uImage = wrap->GetOutput(); + uImage->SetUpdateExtent(ext); + uImage->Update(); + + // Set up the reader with the appropriate filename. + if (this->ArrayFileDimensionality == 3) + { + reader->SetFileName(this->VFlowFileName); + } + else if (this->ArrayFileDimensionality == 2) + { + reader->SetFilePattern("%s.%02d"); + reader->SetFilePrefix(this->VFlowFileName); + } + else + { + vtkErrorMacro("FileDimensionality can only be 2 or 3."); + reader->Delete(); + wrap->Delete(); + return; + } + reader->SetHeaderSize(this->VFlowFileOffset * 4 + * this->Dimensions[0] * this->Dimensions[1]); + wrap->GetOutput()->SetSource(0); + vtkSmartPointer vImage = wrap->GetOutput(); + vImage->SetUpdateExtent(ext); + vImage->Update(); + + uvInc0 = 1; + uvInc1 = ext[1]-ext[0]+1; + uvInc2 = uvInc1 * (ext[3]-ext[2]+1); + vMin = ext[2]; + vMax = ext[3]; + + reader->Delete(); + reader = NULL; + wrap->Delete(); + wrap = NULL; + + fImage = vtkImageData::New(); + fImage->SetExtent(updateExt); + fImage->SetNumberOfScalarComponents(3); + fImage->SetScalarType(VTK_FLOAT); + fImage->AllocateScalars(); + + pfInc1 = 3*(updateExt[1]-updateExt[0]+1); + pfInc2 = (updateExt[1]-updateExt[0]+1)*(updateExt[3]-updateExt[2]+1)*3; + + // Central differences is good, but I do not like it for the + // z/propagation direction (alternation). Normal difference + // produces a shift. As a start, I will use it any way. + // I could always average the top and bottom versions... + + // Now do the computation from bottom to top. + // Since dw is uniform across a level, forget about traversing the points + // back to front. Just do the first slice always. + pp = vtkFloatArray::SafeDownCast(pts)->GetPointer(0); + for (v = updateExt[2]; v <= updateExt[3]; ++v) + { + for (u = updateExt[0]; u <= updateExt[1]; ++u) + { + // Loose a little efficiency here, but ... + pf = (float*)fImage->GetScalarPointer(u, v, updateExt[5]); + pu = (float*)uImage->GetScalarPointer(u, v, updateExt[5]); + pv = (float*)vImage->GetScalarPointer(u, v, updateExt[5]); + // Find the coordinate transform (and deltas as a side effect). + // Except for dw, these are constant up a column. + // W is just the noramlize vector 0->p. + axisW[0] = pp[0]; + axisW[1] = pp[1]; + axisW[2] = pp[2]; + vtkMath::Normalize(axisW); + // Ignore curvature of earth surface. Handle boundaries. + if (v == updateExt[2]) + { + axisV[0] = pp[0] - pp[pfInc1]; + axisV[1] = pp[1] - pp[1+pfInc1]; + axisV[2] = pp[2] - pp[2+pfInc1]; + } + else + { + axisV[0] = pp[-pfInc1] - pp[0]; + axisV[1] = pp[1-pfInc1] - pp[1]; + axisV[2] = pp[2-pfInc1] - pp[2]; + } + dv = vtkMath::Normalize(axisV); + // Last U axis. + if (u == updateExt[0]) + { + axisU[0] = pp[3] - pp[0]; + axisU[1] = pp[4] - pp[1]; + axisU[2] = pp[5] - pp[2]; + } + else + { + axisU[0] = pp[0] - pp[-3]; + axisU[1] = pp[1] - pp[-2]; + axisU[2] = pp[2] - pp[-1]; + } + du = vtkMath::Normalize(axisU); + + // Since the points are not used in the inner most loop, + // move to the next point here. + pp += 3; + + // Now sum the w flow up the column. + w0 = 0.0; + for (w = updateExt[5]; w >= updateExt[4]; --w) + { + // Find dw (easy because we have the depth values in an array). + if (w == 0) + { + if (this->DepthValues->GetNumberOfTuples() <= 1) + { + dw = 0.0; + } + else + { + dw = this->DepthValues->GetValue(1) - this->DepthValues->GetValue(0); + } + } + else + { + dw = this->DepthValues->GetValue(w) - this->DepthValues->GetValue(w-1); + } + + // Compute w componenet of flow ... + // Find the five important values for this point (have w0 already). + // U is circular so does not have boundary checks. + v0 = v2 = 0.0; + u0 = pu[-uvInc0]; + u2 = pu[uvInc0]; + if (v < vMax) + { + v0 = pv[uvInc1]; + } + if (v > vMin) + { + v2 = pv[-uvInc1]; + } + + // Now fill the vector for this point (uvw coords). + pf[0] = *pu; // i.e. u1 + pf[1] = *pv; // i.e. v1 + tmp = 0.5 * (((u0-u2)*dv*dw + (v0-v2)*du*dw)/(du*dv)); + pf[2] = w0 + tmp; + //pf[2] = 0.0; + + // Before we transform and loose w1, + // save it for summing in the next iteration. + w0 = pf[2]; + + // Now compute the vector in the new coordinate system. + nv[0] = axisU[0]*pf[0] + axisV[0]*pf[1] + axisW[0]*pf[2]; + nv[1] = axisU[1]*pf[0] + axisV[1]*pf[1] + axisW[1]*pf[2]; + nv[2] = axisU[2]*pf[0] + axisV[2]*pf[1] + axisW[2]*pf[2]; + pf[0] = nv[0]; + pf[1] = nv[1]; + pf[2] = nv[2]; + + // Move up the column to the next point. + pf -= pfInc2; + pu -= uvInc2; + pv -= uvInc2; + } + } + } + + array = fImage->GetPointData()->GetScalars(); + array->SetName("Flow"); + + output->GetPointData()->AddArray(array); + fImage->ReleaseData(); + fImage->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkPOPReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->FileName) + { + os << indent << "FileName: " << this->FileName << endl; + } + if (this->GridFileName) + { + os << indent << "GridFileName: " << this->GridFileName << endl; + } + + if (this->UFlowFileName) + { + os << indent << "UFlowFileName: " << this->UFlowFileName << endl; + } + if (this->VFlowFileName) + { + os << indent << "VFlowFileName: " << this->VFlowFileName << endl; + } + + os << indent << "Dimensions: " << this->Dimensions[0] << ", " + << this->Dimensions[1] << endl; + + os << indent << "Radius: " << this->Radius << endl; + + os << indent << "ClipExtent: " << this->ClipExtent[0] << ", " + << this->ClipExtent[1] << ", " << this->ClipExtent[2] << ", " + << this->ClipExtent[3] << ", " << this->ClipExtent[4] << ", " + << this->ClipExtent[5] << endl; + + os << indent << "NumberOfGhostLevels = " << this->NumberOfGhostLevels << endl; + +} + diff --git a/Parallel/vtkPOPReader.h b/Parallel/vtkPOPReader.h new file mode 100644 index 0000000..b63b15e --- /dev/null +++ b/Parallel/vtkPOPReader.h @@ -0,0 +1,121 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPOPReader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPOPReader - read POP data files +// .SECTION Description +// vtkPOPReader Just converts from images to a structured grid for now. + + +#ifndef __vtkPOPReader_h +#define __vtkPOPReader_h + +#include "vtkStructuredGridAlgorithm.h" + +class vtkFloatArray; +class vtkImageData; +class vtkPoints; + +class VTK_PARALLEL_EXPORT vtkPOPReader : public vtkStructuredGridAlgorithm +{ +public: + static vtkPOPReader *New(); + vtkTypeRevisionMacro(vtkPOPReader,vtkStructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is the longitude and latitude dimensions of the structured grid. + vtkGetVector2Macro(Dimensions, int); + + // Description: + // This file contains the latitude and longitude of the grid. + // It must be double with no header. + vtkGetStringMacro(GridFileName); + + // Description: + // These files contains the u and v components of the flow. + vtkGetStringMacro(UFlowFileName); + vtkGetStringMacro(VFlowFileName); + + // Description: + // This file contains information about all the files. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Radius of the earth. + vtkSetMacro(Radius, double); + vtkGetMacro(Radius, double); + + // Description: + // Because the data can be so large, here is an option to clip + // while reading. + vtkSetVector6Macro(ClipExtent, int); + vtkGetVector6Macro(ClipExtent, int); + + // Description: + // Set the number of ghost levels to include in the data + vtkSetMacro(NumberOfGhostLevels, int); + vtkGetMacro(NumberOfGhostLevels, int); + +protected: + vtkPOPReader(); + ~vtkPOPReader(); + + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + void ReadInformationFile(); + vtkPoints *ReadPoints(vtkImageData *image, vtkInformation *outInfo); + void ReadFlow(vtkStructuredGrid *output, vtkInformation *outInfo); + // NOT USED + vtkPoints *GeneratePoints(); + + char *FileName; + + int Dimensions[2]; + vtkSetStringMacro(GridFileName); + void SetGridName(char *name); + char *GridFileName; + + double Radius; + vtkFloatArray *DepthValues; + int NumberOfGhostLevels; + + void DeleteArrays(); + void AddArray(char *arrayName, char *fileName, unsigned long offset); + void AddArrayName(char *arrayName, char *fileName, unsigned long offset); + int NumberOfArrays; + int MaximumNumberOfArrays; + char **ArrayNames; + char **ArrayFileNames; + unsigned long *ArrayOffsets; + int ArrayFileDimensionality; + + char *UFlowFileName; + vtkSetStringMacro(UFlowFileName); + unsigned long UFlowFileOffset; + char *VFlowFileName; + vtkSetStringMacro(VFlowFileName); + unsigned long VFlowFileOffset; + + int IsFileName(char *name); + char *MakeFileName(char *name); + + int ClipExtent[6]; + + vtkPOPReader(const vtkPOPReader&); // Not implemented + void operator=(const vtkPOPReader&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkPOutlineCornerFilter.cxx b/Parallel/vtkPOutlineCornerFilter.cxx new file mode 100644 index 0000000..6b6b0cc --- /dev/null +++ b/Parallel/vtkPOutlineCornerFilter.cxx @@ -0,0 +1,177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPOutlineCornerFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPOutlineCornerFilter.h" + +#include "vtkCompositeDataSet.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationDataObjectKey.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineCornerSource.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPOutlineCornerFilter, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkPOutlineCornerFilter); +vtkCxxSetObjectMacro(vtkPOutlineCornerFilter, Controller, vtkMultiProcessController); + +vtkPOutlineCornerFilter::vtkPOutlineCornerFilter () +{ + this->Controller = 0; + this->SetController(vtkMultiProcessController::GetGlobalController()); + this->CornerFactor = 0.2; + this->OutlineCornerSource = vtkOutlineCornerSource::New(); +} + +vtkPOutlineCornerFilter::~vtkPOutlineCornerFilter () +{ + this->SetController(0); + if (this->OutlineCornerSource != NULL) + { + this->OutlineCornerSource->Delete (); + this->OutlineCornerSource = NULL; + } +} + +int vtkPOutlineCornerFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double bds[6]; + + if ( !this->Controller ) + { + vtkErrorMacro("Controller not set"); + return 0; + } + + int doCommunicate = 1; + + // If there is a composite dataset in the input, the request is + // coming from a vtkCompositeDataPipeline and interprocess communication + // is not necessary (simple datasets are not broken into pieces) + vtkCompositeDataSet* cds = vtkCompositeDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (cds) + { + doCommunicate = 0; + } + + input->GetBounds(bds); + //cerr << "Bounds: " << bds[0] << ", " << bds[1] << ", " + //<< bds[2] << ", " << bds[3] << ", " + //<< bds[4] << ", " << bds[5] << endl; + + int procid = this->Controller->GetLocalProcessId(); + + if (doCommunicate) + { + if ( procid ) + { + // Satellite node + this->Controller->Send(bds, 6, 0, 792390); + } + else + { + int numProcs = this->Controller->GetNumberOfProcesses(); + int idx; + double tmp[6]; + + for (idx = 1; idx < numProcs; ++idx) + { + this->Controller->Receive(tmp, 6, idx, 792390); + + if (tmp[0] < bds[0]) + { + bds[0] = tmp[0]; + } + if (tmp[1] > bds[1]) + { + bds[1] = tmp[1]; + } + if (tmp[2] < bds[2]) + { + bds[2] = tmp[2]; + } + if (tmp[3] > bds[3]) + { + bds[3] = tmp[3]; + } + if (tmp[4] < bds[4]) + { + bds[4] = tmp[4]; + } + if (tmp[5] > bds[5]) + { + bds[5] = tmp[5]; + } + } + } + } + + if (!doCommunicate || procid == 0) + { + if (vtkMath::AreBoundsInitialized(bds)) + { + // only output in process 0. + this->OutlineCornerSource->SetBounds(bds); + this->OutlineCornerSource->SetCornerFactor(this->GetCornerFactor()); + this->OutlineCornerSource->Update(); + output->CopyStructure(this->OutlineCornerSource->GetOutput()); + } + } + + return 1; +} + +int vtkPOutlineCornerFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + return 1; +} + +int vtkPOutlineCornerFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkPOutlineCornerFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "CornerFactor: " << this->CornerFactor << "\n"; + os << indent << "Controller: " << this->Controller << endl; +} diff --git a/Parallel/vtkPOutlineCornerFilter.h b/Parallel/vtkPOutlineCornerFilter.h new file mode 100644 index 0000000..1a99376 --- /dev/null +++ b/Parallel/vtkPOutlineCornerFilter.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPOutlineCornerFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPOutlineCornerFilter - create wireframe outline corners for arbitrary data set +// .SECTION Description +// vtkPOutlineCornerFilter works like vtkOutlineCornerFilter, +// but it looks for data +// partitions in other processes. It assumes the filter is operated +// in a data parallel pipeline. + + + +#ifndef __vtkPOutlineCornerFilter_h +#define __vtkPOutlineCornerFilter_h + +#include "vtkPolyDataAlgorithm.h" +class vtkOutlineCornerSource; +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkPOutlineCornerFilter : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkPOutlineCornerFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct outline corner filter with default corner factor = 0.2 + static vtkPOutlineCornerFilter *New(); + + // Description: + // Set/Get the factor that controls the relative size of the corners + // to the length of the corresponding bounds + vtkSetClampMacro(CornerFactor, double, 0.001, 0.5); + vtkGetMacro(CornerFactor, double); + + // Description: + // Set and get the controller. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + +protected: + vtkPOutlineCornerFilter(); + ~vtkPOutlineCornerFilter(); + + vtkMultiProcessController* Controller; + vtkOutlineCornerSource *OutlineCornerSource; + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + double CornerFactor; +private: + vtkPOutlineCornerFilter(const vtkPOutlineCornerFilter&); // Not implemented. + void operator=(const vtkPOutlineCornerFilter&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPOutlineFilter.cxx b/Parallel/vtkPOutlineFilter.cxx new file mode 100644 index 0000000..5ebb02e --- /dev/null +++ b/Parallel/vtkPOutlineFilter.cxx @@ -0,0 +1,168 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPOutlineFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPOutlineFilter.h" + +#include "vtkCompositeDataSet.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMath.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineSource.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPOutlineFilter, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkPOutlineFilter); +vtkCxxSetObjectMacro(vtkPOutlineFilter, Controller, vtkMultiProcessController); + +vtkPOutlineFilter::vtkPOutlineFilter () +{ + this->Controller = 0; + this->SetController(vtkMultiProcessController::GetGlobalController()); + this->OutlineSource = vtkOutlineSource::New(); +} + +vtkPOutlineFilter::~vtkPOutlineFilter () +{ + this->SetController(0); + if (this->OutlineSource != NULL) + { + this->OutlineSource->Delete (); + this->OutlineSource = NULL; + } +} + +int vtkPOutlineFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + double bds[6]; + int procid = 0; + int numProcs = 1; + + if (this->Controller ) + { + procid = this->Controller->GetLocalProcessId(); + numProcs = this->Controller->GetNumberOfProcesses(); + } + + int doCommunicate = 1; + + // If there is a composite dataset in the input, the request is + // coming from a vtkCompositeDataPipeline and interprocess communication + // is not necessary (simple datasets are not broken into pieces) + vtkCompositeDataSet* cds = vtkCompositeDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + if (cds) + { + doCommunicate = 0; + } + + input->GetBounds(bds); + + if (doCommunicate) + { + if ( procid ) + { + // Satellite node + this->Controller->Send(bds, 6, 0, 792390); + } + else + { + int idx; + double tmp[6]; + + for (idx = 1; idx < numProcs; ++idx) + { + this->Controller->Receive(tmp, 6, idx, 792390); + if (tmp[0] < bds[0]) + { + bds[0] = tmp[0]; + } + if (tmp[1] > bds[1]) + { + bds[1] = tmp[1]; + } + if (tmp[2] < bds[2]) + { + bds[2] = tmp[2]; + } + if (tmp[3] > bds[3]) + { + bds[3] = tmp[3]; + } + if (tmp[4] < bds[4]) + { + bds[4] = tmp[4]; + } + if (tmp[5] > bds[5]) + { + bds[5] = tmp[5]; + } + } + } + } + + if (!doCommunicate || procid == 0) + { + if (vtkMath::AreBoundsInitialized(bds)) + { + // only output in process 0. + this->OutlineSource->SetBounds(bds); + this->OutlineSource->Update(); + output->CopyStructure(this->OutlineSource->GetOutput()); + } + } + + return 1; +} + +int vtkPOutlineFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + return 1; +} + +int vtkPOutlineFilter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkPOutlineFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Controller: " << this->Controller << endl; +} diff --git a/Parallel/vtkPOutlineFilter.h b/Parallel/vtkPOutlineFilter.h new file mode 100644 index 0000000..4da5e3c --- /dev/null +++ b/Parallel/vtkPOutlineFilter.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPOutlineFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPOutlineFilter - create wireframe outline for arbitrary data set +// .SECTION Description +// vtkPOutlineFilter works like vtkOutlineFilter, but it looks for data +// partitions in other processes. It assumes the filter is operated +// in a data parallel pipeline. + +#ifndef __vtkPOutlineFilter_h +#define __vtkPOutlineFilter_h + +#include "vtkPolyDataAlgorithm.h" +class vtkOutlineSource; +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkPOutlineFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkPOutlineFilter *New(); + vtkTypeRevisionMacro(vtkPOutlineFilter,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set and get the controller. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + +protected: + vtkPOutlineFilter(); + ~vtkPOutlineFilter(); + + vtkMultiProcessController* Controller; + vtkOutlineSource *OutlineSource; + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkPOutlineFilter(const vtkPOutlineFilter&); // Not implemented. + void operator=(const vtkPOutlineFilter&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPPolyDataNormals.cxx b/Parallel/vtkPPolyDataNormals.cxx new file mode 100644 index 0000000..0f8c15f --- /dev/null +++ b/Parallel/vtkPPolyDataNormals.cxx @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPPolyDataNormals.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPPolyDataNormals.h" + +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPPolyDataNormals, "$Revision: 1.12 $"); +vtkStandardNewMacro(vtkPPolyDataNormals); + +//---------------------------------------------------------------------------- +vtkPPolyDataNormals::vtkPPolyDataNormals() +{ + this->PieceInvariant = 1; +} + +//---------------------------------------------------------------------------- +int vtkPPolyDataNormals::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info object + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the ouptut + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (!this->vtkPolyDataNormals::RequestData(request, inputVector, outputVector)) + { + return 0; + } + + if (this->PieceInvariant) + { + output->RemoveGhostCells( + outInfo->Get( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())+1); + } + + return 1; +} + +//-------------------------------------------------------------------------- +int vtkPPolyDataNormals::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + int piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + int ghostLevel = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + if (this->PieceInvariant) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),piece); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel + 1); + } + else + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),piece); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPPolyDataNormals::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PieceInvariant: " + << this->PieceInvariant << "\n"; +} diff --git a/Parallel/vtkPPolyDataNormals.h b/Parallel/vtkPPolyDataNormals.h new file mode 100644 index 0000000..acf2ec0 --- /dev/null +++ b/Parallel/vtkPPolyDataNormals.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPPolyDataNormals.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPPolyDataNormals - compute normals for polygonal mesh +// .SECTION Description + +#ifndef __vtkPPolyDataNormals_h +#define __vtkPPolyDataNormals_h + +#include "vtkPolyDataNormals.h" + +class VTK_PARALLEL_EXPORT vtkPPolyDataNormals : public vtkPolyDataNormals +{ +public: + vtkTypeRevisionMacro(vtkPPolyDataNormals,vtkPolyDataNormals); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + static vtkPPolyDataNormals *New(); + + // Description: + // To get piece invariance, this filter has to request an + // extra ghost level. By default piece invariance is on. + vtkSetMacro(PieceInvariant, int); + vtkGetMacro(PieceInvariant, int); + vtkBooleanMacro(PieceInvariant, int); + +protected: + vtkPPolyDataNormals(); + ~vtkPPolyDataNormals() {}; + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int PieceInvariant; +private: + vtkPPolyDataNormals(const vtkPPolyDataNormals&); // Not implemented. + void operator=(const vtkPPolyDataNormals&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPProbeFilter.cxx b/Parallel/vtkPProbeFilter.cxx new file mode 100644 index 0000000..a4f56e4 --- /dev/null +++ b/Parallel/vtkPProbeFilter.cxx @@ -0,0 +1,157 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPProbeFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPProbeFilter.h" + +#include "vtkIdTypeArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPProbeFilter, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkPProbeFilter); + +vtkCxxSetObjectMacro(vtkPProbeFilter, Controller, vtkMultiProcessController); + +//---------------------------------------------------------------------------- +vtkPProbeFilter::vtkPProbeFilter() +{ + this->Controller = 0; + this->SetController(vtkMultiProcessController::GetGlobalController()); +} + +//---------------------------------------------------------------------------- +vtkPProbeFilter::~vtkPProbeFilter() +{ + this->SetController(0); +} + +//---------------------------------------------------------------------------- +int vtkPProbeFilter::RequestInformation(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPProbeFilter::RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + this->vtkProbeFilter::RequestData(request, inputVector, outputVector); + int procid = 0; + int numProcs = 1; + if ( this->Controller ) + { + procid = this->Controller->GetLocalProcessId(); + numProcs = this->Controller->GetNumberOfProcesses(); + } + + vtkIdType numPoints = this->GetValidPoints()->GetMaxId() + 1; + if ( procid ) + { + // Satellite node + this->Controller->Send(&numPoints, 1, 0, 1970); + if ( numPoints > 0 ) + { + this->Controller->Send(this->GetValidPoints(), 0, 1971); + this->Controller->Send(output, 0, 1972); + } + output->ReleaseData(); + } + else if ( numProcs > 1 ) + { + vtkIdType numRemotePoints = 0; + vtkIdTypeArray *validPoints = vtkIdTypeArray::New(); + vtkDataSet *remoteProbeOutput = output->NewInstance(); + vtkPointData *remotePointData; + vtkPointData *pointData = output->GetPointData(); + vtkIdType i; + vtkIdType j; + vtkIdType k; + vtkIdType pointId; + vtkIdType numComponents = pointData->GetNumberOfComponents(); + double *tuple = new double[numComponents]; + for (i = 1; i < numProcs; i++) + { + this->Controller->Receive(&numRemotePoints, 1, i, 1970); + if (numRemotePoints > 0) + { + this->Controller->Receive(validPoints, i, 1971); + this->Controller->Receive(remoteProbeOutput, i, 1972); + + remotePointData = remoteProbeOutput->GetPointData(); + for (j = 0; j < numRemotePoints; j++) + { + pointId = validPoints->GetValue(j); + + remotePointData->GetTuple(pointId, tuple); + + for (k = 0; k < numComponents; k++) + { + output->GetPointData()->SetComponent(pointId, k, tuple[k]); + } + } + } + } + validPoints->Delete(); + remoteProbeOutput->Delete(); + delete [] tuple; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkPProbeFilter::RequestUpdateExtent(vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkPProbeFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Controller " << this->Controller << endl; +} diff --git a/Parallel/vtkPProbeFilter.h b/Parallel/vtkPProbeFilter.h new file mode 100644 index 0000000..5003b8e --- /dev/null +++ b/Parallel/vtkPProbeFilter.h @@ -0,0 +1,55 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPProbeFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPProbeFilter - probe dataset in parallel +// .SECTION Description + +#ifndef __vtkPProbeFilter_h +#define __vtkPProbeFilter_h + +#include "vtkProbeFilter.h" + +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkPProbeFilter : public vtkProbeFilter +{ +public: + vtkTypeRevisionMacro(vtkPProbeFilter,vtkProbeFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + static vtkPProbeFilter *New(); + + // Description: + // Set and get the controller. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + +protected: + vtkPProbeFilter(); + ~vtkPProbeFilter(); + + // Usual data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkMultiProcessController* Controller; + +private: + vtkPProbeFilter(const vtkPProbeFilter&); // Not implemented. + void operator=(const vtkPProbeFilter&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPSphereSource.cxx b/Parallel/vtkPSphereSource.cxx new file mode 100644 index 0000000..94e6ab9 --- /dev/null +++ b/Parallel/vtkPSphereSource.cxx @@ -0,0 +1,283 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPSphereSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPSphereSource.h" + +#include "vtkCellArray.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLargeInteger.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include + +vtkCxxRevisionMacro(vtkPSphereSource, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkPSphereSource); + +//---------------------------------------------------------------------------- +int vtkPSphereSource::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + vtkIdType i, j, numOffset; + int jStart, jEnd; + vtkIdType numPts, numPolys; + vtkPoints *newPoints; + vtkFloatArray *newNormals; + vtkCellArray *newPolys; + float x[3], n[3], deltaPhi, deltaTheta, phi, theta, radius, norm; + float startTheta, endTheta, startPhi, endPhi; + vtkIdType base, thetaResolution, phiResolution; + int numPoles = 0; + vtkIdType pts[3]; + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + int piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + // I want to modify the ivars resoultion start theta and end theta, + // so I will make local copies of them. THese might be able to be merged + // with the other copies of them, ... + int localThetaResolution = this->ThetaResolution; + float localStartTheta = this->StartTheta; + float localEndTheta = this->EndTheta; + + while (localEndTheta < localStartTheta) + { + localEndTheta += 360.0; + } + deltaTheta = (localEndTheta - localStartTheta) / localThetaResolution; + + // Change the ivars based on pieces. + vtkIdType start, end; + start = piece * localThetaResolution / numPieces; + end = (piece+1) * localThetaResolution / numPieces; + localEndTheta = localStartTheta + (float)(end) * deltaTheta; + localStartTheta = localStartTheta + (float)(start) * deltaTheta; + localThetaResolution = end - start; + + // + // Set things up; allocate memory + // + + vtkDebugMacro("PSphereSource Executing"); + + numPts = this->PhiResolution * localThetaResolution + 2; + // creating triangles + numPolys = this->PhiResolution * 2 * localThetaResolution; + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newNormals = vtkFloatArray::New(); + newNormals->SetNumberOfComponents(3); + newNormals->Allocate(3*numPts); + + newPolys = vtkCellArray::New(); + newPolys->Allocate(newPolys->EstimateSize(numPolys, 3)); + // + // Create sphere + // + // Create north pole if needed + if ( this->StartPhi <= 0.0 ) + { + x[0] = this->Center[0]; + x[1] = this->Center[1]; + x[2] = this->Center[2] + this->Radius; + newPoints->InsertPoint(numPoles,x); + + x[0] = x[1] = 0.0; x[2] = 1.0; + newNormals->InsertTuple(numPoles,x); + numPoles++; + } + + // Create south pole if needed + if ( this->EndPhi >= 180.0 ) + { + x[0] = this->Center[0]; + x[1] = this->Center[1]; + x[2] = this->Center[2] - this->Radius; + newPoints->InsertPoint(numPoles,x); + + x[0] = x[1] = 0.0; x[2] = -1.0; + newNormals->InsertTuple(numPoles,x); + numPoles++; + } + + // Check data, determine increments, and convert to radians + startTheta = (localStartTheta < localEndTheta ? localStartTheta + : localEndTheta); + startTheta *= vtkMath::Pi() / 180.0; + endTheta = (localEndTheta > localStartTheta ? localEndTheta + : localStartTheta); + endTheta *= vtkMath::Pi() / 180.0; + + startPhi = (this->StartPhi < this->EndPhi ? this->StartPhi : this->EndPhi); + startPhi *= vtkMath::Pi() / 180.0; + endPhi = (this->EndPhi > this->StartPhi ? this->EndPhi : this->StartPhi); + endPhi *= vtkMath::Pi() / 180.0; + + phiResolution = this->PhiResolution - numPoles; + deltaPhi = (endPhi - startPhi) / (this->PhiResolution - 1); + thetaResolution = localThetaResolution; + if (fabs(localStartTheta - localEndTheta) < 360.0) + { + ++localThetaResolution; + } + deltaTheta = (endTheta - startTheta) / thetaResolution; + + jStart = (this->StartPhi <= 0.0 ? 1 : 0); + jEnd = (this->EndPhi >= 180.0 ? this->PhiResolution - 1 + : this->PhiResolution); + + // Create intermediate points + for (i=0; i < localThetaResolution; i++) + { + theta = localStartTheta * vtkMath::Pi() / 180.0 + i*deltaTheta; + + for (j=jStart; jRadius * sin((double)phi); + n[0] = radius * cos((double)theta); + n[1] = radius * sin((double)theta); + n[2] = this->Radius * cos((double)phi); + x[0] = n[0] + this->Center[0]; + x[1] = n[1] + this->Center[1]; + x[2] = n[2] + this->Center[2]; + newPoints->InsertNextPoint(x); + + if ( (norm = vtkMath::Norm(n)) == 0.0 ) + { + norm = 1.0; + } + n[0] /= norm; n[1] /= norm; n[2] /= norm; + newNormals->InsertNextTuple(n); + } + } + + // Generate mesh connectivity + base = phiResolution * localThetaResolution; + + if (fabs(localStartTheta - localEndTheta) < 360.0) + { + --localThetaResolution; + } + + if ( this->StartPhi <= 0.0 ) // around north pole + { + for (i=0; i < localThetaResolution; i++) + { + pts[0] = phiResolution*i + numPoles; + pts[1] = (phiResolution*(i+1) % base) + numPoles; + pts[2] = 0; + newPolys->InsertNextCell(3, pts); + } + } + + if ( this->EndPhi >= 180.0 ) // around south pole + { + numOffset = phiResolution - 1 + numPoles; + + for (i=0; i < localThetaResolution; i++) + { + pts[0] = phiResolution*i + numOffset; + pts[2] = ((phiResolution*(i+1)) % base) + numOffset; + pts[1] = numPoles - 1; + newPolys->InsertNextCell(3, pts); + } + } + + // bands in-between poles + for (i=0; i < localThetaResolution; i++) + { + for (j=0; j < (phiResolution-1); j++) + { + pts[0] = phiResolution*i + j + numPoles; + pts[1] = pts[0] + 1; + pts[2] = ((phiResolution*(i+1)+j) % base) + numPoles + 1; + newPolys->InsertNextCell(3, pts); + + pts[1] = pts[2]; + pts[2] = pts[1] - 1; + newPolys->InsertNextCell(3, pts); + } + } + // + // Update ourselves and release memeory + // + newPoints->Squeeze(); + output->SetPoints(newPoints); + newPoints->Delete(); + + newNormals->Squeeze(); + output->GetPointData()->SetNormals(newNormals); + newNormals->Delete(); + + output->SetPolys(newPolys); + newPolys->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +unsigned long vtkPSphereSource::GetEstimatedMemorySize() +{ + vtkLargeInteger sz; + vtkLargeInteger sz2; + unsigned long thetaResolution = this->ThetaResolution; + vtkInformation *outInfo = this->GetExecutive()->GetOutputInformation(0); + int numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + + if (numPieces) + { + thetaResolution /= numPieces; + } + + if (thetaResolution < 1) + { + thetaResolution = 1; + } + + // ignore poles + sz = thetaResolution; + sz = sz * (this->PhiResolution + 1); + sz2 = thetaResolution; + sz2 = sz2 * this->PhiResolution * 2; + sz = sz * 3 * sizeof(float); + sz2 = sz2 * 4 * sizeof(int); + + sz = sz + sz2; + + // convert to kilobytes + sz >>= 10; + + return sz.CastToUnsignedLong(); +} + +void vtkPSphereSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} diff --git a/Parallel/vtkPSphereSource.h b/Parallel/vtkPSphereSource.h new file mode 100644 index 0000000..b788450 --- /dev/null +++ b/Parallel/vtkPSphereSource.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPSphereSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPSphereSource - sphere source that supports pieces + +#ifndef __vtkPSphereSource_h +#define __vtkPSphereSource_h + +#include "vtkSphereSource.h" + +class VTK_PARALLEL_EXPORT vtkPSphereSource : public vtkSphereSource +{ +public: + vtkTypeRevisionMacro(vtkPSphereSource,vtkSphereSource); + + // Description: + // Construct sphere with radius=0.5 and default resolution 8 in both Phi + // and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees. + static vtkPSphereSource *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the estimated memory size in 1024 bytes + unsigned long GetEstimatedMemorySize(); + +protected: + vtkPSphereSource() {}; + ~vtkPSphereSource() {}; + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); +private: + vtkPSphereSource(const vtkPSphereSource&); // Not implemented. + void operator=(const vtkPSphereSource&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPStreamTracer.cxx b/Parallel/vtkPStreamTracer.cxx new file mode 100644 index 0000000..c9bc076 --- /dev/null +++ b/Parallel/vtkPStreamTracer.cxx @@ -0,0 +1,421 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPStreamTracer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPStreamTracer.h" + +#include "vtkAppendPolyData.h" +#include "vtkCellData.h" +#include "vtkIdList.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkInterpolatedVelocityField.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPStreamTracer, "$Revision: 1.17 $"); + +vtkCxxSetObjectMacro(vtkPStreamTracer, Controller, vtkMultiProcessController); +vtkCxxSetObjectMacro(vtkPStreamTracer, + Interpolator, + vtkInterpolatedVelocityField); + +vtkPStreamTracer::vtkPStreamTracer() +{ + this->Controller = vtkMultiProcessController::GetGlobalController(); + if (this->Controller) + { + this->Controller->Register(this); + } + this->Interpolator = 0; + this->Seeds = 0; + this->SeedIds = 0; + this->IntegrationDirections = 0; + + this->GenerateNormalsInIntegrate = 0; +} + +vtkPStreamTracer::~vtkPStreamTracer() +{ + if (this->Controller) + { + this->Controller->UnRegister(this); + this->Controller = 0; + } + this->SetInterpolator(0); + if (this->Seeds) + { + this->Seeds->Delete(); + } + if (this->SeedIds) + { + this->SeedIds->Delete(); + } + if (this->IntegrationDirections) + { + this->IntegrationDirections->Delete(); + } +} + +// After the integration is over, we need to add one point +// at the end of streamline pieces which were not the end +// piece. This has to be done in order to close the gap between +// pieces which appear due to jump from one process to another. +// This method waits until a process sends its first points. +void vtkPStreamTracer::ReceiveLastPoints(vtkPolyData *output) +{ + int streamId = 0; + + while(1) + { + this->Controller->Receive(&streamId, + 1, + vtkMultiProcessController::ANY_SOURCE, + 733); + if (streamId < 0) + { + break; + } + this->ReceiveCellPoint(this->GetOutput(), streamId, -1); + } + // We were told that it is our turn to send first points. + if (streamId == -2) + { + this->SendFirstPoints(output); + } +} + +// Once we are done sending, let's tell the next guy (unless +// this is the last process) to send it's first points +void vtkPStreamTracer::MoveToNextSend(vtkPolyData *output) +{ + int numProcs = this->Controller->GetNumberOfProcesses(); + int myid = this->Controller->GetLocalProcessId(); + + int tag; + if (myid == numProcs - 1) + { + tag = -1; + for(int i=0; iController->Send(&tag, 1, i, 733); + } + } + } + else + { + tag = -2; + this->Controller->Send(&tag, 1, myid+1, 733); + this->ReceiveLastPoints(output); + } +} + +// After the integration is over, we need to add one point +// at the end of streamline pieces which were not the end +// piece. This has to be done in order to close the gap between +// pieces which appear due to jump from one process to another. +// This method sends the first point of each streamline which +// originated in another process to that process. This information +// is stored in the "Streamline Origin" array. +void vtkPStreamTracer::SendFirstPoints(vtkPolyData *output) +{ + vtkIntArray* strOrigin = vtkIntArray::SafeDownCast( + output->GetCellData()->GetArray("Streamline Origin")); + if (!strOrigin) + { + this->MoveToNextSend(output); + return; + } + int numLines = strOrigin->GetNumberOfTuples(); + int streamId, sendToId; + int i; + for(i=0; iGetValue(2*i); + streamId = strOrigin->GetValue(2*i+1); + if (streamId != -1) + { + this->Controller->Send(&streamId, 1, sendToId, 733); + this->SendCellPoint(output, i, 0, sendToId); + } + } + this->MoveToNextSend(output); +} + +// Receive one point and add it to the given cell. +void vtkPStreamTracer::ReceiveCellPoint(vtkPolyData* tomod, + int streamId, + vtkIdType idx) +{ + vtkPolyData* input = vtkPolyData::New(); + + // Receive a polydata which contains one point. + this->Controller->Receive(input, vtkMultiProcessController::ANY_SOURCE, 765); + + int numCells = tomod->GetNumberOfCells(); + // Use the "Streamline Ids" array to locate the right cell. + vtkIntArray* streamIds = vtkIntArray::SafeDownCast( + tomod->GetCellData()->GetArray("Streamline Ids")); + if (!streamIds) + { + input->Delete(); + return; + } + vtkIdType cellId=-1; + for(vtkIdType cellIdx=0; cellIdx < numCells; cellIdx++) + { + if (streamIds->GetValue(cellIdx) == streamId) + { + cellId = cellIdx; + break; + } + } + + if ( cellId == -1 ) + { + return; + } + + // Find the point to be modified. We don't actually add a point, + // we just replace replace the attributes of one (usually the last) + // with the new attributes we received. + vtkIdType ptId; + vtkIdType npts; + vtkIdType* pts; + tomod->GetCellPoints(cellId, npts, pts); + if (idx == -1) + { + idx = npts-1; + } + ptId = pts[idx]; + + // Replace attributes + vtkPointData* pd = input->GetPointData(); + int numArrays = pd->GetNumberOfArrays(); + int i; + vtkPointData* outputPD = tomod->GetPointData(); + for(i=0; iGetArray(i); + const char* name = da->GetName(); + if (name) + { + vtkDataArray* outputDA = outputPD->GetArray(name); + outputDA->SetTuple(ptId, da->GetTuple(0)); + } + } + + input->Delete(); +} + +// Send one point and all of it's attributes to another process +void vtkPStreamTracer::SendCellPoint(vtkPolyData* togo, + vtkIdType cellId, + vtkIdType idx, + int sendToId) +{ + // We create a dummy dataset which will contain the point + // we want to send and it's attributes. + vtkPolyData* copy = vtkPolyData::New(); + + vtkIdType ptId; + vtkIdType npts; + vtkIdType* pts; + togo->GetCellPoints(cellId, npts, pts); + ptId = pts[idx]; + + vtkPoints* points = vtkPoints::New(); + points->SetNumberOfPoints(1); + points->SetPoint(0, togo->GetPoint(ptId)); + copy->SetPoints(points); + points->Delete(); + + vtkPointData* togoPD = togo->GetPointData(); + vtkPointData* copyPD = copy->GetPointData(); + + copyPD->CopyAllocate(togoPD, 1); + copyPD->CopyData(togoPD, ptId, 0); + + this->Controller->Send(copy, sendToId, 765); + + copy->Delete(); +} + +int vtkPStreamTracer::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + int piece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int numPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + int ghostLevel = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + int numInputs = this->GetNumberOfInputConnections(0); + for (int idx = 0; idx < numInputs; ++idx) + { + vtkInformation *info = inputVector[0]->GetInformationObject(idx); + if (info) + { + info->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + piece); + info->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + numPieces); + info->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel); + } + } + + + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + if (sourceInfo) + { + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + sourceInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ghostLevel); + } + + return 1; +} + +int vtkPStreamTracer::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **vtkNotUsed(inputVector), + vtkInformationVector *outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1); + + return 1; +} + +int vtkPStreamTracer::RequestData( + vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + if (!this->Controller) + { + vtkErrorMacro("No controller assigned. Can not execute."); + return 0; + } + + if (this->Controller->GetNumberOfProcesses() == 1) + { + this->GenerateNormalsInIntegrate = 1; + int retVal = this->Superclass::RequestData(request, inputVector, + outputVector); + this->GenerateNormalsInIntegrate = 0; + return retVal; + } + + vtkInformation *sourceInfo = inputVector[1]->GetInformationObject(0); + vtkDataSet *source = 0; + if (sourceInfo) + { + source = vtkDataSet::SafeDownCast( + sourceInfo->Get(vtkDataObject::DATA_OBJECT())); + } + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkPolyData* output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkInterpolatedVelocityField* func; + int maxCellSize = 0; + if (this->CheckInputs(func, &maxCellSize, inputVector) != VTK_OK) + { + vtkDebugMacro("No appropriate inputs have been found. Can not execute."); + func->Delete(); + // >>>>>>>>>> TODO: All should pass this test. + return 1; + } + func->SetCaching(0); + this->SetInterpolator(func); + func->Delete(); + + this->InitializeSeeds(this->Seeds, + this->SeedIds, + this->IntegrationDirections, + source); + + this->TmpOutputs.erase(this->TmpOutputs.begin(), this->TmpOutputs.end()); + this->ParallelIntegrate(inputVector); + + // The parallel integration adds all streamlines to TmpOutputs + // container. We append them all together here. + vtkAppendPolyData* append = vtkAppendPolyData::New(); + for (TmpOutputsType::iterator it = this->TmpOutputs.begin(); + it != this->TmpOutputs.end(); it++) + { + vtkPolyData* inp = it->GetPointer(); + if ( inp->GetNumberOfCells() > 0 ) + { + append->AddInput(inp); + } + } + if (append->GetNumberOfInputConnections(0) > 0) + { + append->Update(); + vtkPolyData* appoutput = append->GetOutput(); + output->CopyStructure(appoutput); + output->GetPointData()->PassData(appoutput->GetPointData()); + output->GetCellData()->PassData(appoutput->GetCellData()); + } + append->Delete(); + this->TmpOutputs.erase(this->TmpOutputs.begin(), this->TmpOutputs.end()); + + // Fill the gaps between streamlines. + output->BuildCells(); + int myid = this->Controller->GetLocalProcessId(); + if (myid == 0) + { + this->SendFirstPoints(output); + } + else + { + this->ReceiveLastPoints(output); + } + + if (this->Seeds) + { + this->Seeds->Delete(); + this->Seeds = 0; + } + this->IntegrationDirections->Delete(); + this->IntegrationDirections = 0; + this->SeedIds->Delete(); + this->SeedIds = 0; + + output->Squeeze(); + + return 1; +} + +void vtkPStreamTracer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Controller: " << this->Controller << endl; +} diff --git a/Parallel/vtkPStreamTracer.h b/Parallel/vtkPStreamTracer.h new file mode 100644 index 0000000..5d72018 --- /dev/null +++ b/Parallel/vtkPStreamTracer.h @@ -0,0 +1,93 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPStreamTracer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPStreamTracer - Abstract superclass for parallel streamline generators +// .SECTION Description +// This class implements some necessary functionality used by distributed +// and parallel streamline generators. Note that all processes must have +// access to the WHOLE seed source, i.e. the source must be identical +// on all processes. +// .SECTION See Also +// vtkStreamTracer vtkDistributedStreamTracer vtkMPIStreamTracer + +#ifndef __vtkPStreamTracer_h +#define __vtkPStreamTracer_h + +#include "vtkStreamTracer.h" + +#include "vtkSmartPointer.h" // This is a leaf node. No need to +#include // use PIMPL to avoid compile time penalty. + +class vtkInterpolatedVelocityField; +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkPStreamTracer : public vtkStreamTracer +{ +public: + vtkTypeRevisionMacro(vtkPStreamTracer,vtkStreamTracer); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the controller use in compositing (set to + // the global controller by default) + // If not using the default, this must be called before any + // other methods. + virtual void SetController(vtkMultiProcessController* controller); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + +protected: + + vtkPStreamTracer(); + ~vtkPStreamTracer(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkMultiProcessController* Controller; + + vtkInterpolatedVelocityField* Interpolator; + void SetInterpolator(vtkInterpolatedVelocityField*); + + // See the implementation for comments + void SendCellPoint(vtkPolyData* data, + vtkIdType streamId, + vtkIdType idx, + int sendToId); + void ReceiveCellPoint(vtkPolyData* tomod, int streamId, vtkIdType idx); + void SendFirstPoints(vtkPolyData *output); + void ReceiveLastPoints(vtkPolyData *output); + void MoveToNextSend(vtkPolyData *output); + + virtual void ParallelIntegrate(vtkInformationVector **inputVector) = 0; + + vtkDataArray* Seeds; + vtkIdList* SeedIds; + vtkIntArray* IntegrationDirections; + +//BTX + typedef vtkstd::vector< vtkSmartPointer > TmpOutputsType; +//ETX + + TmpOutputsType TmpOutputs; + +private: + vtkPStreamTracer(const vtkPStreamTracer&); // Not implemented. + void operator=(const vtkPStreamTracer&); // Not implemented. +}; + + +#endif + + diff --git a/Parallel/vtkParallelFactory.cxx b/Parallel/vtkParallelFactory.cxx new file mode 100644 index 0000000..602accb --- /dev/null +++ b/Parallel/vtkParallelFactory.cxx @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParallelFactory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkParallelFactory.h" +#include "vtkPImageWriter.h" +#include "vtkPPolyDataNormals.h" +#include "vtkPSphereSource.h" +#include "vtkPOutlineCornerFilter.h" +#include "vtkPOutlineFilter.h" +#include "vtkPStreamTracer.h" +#include "vtkPProbeFilter.h" +#include "vtkPLinearExtrusionFilter.h" +#include "vtkVersion.h" + +vtkCxxRevisionMacro(vtkParallelFactory, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkParallelFactory); + +void vtkParallelFactory::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "VTK Parallel object factory" << endl; +} + + +VTK_CREATE_CREATE_FUNCTION(vtkPImageWriter); +VTK_CREATE_CREATE_FUNCTION(vtkPPolyDataNormals); +VTK_CREATE_CREATE_FUNCTION(vtkPSphereSource); +VTK_CREATE_CREATE_FUNCTION(vtkPStreamTracer); +VTK_CREATE_CREATE_FUNCTION(vtkPLinearExtrusionFilter); +VTK_CREATE_CREATE_FUNCTION(vtkPOutlineCornerFilter); +VTK_CREATE_CREATE_FUNCTION(vtkPOutlineFilter); +VTK_CREATE_CREATE_FUNCTION(vtkPProbeFilter); + +vtkParallelFactory::vtkParallelFactory() +{ + this->RegisterOverride("vtkImageWriter", + "vtkPImageWriter", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPImageWriter); + this->RegisterOverride("vtkPolyDataNormals", + "vtkPPolyDataNormals", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPPolyDataNormals); + this->RegisterOverride("vtkSphereSource", + "vtkPSphereSource", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPSphereSource); + this->RegisterOverride("vtkStreamTracer", + "vtkPStreamTracer", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPStreamTracer); + this->RegisterOverride("vtkLinearExtrusionFilter", + "vtkPLinearExtrusionFilter", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPLinearExtrusionFilter); + this->RegisterOverride("vtkOutlineCornerFilter", + "vtkPOutlineCornerFilter", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPOutlineCornerFilter); + this->RegisterOverride("vtkOutlineFilter", + "vtkPOutlineFilter", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPOutlineFilter); + this->RegisterOverride("vtkProbeFilter", + "vtkPProbeFilter", + "Parallel", + 1, + vtkObjectFactoryCreatevtkPProbeFilter); +} + +const char* vtkParallelFactory::GetVTKSourceVersion() +{ + return VTK_SOURCE_VERSION; +} + +const char* vtkParallelFactory::GetDescription() +{ + return "VTK Parallel Support Factory"; +} + + +extern "C" vtkObjectFactory* vtkLoad() +{ + return vtkParallelFactory::New(); +} diff --git a/Parallel/vtkParallelFactory.h b/Parallel/vtkParallelFactory.h new file mode 100644 index 0000000..d556c6d --- /dev/null +++ b/Parallel/vtkParallelFactory.h @@ -0,0 +1,41 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParallelFactory.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParallelFactory - +// .SECTION Description + +#ifndef __vtkParallelFactory_h +#define __vtkParallelFactory_h + +#include "vtkObjectFactory.h" + +class VTK_PARALLEL_EXPORT vtkParallelFactory : public vtkObjectFactory +{ +public: +// Methods from vtkObject + vtkTypeRevisionMacro(vtkParallelFactory,vtkObjectFactory); + static vtkParallelFactory *New(); + void PrintSelf(ostream& os, vtkIndent indent); + virtual const char* GetVTKSourceVersion(); + virtual const char* GetDescription(); +protected: + vtkParallelFactory(); + ~vtkParallelFactory() { } +private: + vtkParallelFactory(const vtkParallelFactory&); // Not implemented. + void operator=(const vtkParallelFactory&); // Not implemented. +}; + +extern "C" VTK_PARALLEL_EXPORT vtkObjectFactory* vtkLoad(); +#endif diff --git a/Parallel/vtkParallelRenderManager.cxx b/Parallel/vtkParallelRenderManager.cxx new file mode 100644 index 0000000..fc4f883 --- /dev/null +++ b/Parallel/vtkParallelRenderManager.cxx @@ -0,0 +1,1951 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParallelRenderManager.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + Copyright 2003 Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000, there is a non-exclusive license for use of this work by + or on behalf of the U.S. Government. Redistribution and use in source and + binary forms, with or without modification, are permitted provided that this + Notice and any statement of authorship are reproduced on all copies. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParallelRenderManager.h" + +#include "vtkMultiProcessController.h" +#include "vtkCallbackCommand.h" +#include "vtkActorCollection.h" +#include "vtkActor.h" +#include "vtkPolyDataMapper.h" +#include "vtkCamera.h" +#include "vtkDoubleArray.h" +#include "vtkLightCollection.h" +#include "vtkLight.h" +#include "vtkMath.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkRendererCollection.h" +#include "vtkTimerLog.h" +#include "vtkUnsignedCharArray.h" + +static void AbortRenderCheck(vtkObject *caller, unsigned long vtkNotUsed(event), + void *clientData, void *); +static void StartRender(vtkObject *caller, unsigned long vtkNotUsed(event), + void *clientData, void *); +static void EndRender(vtkObject *caller, unsigned long vtkNotUsed(event), + void *clientData, void *); +static void SatelliteStartRender(vtkObject *caller, + unsigned long vtkNotUsed(event), + void *clientData, void *); +static void SatelliteEndRender(vtkObject *caller, + unsigned long vtkNotUsed(event), + void *clientData, void *); +/* +static void ResetCamera(vtkObject *caller, + unsigned long vtkNotUsed(event), + void *clientData, void *); +static void ResetCameraClippingRange(vtkObject *caller, + unsigned long vtkNotUsed(event), + void *clientData, void *); +*/ +static void RenderRMI(void *arg, void *, int, int); +static void ComputeVisiblePropBoundsRMI(void *arg, void *, int, int); +const int vtkParallelRenderManager::WIN_INFO_INT_SIZE = + sizeof(vtkParallelRenderManager::RenderWindowInfoInt)/sizeof(int); +const int vtkParallelRenderManager::WIN_INFO_DOUBLE_SIZE = + sizeof(vtkParallelRenderManager::RenderWindowInfoDouble)/sizeof(double); +const int vtkParallelRenderManager::REN_INFO_INT_SIZE = + sizeof(vtkParallelRenderManager::RendererInfoInt)/sizeof(int); +const int vtkParallelRenderManager::REN_INFO_DOUBLE_SIZE = + sizeof(vtkParallelRenderManager::RendererInfoDouble)/sizeof(double); +const int vtkParallelRenderManager::LIGHT_INFO_DOUBLE_SIZE = + sizeof(vtkParallelRenderManager::LightInfoDouble)/sizeof(double); + +vtkCxxRevisionMacro(vtkParallelRenderManager, "$Revision: 1.52.6.1 $"); + +//---------------------------------------------------------------------------- +vtkParallelRenderManager::vtkParallelRenderManager() +{ + this->RenderWindow = NULL; + this->ObservingRenderWindow = 0; + this->ObservingRenderer = 0; + this->ObservingAbort = 0; + + this->Controller = NULL; + this->SetController(vtkMultiProcessController::GetGlobalController()); + this->RootProcessId = 0; + + this->Lock = 0; + + this->ImageReductionFactor = 1; + this->MaxImageReductionFactor = 16; + this->AutoImageReductionFactor = 0; + this->AverageTimePerPixel = 0.0; + + this->RenderTime = 0.0; + this->ImageProcessingTime = 0.0; + + this->ParallelRendering = 1; + this->WriteBackImages = 1; + this->MagnifyImages = 1; + this->MagnifyImageMethod = vtkParallelRenderManager::NEAREST; + this->RenderEventPropagation = 1; + this->UseCompositing = 1; + + this->FullImage = vtkUnsignedCharArray::New(); + this->ReducedImage = vtkUnsignedCharArray::New(); + this->FullImageUpToDate = 0; + this->ReducedImageUpToDate = 0; + this->RenderWindowImageUpToDate = 0; + this->FullImageSize[0] = 0; + this->FullImageSize[1] = 0; + + this->ReducedImageSize[0] = 0; + this->ReducedImageSize[1] = 0; + + this->Viewports = vtkDoubleArray::New(); + this->Viewports->SetNumberOfComponents(4); + + this->UseRGBA = 1; + + this->AddedRMIs = 0; + this->Timer = vtkTimerLog::New(); +} + +//---------------------------------------------------------------------------- +vtkParallelRenderManager::~vtkParallelRenderManager() +{ + this->SetRenderWindow(NULL); + if (this->Controller && this->AddedRMIs) + { + this->Controller->RemoveFirstRMI(vtkParallelRenderManager::RENDER_RMI_TAG); + this->Controller->RemoveFirstRMI(COMPUTE_VISIBLE_PROP_BOUNDS_RMI_TAG); + this->AddedRMIs = 0; + } + this->SetController(NULL); + this->FullImage->Delete(); + this->ReducedImage->Delete(); + this->Viewports->Delete(); + this->Timer->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "ParallelRendering: " + << (this->ParallelRendering ? "on" : "off") << endl; + os << indent << "RenderEventPropagation: " + << (this->RenderEventPropagation ? "on" : "off") << endl; + os << indent << "UseCompositing: " + << (this->UseCompositing ? "on" : "off") << endl; + + os << indent << "ObservingRendererWindow: " + << (this->ObservingRenderWindow ? "yes" : "no") << endl; + os << indent << "ObservingRenderer: " + << (this->ObservingRenderer ? "yes" : "no") << endl; + os << indent << "Locked: " << (this->Lock ? "yes" : "no") << endl; + + os << indent << "ImageReductionFactor: " + << this->ImageReductionFactor << endl; + os << indent << "MaxImageReductionFactor: " + << this->MaxImageReductionFactor << endl; + os << indent << "AutoImageReductionFactor: " + << (this->AutoImageReductionFactor ? "on" : "off") << endl; + + if (this->MagnifyImageMethod == vtkParallelRenderManager::LINEAR) + { + os << indent << "MagnifyImageMethod: LINEAR\n"; + } + else if (this->MagnifyImageMethod == vtkParallelRenderManager::NEAREST) + { + os << indent << "MagnifyImageMethod: NEAREST\n"; + } + + os << indent << "WriteBackImages: " + << (this->WriteBackImages ? "on" : "off") << endl; + os << indent << "MagnifyImages: " + << (this->MagnifyImages ? "on" : "off") << endl; + + os << indent << "FullImageSize: (" + << this->FullImageSize[0] << ", " << this->FullImageSize[1] << ")" << endl; + os << indent << "ReducedImageSize: (" + << this->ReducedImageSize[0] << ", " + << this->ReducedImageSize[1] << ")" << endl; + + os << indent << "RenderWindow: " << this->RenderWindow << endl; + os << indent << "Controller: " << this->Controller << endl; + os << indent << "RootProcessId: " << this->RootProcessId << endl; + + os << indent << "Last render time: " << this->RenderTime << endl; + + os << indent << "Last image processing time: " + << this->ImageProcessingTime << endl; + os << indent << "UseRGBA: " << this->UseRGBA << endl; +} + +//---------------------------------------------------------------------------- +vtkRenderWindow *vtkParallelRenderManager::MakeRenderWindow() +{ + vtkDebugMacro("MakeRenderWindow"); + + return vtkRenderWindow::New(); +} + +//---------------------------------------------------------------------------- +vtkRenderer *vtkParallelRenderManager::MakeRenderer() +{ + vtkDebugMacro("MakeRenderer"); + + return vtkRenderer::New(); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SetRenderWindow(vtkRenderWindow *renWin) +{ + vtkDebugMacro("SetRenderWindow"); + + vtkRendererCollection *rens; + vtkRenderer *ren; + + if (this->RenderWindow == renWin) + { + return; + } + this->Modified(); + + if (this->RenderWindow) + { + // Remove all of the observers. + if (this->ObservingRenderWindow) + { + rens = this->RenderWindow->GetRenderers(); + ren = rens->GetFirstRenderer(); + if (ren) + { + ren->RemoveObserver(this->StartRenderTag); + ren->RemoveObserver(this->EndRenderTag); + } + + if (this->ObservingRenderer) + { + this->ObservingRenderer = 0; + } + this->ObservingRenderWindow = 0; + } + if (this->ObservingAbort) + { + this->RenderWindow->RemoveObserver(this->AbortRenderCheckTag); + this->ObservingAbort = 0; + } + + // Delete the reference. + this->RenderWindow->UnRegister(this); + this->RenderWindow = NULL; + } + + this->RenderWindow = renWin; + if (this->RenderWindow) + { + vtkCallbackCommand *cbc; + + this->RenderWindow->Register(this); + + // In case a subclass wants to raise aborts. + cbc = vtkCallbackCommand::New(); + cbc->SetCallback(::AbortRenderCheck); + cbc->SetClientData((void*)this); + // renWin will delete the cbc when the observer is removed. + this->AbortRenderCheckTag = renWin->AddObserver(vtkCommand::AbortCheckEvent, + cbc); + cbc->Delete(); + this->ObservingAbort = 1; + + if (this->Controller) + { + if (this->Controller->GetLocalProcessId() == this->RootProcessId) + { + rens = this->RenderWindow->GetRenderers(); + ren = rens->GetFirstRenderer(); + if (ren) + { + this->ObservingRenderWindow = 1; + + cbc = vtkCallbackCommand::New(); + cbc->SetCallback(::StartRender); + cbc->SetClientData((void*)this); + // renWin will delete the cbc when the observer is removed. + this->StartRenderTag = ren->AddObserver(vtkCommand::StartEvent,cbc); + cbc->Delete(); + + cbc = vtkCallbackCommand::New(); + cbc->SetCallback(::EndRender); + cbc->SetClientData((void*)this); + // renWin will delete the cbc when the observer is removed. + this->EndRenderTag = ren->AddObserver(vtkCommand::EndEvent,cbc); + cbc->Delete(); + + this->ObservingRenderer = 1; + + //cbc = vtkCallbackCommand::New(); + //cbc->SetCallback(::ResetCameraClippingRange); + //cbc->SetClientData((void*)this); + // ren will delete the cbc when the observer is removed. + //this->ResetCameraClippingRangeTag = + //ren->AddObserver(vtkCommand::ResetCameraClippingRangeEvent,cbc); + //cbc->Delete(); + + //cbc = vtkCallbackCommand::New(); + //cbc->SetCallback(::ResetCamera); + //cbc->SetClientData((void*)this); + // ren will delete the cbc when the observer is removed. + //this->ResetCameraTag = + //ren->AddObserver(vtkCommand::ResetCameraEvent,cbc); + //cbc->Delete(); + } + } + else // LocalProcessId != RootProcessId + { + rens = this->RenderWindow->GetRenderers(); + ren = rens->GetFirstRenderer(); + if (ren) + { + this->ObservingRenderWindow = 1; + + cbc= vtkCallbackCommand::New(); + cbc->SetCallback(::SatelliteStartRender); + cbc->SetClientData((void*)this); + // renWin will delete the cbc when the observer is removed. + this->StartRenderTag = ren->AddObserver(vtkCommand::StartEvent,cbc); + cbc->Delete(); + + cbc = vtkCallbackCommand::New(); + cbc->SetCallback(::SatelliteEndRender); + cbc->SetClientData((void*)this); + // renWin will delete the cbc when the observer is removed. + this->EndRenderTag = ren->AddObserver(vtkCommand::EndEvent,cbc); + cbc->Delete(); + } + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SetController(vtkMultiProcessController *controller) +{ + //Regular vtkSetObjectMacro: + vtkSetObjectBodyMacro(Controller,vtkMultiProcessController,controller) + + // We've changed the controller. This may change how observers are attached + // to the render window. + if (this->RenderWindow) + { + vtkRenderWindow *saveRenWin = this->RenderWindow; + saveRenWin->Register(this); + this->SetRenderWindow(NULL); + this->SetRenderWindow(saveRenWin); + saveRenWin->UnRegister(this); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::InitializePieces() +{ + vtkDebugMacro("InitializePieces"); + + vtkRendererCollection *rens; + vtkRenderer *ren; + vtkActorCollection *actors; + vtkActor *actor; + vtkMapper *mapper; + vtkPolyDataMapper *pdMapper; + int piece, numPieces; + + if ((this->RenderWindow == NULL) || (this->Controller == NULL)) + { + vtkWarningMacro("Called InitializePieces before setting RenderWindow or Controller"); + return; + } + piece = this->Controller->GetLocalProcessId(); + numPieces = this->Controller->GetNumberOfProcesses(); + + rens = this->RenderWindow->GetRenderers(); + vtkCollectionSimpleIterator rsit; + rens->InitTraversal(rsit); + while ( (ren = rens->GetNextRenderer(rsit)) ) + { + actors = ren->GetActors(); + vtkCollectionSimpleIterator ait; + actors->InitTraversal(ait); + while ( (actor = actors->GetNextActor(ait)) ) + { + mapper = actor->GetMapper(); + pdMapper = vtkPolyDataMapper::SafeDownCast(mapper); + if (pdMapper) + { + pdMapper->SetPiece(piece); + pdMapper->SetNumberOfPieces(numPieces); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::InitializeOffScreen() +{ + vtkDebugMacro("InitializeOffScreen"); + + if ((this->RenderWindow == NULL) || (this->Controller == NULL)) + { + vtkWarningMacro("Called InitializeOffScreen before setting RenderWindow or Controller"); + return; + } + + if ( (this->Controller->GetLocalProcessId() != this->RootProcessId) || + !this->WriteBackImages ) + { + this->RenderWindow->OffScreenRenderingOn(); + } + else + { + this->RenderWindow->OffScreenRenderingOff(); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::StartInteractor() +{ + vtkDebugMacro("StartInteractor"); + + if ((this->Controller == NULL) || (this->RenderWindow == NULL)) + { + vtkErrorMacro("Must set Controller and RenderWindow before starting interactor."); + return; + } + + if (this->Controller->GetLocalProcessId() == this->RootProcessId) + { + vtkRenderWindowInteractor *inter = this->RenderWindow->GetInteractor(); + if (!inter) + { + vtkErrorMacro("Render window does not have an interactor."); + } + else + { + inter->Initialize(); + inter->Start(); + } + //By the time we reach here, the interaction is finished. + this->StopServices(); + } + else + { + this->StartServices(); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::StartServices() +{ + vtkDebugMacro("StartServices"); + + if (!this->Controller) + { + vtkErrorMacro("Must set Controller before starting service"); + return; + } + if (this->Controller->GetLocalProcessId() == this->RootProcessId) + { + vtkWarningMacro("Starting service on root process (probably not what you wanted to do)"); + } + + this->InitializeRMIs(); + this->Controller->ProcessRMIs(); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::StopServices() +{ + vtkDebugMacro("StopServices"); + + if (!this->Controller) + { + vtkErrorMacro("Must set Controller before stopping service"); + return; + } + if (this->Controller->GetLocalProcessId() != this->RootProcessId) + { + vtkErrorMacro("Can only stop services on root node"); + return; + } + + int numProcs = this->Controller->GetNumberOfProcesses(); + for (int id = 0; id < numProcs; id++) + { + if (id == this->RootProcessId) continue; + this->Controller->TriggerRMI(id,vtkMultiProcessController::BREAK_RMI_TAG); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::StartRender() +{ + vtkParallelRenderManager::RenderWindowInfoInt winInfoInt; + vtkParallelRenderManager::RenderWindowInfoDouble winInfoDouble; + vtkParallelRenderManager::RendererInfoInt renInfoInt; + vtkParallelRenderManager::RendererInfoDouble renInfoDouble; + vtkParallelRenderManager::LightInfoDouble lightInfoDouble; + + vtkDebugMacro("StartRender"); + + if ((this->Controller == NULL) || (this->Lock)) + { + return; + } + this->Lock = 1; + + this->FullImageUpToDate = 0; + this->ReducedImageUpToDate = 0; + this->RenderWindowImageUpToDate = 0; + + if (this->FullImage->GetPointer(0) == this->ReducedImage->GetPointer(0)) + { + // "Un-share" pointer for full/reduced images in case we need separate + // arrays this run. + this->ReducedImage->Initialize(); + } + + if (!this->ParallelRendering) + { + this->Lock = 0; + return; + } + + this->InvokeEvent(vtkCommand::StartEvent, NULL); + + // Used to time the total render (without compositing). + this->Timer->StartTimer(); + + if (this->AutoImageReductionFactor) + { + this->SetImageReductionFactorForUpdateRate( + this->RenderWindow->GetDesiredUpdateRate()); + } + + int id; + int numProcs = this->Controller->GetNumberOfProcesses(); + + // Make adjustments for window size. + int *tilesize = this->RenderWindow->GetSize(); + // To me, it seems dangerous for RenderWindow to return a size bigger + // than it actually supports or for GetSize to not return the same values + // as SetSize. Yet this is the case when tile rendering is established + // in RenderWindow. Correct for this. + int size[2]; + int *tilescale; + tilescale = this->RenderWindow->GetTileScale(); + size[0] = tilesize[0]/tilescale[0]; size[1] = tilesize[1]/tilescale[1]; + if ((size[0] == 0) || (size[1] == 0)) + { + // It helps to have a real window size. + vtkDebugMacro("Resetting window size to 300x300"); + size[0] = size[1] = 300; + this->RenderWindow->SetSize(size[0], size[1]); + } + this->FullImageSize[0] = size[0]; + this->FullImageSize[1] = size[1]; + //Round up. + this->ReducedImageSize[0] = + (int)((size[0]+this->ImageReductionFactor-1)/this->ImageReductionFactor); + this->ReducedImageSize[1] = + (int)((size[1]+this->ImageReductionFactor-1)/this->ImageReductionFactor); + + // Collect and distribute information about current state of RenderWindow + vtkRendererCollection *rens = this->RenderWindow->GetRenderers(); + winInfoInt.FullSize[0] = this->FullImageSize[0]; + winInfoInt.FullSize[1] = this->FullImageSize[1]; + winInfoInt.ReducedSize[0] = this->ReducedImageSize[0]; + winInfoInt.ReducedSize[1] = this->ReducedImageSize[1]; +// winInfoInt.NumberOfRenderers = rens->GetNumberOfItems(); + winInfoInt.NumberOfRenderers = 1; + winInfoDouble.ImageReductionFactor = this->ImageReductionFactor; + winInfoInt.UseCompositing = this->UseCompositing; + winInfoDouble.DesiredUpdateRate = this->RenderWindow->GetDesiredUpdateRate(); + + for (id = 0; id < numProcs; id++) + { + if (id == this->RootProcessId) + { + continue; + } + if (this->RenderEventPropagation) + { + this->Controller->TriggerRMI(id, NULL, 0, + vtkParallelRenderManager::RENDER_RMI_TAG); + } + this->Controller->Send((int *)(&winInfoInt), + vtkParallelRenderManager::WIN_INFO_INT_SIZE, + id, + vtkParallelRenderManager::WIN_INFO_INT_TAG); + this->Controller->Send((double *)(&winInfoDouble), + vtkParallelRenderManager::WIN_INFO_DOUBLE_SIZE, + id, + vtkParallelRenderManager::WIN_INFO_DOUBLE_TAG); + } + + this->SendWindowInformation(); + + if (this->ImageReductionFactor > 1) + { + this->Viewports->SetNumberOfTuples(rens->GetNumberOfItems()); + } + vtkRenderer *ren; + ren = rens->GetFirstRenderer(); + + if (ren) + { + ren->GetViewport(renInfoDouble.Viewport); + + // Adjust Renderer viewports to get reduced size image. + if (this->ImageReductionFactor > 1) + { + this->Viewports->SetTuple(0, renInfoDouble.Viewport); + renInfoDouble.Viewport[0] /= this->ImageReductionFactor; + renInfoDouble.Viewport[1] /= this->ImageReductionFactor; + renInfoDouble.Viewport[2] /= this->ImageReductionFactor; + renInfoDouble.Viewport[3] /= this->ImageReductionFactor; + ren->SetViewport(renInfoDouble.Viewport); + } + + vtkCamera *cam = ren->GetActiveCamera(); + cam->GetPosition(renInfoDouble.CameraPosition); + cam->GetFocalPoint(renInfoDouble.CameraFocalPoint); + cam->GetViewUp(renInfoDouble.CameraViewUp); + cam->GetClippingRange(renInfoDouble.CameraClippingRange); + renInfoDouble.CameraViewAngle = cam->GetViewAngle(); + cam->GetWindowCenter(renInfoDouble.WindowCenter); + + ren->GetBackground(renInfoDouble.Background); + if (cam->GetParallelProjection()) + { + renInfoDouble.ParallelScale = cam->GetParallelScale(); + } + else + { + renInfoDouble.ParallelScale = 0.0; + } + vtkLightCollection *lc = ren->GetLights(); + renInfoInt.NumberOfLights = lc->GetNumberOfItems(); + + for (id = 0; id < numProcs; id++) + { + if (id == this->RootProcessId) + { + continue; + } + this->Controller->Send((int *)(&renInfoInt), + vtkParallelRenderManager::REN_INFO_INT_SIZE, + id, + vtkParallelRenderManager::REN_INFO_INT_TAG); + this->Controller->Send((double *)(&renInfoDouble), + vtkParallelRenderManager::REN_INFO_DOUBLE_SIZE, + id, + vtkParallelRenderManager::REN_INFO_DOUBLE_TAG); + } + + vtkLight *light; + vtkCollectionSimpleIterator lsit; + for (lc->InitTraversal(lsit); (light = lc->GetNextLight(lsit)); ) + { + lightInfoDouble.Type = (double)(light->GetLightType()); + light->GetPosition(lightInfoDouble.Position); + light->GetFocalPoint(lightInfoDouble.FocalPoint); + + for (id = 0; id < numProcs; id++) + { + if (id == this->RootProcessId) continue; + this->Controller->Send((double *)(&lightInfoDouble), + vtkParallelRenderManager::LIGHT_INFO_DOUBLE_SIZE, + id, + vtkParallelRenderManager::LIGHT_INFO_DOUBLE_TAG); + } + } + } + + this->SendRendererInformation(ren); + + this->PreRenderProcessing(); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::EndRender() +{ + if (!this->ParallelRendering) + { + return; + } + + this->Timer->StopTimer(); + this->RenderTime = this->Timer->GetElapsedTime(); + this->ImageProcessingTime = 0; + + if (!this->UseCompositing) + { + this->Lock = 0; + return; + } + + // EndRender only happens on root. + if (this->CheckForAbortComposite()) + { + this->Lock = 0; + return; + } + + this->PostRenderProcessing(); + + // Restore renderer viewports, if necessary. + if (this->ImageReductionFactor > 1) + { + vtkRenderer *ren; + ren = this->RenderWindow->GetRenderers()->GetFirstRenderer(); + ren->SetViewport(this->Viewports->GetPointer(0)); + } + + this->WriteFullImage(); + + this->InvokeEvent(vtkCommand::EndEvent, NULL); + + this->Lock = 0; +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SatelliteEndRender() +{ + if (this->CheckForAbortComposite()) + { + return; + } +// It's a mistake to check ParallelRendering on the Satellites. +// The Root node decides if the render calls are to be propagated to the +// satellites...the satellites always reply to the Root nodes requests. +// if (!this->ParallelRendering) +// { +// return; +// } + if (!this->UseCompositing) + { + return; + } + + this->PostRenderProcessing(); + + this->WriteFullImage(); + + this->InvokeEvent(vtkCommand::EndEvent, NULL); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::RenderRMI() +{ + this->RenderWindow->Render(); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::ResetCamera(vtkRenderer *ren) +{ + vtkDebugMacro("ResetCamera"); + + double bounds[6]; + + if (this->Lock) + { + // Can't query other processes in the middle of a render. + // Just grab local value instead. + this->LocalComputeVisiblePropBounds(ren, bounds); + ren->ResetCamera(bounds); + return; + } + + this->Lock = 1; + + this->ComputeVisiblePropBounds(ren, bounds); + // Keep from setting camera from some outrageous value. + if (!vtkMath::AreBoundsInitialized(bounds)) + { + // See if the not pickable values are better. + ren->ComputeVisiblePropBounds(bounds); + if (!vtkMath::AreBoundsInitialized(bounds)) + { + this->Lock = 0; + return; + } + } + ren->ResetCamera(bounds); + + this->Lock = 0; +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::ResetCameraClippingRange(vtkRenderer *ren) +{ + vtkDebugMacro("ResetCameraClippingRange"); + + double bounds[6]; + + if (this->Lock) + { + // Can't query other processes in the middle of a render. + // Just grab local value instead. + this->LocalComputeVisiblePropBounds(ren, bounds); + ren->ResetCameraClippingRange(bounds); + return; + } + + this->Lock = 1; + + this->ComputeVisiblePropBounds(ren, bounds); + ren->ResetCameraClippingRange(bounds); + + this->Lock = 0; +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::ComputeVisiblePropBoundsRMI() +{ + vtkDebugMacro("ComputeVisiblePropBoundsRMI"); + int i; + + // Get proper renderer. + int renderId = -1; + if (!this->Controller->Receive(&renderId, 1, this->RootProcessId, + vtkParallelRenderManager::REN_ID_TAG)) + { + return; + } + vtkRendererCollection *rens = this->RenderWindow->GetRenderers(); + vtkRenderer *ren = NULL; + vtkCollectionSimpleIterator rsit; + rens->InitTraversal(rsit); + for (i = 0; i <= renderId; i++) + { + ren = rens->GetNextRenderer(rsit); + } + + if (ren == NULL) + { + vtkWarningMacro("Client requested invalid renderer in " + "ComputeVisiblePropBoundsRMI\n" + "Defaulting to first renderer"); + ren = rens->GetFirstRenderer(); + } + + double bounds[6]; + this->LocalComputeVisiblePropBounds(ren, bounds); + + this->Controller->Send(bounds, 6, this->RootProcessId, + vtkParallelRenderManager::BOUNDS_TAG); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::LocalComputeVisiblePropBounds(vtkRenderer *ren, + double bounds[6]) +{ + ren->ComputeVisiblePropBounds(bounds); +} + + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::ComputeVisiblePropBounds(vtkRenderer *ren, + double bounds[6]) +{ + vtkDebugMacro("ComputeVisiblePropBounds"); + + if (!this->ParallelRendering) + { + ren->ComputeVisiblePropBounds(bounds); + return; + } + + if (this->Controller) + { + if (this->Controller->GetLocalProcessId() != this->RootProcessId) + { + vtkErrorMacro("ComputeVisiblePropBounds/ResetCamera can only be called on root process"); + return; + } + + vtkRendererCollection *rens = this->RenderWindow->GetRenderers(); + vtkCollectionSimpleIterator rsit; + rens->InitTraversal(rsit); + int renderId = 0; + while (1) + { + vtkRenderer *myren = rens->GetNextRenderer(rsit); + if (myren == NULL) + { + vtkWarningMacro("ComputeVisiblePropBounds called with unregistered renderer " << ren << "\nDefaulting to first renderer."); + renderId = 0; + break; + } + if (myren == ren) + { + //Found correct renderer. + break; + } + renderId++; + } + + //Invoke RMI's on servers to perform their own ComputeVisiblePropBounds. + int numProcs = this->Controller->GetNumberOfProcesses(); + int id; + for (id = 0; id < numProcs; id++) + { + if (id == this->RootProcessId) + { + continue; + } + this->Controller->TriggerRMI( + id, vtkParallelRenderManager::COMPUTE_VISIBLE_PROP_BOUNDS_RMI_TAG); + this->Controller->Send(&renderId, 1, id, + vtkParallelRenderManager::REN_ID_TAG); + } + + //Now that all the RMI's have been invoked, we can safely query our + //local bounds even if an Update requires a parallel operation. + + this->LocalComputeVisiblePropBounds(ren, bounds); + + //Collect all the bounds. + for (id = 0; id < numProcs; id++) + { + double tmp[6]; + + if (id == this->RootProcessId) + { + continue; + } + + this->Controller->Receive(tmp, 6, id, vtkParallelRenderManager::BOUNDS_TAG); + + if (tmp[0] < bounds[0]) + { + bounds[0] = tmp[0]; + } + if (tmp[1] > bounds[1]) + { + bounds[1] = tmp[1]; + } + if (tmp[2] < bounds[2]) + { + bounds[2] = tmp[2]; + } + if (tmp[3] > bounds[3]) + { + bounds[3] = tmp[3]; + } + if (tmp[4] < bounds[4]) + { + bounds[4] = tmp[4]; + } + if (tmp[5] > bounds[5]) + { + bounds[5] = tmp[5]; + } + } + } + else + { + vtkWarningMacro("ComputeVisiblePropBounds/ResetCamera called before Controller set"); + + ren->ComputeVisiblePropBounds(bounds); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::InitializeRMIs() +{ + vtkDebugMacro("InitializeRMIs"); + + if (this->Controller == NULL) + { + vtkErrorMacro("InitializeRMIs requires a controller."); + return; + } + + this->AddedRMIs = 1; + this->Controller->AddRMI(::RenderRMI, this, + vtkParallelRenderManager::RENDER_RMI_TAG); + this->Controller->AddRMI(::ComputeVisiblePropBoundsRMI, this, + vtkParallelRenderManager:: + COMPUTE_VISIBLE_PROP_BOUNDS_RMI_TAG); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::ResetAllCameras() +{ + vtkDebugMacro("ResetAllCameras"); + + if (!this->RenderWindow) + { + vtkErrorMacro("Called ResetAllCameras before RenderWindow set"); + return; + } + + vtkRendererCollection *rens; + vtkRenderer *ren; + + rens = this->RenderWindow->GetRenderers(); + vtkCollectionSimpleIterator rsit; + for (rens->InitTraversal(rsit); (ren = rens->GetNextRenderer(rsit)); ) + { + this->ResetCamera(ren); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SetImageReductionFactor(double factor) +{ + // Clamp factor. + factor = (factor < 1) ? 1 : factor; + factor = (factor > this->MaxImageReductionFactor) + ? this->MaxImageReductionFactor : factor; + + if (this->MagnifyImageMethod == LINEAR) + { + // Make factor be a power of 2. + int pow_of_2 = 1; + while (pow_of_2 <= factor) + { + pow_of_2 <<= 1; + } + factor = pow_of_2 >> 1; + } + + if (factor == this->ImageReductionFactor) + { + return; + } + + this->ImageReductionFactor = factor; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SetMagnifyImageMethod(int method) +{ + if (this->MagnifyImageMethod == method) + { + return; + } + + this->MagnifyImageMethod = method; + // May need to modify image reduction factor. + this->SetImageReductionFactor(this->ImageReductionFactor); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SetImageReductionFactorForUpdateRate(double desiredUpdateRate) +{ + vtkDebugMacro("Setting reduction factor for update rate of " + << desiredUpdateRate); + + if (desiredUpdateRate == 0.0) + { + this->SetImageReductionFactor(1); + return; + } + + int *size = this->RenderWindow->GetSize(); + int numPixels = size[0]*size[1]; + int numReducedPixels + = (int)(numPixels/(this->ImageReductionFactor*this->ImageReductionFactor)); + + double renderTime = this->GetRenderTime(); + double pixelTime = this->GetImageProcessingTime(); + + double timePerPixel; + if (numReducedPixels > 0) + { + timePerPixel = pixelTime/numReducedPixels; + } + else + { + // Must be before first render. + this->SetImageReductionFactor(1); + return; + } + + this->AverageTimePerPixel = (3*this->AverageTimePerPixel + timePerPixel)/4; + if (this->AverageTimePerPixel <= 0) + { + this->AverageTimePerPixel = 0; + this->SetImageReductionFactor(1); + return; + } + + double allottedPixelTime = 1.0/desiredUpdateRate - renderTime; + // Give ourselves at least 15% of render time. + if (allottedPixelTime < 0.15*renderTime) + { + allottedPixelTime = 0.15*renderTime; + } + + vtkDebugMacro("TimePerPixel: " << timePerPixel + << ", AverageTimePerPixel: " << this->AverageTimePerPixel + << ", AllottedPixelTime: " << allottedPixelTime); + + double pixelsToUse = allottedPixelTime/this->AverageTimePerPixel; + + if ( (pixelsToUse < 1) || + (numPixels/pixelsToUse > this->MaxImageReductionFactor) ) + { + this->SetImageReductionFactor(this->MaxImageReductionFactor); + } + else if (pixelsToUse >= numPixels) + { + this->SetImageReductionFactor(1); + } + else + { + this->SetImageReductionFactor((int)(numPixels/pixelsToUse)); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SetRenderWindowSize() +{ + if (!this->RenderWindow->GetOffScreenRendering()) + { + // Make sure we can support the requested image size. + int *screensize = this->RenderWindow->GetScreenSize(); + if (this->FullImageSize[0] > screensize[0]) + { + // Reduce both dimensions to preserve aspect ratio. + this->FullImageSize[1] + = (this->FullImageSize[1]*screensize[0])/this->FullImageSize[0]; + this->FullImageSize[0] = screensize[0]; + } + if (this->FullImageSize[1] > screensize[1]) + { + // Reduce both dimensions to preserve aspect ratio. + this->FullImageSize[0] + = (this->FullImageSize[0]*screensize[1])/this->FullImageSize[1]; + this->FullImageSize[1] = screensize[1]; + } + + // Make sure the reduced image is no bigger than the full image. + if (this->ReducedImageSize[0] > this->FullImageSize[0]) + { + this->ReducedImageSize[0] = this->FullImageSize[0]; + } + if (this->ReducedImageSize[1] > this->FullImageSize[1]) + { + this->ReducedImageSize[1] = this->FullImageSize[1]; + } + } + + // Correct image reduction factor. + this->ImageReductionFactor + = (double)this->FullImageSize[0]/this->ReducedImageSize[0]; + + this->RenderWindow->SetSize(this->FullImageSize[0], this->FullImageSize[1]); +} + +//---------------------------------------------------------------------------- +int vtkParallelRenderManager::LastRenderInFrontBuffer() +{ + return this->RenderWindow->GetSwapBuffers(); +} + +//---------------------------------------------------------------------------- +int vtkParallelRenderManager::ChooseBuffer() +{ + // Choose the back buffer if double buffering is on. + return (this->RenderWindow->GetDoubleBuffer() == 0); +} + +//---------------------------------------------------------------------------- +static void MagnifyImageNearest(vtkUnsignedCharArray *fullImage, + int fullImageSize[2], + vtkUnsignedCharArray *reducedImage, + int reducedImageSize[2], + vtkTimerLog *timer) +{ + int numComp = reducedImage->GetNumberOfComponents();; + + fullImage->SetNumberOfComponents(numComp); + fullImage->SetNumberOfTuples(fullImageSize[0]*fullImageSize[1]); + + timer->StartTimer(); + + // Inflate image. + double xstep = (double)reducedImageSize[0]/fullImageSize[0]; + double ystep = (double)reducedImageSize[1]/fullImageSize[1]; + unsigned char *lastsrcline = NULL; + for (int y = 0; y < fullImageSize[1]; y++) + { + unsigned char *destline = + fullImage->GetPointer(numComp*fullImageSize[0]*y); + unsigned char *srcline = + reducedImage->GetPointer(numComp*reducedImageSize[0]*(int)(ystep*y)); + if (srcline == lastsrcline) + { + // This line same as last one. + memcpy(destline, + (const unsigned char *)(destline - numComp*fullImageSize[0]), + numComp*fullImageSize[0]); + } + else + { + for (int x = 0; x < fullImageSize[0]; x++) + { + int srcloc = numComp*(int)(x*xstep); + int destloc = numComp*x; + for (int i = 0; i < numComp; i++) + { + destline[destloc + i] = srcline[srcloc + i]; + } + } + lastsrcline = srcline; + } + } + + timer->StopTimer(); +} +static void MagnifyImageNearestFourComp(vtkUnsignedCharArray *fullImage, + int fullImageSize[2], + vtkUnsignedCharArray *reducedImage, + int reducedImageSize[2], + vtkTimerLog *timer) +{ + int numComp = reducedImage->GetNumberOfComponents(); + if (numComp != 4) + { + vtkGenericWarningMacro("MagnifyImageNearestFourComp only works on 4 component image"); + return; + } + fullImage->SetNumberOfComponents(numComp); + fullImage->SetNumberOfTuples(fullImageSize[0]*fullImageSize[1]); + + timer->StartTimer(); + + // Making a bunch of tmp variables for speed within the loops + // Look I know the compiler should optimize this stuff + // but I don't trust compilers... besides testing shows + // this code is faster than the old code + float xstep = (float)reducedImageSize[0]/fullImageSize[0]; + float ystep = (float)reducedImageSize[1]/fullImageSize[1]; + float xaccum=0, yaccum=0; + int xfullsize = fullImageSize[0]; + int xmemsize = xfullsize*numComp; + int yfullsize = fullImageSize[1]; + int xreducedsize = reducedImageSize[0]; + unsigned int *lastsrcline = NULL; + unsigned int *destline = (unsigned int*)fullImage->GetPointer(0); + unsigned int *srcline = (unsigned int*)reducedImage->GetPointer(0); + unsigned int *srczero = srcline; + + // Inflate image. + for (int y=0; y < yfullsize; ++y, yaccum+=ystep) + { + // If this line same as last one. + if (srcline == lastsrcline) + { + memcpy(destline, destline - xfullsize, xmemsize); + } + else + { + for (int x = 0; x < xfullsize; ++x, xaccum+=xstep) + { + destline[x] = srcline[(int)(xaccum)]; + } + xaccum=0; + lastsrcline = srcline; + } + destline += xfullsize; + srcline = srczero + xreducedsize * int(yaccum); // Performance fixme + } + + timer->StopTimer(); +} +//---------------------------------------------------------------------------- +// A neat trick to quickly divide all 4 of the bytes in an integer by 2. +#define VTK_VEC_DIV_2(intvector) (((intvector) >> 1) & 0x7F7F7F7F) + +static void MagnifyImageLinear(vtkUnsignedCharArray *fullImage, + int fullImageSize[2], + vtkUnsignedCharArray *reducedImage, + int reducedImageSize[2], + vtkTimerLog *timer) +{ + int xmag, ymag; + int x, y; + int srcComp = reducedImage->GetNumberOfComponents();; + + //Allocate full image so all pixels are on 4-byte integer boundaries. + fullImage->SetNumberOfComponents(4); + fullImage->SetNumberOfTuples(fullImageSize[0]*fullImageSize[1]); + + timer->StartTimer(); + + // Guess x and y magnification. Round up to ensure we do not try to + // read data from the image data that does not exist. + xmag = (fullImageSize[0]+reducedImageSize[0]-1)/reducedImageSize[0]; + ymag = (fullImageSize[1]+reducedImageSize[1]-1)/reducedImageSize[1]; + + // For speed, we only magnify by powers of 2. Round up to the nearest + // power of 2 to ensure that the reduced image is large enough. + int powOf2; + for (powOf2 = 1; powOf2 < xmag; powOf2 <<= 1); + xmag = powOf2; + for (powOf2 = 1; powOf2 < ymag; powOf2 <<= 1); + ymag = powOf2; + + unsigned char *srcline = reducedImage->GetPointer(0); + unsigned char *destline = fullImage->GetPointer(0); + for (y = 0; y < fullImageSize[1]; y += ymag) + { + unsigned char *srcval = srcline; + unsigned char *destval = destline; + for (x = 0; x < fullImageSize[0]; x += xmag) + { + destval[0] = srcval[0]; + destval[1] = srcval[1]; + destval[2] = srcval[2]; + destval[3] = 0xFF; //Hope we don't need the alpha value. + srcval += srcComp; + destval += 4*xmag; + } + srcline += srcComp*reducedImageSize[0]; + destline += 4*fullImageSize[0]*ymag; + } + + // Now that we have everything on 4-byte boundaries, we will treat + // everything as integers for much faster computation. + unsigned int *image = (unsigned int *)fullImage->GetPointer(0); + + // Fill in scanlines. + for (; xmag > 1; xmag >>= 1) + { + int halfXMag = xmag/2; + for (y = 0; y < fullImageSize[1]; y += ymag) + { + unsigned int *scanline = image + y*fullImageSize[0]; + int maxX = fullImageSize[0] - halfXMag; //Don't access bad memory. + for (x = halfXMag; x < maxX; x += xmag) + { + scanline[x] = + VTK_VEC_DIV_2(scanline[x-halfXMag]) + + VTK_VEC_DIV_2(scanline[x+halfXMag]); + } + } + } + + // Add blank scanlines. + for (; ymag > 1; ymag >>= 1) + { + int halfYMag = ymag/2; + int maxY = fullImageSize[1] - halfYMag; //Don't access bad memory. + for (y = halfYMag; y < maxY; y += ymag) + { + unsigned int *destline2 = image + y*fullImageSize[0]; + unsigned int *srcline1 = image + (y-halfYMag)*fullImageSize[0]; + unsigned int *srcline2 = image + (y+halfYMag)*fullImageSize[0]; + for (x = 0; x < fullImageSize[0]; x++) + { + destline2[x] = VTK_VEC_DIV_2(srcline1[x]) + VTK_VEC_DIV_2(srcline2[x]); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::MagnifyReducedImage() +{ + if ((this->FullImageUpToDate)) + { + return; + } + + this->ReadReducedImage(); + + if (this->FullImage->GetPointer(0) != this->ReducedImage->GetPointer(0)) + { + switch (this->MagnifyImageMethod) + { + case vtkParallelRenderManager::NEAREST: + if (this->ReducedImage->GetNumberOfComponents() == 4) + { + MagnifyImageNearestFourComp(this->FullImage, this->FullImageSize, + this->ReducedImage, this->ReducedImageSize, + this->Timer); + } + else + { + MagnifyImageNearest(this->FullImage, this->FullImageSize, + this->ReducedImage, this->ReducedImageSize, + this->Timer); + } + break; + case LINEAR: + MagnifyImageLinear(this->FullImage, this->FullImageSize, + this->ReducedImage, this->ReducedImageSize, + this->Timer); + break; + } + // We log the image inflation under render time because it is inversely + // proportional to the image size. This makes the auto image reduction + // calculation work better. + this->RenderTime += this->Timer->GetElapsedTime(); + } + + this->FullImageUpToDate = 1; +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::WriteFullImage() +{ + if (this->RenderWindowImageUpToDate || !this->WriteBackImages) + { + return; + } + + if ( this->MagnifyImages + && ( (this->FullImageSize[0] != this->ReducedImageSize[0]) + || (this->FullImageSize[1] != this->ReducedImageSize[1]) ) ) + { + this->MagnifyReducedImage(); + this->SetRenderWindowPixelData(this->FullImage, this->FullImageSize); + } + else + { + // Only write back image if it has already been read and potentially + // changed. + if (this->ReducedImageUpToDate) + { + this->SetRenderWindowPixelData(this->ReducedImage, + this->ReducedImageSize); + } + } + + this->RenderWindowImageUpToDate = 1; +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::SetRenderWindowPixelData( + vtkUnsignedCharArray *pixels, const int pixelDimensions[2]) +{ + if (pixels->GetNumberOfComponents() == 4) + { + this->RenderWindow->SetRGBACharPixelData(0, 0, + pixelDimensions[0]-1, + pixelDimensions[1]-1, + pixels, + this->ChooseBuffer()); + } + else + { + this->RenderWindow->SetPixelData(0, 0, + pixelDimensions[0]-1, + pixelDimensions[1]-1, + pixels, + this->ChooseBuffer()); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::ReadReducedImage() +{ + if (this->ReducedImageUpToDate) + { + return; + } + + this->Timer->StartTimer(); + + if (this->ImageReductionFactor > 1) + { + if (this->UseRGBA) + { + this->RenderWindow->GetRGBACharPixelData(0, 0, this->ReducedImageSize[0]-1, + this->ReducedImageSize[1]-1, + this->ChooseBuffer(), + this->ReducedImage); + } + else + { + this->RenderWindow->GetPixelData(0, 0, this->ReducedImageSize[0]-1, + this->ReducedImageSize[1]-1, + this->ChooseBuffer(), + this->ReducedImage); + } + } + else + { + if (this->UseRGBA) + { + this->RenderWindow->GetRGBACharPixelData(0, 0, this->FullImageSize[0]-1, + this->FullImageSize[1]-1, + this->ChooseBuffer(), + this->FullImage); + } + else + { + this->RenderWindow->GetPixelData(0, 0, this->FullImageSize[0]-1, + this->FullImageSize[1]-1, + this->ChooseBuffer(), + this->FullImage); + } + this->FullImageUpToDate = 1; + this->ReducedImage + ->SetNumberOfComponents(this->FullImage->GetNumberOfComponents()); + this->ReducedImage->SetArray(this->FullImage->GetPointer(0), + this->FullImage->GetSize(), 1); + this->ReducedImage->SetNumberOfTuples(this->FullImage->GetNumberOfTuples()); + } + + this->Timer->StopTimer(); + this->ImageProcessingTime += this->Timer->GetElapsedTime(); + + this->ReducedImageUpToDate = 1; +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::GetPixelData(vtkUnsignedCharArray *data) +{ + if (!this->RenderWindow) + { + vtkErrorMacro("Tried to read pixel data from non-existent RenderWindow"); + return; + } + + // Read image from RenderWindow and magnify if necessary. + this->MagnifyReducedImage(); + + data->SetNumberOfComponents(this->FullImage->GetNumberOfComponents()); + data->SetArray(this->FullImage->GetPointer(0), + this->FullImage->GetSize(), 1); + data->SetNumberOfTuples(this->FullImage->GetNumberOfTuples()); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::GetPixelData(int x1, int y1, int x2, int y2, + vtkUnsignedCharArray *data) +{ + if (!this->RenderWindow) + { + vtkErrorMacro("Tried to read pixel data from non-existent RenderWindow"); + return; + } + + this->MagnifyReducedImage(); + + if (x1 > x2) + { + int tmp = x1; + x1 = x2; + x2 = tmp; + } + if (y1 > y2) + { + int tmp = y1; + y1 = y2; + y2 = tmp; + } + + if ( (x1 < 0) || (x2 >= this->FullImageSize[0]) || + (y1 < 0) || (y2 >= this->FullImageSize[1]) ) + { + vtkErrorMacro("Requested pixel data out of RenderWindow bounds"); + return; + } + + vtkIdType width = x2 - x1 + 1; + vtkIdType height = y2 - y1 + 1; + + int numComp = this->FullImage->GetNumberOfComponents(); + + data->SetNumberOfComponents(numComp); + data->SetNumberOfTuples(width*height); + + const unsigned char *src = this->FullImage->GetPointer(0); + unsigned char *dest = data->WritePointer(0, width*height*numComp); + + for (int row = 0; row < height; row++) + { + memcpy(dest + row*width*numComp, + src + (row+y1)*this->FullImageSize[0]*numComp + x1*numComp, + width*numComp); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::GetReducedPixelData(vtkUnsignedCharArray *data) +{ + if (!this->RenderWindow) + { + vtkErrorMacro("Tried to read pixel data from non-existent RenderWindow"); + return; + } + + // Read image from RenderWindow and magnify if necessary. + this->ReadReducedImage(); + + data->SetNumberOfComponents(this->ReducedImage->GetNumberOfComponents()); + data->SetArray(this->ReducedImage->GetPointer(0), + this->ReducedImage->GetSize(), 1); + data->SetNumberOfTuples(this->ReducedImage->GetNumberOfTuples()); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::GetReducedPixelData(int x1, int y1, + int x2, int y2, + vtkUnsignedCharArray *data) +{ + if (!this->RenderWindow) + { + vtkErrorMacro("Tried to read pixel data from non-existent RenderWindow"); + return; + } + + this->ReadReducedImage(); + + if (x1 > x2) + { + int tmp = x1; + x1 = x2; + x2 = tmp; + } + if (y1 > y2) + { + int tmp = y1; + y1 = y2; + y2 = tmp; + } + + if ( (x1 < 0) || (x2 >= this->ReducedImageSize[0]) || + (y1 < 0) || (y2 >= this->ReducedImageSize[1]) ) + { + vtkErrorMacro("Requested pixel data out of RenderWindow bounds"); + return; + } + + vtkIdType width = x2 - x1 + 1; + vtkIdType height = y2 - y1 + 1; + + int numComp = this->ReducedImage->GetNumberOfComponents(); + + data->SetNumberOfComponents(numComp); + data->SetNumberOfTuples(width*height); + + const unsigned char *src = this->ReducedImage->GetPointer(0); + unsigned char *dest = data->WritePointer(0, width*height*numComp); + + for (int row = 0; row < height; row++) + { + memcpy(dest + row*width*numComp, + src + (row+y1)*this->ReducedImageSize[0]*numComp + x1*numComp, + width*numComp); + } +} + +// Static function prototypes -------------------------------------------- + +static void AbortRenderCheck(vtkObject *vtkNotUsed(caller), + unsigned long vtkNotUsed(event), + void *clientData, void *) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)clientData; + self->CheckForAbortRender(); +} + +static void StartRender(vtkObject *vtkNotUsed(caller), + unsigned long vtkNotUsed(event), + void *clientData, void *) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)clientData; + self->StartRender(); +} + +static void EndRender(vtkObject *vtkNotUsed(caller), + unsigned long vtkNotUsed(event), + void *clientData, void *) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)clientData; + self->EndRender(); +} + +static void SatelliteStartRender(vtkObject *vtkNotUsed(caller), + unsigned long vtkNotUsed(event), + void *clientData, void *) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)clientData; + self->SatelliteStartRender(); +} + +static void SatelliteEndRender(vtkObject *vtkNotUsed(caller), + unsigned long vtkNotUsed(event), + void *clientData, void *) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)clientData; + self->SatelliteEndRender(); +} + +/* +static void ResetCamera(vtkObject *caller, + unsigned long vtkNotUsed(event), + void *clientData, void *) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)clientData; + vtkRenderer *ren = (vtkRenderer *)caller; + self->ResetCamera(ren); +} + +static void ResetCameraClippingRange(vtkObject *caller, + unsigned long vtkNotUsed(event), + void *clientData, void *) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)clientData; + vtkRenderer *ren = (vtkRenderer *)caller; + self->ResetCameraClippingRange(ren); +} +*/ + +static void RenderRMI(void *arg, void *, int, int) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)arg; + self->RenderRMI(); +} + +static void ComputeVisiblePropBoundsRMI(void *arg, void *, int, int) +{ + vtkParallelRenderManager *self = (vtkParallelRenderManager *)arg; + self->ComputeVisiblePropBoundsRMI(); +} + + + +//---------------------------------------------------------------------------- +// the variables such as winInfoInt are initialzed prior to use +#if defined(_MSC_VER) && !defined(VTK_DISPLAY_WIN32_WARNINGS) +#pragma warning ( disable : 4701 ) +#endif + +void vtkParallelRenderManager::SatelliteStartRender() +{ + vtkParallelRenderManager::RenderWindowInfoInt winInfoInt; + vtkParallelRenderManager::RenderWindowInfoDouble winInfoDouble; + vtkParallelRenderManager::RendererInfoInt renInfoInt; + vtkParallelRenderManager::RendererInfoDouble renInfoDouble; + vtkParallelRenderManager::LightInfoDouble lightInfoDouble; + int i, j; + + vtkDebugMacro("SatelliteStartRender"); + + this->FullImageUpToDate = 0; + this->ReducedImageUpToDate = 0; + this->RenderWindowImageUpToDate = 0; + + if (this->FullImage->GetPointer(0) == this->ReducedImage->GetPointer(0)) + { + // "Un-share" pointer for full/reduced images in case we need separate + // arrays this run. + this->ReducedImage->Initialize(); + } + +//if (!this->ParallelRendering) +// { +// return; +// } + + this->InvokeEvent(vtkCommand::StartEvent, NULL); + + if (!this->Controller->Receive((int *)(&winInfoInt), + vtkParallelRenderManager::WIN_INFO_INT_SIZE, + this->RootProcessId, + vtkParallelRenderManager::WIN_INFO_INT_TAG)) + { + return; + } + + if (!this->Controller->Receive((double *)(&winInfoDouble), + vtkParallelRenderManager::WIN_INFO_DOUBLE_SIZE, + this->RootProcessId, + vtkParallelRenderManager::WIN_INFO_DOUBLE_TAG)) + { + return; + } + + this->ReceiveWindowInformation(); + + this->RenderWindow->SetDesiredUpdateRate(winInfoDouble.DesiredUpdateRate); + this->SetUseCompositing(winInfoInt.UseCompositing); + if (this->MaxImageReductionFactor < winInfoDouble.ImageReductionFactor) + { + this->SetMaxImageReductionFactor(winInfoDouble.ImageReductionFactor); + } + this->SetImageReductionFactor(winInfoDouble.ImageReductionFactor); + this->FullImageSize[0] = winInfoInt.FullSize[0]; + this->FullImageSize[1] = winInfoInt.FullSize[1]; + this->ReducedImageSize[0] = winInfoInt.ReducedSize[0]; + this->ReducedImageSize[1] = winInfoInt.ReducedSize[1]; + this->SetRenderWindowSize(); + + vtkCollectionSimpleIterator rsit; + vtkRendererCollection *rens = this->RenderWindow->GetRenderers(); + + this->Viewports->SetNumberOfTuples(rens->GetNumberOfItems()); + + rens->InitTraversal(rsit); + for (i = 0; i < winInfoInt.NumberOfRenderers; i++) + { + if (!this->Controller->Receive((int *)(&renInfoInt), + vtkParallelRenderManager::REN_INFO_INT_SIZE, + this->RootProcessId, + vtkParallelRenderManager::REN_INFO_INT_TAG)) + { + continue; + } + if (!this->Controller->Receive((double *)(&renInfoDouble), + vtkParallelRenderManager::REN_INFO_DOUBLE_SIZE, + this->RootProcessId, + vtkParallelRenderManager::REN_INFO_DOUBLE_TAG)) + { + continue; + } + vtkLightCollection *lc = NULL; + vtkCollectionSimpleIterator lsit; + vtkRenderer *ren = rens->GetNextRenderer(rsit); + if (ren == NULL) + { + vtkErrorMacro("Not enough renderers"); + } + else + { + this->Viewports->SetTuple(i, ren->GetViewport()); + ren->SetViewport(renInfoDouble.Viewport); + ren->SetBackground(renInfoDouble.Background[0], + renInfoDouble.Background[1], + renInfoDouble.Background[2]); + vtkCamera *cam = ren->GetActiveCamera(); + cam->SetPosition(renInfoDouble.CameraPosition); + cam->SetFocalPoint(renInfoDouble.CameraFocalPoint); + cam->SetViewUp(renInfoDouble.CameraViewUp); + cam->SetClippingRange(renInfoDouble.CameraClippingRange); + cam->SetViewAngle(renInfoDouble.CameraViewAngle); + cam->SetWindowCenter(renInfoDouble.WindowCenter[0], + renInfoDouble.WindowCenter[1]); + if (renInfoDouble.ParallelScale != 0.0) + { + cam->ParallelProjectionOn(); + cam->SetParallelScale(renInfoDouble.ParallelScale); + } + else + { + cam->ParallelProjectionOff(); + } + lc = ren->GetLights(); + lc->InitTraversal(lsit); + } + + for (j = 0; j < renInfoInt.NumberOfLights; j++) + { + if (ren != NULL && lc != NULL) + { + vtkLight *light = lc->GetNextLight(lsit); + if (light == NULL) + { + // Not enough lights? Just create them. + vtkDebugMacro("Adding light"); + light = vtkLight::New(); + ren->AddLight(light); + light->Delete(); + } + + this->Controller->Receive((double *)(&lightInfoDouble), + vtkParallelRenderManager::LIGHT_INFO_DOUBLE_SIZE, + this->RootProcessId, + vtkParallelRenderManager::LIGHT_INFO_DOUBLE_TAG); + light->SetLightType((int)(lightInfoDouble.Type)); + light->SetPosition(lightInfoDouble.Position); + light->SetFocalPoint(lightInfoDouble.FocalPoint); + } + } + + if (ren != NULL) + { + vtkLight *light; + while ((light = lc->GetNextLight(lsit))) + { + // To many lights? Just remove the extras. + ren->RemoveLight(light); + } + } + + this->ReceiveRendererInformation(ren); + } + + this->PreRenderProcessing(); +} + +//---------------------------------------------------------------------------- +void vtkParallelRenderManager::TileWindows(int xsize, int ysize, int ncolumn) +{ + if (!this->RenderWindow || !this->Controller) + { + return; + } + + int procId = this->Controller->GetLocalProcessId(); + + int row = procId / ncolumn; + int column = procId % ncolumn; + + this->RenderWindow->SetPosition(xsize*column, ysize*row); +} + +//---------------------------------------------------------------------------- + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (disable:858) +#endif + +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef StartService +void const vtkParallelRenderManager::StartServiceA() +{ + VTK_LEGACY_REPLACED_BODY(vtkParallelRenderManager::StartService, "VTK 5.0", + vtkParallelRenderManager::StartServices); + this->StartServices(); +} +void const vtkParallelRenderManager::StartServiceW() +{ + VTK_LEGACY_REPLACED_BODY(vtkParallelRenderManager::StartService, "VTK 5.0", + vtkParallelRenderManager::StartServices); + this->StartServices(); +} +# endif +void const vtkParallelRenderManager::StartService() +{ + VTK_LEGACY_REPLACED_BODY(vtkParallelRenderManager::StartService, "VTK 5.0", + vtkParallelRenderManager::StartServices); + this->StartServices(); +} +#endif diff --git a/Parallel/vtkParallelRenderManager.h b/Parallel/vtkParallelRenderManager.h new file mode 100644 index 0000000..c06da03 --- /dev/null +++ b/Parallel/vtkParallelRenderManager.h @@ -0,0 +1,498 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParallelRenderManager.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + Copyright 2003 Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000, there is a non-exclusive license for use of this work by + or on behalf of the U.S. Government. Redistribution and use in source and + binary forms, with or without modification, are permitted provided that this + Notice and any statement of authorship are reproduced on all copies. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParallelRenderManager - An object to control parallel rendering. +// +// .SECTION Description: +// vtkParallelRenderManager operates in multiple processes. It provides +// proper renderers and render windows for performing the parallel +// rendering correctly. It can also attach itself to render windows and +// propagate rendering events and camera views. +// +// This class is based on the vtkCompositeManager class, except that it can +// handle any type of parallel rendering. +// +// .SECTION Note: +// Many parallel rendering schemes do not correctly handle transparency. +// Unless otherwise documented, assume a sub class does not. +// +// .SECTION ToDo: +// Synchronization/barrier primitives. +// +// Query ranges of scalar values of objects in addition to the boundry in +// three-space +// + +#ifndef __vtkParallelRenderManager_h +#define __vtkParallelRenderManager_h + +#include "vtkObject.h" + +class vtkRenderWindow; +class vtkRenderer; +class vtkUnsignedCharArray; +class vtkDoubleArray; +class vtkTimerLog; +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkParallelRenderManager : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkParallelRenderManager, vtkObject); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + // Description: + // Builds a vtkRenderWindow compatible with this render manager. The + // user program is responsible for registering the render window with the + // SetRenderWindow method and calling Delete. It is not advisable to use + // a parallel render manager with a render window that was not built with + // this method. + virtual vtkRenderWindow *MakeRenderWindow(); + + // Description: + // Builds a vtkRenderer compatible with this render manager. (Should we + // also register it?) The user program is responsible for calling + // Delete. It is not advisable to use a parallel render manager with a + // renderer that was not built with this method. + virtual vtkRenderer *MakeRenderer(); + + // Description: + // Set/Get the RenderWindow to use for compositing. + // We add a start and end observer to the window. + vtkGetObjectMacro(RenderWindow, vtkRenderWindow); + virtual void SetRenderWindow(vtkRenderWindow *renWin); + + // Description: + // Set/Get the vtkMultiProcessController which will handle communications + // for the parallel rendering. + vtkGetObjectMacro(Controller, vtkMultiProcessController); + virtual void SetController(vtkMultiProcessController *controller); + + // Description: + // This method sets the piece and number of pieces for each + // actor with a polydata mapper. + virtual void InitializePieces(); + + // Description: + // Make all rendering windows not viewable set as off screen rendering. + // To make all renderwindows on screen rendering again, call + // OffScreenRenderingOff on all the render windows. This class assumes + // the window on root node is the only one viewable. Subclasses should + // change this as necessary. + virtual void InitializeOffScreen(); + + // Description: + // Initializes the RMIs and then, if on root node, starts the interactor + // on the attached render window. Otherwise, starts processing RMIs. + // When the interactor returns, it breaks the RMI listening on all other + // processors. + virtual void StartInteractor(); + + // Description: + // If on node other than root, starts serving RMI requests for parallel + // renders. + virtual void StartServices(); + + // Description: + // If on root node, stops the RMI processing on all service nodes. + virtual void StopServices(); + + // Description: + // Callbacks that initialize and finish rendering and other tasks. + virtual void StartRender(); + virtual void EndRender(); + virtual void SatelliteStartRender(); + virtual void SatelliteEndRender(); + virtual void RenderRMI(); + virtual void ResetCamera(vtkRenderer *ren); + virtual void ResetCameraClippingRange(vtkRenderer *ren); + virtual void ComputeVisiblePropBoundsRMI(); + + virtual void InitializeRMIs(); + + // Description: + // Resets the camera of each renderer contained in the RenderWindow. + // Should only be called in the "root" process, and all remote processes + // must be processing RMIs for this method to complete. + virtual void ResetAllCameras(); + + // Description: + // Calculates the bounds by gathering information from all processes. + virtual void ComputeVisiblePropBounds(vtkRenderer *ren, double bounds[6]); + + // Description: + // Turns on/off parallel rendering. When on (the default) the object + // responds to render events of the attached window, propagates the + // render event to other processors, and otherwise enables the parallel + // rendering process. + vtkSetMacro(ParallelRendering, int); + vtkGetMacro(ParallelRendering, int); + vtkBooleanMacro(ParallelRendering, int); + + // Description: + // Turns on/off render event propagation. When on (the default) and + // ParallelRendering is on, process 0 will send an RMI call to all remote + // processes to perform a synchronized render. When off, render must be + // manually called on each process. + vtkSetMacro(RenderEventPropagation, int); + vtkGetMacro(RenderEventPropagation, int); + vtkBooleanMacro(RenderEventPropagation, int); + + // Description: + // This is used for tiled display rendering. When data has been + // duplicated on all processes, then we do not need to compositing. + // Cameras and renders are still propagated though. + vtkSetMacro(UseCompositing, int); + vtkGetMacro(UseCompositing, int); + vtkBooleanMacro(UseCompositing, int); + + // Description: + // Set/Get the reduction factor (for sort-last based parallel renderers). + // The size of rendered image is divided by the reduction factor and then + // is blown up to the size of the current vtkRenderWindow. Setting + // higher reduction factors enables shorter image transfer times (which + // is often the bottleneck) but will greatly reduce image quality. A + // reduction factor of 2 or greater should only be used for intermediate + // images in interactive applications. A reduction factor of 1 (or less) + // will result in no change in image quality. A parallel render manager + // may ignore the image reduction factor if it will result in little or + // no performance enhancements (eg. it does not do image space + // manipulations). + virtual void SetImageReductionFactor(double factor); + vtkGetMacro(ImageReductionFactor, double); + + vtkSetMacro(MaxImageReductionFactor, double); + vtkGetMacro(MaxImageReductionFactor, double); + + // Description: + // Sets the ReductionFactor based on the given desired update rate and + // the rendering metrics taken from the last time UpdateServerInfo was + // called. Note that if AutoReductionFactor is on, this function is called + // with the desired update rate of the render window automatically. + virtual void SetImageReductionFactorForUpdateRate(double DesiredUpdateRate); + + // Description: + // If on, the ReductionFactor is automatically adjusted to best meet the + // the DesiredUpdateRate in the current RenderWindow based on metrics + // from the last render. + vtkSetMacro(AutoImageReductionFactor, int); + vtkGetMacro(AutoImageReductionFactor, int); + vtkBooleanMacro(AutoImageReductionFactor, int); + + // Description: + // Get rendering metrics. + vtkGetMacro(RenderTime, double); + vtkGetMacro(ImageProcessingTime, double); + + // Description: + // If on (the default), the result of any image space manipulations are + // written back to the render window frame buffer. If off, the image + // stored in the frame buffer may not be correct. Either way, the + // correct frame buffer images may be read with + // vtkParallelRenderManager::GetPixelData. Turning WriteBackImages off + // may result in a speedup if the render window is not visible to the user + // and images are read back for further processing or transit. + vtkSetMacro(WriteBackImages, int); + vtkGetMacro(WriteBackImages, int); + vtkBooleanMacro(WriteBackImages, int); + + // Description: + // If on (the default), when the ImageReductionFactor is greater than 1 + // and WriteBackImages is on, the image will be magnified to fill the + // entire render window. + vtkSetMacro(MagnifyImages, int); + vtkGetMacro(MagnifyImages, int); + vtkBooleanMacro(MagnifyImages, int); + +//BTX + enum { NEAREST, LINEAR }; +//ETX + + // Description: + // Sets the method used to magnify images. Nearest simply replicates + // each pixel enough times to fill the image. Linear performs linear + // interpolation between the pixels. + virtual void SetMagnifyImageMethod(int method); + vtkGetMacro(MagnifyImageMethod, int); + void SetMagnifyImageMethodToNearest() { + this->SetMagnifyImageMethod(NEAREST); + } + void SetMagnifyImageMethodToLinear() { + this->SetMagnifyImageMethod(LINEAR); + } + + // Description: + // The most appropriate way to retrieve full size image data after a + // render. Will work regardless of whether WriteBackImages or + // MagnifyImage is on or off. The data returned may be a shallow copy of + // an internal array. Therefore, the data may be invalid after the next + // render or if the ParallelRenderManager is destroyed. + virtual void GetPixelData(vtkUnsignedCharArray *data); + virtual void GetPixelData(int x1, int y1, int x2, int y2, + vtkUnsignedCharArray *data); + + // Description: + // The most appropriate way to retrieve reduced size image data after a + // render. Will work regardless of whether WriteBackImages or + // MagnifyImage is on or off. The data returned may be a shallow copy of + // an internal array. Therefore, the data may be invalid after the next + // render or if the ParallelRenderManager is destroyed. + virtual void GetReducedPixelData(vtkUnsignedCharArray *data); + virtual void GetReducedPixelData(int x1, int y1, int x2, int y2, + vtkUnsignedCharArray *data); + + // Description: + // Returns the full image size calculated at the last render. + vtkGetVector2Macro(FullImageSize, int); + // Description: + // Returns the reduced image size calculated at the last render. + vtkGetVector2Macro(ReducedImageSize, int); + + // Description: + // Given the x and y size of the render windows, reposition them + // in a tile of n columns. + void TileWindows(int xsize, int ysize, int nColumns); + + // Description: + // Get/Set if all Images must use RGBA instead of RGB. By default, + // this flag is on. + vtkSetMacro(UseRGBA, int); + vtkGetMacro(UseRGBA, int); + +//BTX + enum Tags { + RENDER_RMI_TAG=34532, + COMPUTE_VISIBLE_PROP_BOUNDS_RMI_TAG=54636, + WIN_INFO_INT_TAG=87834, + WIN_INFO_DOUBLE_TAG=87835, + REN_INFO_INT_TAG=87836, + REN_INFO_DOUBLE_TAG=87837, + LIGHT_INFO_DOUBLE_TAG=87838, + REN_ID_TAG=58794, + BOUNDS_TAG=23543 + }; + + virtual void CheckForAbortRender() {} + virtual int CheckForAbortComposite() {return 0;} +//ETX + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (push) +# pragma warning (disable:858) +#endif + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define StartServiceA StartService +# define StartServiceW StartService +#endif + + // Description: + // @deprecated Replaced by vtkParallelRenderManager::StartServices() + // as of VTK 5.0. + VTK_LEGACY(virtual void const StartService()); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef StartServiceW +# undef StartServiceA + //BTX + VTK_LEGACY(virtual void const StartServiceA()); + VTK_LEGACY(virtual void const StartServiceW()); + //ETX +#endif + +// Reset disabled warning about qualifiers on return types. +#if defined(__INTEL_COMPILER) +# pragma warning (pop) +#endif +#if defined(_COMPILER_VERSION) +# pragma reset woff 3303 +#endif + +protected: + vtkParallelRenderManager(); + ~vtkParallelRenderManager(); + + vtkRenderWindow *RenderWindow; + vtkMultiProcessController *Controller; + + // Description: + // The "root" node's process id. This is the node which is listening for + // and propagating new render events from the RenderWindow. All + // processes on the controller must have the same value. This value must + // be set before SetRenderWindow method is called. In the constructor or + // the SetController methods are good places. By default this is set to + // 0. + int RootProcessId; + + int ObservingRenderWindow; + int ObservingRenderer; + int ObservingAbort; + + unsigned long StartRenderTag; + unsigned long EndRenderTag; + unsigned long ResetCameraTag; + unsigned long ResetCameraClippingRangeTag; + unsigned long AbortRenderCheckTag; + + double ImageReductionFactor; + double MaxImageReductionFactor; + int AutoImageReductionFactor; + + int WriteBackImages; + int MagnifyImages; + int MagnifyImageMethod; + + int UseRGBA; + + int FullImageSize[2]; + int ReducedImageSize[2]; + + vtkUnsignedCharArray *FullImage; + vtkUnsignedCharArray *ReducedImage; + + int FullImageUpToDate; + int ReducedImageUpToDate; + int RenderWindowImageUpToDate; + + vtkDoubleArray *Viewports; + + int Lock; + int ParallelRendering; + int RenderEventPropagation; + int UseCompositing; + + vtkTimerLog *Timer; + + double RenderTime; + double ImageProcessingTime; + + // Description: + // Used by SetImageReductionFactorForUpdateRate to smooth transitions + // transitions between image reduction factors. + double AverageTimePerPixel; + + // Description: + // Used to synchronize rendering information per frame. + virtual void SendWindowInformation() {} + virtual void ReceiveWindowInformation() {} + virtual void SendRendererInformation(vtkRenderer *) {}; + virtual void ReceiveRendererInformation(vtkRenderer *) {}; + + // Description: + // Here is a good place to handle processing of data before and after + // render. + virtual void PreRenderProcessing() = 0; + virtual void PostRenderProcessing() = 0; + + // Description: + // Called in satellites to set the render window size to the current + // FullImageSize and ReducedImageSize (or vice versa) + virtual void SetRenderWindowSize(); + + // Description: + // Called by ComputeVisiblePropBoundsRMI to get the bounds of a local + // renderer. Override this method if the true bounds are different than + // those reported by the renderer. + virtual void LocalComputeVisiblePropBounds(vtkRenderer *ren, double bounds[6]); + + // Description: + // When called, fills FullImage. + virtual void MagnifyReducedImage(); + + // Description: + // Write the full image back to the RenderWindow. + virtual void WriteFullImage(); + + // Description: + // Reads in the reduced image from the RenderWindow. + virtual void ReadReducedImage(); + + // Description: + // Returns 1 if the RenderWindow's last image is in the front buffer, 0 + // if it is in the back. + virtual int LastRenderInFrontBuffer(); + + // Description: + // Select buffer to read from / render into. + virtual int ChooseBuffer(); + + // Description: + // Sets the current render window's pixel data. + virtual void SetRenderWindowPixelData(vtkUnsignedCharArray *pixels, + const int pixelDimensions[2]); + +//BTX + struct RenderWindowInfoInt + { + int FullSize[2]; + int ReducedSize[2]; + int NumberOfRenderers; + int UseCompositing; + }; + + struct RenderWindowInfoDouble + { + double ImageReductionFactor; + double DesiredUpdateRate; + }; + + struct RendererInfoInt + { + int NumberOfLights; + }; + + struct RendererInfoDouble + { + double Viewport[4]; + double CameraPosition[3]; + double CameraFocalPoint[3]; + double CameraViewUp[3]; + double WindowCenter[2]; + double CameraClippingRange[2]; + double CameraViewAngle; + double Background[3]; + double ParallelScale; + }; + + struct LightInfoDouble + { + double Position[3]; + double FocalPoint[3]; + double Type; + }; + + static const int WIN_INFO_INT_SIZE; + static const int WIN_INFO_DOUBLE_SIZE; + static const int REN_INFO_INT_SIZE; + static const int REN_INFO_DOUBLE_SIZE; + static const int LIGHT_INFO_DOUBLE_SIZE; +//ETX + + int AddedRMIs; +private: + vtkParallelRenderManager(const vtkParallelRenderManager &); //Not implemented + void operator=(const vtkParallelRenderManager &); //Not implemented +}; + +#endif //__vtkParalleRenderManager_h diff --git a/Parallel/vtkPassThroughFilter.cxx b/Parallel/vtkPassThroughFilter.cxx new file mode 100644 index 0000000..440650c --- /dev/null +++ b/Parallel/vtkPassThroughFilter.cxx @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPassThroughFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPassThroughFilter.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" + +vtkCxxRevisionMacro(vtkPassThroughFilter, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkPassThroughFilter); + +int vtkPassThroughFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + // This has to be here because it initialized all field datas. + output->CopyStructure( input ); + + // Pass all. (data object's field data is passed by the + // superclass after this method) + output->GetPointData()->PassData( input->GetPointData() ); + output->GetCellData()->PassData( input->GetCellData() ); + + return 1; +} + +void vtkPassThroughFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Parallel/vtkPassThroughFilter.h b/Parallel/vtkPassThroughFilter.h new file mode 100644 index 0000000..1306422 --- /dev/null +++ b/Parallel/vtkPassThroughFilter.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPassThroughFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPassThroughFilter - Filter which shallow copies it's input to it's output +// .SECTION Description +// This filter shallow copies it's input to it's output. It is normally +// used by PVSources with multiple outputs as the VTK filter in the +// dummy connection objects at each output. + +#ifndef __vtkPassThroughFilter_h +#define __vtkPassThroughFilter_h + +#include "vtkDataSetAlgorithm.h" + +class vtkFieldData; + +class VTK_PARALLEL_EXPORT vtkPassThroughFilter : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkPassThroughFilter,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a new vtkPassThroughFilter. + static vtkPassThroughFilter *New(); + + +protected: + + vtkPassThroughFilter() {}; + virtual ~vtkPassThroughFilter() {}; + + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + +private: + vtkPassThroughFilter(const vtkPassThroughFilter&); // Not implemented. + void operator=(const vtkPassThroughFilter&); // Not implemented. +}; + +#endif + + diff --git a/Parallel/vtkPieceScalars.cxx b/Parallel/vtkPieceScalars.cxx new file mode 100644 index 0000000..4edd9d3 --- /dev/null +++ b/Parallel/vtkPieceScalars.cxx @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPieceScalars.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPieceScalars.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPieceScalars, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkPieceScalars); + +//---------------------------------------------------------------------------- +vtkPieceScalars::vtkPieceScalars() +{ + this->CellScalarsFlag = 0; + this->RandomMode = 0; +} + +//---------------------------------------------------------------------------- +vtkPieceScalars::~vtkPieceScalars() +{ +} + +//---------------------------------------------------------------------------- +// Append data sets into single unstructured grid +int vtkPieceScalars::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *pieceColors; + vtkIdType num; + + if (this->CellScalarsFlag) + { + num = input->GetNumberOfCells(); + } + else + { + num = input->GetNumberOfPoints(); + } + + int piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + + if (this->RandomMode) + { + pieceColors = this->MakeRandomScalars(piece, num); + } + else + { + pieceColors = this->MakePieceScalars(piece, num); + } + + output->ShallowCopy(input); + pieceColors->SetName("Piece"); + if (this->CellScalarsFlag) + { + output->GetCellData()->AddArray(pieceColors); + output->GetCellData()->SetActiveScalars(pieceColors->GetName()); + } + else + { + output->GetPointData()->AddArray(pieceColors); + output->GetPointData()->SetActiveScalars(pieceColors->GetName()); + } + + pieceColors->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +vtkIntArray *vtkPieceScalars::MakePieceScalars(int piece, vtkIdType num) +{ + vtkIdType i; + vtkIntArray *pieceColors = NULL; + + pieceColors = vtkIntArray::New(); + pieceColors->SetNumberOfTuples(num); + + for (i = 0; i < num; ++i) + { + pieceColors->SetValue(i, piece); + } + + return pieceColors; +} + +//---------------------------------------------------------------------------- +vtkFloatArray *vtkPieceScalars::MakeRandomScalars(int piece, vtkIdType num) +{ + vtkIdType i; + vtkFloatArray *pieceColors = NULL; + float randomValue; + + vtkMath::RandomSeed(piece); + randomValue = vtkMath::Random(); + + pieceColors = vtkFloatArray::New(); + pieceColors->SetNumberOfTuples(num); + + for (i = 0; i < num; ++i) + { + pieceColors->SetValue(i, randomValue); + } + + return pieceColors; +} + +//---------------------------------------------------------------------------- +void vtkPieceScalars::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "RandomMode: " << this->RandomMode << endl; + if (this->CellScalarsFlag) + { + os << indent << "ScalarMode: CellData\n"; + } + else + { + os << indent << "ScalarMode: PointData\n"; + } +} diff --git a/Parallel/vtkPieceScalars.h b/Parallel/vtkPieceScalars.h new file mode 100644 index 0000000..798dc36 --- /dev/null +++ b/Parallel/vtkPieceScalars.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPieceScalars.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPieceScalars - Sets all cell scalars from the update piece. +// +// .SECTION Description +// vtkPieceScalars is meant to display which piece is being requested +// as scalar values. It is usefull for visualizing the partitioning for +// streaming or distributed pipelines. +// +// .SECTION See Also +// vtkPolyDataStreamer + +#ifndef __vtkPieceScalars_h +#define __vtkPieceScalars_h + +#include "vtkDataSetAlgorithm.h" + +class vtkFloatArray; +class vtkIntArray; + +class VTK_PARALLEL_EXPORT vtkPieceScalars : public vtkDataSetAlgorithm +{ +public: + static vtkPieceScalars *New(); + + vtkTypeRevisionMacro(vtkPieceScalars,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Option to centerate cell scalars of poi9nts scalars. Default is point scalars. + void SetScalarModeToCellData() {this->SetCellScalarsFlag(1);} + void SetScalarModeToPointData() {this->SetCellScalarsFlag(0);} + int GetScalarMode() {return this->CellScalarsFlag;} + + // Dscription: + // This option uses a random mapping between pieces and scalar values. + // The scalar values are choosen between 0 and 1. By default, random mode is off. + vtkSetMacro(RandomMode, int); + vtkGetMacro(RandomMode, int); + vtkBooleanMacro(RandomMode, int); + +protected: + vtkPieceScalars(); + ~vtkPieceScalars(); + + // Append the pieces. + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkIntArray *MakePieceScalars(int piece, vtkIdType numScalars); + vtkFloatArray *MakeRandomScalars(int piece, vtkIdType numScalars); + + vtkSetMacro(CellScalarsFlag,int); + int CellScalarsFlag; + int RandomMode; +private: + vtkPieceScalars(const vtkPieceScalars&); // Not implemented. + void operator=(const vtkPieceScalars&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkPipelineSize.cxx b/Parallel/vtkPipelineSize.cxx new file mode 100644 index 0000000..953825e --- /dev/null +++ b/Parallel/vtkPipelineSize.cxx @@ -0,0 +1,386 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPipelineSize.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPipelineSize.h" + +#include "vtkAlgorithmOutput.h" +#include "vtkConeSource.h" +#include "vtkDataObject.h" +#include "vtkDataReader.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkLargeInteger.h" +#include "vtkObjectFactory.h" +#include "vtkPSphereSource.h" +#include "vtkPlaneSource.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkDataSetAttributes.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkPipelineSize, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkPipelineSize); + +unsigned long +vtkPipelineSize::GetEstimatedSize(vtkAlgorithm *input, int inputPort, + int connection) +{ + unsigned long sizes[3]; + unsigned long memorySize = 0; + + + if(vtkAlgorithmOutput* inInfo = + input->GetInputConnection(inputPort, connection)) + { + if (vtkAlgorithm* srcAlg = + vtkAlgorithm::SafeDownCast( + inInfo->GetProducer())) + { + this->ComputeSourcePipelineSize(srcAlg, inInfo->GetIndex(), sizes ); + memorySize = sizes[2]; + } + } + + return memorySize; +} + +// The first size is the memory going downstream from here - which is all +// the memory coming in minus any data realeased. The second size is the +// size of the specified output (which can be used by the downstream +// filter when determining how much data it might release). The final size +// is the maximum pipeline size encountered here and upstream from here. +void vtkPipelineSize::ComputeSourcePipelineSize(vtkAlgorithm *src, + int outputPort, + unsigned long size[3]) +{ + // watch for special sources + // handle vtkDataReader subclasses + if (src->IsA("vtkDataReader")) + { + ifstream *ifs; + vtkDataReader *rdr = vtkDataReader::SafeDownCast(src); +#ifdef _WIN32 + ifs = new ifstream(rdr->GetFileName(), ios::in | ios::binary); +#else + ifs = new ifstream(rdr->GetFileName(), ios::in); +#endif + if (!ifs->fail()) + { + ifs->seekg(0,ios::end); + int sz = ifs->tellg()/1024; + size[0] = sz; + size[1] = sz; + size[2] = sz; + return; + } + delete ifs; + } + + // handle some simple sources + vtkLargeInteger sz; + if (src->IsA("vtkConeSource")) + { + vtkConeSource *s = vtkConeSource::SafeDownCast(src); + sz = s->GetResolution(); + sz = sz * 32/1024; + size[0] = sz.CastToUnsignedLong(); + size[1] = size[0]; + size[2] = size[0]; + return; + } + if (src->IsA("vtkPlaneSource")) + { + vtkPlaneSource *s = vtkPlaneSource::SafeDownCast(src); + sz = s->GetXResolution(); + sz = sz * s->GetYResolution()*32/1024; + size[0] = sz.CastToUnsignedLong(); + size[1] = size[0]; + size[2] = size[0]; + return; + } + if (src->IsA("vtkPSphereSource")) + { + vtkPSphereSource *s = vtkPSphereSource::SafeDownCast(src); + size[0] = s->GetEstimatedMemorySize(); + size[1] = size[0]; + size[2] = size[0]; + return; + } + + // otherwise use generic approach + this->GenericComputeSourcePipelineSize(src,outputPort,size); +} + +void vtkPipelineSize::GenericComputeSourcePipelineSize(vtkAlgorithm *src, + int outputPort, + unsigned long size[3]) +{ + unsigned long outputSize[2]; + unsigned long inputPipelineSize[3]; + vtkLargeInteger mySize = 0; + unsigned long maxSize = 0; + vtkLargeInteger goingDownstreamSize = 0; + unsigned long *inputSize = NULL; + int idx; + + // We need some space to store the input sizes if there are any inputs + int numberOfInputs = src->GetTotalNumberOfInputConnections(); + if ( numberOfInputs > 0 ) + { + inputSize = new unsigned long[numberOfInputs]; + } + + // Get the pipeline size propagated down each input. Keep track of max + // pipeline size, how much memory will be required downstream from here, + // the size of each input, and the memory required by this filter when + // it executes. + int port = 0; + int conn = 0; + for (idx = 0; idx < numberOfInputs; ++idx) + { + src->ConvertTotalInputToPortConnection(idx,port,conn); + inputSize[idx] = 0; + if(vtkAlgorithmOutput* inInfo = src->GetInputConnection(port, conn)) + { + if (vtkAlgorithm* srcAlg = + vtkAlgorithm::SafeDownCast(inInfo->GetProducer())) + { + // Get the upstream size of the pipeline, the estimated size of this + // input, and the maximum size seen upstream from here. + this->ComputeSourcePipelineSize(srcAlg, inInfo->GetIndex(), + inputPipelineSize); + + // Save this input size to possibly be used when estimating output size + inputSize[idx] = inputPipelineSize[1]; + + // Is the max returned bigger than the max we've seen so far? + if ( inputPipelineSize[2] > maxSize ) + { + maxSize = inputPipelineSize[2]; + } + + // If we are going to release this input, then its size won't matter + // downstream from here. + vtkDemandDrivenPipeline *ddp = + vtkDemandDrivenPipeline::SafeDownCast(srcAlg->GetExecutive()); + if (ddp && + ddp->GetOutputInformation(inInfo->GetIndex()) + ->Get(vtkDemandDrivenPipeline::RELEASE_DATA())) + { + goingDownstreamSize = goingDownstreamSize + inputPipelineSize[0] - + inputPipelineSize[1]; + } + else + { + goingDownstreamSize = goingDownstreamSize + inputPipelineSize[0]; + } + + // During execution this filter will need all the input data + mySize += inputPipelineSize[0]; + } + } + } + + // Now the we know the size of all input, compute the output size + this->ComputeOutputMemorySize(src, outputPort, inputSize, outputSize ); + + // This filter will produce all output so it needs all that memory. + // Also, all this data will flow downstream to the next source (if it is + // the requested output) or will still exist with no chance of being + // released (if it is the non-requested output) + mySize += outputSize[1]; + goingDownstreamSize += outputSize[1]; + + // Is the state of the pipeline during this filter's execution the + // largest that it has been so far? + if ( mySize.CastToUnsignedLong() > maxSize ) + { + maxSize = mySize.CastToUnsignedLong(); + } + + // The first size is the memory going downstream from here - which is all + // the memory coming in minus any data realeased. The second size is the + // size of the specified output (which can be used by the downstream + // filter when determining how much data it might release). The final size + // is the maximum pipeline size encountered here and upstream from here. + size[0] = goingDownstreamSize.CastToUnsignedLong(); + size[1] = outputSize[0]; + size[2] = maxSize; + + // Delete the space we may have created + if ( inputSize ) + { + delete [] inputSize; + } +} + +void vtkPipelineSize:: +ComputeOutputMemorySize( vtkAlgorithm *src, int outputPort, + unsigned long *inputSize, unsigned long size[2] ) +{ + vtkLargeInteger sz; + + // watch for special filters such as Glyph3D + if (src->IsA("vtkGlyph3D")) + { + // the output size is the same as the source size * the number of points + // we guess the number of points to be 1/16 of the input size in bytes + if (src->GetTotalNumberOfInputConnections() >= 2) + { + sz = inputSize[1]; + sz = sz * inputSize[0]*1024/16; + size[0] = sz.CastToUnsignedLong(); + size[1] = size[0]; + return; + } + } + + this->GenericComputeOutputMemorySize(src, outputPort, inputSize, size); +} + + + +void vtkPipelineSize:: +GenericComputeOutputMemorySize( vtkAlgorithm *src, int outputPort, + unsigned long * vtkNotUsed( inputSize ), + unsigned long size[2] ) +{ + int idx; + vtkLargeInteger tmp = 0; + vtkLargeInteger sz = 0; + + vtkDemandDrivenPipeline *ddp = + vtkDemandDrivenPipeline::SafeDownCast(src->GetExecutive()); + + size[0] = 0; + size[1] = 0; + + // loop through all the outputs asking them how big they are given the + // information that they have on their update extent. Keep track of + // the size of the specified output in size[0], and the sum of all + // output size in size[1]. Ignore input sizes in this default implementation. + for (idx = 0; idx < src->GetNumberOfOutputPorts(); ++idx) + { + vtkInformation *outInfo = ddp->GetOutputInformation(idx); + if (outInfo) + { + tmp = 0; + vtkInformation *dataInfo = + outInfo->Get(vtkDataObject::DATA_OBJECT())->GetInformation(); + if (dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == + VTK_PIECES_EXTENT) + { + // TODO: need something here + tmp = 1; + } + if (dataInfo->Get(vtkDataObject::DATA_EXTENT_TYPE()) == VTK_3D_EXTENT) + { + int uExt[6]; + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),uExt); + tmp = 4; + + vtkInformation *scalarInfo = vtkDataObject::GetActiveFieldInformation(outInfo, + vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS); + int numComp = 1; + if (scalarInfo) + { + tmp = vtkDataArray::GetDataTypeSize( + scalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE())); + if (scalarInfo->Has(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS())) + { + numComp = scalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()); + } + } + tmp *= numComp; + for (idx = 0; idx < 3; ++idx) + { + tmp = tmp*(uExt[idx*2+1] - uExt[idx*2] + 1); + } + tmp /= 1024; + } + if (idx == outputPort ) + { + size[0] = tmp.CastToUnsignedLong(); + } + } + sz += tmp; + } + + size[1] = sz.CastToUnsignedLong(); +} + + +unsigned long vtkPipelineSize::GetNumberOfSubPieces(unsigned long memoryLimit, + vtkPolyDataMapper *mapper) +{ + // find the right number of pieces + if (!mapper->GetInput()) + { + return 1; + } + + vtkPolyData *input = mapper->GetInput(); + unsigned long subDivisions = 1; + unsigned long numPieces = mapper->GetNumberOfPieces(); + unsigned long piece = mapper->GetPiece(); + unsigned long oldSize, size = 0; + float ratio; + + // watch for the limiting case where the size is the maximum size + // represented by an unsigned long. In that case we do not want to do the + // ratio test. We actual test for size < 0.5 of the max unsigned long which + // would indicate that oldSize is about at max unsigned long. + unsigned long maxSize; + maxSize = (((unsigned long)0x1) << (8*sizeof(unsigned long) - 1)); + + // we also have to watch how many pieces we are creating. Since + // NumberOfStreamDivisions is an int, it cannot be more that say 2^31 + // (which is a bit much anyhow) so we also stop if the number of pieces is + // too large. Here we start off with the current number of pieces. + int count = (int) (log(static_cast(numPieces))/log(static_cast(2))); + + // double the number of pieces until the size fits in memory + // or the reduction in size falls to 20% + do + { + oldSize = size; + input->SetUpdateExtent(piece*subDivisions, numPieces*subDivisions); + input->PropagateUpdateExtent(); + size = this->GetEstimatedSize(mapper,0,0); + // watch for the first time through + if (!oldSize) + { + ratio = 0.5; + } + // otherwise the normal ratio calculation + else + { + ratio = size/(float)oldSize; + } + subDivisions = subDivisions*2; + count++; + } + while (size > memoryLimit && + (size > maxSize || ratio < 0.8) && count < 29); + + // undo the last *2 + subDivisions = subDivisions/2; + + return subDivisions; +} + +void vtkPipelineSize::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} diff --git a/Parallel/vtkPipelineSize.h b/Parallel/vtkPipelineSize.h new file mode 100644 index 0000000..79393c2 --- /dev/null +++ b/Parallel/vtkPipelineSize.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPipelineSize.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPipelineSize - compute the memory required by a pipeline + + +#ifndef __vtkPipelineSize_h +#define __vtkPipelineSize_h + +#include "vtkObject.h" +class vtkAlgorithm; +class vtkPolyDataMapper; + +class VTK_PARALLEL_EXPORT vtkPipelineSize : public vtkObject +{ +public: + // Description: + static vtkPipelineSize* New(); + vtkTypeRevisionMacro(vtkPipelineSize,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Compute an estimate of how much memory a pipline will require in + // kilobytes (1024 bytes not 1000) This is only an estimate and the + // calculations in here do not take into account the specifics of many + // sources and filters. + unsigned long GetEstimatedSize(vtkAlgorithm *input, int inputPort, + int connection); + + // Description: + // Determine how many subpieces a mapper should use to fit a target memory + // limit. This takes into account the mapper's Piece and NumberOfPieces. + unsigned long GetNumberOfSubPieces(unsigned long memoryLimit, + vtkPolyDataMapper *mapper); + +protected: + vtkPipelineSize() {}; + void GenericComputeSourcePipelineSize(vtkAlgorithm *src, + int outputPort, + unsigned long size[3]); + void ComputeSourcePipelineSize(vtkAlgorithm *src, + int outputPort, + unsigned long size[3]); + void ComputeOutputMemorySize( vtkAlgorithm *src, + int outputPort, + unsigned long *inputSize, + unsigned long size[2] ); + void GenericComputeOutputMemorySize( vtkAlgorithm *src, + int outputPort, + unsigned long *inputSize, + unsigned long size[2] ); + + +private: + vtkPipelineSize(const vtkPipelineSize&); // Not implemented. + void operator=(const vtkPipelineSize&); // Not implemented. +}; + +#endif + + diff --git a/Parallel/vtkProcessIdScalars.cxx b/Parallel/vtkProcessIdScalars.cxx new file mode 100644 index 0000000..cffba9b --- /dev/null +++ b/Parallel/vtkProcessIdScalars.cxx @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcessIdScalars.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProcessIdScalars.h" + +#include "vtkCellData.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkMath.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkProcessIdScalars, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkProcessIdScalars); + +vtkCxxSetObjectMacro(vtkProcessIdScalars,Controller, + vtkMultiProcessController); + +//---------------------------------------------------------------------------- +vtkProcessIdScalars::vtkProcessIdScalars() +{ + this->CellScalarsFlag = 0; + this->RandomMode = 0; + + this->Controller = vtkMultiProcessController::GetGlobalController(); + if (this->Controller) + { + this->Controller->Register(this); + } +} + +//---------------------------------------------------------------------------- +vtkProcessIdScalars::~vtkProcessIdScalars() +{ + if (this->Controller) + { + this->Controller->Delete(); + this->Controller = 0; + } +} + +//---------------------------------------------------------------------------- +// Append data sets into single unstructured grid +int vtkProcessIdScalars::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkDataArray *pieceColors; + vtkIdType num; + + if (this->CellScalarsFlag) + { + num = input->GetNumberOfCells(); + } + else + { + num = input->GetNumberOfPoints(); + } + + int piece = (this->Controller?this->Controller->GetLocalProcessId():0); + + if (this->RandomMode) + { + pieceColors = this->MakeRandomScalars(piece, num); + } + else + { + pieceColors = this->MakeProcessIdScalars(piece, num); + } + + output->ShallowCopy(input); + pieceColors->SetName("ProcessId"); + if (this->CellScalarsFlag) + { + output->GetCellData()->AddArray(pieceColors); + output->GetCellData()->SetActiveScalars(pieceColors->GetName()); + } + else + { + output->GetPointData()->AddArray(pieceColors); + output->GetPointData()->SetActiveScalars(pieceColors->GetName()); + } + + pieceColors->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +vtkIntArray *vtkProcessIdScalars::MakeProcessIdScalars(int piece, vtkIdType num) +{ + vtkIdType i; + vtkIntArray *pieceColors = NULL; + + pieceColors = vtkIntArray::New(); + pieceColors->SetNumberOfTuples(num); + + for (i = 0; i < num; ++i) + { + pieceColors->SetValue(i, piece); + } + + return pieceColors; +} + +//---------------------------------------------------------------------------- +vtkFloatArray *vtkProcessIdScalars::MakeRandomScalars(int piece, vtkIdType num) +{ + vtkIdType i; + vtkFloatArray *pieceColors = NULL; + float randomValue; + + vtkMath::RandomSeed(piece); + randomValue = vtkMath::Random(); + + pieceColors = vtkFloatArray::New(); + pieceColors->SetNumberOfTuples(num); + + for (i = 0; i < num; ++i) + { + pieceColors->SetValue(i, randomValue); + } + + return pieceColors; +} + +//---------------------------------------------------------------------------- +void vtkProcessIdScalars::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "RandomMode: " << this->RandomMode << endl; + if (this->CellScalarsFlag) + { + os << indent << "ScalarMode: CellData\n"; + } + else + { + os << indent << "ScalarMode: PointData\n"; + } + + os << indent << "Controller: "; + if (this->Controller) + { + this->Controller->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << "(none)" << endl; + } +} diff --git a/Parallel/vtkProcessIdScalars.h b/Parallel/vtkProcessIdScalars.h new file mode 100644 index 0000000..b8e63ce --- /dev/null +++ b/Parallel/vtkProcessIdScalars.h @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProcessIdScalars.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProcessIdScalars - Sets all cell scalars from the update piece. +// +// .SECTION Description +// vtkProcessIdScalars is meant to display which piece is being requested +// as scalar values. It is usefull for visualizing the partitioning for +// streaming or distributed pipelines. +// +// .SECTION See Also +// vtkPolyDataStreamer + +#ifndef __vtkProcessIdScalars_h +#define __vtkProcessIdScalars_h + +#include "vtkDataSetAlgorithm.h" + +class vtkFloatArray; +class vtkIntArray; +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkProcessIdScalars : public vtkDataSetAlgorithm +{ +public: + static vtkProcessIdScalars *New(); + + vtkTypeRevisionMacro(vtkProcessIdScalars,vtkDataSetAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Option to centerate cell scalars of poi9nts scalars. Default is point + // scalars. + void SetScalarModeToCellData() {this->SetCellScalarsFlag(1);} + void SetScalarModeToPointData() {this->SetCellScalarsFlag(0);} + int GetScalarMode() {return this->CellScalarsFlag;} + + // Dscription: + // This option uses a random mapping between pieces and scalar values. + // The scalar values are choosen between 0 and 1. By default, random + // mode is off. + vtkSetMacro(RandomMode, int); + vtkGetMacro(RandomMode, int); + vtkBooleanMacro(RandomMode, int); + + // Description: + // By defualt this filter uses the global controller, + // but this method can be used to set another instead. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + + +protected: + vtkProcessIdScalars(); + ~vtkProcessIdScalars(); + + // Append the pieces. + int RequestData( + vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkIntArray *MakeProcessIdScalars(int piece, vtkIdType numScalars); + vtkFloatArray *MakeRandomScalars(int piece, vtkIdType numScalars); + + vtkSetMacro(CellScalarsFlag,int); + int CellScalarsFlag; + int RandomMode; + + vtkMultiProcessController* Controller; + +private: + vtkProcessIdScalars(const vtkProcessIdScalars&); // Not implemented. + void operator=(const vtkProcessIdScalars&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkRTAnalyticSource.cxx b/Parallel/vtkRTAnalyticSource.cxx new file mode 100644 index 0000000..45d0f0a --- /dev/null +++ b/Parallel/vtkRTAnalyticSource.cxx @@ -0,0 +1,224 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRTAnalyticSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRTAnalyticSource.h" + +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkPointData.h" + +#include + +vtkCxxRevisionMacro(vtkRTAnalyticSource, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkRTAnalyticSource); + +//---------------------------------------------------------------------------- +vtkRTAnalyticSource::vtkRTAnalyticSource() +{ + this->Maximum = 255.0; + this->Center[0] = 0.0; + this->Center[1] = 0.0; + this->Center[2] = 0.0; + + this->WholeExtent[0] = -10; this->WholeExtent[1] = 10; + this->WholeExtent[2] = -10; this->WholeExtent[3] = 10; + this->WholeExtent[4] = -10; this->WholeExtent[5] = 10; + this->StandardDeviation = 0.5; + + this->XFreq = 60; + this->XMag = 10; + this->YFreq = 30; + this->YMag = 18; + this->ZFreq = 40; + this->ZMag = 5; + + this->SetNumberOfInputPorts(0); +} + + +//---------------------------------------------------------------------------- +void vtkRTAnalyticSource::SetWholeExtent(int xMin, int xMax, + int yMin, int yMax, + int zMin, int zMax) +{ + int modified = 0; + + if (this->WholeExtent[0] != xMin) + { + modified = 1; + this->WholeExtent[0] = xMin ; + } + if (this->WholeExtent[1] != xMax) + { + modified = 1; + this->WholeExtent[1] = xMax ; + } + if (this->WholeExtent[2] != yMin) + { + modified = 1; + this->WholeExtent[2] = yMin ; + } + if (this->WholeExtent[3] != yMax) + { + modified = 1; + this->WholeExtent[3] = yMax ; + } + if (this->WholeExtent[4] != zMin) + { + modified = 1; + this->WholeExtent[4] = zMin ; + } + if (this->WholeExtent[5] != zMax) + { + modified = 1; + this->WholeExtent[5] = zMax ; + } + if (modified) + { + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkRTAnalyticSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector ** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), + this->WholeExtent,6); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1); + return 1; +} + +void vtkRTAnalyticSource::ExecuteData(vtkDataObject *output) +{ + vtkImageData *data; + float *outPtr; + int idxX, idxY, idxZ; + int maxX, maxY, maxZ; + vtkIdType outIncX, outIncY, outIncZ; + int *outExt, *whlExt; + double sum; + double yContrib, zContrib; + double temp2; + unsigned long count = 0; + unsigned long target; + + data = this->AllocateOutputData(output); + if (data->GetScalarType() != VTK_FLOAT) + { + vtkErrorMacro("Execute: This source only outputs doubles"); + return; + } + if (data->GetNumberOfPoints() <= 0) + { + return; + } + + outExt = data->GetExtent(); + whlExt = data->GetWholeExtent(); + data->GetPointData()->GetScalars()->SetName("RTData"); + + // find the region to loop over + maxX = outExt[1] - outExt[0]; + maxY = outExt[3] - outExt[2]; + maxZ = outExt[5] - outExt[4]; + + // Get increments to march through data + data->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ); + outPtr = (float *) data->GetScalarPointer(outExt[0],outExt[2],outExt[4]); + + target = (unsigned long)((maxZ+1)*(maxY+1)/50.0); + target++; + + // Loop through ouput pixels + temp2 = 1.0 / (2.0 * this->StandardDeviation * this->StandardDeviation); + + double x, y, z; + for (idxZ = 0; idxZ <= maxZ; idxZ++) + { + z = this->Center[2] - (idxZ + outExt[4]); + if (whlExt[5] > whlExt[4]) + { + z /= (whlExt[5] - whlExt[4]); + } + zContrib = z * z; + for (idxY = 0; !this->AbortExecute && idxY <= maxY; idxY++) + { + if (!(count%target)) + { + this->UpdateProgress(count/(50.0*target)); + } + count++; + y = this->Center[1] - (idxY + outExt[2]); + if (whlExt[3] > whlExt[2]) + { + y /= (whlExt[3] - whlExt[2]); + } + yContrib = y * y; + for (idxX = 0; idxX <= maxX; idxX++) + { + // Pixel operation + sum = zContrib + yContrib; + x = this->Center[0] - (idxX + outExt[0]); + if (whlExt[1] > whlExt[0]) + { + x /= (whlExt[1] - whlExt[0]); + } + sum = sum + (x * x); + *outPtr = this->Maximum * exp(-sum * temp2) + + this->XMag*sin(this->XFreq*x) + + this->YMag*sin(this->YFreq*y) + + this->ZMag*cos(this->ZFreq*z); + outPtr++; + } + outPtr += outIncY; + } + outPtr += outIncZ; + } +} + +void vtkRTAnalyticSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximum: " << this->Maximum << "\n"; + os << indent << "StandardDeviation: " << this->StandardDeviation << "\n"; + os << indent << "Center: ( " + << this->Center[0] << ", " + << this->Center[1] << ", " + << this->Center[2] << " )\n"; + os << indent << "XFreq: " << this->XFreq << endl; + os << indent << "YFreq: " << this->YFreq << endl; + os << indent << "ZFreq: " << this->ZFreq << endl; + os << indent << "XMag: " << this->XMag << endl; + os << indent << "YMag: " << this->YMag << endl; + os << indent << "ZMag: " << this->ZMag << endl; + + os << indent << "WholeExtent: " << this->WholeExtent[0] + << ", " << this->WholeExtent[1] << ", " << this->WholeExtent[2] + << ", " << this->WholeExtent[3] << ", " << this->WholeExtent[4] + << ", " << this->WholeExtent[5] << endl; + +} + + diff --git a/Parallel/vtkRTAnalyticSource.h b/Parallel/vtkRTAnalyticSource.h new file mode 100644 index 0000000..730dfc6 --- /dev/null +++ b/Parallel/vtkRTAnalyticSource.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRTAnalyticSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRTAnalyticSource - Create an image for regression testing +// .SECTION Description +// vtkRTAnalyticSource just produces images with pixel values determined +// by a Maximum*Gaussian*XMag*sin(XFreq*x)*sin(YFreq*y)*cos(ZFreq*z) + + +#ifndef __vtkRTAnalyticSource_h +#define __vtkRTAnalyticSource_h + +#include "vtkImageAlgorithm.h" + +class VTK_PARALLEL_EXPORT vtkRTAnalyticSource : public vtkImageAlgorithm +{ +public: + static vtkRTAnalyticSource *New(); + vtkTypeRevisionMacro(vtkRTAnalyticSource,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the extent of the whole output image. + void SetWholeExtent(int xMinx, int xMax, int yMin, int yMax, + int zMin, int zMax); + vtkGetVector6Macro(WholeExtent, int); + + // Description: + // Set/Get the center of function. + vtkSetVector3Macro(Center, double); + vtkGetVector3Macro(Center, double); + + // Description: + // Set/Get the Maximum value of the function. + vtkSetMacro(Maximum, double); + vtkGetMacro(Maximum, double); + + // Description: + // Set/Get the standard deviation of the function. + vtkSetMacro(StandardDeviation, double); + vtkGetMacro(StandardDeviation, double); + + // Description: + // Set the natural frequencies in x,y and z + vtkSetMacro(XFreq, double); + vtkGetMacro(XFreq, double); + vtkSetMacro(YFreq, double); + vtkGetMacro(YFreq, double); + vtkSetMacro(ZFreq, double); + vtkGetMacro(ZFreq, double); + + vtkSetMacro(XMag, double); + vtkGetMacro(XMag, double); + vtkSetMacro(YMag, double); + vtkGetMacro(YMag, double); + vtkSetMacro(ZMag, double); + vtkGetMacro(ZMag, double); + +protected: + vtkRTAnalyticSource(); + ~vtkRTAnalyticSource() {}; + + double XFreq; + double YFreq; + double ZFreq; + double XMag; + double YMag; + double ZMag; + double StandardDeviation; + int WholeExtent[6]; + double Center[3]; + double Maximum; + + virtual int RequestInformation (vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + virtual void ExecuteData(vtkDataObject *data); +private: + vtkRTAnalyticSource(const vtkRTAnalyticSource&); // Not implemented. + void operator=(const vtkRTAnalyticSource&); // Not implemented. +}; + + +#endif diff --git a/Parallel/vtkRectilinearGridOutlineFilter.cxx b/Parallel/vtkRectilinearGridOutlineFilter.cxx new file mode 100644 index 0000000..7f06f9f --- /dev/null +++ b/Parallel/vtkRectilinearGridOutlineFilter.cxx @@ -0,0 +1,227 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridOutlineFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRectilinearGridOutlineFilter.h" + +#include "vtkCellArray.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkRectilinearGridOutlineFilter, "$Revision: 1.10 $"); +vtkStandardNewMacro(vtkRectilinearGridOutlineFilter); + + +int vtkRectilinearGridOutlineFilter::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + // Although there may be overlap between piece outlines, + // it is not worth requesting exact extents. + inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 0); + return 1; +} + +int vtkRectilinearGridOutlineFilter::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkRectilinearGrid *input = vtkRectilinearGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + float bounds[6]; + double *range; + float x[3]; + vtkIdType pts[2]; + vtkPoints* newPts; + vtkCellArray* newLines; + + vtkDataArray* xCoords = input->GetXCoordinates(); + vtkDataArray* yCoords = input->GetYCoordinates(); + vtkDataArray* zCoords = input->GetZCoordinates(); + int* ext = input->GetExtent();; + int* wholeExt = + inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()); + + if (xCoords == NULL || yCoords == NULL || zCoords == NULL || + input->GetNumberOfCells() == 0) + { + return 1; + } + + // We could probably use just the input bounds ... + range = xCoords->GetRange(); + bounds[0] = range[0]; + bounds[1] = range[1]; + range = yCoords->GetRange(); + bounds[2] = range[0]; + bounds[3] = range[1]; + range = zCoords->GetRange(); + bounds[4] = range[0]; + bounds[5] = range[1]; + + // + // Allocate storage and create outline + // + newPts = vtkPoints::New(); + newPts->Allocate(24); + newLines = vtkCellArray::New(); + newLines->Allocate(newLines->EstimateSize(12,2)); + + // xMin yMin + if (ext[0] == wholeExt[0] && ext[2] == wholeExt[2]) + { + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // xMin yMax + if (ext[0] == wholeExt[0] && ext[3] == wholeExt[3]) + { + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // xMin zMin + if (ext[0] == wholeExt[0] && ext[4] == wholeExt[4]) + { + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[4]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // xMin zMax + if (ext[0] == wholeExt[0] && ext[5] == wholeExt[5]) + { + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[5]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // xMax yMin + if (ext[1] == wholeExt[1] && ext[2] == wholeExt[2]) + { + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // xMax yMax + if (ext[1] == wholeExt[1] && ext[3] == wholeExt[3]) + { + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // xMax zMin + if (ext[1] == wholeExt[1] && ext[4] == wholeExt[4]) + { + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[4]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // xMax zMax + if (ext[1] == wholeExt[1] && ext[5] == wholeExt[5]) + { + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[5]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // yMin zMin + if (ext[2] == wholeExt[2] && ext[4] == wholeExt[4]) + { + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[4]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // yMin zMax + if (ext[2] == wholeExt[2] && ext[5] == wholeExt[5]) + { + x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[5]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // yMax zMin + if (ext[3] == wholeExt[3] && ext[4] == wholeExt[4]) + { + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[4]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[4]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + // yMax zMax + if (ext[3] == wholeExt[3] && ext[5] == wholeExt[5]) + { + x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[5]; + pts[0] = newPts->InsertNextPoint(x); + x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[5]; + pts[1] = newPts->InsertNextPoint(x); + newLines->InsertNextCell(2,pts); + } + + output->SetPoints(newPts); + newPts->Delete(); + + output->SetLines(newLines); + newLines->Delete(); + + output->Squeeze(); + + return 1; +} + +int vtkRectilinearGridOutlineFilter::FillInputPortInformation( + int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); + return 1; +} + +void vtkRectilinearGridOutlineFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} diff --git a/Parallel/vtkRectilinearGridOutlineFilter.h b/Parallel/vtkRectilinearGridOutlineFilter.h new file mode 100644 index 0000000..511d7b9 --- /dev/null +++ b/Parallel/vtkRectilinearGridOutlineFilter.h @@ -0,0 +1,46 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRectilinearGridOutlineFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRectilinearGridOutlineFilter - create wireframe outline for a rectilinear grid. +// .SECTION Description +// vtkRectilinearGridOutlineFilter works in parallel. There is no reason. +// to use this filter if you are not breaking the processing into pieces. +// With one piece you can simply use vtkOutlineFilter. This filter +// ignores internal edges when the extent is not the whole extent. + +#ifndef __vtkRectilinearGridOutlineFilter_h +#define __vtkRectilinearGridOutlineFilter_h + +#include "vtkPolyDataAlgorithm.h" + +class VTK_PARALLEL_EXPORT vtkRectilinearGridOutlineFilter : public vtkPolyDataAlgorithm +{ +public: + static vtkRectilinearGridOutlineFilter *New(); + vtkTypeRevisionMacro(vtkRectilinearGridOutlineFilter,vtkPolyDataAlgorithm); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkRectilinearGridOutlineFilter() {}; + ~vtkRectilinearGridOutlineFilter() {}; + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + +private: + vtkRectilinearGridOutlineFilter(const vtkRectilinearGridOutlineFilter&); // Not implemented. + void operator=(const vtkRectilinearGridOutlineFilter&); // Not implemented. +}; + +#endif diff --git a/Parallel/vtkSocketCommunicator.cxx b/Parallel/vtkSocketCommunicator.cxx new file mode 100644 index 0000000..555eb32 --- /dev/null +++ b/Parallel/vtkSocketCommunicator.cxx @@ -0,0 +1,910 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSocketCommunicator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSocketCommunicator.h" + +#include "vtkObjectFactory.h" +#include "vtkSocketController.h" +#include "vtkCommand.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +# define VTK_WINDOWS_FULL +# include "vtkWindows.h" +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define WSA_VERSION MAKEWORD(1,1) +#define vtkCloseSocketMacro(sock) (closesocket(sock)) +#else +#define vtkCloseSocketMacro(sock) (close(sock)) +#endif + +vtkCxxRevisionMacro(vtkSocketCommunicator, "$Revision: 1.61 $"); +vtkStandardNewMacro(vtkSocketCommunicator); + +//---------------------------------------------------------------------------- +vtkSocketCommunicator::vtkSocketCommunicator() +{ + this->Socket = -1; + this->IsConnected = 0; + this->NumberOfProcesses = 2; + this->SwapBytesInReceivedData = vtkSocketCommunicator::SwapNotSet; + this->PerformHandshake = 1; + this->LogStream = 0; + this->LogFile = 0; + + this->ReportErrors = 1; +} + +//---------------------------------------------------------------------------- +vtkSocketCommunicator::~vtkSocketCommunicator() +{ + if (this->IsConnected) + { + vtkCloseSocketMacro(this->Socket); + this->Socket = -1; + } + this->SetLogStream(0); +} + +//---------------------------------------------------------------------------- +void vtkSocketCommunicator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + + os << indent << "SwapBytesInReceivedData: "; + if (this->SwapBytesInReceivedData == SwapOff) + { + os << "Off\n"; + } + if (this->SwapBytesInReceivedData == SwapOn) + { + os << "On\n"; + } + if (this->SwapBytesInReceivedData == SwapNotSet) + { + os << "NotSet\n"; + } + + os << indent << "IsConnected: " << this->IsConnected << endl; + os << indent << "Perform a handshake: " + << ( this->PerformHandshake ? "Yes" : "No" ) << endl; + + os << indent << "ReportErrors: " << this->ReportErrors << endl; +} + +//---------------------------------------------------------------------------- +void vtkSocketCommunicator::SetLogStream(ostream* stream) +{ + if(this->LogStream != stream) + { + // If the log stream is our own log file, close the file. + if(this->LogFile && this->LogFile == this->LogStream) + { + delete this->LogFile; + this->LogFile = 0; + } + + // Use the given log stream. + this->LogStream = stream; + } +} + +//---------------------------------------------------------------------------- +ostream* vtkSocketCommunicator::GetLogStream() +{ + return this->LogStream; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::LogToFile(const char* name) +{ + return this->LogToFile(name, 0); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::LogToFile(const char* name, int append) +{ + // Close old logging file. + if(this->LogFile) + { + delete this->LogFile; + this->LogFile = 0; + } + this->LogStream = 0; + + // Log to given file, if any. + if(name && name[0]) + { + this->LogFile = new ofstream(name, (ios::out | + (append? ios::ate : ios::trunc))); + if(!this->LogFile) + { + return 0; + } + if(!*this->LogFile) + { + delete this->LogFile; + this->LogFile = 0; + return 0; + } + this->LogStream = this->LogFile; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Send(int* data, int length, int remoteProcessId, + int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->SendTagged(data, static_cast(sizeof(int)), + length, tag, "int"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Send(unsigned long* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->SendTagged(data, static_cast(sizeof(unsigned long)), + length, tag, "ulong"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Send(char* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->SendTagged(data, static_cast(sizeof(char)), + length, tag, "char"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Send(unsigned char* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->SendTagged(data, static_cast(sizeof(unsigned char)), + length, tag, "uchar"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Send(float* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->SendTagged(data, static_cast(sizeof(float)), + length, tag, "float"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Send(double *data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->SendTagged(data, static_cast(sizeof(double)), + length, tag, "double"); +} + +#ifdef VTK_USE_64BIT_IDS +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Send(vtkIdType *data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->SendTagged(data, static_cast(sizeof(vtkIdType)), + length, tag, "vtkIdType"); +} +#endif + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Receive(int* data, int length, int remoteProcessId, + int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + int ret = this->ReceiveTagged(data, static_cast(sizeof(int)), + length, tag, "int"); + if(tag == vtkMultiProcessController::RMI_TAG) + { + data[2] = 1; + } + return ret; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Receive(unsigned long* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->ReceiveTagged(data, static_cast(sizeof(unsigned long)), + length, tag, "ulong"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Receive(char* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->ReceiveTagged(data, static_cast(sizeof(char)), + length, tag, "char"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Receive(unsigned char* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->ReceiveTagged(data, static_cast(sizeof(unsigned char)), + length, tag, "uchar"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Receive(float* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->ReceiveTagged(data, static_cast(sizeof(float)), + length, tag, "float"); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::Receive(double* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->ReceiveTagged(data, static_cast(sizeof(double)), + length, tag, "double"); +} + +//---------------------------------------------------------------------------- +#ifdef VTK_USE_64BIT_IDS +int vtkSocketCommunicator::Receive(vtkIdType* data, int length, + int remoteProcessId, int tag) +{ + if(this->CheckForErrorInternal(remoteProcessId)) { return 0; } + return this->ReceiveTagged(data, static_cast(sizeof(vtkIdType)), + length, tag, "vtkIdType"); +} +#endif + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::GetPort(int sock) +{ + struct sockaddr_in sockinfo; + memset(&sockinfo, 0, sizeof(sockinfo)); +#if defined(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T) + socklen_t sizebuf = sizeof(sockinfo); +#else + int sizebuf = sizeof(sockinfo); +#endif + if(getsockname(sock, reinterpret_cast(&sockinfo), &sizebuf) != 0) + { + if (this->ReportErrors) + { + vtkErrorMacro("No port found for socket " << sock); + } + return 0; + } + return ntohs(sockinfo.sin_port); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::OpenSocket(int port, const char* ) +{ + if ( this->IsConnected ) + { + if (this->ReportErrors) + { + vtkErrorMacro("Port " << 1 << " is occupied."); + } + return 0; + } + + int sock = socket(AF_INET, SOCK_STREAM, 0); + // Elimate windows 0.2 second delay sending (buffering) data. + int on = 1; + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on))) + { + return -1; + } + + struct sockaddr_in server; + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(port); + // Allow the socket to be bound to an address that is already in use + int opt=1; +#ifdef _WIN32 + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(int)); +#else + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, sizeof(int)); +#endif + + if ( bind(sock, reinterpret_cast(&server), sizeof(server)) ) + { + if (this->ReportErrors) + { + vtkErrorMacro("Can not bind socket to port " << port); + } + return 0; + } + listen(sock,1); + return sock; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::SelectSocket(int socket, unsigned long msec) +{ + if ( socket < 0 ) + { + return 0; + } + fd_set rset; + struct timeval tval; + struct timeval* tvalptr = 0; + if ( msec > 0 ) + { + tval.tv_sec = msec / 1000; + tval.tv_usec = (msec % 1000)*1000; + tvalptr = &tval; + } + FD_ZERO(&rset); + FD_SET(socket, &rset); + int res = select(socket + 1, &rset, 0, 0, tvalptr); + if(res == 0) + { + return -1;//for time limit expire + } + if ( res < 0 || !(FD_ISSET(socket, &rset)) ) + { + return 0; + } + return 1; +} +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::WaitForConnectionOnSocket(int sock, unsigned long timeout) +{ + int res = this->SelectSocket(sock, timeout); + if ( res <= 0 ) + { + return res; + } + this->Socket = accept(sock, 0, 0); + if ( this->Socket == -1 ) + { + if (this->ReportErrors) + { + vtkErrorMacro("Error in accept."); + } + return 0; + } + vtkCloseSocketMacro(sock); + sock = -1; + + this->IsConnected = 1; + + if ( this->PerformHandshake ) + { + // Handshake to determine if the client machine has the same endianness + char clientIsBE; + if(!this->ReceiveTagged(&clientIsBE, static_cast(sizeof(char)), + 1, vtkSocketController::ENDIAN_TAG, 0)) + { + if (this->ReportErrors) + { + vtkErrorMacro("Endian handshake failed."); + } + return 0; + } + vtkDebugMacro(<< "Client is " << ( clientIsBE ? "big" : "little" ) + << "-endian"); + +#ifdef VTK_WORDS_BIGENDIAN + char IAmBE = 1; +#else + char IAmBE = 0; +#endif + vtkDebugMacro(<< "I am " << ( IAmBE ? "big" : "little" ) << "-endian"); + if(!this->SendTagged(&IAmBE, static_cast(sizeof(char)), + 1, vtkSocketController::ENDIAN_TAG, 0)) + { + if (this->ReportErrors) + { + vtkErrorMacro("Endian handshake failed."); + } + return 0; + } + + if ( clientIsBE != IAmBE ) + { + this->SwapBytesInReceivedData = vtkSocketCommunicator::SwapOn; + } + else + { + this->SwapBytesInReceivedData = vtkSocketCommunicator::SwapOff; + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::WaitForConnection(int port) +{ + int sock = this->OpenSocket(port); + if(sock == 0) + { + return 0; + } + return this->WaitForConnectionOnSocket(sock); +} + +void vtkSocketCommunicator::CloseConnection() +{ + if ( this->IsConnected ) + { + vtkCloseSocketMacro(this->Socket); + this->Socket = -1; + this->IsConnected = 0; + } +} + +int vtkSocketCommunicator::ConnectTo ( char* hostName, int port ) +{ + + if ( this->IsConnected ) + { + if (this->ReportErrors) + { + vtkErrorMacro("Communicator port " << 1 << " is occupied."); + } + return 0; + } + + struct hostent* hp; + hp = gethostbyname(hostName); + if (!hp) + { + unsigned long addr = inet_addr(hostName); + hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); + } + if (!hp) + { + if (this->ReportErrors) + { + vtkErrorMacro("Unknown host: " << hostName); + } + return 0; + } + + this->Socket = socket(AF_INET, SOCK_STREAM, 0); + // Elimate windows 0.2 second delay sending (buffering) data. + int on = 1; + if (setsockopt(this->Socket, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on))) + { + return -1; + } + + struct sockaddr_in name; + name.sin_family = AF_INET; + memcpy(&name.sin_addr, hp->h_addr, hp->h_length); + name.sin_port = htons(port); + + if( connect(this->Socket, reinterpret_cast(&name), sizeof(name)) < 0) + { + if (this->ReportErrors) + { + vtkErrorMacro("Can not connect to " << hostName << " on port " << port); + } + return 0; + } + + vtkDebugMacro("Connected to " << hostName << " on port " << port); + this->IsConnected = 1; + + // Handshake to determine if the server machine has the same endianness +#ifdef VTK_WORDS_BIGENDIAN + char IAmBE = 1; +#else + char IAmBE = 0; +#endif + vtkDebugMacro(<< "I am " << ( IAmBE ? "big" : "little" ) << "-endian"); + if(!this->SendTagged(&IAmBE, static_cast(sizeof(char)), + 1, vtkSocketController::ENDIAN_TAG, 0)) + { + if (this->ReportErrors) + { + vtkErrorMacro("Endian handshake failed."); + } + return 0; + } + + char serverIsBE; + if (!this->ReceiveTagged(&serverIsBE, static_cast(sizeof(char)), 1, + vtkSocketController::ENDIAN_TAG, 0)) + { + if (this->ReportErrors) + { + vtkErrorMacro("Endian handshake failed."); + } + return 0; + } + vtkDebugMacro(<< "Server is " << ( serverIsBE ? "big" : "little" ) << "-endian"); + + if ( serverIsBE != IAmBE ) + { + this->SwapBytesInReceivedData = vtkSocketCommunicator::SwapOn; + } + else + { + this->SwapBytesInReceivedData = vtkSocketCommunicator::SwapOff; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::SendInternal(int socket, void* data, int length) +{ + char* buffer = reinterpret_cast(data); + int total = 0; + do + { + int n = send(socket, buffer+total, length-total, 0); + if(n < 1) + { + return 0; + } + total += n; + } while(total < length); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::ReceiveInternal(int socket, void* data, int length) +{ + char* buffer = reinterpret_cast(data); + int total = 0; + do + { +#if defined(_WIN32) && !defined(__CYGWIN__) + int trys = 0; +#endif + int n = recv(socket, buffer+total, length-total, 0); + if(n < 1) + { +#if defined(_WIN32) && !defined(__CYGWIN__) + // On long messages, Windows recv sometimes fails with WSAENOBUFS, but + // will work if you try again. + int error = WSAGetLastError(); + if ((error == WSAENOBUFS) && (trys++ < 1000)) + { + Sleep(1); + continue; + } +#endif + return 0; + } + total += n; + } while(total < length); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::SendTagged(void* data, int wordSize, + int numWords, int tag, + const char* logName) +{ + if(!this->SendInternal(this->Socket, &tag, static_cast(sizeof(int)))) + { + if (this->ReportErrors) + { + vtkErrorMacro("Could not send tag."); + } + return 0; + } + int length = wordSize * numWords; + if(!this->SendInternal(this->Socket, &length, + static_cast(sizeof(int)))) + { + if (this->ReportErrors) + { + vtkErrorMacro("Could not send length."); + } + return 0; + } + if(!this->SendInternal(this->Socket, data, wordSize*numWords)) + { + if (this->ReportErrors) + { + vtkErrorMacro("Could not send message."); + } + return 0; + } + + // Log this event. + this->LogTagged("Sent", data, wordSize, numWords, tag, logName); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::ReceiveTagged(void* data, int wordSize, + int numWords, int tag, + const char* logName) +{ + int success = 0; + int length = -1; + while ( !success ) + { + int recvTag = -1; + length = -1; + if(!this->ReceiveInternal(this->Socket, &recvTag, + static_cast(sizeof(int)))) + { + if (this->ReportErrors) + { + vtkErrorMacro("Could not receive tag. " << tag); + } + return 0; + } + if(this->SwapBytesInReceivedData == vtkSocketCommunicator::SwapOn) + { + vtkSwap4(reinterpret_cast(&recvTag)); + } + if(!this->ReceiveInternal(this->Socket, &length, + static_cast(sizeof(int)))) + { + if (this->ReportErrors) + { + vtkErrorMacro("Could not receive length."); + } + return 0; + } + if(this->SwapBytesInReceivedData == vtkSocketCommunicator::SwapOn) + { + vtkSwap4(reinterpret_cast(&length)); + } + if(recvTag != tag) + { + char* idata = new char[length + sizeof(recvTag) + sizeof(length)]; + char* ptr = idata; + memcpy(ptr, (void*)&recvTag, sizeof(recvTag)); + ptr += sizeof(recvTag); + memcpy(ptr, (void*)&length, sizeof(length)); + ptr += sizeof(length); + this->ReceivePartialTagged(ptr, 1, length, tag, "Wrong tag"); + int res = this->InvokeEvent(vtkCommand::WrongTagEvent, idata); + delete [] idata; + if ( res ) + { + continue; + } + + if (this->ReportErrors) + { + vtkErrorMacro("Tag mismatch: got " << recvTag << ", expecting " << tag + << "."); + } + return 0; + } + else + { + success = 1; + } + } + // Length may not be correct for the first message sent as an + // endian handshake because the SwapBytesInReceivedData flag + // is not initialized at this point. We could just initialize it + // here, but what is the point. + if ((wordSize * numWords) != length && + this->SwapBytesInReceivedData != vtkSocketCommunicator::SwapNotSet) + { + if (this->ReportErrors) + { + vtkErrorMacro("Requested size (" << (wordSize * numWords) + << ") is different than the size that was sent (" << length << ")"); + } + return 0; + } + return this->ReceivePartialTagged(data, wordSize, numWords, tag, logName); +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::ReceivePartialTagged(void* data, int wordSize, + int numWords, int tag, + const char* logName) +{ + if(!this->ReceiveInternal(this->Socket, data, wordSize*numWords)) + { + if (this->ReportErrors) + { + vtkErrorMacro("Could not receive message."); + } + return 0; + } + // Unless we're dealing with chars, then check byte ordering. + // This is really bad and should probably use some enum for types + if(this->SwapBytesInReceivedData == vtkSocketCommunicator::SwapOn) + { + if(wordSize == 4) + { + vtkDebugMacro(<< " swapping 4 range, size = " << wordSize + << " length = " << numWords); + vtkSwap4Range(reinterpret_cast(data), numWords); + } + else if(wordSize == 8) + { + vtkDebugMacro(<< " swapping 8 range, size = " << wordSize + << " length = " << numWords ); + vtkSwap8Range(reinterpret_cast(data), numWords); + } + } + + // Log this event. + this->LogTagged("Received", data, wordSize, numWords, tag, logName); + + return 1; +} + +//---------------------------------------------------------------------------- +template +void vtkSocketCommunicatorLogArray(ostream& os, T* array, int length, int max, + OutType*) +{ + if(length > 0) + { + int num = (length <= max)? length:max; + os << " data={" << static_cast(array[0]); + for(int i=1; i < num; ++i) + { + os << " " << static_cast(array[i]); + } + if(length > max) + { + os << " ..."; + } + os << "}"; + } +} + +//---------------------------------------------------------------------------- +void vtkSocketCommunicator::LogTagged(const char* name, void* data, + int wordSize, int numWords, + int tag, const char* logName) +{ + if(this->LogStream) + { + // Log the general event information. + *this->LogStream << name; + if(logName) + { + *this->LogStream << " " << logName; + } + *this->LogStream << " data: tag=" << tag + << " wordSize=" << wordSize + << " numWords=" << numWords; + + // If this is a string, log the first 70 characters. If this is + // an array of data values, log the first few. + if(wordSize == static_cast(sizeof(char)) && logName && + (strcmp(logName, "char") == 0)) + { + char* chars = reinterpret_cast(data); + if((chars[numWords-1]) == 0 && + (static_cast(strlen(chars)) == numWords-1)) + { + // String data. Display the first 70 characters. + *this->LogStream << " data={"; + if(numWords <= 71) + { + *this->LogStream << chars; + } + else + { + this->LogStream->write(reinterpret_cast(data), 70); + *this->LogStream << " ..."; + } + *this->LogStream << "}"; + } + else + { + // Not string data. Display the characters as integer values. + vtkSocketCommunicatorLogArray(*this->LogStream, + reinterpret_cast(data), + numWords, 6, static_cast(0)); + } + } + else if(wordSize == static_cast(sizeof(int)) && logName && + (strcmp(logName, "int") == 0)) + { + vtkSocketCommunicatorLogArray(*this->LogStream, + reinterpret_cast(data), + numWords, 6, static_cast(0)); + } + else if(wordSize == static_cast(sizeof(unsigned char)) && logName && + (strcmp(logName, "uchar") == 0)) + { + vtkSocketCommunicatorLogArray(*this->LogStream, + reinterpret_cast(data), + numWords, 6, static_cast(0)); + } + else if(wordSize == static_cast(sizeof(unsigned long)) && logName && + (strcmp(logName, "ulong") == 0)) + { + vtkSocketCommunicatorLogArray(*this->LogStream, + reinterpret_cast(data), + numWords, 6, static_cast(0)); + } + else if(wordSize == static_cast(sizeof(float)) && logName && + (strcmp(logName, "float") == 0)) + { + vtkSocketCommunicatorLogArray(*this->LogStream, + reinterpret_cast(data), + numWords, 6, static_cast(0)); + } + else if(wordSize == static_cast(sizeof(double)) && logName && + (strcmp(logName, "double") == 0)) + { + vtkSocketCommunicatorLogArray(*this->LogStream, + reinterpret_cast(data), + numWords, 6, static_cast(0)); + } +#ifdef VTK_USE_64BIT_IDS + else if(wordSize == static_cast(sizeof(vtkIdType)) && logName && + (strcmp(logName, "vtkIdType") == 0)) + { + vtkSocketCommunicatorLogArray(*this->LogStream, + reinterpret_cast(data), + numWords, 6, static_cast(0)); + } +#endif + *this->LogStream << "\n"; + } +} + +//---------------------------------------------------------------------------- +int vtkSocketCommunicator::CheckForErrorInternal(int id) +{ + if(id == 0) + { + if (this->ReportErrors) + { + vtkErrorMacro("Can not connect to myself!"); + } + return 1; + } + else if(id >= this->NumberOfProcesses) + { + if (this->ReportErrors) + { + vtkErrorMacro("No port for process " << id << " exists."); + } + return 1; + } + return 0; +} diff --git a/Parallel/vtkSocketCommunicator.h b/Parallel/vtkSocketCommunicator.h new file mode 100644 index 0000000..7e2d729 --- /dev/null +++ b/Parallel/vtkSocketCommunicator.h @@ -0,0 +1,207 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSocketCommunicator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSocketCommunicator - Process communication using Sockets +// .SECTION Description +// This is a concrete implementation of vtkCommunicator which supports +// interprocess communication using BSD style sockets. +// It supports byte swapping for the communication of machines +// with different endianness. + +// .SECTION Caveats +// Communication between 32 bit and 64 bit systems is not fully +// supported. If a type does not have the same length on both +// systems, this communicator can not be used to transfer data +// of that type. + +// .SECTION see also +// vtkCommunicator vtkSocketController + +#ifndef __vtkSocketCommunicator_h +#define __vtkSocketCommunicator_h + +#include "vtkCommunicator.h" + +#include "vtkByteSwap.h" // Needed for vtkSwap macros + +#ifdef VTK_WORDS_BIGENDIAN +# define vtkSwap4 vtkByteSwap::Swap4LE +# define vtkSwap4Range vtkByteSwap::Swap4LERange +# define vtkSwap8 vtkByteSwap::Swap8LE +# define vtkSwap8Range vtkByteSwap::Swap8LERange +#else +# define vtkSwap4 vtkByteSwap::Swap4BE +# define vtkSwap4Range vtkByteSwap::Swap4BERange +# define vtkSwap8 vtkByteSwap::Swap8BE +# define vtkSwap8Range vtkByteSwap::Swap8BERange +#endif + +class VTK_PARALLEL_EXPORT vtkSocketCommunicator : public vtkCommunicator +{ +public: + static vtkSocketCommunicator *New(); + vtkTypeRevisionMacro(vtkSocketCommunicator,vtkCommunicator); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a socket on the given port, if port is 0, then + // create a random port. If network is specified, then use + // the given network. The socket number is returned. + virtual int OpenSocket(int port, const char* network = 0); + + // Description: + // Return the port used by an open socket. + virtual int GetPort(int sock); + + // Description: + // Wait for a connection on an already bound port created + // by a call to BindPort. If the timeout is specified, then the call will + // fail after timeout expiers with resulting code of -1. + virtual int WaitForConnectionOnSocket(int socket, unsigned long timeout = 0); + + // Description: + // Wait for connection on a given port. + virtual int WaitForConnection(int port); + + // Description: + // Close a connection. + virtual void CloseConnection(); + + // Description: + // Open a connection to host. + virtual int ConnectTo( char* hostName, int port); + + // Description: + // Returns 1 if bytes must be swapped in received ints, floats, etc + vtkGetMacro(SwapBytesInReceivedData, int); + + // Description: + // Is the communicator connected?. + vtkGetMacro(IsConnected, int); + + //------------------ Communication -------------------- + + // Description: + // This method sends data to another process. Tag eliminates ambiguity + // when multiple sends or receives exist in the same process. + int Send(int *data, int length, int remoteProcessId, int tag); + int Send(unsigned long *data, int length, int remoteProcessId, int tag); + int Send(char *data, int length, int remoteProcessId, int tag); + int Send(unsigned char *data, int length, int remoteProcessId, int tag); + int Send(float *data, int length, int remoteProcessId, int tag); + int Send(double *data, int length, int remoteProcessId, int tag); +#ifdef VTK_USE_64BIT_IDS + int Send(vtkIdType *data, int length, int remoteProcessId, int tag); +#endif + int Send(vtkDataObject *data, int remoteId, int tag) + {return this->vtkCommunicator::Send(data,remoteId,tag);} + int Send(vtkDataArray *data, int remoteId, int tag) + {return this->vtkCommunicator::Send(data,remoteId,tag);} + + // Description: + // This method receives data from a corresponding send. It blocks + // until the receive is finished. It calls methods in "data" + // to communicate the sending data. + int Receive(int *data, int length, int remoteProcessId, int tag); + int Receive(unsigned long *data, int length, int remoteProcessId, int tag); + int Receive(char *data, int length, int remoteProcessId, int tag); + int Receive(unsigned char *data, int length, int remoteProcessId, int tag); + int Receive(float *data, int length, int remoteProcessId, int tag); + int Receive(double *data, int length, int remoteProcessId, int tag); +#ifdef VTK_USE_64BIT_IDS + int Receive(vtkIdType *data, int length, int remoteProcessId, int tag); +#endif + int Receive(vtkDataObject *data, int remoteId, int tag) + {return this->vtkCommunicator::Receive(data, remoteId, tag);} + int Receive(vtkDataArray *data, int remoteId, int tag) + {return this->vtkCommunicator::Receive(data, remoteId, tag);} + + // Description: + // Set or get the PerformHandshake ivar. If it is on, the communicator + // will try to perform a handshake when connected. + // It is on by default. + vtkSetClampMacro(PerformHandshake, int, 0, 1); + vtkBooleanMacro(PerformHandshake, int); + vtkGetMacro(PerformHandshake, int); + + //BTX + // Description: + // Get/Set the output stream to which communications should be + // logged. This is intended as a debugging feature. + virtual void SetLogStream(ostream* stream); + virtual ostream* GetLogStream(); + //ETX + + // Description: + // Log messages to the given file. The file is truncated unless the + // second argument is non-zero (default is to truncate). If the + // file name is empty or NULL, logging is disabled. Returns 0 if + // the file failed to open, and 1 otherwise. + virtual int LogToFile(const char* name); + virtual int LogToFile(const char* name, int append); + + // Description: + // If ReportErrors if false, all vtkErrorMacros are suppressed. + vtkSetMacro(ReportErrors, int); + vtkGetMacro(ReportErrors, int); + +protected: + + int Socket; + int IsConnected; + int NumberOfProcesses; + int SwapBytesInReceivedData; + int PerformHandshake; + + int ReportErrors; + + ofstream* LogFile; + ostream* LogStream; + + vtkSocketCommunicator(); + ~vtkSocketCommunicator(); + + // Wrappers around send/recv calls to implement loops. Return 1 for + // success, and 0 for failure. + int SendInternal(int socket, void* data, int length); + int ReceiveInternal(int socket, void* data, int length); + int SendTagged(void* data, int wordSize, int numWords, int tag, + const char* logName); + int ReceiveTagged(void* data, int wordSize, int numWords, int tag, + const char* logName); + int ReceivePartialTagged(void* data, int wordSize, int numWords, int tag, + const char* logName); + + // Internal utility methods. + void LogTagged(const char* name, void* data, int wordSize, int numWords, + int tag, const char* logName); + int CheckForErrorInternal(int id); +private: + vtkSocketCommunicator(const vtkSocketCommunicator&); // Not implemented. + void operator=(const vtkSocketCommunicator&); // Not implemented. + + int SelectSocket(int socket, unsigned long msec); + +//BTX + // SwapBytesInReceiveData needs an invalid / not set. + // This avoids checking length of endian handshake. + enum ErrorIds { + SwapOff = 0, + SwapOn, + SwapNotSet + }; +//ETX +}; + +#endif diff --git a/Parallel/vtkSocketController.cxx b/Parallel/vtkSocketController.cxx new file mode 100644 index 0000000..9072b34 --- /dev/null +++ b/Parallel/vtkSocketController.cxx @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSocketController.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSocketController.h" + +#include "vtkObjectFactory.h" +#include "vtkSocketCommunicator.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +# define VTK_WINDOWS_FULL +# include "vtkWindows.h" +#else + #include + #include + #include + #include + #include + #include +#endif + +#ifdef _WIN32 +#define WSA_VERSION MAKEWORD(1,1) +#define vtkCloseSocketMacro(sock) (closesocket(sock)) +#else +#define vtkCloseSocketMacro(sock) (close(sock)) +#endif + +int vtkSocketController::Initialized = 0; + +vtkCxxRevisionMacro(vtkSocketController, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkSocketController); + +//---------------------------------------------------------------------------- +vtkSocketController::vtkSocketController() +{ + this->NumberOfProcesses = 2; + this->Communicator = vtkSocketCommunicator::New(); + this->RMICommunicator = this->Communicator; +} + +//---------------------------------------------------------------------------- +vtkSocketController::~vtkSocketController() +{ + this->Communicator->Delete(); + this->Communicator = this->RMICommunicator = 0; +} + +void vtkSocketController::Initialize(int* , char***) +{ + if (vtkSocketController::Initialized) + { + vtkWarningMacro("Already initialized."); + return; + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + WSAData wsaData; + if (WSAStartup(WSA_VERSION, &wsaData)) + { + vtkErrorMacro("Could not initialize sockets !"); + } +#endif + vtkSocketController::Initialized = 1; + +} + +void vtkSocketController::SetNumberOfProcesses(int vtkNotUsed(num)) +{ + vtkErrorMacro("Can not change the number of processes."); + return; +} + +void vtkSocketController::SetCommunicator(vtkSocketCommunicator* comm) +{ + if (comm == this->Communicator) + { + return; + } + if (this->Communicator) + { + this->Communicator->UnRegister(this); + } + this->Communicator = comm; + this->RMICommunicator = comm; + if (comm) + { + comm->Register(this); + } +} + +//---------------------------------------------------------------------------- +void vtkSocketController::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + + +int vtkSocketController::WaitForConnection(int port) +{ + return vtkSocketCommunicator::SafeDownCast(this->Communicator)-> + WaitForConnection(port); +} + +void vtkSocketController::CloseConnection() +{ + vtkSocketCommunicator::SafeDownCast(this->Communicator)-> + CloseConnection(); +} + +int vtkSocketController::ConnectTo( char* hostName, int port ) +{ + return vtkSocketCommunicator::SafeDownCast(this->Communicator)-> + ConnectTo(hostName, port); +} + +int vtkSocketController::GetSwapBytesInReceivedData() +{ + return vtkSocketCommunicator::SafeDownCast(this->Communicator)-> + GetSwapBytesInReceivedData(); +} diff --git a/Parallel/vtkSocketController.h b/Parallel/vtkSocketController.h new file mode 100644 index 0000000..ec2925e --- /dev/null +++ b/Parallel/vtkSocketController.h @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSocketController.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSocketController - Process communication using Sockets +// .SECTION Description +// This is a concrete implementation of vtkMultiProcessController. +// It supports one-to-one communication using sockets. Note that +// process 0 will always correspond to self and process 1 to the +// remote process. This class is best used with ports. + +// .SECTION see also +// vtkMultiProcessController vtkSocketCommunicator vtkInputPort vtkOutputPort + +#ifndef __vtkSocketController_h +#define __vtkSocketController_h + +#include "vtkMultiProcessController.h" + +class vtkSocketCommunicator; + +class VTK_PARALLEL_EXPORT vtkSocketController : public vtkMultiProcessController +{ +public: + static vtkSocketController *New(); + vtkTypeRevisionMacro(vtkSocketController,vtkMultiProcessController); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method is for initialiazing sockets. + // One of these is REQUIRED for Windows. + virtual void Initialize(int* argc, char*** argv, int) + { this->Initialize(argc,argv); } + virtual void Initialize(int* argc, char*** argv); + virtual void Initialize() + { this->Initialize(0,0); } + + // Description: + // Does not apply to sockets. Does nothing. + void Finalize() {}; + void Finalize(int) {}; + + // Description: + // Does not apply to sockets. Does nothing. + void SingleMethodExecute() {}; + + // Description: + // Does not apply to sockets. Does nothing. + void MultipleMethodExecute() {}; + + // Description: + // Does not apply to sockets. Does nothing. + void CreateOutputWindow() {}; + + // Description: + // Does not apply to sockets. Does nothing. + void Barrier() {}; + + // Description: + // Set the number of processes you will be using. + virtual void SetNumberOfProcesses(int num); + + // Description: + // Wait for connection on a given port, forwarded + // to the communicator + virtual int WaitForConnection(int port); + + // Description: + // Close a connection, forwarded + // to the communicator + virtual void CloseConnection(); + + // Description: + // Open a connection to a give machine, forwarded + // to the communicator + virtual int ConnectTo( char* hostName, int port ); + + int GetSwapBytesInReceivedData(); + + // Description: + // Set the communicator used in normal and rmi communications. + void SetCommunicator(vtkSocketCommunicator* comm); + +//BTX + + enum Consts { + ENDIAN_TAG=1010580540 // 0x3c3c3c3c + }; + +//ETX + +protected: + + vtkSocketController(); + ~vtkSocketController(); + + // Initialize only once, finialize on destruction. + static int Initialized; +private: + vtkSocketController(const vtkSocketController&); // Not implemented. + void operator=(const vtkSocketController&); // Not implemented. +}; + + +#endif // __vtkSocketController_h diff --git a/Parallel/vtkSubGroup.cxx b/Parallel/vtkSubGroup.cxx new file mode 100644 index 0000000..4d1c39e --- /dev/null +++ b/Parallel/vtkSubGroup.cxx @@ -0,0 +1,644 @@ +/*========================================================================= + + Program: ParaView + Module: $RCSfile: vtkSubGroup.cxx,v $ + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +#include "vtkObjectFactory.h" +#include "vtkMultiProcessController.h" +#include "vtkSubGroup.h" + +#ifdef _MSC_VER +#pragma warning ( disable : 4100 ) +#endif +#include + +vtkCxxRevisionMacro(vtkSubGroup, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkSubGroup); + +vtkSubGroup::vtkSubGroup() +{ + this->members = NULL; + this->comm = NULL; + + this->nmembers = 0; + this->myLocalRank = -1; + this->tag = 0; + this->nFrom = this->nTo = this->fanInTo = 0; + this->nRecv = this->nSend = 0; + this->gatherRoot = this->gatherLength = -1; +} + +int vtkSubGroup::Initialize(int p0=0, int p1=0, int me=0, int itag=0, vtkCommunicator *c=NULL) +{ + int i, ii; + this->nmembers = p1 - p0 + 1; + this->tag = itag; + this->comm = c; + + if (this->members) + { + delete [] this->members; + } + + this->members = new int [this->nmembers]; + + this->myLocalRank = -1; + + for (i=p0, ii=0; i<=p1; i++) + { + if (i == me) + { + this->myLocalRank = ii; + } + this->members[ii++] = i; + } + + if (this->myLocalRank == -1) + { + delete [] this->members; + this->members = NULL; + return 1; + } + + this->gatherRoot = this->gatherLength = -1; + + this->computeFanInTargets(); + + return 0; +} + +int vtkSubGroup::computeFanInTargets() +{ + int i; + this->nTo = 0; + this->nFrom = 0; + + for (i = 1; i < this->nmembers; i <<= 1) + { + int other = this->myLocalRank ^ i; + + if (other >= this->nmembers) + { + continue; + } + + if (this->myLocalRank > other) + { + this->fanInTo = other; + + this->nTo++; /* one at most */ + + break; + } + else + { + this->fanInFrom[this->nFrom] = other; + this->nFrom++; + } + } + return 0; +} +void vtkSubGroup::moveRoot(int root) +{ + int tmproot = this->members[root]; + this->members[root] = this->members[0]; + this->members[0] = tmproot; + + return; +} +void vtkSubGroup::restoreRoot(int root) +{ + if (root == 0) + { + return; + } + + this->moveRoot(root); + + if (this->myLocalRank == root) + { + this->myLocalRank = 0; + this->computeFanInTargets(); + } + else if (this->myLocalRank == 0) + { + this->myLocalRank = root; + this->computeFanInTargets(); + } + + return; +} +void vtkSubGroup::setUpRoot(int root) +{ + if (root == 0) + { + return; + } + + this->moveRoot(root); + + if (this->myLocalRank == root) + { + this->myLocalRank = 0; + this->computeFanInTargets(); + } + else if (this->myLocalRank == 0) + { + this->myLocalRank = root; + this->computeFanInTargets(); + } + + return; +} + +vtkSubGroup::~vtkSubGroup() +{ + delete [] this->members; + this->members = NULL; +} +void vtkSubGroup::setGatherPattern(int root, int length) +{ + int i; + + if ( (root == this->gatherRoot) && (length == this->gatherLength)) + { + return; + } + + this->gatherRoot = root; + this->gatherLength = length; + + int clogn; // ceiling(log2(this->nmembers)) + for (clogn=0; 1<nmembers; clogn++); + + int left = 0; + int right = this->nmembers - 1; + int iroot = root; + + this->nSend = 0; + this->nRecv = 0; + + for (i=0; imyLocalRank == iroot) + { + this->recvId[this->nRecv] = this->members[src]; + this->recvOffset[this->nRecv] = offset; + this->recvLength[this->nRecv] = len; + + this->nRecv++; + + } + else if (this->myLocalRank == src) + { + this->sendId = this->members[iroot]; + this->sendOffset = offset; + this->sendLength = len; + + this->nSend++; + } + if (this->myLocalRank <= mid) + { + if (iroot > mid) + { + iroot = src; + } + right = mid; + } + else + { + if (iroot <= mid) + { + iroot = src; + } + left = mid + 1; + } + if (left == right) break; + } + return; +} + +int vtkSubGroup::getLocalRank(int processId) +{ + int localRank = processId - this->members[0]; + + if ( (localRank < 0) || (localRank >= this->nmembers)) return -1; + else return localRank; +} +#define MINOP if (tempbuf[p] < buf[p]) {buf[p] = tempbuf[p];} +#define MAXOP if (tempbuf[p] > buf[p]) {buf[p] = tempbuf[p];} +#define SUMOP buf[p] += tempbuf[p]; + +#define REDUCE(Type, name, op) \ +int vtkSubGroup::Reduce##name(Type *data, Type *to, int size, int root) \ +{ \ + int i, p;\ + if (this->nmembers == 1)\ + { \ + for (i=0; i= this->nmembers)) \ + { \ + return 1;\ + } \ + if (root != 0) \ + { \ + this->setUpRoot(root); \ + } \ + Type *buf, *tempbuf; \ + tempbuf = new Type [size]; \ + if (this->nTo > 0) \ + { \ + buf = new Type [size];\ + } \ + else \ + { \ + buf = to;\ + } \ + if (buf != data) \ + { \ + memcpy(buf, data, size * sizeof(Type));\ + } \ + for (i=0; i < this->nFrom; i++) \ + { \ + this->comm->Receive(tempbuf, size,\ + this->members[this->fanInFrom[i]], this->tag);\ + for (p=0; pnTo > 0)\ + { \ + this->comm->Send(buf, size, this->members[this->fanInTo], this->tag);\ + delete [] buf;\ + }\ + if (root != 0) \ + { \ + this->restoreRoot(root);\ + } \ + return 0; \ +} + +REDUCE(int, Min, MINOP) +REDUCE(float, Min, MINOP) +REDUCE(double, Min, MINOP) +REDUCE(int, Max, MAXOP) +REDUCE(float, Max, MAXOP) +REDUCE(double, Max, MAXOP) +REDUCE(int, Sum, SUMOP) + +#define BROADCAST(Type) \ +int vtkSubGroup::Broadcast(Type *data, int length, int root) \ +{ \ + int i;\ + if (this->nmembers == 1) \ + { \ + return 0;\ + } \ + if ( (root < 0) || (root >= this->nmembers)) \ + { \ + return 1;\ + } \ + if (root != 0) \ + { \ + this->setUpRoot(root); \ + } \ + if (this->nTo > 0) \ + { \ + this->comm->Receive(data, length, this->members[this->fanInTo], this->tag);\ + } \ + for (i = this->nFrom-1 ; i >= 0; i--) \ + { \ + this->comm->Send(data, length, this->members[this->fanInFrom[i]], this->tag); \ + } \ + if (root != 0) \ + { \ + this->restoreRoot(root); \ + } \ + return 0; \ +} + +BROADCAST(char) +BROADCAST(int) +BROADCAST(float) +BROADCAST(double) + +#define GATHER(Type)\ +int vtkSubGroup::Gather(Type *data, Type *to, int length, int root)\ +{ \ + int i;\ + Type *recvBuf;\ + if (this->nmembers == 1)\ + { \ + for (i=0; i= this->nmembers)) \ + { \ + return 1;\ + } \ + this->setGatherPattern(root, length);\ + if (this->nSend > 0)\ + { \ + recvBuf = new Type [length * this->nmembers];\ + }\ + else \ + { \ + recvBuf = to;\ + }\ + for (i=0; inRecv; i++) \ + { \ + this->comm->Receive(recvBuf + this->recvOffset[i], \ + this->recvLength[i], this->recvId[i], this->tag);\ + }\ + memcpy(recvBuf + (length * this->myLocalRank), data,\ + length * sizeof(Type));\ + if (this->nSend > 0) \ + { \ + this->comm->Send(recvBuf + this->sendOffset,\ + this->sendLength, this->sendId, this->tag);\ + delete [] recvBuf;\ + }\ + return 0; \ +} + +GATHER(int) +GATHER(char) +GATHER(float) + +int vtkSubGroup::AllReduceUniqueList(int *list, int len, int **newList) +{ + int transferLen, myListLen, lastListLen, nextListLen; + int *myList, *lastList, *nextList; + + myListLen = vtkSubGroup::MakeSortedUnique(list, len, &myList); + + if (this->nmembers == 1) + { + *newList = myList; + return myListLen; + } + + lastList = myList; + lastListLen = myListLen; + + for (int i=0; i < this->nFrom; i++) + { + this->comm->Receive(&transferLen, 1, + this->members[this->fanInFrom[i]], this->tag); + + int *buf = new int [transferLen]; + + this->comm->Receive(buf, transferLen, + this->members[this->fanInFrom[i]], this->tag+1); + + nextListLen = vtkSubGroup::MergeSortedUnique(lastList, lastListLen, + buf, transferLen, &nextList); + + delete [] buf; + delete [] lastList; + + lastList = nextList; + lastListLen = nextListLen; + } + + if (this->nTo > 0) + { + this->comm->Send(&lastListLen, 1, this->members[this->fanInTo], this->tag); + + this->comm->Send(lastList, lastListLen, + this->members[this->fanInTo], this->tag+1); + } + + + this->Broadcast(&lastListLen, 1, 0); + + if (this->myLocalRank > 0) + { + delete [] lastList; + lastList = new int [lastListLen]; + } + + this->Broadcast(lastList, lastListLen, 0); + + *newList = lastList; + + return lastListLen; +} +int vtkSubGroup::MergeSortedUnique(int *list1, int len1, int *list2, int len2, + int **newList) +{ + int newLen = 0; + int i1=0; + int i2=0; + + int *newl = new int [len1 + len2]; + + if (newl == NULL) + { + return 0; + } + + while ((i1 < len1) || (i2 < len2)) + { + if (i2 == len2) + { + newl[newLen++] = list1[i1++]; + } + else if (i1 == len1) + { + newl[newLen++] = list2[i2++]; + } + else if (list1[i1] < list2[i2]) + { + newl[newLen++] = list1[i1++]; + } + else if (list1[i1] > list2[i2]) + { + newl[newLen++] = list2[i2++]; + } + else + { + newl[newLen++] = list1[i1++]; + i2++; + } + } + + *newList = newl; + + return newLen; +} +int vtkSubGroup::MakeSortedUnique(int *list, int len, int **newList) +{ + int i, newlen; + int *newl; + + newl = new int [len]; + if (newl == NULL) + { + return 0; + } + + memcpy(newl, list, len * sizeof(int)); + vtkstd::sort(newl, newl + len); + + for (i=1, newlen=1; iReduceMin(&token, &result, 1, 0); + this->Broadcast(&token, 1, 0); + return 0; +} + +void vtkSubGroup::PrintSubGroup() const +{ + int i; + cout << "(Fan In setup ) nFrom: " << this->nFrom << ", nTo: " << this->nTo << endl; + if (this->nFrom > 0) + { + for (i=0; inRecv << ", nSend: " << this->nSend << endl; + if (this->nRecv > 0) + { + for (i=0; igatherRoot ; + cout << ", gatherLength " << this->gatherLength << endl; + + cout << "nmembers: " << this->nmembers << endl; + cout << "myLocalRank: " << this->myLocalRank << endl; + for (i=0; inmembers; i++) + { + cout << " " << this->members[i]; + if (i && (i%20 == 0)) + { + cout << endl; + } + } + cout << endl; + cout << "comm: " << this->comm; + cout << endl; +} + +void vtkSubGroup::PrintSelf(ostream &os, vtkIndent indent) +{ + int i; + os << indent << "(Fan In setup ) nFrom: " << this->nFrom << ", nTo: " << this->nTo << endl; + if (this->nFrom > 0) + { + for (i=0; inRecv << ", nSend: " << this->nSend << endl; + if (this->nRecv > 0) + { + for (i=0; igatherRoot ; + os << indent << ", gatherLength " << this->gatherLength << endl; + + os << indent << "nmembers: " << this->nmembers << endl; + os << indent << "myLocalRank: " << this->myLocalRank << endl; + for (i=0; inmembers; i++) + { + os << indent << " " << this->members[i]; + if (i && (i%20 == 0)) + { + os << indent << endl; + } + } + os << indent << endl; + os << indent << "comm: " << this->comm; + os << indent << endl; +} diff --git a/Parallel/vtkSubGroup.h b/Parallel/vtkSubGroup.h new file mode 100644 index 0000000..baf41c4 --- /dev/null +++ b/Parallel/vtkSubGroup.h @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: ParaView + Module: $RCSfile: vtkSubGroup.h,v $ + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/*---------------------------------------------------------------------------- + Copyright (c) Sandia Corporation + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. +----------------------------------------------------------------------------*/ + +// .NAME vtkSubGroup - scalable collective communication for a +// subset of members of a parallel VTK application +// +// .SECTION Description +// This class provides scalable broadcast, reduce, etc. using +// only a vtkMultiProcessController. It does not require MPI. +// Users are vtkPKdTree and vtkDistributedDataFilter. +// +// .SECTION See Also +// vtkPKdTree vtkDistributedDataFilter + +#ifndef __vtkSubGroup_h +#define __vtkSubGroup_h + +#include "vtkObject.h" + +class vtkMultiProcessController; +class vtkCommunicator; + +class VTK_PARALLEL_EXPORT vtkSubGroup : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkSubGroup, vtkObject); + virtual void PrintSelf(ostream &os, vtkIndent indent); + static vtkSubGroup *New(); + +//BTX + // The wrapper gets confused here and falls down. + enum {MINOP = 1, MAXOP = 2, SUMOP = 3}; +//ETX + // Description: + // Initialize a communication subgroup for the processes + // with rank p0 through p1 of the given communicator. (So + // vtkSubGroup is limited to working with subgroups that + // are identified by a contiguous set of rank IDs.) + // The third argument is the callers rank, which must + // in the range from p0 through p1. + + int Initialize(int p0, int p1, int me, int tag, vtkCommunicator *c); + + int Gather(int *data, int *to, int length, int root); + int Gather(char *data, char *to, int length, int root); + int Gather(float *data, float *to, int length, int root); + int Broadcast(float *data, int length, int root); + int Broadcast(double *data, int length, int root); + int Broadcast(int *data, int length, int root); + int Broadcast(char *data, int length, int root); + int ReduceSum(int *data, int *to, int length, int root); + int ReduceMax(float *data, float *to, int length, int root); + int ReduceMax(double *data, double *to, int length, int root); + int ReduceMax(int *data, int *to, int length, int root); + int ReduceMin(float *data, float *to, int length, int root); + int ReduceMin(double *data, double *to, int length, int root); + int ReduceMin(int *data, int *to, int length, int root); + + int AllReduceUniqueList(int *list, int len, int **newList); + int MergeSortedUnique(int *list1, int len1, int *list2, int len2, int **newList); + + void setGatherPattern(int root, int length); + int getLocalRank(int processID); + + int Barrier(); + + void PrintSubGroup() const; + + static int MakeSortedUnique(int *list, int len, int **newList); + + int tag; + +protected: + vtkSubGroup(); + ~vtkSubGroup(); + +private: + int computeFanInTargets(); + void restoreRoot(int rootLoc); + void moveRoot(int rootLoc); + void setUpRoot(int root); + + int nFrom; + int nTo; + + int sendId; // gather + int sendOffset; + int sendLength; + + int recvId[20]; + int recvOffset[20]; + int recvLength[20]; + int fanInFrom[20]; // reduce, broadcast + + int fanInTo; + int nSend; + int nRecv; + int gatherRoot; + int gatherLength; + + int *members; + int nmembers; + int myLocalRank; + + vtkCommunicator *comm; + + vtkSubGroup(const vtkSubGroup&); // Not implemented + void operator=(const vtkSubGroup&); // Not implemented +}; +#endif diff --git a/Parallel/vtkTransmitPolyDataPiece.cxx b/Parallel/vtkTransmitPolyDataPiece.cxx new file mode 100644 index 0000000..c3d986d --- /dev/null +++ b/Parallel/vtkTransmitPolyDataPiece.cxx @@ -0,0 +1,277 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransmitPolyDataPiece.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransmitPolyDataPiece.h" + +#include "vtkCellData.h" +#include "vtkExtractPolyDataPiece.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkTransmitPolyDataPiece, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkTransmitPolyDataPiece); + +vtkCxxSetObjectMacro(vtkTransmitPolyDataPiece,Controller, + vtkMultiProcessController); + +//---------------------------------------------------------------------------- +vtkTransmitPolyDataPiece::vtkTransmitPolyDataPiece() +{ + this->CreateGhostCells = 1; + + // Controller keeps a reference to this object as well. + this->Controller = NULL; + this->SetController(vtkMultiProcessController::GetGlobalController()); + + this->Buffer = vtkPolyData::New(); + this->BufferPiece = -1; + this->BufferNumberOfPieces = 0; + this->BufferGhostLevel = 0; +} + +//---------------------------------------------------------------------------- +vtkTransmitPolyDataPiece::~vtkTransmitPolyDataPiece() +{ + this->Buffer->Delete(); + this->Buffer = NULL; + this->SetController(NULL); +} + +//---------------------------------------------------------------------------- +int vtkTransmitPolyDataPiece::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + if (this->Controller == NULL) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + return 1; + } + + if (this->Controller->GetLocalProcessId() == 0) + { // Request everything. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + } + else + { // Request nothing. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkTransmitPolyDataPiece::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkTransmitPolyDataPiece::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkPolyData *input = vtkPolyData::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int procId; + int updateGhostLevel = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + int updatePiece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + int updateNumPieces = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + vtkDemandDrivenPipeline* ddp = + vtkDemandDrivenPipeline::SafeDownCast(this->GetExecutive()); + + // Check the pipline mtime to see if we are executing only because + // the update request changed. If so and the only change was to + // decrease the number of requested ghost levels then do not bother + // retransmitting. + if (ddp + && ddp->GetPipelineMTime() < this->Buffer->GetMTime() + && updatePiece == this->BufferPiece + && updateNumPieces == this->BufferNumberOfPieces + && updateGhostLevel <= this->BufferGhostLevel) + { + // We deep copy, because we do not want to modify the buffer + // when we remove ghost cells from the output. + output->DeepCopy(this->Buffer); + if (updateGhostLevel < this->BufferGhostLevel) + { + output->RemoveGhostCells(updateGhostLevel+1); + } + return 1; + } + + if (this->Controller == NULL) + { + vtkErrorMacro("Could not find Controller."); + return 0; + } + + procId = this->Controller->GetLocalProcessId(); + if (procId == 0) + { + // It is important to synchronize these calls (all processes execute) + // cerr << "Root Execute\n"; + this->RootExecute(input, output, outInfo); + } + else + { + // cerr << "Satellite Execute " << procId << endl; + this->SatelliteExecute(procId, output, outInfo); + } + + // Save the output in the buffer. + this->Buffer->ShallowCopy(output); + // Piece inforomation is not set by this point. + // We do not have access to buffers piece, so save in ivars. + this->BufferPiece = updatePiece; + this->BufferNumberOfPieces = updateNumPieces; + this->BufferGhostLevel = updateGhostLevel; + return 1; +} + +//---------------------------------------------------------------------------- +void vtkTransmitPolyDataPiece::RootExecute(vtkPolyData *input, + vtkPolyData *output, + vtkInformation *outInfo) +{ + vtkPolyData *tmp = vtkPolyData::New(); + vtkExtractPolyDataPiece *extract = vtkExtractPolyDataPiece::New(); + int ext[3]; + int numProcs, i; + + vtkStreamingDemandDrivenPipeline *extractExecutive = + vtkStreamingDemandDrivenPipeline::SafeDownCast(extract->GetExecutive()); + vtkInformation *extractInfo = extractExecutive->GetOutputInformation(0); + + // First, set up the pipeline and handle local request. + tmp->ShallowCopy(input); + tmp->SetReleaseDataFlag(0); + extract->SetCreateGhostCells(this->CreateGhostCells); + extract->SetInput(tmp); + + extractExecutive->UpdateDataObject(); + extractInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + extractInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + extractInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + extractInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED(), 1); + extract->Update(); + + // Copy geometry without copying information. + output->CopyStructure(extract->GetOutput()); + output->GetPointData()->PassData(extract->GetOutput()->GetPointData()); + output->GetCellData()->PassData(extract->GetOutput()->GetCellData()); + output->GetFieldData()->PassData(extract->GetOutput()->GetFieldData()); + + // Now do each of the satellite requests. + numProcs = this->Controller->GetNumberOfProcesses(); + for (i = 1; i < numProcs; ++i) + { + this->Controller->Receive(ext, 3, i, 22341); + extractInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + ext[1]); + extractInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + ext[0]); + extractInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ext[2]); + extract->Update(); + this->Controller->Send(extract->GetOutput(), i, 22342); + } + tmp->Delete(); + extract->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkTransmitPolyDataPiece::SatelliteExecute(int, vtkPolyData *output, + vtkInformation *outInfo) +{ + vtkPolyData *tmp = vtkPolyData::New(); + int ext[3]; + + ext[0] = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + ext[1] = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ext[2] = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + this->Controller->Send(ext, 3, 0, 22341); + this->Controller->Receive(tmp, 0, 22342); + + // Copy geometry without copying information. + output->CopyStructure(tmp); + output->GetPointData()->PassData(tmp->GetPointData()); + output->GetCellData()->PassData(tmp->GetCellData()); + output->GetFieldData()->PassData(tmp->GetFieldData()); + + tmp->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkTransmitPolyDataPiece::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Create Ghost Cells: " << (this->CreateGhostCells ? "On\n" : "Off\n"); + + os << indent << "Controller: (" << this->Controller << ")\n"; + +} diff --git a/Parallel/vtkTransmitPolyDataPiece.h b/Parallel/vtkTransmitPolyDataPiece.h new file mode 100644 index 0000000..9920f3e --- /dev/null +++ b/Parallel/vtkTransmitPolyDataPiece.h @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransmitPolyDataPiece.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransmitPolyDataPiece - Return specified piece, including specified +// number of ghost levels. +// .SECTION Description +// This filter updates the appropriate piece by requesting the piece from +// process 0. Process 0 always updates all of the data. It is important that +// Execute get called on all processes, otherwise the filter will deadlock. + + +#ifndef __vtkTransmitPolyDataPiece_h +#define __vtkTransmitPolyDataPiece_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkTransmitPolyDataPiece : public vtkPolyDataAlgorithm +{ +public: + static vtkTransmitPolyDataPiece *New(); + vtkTypeRevisionMacro(vtkTransmitPolyDataPiece, vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // By defualt this filter uses the global controller, + // but this method can be used to set another instead. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + + // Description: + // Turn on/off creating ghost cells (on by default). + vtkSetMacro(CreateGhostCells, int); + vtkGetMacro(CreateGhostCells, int); + vtkBooleanMacro(CreateGhostCells, int); + +protected: + vtkTransmitPolyDataPiece(); + ~vtkTransmitPolyDataPiece(); + + // Data generation method + int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void RootExecute(vtkPolyData *input, vtkPolyData *output, vtkInformation *outInfo); + void SatelliteExecute(int procId, vtkPolyData *output, vtkInformation *outInfo); + int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + vtkPolyData *Buffer; + int BufferPiece; + int BufferNumberOfPieces; + int BufferGhostLevel; + + int CreateGhostCells; + vtkMultiProcessController *Controller; + +private: + vtkTransmitPolyDataPiece(const vtkTransmitPolyDataPiece&); // Not implemented + void operator=(const vtkTransmitPolyDataPiece&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkTransmitUnstructuredGridPiece.cxx b/Parallel/vtkTransmitUnstructuredGridPiece.cxx new file mode 100644 index 0000000..81b5430 --- /dev/null +++ b/Parallel/vtkTransmitUnstructuredGridPiece.cxx @@ -0,0 +1,254 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransmitUnstructuredGridPiece.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransmitUnstructuredGridPiece.h" + +#include "vtkCellData.h" +#include "vtkExtractUnstructuredGridPiece.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkTransmitUnstructuredGridPiece, "$Revision: 1.20 $"); +vtkStandardNewMacro(vtkTransmitUnstructuredGridPiece); + +vtkCxxSetObjectMacro(vtkTransmitUnstructuredGridPiece,Controller, + vtkMultiProcessController); + +//---------------------------------------------------------------------------- +vtkTransmitUnstructuredGridPiece::vtkTransmitUnstructuredGridPiece() +{ + this->CreateGhostCells = 1; + + // Controller keeps a reference to this object as well. + this->Controller = NULL; + this->SetController(vtkMultiProcessController::GetGlobalController()); +} + +//---------------------------------------------------------------------------- +vtkTransmitUnstructuredGridPiece::~vtkTransmitUnstructuredGridPiece() +{ + this->SetController(NULL); +} + +//---------------------------------------------------------------------------- +int vtkTransmitUnstructuredGridPiece::RequestUpdateExtent( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *vtkNotUsed(outputVector)) +{ + // get the info object + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + + if (this->Controller == NULL) + { + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + return 1; + } + + if (this->Controller->GetLocalProcessId() == 0) + { // Request everything. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 1); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + } + else + { // Request nothing. + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + 0); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + 0); + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkTransmitUnstructuredGridPiece::RequestInformation( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR(), + inInfo->Get(vtkStreamingDemandDrivenPipeline::EXTENT_TRANSLATOR())); + outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), + -1); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkTransmitUnstructuredGridPiece::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + int procId; + + if (this->Controller == NULL) + { + vtkErrorMacro("Could not find Controller."); + return 1; + } + + procId = this->Controller->GetLocalProcessId(); + if (procId == 0) + { + // cerr << "Root Execute\n"; + this->RootExecute(input, output, outInfo); + } + else + { + // cerr << "Satellite Execute " << procId << endl; + this->SatelliteExecute(procId, output, outInfo); + } + + return 1; +} + +//---------------------------------------------------------------------------- +void vtkTransmitUnstructuredGridPiece::RootExecute(vtkUnstructuredGrid *input, + vtkUnstructuredGrid *output, + vtkInformation *outInfo) +{ + vtkUnstructuredGrid *tmp = vtkUnstructuredGrid::New(); + vtkExtractUnstructuredGridPiece *extract = + vtkExtractUnstructuredGridPiece::New(); + int ext[3]; + int numProcs, i; + + int outPiece = + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + if (outPiece != 0) + { + vtkWarningMacro(<< "Piece " << outPiece + << " does not match process 0. " + << "Altering request to try to avoid a deadlock."); + } + + vtkStreamingDemandDrivenPipeline *extractExecutive = + vtkStreamingDemandDrivenPipeline::SafeDownCast(extract->GetExecutive()); + + // First, set up the pipeline and handle local request. + tmp->ShallowCopy(input); + tmp->SetReleaseDataFlag(0); + extract->SetCreateGhostCells(this->CreateGhostCells); + extract->SetInput(tmp); + extractExecutive->UpdateDataObject(); + + vtkInformation *extractOutInfo = extractExecutive->GetOutputInformation(0); + extractOutInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES())); + extractOutInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER())); + extractOutInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS())); + extractOutInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT_INITIALIZED(), 1); + + extract->Update(); + + // Copy geometry without copying information. + output->CopyStructure(extract->GetOutput()); + output->GetPointData()->PassData(extract->GetOutput()->GetPointData()); + output->GetCellData()->PassData(extract->GetOutput()->GetCellData()); + vtkFieldData* inFd = extract->GetOutput()->GetFieldData(); + vtkFieldData* outFd = output->GetFieldData(); + if (inFd && outFd) + { + outFd->PassData(inFd); + } + + // Now do each of the satellite requests. + numProcs = this->Controller->GetNumberOfProcesses(); + for (i = 1; i < numProcs; ++i) + { + this->Controller->Receive(ext, 3, i, 22341); + extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), + ext[1]); + extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), + ext[0]); + extractOutInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), + ext[2]); + extract->Update(); + this->Controller->Send(extract->GetOutput(), i, 22342); + } + tmp->Delete(); + extract->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkTransmitUnstructuredGridPiece::SatelliteExecute( + int, vtkUnstructuredGrid *output, vtkInformation *outInfo) +{ + vtkUnstructuredGrid *tmp = vtkUnstructuredGrid::New(); + int ext[3]; + + ext[0] = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()); + ext[1] = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()); + ext[2] = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()); + + this->Controller->Send(ext, 3, 0, 22341); + this->Controller->Receive(tmp, 0, 22342); + + // Copy geometry without copying information. + output->CopyStructure(tmp); + output->GetPointData()->PassData(tmp->GetPointData()); + output->GetCellData()->PassData(tmp->GetCellData()); + + tmp->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkTransmitUnstructuredGridPiece::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Create Ghost Cells: " << (this->CreateGhostCells ? "On\n" : "Off\n"); + + os << indent << "Controller: (" << this->Controller << ")\n"; + +} + diff --git a/Parallel/vtkTransmitUnstructuredGridPiece.h b/Parallel/vtkTransmitUnstructuredGridPiece.h new file mode 100644 index 0000000..1df1903 --- /dev/null +++ b/Parallel/vtkTransmitUnstructuredGridPiece.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransmitUnstructuredGridPiece.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransmitUnstructuredGridPiece - Return specified piece, including specified +// number of ghost levels. +// .SECTION Description +// This filter updates the appropriate piece by requesting the piece from +// process 0. Process 0 always updates all of the data. It is important that +// Execute get called on all processes, otherwise the filter will deadlock. + + +#ifndef __vtkTransmitUnstructuredGridPiece_h +#define __vtkTransmitUnstructuredGridPiece_h + +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkMultiProcessController; + +class VTK_PARALLEL_EXPORT vtkTransmitUnstructuredGridPiece : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkTransmitUnstructuredGridPiece *New(); + vtkTypeRevisionMacro(vtkTransmitUnstructuredGridPiece, vtkUnstructuredGridAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // By defualt this filter uses the global controller, + // but this method can be used to set another instead. + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + + // Description: + // Turn on/off creating ghost cells (on by default). + vtkSetMacro(CreateGhostCells, int); + vtkGetMacro(CreateGhostCells, int); + vtkBooleanMacro(CreateGhostCells, int); + +protected: + vtkTransmitUnstructuredGridPiece(); + ~vtkTransmitUnstructuredGridPiece(); + + // Data generation method + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + void RootExecute(vtkUnstructuredGrid *input, vtkUnstructuredGrid *output, + vtkInformation *outInfo); + void SatelliteExecute(int procId, vtkUnstructuredGrid *output, + vtkInformation *outInfo); + virtual int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + + int CreateGhostCells; + vtkMultiProcessController *Controller; + +private: + vtkTransmitUnstructuredGridPiece(const vtkTransmitUnstructuredGridPiece&); // Not implemented + void operator=(const vtkTransmitUnstructuredGridPiece&); // Not implemented +}; + +#endif diff --git a/Parallel/vtkTreeCompositer.cxx b/Parallel/vtkTreeCompositer.cxx new file mode 100644 index 0000000..e32fa7f --- /dev/null +++ b/Parallel/vtkTreeCompositer.cxx @@ -0,0 +1,266 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTreeCompositer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// This software and ancillary information known as vtk_ext (and +// herein called "SOFTWARE") is made available under the terms +// described below. The SOFTWARE has been approved for release with +// associated LA_CC Number 99-44, granted by Los Alamos National +// Laboratory in July 1999. +// +// Unless otherwise indicated, this SOFTWARE has been authored by an +// employee or employees of the University of California, operator of +// the Los Alamos National Laboratory under Contract No. W-7405-ENG-36 +// with the United States Department of Energy. +// +// The United States Government has rights to use, reproduce, and +// distribute this SOFTWARE. The public may copy, distribute, prepare +// derivative works and publicly display this SOFTWARE without charge, +// provided that this Notice and any statement of authorship are +// reproduced on all copies. +// +// Neither the U. S. Government, the University of California, nor the +// Advanced Computing Laboratory makes any warranty, either express or +// implied, nor assumes any liability or responsibility for the use of +// this SOFTWARE. +// +// If SOFTWARE is modified to produce derivative works, such modified +// SOFTWARE should be clearly marked, so as not to confuse it with the +// version available from Los Alamos National Laboratory. + +#include "vtkTreeCompositer.h" +#include "vtkObjectFactory.h" +#include "vtkToolkits.h" +#include "vtkFloatArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkMultiProcessController.h" + +vtkCxxRevisionMacro(vtkTreeCompositer, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkTreeCompositer); + +#ifdef VTK_USE_MPI + #include +#endif + +//------------------------------------------------------------------------- +vtkTreeCompositer::vtkTreeCompositer() +{ +} + + +//------------------------------------------------------------------------- +vtkTreeCompositer::~vtkTreeCompositer() +{ +} + +//------------------------------------------------------------------------- +// Jim's composite stuff +//------------------------------------------------------------------------- +// Results are put in the local data. +void vtkCompositeImagePair(vtkFloatArray *localZ, + vtkDataArray *localP, + vtkFloatArray *remoteZ, + vtkDataArray *remoteP) +{ + int i,j; + int pixel_data_size; + float *pEnd; + int numComp = localP->GetNumberOfComponents(); + float* remoteZdata = remoteZ->GetPointer(0); + float* remotePdata = reinterpret_cast(remoteP->GetVoidPointer(0)); + float* localZdata = localZ->GetPointer(0); + float* localPdata = reinterpret_cast(localP->GetVoidPointer(0)); + + int total_pixels = localZ->GetNumberOfTuples(); + int useCharFlag = 0; + + if (localP->GetDataType() == VTK_UNSIGNED_CHAR) + { + useCharFlag = 1; + } + + if (useCharFlag) + { + pEnd = remoteZdata + total_pixels; + if (numComp == 4) + { + while(remoteZdata != pEnd) + { + if (*remoteZdata < *localZdata) + { + *localZdata++ = *remoteZdata++; + *localPdata++ = *remotePdata++; + } + else + { + ++localZdata; + ++remoteZdata; + ++localPdata; + ++remotePdata; + } + } + } + else if (numComp == 3) + { + unsigned char* clocalPdata = reinterpret_cast(localPdata); + unsigned char* cremotePdata = reinterpret_cast(remotePdata); + while(remoteZdata != pEnd) + { + if (*remoteZdata < *localZdata) + { + *localZdata++ = *remoteZdata++; + *clocalPdata++ = *cremotePdata++; + *clocalPdata++ = *cremotePdata++; + *clocalPdata++ = *cremotePdata++; + } + else + { + ++localZdata; + ++remoteZdata; + clocalPdata += 3; + cremotePdata += 3; + } + } + } + } + else + { + pixel_data_size = numComp; + for (i = 0; i < total_pixels; i++) + { + if (remoteZdata[i] < localZdata[i]) + { + localZdata[i] = remoteZdata[i]; + for (j = 0; j < pixel_data_size; j++) + { + localPdata[i*pixel_data_size+j] = remotePdata[i*pixel_data_size+j]; + } + } + } + } +} + + +#define vtkTCPow2(j) (1 << (j)) + +static inline int vtkTCLog2(int j, int& exact) +{ + int counter=0; + exact = 1; + while(j) + { + if ( ( j & 1 ) && (j >> 1) ) + { + exact = 0; + } + j = j >> 1; + counter++; + } + return counter-1; +} + +void vtkTreeCompositer::CompositeBuffer(vtkDataArray *pBuf, + vtkFloatArray *zBuf, + vtkDataArray *pTmp, + vtkFloatArray *zTmp) +{ + int myId = this->Controller->GetLocalProcessId(); + int numProcs = this->NumberOfProcesses; + int totalPixels; + int pSize, zSize; + int i, id; + int numComp = pBuf->GetNumberOfComponents(); + int exactLog; + int logProcs = vtkTCLog2(numProcs,exactLog); + + // not a power of 2 -- need an additional level + if ( !exactLog ) + { + logProcs++; + } + + totalPixels = zBuf->GetNumberOfTuples(); + zSize = totalPixels; + pSize = numComp*totalPixels; + +#ifdef MPIPROALLOC + vtkCommunicator::SetUseCopy(0); +#endif + for (i = 0; i < logProcs; i++) + { + if ((myId % (int)vtkTCPow2(i)) == 0) + { // Find participants + if ((myId % (int)vtkTCPow2(i+1)) < vtkTCPow2(i)) + { + // receivers + id = myId+vtkTCPow2(i); + + // only send or receive if sender or receiver id is valid + // (handles non-power of 2 cases) + if (id < numProcs) + { + this->Controller->Receive(zTmp->GetPointer(0), zSize, id, 99); + if (pTmp->GetDataType() == VTK_UNSIGNED_CHAR) + { + this->Controller->Receive(reinterpret_cast + (pTmp->GetVoidPointer(0)), + pSize, id, 99); + } + else + { + this->Controller->Receive(reinterpret_cast + (pTmp->GetVoidPointer(0)), + pSize, id, 99); + } + + // notice the result is stored as the local data + vtkCompositeImagePair(zBuf, pBuf, zTmp, pTmp); + } + } + else + { + id = myId-vtkTCPow2(i); + if (id < numProcs) + { + this->Controller->Send(zBuf->GetPointer(0), zSize, id, 99); + if (pBuf->GetDataType() == VTK_UNSIGNED_CHAR) + { + this->Controller->Send(reinterpret_cast + (pBuf->GetVoidPointer(0)), + pSize, id, 99); + } + else + { + this->Controller->Send(reinterpret_cast + (pBuf->GetVoidPointer(0)), + pSize, id, 99); + } + } + } + } + } + +#ifdef MPIPROALLOC + vtkCommunicator::SetUseCopy(1); +#endif + +} + +void vtkTreeCompositer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + + + diff --git a/Parallel/vtkTreeCompositer.h b/Parallel/vtkTreeCompositer.h new file mode 100644 index 0000000..db09336 --- /dev/null +++ b/Parallel/vtkTreeCompositer.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTreeCompositer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// This software and ancillary information known as vtk_ext (and +// herein called "SOFTWARE") is made available under the terms +// described below. The SOFTWARE has been approved for release with +// associated LA_CC Number 99-44, granted by Los Alamos National +// Laboratory in July 1999. +// +// Unless otherwise indicated, this SOFTWARE has been authored by an +// employee or employees of the University of California, operator of +// the Los Alamos National Laboratory under Contract No. W-7405-ENG-36 +// with the United States Department of Energy. +// +// The United States Government has rights to use, reproduce, and +// distribute this SOFTWARE. The public may copy, distribute, prepare +// derivative works and publicly display this SOFTWARE without charge, +// provided that this Notice and any statement of authorship are +// reproduced on all copies. +// +// Neither the U. S. Government, the University of California, nor the +// Advanced Computing Laboratory makes any warranty, either express or +// implied, nor assumes any liability or responsibility for the use of +// this SOFTWARE. +// +// If SOFTWARE is modified to produce derivative works, such modified +// SOFTWARE should be clearly marked, so as not to confuse it with the +// version available from Los Alamos National Laboratory. + + +// .NAME vtkTreeCompositer - Implements tree based compositing. +// +// .SECTION Description +// vtkTreeCompositer operates in multiple processes. Each compositer has +// a render window. They use a vtkMultiProcessController to communicate +// the color and depth buffer to process 0's render window. +// It will not handle transparency well. +// +// .SECTION See Also +// vtkCompositeManager + +#ifndef __vtkTreeCompositer_h +#define __vtkTreeCompositer_h + +#include "vtkCompositer.h" + + +class VTK_PARALLEL_EXPORT vtkTreeCompositer : public vtkCompositer +{ +public: + static vtkTreeCompositer *New(); + vtkTypeRevisionMacro(vtkTreeCompositer,vtkCompositer); + void PrintSelf(ostream& os, vtkIndent indent); + + virtual void CompositeBuffer(vtkDataArray *pBuf, vtkFloatArray *zBuf, + vtkDataArray *pTmp, vtkFloatArray *zTmp); + +protected: + vtkTreeCompositer(); + ~vtkTreeCompositer(); + +private: + vtkTreeCompositer(const vtkTreeCompositer&); // Not implemented + void operator=(const vtkTreeCompositer&); // Not implemented +}; + +#endif diff --git a/README.html b/README.html new file mode 100644 index 0000000..f051576 --- /dev/null +++ b/README.html @@ -0,0 +1,602 @@ + +

+VTK README + + + + + + + + + + +
+ + +

+
+Welcome To The Visualization Toolkit +

+ +
+

Introduction

+ +VTK is an open-source software system for image processing, 3D graphics, +volume rendering and visualization. VTK includes many advanced algorithms +(e.g., surface reconstruction, implicit modelling, decimation) and rendering +techniques (e.g., hardware-accelerated volume rendering, LOD control).

+ +VTK is used by academicians for teaching and research; by government research +institutions such as Los Alamos National Lab in the US or CINECA in Italy; and +by many commercial firms who use VTK to build or extend products.

+ +The origin of VTK is with the textbook "The Visualization Toolkit, an +Object-Oriented Approach to 3D Graphics" originally published by +Prentice Hall and now published by Kitware, Inc. (Third Edition +ISBN 1-930934-07-6). VTK has grown (since its initial release in 1994) +to a world-wide user base in the commercial, academic, and research +communities.

+ +This README is written for VTK version 5.0 and greater. For more information, +additional resources, and the FAQ see the web page at +http://www.vtk.org

+ +


+

Copyright Notice

+ +VTK has a generous open-source copyright modelled after the BSD license. Yes, +you can use VTK in commercial products. The complete text of the +copyright follows. + +
+Copyright (c) 1993-2005 Ken Martin, Will Schroeder, Bill Lorensen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
+   of any contributors may be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+ * Modified source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ +
+

Organization

+The VTK source code repository is organized into four major sections. +
    + +
  • The toolkit source code is found in the following directories + next to this README. In some cases an additional README.html + file may be found in the named directory. Please see these for + more information. +
      +
    • Common- Core classes commonly used by other kits +
    • Filtering- Data pipeline implementation superclasses +
    • Rendering- Classes used to render a scene (surface primitives) +
    • Graphics- Filters that process 3D data +
    • Imaging- Specialized image processing filters (2D & 3D) +
    • IO- Classes for reading and writing data +
    • VolumeRendering- Classes for rendering volume data +
    • Hybrid- Complex classes that depend on imaging and graphics +
    • Widgets- Classes for interacting with the objects in the scene +
    • Parallel- Parallel processing support such as MPI +
    • GenericFiltering- Part of an adaptor framework + supporting integration of VTK with external systems +
    +
  • +

  • Examples that are reasonably well documented are found in the + VTK/Examples directory. You may wish to start with the examples + found in the Tutorial directory.

  • +
  • The Utilities directory includes things like jpeg, png, + and zlib source code. This code is used by VTK in various ways + (reading/writing data, etc.)

  • +
  • The Wrapping directory contains code related to VTK's automated + wrapping process. The wrapping process automatically generates + Tcl, Python, and/or Java bindings depending on how the build + process is configured.

  • +
+ +There are hundreds of testing examples located in the Testing/ directory +under each source code directory (e.g., Graphics/Testing). These are +undocumented tests but can be helpful in some cases.

+ + +


+

Documentation

+ +The ideal way to learn about the software is from two books: +The Visualization Toolkit, An Object-Oriented Approach to 3D Graphics +and The VTK User's Guide both published by Kitware, Inc. (Note: +The Visualization Toolkit was originally published by Prentice-Hall, +the third edition is published by Kitware.) +You may order the books from the following locations (Amazon.com also +carries the books.) +
+  The Visualization Toolkit, An Object-Oriented Approach to 3D Graphics (Third Edition)
+  by Will Schroeder, Ken Martin and Bill Lorensen.
+  Kitware, Inc.,
+  ISBN 1-930934-07-6
+  http://www.kitware.com/products/vtktextbook.html
+
+  The VTK User's Guide (VTK 4.2 Edition)
+  Kitware, Inc.,
+  ISBN 1-930934-08-4
+  http://www.kitware.com/products/vtkguide.html
+
+ +On-line Doxygen man pages are also available at + +http://www.vtk.org/doc/nightly/html/

+ +


+

Compilation

+ +
+The Visualization Toolkit can be built on UNIX, PC (Windows +95/98/NT/2000/XP), and Mac OSX Jaguar (or greater) systems. VTK uses +CMake to generate its build system. +To build VTK one must first install CMake version 2.0 or higher. +CMake may be downloaded from http://www.cmake.org/HTML/Download.html. +The instructions below cover the basics of running CMake for VTK under +the assumption that CMake is already installed. See the CMake web +page for details on + intalling and + running CMake. +

+Compiling VTK requires a complete VTK source tree. Running VTK tests +requires a complete VTK data tree. Now is the time to extract the +source and data archives if one has not done so already. These +instructions assume there is a directory "VTK" containing +the source code and optionally a sibling direcory +"VTKData" containing the data. +

+ +

Building with CMake

+ +CMake must be run to generate a build system for VTK. The build +system may be placed either in the VTK source tree (an +in-source build) or in a separate binary tree (an +out-of-source build). We strongly encourage use of +out-of-source builds because they make it easy to have multiple builds +with different configurations sharing the same source tree. Once a +single in-source build has been created it is the only build tree that +can be associated with that source tree. A source tree may not be +used both for an in-source build and an out-of-source build, but any +number of out-of-source builds may share a source tree that does not +have an in-source build. Having multiple out-of-source builds is +particularly useful for installing VTK on multiple architectures using +a single source tree on a shared disk. +

+CMake provides both a command-line tool and interactive interfaces. +Advanced users may wish to use the command-line tool but here we +document the CMake interactive interface for each platform: + +

+ +

Configuration Options in CMake

+ +VTK is a large toolkit providing a wide variety of functionality. +Several configuration options are available to customize the VTK build +system. These options are configured through an interactive CMake +interface as described above. Note that not +all options are available on all platforms, and some options are +available only when other options are set to a particular value. +

+The interactive CMake interface provides brief documentation for every +option. Some options have more meaning than can be described in one +sentence, so additional documentation is provided here: + +

+

    +
  • BUILD_SHARED_LIBS
    +

    + Sets whether the compiled VTK libraries will be shared libraries + or static libraries. When linking executables against static + libraries the needed symbols will be copied from the libraries + into the executables enabling them to run without access to the + original libraries. When linking executables against shared + libraries references to the symbols are placed into the + executables. This has the advantage that many executables can + share a large library without producing many copies of its code. +

    +

    + Shared libraries have the disadvantage that they must be found at + runtime in order for an executable to run. Each operating system + supporting shared libraries has a component known as the + dynamic loader. This component is responsible for finding + the shared libraries needed by an executable when it is run. In + order to run VTK executables from the build tree when using shared + libraries one may need to help the dynamic loader find the + libraries (usually the bin subdirectory of the build tree). +

    +

    + On Windows, the dynamic loader will look for shared libraries in + the directory containing the executable, in directories listed in + the PATH environment variable, and in some system directories. + Since VTK places all of its executables and libraries in the same + directory nothing needs to be set to get them to run. However, + when one builds outside projects against VTK the PATH environment + variable must be set to point at the directory containing the VTK + shared libraries. +

    +

    + On UNIX-style platforms, the dynamic loader will use an + environment variable such as LD_LIBRARY_PATH (Linux and many UNIX + systems) or DYLD_LIBRARY_PATH (Mac OSX) to look for shared + libraries. In order to run VTK executables from the build tree + one must set the appropriate environment variable to point at the + directory containing the VTK shared libraries (unless + VTK_USE_RPATH is ON, see below). The same environment setting + must be used for running outside projects build against the shared + VTK libraries. +

    +
  • + +
  • VTK_USE_RPATH
    +

    + This option is available on non-Windows platforms when the + BUILD_SHARED_LIBS option is set to ON. It enables/disables the + use of the rpath (runtime-path) feature available on most + UNIX-style platforms. If this option is enabled VTK libraries and + executables will be linked with an rpath pointing at the location + in the build tree containing them (usually the bin subdirectory). + This allows them to run from the build tree without setting any + environment variables to help the dynamic loader find the needed + shared libraries. +

    +

    + Warning: enabling VTK_USE_RPATH DISABLES THE INSTALL TARGET + so that the build cannot be used to install VTK! This is + necessary because the installed executables and libraries would + contain references back to the build tree. Running them would + load libraries from the build tree, which may have been updated or + built with an incompatible configuration since the last + installation. VTK release versions set this option to OFF by + default so that it is easy to build and install VTK from a source + distribution. VTK development versions set this option to ON by + default so that dashboard builds and developers (which typically + have many VTK build trees) can run without setting any environment + variables for the dynamic loader. +

    +
  • + +
  • VTK_WRAP_TCL
    + +

    + Enable/Disable automatic generation of VTK bindings in the Tcl + language. In order to build the Tcl-based VTK interpreter one + will need to have Tcl and Tk version 8.2 or newer. Look to + + http://www.tcl.tk + + for information about getting Tcl and Tk. To turn on Tcl wrapping, + set VTK_WRAP_TCL to ON during the configuration process. One may + then have to set the values for Tcl/Tk include directories and + libraries during the next CMake configure iteration. If there is + more than one version of Tcl installed on the computer, make sure + all the TCL_* and TK_* configuration options are set consistently + to use the proper version. This is especially important when + Cygwin is installed because the Cygwin Tcl will not work for a + native Windows VTK build and a Windows Tcl will not work for a + Cygwin VTK build. When building the Tcl/Tk wrappers on Cygwin one + must also install the Cygwin sources for Tcl/Tk and set + TK_XLIB_PATH to "/usr/src/tcltk-20030901-1/tk/xlib" or the + corresponding directory for one's Cygwin Tcl version. See + + Wrapping/Tcl/README + + for details on using the Tcl wrappers once they are built. +

    +
  • + +
  • VTK_WRAP_PYTHON
    + +

    + Enable/Disable automatic generation of VTK bindings in the Python + language. In order to build the Python-based VTK interpreter one + will need to have Python installed. Look to + + http://www.python.org + + for information about getting Python. To turn on Python wrapping, + set VTK_WRAP_PYTHON and BUILD_SHARED_LIBS to ON during the + configuration process. One may then have to set the values for + Python include directories and libraries during the next CMake + configure iteration. If there is more than one version of Python + installed on the computer, make sure all the PYTHON_* + configuration options are set consistently to use the proper + version. This is especially important when Cygwin is installed + because the Cygwin Python will not work for a native Windows VTK + build and a Windows Python will not work for a Cygwin VTK build. + In order to use Tkinter with VTK-Python make sure that the Tcl/Tk + libraries that are set correspond to the same version used by + Tkinter. +

    +

    + Note that the VTK-Python modules are now installed by default via + 'make install', which is a change from previous VTK versions. The + automatic python module installation is highly configurable. The + Wrapping/Python/README.txt + file documents the installation procedure and the VTK-Python + modules. +

    +
  • + +
  • CMAKE_INSTALL_PREFIX
    +

    + When VTK is installed all files are + placed in a directory structure rooted at the directory specified + by CMAKE_INSTALL_PREFIX. +

    +
  • +
+ +
+

Installation

+ +Installing VTK from a source distribution requires first that it be +compiled in a build tree. See the compilation section above for details. Once +VTK has been compiled in a build tree one may build the install +target to actually put VTK in an installation tree. If VTK was built +using a CMake Makefile generator then this is done by running "make +install" from the top of the build tree. If VTK was built using a +CMake project file generator (such as Visual Studio), then building +the INSTALL project from inside the IDE will install VTK. The +installation process will install all files in a directory structure +rooted at the directory specified by CMAKE_INSTALL_PREFIX. + +
+ +
+

Common Problems

+
    +
  • Strange compile errors on UNIX, typically involving system + headers and types. Make sure that you specify the environment + variables CC and CXX prior to running CMake. If you have + already run CMake you must create a fresh build-tree and start + again. If you ran CMake in the source tree then you must delete + the source tree, re-extract the sources, and start again. +
  • Errors on Tcl or Tk include files or libraries. Make sure that + you set the TCL_* and TK_* configuration variables to the + correct location when running CMake. +
  • Link errors on Windows platforms. Make sure that the swap space is + at least 300 MByte. +
  • Link error with borland: TCL82.LIB contains invalid OMF record, + type 0x21 (possibly COFF). You have to convert Tcl libraires + from coff to omf with the Borland utilitiy coff2omf. Once you + have created OMF versions, re-run cmake to tell it where the Borland + versions of Tcl and Tk are located. Also, make sure that you are using + Tcl/Tk 8.3.2. +
+ +
+

Getting Data and Test Images

+ +Many of the examples require data. There are two ways to get data. The +first is to download the file VTKData.tgz. The second is to access the +data via CVS checkout. The CVS checkout also includes many test images +used by the testing process (see http://public.kitware.com/dashboard.php). +These can be used if you wish to test VTK or submit testing dashboards. +The VTKData.tgz contains only data in compressed form is therefore can +be obtained much faster. + +
+  1) Download the data at ftp://public.kitware.com/pub/vtk/VTKData.tgz
+
+  2) Checkout the data from CVS using the folling commands:
+     cvs -d :pserver:anoncvs@www.vtk.org:/cvsroot/VTK login
+        (there is no password...just press enter)
+     cvs -d :pserver:anoncvs@www.vtk.org:/cvsroot/VTK checkout VTKData
+
+ +
+

Running VTK

+ +Many C++ examples will be compiled if BUILD_TESTING and/or +BUILD_EXAMPLES are enabled in CMake. To run these C++ examples just +type their name. (They will be found in the binary build directory.) +If you have built shared libraries, make sure the PATH environment +variable (Windows) or the LD_LIBRARY_PATH (Unix) point to the shared +libraries (see above documentation of the BUILD_SHARED_LIBS for +details). + +If you have enabled Tcl wrapping, you will want to set TCLLIBPATH to point to +the VTK/Wrapping/Tcl directory and check the instructions located in the Wrapping/Tcl/README file. You will then run +the VTK executable found in the bin directory where the code was +compiled. Assuming that the executable VTK is in your path, or has been +aliased, you would type: +
+  vtk mace.tcl 
+
+Note that most Tcl scripts allow you to type "u" in the render window to +obtain an interpreter. You can use the interpreter to modify the application +at run-time. + +

+If you have enabled Python Wrapping you should read the instructions +located in the Wrapping/Python/README.txt file. +

+ +
+

Writing Your Own Class

There are several ways to +extend VTK. The simplest way is, in your own code, create classes that +inherit from the appropriate VTK classes. Please see the +vtkLocal example +for instructions to build your classes outside VTK. + +
+

Getting Help / Mailing List

+For general information go to the VTK web site +http://www.vtk.org +

+If you run into problems, your best bet is to join the VTK mailing list. +Visit +http://www.vtk.org/mailman/listinfo/vtkusers to join the list. +

+Commercial support contracts are available from Kitware at + +http://www.kitware.com/products/vtksupport.html. +

+Kitware also provides consulting services. Read more at + +http://www.kitware.com/products/consult.html. +

+Training is also available from Kitware. See + +http://www.kitware.com/products/vtktrain.html. + + + diff --git a/Rendering/CMakeLists.txt b/Rendering/CMakeLists.txt new file mode 100644 index 0000000..a610cd6 --- /dev/null +++ b/Rendering/CMakeLists.txt @@ -0,0 +1,439 @@ +SET(KIT Rendering) +SET(UKIT RENDERING) +SET(KIT_TCL_LIBS vtkGraphicsTCL vtkImagingTCL ${VTK_TK_LIBRARIES}) +SET(KIT_PYTHON_LIBS vtkGraphicsPythonD vtkImagingPythonD) +SET(KIT_JAVA_LIBS vtkGraphicsJava vtkImagingJava) +IF (JAVA_AWT_LIBRARY) + SET(KIT_JAVA_LIBS ${KIT_JAVA_LIBS} ${JAVA_AWT_LIBRARY}) +ENDIF (JAVA_AWT_LIBRARY) +SET(KIT_LIBS vtkGraphics vtkImaging vtkIO + vtkftgl + ${VTK_FREETYPE_LIBRARIES} +) + +# Fix for bug#1026 moved out of the common section. This should be +# changed to add the flag only in the right places (CMAKE_CXX_FLAGS?). +IF(APPLE AND VTK_WRAP_JAVA) + ADD_DEFINITIONS("-ObjC++") +ENDIF(APPLE AND VTK_WRAP_JAVA) + +SET( Kit_SRCS +vtkAbstractMapper3D.cxx +vtkAbstractVolumeMapper.cxx +vtkAbstractPicker.cxx +vtkAbstractPropPicker.cxx +vtkActor.cxx +vtkActorCollection.cxx +vtkAssembly.cxx +vtkAxisActor2D.cxx +vtkCamera.cxx +vtkCameraInterpolator.cxx +vtkCellPicker.cxx +vtkCuller.cxx +vtkCullerCollection.cxx +vtkDataSetMapper.cxx +vtkExporter.cxx +vtkFollower.cxx +vtkFrustumCoverageCuller.cxx +vtkGenericRenderWindowInteractor.cxx +vtkGraphicsFactory.cxx +vtkHierarchicalPolyDataMapper.cxx +vtkIVExporter.cxx +vtkImageActor.cxx +vtkImageMapper.cxx +vtkImageViewer.cxx +vtkImageViewer2.cxx +vtkImagingFactory.cxx +vtkImporter.cxx +vtkInteractorEventRecorder.cxx +vtkInteractorObserver.cxx +vtkInteractorStyle.cxx +vtkInteractorStyleFlight.cxx +vtkInteractorStyleImage.cxx +vtkInteractorStyleJoystickActor.cxx +vtkInteractorStyleJoystickCamera.cxx +vtkInteractorStyleRubberBandZoom.cxx +vtkInteractorStyleSwitch.cxx +vtkInteractorStyleTerrain.cxx +vtkInteractorStyleTrackball.cxx +vtkInteractorStyleTrackballActor.cxx +vtkInteractorStyleTrackballCamera.cxx +vtkInteractorStyleUnicam.cxx +vtkInteractorStyleUser.cxx +vtkLODActor.cxx +vtkLODProp3D.cxx +vtkLabeledDataMapper.cxx +vtkLight.cxx +vtkLightCollection.cxx +vtkLightKit.cxx +vtkMapper.cxx +vtkMapperCollection.cxx +vtkOBJExporter.cxx +vtkOOGLExporter.cxx +vtkParallelCoordinatesActor.cxx +vtkPicker.cxx +vtkPointPicker.cxx +vtkPolyDataMapper.cxx +vtkPolyDataMapper2D.cxx +vtkProp3D.cxx +vtkProp3DCollection.cxx +vtkPropPicker.cxx +vtkProperty.cxx +vtkQuaternionInterpolator.cxx +vtkRenderWindow.cxx +vtkRenderWindowCollection.cxx +vtkRenderWindowInteractor.cxx +vtkRenderer.cxx +vtkRendererCollection.cxx +vtkRendererSource.cxx +vtkScalarBarActor.cxx +vtkScaledTextActor.cxx +vtkSelectVisiblePoints.cxx +vtkTesting.cxx +vtkTextActor.cxx +# vtkTextActor2D.cxx +vtkTextActor3D.cxx +vtkTextMapper.cxx +vtkTextProperty.cxx +vtkTexture.cxx +vtkTransformInterpolator.cxx +vtkTupleInterpolator.cxx +vtkVRMLExporter.cxx +vtkVolume.cxx +vtkVolumeCollection.cxx +vtkVolumeProperty.cxx +vtkWindowToImageFilter.cxx +vtkWorldPointPicker.cxx +) + +IF(VTK_USE_GL2PS) + SET(Kit_SRCS ${Kit_SRCS} vtkGL2PSExporter.cxx) + SET(Kit_GL2PS_SRCS ${VTK_SOURCE_DIR}/Utilities/gl2ps/gl2ps.c) + ADD_DEFINITIONS(-DGL2PS_HAVE_ZLIB) +ENDIF(VTK_USE_GL2PS) + +SET( KitOpenGL_SRCS + vtkOpenGLActor.cxx + vtkOpenGLCamera.cxx + vtkOpenGLExtensionManager.cxx + vtkOpenGLImageActor.cxx + vtkOpenGLImageMapper.cxx + vtkOpenGLLight.cxx + vtkOpenGLPolyDataMapper.cxx + vtkOpenGLPolyDataMapper2D.cxx + vtkOpenGLProperty.cxx + vtkOpenGLRenderWindow.cxx + vtkOpenGLRenderer.cxx + vtkOpenGLTexture.cxx + ) + + +SET_SOURCE_FILES_PROPERTIES( +vtkAbstractMapper3D +vtkAbstractVolumeMapper +vtkAbstractPicker +vtkAbstractPropPicker +vtkCuller +vtkExporter +vtkImporter +vtkInteractorObserver +vtkMapper +vtkOpenGLRenderWindow +vtkProp3D +ABSTRACT +) + +# Freetype stuff + +SET(Kit_SRCS ${Kit_SRCS} + vtkFreeTypeUtilities.cxx +) +SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkOpenGLFreeTypeTextMapper.cxx +) +SET_SOURCE_FILES_PROPERTIES( + vtkFreeTypeUtilities + WRAP_EXCLUDE +) +SET(Kit_FT_SRCS + fonts/face_arial.cxx + fonts/face_arial_bold.cxx + fonts/face_arial_bold_italic.cxx + fonts/face_arial_italic.cxx + fonts/face_courier.cxx + fonts/face_courier_bold.cxx + fonts/face_courier_bold_italic.cxx + fonts/face_courier_italic.cxx + fonts/face_times.cxx + fonts/face_times_bold.cxx + fonts/face_times_bold_italic.cxx + fonts/face_times_italic.cxx +) + +IF(VTK_USE_X) + SET( Kit_SRCS ${Kit_SRCS} + vtkXRenderWindowInteractor.cxx) +ENDIF(VTK_USE_X) + +# OpenGL extensions stuff. + +# Parse the extensions into vtkgl.h/vtkgl.cxx. +ADD_CUSTOM_COMMAND( + OUTPUT ${VTK_BINARY_DIR}/Rendering/vtkgl.cxx + COMMAND ${VTK_PARSEOGLEXT_EXE} + ARGS ${VTK_BINARY_DIR}/Rendering ${VTK_GLEXT_FILE} ${VTK_GLXEXT_FILE} ${VTK_WGLEXT_FILE} + DEPENDS ${VTK_GLEXT_FILE} ${VTK_GLXEXT_FILE} ${VTK_WGLEXT_FILE} ${VTK_PARSEOGLEXT_EXE} + ) + +SET_SOURCE_FILES_PROPERTIES(vtkOpenGLExtensionManager.cxx + PROPERTIES OBJECT_DEPENDS ${VTK_BINARY_DIR}/Rendering/vtkgl.cxx) + +SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + ${VTK_BINARY_DIR}/Rendering/vtkgl.cxx +) + +SET_SOURCE_FILES_PROPERTIES( + # OK, so it's not abstract, but this stops the instantiator + # from trying to call vtkRenderingInstantiatorvtkglNew(): + ${VTK_BINARY_DIR}/Rendering/vtkgl.cxx + ABSTRACT + ) + +SET_SOURCE_FILES_PROPERTIES( + ${VTK_BINARY_DIR}/Rendering/vtkgl.cxx + GENERATED + ) + +SET_SOURCE_FILES_PROPERTIES( + ${VTK_BINARY_DIR}/Rendering/vtkgl.cxx + WRAP_EXCLUDE + ) + +# Configuration for vtkOpenGLExtensionManager +IF (WIN32) + SET(VTK_USE_WGL_GET_PROC_ADDRESS 1) +ELSE (WIN32) + IF (APPLE) + SET(VTK_USE_APPLE_LOADER 1) + ELSE (APPLE) + INCLUDE(${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake) + SET(VTK_SAVE_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") + SET(CMAKE_REQUIRED_LIBRARIES + ${OPENGL_LIBRARIES} + ${CMAKE_THREAD_LIBS} + ${CMAKE_REQUIRED_LIBRARIES} + -lm + ) + CHECK_FUNCTION_EXISTS(glXGetProcAddressARB VTK_USE_GLX_GET_PROC_ADDRESS_ARB) + IF (VTK_USE_GLX_GET_PROC_ADDRESS_ARB) + IF (NOT VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS_TESTED) + MESSAGE(STATUS "Looking for glXGetProcAddressARB in GL/glx.h") + TRY_COMPILE(VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/CheckglXGetProcAddressARB.cxx + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}" + OUTPUT_VARIABLE OUTPUT) + MESSAGE(STATUS "Looking for glXGetProcAddressARB in GL/glx.h - ${VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS}") + FILE(APPEND ${CMAKE_BINARY_DIR}/CMakeOutput.log + "Determining if glXGetProcAddressARB exists in GL/glx.h ${VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS} with the following output:\n" + "${OUTPUT}\n\n") + SET(VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS_TESTED 1 + CACHE INTERNAL "Already set VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS") + ENDIF (NOT VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS_TESTED) + IF (NOT VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS) + SET(VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE 1) + ENDIF (NOT VTK_GLX_GET_PROC_ADDRESS_ARB_PROTOTYPE_EXISTS) + ELSE (VTK_USE_GLX_GET_PROC_ADDRESS_ARB) + CHECK_FUNCTION_EXISTS(glXGetProcAddress VTK_USE_GLX_GET_PROC_ADDRESS) + IF (NOT VTK_USE_GLX_GET_PROC_ADDRESS) +# SET(VTK_USE_VTK_DYNAMIC_LOADER 1) + MESSAGE(STATUS "Could not find extension loader. Extensions disabled.") + SET(VTK_NO_EXTENSION_LOADING 1) + ENDIF (NOT VTK_USE_GLX_GET_PROC_ADDRESS) + ENDIF (VTK_USE_GLX_GET_PROC_ADDRESS_ARB) + SET(CMAKE_REQUIRED_LIBRARIES "${VTK_SAVE_CMAKE_REQUIRED_LIBRARIES}") + ENDIF (APPLE) +ENDIF (WIN32) +CONFIGURE_FILE( + ${VTK_SOURCE_DIR}/Rendering/vtkOpenGLExtensionManagerConfigure.h.in + ${VTK_BINARY_DIR}/Rendering/vtkOpenGLExtensionManagerConfigure.h) + +# Build a list of libraries to link to vtkRendering. + +IF(VTK_USE_GL2PS) + SET(KIT_LIBS ${KIT_LIBS} ${VTK_ZLIB_LIBRARIES}) +ENDIF(VTK_USE_GL2PS) + +IF (WIN32) + IF(VTK_USE_X) + IF (OPENGL_gl_LIBRARY) + SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkXOpenGLRenderWindow.cxx) + SET (KIT_LIBS ${KIT_LIBS} ${OPENGL_gl_LIBRARY} ) + ENDIF (OPENGL_gl_LIBRARY) + ELSE(VTK_USE_X) + SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkWin32OpenGLRenderWindow.cxx + vtkWin32RenderWindowInteractor.cxx) + SET (KIT_LIBS ${KIT_LIBS} ${OPENGL_gl_LIBRARY} ) + ENDIF(VTK_USE_X) +ELSE (WIN32) + IF (APPLE) + IF(VTK_USE_COCOA) + SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkCocoaRenderWindowInteractor.mm + vtkCocoaRenderWindow.mm + vtkCocoaWindow.mm + vtkCocoaGLView.mm) + SET_SOURCE_FILES_PROPERTIES(vtkCocoaGLView vtkCocoaWindow WRAP_EXCLUDE) + SET (KIT_LIBS ${KIT_LIBS} ${OPENGL_gl_LIBRARY} "-framework Cocoa") + ENDIF(VTK_USE_COCOA) + IF(VTK_USE_CARBON) + SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkCarbonRenderWindowInteractor.cxx + vtkCarbonRenderWindow.cxx) + SET (KIT_LIBS ${KIT_LIBS} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} "-framework Carbon") + ENDIF(VTK_USE_CARBON) + IF(VTK_USE_X) + IF (OPENGL_gl_LIBRARY) + SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkXOpenGLRenderWindow.cxx) + SET (KIT_LIBS ${KIT_LIBS} "-lGL") + ENDIF (OPENGL_gl_LIBRARY) + ENDIF(VTK_USE_X) + ELSE (APPLE) + IF (OPENGL_gl_LIBRARY) + SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkXOpenGLRenderWindow.cxx) + SET (KIT_LIBS ${KIT_LIBS} ${OPENGL_gl_LIBRARY} ) + ENDIF (OPENGL_gl_LIBRARY) + ENDIF (APPLE) +ENDIF (WIN32) + +IF (VTK_USE_MANGLED_MESA) + IF (MANGLED_MESA_LIBRARY) + SET ( KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkMesaActor.cxx + vtkMesaCamera.cxx + vtkMesaImageActor.cxx + vtkMesaImageMapper.cxx + vtkMesaLight.cxx + vtkMesaPolyDataMapper.cxx + vtkMesaPolyDataMapper2D.cxx + vtkMesaProperty.cxx + vtkMesaRenderWindow.cxx + vtkMesaRenderer.cxx + vtkMesaTexture.cxx + vtkXMesaRenderWindow.cxx + ) + SET(KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkMesaFreeTypeTextMapper.cxx + ) + SET_SOURCE_FILES_PROPERTIES(vtkMesaRenderWindow ABSTRACT) + SET (KIT_LIBS ${KIT_LIBS} ${MANGLED_MESA_LIBRARY}) + IF(MANGLED_OSMESA_LIBRARY) + SET( KIT_LIBS ${KIT_LIBS} ${MANGLED_OSMESA_LIBRARY} ) + ENDIF(MANGLED_OSMESA_LIBRARY) + ENDIF (MANGLED_MESA_LIBRARY) +ELSE (VTK_USE_MANGLED_MESA) + IF(VTK_OPENGL_HAS_OSMESA) + IF (OSMESA_LIBRARY) + SET(KIT_LIBS ${KIT_LIBS} ${OSMESA_LIBRARY}) + ENDIF (OSMESA_LIBRARY) + ENDIF(VTK_OPENGL_HAS_OSMESA) +ENDIF(VTK_USE_MANGLED_MESA) +SET(Kit_SRCS ${Kit_SRCS} ${KitOpenGL_SRCS}) +SET(Kit_EXTRA_SRCS ${Kit_FT_SRCS}) + +IF(VTK_USE_GL2PS) +SET(Kit_EXTRA_SRCS ${Kit_EXTRA_SRCS} ${Kit_GL2PS_SRCS}) +ENDIF(VTK_USE_GL2PS) + +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(Kit_TCL_EXTRA_CMDS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +IF (TK_LIBRARY AND VTK_USE_TK) + SET(VTK_GENERATE_TK_INTERNALS 1) +ENDIF (TK_LIBRARY AND VTK_USE_TK) +IF(VTK_GENERATE_TK_INTERNALS) + SET (HAVE_LIMITS_H ${CMAKE_HAVE_LIMITS_H}) + SET (HAVE_UNISTD_H ${CMAKE_HAVE_UNISTD_H}) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/vtkTkInternals.h.in + ${CMAKE_CURRENT_BINARY_DIR}/vtkTkInternals.h) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} + FILES ${CMAKE_CURRENT_BINARY_DIR}/vtkTkInternals.h) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) +ENDIF (VTK_GENERATE_TK_INTERNALS) + +IF (VTK_WRAP_TCL) + IF(VTK_USE_TK) + SET(KitTCL_SRCS + vtkTkRenderWidget.cxx + vtkTkImageViewerWidget.cxx) + + # Use special interactor for X and Tk. + IF(VTK_USE_X) + SET(KitTCL_SRCS ${KitTCL_SRCS} + vtkXRenderWindowTclInteractor.cxx) + ENDIF(VTK_USE_X) + SET(Kit_TCL_EXTRA_CMDS + vtkTkRenderWidget + vtkTkImageViewerWidget) + ENDIF (VTK_USE_TK) +ENDIF (VTK_WRAP_TCL) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtkOpenGL + ) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +IF (VTK_WRAP_PYTHON) + IF(VTK_USE_TK) + IF (TK_LIBRARY) + SET(RenderingPythonTkWidgets_SRCS + vtkTkWidgetsInit.cxx + vtkTkRenderWidgetPython.cxx + vtkTkImageViewerWidgetPython.cxx + ) + ADD_LIBRARY(vtkRenderingPythonTkWidgets SHARED + ${RenderingPythonTkWidgets_SRCS}) + TARGET_LINK_LIBRARIES (vtkRenderingPythonTkWidgets + vtk${KIT} + ${VTK_TK_LIBRARIES}) + + # Apply user-defined properties to the library target. + IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkRenderingPythonTkWidgets PROPERTIES + ${VTK_LIBRARY_PROPERTIES}) + ENDIF(VTK_LIBRARY_PROPERTIES) + + IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkRenderingPythonTkWidgets) + ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) + ENDIF (TK_LIBRARY) + ENDIF(VTK_USE_TK) +ENDIF (VTK_WRAP_PYTHON) + +IF(VTK_USE_X) + TARGET_LINK_LIBRARIES(vtk${KIT} -lXt ${X11_LIBRARIES}) +ENDIF(VTK_USE_X) + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} FILES + ${VTK_SOURCE_DIR}/${KIT}/Testing/Cxx/vtkRegressionTestImage.h) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Rendering/CheckglXGetProcAddressARB.cxx b/Rendering/CheckglXGetProcAddressARB.cxx new file mode 100644 index 0000000..9860c7f --- /dev/null +++ b/Rendering/CheckglXGetProcAddressARB.cxx @@ -0,0 +1,36 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: CheckglXGetProcAddressARB.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + + Copyright 2005 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +// This is just a test program so that CMake can determine if +// glXGetProcAddressARB needs to be declared. + +#include + +int main(int, char **) +{ + void (*FuncPointer)(void); + + FuncPointer = glXGetProcAddressARB((const GLubyte *)"glHelloWorldEXT"); + + return 0; +} + diff --git a/Rendering/Testing/CMakeLists.txt b/Rendering/Testing/CMakeLists.txt new file mode 100644 index 0000000..646ab7c --- /dev/null +++ b/Rendering/Testing/CMakeLists.txt @@ -0,0 +1,29 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Rendering ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Rendering" + VTK_RENDERING_EXPORT + vtkTkRenderWidget.h + vtkTkInternals.h + vtkTkImageViewerWidget.h + vtkCocoaGLView.h + vtkCocoaWindow.h + vtkFreeTypeUtilities.h + vtkgluPickMatrix.h + vtkOpenGL.h + vtkOpenGLStateCache.h + vtkVolumeShearWarpDataStructure.h + vtkgl.h + vtkOpenGLExtensionManagerConfigure.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/Rendering/Testing/Cxx/CMakeLists.txt b/Rendering/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..632458a --- /dev/null +++ b/Rendering/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,69 @@ +SET(KIT Rendering) + +SET(RenderingTests + otherCoordinate.cxx + ) + +SET(RenderingTestsWithArguments) + +IF(VTK_USE_DISPLAY) + # For tests that actually render something + SET(RenderingTestsWithArguments + ${RenderingTestsWithArguments} + LoadOpenGLExtension.cxx + TestOrderedTriangulator.cxx + ) +ENDIF(VTK_USE_DISPLAY) + +CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx + ${RenderingTests};${RenderingTestsWithArguments} + EXTRA_INCLUDE vtkTestDriver.h + ) + +ADD_EXECUTABLE(${KIT}CxxTests ${Tests}) +TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkRendering vtkIO) + + +SET (TestsToRun ${Tests}) +REMOVE (TestsToRun ${KIT}CxxTests.cxx) + +# +# Add all the executables +FOREACH (test ${RenderingTests}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) +ENDFOREACH (test) + +FOREACH (test ${RenderingTestsWithArguments}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + IF (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName} + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/${KIT}/${TName}.png) + ELSE (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) + ENDIF (VTK_DATA_ROOT) +ENDFOREACH(test) + +# +# Add other odd tests or executables +# +FOREACH (exe +# TimeRenderer +# TimeRenderer2 + VTKBenchMark + ) + ADD_EXECUTABLE(${exe} ${exe}.cxx) + TARGET_LINK_LIBRARIES(${exe} vtkRendering vtkIO) + IF (APPLE) + TARGET_LINK_LIBRARIES(${exe} "-framework GLUT") + ENDIF (APPLE) +ENDFOREACH (exe) + + + + + + + diff --git a/Rendering/Testing/Cxx/LoadOpenGLExtension.cxx b/Rendering/Testing/Cxx/LoadOpenGLExtension.cxx new file mode 100644 index 0000000..4a09276 --- /dev/null +++ b/Rendering/Testing/Cxx/LoadOpenGLExtension.cxx @@ -0,0 +1,201 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: LoadOpenGLExtension.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// This code test to make sure vtkOpenGLExtensionManager can properly get +// extension functions that can be used. To do this, we convolve an image +// with a kernel for a Laplacian filter. This requires the use of functions +// defined in OpenGL 1.2, which should be available pretty much everywhere +// but still has functions that can be loaded as extensions. + +#include "vtkConeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkCamera.h" +#include "vtkCallbackCommand.h" +#include "vtkUnsignedCharArray.h" +#include "vtkRegressionTestImage.h" +#include "vtkOpenGLExtensionManager.h" +#include "vtkgl.h" + +vtkUnsignedCharArray *image; + +GLfloat laplacian[3][3] = { + { -0.125f, -0.125f, -0.125f }, + { -0.125f, 1.0f, -0.125f }, + { -0.125f, -0.125f, -0.125f } +}; + +static void ImageCallback(vtkObject *__renwin, unsigned long, void *, void *) +{ + static int inImageCallback = 0; + if (inImageCallback) + { + cout << "*********ImageCallback called recursively?" << endl; + return; + } + inImageCallback = 1; + + cout << "In ImageCallback" << endl; + + vtkRenderWindow *renwin = static_cast(__renwin); + int *size = renwin->GetSize(); + + cout << "Turn on convolution." << endl; + glEnable(vtkgl::CONVOLUTION_2D); + + cout << "Read back image." << endl; + renwin->GetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, 0, image); + + cout << "Turn off convolution." << endl; + glDisable(vtkgl::CONVOLUTION_2D); + + cout << "Write image." << endl; + renwin->SetRGBACharPixelData(0, 0, size[0]-1, size[1]-1, image, 0); + + cout << "Swap buffers." << endl; + renwin->SwapBuffersOn(); + renwin->Frame(); + renwin->SwapBuffersOff(); + + inImageCallback = 0; +} + +int LoadOpenGLExtension(int argc, char *argv[]) +{ + vtkRenderWindow *renwin = vtkRenderWindow::New(); + renwin->SetSize(250, 250); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + renwin->SetInteractor(iren); + + vtkOpenGLExtensionManager *extensions = vtkOpenGLExtensionManager::New(); + extensions->SetRenderWindow(renwin); + + cout << "Query extension." << endl; + if (!extensions->ExtensionSupported("GL_VERSION_1_2")) + { + cout << "Is it possible that your driver does not support OpenGL 1.2?" + << endl << endl;; + int forceLoad = 0; + for (int i = 0; i < argc; i++) + { + if (strcmp("-ForceLoad", argv[i]) == 0) + { + forceLoad = 1; + break; + } + } + if (forceLoad) + { + cout << "Some drivers report supporting only GL 1.1 even though they\n" + << "actually support 1.2 (and probably higher). I'm going to\n" + << "try to load the extension anyway. You will definitely get\n" + << "a warning from vtkOpenGLExtensionManager about it. If GL 1.2\n" + << "really is not supported (or something else is wrong), I will\n" + << "seg fault." << endl << endl; + } + else + { + cout << "Your OpenGL driver reports that it does not support\n" + << "OpenGL 1.2. If this is true, I cannot perform this test.\n" + << "There are a few drivers that report only supporting GL 1.1\n" + << "when they in fact actually support 1.2 (and probably higher).\n" + << "If you think this might be the case, try rerunning this test\n" + << "with the -ForceLoad flag. However, if Opengl 1.2 is really\n" + << "not supported, a seg fault will occur." << endl; + cout << extensions->GetExtensionsString() << endl; + renwin->Delete(); + iren->Delete(); + extensions->Delete(); + return 0; + } + } + cout << extensions->GetExtensionsString() << endl; + cout << "Load extension." << endl; + extensions->LoadExtension("GL_VERSION_1_2"); + extensions->Delete(); + + cout << "Set up pipeline." << endl; + vtkConeSource *cone = vtkConeSource::New(); + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(cone->GetOutputPort()); + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + + vtkRenderer *renderer = vtkRenderer::New(); + renderer->AddActor(actor); + + renwin->AddRenderer(renderer); + + renderer->ResetCamera(); + vtkCamera *camera = renderer->GetActiveCamera(); + camera->Elevation(-45); + + cout << "Do a render without convolution." << endl; + renwin->Render(); + + // Set up a convolution filter. We are using the Laplacian filter, which + // is basically an edge detector. Once vtkgl::CONVOLUTION_2D is enabled, + // the filter will be applied any time an image is transfered in the + // pipeline. + cout << "Set up convolution filter." << endl; + vtkgl::ConvolutionFilter2D(vtkgl::CONVOLUTION_2D, GL_LUMINANCE, 3, 3, + GL_LUMINANCE, GL_FLOAT, laplacian); + vtkgl::ConvolutionParameteri(vtkgl::CONVOLUTION_2D, + vtkgl::CONVOLUTION_BORDER_MODE, + vtkgl::REPLICATE_BORDER); + + image = vtkUnsignedCharArray::New(); + vtkCallbackCommand *cbc = vtkCallbackCommand::New(); + cbc->SetCallback(ImageCallback); + renwin->AddObserver(vtkCommand::EndEvent, cbc); + cbc->Delete(); + + // This is a bit of a hack. The EndEvent on the render window will swap + // the buffers. + renwin->SwapBuffersOff(); + + cout << "Do test render with convolution on." << endl; + renwin->Render(); + int retVal = vtkRegressionTestImage(renwin); + if (retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + cone->Delete(); + mapper->Delete(); + actor->Delete(); + renderer->Delete(); + renwin->Delete(); + iren->Delete(); + image->Delete(); + + return !retVal; +} diff --git a/Rendering/Testing/Cxx/TestOrderedTriangulator.cxx b/Rendering/Testing/Cxx/TestOrderedTriangulator.cxx new file mode 100644 index 0000000..7d8ee9e --- /dev/null +++ b/Rendering/Testing/Cxx/TestOrderedTriangulator.cxx @@ -0,0 +1,262 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestOrderedTriangulator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME Test of vtkOrderedTriangulator +// .SECTION Description +// this program tests the class vtkOrderedTriangulator +// It shows the effect of the delaunay criteria compare to an iso parametric +// case where this criteria does not apply. + +#include "vtkOrderedTriangulator.h" +#include "vtkPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkDataSetMapper.h" +#include "vtkShrinkFilter.h" +#include "vtkRegressionTestImage.h" + +//------------------------------------------------------------------------------ +double para_coord1[24] = { + 0.0, 0.0, 0.0, //0 + 1.0, 0.0, 0.0, //1 + 0.0, 1.0, 0.0, //2 + 0.5, 0.0, 0.0, //3 + 0.0, 0.5, 0.0, //4 + 0.0, 0.0, 1.0, //5 +}; + +double para_coord2[24] = { + 0.0, 1.0, 0.0, //0 + 0.0, 0.0, 0.0, //1 + 1.0, 0.0, 0.0, //2 + 0.0, 0.5, 0.0, //3 + 0.5, 0.5, 0.0, //4 + 0.0, 0.0, 1.0, //5 + }; + +double points[33] = { + 0.0, 0.0, 0.0, //0 + 0.0,-1.0, 0.0, //1 + 1.0, 0.0, 0.0, //2 + 0.0,-0.5, 0.0, //3 + 0.5, 0.0, 0.0, //4 + 0.0, 0.0, 1.0, //5 + }; + +//------------------------------------------------------------------------------ +static void isomorphism(double in[3], double out[3]) +{ + out[0] = in[0]+in[2]; + out[1] = in[0]+in[1]; + out[2] = in[1]+in[2]; +} + +//------------------------------------------------------------------------------ +int TestOrderedTriangulator(int argc, char *argv[]) +{ + int i; + vtkOrderedTriangulator *triangulator1 = vtkOrderedTriangulator::New(); + triangulator1->InitTriangulation(-1.0,1.0, -1.0,1.0, -1.0,1.0, 200); + triangulator1->PreSortedOff(); + + vtkOrderedTriangulator *triangulator2 = vtkOrderedTriangulator::New(); + triangulator2->InitTriangulation(-1.0,1.0, -1.0,1.0, -1.0,1.0, 200); + triangulator2->PreSortedOff(); + + vtkOrderedTriangulator *isotriangulator1 = vtkOrderedTriangulator::New(); + isotriangulator1->InitTriangulation(-1.0,1.0, -1.0,1.0, -1.0,1.0, 200); + isotriangulator1->PreSortedOff(); + + vtkOrderedTriangulator *isotriangulator2 = vtkOrderedTriangulator::New(); + isotriangulator2->InitTriangulation(-1.0,1.0, -1.0,1.0, -1.0,1.0, 200); + isotriangulator2->PreSortedOff(); + + double *p = points; + + vtkPoints *Points = vtkPoints::New(); + Points->SetNumberOfPoints(6); + for(i=0;i<6;i++,p+=3) + { + Points->SetPoint(i, p); + } + + //first case + for(i=0;i<6;i++) + { + double *temp = points + 3*i; + double *temp2 = para_coord1 + 3*i; + triangulator1->InsertPoint(i, temp, temp2, 0); + } + triangulator1->Triangulate(); + + //second case: + for(i=0;i<6;i++) + { + double *temp = points + 3*i; + double *temp2 = para_coord2 + 3*i; + triangulator2->InsertPoint(i, temp, temp2, 0); + } + triangulator2->Triangulate(); + + //We now use isocoordinate and repeat case one and two + //first case + for(i=0;i<6;i++) + { + double *temp = points + 3*i; + double *temp2 = para_coord1 + 3*i; + double iso[3]; + isomorphism(temp2, iso); + isotriangulator1->InsertPoint(i, temp, iso, 0); + } + isotriangulator1->Triangulate(); + + //second case: + for(i=0;i<6;i++) + { + double *temp = points + 3*i; + double *temp2 = para_coord2 + 3*i; + double iso[3]; + isomorphism(temp2, iso); + isotriangulator2->InsertPoint(i, temp, iso, 0); + } + isotriangulator2->Triangulate(); + + vtkUnstructuredGrid *aTetraGrid1 = vtkUnstructuredGrid::New(); + aTetraGrid1->Allocate (1, 1); + triangulator1->AddTetras(0, aTetraGrid1); + aTetraGrid1->SetPoints(Points); + + vtkUnstructuredGrid *aTetraGrid2 = vtkUnstructuredGrid::New(); + aTetraGrid2->Allocate (1, 1); + triangulator2->AddTetras(0, aTetraGrid2); + aTetraGrid2->SetPoints(Points); + + //iso cases: + vtkUnstructuredGrid *isoTetraGrid1 = vtkUnstructuredGrid::New(); + isoTetraGrid1->Allocate (1, 1); + isotriangulator1->AddTetras(0, isoTetraGrid1); + isoTetraGrid1->SetPoints(Points); + + vtkUnstructuredGrid *isoTetraGrid2 = vtkUnstructuredGrid::New(); + isoTetraGrid2->Allocate (1, 1); + isotriangulator2->AddTetras(0, isoTetraGrid2); + isoTetraGrid2->SetPoints(Points); + + //First tets: + vtkShrinkFilter *shrink1 = vtkShrinkFilter::New(); + shrink1->SetInput( aTetraGrid1 ); + shrink1->SetShrinkFactor( 0.7 ); + + vtkDataSetMapper *aTetraMapper1 = vtkDataSetMapper::New(); + aTetraMapper1->SetInputConnection(shrink1->GetOutputPort()); + + vtkActor *aTetraActor1 = vtkActor::New(); + aTetraActor1->SetMapper (aTetraMapper1); + + //Second tets: + vtkShrinkFilter *shrink2 = vtkShrinkFilter::New(); + shrink2->SetInput( aTetraGrid2 ); + shrink2->SetShrinkFactor( 0.7 ); + + vtkDataSetMapper *aTetraMapper2 = vtkDataSetMapper::New(); + aTetraMapper2->SetInputConnection(shrink2->GetOutputPort()); + + vtkActor *aTetraActor2 = vtkActor::New(); + aTetraActor2->SetMapper (aTetraMapper2); + + //iso cases: + //First tets: + vtkShrinkFilter *isoshrink1 = vtkShrinkFilter::New(); + isoshrink1->SetInput( isoTetraGrid1 ); + isoshrink1->SetShrinkFactor( 0.7 ); + + vtkDataSetMapper *isoTetraMapper1 = vtkDataSetMapper::New(); + isoTetraMapper1->SetInputConnection(isoshrink1->GetOutputPort()); + + vtkActor *isoTetraActor1 = vtkActor::New(); + isoTetraActor1->SetMapper (isoTetraMapper1); + + //Second tets: + vtkShrinkFilter *isoshrink2 = vtkShrinkFilter::New(); + isoshrink2->SetInput( isoTetraGrid2 ); + isoshrink2->SetShrinkFactor( 0.7 ); + + vtkDataSetMapper *isoTetraMapper2 = vtkDataSetMapper::New(); + isoTetraMapper2->SetInputConnection(isoshrink2->GetOutputPort()); + + vtkActor *isoTetraActor2 = vtkActor::New(); + isoTetraActor2->SetMapper (isoTetraMapper2); + + //Place everybody + aTetraActor2->AddPosition (1.2, 0.0, 0); + isoTetraActor1->AddPosition (0.0, 1.2, 0); + isoTetraActor2->AddPosition (1.2, 1.2, 0); + + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + + renderer->SetBackground(1,1,1); + renderer->AddActor( aTetraActor1 ); + renderer->AddActor( aTetraActor2 ); + renderer->AddActor( isoTetraActor1 ); + renderer->AddActor( isoTetraActor2 ); + + renWin->AddRenderer( renderer ); + renWin->SetSize( 300, 300 ); + + iren->SetRenderWindow( renWin ); + renWin->Render(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + Points->Delete(); + triangulator1->Delete(); + aTetraGrid1->Delete(); + shrink1->Delete(); + aTetraActor1->Delete(); + aTetraMapper1->Delete(); + + triangulator2->Delete(); + aTetraGrid2->Delete(); + shrink2->Delete(); + aTetraActor2->Delete(); + aTetraMapper2->Delete(); + + isotriangulator1->Delete(); + isoTetraGrid1->Delete(); + isoshrink1->Delete(); + isoTetraActor1->Delete(); + isoTetraMapper1->Delete(); + + isotriangulator2->Delete(); + isoTetraGrid2->Delete(); + isoshrink2->Delete(); + isoTetraActor2->Delete(); + isoTetraMapper2->Delete(); + + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + + return 0; +} diff --git a/Rendering/Testing/Cxx/TimeRenderer.cxx b/Rendering/Testing/Cxx/TimeRenderer.cxx new file mode 100644 index 0000000..e89d3ac --- /dev/null +++ b/Rendering/Testing/Cxx/TimeRenderer.cxx @@ -0,0 +1,240 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TimeRenderer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkConeSource.h" +#include "vtkCubeSource.h" +#include "vtkCullerCollection.h" +#include "vtkGarbageCollector.h" +#include "vtkGlyph3D.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkStripper.h" +#include "vtkTimerLog.h" +#include "vtkTriangleFilter.h" + +int main( int argc, char *argv[] ) +{ + // For timings + int i; + int l, w, nActors, N, n; + vtkIdType aPnts; + + if (argc != 5) + { + l = 10; + w = 10; + aPnts = 15; + nActors = 100; + } + else + { + l = atoi(argv[1]); + w = atoi(argv[2]); + aPnts = atoi(argv[3]); + nActors = atoi(argv[4]); + } + + // n is the number of points per level + n = l * w; + // N is the total number of points + N = aPnts * nActors; + + float x, y, z; + vtkIdType *cdata = new vtkIdType [aPnts]; + for (int j = 0; j < aPnts; j++) + { + cdata[j] = j; + } + + vtkProperty *prop = vtkProperty::New(); + + //vtkGarbageCollector::DeferredCollectionPush(); + + // create a rendering window and both renderers + vtkRenderer *ren1 = vtkRenderer::New(); + ren1->GetCullers()->InitTraversal(); + vtkRenderWindow *renWindow = vtkRenderWindow::New(); + renWindow->AddRenderer(ren1); + + // Create a cube polydata + vtkPoints *cpnts = vtkPoints::New(); + cpnts->SetNumberOfPoints(14); + + vtkCellArray *ccells = vtkCellArray::New(); + + cpnts->SetPoint(0, .1, -.1, -.1); + cpnts->SetPoint(1, -.1, -.1, -.1); + cpnts->SetPoint(2, .1, .1, -.1); + cpnts->SetPoint(3, -.1, .1, -.1); + cpnts->SetPoint(4, -.1, .1, .1); + cpnts->SetPoint(5, -.1, -.1, -.1); + cpnts->SetPoint(6, -.1, -.1, .1); + cpnts->SetPoint(7, .1, -.1, -.1); + cpnts->SetPoint(8, .1, -.1, .1); + cpnts->SetPoint(9, .1, .1, -.1); + cpnts->SetPoint(10, .1, .1, .1); + cpnts->SetPoint(11, -.1, .1, .1); + cpnts->SetPoint(12, .1, -.1, .1); + cpnts->SetPoint(13, -.1, -.1, .1); + + vtkIdType a[14]; + for (i = 0; i < 14; i++) + { + a[i] = i; + } + + ccells->InsertNextCell(14L, a); + ccells->Squeeze(); + + vtkPolyData *cube = vtkPolyData::New(); + cube->SetPoints(cpnts); + cube->SetStrips(ccells); + cpnts->Delete(); + ccells->Delete(); + + vtkPolyDataMapper *mapper; + vtkCellArray *cells; + vtkActor *actor; + vtkGlyph3D *filter; + vtkPolyData *data; + vtkPoints *pnts = 0; + vtkTriangleFilter *tfilter; + vtkStripper *stripper; + + x = 0.0; + y = 0.0; + z = 0.0; + for (i = 0; i < N; i ++) + { + // See if we need to start a new actor + if ((i % aPnts) == 0) + { + if (pnts) + { + pnts->Delete(); + } + + pnts = vtkPoints::New(); + cells = vtkCellArray::New(); + data = vtkPolyData::New(); + filter = vtkGlyph3D::New(); + mapper = vtkPolyDataMapper::New(); + actor = vtkActor::New(); + tfilter = vtkTriangleFilter::New(); + stripper = vtkStripper::New(); + + prop->SetInterpolationToFlat(); + actor->SetProperty(prop); + + pnts->SetNumberOfPoints(aPnts); + cells->Allocate(aPnts); + cells->InsertNextCell(aPnts, cdata); + data->SetVerts(cells); + data->SetPoints(pnts); + tfilter->SetInput(cube); + stripper->SetInputConnection(tfilter->GetOutputPort()); + filter->SetSource(stripper->GetOutput()); + filter->SetInput(data); + mapper->SetInputConnection(filter->GetOutputPort()); + actor->SetMapper(mapper); + ren1->AddActor(actor); + + // all these are held by way of the renderer, so do a fast unref + cells->Delete(); + data->Delete(); + filter->Delete(); + mapper->Delete(); + actor->Delete(); + tfilter->Delete(); + stripper->Delete(); + } + + // See if we are on a new level) + if ((i % n) == 0) + { + z += 1.0; + x = 0.0; + y = 0.0; + } + else + { + if ((i % l) == 0) + { + x += 1.0; + y = 0.0; + } + else + { + y += 1.0; + } + } + + pnts->SetPoint(i % aPnts, x, y, z); + pnts->Modified(); + } + + if (pnts) + { + pnts->Delete(); + } + + // set the size of our window + renWindow->SetSize(500,500); + + // set the viewports and background of the renderers + // ren1->SetViewport(0,0,0.5,1); + ren1->SetBackground(0.2,0.3,0.5); + + // draw the resulting scene + renWindow->Render(); + ren1->GetActiveCamera()->Azimuth(3); + renWindow->Render(); + + // Set up times + vtkTimerLog *tl = vtkTimerLog::New(); + + tl->StartTimer(); + + // do a azimuth of the cameras 3 degrees per iteration + // for (i = 0; i < 360; i += 3) +#if 1 + for (i = 0; i < 360; i += 9) + { + ren1->GetActiveCamera()->Azimuth(3); + renWindow->Render(); + } +#endif + tl->StopTimer(); + + cerr << "Wall Time = " << tl->GetElapsedTime() << "\n"; + cerr << "FrameRate = " << 120.0 / tl->GetElapsedTime() << "\n"; + + // Clean up + cube->Delete(); + vtkGarbageCollector::SetGlobalDebugFlag(1); + vtkGarbageCollector::SetGlobalDebugFlag(0); + prop->Delete(); + ren1->Delete(); + renWindow->Delete(); + tl->Delete(); + //vtkGarbageCollector::DeferredCollectionPop(); + return 1; +} diff --git a/Rendering/Testing/Cxx/TimeRenderer2.cxx b/Rendering/Testing/Cxx/TimeRenderer2.cxx new file mode 100644 index 0000000..ef161b3 --- /dev/null +++ b/Rendering/Testing/Cxx/TimeRenderer2.cxx @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TimeRenderer2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCullerCollection.h" +#include "vtkPlaneSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkStripper.h" +#include "vtkTimerLog.h" +#include "vtkTriangleFilter.h" + +int main( int argc, char *argv[] ) +{ + // For timings + int i; + int RES = 200; + if (argc > 1) + { + RES = atoi(argv[1]); + } + // create a rendering window and both renderers + vtkRenderer *ren1 = vtkRenderer::New(); + ren1->GetCullers()->InitTraversal(); + //ren1->RemoveCuller(ren1->GetCullers()->GetNextItem()); + vtkRenderWindow *renWindow = vtkRenderWindow::New(); + renWindow->AddRenderer(ren1); + + vtkPlaneSource *plane = vtkPlaneSource::New(); + plane->SetResolution(RES,RES); + + vtkPolyDataMapper *mapper; + vtkActor *actor; + vtkTriangleFilter *tfilter; + vtkStripper *stripper; + + mapper = vtkPolyDataMapper::New(); + actor = vtkActor::New(); + tfilter = vtkTriangleFilter::New(); + stripper = vtkStripper::New(); + + tfilter->SetInputConnection(plane->GetOutputPort()); + stripper->SetInputConnection(tfilter->GetOutputPort()); + mapper->SetInputConnection(stripper->GetOutputPort()); + actor->SetMapper(mapper); + ren1->AddActor(actor); + + // set the size of our window + renWindow->SetSize(500,500); + + // set the viewports and background of the renderers + // ren1->SetViewport(0,0,0.5,1); + ren1->SetBackground(0.2,0.3,0.5); + + // draw the resulting scene + renWindow->Render(); + ren1->GetActiveCamera()->Azimuth(3); + renWindow->Render(); + // Set up times + vtkTimerLog *tl = vtkTimerLog::New(); + + tl->StartTimer(); + + // do a azimuth of the cameras 3 degrees per iteration + for (i = 0; i < 360; i += 3) + { + ren1->GetActiveCamera()->Azimuth(3); + renWindow->Render(); + } + + tl->StopTimer(); + + cerr << "Wall Time = " << tl->GetElapsedTime() << "\n"; + cerr << "FrameRate = " << 120.0 / tl->GetElapsedTime() << "\n"; + cerr << "TriRate = " << RES*RES*2*120 / tl->GetElapsedTime() << "\n"; + + // Clean up + ren1->Delete(); + renWindow->Delete(); + tl->Delete(); + return 1; +} diff --git a/Rendering/Testing/Cxx/VTKBenchMark.cxx b/Rendering/Testing/Cxx/VTKBenchMark.cxx new file mode 100644 index 0000000..77ebf7f --- /dev/null +++ b/Rendering/Testing/Cxx/VTKBenchMark.cxx @@ -0,0 +1,235 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: VTKBenchMark.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCutter.h" +#include "vtkImageData.h" +#include "vtkImageGaussianSmooth.h" +#include "vtkImageMandelbrotSource.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyDataNormals.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkSmartPointer.h" +#include "vtkSphere.h" +#include "vtkStripper.h" +#include "vtkTimerLog.h" +#include "vtkTriangleFilter.h" + +class VTKBenchmark +{ +public: + + // Description: + // The main entry point for the benchmark + int Run(); + + VTKBenchmark(); + +private: + + double BuildTheFractal(); + double DrawTheFractal(); + + vtkSmartPointer Timer; + vtkSmartPointer Mandelbrot; + vtkSmartPointer GaussianSmooth; + vtkSmartPointer Cutter; + vtkSmartPointer TriFilter; + vtkSmartPointer Stripper; + vtkSmartPointer Normals; + + int ImmediateMode; + int ScalarColoring; + int UseNormals; + + // all times are in seconds + double DataBuildTime; +}; + +VTKBenchmark::VTKBenchmark() +{ + this->Timer = vtkSmartPointer::New(); + this->Mandelbrot = vtkSmartPointer::New(); + this->GaussianSmooth = vtkSmartPointer::New(); + this->Cutter = vtkSmartPointer::New(); + this->TriFilter = vtkSmartPointer::New(); + this->Stripper = vtkSmartPointer::New(); + this->Normals = vtkSmartPointer::New(); + + this->ImmediateMode = 1; + this->ScalarColoring = 0; + this->UseNormals = 0; +} + +double VTKBenchmark::BuildTheFractal() +{ + cerr << "Building Fractal ... (this may take a minute or two)\n"; + + // time the data creation + this->Timer->StartTimer(); + + // first we want to create some data, a 256 cubed Mandelbrot src + this->Mandelbrot->SetWholeExtent(0,255,0,255,0,255); + this->Mandelbrot->SetOriginCX(-1.75,-1.25,-1,0); + this->Mandelbrot->Update(); + + cerr << "Smoothing...\n"; + this->GaussianSmooth->SetInputConnection(this->Mandelbrot->GetOutputPort()); + this->GaussianSmooth->Update(); + + // extract a sphere from the fractal volume + vtkSmartPointer sphere = + vtkSmartPointer::New(); + + // add two contours + cerr << "Cutting...\n"; + this->Cutter->SetInputConnection(this->GaussianSmooth->GetOutputPort()); + this->Cutter->SetCutFunction(sphere); + this->Cutter->Update(); + + // convert it to all triangles + cerr << "Converting to Triangles...\n"; + this->TriFilter->SetInputConnection(this->Cutter->GetOutputPort()); + this->TriFilter->Update(); + + // generate Normals + cerr << "Computing Normals...\n"; + this->Normals->SetInputConnection(this->TriFilter->GetOutputPort()); + this->Normals->Update(); + + // and then strip them + cerr << "Creating Strips...\n"; + this->Stripper->SetInputConnection(this->Normals->GetOutputPort()); + this->Stripper->Update(); + + + cerr << "Number Of Triangles: " << + this->TriFilter->GetOutput()->GetNumberOfPolys() << "\n"; + cerr << "Average Strip Length: " << + this->TriFilter->GetOutput()->GetNumberOfPolys()/ + (double)this->Stripper->GetOutput()->GetNumberOfStrips() << "\n"; + + this->Timer->StopTimer(); + + return this->Timer->GetElapsedTime(); +} + + +int VTKBenchmark::Run() +{ + this->DataBuildTime = this->BuildTheFractal(); + + cerr << "Build Rate: " << 1.0/this->DataBuildTime << "\n"; + + for (this->ImmediateMode = 0; this->ImmediateMode < 2; + this->ImmediateMode++) + { + for (this->ScalarColoring = 0; this->ScalarColoring < 2; + this->ScalarColoring++) + { + for (this->UseNormals = 0; this->UseNormals < 2; + this->UseNormals++) + { + cerr << "Render Rate: " + << (this->ImmediateMode ? "IMED " : " ") + << (this->ScalarColoring ? "SCAL " : " ") + << (this->UseNormals ? "NORM " : " ") + << this->DrawTheFractal() << " MegaTriangles/Second\n"; + } + } + } + + return 0; +} + + +double VTKBenchmark::DrawTheFractal() +{ + // create a rendering window and both renderers + vtkSmartPointer ren1 = vtkSmartPointer::New(); + vtkSmartPointer renWindow = + vtkSmartPointer::New(); + renWindow->AddRenderer(ren1); + + vtkSmartPointer mapper = + vtkSmartPointer::New(); + + vtkSmartPointer actor = vtkSmartPointer::New(); + + if (this->UseNormals) + { + this->Stripper->SetInputConnection(this->Normals->GetOutputPort()); + } + else + { + this->Stripper->SetInputConnection(this->TriFilter->GetOutputPort()); + } + mapper->SetInputConnection(this->Stripper->GetOutputPort()); + mapper->SetImmediateModeRendering(this->ImmediateMode); + mapper->SetScalarVisibility(this->ScalarColoring); + mapper->SetScalarRange(5,30); + + actor->SetMapper(mapper); + ren1->AddActor(actor); + + // set the size of our window + renWindow->SetSize(500,500); + + // set the viewports and background of the renderers + ren1->SetBackground(0.2,0.3,0.5); + + // draw the resulting scene + renWindow->Render(); + + this->Timer->StartTimer(); + + // do a azimuth of the cameras 50 degrees per iteration + ren1->GetActiveCamera()->Azimuth(50); + renWindow->Render(); + ren1->GetActiveCamera()->Azimuth(50); + renWindow->Render(); + ren1->GetActiveCamera()->Azimuth(50); + renWindow->Render(); + ren1->GetActiveCamera()->Zoom(3.0); + ren1->GetActiveCamera()->Azimuth(50); + renWindow->Render(); + ren1->GetActiveCamera()->Elevation(50); + renWindow->Render(); + ren1->GetActiveCamera()->Elevation(50); + renWindow->Render(); + + this->Timer->StopTimer(); + + // compute the M triangles per second + double numTris = (double)this->TriFilter->GetOutput()->GetNumberOfPolys(); + + return 6.0e-6*numTris/this->Timer->GetElapsedTime(); +} + + + +int main( int argc, char *argv[] ) +{ + VTKBenchmark a; + if (argc > 1) + { + cerr << argv[0] << " takes no arguments\n"; + } + return a.Run(); +} + diff --git a/Rendering/Testing/Cxx/otherCoordinate.cxx b/Rendering/Testing/Cxx/otherCoordinate.cxx new file mode 100644 index 0000000..e088e1e --- /dev/null +++ b/Rendering/Testing/Cxx/otherCoordinate.cxx @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: otherCoordinate.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME +// .SECTION Description +// this program tests vtkCoordinate + +#include "vtkCoordinate.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkCamera.h" + +#include "vtkDebugLeaks.h" + +void ToAll (ostream& strm, vtkCoordinate *c1, vtkViewport *ren1, + double *from) +{ + double *value; + int *ivalue; + const char *whichCoord = c1->GetCoordinateSystemAsString(); + + c1->SetValue (from); + + strm << endl << "========" << endl; + strm << *c1; + value = c1->GetComputedWorldValue (ren1); + strm << whichCoord <<"(" << from[0] << ", " << from[1] << ", " << from[2] + << ") -> World(" << value[0] << ", " << value[1] << ", " << value[2] + << ")" << endl; + ivalue = c1->GetComputedDisplayValue (ren1); + strm << whichCoord << "(" << from[0] << ", " << from[1] << ", " << from[2] + << ") -> Display(" << ivalue[0] << ", " << ivalue[1] << ")" << endl; + ivalue = c1->GetComputedLocalDisplayValue (ren1); + strm << whichCoord << "(" << from[0] << ", " << from[1] << ", " << from[2] + << ") -> LocalDisplay(" << ivalue[0] << ", " << ivalue[1] + << ")" << endl; + ivalue = c1->GetComputedViewportValue (ren1); + strm << whichCoord << "(" << from[0] << ", " << from[1] << ", " << from[2] + << ") -> Viewport(" << ivalue[0] << ", " << ivalue[1] << ")" << endl; + + +} +int Test(ostream& strm) +{ + // actual test + strm << "Testing vtkCoordinate" << endl; + vtkCoordinate *c1 = vtkCoordinate::New(); + vtkCoordinate *c2 = vtkCoordinate::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + vtkRenderer *ren1 = vtkRenderer::New(); + vtkCamera *camera = vtkCamera::New(); + double from[3]; + + ren1->SetActiveCamera (camera); + renWin->AddRenderer (ren1); + renWin->SetSize (100, 100); + + strm << "Origin: (" << ren1->GetOrigin()[0] << ", " << ren1->GetOrigin()[1] << ")" << endl; + strm << "Center: (" << ren1->GetCenter()[0] << ", " << ren1->GetOrigin()[1] << ")" << endl; + + strm << endl << "********** A NULL Viewport **********" << endl; + + c1->SetCoordinateSystemToWorld(); + from[0] = 0.0; from[1] = 0.0; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToDisplay(); + from[0] = 50; from[1] = 50; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToNormalizedDisplay(); + from[0] = .5; from[1] = .5; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToViewport(); + from[0] = 50; from[1] = 50; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToNormalizedViewport(); + from[0] = .5; from[1] = .5; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToView(); + from[0] = 0.0; from[1] = 0.0; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + strm << endl << "********** A specified Viewport **********" << endl; + c1->SetViewport (ren1); + + c1->SetCoordinateSystemToWorld(); + from[0] = 0.0; from[1] = 0.0; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToDisplay(); + from[0] = 50; from[1] = 50; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToNormalizedDisplay(); + from[0] = .5; from[1] = .5; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToViewport(); + from[0] = 50; from[1] = 50; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToNormalizedViewport(); + from[0] = .5; from[1] = .5; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToView(); + from[0] = 0.0; from[1] = 0.0; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + strm << endl << "********** With a Reference Coordinate **********" << endl; + + c2->SetCoordinateSystemToNormalizedDisplay(); + c2->SetCoordinateSystemToWorld(); + c2->SetValue (0.0, 0.0, 0.0); + c1->SetReferenceCoordinate (c2); + + strm << *c2; + + c1->SetCoordinateSystemToWorld(); + from[0] = 0.0; from[1] = 0.0; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToDisplay(); + from[0] = 50; from[1] = 50; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToNormalizedDisplay(); + from[0] = .5; from[1] = .5; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToViewport(); + from[0] = 50; from[1] = 50; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToNormalizedViewport(); + from[0] = .5; from[1] = .5; from[2] = 0; + ToAll (strm, c1, ren1, from); + + c1->SetCoordinateSystemToView(); + from[0] = 0.0; from[1] = 0.0; from[2] = 0.0; + ToAll (strm, c1, ren1, from); + + c1->Delete (); + c2->Delete (); + renWin->Delete (); + ren1->Delete (); + camera->Delete (); + + strm << "Testing completed" << endl; + return 0; +} + +int otherCoordinate(int,char *[]) +{ + ostrstream vtkmsg_with_warning_C4701; + return Test(vtkmsg_with_warning_C4701); +} + diff --git a/Rendering/Testing/Cxx/vtkRegressionTestImage.h b/Rendering/Testing/Cxx/vtkRegressionTestImage.h new file mode 100644 index 0000000..b8ca3b4 --- /dev/null +++ b/Rendering/Testing/Cxx/vtkRegressionTestImage.h @@ -0,0 +1,40 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRegressionTestImage.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkRegressionTestImage_h +#define __vtkRegressionTestImage_h + +// Includes and a macro necessary for saving the image produced by a cxx +// example program. This capability is critical for regression testing. +// This function returns 1 if test passed, 0 if test failed. + +#include "vtkTesting.h" + +class vtkRegressionTester : public vtkTesting +{ +protected: + vtkRegressionTester() {}; + ~vtkRegressionTester() {}; +private: + vtkRegressionTester(const vtkRegressionTester&); // Not implemented. + void operator=(const vtkRegressionTester&); // Not implemented. +}; + +#define vtkRegressionTestImage(rw) \ +vtkTesting::Test(argc, argv, rw, 10) + +#define vtkRegressionTestImageThreshold(rw, t) \ +vtkTesting::Test(argc, argv, rw, t) + +#endif // __vtkRegressionTestImage_h diff --git a/Rendering/Testing/Python/CMakeLists.txt b/Rendering/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..2801a58 --- /dev/null +++ b/Rendering/Testing/Python/CMakeLists.txt @@ -0,0 +1,71 @@ +INCLUDE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake) +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + IF (VTK_PYTHON_EXE) + IF(VTK_USE_TK) + FOREACH ( tfile + TestTkRenderWidget + TestTkRenderWindowInteractor + ) + ADD_TEST(${tfile}Python-image ${VTK_PYTHON_EXE} + ${VTK_SOURCE_DIR}/Rendering/Testing/Python/${tfile}.py + -B ${VTK_DATA_ROOT}/Baseline/Rendering + -D ${VTK_DATA_ROOT}/Data) + ENDFOREACH( tfile ) + ENDIF(VTK_USE_TK) + + ############################# + # Add GL2PS specific tests. + IF(VTK_USE_GL2PS) + FOREACH ( tfile + TestGL2PSExporter + ) + ADD_TEST(${tfile}Python-image ${VTK_PYTHON_EXE} + ${VTK_SOURCE_DIR}/Rendering/Testing/Python/${tfile}.py + -B ${VTK_DATA_ROOT}/Baseline/Rendering + -D ${VTK_DATA_ROOT}/Data) + ENDFOREACH( tfile ) + ENDIF(VTK_USE_GL2PS) + ############################# + + # Add test converted from Tcl + SET(tests + assembly + CamBlur + #cells -- too complex file IO + ImageActor + ImageActorStressed + labeledContours + labeledMesh + multiLineText + pickCells + propAssembly + rendererSource + rotations + ScalarBar + TestFlyTo + TestOnePoint + TestParallelCoordinates + #TestStyleTerrain -- file source + TestTiling + TestTriangleStripCellColor + ) + SET(tests ${tests} + #TestStyleJoystickActor --file source + #TestStyleJoystickCamera + TestStyleRubberBandZoom + #TestStyleTrackballActor -- file source + #TestStyleTrackballCamera -- file source + ) + CONVERT_TCL_TEST_TO_PY( + tests + Rendering) + ENDIF (VTK_PYTHON_EXE) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + diff --git a/Rendering/Testing/Python/TestGL2PSExporter.py b/Rendering/Testing/Python/TestGL2PSExporter.py new file mode 100644 index 0000000..7b0f387 --- /dev/null +++ b/Rendering/Testing/Python/TestGL2PSExporter.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +""" +Run this test like so: +$ vtkpython TestGL2PSExporter.py -D $VTK_DATA_ROOT \ + -B $VTK_DATA_ROOT/Baseline/Rendering/ + +$ vtkpython TestGL2PSExporter.py --help +provides more details on other options. + +Please note that this test requires that you have PIL (the Python +Imaging Library) module installed and also GL2PS support built into +VTK. + +""" + +import sys +import os +import os.path +import tempfile + +import vtk +from vtk.test import Testing + +# This requires that you have PIL installed. +try: + import Image +except ImportError: + print "Please install PIL (Python Imaging Library) to run this test." + sys.exit(0) + + +class TestGL2PSExporter(Testing.vtkTest): + # Create these as class attributes so that they are only created + # once and not for every test. + cs = vtk.vtkConeSource() + mapper = vtk.vtkPolyDataMapper() + mapper.SetInputConnection(cs.GetOutputPort()) + + act = vtk.vtkActor() + act.SetMapper(mapper) + act.GetProperty().SetColor(0.5, 0.5, 1.0) + + axes = vtk.vtkCubeAxesActor2D() + axes.SetInputConnection(cs.GetOutputPort()) + axes.SetFontFactor(2.0) + axes.SetCornerOffset(0.0) + axes.GetProperty().SetColor(0,0,0) + + txt = vtk.vtkTextActor() + txt.SetDisplayPosition(45, 150) + txt.SetInput("This is test\nmultiline\ninput\ndata.") + tprop = txt.GetTextProperty() + tprop.SetFontSize(18) + tprop.SetFontFamilyToArial() + tprop.SetJustificationToCentered() + tprop.BoldOn() + tprop.ItalicOn() + tprop.ShadowOn() + tprop.SetColor(0, 0, 1) + + ren = vtk.vtkRenderer() + ren.AddActor(act) + ren.AddActor(txt) + axes.SetCamera(ren.GetActiveCamera()) + ren.AddActor(axes) + ren.SetBackground(0.8, 0.8, 0.8) + + renWin = vtk.vtkRenderWindow() + renWin.AddRenderer(ren) + + iren = vtk.vtkRenderWindowInteractor() + iren.SetRenderWindow(renWin) + + cam = ren.GetActiveCamera() + cam.Azimuth(30) + + iren.Initialize() + iren.Render() + + def _cleanup(self, files): + """Remove the list of given files.""" + for f in files: + if os.path.isfile(f): + os.remove(f) + + def testVectorEPS(self): + """Test vector EPS output.""" + # Get a temporary file name. Set the extension to empty since + # the exporter appends a suitable extension. + tmp_eps = tempfile.mktemp('') + # Write an EPS file. + exp = vtk.vtkGL2PSExporter() + exp.SetRenderWindow(self.renWin) + exp.SetFilePrefix(tmp_eps) + # Turn off compression so PIL can read file. + exp.CompressOff() + exp.SetSortToBSP() + exp.DrawBackgroundOn() + exp.Write() + # Now read the EPS file using PIL. + tmp_eps += '.eps' + im = Image.open(tmp_eps) + # Get a temporary name for the PNG file. + tmp_png = tempfile.mktemp('.png') + im.save(tmp_png) + + # Now read the saved image and compare it for the test. + png_r = vtk.vtkPNGReader() + png_r.SetFileName(tmp_png) + png_r.Update() + img = png_r.GetOutput() + + # Cleanup. Do this first because if the test fails, an + # exception is raised and the temporary files won't be + # removed. + self._cleanup([tmp_eps, tmp_png]) + + img_file = "TestGL2PSExporter.png" + Testing.compareImageWithSavedImage(img, + Testing.getAbsImagePath(img_file)) + # Interact if necessary. + Testing.interact() + + def testRasterEPS(self): + """Test EPS output when Write3DPropsAsRasterImage is on.""" + # Get a temporary file name. Set the extension to empty since + # the exporter appends a suitable extension. + tmp_eps = tempfile.mktemp('') + # Write an EPS file. + exp = vtk.vtkGL2PSExporter() + exp.SetRenderWindow(self.renWin) + exp.SetFilePrefix(tmp_eps) + # Turn off compression so PIL can read file. + exp.CompressOff() + exp.SetSortToOff() + exp.DrawBackgroundOn() + exp.Write3DPropsAsRasterImageOn() + exp.Write() + # Now read the EPS file using PIL. + tmp_eps += '.eps' + im = Image.open(tmp_eps) + # Get a temporary name for the PNG file. + tmp_png = tempfile.mktemp('.png') + im.save(tmp_png) + + # Now read the saved image and compare it for the test. + png_r = vtk.vtkPNGReader() + png_r.SetFileName(tmp_png) + png_r.Update() + img = png_r.GetOutput() + + # Cleanup. Do this first because if the test fails, an + # exception is raised and the temporary files won't be + # removed. + self._cleanup([tmp_eps, tmp_png]) + + img_file = "TestGL2PSExporter.png" + Testing.compareImageWithSavedImage(img, + Testing.getAbsImagePath(img_file)) + # Interact if necessary. + Testing.interact() + + +if __name__ == "__main__": + cases = [(TestGL2PSExporter, 'test')] + # This should prevent debug leaks messages. + del TestGL2PSExporter + Testing.main(cases) diff --git a/Rendering/Testing/Python/TestTkRenderWidget.py b/Rendering/Testing/Python/TestTkRenderWidget.py new file mode 100644 index 0000000..585c736 --- /dev/null +++ b/Rendering/Testing/Python/TestTkRenderWidget.py @@ -0,0 +1,65 @@ +# A simple test for a vtkTkRenderWidget. Run it like so: +# python TestTkRenderWidget.py -B $VTK_DATA_ROOT/Baseline/Rendering + +import os + +import vtk +from vtk.test import Testing + +import Tkinter +from vtk.tk.vtkTkRenderWidget import vtkTkRenderWidget + + +class TestTkRenderWidget(Testing.vtkTest): + + # Stick your VTK pipeline here if you want to create the pipeline + # only once. If you put it in the constructor or in the function + # the pipeline will be created afresh for each and every test. + + # create a dummy Tkinter root window. + root = Tkinter.Tk() + + # create a rendering window and renderer + ren = vtk.vtkRenderer() + tkrw = vtkTkRenderWidget(root, width=300, height=300) + tkrw.pack() + rw = tkrw.GetRenderWindow() + rw.AddRenderer(ren) + + # create an actor and give it cone geometry + cs = vtk.vtkConeSource() + cs.SetResolution(8) + map = vtk.vtkPolyDataMapper() + map.SetInputConnection(cs.GetOutputPort()) + act = vtk.vtkActor() + act.SetMapper(map) + + # assign our actor to the renderer + ren.AddActor(act) + + def testvtkTkRenderWidget(self): + "Test if vtkTkRenderWidget works." + self.rw.Render() + self.root.update() + img_file = "TestTkRenderWidget.png" + Testing.compareImage(self.rw, Testing.getAbsImagePath(img_file)) + Testing.interact() + + # Dummy tests to demonstrate how the blackbox tests can be done. + def testParse(self): + "Test if vtkActor is parseable" + self._testParse(self.act) + + def testGetSet(self): + "Testing Get/Set methods" + self._testGetSet(self.act) + + def testBoolean(self): + "Testing Boolean methods" + self._testBoolean(self.act) + + +if __name__ == "__main__": + cases = [(TestTkRenderWidget, 'test')] + del TestTkRenderWidget + Testing.main(cases) diff --git a/Rendering/Testing/Python/TestTkRenderWindowInteractor.py b/Rendering/Testing/Python/TestTkRenderWindowInteractor.py new file mode 100644 index 0000000..a1dd150 --- /dev/null +++ b/Rendering/Testing/Python/TestTkRenderWindowInteractor.py @@ -0,0 +1,65 @@ +# A simple test for a vtkTkRenderWidget. Run it like so: +# python TestTkRenderWindowInteractor.py -B $VTK_DATA_ROOT/Baseline/Rendering + +import os +import vtk +from vtk.test import Testing + +import Tkinter +from vtk.tk.vtkTkRenderWindowInteractor import vtkTkRenderWindowInteractor + + +class TestTkRenderWindowInteractor(Testing.vtkTest): + + # Stick your VTK pipeline here if you want to create the pipeline + # only once. If you put it in the constructor or in the function + # the pipeline will be created afresh for each and every test. + + # create a dummy Tkinter root window. + root = Tkinter.Tk() + + # create a rendering window and renderer + ren = vtk.vtkRenderer() + tkrw = vtkTkRenderWindowInteractor(root, width=300, height=300) + tkrw.Initialize() + tkrw.pack() + rw = tkrw.GetRenderWindow() + rw.AddRenderer(ren) + + # create an actor and give it cone geometry + cs = vtk.vtkConeSource() + cs.SetResolution(8) + map = vtk.vtkPolyDataMapper() + map.SetInputConnection(cs.GetOutputPort()) + act = vtk.vtkActor() + act.SetMapper(map) + + # assign our actor to the renderer + ren.AddActor(act) + + def testvtkTkRenderWindowInteractor(self): + "Test if vtkTkRenderWindowInteractor works." + self.tkrw.Start() + self.tkrw.Render() + self.root.update() + img_file = "TestTkRenderWindowInteractor.png" + Testing.compareImage(self.rw, Testing.getAbsImagePath(img_file)) + Testing.interact() + + # These are useful blackbox tests (not dummy ones!) + def testParse(self): + "Test if vtkTkRenderWindowInteractor is parseable" + self._testParse(self.tkrw) + + def testGetSet(self): + "Testing Get/Set methods of vtkTkRenderWindowInteractor" + self._testGetSet(self.tkrw) + + def testBoolean(self): + "Testing Boolean methods of vtkTkRenderWindowInteractor" + self._testBoolean(self.tkrw) + +if __name__ == "__main__": + cases = [(TestTkRenderWindowInteractor, 'test')] + del TestTkRenderWindowInteractor + Testing.main(cases) diff --git a/Rendering/Testing/Tcl/CMakeLists.txt b/Rendering/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..2170361 --- /dev/null +++ b/Rendering/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,85 @@ +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + SET( tests + assembly + CamBlur + cells + ImageActor + ImageActorStressed + labeledContours + labeledMesh + multiLineText + pickCells + propAssembly + rendererSource + rotations + ScalarBar + TestFlyTo + TestOnePoint + TestParallelCoordinates + TestStyleTerrain + TestTiling + TestTriangleStripCellColor + ) + IF(VTK_USE_TK) + SET(tests ${tests} + TestStyleJoystickActor + TestStyleJoystickCamera + TestStyleRubberBandZoom + TestStyleTrackballActor + TestStyleTrackballCamera + ) + ENDIF(VTK_USE_TK) + FOREACH ( tfile ${tests} ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Rendering/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -V Baseline/Rendering/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + + FOREACH ( tfile + TestFreetypeTextMapper + TestFreetypeTextMapperBigger + TestFreetypeTextOverlay + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Rendering/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Rendering/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + + IF (VTK_USE_MANGLED_MESA) + ADD_TEST(MesaText-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Rendering/Testing/Tcl/MesaText.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Rendering/MesaText.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDIF (VTK_USE_MANGLED_MESA) + # + # If we do not have the data, still run the tests that we can + # + ELSE (VTK_DATA_ROOT) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + +ADD_TEST(PrintSelf-Rendering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Rendering) + +ADD_TEST(TestSetObjectMacro-Rendering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Rendering/vtk\\\\*.h" + "vtkSetObjectMacro" + ) diff --git a/Rendering/Testing/Tcl/CamBlur.tcl b/Rendering/Testing/Tcl/CamBlur.tcl new file mode 100644 index 0000000..888b79e --- /dev/null +++ b/Rendering/Testing/Tcl/CamBlur.tcl @@ -0,0 +1,73 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create the piplinee, ball and spikes + +vtkSphereSource sphere + sphere SetThetaResolution 7 ; sphere SetPhiResolution 7 +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +vtkActor sphereActor + sphereActor SetMapper sphereMapper +vtkActor sphereActor2 + sphereActor2 SetMapper sphereMapper +vtkConeSource cone + cone SetResolution 5 + +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 + +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] +vtkActor spikeActor + spikeActor SetMapper spikeMapper +vtkActor spikeActor2 + spikeActor2 SetMapper spikeMapper + +# set the actors position and scale +spikeActor SetPosition 0 0.7 0 +sphereActor SetPosition 0 0.7 0 +spikeActor2 SetPosition 0 -1 -10 +sphereActor2 SetPosition 0 -1 -10 +spikeActor2 SetScale 1.5 1.5 1.5 +sphereActor2 SetScale 1.5 1.5 1.5 + + +ren1 AddActor sphereActor +ren1 AddActor spikeActor +ren1 AddActor sphereActor2 +ren1 AddActor spikeActor2 +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 200 200 +renWin DoubleBufferOff + +# do the first render and then zoom in a little +renWin Render +[ren1 GetActiveCamera] SetFocalPoint 0 0 0 +[ren1 GetActiveCamera] Zoom 1.8 +[ren1 GetActiveCamera] SetFocalDisk 0.05 + +renWin SetFDFrames 11 +renWin Render; + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +#renWin SetFileName CamBlur.tcl.ppm +#renWin SaveImageAsPPM + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Rendering/Testing/Tcl/ImageActor.tcl b/Rendering/Testing/Tcl/ImageActor.tcl new file mode 100644 index 0000000..11df006 --- /dev/null +++ b/Rendering/Testing/Tcl/ImageActor.tcl @@ -0,0 +1,40 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# load in the image +# +vtkTIFFReader pnmReader +pnmReader SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + +vtkImageActor ia +ia SetInput [pnmReader GetOutput] + +# Add the actors to the renderer, set the background and size +ren1 AddActor ia +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 400 400 + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +set cam1 [ren1 GetActiveCamera] +$cam1 Elevation -30 +$cam1 Roll -20 +ren1 ResetCameraClippingRange +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + diff --git a/Rendering/Testing/Tcl/ImageActorStressed.tcl b/Rendering/Testing/Tcl/ImageActorStressed.tcl new file mode 100644 index 0000000..864ab9b --- /dev/null +++ b/Rendering/Testing/Tcl/ImageActorStressed.tcl @@ -0,0 +1,154 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# First one tests the changing display extent without +# changing the size of the display extent (so it +# reuses a texture, but not a contiguous one) +vtkImageEllipsoidSource gsOne +gsOne SetWholeExtent 0 999 0 999 0 0 +gsOne SetCenter 500 500 0 +gsOne SetRadius 300 400 0 +gsOne SetInValue 0 +gsOne SetOutValue 255 +gsOne SetOutputScalarTypeToUnsignedChar + +vtkImageShiftScale ssOne +ssOne SetInputConnection [gsOne GetOutputPort] +ssOne SetOutputScalarTypeToUnsignedChar +ssOne SetShift 0 +ssOne SetScale 1 +ssOne UpdateWholeExtent + +vtkImageActor iaOne +iaOne SetInput [ssOne GetOutput] + +ren1 AddActor iaOne + +# The second one tests a really large texture +vtkImageEllipsoidSource gsTwo +gsTwo SetWholeExtent 1000 8999 1000 8999 0 0 +gsTwo SetCenter 4000 4000 0 +gsTwo SetRadius 1800 1800 0 +gsTwo SetInValue 250 +gsTwo SetOutValue 150 +gsTwo SetOutputScalarTypeToUnsignedChar + +vtkImageShiftScale ssTwo +ssTwo SetInputConnection [gsTwo GetOutputPort] +ssTwo SetOutputScalarTypeToUnsignedChar +ssTwo SetShift 0 +ssTwo SetScale 1 +ssTwo UpdateWholeExtent + +vtkImageActor iaTwo +iaTwo SetInput [ssTwo GetOutput] +iaTwo SetScale 0.1 0.1 1.0 +iaTwo AddPosition 1000 1000 0 + +ren1 AddActor iaTwo + +# The third one will test changing input and a +# power of two texture +vtkImageEllipsoidSource gsThree +gsThree SetWholeExtent 0 511 2000 2511 0 0 +gsThree SetCenter 255 2255 0 +gsThree SetRadius 100 200 0 +gsThree SetInValue 250 +gsThree SetOutValue 0 +gsThree SetOutputScalarTypeToUnsignedChar + +vtkImageShiftScale ssThree +ssThree SetInputConnection [gsThree GetOutputPort] +ssThree SetOutputScalarTypeToUnsignedChar +ssThree SetShift 0 +ssThree SetScale 1 +ssThree UpdateWholeExtent + +vtkImageActor iaThree +iaThree SetInput [ssThree GetOutput] + +ren1 AddActor iaThree + + +# Same as first one, but the display extents +# represent contiguous section of memory that +# are powers of two +vtkImageEllipsoidSource gsFour +gsFour SetWholeExtent 2000 2511 0 511 0 0 +gsFour SetCenter 2255 255 0 +gsFour SetRadius 130 130 0 +gsFour SetInValue 40 +gsFour SetOutValue 190 +gsFour SetOutputScalarTypeToUnsignedChar + +vtkImageShiftScale ssFour +ssFour SetInputConnection [gsFour GetOutputPort] +ssFour SetOutputScalarTypeToUnsignedChar +ssFour SetShift 0 +ssFour SetScale 1 +ssFour UpdateWholeExtent + +vtkImageActor iaFour +iaFour SetInput [ssFour GetOutput] + +ren1 AddActor iaFour + +# Same as previous one, but the display extents +# represent contiguous section of memory that +# are not powers of two +vtkImageEllipsoidSource gsFive +gsFive SetWholeExtent 1200 1712 0 512 0 0 +gsFive SetCenter 1456 256 0 +gsFive SetRadius 130 180 0 +gsFive SetInValue 190 +gsFive SetOutValue 100 +gsFive SetOutputScalarTypeToUnsignedChar + +vtkImageShiftScale ssFive +ssFive SetInputConnection [gsFive GetOutputPort] +ssFive SetOutputScalarTypeToUnsignedChar +ssFive SetShift 0 +ssFive SetScale 1 +ssFive UpdateWholeExtent + +vtkImageActor iaFive +iaFive SetInput [ssFive GetOutput] + +ren1 AddActor iaFive + + +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 400 400 + +# render the image +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + +renWin Render + +iaOne SetDisplayExtent 200 999 200 999 0 0 +iaFour SetDisplayExtent 2000 2511 0 300 0 0 +iaFive SetDisplayExtent 1200 1712 0 300 0 0 +gsThree SetRadius 120 120 0 +renWin Render + +iaOne SetDisplayExtent 0 799 0 799 0 0 +iaFour SetDisplayExtent 2000 2511 200 500 0 0 +iaFive SetDisplayExtent 1200 1712 200 500 0 0 +gsThree SetRadius 150 150 0 +renWin Render + diff --git a/Rendering/Testing/Tcl/MesaText.tcl b/Rendering/Testing/Tcl/MesaText.tcl new file mode 100644 index 0000000..cd7c3b2 --- /dev/null +++ b/Rendering/Testing/Tcl/MesaText.tcl @@ -0,0 +1,39 @@ +package require vtk +package require vtkinteraction + +vtkMesaFreeTypeTextMapper textMapper + textMapper SetInput "This is VTK" + +set tprop [textMapper GetTextProperty] + $tprop SetFontSize 25 + $tprop SetFontFamilyToArial + $tprop SetJustificationToCentered + $tprop BoldOn + $tprop ItalicOn + $tprop ShadowOn + $tprop SetColor 0 0 1 + +vtkScaledTextActor textActor + textActor SetMapper textMapper + textActor SetPosition 0.2 0.2 + textActor SetPosition2 0.6 0.6 + +vtkMesaRenderer ren1 + +vtkXMesaRenderWindow renWin + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor2D textActor + +ren1 SetBackground 0.8 0.5 0.3 +renWin SetSize 250 125 + +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the tk window +wm withdraw . diff --git a/Rendering/Testing/Tcl/ScalarBar.tcl b/Rendering/Testing/Tcl/ScalarBar.tcl new file mode 100644 index 0000000..351a12c --- /dev/null +++ b/Rendering/Testing/Tcl/ScalarBar.tcl @@ -0,0 +1,82 @@ +package require vtk +package require vtkinteraction + +# create pipeline +# +# create sphere to color +vtkSphereSource sphere + sphere SetThetaResolution 20 + sphere SetPhiResolution 40 + + +proc colorCells {} { + vtkMath randomColorGenerator + set input [randomColors GetInput] + set output [randomColors GetOutput] + set numCells [$input GetNumberOfCells] + vtkFloatArray colors + colors SetNumberOfTuples $numCells + + for {set i 0} {$i < $numCells} {incr i} { + colors SetValue $i [randomColorGenerator Random 0 1] + } + + [$output GetCellData] CopyScalarsOff + [$output GetCellData] PassData [$input GetCellData] + [$output GetCellData] SetScalars colors + + colors Delete; #reference counting - it's ok + randomColorGenerator Delete +} + +# Compute random scalars (colors) for each cell +vtkProgrammableAttributeDataFilter randomColors + randomColors SetInputConnection [sphere GetOutputPort] + randomColors SetExecuteMethod colorCells + +# mapper and actor +vtkPolyDataMapper mapper + mapper SetInput [randomColors GetPolyDataOutput] + eval mapper SetScalarRange [[randomColors GetPolyDataOutput] GetScalarRange] +vtkActor sphereActor + sphereActor SetMapper mapper + +# Create a scalar bar +vtkScalarBarActor scalarBar + scalarBar SetLookupTable [mapper GetLookupTable] + scalarBar SetTitle "Temperature" + [scalarBar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport + [scalarBar GetPositionCoordinate] SetValue 0.1 0.01 + scalarBar SetOrientationToHorizontal + scalarBar SetWidth 0.8 + scalarBar SetHeight 0.17 + +# Test the Get/Set Position +eval scalarBar SetPosition [scalarBar GetPosition] + +# Create graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor sphereActor +ren1 AddActor2D scalarBar +renWin SetSize 350 350 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render +scalarBar SetNumberOfLabels 8 +renWin Render + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Rendering/Testing/Tcl/TestBunykRayCastFunction.tcl b/Rendering/Testing/Tcl/TestBunykRayCastFunction.tcl new file mode 100644 index 0000000..fb1a7fb --- /dev/null +++ b/Rendering/Testing/Tcl/TestBunykRayCastFunction.tcl @@ -0,0 +1,103 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create the reader for the data +# This is the data the will be volume rendered +vtkStructuredPointsReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +# create a reader for the other data that will +# be contoured and displayed as a polygonal mesh +vtkSLCReader reader2 + reader2 SetFileName "$VTK_DATA_ROOT/Data/neghip.slc" + +# convert from vtkImageData to vtkUnstructuredGrid, remove +# any cells where all values are below 80 +vtkThreshold thresh + thresh ThresholdByUpper 80 + thresh AllScalarsOff + thresh SetInputConnection [reader GetOutputPort] + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [thresh GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 80 0.0 + opacityTransferFunction AddPoint 120 0.2 + opacityTransferFunction AddPoint 255 0.2 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 80.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 120.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 160.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 200.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 1.0 1.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + +# The mapper / ray cast function know how to render the data +vtkUnstructuredGridVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# contour the second dataset +vtkContourFilter contour + contour SetValue 0 80 + contour SetInputConnection [reader2 GetOutputPort] + +# create a mapper for the polygonal data +vtkPolyDataMapper mapper + mapper SetInputConnection [contour GetOutputPort] + mapper ScalarVisibilityOff + +# create an actor for the polygonal data +vtkActor actor + actor SetMapper mapper + +ren1 AddViewProp actor + +ren1 AddVolume volume +renWin SetSize 300 300 + +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 10.0 +[ren1 GetActiveCamera] Zoom 1.5 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/TestFlyTo.tcl b/Rendering/Testing/Tcl/TestFlyTo.tcl new file mode 100644 index 0000000..cfa0eca --- /dev/null +++ b/Rendering/Testing/Tcl/TestFlyTo.tcl @@ -0,0 +1,61 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a sphere source and actor +# +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper +eval [sphereActor GetProperty] SetDiffuseColor $banana +eval [sphereActor GetProperty] SetSpecular .4 +eval [sphereActor GetProperty] SetSpecularPower 20 + +# create the spikes using a cone source and the sphere source +# +vtkConeSource cone + cone SetResolution 20 +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] +vtkLODActor spikeActor + spikeActor SetMapper spikeMapper +eval [spikeActor GetProperty] SetDiffuseColor $tomato +eval [spikeActor GetProperty] SetSpecular .4 +eval [spikeActor GetProperty] SetSpecularPower 20 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor sphereActor +ren1 AddActor spikeActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +$cam1 Azimuth 30 +$cam1 Elevation 30 +renWin Render + +iren FlyTo ren1 0.37723 0.154699 0.204326 + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Rendering/Testing/Tcl/TestFreetypeTextMapper.tcl b/Rendering/Testing/Tcl/TestFreetypeTextMapper.tcl new file mode 100644 index 0000000..3da4ceb --- /dev/null +++ b/Rendering/Testing/Tcl/TestFreetypeTextMapper.tcl @@ -0,0 +1,76 @@ +package require vtk +package require vtkinteraction + +set current_font_size 16 + +set default_text "ABCDEFGHIJKLMnopqrstuvwxyz 0123456789 !@#$%()-=_+[]{};:,./<>?" + +set text_color [list [expr 246 / 255.0] [expr 255 / 255.0] [expr 11 / 255.0]] +set bg_color [list [expr 56 / 255.0] [expr 56 / 255.0] [expr 154 / 255.0]] + +vtkRenderWindow renWin + renWin SetSize 790 351 + +vtkRenderer ren1 + eval ren1 SetBackground $bg_color + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set i 0 + +foreach family { + Arial + Courier + Times +} { + foreach {bold italic shadow} { + 0 0 0 + 0 0 1 + 1 0 0 + 0 1 0 + 1 1 0 + } { + incr i + + set attribs {} + if {$bold} { + lappend attribs "b" + } + if {$italic} { + lappend attribs "i" + } + if {$shadow} { + lappend attribs "s" + } + set face_name "$family" + if {[llength $attribs]} { + set face_name "$face_name ([join $attribs ,])" + } + + set mapper [vtkOpenGLFreeTypeTextMapper mapper_${family}_${bold}_${italic}_${shadow}] + $mapper SetInput "$face_name: $default_text" + + set tprop [$mapper GetTextProperty] + eval $tprop SetFontFamilyTo$family + eval $tprop SetColor $text_color + $tprop SetBold $bold + $tprop SetItalic $italic + $tprop SetShadow $shadow + $tprop SetFontSize $current_font_size + + set actor [vtkActor2D actor_${family}_${bold}_${italic}_${shadow}] + $actor SetMapper $mapper + $actor SetDisplayPosition 10 [expr $i * ($current_font_size + 5)] + + ren1 AddActor $actor + } +} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Rendering/Testing/Tcl/TestFreetypeTextMapperBigger.tcl b/Rendering/Testing/Tcl/TestFreetypeTextMapperBigger.tcl new file mode 100644 index 0000000..641afc4 --- /dev/null +++ b/Rendering/Testing/Tcl/TestFreetypeTextMapperBigger.tcl @@ -0,0 +1,70 @@ +package require vtk +package require vtkinteraction + +set current_font_size 55 + +set default_text "MmNnKk @" + +set text_color [list [expr 246 / 255.0] [expr 255 / 255.0] [expr 11 / 255.0]] +set bg_color [list [expr 56 / 255.0] [expr 56 / 255.0] [expr 154 / 255.0]] + +vtkRenderWindow renWin + renWin SetSize 790 450 + +vtkRenderer ren1 + eval ren1 SetBackground $bg_color + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set i 0 + +foreach family { + Arial + Courier + Times +} { + foreach {bold italic} { + 0 0 + 1 1 + } { + incr i + + set attribs {} + if {$bold} { + lappend attribs "b" + } + if {$italic} { + lappend attribs "i" + } + set face_name "$family" + if {[llength $attribs]} { + set face_name "$face_name ([join $attribs ,])" + } + + set mapper [vtkOpenGLFreeTypeTextMapper mapper_${family}_${bold}_${italic}] + $mapper SetInput "$face_name: $default_text" + + set tprop [$mapper GetTextProperty] + eval $tprop SetFontFamilyTo$family + eval $tprop SetColor $text_color + $tprop SetBold $bold + $tprop SetItalic $italic + $tprop SetShadow 1 + $tprop SetFontSize $current_font_size + + set actor [vtkActor2D actor_${family}_${bold}_${italic}] + $actor SetMapper $mapper + $actor SetDisplayPosition 10 [expr $i * ($current_font_size + 5)] + + ren1 AddActor $actor + } +} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Rendering/Testing/Tcl/TestFreetypeTextOverlay.tcl b/Rendering/Testing/Tcl/TestFreetypeTextOverlay.tcl new file mode 100644 index 0000000..d7ca856 --- /dev/null +++ b/Rendering/Testing/Tcl/TestFreetypeTextOverlay.tcl @@ -0,0 +1,89 @@ +package require vtk +package require vtkinteraction + +set current_font_size 16 + +set default_text "ABCDEFGHIJKLMnopqrstuvwxyz" + +set text_color [list [expr 246 / 255.0] [expr 255 / 255.0] [expr 11 / 255.0]] +set bg_color [list [expr 56 / 255.0] [expr 56 / 255.0] [expr 154 / 255.0]] + +vtkRenderWindow renWin + renWin SetSize 386 120 + +vtkRenderer ren1 + eval ren1 SetBackground $bg_color + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +set i 0 + +# another actor to test occlusion +vtkPlaneSource plane +plane SetOrigin 120 10 0 +plane SetPoint1 220 10 0 +plane SetPoint2 120 110 0 + +vtkPolyDataMapper2D mapper +mapper SetInputConnection [plane GetOutputPort] + +vtkActor2D actor +actor SetMapper mapper +[actor GetProperty] SetColor 0.5 0.5 0.5 + +ren1 AddActor actor + +foreach family { + Arial +} { + foreach {bold italic shadow} { + 0 0 0 + 0 0 1 + 1 0 0 + 0 1 0 + 1 1 0 + } { + incr i + + set attribs {} + if {$bold} { + lappend attribs "b" + } + if {$italic} { + lappend attribs "i" + } + if {$shadow} { + lappend attribs "s" + } + set face_name "$family" + if {[llength $attribs]} { + set face_name "$face_name ([join $attribs ,])" + } + + set mapper [vtkOpenGLFreeTypeTextMapper mapper_${family}_${bold}_${italic}_${shadow}] + $mapper SetInput "$face_name: $default_text" + + set tprop [$mapper GetTextProperty] + eval $tprop SetFontFamilyTo$family + eval $tprop SetColor $text_color + $tprop SetBold $bold + $tprop SetItalic $italic + $tprop SetShadow $shadow + $tprop SetFontSize $current_font_size + + set actor [vtkActor2D actor_${family}_${bold}_${italic}_${shadow}] + $actor SetMapper $mapper + $actor SetDisplayPosition 10 [expr $i * ($current_font_size + 5)] + + ren1 AddActor $actor + } +} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Rendering/Testing/Tcl/TestHomogeneousRayIntegration.tcl b/Rendering/Testing/Tcl/TestHomogeneousRayIntegration.tcl new file mode 100644 index 0000000..6dc7530 --- /dev/null +++ b/Rendering/Testing/Tcl/TestHomogeneousRayIntegration.tcl @@ -0,0 +1,86 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create a small mesh. The coarser and more opaque the mesh, the easier it +# is to see rendering errors. +vtkImageMandelbrotSource input + input SetWholeExtent 0 2 0 2 0 2 + input SetSizeCX 2 2 2 2 + input SetMaximumNumberOfIterations 10 + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [input GetOutputPort] + +# Convert it to cell centered data. +vtkPointDataToCellData celldata + celldata SetInputConnection [trifilter GetOutputPort] + celldata PassPointDataOff + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 10 1.0 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0 1.0 0.0 1.0 + colorTransferFunction AddRGBPoint 2 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 4 0.0 1.0 1.0 + colorTransferFunction AddRGBPoint 6 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 8 1.0 1.0 0.0 + colorTransferFunction AddRGBPoint 10 1.0 0.0 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + volumeProperty SetScalarOpacityUnitDistance 0.75 + +# The mapper / ray cast function / ray integrator know how to render the data +vtkUnstructuredGridVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [celldata GetOutputPort] + +vtkUnstructuredGridLinearRayIntegrator rayIntegrator + volumeMapper SetRayIntegrator rayIntegrator + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +renWin SetSize 300 300 + +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 15.0 +[ren1 GetActiveCamera] Zoom 1.5 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/TestInteractorStyleTerrain.tcl b/Rendering/Testing/Tcl/TestInteractorStyleTerrain.tcl new file mode 100644 index 0000000..c846bdf --- /dev/null +++ b/Rendering/Testing/Tcl/TestInteractorStyleTerrain.tcl @@ -0,0 +1,93 @@ +package require vtk +package require vtkinteraction + +set Scale 5 +vtkLookupTable lut + lut SetHueRange 0.6 0 + lut SetSaturationRange 1.0 0 + lut SetValueRange 0.5 1.0 + +vtkDEMReader demModel + demModel SetFileName $VTK_DATA_ROOT/Data/SainteHelens.dem + demModel Update + +demModel Print + +set lo [expr $Scale * [lindex [demModel GetElevationBounds] 0]] +set hi [expr $Scale * [lindex [demModel GetElevationBounds] 1]] + +vtkLODActor demActor + +# create a pipeline for each lod mapper +vtkImageShrink3D shrink16 + shrink16 SetShrinkFactors 16 16 1 + shrink16 SetInputConnection [demModel GetOutputPort] + shrink16 AveragingOn + +vtkImageDataGeometryFilter geom16 + geom16 SetInputConnection [shrink16 GetOutputPort] + geom16 ReleaseDataFlagOn + +vtkWarpScalar warp16 + warp16 SetInputConnection [geom16 GetOutputPort] + warp16 SetNormal 0 0 1 + warp16 UseNormalOn + warp16 SetScaleFactor $Scale + warp16 ReleaseDataFlagOn + +vtkElevationFilter elevation16 + elevation16 SetInputConnection [warp16 GetOutputPort] + elevation16 SetLowPoint 0 0 $lo + elevation16 SetHighPoint 0 0 $hi +eval elevation16 SetScalarRange $lo $hi + elevation16 ReleaseDataFlagOn + +vtkPolyDataNormals normals16 + normals16 SetInput [elevation16 GetPolyDataOutput] + normals16 SetFeatureAngle 60 + normals16 ConsistencyOff + normals16 SplittingOff + normals16 ReleaseDataFlagOn + +vtkPolyDataMapper demMapper16 + demMapper16 SetInputConnection [normals16 GetOutputPort] + eval demMapper16 SetScalarRange $lo $hi + demMapper16 SetLookupTable lut + demMapper16 ImmediateModeRenderingOn + +demMapper16 Update +demActor AddLODMapper demMapper16 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +vtkInteractorStyleTerrain t +iren SetInteractorStyle t + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor demActor +ren1 SetBackground .4 .4 .4 + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren SetDesiredUpdateRate 1 + +wm withdraw . +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +[ren1 GetActiveCamera] SetViewUp 0 0 1 +[ren1 GetActiveCamera] SetPosition -99900 -21354 131801 +[ren1 GetActiveCamera] SetFocalPoint 41461 41461 2815 +ren1 ResetCamera +[ren1 GetActiveCamera] Dolly 1.2 +ren1 ResetCameraClippingRange + +renWin Render diff --git a/Rendering/Testing/Tcl/TestLinearRayIntegration.tcl b/Rendering/Testing/Tcl/TestLinearRayIntegration.tcl new file mode 100644 index 0000000..49460ac --- /dev/null +++ b/Rendering/Testing/Tcl/TestLinearRayIntegration.tcl @@ -0,0 +1,81 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create a small mesh. The coarser and more opaque the mesh, the easier it +# is to see rendering errors. +vtkImageMandelbrotSource input + input SetWholeExtent 0 2 0 2 0 2 + input SetSizeCX 2 2 2 2 + input SetMaximumNumberOfIterations 10 + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [input GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 10 1.0 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0 1.0 0.0 1.0 + colorTransferFunction AddRGBPoint 2 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 4 0.0 1.0 1.0 + colorTransferFunction AddRGBPoint 6 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 8 1.0 1.0 0.0 + colorTransferFunction AddRGBPoint 10 1.0 0.0 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + volumeProperty SetScalarOpacityUnitDistance 0.75 + +# The mapper / ray cast function / ray integrator know how to render the data +vtkUnstructuredGridVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +vtkUnstructuredGridLinearRayIntegrator rayIntegrator + volumeMapper SetRayIntegrator rayIntegrator + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +renWin SetSize 300 300 + +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 15.0 +[ren1 GetActiveCamera] Zoom 1.2 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/TestOnePoint.tcl b/Rendering/Testing/Tcl/TestOnePoint.tcl new file mode 100644 index 0000000..408ad93 --- /dev/null +++ b/Rendering/Testing/Tcl/TestOnePoint.tcl @@ -0,0 +1,39 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +vtkPoints points + points InsertPoint 0 0.0 0.0 0.0 + +vtkCellArray verts + verts InsertNextCell 1 + verts InsertCellPoint 0 + +vtkPolyData polyData + polyData SetPoints points + polyData SetVerts verts + +vtkPolyDataMapper mapper + mapper SetInput polyData + +vtkActor actor + actor SetMapper mapper + [actor GetProperty] SetPointSize 8 + +ren1 AddViewProp actor + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + + diff --git a/Rendering/Testing/Tcl/TestParallelCoordinates.tcl b/Rendering/Testing/Tcl/TestParallelCoordinates.tcl new file mode 100644 index 0000000..b3755e8 --- /dev/null +++ b/Rendering/Testing/Tcl/TestParallelCoordinates.tcl @@ -0,0 +1,44 @@ +package require vtk +package require vtkinteraction + +# This example converts data to a field and then displays it using +# parallel coordinates, + +# Create a reader and write out the field +vtkUnstructuredGridReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/blow.vtk" + reader SetVectorsName "displacement9" + reader SetScalarsName "thickness9" +vtkDataSetToDataObjectFilter ds2do + ds2do SetInputConnection [reader GetOutputPort] +vtkParallelCoordinatesActor actor + actor SetInput [ds2do GetOutput] + actor SetTitle "Parallel Coordinates Plot of blow.tcl" + actor SetIndependentVariablesToColumns + [actor GetPositionCoordinate] SetValue 0.05 0.05 0.0 + [actor GetPosition2Coordinate] SetValue 0.95 0.85 0.0 + [actor GetProperty] SetColor 1 0 0 + # Set text colors (same as actor for backward compat with test) + [actor GetTitleTextProperty] SetColor 1 0 0 + [actor GetLabelTextProperty] SetColor 1 0 0 + +# Create the RenderWindow, Renderer and both Actors +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor actor +ren1 SetBackground 1 1 1 +renWin SetSize 500 200 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Rendering/Testing/Tcl/TestPartialPreIntegration.tcl b/Rendering/Testing/Tcl/TestPartialPreIntegration.tcl new file mode 100644 index 0000000..62082e7 --- /dev/null +++ b/Rendering/Testing/Tcl/TestPartialPreIntegration.tcl @@ -0,0 +1,81 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create a small mesh. The coarser and more opaque the mesh, the easier it +# is to see rendering errors. +vtkImageMandelbrotSource input + input SetWholeExtent 0 2 0 2 0 2 + input SetSizeCX 2 2 2 2 + input SetMaximumNumberOfIterations 10 + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [input GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 10 1.0 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0 1.0 0.0 1.0 + colorTransferFunction AddRGBPoint 2 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 4 0.0 1.0 1.0 + colorTransferFunction AddRGBPoint 6 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 8 1.0 1.0 0.0 + colorTransferFunction AddRGBPoint 10 1.0 0.0 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + volumeProperty SetScalarOpacityUnitDistance 0.75 + +# The mapper / ray cast function / ray integrator know how to render the data +vtkUnstructuredGridVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +vtkUnstructuredGridPartialPreIntegration rayIntegrator + volumeMapper SetRayIntegrator rayIntegrator + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +renWin SetSize 300 300 + +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 15.0 +[ren1 GetActiveCamera] Zoom 1.2 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/TestPreIntegration.tcl b/Rendering/Testing/Tcl/TestPreIntegration.tcl new file mode 100644 index 0000000..fe6ed36 --- /dev/null +++ b/Rendering/Testing/Tcl/TestPreIntegration.tcl @@ -0,0 +1,81 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create a small mesh. The coarser and more opaque the mesh, the easier it +# is to see rendering errors. +vtkImageMandelbrotSource input + input SetWholeExtent 0 2 0 2 0 2 + input SetSizeCX 2 2 2 2 + input SetMaximumNumberOfIterations 10 + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [input GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 10 1.0 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0 1.0 0.0 1.0 + colorTransferFunction AddRGBPoint 2 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 4 0.0 1.0 1.0 + colorTransferFunction AddRGBPoint 6 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 8 1.0 1.0 0.0 + colorTransferFunction AddRGBPoint 10 1.0 0.0 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + volumeProperty SetScalarOpacityUnitDistance 0.75 + +# The mapper / ray cast function / ray integrator know how to render the data +vtkUnstructuredGridVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +vtkUnstructuredGridPreIntegration rayIntegrator + volumeMapper SetRayIntegrator rayIntegrator + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +renWin SetSize 300 300 + +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 15.0 +[ren1 GetActiveCamera] Zoom 1.5 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/TestShearWarpComposite.tcl b/Rendering/Testing/Tcl/TestShearWarpComposite.tcl new file mode 100644 index 0000000..bb81378 --- /dev/null +++ b/Rendering/Testing/Tcl/TestShearWarpComposite.tcl @@ -0,0 +1,74 @@ +# This is a simple volume rendering example that +# uses a vtkVolumeRayCast mapper + +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create the reader for the data +vtkStructuredPointsReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 20 0.0 + opacityTransferFunction AddPoint 255 0.2 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOn + volumeProperty SetInterpolationTypeToLinear + +# The mapper / ray cast function know how to render the data +vtkOpenGLVolumeShearWarpMapper volumeMapper + volumeMapper SetInputConnection [reader GetOutputPort] + volumeMapper FastClassificationOn + volumeMapper SetFunctionTypeToComposite + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + + vtkCamera cam + cam ParallelProjectionOn + +ren1 SetActiveCamera cam +ren1 AddVolume volume +ren1 SetBackground 1 1 1 +renWin SetSize 600 600 + +ren1 ResetCamera +renWin Render + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/TestShearWarpMip.tcl b/Rendering/Testing/Tcl/TestShearWarpMip.tcl new file mode 100644 index 0000000..44b5cb4 --- /dev/null +++ b/Rendering/Testing/Tcl/TestShearWarpMip.tcl @@ -0,0 +1,85 @@ +# This is a simple volume rendering example that +# uses a vtkVolumeRayCast mapper + +package require vtk +package require vtkinteraction + +# Simple volume rendering example. +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff +reader SetDataSpacing 2 2 1 +reader SetDataScalarTypeToUnsignedShort +reader Update + +[reader GetOutput] SetOrigin -63 -63 -46 + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 100 0.0 + opacityTransferFunction AddPoint 2000 1.0 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction ClampingOff + colorTransferFunction AddRGBPoint 0.0 1.00 0.0 0.0 + colorTransferFunction AddRGBPoint 1000.0 0.00 1.0 0.0 + colorTransferFunction AddRGBPoint 2000.0 0.00 0.0 1.0 + colorTransferFunction AddRGBPoint 3000.0 1.00 1.0 1.0 + colorTransferFunction AddRGBPoint 4000.0 1.00 1.0 1.0 +# colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOn + volumeProperty SetInterpolationTypeToLinear + +# The mapper / ray cast function know how to render the data +vtkOpenGLVolumeShearWarpMapper volumeMapper + volumeMapper SetInputConnection [reader GetOutputPort] + volumeMapper FastClassificationOff + volumeMapper SetFunctionTypeToMIP +volumeMapper IntermixIntersectingGeometryOn + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + + vtkCamera cam + cam ParallelProjectionOn + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetActiveCamera cam +#ren1 AddVolume volume +ren1 SetBackground 0.5 0.5 0.5 +renWin SetSize 600 600 + +ren1 AddVolume volume +ren1 ResetCamera +renWin Render + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/TestStyleBase.tcl b/Rendering/Testing/Tcl/TestStyleBase.tcl new file mode 100644 index 0000000..6408698 --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleBase.tcl @@ -0,0 +1,131 @@ +# Get random numbers + +vtkMath math +math RandomSeed 1 + +proc randint {min max} { + set f [math Random $min $max] + return [expr int($f)] +} + +# Main testing proc + +proc test_style {style} { + + # Event state to test + + set buttons { + Left + Middle + Right + } + + set ctrls { + 0 1 + } + + set shifts { + 0 1 + } + + # I do not trust timers while testing (since they trigger asynchronous + # rendering/interaction) + + set use_timers [$style GetUseTimers] + $style UseTimersOff + $style AutoAdjustCameraClippingRangeOn + + puts "Testing: [$style GetClassName]" + + set iren [$style GetInteractor] + set renwin [$iren GetRenderWindow] + + $renwin Render + + # Get renwin size and center + + set win_size [$renwin GetSize] + set win_center_x [expr [lindex $win_size 0] / 2.0] + set win_center_y [expr [lindex $win_size 1] / 2.0] + + vtkPropPicker pick + + set radius [expr 5 * (1 + $use_timers)] + + foreach ctrl $ctrls { + foreach shift $shifts { + puts -nonewline " - ctrl: $ctrl shift: $shift button:" + foreach button $buttons { + puts -nonewline " $button" + flush stdout + + # First try to find a starting position where an actor + # can be picked (not mandatory for trackball modes). + # Search in increasingly big area, until we reach win size + # in that case actors might not be on screen, so reset cam + + set search $radius + while {1} { + set start_x [randint [expr $win_center_x - $search] \ + [expr $win_center_x + $search]] + set start_y [randint [expr $win_center_x - $search] \ + [expr $win_center_x + $search]] + if {[pick PickProp $start_x $start_y ren1]} { + break + } else { + if {$search > $win_center_x || + $search > $win_center_y} { + puts " (resetting camera)" + ren1 ResetCamera + set search $radius + } else { + incr search 5 + } + } + } + + # Start by pressing the button + + $iren SetEventInformationFlipY \ + $start_x $start_y $ctrl $shift 0 0 0 + $iren InvokeEvent "${button}ButtonPressEvent" + + # puts " - Starting: [$iren GetEventPosition]" + + # Now move around (alternating left and right around + # the window center in order to compensate somehow). + + set sign 1 + for {set i 0} {$i < 2 + $use_timers} {incr i} { + set sign [expr $sign * -1] + set x [randint [expr $win_center_x + $radius * 2 * $sign] \ + [expr $win_center_y + $radius * $sign]] + set y [randint [expr $win_center_y + $radius * 2 * $sign] \ + [expr $win_center_y + $radius * $sign]] + $iren SetEventInformationFlipY $x $y $ctrl $shift 0 0 0 + # puts " - Moving: [$iren GetEventPosition] $ctrl $shift (was [$iren GetLastEventPosition])" + $iren InvokeEvent "MouseMoveEvent" + + # If this style use timers, run OnTimer multiple times + + if {$use_timers} { + for {set j 0} {$j < 10} {incr j} { + $iren InvokeEvent "TimerEvent" + } + } + $renwin Render + } + + # End by releasing the button + + $iren SetEventInformationFlipY $x $y $ctrl $shift 0 0 0 + $iren InvokeEvent "${button}ButtonReleaseEvent" + } + puts "." + } + } + + $style SetUseTimers $use_timers + + $renwin Render +} diff --git a/Rendering/Testing/Tcl/TestStyleBaseSpike.tcl b/Rendering/Testing/Tcl/TestStyleBaseSpike.tcl new file mode 100644 index 0000000..415cb98 --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleBaseSpike.tcl @@ -0,0 +1,73 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Common script code used to create sphere/glyph (spike) + +vtkRenderer ren1 + +vtkRenderWindow renWin + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate .00001 + iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Create a sphere source and actor + +vtkSphereSource sphere + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + +vtkLODActor sphereActor + sphereActor SetMapper sphereMapper + +eval [sphereActor GetProperty] SetDiffuseColor $banana +eval [sphereActor GetProperty] SetSpecular .4 +eval [sphereActor GetProperty] SetSpecularPower 20 + +# Create the spikes using a cone source and the sphere source + +vtkConeSource cone + cone SetResolution 20 + +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 + +vtkPolyDataMapper spikeMapper + spikeMapper SetInputConnection [glyph GetOutputPort] + +vtkLODActor spikeActor + spikeActor SetMapper spikeMapper + +eval [spikeActor GetProperty] SetDiffuseColor $tomato +eval [spikeActor GetProperty] SetSpecular .4 +eval [spikeActor GetProperty] SetSpecularPower 20 + +# Add the actors to the renderer, set the background and size + +ren1 AddActor sphereActor +ren1 AddActor spikeActor +ren1 SetBackground 0.1 0.2 0.4 + +renWin SetSize 300 300 + +# Render the image + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 Zoom 1.4 +$cam1 Azimuth 30 +$cam1 Elevation 30 + +renWin Render + +# Prevent the tk window from showing up then start the event loop + +wm withdraw . diff --git a/Rendering/Testing/Tcl/TestStyleJoystickActor.tcl b/Rendering/Testing/Tcl/TestStyleJoystickActor.tcl new file mode 100644 index 0000000..4334935 --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleJoystickActor.tcl @@ -0,0 +1,26 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Load base (spike and test) + +source [file join [file dirname [info script]] TestStyleBase.tcl] +source [file join [file dirname [info script]] TestStyleBaseSpike.tcl] + +# Set interactor style + +vtkInteractorStyleSwitch inStyle +iren SetInteractorStyle inStyle +iren Initialize + +# Switch to Joystick+Actor mode + +iren SetKeyEventInformation 0 0 j 0 0 +iren InvokeEvent "CharEvent" + +iren SetKeyEventInformation 0 0 a 0 0 +iren InvokeEvent "CharEvent" + +# Test style + +test_style [inStyle GetCurrentStyle] diff --git a/Rendering/Testing/Tcl/TestStyleJoystickCamera.tcl b/Rendering/Testing/Tcl/TestStyleJoystickCamera.tcl new file mode 100644 index 0000000..00ad11d --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleJoystickCamera.tcl @@ -0,0 +1,26 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Load base (spike and test) + +source [file join [file dirname [info script]] TestStyleBase.tcl] +source [file join [file dirname [info script]] TestStyleBaseSpike.tcl] + +# Set interactor style + +vtkInteractorStyleSwitch inStyle +iren SetInteractorStyle inStyle +iren Initialize + +# Switch to Joystick+Camera mode + +iren SetKeyEventInformation 0 0 j 0 0 +iren InvokeEvent "CharEvent" + +iren SetKeyEventInformation 0 0 c 0 0 +iren InvokeEvent "CharEvent" + +# Test style + +test_style [inStyle GetCurrentStyle] diff --git a/Rendering/Testing/Tcl/TestStyleRubberBandZoom.tcl b/Rendering/Testing/Tcl/TestStyleRubberBandZoom.tcl new file mode 100644 index 0000000..35c2349 --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleRubberBandZoom.tcl @@ -0,0 +1,36 @@ +package require vtk + +# Set up the pipeline + +vtkTIFFReader reader +reader SetFileName "$VTK_DATA_ROOT/Data/beach.tif" + +vtkImageActor ia +ia SetInput [reader GetOutput] + +vtkRenderer ren +ren AddActor ia + +vtkRenderWindow renWin +renWin AddRenderer ren +renWin SetSize 400 400 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +vtkInteractorStyleRubberBandZoom rbz +rbz SetInteractor iren + +iren SetInteractorStyle rbz + +renWin Render + +# Test style + +iren SetEventInformationFlipY 250 250 0 0 "0" 0 "0" +iren InvokeEvent "LeftButtonPressEvent" +iren SetEventInformationFlipY 100 100 0 0 "0" 0 "0" +iren InvokeEvent "MouseMoveEvent" +iren InvokeEvent "LeftButtonReleaseEvent" + +wm withdraw . diff --git a/Rendering/Testing/Tcl/TestStyleTerrain.tcl b/Rendering/Testing/Tcl/TestStyleTerrain.tcl new file mode 100644 index 0000000..ba57f18 --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleTerrain.tcl @@ -0,0 +1,18 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Load base (spike and test) + +source [file join [file dirname [info script]] TestStyleBase.tcl] +source [file join [file dirname [info script]] TestStyleBaseSpike.tcl] + +# Set interactor style + +vtkInteractorStyleTerrain inStyle +iren SetInteractorStyle inStyle +iren Initialize + +# Test style + +test_style inStyle diff --git a/Rendering/Testing/Tcl/TestStyleTrackballActor.tcl b/Rendering/Testing/Tcl/TestStyleTrackballActor.tcl new file mode 100644 index 0000000..5441467 --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleTrackballActor.tcl @@ -0,0 +1,26 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Load base (spike and test) + +source [file join [file dirname [info script]] TestStyleBase.tcl] +source [file join [file dirname [info script]] TestStyleBaseSpike.tcl] + +# Set interactor style + +vtkInteractorStyleSwitch inStyle +iren SetInteractorStyle inStyle +iren Initialize + +# Switch to Trackball+Actor mode + +iren SetKeyEventInformation 0 0 t 0 0 +iren InvokeEvent "CharEvent" + +iren SetKeyEventInformation 0 0 a 0 0 +iren InvokeEvent "CharEvent" + +# Test style + +test_style [inStyle GetCurrentStyle] diff --git a/Rendering/Testing/Tcl/TestStyleTrackballCamera.tcl b/Rendering/Testing/Tcl/TestStyleTrackballCamera.tcl new file mode 100644 index 0000000..67bb834 --- /dev/null +++ b/Rendering/Testing/Tcl/TestStyleTrackballCamera.tcl @@ -0,0 +1,26 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Load base (spike and test) + +source [file join [file dirname [info script]] TestStyleBase.tcl] +source [file join [file dirname [info script]] TestStyleBaseSpike.tcl] + +# Set interactor style + +vtkInteractorStyleSwitch inStyle +iren SetInteractorStyle inStyle +iren Initialize + +# Switch to Trackball+Camera mode + +iren SetKeyEventInformation 0 0 t 0 0 +iren InvokeEvent "CharEvent" + +iren SetKeyEventInformation 0 0 c 0 0 +iren InvokeEvent "CharEvent" + +# Test style + +test_style [inStyle GetCurrentStyle] diff --git a/Rendering/Testing/Tcl/TestTextActor3D.tcl b/Rendering/Testing/Tcl/TestTextActor3D.tcl new file mode 100644 index 0000000..a33c7ec --- /dev/null +++ b/Rendering/Testing/Tcl/TestTextActor3D.tcl @@ -0,0 +1,206 @@ +package require vtk +package require vtkinteraction + +# Renderer, renwin + +vtkRenderer ren1 +ren1 SetBackground 0.1 0.2 0.4 + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 600 600 + +# The Tk render widget + +set vtkw [vtkTkRenderWidget .ren -width 450 -height 450 -rw renWin] +::vtk::bind_tk_render_widget $vtkw + +[[renWin GetInteractor] GetInteractorStyle] SetCurrentStyleToTrackballCamera + +pack $vtkw -side left -fill both -expand yes + +# Base text property + +vtkTextProperty base_text_prop +base_text_prop SetFontSize 48 +base_text_prop ShadowOn +base_text_prop SetColor 1.0 0.0 0.0 +base_text_prop SetFontFamilyToArial + +set base_scale 0.0025 + +set base_text "This is a test" + +# The text actors + +set text_actors {} + +# Add a sphere + +proc add_sphere {} { + vtkSphereSource obj_source + + vtkPolyDataMapper obj_mapper + obj_mapper SetInputConnection [obj_source GetOutputPort] + + vtkActor obj_actor + obj_actor SetMapper obj_mapper + [obj_actor GetProperty] SetRepresentationToWireframe + + ren1 AddActor obj_actor +} + +# Add one text actor, centered + +proc add_one_text_actor {} { + global text_actors + + vtkTextActor3D ia + lappend text_actors ia + + set tprop [ia GetTextProperty] + $tprop ShallowCopy base_text_prop +} + +# Add many text actor + +proc add_many_text_actors {} { + global text_actors + + vtkColorTransferFunction lut + lut SetColorSpaceToHSV + lut AddRGBPoint 0.0 0.0 1.0 1.0 + lut AddRGBPoint 1.0 1.0 1.0 1.0 + + for {set i 0} {$i < 10} {incr i} { + set name "ia$i" + vtkTextActor3D $name + $name SetOrientation 0 [expr $i * 36] 0 + # $name SetPosition [expr cos($i * 0.0314)] 0 0 + lappend text_actors $name + + set tprop [$name GetTextProperty] + $tprop ShallowCopy base_text_prop + set value [expr $i / 10.0] + eval $tprop SetColor [lut GetColor $value] + } + + lut Delete +} + +set scale_length 200 +frame .controls -relief groove -bd 2 +pack .controls -padx 2 -pady 2 -anchor nw -side left -fill both -expand n + +# Add control of text + +set entry_text [entry .controls.text] + +$entry_text insert 0 "$base_text" + +pack $entry_text -padx 4 -pady 4 -side top -fill x -expand n + +bind $entry_text {update_text_actors 0} +bind $entry_text {update_text_actors 0} + +# Add control of orientation + +set scale_orientation [scale .controls.orientation \ + -from 0 -to 360 -res 1 \ + -length $scale_length \ + -orient horizontal \ + -label "Text orientation:" \ + -command update_text_actors] + +$scale_orientation set [base_text_prop GetOrientation] +pack $scale_orientation -side top -fill x -expand n + +# Add control of font size + +set scale_font_size [scale .controls.font_size \ + -from 5 -to 150 -res 1 \ + -length $scale_length \ + -orient horizontal \ + -label "Font Size:" \ + -command update_text_actors] + +$scale_font_size set [base_text_prop GetFontSize] +pack $scale_font_size -side top -fill x -expand n + +# Add control of scale + +set scale_scale [scale .controls.scale \ + -from 0 -to 100 -res 1 \ + -length $scale_length \ + -orient horizontal \ + -label "Actor scale:" \ + -command update_text_actors] + +$scale_scale set [expr $base_scale * 10000.0] +pack $scale_scale -side top -fill x -expand n + +# Add control of opacity + +set scale_opacity [scale .controls.opacity \ + -from 0.0 -to 1.0 -res 0.01 \ + -length $scale_length \ + -orient horizontal \ + -label "Text opacity:" \ + -command update_text_actors] + +$scale_opacity set [base_text_prop GetOpacity] +pack $scale_opacity -side top -fill x -expand n + +# Update all text actors + +proc update_text_actors {dummy} { + global scale_orientation scale_font_size scale_scale entry_text scale_opacity + set orientation [$scale_orientation get] + set font_size [$scale_font_size get] + set scale [expr [$scale_scale get] / 10000.0] + set text [$entry_text get] + set opacity [$scale_opacity get] + + global text_actors + set i 0 + foreach actor $text_actors { + $actor SetScale $scale + $actor SetInput "$text" + set tprop [$actor GetTextProperty] + $tprop SetFontSize $font_size + $tprop SetOrientation $orientation + $tprop SetOpacity $opacity + incr i + } + + renWin Render +} + +# Create and add all text actors + +if {0} { + add_sphere + add_one_text_actor + ren1 ResetCamera +} { + add_many_text_actors + ren1 ResetCamera + + set cam [ren1 GetActiveCamera] + $cam Elevation 30 + $cam Dolly 0.4 +} + +update_text_actors 0 + +foreach actor $text_actors { + ren1 AddActor $actor +} + +# Interact + +renWin Render + +wm protocol . WM_DELETE_WINDOW ::vtk::cb_exit +tkwait window . +vtkCommand DeleteAllObject diff --git a/Rendering/Testing/Tcl/TestTiling.tcl b/Rendering/Testing/Tcl/TestTiling.tcl new file mode 100644 index 0000000..6420b98 --- /dev/null +++ b/Rendering/Testing/Tcl/TestTiling.tcl @@ -0,0 +1,115 @@ +package require vtk +package require vtkinteraction + +# create pipeline +# +# create sphere to color +vtkSphereSource sphere + sphere SetThetaResolution 20 + sphere SetPhiResolution 40 + + +proc colorCells {} { + vtkMath randomColorGenerator + set input [randomColors GetInput] + set output [randomColors GetOutput] + set numCells [$input GetNumberOfCells] + vtkFloatArray colors + colors SetNumberOfTuples $numCells + + for {set i 0} {$i < $numCells} {incr i} { + colors SetValue $i [randomColorGenerator Random 0 1] + } + + [$output GetCellData] CopyScalarsOff + [$output GetCellData] PassData [$input GetCellData] + [$output GetCellData] SetScalars colors + + colors Delete; #reference counting - it's ok + randomColorGenerator Delete +} + +# Compute random scalars (colors) for each cell +vtkProgrammableAttributeDataFilter randomColors + randomColors SetInputConnection [sphere GetOutputPort] + randomColors SetExecuteMethod colorCells + +# mapper and actor +vtkPolyDataMapper mapper + mapper SetInput [randomColors GetPolyDataOutput] + eval mapper SetScalarRange [[randomColors GetPolyDataOutput] GetScalarRange] +vtkActor sphereActor + sphereActor SetMapper mapper + +# Create a scalar bar +vtkScalarBarActor scalarBar + scalarBar SetLookupTable [mapper GetLookupTable] + scalarBar SetTitle "Temperature" + [scalarBar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport + [scalarBar GetPositionCoordinate] SetValue 0.1 0.05 + scalarBar SetOrientationToVertical + scalarBar SetWidth 0.8 + scalarBar SetHeight 0.9 + scalarBar SetLabelFormat "%-#6.3f" + +# Test the Get/Set Position +eval scalarBar SetPosition [scalarBar GetPosition] + +# Create graphics stuff +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 AddActor sphereActor +ren2 AddActor2D scalarBar +renWin SetSize 160 160 +ren1 SetViewport 0 0 0.75 1.0 +ren2 SetViewport 0.75 0 1.0 1.0 +ren2 SetBackground 0.3 0.3 0.3 + +# render the image +# +renWin Render +scalarBar SetNumberOfLabels 8 +renWin Render + + +vtkWindowToImageFilter w2i +w2i SetInput renWin +w2i SetMagnification 2 +w2i Update + +# copy the output +set outputData [[w2i GetOutput] NewInstance] +$outputData DeepCopy [w2i GetOutput] + +vtkImageMapper ia +ia SetInput $outputData +scalarBar ReleaseGraphicsResources renWin +sphereActor ReleaseGraphicsResources renWin +ia SetColorWindow 255 +ia SetColorLevel 127.5 + +vtkActor2D ia2 +ia2 SetMapper ia + +renWin SetSize 320 320 +ren2 RemoveViewProp scalarBar +ren1 RemoveViewProp sphereActor +ren1 AddActor ia2 +renWin RemoveRenderer ren2 +ren1 SetViewport 0 0 1 1 + +renWin Render +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +$outputData UnRegister {} diff --git a/Rendering/Testing/Tcl/TestTriangleStripCellColor.tcl b/Rendering/Testing/Tcl/TestTriangleStripCellColor.tcl new file mode 100644 index 0000000..faf9dfd --- /dev/null +++ b/Rendering/Testing/Tcl/TestTriangleStripCellColor.tcl @@ -0,0 +1,43 @@ +package require vtk +package require vtkinteraction + +vtkSphereSource sphere + +vtkElevationFilter elevation +elevation SetInputConnection [sphere GetOutputPort] +elevation SetLowPoint -1 0 0 +elevation SetHighPoint 1 0 0 + +vtkPointDataToCellData p2c +p2c SetInputConnection [elevation GetOutputPort] + +vtkStripper stripper +stripper SetInputConnection [p2c GetOutputPort] +stripper PassCellDataAsFieldDataOn + +vtkPolyDataMapper sphereMapper +sphereMapper SetInputConnection [stripper GetOutputPort] +sphereMapper SelectColorArray "Elevation" +sphereMapper SetColorModeToMapScalars +sphereMapper SetScalarModeToUseFieldData +sphereMapper SetScalarRange 0.28 0.72 + +vtkActor sphereActor +sphereActor SetMapper sphereMapper +#interpolation must be set to flat for cell colors to work +#for triangle strips. +[sphereActor GetProperty] SetInterpolationToFlat + +vtkRenderer ren1 +ren1 AddActor sphereActor + +vtkRenderWindow renWin +renWin AddRenderer ren1 +renWin SetSize 200 200 + +vtkRenderWindowInteractor iren +iren SetRenderWindow renWin + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +renWin Render +wm withdraw . diff --git a/Rendering/Testing/Tcl/TestWindowToImageTransparency.tcl b/Rendering/Testing/Tcl/TestWindowToImageTransparency.tcl new file mode 100644 index 0000000..90db139 --- /dev/null +++ b/Rendering/Testing/Tcl/TestWindowToImageTransparency.tcl @@ -0,0 +1,63 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow and Renderer +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a default polygonal sphere +vtkSphereSource sphere +vtkPolyDataMapper sphmapper + sphmapper SetInputConnection [sphere GetOutputPort] +vtkActor sphactor + sphactor SetMapper sphmapper + +# Add the actors to the renderer, set the background to initial +# color (which is also transparent), set size. +ren1 AddActor sphactor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 256 256 + +# render first image +renWin Render + +# create window to image filter, grabbing RGB and alpha +vtkWindowToImageFilter w2i + w2i SetInput renWin + w2i SetInputBufferTypeToRGBA + +# grab window +w2i Update + +# set up mappers and actors to display the image +vtkImageMapper im + im SetColorWindow 255 + im SetColorLevel 127.5 + im SetInputConnection [w2i GetOutputPort] +vtkActor2D ia2 + ia2 SetMapper im + +# now, change the image (background is now green) +sphactor SetScale 2 2 2 +ren1 SetBackground 0 1 0 + +# add the image of the sphere (keeping the original sphere too) +ren1 AddActor ia2 +ren1 SetViewport 0 0 1 1 + +# render result (the polygonal sphere appears behind a smaller image +# of itself). Background of original image is transparent, so you +# can see through it back to the larger sphere and new background. + +renWin Render + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +# prevent the tk window from showing up then start the event loop +wm withdraw . + + + + diff --git a/Rendering/Testing/Tcl/TestZSweep.tcl b/Rendering/Testing/Tcl/TestZSweep.tcl new file mode 100644 index 0000000..b88214a --- /dev/null +++ b/Rendering/Testing/Tcl/TestZSweep.tcl @@ -0,0 +1,80 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create a small mesh. The coarser and more opaque the mesh, the easier it +# is to see rendering errors. +vtkImageMandelbrotSource input + input SetWholeExtent 0 2 0 2 0 2 + input SetSizeCX 2 2 2 2 + input SetMaximumNumberOfIterations 10 + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [input GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 10 1.0 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0 1.0 0.0 1.0 + colorTransferFunction AddRGBPoint 2 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 4 0.0 1.0 1.0 + colorTransferFunction AddRGBPoint 6 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 8 1.0 1.0 0.0 + colorTransferFunction AddRGBPoint 10 1.0 0.0 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + volumeProperty SetScalarOpacityUnitDistance 0.75 + +# The mapper / ray cast function / ray integrator know how to render the data +vtkUnstructuredGridVolumeZSweepMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +#vtkUnstructuredGridLinearRayIntegrator rayIntegrator +# volumeMapper SetRayIntegrator rayIntegrator +vtkUnstructuredGridPreIntegration rayIntegrator + volumeMapper SetRayIntegrator rayIntegrator + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +renWin SetSize 300 300 + +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 15.0 +[ren1 GetActiveCamera] Zoom 1.5 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . diff --git a/Rendering/Testing/Tcl/assembly.tcl b/Rendering/Testing/Tcl/assembly.tcl new file mode 100644 index 0000000..23b78d9 --- /dev/null +++ b/Rendering/Testing/Tcl/assembly.tcl @@ -0,0 +1,79 @@ +package require vtk +package require vtkinteraction + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create four parts: a top level assembly and three primitives +# +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +vtkActor sphereActor + sphereActor SetMapper sphereMapper + sphereActor SetOrigin 2 1 3 + sphereActor RotateY 6 + sphereActor SetPosition 2.25 0 0 + [sphereActor GetProperty] SetColor 1 0 1 + +vtkCubeSource cube +vtkPolyDataMapper cubeMapper + cubeMapper SetInputConnection [cube GetOutputPort] +vtkActor cubeActor + cubeActor SetMapper cubeMapper + cubeActor SetPosition 0.0 .25 0 + [cubeActor GetProperty] SetColor 0 0 1 + +vtkConeSource cone +vtkPolyDataMapper coneMapper + coneMapper SetInputConnection [cone GetOutputPort] +vtkActor coneActor + coneActor SetMapper coneMapper + coneActor SetPosition 0 0 .25 + [coneActor GetProperty] SetColor 0 1 0 + +vtkCylinderSource cylinder;#top part +vtkPolyDataMapper cylinderMapper + cylinderMapper SetInputConnection [cylinder GetOutputPort] + cylinderMapper SetResolveCoincidentTopologyToPolygonOffset +vtkActor cylinderActor + cylinderActor SetMapper cylinderMapper + [cylinderActor GetProperty] SetColor 1 0 0 + +vtkAssembly assembly + assembly AddPart cylinderActor + assembly AddPart sphereActor + assembly AddPart cubeActor + assembly AddPart coneActor + assembly SetOrigin 5 10 15 + assembly AddPosition 5 0 0 + assembly RotateX 15 + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor assembly +ren1 AddActor coneActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 200 200 + +# Get handles to some useful objects +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +vtkCamera camera + camera SetClippingRange 21.9464 30.0179 + camera SetFocalPoint 3.49221 2.28844 -0.970866 + camera SetPosition 3.49221 2.28844 24.5216 + camera SetViewAngle 30 + camera SetViewUp 0 1 0 +ren1 SetActiveCamera camera +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Rendering/Testing/Tcl/cells.tcl b/Rendering/Testing/Tcl/cells.tcl new file mode 100644 index 0000000..9483a0b --- /dev/null +++ b/Rendering/Testing/Tcl/cells.tcl @@ -0,0 +1,748 @@ +package require vtk +package require vtkinteraction + +# Demonstrates all cell types +# +# NOTE: the use of NewInstance/DeepCopy is included to increase +# regression coverage. It is not required in most applications. + +vtkRenderer ren1 +# turn off all cullers +[ren1 GetCullers] RemoveAllItems + +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 300 150 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create a scene with one of each cell type + +# Voxel + +vtkPoints voxelPoints + voxelPoints SetNumberOfPoints 8 + voxelPoints InsertPoint 0 0 0 0 + voxelPoints InsertPoint 1 1 0 0 + voxelPoints InsertPoint 2 0 1 0 + voxelPoints InsertPoint 3 1 1 0 + voxelPoints InsertPoint 4 0 0 1 + voxelPoints InsertPoint 5 1 0 1 + voxelPoints InsertPoint 6 0 1 1 + voxelPoints InsertPoint 7 1 1 1 + +vtkVoxel aVoxel + [aVoxel GetPointIds] SetId 0 0 + [aVoxel GetPointIds] SetId 1 1 + [aVoxel GetPointIds] SetId 2 2 + [aVoxel GetPointIds] SetId 3 3 + [aVoxel GetPointIds] SetId 4 4 + [aVoxel GetPointIds] SetId 5 5 + [aVoxel GetPointIds] SetId 6 6 + [aVoxel GetPointIds] SetId 7 7 + +set bVoxel [aVoxel NewInstance] +$bVoxel DeepCopy aVoxel + +vtkUnstructuredGrid aVoxelGrid + aVoxelGrid Allocate 1 1 + aVoxelGrid InsertNextCell [aVoxel GetCellType] [aVoxel GetPointIds] + aVoxelGrid SetPoints voxelPoints + +vtkDataSetMapper aVoxelMapper +aVoxelMapper SetInput aVoxelGrid + +vtkActor aVoxelActor + aVoxelActor SetMapper aVoxelMapper + [aVoxelActor GetProperty] BackfaceCullingOn + +# Hexahedron + +vtkPoints hexahedronPoints + hexahedronPoints SetNumberOfPoints 8 + hexahedronPoints InsertPoint 0 0 0 0 + hexahedronPoints InsertPoint 1 1 0 0 + hexahedronPoints InsertPoint 2 1 1 0 + hexahedronPoints InsertPoint 3 0 1 0 + hexahedronPoints InsertPoint 4 0 0 1 + hexahedronPoints InsertPoint 5 1 0 1 + hexahedronPoints InsertPoint 6 1 1 1 + hexahedronPoints InsertPoint 7 0 1 1 + +vtkHexahedron aHexahedron + [aHexahedron GetPointIds] SetId 0 0 + [aHexahedron GetPointIds] SetId 1 1 + [aHexahedron GetPointIds] SetId 2 2 + [aHexahedron GetPointIds] SetId 3 3 + [aHexahedron GetPointIds] SetId 4 4 + [aHexahedron GetPointIds] SetId 5 5 + [aHexahedron GetPointIds] SetId 6 6 + [aHexahedron GetPointIds] SetId 7 7 + +set bHexahedron [aHexahedron NewInstance] +$bHexahedron DeepCopy aHexahedron + +vtkUnstructuredGrid aHexahedronGrid + aHexahedronGrid Allocate 1 1 + aHexahedronGrid InsertNextCell [aHexahedron GetCellType] [aHexahedron GetPointIds] + aHexahedronGrid SetPoints hexahedronPoints + +vtkDataSetMapper aHexahedronMapper + aHexahedronMapper SetInput aHexahedronGrid + +vtkActor aHexahedronActor + aHexahedronActor SetMapper aHexahedronMapper + aHexahedronActor AddPosition 2 0 0 + [aHexahedronActor GetProperty] BackfaceCullingOn + +# Tetra + +vtkPoints tetraPoints + tetraPoints SetNumberOfPoints 4 + tetraPoints InsertPoint 0 0 0 0 + tetraPoints InsertPoint 1 1 0 0 + tetraPoints InsertPoint 2 .5 1 0 + tetraPoints InsertPoint 3 .5 .5 1 + +vtkTetra aTetra + [aTetra GetPointIds] SetId 0 0 + [aTetra GetPointIds] SetId 1 1 + [aTetra GetPointIds] SetId 2 2 + [aTetra GetPointIds] SetId 3 3 + +set bTetra [aTetra NewInstance] +$bTetra DeepCopy aTetra + +vtkUnstructuredGrid aTetraGrid + aTetraGrid Allocate 1 1 + aTetraGrid InsertNextCell [aTetra GetCellType] [aTetra GetPointIds] + aTetraGrid SetPoints tetraPoints + +vtkUnstructuredGrid aTetraCopy + aTetraCopy ShallowCopy aTetraGrid + +vtkDataSetMapper aTetraMapper + aTetraMapper SetInput aTetraCopy + +vtkActor aTetraActor + aTetraActor SetMapper aTetraMapper + aTetraActor AddPosition 4 0 0 + [aTetraActor GetProperty] BackfaceCullingOn + +# Wedge + +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 6 + wedgePoints InsertPoint 0 0 1 0 + wedgePoints InsertPoint 1 0 0 0 + wedgePoints InsertPoint 2 0 .5 .5 + wedgePoints InsertPoint 3 1 1 0 + wedgePoints InsertPoint 4 1 0 0 + wedgePoints InsertPoint 5 1 .5 .5 + +vtkWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + +set bWedge [aWedge NewInstance] +$bWedge DeepCopy aWedge + +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + +vtkUnstructuredGrid aWedgeCopy + aWedgeCopy DeepCopy aWedgeGrid + +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeCopy + +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + aWedgeActor AddPosition 6 0 0 + [aWedgeActor GetProperty] BackfaceCullingOn + +# Pyramid + +vtkPoints pyramidPoints + pyramidPoints SetNumberOfPoints 5 + pyramidPoints InsertPoint 0 0 0 0 + pyramidPoints InsertPoint 1 1 0 0 + pyramidPoints InsertPoint 2 1 1 0 + pyramidPoints InsertPoint 3 0 1 0 + pyramidPoints InsertPoint 4 .5 .5 1 + +vtkPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + +set bPyramid [aPyramid NewInstance] +$bPyramid DeepCopy aPyramid + +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyramidPoints + +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid + +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + aPyramidActor AddPosition 8 0 0 + [aPyramidActor GetProperty] BackfaceCullingOn + +# Pixel + +vtkPoints pixelPoints + pixelPoints SetNumberOfPoints 4 + pixelPoints InsertPoint 0 0 0 0 + pixelPoints InsertPoint 1 1 0 0 + pixelPoints InsertPoint 2 0 1 0 + pixelPoints InsertPoint 3 1 1 0 + +vtkPixel aPixel + [aPixel GetPointIds] SetId 0 0 + [aPixel GetPointIds] SetId 1 1 + [aPixel GetPointIds] SetId 2 2 + [aPixel GetPointIds] SetId 3 3 + +set bPixel [aPixel NewInstance] +$bPixel DeepCopy aPixel + +vtkUnstructuredGrid aPixelGrid + aPixelGrid Allocate 1 1 + aPixelGrid InsertNextCell [aPixel GetCellType] [aPixel GetPointIds] + aPixelGrid SetPoints pixelPoints + +vtkDataSetMapper aPixelMapper + aPixelMapper SetInput aPixelGrid + +vtkActor aPixelActor + aPixelActor SetMapper aPixelMapper + aPixelActor AddPosition 0 0 2 + [aPixelActor GetProperty] BackfaceCullingOn + +# Quad + +vtkPoints quadPoints + quadPoints SetNumberOfPoints 4 + quadPoints InsertPoint 0 0 0 0 + quadPoints InsertPoint 1 1 0 0 + quadPoints InsertPoint 2 1 1 0 + quadPoints InsertPoint 3 0 1 0 + +vtkQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + +set bQuad [aQuad NewInstance] +$bQuad DeepCopy aQuad + +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid + +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + aQuadActor AddPosition 2 0 2 + [aQuadActor GetProperty] BackfaceCullingOn + +# Triangle + +vtkPoints trianglePoints + trianglePoints SetNumberOfPoints 3 + trianglePoints InsertPoint 0 0 0 0 + trianglePoints InsertPoint 1 1 0 0 + trianglePoints InsertPoint 2 .5 .5 0 + +vtkFloatArray triangleTCoords + triangleTCoords SetNumberOfComponents 2 + triangleTCoords SetNumberOfTuples 3 + triangleTCoords InsertTuple2 0 1 1 + triangleTCoords InsertTuple2 1 2 2 + triangleTCoords InsertTuple2 2 3 3 + +vtkTriangle aTriangle + [aTriangle GetPointIds] SetId 0 0 + [aTriangle GetPointIds] SetId 1 1 + [aTriangle GetPointIds] SetId 2 2 + +set bTriangle [aTriangle NewInstance] +$bTriangle DeepCopy aTriangle + +vtkUnstructuredGrid aTriangleGrid + aTriangleGrid Allocate 1 1 + aTriangleGrid InsertNextCell [aTriangle GetCellType] [aTriangle GetPointIds] + aTriangleGrid SetPoints trianglePoints + [aTriangleGrid GetPointData] SetTCoords triangleTCoords + +vtkDataSetMapper aTriangleMapper + aTriangleMapper SetInput aTriangleGrid + +vtkActor aTriangleActor + aTriangleActor SetMapper aTriangleMapper + aTriangleActor AddPosition 4 0 2 + [aTriangleActor GetProperty] BackfaceCullingOn + +# Polygon + +vtkPoints polygonPoints + polygonPoints SetNumberOfPoints 4 + polygonPoints InsertPoint 0 0 0 0 + polygonPoints InsertPoint 1 1 0 0 + polygonPoints InsertPoint 2 1 1 0 + polygonPoints InsertPoint 3 0 1 0 + +vtkPolygon aPolygon + [aPolygon GetPointIds] SetNumberOfIds 4 + [aPolygon GetPointIds] SetId 0 0 + [aPolygon GetPointIds] SetId 1 1 + [aPolygon GetPointIds] SetId 2 2 + [aPolygon GetPointIds] SetId 3 3 + +set bPolygon [aPolygon NewInstance] +$bPolygon DeepCopy aPolygon + +vtkUnstructuredGrid aPolygonGrid + aPolygonGrid Allocate 1 1 + aPolygonGrid InsertNextCell [aPolygon GetCellType] [aPolygon GetPointIds] + aPolygonGrid SetPoints polygonPoints + +vtkDataSetMapper aPolygonMapper + aPolygonMapper SetInput aPolygonGrid + +vtkActor aPolygonActor + aPolygonActor SetMapper aPolygonMapper + aPolygonActor AddPosition 6 0 2 + [aPolygonActor GetProperty] BackfaceCullingOn + +# Triangle Strip + +vtkPoints triangleStripPoints + triangleStripPoints SetNumberOfPoints 5 + triangleStripPoints InsertPoint 0 0 1 0 + triangleStripPoints InsertPoint 1 0 0 0 + triangleStripPoints InsertPoint 2 1 1 0 + triangleStripPoints InsertPoint 3 1 0 0 + triangleStripPoints InsertPoint 4 2 1 0 + +vtkFloatArray triangleStripTCoords + triangleStripTCoords SetNumberOfComponents 2 + triangleStripTCoords SetNumberOfTuples 3 + triangleStripTCoords InsertTuple2 0 1 1 + triangleStripTCoords InsertTuple2 1 2 2 + triangleStripTCoords InsertTuple2 2 3 3 + triangleStripTCoords InsertTuple2 3 4 4 + triangleStripTCoords InsertTuple2 4 5 5 + +vtkTriangleStrip aTriangleStrip + [aTriangleStrip GetPointIds] SetNumberOfIds 5 + [aTriangleStrip GetPointIds] SetId 0 0 + [aTriangleStrip GetPointIds] SetId 1 1 + [aTriangleStrip GetPointIds] SetId 2 2 + [aTriangleStrip GetPointIds] SetId 3 3 + [aTriangleStrip GetPointIds] SetId 4 4 + +set bTriangleStrip [aTriangleStrip NewInstance] +$bTriangleStrip DeepCopy aTriangleStrip + +vtkUnstructuredGrid aTriangleStripGrid + aTriangleStripGrid Allocate 1 1 + aTriangleStripGrid InsertNextCell [aTriangleStrip GetCellType] [aTriangleStrip GetPointIds] + aTriangleStripGrid SetPoints triangleStripPoints + [aTriangleStripGrid GetPointData] SetTCoords triangleStripTCoords + +vtkDataSetMapper aTriangleStripMapper + aTriangleStripMapper SetInput aTriangleStripGrid + +vtkActor aTriangleStripActor + aTriangleStripActor SetMapper aTriangleStripMapper + aTriangleStripActor AddPosition 8 0 2 + [aTriangleStripActor GetProperty] BackfaceCullingOn + +# Line + +vtkPoints linePoints + linePoints SetNumberOfPoints 2 + linePoints InsertPoint 0 0 0 0 + linePoints InsertPoint 1 1 1 0 + +vtkLine aLine + [aLine GetPointIds] SetId 0 0 + [aLine GetPointIds] SetId 1 1 + +set bLine [aLine NewInstance] +$bLine DeepCopy aLine + +vtkUnstructuredGrid aLineGrid + aLineGrid Allocate 1 1 + aLineGrid InsertNextCell [aLine GetCellType] [aLine GetPointIds] + aLineGrid SetPoints linePoints + +vtkDataSetMapper aLineMapper + aLineMapper SetInput aLineGrid + +vtkActor aLineActor + aLineActor SetMapper aLineMapper + aLineActor AddPosition 0 0 4 + [aLineActor GetProperty] BackfaceCullingOn + +# Poly line + +vtkPoints polyLinePoints + polyLinePoints SetNumberOfPoints 3 + polyLinePoints InsertPoint 0 0 0 0 + polyLinePoints InsertPoint 1 1 1 0 + polyLinePoints InsertPoint 2 1 0 0 + +vtkPolyLine aPolyLine + [aPolyLine GetPointIds] SetNumberOfIds 3 + [aPolyLine GetPointIds] SetId 0 0 + [aPolyLine GetPointIds] SetId 1 1 + [aPolyLine GetPointIds] SetId 2 2 + +set bPolyLine [aPolyLine NewInstance] +$bPolyLine DeepCopy aPolyLine + +vtkUnstructuredGrid aPolyLineGrid + aPolyLineGrid Allocate 1 1 + aPolyLineGrid InsertNextCell [aPolyLine GetCellType] [aPolyLine GetPointIds] + aPolyLineGrid SetPoints polyLinePoints + +vtkDataSetMapper aPolyLineMapper + aPolyLineMapper SetInput aPolyLineGrid + +vtkActor aPolyLineActor + aPolyLineActor SetMapper aPolyLineMapper + aPolyLineActor AddPosition 2 0 4 + [aPolyLineActor GetProperty] BackfaceCullingOn + +# Vertex + +vtkPoints vertexPoints + vertexPoints SetNumberOfPoints 1 + vertexPoints InsertPoint 0 0 0 0 + +vtkVertex aVertex + [aVertex GetPointIds] SetId 0 0 + +set bVertex [aVertex NewInstance] +$bVertex DeepCopy aVertex + +vtkUnstructuredGrid aVertexGrid + aVertexGrid Allocate 1 1 + aVertexGrid InsertNextCell [aVertex GetCellType] [aVertex GetPointIds] + aVertexGrid SetPoints vertexPoints + +vtkDataSetMapper aVertexMapper + aVertexMapper SetInput aVertexGrid + +vtkActor aVertexActor + aVertexActor SetMapper aVertexMapper + aVertexActor AddPosition 0 0 6 + [aVertexActor GetProperty] BackfaceCullingOn + +# Poly Vertex + +vtkPoints polyVertexPoints + polyVertexPoints SetNumberOfPoints 3 + polyVertexPoints InsertPoint 0 0 0 0 + polyVertexPoints InsertPoint 1 1 0 0 + polyVertexPoints InsertPoint 2 1 1 0 + +vtkPolyVertex aPolyVertex + [aPolyVertex GetPointIds] SetNumberOfIds 3 + [aPolyVertex GetPointIds] SetId 0 0 + [aPolyVertex GetPointIds] SetId 1 1 + [aPolyVertex GetPointIds] SetId 2 2 + +set bPolyVertex [aPolyVertex NewInstance] +$bPolyVertex DeepCopy aPolyVertex + +vtkUnstructuredGrid aPolyVertexGrid + aPolyVertexGrid Allocate 1 1 + aPolyVertexGrid InsertNextCell [aPolyVertex GetCellType] [aPolyVertex GetPointIds] + aPolyVertexGrid SetPoints polyVertexPoints + +vtkDataSetMapper aPolyVertexMapper + aPolyVertexMapper SetInput aPolyVertexGrid + +vtkActor aPolyVertexActor + aPolyVertexActor SetMapper aPolyVertexMapper + aPolyVertexActor AddPosition 2 0 6 + [aPolyVertexActor GetProperty] BackfaceCullingOn + +# Pentagonal prism + +vtkPoints pentaPoints + pentaPoints SetNumberOfPoints 10 + pentaPoints InsertPoint 0 0.25 0.0 0.0 + pentaPoints InsertPoint 1 0.75 0.0 0.0 + pentaPoints InsertPoint 2 1.0 0.5 0.0 + pentaPoints InsertPoint 3 0.5 1.0 0.0 + pentaPoints InsertPoint 4 0.0 0.5 0.0 + pentaPoints InsertPoint 5 0.25 0.0 1.0 + pentaPoints InsertPoint 6 0.75 0.0 1.0 + pentaPoints InsertPoint 7 1.0 0.5 1.0 + pentaPoints InsertPoint 8 0.5 1.0 1.0 + pentaPoints InsertPoint 9 0.0 0.5 1.0 + +vtkPentagonalPrism aPenta + [aPenta GetPointIds] SetId 0 0 + [aPenta GetPointIds] SetId 1 1 + [aPenta GetPointIds] SetId 2 2 + [aPenta GetPointIds] SetId 3 3 + [aPenta GetPointIds] SetId 4 4 + [aPenta GetPointIds] SetId 5 5 + [aPenta GetPointIds] SetId 6 6 + [aPenta GetPointIds] SetId 7 7 + [aPenta GetPointIds] SetId 8 8 + [aPenta GetPointIds] SetId 9 9 + +set bPenta [aPenta NewInstance] +$bPenta DeepCopy aPenta + +vtkUnstructuredGrid aPentaGrid + aPentaGrid Allocate 1 1 + aPentaGrid InsertNextCell [aPenta GetCellType] [aPenta GetPointIds] + aPentaGrid SetPoints pentaPoints + +vtkUnstructuredGrid aPentaCopy + aPentaCopy DeepCopy aPentaGrid + +vtkDataSetMapper aPentaMapper + aPentaMapper SetInput aPentaCopy + +vtkActor aPentaActor + aPentaActor SetMapper aPentaMapper + aPentaActor AddPosition 10 0 0 + [aPentaActor GetProperty] BackfaceCullingOn + +# Hexagonal prism + +vtkPoints hexaPoints + hexaPoints SetNumberOfPoints 12 + hexaPoints InsertPoint 0 0.0 0.0 0.0 + hexaPoints InsertPoint 1 0.5 0.0 0.0 + hexaPoints InsertPoint 2 1.0 0.5 0.0 + hexaPoints InsertPoint 3 1.0 1.0 0.0 + hexaPoints InsertPoint 4 0.5 1.0 0.0 + hexaPoints InsertPoint 5 0.0 0.5 0.0 + hexaPoints InsertPoint 6 0.0 0.0 1.0 + hexaPoints InsertPoint 7 0.5 0.0 1.0 + hexaPoints InsertPoint 8 1.0 0.5 1.0 + hexaPoints InsertPoint 9 1.0 1.0 1.0 + hexaPoints InsertPoint 10 0.5 1.0 1.0 + hexaPoints InsertPoint 11 0.0 0.5 1.0 + +vtkHexagonalPrism aHexa + [aHexa GetPointIds] SetId 0 0 + [aHexa GetPointIds] SetId 1 1 + [aHexa GetPointIds] SetId 2 2 + [aHexa GetPointIds] SetId 3 3 + [aHexa GetPointIds] SetId 4 4 + [aHexa GetPointIds] SetId 5 5 + [aHexa GetPointIds] SetId 6 6 + [aHexa GetPointIds] SetId 7 7 + [aHexa GetPointIds] SetId 8 8 + [aHexa GetPointIds] SetId 9 9 + [aHexa GetPointIds] SetId 10 10 + [aHexa GetPointIds] SetId 11 11 + +set bHexa [aHexa NewInstance] +$bHexa DeepCopy aHexa + +vtkUnstructuredGrid aHexaGrid + aHexaGrid Allocate 1 1 + aHexaGrid InsertNextCell [aHexa GetCellType] [aHexa GetPointIds] + aHexaGrid SetPoints hexaPoints + +vtkUnstructuredGrid aHexaCopy + aHexaCopy DeepCopy aHexaGrid + +vtkDataSetMapper aHexaMapper + aHexaMapper SetInput aHexaCopy + +vtkActor aHexaActor + aHexaActor SetMapper aHexaMapper + aHexaActor AddPosition 12 0 0 + [aHexaActor GetProperty] BackfaceCullingOn + +# RIB property + +if { [info command vtkRIBProperty] != "" } { +vtkRIBProperty aProperty + aProperty SetVariable Km float + aProperty SetSurfaceShader LGVeinedmarble + aProperty SetVariable veinfreq float + aProperty AddVariable warpfreq float + aProperty AddVariable veincolor color + aProperty AddParameter veinfreq 2 + aProperty AddParameter veincolor "1.0000 1.0000 0.9412" +vtkRIBProperty bProperty + bProperty SetVariable Km float + bProperty SetParameter Km 1.0 + bProperty SetDisplacementShader dented + bProperty SetSurfaceShader plastic +} else { + vtkProperty aProperty + vtkProperty bProperty +} +aTriangleActor SetProperty aProperty +aTriangleStripActor SetProperty bProperty + +ren1 SetBackground .1 .2 .4 + +ren1 AddActor aVoxelActor; [aVoxelActor GetProperty] SetDiffuseColor 1 0 0 +ren1 AddActor aHexahedronActor; [aHexahedronActor GetProperty] SetDiffuseColor 1 1 0 +ren1 AddActor aTetraActor; [aTetraActor GetProperty] SetDiffuseColor 0 1 0 +ren1 AddActor aWedgeActor; [aWedgeActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aPyramidActor; [aPyramidActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aPixelActor; [aPixelActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aQuadActor; [aQuadActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aTriangleActor; [aTriangleActor GetProperty] SetDiffuseColor .3 1 .5 +ren1 AddActor aPolygonActor; [aPolygonActor GetProperty] SetDiffuseColor 1 .4 .5 +ren1 AddActor aTriangleStripActor; [aTriangleStripActor GetProperty] SetDiffuseColor .3 .7 1 +ren1 AddActor aLineActor; [aLineActor GetProperty] SetDiffuseColor .2 1 1 +ren1 AddActor aPolyLineActor; [aPolyLineActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aVertexActor; [aVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPolyVertexActor; [aPolyVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPentaActor; [aPentaActor GetProperty] SetDiffuseColor .2 .4 .7 +ren1 AddActor aHexaActor; [aHexaActor GetProperty] SetDiffuseColor .7 .5 1 + +if { [info command vtkRIBLight] != "" } { + vtkRIBLight aLight + aLight ShadowsOn +} else { + vtkLight aLight +} +aLight PositionalOn +aLight SetConeAngle 25 + +ren1 AddLight aLight + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Dolly 2.8 +ren1 ResetCameraClippingRange + +eval aLight SetFocalPoint [[ren1 GetActiveCamera] GetFocalPoint] +eval aLight SetPosition [[ren1 GetActiveCamera] GetPosition] +renWin Render + +# +# write to the temp directory if possible, otherwise use . +set dir "." +if {[info commands rtTester] == "rtTester"} { + set dir [rtTester GetTempDirectory] +} + +if { [info command vtkRIBExporter] != "" } { + vtkTexture atext + vtkBMPReader pnmReader + pnmReader SetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" + atext SetInputConnection [pnmReader GetOutputPort] + atext InterpolateOff + aTriangleActor SetTexture atext + vtkRIBExporter rib + rib SetInput renWin + rib SetFilePrefix $dir/cells + rib SetTexturePrefix $dir/cells +} + +vtkIVExporter iv + iv SetInput renWin + iv SetFileName $dir/cells.iv + +vtkOBJExporter obj + obj SetInput renWin + obj SetFilePrefix $dir/cells + +vtkVRMLExporter vrml + vrml SetInput renWin + vrml SetStartWrite {vrml SetFileName $dir/cells.wrl} + vrml SetEndWrite {vrml SetFileName /a/acells.wrl} + vrml SetSpeed 5.5 + +vtkOOGLExporter oogl + oogl SetInput renWin + oogl SetFileName $dir/cells.oogl + + +# +# If the current directory is writable, then test the witers +# + +if {[catch {set channel [open $dir/test.tmp w]}] == 0 } { + close $channel + file delete -force $dir/test.tmp + + iv Write + file delete -force $dir/cells.iv + obj Write + file delete -force $dir/cells.obj + file delete -force $dir/cells.mtl + vrml Write + file delete -force $dir/cells.wrl + oogl Write + file delete -force $dir/cells.oogl + + if { [info command vtkRIBExporter] != "" } { + rib Write + file delete -force $dir/cells.rib + catch {eval file delete -force [glob -nocomplain $dir/cells_*_*.tif]} + } +} + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . + + +# the UnRegister calls are because make object is the same as New, +# and causes memory leaks. (Tcl does not treat NewInstance the same as New). +proc DeleteCopies {} { + global bVoxel bHexahedron bTetra bPixel bQuad bTriangle bPolygon + global bTriangleStrip bLine bPolyLine bVertex bPolyVertex + global bWedge bPyramid bPenta bHexa + $bVoxel UnRegister {} + $bHexahedron UnRegister {} + $bTetra UnRegister {} + $bWedge UnRegister {} + $bPyramid UnRegister {} + $bPixel UnRegister {} + $bQuad UnRegister {} + $bTriangle UnRegister {} + $bPolygon UnRegister {} + $bTriangleStrip UnRegister {} + $bLine UnRegister {} + $bPolyLine UnRegister {} + $bVertex UnRegister {} + $bPolyVertex UnRegister {} + $bPenta UnRegister {} + $bHexa UnRegister {} +} + +DeleteCopies + +# for testing +set threshold 20 + diff --git a/Rendering/Testing/Tcl/labeledContours.tcl b/Rendering/Testing/Tcl/labeledContours.tcl new file mode 100644 index 0000000..5da8133 --- /dev/null +++ b/Rendering/Testing/Tcl/labeledContours.tcl @@ -0,0 +1,72 @@ +package require vtk +package require vtkinteraction + +# demonstrate labeling of contour with scalar value + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Read a slice and contour it +vtkVolume16Reader v16 + v16 SetDataDimensions 64 64 + [v16 GetOutput] SetOrigin 0.0 0.0 0.0 + v16 SetDataByteOrderToLittleEndian + v16 SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" + v16 SetImageRange 45 45 + v16 SetDataSpacing 3.2 3.2 1.5 +vtkContourFilter iso + iso SetInputConnection [v16 GetOutputPort] + iso GenerateValues 6 500 1150 + iso Update +set numPts [[iso GetOutput] GetNumberOfPoints] +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [iso GetOutputPort] + isoMapper ScalarVisibilityOn + eval isoMapper SetScalarRange [[iso GetOutput] GetScalarRange] +vtkActor isoActor + isoActor SetMapper isoMapper + +# Subsample the points and label them +vtkMaskPoints mask + mask SetInputConnection [iso GetOutputPort] + mask SetOnRatio [expr $numPts / 50] + mask SetMaximumNumberOfPoints 50 + mask RandomModeOn + +# Create labels for points - only show visible points +vtkSelectVisiblePoints visPts + visPts SetInputConnection [mask GetOutputPort] + visPts SetRenderer ren1 +vtkLabeledDataMapper ldm + ldm SetInputConnection [mask GetOutputPort] + ldm SetLabelFormat "%g" + ldm SetLabelModeToLabelScalars +set tprop [ldm GetLabelTextProperty] + $tprop SetFontFamilyToArial + $tprop SetFontSize 10 + $tprop SetColor 1 0 0 +vtkActor2D contourLabels + contourLabels SetMapper ldm + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor2D isoActor +ren1 AddActor2D contourLabels + +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +renWin Render +[ren1 GetActiveCamera] Zoom 1.5 + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . + diff --git a/Rendering/Testing/Tcl/labeledMesh.tcl b/Rendering/Testing/Tcl/labeledMesh.tcl new file mode 100644 index 0000000..616ab68 --- /dev/null +++ b/Rendering/Testing/Tcl/labeledMesh.tcl @@ -0,0 +1,142 @@ +package require vtk +package require vtkinteraction + +# demonstrate use of point labeling and the selection window + +# get the interactor ui + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Create a selection window +set xmin 200 +set xLength 100 +set xmax [expr $xmin + $xLength] +set ymin 200 +set yLength 100 +set ymax [expr $ymin + $yLength] + +vtkPoints pts + pts InsertPoint 0 $xmin $ymin 0 + pts InsertPoint 1 $xmax $ymin 0 + pts InsertPoint 2 $xmax $ymax 0 + pts InsertPoint 3 $xmin $ymax 0 +vtkCellArray rect + rect InsertNextCell 5 + rect InsertCellPoint 0 + rect InsertCellPoint 1 + rect InsertCellPoint 2 + rect InsertCellPoint 3 + rect InsertCellPoint 0 +vtkPolyData selectRect + selectRect SetPoints pts + selectRect SetLines rect +vtkPolyDataMapper2D rectMapper + rectMapper SetInput selectRect +vtkActor2D rectActor + rectActor SetMapper rectMapper + +# Create asphere +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] + sphereMapper GlobalImmediateModeRenderingOn +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Generate ids for labeling +vtkIdFilter ids + ids SetInputConnection [sphere GetOutputPort] + ids PointIdsOn + ids CellIdsOn + ids FieldDataOn + +# Create labels for points +vtkSelectVisiblePoints visPts + visPts SetInputConnection [ids GetOutputPort] + visPts SetRenderer ren1 + visPts SelectionWindowOn + visPts SetSelection $xmin [expr $xmin + $xLength] \ + $ymin [expr $ymin + $yLength] +vtkLabeledDataMapper ldm + ldm SetInputConnection [visPts GetOutputPort] + ldm SetLabelFormat "%g" +# ldm SetLabelModeToLabelScalars +# ldm SetLabelModeToLabelNormals + ldm SetLabelModeToLabelFieldData +# ldm SetLabeledComponent 0 +vtkActor2D pointLabels + pointLabels SetMapper ldm + +# Create labels for cells +vtkCellCenters cc + cc SetInputConnection [ids GetOutputPort] +vtkSelectVisiblePoints visCells + visCells SetInputConnection [cc GetOutputPort] + visCells SetRenderer ren1 + visCells SelectionWindowOn + visCells SetSelection $xmin [expr $xmin + $xLength] \ + $ymin [expr $ymin + $yLength] +vtkLabeledDataMapper cellMapper + cellMapper SetInputConnection [visCells GetOutputPort] + cellMapper SetLabelFormat "%g" +# cellMapper SetLabelModeToLabelScalars +# cellMapper SetLabelModeToLabelNormals + cellMapper SetLabelModeToLabelFieldData + [cellMapper GetLabelTextProperty] SetColor 0 1 0 +vtkActor2D cellLabels + cellLabels SetMapper cellMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor sphereActor +ren1 AddActor2D rectActor +ren1 AddActor2D pointLabels +ren1 AddActor2D cellLabels + +ren1 SetBackground 1 1 1 +renWin SetSize 500 500 +renWin Render + + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# prevent the tk window from showing up then start the event loop +wm withdraw . +proc PlaceWindow {xmin ymin} { + global xLength yLength + + set xmax [expr $xmin + $xLength] + set ymax [expr $ymin + $yLength] + + visPts SetSelection $xmin $xmax $ymin $ymax + visCells SetSelection $xmin $xmax $ymin $ymax + + pts InsertPoint 0 $xmin $ymin 0 + pts InsertPoint 1 $xmax $ymin 0 + pts InsertPoint 2 $xmax $ymax 0 + pts InsertPoint 3 $xmin $ymax 0 + pts Modified;#because insertions don't modify object - performance reasons + + renWin Render +} + +proc MoveWindow {} { + for {set y 100} {$y < 300} {incr y 25} { + for {set x 100} {$x < 300} {incr x 25} { + PlaceWindow $x $y + } + } +} + + + +MoveWindow +PlaceWindow $xmin $ymin diff --git a/Rendering/Testing/Tcl/multiLineText.tcl b/Rendering/Testing/Tcl/multiLineText.tcl new file mode 100644 index 0000000..c8458af --- /dev/null +++ b/Rendering/Testing/Tcl/multiLineText.tcl @@ -0,0 +1,203 @@ +# This example demonstrates the use of multiline 2D text using +# vtkTextMappers. It shows several justifications as well as single-line +# and multiple-line text inputs. + +# +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl +# +package require vtk +package require vtkinteraction + +set font_size 14 + +# Create the text mappers and the associated Actor2Ds. + +# The font and text properties (except justification) are the same for each +# single line mapper. Let's create a common text property object + +vtkTextProperty singleLineTextProp + singleLineTextProp SetFontSize $font_size + singleLineTextProp SetFontFamilyToArial + singleLineTextProp BoldOff + singleLineTextProp ItalicOff + singleLineTextProp ShadowOff + +# The font and text properties (except justification) are the same for each +# multi line mapper. Let's create a common text property object + +vtkTextProperty multiLineTextProp + multiLineTextProp ShallowCopy singleLineTextProp + multiLineTextProp BoldOn + multiLineTextProp ItalicOn + multiLineTextProp ShadowOn + +# The text is on a single line and bottom-justified. +vtkTextMapper singleLineTextB + singleLineTextB SetInput "Single line (bottom)" + set tprop [singleLineTextB GetTextProperty] + $tprop ShallowCopy singleLineTextProp + $tprop SetVerticalJustificationToBottom + $tprop SetColor 1 0 0 +vtkActor2D singleLineTextActorB + singleLineTextActorB SetMapper singleLineTextB + [singleLineTextActorB GetPositionCoordinate] \ + SetCoordinateSystemToNormalizedDisplay + [singleLineTextActorB GetPositionCoordinate] SetValue 0.05 0.85 + +# The text is on a single line and center-justified (vertical justification). +vtkTextMapper singleLineTextC + singleLineTextC SetInput "Single line (centered)" + set tprop [singleLineTextC GetTextProperty] + $tprop ShallowCopy singleLineTextProp + $tprop SetVerticalJustificationToCentered + $tprop SetColor 0 1 0 +vtkActor2D singleLineTextActorC + singleLineTextActorC SetMapper singleLineTextC + [singleLineTextActorC GetPositionCoordinate] \ + SetCoordinateSystemToNormalizedDisplay + [singleLineTextActorC GetPositionCoordinate] SetValue 0.05 0.75 + +# The text is on a single line and top-justified. +vtkTextMapper singleLineTextT + singleLineTextT SetInput "Single line (top)" + set tprop [singleLineTextT GetTextProperty] + $tprop ShallowCopy singleLineTextProp + $tprop SetVerticalJustificationToTop + $tprop SetColor 0 0 1 +vtkActor2D singleLineTextActorT + singleLineTextActorT SetMapper singleLineTextT + [singleLineTextActorT GetPositionCoordinate] \ + SetCoordinateSystemToNormalizedDisplay + [singleLineTextActorT GetPositionCoordinate] SetValue 0.05 0.65 + +# The text is on multiple lines and left- and top-justified. +vtkTextMapper textMapperL + textMapperL SetInput "This is\nmulti-line\ntext output\n(left-top)" + set tprop [textMapperL GetTextProperty] + $tprop ShallowCopy multiLineTextProp + $tprop SetJustificationToLeft + $tprop SetVerticalJustificationToTop + $tprop SetColor 1 0 0 +vtkActor2D textActorL + textActorL SetMapper textMapperL + [textActorL GetPositionCoordinate] SetCoordinateSystemToNormalizedDisplay + [textActorL GetPositionCoordinate] SetValue 0.05 0.5 + +# The text is on multiple lines and center-justified (both horizontal and +# vertical). +vtkTextMapper textMapperC + textMapperC SetInput "This is\nmulti-line\ntext output\n(centered)" + set tprop [textMapperC GetTextProperty] + $tprop ShallowCopy multiLineTextProp + $tprop SetJustificationToCentered + $tprop SetVerticalJustificationToCentered + $tprop SetColor 0 1 0 +vtkActor2D textActorC + textActorC SetMapper textMapperC + [textActorC GetPositionCoordinate] SetCoordinateSystemToNormalizedDisplay + [textActorC GetPositionCoordinate] SetValue 0.5 0.5 + +# The text is on multiple lines and right- and bottom-justified. +vtkTextMapper textMapperR + textMapperR SetInput "This is\nmulti-line\ntext output\n(right-bottom)" + set tprop [textMapperR GetTextProperty] + $tprop ShallowCopy multiLineTextProp + $tprop SetJustificationToRight + $tprop SetVerticalJustificationToBottom + $tprop SetColor 0 0 1 +vtkActor2D textActorR + textActorR SetMapper textMapperR + [textActorR GetPositionCoordinate] SetCoordinateSystemToNormalizedDisplay + [textActorR GetPositionCoordinate] SetValue 0.95 0.5 + +# Draw the grid to demonstrate the placement of the text. + +# Set up the necessary points. +vtkPoints Pts + Pts InsertNextPoint 0.05 0.0 0.0 + Pts InsertNextPoint 0.05 1.0 0.0 + Pts InsertNextPoint 0.5 0.0 0.0 + Pts InsertNextPoint 0.5 1.0 0.0 + Pts InsertNextPoint 0.95 0.0 0.0 + Pts InsertNextPoint 0.95 1.0 0.0 + Pts InsertNextPoint 0.0 0.5 0.0 + Pts InsertNextPoint 1.0 0.5 0.0 + Pts InsertNextPoint 0.00 0.85 0.0 + Pts InsertNextPoint 0.50 0.85 0.0 + Pts InsertNextPoint 0.00 0.75 0.0 + Pts InsertNextPoint 0.50 0.75 0.0 + Pts InsertNextPoint 0.00 0.65 0.0 + Pts InsertNextPoint 0.50 0.65 0.0 +# Set up the lines that use these points. +vtkCellArray Lines + Lines InsertNextCell 2 + Lines InsertCellPoint 0 + Lines InsertCellPoint 1 + Lines InsertNextCell 2 + Lines InsertCellPoint 2 + Lines InsertCellPoint 3 + Lines InsertNextCell 2 + Lines InsertCellPoint 4 + Lines InsertCellPoint 5 + Lines InsertNextCell 2 + Lines InsertCellPoint 6 + Lines InsertCellPoint 7 + Lines InsertNextCell 2 + Lines InsertCellPoint 8 + Lines InsertCellPoint 9 + Lines InsertNextCell 2 + Lines InsertCellPoint 10 + Lines InsertCellPoint 11 + Lines InsertNextCell 2 + Lines InsertCellPoint 12 + Lines InsertCellPoint 13 +# Create a grid that uses these points and lines. +vtkPolyData Grid + Grid SetPoints Pts + Grid SetLines Lines +# Set up the coordinate system. +vtkCoordinate normCoords + normCoords SetCoordinateSystemToNormalizedViewport + +# Set up the mapper and actor (2D) for the grid. +vtkPolyDataMapper2D mapper + mapper SetInput Grid + mapper SetTransformCoordinate normCoords +vtkActor2D gridActor + gridActor SetMapper mapper + [gridActor GetProperty] SetColor 0.1 0.1 0.1 + +# Create the Renderer, RenderWindow, and RenderWindowInteractor +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer; set the background and size; zoom in +# closer to the image; render +# +ren1 AddActor2D gridActor +ren1 AddActor2D textActorL +ren1 AddActor2D textActorC +ren1 AddActor2D textActorR +ren1 AddActor2D singleLineTextActorB +ren1 AddActor2D singleLineTextActorC +ren1 AddActor2D singleLineTextActorT + +ren1 SetBackground 1 1 1 +renWin SetSize 500 300 +[ren1 GetActiveCamera] Zoom 1.5 +renWin Render + +# Set the user method (bound to key 'u') +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +# Withdraw the default tk window. +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/pickCells.tcl b/Rendering/Testing/Tcl/pickCells.tcl new file mode 100644 index 0000000..471a6b3 --- /dev/null +++ b/Rendering/Testing/Tcl/pickCells.tcl @@ -0,0 +1,559 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + + +# create a scene with one of each cell type + +# Voxel + +vtkPoints voxelPoints + voxelPoints SetNumberOfPoints 8 + voxelPoints InsertPoint 0 0 0 0 + voxelPoints InsertPoint 1 1 0 0 + voxelPoints InsertPoint 2 0 1 0 + voxelPoints InsertPoint 3 1 1 0 + voxelPoints InsertPoint 4 0 0 1 + voxelPoints InsertPoint 5 1 0 1 + voxelPoints InsertPoint 6 0 1 1 + voxelPoints InsertPoint 7 1 1 1 + +vtkVoxel aVoxel + [aVoxel GetPointIds] SetId 0 0 + [aVoxel GetPointIds] SetId 1 1 + [aVoxel GetPointIds] SetId 2 2 + [aVoxel GetPointIds] SetId 3 3 + [aVoxel GetPointIds] SetId 4 4 + [aVoxel GetPointIds] SetId 5 5 + [aVoxel GetPointIds] SetId 6 6 + [aVoxel GetPointIds] SetId 7 7 + + +vtkUnstructuredGrid aVoxelGrid + aVoxelGrid Allocate 1 1 + aVoxelGrid InsertNextCell [aVoxel GetCellType] [aVoxel GetPointIds] + aVoxelGrid SetPoints voxelPoints + +vtkDataSetMapper aVoxelMapper +aVoxelMapper SetInput aVoxelGrid + +vtkActor aVoxelActor + aVoxelActor SetMapper aVoxelMapper + [aVoxelActor GetProperty] BackfaceCullingOn + +# Hexahedron + +vtkPoints hexahedronPoints + hexahedronPoints SetNumberOfPoints 8 + hexahedronPoints InsertPoint 0 0 0 0 + hexahedronPoints InsertPoint 1 1 0 0 + hexahedronPoints InsertPoint 2 1 1 0 + hexahedronPoints InsertPoint 3 0 1 0 + hexahedronPoints InsertPoint 4 0 0 1 + hexahedronPoints InsertPoint 5 1 0 1 + hexahedronPoints InsertPoint 6 1 1 1 + hexahedronPoints InsertPoint 7 0 1 1 + +vtkHexahedron aHexahedron + [aHexahedron GetPointIds] SetId 0 0 + [aHexahedron GetPointIds] SetId 1 1 + [aHexahedron GetPointIds] SetId 2 2 + [aHexahedron GetPointIds] SetId 3 3 + [aHexahedron GetPointIds] SetId 4 4 + [aHexahedron GetPointIds] SetId 5 5 + [aHexahedron GetPointIds] SetId 6 6 + [aHexahedron GetPointIds] SetId 7 7 + + +vtkUnstructuredGrid aHexahedronGrid + aHexahedronGrid Allocate 1 1 + aHexahedronGrid InsertNextCell [aHexahedron GetCellType] [aHexahedron GetPointIds] + aHexahedronGrid SetPoints hexahedronPoints + +vtkDataSetMapper aHexahedronMapper + aHexahedronMapper SetInput aHexahedronGrid + +vtkActor aHexahedronActor + aHexahedronActor SetMapper aHexahedronMapper + aHexahedronActor AddPosition 2 0 0 + [aHexahedronActor GetProperty] BackfaceCullingOn + +# Tetra + +vtkPoints tetraPoints + tetraPoints SetNumberOfPoints 4 + tetraPoints InsertPoint 0 0 0 0 + tetraPoints InsertPoint 1 1 0 0 + tetraPoints InsertPoint 2 .5 1 0 + tetraPoints InsertPoint 3 .5 .5 1 + +vtkTetra aTetra + [aTetra GetPointIds] SetId 0 0 + [aTetra GetPointIds] SetId 1 1 + [aTetra GetPointIds] SetId 2 2 + [aTetra GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aTetraGrid + aTetraGrid Allocate 1 1 + aTetraGrid InsertNextCell [aTetra GetCellType] [aTetra GetPointIds] + aTetraGrid SetPoints tetraPoints + +vtkDataSetMapper aTetraMapper + aTetraMapper SetInput aTetraGrid + +vtkActor aTetraActor + aTetraActor SetMapper aTetraMapper + aTetraActor AddPosition 4 0 0 + [aTetraActor GetProperty] BackfaceCullingOn + +# Wedge + +vtkPoints wedgePoints + wedgePoints SetNumberOfPoints 6 + wedgePoints InsertPoint 0 0 1 0 + wedgePoints InsertPoint 1 0 0 0 + wedgePoints InsertPoint 2 0 .5 .5 + wedgePoints InsertPoint 3 1 1 0 + wedgePoints InsertPoint 4 1 0 0 + wedgePoints InsertPoint 5 1 .5 .5 + +vtkWedge aWedge + [aWedge GetPointIds] SetId 0 0 + [aWedge GetPointIds] SetId 1 1 + [aWedge GetPointIds] SetId 2 2 + [aWedge GetPointIds] SetId 3 3 + [aWedge GetPointIds] SetId 4 4 + [aWedge GetPointIds] SetId 5 5 + + +vtkUnstructuredGrid aWedgeGrid + aWedgeGrid Allocate 1 1 + aWedgeGrid InsertNextCell [aWedge GetCellType] [aWedge GetPointIds] + aWedgeGrid SetPoints wedgePoints + +vtkDataSetMapper aWedgeMapper + aWedgeMapper SetInput aWedgeGrid + +vtkActor aWedgeActor + aWedgeActor SetMapper aWedgeMapper + aWedgeActor AddPosition 6 0 0 + [aWedgeActor GetProperty] BackfaceCullingOn + +# Pyramid + +vtkPoints pyramidPoints + pyramidPoints SetNumberOfPoints 5 + pyramidPoints InsertPoint 0 0 0 0 + pyramidPoints InsertPoint 1 1 0 0 + pyramidPoints InsertPoint 2 1 1 0 + pyramidPoints InsertPoint 3 0 1 0 + pyramidPoints InsertPoint 4 .5 .5 1 + +vtkPyramid aPyramid + [aPyramid GetPointIds] SetId 0 0 + [aPyramid GetPointIds] SetId 1 1 + [aPyramid GetPointIds] SetId 2 2 + [aPyramid GetPointIds] SetId 3 3 + [aPyramid GetPointIds] SetId 4 4 + + +vtkUnstructuredGrid aPyramidGrid + aPyramidGrid Allocate 1 1 + aPyramidGrid InsertNextCell [aPyramid GetCellType] [aPyramid GetPointIds] + aPyramidGrid SetPoints pyramidPoints + +vtkDataSetMapper aPyramidMapper + aPyramidMapper SetInput aPyramidGrid + +vtkActor aPyramidActor + aPyramidActor SetMapper aPyramidMapper + aPyramidActor AddPosition 8 0 0 + [aPyramidActor GetProperty] BackfaceCullingOn + +# Pixel + +vtkPoints pixelPoints + pixelPoints SetNumberOfPoints 4 + pixelPoints InsertPoint 0 0 0 0 + pixelPoints InsertPoint 1 1 0 0 + pixelPoints InsertPoint 2 0 1 0 + pixelPoints InsertPoint 3 1 1 0 + +vtkPixel aPixel + [aPixel GetPointIds] SetId 0 0 + [aPixel GetPointIds] SetId 1 1 + [aPixel GetPointIds] SetId 2 2 + [aPixel GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aPixelGrid + aPixelGrid Allocate 1 1 + aPixelGrid InsertNextCell [aPixel GetCellType] [aPixel GetPointIds] + aPixelGrid SetPoints pixelPoints + +vtkDataSetMapper aPixelMapper + aPixelMapper SetInput aPixelGrid + +vtkActor aPixelActor + aPixelActor SetMapper aPixelMapper + aPixelActor AddPosition 0 0 2 + [aPixelActor GetProperty] BackfaceCullingOn + +# Quad + +vtkPoints quadPoints + quadPoints SetNumberOfPoints 4 + quadPoints InsertPoint 0 0 0 0 + quadPoints InsertPoint 1 1 0 0 + quadPoints InsertPoint 2 1 1 0 + quadPoints InsertPoint 3 0 1 0 + +vtkQuad aQuad + [aQuad GetPointIds] SetId 0 0 + [aQuad GetPointIds] SetId 1 1 + [aQuad GetPointIds] SetId 2 2 + [aQuad GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aQuadGrid + aQuadGrid Allocate 1 1 + aQuadGrid InsertNextCell [aQuad GetCellType] [aQuad GetPointIds] + aQuadGrid SetPoints quadPoints + +vtkDataSetMapper aQuadMapper + aQuadMapper SetInput aQuadGrid + +vtkActor aQuadActor + aQuadActor SetMapper aQuadMapper + aQuadActor AddPosition 2 0 2 + [aQuadActor GetProperty] BackfaceCullingOn + +# Triangle + +vtkPoints trianglePoints + trianglePoints SetNumberOfPoints 3 + trianglePoints InsertPoint 0 0 0 0 + trianglePoints InsertPoint 1 1 0 0 + trianglePoints InsertPoint 2 .5 .5 0 + +vtkTriangle aTriangle + [aTriangle GetPointIds] SetId 0 0 + [aTriangle GetPointIds] SetId 1 1 + [aTriangle GetPointIds] SetId 2 2 + +vtkUnstructuredGrid aTriangleGrid + aTriangleGrid Allocate 1 1 + aTriangleGrid InsertNextCell [aTriangle GetCellType] [aTriangle GetPointIds] + aTriangleGrid SetPoints trianglePoints + +vtkDataSetMapper aTriangleMapper + aTriangleMapper SetInput aTriangleGrid + +vtkActor aTriangleActor + aTriangleActor SetMapper aTriangleMapper + aTriangleActor AddPosition 4 0 2 + [aTriangleActor GetProperty] BackfaceCullingOn + +# Polygon + +vtkPoints polygonPoints + polygonPoints SetNumberOfPoints 4 + polygonPoints InsertPoint 0 0 0 0 + polygonPoints InsertPoint 1 1 0 0 + polygonPoints InsertPoint 2 1 1 0 + polygonPoints InsertPoint 3 0 1 0 + +vtkPolygon aPolygon + [aPolygon GetPointIds] SetNumberOfIds 4 + [aPolygon GetPointIds] SetId 0 0 + [aPolygon GetPointIds] SetId 1 1 + [aPolygon GetPointIds] SetId 2 2 + [aPolygon GetPointIds] SetId 3 3 + +vtkUnstructuredGrid aPolygonGrid + aPolygonGrid Allocate 1 1 + aPolygonGrid InsertNextCell [aPolygon GetCellType] [aPolygon GetPointIds] + aPolygonGrid SetPoints polygonPoints + +vtkDataSetMapper aPolygonMapper + aPolygonMapper SetInput aPolygonGrid + +vtkActor aPolygonActor + aPolygonActor SetMapper aPolygonMapper + aPolygonActor AddPosition 6 0 2 + [aPolygonActor GetProperty] BackfaceCullingOn + +# Triangle Strip + +vtkPoints triangleStripPoints + triangleStripPoints SetNumberOfPoints 5 + triangleStripPoints InsertPoint 0 0 1 0 + triangleStripPoints InsertPoint 1 0 0 0 + triangleStripPoints InsertPoint 2 1 1 0 + triangleStripPoints InsertPoint 3 1 0 0 + triangleStripPoints InsertPoint 4 2 1 0 + +vtkTriangleStrip aTriangleStrip + [aTriangleStrip GetPointIds] SetNumberOfIds 5 + [aTriangleStrip GetPointIds] SetId 0 0 + [aTriangleStrip GetPointIds] SetId 1 1 + [aTriangleStrip GetPointIds] SetId 2 2 + [aTriangleStrip GetPointIds] SetId 3 3 + [aTriangleStrip GetPointIds] SetId 4 4 + +vtkUnstructuredGrid aTriangleStripGrid + aTriangleStripGrid Allocate 1 1 + aTriangleStripGrid InsertNextCell [aTriangleStrip GetCellType] [aTriangleStrip GetPointIds] + aTriangleStripGrid SetPoints triangleStripPoints + +vtkDataSetMapper aTriangleStripMapper + aTriangleStripMapper SetInput aTriangleStripGrid + +vtkActor aTriangleStripActor + aTriangleStripActor SetMapper aTriangleStripMapper + aTriangleStripActor AddPosition 8 0 2 + [aTriangleStripActor GetProperty] BackfaceCullingOn + +# Line + +vtkPoints linePoints + linePoints SetNumberOfPoints 2 + linePoints InsertPoint 0 0 0 0 + linePoints InsertPoint 1 1 1 0 + +vtkLine aLine + [aLine GetPointIds] SetId 0 0 + [aLine GetPointIds] SetId 1 1 + +vtkUnstructuredGrid aLineGrid + aLineGrid Allocate 1 1 + aLineGrid InsertNextCell [aLine GetCellType] [aLine GetPointIds] + aLineGrid SetPoints linePoints + +vtkDataSetMapper aLineMapper + aLineMapper SetInput aLineGrid + +vtkActor aLineActor + aLineActor SetMapper aLineMapper + aLineActor AddPosition 0 0 4 + [aLineActor GetProperty] BackfaceCullingOn + +# Poly line + +vtkPoints polyLinePoints + polyLinePoints SetNumberOfPoints 3 + polyLinePoints InsertPoint 0 0 0 0 + polyLinePoints InsertPoint 1 1 1 0 + polyLinePoints InsertPoint 2 1 0 0 + +vtkPolyLine aPolyLine + [aPolyLine GetPointIds] SetNumberOfIds 3 + [aPolyLine GetPointIds] SetId 0 0 + [aPolyLine GetPointIds] SetId 1 1 + [aPolyLine GetPointIds] SetId 2 2 + +vtkUnstructuredGrid aPolyLineGrid + aPolyLineGrid Allocate 1 1 + aPolyLineGrid InsertNextCell [aPolyLine GetCellType] [aPolyLine GetPointIds] + aPolyLineGrid SetPoints polyLinePoints + +vtkDataSetMapper aPolyLineMapper + aPolyLineMapper SetInput aPolyLineGrid + +vtkActor aPolyLineActor + aPolyLineActor SetMapper aPolyLineMapper + aPolyLineActor AddPosition 2 0 4 + [aPolyLineActor GetProperty] BackfaceCullingOn + +# Vertex + +vtkPoints vertexPoints + vertexPoints SetNumberOfPoints 1 + vertexPoints InsertPoint 0 0 0 0 + +vtkVertex aVertex + [aVertex GetPointIds] SetId 0 0 + +vtkUnstructuredGrid aVertexGrid + aVertexGrid Allocate 1 1 + aVertexGrid InsertNextCell [aVertex GetCellType] [aVertex GetPointIds] + aVertexGrid SetPoints vertexPoints + +vtkDataSetMapper aVertexMapper + aVertexMapper SetInput aVertexGrid + +vtkActor aVertexActor + aVertexActor SetMapper aVertexMapper + aVertexActor AddPosition 0 0 6 + [aVertexActor GetProperty] BackfaceCullingOn + +# Poly Vertex + +vtkPoints polyVertexPoints + polyVertexPoints SetNumberOfPoints 3 + polyVertexPoints InsertPoint 0 0 0 0 + polyVertexPoints InsertPoint 1 1 0 0 + polyVertexPoints InsertPoint 2 1 1 0 + +vtkPolyVertex aPolyVertex + [aPolyVertex GetPointIds] SetNumberOfIds 3 + [aPolyVertex GetPointIds] SetId 0 0 + [aPolyVertex GetPointIds] SetId 1 1 + [aPolyVertex GetPointIds] SetId 2 2 + +vtkUnstructuredGrid aPolyVertexGrid + aPolyVertexGrid Allocate 1 1 + aPolyVertexGrid InsertNextCell [aPolyVertex GetCellType] [aPolyVertex GetPointIds] + aPolyVertexGrid SetPoints polyVertexPoints + +vtkDataSetMapper aPolyVertexMapper + aPolyVertexMapper SetInput aPolyVertexGrid + +vtkActor aPolyVertexActor + aPolyVertexActor SetMapper aPolyVertexMapper + aPolyVertexActor AddPosition 2 0 6 + [aPolyVertexActor GetProperty] BackfaceCullingOn + +# Pentagonal prism + +vtkPoints pentaPoints + pentaPoints SetNumberOfPoints 10 + pentaPoints InsertPoint 0 0.25 0.0 0.0 + pentaPoints InsertPoint 1 0.75 0.0 0.0 + pentaPoints InsertPoint 2 1.0 0.5 0.0 + pentaPoints InsertPoint 3 0.5 1.0 0.0 + pentaPoints InsertPoint 4 0.0 0.5 0.0 + pentaPoints InsertPoint 5 0.25 0.0 1.0 + pentaPoints InsertPoint 6 0.75 0.0 1.0 + pentaPoints InsertPoint 7 1.0 0.5 1.0 + pentaPoints InsertPoint 8 0.5 1.0 1.0 + pentaPoints InsertPoint 9 0.0 0.5 1.0 + +vtkPentagonalPrism aPenta + [aPenta GetPointIds] SetId 0 0 + [aPenta GetPointIds] SetId 1 1 + [aPenta GetPointIds] SetId 2 2 + [aPenta GetPointIds] SetId 3 3 + [aPenta GetPointIds] SetId 4 4 + [aPenta GetPointIds] SetId 5 5 + [aPenta GetPointIds] SetId 6 6 + [aPenta GetPointIds] SetId 7 7 + [aPenta GetPointIds] SetId 8 8 + [aPenta GetPointIds] SetId 9 9 + +vtkUnstructuredGrid aPentaGrid + aPentaGrid Allocate 1 1 + aPentaGrid InsertNextCell [aPenta GetCellType] [aPenta GetPointIds] + aPentaGrid SetPoints pentaPoints + +vtkDataSetMapper aPentaMapper + aPentaMapper SetInput aPentaGrid + +vtkActor aPentaActor + aPentaActor SetMapper aPentaMapper + aPentaActor AddPosition 10 0 0 + [aPentaActor GetProperty] BackfaceCullingOn + +# Hexagonal prism + +vtkPoints hexaPoints + hexaPoints SetNumberOfPoints 12 + hexaPoints InsertPoint 0 0.0 0.0 0.0 + hexaPoints InsertPoint 1 0.5 0.0 0.0 + hexaPoints InsertPoint 2 1.0 0.5 0.0 + hexaPoints InsertPoint 3 1.0 1.0 0.0 + hexaPoints InsertPoint 4 0.5 1.0 0.0 + hexaPoints InsertPoint 5 0.0 0.5 0.0 + hexaPoints InsertPoint 6 0.0 0.0 1.0 + hexaPoints InsertPoint 7 0.5 0.0 1.0 + hexaPoints InsertPoint 8 1.0 0.5 1.0 + hexaPoints InsertPoint 9 1.0 1.0 1.0 + hexaPoints InsertPoint 10 0.5 1.0 1.0 + hexaPoints InsertPoint 11 0.0 0.5 1.0 + +vtkHexagonalPrism aHexa + [aHexa GetPointIds] SetId 0 0 + [aHexa GetPointIds] SetId 1 1 + [aHexa GetPointIds] SetId 2 2 + [aHexa GetPointIds] SetId 3 3 + [aHexa GetPointIds] SetId 4 4 + [aHexa GetPointIds] SetId 5 5 + [aHexa GetPointIds] SetId 6 6 + [aHexa GetPointIds] SetId 7 7 + [aHexa GetPointIds] SetId 8 8 + [aHexa GetPointIds] SetId 9 9 + [aHexa GetPointIds] SetId 10 10 + [aHexa GetPointIds] SetId 11 11 + +vtkUnstructuredGrid aHexaGrid + aHexaGrid Allocate 1 1 + aHexaGrid InsertNextCell [aHexa GetCellType] [aHexa GetPointIds] + aHexaGrid SetPoints hexaPoints + +vtkDataSetMapper aHexaMapper + aHexaMapper SetInput aHexaGrid + +vtkActor aHexaActor + aHexaActor SetMapper aHexaMapper + aHexaActor AddPosition 12 0 0 + [aHexaActor GetProperty] BackfaceCullingOn + + + +ren1 SetBackground .1 .2 .4 + +ren1 AddActor aVoxelActor; [aVoxelActor GetProperty] SetDiffuseColor 1 0 0 +ren1 AddActor aHexahedronActor; [aHexahedronActor GetProperty] SetDiffuseColor 1 1 0 +ren1 AddActor aTetraActor; [aTetraActor GetProperty] SetDiffuseColor 0 1 0 +ren1 AddActor aWedgeActor; [aWedgeActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aPyramidActor; [aPyramidActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aPixelActor; [aPixelActor GetProperty] SetDiffuseColor 0 1 1 +ren1 AddActor aQuadActor; [aQuadActor GetProperty] SetDiffuseColor 1 0 1 +ren1 AddActor aTriangleActor; [aTriangleActor GetProperty] SetDiffuseColor .3 1 .5 +ren1 AddActor aPolygonActor; [aPolygonActor GetProperty] SetDiffuseColor 1 .4 .5 +ren1 AddActor aTriangleStripActor; [aTriangleStripActor GetProperty] SetDiffuseColor .3 .7 1 +ren1 AddActor aLineActor; [aLineActor GetProperty] SetDiffuseColor .2 1 1 +ren1 AddActor aPolyLineActor; [aPolyLineActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aVertexActor; [aVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPolyVertexActor; [aPolyVertexActor GetProperty] SetDiffuseColor 1 1 1 +ren1 AddActor aPentaActor; [aPentaActor GetProperty] SetDiffuseColor .2 .4 .7 +ren1 AddActor aHexaActor; [aHexaActor GetProperty] SetDiffuseColor .7 .5 1 + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 30 +[ren1 GetActiveCamera] Elevation 20 +[ren1 GetActiveCamera] Dolly 1.25 +ren1 ResetCameraClippingRange + +renWin Render + +vtkCellPicker cellPicker +vtkPointPicker pointPicker +vtkWorldPointPicker worldPicker + +set cellCount 0 +set pointCount 0 +ren1 IsInViewport 0 0 + +for {set x 0} { $x <= 265} {incr x 6} { + for {set y 100} {$y <= 200} {incr y 6} { + cellPicker Pick $x $y 0 ren1 + pointPicker Pick $x $y 0 ren1 + worldPicker Pick $x $y 0 ren1 + if {[cellPicker GetCellId] != "-1" } { + incr cellCount + } + if {[pointPicker GetPointId] != "-1" } { + incr pointCount + } + } +} + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +wm withdraw . diff --git a/Rendering/Testing/Tcl/propAssembly.tcl b/Rendering/Testing/Tcl/propAssembly.tcl new file mode 100644 index 0000000..b71e70d --- /dev/null +++ b/Rendering/Testing/Tcl/propAssembly.tcl @@ -0,0 +1,77 @@ +package require vtk +package require vtkinteraction + +# demonstrates the use of vtkPropAssembly + +# create four parts: a top level assembly and three primitives +# +vtkSphereSource sphere +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphere GetOutputPort] +vtkActor sphereActor + sphereActor SetMapper sphereMapper + sphereActor SetOrigin 2 1 3 + sphereActor RotateY 6 + sphereActor SetPosition 2.25 0 0 + [sphereActor GetProperty] SetColor 1 0 1 + +vtkCubeSource cube +vtkPolyDataMapper cubeMapper + cubeMapper SetInputConnection [cube GetOutputPort] +vtkActor cubeActor + cubeActor SetMapper cubeMapper + cubeActor SetPosition 0.0 .25 0 + [cubeActor GetProperty] SetColor 0 0 1 + +vtkConeSource cone +vtkPolyDataMapper coneMapper + coneMapper SetInputConnection [cone GetOutputPort] +vtkActor coneActor + coneActor SetMapper coneMapper + coneActor SetPosition 0 0 .25 + [coneActor GetProperty] SetColor 0 1 0 + +vtkCylinderSource cylinder;#top part +vtkPolyDataMapper cylinderMapper + cylinderMapper SetInputConnection [cylinder GetOutputPort] +vtkActor cylinderActor + cylinderActor SetMapper cylinderMapper + [cylinderActor GetProperty] SetColor 1 0 0 +vtkAssembly compositeAssembly + compositeAssembly AddPart cylinderActor + compositeAssembly AddPart sphereActor + compositeAssembly AddPart cubeActor + compositeAssembly AddPart coneActor + compositeAssembly SetOrigin 5 10 15 + compositeAssembly AddPosition 5 0 0 + compositeAssembly RotateX 15 + +# Build the prop assembly out of a vtkActor and a vtkAssembly +vtkPropAssembly assembly + assembly AddPart compositeAssembly + assembly AddPart coneActor + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# Add the actors to the renderer, set the background and size +# +ren1 AddViewProp assembly +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# Get handles to some useful objects +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +renWin Render + +# should create the same image as assembly.tcl + +# prevent the tk window from showing up then start the event loop +wm withdraw . diff --git a/Rendering/Testing/Tcl/rendererSource.tcl b/Rendering/Testing/Tcl/rendererSource.tcl new file mode 100644 index 0000000..73bb577 --- /dev/null +++ b/Rendering/Testing/Tcl/rendererSource.tcl @@ -0,0 +1,114 @@ +package require vtk +package require vtkinteraction +package require vtktesting + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderer ren2 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin AddRenderer ren2 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline for ren1 +# +vtkPLOT3DReader pl3d2 + pl3d2 SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d2 SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d2 SetScalarFunctionNumber 153 + pl3d2 Update + +vtkPLOT3DReader pl3d + pl3d SetXYZFileName "$VTK_DATA_ROOT/Data/combxyz.bin" + pl3d SetQFileName "$VTK_DATA_ROOT/Data/combq.bin" + pl3d SetScalarFunctionNumber 120 + pl3d SetVectorFunctionNumber 202 + pl3d Update +vtkContourFilter iso + iso SetInputConnection [pl3d GetOutputPort] + iso SetValue 0 -100000 + +vtkProbeFilter probe2 + probe2 SetInputConnection [iso GetOutputPort] + probe2 SetSource [pl3d2 GetOutput] + +vtkCastToConcrete cast2 + cast2 SetInputConnection [probe2 GetOutputPort] + +vtkPolyDataNormals normals + normals SetInput [cast2 GetPolyDataOutput] + normals SetFeatureAngle 45 +vtkPolyDataMapper isoMapper + isoMapper SetInputConnection [normals GetOutputPort] + isoMapper ScalarVisibilityOn +eval isoMapper SetScalarRange [[[[pl3d2 GetOutput] GetPointData] GetScalars] GetRange] + +vtkActor isoActor + isoActor SetMapper isoMapper + eval [isoActor GetProperty] SetColor $bisque + +vtkStructuredGridOutlineFilter outline + outline SetInputConnection [pl3d GetOutputPort] +vtkPolyDataMapper outlineMapper + outlineMapper SetInputConnection [outline GetOutputPort] +vtkActor outlineActor + outlineActor SetMapper outlineMapper + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor outlineActor +ren1 AddActor isoActor +ren1 SetBackground 1 1 1 +ren1 SetViewport 0 0 .5 1 + +renWin SetSize 512 256 +ren1 SetBackground 0.1 0.2 0.4 + +ren1 ResetCamera +set cam1 [ren1 GetActiveCamera] +$cam1 SetClippingRange 3.95297 50 +$cam1 SetFocalPoint 9.71821 0.458166 29.3999 +$cam1 SetPosition 2.7439 -37.3196 38.7167 +$cam1 SetViewUp -0.16123 0.264271 0.950876 + + +vtkPlaneSource aPlane +vtkPolyDataMapper aPlaneMapper + aPlaneMapper SetInputConnection [aPlane GetOutputPort] + aPlaneMapper ImmediateModeRenderingOn + +vtkActor screen + screen SetMapper aPlaneMapper + +ren2 AddActor screen +ren2 SetViewport .5 0 1 1 +[ren2 GetActiveCamera] Azimuth 30 +[ren2 GetActiveCamera] Elevation 30 +ren2 SetBackground .8 .4 .3 +ren1 ResetCameraClippingRange +ren2 ResetCamera +ren2 ResetCameraClippingRange +renWin Render + +vtkRendererSource ren1Image + ren1Image SetInput ren1 + ren1Image DepthValuesOn +vtkTexture aTexture + aTexture SetInputConnection [ren1Image GetOutputPort] + +screen SetTexture aTexture + +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + +renWin Render + +# prevent the tk window from showing up then start the event loop +wm withdraw . + + diff --git a/Rendering/Testing/Tcl/rotations.tcl b/Rendering/Testing/Tcl/rotations.tcl new file mode 100644 index 0000000..7e35c76 --- /dev/null +++ b/Rendering/Testing/Tcl/rotations.tcl @@ -0,0 +1,116 @@ +package require vtk +package require vtkinteraction + +# Create renderer stuff +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +# create pipeline +# +vtkBYUReader cow + cow SetGeometryFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.g" + +vtkPolyDataMapper cowMapper + cowMapper SetInputConnection [cow GetOutputPort] +vtkActor cowActor + cowActor SetMapper cowMapper + [cowActor GetProperty] SetDiffuseColor 0.9608 0.8706 0.7020 + +vtkAxes cowAxesSource + cowAxesSource SetScaleFactor 10 + cowAxesSource SetOrigin 0 0 0 + +vtkPolyDataMapper cowAxesMapper + cowAxesMapper SetInputConnection [cowAxesSource GetOutputPort] + +vtkActor cowAxes + cowAxes SetMapper cowAxesMapper + +ren1 AddActor cowAxes +cowAxes VisibilityOff + +# Add the actors to the renderer, set the background and size +# +ren1 AddActor cowActor +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 320 240 +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 0 +[ren1 GetActiveCamera] Dolly 1.4 +ren1 ResetCameraClippingRange + +cowAxes VisibilityOn +renWin Render + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} + + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# +proc RotateX {} { + cowActor SetOrientation 0 0 0 + ren1 ResetCameraClippingRange + renWin Render + renWin Render + renWin EraseOff + for {set i 1} {$i <= 6} {incr i} { + cowActor RotateX 60 + renWin Render + renWin Render + } + renWin EraseOn +} +proc RotateY {} { + cowActor SetOrientation 0 0 0 + ren1 ResetCameraClippingRange + renWin Render + renWin Render + renWin EraseOff + for {set i 1} {$i <= 6} {incr i} { + cowActor RotateY 60 + renWin Render + renWin Render + } + renWin EraseOn +} +proc RotateZ {} { + cowActor SetOrientation 0 0 0 + ren1 ResetCameraClippingRange + renWin Render + renWin Render + renWin EraseOff + for {set i 1} {$i <= 6} {incr i} { + cowActor RotateZ 60 + renWin Render + renWin Render + } + renWin EraseOn +} +proc RotateXY {} { + cowActor SetOrientation 0 0 0 + cowActor RotateX 60 + ren1 ResetCameraClippingRange + renWin Render + renWin Render + renWin EraseOff + for {set i 1} {$i <= 6} {incr i} { + cowActor RotateY 60 + renWin Render + renWin Render + } + renWin EraseOn +} + +RotateX +RotateY +RotateZ +RotateXY +renWin EraseOff diff --git a/Rendering/Testing/Tcl/volRCClipPlanes.tcl b/Rendering/Testing/Tcl/volRCClipPlanes.tcl new file mode 100644 index 0000000..2b21412 --- /dev/null +++ b/Rendering/Testing/Tcl/volRCClipPlanes.tcl @@ -0,0 +1,123 @@ +package require vtk + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +reader Update + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 20 0.0 + opacityTransferFunction AddPoint 255 1.0 + +vtkColorTransferFunction colorTransferFunction + +# Improve coverage + colorTransferFunction SetColorSpaceToRGB + colorTransferFunction AddRGBPoint 100 1 1 1 + colorTransferFunction AddRGBPoint 0 0 0 0 + colorTransferFunction AddRGBPoint 200 1 0 1 + colorTransferFunction AddRGBPoint 100 0 0 0 + colorTransferFunction RemovePoint 100 + colorTransferFunction RemovePoint 0 + colorTransferFunction RemovePoint 200 + colorTransferFunction AddHSVPoint 100 1 1 1 + colorTransferFunction AddHSVPoint 0 0 0 0 + colorTransferFunction AddHSVPoint 200 1 0 1 + colorTransferFunction AddHSVPoint 100 0 0 0 + colorTransferFunction RemovePoint 0 + colorTransferFunction RemovePoint 200 + colorTransferFunction RemovePoint 100 + colorTransferFunction AddRGBSegment 0 1 1 1 100 0 0 0 + colorTransferFunction AddRGBSegment 50 1 1 1 150 0 0 0 + colorTransferFunction AddRGBSegment 60 1 1 1 90 0 0 0 + colorTransferFunction AddHSVSegment 90 1 1 1 105 0 0 0 + colorTransferFunction AddHSVSegment 40 1 1 1 155 0 0 0 + colorTransferFunction AddHSVSegment 30 1 1 1 95 0 0 0 + + + colorTransferFunction RemoveAllPoints + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 127.5 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 255.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + +vtkVolumeRayCastCompositeFunction compositeFunction + +vtkVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [reader GetOutputPort] + volumeMapper SetVolumeRayCastFunction compositeFunction + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# Create geometric sphere +vtkSphereSource sphereSource + sphereSource SetCenter 25 25 25 + sphereSource SetRadius 30 + sphereSource SetThetaResolution 15 + sphereSource SetPhiResolution 15 + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphereSource GetOutputPort] + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Set up the planes +vtkPlane plane1 +plane1 SetOrigin 25 25 20 +plane1 SetNormal 0 0 1 + +vtkPlane plane2 +plane2 SetOrigin 25 25 30 +plane2 SetNormal 0 0 -1 + +vtkPlane plane3 +plane3 SetOrigin 20 25 25 +plane3 SetNormal 1 0 0 + +vtkPlane plane4 +plane4 SetOrigin 30 25 25 +plane4 SetNormal -1 0 0 + +sphereMapper AddClippingPlane plane1 +sphereMapper AddClippingPlane plane2 + +volumeMapper AddClippingPlane plane3 +volumeMapper AddClippingPlane plane4 + + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp sphereActor +ren1 AddViewProp volume +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +[ren1 GetActiveCamera] Azimuth 45 +[ren1 GetActiveCamera] Elevation 15 +[ren1 GetActiveCamera] Roll 45 +[ren1 GetActiveCamera] Zoom 2.0 + +wm withdraw . + +iren Initialize diff --git a/Rendering/Testing/Tcl/volRCCropRegions.tcl b/Rendering/Testing/Tcl/volRCCropRegions.tcl new file mode 100644 index 0000000..a3ad2c3 --- /dev/null +++ b/Rendering/Testing/Tcl/volRCCropRegions.tcl @@ -0,0 +1,106 @@ +package require vtk +package require vtkinteraction + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 30 0.0 + opacityTransferFunction AddPoint 80 0.5 + opacityTransferFunction AddPoint 255 0.5 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + volumeProperty ShadeOn + +vtkVolumeRayCastCompositeFunction compositeFunction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 600 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.1 0.2 0.4 + +for { set i 0 } { $i < 2 } { incr i } { + for { set j 0 } { $j < 4 } { incr j } { + vtkVolumeRayCastMapper volumeMapper_${i}_${j} + volumeMapper_${i}_${j} SetInputConnection [reader GetOutputPort] + volumeMapper_${i}_${j} SetVolumeRayCastFunction compositeFunction + volumeMapper_${i}_${j} SetSampleDistance 0.4 + volumeMapper_${i}_${j} CroppingOn + volumeMapper_${i}_${j} SetCroppingRegionPlanes 17 33 17 33 17 33 + + vtkVolume volume_${i}_${j} + volume_${i}_${j} SetMapper volumeMapper_${i}_${j} + volume_${i}_${j} SetProperty volumeProperty + + vtkTransform userMatrix_${i}_${j} + userMatrix_${i}_${j} PostMultiply + userMatrix_${i}_${j} Identity + userMatrix_${i}_${j} Translate -25 -25 -25 + + if { $i == 0 } { + userMatrix_${i}_${j} RotateX [expr $j*87 + 23] + userMatrix_${i}_${j} RotateY 16 + } else { + userMatrix_${i}_${j} RotateX 27 + userMatrix_${i}_${j} RotateY [expr $j*87 + 19] + } + + userMatrix_${i}_${j} Translate [expr $j*55 + 25] [expr $i*55 + 25] 0 + + volume_${i}_${j} SetUserTransform userMatrix_${i}_${j} + + ren1 AddViewProp volume_${i}_${j} + } +} + +volumeMapper_0_0 SetCroppingRegionFlagsToSubVolume +volumeMapper_0_1 SetCroppingRegionFlagsToCross +volumeMapper_0_2 SetCroppingRegionFlagsToInvertedCross +volumeMapper_0_3 SetCroppingRegionFlags 24600 + +volumeMapper_1_0 SetCroppingRegionFlagsToFence +volumeMapper_1_1 SetCroppingRegionFlagsToInvertedFence +volumeMapper_1_2 SetCroppingRegionFlags 1 +volumeMapper_1_3 SetCroppingRegionFlags 67117057 + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 3.0 +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/volRCRotateClip.tcl b/Rendering/Testing/Tcl/volRCRotateClip.tcl new file mode 100644 index 0000000..515b47c --- /dev/null +++ b/Rendering/Testing/Tcl/volRCRotateClip.tcl @@ -0,0 +1,145 @@ +package require vtk + +# Simple volume rendering example. +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff +reader SetDataSpacing 2 2 1 +reader SetDataScalarTypeToUnsignedShort +reader Update + +set readerOutput [reader GetOutput] +$readerOutput SetOrigin -63 -63 -46 + +# Disconnect the output from its reader. First get an extra reference. +$readerOutput Register {} +$readerOutput SetSource {} + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 600 0.0 + opacityTransferFunction AddPoint 2000 1.0 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction ClampingOff + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 1000.0 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 2000.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + +vtkVolumeRayCastCompositeFunction f +vtkVolumeRayCastMapper volumeMapper + volumeMapper SetInput $readerOutput + volumeMapper SetVolumeRayCastFunction f + volumeMapper SetSampleDistance 0.3 + +# The data object is now referenced by the connection. +$readerOutput UnRegister {} + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# Create geometric sphere +vtkSphereSource sphereSource + sphereSource SetRadius 65 + sphereSource SetThetaResolution 20 + sphereSource SetPhiResolution 40 + +# Compute random scalars (colors) for each cell +vtkProgrammableAttributeDataFilter randomColors + randomColors SetInputConnection [sphereSource GetOutputPort] + randomColors SetExecuteMethod colorCells + +proc colorCells {} { + vtkMath randomColorGenerator + set input [randomColors GetInput] + set output [randomColors GetOutput] + set numCells [$input GetNumberOfCells] + vtkFloatArray colors + colors SetNumberOfTuples $numCells + + for {set i 0} {$i < $numCells} {incr i} { + colors SetValue $i [randomColorGenerator Random 0 1] + } + + [$output GetCellData] CopyScalarsOff + [$output GetCellData] PassData [$input GetCellData] + [$output GetCellData] SetScalars colors + + colors Delete; #reference counting - it's ok + randomColorGenerator Delete +} + +vtkPolyDataMapper sphereMapper + sphereMapper SetInput [randomColors GetPolyDataOutput] + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Set up the planes +vtkPlane plane1 +plane1 SetOrigin 0 0 -10 +plane1 SetNormal 0 0 1 + +vtkPlane plane2 +plane2 SetOrigin 0 0 10 +plane2 SetNormal 0 0 -1 + +vtkPlane plane3 +plane3 SetOrigin -10 0 0 +plane3 SetNormal 1 0 0 + +vtkPlane plane4 +plane4 SetOrigin 10 0 0 +plane4 SetNormal -1 0 0 + +sphereMapper AddClippingPlane plane1 +sphereMapper AddClippingPlane plane2 + +volumeMapper AddClippingPlane plane3 +volumeMapper AddClippingPlane plane4 + + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp sphereActor +ren1 AddViewProp volume +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +[ren1 GetActiveCamera] Azimuth 45 +[ren1 GetActiveCamera] Elevation 15 +[ren1 GetActiveCamera] Roll 45 +[ren1 GetActiveCamera] Zoom 2.0 + +wm withdraw . + +iren Initialize + +for { set i 0 } { $i < 5 } { incr i } { + volume RotateY 17 + volume RotateZ 13 + sphereActor RotateX 13 + sphereActor RotateY 17 +} +renWin Render + diff --git a/Rendering/Testing/Tcl/volTM2DCropRegions.tcl b/Rendering/Testing/Tcl/volTM2DCropRegions.tcl new file mode 100644 index 0000000..d5237ce --- /dev/null +++ b/Rendering/Testing/Tcl/volTM2DCropRegions.tcl @@ -0,0 +1,103 @@ +package require vtk +package require vtkinteraction + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 30 0.0 + opacityTransferFunction AddPoint 80 0.5 + opacityTransferFunction AddPoint 255 0.5 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + volumeProperty ShadeOn + + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 600 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.1 0.2 0.4 + +for { set i 0 } { $i < 2 } { incr i } { + for { set j 0 } { $j < 4 } { incr j } { + vtkVolumeTextureMapper2D volumeMapper_${i}_${j} + volumeMapper_${i}_${j} SetInputConnection [reader GetOutputPort] + volumeMapper_${i}_${j} CroppingOn + volumeMapper_${i}_${j} SetCroppingRegionPlanes 17 33 17 33 17 33 + + vtkVolume volume_${i}_${j} + volume_${i}_${j} SetMapper volumeMapper_${i}_${j} + volume_${i}_${j} SetProperty volumeProperty + + vtkTransform userMatrix_${i}_${j} + userMatrix_${i}_${j} PostMultiply + userMatrix_${i}_${j} Identity + userMatrix_${i}_${j} Translate -25 -25 -25 + + if { $i == 0 } { + userMatrix_${i}_${j} RotateX [expr $j*90 + 20] + userMatrix_${i}_${j} RotateY 20 + } else { + userMatrix_${i}_${j} RotateX 20 + userMatrix_${i}_${j} RotateY [expr $j*90 + 20] + } + + userMatrix_${i}_${j} Translate [expr $j*55 + 25] [expr $i*55 + 25] 0 + + volume_${i}_${j} SetUserTransform userMatrix_${i}_${j} + + ren1 AddViewProp volume_${i}_${j} + } +} + +volumeMapper_0_0 SetCroppingRegionFlagsToSubVolume +volumeMapper_0_1 SetCroppingRegionFlagsToCross +volumeMapper_0_2 SetCroppingRegionFlagsToInvertedCross +volumeMapper_0_3 SetCroppingRegionFlags 24600 + +volumeMapper_1_0 SetCroppingRegionFlagsToFence +volumeMapper_1_1 SetCroppingRegionFlagsToInvertedFence +volumeMapper_1_2 SetCroppingRegionFlags 1 +volumeMapper_1_3 SetCroppingRegionFlags 67117057 + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 3.0 +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/Rendering/Testing/Tcl/volTM2DRotateClip.tcl b/Rendering/Testing/Tcl/volTM2DRotateClip.tcl new file mode 100644 index 0000000..20c897a --- /dev/null +++ b/Rendering/Testing/Tcl/volTM2DRotateClip.tcl @@ -0,0 +1,142 @@ +package require vtk + +# Simple volume rendering example. +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff +reader SetDataSpacing 2 2 1 +reader SetDataScalarTypeToUnsignedShort +reader Update + +set readerOutput [reader GetOutput] +$readerOutput SetOrigin -63 -63 -46 + +# Disconnect the output from its reader. First get an extra reference. +$readerOutput Register {} +$readerOutput SetSource {} + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 600 0.0 + opacityTransferFunction AddPoint 2000 1.0 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction ClampingOff + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 1000.0 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 2000.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + +vtkVolumeTextureMapper2D volumeMapper + volumeMapper SetInput $readerOutput + volumeMapper SetMaximumStorageSize 10000000 + +# The data object is now referenced by the connection. +$readerOutput UnRegister {} + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# Create geometric sphere +vtkSphereSource sphereSource + sphereSource SetRadius 65 + sphereSource SetThetaResolution 20 + sphereSource SetPhiResolution 40 + +# Compute random scalars (colors) for each cell +vtkProgrammableAttributeDataFilter randomColors + randomColors SetInputConnection [sphereSource GetOutputPort] + randomColors SetExecuteMethod colorCells + +proc colorCells {} { + vtkMath randomColorGenerator + set input [randomColors GetInput] + set output [randomColors GetOutput] + set numCells [$input GetNumberOfCells] + vtkFloatArray colors + colors SetNumberOfTuples $numCells + + for {set i 0} {$i < $numCells} {incr i} { + colors SetValue $i [randomColorGenerator Random 0 1] + } + + [$output GetCellData] CopyScalarsOff + [$output GetCellData] PassData [$input GetCellData] + [$output GetCellData] SetScalars colors + + colors Delete; #reference counting - it's ok + randomColorGenerator Delete +} + +vtkPolyDataMapper sphereMapper + sphereMapper SetInput [randomColors GetPolyDataOutput] + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Set up the planes +vtkPlane plane1 +plane1 SetOrigin 0 0 -10 +plane1 SetNormal 0 0 1 + +vtkPlane plane2 +plane2 SetOrigin 0 0 10 +plane2 SetNormal 0 0 -1 + +vtkPlane plane3 +plane3 SetOrigin -10 0 0 +plane3 SetNormal 1 0 0 + +vtkPlane plane4 +plane4 SetOrigin 10 0 0 +plane4 SetNormal -1 0 0 + +sphereMapper AddClippingPlane plane1 +sphereMapper AddClippingPlane plane2 + +volumeMapper AddClippingPlane plane3 +volumeMapper AddClippingPlane plane4 + + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp sphereActor +ren1 AddViewProp volume +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +[ren1 GetActiveCamera] Azimuth 45 +[ren1 GetActiveCamera] Elevation 15 +[ren1 GetActiveCamera] Roll 45 +[ren1 GetActiveCamera] Zoom 2.0 + +wm withdraw . + +iren Initialize + +for { set i 0 } { $i < 5 } { incr i } { + volume RotateY 17 + volume RotateZ 13 + sphereActor RotateX 13 + sphereActor RotateY 17 + renWin Render +} + diff --git a/Rendering/fonts/bin2c.tcl b/Rendering/fonts/bin2c.tcl new file mode 100644 index 0000000..ef6df13 --- /dev/null +++ b/Rendering/fonts/bin2c.tcl @@ -0,0 +1,94 @@ +proc convert_bin_to_c {bin_file_name} { + + # Get binary file size + + if {[catch {file size $bin_file_name} bin_file_size]} { + puts stderr "Error: unable to get size of $bin_file_name" + exit + } + + puts "$bin_file_name is $bin_file_size bytes long." + + # Open binary file + + if {[catch {open $bin_file_name r} bin_file_id]} { + puts stderr "Error: unable to open $bin_file_name" + exit + } + + puts "$bin_file_name is open for reading." + + # Read contents of binary file + + fconfigure $bin_file_id -translation binary + + if {[catch {read $bin_file_id} contents]} { + puts stderr "Error: unable to read contents of $bin_file_name" + exit + } + + set contents_length [string length $contents] + puts "$bin_file_name contents is stored ($contents_length bytes)." + if {$contents_length != $bin_file_size} { + puts stderr "Error: file size does not match length of contents" + exit + } + + # Close binary file + + if {[catch {close $bin_file_id}]} { + puts stderr "Error: unable to close $bin_file_name" + } + + puts "$bin_file_name is closed." + + # Open C file + + set bin_file_rootname [file rootname $bin_file_name] + set bin_file_tail [file tail $bin_file_rootname] + set c_file_name "${bin_file_rootname}.cxx" + + if {[catch {open $c_file_name w} c_file_id]} { + puts stderr "Error: unable to open $c_file_name" + exit + } + + puts "$c_file_name is open for writing." + + # Convert bin to C + + puts "$c_file_name is filled." + + puts $c_file_id "size_t face_${bin_file_tail}_buffer_length = $contents_length;\n" + + puts -nonewline $c_file_id "unsigned char face_${bin_file_tail}_buffer\[\] = {\n " + + for {set i 0} {$i < $contents_length} {incr i} { + scan [string index $contents $i] "%c" byte + puts -nonewline $c_file_id [format "%3d, " $byte] + if {[expr $i % 14] == 13} { + puts -nonewline $c_file_id "\n " + } + } + + puts $c_file_id "\n};" + + # Close C file + + if {[catch {close $c_file_id}]} { + puts stderr "Error: unable to close $c_file_name" + } + + puts "$c_file_name is closed." +} + +if {$argc < 1} { + puts stderr "Error: expecting name of the binary file to convert" + exit +} + +foreach arg $argv { + foreach file [glob -nocomplain $arg] { + convert_bin_to_c $file + } +} diff --git a/Rendering/fonts/face_arial.cxx b/Rendering/fonts/face_arial.cxx new file mode 100644 index 0000000..8425828 --- /dev/null +++ b/Rendering/fonts/face_arial.cxx @@ -0,0 +1,2501 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Arial Normal +// URW Gothic L Book (uagk8a.pfb) +// Contributed by URW + +size_t face_arial_buffer_length = 34871; + +unsigned char face_arial_buffer[] = { + 128, 1, 84, 6, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 58, 32, 85, 82, + 87, 71, 111, 116, 104, 105, 99, 76, 45, 66, 111, 111, 107, 32, + 49, 46, 48, 53, 10, 37, 37, 67, 114, 101, 97, 116, 105, 111, + 110, 68, 97, 116, 101, 58, 32, 87, 101, 100, 32, 68, 101, 99, + 32, 50, 50, 32, 49, 57, 57, 57, 10, 37, 32, 67, 111, 112, + 121, 114, 105, 103, 104, 116, 32, 40, 85, 82, 87, 41, 43, 43, + 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, + 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, + 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, + 112, 109, 101, 110, 116, 10, 37, 32, 40, 85, 82, 87, 41, 43, + 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, + 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, + 111, 112, 109, 101, 110, 116, 10, 37, 32, 83, 101, 101, 32, 116, + 104, 101, 32, 102, 105, 108, 101, 32, 80, 85, 66, 76, 73, 67, + 32, 40, 65, 108, 97, 100, 100, 105, 110, 32, 70, 114, 101, 101, + 32, 80, 117, 98, 108, 105, 99, 32, 76, 105, 99, 101, 110, 115, + 101, 41, 32, 102, 111, 114, 32, 108, 105, 99, 101, 110, 115, 101, + 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 46, 10, 37, + 32, 65, 115, 32, 97, 32, 115, 112, 101, 99, 105, 97, 108, 32, + 101, 120, 99, 101, 112, 116, 105, 111, 110, 44, 32, 112, 101, 114, + 109, 105, 115, 115, 105, 111, 110, 32, 105, 115, 32, 103, 114, 97, + 110, 116, 101, 100, 32, 116, 111, 32, 105, 110, 99, 108, 117, 100, + 101, 32, 116, 104, 105, 115, 32, 102, 111, 110, 116, 10, 37, 32, + 112, 114, 111, 103, 114, 97, 109, 32, 105, 110, 32, 97, 32, 80, + 111, 115, 116, 115, 99, 114, 105, 112, 116, 32, 111, 114, 32, 80, + 68, 70, 32, 102, 105, 108, 101, 32, 116, 104, 97, 116, 32, 99, + 111, 110, 115, 105, 115, 116, 115, 32, 111, 102, 32, 97, 32, 100, + 111, 99, 117, 109, 101, 110, 116, 32, 116, 104, 97, 116, 10, 37, + 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, 116, 101, 120, 116, + 32, 116, 111, 32, 98, 101, 32, 100, 105, 115, 112, 108, 97, 121, + 101, 100, 32, 111, 114, 32, 112, 114, 105, 110, 116, 101, 100, 32, + 117, 115, 105, 110, 103, 32, 116, 104, 105, 115, 32, 102, 111, 110, + 116, 44, 32, 114, 101, 103, 97, 114, 100, 108, 101, 115, 115, 10, + 37, 32, 111, 102, 32, 116, 104, 101, 32, 99, 111, 110, 100, 105, + 116, 105, 111, 110, 115, 32, 111, 114, 32, 108, 105, 99, 101, 110, + 115, 101, 32, 97, 112, 112, 108, 121, 105, 110, 103, 32, 116, 111, + 32, 116, 104, 101, 32, 100, 111, 99, 117, 109, 101, 110, 116, 32, + 105, 116, 115, 101, 108, 102, 46, 10, 49, 50, 32, 100, 105, 99, + 116, 32, 98, 101, 103, 105, 110, 10, 47, 70, 111, 110, 116, 73, + 110, 102, 111, 32, 49, 48, 32, 100, 105, 99, 116, 32, 100, 117, + 112, 32, 98, 101, 103, 105, 110, 10, 47, 118, 101, 114, 115, 105, + 111, 110, 32, 40, 49, 46, 48, 53, 41, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, 78, 111, 116, 105, + 99, 101, 32, 40, 40, 85, 82, 87, 41, 43, 43, 44, 67, 111, + 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, 57, 32, 98, + 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, 101, 115, 105, + 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, + 110, 116, 46, 32, 83, 101, 101, 32, 116, 104, 101, 32, 102, 105, + 108, 101, 32, 80, 85, 66, 76, 73, 67, 32, 40, 65, 108, 97, + 100, 100, 105, 110, 32, 70, 114, 101, 101, 32, 80, 117, 98, 108, + 105, 99, 32, 76, 105, 99, 101, 110, 115, 101, 41, 32, 102, 111, + 114, 32, 108, 105, 99, 101, 110, 115, 101, 32, 99, 111, 110, 100, + 105, 116, 105, 111, 110, 115, 46, 32, 65, 115, 32, 97, 32, 115, + 112, 101, 99, 105, 97, 108, 32, 101, 120, 99, 101, 112, 116, 105, + 111, 110, 44, 32, 112, 101, 114, 109, 105, 115, 115, 105, 111, 110, + 32, 105, 115, 32, 103, 114, 97, 110, 116, 101, 100, 32, 116, 111, + 32, 105, 110, 99, 108, 117, 100, 101, 32, 116, 104, 105, 115, 32, + 102, 111, 110, 116, 32, 112, 114, 111, 103, 114, 97, 109, 32, 105, + 110, 32, 97, 32, 80, 111, 115, 116, 115, 99, 114, 105, 112, 116, + 32, 111, 114, 32, 80, 68, 70, 32, 102, 105, 108, 101, 32, 116, + 104, 97, 116, 32, 99, 111, 110, 115, 105, 115, 116, 115, 32, 111, + 102, 32, 97, 32, 100, 111, 99, 117, 109, 101, 110, 116, 32, 116, + 104, 97, 116, 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, 116, + 101, 120, 116, 32, 116, 111, 32, 98, 101, 32, 100, 105, 115, 112, + 108, 97, 121, 101, 100, 32, 111, 114, 32, 112, 114, 105, 110, 116, + 101, 100, 32, 117, 115, 105, 110, 103, 32, 116, 104, 105, 115, 32, + 102, 111, 110, 116, 44, 32, 114, 101, 103, 97, 114, 100, 108, 101, + 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, 99, 111, 110, 100, + 105, 116, 105, 111, 110, 115, 32, 111, 114, 32, 108, 105, 99, 101, + 110, 115, 101, 32, 97, 112, 112, 108, 121, 105, 110, 103, 32, 116, + 111, 32, 116, 104, 101, 32, 100, 111, 99, 117, 109, 101, 110, 116, + 32, 105, 116, 115, 101, 108, 102, 46, 41, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, 67, 111, 112, 121, + 114, 105, 103, 104, 116, 32, 40, 67, 111, 112, 121, 114, 105, 103, + 104, 116, 32, 40, 85, 82, 87, 41, 43, 43, 44, 67, 111, 112, + 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, 57, 32, 98, 121, + 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, 101, 115, 105, 103, + 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, + 116, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, + 102, 10, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 85, + 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, 76, 32, 66, 111, + 111, 107, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, + 101, 102, 10, 47, 70, 97, 109, 105, 108, 121, 78, 97, 109, 101, + 32, 40, 85, 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, 76, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 10, 47, 87, 101, 105, 103, 104, 116, 32, 40, 66, 111, 111, 107, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 10, 47, 73, 116, 97, 108, 105, 99, 65, 110, 103, 108, 101, 32, + 48, 46, 48, 32, 100, 101, 102, 10, 47, 105, 115, 70, 105, 120, + 101, 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, 101, 32, + 100, 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, + 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 57, 54, 32, 100, + 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 84, + 104, 105, 99, 107, 110, 101, 115, 115, 32, 53, 56, 32, 100, 101, + 102, 10, 101, 110, 100, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 10, 47, 70, 111, 110, 116, 78, 97, 109, 101, + 32, 47, 85, 82, 87, 71, 111, 116, 104, 105, 99, 76, 45, 66, + 111, 111, 107, 32, 100, 101, 102, 10, 47, 80, 97, 105, 110, 116, + 84, 121, 112, 101, 32, 48, 32, 100, 101, 102, 10, 47, 87, 77, + 111, 100, 101, 32, 48, 32, 100, 101, 102, 10, 47, 70, 111, 110, + 116, 66, 66, 111, 120, 32, 123, 45, 49, 49, 53, 32, 45, 50, + 52, 48, 32, 49, 49, 53, 49, 32, 57, 55, 54, 125, 32, 114, + 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, 70, + 111, 110, 116, 84, 121, 112, 101, 32, 49, 32, 100, 101, 102, 10, + 47, 70, 111, 110, 116, 77, 97, 116, 114, 105, 120, 32, 91, 48, + 46, 48, 48, 49, 32, 48, 46, 48, 32, 48, 46, 48, 32, 48, + 46, 48, 48, 49, 32, 48, 46, 48, 32, 48, 46, 48, 93, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 69, 110, 99, 111, 100, 105, 110, 103, 32, 83, 116, 97, 110, 100, + 97, 114, 100, 69, 110, 99, 111, 100, 105, 110, 103, 32, 100, 101, + 102, 10, 47, 85, 110, 105, 113, 117, 101, 73, 68, 32, 53, 48, + 49, 57, 53, 53, 51, 32, 100, 101, 102, 10, 99, 117, 114, 114, + 101, 110, 116, 100, 105, 99, 116, 32, 101, 110, 100, 10, 99, 117, + 114, 114, 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, 101, + 99, 13, 128, 2, 187, 127, 0, 0, 233, 141, 9, 215, 96, 163, + 194, 44, 241, 25, 249, 220, 105, 154, 34, 195, 91, 91, 53, 237, + 106, 162, 53, 147, 199, 109, 84, 202, 187, 94, 148, 43, 247, 214, + 221, 132, 241, 102, 75, 137, 105, 156, 116, 180, 114, 222, 159, 142, + 109, 249, 37, 246, 196, 242, 4, 233, 241, 198, 57, 180, 219, 169, + 136, 237, 42, 196, 25, 255, 43, 43, 222, 96, 91, 142, 227, 38, + 78, 221, 102, 65, 45, 79, 33, 198, 74, 197, 34, 189, 252, 124, + 85, 2, 249, 195, 243, 229, 89, 43, 59, 32, 147, 211, 60, 155, + 250, 237, 210, 212, 158, 137, 170, 186, 168, 50, 226, 63, 6, 46, + 145, 162, 80, 50, 81, 157, 24, 104, 129, 110, 68, 180, 224, 116, + 119, 149, 0, 61, 121, 48, 41, 157, 110, 30, 42, 91, 254, 13, + 89, 93, 201, 126, 20, 9, 137, 206, 129, 216, 215, 248, 82, 255, + 156, 220, 122, 27, 27, 89, 140, 105, 19, 29, 238, 0, 91, 65, + 88, 5, 161, 109, 137, 109, 248, 53, 147, 198, 182, 175, 174, 184, + 176, 166, 7, 20, 113, 232, 144, 91, 15, 51, 69, 99, 203, 147, + 112, 163, 68, 81, 104, 255, 241, 180, 22, 136, 149, 122, 168, 215, + 38, 128, 216, 54, 43, 241, 35, 12, 118, 123, 194, 89, 40, 240, + 88, 24, 163, 148, 19, 71, 179, 250, 209, 173, 98, 2, 61, 108, + 39, 178, 72, 109, 195, 13, 242, 18, 154, 56, 166, 221, 144, 182, + 251, 84, 128, 89, 146, 151, 170, 94, 213, 18, 67, 76, 185, 64, + 71, 106, 70, 143, 46, 55, 215, 180, 170, 177, 53, 85, 162, 97, + 21, 70, 160, 255, 28, 41, 39, 91, 39, 45, 197, 76, 162, 227, + 4, 48, 16, 80, 69, 222, 75, 18, 87, 173, 249, 180, 60, 26, + 124, 71, 2, 5, 126, 182, 81, 106, 143, 39, 220, 161, 96, 125, + 182, 7, 246, 9, 113, 104, 123, 242, 12, 229, 19, 202, 61, 83, + 13, 112, 140, 139, 186, 245, 214, 158, 128, 162, 149, 153, 67, 242, + 35, 156, 165, 0, 135, 146, 194, 171, 53, 126, 252, 9, 242, 185, + 162, 251, 139, 209, 127, 253, 127, 71, 218, 141, 187, 10, 85, 33, + 234, 15, 165, 116, 226, 24, 164, 65, 200, 171, 197, 65, 185, 34, + 245, 80, 159, 226, 14, 137, 181, 192, 30, 217, 2, 108, 129, 139, + 208, 143, 198, 131, 173, 4, 201, 75, 254, 11, 158, 182, 11, 105, + 49, 167, 200, 2, 116, 27, 96, 51, 55, 213, 234, 216, 116, 124, + 98, 157, 99, 215, 24, 20, 244, 30, 40, 54, 52, 188, 79, 234, + 17, 61, 196, 107, 12, 132, 231, 36, 222, 100, 144, 230, 189, 240, + 247, 83, 41, 113, 139, 39, 0, 229, 3, 189, 231, 222, 244, 99, + 17, 158, 220, 26, 53, 81, 187, 217, 5, 0, 23, 24, 181, 106, + 123, 128, 28, 197, 27, 224, 244, 199, 222, 85, 116, 130, 187, 146, + 118, 43, 235, 47, 78, 60, 108, 126, 150, 81, 253, 7, 210, 42, + 110, 57, 250, 3, 200, 194, 133, 147, 170, 229, 166, 160, 177, 222, + 240, 142, 42, 76, 16, 125, 78, 159, 235, 199, 213, 210, 250, 66, + 241, 207, 106, 0, 178, 106, 162, 251, 126, 165, 49, 154, 192, 221, + 64, 120, 51, 145, 171, 221, 216, 136, 145, 196, 149, 96, 124, 30, + 172, 226, 203, 64, 128, 161, 108, 86, 179, 6, 213, 191, 108, 215, + 88, 105, 238, 157, 43, 254, 25, 196, 48, 68, 160, 215, 11, 181, + 133, 220, 66, 212, 144, 76, 154, 218, 107, 84, 251, 171, 44, 178, + 243, 223, 133, 236, 180, 190, 128, 10, 60, 181, 155, 237, 127, 27, + 223, 44, 35, 226, 126, 171, 40, 224, 89, 158, 168, 160, 218, 59, + 132, 35, 40, 37, 7, 168, 200, 61, 185, 157, 105, 207, 160, 108, + 166, 203, 25, 213, 199, 237, 35, 163, 48, 139, 69, 20, 65, 168, + 155, 118, 254, 229, 67, 174, 0, 207, 200, 206, 137, 202, 217, 28, + 83, 59, 208, 97, 19, 91, 163, 229, 57, 127, 85, 95, 210, 68, + 244, 219, 83, 200, 169, 99, 121, 201, 85, 226, 255, 73, 153, 198, + 32, 120, 166, 160, 101, 9, 147, 109, 198, 236, 30, 184, 125, 252, + 248, 93, 149, 169, 24, 240, 36, 30, 234, 195, 6, 219, 28, 38, + 149, 214, 180, 94, 59, 45, 7, 72, 188, 6, 124, 83, 231, 9, + 101, 14, 156, 223, 253, 99, 217, 22, 35, 167, 212, 250, 103, 107, + 211, 140, 151, 151, 89, 109, 86, 23, 110, 62, 45, 36, 218, 69, + 150, 56, 16, 3, 221, 207, 167, 162, 103, 142, 182, 117, 99, 190, + 110, 75, 219, 3, 43, 236, 148, 25, 117, 245, 66, 195, 68, 97, + 248, 169, 111, 170, 55, 36, 182, 65, 99, 74, 153, 246, 163, 231, + 95, 39, 78, 99, 77, 196, 4, 25, 188, 236, 132, 165, 136, 139, + 169, 2, 145, 156, 5, 200, 216, 31, 172, 85, 27, 63, 203, 160, + 244, 228, 55, 0, 217, 183, 193, 192, 102, 148, 141, 253, 141, 21, + 195, 124, 72, 217, 69, 177, 176, 39, 138, 82, 141, 86, 166, 251, + 233, 243, 0, 222, 147, 12, 41, 52, 96, 91, 0, 101, 27, 167, + 124, 221, 223, 165, 198, 92, 31, 136, 239, 161, 14, 250, 70, 158, + 35, 5, 13, 246, 222, 122, 86, 104, 152, 243, 32, 183, 27, 1, + 106, 45, 160, 164, 50, 26, 68, 254, 207, 204, 165, 234, 92, 62, + 117, 135, 114, 123, 100, 210, 213, 111, 46, 222, 124, 116, 161, 252, + 210, 30, 87, 137, 169, 60, 134, 38, 233, 128, 48, 60, 26, 187, + 55, 56, 234, 52, 252, 133, 103, 109, 130, 83, 12, 175, 113, 48, + 46, 198, 73, 8, 245, 149, 129, 99, 135, 135, 112, 69, 117, 34, + 56, 95, 161, 193, 188, 223, 98, 89, 95, 227, 68, 218, 163, 51, + 127, 201, 229, 187, 7, 238, 232, 185, 51, 237, 232, 233, 106, 159, + 6, 86, 99, 119, 210, 222, 195, 94, 159, 210, 46, 225, 226, 126, + 128, 17, 120, 251, 69, 54, 92, 112, 56, 211, 242, 103, 246, 70, + 69, 14, 183, 74, 201, 172, 137, 84, 181, 228, 91, 171, 98, 206, + 115, 25, 74, 3, 81, 246, 188, 173, 234, 172, 148, 182, 252, 208, + 23, 209, 80, 174, 177, 31, 225, 140, 101, 34, 111, 21, 253, 118, + 49, 118, 183, 199, 104, 216, 203, 245, 226, 124, 199, 89, 161, 199, + 8, 190, 229, 143, 43, 51, 173, 105, 135, 24, 107, 157, 202, 148, + 143, 24, 52, 19, 6, 49, 22, 41, 222, 131, 178, 72, 27, 115, + 189, 145, 138, 186, 62, 66, 111, 174, 159, 232, 198, 109, 253, 189, + 213, 121, 212, 152, 243, 11, 49, 102, 133, 48, 79, 84, 146, 95, + 73, 85, 44, 225, 97, 249, 48, 85, 195, 67, 44, 70, 193, 66, + 185, 220, 117, 94, 224, 124, 208, 158, 101, 156, 83, 160, 134, 141, + 221, 138, 49, 160, 9, 10, 124, 15, 170, 6, 157, 162, 72, 41, + 124, 159, 29, 203, 80, 90, 120, 184, 133, 185, 110, 128, 97, 80, + 255, 141, 15, 172, 66, 166, 77, 132, 181, 225, 193, 228, 70, 174, + 20, 100, 62, 101, 208, 167, 212, 246, 200, 186, 235, 5, 70, 54, + 156, 250, 135, 217, 197, 132, 117, 145, 99, 56, 93, 133, 65, 172, + 138, 252, 242, 172, 30, 135, 80, 189, 67, 149, 18, 238, 104, 36, + 159, 175, 34, 69, 182, 122, 94, 228, 158, 218, 154, 92, 70, 62, + 215, 82, 169, 1, 28, 13, 216, 14, 12, 7, 86, 249, 209, 119, + 157, 219, 100, 191, 146, 49, 66, 149, 53, 232, 36, 22, 124, 148, + 93, 29, 124, 202, 178, 152, 74, 66, 18, 35, 238, 131, 66, 163, + 253, 98, 153, 124, 164, 224, 150, 166, 148, 243, 135, 9, 165, 143, + 109, 48, 45, 124, 53, 147, 164, 39, 128, 116, 164, 222, 52, 142, + 9, 46, 134, 140, 52, 142, 225, 44, 100, 60, 182, 136, 144, 101, + 144, 224, 29, 149, 88, 245, 179, 250, 221, 156, 250, 164, 119, 19, + 47, 135, 128, 244, 126, 143, 59, 13, 251, 137, 170, 29, 15, 163, + 4, 58, 122, 41, 253, 80, 76, 238, 53, 117, 99, 167, 87, 112, + 24, 232, 21, 7, 1, 23, 41, 63, 229, 21, 53, 250, 27, 65, + 252, 199, 70, 115, 174, 40, 38, 11, 251, 64, 90, 94, 152, 249, + 87, 248, 136, 115, 229, 49, 168, 97, 192, 37, 103, 218, 107, 123, + 138, 153, 76, 33, 31, 46, 142, 31, 173, 48, 16, 206, 181, 115, + 119, 136, 224, 124, 5, 1, 77, 138, 43, 89, 184, 1, 195, 80, + 199, 168, 99, 155, 165, 116, 123, 26, 136, 41, 235, 20, 136, 62, + 167, 220, 10, 193, 247, 43, 227, 119, 57, 60, 20, 145, 37, 239, + 43, 129, 52, 255, 153, 52, 108, 5, 80, 132, 79, 83, 0, 215, + 254, 248, 137, 85, 52, 151, 223, 147, 203, 166, 238, 221, 193, 133, + 173, 27, 225, 140, 201, 78, 35, 222, 73, 248, 210, 10, 125, 146, + 14, 238, 7, 131, 77, 252, 194, 170, 227, 201, 218, 183, 207, 95, + 216, 236, 26, 109, 88, 196, 212, 100, 118, 129, 223, 17, 236, 248, + 187, 172, 124, 102, 114, 130, 160, 194, 64, 14, 131, 186, 54, 217, + 19, 79, 251, 137, 158, 180, 144, 111, 203, 217, 122, 40, 149, 56, + 168, 191, 183, 239, 52, 144, 48, 67, 124, 118, 113, 125, 181, 147, + 22, 196, 35, 126, 242, 76, 7, 178, 192, 203, 234, 83, 103, 78, + 40, 117, 125, 28, 185, 228, 200, 242, 241, 57, 92, 236, 183, 232, + 107, 36, 251, 200, 217, 55, 203, 209, 135, 10, 155, 139, 210, 81, + 232, 48, 167, 35, 203, 249, 207, 159, 65, 25, 10, 198, 206, 176, + 146, 37, 4, 104, 138, 181, 143, 107, 92, 214, 106, 159, 120, 59, + 96, 75, 103, 226, 3, 127, 251, 153, 183, 234, 21, 153, 130, 254, + 49, 248, 149, 205, 1, 98, 193, 62, 229, 91, 150, 10, 67, 27, + 110, 198, 159, 110, 2, 153, 168, 125, 246, 101, 91, 237, 5, 62, + 96, 152, 226, 63, 132, 195, 89, 200, 163, 196, 189, 15, 157, 250, + 69, 65, 61, 66, 157, 214, 254, 84, 15, 16, 96, 6, 76, 159, + 42, 62, 189, 216, 174, 56, 126, 102, 132, 87, 145, 14, 33, 225, + 227, 28, 224, 182, 30, 85, 8, 232, 200, 32, 54, 34, 199, 41, + 8, 253, 57, 4, 227, 98, 7, 235, 46, 116, 128, 225, 32, 129, + 150, 211, 10, 252, 81, 104, 9, 251, 228, 214, 139, 182, 223, 202, + 1, 54, 129, 164, 112, 14, 64, 98, 112, 207, 135, 50, 144, 233, + 106, 148, 155, 121, 135, 190, 112, 137, 66, 153, 92, 188, 81, 100, + 124, 255, 115, 198, 228, 253, 123, 230, 82, 176, 196, 128, 170, 74, + 123, 69, 27, 146, 34, 44, 17, 23, 156, 221, 98, 129, 87, 198, + 123, 199, 103, 208, 79, 241, 84, 190, 208, 39, 200, 243, 110, 224, + 25, 21, 142, 121, 157, 80, 97, 11, 164, 28, 100, 111, 240, 42, + 40, 135, 186, 2, 15, 91, 191, 152, 43, 53, 132, 229, 113, 116, + 146, 86, 237, 186, 230, 200, 0, 18, 171, 142, 40, 231, 173, 189, + 74, 43, 126, 72, 241, 61, 208, 234, 118, 29, 64, 229, 251, 186, + 12, 134, 71, 132, 0, 237, 106, 200, 245, 41, 128, 1, 226, 245, + 19, 224, 164, 152, 18, 31, 143, 99, 190, 219, 138, 87, 88, 137, + 228, 113, 184, 105, 55, 241, 146, 124, 112, 159, 79, 168, 227, 174, + 43, 37, 62, 1, 44, 86, 238, 224, 230, 70, 123, 41, 86, 111, + 97, 89, 61, 228, 35, 225, 26, 249, 9, 31, 177, 138, 134, 157, + 115, 220, 115, 128, 45, 229, 9, 93, 230, 128, 239, 3, 214, 33, + 160, 175, 196, 141, 136, 62, 97, 67, 235, 134, 212, 196, 91, 219, + 99, 33, 234, 159, 20, 223, 79, 189, 117, 36, 32, 101, 85, 88, + 29, 57, 181, 102, 241, 225, 6, 151, 63, 31, 20, 243, 59, 60, + 195, 161, 115, 167, 52, 107, 74, 237, 242, 148, 154, 236, 254, 108, + 37, 90, 234, 120, 93, 131, 138, 149, 6, 195, 232, 57, 161, 5, + 105, 135, 169, 200, 48, 16, 132, 174, 7, 14, 110, 212, 95, 150, + 29, 119, 169, 233, 253, 93, 106, 119, 115, 227, 162, 193, 56, 100, + 240, 245, 39, 63, 105, 29, 96, 181, 51, 252, 219, 20, 199, 177, + 3, 252, 96, 242, 47, 195, 64, 23, 96, 216, 6, 251, 45, 188, + 122, 253, 1, 180, 99, 32, 92, 67, 218, 34, 18, 13, 110, 164, + 80, 56, 98, 157, 175, 90, 227, 21, 172, 248, 169, 113, 2, 129, + 152, 98, 62, 157, 78, 243, 208, 183, 112, 247, 220, 22, 108, 133, + 158, 101, 65, 177, 114, 233, 104, 131, 152, 105, 207, 240, 3, 232, + 149, 170, 5, 26, 133, 207, 142, 192, 130, 56, 111, 173, 95, 237, + 171, 154, 164, 159, 63, 37, 158, 183, 227, 13, 127, 197, 57, 73, + 167, 117, 15, 51, 225, 67, 50, 35, 153, 120, 115, 207, 102, 241, + 246, 254, 14, 217, 182, 79, 158, 237, 15, 150, 217, 243, 179, 30, + 89, 212, 66, 241, 218, 160, 221, 218, 30, 82, 13, 163, 22, 44, + 87, 41, 52, 247, 87, 48, 177, 64, 245, 11, 225, 71, 212, 246, + 145, 161, 175, 33, 141, 211, 72, 173, 239, 151, 229, 181, 228, 199, + 83, 251, 129, 28, 226, 207, 33, 193, 231, 132, 83, 65, 1, 85, + 121, 139, 128, 220, 78, 136, 242, 207, 110, 147, 238, 214, 86, 116, + 97, 62, 176, 255, 24, 163, 118, 255, 111, 46, 1, 155, 145, 60, + 69, 151, 185, 175, 30, 153, 165, 28, 244, 222, 182, 178, 77, 124, + 23, 178, 6, 122, 197, 168, 254, 119, 2, 124, 179, 25, 189, 225, + 195, 185, 86, 207, 125, 101, 1, 213, 247, 240, 237, 156, 192, 148, + 123, 43, 55, 204, 38, 92, 88, 113, 159, 75, 231, 17, 204, 139, + 112, 44, 72, 16, 223, 93, 120, 235, 55, 250, 178, 43, 111, 112, + 103, 66, 136, 224, 77, 27, 91, 47, 163, 86, 144, 23, 163, 225, + 146, 245, 200, 131, 168, 208, 167, 151, 209, 126, 79, 93, 113, 104, + 139, 113, 210, 68, 40, 8, 139, 85, 180, 130, 246, 4, 167, 88, + 16, 89, 6, 109, 183, 145, 62, 82, 114, 244, 140, 124, 32, 228, + 149, 134, 249, 117, 230, 42, 62, 144, 99, 92, 96, 40, 1, 34, + 64, 202, 33, 64, 24, 27, 181, 45, 126, 190, 161, 236, 218, 34, + 157, 182, 82, 208, 83, 130, 151, 163, 231, 60, 169, 20, 184, 66, + 60, 67, 18, 234, 35, 160, 79, 109, 217, 228, 121, 148, 59, 137, + 77, 15, 34, 50, 227, 52, 53, 6, 119, 145, 1, 152, 89, 38, + 64, 129, 249, 168, 38, 244, 25, 244, 68, 179, 214, 142, 147, 81, + 125, 3, 11, 41, 145, 87, 116, 9, 135, 121, 190, 60, 128, 200, + 233, 100, 113, 25, 125, 173, 215, 109, 197, 9, 28, 246, 51, 136, + 205, 165, 124, 97, 203, 96, 252, 60, 19, 237, 9, 225, 239, 201, + 152, 230, 63, 161, 182, 40, 186, 115, 115, 171, 157, 189, 178, 6, + 208, 54, 113, 214, 177, 112, 181, 37, 178, 138, 191, 221, 215, 121, + 253, 112, 188, 20, 239, 87, 164, 13, 168, 224, 173, 21, 241, 141, + 23, 212, 197, 133, 92, 89, 207, 158, 120, 44, 251, 144, 38, 197, + 10, 190, 35, 33, 195, 39, 147, 149, 233, 90, 5, 70, 100, 90, + 5, 224, 82, 100, 28, 99, 132, 115, 81, 50, 106, 58, 47, 108, + 104, 233, 35, 201, 161, 64, 170, 154, 244, 185, 254, 98, 101, 69, + 244, 202, 211, 18, 188, 250, 149, 77, 170, 29, 35, 117, 243, 243, + 224, 91, 129, 141, 68, 173, 31, 80, 237, 105, 249, 215, 113, 126, + 97, 85, 247, 214, 20, 218, 32, 234, 107, 60, 147, 81, 84, 239, + 46, 155, 212, 202, 89, 180, 151, 187, 111, 234, 164, 205, 161, 189, + 37, 88, 14, 230, 182, 159, 33, 199, 142, 92, 242, 50, 225, 46, + 38, 140, 253, 194, 73, 93, 85, 207, 123, 148, 2, 188, 7, 203, + 94, 86, 196, 32, 84, 35, 4, 152, 21, 221, 24, 236, 207, 121, + 174, 117, 119, 7, 35, 208, 251, 94, 252, 52, 19, 110, 41, 24, + 253, 219, 200, 98, 17, 47, 27, 41, 132, 171, 250, 105, 180, 237, + 17, 89, 32, 127, 86, 246, 217, 11, 251, 44, 84, 232, 153, 53, + 50, 228, 235, 33, 16, 139, 183, 87, 247, 60, 71, 191, 69, 25, + 209, 255, 19, 252, 95, 60, 133, 21, 65, 240, 170, 211, 39, 53, + 51, 240, 147, 85, 174, 188, 131, 122, 199, 66, 252, 134, 125, 107, + 74, 34, 249, 91, 214, 148, 198, 11, 29, 199, 24, 183, 140, 125, + 93, 250, 126, 53, 221, 174, 106, 98, 42, 28, 23, 254, 59, 85, + 245, 198, 172, 37, 16, 82, 173, 107, 126, 3, 131, 45, 182, 159, + 208, 17, 63, 89, 160, 254, 230, 11, 131, 66, 171, 181, 188, 110, + 95, 85, 123, 216, 17, 135, 46, 131, 241, 136, 37, 47, 210, 178, + 67, 214, 201, 151, 126, 98, 99, 115, 212, 239, 71, 116, 67, 251, + 84, 173, 120, 98, 186, 127, 161, 252, 147, 94, 199, 61, 42, 210, + 200, 177, 147, 17, 60, 135, 133, 96, 39, 240, 91, 208, 29, 54, + 216, 46, 239, 6, 27, 248, 179, 60, 229, 39, 2, 184, 244, 226, + 72, 4, 46, 59, 163, 45, 96, 8, 188, 217, 149, 98, 60, 155, + 168, 161, 3, 141, 48, 170, 85, 26, 43, 34, 156, 46, 217, 36, + 159, 71, 154, 68, 188, 252, 13, 128, 46, 80, 134, 146, 192, 223, + 210, 152, 246, 219, 253, 202, 135, 27, 25, 67, 115, 25, 246, 81, + 91, 54, 239, 154, 218, 201, 188, 157, 200, 55, 179, 56, 106, 191, + 16, 72, 254, 30, 5, 3, 48, 151, 171, 63, 102, 100, 77, 192, + 185, 16, 143, 191, 70, 120, 34, 66, 97, 148, 9, 62, 34, 119, + 70, 222, 240, 100, 37, 34, 225, 80, 13, 22, 139, 19, 64, 12, + 177, 96, 94, 146, 135, 75, 31, 42, 66, 27, 226, 239, 235, 92, + 74, 193, 82, 96, 180, 207, 244, 205, 63, 203, 72, 6, 175, 155, + 20, 174, 56, 151, 207, 101, 200, 56, 150, 229, 65, 170, 73, 83, + 251, 129, 165, 161, 142, 152, 233, 127, 59, 224, 91, 47, 23, 90, + 14, 125, 151, 135, 66, 206, 167, 150, 149, 162, 111, 68, 27, 218, + 18, 125, 1, 240, 65, 53, 71, 2, 125, 125, 197, 195, 57, 254, + 65, 160, 48, 186, 237, 63, 215, 199, 5, 66, 90, 75, 83, 216, + 70, 176, 34, 71, 114, 248, 16, 63, 88, 8, 200, 226, 193, 255, + 79, 158, 81, 21, 107, 196, 61, 217, 46, 203, 110, 156, 148, 156, + 83, 114, 58, 163, 95, 187, 101, 11, 19, 236, 137, 35, 109, 49, + 220, 63, 237, 150, 37, 221, 187, 110, 248, 67, 65, 195, 37, 82, + 11, 183, 22, 168, 198, 234, 48, 146, 184, 131, 146, 104, 81, 113, + 63, 245, 135, 208, 60, 239, 28, 67, 18, 207, 85, 93, 162, 143, + 117, 179, 133, 27, 144, 80, 250, 202, 176, 27, 25, 127, 122, 185, + 125, 56, 182, 83, 123, 142, 30, 18, 0, 239, 87, 56, 65, 98, + 190, 15, 64, 78, 169, 152, 247, 3, 16, 237, 207, 223, 199, 124, + 141, 187, 65, 236, 143, 243, 227, 240, 75, 150, 15, 215, 193, 217, + 71, 104, 123, 42, 77, 226, 21, 90, 134, 11, 69, 189, 37, 180, + 172, 22, 0, 92, 199, 68, 119, 130, 2, 85, 138, 66, 249, 124, + 137, 96, 28, 197, 227, 122, 187, 13, 140, 45, 96, 123, 198, 28, + 157, 191, 230, 13, 175, 250, 84, 109, 177, 165, 162, 191, 54, 110, + 155, 241, 96, 239, 90, 61, 225, 68, 212, 75, 182, 250, 202, 143, + 123, 22, 48, 61, 22, 232, 176, 76, 220, 68, 247, 52, 155, 29, + 144, 17, 49, 55, 212, 254, 165, 43, 48, 147, 66, 100, 169, 42, + 116, 253, 178, 178, 212, 139, 24, 171, 92, 252, 123, 56, 237, 6, + 86, 215, 10, 220, 4, 220, 76, 110, 50, 208, 85, 22, 117, 250, + 0, 254, 122, 91, 59, 127, 46, 219, 143, 160, 211, 95, 77, 118, + 170, 253, 171, 7, 85, 203, 43, 197, 171, 175, 192, 168, 137, 101, + 52, 198, 142, 49, 175, 121, 149, 105, 228, 230, 186, 50, 22, 164, + 17, 110, 29, 240, 222, 55, 115, 228, 134, 253, 112, 156, 187, 101, + 54, 90, 97, 61, 238, 171, 174, 92, 10, 46, 254, 94, 205, 209, + 79, 11, 248, 150, 228, 247, 29, 220, 185, 250, 126, 43, 69, 124, + 65, 71, 117, 131, 39, 44, 19, 25, 39, 77, 252, 86, 180, 227, + 203, 97, 123, 173, 253, 112, 222, 68, 181, 97, 184, 176, 247, 210, + 23, 83, 59, 124, 175, 33, 149, 232, 159, 102, 216, 189, 196, 207, + 226, 229, 83, 157, 26, 255, 75, 193, 194, 142, 18, 126, 147, 227, + 171, 10, 155, 61, 114, 52, 156, 100, 55, 33, 110, 175, 214, 156, + 120, 131, 158, 60, 33, 17, 160, 93, 87, 21, 192, 212, 55, 187, + 150, 152, 245, 157, 225, 154, 215, 204, 208, 32, 242, 49, 140, 159, + 110, 45, 120, 175, 99, 35, 116, 236, 51, 157, 223, 239, 1, 97, + 93, 234, 115, 26, 115, 130, 166, 227, 215, 95, 166, 89, 101, 223, + 49, 203, 243, 144, 3, 150, 62, 203, 240, 205, 22, 233, 92, 145, + 67, 175, 146, 104, 243, 23, 136, 61, 242, 212, 174, 96, 30, 129, + 121, 96, 240, 156, 155, 115, 44, 51, 230, 253, 201, 103, 231, 85, + 238, 202, 185, 38, 240, 20, 48, 180, 108, 168, 239, 14, 135, 96, + 118, 233, 160, 150, 73, 230, 79, 173, 47, 81, 210, 33, 143, 136, + 139, 160, 28, 25, 202, 3, 235, 226, 241, 238, 229, 104, 178, 40, + 206, 140, 105, 255, 140, 170, 6, 228, 209, 180, 146, 50, 216, 176, + 112, 25, 144, 62, 240, 14, 4, 84, 45, 232, 57, 20, 178, 255, + 198, 33, 244, 133, 215, 158, 109, 74, 91, 167, 123, 92, 140, 92, + 113, 245, 180, 99, 52, 114, 163, 58, 131, 120, 81, 65, 77, 210, + 143, 143, 92, 145, 101, 109, 10, 3, 156, 22, 35, 123, 21, 222, + 93, 118, 209, 8, 150, 61, 140, 128, 154, 207, 249, 69, 6, 100, + 126, 40, 213, 180, 3, 21, 192, 54, 164, 175, 126, 121, 217, 1, + 175, 183, 103, 56, 109, 178, 176, 97, 39, 72, 123, 55, 93, 78, + 58, 177, 50, 238, 166, 27, 22, 53, 195, 230, 128, 189, 174, 249, + 59, 28, 140, 83, 62, 148, 57, 119, 163, 61, 212, 53, 248, 131, + 247, 70, 94, 108, 13, 221, 42, 25, 41, 97, 90, 143, 178, 239, + 100, 250, 239, 221, 231, 137, 36, 88, 73, 69, 33, 113, 86, 5, + 242, 36, 153, 105, 160, 35, 117, 63, 38, 193, 88, 78, 135, 63, + 26, 220, 201, 225, 99, 175, 123, 164, 28, 195, 142, 43, 43, 33, + 243, 35, 181, 90, 224, 13, 109, 143, 50, 53, 221, 109, 58, 227, + 125, 97, 225, 112, 226, 221, 172, 12, 202, 130, 112, 110, 151, 196, + 123, 135, 137, 49, 241, 238, 182, 56, 232, 242, 95, 134, 202, 92, + 223, 64, 155, 196, 26, 143, 192, 30, 177, 243, 187, 32, 222, 28, + 31, 66, 175, 168, 194, 153, 122, 167, 144, 132, 26, 160, 83, 16, + 23, 215, 75, 71, 225, 128, 169, 130, 0, 25, 20, 186, 220, 74, + 123, 240, 211, 161, 91, 61, 26, 175, 104, 226, 84, 4, 8, 167, + 17, 157, 103, 242, 82, 241, 107, 1, 3, 209, 22, 207, 189, 13, + 4, 218, 65, 177, 186, 251, 76, 167, 161, 107, 140, 108, 90, 234, + 135, 246, 131, 61, 107, 179, 6, 38, 133, 15, 53, 84, 54, 128, + 215, 112, 98, 62, 124, 215, 182, 51, 199, 181, 223, 117, 217, 221, + 5, 148, 110, 89, 86, 181, 166, 3, 219, 136, 113, 180, 64, 197, + 172, 52, 27, 114, 15, 90, 231, 210, 64, 168, 50, 85, 47, 131, + 153, 57, 110, 3, 165, 77, 211, 229, 66, 250, 0, 35, 113, 70, + 32, 199, 90, 32, 170, 101, 166, 222, 96, 95, 110, 210, 179, 122, + 222, 135, 192, 58, 45, 209, 62, 227, 11, 61, 169, 75, 225, 119, + 22, 182, 172, 238, 100, 122, 243, 240, 164, 24, 196, 208, 250, 163, + 110, 190, 50, 148, 12, 66, 40, 230, 79, 232, 243, 245, 10, 80, + 73, 131, 144, 194, 61, 65, 49, 93, 168, 29, 138, 108, 98, 189, + 198, 145, 144, 1, 212, 19, 167, 234, 221, 229, 106, 37, 115, 138, + 95, 231, 209, 93, 93, 153, 24, 62, 95, 170, 60, 17, 40, 229, + 6, 97, 187, 70, 152, 208, 146, 170, 103, 102, 80, 255, 0, 63, + 115, 45, 164, 198, 36, 191, 130, 11, 29, 80, 69, 45, 79, 241, + 166, 253, 228, 21, 103, 93, 56, 66, 200, 57, 173, 0, 226, 25, + 19, 91, 28, 6, 97, 226, 216, 235, 195, 5, 160, 112, 82, 189, + 219, 207, 46, 48, 131, 3, 241, 255, 164, 91, 80, 34, 243, 173, + 41, 82, 85, 24, 171, 141, 148, 230, 149, 173, 224, 23, 124, 191, + 10, 46, 164, 56, 196, 140, 67, 48, 73, 149, 85, 64, 200, 177, + 186, 9, 27, 172, 135, 244, 61, 249, 105, 97, 171, 154, 238, 146, + 228, 72, 210, 12, 88, 237, 37, 170, 214, 181, 38, 3, 184, 86, + 245, 9, 83, 151, 6, 84, 70, 247, 101, 52, 79, 60, 243, 197, + 23, 3, 3, 145, 169, 139, 10, 185, 162, 159, 168, 69, 63, 102, + 235, 138, 19, 1, 44, 107, 130, 218, 107, 222, 226, 134, 38, 0, + 229, 17, 57, 157, 34, 204, 172, 91, 169, 62, 107, 207, 51, 212, + 24, 21, 45, 166, 232, 146, 95, 57, 62, 48, 83, 15, 80, 4, + 240, 99, 173, 127, 42, 91, 215, 180, 79, 210, 43, 234, 152, 158, + 14, 9, 108, 63, 172, 252, 153, 106, 13, 204, 145, 72, 92, 223, + 124, 110, 231, 172, 135, 105, 204, 203, 72, 238, 192, 141, 94, 99, + 219, 45, 11, 238, 161, 50, 59, 140, 5, 12, 42, 56, 238, 234, + 93, 68, 170, 249, 203, 236, 122, 144, 222, 136, 83, 196, 177, 29, + 47, 128, 212, 93, 87, 33, 234, 13, 43, 183, 215, 135, 75, 9, + 40, 153, 235, 209, 175, 199, 193, 206, 255, 213, 52, 189, 213, 228, + 110, 130, 225, 45, 170, 46, 63, 96, 171, 131, 251, 116, 107, 144, + 125, 150, 43, 125, 63, 217, 32, 243, 178, 69, 73, 255, 149, 57, + 120, 153, 252, 185, 98, 124, 90, 95, 94, 29, 126, 129, 22, 178, + 185, 186, 44, 6, 29, 13, 137, 158, 225, 209, 89, 30, 65, 90, + 207, 200, 48, 112, 113, 251, 235, 110, 141, 162, 37, 24, 18, 79, + 19, 61, 193, 168, 252, 207, 65, 183, 194, 167, 196, 55, 70, 24, + 24, 31, 253, 242, 56, 43, 175, 23, 170, 4, 184, 10, 3, 78, + 220, 223, 217, 41, 154, 206, 167, 212, 170, 1, 2, 155, 43, 224, + 9, 214, 14, 60, 231, 26, 120, 48, 197, 14, 180, 120, 172, 65, + 49, 228, 1, 249, 108, 140, 254, 82, 238, 18, 117, 176, 93, 25, + 102, 32, 87, 115, 136, 87, 117, 177, 10, 23, 25, 18, 152, 20, + 59, 110, 159, 153, 203, 14, 163, 167, 167, 63, 108, 76, 232, 10, + 224, 66, 78, 111, 128, 14, 194, 85, 226, 190, 50, 242, 104, 28, + 105, 170, 47, 102, 194, 101, 26, 218, 154, 37, 48, 27, 215, 230, + 90, 30, 46, 155, 62, 117, 18, 212, 103, 140, 137, 93, 234, 37, + 20, 175, 17, 113, 143, 73, 61, 95, 100, 159, 126, 209, 88, 79, + 74, 183, 138, 85, 6, 25, 43, 21, 7, 160, 220, 102, 244, 122, + 92, 64, 154, 63, 106, 225, 241, 33, 105, 38, 144, 223, 214, 188, + 33, 119, 202, 111, 219, 163, 65, 156, 99, 78, 170, 20, 161, 3, + 53, 199, 183, 193, 209, 130, 201, 207, 6, 235, 215, 116, 101, 123, + 132, 79, 71, 244, 194, 101, 218, 155, 229, 58, 139, 253, 24, 7, + 70, 216, 228, 35, 31, 165, 249, 159, 211, 130, 231, 178, 27, 13, + 102, 67, 2, 157, 221, 190, 62, 32, 240, 191, 153, 39, 28, 25, + 202, 180, 91, 155, 46, 139, 247, 93, 14, 221, 8, 67, 215, 188, + 223, 169, 47, 140, 134, 185, 138, 54, 225, 179, 134, 159, 166, 90, + 26, 49, 99, 209, 64, 151, 70, 36, 237, 85, 92, 44, 95, 78, + 238, 167, 17, 189, 65, 236, 216, 150, 58, 114, 41, 201, 148, 223, + 117, 44, 68, 161, 153, 236, 75, 124, 127, 38, 6, 22, 91, 166, + 240, 30, 55, 49, 112, 138, 61, 40, 15, 114, 156, 161, 119, 0, + 48, 116, 87, 143, 199, 145, 21, 242, 101, 52, 36, 27, 243, 167, + 96, 241, 87, 103, 152, 137, 74, 141, 153, 112, 127, 232, 247, 75, + 176, 76, 122, 139, 23, 219, 149, 227, 196, 118, 244, 203, 233, 12, + 208, 224, 188, 139, 191, 10, 129, 134, 133, 137, 198, 69, 155, 84, + 160, 127, 53, 147, 186, 218, 218, 107, 43, 81, 11, 90, 177, 179, + 14, 30, 188, 138, 40, 252, 95, 239, 64, 100, 32, 212, 93, 58, + 74, 205, 92, 72, 166, 230, 154, 116, 176, 129, 46, 190, 9, 215, + 71, 100, 37, 113, 147, 146, 192, 149, 147, 202, 192, 51, 199, 63, + 19, 239, 171, 74, 127, 17, 216, 93, 92, 67, 106, 11, 181, 104, + 39, 231, 181, 194, 193, 249, 216, 198, 157, 177, 148, 3, 14, 210, + 234, 71, 95, 80, 46, 31, 178, 212, 16, 195, 100, 26, 195, 168, + 16, 235, 166, 42, 244, 98, 91, 103, 254, 244, 54, 128, 117, 156, + 92, 82, 33, 200, 184, 183, 147, 55, 69, 214, 134, 110, 222, 136, + 198, 88, 1, 93, 147, 193, 120, 127, 105, 147, 54, 15, 102, 184, + 226, 194, 236, 168, 17, 194, 175, 106, 134, 50, 51, 126, 30, 148, + 241, 139, 94, 126, 211, 48, 179, 210, 128, 79, 80, 229, 99, 206, + 10, 174, 5, 75, 198, 207, 35, 237, 38, 45, 199, 247, 208, 21, + 244, 186, 47, 19, 135, 157, 96, 228, 194, 16, 76, 14, 139, 106, + 50, 84, 249, 26, 143, 17, 180, 147, 2, 222, 201, 145, 11, 211, + 41, 181, 165, 25, 210, 196, 11, 217, 231, 71, 166, 47, 150, 1, + 28, 154, 206, 40, 16, 245, 251, 228, 145, 55, 153, 159, 249, 224, + 215, 50, 222, 210, 152, 131, 134, 244, 170, 190, 97, 20, 228, 235, + 132, 40, 123, 240, 117, 190, 36, 87, 50, 29, 211, 106, 251, 184, + 255, 79, 230, 36, 97, 71, 231, 233, 237, 155, 229, 182, 159, 69, + 222, 240, 171, 60, 244, 143, 51, 101, 4, 224, 106, 130, 161, 148, + 178, 227, 172, 48, 181, 30, 249, 11, 143, 180, 133, 86, 247, 144, + 240, 143, 243, 195, 237, 51, 166, 168, 130, 196, 156, 23, 13, 213, + 236, 185, 195, 22, 125, 137, 95, 34, 168, 63, 70, 58, 154, 73, + 60, 111, 250, 144, 82, 86, 230, 117, 115, 250, 26, 120, 189, 225, + 58, 146, 137, 31, 70, 6, 177, 87, 48, 94, 239, 245, 90, 169, + 62, 170, 41, 183, 226, 159, 238, 153, 226, 23, 53, 1, 45, 70, + 159, 206, 201, 83, 38, 29, 253, 123, 163, 162, 194, 19, 14, 3, + 242, 203, 244, 189, 162, 72, 141, 209, 30, 252, 54, 61, 178, 138, + 229, 235, 73, 252, 57, 18, 161, 34, 145, 143, 21, 85, 103, 159, + 196, 152, 201, 113, 229, 254, 231, 79, 225, 226, 244, 201, 78, 61, + 28, 29, 143, 20, 217, 171, 198, 61, 81, 148, 202, 165, 6, 144, + 161, 1, 98, 127, 190, 2, 67, 84, 238, 120, 237, 65, 27, 191, + 191, 203, 112, 159, 7, 84, 31, 105, 115, 13, 19, 191, 17, 98, + 237, 235, 166, 153, 186, 104, 92, 81, 210, 62, 232, 165, 105, 55, + 79, 179, 58, 17, 186, 241, 131, 116, 222, 233, 141, 100, 207, 106, + 48, 248, 64, 4, 214, 187, 206, 240, 156, 93, 131, 82, 245, 134, + 222, 3, 161, 236, 74, 124, 72, 198, 89, 250, 103, 164, 209, 167, + 10, 96, 5, 22, 142, 83, 38, 27, 122, 6, 216, 64, 169, 177, + 58, 93, 19, 35, 214, 24, 229, 77, 154, 142, 5, 239, 43, 2, + 117, 246, 174, 175, 68, 45, 77, 161, 179, 135, 208, 153, 166, 96, + 182, 118, 101, 9, 47, 119, 181, 188, 248, 174, 31, 42, 243, 188, + 54, 67, 36, 53, 50, 16, 101, 125, 248, 3, 125, 11, 205, 133, + 20, 126, 105, 101, 15, 189, 195, 159, 224, 202, 3, 55, 45, 85, + 117, 44, 44, 238, 45, 193, 17, 135, 70, 238, 161, 158, 33, 247, + 77, 76, 148, 164, 16, 176, 36, 135, 150, 75, 14, 132, 0, 0, + 121, 2, 63, 194, 48, 125, 210, 3, 149, 216, 142, 52, 110, 155, + 29, 98, 123, 60, 31, 9, 103, 48, 245, 171, 51, 196, 139, 14, + 152, 109, 66, 180, 193, 122, 114, 24, 121, 249, 234, 92, 189, 106, + 183, 114, 139, 116, 127, 5, 220, 136, 77, 62, 242, 60, 245, 92, + 141, 181, 84, 8, 216, 190, 132, 70, 189, 4, 252, 192, 6, 113, + 244, 229, 33, 29, 182, 159, 236, 155, 85, 229, 131, 43, 2, 130, + 67, 51, 54, 149, 29, 228, 238, 152, 31, 157, 9, 224, 72, 178, + 111, 215, 131, 118, 24, 188, 225, 154, 172, 253, 115, 43, 103, 249, + 254, 62, 28, 76, 161, 116, 74, 222, 250, 181, 103, 30, 183, 172, + 126, 101, 213, 165, 216, 197, 34, 3, 37, 162, 110, 230, 38, 189, + 250, 150, 186, 180, 38, 76, 17, 2, 23, 79, 66, 21, 248, 233, + 144, 71, 89, 133, 133, 237, 12, 120, 180, 162, 69, 20, 36, 209, + 76, 201, 42, 39, 81, 249, 169, 8, 70, 209, 164, 205, 97, 189, + 218, 95, 101, 40, 201, 56, 135, 121, 54, 55, 238, 154, 121, 236, + 63, 88, 135, 40, 209, 178, 27, 77, 27, 21, 179, 238, 95, 142, + 144, 246, 115, 130, 195, 111, 156, 238, 159, 22, 162, 122, 253, 178, + 212, 104, 96, 87, 64, 2, 170, 166, 185, 20, 49, 192, 130, 87, + 190, 172, 124, 59, 1, 246, 142, 249, 29, 24, 113, 244, 7, 204, + 144, 29, 49, 42, 88, 227, 31, 246, 132, 130, 76, 18, 46, 31, + 154, 58, 201, 137, 76, 82, 77, 122, 184, 143, 111, 241, 15, 214, + 106, 118, 129, 136, 94, 129, 203, 51, 22, 38, 254, 110, 191, 162, + 191, 157, 31, 186, 238, 206, 54, 240, 198, 32, 153, 240, 75, 159, + 2, 15, 156, 119, 26, 108, 197, 86, 73, 26, 176, 135, 235, 162, + 54, 190, 122, 92, 189, 26, 19, 77, 153, 99, 237, 245, 248, 234, + 115, 246, 131, 186, 14, 138, 221, 206, 247, 168, 147, 48, 221, 82, + 145, 47, 61, 18, 68, 221, 235, 253, 212, 93, 9, 97, 94, 34, + 84, 7, 5, 14, 240, 39, 99, 216, 57, 2, 246, 124, 126, 196, + 200, 109, 111, 211, 120, 1, 195, 41, 197, 232, 53, 129, 254, 224, + 179, 196, 85, 176, 38, 242, 228, 250, 72, 254, 172, 138, 16, 240, + 66, 254, 129, 34, 35, 191, 165, 43, 211, 67, 244, 55, 152, 123, + 180, 203, 147, 227, 218, 139, 53, 73, 94, 65, 119, 70, 108, 21, + 14, 64, 191, 13, 227, 245, 32, 161, 111, 236, 107, 197, 67, 229, + 61, 51, 33, 117, 121, 32, 9, 242, 35, 73, 188, 20, 35, 13, + 249, 16, 59, 194, 5, 24, 87, 66, 63, 97, 90, 57, 86, 143, + 83, 25, 225, 147, 114, 248, 168, 245, 1, 211, 249, 189, 227, 171, + 168, 36, 181, 184, 195, 115, 68, 12, 118, 81, 51, 193, 177, 85, + 242, 192, 250, 241, 174, 154, 197, 16, 191, 83, 245, 7, 125, 182, + 164, 52, 229, 165, 151, 109, 156, 63, 73, 84, 28, 179, 47, 247, + 209, 71, 203, 119, 201, 134, 77, 169, 230, 239, 31, 58, 202, 87, + 8, 209, 46, 167, 1, 97, 143, 34, 137, 156, 177, 231, 215, 15, + 101, 78, 19, 4, 103, 172, 49, 39, 170, 82, 122, 41, 8, 30, + 21, 129, 142, 147, 53, 199, 13, 150, 41, 239, 203, 215, 232, 167, + 7, 196, 220, 228, 38, 17, 179, 53, 89, 205, 88, 99, 8, 35, + 19, 179, 234, 76, 57, 215, 169, 141, 17, 183, 51, 19, 42, 176, + 26, 0, 67, 32, 18, 34, 165, 122, 183, 208, 151, 103, 245, 190, + 212, 169, 249, 82, 102, 35, 35, 188, 142, 27, 46, 245, 80, 126, + 209, 7, 107, 31, 66, 204, 107, 101, 237, 250, 153, 83, 147, 136, + 189, 138, 209, 169, 204, 241, 221, 198, 255, 21, 59, 171, 25, 205, + 204, 181, 219, 168, 236, 29, 55, 145, 99, 152, 251, 124, 80, 135, + 73, 125, 189, 159, 239, 194, 26, 181, 16, 44, 177, 61, 237, 194, + 42, 153, 112, 117, 212, 241, 149, 192, 7, 129, 63, 64, 170, 75, + 8, 233, 123, 91, 211, 70, 156, 78, 71, 32, 70, 167, 141, 17, + 36, 172, 151, 186, 88, 93, 236, 62, 66, 235, 112, 0, 67, 32, + 125, 7, 192, 133, 15, 66, 34, 93, 239, 93, 255, 154, 15, 50, + 194, 102, 215, 170, 239, 58, 117, 105, 26, 4, 208, 137, 111, 26, + 105, 14, 51, 114, 98, 228, 231, 88, 141, 240, 255, 148, 221, 143, + 89, 96, 253, 187, 228, 236, 107, 81, 85, 169, 19, 84, 169, 177, + 254, 49, 59, 5, 98, 175, 209, 193, 7, 40, 202, 173, 195, 137, + 217, 254, 186, 255, 85, 185, 178, 200, 189, 167, 217, 200, 64, 133, + 168, 146, 112, 46, 143, 132, 2, 146, 223, 241, 71, 12, 150, 181, + 193, 236, 20, 6, 129, 11, 29, 159, 255, 233, 244, 168, 154, 0, + 24, 25, 165, 142, 56, 47, 63, 198, 18, 220, 166, 38, 248, 162, + 20, 127, 109, 218, 41, 120, 230, 244, 90, 108, 236, 70, 36, 104, + 173, 137, 3, 252, 49, 240, 179, 142, 79, 142, 236, 253, 6, 236, + 93, 62, 197, 57, 81, 4, 14, 20, 220, 6, 144, 79, 6, 128, + 168, 12, 63, 193, 75, 70, 195, 8, 212, 104, 120, 34, 172, 192, + 42, 94, 53, 30, 91, 240, 141, 197, 251, 77, 187, 59, 148, 21, + 175, 245, 65, 59, 150, 241, 145, 108, 78, 250, 172, 102, 207, 45, + 34, 207, 155, 127, 125, 233, 81, 121, 135, 95, 33, 252, 154, 60, + 16, 5, 207, 245, 217, 132, 192, 148, 179, 37, 79, 82, 233, 203, + 20, 137, 236, 25, 197, 171, 216, 59, 237, 22, 40, 232, 14, 138, + 193, 83, 84, 209, 135, 48, 252, 212, 44, 69, 197, 132, 208, 86, + 116, 195, 65, 98, 105, 189, 40, 161, 220, 192, 152, 74, 233, 101, + 140, 29, 49, 168, 245, 205, 57, 166, 52, 234, 56, 203, 245, 24, + 80, 42, 200, 17, 215, 176, 61, 131, 66, 224, 125, 142, 247, 20, + 63, 28, 70, 26, 155, 189, 128, 114, 166, 212, 12, 247, 199, 216, + 228, 52, 114, 200, 157, 226, 22, 238, 216, 16, 157, 135, 195, 180, + 199, 144, 117, 206, 251, 48, 90, 218, 214, 34, 151, 109, 236, 147, + 39, 111, 124, 238, 117, 93, 65, 198, 25, 46, 190, 111, 5, 98, + 8, 19, 81, 205, 201, 121, 220, 197, 198, 6, 18, 155, 202, 148, + 62, 209, 238, 53, 179, 0, 219, 76, 191, 183, 146, 27, 122, 44, + 30, 45, 124, 69, 27, 3, 146, 6, 5, 198, 207, 30, 87, 50, + 10, 180, 243, 227, 168, 78, 75, 224, 172, 196, 213, 163, 0, 14, + 1, 219, 35, 130, 176, 128, 148, 169, 94, 16, 194, 83, 23, 23, + 255, 79, 140, 170, 58, 177, 182, 197, 115, 104, 240, 104, 207, 175, + 4, 174, 155, 181, 76, 237, 23, 222, 92, 104, 40, 224, 4, 162, + 182, 230, 47, 18, 50, 202, 179, 177, 176, 125, 165, 13, 24, 64, + 167, 2, 246, 134, 82, 164, 186, 235, 64, 150, 168, 124, 136, 252, + 149, 209, 26, 149, 242, 162, 49, 28, 74, 199, 25, 130, 0, 67, + 139, 117, 36, 247, 91, 113, 204, 243, 168, 163, 79, 27, 161, 31, + 199, 66, 161, 125, 85, 106, 204, 194, 213, 62, 235, 68, 9, 16, + 54, 30, 174, 2, 21, 30, 163, 171, 170, 136, 187, 222, 4, 194, + 66, 151, 34, 164, 145, 130, 197, 169, 235, 30, 32, 26, 214, 245, + 32, 53, 148, 163, 79, 8, 91, 200, 244, 38, 252, 38, 14, 213, + 162, 130, 156, 146, 246, 47, 76, 55, 219, 3, 96, 36, 77, 47, + 238, 18, 12, 123, 166, 12, 32, 53, 159, 54, 167, 94, 226, 142, + 87, 114, 103, 109, 248, 135, 195, 76, 132, 239, 255, 246, 55, 186, + 191, 103, 222, 65, 62, 103, 93, 135, 12, 155, 210, 200, 119, 237, + 90, 250, 193, 192, 103, 90, 19, 81, 44, 37, 207, 75, 39, 105, + 131, 110, 220, 225, 75, 184, 74, 215, 233, 89, 5, 169, 227, 30, + 214, 130, 34, 191, 140, 183, 241, 17, 187, 209, 201, 37, 14, 241, + 70, 15, 35, 110, 10, 21, 140, 73, 30, 10, 48, 106, 186, 7, + 12, 95, 108, 233, 45, 157, 31, 158, 114, 118, 94, 179, 148, 104, + 193, 64, 104, 229, 126, 156, 1, 166, 76, 27, 91, 221, 87, 155, + 69, 57, 205, 206, 178, 81, 4, 231, 110, 56, 70, 81, 92, 80, + 223, 181, 66, 90, 114, 88, 23, 112, 238, 93, 26, 13, 56, 48, + 208, 225, 220, 55, 216, 173, 182, 202, 54, 2, 162, 99, 87, 154, + 18, 84, 19, 101, 232, 196, 28, 239, 164, 20, 138, 93, 136, 27, + 50, 185, 163, 36, 146, 71, 32, 240, 225, 171, 89, 69, 225, 213, + 132, 154, 229, 221, 99, 60, 106, 12, 235, 199, 158, 127, 80, 211, + 223, 159, 75, 186, 179, 103, 203, 184, 236, 111, 9, 210, 251, 34, + 53, 178, 118, 227, 66, 242, 68, 55, 190, 37, 10, 138, 32, 182, + 136, 229, 205, 240, 226, 25, 37, 84, 225, 27, 42, 31, 224, 169, + 142, 99, 56, 75, 171, 145, 44, 191, 236, 9, 130, 101, 159, 213, + 192, 208, 231, 25, 164, 27, 10, 166, 134, 86, 195, 182, 119, 239, + 148, 106, 45, 128, 109, 18, 179, 250, 120, 196, 222, 62, 147, 81, + 23, 244, 132, 247, 85, 15, 169, 77, 29, 17, 40, 232, 68, 198, + 195, 234, 247, 218, 180, 49, 201, 167, 247, 223, 233, 119, 95, 186, + 161, 73, 90, 34, 7, 176, 115, 212, 232, 243, 37, 64, 45, 165, + 17, 208, 63, 96, 43, 152, 247, 140, 231, 88, 124, 194, 23, 249, + 245, 104, 175, 227, 219, 153, 39, 216, 150, 172, 9, 158, 58, 128, + 207, 240, 223, 150, 217, 0, 46, 184, 153, 8, 88, 71, 26, 90, + 7, 164, 24, 246, 134, 221, 39, 102, 19, 4, 231, 24, 199, 51, + 245, 184, 122, 13, 1, 107, 58, 155, 211, 165, 116, 88, 20, 97, + 160, 140, 181, 50, 141, 198, 36, 184, 104, 33, 33, 122, 152, 104, + 215, 217, 49, 243, 55, 105, 35, 59, 126, 115, 84, 119, 189, 202, + 230, 207, 246, 27, 127, 158, 82, 215, 64, 239, 88, 223, 249, 18, + 109, 230, 27, 8, 3, 222, 26, 136, 234, 123, 132, 190, 2, 9, + 145, 15, 225, 45, 140, 214, 166, 198, 83, 128, 182, 254, 169, 164, + 94, 106, 158, 113, 70, 177, 113, 158, 0, 225, 190, 137, 156, 65, + 85, 132, 193, 241, 136, 67, 106, 104, 32, 122, 119, 127, 51, 208, + 141, 221, 221, 80, 29, 60, 60, 122, 180, 85, 188, 204, 177, 36, + 150, 67, 77, 73, 245, 156, 240, 234, 164, 151, 221, 12, 236, 117, + 203, 101, 202, 138, 213, 134, 156, 201, 136, 59, 162, 27, 14, 80, + 140, 82, 70, 197, 149, 246, 158, 155, 239, 188, 161, 213, 65, 229, + 139, 117, 249, 81, 123, 192, 133, 60, 160, 176, 247, 236, 2, 215, + 251, 246, 198, 82, 221, 169, 51, 125, 210, 6, 55, 198, 12, 199, + 7, 154, 179, 151, 8, 211, 28, 37, 201, 251, 79, 245, 97, 0, + 143, 155, 89, 94, 105, 187, 54, 170, 18, 227, 16, 100, 96, 185, + 2, 222, 124, 123, 48, 11, 47, 234, 118, 91, 104, 229, 158, 174, + 11, 130, 192, 145, 117, 165, 166, 228, 47, 67, 3, 247, 183, 4, + 247, 100, 27, 194, 100, 188, 194, 57, 165, 221, 239, 218, 76, 52, + 9, 88, 212, 154, 255, 151, 236, 112, 123, 248, 53, 72, 98, 131, + 57, 111, 35, 160, 183, 9, 244, 5, 98, 211, 158, 243, 241, 106, + 24, 63, 190, 231, 94, 28, 137, 206, 242, 234, 128, 16, 88, 110, + 101, 205, 22, 51, 64, 169, 211, 211, 183, 107, 253, 170, 222, 154, + 80, 38, 99, 118, 244, 210, 223, 141, 182, 159, 141, 152, 170, 137, + 77, 250, 227, 170, 11, 34, 57, 17, 148, 140, 85, 32, 138, 65, + 85, 43, 172, 216, 163, 165, 239, 233, 108, 208, 2, 9, 239, 182, + 12, 29, 55, 206, 173, 194, 237, 41, 205, 79, 80, 208, 27, 9, + 226, 65, 2, 243, 239, 49, 62, 201, 156, 253, 198, 221, 145, 135, + 152, 235, 105, 165, 248, 207, 63, 190, 14, 2, 52, 82, 9, 125, + 77, 202, 181, 132, 27, 184, 62, 122, 45, 219, 36, 183, 4, 41, + 249, 90, 226, 246, 53, 218, 74, 211, 251, 97, 183, 159, 28, 169, + 162, 89, 181, 163, 29, 191, 1, 29, 2, 229, 60, 167, 204, 111, + 214, 48, 13, 42, 251, 103, 30, 21, 27, 32, 243, 171, 94, 58, + 117, 7, 1, 166, 99, 217, 1, 51, 146, 138, 84, 55, 50, 155, + 142, 184, 37, 137, 179, 178, 196, 103, 241, 62, 224, 249, 59, 213, + 107, 106, 247, 138, 145, 237, 183, 121, 50, 19, 47, 189, 59, 137, + 173, 198, 214, 0, 145, 15, 225, 45, 140, 214, 166, 198, 95, 136, + 28, 2, 179, 84, 85, 95, 140, 168, 26, 152, 251, 63, 103, 247, + 235, 253, 185, 208, 165, 183, 197, 164, 170, 9, 138, 213, 166, 203, + 185, 50, 28, 170, 216, 60, 200, 160, 220, 130, 221, 22, 78, 90, + 105, 137, 9, 151, 200, 36, 60, 176, 13, 25, 247, 22, 154, 110, + 51, 232, 1, 67, 212, 47, 109, 183, 212, 228, 203, 127, 139, 54, + 71, 246, 73, 153, 164, 75, 35, 163, 245, 110, 188, 216, 46, 114, + 38, 58, 58, 214, 183, 72, 220, 134, 36, 154, 71, 86, 105, 124, + 107, 28, 137, 196, 102, 90, 57, 87, 185, 203, 242, 49, 224, 152, + 203, 168, 233, 191, 7, 40, 206, 222, 30, 213, 132, 157, 175, 142, + 98, 124, 63, 151, 221, 197, 37, 252, 236, 154, 148, 97, 218, 236, + 131, 12, 163, 211, 159, 151, 166, 238, 200, 189, 128, 6, 108, 168, + 253, 29, 60, 234, 234, 174, 135, 10, 28, 241, 234, 1, 99, 137, + 84, 113, 130, 131, 181, 5, 72, 205, 81, 119, 226, 200, 151, 40, + 66, 90, 28, 156, 167, 204, 228, 81, 108, 44, 154, 101, 57, 73, + 241, 28, 19, 15, 170, 197, 65, 62, 76, 207, 139, 156, 115, 201, + 210, 138, 141, 63, 180, 12, 47, 133, 165, 35, 102, 164, 220, 250, + 28, 9, 97, 132, 212, 141, 24, 229, 245, 145, 132, 56, 124, 65, + 164, 44, 53, 109, 45, 255, 66, 84, 221, 227, 88, 213, 181, 238, + 228, 169, 193, 74, 12, 120, 162, 162, 5, 58, 58, 139, 102, 19, + 225, 16, 144, 51, 52, 160, 238, 162, 252, 60, 192, 69, 186, 137, + 35, 171, 90, 32, 214, 166, 88, 86, 45, 127, 55, 129, 210, 217, + 153, 239, 181, 128, 124, 107, 227, 8, 116, 193, 31, 69, 89, 96, + 245, 94, 40, 240, 132, 43, 119, 19, 148, 62, 152, 220, 169, 92, + 134, 8, 153, 57, 45, 219, 161, 135, 178, 79, 96, 232, 54, 167, + 209, 41, 47, 69, 74, 187, 156, 255, 191, 92, 4, 28, 138, 215, + 107, 112, 224, 218, 207, 152, 177, 233, 126, 253, 112, 234, 70, 219, + 175, 169, 66, 254, 15, 126, 28, 194, 109, 109, 151, 143, 229, 77, + 87, 160, 73, 141, 113, 149, 120, 200, 159, 159, 191, 51, 136, 94, + 238, 79, 98, 116, 48, 44, 17, 232, 240, 209, 134, 113, 211, 241, + 152, 128, 245, 64, 130, 77, 149, 90, 29, 75, 209, 121, 174, 86, + 132, 152, 28, 173, 88, 97, 221, 174, 37, 227, 152, 233, 117, 31, + 17, 149, 141, 22, 186, 18, 43, 248, 16, 190, 40, 52, 66, 45, + 172, 13, 50, 142, 102, 197, 120, 114, 47, 172, 44, 7, 74, 84, + 224, 120, 91, 213, 29, 98, 136, 10, 65, 194, 162, 4, 127, 94, + 28, 32, 13, 13, 88, 176, 189, 190, 70, 91, 201, 16, 130, 24, + 133, 163, 231, 64, 16, 62, 170, 198, 70, 170, 103, 43, 155, 11, + 65, 249, 149, 145, 229, 233, 111, 23, 222, 50, 79, 147, 85, 136, + 127, 137, 110, 66, 183, 116, 29, 53, 34, 179, 190, 75, 161, 136, + 239, 240, 148, 19, 68, 62, 12, 169, 167, 87, 133, 210, 235, 157, + 4, 255, 76, 63, 139, 162, 217, 186, 95, 130, 119, 193, 230, 44, + 237, 135, 40, 105, 172, 65, 255, 80, 108, 198, 97, 44, 173, 231, + 197, 4, 9, 13, 254, 208, 129, 198, 222, 162, 26, 170, 215, 106, + 2, 210, 113, 178, 153, 32, 110, 10, 7, 79, 31, 211, 181, 51, + 87, 185, 176, 95, 86, 1, 119, 141, 116, 52, 49, 104, 106, 204, + 232, 70, 64, 221, 239, 93, 28, 89, 127, 83, 31, 191, 229, 185, + 210, 75, 211, 110, 69, 225, 156, 88, 216, 235, 175, 250, 59, 89, + 179, 132, 178, 229, 146, 176, 163, 244, 53, 48, 154, 43, 15, 184, + 95, 219, 126, 230, 51, 233, 33, 43, 56, 216, 7, 61, 191, 244, + 155, 147, 113, 96, 44, 75, 217, 159, 191, 250, 36, 149, 31, 163, + 121, 51, 68, 139, 121, 157, 41, 253, 244, 26, 65, 159, 137, 64, + 200, 126, 73, 89, 184, 96, 188, 216, 139, 217, 151, 119, 45, 132, + 31, 38, 44, 131, 83, 77, 128, 229, 87, 174, 76, 174, 20, 27, + 150, 127, 159, 236, 183, 238, 54, 86, 166, 201, 112, 78, 122, 66, + 174, 50, 124, 22, 206, 14, 118, 108, 232, 101, 63, 232, 5, 94, + 97, 4, 125, 50, 165, 198, 222, 8, 85, 115, 108, 9, 28, 126, + 208, 127, 199, 0, 48, 244, 82, 70, 53, 24, 63, 67, 230, 251, + 195, 162, 35, 71, 111, 242, 164, 224, 39, 105, 100, 28, 67, 89, + 108, 218, 19, 186, 185, 190, 97, 142, 122, 118, 249, 29, 122, 163, + 175, 59, 79, 154, 162, 250, 251, 181, 24, 206, 98, 65, 39, 137, + 212, 102, 127, 9, 105, 112, 139, 95, 146, 240, 37, 133, 70, 147, + 224, 22, 49, 51, 223, 29, 234, 173, 84, 173, 229, 128, 50, 114, + 164, 208, 2, 17, 22, 139, 239, 39, 105, 125, 0, 133, 141, 233, + 32, 226, 74, 137, 247, 173, 9, 239, 77, 98, 233, 121, 189, 92, + 122, 5, 110, 58, 7, 101, 229, 197, 143, 236, 79, 84, 107, 49, + 86, 109, 192, 79, 248, 33, 0, 33, 114, 119, 158, 93, 43, 209, + 202, 244, 31, 36, 83, 102, 138, 70, 35, 226, 49, 21, 251, 131, + 116, 31, 201, 226, 46, 66, 36, 188, 138, 151, 127, 130, 197, 18, + 99, 8, 245, 189, 6, 134, 6, 143, 88, 134, 126, 1, 45, 112, + 109, 254, 221, 46, 152, 155, 63, 215, 61, 75, 41, 156, 151, 23, + 132, 100, 97, 196, 177, 191, 101, 118, 21, 11, 211, 41, 178, 130, + 252, 83, 185, 40, 196, 3, 168, 224, 255, 122, 246, 152, 36, 224, + 131, 210, 111, 151, 218, 77, 123, 207, 190, 233, 254, 22, 197, 38, + 79, 111, 179, 164, 115, 185, 112, 139, 209, 41, 90, 17, 78, 61, + 154, 137, 52, 58, 58, 209, 208, 114, 53, 59, 138, 8, 13, 217, + 37, 132, 11, 85, 111, 237, 153, 12, 31, 221, 234, 209, 124, 186, + 211, 216, 49, 201, 140, 163, 187, 8, 164, 243, 211, 191, 153, 203, + 120, 201, 66, 39, 163, 172, 182, 20, 155, 97, 209, 50, 64, 45, + 63, 30, 52, 141, 162, 147, 37, 196, 24, 72, 222, 70, 139, 212, + 121, 69, 233, 146, 114, 10, 7, 36, 233, 211, 3, 61, 27, 226, + 221, 141, 211, 90, 227, 234, 192, 190, 66, 228, 177, 46, 69, 34, + 163, 215, 60, 182, 134, 242, 241, 34, 125, 15, 225, 1, 193, 216, + 61, 246, 103, 13, 251, 113, 99, 128, 195, 96, 228, 19, 179, 68, + 145, 76, 191, 17, 42, 35, 154, 249, 255, 55, 47, 201, 220, 10, + 124, 133, 141, 161, 201, 87, 22, 97, 118, 12, 177, 39, 177, 213, + 144, 99, 132, 103, 115, 6, 189, 221, 105, 66, 156, 53, 75, 191, + 146, 211, 241, 202, 189, 196, 82, 220, 86, 43, 148, 207, 69, 44, + 212, 122, 121, 149, 95, 30, 116, 7, 55, 161, 184, 221, 102, 115, + 132, 124, 50, 93, 143, 116, 243, 116, 13, 7, 212, 155, 62, 115, + 52, 123, 209, 89, 198, 251, 102, 13, 101, 198, 187, 231, 99, 112, + 44, 129, 79, 154, 189, 187, 133, 142, 134, 218, 75, 252, 179, 164, + 149, 247, 44, 180, 90, 210, 103, 78, 23, 165, 8, 162, 35, 56, + 199, 233, 215, 251, 12, 134, 132, 106, 202, 211, 86, 97, 172, 231, + 92, 3, 132, 6, 233, 209, 86, 145, 112, 198, 13, 232, 252, 74, + 85, 242, 144, 99, 53, 151, 59, 33, 81, 92, 49, 157, 207, 199, + 26, 154, 0, 169, 3, 227, 239, 193, 194, 52, 141, 100, 24, 214, + 85, 202, 141, 112, 35, 14, 96, 173, 170, 15, 157, 86, 162, 119, + 78, 46, 247, 64, 237, 121, 187, 45, 146, 176, 242, 183, 72, 11, + 28, 91, 33, 169, 46, 176, 77, 82, 164, 38, 132, 25, 129, 105, + 253, 160, 158, 152, 98, 106, 135, 247, 207, 245, 250, 27, 156, 72, + 40, 17, 23, 133, 80, 187, 10, 237, 169, 192, 219, 229, 33, 119, + 85, 170, 192, 145, 208, 77, 29, 21, 102, 179, 0, 124, 32, 20, + 56, 27, 63, 183, 228, 46, 132, 158, 184, 96, 207, 132, 151, 212, + 252, 151, 5, 199, 164, 52, 114, 98, 65, 64, 11, 118, 252, 174, + 41, 181, 15, 135, 56, 103, 234, 103, 68, 160, 170, 109, 159, 50, + 163, 184, 128, 46, 230, 107, 223, 185, 59, 141, 99, 16, 58, 0, + 242, 36, 79, 167, 212, 25, 129, 121, 129, 76, 79, 16, 166, 241, + 49, 1, 212, 48, 163, 181, 57, 215, 200, 0, 233, 224, 200, 54, + 104, 93, 135, 184, 78, 207, 37, 81, 120, 83, 31, 1, 186, 238, + 52, 8, 16, 151, 194, 38, 105, 132, 53, 84, 74, 3, 164, 108, + 216, 66, 69, 234, 79, 153, 131, 184, 76, 118, 193, 139, 149, 13, + 116, 130, 204, 160, 216, 83, 27, 138, 69, 159, 73, 10, 7, 88, + 244, 133, 15, 38, 235, 118, 243, 199, 1, 57, 2, 116, 244, 162, + 51, 53, 53, 25, 92, 34, 255, 251, 140, 200, 159, 30, 214, 189, + 151, 143, 14, 115, 195, 241, 186, 146, 170, 58, 238, 105, 213, 187, + 220, 9, 243, 130, 186, 26, 195, 124, 137, 93, 165, 168, 234, 123, + 208, 192, 198, 10, 157, 148, 241, 115, 72, 136, 117, 63, 154, 146, + 133, 189, 235, 150, 152, 212, 202, 82, 222, 177, 140, 9, 3, 212, + 150, 94, 61, 63, 222, 127, 255, 62, 100, 22, 234, 145, 77, 48, + 151, 46, 94, 158, 125, 54, 145, 156, 254, 65, 95, 179, 86, 66, + 252, 164, 136, 99, 247, 74, 82, 129, 104, 69, 21, 87, 29, 70, + 213, 55, 235, 79, 206, 187, 169, 148, 239, 74, 2, 225, 60, 3, + 148, 10, 91, 48, 102, 103, 214, 199, 50, 104, 165, 103, 196, 161, + 188, 205, 44, 33, 111, 171, 135, 185, 212, 40, 143, 5, 129, 178, + 13, 106, 168, 202, 88, 106, 52, 199, 9, 150, 174, 205, 250, 211, + 181, 93, 145, 173, 216, 73, 117, 84, 98, 68, 16, 105, 246, 159, + 203, 174, 108, 27, 181, 0, 200, 229, 33, 153, 255, 94, 126, 0, + 107, 25, 176, 199, 71, 146, 161, 237, 112, 165, 71, 185, 101, 31, + 175, 142, 1, 228, 23, 212, 13, 62, 15, 36, 175, 46, 246, 166, + 107, 36, 142, 241, 245, 3, 152, 228, 26, 21, 234, 26, 94, 56, + 251, 70, 156, 162, 212, 204, 254, 204, 177, 89, 21, 28, 77, 90, + 188, 96, 69, 130, 105, 121, 67, 221, 237, 13, 223, 238, 3, 31, + 170, 27, 143, 153, 181, 74, 213, 115, 192, 56, 178, 35, 246, 101, + 105, 251, 67, 220, 49, 108, 66, 212, 125, 199, 68, 246, 249, 79, + 195, 11, 190, 124, 211, 94, 169, 204, 157, 30, 219, 183, 177, 88, + 176, 93, 165, 198, 46, 131, 147, 76, 76, 109, 244, 93, 148, 68, + 76, 139, 217, 218, 113, 248, 36, 54, 45, 97, 229, 223, 201, 138, + 249, 78, 236, 66, 130, 239, 99, 51, 100, 134, 224, 185, 74, 250, + 131, 35, 179, 38, 23, 254, 213, 241, 0, 38, 55, 245, 205, 160, + 181, 241, 200, 208, 62, 240, 70, 149, 40, 218, 84, 40, 187, 173, + 26, 206, 176, 235, 120, 203, 70, 41, 214, 129, 243, 132, 193, 84, + 12, 72, 191, 32, 1, 213, 247, 230, 17, 183, 59, 13, 238, 58, + 200, 72, 0, 204, 217, 142, 36, 247, 159, 255, 250, 244, 67, 252, + 204, 36, 16, 19, 231, 52, 140, 165, 155, 214, 235, 232, 187, 106, + 193, 92, 225, 51, 94, 101, 211, 121, 18, 25, 195, 191, 222, 155, + 152, 145, 139, 130, 216, 187, 219, 29, 207, 90, 52, 205, 249, 31, + 117, 217, 210, 98, 139, 118, 13, 176, 158, 39, 216, 143, 188, 195, + 245, 47, 99, 184, 237, 21, 198, 181, 199, 9, 168, 179, 226, 209, + 7, 11, 39, 212, 145, 151, 146, 192, 128, 229, 237, 13, 13, 45, + 128, 214, 29, 137, 248, 230, 176, 46, 227, 237, 76, 144, 87, 30, + 216, 118, 209, 178, 250, 59, 38, 223, 206, 141, 237, 10, 230, 141, + 51, 44, 98, 72, 159, 137, 226, 154, 142, 134, 186, 223, 111, 213, + 161, 217, 13, 24, 85, 84, 134, 239, 195, 87, 136, 69, 248, 223, + 163, 128, 42, 65, 181, 20, 151, 51, 189, 128, 122, 82, 36, 56, + 38, 125, 22, 221, 160, 20, 198, 203, 202, 35, 157, 118, 124, 215, + 67, 65, 230, 204, 198, 9, 174, 52, 12, 111, 120, 99, 220, 23, + 66, 140, 7, 131, 201, 63, 212, 239, 78, 249, 176, 227, 186, 43, + 188, 56, 156, 156, 7, 49, 203, 197, 99, 179, 100, 221, 242, 209, + 252, 133, 34, 218, 86, 128, 171, 207, 160, 181, 78, 185, 159, 223, + 103, 95, 53, 207, 24, 31, 211, 115, 208, 213, 31, 156, 132, 10, + 96, 97, 137, 216, 252, 84, 139, 61, 14, 115, 152, 138, 56, 135, + 118, 60, 78, 207, 217, 137, 44, 216, 84, 29, 64, 102, 255, 184, + 87, 24, 148, 17, 194, 219, 99, 60, 186, 21, 194, 133, 116, 212, + 56, 141, 49, 206, 80, 175, 220, 187, 235, 224, 136, 52, 14, 167, + 115, 81, 65, 183, 156, 76, 56, 1, 159, 125, 170, 53, 232, 47, + 155, 42, 132, 88, 41, 219, 247, 165, 7, 169, 124, 227, 170, 127, + 134, 180, 176, 195, 156, 137, 11, 225, 14, 99, 129, 129, 181, 247, + 137, 57, 109, 195, 233, 108, 226, 253, 208, 152, 108, 118, 51, 101, + 112, 85, 31, 92, 1, 89, 148, 219, 19, 10, 57, 223, 159, 23, + 89, 9, 212, 41, 177, 218, 134, 145, 165, 149, 175, 140, 67, 252, + 164, 191, 115, 156, 130, 155, 160, 249, 156, 157, 64, 177, 226, 112, + 93, 50, 224, 66, 181, 183, 209, 136, 167, 246, 224, 108, 143, 215, + 253, 179, 158, 203, 171, 93, 243, 69, 54, 86, 117, 217, 214, 167, + 248, 255, 81, 107, 184, 158, 146, 248, 11, 116, 71, 97, 41, 164, + 214, 161, 70, 140, 93, 228, 89, 48, 206, 74, 238, 115, 134, 189, + 79, 101, 117, 99, 167, 234, 19, 197, 153, 159, 51, 198, 211, 12, + 79, 48, 172, 117, 155, 6, 201, 42, 204, 127, 125, 156, 82, 253, + 203, 141, 57, 251, 255, 41, 102, 202, 84, 236, 43, 82, 114, 122, + 255, 175, 94, 58, 155, 124, 103, 219, 234, 149, 99, 84, 231, 51, + 230, 42, 217, 199, 228, 180, 44, 10, 164, 111, 11, 189, 37, 237, + 170, 190, 25, 43, 209, 82, 93, 111, 32, 174, 14, 7, 246, 168, + 209, 160, 180, 134, 121, 240, 158, 93, 152, 251, 207, 152, 233, 155, + 8, 123, 182, 123, 218, 218, 137, 232, 118, 152, 47, 204, 5, 251, + 109, 243, 8, 69, 241, 102, 195, 220, 171, 112, 26, 160, 190, 69, + 186, 228, 245, 208, 143, 113, 125, 183, 117, 90, 116, 11, 115, 200, + 20, 229, 133, 27, 98, 143, 221, 24, 55, 24, 174, 45, 98, 60, + 249, 29, 193, 21, 119, 100, 192, 145, 224, 202, 97, 72, 39, 162, + 106, 173, 77, 216, 229, 241, 141, 152, 129, 215, 199, 88, 42, 98, + 76, 48, 7, 212, 226, 85, 82, 197, 59, 229, 66, 164, 129, 39, + 161, 216, 72, 56, 94, 75, 207, 244, 244, 43, 119, 189, 5, 45, + 200, 19, 98, 239, 42, 179, 202, 42, 152, 106, 48, 5, 187, 82, + 72, 60, 46, 51, 105, 223, 0, 242, 169, 39, 255, 202, 229, 39, + 148, 244, 81, 174, 204, 126, 28, 115, 59, 105, 44, 107, 88, 244, + 87, 209, 181, 92, 26, 128, 190, 5, 12, 70, 159, 23, 117, 35, + 127, 6, 230, 167, 57, 89, 242, 164, 35, 44, 77, 164, 196, 191, + 24, 131, 112, 150, 23, 29, 196, 116, 143, 254, 40, 221, 210, 151, + 171, 250, 31, 113, 51, 86, 141, 182, 201, 245, 230, 6, 106, 137, + 201, 104, 217, 137, 207, 154, 49, 58, 106, 93, 234, 43, 95, 176, + 72, 211, 202, 178, 121, 106, 204, 144, 85, 160, 248, 60, 196, 217, + 255, 170, 135, 19, 33, 122, 44, 138, 121, 101, 88, 91, 168, 60, + 105, 255, 232, 192, 190, 63, 218, 67, 76, 103, 45, 250, 77, 160, + 239, 109, 59, 72, 125, 66, 117, 179, 52, 224, 203, 117, 51, 161, + 25, 200, 154, 164, 70, 151, 45, 62, 82, 164, 30, 151, 130, 45, + 202, 231, 42, 157, 65, 164, 11, 50, 155, 96, 75, 237, 212, 165, + 93, 217, 14, 118, 98, 56, 80, 117, 228, 7, 251, 125, 149, 112, + 32, 80, 177, 225, 87, 235, 197, 212, 8, 242, 33, 34, 184, 187, + 183, 59, 220, 49, 24, 43, 168, 140, 139, 134, 65, 90, 23, 35, + 160, 134, 156, 84, 241, 10, 249, 252, 81, 127, 104, 212, 223, 149, + 111, 19, 224, 9, 95, 149, 73, 86, 242, 10, 120, 194, 200, 249, + 40, 229, 211, 71, 165, 100, 91, 13, 87, 211, 225, 35, 238, 144, + 174, 179, 85, 49, 146, 206, 250, 36, 3, 191, 183, 148, 171, 63, + 203, 147, 62, 181, 229, 78, 16, 158, 229, 244, 106, 20, 98, 218, + 180, 239, 225, 165, 125, 51, 225, 93, 2, 3, 145, 23, 159, 217, + 149, 99, 176, 93, 7, 26, 147, 215, 187, 21, 249, 169, 98, 236, + 75, 123, 108, 234, 103, 183, 179, 76, 133, 219, 221, 187, 6, 191, + 91, 116, 17, 91, 126, 36, 198, 57, 173, 6, 205, 224, 175, 206, + 106, 218, 91, 32, 218, 100, 195, 149, 127, 101, 124, 11, 64, 180, + 57, 12, 181, 120, 63, 10, 200, 76, 195, 103, 211, 83, 71, 223, + 200, 86, 111, 138, 231, 70, 20, 112, 86, 204, 242, 55, 251, 50, + 235, 23, 107, 187, 61, 205, 74, 244, 123, 155, 81, 178, 196, 177, + 102, 204, 5, 122, 82, 79, 90, 146, 96, 31, 127, 48, 19, 207, + 223, 120, 84, 30, 181, 3, 127, 176, 153, 123, 54, 116, 131, 69, + 159, 2, 220, 102, 219, 93, 236, 125, 152, 40, 193, 7, 31, 124, + 180, 111, 83, 154, 143, 235, 123, 220, 177, 247, 186, 97, 51, 112, + 179, 51, 120, 180, 203, 36, 179, 67, 184, 37, 5, 209, 229, 127, + 197, 2, 3, 238, 110, 198, 255, 171, 157, 40, 176, 71, 236, 159, + 159, 92, 71, 80, 150, 91, 80, 45, 94, 8, 33, 221, 86, 138, + 52, 207, 202, 128, 142, 119, 23, 11, 201, 52, 221, 178, 117, 206, + 215, 219, 226, 107, 114, 35, 168, 29, 190, 111, 212, 131, 253, 134, + 123, 194, 147, 134, 144, 85, 248, 146, 109, 93, 130, 40, 224, 65, + 197, 109, 183, 38, 232, 248, 10, 249, 21, 236, 21, 92, 25, 226, + 165, 204, 21, 220, 19, 183, 163, 125, 177, 13, 23, 84, 60, 148, + 218, 40, 196, 1, 95, 131, 225, 210, 221, 51, 229, 248, 92, 212, + 21, 130, 231, 76, 235, 109, 90, 133, 92, 60, 234, 74, 159, 181, + 41, 35, 1, 165, 247, 245, 152, 101, 198, 65, 62, 174, 233, 8, + 244, 30, 206, 223, 194, 137, 167, 248, 205, 47, 17, 159, 35, 200, + 115, 49, 201, 87, 155, 159, 120, 135, 26, 67, 0, 50, 113, 205, + 6, 23, 31, 188, 246, 138, 240, 55, 187, 130, 22, 18, 43, 228, + 236, 243, 1, 122, 238, 244, 190, 123, 46, 112, 92, 165, 32, 22, + 9, 219, 238, 56, 150, 36, 217, 189, 171, 173, 200, 89, 188, 77, + 209, 23, 234, 40, 15, 147, 161, 132, 160, 245, 206, 87, 191, 164, + 160, 52, 193, 191, 62, 68, 228, 4, 103, 93, 116, 183, 192, 67, + 56, 124, 66, 111, 246, 124, 156, 6, 49, 146, 203, 213, 10, 69, + 127, 93, 86, 70, 137, 217, 104, 30, 215, 247, 107, 78, 229, 64, + 88, 5, 253, 92, 206, 100, 127, 153, 163, 165, 177, 30, 166, 56, + 81, 151, 172, 212, 13, 206, 45, 114, 154, 108, 3, 43, 238, 24, + 192, 212, 119, 21, 87, 107, 114, 2, 134, 25, 246, 240, 90, 14, + 208, 197, 105, 211, 238, 192, 8, 50, 186, 228, 195, 27, 65, 28, + 88, 34, 150, 96, 5, 87, 30, 53, 23, 234, 132, 68, 57, 233, + 225, 17, 7, 107, 230, 195, 74, 185, 48, 105, 199, 174, 146, 255, + 5, 70, 108, 148, 140, 253, 105, 245, 137, 109, 196, 128, 184, 223, + 1, 222, 235, 32, 193, 197, 44, 55, 104, 51, 204, 156, 7, 13, + 60, 83, 212, 174, 187, 130, 31, 95, 189, 221, 211, 235, 222, 195, + 118, 206, 68, 213, 58, 174, 56, 98, 227, 149, 106, 81, 252, 141, + 80, 31, 126, 49, 147, 99, 85, 200, 97, 215, 38, 71, 38, 80, + 2, 220, 137, 244, 29, 198, 211, 12, 59, 135, 68, 216, 118, 6, + 18, 182, 188, 53, 194, 8, 61, 79, 39, 128, 253, 229, 28, 116, + 229, 3, 128, 28, 94, 251, 187, 210, 210, 13, 37, 111, 101, 184, + 175, 11, 182, 41, 196, 195, 109, 183, 242, 160, 1, 0, 1, 29, + 143, 155, 226, 214, 96, 241, 57, 199, 209, 86, 30, 120, 181, 229, + 224, 29, 114, 48, 229, 142, 135, 88, 128, 243, 176, 210, 196, 211, + 85, 86, 58, 246, 21, 33, 152, 76, 194, 46, 10, 216, 134, 56, + 147, 68, 205, 60, 134, 169, 33, 64, 45, 253, 192, 137, 10, 66, + 150, 79, 48, 209, 248, 120, 160, 147, 184, 133, 139, 170, 43, 192, + 14, 181, 27, 196, 92, 122, 12, 178, 31, 86, 163, 208, 0, 143, + 66, 74, 166, 109, 59, 45, 100, 31, 74, 197, 204, 213, 86, 213, + 51, 237, 239, 7, 100, 91, 106, 74, 196, 222, 6, 53, 74, 40, + 64, 71, 79, 16, 42, 219, 175, 65, 114, 59, 9, 193, 97, 129, + 93, 233, 191, 239, 60, 129, 188, 233, 87, 5, 56, 244, 225, 222, + 168, 243, 220, 254, 13, 146, 230, 96, 79, 5, 247, 93, 17, 96, + 62, 52, 19, 11, 39, 118, 89, 131, 81, 67, 66, 72, 187, 132, + 37, 25, 78, 82, 13, 20, 136, 95, 70, 250, 55, 23, 54, 37, + 121, 222, 93, 219, 181, 156, 4, 77, 124, 121, 218, 125, 46, 88, + 70, 143, 41, 174, 49, 95, 188, 136, 193, 149, 37, 192, 14, 44, + 86, 108, 171, 137, 26, 160, 0, 106, 253, 228, 132, 192, 177, 183, + 170, 121, 188, 170, 112, 229, 171, 250, 190, 118, 72, 184, 31, 21, + 4, 153, 9, 10, 2, 178, 74, 239, 178, 181, 12, 194, 213, 141, + 64, 206, 179, 225, 164, 16, 215, 27, 143, 52, 141, 179, 74, 40, + 242, 86, 228, 184, 5, 192, 104, 211, 185, 158, 86, 234, 149, 130, + 142, 95, 118, 100, 82, 8, 161, 117, 118, 241, 46, 40, 184, 45, + 43, 125, 130, 157, 145, 47, 37, 144, 109, 210, 225, 34, 239, 73, + 6, 12, 93, 151, 133, 195, 164, 142, 146, 173, 195, 93, 33, 99, + 215, 176, 57, 143, 57, 70, 133, 106, 235, 96, 37, 74, 124, 101, + 231, 143, 143, 37, 40, 255, 247, 30, 126, 209, 94, 34, 32, 64, + 190, 170, 186, 125, 71, 22, 222, 53, 150, 98, 138, 201, 75, 43, + 240, 124, 75, 52, 251, 84, 197, 85, 120, 202, 79, 190, 155, 112, + 194, 206, 245, 220, 177, 184, 149, 241, 98, 245, 98, 93, 183, 206, + 143, 8, 230, 108, 138, 233, 25, 4, 99, 77, 191, 61, 164, 12, + 147, 231, 11, 55, 14, 13, 198, 126, 73, 191, 204, 31, 157, 34, + 11, 157, 97, 33, 106, 27, 113, 107, 211, 68, 123, 224, 194, 214, + 222, 89, 177, 3, 97, 51, 71, 161, 54, 155, 119, 249, 164, 144, + 10, 21, 26, 124, 134, 235, 106, 69, 103, 151, 147, 219, 39, 16, + 235, 216, 102, 249, 82, 23, 74, 107, 38, 226, 74, 138, 104, 210, + 183, 169, 100, 152, 67, 131, 242, 118, 209, 219, 109, 228, 165, 150, + 19, 182, 35, 250, 60, 90, 22, 191, 105, 56, 94, 188, 135, 118, + 215, 157, 102, 103, 161, 255, 99, 249, 78, 105, 41, 159, 17, 32, + 246, 158, 45, 153, 162, 126, 214, 6, 108, 31, 173, 41, 10, 32, + 139, 189, 132, 143, 98, 39, 25, 190, 98, 16, 125, 93, 255, 65, + 190, 193, 86, 123, 71, 45, 4, 251, 178, 75, 189, 130, 212, 137, + 4, 47, 174, 255, 244, 245, 149, 222, 165, 70, 140, 170, 194, 9, + 70, 243, 244, 72, 140, 152, 204, 122, 182, 95, 180, 25, 115, 50, + 25, 162, 97, 55, 101, 66, 171, 17, 111, 88, 104, 19, 35, 37, + 178, 106, 149, 185, 26, 145, 68, 54, 57, 91, 117, 130, 121, 14, + 213, 97, 178, 59, 9, 23, 227, 0, 150, 149, 126, 0, 244, 80, + 228, 240, 1, 18, 143, 78, 10, 200, 34, 41, 68, 11, 228, 208, + 16, 111, 158, 172, 4, 206, 21, 125, 123, 54, 204, 169, 94, 186, + 158, 149, 102, 9, 112, 222, 253, 22, 135, 165, 8, 103, 4, 53, + 102, 18, 10, 243, 229, 194, 204, 98, 6, 66, 229, 25, 208, 179, + 131, 233, 64, 71, 200, 175, 57, 255, 219, 140, 34, 59, 250, 227, + 31, 158, 136, 100, 226, 8, 185, 204, 200, 234, 60, 211, 139, 230, + 38, 242, 107, 182, 130, 254, 38, 179, 242, 186, 95, 12, 116, 79, + 137, 176, 217, 112, 220, 101, 232, 179, 234, 12, 49, 77, 112, 11, + 130, 203, 78, 220, 191, 155, 114, 238, 107, 185, 149, 24, 204, 211, + 46, 170, 5, 104, 212, 79, 189, 50, 220, 66, 240, 169, 248, 221, + 124, 190, 190, 191, 197, 165, 145, 0, 98, 203, 110, 49, 141, 89, + 71, 19, 248, 223, 227, 239, 14, 115, 186, 50, 35, 30, 248, 164, + 172, 59, 177, 217, 188, 6, 120, 248, 5, 77, 8, 169, 144, 249, + 190, 177, 229, 219, 44, 45, 102, 18, 166, 160, 90, 178, 85, 41, + 192, 26, 193, 102, 106, 218, 233, 23, 136, 239, 62, 30, 221, 22, + 110, 175, 27, 7, 138, 72, 140, 231, 107, 60, 32, 55, 243, 78, + 239, 79, 57, 209, 179, 73, 127, 187, 97, 3, 20, 147, 155, 142, + 61, 210, 48, 2, 64, 164, 36, 137, 56, 100, 48, 113, 195, 106, + 235, 114, 48, 174, 108, 75, 106, 164, 79, 223, 89, 129, 175, 139, + 234, 66, 58, 27, 166, 74, 215, 82, 99, 106, 223, 163, 141, 166, + 53, 104, 183, 97, 86, 211, 9, 219, 148, 184, 90, 242, 40, 95, + 143, 195, 95, 101, 103, 159, 119, 27, 239, 236, 1, 197, 192, 80, + 57, 26, 200, 45, 213, 75, 57, 126, 130, 136, 67, 39, 214, 112, + 187, 6, 208, 81, 203, 82, 8, 9, 168, 139, 110, 196, 66, 146, + 225, 4, 73, 187, 220, 250, 1, 220, 70, 157, 100, 44, 200, 84, + 211, 94, 237, 146, 113, 172, 92, 245, 76, 214, 12, 229, 180, 22, + 204, 54, 3, 38, 120, 85, 171, 21, 166, 68, 50, 191, 184, 23, + 218, 44, 25, 78, 97, 167, 85, 4, 24, 202, 129, 177, 56, 45, + 126, 157, 7, 85, 247, 132, 20, 19, 103, 248, 56, 150, 115, 5, + 242, 240, 114, 2, 168, 76, 15, 91, 185, 101, 155, 203, 154, 125, + 9, 10, 224, 66, 86, 234, 105, 209, 73, 250, 137, 120, 153, 189, + 18, 208, 243, 35, 159, 85, 205, 174, 103, 56, 104, 96, 201, 126, + 95, 72, 233, 20, 79, 247, 246, 115, 253, 107, 244, 207, 217, 206, + 52, 127, 219, 18, 194, 50, 89, 189, 215, 30, 148, 200, 5, 229, + 73, 47, 192, 37, 187, 174, 14, 234, 163, 0, 254, 41, 148, 105, + 245, 87, 161, 254, 81, 59, 80, 90, 27, 91, 140, 89, 100, 158, + 130, 13, 94, 244, 67, 150, 235, 193, 120, 42, 154, 123, 106, 246, + 22, 255, 186, 44, 159, 75, 255, 166, 54, 183, 62, 154, 26, 124, + 194, 113, 100, 110, 242, 169, 63, 186, 96, 69, 29, 244, 49, 129, + 178, 20, 103, 187, 177, 170, 14, 144, 235, 254, 104, 253, 242, 193, + 201, 202, 133, 80, 37, 110, 113, 3, 148, 241, 41, 172, 73, 98, + 40, 46, 152, 82, 34, 162, 5, 220, 163, 90, 89, 100, 232, 38, + 108, 4, 188, 168, 6, 126, 235, 206, 227, 174, 31, 63, 134, 114, + 222, 216, 171, 133, 138, 55, 8, 254, 149, 224, 32, 222, 36, 3, + 176, 235, 233, 24, 191, 11, 52, 128, 157, 140, 152, 92, 64, 179, + 182, 222, 242, 176, 11, 113, 81, 241, 119, 113, 215, 161, 163, 227, + 224, 252, 161, 132, 202, 180, 169, 64, 219, 104, 204, 24, 96, 179, + 234, 234, 165, 218, 250, 227, 231, 43, 37, 208, 191, 159, 164, 124, + 90, 177, 81, 34, 68, 166, 170, 240, 44, 67, 111, 170, 216, 57, + 210, 192, 164, 4, 69, 0, 255, 236, 38, 130, 199, 37, 70, 133, + 95, 3, 171, 151, 61, 31, 166, 21, 56, 24, 71, 94, 0, 232, + 232, 59, 178, 179, 205, 163, 16, 106, 119, 249, 195, 247, 94, 57, + 105, 145, 208, 74, 25, 60, 177, 172, 115, 144, 100, 58, 255, 155, + 251, 245, 202, 233, 242, 132, 77, 23, 187, 220, 23, 52, 161, 147, + 124, 107, 96, 178, 131, 83, 141, 53, 210, 72, 242, 148, 116, 180, + 226, 164, 160, 84, 39, 216, 46, 83, 220, 38, 118, 139, 53, 143, + 240, 102, 126, 85, 219, 27, 120, 0, 44, 86, 61, 49, 231, 253, + 135, 185, 194, 62, 20, 188, 202, 75, 102, 98, 248, 25, 102, 5, + 175, 152, 169, 166, 48, 254, 139, 251, 95, 54, 128, 235, 1, 73, + 138, 186, 248, 171, 33, 49, 181, 148, 222, 190, 223, 36, 47, 50, + 146, 140, 102, 229, 155, 229, 62, 218, 179, 218, 173, 172, 32, 235, + 188, 124, 14, 128, 135, 11, 48, 208, 145, 101, 249, 22, 8, 54, + 77, 164, 199, 143, 33, 99, 69, 248, 67, 13, 38, 202, 100, 255, + 241, 126, 10, 202, 233, 165, 9, 156, 74, 66, 231, 26, 190, 38, + 106, 175, 101, 236, 152, 127, 196, 251, 31, 101, 52, 251, 7, 35, + 0, 75, 123, 188, 95, 146, 201, 107, 246, 83, 170, 131, 212, 246, + 204, 198, 49, 195, 129, 52, 21, 242, 174, 3, 239, 15, 112, 190, + 101, 85, 136, 208, 141, 198, 10, 53, 84, 70, 96, 106, 141, 82, + 184, 69, 21, 86, 231, 154, 136, 122, 144, 96, 180, 185, 148, 253, + 77, 1, 254, 41, 241, 30, 58, 177, 252, 116, 199, 50, 249, 179, + 95, 250, 25, 51, 252, 159, 83, 63, 5, 230, 105, 63, 248, 185, + 221, 232, 44, 214, 214, 87, 14, 89, 46, 27, 52, 37, 49, 169, + 8, 101, 217, 9, 138, 244, 198, 102, 150, 15, 82, 242, 184, 193, + 114, 189, 164, 142, 4, 148, 37, 71, 83, 140, 4, 235, 115, 98, + 75, 80, 134, 9, 107, 13, 1, 8, 91, 76, 155, 242, 43, 44, + 238, 111, 64, 159, 72, 43, 127, 224, 117, 151, 190, 193, 167, 42, + 3, 161, 71, 23, 54, 52, 97, 151, 148, 78, 35, 40, 11, 102, + 147, 195, 34, 34, 109, 84, 239, 114, 145, 198, 159, 231, 139, 65, + 254, 168, 6, 116, 180, 156, 93, 45, 245, 206, 77, 164, 179, 238, + 56, 245, 222, 225, 39, 162, 180, 140, 109, 51, 154, 76, 226, 161, + 134, 36, 118, 51, 62, 44, 247, 203, 17, 252, 16, 233, 233, 30, + 56, 62, 31, 117, 232, 134, 234, 238, 238, 166, 67, 181, 147, 159, + 97, 53, 46, 48, 194, 160, 186, 121, 165, 13, 81, 128, 217, 231, + 12, 184, 15, 95, 216, 254, 231, 240, 90, 162, 45, 10, 19, 9, + 128, 3, 32, 206, 157, 19, 136, 235, 130, 151, 56, 31, 136, 5, + 123, 97, 6, 253, 20, 73, 97, 201, 245, 161, 109, 190, 147, 45, + 188, 108, 47, 1, 60, 85, 48, 174, 176, 221, 39, 50, 112, 72, + 103, 203, 117, 196, 153, 157, 90, 236, 95, 238, 187, 22, 243, 183, + 243, 170, 219, 62, 148, 139, 213, 152, 205, 93, 92, 94, 152, 35, + 171, 158, 26, 126, 32, 136, 185, 61, 108, 26, 205, 90, 116, 217, + 147, 207, 11, 62, 198, 85, 220, 223, 194, 9, 104, 245, 189, 103, + 111, 125, 187, 148, 23, 251, 32, 28, 150, 177, 193, 238, 45, 196, + 136, 253, 63, 237, 65, 131, 101, 100, 172, 94, 12, 163, 78, 176, + 66, 125, 120, 40, 242, 132, 221, 195, 107, 104, 135, 79, 44, 115, + 88, 67, 180, 136, 230, 146, 122, 25, 203, 119, 173, 100, 156, 50, + 208, 15, 153, 181, 4, 170, 254, 223, 207, 156, 0, 155, 138, 243, + 29, 61, 63, 241, 136, 33, 198, 99, 81, 133, 86, 115, 72, 137, + 190, 203, 79, 178, 54, 101, 61, 132, 61, 159, 98, 60, 101, 77, + 150, 213, 53, 102, 197, 44, 132, 211, 112, 252, 37, 193, 102, 77, + 187, 125, 60, 143, 75, 67, 224, 143, 118, 165, 54, 119, 231, 21, + 12, 185, 150, 75, 155, 37, 210, 112, 225, 130, 176, 3, 239, 131, + 200, 169, 24, 138, 159, 63, 148, 218, 109, 121, 116, 176, 183, 66, + 32, 221, 19, 14, 57, 204, 67, 242, 146, 116, 7, 59, 26, 53, + 144, 135, 22, 211, 162, 110, 194, 99, 41, 82, 131, 236, 0, 143, + 231, 22, 226, 90, 202, 91, 217, 232, 19, 255, 201, 41, 179, 180, + 181, 81, 196, 140, 242, 247, 79, 178, 190, 2, 229, 126, 168, 25, + 69, 16, 5, 237, 42, 123, 2, 164, 131, 126, 92, 155, 233, 221, + 217, 166, 32, 233, 129, 34, 102, 13, 200, 219, 50, 237, 105, 39, + 146, 251, 115, 129, 119, 163, 251, 38, 91, 186, 106, 58, 94, 165, + 66, 148, 147, 254, 206, 14, 1, 247, 100, 236, 78, 219, 48, 214, + 29, 115, 136, 135, 126, 185, 4, 163, 232, 181, 21, 223, 28, 136, + 106, 145, 98, 23, 180, 106, 237, 11, 144, 228, 31, 243, 223, 129, + 0, 130, 101, 189, 243, 83, 189, 175, 23, 131, 186, 249, 216, 160, + 3, 112, 55, 123, 123, 245, 44, 217, 71, 198, 144, 42, 253, 253, + 210, 153, 107, 111, 20, 254, 255, 63, 51, 153, 137, 188, 151, 28, + 132, 234, 109, 204, 85, 244, 35, 48, 88, 116, 212, 174, 201, 103, + 4, 252, 161, 255, 10, 155, 12, 239, 47, 134, 228, 36, 110, 245, + 164, 179, 39, 198, 64, 176, 32, 133, 159, 139, 88, 5, 156, 117, + 169, 44, 10, 13, 116, 173, 104, 212, 63, 8, 100, 138, 86, 94, + 207, 126, 3, 4, 211, 189, 36, 228, 115, 123, 181, 215, 235, 16, + 11, 99, 138, 121, 76, 199, 90, 103, 100, 141, 251, 105, 59, 74, + 144, 206, 237, 120, 215, 231, 101, 67, 25, 40, 42, 70, 19, 93, + 153, 237, 18, 70, 117, 231, 36, 200, 83, 229, 4, 198, 191, 172, + 43, 239, 136, 68, 200, 218, 132, 247, 218, 212, 89, 26, 212, 20, + 91, 183, 85, 91, 246, 139, 131, 178, 224, 70, 151, 150, 56, 44, + 60, 29, 67, 211, 224, 87, 121, 128, 248, 38, 28, 172, 158, 7, + 81, 64, 241, 20, 181, 194, 205, 46, 99, 207, 195, 134, 188, 17, + 176, 81, 201, 91, 154, 131, 119, 8, 38, 202, 221, 174, 175, 211, + 236, 34, 40, 182, 190, 93, 15, 120, 239, 133, 166, 152, 30, 109, + 233, 32, 8, 165, 222, 181, 159, 247, 27, 141, 171, 191, 173, 122, + 195, 191, 179, 174, 96, 76, 137, 135, 135, 228, 57, 179, 70, 149, + 227, 20, 172, 66, 154, 80, 108, 5, 197, 175, 49, 240, 219, 137, + 145, 248, 9, 223, 113, 254, 15, 40, 149, 51, 225, 191, 170, 210, + 61, 26, 155, 52, 76, 213, 115, 197, 51, 17, 153, 47, 4, 252, + 39, 126, 91, 114, 35, 65, 73, 53, 110, 16, 43, 198, 160, 23, + 120, 22, 118, 72, 226, 135, 116, 29, 26, 11, 53, 120, 109, 122, + 202, 152, 214, 43, 27, 33, 140, 139, 137, 113, 187, 232, 177, 34, + 176, 217, 2, 46, 129, 118, 85, 7, 237, 225, 104, 71, 129, 113, + 170, 46, 225, 82, 244, 192, 11, 139, 79, 91, 104, 123, 64, 49, + 153, 34, 41, 100, 82, 98, 100, 43, 91, 94, 112, 185, 61, 221, + 237, 204, 131, 79, 238, 197, 177, 137, 78, 237, 244, 241, 246, 14, + 127, 192, 251, 104, 78, 11, 35, 225, 219, 27, 5, 144, 175, 19, + 247, 44, 170, 166, 231, 108, 202, 215, 166, 196, 117, 181, 59, 91, + 113, 202, 78, 75, 15, 245, 81, 171, 186, 208, 238, 181, 20, 150, + 42, 237, 190, 215, 16, 174, 188, 105, 201, 148, 17, 252, 160, 202, + 91, 170, 89, 60, 113, 83, 114, 221, 244, 204, 91, 5, 196, 130, + 177, 144, 199, 254, 176, 78, 133, 17, 130, 79, 166, 53, 157, 143, + 183, 66, 29, 145, 196, 119, 56, 199, 146, 177, 178, 157, 20, 219, + 10, 35, 120, 222, 202, 170, 216, 8, 158, 82, 193, 99, 80, 114, + 36, 142, 153, 69, 153, 117, 118, 206, 220, 190, 117, 195, 55, 177, + 54, 15, 59, 241, 165, 99, 210, 238, 251, 201, 250, 191, 78, 186, + 2, 69, 83, 142, 89, 152, 189, 122, 163, 147, 129, 176, 219, 229, + 120, 206, 37, 94, 173, 209, 87, 217, 221, 242, 215, 63, 189, 76, + 74, 248, 94, 174, 245, 12, 87, 155, 243, 133, 47, 177, 84, 145, + 204, 58, 85, 90, 207, 220, 2, 143, 218, 171, 116, 5, 52, 211, + 120, 131, 168, 150, 135, 142, 98, 227, 40, 97, 172, 184, 175, 246, + 114, 67, 135, 203, 80, 116, 181, 198, 93, 218, 249, 88, 143, 196, + 50, 223, 196, 205, 68, 53, 36, 179, 107, 76, 146, 6, 47, 90, + 224, 148, 130, 5, 254, 249, 148, 170, 171, 187, 203, 123, 145, 93, + 223, 173, 131, 194, 181, 53, 206, 92, 226, 14, 194, 23, 143, 42, + 118, 72, 74, 7, 113, 25, 53, 195, 201, 40, 150, 94, 113, 72, + 220, 255, 107, 85, 171, 22, 3, 13, 112, 140, 6, 163, 77, 46, + 29, 81, 217, 234, 163, 200, 199, 248, 229, 72, 172, 251, 103, 234, + 232, 170, 161, 253, 69, 110, 176, 160, 174, 75, 103, 223, 14, 61, + 21, 56, 35, 3, 148, 95, 205, 153, 147, 210, 209, 115, 250, 46, + 110, 50, 2, 181, 62, 163, 233, 150, 191, 189, 75, 217, 182, 81, + 50, 80, 150, 12, 224, 71, 190, 251, 137, 182, 218, 250, 199, 191, + 89, 116, 220, 172, 6, 71, 79, 96, 229, 41, 162, 128, 106, 245, + 56, 46, 1, 155, 10, 137, 30, 184, 108, 228, 154, 212, 197, 250, + 173, 231, 234, 146, 156, 7, 249, 123, 82, 167, 145, 207, 135, 37, + 96, 6, 186, 218, 176, 168, 158, 204, 240, 162, 117, 82, 44, 109, + 134, 71, 58, 16, 25, 16, 166, 164, 44, 162, 219, 73, 249, 106, + 248, 150, 249, 176, 158, 169, 226, 198, 248, 210, 177, 47, 219, 241, + 49, 115, 37, 127, 171, 105, 174, 140, 135, 74, 152, 148, 195, 61, + 63, 75, 32, 36, 45, 42, 228, 105, 225, 152, 114, 224, 211, 187, + 127, 66, 192, 28, 127, 47, 17, 174, 60, 152, 44, 80, 75, 144, + 26, 196, 115, 128, 114, 126, 106, 43, 74, 229, 245, 103, 112, 142, + 251, 221, 77, 225, 18, 150, 252, 107, 23, 6, 146, 161, 20, 172, + 77, 214, 115, 82, 100, 45, 78, 197, 126, 36, 182, 96, 200, 61, + 65, 231, 168, 121, 127, 237, 196, 79, 32, 144, 22, 139, 45, 159, + 180, 128, 84, 13, 134, 161, 130, 56, 61, 182, 173, 100, 128, 65, + 99, 131, 32, 196, 254, 21, 60, 200, 204, 106, 237, 200, 227, 242, + 32, 171, 146, 202, 54, 198, 208, 110, 141, 78, 144, 211, 189, 18, + 79, 233, 137, 220, 69, 150, 122, 152, 155, 55, 150, 15, 163, 39, + 249, 131, 227, 237, 209, 240, 117, 216, 2, 172, 195, 112, 31, 74, + 253, 191, 51, 252, 170, 174, 175, 127, 218, 155, 155, 36, 228, 28, + 110, 0, 122, 201, 227, 222, 241, 240, 150, 100, 143, 18, 95, 100, + 163, 87, 154, 0, 125, 240, 70, 179, 80, 28, 197, 241, 250, 111, + 2, 191, 107, 30, 111, 193, 41, 159, 130, 46, 116, 118, 84, 234, + 239, 190, 236, 161, 183, 103, 89, 50, 49, 3, 91, 109, 163, 30, + 154, 199, 59, 49, 227, 58, 224, 155, 62, 58, 49, 164, 125, 237, + 237, 254, 241, 57, 190, 97, 216, 217, 15, 85, 238, 97, 182, 253, + 133, 84, 6, 104, 72, 49, 247, 108, 28, 103, 217, 175, 221, 202, + 164, 196, 47, 184, 147, 48, 93, 76, 177, 217, 169, 141, 214, 216, + 12, 47, 206, 233, 191, 55, 25, 228, 204, 67, 97, 112, 90, 246, + 200, 217, 33, 44, 155, 94, 91, 171, 188, 153, 189, 116, 22, 75, + 224, 18, 248, 209, 175, 59, 194, 113, 130, 228, 252, 150, 169, 137, + 147, 246, 96, 152, 107, 48, 205, 43, 179, 92, 249, 236, 113, 109, + 247, 17, 129, 47, 91, 219, 184, 19, 250, 141, 189, 201, 145, 181, + 118, 109, 171, 141, 64, 47, 35, 32, 52, 183, 188, 115, 126, 56, + 84, 90, 124, 83, 45, 129, 192, 151, 34, 70, 186, 220, 234, 3, + 224, 222, 85, 204, 187, 168, 241, 78, 134, 107, 48, 245, 164, 60, + 170, 196, 126, 96, 179, 193, 64, 183, 147, 5, 89, 41, 82, 141, + 134, 246, 132, 219, 100, 217, 105, 1, 91, 5, 136, 5, 142, 250, + 220, 183, 173, 182, 200, 24, 131, 53, 131, 158, 251, 84, 235, 255, + 125, 121, 81, 198, 249, 242, 141, 110, 234, 175, 34, 184, 148, 51, + 249, 127, 31, 209, 155, 3, 123, 47, 4, 190, 65, 64, 12, 225, + 88, 64, 59, 76, 251, 100, 116, 94, 128, 12, 51, 80, 39, 211, + 119, 181, 164, 58, 191, 49, 254, 216, 69, 211, 4, 249, 99, 78, + 227, 19, 49, 45, 228, 23, 220, 159, 14, 195, 241, 98, 132, 17, + 187, 156, 130, 119, 211, 24, 109, 21, 179, 106, 193, 229, 0, 88, + 200, 245, 79, 242, 5, 101, 41, 144, 98, 55, 201, 241, 198, 161, + 148, 160, 119, 161, 205, 218, 111, 44, 228, 199, 74, 166, 184, 105, + 209, 10, 194, 187, 112, 144, 109, 45, 233, 54, 6, 3, 9, 252, + 32, 163, 8, 232, 196, 125, 38, 233, 137, 137, 219, 3, 156, 158, + 153, 96, 227, 21, 114, 188, 6, 146, 52, 7, 101, 68, 218, 180, + 180, 167, 179, 140, 152, 98, 221, 166, 56, 95, 22, 174, 37, 221, + 208, 85, 195, 210, 96, 26, 92, 182, 241, 209, 224, 113, 231, 180, + 140, 109, 46, 140, 72, 214, 106, 220, 26, 128, 97, 159, 21, 92, + 102, 98, 197, 101, 141, 21, 19, 47, 249, 17, 134, 246, 63, 38, + 29, 232, 54, 56, 51, 5, 233, 246, 152, 51, 96, 166, 1, 191, + 107, 153, 136, 15, 43, 190, 38, 29, 116, 4, 123, 133, 225, 159, + 207, 25, 33, 30, 124, 234, 123, 96, 250, 160, 82, 228, 171, 74, + 175, 196, 40, 191, 133, 144, 103, 242, 37, 55, 242, 177, 220, 255, + 251, 113, 45, 99, 211, 100, 23, 120, 203, 45, 167, 102, 87, 146, + 133, 157, 70, 185, 145, 103, 120, 238, 218, 81, 55, 58, 32, 56, + 90, 110, 106, 156, 236, 229, 93, 20, 121, 90, 244, 140, 209, 28, + 195, 146, 97, 119, 159, 187, 179, 240, 73, 254, 78, 32, 203, 100, + 176, 190, 227, 229, 199, 155, 93, 145, 222, 85, 189, 162, 16, 47, + 189, 206, 81, 55, 124, 76, 58, 254, 95, 32, 60, 22, 179, 242, + 54, 244, 14, 5, 220, 75, 79, 163, 43, 229, 221, 65, 57, 227, + 121, 55, 164, 100, 254, 64, 206, 79, 174, 200, 72, 49, 26, 232, + 22, 27, 213, 180, 50, 75, 97, 178, 91, 184, 0, 140, 118, 101, + 36, 191, 232, 121, 177, 19, 254, 83, 18, 182, 64, 182, 21, 54, + 205, 209, 59, 64, 172, 255, 58, 14, 59, 101, 60, 249, 147, 151, + 40, 230, 212, 211, 206, 142, 85, 251, 130, 125, 43, 83, 113, 195, + 178, 107, 186, 204, 139, 254, 171, 155, 80, 96, 136, 219, 253, 68, + 146, 245, 98, 234, 126, 168, 251, 39, 74, 33, 54, 39, 29, 197, + 145, 98, 100, 26, 2, 4, 196, 48, 209, 210, 104, 201, 1, 114, + 117, 42, 220, 83, 184, 115, 95, 75, 41, 145, 142, 204, 106, 150, + 181, 48, 224, 153, 47, 62, 145, 84, 206, 161, 135, 11, 219, 10, + 175, 122, 53, 114, 254, 17, 138, 226, 158, 103, 97, 247, 78, 109, + 102, 169, 6, 173, 25, 21, 112, 75, 156, 180, 247, 106, 63, 148, + 196, 18, 38, 234, 119, 2, 2, 30, 212, 82, 20, 42, 216, 190, + 198, 198, 197, 154, 134, 15, 178, 98, 22, 79, 255, 215, 216, 57, + 160, 45, 82, 54, 25, 22, 130, 226, 173, 190, 189, 166, 30, 48, + 98, 115, 38, 212, 82, 133, 36, 249, 96, 97, 165, 227, 250, 241, + 99, 109, 217, 219, 69, 236, 196, 165, 242, 99, 65, 252, 137, 28, + 40, 201, 67, 116, 216, 72, 15, 58, 143, 226, 159, 243, 144, 35, + 13, 206, 45, 73, 219, 251, 143, 23, 10, 196, 108, 67, 95, 144, + 86, 185, 236, 143, 30, 90, 55, 134, 136, 39, 121, 85, 66, 183, + 173, 181, 148, 30, 38, 72, 133, 193, 31, 98, 155, 98, 70, 218, + 75, 23, 62, 160, 74, 121, 163, 112, 13, 240, 47, 106, 165, 76, + 102, 6, 175, 239, 169, 32, 214, 114, 153, 140, 219, 223, 128, 131, + 24, 135, 236, 216, 197, 207, 102, 4, 138, 116, 44, 87, 67, 136, + 86, 135, 161, 156, 11, 67, 53, 253, 13, 81, 129, 142, 154, 107, + 144, 212, 202, 107, 228, 199, 129, 127, 138, 247, 2, 168, 249, 122, + 6, 251, 246, 209, 56, 141, 19, 73, 100, 197, 110, 123, 167, 102, + 20, 9, 157, 128, 227, 16, 38, 253, 219, 106, 137, 91, 234, 32, + 49, 228, 149, 114, 14, 56, 20, 217, 215, 196, 144, 191, 65, 132, + 196, 148, 248, 145, 254, 155, 254, 63, 70, 185, 178, 6, 66, 78, + 31, 142, 192, 160, 40, 171, 253, 215, 229, 165, 42, 14, 11, 158, + 185, 236, 57, 238, 244, 138, 195, 120, 44, 204, 120, 54, 133, 70, + 135, 90, 56, 67, 91, 250, 50, 128, 188, 121, 37, 176, 62, 94, + 0, 65, 253, 175, 209, 205, 210, 207, 117, 171, 160, 40, 111, 195, + 30, 187, 229, 65, 15, 236, 210, 246, 96, 151, 78, 178, 107, 39, + 139, 228, 80, 9, 188, 245, 80, 143, 215, 82, 129, 136, 42, 218, + 178, 184, 67, 133, 195, 196, 242, 113, 27, 11, 233, 220, 183, 61, + 233, 177, 43, 33, 186, 222, 156, 69, 128, 39, 19, 144, 212, 160, + 184, 172, 32, 24, 5, 85, 125, 239, 185, 210, 41, 190, 133, 120, + 15, 42, 14, 252, 0, 88, 152, 69, 220, 229, 29, 35, 133, 182, + 106, 74, 169, 252, 133, 252, 122, 88, 87, 111, 35, 205, 142, 239, + 248, 33, 96, 193, 197, 112, 232, 177, 2, 232, 74, 167, 94, 53, + 223, 111, 51, 50, 93, 124, 21, 4, 163, 7, 134, 64, 92, 151, + 110, 118, 239, 223, 238, 189, 187, 69, 9, 125, 136, 148, 42, 122, + 41, 248, 239, 246, 19, 134, 104, 143, 48, 97, 130, 37, 160, 210, + 250, 0, 207, 31, 167, 145, 222, 25, 155, 160, 5, 243, 107, 237, + 116, 4, 85, 176, 57, 215, 206, 156, 26, 76, 144, 59, 83, 251, + 216, 180, 172, 119, 186, 227, 201, 78, 129, 34, 165, 215, 6, 112, + 130, 163, 144, 10, 235, 41, 18, 125, 204, 39, 53, 66, 51, 18, + 43, 91, 210, 129, 80, 115, 147, 136, 198, 163, 252, 129, 113, 63, + 205, 112, 23, 107, 221, 194, 88, 227, 55, 153, 121, 148, 123, 109, + 150, 224, 194, 172, 97, 162, 143, 91, 243, 143, 237, 119, 183, 28, + 159, 167, 72, 209, 47, 43, 80, 201, 31, 74, 70, 183, 19, 215, + 102, 232, 146, 33, 137, 233, 53, 219, 101, 231, 66, 136, 59, 243, + 28, 224, 53, 242, 146, 10, 103, 81, 240, 95, 111, 34, 72, 92, + 233, 133, 47, 65, 203, 231, 104, 199, 136, 50, 6, 50, 188, 15, + 248, 81, 200, 200, 107, 199, 96, 77, 132, 56, 157, 225, 52, 13, + 160, 203, 248, 210, 171, 23, 201, 22, 253, 139, 178, 210, 127, 229, + 98, 121, 88, 75, 61, 91, 98, 107, 119, 123, 169, 216, 245, 2, + 105, 253, 90, 74, 233, 32, 235, 213, 151, 75, 189, 100, 244, 84, + 64, 190, 70, 121, 51, 33, 108, 152, 166, 181, 17, 134, 127, 130, + 106, 99, 208, 221, 64, 184, 202, 232, 13, 201, 4, 132, 140, 21, + 245, 121, 206, 114, 254, 210, 51, 176, 114, 203, 125, 252, 107, 33, + 195, 35, 0, 193, 178, 207, 99, 60, 197, 235, 217, 72, 214, 9, + 218, 178, 91, 190, 113, 211, 180, 194, 17, 210, 111, 240, 221, 37, + 129, 105, 77, 217, 9, 169, 226, 199, 93, 246, 243, 199, 227, 23, + 206, 207, 60, 179, 175, 160, 141, 13, 89, 125, 87, 37, 203, 130, + 66, 115, 194, 97, 26, 193, 8, 88, 247, 134, 86, 30, 84, 166, + 201, 201, 125, 128, 226, 155, 137, 23, 85, 221, 58, 84, 108, 136, + 19, 188, 179, 153, 142, 193, 157, 63, 236, 205, 237, 242, 97, 249, + 244, 79, 127, 28, 8, 74, 109, 207, 31, 218, 0, 54, 215, 152, + 84, 156, 200, 237, 225, 211, 222, 170, 241, 231, 56, 209, 117, 193, + 251, 199, 234, 151, 105, 107, 154, 234, 185, 62, 121, 209, 217, 176, + 232, 69, 168, 148, 188, 134, 82, 105, 96, 138, 157, 204, 118, 51, + 61, 108, 144, 237, 65, 4, 65, 136, 191, 137, 248, 59, 60, 173, + 0, 89, 150, 122, 25, 247, 8, 83, 210, 254, 33, 80, 116, 144, + 86, 12, 223, 179, 168, 196, 121, 57, 211, 207, 113, 184, 104, 88, + 239, 68, 119, 91, 148, 211, 119, 66, 8, 202, 123, 230, 183, 253, + 178, 93, 113, 52, 65, 120, 56, 12, 20, 142, 81, 95, 58, 99, + 11, 215, 248, 126, 34, 90, 213, 9, 237, 117, 50, 194, 253, 117, + 170, 17, 153, 255, 46, 18, 230, 110, 8, 198, 204, 221, 102, 92, + 223, 191, 200, 209, 88, 141, 142, 91, 138, 145, 93, 223, 108, 67, + 8, 118, 76, 184, 53, 72, 189, 196, 106, 36, 115, 11, 152, 203, + 3, 15, 227, 237, 82, 161, 66, 88, 128, 128, 248, 51, 226, 84, + 164, 39, 100, 164, 109, 182, 232, 38, 23, 120, 159, 188, 200, 208, + 42, 180, 239, 20, 54, 148, 120, 155, 203, 56, 166, 187, 17, 162, + 165, 115, 123, 177, 139, 234, 63, 54, 109, 89, 35, 23, 12, 145, + 178, 88, 68, 19, 151, 171, 242, 89, 119, 117, 5, 236, 42, 183, + 69, 63, 135, 189, 221, 112, 138, 223, 252, 245, 90, 234, 14, 124, + 190, 159, 87, 36, 243, 166, 56, 148, 151, 58, 127, 87, 167, 23, + 229, 35, 86, 182, 40, 197, 80, 220, 222, 254, 66, 58, 0, 206, + 214, 132, 5, 116, 172, 220, 68, 187, 154, 34, 49, 56, 172, 24, + 194, 55, 72, 11, 229, 246, 201, 79, 107, 229, 91, 113, 134, 133, + 80, 99, 147, 144, 192, 49, 153, 12, 217, 151, 186, 62, 246, 79, + 136, 59, 40, 198, 50, 87, 86, 84, 106, 118, 215, 207, 102, 184, + 100, 191, 40, 108, 125, 136, 143, 118, 245, 17, 118, 146, 113, 76, + 19, 126, 133, 6, 93, 11, 12, 114, 56, 179, 17, 28, 97, 98, + 50, 76, 141, 99, 192, 247, 245, 251, 59, 230, 41, 120, 234, 51, + 167, 83, 15, 97, 144, 115, 173, 238, 79, 236, 167, 75, 135, 60, + 70, 75, 155, 155, 21, 107, 30, 21, 165, 29, 180, 195, 69, 95, + 130, 109, 194, 55, 88, 175, 199, 70, 113, 130, 237, 191, 191, 167, + 103, 38, 34, 167, 46, 9, 226, 87, 190, 146, 76, 127, 215, 0, + 146, 16, 192, 167, 145, 164, 137, 207, 107, 176, 63, 225, 187, 182, + 39, 202, 196, 56, 215, 177, 255, 45, 192, 45, 9, 77, 148, 72, + 7, 10, 172, 242, 99, 95, 95, 149, 59, 117, 25, 142, 83, 160, + 188, 148, 203, 127, 245, 123, 244, 240, 13, 237, 56, 23, 218, 211, + 104, 31, 100, 171, 248, 11, 144, 109, 13, 33, 84, 187, 152, 76, + 50, 240, 120, 247, 101, 97, 155, 122, 162, 17, 138, 135, 238, 203, + 159, 243, 155, 43, 79, 122, 167, 74, 119, 209, 12, 108, 29, 252, + 12, 6, 90, 158, 18, 33, 165, 11, 8, 147, 77, 164, 242, 214, + 52, 12, 245, 98, 52, 56, 133, 112, 112, 156, 115, 162, 5, 45, + 56, 108, 104, 19, 195, 3, 191, 205, 76, 143, 232, 75, 151, 181, + 234, 155, 59, 32, 23, 168, 107, 48, 230, 218, 234, 234, 21, 146, + 57, 153, 1, 116, 73, 254, 81, 239, 188, 179, 35, 118, 63, 185, + 123, 189, 204, 250, 252, 15, 113, 67, 59, 71, 181, 143, 86, 208, + 116, 74, 12, 183, 175, 252, 237, 175, 209, 97, 174, 118, 27, 99, + 117, 57, 133, 25, 61, 119, 148, 94, 36, 157, 44, 47, 180, 109, + 166, 47, 191, 100, 149, 130, 121, 10, 154, 51, 37, 41, 50, 152, + 174, 145, 14, 144, 195, 83, 244, 100, 234, 251, 152, 146, 64, 209, + 226, 191, 131, 10, 75, 73, 197, 147, 182, 13, 77, 200, 50, 36, + 139, 13, 97, 225, 126, 12, 80, 170, 184, 0, 154, 37, 175, 169, + 179, 70, 215, 140, 74, 66, 163, 242, 122, 73, 133, 199, 113, 47, + 37, 109, 254, 98, 44, 169, 47, 35, 241, 203, 159, 25, 186, 22, + 252, 38, 153, 217, 189, 11, 227, 49, 41, 147, 20, 156, 60, 91, + 217, 238, 151, 10, 47, 161, 217, 15, 201, 174, 223, 247, 42, 149, + 77, 191, 126, 124, 83, 192, 109, 101, 54, 235, 69, 230, 16, 30, + 144, 215, 90, 229, 101, 232, 87, 106, 39, 154, 99, 45, 16, 71, + 56, 169, 63, 202, 191, 64, 181, 245, 223, 255, 169, 206, 70, 117, + 66, 36, 38, 232, 87, 206, 214, 0, 36, 23, 242, 173, 18, 234, + 190, 214, 132, 157, 117, 233, 101, 155, 50, 52, 213, 74, 38, 253, + 6, 196, 94, 42, 8, 97, 115, 108, 109, 230, 77, 215, 148, 93, + 159, 15, 39, 97, 118, 59, 218, 223, 154, 218, 208, 230, 26, 231, + 117, 124, 66, 185, 196, 50, 236, 55, 213, 175, 126, 132, 255, 41, + 121, 148, 66, 51, 8, 215, 208, 253, 122, 233, 37, 107, 176, 85, + 253, 103, 193, 122, 34, 44, 47, 162, 17, 12, 154, 135, 29, 139, + 169, 97, 152, 92, 51, 111, 87, 213, 38, 255, 223, 94, 232, 170, + 122, 7, 37, 149, 189, 12, 46, 236, 43, 189, 190, 100, 35, 198, + 136, 243, 43, 250, 82, 234, 139, 56, 187, 45, 154, 215, 235, 38, + 145, 137, 126, 48, 72, 240, 122, 145, 171, 61, 162, 45, 232, 144, + 13, 70, 162, 202, 118, 69, 172, 150, 158, 191, 185, 89, 125, 112, + 222, 20, 184, 109, 202, 16, 87, 119, 214, 148, 135, 76, 19, 162, + 25, 167, 169, 22, 248, 9, 95, 159, 46, 193, 69, 5, 148, 180, + 17, 10, 25, 129, 180, 80, 68, 173, 138, 155, 226, 104, 188, 189, + 85, 211, 130, 30, 165, 181, 218, 110, 145, 209, 247, 135, 2, 152, + 220, 102, 250, 230, 50, 54, 46, 173, 140, 234, 34, 103, 208, 152, + 217, 249, 182, 169, 105, 235, 180, 165, 49, 229, 247, 95, 42, 160, + 141, 136, 37, 189, 169, 103, 7, 156, 56, 49, 96, 89, 227, 155, + 101, 251, 11, 244, 139, 111, 148, 203, 73, 61, 94, 15, 137, 27, + 119, 4, 136, 156, 169, 212, 82, 147, 129, 85, 161, 221, 27, 147, + 29, 235, 77, 182, 62, 127, 176, 71, 196, 33, 243, 58, 48, 139, + 81, 185, 47, 127, 163, 180, 190, 100, 198, 19, 169, 95, 141, 80, + 48, 199, 28, 37, 14, 217, 122, 152, 52, 62, 110, 2, 246, 254, + 181, 244, 74, 189, 5, 233, 159, 147, 82, 204, 98, 213, 6, 210, + 73, 113, 245, 164, 220, 236, 226, 233, 101, 86, 73, 123, 66, 7, + 198, 211, 23, 148, 57, 84, 30, 52, 58, 87, 177, 165, 136, 34, + 235, 19, 52, 78, 229, 221, 248, 160, 233, 3, 103, 201, 248, 229, + 106, 83, 254, 35, 190, 110, 63, 179, 66, 61, 158, 236, 157, 153, + 45, 150, 30, 102, 65, 215, 121, 157, 161, 202, 232, 217, 156, 238, + 244, 227, 169, 49, 189, 130, 90, 183, 169, 128, 80, 170, 249, 73, + 118, 161, 46, 253, 146, 185, 143, 149, 169, 241, 254, 251, 66, 187, + 41, 67, 131, 242, 193, 210, 88, 168, 178, 136, 24, 72, 204, 110, + 131, 217, 47, 255, 126, 112, 161, 228, 4, 133, 216, 219, 131, 44, + 71, 203, 194, 142, 96, 222, 64, 109, 34, 122, 68, 167, 192, 12, + 77, 236, 8, 69, 223, 133, 211, 7, 102, 116, 242, 1, 97, 165, + 18, 173, 229, 158, 131, 96, 78, 219, 9, 21, 151, 162, 219, 99, + 204, 32, 140, 247, 212, 58, 194, 51, 137, 12, 208, 75, 209, 73, + 84, 80, 138, 156, 26, 177, 209, 85, 189, 108, 72, 109, 221, 169, + 138, 4, 183, 229, 30, 253, 25, 250, 129, 175, 252, 74, 111, 244, + 241, 4, 117, 83, 109, 243, 116, 131, 179, 37, 241, 198, 117, 248, + 177, 106, 1, 198, 199, 10, 154, 118, 90, 56, 163, 188, 236, 8, + 164, 148, 190, 211, 176, 127, 179, 199, 147, 7, 211, 229, 97, 153, + 233, 233, 209, 214, 22, 84, 57, 124, 59, 30, 10, 33, 7, 202, + 15, 180, 237, 189, 196, 192, 188, 91, 248, 226, 206, 22, 49, 226, + 108, 143, 65, 228, 187, 1, 22, 247, 200, 154, 14, 86, 95, 85, + 79, 144, 146, 141, 210, 246, 224, 224, 14, 161, 101, 93, 190, 189, + 246, 232, 11, 7, 243, 65, 147, 75, 120, 121, 86, 36, 225, 50, + 233, 103, 142, 126, 214, 86, 233, 190, 1, 166, 186, 137, 101, 227, + 188, 8, 227, 13, 175, 184, 126, 194, 129, 10, 93, 233, 86, 54, + 145, 181, 201, 35, 5, 234, 197, 42, 131, 223, 14, 22, 186, 19, + 228, 163, 111, 15, 41, 238, 189, 242, 121, 149, 182, 21, 223, 39, + 9, 208, 122, 23, 118, 160, 148, 119, 55, 123, 230, 176, 205, 129, + 103, 54, 175, 235, 100, 98, 85, 141, 219, 114, 232, 113, 107, 74, + 5, 148, 7, 98, 138, 255, 168, 97, 190, 11, 20, 57, 70, 146, + 255, 103, 67, 97, 24, 142, 74, 84, 49, 56, 81, 145, 202, 2, + 200, 158, 187, 129, 6, 238, 149, 47, 170, 231, 58, 135, 5, 112, + 139, 184, 202, 168, 225, 176, 155, 111, 134, 125, 238, 7, 138, 112, + 140, 102, 255, 223, 29, 200, 218, 46, 185, 173, 21, 139, 91, 62, + 49, 118, 75, 182, 111, 31, 177, 152, 88, 146, 115, 120, 204, 107, + 156, 101, 157, 14, 65, 89, 234, 228, 142, 51, 204, 46, 147, 37, + 255, 17, 111, 102, 126, 148, 84, 119, 28, 127, 20, 49, 255, 191, + 116, 243, 234, 41, 107, 224, 80, 230, 154, 249, 223, 123, 199, 43, + 98, 200, 225, 197, 176, 108, 90, 222, 40, 46, 133, 94, 66, 184, + 224, 56, 216, 99, 130, 233, 135, 198, 169, 66, 149, 81, 104, 140, + 147, 74, 185, 254, 157, 141, 8, 76, 98, 63, 237, 92, 135, 217, + 233, 103, 147, 180, 227, 21, 12, 81, 124, 230, 17, 10, 31, 229, + 190, 115, 240, 177, 109, 153, 246, 28, 151, 190, 98, 229, 105, 231, + 20, 172, 160, 151, 40, 152, 45, 100, 139, 228, 174, 64, 129, 36, + 52, 4, 239, 106, 60, 234, 108, 107, 60, 173, 150, 1, 252, 167, + 112, 251, 192, 69, 127, 74, 103, 18, 217, 224, 85, 96, 205, 48, + 44, 164, 117, 214, 218, 37, 50, 16, 230, 7, 176, 69, 102, 185, + 39, 108, 33, 98, 130, 25, 163, 98, 52, 91, 3, 246, 90, 231, + 166, 56, 98, 11, 209, 111, 110, 159, 137, 65, 105, 128, 135, 86, + 24, 198, 4, 86, 97, 134, 166, 226, 116, 161, 235, 165, 156, 161, + 214, 215, 200, 82, 231, 122, 172, 70, 92, 132, 234, 203, 237, 158, + 54, 10, 28, 111, 71, 100, 34, 36, 138, 44, 252, 167, 229, 253, + 64, 83, 187, 148, 0, 225, 158, 115, 143, 52, 162, 98, 126, 21, + 18, 33, 186, 39, 120, 21, 190, 27, 36, 229, 165, 124, 75, 133, + 184, 120, 236, 137, 161, 182, 238, 250, 160, 92, 27, 102, 30, 12, + 194, 234, 228, 220, 57, 236, 50, 155, 224, 228, 147, 239, 95, 103, + 128, 94, 36, 85, 2, 197, 217, 137, 108, 193, 194, 183, 142, 100, + 179, 21, 213, 73, 188, 137, 99, 188, 152, 241, 207, 134, 178, 98, + 234, 97, 89, 131, 252, 199, 133, 34, 235, 15, 189, 105, 248, 161, + 100, 124, 193, 218, 178, 42, 163, 144, 119, 2, 30, 214, 179, 245, + 111, 60, 137, 165, 99, 55, 40, 169, 8, 18, 197, 20, 21, 188, + 151, 147, 240, 113, 164, 26, 42, 176, 231, 237, 187, 150, 100, 21, + 136, 160, 237, 231, 67, 144, 127, 38, 231, 125, 202, 21, 78, 232, + 129, 28, 12, 81, 87, 7, 162, 211, 129, 105, 218, 118, 48, 228, + 81, 198, 126, 178, 109, 210, 31, 208, 92, 36, 73, 3, 153, 161, + 93, 75, 41, 6, 153, 46, 249, 138, 198, 189, 171, 184, 187, 113, + 14, 150, 170, 185, 236, 170, 151, 47, 99, 14, 195, 11, 73, 88, + 129, 62, 215, 53, 123, 91, 77, 163, 178, 87, 64, 102, 230, 158, + 179, 117, 238, 197, 174, 231, 78, 169, 129, 121, 216, 132, 93, 201, + 142, 76, 136, 110, 105, 110, 197, 241, 17, 168, 25, 62, 201, 156, + 152, 218, 99, 7, 190, 205, 88, 68, 150, 111, 4, 31, 6, 253, + 155, 110, 234, 179, 122, 236, 107, 177, 39, 156, 253, 98, 76, 28, + 132, 229, 32, 222, 30, 193, 213, 98, 14, 22, 207, 87, 89, 29, + 255, 236, 208, 250, 166, 88, 106, 31, 121, 96, 80, 63, 190, 228, + 214, 99, 182, 239, 167, 250, 240, 63, 46, 115, 147, 68, 22, 205, + 158, 47, 127, 206, 121, 171, 243, 62, 103, 204, 25, 193, 50, 151, + 141, 250, 132, 163, 121, 254, 172, 144, 79, 73, 205, 204, 82, 148, + 94, 197, 107, 7, 141, 102, 178, 132, 61, 168, 43, 26, 116, 80, + 67, 255, 212, 3, 130, 7, 114, 99, 32, 217, 50, 144, 251, 166, + 38, 211, 61, 189, 174, 254, 251, 159, 79, 208, 158, 246, 187, 81, + 250, 168, 247, 9, 134, 175, 34, 185, 121, 70, 135, 44, 194, 102, + 114, 128, 242, 137, 254, 244, 137, 32, 217, 141, 87, 135, 248, 2, + 77, 88, 30, 171, 18, 2, 95, 113, 95, 206, 6, 118, 85, 190, + 132, 8, 103, 2, 145, 196, 30, 222, 234, 59, 175, 30, 187, 142, + 85, 208, 82, 74, 18, 122, 184, 54, 90, 147, 57, 64, 214, 41, + 11, 218, 60, 189, 110, 147, 247, 183, 255, 193, 53, 210, 237, 237, + 5, 238, 88, 138, 165, 175, 86, 177, 55, 4, 249, 89, 219, 198, + 75, 219, 90, 204, 151, 29, 227, 194, 240, 43, 120, 83, 209, 248, + 64, 177, 65, 214, 244, 246, 87, 116, 129, 153, 129, 208, 184, 77, + 176, 28, 137, 47, 29, 178, 89, 195, 22, 28, 11, 177, 173, 172, + 99, 237, 252, 21, 171, 193, 3, 244, 164, 72, 231, 173, 160, 31, + 78, 111, 172, 218, 134, 84, 232, 245, 69, 128, 128, 233, 76, 122, + 81, 114, 169, 228, 92, 141, 142, 80, 213, 130, 22, 247, 76, 89, + 3, 147, 180, 39, 221, 201, 139, 109, 129, 175, 208, 13, 76, 44, + 236, 124, 103, 36, 156, 53, 184, 198, 73, 82, 114, 198, 58, 174, + 1, 240, 247, 234, 24, 6, 231, 126, 111, 218, 37, 179, 192, 202, + 152, 104, 161, 180, 14, 131, 212, 86, 198, 11, 37, 152, 62, 136, + 2, 59, 119, 102, 44, 137, 209, 247, 147, 138, 215, 5, 114, 48, + 78, 134, 59, 28, 171, 61, 196, 166, 186, 135, 72, 101, 96, 4, + 36, 94, 140, 158, 80, 61, 116, 131, 67, 61, 23, 95, 209, 209, + 200, 187, 145, 83, 253, 104, 251, 152, 210, 120, 145, 197, 168, 161, + 127, 146, 91, 178, 188, 155, 151, 181, 55, 26, 116, 178, 71, 232, + 34, 189, 109, 187, 106, 182, 204, 81, 217, 125, 161, 172, 239, 232, + 12, 101, 101, 91, 46, 20, 32, 86, 67, 217, 137, 195, 184, 108, + 228, 22, 164, 129, 93, 20, 206, 39, 167, 103, 136, 110, 64, 242, + 164, 97, 159, 0, 215, 103, 0, 6, 8, 237, 118, 39, 168, 27, + 233, 35, 185, 34, 143, 16, 119, 15, 148, 221, 162, 20, 253, 13, + 71, 250, 75, 112, 175, 190, 230, 54, 211, 247, 13, 49, 73, 13, + 113, 207, 4, 205, 140, 55, 137, 100, 145, 31, 143, 234, 82, 37, + 230, 234, 31, 191, 151, 28, 202, 228, 70, 194, 190, 187, 56, 52, + 28, 196, 17, 134, 70, 210, 13, 88, 169, 245, 50, 100, 4, 86, + 70, 208, 58, 4, 105, 217, 136, 234, 1, 34, 161, 192, 164, 231, + 71, 213, 59, 126, 10, 151, 247, 177, 137, 155, 227, 109, 121, 148, + 23, 110, 83, 110, 8, 242, 118, 124, 5, 249, 50, 146, 234, 196, + 45, 249, 251, 38, 104, 131, 19, 233, 163, 11, 31, 68, 30, 19, + 198, 38, 201, 74, 111, 138, 98, 26, 234, 113, 232, 98, 178, 152, + 227, 163, 241, 136, 73, 194, 230, 131, 143, 140, 215, 79, 44, 53, + 163, 37, 83, 117, 149, 184, 9, 80, 36, 4, 77, 162, 37, 162, + 219, 27, 129, 12, 98, 40, 173, 135, 217, 127, 191, 60, 190, 52, + 186, 67, 64, 144, 40, 212, 215, 53, 133, 16, 75, 192, 79, 4, + 96, 142, 96, 116, 42, 153, 153, 123, 102, 69, 239, 224, 251, 226, + 31, 20, 238, 135, 84, 17, 79, 45, 44, 254, 3, 180, 103, 80, + 185, 60, 215, 150, 234, 50, 31, 57, 205, 186, 254, 93, 70, 220, + 38, 247, 110, 93, 113, 220, 97, 234, 202, 84, 233, 19, 89, 63, + 227, 43, 85, 254, 144, 203, 236, 81, 143, 155, 177, 204, 140, 203, + 178, 242, 167, 30, 56, 187, 96, 232, 182, 55, 53, 205, 136, 128, + 196, 187, 92, 95, 44, 166, 16, 247, 25, 165, 148, 143, 156, 171, + 178, 109, 97, 2, 96, 111, 131, 69, 164, 135, 175, 106, 112, 205, + 41, 248, 224, 111, 155, 106, 169, 27, 59, 164, 84, 171, 93, 24, + 197, 52, 88, 149, 139, 191, 103, 112, 6, 97, 8, 29, 200, 217, + 103, 225, 36, 140, 45, 52, 85, 99, 133, 36, 116, 105, 42, 85, + 252, 197, 121, 30, 231, 177, 105, 63, 112, 30, 165, 216, 185, 102, + 59, 123, 251, 236, 66, 4, 104, 68, 17, 125, 34, 60, 194, 196, + 228, 43, 118, 10, 96, 62, 232, 193, 134, 179, 21, 106, 179, 26, + 139, 64, 99, 131, 26, 123, 196, 83, 75, 176, 53, 160, 254, 119, + 196, 96, 162, 154, 141, 253, 108, 142, 160, 149, 110, 89, 4, 140, + 245, 244, 15, 35, 37, 34, 139, 46, 246, 47, 8, 193, 163, 169, + 191, 57, 218, 63, 168, 32, 228, 208, 22, 54, 171, 240, 45, 30, + 177, 230, 177, 97, 77, 168, 197, 222, 54, 87, 209, 105, 104, 41, + 143, 249, 48, 15, 87, 129, 54, 32, 119, 26, 240, 147, 233, 160, + 169, 233, 0, 189, 8, 247, 43, 104, 178, 200, 77, 180, 65, 161, + 187, 8, 85, 233, 164, 81, 109, 140, 1, 89, 177, 244, 83, 61, + 128, 98, 128, 193, 95, 47, 190, 224, 57, 178, 253, 135, 163, 27, + 131, 51, 213, 120, 239, 239, 208, 252, 125, 32, 156, 204, 155, 153, + 39, 77, 14, 125, 64, 54, 164, 122, 203, 42, 34, 116, 14, 153, + 65, 117, 255, 42, 131, 132, 254, 132, 96, 16, 52, 141, 245, 27, + 33, 181, 162, 136, 130, 183, 42, 125, 57, 177, 102, 220, 207, 156, + 141, 129, 145, 194, 116, 133, 220, 218, 240, 170, 129, 232, 38, 208, + 44, 33, 24, 10, 176, 210, 238, 190, 176, 20, 114, 41, 11, 80, + 120, 201, 192, 88, 96, 48, 78, 149, 239, 139, 206, 241, 145, 225, + 190, 6, 138, 151, 148, 241, 62, 94, 51, 49, 66, 178, 19, 146, + 139, 41, 143, 159, 65, 118, 188, 39, 203, 165, 62, 167, 229, 191, + 37, 31, 82, 101, 155, 93, 221, 200, 135, 175, 97, 231, 106, 160, + 79, 136, 102, 159, 49, 212, 222, 184, 99, 174, 56, 36, 194, 66, + 33, 104, 28, 218, 167, 187, 142, 91, 187, 194, 188, 13, 77, 164, + 75, 48, 139, 174, 153, 174, 6, 16, 109, 81, 15, 152, 70, 106, + 63, 197, 5, 149, 113, 9, 241, 94, 229, 167, 153, 116, 120, 97, + 68, 149, 209, 121, 104, 5, 132, 67, 77, 52, 5, 64, 16, 166, + 32, 154, 72, 231, 6, 186, 114, 7, 21, 43, 24, 136, 125, 125, + 121, 62, 18, 72, 87, 25, 17, 76, 13, 166, 209, 176, 108, 197, + 178, 175, 121, 130, 233, 48, 44, 81, 188, 93, 115, 6, 10, 102, + 203, 176, 26, 218, 43, 69, 131, 155, 142, 44, 204, 185, 109, 236, + 199, 204, 90, 246, 110, 57, 176, 9, 108, 251, 167, 191, 48, 166, + 60, 1, 172, 135, 58, 246, 222, 111, 127, 109, 164, 232, 12, 137, + 63, 109, 246, 204, 217, 103, 136, 204, 53, 161, 77, 38, 39, 176, + 242, 216, 109, 245, 180, 72, 170, 79, 209, 142, 67, 40, 150, 247, + 147, 159, 64, 24, 70, 18, 247, 55, 116, 138, 93, 84, 130, 222, + 134, 168, 172, 205, 57, 146, 115, 11, 252, 185, 48, 95, 199, 134, + 102, 165, 227, 118, 102, 248, 2, 137, 54, 149, 148, 155, 188, 177, + 226, 245, 37, 31, 140, 135, 103, 135, 77, 61, 15, 67, 160, 1, + 203, 58, 168, 155, 63, 236, 182, 176, 71, 238, 134, 229, 99, 240, + 131, 226, 93, 131, 52, 131, 83, 255, 135, 108, 181, 134, 109, 194, + 34, 202, 32, 249, 199, 83, 194, 114, 137, 181, 107, 209, 89, 41, + 166, 43, 40, 30, 255, 47, 178, 126, 183, 91, 214, 112, 49, 37, + 68, 33, 10, 196, 71, 214, 243, 145, 191, 121, 107, 23, 230, 108, + 176, 10, 97, 161, 222, 108, 146, 78, 229, 115, 124, 127, 199, 3, + 250, 73, 82, 103, 64, 46, 244, 167, 186, 38, 18, 243, 67, 180, + 54, 203, 168, 28, 96, 167, 21, 161, 89, 176, 208, 18, 8, 57, + 45, 148, 208, 216, 107, 135, 228, 162, 245, 110, 239, 159, 184, 211, + 219, 203, 149, 187, 199, 23, 189, 7, 146, 196, 36, 68, 16, 150, + 12, 50, 178, 68, 9, 86, 1, 49, 172, 45, 94, 173, 228, 168, + 79, 205, 5, 140, 196, 20, 43, 94, 234, 14, 39, 42, 220, 64, + 118, 43, 1, 193, 85, 95, 188, 147, 117, 220, 75, 203, 164, 204, + 80, 248, 19, 29, 87, 206, 235, 206, 184, 163, 124, 141, 75, 1, + 77, 185, 233, 131, 152, 145, 240, 83, 218, 78, 35, 107, 84, 226, + 205, 137, 36, 123, 2, 229, 219, 117, 177, 240, 149, 73, 168, 56, + 13, 188, 218, 81, 236, 8, 179, 202, 67, 123, 230, 221, 199, 193, + 6, 139, 2, 214, 6, 39, 33, 109, 8, 230, 177, 7, 4, 203, + 104, 132, 245, 84, 250, 44, 251, 147, 188, 167, 218, 50, 131, 176, + 213, 139, 207, 182, 97, 195, 255, 105, 89, 209, 248, 140, 105, 117, + 142, 50, 229, 37, 187, 44, 56, 78, 120, 144, 144, 82, 179, 173, + 93, 114, 31, 232, 207, 158, 79, 59, 165, 69, 51, 203, 221, 207, + 65, 186, 50, 92, 99, 54, 136, 51, 76, 26, 22, 73, 175, 52, + 50, 207, 203, 193, 214, 134, 8, 86, 58, 148, 63, 79, 181, 114, + 9, 163, 22, 5, 143, 106, 147, 24, 212, 48, 178, 52, 43, 5, + 169, 204, 121, 146, 240, 220, 88, 217, 241, 238, 38, 74, 81, 162, + 9, 171, 192, 229, 190, 101, 148, 219, 41, 170, 244, 229, 123, 105, + 192, 227, 21, 57, 37, 236, 53, 173, 133, 134, 239, 140, 1, 179, + 255, 183, 216, 67, 192, 35, 181, 29, 135, 201, 64, 255, 42, 174, + 118, 124, 58, 68, 78, 1, 36, 156, 26, 164, 230, 99, 43, 34, + 213, 16, 115, 37, 185, 243, 15, 232, 7, 195, 222, 2, 79, 225, + 36, 217, 127, 155, 95, 42, 8, 158, 157, 16, 234, 159, 187, 174, + 178, 167, 160, 43, 194, 149, 133, 248, 231, 49, 125, 154, 247, 231, + 141, 32, 32, 55, 62, 92, 12, 97, 245, 14, 153, 45, 54, 167, + 84, 83, 189, 207, 227, 225, 8, 137, 47, 35, 254, 251, 158, 147, + 119, 39, 48, 194, 223, 5, 44, 128, 15, 42, 203, 10, 236, 17, + 231, 226, 72, 32, 120, 90, 78, 8, 51, 217, 157, 95, 165, 200, + 210, 243, 105, 32, 128, 105, 221, 59, 253, 215, 217, 121, 41, 131, + 173, 77, 97, 148, 228, 80, 219, 2, 49, 63, 194, 100, 96, 227, + 43, 81, 206, 108, 251, 201, 40, 132, 235, 158, 10, 137, 88, 55, + 222, 169, 209, 247, 237, 222, 241, 161, 38, 43, 98, 189, 8, 246, + 47, 147, 234, 6, 50, 1, 209, 170, 239, 210, 140, 61, 81, 16, + 141, 56, 83, 196, 130, 141, 11, 78, 23, 213, 16, 32, 128, 2, + 91, 21, 121, 102, 247, 163, 90, 57, 52, 186, 91, 68, 115, 30, + 247, 190, 204, 202, 214, 134, 224, 16, 106, 45, 72, 137, 181, 240, + 4, 25, 142, 170, 14, 46, 75, 39, 126, 196, 1, 112, 67, 181, + 176, 11, 24, 229, 31, 106, 64, 112, 81, 91, 207, 248, 205, 94, + 17, 120, 80, 33, 14, 130, 92, 27, 76, 194, 22, 92, 35, 228, + 14, 77, 212, 23, 183, 120, 13, 179, 5, 82, 255, 177, 87, 252, + 173, 98, 53, 33, 95, 114, 56, 70, 107, 109, 24, 129, 6, 27, + 238, 5, 210, 228, 144, 44, 187, 56, 175, 77, 250, 191, 229, 49, + 119, 31, 170, 153, 51, 117, 213, 74, 212, 197, 65, 240, 49, 229, + 21, 237, 49, 159, 35, 40, 210, 76, 50, 135, 28, 147, 202, 24, + 182, 126, 7, 175, 195, 0, 116, 105, 134, 124, 12, 21, 230, 227, + 218, 70, 165, 69, 53, 216, 244, 208, 44, 149, 201, 136, 38, 160, + 181, 171, 93, 244, 98, 164, 207, 18, 241, 177, 104, 43, 217, 93, + 22, 240, 169, 55, 55, 18, 25, 157, 249, 35, 113, 211, 250, 42, + 232, 238, 157, 121, 176, 219, 72, 0, 53, 39, 112, 13, 124, 174, + 59, 65, 248, 82, 251, 248, 208, 96, 0, 230, 75, 207, 26, 144, + 25, 192, 133, 122, 105, 111, 90, 241, 194, 108, 92, 84, 130, 205, + 70, 243, 184, 15, 81, 229, 199, 199, 82, 208, 169, 205, 199, 94, + 183, 50, 114, 247, 166, 146, 226, 210, 204, 130, 249, 252, 180, 228, + 194, 86, 78, 87, 195, 84, 33, 197, 232, 110, 153, 165, 163, 131, + 237, 136, 154, 236, 51, 136, 118, 56, 40, 57, 97, 141, 39, 124, + 226, 197, 96, 185, 31, 35, 139, 99, 251, 239, 96, 168, 217, 16, + 156, 107, 23, 38, 228, 64, 81, 183, 184, 10, 4, 198, 17, 28, + 102, 37, 126, 216, 45, 254, 187, 40, 240, 20, 140, 31, 187, 68, + 119, 120, 183, 75, 102, 215, 172, 129, 147, 53, 211, 190, 190, 204, + 151, 69, 222, 233, 222, 219, 19, 143, 155, 158, 158, 71, 128, 70, + 158, 23, 19, 223, 239, 172, 157, 16, 130, 148, 52, 103, 110, 135, + 106, 254, 146, 151, 46, 111, 90, 201, 74, 185, 43, 192, 68, 91, + 67, 128, 150, 51, 156, 71, 60, 73, 223, 62, 31, 83, 236, 146, + 35, 85, 44, 169, 83, 49, 76, 146, 180, 95, 124, 45, 137, 35, + 181, 33, 31, 215, 0, 85, 187, 120, 51, 121, 174, 239, 166, 18, + 175, 241, 141, 142, 147, 70, 41, 36, 81, 25, 104, 155, 235, 191, + 245, 239, 142, 22, 28, 135, 98, 104, 19, 1, 50, 45, 86, 184, + 90, 1, 39, 67, 77, 229, 118, 253, 118, 186, 177, 205, 105, 219, + 152, 127, 203, 56, 229, 208, 209, 60, 122, 187, 74, 16, 131, 71, + 74, 183, 48, 114, 126, 238, 53, 9, 76, 216, 166, 19, 223, 17, + 202, 41, 211, 142, 238, 63, 125, 159, 238, 212, 160, 203, 156, 145, + 46, 50, 149, 206, 169, 155, 169, 181, 200, 240, 187, 123, 132, 56, + 208, 60, 183, 36, 140, 149, 180, 101, 83, 51, 156, 139, 71, 240, + 121, 86, 194, 254, 4, 26, 32, 185, 233, 203, 58, 248, 89, 30, + 164, 216, 81, 110, 243, 245, 112, 244, 53, 24, 146, 195, 109, 197, + 215, 121, 11, 61, 84, 248, 58, 61, 236, 79, 181, 46, 2, 52, + 66, 54, 231, 31, 70, 253, 122, 68, 249, 195, 160, 67, 93, 151, + 0, 105, 199, 43, 17, 179, 85, 235, 137, 58, 89, 68, 28, 255, + 22, 194, 158, 38, 224, 161, 138, 239, 33, 83, 26, 242, 0, 31, + 64, 99, 56, 17, 97, 36, 240, 24, 211, 77, 208, 6, 88, 117, + 126, 219, 246, 173, 203, 254, 31, 98, 202, 221, 194, 192, 226, 10, + 185, 112, 84, 101, 111, 112, 155, 78, 153, 111, 78, 189, 59, 100, + 212, 198, 223, 248, 9, 174, 69, 99, 137, 138, 196, 110, 208, 0, + 106, 108, 164, 51, 185, 88, 64, 239, 123, 52, 87, 243, 129, 165, + 108, 86, 150, 167, 191, 166, 21, 226, 153, 63, 198, 177, 60, 253, + 207, 223, 69, 12, 47, 210, 31, 155, 122, 41, 65, 200, 100, 25, + 25, 223, 112, 89, 136, 54, 115, 97, 235, 192, 152, 243, 44, 81, + 247, 205, 45, 134, 148, 183, 126, 27, 37, 55, 190, 122, 239, 160, + 95, 56, 162, 205, 209, 210, 60, 32, 214, 81, 119, 148, 155, 2, + 88, 176, 101, 102, 242, 140, 57, 94, 18, 144, 207, 189, 80, 161, + 199, 83, 3, 38, 39, 68, 158, 30, 220, 153, 105, 122, 16, 77, + 52, 8, 115, 91, 184, 56, 50, 164, 31, 236, 87, 38, 16, 115, + 16, 227, 194, 165, 157, 42, 228, 220, 119, 122, 244, 224, 60, 46, + 92, 139, 78, 138, 133, 204, 154, 15, 26, 158, 136, 253, 72, 204, + 72, 159, 239, 231, 35, 92, 137, 217, 233, 220, 93, 13, 253, 121, + 183, 25, 151, 14, 49, 238, 120, 54, 232, 100, 39, 62, 127, 89, + 156, 7, 91, 48, 49, 110, 52, 111, 62, 1, 175, 103, 46, 250, + 177, 68, 212, 5, 88, 132, 91, 57, 100, 122, 12, 121, 115, 197, + 87, 88, 133, 50, 71, 243, 190, 92, 119, 184, 57, 153, 152, 190, + 247, 166, 182, 11, 181, 234, 98, 177, 144, 52, 131, 24, 87, 220, + 167, 238, 180, 20, 34, 149, 83, 182, 163, 67, 144, 163, 26, 123, + 42, 187, 43, 225, 29, 110, 142, 90, 60, 49, 168, 202, 43, 57, + 101, 84, 7, 17, 127, 135, 110, 107, 150, 83, 83, 75, 244, 253, + 104, 113, 96, 247, 254, 24, 251, 172, 247, 1, 253, 72, 68, 150, + 108, 112, 53, 55, 156, 21, 237, 99, 126, 31, 33, 203, 25, 226, + 160, 216, 68, 41, 70, 189, 173, 54, 222, 218, 202, 17, 246, 159, + 184, 222, 125, 135, 133, 159, 248, 35, 7, 151, 122, 69, 152, 135, + 204, 119, 115, 100, 40, 85, 203, 210, 224, 176, 207, 41, 102, 242, + 42, 88, 86, 83, 63, 32, 57, 253, 167, 130, 40, 255, 127, 91, + 113, 97, 205, 18, 216, 122, 30, 81, 205, 161, 45, 177, 142, 26, + 143, 110, 99, 75, 178, 242, 91, 164, 104, 47, 70, 113, 0, 24, + 86, 124, 109, 121, 99, 129, 59, 105, 72, 99, 167, 16, 164, 202, + 209, 39, 37, 151, 52, 110, 117, 40, 119, 242, 91, 9, 151, 218, + 50, 5, 104, 169, 40, 207, 196, 17, 146, 206, 36, 148, 169, 92, + 161, 129, 177, 245, 99, 228, 240, 133, 5, 230, 66, 13, 10, 162, + 160, 142, 246, 115, 33, 112, 149, 217, 38, 201, 209, 68, 50, 216, + 196, 56, 222, 101, 190, 19, 61, 81, 54, 1, 193, 114, 121, 15, + 211, 146, 179, 110, 33, 153, 199, 99, 250, 33, 100, 39, 162, 43, + 144, 28, 32, 197, 38, 252, 90, 81, 198, 38, 53, 96, 137, 217, + 133, 128, 85, 86, 88, 19, 195, 167, 93, 167, 242, 113, 196, 39, + 233, 55, 206, 70, 56, 249, 241, 142, 113, 50, 74, 172, 182, 214, + 18, 11, 27, 231, 66, 200, 167, 56, 29, 105, 179, 41, 201, 70, + 56, 8, 106, 84, 241, 139, 121, 158, 62, 189, 240, 80, 143, 151, + 254, 184, 126, 61, 206, 171, 180, 75, 194, 10, 214, 202, 33, 62, + 86, 187, 44, 129, 221, 131, 36, 241, 110, 211, 254, 133, 7, 53, + 222, 180, 8, 195, 48, 155, 194, 150, 130, 62, 111, 120, 170, 222, + 70, 148, 147, 135, 217, 107, 189, 89, 24, 51, 117, 40, 240, 17, + 220, 235, 194, 179, 235, 245, 137, 164, 82, 198, 174, 21, 181, 50, + 87, 79, 144, 168, 47, 107, 36, 230, 109, 108, 42, 190, 220, 97, + 67, 38, 238, 40, 27, 167, 1, 167, 162, 202, 37, 123, 165, 132, + 117, 99, 139, 201, 9, 162, 228, 43, 105, 95, 187, 184, 113, 176, + 202, 171, 188, 18, 158, 162, 81, 195, 114, 33, 163, 186, 213, 218, + 75, 168, 141, 211, 101, 90, 135, 96, 138, 40, 77, 19, 248, 227, + 187, 172, 182, 138, 6, 25, 216, 36, 243, 202, 104, 90, 50, 41, + 99, 250, 128, 144, 59, 212, 31, 239, 2, 183, 57, 167, 45, 49, + 31, 53, 41, 90, 80, 192, 129, 232, 181, 143, 47, 41, 225, 99, + 115, 18, 197, 182, 235, 246, 21, 197, 41, 120, 246, 252, 110, 5, + 192, 172, 109, 224, 143, 166, 128, 40, 161, 129, 47, 94, 179, 40, + 172, 141, 2, 1, 35, 141, 225, 38, 66, 131, 101, 53, 164, 255, + 51, 2, 49, 222, 116, 58, 96, 188, 14, 4, 87, 117, 129, 174, + 78, 67, 138, 70, 158, 211, 150, 209, 218, 112, 113, 88, 24, 80, + 85, 241, 134, 189, 64, 192, 218, 122, 82, 114, 37, 226, 132, 118, + 130, 71, 206, 21, 246, 106, 108, 192, 181, 149, 207, 21, 146, 183, + 56, 242, 152, 71, 209, 38, 238, 248, 2, 186, 1, 223, 204, 79, + 18, 187, 172, 226, 222, 3, 201, 1, 84, 231, 64, 200, 101, 168, + 2, 49, 42, 184, 56, 7, 247, 53, 226, 166, 88, 161, 102, 154, + 11, 158, 88, 251, 225, 20, 49, 241, 72, 101, 43, 232, 236, 150, + 178, 115, 221, 70, 212, 210, 243, 90, 28, 162, 210, 86, 181, 177, + 20, 202, 105, 59, 235, 25, 192, 247, 15, 180, 118, 35, 48, 15, + 156, 39, 40, 80, 246, 206, 218, 206, 200, 170, 109, 241, 110, 108, + 66, 29, 143, 78, 223, 26, 114, 125, 137, 127, 239, 113, 140, 180, + 6, 136, 71, 197, 117, 254, 130, 79, 14, 19, 72, 218, 57, 195, + 53, 3, 177, 187, 174, 52, 162, 6, 57, 32, 117, 45, 110, 124, + 93, 129, 151, 11, 125, 10, 56, 104, 10, 40, 65, 153, 174, 208, + 120, 43, 129, 196, 118, 32, 144, 250, 18, 203, 68, 243, 78, 51, + 231, 79, 62, 34, 136, 49, 16, 148, 156, 218, 104, 245, 216, 52, + 170, 101, 242, 47, 72, 13, 236, 198, 243, 191, 1, 29, 233, 81, + 48, 122, 189, 129, 17, 90, 30, 195, 63, 241, 144, 37, 237, 10, + 168, 4, 32, 232, 9, 83, 207, 27, 18, 155, 214, 168, 149, 112, + 196, 48, 157, 228, 125, 79, 57, 118, 182, 94, 92, 221, 33, 18, + 255, 11, 103, 185, 52, 162, 161, 87, 121, 89, 31, 108, 206, 156, + 11, 239, 83, 92, 239, 225, 100, 162, 43, 145, 97, 234, 228, 145, + 202, 48, 57, 47, 70, 180, 41, 140, 147, 136, 102, 65, 163, 93, + 90, 160, 34, 160, 100, 72, 129, 100, 53, 129, 236, 140, 238, 203, + 89, 117, 196, 50, 11, 74, 235, 133, 253, 101, 220, 152, 183, 92, + 87, 67, 120, 168, 70, 79, 103, 36, 185, 183, 137, 84, 245, 200, + 34, 114, 226, 44, 96, 94, 159, 50, 64, 15, 195, 222, 152, 26, + 225, 21, 169, 35, 249, 220, 28, 135, 134, 25, 9, 12, 243, 84, + 253, 224, 216, 178, 91, 73, 199, 188, 3, 49, 246, 148, 184, 148, + 199, 93, 150, 152, 42, 244, 145, 247, 47, 171, 81, 149, 207, 135, + 110, 45, 103, 96, 161, 47, 176, 247, 61, 117, 169, 178, 27, 251, + 147, 44, 99, 205, 253, 59, 146, 230, 69, 168, 14, 37, 176, 36, + 125, 45, 82, 74, 93, 39, 33, 50, 53, 207, 228, 94, 151, 201, + 221, 244, 66, 98, 60, 8, 120, 229, 89, 231, 26, 61, 156, 170, + 105, 93, 14, 126, 203, 29, 102, 221, 113, 47, 7, 231, 10, 149, + 47, 115, 44, 158, 27, 57, 104, 245, 59, 201, 139, 245, 125, 71, + 144, 231, 145, 26, 204, 199, 120, 179, 20, 182, 252, 201, 237, 177, + 227, 213, 176, 146, 177, 178, 0, 54, 150, 26, 200, 143, 29, 7, + 191, 58, 195, 168, 231, 80, 224, 212, 24, 22, 218, 191, 216, 44, + 108, 121, 132, 201, 197, 213, 97, 161, 48, 215, 126, 27, 95, 180, + 166, 226, 198, 156, 88, 145, 241, 129, 17, 142, 97, 182, 243, 184, + 11, 117, 130, 189, 173, 22, 163, 56, 148, 57, 141, 75, 53, 180, + 251, 204, 190, 205, 33, 102, 175, 160, 204, 246, 230, 156, 123, 73, + 212, 84, 159, 83, 75, 183, 38, 23, 11, 164, 79, 183, 98, 100, + 243, 71, 179, 112, 97, 148, 32, 8, 93, 238, 153, 156, 109, 224, + 179, 109, 176, 143, 56, 8, 15, 41, 231, 155, 32, 42, 233, 220, + 173, 82, 39, 92, 96, 113, 186, 64, 242, 58, 74, 146, 253, 18, + 175, 34, 219, 19, 3, 135, 238, 240, 190, 28, 53, 15, 107, 243, + 236, 201, 193, 223, 58, 151, 35, 143, 202, 98, 96, 80, 168, 64, + 89, 233, 135, 236, 2, 37, 156, 118, 191, 206, 167, 249, 176, 69, + 228, 58, 242, 81, 104, 236, 227, 72, 83, 29, 107, 204, 241, 224, + 88, 133, 124, 196, 41, 38, 88, 23, 94, 6, 36, 112, 73, 8, + 167, 209, 87, 92, 215, 99, 14, 199, 31, 43, 217, 207, 27, 184, + 140, 133, 214, 26, 50, 129, 68, 151, 154, 58, 146, 218, 56, 175, + 158, 54, 80, 211, 209, 192, 25, 118, 93, 78, 49, 232, 115, 33, + 122, 119, 135, 28, 118, 253, 56, 162, 140, 10, 168, 181, 250, 148, + 240, 76, 111, 194, 227, 118, 232, 228, 143, 27, 233, 222, 167, 18, + 194, 108, 184, 36, 199, 41, 26, 89, 117, 29, 140, 6, 3, 120, + 93, 199, 110, 201, 180, 208, 137, 119, 149, 222, 83, 247, 128, 37, + 3, 157, 67, 255, 233, 124, 196, 184, 52, 111, 233, 236, 249, 66, + 212, 134, 61, 34, 135, 237, 116, 246, 16, 151, 136, 180, 119, 232, + 168, 168, 194, 27, 116, 221, 69, 70, 117, 111, 248, 215, 50, 231, + 122, 165, 223, 197, 162, 165, 208, 107, 104, 73, 125, 133, 34, 114, + 209, 198, 193, 115, 170, 143, 69, 20, 187, 11, 61, 222, 64, 130, + 197, 142, 32, 119, 228, 142, 58, 223, 157, 53, 12, 194, 188, 27, + 34, 42, 172, 169, 0, 184, 67, 223, 226, 224, 191, 116, 22, 36, + 211, 193, 204, 73, 227, 117, 12, 255, 24, 80, 54, 74, 67, 104, + 27, 227, 169, 183, 197, 102, 214, 19, 213, 49, 94, 132, 127, 207, + 113, 56, 94, 189, 76, 199, 54, 46, 93, 51, 34, 130, 69, 76, + 76, 234, 14, 47, 209, 138, 184, 98, 173, 77, 201, 122, 46, 178, + 134, 79, 188, 201, 197, 129, 197, 17, 224, 63, 180, 222, 112, 222, + 78, 146, 202, 35, 41, 183, 208, 108, 48, 127, 197, 83, 119, 75, + 49, 157, 149, 74, 169, 99, 96, 106, 21, 236, 50, 229, 120, 60, + 2, 41, 168, 171, 50, 124, 139, 138, 215, 96, 222, 83, 204, 63, + 146, 145, 97, 121, 172, 151, 241, 16, 145, 124, 63, 223, 197, 188, + 210, 97, 21, 53, 65, 221, 114, 168, 105, 8, 34, 186, 246, 83, + 94, 94, 29, 148, 221, 96, 153, 57, 204, 73, 68, 165, 94, 177, + 122, 131, 89, 122, 227, 95, 54, 104, 6, 235, 73, 216, 215, 156, + 185, 245, 50, 204, 205, 73, 37, 210, 214, 220, 95, 184, 133, 83, + 149, 167, 15, 202, 99, 41, 237, 77, 184, 172, 215, 104, 6, 101, + 103, 244, 12, 68, 180, 73, 178, 2, 157, 169, 189, 14, 54, 151, + 100, 16, 145, 43, 87, 125, 66, 124, 95, 86, 220, 159, 230, 79, + 94, 255, 113, 24, 11, 33, 187, 15, 225, 81, 72, 44, 237, 38, + 67, 150, 7, 238, 97, 239, 96, 42, 29, 153, 120, 190, 213, 180, + 45, 24, 9, 142, 63, 122, 38, 23, 252, 144, 158, 28, 26, 190, + 248, 60, 43, 187, 58, 79, 54, 127, 220, 27, 224, 167, 167, 171, + 1, 187, 167, 124, 118, 183, 240, 14, 71, 200, 146, 69, 132, 117, + 70, 65, 37, 64, 245, 191, 128, 148, 209, 87, 56, 98, 171, 93, + 189, 141, 0, 20, 6, 47, 24, 214, 111, 115, 242, 58, 2, 220, + 124, 110, 234, 214, 215, 230, 120, 88, 169, 64, 118, 22, 149, 148, + 177, 154, 107, 226, 212, 128, 137, 146, 142, 45, 101, 12, 150, 127, + 78, 153, 149, 172, 120, 174, 214, 105, 29, 26, 96, 203, 105, 1, + 207, 98, 176, 146, 197, 8, 157, 128, 181, 254, 55, 36, 236, 203, + 162, 169, 13, 35, 136, 221, 168, 107, 213, 228, 27, 247, 40, 162, + 238, 1, 157, 117, 89, 91, 147, 60, 57, 137, 179, 74, 78, 239, + 106, 223, 24, 50, 30, 8, 179, 103, 228, 211, 132, 29, 25, 246, + 181, 244, 46, 57, 2, 55, 96, 41, 215, 225, 150, 210, 194, 192, + 85, 44, 34, 155, 175, 121, 226, 8, 170, 223, 91, 4, 2, 166, + 21, 200, 184, 147, 60, 21, 174, 59, 215, 22, 94, 184, 137, 145, + 249, 211, 7, 88, 138, 154, 123, 158, 155, 224, 196, 236, 199, 197, + 146, 150, 237, 221, 125, 115, 83, 16, 183, 20, 43, 153, 225, 182, + 119, 129, 57, 223, 67, 15, 59, 88, 195, 67, 221, 97, 234, 66, + 3, 183, 227, 135, 131, 234, 34, 174, 217, 69, 92, 58, 178, 145, + 44, 12, 226, 237, 86, 201, 218, 43, 195, 179, 168, 180, 204, 219, + 225, 104, 155, 99, 50, 144, 93, 178, 201, 123, 140, 183, 98, 179, + 31, 245, 26, 129, 170, 142, 40, 193, 220, 54, 16, 0, 102, 28, + 153, 59, 189, 219, 224, 134, 55, 250, 79, 38, 182, 112, 22, 153, + 217, 71, 157, 202, 177, 161, 220, 15, 160, 62, 55, 94, 67, 109, + 169, 197, 49, 225, 241, 209, 240, 32, 174, 177, 17, 51, 143, 132, + 103, 93, 80, 34, 171, 82, 219, 42, 134, 156, 238, 56, 14, 116, + 93, 61, 20, 211, 230, 151, 30, 119, 222, 45, 162, 154, 40, 50, + 252, 159, 53, 233, 125, 36, 187, 211, 226, 223, 158, 99, 110, 53, + 95, 19, 182, 118, 168, 139, 102, 32, 130, 189, 191, 116, 17, 244, + 2, 174, 73, 53, 20, 150, 204, 188, 115, 68, 92, 171, 130, 237, + 221, 77, 182, 13, 92, 65, 57, 50, 103, 160, 192, 250, 167, 154, + 74, 0, 67, 182, 222, 11, 248, 11, 45, 66, 3, 11, 197, 160, + 199, 69, 183, 82, 221, 26, 203, 80, 14, 215, 248, 136, 11, 46, + 123, 20, 160, 88, 150, 128, 54, 194, 227, 2, 69, 62, 51, 136, + 71, 171, 175, 116, 55, 181, 233, 201, 144, 212, 194, 153, 45, 11, + 46, 53, 245, 171, 238, 122, 227, 228, 156, 86, 152, 174, 117, 14, + 179, 172, 150, 181, 84, 191, 4, 167, 99, 82, 99, 230, 214, 24, + 203, 205, 72, 255, 177, 235, 189, 144, 40, 97, 52, 251, 125, 79, + 92, 116, 20, 228, 60, 17, 47, 251, 173, 176, 142, 196, 216, 101, + 82, 127, 170, 126, 34, 37, 38, 126, 138, 156, 29, 154, 11, 213, + 63, 61, 221, 27, 156, 104, 55, 152, 196, 28, 34, 99, 168, 254, + 244, 207, 14, 77, 98, 219, 41, 162, 102, 54, 80, 13, 19, 42, + 242, 97, 53, 84, 178, 176, 113, 10, 126, 12, 4, 132, 119, 237, + 176, 123, 163, 247, 164, 34, 158, 251, 17, 194, 153, 111, 187, 41, + 255, 57, 55, 112, 161, 103, 108, 33, 147, 110, 226, 181, 223, 92, + 175, 56, 189, 225, 144, 250, 208, 8, 156, 203, 158, 176, 237, 228, + 225, 61, 219, 190, 191, 1, 24, 136, 196, 217, 242, 21, 198, 14, + 201, 64, 120, 92, 209, 21, 105, 164, 110, 190, 42, 246, 119, 252, + 107, 166, 30, 204, 150, 197, 212, 12, 195, 253, 81, 207, 117, 229, + 214, 9, 39, 30, 10, 3, 21, 6, 40, 59, 152, 92, 154, 178, + 99, 253, 69, 174, 238, 101, 163, 23, 74, 5, 217, 72, 54, 99, + 33, 103, 49, 210, 168, 129, 216, 94, 254, 173, 181, 34, 40, 89, + 71, 17, 129, 230, 158, 31, 227, 187, 61, 32, 252, 201, 151, 94, + 97, 87, 109, 118, 183, 254, 94, 139, 255, 67, 41, 229, 190, 48, + 250, 110, 11, 60, 204, 13, 75, 237, 217, 32, 50, 38, 4, 134, + 58, 58, 4, 200, 114, 83, 153, 227, 104, 250, 81, 5, 215, 122, + 61, 185, 185, 104, 51, 40, 133, 97, 43, 225, 180, 86, 117, 125, + 109, 91, 155, 71, 97, 128, 180, 116, 87, 232, 247, 202, 62, 237, + 75, 0, 4, 162, 202, 237, 165, 145, 83, 196, 215, 196, 38, 240, + 83, 161, 8, 207, 151, 110, 69, 185, 136, 251, 155, 123, 255, 181, + 119, 98, 90, 147, 20, 40, 33, 183, 251, 215, 21, 169, 164, 5, + 167, 150, 250, 185, 182, 95, 170, 212, 252, 241, 80, 65, 225, 93, + 57, 27, 244, 143, 84, 100, 112, 247, 103, 53, 107, 116, 23, 89, + 195, 241, 14, 215, 73, 40, 94, 29, 6, 18, 170, 8, 180, 195, + 137, 204, 80, 110, 191, 238, 231, 214, 170, 230, 234, 165, 175, 104, + 209, 136, 72, 118, 255, 53, 17, 248, 243, 26, 255, 191, 225, 140, + 86, 6, 39, 144, 146, 174, 157, 31, 60, 225, 158, 44, 245, 239, + 135, 134, 147, 120, 133, 139, 167, 0, 58, 91, 246, 147, 243, 27, + 68, 83, 49, 240, 238, 172, 61, 20, 29, 52, 48, 10, 183, 160, + 164, 36, 177, 117, 183, 245, 200, 244, 35, 126, 24, 129, 169, 12, + 171, 220, 180, 104, 68, 93, 76, 65, 134, 251, 42, 111, 243, 114, + 202, 11, 98, 109, 10, 92, 177, 36, 86, 233, 250, 32, 89, 236, + 37, 149, 99, 173, 28, 14, 151, 51, 43, 210, 1, 198, 158, 194, + 40, 3, 5, 205, 213, 176, 215, 72, 63, 10, 155, 244, 44, 79, + 67, 200, 162, 180, 58, 119, 211, 138, 19, 203, 238, 204, 167, 18, + 246, 52, 48, 251, 57, 188, 192, 160, 248, 94, 35, 139, 222, 95, + 177, 198, 179, 73, 89, 178, 218, 195, 223, 157, 4, 254, 147, 249, + 251, 83, 61, 99, 28, 203, 65, 228, 213, 198, 97, 231, 120, 141, + 58, 107, 252, 127, 162, 164, 224, 23, 19, 49, 81, 148, 219, 255, + 24, 80, 160, 174, 88, 68, 231, 106, 100, 178, 178, 45, 74, 155, + 195, 168, 80, 61, 194, 180, 254, 236, 199, 248, 246, 63, 41, 59, + 71, 134, 106, 196, 233, 13, 160, 29, 230, 122, 215, 84, 46, 175, + 203, 66, 27, 180, 34, 146, 9, 255, 143, 243, 148, 147, 177, 159, + 53, 127, 47, 84, 202, 236, 107, 235, 61, 106, 103, 142, 58, 49, + 83, 249, 218, 13, 207, 32, 160, 199, 128, 116, 240, 159, 6, 128, + 145, 51, 172, 233, 2, 22, 105, 217, 19, 173, 209, 145, 148, 18, + 165, 225, 128, 59, 114, 150, 162, 243, 233, 246, 189, 149, 155, 144, + 57, 34, 171, 64, 29, 224, 95, 222, 162, 11, 237, 37, 35, 162, + 164, 30, 244, 128, 122, 144, 62, 23, 17, 242, 166, 116, 11, 48, + 133, 185, 36, 43, 240, 186, 86, 49, 94, 72, 162, 205, 108, 37, + 88, 172, 35, 128, 8, 224, 64, 237, 156, 15, 156, 249, 19, 204, + 128, 22, 236, 21, 122, 247, 180, 93, 228, 198, 117, 118, 227, 212, + 233, 198, 9, 75, 49, 122, 196, 225, 138, 194, 124, 244, 232, 162, + 0, 107, 124, 243, 136, 118, 3, 200, 187, 236, 45, 75, 67, 198, + 240, 137, 91, 1, 104, 20, 89, 219, 50, 161, 121, 97, 81, 125, + 111, 138, 108, 136, 94, 161, 75, 158, 38, 146, 3, 150, 213, 189, + 87, 210, 54, 57, 177, 35, 208, 67, 88, 61, 67, 46, 137, 83, + 16, 145, 130, 22, 141, 99, 132, 249, 136, 124, 144, 213, 165, 120, + 50, 42, 212, 43, 239, 177, 103, 14, 177, 215, 60, 156, 51, 152, + 165, 253, 253, 192, 220, 225, 233, 18, 220, 52, 165, 89, 245, 217, + 167, 138, 246, 154, 240, 198, 241, 148, 134, 63, 153, 52, 82, 7, + 107, 120, 10, 89, 102, 28, 72, 183, 201, 61, 124, 57, 200, 66, + 63, 163, 246, 248, 105, 58, 154, 221, 9, 63, 54, 158, 157, 123, + 183, 180, 98, 81, 196, 16, 85, 137, 1, 36, 108, 183, 101, 105, + 214, 245, 177, 108, 167, 47, 16, 202, 158, 104, 93, 160, 247, 76, + 28, 67, 164, 68, 33, 91, 88, 41, 107, 122, 221, 198, 91, 145, + 232, 188, 208, 105, 172, 254, 207, 249, 199, 50, 201, 170, 172, 137, + 98, 233, 153, 201, 174, 97, 63, 176, 202, 98, 239, 46, 159, 215, + 94, 20, 10, 165, 152, 99, 67, 171, 21, 125, 2, 154, 195, 75, + 70, 70, 168, 168, 89, 213, 227, 127, 195, 20, 3, 124, 126, 19, + 243, 60, 9, 150, 17, 42, 131, 94, 130, 229, 43, 16, 24, 227, + 143, 4, 70, 146, 76, 134, 244, 214, 48, 178, 139, 27, 57, 55, + 183, 94, 7, 16, 226, 147, 145, 110, 185, 147, 134, 197, 35, 215, + 244, 110, 34, 213, 193, 186, 108, 238, 157, 65, 122, 203, 169, 85, + 138, 242, 209, 216, 61, 230, 128, 174, 120, 45, 110, 22, 181, 1, + 38, 205, 184, 215, 147, 116, 251, 135, 106, 215, 150, 135, 189, 67, + 240, 210, 151, 168, 221, 183, 91, 66, 205, 166, 97, 68, 248, 54, + 248, 236, 19, 67, 20, 206, 86, 222, 108, 245, 116, 94, 184, 119, + 253, 233, 23, 55, 105, 237, 193, 41, 114, 203, 144, 33, 109, 20, + 171, 254, 199, 97, 45, 18, 88, 254, 173, 19, 236, 237, 247, 4, + 10, 83, 199, 161, 144, 176, 55, 193, 112, 227, 127, 78, 219, 123, + 19, 91, 223, 136, 114, 110, 110, 151, 217, 152, 223, 21, 227, 65, + 122, 79, 22, 48, 174, 248, 86, 200, 67, 159, 184, 185, 73, 134, + 217, 112, 75, 207, 35, 41, 72, 55, 197, 30, 8, 18, 82, 187, + 4, 155, 112, 95, 132, 2, 179, 25, 4, 116, 54, 154, 125, 144, + 250, 89, 201, 24, 172, 218, 136, 199, 239, 26, 151, 255, 112, 249, + 30, 12, 248, 10, 162, 116, 47, 79, 127, 195, 32, 151, 208, 28, + 195, 127, 100, 196, 225, 242, 46, 232, 52, 49, 8, 179, 96, 158, + 106, 232, 227, 160, 165, 191, 99, 70, 165, 128, 64, 120, 125, 121, + 64, 214, 218, 8, 241, 242, 2, 159, 104, 41, 166, 181, 93, 202, + 162, 187, 11, 180, 239, 179, 58, 195, 166, 210, 55, 15, 70, 57, + 238, 111, 13, 58, 53, 122, 200, 51, 240, 95, 135, 45, 207, 4, + 70, 175, 124, 3, 64, 235, 192, 18, 37, 13, 203, 217, 247, 224, + 211, 99, 199, 41, 105, 132, 162, 152, 253, 76, 144, 204, 164, 74, + 54, 81, 252, 215, 34, 65, 219, 65, 232, 164, 71, 179, 161, 12, + 229, 51, 116, 10, 120, 142, 76, 11, 246, 86, 17, 239, 171, 182, + 81, 124, 129, 239, 189, 85, 124, 41, 255, 247, 119, 203, 124, 59, + 224, 93, 12, 85, 140, 176, 113, 118, 47, 75, 113, 134, 44, 4, + 56, 177, 31, 217, 123, 127, 142, 130, 134, 108, 98, 32, 50, 29, + 206, 188, 81, 163, 155, 213, 147, 162, 183, 162, 26, 206, 34, 72, + 215, 43, 89, 226, 5, 77, 14, 96, 121, 133, 13, 200, 90, 39, + 128, 191, 90, 118, 213, 87, 227, 163, 196, 253, 52, 175, 218, 241, + 191, 5, 90, 82, 64, 88, 148, 11, 8, 163, 100, 151, 76, 151, + 43, 165, 7, 252, 251, 161, 129, 122, 241, 51, 127, 52, 140, 83, + 30, 15, 61, 46, 182, 158, 171, 38, 198, 223, 142, 172, 49, 147, + 36, 106, 41, 32, 193, 115, 232, 5, 11, 39, 24, 166, 174, 122, + 197, 60, 171, 238, 167, 183, 252, 116, 192, 118, 240, 117, 121, 111, + 2, 132, 1, 94, 164, 89, 52, 57, 79, 254, 172, 7, 166, 1, + 191, 237, 164, 241, 118, 219, 145, 84, 114, 118, 47, 155, 213, 62, + 110, 11, 92, 216, 117, 200, 102, 92, 221, 219, 75, 165, 182, 39, + 39, 67, 132, 148, 38, 138, 175, 169, 249, 73, 205, 24, 211, 111, + 6, 195, 239, 24, 95, 161, 50, 231, 3, 39, 34, 3, 194, 26, + 57, 182, 134, 248, 65, 99, 235, 29, 14, 111, 199, 141, 68, 198, + 6, 168, 233, 148, 29, 236, 182, 63, 117, 182, 7, 83, 126, 65, + 39, 91, 88, 139, 186, 121, 174, 53, 145, 73, 89, 17, 37, 142, + 198, 73, 86, 95, 178, 12, 158, 0, 49, 66, 43, 229, 74, 45, + 96, 96, 203, 117, 191, 23, 25, 107, 66, 137, 51, 236, 9, 151, + 67, 172, 224, 28, 207, 42, 25, 166, 187, 237, 238, 194, 221, 73, + 241, 136, 176, 147, 33, 169, 4, 236, 37, 61, 187, 67, 15, 153, + 150, 235, 230, 113, 2, 130, 133, 169, 186, 66, 84, 25, 95, 44, + 236, 160, 26, 91, 56, 99, 59, 6, 236, 75, 51, 144, 120, 89, + 24, 241, 166, 1, 37, 211, 116, 11, 66, 149, 118, 140, 244, 248, + 186, 157, 247, 74, 155, 150, 61, 132, 106, 59, 235, 108, 164, 180, + 122, 34, 29, 143, 68, 65, 51, 230, 108, 31, 99, 39, 228, 180, + 61, 15, 81, 225, 159, 244, 40, 118, 85, 172, 96, 26, 184, 227, + 122, 242, 68, 243, 228, 59, 36, 114, 110, 48, 241, 191, 117, 140, + 238, 58, 83, 168, 218, 130, 115, 186, 179, 214, 213, 220, 137, 18, + 71, 209, 201, 157, 29, 40, 31, 94, 138, 152, 81, 165, 81, 181, + 177, 243, 178, 121, 42, 172, 140, 186, 191, 4, 42, 106, 21, 72, + 131, 10, 59, 21, 129, 103, 40, 108, 83, 80, 150, 135, 52, 2, + 94, 206, 230, 28, 221, 97, 191, 162, 24, 91, 73, 162, 203, 237, + 25, 56, 133, 22, 102, 77, 143, 234, 196, 245, 122, 236, 99, 145, + 104, 252, 84, 92, 154, 173, 62, 183, 15, 25, 63, 5, 184, 227, + 160, 101, 187, 63, 203, 250, 214, 88, 3, 233, 25, 168, 102, 123, + 101, 51, 152, 7, 244, 40, 25, 213, 43, 71, 220, 204, 80, 159, + 221, 21, 41, 3, 212, 187, 127, 145, 255, 227, 77, 178, 83, 172, + 158, 160, 113, 9, 86, 135, 137, 163, 226, 178, 149, 83, 103, 166, + 56, 30, 19, 60, 253, 233, 244, 164, 50, 207, 115, 114, 209, 166, + 25, 85, 211, 104, 214, 154, 2, 151, 35, 157, 179, 193, 209, 175, + 8, 42, 136, 42, 198, 103, 58, 125, 7, 34, 72, 110, 116, 170, + 6, 200, 211, 143, 172, 82, 124, 171, 48, 19, 116, 168, 84, 3, + 142, 145, 49, 36, 136, 162, 206, 96, 246, 173, 178, 53, 172, 128, + 144, 241, 238, 79, 95, 222, 155, 252, 145, 205, 75, 60, 101, 66, + 204, 9, 47, 4, 202, 247, 121, 131, 152, 150, 189, 17, 92, 23, + 253, 5, 102, 252, 18, 222, 57, 212, 86, 119, 40, 94, 218, 236, + 80, 226, 100, 177, 79, 206, 93, 251, 225, 202, 218, 58, 54, 201, + 160, 221, 63, 53, 245, 238, 178, 96, 224, 90, 20, 232, 211, 129, + 59, 104, 158, 143, 187, 129, 95, 86, 248, 228, 94, 48, 140, 222, + 19, 240, 249, 103, 27, 46, 126, 203, 146, 62, 189, 38, 65, 6, + 77, 6, 159, 18, 105, 54, 251, 24, 30, 167, 240, 130, 77, 173, + 94, 164, 236, 190, 183, 149, 152, 1, 37, 205, 90, 32, 60, 189, + 79, 165, 49, 21, 145, 163, 37, 0, 71, 15, 148, 177, 60, 76, + 165, 162, 57, 12, 243, 149, 151, 189, 38, 104, 1, 203, 41, 253, + 131, 93, 141, 90, 254, 5, 13, 198, 119, 117, 150, 56, 27, 136, + 67, 14, 132, 112, 162, 215, 19, 126, 85, 116, 94, 195, 248, 125, + 230, 124, 88, 216, 19, 199, 145, 55, 7, 82, 116, 1, 210, 227, + 104, 2, 23, 26, 8, 234, 243, 138, 5, 134, 121, 157, 10, 27, + 195, 59, 198, 81, 192, 241, 45, 198, 207, 111, 138, 68, 127, 48, + 236, 27, 1, 84, 123, 210, 108, 36, 175, 164, 100, 37, 115, 241, + 173, 216, 113, 116, 12, 196, 181, 120, 150, 42, 145, 52, 198, 103, + 210, 218, 67, 198, 141, 244, 216, 70, 27, 55, 142, 5, 243, 203, + 28, 150, 168, 40, 32, 82, 244, 64, 188, 97, 73, 129, 206, 133, + 91, 185, 239, 116, 19, 42, 240, 137, 51, 174, 97, 130, 244, 49, + 33, 137, 78, 219, 246, 78, 132, 20, 101, 184, 167, 71, 139, 254, + 173, 2, 253, 168, 34, 214, 196, 28, 44, 76, 228, 164, 251, 187, + 134, 84, 229, 149, 103, 88, 86, 147, 10, 126, 58, 163, 201, 24, + 104, 72, 170, 83, 220, 205, 244, 239, 247, 125, 205, 169, 160, 193, + 136, 5, 15, 79, 122, 40, 144, 166, 52, 58, 41, 104, 238, 154, + 135, 129, 43, 143, 189, 189, 98, 152, 51, 79, 15, 230, 52, 72, + 120, 208, 255, 219, 24, 199, 165, 163, 71, 46, 77, 82, 6, 85, + 11, 4, 23, 38, 70, 60, 6, 139, 5, 141, 72, 53, 26, 78, + 7, 209, 205, 237, 181, 214, 247, 171, 238, 116, 167, 22, 25, 51, + 72, 208, 197, 50, 242, 223, 87, 211, 113, 224, 74, 144, 77, 124, + 204, 223, 75, 232, 242, 76, 247, 231, 167, 18, 116, 83, 139, 52, + 159, 217, 240, 10, 5, 141, 131, 226, 97, 34, 139, 153, 180, 105, + 27, 26, 56, 5, 41, 49, 243, 92, 162, 127, 116, 137, 63, 54, + 15, 210, 214, 19, 255, 139, 233, 52, 165, 103, 178, 211, 200, 134, + 67, 52, 109, 16, 93, 7, 227, 79, 26, 200, 10, 189, 69, 97, + 152, 198, 52, 69, 81, 107, 183, 116, 199, 213, 125, 33, 83, 114, + 129, 200, 90, 43, 40, 15, 43, 246, 139, 210, 53, 55, 63, 51, + 129, 224, 252, 7, 248, 137, 206, 255, 82, 42, 19, 64, 150, 131, + 79, 96, 111, 108, 140, 99, 200, 97, 157, 45, 200, 194, 217, 32, + 255, 214, 245, 233, 213, 104, 205, 51, 102, 140, 151, 109, 238, 228, + 170, 10, 209, 21, 163, 134, 114, 58, 192, 108, 1, 23, 184, 83, + 73, 198, 187, 186, 214, 159, 212, 57, 89, 111, 22, 177, 84, 58, + 146, 13, 167, 181, 222, 207, 30, 85, 168, 157, 112, 104, 217, 129, + 29, 205, 216, 178, 240, 74, 159, 100, 104, 53, 193, 217, 190, 67, + 61, 205, 167, 137, 111, 208, 74, 237, 140, 25, 135, 90, 108, 175, + 32, 84, 250, 91, 4, 248, 35, 47, 175, 210, 222, 118, 98, 234, + 29, 95, 222, 11, 143, 245, 101, 125, 132, 77, 192, 122, 28, 124, + 82, 33, 89, 175, 95, 189, 150, 106, 122, 33, 252, 204, 121, 146, + 53, 233, 221, 155, 212, 182, 127, 180, 215, 189, 73, 145, 19, 64, + 243, 60, 66, 110, 98, 245, 88, 172, 165, 40, 58, 164, 33, 16, + 93, 248, 152, 48, 46, 161, 35, 245, 207, 92, 253, 0, 101, 41, + 140, 199, 173, 140, 45, 184, 221, 40, 236, 189, 78, 186, 34, 36, + 133, 22, 195, 224, 229, 58, 148, 87, 97, 44, 220, 234, 32, 182, + 63, 30, 126, 203, 59, 28, 243, 249, 61, 3, 131, 16, 103, 69, + 161, 26, 106, 176, 220, 226, 30, 150, 233, 164, 140, 245, 65, 14, + 85, 16, 156, 207, 48, 237, 44, 131, 73, 228, 244, 192, 243, 136, + 18, 199, 21, 201, 162, 17, 251, 142, 121, 187, 190, 186, 41, 238, + 151, 222, 217, 71, 4, 107, 179, 59, 122, 160, 143, 127, 161, 109, + 52, 163, 163, 120, 140, 96, 214, 26, 188, 165, 149, 85, 239, 18, + 105, 88, 130, 19, 120, 60, 202, 227, 113, 33, 44, 50, 169, 141, + 26, 224, 115, 168, 36, 162, 138, 160, 194, 5, 48, 196, 186, 129, + 231, 90, 209, 163, 97, 255, 148, 73, 100, 66, 39, 64, 23, 35, + 31, 44, 34, 42, 150, 153, 69, 53, 253, 62, 64, 201, 156, 115, + 220, 129, 216, 173, 235, 82, 233, 169, 205, 37, 45, 124, 160, 111, + 195, 139, 227, 198, 116, 30, 137, 184, 230, 59, 209, 184, 67, 107, + 157, 105, 219, 54, 171, 26, 161, 242, 88, 4, 113, 88, 182, 236, + 167, 107, 230, 66, 48, 119, 233, 120, 122, 93, 67, 134, 107, 155, + 159, 185, 140, 53, 100, 149, 46, 190, 192, 42, 179, 96, 15, 55, + 56, 109, 77, 24, 192, 166, 18, 30, 140, 232, 218, 55, 88, 244, + 140, 4, 237, 19, 142, 20, 156, 189, 173, 180, 123, 241, 204, 13, + 78, 64, 110, 174, 51, 151, 169, 195, 160, 159, 34, 104, 194, 14, + 179, 243, 206, 15, 150, 126, 234, 94, 187, 18, 75, 69, 143, 115, + 10, 180, 90, 162, 115, 21, 50, 21, 231, 3, 255, 110, 143, 20, + 237, 204, 199, 117, 73, 199, 226, 3, 13, 178, 50, 253, 154, 230, + 0, 140, 42, 18, 78, 182, 241, 100, 97, 3, 103, 131, 29, 162, + 97, 20, 36, 129, 79, 43, 207, 8, 62, 198, 49, 201, 92, 3, + 37, 35, 40, 186, 11, 150, 6, 200, 205, 95, 30, 126, 63, 107, + 103, 126, 230, 166, 171, 99, 216, 244, 184, 121, 223, 200, 159, 101, + 164, 29, 232, 68, 91, 123, 183, 231, 179, 70, 105, 226, 221, 152, + 134, 98, 5, 224, 123, 185, 40, 248, 64, 99, 115, 64, 21, 244, + 228, 107, 183, 233, 1, 192, 0, 101, 42, 203, 24, 12, 166, 107, + 117, 138, 33, 140, 149, 158, 214, 200, 216, 136, 127, 162, 5, 128, + 86, 63, 150, 114, 147, 62, 167, 194, 139, 49, 66, 2, 154, 43, + 119, 228, 100, 65, 248, 252, 78, 146, 190, 62, 233, 47, 220, 171, + 0, 233, 187, 181, 74, 40, 51, 72, 35, 162, 115, 71, 67, 29, + 36, 83, 81, 75, 219, 124, 202, 142, 235, 5, 1, 253, 181, 25, + 115, 155, 21, 88, 250, 28, 153, 202, 139, 83, 164, 72, 84, 207, + 159, 196, 190, 210, 227, 205, 177, 174, 172, 102, 44, 127, 237, 126, + 202, 206, 201, 253, 158, 226, 200, 141, 13, 114, 71, 43, 47, 206, + 23, 2, 17, 70, 159, 117, 134, 82, 173, 36, 88, 42, 135, 171, + 94, 232, 114, 143, 170, 247, 58, 198, 202, 211, 121, 230, 188, 199, + 93, 79, 129, 187, 242, 140, 225, 228, 171, 156, 245, 13, 37, 172, + 242, 213, 140, 107, 137, 156, 24, 17, 77, 41, 82, 208, 90, 90, + 188, 133, 116, 223, 211, 136, 251, 70, 245, 162, 23, 128, 1, 248, + 79, 58, 69, 218, 249, 91, 162, 150, 40, 154, 255, 42, 52, 154, + 112, 124, 78, 87, 87, 215, 59, 44, 239, 110, 122, 67, 76, 216, + 16, 98, 118, 118, 58, 149, 67, 248, 138, 128, 43, 40, 233, 126, + 59, 30, 9, 165, 52, 65, 108, 194, 210, 130, 163, 46, 134, 185, + 168, 147, 222, 232, 15, 214, 74, 205, 88, 146, 155, 181, 187, 143, + 70, 97, 233, 104, 113, 179, 143, 14, 240, 234, 153, 240, 175, 236, + 206, 187, 32, 241, 163, 168, 122, 115, 2, 6, 28, 209, 109, 227, + 66, 1, 133, 137, 166, 192, 232, 124, 21, 56, 41, 68, 117, 26, + 102, 170, 164, 139, 0, 10, 172, 56, 220, 104, 161, 124, 26, 38, + 221, 40, 77, 27, 79, 228, 211, 164, 181, 49, 22, 249, 76, 110, + 12, 24, 92, 55, 88, 141, 4, 71, 243, 198, 224, 190, 183, 210, + 25, 87, 110, 143, 199, 98, 70, 40, 56, 14, 131, 148, 62, 191, + 190, 241, 139, 70, 15, 244, 80, 168, 160, 205, 115, 47, 62, 227, + 39, 4, 161, 233, 31, 75, 39, 224, 141, 35, 255, 232, 247, 199, + 211, 37, 190, 132, 66, 169, 36, 107, 242, 50, 142, 91, 193, 5, + 110, 237, 46, 36, 226, 194, 95, 136, 170, 179, 150, 138, 187, 199, + 108, 112, 242, 222, 51, 7, 159, 120, 0, 99, 170, 112, 100, 17, + 131, 234, 23, 145, 62, 35, 191, 25, 206, 5, 157, 208, 244, 74, + 139, 197, 17, 46, 132, 64, 154, 28, 235, 252, 248, 120, 14, 121, + 214, 216, 84, 187, 73, 201, 37, 38, 220, 242, 94, 220, 35, 39, + 151, 18, 168, 156, 192, 3, 55, 222, 250, 96, 155, 246, 58, 25, + 237, 135, 170, 111, 144, 113, 251, 116, 115, 37, 168, 206, 51, 222, + 255, 31, 255, 28, 73, 197, 232, 77, 19, 153, 139, 166, 145, 124, + 72, 191, 238, 75, 82, 44, 172, 151, 94, 170, 112, 99, 249, 231, + 7, 71, 71, 45, 244, 102, 239, 59, 54, 233, 116, 61, 0, 222, + 221, 113, 10, 18, 56, 125, 201, 16, 108, 95, 156, 212, 229, 130, + 32, 228, 82, 203, 127, 145, 236, 231, 223, 168, 165, 243, 171, 157, + 140, 106, 255, 135, 150, 98, 20, 247, 69, 228, 219, 101, 72, 46, + 23, 175, 188, 66, 166, 193, 56, 245, 160, 137, 247, 153, 58, 51, + 139, 6, 54, 231, 147, 51, 2, 210, 102, 78, 24, 228, 30, 229, + 180, 88, 158, 7, 166, 190, 250, 96, 76, 46, 133, 127, 141, 82, + 67, 250, 188, 186, 41, 137, 150, 32, 115, 206, 48, 120, 58, 111, + 62, 188, 225, 178, 24, 54, 74, 208, 91, 189, 9, 159, 43, 53, + 132, 42, 242, 16, 81, 227, 186, 93, 170, 136, 223, 127, 195, 52, + 125, 109, 192, 35, 231, 78, 251, 160, 220, 254, 140, 53, 111, 64, + 6, 228, 246, 184, 74, 207, 15, 117, 217, 190, 110, 1, 116, 135, + 200, 112, 156, 182, 208, 154, 239, 202, 200, 88, 193, 196, 43, 196, + 213, 139, 101, 88, 253, 220, 120, 59, 170, 205, 134, 249, 98, 201, + 1, 186, 123, 7, 233, 38, 52, 71, 209, 10, 129, 223, 46, 201, + 225, 123, 140, 152, 43, 131, 149, 177, 77, 245, 146, 124, 164, 159, + 16, 51, 189, 139, 75, 40, 199, 111, 178, 38, 196, 97, 48, 59, + 101, 90, 200, 90, 28, 146, 19, 23, 27, 113, 15, 139, 68, 12, + 150, 142, 161, 22, 58, 9, 231, 77, 23, 192, 94, 10, 149, 86, + 121, 60, 224, 37, 219, 22, 93, 101, 244, 165, 143, 200, 180, 177, + 175, 241, 157, 65, 107, 50, 87, 14, 84, 60, 130, 102, 221, 58, + 91, 180, 59, 217, 38, 238, 91, 25, 136, 111, 247, 117, 75, 161, + 100, 207, 199, 167, 209, 134, 104, 83, 64, 56, 48, 99, 152, 202, + 107, 102, 161, 139, 113, 225, 72, 107, 50, 158, 120, 90, 129, 19, + 5, 94, 136, 234, 56, 9, 27, 21, 62, 11, 89, 234, 105, 112, + 108, 33, 192, 216, 218, 192, 46, 152, 134, 65, 127, 115, 201, 212, + 190, 50, 6, 79, 76, 88, 9, 246, 160, 238, 237, 91, 225, 32, + 177, 179, 242, 249, 176, 82, 33, 70, 140, 149, 111, 63, 143, 187, + 148, 139, 140, 116, 168, 219, 159, 73, 152, 4, 56, 182, 97, 93, + 35, 163, 52, 152, 86, 243, 114, 203, 156, 250, 247, 218, 60, 26, + 229, 140, 154, 38, 193, 0, 33, 42, 248, 54, 201, 147, 102, 58, + 23, 242, 26, 252, 108, 9, 186, 220, 117, 24, 228, 191, 173, 41, + 56, 26, 196, 195, 121, 31, 165, 114, 252, 34, 169, 73, 54, 78, + 9, 252, 181, 27, 122, 209, 189, 210, 4, 134, 233, 44, 230, 49, + 224, 7, 208, 197, 33, 252, 126, 40, 104, 153, 242, 118, 222, 151, + 68, 43, 201, 134, 137, 208, 183, 142, 188, 234, 32, 46, 75, 113, + 157, 55, 159, 36, 84, 49, 94, 194, 16, 132, 79, 140, 56, 176, + 99, 22, 131, 93, 16, 32, 113, 249, 211, 66, 58, 102, 70, 187, + 178, 156, 59, 71, 233, 181, 47, 25, 161, 156, 17, 0, 76, 216, + 234, 134, 96, 239, 129, 81, 68, 252, 135, 152, 210, 182, 226, 118, + 124, 41, 166, 54, 151, 14, 236, 63, 71, 214, 198, 240, 97, 113, + 178, 51, 159, 147, 226, 7, 177, 138, 126, 50, 144, 53, 93, 93, + 162, 43, 19, 97, 197, 237, 130, 148, 119, 158, 254, 253, 83, 3, + 34, 209, 114, 167, 151, 237, 23, 75, 41, 196, 169, 222, 109, 112, + 66, 202, 147, 85, 124, 99, 40, 19, 155, 212, 221, 126, 134, 112, + 18, 107, 87, 105, 196, 13, 83, 44, 211, 144, 20, 77, 56, 196, + 80, 8, 69, 173, 187, 131, 145, 196, 84, 55, 104, 185, 102, 175, + 166, 154, 9, 111, 125, 134, 41, 204, 58, 30, 92, 187, 236, 81, + 234, 139, 173, 34, 111, 191, 120, 218, 75, 221, 24, 95, 165, 192, + 127, 6, 35, 241, 210, 212, 77, 109, 126, 232, 132, 245, 167, 176, + 139, 4, 18, 118, 62, 65, 38, 180, 221, 16, 81, 201, 137, 249, + 186, 186, 5, 14, 76, 86, 78, 211, 112, 190, 135, 61, 30, 207, + 111, 124, 194, 49, 81, 254, 224, 165, 27, 116, 240, 233, 72, 143, + 174, 67, 192, 71, 6, 137, 125, 117, 246, 241, 247, 160, 166, 137, + 127, 142, 228, 162, 162, 121, 52, 131, 232, 182, 147, 51, 7, 27, + 167, 170, 198, 82, 214, 94, 235, 176, 6, 117, 24, 213, 48, 103, + 132, 212, 189, 41, 230, 35, 160, 223, 240, 240, 78, 104, 76, 135, + 118, 55, 173, 125, 160, 64, 38, 100, 253, 8, 111, 82, 215, 147, + 213, 239, 36, 91, 254, 206, 236, 79, 207, 24, 73, 134, 210, 223, + 197, 198, 197, 114, 144, 120, 118, 60, 8, 171, 4, 58, 14, 255, + 10, 224, 164, 133, 135, 193, 94, 104, 255, 57, 100, 100, 127, 99, + 180, 80, 126, 19, 5, 148, 49, 74, 155, 151, 189, 10, 16, 56, + 244, 140, 62, 145, 89, 124, 6, 150, 131, 170, 25, 128, 195, 102, + 27, 129, 207, 90, 179, 21, 9, 120, 15, 156, 9, 3, 84, 209, + 153, 3, 119, 152, 86, 98, 59, 131, 99, 62, 55, 108, 215, 180, + 228, 40, 89, 235, 83, 176, 153, 232, 109, 134, 245, 167, 122, 102, + 27, 65, 219, 91, 241, 126, 67, 201, 56, 111, 129, 24, 140, 40, + 93, 133, 102, 75, 8, 131, 33, 223, 68, 64, 26, 18, 166, 21, + 177, 253, 66, 82, 219, 125, 158, 201, 33, 32, 126, 215, 64, 115, + 27, 85, 11, 199, 206, 162, 49, 226, 126, 60, 3, 6, 168, 33, + 231, 220, 40, 20, 183, 159, 213, 63, 65, 148, 117, 138, 174, 13, + 182, 138, 7, 222, 247, 192, 25, 149, 123, 56, 167, 129, 102, 51, + 208, 183, 158, 21, 242, 80, 164, 37, 37, 214, 201, 150, 151, 206, + 229, 55, 156, 94, 54, 70, 222, 107, 237, 1, 151, 217, 78, 5, + 105, 30, 129, 148, 76, 87, 153, 170, 120, 217, 22, 54, 148, 64, + 108, 13, 58, 118, 45, 222, 45, 172, 91, 68, 9, 208, 163, 152, + 43, 31, 225, 82, 62, 182, 149, 231, 218, 164, 185, 85, 147, 10, + 187, 65, 229, 27, 249, 52, 212, 80, 100, 8, 70, 179, 228, 192, + 8, 108, 34, 133, 170, 129, 217, 176, 214, 14, 147, 20, 35, 161, + 203, 230, 13, 60, 217, 159, 154, 31, 20, 249, 198, 193, 234, 128, + 207, 194, 87, 236, 91, 107, 222, 96, 62, 110, 144, 98, 201, 93, + 151, 230, 58, 112, 8, 17, 56, 202, 144, 236, 165, 120, 76, 254, + 220, 143, 65, 228, 78, 96, 131, 27, 33, 164, 139, 200, 201, 6, + 145, 233, 232, 230, 185, 195, 187, 25, 43, 83, 132, 249, 249, 82, + 69, 75, 93, 98, 102, 21, 71, 81, 228, 206, 132, 215, 182, 26, + 152, 253, 246, 181, 94, 91, 27, 17, 127, 78, 63, 12, 31, 214, + 192, 21, 141, 54, 14, 8, 245, 45, 140, 78, 17, 233, 31, 40, + 175, 117, 131, 148, 44, 111, 112, 242, 169, 74, 162, 138, 229, 3, + 82, 139, 99, 42, 174, 138, 139, 253, 187, 158, 240, 217, 188, 194, + 228, 14, 4, 97, 184, 37, 64, 190, 192, 244, 215, 244, 143, 201, + 75, 153, 82, 202, 45, 163, 225, 24, 194, 2, 145, 36, 234, 187, + 117, 245, 153, 187, 243, 241, 231, 193, 164, 51, 239, 58, 44, 21, + 219, 84, 228, 229, 100, 236, 133, 16, 188, 239, 45, 68, 15, 187, + 62, 250, 64, 71, 187, 174, 166, 169, 38, 72, 225, 42, 183, 35, + 221, 203, 137, 245, 127, 25, 0, 17, 127, 52, 243, 224, 5, 202, + 228, 168, 14, 219, 132, 5, 211, 80, 140, 206, 0, 74, 81, 156, + 47, 245, 187, 139, 36, 18, 93, 58, 97, 245, 75, 70, 209, 222, + 93, 64, 112, 5, 1, 52, 180, 210, 1, 120, 76, 134, 37, 133, + 249, 172, 102, 3, 146, 88, 142, 64, 27, 12, 102, 170, 164, 114, + 199, 97, 221, 60, 203, 154, 202, 0, 128, 173, 79, 8, 53, 88, + 123, 77, 236, 125, 97, 51, 72, 125, 66, 174, 134, 233, 46, 100, + 18, 152, 8, 152, 212, 170, 157, 56, 34, 104, 170, 236, 69, 57, + 2, 220, 74, 134, 159, 79, 195, 9, 138, 8, 5, 224, 129, 90, + 141, 165, 15, 120, 203, 235, 81, 72, 158, 164, 206, 123, 85, 117, + 86, 199, 217, 20, 91, 201, 177, 67, 92, 127, 146, 34, 250, 106, + 166, 29, 198, 114, 155, 233, 236, 159, 229, 219, 146, 226, 207, 136, + 128, 169, 209, 177, 228, 62, 53, 222, 28, 189, 132, 209, 212, 38, + 181, 177, 78, 140, 96, 77, 222, 251, 0, 37, 159, 184, 105, 196, + 200, 169, 161, 162, 150, 158, 93, 243, 97, 40, 107, 141, 92, 213, + 79, 59, 104, 215, 212, 12, 77, 69, 75, 230, 40, 65, 228, 103, + 104, 132, 195, 182, 54, 182, 161, 138, 39, 146, 76, 197, 133, 40, + 103, 151, 12, 1, 108, 223, 146, 92, 19, 41, 255, 14, 173, 80, + 211, 224, 57, 89, 155, 163, 84, 115, 157, 196, 26, 4, 48, 240, + 17, 145, 165, 108, 151, 255, 154, 131, 130, 44, 217, 104, 190, 28, + 83, 51, 210, 213, 93, 66, 104, 67, 138, 175, 118, 185, 131, 46, + 254, 177, 26, 193, 240, 80, 19, 209, 211, 243, 155, 36, 67, 188, + 19, 251, 190, 15, 217, 122, 116, 43, 37, 142, 204, 213, 145, 28, + 154, 55, 172, 48, 60, 166, 59, 20, 5, 119, 48, 196, 103, 24, + 152, 196, 76, 109, 242, 50, 160, 185, 80, 186, 254, 83, 147, 215, + 57, 51, 222, 213, 44, 65, 184, 87, 220, 6, 234, 66, 181, 40, + 64, 155, 26, 142, 189, 227, 105, 253, 130, 18, 183, 5, 177, 84, + 134, 168, 138, 182, 118, 167, 216, 226, 108, 143, 124, 182, 196, 196, + 164, 43, 39, 180, 130, 85, 113, 15, 252, 112, 165, 78, 251, 94, + 100, 110, 49, 23, 168, 18, 133, 236, 74, 210, 182, 236, 125, 113, + 151, 80, 219, 60, 147, 47, 6, 128, 0, 2, 121, 136, 92, 51, + 170, 99, 116, 144, 166, 225, 146, 202, 89, 220, 31, 66, 17, 56, + 84, 33, 167, 87, 12, 70, 210, 44, 195, 174, 32, 27, 180, 137, + 219, 27, 109, 75, 186, 241, 98, 175, 201, 49, 110, 100, 12, 73, + 45, 77, 93, 0, 202, 219, 67, 129, 36, 168, 87, 212, 155, 31, + 248, 74, 191, 234, 205, 224, 209, 172, 135, 64, 47, 152, 143, 85, + 127, 161, 79, 129, 38, 210, 121, 146, 64, 162, 146, 36, 12, 121, + 0, 222, 78, 169, 90, 250, 208, 2, 54, 86, 145, 236, 44, 90, + 247, 210, 69, 142, 213, 131, 215, 151, 69, 232, 231, 13, 109, 131, + 86, 243, 122, 192, 196, 17, 180, 194, 91, 18, 131, 28, 12, 190, + 250, 244, 137, 220, 43, 113, 225, 18, 120, 165, 167, 134, 134, 98, + 151, 230, 219, 65, 56, 63, 216, 113, 27, 92, 222, 89, 33, 217, + 5, 142, 56, 83, 56, 30, 206, 118, 48, 66, 180, 83, 10, 40, + 99, 231, 20, 145, 59, 172, 57, 40, 58, 147, 212, 59, 116, 148, + 69, 230, 160, 132, 227, 228, 227, 202, 21, 50, 220, 113, 171, 190, + 39, 253, 196, 5, 171, 104, 157, 94, 236, 181, 156, 50, 36, 238, + 203, 232, 182, 140, 175, 236, 190, 116, 194, 48, 6, 199, 158, 212, + 201, 99, 199, 51, 199, 27, 158, 7, 212, 206, 123, 125, 234, 36, + 207, 224, 74, 191, 240, 211, 16, 150, 53, 77, 60, 158, 26, 17, + 108, 167, 125, 183, 212, 212, 48, 107, 78, 172, 36, 111, 40, 180, + 101, 209, 54, 196, 149, 77, 166, 29, 98, 120, 122, 234, 80, 146, + 101, 119, 43, 24, 186, 124, 221, 24, 232, 199, 131, 0, 224, 247, + 183, 197, 42, 141, 221, 3, 244, 163, 3, 0, 192, 144, 179, 161, + 114, 255, 84, 55, 216, 179, 174, 74, 135, 171, 162, 46, 70, 151, + 135, 233, 13, 253, 119, 126, 111, 83, 102, 252, 32, 186, 180, 106, + 201, 230, 213, 2, 217, 229, 201, 244, 100, 246, 191, 34, 21, 133, + 221, 13, 76, 219, 127, 241, 235, 65, 108, 248, 232, 233, 245, 65, + 225, 183, 71, 10, 246, 242, 85, 186, 88, 24, 126, 70, 239, 229, + 161, 103, 18, 229, 143, 244, 54, 186, 174, 58, 127, 216, 70, 127, + 215, 22, 190, 80, 110, 190, 187, 207, 61, 239, 133, 25, 158, 152, + 234, 182, 53, 137, 54, 56, 206, 79, 61, 196, 233, 105, 178, 81, + 111, 254, 104, 12, 101, 121, 88, 80, 68, 224, 42, 128, 209, 236, + 236, 28, 148, 66, 236, 59, 138, 240, 109, 29, 69, 243, 254, 227, + 3, 20, 163, 27, 81, 79, 59, 64, 214, 199, 42, 202, 40, 178, + 159, 237, 39, 73, 19, 155, 240, 85, 95, 152, 73, 82, 213, 152, + 72, 173, 32, 91, 193, 242, 160, 48, 139, 221, 72, 40, 22, 87, + 4, 103, 112, 180, 145, 27, 97, 197, 71, 205, 50, 109, 114, 95, + 60, 253, 148, 245, 80, 136, 18, 93, 248, 97, 241, 128, 157, 154, + 93, 136, 205, 18, 108, 142, 29, 199, 46, 112, 0, 210, 7, 222, + 123, 140, 39, 84, 75, 25, 30, 196, 238, 156, 169, 23, 142, 12, + 126, 52, 88, 253, 156, 45, 228, 114, 149, 224, 18, 128, 17, 66, + 122, 121, 78, 65, 38, 201, 173, 54, 248, 72, 253, 16, 154, 238, + 159, 154, 142, 127, 67, 162, 247, 39, 173, 137, 254, 110, 66, 233, + 115, 185, 35, 244, 38, 202, 244, 101, 108, 190, 146, 22, 252, 169, + 239, 243, 206, 236, 71, 21, 40, 108, 246, 137, 230, 235, 53, 188, + 25, 251, 125, 127, 174, 145, 49, 192, 92, 229, 62, 38, 113, 243, + 5, 81, 20, 236, 221, 63, 25, 88, 224, 152, 222, 231, 88, 192, + 39, 198, 48, 232, 230, 231, 109, 56, 154, 65, 230, 89, 145, 154, + 155, 76, 233, 37, 140, 134, 222, 189, 63, 6, 60, 61, 46, 156, + 68, 26, 170, 148, 190, 173, 184, 133, 19, 208, 95, 112, 221, 73, + 42, 12, 163, 84, 152, 57, 58, 89, 223, 199, 172, 55, 166, 217, + 228, 159, 213, 222, 60, 144, 89, 163, 16, 74, 186, 107, 188, 255, + 129, 253, 185, 171, 0, 143, 138, 136, 116, 201, 145, 248, 63, 58, + 59, 206, 34, 245, 16, 182, 98, 127, 103, 244, 237, 241, 232, 123, + 204, 104, 152, 86, 204, 101, 153, 184, 245, 173, 36, 51, 36, 16, + 207, 47, 18, 83, 119, 81, 209, 73, 67, 146, 98, 222, 100, 215, + 6, 85, 75, 224, 198, 56, 115, 77, 176, 172, 184, 246, 213, 81, + 101, 225, 129, 108, 137, 112, 173, 71, 191, 88, 61, 167, 204, 56, + 204, 101, 120, 18, 179, 101, 25, 200, 3, 199, 63, 55, 253, 253, + 224, 5, 96, 198, 156, 95, 137, 20, 232, 103, 152, 210, 216, 147, + 46, 220, 44, 104, 107, 69, 154, 212, 10, 223, 135, 187, 51, 20, + 78, 224, 2, 158, 171, 26, 177, 59, 82, 13, 14, 163, 241, 178, + 147, 55, 221, 195, 228, 141, 6, 144, 84, 202, 101, 25, 117, 231, + 227, 250, 87, 150, 42, 100, 63, 215, 129, 166, 15, 64, 36, 141, + 246, 149, 93, 104, 47, 141, 169, 22, 225, 57, 18, 17, 20, 177, + 223, 125, 25, 232, 242, 180, 197, 239, 8, 157, 27, 144, 102, 255, + 171, 128, 76, 220, 41, 115, 1, 143, 197, 234, 90, 54, 167, 213, + 5, 153, 60, 152, 28, 122, 96, 59, 131, 201, 74, 178, 111, 215, + 131, 118, 24, 188, 225, 190, 80, 248, 250, 37, 108, 178, 150, 65, + 119, 161, 241, 28, 81, 210, 26, 61, 167, 164, 198, 113, 77, 171, + 2, 125, 86, 29, 141, 173, 209, 249, 54, 31, 236, 133, 55, 92, + 218, 95, 140, 184, 137, 243, 89, 106, 35, 25, 71, 58, 149, 171, + 246, 133, 244, 62, 58, 115, 89, 141, 34, 29, 156, 38, 164, 120, + 14, 183, 205, 201, 227, 17, 243, 45, 211, 250, 176, 101, 37, 194, + 187, 31, 175, 210, 54, 196, 127, 69, 59, 230, 175, 215, 241, 232, + 12, 245, 8, 143, 60, 70, 115, 128, 50, 199, 101, 162, 255, 249, + 206, 157, 108, 133, 199, 184, 14, 197, 20, 151, 106, 116, 123, 80, + 207, 59, 62, 252, 149, 97, 223, 102, 32, 29, 252, 12, 87, 132, + 236, 3, 140, 42, 233, 80, 255, 102, 96, 149, 183, 42, 224, 138, + 13, 57, 130, 134, 108, 128, 177, 156, 93, 194, 104, 64, 124, 117, + 231, 111, 196, 81, 30, 154, 56, 189, 88, 3, 82, 90, 231, 3, + 17, 33, 141, 18, 38, 120, 122, 126, 240, 139, 61, 9, 126, 95, + 162, 40, 26, 249, 253, 248, 199, 98, 243, 55, 15, 147, 232, 141, + 167, 193, 6, 183, 172, 241, 113, 180, 54, 82, 119, 149, 186, 165, + 144, 88, 101, 44, 20, 217, 199, 151, 82, 141, 128, 44, 166, 106, + 246, 25, 186, 252, 24, 165, 84, 112, 2, 68, 158, 152, 6, 134, + 89, 18, 242, 243, 8, 235, 236, 111, 110, 8, 33, 93, 120, 84, + 175, 186, 237, 193, 110, 10, 192, 30, 43, 93, 130, 243, 71, 114, + 114, 111, 61, 136, 8, 144, 205, 235, 77, 20, 237, 117, 147, 246, + 104, 251, 153, 234, 190, 180, 165, 86, 228, 177, 96, 104, 16, 151, + 159, 14, 219, 99, 8, 186, 141, 29, 30, 146, 62, 1, 18, 132, + 232, 250, 21, 163, 205, 14, 253, 118, 78, 60, 79, 109, 112, 85, + 172, 213, 105, 121, 233, 219, 187, 230, 23, 238, 194, 160, 57, 78, + 152, 58, 101, 222, 61, 163, 105, 96, 92, 94, 43, 111, 146, 187, + 85, 227, 146, 200, 15, 52, 241, 192, 153, 209, 36, 187, 94, 58, + 103, 127, 81, 29, 88, 212, 175, 178, 12, 224, 215, 29, 187, 238, + 172, 190, 45, 113, 31, 78, 178, 144, 152, 147, 207, 124, 214, 238, + 206, 226, 113, 210, 62, 39, 45, 157, 158, 167, 4, 205, 203, 243, + 254, 203, 242, 143, 91, 119, 235, 0, 111, 133, 235, 231, 181, 2, + 60, 69, 39, 105, 82, 225, 108, 185, 12, 25, 217, 191, 195, 58, + 123, 36, 173, 81, 184, 140, 106, 68, 178, 145, 89, 177, 230, 188, + 36, 141, 83, 119, 212, 60, 43, 19, 210, 67, 168, 217, 180, 117, + 218, 208, 221, 107, 225, 198, 112, 200, 123, 138, 55, 215, 48, 115, + 195, 16, 165, 132, 17, 68, 136, 212, 194, 64, 245, 48, 191, 114, + 60, 77, 231, 219, 125, 3, 128, 14, 173, 189, 51, 77, 42, 183, + 174, 172, 248, 150, 51, 128, 71, 69, 102, 231, 6, 161, 177, 94, + 137, 197, 3, 224, 145, 255, 52, 81, 223, 32, 121, 116, 130, 166, + 198, 163, 227, 184, 255, 203, 55, 38, 196, 50, 216, 153, 160, 77, + 32, 89, 113, 242, 35, 113, 218, 187, 0, 14, 86, 126, 1, 16, + 189, 55, 175, 239, 105, 16, 226, 43, 36, 217, 13, 218, 175, 160, + 16, 19, 161, 15, 183, 206, 77, 235, 192, 180, 185, 148, 206, 141, + 88, 64, 90, 55, 47, 96, 97, 146, 208, 3, 152, 91, 171, 110, + 178, 105, 230, 132, 15, 225, 38, 27, 228, 88, 167, 4, 171, 168, + 132, 62, 227, 151, 89, 50, 135, 167, 6, 178, 166, 46, 118, 221, + 199, 171, 44, 166, 23, 100, 207, 94, 19, 28, 230, 147, 250, 1, + 70, 224, 71, 118, 143, 70, 127, 126, 108, 57, 114, 99, 241, 138, + 246, 9, 43, 235, 195, 208, 217, 170, 126, 6, 98, 247, 74, 95, + 49, 41, 23, 100, 242, 162, 95, 29, 137, 194, 85, 100, 190, 49, + 41, 148, 166, 130, 172, 24, 68, 146, 33, 142, 98, 243, 80, 236, + 9, 246, 134, 73, 209, 185, 244, 50, 173, 232, 171, 196, 109, 233, + 116, 136, 25, 139, 54, 242, 166, 70, 236, 38, 195, 245, 60, 115, + 196, 206, 74, 20, 45, 42, 237, 23, 203, 253, 52, 155, 251, 168, + 196, 210, 130, 178, 67, 83, 235, 36, 186, 31, 230, 76, 3, 26, + 53, 220, 158, 31, 131, 157, 126, 224, 250, 110, 40, 192, 103, 43, + 211, 66, 19, 87, 230, 20, 160, 19, 156, 199, 126, 242, 104, 94, + 105, 142, 83, 133, 113, 231, 158, 227, 133, 157, 63, 228, 11, 218, + 138, 210, 23, 122, 137, 123, 46, 240, 126, 174, 149, 91, 107, 19, + 15, 105, 222, 95, 9, 94, 219, 117, 186, 59, 59, 81, 91, 129, + 133, 118, 38, 63, 228, 79, 222, 209, 19, 66, 48, 101, 10, 210, + 39, 145, 153, 9, 25, 109, 104, 81, 155, 55, 181, 198, 68, 164, + 102, 167, 252, 234, 129, 153, 106, 70, 104, 48, 83, 174, 10, 223, + 71, 126, 215, 131, 11, 204, 162, 235, 249, 201, 41, 161, 50, 41, + 253, 25, 48, 176, 86, 119, 180, 244, 83, 5, 0, 47, 105, 226, + 227, 255, 214, 73, 147, 245, 146, 67, 33, 168, 161, 181, 123, 184, + 254, 211, 134, 36, 246, 82, 251, 7, 97, 182, 223, 93, 198, 131, + 229, 84, 254, 84, 59, 205, 15, 30, 50, 19, 152, 40, 152, 196, + 227, 88, 186, 210, 18, 141, 208, 156, 85, 102, 13, 98, 21, 56, + 112, 214, 168, 69, 60, 1, 208, 210, 125, 7, 248, 232, 27, 225, + 22, 83, 159, 198, 250, 207, 29, 153, 24, 111, 7, 31, 144, 27, + 76, 7, 39, 126, 43, 29, 172, 40, 250, 120, 165, 16, 220, 163, + 241, 208, 189, 227, 252, 133, 251, 35, 2, 245, 163, 120, 33, 18, + 151, 159, 200, 69, 97, 113, 41, 26, 25, 191, 132, 27, 84, 151, + 183, 124, 73, 11, 172, 14, 16, 175, 33, 249, 45, 16, 91, 138, + 132, 204, 52, 146, 119, 91, 43, 114, 218, 165, 128, 153, 208, 81, + 0, 175, 239, 157, 240, 251, 215, 239, 121, 86, 208, 135, 79, 97, + 185, 197, 131, 137, 120, 100, 229, 156, 26, 248, 93, 218, 131, 30, + 237, 173, 30, 194, 221, 148, 88, 113, 71, 148, 77, 32, 41, 26, + 243, 82, 140, 6, 179, 233, 122, 29, 115, 81, 12, 25, 113, 254, + 132, 32, 222, 49, 211, 33, 79, 8, 11, 117, 245, 152, 22, 113, + 92, 182, 153, 196, 109, 19, 236, 229, 20, 115, 72, 113, 159, 184, + 221, 199, 138, 20, 178, 109, 207, 112, 39, 126, 136, 36, 90, 76, + 149, 66, 238, 104, 240, 75, 173, 154, 202, 90, 49, 148, 39, 134, + 12, 160, 194, 112, 184, 166, 123, 44, 177, 42, 186, 12, 225, 28, + 190, 60, 99, 151, 188, 184, 243, 212, 32, 139, 19, 0, 112, 133, + 171, 178, 48, 109, 23, 38, 60, 84, 236, 133, 218, 128, 116, 24, + 241, 119, 124, 71, 85, 214, 223, 150, 208, 215, 62, 85, 84, 201, + 154, 173, 3, 193, 192, 64, 213, 48, 195, 42, 41, 236, 166, 131, + 223, 57, 176, 16, 31, 142, 53, 71, 152, 227, 138, 133, 33, 134, + 155, 102, 121, 135, 32, 143, 45, 108, 73, 152, 102, 172, 7, 149, + 155, 243, 28, 183, 50, 201, 251, 239, 12, 211, 31, 231, 23, 136, + 200, 50, 71, 214, 204, 73, 208, 105, 134, 69, 164, 66, 71, 23, + 106, 235, 87, 205, 174, 239, 31, 84, 232, 132, 190, 183, 66, 1, + 194, 170, 206, 156, 55, 87, 97, 111, 0, 107, 18, 36, 114, 175, + 233, 237, 78, 160, 55, 174, 123, 241, 230, 93, 127, 190, 150, 252, + 89, 197, 101, 129, 195, 100, 188, 199, 146, 255, 41, 110, 45, 54, + 248, 91, 244, 73, 118, 201, 236, 4, 173, 232, 40, 129, 84, 119, + 153, 126, 234, 38, 77, 100, 63, 141, 45, 197, 68, 103, 121, 239, + 216, 142, 197, 95, 176, 55, 15, 255, 155, 60, 65, 170, 222, 91, + 238, 138, 194, 173, 124, 211, 64, 171, 78, 178, 214, 80, 113, 56, + 69, 105, 36, 16, 24, 185, 36, 170, 113, 225, 73, 139, 132, 121, + 46, 247, 208, 196, 226, 131, 106, 28, 107, 151, 140, 212, 47, 215, + 179, 13, 205, 73, 197, 225, 149, 89, 246, 20, 204, 178, 245, 86, + 167, 124, 195, 138, 176, 83, 101, 126, 171, 1, 22, 146, 2, 213, + 79, 224, 74, 126, 254, 102, 203, 220, 123, 229, 15, 223, 141, 207, + 226, 67, 74, 207, 107, 183, 235, 109, 198, 72, 109, 174, 123, 253, + 51, 25, 31, 211, 59, 231, 101, 119, 107, 40, 232, 189, 223, 116, + 146, 177, 116, 102, 243, 61, 145, 134, 166, 150, 13, 83, 41, 65, + 49, 181, 219, 161, 68, 92, 209, 222, 185, 173, 252, 15, 0, 161, + 110, 233, 234, 26, 29, 79, 229, 13, 190, 93, 163, 141, 112, 4, + 237, 165, 86, 121, 55, 108, 128, 217, 44, 0, 19, 36, 114, 136, + 44, 187, 39, 214, 149, 189, 19, 177, 211, 27, 60, 132, 9, 235, + 124, 59, 99, 149, 145, 55, 195, 19, 251, 27, 187, 131, 16, 85, + 154, 254, 51, 53, 169, 126, 123, 156, 198, 246, 174, 40, 93, 70, + 23, 182, 22, 220, 172, 70, 204, 239, 61, 203, 24, 177, 223, 95, + 139, 19, 255, 31, 189, 219, 24, 184, 144, 206, 118, 218, 50, 140, + 144, 3, 171, 5, 250, 190, 161, 25, 84, 105, 237, 77, 210, 117, + 97, 67, 250, 122, 30, 104, 174, 97, 151, 190, 56, 179, 123, 131, + 185, 164, 87, 103, 122, 39, 231, 165, 169, 104, 84, 209, 10, 26, + 233, 54, 230, 187, 209, 21, 128, 7, 26, 92, 146, 88, 149, 204, + 150, 207, 147, 184, 23, 70, 53, 128, 89, 42, 63, 96, 76, 156, + 172, 129, 215, 32, 159, 54, 141, 137, 14, 174, 201, 24, 24, 126, + 34, 23, 66, 95, 29, 255, 18, 62, 44, 238, 144, 174, 54, 22, + 106, 110, 255, 184, 44, 242, 27, 215, 176, 18, 178, 225, 255, 37, + 20, 148, 138, 200, 224, 45, 177, 18, 123, 177, 37, 20, 253, 110, + 7, 177, 144, 51, 218, 172, 20, 60, 166, 49, 20, 22, 235, 32, + 128, 97, 247, 117, 111, 103, 44, 170, 210, 223, 135, 200, 54, 118, + 31, 189, 255, 56, 121, 2, 65, 32, 249, 196, 100, 172, 234, 104, + 202, 8, 255, 29, 41, 60, 121, 245, 30, 206, 97, 67, 182, 19, + 81, 86, 105, 150, 174, 178, 65, 12, 64, 12, 136, 52, 200, 54, + 108, 193, 113, 87, 121, 35, 153, 183, 40, 39, 38, 247, 70, 98, + 143, 14, 6, 126, 42, 61, 11, 232, 178, 125, 193, 245, 56, 143, + 189, 4, 220, 150, 152, 107, 26, 109, 171, 209, 126, 227, 144, 161, + 206, 148, 46, 10, 120, 112, 7, 148, 235, 179, 84, 45, 5, 24, + 83, 50, 142, 26, 70, 232, 44, 225, 46, 134, 132, 194, 54, 198, + 176, 51, 22, 19, 229, 76, 94, 63, 226, 14, 114, 0, 167, 54, + 130, 112, 234, 3, 73, 201, 147, 209, 5, 115, 39, 168, 91, 68, + 55, 83, 129, 81, 15, 27, 42, 233, 24, 221, 165, 179, 244, 205, + 183, 144, 178, 100, 10, 196, 75, 6, 196, 107, 128, 48, 26, 100, + 21, 94, 65, 156, 173, 111, 233, 14, 85, 89, 60, 166, 124, 83, + 222, 41, 68, 102, 173, 58, 149, 82, 227, 32, 116, 189, 63, 161, + 1, 244, 137, 229, 246, 28, 106, 132, 81, 145, 211, 108, 140, 247, + 40, 107, 121, 97, 85, 97, 214, 125, 70, 221, 130, 124, 233, 139, + 186, 174, 169, 150, 40, 133, 46, 112, 71, 178, 19, 115, 198, 253, + 86, 7, 124, 0, 144, 44, 48, 188, 97, 217, 153, 124, 156, 132, + 244, 104, 146, 118, 81, 103, 63, 129, 182, 53, 63, 229, 188, 82, + 184, 77, 251, 88, 41, 81, 65, 49, 216, 56, 70, 149, 233, 187, + 184, 186, 101, 142, 224, 24, 82, 189, 68, 128, 157, 20, 67, 106, + 248, 74, 105, 15, 86, 160, 154, 120, 125, 215, 10, 29, 171, 39, + 128, 52, 77, 19, 86, 139, 112, 186, 54, 136, 167, 156, 118, 58, + 33, 146, 204, 197, 187, 254, 121, 112, 95, 55, 221, 161, 185, 165, + 97, 108, 105, 96, 147, 40, 114, 254, 144, 129, 216, 5, 129, 121, + 246, 116, 73, 82, 117, 243, 39, 111, 198, 208, 52, 25, 92, 202, + 248, 78, 18, 89, 189, 104, 122, 63, 201, 250, 71, 248, 218, 71, + 42, 19, 171, 102, 184, 59, 254, 177, 22, 15, 4, 100, 16, 113, + 55, 130, 130, 155, 31, 51, 245, 149, 227, 236, 243, 75, 70, 3, + 78, 157, 2, 194, 25, 96, 154, 245, 205, 142, 109, 62, 252, 243, + 168, 251, 246, 82, 231, 5, 116, 112, 154, 31, 149, 221, 200, 218, + 237, 132, 51, 156, 42, 31, 163, 250, 164, 242, 154, 90, 101, 39, + 180, 3, 32, 208, 6, 113, 137, 220, 238, 71, 26, 24, 42, 32, + 232, 165, 82, 85, 48, 127, 32, 230, 38, 59, 119, 24, 161, 175, + 138, 135, 206, 199, 110, 245, 94, 224, 67, 191, 42, 98, 169, 241, + 1, 70, 45, 213, 164, 255, 60, 159, 217, 2, 203, 187, 163, 185, + 95, 124, 125, 147, 236, 31, 14, 229, 41, 209, 251, 35, 99, 102, + 241, 197, 17, 231, 155, 144, 180, 96, 45, 254, 160, 75, 33, 97, + 153, 123, 109, 95, 52, 1, 48, 113, 174, 13, 7, 193, 127, 1, + 192, 56, 187, 85, 190, 207, 40, 9, 142, 75, 111, 138, 49, 210, + 114, 18, 92, 231, 190, 79, 110, 177, 78, 207, 169, 82, 27, 10, + 78, 167, 196, 215, 243, 120, 182, 45, 180, 60, 164, 125, 115, 102, + 122, 88, 16, 109, 162, 54, 166, 192, 252, 22, 50, 18, 23, 246, + 202, 19, 133, 45, 38, 226, 255, 188, 104, 32, 189, 199, 190, 140, + 128, 183, 53, 226, 43, 216, 128, 180, 22, 29, 177, 193, 233, 56, + 180, 239, 123, 42, 140, 186, 145, 138, 177, 44, 176, 139, 111, 95, + 135, 203, 51, 25, 139, 28, 100, 198, 20, 90, 74, 31, 168, 217, + 107, 65, 100, 68, 26, 229, 146, 132, 152, 197, 141, 74, 142, 122, + 174, 207, 195, 82, 127, 159, 80, 181, 208, 134, 211, 62, 15, 21, + 196, 126, 111, 102, 116, 63, 73, 107, 28, 251, 187, 30, 16, 53, + 113, 248, 253, 149, 226, 35, 83, 69, 192, 120, 72, 249, 204, 255, + 240, 162, 140, 140, 24, 51, 223, 214, 133, 252, 11, 207, 80, 224, + 200, 148, 251, 214, 179, 199, 49, 170, 24, 188, 49, 0, 112, 220, + 69, 176, 251, 197, 136, 209, 201, 250, 237, 86, 124, 140, 144, 81, + 41, 30, 213, 40, 180, 183, 175, 200, 131, 184, 231, 96, 112, 0, + 59, 110, 24, 36, 42, 192, 126, 155, 51, 98, 1, 11, 44, 141, + 183, 231, 203, 43, 179, 215, 196, 29, 6, 116, 46, 232, 66, 201, + 38, 233, 44, 82, 117, 172, 137, 230, 199, 247, 50, 114, 58, 234, + 113, 125, 114, 126, 59, 71, 130, 227, 95, 219, 253, 193, 100, 98, + 136, 222, 145, 128, 1, 20, 2, 0, 0, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 99, 108, 101, + 97, 114, 116, 111, 109, 97, 114, 107, 10, 128, 3, +}; diff --git a/Rendering/fonts/face_arial_bold.cxx b/Rendering/fonts/face_arial_bold.cxx new file mode 100644 index 0000000..cd8e27c --- /dev/null +++ b/Rendering/fonts/face_arial_bold.cxx @@ -0,0 +1,2607 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Arial Bold +// URW Gothic L Demi (uagd8a.pfb) +// Contributed by URW + +size_t face_arial_bold_buffer_length = 36354; + +unsigned char face_arial_bold_buffer[] = { + 128, 1, 85, 6, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 58, 32, 85, 82, + 87, 71, 111, 116, 104, 105, 99, 76, 45, 68, 101, 109, 105, 32, + 49, 46, 48, 53, 10, 37, 37, 67, 114, 101, 97, 116, 105, 111, + 110, 68, 97, 116, 101, 58, 32, 87, 101, 100, 32, 68, 101, 99, + 32, 50, 50, 32, 49, 57, 57, 57, 10, 37, 32, 67, 111, 112, + 121, 114, 105, 103, 104, 116, 32, 40, 85, 82, 87, 41, 43, 43, + 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, + 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, + 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, + 112, 109, 101, 110, 116, 10, 37, 32, 40, 85, 82, 87, 41, 43, + 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, + 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, + 111, 112, 109, 101, 110, 116, 10, 37, 32, 83, 101, 101, 32, 116, + 104, 101, 32, 102, 105, 108, 101, 32, 80, 85, 66, 76, 73, 67, + 32, 40, 65, 108, 97, 100, 100, 105, 110, 32, 70, 114, 101, 101, + 32, 80, 117, 98, 108, 105, 99, 32, 76, 105, 99, 101, 110, 115, + 101, 41, 32, 102, 111, 114, 32, 108, 105, 99, 101, 110, 115, 101, + 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 46, 10, 37, + 32, 65, 115, 32, 97, 32, 115, 112, 101, 99, 105, 97, 108, 32, + 101, 120, 99, 101, 112, 116, 105, 111, 110, 44, 32, 112, 101, 114, + 109, 105, 115, 115, 105, 111, 110, 32, 105, 115, 32, 103, 114, 97, + 110, 116, 101, 100, 32, 116, 111, 32, 105, 110, 99, 108, 117, 100, + 101, 32, 116, 104, 105, 115, 32, 102, 111, 110, 116, 10, 37, 32, + 112, 114, 111, 103, 114, 97, 109, 32, 105, 110, 32, 97, 32, 80, + 111, 115, 116, 115, 99, 114, 105, 112, 116, 32, 111, 114, 32, 80, + 68, 70, 32, 102, 105, 108, 101, 32, 116, 104, 97, 116, 32, 99, + 111, 110, 115, 105, 115, 116, 115, 32, 111, 102, 32, 97, 32, 100, + 111, 99, 117, 109, 101, 110, 116, 32, 116, 104, 97, 116, 10, 37, + 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, 116, 101, 120, 116, + 32, 116, 111, 32, 98, 101, 32, 100, 105, 115, 112, 108, 97, 121, + 101, 100, 32, 111, 114, 32, 112, 114, 105, 110, 116, 101, 100, 32, + 117, 115, 105, 110, 103, 32, 116, 104, 105, 115, 32, 102, 111, 110, + 116, 44, 32, 114, 101, 103, 97, 114, 100, 108, 101, 115, 115, 10, + 37, 32, 111, 102, 32, 116, 104, 101, 32, 99, 111, 110, 100, 105, + 116, 105, 111, 110, 115, 32, 111, 114, 32, 108, 105, 99, 101, 110, + 115, 101, 32, 97, 112, 112, 108, 121, 105, 110, 103, 32, 116, 111, + 32, 116, 104, 101, 32, 100, 111, 99, 117, 109, 101, 110, 116, 32, + 105, 116, 115, 101, 108, 102, 46, 10, 49, 50, 32, 100, 105, 99, + 116, 32, 98, 101, 103, 105, 110, 10, 47, 70, 111, 110, 116, 73, + 110, 102, 111, 32, 49, 48, 32, 100, 105, 99, 116, 32, 100, 117, + 112, 32, 98, 101, 103, 105, 110, 10, 47, 118, 101, 114, 115, 105, + 111, 110, 32, 40, 49, 46, 48, 53, 41, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, 78, 111, 116, 105, + 99, 101, 32, 40, 40, 85, 82, 87, 41, 43, 43, 44, 67, 111, + 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, 57, 32, 98, + 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, 101, 115, 105, + 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, + 110, 116, 46, 32, 83, 101, 101, 32, 116, 104, 101, 32, 102, 105, + 108, 101, 32, 80, 85, 66, 76, 73, 67, 32, 40, 65, 108, 97, + 100, 100, 105, 110, 32, 70, 114, 101, 101, 32, 80, 117, 98, 108, + 105, 99, 32, 76, 105, 99, 101, 110, 115, 101, 41, 32, 102, 111, + 114, 32, 108, 105, 99, 101, 110, 115, 101, 32, 99, 111, 110, 100, + 105, 116, 105, 111, 110, 115, 46, 32, 65, 115, 32, 97, 32, 115, + 112, 101, 99, 105, 97, 108, 32, 101, 120, 99, 101, 112, 116, 105, + 111, 110, 44, 32, 112, 101, 114, 109, 105, 115, 115, 105, 111, 110, + 32, 105, 115, 32, 103, 114, 97, 110, 116, 101, 100, 32, 116, 111, + 32, 105, 110, 99, 108, 117, 100, 101, 32, 116, 104, 105, 115, 32, + 102, 111, 110, 116, 32, 112, 114, 111, 103, 114, 97, 109, 32, 105, + 110, 32, 97, 32, 80, 111, 115, 116, 115, 99, 114, 105, 112, 116, + 32, 111, 114, 32, 80, 68, 70, 32, 102, 105, 108, 101, 32, 116, + 104, 97, 116, 32, 99, 111, 110, 115, 105, 115, 116, 115, 32, 111, + 102, 32, 97, 32, 100, 111, 99, 117, 109, 101, 110, 116, 32, 116, + 104, 97, 116, 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, 116, + 101, 120, 116, 32, 116, 111, 32, 98, 101, 32, 100, 105, 115, 112, + 108, 97, 121, 101, 100, 32, 111, 114, 32, 112, 114, 105, 110, 116, + 101, 100, 32, 117, 115, 105, 110, 103, 32, 116, 104, 105, 115, 32, + 102, 111, 110, 116, 44, 32, 114, 101, 103, 97, 114, 100, 108, 101, + 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, 99, 111, 110, 100, + 105, 116, 105, 111, 110, 115, 32, 111, 114, 32, 108, 105, 99, 101, + 110, 115, 101, 32, 97, 112, 112, 108, 121, 105, 110, 103, 32, 116, + 111, 32, 116, 104, 101, 32, 100, 111, 99, 117, 109, 101, 110, 116, + 32, 105, 116, 115, 101, 108, 102, 46, 41, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, 67, 111, 112, 121, + 114, 105, 103, 104, 116, 32, 40, 67, 111, 112, 121, 114, 105, 103, + 104, 116, 32, 40, 85, 82, 87, 41, 43, 43, 44, 67, 111, 112, + 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, 57, 32, 98, 121, + 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, 101, 115, 105, 103, + 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, 112, 109, 101, 110, + 116, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, + 102, 10, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 85, + 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, 76, 32, 68, 101, + 109, 105, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, + 101, 102, 10, 47, 70, 97, 109, 105, 108, 121, 78, 97, 109, 101, + 32, 40, 85, 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, 76, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 10, 47, 87, 101, 105, 103, 104, 116, 32, 40, 68, 101, 109, 105, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 10, 47, 73, 116, 97, 108, 105, 99, 65, 110, 103, 108, 101, 32, + 48, 46, 48, 32, 100, 101, 102, 10, 47, 105, 115, 70, 105, 120, + 101, 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, 101, 32, + 100, 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, + 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 57, 51, 32, 100, + 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 84, + 104, 105, 99, 107, 110, 101, 115, 115, 32, 57, 48, 32, 100, 101, + 102, 10, 101, 110, 100, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 10, 47, 70, 111, 110, 116, 78, 97, 109, 101, + 32, 47, 85, 82, 87, 71, 111, 116, 104, 105, 99, 76, 45, 68, + 101, 109, 105, 32, 100, 101, 102, 10, 47, 80, 97, 105, 110, 116, + 84, 121, 112, 101, 32, 48, 32, 100, 101, 102, 10, 47, 87, 77, + 111, 100, 101, 32, 48, 32, 100, 101, 102, 10, 47, 70, 111, 110, + 116, 66, 66, 111, 120, 32, 123, 45, 49, 50, 49, 32, 45, 50, + 53, 49, 32, 49, 50, 52, 56, 32, 49, 48, 48, 48, 125, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 70, 111, 110, 116, 84, 121, 112, 101, 32, 49, 32, 100, 101, 102, + 10, 47, 70, 111, 110, 116, 77, 97, 116, 114, 105, 120, 32, 91, + 48, 46, 48, 48, 49, 32, 48, 46, 48, 32, 48, 46, 48, 32, + 48, 46, 48, 48, 49, 32, 48, 46, 48, 32, 48, 46, 48, 93, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, + 47, 69, 110, 99, 111, 100, 105, 110, 103, 32, 83, 116, 97, 110, + 100, 97, 114, 100, 69, 110, 99, 111, 100, 105, 110, 103, 32, 100, + 101, 102, 10, 47, 85, 110, 105, 113, 117, 101, 73, 68, 32, 53, + 48, 49, 57, 53, 53, 54, 32, 100, 101, 102, 10, 99, 117, 114, + 114, 101, 110, 116, 100, 105, 99, 116, 32, 101, 110, 100, 10, 99, + 117, 114, 114, 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, + 101, 99, 13, 128, 2, 133, 133, 0, 0, 233, 141, 9, 215, 96, + 163, 194, 44, 241, 25, 249, 220, 105, 154, 34, 195, 91, 91, 53, + 237, 106, 162, 53, 147, 199, 109, 84, 202, 187, 94, 148, 43, 247, + 214, 221, 132, 241, 102, 75, 137, 105, 156, 116, 180, 114, 222, 159, + 142, 109, 249, 37, 246, 196, 242, 4, 233, 241, 198, 57, 180, 219, + 169, 136, 237, 42, 196, 25, 255, 43, 43, 222, 96, 91, 142, 227, + 38, 78, 221, 102, 65, 45, 79, 33, 198, 74, 197, 34, 189, 252, + 124, 85, 2, 249, 195, 243, 229, 89, 43, 59, 32, 147, 211, 60, + 155, 250, 237, 210, 212, 158, 137, 170, 186, 168, 50, 226, 63, 6, + 46, 145, 162, 80, 50, 81, 157, 24, 104, 129, 110, 68, 180, 224, + 116, 119, 149, 0, 61, 121, 48, 41, 157, 110, 30, 42, 91, 254, + 13, 89, 93, 201, 126, 20, 9, 137, 206, 129, 216, 215, 248, 82, + 255, 156, 220, 122, 27, 27, 89, 140, 105, 19, 29, 238, 0, 91, + 65, 88, 5, 161, 109, 137, 109, 248, 53, 150, 113, 115, 81, 142, + 124, 223, 116, 58, 200, 39, 63, 117, 202, 193, 118, 76, 238, 190, + 9, 243, 35, 143, 67, 38, 72, 69, 106, 199, 182, 12, 72, 196, + 208, 170, 198, 93, 84, 150, 158, 84, 172, 85, 13, 124, 191, 16, + 10, 37, 125, 79, 80, 110, 25, 112, 155, 46, 74, 168, 105, 96, + 219, 30, 6, 78, 159, 228, 220, 37, 99, 53, 39, 250, 169, 244, + 203, 1, 164, 171, 22, 23, 37, 0, 84, 84, 65, 226, 249, 87, + 78, 36, 218, 1, 30, 143, 132, 112, 7, 94, 36, 31, 31, 193, + 213, 205, 49, 73, 244, 115, 11, 7, 34, 70, 77, 199, 85, 167, + 244, 211, 183, 212, 16, 77, 95, 243, 19, 222, 128, 186, 109, 106, + 227, 37, 112, 93, 254, 31, 5, 162, 5, 16, 11, 37, 140, 237, + 148, 48, 58, 17, 188, 129, 217, 229, 9, 206, 85, 24, 244, 226, + 10, 136, 75, 39, 211, 112, 243, 19, 236, 89, 176, 200, 101, 55, + 111, 69, 159, 254, 185, 154, 43, 111, 47, 49, 233, 115, 63, 229, + 88, 5, 132, 52, 11, 57, 234, 141, 183, 24, 248, 118, 139, 210, + 47, 189, 29, 83, 143, 89, 100, 154, 70, 250, 119, 90, 76, 65, + 177, 37, 95, 97, 60, 106, 218, 103, 27, 98, 26, 222, 65, 180, + 193, 133, 118, 155, 192, 76, 188, 177, 128, 189, 214, 147, 78, 194, + 70, 108, 181, 171, 101, 138, 169, 216, 150, 105, 235, 242, 74, 45, + 36, 49, 251, 133, 88, 144, 21, 25, 92, 99, 194, 168, 206, 221, + 6, 131, 55, 177, 216, 109, 116, 86, 218, 205, 188, 114, 70, 234, + 12, 71, 61, 217, 32, 217, 249, 117, 65, 184, 96, 93, 229, 117, + 180, 229, 246, 57, 199, 42, 13, 37, 248, 109, 51, 69, 34, 28, + 61, 57, 206, 158, 188, 23, 118, 235, 47, 171, 55, 244, 142, 98, + 12, 141, 224, 88, 102, 218, 150, 189, 121, 63, 208, 78, 125, 169, + 34, 219, 87, 33, 237, 99, 209, 88, 106, 144, 163, 193, 72, 81, + 177, 134, 136, 55, 119, 149, 104, 168, 180, 90, 109, 93, 65, 200, + 124, 29, 69, 238, 140, 127, 149, 244, 228, 19, 235, 100, 136, 228, + 154, 124, 187, 69, 194, 15, 71, 134, 237, 70, 22, 149, 71, 113, + 230, 142, 20, 111, 250, 119, 200, 154, 2, 30, 134, 195, 193, 113, + 78, 242, 235, 61, 153, 136, 228, 120, 40, 30, 124, 154, 105, 54, + 140, 4, 94, 164, 245, 12, 1, 106, 2, 131, 127, 110, 69, 208, + 147, 173, 86, 113, 26, 104, 91, 230, 148, 23, 249, 182, 254, 212, + 196, 48, 43, 67, 2, 34, 24, 78, 10, 26, 26, 249, 211, 151, + 50, 222, 109, 235, 121, 167, 178, 82, 11, 247, 31, 107, 228, 170, + 221, 51, 228, 248, 224, 138, 184, 252, 201, 200, 253, 128, 67, 164, + 6, 82, 90, 20, 73, 6, 149, 148, 10, 118, 13, 186, 172, 252, + 162, 54, 105, 218, 211, 26, 154, 136, 73, 109, 212, 230, 28, 178, + 175, 46, 97, 212, 149, 184, 232, 190, 138, 244, 193, 197, 115, 152, + 44, 252, 132, 0, 154, 144, 23, 39, 175, 89, 75, 55, 141, 104, + 50, 40, 128, 220, 92, 74, 201, 126, 148, 248, 32, 87, 32, 167, + 209, 77, 232, 129, 134, 37, 195, 215, 144, 47, 246, 104, 73, 91, + 162, 95, 110, 218, 138, 84, 98, 42, 55, 83, 142, 124, 22, 231, + 90, 31, 241, 244, 82, 179, 205, 246, 245, 75, 65, 102, 214, 62, + 144, 215, 179, 177, 222, 71, 155, 192, 103, 189, 254, 218, 207, 13, + 67, 130, 111, 217, 41, 250, 251, 211, 117, 183, 102, 27, 20, 172, + 165, 206, 44, 250, 23, 42, 119, 50, 189, 38, 42, 182, 63, 232, + 143, 112, 124, 88, 47, 28, 166, 77, 30, 204, 37, 56, 190, 116, + 6, 150, 68, 78, 128, 195, 201, 226, 106, 103, 162, 164, 195, 103, + 238, 43, 60, 106, 22, 107, 143, 174, 39, 101, 250, 44, 215, 99, + 152, 35, 186, 242, 36, 138, 213, 68, 33, 16, 89, 78, 209, 79, + 95, 244, 74, 25, 246, 194, 75, 56, 177, 180, 13, 83, 236, 228, + 45, 42, 155, 94, 134, 203, 34, 29, 187, 253, 179, 45, 83, 237, + 109, 175, 125, 112, 50, 170, 100, 11, 121, 72, 67, 17, 150, 79, + 136, 112, 107, 212, 63, 128, 246, 236, 224, 70, 191, 151, 244, 129, + 132, 160, 192, 57, 173, 14, 207, 54, 195, 15, 118, 173, 235, 18, + 131, 219, 7, 90, 105, 234, 215, 212, 86, 97, 182, 80, 104, 65, + 202, 190, 23, 23, 71, 98, 85, 23, 229, 227, 12, 147, 62, 242, + 154, 150, 34, 13, 154, 10, 22, 208, 44, 243, 21, 148, 48, 11, + 128, 171, 204, 130, 27, 239, 164, 66, 200, 46, 96, 201, 179, 192, + 58, 179, 19, 91, 145, 116, 70, 68, 81, 60, 129, 225, 149, 87, + 131, 82, 119, 250, 244, 31, 5, 154, 105, 77, 227, 189, 120, 168, + 43, 42, 148, 217, 118, 72, 233, 33, 222, 131, 116, 126, 81, 109, + 2, 213, 187, 157, 221, 159, 60, 200, 182, 141, 213, 243, 177, 80, + 222, 188, 176, 45, 129, 244, 106, 34, 135, 97, 61, 168, 32, 249, + 251, 153, 21, 59, 136, 144, 226, 76, 197, 205, 141, 182, 234, 84, + 25, 86, 185, 4, 39, 50, 190, 42, 153, 49, 201, 246, 122, 207, + 239, 181, 46, 25, 104, 186, 113, 54, 145, 114, 240, 27, 6, 142, + 12, 94, 227, 160, 35, 87, 11, 209, 122, 100, 76, 250, 135, 115, + 84, 155, 174, 67, 255, 26, 208, 125, 33, 154, 220, 54, 90, 200, + 195, 124, 0, 114, 200, 147, 220, 111, 22, 23, 117, 164, 240, 243, + 105, 163, 234, 173, 163, 175, 0, 175, 109, 54, 125, 180, 80, 11, + 38, 169, 26, 188, 98, 153, 85, 140, 229, 107, 233, 114, 115, 217, + 124, 203, 68, 141, 63, 88, 54, 101, 252, 191, 54, 235, 228, 65, + 153, 148, 154, 241, 62, 5, 22, 156, 254, 183, 104, 229, 212, 231, + 19, 122, 20, 77, 40, 177, 34, 142, 194, 48, 185, 52, 10, 91, + 63, 96, 57, 29, 19, 194, 106, 77, 130, 120, 146, 33, 8, 29, + 28, 117, 243, 156, 205, 187, 244, 81, 99, 36, 193, 85, 44, 28, + 167, 120, 2, 52, 46, 27, 28, 186, 205, 122, 61, 125, 145, 236, + 216, 187, 192, 120, 250, 129, 226, 194, 247, 70, 159, 68, 12, 187, + 217, 133, 229, 148, 46, 78, 123, 251, 187, 175, 125, 3, 109, 6, + 77, 89, 60, 173, 198, 171, 41, 230, 60, 169, 26, 153, 212, 228, + 145, 2, 95, 10, 250, 178, 73, 143, 225, 215, 107, 249, 164, 186, + 240, 43, 109, 156, 33, 23, 23, 206, 186, 64, 20, 228, 196, 91, + 168, 251, 125, 125, 145, 171, 216, 225, 195, 248, 249, 222, 38, 222, + 67, 42, 188, 143, 105, 92, 237, 21, 60, 170, 78, 55, 123, 68, + 249, 77, 226, 223, 19, 161, 117, 79, 82, 243, 30, 199, 158, 207, + 31, 255, 80, 108, 212, 151, 133, 64, 141, 240, 79, 4, 201, 155, + 9, 63, 194, 41, 184, 232, 166, 171, 139, 34, 55, 189, 82, 243, + 131, 89, 141, 142, 49, 72, 172, 162, 19, 169, 199, 87, 92, 234, + 139, 94, 54, 28, 245, 113, 88, 202, 10, 8, 7, 137, 21, 105, + 4, 245, 222, 0, 159, 221, 78, 118, 235, 195, 141, 155, 243, 82, + 26, 190, 59, 58, 13, 150, 126, 160, 29, 175, 198, 127, 226, 178, + 226, 74, 173, 83, 227, 92, 39, 0, 149, 154, 98, 202, 207, 92, + 6, 221, 99, 194, 41, 170, 245, 179, 7, 53, 206, 56, 248, 89, + 182, 155, 236, 183, 112, 67, 202, 16, 176, 109, 30, 38, 184, 222, + 85, 177, 52, 114, 181, 26, 32, 161, 77, 217, 202, 234, 87, 239, + 46, 2, 26, 51, 174, 147, 221, 125, 238, 173, 95, 161, 118, 200, + 201, 80, 55, 214, 12, 181, 235, 21, 215, 34, 169, 139, 111, 83, + 188, 180, 170, 109, 32, 211, 89, 222, 136, 111, 36, 163, 182, 190, + 3, 202, 117, 112, 118, 188, 218, 254, 69, 74, 56, 224, 117, 235, + 216, 174, 62, 84, 35, 211, 125, 86, 59, 21, 48, 195, 14, 18, + 136, 235, 40, 117, 14, 179, 241, 3, 29, 42, 226, 52, 2, 70, + 91, 38, 107, 14, 231, 8, 2, 196, 63, 94, 163, 232, 82, 176, + 121, 106, 186, 51, 65, 96, 34, 149, 195, 127, 127, 84, 165, 232, + 9, 237, 114, 123, 147, 155, 118, 6, 109, 61, 150, 8, 94, 143, + 159, 182, 7, 145, 246, 159, 13, 232, 175, 207, 150, 50, 27, 69, + 95, 122, 80, 113, 247, 100, 74, 217, 244, 82, 56, 195, 218, 119, + 212, 139, 174, 34, 93, 195, 71, 32, 153, 208, 100, 89, 85, 239, + 15, 183, 62, 63, 89, 126, 148, 87, 142, 214, 21, 203, 190, 145, + 139, 129, 41, 187, 151, 13, 167, 200, 113, 78, 101, 10, 242, 132, + 146, 110, 192, 234, 109, 87, 2, 12, 22, 184, 219, 160, 157, 67, + 48, 210, 151, 31, 59, 28, 6, 40, 41, 131, 28, 183, 209, 188, + 6, 241, 158, 68, 192, 196, 46, 235, 28, 164, 238, 111, 10, 93, + 245, 124, 232, 168, 37, 245, 38, 145, 251, 15, 116, 227, 79, 115, + 177, 153, 18, 11, 28, 30, 41, 193, 173, 156, 236, 248, 154, 37, + 105, 132, 241, 206, 174, 142, 232, 236, 206, 55, 212, 19, 128, 135, + 222, 206, 43, 181, 238, 29, 194, 27, 130, 114, 81, 104, 250, 161, + 31, 129, 228, 41, 141, 93, 236, 227, 232, 214, 137, 71, 109, 4, + 88, 156, 65, 29, 217, 49, 45, 76, 243, 145, 13, 15, 90, 139, + 232, 49, 192, 213, 6, 72, 131, 231, 157, 39, 109, 15, 1, 201, + 8, 66, 5, 81, 214, 153, 32, 67, 171, 188, 160, 14, 186, 99, + 80, 142, 98, 144, 200, 51, 177, 253, 203, 149, 158, 45, 138, 241, + 121, 102, 210, 1, 254, 231, 25, 159, 16, 255, 46, 38, 201, 135, + 240, 154, 243, 197, 93, 11, 222, 253, 23, 163, 241, 13, 42, 35, + 227, 138, 114, 219, 11, 114, 16, 166, 90, 72, 48, 62, 135, 215, + 189, 75, 147, 230, 145, 101, 214, 222, 231, 159, 36, 117, 200, 143, + 205, 25, 147, 4, 161, 25, 58, 85, 209, 119, 102, 230, 128, 1, + 17, 152, 1, 230, 41, 23, 161, 21, 227, 203, 149, 5, 194, 125, + 242, 25, 45, 46, 111, 58, 246, 175, 138, 181, 62, 70, 141, 190, + 217, 200, 126, 146, 159, 204, 248, 172, 3, 100, 54, 247, 186, 241, + 238, 121, 127, 240, 31, 238, 6, 59, 246, 14, 196, 142, 37, 63, + 178, 92, 133, 121, 46, 23, 122, 71, 129, 49, 156, 207, 196, 137, + 204, 181, 220, 118, 54, 153, 209, 21, 85, 206, 216, 73, 66, 35, + 105, 63, 27, 45, 12, 47, 27, 9, 9, 221, 200, 240, 57, 108, + 190, 110, 69, 24, 25, 29, 106, 160, 105, 107, 238, 228, 236, 192, + 84, 247, 218, 223, 101, 26, 33, 39, 2, 181, 252, 91, 214, 152, + 218, 230, 188, 90, 231, 253, 140, 31, 69, 7, 131, 53, 42, 146, + 214, 30, 55, 239, 201, 217, 208, 197, 206, 164, 207, 27, 222, 94, + 147, 59, 149, 81, 82, 23, 175, 141, 206, 86, 134, 54, 237, 123, + 160, 171, 233, 141, 191, 69, 10, 113, 83, 134, 241, 44, 72, 161, + 16, 224, 182, 166, 253, 246, 69, 64, 27, 156, 164, 53, 124, 158, + 78, 123, 232, 224, 155, 158, 19, 245, 167, 124, 9, 178, 84, 229, + 147, 8, 82, 89, 127, 210, 220, 13, 55, 136, 105, 136, 97, 185, + 148, 143, 202, 140, 44, 72, 12, 25, 15, 247, 118, 210, 252, 74, + 99, 124, 76, 123, 133, 238, 63, 43, 59, 123, 224, 204, 144, 184, + 132, 59, 47, 95, 184, 182, 246, 116, 114, 242, 123, 192, 209, 17, + 72, 172, 26, 182, 232, 195, 227, 51, 141, 124, 244, 70, 97, 209, + 86, 45, 179, 183, 55, 227, 105, 78, 2, 123, 249, 143, 144, 219, + 199, 95, 179, 41, 200, 178, 54, 131, 102, 74, 239, 224, 197, 158, + 218, 132, 23, 136, 178, 163, 15, 216, 48, 229, 171, 193, 48, 87, + 148, 11, 212, 34, 171, 154, 248, 5, 79, 136, 213, 169, 41, 36, + 40, 185, 54, 130, 132, 17, 50, 155, 150, 188, 225, 94, 141, 135, + 204, 198, 101, 128, 203, 104, 156, 218, 155, 229, 227, 240, 172, 255, + 130, 94, 144, 83, 67, 134, 1, 232, 178, 5, 129, 109, 151, 253, + 20, 68, 130, 208, 29, 65, 170, 25, 15, 19, 167, 114, 171, 210, + 241, 203, 200, 72, 7, 216, 123, 145, 180, 137, 33, 113, 179, 96, + 11, 211, 189, 194, 203, 87, 5, 80, 167, 114, 66, 178, 198, 136, + 99, 178, 48, 197, 121, 237, 247, 67, 242, 197, 250, 229, 226, 236, + 186, 218, 12, 223, 130, 174, 251, 187, 104, 39, 48, 126, 53, 147, + 15, 74, 245, 88, 79, 107, 204, 15, 103, 198, 56, 134, 153, 31, + 117, 91, 45, 186, 75, 215, 157, 148, 80, 195, 238, 176, 3, 116, + 193, 205, 118, 66, 209, 145, 53, 85, 234, 18, 35, 76, 131, 19, + 8, 177, 199, 96, 23, 28, 229, 93, 10, 69, 67, 193, 83, 80, + 250, 197, 16, 117, 7, 235, 234, 130, 31, 116, 35, 95, 110, 231, + 210, 190, 4, 172, 126, 128, 74, 137, 123, 51, 73, 90, 149, 79, + 103, 111, 125, 6, 19, 158, 40, 63, 34, 147, 71, 85, 64, 141, + 60, 74, 210, 130, 250, 180, 226, 195, 119, 99, 114, 182, 138, 74, + 176, 215, 218, 55, 9, 58, 234, 78, 129, 80, 111, 191, 66, 56, + 146, 17, 4, 161, 68, 154, 118, 201, 33, 2, 75, 85, 252, 109, + 40, 172, 144, 251, 40, 84, 169, 100, 25, 80, 158, 206, 225, 10, + 249, 161, 231, 240, 229, 20, 10, 248, 37, 248, 163, 112, 138, 164, + 215, 9, 222, 68, 134, 156, 181, 17, 152, 207, 216, 135, 176, 120, + 68, 194, 6, 157, 224, 87, 106, 72, 233, 227, 100, 130, 83, 103, + 193, 213, 18, 66, 95, 209, 221, 79, 231, 136, 201, 122, 32, 65, + 31, 72, 207, 20, 144, 221, 198, 203, 167, 28, 73, 18, 204, 2, + 255, 44, 226, 205, 51, 80, 56, 68, 58, 223, 204, 31, 80, 235, + 35, 44, 146, 249, 252, 120, 253, 214, 85, 221, 209, 219, 36, 160, + 221, 206, 200, 124, 228, 219, 145, 225, 151, 174, 53, 177, 115, 171, + 49, 96, 125, 237, 9, 195, 65, 83, 16, 175, 100, 86, 255, 18, + 189, 10, 104, 168, 251, 91, 50, 125, 224, 151, 185, 153, 232, 144, + 1, 24, 249, 145, 113, 92, 65, 104, 74, 104, 236, 78, 215, 117, + 153, 0, 166, 105, 231, 142, 219, 96, 232, 25, 95, 200, 35, 155, + 117, 36, 187, 56, 7, 234, 15, 167, 77, 246, 182, 7, 50, 70, + 199, 9, 19, 102, 126, 231, 21, 48, 245, 193, 184, 174, 245, 228, + 223, 85, 231, 148, 197, 231, 53, 240, 105, 195, 177, 13, 191, 138, + 138, 74, 229, 154, 11, 211, 239, 253, 41, 42, 76, 243, 137, 238, + 168, 94, 168, 246, 148, 128, 53, 206, 193, 130, 33, 190, 127, 191, + 101, 207, 191, 1, 25, 222, 182, 220, 52, 0, 85, 109, 57, 73, + 129, 194, 161, 86, 2, 127, 104, 80, 62, 224, 25, 119, 158, 9, + 253, 10, 155, 142, 118, 5, 150, 26, 111, 197, 160, 166, 6, 120, + 23, 198, 212, 34, 153, 249, 7, 223, 73, 56, 5, 124, 88, 164, + 7, 20, 215, 20, 67, 38, 28, 84, 125, 109, 199, 147, 234, 208, + 127, 107, 201, 197, 128, 22, 227, 155, 76, 132, 225, 222, 95, 214, + 229, 19, 45, 152, 236, 30, 178, 60, 10, 241, 137, 185, 183, 120, + 190, 5, 185, 3, 193, 229, 224, 255, 38, 111, 53, 231, 76, 0, + 216, 14, 219, 121, 94, 181, 220, 136, 93, 21, 176, 88, 250, 51, + 75, 153, 235, 161, 1, 133, 84, 64, 154, 236, 249, 169, 253, 2, + 76, 198, 21, 40, 214, 58, 166, 100, 117, 198, 121, 166, 72, 66, + 26, 213, 61, 187, 100, 73, 110, 147, 196, 96, 13, 239, 100, 118, + 56, 67, 10, 196, 63, 229, 175, 194, 230, 85, 231, 175, 107, 41, + 170, 109, 144, 38, 107, 165, 30, 123, 143, 154, 206, 40, 96, 199, + 181, 165, 211, 233, 61, 140, 166, 143, 190, 205, 8, 1, 143, 215, + 234, 8, 152, 115, 243, 33, 80, 172, 18, 37, 225, 60, 42, 200, + 186, 197, 254, 38, 22, 111, 93, 114, 195, 242, 225, 1, 105, 60, + 148, 98, 239, 213, 86, 137, 34, 121, 196, 154, 72, 198, 48, 30, + 210, 88, 47, 164, 80, 142, 42, 21, 74, 247, 62, 144, 44, 188, + 25, 0, 164, 166, 167, 72, 116, 133, 162, 117, 215, 13, 0, 243, + 136, 116, 151, 128, 72, 61, 104, 45, 23, 170, 236, 152, 98, 241, + 144, 216, 107, 207, 245, 227, 176, 221, 156, 197, 70, 86, 220, 128, + 167, 253, 174, 226, 17, 105, 243, 39, 50, 147, 171, 21, 59, 110, + 182, 185, 224, 194, 69, 126, 60, 152, 189, 5, 50, 91, 212, 166, + 236, 174, 67, 123, 9, 213, 230, 163, 113, 181, 191, 39, 24, 14, + 111, 155, 0, 152, 18, 142, 83, 204, 219, 239, 183, 178, 119, 215, + 59, 51, 246, 51, 5, 34, 48, 237, 181, 27, 94, 233, 100, 60, + 49, 98, 181, 89, 147, 111, 242, 119, 253, 50, 250, 18, 87, 167, + 34, 161, 35, 184, 159, 217, 80, 165, 145, 22, 163, 153, 26, 235, + 145, 234, 113, 123, 96, 108, 223, 89, 138, 129, 182, 23, 154, 27, + 114, 83, 115, 154, 211, 151, 140, 214, 205, 22, 70, 91, 141, 116, + 150, 159, 159, 70, 193, 46, 183, 68, 189, 128, 72, 4, 98, 127, + 212, 11, 1, 145, 230, 125, 1, 89, 177, 73, 94, 102, 21, 109, + 129, 119, 200, 241, 65, 68, 137, 163, 85, 143, 32, 249, 248, 231, + 179, 191, 87, 127, 161, 72, 148, 89, 148, 75, 166, 56, 117, 70, + 131, 114, 35, 49, 109, 155, 149, 24, 215, 105, 188, 197, 89, 34, + 72, 91, 217, 229, 152, 147, 183, 192, 114, 96, 34, 208, 249, 43, + 81, 52, 190, 150, 213, 80, 245, 96, 10, 168, 3, 107, 58, 255, + 143, 59, 196, 25, 20, 172, 33, 119, 82, 41, 106, 131, 216, 64, + 121, 61, 73, 78, 210, 39, 90, 71, 80, 239, 145, 255, 56, 51, + 221, 38, 125, 78, 59, 21, 10, 9, 153, 147, 181, 106, 212, 221, + 9, 50, 78, 222, 230, 31, 23, 27, 98, 231, 111, 14, 221, 254, + 106, 5, 160, 113, 75, 78, 78, 196, 58, 209, 184, 247, 63, 62, + 214, 38, 207, 109, 154, 245, 126, 162, 131, 238, 9, 187, 38, 188, + 27, 212, 196, 69, 240, 164, 71, 230, 57, 211, 163, 252, 102, 178, + 24, 145, 107, 81, 248, 47, 87, 84, 61, 227, 3, 72, 160, 108, + 148, 42, 205, 233, 65, 66, 100, 192, 110, 130, 54, 179, 185, 244, + 44, 180, 10, 99, 187, 236, 166, 93, 113, 28, 183, 93, 220, 152, + 54, 82, 208, 231, 205, 72, 51, 73, 248, 57, 102, 205, 219, 82, + 110, 165, 161, 194, 61, 215, 210, 213, 235, 134, 132, 64, 153, 88, + 119, 176, 55, 129, 246, 72, 71, 188, 187, 236, 24, 142, 48, 36, + 147, 86, 205, 211, 201, 204, 58, 131, 51, 82, 252, 206, 182, 63, + 55, 106, 217, 64, 154, 81, 68, 207, 80, 175, 23, 224, 200, 22, + 174, 162, 245, 43, 79, 17, 249, 150, 137, 81, 25, 41, 115, 53, + 154, 105, 205, 104, 152, 94, 67, 228, 111, 127, 83, 125, 18, 249, + 77, 70, 149, 189, 236, 213, 44, 251, 216, 247, 141, 165, 19, 42, + 201, 189, 79, 248, 240, 192, 9, 170, 8, 116, 48, 231, 242, 251, + 25, 129, 66, 84, 50, 128, 90, 37, 60, 2, 229, 242, 189, 147, + 158, 232, 81, 155, 137, 181, 121, 139, 135, 104, 157, 43, 104, 119, + 2, 50, 181, 63, 111, 0, 196, 24, 62, 85, 157, 208, 130, 58, + 56, 77, 19, 26, 171, 206, 74, 144, 120, 28, 116, 229, 40, 105, + 14, 69, 86, 225, 40, 11, 123, 162, 113, 35, 75, 198, 157, 229, + 60, 141, 107, 21, 9, 188, 198, 167, 113, 215, 253, 169, 30, 74, + 61, 129, 60, 207, 19, 213, 220, 187, 126, 61, 99, 223, 109, 27, + 79, 122, 235, 175, 212, 35, 171, 90, 162, 203, 222, 164, 225, 152, + 219, 121, 185, 79, 17, 251, 205, 239, 63, 104, 36, 136, 172, 163, + 167, 138, 43, 234, 57, 1, 254, 31, 90, 118, 147, 238, 4, 24, + 75, 70, 73, 175, 74, 153, 128, 57, 40, 243, 243, 235, 15, 41, + 115, 22, 109, 86, 99, 211, 213, 31, 5, 100, 118, 252, 9, 139, + 225, 188, 243, 236, 9, 203, 121, 50, 65, 25, 47, 217, 193, 64, + 5, 133, 30, 190, 63, 178, 124, 23, 216, 240, 28, 121, 107, 208, + 89, 82, 178, 82, 76, 5, 73, 16, 27, 41, 85, 183, 29, 70, + 77, 37, 191, 134, 58, 255, 132, 205, 68, 222, 79, 81, 64, 122, + 209, 239, 241, 141, 231, 86, 94, 239, 84, 206, 5, 206, 82, 100, + 26, 254, 1, 210, 31, 10, 182, 75, 36, 139, 78, 232, 125, 151, + 229, 82, 47, 159, 141, 194, 234, 171, 239, 219, 55, 78, 185, 124, + 86, 62, 3, 245, 231, 91, 237, 101, 210, 195, 56, 120, 242, 160, + 141, 66, 17, 231, 45, 22, 223, 9, 134, 180, 185, 17, 0, 178, + 155, 210, 221, 35, 45, 32, 140, 162, 228, 76, 73, 185, 185, 115, + 10, 167, 189, 255, 237, 55, 170, 100, 171, 191, 86, 246, 205, 215, + 134, 246, 218, 64, 197, 154, 224, 158, 210, 214, 196, 177, 230, 106, + 4, 255, 65, 64, 241, 217, 54, 129, 232, 103, 130, 163, 155, 212, + 201, 181, 3, 20, 206, 129, 194, 47, 1, 7, 229, 153, 158, 141, + 190, 58, 127, 126, 6, 57, 227, 130, 103, 222, 20, 151, 181, 107, + 82, 244, 249, 92, 99, 200, 203, 244, 222, 73, 154, 247, 195, 148, + 172, 70, 216, 34, 78, 137, 82, 220, 198, 215, 48, 113, 201, 253, + 84, 207, 33, 242, 255, 51, 15, 179, 126, 254, 90, 57, 31, 238, + 169, 217, 174, 147, 10, 11, 166, 70, 26, 82, 218, 177, 77, 25, + 194, 209, 48, 149, 160, 147, 6, 84, 93, 174, 66, 186, 161, 200, + 167, 160, 13, 50, 164, 174, 58, 255, 132, 6, 84, 27, 216, 144, + 110, 155, 197, 244, 123, 69, 4, 116, 35, 144, 73, 7, 125, 223, + 26, 176, 201, 160, 17, 206, 159, 203, 26, 140, 217, 53, 81, 201, + 175, 113, 97, 111, 7, 66, 118, 196, 132, 15, 89, 127, 70, 114, + 144, 191, 182, 27, 113, 13, 218, 108, 92, 239, 77, 143, 19, 176, + 8, 183, 116, 21, 35, 12, 112, 41, 77, 232, 235, 92, 141, 45, + 39, 162, 91, 246, 174, 35, 62, 237, 78, 204, 227, 112, 11, 130, + 10, 149, 222, 77, 196, 26, 250, 60, 238, 162, 32, 91, 180, 16, + 179, 225, 49, 142, 2, 106, 42, 151, 211, 183, 92, 118, 245, 242, + 94, 97, 120, 26, 84, 247, 138, 75, 228, 52, 8, 199, 194, 4, + 188, 171, 94, 125, 255, 198, 91, 202, 82, 182, 144, 242, 126, 175, + 4, 110, 4, 127, 4, 63, 77, 120, 14, 104, 151, 12, 6, 106, + 255, 85, 142, 40, 16, 40, 199, 227, 152, 64, 103, 138, 40, 78, + 80, 38, 28, 181, 1, 73, 15, 32, 133, 154, 137, 0, 190, 165, + 133, 230, 216, 255, 162, 201, 91, 234, 26, 13, 238, 98, 3, 243, + 169, 0, 0, 161, 83, 72, 66, 193, 150, 95, 103, 184, 123, 125, + 138, 59, 59, 28, 172, 90, 237, 138, 138, 46, 241, 228, 103, 47, + 23, 161, 57, 21, 197, 214, 86, 242, 107, 64, 121, 83, 141, 252, + 105, 147, 64, 133, 111, 33, 173, 174, 204, 222, 246, 31, 241, 214, + 252, 242, 254, 22, 44, 209, 183, 183, 113, 33, 164, 78, 93, 111, + 58, 208, 145, 103, 124, 49, 129, 19, 158, 163, 156, 31, 77, 128, + 229, 244, 24, 232, 255, 34, 238, 179, 186, 198, 33, 86, 222, 21, + 129, 162, 217, 128, 140, 150, 10, 142, 34, 40, 188, 177, 116, 133, + 92, 186, 80, 168, 166, 144, 109, 193, 180, 36, 183, 238, 108, 156, + 163, 154, 230, 34, 186, 24, 181, 133, 247, 204, 217, 179, 137, 150, + 224, 66, 221, 155, 51, 36, 230, 196, 35, 239, 6, 129, 203, 5, + 142, 67, 6, 183, 148, 65, 201, 41, 238, 63, 35, 86, 124, 224, + 226, 1, 239, 226, 184, 83, 116, 124, 166, 63, 18, 24, 162, 77, + 27, 59, 36, 2, 201, 255, 62, 147, 86, 166, 144, 102, 27, 85, + 142, 184, 116, 82, 154, 182, 240, 49, 7, 230, 146, 221, 3, 158, + 153, 184, 242, 235, 144, 141, 145, 178, 69, 17, 92, 112, 214, 145, + 45, 53, 18, 198, 106, 125, 229, 24, 4, 122, 72, 213, 131, 224, + 22, 116, 143, 123, 27, 4, 59, 206, 72, 216, 164, 140, 220, 94, + 209, 118, 83, 223, 247, 168, 236, 48, 97, 129, 13, 190, 243, 192, + 130, 85, 206, 124, 185, 101, 36, 89, 210, 75, 242, 246, 200, 57, + 74, 86, 3, 193, 164, 175, 187, 81, 109, 171, 184, 37, 118, 183, + 215, 176, 56, 151, 174, 154, 126, 113, 185, 109, 232, 253, 49, 25, + 193, 69, 156, 91, 35, 0, 56, 169, 24, 20, 184, 136, 244, 127, + 3, 12, 245, 64, 187, 69, 158, 76, 19, 181, 7, 177, 24, 141, + 174, 109, 142, 255, 17, 158, 206, 63, 3, 173, 107, 48, 171, 9, + 57, 24, 15, 126, 97, 85, 92, 255, 1, 139, 151, 144, 33, 9, + 147, 53, 66, 108, 215, 146, 225, 206, 73, 169, 249, 71, 108, 197, + 46, 62, 12, 230, 245, 126, 122, 173, 47, 169, 137, 106, 180, 117, + 6, 202, 204, 166, 235, 181, 158, 194, 82, 27, 167, 53, 114, 170, + 64, 119, 48, 244, 57, 9, 136, 246, 166, 236, 167, 22, 75, 252, + 239, 233, 237, 153, 106, 59, 142, 74, 189, 130, 247, 254, 40, 88, + 195, 63, 83, 153, 131, 206, 194, 36, 140, 79, 71, 153, 240, 185, + 70, 90, 39, 197, 63, 52, 168, 81, 112, 20, 122, 207, 223, 110, + 95, 230, 105, 70, 18, 200, 56, 110, 49, 122, 239, 86, 253, 32, + 136, 16, 77, 163, 132, 228, 131, 109, 39, 237, 59, 178, 19, 225, + 150, 64, 34, 74, 81, 139, 243, 120, 192, 185, 212, 107, 193, 238, + 112, 228, 167, 40, 230, 143, 189, 70, 254, 252, 55, 249, 177, 132, + 185, 138, 141, 1, 165, 215, 201, 168, 221, 144, 133, 84, 227, 182, + 15, 187, 68, 137, 227, 141, 212, 165, 194, 169, 35, 70, 18, 159, + 224, 31, 217, 221, 129, 124, 117, 224, 67, 72, 206, 66, 132, 249, + 144, 5, 194, 92, 100, 251, 143, 91, 168, 240, 110, 170, 172, 33, + 244, 245, 170, 109, 106, 124, 217, 23, 202, 142, 15, 151, 58, 143, + 44, 62, 62, 26, 69, 241, 118, 168, 246, 201, 202, 208, 9, 182, + 221, 191, 238, 143, 189, 219, 234, 17, 220, 11, 239, 1, 205, 136, + 32, 99, 234, 255, 130, 105, 155, 111, 218, 150, 163, 186, 36, 150, + 58, 37, 216, 25, 104, 58, 144, 170, 247, 136, 177, 194, 185, 47, + 52, 168, 30, 165, 24, 12, 244, 120, 64, 84, 144, 140, 207, 117, + 104, 223, 5, 51, 200, 140, 44, 143, 75, 34, 169, 48, 60, 201, + 39, 102, 62, 74, 228, 114, 144, 229, 197, 116, 231, 28, 118, 104, + 188, 210, 146, 17, 248, 48, 248, 44, 188, 143, 180, 60, 89, 246, + 190, 244, 246, 213, 7, 183, 232, 189, 127, 42, 32, 247, 42, 199, + 76, 65, 229, 162, 244, 115, 167, 251, 9, 25, 89, 18, 89, 138, + 236, 33, 245, 240, 100, 203, 191, 210, 149, 3, 217, 78, 174, 97, + 155, 149, 250, 56, 120, 29, 176, 164, 24, 107, 143, 150, 38, 127, + 113, 28, 58, 210, 165, 149, 12, 135, 135, 135, 80, 102, 182, 205, + 122, 183, 157, 107, 122, 202, 222, 17, 167, 215, 237, 157, 125, 142, + 170, 128, 138, 227, 175, 15, 197, 222, 245, 17, 84, 243, 255, 212, + 60, 6, 20, 174, 95, 131, 77, 42, 182, 162, 30, 187, 172, 206, + 105, 119, 93, 166, 203, 104, 114, 41, 225, 155, 106, 150, 227, 93, + 100, 42, 47, 33, 21, 201, 132, 38, 19, 69, 147, 246, 23, 171, + 20, 104, 220, 132, 254, 15, 53, 164, 122, 207, 130, 208, 133, 134, + 145, 32, 124, 128, 93, 186, 145, 104, 121, 99, 173, 20, 205, 29, + 157, 91, 186, 196, 142, 170, 12, 240, 108, 5, 86, 78, 207, 77, + 231, 196, 79, 48, 76, 20, 27, 211, 16, 80, 114, 223, 207, 5, + 128, 239, 225, 125, 39, 171, 153, 128, 141, 111, 188, 146, 24, 210, + 7, 173, 11, 81, 39, 106, 254, 159, 137, 74, 120, 109, 159, 100, + 22, 164, 36, 150, 156, 123, 183, 70, 50, 4, 233, 33, 21, 208, + 232, 206, 137, 221, 44, 5, 8, 17, 22, 200, 6, 103, 160, 55, + 187, 69, 165, 90, 13, 193, 20, 36, 35, 60, 173, 119, 238, 251, + 220, 73, 168, 92, 184, 199, 37, 218, 143, 237, 1, 203, 82, 106, + 207, 201, 168, 162, 19, 68, 182, 196, 208, 17, 2, 33, 16, 190, + 58, 230, 162, 239, 59, 104, 16, 75, 190, 122, 136, 118, 6, 239, + 192, 225, 89, 62, 78, 10, 154, 130, 137, 120, 178, 179, 66, 175, + 88, 107, 175, 239, 11, 137, 136, 143, 145, 0, 90, 164, 179, 63, + 98, 142, 155, 121, 251, 33, 170, 96, 84, 63, 52, 112, 176, 171, + 12, 250, 42, 128, 200, 81, 105, 10, 174, 175, 74, 158, 111, 229, + 174, 26, 9, 216, 68, 119, 39, 112, 204, 139, 113, 33, 119, 24, + 7, 95, 14, 77, 122, 209, 31, 27, 64, 9, 176, 162, 81, 50, + 183, 171, 48, 211, 161, 210, 74, 20, 12, 198, 241, 246, 146, 176, + 181, 82, 215, 22, 86, 240, 198, 176, 211, 114, 62, 108, 237, 83, + 227, 103, 135, 75, 7, 13, 16, 87, 132, 107, 118, 97, 101, 50, + 183, 96, 238, 65, 94, 92, 168, 44, 53, 58, 45, 196, 147, 78, + 71, 246, 196, 129, 85, 169, 46, 145, 196, 120, 233, 235, 99, 7, + 103, 3, 178, 157, 13, 153, 124, 179, 187, 215, 22, 111, 44, 6, + 163, 122, 55, 54, 134, 52, 214, 156, 31, 210, 88, 83, 95, 141, + 244, 85, 191, 168, 172, 202, 196, 92, 206, 145, 52, 225, 32, 248, + 220, 201, 236, 116, 121, 53, 254, 154, 154, 95, 44, 95, 35, 162, + 226, 222, 161, 167, 252, 7, 194, 230, 251, 74, 148, 144, 55, 179, + 228, 137, 232, 78, 30, 133, 207, 229, 110, 19, 135, 143, 25, 222, + 47, 217, 168, 39, 30, 153, 69, 247, 167, 29, 152, 159, 219, 152, + 59, 107, 59, 51, 187, 236, 38, 176, 215, 133, 233, 164, 134, 100, + 178, 142, 108, 71, 148, 176, 36, 145, 103, 127, 153, 140, 106, 187, + 156, 160, 72, 167, 253, 221, 91, 203, 133, 63, 191, 103, 171, 194, + 41, 209, 89, 90, 117, 118, 193, 219, 54, 43, 166, 11, 18, 211, + 147, 176, 209, 125, 149, 132, 20, 86, 175, 156, 78, 155, 57, 225, + 239, 206, 133, 50, 88, 217, 189, 85, 45, 233, 184, 176, 83, 99, + 186, 181, 57, 114, 168, 152, 230, 241, 174, 24, 216, 174, 138, 241, + 103, 233, 50, 116, 136, 158, 190, 14, 18, 63, 148, 184, 9, 46, + 223, 152, 191, 30, 74, 248, 147, 25, 246, 176, 69, 81, 89, 41, + 190, 180, 20, 133, 42, 0, 164, 69, 237, 163, 200, 5, 48, 251, + 8, 183, 189, 109, 202, 250, 237, 205, 47, 212, 177, 35, 65, 200, + 90, 61, 227, 132, 234, 135, 18, 44, 179, 171, 92, 134, 79, 186, + 145, 216, 212, 129, 88, 129, 180, 33, 100, 207, 249, 46, 41, 162, + 249, 68, 171, 95, 8, 171, 52, 57, 123, 83, 35, 169, 117, 74, + 14, 152, 195, 143, 214, 55, 47, 214, 20, 179, 16, 115, 69, 55, + 218, 108, 117, 75, 136, 246, 186, 132, 96, 58, 128, 17, 15, 164, + 158, 63, 123, 127, 59, 141, 19, 231, 9, 240, 153, 20, 3, 156, + 52, 213, 67, 246, 207, 208, 222, 59, 65, 53, 67, 150, 243, 113, + 48, 192, 228, 136, 78, 2, 165, 219, 37, 228, 182, 202, 78, 70, + 252, 185, 103, 42, 123, 226, 5, 0, 48, 77, 186, 104, 36, 221, + 227, 248, 70, 207, 232, 25, 17, 209, 129, 88, 49, 84, 8, 60, + 191, 125, 67, 17, 209, 223, 177, 93, 122, 61, 195, 110, 117, 192, + 140, 146, 94, 5, 135, 161, 204, 231, 78, 3, 1, 31, 235, 106, + 186, 227, 175, 79, 253, 110, 45, 27, 236, 5, 35, 50, 157, 5, + 49, 11, 78, 18, 227, 212, 31, 170, 82, 212, 21, 60, 148, 194, + 10, 109, 172, 240, 93, 9, 255, 37, 37, 28, 136, 189, 153, 173, + 25, 113, 251, 2, 68, 5, 114, 187, 152, 95, 14, 141, 24, 232, + 49, 97, 197, 163, 87, 50, 84, 233, 204, 253, 250, 117, 3, 64, + 159, 22, 9, 245, 203, 16, 17, 150, 135, 157, 71, 24, 238, 68, + 40, 6, 234, 177, 119, 6, 130, 78, 145, 49, 21, 29, 146, 138, + 141, 227, 152, 12, 155, 71, 223, 161, 102, 2, 151, 24, 67, 68, + 90, 67, 9, 186, 193, 206, 85, 207, 125, 120, 222, 68, 220, 54, + 220, 253, 111, 5, 57, 21, 141, 51, 5, 162, 244, 173, 201, 93, + 230, 194, 45, 245, 134, 39, 57, 111, 231, 150, 52, 223, 169, 227, + 47, 103, 246, 18, 135, 189, 211, 254, 97, 103, 49, 234, 102, 63, + 215, 149, 156, 109, 73, 16, 232, 110, 225, 144, 165, 107, 103, 118, + 158, 35, 38, 51, 247, 111, 197, 238, 183, 75, 234, 215, 105, 90, + 181, 52, 18, 231, 99, 77, 155, 150, 30, 56, 250, 185, 39, 182, + 213, 248, 217, 252, 75, 165, 232, 155, 91, 251, 81, 120, 164, 103, + 161, 182, 96, 1, 144, 233, 216, 220, 111, 145, 56, 245, 120, 142, + 224, 56, 164, 145, 201, 19, 106, 160, 223, 128, 177, 186, 114, 159, + 224, 161, 74, 56, 93, 191, 18, 54, 202, 85, 153, 95, 47, 21, + 176, 157, 19, 146, 70, 254, 224, 122, 229, 58, 28, 126, 56, 128, + 255, 100, 23, 222, 182, 104, 184, 252, 36, 252, 156, 35, 213, 226, + 80, 240, 194, 226, 79, 220, 205, 125, 51, 88, 128, 134, 87, 42, + 211, 75, 237, 1, 166, 108, 74, 121, 254, 81, 32, 255, 49, 73, + 64, 166, 128, 57, 28, 71, 72, 75, 220, 231, 91, 235, 217, 214, + 68, 87, 222, 226, 76, 56, 187, 185, 108, 164, 137, 226, 219, 20, + 169, 194, 228, 40, 30, 86, 90, 221, 25, 98, 199, 119, 66, 168, + 192, 17, 53, 111, 33, 39, 181, 108, 241, 248, 195, 131, 138, 182, + 225, 73, 6, 55, 124, 90, 108, 19, 71, 121, 73, 200, 134, 79, + 73, 135, 134, 186, 190, 125, 211, 191, 107, 168, 108, 195, 106, 74, + 217, 211, 11, 234, 36, 149, 190, 109, 223, 124, 113, 6, 70, 222, + 111, 35, 20, 170, 254, 23, 100, 31, 143, 153, 105, 206, 77, 19, + 240, 225, 181, 201, 214, 213, 86, 85, 9, 51, 252, 75, 114, 144, + 200, 52, 38, 63, 219, 9, 22, 189, 22, 36, 7, 207, 0, 35, + 249, 129, 108, 55, 217, 130, 38, 52, 58, 41, 232, 233, 236, 17, + 154, 39, 21, 77, 163, 38, 80, 72, 204, 118, 139, 184, 241, 58, + 160, 149, 150, 97, 228, 183, 104, 45, 15, 183, 9, 126, 197, 93, + 196, 74, 137, 42, 205, 118, 249, 215, 212, 193, 89, 157, 167, 62, + 56, 186, 48, 62, 219, 190, 156, 151, 115, 88, 213, 117, 109, 218, + 87, 97, 233, 218, 2, 9, 251, 135, 183, 75, 29, 39, 133, 195, + 120, 196, 95, 112, 103, 179, 198, 199, 206, 187, 90, 23, 80, 147, + 94, 36, 24, 141, 100, 81, 181, 253, 44, 75, 189, 87, 200, 92, + 116, 131, 17, 201, 203, 128, 239, 15, 6, 143, 163, 119, 219, 45, + 254, 193, 119, 143, 85, 27, 199, 34, 147, 60, 143, 165, 10, 53, + 32, 41, 88, 250, 135, 205, 212, 172, 113, 78, 106, 132, 114, 84, + 118, 60, 204, 91, 141, 183, 165, 173, 11, 68, 165, 196, 213, 10, + 84, 68, 136, 28, 211, 35, 67, 180, 47, 41, 93, 233, 61, 35, + 102, 81, 114, 168, 43, 236, 158, 142, 151, 238, 241, 211, 246, 205, + 52, 143, 120, 135, 28, 222, 161, 219, 40, 32, 181, 61, 133, 239, + 79, 20, 110, 204, 78, 130, 212, 207, 142, 111, 123, 91, 17, 64, + 27, 118, 39, 111, 112, 122, 174, 107, 191, 205, 113, 58, 229, 243, + 58, 238, 29, 27, 196, 71, 226, 188, 163, 224, 40, 34, 188, 65, + 109, 233, 106, 179, 141, 15, 7, 246, 75, 174, 93, 83, 82, 60, + 51, 89, 153, 247, 208, 2, 3, 41, 49, 171, 130, 174, 221, 11, + 218, 169, 5, 141, 142, 34, 127, 203, 170, 29, 145, 0, 154, 81, + 32, 29, 247, 121, 77, 116, 120, 147, 127, 177, 241, 195, 248, 40, + 73, 60, 80, 240, 68, 142, 44, 181, 45, 59, 228, 221, 78, 58, + 120, 151, 224, 24, 153, 242, 189, 117, 242, 241, 49, 149, 82, 5, + 116, 175, 69, 53, 1, 153, 1, 123, 24, 12, 186, 198, 130, 48, + 18, 143, 65, 126, 115, 18, 10, 223, 217, 63, 39, 228, 135, 164, + 193, 217, 12, 219, 172, 69, 77, 108, 205, 77, 56, 159, 220, 117, + 198, 13, 198, 59, 144, 161, 216, 23, 151, 70, 133, 65, 174, 236, + 13, 232, 197, 56, 87, 79, 113, 86, 72, 50, 50, 113, 61, 208, + 96, 163, 135, 184, 228, 202, 61, 142, 91, 182, 42, 156, 108, 241, + 139, 161, 140, 68, 57, 58, 155, 178, 251, 130, 177, 209, 226, 226, + 236, 183, 47, 94, 183, 231, 163, 114, 153, 198, 109, 163, 60, 235, + 225, 91, 73, 18, 93, 47, 81, 19, 102, 50, 169, 91, 39, 235, + 79, 158, 38, 187, 89, 160, 201, 245, 19, 202, 226, 112, 171, 228, + 107, 206, 237, 50, 93, 77, 217, 57, 221, 176, 134, 233, 109, 98, + 194, 66, 54, 130, 143, 133, 98, 78, 124, 50, 217, 29, 71, 98, + 140, 16, 64, 252, 41, 161, 61, 212, 8, 113, 78, 142, 124, 1, + 110, 39, 33, 115, 156, 184, 170, 24, 181, 211, 9, 91, 84, 120, + 215, 199, 158, 166, 201, 94, 9, 17, 96, 146, 22, 108, 144, 118, + 106, 202, 125, 148, 106, 44, 80, 72, 48, 240, 58, 234, 129, 94, + 34, 217, 161, 192, 125, 51, 85, 151, 170, 215, 242, 45, 83, 232, + 100, 16, 146, 90, 10, 44, 48, 149, 42, 77, 217, 34, 29, 24, + 30, 23, 245, 93, 221, 112, 144, 149, 251, 94, 193, 225, 111, 32, + 104, 115, 249, 129, 117, 5, 198, 201, 159, 5, 144, 171, 68, 20, + 30, 174, 254, 61, 109, 161, 100, 96, 134, 121, 116, 209, 212, 173, + 221, 35, 254, 17, 71, 71, 235, 60, 242, 77, 107, 253, 64, 43, + 122, 117, 125, 173, 187, 92, 254, 131, 185, 181, 111, 64, 176, 144, + 218, 23, 128, 126, 77, 148, 97, 29, 242, 157, 101, 194, 193, 99, + 205, 108, 108, 247, 171, 202, 148, 27, 25, 221, 211, 99, 79, 88, + 5, 254, 136, 125, 136, 125, 209, 189, 48, 160, 91, 212, 41, 102, + 26, 115, 71, 104, 127, 14, 192, 233, 78, 38, 187, 155, 163, 57, + 160, 30, 230, 252, 91, 31, 121, 33, 118, 180, 58, 193, 250, 145, + 159, 35, 162, 114, 127, 179, 7, 178, 134, 78, 222, 136, 59, 7, + 220, 178, 198, 162, 218, 162, 242, 131, 181, 113, 110, 57, 22, 159, + 141, 193, 212, 6, 65, 138, 59, 21, 206, 17, 112, 21, 183, 218, + 164, 40, 101, 117, 75, 162, 120, 254, 133, 241, 42, 34, 251, 234, + 181, 83, 236, 147, 18, 12, 190, 246, 7, 109, 238, 213, 193, 120, + 192, 32, 232, 205, 49, 120, 5, 184, 131, 184, 36, 49, 76, 124, + 156, 58, 71, 185, 69, 134, 93, 55, 126, 117, 128, 206, 106, 112, + 90, 104, 68, 227, 104, 81, 207, 79, 71, 248, 178, 5, 71, 162, + 164, 187, 122, 20, 72, 57, 143, 52, 94, 165, 109, 159, 36, 249, + 48, 230, 15, 253, 31, 164, 196, 192, 253, 223, 52, 182, 221, 34, + 162, 59, 65, 143, 241, 105, 238, 78, 18, 203, 248, 27, 81, 253, + 159, 134, 37, 58, 219, 55, 250, 242, 221, 149, 66, 149, 185, 48, + 215, 208, 204, 110, 250, 104, 216, 111, 1, 142, 245, 253, 161, 224, + 85, 4, 28, 145, 90, 182, 104, 153, 4, 213, 116, 64, 244, 194, + 74, 8, 18, 203, 241, 74, 25, 130, 34, 122, 50, 58, 39, 80, + 4, 39, 164, 132, 229, 18, 81, 143, 28, 145, 9, 73, 244, 121, + 12, 236, 225, 67, 101, 107, 0, 205, 33, 142, 96, 138, 135, 233, + 172, 211, 33, 252, 57, 56, 135, 51, 202, 224, 194, 77, 15, 209, + 153, 104, 101, 112, 45, 3, 1, 239, 171, 69, 246, 146, 124, 124, + 62, 151, 163, 77, 62, 165, 118, 198, 176, 117, 141, 73, 243, 96, + 131, 195, 35, 120, 79, 89, 108, 89, 161, 59, 58, 172, 241, 27, + 63, 221, 246, 67, 18, 150, 169, 178, 95, 58, 29, 159, 126, 70, + 37, 37, 24, 240, 89, 23, 147, 177, 147, 3, 205, 69, 68, 253, + 55, 16, 58, 176, 152, 223, 80, 12, 176, 6, 170, 106, 125, 68, + 156, 149, 87, 159, 21, 223, 138, 55, 156, 34, 25, 49, 114, 68, + 141, 203, 194, 94, 54, 200, 206, 160, 2, 207, 244, 10, 236, 211, + 165, 249, 88, 168, 64, 133, 251, 201, 34, 34, 146, 32, 227, 56, + 166, 85, 36, 124, 80, 154, 21, 91, 150, 153, 178, 53, 105, 139, + 104, 200, 22, 101, 126, 112, 33, 149, 1, 229, 12, 23, 106, 239, + 177, 35, 10, 169, 242, 103, 104, 128, 55, 141, 71, 41, 22, 202, + 67, 1, 159, 98, 172, 111, 186, 33, 206, 62, 216, 49, 234, 141, + 2, 185, 85, 139, 46, 84, 238, 111, 116, 207, 233, 228, 60, 194, + 96, 249, 229, 224, 156, 227, 133, 87, 50, 221, 125, 200, 106, 221, + 84, 87, 95, 224, 251, 196, 72, 64, 169, 23, 17, 63, 246, 226, + 143, 169, 67, 97, 177, 133, 13, 240, 95, 53, 107, 186, 119, 52, + 237, 250, 145, 21, 107, 14, 94, 12, 134, 144, 56, 145, 32, 79, + 78, 190, 145, 96, 110, 177, 92, 245, 96, 164, 236, 173, 3, 219, + 27, 111, 110, 178, 199, 242, 236, 149, 122, 153, 234, 183, 66, 61, + 170, 85, 93, 206, 86, 107, 166, 225, 8, 98, 187, 173, 39, 159, + 147, 86, 18, 97, 6, 167, 140, 215, 219, 52, 229, 65, 78, 195, + 31, 25, 201, 100, 3, 225, 42, 27, 147, 44, 82, 132, 175, 247, + 3, 26, 130, 255, 94, 70, 96, 106, 141, 82, 184, 69, 21, 157, + 116, 76, 224, 18, 127, 134, 187, 155, 32, 21, 54, 149, 42, 195, + 249, 21, 247, 183, 47, 193, 184, 187, 227, 99, 21, 231, 172, 158, + 139, 216, 208, 17, 229, 145, 233, 46, 136, 191, 14, 138, 233, 168, + 5, 198, 216, 49, 168, 206, 255, 195, 220, 9, 60, 100, 133, 125, + 158, 251, 210, 137, 173, 15, 253, 209, 101, 98, 198, 214, 218, 254, + 136, 178, 181, 80, 117, 243, 136, 227, 25, 52, 179, 2, 255, 179, + 33, 150, 219, 60, 211, 218, 58, 181, 10, 158, 24, 83, 80, 52, + 168, 28, 211, 209, 34, 250, 179, 84, 160, 121, 174, 16, 100, 213, + 223, 214, 111, 38, 42, 33, 185, 203, 84, 22, 186, 166, 226, 148, + 198, 125, 105, 146, 208, 175, 35, 157, 49, 92, 29, 180, 48, 247, + 186, 122, 247, 166, 104, 233, 167, 29, 249, 155, 48, 59, 143, 177, + 10, 81, 234, 238, 224, 234, 10, 145, 134, 98, 1, 224, 135, 231, + 47, 28, 50, 239, 108, 19, 49, 129, 214, 210, 58, 44, 180, 100, + 47, 255, 238, 211, 58, 230, 80, 203, 152, 21, 40, 45, 99, 35, + 102, 7, 220, 155, 116, 37, 121, 162, 190, 135, 5, 15, 138, 232, + 234, 7, 45, 159, 55, 88, 233, 171, 35, 209, 65, 222, 59, 231, + 85, 84, 173, 127, 232, 177, 254, 115, 210, 13, 202, 229, 185, 5, + 96, 212, 252, 94, 104, 202, 64, 71, 70, 23, 124, 165, 202, 234, + 144, 209, 185, 185, 143, 10, 54, 176, 94, 255, 229, 73, 46, 1, + 192, 77, 201, 122, 133, 81, 165, 238, 144, 83, 20, 1, 113, 8, + 183, 86, 131, 44, 137, 21, 208, 192, 227, 166, 77, 186, 92, 251, + 122, 204, 31, 4, 56, 132, 34, 35, 222, 86, 211, 6, 177, 110, + 132, 248, 245, 213, 253, 73, 166, 80, 42, 249, 41, 65, 183, 250, + 197, 98, 155, 5, 205, 113, 76, 74, 77, 73, 217, 114, 217, 42, + 39, 231, 188, 190, 156, 173, 209, 19, 161, 220, 81, 196, 249, 60, + 85, 213, 221, 22, 171, 232, 238, 150, 252, 209, 144, 140, 166, 35, + 253, 68, 89, 199, 135, 231, 33, 128, 126, 93, 140, 106, 149, 82, + 89, 161, 65, 156, 140, 80, 245, 74, 114, 152, 217, 252, 219, 43, + 11, 242, 198, 95, 187, 95, 30, 123, 168, 13, 115, 74, 109, 249, + 154, 52, 104, 192, 249, 69, 49, 137, 162, 128, 165, 73, 214, 41, + 191, 60, 173, 238, 126, 140, 149, 100, 33, 80, 177, 224, 27, 123, + 229, 0, 147, 5, 229, 182, 62, 210, 183, 230, 166, 123, 78, 150, + 26, 255, 206, 109, 219, 60, 168, 238, 136, 75, 83, 64, 113, 221, + 113, 5, 40, 108, 236, 174, 145, 132, 193, 227, 133, 33, 105, 14, + 227, 49, 243, 176, 27, 87, 106, 57, 15, 236, 65, 153, 174, 78, + 75, 35, 70, 126, 167, 239, 82, 254, 185, 44, 57, 201, 237, 214, + 125, 118, 84, 37, 83, 107, 66, 162, 223, 220, 101, 149, 103, 108, + 85, 185, 213, 244, 136, 148, 172, 180, 201, 172, 21, 195, 243, 118, + 79, 0, 236, 170, 114, 214, 54, 174, 150, 146, 86, 220, 175, 7, + 82, 0, 151, 58, 160, 47, 81, 204, 165, 63, 81, 58, 6, 2, + 189, 119, 155, 211, 119, 75, 151, 58, 236, 30, 222, 106, 65, 131, + 129, 207, 50, 104, 208, 110, 220, 156, 150, 31, 202, 154, 110, 135, + 152, 62, 212, 92, 246, 174, 186, 163, 5, 166, 86, 167, 236, 80, + 172, 230, 125, 108, 168, 89, 229, 242, 237, 28, 47, 224, 158, 10, + 249, 164, 165, 117, 134, 1, 244, 228, 229, 1, 208, 2, 197, 169, + 86, 6, 73, 25, 229, 201, 156, 246, 42, 116, 250, 146, 82, 229, + 55, 75, 104, 17, 49, 128, 140, 104, 207, 190, 26, 100, 183, 95, + 14, 214, 118, 27, 82, 29, 89, 214, 47, 23, 182, 213, 10, 163, + 219, 216, 241, 41, 217, 133, 161, 63, 49, 191, 202, 181, 143, 98, + 31, 65, 100, 139, 178, 77, 252, 188, 174, 233, 48, 187, 245, 126, + 39, 89, 179, 146, 186, 138, 255, 231, 180, 30, 204, 76, 146, 177, + 149, 15, 128, 87, 101, 23, 26, 4, 167, 165, 173, 49, 227, 238, + 66, 199, 11, 70, 204, 241, 111, 59, 123, 101, 107, 137, 174, 163, + 165, 195, 149, 63, 182, 102, 102, 29, 107, 82, 31, 69, 110, 153, + 225, 189, 28, 108, 246, 246, 97, 140, 55, 93, 30, 195, 157, 251, + 253, 77, 78, 70, 115, 50, 102, 237, 182, 158, 224, 240, 26, 246, + 223, 195, 168, 75, 56, 93, 37, 155, 125, 236, 56, 244, 180, 27, + 29, 183, 51, 231, 172, 78, 175, 31, 49, 253, 40, 137, 3, 77, + 50, 79, 143, 5, 74, 247, 155, 98, 180, 61, 21, 112, 41, 213, + 70, 96, 141, 118, 53, 112, 185, 164, 119, 124, 40, 168, 45, 162, + 115, 245, 131, 118, 41, 114, 93, 36, 19, 253, 35, 57, 171, 1, + 237, 8, 209, 230, 160, 108, 110, 206, 204, 1, 46, 209, 192, 37, + 58, 219, 240, 240, 70, 146, 99, 108, 215, 28, 229, 236, 105, 249, + 123, 24, 213, 243, 122, 252, 122, 237, 235, 9, 223, 176, 185, 86, + 72, 135, 17, 220, 112, 172, 244, 169, 97, 3, 4, 46, 125, 249, + 253, 188, 174, 194, 15, 133, 15, 54, 47, 111, 20, 206, 104, 151, + 66, 144, 0, 53, 96, 210, 192, 27, 50, 220, 15, 169, 176, 0, + 197, 102, 114, 147, 62, 211, 4, 172, 2, 181, 8, 79, 82, 219, + 77, 49, 125, 25, 178, 1, 14, 51, 147, 52, 234, 248, 8, 51, + 104, 42, 33, 0, 195, 77, 69, 146, 118, 191, 45, 143, 37, 2, + 237, 140, 239, 188, 108, 75, 253, 104, 252, 181, 207, 194, 24, 230, + 133, 245, 27, 148, 127, 195, 234, 130, 186, 236, 24, 52, 6, 231, + 219, 43, 95, 93, 243, 21, 226, 149, 201, 235, 255, 115, 18, 5, + 66, 234, 37, 104, 237, 191, 66, 100, 234, 72, 248, 129, 151, 92, + 38, 182, 166, 22, 66, 93, 128, 15, 53, 133, 107, 109, 32, 29, + 115, 159, 218, 191, 217, 63, 176, 3, 17, 44, 201, 230, 159, 68, + 200, 135, 153, 164, 97, 234, 71, 115, 223, 216, 38, 170, 68, 59, + 107, 115, 232, 13, 121, 206, 92, 67, 174, 108, 252, 183, 106, 44, + 29, 40, 197, 126, 34, 203, 53, 184, 101, 182, 170, 113, 222, 122, + 105, 61, 55, 48, 118, 20, 255, 136, 6, 0, 194, 127, 153, 236, + 50, 193, 184, 164, 120, 253, 38, 94, 162, 241, 251, 229, 104, 10, + 64, 19, 134, 155, 4, 255, 58, 106, 97, 52, 134, 152, 113, 85, + 158, 209, 159, 64, 129, 54, 157, 120, 127, 237, 112, 176, 67, 29, + 53, 217, 126, 119, 166, 71, 243, 152, 127, 191, 192, 104, 155, 228, + 181, 247, 32, 86, 58, 77, 109, 222, 95, 142, 226, 110, 175, 153, + 67, 205, 148, 153, 32, 5, 121, 121, 169, 138, 74, 20, 244, 240, + 27, 204, 113, 202, 74, 229, 122, 186, 212, 192, 86, 20, 248, 243, + 116, 190, 91, 30, 144, 179, 240, 161, 222, 228, 142, 253, 121, 179, + 113, 173, 75, 41, 101, 126, 36, 171, 83, 192, 115, 83, 79, 249, + 135, 63, 16, 46, 235, 197, 239, 59, 222, 13, 51, 24, 146, 152, + 201, 170, 240, 127, 191, 67, 211, 97, 235, 68, 108, 47, 146, 178, + 83, 57, 245, 18, 87, 159, 216, 74, 117, 112, 186, 172, 146, 91, + 20, 52, 67, 39, 177, 28, 106, 217, 41, 94, 153, 2, 6, 181, + 197, 160, 40, 218, 70, 100, 149, 51, 77, 150, 53, 195, 49, 30, + 227, 189, 185, 187, 55, 19, 28, 18, 99, 46, 212, 178, 10, 136, + 175, 136, 192, 136, 102, 74, 45, 252, 229, 129, 224, 75, 217, 55, + 219, 75, 122, 70, 243, 77, 108, 153, 104, 15, 33, 149, 193, 80, + 163, 132, 30, 32, 33, 19, 92, 133, 10, 61, 64, 225, 240, 29, + 232, 189, 32, 131, 98, 80, 41, 36, 39, 140, 248, 214, 80, 6, + 149, 164, 43, 190, 92, 182, 21, 60, 237, 2, 72, 134, 15, 81, + 130, 210, 167, 97, 107, 6, 111, 210, 204, 193, 87, 231, 124, 240, + 207, 77, 212, 196, 198, 188, 53, 249, 31, 91, 18, 49, 113, 166, + 155, 45, 66, 248, 157, 225, 150, 9, 166, 26, 67, 66, 82, 189, + 17, 232, 5, 13, 47, 220, 236, 235, 138, 62, 181, 17, 105, 67, + 201, 13, 233, 106, 37, 199, 208, 248, 60, 177, 96, 193, 112, 41, + 142, 130, 19, 55, 25, 179, 12, 92, 246, 88, 244, 192, 233, 6, + 125, 75, 170, 118, 255, 177, 18, 166, 140, 92, 140, 36, 157, 212, + 222, 190, 135, 182, 121, 246, 244, 97, 184, 210, 157, 132, 16, 62, + 130, 69, 242, 35, 115, 64, 201, 40, 90, 234, 89, 230, 148, 242, + 70, 65, 245, 39, 147, 188, 114, 232, 90, 245, 175, 252, 91, 40, + 55, 49, 66, 62, 244, 142, 88, 152, 157, 222, 42, 55, 215, 35, + 0, 120, 84, 143, 96, 145, 191, 75, 157, 106, 197, 67, 47, 212, + 205, 252, 167, 178, 92, 200, 130, 73, 244, 179, 84, 201, 57, 110, + 238, 244, 136, 244, 136, 180, 27, 156, 217, 59, 101, 229, 190, 132, + 175, 153, 61, 158, 15, 132, 123, 83, 62, 24, 58, 117, 6, 168, + 211, 40, 25, 158, 206, 186, 90, 217, 95, 145, 190, 158, 111, 58, + 7, 186, 213, 117, 17, 218, 45, 9, 84, 3, 121, 156, 249, 245, + 86, 182, 201, 102, 109, 233, 8, 16, 212, 19, 116, 126, 105, 9, + 175, 188, 62, 242, 55, 217, 148, 126, 57, 43, 185, 146, 19, 41, + 44, 217, 118, 172, 16, 213, 187, 32, 227, 39, 156, 22, 135, 152, + 22, 179, 164, 121, 32, 36, 3, 152, 40, 213, 253, 255, 170, 135, + 213, 112, 221, 137, 60, 208, 129, 205, 124, 247, 138, 151, 79, 155, + 197, 11, 100, 194, 132, 64, 89, 43, 21, 0, 124, 212, 81, 143, + 254, 229, 128, 209, 37, 169, 20, 91, 49, 175, 88, 166, 224, 127, + 213, 149, 69, 138, 215, 163, 97, 81, 46, 5, 123, 168, 43, 74, + 61, 179, 208, 179, 10, 51, 170, 50, 190, 120, 99, 153, 148, 144, + 194, 89, 118, 110, 26, 110, 153, 132, 205, 68, 156, 119, 196, 226, + 179, 157, 4, 200, 54, 204, 152, 127, 225, 42, 214, 116, 134, 156, + 55, 94, 23, 6, 85, 28, 89, 149, 170, 199, 158, 182, 192, 65, + 230, 101, 234, 234, 59, 114, 96, 228, 93, 134, 139, 226, 226, 74, + 229, 95, 147, 240, 74, 183, 144, 217, 77, 207, 82, 55, 185, 99, + 93, 49, 140, 165, 121, 166, 217, 101, 148, 45, 98, 103, 165, 8, + 76, 5, 176, 223, 95, 31, 99, 34, 43, 42, 26, 233, 182, 250, + 24, 198, 183, 69, 252, 197, 32, 33, 197, 112, 228, 248, 75, 178, + 57, 145, 24, 199, 232, 236, 34, 6, 245, 174, 186, 199, 62, 18, + 96, 144, 193, 45, 189, 75, 75, 150, 243, 84, 79, 238, 46, 230, + 210, 204, 55, 92, 48, 203, 255, 122, 27, 190, 89, 151, 215, 254, + 205, 104, 113, 84, 150, 95, 213, 2, 220, 240, 187, 22, 2, 92, + 73, 135, 180, 219, 112, 149, 218, 56, 192, 124, 219, 74, 144, 192, + 50, 124, 222, 25, 123, 6, 26, 70, 47, 168, 170, 39, 47, 78, + 20, 231, 50, 131, 39, 179, 94, 99, 25, 133, 178, 12, 177, 168, + 87, 29, 84, 237, 167, 215, 227, 155, 94, 130, 31, 208, 68, 79, + 237, 18, 80, 206, 30, 151, 6, 186, 177, 92, 115, 229, 76, 26, + 75, 47, 198, 71, 157, 244, 108, 206, 226, 165, 35, 229, 206, 252, + 126, 42, 220, 24, 92, 132, 78, 159, 198, 69, 251, 230, 148, 252, + 231, 84, 110, 107, 224, 182, 189, 88, 212, 225, 185, 217, 227, 94, + 181, 222, 126, 17, 169, 37, 118, 83, 253, 99, 150, 134, 53, 27, + 28, 234, 61, 34, 10, 193, 121, 138, 87, 69, 168, 70, 224, 155, + 59, 200, 76, 61, 84, 30, 234, 222, 134, 243, 202, 214, 161, 80, + 219, 124, 111, 106, 192, 134, 192, 95, 15, 205, 80, 244, 95, 101, + 93, 203, 177, 208, 54, 104, 247, 54, 100, 121, 104, 189, 166, 204, + 148, 210, 160, 60, 177, 152, 251, 41, 192, 153, 159, 118, 164, 187, + 62, 77, 156, 86, 179, 11, 239, 146, 74, 160, 73, 243, 218, 82, + 237, 73, 210, 0, 73, 75, 138, 233, 203, 59, 171, 140, 56, 27, + 131, 127, 115, 60, 44, 55, 211, 248, 232, 45, 204, 166, 75, 221, + 244, 50, 238, 230, 107, 207, 137, 145, 248, 247, 45, 142, 78, 30, + 28, 234, 228, 241, 87, 227, 115, 58, 124, 171, 31, 12, 225, 169, + 180, 64, 0, 229, 5, 236, 238, 67, 252, 201, 35, 54, 106, 228, + 101, 51, 21, 216, 203, 106, 37, 69, 167, 174, 80, 82, 125, 73, + 166, 45, 79, 89, 67, 224, 93, 143, 214, 76, 174, 9, 105, 139, + 10, 94, 148, 183, 224, 17, 131, 178, 192, 173, 59, 9, 203, 231, + 50, 138, 43, 244, 240, 116, 49, 7, 109, 40, 111, 69, 198, 17, + 198, 52, 244, 62, 195, 124, 146, 18, 26, 127, 9, 20, 1, 236, + 11, 105, 53, 31, 77, 237, 114, 21, 180, 134, 88, 37, 121, 196, + 199, 154, 159, 101, 6, 60, 110, 212, 232, 125, 211, 22, 206, 68, + 236, 249, 10, 133, 16, 201, 208, 189, 116, 133, 26, 90, 4, 254, + 22, 251, 136, 162, 148, 150, 115, 108, 45, 10, 153, 6, 153, 210, + 18, 138, 240, 171, 221, 189, 105, 177, 237, 119, 123, 0, 122, 72, + 175, 7, 64, 29, 203, 216, 129, 187, 214, 96, 211, 240, 34, 85, + 243, 169, 67, 36, 101, 150, 195, 226, 137, 249, 160, 172, 94, 207, + 63, 15, 89, 54, 226, 116, 136, 18, 126, 100, 60, 17, 64, 111, + 211, 81, 167, 93, 179, 112, 78, 34, 60, 79, 64, 193, 57, 171, + 137, 222, 90, 202, 219, 172, 169, 110, 92, 32, 51, 227, 226, 254, + 154, 6, 26, 144, 53, 176, 120, 160, 250, 2, 107, 6, 246, 46, + 199, 99, 169, 95, 101, 109, 31, 83, 46, 237, 202, 183, 13, 161, + 33, 92, 7, 221, 187, 222, 83, 241, 99, 170, 65, 201, 153, 109, + 4, 132, 249, 178, 107, 247, 7, 240, 74, 81, 152, 31, 193, 175, + 180, 249, 37, 40, 193, 119, 169, 107, 108, 16, 71, 213, 47, 215, + 198, 41, 169, 100, 24, 119, 15, 107, 56, 23, 254, 94, 35, 46, + 84, 170, 43, 4, 176, 191, 169, 98, 81, 75, 208, 121, 174, 106, + 56, 99, 135, 17, 255, 13, 121, 65, 171, 252, 218, 176, 154, 14, + 28, 118, 123, 78, 30, 208, 210, 227, 32, 133, 216, 62, 124, 210, + 227, 162, 36, 13, 182, 171, 177, 66, 241, 172, 214, 169, 197, 223, + 244, 166, 213, 201, 155, 47, 218, 21, 55, 156, 147, 126, 200, 42, + 128, 196, 118, 222, 248, 140, 235, 43, 246, 125, 172, 83, 27, 241, + 106, 238, 120, 37, 227, 129, 172, 207, 32, 250, 119, 14, 54, 205, + 92, 51, 56, 197, 236, 14, 205, 10, 92, 143, 79, 135, 161, 3, + 38, 39, 68, 177, 161, 125, 233, 127, 214, 245, 18, 165, 232, 22, + 124, 199, 117, 249, 69, 207, 31, 150, 232, 98, 228, 194, 196, 186, + 31, 160, 46, 153, 123, 156, 26, 77, 17, 179, 12, 92, 4, 116, + 90, 22, 185, 59, 243, 96, 195, 120, 120, 70, 131, 101, 102, 58, + 171, 101, 156, 147, 20, 144, 176, 143, 153, 15, 115, 199, 51, 157, + 18, 246, 126, 225, 79, 173, 34, 180, 214, 214, 90, 129, 218, 234, + 136, 139, 187, 240, 12, 64, 11, 181, 168, 135, 35, 253, 60, 206, + 204, 247, 236, 174, 169, 23, 114, 116, 244, 187, 220, 200, 203, 80, + 164, 37, 218, 116, 236, 34, 130, 121, 6, 130, 143, 113, 73, 103, + 69, 206, 8, 37, 104, 168, 153, 135, 199, 145, 216, 230, 43, 18, + 132, 36, 167, 244, 30, 57, 77, 32, 88, 66, 123, 157, 170, 72, + 235, 52, 238, 194, 255, 93, 63, 76, 95, 179, 121, 60, 20, 96, + 109, 73, 143, 107, 137, 182, 193, 209, 53, 182, 232, 61, 187, 158, + 102, 211, 189, 55, 14, 21, 239, 3, 42, 110, 248, 22, 204, 174, + 109, 253, 225, 51, 180, 154, 37, 154, 136, 30, 188, 118, 156, 47, + 143, 1, 58, 218, 145, 46, 228, 230, 165, 7, 66, 14, 44, 54, + 135, 96, 120, 17, 118, 7, 98, 52, 226, 96, 102, 77, 18, 34, + 171, 66, 242, 196, 9, 210, 104, 153, 57, 159, 249, 31, 79, 225, + 105, 33, 26, 118, 181, 42, 156, 13, 104, 195, 210, 99, 125, 202, + 252, 211, 193, 73, 43, 118, 157, 253, 6, 93, 72, 150, 98, 115, + 206, 204, 82, 213, 209, 203, 248, 57, 45, 210, 14, 130, 43, 178, + 102, 219, 42, 193, 109, 74, 27, 200, 139, 41, 103, 253, 174, 89, + 95, 187, 12, 177, 84, 107, 190, 190, 25, 226, 242, 125, 113, 7, + 28, 198, 120, 26, 1, 106, 40, 92, 73, 106, 47, 85, 9, 121, + 184, 195, 222, 230, 153, 185, 232, 120, 115, 37, 95, 96, 121, 88, + 110, 107, 101, 169, 88, 249, 102, 206, 92, 117, 80, 250, 238, 44, + 75, 52, 77, 94, 24, 187, 79, 169, 205, 163, 13, 182, 53, 192, + 37, 77, 122, 62, 124, 91, 86, 164, 100, 122, 92, 228, 31, 203, + 85, 231, 38, 88, 174, 176, 225, 147, 65, 110, 109, 44, 193, 47, + 133, 34, 205, 151, 117, 40, 92, 204, 5, 86, 31, 98, 195, 247, + 202, 24, 48, 200, 23, 154, 84, 183, 225, 246, 79, 228, 146, 38, + 170, 208, 248, 130, 29, 228, 208, 187, 40, 248, 181, 153, 126, 195, + 36, 116, 244, 143, 168, 195, 131, 138, 69, 160, 142, 163, 254, 193, + 124, 127, 108, 42, 13, 250, 164, 22, 225, 123, 144, 151, 207, 0, + 161, 110, 119, 232, 54, 135, 163, 128, 197, 251, 241, 170, 173, 77, + 180, 130, 88, 131, 81, 67, 66, 72, 187, 132, 37, 97, 51, 251, + 48, 64, 123, 122, 26, 52, 41, 131, 55, 90, 132, 30, 138, 4, + 21, 110, 194, 209, 145, 240, 213, 150, 26, 151, 56, 0, 26, 51, + 140, 42, 235, 226, 109, 49, 87, 238, 67, 160, 203, 201, 235, 245, + 71, 163, 203, 129, 227, 192, 143, 200, 76, 159, 71, 137, 152, 235, + 238, 206, 20, 26, 53, 70, 221, 239, 138, 51, 52, 22, 8, 112, + 79, 251, 229, 45, 177, 11, 83, 234, 186, 216, 1, 23, 123, 14, + 250, 87, 136, 109, 104, 183, 112, 182, 96, 45, 48, 166, 208, 171, + 150, 245, 132, 234, 84, 144, 13, 122, 119, 84, 161, 13, 54, 66, + 237, 224, 12, 88, 173, 1, 222, 123, 114, 188, 242, 202, 89, 189, + 121, 68, 95, 52, 248, 151, 100, 34, 63, 125, 103, 169, 231, 81, + 228, 196, 215, 53, 7, 36, 18, 5, 216, 197, 228, 91, 238, 232, + 10, 144, 67, 158, 210, 51, 114, 226, 102, 242, 115, 152, 108, 87, + 173, 217, 52, 119, 39, 60, 37, 27, 230, 204, 189, 27, 118, 157, + 226, 248, 15, 106, 185, 15, 8, 50, 123, 27, 143, 92, 211, 34, + 214, 18, 20, 78, 51, 243, 16, 12, 10, 233, 243, 1, 123, 118, + 64, 86, 214, 60, 47, 91, 49, 203, 245, 80, 238, 126, 100, 163, + 202, 118, 197, 128, 174, 247, 85, 12, 244, 197, 133, 180, 1, 192, + 67, 140, 154, 140, 94, 101, 56, 97, 239, 106, 164, 123, 128, 218, + 212, 32, 153, 27, 243, 252, 130, 232, 225, 95, 54, 108, 233, 138, + 226, 66, 228, 118, 173, 240, 72, 86, 55, 87, 104, 211, 68, 72, + 244, 35, 186, 255, 33, 113, 39, 94, 212, 47, 190, 60, 160, 5, + 248, 95, 103, 94, 171, 139, 179, 142, 159, 107, 4, 76, 61, 4, + 17, 138, 249, 228, 223, 202, 42, 185, 138, 16, 244, 63, 149, 235, + 216, 128, 211, 74, 254, 150, 82, 223, 39, 197, 185, 40, 41, 210, + 29, 71, 236, 77, 64, 63, 184, 2, 75, 116, 79, 116, 252, 69, + 1, 134, 232, 245, 48, 214, 175, 172, 49, 130, 95, 204, 234, 171, + 235, 208, 170, 135, 83, 93, 5, 169, 101, 202, 214, 239, 30, 5, + 7, 147, 191, 106, 168, 195, 114, 65, 5, 145, 199, 251, 65, 81, + 46, 109, 222, 176, 65, 55, 102, 221, 229, 14, 97, 78, 228, 56, + 179, 225, 241, 29, 232, 167, 20, 89, 102, 97, 206, 172, 89, 156, + 60, 105, 151, 58, 184, 147, 81, 97, 217, 23, 240, 31, 253, 10, + 166, 81, 211, 225, 25, 148, 116, 193, 66, 87, 122, 16, 235, 123, + 74, 165, 232, 142, 177, 40, 251, 2, 101, 23, 157, 220, 113, 80, + 253, 180, 156, 77, 31, 117, 233, 30, 113, 1, 25, 209, 181, 169, + 123, 69, 56, 106, 24, 212, 82, 220, 1, 96, 133, 148, 93, 131, + 4, 183, 82, 112, 193, 94, 89, 186, 101, 64, 36, 60, 216, 204, + 178, 191, 164, 171, 199, 205, 95, 117, 250, 55, 37, 178, 29, 54, + 127, 193, 215, 75, 222, 167, 121, 48, 244, 176, 60, 36, 13, 184, + 111, 184, 240, 193, 173, 126, 7, 79, 140, 65, 14, 37, 80, 167, + 175, 135, 236, 221, 145, 122, 177, 62, 42, 89, 240, 191, 209, 96, + 100, 87, 197, 211, 197, 121, 147, 169, 213, 228, 240, 68, 210, 182, + 171, 212, 105, 139, 233, 209, 184, 227, 213, 224, 91, 103, 63, 8, + 232, 38, 245, 86, 12, 49, 206, 178, 89, 186, 236, 251, 90, 189, + 143, 172, 251, 214, 224, 24, 127, 160, 127, 55, 123, 211, 145, 130, + 56, 2, 43, 243, 22, 24, 208, 43, 81, 48, 116, 146, 111, 141, + 146, 117, 127, 142, 204, 33, 59, 64, 139, 64, 114, 207, 195, 105, + 167, 89, 24, 249, 186, 137, 139, 55, 171, 163, 204, 139, 172, 103, + 6, 138, 240, 143, 250, 147, 238, 128, 66, 159, 162, 96, 219, 218, + 136, 218, 27, 24, 132, 216, 29, 249, 2, 42, 179, 255, 132, 199, + 210, 246, 25, 107, 161, 59, 229, 117, 32, 94, 154, 39, 121, 103, + 194, 178, 200, 195, 92, 110, 182, 168, 3, 195, 65, 64, 216, 93, + 1, 78, 2, 204, 79, 159, 208, 196, 72, 63, 160, 225, 168, 255, + 219, 110, 112, 240, 168, 99, 20, 155, 66, 66, 52, 41, 114, 108, + 135, 130, 211, 204, 127, 207, 181, 242, 185, 128, 81, 192, 112, 115, + 197, 246, 80, 84, 119, 223, 173, 169, 41, 158, 21, 112, 4, 22, + 168, 199, 207, 119, 159, 64, 133, 49, 219, 253, 88, 134, 106, 212, + 180, 168, 7, 218, 82, 15, 238, 235, 53, 135, 156, 56, 218, 100, + 198, 174, 111, 188, 251, 217, 233, 67, 223, 127, 54, 96, 118, 255, + 49, 225, 108, 180, 237, 250, 96, 206, 127, 90, 10, 97, 200, 132, + 189, 8, 109, 234, 144, 65, 249, 86, 108, 98, 135, 86, 89, 123, + 148, 25, 239, 64, 64, 189, 49, 169, 189, 162, 155, 141, 199, 103, + 126, 121, 244, 166, 107, 135, 144, 201, 10, 56, 153, 11, 36, 145, + 98, 62, 16, 23, 190, 205, 24, 91, 207, 243, 181, 173, 21, 143, + 165, 64, 4, 12, 28, 80, 186, 73, 82, 11, 139, 94, 186, 90, + 112, 115, 110, 214, 213, 103, 56, 86, 121, 146, 87, 137, 52, 165, + 227, 182, 196, 18, 80, 98, 42, 171, 164, 197, 237, 139, 158, 132, + 233, 57, 246, 53, 138, 108, 58, 18, 66, 13, 115, 35, 149, 123, + 153, 32, 202, 100, 74, 153, 109, 229, 182, 205, 46, 206, 241, 231, + 70, 106, 169, 137, 187, 67, 27, 9, 191, 174, 108, 246, 126, 227, + 183, 219, 246, 15, 208, 135, 0, 104, 208, 242, 153, 89, 83, 13, + 212, 145, 44, 187, 172, 37, 10, 56, 49, 187, 69, 233, 192, 150, + 221, 150, 59, 64, 224, 74, 235, 50, 117, 54, 200, 229, 173, 199, + 225, 16, 172, 82, 118, 217, 227, 108, 237, 78, 21, 163, 80, 77, + 221, 230, 245, 160, 97, 130, 195, 185, 132, 244, 174, 217, 225, 220, + 198, 89, 90, 27, 136, 92, 75, 233, 189, 69, 68, 6, 127, 23, + 125, 172, 154, 66, 165, 124, 58, 48, 252, 237, 246, 250, 167, 198, + 96, 54, 114, 97, 27, 151, 53, 239, 226, 146, 217, 96, 118, 29, + 165, 253, 95, 113, 78, 101, 27, 127, 185, 218, 9, 201, 184, 248, + 196, 85, 185, 179, 59, 87, 165, 193, 76, 48, 52, 245, 103, 29, + 42, 217, 37, 177, 79, 252, 82, 244, 231, 199, 214, 137, 234, 151, + 99, 183, 208, 70, 222, 246, 61, 34, 179, 103, 28, 168, 174, 163, + 81, 150, 70, 248, 218, 47, 61, 107, 68, 14, 132, 136, 84, 133, + 22, 78, 134, 97, 249, 202, 255, 224, 55, 156, 241, 178, 123, 78, + 222, 23, 108, 135, 127, 142, 104, 174, 163, 209, 19, 78, 17, 125, + 56, 200, 39, 129, 229, 205, 91, 41, 43, 67, 113, 22, 169, 8, + 52, 60, 234, 171, 62, 134, 131, 161, 160, 103, 149, 197, 220, 115, + 69, 104, 42, 224, 91, 134, 42, 15, 221, 10, 90, 201, 186, 104, + 220, 209, 159, 70, 237, 219, 13, 184, 163, 248, 115, 47, 221, 212, + 129, 252, 165, 45, 25, 49, 161, 20, 52, 255, 10, 109, 110, 231, + 215, 48, 19, 8, 150, 3, 78, 207, 155, 158, 39, 194, 165, 124, + 199, 91, 99, 179, 9, 108, 226, 23, 133, 6, 97, 61, 170, 236, + 172, 31, 22, 186, 241, 129, 76, 120, 12, 232, 195, 65, 113, 154, + 87, 149, 88, 36, 183, 2, 199, 191, 252, 102, 64, 222, 189, 172, + 196, 93, 71, 235, 130, 25, 245, 121, 82, 132, 178, 111, 0, 214, + 220, 95, 19, 36, 82, 76, 220, 151, 254, 57, 149, 31, 128, 174, + 238, 159, 204, 163, 187, 28, 213, 227, 62, 241, 222, 29, 83, 144, + 19, 116, 251, 172, 150, 94, 215, 23, 54, 20, 10, 148, 194, 51, + 126, 131, 247, 182, 75, 245, 29, 255, 90, 238, 71, 234, 168, 37, + 218, 239, 87, 98, 104, 189, 201, 53, 241, 163, 221, 124, 248, 163, + 178, 58, 178, 43, 182, 94, 242, 121, 200, 135, 64, 124, 39, 248, + 48, 20, 51, 66, 152, 185, 126, 160, 73, 14, 255, 139, 10, 103, + 96, 100, 202, 83, 164, 194, 160, 121, 76, 232, 211, 171, 237, 91, + 20, 243, 214, 51, 90, 52, 192, 151, 233, 246, 237, 196, 53, 165, + 252, 143, 61, 63, 35, 21, 188, 189, 77, 153, 200, 86, 129, 210, + 123, 43, 174, 224, 174, 240, 135, 209, 65, 5, 90, 21, 92, 174, + 174, 85, 12, 229, 158, 67, 249, 80, 176, 175, 23, 217, 3, 21, + 137, 251, 223, 66, 143, 89, 150, 53, 94, 234, 38, 205, 229, 26, + 176, 59, 96, 22, 8, 171, 213, 126, 90, 110, 153, 56, 215, 248, + 202, 84, 184, 51, 239, 206, 246, 37, 205, 162, 45, 19, 182, 185, + 12, 84, 252, 66, 78, 35, 203, 34, 52, 251, 104, 205, 115, 13, + 112, 216, 87, 255, 201, 124, 164, 62, 176, 110, 61, 240, 202, 40, + 217, 98, 238, 80, 61, 75, 195, 211, 200, 76, 117, 123, 128, 232, + 185, 111, 248, 120, 47, 227, 215, 97, 127, 97, 246, 33, 59, 51, + 103, 170, 185, 154, 171, 252, 151, 205, 106, 245, 249, 209, 128, 88, + 112, 171, 69, 3, 62, 64, 214, 20, 45, 125, 168, 195, 97, 69, + 104, 155, 124, 167, 107, 40, 206, 95, 125, 239, 54, 141, 34, 186, + 9, 109, 208, 94, 215, 41, 94, 148, 127, 19, 6, 52, 248, 189, + 172, 47, 130, 154, 168, 18, 173, 121, 95, 228, 242, 135, 74, 183, + 205, 24, 186, 137, 41, 200, 50, 90, 129, 242, 157, 12, 230, 241, + 223, 251, 168, 100, 151, 247, 235, 193, 32, 169, 143, 134, 135, 199, + 5, 105, 54, 191, 64, 232, 203, 148, 241, 64, 91, 244, 42, 50, + 42, 115, 141, 205, 53, 14, 16, 15, 141, 138, 19, 190, 123, 50, + 173, 58, 188, 147, 11, 172, 123, 240, 149, 32, 9, 189, 27, 162, + 140, 248, 75, 233, 67, 209, 13, 80, 127, 154, 215, 122, 172, 231, + 41, 115, 231, 241, 17, 59, 10, 196, 80, 232, 66, 49, 133, 238, + 106, 72, 223, 245, 114, 228, 152, 147, 112, 178, 174, 44, 179, 144, + 209, 192, 175, 54, 38, 110, 221, 177, 5, 173, 102, 179, 118, 87, + 83, 100, 188, 192, 169, 200, 140, 217, 106, 9, 225, 155, 52, 170, + 235, 53, 19, 138, 242, 125, 170, 232, 209, 61, 248, 215, 195, 166, + 68, 112, 227, 36, 22, 235, 242, 109, 155, 185, 75, 14, 207, 17, + 18, 250, 49, 209, 5, 101, 118, 6, 8, 195, 179, 181, 117, 48, + 95, 62, 35, 127, 230, 118, 101, 80, 162, 116, 52, 20, 183, 4, + 254, 181, 224, 35, 162, 192, 130, 234, 13, 44, 130, 242, 48, 239, + 155, 38, 228, 208, 82, 29, 54, 23, 67, 156, 0, 105, 181, 254, + 138, 15, 136, 190, 166, 236, 150, 50, 42, 176, 226, 182, 129, 109, + 1, 216, 135, 210, 157, 23, 206, 76, 95, 64, 123, 65, 76, 132, + 69, 51, 30, 7, 234, 30, 20, 121, 84, 69, 137, 112, 20, 167, + 68, 125, 82, 117, 136, 15, 34, 75, 135, 92, 5, 21, 124, 23, + 239, 240, 139, 53, 198, 173, 171, 151, 206, 146, 114, 19, 180, 210, + 10, 104, 62, 109, 120, 141, 3, 77, 120, 76, 64, 130, 169, 49, + 14, 31, 235, 253, 168, 138, 16, 223, 182, 45, 171, 230, 194, 229, + 77, 62, 128, 109, 170, 243, 229, 241, 236, 46, 9, 27, 167, 92, + 89, 178, 115, 72, 101, 105, 126, 179, 23, 221, 86, 33, 234, 80, + 100, 199, 149, 56, 27, 84, 115, 15, 247, 134, 215, 118, 164, 227, + 191, 125, 221, 25, 78, 59, 207, 122, 111, 123, 116, 244, 187, 220, + 200, 203, 80, 164, 101, 213, 209, 16, 53, 149, 112, 43, 219, 162, + 43, 165, 93, 156, 7, 1, 36, 243, 132, 215, 91, 127, 121, 221, + 246, 247, 115, 203, 126, 31, 108, 234, 176, 207, 138, 236, 89, 208, + 51, 103, 78, 135, 56, 159, 71, 222, 221, 164, 161, 68, 145, 65, + 152, 5, 215, 100, 183, 195, 150, 123, 97, 166, 174, 100, 185, 134, + 232, 254, 7, 194, 95, 105, 99, 76, 146, 215, 201, 94, 186, 50, + 60, 140, 62, 99, 70, 20, 191, 241, 37, 246, 6, 160, 30, 29, + 174, 68, 216, 206, 114, 73, 198, 205, 237, 223, 246, 117, 93, 136, + 100, 209, 30, 16, 189, 47, 180, 225, 160, 37, 210, 155, 209, 55, + 250, 208, 93, 180, 177, 35, 41, 28, 59, 30, 210, 250, 147, 55, + 242, 181, 154, 153, 224, 230, 108, 99, 147, 108, 254, 164, 66, 221, + 219, 24, 175, 110, 162, 84, 121, 156, 18, 123, 51, 115, 97, 35, + 92, 228, 10, 170, 234, 247, 186, 18, 100, 97, 104, 71, 175, 13, + 99, 218, 215, 110, 243, 194, 243, 116, 228, 175, 60, 102, 74, 190, + 11, 242, 223, 41, 148, 13, 109, 114, 167, 59, 86, 101, 124, 40, + 177, 80, 221, 146, 166, 242, 100, 121, 74, 48, 69, 84, 46, 152, + 225, 228, 76, 37, 141, 43, 39, 232, 37, 255, 128, 253, 33, 108, + 26, 12, 121, 121, 3, 73, 122, 142, 170, 133, 62, 39, 207, 247, + 232, 241, 200, 155, 160, 32, 255, 127, 247, 194, 0, 72, 157, 72, + 5, 42, 78, 214, 199, 116, 133, 122, 229, 124, 133, 103, 92, 240, + 75, 95, 203, 169, 91, 120, 48, 206, 252, 232, 4, 188, 186, 147, + 184, 169, 168, 167, 0, 39, 201, 0, 183, 204, 132, 41, 114, 109, + 196, 74, 25, 221, 91, 190, 171, 188, 42, 92, 215, 225, 174, 242, + 110, 96, 21, 168, 21, 121, 6, 131, 3, 161, 63, 111, 155, 173, + 212, 41, 144, 247, 166, 47, 181, 129, 180, 70, 76, 126, 71, 20, + 72, 247, 123, 25, 255, 98, 45, 8, 77, 13, 247, 206, 227, 39, + 73, 201, 20, 53, 203, 164, 124, 115, 197, 5, 127, 178, 58, 35, + 98, 240, 173, 30, 1, 37, 231, 168, 159, 215, 217, 236, 12, 121, + 214, 214, 4, 134, 146, 129, 119, 25, 96, 106, 53, 175, 129, 161, + 81, 102, 7, 184, 146, 2, 190, 28, 223, 74, 108, 172, 240, 250, + 215, 156, 101, 75, 98, 222, 111, 159, 62, 91, 12, 0, 82, 223, + 124, 151, 122, 41, 171, 215, 21, 17, 205, 198, 10, 189, 157, 42, + 7, 168, 172, 241, 211, 198, 108, 127, 237, 9, 192, 235, 28, 101, + 109, 106, 204, 59, 213, 54, 146, 33, 160, 155, 7, 217, 224, 23, + 130, 54, 178, 153, 27, 223, 41, 116, 145, 140, 8, 128, 196, 69, + 47, 13, 218, 30, 160, 135, 116, 174, 52, 159, 22, 94, 96, 115, + 97, 27, 225, 56, 174, 31, 149, 18, 37, 193, 252, 203, 198, 119, + 88, 140, 96, 50, 139, 193, 64, 130, 245, 251, 199, 96, 106, 246, + 50, 114, 149, 238, 35, 163, 31, 106, 235, 241, 85, 14, 140, 119, + 236, 43, 217, 192, 158, 143, 175, 91, 108, 94, 243, 141, 98, 189, + 123, 37, 127, 19, 46, 73, 222, 182, 47, 247, 19, 176, 212, 146, + 204, 1, 127, 122, 90, 103, 102, 161, 244, 36, 19, 16, 223, 107, + 216, 35, 174, 200, 106, 22, 198, 68, 99, 38, 110, 75, 143, 72, + 246, 90, 12, 246, 169, 155, 207, 227, 156, 177, 16, 218, 13, 130, + 208, 118, 111, 13, 31, 36, 230, 41, 171, 167, 142, 4, 54, 74, + 15, 178, 85, 231, 222, 238, 163, 22, 31, 16, 33, 108, 146, 246, + 224, 16, 63, 6, 135, 162, 241, 15, 82, 13, 146, 15, 188, 128, + 29, 95, 226, 132, 43, 97, 61, 190, 40, 203, 161, 11, 217, 35, + 189, 254, 246, 28, 130, 18, 163, 55, 246, 154, 130, 228, 85, 128, + 223, 159, 111, 220, 57, 131, 165, 64, 203, 10, 171, 91, 90, 25, + 58, 102, 14, 192, 164, 67, 26, 98, 163, 68, 18, 148, 160, 58, + 231, 28, 27, 205, 110, 71, 86, 27, 162, 50, 184, 6, 188, 66, + 115, 11, 87, 93, 114, 8, 119, 93, 49, 214, 71, 217, 229, 180, + 59, 90, 18, 47, 171, 141, 85, 60, 166, 184, 34, 1, 5, 145, + 233, 169, 110, 252, 122, 68, 196, 3, 88, 146, 92, 64, 170, 26, + 101, 186, 250, 252, 206, 190, 56, 48, 77, 145, 126, 212, 31, 115, + 40, 12, 178, 103, 65, 241, 195, 44, 184, 244, 218, 15, 163, 85, + 197, 142, 104, 184, 43, 20, 221, 172, 106, 236, 254, 136, 189, 254, + 243, 118, 251, 1, 104, 161, 143, 158, 147, 200, 229, 25, 14, 216, + 137, 1, 191, 7, 157, 220, 172, 36, 195, 155, 50, 57, 83, 68, + 223, 250, 234, 182, 139, 24, 117, 144, 136, 201, 179, 34, 17, 22, + 78, 169, 67, 48, 133, 202, 255, 173, 101, 27, 20, 47, 242, 73, + 139, 109, 194, 193, 21, 55, 138, 12, 27, 102, 170, 18, 73, 218, + 129, 66, 206, 74, 207, 168, 146, 48, 116, 178, 84, 56, 250, 45, + 254, 50, 129, 126, 131, 86, 196, 141, 45, 108, 93, 195, 49, 94, + 134, 138, 246, 220, 96, 26, 100, 75, 153, 199, 82, 29, 132, 46, + 61, 46, 95, 237, 127, 234, 226, 220, 67, 8, 115, 193, 237, 250, + 47, 199, 124, 242, 31, 218, 217, 204, 81, 230, 152, 4, 245, 66, + 15, 128, 135, 33, 108, 165, 222, 122, 156, 145, 139, 83, 75, 6, + 84, 0, 246, 37, 231, 222, 178, 140, 136, 75, 165, 18, 103, 114, + 42, 78, 174, 113, 105, 165, 235, 211, 236, 252, 213, 129, 1, 111, + 164, 242, 120, 93, 53, 25, 151, 156, 6, 107, 57, 222, 229, 40, + 207, 221, 252, 34, 117, 3, 8, 168, 240, 52, 140, 209, 79, 198, + 135, 18, 86, 7, 239, 243, 48, 202, 17, 203, 186, 87, 160, 208, + 240, 131, 47, 88, 122, 12, 111, 185, 39, 195, 143, 96, 75, 76, + 229, 110, 9, 218, 116, 136, 20, 222, 0, 52, 126, 243, 159, 139, + 153, 169, 11, 67, 203, 140, 21, 71, 49, 190, 90, 220, 146, 158, + 141, 29, 247, 221, 161, 48, 229, 151, 197, 234, 189, 60, 3, 230, + 85, 186, 16, 81, 47, 222, 30, 50, 170, 29, 133, 181, 119, 62, + 26, 86, 43, 41, 179, 123, 180, 122, 74, 184, 185, 193, 125, 206, + 249, 199, 221, 215, 156, 231, 88, 72, 235, 56, 254, 205, 157, 148, + 201, 92, 62, 162, 10, 112, 110, 238, 86, 213, 253, 146, 215, 25, + 244, 1, 169, 145, 162, 80, 100, 57, 20, 94, 17, 145, 115, 14, + 44, 241, 26, 54, 55, 109, 46, 221, 147, 149, 57, 75, 108, 65, + 188, 226, 110, 75, 86, 201, 208, 126, 254, 191, 196, 67, 106, 76, + 217, 11, 149, 76, 196, 112, 48, 52, 93, 251, 211, 41, 175, 55, + 191, 85, 90, 14, 46, 142, 165, 195, 50, 245, 166, 177, 53, 17, + 28, 94, 164, 87, 56, 148, 93, 166, 187, 167, 205, 158, 242, 100, + 21, 69, 82, 139, 210, 157, 185, 40, 37, 146, 178, 245, 172, 185, + 80, 123, 122, 43, 167, 87, 83, 163, 21, 70, 9, 237, 67, 202, + 156, 43, 48, 183, 136, 58, 15, 193, 216, 44, 12, 71, 71, 24, + 22, 88, 231, 46, 41, 56, 40, 70, 82, 64, 245, 103, 162, 50, + 83, 227, 156, 241, 80, 15, 233, 169, 80, 52, 212, 218, 59, 127, + 40, 168, 4, 100, 246, 36, 35, 66, 16, 162, 223, 227, 186, 40, + 27, 220, 38, 21, 46, 202, 157, 250, 113, 21, 50, 105, 193, 179, + 112, 15, 35, 79, 180, 87, 184, 202, 252, 88, 95, 136, 204, 242, + 103, 205, 218, 54, 67, 27, 200, 159, 184, 28, 29, 112, 45, 115, + 164, 90, 96, 28, 69, 117, 190, 214, 62, 14, 136, 102, 192, 105, + 126, 189, 122, 159, 186, 241, 174, 59, 114, 213, 212, 206, 50, 86, + 246, 163, 200, 231, 81, 202, 100, 38, 194, 54, 18, 201, 58, 169, + 170, 184, 218, 194, 149, 73, 155, 153, 53, 181, 245, 202, 198, 62, + 164, 18, 103, 139, 69, 77, 11, 206, 21, 13, 70, 141, 4, 233, + 196, 195, 206, 183, 140, 111, 93, 7, 185, 7, 34, 56, 212, 213, + 251, 210, 233, 84, 184, 225, 83, 17, 183, 145, 125, 190, 191, 47, + 240, 14, 225, 104, 164, 128, 17, 179, 175, 79, 218, 98, 80, 109, + 47, 162, 206, 56, 208, 78, 103, 211, 15, 212, 96, 239, 93, 26, + 76, 5, 144, 105, 168, 237, 229, 20, 161, 2, 170, 250, 253, 250, + 184, 233, 196, 151, 172, 136, 160, 74, 16, 31, 76, 29, 136, 124, + 190, 22, 31, 189, 23, 154, 215, 50, 214, 175, 79, 65, 18, 202, + 6, 25, 184, 111, 4, 44, 199, 102, 179, 90, 237, 187, 218, 194, + 65, 169, 173, 239, 95, 140, 208, 150, 39, 152, 26, 72, 210, 219, + 185, 48, 113, 119, 192, 239, 137, 172, 99, 239, 131, 144, 105, 86, + 32, 253, 236, 174, 209, 97, 72, 50, 189, 51, 178, 103, 39, 86, + 113, 127, 152, 209, 81, 128, 138, 14, 195, 134, 86, 77, 215, 73, + 181, 84, 107, 146, 100, 77, 83, 227, 67, 19, 14, 202, 99, 91, + 221, 221, 63, 49, 107, 178, 1, 162, 96, 149, 32, 52, 140, 184, + 49, 132, 66, 50, 105, 132, 82, 141, 118, 208, 193, 122, 91, 227, + 113, 185, 132, 49, 198, 82, 196, 50, 109, 70, 170, 57, 194, 219, + 76, 253, 86, 36, 144, 174, 10, 149, 98, 157, 185, 114, 175, 79, + 138, 43, 147, 171, 51, 229, 182, 107, 18, 224, 10, 131, 139, 27, + 30, 127, 173, 187, 180, 236, 179, 86, 52, 128, 201, 18, 60, 84, + 145, 96, 3, 126, 61, 105, 134, 117, 201, 4, 153, 189, 226, 78, + 162, 228, 213, 67, 130, 117, 243, 97, 57, 67, 101, 94, 64, 187, + 16, 174, 84, 20, 209, 244, 201, 114, 19, 122, 148, 108, 162, 224, + 3, 33, 227, 64, 157, 147, 247, 180, 111, 162, 238, 0, 136, 210, + 132, 33, 139, 226, 187, 249, 193, 215, 70, 9, 39, 235, 146, 194, + 33, 107, 56, 174, 76, 239, 223, 118, 50, 125, 193, 226, 42, 70, + 2, 205, 25, 21, 222, 205, 27, 17, 185, 180, 115, 136, 177, 61, + 60, 10, 50, 90, 41, 78, 37, 234, 180, 23, 158, 140, 22, 231, + 124, 39, 100, 29, 44, 158, 194, 106, 108, 203, 78, 186, 141, 125, + 190, 154, 209, 210, 184, 99, 3, 209, 222, 97, 126, 49, 103, 75, + 79, 224, 21, 19, 239, 157, 67, 71, 111, 212, 201, 105, 162, 227, + 33, 235, 221, 49, 16, 195, 229, 109, 94, 12, 221, 133, 140, 44, + 223, 216, 1, 174, 241, 241, 183, 78, 171, 112, 201, 24, 23, 83, + 175, 173, 235, 220, 143, 50, 80, 3, 191, 111, 211, 173, 74, 121, + 229, 160, 212, 167, 202, 19, 42, 11, 136, 42, 119, 234, 58, 229, + 111, 52, 206, 3, 251, 155, 147, 239, 2, 184, 111, 176, 95, 254, + 235, 248, 168, 208, 126, 0, 149, 95, 161, 4, 171, 237, 30, 69, + 244, 120, 106, 84, 145, 143, 42, 145, 76, 118, 64, 231, 72, 42, + 207, 194, 45, 134, 180, 47, 249, 31, 4, 53, 76, 133, 217, 114, + 248, 209, 181, 150, 204, 225, 60, 55, 125, 232, 41, 22, 133, 83, + 191, 180, 28, 217, 46, 125, 225, 85, 247, 117, 162, 88, 53, 173, + 166, 83, 34, 109, 168, 176, 110, 32, 85, 112, 105, 28, 96, 99, + 255, 216, 168, 35, 244, 83, 9, 6, 205, 106, 93, 198, 155, 94, + 116, 46, 59, 123, 232, 180, 150, 91, 58, 242, 185, 254, 227, 193, + 207, 243, 99, 162, 184, 65, 2, 40, 6, 125, 142, 151, 229, 176, + 85, 42, 215, 142, 128, 2, 73, 51, 213, 70, 115, 132, 196, 27, + 65, 47, 172, 2, 164, 209, 171, 100, 216, 21, 211, 81, 37, 137, + 25, 76, 103, 222, 0, 67, 16, 74, 63, 66, 46, 242, 170, 165, + 207, 51, 28, 186, 191, 73, 9, 212, 65, 119, 142, 4, 238, 246, + 162, 232, 38, 225, 134, 197, 248, 52, 109, 140, 251, 115, 59, 99, + 138, 87, 83, 221, 161, 234, 155, 175, 162, 231, 21, 211, 27, 42, + 159, 149, 4, 105, 85, 211, 74, 64, 104, 237, 146, 91, 174, 11, + 103, 62, 16, 176, 55, 163, 166, 223, 172, 9, 28, 135, 18, 66, + 43, 6, 205, 114, 126, 11, 242, 113, 178, 255, 19, 81, 147, 100, + 13, 107, 31, 206, 246, 28, 210, 165, 9, 124, 109, 109, 92, 114, + 137, 221, 191, 109, 46, 50, 128, 215, 0, 37, 158, 165, 3, 36, + 198, 19, 125, 79, 250, 2, 119, 50, 138, 154, 210, 224, 181, 8, + 122, 114, 62, 145, 146, 72, 116, 148, 178, 71, 1, 6, 210, 244, + 253, 94, 222, 87, 207, 236, 40, 182, 20, 129, 53, 181, 69, 63, + 212, 167, 10, 90, 19, 120, 107, 226, 189, 152, 157, 157, 163, 146, + 8, 68, 62, 197, 199, 77, 33, 4, 97, 161, 125, 241, 56, 243, + 123, 15, 85, 240, 93, 162, 128, 36, 229, 228, 48, 143, 243, 128, + 150, 233, 207, 62, 117, 188, 148, 140, 165, 22, 20, 190, 193, 171, + 190, 237, 150, 199, 128, 251, 159, 27, 53, 35, 207, 192, 45, 213, + 175, 16, 149, 217, 19, 100, 110, 253, 178, 196, 35, 121, 254, 76, + 96, 38, 67, 18, 25, 150, 229, 110, 206, 200, 7, 87, 99, 110, + 58, 11, 104, 137, 116, 6, 77, 207, 207, 31, 16, 77, 123, 144, + 234, 9, 208, 119, 137, 23, 174, 175, 3, 77, 80, 209, 127, 42, + 41, 177, 248, 200, 70, 137, 60, 28, 62, 210, 124, 94, 98, 40, + 90, 164, 185, 163, 211, 16, 29, 77, 152, 86, 211, 216, 27, 32, + 209, 134, 16, 240, 56, 111, 101, 168, 218, 169, 62, 209, 69, 241, + 182, 143, 63, 205, 153, 233, 148, 113, 178, 45, 224, 53, 5, 6, + 216, 152, 83, 9, 116, 203, 27, 131, 181, 190, 69, 9, 194, 103, + 25, 27, 73, 125, 91, 6, 188, 102, 97, 56, 172, 22, 42, 70, + 17, 60, 84, 117, 156, 216, 113, 247, 108, 95, 132, 244, 170, 161, + 228, 183, 163, 147, 113, 80, 22, 213, 220, 173, 206, 193, 70, 178, + 113, 115, 5, 109, 93, 58, 21, 140, 128, 165, 182, 93, 12, 56, + 197, 111, 160, 100, 46, 189, 234, 0, 255, 254, 184, 197, 142, 126, + 23, 76, 30, 122, 32, 194, 110, 226, 220, 45, 132, 83, 99, 213, + 43, 170, 119, 83, 228, 49, 120, 202, 108, 61, 147, 22, 132, 74, + 37, 99, 67, 218, 204, 132, 198, 119, 135, 238, 255, 74, 164, 146, + 78, 228, 66, 109, 248, 66, 228, 142, 228, 131, 100, 222, 41, 157, + 18, 94, 9, 190, 45, 39, 188, 66, 23, 181, 38, 33, 26, 76, + 135, 197, 16, 2, 83, 28, 179, 189, 230, 120, 208, 113, 37, 8, + 194, 65, 102, 221, 51, 69, 116, 233, 254, 34, 254, 85, 242, 34, + 213, 19, 20, 38, 192, 233, 156, 124, 196, 61, 10, 48, 182, 43, + 225, 241, 10, 129, 142, 137, 112, 227, 234, 65, 30, 246, 90, 232, + 135, 111, 219, 54, 145, 98, 22, 179, 59, 95, 101, 203, 83, 70, + 42, 19, 195, 32, 252, 66, 80, 58, 249, 65, 53, 216, 44, 127, + 210, 64, 17, 119, 215, 188, 3, 35, 89, 176, 127, 132, 129, 120, + 147, 205, 1, 52, 111, 104, 207, 84, 23, 210, 140, 31, 159, 8, + 97, 195, 96, 91, 85, 65, 51, 37, 69, 165, 78, 28, 38, 197, + 148, 128, 188, 232, 195, 243, 238, 60, 141, 0, 51, 6, 216, 101, + 238, 161, 210, 249, 138, 37, 217, 243, 81, 35, 167, 172, 220, 47, + 72, 4, 74, 77, 24, 228, 207, 231, 218, 192, 191, 254, 220, 135, + 74, 42, 77, 77, 105, 52, 232, 149, 62, 188, 170, 67, 119, 112, + 221, 225, 131, 237, 161, 39, 181, 67, 236, 206, 159, 70, 51, 194, + 60, 72, 109, 198, 191, 229, 16, 241, 128, 198, 60, 208, 243, 168, + 44, 50, 177, 29, 209, 183, 215, 201, 92, 79, 165, 99, 121, 247, + 44, 243, 195, 88, 163, 137, 92, 197, 10, 118, 122, 82, 54, 126, + 186, 204, 120, 9, 125, 134, 168, 82, 163, 41, 137, 166, 56, 5, + 36, 174, 251, 102, 166, 105, 211, 179, 148, 197, 171, 85, 248, 113, + 73, 44, 138, 174, 118, 230, 145, 50, 48, 250, 234, 31, 44, 142, + 192, 14, 106, 251, 179, 98, 144, 162, 230, 159, 212, 150, 66, 6, + 32, 233, 175, 78, 232, 140, 226, 61, 130, 104, 204, 181, 184, 202, + 196, 94, 144, 100, 227, 92, 210, 33, 33, 181, 15, 148, 150, 56, + 99, 133, 41, 27, 43, 14, 36, 171, 24, 186, 22, 27, 8, 29, + 7, 145, 182, 5, 110, 167, 224, 109, 146, 44, 8, 138, 190, 0, + 240, 96, 12, 222, 133, 132, 84, 69, 45, 165, 235, 156, 166, 150, + 41, 81, 107, 151, 167, 60, 29, 220, 95, 173, 207, 38, 255, 7, + 96, 61, 171, 213, 12, 201, 96, 145, 118, 251, 77, 249, 162, 22, + 236, 36, 240, 0, 164, 59, 214, 188, 182, 215, 70, 251, 53, 141, + 50, 237, 89, 83, 185, 185, 61, 152, 205, 205, 63, 17, 41, 96, + 169, 185, 195, 141, 131, 77, 122, 193, 133, 131, 95, 47, 13, 22, + 242, 41, 84, 73, 127, 87, 162, 70, 148, 204, 14, 95, 173, 37, + 29, 162, 141, 171, 134, 45, 78, 59, 91, 192, 39, 142, 206, 9, + 86, 3, 84, 32, 151, 229, 34, 193, 49, 178, 93, 160, 60, 80, + 39, 119, 237, 194, 82, 246, 166, 213, 220, 70, 77, 170, 2, 239, + 11, 106, 99, 170, 189, 28, 105, 193, 200, 87, 137, 100, 133, 185, + 153, 26, 173, 237, 19, 33, 91, 84, 232, 229, 66, 77, 246, 149, + 218, 177, 130, 131, 30, 216, 53, 19, 34, 225, 18, 151, 29, 40, + 14, 113, 244, 80, 156, 205, 49, 247, 103, 193, 76, 150, 1, 71, + 109, 197, 206, 121, 34, 18, 175, 38, 194, 27, 206, 193, 38, 68, + 41, 0, 106, 236, 100, 221, 117, 230, 91, 163, 215, 219, 221, 130, + 120, 78, 4, 247, 212, 94, 140, 215, 227, 254, 8, 117, 93, 140, + 167, 90, 17, 159, 34, 130, 176, 253, 33, 196, 250, 59, 149, 34, + 161, 171, 158, 223, 50, 76, 117, 58, 149, 88, 36, 71, 209, 75, + 169, 177, 228, 189, 38, 29, 16, 14, 23, 39, 228, 77, 244, 44, + 182, 219, 193, 62, 142, 102, 152, 72, 38, 101, 87, 109, 195, 140, + 95, 163, 142, 239, 228, 52, 182, 208, 107, 21, 141, 234, 84, 149, + 213, 232, 200, 251, 64, 76, 89, 12, 92, 106, 105, 139, 147, 187, + 97, 128, 223, 36, 65, 202, 26, 233, 213, 79, 30, 55, 132, 33, + 51, 113, 223, 131, 224, 40, 235, 94, 52, 170, 225, 161, 205, 253, + 44, 208, 221, 195, 108, 209, 204, 126, 126, 68, 79, 34, 134, 168, + 35, 120, 33, 3, 33, 195, 199, 133, 217, 74, 56, 112, 31, 68, + 184, 126, 92, 241, 198, 205, 254, 76, 105, 67, 153, 19, 55, 230, + 97, 73, 197, 9, 151, 211, 236, 4, 112, 23, 174, 7, 214, 187, + 88, 203, 193, 214, 99, 50, 224, 178, 195, 114, 226, 201, 182, 204, + 14, 161, 106, 163, 192, 147, 247, 35, 83, 3, 30, 150, 170, 166, + 226, 16, 193, 120, 26, 78, 45, 198, 187, 19, 219, 217, 142, 166, + 56, 253, 73, 222, 216, 195, 129, 154, 127, 102, 72, 138, 3, 46, + 207, 68, 143, 195, 222, 245, 81, 28, 70, 247, 23, 238, 173, 224, + 103, 97, 204, 57, 239, 205, 77, 254, 254, 105, 130, 217, 24, 199, + 148, 212, 189, 120, 100, 204, 240, 192, 52, 205, 174, 97, 9, 174, + 130, 113, 105, 17, 165, 9, 144, 141, 70, 60, 130, 149, 7, 222, + 149, 9, 245, 175, 149, 16, 20, 82, 123, 164, 89, 206, 65, 79, + 90, 112, 134, 227, 78, 83, 113, 170, 229, 13, 90, 205, 203, 33, + 99, 59, 112, 91, 45, 101, 75, 188, 7, 79, 16, 88, 232, 210, + 28, 0, 170, 150, 4, 37, 50, 107, 61, 115, 211, 158, 80, 7, + 65, 234, 29, 164, 12, 214, 50, 104, 112, 104, 198, 15, 193, 102, + 3, 86, 225, 216, 218, 187, 216, 221, 15, 111, 159, 210, 15, 75, + 180, 239, 82, 165, 252, 244, 60, 79, 17, 24, 160, 64, 121, 246, + 15, 225, 235, 197, 0, 149, 169, 14, 29, 210, 142, 168, 92, 232, + 220, 253, 146, 81, 186, 7, 21, 150, 100, 53, 130, 243, 45, 149, + 140, 77, 231, 218, 28, 82, 202, 114, 93, 18, 61, 97, 91, 70, + 114, 87, 56, 239, 91, 209, 139, 118, 72, 189, 215, 23, 13, 117, + 247, 5, 6, 20, 194, 40, 6, 235, 13, 6, 14, 220, 239, 103, + 1, 35, 146, 30, 191, 231, 77, 214, 233, 88, 141, 80, 163, 63, + 160, 220, 221, 80, 49, 127, 51, 39, 104, 106, 178, 242, 250, 223, + 248, 107, 157, 234, 134, 123, 69, 70, 84, 227, 171, 122, 2, 163, + 181, 48, 207, 104, 40, 65, 193, 192, 55, 242, 98, 150, 90, 20, + 106, 113, 255, 0, 199, 65, 162, 0, 183, 142, 103, 58, 243, 209, + 215, 88, 235, 78, 126, 161, 203, 233, 35, 56, 251, 144, 113, 120, + 198, 63, 211, 240, 162, 124, 116, 38, 171, 234, 148, 85, 124, 22, + 70, 182, 214, 80, 145, 157, 31, 227, 60, 193, 135, 143, 12, 238, + 40, 64, 119, 141, 217, 234, 197, 142, 37, 17, 73, 94, 101, 229, + 166, 3, 231, 51, 120, 40, 28, 49, 100, 118, 65, 144, 232, 159, + 168, 158, 126, 212, 253, 226, 22, 88, 21, 130, 199, 236, 78, 14, + 74, 140, 13, 254, 144, 189, 42, 180, 149, 241, 211, 239, 174, 126, + 54, 94, 165, 74, 41, 134, 194, 30, 98, 68, 30, 81, 37, 154, + 225, 252, 113, 81, 230, 182, 196, 197, 188, 166, 168, 200, 230, 73, + 72, 200, 4, 49, 252, 42, 238, 56, 169, 165, 179, 179, 155, 19, + 216, 107, 227, 135, 32, 229, 167, 183, 92, 247, 207, 121, 114, 17, + 98, 52, 125, 155, 150, 54, 45, 143, 137, 109, 233, 155, 133, 67, + 133, 83, 122, 104, 208, 202, 200, 116, 56, 170, 78, 49, 206, 118, + 235, 63, 24, 67, 67, 0, 95, 77, 65, 198, 228, 170, 107, 110, + 51, 163, 170, 36, 90, 12, 204, 82, 98, 127, 99, 85, 3, 198, + 145, 180, 150, 198, 170, 152, 125, 247, 86, 234, 138, 82, 222, 224, + 247, 212, 80, 156, 235, 173, 189, 47, 87, 193, 252, 124, 252, 104, + 216, 171, 107, 107, 6, 7, 140, 205, 120, 180, 65, 41, 131, 129, + 194, 218, 112, 91, 181, 204, 46, 209, 5, 140, 167, 62, 151, 250, + 220, 190, 10, 218, 223, 203, 131, 244, 210, 99, 148, 117, 186, 30, + 112, 139, 198, 143, 96, 62, 149, 246, 36, 255, 150, 178, 164, 28, + 221, 184, 28, 239, 184, 57, 192, 239, 176, 112, 44, 104, 63, 194, + 85, 133, 131, 250, 14, 125, 22, 211, 19, 239, 239, 217, 98, 2, + 110, 204, 20, 206, 104, 255, 93, 78, 209, 205, 6, 137, 157, 168, + 125, 212, 208, 116, 11, 169, 145, 86, 139, 209, 233, 224, 51, 37, + 9, 215, 161, 98, 8, 197, 112, 103, 226, 46, 238, 166, 152, 157, + 73, 113, 157, 203, 174, 181, 106, 225, 255, 222, 236, 232, 72, 145, + 115, 97, 106, 171, 228, 35, 109, 237, 195, 215, 233, 89, 108, 206, + 144, 227, 165, 39, 204, 148, 65, 241, 70, 184, 12, 242, 39, 194, + 179, 70, 179, 250, 247, 209, 28, 190, 17, 249, 120, 228, 201, 33, + 251, 229, 212, 45, 237, 117, 245, 126, 154, 200, 89, 84, 152, 20, + 12, 184, 170, 178, 155, 216, 1, 136, 23, 157, 145, 67, 226, 207, + 65, 196, 180, 148, 92, 7, 247, 43, 84, 210, 128, 195, 222, 203, + 61, 248, 205, 104, 148, 39, 87, 219, 151, 149, 217, 121, 253, 110, + 96, 211, 86, 30, 216, 83, 206, 175, 102, 221, 143, 0, 159, 124, + 86, 154, 71, 254, 22, 137, 218, 241, 88, 203, 235, 170, 174, 140, + 138, 70, 64, 214, 8, 213, 245, 182, 152, 74, 215, 43, 84, 218, + 90, 52, 54, 130, 220, 22, 196, 133, 20, 33, 148, 19, 205, 126, + 255, 11, 9, 35, 97, 244, 183, 27, 112, 40, 65, 92, 91, 116, + 147, 180, 225, 163, 105, 193, 240, 221, 84, 226, 136, 244, 22, 114, + 178, 99, 20, 55, 20, 252, 2, 236, 17, 122, 224, 248, 204, 214, + 199, 96, 43, 101, 215, 145, 74, 152, 112, 74, 97, 133, 14, 78, + 97, 51, 215, 111, 241, 4, 124, 9, 226, 84, 19, 4, 64, 196, + 108, 205, 18, 245, 6, 7, 177, 8, 77, 251, 245, 82, 217, 220, + 251, 57, 104, 97, 227, 4, 138, 69, 99, 158, 22, 197, 38, 203, + 31, 197, 29, 219, 248, 202, 17, 167, 226, 49, 106, 94, 135, 227, + 134, 216, 82, 164, 51, 167, 210, 130, 178, 159, 253, 151, 8, 2, + 228, 17, 198, 22, 13, 218, 115, 167, 55, 240, 156, 178, 226, 2, + 235, 135, 175, 122, 24, 221, 65, 62, 73, 68, 208, 190, 96, 131, + 243, 228, 233, 141, 226, 85, 63, 81, 33, 29, 148, 71, 22, 139, + 113, 102, 237, 67, 208, 9, 111, 226, 14, 152, 50, 9, 230, 239, + 218, 12, 60, 246, 64, 178, 68, 194, 42, 201, 211, 48, 12, 67, + 97, 92, 174, 242, 251, 61, 197, 197, 1, 118, 171, 59, 181, 42, + 51, 132, 72, 20, 78, 144, 57, 13, 106, 205, 203, 117, 141, 233, + 39, 24, 253, 5, 123, 5, 10, 151, 156, 163, 148, 4, 61, 78, + 100, 186, 86, 235, 103, 103, 205, 194, 41, 222, 231, 144, 202, 168, + 21, 140, 153, 115, 16, 41, 81, 82, 219, 245, 210, 117, 221, 218, + 182, 220, 203, 149, 161, 161, 232, 139, 188, 207, 219, 248, 127, 77, + 43, 227, 46, 214, 193, 59, 15, 56, 142, 245, 135, 3, 220, 199, + 175, 74, 217, 54, 88, 212, 183, 216, 233, 121, 140, 91, 80, 122, + 71, 85, 83, 129, 103, 229, 21, 153, 249, 237, 255, 179, 173, 31, + 154, 196, 89, 59, 127, 196, 62, 187, 47, 23, 60, 215, 235, 99, + 205, 121, 244, 187, 38, 152, 245, 14, 27, 97, 137, 154, 8, 120, + 29, 45, 13, 48, 12, 38, 15, 150, 236, 10, 242, 73, 239, 43, + 247, 84, 76, 106, 235, 141, 142, 33, 200, 58, 50, 116, 21, 161, + 220, 204, 34, 174, 154, 26, 208, 122, 82, 130, 44, 244, 151, 198, + 96, 208, 81, 15, 104, 139, 188, 42, 234, 248, 67, 14, 161, 78, + 69, 59, 196, 214, 142, 53, 189, 61, 140, 206, 184, 200, 77, 52, + 203, 101, 169, 193, 153, 232, 191, 44, 231, 45, 233, 254, 77, 164, + 26, 31, 230, 141, 135, 244, 31, 197, 205, 126, 126, 64, 255, 174, + 195, 13, 83, 150, 15, 94, 183, 105, 207, 83, 83, 209, 11, 251, + 155, 123, 225, 215, 11, 73, 39, 224, 218, 61, 180, 84, 177, 39, + 200, 239, 103, 172, 12, 21, 11, 191, 133, 62, 65, 146, 48, 31, + 105, 164, 211, 187, 98, 40, 109, 139, 226, 113, 214, 95, 60, 2, + 73, 88, 13, 80, 3, 168, 49, 106, 243, 40, 81, 124, 53, 109, + 114, 57, 69, 197, 186, 68, 135, 29, 29, 143, 146, 249, 77, 72, + 164, 50, 52, 231, 100, 130, 183, 93, 157, 142, 113, 57, 216, 73, + 92, 17, 183, 98, 135, 31, 6, 218, 243, 239, 66, 74, 88, 131, + 200, 147, 243, 212, 163, 155, 147, 200, 8, 32, 56, 51, 71, 245, + 46, 238, 45, 131, 35, 219, 63, 192, 109, 66, 149, 28, 173, 168, + 124, 0, 101, 111, 148, 155, 29, 66, 32, 125, 30, 190, 9, 77, + 60, 8, 231, 66, 118, 224, 176, 33, 14, 143, 181, 255, 33, 129, + 8, 40, 153, 138, 197, 207, 49, 147, 228, 134, 177, 124, 113, 177, + 139, 151, 123, 149, 76, 128, 107, 151, 125, 25, 11, 138, 209, 56, + 6, 46, 199, 21, 134, 196, 151, 14, 157, 34, 98, 242, 56, 47, + 102, 32, 218, 1, 246, 193, 80, 221, 81, 0, 134, 42, 84, 141, + 233, 157, 131, 166, 58, 217, 188, 226, 217, 223, 130, 248, 12, 94, + 186, 84, 19, 176, 19, 134, 139, 61, 128, 61, 176, 108, 106, 23, + 111, 108, 72, 235, 149, 130, 219, 58, 54, 17, 251, 67, 244, 54, + 90, 9, 22, 83, 68, 196, 182, 225, 91, 137, 61, 98, 64, 174, + 87, 8, 82, 26, 171, 100, 38, 53, 71, 145, 200, 75, 170, 207, + 59, 165, 33, 23, 45, 236, 152, 30, 189, 103, 97, 201, 11, 177, + 22, 42, 246, 2, 218, 233, 35, 106, 228, 79, 242, 166, 146, 37, + 161, 43, 119, 187, 248, 23, 21, 3, 59, 188, 113, 207, 0, 29, + 227, 241, 4, 173, 26, 199, 27, 39, 94, 4, 194, 53, 165, 4, + 211, 157, 60, 54, 152, 152, 129, 79, 185, 32, 114, 211, 135, 13, + 221, 31, 124, 117, 126, 144, 43, 112, 220, 9, 98, 42, 164, 186, + 150, 52, 123, 105, 74, 251, 130, 224, 45, 229, 78, 31, 184, 143, + 158, 131, 112, 141, 96, 120, 17, 118, 6, 18, 119, 46, 241, 129, + 71, 40, 39, 41, 191, 159, 106, 96, 210, 122, 47, 79, 176, 129, + 202, 110, 163, 98, 178, 115, 171, 53, 19, 246, 141, 222, 236, 141, + 54, 187, 230, 218, 32, 180, 165, 8, 111, 152, 47, 205, 213, 255, + 212, 235, 164, 17, 143, 73, 222, 14, 209, 52, 135, 185, 94, 117, + 157, 61, 232, 162, 147, 160, 46, 27, 91, 9, 129, 120, 214, 229, + 3, 46, 150, 88, 4, 252, 237, 76, 160, 225, 30, 140, 197, 6, + 6, 175, 237, 124, 207, 20, 47, 127, 144, 62, 214, 30, 127, 253, + 6, 103, 11, 174, 149, 100, 190, 149, 143, 118, 56, 40, 178, 63, + 251, 242, 234, 99, 221, 227, 220, 46, 128, 181, 149, 87, 61, 176, + 218, 6, 72, 26, 243, 166, 172, 23, 194, 2, 168, 35, 22, 28, + 46, 240, 146, 212, 157, 124, 145, 112, 115, 32, 68, 3, 15, 163, + 74, 20, 56, 42, 164, 51, 40, 73, 89, 138, 213, 22, 109, 80, + 250, 131, 162, 239, 54, 151, 170, 144, 100, 56, 87, 205, 28, 52, + 191, 95, 108, 141, 94, 208, 144, 142, 241, 26, 200, 220, 147, 169, + 83, 243, 46, 122, 71, 89, 193, 13, 174, 234, 99, 123, 56, 68, + 202, 180, 122, 46, 116, 207, 166, 169, 204, 204, 107, 186, 29, 121, + 158, 194, 243, 109, 71, 114, 31, 244, 211, 116, 52, 251, 175, 103, + 79, 70, 225, 227, 116, 133, 129, 170, 114, 236, 58, 0, 146, 217, + 156, 34, 142, 251, 36, 105, 138, 210, 250, 165, 157, 218, 176, 160, + 170, 140, 60, 92, 196, 47, 111, 243, 0, 61, 164, 37, 39, 71, + 19, 141, 58, 126, 255, 128, 114, 19, 202, 27, 249, 159, 61, 241, + 29, 16, 66, 56, 92, 90, 167, 110, 140, 54, 159, 171, 163, 194, + 147, 211, 40, 72, 59, 64, 69, 49, 199, 131, 45, 220, 76, 195, + 53, 36, 239, 46, 57, 124, 125, 212, 95, 119, 36, 180, 81, 246, + 11, 235, 201, 96, 55, 255, 137, 28, 63, 99, 211, 253, 234, 46, + 16, 127, 112, 177, 39, 52, 82, 165, 104, 76, 170, 89, 196, 124, + 145, 165, 108, 115, 167, 180, 13, 136, 212, 93, 118, 231, 12, 201, + 14, 177, 36, 175, 154, 51, 114, 197, 204, 231, 73, 23, 105, 153, + 219, 70, 253, 212, 193, 65, 95, 39, 180, 165, 94, 216, 13, 25, + 123, 211, 67, 203, 80, 225, 183, 80, 189, 250, 106, 49, 194, 157, + 75, 76, 7, 77, 11, 231, 225, 73, 136, 212, 168, 220, 154, 208, + 120, 231, 220, 68, 96, 151, 78, 181, 203, 128, 51, 239, 152, 93, + 91, 163, 71, 235, 26, 233, 31, 204, 121, 0, 109, 119, 43, 201, + 185, 49, 107, 7, 190, 189, 220, 63, 89, 176, 189, 27, 166, 158, + 111, 41, 55, 173, 128, 71, 120, 64, 183, 86, 108, 173, 10, 212, + 120, 184, 151, 139, 157, 80, 54, 87, 107, 188, 139, 2, 74, 98, + 160, 164, 30, 215, 247, 215, 185, 98, 116, 68, 31, 254, 203, 161, + 146, 77, 50, 114, 171, 138, 73, 38, 157, 83, 0, 163, 189, 63, + 230, 141, 38, 15, 10, 126, 3, 119, 50, 230, 140, 102, 137, 129, + 223, 110, 138, 248, 52, 147, 19, 91, 33, 50, 4, 51, 94, 50, + 61, 131, 78, 159, 48, 224, 16, 10, 44, 126, 29, 248, 176, 120, + 106, 147, 185, 237, 230, 204, 105, 218, 174, 22, 188, 117, 189, 147, + 156, 65, 240, 229, 123, 124, 14, 41, 182, 70, 55, 209, 201, 120, + 99, 138, 84, 43, 57, 172, 159, 219, 216, 116, 221, 109, 53, 19, + 140, 148, 162, 103, 5, 170, 210, 127, 124, 158, 145, 231, 221, 216, + 252, 204, 179, 94, 205, 79, 150, 115, 69, 187, 175, 175, 87, 221, + 74, 134, 149, 163, 208, 119, 227, 155, 198, 121, 220, 224, 215, 83, + 118, 181, 129, 97, 134, 107, 243, 85, 4, 103, 97, 34, 173, 65, + 229, 196, 118, 10, 15, 209, 26, 241, 193, 211, 146, 82, 45, 18, + 52, 255, 192, 21, 82, 213, 240, 151, 225, 59, 164, 50, 158, 120, + 243, 255, 75, 143, 23, 198, 212, 90, 46, 9, 116, 214, 14, 222, + 206, 182, 131, 129, 228, 201, 3, 148, 163, 240, 174, 2, 41, 228, + 33, 219, 240, 240, 44, 216, 124, 248, 1, 1, 215, 86, 8, 204, + 226, 180, 151, 250, 48, 46, 58, 165, 246, 191, 107, 44, 48, 131, + 27, 18, 210, 109, 221, 154, 252, 252, 183, 193, 84, 106, 27, 125, + 190, 62, 124, 123, 221, 94, 252, 129, 249, 83, 158, 207, 193, 87, + 170, 114, 204, 117, 189, 212, 214, 167, 34, 63, 26, 65, 142, 35, + 171, 90, 32, 214, 166, 88, 86, 41, 114, 160, 199, 55, 81, 239, + 87, 113, 39, 142, 98, 25, 97, 72, 144, 38, 66, 106, 4, 25, + 46, 222, 59, 68, 24, 205, 68, 195, 56, 22, 33, 126, 17, 58, + 29, 230, 203, 181, 2, 236, 49, 35, 78, 152, 86, 234, 230, 161, + 178, 79, 156, 147, 120, 245, 238, 207, 122, 33, 32, 119, 76, 37, + 65, 67, 37, 196, 167, 175, 167, 89, 138, 172, 245, 49, 65, 62, + 0, 80, 212, 24, 137, 96, 193, 128, 4, 174, 61, 106, 152, 61, + 229, 131, 191, 168, 229, 182, 109, 180, 60, 67, 101, 105, 131, 148, + 19, 163, 6, 187, 21, 218, 92, 183, 254, 0, 241, 104, 232, 243, + 151, 188, 120, 29, 252, 47, 25, 223, 76, 123, 255, 87, 182, 10, + 20, 28, 165, 175, 220, 137, 77, 196, 239, 167, 162, 41, 222, 38, + 86, 216, 167, 186, 68, 78, 45, 213, 158, 108, 135, 145, 154, 37, + 31, 195, 171, 245, 239, 33, 151, 227, 178, 108, 115, 115, 7, 224, + 246, 72, 222, 5, 99, 138, 226, 78, 235, 27, 144, 99, 145, 49, + 61, 20, 202, 7, 109, 162, 70, 202, 30, 234, 27, 197, 103, 200, + 85, 228, 118, 92, 73, 212, 157, 135, 190, 114, 76, 223, 170, 16, + 215, 171, 184, 135, 40, 149, 220, 229, 132, 64, 238, 242, 122, 187, + 50, 20, 95, 211, 0, 4, 237, 231, 140, 200, 230, 244, 255, 4, + 35, 76, 135, 121, 120, 225, 38, 18, 18, 247, 48, 43, 162, 24, + 12, 229, 129, 113, 50, 168, 79, 11, 21, 139, 43, 216, 67, 136, + 19, 138, 223, 106, 18, 156, 36, 80, 141, 27, 210, 71, 185, 84, + 17, 10, 99, 233, 97, 81, 220, 208, 102, 53, 34, 15, 185, 132, + 149, 178, 114, 216, 43, 197, 237, 196, 17, 79, 128, 38, 254, 217, + 96, 118, 96, 164, 64, 88, 75, 195, 206, 140, 230, 20, 2, 106, + 70, 104, 45, 128, 26, 57, 85, 29, 125, 93, 69, 240, 32, 41, + 208, 81, 163, 87, 112, 157, 17, 97, 109, 170, 104, 146, 72, 209, + 163, 219, 25, 35, 151, 60, 128, 9, 177, 7, 150, 103, 166, 62, + 163, 47, 220, 179, 15, 30, 171, 69, 131, 97, 101, 173, 5, 223, + 134, 106, 174, 185, 231, 98, 249, 229, 114, 30, 55, 246, 238, 156, + 254, 47, 251, 227, 86, 66, 184, 150, 29, 173, 177, 158, 13, 170, + 42, 30, 106, 96, 66, 234, 54, 116, 166, 246, 74, 71, 213, 40, + 171, 198, 164, 219, 72, 214, 123, 11, 123, 16, 169, 177, 209, 57, + 182, 124, 150, 77, 41, 208, 250, 216, 177, 152, 221, 75, 188, 42, + 168, 229, 42, 67, 192, 21, 247, 24, 224, 119, 219, 240, 177, 118, + 143, 216, 200, 30, 71, 178, 57, 207, 3, 116, 75, 210, 127, 68, + 9, 209, 163, 46, 77, 160, 172, 140, 113, 142, 87, 62, 10, 219, + 169, 45, 171, 188, 127, 52, 148, 207, 187, 55, 33, 140, 39, 231, + 84, 173, 72, 131, 204, 15, 234, 160, 247, 48, 228, 148, 32, 247, + 222, 133, 10, 81, 197, 204, 107, 116, 77, 79, 98, 57, 163, 51, + 108, 245, 136, 205, 144, 102, 251, 188, 194, 204, 251, 79, 83, 110, + 35, 112, 138, 169, 165, 172, 221, 167, 181, 81, 247, 145, 38, 171, + 196, 162, 212, 234, 226, 154, 191, 155, 231, 41, 203, 224, 223, 68, + 247, 130, 212, 34, 109, 205, 50, 169, 239, 142, 148, 10, 67, 89, + 200, 93, 221, 40, 195, 210, 112, 118, 83, 11, 73, 73, 157, 46, + 254, 22, 203, 103, 83, 92, 9, 111, 244, 209, 252, 146, 209, 123, + 14, 235, 203, 81, 59, 196, 155, 19, 129, 54, 132, 220, 89, 127, + 229, 185, 47, 202, 91, 83, 89, 95, 192, 201, 125, 3, 96, 15, + 232, 195, 247, 184, 208, 61, 129, 189, 45, 131, 199, 27, 160, 126, + 253, 169, 78, 71, 88, 1, 206, 222, 140, 144, 234, 130, 40, 79, + 204, 82, 18, 37, 251, 229, 209, 62, 69, 130, 203, 252, 74, 99, + 100, 29, 159, 35, 248, 0, 183, 212, 31, 58, 155, 195, 96, 42, + 146, 192, 43, 17, 74, 239, 34, 16, 61, 114, 75, 30, 253, 50, + 227, 217, 140, 243, 185, 248, 118, 87, 193, 18, 193, 25, 14, 114, + 37, 190, 93, 155, 56, 204, 187, 238, 13, 223, 33, 241, 88, 32, + 36, 178, 105, 119, 234, 126, 10, 37, 209, 126, 6, 171, 182, 123, + 115, 39, 29, 180, 19, 189, 120, 58, 69, 113, 207, 138, 111, 168, + 81, 16, 78, 141, 27, 166, 140, 245, 89, 54, 11, 192, 122, 102, + 10, 215, 161, 83, 16, 202, 103, 64, 138, 150, 188, 111, 37, 190, + 115, 173, 81, 12, 171, 17, 221, 214, 44, 90, 214, 20, 69, 151, + 134, 23, 231, 71, 202, 181, 47, 92, 35, 153, 163, 7, 26, 11, + 99, 89, 2, 185, 81, 15, 150, 228, 54, 2, 189, 102, 230, 195, + 102, 191, 124, 94, 242, 66, 178, 25, 240, 68, 12, 227, 139, 110, + 201, 224, 130, 162, 151, 127, 221, 194, 226, 35, 183, 154, 220, 148, + 192, 105, 125, 101, 73, 164, 32, 131, 95, 46, 87, 10, 57, 15, + 75, 2, 235, 248, 69, 236, 96, 36, 215, 202, 97, 182, 157, 60, + 190, 174, 12, 247, 145, 83, 75, 62, 98, 44, 191, 200, 18, 169, + 164, 62, 66, 109, 169, 16, 243, 203, 29, 199, 179, 3, 250, 199, + 206, 173, 34, 52, 195, 43, 141, 28, 61, 192, 12, 46, 209, 98, + 25, 174, 143, 215, 46, 40, 138, 184, 13, 175, 193, 219, 92, 210, + 36, 39, 71, 124, 29, 81, 190, 11, 134, 233, 101, 143, 236, 87, + 132, 128, 131, 143, 13, 97, 47, 185, 21, 4, 37, 181, 61, 104, + 73, 218, 252, 91, 228, 243, 122, 93, 209, 105, 190, 116, 102, 170, + 18, 134, 161, 25, 124, 27, 108, 251, 46, 171, 142, 79, 64, 123, + 191, 12, 195, 2, 219, 142, 76, 122, 82, 192, 249, 51, 112, 150, + 96, 194, 22, 60, 242, 157, 89, 30, 23, 53, 206, 186, 104, 74, + 7, 166, 100, 206, 113, 99, 235, 255, 140, 103, 241, 206, 39, 154, + 148, 153, 68, 251, 237, 184, 161, 223, 42, 115, 177, 102, 251, 231, + 85, 109, 176, 204, 63, 168, 115, 134, 233, 65, 169, 158, 220, 167, + 75, 250, 11, 137, 6, 252, 11, 59, 227, 16, 124, 66, 144, 3, + 14, 153, 20, 13, 57, 160, 105, 176, 189, 104, 131, 139, 20, 197, + 1, 174, 43, 65, 179, 135, 187, 99, 88, 78, 144, 244, 207, 154, + 131, 192, 118, 20, 114, 193, 151, 214, 129, 231, 119, 41, 168, 61, + 101, 112, 190, 40, 230, 127, 162, 151, 54, 93, 90, 231, 3, 220, + 175, 141, 3, 170, 127, 222, 160, 175, 81, 221, 103, 187, 116, 183, + 100, 223, 221, 172, 72, 205, 188, 28, 73, 2, 231, 110, 106, 22, + 19, 28, 162, 42, 186, 51, 69, 191, 196, 239, 174, 59, 152, 164, + 18, 92, 175, 65, 103, 182, 16, 211, 35, 21, 43, 140, 144, 155, + 53, 249, 216, 190, 22, 152, 28, 150, 72, 144, 147, 244, 241, 126, + 151, 28, 203, 60, 144, 80, 177, 101, 61, 43, 102, 122, 49, 139, + 94, 172, 245, 209, 36, 114, 244, 199, 49, 252, 95, 11, 69, 94, + 22, 144, 123, 109, 246, 61, 164, 56, 44, 227, 191, 135, 122, 155, + 84, 2, 210, 117, 88, 243, 132, 22, 81, 217, 229, 49, 54, 149, + 161, 154, 52, 123, 196, 64, 35, 232, 133, 35, 99, 11, 81, 165, + 82, 142, 162, 211, 212, 31, 201, 63, 91, 218, 76, 254, 238, 23, + 185, 144, 243, 195, 196, 0, 84, 148, 14, 77, 115, 229, 51, 225, + 218, 83, 52, 25, 39, 54, 161, 202, 193, 176, 28, 114, 223, 102, + 154, 208, 55, 196, 251, 99, 186, 194, 56, 42, 57, 168, 225, 119, + 141, 174, 73, 31, 188, 51, 217, 92, 120, 96, 124, 23, 31, 237, + 234, 42, 138, 182, 188, 72, 220, 0, 77, 125, 37, 172, 152, 237, + 116, 205, 214, 94, 154, 129, 8, 54, 208, 238, 217, 148, 5, 254, + 155, 153, 98, 140, 213, 234, 14, 24, 220, 91, 26, 250, 223, 203, + 96, 81, 217, 80, 58, 64, 245, 248, 3, 239, 67, 253, 16, 213, + 153, 67, 215, 140, 84, 177, 136, 106, 126, 206, 101, 154, 170, 197, + 74, 99, 45, 63, 28, 216, 55, 100, 209, 226, 112, 94, 239, 7, + 91, 77, 139, 208, 35, 85, 166, 126, 22, 176, 56, 75, 152, 122, + 179, 217, 89, 255, 246, 194, 146, 159, 203, 118, 162, 151, 80, 106, + 211, 101, 248, 215, 233, 81, 3, 21, 123, 26, 137, 74, 187, 103, + 151, 157, 155, 174, 205, 197, 41, 151, 105, 191, 138, 60, 71, 72, + 249, 192, 131, 124, 52, 241, 245, 54, 147, 51, 212, 122, 239, 228, + 99, 193, 113, 154, 102, 18, 224, 160, 104, 36, 111, 54, 126, 136, + 131, 252, 155, 155, 13, 151, 106, 150, 62, 241, 120, 176, 6, 52, + 57, 232, 141, 246, 33, 153, 143, 95, 38, 211, 207, 241, 72, 148, + 251, 181, 9, 156, 60, 185, 143, 58, 227, 140, 188, 199, 96, 85, + 150, 78, 187, 30, 82, 106, 144, 36, 187, 30, 34, 9, 43, 35, + 113, 119, 94, 122, 193, 10, 117, 50, 93, 221, 103, 189, 5, 217, + 220, 157, 201, 118, 107, 96, 75, 77, 189, 154, 77, 224, 18, 54, + 230, 181, 97, 39, 91, 5, 14, 128, 49, 0, 157, 30, 223, 141, + 199, 47, 102, 110, 165, 212, 132, 195, 100, 80, 114, 46, 122, 186, + 225, 83, 61, 63, 222, 217, 46, 197, 202, 199, 65, 110, 78, 110, + 250, 30, 237, 135, 200, 160, 58, 64, 7, 236, 153, 33, 79, 246, + 110, 48, 238, 10, 231, 7, 240, 95, 142, 18, 40, 236, 6, 190, + 82, 12, 154, 62, 170, 146, 242, 32, 155, 176, 187, 249, 93, 74, + 161, 8, 60, 156, 19, 193, 31, 50, 94, 59, 208, 36, 114, 245, + 228, 247, 14, 97, 9, 179, 48, 194, 128, 129, 198, 252, 180, 84, + 228, 185, 119, 37, 110, 38, 28, 92, 181, 231, 171, 228, 217, 247, + 54, 60, 67, 128, 33, 133, 179, 217, 200, 106, 29, 54, 74, 130, + 1, 140, 61, 190, 53, 86, 38, 9, 63, 18, 59, 227, 43, 214, + 139, 36, 42, 224, 129, 120, 193, 189, 57, 83, 184, 223, 55, 158, + 50, 188, 117, 250, 71, 225, 210, 164, 119, 127, 224, 56, 192, 158, + 167, 79, 106, 63, 166, 72, 57, 153, 87, 242, 150, 120, 28, 80, + 144, 61, 195, 233, 84, 44, 21, 124, 204, 150, 147, 106, 35, 92, + 254, 146, 87, 165, 80, 34, 50, 150, 218, 20, 105, 87, 148, 130, + 60, 115, 65, 161, 133, 41, 216, 85, 134, 241, 225, 151, 221, 158, + 124, 106, 11, 92, 61, 151, 235, 48, 96, 184, 84, 250, 165, 211, + 113, 187, 214, 130, 21, 39, 233, 225, 45, 14, 112, 51, 227, 134, + 48, 139, 139, 153, 163, 184, 174, 162, 74, 105, 52, 195, 197, 30, + 240, 49, 229, 190, 10, 31, 212, 34, 143, 136, 5, 223, 48, 192, + 65, 68, 117, 163, 179, 191, 208, 174, 7, 85, 73, 198, 211, 90, + 228, 124, 182, 0, 184, 37, 69, 126, 153, 208, 181, 254, 82, 128, + 161, 9, 222, 72, 53, 44, 97, 155, 247, 224, 48, 76, 114, 213, + 102, 255, 249, 250, 237, 32, 95, 163, 88, 59, 144, 1, 75, 252, + 77, 4, 126, 234, 69, 33, 154, 234, 249, 130, 119, 19, 13, 159, + 8, 180, 223, 145, 185, 131, 153, 175, 255, 21, 101, 222, 69, 91, + 170, 203, 126, 40, 147, 125, 213, 14, 155, 51, 180, 183, 76, 42, + 238, 93, 127, 154, 141, 236, 125, 249, 56, 249, 89, 247, 8, 106, + 97, 137, 169, 111, 109, 57, 223, 206, 210, 101, 141, 117, 152, 214, + 83, 246, 36, 156, 135, 76, 54, 183, 52, 182, 184, 143, 26, 248, + 154, 212, 78, 50, 87, 14, 128, 191, 252, 118, 190, 3, 21, 248, + 34, 244, 196, 79, 129, 250, 45, 235, 231, 147, 15, 20, 22, 75, + 144, 207, 112, 108, 188, 16, 100, 31, 94, 64, 45, 139, 103, 240, + 31, 122, 142, 0, 87, 228, 158, 121, 167, 128, 137, 163, 0, 34, + 89, 193, 237, 184, 95, 232, 77, 248, 241, 66, 142, 161, 235, 48, + 174, 135, 223, 172, 127, 135, 8, 100, 34, 97, 120, 42, 153, 61, + 253, 193, 120, 105, 84, 146, 78, 80, 160, 189, 188, 175, 136, 19, + 75, 102, 121, 248, 170, 163, 57, 231, 9, 215, 37, 8, 119, 188, + 204, 233, 99, 248, 155, 161, 69, 31, 243, 152, 26, 133, 123, 212, + 9, 37, 183, 210, 82, 232, 17, 149, 6, 17, 47, 59, 4, 246, + 217, 33, 240, 202, 137, 171, 190, 229, 21, 1, 187, 51, 194, 74, + 143, 21, 28, 157, 118, 181, 79, 109, 101, 186, 188, 71, 197, 255, + 88, 88, 103, 195, 73, 72, 175, 223, 145, 206, 165, 55, 253, 66, + 221, 53, 115, 59, 94, 20, 147, 245, 122, 1, 231, 90, 161, 251, + 238, 202, 61, 10, 236, 62, 78, 24, 132, 26, 160, 215, 146, 123, + 178, 158, 160, 70, 217, 84, 170, 7, 26, 29, 73, 195, 114, 28, + 137, 32, 118, 139, 98, 140, 143, 71, 205, 189, 63, 186, 230, 28, + 0, 49, 206, 0, 179, 222, 36, 14, 164, 206, 119, 194, 167, 128, + 61, 31, 11, 109, 64, 167, 184, 116, 120, 113, 103, 96, 83, 72, + 77, 234, 43, 125, 58, 178, 193, 17, 131, 42, 88, 129, 144, 146, + 247, 27, 107, 154, 148, 215, 208, 215, 5, 133, 192, 171, 47, 90, + 206, 121, 141, 247, 70, 136, 32, 162, 55, 252, 194, 40, 109, 210, + 196, 233, 145, 111, 239, 76, 239, 239, 226, 6, 176, 169, 187, 251, + 204, 168, 98, 46, 240, 10, 140, 137, 59, 223, 35, 45, 198, 73, + 147, 172, 222, 97, 13, 226, 184, 163, 178, 180, 203, 253, 57, 247, + 79, 1, 79, 242, 125, 89, 170, 34, 156, 110, 204, 23, 22, 178, + 140, 93, 189, 161, 241, 38, 142, 67, 79, 228, 251, 204, 172, 28, + 109, 93, 41, 110, 159, 118, 209, 198, 243, 14, 99, 8, 11, 228, + 231, 205, 189, 139, 235, 70, 63, 229, 23, 198, 66, 205, 82, 188, + 246, 42, 85, 108, 173, 111, 15, 67, 134, 24, 140, 208, 68, 88, + 17, 248, 111, 22, 116, 170, 3, 171, 131, 66, 140, 102, 94, 157, + 212, 176, 21, 3, 210, 251, 231, 140, 27, 7, 61, 53, 248, 197, + 33, 126, 138, 78, 74, 39, 75, 65, 87, 232, 122, 18, 222, 229, + 27, 193, 174, 145, 157, 26, 246, 3, 134, 71, 138, 254, 83, 113, + 240, 252, 192, 127, 36, 190, 92, 216, 166, 3, 188, 196, 221, 167, + 39, 209, 52, 203, 118, 123, 0, 153, 2, 151, 195, 236, 1, 117, + 64, 99, 27, 34, 171, 86, 193, 127, 7, 27, 80, 181, 151, 185, + 73, 102, 41, 20, 37, 27, 239, 85, 99, 230, 154, 208, 241, 236, + 19, 9, 48, 69, 200, 6, 227, 206, 32, 43, 104, 42, 212, 225, + 5, 57, 1, 146, 158, 109, 76, 183, 6, 233, 129, 244, 71, 71, + 34, 152, 27, 215, 176, 249, 200, 134, 44, 45, 92, 217, 58, 229, + 34, 237, 157, 1, 85, 168, 253, 208, 85, 102, 191, 23, 20, 28, + 18, 58, 185, 137, 212, 246, 94, 214, 131, 243, 101, 38, 212, 48, + 44, 168, 164, 143, 135, 49, 34, 115, 200, 117, 142, 156, 206, 145, + 187, 117, 218, 81, 144, 134, 202, 121, 119, 24, 233, 132, 155, 165, + 11, 134, 204, 136, 201, 45, 156, 131, 172, 171, 214, 142, 43, 70, + 184, 243, 108, 163, 173, 162, 214, 46, 117, 91, 182, 49, 241, 5, + 215, 124, 223, 24, 162, 106, 36, 57, 149, 153, 237, 92, 187, 209, + 15, 4, 104, 58, 25, 212, 253, 61, 34, 125, 208, 59, 197, 25, + 64, 138, 57, 199, 132, 110, 39, 109, 84, 58, 1, 54, 177, 187, + 154, 17, 196, 134, 188, 83, 111, 154, 127, 57, 170, 78, 56, 85, + 191, 168, 109, 19, 11, 85, 45, 155, 195, 142, 147, 250, 98, 7, + 7, 156, 160, 179, 227, 183, 101, 155, 19, 174, 164, 122, 64, 184, + 236, 102, 162, 154, 222, 45, 138, 175, 94, 185, 224, 21, 164, 13, + 236, 18, 33, 195, 113, 227, 218, 161, 231, 22, 46, 80, 26, 239, + 253, 215, 158, 205, 86, 7, 56, 247, 16, 59, 233, 45, 38, 143, + 216, 91, 4, 82, 112, 99, 182, 62, 139, 225, 252, 101, 26, 154, + 254, 161, 112, 83, 62, 92, 245, 235, 88, 174, 31, 87, 176, 221, + 198, 9, 165, 0, 199, 65, 218, 90, 138, 192, 158, 248, 98, 159, + 18, 187, 216, 171, 122, 19, 117, 90, 235, 129, 65, 220, 64, 120, + 107, 77, 188, 195, 89, 74, 123, 175, 88, 197, 151, 155, 32, 107, + 84, 236, 200, 46, 205, 187, 118, 17, 255, 160, 155, 230, 231, 140, + 37, 74, 193, 63, 63, 220, 124, 11, 103, 211, 92, 194, 187, 226, + 20, 18, 143, 115, 16, 205, 219, 100, 210, 163, 11, 174, 154, 44, + 163, 144, 12, 79, 55, 29, 98, 14, 27, 22, 135, 233, 208, 55, + 101, 66, 104, 16, 42, 215, 229, 3, 75, 136, 196, 162, 232, 118, + 131, 159, 10, 212, 101, 140, 92, 144, 53, 136, 37, 174, 160, 121, + 19, 150, 101, 214, 28, 239, 69, 29, 201, 145, 178, 122, 99, 135, + 0, 41, 156, 68, 47, 37, 110, 232, 235, 155, 91, 68, 197, 251, + 207, 108, 187, 127, 77, 37, 87, 150, 219, 13, 89, 32, 243, 31, + 156, 249, 87, 154, 214, 79, 233, 94, 11, 200, 15, 19, 107, 108, + 144, 49, 43, 94, 152, 201, 124, 3, 93, 114, 86, 161, 236, 178, + 162, 49, 60, 180, 105, 190, 237, 136, 196, 191, 170, 41, 106, 71, + 207, 49, 81, 102, 229, 138, 189, 0, 17, 167, 52, 254, 124, 174, + 195, 129, 106, 102, 205, 160, 107, 18, 173, 39, 195, 219, 185, 200, + 26, 76, 30, 18, 30, 191, 109, 66, 20, 163, 13, 21, 229, 207, + 173, 215, 81, 155, 201, 0, 178, 23, 160, 248, 17, 30, 195, 120, + 178, 224, 207, 227, 114, 220, 117, 51, 15, 2, 0, 58, 219, 55, + 174, 94, 48, 24, 57, 198, 239, 206, 197, 28, 168, 225, 0, 204, + 11, 172, 185, 57, 105, 22, 119, 81, 217, 68, 73, 90, 251, 2, + 157, 57, 17, 90, 159, 185, 22, 163, 182, 195, 159, 158, 134, 137, + 193, 197, 11, 108, 189, 230, 45, 208, 88, 6, 255, 50, 4, 122, + 226, 147, 222, 133, 207, 66, 253, 30, 210, 126, 139, 37, 102, 40, + 36, 215, 76, 163, 183, 145, 182, 12, 250, 97, 132, 192, 95, 246, + 246, 76, 94, 254, 104, 39, 162, 232, 55, 131, 31, 250, 56, 76, + 203, 104, 188, 225, 87, 119, 38, 222, 224, 118, 17, 67, 251, 203, + 146, 87, 66, 74, 50, 137, 129, 219, 103, 12, 245, 203, 208, 60, + 52, 110, 194, 135, 193, 27, 131, 82, 231, 241, 127, 145, 201, 190, + 160, 4, 80, 92, 68, 198, 158, 81, 109, 88, 255, 236, 37, 81, + 161, 86, 48, 3, 118, 84, 244, 235, 223, 177, 220, 204, 81, 142, + 17, 238, 209, 167, 56, 119, 240, 241, 7, 213, 109, 107, 217, 71, + 255, 232, 210, 147, 171, 224, 103, 53, 113, 222, 87, 1, 3, 112, + 3, 232, 149, 144, 224, 74, 249, 34, 126, 107, 39, 55, 20, 97, + 190, 36, 214, 97, 110, 77, 145, 41, 179, 56, 20, 150, 112, 171, + 190, 62, 166, 36, 179, 224, 240, 143, 86, 229, 248, 175, 73, 229, + 92, 106, 26, 141, 12, 30, 188, 70, 98, 116, 237, 240, 169, 218, + 22, 19, 80, 125, 56, 221, 204, 106, 80, 108, 223, 85, 63, 174, + 111, 47, 44, 238, 255, 103, 146, 176, 97, 236, 131, 228, 153, 230, + 177, 137, 216, 101, 73, 126, 107, 14, 148, 84, 68, 48, 53, 49, + 159, 202, 67, 66, 180, 120, 56, 67, 8, 74, 94, 86, 163, 85, + 177, 68, 204, 154, 214, 10, 52, 52, 55, 144, 104, 68, 22, 91, + 10, 188, 251, 109, 78, 124, 153, 146, 136, 87, 74, 46, 16, 148, + 157, 77, 166, 52, 255, 107, 54, 0, 213, 72, 220, 85, 9, 34, + 19, 43, 182, 163, 149, 2, 181, 228, 170, 143, 99, 181, 250, 169, + 34, 169, 224, 47, 187, 75, 114, 202, 48, 235, 217, 7, 183, 252, + 154, 27, 45, 58, 194, 210, 255, 51, 63, 247, 241, 27, 29, 142, + 191, 1, 214, 241, 59, 186, 236, 248, 71, 26, 194, 207, 53, 7, + 134, 41, 220, 77, 96, 148, 135, 126, 111, 250, 61, 254, 125, 242, + 37, 28, 122, 241, 206, 220, 111, 135, 77, 37, 89, 45, 161, 177, + 154, 63, 251, 145, 204, 193, 232, 100, 127, 216, 70, 168, 49, 79, + 222, 179, 252, 51, 31, 155, 211, 196, 83, 145, 114, 100, 59, 66, + 26, 247, 126, 3, 83, 31, 140, 122, 230, 62, 230, 61, 52, 166, + 47, 76, 147, 6, 4, 122, 94, 74, 255, 35, 77, 105, 96, 21, + 83, 163, 147, 20, 143, 186, 197, 243, 185, 57, 63, 98, 0, 118, + 12, 35, 48, 156, 42, 183, 107, 48, 159, 110, 199, 119, 157, 115, + 63, 83, 31, 246, 97, 160, 55, 165, 117, 79, 183, 102, 74, 243, + 72, 138, 220, 149, 106, 141, 112, 121, 41, 22, 75, 65, 145, 235, + 20, 38, 235, 161, 68, 117, 230, 57, 37, 49, 95, 100, 114, 8, + 212, 176, 118, 154, 15, 38, 21, 231, 237, 104, 254, 52, 41, 59, + 218, 5, 135, 9, 120, 21, 213, 101, 147, 210, 106, 169, 208, 94, + 25, 230, 115, 162, 212, 64, 150, 236, 108, 229, 250, 129, 218, 31, + 231, 188, 98, 243, 7, 59, 231, 37, 2, 6, 246, 156, 242, 142, + 32, 152, 82, 236, 65, 209, 33, 209, 78, 165, 184, 195, 199, 161, + 248, 22, 133, 141, 107, 67, 0, 121, 108, 74, 245, 79, 127, 125, + 51, 20, 176, 86, 128, 96, 83, 23, 238, 143, 126, 176, 238, 200, + 190, 198, 205, 57, 127, 134, 52, 208, 252, 56, 250, 228, 138, 15, + 172, 243, 126, 73, 216, 234, 211, 44, 162, 187, 8, 189, 149, 15, + 58, 50, 29, 196, 64, 202, 20, 106, 111, 152, 79, 146, 182, 162, + 169, 205, 34, 143, 41, 238, 136, 105, 109, 20, 149, 148, 65, 179, + 134, 5, 161, 109, 12, 2, 212, 87, 130, 244, 123, 249, 91, 12, + 166, 6, 165, 26, 235, 44, 39, 167, 249, 151, 116, 6, 66, 110, + 107, 2, 119, 71, 208, 8, 28, 213, 166, 251, 204, 186, 68, 165, + 54, 109, 1, 189, 244, 5, 247, 251, 206, 112, 231, 51, 137, 232, + 225, 147, 121, 190, 141, 218, 22, 229, 55, 207, 19, 175, 139, 85, + 78, 39, 10, 53, 23, 145, 207, 147, 34, 89, 223, 89, 253, 129, + 111, 88, 246, 163, 95, 164, 191, 37, 188, 231, 133, 86, 75, 170, + 225, 241, 251, 77, 165, 17, 68, 149, 67, 67, 0, 210, 221, 83, + 27, 210, 252, 9, 255, 44, 32, 200, 13, 201, 180, 166, 135, 187, + 227, 6, 83, 84, 206, 185, 254, 16, 175, 69, 150, 79, 160, 106, + 101, 229, 63, 78, 177, 143, 89, 104, 164, 19, 155, 155, 95, 162, + 235, 243, 166, 127, 207, 141, 255, 161, 7, 231, 57, 214, 65, 212, + 121, 241, 1, 56, 65, 197, 6, 224, 8, 170, 7, 95, 161, 32, + 3, 153, 83, 90, 139, 184, 79, 151, 2, 48, 169, 32, 114, 105, + 56, 193, 48, 72, 144, 107, 111, 53, 165, 216, 24, 203, 14, 160, + 43, 152, 206, 213, 151, 76, 41, 194, 33, 204, 252, 109, 111, 3, + 226, 174, 224, 227, 129, 122, 59, 68, 8, 103, 172, 108, 93, 78, + 247, 236, 229, 133, 218, 192, 197, 125, 114, 7, 48, 162, 23, 193, + 107, 231, 27, 47, 137, 90, 136, 137, 139, 247, 104, 154, 117, 76, + 146, 5, 197, 14, 77, 143, 19, 254, 214, 216, 96, 99, 26, 20, + 229, 231, 28, 247, 126, 135, 32, 153, 250, 193, 253, 87, 248, 124, + 92, 179, 254, 212, 155, 11, 70, 153, 144, 48, 25, 250, 130, 44, + 45, 130, 5, 18, 46, 235, 178, 238, 15, 214, 147, 54, 231, 165, + 147, 207, 193, 179, 170, 221, 142, 107, 176, 220, 230, 71, 220, 68, + 147, 61, 71, 57, 187, 214, 198, 188, 28, 176, 133, 205, 9, 123, + 45, 100, 69, 8, 21, 85, 252, 11, 126, 236, 73, 146, 18, 165, + 101, 52, 223, 244, 240, 148, 226, 58, 247, 57, 71, 19, 237, 254, + 189, 59, 166, 225, 210, 81, 196, 199, 61, 29, 143, 243, 59, 195, + 212, 118, 210, 177, 181, 33, 236, 63, 201, 119, 63, 221, 210, 63, + 200, 8, 193, 123, 4, 40, 102, 125, 15, 67, 210, 226, 50, 155, + 150, 2, 15, 154, 199, 130, 30, 123, 232, 155, 183, 110, 245, 46, + 56, 43, 49, 164, 61, 238, 98, 130, 87, 226, 115, 38, 148, 28, + 142, 48, 195, 19, 173, 88, 156, 160, 27, 149, 155, 162, 56, 107, + 56, 141, 112, 180, 125, 191, 244, 0, 228, 107, 234, 127, 205, 255, + 6, 56, 109, 24, 111, 43, 150, 123, 202, 187, 114, 210, 252, 219, + 225, 67, 136, 241, 88, 1, 155, 54, 74, 218, 193, 186, 252, 177, + 175, 106, 45, 132, 36, 15, 189, 72, 218, 72, 244, 17, 163, 212, + 116, 21, 122, 143, 211, 13, 142, 157, 167, 243, 109, 223, 130, 36, + 72, 102, 161, 241, 60, 242, 161, 220, 179, 206, 165, 129, 218, 214, + 248, 115, 5, 150, 248, 195, 158, 176, 20, 73, 130, 86, 85, 101, + 42, 59, 166, 52, 198, 107, 178, 72, 195, 139, 53, 121, 15, 38, + 123, 237, 179, 85, 220, 117, 209, 142, 18, 189, 81, 206, 62, 158, + 214, 21, 21, 145, 199, 161, 15, 232, 170, 129, 32, 147, 94, 170, + 117, 149, 114, 105, 0, 14, 68, 57, 30, 139, 68, 45, 246, 176, + 232, 80, 84, 186, 53, 52, 183, 203, 209, 130, 33, 17, 106, 197, + 242, 61, 208, 12, 108, 72, 174, 10, 131, 217, 35, 209, 107, 60, + 79, 190, 183, 16, 131, 103, 153, 149, 47, 29, 236, 183, 220, 221, + 115, 212, 182, 220, 116, 27, 163, 192, 193, 114, 143, 112, 246, 29, + 104, 119, 71, 197, 180, 77, 59, 130, 161, 51, 250, 115, 227, 199, + 16, 109, 227, 10, 11, 69, 169, 75, 112, 247, 161, 147, 251, 89, + 46, 146, 251, 204, 87, 106, 102, 91, 26, 24, 47, 22, 119, 71, + 161, 102, 114, 183, 229, 47, 178, 71, 136, 81, 30, 213, 136, 226, + 90, 46, 9, 181, 65, 251, 141, 36, 71, 153, 123, 243, 131, 192, + 65, 210, 5, 7, 248, 21, 242, 34, 97, 250, 50, 19, 71, 12, + 113, 160, 148, 205, 77, 47, 138, 210, 135, 30, 252, 21, 233, 120, + 177, 92, 227, 161, 77, 245, 4, 74, 95, 42, 126, 217, 31, 222, + 197, 151, 159, 255, 30, 130, 201, 65, 152, 249, 150, 252, 93, 117, + 254, 201, 176, 192, 7, 244, 197, 2, 66, 228, 18, 102, 176, 41, + 77, 215, 28, 48, 161, 239, 102, 19, 143, 68, 63, 153, 180, 246, + 144, 168, 73, 25, 63, 140, 96, 145, 201, 169, 84, 145, 195, 65, + 226, 122, 250, 166, 131, 109, 63, 137, 203, 80, 224, 152, 36, 1, + 120, 50, 234, 8, 202, 67, 143, 148, 255, 160, 183, 88, 24, 28, + 26, 80, 200, 120, 17, 153, 183, 128, 80, 210, 108, 181, 142, 186, + 0, 92, 219, 228, 91, 55, 79, 200, 41, 68, 136, 166, 117, 91, + 213, 229, 7, 63, 120, 162, 80, 96, 225, 154, 15, 224, 211, 170, + 253, 234, 62, 123, 47, 169, 216, 22, 168, 9, 56, 140, 178, 187, + 98, 77, 194, 255, 187, 148, 30, 81, 194, 16, 230, 67, 174, 189, + 120, 190, 47, 28, 100, 90, 101, 185, 71, 6, 36, 118, 171, 243, + 3, 75, 119, 110, 81, 6, 22, 65, 43, 123, 99, 100, 3, 31, + 163, 143, 2, 106, 113, 16, 22, 95, 173, 174, 90, 83, 8, 239, + 238, 78, 242, 42, 63, 80, 58, 107, 24, 121, 106, 249, 139, 207, + 121, 166, 89, 52, 197, 104, 119, 6, 161, 167, 132, 97, 140, 125, + 173, 212, 22, 84, 121, 173, 131, 158, 41, 185, 211, 203, 60, 101, + 105, 9, 16, 207, 61, 76, 246, 144, 240, 177, 92, 64, 49, 225, + 244, 173, 233, 162, 90, 179, 86, 137, 16, 164, 15, 26, 25, 0, + 147, 94, 162, 242, 114, 69, 6, 46, 184, 81, 228, 29, 127, 173, + 38, 77, 18, 170, 251, 112, 230, 122, 221, 228, 253, 210, 46, 53, + 189, 26, 247, 4, 245, 94, 40, 200, 79, 59, 16, 31, 100, 192, + 85, 68, 68, 43, 134, 55, 181, 125, 226, 57, 154, 4, 156, 156, + 239, 4, 114, 9, 127, 39, 28, 228, 38, 79, 127, 47, 24, 210, + 222, 167, 93, 231, 141, 253, 108, 218, 75, 94, 193, 174, 148, 129, + 21, 180, 160, 230, 216, 32, 229, 171, 209, 134, 23, 69, 89, 59, + 57, 178, 62, 78, 235, 213, 100, 58, 146, 44, 239, 17, 11, 173, + 97, 223, 171, 221, 18, 194, 56, 132, 99, 5, 240, 117, 31, 154, + 107, 73, 98, 71, 32, 196, 138, 172, 166, 9, 182, 223, 24, 119, + 63, 148, 48, 1, 214, 82, 53, 169, 206, 101, 48, 227, 33, 243, + 221, 243, 249, 6, 82, 209, 98, 66, 75, 239, 223, 251, 101, 17, + 91, 144, 57, 131, 202, 87, 249, 115, 232, 93, 174, 227, 151, 150, + 206, 167, 47, 120, 160, 28, 182, 226, 60, 118, 148, 226, 244, 164, + 239, 133, 54, 121, 129, 41, 123, 117, 89, 229, 45, 148, 44, 164, + 76, 143, 253, 161, 212, 202, 206, 201, 167, 241, 117, 214, 136, 228, + 187, 186, 135, 97, 10, 78, 173, 135, 252, 254, 190, 251, 224, 159, + 218, 164, 193, 64, 46, 52, 238, 107, 20, 13, 228, 106, 59, 191, + 43, 139, 34, 218, 32, 67, 38, 217, 120, 88, 1, 0, 68, 244, + 99, 22, 146, 250, 47, 34, 237, 238, 251, 79, 197, 119, 157, 224, + 6, 72, 175, 16, 75, 238, 156, 185, 219, 249, 48, 196, 227, 174, + 93, 3, 14, 7, 12, 85, 159, 46, 16, 163, 125, 66, 145, 39, + 86, 57, 198, 222, 105, 197, 102, 170, 81, 84, 27, 38, 90, 83, + 27, 29, 137, 240, 9, 246, 128, 0, 206, 60, 206, 184, 169, 3, + 190, 105, 213, 248, 165, 51, 185, 105, 174, 116, 99, 142, 180, 160, + 36, 37, 59, 115, 105, 13, 5, 93, 18, 192, 125, 64, 215, 9, + 62, 22, 166, 50, 123, 111, 11, 31, 182, 70, 136, 73, 138, 147, + 156, 147, 229, 2, 224, 31, 62, 19, 230, 217, 46, 174, 243, 175, + 237, 77, 101, 136, 235, 171, 111, 252, 249, 1, 113, 71, 92, 97, + 133, 97, 111, 207, 167, 113, 91, 107, 118, 36, 125, 30, 169, 172, + 18, 215, 161, 135, 205, 186, 5, 205, 173, 105, 222, 231, 125, 215, + 157, 169, 248, 248, 59, 226, 88, 138, 252, 83, 149, 206, 18, 229, + 213, 32, 96, 63, 241, 18, 117, 73, 194, 17, 205, 233, 6, 46, + 56, 164, 65, 127, 7, 78, 84, 108, 219, 162, 144, 23, 238, 105, + 145, 10, 91, 104, 79, 16, 14, 239, 229, 231, 60, 12, 255, 238, + 150, 31, 110, 68, 6, 157, 31, 146, 67, 83, 11, 64, 43, 120, + 105, 2, 223, 26, 183, 88, 192, 30, 102, 242, 204, 82, 187, 122, + 174, 43, 146, 50, 165, 96, 68, 49, 31, 246, 134, 147, 165, 94, + 219, 7, 90, 179, 42, 65, 83, 29, 4, 165, 214, 34, 104, 131, + 86, 157, 2, 60, 9, 51, 186, 138, 33, 21, 14, 48, 123, 145, + 190, 134, 20, 65, 175, 184, 70, 83, 116, 82, 57, 7, 38, 48, + 221, 223, 58, 60, 248, 61, 87, 63, 245, 204, 82, 112, 187, 50, + 144, 13, 247, 226, 190, 186, 239, 31, 4, 239, 185, 112, 232, 143, + 209, 38, 109, 78, 241, 22, 243, 194, 55, 221, 62, 164, 28, 186, + 29, 249, 168, 243, 161, 37, 190, 255, 91, 180, 157, 102, 111, 21, + 102, 87, 172, 142, 115, 75, 164, 150, 183, 208, 143, 43, 45, 141, + 211, 11, 201, 65, 109, 9, 152, 89, 77, 7, 91, 218, 126, 107, + 220, 173, 86, 35, 0, 86, 93, 191, 83, 172, 217, 177, 110, 149, + 211, 112, 157, 30, 175, 11, 195, 249, 161, 8, 133, 0, 166, 84, + 151, 242, 172, 224, 140, 216, 238, 77, 2, 102, 219, 127, 224, 43, + 27, 206, 187, 59, 48, 13, 14, 55, 194, 133, 186, 139, 206, 118, + 41, 80, 114, 239, 38, 242, 145, 109, 204, 49, 155, 98, 184, 113, + 92, 160, 170, 222, 108, 35, 145, 7, 38, 228, 133, 254, 207, 151, + 194, 88, 254, 212, 48, 197, 102, 111, 31, 101, 234, 66, 43, 46, + 117, 197, 96, 25, 28, 126, 46, 249, 75, 236, 155, 26, 99, 232, + 213, 200, 91, 252, 62, 146, 45, 3, 102, 233, 187, 245, 224, 162, + 28, 161, 84, 107, 143, 123, 30, 234, 113, 232, 166, 227, 204, 195, + 214, 204, 177, 76, 150, 203, 13, 86, 21, 241, 65, 220, 141, 37, + 252, 238, 245, 149, 218, 27, 54, 212, 134, 101, 131, 91, 77, 124, + 26, 192, 118, 109, 179, 99, 149, 10, 148, 148, 252, 229, 51, 164, + 194, 56, 38, 33, 44, 165, 26, 171, 237, 132, 70, 69, 199, 58, + 127, 247, 236, 195, 132, 96, 0, 150, 36, 218, 32, 33, 220, 167, + 87, 189, 11, 22, 133, 230, 70, 10, 147, 115, 77, 75, 4, 39, + 48, 236, 154, 207, 161, 214, 229, 200, 232, 186, 23, 63, 158, 135, + 142, 171, 163, 104, 160, 69, 21, 23, 139, 85, 168, 27, 187, 4, + 112, 143, 114, 3, 179, 90, 154, 101, 11, 36, 77, 112, 95, 91, + 240, 196, 135, 179, 72, 120, 25, 150, 123, 193, 146, 215, 1, 106, + 245, 228, 104, 154, 217, 17, 78, 226, 50, 115, 73, 107, 59, 166, + 7, 103, 54, 105, 31, 239, 165, 217, 227, 46, 55, 87, 210, 88, + 148, 124, 14, 9, 95, 200, 64, 127, 172, 113, 63, 185, 252, 53, + 183, 37, 87, 88, 227, 67, 84, 62, 176, 89, 154, 107, 220, 102, + 195, 220, 156, 103, 215, 7, 42, 253, 59, 252, 236, 31, 73, 203, + 36, 197, 100, 40, 238, 131, 89, 27, 153, 149, 228, 80, 250, 79, + 14, 80, 174, 137, 26, 120, 91, 158, 241, 67, 76, 56, 102, 181, + 28, 140, 222, 184, 184, 231, 199, 86, 134, 206, 163, 187, 175, 230, + 209, 101, 227, 174, 139, 21, 143, 224, 11, 181, 212, 206, 207, 38, + 74, 202, 52, 207, 153, 9, 159, 203, 55, 222, 91, 193, 223, 253, + 233, 153, 204, 78, 191, 138, 208, 175, 154, 159, 7, 2, 33, 249, + 16, 207, 80, 216, 42, 3, 208, 182, 254, 29, 228, 142, 161, 185, + 125, 113, 76, 238, 190, 152, 67, 237, 40, 97, 246, 116, 252, 119, + 184, 123, 229, 92, 37, 224, 131, 25, 59, 228, 9, 1, 166, 159, + 18, 26, 18, 170, 61, 146, 191, 134, 119, 67, 111, 42, 17, 0, + 89, 21, 241, 191, 187, 115, 32, 182, 132, 117, 106, 223, 24, 50, + 25, 58, 66, 146, 72, 211, 61, 197, 43, 125, 173, 51, 87, 14, + 41, 138, 103, 14, 9, 144, 46, 160, 174, 199, 245, 176, 182, 128, + 23, 237, 120, 120, 68, 114, 32, 153, 212, 81, 48, 161, 133, 155, + 89, 80, 166, 250, 106, 64, 218, 148, 220, 155, 19, 129, 153, 11, + 33, 167, 11, 232, 202, 141, 49, 211, 216, 247, 32, 253, 28, 109, + 140, 186, 197, 102, 174, 26, 87, 245, 208, 254, 70, 196, 108, 214, + 30, 141, 197, 55, 112, 225, 22, 155, 236, 251, 174, 186, 105, 158, + 21, 200, 166, 11, 41, 77, 61, 173, 163, 201, 156, 188, 151, 41, + 195, 99, 157, 159, 156, 60, 208, 161, 153, 250, 174, 25, 247, 178, + 93, 168, 223, 195, 35, 247, 39, 223, 89, 88, 94, 127, 143, 4, + 138, 120, 148, 22, 118, 41, 0, 193, 166, 36, 170, 187, 232, 53, + 77, 4, 253, 37, 92, 142, 203, 204, 188, 99, 176, 37, 212, 217, + 137, 182, 92, 144, 36, 98, 46, 170, 77, 2, 115, 252, 68, 145, + 203, 239, 253, 1, 166, 246, 146, 96, 200, 71, 129, 215, 56, 230, + 174, 133, 231, 127, 204, 246, 28, 68, 129, 250, 230, 245, 174, 74, + 107, 188, 132, 109, 30, 128, 27, 15, 183, 144, 158, 6, 241, 55, + 214, 22, 3, 172, 145, 138, 191, 34, 9, 68, 193, 73, 179, 169, + 162, 145, 82, 18, 43, 37, 234, 87, 203, 233, 96, 241, 158, 75, + 71, 233, 227, 147, 176, 82, 150, 30, 213, 159, 133, 196, 148, 119, + 248, 183, 130, 4, 216, 234, 97, 138, 113, 240, 142, 119, 29, 219, + 183, 48, 182, 43, 75, 231, 165, 158, 189, 248, 21, 10, 97, 62, + 83, 21, 162, 85, 245, 160, 167, 254, 215, 108, 12, 198, 77, 14, + 94, 139, 158, 16, 12, 178, 13, 7, 74, 163, 139, 222, 89, 195, + 0, 23, 46, 92, 210, 26, 0, 231, 34, 42, 25, 191, 193, 156, + 249, 68, 164, 100, 205, 229, 29, 216, 85, 62, 191, 118, 94, 142, + 84, 67, 112, 58, 108, 209, 202, 39, 19, 183, 244, 51, 103, 115, + 115, 90, 185, 205, 40, 128, 216, 223, 179, 121, 247, 73, 80, 45, + 228, 42, 168, 250, 229, 202, 238, 178, 31, 241, 129, 196, 106, 114, + 22, 185, 149, 61, 183, 70, 222, 115, 59, 211, 8, 18, 116, 130, + 251, 242, 59, 172, 42, 253, 219, 253, 29, 225, 145, 89, 126, 173, + 59, 12, 199, 169, 222, 155, 108, 244, 188, 121, 43, 130, 41, 12, + 147, 11, 116, 253, 99, 229, 169, 215, 228, 86, 52, 250, 47, 61, + 125, 114, 142, 70, 198, 58, 74, 199, 99, 238, 129, 46, 182, 81, + 143, 206, 190, 136, 75, 236, 232, 99, 199, 51, 235, 17, 146, 213, + 250, 116, 245, 187, 201, 198, 157, 186, 51, 77, 195, 154, 99, 240, + 41, 210, 192, 42, 126, 49, 242, 149, 72, 198, 49, 128, 195, 70, + 161, 119, 75, 230, 160, 247, 75, 123, 248, 113, 247, 122, 70, 198, + 93, 74, 7, 230, 135, 148, 51, 23, 17, 140, 164, 245, 20, 200, + 237, 87, 38, 111, 166, 163, 204, 0, 130, 5, 42, 229, 89, 248, + 17, 140, 134, 44, 124, 46, 72, 170, 252, 43, 15, 234, 111, 173, + 56, 38, 199, 211, 250, 128, 208, 119, 7, 81, 127, 136, 218, 79, + 135, 52, 143, 117, 234, 234, 233, 17, 122, 253, 253, 162, 41, 111, + 147, 218, 215, 224, 103, 84, 43, 58, 48, 128, 229, 121, 167, 113, + 222, 149, 185, 90, 1, 48, 38, 252, 70, 11, 118, 21, 193, 44, + 52, 98, 62, 178, 108, 190, 137, 98, 186, 14, 2, 68, 65, 24, + 7, 110, 117, 71, 28, 122, 206, 209, 30, 109, 82, 225, 206, 250, + 237, 254, 211, 119, 47, 68, 229, 0, 100, 237, 247, 162, 71, 0, + 126, 201, 181, 248, 224, 226, 205, 66, 251, 118, 228, 11, 147, 209, + 20, 47, 49, 220, 160, 137, 238, 134, 113, 8, 15, 142, 240, 219, + 249, 110, 11, 234, 27, 104, 4, 164, 249, 66, 116, 0, 222, 236, + 55, 64, 44, 169, 154, 161, 150, 190, 113, 111, 113, 71, 215, 132, + 225, 88, 1, 223, 143, 173, 155, 154, 168, 145, 237, 12, 255, 28, + 231, 23, 12, 217, 24, 102, 201, 252, 160, 161, 209, 57, 247, 91, + 80, 41, 65, 178, 131, 126, 67, 200, 74, 147, 18, 15, 81, 178, + 112, 29, 146, 166, 7, 204, 130, 34, 88, 121, 122, 65, 13, 209, + 111, 241, 111, 69, 128, 131, 182, 8, 64, 27, 87, 210, 172, 91, + 50, 40, 98, 192, 32, 147, 143, 38, 254, 31, 2, 140, 121, 3, + 89, 242, 233, 38, 109, 118, 89, 109, 52, 247, 4, 170, 107, 122, + 245, 193, 195, 208, 7, 40, 40, 54, 116, 144, 251, 129, 87, 9, + 6, 105, 146, 68, 143, 99, 220, 55, 42, 138, 100, 154, 205, 42, + 201, 107, 11, 164, 188, 80, 99, 204, 138, 57, 155, 155, 162, 154, + 214, 6, 60, 116, 30, 158, 246, 87, 241, 241, 85, 158, 217, 251, + 60, 150, 228, 200, 106, 119, 145, 99, 211, 245, 17, 221, 21, 95, + 190, 27, 238, 205, 62, 2, 201, 76, 16, 101, 107, 32, 89, 105, + 157, 188, 210, 90, 132, 204, 106, 62, 178, 0, 1, 242, 143, 121, + 0, 248, 106, 156, 150, 2, 165, 48, 141, 81, 254, 149, 21, 58, + 41, 80, 174, 218, 51, 107, 39, 237, 209, 190, 191, 219, 126, 182, + 249, 60, 240, 65, 190, 11, 198, 220, 130, 154, 61, 36, 176, 133, + 100, 22, 223, 196, 124, 202, 73, 254, 251, 77, 185, 158, 94, 8, + 23, 48, 251, 15, 67, 104, 217, 156, 49, 8, 139, 201, 84, 233, + 85, 2, 232, 92, 205, 52, 66, 244, 184, 133, 178, 162, 240, 64, + 119, 25, 151, 181, 97, 110, 100, 219, 168, 75, 118, 25, 71, 57, + 10, 234, 130, 224, 159, 225, 45, 58, 195, 207, 180, 74, 138, 38, + 97, 120, 239, 131, 169, 95, 228, 238, 73, 80, 105, 161, 221, 241, + 29, 197, 81, 6, 0, 242, 194, 219, 172, 42, 193, 85, 197, 208, + 240, 188, 24, 221, 96, 250, 111, 108, 186, 85, 25, 118, 133, 43, + 177, 174, 185, 136, 2, 41, 28, 82, 163, 153, 83, 142, 109, 216, + 23, 210, 247, 87, 144, 87, 31, 101, 208, 161, 140, 143, 162, 240, + 139, 39, 199, 24, 143, 113, 65, 140, 29, 63, 65, 177, 62, 237, + 237, 98, 88, 150, 14, 197, 3, 71, 191, 114, 244, 31, 71, 144, + 90, 243, 242, 98, 248, 200, 51, 161, 165, 31, 141, 40, 68, 70, + 208, 203, 197, 159, 237, 190, 147, 52, 251, 172, 149, 89, 62, 250, + 230, 69, 228, 221, 42, 217, 171, 115, 32, 31, 66, 244, 105, 109, + 183, 245, 22, 161, 126, 233, 224, 53, 4, 175, 18, 104, 98, 198, + 147, 226, 204, 206, 117, 94, 234, 227, 24, 127, 245, 193, 40, 117, + 233, 179, 42, 58, 192, 231, 115, 187, 246, 70, 172, 18, 109, 103, + 208, 91, 20, 63, 152, 227, 102, 5, 214, 189, 2, 42, 76, 157, + 204, 154, 4, 223, 31, 26, 248, 125, 192, 247, 34, 243, 140, 83, + 121, 43, 189, 253, 254, 157, 26, 192, 0, 217, 199, 168, 127, 137, + 48, 218, 23, 227, 40, 89, 43, 191, 214, 123, 145, 197, 23, 27, + 175, 103, 18, 194, 201, 171, 52, 4, 10, 35, 193, 191, 38, 164, + 35, 251, 115, 233, 214, 164, 128, 216, 198, 84, 40, 171, 29, 224, + 87, 229, 43, 71, 251, 100, 251, 91, 93, 232, 211, 42, 196, 31, + 222, 151, 244, 251, 30, 214, 60, 104, 39, 234, 242, 5, 187, 255, + 100, 19, 212, 179, 161, 3, 111, 137, 184, 47, 229, 201, 27, 17, + 164, 76, 125, 88, 6, 16, 144, 88, 71, 166, 73, 60, 35, 188, + 220, 59, 115, 54, 2, 246, 10, 70, 95, 174, 68, 217, 214, 206, + 137, 120, 226, 134, 161, 229, 74, 50, 203, 91, 41, 68, 77, 192, + 169, 153, 171, 133, 36, 118, 240, 65, 48, 189, 246, 250, 41, 208, + 6, 15, 156, 29, 111, 232, 222, 81, 125, 40, 169, 113, 62, 127, + 59, 251, 234, 50, 229, 8, 66, 87, 234, 25, 69, 81, 246, 70, + 200, 44, 253, 241, 61, 186, 177, 125, 52, 192, 144, 190, 173, 42, + 8, 248, 38, 239, 130, 85, 18, 218, 27, 150, 174, 116, 223, 252, + 31, 141, 190, 165, 195, 208, 93, 108, 31, 0, 239, 198, 123, 72, + 85, 191, 208, 178, 46, 139, 94, 101, 12, 193, 61, 15, 140, 42, + 52, 121, 120, 80, 198, 188, 229, 253, 1, 98, 210, 154, 188, 199, + 23, 52, 230, 121, 37, 175, 130, 135, 164, 223, 204, 165, 120, 31, + 160, 74, 68, 198, 97, 10, 47, 185, 15, 28, 98, 210, 158, 188, + 35, 174, 239, 59, 104, 7, 47, 107, 73, 46, 147, 78, 177, 98, + 44, 98, 35, 204, 147, 171, 172, 9, 189, 123, 71, 92, 199, 89, + 10, 247, 40, 181, 94, 4, 9, 128, 187, 80, 152, 148, 176, 148, + 58, 194, 81, 85, 44, 98, 175, 156, 185, 129, 192, 220, 249, 73, + 232, 134, 101, 206, 142, 255, 153, 68, 125, 80, 187, 208, 54, 172, + 123, 223, 134, 36, 210, 248, 22, 119, 129, 49, 68, 45, 84, 31, + 171, 54, 174, 181, 118, 143, 19, 139, 165, 80, 88, 1, 53, 210, + 169, 108, 232, 66, 208, 88, 88, 145, 201, 16, 34, 136, 184, 90, + 161, 251, 226, 158, 12, 119, 189, 207, 37, 161, 162, 44, 246, 86, + 131, 239, 23, 32, 74, 159, 85, 205, 73, 163, 114, 170, 255, 207, + 77, 198, 224, 89, 198, 123, 1, 83, 227, 228, 154, 49, 67, 112, + 229, 208, 51, 181, 246, 169, 1, 51, 93, 65, 245, 147, 23, 244, + 74, 186, 112, 166, 75, 240, 142, 234, 30, 106, 226, 42, 140, 9, + 172, 94, 218, 13, 184, 173, 190, 118, 114, 109, 119, 226, 149, 152, + 118, 43, 126, 84, 144, 231, 127, 80, 141, 240, 162, 75, 118, 172, + 247, 26, 66, 122, 202, 111, 126, 41, 38, 17, 72, 0, 158, 0, + 112, 184, 163, 87, 249, 243, 197, 105, 169, 12, 22, 2, 186, 151, + 148, 184, 181, 124, 189, 173, 241, 199, 109, 217, 108, 131, 171, 135, + 97, 180, 76, 247, 94, 238, 115, 192, 87, 176, 174, 63, 166, 16, + 232, 140, 219, 210, 80, 221, 151, 35, 225, 197, 197, 113, 194, 156, + 88, 55, 255, 251, 173, 154, 6, 24, 152, 40, 202, 187, 9, 42, + 21, 192, 160, 134, 198, 78, 181, 73, 221, 123, 110, 155, 127, 86, + 41, 6, 214, 183, 48, 210, 16, 173, 231, 53, 158, 177, 37, 161, + 147, 210, 73, 22, 28, 95, 89, 215, 251, 50, 161, 2, 61, 38, + 26, 182, 41, 153, 187, 173, 51, 161, 51, 90, 147, 42, 59, 87, + 19, 97, 49, 141, 205, 119, 233, 83, 201, 225, 142, 64, 126, 61, + 142, 154, 73, 182, 152, 21, 99, 176, 102, 238, 174, 125, 108, 213, + 127, 39, 28, 228, 239, 9, 44, 115, 4, 229, 39, 192, 189, 167, + 201, 204, 202, 165, 214, 37, 228, 150, 251, 222, 110, 20, 70, 224, + 107, 105, 235, 215, 241, 221, 225, 212, 210, 95, 182, 10, 31, 82, + 132, 226, 38, 37, 254, 213, 71, 134, 125, 179, 188, 48, 107, 190, + 208, 26, 48, 140, 242, 143, 187, 0, 12, 223, 150, 96, 241, 210, + 142, 76, 174, 234, 75, 19, 98, 116, 202, 101, 8, 192, 174, 100, + 213, 138, 184, 232, 9, 121, 65, 205, 94, 72, 30, 149, 230, 14, + 47, 6, 155, 63, 13, 225, 4, 56, 84, 161, 112, 161, 148, 61, + 146, 1, 81, 68, 42, 58, 28, 128, 249, 20, 134, 217, 99, 192, + 1, 40, 81, 249, 124, 232, 212, 231, 223, 165, 69, 182, 229, 135, + 208, 30, 215, 92, 188, 139, 217, 222, 222, 112, 53, 10, 59, 218, + 195, 121, 207, 230, 190, 219, 125, 181, 99, 150, 179, 192, 147, 163, + 7, 76, 25, 205, 110, 25, 174, 58, 231, 83, 149, 3, 4, 124, + 153, 166, 226, 71, 95, 205, 79, 230, 105, 147, 164, 103, 208, 78, + 153, 96, 0, 165, 191, 7, 84, 234, 246, 13, 143, 227, 159, 83, + 110, 143, 111, 58, 51, 14, 8, 134, 155, 138, 225, 20, 237, 166, + 49, 165, 91, 137, 62, 138, 44, 98, 77, 132, 113, 26, 189, 131, + 41, 125, 15, 185, 16, 165, 79, 19, 59, 115, 207, 181, 32, 243, + 71, 200, 180, 126, 229, 4, 221, 213, 66, 162, 232, 101, 136, 75, + 206, 192, 35, 39, 22, 233, 72, 50, 251, 16, 96, 15, 51, 180, + 250, 142, 108, 83, 14, 29, 16, 158, 28, 36, 101, 177, 249, 27, + 101, 77, 74, 86, 234, 194, 121, 206, 161, 108, 56, 249, 247, 99, + 45, 52, 239, 101, 154, 154, 73, 102, 118, 100, 162, 227, 254, 58, + 33, 83, 85, 102, 187, 234, 19, 225, 116, 9, 235, 230, 106, 137, + 35, 177, 54, 246, 220, 3, 63, 229, 191, 122, 28, 150, 235, 231, + 48, 127, 139, 129, 28, 114, 13, 232, 63, 95, 181, 104, 159, 181, + 147, 218, 12, 4, 185, 239, 164, 199, 91, 230, 84, 90, 136, 101, + 233, 92, 19, 219, 1, 56, 250, 242, 64, 140, 162, 77, 89, 101, + 184, 232, 64, 20, 86, 26, 37, 131, 59, 219, 141, 24, 235, 100, + 18, 28, 74, 35, 250, 72, 175, 162, 74, 146, 6, 153, 187, 24, + 51, 140, 164, 163, 184, 74, 87, 169, 46, 57, 57, 89, 135, 232, + 207, 1, 35, 170, 123, 170, 54, 213, 187, 251, 5, 0, 23, 108, + 133, 93, 93, 60, 25, 4, 199, 193, 187, 190, 1, 173, 42, 31, + 162, 109, 247, 29, 101, 80, 143, 145, 200, 56, 106, 109, 55, 163, + 136, 249, 85, 184, 198, 220, 112, 217, 126, 170, 220, 201, 245, 42, + 63, 105, 208, 153, 203, 192, 80, 227, 240, 42, 150, 54, 232, 65, + 109, 142, 176, 119, 97, 127, 11, 229, 94, 217, 212, 94, 38, 115, + 105, 55, 215, 106, 24, 217, 42, 209, 84, 73, 246, 78, 115, 100, + 213, 56, 105, 246, 0, 19, 12, 101, 15, 241, 195, 48, 135, 93, + 63, 135, 10, 29, 44, 246, 204, 145, 163, 155, 163, 152, 185, 32, + 181, 214, 60, 46, 71, 54, 176, 159, 129, 79, 234, 78, 7, 249, + 211, 19, 130, 125, 108, 65, 183, 90, 64, 238, 175, 17, 194, 43, + 114, 244, 199, 213, 114, 255, 72, 208, 5, 223, 84, 214, 90, 101, + 20, 21, 96, 90, 158, 226, 28, 248, 54, 249, 145, 78, 9, 74, + 214, 238, 187, 232, 252, 111, 70, 11, 81, 153, 127, 207, 110, 169, + 38, 159, 110, 201, 205, 202, 249, 200, 70, 184, 85, 56, 87, 138, + 51, 221, 34, 105, 229, 47, 51, 11, 75, 144, 95, 147, 199, 99, + 217, 132, 210, 12, 255, 18, 140, 52, 252, 175, 184, 213, 251, 42, + 188, 228, 238, 110, 195, 32, 163, 220, 223, 60, 73, 219, 125, 147, + 215, 90, 101, 227, 89, 23, 222, 141, 211, 12, 186, 199, 97, 24, + 163, 55, 78, 237, 107, 234, 151, 250, 213, 2, 131, 121, 42, 82, + 96, 1, 124, 236, 58, 50, 211, 181, 118, 23, 68, 53, 54, 106, + 96, 39, 30, 133, 212, 251, 36, 60, 78, 100, 136, 210, 211, 204, + 28, 26, 7, 130, 76, 104, 214, 4, 114, 91, 53, 191, 188, 206, + 254, 239, 63, 38, 58, 131, 216, 12, 170, 81, 242, 86, 104, 189, + 163, 21, 167, 236, 127, 21, 188, 94, 41, 128, 135, 47, 44, 205, + 65, 4, 101, 160, 49, 63, 208, 12, 236, 156, 243, 105, 133, 85, + 70, 151, 179, 189, 130, 169, 81, 86, 199, 174, 29, 3, 29, 143, + 20, 209, 86, 82, 94, 114, 142, 199, 51, 211, 229, 33, 157, 139, + 81, 28, 245, 32, 93, 205, 165, 222, 129, 203, 138, 222, 170, 192, + 137, 4, 231, 133, 88, 28, 56, 103, 132, 202, 12, 228, 251, 227, + 228, 251, 144, 25, 136, 99, 181, 208, 12, 67, 206, 132, 155, 199, + 84, 15, 22, 212, 47, 163, 133, 33, 190, 80, 127, 126, 86, 18, + 44, 244, 214, 165, 125, 241, 54, 146, 175, 212, 54, 148, 227, 8, + 200, 115, 210, 222, 42, 51, 30, 46, 185, 145, 17, 254, 79, 73, + 56, 100, 42, 180, 153, 117, 98, 234, 184, 52, 98, 13, 14, 52, + 22, 6, 184, 100, 153, 130, 97, 32, 71, 4, 248, 72, 157, 43, + 199, 62, 88, 163, 43, 145, 214, 82, 137, 152, 111, 230, 230, 168, + 61, 125, 211, 167, 231, 109, 91, 91, 21, 5, 28, 153, 62, 223, + 225, 20, 5, 68, 148, 99, 233, 70, 166, 222, 180, 186, 122, 127, + 8, 166, 183, 10, 116, 155, 254, 86, 236, 218, 126, 179, 3, 232, + 234, 175, 150, 255, 255, 244, 173, 240, 41, 39, 215, 166, 25, 103, + 75, 155, 239, 241, 160, 157, 150, 147, 0, 16, 7, 86, 185, 119, + 184, 49, 163, 35, 137, 30, 113, 113, 151, 243, 206, 192, 46, 235, + 49, 132, 86, 0, 94, 23, 224, 42, 17, 37, 59, 119, 140, 42, + 197, 138, 99, 156, 96, 216, 122, 51, 10, 246, 179, 151, 39, 186, + 150, 178, 115, 221, 80, 190, 138, 194, 101, 4, 206, 253, 132, 145, + 143, 254, 32, 172, 190, 37, 62, 79, 142, 186, 143, 166, 136, 139, + 6, 224, 84, 1, 15, 242, 14, 77, 238, 6, 165, 38, 189, 75, + 85, 153, 179, 7, 128, 163, 88, 226, 74, 70, 3, 115, 165, 238, + 148, 11, 199, 142, 47, 84, 81, 194, 245, 122, 30, 227, 3, 103, + 208, 197, 173, 76, 182, 178, 215, 10, 168, 144, 186, 222, 234, 229, + 114, 70, 223, 242, 26, 142, 55, 70, 205, 69, 14, 106, 193, 240, + 71, 167, 107, 180, 233, 199, 18, 167, 32, 117, 42, 47, 197, 238, + 91, 221, 35, 198, 36, 112, 228, 133, 186, 196, 39, 203, 15, 116, + 192, 62, 28, 200, 224, 61, 56, 226, 122, 132, 113, 10, 70, 204, + 149, 174, 96, 113, 75, 175, 155, 41, 72, 136, 138, 5, 116, 19, + 167, 167, 226, 142, 37, 182, 155, 237, 81, 248, 106, 205, 243, 148, + 1, 15, 212, 241, 85, 111, 50, 161, 234, 39, 168, 39, 255, 11, + 238, 146, 191, 242, 195, 75, 117, 162, 121, 80, 184, 151, 199, 64, + 147, 25, 215, 115, 60, 85, 170, 10, 194, 34, 122, 17, 179, 58, + 156, 185, 148, 197, 70, 11, 93, 79, 224, 250, 211, 171, 187, 172, + 20, 109, 50, 176, 44, 243, 75, 42, 34, 26, 72, 21, 160, 17, + 190, 125, 132, 138, 97, 90, 250, 136, 38, 184, 112, 16, 142, 122, + 119, 35, 191, 36, 148, 251, 47, 5, 147, 6, 224, 231, 43, 144, + 142, 221, 42, 52, 2, 228, 245, 119, 16, 5, 4, 66, 204, 149, + 223, 169, 60, 128, 50, 175, 184, 120, 231, 182, 38, 88, 120, 54, + 176, 86, 234, 92, 173, 32, 83, 41, 224, 132, 44, 137, 118, 116, + 193, 171, 42, 109, 244, 61, 50, 238, 113, 6, 99, 34, 94, 19, + 236, 114, 244, 83, 254, 114, 65, 79, 117, 99, 187, 18, 58, 175, + 156, 158, 75, 154, 138, 153, 241, 134, 76, 144, 202, 104, 215, 167, + 28, 9, 93, 121, 163, 167, 56, 231, 152, 145, 194, 150, 60, 88, + 252, 201, 170, 103, 11, 52, 201, 38, 147, 125, 240, 197, 79, 6, + 122, 185, 189, 40, 217, 202, 183, 185, 254, 7, 143, 130, 35, 138, + 58, 183, 202, 214, 85, 254, 136, 101, 33, 8, 255, 117, 42, 32, + 126, 133, 29, 253, 147, 177, 33, 188, 29, 117, 83, 163, 172, 80, + 74, 230, 116, 73, 120, 180, 249, 153, 152, 49, 21, 127, 127, 185, + 117, 101, 243, 34, 238, 183, 65, 4, 207, 231, 61, 77, 82, 161, + 200, 82, 192, 238, 220, 175, 254, 200, 228, 124, 90, 146, 233, 32, + 138, 237, 221, 43, 78, 229, 223, 30, 231, 106, 110, 3, 80, 44, + 180, 124, 147, 162, 232, 78, 99, 132, 97, 212, 101, 165, 213, 173, + 197, 192, 194, 113, 239, 200, 203, 201, 200, 134, 182, 154, 46, 255, + 65, 254, 129, 251, 33, 41, 231, 7, 210, 245, 201, 85, 253, 246, + 91, 94, 68, 8, 43, 100, 19, 159, 255, 173, 224, 142, 218, 62, + 166, 226, 240, 69, 95, 37, 153, 8, 166, 142, 227, 214, 75, 168, + 137, 22, 170, 247, 154, 154, 195, 75, 157, 6, 149, 103, 66, 198, + 33, 78, 134, 61, 182, 104, 131, 96, 213, 37, 155, 46, 42, 38, + 181, 250, 246, 64, 213, 245, 153, 18, 65, 21, 157, 214, 174, 149, + 154, 249, 95, 121, 43, 111, 77, 154, 17, 87, 74, 196, 100, 237, + 59, 52, 85, 196, 208, 167, 30, 134, 110, 238, 141, 183, 107, 99, + 233, 164, 203, 243, 93, 68, 94, 118, 61, 194, 199, 78, 151, 129, + 254, 114, 88, 148, 127, 41, 82, 36, 14, 17, 175, 65, 88, 6, + 13, 6, 233, 112, 149, 48, 252, 70, 198, 51, 232, 175, 52, 116, + 109, 191, 39, 67, 152, 250, 46, 29, 108, 225, 243, 40, 184, 9, + 91, 218, 163, 83, 149, 173, 31, 196, 37, 43, 192, 82, 131, 108, + 86, 37, 142, 123, 100, 236, 97, 57, 27, 157, 157, 18, 129, 89, + 75, 53, 255, 142, 195, 33, 33, 12, 99, 190, 153, 203, 135, 22, + 196, 180, 153, 114, 13, 179, 49, 218, 116, 156, 1, 106, 128, 183, + 227, 181, 240, 51, 126, 59, 241, 129, 119, 121, 21, 233, 29, 166, + 66, 73, 139, 12, 78, 58, 193, 246, 199, 35, 237, 18, 82, 84, + 180, 42, 227, 79, 164, 70, 62, 218, 93, 96, 136, 129, 105, 160, + 66, 73, 223, 50, 79, 101, 23, 177, 232, 79, 42, 137, 178, 57, + 57, 234, 139, 143, 157, 129, 240, 196, 82, 216, 240, 108, 135, 130, + 47, 152, 141, 172, 159, 192, 106, 110, 6, 205, 33, 27, 33, 100, + 240, 163, 43, 116, 214, 73, 236, 177, 104, 211, 252, 214, 175, 215, + 76, 234, 249, 253, 124, 57, 228, 114, 91, 181, 5, 255, 227, 199, + 54, 86, 98, 193, 179, 113, 73, 217, 187, 63, 12, 112, 235, 58, + 81, 117, 54, 34, 221, 200, 195, 79, 144, 136, 200, 255, 223, 164, + 44, 80, 247, 9, 196, 132, 136, 205, 93, 251, 66, 66, 166, 9, + 19, 20, 165, 56, 81, 30, 231, 156, 36, 225, 42, 156, 29, 158, + 82, 55, 0, 196, 88, 219, 68, 229, 216, 219, 177, 144, 88, 132, + 29, 152, 33, 215, 249, 139, 152, 85, 53, 48, 95, 53, 49, 2, + 255, 77, 185, 233, 169, 140, 28, 40, 23, 129, 72, 243, 53, 213, + 46, 68, 87, 232, 221, 160, 71, 21, 77, 225, 59, 190, 111, 62, + 144, 39, 160, 112, 197, 120, 170, 121, 209, 61, 242, 108, 10, 222, + 238, 8, 43, 176, 241, 124, 69, 121, 221, 176, 169, 223, 97, 105, + 225, 236, 213, 85, 157, 252, 95, 83, 198, 149, 113, 204, 70, 117, + 220, 42, 102, 242, 106, 101, 219, 160, 5, 162, 147, 115, 62, 30, + 6, 161, 171, 152, 92, 121, 217, 183, 121, 106, 214, 64, 139, 2, + 200, 138, 246, 192, 125, 193, 132, 121, 50, 208, 59, 159, 105, 136, + 183, 221, 53, 51, 119, 91, 87, 84, 226, 14, 28, 73, 150, 101, + 166, 231, 158, 3, 162, 7, 186, 213, 120, 192, 131, 238, 235, 92, + 39, 120, 59, 212, 89, 19, 6, 97, 1, 119, 129, 188, 106, 219, + 187, 39, 244, 195, 38, 199, 2, 20, 128, 123, 8, 44, 251, 120, + 103, 93, 60, 198, 41, 202, 209, 52, 93, 139, 90, 129, 15, 49, + 43, 167, 247, 121, 67, 181, 219, 80, 15, 165, 173, 65, 132, 219, + 242, 132, 39, 144, 43, 164, 83, 209, 26, 123, 206, 101, 205, 201, + 163, 12, 151, 37, 7, 148, 17, 160, 191, 13, 112, 114, 150, 23, + 178, 21, 27, 38, 160, 163, 53, 75, 161, 132, 104, 202, 32, 10, + 103, 219, 60, 137, 21, 99, 124, 117, 46, 39, 52, 110, 129, 152, + 16, 121, 239, 147, 14, 27, 124, 183, 47, 116, 195, 163, 89, 44, + 43, 74, 168, 46, 36, 56, 37, 223, 192, 213, 239, 82, 77, 69, + 33, 230, 49, 10, 215, 77, 207, 101, 191, 131, 242, 156, 157, 28, + 8, 2, 223, 83, 66, 185, 182, 25, 228, 190, 30, 77, 119, 209, + 126, 170, 53, 189, 125, 73, 97, 9, 107, 32, 27, 23, 21, 124, + 6, 245, 185, 55, 73, 118, 119, 90, 108, 36, 54, 30, 127, 27, + 180, 33, 111, 26, 11, 233, 223, 136, 200, 172, 176, 99, 114, 104, + 236, 101, 117, 88, 212, 169, 131, 156, 64, 110, 45, 112, 158, 253, + 19, 175, 113, 222, 252, 205, 115, 144, 138, 99, 81, 124, 223, 207, + 130, 73, 183, 42, 222, 113, 1, 16, 79, 210, 244, 48, 66, 32, + 134, 20, 234, 148, 153, 11, 126, 40, 66, 109, 12, 17, 140, 66, + 14, 221, 125, 20, 61, 18, 113, 112, 180, 185, 18, 200, 140, 6, + 151, 174, 202, 176, 219, 221, 148, 245, 12, 253, 56, 204, 245, 127, + 179, 208, 118, 235, 237, 247, 209, 23, 35, 83, 133, 189, 223, 188, + 55, 24, 245, 137, 138, 151, 6, 242, 82, 118, 185, 4, 188, 13, + 31, 167, 120, 250, 206, 190, 63, 195, 133, 215, 108, 39, 212, 212, + 243, 88, 153, 237, 30, 126, 206, 244, 44, 121, 232, 60, 73, 176, + 149, 44, 164, 167, 12, 242, 147, 252, 7, 244, 197, 200, 215, 82, + 115, 126, 8, 140, 78, 172, 5, 132, 102, 241, 59, 101, 3, 176, + 122, 104, 168, 96, 11, 79, 0, 245, 138, 249, 42, 75, 116, 38, + 45, 119, 41, 7, 5, 106, 206, 172, 222, 117, 202, 5, 134, 181, + 40, 219, 241, 17, 29, 176, 211, 111, 181, 163, 203, 139, 179, 128, + 144, 165, 239, 214, 172, 86, 206, 235, 36, 115, 9, 200, 255, 200, + 124, 130, 9, 103, 168, 121, 100, 173, 185, 86, 243, 210, 150, 13, + 228, 58, 79, 86, 35, 72, 228, 194, 160, 240, 211, 41, 163, 74, + 80, 105, 19, 182, 39, 102, 216, 79, 121, 82, 163, 9, 110, 145, + 248, 244, 16, 211, 27, 185, 146, 54, 96, 197, 206, 135, 233, 29, + 32, 24, 69, 183, 220, 123, 209, 121, 167, 89, 44, 215, 53, 239, + 87, 214, 55, 115, 104, 147, 197, 138, 37, 152, 96, 226, 148, 228, + 158, 9, 136, 115, 234, 137, 64, 180, 108, 91, 5, 199, 194, 24, + 230, 186, 91, 112, 72, 224, 232, 177, 93, 82, 77, 44, 144, 109, + 68, 254, 76, 97, 9, 226, 107, 129, 26, 77, 197, 93, 156, 217, + 118, 40, 198, 188, 108, 5, 108, 149, 153, 241, 250, 149, 126, 86, + 176, 235, 86, 113, 217, 30, 220, 179, 19, 118, 81, 203, 235, 230, + 154, 157, 28, 118, 151, 53, 251, 134, 237, 121, 197, 54, 116, 19, + 65, 31, 83, 245, 107, 223, 67, 228, 138, 168, 14, 249, 157, 187, + 158, 141, 32, 172, 119, 0, 133, 134, 240, 189, 160, 75, 112, 254, + 63, 54, 158, 67, 173, 25, 207, 54, 182, 42, 100, 8, 247, 22, + 120, 140, 169, 140, 13, 143, 237, 22, 47, 193, 94, 109, 82, 190, + 138, 235, 49, 199, 200, 42, 50, 86, 18, 241, 195, 62, 203, 45, + 70, 12, 120, 68, 57, 146, 116, 251, 200, 1, 193, 30, 204, 134, + 11, 200, 229, 30, 181, 3, 155, 244, 128, 51, 204, 78, 78, 41, + 214, 202, 23, 65, 41, 99, 152, 215, 221, 213, 53, 163, 137, 138, + 107, 159, 134, 41, 208, 253, 112, 240, 239, 23, 42, 131, 157, 48, + 191, 156, 56, 47, 193, 11, 101, 92, 90, 233, 71, 138, 157, 131, + 54, 138, 142, 8, 125, 101, 52, 60, 126, 55, 174, 248, 73, 151, + 173, 96, 47, 241, 209, 69, 9, 222, 127, 92, 110, 63, 70, 181, + 49, 95, 255, 0, 132, 80, 24, 85, 115, 113, 203, 234, 62, 28, + 25, 97, 248, 62, 24, 66, 204, 45, 251, 155, 129, 50, 169, 112, + 139, 67, 1, 32, 141, 153, 176, 254, 87, 31, 249, 130, 230, 27, + 205, 249, 212, 117, 86, 193, 254, 176, 182, 92, 219, 45, 163, 246, + 20, 188, 121, 135, 7, 13, 156, 225, 62, 166, 91, 75, 32, 210, + 158, 135, 119, 237, 102, 97, 128, 109, 141, 83, 135, 185, 201, 157, + 158, 211, 59, 104, 235, 223, 54, 211, 112, 94, 119, 30, 147, 66, + 92, 1, 80, 129, 83, 245, 213, 239, 205, 199, 20, 107, 83, 128, + 82, 40, 63, 135, 67, 9, 181, 244, 178, 177, 213, 140, 87, 249, + 109, 67, 54, 144, 94, 130, 149, 237, 29, 73, 75, 170, 253, 98, + 149, 196, 217, 56, 144, 25, 252, 92, 115, 0, 29, 205, 48, 237, + 250, 175, 95, 34, 23, 249, 13, 170, 233, 1, 26, 82, 76, 197, + 21, 115, 156, 196, 186, 251, 59, 139, 162, 121, 177, 215, 15, 172, + 16, 164, 235, 105, 200, 95, 40, 109, 51, 9, 71, 207, 115, 98, + 24, 89, 208, 124, 10, 84, 231, 255, 31, 108, 31, 112, 233, 236, + 23, 233, 41, 235, 57, 209, 17, 67, 12, 55, 25, 80, 248, 201, + 160, 156, 221, 231, 42, 32, 26, 225, 46, 10, 72, 220, 231, 170, + 155, 143, 96, 233, 7, 102, 215, 212, 137, 68, 189, 141, 152, 148, + 117, 249, 231, 126, 17, 255, 60, 236, 35, 103, 0, 149, 47, 182, + 18, 42, 218, 16, 254, 92, 9, 177, 65, 143, 167, 122, 241, 14, + 118, 124, 76, 198, 28, 235, 111, 187, 246, 107, 73, 229, 68, 149, + 33, 42, 228, 244, 148, 126, 102, 233, 38, 185, 225, 99, 94, 177, + 183, 49, 222, 108, 171, 71, 230, 142, 241, 27, 201, 199, 54, 231, + 20, 189, 86, 39, 152, 138, 160, 1, 1, 55, 201, 243, 226, 11, + 7, 130, 18, 157, 132, 71, 21, 251, 161, 166, 61, 118, 239, 23, + 28, 205, 34, 220, 180, 115, 184, 205, 255, 212, 101, 109, 178, 204, + 84, 104, 12, 6, 86, 125, 21, 116, 77, 192, 116, 140, 41, 127, + 17, 52, 62, 108, 122, 37, 195, 191, 151, 30, 220, 189, 165, 200, + 246, 104, 56, 119, 3, 218, 219, 224, 3, 153, 47, 63, 13, 205, + 15, 205, 51, 13, 182, 232, 14, 173, 188, 229, 83, 59, 208, 238, + 4, 105, 104, 106, 43, 204, 188, 212, 27, 225, 14, 145, 240, 220, + 134, 160, 50, 246, 30, 217, 116, 252, 154, 98, 2, 158, 168, 71, + 162, 208, 115, 93, 67, 12, 118, 73, 170, 51, 50, 227, 221, 235, + 186, 18, 184, 6, 35, 100, 53, 9, 232, 119, 69, 20, 52, 133, + 187, 4, 185, 199, 86, 188, 118, 78, 84, 183, 101, 25, 32, 234, + 216, 154, 184, 167, 39, 210, 91, 173, 149, 196, 203, 26, 111, 53, + 130, 15, 220, 211, 21, 51, 192, 81, 190, 25, 147, 186, 139, 90, + 61, 253, 211, 56, 151, 74, 42, 26, 75, 30, 190, 192, 76, 53, + 91, 30, 239, 132, 24, 39, 164, 67, 172, 138, 150, 22, 199, 27, + 225, 83, 42, 239, 233, 185, 172, 13, 118, 98, 189, 38, 180, 26, + 63, 169, 198, 111, 51, 208, 190, 2, 164, 28, 38, 48, 127, 110, + 62, 139, 200, 199, 194, 253, 21, 157, 204, 74, 23, 175, 156, 57, + 66, 247, 7, 149, 86, 134, 45, 94, 110, 39, 149, 64, 213, 82, + 71, 51, 221, 64, 81, 6, 56, 110, 6, 49, 201, 124, 99, 67, + 156, 67, 85, 195, 141, 98, 249, 194, 140, 39, 139, 80, 249, 153, + 182, 220, 131, 20, 18, 234, 210, 43, 210, 158, 35, 98, 231, 159, + 187, 168, 165, 112, 92, 119, 58, 166, 192, 168, 243, 37, 31, 74, + 204, 133, 239, 252, 238, 169, 165, 152, 197, 220, 124, 227, 129, 109, + 119, 20, 49, 199, 69, 48, 221, 147, 99, 25, 220, 139, 198, 141, + 166, 77, 229, 139, 254, 195, 143, 160, 240, 132, 154, 254, 230, 36, + 41, 22, 186, 217, 170, 197, 236, 37, 236, 141, 247, 244, 49, 22, + 74, 33, 72, 154, 173, 160, 222, 199, 42, 141, 31, 34, 14, 208, + 150, 174, 93, 237, 125, 139, 10, 220, 233, 73, 56, 92, 41, 119, + 207, 214, 237, 161, 225, 89, 76, 22, 48, 87, 77, 190, 227, 161, + 118, 254, 156, 119, 86, 12, 124, 16, 253, 8, 65, 206, 151, 36, + 213, 78, 105, 199, 171, 24, 76, 98, 76, 49, 243, 104, 114, 189, + 197, 98, 101, 114, 242, 226, 170, 100, 142, 160, 172, 95, 26, 133, + 51, 32, 189, 250, 12, 180, 226, 172, 216, 245, 22, 237, 198, 74, + 225, 102, 157, 186, 251, 55, 81, 197, 115, 131, 111, 66, 160, 83, + 115, 0, 237, 87, 254, 83, 218, 21, 133, 49, 68, 102, 212, 208, + 205, 27, 253, 91, 253, 224, 73, 190, 22, 31, 250, 147, 103, 68, + 70, 54, 176, 230, 247, 162, 178, 200, 160, 134, 8, 10, 110, 99, + 232, 75, 129, 88, 54, 40, 156, 129, 32, 41, 135, 63, 227, 238, + 93, 192, 26, 159, 169, 211, 192, 218, 209, 32, 137, 48, 96, 58, + 173, 167, 226, 105, 203, 167, 111, 95, 59, 218, 66, 137, 14, 163, + 164, 171, 160, 92, 239, 36, 250, 171, 92, 64, 66, 94, 33, 193, + 202, 231, 58, 170, 110, 118, 141, 57, 51, 131, 165, 54, 99, 142, + 246, 117, 154, 115, 135, 111, 157, 2, 212, 91, 82, 126, 59, 69, + 70, 197, 114, 248, 111, 8, 187, 58, 48, 120, 28, 253, 141, 92, + 95, 199, 215, 30, 115, 122, 252, 106, 57, 210, 254, 185, 113, 134, + 184, 41, 112, 134, 78, 38, 161, 228, 241, 205, 242, 68, 118, 196, + 44, 11, 206, 51, 8, 68, 89, 132, 54, 224, 167, 118, 230, 10, + 252, 224, 97, 158, 67, 204, 139, 85, 237, 38, 176, 139, 6, 43, + 187, 138, 55, 35, 180, 10, 46, 164, 237, 37, 103, 181, 255, 70, + 197, 157, 27, 166, 107, 65, 246, 72, 18, 27, 120, 123, 166, 47, + 47, 57, 42, 156, 104, 170, 119, 197, 172, 1, 191, 10, 126, 57, + 211, 249, 160, 142, 95, 124, 194, 208, 231, 238, 101, 222, 58, 215, + 188, 158, 54, 8, 36, 246, 107, 96, 112, 103, 245, 249, 172, 9, + 172, 219, 207, 168, 197, 2, 158, 249, 190, 225, 181, 149, 250, 123, + 235, 203, 245, 95, 8, 50, 118, 55, 173, 14, 115, 110, 9, 198, + 154, 30, 199, 125, 85, 228, 248, 157, 75, 25, 243, 214, 110, 31, + 2, 238, 102, 229, 209, 162, 79, 61, 49, 116, 199, 183, 21, 50, + 169, 107, 17, 108, 5, 113, 220, 75, 13, 96, 151, 248, 212, 174, + 8, 113, 134, 249, 212, 80, 227, 175, 114, 168, 199, 33, 170, 227, + 233, 214, 68, 33, 53, 7, 99, 64, 185, 137, 67, 100, 154, 33, + 203, 34, 5, 196, 229, 53, 89, 182, 155, 196, 5, 80, 133, 188, + 151, 114, 106, 202, 217, 183, 134, 81, 242, 153, 253, 67, 22, 242, + 255, 216, 253, 222, 204, 200, 32, 86, 56, 221, 181, 131, 243, 241, + 201, 223, 12, 140, 202, 200, 191, 172, 252, 240, 11, 156, 242, 89, + 12, 235, 153, 154, 136, 169, 196, 200, 212, 143, 81, 101, 122, 224, + 183, 75, 255, 173, 63, 163, 213, 202, 93, 107, 0, 185, 107, 183, + 208, 182, 21, 104, 228, 21, 78, 105, 18, 25, 240, 49, 223, 220, + 159, 168, 140, 25, 143, 11, 146, 106, 156, 208, 190, 133, 221, 125, + 239, 175, 115, 165, 249, 143, 172, 203, 171, 222, 165, 32, 195, 231, + 182, 88, 108, 171, 154, 180, 97, 75, 42, 242, 55, 12, 30, 253, + 168, 45, 74, 235, 118, 54, 198, 173, 42, 56, 226, 76, 234, 134, + 57, 128, 60, 49, 219, 22, 67, 2, 207, 196, 43, 1, 251, 59, + 102, 63, 184, 247, 242, 179, 86, 157, 100, 197, 143, 88, 15, 81, + 153, 85, 245, 222, 187, 188, 227, 32, 164, 20, 139, 112, 71, 126, + 6, 139, 192, 169, 138, 154, 34, 146, 180, 92, 26, 241, 253, 162, + 215, 236, 246, 39, 186, 157, 19, 168, 193, 159, 50, 90, 64, 176, + 62, 146, 208, 29, 222, 214, 45, 214, 5, 86, 25, 155, 74, 228, + 99, 158, 102, 216, 149, 21, 244, 219, 60, 237, 92, 145, 19, 3, + 150, 42, 250, 150, 107, 60, 187, 189, 21, 154, 39, 240, 215, 86, + 147, 151, 159, 219, 198, 34, 78, 24, 97, 250, 109, 190, 220, 21, + 254, 3, 7, 92, 54, 20, 247, 237, 23, 64, 153, 176, 58, 187, + 66, 113, 63, 170, 145, 101, 190, 179, 140, 112, 103, 163, 15, 196, + 112, 253, 131, 74, 32, 144, 116, 128, 184, 15, 62, 96, 30, 160, + 46, 196, 173, 26, 66, 146, 106, 110, 162, 49, 209, 49, 250, 93, + 60, 78, 247, 72, 166, 3, 9, 104, 217, 163, 21, 171, 138, 230, + 166, 119, 213, 156, 200, 139, 234, 228, 219, 95, 148, 231, 19, 255, + 101, 32, 212, 237, 191, 64, 68, 240, 226, 183, 164, 243, 82, 208, + 30, 124, 18, 38, 21, 11, 97, 195, 158, 61, 50, 119, 19, 46, + 199, 19, 215, 167, 237, 155, 116, 77, 44, 13, 216, 13, 81, 200, + 59, 152, 124, 150, 56, 65, 50, 161, 45, 17, 74, 88, 248, 229, + 61, 109, 12, 230, 158, 101, 201, 84, 207, 250, 128, 156, 31, 185, + 11, 105, 16, 45, 254, 110, 109, 225, 20, 96, 126, 37, 13, 75, + 120, 60, 231, 98, 148, 23, 4, 236, 127, 231, 250, 253, 173, 156, + 58, 162, 195, 42, 141, 72, 119, 128, 180, 144, 7, 62, 48, 255, + 245, 132, 85, 243, 248, 70, 161, 21, 216, 66, 216, 125, 107, 131, + 108, 31, 175, 152, 192, 122, 102, 79, 66, 236, 172, 232, 115, 182, + 127, 132, 190, 88, 173, 124, 91, 208, 101, 178, 40, 245, 108, 104, + 204, 223, 171, 19, 53, 28, 83, 209, 56, 96, 238, 134, 218, 40, + 196, 147, 106, 1, 13, 248, 235, 146, 219, 122, 209, 164, 38, 99, + 46, 217, 34, 163, 89, 57, 198, 173, 154, 196, 234, 156, 26, 62, + 48, 142, 20, 114, 52, 98, 42, 114, 210, 128, 32, 65, 175, 2, + 37, 154, 81, 248, 80, 113, 51, 25, 114, 129, 183, 203, 85, 94, + 19, 156, 57, 241, 148, 116, 34, 166, 218, 0, 152, 168, 9, 36, + 93, 229, 252, 147, 136, 178, 117, 21, 205, 185, 105, 187, 24, 111, + 183, 101, 74, 3, 18, 51, 0, 241, 30, 247, 91, 155, 130, 242, + 97, 108, 252, 84, 180, 176, 199, 254, 162, 73, 1, 25, 205, 112, + 229, 148, 179, 173, 236, 133, 167, 122, 66, 109, 251, 199, 221, 253, + 84, 62, 246, 77, 88, 125, 40, 2, 189, 140, 68, 175, 159, 99, + 211, 89, 21, 24, 76, 82, 50, 0, 223, 237, 217, 83, 120, 49, + 21, 45, 116, 148, 166, 140, 99, 75, 139, 103, 210, 206, 169, 79, + 81, 77, 125, 182, 85, 145, 69, 8, 181, 88, 60, 184, 122, 95, + 215, 197, 117, 50, 152, 194, 199, 240, 142, 171, 80, 30, 231, 50, + 227, 42, 182, 159, 114, 44, 21, 55, 180, 5, 237, 135, 75, 235, + 167, 2, 114, 150, 237, 246, 150, 53, 222, 159, 135, 176, 45, 119, + 207, 91, 215, 103, 239, 1, 249, 188, 64, 46, 30, 73, 218, 155, + 67, 18, 43, 187, 157, 180, 151, 74, 75, 174, 111, 176, 139, 233, + 183, 225, 2, 32, 160, 229, 80, 8, 245, 14, 207, 121, 150, 181, + 153, 184, 83, 79, 212, 233, 165, 155, 181, 193, 87, 29, 171, 3, + 46, 76, 195, 151, 247, 12, 81, 11, 135, 52, 143, 33, 152, 89, + 18, 34, 206, 118, 84, 124, 123, 206, 165, 85, 157, 221, 63, 221, + 149, 96, 121, 108, 39, 65, 203, 131, 122, 31, 157, 162, 144, 173, + 114, 133, 85, 66, 83, 107, 46, 213, 101, 192, 199, 68, 234, 101, + 147, 66, 164, 79, 220, 154, 207, 180, 85, 235, 112, 148, 137, 176, + 239, 69, 79, 55, 233, 36, 51, 136, 105, 133, 195, 106, 39, 198, + 24, 147, 71, 142, 237, 172, 213, 15, 120, 206, 191, 12, 218, 170, + 74, 16, 184, 51, 129, 107, 88, 72, 250, 193, 161, 27, 39, 17, + 23, 57, 189, 20, 36, 76, 4, 78, 174, 60, 151, 252, 192, 138, + 110, 103, 151, 7, 71, 111, 226, 78, 169, 53, 105, 99, 181, 12, + 189, 115, 200, 79, 191, 204, 185, 164, 30, 212, 43, 240, 218, 49, + 146, 113, 31, 151, 63, 13, 233, 181, 247, 57, 91, 129, 253, 133, + 35, 28, 254, 64, 80, 169, 216, 246, 135, 29, 237, 40, 176, 135, + 90, 66, 38, 76, 21, 164, 16, 172, 90, 195, 95, 203, 233, 236, + 185, 13, 105, 183, 65, 230, 244, 18, 221, 218, 166, 47, 155, 45, + 229, 172, 163, 50, 85, 158, 152, 218, 136, 133, 180, 158, 235, 52, + 6, 165, 82, 96, 85, 92, 229, 141, 113, 98, 131, 31, 239, 129, + 218, 174, 64, 197, 3, 177, 50, 2, 155, 235, 180, 23, 81, 205, + 191, 30, 177, 201, 91, 191, 250, 84, 14, 59, 212, 247, 116, 101, + 142, 227, 11, 82, 189, 64, 126, 94, 125, 51, 173, 166, 208, 157, + 148, 242, 6, 217, 81, 118, 110, 156, 220, 29, 169, 11, 172, 71, + 237, 194, 63, 243, 125, 11, 201, 5, 126, 166, 190, 9, 148, 196, + 27, 73, 65, 36, 251, 2, 234, 155, 180, 76, 25, 246, 9, 138, + 188, 5, 126, 226, 226, 34, 203, 202, 64, 82, 201, 22, 204, 203, + 29, 54, 119, 11, 249, 245, 129, 140, 218, 179, 69, 221, 95, 194, + 175, 154, 54, 48, 94, 54, 28, 78, 14, 97, 192, 163, 6, 28, + 130, 30, 7, 91, 220, 211, 197, 170, 101, 219, 63, 6, 26, 26, + 239, 45, 192, 169, 221, 23, 231, 208, 21, 249, 3, 21, 102, 216, + 14, 7, 247, 235, 105, 154, 222, 79, 83, 71, 132, 56, 246, 196, + 50, 99, 109, 71, 17, 207, 89, 39, 66, 254, 3, 130, 152, 205, + 220, 43, 45, 177, 188, 216, 143, 127, 222, 177, 87, 128, 31, 96, + 152, 133, 39, 100, 217, 94, 40, 79, 83, 185, 69, 77, 70, 143, + 181, 243, 60, 58, 9, 149, 70, 91, 131, 97, 217, 20, 225, 167, + 240, 183, 166, 232, 16, 190, 77, 86, 198, 14, 169, 45, 223, 98, + 62, 57, 233, 65, 177, 184, 18, 86, 220, 119, 179, 138, 92, 48, + 97, 43, 233, 151, 153, 80, 146, 43, 200, 163, 7, 167, 76, 144, + 126, 34, 27, 119, 9, 144, 90, 78, 214, 152, 4, 103, 211, 172, + 92, 229, 6, 17, 83, 158, 231, 196, 24, 169, 4, 39, 31, 168, + 135, 86, 122, 198, 181, 8, 200, 140, 116, 147, 56, 125, 1, 233, + 52, 124, 28, 96, 137, 171, 9, 24, 31, 63, 59, 250, 95, 165, + 22, 44, 214, 138, 109, 77, 157, 150, 89, 29, 235, 41, 176, 181, + 165, 124, 247, 53, 54, 21, 72, 97, 13, 176, 85, 43, 119, 93, + 30, 236, 14, 248, 65, 43, 218, 168, 47, 154, 191, 72, 253, 105, + 210, 40, 41, 15, 250, 25, 216, 213, 161, 161, 154, 214, 173, 123, + 130, 253, 236, 59, 78, 248, 86, 188, 201, 73, 131, 199, 130, 167, + 240, 54, 175, 233, 188, 99, 37, 75, 16, 32, 101, 56, 243, 146, + 102, 19, 212, 216, 8, 238, 80, 79, 59, 213, 240, 103, 143, 37, + 45, 255, 71, 149, 28, 6, 80, 108, 124, 180, 55, 236, 44, 60, + 183, 135, 186, 103, 51, 74, 65, 21, 106, 7, 8, 25, 157, 204, + 161, 187, 155, 77, 79, 91, 47, 68, 24, 74, 110, 13, 85, 160, + 202, 131, 248, 152, 45, 47, 176, 48, 12, 70, 32, 67, 250, 174, + 68, 15, 251, 175, 13, 175, 4, 96, 147, 141, 242, 245, 230, 202, + 176, 230, 127, 237, 140, 29, 123, 165, 169, 234, 60, 239, 79, 28, + 226, 221, 144, 3, 91, 199, 41, 99, 68, 251, 145, 0, 167, 163, + 205, 207, 162, 202, 53, 124, 11, 15, 195, 143, 211, 97, 244, 187, + 25, 180, 174, 102, 95, 16, 30, 149, 216, 203, 82, 52, 61, 106, + 139, 122, 215, 127, 64, 213, 116, 83, 176, 124, 64, 75, 171, 248, + 187, 183, 194, 167, 226, 66, 2, 118, 9, 148, 161, 23, 203, 193, + 121, 154, 85, 124, 65, 125, 103, 179, 203, 20, 74, 159, 238, 193, + 91, 135, 14, 243, 132, 37, 144, 19, 103, 228, 90, 31, 116, 0, + 142, 84, 69, 159, 38, 181, 48, 229, 224, 238, 247, 244, 217, 31, + 122, 247, 51, 32, 8, 135, 78, 50, 94, 86, 75, 90, 233, 8, + 221, 127, 94, 94, 13, 208, 152, 163, 40, 210, 30, 158, 47, 143, + 39, 205, 35, 185, 178, 58, 227, 56, 162, 27, 71, 21, 27, 107, + 154, 104, 129, 159, 42, 108, 26, 163, 210, 112, 182, 121, 4, 56, + 137, 63, 88, 113, 132, 227, 127, 161, 177, 140, 224, 190, 199, 159, + 86, 176, 54, 26, 192, 145, 118, 191, 113, 45, 2, 241, 191, 47, + 72, 240, 9, 99, 50, 171, 54, 10, 128, 58, 167, 19, 52, 193, + 100, 38, 122, 123, 59, 157, 38, 247, 0, 247, 205, 98, 45, 172, + 112, 43, 212, 50, 136, 50, 167, 115, 143, 68, 164, 222, 227, 97, + 51, 56, 221, 159, 137, 3, 49, 215, 184, 55, 184, 151, 109, 240, + 13, 116, 249, 143, 218, 136, 188, 61, 121, 120, 85, 78, 244, 57, + 239, 0, 163, 229, 131, 122, 76, 21, 144, 152, 10, 175, 150, 191, + 242, 124, 94, 75, 234, 159, 137, 52, 223, 62, 24, 17, 161, 30, + 24, 213, 85, 74, 6, 109, 0, 235, 144, 145, 26, 90, 53, 30, + 77, 205, 129, 243, 199, 136, 38, 193, 196, 96, 253, 51, 48, 251, + 73, 7, 168, 65, 223, 22, 58, 226, 133, 87, 50, 221, 125, 200, + 106, 221, 161, 254, 9, 246, 21, 224, 183, 227, 0, 10, 196, 227, + 38, 238, 161, 188, 34, 165, 209, 109, 70, 154, 32, 206, 61, 4, + 253, 7, 211, 28, 216, 125, 55, 178, 47, 197, 165, 162, 100, 105, + 158, 228, 5, 211, 206, 99, 124, 236, 14, 47, 201, 134, 34, 126, + 122, 225, 62, 254, 195, 82, 176, 105, 30, 169, 55, 83, 142, 21, + 0, 4, 164, 31, 132, 48, 247, 199, 86, 62, 48, 107, 19, 251, + 195, 99, 49, 9, 103, 254, 116, 212, 20, 236, 230, 218, 29, 129, + 129, 128, 33, 174, 80, 81, 7, 137, 216, 252, 152, 38, 86, 238, + 146, 113, 41, 141, 202, 75, 83, 232, 182, 240, 94, 209, 233, 227, + 7, 135, 184, 142, 97, 84, 6, 179, 239, 253, 208, 145, 94, 23, + 225, 127, 155, 194, 161, 37, 131, 161, 54, 15, 100, 11, 45, 198, + 2, 199, 86, 181, 98, 93, 69, 64, 36, 51, 245, 164, 249, 123, + 195, 176, 58, 136, 200, 131, 192, 204, 123, 114, 129, 186, 194, 184, + 176, 242, 68, 212, 126, 20, 65, 58, 49, 212, 147, 189, 236, 232, + 142, 248, 193, 58, 58, 20, 103, 132, 97, 163, 107, 209, 19, 185, + 132, 167, 140, 209, 195, 214, 239, 243, 189, 35, 134, 156, 172, 238, + 130, 191, 22, 190, 79, 37, 249, 120, 24, 242, 198, 33, 100, 24, + 153, 166, 96, 226, 112, 199, 46, 234, 193, 127, 1, 171, 118, 52, + 175, 92, 247, 57, 65, 244, 35, 222, 57, 115, 121, 226, 181, 148, + 123, 2, 17, 121, 142, 245, 10, 103, 225, 111, 17, 229, 219, 72, + 214, 169, 1, 19, 85, 166, 117, 0, 184, 34, 249, 40, 91, 253, + 130, 231, 98, 105, 224, 238, 210, 171, 207, 195, 68, 233, 144, 109, + 219, 216, 146, 62, 226, 127, 78, 6, 128, 175, 30, 107, 195, 85, + 85, 201, 211, 110, 67, 254, 86, 125, 139, 77, 84, 54, 142, 100, + 69, 5, 127, 17, 165, 37, 245, 81, 247, 235, 39, 220, 70, 69, + 50, 120, 230, 76, 74, 227, 209, 109, 92, 156, 189, 184, 89, 212, + 176, 235, 47, 60, 194, 182, 248, 254, 236, 183, 230, 114, 42, 148, + 47, 112, 239, 167, 230, 21, 8, 170, 188, 154, 50, 221, 98, 201, + 124, 92, 251, 78, 67, 87, 176, 127, 251, 102, 145, 204, 165, 11, + 12, 113, 241, 8, 119, 226, 14, 243, 113, 173, 185, 233, 223, 212, + 202, 42, 134, 176, 209, 228, 94, 56, 129, 49, 30, 82, 78, 169, + 174, 7, 94, 175, 1, 162, 109, 16, 241, 40, 186, 78, 3, 223, + 12, 118, 82, 138, 119, 200, 108, 245, 130, 233, 65, 100, 98, 155, + 148, 158, 231, 131, 134, 218, 229, 142, 3, 19, 209, 58, 182, 125, + 127, 240, 45, 0, 8, 201, 4, 145, 254, 217, 139, 44, 247, 131, + 120, 187, 79, 106, 84, 89, 129, 149, 8, 144, 6, 190, 13, 226, + 144, 61, 87, 250, 229, 200, 67, 31, 76, 50, 61, 224, 114, 54, + 224, 91, 248, 88, 236, 3, 246, 156, 133, 23, 29, 53, 152, 167, + 193, 89, 0, 129, 149, 10, 19, 55, 127, 163, 98, 164, 133, 252, + 83, 249, 90, 128, 228, 244, 226, 143, 56, 32, 176, 109, 212, 62, + 93, 32, 21, 251, 48, 128, 27, 140, 205, 32, 239, 110, 28, 85, + 115, 144, 200, 91, 133, 217, 251, 154, 78, 150, 53, 73, 153, 87, + 208, 186, 29, 50, 102, 4, 222, 133, 57, 250, 0, 194, 120, 30, + 69, 242, 219, 201, 175, 182, 29, 59, 28, 198, 238, 82, 202, 247, + 141, 185, 231, 153, 206, 61, 37, 124, 52, 60, 133, 68, 223, 100, + 85, 21, 143, 42, 201, 72, 76, 94, 186, 92, 53, 101, 194, 36, + 4, 134, 111, 17, 172, 221, 164, 192, 147, 203, 233, 175, 129, 43, + 67, 166, 28, 211, 104, 245, 91, 76, 178, 230, 11, 113, 122, 0, + 119, 220, 93, 112, 33, 154, 252, 61, 123, 196, 190, 218, 202, 152, + 65, 247, 172, 166, 178, 230, 192, 3, 167, 138, 53, 236, 153, 207, + 49, 198, 112, 172, 160, 232, 20, 91, 128, 31, 59, 218, 32, 65, + 88, 143, 183, 190, 125, 156, 93, 87, 78, 30, 83, 177, 176, 140, + 174, 118, 157, 142, 107, 133, 133, 84, 77, 164, 198, 96, 199, 208, + 175, 142, 169, 32, 249, 175, 12, 189, 44, 247, 57, 177, 199, 234, + 194, 96, 51, 20, 4, 36, 48, 120, 3, 126, 2, 208, 33, 232, + 228, 88, 161, 169, 55, 139, 205, 45, 159, 13, 113, 110, 226, 32, + 236, 240, 74, 217, 175, 249, 77, 244, 45, 78, 152, 111, 99, 6, + 134, 183, 95, 232, 46, 136, 234, 160, 145, 90, 188, 236, 211, 119, + 219, 222, 108, 67, 214, 220, 48, 81, 17, 249, 212, 128, 158, 172, + 130, 233, 48, 205, 6, 110, 68, 224, 214, 136, 100, 237, 113, 43, + 219, 246, 163, 192, 71, 96, 118, 143, 228, 48, 201, 242, 55, 115, + 77, 202, 224, 197, 164, 254, 231, 150, 65, 118, 81, 205, 101, 205, + 129, 205, 198, 39, 251, 86, 252, 75, 192, 199, 137, 218, 128, 193, + 146, 237, 10, 83, 127, 191, 143, 53, 76, 88, 215, 152, 21, 25, + 126, 109, 250, 191, 132, 211, 4, 92, 147, 252, 98, 26, 157, 11, + 63, 135, 113, 9, 91, 17, 35, 133, 196, 57, 120, 251, 160, 35, + 120, 114, 37, 244, 81, 54, 84, 74, 163, 229, 88, 190, 14, 230, + 185, 206, 139, 35, 182, 251, 98, 127, 148, 226, 5, 68, 243, 21, + 215, 209, 171, 201, 182, 10, 19, 137, 231, 18, 62, 49, 222, 152, + 134, 149, 95, 70, 210, 166, 210, 193, 46, 135, 230, 79, 202, 67, + 192, 160, 12, 3, 139, 114, 156, 232, 244, 5, 127, 110, 39, 53, + 83, 127, 106, 171, 200, 205, 143, 148, 2, 232, 234, 112, 203, 184, + 106, 3, 5, 50, 209, 196, 102, 254, 121, 8, 50, 81, 179, 62, + 62, 32, 70, 1, 177, 128, 236, 23, 80, 123, 242, 161, 202, 244, + 62, 190, 250, 190, 242, 199, 146, 32, 201, 59, 98, 155, 160, 44, + 75, 21, 216, 211, 14, 244, 78, 249, 202, 61, 63, 232, 111, 203, + 190, 173, 72, 103, 15, 230, 143, 218, 82, 254, 190, 17, 118, 250, + 240, 108, 6, 40, 80, 240, 6, 244, 49, 71, 196, 75, 248, 174, + 201, 96, 238, 59, 205, 237, 54, 2, 144, 241, 85, 14, 205, 216, + 116, 31, 233, 252, 253, 72, 172, 194, 126, 5, 239, 170, 20, 206, + 174, 193, 70, 168, 153, 122, 74, 227, 112, 114, 254, 16, 115, 175, + 66, 118, 32, 102, 130, 54, 81, 119, 184, 203, 138, 48, 6, 227, + 41, 59, 192, 19, 255, 244, 36, 99, 196, 93, 135, 157, 220, 29, + 200, 177, 130, 124, 87, 24, 214, 192, 220, 84, 148, 203, 201, 56, + 2, 101, 179, 52, 72, 196, 165, 79, 242, 254, 113, 148, 64, 32, + 137, 71, 196, 37, 46, 31, 172, 111, 144, 13, 192, 68, 147, 186, + 133, 235, 103, 135, 127, 221, 237, 151, 253, 124, 43, 135, 130, 165, + 231, 9, 254, 173, 227, 38, 133, 175, 74, 138, 173, 165, 41, 114, + 70, 153, 196, 16, 247, 164, 84, 141, 85, 4, 157, 180, 123, 194, + 178, 252, 162, 21, 74, 10, 67, 141, 180, 140, 125, 71, 247, 154, + 6, 160, 163, 86, 25, 28, 22, 254, 67, 45, 87, 78, 252, 73, + 105, 199, 238, 150, 13, 112, 236, 180, 7, 166, 91, 122, 57, 215, + 211, 152, 67, 240, 80, 2, 83, 62, 40, 138, 118, 241, 220, 3, + 199, 42, 234, 251, 109, 183, 0, 130, 151, 239, 1, 127, 242, 167, + 95, 124, 188, 98, 98, 64, 111, 159, 3, 51, 152, 151, 86, 77, + 181, 215, 20, 156, 234, 26, 121, 229, 66, 156, 126, 177, 74, 41, + 80, 73, 212, 110, 12, 71, 7, 80, 117, 121, 105, 93, 110, 5, + 82, 199, 144, 51, 223, 240, 110, 79, 21, 213, 173, 79, 101, 15, + 146, 22, 151, 231, 166, 25, 72, 192, 128, 251, 82, 202, 37, 206, + 13, 58, 4, 106, 237, 94, 27, 138, 57, 179, 188, 198, 245, 100, + 126, 110, 152, 63, 230, 14, 216, 54, 90, 67, 166, 58, 209, 73, + 148, 136, 77, 153, 14, 178, 204, 244, 232, 94, 171, 211, 209, 56, + 190, 252, 106, 0, 246, 63, 78, 171, 199, 145, 94, 180, 194, 59, + 166, 10, 98, 188, 52, 14, 21, 161, 92, 246, 168, 245, 160, 149, + 215, 250, 182, 245, 2, 150, 96, 210, 51, 221, 158, 56, 65, 0, + 139, 69, 126, 130, 81, 185, 92, 203, 247, 44, 163, 230, 123, 63, + 243, 228, 50, 212, 81, 3, 199, 218, 134, 219, 32, 7, 247, 80, + 157, 155, 86, 121, 42, 255, 248, 253, 210, 194, 10, 236, 93, 254, + 16, 118, 145, 8, 85, 183, 138, 239, 215, 98, 208, 118, 75, 233, + 22, 155, 35, 41, 148, 62, 167, 151, 104, 113, 69, 211, 243, 25, + 208, 205, 214, 172, 185, 162, 68, 69, 7, 184, 7, 97, 106, 110, + 188, 128, 86, 185, 141, 14, 238, 48, 74, 194, 111, 136, 59, 186, + 97, 250, 115, 78, 40, 127, 253, 61, 76, 202, 102, 35, 5, 201, + 63, 108, 103, 162, 233, 132, 183, 171, 201, 189, 229, 87, 48, 138, + 108, 89, 128, 1, 20, 2, 0, 0, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 99, 108, 101, 97, + 114, 116, 111, 109, 97, 114, 107, 10, 128, 3, +}; diff --git a/Rendering/fonts/face_arial_bold_italic.cxx b/Rendering/fonts/face_arial_bold_italic.cxx new file mode 100644 index 0000000..0c2deae --- /dev/null +++ b/Rendering/fonts/face_arial_bold_italic.cxx @@ -0,0 +1,2591 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Arial Bold Italic +// URW Gothic L Demi Oblique (uagdo8a.pfb) +// Contributed by URW + +size_t face_arial_bold_italic_buffer_length = 36128; + +unsigned char face_arial_bold_italic_buffer[] = { + 128, 1, 103, 6, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 58, 32, 85, 82, + 87, 71, 111, 116, 104, 105, 99, 76, 45, 68, 101, 109, 105, 79, + 98, 108, 105, 32, 49, 46, 48, 53, 10, 37, 37, 67, 114, 101, + 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 87, 101, 100, + 32, 68, 101, 99, 32, 50, 50, 32, 49, 57, 57, 57, 10, 37, + 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 85, 82, + 87, 41, 43, 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, + 43, 43, 32, 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, + 118, 101, 108, 111, 112, 109, 101, 110, 116, 10, 37, 32, 40, 85, + 82, 87, 41, 43, 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, + 116, 32, 49, 57, 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, + 41, 43, 43, 32, 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, + 101, 118, 101, 108, 111, 112, 109, 101, 110, 116, 10, 37, 32, 83, + 101, 101, 32, 116, 104, 101, 32, 102, 105, 108, 101, 32, 80, 85, + 66, 76, 73, 67, 32, 40, 65, 108, 97, 100, 100, 105, 110, 32, + 70, 114, 101, 101, 32, 80, 117, 98, 108, 105, 99, 32, 76, 105, + 99, 101, 110, 115, 101, 41, 32, 102, 111, 114, 32, 108, 105, 99, + 101, 110, 115, 101, 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, + 115, 46, 10, 37, 32, 65, 115, 32, 97, 32, 115, 112, 101, 99, + 105, 97, 108, 32, 101, 120, 99, 101, 112, 116, 105, 111, 110, 44, + 32, 112, 101, 114, 109, 105, 115, 115, 105, 111, 110, 32, 105, 115, + 32, 103, 114, 97, 110, 116, 101, 100, 32, 116, 111, 32, 105, 110, + 99, 108, 117, 100, 101, 32, 116, 104, 105, 115, 32, 102, 111, 110, + 116, 10, 37, 32, 112, 114, 111, 103, 114, 97, 109, 32, 105, 110, + 32, 97, 32, 80, 111, 115, 116, 115, 99, 114, 105, 112, 116, 32, + 111, 114, 32, 80, 68, 70, 32, 102, 105, 108, 101, 32, 116, 104, + 97, 116, 32, 99, 111, 110, 115, 105, 115, 116, 115, 32, 111, 102, + 32, 97, 32, 100, 111, 99, 117, 109, 101, 110, 116, 32, 116, 104, + 97, 116, 10, 37, 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, + 116, 101, 120, 116, 32, 116, 111, 32, 98, 101, 32, 100, 105, 115, + 112, 108, 97, 121, 101, 100, 32, 111, 114, 32, 112, 114, 105, 110, + 116, 101, 100, 32, 117, 115, 105, 110, 103, 32, 116, 104, 105, 115, + 32, 102, 111, 110, 116, 44, 32, 114, 101, 103, 97, 114, 100, 108, + 101, 115, 115, 10, 37, 32, 111, 102, 32, 116, 104, 101, 32, 99, + 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 114, 32, 108, + 105, 99, 101, 110, 115, 101, 32, 97, 112, 112, 108, 121, 105, 110, + 103, 32, 116, 111, 32, 116, 104, 101, 32, 100, 111, 99, 117, 109, + 101, 110, 116, 32, 105, 116, 115, 101, 108, 102, 46, 10, 49, 50, + 32, 100, 105, 99, 116, 32, 98, 101, 103, 105, 110, 10, 47, 70, + 111, 110, 116, 73, 110, 102, 111, 32, 49, 48, 32, 100, 105, 99, + 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, 110, 10, 47, 118, + 101, 114, 115, 105, 111, 110, 32, 40, 49, 46, 48, 53, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 78, 111, 116, 105, 99, 101, 32, 40, 40, 85, 82, 87, 41, 43, + 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, + 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, + 111, 112, 109, 101, 110, 116, 46, 32, 83, 101, 101, 32, 116, 104, + 101, 32, 102, 105, 108, 101, 32, 80, 85, 66, 76, 73, 67, 32, + 40, 65, 108, 97, 100, 100, 105, 110, 32, 70, 114, 101, 101, 32, + 80, 117, 98, 108, 105, 99, 32, 76, 105, 99, 101, 110, 115, 101, + 41, 32, 102, 111, 114, 32, 108, 105, 99, 101, 110, 115, 101, 32, + 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 46, 32, 65, 115, + 32, 97, 32, 115, 112, 101, 99, 105, 97, 108, 32, 101, 120, 99, + 101, 112, 116, 105, 111, 110, 44, 32, 112, 101, 114, 109, 105, 115, + 115, 105, 111, 110, 32, 105, 115, 32, 103, 114, 97, 110, 116, 101, + 100, 32, 116, 111, 32, 105, 110, 99, 108, 117, 100, 101, 32, 116, + 104, 105, 115, 32, 102, 111, 110, 116, 32, 112, 114, 111, 103, 114, + 97, 109, 32, 105, 110, 32, 97, 32, 80, 111, 115, 116, 115, 99, + 114, 105, 112, 116, 32, 111, 114, 32, 80, 68, 70, 32, 102, 105, + 108, 101, 32, 116, 104, 97, 116, 32, 99, 111, 110, 115, 105, 115, + 116, 115, 32, 111, 102, 32, 97, 32, 100, 111, 99, 117, 109, 101, + 110, 116, 32, 116, 104, 97, 116, 32, 99, 111, 110, 116, 97, 105, + 110, 115, 32, 116, 101, 120, 116, 32, 116, 111, 32, 98, 101, 32, + 100, 105, 115, 112, 108, 97, 121, 101, 100, 32, 111, 114, 32, 112, + 114, 105, 110, 116, 101, 100, 32, 117, 115, 105, 110, 103, 32, 116, + 104, 105, 115, 32, 102, 111, 110, 116, 44, 32, 114, 101, 103, 97, + 114, 100, 108, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, + 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 114, 32, + 108, 105, 99, 101, 110, 115, 101, 32, 97, 112, 112, 108, 121, 105, + 110, 103, 32, 116, 111, 32, 116, 104, 101, 32, 100, 111, 99, 117, + 109, 101, 110, 116, 32, 105, 116, 115, 101, 108, 102, 46, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 67, 111, 112, + 121, 114, 105, 103, 104, 116, 32, 40, 85, 82, 87, 41, 43, 43, + 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, + 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, + 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, + 112, 109, 101, 110, 116, 41, 32, 114, 101, 97, 100, 111, 110, 108, + 121, 32, 100, 101, 102, 10, 47, 70, 117, 108, 108, 78, 97, 109, + 101, 32, 40, 85, 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, + 76, 32, 68, 101, 109, 105, 32, 79, 98, 108, 105, 113, 117, 101, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 10, 47, 70, 97, 109, 105, 108, 121, 78, 97, 109, 101, 32, 40, + 85, 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, 76, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 87, 101, 105, 103, 104, 116, 32, 40, 68, 101, 109, 105, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 73, 116, 97, 108, 105, 99, 65, 110, 103, 108, 101, 32, 45, 49, + 48, 46, 53, 32, 100, 101, 102, 10, 47, 105, 115, 70, 105, 120, + 101, 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, 101, 32, + 100, 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, + 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 57, 51, 32, 100, + 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 84, + 104, 105, 99, 107, 110, 101, 115, 115, 32, 57, 48, 32, 100, 101, + 102, 10, 101, 110, 100, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 10, 47, 70, 111, 110, 116, 78, 97, 109, 101, + 32, 47, 85, 82, 87, 71, 111, 116, 104, 105, 99, 76, 45, 68, + 101, 109, 105, 79, 98, 108, 105, 32, 100, 101, 102, 10, 47, 80, + 97, 105, 110, 116, 84, 121, 112, 101, 32, 48, 32, 100, 101, 102, + 10, 47, 87, 77, 111, 100, 101, 32, 48, 32, 100, 101, 102, 10, + 47, 70, 111, 110, 116, 66, 66, 111, 120, 32, 123, 45, 49, 50, + 49, 32, 45, 50, 53, 49, 32, 49, 50, 56, 49, 32, 49, 48, + 49, 51, 125, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, + 101, 102, 10, 47, 70, 111, 110, 116, 84, 121, 112, 101, 32, 49, + 32, 100, 101, 102, 10, 47, 70, 111, 110, 116, 77, 97, 116, 114, + 105, 120, 32, 91, 48, 46, 48, 48, 49, 32, 48, 46, 48, 32, + 48, 46, 48, 32, 48, 46, 48, 48, 49, 32, 48, 46, 48, 32, + 48, 46, 48, 93, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, + 100, 101, 102, 10, 47, 69, 110, 99, 111, 100, 105, 110, 103, 32, + 83, 116, 97, 110, 100, 97, 114, 100, 69, 110, 99, 111, 100, 105, + 110, 103, 32, 100, 101, 102, 10, 47, 85, 110, 105, 113, 117, 101, + 73, 68, 32, 53, 48, 49, 57, 53, 54, 51, 32, 100, 101, 102, + 10, 99, 117, 114, 114, 101, 110, 116, 100, 105, 99, 116, 32, 101, + 110, 100, 10, 99, 117, 114, 114, 101, 110, 116, 102, 105, 108, 101, + 32, 101, 101, 120, 101, 99, 13, 128, 2, 145, 132, 0, 0, 233, + 141, 9, 215, 96, 163, 194, 44, 241, 25, 249, 220, 105, 154, 34, + 195, 91, 91, 53, 237, 106, 162, 53, 147, 199, 109, 84, 202, 187, + 94, 148, 43, 247, 214, 221, 132, 241, 102, 75, 137, 105, 156, 116, + 180, 114, 222, 159, 142, 109, 249, 37, 246, 196, 242, 4, 233, 241, + 198, 57, 180, 219, 169, 136, 237, 42, 196, 25, 255, 43, 43, 222, + 96, 91, 142, 227, 38, 78, 221, 102, 65, 45, 79, 33, 198, 74, + 197, 34, 189, 252, 124, 85, 2, 249, 195, 243, 229, 89, 43, 59, + 32, 147, 211, 60, 155, 250, 237, 210, 212, 158, 137, 170, 186, 168, + 50, 226, 63, 6, 46, 145, 162, 80, 50, 81, 157, 24, 104, 129, + 110, 68, 180, 224, 116, 119, 149, 0, 61, 121, 48, 41, 157, 110, + 30, 42, 91, 254, 13, 89, 93, 201, 126, 20, 9, 137, 206, 129, + 216, 215, 248, 82, 255, 156, 220, 122, 27, 27, 89, 140, 105, 19, + 29, 238, 0, 91, 65, 88, 5, 161, 109, 137, 109, 248, 54, 93, + 213, 241, 127, 85, 143, 231, 125, 84, 76, 1, 176, 57, 174, 190, + 69, 235, 251, 243, 178, 16, 82, 102, 116, 27, 18, 155, 24, 240, + 37, 136, 17, 60, 126, 139, 161, 49, 204, 203, 52, 235, 139, 33, + 11, 149, 25, 128, 25, 112, 48, 53, 166, 201, 208, 203, 202, 24, + 102, 196, 175, 230, 114, 188, 219, 171, 188, 53, 221, 3, 160, 15, + 11, 28, 129, 157, 128, 147, 228, 211, 176, 91, 155, 132, 245, 110, + 117, 237, 33, 166, 75, 44, 229, 11, 60, 13, 92, 99, 72, 232, + 50, 120, 52, 119, 15, 25, 82, 26, 196, 238, 20, 27, 238, 28, + 110, 129, 57, 198, 92, 236, 221, 187, 54, 181, 135, 244, 9, 28, + 158, 60, 45, 157, 69, 24, 76, 145, 60, 22, 153, 252, 197, 166, + 9, 24, 90, 253, 239, 29, 170, 212, 243, 169, 210, 115, 95, 147, + 255, 17, 65, 60, 0, 97, 24, 185, 1, 28, 167, 67, 49, 190, + 180, 32, 87, 65, 11, 146, 184, 216, 102, 146, 58, 151, 217, 237, + 175, 237, 223, 137, 155, 53, 111, 185, 144, 239, 134, 161, 218, 86, + 4, 156, 241, 166, 230, 254, 192, 237, 205, 51, 145, 137, 189, 156, + 16, 191, 162, 218, 138, 201, 23, 181, 230, 100, 2, 203, 22, 1, + 57, 33, 245, 188, 118, 205, 247, 91, 10, 49, 141, 153, 150, 246, + 58, 85, 194, 115, 43, 96, 147, 191, 156, 231, 83, 155, 50, 86, + 28, 74, 170, 127, 121, 125, 59, 49, 124, 202, 168, 85, 190, 109, + 182, 18, 114, 84, 126, 179, 128, 196, 121, 60, 224, 8, 88, 178, + 13, 224, 125, 147, 171, 116, 128, 41, 213, 162, 194, 94, 185, 28, + 95, 253, 193, 241, 114, 120, 206, 51, 30, 95, 44, 243, 151, 0, + 221, 254, 66, 220, 251, 194, 161, 35, 234, 70, 160, 43, 13, 104, + 230, 147, 234, 9, 6, 70, 61, 33, 240, 65, 6, 153, 181, 12, + 27, 241, 190, 211, 19, 111, 120, 127, 144, 19, 251, 188, 54, 88, + 119, 233, 76, 94, 134, 101, 203, 235, 25, 61, 234, 62, 110, 238, + 250, 155, 203, 82, 177, 107, 230, 13, 122, 185, 249, 90, 188, 249, + 12, 55, 219, 120, 236, 146, 217, 184, 171, 41, 216, 72, 101, 228, + 65, 31, 112, 238, 252, 112, 124, 196, 82, 175, 99, 67, 181, 153, + 110, 100, 107, 18, 104, 49, 225, 24, 134, 249, 157, 193, 255, 45, + 228, 68, 135, 122, 89, 16, 48, 30, 216, 253, 13, 209, 160, 5, + 184, 88, 120, 152, 137, 241, 9, 193, 139, 132, 121, 166, 210, 126, + 102, 45, 47, 75, 226, 153, 252, 100, 219, 19, 190, 251, 92, 190, + 63, 88, 44, 53, 103, 33, 54, 123, 96, 94, 189, 188, 13, 115, + 254, 65, 34, 70, 181, 10, 247, 92, 118, 255, 68, 224, 49, 91, + 209, 30, 95, 102, 21, 164, 201, 231, 58, 48, 69, 227, 23, 202, + 12, 92, 22, 214, 236, 18, 60, 99, 249, 230, 152, 5, 227, 182, + 42, 80, 77, 176, 55, 26, 59, 174, 186, 154, 230, 193, 155, 224, + 107, 196, 163, 249, 183, 212, 125, 240, 97, 27, 211, 153, 156, 182, + 27, 137, 150, 230, 235, 116, 12, 233, 191, 137, 202, 217, 28, 77, + 54, 55, 0, 227, 141, 60, 140, 207, 235, 208, 120, 125, 218, 5, + 228, 106, 158, 243, 155, 38, 104, 122, 54, 22, 108, 102, 96, 183, + 144, 112, 249, 50, 48, 28, 184, 123, 241, 179, 169, 70, 218, 0, + 3, 235, 222, 187, 76, 58, 18, 231, 174, 127, 147, 138, 148, 82, + 241, 63, 182, 0, 91, 51, 107, 14, 28, 6, 140, 148, 111, 189, + 255, 99, 191, 209, 15, 228, 238, 137, 130, 75, 70, 1, 93, 17, + 52, 145, 231, 111, 168, 178, 117, 68, 230, 204, 205, 9, 141, 116, + 134, 161, 23, 223, 24, 67, 101, 179, 240, 218, 99, 149, 209, 235, + 85, 179, 66, 222, 85, 238, 207, 43, 123, 107, 60, 229, 9, 38, + 78, 103, 160, 100, 124, 229, 143, 113, 129, 97, 238, 77, 101, 71, + 95, 38, 191, 11, 188, 172, 38, 217, 250, 245, 180, 187, 236, 84, + 22, 80, 146, 49, 111, 249, 247, 157, 41, 213, 171, 125, 194, 60, + 255, 184, 204, 72, 108, 87, 229, 45, 212, 18, 251, 230, 182, 186, + 199, 214, 152, 231, 186, 35, 212, 117, 215, 156, 22, 228, 125, 92, + 242, 33, 1, 168, 9, 126, 67, 250, 69, 92, 23, 188, 163, 44, + 212, 238, 66, 216, 102, 71, 48, 243, 219, 48, 202, 249, 207, 144, + 2, 50, 189, 126, 189, 107, 75, 59, 173, 43, 84, 99, 142, 32, + 223, 240, 246, 201, 95, 38, 228, 200, 31, 40, 104, 177, 173, 83, + 8, 8, 205, 103, 35, 210, 41, 66, 213, 221, 237, 81, 228, 192, + 127, 23, 225, 155, 123, 217, 25, 163, 241, 153, 86, 0, 192, 191, + 122, 28, 4, 143, 112, 155, 77, 85, 77, 175, 86, 204, 17, 140, + 189, 204, 121, 220, 76, 212, 6, 165, 237, 207, 68, 3, 2, 115, + 157, 126, 198, 163, 189, 27, 22, 31, 139, 64, 95, 124, 245, 145, + 47, 119, 229, 194, 19, 215, 22, 65, 119, 82, 51, 33, 248, 65, + 51, 196, 12, 198, 227, 128, 194, 186, 86, 91, 175, 234, 11, 187, + 152, 205, 92, 235, 77, 229, 202, 21, 201, 102, 136, 195, 200, 97, + 187, 52, 127, 238, 144, 211, 55, 116, 134, 166, 226, 217, 42, 137, + 183, 16, 122, 62, 179, 27, 154, 110, 211, 220, 154, 3, 198, 105, + 90, 82, 48, 195, 125, 3, 17, 5, 149, 112, 195, 111, 116, 146, + 66, 113, 76, 97, 171, 29, 29, 221, 245, 224, 41, 62, 112, 186, + 0, 18, 112, 49, 226, 86, 16, 66, 0, 244, 216, 127, 171, 34, + 57, 41, 132, 60, 187, 46, 193, 209, 57, 46, 230, 159, 151, 224, + 116, 41, 228, 64, 18, 61, 82, 115, 15, 72, 60, 102, 147, 14, + 117, 210, 77, 8, 158, 239, 79, 231, 100, 254, 236, 213, 28, 112, + 239, 150, 161, 211, 90, 83, 162, 234, 196, 139, 23, 218, 83, 239, + 34, 44, 230, 12, 117, 88, 163, 122, 108, 236, 130, 221, 247, 184, + 187, 140, 235, 46, 36, 236, 137, 224, 181, 61, 247, 233, 139, 167, + 140, 43, 82, 96, 141, 0, 133, 176, 221, 6, 146, 214, 180, 236, + 145, 184, 49, 149, 191, 171, 225, 83, 240, 3, 87, 155, 67, 204, + 254, 245, 209, 136, 236, 187, 113, 1, 79, 145, 162, 186, 163, 219, + 149, 77, 48, 152, 118, 231, 182, 184, 116, 183, 164, 155, 124, 160, + 253, 30, 5, 245, 237, 188, 64, 111, 128, 204, 153, 49, 253, 163, + 236, 241, 74, 200, 170, 9, 30, 111, 53, 87, 9, 179, 243, 253, + 207, 240, 155, 204, 16, 85, 45, 183, 65, 5, 48, 29, 9, 85, + 114, 29, 100, 148, 54, 59, 33, 20, 41, 78, 102, 116, 38, 191, + 94, 252, 241, 83, 163, 120, 244, 221, 170, 183, 47, 40, 120, 165, + 176, 200, 64, 231, 182, 150, 23, 83, 55, 235, 18, 214, 67, 130, + 74, 59, 255, 139, 159, 104, 167, 224, 120, 91, 98, 209, 133, 240, + 81, 236, 94, 167, 82, 238, 73, 96, 43, 178, 192, 97, 149, 13, + 69, 223, 71, 201, 156, 92, 176, 203, 193, 243, 140, 238, 93, 230, + 108, 148, 63, 184, 215, 66, 199, 52, 68, 234, 170, 47, 248, 14, + 245, 224, 90, 14, 53, 167, 179, 54, 187, 231, 132, 235, 119, 47, + 43, 239, 84, 151, 170, 141, 225, 170, 148, 170, 202, 11, 98, 62, + 154, 122, 43, 175, 113, 75, 220, 214, 243, 85, 4, 84, 222, 248, + 50, 58, 95, 77, 214, 212, 196, 157, 36, 2, 116, 70, 176, 72, + 30, 248, 89, 8, 121, 72, 228, 61, 218, 219, 254, 18, 170, 214, + 244, 128, 122, 2, 75, 92, 49, 159, 146, 45, 83, 134, 77, 6, + 56, 81, 95, 10, 4, 177, 188, 239, 178, 127, 2, 145, 176, 50, + 92, 217, 237, 253, 73, 232, 144, 82, 210, 19, 1, 190, 172, 199, + 69, 178, 244, 91, 240, 111, 6, 43, 42, 70, 219, 199, 230, 151, + 130, 210, 143, 217, 112, 44, 249, 46, 152, 111, 105, 193, 46, 227, + 69, 103, 122, 50, 76, 119, 96, 15, 4, 105, 124, 36, 21, 94, + 227, 166, 124, 67, 17, 242, 192, 117, 235, 137, 70, 104, 82, 189, + 171, 170, 221, 155, 29, 153, 81, 253, 58, 132, 44, 106, 105, 25, + 109, 6, 134, 12, 251, 113, 59, 196, 15, 2, 137, 175, 183, 59, + 191, 33, 21, 71, 69, 102, 150, 255, 72, 194, 131, 209, 31, 61, + 166, 82, 131, 73, 85, 71, 90, 145, 20, 134, 199, 59, 43, 214, + 186, 93, 38, 224, 244, 108, 6, 25, 81, 22, 223, 231, 172, 134, + 75, 101, 185, 219, 246, 187, 172, 252, 201, 102, 101, 45, 2, 25, + 139, 16, 243, 234, 234, 205, 9, 87, 136, 106, 64, 114, 75, 163, + 202, 199, 22, 27, 204, 252, 243, 131, 170, 133, 241, 95, 31, 203, + 129, 165, 149, 65, 164, 58, 129, 55, 223, 194, 75, 131, 168, 227, + 141, 133, 200, 38, 165, 176, 7, 140, 175, 146, 57, 65, 195, 225, + 188, 108, 149, 240, 172, 129, 136, 1, 176, 150, 229, 90, 62, 174, + 225, 44, 82, 230, 131, 27, 183, 83, 31, 153, 161, 67, 187, 13, + 215, 160, 79, 131, 90, 103, 47, 159, 246, 139, 86, 158, 196, 127, + 32, 88, 88, 167, 248, 15, 242, 242, 41, 105, 128, 77, 90, 136, + 190, 127, 13, 204, 63, 61, 154, 229, 112, 209, 147, 205, 94, 83, + 216, 37, 191, 23, 51, 84, 54, 147, 176, 142, 88, 95, 217, 17, + 36, 30, 196, 57, 206, 67, 160, 40, 40, 82, 194, 30, 171, 43, + 199, 94, 99, 99, 133, 208, 208, 102, 18, 156, 145, 162, 165, 128, + 77, 198, 208, 118, 195, 234, 236, 86, 163, 91, 135, 135, 25, 65, + 83, 20, 178, 174, 52, 49, 8, 134, 89, 10, 255, 176, 60, 178, + 33, 193, 19, 248, 228, 20, 161, 90, 245, 108, 48, 28, 132, 53, + 166, 76, 154, 69, 109, 42, 178, 145, 24, 153, 254, 8, 95, 37, + 70, 84, 237, 158, 252, 146, 10, 184, 1, 43, 191, 250, 179, 78, + 254, 250, 210, 242, 200, 242, 148, 233, 167, 174, 172, 221, 204, 171, + 115, 88, 3, 242, 193, 186, 244, 211, 176, 156, 211, 168, 94, 212, + 136, 30, 31, 148, 111, 212, 135, 209, 198, 101, 215, 104, 71, 4, + 188, 50, 170, 8, 38, 44, 158, 23, 207, 29, 202, 90, 80, 49, + 75, 102, 160, 30, 6, 125, 177, 19, 129, 47, 166, 162, 102, 105, + 208, 235, 157, 215, 139, 73, 35, 0, 149, 157, 58, 119, 4, 138, + 214, 5, 158, 1, 64, 61, 251, 113, 192, 225, 100, 22, 101, 205, + 198, 47, 73, 60, 33, 238, 201, 76, 245, 52, 43, 71, 154, 70, + 81, 196, 193, 248, 67, 197, 59, 187, 182, 88, 27, 19, 181, 30, + 250, 62, 120, 54, 10, 101, 151, 194, 72, 155, 34, 15, 99, 43, + 68, 112, 15, 113, 231, 156, 34, 146, 89, 19, 99, 83, 23, 195, + 188, 143, 4, 239, 108, 88, 160, 85, 59, 121, 84, 194, 8, 109, + 142, 113, 195, 70, 148, 61, 150, 136, 154, 242, 232, 154, 223, 207, + 63, 98, 91, 135, 55, 106, 196, 3, 61, 77, 114, 53, 114, 49, + 37, 253, 166, 88, 139, 140, 227, 57, 139, 163, 214, 199, 240, 112, + 54, 146, 58, 141, 225, 217, 195, 49, 50, 11, 27, 73, 86, 9, + 59, 91, 199, 5, 116, 220, 217, 195, 142, 146, 215, 152, 157, 248, + 131, 132, 171, 0, 72, 34, 97, 250, 233, 124, 5, 33, 227, 206, + 18, 5, 64, 233, 182, 82, 70, 136, 182, 97, 188, 59, 175, 107, + 40, 90, 76, 176, 5, 138, 171, 128, 59, 136, 85, 187, 16, 108, + 109, 123, 154, 36, 72, 161, 115, 141, 26, 120, 107, 165, 103, 88, + 37, 35, 115, 16, 251, 182, 106, 40, 129, 212, 245, 79, 31, 162, + 251, 221, 248, 77, 171, 219, 169, 225, 234, 46, 110, 81, 150, 222, + 2, 138, 246, 238, 123, 113, 26, 100, 28, 179, 170, 92, 6, 144, + 66, 165, 89, 68, 253, 152, 62, 51, 47, 191, 132, 173, 86, 187, + 70, 38, 242, 100, 211, 244, 238, 198, 3, 198, 117, 249, 55, 46, + 213, 199, 241, 173, 80, 160, 255, 221, 17, 136, 50, 89, 71, 65, + 222, 132, 53, 95, 61, 178, 81, 195, 56, 124, 253, 34, 212, 184, + 175, 78, 230, 188, 2, 33, 93, 73, 83, 193, 168, 54, 4, 72, + 54, 249, 202, 177, 92, 160, 120, 120, 119, 135, 179, 248, 220, 226, + 190, 116, 29, 22, 53, 149, 168, 52, 44, 43, 253, 55, 181, 158, + 56, 100, 131, 179, 133, 140, 4, 177, 90, 206, 89, 249, 53, 62, + 40, 154, 6, 211, 105, 88, 170, 50, 157, 222, 108, 171, 98, 191, + 125, 17, 173, 136, 219, 179, 231, 38, 140, 169, 49, 84, 97, 174, + 255, 245, 131, 39, 37, 85, 75, 16, 67, 201, 66, 243, 109, 54, + 204, 22, 163, 241, 150, 21, 156, 212, 238, 133, 17, 122, 220, 25, + 169, 88, 134, 192, 69, 136, 126, 4, 2, 50, 6, 218, 22, 161, + 189, 107, 79, 204, 198, 14, 35, 28, 127, 86, 123, 120, 20, 180, + 126, 9, 66, 156, 131, 238, 103, 203, 92, 186, 135, 76, 213, 35, + 114, 195, 185, 165, 133, 174, 212, 162, 172, 172, 225, 200, 110, 14, + 194, 189, 18, 112, 13, 102, 229, 95, 189, 35, 196, 120, 183, 226, + 158, 7, 36, 179, 196, 32, 104, 0, 90, 43, 97, 105, 30, 165, + 47, 49, 14, 15, 221, 57, 25, 106, 12, 23, 12, 80, 22, 160, + 212, 104, 135, 103, 184, 241, 214, 211, 23, 212, 105, 244, 70, 186, + 145, 21, 107, 24, 220, 155, 66, 227, 37, 93, 159, 163, 49, 223, + 217, 75, 46, 58, 82, 151, 123, 117, 192, 238, 180, 225, 67, 12, + 205, 8, 245, 116, 143, 209, 240, 102, 76, 30, 172, 14, 191, 224, + 46, 82, 79, 128, 3, 86, 7, 37, 162, 73, 75, 35, 244, 115, + 124, 188, 77, 195, 156, 110, 134, 138, 83, 180, 63, 197, 30, 120, + 79, 132, 2, 160, 41, 143, 219, 165, 62, 145, 96, 93, 80, 142, + 90, 2, 164, 62, 57, 0, 129, 64, 49, 15, 164, 141, 125, 25, + 252, 166, 208, 242, 184, 198, 46, 184, 70, 31, 235, 118, 112, 28, + 129, 73, 44, 45, 245, 35, 86, 48, 229, 84, 79, 211, 148, 33, + 201, 4, 170, 205, 99, 15, 47, 226, 24, 102, 66, 122, 4, 54, + 249, 133, 30, 42, 102, 48, 221, 195, 27, 112, 74, 37, 144, 152, + 33, 92, 191, 84, 246, 243, 186, 50, 111, 110, 174, 1, 231, 129, + 252, 250, 114, 240, 188, 171, 40, 90, 78, 5, 67, 153, 61, 192, + 235, 72, 112, 213, 67, 183, 85, 122, 158, 38, 241, 198, 150, 155, + 245, 96, 187, 234, 11, 141, 87, 27, 121, 46, 136, 114, 78, 36, + 49, 218, 169, 12, 237, 148, 240, 6, 215, 180, 22, 118, 242, 108, + 131, 198, 14, 0, 217, 217, 26, 124, 215, 223, 12, 70, 219, 139, + 182, 29, 16, 11, 175, 217, 3, 102, 236, 66, 137, 182, 130, 90, + 2, 200, 2, 54, 67, 154, 109, 33, 37, 118, 105, 73, 211, 100, + 242, 226, 182, 143, 48, 20, 27, 75, 190, 62, 46, 215, 106, 149, + 41, 189, 51, 139, 232, 145, 114, 160, 43, 161, 91, 170, 206, 196, + 157, 123, 44, 76, 172, 212, 78, 113, 30, 6, 66, 189, 214, 249, + 228, 172, 4, 58, 26, 21, 174, 102, 207, 172, 244, 101, 170, 42, + 251, 86, 105, 105, 107, 136, 153, 84, 57, 34, 205, 251, 216, 109, + 214, 157, 87, 210, 249, 236, 49, 63, 174, 29, 95, 10, 240, 238, + 134, 27, 198, 105, 58, 40, 79, 214, 90, 229, 59, 52, 218, 3, + 191, 164, 195, 219, 89, 211, 71, 128, 155, 248, 213, 132, 224, 194, + 216, 99, 200, 175, 93, 207, 52, 74, 203, 185, 229, 218, 208, 215, + 169, 160, 101, 61, 2, 209, 219, 3, 73, 144, 188, 249, 232, 184, + 30, 86, 36, 175, 125, 129, 230, 249, 207, 55, 163, 11, 193, 214, + 12, 243, 248, 25, 159, 23, 114, 46, 64, 184, 208, 150, 175, 235, + 57, 173, 252, 46, 221, 150, 250, 131, 86, 253, 174, 54, 205, 182, + 10, 239, 0, 223, 207, 247, 31, 19, 12, 49, 237, 142, 233, 46, + 232, 188, 160, 49, 172, 33, 99, 224, 74, 105, 162, 170, 87, 2, + 45, 167, 65, 73, 92, 234, 46, 20, 68, 7, 85, 149, 58, 20, + 216, 118, 47, 13, 74, 129, 4, 47, 205, 246, 50, 226, 194, 223, + 255, 123, 137, 60, 195, 31, 121, 73, 216, 78, 138, 34, 171, 215, + 39, 51, 56, 160, 43, 211, 47, 12, 35, 53, 161, 138, 157, 42, + 62, 195, 173, 68, 81, 147, 190, 193, 139, 51, 14, 81, 111, 154, + 18, 101, 92, 243, 49, 164, 199, 242, 248, 88, 122, 249, 171, 190, + 5, 122, 47, 130, 9, 202, 242, 52, 204, 238, 113, 172, 182, 36, + 137, 78, 90, 132, 207, 146, 196, 204, 31, 234, 155, 204, 222, 70, + 64, 172, 195, 198, 223, 173, 70, 193, 109, 167, 82, 203, 75, 4, + 125, 153, 163, 206, 202, 105, 68, 204, 116, 109, 0, 245, 45, 57, + 207, 215, 85, 141, 94, 121, 20, 7, 203, 139, 151, 241, 207, 72, + 111, 141, 208, 21, 43, 121, 176, 133, 74, 132, 228, 0, 146, 157, + 158, 53, 231, 4, 27, 118, 194, 3, 16, 88, 232, 249, 185, 28, + 37, 121, 59, 107, 154, 243, 209, 208, 100, 235, 223, 225, 87, 74, + 4, 216, 18, 161, 45, 180, 234, 155, 164, 127, 72, 133, 215, 55, + 184, 144, 239, 252, 76, 34, 135, 194, 70, 132, 228, 114, 105, 112, + 193, 140, 122, 73, 112, 186, 210, 240, 248, 114, 23, 196, 157, 76, + 118, 251, 68, 106, 101, 129, 150, 190, 107, 55, 184, 44, 145, 195, + 75, 58, 172, 147, 167, 45, 4, 100, 144, 224, 125, 214, 53, 80, + 109, 57, 124, 47, 239, 121, 181, 133, 195, 253, 204, 221, 163, 208, + 76, 223, 189, 130, 43, 241, 207, 250, 57, 238, 6, 177, 66, 133, + 89, 195, 44, 175, 120, 41, 193, 80, 44, 209, 154, 204, 23, 74, + 88, 124, 189, 26, 21, 1, 8, 217, 117, 21, 203, 108, 241, 18, + 66, 253, 87, 116, 22, 223, 132, 163, 231, 53, 170, 31, 127, 210, + 0, 61, 72, 78, 30, 187, 231, 125, 89, 81, 231, 99, 99, 206, + 126, 254, 36, 173, 63, 103, 168, 215, 234, 191, 132, 183, 208, 253, + 68, 39, 37, 36, 189, 130, 176, 19, 153, 223, 236, 162, 119, 28, + 199, 2, 211, 213, 123, 9, 239, 139, 191, 240, 176, 247, 81, 145, + 250, 142, 130, 246, 196, 92, 129, 88, 2, 138, 160, 188, 254, 99, + 61, 143, 124, 65, 28, 201, 173, 25, 63, 148, 56, 28, 198, 179, + 66, 72, 68, 65, 228, 142, 83, 182, 186, 120, 168, 122, 220, 174, + 1, 248, 92, 66, 115, 10, 147, 142, 72, 153, 26, 174, 173, 110, + 149, 234, 94, 46, 181, 235, 188, 227, 35, 88, 185, 72, 226, 169, + 71, 240, 89, 156, 227, 150, 230, 97, 19, 81, 64, 208, 144, 164, + 230, 26, 99, 120, 185, 75, 132, 185, 57, 160, 180, 80, 105, 208, + 151, 113, 163, 69, 230, 243, 169, 64, 38, 46, 204, 26, 127, 203, + 244, 208, 68, 149, 203, 202, 135, 152, 59, 138, 23, 3, 107, 91, + 221, 66, 113, 117, 167, 130, 125, 247, 62, 172, 61, 15, 174, 204, + 8, 12, 187, 138, 165, 22, 87, 224, 137, 157, 188, 209, 215, 95, + 245, 247, 177, 110, 254, 135, 117, 16, 222, 61, 174, 64, 8, 161, + 169, 29, 49, 163, 253, 253, 154, 199, 229, 9, 106, 234, 208, 186, + 238, 81, 18, 141, 128, 58, 200, 140, 77, 88, 106, 175, 62, 178, + 74, 135, 97, 243, 185, 115, 244, 93, 78, 222, 228, 43, 147, 136, + 227, 76, 243, 154, 203, 75, 12, 11, 193, 248, 152, 24, 22, 116, + 229, 28, 200, 235, 174, 117, 88, 87, 213, 27, 193, 26, 203, 146, + 130, 1, 36, 132, 175, 118, 73, 195, 135, 25, 16, 74, 172, 65, + 124, 71, 30, 247, 209, 65, 29, 58, 53, 206, 3, 23, 142, 182, + 92, 223, 55, 154, 30, 227, 38, 255, 160, 247, 186, 127, 202, 59, + 72, 25, 101, 200, 63, 108, 166, 85, 190, 127, 3, 84, 238, 170, + 176, 139, 16, 220, 21, 230, 144, 108, 190, 34, 216, 137, 154, 113, + 191, 251, 201, 109, 32, 207, 32, 33, 173, 20, 195, 170, 198, 248, + 153, 71, 209, 169, 180, 216, 237, 25, 253, 38, 233, 36, 48, 137, + 199, 128, 56, 216, 82, 31, 136, 225, 228, 116, 70, 0, 0, 70, + 226, 46, 20, 255, 39, 135, 172, 230, 83, 195, 184, 97, 64, 80, + 73, 162, 40, 231, 14, 156, 139, 100, 160, 207, 142, 28, 237, 237, + 154, 42, 24, 65, 64, 12, 70, 45, 160, 9, 143, 251, 41, 111, + 153, 202, 130, 175, 83, 234, 172, 79, 3, 233, 6, 87, 129, 110, + 225, 27, 72, 140, 230, 208, 130, 115, 103, 247, 92, 137, 9, 56, + 130, 142, 166, 62, 176, 234, 168, 187, 33, 228, 160, 82, 123, 168, + 155, 120, 179, 122, 63, 31, 20, 39, 245, 130, 111, 93, 248, 252, + 48, 26, 220, 124, 161, 113, 193, 207, 156, 229, 195, 135, 70, 221, + 84, 60, 89, 149, 23, 160, 97, 44, 221, 112, 239, 204, 119, 36, + 126, 118, 128, 153, 127, 1, 27, 4, 146, 161, 78, 173, 40, 185, + 155, 118, 49, 147, 54, 76, 61, 59, 37, 97, 164, 208, 16, 163, + 149, 212, 202, 20, 195, 250, 103, 182, 228, 165, 81, 177, 140, 25, + 10, 95, 77, 74, 28, 227, 51, 222, 241, 21, 154, 163, 168, 109, + 225, 150, 205, 225, 37, 139, 55, 226, 58, 248, 216, 153, 38, 137, + 51, 14, 231, 132, 123, 207, 68, 52, 56, 36, 152, 22, 14, 75, + 83, 44, 70, 65, 43, 111, 229, 90, 137, 58, 95, 155, 123, 55, + 249, 245, 220, 152, 130, 84, 66, 94, 135, 174, 108, 172, 4, 179, + 249, 100, 3, 199, 130, 108, 241, 31, 96, 243, 143, 192, 52, 84, + 195, 167, 222, 229, 1, 164, 64, 231, 100, 30, 134, 64, 51, 29, + 108, 189, 107, 82, 160, 130, 18, 145, 89, 28, 66, 237, 194, 235, + 232, 232, 216, 2, 89, 39, 115, 20, 229, 4, 139, 138, 105, 179, + 31, 110, 53, 35, 138, 158, 193, 54, 202, 49, 219, 91, 64, 212, + 39, 200, 227, 203, 60, 86, 243, 221, 218, 253, 32, 151, 155, 102, + 12, 175, 80, 55, 29, 106, 186, 134, 104, 184, 81, 86, 8, 81, + 88, 129, 125, 246, 32, 229, 76, 241, 196, 223, 178, 66, 20, 243, + 192, 70, 161, 240, 178, 106, 48, 199, 93, 229, 219, 173, 218, 231, + 56, 95, 188, 223, 20, 238, 164, 125, 39, 42, 129, 150, 169, 6, + 132, 2, 84, 131, 74, 135, 250, 245, 18, 33, 5, 48, 244, 0, + 147, 90, 131, 127, 192, 148, 247, 116, 4, 88, 220, 163, 166, 135, + 177, 111, 208, 107, 105, 25, 42, 33, 186, 195, 38, 16, 100, 227, + 190, 94, 49, 151, 161, 58, 226, 239, 141, 128, 178, 73, 176, 117, + 71, 150, 2, 108, 65, 131, 253, 251, 91, 123, 117, 115, 129, 99, + 136, 168, 63, 97, 22, 14, 201, 82, 8, 199, 89, 75, 127, 86, + 143, 64, 187, 64, 225, 87, 183, 216, 242, 71, 139, 147, 135, 163, + 192, 103, 161, 193, 7, 236, 107, 10, 9, 48, 59, 92, 18, 229, + 203, 179, 78, 18, 233, 71, 181, 19, 60, 122, 72, 53, 8, 124, + 193, 74, 185, 71, 136, 195, 106, 39, 161, 124, 158, 19, 224, 184, + 136, 192, 38, 253, 104, 108, 167, 102, 243, 161, 230, 58, 8, 116, + 173, 246, 122, 11, 230, 125, 103, 121, 251, 183, 196, 19, 27, 156, + 201, 207, 38, 164, 52, 113, 253, 102, 139, 154, 116, 164, 11, 40, + 18, 72, 137, 43, 226, 126, 161, 174, 111, 210, 240, 207, 209, 248, + 71, 142, 116, 241, 12, 101, 223, 74, 92, 2, 186, 92, 216, 125, + 228, 153, 163, 174, 49, 230, 191, 46, 37, 162, 64, 56, 10, 80, + 50, 188, 195, 11, 139, 252, 255, 72, 49, 155, 100, 160, 88, 96, + 208, 147, 13, 122, 99, 134, 195, 128, 182, 21, 36, 130, 127, 56, + 112, 251, 201, 239, 58, 173, 204, 219, 72, 38, 4, 245, 86, 234, + 31, 75, 155, 48, 108, 218, 217, 114, 16, 17, 130, 86, 39, 220, + 116, 88, 29, 228, 141, 250, 148, 195, 243, 15, 74, 201, 249, 255, + 154, 216, 104, 150, 173, 218, 79, 222, 226, 204, 159, 153, 108, 203, + 249, 113, 254, 222, 37, 234, 94, 222, 226, 96, 63, 24, 128, 210, + 124, 15, 125, 115, 175, 199, 97, 141, 217, 166, 5, 25, 78, 37, + 155, 12, 186, 35, 51, 49, 47, 250, 84, 172, 5, 177, 81, 123, + 23, 97, 243, 171, 175, 166, 26, 163, 23, 89, 13, 147, 94, 136, + 44, 74, 209, 244, 49, 235, 89, 20, 37, 33, 219, 119, 155, 31, + 5, 214, 53, 179, 9, 189, 169, 121, 84, 129, 165, 98, 161, 6, + 168, 136, 24, 224, 244, 176, 61, 163, 190, 194, 212, 214, 176, 65, + 1, 248, 247, 146, 182, 129, 244, 146, 51, 247, 91, 6, 197, 85, + 217, 102, 231, 204, 107, 218, 215, 149, 194, 246, 248, 75, 115, 146, + 38, 81, 232, 112, 134, 89, 102, 123, 127, 111, 82, 229, 116, 42, + 98, 137, 255, 47, 209, 246, 19, 108, 129, 60, 148, 220, 152, 4, + 190, 204, 224, 65, 198, 83, 120, 241, 255, 58, 30, 177, 8, 95, + 72, 201, 211, 43, 97, 70, 123, 219, 20, 37, 103, 231, 79, 216, + 76, 64, 60, 98, 127, 196, 179, 208, 55, 23, 150, 167, 130, 236, + 60, 126, 223, 224, 149, 33, 52, 221, 101, 33, 249, 168, 48, 211, + 161, 210, 74, 20, 12, 198, 241, 134, 109, 186, 212, 25, 29, 178, + 69, 42, 175, 244, 132, 154, 79, 199, 0, 97, 152, 49, 192, 19, + 141, 193, 212, 73, 203, 70, 238, 78, 131, 138, 221, 230, 16, 4, + 122, 139, 116, 217, 193, 163, 164, 151, 227, 189, 141, 244, 187, 2, + 126, 63, 79, 33, 83, 250, 184, 83, 110, 222, 235, 60, 78, 193, + 154, 13, 99, 17, 34, 85, 112, 113, 149, 227, 200, 142, 77, 164, + 26, 104, 249, 164, 185, 9, 60, 242, 55, 90, 149, 145, 154, 187, + 174, 178, 119, 75, 121, 156, 136, 228, 0, 230, 71, 181, 111, 236, + 66, 160, 75, 228, 31, 24, 178, 205, 25, 200, 222, 25, 195, 139, + 59, 209, 42, 189, 89, 164, 45, 17, 164, 40, 214, 106, 130, 154, + 184, 44, 195, 142, 212, 103, 61, 171, 252, 31, 131, 149, 190, 139, + 63, 142, 50, 60, 173, 195, 59, 238, 79, 74, 121, 141, 181, 210, + 45, 118, 238, 74, 193, 122, 177, 213, 52, 223, 240, 30, 67, 74, + 154, 183, 152, 254, 159, 247, 77, 99, 195, 80, 112, 1, 213, 106, + 106, 234, 251, 193, 78, 208, 51, 177, 8, 81, 176, 136, 58, 33, + 30, 143, 156, 183, 229, 58, 202, 5, 122, 17, 155, 223, 189, 195, + 170, 161, 140, 155, 210, 255, 41, 147, 178, 113, 202, 130, 235, 240, + 196, 211, 204, 188, 91, 126, 2, 214, 201, 181, 228, 252, 7, 213, + 86, 181, 68, 108, 193, 222, 209, 194, 176, 185, 165, 127, 253, 42, + 242, 145, 221, 85, 237, 75, 135, 73, 20, 137, 44, 246, 0, 2, + 171, 111, 243, 120, 72, 195, 120, 203, 210, 59, 49, 60, 159, 106, + 196, 242, 110, 120, 183, 201, 83, 138, 47, 137, 87, 77, 148, 223, + 51, 161, 98, 202, 227, 33, 120, 238, 231, 237, 36, 68, 187, 130, + 143, 153, 240, 235, 131, 140, 241, 0, 149, 183, 103, 198, 36, 35, + 235, 223, 192, 10, 255, 33, 78, 184, 164, 211, 245, 83, 248, 186, + 152, 47, 85, 202, 125, 1, 141, 144, 243, 119, 143, 147, 130, 182, + 135, 110, 166, 230, 160, 169, 222, 218, 129, 155, 116, 176, 124, 187, + 249, 197, 111, 164, 5, 66, 60, 26, 100, 3, 161, 190, 178, 133, + 240, 40, 216, 10, 131, 201, 1, 181, 35, 15, 209, 73, 44, 48, + 145, 144, 89, 20, 64, 112, 197, 163, 22, 223, 207, 39, 67, 161, + 95, 138, 155, 78, 249, 91, 69, 191, 195, 249, 21, 2, 253, 140, + 247, 16, 111, 240, 60, 118, 188, 85, 70, 88, 247, 87, 192, 37, + 173, 36, 102, 76, 150, 238, 201, 210, 92, 163, 64, 77, 150, 51, + 77, 175, 243, 221, 82, 158, 20, 76, 207, 209, 27, 187, 186, 218, + 58, 104, 113, 103, 57, 136, 202, 240, 89, 129, 89, 31, 228, 20, + 144, 252, 237, 126, 171, 55, 243, 146, 20, 208, 111, 45, 155, 169, + 24, 106, 93, 133, 182, 172, 32, 221, 215, 89, 46, 142, 10, 148, + 165, 41, 46, 250, 103, 7, 11, 166, 12, 83, 64, 85, 94, 185, + 95, 103, 125, 38, 50, 168, 87, 220, 23, 144, 226, 9, 174, 230, + 24, 26, 80, 230, 40, 147, 231, 192, 189, 1, 31, 83, 127, 19, + 173, 63, 168, 217, 207, 142, 70, 8, 160, 119, 150, 160, 176, 99, + 184, 21, 146, 60, 171, 10, 143, 61, 198, 98, 119, 195, 227, 43, + 37, 142, 38, 227, 152, 145, 138, 241, 11, 77, 227, 60, 25, 202, + 211, 118, 114, 91, 255, 39, 107, 87, 88, 158, 157, 72, 138, 0, + 197, 84, 66, 159, 114, 4, 199, 195, 139, 185, 160, 193, 95, 149, + 246, 95, 74, 111, 250, 159, 135, 80, 32, 35, 16, 2, 138, 124, + 19, 63, 104, 122, 221, 190, 190, 205, 206, 174, 199, 229, 113, 200, + 145, 115, 61, 226, 186, 212, 105, 36, 154, 246, 152, 246, 36, 229, + 175, 180, 117, 47, 84, 192, 77, 189, 133, 167, 120, 174, 114, 247, + 236, 41, 134, 2, 107, 54, 213, 188, 131, 114, 213, 82, 168, 173, + 43, 60, 234, 58, 12, 56, 227, 140, 200, 58, 152, 191, 97, 215, + 248, 114, 123, 127, 2, 27, 206, 63, 69, 235, 113, 10, 168, 230, + 125, 114, 21, 235, 218, 132, 212, 174, 234, 29, 19, 156, 82, 56, + 120, 220, 18, 118, 43, 133, 39, 203, 227, 56, 108, 20, 127, 120, + 199, 138, 212, 89, 117, 146, 68, 107, 107, 16, 152, 48, 214, 5, + 12, 195, 35, 123, 162, 197, 143, 139, 100, 146, 51, 140, 194, 80, + 249, 170, 228, 88, 23, 186, 197, 213, 10, 195, 147, 245, 232, 59, + 67, 23, 70, 28, 64, 124, 141, 153, 227, 222, 73, 38, 145, 79, + 126, 241, 251, 156, 70, 155, 145, 81, 97, 223, 240, 200, 108, 78, + 204, 18, 209, 138, 232, 201, 143, 85, 54, 216, 178, 222, 36, 215, + 28, 224, 191, 229, 229, 225, 73, 44, 218, 164, 81, 53, 221, 219, + 65, 174, 128, 10, 113, 206, 100, 233, 146, 79, 102, 162, 0, 202, + 175, 106, 99, 34, 107, 121, 57, 40, 86, 73, 92, 50, 196, 15, + 122, 107, 232, 158, 68, 179, 222, 75, 209, 146, 43, 204, 47, 159, + 29, 234, 252, 2, 135, 33, 221, 43, 2, 165, 83, 235, 88, 87, + 42, 10, 252, 116, 244, 9, 181, 1, 164, 63, 222, 131, 81, 172, + 224, 32, 134, 9, 124, 9, 31, 41, 204, 119, 238, 239, 54, 7, + 239, 157, 34, 235, 175, 225, 242, 235, 88, 61, 142, 245, 159, 2, + 151, 118, 93, 62, 205, 81, 237, 216, 197, 38, 56, 85, 73, 187, + 235, 149, 211, 255, 18, 110, 48, 45, 182, 185, 205, 101, 5, 238, + 137, 114, 87, 76, 213, 19, 72, 34, 84, 119, 1, 146, 14, 164, + 23, 76, 127, 201, 195, 150, 101, 170, 218, 47, 225, 15, 181, 218, + 247, 54, 253, 255, 95, 156, 96, 46, 180, 127, 231, 33, 118, 232, + 230, 169, 27, 112, 193, 212, 60, 194, 168, 206, 166, 172, 245, 135, + 82, 254, 219, 137, 31, 121, 152, 42, 7, 162, 145, 113, 59, 148, + 36, 251, 14, 130, 36, 208, 57, 183, 133, 154, 249, 167, 222, 21, + 25, 98, 158, 230, 94, 172, 9, 193, 144, 155, 26, 77, 201, 217, + 103, 219, 244, 48, 220, 162, 250, 245, 132, 194, 218, 224, 142, 54, + 100, 183, 85, 167, 125, 212, 215, 181, 122, 89, 174, 24, 101, 180, + 108, 33, 224, 229, 213, 103, 100, 62, 32, 252, 185, 166, 186, 148, + 236, 22, 128, 209, 104, 148, 182, 144, 76, 213, 142, 33, 177, 104, + 74, 36, 48, 19, 34, 186, 221, 144, 248, 94, 156, 67, 81, 153, + 6, 96, 185, 71, 48, 190, 228, 252, 234, 152, 64, 252, 218, 26, + 66, 125, 52, 58, 233, 123, 27, 205, 153, 109, 220, 231, 168, 100, + 89, 83, 38, 226, 147, 154, 142, 15, 79, 234, 220, 132, 110, 128, + 233, 11, 129, 195, 224, 252, 204, 232, 74, 209, 143, 180, 77, 141, + 6, 173, 176, 105, 215, 190, 180, 37, 24, 110, 98, 13, 32, 27, + 210, 219, 156, 234, 71, 7, 181, 133, 24, 195, 49, 77, 242, 98, + 13, 153, 57, 105, 90, 103, 200, 67, 121, 198, 7, 135, 118, 33, + 53, 253, 115, 254, 41, 122, 249, 13, 240, 149, 44, 242, 112, 56, + 34, 182, 159, 62, 102, 87, 212, 161, 172, 185, 71, 135, 18, 12, + 129, 108, 140, 8, 241, 133, 205, 220, 141, 179, 78, 101, 107, 239, + 162, 153, 155, 4, 155, 5, 117, 58, 203, 233, 167, 24, 247, 212, + 93, 48, 5, 63, 141, 97, 68, 111, 87, 79, 30, 185, 145, 73, + 49, 247, 59, 71, 33, 244, 125, 71, 80, 165, 80, 16, 109, 240, + 7, 31, 102, 239, 224, 225, 92, 112, 64, 196, 209, 148, 134, 81, + 134, 234, 125, 25, 179, 56, 172, 70, 214, 56, 130, 71, 22, 157, + 179, 103, 21, 16, 19, 214, 184, 172, 46, 170, 233, 239, 122, 122, + 52, 151, 145, 190, 94, 99, 29, 183, 186, 133, 199, 84, 163, 123, + 18, 211, 72, 187, 23, 80, 83, 215, 246, 114, 247, 95, 25, 47, + 47, 163, 191, 215, 180, 160, 134, 80, 89, 91, 116, 82, 254, 89, + 156, 78, 83, 126, 210, 165, 135, 9, 37, 26, 210, 68, 21, 83, + 55, 88, 26, 5, 178, 123, 74, 173, 230, 69, 218, 89, 16, 39, + 162, 73, 238, 173, 85, 128, 1, 187, 249, 241, 226, 232, 138, 118, + 39, 204, 202, 171, 191, 161, 251, 183, 219, 219, 239, 74, 65, 76, + 46, 56, 5, 233, 66, 79, 73, 172, 77, 234, 130, 28, 197, 254, + 127, 171, 216, 49, 67, 233, 159, 240, 27, 176, 161, 184, 194, 77, + 53, 215, 115, 225, 25, 96, 33, 211, 18, 148, 176, 86, 227, 170, + 43, 66, 155, 247, 1, 129, 141, 205, 186, 146, 99, 125, 44, 227, + 61, 178, 208, 208, 163, 186, 136, 225, 195, 174, 235, 75, 36, 182, + 125, 46, 7, 240, 212, 94, 116, 147, 63, 41, 39, 162, 246, 230, + 109, 117, 79, 25, 245, 146, 60, 187, 186, 108, 51, 192, 128, 250, + 253, 209, 50, 237, 107, 68, 241, 67, 30, 28, 195, 130, 231, 181, + 70, 26, 171, 51, 52, 88, 139, 104, 14, 143, 70, 254, 205, 233, + 24, 232, 21, 128, 83, 228, 115, 226, 30, 184, 190, 9, 211, 195, + 137, 70, 199, 165, 201, 154, 12, 153, 32, 206, 107, 66, 43, 109, + 3, 33, 18, 208, 248, 28, 185, 155, 205, 68, 121, 201, 3, 59, + 250, 145, 153, 214, 50, 84, 93, 8, 105, 223, 36, 195, 253, 208, + 83, 67, 75, 29, 229, 145, 57, 133, 4, 109, 100, 133, 154, 87, + 126, 155, 180, 46, 84, 44, 241, 250, 70, 101, 32, 169, 250, 193, + 127, 15, 48, 55, 87, 51, 168, 200, 59, 244, 186, 68, 157, 171, + 96, 152, 76, 124, 176, 19, 44, 125, 0, 47, 71, 79, 221, 109, + 135, 192, 120, 237, 24, 209, 176, 230, 118, 12, 174, 52, 201, 69, + 207, 78, 62, 34, 105, 131, 40, 171, 150, 62, 165, 6, 162, 161, + 121, 64, 110, 44, 229, 165, 60, 41, 150, 150, 147, 9, 105, 206, + 158, 201, 149, 67, 93, 8, 25, 163, 225, 102, 54, 231, 181, 98, + 155, 122, 56, 214, 154, 40, 18, 186, 163, 85, 190, 66, 237, 119, + 204, 197, 110, 221, 22, 26, 184, 137, 204, 171, 92, 226, 60, 166, + 232, 27, 132, 139, 49, 205, 194, 252, 188, 52, 152, 168, 112, 193, + 61, 188, 229, 32, 50, 232, 131, 64, 203, 109, 229, 170, 198, 55, + 195, 221, 211, 67, 49, 152, 103, 28, 28, 77, 85, 150, 127, 133, + 214, 103, 240, 22, 156, 184, 140, 219, 172, 63, 217, 59, 164, 25, + 237, 75, 92, 241, 32, 194, 223, 201, 218, 43, 25, 34, 79, 245, + 21, 222, 187, 58, 56, 149, 155, 74, 174, 234, 208, 67, 176, 75, + 199, 95, 169, 195, 204, 150, 183, 142, 246, 142, 210, 81, 57, 151, + 107, 224, 178, 191, 63, 188, 119, 90, 42, 158, 115, 200, 166, 112, + 2, 119, 222, 14, 216, 67, 33, 60, 169, 1, 118, 99, 55, 93, + 78, 141, 126, 139, 130, 218, 86, 168, 120, 3, 181, 52, 77, 92, + 117, 24, 219, 6, 43, 84, 15, 217, 106, 15, 123, 92, 60, 18, + 117, 172, 77, 243, 50, 67, 215, 15, 58, 248, 189, 215, 223, 4, + 184, 130, 80, 204, 219, 135, 199, 192, 99, 201, 3, 74, 25, 52, + 80, 11, 208, 30, 220, 234, 183, 142, 231, 247, 62, 12, 230, 255, + 0, 249, 54, 33, 30, 254, 44, 113, 78, 43, 236, 196, 93, 196, + 179, 253, 139, 82, 85, 62, 201, 154, 136, 220, 95, 165, 230, 28, + 36, 55, 110, 7, 158, 243, 223, 39, 22, 145, 104, 196, 192, 161, + 224, 47, 185, 225, 150, 102, 67, 197, 60, 184, 109, 157, 131, 134, + 147, 110, 19, 79, 198, 218, 35, 173, 71, 33, 18, 177, 229, 232, + 120, 2, 67, 69, 85, 217, 159, 46, 47, 158, 52, 36, 69, 76, + 208, 255, 53, 13, 28, 239, 172, 161, 4, 48, 190, 100, 101, 116, + 46, 96, 231, 14, 92, 94, 8, 170, 219, 170, 144, 87, 174, 125, + 11, 156, 242, 112, 10, 255, 172, 78, 145, 114, 105, 78, 109, 21, + 26, 68, 199, 85, 42, 245, 65, 91, 127, 54, 107, 46, 210, 3, + 135, 0, 185, 9, 164, 52, 244, 23, 180, 0, 219, 169, 211, 231, + 145, 82, 206, 134, 156, 184, 43, 109, 221, 77, 202, 225, 34, 30, + 35, 108, 173, 51, 131, 200, 171, 148, 236, 218, 88, 109, 45, 145, + 20, 23, 255, 138, 185, 227, 65, 153, 137, 33, 153, 178, 145, 103, + 232, 254, 120, 117, 2, 216, 245, 176, 21, 76, 49, 2, 196, 63, + 72, 65, 80, 145, 180, 101, 144, 132, 129, 33, 154, 207, 147, 104, + 240, 61, 128, 154, 96, 152, 152, 5, 86, 4, 178, 40, 186, 26, + 8, 222, 247, 40, 9, 125, 221, 72, 214, 250, 167, 99, 253, 34, + 195, 124, 129, 54, 201, 75, 93, 169, 215, 199, 136, 118, 131, 150, + 239, 236, 40, 41, 142, 243, 174, 171, 146, 65, 72, 143, 144, 100, + 80, 173, 112, 113, 219, 218, 226, 149, 34, 52, 122, 68, 89, 195, + 3, 172, 149, 66, 34, 180, 242, 153, 222, 213, 66, 42, 230, 229, + 66, 14, 13, 20, 94, 60, 2, 245, 158, 158, 236, 222, 241, 74, + 51, 240, 156, 90, 174, 188, 112, 27, 210, 7, 121, 215, 76, 62, + 173, 5, 31, 232, 27, 221, 155, 55, 122, 76, 91, 238, 164, 198, + 94, 70, 58, 195, 150, 157, 131, 37, 216, 216, 194, 108, 103, 150, + 214, 0, 245, 97, 183, 106, 188, 197, 209, 81, 33, 17, 244, 201, + 146, 38, 140, 59, 251, 75, 54, 178, 241, 30, 55, 112, 188, 29, + 87, 171, 77, 74, 6, 38, 136, 33, 124, 3, 193, 35, 115, 254, + 154, 108, 213, 80, 182, 120, 109, 120, 172, 159, 196, 36, 171, 109, + 115, 8, 153, 115, 50, 126, 107, 81, 198, 204, 217, 49, 73, 35, + 245, 50, 226, 251, 149, 231, 176, 117, 4, 230, 195, 86, 177, 73, + 226, 224, 193, 183, 84, 166, 116, 198, 250, 254, 102, 246, 8, 237, + 219, 27, 93, 234, 84, 169, 81, 39, 137, 226, 251, 214, 35, 104, + 90, 231, 91, 42, 108, 80, 151, 236, 80, 194, 105, 140, 136, 221, + 104, 246, 51, 165, 140, 0, 137, 205, 188, 2, 61, 86, 170, 120, + 118, 76, 208, 243, 15, 50, 116, 7, 4, 105, 182, 204, 199, 107, + 133, 184, 236, 129, 9, 4, 150, 44, 220, 244, 179, 61, 181, 241, + 112, 64, 3, 214, 16, 145, 33, 136, 141, 120, 249, 53, 123, 129, + 182, 204, 230, 211, 252, 180, 214, 39, 0, 85, 228, 112, 210, 116, + 142, 249, 114, 5, 162, 29, 229, 62, 222, 234, 94, 107, 95, 88, + 151, 68, 167, 68, 20, 179, 186, 62, 151, 51, 112, 197, 137, 182, + 110, 237, 212, 94, 45, 237, 76, 136, 213, 11, 200, 82, 123, 184, + 253, 121, 104, 214, 156, 184, 252, 234, 169, 104, 59, 150, 191, 210, + 207, 222, 18, 108, 17, 67, 45, 140, 8, 63, 137, 96, 39, 207, + 196, 67, 13, 207, 178, 205, 100, 205, 50, 94, 74, 74, 153, 172, + 204, 182, 142, 93, 96, 54, 250, 181, 46, 22, 27, 19, 131, 83, + 90, 70, 209, 50, 171, 89, 28, 202, 55, 236, 238, 164, 170, 246, + 252, 203, 199, 247, 13, 117, 157, 249, 165, 81, 165, 97, 126, 103, + 155, 65, 160, 147, 183, 105, 187, 9, 185, 27, 141, 107, 189, 180, + 139, 97, 34, 78, 191, 36, 255, 125, 13, 120, 152, 138, 245, 81, + 44, 150, 153, 47, 123, 131, 184, 239, 240, 27, 159, 45, 188, 230, + 95, 140, 146, 144, 0, 248, 192, 199, 15, 69, 54, 98, 114, 73, + 207, 87, 229, 99, 230, 210, 144, 212, 25, 199, 195, 52, 101, 53, + 93, 195, 206, 166, 125, 56, 178, 199, 214, 185, 121, 52, 41, 92, + 243, 108, 148, 168, 178, 246, 248, 81, 2, 66, 175, 145, 77, 216, + 102, 247, 4, 157, 61, 44, 32, 42, 157, 240, 41, 143, 77, 218, + 62, 133, 123, 32, 234, 239, 34, 195, 111, 209, 127, 188, 188, 198, + 34, 186, 46, 150, 7, 167, 219, 82, 203, 79, 69, 187, 145, 207, + 48, 30, 135, 66, 32, 232, 234, 53, 169, 129, 192, 172, 141, 22, + 198, 196, 36, 245, 173, 140, 244, 80, 92, 69, 163, 141, 125, 38, + 193, 153, 5, 167, 75, 160, 79, 255, 150, 2, 60, 187, 232, 187, + 49, 241, 141, 67, 86, 25, 218, 197, 63, 59, 71, 204, 33, 44, + 105, 125, 145, 250, 99, 214, 144, 95, 124, 154, 142, 122, 142, 33, + 81, 45, 72, 57, 100, 143, 184, 173, 37, 117, 183, 178, 59, 244, + 179, 66, 50, 216, 246, 182, 153, 185, 106, 101, 119, 32, 158, 96, + 151, 198, 31, 171, 67, 211, 219, 168, 146, 2, 6, 0, 47, 34, + 194, 90, 123, 137, 101, 213, 18, 219, 52, 89, 139, 140, 174, 38, + 33, 114, 76, 94, 219, 38, 181, 201, 203, 121, 52, 181, 179, 137, + 13, 118, 253, 99, 231, 179, 81, 68, 41, 255, 21, 145, 145, 118, + 106, 239, 217, 169, 183, 6, 210, 125, 106, 57, 158, 114, 210, 251, + 160, 177, 64, 16, 84, 24, 217, 87, 86, 180, 61, 144, 226, 82, + 253, 16, 153, 123, 67, 159, 90, 28, 183, 230, 178, 177, 152, 235, + 26, 224, 124, 27, 26, 254, 231, 103, 199, 84, 163, 76, 162, 107, + 145, 205, 60, 67, 137, 227, 0, 226, 33, 233, 216, 193, 33, 240, + 36, 239, 170, 218, 86, 50, 235, 102, 126, 2, 2, 200, 39, 16, + 72, 186, 197, 254, 149, 222, 223, 117, 198, 14, 117, 147, 56, 208, + 246, 72, 159, 34, 125, 52, 0, 215, 34, 169, 163, 189, 107, 143, + 49, 157, 51, 165, 134, 202, 27, 80, 185, 198, 137, 217, 159, 247, + 6, 126, 182, 105, 218, 41, 141, 145, 10, 57, 154, 97, 24, 219, + 173, 252, 166, 89, 47, 77, 12, 108, 212, 206, 240, 155, 14, 208, + 253, 120, 123, 13, 46, 158, 190, 99, 79, 209, 123, 42, 47, 67, + 134, 4, 71, 11, 148, 94, 141, 161, 66, 203, 101, 225, 138, 81, + 195, 89, 250, 211, 79, 157, 58, 211, 222, 212, 241, 235, 129, 105, + 221, 227, 103, 196, 156, 95, 1, 225, 130, 29, 235, 81, 150, 143, + 119, 254, 105, 242, 162, 182, 87, 228, 52, 7, 253, 111, 36, 85, + 254, 67, 249, 63, 238, 144, 16, 112, 160, 36, 214, 152, 213, 26, + 56, 9, 113, 170, 234, 219, 31, 70, 167, 46, 167, 248, 242, 171, + 214, 153, 88, 95, 54, 134, 57, 172, 79, 132, 197, 56, 34, 48, + 75, 111, 30, 60, 51, 47, 209, 14, 247, 212, 186, 196, 223, 246, + 12, 15, 203, 242, 243, 37, 239, 121, 84, 155, 90, 6, 201, 24, + 87, 240, 249, 145, 77, 65, 87, 66, 79, 0, 217, 246, 197, 161, + 124, 53, 2, 174, 213, 119, 19, 81, 218, 32, 15, 181, 109, 196, + 131, 187, 95, 234, 201, 103, 201, 185, 228, 194, 170, 30, 93, 254, + 109, 138, 156, 190, 105, 210, 182, 246, 0, 159, 198, 26, 199, 8, + 121, 60, 138, 116, 218, 37, 57, 108, 76, 53, 116, 70, 188, 19, + 213, 167, 163, 26, 105, 246, 136, 29, 91, 110, 47, 53, 63, 253, + 24, 44, 3, 67, 84, 2, 95, 84, 10, 68, 211, 141, 29, 145, + 81, 39, 16, 215, 248, 93, 88, 197, 53, 204, 235, 0, 199, 75, + 90, 62, 153, 103, 239, 173, 170, 33, 209, 200, 188, 255, 210, 45, + 115, 27, 62, 60, 131, 202, 25, 44, 62, 206, 27, 243, 252, 130, + 232, 225, 95, 54, 108, 233, 138, 53, 146, 112, 100, 136, 174, 215, + 95, 6, 116, 193, 179, 214, 85, 48, 98, 91, 251, 102, 111, 173, + 178, 180, 234, 66, 80, 121, 152, 251, 201, 212, 156, 4, 129, 147, + 99, 251, 234, 99, 207, 175, 1, 2, 26, 51, 163, 123, 119, 4, + 120, 204, 98, 116, 195, 129, 109, 87, 44, 171, 150, 49, 237, 74, + 32, 169, 45, 144, 101, 221, 122, 149, 96, 209, 2, 233, 105, 204, + 226, 126, 141, 244, 106, 141, 102, 249, 185, 64, 36, 203, 45, 111, + 87, 204, 68, 82, 229, 95, 177, 146, 213, 97, 146, 91, 240, 23, + 60, 9, 171, 200, 192, 122, 170, 151, 192, 200, 171, 119, 207, 156, + 205, 148, 171, 20, 12, 4, 239, 243, 206, 16, 104, 59, 234, 152, + 24, 83, 74, 32, 98, 95, 201, 169, 243, 8, 47, 234, 79, 135, + 206, 87, 208, 101, 121, 95, 106, 234, 78, 114, 213, 154, 44, 82, + 196, 40, 87, 145, 19, 234, 227, 113, 64, 53, 127, 151, 74, 239, + 94, 112, 27, 220, 118, 231, 185, 131, 52, 106, 52, 17, 25, 96, + 166, 8, 102, 41, 243, 23, 62, 112, 226, 36, 205, 163, 181, 121, + 135, 141, 243, 152, 41, 77, 135, 194, 208, 163, 123, 242, 204, 49, + 123, 217, 214, 204, 165, 230, 229, 67, 119, 141, 161, 153, 156, 185, + 106, 82, 36, 205, 74, 189, 41, 65, 179, 252, 41, 203, 253, 83, + 10, 178, 165, 204, 69, 96, 129, 0, 199, 236, 118, 0, 93, 19, + 41, 50, 162, 163, 142, 83, 157, 147, 69, 8, 148, 165, 234, 154, + 212, 221, 88, 21, 55, 97, 11, 149, 181, 193, 32, 77, 248, 177, + 66, 45, 252, 87, 24, 115, 62, 238, 1, 9, 108, 142, 107, 147, + 64, 202, 44, 50, 200, 148, 197, 157, 176, 92, 220, 9, 99, 212, + 74, 43, 80, 104, 154, 253, 217, 12, 140, 239, 96, 35, 217, 40, + 117, 253, 52, 105, 227, 34, 213, 33, 163, 255, 194, 109, 186, 197, + 66, 10, 163, 159, 232, 88, 117, 122, 209, 107, 214, 211, 206, 227, + 195, 126, 147, 66, 233, 146, 116, 81, 241, 223, 249, 250, 125, 199, + 8, 196, 237, 48, 115, 246, 223, 47, 34, 243, 23, 217, 231, 153, + 21, 56, 253, 14, 144, 33, 19, 161, 68, 219, 46, 156, 54, 254, + 110, 184, 169, 16, 131, 222, 216, 173, 44, 50, 144, 188, 142, 246, + 112, 138, 235, 248, 107, 212, 37, 16, 254, 64, 70, 87, 67, 15, + 28, 236, 83, 17, 183, 64, 209, 61, 4, 86, 95, 248, 4, 43, + 30, 78, 39, 247, 153, 183, 223, 68, 130, 33, 233, 112, 201, 125, + 42, 250, 85, 134, 22, 171, 249, 105, 228, 162, 32, 222, 57, 232, + 208, 62, 49, 189, 50, 41, 197, 248, 147, 128, 81, 3, 249, 248, + 149, 18, 164, 42, 23, 53, 228, 103, 63, 109, 9, 87, 31, 209, + 234, 0, 55, 68, 137, 11, 9, 63, 211, 224, 149, 179, 14, 199, + 191, 121, 165, 9, 154, 219, 8, 116, 245, 154, 47, 140, 94, 18, + 242, 14, 110, 217, 207, 120, 181, 196, 15, 182, 203, 238, 1, 75, + 215, 248, 96, 64, 211, 28, 26, 14, 179, 3, 43, 24, 219, 236, + 2, 250, 232, 245, 247, 82, 163, 108, 1, 64, 227, 246, 179, 171, + 179, 217, 220, 68, 96, 90, 191, 99, 166, 134, 98, 139, 36, 243, + 38, 187, 177, 229, 70, 175, 215, 172, 40, 51, 49, 136, 58, 121, + 208, 97, 254, 123, 62, 44, 216, 69, 161, 87, 141, 44, 70, 137, + 67, 191, 8, 116, 197, 173, 158, 193, 223, 225, 48, 70, 9, 207, + 224, 143, 96, 189, 231, 10, 140, 231, 15, 3, 137, 8, 165, 189, + 96, 24, 200, 239, 43, 28, 155, 204, 228, 102, 97, 121, 82, 215, + 115, 27, 152, 14, 243, 199, 147, 33, 6, 84, 177, 242, 71, 163, + 82, 206, 0, 54, 4, 192, 68, 164, 144, 236, 75, 7, 164, 133, + 101, 57, 55, 217, 181, 61, 98, 180, 120, 187, 42, 160, 138, 34, + 213, 248, 110, 147, 173, 41, 85, 221, 139, 26, 53, 207, 219, 130, + 228, 51, 97, 129, 36, 218, 22, 39, 64, 110, 18, 183, 219, 177, + 39, 79, 76, 2, 44, 126, 235, 62, 48, 249, 155, 50, 225, 43, + 86, 212, 253, 182, 114, 216, 117, 41, 104, 155, 92, 233, 115, 187, + 6, 231, 38, 219, 229, 161, 64, 213, 235, 42, 179, 228, 161, 84, + 239, 180, 227, 5, 102, 206, 44, 220, 62, 12, 247, 48, 245, 194, + 105, 147, 76, 147, 46, 143, 208, 25, 69, 197, 57, 89, 189, 185, + 92, 114, 143, 107, 235, 141, 252, 37, 131, 172, 233, 99, 103, 189, + 197, 68, 193, 165, 20, 178, 254, 234, 237, 167, 206, 75, 255, 22, + 63, 228, 111, 35, 85, 151, 111, 157, 10, 2, 139, 90, 136, 203, + 232, 248, 234, 190, 135, 57, 201, 42, 94, 75, 148, 251, 99, 145, + 204, 96, 84, 134, 106, 77, 119, 199, 206, 214, 186, 253, 150, 186, + 51, 23, 108, 107, 107, 226, 0, 14, 31, 47, 234, 151, 11, 181, + 159, 45, 114, 5, 3, 18, 99, 247, 59, 68, 165, 103, 61, 212, + 52, 176, 30, 137, 1, 134, 22, 91, 35, 44, 203, 114, 247, 196, + 245, 97, 245, 100, 155, 101, 45, 62, 139, 8, 134, 218, 223, 223, + 189, 80, 3, 137, 144, 5, 44, 99, 132, 5, 121, 127, 151, 152, + 38, 135, 68, 248, 22, 64, 105, 155, 181, 233, 95, 130, 157, 154, + 72, 55, 205, 174, 16, 193, 206, 181, 192, 14, 187, 131, 62, 106, + 65, 24, 66, 6, 32, 14, 6, 154, 169, 57, 111, 68, 71, 244, + 191, 4, 66, 60, 249, 90, 2, 235, 185, 72, 186, 113, 41, 124, + 77, 136, 39, 158, 250, 249, 186, 223, 206, 93, 38, 0, 3, 76, + 214, 112, 185, 20, 167, 0, 54, 80, 77, 92, 125, 93, 243, 233, + 87, 227, 66, 152, 80, 205, 245, 150, 12, 179, 157, 14, 50, 63, + 144, 2, 12, 194, 151, 20, 92, 159, 111, 213, 136, 34, 103, 221, + 223, 223, 167, 45, 111, 16, 57, 83, 164, 66, 64, 22, 244, 211, + 175, 115, 176, 147, 119, 112, 188, 110, 168, 123, 242, 64, 23, 36, + 191, 248, 156, 1, 102, 155, 21, 88, 222, 53, 50, 0, 254, 116, + 93, 90, 195, 158, 193, 250, 130, 38, 169, 217, 17, 84, 205, 83, + 170, 145, 229, 244, 195, 228, 80, 229, 86, 84, 149, 165, 151, 131, + 117, 71, 45, 10, 21, 108, 106, 237, 118, 103, 218, 15, 30, 152, + 5, 156, 84, 212, 56, 40, 15, 133, 141, 237, 80, 86, 243, 225, + 187, 199, 41, 180, 117, 112, 35, 191, 61, 65, 217, 36, 37, 233, + 76, 60, 82, 153, 210, 128, 199, 236, 112, 245, 82, 82, 130, 244, + 150, 41, 127, 222, 190, 208, 60, 194, 193, 84, 113, 245, 255, 52, + 32, 5, 42, 226, 220, 172, 89, 9, 17, 101, 205, 242, 172, 130, + 58, 174, 231, 184, 151, 241, 7, 102, 46, 64, 69, 157, 249, 134, + 190, 44, 222, 249, 139, 207, 141, 214, 190, 208, 198, 229, 251, 250, + 135, 130, 18, 207, 62, 141, 77, 2, 131, 155, 207, 10, 234, 233, + 155, 92, 48, 21, 51, 222, 135, 24, 10, 46, 210, 178, 24, 139, + 14, 81, 151, 95, 170, 182, 30, 147, 101, 121, 70, 249, 249, 225, + 104, 65, 48, 198, 119, 0, 169, 71, 93, 8, 225, 149, 153, 21, + 15, 194, 176, 188, 56, 195, 216, 202, 250, 117, 161, 127, 226, 177, + 233, 179, 232, 74, 206, 182, 216, 216, 195, 139, 122, 61, 131, 138, + 150, 143, 25, 17, 160, 139, 208, 138, 178, 141, 154, 240, 190, 186, + 235, 29, 58, 218, 202, 56, 140, 188, 129, 168, 83, 157, 185, 94, + 56, 151, 192, 116, 25, 60, 144, 38, 216, 5, 205, 135, 180, 28, + 6, 24, 156, 163, 253, 179, 193, 253, 208, 71, 187, 208, 252, 251, + 93, 162, 243, 133, 168, 75, 182, 75, 39, 30, 233, 89, 85, 31, + 87, 24, 6, 207, 145, 164, 127, 4, 62, 34, 48, 211, 200, 153, + 249, 151, 226, 75, 171, 151, 97, 7, 225, 40, 61, 190, 145, 112, + 97, 159, 172, 92, 27, 223, 113, 96, 76, 184, 138, 6, 118, 40, + 124, 39, 3, 125, 244, 210, 34, 108, 239, 131, 223, 245, 126, 202, + 24, 150, 7, 131, 196, 177, 139, 149, 82, 196, 9, 221, 140, 82, + 86, 113, 192, 117, 221, 83, 165, 168, 235, 105, 165, 61, 222, 119, + 253, 22, 56, 242, 211, 204, 134, 98, 106, 107, 82, 170, 242, 18, + 188, 173, 242, 103, 157, 71, 102, 129, 111, 136, 52, 5, 165, 99, + 132, 202, 148, 35, 213, 134, 29, 1, 132, 244, 149, 109, 125, 174, + 52, 234, 212, 56, 80, 48, 83, 129, 70, 11, 23, 41, 4, 214, + 238, 161, 197, 244, 134, 184, 67, 186, 227, 38, 212, 89, 126, 73, + 9, 202, 24, 168, 193, 42, 176, 7, 216, 164, 109, 94, 112, 196, + 121, 63, 141, 29, 220, 254, 188, 16, 153, 171, 5, 161, 7, 190, + 172, 77, 222, 21, 127, 15, 111, 231, 186, 159, 34, 106, 67, 175, + 242, 97, 93, 249, 12, 217, 159, 115, 23, 130, 6, 38, 231, 33, + 193, 254, 238, 153, 130, 66, 63, 227, 48, 32, 45, 100, 241, 127, + 97, 222, 138, 157, 75, 238, 16, 129, 192, 92, 163, 121, 252, 241, + 106, 75, 142, 186, 253, 169, 116, 168, 105, 38, 95, 189, 225, 7, + 155, 13, 76, 70, 112, 8, 226, 160, 174, 213, 179, 236, 36, 30, + 225, 96, 248, 233, 33, 227, 108, 236, 152, 70, 153, 198, 245, 7, + 175, 58, 10, 142, 133, 253, 36, 146, 24, 57, 93, 243, 222, 227, + 97, 55, 168, 209, 84, 1, 11, 152, 28, 196, 147, 48, 67, 170, + 216, 54, 186, 154, 37, 159, 198, 74, 246, 126, 45, 185, 248, 75, + 180, 182, 171, 142, 159, 230, 85, 37, 105, 99, 170, 178, 197, 235, + 55, 113, 189, 139, 6, 36, 9, 32, 130, 11, 91, 188, 174, 96, + 72, 210, 89, 126, 192, 58, 97, 187, 76, 0, 110, 20, 19, 2, + 187, 39, 30, 243, 132, 181, 20, 40, 144, 195, 67, 121, 10, 146, + 76, 154, 5, 79, 22, 136, 27, 230, 141, 161, 145, 154, 50, 40, + 40, 23, 33, 178, 235, 79, 48, 221, 132, 164, 169, 249, 155, 38, + 185, 170, 165, 54, 130, 66, 23, 161, 250, 85, 143, 43, 252, 254, + 135, 211, 166, 240, 140, 37, 47, 86, 96, 220, 128, 75, 153, 213, + 251, 167, 216, 177, 142, 157, 193, 59, 245, 215, 116, 65, 192, 235, + 95, 199, 71, 120, 130, 226, 113, 243, 233, 90, 178, 108, 222, 97, + 88, 248, 163, 118, 48, 190, 201, 4, 24, 161, 35, 241, 179, 246, + 24, 76, 188, 98, 152, 53, 51, 212, 156, 117, 171, 215, 13, 133, + 185, 88, 126, 150, 223, 97, 174, 126, 171, 28, 6, 219, 102, 240, + 28, 64, 33, 105, 220, 200, 139, 142, 53, 20, 176, 102, 148, 226, + 46, 86, 210, 23, 164, 128, 25, 240, 214, 254, 240, 163, 181, 44, + 132, 35, 29, 91, 155, 67, 83, 11, 64, 43, 120, 105, 2, 177, + 110, 244, 223, 186, 182, 239, 14, 21, 166, 41, 164, 149, 153, 76, + 175, 238, 16, 173, 65, 193, 175, 110, 73, 18, 149, 149, 157, 166, + 118, 200, 197, 197, 197, 116, 232, 147, 35, 175, 135, 174, 153, 65, + 27, 187, 77, 114, 19, 254, 211, 216, 181, 246, 59, 66, 17, 240, + 173, 42, 133, 121, 84, 73, 241, 80, 232, 152, 173, 154, 235, 67, + 48, 79, 41, 63, 251, 115, 0, 15, 106, 64, 31, 62, 14, 243, + 9, 6, 247, 252, 151, 211, 182, 77, 7, 154, 59, 168, 109, 121, + 43, 186, 186, 21, 80, 11, 143, 89, 168, 47, 202, 60, 153, 27, + 248, 129, 224, 103, 106, 144, 86, 225, 187, 13, 142, 243, 171, 25, + 50, 203, 245, 2, 98, 139, 17, 10, 120, 178, 48, 149, 149, 198, + 116, 217, 77, 30, 236, 223, 229, 87, 126, 94, 87, 160, 75, 26, + 26, 182, 27, 226, 166, 177, 181, 20, 219, 22, 224, 207, 161, 123, + 180, 156, 33, 252, 126, 0, 158, 175, 249, 34, 203, 124, 221, 95, + 142, 26, 68, 111, 161, 24, 220, 139, 85, 239, 42, 110, 138, 34, + 84, 149, 59, 137, 12, 16, 169, 178, 197, 93, 206, 208, 134, 115, + 161, 65, 141, 58, 16, 11, 236, 25, 225, 58, 101, 213, 55, 183, + 179, 177, 216, 220, 240, 168, 57, 55, 50, 15, 135, 34, 155, 68, + 231, 87, 250, 17, 122, 231, 178, 90, 152, 222, 165, 81, 26, 101, + 49, 239, 4, 168, 131, 168, 67, 133, 210, 39, 55, 234, 109, 168, + 20, 126, 39, 252, 83, 127, 54, 156, 154, 90, 146, 97, 145, 50, + 181, 44, 54, 235, 74, 232, 168, 117, 101, 28, 64, 238, 167, 239, + 181, 124, 16, 66, 231, 159, 250, 46, 22, 237, 194, 19, 14, 221, + 241, 48, 249, 242, 119, 35, 13, 52, 55, 111, 53, 208, 130, 50, + 72, 230, 32, 219, 19, 20, 180, 124, 133, 8, 0, 121, 134, 249, + 183, 41, 65, 193, 162, 72, 43, 117, 239, 114, 60, 223, 80, 194, + 215, 0, 242, 15, 198, 212, 2, 66, 0, 90, 16, 29, 250, 240, + 138, 104, 17, 157, 198, 113, 24, 94, 220, 94, 111, 51, 164, 226, + 222, 16, 222, 140, 119, 72, 36, 252, 175, 145, 73, 124, 95, 152, + 251, 192, 162, 96, 238, 61, 0, 82, 94, 108, 36, 109, 74, 90, + 124, 59, 76, 244, 17, 8, 108, 8, 65, 224, 78, 134, 35, 67, + 51, 158, 248, 152, 99, 114, 86, 1, 160, 12, 127, 193, 186, 220, + 215, 120, 233, 78, 170, 197, 133, 219, 216, 245, 172, 41, 76, 44, + 51, 234, 238, 131, 46, 170, 125, 91, 107, 88, 186, 177, 159, 168, + 92, 209, 150, 149, 68, 50, 30, 218, 149, 225, 84, 229, 165, 146, + 7, 255, 30, 104, 230, 118, 115, 73, 171, 135, 97, 64, 122, 192, + 116, 82, 149, 37, 89, 216, 243, 215, 157, 139, 197, 101, 210, 206, + 183, 227, 184, 123, 242, 189, 128, 16, 121, 134, 73, 158, 77, 33, + 203, 21, 104, 59, 140, 110, 23, 170, 36, 177, 227, 0, 85, 98, + 208, 165, 125, 99, 244, 51, 71, 194, 197, 251, 55, 155, 78, 212, + 190, 116, 121, 5, 25, 45, 24, 160, 53, 17, 147, 17, 185, 136, + 141, 11, 233, 135, 0, 87, 245, 147, 159, 147, 145, 131, 231, 174, + 173, 251, 108, 10, 166, 90, 91, 169, 50, 226, 43, 56, 106, 3, + 74, 108, 134, 194, 240, 94, 186, 203, 41, 104, 252, 92, 72, 181, + 129, 65, 199, 44, 156, 69, 67, 114, 41, 113, 179, 241, 167, 184, + 180, 32, 232, 77, 75, 96, 97, 0, 98, 54, 173, 35, 147, 94, + 152, 117, 134, 220, 252, 32, 37, 18, 3, 118, 61, 193, 133, 112, + 68, 142, 113, 188, 196, 235, 50, 160, 104, 225, 254, 0, 98, 154, + 160, 228, 159, 89, 153, 254, 53, 149, 25, 139, 110, 170, 134, 249, + 112, 125, 249, 212, 242, 225, 161, 214, 23, 179, 152, 63, 162, 211, + 167, 199, 72, 102, 77, 13, 68, 161, 137, 65, 220, 36, 120, 206, + 68, 238, 158, 230, 53, 69, 23, 216, 223, 4, 224, 196, 103, 198, + 44, 199, 47, 4, 217, 12, 154, 41, 197, 237, 61, 25, 165, 131, + 63, 165, 137, 153, 136, 86, 206, 16, 183, 83, 19, 151, 112, 185, + 184, 143, 178, 233, 255, 164, 234, 204, 199, 231, 224, 91, 78, 193, + 95, 177, 146, 125, 180, 103, 32, 25, 137, 4, 99, 200, 135, 191, + 55, 196, 7, 79, 193, 203, 61, 46, 44, 212, 255, 152, 220, 200, + 74, 90, 78, 63, 210, 182, 61, 175, 249, 192, 68, 208, 143, 133, + 178, 149, 185, 191, 76, 75, 167, 211, 14, 221, 224, 40, 216, 124, + 148, 223, 51, 190, 174, 137, 168, 221, 227, 155, 92, 185, 64, 180, + 239, 230, 216, 245, 77, 112, 224, 160, 223, 0, 58, 204, 157, 225, + 136, 92, 11, 106, 74, 242, 28, 235, 246, 103, 108, 14, 173, 27, + 17, 92, 135, 24, 22, 38, 7, 192, 252, 247, 131, 161, 213, 61, + 137, 209, 255, 161, 27, 226, 60, 40, 76, 235, 138, 113, 100, 67, + 190, 113, 184, 144, 102, 132, 171, 217, 118, 29, 255, 193, 74, 186, + 105, 219, 12, 6, 209, 217, 7, 114, 107, 55, 135, 28, 158, 228, + 125, 63, 103, 52, 233, 23, 173, 159, 153, 32, 141, 38, 165, 139, + 242, 224, 147, 155, 151, 87, 231, 75, 78, 82, 253, 34, 174, 20, + 31, 134, 248, 169, 22, 139, 175, 238, 254, 46, 232, 238, 120, 19, + 106, 216, 126, 0, 73, 192, 155, 25, 63, 82, 166, 159, 131, 255, + 29, 129, 217, 147, 110, 227, 67, 160, 251, 68, 59, 213, 7, 41, + 212, 185, 230, 1, 229, 119, 9, 61, 94, 42, 247, 42, 124, 68, + 6, 228, 52, 86, 209, 81, 59, 127, 243, 184, 45, 33, 56, 63, + 117, 4, 222, 88, 220, 45, 37, 203, 89, 223, 218, 166, 3, 93, + 29, 118, 185, 120, 230, 126, 177, 37, 62, 21, 157, 140, 25, 141, + 89, 221, 172, 224, 81, 108, 227, 122, 33, 167, 245, 181, 95, 191, + 60, 88, 94, 71, 52, 173, 154, 27, 113, 62, 46, 82, 46, 39, + 27, 6, 109, 213, 42, 215, 122, 108, 167, 56, 215, 72, 240, 23, + 85, 251, 128, 202, 188, 224, 98, 35, 255, 138, 1, 95, 44, 1, + 68, 152, 118, 255, 207, 24, 174, 107, 42, 72, 83, 84, 42, 121, + 254, 91, 136, 108, 83, 255, 155, 69, 182, 205, 149, 116, 243, 70, + 44, 127, 111, 108, 195, 138, 52, 146, 17, 208, 12, 33, 107, 16, + 214, 173, 158, 17, 100, 218, 215, 166, 54, 160, 28, 230, 164, 248, + 186, 132, 36, 69, 137, 24, 230, 145, 65, 34, 38, 20, 111, 60, + 51, 184, 139, 85, 141, 110, 37, 81, 224, 111, 160, 77, 145, 154, + 15, 30, 209, 16, 243, 248, 144, 28, 52, 21, 11, 133, 172, 244, + 38, 215, 66, 100, 100, 34, 125, 121, 30, 104, 66, 45, 62, 8, + 228, 76, 141, 127, 195, 123, 204, 247, 1, 67, 167, 52, 250, 196, + 111, 233, 106, 216, 113, 212, 0, 70, 158, 155, 192, 194, 143, 215, + 19, 104, 61, 236, 29, 93, 247, 1, 99, 106, 53, 100, 189, 190, + 30, 87, 26, 68, 1, 32, 132, 90, 158, 145, 168, 106, 12, 155, + 232, 14, 168, 90, 248, 234, 30, 199, 226, 112, 120, 100, 187, 4, + 56, 59, 22, 193, 124, 210, 248, 59, 151, 16, 249, 12, 68, 227, + 214, 131, 218, 73, 33, 92, 65, 185, 42, 123, 13, 237, 150, 45, + 78, 237, 147, 201, 50, 27, 58, 66, 170, 125, 250, 55, 154, 229, + 191, 30, 13, 152, 219, 21, 49, 189, 127, 132, 242, 189, 134, 13, + 34, 67, 209, 36, 145, 122, 240, 122, 201, 238, 137, 73, 221, 171, + 220, 14, 207, 137, 56, 107, 118, 211, 188, 14, 208, 196, 150, 198, + 188, 39, 182, 255, 139, 34, 59, 44, 84, 166, 172, 26, 88, 117, + 87, 113, 244, 134, 18, 46, 224, 138, 72, 112, 185, 76, 136, 45, + 202, 45, 26, 70, 150, 253, 210, 221, 94, 126, 49, 169, 141, 192, + 12, 130, 24, 14, 121, 94, 47, 165, 20, 217, 35, 156, 234, 63, + 224, 122, 63, 218, 121, 159, 64, 245, 65, 105, 193, 146, 39, 174, + 216, 254, 222, 97, 15, 155, 9, 153, 105, 149, 151, 122, 49, 228, + 15, 183, 96, 27, 140, 91, 160, 12, 157, 250, 49, 206, 176, 78, + 230, 110, 29, 71, 138, 169, 221, 251, 174, 32, 214, 153, 90, 135, + 239, 156, 180, 155, 107, 76, 34, 137, 223, 142, 199, 104, 209, 212, + 167, 121, 246, 163, 94, 220, 235, 62, 51, 237, 0, 51, 63, 56, + 86, 12, 163, 62, 81, 109, 104, 47, 125, 62, 86, 226, 88, 66, + 115, 35, 4, 133, 103, 130, 225, 58, 98, 43, 214, 73, 239, 63, + 180, 126, 198, 127, 249, 167, 77, 60, 162, 64, 127, 81, 250, 212, + 163, 52, 14, 5, 96, 176, 140, 76, 240, 56, 68, 197, 52, 225, + 201, 43, 100, 106, 241, 68, 118, 2, 72, 58, 52, 131, 218, 47, + 182, 215, 139, 254, 46, 72, 222, 5, 90, 27, 171, 185, 174, 90, + 175, 30, 204, 225, 239, 236, 251, 125, 172, 55, 14, 253, 47, 177, + 182, 8, 94, 153, 70, 215, 35, 226, 236, 31, 220, 228, 69, 75, + 122, 245, 207, 185, 55, 29, 63, 245, 39, 16, 67, 221, 91, 189, + 150, 57, 12, 113, 121, 47, 48, 195, 31, 151, 223, 40, 146, 19, + 175, 197, 75, 197, 71, 66, 82, 65, 182, 165, 181, 145, 153, 9, + 71, 116, 180, 243, 240, 214, 246, 83, 83, 167, 207, 86, 246, 57, + 82, 166, 133, 21, 13, 137, 51, 87, 217, 155, 51, 131, 81, 245, + 196, 249, 180, 214, 116, 85, 114, 154, 206, 159, 86, 177, 97, 109, + 244, 74, 49, 164, 126, 149, 174, 229, 167, 240, 183, 26, 241, 193, + 37, 152, 16, 246, 240, 37, 200, 184, 230, 120, 72, 201, 47, 219, + 117, 252, 83, 220, 191, 16, 252, 231, 77, 8, 79, 4, 26, 95, + 210, 26, 92, 106, 247, 147, 140, 64, 0, 149, 84, 249, 194, 225, + 87, 171, 24, 144, 125, 233, 234, 125, 66, 83, 229, 243, 161, 223, + 192, 40, 122, 119, 161, 162, 99, 60, 193, 182, 96, 28, 192, 254, + 17, 130, 69, 195, 218, 165, 34, 151, 190, 135, 122, 253, 72, 255, + 95, 87, 65, 57, 4, 54, 74, 197, 251, 114, 225, 25, 104, 145, + 102, 98, 217, 123, 190, 43, 51, 178, 226, 40, 151, 69, 117, 139, + 82, 143, 225, 1, 32, 231, 228, 38, 14, 21, 110, 2, 113, 226, + 21, 251, 108, 82, 123, 248, 150, 193, 26, 243, 134, 70, 166, 136, + 9, 233, 70, 54, 78, 2, 150, 113, 54, 128, 240, 102, 199, 1, + 162, 51, 253, 49, 43, 199, 247, 5, 222, 33, 222, 51, 192, 153, + 101, 156, 200, 144, 200, 230, 83, 158, 77, 42, 136, 215, 84, 248, + 51, 88, 31, 80, 126, 101, 96, 5, 42, 253, 31, 131, 57, 1, + 77, 118, 221, 5, 176, 126, 153, 187, 183, 148, 83, 93, 168, 218, + 220, 195, 203, 221, 209, 125, 167, 191, 57, 134, 12, 97, 131, 180, + 138, 238, 4, 146, 249, 222, 31, 222, 123, 217, 146, 181, 83, 146, + 176, 172, 117, 248, 33, 218, 92, 170, 82, 116, 144, 124, 127, 244, + 174, 156, 8, 245, 226, 147, 39, 7, 48, 236, 143, 156, 42, 227, + 52, 47, 204, 43, 184, 78, 252, 114, 208, 15, 27, 84, 81, 95, + 6, 230, 200, 6, 199, 146, 179, 12, 188, 118, 69, 60, 40, 141, + 160, 26, 65, 51, 239, 169, 27, 24, 196, 96, 152, 50, 44, 73, + 171, 191, 52, 24, 97, 93, 185, 39, 80, 1, 225, 179, 252, 90, + 145, 254, 20, 95, 248, 196, 14, 18, 148, 148, 9, 18, 199, 45, + 113, 40, 101, 208, 239, 29, 58, 124, 61, 103, 198, 172, 103, 77, + 25, 91, 97, 90, 208, 211, 243, 221, 226, 50, 95, 181, 240, 69, + 34, 92, 148, 187, 187, 149, 143, 54, 53, 62, 153, 36, 22, 19, + 90, 4, 11, 204, 181, 179, 157, 111, 202, 106, 127, 199, 196, 146, + 92, 18, 46, 90, 64, 213, 207, 90, 201, 36, 205, 41, 65, 98, + 119, 9, 68, 3, 194, 200, 62, 207, 221, 68, 227, 139, 100, 212, + 115, 164, 162, 65, 200, 104, 68, 142, 249, 131, 173, 103, 35, 94, + 28, 248, 251, 213, 212, 118, 205, 33, 73, 175, 105, 119, 148, 151, + 173, 147, 132, 47, 92, 27, 209, 210, 90, 152, 39, 234, 179, 72, + 108, 222, 169, 238, 14, 233, 180, 117, 229, 155, 168, 36, 193, 153, + 60, 225, 26, 242, 71, 251, 145, 20, 252, 157, 239, 229, 209, 132, + 136, 51, 180, 140, 16, 188, 229, 142, 144, 145, 200, 58, 116, 96, + 212, 152, 161, 156, 186, 154, 43, 103, 91, 17, 51, 33, 91, 7, + 7, 202, 115, 248, 216, 98, 3, 91, 74, 129, 102, 61, 31, 21, + 173, 183, 16, 49, 157, 31, 215, 22, 188, 28, 183, 17, 34, 78, + 215, 23, 52, 226, 105, 45, 62, 63, 59, 23, 253, 158, 70, 16, + 70, 205, 96, 177, 90, 80, 145, 74, 193, 100, 15, 142, 176, 33, + 251, 134, 4, 137, 114, 161, 59, 22, 235, 247, 141, 251, 25, 230, + 36, 197, 139, 102, 23, 205, 12, 104, 109, 51, 188, 247, 193, 242, + 211, 111, 128, 131, 98, 110, 91, 187, 196, 124, 98, 21, 209, 159, + 42, 9, 34, 150, 48, 243, 204, 17, 70, 107, 210, 85, 131, 141, + 111, 252, 174, 192, 45, 51, 31, 105, 248, 91, 45, 29, 228, 139, + 77, 223, 159, 161, 7, 42, 102, 236, 193, 231, 233, 121, 97, 154, + 36, 50, 111, 49, 222, 217, 73, 123, 62, 239, 252, 182, 220, 29, + 44, 111, 25, 212, 224, 144, 18, 195, 208, 8, 240, 18, 181, 132, + 214, 224, 247, 94, 128, 237, 97, 142, 141, 65, 85, 120, 58, 46, + 124, 68, 26, 164, 255, 43, 119, 205, 176, 92, 151, 34, 99, 48, + 35, 38, 248, 254, 155, 213, 14, 255, 123, 58, 5, 92, 241, 182, + 156, 217, 39, 150, 135, 113, 237, 201, 50, 17, 107, 24, 200, 65, + 64, 130, 219, 151, 24, 11, 247, 169, 14, 36, 170, 102, 87, 54, + 98, 73, 247, 100, 250, 48, 36, 44, 167, 195, 221, 84, 162, 82, + 247, 154, 157, 165, 163, 199, 97, 210, 72, 176, 151, 71, 125, 248, + 198, 195, 249, 242, 0, 153, 60, 220, 152, 215, 17, 125, 8, 201, + 176, 35, 94, 42, 26, 95, 9, 181, 46, 97, 36, 189, 215, 7, + 103, 40, 199, 38, 170, 138, 3, 12, 170, 33, 181, 39, 166, 4, + 191, 201, 89, 88, 26, 52, 73, 133, 147, 62, 197, 93, 117, 189, + 111, 25, 217, 14, 121, 79, 130, 231, 19, 65, 149, 202, 222, 127, + 89, 251, 1, 179, 111, 248, 215, 233, 224, 92, 69, 251, 35, 240, + 56, 238, 177, 236, 238, 226, 231, 147, 95, 42, 48, 231, 22, 161, + 23, 124, 110, 47, 229, 106, 77, 86, 147, 32, 69, 93, 128, 75, + 59, 101, 71, 35, 125, 13, 15, 248, 28, 10, 232, 139, 71, 123, + 67, 162, 212, 100, 229, 101, 103, 80, 60, 214, 77, 179, 115, 183, + 246, 241, 32, 9, 3, 76, 21, 128, 156, 159, 31, 124, 84, 55, + 16, 187, 229, 112, 54, 177, 61, 53, 237, 61, 236, 27, 201, 76, + 189, 140, 161, 115, 42, 36, 135, 45, 52, 76, 69, 158, 133, 181, + 175, 30, 128, 24, 144, 13, 80, 209, 26, 177, 148, 121, 247, 118, + 90, 233, 45, 53, 19, 100, 200, 94, 245, 213, 118, 98, 113, 232, + 30, 134, 72, 240, 216, 57, 180, 225, 34, 67, 17, 154, 127, 22, + 9, 205, 71, 57, 149, 185, 12, 143, 57, 146, 72, 184, 237, 51, + 60, 232, 174, 65, 21, 100, 112, 182, 236, 0, 3, 97, 95, 64, + 51, 248, 60, 130, 239, 96, 216, 144, 240, 151, 2, 252, 66, 252, + 98, 86, 60, 217, 31, 16, 193, 246, 138, 127, 171, 240, 240, 100, + 163, 228, 118, 147, 35, 170, 222, 136, 168, 194, 132, 87, 87, 243, + 237, 178, 202, 96, 121, 48, 218, 77, 12, 99, 66, 67, 244, 82, + 38, 111, 130, 104, 185, 84, 52, 204, 250, 130, 248, 237, 109, 246, + 63, 14, 18, 73, 41, 229, 142, 231, 60, 122, 50, 73, 19, 109, + 44, 137, 231, 123, 103, 147, 110, 21, 106, 203, 136, 155, 49, 19, + 24, 118, 179, 3, 123, 73, 200, 51, 241, 173, 229, 187, 19, 1, + 83, 5, 196, 133, 152, 98, 241, 241, 230, 113, 231, 117, 145, 125, + 163, 91, 40, 9, 150, 138, 149, 138, 53, 17, 83, 120, 194, 165, + 27, 98, 76, 176, 60, 234, 146, 101, 122, 45, 76, 125, 233, 68, + 97, 23, 157, 132, 178, 77, 117, 119, 8, 15, 86, 168, 163, 56, + 29, 54, 200, 146, 85, 150, 69, 189, 247, 173, 250, 220, 88, 157, + 100, 68, 104, 33, 46, 162, 128, 111, 122, 119, 219, 132, 216, 76, + 119, 128, 112, 131, 88, 189, 92, 95, 148, 205, 233, 247, 220, 107, + 57, 219, 55, 167, 29, 241, 152, 94, 0, 120, 245, 244, 10, 107, + 107, 216, 85, 46, 221, 225, 207, 166, 143, 37, 58, 233, 201, 6, + 252, 95, 29, 179, 51, 78, 204, 89, 177, 85, 117, 71, 139, 104, + 134, 89, 112, 218, 26, 186, 104, 169, 255, 216, 85, 182, 198, 136, + 0, 37, 86, 90, 51, 12, 46, 219, 24, 193, 1, 193, 89, 45, + 183, 107, 232, 27, 109, 154, 41, 82, 144, 208, 250, 22, 1, 152, + 90, 50, 47, 31, 115, 239, 52, 70, 69, 108, 7, 211, 148, 187, + 20, 213, 2, 0, 194, 101, 48, 23, 127, 21, 172, 31, 76, 202, + 137, 124, 83, 181, 26, 132, 10, 248, 224, 98, 246, 192, 6, 9, + 148, 119, 180, 144, 26, 245, 50, 28, 146, 111, 69, 66, 231, 222, + 94, 206, 138, 10, 169, 68, 250, 3, 64, 74, 19, 94, 206, 172, + 240, 29, 113, 35, 119, 190, 56, 76, 204, 42, 114, 138, 218, 76, + 33, 208, 191, 136, 234, 167, 34, 142, 150, 50, 244, 140, 21, 130, + 228, 236, 27, 245, 85, 126, 82, 9, 250, 74, 238, 111, 35, 213, + 254, 161, 54, 42, 108, 68, 184, 113, 111, 110, 47, 125, 88, 135, + 76, 140, 185, 41, 190, 55, 2, 235, 123, 18, 44, 82, 48, 9, + 208, 236, 145, 123, 247, 229, 24, 34, 2, 105, 167, 205, 62, 163, + 137, 1, 197, 91, 158, 57, 172, 171, 41, 125, 100, 80, 161, 138, + 48, 56, 207, 242, 138, 164, 113, 5, 110, 249, 106, 217, 0, 126, + 86, 183, 74, 57, 194, 76, 55, 155, 255, 115, 124, 226, 180, 23, + 79, 0, 245, 93, 66, 60, 97, 233, 67, 137, 77, 103, 115, 174, + 195, 211, 22, 108, 57, 220, 182, 67, 235, 150, 245, 245, 218, 132, + 251, 209, 188, 156, 202, 36, 226, 77, 211, 113, 252, 104, 64, 104, + 73, 110, 204, 228, 96, 66, 163, 244, 196, 254, 80, 168, 149, 130, + 172, 131, 12, 192, 85, 94, 212, 230, 184, 21, 180, 252, 116, 161, + 219, 169, 173, 194, 104, 32, 104, 131, 132, 80, 221, 198, 93, 235, + 234, 91, 181, 189, 50, 5, 63, 1, 188, 191, 113, 81, 60, 60, + 202, 138, 189, 249, 83, 92, 91, 46, 122, 0, 127, 199, 46, 43, + 56, 206, 237, 145, 53, 70, 12, 163, 73, 107, 133, 180, 217, 113, + 162, 229, 6, 225, 8, 105, 21, 170, 31, 197, 137, 20, 122, 90, + 22, 68, 154, 220, 10, 219, 164, 149, 80, 58, 78, 44, 175, 185, + 157, 87, 240, 61, 76, 84, 163, 37, 205, 249, 199, 68, 147, 148, + 246, 137, 234, 160, 139, 151, 132, 127, 61, 147, 212, 77, 242, 30, + 139, 43, 182, 237, 18, 38, 84, 223, 94, 44, 114, 38, 243, 194, + 74, 217, 41, 21, 141, 106, 38, 104, 160, 33, 14, 218, 222, 41, + 210, 143, 210, 196, 232, 201, 120, 97, 41, 89, 218, 196, 174, 40, + 2, 161, 209, 52, 211, 186, 81, 59, 73, 31, 223, 148, 187, 12, + 238, 163, 11, 148, 113, 143, 31, 38, 36, 171, 160, 192, 11, 79, + 5, 162, 197, 144, 132, 169, 199, 21, 22, 88, 43, 18, 224, 119, + 54, 200, 80, 78, 166, 80, 43, 68, 154, 101, 196, 12, 214, 186, + 6, 230, 207, 73, 172, 34, 219, 221, 169, 32, 75, 205, 217, 233, + 72, 133, 195, 36, 53, 227, 234, 6, 97, 128, 91, 65, 38, 240, + 185, 215, 215, 94, 28, 240, 204, 190, 201, 218, 217, 49, 37, 159, + 51, 145, 147, 14, 94, 116, 58, 15, 138, 141, 12, 67, 153, 31, + 39, 179, 102, 223, 238, 136, 90, 42, 39, 44, 165, 173, 252, 81, + 198, 13, 29, 109, 132, 91, 93, 180, 56, 217, 38, 180, 246, 41, + 103, 28, 150, 150, 27, 54, 7, 74, 197, 79, 8, 149, 207, 67, + 229, 7, 145, 208, 57, 210, 0, 154, 93, 34, 20, 31, 163, 90, + 21, 27, 158, 160, 221, 238, 146, 67, 152, 160, 134, 163, 117, 221, + 12, 20, 252, 250, 102, 19, 172, 155, 175, 43, 194, 121, 104, 249, + 250, 134, 20, 215, 217, 170, 29, 30, 234, 244, 24, 100, 145, 29, + 62, 150, 34, 54, 95, 29, 244, 148, 104, 41, 109, 217, 177, 104, + 121, 130, 168, 85, 56, 95, 154, 55, 216, 187, 48, 104, 64, 114, + 232, 57, 151, 184, 115, 85, 176, 131, 12, 13, 161, 27, 202, 24, + 238, 114, 238, 122, 1, 173, 140, 224, 6, 199, 134, 145, 127, 132, + 69, 195, 242, 149, 78, 255, 21, 176, 34, 193, 102, 78, 112, 85, + 217, 97, 154, 0, 29, 229, 54, 249, 137, 148, 214, 70, 81, 195, + 91, 255, 24, 206, 79, 179, 150, 37, 126, 245, 253, 89, 1, 26, + 70, 163, 250, 140, 131, 228, 173, 67, 60, 8, 239, 205, 134, 115, + 210, 173, 81, 132, 26, 224, 4, 16, 57, 241, 174, 213, 96, 245, + 124, 158, 139, 74, 229, 133, 123, 102, 60, 84, 161, 170, 1, 142, + 190, 199, 204, 227, 63, 89, 83, 9, 188, 195, 163, 96, 157, 20, + 162, 119, 54, 158, 90, 122, 61, 185, 64, 128, 132, 12, 53, 100, + 18, 47, 36, 126, 133, 147, 59, 150, 181, 143, 46, 162, 187, 0, + 64, 123, 67, 62, 122, 1, 70, 144, 22, 59, 230, 1, 202, 85, + 22, 64, 15, 90, 217, 241, 185, 118, 16, 8, 140, 121, 102, 203, + 226, 71, 125, 17, 24, 147, 213, 139, 173, 77, 59, 81, 15, 21, + 95, 255, 130, 204, 130, 45, 173, 225, 15, 158, 142, 50, 8, 124, + 193, 74, 185, 71, 136, 195, 92, 20, 192, 110, 90, 207, 49, 157, + 239, 173, 209, 162, 161, 84, 17, 240, 228, 211, 68, 13, 74, 163, + 149, 11, 213, 15, 112, 220, 0, 129, 1, 65, 8, 153, 212, 109, + 94, 17, 157, 93, 238, 212, 135, 92, 19, 167, 47, 63, 17, 5, + 32, 85, 113, 253, 233, 35, 103, 187, 188, 88, 3, 161, 125, 194, + 30, 105, 159, 153, 6, 155, 11, 16, 56, 66, 123, 49, 190, 150, + 83, 180, 38, 162, 235, 78, 36, 194, 89, 108, 116, 165, 254, 154, + 135, 250, 164, 250, 176, 43, 32, 147, 63, 216, 177, 105, 141, 196, + 16, 79, 86, 133, 186, 19, 159, 125, 57, 17, 244, 142, 27, 47, + 126, 74, 21, 237, 94, 129, 190, 26, 135, 45, 191, 240, 113, 252, + 223, 102, 236, 171, 140, 11, 79, 230, 125, 219, 32, 116, 234, 242, + 58, 196, 45, 227, 94, 190, 162, 192, 57, 101, 218, 234, 54, 111, + 52, 101, 249, 187, 85, 240, 250, 194, 162, 189, 212, 175, 211, 60, + 250, 103, 50, 41, 131, 4, 91, 62, 232, 157, 123, 252, 87, 128, + 29, 3, 58, 114, 120, 142, 104, 125, 83, 100, 238, 123, 29, 191, + 53, 31, 217, 58, 213, 128, 66, 35, 146, 239, 247, 127, 37, 196, + 86, 21, 189, 30, 133, 42, 214, 189, 50, 195, 245, 206, 218, 122, + 81, 99, 178, 200, 241, 208, 178, 38, 218, 171, 52, 242, 161, 205, + 128, 22, 168, 99, 240, 39, 164, 127, 135, 26, 254, 35, 43, 201, + 33, 122, 180, 213, 244, 22, 80, 160, 55, 204, 47, 19, 8, 40, + 7, 5, 41, 155, 187, 233, 204, 113, 213, 55, 147, 251, 91, 143, + 86, 103, 254, 138, 47, 148, 112, 48, 65, 241, 43, 236, 178, 180, + 45, 192, 140, 100, 225, 14, 202, 117, 178, 201, 240, 92, 219, 30, + 52, 45, 168, 29, 153, 34, 63, 197, 129, 153, 222, 234, 239, 0, + 238, 134, 85, 78, 94, 243, 32, 204, 76, 223, 99, 70, 120, 115, + 179, 253, 135, 116, 175, 57, 79, 191, 50, 136, 157, 159, 114, 209, + 137, 33, 92, 217, 223, 126, 205, 225, 62, 143, 209, 209, 74, 140, + 52, 84, 158, 172, 34, 239, 93, 64, 125, 245, 91, 72, 120, 38, + 72, 19, 211, 50, 52, 29, 26, 179, 19, 162, 122, 214, 50, 48, + 9, 0, 115, 181, 122, 76, 126, 188, 252, 94, 220, 153, 183, 189, + 208, 43, 45, 154, 70, 120, 83, 222, 132, 111, 170, 17, 191, 48, + 20, 121, 90, 158, 60, 89, 46, 242, 57, 212, 245, 54, 202, 191, + 160, 131, 102, 29, 18, 40, 159, 77, 34, 187, 70, 200, 83, 233, + 91, 173, 76, 171, 110, 187, 7, 148, 98, 95, 167, 252, 227, 2, + 48, 118, 73, 225, 83, 113, 194, 250, 239, 234, 137, 124, 71, 2, + 253, 23, 16, 17, 159, 221, 182, 199, 9, 93, 129, 138, 246, 106, + 42, 89, 122, 151, 142, 111, 61, 238, 247, 172, 101, 208, 64, 126, + 248, 245, 31, 38, 237, 33, 143, 247, 19, 137, 133, 140, 201, 116, + 23, 67, 115, 127, 36, 33, 41, 164, 226, 228, 201, 79, 168, 95, + 242, 42, 151, 10, 28, 68, 74, 143, 1, 221, 228, 41, 70, 111, + 81, 155, 87, 200, 120, 244, 191, 182, 151, 9, 251, 206, 111, 74, + 178, 244, 170, 209, 35, 147, 11, 40, 75, 241, 250, 177, 133, 248, + 96, 103, 202, 10, 148, 35, 5, 155, 214, 6, 253, 250, 62, 111, + 224, 241, 82, 144, 139, 77, 78, 200, 137, 156, 39, 188, 155, 248, + 64, 62, 20, 89, 47, 250, 46, 212, 98, 98, 167, 169, 245, 148, + 154, 191, 7, 185, 143, 241, 68, 233, 95, 196, 248, 134, 6, 25, + 104, 58, 94, 126, 186, 150, 102, 157, 128, 238, 165, 224, 172, 167, + 251, 41, 141, 163, 246, 88, 223, 102, 167, 8, 180, 145, 248, 250, + 112, 41, 231, 255, 27, 41, 237, 204, 110, 166, 151, 21, 19, 81, + 64, 23, 214, 21, 237, 87, 108, 192, 18, 184, 87, 39, 10, 1, + 128, 141, 251, 179, 2, 208, 102, 159, 167, 56, 230, 120, 23, 208, + 156, 245, 20, 140, 77, 45, 57, 180, 172, 247, 161, 253, 223, 224, + 132, 189, 214, 81, 160, 88, 249, 148, 4, 154, 183, 56, 0, 94, + 184, 214, 221, 149, 101, 42, 239, 204, 109, 38, 29, 163, 14, 43, + 82, 138, 179, 151, 89, 148, 192, 168, 246, 114, 46, 246, 196, 4, + 73, 150, 141, 89, 47, 189, 72, 244, 75, 239, 198, 238, 82, 210, + 229, 143, 201, 237, 130, 191, 70, 202, 17, 170, 233, 210, 41, 93, + 211, 172, 247, 137, 29, 61, 158, 91, 116, 234, 27, 179, 58, 212, + 202, 96, 56, 233, 85, 84, 41, 229, 37, 91, 85, 217, 143, 148, + 13, 58, 196, 72, 180, 55, 161, 49, 68, 201, 98, 105, 99, 157, + 47, 175, 130, 120, 196, 18, 244, 73, 156, 17, 102, 100, 4, 244, + 42, 235, 206, 181, 94, 164, 159, 194, 152, 71, 106, 143, 138, 191, + 48, 144, 233, 231, 127, 47, 148, 222, 141, 134, 28, 233, 48, 164, + 202, 200, 107, 23, 173, 222, 201, 161, 180, 83, 153, 153, 146, 107, + 58, 250, 52, 15, 190, 218, 61, 125, 132, 160, 128, 21, 241, 111, + 237, 74, 216, 90, 132, 86, 211, 248, 10, 7, 184, 163, 147, 84, + 70, 220, 198, 130, 51, 199, 85, 21, 164, 97, 58, 225, 223, 156, + 100, 153, 151, 151, 123, 73, 208, 231, 171, 2, 153, 151, 43, 176, + 99, 16, 45, 27, 242, 23, 219, 48, 222, 254, 130, 66, 106, 2, + 99, 191, 196, 126, 6, 98, 186, 50, 200, 123, 62, 255, 188, 122, + 230, 232, 25, 227, 142, 67, 139, 218, 91, 35, 59, 185, 199, 72, + 10, 226, 244, 36, 135, 4, 182, 211, 111, 0, 243, 155, 84, 95, + 187, 16, 216, 109, 128, 206, 171, 41, 118, 43, 184, 239, 91, 140, + 110, 31, 180, 110, 180, 250, 186, 99, 225, 121, 231, 47, 152, 148, + 5, 213, 32, 82, 21, 192, 117, 253, 243, 211, 68, 254, 115, 161, + 236, 89, 42, 18, 23, 214, 172, 237, 85, 124, 154, 150, 171, 13, + 237, 185, 99, 101, 153, 102, 239, 88, 16, 40, 183, 126, 140, 210, + 79, 22, 16, 212, 219, 148, 47, 180, 230, 190, 73, 74, 187, 86, + 194, 97, 105, 201, 244, 153, 91, 98, 13, 217, 89, 242, 145, 182, + 166, 227, 28, 24, 175, 131, 28, 247, 253, 3, 183, 85, 24, 18, + 78, 17, 171, 250, 242, 145, 235, 50, 163, 176, 90, 145, 111, 80, + 7, 119, 169, 175, 251, 45, 90, 225, 50, 109, 143, 137, 185, 55, + 78, 17, 9, 42, 33, 211, 149, 81, 252, 31, 250, 108, 28, 178, + 25, 189, 245, 11, 245, 218, 5, 163, 122, 241, 94, 101, 88, 191, + 4, 21, 151, 168, 165, 119, 48, 70, 139, 186, 245, 73, 189, 121, + 124, 56, 182, 18, 232, 14, 158, 79, 79, 0, 220, 227, 55, 167, + 44, 79, 205, 176, 27, 175, 244, 238, 220, 69, 214, 2, 185, 255, + 240, 189, 104, 148, 54, 59, 33, 20, 41, 78, 102, 89, 160, 208, + 114, 65, 49, 53, 180, 240, 216, 232, 243, 225, 140, 15, 34, 42, + 149, 15, 105, 125, 122, 164, 58, 226, 245, 231, 30, 30, 104, 72, + 191, 21, 15, 8, 190, 20, 183, 116, 122, 140, 47, 213, 53, 186, + 11, 192, 207, 32, 233, 206, 154, 174, 121, 65, 151, 247, 80, 76, + 143, 27, 146, 243, 160, 92, 223, 254, 75, 16, 222, 32, 164, 48, + 182, 150, 98, 142, 65, 194, 95, 127, 107, 143, 3, 170, 19, 17, + 210, 33, 142, 170, 113, 41, 223, 252, 224, 225, 201, 41, 141, 203, + 234, 153, 161, 37, 13, 136, 55, 23, 169, 165, 172, 10, 90, 207, + 194, 74, 63, 231, 95, 68, 146, 143, 56, 178, 180, 161, 68, 255, + 86, 208, 150, 127, 131, 225, 62, 187, 171, 167, 121, 108, 167, 134, + 128, 151, 62, 8, 25, 38, 19, 95, 150, 11, 186, 76, 4, 3, + 243, 253, 156, 155, 76, 5, 125, 120, 95, 201, 214, 185, 16, 255, + 183, 104, 44, 217, 112, 164, 217, 224, 180, 162, 36, 161, 57, 36, + 79, 122, 105, 189, 92, 251, 158, 238, 174, 190, 140, 175, 230, 207, + 182, 241, 76, 236, 20, 100, 144, 215, 199, 191, 204, 11, 69, 16, + 134, 151, 28, 9, 16, 88, 39, 156, 34, 244, 196, 2, 35, 21, + 180, 123, 128, 106, 141, 205, 219, 56, 211, 220, 84, 9, 2, 200, + 127, 96, 253, 205, 92, 38, 13, 67, 107, 217, 205, 25, 120, 220, + 244, 40, 195, 254, 118, 211, 87, 173, 88, 120, 249, 52, 216, 207, + 62, 231, 71, 151, 83, 113, 9, 56, 101, 187, 162, 242, 85, 244, + 22, 188, 180, 230, 137, 73, 228, 156, 26, 210, 54, 22, 41, 121, + 113, 15, 118, 133, 51, 30, 68, 171, 72, 162, 192, 189, 153, 238, + 154, 176, 251, 140, 2, 40, 215, 26, 58, 125, 128, 94, 94, 163, + 217, 19, 190, 191, 60, 246, 15, 71, 87, 43, 224, 131, 185, 197, + 210, 247, 149, 195, 111, 205, 19, 183, 48, 157, 25, 1, 141, 13, + 202, 73, 202, 174, 136, 9, 186, 109, 60, 251, 181, 118, 215, 172, + 132, 32, 242, 252, 90, 243, 248, 69, 226, 149, 4, 241, 123, 103, + 138, 230, 235, 19, 197, 225, 122, 238, 164, 9, 9, 26, 138, 2, + 223, 149, 84, 19, 110, 26, 137, 147, 77, 197, 202, 168, 210, 214, + 232, 159, 233, 214, 46, 215, 203, 232, 222, 43, 47, 170, 88, 186, + 138, 46, 43, 139, 82, 139, 41, 3, 57, 1, 158, 97, 246, 169, + 103, 33, 28, 132, 65, 52, 51, 31, 87, 132, 11, 50, 178, 243, + 12, 183, 15, 11, 72, 38, 216, 74, 20, 158, 89, 191, 192, 202, + 26, 253, 103, 37, 212, 29, 2, 129, 171, 127, 236, 114, 195, 144, + 127, 203, 144, 124, 121, 49, 48, 252, 72, 226, 178, 174, 67, 170, + 150, 253, 156, 96, 54, 164, 83, 102, 211, 124, 210, 32, 253, 161, + 184, 217, 174, 159, 89, 108, 37, 145, 30, 226, 202, 181, 5, 37, + 54, 50, 99, 178, 135, 78, 211, 104, 84, 78, 167, 49, 137, 117, + 11, 229, 189, 101, 67, 190, 54, 115, 233, 106, 163, 127, 243, 183, + 183, 84, 171, 112, 252, 5, 220, 195, 138, 186, 33, 171, 163, 16, + 246, 253, 162, 66, 16, 93, 244, 8, 160, 87, 128, 131, 101, 150, + 127, 194, 207, 72, 219, 208, 240, 202, 44, 118, 166, 217, 198, 217, + 239, 187, 50, 0, 45, 131, 8, 71, 43, 105, 159, 232, 255, 210, + 185, 181, 145, 193, 135, 243, 164, 185, 72, 68, 137, 33, 95, 72, + 201, 110, 111, 169, 91, 84, 165, 76, 165, 131, 166, 34, 230, 114, + 193, 131, 217, 78, 240, 86, 151, 31, 4, 214, 176, 208, 229, 153, + 68, 133, 38, 183, 186, 247, 228, 34, 154, 104, 249, 209, 90, 109, + 77, 230, 92, 61, 233, 215, 26, 237, 19, 162, 97, 141, 206, 134, + 12, 18, 224, 147, 172, 243, 28, 183, 125, 69, 55, 111, 11, 248, + 225, 19, 98, 207, 29, 248, 36, 63, 198, 59, 145, 134, 54, 103, + 58, 3, 28, 78, 176, 108, 210, 129, 183, 33, 114, 76, 14, 92, + 107, 134, 238, 218, 173, 236, 248, 6, 12, 74, 172, 51, 202, 162, + 243, 171, 115, 105, 212, 74, 37, 8, 72, 180, 249, 250, 55, 88, + 181, 215, 223, 62, 4, 1, 49, 81, 198, 44, 35, 174, 243, 101, + 68, 205, 54, 168, 11, 171, 223, 157, 153, 171, 68, 104, 209, 255, + 192, 222, 241, 111, 160, 147, 186, 155, 223, 191, 227, 183, 27, 101, + 142, 55, 113, 139, 63, 189, 118, 136, 84, 174, 188, 89, 194, 214, + 118, 116, 161, 243, 16, 155, 120, 73, 237, 49, 201, 214, 234, 2, + 87, 36, 199, 174, 201, 86, 231, 213, 30, 161, 225, 160, 49, 218, + 176, 160, 219, 203, 226, 95, 103, 94, 234, 248, 79, 51, 85, 107, + 65, 94, 0, 59, 98, 105, 1, 247, 244, 0, 22, 149, 49, 242, + 142, 39, 11, 59, 71, 55, 51, 33, 255, 77, 199, 129, 58, 249, + 82, 2, 85, 173, 225, 242, 18, 13, 142, 107, 183, 17, 126, 92, + 14, 187, 83, 192, 49, 101, 207, 161, 166, 128, 90, 47, 215, 167, + 119, 7, 212, 199, 74, 63, 196, 39, 123, 10, 116, 51, 245, 87, + 213, 230, 40, 94, 9, 193, 45, 120, 42, 235, 212, 162, 192, 253, + 36, 109, 218, 2, 34, 211, 16, 123, 155, 73, 246, 87, 114, 152, + 143, 166, 116, 53, 190, 180, 143, 115, 112, 236, 219, 253, 112, 21, + 254, 144, 155, 130, 87, 84, 67, 75, 42, 27, 85, 54, 252, 189, + 176, 103, 171, 126, 246, 42, 169, 157, 31, 161, 209, 5, 8, 28, + 242, 110, 70, 48, 219, 64, 249, 174, 63, 77, 36, 133, 152, 144, + 173, 55, 70, 24, 11, 146, 233, 237, 107, 195, 1, 184, 49, 188, + 71, 156, 200, 23, 172, 156, 24, 71, 240, 202, 165, 235, 178, 68, + 196, 254, 165, 141, 72, 139, 93, 64, 203, 23, 100, 83, 105, 158, + 208, 232, 47, 254, 252, 66, 155, 157, 140, 2, 238, 96, 219, 112, + 95, 199, 107, 143, 143, 175, 80, 34, 65, 58, 196, 154, 30, 138, + 71, 248, 144, 119, 71, 178, 227, 139, 195, 154, 212, 199, 123, 190, + 182, 128, 232, 134, 96, 242, 95, 228, 230, 74, 241, 223, 172, 226, + 103, 164, 234, 116, 34, 34, 237, 8, 214, 157, 233, 241, 238, 251, + 52, 92, 79, 37, 101, 47, 9, 165, 14, 46, 82, 38, 145, 182, + 31, 206, 131, 63, 22, 238, 177, 214, 60, 25, 170, 250, 65, 54, + 75, 102, 21, 107, 57, 57, 23, 62, 41, 159, 57, 84, 128, 219, + 34, 195, 48, 41, 45, 134, 203, 222, 55, 206, 108, 181, 251, 59, + 96, 142, 188, 225, 79, 241, 165, 141, 180, 113, 9, 83, 175, 73, + 19, 105, 176, 107, 158, 165, 135, 144, 19, 60, 6, 124, 249, 60, + 96, 127, 234, 66, 141, 237, 161, 42, 141, 225, 74, 248, 89, 24, + 166, 66, 99, 207, 236, 234, 35, 182, 102, 94, 236, 232, 32, 196, + 214, 76, 227, 236, 58, 51, 228, 177, 219, 251, 202, 143, 104, 21, + 15, 43, 135, 49, 248, 23, 51, 128, 47, 174, 65, 29, 67, 242, + 161, 29, 196, 103, 193, 124, 63, 116, 102, 230, 133, 230, 144, 5, + 162, 92, 222, 46, 226, 234, 42, 87, 24, 157, 11, 226, 105, 71, + 30, 182, 118, 192, 182, 246, 136, 212, 197, 229, 68, 90, 144, 149, + 63, 234, 166, 231, 95, 215, 100, 118, 81, 12, 175, 147, 14, 168, + 37, 107, 121, 109, 245, 110, 73, 126, 130, 77, 22, 56, 59, 191, + 74, 95, 122, 206, 59, 250, 34, 41, 97, 119, 87, 160, 212, 34, + 128, 254, 225, 57, 218, 162, 170, 250, 213, 51, 253, 249, 178, 149, + 97, 87, 58, 168, 87, 112, 43, 181, 237, 209, 75, 244, 41, 226, + 137, 76, 102, 239, 240, 242, 3, 200, 188, 33, 45, 224, 47, 242, + 118, 174, 4, 238, 192, 167, 153, 159, 107, 10, 94, 55, 103, 128, + 60, 40, 20, 143, 45, 200, 164, 168, 30, 96, 139, 148, 54, 255, + 10, 3, 169, 251, 48, 31, 223, 43, 108, 217, 200, 139, 222, 11, + 111, 87, 203, 17, 156, 64, 106, 197, 37, 141, 242, 214, 143, 169, + 17, 202, 215, 178, 241, 56, 8, 223, 143, 7, 232, 15, 0, 191, + 141, 141, 181, 191, 164, 243, 198, 251, 83, 186, 182, 212, 225, 86, + 183, 64, 24, 203, 39, 64, 86, 19, 175, 106, 191, 237, 146, 18, + 160, 180, 74, 243, 113, 119, 246, 126, 248, 24, 129, 229, 54, 46, + 96, 64, 233, 100, 251, 157, 197, 66, 206, 167, 31, 100, 158, 179, + 194, 80, 191, 97, 153, 249, 242, 89, 150, 3, 46, 225, 127, 182, + 82, 210, 155, 181, 63, 30, 193, 160, 216, 125, 80, 126, 230, 239, + 49, 124, 57, 66, 177, 220, 221, 224, 134, 173, 206, 129, 3, 12, + 213, 167, 164, 158, 235, 91, 41, 29, 60, 15, 89, 18, 68, 91, + 22, 154, 134, 73, 203, 240, 255, 95, 132, 62, 99, 91, 121, 43, + 210, 254, 113, 97, 189, 14, 10, 82, 213, 31, 45, 196, 37, 155, + 197, 60, 142, 33, 4, 48, 16, 104, 195, 248, 90, 112, 83, 200, + 124, 160, 15, 186, 216, 79, 167, 107, 191, 66, 250, 222, 26, 208, + 141, 213, 124, 206, 216, 70, 232, 115, 91, 248, 13, 120, 197, 99, + 16, 236, 227, 99, 143, 173, 210, 235, 6, 0, 25, 238, 208, 92, + 151, 91, 181, 141, 13, 47, 79, 246, 37, 89, 97, 47, 129, 3, + 182, 68, 152, 36, 226, 233, 156, 134, 155, 141, 108, 135, 3, 251, + 214, 221, 242, 37, 194, 24, 29, 136, 40, 127, 24, 51, 212, 153, + 73, 246, 179, 181, 27, 156, 200, 86, 21, 184, 229, 34, 70, 160, + 27, 71, 175, 121, 125, 213, 119, 21, 153, 137, 3, 142, 155, 37, + 5, 126, 172, 191, 207, 68, 117, 160, 188, 204, 251, 63, 72, 37, + 97, 58, 105, 246, 219, 112, 105, 229, 7, 252, 95, 85, 39, 139, + 17, 192, 246, 75, 0, 126, 158, 175, 175, 205, 60, 130, 108, 191, + 178, 55, 119, 114, 209, 72, 60, 218, 212, 94, 65, 249, 86, 108, + 114, 237, 42, 52, 240, 255, 249, 26, 38, 53, 50, 143, 206, 188, + 6, 217, 225, 31, 245, 140, 84, 143, 199, 69, 26, 151, 239, 120, + 179, 244, 57, 57, 150, 128, 106, 29, 69, 15, 114, 163, 10, 68, + 198, 171, 42, 135, 203, 68, 85, 190, 129, 165, 193, 62, 31, 141, + 180, 236, 30, 234, 14, 125, 130, 193, 57, 30, 67, 109, 0, 223, + 66, 118, 140, 93, 195, 26, 139, 189, 44, 14, 169, 239, 23, 156, + 253, 81, 194, 166, 88, 11, 173, 86, 135, 42, 218, 166, 179, 43, + 188, 115, 196, 201, 202, 118, 143, 58, 31, 142, 65, 29, 64, 108, + 34, 237, 226, 119, 101, 48, 97, 234, 245, 45, 184, 192, 59, 28, + 251, 82, 120, 103, 148, 92, 133, 3, 166, 188, 238, 113, 220, 139, + 230, 151, 110, 222, 126, 168, 160, 179, 255, 182, 247, 13, 217, 98, + 195, 194, 234, 167, 79, 205, 166, 72, 229, 167, 184, 127, 144, 205, + 89, 141, 144, 219, 12, 254, 207, 114, 231, 101, 206, 22, 125, 178, + 159, 95, 16, 83, 230, 158, 27, 153, 249, 20, 87, 245, 49, 61, + 219, 63, 55, 19, 99, 190, 174, 87, 60, 170, 159, 228, 87, 62, + 11, 86, 33, 74, 120, 216, 224, 219, 120, 80, 33, 49, 41, 218, + 133, 101, 56, 39, 244, 255, 241, 116, 32, 75, 165, 82, 158, 206, + 179, 117, 142, 157, 253, 233, 61, 250, 66, 91, 216, 79, 48, 210, + 46, 218, 165, 241, 163, 180, 205, 184, 138, 133, 201, 109, 134, 109, + 114, 251, 167, 73, 228, 142, 176, 11, 90, 221, 93, 91, 44, 61, + 135, 176, 229, 79, 175, 121, 131, 108, 248, 226, 68, 175, 61, 235, + 16, 254, 47, 167, 143, 10, 53, 225, 157, 131, 171, 178, 221, 62, + 247, 228, 10, 35, 119, 148, 174, 133, 46, 230, 212, 57, 237, 204, + 69, 105, 67, 100, 168, 206, 113, 87, 79, 45, 46, 141, 132, 48, + 64, 111, 139, 117, 251, 237, 9, 223, 239, 82, 25, 76, 44, 83, + 230, 228, 24, 88, 208, 28, 26, 44, 128, 108, 191, 8, 136, 194, + 5, 81, 101, 255, 122, 140, 27, 204, 95, 19, 239, 84, 50, 232, + 105, 235, 35, 169, 44, 121, 146, 14, 229, 250, 80, 134, 221, 116, + 222, 119, 99, 210, 183, 131, 24, 51, 237, 143, 88, 68, 149, 215, + 155, 39, 156, 186, 203, 187, 80, 184, 89, 73, 187, 207, 166, 69, + 46, 228, 73, 209, 212, 35, 238, 190, 215, 255, 37, 74, 156, 173, + 15, 103, 94, 227, 150, 10, 18, 179, 121, 103, 46, 57, 249, 168, + 152, 121, 215, 228, 234, 45, 4, 112, 160, 32, 246, 2, 17, 88, + 131, 82, 169, 105, 167, 46, 223, 38, 11, 73, 109, 232, 173, 18, + 74, 203, 110, 228, 104, 96, 217, 129, 123, 178, 52, 106, 103, 42, + 24, 37, 154, 208, 44, 219, 81, 139, 73, 197, 250, 70, 164, 2, + 201, 186, 228, 208, 63, 255, 208, 66, 250, 230, 169, 73, 14, 121, + 231, 122, 202, 153, 74, 7, 138, 189, 159, 66, 197, 182, 25, 103, + 68, 1, 100, 123, 135, 184, 13, 244, 26, 227, 183, 186, 26, 155, + 212, 177, 41, 94, 15, 160, 78, 182, 156, 128, 163, 90, 29, 148, + 136, 67, 217, 154, 116, 137, 111, 187, 5, 197, 48, 225, 55, 138, + 193, 227, 49, 52, 130, 182, 153, 23, 140, 170, 142, 26, 40, 57, + 81, 45, 56, 49, 41, 161, 107, 12, 237, 55, 160, 53, 107, 243, + 214, 197, 251, 177, 227, 47, 201, 94, 92, 4, 151, 188, 49, 177, + 89, 42, 89, 71, 68, 99, 204, 255, 27, 240, 56, 159, 78, 95, + 228, 147, 43, 133, 83, 39, 234, 48, 3, 157, 174, 144, 122, 110, + 110, 14, 234, 36, 33, 79, 75, 60, 50, 165, 218, 248, 192, 249, + 99, 81, 121, 65, 130, 172, 246, 217, 119, 247, 58, 182, 119, 71, + 87, 81, 184, 30, 131, 170, 21, 86, 76, 125, 231, 103, 135, 190, + 219, 212, 190, 232, 216, 45, 243, 190, 121, 46, 19, 44, 178, 77, + 112, 132, 188, 167, 22, 175, 6, 188, 170, 99, 45, 190, 11, 89, + 245, 207, 101, 83, 219, 49, 170, 147, 168, 46, 63, 191, 148, 132, + 38, 147, 165, 62, 115, 114, 238, 205, 209, 255, 64, 107, 61, 75, + 63, 108, 249, 235, 231, 130, 27, 77, 62, 162, 150, 161, 44, 246, + 70, 230, 138, 11, 95, 111, 222, 193, 248, 75, 170, 105, 143, 89, + 38, 77, 211, 216, 145, 122, 252, 49, 206, 198, 170, 8, 65, 241, + 23, 214, 180, 97, 104, 147, 97, 161, 244, 129, 166, 122, 106, 209, + 183, 190, 214, 252, 23, 246, 128, 6, 47, 28, 122, 249, 158, 77, + 158, 242, 231, 53, 30, 130, 24, 177, 84, 216, 255, 235, 53, 242, + 202, 154, 102, 240, 31, 107, 251, 233, 216, 132, 255, 141, 154, 190, + 126, 173, 218, 21, 120, 196, 172, 175, 81, 178, 67, 85, 48, 74, + 35, 4, 200, 85, 138, 136, 132, 123, 13, 13, 30, 241, 69, 25, + 25, 178, 36, 237, 189, 103, 24, 105, 62, 198, 40, 81, 142, 251, + 113, 166, 85, 239, 2, 255, 39, 226, 142, 211, 151, 133, 64, 141, + 240, 79, 4, 201, 229, 142, 225, 207, 17, 167, 134, 117, 134, 81, + 47, 127, 66, 226, 107, 133, 249, 109, 139, 7, 104, 235, 11, 216, + 33, 248, 185, 149, 183, 111, 69, 127, 102, 102, 185, 65, 22, 65, + 178, 183, 175, 209, 227, 246, 118, 29, 207, 193, 6, 167, 89, 129, + 128, 199, 89, 159, 220, 134, 101, 227, 84, 3, 55, 34, 94, 165, + 221, 250, 157, 193, 34, 215, 188, 99, 93, 45, 143, 10, 107, 10, + 234, 208, 58, 180, 133, 244, 193, 192, 180, 150, 11, 47, 240, 96, + 53, 18, 233, 111, 10, 69, 147, 184, 17, 195, 173, 107, 127, 7, + 145, 252, 172, 63, 61, 1, 132, 73, 39, 77, 96, 221, 48, 108, + 18, 38, 95, 104, 190, 145, 107, 4, 234, 13, 204, 214, 109, 40, + 162, 71, 188, 41, 131, 238, 85, 57, 141, 59, 254, 17, 157, 3, + 229, 146, 194, 51, 183, 5, 149, 222, 154, 159, 74, 69, 52, 223, + 113, 98, 157, 4, 30, 70, 105, 160, 167, 12, 103, 73, 39, 48, + 20, 218, 212, 56, 42, 107, 166, 80, 77, 216, 4, 234, 238, 214, + 93, 30, 201, 254, 93, 117, 135, 141, 214, 11, 196, 115, 224, 26, + 82, 227, 200, 26, 9, 24, 209, 109, 118, 201, 104, 233, 88, 10, + 45, 248, 17, 147, 103, 93, 119, 54, 182, 20, 254, 238, 213, 224, + 14, 225, 13, 157, 204, 172, 53, 94, 133, 218, 183, 164, 191, 77, + 19, 228, 7, 32, 239, 37, 173, 208, 43, 2, 12, 124, 211, 68, + 160, 119, 65, 230, 33, 6, 191, 33, 71, 88, 160, 61, 54, 210, + 152, 237, 55, 63, 220, 46, 57, 196, 178, 150, 44, 157, 50, 88, + 123, 158, 86, 17, 1, 176, 225, 96, 247, 113, 157, 150, 242, 85, + 37, 88, 135, 188, 232, 115, 1, 124, 27, 105, 158, 234, 2, 228, + 82, 28, 223, 57, 104, 203, 86, 153, 122, 18, 194, 38, 65, 23, + 93, 117, 133, 138, 250, 83, 138, 163, 9, 169, 82, 212, 71, 115, + 128, 80, 158, 202, 7, 70, 17, 127, 122, 70, 250, 49, 186, 116, + 4, 238, 252, 101, 127, 8, 25, 251, 71, 181, 104, 201, 198, 184, + 25, 122, 93, 155, 103, 160, 37, 6, 174, 54, 39, 138, 137, 176, + 144, 72, 210, 36, 255, 71, 63, 212, 246, 36, 30, 242, 239, 90, + 32, 131, 172, 149, 162, 96, 161, 42, 247, 131, 104, 173, 13, 184, + 167, 221, 236, 63, 39, 82, 100, 122, 226, 5, 197, 241, 202, 44, + 46, 53, 239, 158, 146, 238, 145, 188, 18, 12, 1, 123, 39, 74, + 196, 218, 213, 57, 255, 18, 102, 81, 110, 48, 248, 54, 150, 84, + 128, 19, 56, 46, 105, 147, 5, 69, 219, 124, 118, 58, 25, 29, + 178, 124, 212, 78, 1, 143, 144, 138, 154, 12, 109, 147, 216, 235, + 38, 19, 42, 240, 109, 163, 80, 232, 89, 20, 109, 4, 29, 33, + 145, 112, 198, 146, 94, 56, 203, 230, 204, 168, 151, 150, 138, 9, + 157, 183, 151, 184, 60, 185, 247, 255, 88, 245, 2, 80, 190, 55, + 115, 228, 135, 142, 16, 16, 114, 248, 112, 128, 47, 46, 225, 179, + 207, 20, 12, 51, 5, 116, 227, 102, 152, 40, 251, 186, 189, 220, + 6, 57, 45, 105, 154, 154, 164, 114, 104, 51, 255, 73, 143, 76, + 52, 248, 159, 160, 148, 115, 113, 216, 152, 66, 238, 184, 72, 71, + 203, 194, 78, 110, 83, 32, 9, 85, 106, 171, 158, 18, 187, 125, + 172, 34, 45, 163, 78, 51, 172, 202, 206, 4, 91, 23, 10, 229, + 208, 193, 253, 47, 217, 173, 238, 202, 33, 187, 45, 123, 144, 96, + 199, 113, 60, 148, 243, 136, 10, 41, 228, 30, 237, 154, 85, 41, + 37, 46, 86, 66, 187, 194, 127, 0, 193, 146, 82, 132, 181, 166, + 109, 150, 230, 71, 200, 51, 194, 196, 219, 71, 70, 224, 140, 106, + 248, 0, 103, 16, 193, 183, 86, 227, 50, 221, 188, 11, 27, 63, + 220, 167, 200, 116, 87, 80, 101, 235, 161, 123, 244, 165, 89, 142, + 94, 32, 217, 175, 7, 190, 110, 79, 8, 89, 175, 215, 78, 114, + 251, 71, 71, 188, 206, 164, 26, 231, 118, 41, 29, 5, 255, 54, + 177, 50, 51, 219, 189, 46, 143, 17, 60, 90, 202, 229, 95, 237, + 45, 90, 212, 27, 0, 70, 54, 232, 106, 44, 213, 13, 217, 141, + 15, 128, 190, 46, 10, 3, 33, 164, 62, 55, 240, 139, 123, 126, + 65, 53, 74, 202, 209, 245, 114, 69, 126, 248, 192, 60, 250, 20, + 47, 96, 109, 251, 179, 28, 198, 75, 117, 96, 129, 51, 121, 47, + 6, 250, 121, 109, 4, 123, 54, 178, 221, 211, 231, 122, 164, 121, + 6, 122, 35, 35, 151, 104, 148, 11, 72, 148, 245, 182, 170, 152, + 230, 152, 152, 123, 119, 179, 225, 1, 58, 64, 197, 75, 181, 154, + 192, 155, 0, 148, 200, 46, 200, 205, 198, 207, 223, 249, 167, 222, + 95, 82, 35, 174, 133, 188, 213, 71, 21, 72, 141, 140, 155, 9, + 118, 39, 127, 185, 157, 108, 119, 223, 243, 75, 26, 56, 24, 197, + 254, 235, 59, 88, 118, 249, 250, 123, 106, 200, 190, 206, 104, 181, + 89, 62, 234, 94, 28, 215, 26, 247, 42, 42, 35, 148, 8, 72, + 109, 25, 195, 106, 187, 65, 251, 112, 235, 167, 138, 69, 108, 236, + 253, 99, 179, 71, 253, 50, 189, 38, 66, 166, 5, 125, 151, 255, + 164, 86, 6, 125, 57, 39, 159, 119, 3, 6, 146, 25, 178, 25, + 105, 28, 233, 24, 84, 137, 75, 185, 53, 124, 112, 155, 251, 13, + 82, 151, 125, 150, 106, 149, 122, 138, 146, 131, 72, 211, 74, 224, + 58, 135, 29, 57, 203, 231, 188, 21, 158, 106, 124, 107, 218, 232, + 120, 84, 202, 165, 207, 83, 125, 8, 132, 208, 201, 103, 243, 160, + 209, 170, 131, 18, 90, 196, 83, 151, 68, 219, 10, 148, 224, 114, + 115, 192, 81, 120, 188, 233, 130, 198, 234, 78, 185, 174, 170, 149, + 16, 125, 226, 91, 26, 36, 14, 213, 73, 86, 42, 106, 104, 8, + 148, 139, 5, 164, 14, 136, 37, 127, 33, 161, 91, 81, 90, 244, + 198, 193, 160, 70, 87, 58, 60, 112, 176, 207, 205, 62, 192, 99, + 239, 217, 167, 217, 194, 47, 220, 2, 137, 69, 29, 217, 244, 110, + 94, 40, 184, 200, 191, 144, 135, 159, 85, 244, 25, 43, 88, 151, + 22, 200, 50, 227, 15, 59, 25, 245, 152, 251, 188, 95, 213, 16, + 85, 113, 215, 84, 7, 163, 16, 117, 180, 65, 102, 204, 122, 94, + 190, 111, 54, 139, 94, 159, 71, 21, 234, 18, 44, 45, 159, 56, + 124, 137, 33, 114, 22, 115, 150, 225, 16, 196, 20, 34, 59, 15, + 212, 148, 82, 227, 31, 89, 109, 41, 43, 228, 164, 23, 227, 82, + 230, 194, 187, 214, 221, 20, 90, 221, 245, 164, 124, 11, 189, 43, + 63, 128, 220, 25, 96, 195, 11, 29, 120, 245, 60, 30, 222, 6, + 185, 8, 52, 41, 133, 125, 246, 67, 164, 43, 133, 253, 160, 124, + 159, 15, 204, 128, 170, 151, 132, 116, 166, 55, 188, 104, 10, 252, + 181, 234, 169, 48, 167, 18, 248, 170, 170, 34, 184, 67, 253, 179, + 182, 189, 12, 215, 112, 128, 77, 44, 138, 187, 175, 82, 138, 196, + 26, 187, 82, 239, 242, 253, 236, 160, 21, 174, 233, 241, 63, 123, + 23, 141, 171, 231, 147, 55, 244, 124, 121, 98, 154, 75, 191, 157, + 207, 6, 70, 80, 23, 156, 247, 236, 147, 110, 155, 170, 153, 253, + 230, 236, 136, 180, 28, 23, 120, 213, 168, 159, 251, 45, 44, 227, + 109, 27, 12, 130, 178, 225, 49, 251, 206, 24, 207, 1, 89, 127, + 52, 3, 80, 227, 56, 109, 36, 251, 113, 136, 41, 212, 184, 101, + 23, 167, 83, 125, 79, 251, 226, 27, 81, 201, 31, 92, 205, 152, + 253, 173, 34, 250, 163, 145, 217, 70, 121, 171, 249, 144, 124, 36, + 28, 211, 173, 73, 246, 104, 45, 12, 21, 153, 20, 130, 208, 28, + 59, 129, 34, 219, 103, 213, 49, 232, 193, 58, 207, 126, 248, 136, + 51, 76, 255, 127, 133, 232, 106, 35, 142, 239, 111, 9, 34, 49, + 129, 249, 128, 57, 100, 86, 67, 60, 46, 96, 9, 200, 168, 24, + 5, 112, 126, 90, 142, 175, 162, 78, 227, 21, 204, 249, 189, 141, + 29, 88, 94, 28, 231, 205, 206, 231, 83, 164, 57, 51, 161, 85, + 182, 186, 220, 95, 59, 66, 72, 241, 1, 231, 159, 123, 107, 36, + 43, 225, 9, 101, 195, 146, 75, 87, 98, 8, 219, 223, 68, 103, + 224, 101, 199, 180, 103, 209, 253, 51, 74, 41, 129, 214, 127, 197, + 195, 172, 41, 237, 62, 48, 231, 192, 233, 41, 250, 98, 200, 115, + 117, 244, 172, 233, 234, 239, 66, 249, 63, 61, 119, 246, 21, 98, + 216, 232, 181, 252, 224, 157, 195, 99, 174, 131, 62, 76, 24, 241, + 55, 251, 131, 164, 162, 217, 46, 27, 142, 41, 42, 11, 169, 119, + 70, 185, 117, 27, 10, 132, 175, 182, 252, 187, 78, 190, 178, 130, + 128, 141, 110, 136, 13, 56, 234, 132, 18, 196, 18, 126, 112, 209, + 12, 58, 4, 238, 68, 216, 117, 179, 246, 140, 72, 183, 140, 118, + 192, 253, 168, 244, 164, 82, 39, 123, 247, 90, 115, 172, 211, 145, + 167, 114, 141, 81, 177, 138, 210, 196, 55, 111, 242, 196, 38, 78, + 9, 250, 120, 182, 212, 105, 52, 198, 95, 63, 232, 251, 120, 77, + 177, 118, 164, 245, 192, 39, 139, 57, 128, 71, 165, 26, 218, 24, + 119, 33, 30, 115, 60, 95, 55, 249, 201, 219, 36, 38, 47, 139, + 253, 79, 7, 111, 130, 236, 37, 29, 89, 94, 247, 39, 21, 1, + 202, 46, 6, 23, 93, 123, 148, 234, 177, 109, 135, 157, 21, 193, + 128, 63, 86, 99, 57, 130, 108, 186, 64, 72, 8, 132, 252, 249, + 3, 185, 197, 164, 22, 33, 147, 231, 192, 196, 103, 39, 122, 118, + 206, 58, 96, 54, 83, 72, 134, 54, 201, 229, 27, 235, 214, 3, + 93, 7, 195, 144, 209, 61, 188, 119, 161, 44, 79, 205, 161, 246, + 179, 90, 9, 58, 231, 78, 52, 250, 246, 152, 153, 6, 193, 188, + 118, 177, 32, 63, 53, 161, 98, 9, 237, 20, 135, 131, 59, 182, + 65, 167, 209, 201, 80, 187, 188, 93, 21, 146, 222, 133, 91, 159, + 115, 35, 165, 186, 146, 222, 72, 44, 143, 181, 83, 123, 79, 49, + 130, 18, 209, 211, 250, 213, 83, 179, 110, 147, 56, 199, 193, 167, + 143, 1, 151, 228, 170, 165, 220, 68, 7, 4, 156, 119, 238, 14, + 245, 55, 105, 198, 198, 109, 56, 233, 103, 93, 203, 70, 3, 0, + 195, 13, 107, 164, 214, 245, 226, 56, 69, 195, 174, 181, 133, 21, + 128, 239, 223, 113, 91, 120, 135, 90, 223, 48, 211, 221, 128, 197, + 120, 138, 19, 63, 49, 37, 207, 31, 27, 162, 175, 35, 106, 169, + 189, 202, 119, 250, 185, 232, 75, 2, 9, 133, 81, 233, 245, 193, + 31, 149, 214, 210, 118, 58, 155, 134, 117, 42, 242, 74, 48, 150, + 147, 171, 77, 88, 182, 248, 247, 165, 239, 169, 99, 205, 232, 244, + 170, 125, 80, 105, 249, 226, 229, 151, 66, 229, 50, 96, 116, 203, + 130, 16, 201, 15, 45, 121, 181, 167, 218, 147, 49, 42, 140, 142, + 219, 99, 101, 202, 59, 103, 26, 59, 61, 16, 14, 199, 244, 88, + 200, 207, 0, 42, 38, 61, 188, 87, 243, 174, 105, 156, 61, 95, + 18, 51, 84, 75, 146, 88, 109, 84, 210, 102, 49, 41, 193, 205, + 41, 33, 70, 151, 167, 174, 69, 48, 63, 242, 231, 205, 123, 59, + 143, 177, 77, 7, 222, 201, 188, 144, 238, 254, 212, 46, 86, 179, + 133, 43, 159, 124, 182, 155, 217, 179, 39, 57, 36, 40, 200, 213, + 82, 174, 138, 178, 89, 235, 113, 158, 31, 79, 222, 198, 208, 54, + 92, 144, 201, 130, 188, 44, 18, 155, 243, 164, 132, 140, 2, 37, + 110, 48, 60, 173, 203, 158, 125, 171, 25, 183, 162, 181, 223, 231, + 6, 241, 71, 111, 57, 67, 106, 82, 71, 150, 38, 44, 44, 150, + 125, 127, 49, 208, 146, 47, 118, 76, 212, 29, 116, 188, 135, 50, + 118, 114, 141, 186, 130, 187, 170, 106, 37, 113, 77, 118, 118, 123, + 59, 46, 18, 62, 125, 111, 214, 178, 42, 129, 84, 243, 52, 118, + 213, 153, 55, 59, 87, 80, 248, 8, 12, 158, 115, 37, 90, 110, + 250, 16, 150, 15, 104, 254, 41, 133, 63, 245, 22, 248, 28, 116, + 198, 222, 199, 24, 154, 109, 253, 181, 175, 215, 36, 115, 132, 127, + 53, 216, 53, 90, 117, 244, 71, 10, 163, 167, 142, 194, 192, 114, + 25, 175, 67, 12, 159, 118, 31, 163, 70, 121, 193, 166, 84, 35, + 207, 17, 235, 146, 179, 14, 38, 165, 119, 39, 180, 72, 57, 146, + 58, 195, 202, 224, 182, 3, 241, 154, 50, 188, 226, 175, 70, 80, + 213, 212, 57, 250, 198, 162, 96, 127, 87, 14, 143, 239, 34, 205, + 199, 17, 15, 70, 115, 28, 234, 141, 130, 153, 40, 91, 171, 94, + 124, 86, 142, 172, 73, 33, 28, 209, 138, 133, 215, 164, 87, 199, + 225, 100, 246, 205, 90, 172, 105, 133, 45, 102, 37, 93, 42, 40, + 176, 32, 215, 209, 155, 18, 173, 187, 130, 64, 68, 140, 141, 95, + 0, 145, 226, 10, 191, 54, 192, 69, 6, 11, 142, 213, 220, 72, + 91, 184, 52, 152, 185, 127, 48, 241, 24, 175, 79, 76, 34, 195, + 117, 15, 185, 10, 18, 11, 9, 76, 108, 93, 96, 114, 103, 33, + 230, 88, 141, 61, 47, 167, 39, 145, 30, 59, 142, 232, 240, 207, + 192, 117, 175, 124, 165, 62, 252, 201, 135, 72, 54, 166, 150, 82, + 141, 163, 153, 199, 167, 24, 162, 108, 85, 133, 73, 132, 97, 157, + 75, 51, 22, 66, 152, 219, 124, 192, 131, 230, 112, 197, 226, 71, + 189, 183, 184, 45, 48, 81, 235, 160, 221, 96, 136, 245, 65, 197, + 223, 220, 168, 59, 93, 243, 103, 19, 216, 164, 171, 179, 58, 210, + 100, 86, 1, 67, 78, 37, 205, 91, 26, 195, 151, 176, 169, 248, + 14, 165, 49, 254, 155, 59, 249, 64, 101, 230, 15, 197, 126, 219, + 117, 109, 40, 202, 236, 5, 254, 237, 253, 110, 70, 108, 6, 248, + 101, 28, 227, 91, 162, 75, 218, 98, 255, 80, 166, 84, 116, 31, + 176, 52, 232, 18, 32, 237, 215, 151, 3, 101, 78, 251, 25, 214, + 101, 11, 197, 224, 141, 202, 250, 27, 229, 230, 70, 165, 86, 236, + 121, 141, 37, 2, 124, 35, 92, 221, 160, 150, 174, 221, 0, 144, + 55, 35, 73, 112, 124, 11, 136, 166, 113, 187, 215, 203, 0, 143, + 134, 159, 217, 86, 95, 101, 85, 120, 19, 11, 173, 187, 187, 33, + 193, 200, 71, 7, 65, 69, 88, 184, 100, 149, 217, 6, 115, 236, + 195, 46, 79, 180, 213, 32, 133, 49, 224, 201, 120, 77, 154, 135, + 218, 46, 118, 9, 134, 191, 191, 59, 125, 133, 185, 210, 19, 45, + 75, 23, 164, 12, 100, 155, 194, 156, 145, 20, 26, 228, 93, 17, + 6, 242, 246, 59, 180, 8, 142, 8, 104, 236, 170, 138, 122, 187, + 207, 35, 1, 202, 90, 92, 48, 71, 255, 176, 245, 139, 133, 243, + 49, 224, 42, 164, 1, 227, 189, 122, 49, 77, 216, 243, 153, 117, + 145, 215, 112, 10, 143, 20, 238, 240, 36, 44, 145, 80, 188, 18, + 233, 156, 5, 147, 254, 19, 122, 127, 226, 168, 25, 243, 110, 183, + 25, 80, 34, 0, 160, 143, 112, 105, 192, 47, 117, 68, 230, 165, + 91, 185, 21, 67, 251, 207, 26, 38, 68, 80, 25, 48, 85, 161, + 118, 92, 39, 166, 85, 245, 84, 120, 105, 240, 70, 143, 179, 47, + 106, 5, 110, 87, 206, 35, 174, 167, 245, 115, 205, 203, 209, 141, + 93, 76, 12, 50, 120, 88, 88, 83, 143, 185, 145, 212, 27, 185, + 196, 176, 106, 218, 181, 64, 28, 159, 122, 189, 49, 223, 70, 152, + 231, 187, 226, 178, 194, 197, 240, 80, 186, 115, 208, 33, 195, 158, + 90, 213, 25, 158, 158, 51, 178, 167, 55, 133, 71, 221, 156, 57, + 71, 151, 83, 136, 6, 68, 99, 31, 145, 21, 112, 141, 230, 189, + 204, 48, 205, 205, 218, 242, 255, 155, 23, 246, 197, 39, 188, 20, + 136, 45, 104, 29, 252, 23, 255, 121, 88, 138, 13, 190, 122, 62, + 242, 44, 59, 95, 147, 47, 139, 190, 63, 20, 109, 175, 36, 13, + 70, 191, 70, 162, 160, 219, 163, 5, 60, 198, 154, 160, 126, 64, + 172, 110, 204, 139, 135, 224, 137, 238, 188, 134, 110, 104, 232, 99, + 12, 70, 174, 145, 153, 66, 190, 245, 21, 39, 242, 218, 252, 172, + 165, 102, 154, 13, 56, 199, 196, 128, 65, 119, 240, 72, 211, 23, + 33, 10, 103, 145, 83, 205, 136, 208, 27, 74, 10, 223, 179, 92, + 190, 17, 23, 68, 114, 189, 57, 208, 74, 246, 174, 202, 173, 99, + 94, 87, 133, 110, 187, 205, 110, 24, 187, 178, 224, 31, 132, 241, + 14, 139, 62, 67, 111, 91, 178, 245, 172, 204, 5, 191, 142, 164, + 233, 30, 232, 127, 209, 175, 215, 93, 11, 99, 131, 208, 238, 136, + 226, 217, 74, 73, 208, 249, 249, 199, 27, 112, 78, 91, 58, 23, + 141, 109, 158, 231, 143, 39, 226, 230, 62, 46, 27, 68, 18, 74, + 138, 18, 70, 83, 18, 1, 179, 205, 212, 5, 0, 221, 48, 20, + 65, 188, 226, 5, 166, 234, 90, 33, 246, 235, 25, 190, 72, 200, + 224, 132, 29, 116, 47, 36, 18, 164, 63, 240, 243, 192, 233, 178, + 238, 202, 160, 30, 121, 232, 141, 71, 37, 10, 80, 150, 102, 35, + 113, 184, 116, 131, 38, 128, 96, 158, 158, 184, 76, 7, 225, 4, + 221, 52, 14, 99, 50, 98, 206, 185, 193, 20, 157, 144, 58, 139, + 124, 136, 165, 50, 67, 251, 46, 177, 76, 16, 217, 176, 14, 143, + 99, 161, 128, 8, 165, 70, 54, 236, 95, 232, 196, 176, 201, 83, + 64, 103, 112, 250, 116, 185, 40, 193, 79, 136, 83, 245, 240, 171, + 11, 1, 40, 85, 249, 162, 192, 76, 239, 40, 147, 124, 24, 246, + 31, 210, 85, 13, 93, 100, 181, 128, 46, 162, 177, 132, 160, 77, + 105, 45, 112, 215, 89, 180, 59, 68, 219, 29, 99, 147, 47, 33, + 236, 111, 255, 45, 215, 52, 95, 8, 160, 155, 96, 132, 184, 149, + 122, 247, 106, 32, 58, 154, 231, 30, 134, 204, 154, 232, 129, 41, + 129, 61, 102, 50, 200, 164, 162, 238, 18, 82, 131, 56, 76, 179, + 211, 190, 247, 39, 69, 15, 59, 41, 19, 11, 26, 124, 116, 149, + 14, 157, 164, 82, 99, 15, 69, 234, 82, 41, 120, 152, 63, 139, + 113, 120, 183, 31, 171, 151, 133, 166, 197, 223, 128, 83, 216, 100, + 130, 158, 91, 142, 17, 9, 150, 238, 40, 199, 47, 225, 51, 246, + 248, 168, 31, 94, 107, 94, 84, 188, 185, 161, 36, 254, 245, 91, + 6, 166, 3, 106, 1, 129, 238, 222, 228, 187, 246, 195, 232, 17, + 94, 99, 72, 220, 151, 71, 250, 194, 235, 131, 84, 170, 22, 180, + 138, 193, 155, 89, 18, 207, 67, 43, 189, 221, 244, 55, 136, 168, + 228, 235, 124, 44, 127, 175, 254, 49, 174, 35, 114, 35, 216, 109, + 65, 79, 85, 142, 225, 119, 226, 120, 58, 131, 179, 179, 250, 5, + 202, 255, 75, 43, 57, 158, 109, 14, 59, 26, 22, 152, 138, 191, + 255, 144, 18, 137, 186, 32, 113, 234, 167, 25, 0, 16, 23, 157, + 163, 43, 99, 215, 204, 187, 213, 153, 121, 25, 128, 85, 92, 159, + 71, 149, 50, 127, 186, 86, 131, 235, 89, 1, 2, 150, 63, 163, + 190, 75, 246, 128, 104, 184, 216, 32, 17, 192, 93, 202, 25, 127, + 213, 222, 144, 92, 95, 252, 82, 209, 101, 250, 226, 165, 75, 175, + 179, 90, 242, 5, 65, 53, 175, 228, 11, 54, 66, 77, 201, 135, + 223, 248, 62, 125, 106, 147, 78, 87, 13, 2, 204, 81, 163, 36, + 171, 22, 101, 233, 181, 29, 217, 227, 242, 250, 12, 107, 57, 96, + 90, 65, 65, 204, 76, 250, 130, 186, 110, 44, 29, 111, 105, 34, + 12, 128, 114, 48, 54, 160, 105, 42, 249, 49, 37, 138, 119, 31, + 125, 87, 215, 76, 45, 79, 53, 204, 121, 231, 202, 191, 127, 64, + 136, 44, 23, 159, 110, 208, 170, 177, 222, 60, 54, 220, 197, 3, + 8, 218, 203, 74, 212, 11, 149, 120, 88, 76, 15, 75, 220, 93, + 223, 73, 171, 9, 147, 60, 233, 173, 134, 122, 11, 50, 127, 3, + 117, 244, 209, 96, 9, 146, 147, 40, 203, 254, 13, 206, 55, 20, + 140, 19, 221, 130, 112, 206, 31, 87, 66, 143, 57, 20, 47, 203, + 225, 210, 213, 174, 171, 7, 3, 193, 231, 168, 181, 123, 43, 113, + 208, 168, 63, 66, 158, 163, 105, 69, 69, 189, 233, 217, 17, 86, + 214, 112, 38, 25, 55, 73, 25, 232, 205, 56, 65, 55, 169, 254, + 134, 102, 7, 210, 177, 112, 155, 130, 226, 186, 198, 180, 178, 238, + 70, 84, 245, 49, 50, 145, 155, 46, 226, 174, 21, 123, 160, 98, + 8, 108, 26, 246, 132, 25, 87, 142, 188, 143, 254, 0, 246, 127, + 89, 142, 158, 43, 139, 243, 176, 103, 242, 84, 77, 250, 67, 66, + 155, 34, 239, 132, 0, 155, 207, 18, 83, 75, 251, 201, 212, 31, + 98, 11, 120, 213, 119, 124, 45, 158, 44, 170, 195, 37, 165, 247, + 105, 11, 77, 173, 94, 89, 203, 161, 46, 175, 167, 145, 187, 70, + 11, 171, 178, 152, 139, 63, 91, 46, 164, 230, 239, 47, 70, 183, + 242, 201, 175, 94, 150, 78, 40, 242, 56, 64, 189, 110, 19, 77, + 19, 31, 14, 219, 187, 231, 139, 210, 98, 178, 66, 86, 12, 42, + 1, 226, 180, 228, 171, 95, 112, 53, 11, 134, 241, 35, 85, 100, + 26, 61, 101, 2, 86, 158, 251, 40, 247, 80, 207, 171, 122, 246, + 145, 194, 15, 91, 25, 217, 74, 185, 195, 10, 23, 71, 188, 103, + 40, 20, 92, 180, 34, 56, 206, 140, 229, 101, 189, 34, 194, 6, + 141, 183, 176, 209, 222, 72, 79, 153, 150, 129, 67, 166, 90, 115, + 188, 88, 115, 73, 59, 69, 131, 242, 118, 192, 42, 150, 46, 83, + 92, 65, 16, 247, 158, 201, 216, 157, 75, 194, 142, 140, 27, 167, + 90, 194, 59, 118, 206, 25, 240, 16, 182, 0, 49, 73, 104, 225, + 206, 205, 56, 190, 3, 114, 15, 179, 171, 15, 177, 232, 182, 85, + 215, 183, 200, 92, 41, 186, 182, 134, 226, 196, 97, 7, 58, 54, + 244, 161, 21, 89, 82, 18, 39, 173, 210, 191, 179, 47, 236, 186, + 98, 194, 47, 46, 123, 240, 218, 232, 224, 245, 149, 36, 64, 193, + 235, 8, 234, 157, 113, 115, 123, 22, 25, 38, 156, 107, 115, 195, + 247, 54, 47, 126, 38, 68, 177, 82, 198, 54, 156, 214, 78, 34, + 150, 8, 69, 159, 4, 108, 62, 195, 149, 4, 177, 72, 112, 246, + 18, 213, 176, 132, 78, 225, 245, 96, 64, 146, 246, 82, 49, 186, + 222, 244, 218, 50, 154, 72, 54, 74, 70, 39, 216, 48, 177, 10, + 11, 153, 95, 129, 8, 57, 155, 57, 186, 125, 79, 92, 36, 27, + 0, 110, 141, 208, 64, 68, 111, 98, 158, 173, 42, 179, 191, 108, + 254, 188, 155, 136, 218, 187, 43, 201, 152, 63, 187, 43, 106, 96, + 45, 49, 57, 207, 13, 232, 64, 95, 70, 239, 26, 47, 7, 166, + 123, 69, 147, 186, 58, 229, 214, 244, 239, 14, 32, 95, 193, 40, + 27, 130, 2, 125, 245, 43, 40, 251, 212, 192, 88, 214, 118, 234, + 141, 90, 94, 16, 244, 173, 101, 170, 13, 27, 57, 52, 23, 116, + 241, 64, 85, 17, 129, 189, 244, 217, 166, 64, 238, 42, 3, 116, + 224, 180, 49, 245, 198, 215, 61, 89, 23, 69, 83, 249, 157, 184, + 129, 251, 45, 101, 236, 96, 23, 140, 125, 60, 197, 112, 152, 192, + 107, 30, 210, 12, 10, 179, 233, 27, 14, 26, 188, 121, 248, 114, + 66, 11, 166, 30, 87, 151, 125, 132, 73, 32, 207, 119, 81, 199, + 139, 49, 115, 7, 250, 167, 244, 19, 29, 70, 196, 188, 238, 48, + 134, 185, 40, 243, 7, 219, 225, 3, 96, 188, 155, 183, 34, 99, + 108, 253, 57, 254, 148, 227, 252, 48, 180, 82, 232, 15, 219, 162, + 60, 65, 15, 52, 145, 222, 34, 126, 174, 167, 147, 245, 253, 207, + 168, 52, 142, 74, 113, 208, 17, 26, 105, 135, 144, 105, 247, 222, + 231, 109, 28, 192, 132, 218, 86, 243, 98, 49, 54, 80, 29, 152, + 19, 79, 30, 2, 180, 96, 6, 55, 161, 117, 8, 74, 121, 58, + 155, 26, 241, 196, 95, 4, 137, 82, 115, 135, 217, 202, 236, 31, + 171, 95, 140, 178, 241, 147, 54, 137, 172, 210, 94, 234, 42, 172, + 5, 199, 90, 3, 104, 14, 76, 95, 111, 12, 192, 116, 11, 80, + 133, 159, 105, 131, 3, 24, 127, 226, 123, 35, 135, 131, 76, 124, + 62, 86, 236, 177, 19, 111, 163, 23, 96, 225, 140, 103, 203, 81, + 125, 224, 87, 214, 127, 6, 45, 135, 234, 181, 220, 61, 76, 139, + 56, 35, 140, 44, 10, 133, 123, 16, 237, 9, 79, 0, 197, 130, + 231, 163, 216, 226, 114, 161, 148, 29, 83, 222, 80, 49, 77, 173, + 199, 45, 172, 121, 190, 117, 122, 71, 223, 203, 158, 230, 17, 104, + 222, 66, 53, 190, 227, 20, 181, 59, 171, 9, 165, 187, 211, 115, + 50, 3, 3, 100, 173, 96, 63, 125, 64, 175, 108, 68, 209, 162, + 86, 14, 37, 2, 169, 199, 44, 246, 170, 89, 123, 102, 116, 72, + 133, 207, 118, 125, 74, 203, 149, 2, 157, 90, 57, 110, 4, 85, + 96, 32, 106, 146, 194, 12, 133, 5, 127, 40, 2, 23, 67, 251, + 45, 183, 175, 36, 215, 95, 134, 78, 178, 120, 28, 8, 84, 67, + 213, 62, 142, 215, 1, 100, 168, 102, 161, 40, 23, 162, 200, 238, + 16, 1, 158, 146, 52, 147, 36, 239, 52, 7, 228, 160, 215, 146, + 8, 198, 195, 208, 42, 116, 152, 227, 62, 110, 142, 41, 175, 125, + 173, 219, 252, 146, 162, 91, 232, 10, 163, 54, 214, 239, 148, 164, + 98, 151, 198, 223, 228, 115, 11, 54, 169, 184, 144, 6, 12, 54, + 87, 219, 106, 39, 128, 180, 87, 82, 221, 187, 20, 241, 72, 148, + 151, 229, 253, 51, 122, 9, 192, 251, 67, 254, 190, 213, 148, 7, + 249, 139, 56, 191, 53, 124, 76, 91, 247, 121, 214, 63, 59, 13, + 43, 164, 109, 196, 232, 29, 38, 69, 95, 220, 30, 165, 204, 239, + 237, 59, 182, 173, 216, 96, 4, 117, 4, 162, 159, 250, 57, 18, + 25, 11, 96, 185, 71, 75, 175, 175, 212, 97, 191, 32, 215, 52, + 3, 250, 70, 83, 60, 144, 111, 112, 153, 243, 67, 181, 78, 254, + 79, 172, 249, 162, 95, 195, 165, 67, 223, 27, 233, 128, 77, 142, + 188, 230, 24, 109, 122, 191, 127, 60, 78, 98, 204, 207, 0, 247, + 27, 237, 9, 53, 225, 82, 54, 131, 40, 226, 205, 230, 107, 198, + 186, 152, 158, 71, 185, 247, 44, 62, 72, 184, 36, 229, 39, 236, + 138, 38, 34, 151, 120, 103, 108, 205, 1, 160, 64, 247, 47, 123, + 198, 189, 115, 188, 34, 167, 219, 203, 53, 253, 200, 164, 73, 13, + 240, 47, 45, 77, 28, 219, 32, 96, 218, 151, 211, 32, 144, 145, + 216, 45, 219, 176, 96, 113, 74, 170, 23, 81, 255, 230, 189, 235, + 115, 135, 173, 208, 160, 8, 203, 70, 115, 212, 227, 82, 211, 221, + 229, 223, 249, 207, 181, 249, 133, 77, 96, 59, 182, 108, 36, 250, + 80, 111, 3, 60, 131, 172, 21, 72, 121, 200, 18, 22, 105, 107, + 30, 13, 19, 168, 213, 30, 54, 118, 85, 167, 192, 31, 5, 50, + 151, 13, 213, 216, 62, 168, 254, 195, 209, 143, 28, 163, 174, 242, + 9, 18, 120, 45, 113, 103, 28, 233, 154, 165, 254, 252, 18, 252, + 180, 242, 112, 143, 158, 203, 150, 132, 41, 186, 188, 55, 126, 97, + 28, 123, 177, 38, 168, 138, 39, 155, 115, 160, 170, 84, 53, 116, + 221, 3, 41, 43, 84, 55, 6, 52, 234, 54, 187, 74, 26, 189, + 40, 31, 156, 98, 224, 47, 38, 105, 112, 46, 135, 73, 83, 92, + 74, 255, 224, 52, 178, 247, 176, 129, 130, 44, 78, 196, 155, 144, + 24, 108, 121, 2, 252, 191, 209, 106, 97, 181, 96, 161, 214, 146, + 7, 121, 25, 116, 124, 111, 247, 143, 211, 71, 205, 123, 182, 4, + 129, 249, 60, 253, 214, 223, 218, 142, 129, 83, 239, 36, 53, 1, + 99, 246, 134, 177, 80, 210, 0, 61, 173, 125, 232, 196, 145, 98, + 62, 158, 49, 195, 133, 131, 220, 231, 132, 165, 186, 187, 193, 88, + 118, 107, 177, 157, 195, 152, 198, 153, 173, 215, 39, 176, 209, 38, + 31, 209, 247, 103, 92, 85, 142, 93, 23, 4, 57, 170, 66, 87, + 106, 242, 11, 12, 151, 6, 31, 14, 165, 253, 66, 78, 192, 27, + 147, 28, 173, 3, 165, 102, 34, 239, 25, 136, 30, 176, 50, 93, + 28, 190, 216, 110, 23, 243, 80, 184, 239, 133, 32, 62, 77, 63, + 137, 133, 235, 33, 20, 117, 71, 106, 59, 175, 161, 109, 29, 138, + 139, 166, 175, 132, 169, 69, 93, 8, 147, 59, 33, 127, 98, 51, + 221, 153, 90, 1, 167, 125, 10, 157, 233, 151, 97, 249, 197, 40, + 251, 170, 12, 37, 55, 57, 126, 236, 96, 137, 160, 88, 8, 34, + 171, 253, 72, 80, 143, 185, 8, 15, 170, 164, 154, 157, 229, 52, + 134, 17, 82, 53, 19, 75, 134, 203, 176, 212, 103, 122, 109, 42, + 237, 115, 64, 138, 63, 100, 9, 215, 30, 172, 48, 175, 111, 157, + 14, 107, 76, 14, 1, 34, 12, 216, 151, 184, 176, 170, 180, 40, + 124, 18, 138, 217, 225, 93, 240, 141, 68, 45, 71, 198, 175, 149, + 187, 197, 67, 204, 169, 57, 134, 187, 148, 34, 232, 49, 228, 185, + 224, 101, 135, 3, 100, 129, 140, 232, 171, 221, 103, 149, 132, 184, + 198, 121, 140, 97, 181, 28, 205, 31, 21, 10, 230, 52, 17, 211, + 49, 230, 154, 75, 154, 223, 38, 168, 107, 167, 240, 95, 92, 91, + 203, 98, 233, 222, 210, 83, 77, 52, 161, 198, 152, 207, 55, 210, + 141, 202, 26, 196, 243, 174, 165, 87, 87, 128, 31, 70, 125, 203, + 55, 41, 96, 197, 187, 130, 202, 22, 84, 180, 205, 54, 140, 65, + 244, 62, 224, 24, 199, 219, 35, 251, 85, 124, 188, 81, 237, 0, + 229, 118, 70, 205, 181, 235, 133, 245, 122, 227, 41, 181, 224, 101, + 198, 177, 193, 70, 139, 0, 204, 231, 42, 106, 191, 205, 109, 146, + 246, 216, 191, 191, 54, 28, 16, 128, 154, 167, 129, 122, 118, 174, + 75, 222, 88, 45, 33, 108, 230, 28, 111, 14, 40, 215, 225, 148, + 157, 1, 211, 50, 128, 198, 63, 19, 197, 104, 103, 85, 100, 152, + 227, 220, 187, 46, 167, 183, 162, 36, 16, 202, 180, 40, 198, 70, + 219, 243, 158, 186, 105, 14, 161, 147, 240, 110, 154, 41, 84, 245, + 108, 63, 56, 189, 252, 205, 1, 150, 57, 65, 193, 216, 63, 103, + 173, 192, 210, 190, 102, 91, 249, 11, 245, 233, 172, 30, 98, 205, + 171, 82, 184, 94, 224, 28, 247, 86, 110, 147, 85, 156, 218, 185, + 159, 72, 151, 113, 57, 105, 74, 228, 64, 168, 57, 42, 9, 68, + 87, 155, 58, 246, 176, 33, 100, 88, 127, 158, 165, 235, 50, 138, + 195, 118, 145, 171, 209, 250, 11, 250, 229, 144, 97, 219, 35, 29, + 100, 23, 235, 83, 213, 129, 168, 204, 251, 164, 101, 138, 219, 214, + 18, 52, 115, 83, 118, 11, 53, 205, 226, 89, 51, 168, 44, 53, + 72, 190, 211, 16, 179, 196, 166, 2, 139, 94, 179, 159, 54, 231, + 200, 216, 248, 62, 176, 202, 243, 91, 108, 53, 26, 32, 131, 117, + 180, 140, 175, 203, 240, 18, 120, 134, 95, 236, 195, 237, 246, 4, + 148, 9, 6, 188, 156, 137, 134, 211, 151, 205, 43, 65, 159, 202, + 1, 140, 215, 219, 13, 76, 217, 146, 225, 77, 211, 77, 118, 197, + 217, 181, 123, 234, 104, 50, 114, 185, 168, 49, 18, 114, 244, 216, + 235, 199, 146, 137, 71, 214, 182, 66, 85, 59, 193, 241, 135, 193, + 91, 151, 247, 193, 49, 148, 26, 31, 65, 145, 0, 210, 86, 113, + 143, 145, 201, 157, 219, 169, 95, 226, 69, 20, 20, 202, 20, 25, + 254, 146, 123, 34, 189, 223, 212, 172, 242, 119, 233, 188, 177, 187, + 77, 250, 167, 64, 251, 157, 7, 34, 169, 113, 67, 61, 56, 14, + 113, 161, 134, 176, 177, 88, 133, 11, 40, 219, 243, 59, 219, 37, + 151, 203, 149, 77, 61, 145, 164, 249, 196, 154, 57, 229, 39, 54, + 208, 183, 132, 225, 95, 138, 211, 50, 63, 203, 13, 203, 136, 15, + 188, 218, 226, 223, 207, 22, 183, 8, 158, 252, 183, 209, 97, 151, + 219, 29, 105, 61, 41, 183, 90, 253, 8, 85, 146, 9, 212, 173, + 139, 105, 200, 72, 79, 152, 172, 243, 40, 142, 55, 26, 214, 28, + 94, 17, 119, 229, 26, 59, 4, 94, 179, 158, 132, 85, 192, 82, + 86, 117, 181, 217, 73, 176, 232, 55, 11, 127, 144, 68, 83, 200, + 56, 48, 73, 61, 15, 135, 65, 13, 252, 54, 17, 221, 49, 42, + 108, 243, 220, 125, 12, 167, 96, 251, 198, 180, 205, 39, 180, 131, + 227, 178, 7, 158, 60, 40, 39, 253, 111, 62, 224, 75, 82, 154, + 111, 210, 100, 249, 207, 251, 1, 207, 241, 180, 203, 231, 252, 185, + 40, 206, 53, 95, 124, 160, 28, 249, 156, 138, 167, 192, 210, 103, + 172, 8, 20, 170, 179, 157, 202, 142, 166, 150, 157, 171, 184, 243, + 104, 46, 9, 131, 156, 219, 179, 200, 4, 97, 60, 93, 9, 48, + 75, 50, 43, 70, 93, 147, 122, 60, 177, 215, 79, 148, 160, 246, + 115, 79, 215, 112, 18, 175, 97, 185, 244, 187, 48, 219, 204, 115, + 78, 108, 216, 168, 155, 199, 85, 212, 57, 66, 89, 182, 13, 119, + 174, 81, 130, 232, 100, 238, 180, 189, 138, 77, 10, 72, 178, 254, + 149, 86, 177, 207, 90, 149, 218, 81, 58, 74, 175, 79, 235, 157, + 32, 200, 182, 212, 198, 182, 235, 177, 194, 71, 210, 80, 144, 32, + 2, 131, 188, 41, 177, 13, 122, 97, 127, 127, 150, 38, 150, 243, + 63, 95, 41, 36, 133, 203, 43, 76, 126, 147, 64, 147, 153, 236, + 245, 70, 240, 125, 174, 199, 102, 38, 250, 7, 152, 112, 39, 194, + 114, 147, 19, 182, 207, 24, 209, 45, 81, 17, 166, 157, 36, 50, + 4, 65, 28, 175, 111, 187, 151, 52, 18, 228, 216, 150, 180, 147, + 105, 182, 106, 140, 213, 223, 60, 22, 86, 157, 201, 227, 4, 120, + 199, 105, 159, 87, 92, 237, 11, 47, 230, 98, 58, 217, 89, 83, + 174, 178, 20, 11, 139, 196, 102, 179, 198, 70, 103, 183, 82, 12, + 141, 173, 119, 198, 57, 86, 86, 165, 216, 145, 124, 185, 233, 95, + 163, 255, 174, 103, 112, 236, 53, 55, 74, 90, 55, 166, 95, 46, + 84, 18, 1, 238, 135, 253, 133, 20, 24, 16, 2, 35, 15, 72, + 47, 139, 232, 42, 251, 186, 204, 29, 67, 33, 58, 163, 217, 199, + 165, 67, 69, 153, 69, 178, 174, 6, 152, 226, 227, 77, 226, 102, + 108, 57, 195, 143, 144, 41, 195, 147, 148, 170, 152, 245, 0, 124, + 171, 27, 47, 109, 54, 247, 185, 105, 66, 101, 80, 125, 54, 142, + 150, 187, 116, 165, 247, 220, 99, 120, 253, 14, 133, 123, 174, 100, + 119, 253, 247, 242, 197, 218, 196, 39, 18, 193, 44, 184, 95, 23, + 101, 111, 208, 196, 47, 136, 201, 198, 213, 145, 42, 37, 2, 93, + 25, 148, 15, 219, 251, 179, 134, 43, 163, 45, 210, 63, 99, 7, + 255, 22, 183, 86, 62, 71, 85, 138, 198, 175, 182, 166, 229, 15, + 222, 100, 8, 58, 167, 41, 21, 221, 162, 36, 130, 226, 244, 17, + 53, 27, 16, 68, 69, 122, 122, 126, 8, 35, 166, 48, 203, 139, + 112, 11, 65, 225, 49, 3, 113, 146, 145, 217, 132, 181, 243, 149, + 141, 161, 27, 205, 88, 250, 146, 200, 95, 15, 163, 28, 19, 131, + 110, 110, 30, 237, 179, 146, 94, 229, 221, 126, 197, 168, 109, 179, + 11, 175, 59, 81, 12, 237, 234, 62, 195, 98, 110, 121, 78, 118, + 215, 158, 105, 220, 240, 162, 173, 77, 218, 108, 101, 151, 145, 249, + 59, 84, 55, 246, 82, 66, 38, 212, 237, 32, 185, 138, 8, 44, + 105, 30, 182, 236, 236, 109, 145, 157, 52, 213, 146, 28, 21, 83, + 105, 220, 140, 161, 73, 230, 143, 76, 12, 194, 53, 122, 91, 37, + 195, 17, 244, 165, 33, 194, 202, 128, 92, 203, 108, 184, 51, 169, + 96, 105, 246, 197, 203, 172, 203, 201, 229, 195, 157, 225, 131, 92, + 182, 21, 21, 133, 136, 83, 247, 212, 74, 194, 75, 129, 128, 74, + 27, 172, 7, 215, 145, 55, 230, 17, 47, 78, 171, 249, 103, 45, + 125, 187, 75, 86, 41, 230, 129, 35, 144, 177, 181, 99, 183, 115, + 136, 196, 46, 60, 247, 231, 220, 103, 121, 22, 251, 47, 220, 200, + 76, 248, 219, 190, 108, 115, 86, 117, 1, 93, 224, 4, 130, 54, + 185, 36, 190, 63, 216, 193, 28, 223, 241, 24, 254, 184, 190, 102, + 142, 170, 12, 66, 251, 205, 206, 156, 248, 30, 235, 118, 120, 137, + 135, 254, 183, 151, 194, 107, 32, 85, 21, 86, 76, 19, 98, 107, + 94, 174, 246, 60, 32, 120, 70, 106, 169, 191, 172, 5, 223, 156, + 147, 173, 104, 203, 96, 126, 37, 197, 200, 67, 2, 226, 60, 91, + 248, 21, 58, 159, 70, 241, 195, 2, 170, 204, 181, 14, 15, 16, + 110, 101, 49, 33, 206, 185, 222, 167, 0, 4, 67, 106, 189, 80, + 117, 113, 184, 50, 165, 21, 10, 55, 63, 154, 152, 166, 177, 234, + 72, 66, 227, 155, 34, 44, 104, 97, 189, 188, 203, 245, 229, 174, + 194, 150, 184, 120, 26, 232, 159, 37, 50, 199, 86, 58, 106, 69, + 16, 139, 253, 196, 20, 43, 103, 97, 62, 3, 176, 118, 44, 232, + 246, 0, 162, 201, 210, 26, 133, 41, 70, 208, 225, 223, 250, 227, + 103, 119, 215, 77, 35, 71, 221, 182, 130, 74, 254, 64, 54, 97, + 108, 54, 74, 17, 141, 158, 41, 223, 42, 126, 66, 103, 79, 4, + 165, 251, 102, 141, 158, 95, 27, 132, 240, 110, 227, 196, 19, 189, + 36, 31, 49, 43, 176, 5, 162, 147, 143, 17, 22, 222, 5, 232, + 235, 220, 12, 24, 3, 135, 3, 227, 141, 55, 150, 124, 130, 135, + 180, 3, 239, 102, 177, 251, 254, 44, 194, 88, 32, 67, 145, 15, + 48, 51, 46, 10, 98, 133, 29, 4, 174, 21, 153, 113, 252, 159, + 43, 70, 10, 113, 20, 225, 63, 34, 230, 56, 88, 172, 60, 245, + 147, 200, 204, 114, 200, 255, 92, 124, 162, 15, 92, 12, 228, 140, + 175, 28, 253, 236, 30, 157, 88, 180, 165, 162, 35, 156, 98, 147, + 49, 20, 76, 45, 95, 177, 176, 190, 186, 101, 235, 77, 210, 85, + 124, 55, 186, 88, 114, 163, 193, 189, 29, 148, 136, 135, 204, 145, + 212, 139, 113, 174, 41, 15, 68, 78, 206, 241, 0, 212, 17, 170, + 63, 47, 233, 136, 104, 52, 223, 254, 203, 93, 43, 175, 220, 105, + 228, 220, 141, 41, 161, 251, 233, 189, 139, 20, 195, 38, 13, 85, + 161, 16, 252, 212, 152, 185, 226, 158, 99, 99, 221, 183, 125, 22, + 125, 212, 7, 104, 176, 58, 207, 211, 134, 253, 128, 43, 5, 106, + 42, 110, 248, 160, 220, 250, 13, 97, 203, 189, 255, 114, 4, 247, + 26, 228, 101, 20, 197, 244, 190, 80, 3, 63, 225, 208, 110, 170, + 57, 168, 202, 9, 168, 89, 10, 75, 110, 72, 50, 189, 51, 178, + 103, 39, 86, 156, 186, 239, 3, 129, 122, 84, 162, 125, 243, 89, + 148, 155, 154, 159, 181, 8, 77, 93, 216, 94, 187, 252, 86, 103, + 112, 35, 42, 177, 195, 250, 37, 196, 14, 190, 98, 9, 21, 50, + 85, 77, 85, 190, 146, 52, 251, 238, 111, 236, 135, 153, 172, 239, + 223, 0, 24, 36, 222, 22, 36, 15, 90, 232, 46, 158, 174, 180, + 119, 173, 31, 79, 38, 67, 87, 125, 15, 242, 16, 82, 26, 119, + 71, 73, 108, 233, 176, 29, 222, 32, 118, 151, 152, 181, 67, 166, + 218, 16, 96, 120, 164, 52, 255, 32, 199, 76, 161, 67, 202, 234, + 212, 175, 131, 14, 231, 138, 240, 41, 153, 72, 181, 18, 201, 30, + 254, 106, 190, 220, 34, 48, 172, 247, 97, 247, 54, 169, 221, 2, + 167, 9, 213, 248, 174, 221, 118, 138, 16, 76, 53, 158, 53, 93, + 127, 253, 52, 34, 25, 239, 123, 82, 127, 202, 111, 24, 32, 145, + 93, 183, 74, 246, 79, 77, 48, 135, 147, 252, 193, 207, 101, 17, + 130, 245, 131, 95, 192, 60, 16, 150, 169, 189, 121, 207, 128, 3, + 23, 117, 113, 121, 92, 137, 143, 58, 187, 57, 42, 128, 131, 120, + 7, 228, 213, 240, 169, 145, 102, 114, 212, 251, 55, 202, 79, 79, + 56, 251, 112, 197, 154, 251, 105, 202, 46, 24, 84, 176, 213, 131, + 220, 211, 73, 182, 191, 5, 19, 178, 189, 107, 20, 88, 96, 248, + 122, 230, 113, 177, 194, 92, 78, 126, 2, 71, 36, 62, 119, 190, + 241, 167, 57, 192, 252, 117, 241, 145, 6, 169, 21, 72, 94, 169, + 152, 118, 15, 253, 219, 172, 73, 210, 195, 79, 189, 174, 70, 228, + 156, 82, 220, 189, 115, 52, 110, 46, 179, 171, 87, 176, 171, 181, + 37, 48, 234, 45, 244, 136, 160, 134, 175, 131, 63, 29, 16, 157, + 198, 63, 134, 154, 234, 239, 177, 232, 48, 76, 51, 41, 70, 121, + 104, 20, 0, 82, 242, 60, 56, 89, 139, 32, 194, 228, 143, 153, + 7, 202, 189, 187, 172, 88, 152, 244, 154, 171, 217, 72, 218, 48, + 211, 192, 188, 120, 11, 99, 168, 225, 18, 228, 93, 224, 143, 150, + 29, 217, 69, 64, 201, 55, 228, 186, 184, 231, 170, 26, 83, 118, + 90, 74, 117, 105, 46, 204, 101, 199, 69, 112, 191, 3, 55, 22, + 8, 197, 123, 223, 221, 251, 196, 82, 206, 216, 59, 223, 154, 52, + 29, 44, 162, 244, 76, 128, 139, 68, 82, 221, 12, 12, 195, 100, + 207, 150, 118, 135, 227, 188, 13, 211, 129, 207, 227, 155, 26, 136, + 228, 127, 13, 46, 54, 236, 69, 230, 166, 80, 15, 255, 197, 5, + 30, 191, 215, 28, 53, 237, 27, 27, 3, 233, 35, 231, 175, 107, + 194, 133, 41, 22, 53, 51, 108, 147, 31, 108, 198, 237, 16, 142, + 174, 104, 92, 126, 165, 250, 199, 191, 165, 168, 31, 170, 48, 153, + 207, 127, 62, 162, 134, 244, 26, 211, 115, 149, 51, 127, 127, 228, + 17, 111, 108, 78, 133, 160, 63, 142, 85, 80, 121, 182, 117, 214, + 106, 187, 213, 7, 138, 99, 138, 83, 107, 203, 146, 48, 100, 119, + 232, 87, 141, 60, 37, 215, 68, 37, 98, 55, 45, 219, 238, 68, + 170, 149, 44, 88, 17, 139, 16, 172, 196, 187, 55, 142, 230, 248, + 96, 20, 203, 253, 223, 44, 212, 57, 190, 244, 85, 87, 77, 31, + 49, 2, 162, 49, 79, 98, 17, 30, 211, 145, 251, 239, 51, 26, + 251, 95, 126, 186, 72, 251, 32, 180, 28, 103, 246, 123, 25, 106, + 144, 1, 248, 32, 102, 48, 140, 197, 239, 250, 107, 160, 137, 238, + 78, 213, 173, 78, 51, 49, 233, 238, 48, 237, 186, 78, 52, 195, + 131, 18, 125, 5, 244, 77, 229, 64, 223, 211, 152, 88, 103, 120, + 82, 116, 146, 140, 35, 39, 176, 47, 118, 78, 142, 211, 15, 23, + 157, 144, 175, 140, 131, 152, 45, 202, 161, 33, 51, 181, 182, 1, + 202, 184, 203, 39, 116, 48, 141, 146, 90, 135, 146, 222, 3, 118, + 102, 40, 126, 40, 253, 144, 249, 2, 128, 71, 193, 120, 6, 72, + 234, 151, 153, 63, 161, 54, 1, 36, 159, 44, 150, 57, 200, 64, + 147, 219, 9, 109, 242, 46, 10, 149, 202, 60, 35, 179, 68, 212, + 55, 77, 48, 61, 210, 59, 230, 243, 16, 53, 110, 20, 127, 125, + 37, 166, 184, 251, 169, 133, 11, 183, 114, 108, 205, 234, 74, 221, + 101, 113, 38, 206, 240, 26, 101, 53, 153, 191, 132, 202, 218, 177, + 180, 183, 83, 241, 179, 42, 131, 22, 170, 65, 215, 41, 82, 184, + 83, 93, 65, 157, 42, 202, 221, 93, 24, 17, 208, 221, 139, 93, + 191, 167, 215, 12, 123, 23, 94, 117, 129, 217, 160, 101, 246, 20, + 217, 117, 253, 39, 16, 141, 142, 192, 104, 26, 248, 131, 122, 9, + 74, 119, 220, 108, 143, 222, 74, 177, 21, 140, 182, 165, 220, 239, + 107, 64, 87, 137, 144, 49, 239, 14, 229, 180, 174, 165, 173, 65, + 87, 95, 3, 108, 124, 109, 232, 219, 147, 108, 212, 27, 56, 181, + 18, 74, 52, 94, 51, 185, 138, 132, 190, 244, 112, 150, 90, 47, + 238, 162, 44, 210, 175, 111, 224, 235, 216, 229, 110, 183, 204, 226, + 120, 104, 166, 218, 152, 42, 82, 138, 196, 127, 166, 253, 45, 229, + 178, 146, 217, 129, 203, 143, 55, 114, 35, 225, 17, 94, 17, 28, + 201, 74, 64, 185, 94, 39, 202, 181, 94, 61, 184, 252, 237, 226, + 183, 23, 52, 239, 245, 131, 63, 80, 211, 49, 122, 11, 94, 31, + 249, 168, 17, 115, 215, 89, 91, 229, 243, 202, 180, 197, 13, 121, + 205, 237, 146, 229, 147, 110, 153, 132, 74, 156, 224, 68, 3, 8, + 216, 48, 87, 100, 93, 32, 202, 219, 70, 116, 21, 176, 22, 97, + 206, 25, 188, 140, 188, 216, 209, 49, 215, 147, 136, 203, 248, 42, + 84, 195, 238, 130, 87, 167, 95, 49, 26, 245, 197, 236, 225, 218, + 131, 142, 115, 147, 79, 150, 224, 161, 79, 22, 184, 13, 149, 148, + 133, 126, 154, 76, 185, 56, 151, 165, 118, 178, 41, 118, 208, 185, + 76, 211, 55, 34, 122, 95, 218, 88, 216, 199, 72, 160, 34, 17, + 119, 147, 255, 158, 70, 94, 161, 5, 166, 180, 200, 135, 223, 50, + 23, 243, 227, 159, 186, 226, 81, 85, 199, 181, 238, 82, 13, 73, + 215, 248, 235, 58, 147, 247, 2, 212, 201, 135, 237, 99, 132, 198, + 31, 255, 252, 139, 187, 17, 44, 250, 17, 254, 206, 16, 123, 189, + 57, 28, 106, 247, 101, 73, 123, 83, 43, 85, 99, 219, 62, 181, + 99, 254, 44, 70, 91, 219, 80, 89, 245, 55, 172, 166, 29, 10, + 234, 122, 94, 53, 95, 40, 59, 92, 152, 248, 22, 141, 104, 86, + 50, 144, 113, 207, 9, 170, 98, 59, 84, 197, 15, 214, 223, 112, + 9, 16, 124, 34, 207, 146, 91, 75, 107, 92, 5, 92, 212, 232, + 99, 132, 251, 81, 194, 37, 96, 111, 198, 215, 204, 248, 172, 230, + 99, 43, 34, 213, 16, 115, 37, 254, 180, 101, 186, 115, 18, 117, + 163, 247, 20, 186, 196, 171, 72, 48, 255, 70, 98, 202, 7, 225, + 90, 145, 228, 75, 42, 246, 254, 175, 150, 144, 85, 21, 196, 18, + 134, 174, 204, 234, 238, 202, 234, 67, 71, 221, 62, 164, 28, 165, + 241, 176, 162, 175, 247, 63, 218, 6, 243, 197, 141, 36, 75, 26, + 213, 235, 27, 91, 67, 10, 72, 52, 3, 110, 18, 159, 97, 104, + 194, 233, 104, 75, 10, 232, 132, 226, 157, 66, 159, 207, 197, 44, + 60, 239, 74, 187, 77, 143, 237, 158, 89, 128, 149, 24, 21, 197, + 138, 108, 85, 154, 46, 76, 185, 215, 0, 163, 245, 250, 185, 33, + 151, 204, 75, 69, 171, 238, 88, 46, 190, 84, 193, 208, 172, 159, + 191, 56, 59, 51, 100, 181, 241, 224, 87, 59, 41, 78, 201, 226, + 67, 253, 184, 136, 128, 121, 15, 13, 225, 181, 3, 70, 255, 214, + 248, 252, 131, 215, 148, 209, 91, 235, 80, 84, 140, 224, 224, 223, + 70, 225, 139, 5, 186, 46, 115, 213, 238, 228, 147, 170, 84, 2, + 18, 190, 52, 15, 175, 183, 122, 73, 155, 62, 68, 210, 40, 247, + 3, 201, 88, 77, 221, 4, 42, 241, 236, 78, 119, 92, 108, 243, + 158, 47, 202, 73, 177, 212, 137, 65, 54, 210, 131, 168, 101, 232, + 115, 56, 128, 64, 74, 182, 82, 28, 45, 24, 65, 145, 70, 230, + 206, 206, 108, 43, 187, 226, 3, 171, 98, 60, 125, 244, 63, 189, + 195, 5, 225, 122, 15, 249, 251, 211, 234, 144, 49, 218, 236, 234, + 51, 117, 244, 128, 160, 132, 89, 214, 224, 66, 95, 63, 243, 200, + 168, 149, 190, 254, 37, 123, 57, 129, 175, 162, 40, 135, 134, 163, + 76, 169, 148, 129, 41, 100, 12, 131, 215, 36, 74, 171, 155, 116, + 107, 222, 169, 182, 165, 227, 3, 248, 89, 132, 45, 121, 111, 28, + 175, 228, 174, 35, 11, 144, 209, 31, 147, 84, 145, 33, 237, 169, + 125, 96, 107, 13, 2, 156, 127, 78, 254, 179, 232, 118, 54, 58, + 162, 249, 139, 196, 248, 213, 234, 177, 179, 38, 80, 76, 140, 47, + 150, 141, 9, 20, 207, 178, 196, 133, 78, 250, 27, 234, 224, 245, + 82, 27, 78, 230, 45, 18, 160, 159, 55, 170, 93, 69, 4, 153, + 88, 178, 27, 127, 170, 119, 38, 178, 253, 101, 203, 17, 45, 142, + 85, 42, 164, 202, 63, 132, 14, 45, 172, 246, 9, 244, 89, 41, + 119, 225, 206, 163, 20, 246, 101, 0, 254, 30, 11, 7, 158, 207, + 155, 240, 80, 99, 85, 40, 129, 126, 4, 251, 197, 60, 97, 178, + 72, 163, 112, 30, 50, 224, 3, 30, 160, 45, 33, 91, 146, 169, + 188, 109, 39, 43, 125, 56, 204, 56, 65, 10, 90, 123, 114, 67, + 103, 73, 249, 40, 29, 133, 80, 216, 76, 65, 48, 124, 6, 150, + 58, 113, 50, 187, 162, 10, 255, 146, 141, 174, 71, 57, 155, 219, + 193, 53, 87, 214, 204, 247, 229, 84, 162, 211, 99, 59, 160, 81, + 229, 78, 103, 163, 167, 172, 33, 160, 3, 45, 252, 216, 243, 163, + 245, 195, 30, 235, 247, 77, 115, 16, 95, 195, 222, 96, 157, 69, + 87, 245, 129, 242, 226, 21, 208, 223, 206, 188, 88, 133, 123, 196, + 115, 216, 208, 137, 212, 131, 237, 206, 41, 200, 15, 21, 109, 23, + 11, 11, 159, 49, 155, 88, 112, 247, 136, 161, 226, 38, 184, 185, + 50, 161, 149, 204, 232, 241, 64, 175, 46, 153, 227, 147, 57, 194, + 172, 146, 167, 177, 153, 207, 86, 215, 151, 41, 231, 29, 147, 141, + 139, 91, 188, 16, 7, 223, 239, 1, 17, 88, 145, 175, 240, 30, + 74, 223, 161, 162, 137, 54, 243, 165, 62, 159, 71, 165, 182, 54, + 130, 153, 3, 251, 241, 211, 77, 141, 136, 56, 138, 37, 219, 116, + 55, 199, 217, 189, 108, 144, 175, 221, 37, 205, 2, 24, 93, 191, + 206, 181, 59, 89, 24, 188, 92, 108, 84, 251, 71, 38, 217, 34, + 129, 26, 26, 93, 143, 166, 138, 122, 103, 215, 243, 7, 7, 236, + 83, 225, 207, 17, 71, 19, 144, 207, 37, 5, 92, 170, 172, 230, + 162, 71, 141, 138, 7, 175, 252, 224, 206, 141, 75, 252, 81, 239, + 11, 229, 115, 0, 120, 82, 212, 246, 18, 238, 147, 27, 96, 183, + 184, 54, 226, 217, 160, 181, 97, 47, 245, 90, 23, 142, 68, 231, + 78, 125, 96, 250, 225, 24, 159, 171, 142, 235, 44, 89, 65, 62, + 180, 239, 125, 97, 229, 187, 119, 212, 9, 221, 104, 117, 125, 101, + 109, 178, 17, 198, 212, 230, 145, 170, 137, 156, 46, 123, 165, 111, + 154, 82, 50, 112, 65, 48, 125, 25, 54, 177, 74, 230, 86, 182, + 174, 12, 52, 98, 129, 169, 51, 212, 122, 91, 150, 253, 158, 18, + 61, 137, 44, 15, 109, 31, 162, 3, 174, 52, 21, 174, 234, 135, + 204, 211, 115, 194, 231, 30, 240, 29, 51, 93, 223, 202, 154, 105, + 162, 122, 64, 210, 248, 116, 8, 142, 123, 86, 19, 235, 93, 3, + 206, 194, 105, 50, 104, 160, 151, 255, 232, 62, 182, 29, 74, 35, + 162, 228, 211, 185, 233, 94, 28, 116, 89, 153, 99, 253, 250, 45, + 155, 42, 107, 131, 233, 134, 211, 187, 86, 226, 216, 50, 26, 191, + 165, 109, 121, 96, 142, 128, 18, 108, 89, 55, 241, 93, 200, 116, + 201, 63, 70, 113, 110, 223, 175, 107, 225, 153, 9, 57, 182, 26, + 18, 96, 62, 173, 29, 163, 17, 76, 164, 152, 57, 8, 91, 43, + 182, 177, 73, 91, 137, 116, 1, 30, 109, 181, 117, 40, 122, 218, + 39, 108, 240, 86, 251, 116, 143, 80, 204, 226, 21, 245, 137, 78, + 174, 56, 183, 126, 185, 189, 27, 76, 217, 20, 11, 248, 178, 3, + 181, 228, 239, 67, 10, 119, 155, 84, 162, 147, 25, 106, 88, 181, + 148, 152, 232, 219, 18, 134, 166, 106, 228, 66, 138, 110, 50, 176, + 60, 54, 188, 225, 234, 234, 218, 177, 236, 109, 234, 192, 40, 18, + 159, 157, 231, 132, 49, 133, 160, 184, 203, 156, 141, 87, 88, 24, + 197, 191, 107, 15, 131, 166, 118, 22, 57, 159, 201, 230, 183, 101, + 7, 1, 221, 111, 86, 44, 155, 33, 186, 6, 77, 129, 107, 133, + 218, 222, 40, 192, 34, 234, 10, 237, 224, 106, 72, 104, 88, 48, + 232, 72, 88, 150, 223, 219, 28, 163, 158, 187, 72, 13, 220, 18, + 38, 30, 170, 19, 112, 91, 173, 208, 3, 226, 141, 184, 151, 196, + 235, 151, 195, 123, 246, 184, 123, 126, 14, 204, 100, 32, 139, 94, + 89, 113, 125, 81, 225, 224, 210, 79, 141, 45, 57, 0, 157, 7, + 73, 203, 196, 61, 18, 76, 54, 17, 237, 139, 150, 83, 56, 236, + 140, 255, 203, 140, 212, 83, 50, 59, 161, 58, 19, 56, 130, 233, + 170, 46, 169, 110, 255, 177, 216, 112, 150, 239, 177, 244, 25, 216, + 74, 149, 101, 112, 246, 71, 54, 197, 52, 203, 39, 117, 108, 71, + 181, 216, 197, 221, 95, 54, 183, 123, 167, 84, 111, 238, 194, 215, + 196, 66, 69, 41, 70, 58, 70, 196, 209, 111, 85, 134, 108, 239, + 32, 144, 180, 28, 35, 157, 195, 209, 176, 0, 78, 59, 24, 5, + 57, 197, 164, 155, 38, 63, 132, 183, 11, 161, 167, 131, 107, 110, + 102, 80, 45, 223, 132, 35, 163, 218, 77, 158, 204, 202, 213, 55, + 148, 161, 37, 145, 188, 194, 57, 71, 50, 21, 1, 235, 114, 233, + 236, 166, 35, 198, 58, 137, 95, 230, 110, 20, 189, 104, 156, 31, + 62, 25, 32, 143, 11, 180, 251, 12, 235, 179, 178, 126, 101, 246, + 225, 12, 189, 188, 7, 5, 178, 142, 240, 13, 118, 115, 189, 159, + 174, 65, 190, 129, 244, 146, 156, 235, 39, 106, 221, 192, 134, 194, + 176, 218, 147, 206, 25, 113, 199, 234, 19, 6, 44, 238, 176, 2, + 225, 60, 188, 36, 36, 115, 62, 151, 156, 77, 136, 139, 60, 116, + 164, 183, 197, 12, 213, 201, 140, 148, 53, 222, 144, 41, 190, 192, + 254, 55, 109, 136, 88, 235, 232, 241, 102, 50, 27, 141, 82, 81, + 113, 231, 253, 71, 15, 28, 107, 21, 53, 105, 37, 168, 230, 10, + 251, 173, 246, 144, 5, 161, 5, 173, 70, 132, 124, 104, 28, 228, + 5, 158, 133, 219, 60, 196, 159, 249, 2, 166, 105, 147, 99, 193, + 194, 13, 105, 238, 213, 213, 226, 232, 187, 219, 45, 34, 174, 218, + 30, 194, 131, 108, 236, 135, 33, 154, 13, 163, 40, 57, 11, 191, + 16, 137, 106, 207, 190, 110, 221, 19, 126, 73, 204, 193, 226, 29, + 47, 123, 51, 207, 163, 207, 243, 239, 149, 246, 90, 82, 121, 4, + 62, 104, 255, 185, 230, 252, 244, 65, 228, 176, 14, 95, 41, 174, + 88, 55, 156, 206, 161, 75, 162, 239, 197, 227, 44, 58, 147, 34, + 196, 124, 134, 247, 213, 253, 104, 220, 123, 144, 30, 24, 115, 169, + 127, 61, 141, 244, 227, 124, 74, 247, 217, 254, 14, 190, 214, 183, + 28, 39, 175, 202, 212, 117, 163, 3, 228, 143, 227, 13, 120, 40, + 253, 172, 217, 47, 233, 23, 154, 108, 59, 73, 14, 203, 163, 134, + 218, 142, 39, 29, 204, 35, 67, 88, 241, 153, 197, 244, 93, 58, + 178, 225, 199, 54, 65, 109, 177, 69, 71, 71, 159, 178, 133, 147, + 18, 181, 154, 237, 155, 117, 76, 185, 46, 32, 51, 47, 180, 66, + 75, 155, 101, 234, 248, 87, 216, 126, 207, 120, 240, 239, 136, 57, + 182, 254, 157, 228, 238, 238, 207, 30, 116, 248, 123, 70, 226, 11, + 207, 202, 211, 70, 90, 151, 190, 200, 151, 11, 75, 150, 13, 173, + 24, 81, 132, 77, 83, 208, 95, 71, 218, 94, 128, 231, 19, 165, + 80, 47, 19, 185, 38, 128, 103, 28, 235, 234, 177, 83, 20, 148, + 249, 170, 222, 127, 147, 130, 69, 249, 149, 143, 42, 224, 153, 17, + 67, 216, 60, 224, 92, 102, 47, 45, 245, 235, 232, 131, 50, 8, + 130, 90, 218, 7, 47, 174, 255, 212, 105, 77, 96, 23, 104, 145, + 63, 39, 176, 97, 37, 186, 82, 203, 61, 18, 170, 228, 195, 202, + 45, 191, 186, 234, 180, 113, 160, 46, 57, 150, 222, 138, 32, 148, + 133, 183, 233, 213, 42, 5, 182, 158, 85, 150, 154, 231, 76, 47, + 247, 46, 18, 157, 13, 65, 44, 146, 96, 127, 154, 13, 63, 174, + 185, 55, 236, 114, 29, 213, 101, 165, 167, 83, 93, 82, 86, 233, + 104, 105, 239, 118, 252, 202, 98, 170, 19, 117, 92, 84, 247, 130, + 33, 0, 146, 94, 36, 116, 107, 123, 122, 28, 47, 113, 161, 140, + 57, 226, 250, 191, 26, 217, 207, 181, 191, 123, 155, 41, 124, 18, + 114, 244, 86, 8, 23, 236, 155, 83, 238, 0, 229, 150, 53, 0, + 13, 200, 10, 4, 150, 3, 18, 89, 232, 221, 175, 63, 205, 168, + 149, 57, 41, 39, 243, 0, 46, 56, 67, 176, 199, 54, 16, 13, + 237, 187, 50, 3, 115, 71, 112, 43, 171, 4, 134, 2, 243, 108, + 23, 198, 116, 171, 41, 76, 64, 21, 52, 59, 117, 223, 181, 66, + 49, 70, 101, 239, 195, 100, 226, 152, 32, 94, 223, 77, 7, 2, + 183, 153, 211, 221, 135, 209, 23, 210, 128, 17, 214, 115, 117, 54, + 32, 240, 207, 7, 101, 214, 220, 126, 214, 180, 180, 92, 157, 20, + 221, 245, 90, 189, 130, 28, 19, 129, 99, 149, 117, 115, 72, 68, + 62, 5, 79, 240, 4, 103, 199, 135, 237, 164, 235, 157, 181, 89, + 247, 199, 102, 88, 179, 172, 20, 128, 77, 73, 10, 101, 199, 141, + 180, 1, 155, 74, 13, 72, 11, 28, 35, 221, 234, 150, 61, 61, + 232, 96, 245, 96, 110, 154, 174, 170, 28, 163, 70, 214, 170, 110, + 35, 151, 204, 228, 138, 99, 5, 21, 149, 7, 231, 156, 122, 0, + 98, 60, 239, 120, 28, 207, 119, 19, 159, 20, 129, 36, 79, 86, + 223, 47, 101, 145, 186, 145, 235, 130, 22, 191, 180, 185, 151, 77, + 175, 90, 157, 65, 204, 201, 150, 208, 23, 44, 10, 130, 70, 171, + 130, 178, 184, 9, 238, 70, 214, 19, 65, 144, 64, 114, 57, 158, + 211, 75, 62, 248, 145, 41, 179, 197, 42, 133, 227, 160, 105, 41, + 206, 161, 191, 200, 95, 153, 131, 51, 204, 104, 237, 46, 133, 47, + 123, 170, 243, 183, 39, 68, 121, 195, 59, 16, 142, 250, 178, 25, + 240, 48, 157, 138, 53, 119, 153, 72, 205, 251, 198, 186, 72, 32, + 52, 89, 250, 48, 1, 41, 219, 206, 64, 96, 104, 75, 240, 30, + 27, 162, 146, 85, 161, 154, 205, 223, 120, 74, 212, 151, 43, 8, + 70, 176, 24, 108, 253, 151, 249, 215, 233, 117, 36, 43, 129, 251, + 119, 105, 101, 101, 47, 224, 243, 230, 118, 140, 5, 245, 213, 211, + 212, 244, 78, 191, 196, 102, 244, 233, 182, 20, 92, 69, 230, 169, + 234, 201, 98, 106, 119, 4, 134, 114, 174, 49, 7, 229, 249, 47, + 57, 30, 1, 9, 158, 242, 74, 172, 164, 185, 95, 167, 1, 41, + 187, 5, 139, 159, 208, 93, 127, 45, 252, 31, 250, 104, 126, 153, + 176, 95, 137, 157, 172, 247, 191, 236, 101, 250, 236, 142, 8, 205, + 190, 207, 139, 218, 44, 198, 23, 203, 234, 159, 54, 237, 198, 255, + 101, 111, 92, 34, 146, 249, 104, 45, 111, 23, 31, 52, 217, 66, + 212, 45, 43, 16, 60, 99, 251, 93, 223, 157, 240, 98, 144, 173, + 175, 221, 247, 71, 57, 103, 168, 72, 209, 121, 23, 242, 171, 93, + 102, 3, 91, 167, 209, 198, 211, 203, 102, 18, 34, 55, 117, 243, + 191, 221, 252, 156, 244, 64, 234, 15, 3, 138, 16, 141, 119, 243, + 21, 80, 175, 123, 108, 88, 107, 213, 117, 13, 255, 7, 93, 219, + 6, 134, 205, 167, 224, 60, 42, 116, 25, 26, 231, 160, 111, 76, + 57, 204, 249, 157, 75, 147, 62, 107, 34, 99, 17, 37, 189, 144, + 191, 31, 169, 199, 44, 21, 39, 62, 198, 17, 38, 167, 212, 154, + 63, 120, 67, 244, 72, 76, 254, 175, 61, 142, 112, 9, 182, 33, + 218, 179, 138, 177, 204, 179, 130, 96, 151, 222, 152, 193, 85, 169, + 14, 112, 242, 118, 45, 227, 100, 201, 211, 42, 146, 91, 174, 172, + 66, 102, 29, 135, 150, 87, 81, 122, 90, 182, 57, 5, 76, 220, + 188, 192, 160, 244, 220, 207, 21, 67, 46, 163, 170, 203, 23, 126, + 143, 103, 8, 1, 103, 136, 33, 90, 44, 63, 179, 150, 244, 108, + 246, 210, 109, 163, 19, 162, 80, 239, 159, 3, 70, 175, 201, 202, + 227, 37, 44, 87, 39, 182, 43, 149, 240, 14, 203, 123, 23, 80, + 215, 30, 165, 224, 158, 238, 9, 216, 118, 129, 94, 85, 49, 194, + 234, 13, 111, 248, 167, 132, 199, 219, 39, 8, 37, 249, 104, 24, + 78, 148, 31, 248, 165, 112, 1, 222, 41, 146, 35, 221, 187, 207, + 126, 102, 213, 16, 75, 90, 10, 229, 174, 39, 144, 84, 254, 163, + 193, 184, 62, 177, 105, 162, 224, 147, 234, 96, 52, 83, 6, 195, + 11, 137, 217, 127, 62, 66, 108, 184, 90, 244, 73, 195, 179, 117, + 14, 254, 57, 253, 195, 122, 58, 191, 12, 27, 25, 153, 226, 239, + 87, 143, 144, 30, 164, 244, 216, 36, 145, 70, 167, 185, 138, 107, + 2, 7, 178, 115, 216, 108, 225, 54, 115, 238, 41, 133, 148, 41, + 220, 180, 236, 236, 125, 54, 46, 25, 149, 184, 214, 146, 92, 8, + 131, 117, 219, 195, 8, 47, 204, 71, 139, 139, 2, 84, 162, 138, + 187, 136, 207, 226, 215, 136, 168, 192, 75, 205, 44, 0, 147, 164, + 43, 67, 112, 147, 5, 249, 219, 190, 242, 68, 246, 43, 49, 189, + 29, 131, 146, 101, 51, 119, 251, 85, 130, 146, 84, 124, 65, 217, + 220, 229, 217, 84, 28, 36, 186, 252, 83, 10, 22, 3, 73, 183, + 200, 68, 22, 20, 211, 50, 53, 157, 160, 200, 3, 215, 208, 177, + 72, 202, 142, 240, 71, 110, 201, 242, 83, 63, 158, 69, 224, 25, + 207, 223, 70, 237, 186, 9, 237, 212, 79, 16, 80, 75, 133, 192, + 51, 82, 151, 166, 201, 147, 45, 6, 246, 66, 65, 156, 161, 94, + 183, 207, 235, 98, 233, 199, 103, 102, 163, 46, 122, 210, 18, 71, + 9, 20, 79, 185, 138, 69, 63, 93, 35, 110, 227, 182, 114, 69, + 78, 144, 182, 255, 170, 255, 122, 7, 52, 67, 13, 192, 183, 77, + 115, 113, 11, 253, 186, 85, 56, 134, 133, 247, 190, 254, 1, 147, + 233, 54, 229, 157, 21, 144, 101, 149, 136, 233, 23, 14, 113, 7, + 199, 235, 241, 184, 87, 194, 140, 30, 176, 159, 206, 100, 225, 75, + 159, 139, 159, 140, 135, 239, 233, 207, 24, 27, 55, 227, 163, 56, + 133, 105, 154, 31, 179, 20, 153, 138, 34, 132, 232, 117, 221, 216, + 19, 84, 170, 40, 1, 12, 161, 192, 227, 239, 197, 232, 213, 162, + 135, 89, 110, 250, 109, 29, 88, 250, 17, 150, 117, 168, 148, 238, + 231, 122, 17, 12, 71, 221, 150, 3, 132, 95, 120, 69, 169, 162, + 54, 75, 14, 240, 37, 142, 97, 89, 69, 211, 62, 105, 173, 81, + 142, 115, 53, 140, 37, 182, 244, 247, 145, 185, 196, 90, 92, 21, + 117, 37, 239, 136, 0, 86, 1, 56, 82, 117, 15, 172, 244, 194, + 130, 33, 202, 145, 14, 15, 133, 108, 96, 201, 103, 15, 127, 121, + 119, 244, 153, 145, 74, 75, 243, 227, 163, 125, 95, 182, 221, 0, + 10, 154, 153, 142, 215, 120, 254, 74, 183, 59, 156, 68, 134, 198, + 46, 123, 3, 42, 214, 126, 144, 194, 136, 124, 84, 184, 136, 126, + 201, 91, 113, 21, 158, 242, 147, 146, 28, 7, 203, 83, 96, 137, + 152, 165, 7, 168, 177, 24, 1, 17, 143, 13, 177, 167, 126, 177, + 74, 16, 183, 240, 165, 22, 217, 8, 98, 197, 251, 11, 177, 171, + 33, 58, 82, 62, 189, 97, 124, 148, 147, 84, 207, 132, 39, 81, + 77, 32, 77, 75, 105, 56, 205, 89, 117, 75, 131, 31, 175, 240, + 177, 207, 177, 208, 177, 149, 125, 96, 33, 128, 103, 141, 156, 18, + 99, 64, 17, 73, 250, 60, 43, 213, 151, 245, 190, 99, 64, 33, + 145, 48, 182, 183, 187, 226, 103, 151, 136, 85, 95, 180, 225, 250, + 111, 53, 129, 240, 80, 200, 245, 238, 226, 219, 45, 12, 188, 54, + 24, 159, 194, 176, 15, 101, 48, 164, 188, 206, 73, 171, 218, 98, + 141, 139, 207, 17, 8, 39, 29, 88, 14, 2, 2, 122, 163, 133, + 97, 83, 113, 8, 237, 24, 255, 43, 152, 13, 166, 187, 138, 108, + 9, 181, 137, 8, 47, 128, 167, 117, 41, 115, 224, 37, 228, 87, + 30, 7, 148, 53, 168, 94, 24, 146, 1, 188, 98, 108, 236, 130, + 92, 245, 240, 130, 69, 17, 80, 183, 239, 251, 133, 108, 218, 238, + 132, 133, 24, 13, 238, 214, 96, 143, 110, 225, 50, 177, 179, 136, + 184, 98, 93, 75, 27, 90, 23, 19, 190, 188, 50, 131, 224, 81, + 181, 90, 85, 74, 127, 29, 132, 66, 28, 50, 220, 152, 163, 34, + 21, 100, 62, 65, 67, 238, 58, 119, 110, 255, 15, 75, 9, 69, + 59, 171, 254, 156, 240, 234, 17, 176, 134, 16, 129, 11, 96, 164, + 39, 165, 25, 136, 108, 207, 176, 136, 2, 7, 152, 33, 127, 131, + 117, 209, 23, 239, 127, 181, 122, 215, 242, 15, 123, 43, 77, 186, + 201, 221, 5, 119, 143, 224, 177, 44, 200, 53, 109, 191, 231, 127, + 82, 77, 232, 100, 168, 239, 84, 156, 194, 24, 234, 55, 185, 83, + 87, 170, 215, 69, 3, 77, 235, 134, 245, 223, 131, 9, 165, 246, + 238, 232, 66, 12, 246, 180, 120, 247, 3, 228, 215, 92, 66, 125, + 144, 159, 145, 13, 206, 202, 88, 124, 26, 212, 162, 96, 227, 148, + 213, 181, 119, 106, 219, 194, 15, 67, 61, 23, 196, 183, 173, 40, + 207, 0, 169, 185, 46, 129, 217, 255, 91, 187, 202, 155, 19, 35, + 206, 102, 14, 106, 70, 204, 242, 102, 44, 158, 115, 37, 69, 49, + 44, 227, 225, 193, 192, 7, 201, 216, 252, 131, 188, 178, 22, 166, + 236, 13, 118, 179, 127, 16, 252, 53, 216, 160, 71, 119, 156, 150, + 235, 29, 184, 255, 222, 58, 21, 241, 120, 123, 210, 173, 107, 77, + 130, 121, 165, 103, 251, 197, 108, 93, 97, 207, 46, 68, 2, 90, + 205, 243, 131, 202, 245, 40, 64, 235, 80, 130, 224, 157, 50, 57, + 100, 202, 39, 141, 204, 56, 104, 46, 27, 36, 195, 169, 175, 11, + 250, 41, 147, 188, 176, 42, 117, 112, 67, 75, 156, 61, 73, 75, + 1, 222, 221, 6, 63, 246, 5, 227, 15, 165, 50, 195, 33, 60, + 250, 125, 224, 60, 174, 218, 102, 233, 133, 127, 117, 237, 246, 209, + 220, 237, 84, 234, 80, 143, 184, 98, 36, 69, 23, 191, 70, 46, + 62, 123, 156, 105, 96, 90, 65, 99, 197, 200, 109, 194, 112, 125, + 169, 72, 36, 73, 166, 153, 72, 19, 102, 9, 68, 194, 7, 209, + 238, 176, 69, 240, 48, 200, 186, 173, 80, 242, 46, 33, 61, 133, + 174, 201, 171, 110, 189, 251, 66, 15, 2, 214, 24, 174, 24, 11, + 163, 23, 217, 200, 87, 114, 128, 54, 0, 27, 238, 220, 24, 141, + 133, 179, 119, 144, 182, 190, 223, 15, 172, 8, 166, 190, 169, 156, + 227, 50, 89, 207, 173, 44, 150, 175, 74, 164, 34, 2, 40, 33, + 19, 93, 213, 108, 9, 8, 165, 3, 211, 132, 55, 167, 56, 68, + 200, 149, 132, 202, 21, 81, 164, 117, 55, 251, 53, 249, 48, 116, + 203, 224, 249, 69, 89, 145, 177, 92, 207, 16, 250, 52, 26, 109, + 73, 28, 54, 56, 64, 24, 156, 12, 129, 191, 55, 46, 190, 1, + 227, 230, 201, 251, 125, 215, 160, 94, 42, 89, 226, 105, 123, 226, + 45, 91, 113, 221, 176, 80, 8, 197, 115, 94, 241, 134, 166, 124, + 146, 132, 15, 108, 105, 247, 213, 251, 235, 107, 151, 98, 11, 163, + 248, 108, 54, 193, 147, 112, 171, 175, 30, 9, 210, 248, 26, 183, + 96, 29, 44, 148, 231, 164, 160, 101, 43, 160, 245, 140, 61, 36, + 203, 86, 100, 72, 74, 51, 233, 215, 221, 249, 241, 220, 229, 54, + 235, 195, 110, 222, 168, 111, 0, 74, 83, 52, 210, 130, 240, 63, + 211, 144, 8, 166, 141, 149, 160, 247, 129, 8, 142, 121, 150, 87, + 214, 191, 241, 227, 3, 15, 72, 85, 253, 146, 215, 187, 132, 173, + 185, 238, 12, 251, 227, 205, 187, 60, 182, 55, 155, 213, 61, 183, + 44, 117, 216, 128, 110, 79, 131, 128, 125, 123, 39, 88, 44, 35, + 54, 67, 113, 143, 2, 0, 243, 142, 107, 142, 3, 21, 245, 35, + 107, 228, 101, 18, 90, 157, 1, 167, 21, 171, 169, 221, 120, 229, + 218, 123, 160, 36, 95, 91, 9, 123, 97, 145, 156, 76, 116, 121, + 74, 131, 125, 17, 136, 199, 253, 47, 96, 87, 193, 105, 44, 208, + 194, 165, 5, 9, 13, 88, 194, 7, 120, 241, 131, 0, 169, 63, + 65, 211, 241, 46, 81, 245, 131, 218, 100, 210, 226, 198, 240, 37, + 53, 52, 136, 194, 238, 85, 145, 187, 11, 38, 105, 35, 18, 98, + 239, 116, 8, 174, 94, 100, 188, 163, 105, 30, 231, 204, 91, 2, + 199, 210, 99, 77, 212, 169, 171, 126, 34, 205, 124, 254, 22, 143, + 24, 204, 136, 23, 47, 71, 26, 236, 185, 1, 104, 37, 134, 161, + 239, 121, 82, 48, 77, 104, 2, 40, 109, 170, 209, 146, 155, 24, + 248, 218, 71, 207, 151, 212, 187, 160, 232, 122, 242, 111, 244, 4, + 32, 56, 235, 229, 40, 102, 23, 174, 177, 94, 182, 45, 107, 36, + 194, 164, 67, 222, 176, 207, 153, 177, 40, 21, 187, 199, 144, 207, + 66, 171, 223, 237, 59, 153, 40, 219, 69, 234, 123, 84, 122, 3, + 4, 89, 11, 92, 179, 186, 7, 7, 62, 44, 31, 108, 13, 151, + 238, 224, 3, 203, 149, 160, 152, 141, 64, 158, 57, 88, 40, 33, + 6, 165, 15, 179, 100, 213, 237, 65, 54, 151, 234, 88, 178, 194, + 50, 219, 168, 25, 180, 27, 42, 16, 102, 167, 177, 239, 246, 249, + 203, 224, 48, 253, 250, 82, 164, 160, 221, 170, 132, 38, 59, 70, + 90, 32, 254, 88, 83, 137, 196, 109, 74, 35, 191, 71, 162, 202, + 7, 71, 61, 55, 139, 171, 123, 244, 159, 25, 53, 56, 58, 25, + 6, 230, 90, 14, 221, 131, 171, 147, 41, 85, 234, 107, 133, 156, + 85, 168, 76, 7, 63, 253, 82, 154, 127, 34, 130, 93, 240, 125, + 121, 143, 69, 255, 26, 180, 211, 201, 91, 111, 152, 191, 22, 163, + 69, 210, 174, 190, 190, 46, 208, 90, 78, 39, 28, 116, 238, 57, + 240, 252, 219, 192, 207, 168, 22, 68, 205, 70, 167, 222, 114, 64, + 3, 115, 235, 7, 166, 39, 98, 76, 236, 81, 163, 96, 174, 162, + 33, 55, 192, 224, 126, 72, 95, 243, 83, 9, 13, 144, 134, 131, + 168, 184, 73, 187, 72, 228, 128, 103, 63, 39, 213, 137, 193, 24, + 184, 3, 99, 42, 219, 31, 44, 119, 243, 73, 80, 118, 254, 73, + 193, 125, 94, 161, 4, 183, 10, 77, 165, 84, 167, 184, 52, 237, + 236, 151, 83, 63, 136, 10, 10, 168, 82, 117, 193, 102, 207, 152, + 154, 49, 176, 91, 95, 115, 247, 184, 0, 154, 83, 232, 86, 164, + 115, 214, 228, 63, 218, 177, 101, 108, 160, 252, 68, 193, 228, 84, + 185, 165, 71, 108, 7, 92, 87, 189, 243, 80, 78, 126, 46, 3, + 136, 82, 102, 185, 28, 21, 136, 27, 149, 133, 32, 251, 80, 28, + 34, 63, 73, 61, 243, 156, 45, 143, 26, 156, 121, 187, 52, 152, + 120, 192, 131, 153, 51, 26, 59, 248, 203, 49, 86, 114, 58, 0, + 47, 15, 194, 62, 34, 24, 85, 143, 101, 255, 95, 109, 70, 210, + 94, 63, 94, 169, 166, 152, 41, 82, 44, 243, 177, 133, 75, 154, + 150, 159, 101, 244, 120, 212, 64, 51, 103, 202, 73, 27, 28, 40, + 224, 6, 200, 218, 189, 3, 200, 232, 209, 118, 4, 47, 217, 111, + 88, 241, 98, 156, 242, 224, 72, 137, 167, 129, 180, 222, 65, 158, + 94, 88, 34, 221, 252, 70, 154, 38, 13, 244, 178, 235, 46, 97, + 236, 123, 222, 221, 144, 78, 229, 100, 118, 186, 245, 199, 163, 6, + 121, 23, 158, 68, 64, 30, 138, 125, 176, 94, 60, 108, 108, 81, + 57, 79, 200, 77, 68, 17, 49, 52, 54, 215, 141, 6, 216, 98, + 111, 90, 227, 157, 199, 212, 195, 152, 168, 249, 254, 229, 161, 2, + 198, 23, 14, 76, 160, 222, 121, 230, 74, 188, 80, 67, 201, 159, + 242, 76, 92, 223, 99, 160, 212, 39, 153, 106, 177, 181, 159, 42, + 115, 210, 55, 9, 244, 27, 50, 113, 168, 102, 247, 134, 92, 73, + 2, 129, 47, 95, 4, 116, 100, 19, 111, 235, 130, 203, 117, 161, + 216, 27, 218, 173, 103, 70, 176, 116, 131, 174, 215, 127, 194, 232, + 21, 124, 188, 117, 144, 50, 94, 15, 112, 95, 25, 125, 4, 102, + 102, 134, 214, 187, 230, 77, 92, 161, 213, 106, 27, 96, 33, 123, + 123, 104, 188, 197, 190, 14, 14, 17, 67, 93, 254, 170, 253, 227, + 208, 80, 142, 232, 92, 233, 244, 158, 122, 180, 1, 30, 104, 79, + 150, 140, 18, 181, 138, 58, 175, 15, 177, 205, 17, 204, 12, 218, + 126, 173, 242, 204, 26, 86, 136, 218, 25, 138, 254, 184, 116, 154, + 122, 149, 13, 82, 88, 101, 99, 57, 248, 27, 222, 133, 136, 168, + 89, 21, 184, 43, 251, 97, 79, 8, 127, 227, 106, 167, 29, 65, + 17, 203, 177, 84, 64, 115, 220, 131, 14, 3, 51, 223, 47, 3, + 29, 93, 134, 249, 36, 166, 83, 112, 223, 66, 61, 48, 128, 153, + 250, 133, 235, 161, 166, 199, 43, 56, 50, 37, 63, 197, 195, 62, + 211, 75, 103, 47, 74, 224, 24, 34, 169, 28, 203, 210, 202, 160, + 109, 110, 51, 240, 127, 164, 160, 213, 192, 205, 117, 231, 89, 176, + 33, 79, 196, 181, 166, 125, 134, 68, 88, 9, 146, 98, 162, 194, + 214, 85, 55, 163, 5, 229, 222, 77, 7, 46, 146, 99, 133, 28, + 93, 145, 188, 15, 51, 240, 233, 141, 62, 56, 12, 22, 209, 124, + 4, 206, 140, 67, 54, 250, 31, 21, 62, 66, 247, 185, 95, 31, + 99, 234, 133, 234, 48, 78, 79, 97, 196, 20, 205, 60, 79, 24, + 75, 23, 75, 154, 96, 249, 68, 201, 152, 99, 82, 16, 70, 6, + 80, 8, 136, 122, 228, 161, 161, 177, 11, 158, 169, 113, 251, 164, + 26, 119, 135, 205, 248, 176, 132, 21, 184, 203, 106, 129, 26, 159, + 148, 187, 6, 250, 171, 159, 60, 245, 244, 59, 58, 195, 80, 168, + 48, 193, 252, 99, 203, 204, 91, 119, 163, 79, 235, 251, 73, 116, + 84, 236, 44, 126, 82, 249, 71, 164, 150, 239, 126, 240, 189, 142, + 193, 184, 76, 227, 42, 105, 50, 134, 236, 158, 133, 63, 93, 228, + 160, 73, 133, 182, 68, 47, 132, 79, 47, 215, 44, 236, 111, 0, + 5, 90, 19, 246, 213, 121, 151, 162, 20, 226, 69, 149, 109, 77, + 239, 247, 57, 213, 243, 13, 142, 73, 41, 176, 8, 201, 71, 154, + 203, 194, 28, 113, 242, 105, 27, 45, 136, 135, 55, 173, 185, 231, + 146, 151, 211, 49, 155, 178, 67, 181, 170, 95, 121, 116, 196, 213, + 209, 74, 202, 141, 122, 42, 81, 141, 208, 75, 132, 108, 107, 120, + 49, 168, 210, 139, 25, 141, 149, 251, 19, 65, 224, 4, 176, 160, + 45, 240, 7, 89, 49, 238, 98, 101, 97, 36, 76, 98, 126, 228, + 142, 253, 176, 134, 179, 247, 15, 74, 105, 107, 125, 194, 202, 5, + 152, 50, 82, 205, 225, 62, 0, 72, 255, 67, 56, 110, 46, 41, + 115, 90, 106, 168, 160, 42, 250, 163, 242, 100, 167, 131, 3, 137, + 192, 101, 35, 207, 88, 134, 229, 124, 42, 12, 217, 211, 248, 164, + 212, 139, 204, 50, 236, 37, 240, 180, 123, 43, 118, 76, 145, 66, + 215, 74, 35, 240, 64, 225, 68, 37, 129, 234, 45, 24, 242, 152, + 77, 235, 147, 209, 70, 33, 226, 71, 205, 200, 179, 200, 184, 155, + 81, 189, 250, 244, 116, 243, 138, 92, 191, 16, 203, 162, 131, 169, + 31, 209, 75, 255, 185, 121, 246, 192, 220, 196, 106, 189, 65, 171, + 104, 185, 146, 115, 156, 136, 104, 78, 83, 242, 140, 225, 228, 184, + 5, 204, 1, 14, 19, 26, 239, 98, 228, 20, 45, 55, 145, 211, + 225, 27, 136, 250, 140, 150, 27, 56, 41, 48, 203, 243, 133, 83, + 65, 130, 245, 247, 83, 168, 34, 24, 159, 214, 251, 255, 31, 201, + 119, 6, 153, 236, 185, 193, 102, 36, 72, 207, 226, 85, 193, 78, + 210, 146, 119, 41, 20, 18, 70, 249, 56, 175, 118, 169, 126, 221, + 64, 75, 54, 254, 185, 138, 54, 82, 199, 16, 40, 108, 108, 1, + 163, 163, 57, 8, 88, 89, 160, 239, 85, 155, 153, 236, 82, 158, + 211, 11, 230, 234, 84, 79, 175, 192, 195, 114, 97, 238, 150, 67, + 75, 83, 10, 135, 122, 112, 226, 14, 123, 240, 66, 49, 234, 94, + 121, 48, 179, 231, 26, 16, 255, 7, 225, 196, 25, 142, 97, 239, + 53, 55, 130, 250, 86, 19, 30, 43, 148, 102, 152, 81, 111, 40, + 154, 125, 254, 212, 89, 126, 73, 45, 214, 174, 227, 6, 229, 52, + 118, 202, 79, 60, 221, 124, 177, 216, 122, 237, 58, 198, 87, 97, + 24, 36, 139, 59, 158, 255, 120, 17, 211, 171, 146, 229, 3, 17, + 179, 119, 237, 135, 123, 144, 30, 242, 156, 140, 30, 54, 98, 79, + 179, 242, 36, 201, 31, 90, 132, 143, 234, 166, 36, 117, 59, 151, + 61, 198, 70, 2, 34, 63, 134, 233, 178, 54, 244, 134, 105, 132, + 241, 255, 248, 63, 219, 74, 149, 214, 230, 239, 115, 144, 7, 222, + 73, 149, 139, 139, 20, 216, 149, 56, 48, 189, 18, 250, 244, 11, + 69, 134, 33, 231, 0, 162, 210, 4, 140, 236, 36, 134, 29, 219, + 68, 188, 112, 42, 226, 102, 29, 116, 109, 194, 227, 129, 39, 134, + 236, 220, 144, 111, 75, 78, 232, 75, 234, 83, 7, 113, 100, 87, + 16, 199, 52, 161, 146, 116, 136, 5, 240, 26, 90, 77, 63, 214, + 180, 245, 62, 161, 212, 151, 108, 71, 23, 118, 139, 89, 188, 123, + 227, 88, 80, 234, 194, 116, 182, 217, 56, 139, 139, 88, 145, 177, + 67, 48, 100, 149, 68, 157, 41, 33, 111, 140, 66, 220, 236, 40, + 39, 229, 125, 253, 197, 144, 154, 215, 175, 208, 82, 129, 133, 180, + 22, 73, 182, 244, 194, 235, 234, 228, 57, 48, 104, 222, 171, 148, + 118, 101, 152, 86, 183, 34, 217, 215, 225, 32, 231, 151, 86, 98, + 112, 47, 193, 143, 68, 185, 180, 39, 130, 231, 24, 91, 246, 41, + 155, 144, 37, 22, 250, 137, 151, 238, 189, 178, 105, 247, 29, 81, + 224, 249, 230, 141, 101, 189, 149, 202, 83, 92, 226, 112, 183, 5, + 176, 157, 232, 114, 211, 55, 189, 103, 54, 48, 87, 202, 132, 2, + 251, 198, 105, 230, 34, 1, 155, 239, 137, 14, 157, 213, 54, 88, + 52, 46, 22, 8, 152, 43, 194, 84, 7, 227, 95, 77, 255, 48, + 50, 169, 127, 11, 76, 215, 40, 163, 207, 69, 194, 123, 111, 51, + 198, 188, 49, 31, 152, 245, 195, 48, 63, 170, 8, 46, 163, 194, + 147, 137, 163, 210, 87, 8, 98, 224, 126, 153, 140, 86, 26, 190, + 1, 188, 234, 57, 169, 38, 50, 64, 17, 5, 13, 129, 166, 236, + 165, 112, 0, 228, 216, 15, 22, 39, 69, 72, 113, 90, 18, 35, + 59, 56, 35, 103, 141, 76, 12, 53, 145, 150, 137, 90, 171, 30, + 206, 202, 51, 186, 140, 236, 105, 173, 180, 199, 77, 167, 80, 57, + 220, 65, 232, 72, 187, 87, 161, 237, 51, 53, 81, 206, 120, 101, + 135, 124, 95, 214, 49, 209, 58, 128, 44, 183, 182, 37, 237, 57, + 27, 9, 206, 13, 63, 26, 184, 174, 95, 91, 30, 131, 1, 152, + 57, 243, 120, 46, 26, 2, 48, 183, 38, 220, 194, 201, 189, 138, + 31, 75, 83, 158, 95, 178, 26, 229, 210, 101, 50, 18, 106, 254, + 29, 225, 137, 1, 194, 121, 143, 159, 141, 5, 49, 247, 74, 55, + 18, 223, 188, 178, 81, 193, 78, 229, 220, 105, 183, 169, 92, 118, + 145, 183, 42, 212, 66, 189, 108, 148, 175, 52, 114, 178, 63, 249, + 74, 140, 91, 122, 216, 198, 200, 162, 149, 222, 132, 249, 127, 127, + 214, 246, 26, 204, 251, 198, 48, 194, 1, 234, 232, 143, 251, 41, + 174, 51, 238, 140, 186, 7, 245, 178, 235, 220, 86, 119, 100, 107, + 118, 244, 250, 127, 152, 5, 11, 26, 249, 164, 60, 171, 13, 154, + 253, 77, 23, 49, 48, 73, 152, 224, 103, 189, 112, 116, 193, 240, + 120, 47, 57, 53, 209, 96, 60, 97, 196, 213, 116, 147, 212, 64, + 231, 207, 55, 30, 185, 122, 240, 28, 16, 156, 40, 46, 24, 247, + 255, 32, 75, 187, 172, 148, 90, 115, 212, 101, 69, 85, 15, 169, + 189, 127, 12, 156, 225, 151, 49, 27, 123, 140, 164, 250, 75, 67, + 237, 201, 59, 154, 147, 236, 47, 194, 167, 50, 87, 98, 164, 198, + 5, 191, 173, 132, 189, 251, 80, 92, 19, 243, 120, 141, 101, 32, + 53, 37, 7, 172, 68, 175, 100, 25, 32, 23, 32, 122, 6, 36, + 173, 164, 36, 33, 161, 137, 65, 131, 190, 94, 227, 47, 113, 49, + 105, 35, 59, 126, 115, 84, 119, 189, 140, 130, 250, 46, 40, 227, + 133, 250, 212, 183, 65, 175, 29, 64, 233, 173, 68, 100, 176, 40, + 19, 233, 116, 27, 138, 63, 35, 207, 200, 216, 24, 132, 81, 175, + 169, 16, 9, 114, 70, 145, 111, 88, 77, 118, 172, 159, 5, 93, + 54, 228, 59, 200, 96, 43, 196, 181, 48, 175, 8, 199, 163, 220, + 0, 216, 154, 233, 25, 134, 229, 131, 234, 182, 138, 242, 72, 72, + 58, 42, 126, 171, 81, 190, 5, 210, 165, 232, 66, 152, 70, 39, + 159, 107, 36, 89, 252, 75, 55, 47, 63, 85, 91, 212, 197, 77, + 57, 59, 92, 130, 93, 159, 92, 199, 88, 214, 98, 74, 12, 118, + 29, 155, 81, 232, 184, 238, 9, 94, 143, 0, 23, 178, 251, 111, + 14, 222, 34, 236, 207, 54, 47, 159, 160, 105, 30, 44, 205, 126, + 239, 38, 99, 105, 236, 202, 159, 63, 58, 237, 40, 223, 134, 138, + 9, 23, 178, 188, 205, 68, 134, 140, 76, 113, 140, 55, 99, 208, + 250, 46, 142, 79, 78, 114, 240, 37, 243, 141, 112, 108, 166, 229, + 58, 179, 17, 203, 20, 18, 95, 248, 186, 115, 140, 117, 249, 191, + 131, 19, 33, 120, 135, 126, 137, 66, 111, 198, 184, 204, 227, 154, + 70, 208, 75, 156, 175, 143, 246, 46, 137, 148, 21, 170, 12, 116, + 152, 10, 33, 53, 216, 183, 0, 183, 22, 51, 194, 247, 147, 242, + 205, 57, 167, 170, 204, 188, 210, 96, 32, 39, 161, 3, 91, 215, + 229, 164, 240, 116, 179, 181, 187, 56, 22, 31, 209, 234, 224, 159, + 222, 104, 53, 227, 138, 14, 97, 96, 73, 164, 129, 14, 106, 118, + 202, 228, 92, 25, 117, 83, 4, 6, 211, 240, 56, 48, 157, 201, + 166, 163, 61, 16, 75, 44, 158, 20, 70, 140, 77, 230, 31, 131, + 113, 113, 178, 215, 17, 238, 206, 165, 220, 5, 136, 43, 77, 113, + 185, 81, 41, 11, 67, 250, 196, 173, 5, 11, 217, 166, 88, 150, + 155, 59, 169, 15, 79, 238, 187, 7, 10, 24, 235, 40, 197, 123, + 243, 196, 119, 60, 217, 160, 101, 149, 255, 165, 233, 62, 177, 109, + 87, 113, 38, 197, 106, 42, 132, 105, 172, 61, 206, 207, 156, 33, + 143, 70, 100, 100, 253, 161, 96, 249, 25, 81, 14, 253, 239, 120, + 189, 91, 128, 249, 215, 114, 3, 118, 189, 0, 15, 147, 207, 120, + 210, 93, 86, 17, 114, 223, 43, 5, 126, 171, 214, 242, 155, 247, + 62, 120, 161, 78, 6, 155, 59, 164, 206, 246, 218, 131, 53, 126, + 184, 243, 207, 27, 157, 113, 250, 213, 44, 201, 5, 52, 16, 103, + 117, 0, 229, 168, 195, 225, 149, 9, 159, 202, 199, 182, 218, 187, + 59, 19, 112, 164, 248, 97, 146, 124, 38, 210, 74, 114, 225, 172, + 184, 25, 135, 107, 226, 99, 20, 154, 65, 115, 77, 197, 102, 25, + 165, 196, 41, 110, 240, 208, 75, 126, 223, 22, 235, 68, 55, 136, + 125, 198, 45, 67, 142, 251, 105, 230, 131, 206, 186, 251, 138, 138, + 241, 25, 235, 122, 117, 178, 77, 207, 220, 107, 184, 63, 96, 110, + 202, 195, 184, 252, 55, 126, 216, 179, 195, 91, 68, 92, 97, 31, + 169, 246, 51, 18, 207, 123, 106, 235, 117, 62, 88, 222, 150, 249, + 107, 224, 150, 53, 219, 81, 206, 209, 52, 234, 213, 14, 46, 236, + 215, 191, 5, 174, 136, 174, 54, 210, 62, 74, 183, 146, 132, 150, + 124, 187, 193, 66, 109, 36, 17, 184, 103, 121, 143, 191, 6, 116, + 111, 204, 82, 59, 189, 46, 156, 239, 197, 197, 142, 108, 74, 149, + 225, 2, 114, 187, 216, 60, 104, 243, 126, 5, 209, 58, 101, 193, + 206, 210, 136, 128, 211, 128, 20, 237, 38, 111, 58, 254, 244, 151, + 132, 148, 217, 12, 213, 110, 212, 241, 185, 244, 116, 190, 192, 206, + 181, 208, 251, 153, 103, 224, 251, 50, 231, 176, 36, 47, 137, 121, + 79, 213, 55, 215, 172, 135, 22, 215, 11, 79, 162, 135, 2, 86, + 20, 33, 210, 85, 149, 169, 203, 84, 230, 105, 130, 211, 218, 254, + 15, 241, 106, 85, 114, 71, 57, 93, 199, 9, 58, 61, 63, 165, + 84, 137, 211, 60, 170, 92, 20, 223, 14, 38, 135, 95, 74, 37, + 75, 16, 212, 222, 234, 6, 43, 168, 68, 159, 214, 11, 156, 30, + 187, 169, 169, 253, 132, 47, 201, 133, 107, 198, 203, 255, 212, 183, + 165, 8, 246, 79, 240, 183, 196, 161, 173, 236, 253, 106, 106, 116, + 167, 200, 94, 7, 228, 202, 236, 31, 222, 163, 213, 227, 182, 189, + 241, 60, 54, 151, 110, 130, 163, 59, 153, 28, 103, 191, 91, 101, + 82, 226, 179, 81, 115, 98, 192, 210, 254, 118, 110, 134, 21, 191, + 117, 142, 33, 82, 149, 247, 59, 60, 185, 188, 52, 102, 183, 14, + 168, 96, 182, 62, 107, 190, 211, 5, 85, 220, 202, 170, 189, 99, + 196, 158, 102, 94, 98, 247, 42, 180, 34, 224, 224, 155, 80, 197, + 58, 35, 60, 135, 29, 187, 177, 131, 255, 44, 148, 11, 228, 83, + 96, 61, 29, 84, 74, 142, 42, 68, 99, 217, 84, 113, 190, 242, + 39, 122, 235, 179, 21, 58, 65, 84, 121, 33, 4, 20, 154, 192, + 183, 195, 232, 245, 119, 129, 214, 237, 160, 195, 94, 255, 243, 21, + 89, 136, 61, 19, 159, 63, 154, 170, 12, 226, 21, 59, 243, 29, + 91, 35, 168, 201, 181, 232, 247, 31, 100, 213, 18, 135, 161, 192, + 60, 137, 160, 229, 108, 61, 115, 198, 115, 228, 97, 35, 77, 29, + 172, 213, 8, 112, 183, 66, 127, 175, 144, 103, 59, 25, 64, 96, + 149, 126, 63, 209, 237, 127, 230, 54, 14, 172, 243, 16, 165, 246, + 56, 173, 228, 252, 176, 121, 176, 208, 33, 161, 7, 219, 211, 232, + 26, 50, 249, 109, 189, 125, 175, 222, 138, 202, 76, 156, 228, 27, + 212, 237, 200, 27, 22, 229, 205, 156, 173, 108, 142, 101, 190, 233, + 234, 213, 208, 40, 144, 89, 42, 145, 95, 109, 165, 203, 187, 125, + 38, 48, 246, 17, 19, 177, 46, 196, 131, 186, 158, 158, 157, 249, + 50, 83, 245, 112, 181, 192, 8, 35, 78, 228, 110, 167, 189, 189, + 204, 170, 165, 225, 31, 195, 10, 245, 27, 162, 168, 179, 187, 236, + 82, 162, 57, 76, 27, 68, 22, 150, 29, 23, 105, 255, 23, 191, + 103, 73, 47, 245, 158, 91, 171, 114, 142, 184, 135, 252, 98, 133, + 240, 137, 105, 47, 23, 226, 99, 67, 227, 213, 12, 56, 4, 228, + 205, 166, 189, 50, 75, 166, 139, 22, 223, 217, 6, 114, 78, 88, + 52, 27, 104, 177, 219, 142, 244, 3, 187, 113, 216, 15, 36, 73, + 37, 88, 196, 54, 51, 1, 36, 57, 13, 108, 54, 27, 162, 118, + 25, 63, 138, 64, 167, 153, 219, 221, 22, 229, 58, 94, 36, 31, + 211, 103, 126, 19, 51, 70, 73, 90, 26, 176, 149, 243, 36, 123, + 245, 165, 180, 121, 16, 141, 152, 194, 82, 166, 55, 132, 128, 60, + 176, 36, 83, 248, 10, 162, 131, 252, 176, 253, 246, 61, 130, 87, + 194, 37, 68, 77, 220, 42, 232, 43, 118, 37, 188, 236, 119, 27, + 94, 211, 172, 46, 240, 183, 148, 233, 146, 96, 247, 121, 149, 244, + 8, 240, 248, 230, 142, 38, 44, 56, 204, 179, 79, 112, 133, 64, + 46, 158, 47, 117, 180, 188, 128, 202, 4, 250, 75, 73, 191, 186, + 242, 78, 108, 232, 223, 124, 255, 135, 92, 100, 83, 206, 23, 37, + 122, 212, 89, 72, 178, 34, 95, 1, 127, 68, 203, 50, 71, 199, + 215, 132, 122, 42, 61, 231, 241, 65, 242, 142, 223, 180, 154, 103, + 100, 162, 162, 234, 15, 246, 129, 165, 60, 69, 80, 155, 201, 243, + 88, 30, 141, 164, 28, 132, 198, 80, 145, 36, 25, 53, 85, 189, + 178, 252, 214, 167, 233, 199, 93, 125, 110, 235, 31, 156, 53, 62, + 75, 59, 187, 111, 17, 107, 159, 203, 153, 138, 124, 98, 235, 217, + 51, 93, 223, 114, 156, 242, 248, 147, 135, 18, 196, 197, 201, 61, + 48, 227, 140, 72, 158, 228, 9, 43, 203, 121, 111, 120, 127, 194, + 39, 64, 160, 37, 136, 191, 251, 181, 149, 238, 149, 248, 190, 176, + 209, 152, 254, 26, 53, 34, 2, 119, 105, 73, 48, 211, 39, 22, + 189, 186, 107, 250, 182, 215, 94, 83, 62, 173, 231, 135, 144, 15, + 15, 130, 174, 36, 111, 153, 219, 141, 224, 249, 59, 104, 164, 158, + 81, 151, 195, 122, 206, 67, 239, 169, 38, 93, 101, 52, 93, 88, + 14, 123, 107, 50, 0, 210, 234, 184, 42, 9, 120, 146, 23, 5, + 148, 206, 109, 208, 100, 204, 237, 123, 43, 178, 105, 202, 184, 195, + 134, 61, 191, 166, 95, 29, 188, 100, 240, 17, 246, 153, 44, 205, + 119, 71, 190, 239, 190, 55, 60, 43, 238, 24, 232, 16, 227, 54, + 178, 224, 185, 153, 184, 243, 209, 92, 119, 72, 80, 86, 95, 218, + 51, 125, 254, 135, 176, 5, 68, 138, 23, 255, 26, 49, 220, 106, + 0, 22, 67, 26, 183, 107, 34, 139, 94, 20, 15, 64, 146, 44, + 78, 165, 72, 197, 101, 185, 217, 111, 247, 127, 49, 191, 42, 38, + 216, 71, 203, 249, 98, 82, 54, 144, 11, 217, 24, 72, 197, 230, + 173, 82, 66, 49, 32, 20, 132, 201, 24, 116, 155, 131, 174, 17, + 149, 156, 124, 253, 21, 179, 75, 106, 6, 235, 120, 151, 151, 222, + 133, 98, 41, 14, 145, 68, 118, 127, 164, 237, 18, 223, 193, 161, + 58, 1, 41, 250, 25, 30, 249, 25, 39, 106, 198, 74, 145, 124, + 59, 18, 117, 166, 238, 7, 74, 7, 40, 126, 58, 13, 226, 15, + 89, 188, 198, 97, 178, 171, 118, 99, 237, 189, 42, 205, 248, 173, + 29, 251, 130, 107, 1, 91, 186, 99, 251, 169, 181, 145, 62, 184, + 7, 125, 226, 28, 0, 71, 243, 145, 48, 251, 14, 207, 121, 184, + 107, 233, 138, 101, 202, 201, 147, 183, 106, 34, 73, 142, 62, 51, + 222, 184, 164, 128, 152, 70, 228, 64, 251, 247, 226, 216, 187, 211, + 152, 1, 46, 83, 161, 29, 220, 51, 21, 128, 61, 220, 202, 154, + 104, 95, 196, 103, 147, 148, 185, 8, 144, 225, 192, 67, 44, 246, + 116, 124, 15, 111, 118, 219, 16, 139, 152, 220, 188, 37, 80, 181, + 109, 42, 219, 166, 70, 118, 28, 17, 198, 58, 206, 207, 223, 105, + 128, 1, 20, 2, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 13, 99, 108, 101, 97, 114, 116, + 111, 109, 97, 114, 107, 10, 128, 3, +}; diff --git a/Rendering/fonts/face_arial_italic.cxx b/Rendering/fonts/face_arial_italic.cxx new file mode 100644 index 0000000..2f45733 --- /dev/null +++ b/Rendering/fonts/face_arial_italic.cxx @@ -0,0 +1,2522 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Arial Italic +// URW Gothic L Book Oblique (uagko8a.pfb) +// Contributed by URW + +size_t face_arial_italic_buffer_length = 35156; + +unsigned char face_arial_italic_buffer[] = { + 128, 1, 102, 6, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 58, 32, 85, 82, + 87, 71, 111, 116, 104, 105, 99, 76, 45, 66, 111, 111, 107, 79, + 98, 108, 105, 32, 49, 46, 48, 53, 10, 37, 37, 67, 114, 101, + 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 87, 101, 100, + 32, 68, 101, 99, 32, 50, 50, 32, 49, 57, 57, 57, 10, 37, + 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 85, 82, + 87, 41, 43, 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, + 43, 43, 32, 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, + 118, 101, 108, 111, 112, 109, 101, 110, 116, 10, 37, 32, 40, 85, + 82, 87, 41, 43, 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, + 116, 32, 49, 57, 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, + 41, 43, 43, 32, 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, + 101, 118, 101, 108, 111, 112, 109, 101, 110, 116, 10, 37, 32, 83, + 101, 101, 32, 116, 104, 101, 32, 102, 105, 108, 101, 32, 80, 85, + 66, 76, 73, 67, 32, 40, 65, 108, 97, 100, 100, 105, 110, 32, + 70, 114, 101, 101, 32, 80, 117, 98, 108, 105, 99, 32, 76, 105, + 99, 101, 110, 115, 101, 41, 32, 102, 111, 114, 32, 108, 105, 99, + 101, 110, 115, 101, 32, 99, 111, 110, 100, 105, 116, 105, 111, 110, + 115, 46, 10, 37, 32, 65, 115, 32, 97, 32, 115, 112, 101, 99, + 105, 97, 108, 32, 101, 120, 99, 101, 112, 116, 105, 111, 110, 44, + 32, 112, 101, 114, 109, 105, 115, 115, 105, 111, 110, 32, 105, 115, + 32, 103, 114, 97, 110, 116, 101, 100, 32, 116, 111, 32, 105, 110, + 99, 108, 117, 100, 101, 32, 116, 104, 105, 115, 32, 102, 111, 110, + 116, 10, 37, 32, 112, 114, 111, 103, 114, 97, 109, 32, 105, 110, + 32, 97, 32, 80, 111, 115, 116, 115, 99, 114, 105, 112, 116, 32, + 111, 114, 32, 80, 68, 70, 32, 102, 105, 108, 101, 32, 116, 104, + 97, 116, 32, 99, 111, 110, 115, 105, 115, 116, 115, 32, 111, 102, + 32, 97, 32, 100, 111, 99, 117, 109, 101, 110, 116, 32, 116, 104, + 97, 116, 10, 37, 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, + 116, 101, 120, 116, 32, 116, 111, 32, 98, 101, 32, 100, 105, 115, + 112, 108, 97, 121, 101, 100, 32, 111, 114, 32, 112, 114, 105, 110, + 116, 101, 100, 32, 117, 115, 105, 110, 103, 32, 116, 104, 105, 115, + 32, 102, 111, 110, 116, 44, 32, 114, 101, 103, 97, 114, 100, 108, + 101, 115, 115, 10, 37, 32, 111, 102, 32, 116, 104, 101, 32, 99, + 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 114, 32, 108, + 105, 99, 101, 110, 115, 101, 32, 97, 112, 112, 108, 121, 105, 110, + 103, 32, 116, 111, 32, 116, 104, 101, 32, 100, 111, 99, 117, 109, + 101, 110, 116, 32, 105, 116, 115, 101, 108, 102, 46, 10, 49, 50, + 32, 100, 105, 99, 116, 32, 98, 101, 103, 105, 110, 10, 47, 70, + 111, 110, 116, 73, 110, 102, 111, 32, 49, 48, 32, 100, 105, 99, + 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, 110, 10, 47, 118, + 101, 114, 115, 105, 111, 110, 32, 40, 49, 46, 48, 53, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 78, 111, 116, 105, 99, 101, 32, 40, 40, 85, 82, 87, 41, 43, + 43, 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, + 68, 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, + 111, 112, 109, 101, 110, 116, 46, 32, 83, 101, 101, 32, 116, 104, + 101, 32, 102, 105, 108, 101, 32, 80, 85, 66, 76, 73, 67, 32, + 40, 65, 108, 97, 100, 100, 105, 110, 32, 70, 114, 101, 101, 32, + 80, 117, 98, 108, 105, 99, 32, 76, 105, 99, 101, 110, 115, 101, + 41, 32, 102, 111, 114, 32, 108, 105, 99, 101, 110, 115, 101, 32, + 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 46, 32, 65, 115, + 32, 97, 32, 115, 112, 101, 99, 105, 97, 108, 32, 101, 120, 99, + 101, 112, 116, 105, 111, 110, 44, 32, 112, 101, 114, 109, 105, 115, + 115, 105, 111, 110, 32, 105, 115, 32, 103, 114, 97, 110, 116, 101, + 100, 32, 116, 111, 32, 105, 110, 99, 108, 117, 100, 101, 32, 116, + 104, 105, 115, 32, 102, 111, 110, 116, 32, 112, 114, 111, 103, 114, + 97, 109, 32, 105, 110, 32, 97, 32, 80, 111, 115, 116, 115, 99, + 114, 105, 112, 116, 32, 111, 114, 32, 80, 68, 70, 32, 102, 105, + 108, 101, 32, 116, 104, 97, 116, 32, 99, 111, 110, 115, 105, 115, + 116, 115, 32, 111, 102, 32, 97, 32, 100, 111, 99, 117, 109, 101, + 110, 116, 32, 116, 104, 97, 116, 32, 99, 111, 110, 116, 97, 105, + 110, 115, 32, 116, 101, 120, 116, 32, 116, 111, 32, 98, 101, 32, + 100, 105, 115, 112, 108, 97, 121, 101, 100, 32, 111, 114, 32, 112, + 114, 105, 110, 116, 101, 100, 32, 117, 115, 105, 110, 103, 32, 116, + 104, 105, 115, 32, 102, 111, 110, 116, 44, 32, 114, 101, 103, 97, + 114, 100, 108, 101, 115, 115, 32, 111, 102, 32, 116, 104, 101, 32, + 99, 111, 110, 100, 105, 116, 105, 111, 110, 115, 32, 111, 114, 32, + 108, 105, 99, 101, 110, 115, 101, 32, 97, 112, 112, 108, 121, 105, + 110, 103, 32, 116, 111, 32, 116, 104, 101, 32, 100, 111, 99, 117, + 109, 101, 110, 116, 32, 105, 116, 115, 101, 108, 102, 46, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 67, 111, 112, + 121, 114, 105, 103, 104, 116, 32, 40, 85, 82, 87, 41, 43, 43, + 44, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, 57, + 57, 32, 98, 121, 32, 40, 85, 82, 87, 41, 43, 43, 32, 68, + 101, 115, 105, 103, 110, 32, 38, 32, 68, 101, 118, 101, 108, 111, + 112, 109, 101, 110, 116, 41, 32, 114, 101, 97, 100, 111, 110, 108, + 121, 32, 100, 101, 102, 10, 47, 70, 117, 108, 108, 78, 97, 109, + 101, 32, 40, 85, 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, + 76, 32, 66, 111, 111, 107, 32, 79, 98, 108, 105, 113, 117, 101, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 10, 47, 70, 97, 109, 105, 108, 121, 78, 97, 109, 101, 32, 40, + 85, 82, 87, 32, 71, 111, 116, 104, 105, 99, 32, 76, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 87, 101, 105, 103, 104, 116, 32, 40, 66, 111, 111, 107, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 10, 47, + 73, 116, 97, 108, 105, 99, 65, 110, 103, 108, 101, 32, 45, 49, + 48, 46, 53, 32, 100, 101, 102, 10, 47, 105, 115, 70, 105, 120, + 101, 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, 101, 32, + 100, 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, + 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 57, 54, 32, 100, + 101, 102, 10, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 84, + 104, 105, 99, 107, 110, 101, 115, 115, 32, 53, 56, 32, 100, 101, + 102, 10, 101, 110, 100, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 10, 47, 70, 111, 110, 116, 78, 97, 109, 101, + 32, 47, 85, 82, 87, 71, 111, 116, 104, 105, 99, 76, 45, 66, + 111, 111, 107, 79, 98, 108, 105, 32, 100, 101, 102, 10, 47, 80, + 97, 105, 110, 116, 84, 121, 112, 101, 32, 48, 32, 100, 101, 102, + 10, 47, 87, 77, 111, 100, 101, 32, 48, 32, 100, 101, 102, 10, + 47, 70, 111, 110, 116, 66, 66, 111, 120, 32, 123, 45, 49, 49, + 53, 32, 45, 50, 51, 50, 32, 49, 50, 55, 53, 32, 57, 55, + 50, 125, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, + 102, 10, 47, 70, 111, 110, 116, 84, 121, 112, 101, 32, 49, 32, + 100, 101, 102, 10, 47, 70, 111, 110, 116, 77, 97, 116, 114, 105, + 120, 32, 91, 48, 46, 48, 48, 49, 32, 48, 46, 48, 32, 48, + 46, 48, 32, 48, 46, 48, 48, 49, 32, 48, 46, 48, 32, 48, + 46, 48, 93, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, + 101, 102, 10, 47, 69, 110, 99, 111, 100, 105, 110, 103, 32, 83, + 116, 97, 110, 100, 97, 114, 100, 69, 110, 99, 111, 100, 105, 110, + 103, 32, 100, 101, 102, 10, 47, 85, 110, 105, 113, 117, 101, 73, + 68, 32, 53, 48, 49, 57, 53, 54, 48, 32, 100, 101, 102, 10, + 99, 117, 114, 114, 101, 110, 116, 100, 105, 99, 116, 32, 101, 110, + 100, 10, 99, 117, 114, 114, 101, 110, 116, 102, 105, 108, 101, 32, + 101, 101, 120, 101, 99, 13, 128, 2, 198, 128, 0, 0, 233, 141, + 9, 215, 96, 163, 194, 44, 241, 25, 249, 220, 105, 154, 34, 195, + 91, 91, 53, 237, 106, 162, 53, 147, 199, 109, 84, 202, 187, 94, + 148, 43, 247, 214, 221, 132, 241, 102, 75, 137, 105, 156, 116, 180, + 114, 222, 159, 142, 109, 249, 37, 246, 196, 242, 4, 233, 241, 198, + 57, 180, 219, 169, 136, 237, 42, 196, 25, 255, 43, 43, 222, 96, + 91, 142, 227, 38, 78, 221, 102, 65, 45, 79, 33, 198, 74, 197, + 34, 189, 252, 124, 85, 2, 249, 195, 243, 229, 89, 43, 59, 32, + 147, 211, 60, 155, 250, 237, 210, 212, 158, 137, 170, 186, 168, 50, + 226, 63, 6, 46, 145, 162, 80, 50, 81, 157, 24, 104, 129, 110, + 68, 180, 224, 116, 119, 149, 0, 61, 121, 48, 41, 157, 110, 30, + 42, 91, 254, 13, 89, 93, 201, 126, 20, 9, 137, 206, 129, 216, + 215, 248, 82, 255, 156, 220, 122, 27, 27, 89, 140, 105, 19, 29, + 238, 0, 91, 65, 88, 5, 161, 109, 137, 109, 248, 54, 94, 228, + 44, 236, 52, 33, 125, 213, 255, 45, 43, 0, 99, 74, 190, 150, + 32, 7, 131, 173, 135, 6, 198, 51, 96, 27, 98, 102, 63, 127, + 231, 23, 16, 107, 156, 49, 147, 231, 150, 30, 113, 45, 21, 28, + 147, 182, 46, 121, 228, 65, 27, 212, 125, 221, 187, 91, 10, 16, + 96, 55, 254, 134, 43, 61, 162, 41, 224, 12, 57, 9, 244, 76, + 63, 231, 100, 225, 113, 122, 78, 9, 154, 54, 129, 106, 71, 231, + 209, 213, 178, 253, 110, 1, 230, 159, 45, 31, 40, 39, 252, 237, + 253, 28, 246, 125, 73, 170, 198, 126, 194, 4, 107, 7, 192, 67, + 121, 36, 12, 240, 18, 69, 68, 35, 108, 38, 4, 34, 10, 63, + 146, 155, 166, 39, 207, 8, 65, 145, 192, 141, 21, 167, 121, 241, + 135, 219, 94, 141, 23, 78, 151, 248, 5, 220, 124, 14, 178, 1, + 77, 241, 34, 170, 41, 22, 242, 119, 65, 105, 34, 127, 90, 145, + 119, 250, 223, 148, 91, 125, 235, 157, 108, 77, 111, 253, 186, 254, + 87, 148, 86, 6, 101, 152, 222, 105, 221, 37, 233, 240, 200, 70, + 43, 54, 3, 102, 224, 94, 138, 118, 183, 204, 199, 59, 106, 133, + 87, 213, 230, 120, 54, 201, 156, 73, 2, 129, 126, 25, 113, 121, + 169, 104, 198, 202, 142, 122, 170, 13, 195, 249, 7, 146, 45, 60, + 242, 228, 169, 44, 58, 163, 99, 150, 46, 7, 237, 234, 60, 75, + 234, 168, 130, 127, 44, 163, 232, 87, 168, 195, 57, 31, 57, 171, + 140, 83, 131, 251, 194, 14, 128, 157, 10, 194, 212, 107, 157, 123, + 195, 32, 111, 180, 47, 93, 52, 66, 247, 228, 166, 201, 99, 161, + 190, 112, 203, 221, 70, 46, 41, 169, 123, 82, 68, 147, 6, 139, + 97, 79, 61, 136, 52, 224, 169, 209, 116, 155, 208, 238, 12, 150, + 139, 151, 201, 9, 207, 147, 115, 179, 125, 152, 152, 90, 57, 98, + 210, 72, 157, 147, 121, 59, 140, 44, 190, 116, 46, 80, 243, 102, + 127, 166, 72, 242, 135, 5, 90, 146, 127, 46, 251, 202, 67, 102, + 9, 108, 81, 156, 93, 221, 176, 7, 10, 250, 156, 192, 124, 228, + 223, 59, 64, 153, 21, 84, 67, 84, 180, 222, 204, 20, 140, 121, + 11, 14, 232, 33, 34, 39, 116, 71, 2, 181, 35, 235, 112, 232, + 230, 65, 240, 117, 138, 231, 67, 57, 221, 41, 2, 47, 100, 8, + 113, 150, 7, 206, 70, 53, 151, 108, 110, 143, 248, 22, 136, 69, + 155, 9, 88, 81, 137, 21, 23, 213, 143, 1, 160, 239, 126, 136, + 21, 250, 129, 230, 226, 126, 43, 41, 113, 205, 9, 152, 93, 56, + 11, 164, 13, 159, 169, 140, 12, 0, 134, 41, 44, 143, 48, 236, + 157, 154, 90, 12, 249, 82, 234, 13, 156, 65, 118, 213, 41, 42, + 20, 194, 66, 8, 178, 123, 2, 27, 147, 219, 30, 67, 81, 48, + 41, 108, 233, 5, 78, 180, 36, 172, 51, 88, 115, 248, 217, 144, + 103, 144, 8, 79, 250, 111, 233, 208, 239, 145, 106, 26, 235, 5, + 30, 72, 32, 193, 47, 228, 126, 49, 212, 50, 87, 170, 225, 128, + 27, 191, 52, 209, 11, 22, 35, 213, 17, 175, 138, 177, 125, 209, + 11, 58, 170, 126, 118, 238, 36, 164, 203, 185, 160, 165, 245, 54, + 229, 147, 144, 74, 114, 162, 10, 31, 124, 240, 178, 163, 173, 2, + 221, 255, 212, 111, 188, 53, 137, 197, 209, 249, 106, 90, 221, 228, + 128, 142, 7, 230, 104, 198, 163, 27, 165, 65, 155, 54, 220, 60, + 9, 26, 208, 208, 3, 92, 180, 158, 141, 205, 177, 210, 250, 72, + 83, 103, 3, 157, 179, 135, 244, 200, 88, 145, 126, 49, 18, 134, + 176, 191, 244, 226, 95, 202, 108, 106, 53, 98, 96, 96, 141, 112, + 215, 221, 96, 95, 15, 150, 42, 35, 59, 40, 78, 187, 96, 182, + 45, 120, 107, 63, 23, 147, 166, 16, 90, 156, 82, 95, 59, 136, + 19, 53, 14, 160, 149, 105, 206, 49, 142, 33, 193, 26, 151, 127, + 15, 24, 251, 238, 130, 178, 62, 52, 250, 100, 21, 239, 17, 112, + 122, 126, 219, 175, 178, 59, 46, 111, 136, 32, 80, 72, 217, 235, + 166, 221, 229, 210, 66, 149, 198, 131, 75, 54, 92, 57, 244, 245, + 107, 116, 180, 226, 119, 66, 39, 44, 207, 24, 203, 168, 154, 211, + 204, 51, 107, 192, 18, 253, 38, 134, 186, 58, 48, 9, 19, 108, + 201, 26, 142, 144, 115, 18, 178, 12, 61, 31, 90, 5, 16, 41, + 107, 15, 149, 105, 127, 129, 142, 161, 3, 241, 118, 116, 27, 232, + 164, 196, 188, 166, 185, 11, 74, 92, 94, 170, 20, 180, 60, 121, + 44, 212, 101, 9, 21, 111, 134, 152, 243, 177, 213, 237, 231, 87, + 245, 210, 103, 244, 151, 127, 49, 68, 160, 2, 86, 115, 108, 255, + 139, 81, 82, 190, 148, 52, 162, 153, 127, 235, 125, 105, 192, 248, + 97, 228, 41, 183, 198, 203, 89, 132, 130, 81, 67, 143, 5, 179, + 234, 31, 238, 63, 73, 35, 119, 8, 151, 68, 190, 171, 17, 102, + 108, 255, 73, 209, 186, 197, 243, 249, 231, 5, 40, 36, 144, 123, + 34, 141, 75, 154, 107, 14, 243, 64, 185, 204, 28, 63, 195, 96, + 114, 75, 83, 21, 170, 90, 180, 93, 12, 114, 217, 124, 145, 70, + 235, 199, 217, 244, 28, 169, 37, 160, 1, 251, 84, 237, 217, 82, + 28, 6, 111, 63, 168, 66, 185, 223, 100, 148, 110, 80, 252, 252, + 80, 223, 29, 239, 91, 117, 29, 59, 68, 200, 196, 104, 117, 159, + 114, 192, 132, 54, 135, 96, 52, 245, 200, 83, 73, 172, 192, 114, + 4, 103, 230, 142, 44, 199, 31, 213, 18, 52, 156, 32, 233, 209, + 139, 217, 78, 176, 73, 151, 18, 126, 244, 137, 220, 34, 158, 157, + 101, 159, 43, 149, 35, 52, 143, 165, 88, 239, 141, 14, 31, 83, + 159, 112, 151, 208, 50, 204, 14, 37, 201, 120, 214, 44, 242, 98, + 206, 5, 25, 237, 250, 43, 174, 25, 81, 59, 220, 41, 176, 156, + 44, 132, 246, 74, 70, 0, 252, 108, 74, 8, 150, 8, 192, 131, + 15, 118, 248, 77, 60, 105, 242, 135, 105, 127, 185, 114, 206, 36, + 223, 86, 172, 232, 62, 178, 235, 174, 51, 9, 132, 95, 99, 109, + 53, 107, 41, 23, 177, 234, 92, 244, 178, 131, 244, 202, 161, 194, + 58, 87, 123, 70, 240, 240, 201, 76, 209, 176, 143, 150, 253, 159, + 85, 146, 64, 233, 198, 146, 64, 114, 89, 46, 21, 225, 188, 120, + 159, 168, 62, 31, 218, 250, 127, 3, 106, 128, 228, 58, 68, 10, + 152, 9, 145, 98, 106, 104, 114, 80, 66, 16, 98, 219, 121, 59, + 240, 201, 141, 126, 64, 187, 151, 121, 111, 204, 172, 72, 217, 82, + 141, 48, 149, 205, 149, 82, 119, 208, 168, 247, 138, 109, 48, 148, + 212, 131, 157, 116, 139, 251, 182, 243, 99, 0, 20, 241, 90, 210, + 62, 76, 142, 80, 22, 144, 208, 217, 41, 131, 58, 106, 126, 67, + 98, 116, 148, 207, 131, 34, 200, 102, 27, 230, 87, 52, 225, 214, + 59, 92, 166, 18, 14, 235, 41, 156, 39, 97, 153, 37, 54, 124, + 102, 66, 226, 16, 141, 161, 203, 94, 167, 161, 8, 194, 146, 93, + 236, 97, 28, 182, 219, 162, 6, 120, 143, 43, 218, 62, 233, 151, + 63, 57, 112, 27, 101, 242, 112, 153, 139, 224, 185, 175, 179, 242, + 46, 5, 196, 133, 228, 41, 101, 242, 88, 75, 114, 154, 29, 223, + 194, 34, 26, 135, 175, 146, 184, 143, 155, 68, 72, 100, 239, 53, + 101, 251, 230, 74, 131, 31, 40, 252, 35, 164, 199, 61, 4, 47, + 248, 117, 16, 6, 138, 181, 255, 99, 83, 108, 195, 119, 199, 114, + 180, 28, 138, 168, 20, 48, 83, 57, 33, 128, 155, 96, 39, 237, + 155, 126, 56, 179, 227, 227, 112, 151, 121, 155, 93, 183, 88, 125, + 162, 190, 135, 5, 15, 138, 232, 234, 73, 155, 79, 234, 162, 228, + 99, 123, 64, 124, 17, 198, 28, 34, 81, 240, 173, 252, 100, 200, + 109, 70, 73, 185, 68, 38, 35, 2, 36, 191, 138, 72, 97, 184, + 192, 21, 68, 199, 108, 146, 34, 61, 243, 164, 60, 130, 228, 230, + 177, 177, 119, 209, 118, 46, 102, 187, 38, 95, 108, 30, 12, 115, + 249, 156, 5, 96, 69, 160, 54, 159, 247, 109, 187, 128, 55, 84, + 46, 208, 196, 11, 140, 219, 37, 151, 40, 25, 8, 133, 200, 46, + 98, 197, 117, 137, 98, 166, 80, 159, 236, 103, 104, 35, 146, 19, + 16, 215, 5, 238, 203, 25, 13, 42, 198, 15, 217, 127, 61, 255, + 59, 112, 152, 10, 131, 144, 102, 133, 16, 50, 170, 234, 113, 120, + 213, 164, 76, 212, 177, 176, 81, 102, 22, 51, 139, 53, 7, 168, + 84, 53, 247, 37, 52, 130, 103, 221, 226, 177, 37, 245, 229, 210, + 107, 63, 78, 10, 227, 159, 166, 152, 180, 133, 93, 203, 243, 189, + 211, 13, 155, 93, 119, 112, 58, 156, 181, 67, 106, 175, 63, 7, + 92, 233, 184, 143, 104, 182, 151, 130, 10, 207, 20, 237, 19, 146, + 64, 43, 55, 213, 56, 9, 28, 195, 116, 151, 232, 97, 190, 235, + 231, 123, 243, 128, 232, 211, 108, 167, 232, 48, 129, 228, 51, 124, + 26, 27, 231, 41, 140, 244, 231, 12, 213, 251, 192, 220, 34, 191, + 183, 9, 244, 5, 98, 208, 10, 189, 122, 14, 174, 150, 93, 174, + 1, 37, 64, 217, 45, 55, 207, 105, 230, 245, 198, 219, 251, 11, + 178, 91, 177, 57, 97, 239, 59, 34, 181, 34, 106, 60, 230, 110, + 248, 41, 164, 201, 249, 214, 229, 163, 197, 186, 90, 83, 170, 36, + 62, 83, 158, 89, 253, 127, 189, 10, 138, 38, 218, 216, 191, 93, + 121, 160, 29, 239, 213, 75, 231, 137, 217, 191, 213, 105, 190, 192, + 142, 167, 255, 46, 208, 214, 202, 226, 57, 6, 69, 38, 97, 102, + 249, 5, 172, 120, 99, 104, 72, 84, 159, 116, 150, 88, 241, 129, + 78, 87, 25, 255, 246, 226, 213, 204, 58, 115, 86, 61, 2, 236, + 154, 38, 233, 48, 38, 71, 202, 250, 77, 195, 214, 95, 118, 237, + 121, 129, 66, 182, 231, 71, 42, 117, 178, 190, 127, 97, 125, 167, + 84, 137, 98, 212, 139, 10, 15, 54, 175, 146, 142, 110, 181, 108, + 4, 135, 245, 193, 81, 33, 226, 141, 37, 253, 34, 31, 141, 140, + 115, 110, 170, 215, 112, 62, 79, 77, 207, 236, 60, 235, 10, 2, + 89, 135, 248, 143, 89, 22, 24, 193, 73, 238, 44, 101, 187, 89, + 59, 135, 59, 38, 74, 26, 49, 45, 92, 170, 226, 250, 72, 151, + 172, 146, 192, 115, 51, 58, 198, 197, 145, 41, 118, 111, 233, 84, + 224, 215, 178, 243, 242, 73, 38, 33, 100, 143, 72, 204, 65, 62, + 222, 14, 207, 245, 6, 178, 10, 72, 134, 106, 187, 129, 157, 84, + 23, 60, 152, 122, 198, 146, 152, 72, 23, 77, 194, 48, 42, 215, + 221, 197, 121, 246, 112, 102, 77, 211, 195, 145, 22, 159, 141, 193, + 212, 6, 65, 136, 88, 111, 183, 251, 99, 70, 30, 215, 100, 181, + 48, 210, 203, 142, 99, 66, 73, 79, 226, 27, 246, 35, 102, 12, + 58, 95, 197, 174, 98, 110, 252, 0, 235, 133, 63, 133, 122, 85, + 179, 127, 117, 110, 50, 153, 178, 96, 178, 187, 7, 38, 145, 180, + 130, 96, 53, 69, 78, 57, 135, 24, 236, 210, 28, 130, 100, 33, + 70, 92, 22, 216, 87, 238, 239, 99, 43, 175, 194, 166, 100, 23, + 112, 245, 233, 247, 92, 164, 162, 221, 144, 158, 63, 188, 107, 253, + 35, 230, 111, 194, 66, 66, 92, 109, 228, 235, 127, 108, 120, 98, + 1, 36, 123, 159, 108, 166, 34, 113, 76, 212, 74, 4, 206, 41, + 59, 10, 58, 190, 97, 87, 58, 72, 232, 235, 181, 224, 99, 222, + 108, 104, 32, 224, 74, 122, 181, 194, 15, 44, 242, 125, 47, 28, + 194, 223, 220, 250, 149, 15, 228, 175, 174, 169, 189, 206, 120, 113, + 219, 171, 68, 34, 142, 88, 115, 193, 159, 207, 171, 154, 191, 99, + 242, 178, 109, 250, 223, 209, 113, 122, 145, 98, 66, 3, 188, 153, + 52, 9, 220, 5, 10, 228, 139, 150, 114, 83, 16, 91, 178, 120, + 133, 16, 102, 2, 237, 7, 198, 82, 134, 98, 178, 71, 35, 68, + 128, 53, 167, 137, 184, 143, 66, 66, 69, 151, 171, 188, 120, 40, + 125, 134, 10, 109, 7, 93, 149, 126, 82, 96, 212, 234, 95, 252, + 79, 212, 182, 94, 193, 110, 4, 157, 46, 102, 69, 35, 231, 128, + 169, 206, 181, 169, 139, 29, 50, 245, 102, 235, 250, 195, 217, 10, + 169, 48, 212, 96, 27, 192, 229, 87, 40, 110, 212, 34, 108, 176, + 52, 209, 242, 97, 160, 252, 180, 241, 204, 137, 153, 151, 16, 95, + 28, 221, 13, 225, 117, 91, 137, 114, 202, 89, 140, 40, 60, 22, + 254, 156, 90, 62, 111, 20, 255, 161, 224, 46, 159, 47, 6, 68, + 127, 55, 242, 50, 180, 23, 170, 38, 226, 251, 106, 172, 160, 113, + 133, 6, 30, 169, 110, 72, 14, 138, 98, 65, 175, 206, 20, 97, + 23, 69, 241, 181, 220, 85, 136, 254, 244, 9, 137, 146, 147, 145, + 240, 15, 33, 234, 190, 136, 144, 119, 115, 107, 109, 32, 186, 129, + 122, 180, 156, 108, 99, 199, 175, 185, 173, 16, 24, 242, 69, 243, + 58, 225, 77, 14, 217, 183, 147, 95, 129, 125, 71, 255, 198, 132, + 188, 138, 211, 11, 22, 167, 229, 164, 152, 157, 46, 161, 237, 113, + 233, 236, 106, 135, 43, 254, 178, 79, 79, 82, 162, 144, 135, 163, + 232, 58, 215, 37, 8, 156, 142, 120, 54, 194, 157, 177, 123, 121, + 15, 243, 95, 97, 37, 62, 248, 197, 56, 155, 199, 180, 221, 183, + 84, 74, 115, 230, 29, 178, 48, 50, 115, 107, 34, 74, 103, 170, + 160, 116, 197, 123, 166, 162, 112, 30, 21, 248, 16, 201, 119, 249, + 194, 132, 135, 217, 73, 124, 202, 191, 148, 157, 149, 191, 50, 168, + 19, 114, 91, 232, 132, 99, 152, 177, 239, 42, 9, 80, 167, 5, + 112, 58, 63, 10, 6, 34, 175, 117, 138, 78, 222, 49, 227, 122, + 254, 156, 118, 234, 180, 86, 147, 103, 152, 165, 20, 3, 49, 162, + 49, 68, 72, 23, 97, 208, 202, 213, 210, 67, 239, 231, 234, 30, + 163, 162, 122, 183, 249, 5, 52, 74, 135, 80, 171, 36, 56, 7, + 70, 208, 225, 255, 126, 224, 133, 184, 142, 240, 65, 172, 79, 112, + 83, 144, 146, 2, 151, 13, 176, 83, 187, 113, 156, 233, 178, 83, + 119, 52, 100, 164, 72, 77, 34, 69, 163, 142, 178, 11, 111, 7, + 119, 205, 180, 166, 116, 238, 152, 34, 78, 72, 186, 23, 240, 61, + 90, 239, 220, 197, 103, 227, 164, 193, 83, 51, 197, 105, 171, 239, + 43, 136, 93, 225, 152, 22, 164, 165, 42, 199, 229, 83, 103, 121, + 81, 208, 175, 135, 174, 33, 121, 224, 52, 173, 101, 8, 1, 42, + 224, 6, 8, 8, 224, 70, 125, 78, 217, 152, 163, 155, 60, 227, + 154, 122, 176, 67, 46, 243, 111, 8, 169, 68, 112, 225, 74, 156, + 220, 66, 10, 51, 230, 121, 57, 111, 164, 11, 28, 220, 150, 121, + 153, 48, 73, 85, 232, 58, 6, 30, 10, 255, 93, 73, 178, 13, + 154, 143, 66, 13, 20, 99, 61, 111, 113, 136, 252, 19, 76, 225, + 174, 117, 85, 158, 194, 144, 182, 211, 139, 120, 63, 66, 93, 61, + 237, 231, 203, 126, 98, 37, 189, 218, 20, 118, 2, 247, 73, 16, + 64, 195, 44, 3, 147, 142, 184, 107, 208, 240, 219, 227, 151, 82, + 156, 94, 210, 87, 63, 220, 105, 158, 134, 177, 173, 33, 162, 151, + 198, 159, 231, 252, 215, 13, 53, 153, 210, 116, 28, 77, 94, 68, + 48, 120, 185, 234, 201, 164, 180, 184, 137, 184, 236, 205, 65, 167, + 182, 49, 243, 250, 40, 177, 198, 179, 166, 159, 215, 11, 35, 79, + 119, 206, 108, 107, 42, 193, 214, 171, 30, 120, 118, 59, 107, 155, + 144, 114, 33, 6, 127, 75, 137, 157, 4, 101, 182, 157, 129, 222, + 89, 177, 153, 125, 58, 13, 237, 187, 184, 145, 156, 13, 225, 68, + 73, 187, 150, 164, 224, 66, 82, 151, 183, 132, 87, 119, 196, 219, + 230, 58, 135, 236, 65, 231, 207, 81, 223, 245, 191, 203, 127, 33, + 246, 71, 8, 178, 241, 123, 150, 124, 250, 35, 247, 80, 15, 33, + 141, 160, 177, 115, 212, 48, 30, 4, 219, 178, 139, 17, 235, 30, + 255, 213, 124, 192, 150, 191, 129, 239, 51, 91, 68, 66, 241, 25, + 147, 171, 122, 45, 164, 126, 29, 190, 129, 3, 147, 100, 41, 179, + 80, 119, 11, 166, 109, 239, 128, 166, 230, 39, 60, 136, 245, 99, + 164, 6, 193, 13, 238, 248, 49, 166, 143, 170, 197, 9, 190, 11, + 40, 17, 78, 91, 10, 122, 58, 0, 168, 72, 215, 70, 171, 67, + 2, 222, 3, 5, 187, 170, 187, 253, 15, 96, 145, 245, 135, 43, + 184, 103, 122, 172, 104, 230, 178, 248, 99, 97, 214, 175, 122, 125, + 184, 16, 211, 227, 11, 141, 50, 250, 249, 239, 169, 124, 95, 168, + 23, 130, 232, 72, 205, 239, 4, 55, 45, 168, 11, 152, 37, 31, + 145, 25, 183, 183, 23, 235, 143, 38, 181, 205, 16, 105, 31, 185, + 43, 49, 28, 53, 213, 101, 250, 33, 212, 63, 60, 182, 186, 92, + 26, 71, 151, 158, 193, 242, 177, 95, 83, 31, 228, 251, 171, 185, + 87, 199, 219, 154, 163, 60, 241, 216, 84, 86, 81, 234, 119, 110, + 4, 153, 30, 163, 241, 250, 138, 199, 45, 19, 1, 104, 177, 97, + 100, 75, 90, 11, 248, 36, 4, 163, 106, 254, 116, 9, 51, 107, + 22, 88, 209, 133, 140, 244, 174, 6, 239, 184, 92, 158, 175, 133, + 142, 54, 166, 12, 4, 85, 33, 136, 205, 84, 57, 228, 215, 142, + 18, 243, 56, 107, 166, 36, 19, 166, 211, 42, 227, 229, 26, 116, + 30, 112, 240, 76, 229, 247, 213, 5, 91, 66, 107, 28, 234, 119, + 224, 225, 207, 229, 187, 202, 179, 115, 19, 102, 195, 105, 108, 98, + 184, 215, 177, 223, 156, 119, 112, 187, 149, 48, 24, 161, 158, 69, + 42, 191, 254, 65, 13, 236, 83, 126, 231, 12, 149, 10, 35, 184, + 46, 207, 80, 55, 96, 143, 61, 211, 194, 101, 155, 25, 108, 34, + 70, 88, 39, 232, 160, 181, 94, 198, 37, 120, 60, 252, 252, 169, + 218, 228, 226, 124, 67, 73, 37, 236, 145, 217, 33, 56, 125, 102, + 186, 151, 49, 216, 242, 122, 230, 154, 99, 229, 155, 181, 160, 116, + 199, 139, 146, 200, 87, 55, 163, 138, 3, 155, 177, 84, 15, 46, + 159, 224, 175, 229, 110, 176, 50, 77, 222, 235, 76, 170, 109, 14, + 45, 183, 169, 147, 155, 41, 224, 105, 17, 20, 243, 59, 230, 247, + 198, 232, 10, 209, 63, 168, 88, 188, 182, 172, 240, 167, 47, 247, + 36, 178, 77, 68, 237, 30, 61, 63, 118, 108, 184, 95, 130, 214, + 225, 120, 230, 110, 95, 196, 130, 192, 111, 56, 58, 202, 142, 213, + 33, 90, 44, 68, 219, 145, 22, 180, 232, 203, 237, 47, 184, 59, + 214, 223, 77, 127, 248, 213, 100, 135, 119, 144, 7, 234, 46, 233, + 40, 202, 160, 41, 96, 213, 253, 88, 153, 26, 49, 149, 233, 238, + 82, 26, 90, 114, 28, 175, 232, 62, 193, 81, 5, 33, 253, 170, + 212, 144, 224, 142, 50, 150, 3, 40, 228, 158, 149, 14, 169, 24, + 143, 28, 241, 43, 97, 73, 29, 108, 169, 203, 214, 211, 60, 83, + 88, 5, 173, 124, 68, 11, 107, 72, 156, 240, 156, 164, 115, 253, + 17, 163, 104, 137, 15, 226, 31, 34, 74, 227, 19, 33, 116, 213, + 205, 168, 80, 100, 254, 168, 209, 92, 18, 209, 27, 135, 43, 91, + 180, 216, 32, 177, 219, 78, 34, 240, 15, 29, 78, 178, 164, 237, + 213, 178, 30, 50, 138, 25, 188, 186, 246, 17, 178, 226, 155, 187, + 144, 147, 253, 185, 153, 238, 57, 204, 43, 182, 172, 40, 23, 152, + 129, 242, 109, 84, 113, 48, 211, 32, 154, 188, 2, 250, 110, 234, + 12, 64, 183, 106, 127, 227, 252, 131, 181, 140, 47, 234, 245, 71, + 53, 1, 153, 1, 123, 24, 12, 186, 146, 242, 68, 179, 124, 187, + 119, 55, 17, 62, 0, 77, 193, 227, 150, 189, 161, 221, 168, 14, + 60, 99, 164, 46, 146, 189, 59, 9, 140, 206, 83, 223, 102, 219, + 137, 128, 167, 93, 110, 181, 237, 253, 126, 173, 244, 121, 196, 113, + 254, 36, 5, 119, 62, 255, 45, 116, 220, 11, 149, 27, 100, 31, + 167, 52, 201, 204, 42, 166, 195, 208, 254, 77, 218, 147, 108, 198, + 18, 39, 245, 175, 80, 69, 83, 125, 253, 234, 176, 56, 57, 179, + 77, 194, 252, 184, 22, 11, 51, 166, 189, 8, 64, 20, 211, 245, + 205, 222, 139, 106, 67, 197, 7, 186, 179, 85, 91, 38, 83, 152, + 51, 188, 108, 246, 64, 88, 164, 3, 204, 99, 202, 167, 10, 223, + 220, 37, 224, 151, 10, 26, 132, 46, 0, 222, 198, 169, 213, 83, + 124, 152, 242, 159, 47, 130, 28, 40, 236, 212, 52, 15, 106, 12, + 85, 162, 5, 245, 154, 51, 78, 248, 61, 151, 87, 111, 213, 173, + 49, 230, 162, 39, 99, 32, 214, 14, 15, 43, 151, 241, 18, 89, + 110, 84, 132, 138, 149, 139, 173, 47, 138, 196, 138, 186, 171, 39, + 115, 58, 137, 59, 145, 24, 178, 178, 147, 159, 101, 243, 94, 251, + 22, 18, 151, 28, 37, 59, 90, 5, 91, 144, 105, 208, 92, 13, + 119, 109, 191, 103, 88, 56, 194, 16, 117, 176, 142, 202, 202, 74, + 22, 35, 5, 197, 250, 165, 165, 222, 181, 52, 162, 161, 87, 121, + 89, 31, 108, 160, 28, 165, 20, 166, 163, 30, 181, 185, 201, 58, + 45, 30, 215, 6, 7, 23, 34, 249, 95, 108, 234, 70, 66, 0, + 77, 199, 51, 63, 112, 53, 219, 73, 32, 240, 184, 233, 108, 161, + 23, 238, 174, 244, 248, 81, 213, 196, 40, 199, 26, 185, 46, 146, + 205, 167, 130, 200, 202, 70, 172, 210, 94, 113, 193, 10, 88, 97, + 207, 117, 73, 249, 204, 201, 135, 27, 143, 203, 253, 206, 122, 65, + 229, 21, 106, 224, 234, 49, 117, 136, 63, 123, 100, 190, 197, 5, + 82, 171, 247, 13, 25, 62, 31, 85, 141, 213, 53, 46, 43, 50, + 217, 3, 21, 234, 74, 62, 5, 237, 191, 22, 12, 3, 206, 73, + 126, 35, 212, 29, 129, 121, 114, 126, 71, 194, 158, 90, 106, 203, + 153, 113, 116, 187, 153, 219, 198, 86, 129, 157, 71, 120, 87, 165, + 62, 23, 35, 61, 194, 181, 162, 218, 145, 175, 244, 147, 63, 217, + 100, 75, 69, 60, 123, 31, 72, 226, 43, 1, 63, 54, 231, 76, + 114, 219, 60, 217, 195, 230, 151, 234, 19, 196, 10, 63, 115, 40, + 239, 111, 254, 126, 242, 150, 41, 153, 111, 199, 225, 98, 255, 221, + 120, 44, 160, 17, 187, 253, 141, 243, 238, 113, 151, 55, 84, 78, + 206, 121, 52, 223, 202, 6, 153, 147, 68, 228, 97, 94, 62, 255, + 0, 213, 254, 112, 87, 110, 164, 37, 122, 73, 17, 141, 204, 152, + 0, 27, 56, 31, 240, 161, 210, 224, 172, 248, 53, 94, 45, 180, + 76, 140, 91, 172, 153, 146, 5, 255, 207, 136, 155, 219, 91, 180, + 50, 164, 7, 252, 57, 157, 245, 34, 0, 73, 150, 247, 41, 45, + 54, 212, 182, 200, 157, 196, 63, 105, 229, 180, 196, 4, 130, 86, + 63, 67, 235, 34, 231, 254, 221, 40, 95, 36, 155, 42, 104, 156, + 26, 252, 116, 159, 171, 81, 50, 5, 240, 168, 186, 242, 236, 222, + 33, 219, 115, 241, 81, 166, 176, 61, 229, 82, 189, 214, 31, 242, + 138, 2, 231, 19, 186, 255, 11, 13, 40, 176, 73, 243, 61, 200, + 247, 229, 247, 184, 14, 164, 32, 23, 98, 109, 19, 209, 133, 60, + 221, 96, 229, 128, 102, 123, 160, 248, 150, 105, 235, 154, 73, 59, + 40, 102, 136, 46, 156, 41, 88, 186, 33, 204, 1, 155, 19, 116, + 64, 244, 137, 136, 83, 116, 102, 147, 78, 196, 75, 108, 188, 47, + 175, 151, 214, 250, 214, 127, 93, 152, 165, 98, 238, 163, 175, 44, + 14, 87, 67, 233, 82, 141, 199, 123, 213, 55, 227, 222, 85, 43, + 138, 106, 109, 135, 103, 156, 174, 136, 160, 89, 227, 106, 43, 236, + 6, 145, 135, 245, 77, 231, 122, 18, 44, 104, 199, 239, 84, 91, + 138, 43, 72, 40, 104, 210, 174, 255, 81, 63, 177, 97, 253, 206, + 222, 110, 182, 209, 122, 216, 211, 203, 14, 153, 182, 75, 92, 63, + 225, 111, 90, 53, 132, 237, 242, 234, 6, 69, 248, 158, 18, 203, + 214, 225, 120, 6, 187, 217, 90, 159, 100, 149, 70, 181, 17, 185, + 35, 119, 95, 122, 78, 104, 216, 155, 114, 216, 239, 104, 66, 41, + 209, 30, 250, 170, 146, 162, 79, 152, 136, 121, 144, 33, 50, 88, + 207, 48, 55, 138, 215, 178, 56, 148, 188, 113, 157, 104, 194, 111, + 157, 230, 127, 26, 52, 77, 119, 57, 189, 51, 58, 58, 241, 27, + 91, 208, 84, 224, 88, 211, 233, 22, 226, 103, 18, 114, 68, 31, + 254, 203, 161, 146, 77, 50, 154, 29, 14, 157, 160, 20, 173, 199, + 215, 126, 32, 108, 16, 103, 198, 205, 35, 122, 180, 249, 19, 91, + 102, 38, 239, 135, 96, 211, 172, 25, 144, 219, 236, 248, 60, 212, + 215, 224, 181, 108, 118, 249, 132, 54, 203, 101, 58, 108, 33, 78, + 22, 143, 129, 34, 162, 215, 210, 133, 89, 14, 32, 232, 67, 22, + 70, 68, 60, 168, 46, 155, 165, 92, 71, 50, 193, 188, 87, 162, + 235, 115, 79, 211, 48, 212, 18, 164, 68, 243, 157, 44, 251, 131, + 245, 15, 100, 118, 80, 233, 252, 26, 26, 91, 145, 52, 119, 135, + 202, 150, 226, 224, 7, 137, 197, 32, 59, 188, 78, 2, 166, 234, + 227, 82, 32, 158, 223, 104, 136, 219, 13, 105, 115, 205, 21, 180, + 199, 217, 227, 143, 138, 79, 196, 112, 151, 201, 208, 173, 196, 10, + 8, 85, 59, 40, 21, 220, 24, 47, 18, 57, 214, 236, 50, 152, + 93, 90, 218, 196, 57, 242, 166, 19, 79, 208, 124, 7, 109, 192, + 21, 52, 234, 253, 104, 202, 231, 152, 152, 120, 95, 163, 249, 238, + 122, 101, 174, 143, 33, 173, 79, 203, 221, 252, 59, 108, 67, 47, + 37, 83, 14, 201, 235, 112, 239, 159, 55, 127, 228, 206, 90, 175, + 120, 148, 252, 148, 104, 83, 243, 236, 119, 84, 64, 148, 4, 18, + 123, 11, 160, 190, 149, 153, 214, 197, 184, 254, 236, 26, 152, 181, + 227, 49, 166, 98, 239, 80, 87, 210, 153, 180, 41, 43, 100, 92, + 111, 152, 184, 179, 141, 67, 50, 233, 168, 35, 199, 254, 43, 82, + 136, 6, 244, 220, 53, 11, 253, 58, 181, 150, 131, 42, 161, 141, + 115, 10, 167, 201, 63, 205, 0, 207, 110, 48, 255, 174, 219, 36, + 177, 87, 96, 191, 235, 20, 121, 53, 54, 246, 124, 21, 136, 237, + 174, 98, 133, 21, 152, 118, 235, 77, 197, 53, 172, 45, 92, 219, + 125, 253, 87, 214, 43, 93, 134, 66, 160, 44, 231, 116, 175, 203, + 210, 186, 97, 198, 251, 148, 66, 149, 251, 222, 31, 96, 142, 170, + 127, 104, 191, 109, 92, 110, 4, 75, 55, 188, 109, 134, 181, 171, + 87, 49, 199, 154, 202, 187, 5, 50, 177, 1, 210, 32, 36, 40, + 229, 26, 98, 216, 122, 167, 33, 26, 4, 154, 86, 48, 115, 111, + 151, 84, 17, 37, 181, 18, 242, 202, 213, 229, 107, 84, 18, 148, + 56, 180, 37, 124, 158, 1, 143, 70, 37, 128, 74, 160, 152, 26, + 0, 174, 162, 30, 184, 175, 109, 174, 176, 21, 73, 115, 69, 184, + 15, 183, 228, 92, 109, 169, 79, 235, 196, 116, 42, 227, 23, 21, + 156, 252, 95, 55, 97, 195, 43, 98, 29, 141, 119, 209, 28, 206, + 143, 228, 190, 97, 60, 223, 37, 34, 138, 145, 64, 144, 95, 100, + 242, 243, 6, 56, 206, 113, 140, 247, 123, 21, 134, 164, 141, 27, + 110, 211, 210, 163, 164, 168, 56, 251, 217, 52, 228, 39, 153, 37, + 45, 125, 87, 50, 228, 43, 60, 139, 8, 71, 23, 37, 253, 185, + 76, 59, 135, 106, 114, 72, 100, 227, 80, 55, 94, 232, 137, 1, + 23, 138, 105, 101, 242, 192, 154, 68, 117, 111, 87, 246, 156, 194, + 206, 14, 88, 80, 249, 199, 37, 125, 11, 194, 1, 67, 4, 255, + 16, 155, 107, 84, 162, 235, 58, 189, 192, 37, 67, 48, 42, 219, + 84, 77, 248, 83, 46, 74, 78, 95, 108, 237, 96, 248, 17, 91, + 192, 124, 96, 254, 100, 152, 169, 110, 113, 163, 29, 78, 157, 211, + 5, 193, 129, 119, 173, 64, 43, 50, 231, 153, 193, 66, 204, 82, + 224, 240, 201, 203, 197, 75, 196, 205, 70, 229, 63, 49, 108, 180, + 227, 43, 248, 184, 11, 231, 216, 203, 188, 243, 121, 207, 102, 243, + 87, 253, 77, 93, 33, 34, 175, 25, 251, 187, 62, 188, 178, 60, + 114, 105, 97, 182, 144, 245, 164, 40, 199, 135, 68, 88, 46, 228, + 8, 56, 8, 186, 250, 124, 255, 111, 137, 139, 181, 110, 220, 56, + 191, 213, 200, 27, 101, 104, 111, 228, 70, 82, 144, 12, 71, 41, + 180, 217, 28, 36, 191, 83, 14, 190, 171, 173, 158, 213, 129, 32, + 215, 123, 193, 18, 209, 119, 149, 226, 134, 28, 7, 162, 195, 24, + 40, 186, 36, 183, 32, 222, 115, 62, 40, 118, 35, 24, 79, 142, + 184, 201, 199, 6, 222, 73, 19, 52, 203, 198, 169, 132, 219, 253, + 235, 246, 191, 59, 46, 59, 4, 20, 38, 107, 180, 95, 214, 209, + 47, 85, 121, 221, 248, 82, 97, 84, 219, 20, 159, 14, 235, 225, + 8, 232, 112, 31, 61, 94, 164, 243, 184, 4, 135, 115, 61, 224, + 187, 65, 221, 56, 128, 115, 69, 108, 132, 226, 16, 110, 203, 122, + 230, 247, 147, 142, 147, 17, 100, 207, 224, 240, 128, 97, 193, 237, + 253, 57, 216, 40, 13, 251, 86, 81, 118, 246, 200, 68, 246, 45, + 81, 197, 248, 120, 99, 156, 234, 227, 226, 149, 235, 239, 225, 58, + 11, 33, 85, 166, 109, 198, 221, 200, 193, 24, 152, 99, 111, 142, + 26, 66, 125, 79, 232, 84, 184, 238, 109, 4, 182, 108, 55, 96, + 187, 58, 209, 6, 19, 191, 51, 142, 142, 149, 244, 47, 253, 248, + 5, 106, 228, 57, 167, 201, 95, 161, 217, 228, 56, 249, 114, 95, + 112, 241, 31, 70, 17, 61, 14, 83, 228, 201, 252, 35, 58, 17, + 204, 225, 29, 137, 5, 214, 47, 9, 171, 226, 13, 178, 177, 57, + 59, 202, 44, 146, 26, 119, 92, 109, 121, 124, 143, 1, 71, 136, + 248, 195, 107, 88, 218, 44, 171, 8, 131, 205, 80, 71, 191, 91, + 111, 106, 211, 101, 62, 117, 144, 20, 60, 26, 140, 79, 41, 84, + 213, 107, 44, 88, 161, 197, 231, 216, 177, 161, 242, 222, 167, 132, + 192, 176, 103, 52, 83, 208, 44, 75, 17, 44, 114, 151, 59, 241, + 29, 167, 250, 30, 97, 82, 103, 217, 255, 193, 145, 162, 88, 243, + 45, 88, 4, 221, 180, 178, 121, 82, 195, 116, 219, 35, 152, 124, + 19, 90, 116, 152, 25, 241, 200, 77, 197, 211, 128, 94, 144, 113, + 11, 7, 29, 193, 47, 208, 152, 60, 59, 245, 120, 135, 77, 79, + 58, 148, 75, 113, 216, 111, 66, 219, 2, 11, 192, 127, 237, 10, + 49, 190, 146, 109, 140, 106, 50, 44, 127, 180, 225, 50, 134, 52, + 8, 123, 17, 79, 173, 22, 235, 11, 179, 197, 81, 180, 76, 89, + 139, 170, 98, 7, 181, 124, 124, 104, 255, 152, 57, 62, 120, 138, + 82, 239, 203, 82, 89, 152, 68, 232, 248, 204, 75, 9, 45, 154, + 82, 112, 30, 249, 182, 244, 20, 26, 231, 115, 56, 247, 164, 91, + 255, 79, 199, 174, 49, 15, 64, 244, 229, 202, 217, 51, 5, 220, + 7, 138, 72, 163, 134, 231, 63, 39, 228, 14, 55, 72, 202, 31, + 45, 193, 221, 193, 61, 101, 144, 108, 171, 179, 244, 197, 90, 29, + 81, 163, 51, 135, 177, 29, 117, 155, 227, 35, 157, 145, 17, 109, + 24, 64, 1, 237, 50, 184, 215, 199, 78, 20, 131, 194, 3, 158, + 206, 86, 123, 168, 32, 155, 63, 254, 126, 195, 174, 62, 236, 69, + 23, 196, 204, 228, 24, 54, 115, 205, 167, 196, 75, 223, 202, 220, + 58, 52, 108, 127, 59, 208, 2, 184, 34, 245, 160, 123, 58, 109, + 109, 118, 115, 235, 30, 31, 205, 223, 30, 42, 117, 43, 236, 136, + 146, 175, 24, 135, 190, 221, 189, 91, 252, 49, 51, 118, 140, 95, + 194, 151, 134, 35, 45, 68, 5, 114, 142, 122, 238, 55, 180, 156, + 209, 86, 138, 239, 112, 131, 42, 0, 193, 32, 10, 227, 173, 190, + 7, 94, 190, 213, 166, 205, 137, 44, 20, 218, 139, 40, 26, 190, + 218, 172, 153, 130, 7, 97, 244, 88, 35, 26, 159, 70, 248, 241, + 198, 151, 166, 253, 166, 33, 200, 43, 120, 254, 68, 168, 242, 95, + 229, 56, 210, 173, 97, 152, 164, 115, 241, 249, 235, 180, 9, 46, + 7, 34, 4, 96, 70, 220, 148, 181, 1, 8, 67, 29, 68, 76, + 171, 91, 186, 45, 2, 115, 75, 225, 218, 77, 120, 158, 54, 120, + 2, 152, 188, 196, 155, 218, 142, 196, 210, 18, 10, 117, 248, 177, + 232, 224, 231, 170, 54, 175, 174, 189, 137, 204, 141, 234, 51, 152, + 202, 187, 212, 195, 77, 50, 247, 17, 153, 100, 190, 16, 202, 215, + 251, 138, 36, 71, 237, 147, 30, 54, 236, 185, 60, 118, 233, 230, + 170, 26, 163, 219, 81, 216, 94, 175, 220, 191, 179, 124, 72, 233, + 107, 132, 47, 56, 248, 139, 142, 232, 248, 131, 245, 156, 20, 135, + 202, 10, 110, 125, 210, 174, 50, 11, 9, 198, 167, 73, 195, 102, + 104, 41, 183, 149, 1, 241, 78, 115, 157, 232, 194, 0, 241, 121, + 96, 138, 37, 251, 43, 84, 224, 50, 199, 93, 35, 6, 169, 144, + 125, 248, 225, 3, 135, 25, 92, 3, 254, 123, 138, 24, 29, 86, + 9, 139, 109, 85, 48, 245, 163, 173, 27, 15, 167, 75, 236, 255, + 120, 19, 32, 244, 220, 191, 111, 32, 4, 125, 150, 195, 145, 167, + 8, 252, 31, 96, 195, 85, 105, 142, 55, 193, 189, 124, 232, 205, + 175, 119, 185, 191, 5, 14, 54, 29, 194, 115, 140, 21, 143, 169, + 59, 86, 47, 233, 176, 176, 89, 157, 145, 116, 102, 215, 191, 60, + 151, 233, 125, 57, 78, 168, 17, 41, 57, 29, 169, 188, 61, 40, + 39, 226, 166, 244, 210, 160, 218, 243, 87, 98, 210, 132, 126, 140, + 129, 71, 180, 57, 162, 163, 115, 185, 69, 170, 73, 30, 101, 146, + 203, 101, 40, 137, 68, 165, 53, 23, 134, 184, 108, 220, 93, 14, + 63, 158, 7, 83, 156, 128, 87, 182, 25, 153, 219, 189, 122, 82, + 108, 246, 170, 146, 100, 27, 21, 251, 22, 241, 137, 56, 158, 107, + 133, 196, 57, 103, 227, 23, 134, 178, 236, 106, 170, 214, 129, 112, + 208, 123, 248, 22, 24, 12, 202, 49, 129, 244, 222, 13, 204, 173, + 177, 212, 109, 46, 204, 53, 112, 71, 91, 16, 16, 64, 170, 145, + 23, 136, 155, 131, 151, 179, 97, 33, 49, 162, 180, 62, 200, 226, + 240, 64, 53, 42, 135, 127, 135, 91, 229, 207, 71, 97, 92, 57, + 135, 15, 205, 14, 227, 5, 132, 204, 237, 149, 241, 144, 254, 108, + 151, 181, 219, 160, 52, 159, 101, 154, 72, 150, 188, 165, 211, 130, + 182, 62, 65, 243, 113, 179, 214, 241, 81, 78, 179, 161, 210, 220, + 244, 149, 194, 5, 205, 89, 97, 233, 175, 60, 155, 55, 77, 115, + 6, 66, 78, 216, 61, 184, 238, 201, 153, 218, 147, 249, 184, 215, + 209, 197, 16, 4, 220, 187, 10, 206, 147, 66, 42, 100, 145, 212, + 14, 225, 43, 151, 154, 191, 249, 126, 57, 37, 187, 147, 23, 32, + 158, 51, 189, 94, 139, 75, 168, 105, 160, 181, 239, 39, 104, 74, + 99, 87, 90, 226, 172, 57, 38, 43, 70, 35, 117, 198, 84, 100, + 220, 223, 142, 107, 36, 139, 29, 107, 173, 19, 160, 54, 0, 31, + 9, 151, 180, 213, 178, 146, 29, 223, 52, 81, 40, 237, 32, 42, + 130, 190, 188, 168, 82, 32, 206, 247, 120, 68, 60, 132, 192, 80, + 242, 4, 96, 212, 9, 18, 18, 218, 62, 242, 120, 1, 107, 31, + 88, 239, 104, 141, 157, 74, 184, 98, 171, 123, 243, 96, 30, 76, + 255, 13, 13, 4, 15, 67, 176, 75, 205, 120, 127, 108, 25, 121, + 179, 50, 43, 92, 49, 149, 163, 156, 116, 24, 63, 65, 228, 111, + 89, 242, 14, 140, 128, 133, 193, 83, 11, 202, 7, 208, 120, 81, + 216, 254, 155, 202, 151, 3, 103, 206, 5, 5, 124, 147, 242, 23, + 248, 81, 169, 226, 209, 229, 42, 17, 67, 211, 255, 75, 214, 203, + 27, 179, 31, 201, 162, 218, 157, 1, 143, 98, 16, 231, 189, 72, + 41, 163, 125, 197, 253, 240, 82, 50, 46, 33, 252, 117, 212, 56, + 17, 93, 95, 247, 183, 254, 190, 145, 185, 35, 155, 40, 122, 68, + 150, 114, 126, 167, 218, 127, 221, 56, 16, 29, 178, 133, 28, 37, + 69, 150, 197, 17, 174, 216, 94, 167, 26, 77, 204, 32, 176, 133, + 111, 171, 183, 168, 198, 68, 222, 90, 101, 27, 89, 56, 215, 42, + 228, 67, 184, 118, 67, 166, 70, 192, 146, 235, 126, 187, 189, 224, + 121, 38, 202, 249, 114, 210, 3, 157, 127, 215, 22, 4, 20, 99, + 213, 110, 221, 183, 109, 197, 2, 203, 157, 136, 174, 124, 218, 191, + 130, 71, 54, 120, 150, 164, 76, 71, 152, 60, 136, 94, 8, 60, + 56, 45, 27, 32, 33, 6, 97, 90, 74, 189, 101, 71, 39, 5, + 253, 253, 236, 23, 243, 63, 221, 59, 14, 10, 59, 99, 255, 135, + 18, 5, 19, 0, 97, 166, 88, 24, 232, 235, 215, 173, 152, 206, + 244, 105, 224, 48, 244, 71, 118, 114, 185, 6, 122, 224, 62, 146, + 170, 36, 70, 214, 6, 209, 89, 236, 34, 230, 25, 22, 135, 88, + 171, 225, 52, 163, 225, 15, 68, 27, 173, 201, 102, 130, 230, 12, + 49, 238, 46, 39, 247, 99, 218, 237, 0, 164, 126, 153, 173, 12, + 158, 222, 4, 9, 227, 202, 92, 240, 223, 82, 181, 191, 207, 101, + 105, 163, 6, 138, 157, 143, 165, 197, 195, 75, 68, 250, 72, 107, + 22, 148, 136, 111, 122, 208, 68, 240, 56, 120, 224, 15, 115, 25, + 165, 166, 187, 226, 7, 33, 118, 103, 201, 93, 50, 81, 151, 240, + 139, 46, 214, 218, 133, 65, 127, 191, 116, 158, 30, 148, 99, 42, + 196, 151, 60, 151, 29, 109, 245, 165, 10, 97, 90, 181, 101, 237, + 40, 82, 242, 185, 232, 150, 84, 156, 128, 37, 100, 218, 108, 122, + 125, 102, 97, 236, 202, 244, 205, 224, 86, 50, 40, 130, 18, 105, + 148, 6, 87, 36, 52, 31, 144, 126, 53, 218, 176, 186, 253, 54, + 178, 134, 126, 11, 136, 22, 154, 35, 180, 7, 8, 230, 43, 240, + 91, 76, 26, 192, 80, 45, 172, 19, 97, 93, 92, 98, 225, 102, + 170, 27, 215, 13, 79, 16, 55, 188, 146, 162, 30, 28, 104, 178, + 187, 187, 255, 145, 115, 255, 91, 173, 238, 69, 151, 36, 250, 49, + 26, 106, 13, 26, 194, 69, 241, 39, 214, 64, 90, 111, 12, 28, + 172, 212, 77, 48, 247, 176, 233, 75, 172, 114, 103, 38, 4, 241, + 57, 196, 153, 148, 90, 171, 18, 50, 48, 187, 34, 208, 141, 61, + 228, 234, 31, 9, 220, 145, 14, 184, 10, 159, 47, 212, 102, 129, + 178, 70, 99, 207, 37, 117, 29, 31, 240, 50, 97, 4, 16, 222, + 245, 134, 226, 32, 138, 211, 23, 79, 193, 107, 134, 99, 147, 126, + 234, 247, 110, 105, 180, 13, 158, 209, 6, 226, 203, 196, 65, 208, + 145, 142, 216, 218, 49, 186, 238, 190, 115, 99, 106, 126, 27, 76, + 164, 135, 130, 188, 67, 135, 199, 58, 18, 112, 205, 190, 255, 1, + 160, 45, 144, 48, 74, 227, 221, 208, 203, 13, 85, 22, 246, 21, + 254, 58, 102, 144, 120, 88, 143, 226, 153, 24, 21, 132, 251, 102, + 152, 75, 244, 68, 172, 94, 171, 249, 138, 57, 113, 215, 28, 51, + 229, 148, 70, 22, 133, 169, 45, 199, 235, 171, 103, 9, 15, 162, + 196, 164, 198, 167, 84, 59, 36, 24, 173, 204, 188, 37, 134, 68, + 14, 23, 5, 39, 121, 189, 253, 251, 62, 72, 130, 10, 19, 192, + 132, 216, 68, 134, 156, 181, 17, 152, 207, 216, 135, 225, 79, 2, + 3, 116, 65, 201, 152, 191, 230, 115, 203, 100, 179, 120, 169, 139, + 165, 247, 191, 253, 192, 205, 36, 77, 58, 14, 135, 69, 154, 183, + 250, 207, 96, 128, 145, 46, 214, 99, 225, 210, 79, 152, 86, 75, + 175, 189, 140, 127, 231, 209, 14, 167, 214, 81, 210, 17, 88, 255, + 154, 25, 62, 72, 67, 179, 154, 39, 230, 23, 18, 140, 216, 15, + 67, 74, 64, 151, 97, 168, 151, 108, 104, 94, 184, 167, 117, 40, + 217, 233, 236, 98, 97, 105, 177, 79, 71, 78, 157, 108, 199, 200, + 7, 155, 50, 102, 205, 168, 248, 49, 142, 144, 44, 195, 182, 247, + 226, 206, 136, 246, 18, 107, 138, 57, 47, 159, 105, 0, 162, 211, + 240, 120, 138, 172, 162, 220, 142, 251, 241, 113, 27, 73, 211, 3, + 82, 247, 74, 134, 30, 96, 18, 57, 51, 82, 119, 239, 34, 148, + 52, 211, 93, 128, 80, 0, 107, 90, 230, 72, 104, 252, 106, 238, + 42, 120, 19, 229, 102, 180, 126, 83, 125, 117, 162, 123, 136, 245, + 247, 18, 244, 82, 181, 43, 66, 184, 86, 234, 7, 62, 132, 254, + 81, 4, 138, 31, 149, 119, 120, 192, 234, 212, 205, 23, 230, 121, + 78, 159, 32, 216, 226, 146, 48, 44, 103, 134, 208, 93, 65, 144, + 2, 220, 228, 16, 72, 176, 56, 150, 243, 44, 225, 43, 200, 98, + 217, 7, 77, 72, 114, 64, 43, 129, 49, 242, 72, 47, 36, 76, + 116, 166, 158, 30, 99, 210, 21, 41, 85, 166, 116, 198, 13, 87, + 116, 21, 22, 31, 35, 247, 47, 233, 112, 49, 233, 80, 11, 123, + 144, 164, 193, 59, 91, 140, 237, 198, 96, 225, 188, 63, 29, 123, + 18, 178, 52, 118, 93, 82, 239, 163, 174, 78, 177, 186, 82, 213, + 120, 147, 125, 27, 108, 231, 165, 144, 221, 175, 255, 195, 208, 0, + 62, 215, 154, 11, 214, 146, 88, 104, 36, 89, 45, 5, 194, 29, + 183, 176, 49, 70, 195, 22, 190, 13, 136, 174, 142, 54, 142, 159, + 26, 247, 243, 58, 113, 252, 238, 155, 56, 164, 27, 32, 73, 252, + 113, 97, 250, 19, 196, 218, 22, 19, 213, 47, 11, 5, 65, 216, + 195, 87, 158, 215, 28, 60, 161, 193, 246, 111, 213, 213, 159, 154, + 64, 127, 81, 247, 45, 92, 203, 146, 36, 136, 82, 44, 152, 223, + 29, 141, 116, 151, 210, 230, 247, 141, 8, 18, 140, 39, 74, 184, + 211, 245, 164, 203, 122, 167, 189, 127, 144, 237, 24, 229, 208, 135, + 29, 179, 62, 227, 104, 240, 248, 125, 129, 142, 24, 55, 188, 112, + 243, 245, 239, 218, 124, 160, 71, 61, 235, 196, 121, 61, 114, 92, + 169, 128, 233, 105, 152, 27, 121, 123, 252, 32, 138, 8, 162, 207, + 234, 130, 26, 135, 5, 213, 203, 249, 104, 143, 19, 4, 227, 50, + 86, 198, 222, 31, 66, 181, 250, 211, 28, 96, 181, 101, 245, 188, + 136, 94, 237, 89, 41, 43, 207, 90, 69, 196, 103, 196, 233, 112, + 102, 32, 46, 222, 234, 7, 216, 14, 22, 63, 216, 23, 191, 65, + 253, 36, 10, 82, 114, 100, 23, 137, 109, 220, 58, 38, 38, 208, + 134, 58, 69, 115, 190, 82, 10, 179, 76, 164, 12, 127, 225, 111, + 135, 20, 158, 135, 98, 213, 159, 219, 230, 68, 37, 187, 191, 132, + 253, 153, 148, 5, 72, 226, 173, 191, 114, 241, 100, 47, 151, 112, + 127, 200, 101, 135, 21, 19, 52, 179, 31, 112, 229, 157, 232, 99, + 0, 201, 80, 121, 5, 217, 125, 147, 109, 3, 118, 106, 210, 27, + 69, 24, 13, 154, 217, 169, 96, 21, 211, 130, 44, 246, 36, 89, + 85, 13, 68, 163, 214, 70, 7, 140, 34, 244, 225, 222, 103, 139, + 0, 75, 88, 167, 1, 103, 189, 80, 247, 12, 147, 161, 219, 70, + 174, 97, 66, 250, 180, 26, 157, 224, 41, 241, 57, 154, 21, 97, + 137, 53, 85, 89, 145, 115, 111, 48, 148, 180, 198, 169, 22, 153, + 41, 34, 220, 245, 126, 244, 165, 231, 221, 52, 73, 157, 60, 48, + 106, 9, 104, 142, 238, 223, 199, 156, 201, 153, 159, 207, 94, 210, + 143, 161, 233, 252, 177, 206, 30, 251, 229, 162, 181, 16, 89, 215, + 201, 9, 207, 248, 183, 31, 63, 18, 4, 113, 136, 26, 85, 147, + 27, 81, 97, 238, 91, 139, 244, 98, 228, 17, 20, 244, 50, 197, + 144, 47, 219, 70, 233, 73, 64, 56, 200, 196, 20, 109, 3, 220, + 255, 91, 115, 166, 98, 200, 85, 87, 161, 160, 96, 121, 182, 255, + 17, 196, 26, 38, 154, 158, 249, 205, 218, 244, 106, 13, 192, 8, + 58, 19, 36, 97, 109, 220, 43, 25, 156, 247, 13, 147, 248, 247, + 133, 131, 232, 71, 200, 110, 176, 210, 218, 74, 77, 218, 220, 163, + 183, 206, 32, 10, 11, 36, 119, 251, 136, 215, 60, 15, 194, 28, + 214, 208, 34, 226, 80, 15, 249, 53, 247, 152, 116, 135, 236, 106, + 2, 147, 22, 131, 41, 168, 170, 174, 191, 245, 97, 160, 118, 126, + 200, 195, 42, 230, 206, 171, 173, 22, 25, 216, 128, 136, 39, 80, + 5, 175, 154, 131, 61, 71, 200, 59, 197, 93, 245, 161, 93, 46, + 226, 28, 71, 202, 92, 95, 129, 228, 84, 69, 247, 180, 111, 77, + 238, 169, 160, 169, 36, 162, 115, 221, 52, 66, 31, 142, 94, 32, + 0, 201, 209, 233, 84, 53, 189, 151, 176, 50, 92, 217, 237, 253, + 73, 232, 144, 141, 197, 88, 195, 66, 233, 63, 174, 69, 174, 166, + 137, 202, 138, 8, 237, 93, 200, 187, 47, 177, 90, 20, 56, 144, + 119, 89, 51, 120, 70, 86, 169, 216, 69, 173, 205, 163, 136, 103, + 35, 196, 3, 109, 65, 218, 67, 139, 123, 71, 224, 0, 107, 93, + 88, 249, 51, 62, 107, 182, 95, 134, 184, 86, 216, 207, 215, 110, + 59, 2, 163, 37, 189, 217, 63, 112, 216, 7, 180, 197, 3, 103, + 11, 232, 65, 84, 181, 31, 103, 204, 25, 124, 103, 117, 161, 23, + 42, 92, 197, 80, 141, 169, 88, 229, 94, 32, 162, 28, 121, 66, + 86, 15, 69, 131, 59, 231, 222, 58, 30, 239, 163, 242, 198, 211, + 167, 142, 146, 88, 45, 196, 75, 217, 118, 51, 127, 114, 205, 157, + 120, 253, 37, 88, 137, 125, 13, 175, 5, 5, 212, 131, 228, 6, + 191, 33, 213, 100, 207, 67, 49, 246, 193, 218, 213, 228, 23, 228, + 176, 11, 1, 121, 242, 219, 247, 213, 122, 67, 157, 222, 13, 131, + 236, 67, 102, 228, 172, 127, 238, 39, 6, 126, 114, 23, 117, 43, + 60, 209, 193, 199, 78, 82, 37, 62, 219, 63, 194, 37, 235, 239, + 112, 251, 233, 96, 208, 99, 101, 55, 235, 184, 163, 150, 41, 221, + 29, 199, 91, 114, 144, 146, 254, 97, 73, 240, 218, 239, 188, 177, + 157, 112, 172, 242, 158, 208, 211, 62, 27, 127, 74, 194, 138, 36, + 23, 29, 189, 172, 81, 134, 249, 143, 51, 79, 162, 72, 0, 117, + 110, 251, 120, 191, 86, 180, 55, 86, 162, 211, 73, 241, 176, 254, + 29, 85, 41, 106, 145, 194, 154, 43, 167, 143, 232, 206, 45, 207, + 135, 154, 125, 62, 35, 152, 249, 209, 119, 226, 32, 185, 166, 171, + 173, 147, 54, 44, 90, 183, 32, 105, 60, 153, 255, 141, 202, 224, + 91, 164, 97, 205, 245, 38, 23, 119, 16, 235, 110, 142, 26, 201, + 68, 231, 12, 251, 207, 190, 9, 198, 127, 80, 78, 11, 184, 245, + 243, 231, 172, 124, 76, 173, 4, 123, 208, 1, 231, 58, 22, 188, + 116, 62, 82, 92, 42, 78, 189, 35, 165, 127, 184, 252, 141, 248, + 126, 131, 78, 137, 59, 72, 100, 230, 64, 85, 127, 36, 59, 241, + 229, 170, 137, 165, 102, 4, 193, 47, 186, 207, 140, 79, 54, 64, + 35, 160, 142, 185, 129, 92, 48, 82, 38, 165, 211, 229, 28, 165, + 139, 33, 177, 108, 221, 254, 189, 78, 84, 124, 16, 35, 241, 52, + 251, 200, 29, 179, 53, 75, 70, 231, 134, 17, 96, 249, 228, 16, + 153, 113, 156, 101, 68, 251, 216, 99, 110, 245, 59, 149, 116, 251, + 97, 51, 88, 21, 149, 244, 98, 216, 166, 252, 1, 250, 120, 34, + 140, 91, 65, 8, 56, 224, 31, 145, 167, 173, 178, 207, 168, 169, + 62, 126, 247, 151, 216, 8, 64, 125, 28, 58, 27, 17, 151, 21, + 66, 145, 93, 112, 115, 123, 227, 205, 67, 192, 229, 222, 43, 88, + 116, 178, 160, 151, 18, 242, 139, 238, 189, 172, 195, 64, 246, 12, + 220, 199, 42, 244, 154, 192, 122, 115, 12, 39, 182, 117, 90, 158, + 238, 88, 45, 6, 38, 147, 223, 82, 44, 102, 87, 15, 229, 84, + 167, 139, 136, 134, 11, 97, 105, 12, 232, 35, 176, 248, 177, 0, + 73, 73, 184, 20, 59, 116, 220, 85, 12, 74, 68, 84, 245, 46, + 118, 16, 103, 139, 7, 234, 153, 238, 4, 235, 233, 44, 176, 52, + 70, 239, 74, 113, 202, 147, 31, 166, 144, 180, 76, 76, 80, 25, + 158, 152, 137, 9, 250, 82, 102, 137, 72, 6, 42, 181, 101, 37, + 214, 99, 119, 37, 81, 109, 203, 32, 61, 71, 100, 190, 66, 145, + 204, 190, 144, 157, 107, 38, 98, 129, 190, 87, 21, 76, 73, 137, + 39, 3, 112, 8, 36, 107, 230, 17, 213, 91, 40, 209, 19, 185, + 135, 39, 177, 196, 131, 127, 167, 145, 81, 141, 253, 255, 61, 102, + 38, 91, 198, 165, 248, 168, 104, 86, 131, 15, 62, 181, 57, 156, + 113, 23, 130, 210, 153, 48, 133, 0, 124, 177, 235, 124, 97, 210, + 182, 178, 101, 127, 31, 59, 254, 151, 65, 47, 203, 254, 216, 250, + 227, 245, 127, 71, 8, 110, 121, 46, 11, 215, 227, 194, 229, 46, + 219, 40, 231, 252, 57, 39, 139, 186, 146, 196, 83, 229, 10, 68, + 55, 152, 43, 116, 9, 225, 40, 25, 68, 91, 233, 36, 209, 54, + 211, 0, 0, 134, 137, 106, 169, 224, 230, 31, 51, 249, 25, 38, + 21, 0, 107, 25, 22, 209, 164, 70, 0, 113, 200, 173, 161, 16, + 85, 134, 226, 137, 34, 197, 95, 235, 246, 249, 184, 184, 74, 244, + 18, 218, 116, 89, 0, 34, 192, 20, 247, 21, 169, 226, 187, 76, + 205, 213, 182, 16, 28, 254, 206, 135, 98, 139, 188, 114, 65, 57, + 208, 161, 122, 208, 232, 240, 13, 155, 207, 85, 202, 105, 221, 148, + 4, 4, 200, 10, 225, 49, 142, 120, 153, 128, 233, 108, 6, 200, + 18, 89, 105, 75, 162, 44, 137, 201, 42, 105, 216, 46, 212, 248, + 150, 96, 149, 184, 12, 242, 207, 22, 108, 26, 216, 86, 10, 198, + 90, 164, 246, 154, 239, 112, 135, 122, 6, 222, 24, 239, 75, 237, + 220, 92, 24, 53, 205, 221, 121, 244, 132, 196, 132, 43, 143, 168, + 75, 113, 148, 55, 103, 26, 21, 5, 98, 182, 12, 175, 115, 130, + 127, 191, 121, 26, 104, 9, 22, 69, 50, 42, 79, 46, 174, 103, + 220, 91, 161, 146, 47, 234, 254, 159, 53, 66, 56, 23, 106, 199, + 245, 24, 74, 40, 144, 254, 29, 60, 7, 234, 147, 56, 134, 38, + 242, 69, 226, 29, 15, 146, 246, 112, 1, 112, 175, 143, 111, 27, + 183, 55, 113, 243, 80, 0, 39, 79, 118, 183, 150, 184, 142, 50, + 129, 251, 201, 251, 177, 109, 203, 157, 161, 91, 109, 202, 90, 190, + 174, 249, 99, 78, 207, 223, 50, 219, 88, 129, 243, 229, 10, 33, + 45, 72, 216, 5, 131, 142, 90, 18, 54, 68, 122, 72, 155, 230, + 178, 8, 32, 53, 91, 125, 79, 211, 225, 130, 175, 156, 7, 49, + 176, 232, 224, 0, 67, 138, 13, 71, 138, 7, 28, 98, 237, 91, + 243, 76, 21, 227, 55, 231, 77, 212, 222, 55, 107, 246, 251, 183, + 180, 120, 99, 83, 225, 22, 73, 139, 244, 129, 254, 113, 11, 17, + 183, 162, 234, 166, 204, 156, 203, 205, 153, 212, 248, 98, 154, 135, + 217, 144, 42, 25, 145, 220, 101, 157, 131, 38, 227, 219, 131, 117, + 59, 98, 109, 68, 81, 219, 74, 150, 104, 132, 203, 222, 59, 166, + 211, 251, 29, 116, 210, 51, 87, 218, 100, 143, 214, 14, 154, 195, + 142, 215, 121, 208, 88, 61, 159, 145, 216, 116, 78, 11, 242, 76, + 11, 77, 0, 186, 84, 127, 79, 7, 157, 53, 24, 186, 106, 232, + 70, 247, 199, 63, 102, 180, 130, 104, 240, 200, 184, 175, 182, 184, + 154, 196, 86, 187, 60, 81, 150, 172, 33, 233, 118, 67, 197, 255, + 50, 150, 26, 229, 196, 102, 90, 43, 197, 201, 160, 248, 46, 37, + 48, 194, 96, 83, 96, 150, 121, 90, 100, 125, 77, 8, 84, 20, + 186, 124, 94, 235, 227, 150, 48, 73, 230, 77, 68, 90, 214, 242, + 2, 13, 176, 59, 45, 169, 35, 210, 15, 187, 211, 30, 65, 177, + 236, 80, 107, 94, 195, 19, 106, 226, 6, 165, 11, 249, 143, 87, + 151, 107, 33, 42, 63, 79, 165, 90, 218, 63, 214, 204, 125, 160, + 233, 138, 197, 8, 222, 26, 39, 56, 237, 40, 4, 30, 170, 78, + 146, 102, 34, 89, 228, 228, 5, 184, 221, 25, 119, 251, 252, 51, + 187, 233, 218, 158, 219, 72, 55, 67, 15, 8, 184, 155, 167, 84, + 102, 18, 122, 209, 45, 89, 56, 79, 91, 109, 228, 221, 213, 190, + 73, 179, 230, 245, 100, 25, 145, 142, 210, 167, 228, 11, 69, 66, + 101, 148, 149, 152, 97, 126, 145, 64, 80, 196, 132, 102, 196, 53, + 44, 165, 148, 219, 255, 58, 221, 191, 84, 52, 54, 85, 52, 31, + 224, 211, 46, 20, 164, 43, 200, 27, 121, 19, 120, 40, 131, 127, + 157, 6, 46, 38, 210, 79, 235, 112, 128, 7, 31, 22, 248, 135, + 71, 237, 90, 95, 200, 227, 244, 9, 59, 41, 219, 0, 254, 175, + 94, 183, 50, 250, 111, 92, 95, 80, 31, 164, 93, 12, 40, 144, + 237, 98, 13, 66, 27, 146, 223, 176, 65, 178, 241, 168, 200, 219, + 216, 236, 254, 9, 77, 53, 106, 198, 27, 172, 182, 188, 238, 217, + 23, 28, 216, 233, 6, 11, 113, 177, 103, 89, 153, 166, 20, 234, + 42, 135, 224, 60, 82, 55, 121, 170, 220, 234, 181, 12, 78, 246, + 81, 98, 110, 202, 76, 19, 155, 142, 46, 66, 212, 208, 53, 139, + 56, 11, 80, 95, 114, 93, 99, 255, 100, 210, 164, 202, 113, 95, + 113, 102, 179, 110, 64, 6, 35, 145, 36, 69, 11, 48, 81, 71, + 23, 128, 81, 56, 191, 76, 187, 110, 4, 144, 158, 182, 94, 4, + 9, 128, 187, 80, 152, 148, 148, 157, 229, 176, 97, 224, 49, 246, + 221, 242, 105, 167, 72, 250, 255, 10, 177, 85, 84, 14, 80, 54, + 25, 253, 57, 225, 55, 40, 172, 239, 180, 63, 23, 250, 156, 251, + 237, 115, 235, 215, 13, 225, 202, 237, 39, 67, 99, 252, 126, 254, + 110, 177, 227, 228, 160, 161, 172, 103, 63, 6, 214, 208, 85, 191, + 248, 177, 233, 80, 26, 79, 213, 168, 246, 95, 13, 144, 1, 129, + 254, 160, 60, 138, 220, 10, 225, 155, 35, 1, 212, 233, 162, 103, + 60, 48, 181, 240, 87, 105, 88, 116, 14, 206, 240, 93, 157, 69, + 80, 236, 103, 194, 230, 237, 30, 94, 194, 196, 158, 21, 85, 100, + 197, 149, 42, 173, 234, 144, 88, 228, 242, 104, 88, 4, 187, 101, + 216, 138, 122, 173, 147, 150, 25, 170, 96, 202, 37, 239, 128, 134, + 20, 147, 193, 10, 253, 144, 170, 190, 87, 36, 29, 44, 213, 247, + 95, 226, 26, 81, 249, 229, 248, 7, 90, 245, 11, 156, 158, 202, + 191, 244, 236, 59, 204, 153, 76, 61, 19, 3, 231, 144, 19, 219, + 199, 145, 148, 56, 1, 223, 121, 149, 10, 229, 121, 154, 191, 132, + 148, 181, 155, 36, 89, 99, 161, 9, 35, 101, 66, 7, 68, 162, + 190, 144, 195, 109, 162, 104, 63, 238, 210, 64, 131, 115, 32, 72, + 189, 29, 189, 168, 37, 71, 132, 143, 72, 88, 47, 145, 232, 46, + 198, 49, 142, 226, 14, 21, 147, 119, 100, 198, 180, 52, 23, 63, + 148, 120, 57, 251, 54, 156, 189, 197, 45, 132, 237, 1, 153, 108, + 140, 228, 96, 220, 181, 125, 208, 171, 252, 196, 56, 185, 57, 165, + 47, 65, 46, 110, 146, 210, 150, 13, 144, 229, 186, 232, 127, 95, + 80, 115, 15, 135, 70, 29, 129, 174, 219, 57, 133, 9, 248, 155, + 255, 30, 77, 22, 226, 225, 46, 51, 13, 244, 95, 77, 255, 4, + 92, 144, 197, 249, 175, 16, 32, 45, 199, 44, 87, 124, 173, 14, + 213, 242, 181, 120, 236, 219, 182, 252, 63, 219, 212, 42, 183, 248, + 129, 137, 82, 104, 191, 92, 221, 183, 90, 111, 154, 244, 41, 89, + 250, 107, 178, 91, 32, 174, 82, 92, 166, 243, 238, 180, 133, 85, + 176, 93, 244, 105, 135, 200, 58, 199, 178, 130, 216, 221, 115, 96, + 237, 34, 235, 243, 218, 60, 239, 206, 195, 191, 195, 121, 131, 26, + 65, 30, 59, 155, 251, 153, 14, 121, 144, 102, 138, 226, 129, 19, + 135, 49, 78, 201, 56, 224, 249, 4, 96, 174, 83, 225, 57, 191, + 148, 2, 208, 81, 134, 212, 110, 77, 104, 197, 115, 176, 158, 159, + 99, 54, 81, 201, 117, 66, 174, 37, 197, 15, 121, 155, 129, 131, + 215, 28, 205, 217, 248, 205, 59, 56, 97, 252, 30, 244, 242, 188, + 87, 150, 243, 216, 40, 72, 44, 120, 110, 245, 178, 113, 178, 36, + 245, 177, 41, 186, 116, 21, 4, 155, 238, 107, 177, 154, 94, 35, + 180, 24, 255, 155, 177, 161, 225, 207, 159, 35, 255, 119, 193, 134, + 3, 48, 79, 81, 212, 241, 125, 200, 62, 132, 119, 28, 87, 12, + 64, 125, 70, 0, 121, 67, 175, 178, 190, 221, 56, 73, 119, 200, + 220, 83, 246, 168, 63, 137, 97, 242, 123, 250, 72, 58, 218, 43, + 88, 27, 161, 170, 42, 41, 126, 255, 26, 45, 139, 15, 124, 181, + 233, 199, 57, 232, 82, 234, 74, 157, 165, 92, 175, 109, 98, 208, + 29, 3, 3, 25, 188, 175, 214, 6, 73, 47, 209, 179, 117, 143, + 208, 98, 222, 209, 252, 69, 82, 60, 139, 164, 64, 109, 78, 204, + 147, 79, 93, 53, 206, 121, 62, 52, 227, 159, 3, 63, 199, 85, + 207, 133, 196, 185, 235, 72, 5, 29, 170, 38, 168, 136, 27, 236, + 10, 230, 191, 106, 75, 67, 13, 159, 206, 101, 157, 156, 11, 128, + 40, 17, 228, 185, 251, 55, 249, 86, 244, 162, 26, 190, 133, 107, + 159, 213, 32, 122, 12, 34, 157, 164, 8, 188, 30, 36, 144, 249, + 192, 119, 119, 170, 149, 139, 83, 26, 122, 135, 77, 251, 17, 165, + 13, 189, 184, 31, 61, 84, 103, 124, 165, 130, 156, 28, 88, 86, + 246, 0, 102, 101, 90, 126, 227, 79, 16, 2, 123, 215, 62, 30, + 103, 36, 76, 6, 15, 34, 113, 235, 182, 252, 197, 154, 220, 223, + 182, 55, 178, 174, 107, 38, 76, 142, 216, 105, 207, 147, 76, 38, + 230, 7, 125, 227, 248, 71, 53, 137, 59, 10, 134, 117, 198, 4, + 62, 122, 53, 182, 139, 127, 195, 173, 195, 244, 121, 140, 62, 244, + 165, 145, 204, 109, 225, 127, 88, 2, 194, 93, 252, 91, 195, 4, + 238, 60, 157, 56, 128, 70, 141, 100, 62, 104, 154, 52, 247, 80, + 157, 141, 20, 188, 67, 94, 144, 176, 47, 129, 2, 250, 55, 186, + 45, 147, 253, 171, 127, 192, 83, 61, 148, 201, 206, 20, 36, 232, + 107, 8, 120, 14, 143, 23, 78, 92, 161, 88, 84, 182, 146, 54, + 182, 100, 65, 136, 45, 36, 28, 36, 43, 203, 197, 98, 146, 244, + 26, 106, 7, 238, 171, 242, 174, 25, 26, 223, 249, 245, 219, 15, + 11, 162, 212, 157, 33, 138, 71, 76, 52, 100, 140, 143, 213, 84, + 250, 61, 44, 205, 163, 209, 63, 178, 81, 112, 90, 150, 245, 213, + 58, 236, 33, 130, 11, 249, 28, 82, 109, 198, 187, 237, 183, 221, + 106, 198, 241, 14, 107, 66, 21, 166, 94, 218, 18, 5, 207, 72, + 4, 172, 191, 121, 176, 32, 34, 106, 155, 176, 239, 96, 237, 199, + 106, 90, 10, 30, 78, 145, 202, 95, 122, 84, 213, 99, 142, 233, + 20, 200, 140, 115, 14, 254, 44, 244, 66, 231, 155, 190, 251, 162, + 99, 8, 239, 101, 91, 28, 21, 87, 94, 147, 224, 29, 89, 243, + 0, 175, 222, 154, 236, 242, 44, 94, 174, 0, 193, 202, 94, 157, + 176, 171, 7, 233, 166, 128, 19, 225, 152, 169, 145, 242, 43, 82, + 3, 186, 36, 72, 243, 93, 160, 108, 93, 148, 251, 39, 61, 228, + 185, 121, 242, 89, 140, 148, 210, 105, 249, 240, 237, 99, 168, 142, + 71, 148, 45, 124, 63, 2, 23, 104, 239, 180, 114, 190, 27, 16, + 63, 97, 231, 184, 150, 135, 255, 251, 136, 81, 253, 118, 194, 102, + 71, 160, 253, 127, 133, 242, 239, 233, 174, 41, 46, 180, 61, 33, + 208, 226, 150, 176, 249, 254, 112, 103, 9, 144, 242, 144, 129, 167, + 224, 223, 206, 66, 223, 226, 215, 247, 52, 72, 72, 241, 168, 28, + 115, 224, 205, 114, 180, 238, 139, 98, 201, 147, 175, 28, 41, 77, + 110, 145, 167, 165, 96, 74, 180, 158, 213, 183, 86, 216, 197, 252, + 7, 176, 202, 144, 246, 159, 10, 232, 228, 96, 132, 105, 126, 33, + 32, 105, 131, 126, 5, 110, 127, 231, 46, 208, 36, 35, 249, 206, + 214, 139, 206, 82, 92, 240, 235, 16, 223, 201, 215, 206, 174, 61, + 135, 61, 122, 147, 180, 138, 162, 89, 41, 0, 199, 67, 84, 244, + 242, 197, 127, 50, 204, 82, 119, 95, 74, 86, 179, 187, 206, 178, + 68, 241, 182, 236, 188, 161, 215, 211, 26, 159, 107, 230, 241, 70, + 8, 135, 43, 227, 192, 122, 218, 95, 117, 209, 168, 133, 138, 217, + 139, 98, 150, 232, 232, 39, 55, 214, 75, 237, 34, 125, 38, 192, + 181, 178, 13, 206, 121, 124, 29, 49, 81, 206, 27, 23, 48, 49, + 217, 100, 218, 128, 147, 75, 37, 4, 17, 229, 218, 4, 112, 40, + 12, 188, 118, 187, 66, 163, 188, 117, 224, 36, 198, 236, 40, 194, + 87, 171, 24, 216, 110, 162, 254, 113, 175, 169, 242, 242, 73, 65, + 37, 151, 206, 88, 214, 172, 159, 191, 56, 59, 51, 100, 181, 137, + 232, 4, 109, 207, 178, 85, 212, 24, 54, 54, 51, 54, 119, 129, + 50, 186, 14, 158, 123, 119, 164, 81, 113, 24, 137, 146, 28, 137, + 149, 33, 68, 23, 215, 3, 15, 202, 96, 153, 66, 25, 229, 152, + 160, 49, 130, 154, 208, 55, 254, 192, 173, 106, 233, 133, 169, 85, + 168, 101, 32, 167, 27, 189, 102, 134, 81, 168, 235, 122, 191, 187, + 24, 95, 87, 184, 152, 221, 186, 202, 199, 146, 253, 74, 25, 216, + 144, 213, 199, 135, 234, 85, 71, 0, 204, 196, 85, 165, 33, 239, + 6, 19, 111, 5, 177, 113, 213, 132, 47, 64, 38, 136, 45, 10, + 109, 218, 158, 53, 90, 106, 252, 180, 74, 138, 24, 247, 245, 116, + 226, 117, 36, 234, 78, 106, 108, 41, 61, 184, 51, 98, 105, 56, + 245, 105, 57, 244, 16, 86, 140, 78, 237, 59, 97, 173, 84, 149, + 48, 250, 212, 40, 28, 49, 233, 91, 67, 177, 41, 77, 141, 110, + 138, 141, 187, 70, 26, 239, 102, 130, 79, 115, 29, 168, 235, 234, + 79, 88, 39, 222, 215, 106, 46, 193, 90, 254, 249, 6, 99, 83, + 220, 56, 91, 106, 250, 5, 110, 224, 193, 209, 96, 75, 49, 249, + 88, 40, 129, 252, 255, 243, 62, 141, 153, 209, 251, 147, 212, 250, + 207, 164, 94, 104, 92, 73, 18, 116, 205, 88, 97, 188, 231, 140, + 242, 128, 190, 243, 240, 156, 0, 14, 162, 119, 134, 55, 59, 129, + 110, 187, 243, 208, 228, 171, 191, 43, 47, 143, 41, 97, 9, 149, + 84, 136, 89, 116, 159, 120, 88, 169, 161, 215, 136, 1, 75, 207, + 244, 167, 147, 166, 222, 72, 105, 151, 199, 157, 246, 64, 221, 42, + 138, 199, 57, 163, 221, 19, 26, 115, 38, 147, 194, 193, 93, 199, + 93, 47, 146, 126, 234, 99, 220, 154, 132, 56, 191, 229, 188, 97, + 190, 244, 223, 238, 145, 230, 141, 214, 167, 71, 226, 183, 215, 122, + 113, 246, 124, 224, 129, 99, 124, 20, 242, 121, 127, 40, 45, 53, + 28, 170, 65, 232, 107, 79, 115, 120, 173, 96, 94, 44, 182, 195, + 41, 189, 252, 100, 137, 178, 87, 211, 77, 74, 188, 179, 101, 47, + 161, 3, 243, 224, 59, 140, 251, 63, 239, 39, 85, 15, 198, 5, + 200, 101, 110, 53, 139, 246, 114, 154, 13, 211, 15, 32, 16, 189, + 103, 234, 242, 184, 79, 111, 160, 43, 150, 210, 97, 231, 18, 153, + 141, 66, 250, 56, 16, 125, 77, 147, 248, 114, 220, 148, 47, 173, + 243, 218, 0, 4, 38, 232, 111, 59, 18, 158, 90, 95, 115, 47, + 192, 254, 48, 211, 162, 212, 151, 17, 79, 13, 13, 239, 166, 237, + 217, 60, 45, 175, 100, 250, 195, 192, 46, 50, 221, 118, 222, 139, + 83, 191, 121, 201, 26, 173, 42, 63, 209, 133, 243, 99, 31, 219, + 222, 188, 99, 145, 64, 176, 18, 175, 124, 8, 4, 9, 181, 30, + 128, 254, 88, 199, 173, 178, 33, 203, 38, 225, 45, 203, 89, 198, + 37, 77, 219, 207, 106, 191, 147, 13, 152, 9, 193, 215, 81, 138, + 97, 232, 101, 21, 168, 106, 221, 244, 219, 241, 212, 12, 96, 29, + 97, 73, 39, 18, 60, 68, 250, 103, 12, 10, 84, 127, 229, 247, + 77, 73, 200, 195, 49, 63, 40, 65, 110, 137, 158, 183, 57, 197, + 167, 176, 205, 56, 114, 203, 74, 15, 197, 48, 228, 60, 210, 178, + 150, 217, 31, 173, 72, 160, 219, 101, 208, 126, 40, 179, 48, 245, + 245, 249, 136, 249, 37, 144, 33, 48, 246, 186, 66, 135, 157, 212, + 109, 47, 185, 109, 30, 110, 19, 75, 125, 192, 34, 150, 18, 108, + 80, 56, 4, 95, 62, 187, 20, 198, 173, 14, 163, 231, 149, 137, + 205, 120, 83, 91, 196, 246, 86, 165, 10, 210, 161, 199, 222, 192, + 250, 211, 230, 241, 137, 247, 176, 247, 142, 220, 46, 98, 215, 99, + 224, 142, 134, 131, 76, 182, 186, 130, 78, 175, 244, 124, 156, 188, + 8, 81, 6, 44, 191, 31, 12, 182, 157, 154, 194, 4, 86, 93, + 208, 135, 167, 240, 7, 63, 233, 77, 128, 217, 40, 133, 56, 215, + 31, 21, 46, 58, 172, 220, 229, 177, 20, 193, 5, 161, 135, 228, + 173, 8, 161, 77, 147, 255, 234, 134, 20, 251, 175, 57, 75, 150, + 37, 240, 132, 45, 85, 99, 90, 37, 41, 116, 53, 35, 220, 139, + 201, 81, 165, 236, 169, 58, 124, 70, 194, 94, 217, 230, 16, 249, + 215, 188, 235, 80, 183, 229, 45, 235, 182, 136, 63, 32, 145, 58, + 99, 39, 243, 40, 211, 247, 178, 72, 87, 25, 173, 9, 135, 110, + 51, 207, 194, 156, 170, 76, 249, 201, 211, 243, 182, 35, 30, 140, + 140, 174, 27, 52, 143, 198, 216, 189, 233, 132, 177, 127, 233, 48, + 63, 19, 170, 43, 95, 32, 93, 138, 98, 199, 234, 199, 59, 29, + 4, 3, 87, 218, 161, 38, 183, 129, 86, 116, 227, 208, 38, 139, + 254, 116, 17, 249, 186, 231, 102, 42, 133, 144, 148, 231, 194, 83, + 141, 213, 14, 183, 3, 233, 159, 12, 51, 155, 13, 70, 191, 111, + 8, 44, 109, 74, 182, 165, 8, 243, 172, 143, 28, 56, 70, 77, + 185, 72, 128, 175, 163, 7, 222, 80, 79, 73, 145, 152, 67, 43, + 143, 254, 175, 5, 59, 58, 115, 8, 124, 20, 171, 76, 115, 200, + 42, 141, 38, 106, 12, 41, 252, 61, 147, 46, 160, 194, 128, 18, + 117, 120, 187, 238, 204, 53, 228, 14, 41, 226, 162, 12, 234, 189, + 222, 21, 57, 80, 49, 184, 90, 38, 43, 139, 89, 96, 73, 102, + 109, 47, 180, 182, 3, 128, 229, 242, 217, 225, 55, 158, 217, 254, + 122, 211, 26, 75, 22, 190, 42, 247, 144, 163, 134, 203, 255, 5, + 114, 77, 206, 45, 51, 17, 96, 188, 102, 32, 183, 201, 212, 208, + 168, 74, 88, 155, 24, 11, 182, 90, 95, 189, 11, 160, 233, 77, + 224, 143, 69, 121, 18, 232, 215, 31, 130, 53, 131, 67, 59, 165, + 42, 161, 140, 211, 0, 192, 121, 156, 91, 229, 28, 29, 131, 129, + 16, 179, 132, 82, 111, 218, 19, 9, 108, 209, 149, 57, 38, 4, + 227, 56, 69, 15, 161, 55, 220, 20, 16, 180, 207, 77, 136, 197, + 36, 140, 18, 180, 140, 147, 77, 28, 8, 138, 48, 218, 12, 163, + 170, 100, 66, 177, 68, 186, 255, 239, 65, 42, 49, 209, 32, 145, + 175, 152, 163, 97, 162, 59, 6, 43, 89, 175, 76, 154, 193, 69, + 226, 121, 171, 94, 178, 194, 37, 82, 93, 161, 86, 94, 25, 44, + 34, 135, 136, 108, 160, 30, 147, 50, 5, 184, 133, 162, 34, 34, + 117, 16, 46, 202, 140, 93, 41, 230, 253, 229, 214, 103, 118, 45, + 167, 254, 57, 28, 23, 16, 109, 93, 172, 7, 11, 196, 239, 202, + 239, 110, 251, 45, 178, 241, 211, 171, 249, 188, 57, 44, 208, 229, + 20, 93, 156, 20, 190, 226, 76, 22, 144, 18, 216, 17, 66, 73, + 120, 7, 130, 12, 36, 100, 103, 72, 85, 15, 230, 49, 209, 209, + 249, 221, 1, 81, 91, 190, 198, 248, 65, 152, 35, 156, 30, 103, + 46, 11, 201, 153, 248, 196, 55, 254, 61, 128, 100, 34, 85, 232, + 85, 247, 197, 30, 134, 122, 34, 218, 69, 197, 125, 225, 57, 79, + 252, 252, 57, 67, 149, 137, 166, 195, 60, 141, 36, 24, 239, 141, + 124, 49, 200, 116, 93, 143, 139, 36, 165, 87, 171, 98, 107, 244, + 0, 128, 84, 247, 98, 191, 218, 67, 145, 168, 37, 208, 23, 240, + 194, 156, 95, 49, 9, 245, 133, 25, 203, 152, 93, 114, 240, 79, + 112, 6, 87, 199, 161, 33, 179, 18, 142, 18, 121, 58, 11, 207, + 8, 253, 76, 121, 228, 210, 35, 37, 17, 213, 205, 84, 193, 141, + 227, 74, 169, 23, 156, 210, 48, 43, 115, 22, 20, 70, 212, 185, + 248, 56, 120, 221, 164, 106, 101, 50, 217, 168, 55, 47, 75, 170, + 22, 59, 85, 231, 93, 234, 141, 192, 33, 180, 15, 45, 60, 231, + 214, 89, 191, 96, 225, 49, 237, 154, 233, 174, 81, 110, 197, 246, + 75, 184, 51, 156, 30, 251, 221, 67, 164, 30, 17, 1, 121, 170, + 157, 241, 255, 215, 34, 208, 28, 233, 188, 122, 78, 222, 143, 32, + 78, 9, 165, 252, 143, 61, 63, 35, 21, 188, 189, 77, 155, 165, + 82, 172, 198, 252, 93, 140, 103, 71, 152, 218, 203, 179, 68, 33, + 2, 226, 2, 84, 176, 48, 138, 214, 49, 165, 245, 73, 166, 32, + 238, 80, 29, 69, 9, 178, 45, 27, 231, 2, 0, 212, 166, 225, + 47, 121, 87, 216, 57, 234, 209, 245, 158, 188, 229, 38, 176, 107, + 97, 229, 16, 77, 228, 231, 33, 236, 254, 20, 63, 118, 128, 206, + 193, 205, 150, 33, 175, 132, 212, 62, 231, 236, 224, 214, 164, 45, + 51, 44, 247, 79, 14, 227, 213, 255, 44, 51, 177, 197, 236, 144, + 254, 11, 81, 243, 36, 31, 84, 93, 47, 240, 110, 37, 1, 242, + 45, 31, 70, 60, 199, 7, 93, 82, 241, 152, 217, 139, 241, 218, + 216, 177, 38, 190, 154, 104, 252, 87, 121, 16, 150, 1, 33, 104, + 194, 195, 58, 16, 37, 253, 106, 215, 60, 191, 171, 131, 162, 197, + 95, 194, 143, 197, 172, 90, 103, 192, 203, 25, 255, 53, 138, 0, + 240, 248, 161, 159, 106, 86, 61, 251, 96, 220, 113, 206, 181, 161, + 175, 196, 131, 193, 246, 167, 125, 204, 240, 222, 84, 185, 150, 199, + 192, 131, 94, 4, 42, 189, 150, 35, 229, 189, 35, 163, 34, 173, + 159, 74, 18, 91, 172, 25, 37, 240, 177, 202, 112, 212, 49, 241, + 19, 155, 15, 9, 119, 90, 164, 38, 45, 62, 8, 204, 146, 193, + 4, 148, 225, 156, 4, 255, 148, 197, 5, 155, 172, 248, 106, 126, + 40, 243, 28, 212, 107, 31, 54, 117, 176, 231, 117, 171, 182, 216, + 163, 0, 200, 187, 63, 68, 233, 77, 179, 95, 154, 253, 165, 26, + 132, 178, 86, 68, 179, 12, 100, 198, 141, 249, 182, 86, 133, 94, + 55, 159, 74, 126, 222, 151, 219, 168, 196, 245, 32, 187, 26, 239, + 72, 39, 158, 177, 203, 152, 29, 113, 234, 217, 199, 157, 17, 1, + 250, 180, 110, 48, 38, 3, 193, 216, 75, 99, 222, 81, 173, 208, + 48, 21, 95, 155, 141, 100, 191, 236, 152, 23, 35, 115, 227, 71, + 230, 220, 232, 180, 245, 88, 62, 185, 183, 234, 210, 35, 73, 149, + 159, 2, 197, 200, 144, 174, 6, 234, 101, 43, 21, 75, 81, 63, + 66, 44, 220, 186, 152, 236, 26, 28, 50, 216, 16, 27, 209, 152, + 229, 194, 224, 76, 122, 151, 247, 227, 96, 216, 222, 209, 52, 244, + 76, 16, 66, 6, 250, 178, 236, 135, 234, 117, 136, 169, 5, 16, + 20, 212, 151, 227, 241, 251, 194, 65, 155, 191, 36, 73, 96, 38, + 86, 39, 27, 190, 67, 89, 181, 193, 223, 91, 193, 0, 252, 106, + 17, 23, 93, 166, 61, 198, 158, 105, 135, 38, 116, 57, 186, 139, + 209, 222, 216, 103, 10, 219, 241, 69, 72, 203, 68, 96, 116, 120, + 184, 138, 110, 142, 200, 240, 244, 67, 239, 167, 151, 14, 220, 174, + 55, 131, 139, 179, 117, 16, 61, 125, 132, 128, 138, 132, 190, 102, + 216, 135, 232, 161, 61, 83, 22, 103, 182, 219, 221, 202, 144, 68, + 82, 79, 249, 70, 221, 94, 38, 210, 219, 160, 108, 184, 3, 176, + 36, 254, 94, 67, 167, 75, 2, 25, 240, 230, 17, 168, 102, 18, + 15, 223, 128, 26, 63, 3, 84, 156, 44, 209, 146, 168, 222, 163, + 44, 177, 87, 183, 216, 97, 18, 194, 5, 65, 235, 104, 179, 247, + 241, 61, 54, 81, 199, 223, 254, 218, 111, 179, 163, 59, 2, 11, + 211, 2, 133, 27, 142, 236, 243, 103, 195, 200, 114, 20, 138, 64, + 141, 255, 77, 181, 2, 219, 204, 219, 23, 9, 136, 59, 60, 148, + 103, 254, 239, 19, 50, 76, 142, 212, 44, 83, 177, 107, 198, 74, + 153, 188, 61, 212, 32, 126, 97, 196, 159, 215, 195, 156, 95, 179, + 131, 150, 58, 50, 32, 117, 54, 160, 6, 19, 166, 182, 97, 66, + 217, 165, 170, 27, 71, 15, 197, 181, 197, 113, 142, 240, 127, 82, + 188, 130, 245, 228, 196, 255, 116, 243, 62, 238, 60, 243, 177, 16, + 47, 239, 9, 194, 93, 132, 157, 198, 75, 76, 37, 74, 173, 18, + 126, 218, 13, 120, 255, 125, 29, 187, 214, 231, 190, 25, 220, 39, + 253, 118, 42, 238, 243, 38, 230, 135, 130, 194, 92, 76, 247, 137, + 147, 13, 188, 245, 135, 54, 160, 112, 16, 165, 81, 164, 143, 254, + 245, 1, 66, 48, 234, 124, 194, 107, 52, 9, 44, 240, 11, 160, + 15, 208, 34, 103, 234, 246, 136, 226, 146, 117, 32, 247, 123, 12, + 197, 56, 89, 141, 132, 158, 69, 130, 178, 6, 108, 251, 19, 120, + 156, 141, 5, 150, 196, 143, 8, 144, 145, 43, 79, 173, 182, 181, + 171, 218, 55, 249, 91, 148, 57, 0, 230, 232, 113, 110, 83, 105, + 60, 41, 246, 152, 126, 48, 118, 141, 241, 143, 238, 184, 220, 115, + 174, 35, 201, 164, 73, 250, 151, 139, 85, 46, 148, 158, 245, 228, + 58, 134, 211, 211, 40, 121, 165, 245, 72, 45, 237, 10, 97, 192, + 163, 215, 93, 183, 168, 140, 242, 120, 196, 20, 53, 178, 101, 69, + 144, 112, 35, 96, 32, 169, 9, 125, 37, 138, 50, 29, 208, 105, + 94, 27, 141, 67, 251, 66, 25, 184, 247, 25, 251, 67, 180, 246, + 180, 254, 246, 243, 29, 32, 6, 229, 193, 28, 105, 15, 190, 21, + 16, 62, 188, 65, 228, 233, 97, 153, 103, 43, 129, 213, 121, 5, + 239, 62, 29, 134, 204, 82, 200, 71, 105, 209, 228, 23, 111, 165, + 7, 78, 62, 144, 1, 128, 202, 187, 37, 107, 53, 28, 120, 217, + 216, 186, 125, 96, 181, 229, 216, 42, 100, 18, 74, 27, 192, 29, + 15, 178, 194, 26, 138, 177, 217, 74, 43, 251, 100, 168, 44, 138, + 71, 53, 138, 212, 95, 206, 32, 228, 27, 88, 243, 22, 204, 132, + 168, 106, 207, 71, 126, 143, 180, 182, 159, 158, 184, 215, 135, 251, + 40, 161, 230, 15, 0, 46, 203, 253, 91, 228, 132, 40, 1, 21, + 179, 143, 96, 82, 205, 35, 28, 215, 54, 174, 30, 22, 54, 23, + 67, 112, 149, 49, 81, 50, 45, 172, 150, 209, 225, 166, 135, 128, + 159, 40, 188, 133, 195, 174, 175, 177, 83, 171, 185, 167, 153, 222, + 134, 89, 72, 216, 78, 123, 249, 5, 152, 149, 228, 145, 84, 5, + 153, 186, 34, 163, 49, 29, 72, 75, 187, 252, 234, 8, 103, 133, + 191, 244, 213, 232, 240, 222, 221, 20, 40, 136, 28, 133, 97, 90, + 152, 108, 222, 195, 62, 145, 21, 206, 9, 161, 237, 221, 104, 187, + 169, 99, 89, 238, 109, 84, 182, 76, 165, 4, 254, 210, 252, 171, + 203, 218, 179, 32, 30, 200, 153, 14, 135, 8, 130, 111, 229, 19, + 98, 217, 35, 184, 191, 28, 255, 188, 210, 39, 75, 103, 177, 117, + 95, 114, 39, 132, 184, 204, 96, 160, 21, 103, 6, 152, 149, 250, + 10, 171, 169, 164, 181, 116, 212, 179, 57, 243, 10, 176, 250, 203, + 212, 20, 47, 241, 218, 142, 113, 58, 73, 192, 120, 156, 88, 0, + 43, 13, 221, 218, 201, 208, 175, 4, 234, 37, 230, 169, 118, 48, + 173, 7, 40, 135, 139, 163, 212, 196, 91, 21, 99, 2, 173, 155, + 102, 130, 11, 93, 89, 44, 41, 126, 160, 202, 46, 215, 253, 105, + 251, 73, 244, 163, 103, 175, 187, 156, 65, 151, 54, 216, 46, 60, + 229, 212, 248, 111, 141, 215, 198, 150, 22, 149, 34, 88, 192, 63, + 158, 92, 244, 156, 68, 166, 78, 69, 15, 27, 222, 155, 141, 150, + 135, 172, 102, 199, 182, 98, 24, 211, 239, 44, 71, 219, 165, 69, + 162, 35, 243, 11, 218, 33, 171, 140, 138, 215, 76, 64, 197, 203, + 253, 132, 66, 18, 58, 123, 223, 160, 127, 124, 235, 114, 138, 51, + 231, 143, 166, 181, 134, 111, 67, 69, 249, 168, 101, 121, 110, 221, + 115, 183, 236, 152, 202, 175, 183, 153, 59, 167, 113, 195, 113, 71, + 181, 219, 201, 2, 149, 21, 246, 69, 91, 235, 51, 11, 42, 10, + 76, 214, 72, 219, 108, 10, 152, 86, 137, 93, 94, 138, 44, 207, + 152, 125, 198, 192, 36, 248, 91, 219, 201, 58, 65, 24, 27, 59, + 176, 103, 24, 214, 165, 11, 147, 251, 8, 6, 67, 254, 111, 172, + 222, 194, 19, 212, 9, 200, 198, 208, 114, 193, 81, 209, 156, 17, + 89, 85, 155, 225, 138, 122, 63, 83, 23, 183, 145, 99, 33, 62, + 143, 180, 114, 132, 225, 66, 130, 152, 44, 26, 209, 52, 130, 20, + 219, 0, 171, 35, 242, 72, 159, 165, 52, 35, 113, 188, 192, 18, + 27, 97, 10, 66, 217, 26, 18, 46, 253, 240, 64, 45, 22, 56, + 161, 58, 1, 180, 244, 204, 208, 146, 188, 122, 176, 118, 250, 38, + 64, 139, 234, 203, 221, 1, 109, 49, 67, 18, 160, 218, 225, 134, + 115, 25, 143, 108, 147, 25, 118, 108, 79, 167, 203, 73, 99, 104, + 9, 18, 130, 92, 151, 90, 190, 24, 62, 231, 145, 217, 243, 178, + 186, 200, 251, 237, 159, 92, 29, 165, 207, 46, 178, 107, 230, 38, + 131, 149, 49, 255, 151, 133, 72, 163, 3, 135, 239, 221, 11, 163, + 137, 141, 251, 190, 13, 81, 15, 179, 80, 8, 117, 177, 124, 108, + 8, 65, 68, 199, 38, 46, 157, 139, 53, 23, 111, 49, 84, 232, + 144, 213, 36, 90, 236, 160, 177, 12, 90, 91, 108, 41, 221, 144, + 60, 105, 135, 200, 41, 51, 65, 198, 33, 144, 129, 134, 95, 196, + 91, 175, 180, 30, 56, 187, 248, 210, 180, 16, 62, 187, 146, 163, + 248, 1, 242, 56, 121, 149, 93, 72, 214, 2, 40, 155, 219, 41, + 90, 160, 120, 194, 200, 108, 235, 38, 44, 87, 208, 63, 124, 129, + 101, 41, 82, 247, 141, 85, 198, 110, 162, 45, 139, 170, 234, 155, + 169, 139, 217, 255, 226, 202, 132, 132, 18, 193, 116, 131, 132, 210, + 45, 231, 170, 13, 158, 211, 104, 115, 123, 69, 88, 237, 180, 121, + 109, 134, 89, 219, 163, 111, 197, 219, 158, 100, 108, 199, 135, 248, + 210, 56, 3, 2, 192, 34, 147, 46, 253, 216, 242, 136, 26, 20, + 195, 22, 105, 202, 180, 160, 110, 36, 178, 33, 60, 177, 43, 173, + 48, 132, 247, 156, 5, 47, 9, 33, 241, 94, 153, 92, 161, 4, + 205, 11, 191, 56, 105, 97, 8, 253, 222, 189, 52, 235, 25, 126, + 3, 179, 245, 10, 137, 62, 207, 14, 58, 246, 138, 122, 192, 158, + 19, 233, 6, 144, 168, 13, 19, 227, 100, 209, 68, 46, 59, 111, + 171, 31, 131, 39, 175, 112, 234, 32, 68, 195, 233, 5, 220, 214, + 0, 164, 87, 10, 114, 246, 182, 181, 160, 237, 200, 119, 85, 187, + 131, 59, 13, 145, 168, 116, 249, 91, 143, 100, 174, 128, 60, 126, + 135, 140, 72, 101, 109, 67, 248, 127, 27, 30, 157, 68, 116, 152, + 229, 142, 236, 75, 55, 191, 40, 255, 225, 80, 95, 139, 91, 241, + 52, 253, 97, 99, 37, 163, 131, 216, 16, 57, 177, 148, 42, 229, + 52, 100, 33, 149, 9, 74, 211, 253, 215, 150, 106, 84, 183, 73, + 227, 72, 23, 52, 207, 172, 92, 39, 98, 5, 183, 249, 238, 179, + 28, 224, 24, 185, 86, 212, 224, 148, 205, 196, 150, 171, 58, 229, + 156, 186, 40, 30, 208, 190, 217, 148, 184, 78, 99, 198, 21, 131, + 65, 118, 77, 113, 123, 215, 224, 216, 37, 100, 155, 254, 250, 74, + 108, 112, 192, 17, 76, 229, 21, 56, 171, 29, 12, 165, 25, 59, + 62, 108, 157, 161, 67, 72, 41, 87, 25, 145, 190, 203, 34, 207, + 203, 18, 238, 253, 245, 92, 6, 203, 77, 43, 24, 12, 3, 171, + 125, 253, 215, 224, 120, 217, 250, 20, 38, 128, 190, 211, 196, 155, + 59, 84, 40, 254, 61, 119, 15, 180, 187, 207, 14, 0, 156, 195, + 143, 203, 233, 198, 52, 198, 14, 77, 156, 14, 183, 212, 255, 251, + 244, 13, 33, 137, 122, 33, 198, 151, 188, 54, 41, 140, 195, 44, + 225, 33, 50, 199, 151, 202, 50, 184, 93, 224, 235, 31, 111, 187, + 238, 239, 110, 155, 220, 192, 130, 54, 98, 83, 122, 160, 58, 182, + 253, 13, 91, 76, 142, 215, 137, 218, 108, 190, 42, 117, 222, 31, + 88, 129, 254, 105, 165, 47, 248, 156, 171, 70, 176, 156, 47, 196, + 75, 6, 17, 21, 224, 36, 126, 144, 163, 77, 12, 101, 195, 143, + 172, 69, 239, 172, 138, 64, 242, 141, 53, 99, 53, 199, 150, 46, + 232, 243, 163, 17, 73, 137, 65, 34, 157, 13, 205, 97, 119, 240, + 66, 135, 155, 43, 6, 228, 215, 196, 205, 190, 124, 184, 76, 215, + 204, 119, 149, 168, 241, 15, 160, 200, 152, 255, 239, 185, 128, 22, + 189, 197, 61, 148, 231, 251, 39, 31, 168, 191, 40, 176, 60, 163, + 82, 134, 74, 186, 50, 189, 81, 61, 229, 204, 82, 86, 212, 112, + 55, 158, 152, 192, 252, 137, 105, 96, 92, 237, 83, 20, 122, 90, + 80, 208, 41, 2, 77, 64, 6, 29, 7, 152, 133, 18, 240, 142, + 142, 116, 150, 224, 14, 246, 238, 103, 107, 254, 89, 133, 42, 232, + 94, 160, 171, 244, 182, 24, 110, 198, 157, 227, 64, 153, 204, 155, + 217, 28, 212, 30, 29, 160, 81, 22, 5, 178, 140, 84, 2, 162, + 79, 0, 226, 195, 7, 18, 218, 129, 36, 184, 25, 242, 223, 117, + 79, 7, 209, 182, 124, 233, 166, 140, 17, 31, 142, 223, 87, 208, + 111, 180, 79, 84, 141, 239, 161, 138, 225, 176, 35, 183, 143, 147, + 167, 89, 145, 147, 170, 155, 249, 146, 109, 98, 146, 90, 222, 161, + 34, 209, 222, 70, 95, 197, 62, 80, 241, 153, 167, 253, 229, 237, + 51, 178, 1, 64, 183, 254, 113, 179, 32, 242, 140, 189, 150, 106, + 224, 112, 13, 83, 42, 28, 141, 87, 254, 91, 203, 35, 151, 209, + 145, 108, 10, 241, 39, 200, 106, 242, 207, 241, 57, 29, 114, 219, + 8, 176, 201, 211, 87, 221, 244, 183, 53, 234, 132, 251, 136, 64, + 144, 106, 131, 144, 109, 54, 239, 181, 4, 245, 64, 164, 202, 63, + 114, 153, 29, 138, 80, 84, 223, 125, 15, 13, 178, 33, 79, 69, + 91, 104, 120, 185, 140, 97, 21, 96, 110, 29, 59, 223, 254, 147, + 248, 193, 15, 242, 55, 227, 139, 200, 225, 90, 6, 97, 208, 172, + 232, 47, 207, 130, 164, 233, 205, 156, 16, 125, 167, 186, 170, 156, + 183, 225, 225, 76, 147, 118, 60, 104, 95, 114, 114, 6, 206, 184, + 237, 141, 193, 116, 115, 128, 224, 191, 220, 135, 216, 207, 103, 21, + 236, 209, 154, 199, 158, 248, 39, 128, 192, 123, 148, 225, 6, 10, + 171, 226, 1, 39, 161, 98, 10, 210, 236, 160, 156, 232, 143, 57, + 6, 156, 28, 232, 83, 204, 132, 158, 100, 45, 186, 198, 32, 124, + 252, 133, 93, 203, 136, 94, 173, 44, 171, 38, 196, 207, 110, 180, + 240, 108, 50, 153, 134, 61, 96, 179, 71, 35, 128, 213, 32, 93, + 187, 203, 114, 97, 171, 179, 74, 52, 142, 198, 179, 247, 94, 120, + 210, 229, 202, 9, 23, 165, 163, 201, 2, 190, 250, 20, 83, 220, + 253, 122, 17, 96, 14, 39, 101, 71, 236, 165, 92, 209, 51, 167, + 51, 192, 191, 165, 35, 43, 51, 34, 196, 28, 224, 56, 11, 63, + 41, 90, 45, 33, 182, 48, 226, 208, 213, 248, 247, 115, 77, 63, + 73, 162, 247, 114, 190, 135, 38, 190, 200, 131, 153, 150, 105, 194, + 116, 184, 254, 228, 68, 108, 12, 215, 216, 46, 28, 43, 169, 147, + 62, 232, 233, 251, 201, 211, 83, 50, 62, 43, 4, 127, 185, 215, + 220, 137, 58, 26, 83, 168, 14, 5, 140, 30, 193, 174, 79, 222, + 67, 105, 49, 27, 227, 242, 173, 129, 229, 136, 101, 62, 2, 43, + 222, 2, 229, 29, 103, 243, 46, 209, 103, 185, 61, 171, 142, 109, + 64, 122, 13, 162, 86, 105, 18, 208, 73, 145, 213, 117, 62, 214, + 43, 126, 230, 143, 47, 57, 115, 93, 122, 248, 227, 211, 165, 210, + 44, 5, 238, 115, 31, 136, 209, 127, 251, 32, 86, 60, 172, 60, + 174, 115, 116, 67, 121, 147, 1, 62, 205, 35, 63, 224, 142, 7, + 14, 211, 80, 78, 38, 197, 60, 85, 12, 234, 170, 93, 15, 224, + 90, 205, 243, 84, 187, 217, 137, 87, 218, 232, 142, 251, 186, 165, + 166, 125, 16, 121, 15, 240, 129, 113, 80, 9, 81, 128, 161, 121, + 163, 239, 199, 199, 96, 156, 136, 85, 238, 34, 112, 240, 230, 199, + 88, 28, 203, 177, 185, 51, 81, 125, 55, 103, 66, 156, 146, 239, + 166, 10, 25, 164, 22, 90, 199, 63, 50, 208, 44, 185, 166, 138, + 41, 253, 30, 111, 103, 70, 168, 194, 132, 166, 173, 168, 78, 154, + 107, 43, 50, 9, 135, 15, 95, 46, 106, 255, 115, 16, 161, 230, + 126, 255, 243, 66, 59, 66, 178, 216, 58, 61, 9, 56, 199, 181, + 138, 246, 140, 254, 203, 180, 127, 29, 239, 199, 169, 29, 161, 96, + 50, 199, 131, 86, 3, 212, 224, 254, 117, 189, 235, 247, 18, 38, + 113, 231, 249, 13, 178, 183, 18, 36, 136, 247, 218, 71, 90, 115, + 58, 250, 205, 83, 48, 192, 45, 114, 106, 112, 241, 211, 48, 23, + 157, 203, 58, 236, 78, 191, 56, 202, 159, 99, 212, 117, 240, 76, + 202, 42, 1, 89, 70, 17, 185, 90, 147, 131, 209, 131, 224, 150, + 120, 219, 221, 80, 83, 131, 15, 190, 113, 17, 170, 233, 231, 158, + 68, 91, 177, 212, 255, 2, 222, 73, 145, 8, 131, 44, 113, 182, + 176, 154, 113, 237, 227, 232, 45, 147, 111, 175, 166, 89, 75, 114, + 70, 203, 156, 224, 31, 66, 220, 194, 110, 194, 55, 11, 159, 147, + 116, 59, 85, 168, 30, 14, 120, 39, 203, 72, 143, 219, 222, 25, + 200, 104, 38, 17, 109, 130, 182, 93, 130, 42, 88, 204, 233, 22, + 15, 19, 67, 224, 251, 197, 17, 191, 172, 243, 160, 67, 143, 235, + 181, 217, 124, 171, 38, 189, 16, 237, 196, 151, 104, 22, 67, 166, + 91, 173, 64, 215, 9, 108, 84, 79, 21, 29, 176, 49, 49, 167, + 83, 223, 194, 208, 20, 5, 37, 48, 132, 92, 38, 220, 143, 88, + 69, 179, 112, 71, 201, 240, 209, 68, 229, 253, 244, 31, 115, 194, + 52, 14, 164, 166, 121, 209, 121, 206, 103, 153, 40, 37, 183, 210, + 149, 25, 176, 232, 161, 86, 176, 118, 118, 97, 174, 217, 179, 52, + 72, 133, 5, 136, 7, 65, 21, 22, 214, 213, 168, 217, 200, 194, + 234, 85, 19, 248, 138, 18, 200, 228, 1, 248, 237, 188, 172, 152, + 74, 224, 4, 117, 77, 4, 103, 169, 193, 122, 179, 227, 220, 172, + 118, 201, 170, 205, 166, 194, 213, 105, 21, 169, 93, 253, 217, 172, + 238, 220, 66, 63, 246, 230, 141, 148, 35, 163, 253, 104, 54, 241, + 128, 191, 77, 187, 44, 53, 34, 36, 26, 152, 112, 237, 166, 83, + 155, 229, 8, 15, 74, 22, 195, 249, 158, 183, 217, 65, 115, 168, + 65, 247, 102, 110, 131, 253, 78, 217, 68, 30, 62, 101, 32, 7, + 171, 9, 235, 102, 221, 183, 138, 233, 49, 69, 254, 209, 186, 121, + 177, 207, 217, 66, 206, 82, 203, 126, 0, 213, 202, 112, 183, 246, + 8, 111, 169, 97, 165, 183, 252, 234, 33, 251, 137, 6, 94, 217, + 68, 25, 173, 69, 33, 29, 74, 196, 29, 138, 219, 64, 109, 209, + 222, 250, 198, 147, 206, 8, 58, 234, 39, 242, 75, 20, 244, 91, + 34, 98, 210, 157, 21, 95, 190, 244, 188, 225, 73, 19, 122, 50, + 201, 32, 45, 42, 161, 142, 216, 144, 18, 6, 174, 66, 186, 157, + 116, 71, 148, 247, 233, 5, 111, 120, 9, 245, 154, 94, 158, 108, + 78, 159, 168, 91, 26, 171, 24, 64, 89, 49, 1, 168, 158, 44, + 77, 135, 182, 49, 130, 25, 167, 104, 216, 188, 0, 192, 172, 102, + 236, 34, 159, 156, 58, 186, 0, 51, 189, 128, 170, 80, 177, 115, + 178, 24, 10, 34, 116, 214, 105, 236, 181, 180, 192, 168, 145, 250, + 221, 83, 40, 109, 126, 142, 205, 252, 222, 236, 166, 79, 174, 175, + 34, 5, 212, 138, 16, 112, 52, 173, 99, 184, 122, 182, 145, 73, + 29, 161, 64, 138, 73, 0, 34, 220, 99, 97, 20, 125, 208, 206, + 234, 28, 29, 100, 248, 132, 159, 21, 12, 31, 152, 24, 215, 175, + 193, 165, 200, 117, 119, 152, 154, 250, 105, 240, 172, 135, 29, 41, + 174, 8, 167, 98, 13, 129, 165, 162, 221, 108, 235, 64, 117, 150, + 42, 111, 193, 137, 19, 255, 198, 253, 112, 116, 146, 155, 15, 138, + 95, 16, 88, 112, 137, 58, 27, 77, 129, 226, 34, 182, 243, 132, + 196, 57, 77, 54, 55, 70, 20, 115, 23, 34, 99, 200, 191, 186, + 219, 173, 4, 92, 0, 88, 68, 9, 172, 30, 80, 157, 133, 123, + 163, 233, 13, 108, 165, 92, 136, 160, 17, 89, 110, 174, 66, 9, + 64, 166, 223, 208, 102, 125, 196, 152, 63, 119, 206, 109, 47, 44, + 197, 63, 131, 82, 231, 127, 207, 196, 49, 203, 80, 166, 83, 87, + 17, 154, 194, 149, 53, 250, 179, 185, 21, 245, 22, 105, 168, 237, + 27, 207, 126, 203, 213, 238, 239, 215, 205, 37, 253, 43, 83, 233, + 144, 33, 167, 221, 67, 132, 132, 55, 29, 78, 183, 60, 190, 243, + 210, 137, 18, 228, 51, 89, 110, 52, 180, 51, 52, 87, 170, 157, + 207, 22, 250, 34, 208, 56, 213, 108, 137, 131, 20, 221, 37, 180, + 182, 20, 253, 73, 186, 65, 168, 52, 124, 103, 238, 85, 254, 204, + 117, 131, 177, 69, 125, 46, 203, 245, 122, 65, 253, 234, 109, 201, + 128, 197, 24, 108, 87, 63, 44, 90, 158, 241, 115, 143, 13, 236, + 234, 182, 21, 87, 190, 1, 72, 131, 123, 86, 146, 16, 235, 140, + 66, 18, 206, 115, 182, 102, 74, 51, 101, 176, 69, 32, 65, 55, + 212, 236, 114, 15, 16, 81, 129, 108, 250, 1, 190, 159, 181, 19, + 230, 4, 173, 223, 158, 208, 58, 96, 179, 229, 163, 253, 164, 18, + 72, 14, 253, 148, 21, 238, 153, 245, 232, 134, 93, 68, 248, 57, + 128, 234, 145, 56, 128, 183, 245, 123, 253, 45, 78, 182, 183, 215, + 178, 160, 120, 226, 182, 253, 27, 162, 214, 156, 78, 117, 221, 119, + 48, 98, 112, 43, 85, 188, 217, 150, 205, 4, 242, 162, 61, 152, + 53, 202, 199, 54, 73, 79, 224, 8, 190, 247, 7, 178, 129, 125, + 91, 60, 116, 61, 248, 91, 1, 94, 241, 116, 161, 225, 33, 133, + 16, 154, 22, 46, 39, 90, 98, 223, 147, 67, 175, 40, 174, 50, + 2, 115, 59, 68, 131, 107, 178, 99, 169, 92, 203, 231, 166, 200, + 166, 248, 220, 25, 74, 174, 75, 202, 17, 131, 119, 62, 88, 153, + 134, 51, 206, 228, 127, 202, 28, 213, 144, 49, 14, 61, 176, 245, + 38, 131, 172, 245, 8, 34, 112, 143, 156, 25, 18, 27, 113, 201, + 44, 22, 166, 213, 44, 105, 149, 31, 185, 219, 116, 201, 61, 174, + 63, 169, 231, 27, 117, 6, 255, 61, 43, 103, 108, 229, 87, 93, + 157, 78, 104, 128, 237, 71, 39, 130, 31, 42, 142, 234, 73, 97, + 189, 69, 106, 240, 13, 9, 77, 113, 59, 147, 102, 192, 169, 214, + 117, 167, 27, 198, 9, 95, 60, 78, 72, 193, 24, 64, 147, 124, + 47, 96, 169, 201, 152, 172, 7, 131, 24, 234, 113, 127, 99, 219, + 116, 193, 33, 84, 90, 143, 50, 83, 69, 172, 86, 152, 56, 63, + 33, 13, 181, 130, 10, 249, 220, 8, 67, 12, 29, 40, 193, 15, + 124, 169, 204, 22, 230, 191, 67, 34, 149, 171, 180, 36, 190, 16, + 33, 109, 106, 96, 137, 182, 121, 187, 114, 149, 113, 56, 72, 36, + 86, 161, 217, 51, 215, 137, 196, 173, 143, 48, 202, 24, 195, 95, + 33, 90, 27, 83, 17, 249, 198, 213, 152, 181, 75, 241, 30, 21, + 116, 180, 213, 141, 189, 78, 182, 130, 197, 227, 197, 182, 114, 58, + 3, 82, 14, 188, 28, 62, 38, 176, 177, 246, 44, 100, 109, 218, + 19, 116, 208, 88, 220, 216, 254, 1, 142, 95, 242, 84, 17, 25, + 95, 25, 27, 196, 95, 215, 94, 97, 215, 170, 100, 173, 129, 10, + 233, 225, 161, 99, 177, 250, 34, 139, 195, 98, 42, 116, 96, 132, + 227, 85, 227, 45, 162, 216, 121, 190, 104, 143, 96, 48, 93, 27, + 172, 230, 98, 69, 233, 6, 27, 244, 19, 95, 248, 239, 96, 212, + 233, 116, 64, 13, 195, 60, 143, 174, 247, 211, 190, 207, 220, 172, + 6, 126, 75, 126, 141, 35, 89, 10, 73, 231, 250, 133, 243, 164, + 113, 230, 135, 1, 192, 189, 35, 200, 183, 79, 120, 49, 50, 183, + 174, 54, 137, 201, 192, 244, 134, 241, 243, 70, 108, 18, 209, 127, + 246, 193, 155, 154, 88, 16, 151, 213, 224, 26, 247, 8, 48, 16, + 103, 132, 62, 179, 205, 255, 69, 34, 111, 88, 45, 175, 206, 186, + 99, 202, 140, 238, 117, 141, 161, 117, 12, 157, 15, 231, 159, 63, + 216, 250, 248, 71, 199, 169, 74, 60, 241, 169, 70, 10, 11, 122, + 197, 197, 245, 246, 188, 238, 141, 167, 182, 45, 161, 179, 13, 31, + 138, 65, 46, 139, 253, 173, 105, 191, 242, 106, 180, 64, 201, 113, + 40, 68, 143, 0, 251, 248, 136, 66, 163, 11, 66, 46, 6, 129, + 148, 204, 182, 211, 164, 228, 25, 158, 214, 192, 56, 144, 52, 203, + 150, 62, 6, 241, 105, 201, 9, 92, 156, 50, 107, 105, 10, 156, + 23, 246, 15, 13, 115, 146, 23, 134, 94, 56, 10, 42, 247, 69, + 53, 9, 47, 79, 40, 40, 86, 222, 161, 221, 39, 177, 204, 48, + 169, 51, 210, 246, 136, 205, 130, 247, 130, 69, 7, 193, 196, 21, + 115, 51, 86, 45, 183, 146, 34, 53, 61, 169, 162, 197, 55, 206, + 102, 110, 2, 221, 182, 31, 252, 10, 233, 143, 56, 141, 173, 54, + 169, 49, 7, 160, 62, 115, 246, 225, 133, 238, 0, 57, 236, 243, + 210, 150, 57, 228, 37, 101, 112, 151, 91, 249, 85, 56, 174, 231, + 204, 148, 83, 188, 34, 93, 190, 71, 211, 100, 146, 164, 137, 120, + 30, 142, 56, 61, 9, 70, 225, 202, 132, 51, 200, 81, 25, 208, + 240, 14, 105, 38, 136, 45, 51, 214, 89, 177, 243, 43, 140, 73, + 242, 156, 197, 28, 248, 218, 71, 207, 151, 212, 187, 160, 250, 148, + 209, 14, 92, 52, 138, 90, 28, 34, 53, 130, 162, 231, 237, 89, + 43, 189, 107, 15, 101, 161, 126, 184, 17, 1, 151, 20, 39, 91, + 184, 229, 176, 73, 177, 22, 165, 241, 8, 16, 145, 106, 183, 3, + 177, 129, 3, 44, 45, 15, 92, 183, 59, 218, 124, 243, 194, 255, + 37, 102, 67, 37, 6, 28, 5, 44, 146, 233, 22, 128, 148, 41, + 200, 37, 76, 166, 228, 137, 126, 9, 109, 225, 64, 59, 53, 33, + 255, 157, 55, 214, 85, 31, 192, 167, 109, 153, 61, 14, 119, 168, + 227, 104, 103, 207, 189, 224, 16, 159, 35, 190, 14, 7, 200, 106, + 35, 204, 218, 255, 15, 106, 21, 199, 28, 105, 146, 59, 107, 53, + 118, 244, 87, 25, 138, 176, 105, 43, 255, 209, 205, 227, 191, 38, + 203, 98, 130, 127, 68, 160, 54, 152, 4, 167, 82, 148, 71, 78, + 151, 82, 157, 151, 137, 21, 102, 142, 232, 187, 100, 34, 0, 176, + 25, 158, 117, 88, 95, 171, 239, 222, 21, 38, 53, 232, 53, 210, + 215, 76, 187, 42, 225, 148, 120, 234, 189, 35, 103, 66, 138, 245, + 170, 229, 84, 57, 40, 200, 247, 79, 178, 81, 169, 213, 161, 57, + 94, 1, 29, 81, 3, 251, 166, 135, 60, 117, 236, 235, 172, 116, + 132, 27, 145, 173, 20, 232, 126, 157, 169, 133, 34, 194, 15, 87, + 181, 0, 182, 68, 228, 109, 241, 66, 35, 18, 32, 77, 221, 128, + 103, 118, 131, 13, 87, 6, 153, 214, 150, 177, 79, 119, 61, 213, + 141, 233, 114, 63, 224, 199, 185, 154, 86, 250, 47, 98, 9, 47, + 106, 166, 131, 228, 172, 237, 21, 80, 44, 159, 180, 56, 20, 3, + 193, 38, 9, 77, 139, 110, 86, 178, 206, 69, 0, 240, 136, 35, + 0, 239, 51, 221, 18, 8, 13, 123, 186, 188, 197, 246, 58, 42, + 118, 202, 110, 59, 5, 212, 209, 135, 219, 124, 172, 150, 181, 36, + 212, 212, 228, 145, 77, 132, 62, 124, 76, 231, 186, 193, 249, 155, + 154, 168, 79, 109, 175, 240, 184, 244, 202, 84, 112, 241, 41, 255, + 255, 245, 20, 195, 58, 252, 56, 3, 4, 18, 112, 137, 231, 194, + 72, 162, 109, 126, 194, 143, 237, 102, 139, 21, 17, 88, 100, 185, + 242, 137, 65, 100, 213, 97, 249, 244, 234, 50, 65, 150, 131, 213, + 61, 141, 153, 149, 174, 92, 125, 199, 44, 121, 159, 24, 10, 231, + 108, 224, 79, 114, 253, 221, 194, 139, 226, 36, 68, 90, 247, 182, + 82, 190, 108, 172, 252, 255, 83, 169, 147, 208, 179, 27, 21, 111, + 151, 17, 209, 201, 21, 134, 9, 89, 175, 84, 199, 14, 223, 218, + 7, 159, 147, 222, 230, 61, 146, 62, 56, 76, 224, 95, 206, 146, + 154, 71, 84, 203, 246, 223, 70, 103, 141, 138, 122, 235, 187, 184, + 104, 61, 240, 186, 73, 169, 154, 175, 4, 107, 77, 186, 174, 21, + 169, 88, 7, 33, 222, 137, 114, 187, 119, 218, 100, 16, 130, 113, + 231, 146, 107, 42, 111, 135, 233, 251, 58, 6, 26, 155, 58, 172, + 80, 236, 237, 196, 179, 149, 149, 149, 220, 198, 177, 127, 173, 159, + 36, 0, 168, 4, 87, 32, 211, 66, 241, 201, 155, 184, 170, 118, + 145, 96, 124, 106, 225, 174, 251, 212, 111, 8, 102, 54, 155, 209, + 184, 151, 1, 43, 186, 81, 221, 33, 37, 235, 0, 88, 43, 231, + 21, 169, 37, 117, 233, 37, 59, 88, 159, 89, 243, 130, 119, 122, + 133, 161, 159, 173, 145, 33, 6, 193, 205, 58, 37, 144, 247, 163, + 255, 60, 240, 46, 63, 144, 181, 19, 19, 215, 67, 211, 197, 158, + 89, 206, 202, 64, 183, 244, 16, 83, 0, 223, 211, 214, 164, 54, + 106, 249, 124, 130, 90, 56, 78, 132, 2, 17, 118, 156, 33, 255, + 186, 109, 120, 128, 235, 246, 87, 72, 129, 55, 255, 161, 77, 69, + 162, 115, 57, 210, 235, 109, 136, 200, 229, 21, 191, 61, 5, 160, + 70, 86, 196, 115, 72, 2, 154, 110, 98, 90, 195, 218, 78, 160, + 75, 149, 28, 255, 128, 118, 75, 108, 106, 63, 199, 1, 161, 49, + 0, 20, 131, 252, 46, 30, 212, 77, 235, 27, 189, 109, 99, 138, + 197, 31, 206, 145, 5, 116, 54, 215, 56, 166, 18, 96, 76, 148, + 240, 174, 32, 104, 69, 187, 87, 99, 34, 116, 5, 179, 95, 72, + 254, 173, 40, 102, 174, 25, 63, 58, 90, 191, 212, 204, 83, 236, + 217, 198, 42, 228, 100, 91, 208, 3, 170, 113, 190, 232, 160, 104, + 130, 110, 181, 89, 205, 238, 5, 102, 102, 137, 23, 90, 75, 37, + 236, 100, 208, 114, 150, 90, 182, 145, 53, 160, 128, 147, 44, 171, + 132, 208, 17, 229, 199, 211, 213, 102, 3, 73, 61, 58, 199, 226, + 74, 235, 44, 236, 224, 121, 71, 157, 177, 49, 223, 174, 103, 243, + 111, 83, 243, 104, 157, 246, 183, 144, 121, 125, 151, 220, 32, 44, + 137, 22, 21, 0, 59, 126, 103, 7, 141, 249, 204, 110, 137, 204, + 240, 130, 241, 62, 93, 77, 198, 227, 146, 36, 194, 84, 176, 144, + 11, 118, 132, 209, 141, 169, 148, 111, 207, 102, 59, 178, 149, 110, + 30, 233, 151, 87, 179, 39, 50, 196, 145, 128, 181, 83, 150, 3, + 178, 247, 186, 143, 44, 67, 81, 105, 34, 241, 153, 115, 30, 245, + 197, 28, 255, 18, 78, 212, 4, 32, 84, 182, 66, 0, 82, 216, + 120, 235, 250, 132, 246, 57, 236, 70, 132, 137, 57, 223, 146, 182, + 194, 138, 104, 197, 126, 169, 60, 174, 201, 58, 152, 171, 55, 103, + 48, 100, 133, 98, 218, 189, 125, 184, 231, 244, 99, 225, 104, 63, + 166, 220, 57, 181, 9, 242, 0, 57, 213, 249, 97, 144, 247, 211, + 213, 95, 110, 17, 72, 33, 7, 37, 96, 38, 7, 199, 14, 12, + 151, 41, 106, 34, 236, 218, 8, 28, 21, 29, 105, 214, 168, 155, + 47, 127, 75, 210, 73, 184, 106, 146, 176, 131, 241, 146, 179, 61, + 54, 118, 101, 190, 186, 113, 241, 141, 141, 92, 82, 182, 213, 172, + 238, 148, 14, 72, 39, 174, 191, 37, 213, 73, 186, 20, 117, 176, + 12, 78, 250, 228, 79, 236, 201, 172, 45, 215, 216, 103, 35, 152, + 150, 120, 202, 250, 94, 96, 184, 88, 43, 154, 115, 73, 213, 58, + 27, 235, 149, 161, 46, 34, 13, 194, 92, 235, 159, 229, 74, 46, + 95, 14, 101, 191, 53, 95, 89, 81, 139, 63, 75, 58, 160, 105, + 10, 65, 148, 171, 84, 253, 179, 232, 170, 12, 248, 206, 198, 174, + 222, 128, 252, 220, 66, 224, 233, 113, 137, 188, 167, 122, 205, 67, + 172, 247, 120, 174, 214, 175, 128, 237, 133, 185, 210, 195, 118, 102, + 11, 176, 112, 90, 159, 248, 6, 209, 49, 47, 223, 252, 37, 51, + 71, 132, 111, 127, 92, 226, 18, 125, 214, 161, 246, 69, 33, 146, + 201, 111, 35, 59, 217, 205, 33, 209, 233, 197, 97, 26, 23, 75, + 210, 96, 122, 116, 149, 59, 59, 206, 195, 208, 73, 197, 59, 241, + 100, 58, 156, 183, 57, 114, 128, 141, 214, 230, 58, 27, 165, 102, + 204, 240, 67, 102, 205, 80, 61, 13, 131, 10, 179, 41, 216, 247, + 87, 222, 97, 207, 225, 234, 206, 193, 124, 90, 229, 135, 255, 250, + 129, 26, 225, 79, 35, 102, 182, 154, 186, 84, 80, 194, 226, 39, + 150, 195, 147, 48, 57, 242, 89, 45, 134, 183, 171, 166, 115, 212, + 198, 25, 161, 252, 167, 59, 194, 152, 214, 117, 190, 83, 85, 17, + 211, 29, 63, 249, 66, 224, 209, 250, 82, 181, 19, 84, 160, 172, + 144, 212, 25, 49, 173, 32, 219, 215, 213, 254, 115, 83, 176, 120, + 251, 251, 100, 219, 180, 33, 81, 109, 204, 239, 71, 19, 165, 202, + 207, 148, 33, 207, 8, 241, 175, 31, 250, 33, 61, 152, 221, 173, + 199, 40, 162, 180, 99, 33, 148, 93, 161, 172, 54, 30, 21, 149, + 220, 140, 18, 179, 2, 253, 61, 127, 64, 84, 181, 92, 210, 97, + 155, 193, 219, 60, 105, 73, 94, 42, 243, 206, 54, 187, 48, 194, + 7, 188, 139, 183, 113, 170, 25, 47, 88, 73, 174, 155, 198, 156, + 93, 226, 168, 14, 131, 131, 251, 50, 179, 177, 71, 47, 24, 213, + 77, 3, 243, 54, 68, 169, 104, 104, 156, 99, 121, 204, 141, 222, + 152, 118, 70, 115, 206, 74, 178, 160, 164, 107, 34, 139, 28, 70, + 96, 44, 244, 227, 65, 22, 162, 178, 71, 32, 151, 9, 22, 90, + 13, 119, 4, 202, 191, 128, 151, 165, 148, 196, 74, 183, 192, 101, + 211, 96, 23, 37, 155, 44, 47, 1, 243, 254, 13, 45, 160, 159, + 65, 30, 131, 233, 138, 234, 46, 102, 34, 113, 221, 213, 232, 113, + 49, 178, 184, 69, 175, 31, 88, 97, 66, 178, 82, 74, 102, 235, + 189, 156, 219, 117, 87, 40, 40, 172, 13, 129, 240, 44, 161, 184, + 200, 179, 166, 47, 232, 208, 168, 94, 93, 213, 192, 36, 178, 71, + 156, 85, 196, 78, 121, 72, 43, 123, 174, 188, 206, 3, 118, 163, + 143, 7, 236, 42, 255, 98, 162, 70, 117, 76, 109, 209, 96, 32, + 109, 186, 120, 255, 104, 147, 130, 223, 188, 234, 126, 22, 112, 26, + 92, 111, 246, 228, 154, 60, 177, 48, 239, 53, 99, 237, 27, 66, + 82, 176, 5, 185, 162, 139, 123, 81, 107, 146, 50, 140, 23, 217, + 28, 111, 173, 178, 227, 223, 255, 40, 64, 69, 123, 224, 0, 130, + 168, 120, 95, 50, 31, 202, 113, 59, 13, 123, 36, 55, 50, 61, + 37, 134, 32, 91, 79, 69, 197, 136, 223, 40, 238, 163, 245, 109, + 229, 251, 17, 253, 210, 23, 78, 31, 94, 249, 155, 122, 212, 181, + 255, 155, 33, 241, 198, 25, 77, 120, 114, 20, 85, 160, 21, 246, + 46, 80, 236, 67, 201, 251, 89, 202, 155, 2, 106, 147, 165, 214, + 73, 151, 24, 56, 53, 66, 114, 129, 114, 2, 230, 127, 145, 110, + 249, 223, 33, 58, 134, 25, 33, 32, 12, 35, 197, 200, 152, 147, + 248, 60, 0, 250, 75, 49, 202, 235, 206, 35, 108, 197, 104, 209, + 114, 35, 177, 84, 181, 76, 145, 197, 130, 149, 121, 245, 163, 178, + 13, 229, 221, 177, 210, 14, 188, 5, 206, 166, 187, 56, 222, 209, + 45, 193, 21, 189, 123, 184, 10, 52, 235, 48, 29, 28, 102, 232, + 220, 72, 125, 105, 91, 169, 4, 242, 226, 235, 131, 56, 30, 110, + 254, 142, 230, 47, 30, 167, 135, 150, 35, 228, 210, 20, 191, 154, + 228, 239, 121, 126, 101, 147, 138, 180, 26, 122, 233, 50, 197, 239, + 90, 204, 17, 117, 196, 7, 4, 26, 235, 76, 240, 174, 64, 2, + 246, 65, 238, 244, 8, 22, 166, 173, 232, 236, 91, 122, 214, 15, + 26, 87, 57, 149, 27, 15, 63, 128, 99, 176, 191, 50, 93, 220, + 112, 181, 244, 142, 144, 16, 122, 11, 46, 60, 126, 34, 74, 115, + 146, 65, 184, 234, 40, 67, 132, 194, 114, 104, 120, 226, 208, 54, + 88, 3, 134, 19, 81, 131, 22, 239, 12, 215, 146, 228, 77, 240, + 191, 193, 208, 82, 58, 241, 218, 139, 215, 32, 141, 49, 94, 113, + 53, 208, 29, 127, 86, 212, 176, 236, 212, 37, 12, 170, 203, 212, + 209, 57, 57, 62, 163, 172, 149, 122, 15, 170, 7, 144, 230, 121, + 188, 250, 249, 181, 84, 14, 139, 212, 162, 130, 86, 90, 88, 172, + 177, 112, 254, 102, 17, 98, 231, 5, 214, 187, 65, 196, 102, 42, + 85, 101, 197, 178, 146, 222, 72, 44, 143, 181, 83, 123, 68, 165, + 109, 122, 112, 18, 157, 35, 151, 171, 159, 74, 6, 93, 157, 109, + 177, 90, 217, 149, 96, 115, 153, 8, 77, 143, 49, 249, 200, 117, + 163, 232, 24, 152, 133, 157, 192, 165, 142, 198, 54, 229, 211, 46, + 148, 136, 225, 202, 244, 119, 129, 64, 30, 152, 21, 163, 173, 172, + 206, 177, 75, 118, 141, 122, 72, 214, 81, 21, 70, 96, 89, 31, + 36, 123, 246, 150, 116, 49, 228, 26, 231, 1, 88, 214, 174, 180, + 110, 140, 196, 100, 247, 99, 229, 134, 250, 92, 88, 124, 146, 38, + 47, 252, 126, 224, 198, 157, 43, 230, 197, 115, 151, 254, 243, 8, + 68, 14, 106, 124, 131, 167, 218, 70, 101, 21, 110, 167, 196, 23, + 90, 252, 161, 182, 104, 152, 157, 197, 215, 147, 21, 75, 129, 235, + 180, 80, 10, 98, 57, 61, 100, 66, 80, 133, 85, 54, 136, 248, + 188, 182, 157, 65, 229, 198, 187, 170, 130, 138, 227, 95, 223, 65, + 28, 26, 90, 142, 224, 253, 197, 200, 42, 119, 236, 149, 207, 140, + 196, 224, 186, 122, 124, 108, 230, 17, 11, 84, 12, 130, 206, 74, + 131, 41, 190, 210, 118, 7, 202, 232, 108, 233, 144, 138, 211, 84, + 170, 68, 171, 39, 192, 161, 205, 14, 91, 115, 243, 235, 151, 36, + 121, 213, 55, 246, 150, 114, 74, 73, 156, 249, 31, 21, 44, 120, + 203, 200, 207, 254, 205, 254, 241, 118, 39, 106, 43, 23, 244, 190, + 65, 236, 45, 229, 106, 56, 168, 211, 139, 22, 159, 97, 190, 37, + 227, 181, 234, 129, 172, 80, 72, 40, 39, 179, 25, 145, 128, 116, + 14, 171, 198, 34, 134, 103, 223, 253, 9, 126, 255, 65, 215, 174, + 197, 75, 47, 157, 114, 149, 214, 255, 40, 110, 226, 118, 14, 211, + 182, 192, 94, 25, 91, 46, 86, 43, 154, 21, 148, 33, 98, 115, + 4, 174, 6, 69, 202, 163, 195, 45, 64, 187, 124, 193, 184, 29, + 68, 243, 145, 90, 238, 249, 186, 48, 79, 138, 252, 212, 14, 86, + 121, 98, 195, 114, 59, 246, 230, 30, 213, 1, 66, 6, 164, 227, + 125, 41, 235, 40, 148, 216, 197, 233, 92, 237, 5, 61, 213, 229, + 164, 201, 95, 114, 137, 16, 86, 145, 178, 212, 87, 84, 180, 236, + 99, 206, 64, 181, 11, 158, 102, 93, 85, 186, 215, 16, 143, 164, + 148, 63, 30, 118, 115, 150, 63, 165, 193, 9, 43, 105, 201, 228, + 12, 237, 109, 251, 9, 178, 145, 131, 221, 51, 63, 19, 30, 167, + 181, 223, 217, 46, 173, 180, 36, 120, 40, 210, 249, 70, 23, 224, + 75, 13, 169, 145, 68, 138, 194, 29, 183, 253, 191, 147, 71, 196, + 220, 101, 132, 248, 79, 147, 9, 209, 45, 90, 152, 131, 152, 43, + 54, 2, 20, 4, 174, 106, 245, 165, 77, 250, 140, 184, 252, 152, + 159, 175, 182, 215, 211, 93, 4, 227, 246, 247, 171, 77, 141, 128, + 121, 97, 57, 146, 237, 203, 191, 145, 151, 117, 143, 196, 219, 71, + 244, 32, 191, 249, 29, 57, 40, 39, 107, 140, 75, 80, 203, 185, + 122, 20, 12, 129, 219, 81, 149, 43, 139, 93, 161, 98, 110, 183, + 112, 35, 168, 231, 151, 166, 167, 196, 189, 226, 7, 85, 185, 133, + 214, 172, 77, 15, 55, 164, 90, 139, 158, 96, 215, 20, 31, 178, + 184, 14, 67, 69, 241, 187, 171, 6, 27, 204, 203, 146, 249, 87, + 237, 139, 46, 221, 255, 101, 99, 213, 22, 71, 159, 233, 217, 132, + 66, 45, 66, 130, 0, 103, 157, 145, 15, 219, 142, 217, 221, 236, + 28, 241, 111, 201, 160, 230, 3, 250, 192, 220, 174, 165, 98, 103, + 76, 83, 143, 131, 228, 26, 166, 229, 42, 239, 93, 165, 57, 230, + 189, 205, 198, 56, 120, 114, 80, 221, 82, 244, 250, 85, 105, 29, + 48, 214, 218, 120, 94, 80, 42, 64, 224, 227, 193, 26, 22, 205, + 221, 156, 250, 222, 176, 194, 121, 2, 135, 8, 229, 90, 122, 207, + 144, 134, 98, 180, 255, 251, 223, 205, 250, 217, 13, 182, 190, 202, + 130, 62, 132, 194, 9, 1, 196, 164, 49, 7, 33, 135, 115, 132, + 23, 227, 191, 249, 83, 141, 97, 11, 73, 183, 159, 221, 191, 177, + 39, 84, 141, 73, 63, 134, 68, 40, 139, 117, 113, 122, 72, 129, + 145, 248, 224, 162, 0, 10, 237, 110, 183, 251, 189, 221, 74, 217, + 229, 69, 159, 194, 147, 122, 242, 177, 238, 165, 136, 170, 238, 60, + 169, 174, 168, 23, 217, 121, 200, 23, 181, 160, 197, 42, 47, 74, + 61, 46, 54, 18, 252, 138, 48, 164, 136, 126, 64, 65, 207, 94, + 254, 252, 78, 172, 108, 42, 179, 222, 17, 161, 130, 246, 99, 219, + 196, 91, 181, 55, 98, 86, 240, 162, 208, 133, 110, 148, 23, 0, + 213, 115, 48, 239, 13, 178, 83, 26, 35, 146, 234, 73, 80, 211, + 145, 175, 47, 164, 199, 29, 204, 31, 114, 98, 164, 180, 187, 112, + 148, 92, 22, 156, 103, 40, 195, 130, 129, 193, 53, 139, 163, 133, + 115, 185, 154, 2, 53, 247, 251, 82, 23, 38, 25, 193, 237, 125, + 141, 236, 159, 0, 165, 103, 228, 241, 241, 36, 188, 30, 168, 252, + 40, 123, 117, 52, 108, 56, 100, 185, 114, 64, 172, 60, 76, 224, + 47, 238, 228, 93, 15, 154, 49, 93, 99, 96, 58, 82, 213, 40, + 105, 207, 111, 68, 76, 96, 93, 107, 37, 81, 71, 173, 56, 137, + 121, 125, 255, 214, 143, 229, 73, 183, 97, 182, 193, 212, 99, 152, + 8, 72, 128, 122, 19, 76, 218, 3, 69, 175, 225, 155, 221, 140, + 65, 37, 35, 57, 248, 34, 164, 230, 190, 96, 246, 13, 198, 39, + 155, 146, 104, 117, 107, 42, 142, 147, 60, 13, 32, 66, 207, 176, + 224, 19, 211, 198, 133, 6, 52, 75, 87, 62, 233, 132, 226, 2, + 186, 134, 7, 21, 13, 224, 160, 195, 99, 201, 24, 166, 33, 209, + 42, 136, 146, 223, 203, 178, 222, 187, 159, 202, 34, 87, 22, 213, + 213, 167, 141, 42, 86, 248, 33, 99, 132, 210, 163, 228, 239, 217, + 221, 250, 32, 141, 51, 195, 105, 27, 127, 7, 6, 115, 129, 59, + 12, 5, 13, 115, 95, 170, 40, 192, 19, 80, 155, 170, 59, 85, + 198, 75, 174, 10, 246, 212, 133, 138, 1, 44, 11, 149, 220, 98, + 58, 236, 132, 3, 145, 22, 60, 82, 112, 71, 161, 180, 28, 214, + 126, 16, 229, 15, 140, 84, 11, 151, 236, 68, 148, 191, 124, 190, + 75, 194, 223, 177, 117, 181, 3, 119, 11, 241, 234, 82, 22, 7, + 201, 128, 122, 189, 99, 149, 69, 169, 87, 242, 223, 236, 238, 21, + 75, 23, 234, 229, 186, 197, 140, 91, 116, 154, 84, 130, 178, 24, + 71, 163, 73, 225, 19, 79, 140, 98, 77, 234, 141, 61, 159, 136, + 250, 17, 181, 34, 19, 53, 215, 224, 240, 176, 202, 90, 47, 136, + 177, 209, 16, 171, 203, 55, 41, 210, 237, 58, 59, 161, 197, 44, + 30, 196, 17, 239, 14, 77, 77, 140, 151, 89, 27, 213, 123, 80, + 250, 182, 100, 65, 45, 185, 219, 81, 111, 114, 156, 1, 239, 65, + 158, 158, 16, 176, 145, 113, 94, 95, 44, 253, 152, 146, 137, 222, + 195, 200, 202, 165, 113, 42, 198, 199, 154, 215, 83, 80, 205, 81, + 155, 91, 59, 64, 220, 204, 3, 238, 201, 195, 55, 23, 67, 205, + 81, 184, 165, 66, 215, 87, 98, 99, 64, 167, 95, 79, 39, 36, + 178, 86, 30, 207, 168, 244, 80, 106, 34, 9, 182, 174, 83, 230, + 36, 77, 88, 53, 164, 214, 29, 64, 120, 64, 144, 124, 81, 239, + 48, 107, 223, 161, 237, 225, 197, 252, 2, 164, 2, 137, 68, 230, + 234, 51, 220, 165, 23, 81, 240, 42, 184, 66, 195, 211, 197, 22, + 27, 59, 132, 207, 157, 222, 37, 152, 38, 62, 64, 201, 224, 130, + 206, 98, 228, 219, 84, 48, 75, 27, 123, 57, 11, 239, 185, 170, + 194, 149, 96, 45, 172, 24, 194, 227, 77, 94, 52, 17, 84, 179, + 236, 220, 156, 126, 190, 36, 0, 35, 96, 94, 210, 248, 72, 52, + 206, 58, 228, 0, 20, 150, 90, 152, 164, 84, 21, 141, 212, 191, + 73, 45, 150, 3, 113, 205, 179, 32, 143, 124, 200, 79, 27, 208, + 39, 4, 230, 210, 136, 68, 164, 185, 101, 170, 238, 143, 107, 145, + 232, 46, 149, 149, 104, 27, 187, 104, 183, 133, 60, 94, 237, 93, + 191, 87, 168, 51, 88, 209, 0, 162, 197, 87, 106, 120, 138, 63, + 55, 189, 46, 23, 73, 98, 225, 67, 231, 104, 158, 116, 110, 108, + 207, 222, 108, 222, 251, 254, 220, 194, 40, 53, 254, 77, 247, 197, + 66, 84, 111, 58, 154, 185, 74, 198, 70, 96, 245, 102, 232, 249, + 180, 11, 85, 22, 206, 41, 78, 236, 26, 4, 202, 80, 1, 82, + 66, 203, 1, 189, 127, 105, 101, 66, 224, 190, 72, 186, 62, 205, + 128, 240, 110, 87, 48, 248, 109, 64, 167, 221, 41, 243, 66, 217, + 12, 162, 51, 75, 216, 11, 58, 23, 144, 192, 208, 255, 98, 238, + 224, 105, 134, 155, 208, 148, 132, 45, 10, 49, 219, 25, 78, 85, + 72, 8, 37, 151, 180, 140, 97, 118, 132, 122, 167, 111, 46, 67, + 89, 199, 170, 30, 100, 214, 253, 209, 249, 179, 139, 32, 250, 173, + 198, 227, 93, 103, 39, 38, 124, 193, 178, 136, 38, 26, 213, 0, + 123, 74, 129, 153, 90, 156, 68, 191, 35, 171, 144, 182, 188, 121, + 119, 166, 201, 241, 226, 128, 232, 127, 232, 66, 173, 219, 18, 174, + 200, 25, 251, 182, 240, 183, 94, 122, 251, 8, 116, 66, 102, 195, + 204, 103, 128, 115, 197, 24, 9, 19, 61, 162, 117, 188, 86, 222, + 37, 83, 249, 179, 112, 88, 106, 219, 157, 5, 48, 85, 95, 39, + 161, 5, 123, 64, 120, 50, 115, 176, 13, 19, 131, 162, 251, 104, + 95, 208, 152, 180, 157, 196, 181, 120, 39, 164, 158, 41, 169, 53, + 143, 92, 132, 252, 122, 219, 71, 115, 176, 242, 250, 119, 255, 227, + 245, 78, 143, 87, 216, 238, 11, 137, 197, 42, 199, 118, 1, 74, + 212, 66, 95, 236, 87, 174, 247, 4, 108, 61, 38, 146, 211, 23, + 140, 83, 97, 168, 90, 242, 114, 190, 209, 198, 103, 88, 80, 202, + 129, 149, 101, 61, 240, 159, 101, 138, 169, 167, 28, 100, 243, 6, + 232, 190, 157, 218, 102, 189, 49, 91, 1, 194, 2, 220, 146, 162, + 99, 204, 243, 5, 228, 30, 52, 43, 244, 10, 117, 196, 174, 244, + 92, 47, 17, 67, 108, 121, 52, 250, 187, 39, 59, 95, 81, 171, + 163, 245, 216, 174, 212, 250, 84, 60, 66, 17, 112, 160, 57, 128, + 22, 94, 179, 184, 64, 115, 197, 188, 49, 96, 14, 119, 25, 222, + 27, 252, 66, 200, 136, 191, 140, 152, 143, 117, 138, 76, 189, 27, + 25, 169, 190, 152, 103, 14, 111, 68, 162, 140, 199, 72, 168, 189, + 92, 80, 74, 22, 166, 167, 170, 254, 12, 141, 20, 204, 25, 85, + 14, 50, 204, 161, 104, 114, 252, 200, 142, 30, 193, 44, 234, 160, + 31, 117, 205, 232, 249, 184, 92, 20, 255, 24, 199, 18, 21, 232, + 80, 81, 29, 46, 120, 210, 8, 87, 141, 251, 122, 18, 109, 165, + 71, 1, 96, 234, 189, 104, 59, 4, 197, 230, 249, 60, 37, 100, + 70, 117, 172, 104, 206, 253, 188, 172, 195, 224, 253, 62, 142, 198, + 100, 77, 69, 214, 94, 183, 116, 69, 251, 127, 70, 165, 141, 243, + 210, 247, 167, 128, 84, 154, 98, 252, 148, 254, 222, 228, 19, 13, + 180, 26, 178, 173, 169, 162, 190, 30, 44, 255, 42, 198, 176, 112, + 90, 210, 205, 18, 38, 91, 228, 229, 231, 164, 117, 9, 120, 12, + 114, 78, 27, 238, 108, 142, 228, 67, 214, 194, 250, 221, 55, 130, + 37, 176, 118, 165, 227, 42, 118, 18, 201, 126, 58, 34, 190, 46, + 143, 154, 252, 113, 92, 84, 139, 253, 221, 15, 77, 160, 244, 217, + 215, 127, 121, 137, 61, 84, 82, 74, 60, 114, 253, 74, 75, 148, + 168, 12, 224, 202, 129, 250, 225, 75, 236, 50, 242, 189, 172, 189, + 40, 199, 26, 75, 109, 131, 117, 60, 186, 30, 50, 23, 117, 254, + 86, 17, 53, 15, 132, 152, 42, 204, 20, 196, 23, 178, 107, 224, + 17, 143, 106, 39, 171, 155, 72, 121, 237, 201, 39, 12, 37, 132, + 12, 131, 133, 144, 109, 207, 196, 15, 104, 196, 49, 219, 189, 145, + 164, 123, 90, 127, 187, 210, 133, 173, 57, 36, 226, 190, 8, 111, + 221, 75, 249, 222, 181, 167, 154, 191, 130, 76, 92, 115, 113, 143, + 56, 164, 230, 126, 131, 196, 140, 189, 117, 214, 214, 155, 233, 255, + 64, 222, 121, 149, 184, 74, 221, 101, 17, 210, 158, 171, 27, 84, + 182, 65, 177, 183, 143, 120, 25, 123, 127, 17, 50, 152, 21, 37, + 158, 244, 75, 241, 64, 200, 222, 72, 89, 254, 204, 217, 20, 21, + 66, 255, 43, 127, 30, 86, 49, 116, 164, 32, 148, 106, 221, 254, + 228, 77, 87, 104, 92, 147, 174, 165, 36, 207, 243, 205, 26, 200, + 115, 219, 110, 12, 189, 6, 166, 142, 240, 181, 176, 49, 134, 135, + 37, 91, 219, 66, 143, 208, 73, 150, 245, 158, 155, 197, 135, 109, + 179, 158, 16, 60, 140, 19, 41, 188, 42, 98, 137, 238, 66, 194, + 95, 244, 238, 5, 110, 128, 73, 37, 94, 84, 183, 219, 122, 12, + 207, 122, 94, 253, 128, 27, 249, 213, 56, 234, 240, 170, 91, 207, + 85, 242, 175, 196, 30, 211, 82, 145, 234, 166, 142, 37, 240, 106, + 214, 130, 68, 87, 119, 135, 254, 213, 187, 43, 217, 219, 11, 3, + 44, 166, 204, 3, 14, 140, 240, 95, 28, 66, 147, 153, 251, 180, + 187, 87, 43, 218, 76, 105, 111, 196, 168, 151, 202, 227, 184, 209, + 2, 9, 212, 121, 49, 216, 192, 15, 14, 70, 20, 8, 2, 116, + 46, 71, 204, 126, 238, 195, 30, 196, 56, 212, 126, 11, 73, 183, + 84, 97, 228, 44, 42, 172, 10, 71, 147, 173, 45, 99, 218, 193, + 176, 115, 68, 43, 231, 12, 192, 184, 147, 114, 160, 58, 59, 132, + 149, 113, 165, 178, 111, 105, 240, 99, 112, 52, 10, 115, 161, 60, + 135, 187, 63, 175, 234, 207, 137, 233, 192, 136, 221, 109, 227, 14, + 134, 228, 140, 96, 43, 228, 8, 183, 92, 218, 207, 141, 164, 124, + 240, 120, 22, 243, 1, 187, 134, 216, 101, 91, 77, 12, 55, 112, + 179, 158, 221, 179, 59, 72, 163, 99, 246, 183, 92, 217, 230, 31, + 112, 96, 190, 84, 81, 9, 53, 251, 135, 145, 103, 142, 105, 133, + 197, 144, 79, 186, 122, 203, 232, 160, 175, 8, 78, 243, 57, 25, + 242, 234, 131, 72, 34, 22, 116, 153, 190, 100, 226, 182, 176, 180, + 84, 127, 52, 208, 215, 210, 33, 224, 30, 168, 78, 232, 244, 217, + 217, 113, 83, 211, 165, 197, 206, 182, 103, 33, 157, 23, 94, 251, + 235, 87, 234, 82, 175, 218, 49, 204, 176, 174, 164, 147, 17, 73, + 231, 176, 51, 4, 141, 123, 14, 164, 209, 29, 33, 60, 182, 116, + 16, 135, 7, 169, 139, 97, 42, 75, 195, 194, 79, 161, 77, 55, + 115, 125, 47, 40, 5, 21, 80, 228, 159, 235, 42, 205, 66, 97, + 122, 210, 99, 106, 95, 7, 223, 223, 34, 169, 179, 134, 244, 11, + 77, 252, 133, 181, 242, 179, 129, 209, 68, 99, 217, 204, 75, 55, + 24, 15, 176, 15, 220, 238, 113, 125, 96, 45, 220, 81, 242, 152, + 223, 193, 210, 55, 245, 122, 247, 146, 49, 55, 116, 50, 44, 0, + 69, 46, 24, 8, 226, 59, 66, 43, 174, 243, 20, 45, 93, 80, + 100, 91, 9, 237, 226, 83, 240, 227, 185, 106, 84, 30, 217, 233, + 0, 28, 59, 137, 94, 130, 77, 237, 154, 132, 183, 203, 225, 246, + 213, 183, 122, 53, 177, 158, 36, 88, 125, 191, 26, 83, 135, 165, + 65, 170, 125, 200, 178, 218, 167, 186, 229, 241, 32, 83, 106, 37, + 151, 23, 140, 83, 3, 18, 0, 96, 55, 208, 181, 114, 46, 222, + 208, 50, 134, 196, 25, 181, 139, 238, 124, 133, 216, 250, 222, 4, + 155, 90, 115, 197, 16, 164, 74, 92, 137, 171, 220, 98, 239, 240, + 214, 232, 104, 58, 164, 234, 122, 21, 116, 216, 43, 150, 105, 120, + 194, 203, 153, 8, 227, 90, 108, 119, 230, 207, 138, 107, 254, 166, + 225, 248, 203, 57, 81, 63, 28, 146, 232, 173, 165, 2, 90, 125, + 61, 240, 121, 84, 191, 86, 93, 50, 165, 227, 104, 233, 115, 18, + 83, 191, 231, 136, 242, 177, 16, 217, 5, 28, 200, 222, 211, 47, + 170, 220, 217, 202, 109, 64, 41, 146, 33, 220, 199, 45, 177, 102, + 157, 51, 184, 181, 79, 255, 227, 143, 25, 245, 54, 187, 98, 174, + 139, 214, 39, 249, 6, 72, 244, 224, 231, 38, 173, 157, 90, 239, + 124, 242, 65, 137, 18, 87, 206, 63, 238, 64, 155, 201, 64, 160, + 78, 139, 171, 27, 156, 217, 108, 167, 24, 80, 210, 176, 200, 29, + 202, 69, 221, 248, 89, 28, 128, 35, 225, 177, 191, 55, 248, 48, + 39, 35, 37, 223, 85, 82, 150, 203, 123, 206, 204, 142, 102, 118, + 238, 199, 71, 220, 38, 80, 63, 236, 134, 8, 179, 157, 201, 229, + 21, 192, 68, 9, 55, 224, 38, 139, 59, 187, 167, 70, 40, 178, + 228, 164, 212, 175, 198, 64, 62, 26, 155, 56, 180, 139, 118, 109, + 242, 236, 149, 190, 31, 161, 178, 57, 19, 102, 49, 178, 87, 116, + 247, 52, 93, 227, 90, 238, 200, 118, 160, 20, 171, 148, 216, 206, + 205, 157, 143, 160, 9, 181, 25, 153, 136, 91, 200, 4, 91, 244, + 198, 209, 109, 97, 100, 144, 195, 34, 64, 104, 138, 238, 242, 6, + 247, 71, 60, 121, 17, 1, 150, 111, 232, 116, 74, 177, 61, 22, + 183, 67, 17, 136, 109, 114, 108, 96, 23, 75, 229, 212, 56, 236, + 212, 108, 158, 42, 39, 59, 218, 88, 100, 126, 134, 223, 142, 153, + 132, 140, 45, 122, 5, 178, 248, 142, 133, 242, 195, 250, 151, 237, + 187, 170, 233, 247, 23, 69, 50, 96, 43, 221, 162, 219, 8, 198, + 219, 128, 114, 3, 237, 253, 168, 123, 76, 238, 160, 75, 117, 199, + 83, 229, 106, 210, 205, 199, 48, 197, 167, 190, 34, 4, 79, 85, + 247, 84, 168, 226, 70, 144, 68, 15, 58, 215, 218, 111, 199, 243, + 218, 127, 111, 66, 207, 78, 161, 164, 235, 63, 78, 49, 131, 99, + 3, 212, 117, 81, 233, 223, 8, 106, 160, 30, 103, 22, 101, 248, + 79, 139, 50, 19, 127, 99, 73, 233, 223, 58, 51, 61, 197, 15, + 57, 94, 94, 177, 80, 46, 73, 73, 0, 53, 111, 92, 64, 28, + 13, 216, 99, 142, 105, 134, 225, 110, 171, 70, 177, 5, 232, 137, + 122, 115, 150, 176, 148, 66, 47, 92, 198, 142, 103, 199, 213, 132, + 148, 187, 52, 122, 248, 34, 89, 169, 169, 127, 226, 197, 251, 112, + 9, 100, 27, 134, 76, 75, 144, 25, 73, 2, 114, 22, 179, 122, + 182, 169, 55, 210, 255, 123, 63, 131, 224, 101, 108, 227, 125, 137, + 66, 157, 75, 166, 214, 124, 24, 118, 198, 21, 72, 159, 118, 184, + 225, 13, 181, 110, 88, 90, 10, 47, 2, 201, 122, 29, 76, 83, + 73, 222, 136, 224, 93, 35, 231, 41, 31, 120, 28, 80, 165, 175, + 109, 94, 94, 179, 166, 106, 183, 193, 190, 132, 84, 108, 187, 94, + 161, 36, 233, 90, 80, 30, 214, 21, 132, 217, 218, 153, 143, 247, + 232, 143, 55, 233, 41, 94, 120, 230, 165, 169, 67, 112, 46, 247, + 56, 214, 109, 166, 100, 214, 57, 164, 206, 108, 49, 197, 163, 250, + 55, 189, 172, 93, 120, 41, 87, 173, 84, 150, 128, 25, 35, 95, + 199, 19, 113, 137, 80, 192, 65, 160, 117, 65, 212, 35, 27, 34, + 2, 105, 173, 88, 73, 252, 56, 246, 116, 239, 125, 21, 14, 188, + 56, 55, 186, 46, 100, 44, 214, 141, 171, 177, 141, 208, 155, 62, + 21, 129, 99, 60, 249, 54, 216, 160, 76, 3, 194, 9, 104, 217, + 214, 169, 65, 78, 171, 171, 6, 132, 36, 97, 212, 71, 123, 71, + 37, 36, 215, 124, 164, 203, 10, 112, 219, 249, 124, 226, 181, 141, + 234, 119, 237, 27, 199, 84, 247, 156, 223, 169, 148, 29, 135, 132, + 245, 108, 85, 228, 214, 61, 67, 13, 28, 3, 28, 165, 110, 184, + 125, 255, 119, 149, 88, 177, 143, 247, 254, 82, 243, 237, 196, 226, + 204, 160, 190, 169, 243, 61, 189, 249, 187, 15, 140, 95, 92, 78, + 107, 240, 218, 49, 75, 175, 111, 235, 254, 107, 41, 227, 93, 147, + 93, 93, 208, 143, 12, 165, 255, 192, 127, 63, 125, 22, 176, 59, + 149, 170, 102, 3, 180, 4, 116, 246, 164, 185, 202, 94, 229, 131, + 130, 211, 39, 213, 225, 13, 66, 73, 177, 114, 101, 92, 103, 124, + 23, 226, 21, 179, 150, 125, 146, 92, 181, 42, 81, 57, 36, 89, + 158, 67, 225, 161, 152, 106, 98, 254, 139, 23, 118, 184, 99, 83, + 6, 127, 240, 232, 169, 241, 33, 195, 86, 57, 248, 93, 104, 116, + 100, 84, 41, 227, 62, 197, 44, 143, 92, 196, 135, 53, 153, 97, + 230, 48, 222, 210, 201, 22, 113, 10, 25, 25, 224, 192, 21, 251, + 134, 228, 119, 83, 192, 51, 14, 162, 77, 51, 236, 18, 48, 196, + 251, 141, 185, 230, 199, 45, 113, 161, 58, 52, 34, 112, 203, 190, + 51, 155, 183, 109, 110, 0, 219, 133, 92, 255, 165, 187, 166, 240, + 121, 186, 251, 176, 194, 204, 151, 39, 76, 183, 205, 228, 194, 59, + 241, 37, 209, 255, 120, 46, 45, 230, 234, 86, 30, 74, 45, 26, + 17, 139, 146, 164, 120, 226, 214, 144, 124, 244, 92, 244, 230, 186, + 245, 86, 225, 249, 77, 24, 0, 152, 71, 240, 93, 102, 36, 214, + 27, 242, 30, 113, 140, 6, 144, 127, 124, 119, 247, 223, 110, 232, + 235, 78, 118, 36, 68, 186, 91, 142, 120, 38, 220, 41, 210, 93, + 51, 9, 243, 150, 162, 219, 236, 167, 81, 98, 144, 104, 23, 140, + 136, 98, 116, 98, 251, 223, 8, 220, 202, 60, 151, 4, 126, 131, + 82, 214, 129, 176, 143, 185, 84, 253, 119, 121, 74, 120, 43, 204, + 202, 26, 4, 48, 131, 107, 60, 64, 135, 169, 163, 166, 185, 13, + 185, 123, 242, 167, 71, 1, 79, 206, 186, 128, 74, 168, 57, 46, + 197, 170, 94, 103, 15, 145, 149, 126, 51, 92, 45, 205, 93, 187, + 154, 77, 218, 185, 253, 68, 205, 125, 184, 69, 113, 189, 178, 40, + 39, 142, 93, 142, 50, 239, 99, 234, 202, 30, 98, 30, 210, 166, + 93, 102, 17, 224, 27, 193, 9, 177, 152, 52, 161, 166, 60, 147, + 25, 74, 145, 59, 28, 9, 157, 143, 32, 212, 72, 162, 252, 77, + 116, 42, 194, 190, 71, 171, 191, 17, 229, 36, 2, 125, 136, 158, + 8, 54, 243, 45, 25, 230, 175, 208, 16, 97, 228, 124, 20, 237, + 187, 227, 30, 106, 75, 201, 234, 77, 42, 67, 235, 39, 179, 205, + 250, 164, 55, 115, 208, 40, 167, 25, 42, 134, 125, 216, 2, 15, + 113, 8, 233, 150, 141, 160, 99, 141, 202, 136, 41, 92, 175, 187, + 216, 180, 193, 149, 111, 81, 30, 78, 135, 40, 15, 147, 228, 192, + 255, 138, 181, 178, 134, 25, 232, 39, 215, 235, 198, 159, 224, 24, + 145, 129, 134, 156, 143, 224, 128, 133, 52, 234, 15, 124, 182, 21, + 109, 134, 239, 170, 200, 255, 101, 108, 203, 202, 186, 123, 79, 71, + 109, 51, 131, 166, 135, 224, 173, 26, 211, 133, 162, 66, 24, 210, + 21, 227, 107, 148, 128, 115, 132, 14, 100, 22, 203, 202, 121, 161, + 110, 167, 22, 67, 194, 97, 213, 16, 232, 118, 3, 144, 158, 224, + 74, 19, 152, 183, 245, 171, 93, 168, 23, 168, 30, 135, 229, 231, + 122, 98, 148, 59, 219, 105, 212, 11, 52, 239, 32, 47, 60, 123, + 130, 225, 68, 98, 49, 108, 9, 105, 229, 202, 82, 180, 51, 5, + 155, 88, 237, 147, 59, 52, 233, 30, 137, 137, 148, 163, 201, 121, + 125, 109, 214, 220, 123, 131, 125, 248, 139, 228, 9, 6, 245, 52, + 72, 177, 231, 70, 131, 196, 172, 44, 95, 114, 140, 55, 220, 39, + 37, 30, 69, 67, 240, 46, 89, 169, 67, 134, 124, 232, 239, 103, + 249, 44, 140, 45, 107, 227, 37, 49, 231, 4, 210, 65, 235, 187, + 85, 229, 4, 234, 62, 181, 75, 223, 195, 212, 24, 217, 219, 131, + 87, 199, 36, 165, 215, 10, 52, 154, 196, 235, 0, 134, 162, 186, + 43, 238, 186, 2, 152, 82, 100, 78, 114, 70, 60, 249, 219, 182, + 47, 7, 56, 189, 33, 205, 77, 205, 25, 163, 239, 128, 84, 118, + 161, 90, 123, 176, 49, 198, 52, 86, 235, 208, 62, 146, 223, 232, + 3, 224, 153, 249, 137, 177, 75, 24, 33, 46, 201, 202, 245, 52, + 103, 142, 169, 20, 230, 158, 247, 230, 145, 223, 63, 238, 51, 164, + 69, 183, 157, 76, 163, 93, 251, 220, 73, 176, 43, 90, 243, 83, + 207, 83, 181, 101, 92, 207, 129, 37, 123, 178, 173, 209, 120, 210, + 255, 193, 220, 184, 113, 251, 107, 32, 140, 114, 91, 238, 244, 169, + 187, 187, 245, 37, 76, 8, 179, 104, 25, 138, 32, 114, 248, 172, + 248, 136, 50, 67, 164, 8, 51, 126, 90, 152, 56, 255, 93, 140, + 207, 22, 23, 117, 24, 41, 46, 206, 129, 119, 101, 152, 228, 226, + 146, 218, 125, 131, 18, 2, 111, 38, 47, 237, 64, 248, 97, 253, + 248, 16, 124, 15, 176, 15, 50, 74, 118, 217, 142, 24, 249, 178, + 86, 239, 174, 52, 185, 69, 43, 93, 116, 5, 100, 67, 109, 48, + 163, 10, 170, 215, 184, 69, 238, 185, 170, 64, 71, 199, 175, 65, + 198, 191, 159, 124, 223, 193, 191, 125, 157, 35, 121, 94, 254, 95, + 110, 50, 168, 159, 134, 122, 66, 244, 75, 62, 78, 170, 250, 213, + 55, 163, 221, 196, 195, 78, 218, 95, 42, 146, 94, 100, 77, 154, + 96, 45, 129, 183, 215, 35, 11, 185, 58, 9, 30, 246, 118, 225, + 78, 127, 114, 184, 140, 151, 9, 226, 159, 197, 167, 157, 62, 75, + 157, 134, 36, 217, 122, 79, 243, 188, 111, 36, 202, 117, 58, 17, + 129, 88, 202, 27, 202, 17, 31, 23, 133, 74, 214, 112, 223, 172, + 119, 118, 46, 241, 4, 33, 18, 59, 121, 142, 156, 219, 151, 95, + 89, 8, 123, 229, 214, 97, 208, 67, 10, 212, 16, 126, 28, 199, + 131, 158, 27, 48, 174, 55, 46, 25, 250, 63, 233, 21, 12, 211, + 67, 207, 131, 145, 39, 93, 100, 85, 71, 88, 238, 48, 102, 59, + 128, 154, 9, 163, 119, 103, 130, 2, 218, 48, 148, 64, 99, 148, + 80, 37, 242, 229, 231, 229, 90, 175, 114, 69, 52, 70, 63, 37, + 215, 203, 40, 129, 124, 187, 46, 27, 170, 63, 210, 92, 90, 245, + 146, 133, 103, 204, 179, 40, 59, 204, 220, 48, 10, 75, 170, 173, + 255, 247, 210, 81, 19, 122, 191, 55, 116, 108, 118, 90, 227, 98, + 114, 161, 233, 4, 248, 101, 93, 138, 33, 135, 135, 124, 242, 187, + 140, 254, 37, 177, 227, 188, 202, 198, 143, 194, 116, 173, 195, 10, + 109, 27, 231, 171, 244, 157, 36, 200, 109, 20, 212, 146, 215, 32, + 147, 174, 17, 186, 218, 231, 252, 21, 132, 244, 83, 40, 238, 137, + 172, 64, 108, 237, 97, 24, 193, 114, 119, 155, 16, 237, 209, 90, + 108, 229, 14, 108, 50, 241, 7, 131, 183, 198, 226, 190, 7, 204, + 169, 107, 108, 161, 187, 16, 65, 97, 47, 59, 151, 214, 225, 73, + 210, 82, 174, 109, 155, 51, 3, 77, 29, 72, 184, 222, 127, 217, + 115, 129, 235, 19, 30, 137, 160, 83, 232, 152, 11, 222, 26, 21, + 100, 76, 23, 117, 92, 86, 6, 82, 128, 213, 200, 15, 110, 55, + 5, 105, 215, 118, 9, 132, 113, 221, 131, 230, 180, 175, 37, 197, + 144, 17, 137, 129, 7, 255, 26, 232, 36, 147, 43, 159, 156, 0, + 17, 66, 120, 12, 63, 234, 80, 73, 42, 195, 203, 20, 83, 188, + 182, 64, 115, 90, 21, 59, 58, 122, 134, 32, 22, 127, 218, 28, + 65, 3, 65, 118, 247, 155, 217, 251, 100, 10, 153, 119, 56, 212, + 218, 179, 73, 46, 56, 74, 151, 206, 186, 76, 225, 86, 212, 61, + 166, 239, 143, 156, 27, 254, 101, 110, 0, 19, 255, 160, 126, 149, + 183, 251, 45, 79, 89, 231, 230, 192, 33, 77, 132, 192, 32, 238, + 14, 131, 92, 144, 206, 68, 34, 110, 131, 227, 75, 121, 20, 36, + 130, 178, 254, 120, 175, 22, 87, 176, 215, 5, 151, 138, 82, 29, + 174, 134, 15, 34, 67, 146, 209, 122, 208, 210, 128, 71, 211, 219, + 249, 44, 37, 187, 173, 233, 107, 78, 111, 198, 21, 37, 46, 166, + 218, 212, 146, 75, 14, 81, 139, 102, 60, 104, 5, 236, 81, 170, + 41, 84, 227, 136, 52, 91, 247, 37, 122, 150, 240, 69, 74, 141, + 14, 142, 158, 4, 155, 109, 111, 21, 43, 189, 143, 253, 128, 113, + 169, 73, 43, 132, 136, 81, 58, 48, 0, 21, 89, 154, 103, 200, + 216, 43, 198, 167, 219, 83, 51, 6, 12, 224, 5, 245, 67, 63, + 114, 172, 247, 200, 215, 32, 160, 76, 123, 206, 112, 178, 217, 240, + 190, 222, 83, 115, 190, 6, 6, 215, 226, 38, 203, 244, 248, 209, + 200, 162, 89, 70, 100, 221, 44, 153, 21, 0, 202, 116, 8, 148, + 103, 158, 220, 204, 86, 111, 105, 185, 245, 171, 112, 190, 228, 141, + 250, 115, 90, 243, 19, 41, 101, 95, 143, 37, 200, 158, 101, 7, + 167, 56, 198, 218, 88, 90, 112, 84, 108, 152, 39, 53, 181, 216, + 207, 248, 139, 218, 71, 61, 191, 86, 253, 116, 168, 87, 223, 200, + 216, 141, 104, 30, 129, 24, 90, 24, 203, 160, 45, 184, 105, 125, + 115, 66, 19, 228, 82, 53, 10, 46, 204, 211, 175, 6, 17, 140, + 83, 194, 238, 173, 149, 208, 182, 157, 173, 66, 180, 241, 188, 154, + 1, 53, 227, 0, 191, 163, 92, 195, 154, 110, 167, 167, 238, 129, + 28, 77, 102, 77, 59, 252, 174, 4, 78, 220, 131, 13, 71, 40, + 240, 55, 91, 25, 244, 148, 14, 179, 182, 46, 147, 165, 88, 250, + 12, 150, 99, 121, 46, 52, 137, 226, 97, 255, 237, 142, 98, 170, + 16, 97, 170, 132, 196, 210, 5, 6, 2, 73, 57, 158, 185, 172, + 131, 59, 232, 50, 222, 67, 104, 49, 32, 119, 85, 174, 161, 124, + 166, 222, 25, 19, 75, 237, 114, 180, 148, 141, 66, 139, 74, 220, + 146, 127, 23, 87, 172, 228, 14, 49, 40, 53, 59, 120, 89, 127, + 83, 0, 222, 79, 192, 134, 187, 33, 171, 114, 170, 184, 78, 191, + 11, 121, 10, 143, 116, 219, 61, 171, 160, 200, 110, 86, 136, 234, + 225, 69, 35, 197, 250, 171, 14, 20, 112, 95, 42, 234, 200, 100, + 92, 242, 81, 34, 47, 119, 45, 102, 137, 122, 132, 212, 237, 100, + 238, 235, 206, 56, 48, 111, 177, 193, 52, 195, 134, 11, 190, 200, + 78, 122, 142, 218, 39, 182, 187, 8, 216, 246, 114, 80, 58, 92, + 50, 243, 162, 168, 129, 221, 173, 195, 41, 250, 178, 36, 82, 40, + 7, 126, 203, 64, 218, 62, 21, 190, 203, 209, 98, 107, 196, 78, + 60, 93, 33, 190, 8, 187, 121, 42, 96, 6, 12, 22, 125, 113, + 253, 233, 171, 218, 237, 148, 146, 239, 4, 93, 114, 144, 18, 21, + 95, 93, 17, 123, 226, 206, 101, 127, 119, 93, 121, 238, 116, 123, + 1, 130, 160, 48, 123, 181, 69, 252, 241, 212, 204, 41, 52, 13, + 166, 189, 9, 73, 15, 89, 187, 59, 250, 30, 71, 76, 166, 210, + 4, 136, 24, 237, 69, 179, 0, 120, 148, 165, 174, 94, 10, 94, + 103, 168, 234, 162, 134, 14, 234, 67, 35, 251, 136, 121, 33, 5, + 243, 92, 95, 103, 80, 239, 133, 96, 234, 187, 137, 22, 250, 163, + 129, 5, 23, 244, 67, 90, 239, 220, 2, 60, 12, 20, 192, 48, + 162, 169, 223, 6, 18, 222, 73, 131, 141, 209, 41, 1, 81, 178, + 66, 89, 61, 96, 38, 117, 112, 167, 169, 197, 136, 188, 215, 219, + 145, 182, 91, 136, 127, 56, 129, 200, 241, 233, 166, 83, 9, 52, + 131, 180, 37, 75, 205, 136, 95, 24, 139, 153, 75, 179, 161, 97, + 198, 12, 220, 138, 173, 91, 126, 112, 66, 156, 220, 113, 45, 47, + 199, 203, 243, 66, 123, 98, 62, 222, 230, 80, 234, 11, 209, 250, + 88, 222, 175, 54, 14, 3, 59, 216, 40, 246, 173, 234, 210, 66, + 220, 40, 169, 125, 178, 16, 104, 231, 214, 112, 163, 24, 237, 170, + 133, 162, 57, 237, 166, 62, 16, 172, 223, 188, 29, 204, 143, 31, + 70, 29, 81, 17, 170, 80, 46, 26, 160, 88, 186, 71, 194, 147, + 77, 87, 26, 164, 226, 39, 33, 157, 225, 55, 170, 6, 183, 253, + 167, 248, 19, 65, 101, 68, 237, 253, 172, 168, 51, 193, 182, 48, + 28, 101, 177, 46, 89, 67, 77, 121, 29, 49, 246, 182, 239, 108, + 254, 168, 183, 70, 125, 108, 179, 84, 194, 39, 253, 87, 146, 104, + 10, 219, 33, 164, 93, 245, 32, 244, 18, 138, 86, 50, 240, 249, + 187, 139, 188, 9, 122, 55, 167, 211, 143, 225, 161, 15, 79, 106, + 52, 251, 99, 45, 86, 244, 77, 244, 129, 72, 46, 35, 194, 215, + 133, 2, 76, 36, 71, 162, 67, 161, 68, 251, 127, 159, 86, 122, + 47, 205, 90, 20, 241, 35, 7, 165, 158, 173, 62, 194, 96, 118, + 219, 196, 102, 33, 96, 99, 171, 36, 10, 179, 201, 144, 136, 186, + 62, 94, 153, 135, 134, 132, 64, 97, 79, 70, 8, 29, 223, 223, + 150, 129, 67, 154, 198, 234, 104, 206, 77, 22, 232, 49, 99, 185, + 104, 116, 128, 40, 27, 241, 129, 26, 220, 51, 90, 189, 114, 20, + 112, 127, 120, 196, 139, 80, 171, 175, 170, 82, 236, 95, 40, 150, + 229, 177, 74, 176, 182, 0, 5, 99, 77, 79, 77, 151, 112, 9, + 157, 86, 72, 66, 70, 196, 211, 35, 109, 19, 200, 137, 37, 159, + 245, 11, 40, 237, 74, 47, 205, 197, 127, 166, 146, 73, 89, 184, + 173, 160, 155, 81, 15, 248, 152, 101, 201, 161, 113, 191, 173, 35, + 223, 10, 130, 204, 72, 30, 112, 113, 50, 21, 123, 89, 86, 173, + 231, 73, 62, 16, 166, 196, 201, 128, 1, 42, 16, 220, 101, 106, + 159, 49, 170, 0, 56, 222, 241, 12, 203, 11, 222, 26, 103, 74, + 14, 169, 110, 65, 233, 217, 230, 160, 78, 179, 172, 24, 186, 208, + 252, 71, 186, 247, 169, 33, 173, 94, 101, 69, 196, 20, 200, 50, + 49, 217, 160, 98, 79, 195, 160, 3, 185, 138, 252, 165, 219, 134, + 106, 9, 244, 12, 101, 183, 15, 173, 206, 18, 96, 211, 167, 167, + 208, 30, 137, 45, 182, 20, 165, 248, 240, 0, 137, 148, 158, 203, + 239, 224, 60, 185, 201, 27, 116, 51, 124, 102, 218, 20, 6, 200, + 79, 116, 58, 41, 115, 20, 209, 136, 203, 47, 8, 156, 255, 0, + 190, 227, 236, 115, 57, 182, 64, 150, 2, 75, 117, 177, 49, 193, + 237, 215, 127, 228, 183, 5, 143, 178, 243, 244, 173, 198, 79, 116, + 112, 54, 230, 253, 18, 204, 154, 138, 242, 136, 108, 85, 24, 145, + 108, 103, 27, 55, 122, 178, 112, 3, 125, 232, 94, 82, 201, 185, + 33, 10, 190, 0, 89, 70, 20, 34, 55, 212, 13, 30, 47, 25, + 118, 163, 156, 141, 44, 56, 24, 173, 87, 1, 64, 6, 132, 84, + 84, 220, 96, 51, 121, 137, 112, 211, 137, 71, 76, 166, 170, 46, + 18, 200, 240, 11, 243, 192, 170, 245, 22, 121, 113, 46, 156, 175, + 215, 208, 240, 4, 97, 17, 0, 37, 127, 153, 228, 252, 164, 207, + 148, 117, 165, 20, 35, 75, 101, 215, 193, 186, 120, 121, 64, 19, + 52, 198, 139, 45, 59, 248, 208, 202, 118, 116, 252, 23, 177, 112, + 78, 152, 65, 202, 27, 7, 176, 218, 135, 143, 209, 118, 127, 135, + 6, 124, 176, 207, 76, 252, 132, 165, 101, 71, 73, 14, 148, 108, + 78, 24, 78, 175, 134, 84, 223, 73, 211, 148, 130, 31, 9, 163, + 163, 113, 109, 35, 197, 80, 167, 230, 169, 168, 142, 127, 60, 120, + 210, 108, 137, 241, 28, 111, 22, 253, 25, 226, 198, 147, 43, 53, + 191, 215, 203, 103, 91, 61, 170, 216, 72, 14, 101, 35, 96, 153, + 131, 106, 220, 38, 223, 88, 42, 44, 2, 70, 220, 13, 23, 112, + 162, 96, 207, 234, 235, 138, 84, 169, 166, 7, 149, 112, 196, 40, + 218, 126, 177, 106, 249, 193, 250, 119, 120, 154, 185, 150, 213, 173, + 229, 233, 31, 251, 90, 90, 48, 154, 174, 249, 53, 72, 69, 203, + 9, 60, 8, 43, 63, 94, 44, 155, 221, 238, 120, 255, 252, 113, + 39, 124, 220, 82, 159, 96, 121, 2, 201, 210, 217, 13, 17, 0, + 102, 12, 110, 42, 81, 205, 135, 13, 98, 161, 110, 7, 231, 216, + 182, 244, 75, 220, 220, 214, 46, 120, 33, 124, 177, 168, 79, 119, + 37, 202, 211, 247, 32, 180, 228, 160, 184, 253, 165, 142, 22, 98, + 192, 47, 31, 174, 148, 209, 231, 147, 102, 242, 82, 223, 248, 59, + 77, 127, 203, 107, 190, 227, 5, 237, 45, 131, 118, 151, 203, 118, + 160, 151, 22, 139, 34, 189, 174, 221, 161, 145, 67, 29, 25, 104, + 209, 97, 230, 199, 121, 212, 59, 105, 247, 101, 66, 81, 85, 239, + 133, 2, 221, 250, 152, 70, 12, 141, 152, 207, 78, 195, 113, 141, + 24, 217, 231, 135, 192, 103, 14, 54, 82, 27, 235, 191, 239, 2, + 243, 150, 20, 116, 132, 252, 45, 247, 228, 127, 254, 119, 207, 18, + 154, 253, 52, 129, 1, 184, 116, 120, 177, 136, 28, 19, 128, 113, + 125, 239, 69, 227, 150, 31, 90, 1, 50, 65, 95, 163, 134, 252, + 72, 64, 212, 99, 174, 254, 249, 209, 224, 142, 231, 93, 79, 247, + 153, 183, 2, 165, 154, 23, 138, 185, 149, 228, 55, 151, 8, 208, + 136, 210, 0, 177, 27, 120, 123, 173, 221, 8, 76, 189, 86, 232, + 163, 142, 224, 112, 217, 227, 214, 57, 84, 82, 180, 107, 46, 103, + 2, 132, 3, 172, 29, 30, 7, 225, 236, 233, 169, 141, 133, 106, + 10, 28, 42, 121, 84, 141, 173, 253, 190, 184, 79, 246, 93, 138, + 221, 220, 190, 212, 31, 20, 155, 6, 10, 105, 247, 167, 84, 61, + 138, 255, 250, 140, 126, 237, 0, 77, 52, 144, 87, 64, 61, 183, + 220, 13, 193, 48, 33, 91, 189, 47, 0, 53, 136, 88, 86, 187, + 162, 62, 254, 162, 28, 149, 120, 29, 10, 65, 238, 191, 238, 123, + 101, 34, 128, 189, 233, 156, 245, 220, 89, 75, 88, 38, 235, 69, + 57, 13, 97, 106, 72, 25, 42, 143, 143, 213, 71, 8, 98, 167, + 142, 241, 226, 203, 208, 54, 239, 221, 194, 100, 241, 68, 163, 19, + 160, 127, 229, 151, 147, 197, 172, 119, 114, 116, 35, 74, 35, 182, + 133, 46, 98, 125, 106, 3, 44, 75, 229, 177, 28, 226, 163, 132, + 5, 119, 200, 217, 60, 22, 136, 125, 227, 192, 1, 94, 70, 170, + 88, 43, 243, 21, 15, 56, 228, 253, 18, 6, 225, 202, 146, 147, + 32, 89, 122, 12, 122, 126, 56, 1, 17, 139, 233, 114, 154, 32, + 103, 183, 30, 43, 11, 59, 89, 77, 90, 69, 65, 86, 126, 183, + 207, 34, 158, 75, 43, 27, 14, 130, 206, 31, 209, 245, 14, 173, + 52, 238, 65, 58, 225, 183, 121, 158, 151, 26, 134, 35, 250, 161, + 104, 62, 219, 126, 38, 76, 129, 103, 73, 38, 159, 157, 33, 241, + 46, 107, 60, 254, 104, 147, 25, 7, 192, 95, 161, 129, 254, 93, + 204, 215, 159, 96, 228, 40, 108, 149, 53, 43, 159, 232, 10, 174, + 124, 126, 2, 114, 126, 32, 61, 88, 46, 145, 45, 62, 155, 15, + 24, 250, 138, 230, 5, 186, 244, 180, 121, 126, 70, 119, 174, 53, + 58, 193, 59, 202, 182, 120, 134, 130, 82, 213, 199, 248, 154, 169, + 171, 31, 140, 2, 208, 32, 194, 30, 59, 129, 214, 139, 245, 252, + 74, 216, 195, 151, 108, 37, 104, 151, 104, 174, 179, 15, 127, 115, + 23, 26, 133, 182, 69, 242, 243, 226, 65, 72, 118, 221, 117, 130, + 191, 15, 112, 177, 174, 145, 26, 206, 191, 227, 121, 70, 219, 30, + 234, 46, 178, 11, 228, 244, 247, 119, 63, 58, 238, 140, 241, 68, + 155, 249, 32, 31, 186, 151, 188, 28, 91, 60, 79, 176, 239, 202, + 35, 15, 112, 164, 81, 203, 139, 119, 213, 26, 214, 77, 129, 23, + 182, 89, 254, 33, 177, 92, 173, 119, 59, 158, 208, 82, 5, 120, + 11, 10, 60, 248, 68, 212, 10, 185, 195, 53, 132, 80, 215, 34, + 161, 85, 180, 102, 62, 67, 73, 173, 88, 139, 67, 82, 132, 201, + 220, 26, 35, 41, 191, 82, 220, 102, 40, 132, 103, 188, 231, 181, + 241, 169, 183, 122, 34, 39, 126, 24, 52, 149, 41, 198, 250, 235, + 209, 226, 80, 205, 207, 239, 139, 184, 52, 49, 123, 171, 31, 140, + 244, 116, 127, 36, 81, 185, 36, 69, 237, 212, 49, 62, 125, 135, + 179, 20, 55, 104, 62, 200, 250, 14, 219, 30, 163, 250, 196, 234, + 72, 180, 124, 140, 45, 136, 94, 65, 106, 254, 151, 128, 164, 46, + 211, 106, 51, 233, 156, 223, 161, 114, 86, 35, 93, 73, 93, 96, + 220, 252, 87, 98, 232, 181, 16, 112, 252, 138, 86, 202, 123, 170, + 240, 100, 232, 172, 59, 59, 43, 171, 67, 164, 127, 235, 206, 5, + 77, 71, 52, 56, 249, 96, 16, 95, 190, 88, 84, 208, 146, 24, + 189, 227, 97, 155, 25, 203, 208, 54, 243, 217, 224, 246, 186, 120, + 19, 37, 203, 60, 214, 239, 197, 227, 163, 11, 121, 133, 125, 49, + 88, 138, 15, 152, 61, 101, 10, 194, 130, 41, 223, 25, 162, 224, + 241, 28, 1, 29, 203, 162, 219, 159, 79, 192, 119, 73, 214, 76, + 202, 30, 92, 136, 125, 54, 101, 8, 44, 20, 136, 187, 169, 90, + 150, 101, 126, 127, 48, 58, 205, 93, 219, 2, 13, 25, 99, 248, + 106, 38, 219, 246, 137, 103, 194, 90, 169, 109, 193, 87, 174, 199, + 33, 45, 3, 157, 215, 177, 91, 108, 246, 82, 73, 200, 178, 62, + 223, 68, 79, 196, 252, 238, 196, 23, 174, 59, 143, 122, 174, 82, + 28, 19, 4, 70, 128, 113, 186, 173, 232, 251, 129, 163, 131, 205, + 11, 3, 1, 23, 109, 165, 239, 156, 28, 171, 130, 75, 1, 122, + 208, 228, 229, 125, 182, 183, 227, 41, 160, 11, 229, 150, 111, 250, + 184, 6, 43, 118, 230, 19, 248, 89, 238, 103, 168, 228, 159, 96, + 230, 187, 231, 45, 255, 62, 72, 5, 28, 79, 49, 186, 155, 255, + 10, 45, 74, 195, 71, 56, 45, 222, 186, 79, 223, 6, 86, 153, + 13, 56, 84, 111, 204, 216, 207, 168, 229, 222, 83, 213, 46, 162, + 88, 29, 151, 255, 93, 88, 253, 20, 209, 47, 250, 224, 39, 24, + 255, 244, 112, 114, 78, 176, 82, 12, 13, 190, 12, 85, 58, 184, + 187, 162, 9, 0, 50, 183, 194, 104, 123, 114, 237, 87, 186, 184, + 42, 24, 207, 2, 226, 236, 195, 167, 186, 238, 85, 205, 22, 160, + 22, 50, 123, 94, 17, 120, 221, 248, 229, 110, 217, 117, 81, 118, + 48, 173, 154, 53, 183, 117, 142, 79, 135, 80, 33, 198, 107, 129, + 18, 76, 132, 6, 11, 23, 151, 78, 18, 210, 111, 161, 151, 83, + 248, 1, 49, 108, 44, 227, 15, 131, 122, 223, 12, 69, 38, 248, + 192, 99, 245, 99, 129, 129, 143, 143, 3, 2, 221, 51, 169, 149, + 187, 90, 255, 49, 237, 249, 159, 172, 196, 134, 251, 41, 214, 92, + 42, 2, 139, 113, 125, 112, 31, 77, 154, 237, 160, 5, 31, 219, + 7, 246, 94, 171, 137, 227, 83, 153, 4, 136, 243, 110, 223, 172, + 220, 76, 192, 243, 254, 226, 164, 197, 173, 14, 28, 86, 61, 162, + 35, 244, 166, 174, 193, 188, 247, 103, 221, 47, 134, 1, 121, 62, + 126, 26, 115, 86, 56, 231, 183, 192, 188, 41, 223, 202, 29, 184, + 8, 25, 98, 136, 18, 35, 183, 41, 221, 144, 188, 248, 90, 41, + 109, 131, 216, 73, 222, 120, 131, 158, 98, 113, 86, 36, 35, 238, + 36, 1, 121, 115, 179, 176, 196, 87, 52, 83, 194, 118, 32, 155, + 202, 157, 56, 74, 39, 121, 4, 132, 13, 237, 14, 62, 68, 171, + 41, 116, 106, 38, 218, 66, 235, 243, 43, 20, 163, 104, 229, 237, + 214, 88, 51, 228, 48, 178, 180, 112, 31, 163, 38, 179, 248, 195, + 222, 254, 200, 54, 135, 175, 137, 81, 141, 190, 224, 41, 250, 38, + 145, 247, 66, 90, 205, 191, 201, 155, 249, 218, 24, 231, 124, 39, + 100, 29, 44, 158, 194, 162, 52, 187, 55, 115, 131, 213, 153, 218, + 140, 235, 138, 121, 223, 138, 229, 181, 175, 231, 81, 255, 19, 163, + 146, 237, 200, 154, 118, 83, 63, 209, 145, 4, 252, 222, 252, 120, + 179, 168, 78, 180, 218, 177, 120, 3, 246, 85, 204, 92, 173, 176, + 231, 202, 123, 161, 135, 205, 138, 4, 84, 61, 157, 127, 255, 152, + 94, 65, 47, 21, 7, 37, 203, 93, 165, 249, 69, 240, 2, 221, + 113, 58, 218, 118, 100, 111, 241, 220, 154, 48, 145, 177, 216, 81, + 77, 204, 163, 145, 216, 167, 71, 157, 146, 110, 124, 245, 196, 123, + 203, 43, 120, 225, 188, 33, 140, 135, 159, 222, 182, 251, 80, 88, + 155, 251, 108, 189, 43, 228, 64, 97, 160, 180, 255, 36, 92, 45, + 194, 195, 52, 116, 87, 50, 79, 193, 231, 124, 161, 38, 14, 68, + 237, 35, 154, 98, 137, 47, 189, 2, 26, 96, 95, 219, 159, 22, + 181, 19, 111, 236, 236, 182, 77, 0, 4, 82, 30, 10, 29, 106, + 146, 223, 64, 234, 54, 254, 195, 140, 131, 153, 65, 154, 11, 49, + 153, 106, 83, 190, 95, 221, 232, 111, 73, 56, 14, 161, 201, 37, + 81, 181, 127, 97, 125, 19, 45, 232, 159, 215, 36, 186, 254, 62, + 250, 223, 64, 61, 251, 162, 1, 198, 237, 49, 162, 221, 206, 128, + 126, 190, 9, 197, 8, 79, 77, 212, 52, 224, 96, 121, 123, 252, + 193, 142, 177, 111, 127, 74, 139, 217, 99, 83, 17, 16, 113, 56, + 135, 49, 194, 183, 163, 38, 98, 176, 84, 56, 150, 32, 166, 219, + 98, 149, 153, 109, 244, 87, 98, 203, 221, 242, 220, 89, 188, 52, + 216, 116, 26, 160, 199, 119, 151, 135, 29, 155, 220, 87, 132, 24, + 12, 156, 208, 45, 231, 194, 131, 27, 208, 5, 199, 41, 75, 126, + 107, 15, 243, 196, 151, 47, 3, 182, 185, 75, 72, 225, 222, 198, + 87, 57, 7, 55, 171, 117, 220, 130, 0, 91, 208, 39, 126, 163, + 15, 65, 244, 220, 253, 20, 200, 5, 174, 191, 33, 10, 162, 179, + 144, 13, 92, 156, 197, 214, 146, 198, 160, 176, 249, 252, 25, 76, + 113, 220, 61, 57, 19, 32, 101, 1, 111, 218, 170, 68, 224, 24, + 134, 205, 160, 22, 69, 201, 107, 242, 124, 190, 142, 162, 207, 109, + 206, 200, 252, 16, 174, 187, 195, 163, 177, 204, 104, 163, 110, 171, + 9, 162, 29, 110, 127, 137, 1, 99, 5, 28, 50, 106, 69, 0, + 13, 7, 60, 94, 244, 129, 14, 226, 124, 73, 183, 40, 76, 106, + 61, 39, 156, 103, 64, 95, 80, 199, 37, 78, 218, 138, 244, 118, + 182, 47, 39, 155, 242, 191, 157, 174, 48, 211, 113, 173, 84, 30, + 84, 10, 38, 138, 32, 27, 141, 146, 39, 70, 212, 7, 1, 118, + 193, 98, 69, 92, 242, 253, 28, 0, 114, 156, 105, 130, 34, 11, + 16, 60, 38, 61, 100, 150, 133, 92, 115, 242, 187, 162, 187, 102, + 34, 167, 191, 8, 1, 78, 82, 238, 151, 172, 56, 60, 102, 213, + 59, 206, 144, 15, 100, 214, 103, 248, 49, 225, 92, 177, 246, 255, + 22, 170, 18, 197, 235, 119, 228, 236, 2, 209, 58, 85, 127, 83, + 79, 116, 158, 251, 89, 14, 15, 208, 67, 127, 63, 196, 232, 214, + 154, 206, 123, 210, 198, 88, 140, 228, 56, 192, 113, 194, 156, 88, + 55, 255, 251, 173, 247, 216, 100, 95, 91, 55, 111, 122, 183, 93, + 168, 12, 30, 69, 215, 50, 25, 50, 233, 163, 66, 223, 15, 217, + 112, 118, 174, 130, 74, 234, 189, 2, 55, 199, 74, 38, 125, 89, + 184, 64, 14, 174, 78, 193, 230, 123, 111, 189, 81, 248, 228, 136, + 84, 227, 100, 24, 233, 146, 41, 81, 103, 34, 231, 214, 114, 161, + 227, 57, 178, 6, 163, 182, 149, 1, 141, 87, 33, 0, 203, 223, + 251, 161, 112, 149, 250, 251, 52, 52, 52, 45, 58, 6, 28, 72, + 13, 226, 10, 160, 191, 110, 195, 106, 105, 9, 204, 117, 16, 152, + 213, 220, 108, 212, 130, 92, 224, 52, 195, 232, 132, 147, 133, 7, + 75, 60, 104, 128, 115, 76, 240, 184, 110, 33, 122, 189, 255, 225, + 66, 189, 216, 128, 144, 16, 96, 101, 242, 249, 86, 224, 123, 77, + 27, 235, 237, 46, 146, 10, 200, 166, 155, 207, 200, 76, 95, 17, + 78, 220, 140, 6, 108, 28, 53, 191, 150, 114, 122, 238, 147, 119, + 183, 18, 157, 6, 244, 148, 53, 0, 81, 115, 211, 61, 209, 6, + 227, 98, 132, 8, 148, 241, 29, 223, 167, 188, 217, 108, 137, 251, + 12, 26, 19, 87, 81, 153, 181, 165, 17, 84, 108, 135, 25, 181, + 103, 7, 14, 5, 216, 156, 53, 91, 245, 2, 135, 33, 71, 79, + 203, 104, 216, 212, 96, 64, 96, 223, 68, 22, 43, 10, 195, 132, + 234, 202, 22, 39, 93, 46, 174, 179, 246, 68, 122, 220, 195, 153, + 204, 179, 196, 192, 58, 148, 224, 221, 26, 31, 203, 246, 241, 134, + 202, 56, 24, 168, 104, 27, 62, 61, 47, 162, 178, 53, 33, 30, + 74, 202, 74, 33, 249, 39, 96, 180, 165, 196, 195, 173, 234, 88, + 59, 185, 20, 183, 161, 10, 30, 250, 50, 177, 201, 153, 110, 214, + 94, 173, 212, 228, 1, 46, 200, 203, 173, 79, 230, 71, 230, 3, + 131, 60, 130, 133, 53, 212, 123, 160, 186, 122, 199, 28, 195, 38, + 116, 52, 177, 69, 168, 151, 61, 31, 166, 21, 56, 24, 71, 58, + 48, 189, 71, 92, 174, 220, 54, 158, 12, 56, 189, 78, 70, 175, + 165, 73, 42, 175, 77, 40, 86, 103, 254, 213, 147, 244, 13, 63, + 162, 121, 198, 78, 66, 224, 4, 244, 94, 236, 3, 118, 58, 108, + 170, 155, 46, 88, 223, 51, 68, 220, 94, 13, 47, 40, 44, 91, + 22, 67, 55, 146, 236, 64, 45, 196, 70, 238, 155, 35, 68, 21, + 74, 187, 92, 183, 233, 123, 50, 144, 237, 174, 215, 117, 14, 211, + 126, 17, 59, 89, 225, 220, 127, 187, 53, 119, 196, 140, 98, 247, + 37, 231, 73, 52, 199, 134, 192, 44, 21, 230, 90, 50, 58, 120, + 145, 192, 248, 199, 254, 80, 195, 167, 93, 147, 7, 188, 104, 73, + 15, 244, 213, 221, 132, 155, 117, 199, 210, 225, 224, 100, 135, 107, + 109, 162, 168, 154, 149, 55, 148, 95, 174, 49, 105, 145, 82, 132, + 59, 93, 154, 48, 115, 239, 28, 25, 223, 75, 98, 232, 1, 57, + 137, 151, 160, 68, 62, 143, 138, 174, 80, 226, 50, 61, 189, 69, + 91, 46, 164, 181, 167, 171, 41, 117, 11, 122, 201, 137, 173, 197, + 243, 78, 98, 202, 135, 116, 88, 157, 96, 3, 177, 120, 132, 120, + 91, 43, 42, 139, 211, 177, 183, 242, 223, 59, 43, 225, 229, 75, + 184, 239, 75, 201, 107, 3, 86, 56, 75, 121, 100, 167, 157, 159, + 120, 116, 162, 252, 212, 71, 38, 236, 248, 62, 2, 25, 90, 220, + 157, 228, 75, 112, 248, 66, 122, 142, 158, 139, 52, 212, 121, 84, + 41, 94, 175, 74, 183, 65, 231, 54, 145, 197, 252, 206, 44, 46, + 147, 226, 197, 218, 26, 183, 188, 133, 103, 51, 183, 9, 51, 120, + 3, 173, 231, 192, 79, 225, 215, 17, 65, 182, 10, 91, 224, 153, + 135, 113, 91, 5, 127, 114, 111, 4, 218, 228, 79, 111, 171, 107, + 5, 126, 13, 107, 203, 15, 217, 164, 211, 158, 200, 32, 224, 74, + 222, 199, 31, 41, 81, 206, 239, 108, 254, 20, 113, 184, 106, 155, + 92, 233, 187, 146, 52, 140, 148, 201, 52, 213, 200, 137, 99, 197, + 130, 66, 244, 246, 211, 53, 56, 198, 236, 41, 61, 249, 198, 88, + 167, 208, 63, 243, 157, 204, 37, 118, 250, 134, 216, 136, 60, 75, + 119, 30, 139, 192, 97, 58, 221, 193, 237, 14, 234, 64, 20, 126, + 112, 162, 123, 178, 68, 36, 230, 8, 103, 78, 84, 109, 32, 116, + 22, 196, 98, 60, 81, 42, 60, 99, 241, 172, 221, 156, 240, 49, + 174, 132, 128, 177, 206, 170, 18, 78, 77, 119, 42, 13, 118, 153, + 13, 4, 247, 95, 86, 234, 104, 184, 57, 6, 216, 243, 186, 214, + 182, 56, 189, 143, 152, 31, 221, 243, 61, 201, 220, 138, 247, 102, + 109, 226, 79, 196, 139, 2, 143, 45, 248, 84, 28, 24, 72, 180, + 184, 111, 37, 131, 64, 123, 56, 53, 210, 64, 50, 66, 108, 242, + 146, 55, 82, 45, 51, 108, 69, 135, 4, 92, 7, 165, 128, 123, + 246, 80, 117, 195, 184, 196, 239, 130, 131, 225, 106, 138, 166, 22, + 81, 240, 82, 112, 94, 156, 114, 104, 142, 193, 221, 252, 252, 191, + 201, 253, 26, 46, 212, 90, 147, 163, 106, 178, 78, 3, 190, 155, + 80, 169, 104, 78, 15, 35, 60, 207, 21, 2, 242, 248, 138, 40, + 194, 85, 79, 56, 178, 43, 133, 70, 159, 172, 156, 249, 255, 150, + 174, 193, 205, 241, 3, 32, 14, 16, 252, 190, 108, 230, 88, 50, + 177, 122, 168, 83, 196, 238, 172, 33, 69, 51, 194, 62, 185, 221, + 129, 225, 133, 75, 143, 248, 31, 92, 55, 84, 246, 146, 127, 224, + 70, 9, 105, 27, 96, 137, 92, 40, 146, 96, 232, 171, 39, 8, + 60, 251, 227, 30, 50, 147, 35, 9, 252, 85, 202, 205, 216, 113, + 140, 0, 135, 156, 153, 9, 62, 48, 160, 44, 196, 201, 163, 118, + 211, 113, 88, 133, 101, 55, 192, 111, 117, 186, 176, 216, 72, 0, + 168, 231, 205, 244, 34, 240, 236, 247, 1, 226, 179, 30, 140, 25, + 18, 86, 10, 188, 21, 199, 142, 191, 177, 116, 184, 148, 95, 220, + 145, 129, 59, 79, 14, 11, 200, 208, 141, 196, 1, 136, 54, 241, + 150, 160, 38, 11, 13, 82, 104, 79, 208, 20, 169, 251, 56, 116, + 24, 253, 36, 223, 19, 194, 102, 47, 251, 111, 107, 157, 244, 191, + 100, 253, 11, 48, 40, 162, 121, 79, 188, 99, 134, 176, 53, 143, + 187, 151, 25, 213, 44, 137, 27, 4, 118, 179, 136, 52, 17, 159, + 215, 203, 15, 145, 168, 90, 156, 95, 235, 22, 47, 34, 18, 240, + 28, 41, 245, 71, 19, 201, 33, 222, 88, 191, 45, 14, 231, 241, + 245, 123, 58, 38, 141, 76, 110, 152, 121, 231, 155, 48, 126, 83, + 63, 69, 229, 71, 45, 62, 112, 176, 60, 242, 170, 116, 54, 129, + 219, 250, 183, 198, 196, 224, 138, 75, 76, 2, 253, 244, 91, 100, + 175, 107, 134, 189, 202, 35, 13, 154, 179, 2, 175, 125, 194, 221, + 224, 187, 38, 66, 155, 85, 162, 14, 32, 111, 194, 255, 66, 176, + 124, 47, 204, 102, 32, 39, 142, 125, 222, 197, 198, 167, 39, 218, + 108, 225, 171, 237, 171, 181, 252, 46, 97, 189, 48, 31, 134, 252, + 217, 154, 11, 194, 129, 28, 145, 67, 22, 210, 13, 73, 89, 120, + 233, 211, 248, 84, 121, 129, 99, 42, 187, 148, 1, 57, 126, 48, + 31, 66, 157, 249, 66, 212, 31, 57, 196, 229, 253, 229, 8, 27, + 63, 179, 220, 22, 14, 32, 94, 49, 238, 46, 246, 151, 198, 248, + 34, 2, 237, 79, 168, 24, 160, 59, 220, 229, 131, 111, 130, 30, + 56, 48, 99, 236, 17, 104, 21, 168, 196, 133, 164, 41, 239, 253, + 184, 185, 242, 67, 134, 28, 226, 29, 24, 164, 249, 232, 140, 49, + 19, 28, 163, 252, 65, 248, 131, 203, 102, 217, 129, 128, 235, 226, + 148, 108, 96, 202, 131, 225, 52, 3, 14, 248, 33, 99, 17, 152, + 159, 250, 244, 93, 37, 217, 132, 192, 167, 227, 168, 214, 44, 46, + 11, 230, 120, 155, 175, 106, 208, 163, 247, 124, 221, 224, 178, 201, + 30, 169, 110, 254, 97, 248, 41, 168, 35, 3, 9, 88, 178, 184, + 119, 227, 197, 139, 148, 17, 102, 193, 2, 171, 22, 162, 248, 165, + 87, 188, 244, 219, 24, 24, 82, 60, 168, 103, 229, 111, 19, 59, + 252, 151, 240, 243, 35, 169, 45, 175, 122, 115, 136, 22, 77, 137, + 149, 155, 24, 146, 51, 166, 235, 249, 238, 94, 108, 132, 90, 96, + 67, 199, 48, 42, 243, 233, 39, 77, 189, 0, 109, 71, 137, 228, + 113, 169, 161, 14, 162, 96, 118, 247, 89, 3, 244, 114, 185, 60, + 148, 199, 9, 250, 126, 181, 46, 25, 15, 27, 48, 7, 49, 115, + 107, 57, 115, 187, 35, 108, 72, 38, 66, 106, 149, 141, 183, 38, + 17, 103, 101, 103, 254, 254, 174, 103, 141, 224, 186, 78, 225, 4, + 109, 176, 227, 123, 178, 34, 251, 143, 78, 179, 254, 142, 168, 235, + 211, 67, 42, 139, 238, 111, 34, 163, 211, 69, 99, 143, 61, 187, + 135, 180, 13, 123, 76, 165, 212, 192, 59, 154, 247, 196, 60, 211, + 222, 151, 103, 95, 27, 19, 192, 49, 178, 154, 97, 21, 179, 92, + 29, 214, 214, 137, 123, 127, 98, 51, 177, 81, 235, 4, 67, 190, + 231, 85, 217, 11, 167, 156, 127, 39, 201, 208, 32, 85, 204, 156, + 20, 168, 140, 173, 191, 19, 78, 105, 72, 146, 115, 142, 193, 198, + 0, 131, 154, 235, 210, 177, 229, 230, 118, 229, 239, 86, 25, 37, + 130, 52, 184, 231, 31, 129, 96, 104, 8, 29, 135, 29, 224, 105, + 82, 126, 53, 5, 58, 150, 92, 181, 110, 37, 81, 78, 37, 218, + 143, 209, 248, 107, 193, 178, 165, 244, 25, 35, 4, 25, 190, 48, + 8, 233, 193, 253, 149, 248, 122, 97, 243, 228, 115, 80, 210, 188, + 120, 174, 97, 25, 56, 166, 122, 64, 151, 199, 18, 176, 50, 31, + 114, 106, 99, 247, 68, 2, 126, 245, 51, 244, 188, 76, 8, 121, + 141, 217, 49, 219, 98, 120, 117, 149, 166, 114, 61, 234, 247, 186, + 132, 209, 99, 146, 74, 5, 46, 166, 225, 102, 99, 230, 38, 103, + 226, 199, 220, 40, 36, 126, 21, 23, 116, 50, 215, 165, 175, 128, + 39, 148, 93, 214, 228, 218, 181, 88, 139, 220, 235, 36, 248, 222, + 91, 79, 219, 4, 226, 230, 179, 17, 156, 108, 198, 153, 135, 191, + 78, 44, 76, 134, 199, 76, 105, 78, 189, 181, 169, 219, 146, 235, + 183, 156, 138, 171, 140, 51, 216, 6, 103, 96, 90, 85, 121, 231, + 7, 72, 39, 137, 35, 33, 111, 218, 158, 56, 156, 178, 164, 79, + 195, 92, 165, 137, 67, 232, 223, 47, 233, 187, 221, 68, 203, 239, + 166, 49, 104, 132, 33, 239, 235, 141, 95, 11, 32, 94, 180, 178, + 182, 90, 233, 139, 54, 247, 166, 128, 23, 188, 93, 228, 29, 192, + 195, 195, 79, 107, 126, 122, 122, 10, 195, 156, 145, 239, 27, 223, + 136, 53, 23, 111, 49, 84, 232, 137, 176, 88, 59, 181, 89, 44, + 134, 60, 191, 228, 177, 22, 34, 230, 67, 102, 161, 216, 244, 126, + 2, 87, 124, 167, 27, 248, 5, 254, 106, 247, 119, 88, 178, 162, + 48, 5, 216, 88, 34, 137, 62, 81, 167, 85, 126, 161, 188, 240, + 230, 235, 113, 181, 71, 90, 90, 84, 224, 52, 254, 1, 100, 161, + 51, 188, 176, 209, 67, 151, 193, 54, 167, 213, 88, 87, 157, 181, + 11, 45, 231, 27, 32, 249, 217, 81, 83, 184, 99, 36, 10, 213, + 220, 9, 197, 55, 7, 144, 192, 51, 41, 95, 238, 112, 214, 190, + 14, 145, 24, 69, 230, 23, 74, 75, 105, 176, 13, 128, 136, 167, + 120, 124, 209, 10, 187, 154, 219, 46, 175, 67, 10, 103, 5, 38, + 171, 185, 9, 141, 157, 246, 203, 165, 12, 6, 198, 254, 224, 48, + 121, 199, 245, 112, 171, 56, 212, 206, 64, 226, 82, 248, 28, 208, + 23, 198, 83, 251, 16, 94, 177, 4, 190, 251, 154, 217, 230, 58, + 23, 210, 138, 233, 37, 173, 44, 227, 98, 6, 191, 174, 177, 81, + 203, 119, 127, 227, 90, 228, 150, 160, 120, 130, 47, 211, 147, 10, + 78, 37, 124, 84, 152, 112, 92, 54, 108, 95, 44, 176, 206, 30, + 74, 176, 111, 101, 227, 105, 158, 215, 173, 204, 222, 47, 64, 193, + 15, 124, 249, 230, 124, 213, 249, 202, 7, 158, 25, 189, 225, 179, + 224, 153, 122, 241, 192, 101, 157, 47, 104, 48, 251, 165, 16, 115, + 219, 86, 67, 28, 84, 120, 92, 112, 201, 18, 55, 115, 131, 208, + 4, 243, 96, 23, 169, 63, 254, 163, 110, 16, 73, 193, 201, 229, + 171, 106, 68, 41, 116, 8, 246, 223, 40, 236, 201, 210, 128, 39, + 204, 32, 215, 116, 144, 192, 155, 19, 198, 250, 148, 110, 68, 135, + 0, 22, 45, 60, 119, 107, 63, 189, 171, 6, 4, 101, 243, 47, + 212, 111, 109, 165, 176, 38, 74, 251, 119, 109, 6, 20, 140, 58, + 206, 177, 76, 81, 43, 198, 191, 12, 232, 143, 96, 44, 29, 59, + 20, 2, 161, 145, 60, 245, 198, 121, 31, 225, 162, 255, 97, 133, + 31, 61, 122, 132, 155, 218, 2, 99, 209, 42, 177, 175, 197, 159, + 127, 91, 150, 129, 80, 190, 140, 74, 197, 222, 99, 228, 48, 14, + 184, 95, 176, 45, 137, 113, 219, 221, 36, 236, 228, 245, 202, 4, + 221, 175, 35, 115, 235, 31, 157, 145, 144, 240, 196, 57, 233, 45, + 254, 85, 46, 150, 234, 231, 62, 134, 11, 113, 172, 73, 181, 107, + 225, 159, 82, 36, 21, 63, 74, 20, 33, 109, 217, 124, 237, 38, + 21, 94, 102, 168, 105, 121, 235, 250, 88, 216, 239, 229, 203, 159, + 148, 86, 20, 255, 200, 110, 106, 17, 222, 85, 141, 121, 43, 167, + 14, 74, 152, 103, 24, 25, 7, 34, 235, 115, 194, 240, 183, 97, + 106, 66, 249, 10, 72, 86, 194, 73, 154, 58, 184, 94, 99, 15, + 80, 148, 201, 197, 60, 91, 53, 227, 85, 63, 26, 109, 126, 185, + 210, 183, 199, 182, 113, 33, 73, 217, 37, 129, 108, 147, 55, 239, + 109, 57, 37, 199, 74, 104, 37, 81, 210, 125, 118, 13, 179, 251, + 228, 109, 145, 116, 67, 63, 156, 206, 183, 209, 190, 122, 81, 228, + 16, 80, 191, 134, 196, 191, 237, 25, 43, 43, 148, 83, 230, 50, + 238, 29, 23, 25, 173, 8, 121, 12, 114, 222, 250, 131, 126, 111, + 35, 156, 58, 130, 108, 205, 127, 130, 86, 32, 45, 16, 118, 234, + 61, 106, 175, 206, 151, 146, 161, 79, 49, 149, 102, 243, 3, 53, + 123, 95, 159, 75, 114, 182, 132, 141, 73, 186, 123, 39, 228, 144, + 75, 4, 150, 241, 214, 190, 108, 173, 191, 38, 196, 143, 21, 244, + 127, 144, 245, 227, 144, 1, 166, 245, 193, 250, 212, 192, 137, 173, + 76, 15, 164, 146, 86, 81, 199, 191, 205, 33, 246, 243, 43, 222, + 131, 183, 1, 240, 131, 63, 139, 161, 246, 151, 32, 217, 249, 48, + 129, 116, 78, 182, 205, 129, 58, 42, 30, 177, 176, 219, 208, 250, + 43, 45, 9, 170, 58, 59, 51, 216, 16, 228, 238, 179, 86, 255, + 127, 40, 125, 65, 220, 98, 185, 146, 181, 6, 252, 247, 133, 80, + 194, 201, 242, 224, 133, 105, 195, 20, 124, 16, 27, 199, 118, 248, + 7, 113, 42, 193, 143, 144, 58, 93, 160, 161, 31, 61, 172, 187, + 178, 146, 87, 180, 77, 174, 142, 144, 201, 183, 222, 225, 14, 131, + 173, 15, 185, 71, 50, 111, 116, 113, 167, 43, 143, 10, 18, 60, + 229, 100, 82, 97, 172, 245, 218, 248, 129, 207, 213, 66, 14, 22, + 112, 238, 62, 193, 169, 254, 247, 218, 49, 143, 195, 240, 216, 148, + 36, 16, 101, 57, 192, 84, 232, 107, 189, 92, 237, 59, 219, 0, + 206, 6, 230, 79, 126, 187, 95, 63, 56, 179, 36, 166, 188, 91, + 195, 17, 49, 137, 210, 4, 82, 221, 182, 31, 229, 162, 126, 121, + 105, 126, 209, 37, 34, 60, 172, 98, 203, 98, 252, 102, 200, 72, + 232, 138, 93, 51, 158, 93, 254, 107, 27, 192, 228, 28, 98, 135, + 161, 179, 119, 244, 105, 121, 116, 90, 65, 85, 47, 149, 247, 185, + 118, 24, 150, 46, 24, 171, 4, 107, 73, 234, 251, 91, 106, 110, + 5, 160, 152, 223, 28, 99, 166, 228, 247, 144, 92, 213, 198, 177, + 112, 220, 112, 128, 29, 23, 210, 62, 87, 235, 129, 104, 40, 14, + 73, 87, 191, 197, 71, 183, 202, 255, 215, 100, 243, 186, 110, 13, + 140, 145, 88, 221, 179, 54, 90, 241, 81, 10, 41, 221, 206, 82, + 44, 67, 134, 215, 94, 35, 182, 35, 45, 229, 151, 89, 178, 167, + 120, 128, 241, 143, 237, 32, 136, 63, 57, 208, 11, 212, 20, 177, + 186, 133, 60, 240, 15, 243, 94, 241, 174, 74, 253, 139, 33, 230, + 42, 108, 78, 6, 177, 25, 202, 10, 163, 228, 52, 212, 211, 140, + 57, 66, 18, 124, 147, 174, 239, 249, 0, 2, 34, 87, 208, 146, + 106, 94, 1, 216, 184, 91, 94, 11, 82, 201, 228, 21, 210, 224, + 145, 132, 199, 126, 0, 162, 50, 220, 107, 86, 18, 64, 120, 29, + 58, 25, 141, 237, 218, 175, 144, 72, 41, 213, 106, 39, 199, 38, + 247, 16, 86, 10, 155, 184, 141, 65, 112, 47, 114, 171, 241, 196, + 59, 209, 4, 173, 232, 249, 109, 21, 38, 195, 33, 133, 159, 143, + 27, 163, 181, 152, 146, 248, 45, 33, 208, 254, 28, 129, 98, 177, + 169, 139, 108, 182, 158, 152, 175, 15, 195, 165, 64, 61, 175, 92, + 97, 190, 54, 223, 129, 68, 126, 86, 166, 42, 125, 56, 176, 226, + 86, 243, 82, 51, 74, 205, 10, 244, 156, 84, 5, 164, 232, 255, + 97, 66, 239, 26, 74, 16, 24, 2, 17, 154, 148, 20, 4, 76, + 189, 49, 181, 104, 20, 58, 56, 231, 73, 23, 105, 153, 219, 70, + 253, 236, 149, 182, 168, 178, 235, 90, 86, 140, 164, 127, 185, 237, + 139, 84, 16, 248, 189, 50, 220, 218, 86, 131, 223, 65, 197, 55, + 92, 222, 128, 100, 43, 206, 132, 46, 82, 24, 221, 26, 157, 180, + 237, 185, 170, 136, 118, 155, 150, 11, 164, 87, 10, 114, 231, 203, + 214, 234, 212, 216, 41, 205, 113, 171, 210, 40, 244, 236, 2, 9, + 11, 39, 134, 229, 132, 141, 125, 112, 165, 128, 19, 16, 47, 13, + 211, 161, 238, 87, 12, 229, 138, 26, 205, 162, 51, 250, 185, 95, + 16, 111, 44, 105, 22, 120, 174, 198, 12, 31, 125, 30, 68, 62, + 129, 251, 18, 127, 240, 13, 25, 57, 230, 4, 112, 224, 160, 163, + 26, 202, 5, 142, 59, 150, 212, 188, 225, 195, 103, 242, 182, 190, + 245, 128, 138, 45, 207, 149, 57, 66, 80, 32, 159, 254, 165, 64, + 178, 250, 183, 198, 178, 52, 134, 137, 75, 189, 82, 1, 23, 91, + 192, 98, 3, 24, 157, 184, 210, 160, 209, 137, 105, 83, 40, 78, + 55, 228, 48, 223, 118, 76, 68, 233, 132, 172, 210, 86, 183, 128, + 213, 210, 189, 66, 252, 115, 218, 33, 128, 2, 77, 205, 169, 198, + 36, 153, 189, 4, 191, 134, 182, 81, 85, 3, 242, 59, 234, 3, + 164, 50, 73, 204, 216, 237, 236, 233, 74, 191, 184, 69, 0, 149, + 30, 8, 42, 54, 129, 225, 25, 242, 226, 85, 51, 200, 70, 41, + 203, 134, 142, 142, 212, 96, 250, 151, 195, 255, 105, 252, 62, 58, + 137, 191, 106, 75, 193, 48, 156, 152, 118, 131, 102, 12, 165, 74, + 44, 77, 111, 85, 93, 172, 154, 109, 235, 34, 101, 159, 188, 226, + 255, 100, 141, 69, 199, 74, 163, 96, 22, 3, 218, 234, 85, 47, + 40, 155, 239, 226, 125, 227, 38, 60, 98, 79, 199, 89, 236, 246, + 53, 72, 69, 203, 9, 60, 8, 43, 25, 33, 248, 126, 193, 118, + 130, 140, 49, 222, 248, 107, 5, 105, 145, 162, 140, 106, 95, 194, + 109, 88, 98, 78, 118, 70, 85, 130, 31, 207, 190, 213, 119, 190, + 201, 202, 241, 13, 199, 220, 171, 40, 1, 211, 227, 39, 25, 60, + 145, 180, 182, 227, 1, 202, 230, 183, 129, 22, 200, 204, 237, 18, + 88, 190, 236, 220, 204, 144, 46, 121, 12, 47, 59, 111, 142, 118, + 33, 198, 168, 121, 154, 88, 134, 102, 90, 55, 54, 237, 79, 182, + 223, 84, 143, 209, 51, 105, 78, 90, 206, 81, 53, 184, 13, 221, + 6, 242, 80, 231, 30, 174, 255, 111, 16, 156, 130, 42, 133, 95, + 53, 189, 205, 53, 164, 14, 96, 155, 234, 173, 13, 165, 97, 143, + 19, 2, 248, 82, 47, 194, 23, 61, 151, 53, 175, 65, 25, 102, + 186, 17, 116, 8, 154, 247, 230, 43, 116, 242, 32, 58, 33, 100, + 113, 181, 200, 195, 241, 139, 193, 185, 223, 130, 50, 183, 80, 62, + 105, 228, 156, 27, 33, 247, 202, 58, 235, 252, 243, 108, 101, 38, + 131, 239, 165, 32, 31, 84, 97, 210, 118, 206, 199, 208, 215, 183, + 38, 156, 73, 93, 69, 151, 126, 73, 17, 232, 16, 147, 93, 96, + 236, 166, 73, 2, 51, 247, 60, 110, 39, 248, 80, 140, 23, 187, + 79, 247, 121, 182, 21, 164, 174, 28, 144, 49, 157, 189, 252, 170, + 92, 25, 15, 180, 215, 144, 6, 213, 11, 157, 231, 250, 118, 101, + 44, 216, 148, 38, 51, 114, 179, 248, 167, 2, 185, 86, 237, 62, + 97, 189, 35, 229, 58, 195, 3, 3, 59, 41, 58, 247, 41, 128, + 245, 66, 47, 13, 125, 24, 193, 90, 146, 168, 14, 17, 24, 182, + 61, 203, 228, 135, 100, 237, 117, 169, 229, 1, 180, 43, 8, 228, + 101, 31, 112, 80, 17, 92, 245, 56, 79, 228, 54, 92, 79, 169, + 156, 170, 56, 219, 5, 172, 33, 179, 89, 111, 145, 61, 183, 209, + 113, 133, 175, 177, 59, 24, 224, 210, 242, 250, 242, 70, 175, 35, + 39, 32, 3, 75, 127, 236, 194, 234, 25, 88, 102, 39, 173, 213, + 34, 205, 34, 9, 148, 4, 116, 99, 210, 6, 189, 46, 241, 84, + 23, 91, 36, 177, 40, 66, 80, 248, 75, 53, 216, 134, 9, 21, + 193, 128, 232, 95, 173, 184, 189, 28, 98, 203, 132, 79, 63, 85, + 185, 248, 51, 132, 105, 42, 250, 51, 205, 241, 77, 230, 111, 120, + 232, 122, 144, 40, 218, 23, 255, 67, 156, 98, 142, 170, 158, 148, + 150, 192, 144, 115, 86, 110, 124, 126, 13, 63, 207, 29, 214, 106, + 131, 253, 93, 204, 70, 36, 112, 26, 229, 166, 196, 104, 17, 162, + 54, 25, 133, 233, 70, 61, 208, 126, 90, 59, 2, 168, 165, 219, + 178, 119, 140, 222, 13, 124, 225, 231, 5, 107, 128, 56, 47, 159, + 188, 203, 81, 236, 55, 29, 20, 70, 186, 141, 243, 46, 48, 6, + 195, 214, 119, 35, 209, 138, 238, 170, 7, 89, 72, 207, 96, 45, + 212, 251, 216, 239, 240, 138, 136, 137, 16, 91, 117, 211, 137, 17, + 89, 146, 180, 226, 179, 32, 96, 69, 201, 81, 136, 134, 44, 48, + 197, 224, 41, 96, 239, 79, 12, 69, 130, 217, 247, 144, 80, 30, + 169, 99, 235, 4, 37, 42, 134, 57, 8, 74, 16, 112, 68, 94, + 111, 22, 162, 197, 34, 237, 177, 94, 44, 44, 243, 240, 227, 105, + 173, 8, 242, 50, 59, 181, 100, 18, 77, 100, 173, 79, 202, 116, + 247, 25, 111, 62, 134, 132, 232, 99, 1, 218, 178, 26, 227, 238, + 8, 180, 241, 17, 137, 62, 82, 195, 138, 79, 201, 47, 170, 4, + 239, 229, 15, 174, 170, 140, 173, 120, 94, 111, 80, 196, 10, 108, + 9, 193, 104, 116, 147, 201, 60, 47, 171, 167, 18, 57, 226, 82, + 18, 221, 10, 148, 207, 106, 171, 115, 25, 138, 27, 216, 127, 168, + 67, 6, 64, 28, 8, 97, 159, 146, 200, 114, 206, 216, 135, 110, + 154, 211, 21, 14, 251, 111, 248, 40, 59, 169, 45, 17, 189, 211, + 155, 166, 51, 222, 207, 109, 118, 124, 159, 36, 20, 146, 239, 76, + 42, 247, 92, 233, 154, 244, 4, 157, 112, 206, 74, 85, 145, 89, + 18, 101, 18, 227, 200, 153, 75, 232, 222, 134, 114, 32, 119, 224, + 75, 32, 46, 248, 219, 49, 167, 10, 2, 160, 22, 29, 76, 165, + 118, 226, 35, 108, 134, 40, 68, 229, 159, 190, 45, 214, 124, 94, + 146, 115, 174, 14, 109, 30, 3, 8, 16, 25, 169, 7, 112, 91, + 159, 190, 9, 67, 196, 80, 237, 124, 85, 19, 176, 231, 150, 13, + 112, 66, 122, 81, 56, 194, 64, 128, 251, 153, 3, 18, 193, 15, + 33, 30, 34, 59, 104, 123, 235, 228, 27, 84, 232, 7, 63, 87, + 72, 5, 167, 120, 100, 156, 172, 169, 212, 191, 61, 37, 172, 31, + 119, 165, 27, 88, 67, 168, 168, 82, 26, 219, 77, 201, 223, 246, + 199, 193, 26, 103, 171, 235, 237, 238, 186, 64, 177, 97, 65, 175, + 158, 135, 77, 151, 90, 196, 230, 145, 56, 201, 221, 134, 184, 10, + 36, 156, 80, 252, 234, 76, 120, 138, 74, 158, 195, 223, 129, 14, + 255, 183, 239, 48, 180, 50, 150, 6, 129, 244, 120, 18, 90, 137, + 45, 245, 109, 85, 30, 177, 236, 66, 10, 113, 26, 162, 199, 146, + 227, 46, 144, 234, 168, 47, 83, 40, 183, 120, 218, 113, 77, 38, + 61, 23, 142, 181, 217, 106, 224, 243, 98, 4, 102, 190, 200, 57, + 209, 51, 162, 125, 188, 108, 174, 233, 195, 143, 48, 101, 178, 148, + 48, 94, 217, 108, 25, 69, 5, 153, 33, 35, 76, 101, 88, 250, + 199, 35, 2, 210, 237, 116, 222, 0, 248, 4, 214, 128, 135, 182, + 70, 100, 146, 96, 141, 231, 151, 174, 238, 4, 12, 128, 22, 31, + 5, 85, 160, 62, 236, 7, 243, 151, 44, 214, 118, 123, 116, 69, + 159, 124, 34, 101, 146, 74, 176, 189, 240, 205, 113, 66, 207, 118, + 73, 211, 9, 136, 65, 39, 94, 29, 116, 209, 30, 107, 129, 45, + 201, 7, 86, 157, 240, 252, 232, 213, 241, 89, 243, 188, 177, 227, + 146, 109, 166, 145, 242, 251, 125, 120, 6, 92, 178, 25, 201, 38, + 212, 81, 159, 129, 125, 93, 30, 117, 115, 201, 241, 76, 83, 181, + 22, 106, 205, 205, 30, 203, 157, 216, 162, 175, 171, 118, 33, 97, + 46, 126, 253, 35, 121, 149, 10, 152, 184, 237, 181, 82, 179, 59, + 63, 40, 2, 218, 16, 236, 134, 90, 5, 47, 77, 83, 214, 18, + 78, 182, 17, 137, 1, 29, 69, 163, 166, 32, 131, 144, 4, 106, + 207, 78, 169, 67, 11, 112, 143, 67, 217, 203, 25, 83, 120, 210, + 134, 102, 78, 88, 134, 250, 146, 187, 158, 116, 151, 201, 98, 172, + 112, 112, 77, 145, 199, 42, 89, 241, 224, 192, 165, 215, 133, 7, + 141, 123, 125, 88, 47, 251, 181, 220, 49, 205, 36, 153, 172, 107, + 237, 143, 184, 10, 224, 226, 101, 25, 213, 56, 167, 243, 185, 205, + 159, 66, 27, 167, 17, 233, 4, 13, 69, 45, 242, 59, 89, 238, + 177, 245, 125, 253, 74, 119, 58, 40, 42, 21, 35, 126, 11, 63, + 137, 83, 57, 251, 205, 129, 63, 198, 49, 54, 194, 224, 38, 189, + 143, 141, 127, 6, 203, 180, 202, 45, 181, 120, 66, 223, 88, 198, + 60, 1, 5, 200, 119, 107, 21, 41, 210, 32, 82, 52, 241, 30, + 25, 28, 123, 239, 210, 1, 150, 241, 114, 35, 223, 7, 233, 22, + 134, 204, 237, 252, 35, 153, 249, 99, 115, 20, 146, 188, 193, 40, + 1, 7, 142, 107, 34, 188, 247, 127, 208, 47, 116, 67, 142, 200, + 43, 225, 168, 203, 171, 56, 13, 3, 213, 110, 252, 212, 15, 216, + 235, 46, 182, 136, 166, 69, 172, 232, 106, 178, 229, 41, 195, 62, + 92, 141, 220, 6, 100, 191, 45, 231, 249, 163, 187, 27, 212, 241, + 158, 72, 140, 78, 59, 32, 116, 124, 132, 221, 218, 125, 65, 9, + 76, 87, 90, 104, 95, 62, 105, 252, 183, 61, 11, 171, 111, 228, + 214, 145, 57, 244, 235, 49, 183, 124, 137, 9, 9, 113, 25, 35, + 43, 141, 255, 174, 194, 183, 196, 243, 170, 240, 114, 203, 4, 190, + 16, 147, 159, 224, 159, 95, 16, 29, 233, 47, 148, 71, 117, 46, + 104, 151, 233, 34, 98, 165, 166, 6, 103, 86, 248, 212, 254, 111, + 162, 75, 114, 104, 14, 47, 141, 166, 102, 240, 162, 233, 136, 252, + 32, 241, 146, 253, 50, 242, 238, 30, 152, 5, 132, 229, 128, 177, + 114, 36, 191, 169, 169, 2, 208, 28, 79, 112, 105, 74, 125, 87, + 34, 162, 230, 199, 137, 254, 9, 215, 54, 83, 64, 64, 68, 105, + 39, 158, 134, 149, 39, 254, 38, 112, 81, 147, 78, 54, 147, 0, + 40, 85, 190, 191, 96, 28, 243, 15, 148, 174, 120, 98, 65, 110, + 35, 203, 191, 155, 17, 48, 62, 129, 89, 149, 213, 79, 251, 43, + 33, 165, 206, 75, 131, 11, 13, 228, 188, 45, 245, 215, 193, 4, + 29, 60, 141, 159, 113, 228, 128, 17, 221, 17, 33, 148, 230, 10, + 243, 187, 223, 104, 204, 64, 52, 50, 247, 216, 48, 238, 93, 19, + 148, 215, 82, 147, 215, 134, 104, 10, 74, 204, 12, 93, 117, 51, + 149, 28, 226, 195, 168, 218, 157, 174, 93, 21, 188, 90, 170, 202, + 199, 136, 171, 81, 100, 144, 21, 19, 211, 23, 102, 86, 69, 76, + 18, 27, 220, 82, 246, 128, 169, 125, 16, 142, 183, 156, 31, 71, + 229, 27, 198, 238, 121, 39, 174, 172, 112, 211, 15, 212, 78, 252, + 0, 73, 226, 151, 144, 145, 64, 242, 213, 67, 28, 122, 169, 52, + 138, 176, 159, 127, 119, 32, 1, 175, 32, 239, 255, 33, 210, 99, + 51, 23, 138, 77, 55, 166, 17, 225, 91, 158, 52, 93, 123, 210, + 211, 98, 80, 229, 73, 123, 201, 131, 107, 132, 147, 120, 122, 93, + 235, 251, 81, 102, 159, 203, 179, 235, 96, 241, 155, 170, 110, 154, + 189, 133, 183, 6, 189, 135, 210, 200, 240, 182, 146, 79, 6, 179, + 241, 251, 74, 28, 191, 171, 119, 159, 42, 29, 195, 13, 87, 134, + 205, 113, 177, 114, 100, 208, 96, 90, 241, 117, 129, 27, 20, 68, + 140, 239, 27, 183, 188, 40, 101, 92, 153, 150, 103, 101, 196, 19, + 108, 99, 116, 69, 147, 81, 85, 159, 22, 199, 22, 88, 195, 26, + 20, 73, 186, 153, 128, 220, 165, 43, 62, 115, 57, 87, 28, 51, + 219, 15, 218, 41, 71, 100, 67, 115, 217, 231, 117, 218, 190, 255, + 64, 20, 182, 246, 164, 139, 212, 247, 219, 28, 139, 61, 64, 208, + 61, 126, 84, 204, 106, 95, 138, 250, 219, 107, 197, 32, 61, 46, + 51, 63, 79, 39, 13, 225, 226, 118, 13, 25, 209, 85, 237, 121, + 84, 64, 230, 86, 20, 82, 254, 116, 240, 208, 120, 28, 220, 211, + 157, 50, 162, 17, 122, 224, 135, 179, 113, 65, 254, 148, 95, 252, + 151, 104, 48, 59, 161, 236, 48, 23, 2, 178, 158, 76, 138, 85, + 166, 31, 179, 135, 24, 122, 128, 40, 190, 27, 19, 96, 12, 113, + 144, 5, 66, 10, 67, 18, 247, 143, 27, 6, 177, 227, 122, 197, + 246, 1, 66, 64, 232, 120, 68, 56, 237, 106, 200, 118, 167, 122, + 111, 165, 171, 102, 56, 242, 15, 183, 221, 57, 130, 140, 92, 134, + 247, 251, 35, 170, 109, 22, 117, 116, 118, 134, 246, 253, 83, 155, + 146, 106, 173, 202, 111, 117, 54, 157, 128, 1, 20, 2, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 13, 99, 108, 101, 97, 114, 116, 111, 109, 97, 114, 107, 10, + 128, 3, +}; diff --git a/Rendering/fonts/face_courier.cxx b/Rendering/fonts/face_courier.cxx new file mode 100644 index 0000000..3831484 --- /dev/null +++ b/Rendering/fonts/face_courier.cxx @@ -0,0 +1,2922 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Courier Normal +// Courier 10 Pitch (c0419bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_courier_buffer_length = 40766; + +unsigned char face_courier_buffer[] = { + 128, 1, 213, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 83, + 117, 110, 32, 78, 111, 118, 32, 32, 52, 32, 49, 57, 58, 49, + 55, 58, 50, 51, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 67, + 111, 117, 114, 105, 101, 114, 32, 49, 48, 32, 80, 105, 116, 99, + 104, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, + 102, 13, 32, 32, 47, 70, 97, 109, 105, 108, 121, 78, 97, 109, + 101, 32, 40, 67, 111, 117, 114, 105, 101, 114, 32, 49, 48, 32, + 80, 105, 116, 99, 104, 41, 32, 114, 101, 97, 100, 111, 110, 108, + 121, 32, 100, 101, 102, 13, 32, 32, 47, 87, 101, 105, 103, 104, + 116, 32, 40, 78, 111, 114, 109, 97, 108, 41, 32, 114, 101, 97, + 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 73, + 116, 97, 108, 105, 99, 65, 110, 103, 108, 101, 32, 48, 32, 100, + 101, 102, 13, 32, 32, 47, 105, 115, 70, 105, 120, 101, 100, 80, + 105, 116, 99, 104, 32, 116, 114, 117, 101, 32, 100, 101, 102, 13, + 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 80, 111, + 115, 105, 116, 105, 111, 110, 32, 45, 57, 55, 32, 100, 101, 102, + 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 84, + 104, 105, 99, 107, 110, 101, 115, 115, 32, 56, 49, 32, 100, 101, + 102, 13, 101, 110, 100, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 78, 97, 109, 101, + 32, 47, 67, 111, 117, 114, 105, 101, 114, 49, 48, 80, 105, 116, + 99, 104, 66, 84, 45, 82, 111, 109, 97, 110, 32, 100, 101, 102, + 13, 47, 80, 97, 105, 110, 116, 84, 121, 112, 101, 32, 48, 32, + 100, 101, 102, 13, 47, 70, 111, 110, 116, 84, 121, 112, 101, 32, + 49, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 77, 97, 116, + 114, 105, 120, 32, 91, 48, 46, 48, 48, 49, 32, 48, 32, 48, + 32, 48, 46, 48, 48, 49, 32, 48, 32, 48, 93, 32, 114, 101, + 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 69, 110, + 99, 111, 100, 105, 110, 103, 32, 83, 116, 97, 110, 100, 97, 114, + 100, 69, 110, 99, 111, 100, 105, 110, 103, 32, 100, 101, 102, 13, + 47, 70, 111, 110, 116, 66, 66, 111, 120, 32, 123, 45, 52, 52, + 32, 45, 50, 57, 57, 32, 54, 54, 51, 32, 56, 53, 56, 125, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 47, 85, 110, 105, 113, 117, 101, 73, 68, 32, 49, 53, 53, 51, + 48, 52, 49, 57, 32, 100, 101, 102, 13, 99, 117, 114, 114, 101, + 110, 116, 100, 105, 99, 116, 32, 101, 110, 100, 13, 99, 117, 114, + 114, 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, 101, 99, + 13, 128, 2, 65, 151, 0, 0, 162, 149, 24, 64, 131, 138, 65, + 51, 131, 156, 169, 210, 46, 43, 153, 242, 182, 28, 118, 124, 214, + 117, 8, 10, 172, 252, 178, 78, 25, 205, 19, 54, 115, 155, 182, + 73, 148, 197, 103, 55, 9, 11, 76, 236, 146, 201, 148, 95, 240, + 116, 94, 247, 255, 198, 27, 176, 169, 163, 184, 73, 231, 233, 135, + 64, 229, 108, 11, 90, 247, 135, 85, 156, 198, 149, 106, 179, 30, + 51, 207, 133, 83, 213, 92, 11, 14, 129, 142, 245, 236, 107, 244, + 129, 98, 234, 196, 46, 115, 128, 202, 146, 29, 174, 28, 130, 179, + 143, 214, 188, 242, 0, 26, 187, 93, 0, 26, 86, 21, 112, 148, + 207, 226, 125, 143, 78, 172, 150, 147, 232, 131, 114, 210, 3, 88, + 180, 126, 12, 56, 118, 85, 142, 191, 117, 122, 31, 188, 92, 28, + 221, 246, 43, 60, 87, 191, 114, 126, 241, 196, 135, 148, 34, 193, + 66, 160, 132, 209, 199, 70, 42, 194, 147, 224, 151, 250, 190, 58, + 62, 207, 205, 130, 113, 242, 89, 131, 59, 172, 121, 18, 112, 114, + 24, 236, 154, 48, 99, 191, 115, 133, 224, 45, 140, 16, 88, 172, + 6, 223, 0, 179, 59, 140, 1, 135, 104, 178, 120, 1, 14, 179, + 36, 158, 166, 120, 127, 110, 184, 35, 211, 222, 67, 84, 5, 49, + 84, 77, 76, 244, 36, 160, 240, 59, 160, 193, 146, 55, 177, 56, + 123, 31, 151, 198, 153, 95, 194, 242, 116, 202, 52, 33, 76, 160, + 46, 56, 94, 37, 225, 157, 203, 215, 152, 222, 48, 134, 18, 124, + 224, 6, 169, 132, 185, 13, 10, 186, 103, 133, 120, 179, 138, 226, + 160, 195, 92, 98, 235, 252, 232, 152, 108, 105, 77, 64, 50, 110, + 212, 86, 137, 129, 25, 110, 28, 0, 249, 115, 157, 25, 229, 81, + 112, 13, 180, 112, 38, 114, 226, 254, 239, 24, 234, 140, 5, 129, + 255, 249, 205, 167, 129, 154, 4, 134, 221, 122, 63, 248, 62, 160, + 1, 217, 83, 222, 44, 85, 140, 213, 24, 26, 61, 122, 243, 226, + 16, 23, 51, 48, 41, 153, 190, 224, 19, 232, 138, 102, 70, 75, + 72, 126, 131, 209, 16, 187, 233, 152, 209, 23, 153, 120, 98, 17, + 90, 244, 181, 35, 178, 227, 179, 4, 210, 167, 212, 17, 3, 183, + 61, 118, 166, 138, 229, 60, 80, 237, 122, 232, 133, 47, 93, 140, + 123, 89, 88, 50, 219, 53, 248, 17, 125, 95, 44, 60, 97, 114, + 185, 219, 41, 143, 128, 83, 118, 176, 193, 107, 8, 248, 153, 3, + 106, 151, 244, 108, 104, 42, 212, 133, 35, 205, 111, 137, 28, 66, + 70, 167, 183, 36, 86, 254, 206, 248, 195, 186, 198, 84, 109, 151, + 54, 176, 201, 83, 0, 216, 224, 161, 103, 231, 22, 7, 0, 72, + 128, 145, 91, 54, 237, 70, 117, 53, 55, 193, 4, 150, 125, 85, + 222, 109, 147, 212, 182, 245, 150, 65, 7, 162, 167, 187, 7, 12, + 148, 23, 143, 66, 80, 138, 36, 153, 230, 140, 67, 182, 233, 153, + 97, 131, 153, 170, 75, 58, 13, 122, 14, 194, 186, 94, 68, 229, + 154, 218, 174, 238, 174, 34, 180, 181, 61, 159, 246, 189, 90, 58, + 105, 130, 236, 25, 24, 240, 221, 188, 238, 223, 76, 45, 245, 137, + 247, 107, 122, 241, 87, 110, 50, 2, 5, 232, 61, 183, 177, 70, + 119, 87, 191, 154, 121, 57, 24, 140, 184, 171, 128, 71, 209, 135, + 119, 32, 57, 132, 18, 32, 158, 87, 123, 131, 174, 119, 25, 147, + 69, 114, 145, 62, 30, 135, 81, 33, 255, 165, 248, 48, 84, 114, + 158, 5, 80, 228, 255, 167, 215, 228, 160, 187, 13, 78, 97, 162, + 78, 232, 109, 193, 178, 253, 13, 73, 228, 124, 241, 169, 176, 17, + 8, 22, 74, 13, 211, 160, 186, 209, 209, 130, 199, 170, 142, 240, + 237, 76, 148, 57, 210, 234, 79, 7, 171, 70, 42, 213, 147, 34, + 148, 98, 23, 146, 58, 180, 252, 210, 26, 78, 150, 223, 232, 138, + 44, 195, 190, 199, 110, 171, 177, 52, 73, 176, 53, 52, 176, 25, + 30, 49, 104, 29, 39, 14, 121, 22, 167, 38, 118, 57, 11, 56, + 212, 63, 165, 27, 109, 230, 164, 254, 209, 128, 253, 126, 29, 201, + 146, 251, 86, 130, 97, 30, 46, 82, 39, 185, 178, 213, 160, 25, + 222, 68, 6, 51, 39, 16, 89, 171, 105, 127, 6, 250, 116, 12, + 127, 153, 252, 202, 148, 189, 230, 185, 143, 131, 152, 179, 253, 33, + 217, 13, 52, 230, 27, 152, 224, 249, 241, 122, 58, 92, 243, 90, + 38, 241, 110, 251, 93, 23, 63, 251, 62, 4, 108, 173, 230, 63, + 245, 41, 223, 148, 101, 127, 153, 230, 209, 5, 161, 105, 145, 232, + 171, 220, 204, 236, 222, 87, 123, 153, 74, 166, 97, 8, 85, 228, + 189, 190, 56, 104, 144, 82, 50, 163, 115, 124, 83, 32, 192, 100, + 97, 236, 122, 1, 233, 20, 118, 51, 228, 109, 140, 132, 201, 7, + 198, 211, 45, 79, 107, 196, 16, 241, 138, 23, 32, 254, 199, 89, + 51, 207, 6, 185, 56, 152, 234, 164, 193, 125, 126, 11, 178, 208, + 80, 51, 153, 52, 157, 29, 6, 61, 165, 103, 9, 210, 139, 136, + 96, 133, 249, 148, 174, 54, 201, 161, 128, 148, 53, 254, 131, 36, + 35, 71, 194, 69, 193, 183, 148, 206, 141, 88, 93, 226, 31, 221, + 167, 135, 227, 134, 187, 208, 37, 64, 217, 202, 250, 12, 174, 175, + 89, 250, 171, 220, 61, 199, 189, 212, 78, 89, 227, 6, 29, 15, + 144, 220, 244, 149, 195, 147, 30, 54, 170, 128, 30, 198, 53, 76, + 6, 177, 166, 32, 167, 243, 239, 59, 165, 55, 130, 57, 129, 70, + 183, 26, 157, 65, 31, 144, 66, 78, 23, 106, 48, 152, 21, 88, + 153, 124, 251, 154, 217, 110, 19, 129, 82, 141, 247, 240, 94, 98, + 63, 151, 175, 145, 173, 254, 170, 115, 236, 170, 92, 57, 238, 212, + 143, 172, 145, 141, 199, 48, 26, 133, 213, 94, 216, 65, 107, 40, + 170, 25, 23, 76, 124, 214, 150, 57, 75, 14, 105, 42, 176, 38, + 126, 162, 154, 37, 131, 14, 133, 167, 118, 236, 232, 90, 188, 49, + 94, 134, 173, 72, 135, 11, 128, 83, 154, 249, 168, 223, 106, 128, + 179, 111, 249, 209, 61, 62, 65, 213, 41, 132, 17, 234, 4, 235, + 247, 211, 175, 40, 106, 3, 155, 102, 62, 167, 108, 48, 33, 76, + 133, 51, 129, 152, 117, 251, 76, 192, 149, 24, 76, 45, 53, 134, + 182, 109, 95, 236, 144, 115, 1, 91, 235, 128, 169, 23, 31, 241, + 223, 38, 170, 115, 125, 45, 13, 40, 110, 50, 11, 228, 194, 226, + 130, 137, 73, 117, 38, 57, 247, 57, 113, 1, 146, 161, 207, 58, + 140, 135, 136, 124, 57, 51, 195, 249, 210, 112, 236, 221, 178, 141, + 37, 226, 180, 184, 57, 235, 57, 171, 242, 168, 63, 18, 248, 171, + 123, 134, 3, 172, 23, 209, 70, 36, 164, 212, 200, 142, 46, 66, + 173, 93, 236, 43, 48, 195, 240, 192, 105, 205, 150, 106, 148, 198, + 77, 45, 238, 163, 109, 255, 169, 205, 20, 129, 78, 71, 222, 242, + 200, 60, 43, 224, 150, 109, 93, 179, 189, 18, 24, 224, 193, 101, + 81, 200, 247, 25, 217, 94, 192, 60, 115, 44, 78, 161, 142, 172, + 100, 59, 72, 199, 17, 211, 83, 47, 46, 155, 172, 75, 28, 16, + 52, 38, 111, 13, 196, 55, 209, 181, 246, 160, 96, 221, 205, 9, + 234, 180, 80, 28, 189, 119, 6, 249, 42, 253, 87, 125, 111, 98, + 148, 175, 28, 5, 42, 138, 21, 30, 181, 180, 189, 204, 23, 103, + 87, 7, 204, 55, 66, 121, 236, 156, 157, 207, 3, 242, 27, 211, + 248, 81, 122, 158, 82, 115, 0, 15, 126, 107, 50, 29, 99, 78, + 13, 226, 126, 70, 138, 33, 129, 243, 157, 29, 0, 170, 118, 157, + 117, 121, 47, 243, 184, 26, 224, 185, 144, 216, 178, 71, 186, 156, + 111, 221, 150, 22, 124, 150, 19, 65, 119, 173, 226, 26, 194, 127, + 255, 223, 249, 251, 123, 119, 56, 168, 216, 140, 80, 37, 222, 116, + 167, 155, 250, 230, 194, 217, 0, 168, 65, 93, 96, 173, 21, 172, + 36, 73, 122, 148, 178, 247, 1, 242, 94, 102, 230, 29, 15, 253, + 132, 18, 145, 160, 19, 59, 73, 151, 247, 121, 208, 215, 253, 183, + 111, 240, 0, 41, 245, 74, 198, 45, 22, 220, 67, 214, 67, 231, + 17, 214, 253, 50, 210, 128, 108, 68, 203, 207, 223, 103, 210, 58, + 232, 139, 65, 12, 170, 237, 119, 144, 67, 20, 83, 246, 229, 166, + 21, 33, 66, 186, 231, 106, 77, 204, 82, 225, 191, 225, 220, 213, + 228, 168, 171, 19, 255, 198, 1, 163, 39, 39, 152, 2, 136, 211, + 19, 53, 50, 31, 189, 188, 46, 123, 185, 241, 107, 72, 83, 25, + 118, 8, 154, 154, 98, 220, 122, 81, 250, 158, 236, 191, 38, 22, + 86, 183, 204, 232, 56, 137, 51, 17, 63, 165, 248, 181, 107, 83, + 131, 74, 42, 60, 239, 123, 37, 227, 228, 143, 173, 243, 252, 113, + 18, 27, 27, 56, 187, 61, 194, 183, 156, 208, 37, 46, 91, 32, + 251, 136, 22, 229, 150, 125, 199, 133, 188, 43, 13, 96, 193, 75, + 39, 144, 222, 188, 117, 238, 201, 214, 11, 136, 148, 131, 179, 201, + 62, 233, 91, 77, 223, 144, 241, 117, 100, 203, 230, 100, 47, 8, + 10, 239, 16, 218, 142, 146, 181, 2, 197, 226, 154, 14, 48, 251, + 68, 94, 47, 179, 148, 167, 224, 211, 5, 185, 47, 13, 182, 42, + 41, 220, 121, 139, 87, 182, 215, 188, 108, 168, 0, 42, 44, 158, + 118, 221, 166, 21, 96, 223, 21, 222, 146, 3, 80, 12, 127, 90, + 24, 165, 13, 111, 52, 30, 176, 72, 143, 127, 132, 105, 184, 207, + 153, 221, 221, 43, 190, 38, 239, 56, 154, 169, 95, 46, 196, 149, + 178, 62, 145, 157, 102, 0, 190, 196, 71, 35, 22, 16, 32, 157, + 122, 86, 62, 215, 78, 55, 150, 146, 79, 240, 20, 12, 11, 111, + 95, 87, 163, 14, 56, 88, 48, 175, 163, 213, 159, 96, 42, 210, + 99, 199, 119, 40, 98, 154, 52, 135, 65, 16, 0, 142, 180, 95, + 8, 204, 45, 160, 128, 115, 149, 182, 104, 50, 99, 28, 68, 167, + 188, 163, 58, 75, 187, 177, 169, 61, 40, 215, 148, 233, 141, 204, + 71, 99, 119, 20, 253, 178, 253, 233, 208, 110, 223, 228, 172, 170, + 195, 156, 68, 157, 59, 2, 211, 236, 25, 102, 99, 48, 13, 244, + 101, 158, 51, 196, 140, 27, 102, 126, 102, 107, 132, 188, 88, 254, + 196, 196, 141, 248, 58, 241, 206, 25, 108, 74, 35, 227, 212, 37, + 187, 132, 242, 8, 240, 174, 50, 91, 83, 212, 69, 51, 238, 236, + 161, 243, 226, 137, 79, 14, 90, 127, 53, 239, 178, 82, 26, 79, + 14, 90, 2, 234, 224, 44, 226, 57, 142, 6, 196, 136, 116, 32, + 208, 124, 221, 253, 65, 141, 54, 128, 147, 180, 131, 185, 22, 195, + 20, 68, 177, 76, 194, 230, 86, 125, 163, 74, 176, 66, 34, 192, + 31, 11, 168, 34, 18, 3, 230, 94, 56, 60, 231, 186, 26, 55, + 37, 216, 70, 188, 37, 53, 135, 58, 179, 135, 128, 219, 45, 63, + 16, 157, 245, 69, 189, 42, 46, 235, 43, 170, 187, 132, 145, 34, + 175, 179, 92, 153, 94, 28, 107, 117, 132, 11, 17, 58, 130, 248, + 113, 174, 35, 223, 253, 209, 133, 227, 219, 26, 122, 79, 155, 159, + 254, 178, 177, 23, 251, 200, 155, 152, 170, 243, 60, 128, 162, 51, + 237, 39, 130, 224, 165, 194, 212, 11, 27, 76, 122, 185, 233, 14, + 141, 135, 4, 248, 237, 114, 202, 5, 195, 246, 147, 79, 17, 164, + 81, 219, 83, 201, 176, 225, 50, 221, 16, 202, 188, 227, 79, 171, + 12, 186, 249, 97, 160, 147, 176, 140, 186, 111, 22, 153, 219, 85, + 173, 63, 81, 38, 112, 217, 248, 93, 222, 66, 48, 156, 95, 216, + 246, 17, 75, 119, 21, 253, 67, 108, 34, 69, 254, 67, 187, 200, + 18, 116, 221, 64, 46, 13, 66, 135, 110, 188, 198, 74, 59, 104, + 216, 162, 123, 91, 20, 106, 153, 63, 134, 213, 129, 68, 101, 63, + 172, 153, 122, 122, 186, 37, 30, 15, 230, 136, 41, 40, 192, 188, + 235, 96, 225, 174, 110, 230, 26, 204, 167, 154, 50, 123, 210, 120, + 17, 178, 117, 243, 114, 189, 190, 178, 210, 127, 198, 178, 72, 109, + 97, 199, 148, 67, 144, 92, 242, 116, 173, 235, 184, 89, 109, 96, + 243, 237, 248, 199, 105, 79, 136, 66, 232, 118, 54, 208, 85, 106, + 70, 19, 19, 3, 36, 116, 131, 249, 25, 74, 47, 238, 116, 11, + 186, 91, 185, 55, 82, 122, 230, 134, 178, 98, 58, 127, 112, 110, + 111, 63, 221, 154, 234, 253, 46, 219, 98, 249, 236, 182, 130, 102, + 148, 40, 248, 157, 107, 133, 57, 74, 72, 24, 23, 165, 212, 232, + 212, 1, 241, 55, 83, 45, 127, 2, 251, 7, 4, 67, 111, 0, + 199, 3, 58, 18, 206, 108, 158, 170, 130, 59, 34, 16, 5, 201, + 18, 124, 112, 24, 197, 153, 151, 214, 66, 101, 132, 68, 62, 166, + 84, 125, 71, 24, 125, 49, 136, 211, 255, 144, 146, 136, 193, 188, + 80, 152, 70, 2, 163, 133, 129, 116, 82, 237, 237, 78, 203, 187, + 154, 100, 36, 238, 148, 202, 152, 231, 136, 200, 104, 110, 93, 49, + 173, 0, 160, 77, 130, 10, 123, 147, 204, 81, 97, 176, 205, 170, + 101, 169, 209, 214, 167, 184, 81, 37, 213, 173, 70, 106, 106, 10, + 131, 204, 56, 78, 133, 102, 176, 236, 78, 10, 176, 18, 142, 241, + 136, 122, 174, 175, 81, 191, 6, 248, 3, 111, 252, 64, 226, 188, + 23, 10, 127, 101, 121, 30, 43, 50, 106, 206, 128, 183, 231, 100, + 94, 140, 87, 105, 229, 90, 241, 251, 32, 63, 120, 67, 111, 29, + 127, 221, 90, 157, 224, 44, 95, 170, 227, 213, 239, 164, 167, 36, + 219, 161, 230, 208, 39, 31, 110, 120, 141, 112, 39, 198, 23, 181, + 202, 239, 0, 203, 158, 49, 35, 238, 32, 203, 199, 169, 190, 21, + 191, 6, 86, 242, 167, 229, 61, 189, 152, 64, 32, 20, 20, 125, + 230, 163, 184, 184, 25, 83, 71, 60, 64, 252, 6, 41, 255, 20, + 109, 4, 64, 0, 126, 224, 182, 168, 74, 222, 67, 103, 138, 239, + 180, 63, 53, 122, 20, 123, 215, 203, 42, 134, 155, 55, 245, 152, + 184, 87, 87, 81, 219, 29, 214, 175, 152, 150, 214, 237, 104, 248, + 19, 134, 208, 162, 101, 235, 22, 23, 89, 40, 36, 25, 229, 63, + 174, 243, 34, 65, 181, 120, 201, 7, 95, 107, 118, 31, 88, 30, + 35, 132, 197, 114, 3, 192, 75, 241, 241, 106, 20, 197, 221, 198, + 127, 123, 29, 192, 85, 18, 0, 109, 11, 69, 75, 21, 201, 235, + 92, 79, 144, 209, 253, 179, 250, 73, 5, 49, 39, 15, 63, 20, + 121, 194, 89, 227, 245, 8, 48, 189, 63, 136, 33, 20, 56, 233, + 193, 29, 145, 86, 78, 183, 252, 90, 135, 169, 244, 62, 236, 218, + 70, 88, 177, 28, 130, 214, 104, 180, 60, 210, 11, 192, 81, 31, + 109, 239, 59, 64, 54, 241, 128, 76, 239, 166, 90, 107, 113, 111, + 13, 144, 16, 196, 49, 179, 130, 193, 57, 192, 183, 60, 190, 54, + 7, 241, 39, 166, 67, 112, 58, 65, 140, 58, 164, 235, 59, 122, + 100, 149, 20, 97, 162, 52, 220, 72, 246, 239, 92, 153, 51, 186, + 227, 132, 206, 149, 231, 35, 0, 131, 148, 193, 79, 70, 161, 27, + 157, 245, 122, 173, 195, 47, 99, 249, 146, 211, 17, 33, 64, 180, + 31, 214, 136, 230, 253, 205, 164, 250, 73, 251, 195, 210, 133, 164, + 154, 249, 252, 226, 201, 45, 13, 81, 173, 235, 83, 120, 215, 228, + 152, 208, 145, 141, 149, 67, 111, 119, 105, 146, 215, 196, 0, 4, + 149, 142, 239, 173, 55, 149, 170, 171, 117, 226, 187, 153, 89, 163, + 255, 1, 91, 198, 41, 93, 14, 33, 103, 237, 2, 216, 210, 195, + 208, 116, 34, 60, 108, 191, 195, 212, 34, 207, 71, 12, 92, 38, + 205, 66, 236, 89, 80, 233, 202, 186, 58, 8, 199, 199, 197, 106, + 135, 247, 207, 103, 151, 62, 237, 154, 95, 229, 87, 176, 132, 42, + 201, 122, 227, 175, 200, 220, 137, 139, 101, 194, 247, 82, 142, 232, + 98, 235, 154, 252, 53, 234, 211, 121, 142, 254, 90, 81, 128, 40, + 205, 238, 117, 176, 144, 120, 154, 126, 2, 255, 36, 235, 247, 59, + 83, 67, 121, 185, 130, 185, 7, 186, 36, 207, 139, 131, 236, 232, + 87, 31, 96, 208, 14, 4, 124, 145, 99, 31, 9, 41, 72, 68, + 67, 154, 19, 138, 196, 147, 24, 214, 244, 131, 36, 183, 207, 23, + 225, 94, 103, 153, 2, 240, 145, 66, 71, 24, 238, 148, 5, 143, + 229, 112, 48, 167, 32, 37, 127, 254, 247, 77, 46, 101, 41, 30, + 70, 239, 121, 181, 202, 76, 69, 30, 7, 102, 160, 126, 144, 49, + 104, 227, 92, 181, 38, 82, 199, 205, 174, 212, 157, 238, 2, 114, + 217, 70, 153, 162, 208, 14, 120, 42, 137, 174, 87, 218, 142, 157, + 44, 211, 242, 234, 187, 52, 225, 206, 12, 118, 23, 36, 214, 52, + 60, 122, 5, 243, 77, 78, 35, 49, 127, 73, 60, 135, 183, 122, + 41, 24, 170, 196, 86, 157, 98, 43, 248, 90, 97, 0, 202, 73, + 217, 96, 233, 78, 223, 243, 173, 253, 192, 18, 46, 176, 17, 111, + 6, 24, 83, 53, 220, 156, 227, 136, 182, 239, 239, 225, 96, 78, + 12, 99, 194, 163, 239, 241, 94, 224, 211, 171, 44, 250, 100, 68, + 45, 16, 152, 219, 28, 156, 140, 216, 101, 32, 234, 202, 132, 211, + 111, 242, 52, 148, 117, 79, 25, 220, 128, 246, 126, 100, 200, 248, + 225, 117, 189, 81, 159, 101, 181, 107, 155, 26, 59, 36, 72, 17, + 61, 34, 21, 43, 204, 83, 160, 94, 1, 48, 34, 28, 197, 207, + 110, 61, 247, 153, 72, 248, 143, 116, 76, 238, 204, 252, 33, 0, + 235, 39, 94, 86, 169, 74, 151, 132, 48, 223, 63, 206, 45, 197, + 8, 93, 120, 57, 76, 71, 189, 161, 191, 175, 126, 235, 226, 186, + 136, 143, 202, 117, 98, 205, 56, 84, 40, 236, 119, 61, 245, 130, + 144, 100, 62, 40, 41, 31, 5, 86, 89, 38, 36, 196, 109, 174, + 33, 6, 241, 152, 218, 130, 123, 248, 212, 6, 90, 146, 185, 140, + 191, 169, 12, 91, 6, 12, 21, 3, 177, 77, 35, 164, 108, 35, + 176, 150, 59, 8, 167, 63, 196, 195, 25, 106, 250, 232, 41, 204, + 210, 37, 167, 179, 66, 77, 191, 191, 150, 164, 254, 153, 70, 58, + 114, 12, 97, 124, 101, 157, 154, 69, 151, 123, 214, 57, 198, 61, + 19, 93, 7, 140, 239, 0, 189, 220, 23, 174, 77, 225, 154, 189, + 223, 121, 93, 228, 140, 80, 151, 177, 126, 109, 145, 23, 192, 83, + 87, 14, 37, 219, 188, 154, 28, 251, 151, 234, 159, 28, 54, 16, + 43, 231, 202, 239, 87, 162, 221, 23, 208, 26, 75, 100, 84, 149, + 95, 86, 122, 199, 43, 177, 166, 9, 158, 3, 171, 58, 226, 104, + 250, 126, 255, 55, 159, 84, 233, 224, 71, 201, 33, 39, 172, 245, + 16, 130, 100, 179, 105, 104, 121, 208, 203, 1, 200, 1, 181, 9, + 112, 177, 146, 230, 65, 114, 175, 0, 205, 95, 67, 163, 214, 162, + 113, 245, 44, 16, 21, 50, 3, 244, 77, 224, 4, 155, 62, 247, + 24, 27, 14, 52, 206, 77, 158, 59, 46, 204, 51, 163, 157, 60, + 196, 56, 187, 23, 1, 132, 220, 75, 205, 86, 254, 139, 3, 62, + 137, 23, 244, 45, 132, 94, 214, 53, 211, 115, 251, 253, 57, 84, + 121, 83, 57, 46, 232, 14, 45, 79, 105, 26, 203, 142, 110, 25, + 148, 38, 155, 110, 108, 254, 68, 54, 233, 215, 127, 25, 191, 113, + 223, 128, 49, 243, 95, 58, 48, 72, 223, 187, 9, 251, 59, 57, + 83, 65, 196, 1, 197, 97, 132, 149, 112, 125, 23, 75, 144, 240, + 5, 20, 244, 67, 54, 4, 14, 122, 168, 100, 37, 169, 196, 228, + 115, 72, 182, 88, 33, 240, 92, 191, 9, 152, 8, 198, 29, 205, + 67, 104, 105, 148, 66, 250, 141, 174, 122, 157, 195, 144, 117, 185, + 189, 201, 39, 88, 40, 95, 176, 95, 232, 29, 62, 211, 173, 178, + 73, 222, 87, 67, 7, 5, 121, 64, 52, 92, 18, 106, 112, 192, + 234, 40, 105, 74, 31, 23, 8, 211, 153, 36, 8, 213, 5, 119, + 139, 143, 230, 72, 27, 106, 61, 34, 225, 78, 13, 7, 26, 149, + 22, 161, 122, 16, 207, 129, 39, 130, 48, 208, 174, 174, 251, 110, + 30, 132, 183, 131, 181, 73, 127, 243, 156, 135, 68, 38, 65, 156, + 176, 221, 2, 52, 172, 168, 74, 114, 28, 184, 103, 4, 84, 140, + 70, 144, 205, 123, 77, 51, 131, 144, 11, 54, 154, 74, 28, 152, + 89, 236, 213, 137, 30, 212, 197, 7, 248, 150, 219, 11, 68, 175, + 30, 109, 136, 43, 130, 240, 175, 173, 183, 6, 33, 138, 101, 196, + 106, 91, 154, 69, 20, 233, 138, 146, 218, 97, 113, 97, 122, 187, + 129, 56, 187, 94, 142, 179, 58, 57, 24, 32, 233, 242, 124, 164, + 227, 20, 173, 113, 218, 68, 196, 95, 229, 8, 189, 34, 234, 112, + 251, 154, 84, 100, 19, 139, 250, 135, 193, 44, 206, 50, 197, 13, + 230, 203, 107, 175, 109, 90, 181, 66, 153, 11, 113, 82, 7, 31, + 215, 83, 172, 246, 132, 74, 225, 253, 200, 63, 11, 242, 0, 48, + 249, 250, 160, 123, 88, 32, 35, 216, 51, 214, 106, 67, 55, 3, + 223, 54, 118, 114, 35, 195, 241, 175, 123, 81, 253, 3, 236, 241, + 51, 160, 204, 134, 134, 7, 31, 158, 213, 57, 69, 243, 36, 253, + 233, 6, 170, 174, 92, 179, 101, 168, 4, 95, 245, 216, 200, 42, + 75, 146, 9, 41, 228, 171, 107, 240, 59, 73, 231, 186, 2, 241, + 78, 225, 7, 204, 194, 1, 169, 71, 158, 239, 209, 174, 117, 182, + 74, 58, 91, 255, 101, 180, 53, 215, 141, 5, 25, 237, 44, 87, + 229, 4, 70, 226, 237, 128, 217, 201, 150, 227, 252, 35, 51, 116, + 189, 201, 30, 12, 79, 37, 98, 34, 151, 17, 189, 50, 126, 82, + 51, 224, 204, 157, 17, 56, 111, 142, 218, 255, 253, 19, 156, 141, + 97, 32, 241, 111, 171, 121, 209, 84, 83, 161, 250, 77, 112, 127, + 75, 55, 176, 112, 166, 25, 0, 47, 150, 131, 66, 140, 176, 199, + 182, 10, 14, 52, 104, 242, 191, 20, 15, 184, 59, 14, 132, 131, + 168, 127, 50, 30, 218, 30, 89, 186, 151, 76, 151, 129, 243, 197, + 170, 126, 90, 77, 54, 73, 88, 17, 236, 148, 168, 46, 215, 246, + 223, 92, 214, 221, 233, 28, 197, 215, 251, 100, 77, 30, 132, 149, + 147, 207, 18, 248, 158, 58, 241, 148, 223, 96, 40, 92, 210, 89, + 119, 166, 116, 241, 181, 155, 203, 87, 155, 175, 116, 112, 228, 65, + 63, 242, 51, 30, 137, 37, 233, 177, 23, 20, 117, 170, 20, 78, + 226, 85, 238, 14, 71, 138, 33, 52, 98, 221, 121, 136, 30, 10, + 72, 139, 226, 233, 172, 125, 172, 107, 40, 50, 39, 240, 52, 6, + 0, 152, 110, 98, 118, 137, 181, 114, 17, 43, 59, 96, 12, 146, + 105, 187, 234, 183, 13, 100, 96, 75, 130, 172, 0, 13, 230, 122, + 186, 98, 222, 183, 192, 181, 140, 21, 77, 189, 75, 73, 51, 176, + 114, 197, 95, 242, 60, 27, 44, 81, 132, 210, 86, 0, 175, 129, + 219, 51, 3, 97, 64, 240, 110, 241, 146, 245, 208, 77, 219, 89, + 124, 110, 62, 223, 178, 64, 217, 6, 112, 210, 149, 204, 63, 27, + 104, 54, 202, 96, 3, 61, 55, 198, 52, 125, 208, 15, 95, 254, + 201, 53, 158, 197, 166, 89, 204, 48, 77, 200, 114, 156, 61, 214, + 228, 97, 152, 52, 254, 180, 6, 250, 40, 238, 115, 89, 242, 112, + 92, 90, 205, 29, 143, 230, 96, 149, 45, 23, 91, 42, 242, 109, + 197, 249, 38, 101, 11, 99, 135, 235, 65, 224, 25, 200, 24, 233, + 221, 150, 22, 111, 121, 95, 211, 48, 151, 174, 198, 119, 132, 99, + 113, 248, 246, 253, 58, 171, 32, 29, 150, 189, 138, 40, 41, 174, + 124, 140, 134, 77, 196, 58, 108, 150, 78, 202, 192, 197, 97, 217, + 112, 43, 90, 12, 95, 214, 38, 225, 3, 239, 123, 234, 229, 113, + 38, 76, 37, 146, 189, 33, 220, 9, 10, 130, 120, 110, 223, 218, + 45, 189, 111, 179, 199, 226, 100, 169, 29, 223, 133, 68, 108, 70, + 36, 251, 157, 38, 15, 198, 232, 103, 114, 88, 119, 104, 34, 179, + 108, 110, 75, 197, 55, 119, 226, 54, 44, 62, 252, 228, 173, 250, + 91, 60, 251, 110, 177, 112, 167, 78, 91, 87, 95, 6, 144, 16, + 73, 198, 105, 79, 253, 188, 131, 91, 45, 177, 164, 50, 40, 44, + 142, 207, 46, 135, 106, 192, 69, 6, 11, 142, 213, 220, 68, 222, + 235, 233, 45, 162, 230, 190, 35, 186, 215, 225, 145, 169, 69, 152, + 32, 254, 122, 80, 129, 5, 53, 152, 236, 197, 179, 84, 180, 65, + 242, 189, 22, 122, 112, 57, 63, 57, 97, 108, 53, 154, 248, 48, + 205, 252, 90, 172, 237, 47, 227, 232, 11, 170, 171, 60, 157, 105, + 71, 121, 234, 138, 67, 53, 110, 212, 99, 83, 146, 51, 246, 221, + 66, 234, 188, 11, 246, 176, 162, 122, 32, 216, 9, 148, 230, 161, + 92, 249, 12, 115, 130, 244, 11, 237, 59, 251, 248, 118, 78, 156, + 248, 220, 86, 83, 90, 47, 31, 36, 194, 32, 235, 28, 5, 70, + 15, 150, 61, 136, 234, 102, 185, 176, 11, 13, 41, 69, 131, 108, + 120, 115, 187, 150, 135, 225, 51, 9, 244, 142, 86, 116, 78, 63, + 245, 91, 169, 14, 227, 2, 159, 54, 136, 204, 201, 215, 86, 135, + 219, 51, 120, 91, 152, 191, 103, 170, 158, 41, 3, 104, 229, 38, + 133, 105, 129, 109, 40, 6, 135, 220, 62, 154, 130, 81, 17, 36, + 38, 22, 134, 14, 115, 110, 171, 202, 117, 247, 164, 20, 99, 159, + 153, 132, 0, 235, 6, 142, 192, 111, 157, 229, 44, 85, 206, 84, + 92, 181, 88, 29, 0, 233, 109, 31, 223, 113, 83, 77, 14, 70, + 99, 238, 38, 202, 143, 233, 9, 22, 167, 231, 187, 15, 206, 196, + 104, 210, 87, 40, 40, 155, 169, 108, 185, 121, 198, 17, 147, 231, + 212, 253, 50, 231, 245, 199, 68, 179, 52, 56, 158, 134, 119, 246, + 88, 156, 232, 20, 122, 209, 57, 19, 31, 51, 153, 93, 137, 45, + 131, 226, 140, 25, 189, 170, 178, 71, 175, 150, 176, 133, 179, 155, + 124, 212, 160, 84, 31, 84, 238, 93, 226, 85, 147, 233, 127, 214, + 120, 228, 175, 94, 167, 223, 248, 178, 57, 218, 178, 222, 141, 171, + 46, 136, 21, 42, 211, 152, 129, 113, 31, 249, 28, 52, 18, 221, + 85, 34, 219, 18, 197, 140, 238, 179, 7, 201, 154, 117, 45, 53, + 208, 180, 116, 102, 229, 249, 229, 173, 112, 234, 24, 35, 33, 77, + 206, 86, 222, 134, 62, 218, 9, 40, 126, 45, 61, 133, 10, 198, + 25, 152, 77, 238, 188, 139, 212, 194, 100, 161, 47, 51, 121, 241, + 199, 15, 9, 50, 197, 149, 82, 117, 203, 74, 73, 169, 127, 243, + 195, 102, 92, 33, 34, 126, 6, 59, 154, 192, 226, 241, 153, 240, + 170, 100, 37, 56, 230, 147, 119, 253, 58, 138, 206, 75, 146, 96, + 65, 94, 117, 245, 204, 234, 66, 98, 161, 55, 105, 58, 110, 187, + 190, 71, 248, 244, 240, 41, 243, 113, 251, 63, 106, 82, 226, 165, + 98, 49, 68, 87, 7, 220, 60, 101, 141, 53, 166, 2, 247, 45, + 234, 186, 41, 62, 228, 191, 79, 77, 205, 187, 9, 153, 239, 187, + 211, 227, 73, 104, 14, 69, 63, 148, 218, 55, 240, 36, 94, 65, + 129, 225, 225, 103, 230, 23, 23, 126, 57, 17, 96, 34, 52, 189, + 152, 164, 170, 78, 47, 58, 125, 194, 98, 48, 29, 163, 245, 197, + 196, 132, 137, 79, 128, 13, 164, 156, 207, 104, 135, 52, 77, 101, + 209, 234, 235, 72, 51, 141, 169, 157, 187, 51, 7, 188, 133, 28, + 204, 67, 195, 84, 251, 67, 229, 104, 122, 117, 117, 13, 56, 145, + 228, 1, 254, 73, 66, 89, 197, 12, 207, 177, 136, 141, 13, 243, + 165, 67, 208, 205, 200, 22, 232, 193, 196, 187, 122, 153, 90, 99, + 78, 0, 2, 184, 104, 68, 166, 140, 194, 224, 207, 228, 28, 244, + 128, 15, 61, 195, 45, 183, 134, 38, 157, 25, 113, 3, 160, 25, + 184, 117, 59, 134, 221, 200, 250, 21, 27, 187, 187, 252, 63, 174, + 146, 76, 59, 230, 127, 51, 222, 175, 105, 205, 78, 188, 28, 196, + 181, 58, 48, 60, 228, 217, 118, 186, 154, 255, 8, 57, 104, 150, + 180, 33, 49, 67, 146, 115, 54, 12, 78, 181, 232, 151, 80, 44, + 172, 192, 55, 238, 86, 42, 83, 240, 208, 103, 33, 138, 39, 140, + 4, 108, 246, 86, 14, 177, 59, 171, 190, 228, 38, 27, 211, 130, + 243, 166, 82, 115, 143, 176, 213, 181, 203, 187, 133, 156, 12, 89, + 5, 253, 80, 79, 38, 249, 23, 149, 156, 142, 128, 221, 78, 199, + 76, 52, 22, 61, 39, 173, 124, 7, 118, 219, 122, 47, 45, 199, + 210, 4, 37, 167, 247, 120, 3, 225, 143, 208, 69, 5, 59, 120, + 116, 48, 157, 123, 46, 199, 15, 208, 200, 184, 109, 205, 232, 164, + 79, 92, 46, 174, 120, 162, 222, 182, 62, 194, 108, 215, 35, 47, + 7, 168, 227, 224, 242, 78, 216, 138, 9, 103, 135, 172, 197, 225, + 220, 132, 41, 39, 165, 155, 96, 52, 81, 225, 168, 227, 144, 38, + 65, 19, 252, 214, 153, 154, 87, 12, 129, 50, 210, 227, 192, 71, + 136, 2, 234, 2, 181, 202, 96, 211, 60, 240, 62, 176, 32, 218, + 138, 182, 228, 103, 201, 37, 40, 18, 53, 143, 254, 79, 83, 170, + 223, 254, 186, 116, 62, 67, 15, 189, 27, 176, 27, 197, 218, 126, + 118, 106, 102, 75, 40, 162, 169, 244, 163, 130, 126, 70, 203, 26, + 46, 136, 245, 168, 46, 48, 229, 27, 39, 80, 231, 221, 14, 220, + 92, 223, 136, 106, 245, 36, 65, 232, 186, 35, 16, 90, 153, 22, + 146, 48, 109, 219, 180, 227, 129, 65, 39, 153, 32, 115, 246, 69, + 117, 53, 198, 200, 157, 228, 80, 52, 108, 10, 147, 140, 126, 34, + 120, 67, 118, 111, 185, 161, 75, 128, 240, 199, 12, 252, 48, 130, + 47, 231, 46, 67, 176, 154, 0, 187, 74, 18, 177, 191, 170, 7, + 52, 83, 178, 72, 21, 217, 146, 81, 39, 12, 22, 44, 83, 174, + 251, 174, 130, 69, 204, 172, 54, 21, 216, 201, 149, 189, 56, 222, + 80, 150, 151, 92, 21, 113, 30, 149, 74, 221, 80, 61, 227, 231, + 245, 3, 217, 140, 252, 0, 149, 86, 132, 67, 64, 192, 45, 214, + 211, 158, 158, 241, 147, 8, 83, 137, 183, 166, 215, 128, 71, 23, + 179, 205, 128, 110, 215, 47, 147, 185, 140, 242, 240, 142, 240, 129, + 166, 2, 97, 188, 2, 75, 203, 165, 108, 14, 172, 166, 9, 228, + 197, 232, 162, 52, 175, 221, 14, 49, 229, 224, 211, 104, 212, 23, + 17, 173, 141, 235, 219, 174, 237, 80, 167, 132, 41, 182, 20, 108, + 220, 208, 194, 51, 24, 166, 136, 76, 217, 2, 86, 123, 167, 9, + 238, 246, 78, 255, 150, 173, 77, 138, 157, 233, 131, 125, 91, 117, + 17, 31, 158, 188, 252, 162, 179, 155, 81, 57, 34, 158, 19, 32, + 130, 229, 199, 128, 136, 187, 13, 20, 84, 206, 2, 119, 21, 10, + 58, 5, 247, 209, 200, 21, 10, 227, 77, 81, 116, 154, 10, 177, + 75, 191, 16, 191, 17, 109, 145, 222, 172, 68, 134, 60, 114, 178, + 106, 206, 241, 186, 246, 89, 19, 95, 227, 50, 38, 42, 15, 138, + 218, 129, 174, 39, 201, 75, 90, 19, 80, 4, 163, 49, 141, 161, + 153, 139, 182, 235, 176, 74, 97, 153, 13, 47, 25, 50, 48, 164, + 50, 79, 118, 127, 117, 211, 119, 70, 2, 163, 133, 129, 116, 82, + 237, 237, 78, 203, 187, 154, 100, 36, 238, 148, 202, 154, 93, 166, + 71, 128, 49, 68, 142, 11, 140, 224, 223, 58, 165, 34, 123, 83, + 184, 2, 126, 101, 108, 145, 198, 14, 141, 48, 160, 130, 166, 59, + 203, 226, 185, 126, 128, 129, 110, 75, 167, 240, 145, 160, 6, 212, + 148, 77, 155, 242, 109, 16, 75, 157, 59, 77, 63, 231, 195, 194, + 98, 79, 136, 14, 146, 62, 253, 23, 45, 46, 89, 115, 50, 112, + 77, 59, 25, 121, 77, 143, 92, 58, 38, 181, 126, 151, 43, 79, + 113, 196, 235, 212, 249, 182, 87, 166, 230, 119, 240, 154, 197, 172, + 22, 139, 183, 186, 146, 178, 186, 52, 6, 113, 8, 33, 0, 74, + 6, 176, 137, 60, 159, 122, 152, 36, 252, 222, 174, 237, 203, 185, + 105, 221, 130, 17, 85, 197, 134, 182, 89, 187, 60, 233, 124, 131, + 218, 139, 213, 224, 218, 46, 231, 248, 12, 185, 210, 35, 193, 158, + 0, 27, 75, 155, 121, 91, 136, 78, 78, 111, 57, 107, 110, 173, + 238, 178, 10, 214, 164, 243, 67, 46, 52, 236, 144, 39, 18, 178, + 80, 186, 95, 203, 66, 99, 77, 238, 78, 127, 27, 231, 21, 157, + 150, 245, 207, 179, 140, 85, 132, 42, 172, 183, 226, 36, 66, 198, + 189, 108, 104, 232, 78, 112, 186, 51, 123, 209, 109, 96, 4, 176, + 212, 104, 193, 192, 182, 113, 126, 139, 9, 63, 113, 120, 37, 210, + 71, 192, 87, 250, 234, 203, 147, 149, 129, 228, 100, 137, 39, 212, + 124, 230, 99, 113, 188, 34, 156, 100, 178, 47, 68, 99, 111, 1, + 150, 4, 203, 16, 167, 135, 165, 162, 157, 13, 222, 43, 236, 181, + 225, 120, 233, 255, 116, 118, 182, 185, 222, 182, 239, 119, 94, 129, + 36, 226, 233, 169, 226, 89, 88, 93, 29, 228, 35, 41, 15, 248, + 124, 3, 31, 55, 65, 49, 49, 155, 140, 104, 172, 207, 36, 249, + 101, 112, 109, 80, 176, 223, 149, 134, 131, 155, 246, 216, 36, 192, + 246, 62, 183, 182, 237, 0, 146, 78, 81, 234, 247, 139, 208, 68, + 140, 12, 236, 147, 240, 30, 56, 217, 205, 158, 30, 125, 39, 237, + 66, 95, 79, 55, 62, 49, 64, 49, 186, 55, 158, 238, 119, 172, + 152, 198, 64, 137, 113, 106, 173, 225, 170, 133, 245, 117, 188, 30, + 127, 58, 131, 113, 46, 126, 60, 172, 135, 95, 81, 201, 20, 6, + 142, 59, 171, 165, 238, 133, 129, 192, 115, 240, 71, 176, 111, 120, + 158, 150, 89, 162, 124, 175, 160, 141, 191, 109, 167, 5, 50, 236, + 199, 84, 135, 235, 239, 201, 237, 198, 141, 101, 101, 162, 170, 41, + 73, 204, 12, 36, 208, 162, 34, 170, 235, 244, 120, 160, 183, 68, + 30, 216, 13, 43, 237, 79, 165, 49, 249, 202, 56, 8, 207, 198, + 106, 142, 118, 200, 88, 30, 116, 229, 213, 78, 88, 175, 83, 29, + 82, 172, 230, 179, 82, 160, 161, 146, 22, 222, 198, 248, 47, 209, + 99, 225, 16, 118, 43, 9, 42, 207, 201, 162, 126, 34, 86, 197, + 54, 141, 7, 17, 75, 189, 153, 77, 235, 212, 143, 197, 178, 69, + 230, 29, 24, 192, 71, 17, 126, 36, 76, 107, 0, 188, 134, 175, + 65, 92, 66, 153, 57, 247, 135, 139, 250, 30, 90, 225, 86, 50, + 78, 225, 238, 70, 11, 172, 183, 144, 31, 160, 138, 64, 136, 45, + 103, 129, 233, 187, 193, 14, 144, 193, 187, 64, 47, 91, 71, 86, + 30, 237, 104, 4, 235, 54, 121, 64, 20, 165, 239, 52, 21, 0, + 18, 196, 126, 147, 128, 241, 172, 200, 255, 252, 66, 3, 103, 216, + 237, 231, 53, 199, 116, 64, 60, 93, 206, 252, 40, 255, 223, 132, + 195, 215, 241, 125, 150, 42, 182, 235, 114, 142, 255, 53, 221, 106, + 82, 167, 156, 103, 21, 74, 172, 108, 19, 70, 175, 229, 40, 89, + 136, 48, 171, 127, 184, 19, 7, 9, 98, 57, 233, 43, 184, 182, + 19, 117, 41, 181, 53, 165, 68, 104, 87, 182, 170, 127, 74, 181, + 77, 137, 154, 141, 208, 160, 192, 195, 120, 102, 117, 139, 239, 228, + 179, 146, 37, 144, 33, 230, 216, 159, 105, 36, 80, 244, 1, 15, + 142, 88, 159, 29, 57, 99, 251, 190, 216, 105, 226, 236, 34, 162, + 28, 73, 73, 166, 140, 46, 206, 181, 164, 29, 117, 114, 48, 88, + 120, 24, 208, 219, 182, 138, 208, 166, 10, 158, 111, 90, 47, 148, + 134, 31, 68, 223, 127, 70, 206, 127, 170, 142, 3, 148, 10, 104, + 6, 43, 207, 91, 47, 49, 45, 202, 5, 211, 219, 82, 148, 139, + 226, 207, 52, 171, 83, 37, 79, 210, 27, 174, 201, 50, 30, 192, + 93, 221, 120, 166, 94, 108, 181, 109, 206, 119, 29, 57, 12, 97, + 90, 208, 158, 213, 61, 1, 159, 104, 118, 98, 173, 183, 172, 245, + 119, 4, 38, 245, 185, 113, 235, 138, 23, 108, 5, 102, 132, 91, + 208, 114, 123, 214, 179, 112, 20, 55, 175, 227, 66, 59, 93, 190, + 58, 253, 177, 102, 199, 6, 152, 238, 41, 112, 148, 210, 53, 116, + 199, 72, 137, 74, 2, 153, 101, 91, 137, 100, 209, 216, 20, 98, + 165, 10, 245, 157, 214, 158, 123, 143, 112, 214, 10, 238, 147, 142, + 119, 40, 97, 217, 98, 15, 98, 184, 35, 136, 67, 12, 146, 52, + 122, 116, 109, 231, 122, 176, 158, 146, 0, 3, 75, 213, 204, 107, + 14, 90, 92, 80, 136, 180, 201, 231, 37, 211, 120, 40, 229, 182, + 133, 39, 85, 4, 20, 155, 242, 35, 148, 182, 162, 169, 6, 168, + 202, 154, 242, 83, 68, 161, 48, 28, 237, 189, 100, 171, 250, 253, + 64, 246, 73, 77, 101, 129, 169, 71, 204, 65, 164, 45, 206, 232, + 166, 168, 117, 147, 227, 48, 248, 150, 132, 184, 57, 154, 30, 255, + 199, 129, 112, 15, 253, 154, 78, 225, 116, 71, 85, 26, 204, 15, + 170, 121, 91, 118, 204, 199, 212, 230, 5, 124, 95, 238, 135, 77, + 154, 12, 74, 123, 131, 19, 97, 51, 84, 219, 136, 133, 103, 217, + 132, 230, 53, 81, 156, 74, 47, 145, 220, 90, 84, 163, 47, 229, + 230, 135, 159, 252, 246, 183, 23, 8, 236, 254, 247, 59, 160, 194, + 190, 137, 39, 38, 77, 114, 255, 199, 166, 102, 17, 66, 50, 127, + 122, 138, 247, 40, 123, 120, 127, 227, 50, 59, 35, 63, 246, 79, + 206, 168, 166, 105, 168, 100, 54, 88, 216, 204, 180, 35, 69, 45, + 245, 78, 87, 169, 147, 16, 0, 93, 241, 180, 27, 218, 92, 62, + 98, 97, 0, 144, 49, 231, 226, 191, 198, 37, 205, 120, 109, 219, + 97, 183, 172, 192, 110, 53, 96, 131, 249, 133, 78, 36, 230, 112, + 100, 123, 50, 124, 140, 188, 3, 92, 59, 49, 158, 190, 196, 109, + 42, 207, 7, 154, 78, 43, 30, 110, 186, 178, 234, 254, 81, 134, + 36, 129, 6, 202, 190, 198, 153, 70, 126, 245, 163, 162, 138, 4, + 91, 181, 185, 186, 99, 34, 24, 163, 91, 205, 130, 39, 238, 156, + 53, 251, 167, 191, 152, 197, 71, 26, 102, 142, 55, 46, 185, 93, + 228, 95, 174, 38, 80, 209, 43, 137, 78, 44, 108, 232, 175, 61, + 144, 233, 202, 151, 177, 54, 254, 109, 24, 18, 29, 4, 177, 84, + 211, 123, 99, 23, 129, 98, 16, 181, 0, 115, 84, 82, 98, 177, + 33, 35, 177, 131, 39, 180, 239, 125, 242, 199, 246, 148, 105, 82, + 205, 143, 35, 194, 131, 107, 204, 78, 204, 215, 223, 50, 174, 86, + 51, 132, 205, 183, 108, 171, 149, 223, 84, 94, 53, 163, 162, 249, + 220, 213, 65, 141, 32, 250, 202, 1, 87, 94, 95, 98, 217, 228, + 189, 57, 41, 115, 117, 181, 111, 126, 46, 63, 105, 212, 223, 48, + 155, 134, 44, 56, 235, 47, 117, 175, 232, 10, 63, 159, 140, 9, + 24, 237, 189, 190, 44, 79, 40, 179, 33, 10, 208, 35, 41, 138, + 198, 133, 36, 237, 246, 116, 251, 172, 75, 190, 60, 146, 209, 79, + 255, 82, 212, 101, 171, 247, 79, 69, 100, 210, 136, 171, 85, 190, + 140, 123, 177, 154, 5, 97, 161, 4, 240, 227, 176, 57, 216, 119, + 244, 161, 65, 195, 63, 137, 7, 168, 246, 20, 19, 72, 59, 135, + 56, 240, 108, 217, 203, 147, 105, 149, 90, 203, 12, 0, 53, 214, + 60, 192, 112, 102, 116, 245, 242, 69, 147, 195, 125, 192, 32, 143, + 163, 224, 199, 113, 221, 146, 40, 151, 205, 201, 25, 34, 39, 6, + 154, 13, 250, 15, 229, 98, 215, 149, 6, 154, 162, 45, 142, 66, + 219, 101, 138, 17, 23, 205, 65, 150, 132, 59, 80, 84, 150, 203, + 122, 78, 39, 61, 184, 149, 201, 95, 141, 82, 70, 52, 114, 108, + 233, 164, 84, 122, 53, 84, 104, 116, 255, 154, 227, 118, 227, 45, + 58, 101, 27, 228, 128, 130, 140, 158, 113, 29, 111, 212, 103, 135, + 127, 221, 128, 178, 149, 246, 106, 202, 100, 208, 210, 39, 154, 45, + 177, 120, 153, 211, 155, 45, 136, 189, 192, 58, 26, 25, 38, 59, + 75, 183, 82, 169, 114, 51, 126, 19, 224, 105, 81, 113, 130, 214, + 125, 223, 66, 186, 168, 205, 201, 214, 246, 63, 202, 61, 211, 26, + 15, 13, 205, 132, 38, 235, 49, 51, 204, 3, 137, 187, 175, 216, + 62, 0, 252, 31, 233, 250, 153, 55, 216, 151, 21, 110, 30, 68, + 184, 19, 117, 145, 84, 164, 99, 15, 76, 53, 22, 75, 9, 232, + 170, 36, 219, 121, 206, 130, 213, 45, 5, 160, 96, 175, 4, 123, + 122, 24, 25, 67, 184, 116, 207, 183, 216, 92, 185, 222, 251, 197, + 154, 220, 223, 192, 167, 89, 173, 87, 51, 129, 18, 116, 140, 157, + 141, 199, 76, 51, 3, 77, 226, 16, 230, 57, 167, 180, 186, 13, + 122, 158, 152, 167, 11, 82, 197, 190, 2, 194, 116, 239, 242, 216, + 15, 73, 54, 102, 112, 6, 209, 222, 214, 87, 99, 145, 140, 247, + 243, 180, 249, 75, 235, 217, 51, 19, 200, 63, 6, 138, 108, 23, + 145, 201, 76, 165, 150, 239, 226, 19, 1, 43, 113, 165, 204, 128, + 180, 10, 29, 113, 202, 156, 225, 81, 110, 255, 111, 111, 251, 123, + 191, 140, 13, 111, 95, 211, 65, 96, 43, 77, 74, 30, 108, 65, + 248, 12, 204, 230, 153, 158, 127, 169, 37, 131, 183, 227, 206, 231, + 56, 154, 179, 91, 107, 89, 174, 123, 249, 145, 70, 19, 129, 122, + 63, 200, 196, 31, 74, 157, 221, 223, 52, 211, 59, 27, 167, 51, + 235, 253, 229, 148, 138, 70, 135, 73, 237, 211, 161, 249, 118, 81, + 121, 1, 166, 249, 16, 74, 102, 166, 124, 134, 28, 205, 200, 112, + 34, 149, 137, 40, 215, 36, 15, 38, 29, 182, 94, 177, 233, 59, + 173, 57, 163, 4, 203, 121, 103, 163, 6, 27, 44, 229, 204, 192, + 236, 221, 1, 212, 74, 236, 47, 62, 211, 191, 84, 109, 22, 255, + 254, 232, 21, 185, 87, 189, 82, 252, 116, 121, 231, 243, 16, 236, + 100, 100, 48, 82, 107, 25, 228, 236, 21, 83, 123, 235, 14, 129, + 135, 133, 237, 70, 233, 151, 5, 168, 125, 60, 73, 58, 180, 206, + 130, 41, 172, 26, 145, 15, 72, 254, 38, 123, 47, 210, 21, 81, + 63, 185, 157, 1, 149, 34, 55, 109, 214, 117, 34, 28, 2, 40, + 115, 40, 193, 20, 76, 161, 51, 199, 132, 198, 33, 165, 240, 8, + 208, 198, 131, 95, 199, 183, 166, 4, 135, 12, 200, 4, 54, 26, + 84, 56, 149, 247, 159, 227, 119, 150, 115, 167, 227, 227, 32, 237, + 18, 153, 194, 107, 168, 226, 178, 224, 91, 32, 199, 17, 238, 32, + 170, 40, 0, 70, 168, 6, 74, 47, 107, 193, 125, 7, 56, 225, + 120, 78, 142, 213, 130, 36, 39, 55, 207, 242, 40, 124, 6, 193, + 233, 165, 23, 51, 53, 237, 75, 129, 93, 223, 88, 182, 49, 158, + 91, 229, 228, 61, 243, 8, 233, 208, 223, 225, 131, 185, 144, 62, + 237, 102, 103, 101, 49, 104, 79, 55, 40, 210, 228, 218, 226, 198, + 154, 38, 130, 183, 246, 66, 14, 81, 71, 233, 16, 96, 164, 132, + 78, 175, 191, 114, 77, 56, 1, 159, 125, 183, 113, 242, 39, 208, + 113, 20, 214, 203, 14, 200, 5, 5, 81, 10, 99, 235, 61, 14, + 54, 150, 165, 189, 73, 87, 94, 104, 202, 100, 133, 252, 24, 78, + 159, 181, 255, 111, 198, 84, 197, 24, 252, 150, 47, 203, 190, 63, + 91, 236, 93, 148, 232, 246, 190, 188, 164, 209, 90, 183, 91, 92, + 179, 89, 57, 122, 100, 34, 63, 117, 21, 25, 24, 11, 120, 194, + 5, 164, 214, 142, 193, 33, 246, 27, 62, 182, 213, 53, 246, 106, + 66, 149, 112, 145, 219, 229, 221, 201, 106, 10, 239, 109, 249, 67, + 143, 217, 254, 160, 197, 9, 107, 169, 243, 163, 237, 197, 30, 198, + 48, 84, 228, 174, 89, 33, 248, 6, 224, 80, 221, 73, 63, 49, + 117, 145, 151, 78, 164, 24, 254, 147, 3, 82, 18, 17, 201, 40, + 113, 102, 4, 119, 93, 9, 172, 114, 97, 82, 72, 106, 249, 47, + 224, 240, 19, 107, 218, 145, 148, 6, 238, 148, 69, 198, 231, 92, + 92, 170, 76, 174, 2, 28, 174, 45, 185, 191, 44, 21, 68, 201, + 198, 250, 82, 125, 253, 236, 46, 115, 215, 204, 178, 142, 131, 13, + 25, 210, 197, 169, 106, 139, 203, 108, 150, 211, 231, 136, 175, 247, + 77, 8, 235, 127, 212, 57, 166, 239, 21, 36, 211, 140, 66, 42, + 17, 215, 102, 40, 178, 57, 121, 103, 6, 197, 33, 110, 40, 124, + 123, 167, 179, 150, 83, 156, 231, 180, 160, 131, 163, 47, 52, 35, + 159, 200, 190, 120, 9, 241, 11, 194, 116, 133, 175, 94, 140, 147, + 92, 194, 76, 189, 150, 83, 183, 254, 160, 60, 122, 227, 63, 14, + 249, 185, 112, 138, 67, 241, 229, 57, 209, 177, 21, 239, 96, 142, + 79, 218, 45, 154, 74, 119, 113, 100, 51, 86, 67, 155, 195, 57, + 164, 51, 51, 82, 40, 113, 76, 221, 4, 72, 241, 123, 249, 166, + 147, 43, 49, 30, 101, 168, 56, 203, 89, 146, 166, 248, 75, 153, + 58, 95, 220, 133, 97, 147, 111, 165, 205, 63, 107, 188, 163, 167, + 235, 148, 192, 8, 82, 51, 96, 237, 134, 250, 22, 199, 247, 84, + 168, 107, 104, 247, 105, 82, 72, 24, 130, 207, 74, 127, 9, 192, + 162, 134, 125, 0, 247, 109, 72, 10, 96, 210, 210, 144, 223, 131, + 229, 153, 43, 41, 38, 55, 113, 18, 192, 175, 125, 96, 229, 168, + 148, 107, 120, 224, 92, 22, 119, 45, 77, 186, 101, 217, 174, 130, + 230, 161, 208, 166, 57, 4, 230, 248, 216, 227, 215, 45, 111, 167, + 42, 179, 18, 50, 6, 19, 255, 148, 188, 22, 193, 224, 134, 128, + 230, 13, 61, 138, 18, 214, 55, 60, 199, 46, 44, 195, 66, 30, + 219, 159, 206, 135, 174, 209, 205, 4, 243, 116, 239, 30, 221, 59, + 128, 45, 48, 36, 204, 125, 193, 218, 251, 232, 12, 32, 96, 157, + 198, 79, 245, 34, 189, 211, 175, 182, 158, 161, 190, 65, 79, 190, + 195, 21, 252, 6, 130, 139, 46, 8, 96, 11, 250, 13, 54, 49, + 189, 165, 41, 116, 46, 189, 166, 119, 146, 128, 69, 173, 162, 46, + 47, 39, 201, 43, 40, 35, 238, 118, 118, 216, 171, 194, 34, 7, + 253, 139, 38, 206, 150, 120, 108, 252, 56, 71, 204, 184, 254, 36, + 62, 120, 19, 113, 232, 154, 96, 93, 198, 58, 157, 121, 191, 20, + 135, 233, 31, 7, 116, 109, 42, 207, 237, 83, 226, 128, 5, 131, + 111, 65, 38, 191, 187, 215, 35, 147, 29, 138, 178, 8, 80, 84, + 76, 23, 58, 214, 78, 157, 113, 245, 135, 19, 102, 44, 134, 22, + 33, 44, 8, 52, 119, 77, 21, 164, 137, 23, 47, 179, 239, 35, + 9, 238, 195, 57, 92, 120, 140, 227, 64, 215, 224, 59, 243, 32, + 29, 42, 73, 72, 56, 48, 190, 198, 30, 171, 72, 105, 169, 128, + 142, 229, 246, 156, 226, 123, 239, 71, 195, 3, 219, 96, 208, 232, + 141, 219, 181, 56, 155, 245, 253, 194, 18, 150, 68, 170, 137, 241, + 202, 65, 186, 249, 130, 175, 89, 126, 148, 56, 99, 0, 41, 213, + 250, 188, 99, 156, 224, 142, 200, 61, 201, 100, 170, 209, 43, 190, + 227, 18, 13, 250, 26, 55, 200, 10, 22, 89, 247, 196, 145, 245, + 151, 23, 153, 110, 176, 247, 82, 17, 1, 158, 134, 241, 124, 87, + 107, 149, 135, 252, 235, 249, 255, 157, 91, 230, 11, 154, 62, 133, + 253, 250, 244, 33, 5, 72, 124, 173, 219, 74, 102, 145, 167, 118, + 171, 232, 183, 108, 252, 217, 76, 137, 251, 106, 248, 142, 188, 103, + 191, 166, 27, 87, 80, 173, 225, 2, 179, 165, 205, 155, 225, 37, + 87, 163, 56, 187, 120, 114, 69, 126, 171, 90, 164, 160, 75, 62, + 26, 13, 151, 228, 110, 112, 231, 169, 147, 192, 191, 48, 194, 186, + 111, 72, 143, 245, 186, 103, 66, 196, 198, 157, 46, 245, 174, 81, + 55, 67, 90, 158, 209, 123, 185, 16, 177, 106, 207, 31, 196, 33, + 203, 145, 100, 65, 88, 9, 198, 179, 180, 188, 0, 207, 20, 130, + 22, 69, 14, 54, 11, 56, 109, 141, 138, 188, 118, 178, 155, 38, + 150, 167, 209, 156, 126, 21, 156, 183, 255, 84, 138, 172, 45, 93, + 205, 235, 109, 195, 35, 210, 78, 18, 244, 33, 214, 132, 175, 132, + 168, 207, 63, 54, 175, 219, 215, 164, 162, 97, 234, 68, 187, 64, + 100, 83, 204, 7, 52, 80, 156, 162, 238, 157, 199, 26, 156, 248, + 237, 234, 89, 103, 158, 85, 64, 152, 185, 46, 27, 220, 151, 187, + 16, 83, 41, 178, 68, 55, 100, 230, 240, 69, 19, 175, 11, 172, + 141, 77, 126, 55, 137, 98, 181, 10, 85, 252, 189, 105, 227, 140, + 203, 120, 99, 219, 156, 51, 120, 199, 156, 238, 55, 236, 84, 190, + 24, 34, 129, 242, 99, 80, 2, 106, 48, 152, 254, 221, 66, 132, + 210, 138, 88, 189, 131, 173, 125, 144, 228, 51, 238, 92, 233, 20, + 57, 61, 201, 19, 40, 165, 184, 102, 9, 130, 104, 96, 88, 246, + 241, 127, 12, 67, 44, 4, 117, 136, 97, 162, 1, 138, 149, 168, + 144, 217, 43, 208, 221, 223, 227, 107, 205, 85, 116, 22, 33, 122, + 169, 113, 183, 128, 153, 13, 179, 95, 121, 40, 147, 232, 70, 26, + 69, 160, 66, 120, 200, 15, 25, 232, 118, 177, 35, 8, 161, 180, + 82, 112, 183, 100, 78, 133, 160, 251, 249, 96, 25, 251, 31, 20, + 164, 179, 72, 219, 60, 17, 128, 54, 206, 56, 76, 130, 8, 171, + 104, 62, 48, 63, 235, 24, 165, 227, 175, 150, 96, 115, 153, 219, + 141, 132, 152, 231, 25, 240, 14, 158, 216, 189, 217, 108, 136, 129, + 126, 146, 249, 138, 176, 61, 74, 44, 185, 52, 114, 126, 226, 108, + 64, 235, 251, 165, 135, 81, 22, 233, 232, 165, 107, 142, 207, 210, + 34, 211, 97, 199, 152, 146, 30, 155, 99, 198, 200, 124, 43, 181, + 85, 56, 1, 250, 150, 127, 99, 21, 60, 226, 140, 69, 110, 180, + 233, 82, 165, 49, 252, 212, 113, 246, 106, 39, 203, 203, 90, 79, + 202, 124, 228, 97, 11, 99, 98, 127, 68, 38, 46, 237, 177, 124, + 43, 160, 103, 234, 164, 171, 7, 210, 145, 47, 115, 248, 7, 58, + 126, 139, 72, 30, 162, 200, 136, 239, 120, 26, 128, 168, 113, 95, + 177, 25, 14, 223, 95, 16, 118, 23, 181, 72, 118, 122, 120, 253, + 7, 112, 224, 60, 131, 168, 163, 44, 24, 68, 197, 67, 179, 180, + 253, 235, 70, 83, 119, 139, 112, 222, 207, 187, 143, 223, 84, 86, + 57, 60, 76, 185, 78, 74, 222, 8, 229, 77, 117, 192, 180, 196, + 143, 73, 86, 185, 24, 46, 140, 233, 146, 7, 155, 186, 68, 130, + 32, 170, 21, 125, 73, 129, 41, 182, 104, 0, 212, 11, 69, 197, + 167, 195, 21, 61, 72, 56, 95, 190, 221, 214, 109, 164, 57, 157, + 38, 107, 68, 59, 175, 227, 193, 6, 78, 40, 230, 183, 29, 61, + 47, 184, 100, 29, 49, 30, 19, 155, 141, 96, 149, 45, 147, 156, + 215, 163, 3, 110, 93, 212, 142, 37, 103, 94, 24, 176, 20, 182, + 60, 222, 128, 239, 137, 15, 80, 72, 239, 111, 238, 248, 78, 125, + 166, 196, 27, 139, 19, 139, 12, 108, 250, 147, 220, 181, 52, 36, + 155, 13, 203, 208, 6, 140, 177, 69, 9, 64, 209, 37, 18, 119, + 2, 140, 126, 188, 181, 176, 13, 139, 71, 101, 58, 199, 34, 200, + 4, 143, 222, 180, 112, 190, 28, 157, 228, 78, 33, 138, 157, 28, + 15, 160, 87, 244, 228, 1, 121, 114, 50, 120, 177, 228, 125, 163, + 250, 141, 166, 29, 124, 59, 22, 169, 17, 108, 24, 75, 55, 239, + 89, 99, 24, 213, 24, 192, 107, 59, 144, 150, 86, 6, 24, 186, + 223, 11, 67, 166, 175, 55, 114, 135, 105, 104, 131, 116, 219, 105, + 42, 181, 115, 48, 49, 74, 170, 74, 247, 91, 63, 16, 152, 189, + 20, 72, 81, 136, 164, 153, 122, 245, 28, 33, 236, 203, 196, 242, + 174, 70, 207, 48, 139, 70, 123, 118, 31, 217, 69, 205, 103, 186, + 230, 131, 113, 67, 38, 138, 140, 99, 118, 90, 245, 53, 3, 101, + 67, 231, 199, 109, 74, 217, 211, 171, 39, 186, 185, 178, 69, 133, + 170, 95, 119, 152, 250, 229, 196, 38, 39, 12, 56, 203, 156, 210, + 210, 116, 215, 38, 227, 55, 115, 174, 179, 26, 32, 79, 1, 121, + 37, 243, 251, 246, 198, 50, 30, 11, 209, 154, 62, 233, 100, 141, + 87, 129, 107, 252, 52, 36, 130, 127, 153, 194, 88, 196, 38, 165, + 101, 213, 251, 97, 111, 209, 105, 13, 186, 53, 190, 16, 164, 248, + 214, 1, 42, 163, 111, 103, 245, 111, 202, 75, 75, 121, 47, 29, + 188, 247, 117, 214, 186, 125, 156, 41, 48, 10, 194, 153, 76, 197, + 83, 218, 184, 128, 150, 167, 229, 89, 229, 202, 129, 162, 198, 2, + 25, 3, 237, 170, 108, 196, 115, 178, 48, 152, 194, 0, 109, 115, + 145, 136, 175, 122, 174, 197, 227, 190, 51, 127, 106, 87, 184, 180, + 103, 156, 71, 251, 198, 4, 214, 134, 90, 133, 35, 194, 108, 24, + 95, 105, 34, 52, 244, 12, 206, 118, 151, 210, 174, 221, 165, 174, + 150, 7, 37, 96, 186, 12, 9, 6, 207, 21, 59, 51, 65, 32, + 203, 192, 136, 251, 32, 85, 156, 110, 149, 20, 92, 233, 96, 42, + 143, 22, 139, 108, 216, 189, 4, 162, 177, 57, 250, 113, 105, 125, + 76, 222, 30, 166, 109, 80, 205, 64, 18, 115, 122, 165, 206, 235, + 230, 225, 159, 252, 80, 230, 20, 32, 96, 245, 193, 20, 240, 160, + 239, 32, 107, 200, 236, 0, 62, 53, 239, 167, 227, 188, 46, 17, + 170, 105, 108, 235, 132, 138, 72, 25, 88, 190, 83, 103, 218, 168, + 166, 237, 135, 139, 121, 127, 11, 134, 5, 31, 115, 0, 194, 16, + 224, 36, 131, 57, 232, 22, 145, 95, 232, 44, 183, 125, 183, 129, + 88, 215, 202, 238, 211, 19, 170, 107, 94, 113, 175, 220, 231, 44, + 142, 2, 142, 233, 13, 89, 214, 75, 249, 182, 139, 130, 193, 228, + 60, 182, 112, 33, 224, 87, 101, 12, 0, 28, 24, 53, 204, 162, + 38, 173, 246, 251, 50, 99, 201, 182, 23, 112, 128, 95, 252, 61, + 123, 49, 42, 93, 65, 75, 217, 183, 32, 205, 205, 102, 177, 209, + 84, 10, 157, 213, 255, 107, 14, 96, 40, 171, 100, 7, 110, 185, + 234, 141, 183, 9, 44, 125, 110, 230, 48, 144, 243, 47, 210, 86, + 213, 72, 159, 134, 168, 45, 36, 63, 133, 7, 132, 152, 160, 188, + 162, 146, 202, 107, 173, 125, 192, 246, 160, 60, 121, 21, 132, 131, + 0, 150, 37, 98, 146, 248, 52, 223, 87, 155, 100, 36, 105, 247, + 61, 164, 138, 171, 145, 253, 73, 14, 111, 74, 186, 87, 195, 161, + 239, 141, 38, 245, 214, 255, 88, 158, 16, 76, 108, 99, 55, 46, + 167, 204, 66, 202, 163, 132, 134, 211, 72, 190, 60, 199, 171, 132, + 93, 24, 16, 5, 14, 228, 175, 174, 147, 101, 20, 139, 235, 69, + 25, 131, 154, 180, 209, 126, 59, 159, 234, 232, 234, 15, 146, 228, + 68, 156, 183, 113, 46, 29, 122, 197, 211, 73, 65, 76, 102, 91, + 8, 151, 41, 194, 74, 211, 115, 76, 35, 58, 35, 189, 131, 35, + 133, 60, 241, 154, 241, 189, 69, 45, 242, 236, 217, 174, 31, 181, + 23, 239, 129, 7, 166, 181, 198, 106, 131, 1, 33, 127, 30, 44, + 129, 213, 219, 92, 59, 74, 5, 245, 255, 33, 184, 78, 29, 207, + 117, 252, 190, 102, 30, 108, 19, 131, 193, 243, 151, 93, 67, 210, + 183, 178, 21, 228, 113, 10, 42, 66, 245, 30, 116, 50, 185, 77, + 10, 168, 207, 123, 49, 14, 85, 206, 96, 119, 61, 21, 29, 103, + 139, 154, 4, 195, 182, 201, 168, 239, 224, 174, 59, 40, 119, 50, + 167, 69, 3, 226, 52, 118, 242, 3, 99, 119, 138, 24, 69, 96, + 68, 245, 203, 156, 178, 51, 39, 29, 141, 198, 36, 182, 31, 96, + 244, 238, 235, 55, 228, 216, 210, 19, 193, 221, 193, 82, 76, 22, + 79, 42, 108, 66, 159, 181, 154, 182, 92, 48, 5, 55, 228, 246, + 248, 110, 7, 248, 82, 167, 29, 78, 94, 130, 147, 174, 37, 219, + 111, 136, 76, 47, 167, 230, 217, 176, 186, 13, 11, 189, 120, 236, + 154, 85, 222, 2, 12, 31, 144, 224, 97, 49, 161, 183, 102, 26, + 153, 227, 202, 189, 172, 114, 101, 195, 140, 194, 60, 6, 82, 252, + 2, 155, 119, 76, 87, 60, 183, 139, 132, 100, 90, 234, 39, 142, + 253, 213, 53, 161, 8, 107, 133, 64, 100, 73, 162, 98, 219, 8, + 36, 35, 212, 26, 44, 226, 177, 214, 91, 60, 41, 99, 71, 195, + 245, 147, 233, 0, 132, 123, 106, 64, 162, 64, 248, 7, 24, 148, + 20, 33, 162, 253, 155, 196, 18, 107, 239, 216, 145, 131, 79, 150, + 218, 154, 26, 243, 141, 134, 182, 19, 190, 28, 119, 39, 19, 206, + 141, 24, 42, 113, 146, 130, 132, 244, 219, 10, 52, 75, 69, 52, + 20, 1, 225, 112, 61, 124, 82, 236, 217, 239, 65, 47, 163, 140, + 223, 205, 184, 12, 34, 156, 34, 200, 50, 101, 5, 252, 78, 247, + 187, 80, 216, 4, 149, 152, 240, 76, 79, 5, 186, 163, 94, 225, + 151, 180, 228, 141, 109, 176, 154, 237, 34, 186, 203, 26, 45, 203, + 190, 160, 136, 154, 241, 85, 18, 36, 154, 239, 138, 222, 159, 86, + 226, 152, 168, 58, 60, 198, 194, 119, 90, 3, 23, 123, 147, 61, + 236, 138, 127, 156, 183, 203, 173, 126, 244, 238, 106, 237, 6, 197, + 186, 240, 84, 68, 50, 183, 20, 61, 22, 223, 223, 113, 96, 234, + 79, 228, 78, 61, 111, 255, 36, 92, 179, 124, 133, 212, 17, 44, + 154, 138, 250, 73, 16, 173, 166, 183, 8, 75, 192, 20, 83, 199, + 137, 49, 73, 176, 207, 220, 100, 217, 115, 45, 188, 91, 197, 45, + 134, 120, 169, 230, 28, 164, 93, 85, 126, 80, 141, 122, 83, 235, + 221, 141, 211, 90, 254, 99, 7, 103, 89, 48, 187, 78, 118, 144, + 212, 200, 188, 155, 180, 106, 43, 32, 26, 33, 179, 172, 93, 121, + 130, 6, 67, 97, 45, 45, 53, 158, 206, 226, 244, 159, 237, 163, + 194, 215, 97, 189, 199, 198, 51, 186, 133, 56, 123, 229, 88, 226, + 148, 79, 51, 107, 230, 67, 140, 212, 173, 209, 90, 173, 21, 118, + 174, 242, 205, 90, 172, 139, 109, 198, 28, 8, 139, 161, 21, 26, + 91, 33, 71, 251, 249, 8, 174, 7, 135, 89, 155, 47, 130, 173, + 133, 230, 42, 75, 144, 98, 115, 168, 15, 57, 209, 12, 120, 102, + 85, 214, 230, 187, 224, 122, 128, 86, 197, 178, 65, 35, 173, 100, + 2, 65, 149, 101, 165, 115, 99, 163, 85, 107, 17, 15, 151, 101, + 117, 31, 27, 118, 67, 65, 147, 59, 96, 101, 26, 128, 13, 241, + 130, 225, 156, 59, 242, 134, 46, 125, 160, 130, 150, 167, 184, 39, + 66, 51, 34, 160, 187, 176, 158, 167, 120, 82, 224, 24, 81, 196, + 126, 222, 115, 127, 18, 202, 7, 32, 83, 91, 207, 99, 189, 163, + 74, 35, 190, 226, 60, 103, 12, 147, 145, 21, 142, 31, 180, 250, + 221, 28, 87, 225, 152, 89, 98, 121, 21, 38, 255, 35, 204, 78, + 90, 165, 2, 15, 69, 82, 94, 115, 22, 177, 101, 165, 47, 114, + 163, 64, 12, 11, 225, 0, 158, 100, 165, 155, 212, 9, 65, 42, + 105, 110, 142, 125, 238, 107, 95, 243, 205, 90, 174, 102, 101, 116, + 113, 159, 241, 143, 22, 53, 21, 21, 88, 61, 156, 85, 227, 165, + 189, 254, 179, 104, 251, 73, 222, 64, 123, 172, 31, 215, 143, 151, + 179, 201, 163, 169, 55, 104, 108, 253, 216, 195, 175, 22, 47, 206, + 1, 103, 223, 45, 58, 160, 97, 170, 174, 156, 252, 220, 154, 239, + 178, 120, 42, 177, 49, 242, 159, 6, 171, 67, 179, 111, 158, 45, + 109, 136, 189, 98, 33, 71, 26, 8, 103, 164, 22, 16, 89, 59, + 241, 4, 187, 60, 90, 118, 102, 16, 221, 17, 174, 166, 61, 247, + 0, 228, 12, 46, 156, 127, 246, 133, 206, 209, 13, 24, 243, 178, + 167, 111, 2, 203, 128, 53, 113, 112, 245, 33, 152, 101, 146, 195, + 169, 201, 246, 165, 69, 142, 136, 154, 90, 30, 175, 12, 174, 191, + 222, 167, 188, 218, 149, 117, 141, 174, 107, 218, 65, 198, 112, 158, + 72, 113, 217, 176, 231, 114, 119, 226, 226, 162, 6, 130, 63, 246, + 143, 5, 212, 211, 56, 16, 3, 155, 46, 45, 45, 232, 239, 106, + 120, 229, 147, 215, 88, 32, 171, 98, 250, 130, 32, 163, 222, 35, + 207, 227, 229, 3, 197, 221, 250, 211, 32, 20, 181, 215, 136, 203, + 61, 149, 168, 206, 97, 245, 56, 133, 126, 239, 23, 152, 96, 95, + 38, 5, 182, 99, 168, 18, 245, 174, 153, 225, 220, 52, 72, 117, + 199, 181, 6, 128, 51, 43, 37, 11, 141, 219, 157, 78, 104, 89, + 141, 207, 29, 103, 5, 220, 84, 51, 18, 180, 147, 244, 87, 250, + 41, 77, 125, 187, 196, 166, 84, 85, 25, 138, 102, 120, 146, 232, + 133, 123, 227, 158, 60, 61, 106, 61, 109, 243, 10, 175, 103, 236, + 150, 190, 3, 27, 10, 248, 181, 116, 88, 181, 143, 103, 247, 182, + 239, 36, 29, 99, 26, 221, 238, 243, 154, 243, 60, 206, 205, 233, + 193, 128, 215, 66, 241, 64, 158, 172, 202, 223, 148, 185, 93, 29, + 77, 49, 17, 15, 188, 245, 17, 50, 243, 136, 168, 123, 177, 67, + 86, 55, 143, 229, 202, 168, 117, 142, 180, 207, 30, 249, 253, 125, + 26, 173, 22, 210, 65, 192, 93, 93, 218, 245, 8, 250, 85, 65, + 57, 32, 198, 237, 4, 146, 41, 230, 4, 229, 12, 207, 55, 38, + 81, 72, 96, 194, 91, 144, 48, 255, 225, 59, 68, 198, 197, 176, + 73, 178, 205, 146, 149, 62, 140, 197, 87, 85, 217, 193, 21, 117, + 54, 13, 179, 99, 235, 218, 32, 39, 202, 65, 218, 60, 229, 91, + 71, 19, 42, 167, 184, 143, 223, 183, 18, 114, 17, 253, 218, 178, + 232, 251, 37, 77, 203, 118, 32, 189, 180, 20, 200, 1, 78, 109, + 22, 106, 245, 172, 150, 251, 116, 173, 7, 15, 196, 139, 209, 197, + 133, 241, 213, 61, 198, 97, 208, 32, 240, 248, 148, 161, 249, 23, + 9, 81, 163, 121, 22, 48, 160, 253, 53, 175, 209, 61, 146, 205, + 126, 191, 191, 5, 81, 24, 164, 236, 237, 126, 212, 22, 123, 121, + 66, 238, 109, 134, 13, 46, 157, 168, 195, 222, 103, 51, 75, 2, + 190, 151, 38, 14, 217, 205, 169, 91, 219, 199, 240, 135, 232, 155, + 152, 180, 12, 243, 118, 248, 170, 51, 238, 115, 221, 152, 110, 176, + 164, 11, 95, 104, 47, 45, 43, 149, 45, 207, 249, 255, 7, 179, + 3, 75, 88, 94, 25, 230, 72, 224, 170, 21, 159, 83, 48, 178, + 60, 64, 233, 118, 197, 204, 167, 96, 107, 224, 174, 3, 60, 198, + 211, 91, 134, 251, 26, 67, 104, 96, 61, 104, 125, 248, 92, 235, + 88, 27, 111, 149, 119, 123, 6, 64, 70, 58, 176, 48, 251, 220, + 38, 219, 13, 176, 166, 91, 119, 255, 200, 102, 113, 164, 19, 67, + 214, 29, 198, 178, 253, 145, 120, 82, 177, 25, 180, 43, 24, 98, + 241, 236, 180, 209, 182, 92, 8, 159, 104, 225, 183, 62, 154, 51, + 155, 163, 239, 19, 113, 90, 160, 233, 106, 157, 167, 59, 179, 73, + 155, 214, 100, 230, 197, 108, 232, 161, 129, 36, 32, 80, 133, 12, + 133, 155, 158, 59, 26, 178, 31, 171, 49, 246, 245, 27, 219, 82, + 141, 252, 113, 27, 142, 29, 161, 67, 67, 68, 246, 7, 25, 26, + 96, 215, 74, 181, 83, 127, 219, 5, 198, 60, 37, 173, 157, 95, + 110, 168, 151, 81, 81, 167, 61, 113, 42, 92, 152, 62, 108, 90, + 227, 229, 186, 82, 99, 184, 165, 220, 215, 142, 235, 198, 167, 205, + 209, 62, 253, 15, 103, 102, 69, 206, 77, 61, 111, 19, 157, 103, + 117, 82, 167, 87, 117, 134, 245, 255, 164, 41, 143, 27, 119, 134, + 217, 197, 59, 119, 219, 42, 191, 17, 98, 63, 251, 92, 75, 84, + 21, 175, 184, 208, 200, 31, 63, 186, 105, 65, 118, 34, 173, 0, + 6, 202, 213, 213, 45, 216, 239, 123, 32, 133, 90, 107, 250, 115, + 25, 230, 103, 21, 182, 123, 45, 135, 178, 108, 207, 198, 51, 179, + 147, 249, 126, 9, 172, 74, 229, 15, 48, 182, 227, 232, 9, 169, + 107, 100, 127, 3, 54, 135, 111, 156, 20, 158, 153, 187, 77, 196, + 213, 45, 232, 128, 128, 48, 132, 175, 204, 84, 138, 161, 67, 218, + 224, 58, 201, 63, 188, 101, 182, 153, 21, 215, 64, 184, 112, 132, + 161, 164, 178, 99, 97, 216, 214, 73, 60, 202, 100, 196, 225, 246, + 198, 35, 55, 204, 174, 227, 251, 106, 255, 130, 135, 101, 213, 102, + 131, 111, 98, 123, 49, 187, 100, 21, 73, 6, 163, 1, 1, 204, + 195, 22, 180, 232, 216, 165, 152, 193, 221, 71, 187, 228, 69, 51, + 135, 5, 8, 117, 201, 227, 1, 199, 94, 246, 126, 21, 220, 74, + 9, 229, 102, 203, 152, 82, 57, 136, 73, 26, 27, 229, 80, 164, + 238, 146, 40, 229, 53, 99, 82, 167, 140, 52, 254, 243, 114, 18, + 131, 31, 85, 247, 143, 75, 166, 28, 94, 119, 147, 19, 163, 157, + 167, 117, 166, 228, 253, 227, 111, 117, 68, 221, 33, 156, 106, 179, + 8, 13, 88, 88, 155, 147, 51, 143, 160, 48, 12, 218, 188, 136, + 255, 10, 17, 31, 54, 129, 202, 106, 245, 201, 87, 120, 214, 31, + 89, 112, 51, 30, 139, 169, 237, 72, 7, 113, 95, 155, 71, 45, + 219, 5, 246, 109, 126, 177, 71, 185, 72, 145, 254, 167, 105, 49, + 245, 77, 82, 39, 21, 166, 185, 109, 102, 234, 16, 70, 207, 248, + 166, 177, 205, 157, 180, 59, 142, 231, 130, 66, 2, 44, 114, 165, + 252, 17, 78, 147, 19, 7, 233, 160, 56, 206, 239, 107, 195, 196, + 80, 131, 140, 241, 73, 40, 134, 120, 143, 155, 223, 45, 61, 87, + 90, 120, 223, 138, 55, 207, 254, 245, 0, 141, 169, 222, 121, 190, + 51, 94, 131, 145, 74, 233, 133, 111, 174, 22, 62, 173, 201, 31, + 222, 142, 147, 37, 103, 121, 35, 240, 221, 34, 166, 222, 120, 79, + 202, 112, 0, 201, 186, 96, 121, 80, 36, 213, 21, 93, 40, 183, + 134, 219, 139, 185, 57, 179, 246, 215, 120, 76, 126, 125, 22, 209, + 90, 173, 192, 168, 109, 150, 69, 181, 66, 216, 176, 216, 174, 135, + 241, 82, 75, 196, 181, 124, 155, 48, 156, 232, 76, 106, 119, 81, + 247, 7, 13, 118, 234, 24, 140, 194, 14, 216, 119, 167, 185, 226, + 7, 118, 231, 67, 221, 227, 50, 20, 29, 235, 233, 165, 53, 205, + 234, 177, 14, 138, 251, 50, 28, 161, 212, 108, 158, 230, 107, 193, + 110, 144, 158, 79, 155, 177, 147, 127, 5, 236, 66, 248, 105, 240, + 216, 11, 96, 253, 80, 149, 13, 175, 198, 188, 123, 92, 116, 252, + 50, 166, 5, 190, 227, 60, 4, 90, 120, 192, 69, 50, 73, 135, + 111, 115, 240, 72, 208, 122, 65, 89, 182, 87, 242, 108, 76, 202, + 176, 145, 239, 156, 82, 135, 205, 47, 104, 239, 73, 131, 197, 146, + 133, 226, 125, 131, 218, 55, 101, 152, 234, 83, 120, 211, 210, 31, + 164, 51, 178, 49, 28, 184, 120, 90, 43, 155, 85, 213, 174, 199, + 79, 174, 47, 135, 152, 119, 209, 255, 117, 106, 53, 243, 45, 194, + 138, 121, 57, 102, 253, 239, 64, 129, 128, 180, 80, 56, 12, 102, + 220, 149, 42, 48, 61, 233, 128, 70, 96, 228, 6, 114, 154, 255, + 160, 72, 26, 4, 50, 105, 54, 200, 14, 241, 213, 26, 252, 12, + 250, 71, 234, 105, 50, 60, 7, 47, 72, 203, 31, 142, 105, 22, + 23, 2, 181, 88, 154, 193, 218, 18, 153, 249, 106, 240, 178, 42, + 230, 7, 94, 1, 251, 147, 117, 107, 183, 3, 109, 199, 224, 68, + 245, 6, 179, 155, 105, 190, 158, 127, 164, 77, 147, 225, 129, 41, + 114, 121, 12, 225, 20, 96, 134, 25, 163, 211, 100, 123, 207, 194, + 98, 113, 49, 14, 38, 116, 93, 174, 171, 31, 157, 13, 170, 109, + 156, 55, 151, 65, 38, 113, 60, 243, 46, 178, 16, 66, 27, 250, + 149, 114, 132, 229, 20, 245, 148, 142, 52, 253, 19, 60, 69, 217, + 223, 100, 115, 200, 75, 97, 145, 173, 150, 237, 145, 56, 17, 220, + 61, 3, 132, 92, 243, 19, 175, 222, 130, 86, 0, 218, 205, 96, + 81, 81, 240, 179, 39, 86, 20, 46, 207, 54, 248, 225, 230, 4, + 160, 250, 179, 240, 200, 134, 18, 49, 231, 61, 95, 189, 174, 186, + 144, 183, 75, 170, 225, 175, 135, 216, 43, 134, 151, 235, 55, 138, + 185, 87, 169, 51, 88, 62, 93, 13, 148, 84, 138, 68, 244, 226, + 245, 152, 0, 124, 158, 233, 197, 18, 232, 192, 104, 238, 139, 193, + 107, 12, 28, 31, 29, 104, 219, 73, 142, 129, 222, 213, 209, 35, + 129, 177, 78, 26, 50, 146, 142, 82, 15, 101, 128, 94, 85, 224, + 255, 69, 57, 119, 35, 110, 56, 208, 119, 127, 27, 203, 99, 137, + 221, 137, 131, 227, 158, 65, 253, 173, 226, 10, 67, 168, 149, 163, + 193, 170, 151, 14, 201, 192, 43, 24, 234, 218, 87, 45, 233, 61, + 43, 103, 89, 162, 145, 153, 239, 218, 140, 147, 82, 205, 53, 147, + 131, 111, 213, 142, 4, 174, 165, 41, 180, 149, 121, 125, 23, 58, + 237, 177, 117, 90, 211, 25, 10, 51, 247, 182, 129, 249, 108, 63, + 230, 209, 0, 10, 190, 84, 80, 16, 32, 164, 203, 172, 245, 210, + 214, 197, 93, 76, 147, 120, 65, 178, 181, 1, 54, 59, 11, 14, + 223, 68, 105, 221, 156, 121, 197, 178, 64, 156, 251, 56, 250, 52, + 46, 0, 136, 42, 202, 206, 23, 96, 103, 232, 116, 194, 116, 85, + 115, 43, 146, 44, 115, 179, 138, 42, 44, 165, 123, 117, 196, 52, + 140, 86, 164, 221, 202, 91, 105, 14, 242, 240, 10, 193, 32, 192, + 0, 141, 77, 156, 39, 103, 192, 180, 45, 207, 157, 50, 226, 92, + 215, 9, 210, 87, 36, 168, 181, 171, 122, 74, 165, 133, 176, 185, + 70, 247, 37, 181, 77, 186, 201, 26, 134, 45, 0, 221, 245, 43, + 202, 153, 72, 39, 134, 179, 229, 162, 109, 38, 110, 24, 170, 38, + 202, 24, 112, 78, 245, 229, 61, 231, 102, 245, 128, 96, 251, 181, + 107, 196, 48, 156, 113, 223, 102, 151, 130, 254, 39, 164, 201, 154, + 98, 141, 39, 95, 186, 25, 6, 229, 242, 14, 211, 53, 185, 87, + 73, 43, 233, 236, 141, 229, 201, 187, 131, 16, 237, 91, 224, 73, + 91, 93, 161, 134, 255, 245, 146, 198, 217, 124, 204, 0, 26, 141, + 86, 38, 214, 245, 159, 220, 228, 22, 195, 2, 238, 112, 133, 245, + 160, 239, 125, 120, 26, 115, 225, 215, 226, 176, 219, 250, 235, 169, + 185, 87, 112, 135, 184, 224, 184, 36, 200, 208, 109, 5, 196, 99, + 190, 143, 76, 51, 134, 163, 135, 19, 128, 163, 56, 132, 88, 238, + 60, 248, 115, 115, 138, 124, 109, 132, 69, 252, 68, 208, 149, 138, + 151, 1, 237, 46, 26, 25, 194, 168, 164, 143, 164, 11, 70, 61, + 251, 207, 102, 147, 41, 144, 39, 92, 131, 160, 220, 145, 193, 37, + 12, 46, 118, 200, 76, 205, 227, 60, 224, 55, 11, 49, 24, 22, + 244, 229, 161, 48, 4, 195, 204, 170, 105, 69, 66, 204, 185, 62, + 8, 46, 122, 55, 146, 252, 48, 154, 45, 163, 77, 187, 58, 225, + 180, 125, 81, 156, 66, 67, 86, 134, 180, 209, 186, 19, 134, 12, + 255, 62, 133, 138, 219, 77, 48, 39, 207, 27, 255, 16, 33, 112, + 221, 188, 188, 88, 100, 136, 31, 94, 166, 11, 246, 219, 251, 250, + 111, 71, 181, 37, 235, 87, 33, 65, 19, 223, 199, 90, 67, 228, + 182, 95, 97, 61, 9, 76, 185, 215, 110, 176, 136, 184, 247, 221, + 99, 64, 158, 207, 88, 102, 147, 103, 43, 155, 145, 193, 232, 27, + 15, 141, 6, 248, 237, 108, 129, 98, 251, 160, 128, 54, 107, 120, + 121, 63, 102, 30, 143, 51, 152, 232, 210, 16, 132, 241, 179, 198, + 126, 70, 174, 75, 248, 196, 20, 54, 131, 76, 225, 118, 117, 47, + 101, 116, 218, 255, 18, 88, 137, 222, 168, 136, 191, 219, 10, 47, + 50, 34, 5, 194, 201, 88, 255, 118, 91, 45, 72, 72, 115, 59, + 92, 136, 160, 17, 124, 244, 189, 201, 69, 58, 251, 162, 198, 7, + 72, 130, 185, 91, 144, 85, 198, 35, 160, 189, 191, 192, 220, 134, + 136, 204, 189, 41, 146, 171, 150, 115, 249, 214, 14, 161, 108, 213, + 204, 241, 162, 220, 94, 125, 35, 66, 111, 61, 204, 69, 194, 123, + 76, 121, 59, 202, 17, 94, 41, 128, 224, 106, 15, 162, 134, 129, + 30, 188, 166, 62, 138, 89, 139, 177, 47, 42, 92, 54, 184, 180, + 252, 84, 79, 159, 53, 157, 202, 156, 157, 168, 238, 50, 158, 188, + 69, 81, 60, 192, 85, 119, 218, 33, 10, 228, 2, 241, 12, 248, + 34, 84, 70, 99, 194, 89, 67, 173, 243, 124, 224, 1, 185, 234, + 189, 3, 124, 207, 85, 76, 199, 109, 104, 55, 25, 84, 32, 224, + 16, 5, 167, 112, 144, 216, 109, 223, 187, 19, 250, 245, 166, 195, + 145, 12, 232, 5, 96, 162, 198, 255, 134, 53, 133, 63, 58, 0, + 80, 104, 234, 254, 164, 191, 40, 18, 219, 18, 164, 0, 247, 71, + 230, 177, 211, 219, 81, 242, 122, 123, 192, 69, 142, 214, 122, 107, + 164, 185, 159, 112, 175, 19, 52, 5, 59, 239, 67, 197, 115, 169, + 239, 138, 88, 176, 103, 212, 223, 230, 197, 159, 101, 195, 58, 100, + 40, 186, 82, 130, 172, 109, 188, 19, 16, 186, 160, 252, 211, 95, + 239, 223, 14, 76, 64, 128, 9, 147, 171, 139, 168, 164, 183, 153, + 12, 110, 63, 183, 229, 183, 125, 91, 56, 59, 240, 179, 67, 119, + 156, 96, 170, 239, 186, 11, 143, 200, 148, 226, 150, 99, 22, 175, + 46, 168, 197, 117, 253, 106, 196, 239, 50, 147, 173, 44, 214, 61, + 154, 75, 244, 9, 66, 100, 235, 20, 210, 11, 54, 101, 106, 62, + 178, 73, 75, 70, 97, 126, 112, 181, 231, 85, 237, 202, 170, 54, + 89, 76, 91, 108, 8, 120, 16, 154, 133, 145, 97, 38, 5, 195, + 60, 54, 101, 200, 14, 243, 230, 120, 157, 11, 175, 18, 191, 182, + 187, 122, 138, 194, 251, 113, 12, 74, 29, 138, 154, 10, 169, 91, + 15, 238, 211, 39, 200, 91, 86, 109, 90, 95, 3, 97, 21, 56, + 82, 118, 105, 30, 39, 172, 15, 133, 233, 179, 22, 127, 13, 200, + 6, 67, 149, 218, 230, 84, 131, 25, 215, 111, 114, 207, 131, 219, + 15, 166, 82, 68, 61, 164, 69, 218, 84, 226, 0, 69, 173, 242, + 73, 25, 113, 119, 186, 112, 79, 33, 7, 7, 56, 252, 95, 80, + 71, 120, 90, 130, 103, 192, 112, 151, 141, 8, 74, 123, 223, 6, + 129, 224, 195, 79, 104, 201, 5, 170, 163, 204, 153, 253, 224, 253, + 106, 143, 214, 166, 223, 6, 241, 232, 232, 120, 54, 37, 53, 216, + 154, 127, 133, 76, 117, 42, 184, 229, 71, 156, 252, 59, 34, 89, + 222, 28, 210, 233, 203, 98, 170, 234, 240, 145, 200, 161, 26, 190, + 77, 3, 63, 216, 70, 238, 24, 93, 113, 171, 19, 58, 101, 189, + 246, 83, 187, 226, 180, 111, 72, 52, 141, 206, 243, 131, 41, 147, + 117, 246, 3, 132, 24, 160, 72, 35, 214, 202, 192, 174, 249, 215, + 80, 21, 230, 79, 247, 22, 190, 46, 253, 126, 56, 168, 15, 13, + 224, 209, 166, 56, 93, 229, 134, 214, 95, 203, 103, 148, 218, 216, + 199, 130, 19, 150, 206, 24, 1, 81, 40, 5, 71, 243, 189, 127, + 21, 95, 235, 93, 50, 54, 32, 134, 228, 18, 170, 203, 198, 49, + 217, 206, 108, 97, 54, 120, 187, 161, 44, 224, 136, 131, 177, 99, + 194, 198, 161, 209, 140, 108, 110, 217, 171, 250, 78, 59, 229, 223, + 61, 183, 62, 187, 170, 17, 140, 253, 116, 165, 78, 55, 216, 107, + 120, 212, 193, 165, 253, 170, 177, 68, 7, 50, 175, 127, 55, 185, + 183, 193, 137, 12, 60, 75, 105, 173, 92, 80, 151, 158, 69, 23, + 34, 255, 218, 48, 165, 53, 108, 38, 1, 169, 218, 56, 112, 143, + 38, 239, 175, 141, 110, 54, 31, 142, 80, 138, 180, 58, 127, 87, + 67, 79, 37, 244, 95, 139, 65, 36, 35, 92, 197, 104, 15, 144, + 172, 92, 81, 88, 131, 154, 88, 251, 53, 50, 66, 233, 163, 203, + 8, 129, 79, 162, 202, 143, 42, 7, 72, 47, 44, 19, 122, 126, + 252, 248, 40, 162, 207, 139, 200, 253, 125, 110, 6, 176, 126, 138, + 253, 185, 198, 229, 204, 100, 58, 66, 92, 252, 108, 233, 217, 33, + 178, 174, 129, 210, 0, 85, 69, 242, 197, 218, 25, 212, 231, 58, + 209, 148, 172, 239, 1, 76, 167, 196, 116, 46, 9, 87, 30, 254, + 26, 237, 68, 93, 34, 158, 65, 193, 111, 119, 95, 74, 86, 130, + 36, 48, 151, 51, 211, 151, 72, 43, 233, 170, 248, 87, 131, 30, + 217, 241, 30, 63, 118, 37, 157, 48, 108, 117, 166, 126, 27, 174, + 228, 186, 86, 97, 195, 72, 174, 19, 36, 0, 138, 150, 58, 134, + 208, 55, 204, 89, 150, 63, 210, 77, 206, 78, 11, 224, 140, 33, + 91, 19, 188, 110, 78, 28, 99, 185, 60, 235, 201, 73, 219, 205, + 90, 127, 35, 140, 176, 254, 231, 192, 147, 173, 20, 5, 9, 15, + 255, 30, 7, 162, 153, 18, 170, 194, 120, 48, 104, 46, 222, 118, + 118, 158, 187, 108, 161, 123, 100, 165, 11, 30, 35, 23, 19, 219, + 76, 255, 47, 12, 165, 246, 98, 0, 0, 2, 98, 27, 136, 185, + 207, 236, 218, 51, 110, 98, 139, 50, 108, 87, 23, 195, 105, 27, + 190, 111, 68, 38, 239, 146, 94, 55, 77, 10, 123, 115, 217, 2, + 114, 223, 102, 252, 56, 34, 251, 153, 130, 188, 163, 120, 221, 248, + 20, 237, 215, 78, 179, 232, 7, 166, 234, 227, 26, 235, 174, 109, + 174, 100, 172, 232, 21, 211, 53, 7, 124, 8, 110, 247, 46, 64, + 46, 53, 27, 211, 216, 55, 112, 212, 229, 44, 124, 111, 83, 143, + 140, 154, 216, 6, 109, 245, 70, 102, 172, 94, 199, 198, 216, 82, + 142, 102, 211, 51, 190, 138, 66, 179, 55, 47, 42, 145, 177, 169, + 117, 185, 164, 202, 26, 247, 135, 206, 136, 196, 182, 172, 69, 224, + 103, 82, 54, 111, 224, 62, 106, 123, 99, 199, 254, 182, 199, 245, + 95, 165, 18, 175, 37, 32, 218, 2, 245, 171, 35, 228, 231, 58, + 96, 28, 149, 197, 249, 21, 119, 50, 155, 3, 213, 35, 79, 161, + 65, 105, 227, 0, 27, 140, 136, 189, 30, 113, 250, 149, 140, 70, + 31, 127, 152, 234, 187, 121, 218, 28, 62, 13, 106, 210, 221, 88, + 36, 237, 202, 47, 142, 85, 30, 121, 194, 183, 196, 251, 24, 226, + 0, 86, 114, 47, 74, 78, 63, 249, 170, 32, 254, 166, 31, 101, + 170, 201, 91, 158, 50, 187, 106, 113, 44, 243, 244, 41, 173, 7, + 104, 133, 30, 20, 134, 41, 26, 80, 72, 195, 56, 141, 230, 169, + 34, 125, 66, 164, 186, 192, 234, 72, 5, 151, 55, 233, 127, 192, + 77, 1, 77, 74, 44, 172, 118, 241, 192, 44, 127, 7, 17, 207, + 200, 75, 177, 97, 13, 93, 199, 156, 199, 99, 187, 173, 70, 42, + 134, 9, 3, 185, 102, 168, 240, 116, 196, 173, 122, 59, 231, 142, + 190, 103, 43, 156, 126, 68, 47, 212, 76, 95, 181, 70, 220, 89, + 133, 197, 193, 229, 222, 166, 2, 21, 94, 213, 170, 180, 35, 11, + 145, 11, 173, 87, 110, 199, 98, 159, 102, 165, 144, 40, 109, 9, + 29, 249, 136, 88, 47, 56, 204, 239, 237, 164, 206, 231, 29, 187, + 41, 254, 135, 72, 137, 232, 56, 108, 80, 148, 220, 235, 15, 50, + 156, 161, 184, 6, 92, 141, 123, 203, 43, 115, 91, 32, 18, 92, + 84, 179, 143, 64, 25, 59, 149, 77, 78, 59, 45, 192, 184, 12, + 194, 7, 57, 112, 70, 132, 173, 170, 75, 189, 213, 75, 241, 36, + 211, 220, 237, 23, 181, 37, 215, 164, 59, 56, 124, 216, 114, 49, + 113, 117, 229, 101, 189, 162, 92, 46, 1, 231, 103, 15, 208, 67, + 127, 34, 39, 23, 186, 130, 106, 230, 148, 103, 27, 61, 22, 210, + 162, 102, 182, 46, 63, 206, 165, 43, 165, 160, 179, 144, 80, 36, + 9, 53, 99, 127, 63, 48, 194, 227, 172, 176, 138, 210, 213, 53, + 132, 145, 161, 119, 129, 32, 209, 39, 164, 219, 36, 88, 240, 165, + 212, 6, 56, 59, 202, 231, 148, 209, 50, 2, 74, 154, 143, 1, + 195, 181, 22, 158, 116, 108, 25, 164, 46, 160, 57, 120, 117, 50, + 123, 0, 104, 194, 122, 224, 130, 41, 108, 1, 46, 175, 85, 60, + 123, 217, 154, 198, 9, 165, 43, 213, 70, 7, 27, 95, 136, 31, + 246, 109, 230, 54, 4, 28, 47, 82, 53, 204, 221, 167, 242, 17, + 195, 50, 174, 192, 143, 180, 195, 177, 108, 180, 236, 228, 160, 181, + 153, 82, 69, 199, 41, 35, 156, 37, 111, 132, 156, 117, 74, 229, + 141, 50, 216, 124, 26, 98, 157, 87, 34, 228, 13, 60, 169, 151, + 126, 198, 95, 32, 175, 75, 249, 234, 249, 68, 221, 192, 183, 67, + 248, 145, 82, 8, 37, 110, 68, 126, 1, 96, 135, 3, 172, 194, + 82, 90, 164, 104, 114, 72, 139, 238, 107, 71, 158, 194, 226, 8, + 136, 166, 160, 187, 243, 47, 36, 82, 78, 203, 115, 6, 32, 161, + 55, 10, 118, 71, 123, 199, 4, 108, 44, 180, 84, 126, 145, 133, + 52, 74, 107, 132, 136, 251, 38, 161, 171, 3, 81, 120, 185, 254, + 102, 236, 115, 243, 79, 24, 237, 112, 153, 175, 21, 9, 232, 83, + 38, 31, 186, 63, 150, 127, 59, 169, 117, 234, 177, 94, 156, 41, + 195, 226, 82, 31, 200, 16, 70, 219, 229, 204, 148, 171, 178, 28, + 26, 223, 233, 212, 54, 112, 202, 194, 89, 36, 45, 149, 81, 96, + 123, 39, 213, 188, 238, 108, 17, 129, 0, 139, 41, 105, 13, 202, + 187, 164, 190, 123, 38, 194, 13, 14, 175, 175, 245, 181, 132, 253, + 19, 68, 173, 227, 88, 31, 55, 16, 40, 149, 219, 252, 70, 75, + 211, 123, 21, 60, 158, 119, 128, 73, 202, 1, 254, 112, 131, 178, + 126, 169, 13, 255, 169, 86, 217, 197, 118, 85, 186, 164, 40, 25, + 53, 3, 219, 40, 37, 43, 155, 246, 186, 134, 33, 38, 58, 76, + 18, 100, 58, 224, 7, 200, 82, 175, 174, 247, 5, 176, 57, 101, + 192, 159, 102, 77, 127, 53, 241, 182, 2, 252, 86, 59, 197, 214, + 71, 176, 26, 228, 39, 137, 146, 210, 113, 43, 228, 1, 66, 35, + 171, 255, 38, 152, 186, 174, 77, 39, 91, 57, 170, 223, 152, 9, + 245, 23, 12, 71, 194, 161, 205, 210, 25, 137, 94, 239, 225, 80, + 241, 45, 171, 248, 0, 89, 179, 71, 6, 169, 203, 204, 61, 184, + 46, 23, 11, 96, 52, 232, 75, 170, 134, 42, 211, 220, 45, 58, + 61, 205, 213, 159, 150, 41, 109, 195, 20, 227, 55, 4, 66, 53, + 191, 25, 153, 28, 116, 61, 26, 119, 169, 114, 163, 146, 4, 71, + 104, 18, 164, 121, 33, 178, 223, 39, 139, 46, 93, 77, 151, 167, + 137, 112, 32, 98, 253, 186, 53, 207, 27, 204, 140, 223, 233, 223, + 115, 255, 117, 90, 18, 37, 246, 16, 53, 63, 72, 94, 202, 33, + 197, 171, 63, 139, 142, 84, 38, 196, 182, 112, 171, 208, 183, 207, + 244, 15, 80, 39, 32, 162, 209, 113, 140, 196, 222, 28, 33, 134, + 164, 134, 79, 91, 141, 117, 255, 152, 114, 118, 59, 190, 187, 253, + 182, 103, 206, 6, 229, 134, 249, 242, 38, 19, 116, 72, 33, 4, + 186, 223, 159, 48, 63, 36, 185, 88, 118, 190, 67, 252, 162, 209, + 137, 139, 120, 110, 193, 49, 149, 80, 216, 54, 214, 249, 82, 88, + 77, 46, 56, 49, 9, 11, 85, 106, 95, 38, 213, 215, 190, 208, + 34, 130, 158, 70, 248, 187, 207, 3, 150, 222, 20, 216, 236, 97, + 155, 82, 165, 23, 183, 110, 212, 17, 129, 79, 80, 45, 158, 58, + 161, 169, 179, 208, 249, 85, 75, 118, 92, 133, 134, 209, 203, 8, + 49, 10, 156, 189, 63, 22, 45, 226, 47, 6, 143, 246, 194, 150, + 189, 68, 191, 238, 46, 194, 26, 246, 153, 102, 40, 214, 210, 252, + 150, 146, 206, 192, 212, 207, 43, 177, 103, 49, 238, 38, 14, 246, + 164, 25, 148, 37, 24, 102, 66, 157, 143, 186, 90, 223, 100, 47, + 198, 207, 159, 212, 42, 123, 36, 147, 97, 24, 218, 150, 176, 254, + 253, 189, 23, 193, 63, 254, 210, 98, 27, 240, 2, 6, 222, 153, + 237, 230, 244, 254, 168, 222, 58, 227, 217, 86, 188, 209, 79, 167, + 128, 233, 189, 48, 80, 22, 211, 161, 111, 184, 223, 136, 113, 197, + 244, 26, 246, 241, 56, 241, 16, 173, 243, 89, 207, 131, 111, 36, + 77, 151, 34, 240, 252, 150, 5, 163, 57, 28, 66, 238, 179, 174, + 10, 25, 226, 127, 240, 179, 92, 194, 213, 180, 69, 73, 198, 20, + 248, 39, 110, 218, 36, 220, 111, 193, 7, 215, 238, 141, 97, 38, + 12, 85, 115, 246, 119, 98, 72, 95, 251, 128, 160, 249, 86, 46, + 192, 2, 149, 206, 197, 19, 33, 251, 179, 63, 186, 232, 62, 191, + 51, 253, 32, 36, 173, 237, 45, 116, 27, 212, 137, 204, 35, 244, + 119, 200, 169, 52, 233, 10, 136, 218, 206, 108, 217, 252, 74, 211, + 19, 48, 235, 3, 160, 12, 135, 130, 107, 29, 182, 133, 48, 112, + 61, 145, 2, 158, 173, 241, 212, 16, 190, 206, 194, 58, 184, 253, + 23, 56, 132, 106, 115, 252, 17, 65, 35, 67, 212, 130, 190, 182, + 64, 164, 58, 59, 194, 8, 65, 20, 139, 235, 154, 136, 178, 83, + 29, 93, 229, 27, 237, 145, 97, 20, 208, 209, 82, 152, 45, 15, + 97, 142, 78, 24, 188, 237, 146, 75, 215, 248, 190, 234, 228, 253, + 202, 232, 63, 115, 157, 33, 69, 130, 123, 171, 18, 98, 119, 233, + 136, 242, 13, 41, 179, 224, 44, 126, 196, 10, 19, 236, 247, 12, + 36, 208, 1, 54, 244, 139, 29, 215, 174, 12, 164, 245, 137, 61, + 173, 9, 129, 47, 140, 174, 30, 54, 237, 185, 169, 0, 66, 187, + 227, 164, 194, 232, 128, 156, 168, 220, 102, 6, 187, 0, 88, 181, + 71, 49, 204, 46, 53, 220, 99, 47, 220, 129, 35, 98, 52, 37, + 82, 30, 5, 92, 177, 48, 215, 111, 223, 105, 205, 189, 68, 191, + 4, 100, 36, 178, 36, 81, 168, 128, 239, 188, 72, 127, 228, 201, + 16, 226, 169, 197, 220, 206, 248, 212, 128, 79, 93, 4, 107, 201, + 193, 87, 147, 109, 44, 12, 192, 154, 172, 179, 3, 227, 134, 209, + 15, 67, 207, 204, 119, 74, 197, 110, 170, 240, 137, 107, 74, 153, + 11, 29, 230, 142, 126, 171, 93, 156, 22, 5, 91, 111, 206, 48, + 121, 145, 94, 4, 33, 46, 219, 222, 153, 223, 238, 6, 47, 201, + 37, 208, 46, 38, 231, 158, 113, 4, 164, 81, 68, 154, 58, 212, + 105, 38, 127, 151, 51, 8, 184, 111, 1, 209, 170, 224, 19, 55, + 100, 197, 33, 234, 117, 52, 232, 63, 135, 82, 122, 108, 116, 95, + 7, 166, 141, 221, 182, 253, 30, 247, 53, 136, 246, 12, 110, 168, + 151, 121, 26, 230, 22, 61, 179, 215, 197, 102, 214, 137, 13, 34, + 84, 214, 241, 52, 134, 217, 6, 214, 100, 182, 129, 112, 179, 162, + 110, 65, 150, 96, 22, 138, 96, 172, 185, 254, 209, 94, 82, 82, + 104, 157, 163, 167, 247, 232, 84, 232, 230, 60, 123, 144, 61, 152, + 122, 53, 52, 132, 158, 81, 243, 110, 247, 122, 45, 98, 206, 71, + 24, 78, 174, 34, 153, 167, 218, 155, 16, 174, 213, 29, 216, 235, + 223, 101, 74, 206, 88, 203, 107, 195, 52, 203, 168, 210, 85, 156, + 133, 65, 200, 149, 198, 154, 146, 90, 66, 59, 5, 71, 6, 20, + 93, 209, 86, 125, 205, 246, 76, 242, 249, 139, 146, 136, 117, 232, + 49, 22, 183, 76, 129, 220, 220, 145, 12, 136, 234, 120, 151, 35, + 202, 181, 245, 133, 7, 40, 168, 248, 184, 162, 49, 145, 99, 193, + 81, 85, 89, 228, 181, 183, 150, 143, 50, 254, 156, 129, 243, 194, + 24, 5, 169, 238, 48, 139, 122, 96, 47, 76, 253, 53, 178, 85, + 114, 222, 70, 170, 219, 59, 132, 90, 28, 55, 169, 230, 181, 13, + 54, 149, 202, 8, 144, 194, 211, 16, 187, 24, 124, 127, 131, 227, + 137, 172, 201, 190, 169, 220, 227, 95, 107, 252, 138, 195, 78, 110, + 134, 89, 124, 103, 235, 122, 151, 125, 3, 89, 162, 81, 155, 156, + 252, 131, 219, 127, 169, 88, 195, 113, 21, 159, 56, 155, 208, 169, + 65, 30, 153, 11, 228, 45, 249, 44, 107, 120, 26, 4, 80, 109, + 131, 143, 201, 247, 236, 213, 129, 147, 76, 114, 181, 164, 165, 141, + 60, 173, 203, 134, 115, 241, 241, 182, 44, 253, 128, 158, 13, 133, + 181, 27, 1, 71, 174, 136, 229, 9, 154, 18, 8, 29, 116, 119, + 106, 71, 196, 39, 82, 41, 254, 110, 194, 184, 110, 150, 114, 28, + 51, 213, 111, 192, 226, 135, 162, 21, 109, 162, 221, 250, 7, 73, + 204, 236, 171, 38, 73, 110, 92, 129, 74, 81, 55, 121, 69, 105, + 28, 206, 175, 84, 34, 158, 166, 243, 28, 191, 2, 196, 99, 175, + 84, 227, 254, 100, 16, 145, 237, 252, 24, 7, 169, 196, 177, 161, + 115, 149, 200, 113, 142, 170, 70, 233, 7, 207, 202, 49, 2, 58, + 207, 236, 45, 156, 6, 163, 51, 93, 91, 191, 24, 215, 3, 216, + 148, 100, 237, 150, 176, 124, 118, 23, 102, 170, 9, 124, 252, 126, + 85, 215, 140, 66, 42, 17, 229, 99, 23, 227, 94, 24, 60, 236, + 115, 35, 142, 233, 66, 236, 31, 242, 14, 99, 19, 185, 77, 115, + 195, 242, 76, 226, 88, 84, 204, 87, 154, 145, 105, 136, 75, 43, + 7, 77, 176, 95, 148, 46, 28, 24, 17, 229, 75, 175, 25, 37, + 187, 190, 135, 6, 136, 236, 79, 22, 77, 158, 231, 56, 16, 6, + 41, 66, 117, 161, 40, 191, 106, 204, 21, 60, 108, 143, 180, 97, + 107, 254, 51, 129, 154, 249, 73, 49, 191, 124, 212, 107, 250, 143, + 111, 18, 32, 0, 46, 38, 181, 166, 176, 161, 82, 155, 159, 75, + 241, 236, 49, 142, 146, 150, 61, 109, 213, 34, 244, 252, 191, 117, + 185, 150, 247, 255, 49, 201, 176, 103, 116, 11, 219, 12, 194, 250, + 3, 154, 21, 90, 148, 79, 2, 129, 92, 14, 199, 49, 43, 101, + 38, 69, 154, 173, 116, 217, 5, 97, 20, 188, 31, 249, 205, 169, + 16, 238, 214, 211, 122, 223, 1, 136, 216, 132, 201, 191, 12, 192, + 229, 18, 174, 122, 202, 36, 221, 183, 115, 58, 18, 152, 100, 87, + 220, 148, 21, 19, 208, 124, 62, 252, 93, 8, 228, 204, 81, 220, + 252, 100, 77, 167, 133, 155, 30, 248, 164, 177, 154, 206, 220, 111, + 32, 127, 236, 44, 161, 84, 43, 143, 91, 64, 72, 10, 143, 72, + 246, 110, 22, 107, 163, 198, 65, 126, 115, 17, 110, 36, 0, 159, + 138, 50, 178, 250, 138, 14, 115, 8, 148, 117, 73, 213, 95, 36, + 31, 37, 57, 147, 84, 172, 175, 172, 36, 236, 198, 151, 212, 85, + 88, 58, 16, 112, 253, 154, 25, 123, 195, 12, 111, 45, 243, 157, + 53, 13, 83, 183, 40, 171, 76, 243, 220, 12, 47, 8, 188, 168, + 63, 64, 81, 128, 248, 28, 68, 29, 151, 195, 115, 81, 253, 103, + 45, 245, 72, 242, 114, 141, 54, 105, 226, 245, 47, 34, 59, 204, + 220, 62, 107, 220, 97, 76, 163, 15, 77, 250, 78, 3, 174, 116, + 137, 18, 187, 102, 194, 63, 152, 64, 209, 193, 48, 186, 11, 110, + 248, 75, 117, 177, 110, 15, 255, 98, 2, 76, 24, 193, 152, 129, + 238, 154, 243, 247, 132, 34, 102, 99, 153, 63, 94, 81, 218, 157, + 125, 227, 221, 252, 156, 166, 69, 13, 118, 140, 187, 60, 150, 120, + 107, 144, 191, 17, 18, 227, 128, 72, 181, 38, 191, 124, 69, 103, + 50, 91, 81, 238, 80, 18, 141, 15, 28, 22, 125, 203, 232, 82, + 238, 90, 147, 106, 80, 201, 108, 73, 171, 25, 234, 218, 250, 182, + 228, 114, 172, 140, 140, 153, 219, 109, 225, 168, 201, 174, 175, 169, + 76, 173, 50, 208, 213, 186, 186, 8, 250, 244, 246, 243, 45, 104, + 31, 88, 4, 248, 68, 89, 13, 225, 140, 45, 185, 222, 249, 121, + 107, 51, 24, 242, 68, 111, 117, 8, 77, 79, 71, 158, 90, 50, + 177, 115, 127, 184, 73, 255, 92, 201, 1, 153, 128, 12, 101, 245, + 53, 17, 91, 193, 112, 199, 159, 60, 38, 211, 30, 22, 75, 172, + 41, 217, 234, 24, 81, 35, 63, 215, 31, 224, 142, 139, 111, 180, + 176, 182, 52, 252, 216, 216, 7, 138, 245, 173, 178, 23, 44, 152, + 120, 145, 71, 155, 241, 41, 114, 84, 163, 9, 28, 209, 231, 134, + 236, 155, 110, 214, 16, 21, 116, 208, 0, 225, 83, 134, 178, 132, + 129, 231, 0, 104, 127, 27, 246, 166, 152, 158, 133, 127, 245, 147, + 162, 58, 64, 16, 153, 73, 6, 194, 55, 224, 134, 154, 182, 51, + 195, 99, 36, 118, 170, 21, 151, 143, 184, 114, 142, 180, 239, 232, + 197, 238, 33, 235, 178, 52, 71, 187, 101, 114, 255, 181, 39, 233, + 165, 158, 133, 47, 31, 62, 65, 94, 174, 27, 223, 131, 84, 167, + 28, 220, 154, 236, 15, 3, 53, 120, 199, 25, 220, 4, 12, 255, + 161, 90, 121, 126, 60, 44, 88, 106, 22, 148, 91, 243, 236, 252, + 21, 191, 39, 170, 125, 52, 37, 242, 118, 218, 51, 37, 110, 25, + 69, 73, 126, 86, 123, 248, 153, 221, 139, 36, 90, 70, 234, 52, + 197, 3, 154, 94, 205, 107, 132, 97, 94, 37, 44, 221, 247, 174, + 57, 218, 129, 184, 115, 204, 69, 20, 69, 144, 104, 215, 182, 173, + 177, 171, 0, 1, 68, 157, 183, 219, 234, 42, 213, 72, 240, 207, + 84, 5, 254, 116, 188, 84, 200, 171, 139, 101, 249, 20, 235, 96, + 174, 177, 109, 44, 118, 220, 99, 160, 187, 55, 135, 122, 51, 109, + 120, 140, 6, 240, 153, 11, 25, 174, 58, 219, 87, 182, 82, 171, + 226, 59, 72, 100, 72, 222, 125, 233, 20, 70, 244, 245, 214, 38, + 86, 244, 207, 67, 33, 151, 200, 212, 203, 3, 49, 156, 87, 97, + 169, 33, 35, 76, 101, 119, 167, 86, 87, 196, 228, 114, 112, 103, + 26, 172, 203, 218, 128, 171, 119, 107, 136, 36, 123, 41, 229, 18, + 185, 128, 146, 36, 246, 35, 54, 86, 61, 86, 100, 41, 10, 78, + 12, 140, 213, 214, 184, 53, 180, 125, 98, 202, 61, 116, 33, 255, + 193, 143, 41, 246, 111, 177, 230, 229, 132, 176, 188, 255, 22, 132, + 150, 2, 21, 117, 212, 83, 99, 156, 208, 105, 169, 19, 122, 164, + 225, 217, 54, 6, 137, 98, 128, 14, 243, 58, 45, 52, 133, 251, + 51, 14, 146, 254, 93, 143, 95, 228, 105, 163, 177, 49, 214, 29, + 49, 184, 181, 217, 113, 32, 84, 72, 208, 138, 75, 21, 81, 190, + 251, 93, 28, 123, 229, 3, 238, 248, 133, 216, 30, 251, 236, 9, + 116, 140, 204, 29, 8, 156, 7, 137, 167, 20, 238, 104, 51, 180, + 145, 84, 184, 57, 241, 103, 208, 59, 155, 128, 220, 137, 108, 226, + 89, 231, 202, 45, 249, 1, 216, 221, 143, 191, 167, 234, 252, 85, + 147, 136, 52, 111, 244, 21, 174, 157, 97, 237, 125, 56, 79, 94, + 142, 164, 225, 156, 86, 199, 245, 34, 227, 212, 10, 240, 110, 243, + 183, 152, 95, 22, 230, 29, 233, 177, 166, 141, 230, 137, 252, 140, + 51, 31, 14, 219, 40, 26, 206, 161, 213, 87, 189, 157, 30, 130, + 1, 153, 226, 40, 177, 79, 199, 120, 109, 86, 38, 88, 178, 207, + 116, 224, 55, 226, 81, 127, 83, 127, 155, 28, 252, 209, 54, 219, + 33, 149, 32, 73, 83, 165, 113, 3, 31, 108, 126, 177, 157, 84, + 48, 172, 57, 189, 230, 96, 133, 205, 70, 166, 242, 72, 98, 38, + 162, 83, 240, 52, 177, 28, 104, 240, 8, 154, 145, 213, 25, 182, + 71, 51, 193, 93, 237, 83, 164, 56, 223, 141, 174, 66, 37, 200, + 200, 75, 154, 81, 58, 90, 95, 205, 253, 158, 194, 210, 232, 223, + 192, 105, 100, 128, 195, 213, 182, 223, 151, 209, 127, 153, 101, 109, + 28, 187, 156, 38, 181, 137, 190, 34, 156, 106, 254, 119, 174, 172, + 124, 45, 191, 16, 72, 53, 80, 127, 246, 169, 132, 220, 148, 71, + 63, 213, 162, 121, 30, 200, 121, 201, 129, 62, 89, 88, 237, 109, + 178, 86, 100, 33, 85, 214, 102, 244, 33, 209, 167, 99, 95, 44, + 180, 71, 147, 31, 224, 191, 11, 184, 138, 51, 37, 247, 178, 70, + 192, 135, 76, 65, 128, 240, 65, 46, 129, 140, 87, 233, 238, 202, + 106, 17, 63, 161, 89, 129, 149, 115, 136, 52, 217, 242, 208, 116, + 231, 52, 69, 12, 30, 110, 61, 30, 252, 111, 239, 179, 249, 165, + 71, 75, 238, 166, 193, 126, 58, 212, 62, 212, 181, 236, 8, 114, + 86, 102, 250, 148, 185, 72, 198, 253, 83, 192, 248, 35, 211, 92, + 249, 164, 142, 223, 173, 91, 163, 185, 131, 246, 88, 69, 186, 25, + 43, 174, 240, 18, 195, 0, 161, 173, 65, 196, 202, 139, 234, 109, + 128, 99, 138, 119, 89, 107, 229, 219, 104, 19, 124, 200, 239, 143, + 163, 243, 153, 208, 149, 118, 161, 24, 172, 210, 31, 136, 158, 21, + 217, 143, 226, 76, 230, 117, 32, 193, 41, 116, 41, 238, 86, 176, + 99, 209, 1, 49, 241, 149, 65, 143, 23, 4, 216, 57, 71, 160, + 82, 97, 147, 254, 109, 3, 183, 227, 24, 38, 198, 48, 114, 90, + 229, 185, 163, 6, 226, 18, 139, 80, 70, 125, 29, 218, 44, 251, + 138, 8, 60, 107, 247, 215, 129, 221, 204, 212, 108, 158, 81, 53, + 132, 138, 109, 189, 53, 158, 228, 224, 57, 224, 177, 227, 96, 118, + 230, 192, 124, 55, 129, 93, 87, 116, 249, 215, 24, 169, 103, 160, + 97, 209, 253, 240, 38, 19, 141, 51, 136, 237, 200, 178, 5, 14, + 42, 56, 10, 70, 214, 75, 147, 64, 88, 113, 103, 110, 178, 123, + 91, 249, 122, 158, 206, 65, 221, 232, 11, 112, 126, 193, 133, 53, + 125, 56, 237, 142, 99, 154, 45, 124, 5, 57, 16, 230, 15, 242, + 57, 210, 207, 47, 163, 97, 175, 95, 252, 118, 195, 66, 248, 153, + 223, 228, 68, 92, 108, 15, 138, 154, 139, 31, 241, 161, 32, 39, + 237, 197, 34, 132, 6, 41, 155, 60, 126, 19, 81, 27, 145, 139, + 115, 121, 85, 199, 233, 188, 159, 66, 174, 214, 46, 176, 164, 110, + 126, 228, 57, 86, 46, 44, 87, 28, 85, 99, 241, 56, 245, 162, + 230, 119, 63, 90, 15, 100, 27, 94, 198, 249, 49, 40, 133, 64, + 164, 56, 233, 134, 72, 158, 195, 112, 147, 184, 63, 91, 24, 125, + 187, 148, 68, 22, 109, 226, 133, 123, 138, 201, 247, 228, 127, 44, + 8, 181, 195, 94, 122, 199, 60, 70, 70, 37, 131, 157, 88, 110, + 21, 177, 105, 148, 236, 110, 30, 172, 178, 53, 188, 144, 241, 96, + 35, 3, 48, 211, 85, 229, 167, 55, 211, 92, 51, 59, 38, 99, + 19, 92, 30, 7, 161, 125, 68, 74, 77, 10, 156, 221, 59, 151, + 72, 89, 57, 71, 22, 105, 222, 133, 97, 211, 60, 169, 248, 200, + 121, 101, 180, 253, 48, 196, 237, 82, 160, 111, 249, 84, 254, 63, + 6, 136, 172, 167, 36, 4, 206, 195, 244, 214, 206, 224, 112, 58, + 24, 196, 120, 20, 113, 103, 172, 67, 204, 88, 13, 142, 71, 3, + 17, 204, 64, 161, 21, 121, 229, 110, 191, 135, 110, 21, 36, 75, + 170, 46, 166, 27, 50, 125, 38, 236, 152, 95, 72, 18, 173, 61, + 162, 238, 72, 81, 252, 50, 135, 55, 69, 130, 94, 50, 151, 90, + 112, 122, 210, 144, 230, 97, 178, 66, 248, 78, 199, 208, 121, 8, + 133, 142, 237, 162, 194, 247, 214, 164, 13, 161, 173, 29, 115, 140, + 157, 59, 64, 162, 195, 63, 151, 102, 118, 159, 195, 239, 237, 201, + 47, 91, 85, 158, 88, 171, 179, 230, 108, 91, 159, 83, 235, 252, + 91, 232, 241, 0, 45, 245, 214, 5, 204, 118, 219, 249, 131, 5, + 108, 249, 57, 104, 241, 245, 201, 214, 134, 92, 182, 192, 50, 8, + 211, 68, 110, 173, 84, 209, 208, 202, 186, 86, 203, 75, 233, 127, + 212, 166, 103, 9, 15, 163, 177, 90, 29, 124, 252, 113, 230, 172, + 74, 54, 5, 0, 40, 109, 235, 152, 87, 6, 111, 68, 144, 13, + 107, 230, 191, 249, 251, 129, 173, 235, 244, 108, 115, 25, 149, 165, + 215, 23, 234, 168, 105, 245, 93, 83, 216, 48, 154, 219, 41, 243, + 8, 48, 29, 79, 169, 83, 12, 79, 71, 208, 253, 157, 60, 58, + 24, 113, 24, 155, 24, 161, 7, 233, 50, 199, 92, 59, 136, 217, + 181, 118, 65, 70, 165, 202, 107, 231, 141, 237, 39, 105, 119, 240, + 250, 90, 238, 124, 181, 176, 169, 89, 77, 195, 232, 87, 195, 189, + 165, 2, 66, 164, 103, 64, 194, 180, 128, 155, 5, 176, 141, 2, + 12, 201, 182, 194, 82, 1, 160, 9, 140, 133, 215, 52, 178, 254, + 243, 138, 188, 109, 25, 64, 210, 20, 204, 43, 181, 19, 41, 196, + 91, 182, 210, 47, 7, 94, 229, 109, 7, 99, 180, 202, 34, 161, + 216, 220, 61, 202, 129, 246, 69, 89, 139, 129, 237, 106, 16, 113, + 212, 206, 210, 232, 106, 198, 147, 70, 247, 43, 99, 252, 172, 81, + 105, 238, 149, 135, 11, 41, 59, 113, 84, 76, 158, 34, 244, 89, + 162, 31, 61, 50, 129, 72, 23, 207, 105, 8, 30, 183, 130, 146, + 218, 194, 58, 121, 1, 198, 27, 208, 198, 167, 204, 43, 219, 16, + 216, 195, 68, 183, 113, 50, 235, 144, 67, 115, 86, 200, 60, 98, + 67, 178, 229, 55, 14, 179, 27, 219, 11, 202, 3, 55, 194, 190, + 233, 255, 221, 150, 166, 115, 72, 252, 70, 105, 39, 112, 80, 18, + 198, 98, 196, 63, 220, 216, 178, 92, 95, 228, 172, 37, 248, 61, + 2, 210, 27, 131, 30, 157, 7, 208, 206, 39, 228, 189, 254, 80, + 61, 209, 241, 147, 131, 224, 141, 163, 139, 34, 218, 74, 123, 168, + 147, 162, 215, 63, 218, 179, 50, 230, 111, 76, 207, 7, 168, 12, + 2, 171, 1, 3, 85, 169, 43, 232, 1, 26, 97, 157, 74, 133, + 229, 47, 123, 205, 235, 237, 137, 195, 220, 64, 184, 230, 188, 50, + 232, 133, 111, 73, 99, 45, 19, 163, 155, 99, 250, 108, 208, 107, + 162, 99, 58, 37, 155, 26, 245, 207, 81, 17, 251, 217, 143, 63, + 117, 94, 53, 30, 8, 6, 166, 117, 57, 172, 152, 3, 19, 99, + 63, 186, 179, 170, 120, 92, 76, 135, 164, 27, 251, 8, 148, 118, + 110, 214, 255, 6, 250, 123, 126, 134, 12, 65, 166, 183, 67, 183, + 121, 72, 55, 177, 112, 35, 47, 169, 207, 52, 119, 75, 238, 161, + 197, 6, 238, 162, 65, 221, 37, 156, 22, 67, 252, 201, 218, 168, + 117, 247, 229, 219, 95, 38, 239, 159, 161, 88, 67, 0, 171, 20, + 125, 171, 96, 254, 93, 97, 233, 130, 9, 197, 63, 131, 82, 135, + 69, 121, 12, 27, 205, 143, 204, 104, 152, 129, 15, 97, 204, 82, + 14, 85, 152, 110, 158, 226, 174, 150, 101, 235, 213, 83, 112, 23, + 60, 93, 55, 109, 216, 247, 221, 169, 208, 161, 211, 142, 162, 214, + 110, 33, 217, 40, 196, 117, 13, 218, 88, 150, 86, 222, 6, 182, + 98, 184, 134, 73, 3, 87, 3, 14, 168, 57, 36, 124, 203, 204, + 99, 225, 66, 99, 184, 111, 180, 87, 31, 114, 187, 211, 172, 242, + 195, 251, 31, 253, 194, 17, 107, 68, 182, 198, 98, 23, 31, 176, + 216, 113, 36, 97, 73, 238, 224, 73, 218, 11, 174, 170, 254, 78, + 154, 215, 53, 14, 176, 166, 2, 231, 88, 32, 33, 166, 184, 89, + 71, 203, 211, 106, 60, 97, 98, 243, 61, 119, 195, 125, 201, 75, + 112, 73, 92, 107, 188, 76, 139, 23, 177, 244, 213, 31, 86, 46, + 187, 48, 232, 84, 253, 46, 221, 122, 82, 4, 222, 19, 225, 163, + 102, 123, 85, 95, 223, 55, 220, 246, 3, 197, 182, 252, 141, 249, + 69, 95, 222, 173, 251, 44, 162, 31, 228, 110, 174, 173, 100, 210, + 97, 141, 199, 103, 207, 84, 8, 100, 200, 44, 102, 235, 212, 7, + 154, 27, 171, 110, 134, 103, 235, 192, 216, 216, 157, 41, 103, 178, + 69, 108, 49, 20, 114, 192, 187, 226, 24, 28, 95, 193, 90, 30, + 29, 198, 172, 225, 34, 184, 16, 46, 56, 56, 40, 92, 141, 22, + 103, 56, 127, 139, 98, 160, 195, 1, 7, 167, 150, 173, 2, 222, + 115, 196, 126, 218, 46, 187, 169, 11, 113, 1, 248, 77, 124, 219, + 70, 5, 99, 67, 198, 210, 177, 44, 102, 144, 34, 186, 164, 63, + 210, 62, 154, 25, 230, 181, 11, 59, 97, 53, 101, 247, 247, 165, + 43, 122, 36, 73, 45, 29, 113, 56, 83, 210, 104, 242, 73, 245, + 133, 202, 95, 168, 167, 158, 87, 14, 41, 90, 152, 181, 253, 160, + 71, 243, 199, 90, 160, 251, 114, 195, 134, 150, 69, 18, 207, 166, + 112, 109, 217, 114, 120, 164, 190, 137, 82, 19, 89, 73, 183, 94, + 43, 75, 226, 231, 50, 26, 193, 170, 45, 253, 163, 74, 101, 136, + 201, 167, 109, 186, 230, 43, 240, 81, 119, 34, 75, 217, 145, 25, + 216, 124, 42, 16, 209, 217, 255, 117, 75, 173, 86, 224, 18, 101, + 229, 95, 254, 94, 143, 178, 22, 3, 57, 8, 25, 135, 31, 53, + 106, 247, 220, 181, 193, 106, 142, 5, 20, 96, 150, 185, 170, 68, + 39, 2, 195, 115, 118, 84, 90, 137, 128, 216, 192, 16, 56, 99, + 156, 73, 171, 59, 245, 95, 103, 138, 211, 202, 137, 108, 23, 78, + 194, 90, 4, 162, 200, 10, 41, 110, 122, 218, 245, 212, 108, 225, + 86, 23, 77, 16, 101, 181, 58, 128, 28, 116, 162, 234, 122, 63, + 177, 156, 43, 138, 210, 26, 113, 195, 186, 174, 131, 184, 48, 193, + 92, 224, 56, 147, 171, 174, 102, 38, 80, 95, 109, 39, 238, 74, + 187, 85, 53, 140, 170, 51, 159, 21, 112, 193, 221, 163, 222, 116, + 151, 127, 131, 135, 184, 202, 129, 165, 226, 127, 17, 24, 91, 13, + 240, 197, 36, 14, 128, 46, 204, 243, 144, 225, 200, 168, 60, 235, + 245, 199, 142, 61, 186, 61, 236, 228, 39, 232, 129, 249, 221, 43, + 4, 28, 221, 37, 156, 229, 56, 29, 23, 114, 221, 65, 193, 152, + 19, 90, 124, 29, 82, 27, 193, 234, 83, 97, 202, 238, 249, 50, + 93, 185, 229, 61, 254, 160, 233, 172, 83, 23, 107, 85, 50, 103, + 153, 16, 134, 185, 12, 157, 39, 39, 88, 174, 238, 50, 29, 25, + 168, 120, 61, 190, 106, 135, 186, 117, 9, 107, 164, 103, 206, 103, + 201, 123, 183, 194, 203, 138, 0, 205, 138, 252, 24, 128, 101, 254, + 95, 13, 103, 44, 87, 187, 237, 231, 6, 80, 25, 240, 51, 46, + 125, 178, 138, 108, 167, 214, 127, 168, 194, 164, 238, 89, 196, 141, + 175, 188, 113, 69, 29, 19, 91, 22, 159, 111, 97, 14, 49, 119, + 163, 95, 211, 221, 164, 111, 126, 116, 74, 241, 248, 12, 240, 21, + 63, 0, 219, 123, 196, 164, 38, 102, 68, 149, 164, 198, 231, 40, + 175, 81, 187, 110, 156, 182, 5, 107, 42, 51, 252, 128, 88, 62, + 75, 193, 82, 103, 66, 146, 132, 186, 128, 252, 191, 178, 186, 38, + 64, 10, 171, 41, 169, 203, 198, 166, 3, 70, 118, 61, 76, 71, + 169, 26, 30, 235, 180, 199, 164, 234, 161, 222, 147, 213, 117, 48, + 252, 229, 26, 103, 73, 158, 184, 68, 27, 231, 219, 143, 32, 92, + 94, 70, 134, 2, 104, 196, 204, 54, 208, 124, 201, 110, 110, 179, + 198, 23, 158, 120, 251, 65, 244, 156, 118, 162, 61, 220, 13, 6, + 145, 138, 81, 133, 22, 121, 34, 200, 240, 39, 86, 177, 153, 54, + 171, 120, 143, 209, 152, 214, 6, 10, 150, 189, 20, 187, 119, 241, + 185, 244, 51, 252, 124, 176, 115, 176, 202, 122, 39, 80, 142, 45, + 89, 5, 245, 237, 175, 163, 180, 228, 17, 182, 13, 133, 226, 28, + 149, 156, 252, 214, 85, 46, 157, 44, 110, 46, 227, 8, 189, 230, + 14, 145, 207, 213, 201, 0, 160, 247, 232, 158, 110, 73, 188, 131, + 38, 122, 147, 163, 66, 103, 82, 152, 62, 117, 129, 189, 200, 160, + 39, 67, 63, 14, 57, 192, 226, 14, 12, 212, 53, 225, 174, 16, + 195, 122, 45, 180, 187, 76, 142, 172, 16, 65, 120, 160, 215, 248, + 246, 195, 62, 43, 185, 24, 169, 95, 106, 27, 129, 23, 243, 133, + 56, 193, 187, 134, 39, 193, 249, 177, 195, 229, 239, 149, 49, 36, + 105, 92, 128, 53, 91, 227, 27, 96, 253, 95, 3, 35, 126, 173, + 92, 54, 63, 101, 61, 133, 48, 209, 233, 16, 104, 53, 59, 226, + 79, 107, 222, 163, 99, 5, 226, 135, 215, 208, 86, 29, 85, 201, + 156, 209, 9, 142, 185, 34, 98, 255, 94, 250, 228, 79, 7, 51, + 136, 131, 114, 20, 196, 1, 138, 166, 187, 237, 164, 243, 48, 255, + 93, 33, 197, 194, 145, 220, 229, 226, 208, 200, 111, 139, 197, 152, + 205, 122, 15, 29, 28, 15, 133, 23, 31, 141, 34, 64, 3, 232, + 147, 72, 252, 131, 79, 229, 184, 182, 192, 27, 50, 164, 104, 64, + 174, 230, 200, 40, 151, 11, 29, 199, 33, 63, 86, 172, 48, 23, + 165, 79, 72, 235, 254, 204, 113, 98, 142, 225, 68, 50, 123, 102, + 124, 232, 39, 33, 51, 165, 137, 229, 222, 7, 63, 97, 102, 36, + 181, 243, 163, 8, 9, 75, 94, 74, 154, 64, 171, 36, 164, 89, + 109, 251, 218, 88, 245, 137, 136, 228, 42, 203, 104, 198, 189, 205, + 243, 57, 97, 204, 236, 247, 157, 63, 223, 44, 210, 8, 131, 246, + 79, 60, 198, 10, 114, 23, 232, 50, 199, 225, 216, 221, 46, 244, + 19, 250, 255, 112, 25, 179, 191, 93, 187, 26, 39, 65, 6, 111, + 20, 27, 97, 197, 71, 228, 194, 45, 240, 252, 20, 243, 239, 253, + 28, 198, 181, 121, 136, 146, 102, 142, 207, 120, 47, 134, 45, 246, + 37, 180, 89, 213, 35, 198, 14, 69, 91, 20, 130, 178, 233, 186, + 32, 219, 137, 14, 202, 91, 187, 228, 58, 39, 128, 247, 55, 144, + 120, 175, 30, 11, 184, 178, 81, 53, 121, 206, 48, 160, 94, 132, + 85, 202, 40, 97, 67, 134, 113, 164, 250, 39, 101, 95, 19, 39, + 224, 159, 46, 183, 134, 155, 251, 96, 201, 191, 173, 26, 205, 167, + 72, 121, 7, 171, 105, 126, 46, 119, 11, 234, 238, 99, 250, 0, + 176, 206, 15, 251, 134, 121, 190, 172, 176, 144, 99, 10, 23, 116, + 165, 52, 65, 47, 92, 200, 43, 216, 104, 5, 154, 109, 237, 212, + 134, 119, 173, 78, 52, 120, 196, 239, 11, 223, 180, 33, 238, 32, + 226, 152, 61, 202, 71, 158, 49, 150, 151, 183, 98, 66, 183, 203, + 6, 171, 181, 8, 142, 164, 108, 243, 28, 19, 74, 193, 110, 246, + 106, 22, 103, 140, 4, 99, 92, 112, 109, 98, 179, 163, 109, 114, + 135, 30, 41, 77, 139, 54, 90, 216, 14, 195, 68, 148, 49, 145, + 105, 85, 214, 56, 133, 206, 98, 116, 190, 149, 129, 91, 173, 111, + 15, 237, 31, 157, 27, 75, 190, 244, 25, 198, 191, 5, 114, 193, + 234, 84, 103, 211, 198, 48, 127, 45, 200, 143, 214, 112, 89, 39, + 17, 108, 194, 87, 138, 147, 122, 136, 111, 82, 94, 245, 189, 232, + 106, 117, 6, 152, 229, 179, 45, 225, 86, 17, 87, 141, 152, 77, + 130, 186, 123, 115, 182, 185, 119, 229, 254, 178, 1, 188, 31, 136, + 218, 136, 189, 61, 152, 31, 103, 149, 98, 145, 230, 0, 100, 113, + 100, 140, 233, 12, 199, 71, 83, 95, 31, 42, 17, 35, 3, 169, + 229, 46, 70, 44, 104, 133, 190, 112, 103, 181, 249, 140, 228, 68, + 95, 58, 42, 155, 111, 44, 228, 249, 11, 220, 67, 51, 38, 200, + 10, 86, 117, 65, 175, 170, 241, 239, 76, 107, 70, 194, 66, 143, + 85, 222, 67, 9, 42, 132, 231, 244, 239, 59, 105, 219, 221, 172, + 104, 58, 171, 178, 182, 125, 225, 163, 130, 112, 37, 121, 138, 51, + 116, 177, 122, 5, 191, 38, 29, 211, 215, 241, 119, 102, 236, 230, + 178, 147, 60, 231, 11, 186, 37, 63, 83, 92, 118, 86, 241, 252, + 241, 170, 195, 231, 135, 118, 3, 151, 255, 132, 73, 135, 242, 158, + 191, 56, 19, 71, 186, 14, 198, 19, 122, 217, 170, 208, 39, 11, + 212, 3, 154, 161, 48, 177, 176, 155, 163, 137, 27, 38, 67, 201, + 64, 118, 153, 223, 113, 195, 41, 62, 28, 206, 224, 79, 227, 137, + 126, 73, 131, 109, 51, 215, 66, 110, 114, 196, 136, 176, 81, 21, + 121, 228, 26, 97, 234, 10, 84, 147, 68, 30, 128, 56, 188, 251, + 246, 196, 98, 157, 187, 91, 157, 232, 138, 89, 158, 115, 121, 76, + 157, 56, 34, 15, 99, 252, 242, 118, 110, 113, 170, 107, 171, 92, + 237, 122, 59, 135, 28, 114, 101, 232, 236, 148, 99, 33, 116, 225, + 132, 7, 226, 221, 57, 74, 158, 49, 63, 39, 143, 28, 74, 218, + 16, 126, 20, 44, 110, 27, 94, 124, 105, 92, 242, 16, 25, 132, + 226, 72, 230, 223, 10, 139, 211, 56, 179, 36, 235, 108, 218, 194, + 38, 179, 42, 161, 2, 107, 55, 141, 24, 48, 5, 56, 250, 82, + 104, 64, 239, 21, 141, 222, 25, 161, 35, 142, 194, 80, 118, 226, + 147, 154, 64, 162, 66, 133, 149, 186, 79, 164, 215, 125, 217, 82, + 226, 84, 222, 29, 88, 241, 180, 11, 224, 217, 108, 196, 240, 37, + 221, 232, 87, 103, 127, 69, 224, 129, 218, 2, 9, 25, 202, 93, + 16, 150, 169, 109, 58, 107, 101, 151, 50, 109, 232, 51, 20, 188, + 218, 16, 246, 3, 44, 133, 191, 150, 1, 139, 71, 18, 166, 7, + 171, 185, 226, 154, 252, 91, 60, 9, 185, 159, 91, 128, 146, 209, + 31, 254, 168, 95, 214, 28, 59, 134, 60, 156, 86, 255, 199, 12, + 144, 49, 243, 87, 162, 219, 116, 1, 243, 189, 203, 154, 172, 147, + 65, 5, 9, 89, 227, 95, 217, 111, 84, 114, 129, 143, 167, 108, + 108, 91, 81, 10, 113, 91, 67, 20, 183, 142, 150, 173, 190, 89, + 136, 247, 147, 24, 112, 120, 124, 71, 56, 100, 106, 144, 26, 82, + 67, 243, 189, 41, 162, 75, 5, 10, 13, 119, 74, 6, 13, 2, + 139, 81, 80, 201, 183, 136, 95, 100, 39, 149, 130, 242, 155, 111, + 192, 127, 124, 182, 11, 217, 61, 9, 40, 35, 156, 1, 112, 17, + 193, 224, 9, 228, 122, 76, 25, 78, 243, 243, 91, 108, 204, 133, + 12, 177, 217, 70, 228, 200, 248, 0, 216, 93, 76, 88, 242, 16, + 97, 202, 21, 176, 238, 24, 22, 179, 193, 45, 43, 112, 21, 45, + 146, 63, 114, 103, 20, 17, 242, 91, 167, 191, 129, 73, 126, 222, + 6, 44, 81, 96, 191, 171, 94, 191, 81, 249, 144, 62, 118, 232, + 50, 157, 198, 64, 49, 34, 86, 18, 164, 250, 55, 88, 95, 125, + 196, 166, 149, 235, 149, 208, 97, 222, 163, 106, 243, 230, 4, 13, + 38, 188, 214, 144, 42, 176, 219, 39, 229, 41, 198, 99, 114, 80, + 110, 236, 148, 0, 29, 89, 177, 226, 51, 109, 192, 130, 16, 192, + 122, 243, 16, 20, 236, 89, 170, 152, 161, 159, 254, 38, 136, 37, + 146, 21, 37, 24, 96, 140, 29, 153, 100, 251, 61, 182, 6, 140, + 102, 199, 17, 70, 239, 211, 178, 160, 29, 138, 237, 167, 39, 28, + 2, 135, 17, 243, 220, 56, 73, 227, 79, 242, 141, 227, 6, 179, + 146, 164, 73, 40, 135, 168, 109, 38, 185, 102, 102, 45, 115, 55, + 196, 15, 227, 220, 87, 19, 30, 202, 139, 17, 51, 199, 76, 134, + 187, 250, 208, 236, 192, 57, 213, 80, 123, 130, 17, 114, 16, 115, + 122, 165, 206, 245, 90, 53, 236, 53, 188, 196, 96, 193, 128, 87, + 65, 8, 230, 221, 2, 49, 74, 141, 59, 31, 198, 206, 45, 133, + 41, 31, 205, 0, 219, 20, 155, 54, 175, 164, 60, 65, 171, 234, + 184, 129, 125, 72, 141, 222, 1, 50, 170, 113, 187, 15, 217, 37, + 132, 107, 78, 82, 27, 179, 68, 199, 49, 184, 210, 247, 76, 203, + 215, 168, 27, 29, 140, 189, 105, 108, 62, 189, 176, 163, 246, 74, + 27, 238, 188, 115, 183, 104, 47, 201, 64, 148, 217, 91, 227, 233, + 241, 104, 224, 118, 95, 124, 181, 57, 14, 161, 207, 233, 241, 60, + 139, 50, 216, 123, 80, 240, 25, 94, 75, 147, 224, 131, 175, 192, + 183, 244, 132, 35, 152, 92, 150, 215, 170, 225, 165, 117, 8, 50, + 145, 109, 144, 22, 184, 84, 55, 154, 84, 84, 89, 215, 187, 185, + 102, 113, 247, 57, 253, 65, 135, 148, 63, 138, 212, 22, 31, 4, + 55, 6, 193, 206, 90, 20, 171, 127, 151, 101, 62, 75, 87, 211, + 252, 99, 185, 101, 228, 123, 156, 125, 157, 66, 102, 24, 48, 135, + 71, 120, 173, 57, 143, 41, 102, 66, 89, 18, 250, 249, 148, 246, + 83, 104, 195, 161, 175, 113, 158, 12, 217, 239, 55, 132, 141, 125, + 193, 134, 205, 118, 226, 15, 92, 11, 2, 166, 124, 32, 176, 249, + 209, 193, 48, 0, 78, 118, 57, 165, 182, 201, 21, 164, 48, 203, + 226, 183, 61, 5, 46, 172, 188, 225, 13, 248, 66, 95, 23, 161, + 216, 113, 225, 28, 31, 241, 29, 198, 126, 104, 205, 7, 39, 210, + 104, 79, 132, 70, 185, 185, 152, 127, 77, 137, 227, 75, 234, 87, + 40, 58, 139, 83, 13, 252, 18, 114, 133, 96, 4, 194, 208, 32, + 175, 44, 157, 186, 44, 156, 40, 19, 58, 45, 160, 148, 8, 30, + 132, 43, 31, 6, 126, 95, 77, 150, 216, 11, 120, 175, 49, 12, + 222, 117, 228, 124, 224, 107, 19, 176, 155, 149, 69, 254, 152, 168, + 49, 98, 254, 239, 224, 21, 201, 4, 65, 10, 128, 226, 184, 254, + 88, 49, 53, 10, 11, 19, 213, 50, 168, 102, 97, 231, 164, 109, + 10, 78, 124, 77, 248, 191, 182, 202, 46, 251, 129, 223, 46, 109, + 207, 244, 204, 232, 14, 57, 61, 197, 32, 28, 3, 41, 157, 139, + 92, 90, 143, 183, 78, 79, 43, 19, 163, 161, 99, 195, 153, 51, + 178, 166, 73, 70, 225, 176, 146, 221, 253, 92, 83, 132, 104, 114, + 206, 233, 232, 134, 178, 203, 191, 117, 2, 138, 11, 66, 79, 230, + 70, 84, 175, 21, 2, 3, 202, 106, 78, 110, 163, 124, 115, 35, + 102, 182, 153, 156, 87, 128, 194, 249, 52, 165, 30, 5, 177, 67, + 207, 153, 204, 100, 0, 146, 34, 77, 225, 170, 4, 114, 128, 0, + 34, 186, 92, 129, 169, 136, 82, 91, 178, 38, 64, 84, 188, 187, + 150, 56, 91, 150, 192, 109, 105, 248, 79, 98, 205, 86, 218, 159, + 59, 14, 86, 235, 66, 10, 93, 119, 27, 54, 210, 79, 86, 245, + 156, 65, 135, 152, 215, 18, 208, 232, 226, 159, 9, 165, 70, 49, + 6, 90, 89, 66, 206, 156, 218, 162, 155, 30, 110, 152, 115, 137, + 18, 195, 219, 241, 162, 251, 47, 235, 145, 150, 140, 36, 6, 126, + 237, 110, 35, 99, 17, 78, 29, 247, 216, 165, 191, 69, 153, 215, + 57, 131, 115, 227, 2, 223, 195, 253, 39, 90, 17, 48, 3, 44, + 95, 217, 158, 39, 100, 146, 127, 56, 40, 107, 249, 244, 146, 185, + 30, 135, 84, 130, 186, 146, 143, 212, 207, 149, 206, 26, 5, 57, + 58, 50, 11, 147, 207, 50, 114, 107, 113, 103, 110, 35, 30, 119, + 38, 185, 34, 131, 167, 92, 146, 105, 223, 127, 198, 193, 136, 57, + 169, 110, 64, 68, 247, 240, 122, 184, 127, 189, 17, 132, 189, 228, + 229, 212, 70, 17, 226, 60, 23, 28, 233, 91, 83, 38, 154, 210, + 189, 180, 164, 164, 248, 183, 80, 43, 13, 70, 195, 254, 27, 241, + 201, 188, 60, 165, 106, 153, 211, 175, 177, 173, 233, 93, 174, 135, + 18, 45, 190, 187, 186, 11, 246, 33, 39, 175, 22, 71, 161, 48, + 57, 140, 249, 192, 223, 135, 37, 160, 251, 66, 195, 24, 192, 233, + 222, 205, 250, 136, 97, 189, 31, 240, 157, 181, 140, 137, 240, 226, + 41, 26, 110, 29, 130, 193, 18, 160, 112, 210, 99, 165, 181, 126, + 105, 71, 170, 131, 61, 60, 197, 153, 188, 46, 212, 150, 239, 208, + 161, 52, 34, 229, 231, 182, 157, 98, 212, 62, 94, 139, 126, 204, + 57, 223, 207, 62, 153, 225, 0, 242, 11, 6, 122, 71, 222, 53, + 250, 101, 18, 124, 214, 133, 201, 36, 1, 100, 30, 138, 166, 94, + 153, 175, 1, 130, 14, 229, 128, 237, 98, 166, 189, 38, 16, 197, + 6, 233, 235, 6, 87, 28, 102, 57, 88, 160, 201, 201, 23, 236, + 59, 47, 245, 195, 159, 14, 25, 218, 249, 142, 20, 72, 186, 57, + 113, 4, 247, 212, 94, 158, 26, 196, 229, 134, 160, 97, 64, 1, + 139, 222, 126, 170, 131, 116, 252, 6, 161, 122, 64, 161, 93, 85, + 80, 59, 226, 184, 95, 231, 18, 14, 194, 151, 114, 18, 124, 84, + 9, 38, 8, 111, 246, 40, 109, 214, 55, 174, 155, 41, 49, 74, + 52, 167, 47, 174, 219, 182, 12, 22, 249, 224, 121, 172, 115, 82, + 22, 43, 95, 208, 237, 144, 106, 207, 212, 187, 209, 217, 181, 144, + 93, 236, 10, 128, 198, 48, 14, 33, 82, 63, 139, 82, 199, 14, + 159, 198, 247, 74, 13, 144, 224, 149, 93, 107, 170, 201, 16, 220, + 224, 32, 115, 180, 63, 82, 37, 217, 226, 77, 36, 162, 99, 70, + 241, 248, 42, 141, 28, 9, 227, 75, 147, 90, 29, 112, 61, 219, + 23, 254, 82, 246, 72, 6, 96, 98, 18, 251, 111, 179, 8, 17, + 166, 151, 165, 68, 214, 198, 124, 16, 143, 23, 161, 77, 161, 193, + 165, 130, 199, 48, 195, 6, 102, 131, 202, 7, 110, 214, 181, 166, + 8, 241, 19, 49, 41, 160, 221, 187, 77, 46, 23, 248, 173, 3, + 41, 183, 181, 87, 225, 211, 190, 183, 252, 11, 235, 107, 195, 177, + 16, 242, 192, 82, 253, 204, 213, 25, 120, 194, 28, 236, 73, 126, + 184, 25, 19, 98, 9, 126, 88, 60, 119, 2, 114, 107, 232, 77, + 187, 36, 33, 123, 126, 187, 58, 58, 191, 247, 231, 114, 235, 245, + 25, 179, 141, 141, 59, 173, 74, 183, 252, 69, 133, 168, 148, 64, + 24, 44, 145, 234, 61, 220, 172, 75, 217, 53, 227, 97, 1, 140, + 229, 238, 4, 73, 11, 178, 94, 135, 100, 134, 102, 92, 157, 143, + 94, 110, 191, 46, 164, 127, 239, 192, 238, 44, 20, 33, 36, 87, + 230, 173, 86, 190, 212, 223, 64, 2, 149, 230, 250, 210, 213, 104, + 94, 103, 192, 131, 223, 154, 89, 71, 32, 202, 206, 175, 135, 189, + 60, 239, 255, 132, 48, 218, 244, 198, 70, 129, 201, 227, 95, 170, + 159, 65, 53, 212, 207, 190, 208, 4, 145, 151, 15, 243, 40, 22, + 34, 46, 229, 69, 65, 78, 154, 175, 113, 204, 203, 170, 145, 168, + 183, 27, 158, 105, 185, 25, 96, 25, 87, 61, 237, 20, 135, 195, + 184, 41, 123, 148, 201, 134, 138, 190, 42, 226, 140, 32, 191, 126, + 183, 94, 80, 20, 122, 192, 203, 40, 128, 7, 190, 19, 193, 118, + 59, 81, 38, 142, 100, 139, 103, 118, 131, 13, 99, 77, 243, 132, + 81, 83, 99, 113, 19, 164, 8, 23, 60, 189, 105, 39, 191, 62, + 57, 105, 2, 21, 116, 207, 222, 226, 137, 177, 155, 201, 164, 182, + 126, 92, 134, 221, 61, 219, 146, 78, 6, 48, 246, 81, 11, 13, + 64, 93, 160, 83, 154, 40, 61, 151, 3, 243, 244, 221, 34, 169, + 246, 25, 193, 7, 169, 210, 67, 20, 32, 107, 150, 37, 20, 165, + 44, 189, 153, 32, 4, 255, 154, 192, 225, 154, 147, 7, 118, 47, + 82, 63, 68, 67, 233, 30, 17, 244, 233, 76, 158, 208, 165, 19, + 6, 0, 173, 151, 165, 204, 237, 216, 15, 3, 82, 134, 50, 31, + 98, 252, 34, 126, 197, 233, 82, 111, 90, 50, 162, 219, 228, 251, + 205, 36, 13, 2, 46, 68, 119, 36, 109, 50, 161, 16, 120, 162, + 197, 124, 79, 38, 63, 17, 176, 122, 238, 220, 75, 139, 123, 243, + 84, 237, 161, 194, 6, 227, 207, 127, 202, 49, 199, 159, 59, 196, + 231, 175, 82, 140, 103, 91, 215, 26, 57, 160, 219, 53, 141, 202, + 70, 90, 93, 141, 43, 186, 212, 106, 102, 205, 184, 30, 28, 96, + 198, 232, 212, 81, 128, 168, 223, 120, 35, 156, 166, 111, 228, 61, + 71, 52, 55, 131, 37, 178, 108, 84, 172, 36, 45, 3, 199, 188, + 4, 21, 202, 55, 51, 153, 25, 2, 78, 101, 44, 136, 69, 69, + 45, 227, 58, 160, 167, 205, 189, 53, 222, 173, 18, 232, 208, 152, + 205, 215, 6, 248, 208, 173, 132, 139, 66, 139, 16, 156, 41, 121, + 19, 252, 251, 173, 14, 225, 148, 197, 203, 109, 64, 166, 147, 255, + 53, 92, 162, 26, 15, 76, 91, 126, 157, 153, 245, 31, 201, 190, + 33, 144, 129, 23, 182, 141, 157, 114, 165, 38, 26, 45, 232, 165, + 56, 95, 229, 212, 74, 195, 187, 89, 115, 46, 20, 158, 220, 98, + 86, 49, 231, 169, 209, 62, 153, 213, 12, 207, 27, 14, 174, 186, + 22, 95, 67, 135, 217, 93, 169, 174, 139, 89, 254, 63, 4, 151, + 115, 121, 186, 216, 69, 27, 0, 151, 88, 231, 68, 120, 235, 23, + 35, 249, 151, 75, 91, 10, 6, 159, 14, 209, 48, 97, 38, 83, + 2, 239, 58, 186, 119, 253, 196, 229, 28, 148, 192, 176, 137, 233, + 60, 109, 161, 217, 229, 147, 115, 72, 61, 86, 225, 44, 78, 224, + 197, 216, 239, 25, 239, 160, 198, 16, 33, 117, 64, 128, 200, 228, + 169, 16, 22, 81, 165, 172, 43, 35, 18, 244, 129, 217, 105, 152, + 139, 244, 229, 113, 167, 10, 107, 117, 67, 158, 42, 30, 43, 221, + 229, 202, 20, 247, 45, 82, 172, 191, 119, 211, 107, 42, 201, 158, + 47, 6, 8, 242, 84, 218, 174, 30, 113, 200, 33, 44, 166, 204, + 37, 49, 244, 74, 14, 152, 42, 162, 221, 149, 17, 167, 73, 36, + 249, 135, 82, 155, 184, 152, 220, 182, 221, 80, 227, 221, 13, 231, + 175, 136, 244, 213, 147, 83, 209, 249, 178, 201, 20, 115, 250, 51, + 163, 73, 211, 10, 188, 134, 189, 188, 215, 85, 5, 90, 173, 217, + 120, 4, 229, 94, 95, 58, 253, 154, 172, 3, 110, 104, 223, 96, + 24, 103, 133, 240, 162, 218, 247, 102, 172, 172, 246, 68, 72, 201, + 178, 82, 22, 119, 16, 56, 132, 88, 81, 150, 231, 235, 18, 81, + 187, 217, 230, 109, 68, 46, 60, 40, 125, 71, 7, 61, 180, 106, + 250, 202, 228, 237, 178, 90, 161, 114, 141, 16, 29, 240, 190, 32, + 40, 108, 80, 130, 101, 214, 197, 214, 113, 227, 1, 210, 208, 184, + 144, 234, 243, 29, 249, 227, 126, 106, 102, 189, 129, 55, 97, 88, + 19, 194, 40, 191, 149, 238, 87, 225, 136, 175, 42, 20, 49, 153, + 36, 229, 13, 79, 54, 153, 115, 191, 231, 148, 3, 177, 70, 133, + 249, 210, 125, 58, 129, 50, 77, 34, 251, 155, 232, 238, 205, 144, + 135, 57, 225, 36, 193, 150, 88, 44, 46, 173, 86, 220, 84, 166, + 15, 48, 123, 165, 94, 196, 96, 175, 58, 53, 10, 143, 138, 238, + 9, 21, 85, 31, 121, 140, 93, 97, 152, 106, 251, 123, 165, 5, + 93, 181, 54, 252, 168, 246, 16, 115, 157, 23, 149, 217, 201, 164, + 153, 105, 222, 72, 225, 190, 143, 127, 96, 245, 94, 40, 193, 33, + 37, 103, 45, 254, 77, 143, 127, 166, 239, 163, 3, 172, 167, 137, + 106, 62, 167, 83, 71, 201, 109, 180, 205, 228, 3, 149, 133, 170, + 199, 152, 44, 58, 218, 5, 65, 101, 112, 252, 96, 215, 18, 230, + 168, 84, 20, 34, 32, 199, 61, 111, 7, 229, 82, 71, 17, 191, + 234, 41, 69, 60, 83, 235, 159, 9, 152, 178, 185, 67, 113, 139, + 21, 91, 255, 133, 109, 85, 69, 138, 252, 76, 181, 133, 92, 198, + 219, 140, 119, 106, 106, 33, 159, 32, 61, 238, 13, 220, 238, 157, + 56, 44, 72, 176, 150, 30, 152, 27, 42, 178, 47, 78, 183, 188, + 60, 16, 94, 129, 105, 48, 198, 3, 128, 87, 35, 12, 87, 133, + 24, 8, 193, 193, 254, 64, 5, 42, 135, 221, 79, 208, 142, 245, + 33, 80, 169, 72, 98, 92, 181, 53, 68, 251, 238, 0, 201, 175, + 59, 146, 76, 113, 54, 239, 78, 16, 118, 7, 4, 130, 224, 253, + 249, 219, 173, 196, 227, 165, 29, 97, 149, 226, 241, 5, 105, 154, + 96, 106, 93, 178, 71, 232, 105, 213, 95, 140, 54, 91, 111, 115, + 247, 185, 196, 52, 183, 55, 205, 50, 98, 98, 166, 30, 241, 240, + 51, 244, 140, 238, 115, 138, 157, 162, 160, 53, 139, 153, 9, 165, + 62, 229, 71, 168, 103, 11, 73, 220, 204, 165, 184, 104, 244, 248, + 144, 191, 179, 242, 39, 89, 6, 129, 164, 106, 249, 236, 106, 152, + 93, 200, 88, 42, 116, 80, 146, 70, 164, 85, 172, 103, 0, 130, + 6, 202, 49, 180, 109, 232, 249, 88, 117, 9, 255, 75, 80, 24, + 58, 27, 50, 77, 63, 125, 6, 43, 146, 200, 237, 235, 90, 52, + 103, 181, 22, 68, 132, 240, 183, 37, 221, 191, 129, 220, 33, 29, + 51, 35, 62, 136, 44, 144, 38, 55, 129, 14, 51, 48, 133, 222, + 111, 148, 126, 176, 118, 116, 81, 197, 244, 117, 155, 255, 127, 114, + 127, 225, 20, 129, 160, 136, 130, 123, 14, 135, 38, 144, 129, 242, + 177, 232, 227, 165, 41, 234, 79, 133, 124, 141, 69, 83, 31, 72, + 189, 89, 142, 9, 79, 18, 190, 188, 162, 225, 67, 30, 82, 32, + 212, 4, 250, 112, 57, 161, 240, 96, 68, 84, 120, 189, 237, 187, + 212, 245, 15, 65, 230, 154, 222, 234, 113, 214, 92, 180, 127, 10, + 30, 62, 171, 248, 246, 25, 95, 161, 104, 180, 228, 241, 144, 149, + 176, 88, 170, 21, 37, 177, 226, 84, 47, 252, 29, 224, 252, 246, + 9, 186, 86, 37, 65, 43, 72, 179, 30, 53, 67, 153, 26, 117, + 246, 171, 141, 167, 170, 3, 165, 49, 89, 192, 242, 198, 15, 7, + 13, 17, 114, 22, 80, 90, 141, 149, 144, 189, 77, 63, 119, 94, + 183, 225, 59, 139, 86, 178, 212, 50, 115, 117, 246, 0, 126, 119, + 233, 207, 63, 247, 49, 187, 93, 244, 132, 74, 22, 119, 248, 61, + 77, 141, 9, 45, 177, 78, 2, 56, 158, 210, 198, 247, 108, 242, + 54, 227, 179, 185, 187, 238, 218, 95, 233, 131, 0, 138, 142, 175, + 57, 184, 80, 89, 45, 175, 68, 135, 117, 171, 63, 89, 62, 122, + 114, 237, 139, 108, 25, 2, 182, 198, 229, 177, 240, 194, 127, 16, + 227, 59, 119, 85, 77, 1, 117, 7, 145, 91, 54, 118, 215, 117, + 58, 0, 33, 159, 172, 22, 77, 121, 226, 143, 135, 146, 135, 142, + 107, 55, 138, 61, 34, 112, 112, 19, 210, 202, 249, 145, 12, 92, + 176, 167, 164, 84, 230, 180, 18, 49, 159, 102, 167, 120, 22, 87, + 161, 221, 211, 104, 81, 80, 16, 104, 60, 14, 73, 151, 139, 19, + 68, 51, 72, 207, 63, 64, 213, 58, 55, 21, 204, 252, 92, 237, + 173, 58, 207, 179, 241, 209, 144, 172, 46, 185, 146, 6, 112, 65, + 65, 159, 185, 82, 202, 76, 75, 182, 174, 85, 185, 96, 219, 75, + 123, 248, 138, 11, 55, 210, 19, 114, 208, 243, 220, 86, 141, 4, + 161, 178, 93, 144, 94, 166, 8, 196, 53, 90, 104, 46, 112, 234, + 209, 72, 152, 81, 199, 151, 87, 60, 113, 96, 31, 144, 11, 93, + 244, 84, 156, 177, 139, 189, 115, 146, 193, 36, 156, 79, 127, 47, + 227, 145, 123, 54, 5, 238, 220, 96, 155, 65, 156, 31, 194, 143, + 30, 18, 30, 102, 246, 219, 118, 93, 255, 91, 173, 137, 124, 207, + 14, 59, 16, 185, 16, 60, 20, 249, 207, 122, 197, 240, 128, 148, + 246, 150, 26, 191, 69, 182, 218, 65, 171, 86, 189, 167, 125, 26, + 93, 44, 141, 126, 224, 86, 27, 5, 229, 104, 160, 76, 212, 201, + 28, 172, 74, 107, 101, 139, 70, 101, 102, 102, 109, 231, 150, 142, + 178, 66, 242, 174, 95, 238, 171, 50, 124, 96, 154, 222, 120, 148, + 174, 29, 49, 99, 159, 198, 103, 60, 51, 145, 153, 25, 212, 16, + 9, 253, 228, 96, 243, 43, 192, 43, 77, 17, 174, 35, 142, 11, + 132, 17, 35, 43, 88, 25, 69, 135, 136, 105, 67, 211, 18, 205, + 140, 81, 5, 252, 69, 31, 160, 126, 87, 187, 59, 195, 130, 112, + 25, 230, 193, 84, 160, 19, 28, 166, 89, 15, 48, 90, 149, 11, + 228, 212, 26, 159, 147, 163, 38, 119, 3, 65, 246, 107, 215, 238, + 38, 103, 243, 34, 247, 239, 36, 90, 193, 209, 167, 77, 80, 69, + 226, 95, 103, 135, 31, 215, 121, 27, 87, 242, 208, 10, 67, 240, + 179, 65, 153, 94, 66, 53, 12, 64, 2, 208, 230, 199, 30, 217, + 118, 137, 133, 25, 95, 60, 163, 6, 202, 51, 73, 211, 198, 80, + 89, 17, 225, 110, 160, 248, 92, 147, 251, 27, 32, 23, 46, 247, + 186, 69, 199, 125, 75, 20, 232, 220, 144, 230, 171, 85, 74, 135, + 51, 40, 52, 30, 212, 46, 140, 159, 121, 3, 95, 153, 45, 77, + 151, 78, 13, 151, 189, 139, 108, 160, 73, 57, 25, 118, 26, 27, + 179, 7, 206, 211, 10, 190, 225, 231, 114, 229, 219, 193, 19, 84, + 205, 153, 92, 140, 142, 41, 105, 174, 146, 114, 155, 167, 199, 173, + 223, 144, 249, 55, 112, 142, 13, 209, 155, 85, 51, 229, 190, 119, + 111, 109, 161, 150, 227, 255, 29, 50, 34, 26, 125, 203, 149, 25, + 151, 230, 22, 120, 15, 58, 165, 197, 101, 153, 254, 151, 192, 34, + 113, 242, 173, 163, 197, 87, 123, 189, 10, 7, 214, 71, 111, 172, + 12, 241, 217, 33, 48, 93, 48, 176, 227, 195, 248, 231, 195, 140, + 17, 163, 133, 123, 38, 0, 72, 47, 174, 62, 239, 13, 192, 88, + 12, 70, 34, 137, 187, 171, 77, 27, 254, 250, 87, 172, 36, 65, + 34, 15, 61, 201, 188, 170, 124, 41, 68, 25, 152, 230, 26, 82, + 164, 45, 224, 247, 64, 4, 55, 157, 119, 160, 56, 160, 255, 11, + 237, 82, 164, 0, 75, 77, 213, 177, 55, 236, 173, 22, 119, 172, + 167, 204, 238, 116, 180, 162, 59, 242, 204, 38, 62, 228, 108, 8, + 180, 221, 47, 43, 12, 180, 171, 124, 51, 188, 186, 156, 55, 228, + 160, 15, 245, 118, 241, 238, 159, 152, 139, 148, 223, 52, 209, 211, + 16, 34, 164, 65, 160, 167, 129, 235, 14, 181, 55, 122, 238, 25, + 83, 137, 50, 147, 7, 24, 49, 202, 109, 218, 46, 163, 216, 189, + 88, 236, 167, 80, 146, 66, 88, 244, 164, 123, 40, 0, 186, 43, + 204, 56, 20, 185, 23, 238, 30, 103, 148, 180, 91, 185, 3, 146, + 222, 54, 183, 141, 226, 37, 159, 36, 49, 76, 133, 178, 167, 194, + 27, 183, 90, 183, 72, 123, 104, 226, 255, 244, 181, 111, 9, 16, + 163, 185, 76, 249, 12, 222, 41, 73, 2, 75, 80, 212, 101, 187, + 254, 99, 91, 166, 15, 48, 148, 241, 224, 7, 174, 98, 254, 194, + 20, 94, 178, 57, 141, 114, 247, 207, 197, 248, 189, 67, 107, 214, + 200, 22, 215, 238, 192, 145, 217, 197, 23, 94, 7, 36, 176, 120, + 214, 63, 119, 172, 77, 248, 226, 223, 69, 203, 189, 243, 129, 233, + 222, 255, 231, 16, 194, 156, 131, 89, 87, 56, 114, 243, 159, 52, + 33, 151, 249, 71, 50, 60, 192, 98, 243, 26, 90, 113, 73, 45, + 156, 18, 48, 13, 102, 221, 53, 247, 181, 248, 98, 143, 198, 152, + 205, 144, 41, 243, 206, 142, 114, 31, 13, 245, 152, 71, 105, 227, + 192, 242, 131, 139, 230, 192, 56, 231, 105, 187, 12, 83, 115, 38, + 220, 124, 97, 7, 107, 156, 68, 243, 4, 184, 141, 96, 110, 34, + 14, 96, 196, 15, 47, 104, 73, 59, 240, 52, 75, 178, 142, 12, + 74, 166, 80, 152, 233, 199, 137, 127, 28, 190, 155, 101, 100, 129, + 73, 247, 186, 108, 71, 255, 111, 206, 156, 11, 249, 31, 67, 198, + 55, 65, 130, 68, 85, 203, 26, 22, 125, 231, 7, 31, 99, 160, + 26, 98, 20, 7, 14, 148, 112, 156, 47, 28, 83, 209, 197, 203, + 131, 86, 135, 219, 10, 189, 127, 117, 97, 60, 123, 252, 143, 240, + 104, 242, 213, 251, 212, 15, 95, 81, 147, 192, 49, 109, 143, 176, + 244, 101, 82, 203, 191, 235, 29, 67, 115, 213, 245, 44, 104, 160, + 45, 138, 17, 137, 159, 85, 36, 122, 176, 11, 62, 163, 2, 238, + 240, 90, 11, 3, 113, 76, 159, 20, 26, 159, 28, 86, 221, 148, + 15, 196, 242, 119, 117, 58, 69, 179, 64, 197, 83, 10, 163, 131, + 71, 2, 227, 211, 126, 225, 243, 90, 242, 105, 201, 68, 144, 45, + 117, 51, 84, 175, 249, 43, 204, 108, 216, 101, 35, 105, 180, 94, + 76, 76, 184, 27, 72, 32, 157, 244, 2, 245, 136, 44, 116, 137, + 45, 200, 32, 202, 50, 13, 38, 117, 186, 27, 115, 8, 41, 134, + 120, 199, 175, 154, 3, 102, 213, 18, 241, 111, 34, 56, 11, 16, + 190, 42, 23, 26, 83, 7, 212, 255, 118, 215, 254, 130, 223, 197, + 122, 14, 197, 23, 118, 229, 67, 121, 101, 190, 138, 24, 137, 165, + 234, 183, 40, 226, 91, 26, 251, 169, 172, 147, 175, 105, 68, 76, + 226, 178, 92, 141, 84, 63, 100, 89, 137, 236, 52, 222, 37, 251, + 237, 24, 75, 230, 140, 64, 110, 165, 112, 3, 30, 4, 40, 8, + 213, 185, 240, 88, 175, 47, 4, 208, 3, 244, 83, 177, 50, 219, + 172, 42, 178, 137, 172, 111, 58, 80, 192, 42, 18, 197, 221, 8, + 211, 71, 111, 176, 196, 33, 177, 239, 179, 172, 231, 195, 211, 12, + 198, 183, 116, 201, 31, 102, 166, 86, 18, 138, 2, 26, 115, 124, + 237, 129, 137, 255, 213, 186, 102, 37, 156, 171, 255, 97, 28, 16, + 67, 75, 64, 244, 185, 90, 67, 44, 54, 201, 53, 75, 198, 69, + 86, 7, 143, 105, 189, 236, 228, 34, 132, 253, 58, 50, 100, 156, + 81, 75, 108, 29, 129, 197, 35, 131, 221, 206, 229, 88, 219, 131, + 48, 135, 28, 45, 74, 69, 182, 149, 231, 25, 149, 167, 32, 28, + 40, 112, 43, 107, 69, 172, 31, 246, 221, 33, 82, 247, 145, 80, + 231, 105, 8, 238, 24, 232, 28, 44, 139, 113, 175, 58, 182, 121, + 231, 148, 23, 166, 230, 70, 26, 20, 108, 211, 147, 242, 6, 143, + 247, 44, 208, 18, 238, 184, 131, 212, 212, 173, 213, 233, 229, 152, + 80, 83, 16, 242, 38, 175, 6, 138, 106, 224, 164, 211, 217, 61, + 51, 135, 239, 180, 217, 189, 223, 249, 27, 112, 9, 65, 28, 141, + 209, 14, 140, 89, 180, 118, 25, 248, 154, 193, 152, 216, 217, 162, + 247, 172, 239, 78, 40, 231, 217, 60, 57, 68, 12, 137, 64, 51, + 142, 30, 187, 153, 58, 130, 98, 95, 32, 83, 130, 77, 75, 204, + 157, 80, 218, 232, 78, 99, 130, 200, 125, 47, 4, 52, 151, 64, + 194, 234, 90, 15, 229, 32, 30, 169, 239, 168, 39, 50, 101, 182, + 156, 220, 242, 8, 104, 253, 212, 231, 7, 39, 125, 153, 71, 55, + 59, 70, 164, 244, 168, 230, 214, 66, 148, 96, 9, 74, 243, 164, + 125, 86, 20, 63, 17, 65, 223, 163, 193, 100, 183, 133, 45, 119, + 221, 0, 89, 194, 204, 138, 159, 6, 247, 251, 159, 30, 180, 161, + 159, 215, 167, 199, 59, 150, 53, 28, 105, 153, 177, 250, 97, 182, + 89, 239, 146, 142, 7, 249, 143, 244, 65, 179, 248, 213, 134, 240, + 159, 174, 111, 179, 173, 106, 197, 234, 103, 42, 114, 158, 244, 197, + 70, 243, 208, 73, 135, 208, 217, 136, 155, 250, 15, 174, 66, 224, + 18, 88, 134, 154, 229, 211, 60, 153, 34, 149, 66, 142, 5, 196, + 100, 189, 94, 141, 180, 6, 75, 121, 185, 215, 146, 162, 202, 163, + 58, 208, 113, 242, 55, 78, 112, 99, 43, 42, 163, 77, 241, 221, + 121, 186, 122, 209, 0, 128, 251, 17, 41, 82, 107, 66, 225, 128, + 197, 133, 118, 241, 112, 102, 143, 91, 175, 158, 179, 237, 183, 12, + 233, 193, 98, 207, 219, 240, 105, 226, 131, 89, 98, 249, 109, 155, + 40, 38, 34, 250, 45, 150, 141, 25, 67, 252, 112, 44, 219, 222, + 99, 216, 168, 243, 82, 61, 176, 7, 43, 219, 161, 164, 108, 40, + 73, 241, 159, 236, 59, 76, 219, 157, 158, 207, 6, 67, 211, 120, + 1, 107, 218, 197, 54, 209, 221, 98, 124, 84, 167, 79, 81, 241, + 110, 153, 70, 7, 8, 146, 70, 43, 143, 19, 93, 134, 82, 105, + 47, 179, 218, 85, 139, 243, 70, 202, 26, 84, 24, 114, 115, 175, + 119, 38, 38, 96, 168, 219, 65, 41, 178, 186, 99, 33, 107, 253, + 241, 234, 89, 181, 7, 32, 155, 219, 99, 47, 223, 40, 172, 91, + 135, 224, 89, 243, 67, 115, 197, 178, 96, 1, 109, 150, 39, 223, + 87, 118, 23, 227, 230, 185, 97, 221, 171, 232, 67, 153, 222, 74, + 79, 71, 225, 206, 218, 172, 20, 139, 77, 86, 249, 80, 28, 77, + 42, 147, 116, 235, 34, 9, 105, 193, 247, 77, 87, 210, 200, 211, + 78, 148, 232, 203, 55, 227, 31, 230, 108, 212, 97, 124, 151, 1, + 11, 39, 197, 52, 56, 173, 134, 247, 21, 199, 252, 168, 107, 96, + 36, 40, 178, 145, 216, 36, 35, 23, 119, 30, 59, 143, 70, 102, + 233, 51, 200, 198, 248, 3, 143, 121, 80, 60, 233, 241, 203, 225, + 150, 147, 60, 15, 72, 241, 115, 177, 224, 65, 90, 39, 196, 146, + 192, 65, 227, 105, 93, 186, 220, 177, 240, 147, 8, 108, 78, 167, + 92, 86, 220, 40, 105, 117, 189, 123, 32, 210, 174, 226, 175, 255, + 245, 98, 103, 177, 214, 57, 187, 91, 183, 163, 47, 213, 173, 131, + 68, 255, 115, 193, 96, 88, 237, 48, 104, 176, 199, 59, 164, 72, + 245, 150, 223, 156, 243, 78, 193, 221, 133, 122, 57, 198, 14, 119, + 55, 13, 105, 136, 55, 119, 126, 38, 251, 208, 56, 55, 2, 198, + 145, 194, 168, 170, 189, 118, 140, 119, 177, 176, 7, 150, 25, 107, + 41, 213, 91, 114, 229, 155, 37, 232, 163, 208, 26, 246, 84, 107, + 251, 117, 252, 211, 129, 201, 220, 91, 115, 209, 254, 91, 203, 221, + 220, 106, 134, 235, 202, 89, 251, 0, 44, 188, 242, 11, 191, 231, + 202, 58, 157, 124, 186, 42, 16, 254, 3, 106, 64, 174, 204, 110, + 67, 107, 229, 189, 3, 184, 155, 50, 198, 239, 76, 59, 143, 121, + 0, 175, 53, 114, 32, 243, 17, 104, 43, 71, 77, 230, 152, 235, + 226, 230, 45, 164, 246, 105, 134, 66, 166, 184, 46, 233, 110, 91, + 26, 104, 192, 38, 69, 141, 230, 189, 38, 132, 151, 212, 95, 206, + 13, 104, 248, 115, 204, 107, 240, 117, 104, 232, 76, 45, 156, 152, + 209, 146, 141, 97, 224, 124, 82, 158, 229, 56, 95, 119, 201, 138, + 75, 219, 134, 30, 62, 140, 218, 134, 92, 248, 120, 151, 252, 242, + 27, 92, 78, 225, 129, 186, 88, 236, 88, 249, 168, 185, 228, 161, + 241, 53, 164, 33, 225, 133, 86, 54, 207, 122, 152, 51, 173, 136, + 184, 252, 101, 142, 245, 213, 251, 178, 102, 45, 88, 41, 188, 209, + 48, 250, 124, 255, 62, 155, 163, 113, 146, 233, 135, 138, 144, 231, + 198, 27, 49, 106, 70, 98, 170, 53, 217, 54, 116, 12, 83, 158, + 101, 100, 26, 105, 189, 225, 227, 52, 205, 222, 229, 52, 242, 99, + 85, 55, 39, 167, 208, 166, 92, 136, 97, 39, 141, 169, 247, 163, + 184, 129, 43, 77, 96, 239, 72, 112, 197, 34, 176, 16, 23, 235, + 166, 181, 255, 201, 219, 37, 176, 45, 77, 125, 239, 203, 43, 9, + 20, 1, 72, 87, 73, 73, 98, 16, 222, 241, 89, 128, 60, 77, + 38, 107, 84, 44, 59, 136, 26, 244, 250, 220, 174, 183, 243, 144, + 174, 120, 57, 25, 172, 119, 170, 160, 181, 163, 102, 46, 103, 155, + 143, 207, 50, 238, 238, 39, 224, 250, 5, 223, 143, 245, 69, 149, + 205, 167, 208, 175, 181, 25, 28, 92, 204, 200, 203, 57, 104, 232, + 36, 52, 218, 82, 26, 31, 237, 248, 43, 234, 7, 208, 194, 14, + 164, 178, 75, 202, 123, 39, 161, 122, 4, 84, 230, 149, 153, 100, + 135, 14, 207, 203, 9, 183, 92, 160, 211, 45, 50, 217, 247, 86, + 16, 105, 85, 10, 27, 213, 223, 3, 64, 101, 1, 206, 53, 19, + 24, 105, 52, 68, 220, 80, 246, 232, 118, 186, 39, 56, 26, 51, + 155, 173, 83, 183, 85, 124, 112, 26, 206, 218, 151, 100, 245, 110, + 224, 8, 105, 37, 113, 248, 84, 104, 204, 245, 159, 70, 108, 11, + 100, 13, 136, 248, 118, 97, 6, 144, 189, 65, 4, 92, 254, 73, + 195, 124, 151, 5, 101, 246, 35, 78, 110, 75, 158, 243, 138, 63, + 82, 237, 145, 145, 130, 193, 179, 137, 77, 141, 205, 142, 191, 232, + 127, 43, 216, 131, 49, 68, 63, 138, 94, 145, 177, 83, 223, 176, + 214, 40, 3, 166, 13, 82, 62, 104, 241, 92, 209, 159, 52, 161, + 11, 187, 252, 21, 103, 227, 195, 117, 242, 236, 247, 61, 127, 32, + 24, 191, 126, 127, 237, 247, 2, 28, 213, 174, 250, 174, 105, 182, + 75, 1, 213, 116, 103, 68, 78, 4, 178, 229, 78, 242, 99, 241, + 129, 137, 162, 221, 225, 101, 134, 121, 56, 128, 242, 132, 29, 88, + 24, 39, 99, 152, 112, 125, 239, 183, 52, 72, 137, 97, 50, 85, + 68, 162, 161, 108, 220, 137, 210, 150, 149, 208, 217, 16, 251, 193, + 156, 96, 9, 144, 11, 41, 2, 43, 118, 166, 245, 163, 33, 174, + 190, 155, 197, 65, 9, 136, 149, 151, 194, 6, 149, 226, 188, 94, + 122, 111, 79, 201, 137, 104, 203, 62, 14, 136, 18, 49, 142, 148, + 34, 106, 202, 36, 69, 44, 136, 156, 68, 77, 209, 144, 27, 72, + 213, 69, 78, 163, 243, 143, 229, 202, 144, 208, 173, 3, 126, 50, + 156, 93, 153, 86, 136, 230, 94, 211, 89, 1, 169, 125, 199, 166, + 24, 158, 154, 206, 141, 179, 59, 79, 180, 120, 54, 208, 202, 79, + 81, 41, 33, 21, 132, 36, 34, 180, 156, 207, 112, 227, 120, 182, + 110, 59, 136, 42, 192, 134, 153, 84, 188, 126, 232, 137, 95, 83, + 77, 4, 37, 191, 191, 236, 90, 100, 250, 155, 160, 231, 107, 255, + 107, 230, 155, 145, 50, 17, 92, 145, 138, 86, 225, 196, 219, 182, + 66, 19, 121, 235, 75, 105, 79, 152, 43, 109, 100, 120, 51, 26, + 58, 49, 177, 234, 36, 36, 146, 27, 1, 189, 38, 82, 66, 40, + 0, 16, 138, 19, 152, 30, 203, 168, 162, 55, 4, 203, 125, 110, + 47, 164, 134, 149, 79, 245, 180, 97, 80, 251, 58, 167, 43, 168, + 1, 185, 102, 133, 70, 22, 69, 101, 180, 103, 66, 38, 169, 133, + 80, 172, 59, 11, 15, 141, 0, 183, 223, 126, 230, 163, 192, 92, + 132, 169, 218, 121, 176, 196, 185, 206, 124, 54, 76, 161, 91, 17, + 245, 227, 74, 232, 158, 147, 133, 6, 15, 135, 205, 33, 16, 221, + 138, 132, 20, 26, 244, 199, 197, 19, 87, 16, 176, 192, 129, 126, + 211, 62, 215, 116, 24, 246, 115, 242, 197, 76, 26, 190, 20, 15, + 67, 78, 151, 89, 160, 101, 180, 246, 255, 93, 9, 227, 50, 95, + 224, 92, 109, 15, 249, 253, 187, 217, 115, 35, 168, 163, 88, 162, + 225, 23, 88, 137, 138, 197, 248, 47, 61, 46, 222, 20, 113, 53, + 203, 108, 44, 115, 97, 12, 247, 48, 147, 159, 142, 48, 61, 77, + 230, 218, 118, 230, 188, 47, 177, 85, 12, 75, 78, 230, 93, 67, + 119, 238, 251, 143, 16, 70, 99, 228, 251, 195, 248, 171, 81, 68, + 161, 153, 67, 108, 92, 55, 118, 250, 72, 243, 168, 234, 146, 245, + 201, 83, 86, 181, 219, 242, 253, 244, 18, 81, 96, 214, 191, 15, + 12, 152, 40, 91, 202, 135, 69, 245, 66, 193, 242, 219, 247, 38, + 169, 167, 174, 48, 119, 233, 218, 4, 102, 33, 153, 14, 171, 239, + 234, 127, 239, 221, 8, 40, 48, 135, 139, 160, 87, 142, 36, 153, + 109, 43, 13, 18, 22, 74, 47, 199, 158, 112, 49, 148, 225, 72, + 168, 144, 65, 183, 94, 220, 50, 203, 16, 98, 198, 147, 101, 135, + 213, 170, 7, 2, 90, 223, 28, 94, 210, 160, 21, 112, 14, 1, + 176, 255, 40, 189, 11, 167, 224, 199, 29, 180, 134, 212, 198, 170, + 168, 49, 12, 219, 215, 217, 43, 106, 29, 47, 82, 112, 189, 84, + 210, 247, 145, 73, 49, 27, 134, 98, 46, 21, 91, 223, 130, 224, + 80, 216, 54, 98, 54, 70, 78, 164, 96, 75, 171, 203, 76, 194, + 127, 181, 215, 209, 9, 241, 8, 253, 103, 181, 127, 246, 130, 247, + 47, 200, 204, 41, 108, 223, 102, 214, 89, 98, 185, 167, 116, 177, + 46, 119, 46, 26, 111, 8, 176, 1, 241, 135, 187, 143, 44, 93, + 23, 71, 14, 35, 3, 166, 118, 237, 235, 22, 9, 212, 16, 84, + 208, 132, 35, 178, 31, 13, 102, 181, 75, 158, 77, 238, 217, 179, + 229, 89, 38, 183, 78, 50, 15, 16, 103, 22, 8, 188, 185, 15, + 224, 86, 17, 218, 27, 218, 19, 150, 34, 95, 92, 106, 225, 111, + 36, 177, 171, 52, 63, 196, 129, 157, 181, 228, 156, 53, 160, 71, + 69, 191, 100, 138, 194, 79, 143, 70, 88, 60, 115, 224, 74, 143, + 177, 60, 183, 219, 143, 197, 51, 225, 240, 1, 13, 153, 22, 206, + 170, 166, 30, 239, 81, 212, 175, 99, 72, 82, 200, 239, 24, 230, + 251, 200, 41, 165, 164, 217, 19, 48, 105, 99, 239, 163, 175, 89, + 240, 64, 248, 30, 113, 58, 230, 16, 79, 127, 48, 193, 33, 174, + 14, 54, 18, 189, 144, 120, 11, 132, 42, 49, 80, 178, 234, 78, + 241, 241, 223, 37, 248, 171, 171, 95, 223, 183, 138, 93, 79, 89, + 254, 51, 156, 210, 69, 122, 52, 65, 43, 78, 202, 250, 4, 188, + 69, 52, 202, 184, 63, 109, 235, 193, 45, 18, 175, 86, 209, 151, + 14, 186, 250, 49, 241, 249, 143, 56, 49, 185, 235, 179, 91, 42, + 130, 152, 137, 9, 192, 79, 203, 38, 194, 36, 149, 2, 65, 134, + 86, 97, 230, 5, 232, 18, 19, 184, 57, 27, 253, 230, 19, 152, + 38, 31, 133, 106, 94, 140, 224, 160, 120, 91, 88, 190, 95, 158, + 184, 12, 186, 209, 113, 211, 72, 154, 226, 4, 23, 112, 212, 88, + 62, 226, 100, 16, 96, 159, 246, 188, 161, 20, 159, 64, 118, 78, + 94, 147, 156, 0, 160, 5, 5, 62, 224, 169, 131, 19, 161, 187, + 183, 112, 90, 67, 251, 73, 188, 234, 88, 83, 255, 105, 18, 16, + 15, 174, 168, 42, 173, 24, 95, 186, 11, 13, 47, 149, 231, 40, + 73, 248, 0, 87, 239, 202, 173, 15, 184, 211, 156, 88, 53, 111, + 68, 224, 207, 176, 6, 85, 42, 150, 155, 22, 192, 146, 164, 139, + 48, 120, 88, 245, 133, 25, 148, 71, 26, 52, 83, 16, 95, 33, + 56, 237, 128, 58, 248, 218, 152, 153, 148, 87, 167, 232, 167, 74, + 131, 62, 151, 75, 103, 252, 18, 14, 148, 155, 116, 172, 244, 17, + 135, 95, 165, 146, 28, 10, 216, 17, 113, 117, 207, 162, 59, 23, + 31, 49, 227, 92, 154, 102, 36, 88, 108, 134, 204, 87, 65, 48, + 195, 68, 15, 120, 146, 107, 54, 246, 218, 245, 160, 33, 160, 29, + 54, 43, 222, 134, 1, 241, 190, 153, 243, 4, 69, 46, 7, 229, + 143, 246, 138, 250, 138, 77, 212, 206, 68, 108, 65, 197, 108, 161, + 38, 85, 169, 21, 130, 96, 10, 44, 216, 14, 186, 45, 148, 211, + 47, 46, 246, 84, 217, 214, 88, 187, 76, 5, 122, 228, 2, 203, + 139, 204, 215, 233, 82, 185, 162, 20, 29, 240, 50, 141, 180, 36, + 234, 154, 137, 22, 76, 131, 153, 174, 182, 101, 23, 162, 115, 191, + 228, 14, 88, 121, 125, 141, 39, 19, 224, 219, 136, 109, 4, 10, + 63, 136, 199, 172, 151, 3, 217, 53, 145, 77, 246, 66, 221, 235, + 52, 246, 243, 161, 100, 96, 203, 46, 73, 217, 195, 161, 212, 155, + 170, 148, 234, 234, 36, 167, 239, 241, 243, 128, 176, 201, 40, 55, + 84, 235, 143, 2, 8, 146, 95, 57, 63, 217, 112, 228, 202, 115, + 59, 113, 138, 8, 174, 64, 102, 229, 75, 116, 171, 3, 125, 157, + 219, 183, 1, 25, 162, 49, 178, 126, 48, 214, 209, 109, 76, 142, + 116, 53, 118, 43, 135, 11, 5, 209, 113, 125, 116, 3, 144, 29, + 115, 77, 89, 206, 185, 82, 19, 119, 108, 42, 43, 244, 184, 194, + 20, 112, 232, 7, 203, 223, 215, 199, 126, 244, 219, 7, 221, 59, + 233, 218, 9, 131, 169, 78, 7, 29, 89, 236, 168, 98, 59, 19, + 202, 214, 49, 196, 168, 237, 218, 65, 239, 168, 213, 18, 201, 200, + 148, 89, 0, 242, 118, 185, 180, 137, 11, 75, 43, 103, 20, 216, + 128, 20, 88, 133, 190, 249, 132, 134, 100, 60, 234, 156, 76, 189, + 78, 76, 11, 111, 158, 239, 178, 179, 79, 68, 143, 73, 49, 126, + 248, 78, 156, 97, 218, 70, 161, 203, 211, 190, 224, 114, 64, 224, + 31, 95, 140, 148, 58, 162, 84, 180, 151, 189, 205, 116, 174, 147, + 228, 60, 69, 253, 22, 143, 139, 158, 6, 237, 135, 235, 2, 40, + 23, 179, 78, 5, 154, 255, 183, 41, 138, 243, 87, 91, 40, 109, + 134, 153, 123, 253, 139, 99, 54, 221, 125, 71, 23, 246, 25, 118, + 50, 18, 119, 64, 215, 124, 86, 214, 136, 172, 64, 197, 254, 3, + 182, 190, 223, 174, 44, 44, 203, 247, 252, 53, 25, 173, 225, 134, + 142, 41, 215, 209, 68, 182, 21, 247, 117, 20, 60, 118, 44, 48, + 60, 156, 5, 170, 7, 139, 249, 85, 66, 148, 153, 27, 135, 223, + 51, 161, 166, 47, 162, 143, 167, 111, 215, 219, 140, 200, 93, 14, + 64, 8, 55, 204, 142, 152, 33, 154, 212, 149, 53, 160, 58, 122, + 44, 140, 18, 100, 126, 4, 217, 211, 238, 222, 8, 167, 217, 195, + 209, 104, 110, 151, 132, 239, 133, 44, 101, 208, 121, 202, 62, 156, + 6, 168, 65, 76, 184, 240, 208, 79, 221, 208, 129, 120, 165, 15, + 173, 49, 74, 149, 59, 17, 70, 155, 201, 84, 19, 238, 21, 65, + 210, 125, 137, 153, 43, 34, 80, 215, 116, 96, 199, 133, 140, 56, + 57, 224, 39, 179, 230, 56, 149, 202, 107, 104, 220, 203, 0, 249, + 100, 3, 4, 71, 121, 246, 228, 236, 21, 200, 23, 190, 232, 167, + 28, 134, 201, 115, 0, 178, 32, 113, 36, 146, 76, 188, 1, 16, + 87, 78, 55, 181, 160, 142, 15, 158, 41, 192, 81, 64, 31, 70, + 71, 191, 82, 144, 210, 155, 24, 254, 236, 93, 176, 151, 192, 188, + 255, 131, 42, 14, 208, 113, 139, 75, 123, 37, 142, 160, 186, 1, + 62, 65, 209, 135, 201, 29, 219, 85, 38, 13, 188, 126, 185, 96, + 151, 118, 221, 156, 39, 136, 37, 134, 213, 74, 20, 207, 194, 191, + 192, 220, 239, 122, 147, 102, 38, 136, 244, 86, 85, 193, 183, 238, + 10, 201, 27, 173, 41, 175, 208, 244, 9, 141, 204, 14, 171, 49, + 58, 180, 182, 118, 40, 181, 254, 238, 183, 192, 216, 234, 32, 130, + 108, 111, 81, 6, 106, 121, 138, 111, 148, 47, 139, 213, 93, 92, + 83, 127, 48, 112, 233, 22, 56, 192, 174, 72, 178, 216, 100, 230, + 142, 211, 214, 68, 121, 75, 192, 152, 132, 238, 91, 76, 68, 62, + 65, 173, 149, 255, 60, 169, 18, 49, 44, 13, 46, 106, 68, 63, + 58, 172, 239, 177, 63, 172, 28, 23, 88, 69, 234, 169, 253, 177, + 170, 101, 149, 201, 188, 164, 72, 206, 92, 5, 116, 60, 82, 151, + 64, 34, 67, 68, 66, 124, 252, 166, 56, 92, 106, 238, 182, 14, + 226, 217, 240, 208, 194, 183, 36, 118, 243, 147, 71, 72, 5, 212, + 190, 230, 205, 47, 210, 243, 42, 156, 56, 235, 69, 122, 221, 245, + 254, 70, 251, 222, 140, 97, 111, 124, 75, 40, 228, 4, 235, 136, + 190, 26, 36, 140, 110, 128, 221, 182, 164, 78, 45, 131, 70, 31, + 10, 230, 73, 208, 95, 20, 54, 104, 221, 174, 132, 133, 106, 62, + 136, 10, 225, 191, 168, 204, 115, 234, 65, 20, 124, 147, 205, 153, + 157, 194, 44, 163, 115, 185, 103, 197, 177, 250, 209, 154, 40, 32, + 222, 185, 54, 37, 222, 251, 238, 101, 120, 210, 87, 230, 4, 169, + 63, 120, 41, 76, 77, 139, 63, 124, 126, 215, 126, 4, 103, 80, + 40, 66, 213, 98, 188, 66, 174, 202, 254, 249, 37, 136, 118, 0, + 172, 18, 144, 195, 54, 143, 245, 105, 58, 111, 117, 255, 61, 63, + 158, 249, 81, 157, 180, 58, 110, 190, 157, 165, 30, 120, 72, 238, + 202, 23, 104, 26, 224, 100, 79, 19, 57, 245, 146, 246, 210, 214, + 58, 231, 13, 22, 2, 97, 134, 18, 69, 57, 128, 132, 235, 127, + 185, 64, 230, 139, 172, 164, 213, 116, 3, 199, 194, 33, 119, 148, + 221, 255, 80, 42, 15, 107, 93, 202, 182, 84, 186, 201, 168, 95, + 100, 112, 62, 89, 186, 181, 165, 196, 8, 8, 152, 89, 37, 189, + 12, 59, 180, 120, 93, 231, 58, 62, 59, 123, 104, 151, 129, 206, + 71, 43, 73, 185, 169, 221, 10, 187, 211, 38, 135, 25, 48, 159, + 147, 182, 80, 87, 19, 46, 0, 242, 164, 106, 48, 149, 5, 219, + 98, 28, 79, 87, 125, 177, 189, 215, 103, 102, 100, 135, 196, 225, + 75, 82, 254, 29, 245, 13, 63, 6, 14, 46, 215, 62, 231, 230, + 222, 250, 155, 31, 214, 167, 92, 11, 187, 116, 122, 183, 64, 42, + 97, 157, 171, 192, 174, 190, 233, 235, 1, 253, 184, 182, 116, 103, + 63, 202, 10, 225, 119, 191, 110, 147, 125, 55, 120, 12, 67, 49, + 34, 163, 179, 217, 71, 170, 223, 135, 164, 97, 232, 8, 9, 104, + 59, 58, 116, 41, 196, 135, 76, 155, 112, 135, 194, 169, 130, 245, + 94, 217, 11, 140, 33, 172, 100, 137, 2, 171, 65, 153, 139, 52, + 94, 30, 165, 227, 102, 195, 211, 46, 238, 155, 167, 166, 42, 89, + 14, 22, 191, 237, 207, 101, 59, 24, 47, 54, 82, 222, 42, 39, + 152, 197, 49, 126, 69, 32, 230, 125, 171, 164, 245, 142, 113, 184, + 226, 17, 220, 150, 161, 161, 151, 78, 60, 245, 225, 55, 126, 215, + 229, 149, 58, 237, 2, 227, 186, 159, 234, 1, 92, 253, 77, 248, + 224, 252, 111, 66, 73, 2, 57, 113, 176, 28, 230, 17, 178, 150, + 199, 178, 62, 130, 107, 51, 142, 72, 17, 177, 27, 76, 57, 244, + 171, 99, 225, 112, 141, 242, 249, 189, 211, 198, 145, 38, 204, 31, + 189, 234, 58, 62, 46, 77, 177, 174, 83, 4, 78, 143, 98, 109, + 146, 193, 123, 220, 93, 170, 10, 108, 20, 13, 96, 57, 96, 25, + 74, 74, 71, 165, 192, 238, 215, 105, 36, 75, 143, 141, 83, 243, + 235, 73, 208, 212, 212, 192, 45, 66, 103, 203, 150, 54, 61, 24, + 48, 83, 251, 226, 28, 155, 26, 5, 206, 88, 91, 25, 104, 159, + 98, 182, 17, 106, 107, 90, 21, 84, 11, 194, 242, 53, 108, 247, + 193, 36, 114, 229, 40, 45, 159, 77, 110, 187, 74, 178, 189, 209, + 67, 203, 8, 242, 138, 58, 116, 151, 28, 47, 91, 157, 170, 170, + 62, 26, 34, 100, 0, 23, 17, 210, 180, 158, 30, 201, 85, 11, + 139, 75, 85, 81, 76, 180, 95, 168, 69, 84, 82, 59, 187, 80, + 136, 137, 174, 17, 125, 24, 225, 220, 255, 248, 1, 235, 218, 150, + 3, 23, 132, 165, 144, 100, 248, 245, 178, 247, 0, 116, 73, 63, + 105, 163, 30, 162, 211, 244, 248, 215, 48, 159, 234, 223, 239, 175, + 25, 212, 137, 218, 86, 26, 110, 56, 149, 134, 19, 39, 244, 194, + 28, 225, 68, 176, 64, 189, 190, 242, 126, 112, 118, 88, 234, 221, + 73, 96, 183, 54, 110, 17, 209, 29, 252, 108, 18, 169, 22, 226, + 68, 167, 8, 7, 188, 85, 62, 137, 187, 151, 45, 181, 204, 31, + 250, 113, 63, 224, 227, 40, 195, 254, 49, 109, 162, 230, 7, 207, + 52, 99, 143, 222, 163, 178, 161, 36, 123, 48, 168, 203, 162, 78, + 216, 183, 91, 93, 149, 245, 114, 109, 173, 33, 20, 120, 255, 239, + 237, 139, 66, 13, 115, 148, 134, 210, 254, 169, 57, 70, 115, 131, + 75, 231, 79, 146, 187, 126, 186, 89, 48, 194, 210, 245, 93, 217, + 145, 84, 13, 92, 234, 122, 39, 53, 49, 104, 182, 30, 169, 249, + 207, 11, 105, 110, 56, 255, 109, 30, 239, 85, 74, 64, 97, 176, + 70, 24, 22, 101, 41, 237, 153, 211, 167, 188, 183, 32, 43, 69, + 202, 197, 89, 39, 136, 211, 46, 170, 16, 24, 25, 224, 52, 38, + 126, 98, 79, 101, 33, 72, 27, 114, 28, 34, 98, 116, 144, 18, + 139, 233, 245, 100, 154, 159, 225, 239, 248, 90, 7, 203, 57, 97, + 185, 173, 235, 218, 202, 196, 63, 180, 201, 94, 191, 66, 177, 255, + 120, 63, 247, 189, 31, 91, 57, 45, 148, 197, 226, 90, 46, 238, + 41, 196, 244, 189, 243, 6, 151, 85, 149, 51, 138, 254, 203, 180, + 224, 145, 102, 121, 134, 70, 112, 9, 32, 112, 59, 59, 230, 56, + 29, 180, 174, 207, 192, 125, 137, 80, 143, 111, 148, 57, 214, 184, + 181, 179, 137, 5, 152, 41, 57, 119, 163, 244, 22, 171, 235, 14, + 146, 46, 78, 234, 45, 82, 176, 4, 94, 119, 3, 82, 187, 175, + 122, 158, 81, 107, 149, 56, 164, 227, 63, 3, 107, 183, 198, 139, + 154, 249, 25, 151, 43, 47, 227, 104, 33, 9, 196, 189, 228, 54, + 32, 89, 180, 9, 96, 214, 31, 39, 25, 152, 124, 51, 139, 184, + 38, 124, 161, 69, 189, 89, 139, 188, 85, 251, 49, 104, 163, 44, + 89, 193, 2, 80, 215, 79, 128, 188, 212, 69, 229, 101, 228, 227, + 66, 164, 220, 204, 243, 251, 212, 225, 165, 136, 112, 15, 84, 226, + 13, 109, 107, 192, 31, 245, 31, 120, 255, 11, 76, 165, 44, 248, + 86, 222, 172, 87, 212, 200, 203, 22, 244, 175, 227, 126, 31, 145, + 146, 220, 211, 22, 49, 182, 40, 37, 88, 207, 151, 25, 90, 14, + 204, 130, 197, 177, 107, 57, 112, 20, 164, 140, 130, 93, 249, 253, + 185, 63, 161, 219, 150, 139, 88, 3, 70, 86, 222, 170, 176, 25, + 214, 78, 222, 195, 136, 143, 231, 134, 82, 53, 176, 84, 52, 175, + 10, 118, 220, 202, 58, 25, 28, 85, 164, 16, 97, 42, 91, 140, + 86, 107, 63, 248, 9, 132, 200, 160, 201, 39, 11, 179, 0, 85, + 143, 156, 37, 232, 145, 218, 76, 10, 193, 180, 193, 208, 18, 92, + 216, 142, 109, 210, 238, 153, 166, 7, 186, 227, 158, 167, 42, 187, + 5, 134, 49, 231, 11, 227, 245, 209, 95, 117, 101, 223, 163, 30, + 229, 116, 56, 137, 248, 51, 57, 112, 54, 233, 50, 145, 204, 104, + 189, 112, 66, 29, 64, 54, 34, 14, 139, 7, 192, 29, 225, 158, + 92, 214, 214, 135, 118, 199, 102, 91, 18, 165, 46, 154, 112, 118, + 98, 184, 146, 241, 2, 217, 159, 171, 72, 22, 243, 224, 228, 97, + 47, 92, 233, 100, 100, 172, 134, 149, 57, 97, 128, 114, 253, 89, + 118, 204, 81, 189, 27, 207, 36, 195, 51, 58, 18, 157, 178, 4, + 73, 95, 114, 194, 206, 22, 195, 249, 63, 129, 13, 58, 173, 253, + 94, 161, 35, 227, 19, 64, 95, 249, 184, 151, 29, 40, 150, 31, + 75, 116, 117, 109, 90, 6, 35, 163, 192, 151, 117, 239, 150, 2, + 61, 83, 243, 123, 98, 245, 82, 235, 39, 10, 34, 91, 217, 68, + 130, 20, 179, 95, 97, 52, 217, 160, 151, 195, 159, 240, 170, 117, + 60, 54, 83, 12, 104, 108, 222, 219, 138, 165, 164, 46, 195, 99, + 61, 107, 106, 19, 215, 154, 188, 239, 59, 241, 78, 14, 118, 13, + 185, 21, 125, 97, 140, 45, 75, 89, 217, 118, 165, 26, 218, 98, + 247, 51, 131, 120, 186, 64, 148, 56, 194, 213, 117, 226, 138, 85, + 47, 162, 138, 43, 140, 176, 83, 8, 247, 230, 18, 81, 127, 201, + 214, 65, 59, 225, 72, 136, 147, 205, 250, 39, 35, 197, 217, 84, + 1, 50, 81, 193, 178, 139, 235, 41, 120, 11, 36, 203, 110, 140, + 11, 212, 23, 36, 17, 32, 68, 5, 96, 81, 246, 156, 99, 0, + 22, 55, 208, 122, 36, 249, 119, 196, 148, 248, 22, 185, 218, 12, + 108, 1, 179, 18, 192, 36, 2, 48, 33, 73, 189, 7, 181, 24, + 38, 123, 149, 123, 36, 73, 66, 205, 89, 98, 44, 38, 210, 43, + 119, 250, 45, 179, 112, 132, 245, 253, 83, 27, 91, 120, 115, 184, + 221, 101, 40, 247, 30, 59, 188, 113, 128, 12, 229, 44, 61, 34, + 232, 113, 207, 33, 63, 72, 48, 69, 237, 224, 249, 182, 112, 22, + 69, 223, 11, 225, 174, 250, 63, 245, 155, 145, 240, 1, 118, 60, + 240, 126, 236, 226, 136, 33, 125, 156, 124, 23, 36, 66, 219, 192, + 19, 226, 205, 46, 144, 155, 199, 70, 147, 214, 235, 191, 84, 142, + 186, 11, 18, 140, 131, 237, 212, 145, 180, 191, 26, 48, 146, 177, + 166, 205, 116, 106, 217, 14, 200, 218, 120, 76, 28, 245, 144, 244, + 213, 46, 59, 73, 198, 5, 4, 129, 224, 215, 231, 182, 60, 95, + 189, 175, 174, 131, 178, 77, 159, 146, 67, 64, 177, 39, 116, 17, + 39, 250, 23, 182, 197, 33, 35, 57, 243, 252, 226, 183, 45, 59, + 161, 233, 156, 184, 65, 194, 84, 50, 214, 22, 98, 255, 11, 160, + 20, 132, 19, 101, 208, 83, 0, 109, 64, 115, 54, 175, 72, 83, + 202, 85, 238, 21, 5, 88, 31, 245, 189, 235, 95, 87, 31, 91, + 107, 186, 51, 54, 226, 4, 216, 177, 254, 224, 74, 16, 150, 133, + 214, 238, 84, 18, 18, 181, 104, 112, 142, 63, 2, 212, 229, 170, + 146, 234, 109, 12, 192, 128, 205, 99, 219, 207, 200, 20, 18, 90, + 240, 114, 163, 4, 222, 208, 194, 34, 167, 141, 43, 231, 116, 48, + 40, 137, 196, 147, 53, 135, 116, 171, 137, 122, 243, 89, 108, 57, + 165, 23, 136, 31, 53, 201, 226, 27, 94, 249, 74, 64, 194, 63, + 2, 148, 232, 97, 112, 160, 172, 97, 145, 162, 204, 172, 159, 70, + 121, 208, 249, 60, 0, 49, 47, 71, 59, 129, 160, 18, 246, 197, + 195, 247, 54, 96, 224, 107, 172, 24, 58, 32, 146, 159, 253, 244, + 229, 70, 2, 31, 9, 160, 24, 88, 105, 36, 234, 70, 74, 63, + 8, 205, 235, 31, 153, 196, 20, 115, 32, 129, 35, 162, 75, 136, + 63, 255, 243, 185, 137, 250, 219, 45, 182, 171, 72, 182, 240, 146, + 19, 246, 168, 84, 148, 172, 125, 111, 18, 212, 166, 99, 35, 146, + 69, 108, 168, 136, 47, 148, 98, 190, 68, 136, 121, 125, 147, 0, + 148, 156, 88, 11, 63, 111, 31, 219, 74, 253, 98, 21, 81, 147, + 84, 120, 56, 87, 7, 54, 227, 140, 195, 84, 236, 37, 215, 169, + 116, 37, 21, 221, 236, 221, 112, 75, 15, 160, 102, 132, 191, 219, + 239, 82, 239, 74, 3, 37, 116, 218, 151, 249, 103, 225, 220, 145, + 6, 129, 215, 220, 5, 35, 112, 96, 65, 63, 57, 185, 29, 104, + 66, 87, 182, 205, 201, 126, 61, 41, 59, 249, 242, 107, 126, 169, + 0, 126, 33, 254, 59, 242, 37, 166, 241, 120, 175, 141, 128, 13, + 216, 127, 227, 125, 61, 19, 16, 143, 97, 125, 177, 228, 235, 128, + 78, 246, 200, 241, 190, 228, 10, 107, 107, 18, 184, 128, 255, 159, + 118, 160, 94, 166, 27, 143, 46, 162, 247, 137, 139, 80, 41, 88, + 66, 38, 34, 143, 223, 27, 232, 87, 14, 198, 226, 222, 14, 66, + 121, 148, 75, 7, 5, 182, 59, 129, 216, 23, 122, 208, 104, 32, + 55, 176, 166, 232, 187, 119, 95, 106, 141, 166, 132, 142, 98, 142, + 174, 39, 64, 14, 123, 56, 80, 118, 143, 157, 194, 75, 87, 210, + 210, 204, 33, 194, 118, 107, 125, 110, 103, 195, 49, 237, 11, 217, + 250, 213, 238, 155, 198, 222, 20, 46, 73, 84, 52, 174, 72, 243, + 219, 34, 108, 249, 19, 102, 139, 188, 3, 233, 130, 186, 108, 5, + 17, 175, 145, 58, 236, 43, 37, 221, 84, 82, 159, 15, 61, 61, + 67, 220, 103, 126, 126, 119, 85, 153, 90, 85, 170, 168, 19, 94, + 136, 29, 193, 108, 178, 16, 245, 182, 6, 130, 195, 14, 3, 129, + 75, 95, 79, 79, 100, 114, 75, 220, 193, 36, 44, 93, 191, 141, + 202, 39, 92, 115, 165, 143, 139, 83, 91, 139, 45, 26, 91, 238, + 52, 87, 104, 164, 57, 90, 140, 110, 123, 105, 180, 200, 222, 218, + 0, 108, 230, 28, 55, 33, 41, 201, 124, 161, 163, 191, 72, 183, + 226, 74, 14, 168, 104, 36, 129, 188, 192, 184, 61, 39, 196, 19, + 162, 171, 213, 144, 84, 93, 39, 62, 221, 51, 85, 86, 249, 157, + 150, 10, 41, 26, 91, 249, 33, 222, 239, 125, 140, 164, 24, 255, + 168, 116, 193, 184, 212, 82, 176, 182, 184, 69, 13, 235, 71, 25, + 231, 46, 97, 14, 113, 245, 177, 32, 113, 84, 25, 77, 162, 228, + 22, 129, 214, 74, 124, 26, 81, 34, 97, 234, 20, 138, 30, 38, + 70, 140, 92, 174, 81, 177, 23, 18, 115, 163, 125, 197, 92, 138, + 164, 227, 1, 242, 144, 81, 182, 232, 147, 34, 119, 70, 111, 190, + 154, 10, 24, 144, 124, 171, 107, 169, 255, 96, 80, 155, 192, 88, + 103, 218, 217, 192, 13, 237, 21, 14, 15, 244, 195, 232, 174, 5, + 245, 94, 42, 10, 114, 76, 4, 24, 50, 15, 210, 160, 141, 254, + 231, 141, 244, 55, 72, 225, 6, 118, 41, 248, 110, 222, 20, 20, + 31, 133, 220, 180, 142, 150, 157, 189, 229, 240, 57, 70, 177, 32, + 51, 127, 65, 10, 66, 43, 146, 177, 49, 115, 218, 176, 53, 104, + 86, 74, 222, 161, 84, 128, 181, 36, 192, 44, 252, 153, 213, 31, + 162, 16, 167, 212, 85, 86, 152, 229, 139, 99, 20, 142, 227, 175, + 37, 155, 208, 87, 149, 22, 43, 161, 254, 141, 145, 245, 58, 213, + 40, 133, 63, 136, 114, 79, 177, 216, 93, 17, 116, 179, 92, 38, + 16, 135, 3, 95, 26, 76, 52, 190, 136, 58, 117, 79, 163, 8, + 64, 38, 8, 14, 80, 78, 240, 157, 173, 205, 198, 239, 163, 127, + 181, 93, 238, 13, 67, 176, 229, 188, 78, 156, 127, 81, 209, 12, + 131, 180, 217, 35, 2, 45, 83, 107, 165, 111, 3, 22, 218, 136, + 145, 91, 20, 197, 14, 226, 195, 76, 165, 160, 250, 23, 80, 66, + 127, 66, 188, 220, 87, 166, 139, 168, 219, 187, 222, 146, 56, 66, + 106, 185, 99, 201, 159, 241, 142, 227, 225, 84, 119, 76, 53, 81, + 192, 191, 209, 171, 229, 41, 95, 193, 190, 188, 59, 73, 19, 125, + 191, 207, 92, 84, 92, 198, 49, 135, 44, 65, 154, 128, 189, 203, + 209, 81, 206, 89, 20, 238, 28, 7, 135, 120, 171, 181, 136, 92, + 174, 150, 75, 53, 112, 220, 146, 11, 247, 174, 90, 76, 126, 226, + 50, 255, 116, 185, 202, 185, 242, 236, 57, 242, 68, 103, 118, 119, + 146, 153, 226, 249, 202, 152, 250, 29, 201, 81, 89, 130, 83, 84, + 115, 212, 65, 172, 107, 247, 216, 31, 95, 132, 115, 1, 68, 102, + 207, 59, 82, 132, 63, 134, 19, 157, 0, 16, 15, 117, 28, 138, + 239, 20, 205, 187, 167, 141, 33, 70, 141, 10, 82, 115, 102, 202, + 170, 236, 250, 231, 195, 176, 40, 171, 171, 239, 121, 82, 6, 158, + 149, 61, 225, 156, 244, 75, 137, 140, 214, 202, 251, 121, 241, 122, + 18, 185, 3, 161, 149, 120, 77, 117, 189, 228, 116, 249, 73, 10, + 99, 43, 184, 187, 119, 232, 247, 83, 140, 176, 193, 9, 246, 145, + 177, 165, 169, 121, 21, 155, 161, 27, 106, 140, 80, 63, 232, 168, + 240, 42, 190, 209, 234, 0, 248, 50, 236, 183, 169, 97, 25, 92, + 139, 106, 32, 67, 222, 120, 79, 6, 111, 151, 252, 162, 26, 142, + 193, 16, 43, 142, 35, 125, 21, 111, 226, 178, 224, 64, 220, 214, + 136, 197, 35, 81, 80, 214, 104, 105, 183, 21, 141, 84, 242, 0, + 18, 219, 95, 231, 171, 251, 4, 10, 167, 158, 83, 21, 201, 82, + 122, 33, 206, 77, 39, 91, 156, 253, 137, 181, 251, 84, 159, 23, + 2, 5, 201, 17, 19, 43, 224, 141, 40, 117, 54, 112, 166, 68, + 43, 67, 155, 200, 15, 87, 50, 163, 92, 211, 49, 104, 148, 180, + 144, 74, 175, 76, 45, 212, 140, 141, 52, 195, 135, 224, 179, 132, + 15, 180, 58, 202, 233, 39, 200, 215, 189, 179, 165, 39, 255, 6, + 227, 141, 237, 26, 188, 80, 104, 55, 65, 88, 255, 90, 211, 192, + 83, 23, 118, 178, 107, 174, 227, 119, 247, 255, 232, 178, 190, 31, + 12, 43, 13, 220, 159, 4, 196, 102, 63, 217, 81, 172, 29, 164, + 34, 237, 49, 182, 247, 162, 210, 239, 20, 128, 69, 8, 139, 50, + 224, 40, 172, 230, 159, 157, 72, 100, 200, 120, 251, 206, 245, 220, + 115, 142, 22, 45, 127, 224, 40, 7, 121, 73, 145, 215, 43, 163, + 173, 187, 58, 26, 117, 229, 250, 55, 199, 189, 81, 166, 209, 126, + 229, 85, 39, 50, 164, 154, 124, 41, 65, 26, 71, 243, 56, 29, + 142, 92, 30, 228, 63, 14, 172, 136, 101, 101, 37, 204, 103, 163, + 225, 111, 127, 59, 36, 152, 230, 146, 121, 168, 125, 43, 148, 231, + 2, 219, 83, 95, 93, 205, 35, 245, 12, 240, 56, 207, 172, 49, + 2, 108, 51, 164, 234, 165, 0, 55, 199, 33, 114, 23, 210, 58, + 29, 225, 187, 177, 178, 158, 240, 155, 244, 81, 140, 56, 217, 3, + 26, 141, 248, 50, 209, 253, 44, 252, 245, 159, 9, 137, 190, 0, + 178, 32, 23, 219, 176, 25, 28, 200, 55, 82, 104, 128, 50, 137, + 181, 113, 99, 6, 179, 229, 163, 69, 134, 119, 122, 28, 105, 245, + 78, 241, 113, 219, 191, 60, 214, 125, 227, 252, 93, 145, 129, 146, + 94, 151, 101, 105, 101, 20, 26, 89, 103, 77, 103, 132, 3, 11, + 216, 161, 187, 181, 162, 86, 79, 89, 27, 53, 0, 58, 14, 149, + 107, 5, 128, 69, 60, 171, 201, 50, 125, 240, 84, 153, 235, 133, + 20, 215, 134, 68, 147, 69, 237, 230, 7, 120, 85, 209, 250, 244, + 206, 133, 178, 62, 4, 244, 51, 30, 47, 130, 63, 228, 194, 191, + 179, 136, 225, 1, 251, 154, 61, 204, 253, 154, 72, 158, 136, 208, + 198, 33, 248, 67, 200, 198, 1, 57, 1, 158, 97, 141, 128, 220, + 223, 53, 169, 37, 157, 85, 24, 169, 53, 5, 59, 158, 26, 110, + 121, 152, 221, 81, 171, 29, 136, 169, 156, 194, 87, 217, 124, 246, + 109, 122, 165, 104, 219, 89, 91, 2, 13, 163, 59, 46, 168, 113, + 223, 75, 2, 131, 55, 219, 245, 250, 85, 18, 202, 220, 92, 79, + 77, 67, 86, 2, 11, 86, 86, 244, 169, 0, 70, 167, 222, 101, + 16, 86, 29, 237, 215, 119, 33, 237, 142, 242, 198, 196, 101, 75, + 25, 154, 88, 235, 224, 53, 41, 252, 203, 136, 21, 168, 102, 163, + 114, 31, 119, 25, 113, 75, 184, 66, 152, 248, 58, 188, 183, 77, + 208, 219, 141, 170, 55, 234, 31, 123, 170, 231, 61, 97, 222, 238, + 205, 115, 27, 246, 177, 106, 174, 20, 70, 73, 106, 195, 22, 202, + 27, 143, 120, 52, 3, 174, 183, 179, 248, 243, 214, 182, 243, 12, + 147, 204, 217, 238, 177, 130, 156, 42, 59, 11, 104, 67, 172, 177, + 96, 96, 5, 225, 106, 138, 180, 250, 227, 90, 234, 61, 131, 145, + 131, 27, 55, 206, 181, 75, 112, 228, 226, 197, 227, 84, 189, 12, + 85, 85, 234, 221, 66, 233, 245, 21, 2, 77, 35, 96, 124, 146, + 245, 17, 233, 85, 150, 97, 101, 121, 155, 236, 118, 111, 199, 233, + 172, 167, 57, 81, 51, 44, 9, 34, 188, 27, 224, 147, 3, 77, + 152, 165, 27, 149, 20, 119, 189, 1, 100, 114, 213, 23, 107, 181, + 245, 58, 204, 39, 39, 39, 145, 184, 225, 187, 4, 255, 208, 17, + 184, 123, 51, 11, 180, 86, 150, 254, 250, 222, 108, 65, 37, 178, + 30, 10, 206, 155, 82, 93, 102, 48, 226, 18, 59, 56, 80, 90, + 253, 16, 238, 52, 207, 63, 42, 64, 61, 107, 242, 126, 233, 163, + 157, 36, 10, 137, 45, 179, 126, 18, 209, 55, 5, 184, 117, 5, + 27, 115, 196, 211, 36, 66, 182, 65, 88, 97, 92, 19, 19, 107, + 179, 123, 67, 31, 155, 66, 153, 154, 185, 50, 51, 216, 236, 136, + 125, 166, 181, 96, 44, 66, 95, 50, 27, 4, 244, 134, 252, 208, + 171, 213, 174, 160, 167, 63, 254, 195, 53, 63, 202, 5, 166, 34, + 96, 226, 228, 146, 215, 62, 162, 3, 73, 191, 47, 137, 163, 117, + 50, 85, 195, 210, 71, 209, 44, 88, 62, 50, 237, 151, 74, 231, + 200, 43, 58, 254, 250, 183, 243, 73, 51, 245, 14, 201, 176, 20, + 195, 222, 109, 10, 213, 246, 106, 169, 202, 147, 71, 252, 154, 113, + 170, 58, 71, 23, 180, 127, 32, 241, 80, 59, 180, 207, 118, 156, + 118, 213, 202, 3, 88, 172, 51, 37, 37, 196, 64, 219, 174, 166, + 63, 196, 177, 219, 146, 148, 120, 146, 238, 61, 140, 226, 210, 212, + 1, 203, 158, 234, 226, 56, 164, 102, 75, 133, 166, 179, 42, 145, + 147, 10, 40, 223, 90, 138, 116, 238, 43, 74, 134, 13, 255, 199, + 105, 8, 66, 188, 120, 96, 47, 222, 216, 71, 20, 168, 198, 42, + 77, 110, 19, 140, 55, 172, 84, 127, 118, 60, 119, 108, 46, 247, + 144, 155, 75, 87, 226, 19, 127, 0, 155, 105, 93, 125, 136, 103, + 222, 72, 226, 58, 215, 132, 25, 31, 158, 73, 9, 172, 50, 231, + 237, 194, 190, 139, 125, 129, 115, 117, 155, 135, 98, 191, 63, 189, + 34, 163, 179, 104, 223, 80, 93, 81, 95, 4, 215, 170, 46, 133, + 248, 80, 116, 93, 47, 50, 111, 53, 79, 177, 177, 202, 76, 97, + 183, 3, 78, 17, 249, 116, 140, 83, 67, 18, 54, 19, 197, 83, + 98, 187, 73, 76, 221, 69, 158, 44, 99, 205, 19, 212, 227, 150, + 151, 212, 132, 144, 240, 193, 249, 222, 239, 19, 189, 91, 8, 217, + 180, 94, 6, 56, 80, 118, 40, 96, 10, 66, 251, 36, 197, 207, + 238, 209, 239, 6, 220, 160, 26, 232, 4, 45, 158, 6, 56, 5, + 197, 178, 76, 98, 142, 223, 226, 202, 41, 194, 89, 91, 13, 239, + 188, 213, 22, 38, 59, 220, 202, 132, 229, 5, 11, 206, 179, 143, + 252, 84, 64, 168, 3, 180, 181, 31, 243, 97, 164, 74, 191, 121, + 210, 128, 232, 106, 40, 221, 177, 59, 55, 228, 52, 100, 152, 36, + 197, 153, 82, 235, 112, 183, 156, 38, 169, 213, 195, 48, 98, 159, + 127, 98, 84, 169, 71, 141, 243, 195, 107, 102, 247, 68, 149, 152, + 45, 129, 252, 119, 180, 191, 129, 16, 250, 55, 234, 92, 86, 23, + 109, 153, 5, 45, 228, 29, 193, 62, 42, 85, 179, 64, 22, 127, + 183, 68, 54, 243, 14, 120, 196, 204, 226, 229, 28, 118, 109, 1, + 165, 209, 51, 12, 87, 211, 133, 115, 228, 228, 85, 149, 148, 103, + 7, 189, 98, 31, 80, 129, 55, 216, 101, 191, 79, 35, 222, 6, + 247, 149, 132, 87, 68, 74, 136, 233, 184, 125, 30, 215, 49, 115, + 178, 236, 128, 66, 112, 157, 34, 61, 22, 102, 178, 141, 241, 176, + 199, 60, 231, 188, 13, 208, 203, 156, 36, 8, 88, 106, 138, 44, + 196, 64, 110, 83, 219, 207, 45, 127, 167, 117, 150, 15, 129, 61, + 125, 34, 15, 190, 23, 163, 28, 27, 225, 36, 195, 219, 144, 172, + 196, 210, 35, 43, 0, 231, 180, 110, 190, 74, 86, 59, 110, 175, + 101, 1, 165, 43, 198, 35, 155, 103, 203, 58, 50, 63, 29, 185, + 169, 87, 128, 150, 161, 5, 152, 17, 205, 208, 147, 74, 197, 26, + 15, 174, 222, 52, 80, 209, 96, 244, 235, 139, 21, 35, 233, 226, + 195, 175, 188, 84, 136, 5, 65, 249, 173, 254, 144, 20, 102, 180, + 128, 71, 239, 162, 64, 170, 166, 117, 96, 14, 182, 196, 232, 203, + 38, 152, 140, 213, 33, 153, 199, 56, 165, 168, 99, 255, 183, 242, + 192, 122, 45, 227, 19, 36, 64, 158, 69, 58, 7, 138, 153, 6, + 107, 93, 244, 137, 127, 171, 101, 220, 184, 130, 119, 192, 30, 53, + 51, 63, 232, 80, 255, 222, 93, 125, 66, 181, 156, 235, 200, 217, + 243, 252, 241, 214, 241, 67, 76, 138, 212, 184, 168, 113, 233, 247, + 39, 26, 145, 141, 59, 234, 13, 1, 4, 200, 69, 205, 154, 107, + 47, 221, 45, 16, 96, 220, 121, 186, 156, 60, 199, 45, 123, 34, + 134, 57, 48, 232, 77, 95, 214, 137, 55, 91, 12, 140, 224, 67, + 188, 157, 246, 119, 250, 244, 134, 116, 10, 191, 191, 140, 243, 252, + 24, 192, 119, 138, 241, 78, 31, 212, 198, 150, 95, 72, 214, 160, + 167, 212, 49, 247, 132, 83, 253, 0, 63, 94, 14, 224, 7, 125, + 204, 177, 66, 200, 217, 20, 79, 89, 249, 206, 54, 186, 93, 19, + 116, 108, 3, 15, 218, 197, 89, 95, 46, 113, 36, 243, 209, 103, + 122, 5, 245, 55, 236, 60, 147, 134, 227, 175, 250, 241, 32, 65, + 65, 249, 85, 83, 123, 69, 149, 61, 248, 144, 7, 214, 253, 149, + 177, 187, 23, 249, 95, 165, 194, 242, 115, 244, 238, 89, 240, 164, + 97, 136, 171, 201, 169, 39, 221, 98, 90, 26, 237, 159, 148, 145, + 13, 184, 39, 142, 208, 203, 32, 41, 48, 240, 71, 32, 232, 144, + 49, 97, 61, 144, 110, 199, 63, 63, 195, 90, 201, 79, 15, 22, + 101, 25, 0, 101, 218, 105, 71, 188, 225, 68, 222, 61, 84, 190, + 229, 18, 58, 183, 109, 23, 93, 75, 8, 174, 107, 245, 228, 220, + 64, 182, 53, 147, 56, 75, 37, 100, 95, 213, 60, 10, 254, 199, + 234, 184, 152, 23, 111, 230, 212, 148, 171, 236, 42, 30, 38, 226, + 232, 159, 178, 229, 126, 174, 244, 19, 28, 133, 90, 99, 81, 8, + 130, 81, 224, 4, 97, 31, 77, 129, 169, 166, 195, 6, 19, 188, + 124, 20, 199, 152, 135, 112, 7, 135, 202, 208, 63, 164, 113, 55, + 111, 9, 65, 140, 242, 188, 66, 115, 142, 50, 69, 51, 66, 236, + 40, 36, 249, 241, 235, 221, 17, 41, 227, 156, 13, 167, 23, 209, + 252, 12, 81, 232, 124, 176, 211, 168, 172, 44, 111, 215, 208, 45, + 25, 2, 87, 113, 185, 116, 235, 73, 52, 215, 6, 21, 73, 125, + 101, 195, 141, 4, 184, 78, 177, 196, 45, 109, 84, 136, 35, 8, + 181, 189, 223, 18, 181, 7, 114, 215, 89, 45, 235, 44, 123, 89, + 217, 201, 121, 129, 53, 36, 52, 10, 33, 106, 12, 110, 201, 214, + 196, 38, 48, 104, 165, 226, 75, 159, 36, 83, 212, 91, 129, 200, + 37, 75, 129, 175, 26, 33, 118, 60, 129, 24, 209, 92, 134, 35, + 246, 65, 82, 128, 28, 82, 68, 3, 243, 159, 198, 80, 9, 135, + 237, 241, 20, 184, 122, 169, 52, 38, 163, 19, 87, 183, 216, 178, + 77, 163, 228, 92, 110, 182, 185, 49, 45, 186, 11, 225, 97, 76, + 159, 82, 13, 74, 99, 69, 151, 226, 34, 36, 69, 207, 248, 43, + 94, 238, 28, 94, 204, 226, 70, 180, 129, 180, 161, 155, 20, 111, + 213, 160, 220, 146, 39, 197, 91, 138, 224, 58, 223, 56, 200, 57, + 217, 51, 167, 84, 174, 125, 18, 189, 137, 157, 40, 222, 139, 63, + 124, 121, 26, 69, 95, 143, 57, 189, 218, 248, 245, 149, 141, 141, + 216, 28, 116, 97, 77, 84, 6, 119, 244, 62, 94, 150, 82, 194, + 88, 184, 221, 59, 149, 169, 177, 188, 155, 43, 119, 109, 138, 127, + 235, 217, 84, 142, 139, 171, 221, 7, 217, 237, 78, 185, 214, 21, + 20, 126, 209, 34, 6, 124, 146, 9, 79, 86, 88, 236, 140, 144, + 140, 184, 24, 52, 62, 57, 107, 63, 46, 135, 254, 60, 49, 86, + 192, 208, 51, 77, 238, 254, 85, 144, 26, 180, 160, 245, 181, 94, + 119, 227, 211, 21, 243, 145, 143, 198, 8, 86, 221, 202, 72, 98, + 147, 41, 120, 158, 108, 186, 124, 220, 184, 151, 254, 186, 237, 31, + 110, 57, 76, 176, 179, 87, 122, 189, 173, 226, 183, 167, 40, 128, + 48, 98, 47, 127, 252, 102, 55, 124, 36, 185, 245, 116, 89, 121, + 78, 118, 116, 57, 209, 52, 50, 190, 184, 166, 200, 22, 213, 24, + 133, 150, 108, 226, 203, 92, 208, 139, 210, 255, 232, 10, 243, 187, + 223, 21, 235, 106, 1, 131, 189, 106, 70, 3, 194, 61, 231, 113, + 225, 71, 28, 211, 253, 102, 118, 22, 236, 79, 194, 18, 91, 68, + 239, 75, 32, 220, 245, 213, 92, 161, 15, 247, 249, 25, 168, 156, + 23, 222, 0, 94, 1, 153, 24, 140, 16, 128, 108, 254, 60, 11, + 53, 14, 160, 123, 53, 215, 150, 99, 230, 42, 48, 75, 240, 166, + 125, 136, 39, 253, 13, 128, 83, 132, 18, 248, 216, 212, 133, 140, + 85, 165, 146, 200, 218, 52, 94, 166, 192, 231, 126, 140, 170, 207, + 228, 29, 228, 15, 71, 39, 132, 164, 209, 151, 162, 250, 61, 53, + 226, 228, 57, 154, 53, 152, 32, 76, 7, 25, 123, 44, 75, 171, + 145, 220, 59, 167, 225, 133, 46, 187, 250, 23, 63, 91, 18, 86, + 193, 107, 36, 73, 30, 91, 184, 34, 161, 145, 61, 25, 128, 50, + 23, 252, 60, 154, 79, 195, 65, 0, 213, 94, 222, 60, 66, 239, + 89, 51, 59, 32, 192, 95, 111, 114, 56, 222, 226, 239, 195, 148, + 255, 155, 144, 152, 140, 191, 117, 169, 209, 221, 18, 162, 33, 145, + 149, 243, 150, 53, 108, 164, 22, 143, 50, 95, 155, 91, 134, 53, + 119, 157, 176, 227, 238, 63, 45, 98, 60, 83, 158, 239, 129, 180, + 20, 215, 249, 254, 136, 208, 235, 78, 7, 200, 234, 8, 167, 184, + 27, 53, 253, 115, 196, 44, 225, 121, 180, 58, 193, 250, 220, 37, + 147, 6, 147, 140, 70, 192, 107, 143, 150, 200, 241, 101, 238, 255, + 51, 110, 243, 140, 206, 236, 67, 77, 37, 7, 27, 93, 10, 169, + 195, 228, 102, 131, 150, 11, 162, 67, 196, 139, 166, 248, 3, 75, + 139, 238, 183, 231, 36, 202, 87, 12, 174, 252, 250, 173, 245, 67, + 252, 240, 218, 103, 97, 131, 167, 119, 216, 54, 9, 101, 165, 186, + 66, 31, 24, 35, 249, 53, 220, 55, 2, 213, 224, 123, 217, 232, + 174, 141, 88, 191, 126, 126, 7, 178, 250, 245, 35, 87, 100, 124, + 0, 173, 80, 181, 78, 2, 49, 35, 246, 160, 16, 41, 46, 134, + 80, 191, 12, 193, 78, 0, 61, 126, 15, 21, 59, 167, 33, 79, + 233, 204, 201, 95, 84, 188, 43, 46, 9, 70, 249, 97, 62, 118, + 52, 179, 189, 86, 174, 171, 112, 139, 22, 88, 190, 83, 103, 146, + 74, 36, 145, 239, 132, 246, 8, 192, 107, 36, 100, 130, 116, 7, + 101, 251, 33, 205, 141, 233, 169, 62, 103, 97, 56, 93, 42, 199, + 15, 41, 26, 190, 255, 233, 107, 141, 218, 203, 20, 105, 185, 32, + 147, 64, 212, 135, 208, 226, 9, 54, 202, 22, 126, 71, 252, 22, + 26, 149, 204, 30, 55, 241, 66, 82, 117, 135, 26, 92, 175, 64, + 64, 127, 11, 146, 13, 192, 190, 224, 125, 70, 11, 230, 145, 46, + 33, 239, 37, 190, 49, 42, 250, 110, 55, 97, 146, 134, 51, 245, + 100, 160, 199, 56, 63, 144, 147, 102, 41, 19, 107, 14, 252, 226, + 2, 64, 60, 124, 211, 213, 30, 109, 203, 64, 67, 208, 218, 149, + 12, 117, 235, 130, 60, 189, 201, 220, 84, 106, 191, 112, 140, 28, + 80, 174, 49, 210, 226, 17, 197, 188, 144, 64, 131, 206, 63, 91, + 191, 189, 30, 108, 66, 58, 84, 17, 229, 164, 12, 28, 77, 52, + 32, 25, 8, 38, 116, 132, 168, 86, 220, 149, 111, 21, 169, 129, + 201, 164, 172, 165, 171, 188, 96, 179, 58, 1, 28, 96, 251, 237, + 252, 159, 96, 129, 32, 229, 102, 35, 56, 192, 11, 250, 140, 1, + 134, 229, 177, 117, 37, 151, 34, 173, 98, 115, 180, 124, 152, 225, + 89, 67, 145, 96, 66, 217, 33, 249, 155, 233, 149, 163, 103, 4, + 164, 246, 54, 225, 226, 32, 107, 163, 253, 231, 135, 22, 183, 99, + 85, 217, 101, 157, 22, 223, 233, 213, 102, 37, 4, 188, 96, 4, + 214, 41, 26, 3, 239, 45, 80, 51, 181, 92, 142, 185, 149, 197, + 208, 107, 178, 111, 117, 29, 242, 90, 189, 251, 2, 181, 232, 100, + 122, 229, 254, 216, 249, 39, 77, 172, 22, 192, 93, 138, 134, 174, + 10, 123, 136, 92, 118, 123, 221, 40, 25, 103, 215, 195, 244, 79, + 125, 92, 108, 26, 55, 20, 3, 112, 150, 34, 16, 158, 63, 251, + 54, 102, 147, 86, 214, 6, 180, 85, 104, 194, 58, 136, 154, 215, + 118, 49, 254, 71, 4, 205, 120, 38, 209, 177, 64, 27, 35, 66, + 205, 129, 207, 124, 112, 231, 23, 214, 101, 168, 252, 128, 24, 41, + 239, 191, 18, 215, 186, 36, 51, 111, 119, 230, 60, 130, 37, 60, + 206, 103, 91, 228, 8, 246, 201, 255, 136, 58, 167, 172, 113, 252, + 11, 237, 240, 200, 98, 116, 117, 44, 130, 191, 1, 205, 169, 232, + 247, 58, 159, 198, 147, 232, 145, 222, 143, 143, 247, 145, 90, 243, + 28, 138, 179, 123, 197, 223, 115, 84, 231, 61, 176, 111, 209, 71, + 140, 241, 198, 178, 29, 205, 179, 182, 32, 30, 92, 252, 76, 30, + 147, 8, 56, 84, 87, 38, 232, 205, 112, 155, 207, 59, 39, 235, + 48, 195, 43, 183, 114, 139, 17, 207, 48, 102, 229, 202, 121, 54, + 105, 206, 251, 202, 103, 29, 36, 232, 84, 41, 26, 109, 179, 187, + 8, 192, 0, 70, 175, 167, 245, 136, 3, 51, 25, 62, 34, 162, + 247, 84, 99, 129, 162, 232, 120, 190, 255, 162, 44, 115, 84, 66, + 224, 203, 20, 150, 81, 166, 234, 142, 225, 169, 172, 91, 79, 100, + 85, 63, 44, 49, 233, 6, 250, 87, 189, 138, 73, 149, 9, 161, + 179, 126, 92, 241, 198, 205, 207, 1, 42, 94, 176, 160, 122, 42, + 202, 165, 156, 11, 75, 187, 25, 55, 136, 154, 232, 53, 45, 173, + 76, 10, 177, 189, 47, 55, 165, 13, 174, 233, 130, 127, 110, 22, + 204, 154, 224, 24, 200, 231, 141, 153, 141, 4, 87, 14, 147, 101, + 216, 132, 232, 161, 3, 154, 132, 89, 172, 80, 126, 107, 192, 30, + 150, 119, 121, 9, 199, 8, 166, 241, 248, 82, 38, 75, 22, 65, + 140, 25, 105, 83, 187, 213, 171, 81, 245, 219, 58, 210, 246, 196, + 205, 248, 102, 207, 160, 21, 197, 11, 225, 167, 110, 199, 111, 80, + 161, 138, 15, 148, 72, 189, 59, 10, 179, 234, 241, 103, 221, 211, + 202, 26, 223, 57, 62, 3, 183, 104, 140, 174, 253, 8, 201, 1, + 48, 151, 49, 26, 110, 140, 67, 131, 80, 249, 153, 182, 163, 249, + 97, 133, 202, 130, 155, 135, 245, 108, 79, 76, 10, 180, 130, 57, + 155, 122, 177, 175, 95, 192, 202, 181, 244, 3, 99, 143, 21, 0, + 168, 234, 51, 152, 165, 142, 30, 58, 144, 105, 230, 5, 129, 187, + 51, 53, 238, 56, 252, 191, 202, 208, 209, 180, 244, 54, 68, 176, + 196, 221, 65, 84, 135, 207, 150, 105, 39, 166, 148, 8, 139, 36, + 168, 189, 57, 174, 225, 121, 121, 40, 149, 220, 183, 214, 94, 124, + 70, 142, 10, 66, 172, 134, 43, 31, 139, 205, 46, 109, 62, 233, + 94, 146, 63, 132, 90, 168, 27, 227, 185, 56, 125, 152, 134, 39, + 233, 69, 130, 233, 68, 43, 15, 33, 19, 180, 255, 18, 151, 107, + 232, 208, 40, 144, 186, 228, 210, 113, 200, 23, 7, 211, 187, 45, + 155, 103, 217, 212, 4, 131, 29, 44, 10, 71, 170, 187, 100, 217, + 190, 195, 92, 7, 150, 97, 163, 12, 148, 178, 213, 103, 92, 7, + 82, 104, 14, 221, 66, 5, 204, 18, 141, 196, 142, 189, 149, 215, + 154, 43, 165, 179, 95, 86, 75, 148, 184, 204, 129, 253, 32, 64, + 248, 243, 173, 30, 201, 207, 36, 229, 169, 84, 230, 137, 39, 158, + 184, 16, 36, 155, 84, 114, 248, 80, 97, 143, 28, 99, 142, 214, + 33, 78, 49, 245, 128, 118, 184, 215, 242, 145, 100, 65, 252, 146, + 63, 168, 37, 214, 208, 106, 156, 0, 165, 116, 202, 2, 204, 51, + 117, 88, 167, 93, 186, 143, 42, 193, 181, 215, 151, 8, 99, 171, + 5, 135, 85, 143, 165, 193, 98, 91, 216, 225, 136, 109, 52, 161, + 98, 46, 211, 7, 122, 11, 58, 26, 190, 195, 160, 31, 63, 0, + 131, 108, 123, 191, 133, 197, 188, 205, 255, 33, 173, 8, 175, 225, + 239, 72, 75, 3, 33, 106, 255, 189, 220, 97, 143, 196, 114, 232, + 251, 131, 191, 18, 143, 149, 110, 75, 122, 114, 142, 99, 75, 167, + 65, 13, 124, 145, 31, 88, 151, 202, 236, 179, 73, 100, 115, 40, + 33, 74, 198, 104, 24, 125, 238, 156, 37, 143, 252, 191, 135, 208, + 120, 121, 24, 227, 6, 220, 76, 121, 41, 136, 175, 78, 129, 9, + 246, 148, 64, 84, 216, 216, 242, 87, 40, 215, 47, 120, 221, 57, + 83, 142, 156, 200, 73, 119, 59, 43, 105, 201, 68, 16, 116, 2, + 52, 24, 93, 137, 103, 187, 55, 255, 246, 177, 226, 2, 237, 3, + 166, 14, 113, 23, 129, 153, 68, 106, 209, 9, 74, 92, 112, 196, + 221, 210, 108, 89, 250, 202, 230, 205, 231, 162, 125, 35, 73, 164, + 236, 226, 190, 21, 224, 186, 44, 93, 238, 244, 155, 250, 186, 168, + 193, 37, 124, 247, 80, 251, 3, 131, 34, 141, 65, 198, 156, 147, + 167, 215, 107, 41, 42, 77, 90, 77, 193, 16, 246, 133, 197, 134, + 23, 54, 193, 61, 167, 89, 190, 151, 203, 104, 2, 229, 45, 211, + 75, 150, 219, 71, 29, 195, 183, 174, 211, 219, 90, 237, 55, 154, + 84, 126, 65, 8, 156, 221, 85, 209, 175, 43, 172, 55, 224, 187, + 187, 213, 126, 131, 205, 249, 59, 109, 113, 112, 19, 73, 181, 133, + 48, 240, 135, 173, 196, 64, 219, 109, 89, 240, 126, 2, 213, 239, + 71, 21, 162, 245, 37, 110, 133, 38, 161, 187, 218, 3, 80, 48, + 206, 107, 222, 9, 250, 71, 50, 73, 66, 154, 76, 203, 36, 4, + 14, 210, 149, 60, 135, 167, 68, 184, 145, 167, 72, 69, 14, 62, + 216, 139, 120, 45, 79, 39, 230, 244, 233, 189, 199, 251, 151, 8, + 166, 229, 126, 183, 59, 64, 68, 160, 97, 191, 129, 72, 191, 221, + 56, 67, 208, 1, 225, 171, 242, 10, 64, 225, 36, 231, 225, 136, + 158, 230, 222, 83, 4, 140, 153, 12, 188, 156, 40, 119, 197, 247, + 168, 0, 188, 141, 197, 203, 81, 137, 112, 212, 10, 234, 146, 99, + 57, 185, 153, 134, 101, 123, 39, 18, 103, 149, 130, 48, 181, 65, + 58, 241, 206, 63, 129, 160, 130, 87, 248, 248, 84, 126, 171, 78, + 53, 237, 70, 54, 165, 145, 163, 81, 154, 112, 55, 234, 224, 181, + 255, 212, 112, 136, 82, 80, 17, 141, 226, 109, 22, 61, 68, 81, + 178, 116, 127, 206, 103, 60, 133, 79, 56, 112, 218, 170, 51, 175, + 23, 171, 171, 205, 230, 24, 60, 206, 38, 240, 161, 134, 38, 218, + 202, 171, 81, 77, 210, 5, 24, 78, 67, 35, 133, 206, 229, 147, + 193, 138, 99, 87, 41, 135, 146, 21, 152, 216, 148, 165, 60, 18, + 35, 115, 87, 84, 16, 222, 230, 111, 41, 74, 28, 80, 253, 196, + 31, 5, 57, 68, 167, 77, 32, 158, 119, 156, 43, 175, 253, 156, + 67, 150, 203, 165, 231, 141, 167, 53, 255, 42, 67, 177, 18, 129, + 80, 208, 154, 12, 81, 86, 91, 105, 182, 21, 217, 171, 125, 197, + 81, 42, 254, 213, 186, 138, 61, 14, 249, 246, 245, 65, 230, 225, + 138, 102, 153, 176, 109, 48, 237, 142, 39, 3, 41, 94, 68, 73, + 87, 183, 206, 129, 40, 85, 21, 223, 90, 183, 143, 243, 146, 64, + 238, 50, 64, 63, 200, 88, 40, 143, 211, 218, 9, 186, 68, 40, + 245, 201, 29, 183, 47, 232, 250, 11, 173, 212, 209, 117, 124, 144, + 205, 210, 132, 188, 127, 65, 243, 246, 62, 88, 106, 79, 58, 180, + 55, 158, 66, 63, 2, 155, 111, 11, 103, 129, 175, 163, 160, 16, + 139, 109, 10, 223, 130, 158, 54, 248, 209, 225, 82, 155, 199, 205, + 82, 167, 254, 99, 20, 29, 246, 15, 88, 100, 87, 205, 30, 174, + 70, 231, 29, 30, 110, 175, 164, 149, 118, 94, 48, 60, 28, 174, + 35, 221, 21, 42, 209, 146, 5, 182, 50, 4, 21, 143, 196, 64, + 149, 147, 35, 245, 72, 82, 107, 92, 203, 85, 182, 104, 97, 115, + 228, 93, 21, 47, 186, 152, 172, 226, 39, 14, 116, 78, 9, 77, + 98, 139, 110, 202, 117, 250, 205, 30, 210, 31, 202, 223, 0, 138, + 133, 22, 92, 57, 95, 30, 158, 78, 84, 132, 67, 8, 60, 218, + 61, 141, 155, 104, 196, 203, 249, 73, 249, 143, 254, 168, 72, 172, + 142, 251, 246, 186, 23, 49, 164, 157, 235, 132, 215, 62, 182, 124, + 162, 203, 199, 63, 93, 161, 33, 253, 83, 159, 214, 214, 2, 125, + 57, 13, 157, 42, 82, 178, 193, 163, 180, 34, 177, 42, 196, 79, + 74, 8, 194, 67, 192, 202, 150, 210, 232, 183, 77, 119, 254, 201, + 53, 51, 153, 137, 188, 140, 199, 87, 182, 112, 47, 218, 136, 137, + 48, 200, 165, 152, 238, 34, 214, 126, 36, 193, 178, 169, 128, 114, + 154, 46, 90, 244, 2, 112, 252, 57, 247, 64, 221, 142, 81, 163, + 58, 38, 47, 19, 234, 84, 194, 26, 123, 136, 236, 252, 210, 120, + 193, 194, 70, 235, 238, 216, 202, 103, 130, 192, 29, 102, 20, 202, + 149, 168, 179, 16, 183, 228, 141, 211, 203, 98, 72, 175, 178, 164, + 0, 140, 91, 22, 109, 200, 163, 168, 242, 246, 138, 151, 159, 199, + 105, 74, 232, 117, 166, 138, 113, 26, 226, 109, 205, 163, 133, 56, + 76, 105, 57, 100, 17, 85, 121, 146, 125, 114, 62, 128, 16, 40, + 81, 139, 90, 76, 118, 62, 194, 253, 54, 206, 54, 174, 18, 233, + 5, 54, 44, 25, 96, 197, 79, 91, 198, 143, 195, 26, 27, 172, + 38, 200, 233, 105, 205, 181, 198, 30, 173, 51, 17, 123, 57, 34, + 49, 249, 179, 42, 2, 179, 58, 8, 249, 120, 21, 113, 103, 43, + 97, 83, 199, 224, 57, 179, 119, 141, 198, 119, 47, 17, 228, 74, + 54, 210, 158, 152, 130, 2, 122, 169, 133, 169, 92, 130, 40, 219, + 161, 161, 229, 90, 83, 170, 96, 124, 11, 6, 228, 221, 118, 205, + 73, 139, 5, 19, 16, 176, 16, 171, 148, 88, 252, 156, 156, 121, + 58, 229, 199, 103, 71, 133, 199, 169, 132, 73, 39, 37, 205, 185, + 248, 53, 78, 73, 23, 230, 28, 167, 123, 122, 85, 205, 3, 197, + 247, 100, 106, 164, 209, 64, 241, 41, 216, 89, 149, 210, 2, 252, + 77, 67, 157, 51, 119, 151, 124, 51, 33, 48, 220, 210, 214, 182, + 101, 163, 20, 63, 145, 234, 219, 13, 116, 58, 53, 195, 104, 192, + 89, 250, 9, 3, 36, 83, 39, 244, 68, 23, 191, 9, 65, 30, + 193, 214, 49, 209, 142, 39, 1, 164, 48, 95, 125, 210, 194, 159, + 151, 107, 245, 188, 97, 86, 121, 225, 95, 97, 42, 38, 37, 49, + 196, 101, 245, 119, 135, 27, 197, 196, 219, 13, 92, 54, 221, 173, + 14, 1, 253, 42, 113, 126, 68, 75, 181, 120, 247, 18, 155, 66, + 24, 212, 147, 208, 245, 202, 216, 197, 168, 92, 255, 60, 151, 76, + 224, 63, 159, 216, 29, 71, 135, 4, 110, 100, 210, 130, 60, 17, + 217, 8, 232, 66, 140, 136, 67, 250, 238, 237, 192, 204, 122, 61, + 139, 151, 201, 2, 104, 108, 39, 38, 69, 96, 178, 56, 116, 37, + 79, 167, 100, 206, 186, 199, 165, 190, 12, 20, 74, 44, 240, 244, + 3, 34, 74, 90, 26, 137, 30, 22, 27, 236, 255, 79, 229, 235, + 36, 127, 75, 79, 16, 113, 99, 139, 65, 9, 187, 8, 43, 194, + 12, 194, 24, 197, 160, 78, 94, 228, 183, 25, 1, 217, 233, 0, + 164, 212, 188, 187, 75, 59, 84, 39, 164, 101, 117, 158, 141, 39, + 61, 245, 116, 195, 187, 46, 114, 141, 239, 127, 24, 143, 24, 192, + 76, 211, 174, 64, 35, 120, 137, 18, 23, 103, 107, 78, 228, 24, + 248, 30, 12, 80, 111, 73, 122, 190, 217, 96, 195, 68, 64, 68, + 199, 232, 96, 132, 254, 86, 235, 173, 12, 104, 121, 73, 92, 217, + 138, 13, 245, 75, 63, 20, 236, 153, 201, 136, 171, 223, 61, 34, + 114, 111, 101, 201, 27, 88, 169, 141, 40, 161, 154, 60, 133, 190, + 208, 247, 195, 98, 195, 13, 76, 227, 110, 124, 25, 191, 125, 91, + 142, 186, 221, 77, 59, 34, 72, 230, 210, 208, 207, 48, 226, 241, + 148, 104, 177, 218, 109, 132, 166, 202, 87, 94, 79, 157, 231, 68, + 2, 252, 220, 94, 102, 46, 225, 2, 10, 189, 235, 88, 238, 122, + 175, 26, 57, 43, 9, 116, 128, 185, 114, 15, 78, 73, 172, 3, + 121, 6, 148, 134, 163, 117, 216, 153, 169, 236, 97, 13, 124, 208, + 120, 36, 172, 141, 244, 18, 151, 241, 116, 53, 83, 37, 105, 231, + 176, 23, 41, 245, 57, 3, 201, 235, 34, 30, 3, 105, 225, 55, + 255, 211, 150, 255, 40, 211, 123, 49, 124, 130, 203, 149, 95, 216, + 249, 126, 56, 205, 64, 24, 45, 227, 114, 74, 132, 202, 53, 141, + 10, 116, 136, 190, 131, 245, 249, 136, 89, 112, 204, 78, 117, 239, + 48, 253, 92, 114, 198, 62, 81, 41, 130, 37, 205, 100, 97, 90, + 120, 151, 104, 226, 195, 12, 184, 140, 100, 39, 114, 40, 45, 44, + 159, 186, 244, 36, 74, 73, 101, 57, 61, 128, 25, 2, 137, 171, + 50, 69, 120, 234, 27, 14, 43, 246, 69, 248, 244, 25, 234, 20, + 160, 22, 204, 171, 154, 98, 170, 50, 45, 229, 8, 193, 84, 67, + 205, 187, 54, 156, 172, 136, 103, 114, 187, 42, 114, 84, 108, 237, + 198, 167, 68, 53, 149, 51, 17, 162, 31, 114, 160, 201, 98, 97, + 127, 15, 196, 194, 141, 115, 154, 228, 71, 48, 82, 110, 46, 65, + 24, 75, 151, 142, 70, 128, 231, 229, 108, 138, 210, 35, 152, 113, + 204, 106, 202, 145, 182, 64, 42, 228, 111, 60, 50, 133, 221, 4, + 245, 109, 44, 248, 161, 162, 192, 33, 211, 165, 127, 104, 77, 243, + 131, 215, 60, 107, 33, 82, 191, 137, 171, 7, 245, 209, 240, 244, + 226, 142, 35, 84, 123, 176, 90, 35, 242, 32, 78, 10, 66, 194, + 163, 179, 22, 173, 225, 60, 24, 148, 131, 71, 187, 193, 134, 160, + 44, 156, 161, 17, 187, 146, 150, 193, 125, 69, 170, 179, 245, 230, + 151, 5, 59, 129, 169, 134, 118, 10, 152, 255, 246, 225, 76, 8, + 164, 92, 239, 0, 216, 176, 25, 163, 45, 188, 70, 201, 223, 211, + 31, 121, 2, 83, 119, 130, 100, 17, 36, 43, 86, 137, 98, 2, + 78, 47, 255, 57, 137, 173, 97, 229, 169, 170, 145, 254, 140, 16, + 110, 176, 73, 248, 88, 249, 112, 160, 239, 155, 49, 247, 236, 210, + 39, 51, 196, 236, 96, 176, 34, 143, 80, 10, 140, 203, 52, 154, + 29, 113, 63, 17, 63, 83, 210, 56, 202, 112, 30, 8, 30, 43, + 133, 221, 249, 221, 125, 162, 234, 114, 115, 62, 242, 249, 178, 111, + 6, 51, 171, 79, 103, 137, 145, 48, 209, 30, 18, 143, 0, 13, + 45, 236, 254, 221, 90, 152, 176, 149, 58, 152, 19, 17, 253, 185, + 129, 109, 50, 111, 54, 112, 12, 187, 156, 138, 15, 89, 30, 171, + 167, 114, 98, 51, 18, 131, 29, 75, 49, 9, 107, 236, 96, 222, + 192, 170, 87, 2, 143, 124, 165, 179, 198, 225, 102, 151, 163, 30, + 96, 95, 186, 81, 72, 105, 220, 22, 63, 247, 170, 29, 111, 244, + 78, 203, 115, 172, 68, 36, 71, 23, 6, 189, 67, 193, 87, 74, + 240, 196, 27, 104, 8, 254, 94, 34, 74, 172, 96, 128, 8, 167, + 181, 61, 149, 32, 17, 149, 142, 169, 55, 105, 6, 135, 40, 212, + 220, 210, 190, 90, 90, 192, 199, 123, 56, 206, 41, 189, 71, 139, + 61, 14, 138, 243, 118, 228, 229, 1, 7, 42, 216, 87, 102, 189, + 41, 43, 150, 90, 56, 240, 116, 151, 180, 210, 118, 178, 73, 132, + 190, 33, 183, 152, 6, 34, 199, 18, 205, 153, 190, 119, 70, 47, + 106, 222, 16, 188, 186, 64, 7, 181, 107, 155, 67, 173, 173, 59, + 195, 212, 73, 126, 98, 253, 54, 117, 63, 181, 4, 96, 66, 136, + 229, 62, 106, 42, 95, 11, 74, 119, 218, 37, 112, 108, 5, 195, + 58, 10, 137, 231, 234, 121, 220, 83, 217, 78, 253, 187, 12, 42, + 188, 61, 221, 146, 198, 132, 247, 161, 127, 189, 38, 182, 68, 217, + 48, 76, 134, 28, 117, 237, 126, 197, 112, 246, 45, 190, 47, 119, + 238, 9, 88, 127, 34, 167, 244, 184, 129, 26, 19, 173, 220, 47, + 215, 178, 254, 194, 23, 83, 1, 19, 107, 243, 119, 207, 6, 144, + 73, 107, 143, 161, 251, 223, 236, 102, 112, 173, 199, 94, 104, 112, + 14, 176, 51, 123, 172, 14, 233, 254, 41, 229, 236, 144, 28, 154, + 10, 33, 81, 222, 255, 215, 37, 10, 203, 41, 236, 162, 213, 177, + 8, 228, 136, 68, 216, 131, 71, 164, 63, 44, 118, 210, 137, 75, + 229, 14, 254, 64, 139, 111, 213, 37, 164, 80, 189, 169, 181, 9, + 224, 144, 196, 15, 202, 94, 236, 219, 244, 187, 186, 151, 50, 114, + 14, 147, 223, 135, 180, 202, 182, 118, 210, 251, 47, 176, 97, 199, + 180, 108, 53, 124, 192, 148, 1, 29, 172, 124, 2, 124, 205, 172, + 92, 5, 167, 16, 73, 148, 6, 31, 198, 43, 61, 229, 56, 6, + 63, 126, 193, 179, 45, 39, 158, 99, 11, 171, 100, 198, 91, 89, + 214, 237, 30, 113, 218, 15, 83, 178, 254, 174, 226, 131, 15, 162, + 144, 20, 108, 47, 53, 152, 131, 48, 181, 55, 41, 234, 55, 197, + 154, 187, 239, 85, 59, 239, 8, 241, 133, 250, 153, 189, 214, 217, + 223, 145, 2, 147, 249, 146, 73, 113, 187, 220, 129, 122, 227, 237, + 229, 126, 215, 58, 146, 16, 36, 95, 208, 113, 9, 150, 132, 238, + 232, 67, 210, 8, 160, 128, 70, 23, 21, 51, 201, 247, 147, 51, + 46, 158, 189, 172, 49, 205, 202, 245, 108, 98, 13, 175, 73, 205, + 182, 96, 197, 94, 225, 189, 47, 112, 195, 19, 14, 143, 27, 92, + 160, 142, 99, 94, 87, 120, 173, 7, 158, 211, 80, 233, 234, 118, + 154, 204, 210, 121, 20, 69, 191, 108, 3, 146, 153, 234, 232, 140, + 128, 52, 156, 93, 87, 57, 7, 205, 19, 214, 134, 234, 9, 71, + 201, 116, 0, 245, 161, 92, 47, 35, 242, 33, 45, 53, 175, 153, + 174, 146, 156, 247, 214, 26, 46, 29, 60, 56, 223, 31, 63, 18, + 227, 184, 57, 216, 226, 233, 18, 52, 156, 227, 47, 36, 45, 112, + 71, 62, 111, 39, 198, 216, 59, 14, 148, 6, 124, 133, 70, 108, + 119, 203, 212, 23, 243, 192, 227, 203, 5, 88, 177, 144, 78, 78, + 163, 48, 243, 154, 140, 3, 130, 38, 247, 6, 223, 178, 16, 67, + 137, 230, 118, 166, 190, 211, 178, 27, 166, 21, 75, 204, 161, 98, + 151, 40, 138, 57, 230, 59, 184, 148, 152, 142, 47, 241, 225, 215, + 78, 95, 67, 53, 93, 123, 150, 8, 199, 21, 7, 89, 158, 207, + 150, 109, 92, 66, 28, 38, 185, 83, 209, 8, 158, 143, 55, 203, + 144, 155, 83, 123, 216, 85, 89, 24, 166, 66, 78, 33, 109, 122, + 240, 170, 73, 178, 118, 155, 180, 111, 120, 86, 105, 17, 57, 150, + 212, 235, 33, 185, 104, 132, 82, 211, 170, 122, 23, 114, 142, 103, + 156, 104, 164, 46, 24, 100, 18, 183, 176, 109, 94, 90, 200, 210, + 208, 193, 91, 232, 204, 167, 55, 145, 112, 143, 245, 31, 222, 104, + 231, 19, 116, 81, 128, 180, 230, 4, 143, 5, 100, 53, 20, 255, + 170, 160, 6, 215, 3, 91, 164, 204, 125, 27, 253, 237, 211, 26, + 77, 99, 171, 147, 153, 228, 255, 134, 51, 107, 54, 224, 152, 74, + 115, 16, 198, 115, 231, 237, 150, 178, 47, 115, 73, 141, 176, 214, + 205, 75, 62, 14, 43, 117, 82, 203, 61, 205, 35, 221, 95, 68, + 250, 8, 78, 23, 234, 26, 38, 117, 240, 36, 181, 53, 100, 151, + 157, 46, 188, 179, 226, 135, 155, 65, 163, 181, 219, 19, 146, 115, + 159, 19, 67, 89, 29, 195, 119, 215, 22, 196, 65, 123, 32, 65, + 87, 31, 66, 227, 81, 35, 212, 36, 49, 227, 113, 133, 174, 114, + 47, 228, 183, 200, 56, 33, 199, 25, 52, 213, 0, 67, 86, 22, + 223, 139, 124, 209, 206, 100, 115, 166, 2, 6, 13, 231, 86, 105, + 166, 219, 220, 205, 64, 53, 236, 227, 192, 0, 133, 94, 249, 85, + 52, 199, 164, 6, 176, 148, 230, 117, 33, 37, 5, 229, 129, 131, + 18, 162, 55, 95, 184, 242, 224, 14, 99, 47, 252, 141, 228, 206, + 189, 195, 98, 141, 217, 75, 27, 6, 234, 209, 217, 205, 208, 239, + 197, 196, 146, 101, 117, 155, 7, 71, 63, 58, 16, 255, 36, 224, + 183, 23, 159, 20, 113, 169, 65, 131, 71, 123, 19, 47, 86, 45, + 235, 155, 59, 94, 64, 36, 251, 82, 25, 32, 162, 120, 126, 32, + 243, 251, 37, 147, 2, 224, 132, 114, 123, 94, 248, 26, 65, 45, + 207, 77, 193, 168, 132, 85, 217, 4, 183, 240, 49, 187, 251, 124, + 109, 117, 81, 32, 200, 65, 53, 103, 105, 240, 73, 73, 218, 0, + 248, 142, 137, 156, 5, 166, 38, 97, 32, 33, 163, 144, 126, 128, + 42, 199, 220, 216, 8, 57, 151, 94, 6, 88, 37, 123, 242, 132, + 168, 169, 36, 207, 211, 119, 59, 110, 125, 65, 47, 210, 42, 117, + 116, 18, 58, 122, 129, 83, 126, 203, 35, 13, 108, 131, 222, 96, + 0, 49, 60, 74, 13, 211, 91, 33, 196, 141, 41, 107, 65, 203, + 211, 66, 38, 193, 205, 35, 37, 189, 132, 166, 251, 25, 231, 203, + 61, 197, 253, 222, 151, 186, 186, 9, 90, 79, 160, 46, 133, 158, + 70, 101, 59, 110, 169, 14, 72, 188, 147, 254, 98, 241, 9, 221, + 11, 244, 232, 238, 175, 84, 237, 22, 65, 126, 242, 224, 200, 168, + 85, 179, 178, 160, 123, 251, 5, 128, 104, 55, 33, 164, 114, 212, + 68, 151, 227, 77, 243, 187, 134, 0, 25, 13, 76, 192, 253, 194, + 197, 183, 52, 110, 73, 209, 116, 57, 60, 168, 184, 209, 88, 47, + 139, 23, 251, 59, 187, 44, 136, 157, 59, 86, 52, 12, 71, 176, + 134, 91, 18, 149, 255, 20, 145, 227, 156, 114, 179, 123, 195, 0, + 175, 140, 137, 159, 40, 60, 12, 136, 161, 217, 171, 40, 216, 221, + 150, 104, 209, 165, 130, 143, 147, 46, 223, 188, 37, 45, 20, 156, + 73, 201, 1, 12, 68, 40, 219, 7, 197, 173, 63, 59, 93, 145, + 48, 22, 172, 100, 253, 254, 115, 13, 222, 144, 134, 191, 165, 58, + 205, 44, 163, 37, 195, 143, 80, 233, 78, 4, 73, 154, 35, 104, + 234, 224, 17, 18, 132, 36, 102, 171, 9, 136, 8, 165, 2, 245, + 97, 213, 230, 120, 246, 26, 159, 70, 145, 228, 32, 93, 74, 151, + 52, 109, 238, 203, 239, 19, 109, 180, 190, 185, 156, 129, 250, 34, + 233, 174, 39, 28, 215, 255, 209, 68, 55, 106, 215, 134, 10, 33, + 33, 20, 158, 106, 40, 219, 53, 11, 193, 105, 108, 131, 171, 137, + 242, 68, 253, 43, 229, 28, 165, 182, 8, 245, 154, 156, 175, 213, + 6, 97, 228, 2, 146, 192, 25, 88, 171, 165, 82, 20, 213, 194, + 185, 220, 115, 231, 106, 130, 130, 126, 210, 15, 162, 111, 63, 130, + 208, 242, 49, 77, 209, 182, 38, 100, 234, 200, 68, 74, 235, 195, + 223, 124, 4, 151, 218, 180, 91, 210, 24, 53, 36, 179, 237, 228, + 33, 200, 88, 212, 157, 154, 5, 121, 136, 95, 139, 240, 229, 200, + 145, 10, 187, 41, 95, 70, 104, 240, 215, 219, 55, 115, 173, 132, + 253, 111, 247, 5, 223, 166, 81, 25, 45, 184, 181, 57, 180, 1, + 94, 125, 240, 44, 95, 78, 86, 5, 224, 28, 226, 47, 103, 4, + 21, 247, 120, 93, 212, 73, 193, 80, 14, 240, 130, 249, 81, 254, + 34, 60, 114, 216, 107, 194, 147, 177, 197, 231, 59, 237, 178, 156, + 103, 202, 211, 204, 48, 133, 37, 220, 22, 26, 102, 66, 224, 161, + 220, 176, 166, 19, 232, 29, 176, 37, 119, 11, 14, 131, 74, 91, + 117, 135, 184, 128, 15, 25, 75, 181, 106, 204, 16, 12, 175, 243, + 225, 134, 187, 224, 89, 210, 190, 167, 116, 229, 167, 31, 131, 113, + 178, 121, 169, 104, 1, 40, 84, 175, 232, 243, 204, 186, 27, 15, + 251, 145, 138, 154, 234, 55, 167, 121, 216, 209, 37, 67, 10, 31, + 123, 101, 178, 157, 116, 28, 237, 248, 82, 213, 202, 81, 239, 225, + 83, 164, 69, 23, 139, 200, 123, 152, 237, 62, 152, 111, 237, 130, + 103, 96, 36, 166, 131, 207, 1, 101, 29, 161, 192, 110, 118, 29, + 96, 176, 49, 68, 84, 79, 217, 113, 235, 125, 59, 48, 99, 32, + 144, 124, 179, 132, 193, 175, 14, 14, 243, 214, 233, 66, 150, 86, + 61, 139, 174, 214, 89, 230, 26, 18, 150, 132, 165, 203, 172, 202, + 204, 69, 153, 190, 202, 0, 146, 73, 209, 11, 33, 255, 118, 7, + 138, 46, 160, 187, 28, 130, 126, 89, 142, 192, 2, 163, 38, 20, + 44, 7, 178, 142, 193, 171, 91, 51, 53, 4, 225, 198, 185, 229, + 226, 78, 231, 77, 137, 234, 100, 23, 243, 30, 214, 185, 97, 53, + 77, 1, 113, 145, 69, 102, 30, 30, 80, 42, 184, 44, 227, 203, + 22, 126, 178, 204, 214, 115, 59, 0, 179, 15, 219, 181, 58, 110, + 9, 17, 67, 202, 14, 23, 223, 74, 135, 70, 34, 161, 220, 104, + 47, 128, 79, 219, 155, 245, 37, 212, 15, 245, 140, 73, 198, 119, + 122, 67, 81, 56, 55, 14, 162, 58, 126, 81, 172, 144, 73, 84, + 108, 203, 132, 30, 60, 94, 121, 31, 194, 239, 0, 198, 155, 182, + 126, 246, 232, 112, 124, 143, 153, 192, 81, 217, 1, 110, 125, 70, + 23, 13, 180, 87, 154, 228, 68, 134, 243, 254, 255, 208, 152, 199, + 132, 163, 112, 69, 217, 144, 195, 201, 157, 247, 243, 243, 70, 102, + 35, 79, 60, 223, 219, 49, 226, 213, 27, 136, 167, 77, 228, 11, + 252, 179, 221, 152, 245, 196, 242, 150, 42, 243, 149, 5, 128, 247, + 113, 24, 16, 170, 177, 99, 27, 69, 178, 243, 60, 0, 122, 245, + 56, 161, 152, 222, 128, 68, 252, 56, 175, 45, 65, 174, 109, 203, + 221, 122, 10, 9, 84, 67, 32, 154, 78, 38, 206, 107, 216, 139, + 16, 193, 216, 64, 179, 255, 162, 151, 75, 203, 236, 111, 91, 6, + 184, 165, 249, 4, 170, 158, 253, 25, 99, 145, 135, 199, 239, 229, + 217, 119, 94, 49, 9, 195, 58, 70, 194, 43, 233, 144, 142, 190, + 227, 109, 153, 61, 141, 209, 183, 116, 76, 53, 48, 64, 24, 79, + 51, 28, 212, 227, 61, 188, 215, 68, 224, 143, 174, 149, 146, 149, + 168, 59, 133, 66, 147, 168, 74, 76, 122, 62, 154, 152, 33, 181, + 24, 56, 173, 4, 165, 219, 227, 55, 23, 234, 107, 38, 14, 199, + 254, 66, 105, 139, 251, 28, 36, 164, 25, 222, 43, 70, 188, 169, + 105, 111, 4, 9, 253, 235, 196, 29, 62, 107, 230, 248, 152, 59, + 148, 99, 138, 49, 22, 9, 176, 57, 67, 148, 227, 64, 2, 46, + 161, 209, 109, 47, 151, 112, 117, 81, 42, 93, 19, 197, 192, 184, + 14, 103, 132, 213, 70, 30, 60, 158, 106, 66, 207, 2, 17, 33, + 202, 245, 159, 141, 60, 234, 234, 114, 65, 236, 232, 133, 214, 125, + 21, 16, 129, 239, 71, 108, 196, 87, 79, 172, 17, 167, 37, 103, + 113, 7, 93, 6, 0, 225, 116, 122, 126, 41, 247, 102, 248, 169, + 221, 237, 153, 143, 169, 102, 33, 160, 25, 250, 215, 115, 92, 81, + 251, 211, 127, 85, 194, 175, 153, 221, 46, 81, 237, 26, 69, 219, + 194, 208, 100, 46, 4, 230, 185, 185, 197, 175, 58, 33, 30, 67, + 184, 210, 108, 2, 201, 80, 1, 183, 196, 172, 72, 236, 19, 159, + 170, 107, 144, 90, 93, 114, 247, 48, 168, 115, 26, 140, 223, 63, + 52, 32, 241, 236, 220, 228, 87, 78, 48, 47, 92, 172, 156, 105, + 175, 20, 227, 112, 187, 172, 68, 28, 229, 97, 1, 157, 184, 164, + 5, 217, 38, 103, 200, 81, 4, 58, 194, 214, 40, 17, 132, 73, + 20, 97, 163, 24, 22, 91, 164, 103, 16, 162, 68, 73, 35, 107, + 12, 205, 66, 199, 226, 198, 185, 210, 173, 196, 0, 94, 183, 55, + 36, 13, 64, 33, 93, 100, 143, 216, 159, 253, 94, 184, 235, 194, + 195, 89, 46, 193, 9, 127, 195, 35, 147, 205, 228, 54, 71, 152, + 57, 100, 176, 210, 65, 102, 72, 213, 179, 201, 124, 253, 152, 107, + 127, 95, 67, 76, 101, 14, 179, 163, 243, 51, 77, 101, 225, 137, + 2, 228, 152, 138, 3, 179, 187, 63, 247, 154, 163, 89, 58, 64, + 135, 214, 233, 51, 203, 190, 75, 152, 120, 15, 167, 170, 187, 26, + 55, 74, 186, 99, 27, 181, 155, 218, 236, 128, 174, 76, 0, 218, + 136, 154, 168, 57, 242, 254, 179, 124, 158, 42, 30, 59, 154, 147, + 22, 19, 115, 217, 169, 29, 247, 139, 98, 176, 10, 203, 184, 64, + 132, 19, 1, 236, 166, 123, 170, 7, 235, 238, 209, 237, 3, 45, + 212, 150, 237, 219, 234, 124, 146, 150, 105, 49, 27, 34, 227, 110, + 82, 170, 89, 11, 249, 16, 195, 217, 225, 66, 202, 196, 219, 137, + 78, 222, 102, 5, 223, 95, 78, 49, 216, 57, 226, 7, 230, 82, + 128, 92, 146, 45, 138, 38, 189, 84, 87, 228, 93, 95, 213, 93, + 23, 29, 24, 221, 174, 221, 58, 245, 91, 52, 247, 56, 86, 97, + 243, 68, 121, 227, 242, 39, 120, 3, 239, 91, 24, 97, 92, 106, + 181, 34, 21, 226, 106, 210, 186, 200, 98, 8, 204, 4, 221, 135, + 92, 39, 213, 169, 30, 155, 131, 79, 19, 32, 78, 98, 1, 177, + 6, 45, 233, 207, 248, 225, 143, 198, 74, 16, 192, 248, 119, 108, + 132, 156, 177, 174, 7, 54, 244, 207, 96, 245, 239, 165, 29, 224, + 197, 157, 136, 84, 225, 214, 240, 30, 235, 169, 231, 121, 21, 16, + 26, 227, 51, 94, 183, 175, 123, 195, 25, 251, 235, 249, 83, 60, + 40, 88, 198, 222, 104, 60, 18, 144, 42, 28, 199, 61, 21, 11, + 170, 213, 164, 59, 175, 101, 49, 219, 205, 249, 199, 34, 132, 178, + 170, 65, 79, 16, 120, 231, 222, 248, 168, 5, 208, 161, 234, 64, + 47, 39, 147, 231, 47, 120, 158, 213, 165, 142, 62, 80, 232, 189, + 245, 236, 87, 36, 240, 42, 141, 115, 245, 44, 179, 140, 203, 136, + 254, 219, 112, 144, 61, 187, 127, 70, 241, 240, 161, 148, 63, 116, + 227, 247, 53, 148, 50, 144, 188, 156, 93, 187, 73, 218, 56, 184, + 237, 242, 186, 20, 59, 56, 143, 52, 12, 19, 63, 220, 66, 203, + 195, 207, 115, 19, 5, 187, 196, 48, 175, 142, 225, 244, 16, 169, + 134, 52, 29, 167, 76, 189, 145, 67, 146, 235, 239, 183, 254, 181, + 194, 188, 233, 166, 254, 69, 97, 253, 97, 107, 151, 61, 34, 38, + 216, 68, 120, 249, 234, 98, 91, 201, 51, 137, 47, 213, 144, 5, + 0, 144, 201, 76, 128, 1, 20, 2, 0, 0, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 99, 108, + 101, 97, 114, 116, 111, 109, 97, 114, 107, 13, 128, 3, +}; diff --git a/Rendering/fonts/face_courier_bold.cxx b/Rendering/fonts/face_courier_bold.cxx new file mode 100644 index 0000000..bb7cad3 --- /dev/null +++ b/Rendering/fonts/face_courier_bold.cxx @@ -0,0 +1,2868 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Courier Bold +// Courier 10 Pitch Bold (c0583bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_courier_bold_buffer_length = 40008; + +unsigned char face_courier_bold_buffer[] = { + 128, 1, 215, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 83, + 117, 110, 32, 78, 111, 118, 32, 32, 52, 32, 49, 57, 58, 51, + 49, 58, 49, 48, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 67, + 111, 117, 114, 105, 101, 114, 32, 49, 48, 32, 80, 105, 116, 99, + 104, 32, 66, 111, 108, 100, 41, 32, 114, 101, 97, 100, 111, 110, + 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 70, 97, 109, 105, + 108, 121, 78, 97, 109, 101, 32, 40, 67, 111, 117, 114, 105, 101, + 114, 32, 49, 48, 32, 80, 105, 116, 99, 104, 41, 32, 114, 101, + 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, + 87, 101, 105, 103, 104, 116, 32, 40, 66, 111, 108, 100, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, + 32, 47, 73, 116, 97, 108, 105, 99, 65, 110, 103, 108, 101, 32, + 48, 32, 100, 101, 102, 13, 32, 32, 47, 105, 115, 70, 105, 120, + 101, 100, 80, 105, 116, 99, 104, 32, 116, 114, 117, 101, 32, 100, + 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, + 101, 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 57, 55, 32, + 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, + 110, 101, 84, 104, 105, 99, 107, 110, 101, 115, 115, 32, 57, 51, + 32, 100, 101, 102, 13, 101, 110, 100, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 78, + 97, 109, 101, 32, 47, 67, 111, 117, 114, 105, 101, 114, 49, 48, + 80, 105, 116, 99, 104, 66, 84, 45, 66, 111, 108, 100, 32, 100, + 101, 102, 13, 47, 80, 97, 105, 110, 116, 84, 121, 112, 101, 32, + 48, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 84, 121, 112, + 101, 32, 49, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 77, + 97, 116, 114, 105, 120, 32, 91, 48, 46, 48, 48, 49, 32, 48, + 32, 48, 32, 48, 46, 48, 48, 49, 32, 48, 32, 48, 93, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, + 69, 110, 99, 111, 100, 105, 110, 103, 32, 83, 116, 97, 110, 100, + 97, 114, 100, 69, 110, 99, 111, 100, 105, 110, 103, 32, 100, 101, + 102, 13, 47, 70, 111, 110, 116, 66, 66, 111, 120, 32, 123, 45, + 52, 52, 32, 45, 51, 48, 57, 32, 54, 54, 52, 32, 56, 55, + 53, 125, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, + 102, 13, 47, 85, 110, 105, 113, 117, 101, 73, 68, 32, 49, 53, + 53, 51, 48, 53, 56, 51, 32, 100, 101, 102, 13, 99, 117, 114, + 114, 101, 110, 116, 100, 105, 99, 116, 32, 101, 110, 100, 13, 99, + 117, 114, 114, 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, + 101, 99, 13, 128, 2, 73, 148, 0, 0, 162, 149, 24, 64, 131, + 138, 65, 51, 131, 156, 169, 210, 46, 43, 153, 242, 182, 28, 118, + 124, 214, 117, 8, 10, 172, 252, 178, 78, 25, 205, 19, 54, 115, + 155, 182, 73, 148, 197, 103, 55, 9, 11, 76, 236, 146, 201, 148, + 95, 240, 116, 94, 247, 255, 198, 27, 176, 169, 163, 184, 73, 231, + 233, 135, 64, 229, 108, 11, 90, 247, 135, 85, 156, 198, 149, 106, + 179, 30, 51, 207, 133, 83, 213, 92, 11, 14, 129, 142, 245, 236, + 107, 244, 129, 98, 234, 196, 46, 115, 128, 202, 146, 29, 174, 28, + 130, 179, 143, 214, 188, 242, 0, 26, 187, 93, 0, 26, 86, 21, + 112, 148, 207, 226, 125, 143, 78, 172, 150, 147, 232, 131, 114, 210, + 3, 88, 180, 126, 12, 56, 118, 85, 142, 191, 117, 122, 31, 188, + 92, 28, 221, 246, 43, 60, 87, 191, 114, 126, 241, 196, 135, 148, + 34, 193, 66, 160, 132, 209, 199, 70, 42, 194, 147, 224, 151, 250, + 190, 58, 62, 207, 205, 130, 113, 242, 89, 131, 59, 172, 121, 18, + 112, 114, 24, 236, 154, 48, 99, 191, 115, 133, 224, 45, 140, 16, + 88, 172, 6, 223, 0, 179, 59, 140, 1, 135, 104, 178, 120, 1, + 14, 178, 127, 94, 177, 18, 214, 48, 220, 65, 177, 171, 175, 91, + 243, 199, 6, 173, 165, 169, 173, 20, 196, 58, 195, 84, 191, 23, + 205, 41, 104, 116, 142, 32, 16, 220, 114, 205, 102, 33, 131, 58, + 163, 215, 21, 119, 224, 110, 14, 31, 218, 59, 15, 185, 149, 32, + 233, 64, 65, 246, 154, 168, 212, 168, 175, 8, 134, 218, 55, 5, + 106, 178, 253, 94, 233, 232, 12, 153, 52, 239, 27, 169, 57, 42, + 223, 14, 79, 43, 133, 55, 107, 42, 50, 205, 40, 168, 17, 227, + 134, 242, 216, 168, 15, 63, 55, 32, 43, 128, 2, 95, 4, 186, + 170, 6, 99, 98, 98, 146, 172, 133, 121, 105, 97, 74, 175, 65, + 0, 87, 20, 113, 32, 207, 132, 86, 161, 57, 250, 247, 56, 9, + 128, 215, 253, 112, 74, 201, 69, 151, 118, 212, 240, 20, 117, 6, + 158, 249, 58, 18, 35, 205, 136, 219, 104, 59, 141, 53, 8, 217, + 10, 114, 153, 252, 231, 71, 226, 67, 41, 227, 44, 254, 203, 75, + 247, 216, 203, 56, 96, 149, 196, 27, 194, 98, 117, 36, 17, 179, + 129, 73, 8, 229, 197, 196, 141, 252, 60, 15, 176, 191, 181, 212, + 254, 155, 236, 28, 108, 191, 205, 88, 14, 180, 198, 155, 192, 195, + 94, 253, 92, 28, 104, 9, 147, 53, 123, 162, 115, 183, 66, 172, + 212, 196, 51, 106, 67, 205, 86, 82, 128, 200, 234, 42, 160, 87, + 5, 195, 82, 235, 89, 48, 139, 173, 206, 175, 95, 6, 62, 237, + 51, 96, 169, 190, 94, 125, 104, 58, 89, 143, 233, 39, 177, 182, + 182, 241, 240, 50, 184, 87, 114, 240, 85, 250, 248, 225, 87, 220, + 114, 52, 15, 237, 154, 207, 224, 133, 64, 223, 186, 85, 155, 18, + 162, 218, 2, 58, 3, 47, 193, 241, 51, 209, 57, 199, 70, 52, + 4, 123, 0, 102, 189, 225, 6, 191, 4, 219, 130, 198, 67, 216, + 90, 147, 231, 30, 134, 172, 176, 250, 159, 140, 47, 148, 168, 17, + 69, 87, 16, 121, 183, 7, 208, 86, 186, 208, 75, 111, 171, 125, + 202, 225, 98, 139, 206, 218, 110, 191, 48, 65, 56, 101, 56, 216, + 222, 34, 99, 232, 26, 249, 61, 218, 90, 173, 82, 72, 200, 193, + 145, 118, 21, 215, 175, 91, 115, 125, 154, 204, 222, 110, 255, 206, + 97, 25, 136, 50, 1, 240, 144, 192, 169, 131, 119, 167, 222, 63, + 20, 15, 107, 212, 201, 228, 28, 53, 85, 201, 129, 81, 6, 60, + 141, 160, 196, 111, 241, 217, 136, 89, 17, 20, 137, 165, 198, 43, + 128, 96, 53, 230, 141, 187, 249, 76, 210, 154, 105, 51, 14, 150, + 194, 1, 170, 21, 46, 222, 224, 200, 83, 161, 215, 25, 75, 201, + 153, 94, 250, 148, 77, 87, 98, 34, 196, 2, 220, 130, 39, 109, + 202, 71, 150, 158, 76, 194, 210, 174, 65, 117, 254, 19, 109, 137, + 200, 177, 97, 233, 161, 227, 41, 136, 163, 89, 146, 255, 133, 128, + 156, 113, 222, 89, 167, 116, 86, 214, 64, 72, 57, 106, 97, 195, + 216, 137, 242, 42, 161, 214, 21, 180, 168, 59, 38, 27, 21, 83, + 123, 55, 133, 43, 203, 195, 129, 48, 51, 165, 208, 159, 99, 228, + 66, 197, 67, 193, 212, 89, 65, 199, 63, 105, 86, 230, 190, 204, + 72, 226, 245, 139, 86, 118, 59, 154, 155, 68, 240, 167, 144, 180, + 99, 97, 158, 170, 89, 161, 160, 251, 245, 102, 67, 2, 150, 97, + 86, 222, 155, 102, 163, 192, 145, 127, 207, 55, 237, 237, 135, 34, + 154, 10, 95, 202, 196, 96, 18, 243, 164, 254, 253, 77, 202, 104, + 80, 47, 19, 114, 220, 189, 16, 253, 167, 88, 142, 142, 26, 14, + 156, 95, 158, 214, 229, 161, 132, 60, 134, 85, 252, 233, 118, 48, + 135, 104, 190, 71, 102, 85, 73, 95, 90, 235, 30, 250, 34, 187, + 74, 216, 17, 86, 177, 200, 185, 108, 186, 110, 119, 170, 59, 62, + 147, 157, 243, 59, 151, 101, 229, 57, 175, 191, 43, 104, 10, 118, + 75, 175, 231, 218, 244, 75, 43, 1, 127, 8, 110, 80, 177, 233, + 210, 162, 210, 102, 142, 219, 185, 214, 176, 97, 227, 143, 196, 96, + 33, 240, 57, 23, 105, 23, 208, 254, 116, 148, 247, 104, 9, 29, + 80, 251, 153, 127, 248, 244, 94, 230, 31, 153, 3, 25, 94, 170, + 55, 218, 15, 37, 4, 145, 136, 187, 237, 162, 205, 0, 133, 199, + 146, 223, 117, 31, 135, 98, 161, 46, 107, 22, 213, 223, 198, 163, + 86, 58, 98, 214, 15, 123, 92, 5, 42, 234, 7, 131, 116, 206, + 124, 7, 242, 73, 189, 74, 183, 244, 175, 156, 222, 173, 79, 70, + 2, 149, 127, 49, 163, 76, 209, 163, 111, 92, 49, 50, 88, 113, + 236, 73, 117, 95, 92, 195, 187, 41, 171, 58, 163, 83, 66, 41, + 184, 103, 135, 112, 209, 131, 27, 61, 140, 23, 103, 99, 254, 70, + 23, 226, 211, 118, 22, 30, 245, 25, 43, 189, 55, 177, 188, 113, + 219, 84, 28, 193, 218, 4, 101, 35, 27, 242, 129, 235, 249, 76, + 71, 84, 228, 112, 88, 2, 64, 103, 72, 182, 67, 195, 127, 191, + 176, 37, 140, 213, 154, 147, 13, 31, 37, 178, 205, 238, 83, 31, + 81, 71, 216, 38, 152, 250, 61, 10, 60, 10, 10, 179, 207, 107, + 84, 103, 254, 243, 39, 124, 29, 174, 42, 117, 207, 140, 22, 46, + 122, 72, 82, 52, 92, 238, 58, 125, 123, 111, 213, 150, 97, 87, + 30, 66, 186, 218, 153, 210, 182, 176, 159, 246, 180, 184, 214, 218, + 92, 200, 230, 66, 82, 23, 206, 228, 33, 234, 76, 195, 236, 25, + 209, 81, 210, 160, 154, 115, 181, 128, 170, 37, 121, 26, 0, 4, + 85, 170, 53, 147, 218, 10, 172, 57, 73, 137, 45, 17, 66, 164, + 121, 34, 98, 164, 210, 246, 229, 232, 226, 238, 188, 92, 102, 168, + 8, 25, 125, 22, 47, 28, 26, 172, 145, 213, 74, 222, 70, 98, + 197, 234, 171, 200, 84, 13, 86, 106, 165, 121, 63, 182, 88, 201, + 174, 235, 67, 248, 7, 47, 9, 97, 94, 41, 35, 129, 159, 173, + 156, 200, 123, 133, 46, 102, 248, 16, 27, 57, 22, 102, 241, 122, + 147, 103, 53, 216, 33, 132, 42, 52, 193, 73, 67, 153, 123, 208, + 107, 60, 70, 76, 249, 196, 159, 207, 218, 163, 189, 103, 239, 0, + 199, 150, 51, 237, 167, 31, 248, 20, 124, 127, 1, 69, 72, 51, + 136, 63, 245, 25, 187, 69, 48, 21, 109, 238, 3, 140, 68, 107, + 202, 46, 186, 156, 29, 132, 130, 204, 172, 135, 19, 86, 247, 21, + 44, 199, 69, 1, 39, 35, 174, 124, 124, 173, 27, 183, 133, 221, + 70, 190, 95, 235, 202, 45, 218, 45, 138, 152, 222, 33, 204, 137, + 22, 37, 133, 147, 178, 61, 234, 41, 220, 37, 193, 39, 88, 210, + 46, 105, 99, 176, 88, 135, 151, 23, 223, 170, 134, 52, 163, 240, + 150, 190, 43, 156, 233, 127, 166, 170, 89, 50, 94, 83, 183, 73, + 60, 170, 98, 48, 153, 252, 42, 106, 79, 56, 88, 103, 14, 125, + 199, 107, 163, 96, 222, 170, 239, 205, 9, 17, 89, 123, 17, 187, + 189, 117, 161, 80, 223, 150, 249, 103, 97, 238, 166, 192, 175, 18, + 115, 34, 199, 243, 190, 216, 184, 8, 224, 21, 212, 58, 165, 1, + 51, 174, 89, 160, 54, 51, 151, 200, 150, 12, 247, 71, 144, 39, + 94, 3, 211, 201, 92, 168, 203, 23, 1, 117, 107, 15, 136, 245, + 217, 107, 63, 190, 151, 84, 168, 181, 37, 210, 61, 193, 152, 4, + 157, 16, 30, 38, 113, 138, 50, 236, 115, 217, 195, 208, 164, 109, + 235, 29, 191, 80, 126, 78, 67, 233, 29, 151, 76, 139, 216, 94, + 30, 3, 134, 167, 18, 12, 233, 163, 29, 160, 229, 83, 17, 199, + 31, 133, 28, 14, 19, 125, 178, 232, 137, 253, 127, 80, 189, 133, + 189, 149, 160, 231, 216, 211, 188, 148, 177, 53, 29, 198, 30, 49, + 171, 213, 117, 194, 44, 169, 187, 150, 141, 129, 59, 164, 134, 128, + 4, 20, 60, 222, 195, 98, 119, 189, 197, 195, 13, 229, 146, 81, + 235, 231, 14, 6, 204, 75, 155, 124, 66, 33, 214, 230, 163, 233, + 49, 162, 152, 238, 39, 29, 43, 165, 219, 221, 232, 24, 216, 91, + 209, 196, 93, 77, 249, 194, 184, 95, 6, 8, 9, 121, 231, 62, + 60, 46, 18, 220, 90, 91, 8, 250, 190, 75, 223, 124, 44, 57, + 6, 190, 3, 182, 231, 106, 81, 58, 120, 163, 222, 163, 153, 123, + 65, 70, 195, 187, 132, 122, 96, 234, 138, 134, 210, 58, 130, 180, + 122, 86, 79, 209, 90, 52, 212, 184, 130, 39, 252, 113, 219, 195, + 82, 109, 158, 106, 77, 12, 230, 93, 143, 127, 6, 39, 8, 192, + 61, 56, 228, 237, 160, 190, 129, 201, 244, 251, 183, 122, 99, 70, + 202, 190, 40, 93, 147, 194, 41, 98, 235, 117, 17, 15, 91, 147, + 229, 149, 235, 61, 144, 33, 157, 234, 178, 22, 105, 57, 121, 172, + 157, 131, 183, 181, 105, 151, 252, 248, 231, 48, 1, 70, 127, 33, + 172, 156, 231, 182, 206, 100, 40, 163, 126, 178, 35, 252, 213, 112, + 195, 115, 218, 255, 20, 119, 25, 194, 22, 183, 137, 207, 42, 61, + 13, 151, 31, 196, 79, 65, 83, 85, 101, 89, 14, 136, 46, 245, + 146, 14, 138, 166, 187, 12, 34, 213, 114, 182, 145, 225, 129, 90, + 114, 189, 106, 108, 123, 160, 47, 68, 7, 149, 42, 79, 44, 141, + 19, 117, 210, 157, 248, 172, 17, 189, 82, 252, 32, 19, 139, 13, + 64, 44, 15, 38, 39, 56, 149, 224, 111, 198, 71, 126, 121, 116, + 242, 13, 3, 64, 136, 115, 18, 155, 3, 177, 139, 249, 225, 136, + 142, 73, 125, 50, 226, 193, 226, 244, 54, 146, 185, 87, 166, 196, + 14, 230, 242, 230, 57, 176, 72, 163, 178, 253, 250, 145, 46, 194, + 177, 112, 109, 45, 143, 23, 230, 167, 15, 30, 247, 78, 255, 176, + 119, 221, 136, 35, 22, 3, 181, 102, 127, 82, 83, 216, 5, 234, + 240, 173, 28, 124, 206, 221, 91, 109, 230, 52, 121, 40, 148, 72, + 186, 54, 51, 169, 167, 91, 132, 97, 112, 224, 14, 8, 126, 12, + 22, 104, 143, 191, 216, 228, 175, 236, 56, 107, 224, 231, 90, 28, + 69, 132, 0, 39, 23, 0, 60, 98, 86, 48, 15, 119, 96, 117, + 140, 28, 109, 195, 0, 92, 167, 91, 188, 144, 22, 191, 230, 45, + 199, 239, 181, 3, 38, 15, 144, 118, 131, 201, 79, 48, 16, 205, + 159, 143, 14, 11, 20, 90, 121, 161, 232, 174, 152, 61, 134, 240, + 101, 119, 191, 253, 223, 226, 96, 46, 55, 80, 145, 72, 57, 182, + 152, 91, 225, 223, 142, 139, 219, 133, 183, 176, 12, 144, 57, 24, + 77, 14, 11, 10, 124, 177, 244, 67, 19, 31, 184, 139, 243, 212, + 69, 118, 111, 219, 109, 96, 130, 72, 233, 100, 254, 28, 136, 89, + 36, 63, 195, 160, 202, 177, 120, 28, 101, 103, 48, 226, 29, 41, + 41, 235, 15, 45, 100, 56, 205, 117, 209, 56, 104, 38, 66, 1, + 36, 233, 188, 146, 100, 179, 166, 212, 52, 131, 209, 3, 66, 230, + 100, 219, 12, 92, 37, 247, 252, 152, 232, 241, 129, 237, 164, 199, + 185, 158, 2, 255, 111, 144, 205, 67, 177, 17, 131, 140, 35, 190, + 188, 106, 115, 204, 168, 167, 232, 76, 81, 33, 155, 100, 194, 226, + 235, 72, 225, 214, 168, 103, 210, 72, 164, 180, 208, 152, 5, 123, + 199, 53, 186, 162, 110, 241, 255, 184, 172, 154, 125, 193, 167, 196, + 14, 45, 55, 43, 182, 177, 2, 185, 36, 95, 46, 148, 51, 147, + 243, 89, 64, 155, 159, 154, 160, 230, 29, 3, 229, 111, 119, 207, + 119, 62, 113, 0, 58, 135, 134, 53, 30, 5, 171, 113, 234, 116, + 12, 18, 15, 198, 198, 180, 250, 227, 67, 75, 29, 243, 40, 231, + 233, 40, 41, 110, 96, 194, 200, 44, 22, 245, 139, 200, 89, 50, + 23, 50, 182, 182, 193, 28, 120, 151, 231, 243, 165, 96, 60, 163, + 94, 147, 85, 157, 143, 71, 244, 219, 152, 57, 187, 26, 246, 192, + 185, 152, 14, 150, 40, 148, 170, 126, 105, 233, 83, 248, 61, 222, + 30, 232, 230, 211, 11, 250, 211, 143, 75, 200, 180, 165, 42, 90, + 108, 21, 252, 122, 63, 183, 217, 182, 130, 118, 55, 168, 2, 69, + 58, 185, 188, 246, 37, 248, 49, 173, 144, 9, 237, 62, 176, 231, + 158, 149, 52, 17, 53, 57, 9, 121, 109, 14, 11, 91, 89, 140, + 72, 165, 3, 229, 228, 229, 77, 84, 78, 53, 75, 106, 218, 7, + 22, 14, 189, 13, 31, 187, 228, 133, 91, 118, 90, 164, 81, 80, + 180, 215, 153, 145, 227, 214, 110, 210, 228, 147, 115, 241, 209, 228, + 104, 11, 197, 31, 228, 82, 251, 201, 147, 134, 151, 124, 59, 103, + 24, 23, 19, 244, 56, 112, 145, 193, 49, 59, 150, 61, 135, 105, + 104, 2, 51, 181, 251, 65, 24, 169, 162, 120, 154, 80, 96, 232, + 11, 168, 65, 87, 129, 107, 35, 60, 159, 139, 144, 42, 216, 192, + 13, 235, 172, 245, 154, 136, 226, 83, 126, 255, 223, 46, 34, 140, + 129, 248, 186, 32, 223, 33, 119, 242, 240, 136, 208, 199, 229, 10, + 36, 255, 222, 41, 208, 131, 64, 81, 45, 165, 67, 37, 218, 40, + 64, 131, 231, 144, 193, 246, 51, 40, 118, 237, 141, 206, 117, 227, + 82, 85, 228, 143, 232, 91, 236, 225, 201, 101, 113, 54, 169, 131, + 151, 221, 12, 67, 211, 243, 120, 170, 71, 154, 238, 197, 123, 81, + 128, 56, 31, 157, 210, 159, 60, 99, 49, 73, 254, 88, 234, 141, + 23, 137, 112, 159, 38, 234, 210, 139, 152, 223, 29, 181, 149, 60, + 183, 216, 57, 104, 245, 80, 243, 66, 88, 188, 194, 180, 177, 8, + 46, 4, 202, 65, 64, 109, 66, 97, 95, 73, 246, 254, 161, 100, + 147, 199, 40, 232, 228, 104, 101, 158, 211, 213, 94, 240, 169, 109, + 76, 89, 18, 85, 196, 45, 138, 63, 168, 157, 89, 55, 111, 134, + 133, 64, 232, 195, 5, 35, 88, 128, 102, 195, 5, 151, 4, 250, + 224, 25, 113, 22, 24, 10, 96, 241, 32, 230, 31, 67, 84, 0, + 221, 83, 184, 108, 220, 243, 9, 78, 52, 33, 161, 35, 221, 104, + 221, 138, 85, 230, 99, 75, 125, 82, 74, 226, 168, 170, 25, 211, + 130, 146, 242, 24, 46, 243, 63, 109, 240, 244, 129, 98, 227, 252, + 111, 246, 114, 9, 162, 9, 189, 85, 14, 250, 54, 172, 217, 139, + 15, 42, 225, 103, 143, 15, 71, 10, 84, 99, 176, 145, 209, 231, + 218, 115, 32, 199, 25, 11, 202, 46, 36, 86, 30, 179, 154, 202, + 190, 208, 164, 159, 125, 142, 205, 119, 84, 159, 41, 202, 141, 57, + 25, 141, 93, 78, 63, 155, 109, 51, 21, 216, 3, 239, 211, 93, + 211, 213, 101, 158, 248, 39, 254, 6, 7, 169, 246, 76, 95, 141, + 148, 15, 204, 116, 196, 90, 179, 210, 205, 160, 48, 178, 87, 129, + 121, 33, 213, 83, 102, 11, 181, 89, 50, 92, 137, 41, 36, 243, + 119, 153, 29, 189, 30, 112, 238, 71, 209, 240, 22, 57, 236, 64, + 68, 245, 83, 23, 211, 96, 16, 209, 205, 175, 211, 65, 137, 109, + 116, 7, 205, 255, 166, 175, 51, 74, 47, 239, 8, 117, 10, 244, + 70, 94, 59, 137, 5, 7, 24, 165, 133, 174, 210, 231, 206, 71, + 20, 205, 41, 92, 234, 38, 220, 199, 60, 2, 178, 50, 70, 165, + 155, 189, 20, 227, 151, 37, 60, 95, 166, 54, 239, 162, 63, 29, + 111, 71, 193, 123, 229, 8, 213, 143, 75, 230, 70, 248, 66, 123, + 180, 20, 155, 26, 48, 22, 192, 119, 38, 241, 200, 133, 190, 233, + 224, 65, 88, 75, 139, 24, 44, 190, 40, 222, 121, 102, 13, 188, + 99, 73, 149, 239, 26, 174, 87, 247, 18, 12, 192, 0, 172, 147, + 58, 236, 210, 193, 46, 151, 241, 75, 130, 234, 191, 84, 24, 190, + 34, 87, 71, 90, 101, 198, 205, 79, 234, 142, 25, 175, 97, 27, + 182, 9, 77, 160, 78, 206, 78, 92, 37, 113, 232, 2, 89, 92, + 239, 250, 209, 82, 42, 43, 140, 214, 189, 52, 165, 217, 14, 122, + 158, 152, 17, 87, 128, 54, 20, 234, 170, 111, 194, 242, 157, 0, + 195, 37, 250, 19, 178, 75, 28, 142, 51, 116, 152, 56, 162, 219, + 59, 182, 59, 40, 194, 192, 88, 39, 94, 164, 105, 80, 67, 75, + 49, 93, 36, 118, 199, 3, 231, 153, 117, 126, 72, 54, 50, 149, + 250, 67, 124, 164, 130, 245, 222, 175, 161, 27, 162, 14, 116, 205, + 184, 231, 176, 235, 14, 164, 250, 249, 136, 109, 199, 122, 229, 13, + 227, 194, 48, 86, 191, 164, 27, 237, 50, 38, 81, 74, 113, 0, + 192, 76, 139, 105, 70, 26, 187, 45, 237, 171, 6, 113, 249, 6, + 213, 61, 28, 100, 127, 0, 146, 78, 228, 234, 228, 220, 123, 174, + 188, 32, 117, 171, 110, 235, 125, 143, 236, 109, 128, 101, 240, 104, + 221, 233, 28, 111, 94, 38, 150, 125, 108, 166, 246, 252, 133, 143, + 18, 227, 109, 28, 141, 132, 104, 73, 25, 223, 72, 193, 12, 138, + 229, 12, 226, 180, 33, 196, 99, 221, 187, 102, 231, 191, 85, 44, + 162, 185, 20, 204, 93, 156, 233, 98, 60, 170, 91, 155, 80, 235, + 66, 219, 242, 246, 98, 18, 191, 80, 139, 47, 222, 200, 102, 129, + 166, 65, 66, 142, 197, 254, 137, 87, 193, 223, 195, 228, 16, 196, + 106, 240, 7, 180, 84, 193, 141, 142, 113, 56, 81, 250, 58, 23, + 62, 22, 39, 100, 36, 160, 106, 142, 100, 154, 78, 155, 236, 17, + 125, 208, 111, 58, 250, 188, 137, 151, 171, 203, 209, 59, 18, 159, + 30, 131, 203, 48, 2, 49, 139, 173, 189, 135, 89, 185, 190, 43, + 169, 240, 205, 140, 76, 231, 91, 101, 227, 204, 112, 239, 153, 104, + 119, 116, 41, 219, 155, 120, 155, 34, 33, 250, 88, 174, 154, 183, + 243, 239, 28, 230, 186, 177, 35, 56, 173, 179, 30, 152, 112, 156, + 108, 209, 45, 169, 4, 31, 222, 10, 224, 185, 47, 76, 228, 52, + 2, 19, 217, 161, 217, 24, 51, 212, 254, 111, 236, 119, 87, 12, + 247, 146, 106, 2, 68, 58, 224, 99, 114, 71, 145, 241, 219, 207, + 241, 0, 233, 127, 197, 196, 52, 41, 173, 151, 0, 163, 114, 97, + 220, 209, 138, 51, 211, 28, 177, 167, 51, 163, 58, 97, 212, 250, + 43, 198, 168, 30, 248, 229, 197, 20, 144, 33, 41, 100, 16, 174, + 167, 89, 3, 7, 128, 204, 236, 55, 190, 148, 157, 208, 143, 171, + 58, 58, 176, 14, 192, 228, 8, 138, 35, 220, 189, 129, 234, 53, + 247, 193, 26, 215, 202, 211, 88, 44, 193, 137, 1, 242, 118, 212, + 123, 162, 242, 63, 210, 48, 107, 106, 71, 246, 196, 129, 85, 166, + 154, 216, 149, 96, 14, 96, 102, 206, 92, 94, 220, 172, 85, 51, + 111, 137, 108, 185, 62, 123, 155, 186, 254, 215, 50, 37, 26, 103, + 224, 87, 238, 0, 90, 116, 183, 58, 47, 25, 240, 79, 129, 164, + 171, 49, 128, 18, 34, 156, 154, 62, 183, 94, 105, 161, 239, 146, + 21, 82, 102, 232, 5, 239, 99, 147, 118, 151, 113, 242, 208, 157, + 254, 103, 88, 98, 102, 103, 234, 38, 4, 71, 31, 64, 243, 89, + 210, 85, 200, 233, 143, 23, 166, 204, 60, 106, 6, 100, 64, 34, + 224, 237, 89, 175, 119, 173, 146, 135, 92, 122, 181, 46, 137, 227, + 90, 100, 125, 255, 220, 85, 215, 100, 80, 120, 141, 73, 119, 26, + 158, 8, 32, 96, 238, 151, 89, 219, 33, 254, 147, 224, 26, 17, + 78, 44, 27, 189, 99, 55, 135, 177, 250, 138, 57, 140, 205, 24, + 123, 111, 50, 5, 239, 194, 22, 33, 156, 195, 255, 50, 26, 229, + 22, 102, 16, 227, 60, 222, 179, 180, 118, 99, 220, 140, 140, 96, + 23, 42, 112, 42, 34, 119, 13, 211, 58, 237, 213, 109, 229, 98, + 156, 41, 32, 165, 55, 40, 116, 229, 1, 58, 78, 120, 105, 38, + 63, 247, 127, 11, 184, 189, 31, 110, 232, 151, 168, 59, 24, 252, + 196, 104, 154, 240, 38, 132, 57, 126, 118, 223, 192, 47, 33, 198, + 129, 83, 138, 124, 74, 24, 251, 60, 123, 43, 54, 210, 101, 31, + 171, 84, 122, 197, 41, 75, 106, 212, 13, 210, 243, 255, 92, 74, + 218, 214, 186, 227, 167, 202, 84, 185, 89, 132, 183, 150, 241, 170, + 234, 130, 8, 70, 84, 7, 222, 236, 7, 174, 240, 92, 171, 244, + 22, 44, 29, 178, 28, 62, 151, 20, 72, 201, 65, 244, 125, 152, + 97, 110, 52, 1, 209, 198, 188, 166, 108, 11, 63, 44, 68, 170, + 174, 196, 194, 195, 118, 250, 23, 188, 156, 5, 146, 243, 24, 223, + 44, 0, 33, 14, 5, 44, 91, 172, 69, 118, 123, 209, 32, 22, + 151, 94, 65, 180, 44, 73, 229, 182, 60, 120, 245, 56, 38, 22, + 192, 176, 91, 181, 39, 33, 23, 24, 123, 159, 8, 68, 194, 29, + 119, 180, 109, 240, 39, 134, 173, 50, 67, 239, 12, 142, 57, 156, + 108, 61, 23, 133, 44, 229, 210, 148, 115, 83, 120, 39, 89, 129, + 172, 163, 203, 146, 223, 240, 243, 208, 235, 177, 206, 149, 237, 92, + 78, 79, 26, 241, 134, 219, 204, 4, 187, 158, 3, 26, 199, 26, + 247, 232, 247, 193, 202, 87, 164, 62, 66, 39, 232, 87, 183, 156, + 152, 231, 20, 61, 191, 242, 29, 238, 221, 36, 212, 200, 180, 35, + 249, 46, 234, 232, 22, 209, 242, 108, 187, 10, 42, 83, 31, 177, + 204, 62, 89, 95, 58, 62, 109, 175, 134, 203, 184, 65, 11, 231, + 69, 28, 244, 153, 53, 130, 83, 181, 199, 112, 171, 27, 16, 119, + 185, 116, 12, 216, 138, 64, 148, 189, 123, 25, 202, 86, 100, 155, + 212, 29, 9, 207, 43, 5, 192, 149, 165, 3, 138, 144, 102, 202, + 148, 205, 91, 150, 11, 129, 208, 56, 201, 175, 255, 57, 196, 124, + 63, 255, 74, 39, 32, 132, 113, 36, 238, 139, 222, 135, 70, 215, + 130, 198, 233, 184, 244, 64, 67, 248, 188, 226, 2, 137, 82, 28, + 3, 121, 146, 216, 186, 0, 102, 177, 59, 173, 122, 11, 89, 83, + 178, 122, 182, 66, 254, 48, 103, 77, 14, 43, 249, 88, 249, 47, + 210, 246, 134, 239, 255, 18, 125, 21, 192, 187, 158, 197, 34, 93, + 243, 125, 239, 0, 39, 140, 73, 63, 161, 133, 172, 84, 174, 122, + 217, 244, 49, 172, 83, 196, 34, 130, 39, 113, 154, 34, 85, 129, + 31, 28, 20, 9, 36, 53, 166, 135, 169, 143, 196, 89, 156, 107, + 113, 44, 213, 143, 196, 82, 237, 77, 41, 130, 130, 206, 99, 43, + 20, 59, 104, 103, 208, 17, 94, 49, 196, 89, 8, 9, 147, 206, + 158, 154, 68, 51, 235, 73, 102, 0, 37, 146, 220, 80, 253, 34, + 32, 131, 234, 200, 31, 38, 159, 209, 165, 138, 53, 79, 159, 111, + 79, 234, 42, 136, 202, 15, 14, 234, 34, 71, 174, 80, 207, 145, + 59, 34, 207, 209, 22, 140, 231, 49, 75, 42, 143, 10, 166, 104, + 173, 86, 112, 35, 60, 157, 223, 122, 120, 90, 197, 230, 114, 140, + 7, 31, 197, 95, 94, 172, 57, 67, 150, 64, 129, 245, 19, 82, + 83, 200, 83, 160, 237, 119, 247, 112, 157, 105, 62, 204, 166, 64, + 32, 211, 12, 27, 157, 229, 205, 197, 3, 169, 248, 177, 183, 94, + 10, 2, 228, 235, 96, 39, 226, 217, 227, 231, 213, 58, 176, 86, + 187, 77, 29, 45, 74, 97, 235, 24, 111, 217, 158, 37, 201, 54, + 97, 228, 38, 234, 81, 97, 250, 30, 186, 242, 184, 201, 243, 127, + 35, 33, 213, 203, 102, 55, 141, 61, 113, 223, 29, 52, 178, 87, + 246, 107, 216, 6, 220, 45, 81, 100, 13, 116, 148, 186, 198, 180, + 12, 2, 230, 196, 72, 149, 202, 196, 41, 195, 54, 80, 52, 229, + 22, 142, 31, 236, 211, 34, 251, 19, 166, 243, 128, 244, 70, 74, + 93, 2, 247, 0, 46, 131, 22, 3, 64, 24, 170, 86, 138, 227, + 2, 151, 248, 238, 49, 251, 36, 224, 253, 106, 139, 215, 157, 29, + 223, 223, 195, 89, 238, 241, 172, 109, 130, 100, 62, 130, 146, 20, + 52, 210, 139, 58, 156, 105, 143, 182, 228, 96, 32, 141, 191, 5, + 48, 0, 169, 98, 129, 120, 176, 132, 39, 0, 12, 128, 238, 218, + 237, 57, 246, 125, 23, 200, 201, 131, 63, 211, 25, 199, 99, 201, + 233, 180, 59, 249, 30, 19, 4, 195, 239, 187, 100, 94, 195, 117, + 148, 95, 117, 48, 66, 229, 80, 0, 106, 190, 64, 37, 146, 249, + 25, 57, 64, 221, 230, 160, 100, 225, 23, 51, 173, 82, 4, 139, + 58, 105, 25, 166, 240, 95, 196, 214, 60, 151, 149, 3, 146, 242, + 159, 186, 160, 252, 13, 144, 219, 109, 107, 13, 185, 162, 188, 251, + 143, 140, 198, 234, 60, 96, 143, 243, 121, 180, 130, 195, 156, 218, + 55, 208, 105, 4, 18, 12, 132, 203, 116, 176, 163, 237, 174, 129, + 24, 65, 87, 240, 107, 63, 79, 144, 254, 69, 206, 88, 120, 59, + 77, 74, 6, 47, 130, 159, 108, 205, 135, 41, 130, 138, 223, 146, + 233, 42, 31, 221, 85, 149, 27, 62, 193, 92, 108, 50, 85, 135, + 183, 210, 93, 112, 139, 204, 54, 148, 216, 0, 152, 127, 218, 188, + 155, 120, 6, 78, 23, 28, 30, 161, 78, 123, 142, 220, 29, 232, + 19, 170, 38, 195, 194, 94, 55, 118, 146, 84, 152, 101, 26, 149, + 104, 182, 44, 47, 153, 154, 193, 183, 245, 93, 250, 191, 223, 124, + 85, 42, 27, 106, 240, 17, 159, 32, 30, 58, 175, 80, 76, 107, + 190, 230, 3, 122, 229, 84, 164, 76, 2, 156, 227, 217, 192, 19, + 31, 165, 217, 240, 29, 59, 33, 165, 150, 245, 171, 77, 14, 247, + 46, 16, 218, 127, 111, 103, 43, 33, 4, 83, 63, 247, 24, 206, + 145, 246, 125, 244, 106, 4, 68, 184, 123, 147, 151, 172, 109, 149, + 155, 161, 20, 92, 34, 124, 128, 212, 140, 62, 116, 10, 32, 252, + 225, 248, 32, 54, 26, 44, 199, 73, 209, 183, 212, 153, 149, 184, + 195, 7, 226, 227, 11, 106, 185, 111, 122, 160, 46, 237, 234, 160, + 110, 224, 98, 82, 54, 57, 133, 199, 11, 60, 32, 171, 112, 40, + 115, 178, 60, 81, 194, 246, 169, 40, 69, 101, 162, 130, 199, 198, + 226, 166, 198, 23, 146, 108, 162, 224, 3, 61, 241, 196, 224, 235, + 242, 233, 184, 228, 212, 6, 234, 118, 114, 211, 195, 141, 119, 20, + 146, 50, 115, 27, 160, 249, 128, 105, 160, 112, 105, 3, 184, 1, + 190, 79, 113, 127, 108, 68, 213, 164, 163, 138, 152, 44, 2, 27, + 98, 25, 247, 219, 245, 168, 69, 168, 54, 4, 60, 139, 210, 235, + 41, 42, 221, 43, 20, 86, 68, 229, 186, 47, 228, 171, 70, 187, + 22, 228, 239, 115, 168, 60, 27, 130, 222, 74, 25, 131, 87, 200, + 207, 78, 118, 229, 23, 28, 61, 121, 61, 103, 137, 248, 205, 98, + 142, 113, 116, 74, 2, 51, 81, 202, 227, 214, 76, 195, 201, 167, + 253, 123, 28, 98, 243, 244, 138, 237, 23, 219, 227, 18, 79, 159, + 71, 230, 117, 67, 54, 53, 172, 196, 21, 172, 87, 99, 121, 72, + 119, 132, 178, 0, 69, 85, 177, 228, 119, 131, 165, 156, 75, 17, + 38, 221, 201, 142, 3, 214, 200, 125, 248, 29, 156, 7, 196, 1, + 190, 90, 167, 116, 112, 218, 107, 96, 69, 156, 72, 128, 210, 43, + 76, 209, 210, 38, 246, 41, 212, 3, 184, 180, 149, 36, 239, 156, + 56, 253, 194, 242, 178, 160, 38, 174, 98, 51, 97, 117, 161, 88, + 20, 250, 100, 185, 102, 91, 14, 67, 177, 105, 247, 47, 163, 95, + 252, 25, 162, 255, 111, 131, 220, 152, 210, 248, 22, 169, 27, 81, + 170, 10, 254, 206, 20, 151, 152, 73, 251, 55, 124, 180, 163, 141, + 12, 48, 90, 13, 102, 91, 83, 104, 45, 81, 147, 134, 114, 226, + 7, 170, 53, 56, 232, 161, 255, 225, 64, 103, 110, 120, 79, 123, + 21, 249, 218, 163, 171, 51, 41, 149, 251, 177, 187, 236, 206, 159, + 143, 14, 11, 20, 90, 121, 161, 232, 174, 152, 61, 134, 240, 101, + 119, 191, 253, 213, 244, 156, 203, 37, 214, 206, 220, 190, 165, 118, + 56, 9, 249, 49, 89, 147, 80, 152, 254, 23, 90, 151, 163, 184, + 148, 55, 206, 151, 157, 220, 33, 241, 152, 163, 234, 178, 213, 27, + 136, 227, 235, 9, 172, 169, 68, 54, 231, 247, 156, 155, 133, 240, + 42, 220, 199, 82, 155, 232, 40, 124, 2, 231, 147, 152, 169, 156, + 73, 73, 235, 236, 159, 181, 206, 1, 24, 83, 52, 6, 225, 112, + 145, 157, 58, 132, 168, 16, 229, 168, 137, 252, 4, 149, 208, 69, + 232, 93, 171, 113, 60, 207, 203, 80, 49, 73, 229, 89, 13, 205, + 86, 132, 225, 38, 48, 244, 212, 199, 204, 164, 144, 26, 88, 133, + 249, 29, 171, 47, 61, 139, 217, 252, 109, 162, 170, 117, 146, 13, + 122, 13, 185, 56, 43, 173, 159, 13, 15, 111, 48, 119, 103, 140, + 50, 19, 50, 101, 247, 36, 112, 77, 2, 131, 221, 165, 67, 112, + 178, 53, 24, 251, 250, 88, 85, 18, 21, 63, 235, 207, 199, 77, + 203, 154, 114, 243, 143, 234, 141, 191, 223, 132, 199, 61, 222, 232, + 92, 230, 31, 145, 19, 100, 3, 243, 116, 220, 25, 155, 41, 40, + 206, 18, 13, 60, 244, 21, 134, 25, 37, 213, 213, 220, 247, 177, + 153, 179, 159, 249, 136, 225, 238, 223, 77, 171, 83, 140, 40, 10, + 134, 126, 238, 115, 59, 88, 101, 86, 220, 31, 222, 123, 6, 156, + 119, 17, 12, 211, 113, 88, 226, 196, 4, 135, 28, 211, 240, 55, + 117, 213, 204, 28, 169, 103, 15, 169, 42, 106, 34, 80, 215, 25, + 81, 80, 251, 223, 157, 41, 188, 132, 96, 52, 10, 55, 181, 188, + 165, 193, 34, 23, 80, 23, 32, 150, 253, 192, 205, 148, 227, 76, + 113, 182, 117, 0, 45, 118, 106, 115, 243, 229, 31, 217, 22, 113, + 69, 176, 222, 71, 209, 252, 251, 154, 202, 219, 106, 87, 196, 179, + 9, 193, 28, 72, 69, 189, 76, 93, 64, 37, 148, 123, 53, 253, + 101, 147, 32, 49, 104, 251, 89, 219, 163, 16, 168, 39, 48, 6, + 149, 165, 193, 131, 15, 254, 149, 236, 0, 63, 158, 168, 201, 200, + 40, 44, 161, 208, 37, 114, 211, 31, 13, 35, 93, 45, 115, 124, + 4, 10, 54, 42, 33, 134, 103, 177, 157, 193, 132, 131, 149, 203, + 50, 189, 193, 12, 33, 97, 41, 100, 179, 8, 134, 120, 178, 191, + 199, 160, 167, 206, 214, 33, 53, 10, 235, 130, 151, 44, 156, 243, + 6, 107, 209, 248, 207, 255, 195, 192, 22, 242, 165, 185, 231, 203, + 118, 81, 204, 237, 77, 204, 173, 29, 165, 221, 115, 154, 186, 88, + 224, 189, 250, 46, 59, 92, 223, 186, 20, 192, 67, 202, 132, 198, + 169, 37, 86, 62, 190, 177, 192, 84, 49, 32, 255, 170, 111, 100, + 209, 224, 50, 221, 6, 81, 219, 222, 160, 224, 105, 18, 31, 53, + 101, 253, 131, 195, 8, 243, 41, 193, 147, 186, 144, 12, 129, 75, + 165, 231, 14, 179, 53, 189, 236, 11, 13, 200, 34, 100, 162, 217, + 57, 194, 53, 5, 181, 59, 97, 81, 159, 129, 212, 21, 39, 147, + 38, 65, 102, 71, 186, 144, 198, 12, 219, 254, 202, 163, 175, 252, + 229, 112, 96, 121, 82, 223, 87, 23, 4, 193, 250, 198, 143, 106, + 34, 12, 120, 155, 22, 35, 113, 14, 100, 194, 82, 122, 243, 64, + 116, 134, 132, 80, 239, 13, 1, 223, 4, 0, 34, 102, 149, 115, + 176, 46, 243, 214, 118, 106, 158, 202, 16, 53, 125, 132, 79, 75, + 46, 209, 104, 255, 254, 143, 146, 11, 91, 79, 205, 72, 161, 133, + 161, 125, 205, 96, 117, 212, 10, 56, 237, 71, 29, 40, 208, 157, + 22, 105, 43, 237, 98, 171, 142, 49, 91, 246, 41, 152, 95, 37, + 3, 181, 86, 168, 234, 108, 174, 131, 139, 143, 103, 46, 153, 156, + 167, 194, 192, 118, 138, 151, 170, 175, 133, 61, 52, 113, 148, 123, + 95, 125, 10, 26, 31, 223, 232, 90, 217, 86, 121, 25, 134, 217, + 46, 252, 197, 118, 202, 231, 20, 161, 190, 181, 91, 9, 195, 94, + 227, 113, 190, 208, 235, 69, 92, 249, 136, 231, 46, 4, 66, 124, + 83, 224, 183, 108, 11, 103, 240, 38, 226, 95, 12, 84, 226, 124, + 84, 234, 58, 116, 188, 254, 166, 151, 203, 112, 230, 117, 161, 6, + 100, 125, 134, 89, 19, 172, 132, 218, 66, 70, 27, 95, 20, 175, + 116, 147, 221, 177, 174, 162, 78, 66, 69, 31, 54, 163, 184, 61, + 61, 213, 230, 29, 91, 133, 198, 223, 96, 184, 108, 188, 149, 28, + 85, 232, 50, 154, 60, 253, 93, 253, 91, 103, 139, 111, 25, 12, + 207, 135, 10, 173, 138, 140, 9, 192, 65, 4, 47, 93, 181, 65, + 194, 230, 226, 37, 211, 200, 59, 216, 113, 228, 183, 35, 64, 103, + 90, 197, 133, 80, 47, 139, 150, 40, 155, 117, 87, 80, 206, 18, + 83, 37, 8, 182, 65, 26, 156, 82, 84, 194, 87, 130, 11, 134, + 137, 215, 62, 193, 86, 26, 215, 86, 17, 7, 244, 58, 16, 206, + 143, 31, 222, 1, 207, 133, 9, 155, 9, 118, 33, 238, 241, 134, + 24, 143, 165, 79, 92, 66, 30, 149, 236, 254, 72, 197, 93, 226, + 166, 131, 142, 232, 118, 77, 175, 107, 100, 48, 18, 100, 200, 166, + 197, 151, 91, 62, 61, 247, 255, 129, 124, 216, 117, 162, 236, 83, + 46, 175, 83, 207, 142, 154, 153, 149, 220, 225, 76, 179, 144, 187, + 183, 17, 168, 29, 116, 34, 232, 13, 168, 35, 59, 248, 94, 212, + 137, 249, 172, 59, 72, 191, 118, 239, 59, 144, 189, 166, 62, 239, + 84, 239, 218, 22, 188, 162, 59, 156, 131, 242, 40, 208, 251, 252, + 249, 93, 168, 155, 206, 46, 182, 39, 142, 100, 78, 132, 186, 36, + 135, 164, 199, 134, 218, 114, 82, 128, 250, 26, 93, 15, 141, 162, + 92, 193, 79, 114, 246, 76, 242, 29, 18, 135, 251, 7, 171, 51, + 65, 30, 202, 79, 110, 211, 143, 83, 123, 35, 40, 52, 139, 11, + 42, 209, 51, 113, 236, 133, 84, 187, 198, 145, 178, 213, 134, 159, + 27, 192, 6, 52, 160, 190, 226, 33, 12, 85, 89, 83, 15, 211, + 34, 54, 200, 205, 232, 217, 83, 119, 224, 211, 247, 56, 120, 167, + 37, 237, 168, 48, 190, 14, 123, 115, 114, 250, 64, 218, 119, 198, + 45, 191, 14, 29, 16, 105, 176, 87, 177, 145, 169, 176, 192, 103, + 59, 243, 195, 92, 66, 125, 167, 190, 223, 34, 246, 247, 163, 123, + 72, 121, 236, 139, 185, 231, 227, 38, 85, 159, 191, 39, 195, 139, + 227, 183, 3, 158, 88, 130, 169, 187, 205, 240, 31, 176, 128, 126, + 149, 82, 169, 142, 14, 222, 244, 168, 62, 165, 90, 223, 248, 243, + 19, 238, 126, 160, 89, 76, 220, 2, 42, 190, 26, 99, 129, 248, + 160, 14, 109, 45, 31, 254, 190, 138, 30, 102, 46, 242, 213, 144, + 59, 98, 107, 91, 72, 7, 86, 160, 210, 126, 14, 15, 172, 137, + 190, 205, 175, 161, 246, 226, 2, 145, 254, 217, 139, 34, 136, 35, + 148, 217, 197, 227, 155, 207, 93, 227, 9, 23, 12, 72, 88, 168, + 20, 129, 3, 92, 169, 212, 132, 189, 95, 159, 16, 226, 245, 0, + 229, 103, 140, 5, 38, 181, 67, 39, 131, 111, 170, 1, 196, 132, + 166, 124, 110, 108, 21, 230, 15, 228, 37, 21, 36, 117, 47, 60, + 118, 158, 131, 85, 60, 31, 138, 165, 150, 92, 152, 121, 0, 6, + 4, 198, 203, 102, 135, 122, 121, 18, 230, 87, 92, 87, 14, 9, + 174, 151, 112, 1, 192, 200, 147, 2, 61, 64, 77, 87, 88, 187, + 160, 196, 176, 52, 2, 96, 93, 96, 217, 157, 236, 74, 252, 218, + 165, 32, 126, 250, 31, 27, 151, 9, 190, 146, 173, 112, 206, 227, + 202, 31, 203, 239, 84, 98, 28, 41, 117, 29, 60, 185, 224, 3, + 136, 235, 208, 215, 191, 130, 117, 134, 205, 115, 138, 254, 144, 153, + 96, 63, 249, 69, 63, 232, 140, 19, 164, 141, 142, 182, 86, 255, + 92, 107, 138, 179, 193, 21, 77, 179, 123, 86, 176, 2, 66, 45, + 193, 215, 74, 22, 247, 108, 124, 196, 207, 147, 153, 190, 233, 28, + 153, 146, 31, 4, 145, 34, 91, 209, 178, 98, 15, 73, 11, 171, + 11, 240, 60, 190, 249, 153, 202, 26, 179, 146, 63, 109, 0, 23, + 200, 149, 134, 248, 47, 151, 199, 75, 58, 43, 137, 58, 162, 93, + 32, 176, 155, 32, 113, 57, 62, 222, 20, 198, 38, 126, 162, 175, + 87, 29, 84, 237, 254, 151, 239, 46, 24, 46, 172, 29, 176, 108, + 60, 137, 67, 223, 229, 65, 114, 83, 102, 4, 126, 163, 98, 37, + 170, 200, 112, 7, 251, 49, 58, 250, 196, 221, 29, 217, 222, 53, + 47, 18, 184, 55, 84, 96, 46, 78, 220, 41, 172, 214, 233, 240, + 45, 57, 240, 199, 10, 40, 232, 225, 236, 24, 63, 23, 42, 62, + 173, 70, 197, 150, 98, 55, 199, 145, 180, 75, 212, 152, 192, 191, + 255, 85, 58, 83, 190, 46, 81, 50, 161, 252, 61, 251, 8, 119, + 15, 34, 61, 149, 172, 236, 95, 99, 17, 234, 77, 92, 225, 209, + 219, 39, 220, 123, 247, 150, 79, 247, 15, 23, 225, 57, 212, 194, + 199, 53, 188, 110, 47, 125, 71, 95, 6, 244, 81, 37, 232, 80, + 182, 209, 109, 231, 87, 22, 13, 78, 109, 209, 173, 248, 150, 157, + 212, 70, 161, 165, 136, 53, 248, 149, 34, 95, 223, 182, 59, 83, + 178, 250, 75, 212, 44, 172, 78, 211, 142, 240, 247, 29, 197, 170, + 122, 19, 197, 166, 215, 96, 113, 198, 225, 87, 61, 217, 2, 251, + 158, 163, 90, 28, 2, 182, 65, 210, 248, 51, 57, 140, 38, 186, + 59, 219, 51, 253, 188, 249, 34, 146, 6, 129, 39, 240, 220, 163, + 243, 77, 55, 124, 81, 168, 255, 100, 181, 31, 180, 224, 131, 241, + 174, 26, 158, 48, 167, 121, 117, 241, 9, 56, 211, 188, 104, 36, + 211, 108, 90, 73, 24, 140, 212, 234, 122, 82, 229, 33, 95, 190, + 124, 32, 189, 224, 202, 32, 213, 146, 119, 60, 29, 219, 44, 174, + 103, 62, 50, 59, 135, 41, 246, 39, 204, 148, 68, 66, 7, 182, + 14, 237, 252, 104, 124, 2, 112, 180, 176, 133, 29, 130, 246, 74, + 135, 56, 97, 19, 147, 70, 200, 158, 227, 156, 181, 64, 120, 170, + 243, 47, 115, 121, 69, 95, 175, 11, 252, 73, 214, 12, 242, 216, + 232, 76, 158, 52, 99, 226, 112, 1, 89, 166, 207, 13, 177, 85, + 182, 6, 44, 81, 109, 109, 245, 129, 141, 246, 56, 227, 36, 106, + 155, 217, 188, 205, 216, 175, 61, 30, 110, 160, 64, 28, 84, 81, + 227, 100, 174, 58, 244, 120, 83, 237, 64, 206, 109, 9, 153, 111, + 115, 207, 158, 136, 165, 233, 133, 107, 187, 16, 235, 16, 219, 74, + 5, 139, 152, 207, 239, 81, 10, 224, 67, 29, 60, 140, 245, 235, + 158, 206, 252, 249, 130, 42, 253, 234, 184, 46, 190, 226, 87, 180, + 50, 228, 179, 136, 208, 158, 7, 121, 191, 176, 157, 21, 183, 143, + 56, 199, 125, 55, 29, 86, 144, 100, 24, 124, 52, 17, 5, 247, + 172, 234, 86, 248, 21, 103, 130, 1, 107, 147, 140, 243, 72, 33, + 94, 228, 16, 40, 220, 52, 237, 214, 185, 221, 51, 73, 210, 90, + 120, 53, 221, 109, 15, 178, 231, 194, 229, 83, 7, 132, 117, 173, + 201, 25, 228, 195, 102, 41, 147, 70, 138, 216, 254, 109, 88, 214, + 71, 245, 84, 242, 9, 137, 114, 59, 27, 78, 222, 56, 143, 128, + 219, 72, 68, 242, 196, 135, 248, 206, 157, 22, 182, 100, 234, 27, + 225, 139, 227, 214, 79, 114, 234, 14, 185, 45, 145, 190, 163, 249, + 235, 174, 194, 83, 174, 252, 86, 90, 132, 86, 42, 179, 32, 107, + 128, 121, 117, 230, 158, 245, 178, 33, 51, 207, 224, 66, 131, 244, + 192, 156, 173, 40, 198, 169, 155, 100, 75, 126, 8, 85, 15, 120, + 143, 117, 49, 235, 223, 78, 50, 228, 251, 175, 114, 210, 20, 167, + 35, 73, 109, 136, 130, 90, 215, 166, 49, 125, 70, 35, 140, 111, + 156, 182, 71, 163, 51, 200, 127, 185, 212, 99, 45, 175, 134, 151, + 39, 155, 93, 3, 158, 218, 221, 51, 230, 126, 68, 213, 248, 153, + 232, 232, 110, 248, 182, 239, 228, 139, 230, 71, 18, 104, 147, 197, + 88, 121, 207, 102, 219, 16, 110, 235, 149, 133, 44, 90, 221, 135, + 151, 88, 161, 40, 117, 215, 68, 176, 223, 235, 166, 81, 17, 96, + 108, 166, 248, 98, 243, 217, 224, 57, 203, 230, 72, 8, 230, 29, + 213, 150, 186, 250, 42, 203, 128, 170, 115, 107, 232, 54, 205, 207, + 90, 147, 198, 180, 245, 181, 152, 52, 93, 92, 137, 83, 75, 186, + 180, 250, 48, 51, 114, 179, 7, 23, 194, 208, 148, 204, 147, 137, + 254, 245, 168, 107, 189, 230, 212, 175, 46, 71, 208, 61, 92, 56, + 86, 4, 108, 235, 190, 43, 23, 146, 233, 177, 254, 201, 111, 13, + 172, 60, 2, 130, 247, 223, 77, 102, 232, 83, 222, 40, 111, 72, + 142, 197, 93, 84, 10, 48, 77, 152, 215, 103, 239, 57, 122, 192, + 23, 60, 242, 230, 169, 153, 152, 183, 33, 58, 166, 105, 40, 107, + 58, 246, 40, 8, 146, 148, 134, 0, 189, 213, 47, 77, 75, 154, + 167, 87, 113, 54, 207, 119, 47, 133, 2, 183, 245, 237, 103, 88, + 191, 79, 22, 181, 10, 224, 189, 97, 91, 146, 204, 114, 200, 132, + 246, 173, 59, 137, 49, 84, 13, 31, 146, 111, 204, 81, 35, 172, + 207, 81, 76, 75, 24, 196, 205, 73, 251, 224, 110, 227, 146, 70, + 97, 67, 89, 167, 54, 192, 62, 87, 195, 136, 170, 6, 13, 246, + 192, 237, 230, 174, 172, 2, 237, 84, 7, 64, 4, 224, 252, 163, + 204, 89, 117, 121, 159, 175, 86, 129, 250, 231, 106, 47, 227, 34, + 103, 173, 181, 107, 99, 107, 135, 222, 156, 67, 36, 89, 236, 133, + 105, 185, 171, 83, 46, 50, 236, 223, 208, 191, 147, 158, 185, 27, + 115, 233, 52, 235, 202, 20, 240, 173, 228, 119, 39, 52, 194, 92, + 191, 36, 154, 78, 135, 44, 59, 224, 13, 109, 164, 23, 137, 190, + 90, 195, 119, 204, 237, 254, 125, 128, 60, 185, 177, 111, 141, 100, + 79, 214, 92, 160, 51, 1, 226, 75, 50, 17, 54, 56, 140, 18, + 32, 152, 11, 156, 252, 84, 151, 167, 126, 39, 17, 252, 215, 109, + 174, 177, 223, 43, 120, 4, 251, 51, 113, 148, 173, 81, 249, 80, + 113, 129, 58, 107, 170, 36, 123, 228, 15, 7, 249, 154, 155, 118, + 121, 78, 8, 193, 45, 127, 117, 19, 118, 228, 191, 195, 168, 38, + 159, 202, 241, 171, 215, 95, 145, 143, 89, 58, 7, 230, 32, 51, + 192, 92, 227, 40, 141, 218, 5, 84, 143, 130, 137, 107, 15, 101, + 215, 167, 155, 234, 242, 133, 139, 88, 31, 179, 137, 151, 104, 210, + 157, 103, 55, 95, 149, 76, 232, 248, 186, 92, 149, 141, 73, 12, + 74, 57, 168, 174, 167, 16, 64, 213, 220, 82, 24, 100, 77, 11, + 99, 235, 31, 156, 46, 186, 198, 30, 23, 193, 78, 29, 80, 240, + 213, 84, 245, 82, 187, 104, 227, 253, 163, 201, 194, 199, 57, 68, + 67, 162, 167, 45, 3, 22, 145, 107, 86, 63, 110, 32, 211, 170, + 194, 30, 226, 75, 64, 195, 153, 64, 12, 225, 237, 30, 122, 229, + 252, 228, 4, 139, 118, 8, 20, 101, 48, 252, 174, 67, 158, 49, + 70, 75, 59, 20, 41, 222, 123, 246, 146, 137, 94, 120, 17, 1, + 178, 141, 138, 132, 122, 10, 84, 111, 232, 230, 145, 140, 80, 249, + 32, 27, 5, 7, 177, 175, 100, 117, 226, 31, 138, 47, 224, 188, + 131, 212, 52, 78, 255, 226, 88, 192, 87, 81, 66, 3, 255, 160, + 235, 91, 160, 67, 114, 136, 13, 22, 184, 6, 232, 182, 162, 36, + 65, 46, 200, 214, 190, 118, 107, 167, 128, 189, 146, 212, 42, 169, + 214, 169, 244, 172, 53, 17, 166, 96, 252, 215, 251, 39, 63, 238, + 97, 182, 164, 72, 206, 241, 238, 223, 143, 46, 207, 235, 170, 225, + 255, 84, 251, 79, 59, 145, 221, 66, 124, 121, 185, 76, 148, 220, + 68, 29, 68, 190, 103, 78, 75, 201, 231, 104, 202, 23, 109, 200, + 108, 125, 182, 19, 84, 145, 38, 195, 183, 213, 56, 208, 131, 247, + 117, 241, 108, 241, 149, 26, 85, 182, 102, 51, 51, 206, 52, 47, + 225, 131, 52, 11, 238, 247, 202, 57, 252, 221, 93, 201, 88, 82, + 67, 144, 154, 174, 251, 47, 133, 237, 96, 146, 252, 67, 75, 100, + 65, 243, 58, 28, 125, 177, 97, 52, 227, 235, 68, 37, 219, 37, + 6, 77, 232, 39, 94, 65, 202, 142, 152, 139, 91, 27, 66, 16, + 49, 113, 202, 76, 33, 57, 196, 62, 95, 193, 15, 244, 143, 245, + 33, 80, 107, 204, 149, 138, 171, 127, 231, 37, 214, 31, 176, 75, + 131, 129, 211, 186, 3, 185, 4, 28, 223, 125, 211, 39, 21, 197, + 94, 1, 213, 208, 137, 107, 156, 81, 82, 253, 115, 51, 79, 20, + 215, 180, 182, 193, 35, 30, 86, 52, 151, 223, 147, 203, 243, 225, + 212, 54, 48, 41, 133, 66, 166, 189, 75, 43, 58, 128, 78, 22, + 54, 95, 192, 182, 222, 161, 61, 239, 245, 114, 40, 191, 108, 141, + 89, 152, 142, 19, 120, 201, 203, 247, 9, 221, 110, 204, 2, 84, + 168, 178, 6, 245, 112, 221, 93, 146, 18, 30, 11, 12, 235, 77, + 102, 240, 207, 141, 41, 189, 31, 28, 166, 144, 229, 150, 191, 208, + 146, 92, 185, 137, 92, 188, 102, 183, 194, 136, 228, 93, 98, 131, + 239, 153, 227, 48, 28, 249, 247, 112, 179, 217, 7, 149, 82, 79, + 92, 161, 100, 244, 215, 122, 176, 28, 233, 90, 139, 97, 251, 35, + 98, 18, 245, 237, 100, 181, 186, 219, 24, 215, 68, 24, 113, 211, + 31, 125, 143, 245, 95, 49, 144, 1, 82, 154, 7, 159, 47, 201, + 64, 179, 197, 232, 21, 53, 36, 24, 68, 75, 148, 157, 26, 113, + 3, 65, 71, 96, 28, 39, 70, 250, 135, 154, 236, 201, 53, 55, + 203, 6, 114, 52, 29, 91, 10, 129, 252, 90, 239, 61, 214, 139, + 248, 30, 32, 91, 72, 43, 3, 251, 16, 193, 176, 160, 71, 2, + 228, 84, 190, 121, 82, 187, 53, 207, 245, 11, 188, 204, 69, 115, + 254, 180, 57, 115, 98, 203, 143, 20, 212, 68, 205, 242, 42, 124, + 246, 162, 232, 78, 42, 19, 190, 107, 120, 229, 254, 218, 133, 123, + 223, 18, 89, 132, 85, 177, 252, 199, 31, 213, 90, 106, 143, 248, + 112, 82, 96, 20, 177, 246, 184, 171, 159, 77, 162, 254, 37, 221, + 90, 91, 135, 192, 20, 106, 141, 162, 246, 36, 103, 227, 183, 183, + 236, 79, 165, 138, 70, 243, 85, 47, 130, 166, 183, 25, 177, 110, + 191, 88, 29, 215, 218, 194, 191, 121, 57, 17, 157, 143, 116, 81, + 168, 191, 82, 183, 31, 97, 119, 213, 250, 21, 220, 143, 217, 247, + 245, 137, 87, 175, 157, 207, 148, 227, 52, 135, 124, 223, 157, 158, + 117, 30, 35, 196, 56, 33, 18, 205, 130, 159, 110, 183, 55, 108, + 83, 249, 108, 66, 58, 95, 204, 187, 65, 90, 164, 83, 63, 79, + 27, 11, 244, 23, 26, 173, 170, 85, 25, 30, 161, 102, 137, 115, + 32, 177, 1, 1, 161, 128, 81, 160, 192, 193, 21, 3, 90, 229, + 74, 143, 194, 184, 113, 232, 10, 15, 117, 11, 205, 197, 39, 154, + 66, 189, 124, 38, 122, 26, 154, 104, 178, 73, 164, 154, 242, 118, + 23, 99, 62, 212, 7, 54, 199, 118, 67, 232, 157, 91, 227, 115, + 194, 49, 65, 110, 74, 202, 79, 226, 156, 184, 72, 48, 215, 131, + 106, 181, 206, 222, 135, 55, 42, 155, 60, 13, 186, 10, 200, 172, + 223, 26, 206, 21, 64, 232, 39, 131, 137, 229, 58, 36, 145, 114, + 155, 52, 37, 104, 70, 47, 35, 26, 97, 252, 89, 236, 150, 230, + 251, 159, 24, 130, 43, 219, 164, 79, 62, 44, 162, 217, 189, 32, + 160, 164, 163, 155, 199, 72, 47, 119, 1, 205, 88, 67, 151, 169, + 116, 88, 0, 103, 102, 205, 191, 60, 129, 246, 39, 154, 129, 218, + 191, 59, 172, 85, 1, 10, 196, 122, 192, 251, 66, 217, 16, 171, + 205, 115, 17, 78, 130, 247, 138, 240, 64, 137, 244, 136, 165, 243, + 242, 93, 177, 115, 255, 183, 127, 210, 116, 48, 46, 23, 27, 38, + 201, 211, 167, 52, 57, 113, 202, 156, 139, 36, 75, 26, 213, 235, + 120, 6, 184, 2, 175, 12, 111, 125, 228, 217, 19, 107, 136, 179, + 82, 199, 56, 141, 72, 223, 17, 189, 253, 94, 186, 249, 232, 10, + 248, 38, 44, 189, 0, 133, 19, 72, 172, 161, 166, 159, 132, 4, + 207, 12, 196, 16, 108, 152, 130, 49, 254, 30, 97, 70, 187, 129, + 6, 4, 80, 106, 32, 189, 79, 111, 45, 240, 142, 19, 239, 167, + 5, 211, 23, 126, 58, 185, 4, 112, 74, 96, 120, 210, 101, 143, + 196, 142, 74, 190, 16, 211, 122, 122, 248, 163, 202, 26, 247, 82, + 227, 241, 187, 107, 195, 159, 250, 96, 192, 167, 208, 254, 43, 64, + 205, 142, 227, 188, 53, 29, 196, 126, 132, 246, 255, 67, 69, 26, + 37, 187, 219, 25, 179, 31, 205, 217, 88, 83, 186, 76, 169, 90, + 38, 251, 79, 130, 105, 254, 137, 211, 142, 192, 217, 169, 134, 82, + 176, 207, 207, 67, 40, 52, 186, 47, 69, 50, 53, 245, 73, 174, + 118, 184, 12, 33, 196, 44, 88, 102, 86, 175, 94, 104, 195, 97, + 227, 243, 129, 210, 207, 85, 3, 180, 145, 71, 236, 97, 180, 111, + 73, 95, 189, 234, 15, 250, 37, 7, 24, 99, 204, 142, 39, 91, + 28, 12, 44, 127, 190, 241, 242, 165, 223, 166, 239, 46, 18, 6, + 26, 22, 87, 129, 186, 169, 36, 251, 76, 82, 61, 167, 144, 176, + 13, 4, 170, 111, 171, 186, 44, 29, 42, 114, 11, 55, 243, 188, + 21, 87, 144, 41, 108, 24, 179, 222, 151, 87, 124, 147, 207, 84, + 113, 27, 236, 81, 52, 153, 152, 99, 71, 14, 158, 102, 153, 84, + 109, 184, 171, 181, 90, 99, 141, 159, 110, 230, 6, 202, 236, 140, + 188, 168, 176, 79, 51, 43, 20, 240, 127, 9, 60, 82, 210, 152, + 21, 244, 46, 81, 104, 214, 225, 72, 43, 127, 51, 174, 255, 10, + 174, 11, 20, 173, 124, 143, 240, 172, 43, 25, 63, 239, 152, 22, + 45, 230, 134, 88, 190, 148, 251, 90, 30, 147, 148, 84, 150, 250, + 18, 199, 175, 22, 191, 79, 164, 12, 155, 119, 40, 1, 57, 227, + 69, 39, 164, 111, 123, 50, 212, 192, 137, 7, 209, 11, 216, 47, + 55, 247, 140, 217, 153, 78, 150, 32, 101, 203, 224, 75, 4, 86, + 199, 26, 147, 62, 119, 57, 119, 206, 83, 110, 179, 75, 70, 178, + 132, 133, 206, 91, 109, 155, 151, 22, 111, 44, 157, 226, 190, 117, + 73, 42, 159, 146, 42, 73, 237, 172, 109, 141, 191, 232, 72, 67, + 12, 102, 72, 154, 244, 132, 159, 129, 112, 66, 161, 169, 157, 164, + 14, 166, 74, 91, 111, 86, 9, 237, 151, 215, 140, 179, 228, 126, + 75, 119, 129, 237, 254, 89, 189, 14, 154, 214, 110, 214, 50, 87, + 78, 215, 206, 227, 157, 194, 216, 181, 181, 204, 144, 127, 216, 88, + 44, 111, 171, 112, 134, 236, 90, 229, 53, 149, 144, 123, 231, 141, + 251, 5, 140, 126, 156, 94, 2, 57, 244, 34, 203, 155, 111, 218, + 214, 44, 83, 218, 50, 94, 240, 21, 146, 99, 43, 130, 227, 108, + 43, 30, 152, 119, 168, 192, 254, 198, 22, 70, 171, 250, 203, 213, + 55, 1, 71, 162, 116, 184, 0, 177, 133, 227, 42, 57, 179, 26, + 109, 19, 37, 27, 126, 94, 89, 134, 170, 10, 43, 148, 155, 65, + 7, 200, 6, 136, 75, 221, 180, 161, 97, 64, 221, 64, 229, 96, + 153, 202, 246, 76, 108, 86, 250, 54, 141, 176, 32, 44, 219, 146, + 243, 247, 27, 194, 70, 229, 252, 211, 95, 38, 172, 111, 136, 20, + 134, 224, 94, 193, 14, 139, 236, 254, 124, 31, 209, 189, 230, 122, + 134, 15, 230, 121, 242, 177, 113, 207, 124, 123, 128, 102, 42, 176, + 117, 95, 173, 231, 236, 230, 57, 12, 10, 55, 94, 141, 239, 216, + 156, 49, 167, 106, 69, 117, 78, 248, 221, 243, 239, 171, 5, 25, + 174, 142, 22, 72, 125, 176, 5, 134, 248, 197, 233, 58, 233, 246, + 69, 204, 180, 72, 170, 120, 148, 27, 13, 221, 82, 162, 152, 156, + 17, 86, 237, 120, 44, 125, 156, 77, 108, 67, 233, 193, 231, 204, + 17, 230, 199, 62, 61, 249, 203, 245, 244, 156, 211, 216, 65, 169, + 118, 228, 50, 127, 144, 172, 101, 0, 129, 5, 81, 5, 136, 218, + 247, 52, 88, 69, 103, 173, 223, 201, 255, 138, 116, 92, 68, 54, + 65, 227, 1, 199, 225, 62, 203, 210, 252, 26, 182, 80, 105, 100, + 68, 137, 61, 206, 212, 205, 148, 153, 28, 127, 38, 251, 234, 234, + 189, 163, 82, 240, 29, 165, 244, 71, 201, 166, 202, 175, 144, 190, + 142, 224, 205, 50, 11, 37, 188, 9, 221, 149, 198, 178, 87, 174, + 136, 176, 211, 193, 117, 2, 47, 85, 244, 16, 194, 215, 36, 247, + 224, 221, 85, 104, 7, 12, 38, 67, 225, 120, 161, 245, 195, 87, + 167, 61, 243, 147, 144, 152, 217, 192, 226, 148, 178, 53, 10, 123, + 190, 213, 190, 110, 134, 131, 123, 74, 147, 162, 88, 120, 18, 115, + 31, 213, 143, 219, 211, 25, 0, 47, 179, 57, 156, 255, 157, 233, + 120, 172, 131, 90, 40, 191, 28, 41, 53, 115, 72, 50, 181, 201, + 167, 10, 216, 61, 132, 20, 49, 39, 184, 193, 86, 73, 22, 200, + 238, 154, 5, 125, 174, 98, 159, 79, 165, 199, 214, 57, 100, 68, + 158, 106, 86, 215, 155, 57, 226, 225, 26, 154, 63, 105, 125, 88, + 86, 220, 118, 31, 134, 212, 84, 109, 140, 189, 244, 222, 191, 233, + 133, 85, 80, 50, 84, 49, 248, 75, 153, 126, 156, 236, 244, 187, + 226, 206, 63, 147, 35, 233, 41, 42, 106, 50, 125, 184, 17, 206, + 169, 210, 170, 132, 150, 197, 227, 45, 81, 189, 159, 165, 162, 4, + 185, 144, 203, 248, 114, 4, 84, 140, 48, 159, 23, 165, 176, 169, + 47, 133, 145, 215, 129, 22, 200, 162, 65, 61, 181, 207, 240, 226, + 35, 229, 191, 52, 254, 147, 184, 213, 254, 148, 34, 19, 104, 60, + 46, 138, 89, 15, 78, 196, 252, 135, 48, 44, 241, 96, 149, 95, + 87, 64, 67, 10, 37, 97, 8, 71, 87, 232, 45, 208, 248, 51, + 175, 227, 34, 162, 19, 7, 39, 194, 128, 113, 179, 47, 182, 245, + 109, 118, 81, 239, 115, 232, 26, 129, 243, 3, 98, 80, 8, 129, + 201, 53, 2, 218, 132, 141, 158, 65, 96, 138, 235, 224, 132, 208, + 64, 26, 211, 21, 106, 61, 138, 136, 144, 216, 158, 198, 80, 18, + 56, 185, 209, 252, 254, 220, 112, 49, 208, 129, 108, 253, 171, 99, + 206, 200, 137, 53, 85, 230, 86, 191, 129, 249, 158, 12, 80, 43, + 9, 0, 129, 91, 172, 125, 182, 212, 190, 144, 211, 71, 211, 149, + 58, 241, 131, 124, 113, 75, 174, 255, 207, 190, 122, 143, 204, 180, + 254, 222, 211, 19, 191, 83, 102, 120, 33, 170, 179, 194, 112, 80, + 93, 187, 92, 151, 47, 67, 210, 14, 81, 97, 199, 13, 87, 247, + 34, 43, 129, 82, 174, 122, 30, 205, 129, 33, 133, 111, 69, 125, + 209, 88, 242, 200, 142, 126, 63, 173, 201, 97, 202, 126, 215, 27, + 176, 73, 112, 24, 40, 191, 229, 127, 228, 187, 116, 44, 237, 255, + 4, 75, 219, 132, 59, 60, 4, 241, 223, 172, 124, 143, 165, 217, + 156, 211, 77, 20, 47, 244, 91, 18, 201, 125, 198, 14, 211, 131, + 22, 173, 202, 129, 214, 140, 116, 116, 194, 12, 23, 191, 211, 8, + 210, 214, 241, 83, 236, 20, 3, 183, 231, 163, 230, 178, 99, 116, + 122, 45, 84, 45, 167, 29, 217, 116, 36, 160, 124, 243, 13, 132, + 119, 253, 144, 93, 150, 116, 98, 82, 12, 93, 156, 163, 43, 165, + 94, 198, 135, 25, 75, 152, 158, 81, 37, 0, 25, 48, 66, 200, + 177, 46, 56, 86, 206, 176, 136, 211, 115, 172, 62, 61, 0, 136, + 85, 63, 59, 161, 221, 144, 58, 228, 78, 6, 199, 149, 123, 29, + 119, 176, 79, 253, 109, 251, 107, 181, 23, 189, 66, 1, 210, 223, + 112, 3, 5, 32, 42, 144, 59, 32, 223, 121, 208, 10, 192, 71, + 5, 20, 188, 64, 240, 200, 178, 228, 175, 142, 13, 93, 251, 102, + 129, 19, 144, 230, 210, 236, 252, 130, 244, 223, 138, 222, 198, 188, + 166, 108, 62, 167, 238, 28, 27, 112, 95, 210, 242, 236, 223, 235, + 130, 208, 60, 253, 22, 194, 163, 238, 53, 49, 165, 61, 7, 72, + 91, 6, 42, 139, 150, 7, 208, 136, 238, 142, 238, 225, 75, 95, + 34, 184, 7, 196, 107, 202, 162, 237, 52, 107, 226, 135, 30, 210, + 70, 126, 155, 11, 71, 125, 24, 64, 91, 198, 175, 74, 198, 118, + 16, 52, 136, 39, 203, 227, 11, 186, 39, 50, 135, 127, 164, 199, + 31, 121, 127, 23, 184, 107, 76, 109, 223, 216, 34, 115, 35, 249, + 26, 25, 197, 40, 231, 32, 4, 118, 237, 53, 49, 56, 132, 190, + 192, 20, 6, 199, 247, 14, 23, 210, 81, 2, 213, 21, 230, 63, + 99, 55, 221, 218, 102, 223, 202, 238, 192, 251, 63, 58, 67, 66, + 95, 35, 154, 23, 108, 71, 247, 235, 99, 66, 179, 252, 194, 134, + 247, 66, 178, 189, 6, 158, 158, 67, 112, 69, 217, 203, 53, 34, + 79, 98, 172, 156, 78, 187, 37, 55, 163, 204, 231, 143, 233, 181, + 54, 117, 116, 217, 73, 7, 44, 120, 163, 51, 183, 88, 176, 93, + 165, 198, 62, 178, 125, 36, 140, 170, 41, 254, 27, 208, 208, 243, + 209, 188, 40, 143, 141, 97, 167, 180, 30, 15, 175, 160, 233, 235, + 37, 82, 182, 71, 74, 225, 140, 210, 87, 10, 22, 62, 112, 160, + 195, 157, 71, 159, 67, 30, 17, 113, 227, 212, 184, 157, 8, 81, + 112, 97, 245, 91, 174, 109, 32, 245, 84, 146, 76, 215, 64, 87, + 201, 95, 143, 121, 252, 21, 23, 53, 92, 162, 164, 203, 117, 21, + 228, 245, 69, 238, 49, 11, 51, 232, 212, 16, 84, 186, 122, 36, + 37, 203, 244, 137, 139, 182, 19, 221, 129, 212, 147, 93, 111, 125, + 184, 142, 227, 141, 118, 164, 19, 254, 179, 60, 28, 66, 254, 77, + 188, 224, 46, 161, 155, 56, 198, 19, 6, 187, 94, 67, 59, 234, + 24, 5, 144, 75, 89, 39, 108, 57, 25, 127, 113, 209, 164, 139, + 56, 91, 235, 228, 99, 81, 245, 126, 109, 163, 46, 57, 122, 176, + 191, 190, 141, 56, 23, 4, 0, 182, 200, 187, 183, 111, 99, 220, + 115, 125, 108, 82, 90, 156, 108, 213, 126, 110, 213, 3, 248, 8, + 101, 84, 187, 22, 199, 32, 115, 163, 70, 214, 108, 62, 152, 177, + 176, 242, 7, 248, 149, 44, 128, 59, 178, 121, 197, 192, 159, 2, + 246, 128, 65, 36, 97, 165, 232, 211, 225, 85, 123, 172, 203, 53, + 44, 90, 163, 43, 249, 214, 31, 163, 119, 102, 208, 248, 239, 54, + 217, 182, 181, 106, 79, 9, 229, 31, 137, 43, 85, 77, 86, 51, + 193, 52, 209, 95, 84, 132, 49, 9, 54, 83, 86, 74, 182, 248, + 98, 66, 15, 95, 76, 240, 52, 87, 133, 187, 145, 212, 135, 240, + 4, 76, 19, 196, 30, 5, 132, 26, 198, 218, 248, 51, 108, 58, + 33, 122, 189, 200, 235, 181, 45, 25, 35, 118, 62, 206, 87, 155, + 183, 227, 177, 175, 203, 220, 97, 235, 55, 222, 242, 41, 42, 71, + 56, 196, 236, 136, 197, 206, 246, 95, 241, 233, 7, 158, 254, 0, + 52, 167, 247, 31, 188, 40, 18, 223, 253, 232, 10, 196, 41, 166, + 169, 81, 236, 174, 217, 84, 233, 45, 247, 109, 167, 50, 4, 218, + 60, 202, 159, 112, 144, 169, 219, 151, 112, 206, 44, 109, 211, 245, + 194, 29, 202, 194, 7, 167, 21, 0, 137, 47, 27, 66, 183, 68, + 89, 189, 138, 118, 44, 202, 34, 242, 227, 176, 124, 142, 99, 84, + 34, 132, 73, 24, 102, 199, 53, 108, 140, 121, 88, 44, 187, 138, + 182, 227, 185, 122, 159, 102, 40, 115, 66, 209, 2, 47, 87, 187, + 106, 35, 91, 11, 97, 54, 42, 223, 47, 108, 219, 53, 122, 13, + 239, 17, 20, 101, 45, 115, 87, 108, 93, 178, 185, 177, 64, 167, + 104, 29, 20, 188, 193, 145, 170, 175, 7, 126, 20, 155, 210, 184, + 178, 226, 115, 234, 96, 189, 110, 249, 191, 225, 219, 239, 94, 48, + 253, 133, 151, 27, 208, 107, 58, 32, 62, 74, 251, 24, 230, 38, + 40, 34, 24, 221, 215, 240, 160, 163, 0, 166, 116, 251, 48, 182, + 141, 109, 115, 86, 122, 112, 207, 59, 54, 44, 43, 255, 85, 9, + 237, 196, 48, 173, 254, 168, 233, 46, 117, 6, 52, 110, 192, 209, + 202, 68, 230, 21, 85, 239, 112, 62, 96, 79, 220, 156, 255, 205, + 230, 189, 50, 117, 90, 96, 98, 100, 44, 17, 71, 141, 78, 52, + 109, 82, 218, 200, 55, 119, 64, 228, 132, 21, 40, 136, 36, 77, + 193, 225, 75, 80, 163, 237, 20, 211, 106, 93, 18, 121, 230, 167, + 136, 178, 109, 91, 17, 221, 9, 126, 205, 7, 184, 104, 176, 163, + 28, 119, 25, 55, 135, 77, 24, 27, 104, 206, 146, 226, 41, 22, + 65, 225, 50, 220, 135, 161, 44, 221, 124, 117, 97, 87, 5, 63, + 131, 107, 96, 103, 96, 13, 204, 161, 163, 140, 215, 22, 237, 164, + 166, 218, 64, 83, 52, 176, 117, 59, 39, 156, 206, 211, 223, 63, + 78, 220, 159, 138, 77, 23, 227, 181, 153, 220, 39, 226, 165, 81, + 89, 26, 199, 245, 13, 171, 45, 29, 10, 79, 106, 147, 104, 207, + 28, 194, 233, 44, 177, 57, 143, 73, 170, 52, 46, 30, 24, 171, + 97, 13, 16, 31, 138, 136, 0, 119, 35, 167, 119, 35, 231, 236, + 136, 197, 112, 81, 17, 116, 54, 148, 213, 119, 242, 209, 155, 55, + 49, 134, 202, 202, 48, 199, 217, 67, 64, 86, 87, 166, 245, 65, + 37, 54, 125, 126, 228, 170, 10, 113, 83, 157, 179, 73, 208, 188, + 99, 1, 198, 113, 11, 163, 243, 55, 198, 164, 57, 237, 83, 228, + 11, 206, 143, 139, 19, 28, 230, 213, 232, 171, 213, 129, 226, 120, + 238, 104, 198, 208, 124, 25, 176, 197, 52, 62, 21, 179, 89, 237, + 217, 187, 232, 202, 6, 10, 69, 150, 236, 122, 120, 91, 164, 249, + 116, 95, 206, 221, 4, 107, 204, 79, 73, 254, 138, 112, 225, 187, + 145, 140, 62, 75, 32, 202, 7, 181, 242, 74, 101, 185, 24, 5, + 44, 157, 0, 54, 157, 22, 56, 209, 216, 96, 220, 154, 241, 155, + 136, 49, 243, 249, 84, 9, 99, 164, 236, 33, 78, 128, 38, 228, + 249, 212, 60, 206, 99, 241, 191, 71, 173, 175, 92, 193, 152, 190, + 93, 43, 172, 61, 56, 85, 232, 219, 156, 221, 59, 232, 158, 168, + 162, 163, 173, 26, 226, 220, 85, 244, 11, 231, 30, 249, 30, 223, + 45, 184, 190, 53, 29, 61, 160, 63, 168, 155, 254, 93, 106, 40, + 190, 224, 57, 178, 174, 236, 142, 161, 121, 88, 33, 115, 92, 226, + 10, 151, 167, 218, 240, 50, 84, 226, 139, 226, 227, 206, 169, 245, + 253, 41, 92, 111, 37, 125, 56, 232, 86, 12, 177, 35, 105, 157, + 176, 191, 104, 107, 93, 49, 11, 6, 199, 45, 211, 182, 93, 212, + 177, 157, 5, 164, 54, 0, 110, 255, 225, 23, 3, 236, 199, 224, + 203, 151, 87, 17, 180, 22, 59, 209, 187, 215, 116, 101, 122, 105, + 102, 158, 195, 82, 166, 18, 156, 55, 89, 131, 107, 11, 210, 170, + 82, 182, 45, 236, 128, 136, 90, 93, 105, 130, 9, 245, 219, 96, + 155, 34, 133, 34, 220, 219, 26, 207, 38, 217, 91, 128, 212, 43, + 155, 151, 100, 254, 110, 7, 153, 139, 53, 136, 3, 77, 168, 199, + 9, 50, 52, 149, 119, 72, 225, 157, 219, 69, 155, 45, 98, 178, + 254, 141, 14, 7, 64, 147, 252, 57, 202, 239, 78, 37, 76, 134, + 113, 228, 96, 116, 224, 198, 74, 53, 95, 223, 25, 28, 237, 82, + 21, 214, 65, 172, 121, 37, 133, 55, 192, 28, 71, 113, 184, 145, + 216, 117, 103, 247, 149, 3, 115, 51, 94, 49, 12, 232, 152, 122, + 118, 217, 20, 64, 114, 50, 30, 76, 128, 33, 54, 242, 147, 220, + 243, 72, 87, 94, 1, 180, 253, 30, 91, 92, 75, 1, 94, 182, + 47, 71, 7, 96, 246, 143, 65, 134, 32, 126, 218, 112, 72, 226, + 147, 41, 168, 88, 234, 232, 92, 250, 132, 138, 103, 211, 91, 69, + 186, 63, 237, 14, 146, 139, 135, 189, 225, 4, 248, 135, 194, 250, + 69, 84, 205, 95, 104, 18, 105, 201, 78, 200, 32, 72, 154, 4, + 63, 195, 235, 143, 199, 138, 41, 173, 55, 187, 45, 254, 80, 237, + 1, 92, 166, 145, 197, 136, 61, 9, 49, 161, 237, 242, 121, 207, + 11, 254, 3, 65, 63, 49, 123, 203, 166, 110, 2, 221, 86, 102, + 133, 35, 12, 206, 53, 35, 47, 58, 60, 174, 123, 43, 126, 50, + 29, 153, 130, 49, 101, 127, 243, 72, 214, 0, 204, 236, 66, 191, + 138, 255, 3, 131, 75, 242, 192, 118, 34, 152, 84, 187, 63, 39, + 71, 239, 159, 152, 241, 12, 78, 72, 56, 0, 111, 174, 238, 210, + 141, 140, 114, 68, 114, 105, 118, 135, 170, 127, 5, 75, 75, 213, + 142, 168, 182, 105, 160, 38, 187, 85, 171, 234, 149, 19, 47, 191, + 206, 157, 136, 203, 181, 77, 255, 17, 109, 54, 96, 111, 134, 249, + 102, 158, 5, 69, 123, 6, 118, 1, 64, 95, 245, 173, 201, 35, + 54, 41, 144, 164, 40, 117, 212, 100, 89, 107, 137, 2, 180, 4, + 103, 193, 134, 68, 131, 30, 44, 136, 171, 171, 101, 201, 92, 106, + 89, 19, 162, 11, 138, 10, 54, 35, 155, 65, 163, 21, 189, 92, + 26, 200, 188, 234, 86, 181, 245, 3, 120, 149, 110, 49, 146, 125, + 154, 2, 93, 123, 7, 108, 57, 224, 29, 123, 150, 94, 167, 74, + 152, 223, 30, 124, 197, 201, 176, 165, 163, 213, 34, 12, 16, 56, + 94, 140, 218, 121, 146, 50, 215, 173, 84, 229, 184, 33, 254, 222, + 129, 166, 223, 243, 62, 234, 76, 217, 98, 83, 178, 248, 75, 236, + 228, 41, 47, 17, 37, 94, 94, 149, 85, 211, 167, 1, 137, 162, + 2, 69, 139, 215, 174, 127, 155, 127, 202, 19, 109, 218, 137, 86, + 214, 183, 15, 113, 59, 93, 74, 81, 146, 152, 102, 113, 247, 57, + 253, 82, 57, 115, 13, 22, 106, 31, 224, 191, 103, 154, 5, 71, + 250, 84, 4, 30, 27, 228, 124, 99, 83, 80, 148, 181, 34, 138, + 34, 20, 90, 9, 122, 50, 109, 193, 119, 201, 156, 112, 195, 164, + 56, 34, 251, 4, 238, 231, 206, 240, 212, 109, 86, 170, 93, 204, + 210, 238, 158, 167, 144, 108, 33, 246, 122, 207, 238, 215, 196, 195, + 223, 187, 137, 143, 95, 62, 15, 168, 13, 216, 212, 56, 41, 84, + 22, 62, 137, 247, 16, 42, 8, 112, 0, 224, 49, 150, 248, 31, + 139, 163, 98, 35, 187, 132, 228, 226, 47, 36, 97, 15, 48, 236, + 85, 30, 228, 12, 96, 219, 129, 39, 28, 213, 54, 56, 145, 225, + 204, 246, 186, 10, 29, 28, 97, 168, 217, 112, 213, 186, 89, 243, + 175, 4, 23, 149, 62, 123, 101, 219, 100, 27, 227, 70, 144, 213, + 144, 232, 30, 102, 231, 85, 76, 35, 174, 183, 254, 67, 162, 161, + 219, 96, 34, 2, 122, 224, 205, 169, 136, 154, 21, 252, 247, 86, + 20, 40, 45, 242, 204, 223, 159, 89, 118, 32, 18, 4, 199, 4, + 95, 65, 121, 130, 179, 213, 204, 209, 246, 4, 83, 198, 150, 237, + 153, 233, 193, 163, 170, 52, 161, 159, 134, 34, 206, 247, 219, 101, + 250, 73, 155, 198, 28, 97, 78, 11, 48, 138, 168, 153, 63, 230, + 237, 111, 240, 176, 207, 26, 66, 13, 124, 41, 65, 94, 202, 184, + 39, 5, 86, 121, 90, 254, 131, 156, 199, 19, 77, 125, 227, 102, + 154, 73, 221, 214, 223, 245, 8, 240, 249, 98, 64, 252, 26, 29, + 39, 124, 43, 122, 54, 163, 224, 75, 36, 181, 171, 158, 124, 35, + 146, 179, 2, 83, 177, 179, 113, 34, 114, 168, 30, 88, 182, 161, + 129, 63, 37, 162, 63, 155, 76, 95, 109, 216, 74, 156, 126, 187, + 189, 159, 69, 122, 108, 70, 191, 90, 235, 186, 80, 72, 227, 195, + 124, 192, 187, 8, 5, 6, 9, 129, 144, 142, 223, 128, 43, 29, + 221, 29, 90, 47, 69, 94, 126, 164, 141, 52, 12, 140, 154, 66, + 100, 211, 137, 138, 140, 177, 23, 5, 150, 36, 102, 158, 134, 35, + 85, 14, 103, 240, 200, 2, 132, 52, 65, 143, 168, 75, 143, 239, + 41, 89, 153, 80, 217, 194, 89, 115, 28, 82, 180, 163, 168, 61, + 30, 196, 172, 210, 182, 105, 240, 253, 252, 170, 233, 3, 137, 181, + 59, 64, 242, 69, 145, 249, 216, 94, 102, 130, 186, 126, 234, 78, + 253, 114, 30, 116, 26, 62, 137, 26, 156, 176, 47, 254, 186, 235, + 108, 241, 21, 200, 0, 249, 53, 83, 175, 236, 238, 46, 185, 73, + 185, 224, 128, 30, 115, 113, 166, 35, 0, 163, 69, 190, 126, 71, + 58, 83, 171, 162, 31, 146, 215, 68, 237, 193, 206, 15, 144, 47, + 6, 173, 233, 101, 20, 161, 96, 114, 140, 165, 195, 52, 207, 239, + 135, 238, 152, 190, 94, 172, 199, 2, 36, 159, 21, 123, 226, 178, + 115, 197, 244, 147, 52, 193, 234, 174, 184, 2, 175, 201, 118, 46, + 121, 103, 213, 26, 223, 40, 125, 174, 92, 47, 218, 130, 92, 114, + 203, 251, 115, 185, 163, 223, 104, 1, 125, 70, 35, 128, 152, 201, + 155, 249, 170, 63, 149, 102, 54, 201, 198, 49, 213, 229, 41, 220, + 194, 33, 252, 59, 137, 38, 74, 246, 138, 225, 24, 123, 145, 76, + 237, 192, 188, 135, 223, 215, 176, 210, 91, 96, 172, 255, 100, 209, + 188, 80, 84, 245, 77, 161, 215, 49, 105, 195, 219, 99, 143, 50, + 186, 46, 109, 124, 2, 46, 147, 199, 78, 204, 197, 41, 15, 157, + 198, 197, 234, 248, 188, 98, 206, 85, 189, 164, 89, 21, 4, 218, + 125, 177, 145, 134, 121, 242, 28, 209, 223, 10, 21, 241, 32, 151, + 202, 113, 216, 106, 234, 23, 206, 220, 14, 21, 178, 115, 234, 131, + 62, 193, 65, 152, 72, 145, 111, 163, 141, 229, 188, 255, 111, 134, + 98, 79, 48, 26, 129, 40, 236, 175, 138, 200, 68, 250, 66, 117, + 28, 130, 113, 181, 242, 95, 40, 130, 17, 90, 115, 10, 241, 48, + 212, 95, 172, 233, 239, 248, 203, 89, 11, 212, 244, 56, 115, 144, + 150, 143, 64, 177, 162, 202, 21, 178, 76, 72, 68, 98, 142, 73, + 219, 171, 152, 22, 208, 10, 123, 153, 65, 39, 202, 115, 50, 202, + 78, 123, 26, 43, 117, 232, 190, 25, 215, 184, 117, 109, 239, 219, + 128, 252, 249, 131, 196, 232, 205, 205, 153, 130, 0, 41, 219, 60, + 204, 156, 64, 108, 150, 104, 62, 135, 156, 88, 25, 69, 156, 177, + 223, 76, 110, 217, 224, 182, 0, 76, 200, 28, 248, 153, 65, 144, + 195, 244, 146, 80, 191, 48, 193, 5, 231, 143, 71, 109, 97, 186, + 94, 93, 232, 248, 104, 35, 84, 165, 94, 108, 3, 104, 130, 67, + 77, 241, 128, 253, 69, 41, 121, 15, 1, 247, 84, 196, 251, 242, + 216, 149, 164, 41, 152, 21, 0, 24, 50, 103, 113, 244, 86, 206, + 101, 44, 229, 49, 210, 119, 111, 76, 223, 242, 0, 119, 242, 149, + 141, 160, 47, 241, 146, 230, 69, 53, 126, 219, 31, 174, 59, 125, + 172, 45, 83, 234, 36, 87, 113, 177, 82, 177, 1, 83, 15, 84, + 138, 94, 43, 169, 134, 161, 193, 126, 107, 94, 148, 184, 79, 173, + 52, 127, 118, 129, 193, 157, 249, 130, 162, 168, 191, 175, 58, 161, + 30, 2, 20, 196, 92, 179, 242, 124, 142, 124, 213, 154, 206, 55, + 180, 68, 156, 8, 50, 118, 6, 148, 209, 8, 190, 127, 53, 162, + 7, 32, 73, 108, 24, 70, 246, 59, 28, 23, 104, 243, 54, 205, + 66, 93, 100, 244, 97, 198, 11, 24, 9, 26, 125, 6, 40, 125, + 134, 252, 210, 139, 166, 9, 102, 245, 188, 176, 179, 223, 3, 101, + 211, 190, 58, 210, 42, 236, 103, 154, 72, 186, 69, 201, 244, 233, + 248, 136, 178, 167, 207, 166, 116, 192, 62, 0, 188, 155, 178, 25, + 114, 191, 60, 124, 195, 201, 73, 89, 63, 189, 6, 250, 98, 83, + 61, 96, 56, 82, 109, 31, 211, 245, 198, 121, 31, 228, 84, 229, + 216, 84, 17, 231, 71, 193, 20, 8, 9, 160, 134, 124, 207, 192, + 231, 181, 251, 22, 156, 10, 92, 64, 74, 76, 54, 214, 162, 15, + 225, 124, 178, 196, 17, 241, 192, 6, 69, 49, 235, 167, 154, 128, + 34, 131, 85, 81, 65, 171, 163, 229, 183, 25, 242, 238, 165, 33, + 145, 130, 66, 133, 99, 119, 154, 168, 217, 150, 214, 192, 117, 198, + 38, 187, 157, 201, 71, 187, 227, 173, 43, 251, 141, 109, 15, 235, + 147, 164, 189, 148, 30, 151, 179, 158, 190, 62, 18, 205, 61, 6, + 52, 93, 227, 37, 117, 2, 167, 247, 10, 124, 233, 250, 109, 37, + 205, 84, 10, 243, 129, 13, 214, 31, 25, 18, 95, 52, 50, 112, + 71, 206, 250, 184, 77, 168, 157, 164, 201, 149, 2, 10, 112, 166, + 156, 171, 154, 15, 91, 206, 179, 165, 208, 240, 29, 144, 243, 223, + 27, 137, 68, 31, 118, 164, 181, 80, 44, 147, 14, 39, 229, 163, + 124, 68, 176, 6, 190, 193, 55, 183, 213, 205, 221, 242, 129, 141, + 209, 181, 23, 157, 242, 218, 155, 98, 171, 253, 26, 106, 75, 140, + 27, 149, 100, 67, 244, 165, 31, 177, 57, 46, 252, 153, 78, 85, + 86, 58, 2, 108, 134, 53, 24, 189, 146, 223, 108, 116, 60, 150, + 124, 249, 143, 6, 120, 223, 94, 224, 109, 27, 135, 80, 166, 147, + 53, 104, 69, 71, 9, 14, 200, 149, 161, 222, 63, 197, 101, 223, + 148, 246, 80, 237, 137, 85, 85, 201, 29, 98, 149, 114, 245, 223, + 18, 240, 137, 168, 35, 58, 64, 166, 243, 13, 177, 190, 253, 40, + 87, 10, 195, 67, 75, 21, 93, 45, 116, 189, 104, 137, 100, 244, + 25, 140, 118, 245, 34, 216, 32, 127, 177, 136, 107, 146, 22, 53, + 61, 233, 86, 31, 14, 201, 124, 195, 235, 174, 64, 45, 50, 146, + 94, 47, 224, 86, 116, 18, 196, 183, 108, 101, 105, 131, 71, 87, + 64, 2, 84, 8, 97, 2, 193, 95, 175, 25, 148, 181, 220, 9, + 117, 128, 222, 139, 159, 47, 52, 31, 154, 101, 168, 153, 217, 89, + 93, 68, 226, 76, 161, 32, 148, 171, 118, 86, 148, 179, 10, 115, + 90, 20, 63, 255, 176, 253, 199, 171, 57, 174, 67, 97, 146, 45, + 196, 160, 121, 190, 117, 202, 44, 118, 33, 241, 249, 126, 219, 187, + 45, 254, 224, 235, 185, 239, 94, 120, 229, 143, 211, 159, 33, 196, + 3, 76, 116, 16, 162, 246, 162, 181, 145, 58, 234, 252, 74, 122, + 40, 243, 160, 70, 188, 188, 165, 99, 138, 112, 76, 201, 8, 53, + 208, 53, 245, 193, 202, 59, 31, 187, 117, 219, 26, 77, 27, 95, + 164, 215, 49, 22, 184, 228, 79, 164, 171, 117, 74, 195, 51, 176, + 96, 134, 247, 25, 49, 202, 206, 110, 126, 146, 9, 14, 191, 226, + 5, 164, 73, 172, 204, 96, 229, 79, 73, 180, 76, 218, 87, 36, + 152, 223, 145, 181, 27, 49, 168, 228, 129, 76, 122, 13, 4, 30, + 58, 251, 38, 117, 93, 67, 150, 117, 123, 208, 214, 236, 134, 191, + 54, 166, 180, 34, 0, 197, 240, 166, 24, 141, 32, 110, 187, 209, + 217, 34, 228, 32, 48, 37, 62, 101, 50, 253, 137, 131, 236, 232, + 43, 41, 185, 141, 85, 112, 95, 152, 80, 102, 127, 247, 209, 77, + 57, 165, 208, 50, 125, 247, 127, 97, 168, 99, 68, 67, 43, 72, + 98, 162, 193, 74, 227, 3, 88, 95, 153, 173, 205, 32, 30, 145, + 193, 34, 150, 78, 44, 91, 80, 33, 31, 116, 143, 92, 218, 65, + 89, 140, 75, 250, 97, 213, 142, 160, 69, 115, 165, 120, 165, 206, + 166, 142, 201, 56, 4, 163, 80, 77, 216, 158, 198, 37, 11, 75, + 198, 61, 127, 168, 208, 196, 9, 47, 32, 143, 41, 184, 156, 45, + 42, 236, 177, 211, 122, 191, 5, 188, 70, 182, 68, 106, 55, 79, + 12, 101, 245, 97, 185, 177, 132, 32, 162, 165, 56, 110, 15, 181, + 7, 22, 182, 140, 117, 226, 229, 90, 217, 225, 141, 118, 249, 168, + 5, 158, 105, 137, 38, 215, 3, 125, 9, 202, 246, 87, 243, 97, + 46, 67, 48, 99, 233, 252, 155, 71, 147, 141, 47, 176, 99, 248, + 165, 254, 190, 107, 214, 61, 36, 224, 176, 185, 145, 213, 207, 204, + 212, 47, 135, 79, 56, 105, 119, 41, 156, 129, 16, 84, 110, 91, + 172, 72, 200, 217, 127, 1, 251, 122, 244, 55, 16, 219, 82, 206, + 114, 218, 151, 74, 246, 215, 56, 154, 183, 245, 152, 43, 196, 111, + 37, 214, 163, 250, 243, 141, 215, 182, 131, 82, 228, 249, 198, 23, + 84, 172, 122, 7, 7, 20, 54, 64, 85, 49, 167, 0, 21, 100, + 53, 255, 127, 37, 5, 91, 237, 17, 83, 17, 234, 105, 52, 252, + 149, 219, 101, 52, 154, 86, 148, 102, 66, 85, 230, 234, 90, 82, + 12, 154, 168, 26, 51, 133, 18, 213, 146, 119, 13, 181, 203, 90, + 144, 190, 88, 132, 99, 174, 219, 204, 76, 174, 108, 155, 242, 178, + 216, 35, 140, 21, 124, 234, 198, 6, 183, 212, 247, 250, 126, 171, + 150, 99, 175, 62, 34, 201, 47, 178, 210, 247, 148, 108, 47, 150, + 209, 83, 198, 124, 6, 24, 166, 119, 19, 24, 175, 227, 110, 43, + 47, 36, 222, 156, 73, 3, 175, 180, 119, 35, 88, 233, 244, 111, + 83, 117, 66, 145, 138, 96, 241, 86, 221, 148, 0, 170, 29, 75, + 110, 90, 83, 121, 147, 189, 54, 14, 62, 83, 120, 240, 116, 58, + 134, 15, 138, 82, 216, 39, 147, 111, 222, 106, 129, 40, 99, 122, + 81, 200, 23, 152, 188, 85, 55, 183, 186, 107, 10, 236, 56, 73, + 63, 29, 227, 23, 148, 250, 103, 124, 232, 146, 48, 143, 57, 244, + 179, 214, 161, 240, 247, 211, 161, 221, 75, 37, 157, 4, 73, 88, + 40, 116, 90, 202, 114, 0, 11, 61, 68, 159, 134, 135, 186, 42, + 124, 129, 151, 247, 221, 6, 166, 34, 217, 175, 61, 138, 78, 9, + 26, 215, 168, 30, 133, 7, 189, 208, 40, 131, 110, 56, 214, 221, + 95, 168, 173, 193, 220, 80, 170, 140, 60, 68, 231, 167, 136, 84, + 215, 196, 141, 243, 6, 234, 130, 161, 50, 110, 106, 240, 160, 101, + 100, 191, 225, 190, 231, 180, 51, 77, 132, 2, 231, 134, 112, 35, + 92, 121, 95, 91, 176, 64, 192, 250, 5, 162, 142, 236, 29, 169, + 113, 130, 245, 43, 154, 229, 86, 187, 171, 226, 222, 193, 230, 114, + 169, 58, 62, 62, 129, 8, 88, 34, 76, 104, 254, 200, 219, 151, + 92, 46, 117, 172, 107, 121, 149, 215, 60, 141, 74, 178, 224, 34, + 82, 60, 228, 207, 236, 109, 176, 240, 49, 164, 119, 192, 97, 80, + 99, 135, 14, 47, 220, 67, 236, 229, 14, 242, 141, 113, 141, 74, + 82, 198, 135, 14, 126, 21, 207, 115, 98, 14, 162, 127, 66, 19, + 150, 226, 103, 153, 254, 221, 135, 134, 3, 34, 74, 145, 31, 1, + 162, 193, 124, 254, 2, 40, 208, 178, 186, 5, 143, 159, 202, 128, + 113, 105, 77, 173, 184, 101, 18, 215, 100, 2, 4, 166, 12, 197, + 150, 188, 89, 115, 52, 110, 211, 204, 123, 42, 247, 87, 105, 94, + 232, 71, 201, 249, 201, 139, 37, 174, 11, 2, 86, 51, 224, 205, + 32, 55, 129, 1, 2, 77, 211, 102, 117, 235, 149, 167, 218, 99, + 147, 103, 104, 33, 214, 154, 165, 138, 207, 150, 28, 169, 167, 245, + 61, 242, 187, 194, 40, 150, 97, 113, 116, 210, 104, 212, 112, 6, + 26, 18, 116, 241, 143, 209, 240, 110, 21, 138, 246, 235, 182, 215, + 192, 143, 17, 174, 132, 114, 114, 10, 230, 5, 156, 67, 74, 105, + 4, 96, 204, 218, 97, 105, 135, 202, 207, 14, 159, 9, 113, 28, + 181, 46, 148, 43, 139, 145, 134, 152, 62, 185, 75, 47, 129, 69, + 69, 25, 248, 126, 198, 115, 119, 207, 241, 214, 132, 81, 2, 209, + 250, 49, 193, 19, 205, 36, 118, 85, 193, 63, 123, 181, 163, 35, + 23, 243, 102, 17, 77, 14, 12, 45, 63, 91, 189, 79, 66, 193, + 28, 102, 34, 58, 119, 253, 171, 155, 73, 128, 110, 100, 195, 42, + 153, 62, 128, 31, 190, 192, 177, 174, 56, 229, 175, 175, 137, 127, + 205, 185, 188, 180, 74, 230, 203, 57, 92, 43, 55, 209, 23, 95, + 106, 61, 28, 87, 24, 201, 192, 234, 56, 79, 184, 83, 30, 138, + 225, 212, 231, 218, 205, 123, 227, 57, 33, 156, 146, 198, 242, 246, + 195, 95, 220, 248, 118, 114, 25, 212, 33, 102, 154, 90, 165, 74, + 72, 21, 243, 49, 61, 215, 112, 207, 209, 156, 34, 102, 91, 204, + 56, 154, 166, 6, 244, 234, 37, 88, 210, 237, 164, 9, 231, 100, + 188, 11, 235, 177, 178, 92, 73, 70, 49, 9, 47, 81, 213, 68, + 8, 151, 110, 216, 218, 29, 199, 131, 184, 240, 194, 113, 141, 95, + 46, 96, 251, 119, 89, 115, 200, 86, 81, 41, 69, 251, 24, 140, + 217, 3, 27, 201, 72, 202, 154, 229, 70, 10, 213, 178, 218, 96, + 44, 3, 244, 54, 40, 203, 175, 171, 34, 40, 27, 16, 244, 53, + 153, 135, 80, 38, 34, 200, 70, 247, 193, 148, 96, 231, 49, 246, + 80, 123, 95, 218, 135, 7, 77, 84, 170, 20, 19, 238, 106, 78, + 207, 4, 220, 136, 149, 177, 205, 207, 90, 246, 128, 252, 169, 207, + 249, 90, 45, 43, 202, 73, 178, 221, 227, 40, 171, 178, 205, 178, + 148, 248, 234, 194, 137, 220, 54, 71, 238, 33, 216, 32, 111, 58, + 106, 253, 183, 3, 118, 224, 193, 205, 187, 152, 247, 133, 252, 122, + 88, 39, 16, 49, 122, 19, 91, 3, 92, 143, 187, 29, 161, 233, + 195, 201, 103, 97, 85, 92, 230, 197, 61, 164, 10, 67, 82, 103, + 149, 99, 240, 214, 96, 65, 87, 249, 157, 151, 43, 141, 38, 69, + 237, 131, 191, 83, 184, 223, 198, 59, 89, 6, 19, 13, 214, 135, + 221, 48, 180, 24, 21, 175, 14, 178, 122, 234, 135, 222, 132, 156, + 185, 9, 37, 242, 100, 92, 180, 66, 172, 217, 235, 133, 36, 59, + 32, 166, 68, 83, 39, 194, 203, 118, 167, 141, 236, 122, 97, 104, + 81, 203, 38, 195, 254, 254, 76, 31, 59, 213, 204, 254, 237, 212, + 156, 190, 19, 150, 124, 183, 15, 99, 33, 114, 97, 114, 50, 182, + 126, 67, 229, 128, 7, 132, 82, 171, 146, 110, 47, 196, 97, 32, + 26, 132, 79, 184, 188, 6, 106, 229, 245, 151, 169, 233, 87, 106, + 62, 182, 170, 38, 181, 244, 85, 232, 136, 227, 176, 102, 174, 22, + 112, 203, 253, 245, 211, 108, 59, 101, 44, 123, 217, 167, 123, 112, + 25, 214, 25, 194, 111, 160, 193, 184, 55, 243, 158, 49, 192, 97, + 154, 79, 140, 130, 66, 23, 46, 183, 250, 32, 231, 57, 128, 94, + 240, 170, 74, 86, 179, 62, 198, 49, 160, 192, 247, 241, 77, 238, + 175, 66, 153, 48, 46, 219, 153, 111, 109, 98, 193, 244, 54, 37, + 71, 157, 245, 60, 120, 242, 38, 196, 80, 95, 91, 131, 175, 182, + 46, 62, 20, 40, 188, 217, 208, 30, 188, 37, 235, 38, 203, 57, + 218, 109, 157, 31, 229, 248, 53, 50, 212, 198, 175, 55, 132, 137, + 238, 149, 128, 187, 118, 177, 157, 97, 186, 55, 38, 205, 19, 132, + 191, 67, 174, 245, 129, 227, 208, 148, 8, 255, 209, 233, 193, 27, + 109, 206, 137, 152, 145, 194, 66, 230, 54, 239, 217, 180, 100, 21, + 8, 179, 160, 78, 59, 104, 93, 121, 174, 181, 192, 164, 158, 194, + 32, 22, 9, 63, 197, 184, 70, 179, 164, 14, 6, 71, 165, 230, + 144, 147, 51, 184, 216, 202, 196, 214, 144, 124, 113, 28, 244, 112, + 127, 44, 91, 90, 146, 134, 161, 52, 159, 131, 133, 107, 191, 137, + 34, 121, 193, 178, 125, 78, 91, 135, 3, 33, 109, 216, 83, 39, + 102, 243, 96, 99, 180, 162, 130, 193, 21, 27, 232, 198, 181, 86, + 46, 250, 15, 143, 165, 91, 37, 125, 226, 51, 137, 237, 1, 24, + 13, 38, 180, 222, 84, 144, 50, 43, 148, 153, 154, 43, 163, 20, + 108, 25, 194, 97, 22, 166, 161, 164, 245, 175, 163, 210, 189, 10, + 207, 171, 121, 199, 99, 132, 245, 253, 120, 178, 55, 135, 143, 191, + 218, 183, 94, 193, 168, 56, 100, 123, 21, 139, 4, 189, 182, 38, + 211, 27, 193, 38, 244, 151, 106, 245, 245, 141, 160, 236, 182, 1, + 58, 76, 129, 13, 20, 47, 8, 124, 233, 119, 91, 98, 54, 94, + 237, 95, 243, 23, 12, 24, 28, 37, 192, 86, 88, 172, 46, 242, + 251, 65, 97, 203, 252, 38, 46, 81, 248, 204, 125, 112, 169, 21, + 194, 100, 245, 32, 44, 33, 98, 67, 140, 10, 30, 64, 99, 102, + 221, 152, 251, 176, 106, 180, 132, 232, 191, 221, 63, 4, 113, 78, + 169, 67, 61, 76, 88, 179, 112, 215, 22, 9, 248, 29, 159, 102, + 227, 252, 188, 226, 10, 226, 101, 89, 70, 52, 227, 217, 30, 244, + 75, 80, 5, 70, 240, 121, 194, 47, 164, 85, 232, 252, 144, 243, + 102, 64, 190, 93, 4, 0, 155, 191, 54, 60, 171, 20, 189, 137, + 91, 32, 115, 75, 139, 100, 158, 188, 12, 97, 53, 44, 236, 238, + 87, 179, 238, 245, 37, 180, 170, 174, 80, 209, 74, 241, 20, 204, + 148, 95, 226, 136, 132, 47, 29, 114, 58, 66, 161, 71, 189, 139, + 59, 210, 227, 184, 200, 135, 10, 74, 109, 92, 87, 139, 246, 151, + 33, 254, 176, 137, 242, 90, 147, 35, 67, 239, 65, 223, 29, 83, + 69, 152, 64, 24, 49, 173, 101, 143, 16, 249, 36, 209, 31, 101, + 32, 171, 222, 74, 242, 125, 255, 71, 21, 126, 125, 99, 132, 32, + 44, 101, 3, 33, 195, 148, 2, 172, 97, 162, 135, 47, 210, 134, + 19, 182, 230, 112, 188, 140, 29, 237, 242, 160, 8, 166, 217, 52, + 34, 15, 166, 157, 140, 121, 116, 41, 31, 185, 64, 134, 111, 138, + 212, 91, 0, 113, 220, 143, 188, 20, 104, 227, 22, 65, 113, 84, + 29, 226, 21, 241, 229, 170, 126, 112, 229, 78, 223, 188, 226, 215, + 52, 68, 17, 239, 9, 47, 175, 115, 237, 133, 154, 175, 91, 12, + 69, 98, 254, 19, 173, 176, 6, 175, 213, 225, 200, 128, 30, 37, + 226, 70, 54, 140, 142, 12, 190, 33, 213, 88, 25, 197, 157, 209, + 168, 90, 234, 254, 169, 113, 31, 85, 7, 113, 156, 140, 122, 24, + 173, 41, 105, 148, 78, 238, 72, 168, 54, 207, 41, 97, 3, 205, + 33, 45, 146, 53, 159, 141, 250, 122, 238, 184, 115, 166, 46, 89, + 222, 58, 158, 160, 180, 172, 16, 122, 69, 217, 140, 236, 73, 24, + 236, 219, 137, 223, 63, 44, 147, 128, 67, 74, 218, 219, 83, 255, + 241, 225, 58, 24, 232, 25, 54, 83, 229, 151, 116, 246, 22, 237, + 229, 98, 58, 85, 112, 205, 229, 27, 56, 1, 88, 143, 225, 67, + 81, 10, 222, 19, 62, 215, 194, 163, 186, 162, 243, 221, 116, 49, + 250, 163, 73, 208, 159, 73, 72, 49, 187, 56, 30, 210, 8, 203, + 175, 35, 84, 215, 53, 165, 235, 35, 81, 124, 77, 245, 192, 23, + 54, 204, 93, 91, 50, 230, 180, 188, 87, 88, 207, 149, 178, 252, + 213, 43, 45, 66, 166, 24, 56, 219, 237, 151, 104, 123, 192, 6, + 249, 232, 235, 180, 155, 80, 49, 139, 125, 175, 3, 235, 151, 243, + 35, 188, 28, 168, 245, 238, 1, 131, 194, 130, 30, 10, 168, 112, + 15, 17, 61, 187, 243, 80, 121, 220, 185, 95, 22, 150, 186, 109, + 132, 175, 43, 191, 237, 11, 203, 211, 143, 70, 14, 127, 168, 57, + 241, 47, 208, 90, 183, 0, 144, 231, 213, 224, 193, 47, 204, 209, + 51, 172, 40, 40, 47, 132, 254, 130, 201, 20, 9, 247, 126, 52, + 35, 150, 62, 255, 94, 108, 17, 76, 116, 123, 191, 156, 65, 107, + 235, 246, 202, 80, 236, 140, 244, 127, 176, 115, 112, 74, 70, 170, + 244, 43, 180, 108, 231, 72, 134, 78, 218, 23, 111, 7, 24, 255, + 41, 134, 220, 99, 37, 118, 222, 122, 116, 78, 34, 128, 233, 11, + 48, 235, 248, 64, 251, 25, 61, 77, 43, 175, 186, 48, 136, 188, + 112, 226, 4, 39, 77, 9, 68, 219, 58, 252, 49, 207, 193, 181, + 117, 134, 127, 148, 193, 175, 123, 130, 135, 148, 104, 141, 208, 251, + 161, 78, 96, 18, 118, 168, 23, 0, 96, 185, 199, 141, 130, 56, + 205, 240, 97, 181, 254, 12, 2, 35, 18, 71, 33, 233, 45, 241, + 113, 0, 127, 17, 149, 63, 108, 90, 49, 226, 79, 206, 82, 42, + 174, 193, 89, 162, 221, 164, 98, 25, 129, 179, 147, 50, 18, 106, + 9, 35, 156, 126, 89, 0, 182, 67, 192, 251, 84, 106, 210, 6, + 170, 224, 185, 191, 183, 16, 5, 6, 217, 190, 12, 177, 80, 142, + 239, 209, 135, 93, 242, 224, 142, 218, 74, 70, 193, 44, 173, 190, + 24, 47, 121, 190, 226, 185, 120, 168, 95, 173, 46, 135, 184, 71, + 234, 196, 80, 137, 199, 230, 253, 56, 77, 39, 145, 74, 179, 253, + 150, 156, 156, 73, 228, 140, 89, 149, 60, 72, 180, 37, 15, 163, + 121, 184, 144, 206, 144, 193, 67, 194, 186, 51, 163, 78, 17, 127, + 150, 30, 180, 78, 209, 137, 176, 8, 134, 192, 222, 86, 99, 94, + 65, 97, 203, 248, 234, 28, 225, 47, 61, 125, 103, 103, 30, 124, + 14, 100, 216, 22, 20, 18, 94, 63, 83, 119, 158, 68, 111, 175, + 194, 126, 194, 219, 76, 191, 165, 232, 153, 32, 53, 133, 159, 106, + 178, 245, 191, 211, 96, 117, 143, 22, 162, 245, 86, 139, 188, 240, + 60, 212, 187, 82, 9, 217, 179, 170, 32, 143, 188, 64, 168, 59, + 169, 112, 72, 63, 221, 136, 191, 228, 15, 235, 219, 209, 10, 101, + 57, 81, 231, 98, 214, 135, 51, 39, 91, 172, 131, 167, 149, 169, + 98, 149, 162, 84, 196, 53, 102, 150, 91, 118, 65, 156, 50, 47, + 83, 152, 82, 23, 53, 242, 77, 98, 68, 169, 167, 68, 21, 204, + 170, 194, 163, 159, 171, 21, 176, 230, 45, 212, 103, 66, 114, 212, + 177, 42, 1, 180, 103, 18, 112, 232, 11, 194, 196, 204, 190, 238, + 143, 224, 214, 65, 123, 30, 75, 29, 247, 174, 198, 135, 65, 108, + 9, 186, 216, 217, 1, 43, 227, 66, 209, 11, 247, 102, 1, 167, + 37, 96, 116, 22, 107, 129, 60, 244, 32, 160, 84, 58, 141, 19, + 202, 28, 46, 237, 163, 211, 53, 114, 180, 105, 116, 199, 190, 12, + 157, 238, 132, 8, 159, 51, 195, 6, 8, 116, 51, 47, 137, 193, + 188, 210, 72, 225, 1, 245, 79, 207, 175, 68, 217, 134, 205, 238, + 133, 164, 76, 36, 101, 48, 149, 11, 118, 246, 218, 43, 162, 78, + 159, 202, 12, 172, 240, 38, 101, 253, 189, 19, 209, 226, 111, 142, + 109, 68, 125, 24, 212, 59, 50, 169, 1, 167, 186, 235, 72, 62, + 14, 110, 251, 108, 66, 163, 40, 187, 14, 17, 9, 44, 41, 173, + 231, 40, 49, 179, 29, 247, 87, 32, 117, 83, 22, 119, 70, 104, + 30, 237, 59, 207, 206, 82, 84, 68, 3, 236, 85, 67, 89, 104, + 224, 63, 187, 49, 17, 89, 122, 247, 46, 220, 38, 10, 142, 9, + 233, 36, 113, 140, 251, 1, 132, 47, 143, 167, 29, 175, 8, 220, + 149, 60, 211, 52, 39, 199, 9, 214, 23, 86, 209, 8, 40, 126, + 212, 109, 91, 74, 69, 40, 209, 58, 147, 51, 148, 78, 136, 19, + 164, 199, 161, 187, 196, 185, 45, 151, 243, 188, 47, 35, 66, 19, + 216, 37, 82, 220, 160, 181, 255, 109, 203, 93, 255, 74, 107, 178, + 23, 252, 158, 65, 137, 2, 106, 64, 243, 2, 189, 80, 116, 124, + 218, 176, 142, 104, 20, 72, 137, 74, 179, 50, 227, 90, 222, 106, + 77, 188, 233, 210, 61, 44, 33, 95, 91, 119, 94, 248, 49, 199, + 83, 75, 234, 64, 114, 17, 214, 40, 63, 57, 64, 72, 105, 200, + 131, 114, 151, 78, 26, 45, 140, 110, 253, 227, 178, 165, 79, 83, + 149, 16, 185, 0, 153, 79, 12, 164, 74, 198, 198, 129, 103, 106, + 251, 100, 230, 89, 79, 137, 185, 143, 249, 233, 206, 37, 144, 183, + 99, 167, 162, 190, 11, 130, 113, 179, 119, 220, 236, 65, 64, 24, + 45, 235, 86, 226, 147, 123, 214, 151, 193, 113, 244, 60, 119, 248, + 29, 48, 185, 187, 80, 240, 99, 207, 236, 1, 44, 203, 199, 238, + 182, 118, 1, 183, 51, 87, 179, 253, 248, 25, 226, 202, 36, 27, + 239, 215, 242, 148, 174, 125, 88, 142, 255, 157, 201, 208, 72, 35, + 75, 249, 175, 210, 19, 151, 11, 62, 27, 37, 163, 231, 40, 25, + 162, 30, 191, 175, 61, 240, 235, 141, 204, 108, 177, 77, 229, 153, + 118, 106, 73, 51, 112, 234, 11, 54, 96, 36, 198, 90, 22, 123, + 35, 201, 205, 160, 55, 36, 190, 20, 129, 79, 204, 141, 88, 234, + 12, 41, 238, 185, 68, 227, 170, 202, 156, 147, 251, 120, 157, 16, + 228, 128, 95, 17, 221, 30, 234, 120, 91, 174, 242, 24, 15, 79, + 75, 130, 82, 99, 8, 99, 107, 253, 196, 87, 59, 239, 229, 188, + 66, 93, 226, 12, 184, 233, 29, 213, 185, 12, 8, 185, 190, 33, + 107, 119, 122, 245, 100, 183, 248, 243, 213, 133, 126, 59, 92, 223, + 253, 203, 79, 136, 121, 116, 200, 56, 215, 27, 165, 175, 7, 63, + 136, 187, 161, 253, 96, 190, 117, 34, 101, 109, 158, 13, 179, 90, + 67, 172, 61, 8, 37, 65, 229, 148, 43, 49, 205, 150, 43, 125, + 196, 197, 35, 73, 177, 10, 105, 141, 242, 69, 214, 233, 93, 74, + 29, 219, 224, 24, 130, 207, 231, 90, 58, 71, 238, 181, 103, 230, + 34, 236, 144, 64, 83, 218, 171, 99, 155, 186, 17, 64, 169, 181, + 68, 163, 227, 187, 2, 195, 210, 104, 128, 126, 156, 191, 54, 26, + 122, 91, 79, 203, 195, 214, 11, 55, 198, 87, 57, 61, 163, 47, + 84, 113, 52, 193, 221, 209, 144, 88, 214, 240, 116, 138, 74, 96, + 159, 150, 31, 212, 75, 16, 66, 76, 161, 145, 105, 210, 183, 236, + 156, 47, 207, 183, 83, 54, 75, 140, 214, 201, 62, 83, 83, 116, + 221, 29, 232, 118, 41, 246, 87, 3, 170, 207, 115, 145, 228, 113, + 172, 254, 30, 71, 22, 18, 30, 37, 158, 157, 77, 196, 202, 35, + 55, 166, 150, 206, 29, 90, 53, 8, 235, 184, 184, 31, 19, 58, + 57, 215, 85, 97, 226, 229, 27, 138, 15, 145, 219, 32, 205, 133, + 64, 181, 61, 60, 162, 1, 76, 187, 83, 28, 8, 17, 251, 188, + 172, 242, 227, 67, 113, 215, 4, 62, 97, 102, 242, 85, 165, 85, + 83, 4, 241, 111, 184, 66, 236, 57, 216, 200, 234, 192, 158, 241, + 87, 181, 129, 237, 208, 234, 23, 41, 171, 109, 142, 41, 135, 1, + 200, 119, 244, 195, 170, 232, 217, 6, 41, 235, 118, 9, 180, 169, + 220, 9, 141, 175, 193, 160, 194, 57, 24, 156, 40, 200, 184, 246, + 114, 63, 160, 81, 130, 71, 43, 74, 116, 159, 53, 124, 126, 145, + 91, 241, 190, 57, 27, 109, 174, 120, 247, 60, 221, 1, 134, 8, + 71, 222, 35, 170, 128, 249, 127, 188, 250, 112, 68, 195, 166, 139, + 163, 39, 82, 3, 159, 101, 140, 81, 150, 79, 195, 102, 36, 16, + 202, 56, 51, 48, 161, 98, 90, 231, 181, 236, 244, 186, 1, 67, + 60, 36, 186, 47, 147, 54, 25, 165, 21, 169, 88, 120, 181, 15, + 39, 163, 126, 100, 214, 0, 86, 102, 76, 173, 247, 181, 211, 101, + 232, 208, 213, 200, 145, 124, 36, 90, 221, 158, 88, 122, 214, 165, + 245, 155, 56, 173, 202, 80, 105, 100, 214, 1, 54, 97, 43, 163, + 228, 23, 56, 158, 59, 150, 166, 224, 226, 64, 84, 21, 176, 115, + 115, 97, 202, 52, 232, 139, 23, 12, 170, 108, 207, 159, 8, 242, + 120, 65, 211, 89, 192, 224, 35, 22, 17, 69, 9, 204, 61, 253, + 247, 213, 50, 94, 100, 88, 246, 233, 131, 215, 45, 240, 194, 180, + 231, 175, 42, 46, 109, 103, 95, 73, 124, 234, 69, 180, 133, 130, + 203, 141, 125, 125, 93, 159, 22, 55, 245, 25, 12, 100, 155, 4, + 173, 70, 231, 157, 37, 156, 194, 32, 47, 167, 41, 40, 54, 19, + 66, 43, 172, 183, 49, 160, 9, 85, 180, 56, 159, 19, 170, 37, + 34, 205, 90, 91, 59, 178, 255, 64, 1, 47, 12, 232, 34, 206, + 62, 82, 2, 168, 41, 18, 183, 99, 123, 119, 43, 145, 199, 142, + 196, 95, 230, 199, 179, 53, 94, 178, 146, 15, 41, 78, 101, 10, + 14, 35, 192, 180, 23, 169, 227, 44, 255, 250, 5, 224, 49, 125, + 224, 174, 147, 245, 144, 122, 35, 186, 197, 162, 80, 101, 98, 189, + 246, 114, 220, 223, 183, 197, 18, 176, 63, 144, 80, 161, 204, 109, + 240, 241, 66, 59, 198, 171, 111, 13, 190, 218, 165, 75, 86, 45, + 16, 18, 67, 223, 129, 224, 139, 5, 44, 238, 228, 0, 118, 51, + 74, 77, 76, 34, 51, 113, 41, 188, 26, 171, 34, 143, 200, 211, + 54, 123, 39, 197, 71, 248, 52, 139, 14, 143, 28, 104, 24, 177, + 224, 180, 237, 166, 197, 9, 24, 48, 200, 89, 216, 242, 247, 245, + 192, 17, 70, 62, 32, 181, 217, 199, 112, 111, 194, 202, 87, 164, + 62, 121, 88, 71, 150, 245, 180, 183, 122, 16, 123, 170, 127, 79, + 201, 116, 68, 33, 1, 205, 32, 4, 50, 253, 7, 48, 253, 45, + 237, 131, 71, 132, 76, 39, 86, 218, 96, 91, 28, 123, 43, 24, + 244, 56, 108, 88, 59, 35, 96, 171, 110, 180, 44, 215, 62, 68, + 132, 42, 12, 222, 33, 11, 253, 241, 100, 116, 93, 200, 8, 76, + 17, 167, 128, 188, 176, 78, 136, 102, 215, 135, 43, 169, 0, 163, + 130, 118, 202, 241, 52, 122, 115, 135, 11, 113, 247, 146, 238, 157, + 191, 73, 198, 145, 54, 237, 230, 181, 100, 71, 38, 205, 113, 120, + 20, 157, 154, 186, 250, 148, 122, 218, 64, 111, 213, 95, 140, 141, + 13, 137, 79, 179, 225, 205, 250, 243, 29, 82, 107, 215, 128, 46, + 43, 196, 208, 139, 254, 153, 233, 162, 167, 180, 148, 218, 240, 23, + 123, 148, 156, 163, 121, 28, 233, 88, 173, 138, 0, 187, 193, 211, + 137, 39, 50, 254, 32, 252, 223, 150, 58, 49, 222, 181, 209, 89, + 79, 168, 185, 143, 4, 79, 237, 154, 242, 101, 187, 156, 33, 75, + 192, 167, 6, 183, 252, 140, 243, 99, 122, 30, 201, 176, 250, 121, + 167, 194, 230, 81, 253, 27, 113, 183, 35, 151, 148, 3, 240, 26, + 18, 77, 238, 32, 151, 191, 64, 97, 83, 164, 76, 88, 215, 87, + 55, 51, 147, 108, 58, 169, 210, 64, 250, 80, 35, 7, 191, 64, + 137, 124, 111, 194, 193, 164, 241, 39, 50, 24, 249, 14, 186, 78, + 31, 212, 132, 136, 228, 210, 181, 167, 52, 162, 15, 99, 29, 195, + 122, 222, 83, 227, 203, 227, 71, 74, 202, 175, 43, 89, 123, 101, + 112, 45, 218, 168, 93, 43, 86, 245, 140, 214, 6, 158, 214, 190, + 170, 19, 207, 236, 16, 205, 236, 175, 5, 208, 223, 3, 83, 161, + 54, 192, 115, 88, 253, 174, 166, 181, 1, 30, 252, 209, 221, 11, + 27, 72, 236, 83, 238, 249, 6, 190, 254, 36, 106, 118, 4, 140, + 243, 207, 29, 2, 64, 128, 94, 106, 52, 134, 87, 248, 51, 137, + 192, 208, 235, 70, 236, 81, 186, 177, 59, 245, 15, 40, 74, 139, + 26, 162, 61, 161, 194, 92, 197, 217, 84, 34, 193, 241, 51, 95, + 112, 44, 194, 194, 95, 189, 137, 166, 52, 83, 145, 195, 119, 137, + 149, 243, 184, 36, 159, 111, 147, 88, 250, 101, 23, 237, 69, 138, + 131, 210, 220, 253, 240, 197, 191, 181, 159, 152, 211, 150, 56, 19, + 69, 126, 132, 29, 199, 56, 190, 217, 246, 9, 56, 43, 127, 52, + 137, 32, 26, 68, 159, 239, 154, 121, 59, 230, 54, 181, 56, 144, + 34, 179, 196, 74, 145, 92, 0, 164, 213, 39, 102, 58, 208, 111, + 158, 126, 242, 231, 205, 242, 13, 90, 55, 218, 169, 116, 93, 131, + 40, 117, 87, 191, 251, 179, 157, 124, 123, 14, 24, 224, 43, 225, + 223, 63, 16, 39, 176, 31, 244, 129, 199, 246, 184, 140, 208, 44, + 165, 122, 115, 58, 236, 232, 22, 127, 103, 134, 108, 251, 3, 67, + 19, 189, 120, 129, 223, 164, 155, 181, 84, 124, 170, 223, 113, 228, + 205, 79, 32, 83, 28, 203, 131, 113, 94, 242, 2, 210, 162, 199, + 159, 217, 152, 78, 252, 83, 0, 135, 147, 37, 208, 146, 4, 167, + 50, 29, 216, 151, 102, 163, 100, 158, 28, 243, 251, 9, 88, 55, + 103, 143, 159, 118, 254, 145, 169, 130, 136, 44, 57, 120, 248, 104, + 87, 46, 164, 14, 108, 188, 31, 97, 132, 103, 209, 13, 93, 46, + 246, 159, 126, 113, 190, 139, 125, 74, 24, 93, 63, 195, 99, 145, + 120, 22, 179, 13, 95, 141, 68, 105, 184, 234, 104, 15, 140, 49, + 142, 165, 23, 33, 101, 193, 158, 151, 165, 218, 1, 40, 118, 139, + 33, 187, 70, 227, 86, 251, 12, 205, 196, 211, 143, 113, 11, 55, + 88, 42, 243, 208, 60, 210, 113, 25, 30, 178, 114, 166, 111, 156, + 151, 231, 81, 22, 96, 233, 201, 130, 180, 153, 91, 173, 147, 171, + 172, 83, 249, 33, 181, 217, 129, 73, 94, 245, 160, 31, 85, 198, + 158, 11, 129, 147, 248, 165, 42, 137, 215, 67, 190, 99, 207, 29, + 222, 99, 17, 232, 134, 25, 223, 58, 157, 132, 233, 189, 217, 27, + 142, 171, 155, 41, 53, 230, 27, 29, 109, 38, 21, 121, 8, 58, + 220, 113, 22, 1, 246, 114, 83, 6, 165, 20, 25, 82, 252, 193, + 215, 238, 144, 212, 210, 111, 228, 139, 105, 136, 12, 148, 229, 69, + 41, 93, 65, 160, 192, 76, 79, 50, 108, 91, 58, 107, 125, 73, + 237, 219, 123, 210, 187, 173, 8, 48, 223, 12, 44, 52, 153, 150, + 166, 146, 247, 158, 157, 229, 222, 133, 232, 15, 141, 199, 50, 30, + 173, 51, 150, 56, 60, 144, 169, 103, 91, 255, 231, 81, 240, 65, + 134, 84, 8, 33, 167, 70, 2, 79, 190, 62, 230, 54, 113, 51, + 27, 178, 99, 14, 114, 31, 176, 244, 253, 239, 81, 27, 26, 18, + 100, 19, 104, 164, 71, 56, 112, 170, 223, 158, 167, 12, 51, 99, + 223, 101, 74, 84, 102, 183, 188, 37, 244, 38, 77, 68, 152, 239, + 16, 17, 130, 131, 163, 224, 105, 140, 75, 205, 23, 89, 226, 11, + 209, 206, 116, 131, 7, 222, 243, 58, 232, 126, 61, 45, 170, 160, + 188, 111, 157, 161, 120, 124, 76, 156, 143, 207, 44, 166, 210, 214, + 16, 23, 35, 234, 51, 47, 220, 201, 52, 26, 234, 92, 231, 74, + 65, 164, 209, 196, 94, 209, 63, 22, 158, 139, 65, 217, 242, 251, + 21, 201, 236, 122, 196, 93, 164, 53, 238, 104, 185, 188, 64, 89, + 47, 202, 157, 231, 116, 250, 73, 88, 190, 70, 233, 70, 231, 54, + 5, 243, 125, 252, 241, 206, 53, 19, 71, 210, 212, 183, 223, 15, + 226, 22, 109, 74, 229, 6, 193, 149, 53, 216, 116, 108, 135, 14, + 66, 228, 102, 242, 17, 90, 44, 58, 131, 224, 227, 73, 45, 93, + 253, 134, 177, 99, 15, 217, 222, 117, 179, 147, 205, 216, 74, 222, + 68, 15, 198, 167, 30, 17, 142, 167, 6, 246, 163, 157, 156, 140, + 119, 216, 37, 215, 230, 213, 109, 148, 168, 115, 18, 20, 38, 17, + 24, 37, 103, 24, 96, 240, 128, 165, 244, 7, 173, 205, 167, 109, + 204, 77, 132, 167, 151, 250, 78, 127, 108, 17, 120, 145, 164, 194, + 59, 125, 126, 15, 115, 37, 178, 8, 154, 117, 166, 75, 116, 97, + 228, 242, 42, 252, 184, 168, 146, 96, 156, 67, 207, 60, 135, 202, + 203, 120, 62, 126, 16, 90, 157, 90, 206, 215, 63, 249, 239, 3, + 207, 68, 67, 224, 202, 241, 126, 253, 61, 108, 89, 247, 51, 113, + 211, 74, 249, 156, 154, 184, 212, 221, 162, 125, 154, 77, 91, 200, + 56, 102, 57, 58, 218, 129, 54, 243, 151, 78, 50, 140, 234, 32, + 61, 91, 49, 226, 36, 216, 159, 64, 101, 150, 105, 76, 67, 56, + 60, 152, 152, 215, 138, 90, 184, 83, 191, 234, 54, 191, 85, 231, + 95, 193, 208, 28, 253, 231, 237, 51, 176, 187, 76, 235, 25, 103, + 51, 97, 165, 173, 158, 118, 141, 231, 199, 65, 91, 48, 155, 52, + 236, 182, 133, 35, 21, 204, 237, 237, 218, 195, 147, 0, 186, 29, + 112, 9, 152, 204, 42, 224, 202, 35, 51, 253, 18, 107, 200, 42, + 234, 25, 250, 197, 73, 33, 77, 160, 121, 74, 239, 13, 57, 65, + 163, 168, 74, 240, 121, 104, 116, 119, 220, 194, 82, 172, 76, 122, + 96, 156, 251, 204, 36, 163, 253, 202, 52, 135, 113, 155, 198, 190, + 206, 236, 157, 56, 157, 201, 114, 222, 155, 77, 138, 178, 65, 229, + 209, 40, 166, 251, 200, 12, 68, 248, 245, 80, 147, 121, 88, 74, + 189, 144, 77, 9, 150, 65, 148, 254, 2, 245, 46, 210, 151, 224, + 158, 27, 29, 218, 235, 188, 97, 20, 96, 83, 12, 254, 127, 39, + 20, 158, 19, 102, 101, 3, 190, 222, 241, 96, 15, 102, 82, 249, + 68, 202, 116, 229, 134, 170, 212, 79, 88, 125, 48, 126, 232, 61, + 3, 234, 159, 2, 166, 30, 5, 239, 109, 24, 126, 126, 123, 46, + 73, 170, 42, 157, 54, 233, 58, 123, 111, 126, 118, 18, 38, 118, + 226, 70, 209, 244, 195, 139, 83, 228, 213, 158, 139, 171, 98, 209, + 63, 96, 40, 247, 162, 17, 255, 189, 79, 2, 152, 97, 255, 244, + 222, 138, 42, 63, 98, 105, 189, 164, 95, 97, 223, 249, 52, 213, + 184, 52, 133, 191, 252, 26, 158, 143, 8, 170, 14, 151, 115, 65, + 140, 40, 204, 107, 26, 170, 34, 68, 49, 93, 182, 18, 69, 129, + 106, 187, 3, 234, 151, 233, 202, 34, 135, 249, 221, 254, 154, 116, + 125, 214, 89, 73, 147, 44, 42, 129, 114, 65, 251, 91, 92, 6, + 146, 90, 129, 203, 192, 222, 112, 50, 139, 212, 3, 187, 216, 224, + 140, 142, 103, 180, 31, 112, 159, 205, 109, 231, 26, 171, 135, 204, + 78, 94, 243, 227, 216, 75, 222, 20, 208, 172, 181, 240, 150, 184, + 135, 233, 85, 155, 78, 180, 188, 228, 236, 221, 39, 239, 247, 158, + 23, 28, 20, 190, 146, 81, 236, 188, 64, 168, 150, 209, 215, 120, + 70, 32, 59, 185, 7, 113, 12, 91, 135, 184, 184, 47, 111, 27, + 75, 210, 255, 227, 71, 45, 168, 161, 151, 192, 111, 117, 29, 5, + 29, 128, 136, 64, 103, 231, 107, 52, 8, 237, 213, 198, 121, 49, + 95, 226, 10, 200, 169, 63, 155, 214, 164, 197, 170, 95, 84, 180, + 111, 13, 193, 200, 18, 131, 246, 206, 10, 104, 28, 22, 255, 15, + 249, 181, 150, 204, 228, 57, 73, 67, 165, 21, 64, 109, 104, 188, + 206, 92, 252, 30, 222, 229, 235, 75, 182, 69, 183, 223, 200, 102, + 214, 239, 129, 139, 213, 188, 53, 223, 119, 235, 43, 88, 183, 255, + 22, 68, 252, 115, 128, 213, 7, 193, 149, 89, 229, 171, 229, 198, + 15, 118, 40, 251, 132, 27, 76, 250, 43, 228, 140, 97, 227, 180, + 240, 74, 27, 61, 167, 174, 183, 87, 82, 183, 167, 78, 222, 183, + 212, 8, 139, 18, 105, 16, 242, 48, 22, 180, 239, 235, 0, 37, + 255, 202, 204, 127, 97, 56, 38, 10, 71, 81, 31, 135, 71, 172, + 24, 186, 210, 240, 201, 171, 145, 146, 25, 65, 80, 106, 103, 51, + 217, 245, 112, 213, 115, 247, 182, 6, 247, 178, 53, 67, 146, 16, + 57, 139, 134, 173, 124, 28, 248, 10, 22, 104, 227, 169, 220, 246, + 104, 133, 194, 95, 101, 0, 121, 136, 42, 156, 243, 196, 228, 244, + 85, 107, 137, 112, 39, 57, 100, 254, 221, 182, 51, 30, 34, 96, + 78, 2, 138, 101, 166, 146, 56, 145, 24, 247, 63, 130, 11, 105, + 186, 43, 77, 153, 48, 7, 197, 110, 190, 109, 44, 0, 229, 149, + 211, 95, 79, 3, 28, 159, 26, 166, 117, 234, 235, 78, 199, 167, + 139, 240, 5, 177, 81, 83, 119, 251, 218, 156, 67, 7, 74, 170, + 23, 236, 107, 128, 185, 75, 211, 233, 164, 62, 7, 105, 112, 65, + 68, 82, 12, 204, 76, 136, 157, 177, 215, 136, 99, 137, 2, 177, + 244, 102, 75, 77, 202, 210, 30, 158, 144, 219, 28, 72, 98, 185, + 191, 228, 37, 79, 99, 32, 184, 5, 181, 96, 208, 135, 77, 63, + 251, 126, 15, 185, 107, 200, 3, 135, 121, 215, 218, 187, 55, 116, + 170, 19, 232, 44, 94, 145, 183, 24, 185, 177, 244, 202, 217, 243, + 117, 116, 17, 31, 176, 27, 33, 23, 217, 53, 21, 10, 31, 151, + 20, 74, 212, 60, 237, 214, 249, 67, 123, 28, 222, 119, 239, 68, + 166, 12, 217, 18, 19, 210, 6, 132, 173, 253, 230, 115, 136, 124, + 153, 205, 16, 241, 47, 196, 145, 145, 138, 18, 5, 191, 156, 77, + 13, 104, 106, 147, 63, 54, 213, 194, 27, 23, 249, 233, 172, 150, + 11, 116, 221, 29, 51, 41, 197, 170, 45, 154, 116, 246, 226, 164, + 219, 90, 221, 173, 159, 29, 125, 127, 128, 42, 246, 183, 220, 23, + 21, 14, 157, 144, 150, 126, 177, 110, 190, 83, 134, 113, 82, 66, + 86, 140, 253, 97, 163, 135, 142, 19, 207, 117, 95, 97, 175, 15, + 111, 192, 182, 34, 34, 115, 75, 232, 83, 96, 117, 250, 202, 15, + 51, 193, 208, 254, 34, 67, 212, 148, 118, 162, 50, 217, 240, 34, + 151, 164, 38, 242, 59, 170, 70, 143, 168, 96, 80, 25, 74, 60, + 3, 221, 254, 176, 79, 132, 204, 195, 170, 249, 220, 218, 28, 179, + 157, 11, 208, 114, 222, 221, 74, 115, 91, 199, 135, 181, 213, 9, + 134, 14, 30, 207, 70, 186, 246, 145, 9, 106, 15, 1, 69, 244, + 69, 29, 33, 7, 189, 173, 161, 159, 127, 67, 208, 147, 38, 230, + 214, 137, 229, 250, 55, 201, 174, 177, 139, 55, 219, 72, 83, 106, + 203, 76, 163, 51, 113, 234, 32, 43, 138, 34, 235, 139, 113, 109, + 211, 238, 227, 203, 153, 212, 222, 209, 234, 232, 242, 245, 83, 83, + 95, 100, 88, 122, 219, 113, 29, 23, 31, 190, 88, 87, 129, 95, + 81, 88, 100, 131, 217, 216, 242, 156, 143, 36, 108, 38, 89, 114, + 110, 215, 243, 31, 133, 83, 67, 12, 42, 155, 98, 88, 228, 213, + 245, 19, 203, 47, 194, 33, 147, 72, 209, 22, 118, 180, 224, 108, + 218, 226, 159, 102, 166, 165, 67, 171, 54, 77, 158, 154, 2, 36, + 143, 61, 6, 70, 248, 117, 167, 27, 20, 180, 158, 13, 195, 41, + 72, 78, 56, 186, 111, 55, 234, 62, 202, 24, 53, 36, 152, 32, + 31, 115, 240, 168, 128, 11, 116, 232, 78, 252, 129, 105, 15, 242, + 101, 82, 117, 253, 122, 0, 0, 8, 183, 201, 207, 241, 214, 32, + 195, 232, 105, 95, 63, 213, 251, 136, 201, 147, 136, 74, 206, 249, + 61, 32, 191, 221, 145, 61, 250, 90, 167, 221, 234, 30, 216, 10, + 237, 207, 188, 157, 65, 102, 91, 60, 64, 65, 8, 67, 50, 218, + 242, 136, 242, 89, 1, 214, 109, 237, 8, 139, 179, 160, 16, 185, + 87, 228, 213, 171, 106, 160, 59, 77, 191, 230, 42, 135, 35, 123, + 200, 183, 194, 75, 126, 131, 83, 40, 18, 243, 53, 56, 148, 230, + 141, 185, 82, 188, 224, 186, 110, 35, 224, 130, 30, 36, 84, 139, + 101, 163, 158, 199, 63, 192, 84, 153, 11, 49, 166, 77, 89, 156, + 94, 3, 255, 128, 253, 57, 190, 114, 43, 37, 91, 29, 79, 119, + 250, 206, 157, 148, 104, 121, 158, 177, 6, 231, 89, 233, 135, 245, + 144, 137, 102, 151, 52, 243, 24, 2, 237, 148, 224, 196, 184, 240, + 48, 17, 118, 153, 107, 46, 233, 95, 156, 93, 204, 89, 81, 17, + 39, 115, 191, 42, 64, 95, 159, 27, 165, 21, 112, 52, 179, 113, + 126, 34, 52, 161, 250, 168, 78, 223, 59, 238, 14, 80, 130, 151, + 78, 175, 210, 66, 218, 221, 103, 125, 111, 201, 221, 133, 123, 60, + 4, 88, 28, 56, 31, 218, 222, 102, 119, 78, 39, 182, 73, 11, + 158, 134, 197, 26, 100, 80, 24, 194, 155, 141, 108, 99, 30, 37, + 134, 190, 33, 75, 166, 80, 21, 214, 243, 111, 64, 176, 115, 56, + 197, 232, 229, 68, 5, 131, 88, 69, 12, 65, 175, 42, 178, 103, + 153, 223, 197, 41, 59, 40, 187, 93, 65, 183, 186, 209, 248, 228, + 44, 120, 7, 65, 101, 153, 105, 204, 104, 57, 122, 203, 96, 116, + 233, 217, 54, 54, 98, 80, 206, 80, 183, 39, 183, 250, 69, 253, + 0, 85, 121, 165, 29, 187, 184, 38, 176, 185, 223, 230, 228, 42, + 241, 251, 201, 174, 241, 133, 249, 174, 133, 80, 163, 249, 113, 28, + 32, 50, 255, 101, 70, 104, 64, 111, 63, 218, 108, 170, 48, 245, + 61, 40, 137, 234, 173, 6, 2, 76, 114, 234, 150, 97, 75, 36, + 61, 25, 59, 19, 130, 254, 33, 251, 126, 171, 244, 28, 17, 231, + 67, 140, 184, 245, 160, 212, 23, 141, 48, 120, 158, 226, 41, 143, + 70, 179, 215, 149, 29, 216, 152, 89, 129, 135, 116, 125, 227, 81, + 100, 76, 126, 122, 4, 105, 229, 129, 174, 252, 105, 231, 136, 26, + 160, 39, 121, 155, 164, 27, 240, 137, 241, 96, 40, 245, 71, 27, + 123, 149, 199, 99, 189, 75, 143, 149, 134, 215, 253, 13, 3, 178, + 229, 56, 211, 240, 239, 173, 229, 202, 255, 30, 88, 43, 70, 162, + 234, 174, 126, 81, 42, 171, 99, 10, 148, 147, 40, 224, 19, 238, + 230, 186, 53, 45, 233, 153, 209, 105, 199, 93, 142, 193, 174, 106, + 109, 21, 177, 110, 94, 39, 247, 238, 173, 149, 76, 34, 107, 83, + 52, 137, 26, 133, 78, 17, 39, 213, 55, 82, 111, 2, 39, 54, + 197, 192, 240, 215, 126, 179, 8, 29, 192, 241, 98, 97, 249, 175, + 253, 113, 174, 155, 14, 114, 141, 51, 145, 172, 237, 41, 0, 184, + 97, 164, 145, 40, 171, 191, 166, 246, 20, 89, 151, 12, 124, 70, + 181, 183, 68, 22, 178, 167, 53, 196, 104, 139, 204, 149, 193, 225, + 117, 35, 215, 41, 228, 173, 22, 107, 19, 9, 198, 79, 64, 152, + 239, 164, 173, 75, 63, 224, 224, 72, 65, 107, 238, 129, 249, 91, + 191, 137, 171, 12, 42, 210, 88, 45, 202, 232, 224, 110, 252, 103, + 50, 159, 5, 219, 177, 97, 174, 93, 93, 43, 106, 48, 89, 181, + 46, 16, 28, 252, 67, 44, 186, 67, 10, 88, 241, 19, 233, 83, + 122, 246, 218, 30, 37, 26, 188, 253, 163, 6, 241, 225, 115, 96, + 159, 90, 109, 122, 240, 12, 39, 235, 110, 244, 62, 254, 19, 245, + 175, 171, 124, 49, 253, 23, 121, 228, 96, 65, 106, 134, 173, 57, + 239, 203, 238, 50, 15, 98, 51, 219, 172, 193, 148, 17, 109, 68, + 10, 146, 107, 10, 233, 133, 20, 36, 236, 163, 72, 27, 150, 131, + 141, 124, 220, 59, 29, 138, 197, 147, 33, 77, 7, 31, 153, 66, + 210, 71, 80, 70, 224, 162, 118, 198, 250, 169, 67, 148, 139, 58, + 227, 75, 219, 22, 141, 253, 21, 188, 183, 10, 66, 13, 81, 208, + 117, 138, 205, 226, 107, 99, 0, 116, 33, 189, 21, 189, 84, 121, + 73, 173, 227, 115, 127, 112, 83, 142, 69, 86, 240, 250, 48, 240, + 70, 0, 215, 164, 80, 210, 64, 240, 120, 32, 62, 238, 115, 218, + 99, 22, 144, 189, 12, 183, 19, 132, 243, 74, 139, 168, 169, 73, + 18, 114, 75, 165, 209, 211, 16, 61, 58, 77, 72, 97, 238, 220, + 62, 219, 223, 249, 196, 93, 227, 77, 101, 73, 23, 56, 191, 78, + 151, 74, 244, 253, 211, 17, 229, 204, 150, 28, 183, 224, 170, 55, + 27, 209, 141, 194, 170, 227, 88, 233, 238, 170, 128, 147, 80, 85, + 124, 181, 144, 52, 160, 117, 82, 60, 30, 57, 63, 190, 150, 185, + 178, 134, 19, 174, 137, 146, 254, 44, 218, 161, 201, 166, 155, 155, + 124, 172, 127, 248, 120, 56, 210, 182, 131, 206, 120, 252, 132, 115, + 197, 186, 53, 164, 113, 250, 199, 230, 69, 166, 233, 14, 104, 59, + 11, 124, 20, 185, 173, 160, 119, 225, 108, 156, 78, 199, 154, 150, + 247, 9, 242, 229, 101, 158, 234, 114, 60, 39, 114, 19, 202, 192, + 4, 21, 44, 98, 43, 77, 3, 175, 226, 178, 45, 17, 180, 89, + 133, 32, 35, 73, 194, 217, 2, 116, 238, 178, 115, 251, 245, 69, + 183, 39, 58, 40, 243, 153, 50, 219, 165, 59, 30, 193, 101, 250, + 126, 61, 161, 220, 194, 148, 214, 197, 17, 39, 50, 248, 86, 98, + 135, 94, 90, 235, 202, 233, 161, 204, 62, 177, 46, 91, 70, 110, + 180, 141, 64, 244, 54, 154, 38, 89, 51, 171, 242, 119, 13, 64, + 57, 112, 51, 171, 200, 66, 185, 236, 224, 41, 133, 208, 196, 60, + 141, 81, 231, 77, 11, 235, 76, 116, 53, 132, 100, 222, 40, 202, + 90, 1, 16, 3, 123, 74, 155, 6, 32, 103, 127, 238, 84, 89, + 93, 28, 135, 97, 117, 23, 198, 243, 185, 34, 238, 241, 135, 6, + 80, 171, 228, 109, 114, 73, 194, 129, 23, 180, 44, 102, 77, 8, + 183, 187, 165, 236, 190, 31, 100, 97, 213, 222, 51, 23, 61, 163, + 229, 14, 87, 91, 231, 34, 27, 113, 135, 139, 166, 48, 57, 26, + 118, 6, 120, 163, 201, 195, 245, 70, 125, 154, 140, 202, 223, 198, + 234, 60, 114, 64, 141, 252, 199, 251, 20, 54, 5, 159, 54, 31, + 101, 187, 77, 115, 115, 126, 153, 230, 72, 112, 92, 102, 114, 0, + 65, 39, 198, 240, 197, 213, 231, 207, 236, 60, 75, 35, 32, 176, + 106, 184, 215, 85, 177, 174, 116, 46, 45, 227, 204, 178, 63, 21, + 115, 185, 224, 232, 73, 235, 31, 183, 124, 181, 179, 116, 2, 72, + 124, 131, 204, 59, 142, 141, 193, 127, 99, 77, 4, 169, 215, 41, + 43, 55, 252, 12, 171, 62, 249, 124, 190, 208, 129, 244, 154, 36, + 219, 122, 89, 243, 219, 180, 248, 240, 139, 10, 195, 113, 19, 189, + 169, 31, 228, 98, 25, 43, 157, 115, 167, 84, 175, 127, 34, 102, + 107, 159, 234, 172, 198, 188, 181, 146, 4, 129, 38, 181, 227, 129, + 132, 74, 139, 253, 1, 93, 159, 76, 14, 157, 77, 187, 158, 253, + 255, 47, 76, 112, 127, 75, 71, 23, 55, 158, 191, 95, 180, 88, + 105, 201, 88, 58, 4, 246, 155, 224, 152, 10, 30, 35, 108, 220, + 232, 96, 27, 34, 100, 73, 98, 70, 226, 125, 249, 45, 232, 211, + 12, 237, 188, 150, 98, 151, 6, 212, 58, 200, 6, 228, 84, 40, + 135, 87, 145, 155, 80, 61, 211, 105, 207, 70, 173, 29, 46, 193, + 234, 236, 113, 172, 90, 108, 157, 169, 162, 209, 186, 83, 56, 66, + 232, 54, 218, 28, 43, 241, 115, 146, 168, 65, 127, 175, 53, 42, + 231, 199, 117, 161, 248, 219, 189, 2, 15, 121, 181, 89, 75, 29, + 216, 121, 209, 68, 28, 202, 193, 60, 119, 219, 190, 131, 55, 27, + 164, 116, 88, 114, 36, 199, 155, 160, 42, 12, 244, 28, 125, 153, + 19, 192, 88, 131, 211, 14, 50, 143, 252, 136, 55, 145, 90, 158, + 180, 184, 10, 86, 246, 158, 197, 95, 137, 244, 154, 61, 18, 250, + 1, 96, 247, 237, 41, 57, 173, 7, 94, 190, 149, 78, 33, 221, + 209, 33, 84, 219, 215, 177, 163, 197, 165, 70, 1, 147, 250, 114, + 186, 25, 41, 20, 76, 254, 17, 129, 200, 52, 115, 242, 158, 143, + 178, 72, 109, 201, 246, 32, 76, 73, 203, 237, 231, 3, 193, 248, + 225, 68, 13, 252, 105, 87, 8, 93, 34, 17, 110, 227, 36, 171, + 97, 195, 103, 195, 55, 118, 151, 68, 110, 144, 122, 29, 126, 191, + 100, 177, 34, 116, 52, 121, 87, 55, 39, 223, 97, 65, 215, 38, + 52, 132, 91, 130, 219, 242, 182, 198, 33, 35, 37, 250, 235, 39, + 90, 75, 123, 30, 50, 31, 93, 160, 236, 234, 116, 112, 196, 130, + 153, 129, 198, 167, 137, 72, 86, 40, 116, 182, 122, 127, 21, 133, + 253, 119, 105, 11, 34, 6, 56, 199, 94, 231, 73, 111, 171, 125, + 31, 130, 245, 138, 86, 83, 174, 199, 180, 203, 190, 68, 188, 66, + 52, 144, 174, 182, 193, 217, 215, 164, 47, 182, 15, 74, 196, 78, + 75, 94, 190, 223, 208, 32, 34, 19, 165, 235, 253, 113, 181, 108, + 71, 238, 31, 5, 139, 170, 152, 80, 103, 169, 161, 131, 13, 107, + 26, 248, 13, 156, 89, 138, 177, 142, 84, 112, 191, 209, 8, 17, + 19, 93, 66, 62, 18, 97, 41, 114, 142, 38, 80, 129, 14, 160, + 194, 175, 13, 93, 202, 245, 251, 70, 207, 181, 91, 14, 14, 81, + 169, 235, 153, 230, 6, 77, 253, 70, 141, 218, 189, 94, 201, 121, + 46, 221, 52, 52, 172, 213, 61, 69, 125, 135, 235, 250, 42, 49, + 180, 24, 65, 19, 120, 119, 74, 55, 45, 99, 159, 88, 102, 227, + 155, 98, 52, 77, 94, 67, 64, 174, 167, 134, 59, 55, 73, 96, + 37, 8, 69, 56, 97, 150, 127, 130, 183, 203, 23, 239, 220, 65, + 73, 118, 251, 219, 213, 236, 161, 164, 155, 112, 39, 231, 9, 147, + 173, 41, 26, 48, 82, 195, 45, 6, 157, 189, 217, 58, 100, 20, + 195, 124, 209, 14, 198, 182, 208, 131, 26, 120, 236, 123, 222, 95, + 163, 0, 147, 182, 228, 210, 85, 168, 249, 101, 197, 39, 75, 188, + 33, 198, 64, 35, 72, 230, 200, 220, 30, 98, 2, 94, 50, 179, + 235, 194, 42, 161, 96, 191, 210, 161, 214, 138, 158, 46, 223, 39, + 119, 77, 153, 104, 132, 24, 124, 44, 204, 169, 36, 130, 120, 33, + 65, 134, 114, 205, 54, 242, 25, 122, 9, 250, 0, 98, 65, 131, + 121, 182, 28, 40, 110, 168, 125, 192, 207, 150, 158, 72, 85, 63, + 22, 184, 76, 190, 27, 17, 242, 41, 221, 79, 57, 225, 143, 17, + 252, 42, 100, 0, 51, 111, 132, 38, 2, 12, 245, 109, 28, 160, + 33, 112, 102, 156, 34, 172, 90, 253, 170, 20, 145, 244, 18, 251, + 238, 238, 214, 18, 224, 217, 134, 203, 214, 50, 113, 170, 60, 6, + 139, 208, 252, 77, 83, 211, 18, 26, 17, 12, 112, 237, 104, 66, + 46, 74, 32, 23, 240, 189, 48, 144, 207, 109, 159, 84, 215, 28, + 192, 179, 188, 7, 53, 53, 73, 69, 147, 249, 168, 11, 97, 112, + 162, 13, 126, 111, 237, 45, 210, 159, 124, 106, 231, 185, 151, 92, + 8, 110, 171, 114, 57, 48, 129, 17, 130, 222, 10, 228, 247, 195, + 194, 127, 237, 23, 176, 11, 93, 232, 237, 116, 234, 62, 66, 218, + 213, 165, 59, 138, 53, 98, 7, 167, 214, 26, 246, 107, 33, 119, + 124, 61, 224, 240, 202, 102, 187, 17, 89, 157, 215, 123, 167, 174, + 76, 249, 14, 216, 206, 55, 25, 86, 205, 105, 223, 53, 209, 186, + 55, 86, 196, 245, 88, 16, 201, 133, 144, 132, 191, 8, 122, 128, + 127, 27, 164, 231, 210, 242, 221, 112, 202, 66, 157, 38, 28, 201, + 107, 120, 238, 61, 97, 74, 71, 103, 13, 47, 33, 161, 87, 52, + 1, 50, 215, 116, 81, 214, 90, 49, 175, 219, 206, 248, 124, 254, + 177, 62, 168, 102, 234, 40, 159, 146, 88, 57, 245, 93, 182, 20, + 95, 99, 218, 127, 79, 150, 231, 132, 190, 128, 18, 36, 211, 30, + 208, 131, 220, 148, 16, 166, 45, 232, 233, 187, 182, 43, 101, 159, + 189, 139, 20, 238, 222, 239, 199, 21, 155, 156, 247, 154, 87, 164, + 242, 54, 199, 70, 86, 140, 145, 116, 98, 252, 174, 241, 47, 244, + 217, 70, 59, 137, 133, 184, 104, 208, 224, 180, 21, 2, 149, 150, + 121, 183, 223, 14, 174, 150, 77, 157, 145, 198, 2, 43, 204, 204, + 242, 206, 189, 232, 18, 251, 187, 34, 239, 94, 65, 28, 0, 78, + 101, 39, 14, 73, 210, 170, 230, 85, 252, 61, 12, 146, 151, 37, + 187, 151, 227, 22, 104, 19, 26, 28, 213, 53, 209, 25, 36, 165, + 51, 222, 88, 146, 139, 18, 253, 219, 217, 22, 101, 220, 194, 89, + 11, 2, 247, 170, 76, 12, 181, 214, 217, 82, 93, 136, 93, 124, + 106, 249, 236, 162, 223, 96, 238, 208, 50, 144, 13, 240, 143, 216, + 194, 73, 113, 244, 99, 12, 236, 14, 167, 238, 122, 39, 130, 42, + 204, 240, 65, 10, 228, 231, 163, 196, 227, 178, 125, 250, 30, 168, + 125, 31, 85, 106, 2, 52, 178, 245, 5, 220, 76, 214, 18, 44, + 150, 136, 61, 68, 198, 54, 161, 209, 140, 112, 179, 135, 86, 10, + 213, 91, 154, 113, 55, 244, 107, 176, 204, 242, 56, 237, 12, 110, + 121, 65, 143, 216, 10, 203, 55, 22, 126, 205, 78, 216, 66, 233, + 181, 121, 153, 94, 51, 189, 133, 6, 46, 234, 1, 137, 209, 167, + 69, 101, 181, 136, 109, 137, 213, 40, 215, 140, 103, 217, 217, 25, + 129, 222, 49, 241, 117, 195, 94, 201, 255, 155, 70, 32, 53, 88, + 213, 99, 150, 27, 253, 41, 91, 72, 123, 230, 114, 239, 195, 115, + 174, 57, 175, 237, 165, 88, 221, 204, 6, 102, 127, 254, 35, 255, + 62, 143, 84, 74, 192, 7, 34, 124, 22, 54, 79, 102, 133, 201, + 140, 22, 31, 225, 157, 109, 142, 169, 244, 111, 242, 50, 154, 144, + 182, 183, 192, 173, 167, 136, 140, 28, 180, 160, 163, 139, 10, 205, + 95, 150, 229, 111, 109, 201, 53, 64, 252, 241, 74, 198, 159, 187, + 40, 126, 181, 111, 162, 127, 30, 28, 29, 244, 224, 126, 44, 145, + 236, 162, 81, 169, 27, 217, 201, 9, 5, 119, 130, 83, 129, 109, + 199, 87, 246, 7, 136, 27, 11, 69, 82, 160, 74, 146, 62, 63, + 5, 191, 20, 236, 10, 168, 119, 4, 139, 144, 40, 95, 63, 18, + 249, 75, 184, 238, 216, 36, 2, 184, 44, 163, 19, 161, 205, 193, + 78, 226, 213, 55, 16, 42, 227, 55, 39, 158, 159, 37, 50, 233, + 41, 81, 212, 173, 25, 18, 219, 210, 63, 42, 199, 149, 158, 162, + 18, 161, 242, 187, 131, 115, 39, 25, 237, 212, 148, 186, 55, 73, + 242, 147, 244, 199, 195, 125, 115, 30, 83, 144, 34, 189, 185, 130, + 3, 21, 79, 214, 44, 242, 122, 177, 115, 173, 34, 142, 4, 0, + 128, 93, 193, 215, 233, 171, 56, 32, 48, 181, 192, 186, 1, 224, + 162, 252, 107, 201, 159, 188, 187, 56, 3, 115, 28, 122, 57, 107, + 202, 17, 116, 155, 7, 0, 23, 206, 207, 213, 92, 249, 137, 212, + 174, 119, 85, 124, 134, 96, 194, 151, 73, 135, 42, 49, 15, 121, + 9, 22, 33, 146, 191, 183, 76, 208, 180, 94, 80, 161, 37, 90, + 72, 191, 65, 175, 98, 200, 96, 11, 81, 118, 97, 28, 95, 246, + 253, 200, 14, 175, 112, 95, 110, 244, 117, 113, 123, 176, 137, 161, + 72, 96, 200, 73, 137, 203, 251, 227, 110, 158, 167, 173, 8, 152, + 70, 121, 109, 61, 163, 144, 132, 60, 28, 47, 144, 230, 237, 81, + 238, 123, 212, 250, 197, 249, 117, 67, 206, 42, 63, 166, 161, 78, + 81, 113, 62, 170, 83, 240, 44, 155, 156, 8, 215, 163, 225, 210, + 12, 224, 232, 122, 241, 177, 168, 231, 18, 98, 238, 190, 118, 206, + 118, 252, 243, 9, 193, 195, 193, 108, 111, 198, 24, 176, 136, 35, + 60, 190, 20, 16, 45, 12, 212, 73, 215, 205, 151, 36, 25, 66, + 248, 83, 167, 185, 44, 173, 155, 83, 185, 234, 9, 245, 163, 122, + 78, 116, 169, 85, 252, 176, 157, 177, 144, 171, 74, 48, 220, 108, + 128, 197, 132, 145, 136, 159, 243, 37, 79, 114, 209, 236, 54, 8, + 220, 195, 121, 29, 100, 172, 78, 30, 193, 48, 166, 54, 44, 107, + 142, 248, 166, 200, 114, 205, 184, 173, 32, 172, 36, 166, 219, 40, + 111, 81, 55, 255, 21, 185, 251, 172, 109, 56, 144, 205, 135, 216, + 230, 229, 216, 207, 98, 234, 123, 46, 79, 22, 212, 21, 11, 85, + 160, 188, 196, 205, 188, 176, 87, 11, 119, 214, 137, 226, 104, 185, + 64, 111, 215, 254, 165, 1, 131, 237, 37, 222, 141, 58, 79, 220, + 188, 93, 189, 249, 231, 23, 124, 36, 122, 157, 222, 124, 104, 199, + 47, 129, 53, 83, 81, 217, 159, 79, 105, 176, 216, 138, 172, 58, + 147, 25, 236, 98, 87, 140, 185, 168, 210, 119, 198, 50, 255, 235, + 241, 37, 249, 21, 212, 127, 212, 164, 66, 174, 177, 88, 137, 109, + 204, 183, 222, 119, 9, 212, 138, 198, 214, 41, 120, 226, 42, 251, + 92, 79, 17, 112, 193, 35, 10, 249, 66, 4, 55, 22, 155, 16, + 66, 116, 32, 112, 233, 218, 51, 107, 77, 209, 9, 202, 85, 90, + 201, 191, 38, 148, 78, 157, 22, 175, 99, 9, 84, 250, 170, 0, + 241, 108, 146, 34, 4, 113, 180, 191, 180, 212, 255, 117, 49, 194, + 138, 166, 202, 148, 113, 192, 14, 104, 193, 139, 116, 27, 93, 158, + 59, 211, 130, 204, 130, 23, 127, 195, 65, 102, 144, 81, 175, 166, + 200, 199, 136, 102, 187, 249, 168, 62, 247, 246, 157, 120, 138, 49, + 103, 232, 109, 199, 67, 129, 149, 87, 237, 245, 87, 139, 172, 44, + 129, 132, 93, 200, 149, 116, 222, 85, 220, 213, 185, 68, 223, 153, + 34, 119, 42, 121, 101, 126, 13, 111, 34, 238, 92, 178, 63, 92, + 23, 174, 134, 199, 104, 83, 62, 44, 214, 254, 146, 106, 198, 69, + 248, 202, 189, 168, 99, 238, 25, 184, 170, 215, 197, 155, 55, 196, + 111, 236, 12, 106, 80, 145, 21, 228, 184, 143, 16, 211, 113, 214, + 240, 221, 249, 66, 37, 56, 0, 203, 236, 163, 202, 229, 214, 69, + 82, 176, 160, 178, 110, 179, 12, 189, 58, 197, 6, 13, 214, 116, + 181, 113, 246, 138, 97, 238, 29, 3, 244, 24, 31, 88, 140, 176, + 94, 10, 88, 182, 38, 246, 172, 18, 180, 167, 235, 148, 154, 14, + 34, 201, 90, 184, 247, 136, 213, 200, 169, 128, 145, 90, 210, 20, + 0, 193, 104, 13, 250, 170, 244, 74, 130, 56, 112, 241, 136, 180, + 147, 102, 15, 161, 132, 180, 155, 247, 248, 253, 115, 158, 161, 28, + 36, 75, 4, 59, 125, 45, 176, 60, 177, 39, 190, 243, 215, 155, + 163, 50, 209, 74, 192, 6, 164, 128, 148, 164, 247, 13, 233, 104, + 73, 164, 123, 81, 48, 168, 254, 240, 240, 242, 25, 107, 6, 87, + 253, 27, 203, 65, 245, 1, 58, 201, 145, 107, 96, 120, 211, 238, + 188, 161, 46, 121, 235, 26, 153, 20, 123, 108, 192, 4, 57, 191, + 101, 131, 131, 64, 57, 213, 191, 73, 42, 49, 166, 236, 230, 217, + 254, 34, 99, 82, 136, 238, 234, 12, 155, 151, 0, 105, 30, 58, + 14, 183, 217, 243, 212, 43, 2, 58, 91, 144, 132, 127, 77, 252, + 191, 255, 61, 218, 83, 87, 70, 188, 56, 145, 207, 110, 7, 29, + 94, 56, 175, 192, 10, 231, 199, 71, 57, 3, 246, 252, 189, 130, + 199, 54, 201, 22, 185, 118, 86, 19, 130, 48, 160, 164, 97, 138, + 138, 2, 1, 218, 242, 8, 36, 247, 24, 4, 30, 247, 85, 13, + 227, 165, 58, 235, 123, 147, 121, 210, 0, 171, 75, 63, 20, 35, + 63, 172, 157, 225, 55, 137, 122, 45, 141, 134, 113, 109, 72, 107, + 111, 79, 248, 30, 128, 10, 82, 144, 72, 250, 127, 219, 120, 231, + 226, 80, 54, 224, 104, 44, 170, 110, 151, 129, 192, 225, 231, 119, + 213, 22, 230, 21, 50, 224, 130, 198, 98, 234, 249, 186, 201, 66, + 92, 138, 193, 86, 156, 26, 178, 93, 188, 209, 210, 13, 26, 116, + 90, 219, 235, 145, 253, 98, 145, 205, 58, 8, 142, 254, 175, 25, + 100, 84, 7, 174, 242, 9, 243, 255, 71, 39, 222, 117, 141, 171, + 103, 219, 233, 21, 24, 239, 241, 7, 92, 184, 137, 103, 26, 12, + 166, 46, 215, 241, 122, 53, 237, 40, 227, 36, 96, 243, 184, 119, + 167, 233, 138, 47, 199, 200, 218, 250, 105, 59, 119, 65, 111, 213, + 230, 151, 31, 96, 26, 215, 134, 252, 53, 142, 10, 52, 85, 110, + 229, 91, 172, 179, 223, 243, 130, 62, 48, 33, 223, 249, 153, 160, + 49, 94, 190, 251, 44, 195, 163, 161, 38, 32, 224, 160, 48, 160, + 7, 211, 101, 76, 161, 153, 157, 185, 45, 132, 188, 187, 10, 83, + 204, 196, 126, 45, 137, 197, 58, 166, 130, 224, 254, 245, 89, 30, + 199, 137, 46, 185, 30, 93, 110, 91, 135, 254, 212, 15, 199, 172, + 43, 15, 156, 247, 32, 182, 239, 65, 247, 76, 56, 115, 242, 27, + 180, 4, 108, 178, 154, 43, 87, 76, 205, 221, 179, 213, 219, 174, + 97, 8, 221, 80, 122, 73, 215, 149, 234, 165, 95, 2, 125, 210, + 255, 178, 192, 111, 32, 6, 79, 75, 111, 0, 0, 16, 126, 219, + 122, 77, 165, 132, 49, 61, 95, 179, 33, 53, 253, 126, 170, 172, + 246, 84, 237, 159, 99, 167, 209, 229, 89, 31, 242, 98, 153, 226, + 3, 17, 92, 186, 62, 123, 232, 220, 48, 83, 128, 104, 74, 218, + 226, 105, 110, 251, 128, 214, 132, 233, 162, 123, 222, 68, 174, 179, + 114, 118, 242, 145, 52, 123, 255, 153, 61, 4, 204, 120, 236, 190, + 218, 159, 15, 205, 46, 215, 118, 102, 37, 132, 139, 202, 65, 45, + 160, 25, 73, 208, 87, 29, 184, 48, 64, 195, 65, 208, 176, 122, + 158, 182, 218, 220, 7, 48, 37, 43, 248, 44, 97, 190, 206, 102, + 189, 5, 93, 14, 238, 202, 218, 125, 96, 107, 228, 46, 17, 123, + 130, 39, 147, 147, 200, 131, 123, 33, 189, 194, 194, 71, 109, 22, + 68, 170, 92, 19, 59, 59, 46, 216, 161, 75, 20, 245, 181, 60, + 207, 115, 56, 128, 91, 160, 194, 96, 25, 85, 46, 157, 53, 119, + 77, 243, 229, 151, 35, 44, 232, 218, 49, 54, 64, 16, 94, 77, + 217, 42, 120, 145, 239, 172, 79, 91, 129, 226, 28, 211, 251, 224, + 241, 89, 56, 49, 162, 103, 69, 133, 182, 58, 151, 124, 104, 42, + 99, 128, 21, 129, 4, 159, 197, 58, 215, 250, 169, 119, 209, 5, + 199, 62, 161, 106, 41, 97, 51, 229, 107, 173, 197, 214, 84, 157, + 139, 252, 7, 175, 74, 234, 39, 46, 82, 236, 204, 192, 52, 167, + 43, 170, 9, 3, 73, 17, 194, 218, 71, 249, 74, 112, 250, 203, + 61, 183, 57, 209, 242, 49, 136, 32, 195, 239, 142, 247, 76, 105, + 112, 248, 17, 226, 162, 32, 91, 180, 113, 3, 135, 165, 122, 122, + 205, 130, 245, 140, 156, 19, 140, 102, 67, 189, 51, 135, 232, 152, + 21, 166, 63, 30, 224, 223, 37, 216, 116, 51, 73, 108, 18, 137, + 136, 181, 201, 11, 96, 213, 168, 39, 114, 135, 27, 38, 186, 33, + 157, 234, 173, 239, 125, 72, 97, 125, 67, 98, 67, 135, 126, 238, + 192, 155, 183, 42, 18, 201, 120, 220, 226, 158, 75, 88, 111, 220, + 114, 74, 112, 107, 170, 160, 180, 6, 111, 159, 98, 174, 207, 98, + 57, 246, 100, 102, 191, 84, 142, 197, 34, 206, 135, 22, 243, 100, + 15, 219, 235, 128, 73, 147, 205, 118, 107, 79, 195, 248, 194, 215, + 237, 239, 21, 164, 212, 51, 93, 223, 11, 68, 172, 188, 178, 62, + 197, 114, 17, 14, 161, 165, 174, 218, 201, 143, 65, 194, 102, 125, + 247, 253, 215, 89, 55, 170, 201, 49, 72, 181, 255, 195, 249, 172, + 149, 197, 28, 106, 142, 254, 23, 248, 7, 165, 12, 29, 238, 109, + 177, 247, 64, 53, 235, 91, 229, 153, 103, 158, 176, 139, 234, 78, + 126, 97, 22, 138, 27, 241, 98, 2, 54, 226, 5, 36, 196, 181, + 216, 60, 114, 92, 226, 142, 228, 209, 102, 140, 3, 240, 10, 13, + 92, 138, 87, 202, 34, 25, 235, 175, 170, 92, 69, 189, 134, 154, + 24, 45, 0, 230, 96, 183, 124, 248, 139, 9, 71, 160, 172, 243, + 139, 52, 82, 86, 245, 19, 223, 192, 162, 224, 173, 50, 231, 22, + 13, 43, 113, 129, 164, 172, 223, 92, 166, 108, 45, 198, 186, 40, + 122, 90, 109, 190, 203, 64, 64, 67, 7, 2, 212, 153, 208, 154, + 105, 117, 100, 203, 213, 72, 17, 198, 104, 49, 29, 251, 18, 208, + 95, 236, 85, 49, 31, 120, 134, 207, 231, 236, 150, 23, 196, 29, + 194, 246, 235, 225, 48, 115, 56, 231, 114, 93, 206, 97, 69, 48, + 191, 25, 240, 211, 116, 33, 14, 182, 168, 97, 198, 104, 252, 250, + 213, 225, 117, 161, 105, 255, 217, 134, 29, 55, 154, 83, 33, 87, + 216, 112, 228, 75, 51, 165, 41, 207, 208, 208, 26, 69, 126, 180, + 224, 144, 138, 121, 194, 209, 131, 104, 181, 50, 1, 98, 91, 233, + 152, 93, 246, 237, 111, 162, 26, 35, 184, 217, 153, 212, 238, 255, + 109, 131, 246, 143, 130, 42, 148, 63, 129, 15, 14, 2, 93, 155, + 101, 113, 200, 17, 122, 127, 191, 14, 38, 164, 104, 81, 165, 26, + 242, 101, 116, 156, 228, 178, 57, 20, 122, 71, 93, 100, 5, 88, + 25, 16, 92, 38, 220, 198, 72, 230, 151, 116, 172, 103, 174, 243, + 8, 180, 166, 151, 237, 103, 133, 55, 123, 94, 241, 211, 219, 35, + 207, 158, 44, 213, 32, 168, 192, 49, 89, 37, 148, 214, 71, 175, + 239, 229, 76, 168, 9, 213, 112, 206, 92, 34, 241, 157, 72, 98, + 150, 51, 101, 178, 30, 214, 158, 89, 5, 91, 240, 155, 138, 62, + 146, 234, 142, 77, 201, 201, 135, 218, 211, 254, 36, 151, 100, 129, + 219, 172, 70, 36, 106, 54, 67, 117, 96, 95, 124, 193, 172, 217, + 213, 71, 105, 214, 146, 34, 87, 54, 252, 218, 222, 222, 148, 38, + 81, 254, 32, 195, 41, 30, 14, 239, 71, 147, 235, 93, 159, 19, + 147, 3, 166, 50, 78, 135, 212, 55, 133, 168, 228, 172, 27, 14, + 206, 15, 98, 165, 227, 179, 92, 11, 221, 105, 235, 162, 12, 80, + 36, 212, 205, 90, 176, 229, 46, 135, 252, 161, 32, 167, 207, 226, + 205, 191, 152, 69, 81, 105, 214, 245, 232, 128, 160, 190, 91, 254, + 179, 13, 244, 83, 162, 247, 153, 44, 140, 147, 211, 180, 249, 82, + 33, 137, 92, 10, 119, 61, 89, 207, 88, 59, 50, 171, 155, 99, + 210, 244, 115, 33, 180, 18, 154, 225, 62, 253, 91, 208, 208, 140, + 189, 217, 209, 70, 243, 4, 238, 117, 66, 98, 48, 152, 54, 255, + 128, 61, 247, 193, 88, 168, 125, 194, 90, 49, 209, 201, 40, 168, + 247, 79, 75, 244, 4, 15, 3, 106, 5, 80, 71, 160, 240, 42, + 17, 228, 135, 80, 247, 147, 74, 148, 135, 223, 145, 243, 121, 42, + 181, 221, 188, 106, 124, 252, 226, 50, 116, 98, 30, 33, 96, 13, + 199, 79, 219, 254, 78, 165, 113, 52, 122, 142, 231, 30, 145, 198, + 148, 215, 45, 176, 38, 61, 32, 72, 178, 54, 2, 211, 119, 133, + 107, 38, 105, 77, 230, 122, 6, 250, 254, 15, 148, 33, 249, 113, + 47, 41, 253, 24, 41, 7, 34, 118, 100, 58, 224, 96, 63, 184, + 191, 145, 32, 227, 22, 146, 131, 180, 9, 141, 25, 58, 188, 102, + 55, 74, 188, 222, 253, 195, 151, 214, 98, 161, 152, 239, 43, 125, + 194, 186, 36, 166, 111, 17, 10, 100, 58, 157, 133, 167, 121, 229, + 61, 22, 101, 8, 60, 42, 37, 217, 210, 87, 185, 251, 235, 102, + 210, 109, 99, 28, 9, 108, 162, 96, 137, 48, 117, 43, 80, 56, + 29, 178, 19, 73, 112, 164, 132, 28, 110, 157, 101, 234, 191, 247, + 123, 82, 229, 159, 123, 160, 136, 252, 230, 132, 101, 116, 26, 140, + 166, 157, 87, 204, 236, 151, 90, 107, 97, 141, 182, 124, 27, 52, + 73, 198, 34, 101, 45, 44, 133, 255, 56, 163, 6, 235, 77, 146, + 155, 213, 64, 49, 214, 33, 140, 195, 29, 39, 184, 9, 123, 169, + 32, 11, 59, 173, 189, 172, 8, 118, 19, 250, 228, 83, 239, 90, + 27, 20, 13, 64, 49, 224, 88, 17, 231, 148, 15, 23, 110, 199, + 65, 54, 87, 3, 253, 254, 68, 73, 175, 0, 207, 189, 74, 81, + 94, 56, 59, 234, 139, 65, 87, 83, 32, 161, 138, 132, 163, 134, + 228, 238, 29, 47, 166, 139, 168, 217, 247, 168, 165, 67, 211, 73, + 108, 96, 211, 4, 1, 23, 202, 160, 135, 231, 168, 243, 77, 137, + 241, 179, 230, 47, 77, 84, 192, 247, 202, 91, 212, 12, 130, 178, + 148, 131, 76, 175, 9, 146, 96, 42, 2, 155, 168, 103, 31, 15, + 92, 12, 155, 204, 166, 37, 155, 123, 8, 222, 199, 51, 250, 60, + 30, 109, 69, 98, 193, 31, 97, 214, 109, 102, 9, 39, 96, 111, + 148, 123, 26, 61, 163, 9, 242, 125, 116, 106, 184, 174, 66, 117, + 63, 242, 235, 238, 113, 23, 230, 79, 44, 121, 11, 148, 107, 181, + 36, 113, 89, 207, 246, 146, 43, 105, 166, 91, 23, 239, 248, 92, + 66, 167, 51, 10, 247, 232, 59, 109, 6, 197, 128, 251, 43, 85, + 100, 142, 214, 170, 198, 22, 120, 47, 243, 28, 154, 218, 84, 67, + 236, 185, 141, 169, 208, 63, 75, 22, 78, 230, 87, 144, 1, 252, + 237, 152, 191, 181, 44, 33, 231, 50, 163, 122, 68, 75, 242, 89, + 143, 171, 219, 102, 63, 196, 249, 80, 149, 53, 125, 80, 34, 246, + 234, 101, 17, 55, 199, 56, 19, 153, 97, 203, 37, 93, 84, 116, + 63, 171, 231, 109, 84, 160, 3, 24, 187, 6, 99, 249, 241, 181, + 234, 83, 152, 220, 169, 18, 189, 30, 59, 8, 143, 239, 237, 82, + 14, 220, 62, 89, 201, 174, 72, 176, 0, 144, 51, 77, 151, 232, + 233, 157, 242, 197, 234, 90, 51, 161, 45, 144, 30, 158, 79, 185, + 155, 123, 161, 20, 8, 76, 148, 63, 208, 81, 18, 250, 91, 112, + 154, 177, 227, 20, 245, 204, 66, 218, 11, 151, 37, 28, 29, 147, + 234, 24, 103, 168, 55, 144, 104, 3, 36, 252, 140, 165, 38, 199, + 234, 81, 245, 201, 2, 229, 29, 12, 230, 32, 248, 5, 244, 157, + 175, 111, 252, 224, 159, 116, 84, 31, 52, 182, 171, 204, 49, 126, + 41, 143, 177, 12, 236, 142, 156, 148, 200, 206, 192, 50, 243, 64, + 182, 112, 68, 200, 144, 100, 152, 237, 216, 119, 26, 11, 105, 237, + 144, 56, 158, 91, 10, 245, 30, 223, 18, 255, 5, 240, 202, 69, + 161, 184, 168, 114, 183, 202, 91, 46, 53, 95, 230, 126, 2, 156, + 103, 225, 99, 65, 86, 21, 156, 197, 179, 225, 240, 179, 197, 246, + 101, 184, 15, 2, 201, 13, 81, 79, 94, 140, 28, 124, 77, 221, + 63, 174, 68, 159, 178, 77, 68, 10, 140, 52, 66, 239, 43, 247, + 108, 63, 225, 193, 210, 107, 207, 211, 44, 69, 95, 81, 9, 106, + 5, 212, 240, 171, 117, 155, 100, 207, 46, 186, 101, 61, 120, 98, + 91, 84, 40, 50, 115, 138, 216, 20, 74, 33, 93, 49, 26, 217, + 143, 57, 43, 5, 147, 91, 147, 184, 90, 121, 168, 73, 164, 233, + 218, 110, 2, 80, 150, 41, 191, 205, 138, 177, 145, 6, 102, 229, + 41, 131, 187, 230, 91, 201, 172, 78, 43, 203, 109, 28, 91, 43, + 250, 138, 134, 134, 228, 177, 41, 50, 96, 98, 162, 189, 229, 107, + 4, 99, 78, 107, 52, 0, 153, 183, 166, 41, 0, 25, 132, 127, + 160, 185, 226, 195, 144, 121, 80, 239, 142, 102, 175, 95, 14, 175, + 82, 98, 186, 153, 153, 214, 137, 145, 69, 154, 242, 10, 9, 92, + 7, 239, 209, 76, 210, 8, 129, 47, 44, 205, 65, 105, 186, 84, + 130, 203, 15, 149, 16, 43, 184, 4, 230, 18, 30, 18, 209, 146, + 169, 103, 157, 115, 202, 14, 123, 118, 84, 201, 61, 73, 173, 117, + 194, 211, 198, 182, 148, 231, 27, 175, 17, 24, 0, 20, 229, 240, + 76, 152, 235, 90, 192, 129, 46, 91, 31, 89, 223, 63, 190, 47, + 144, 6, 19, 136, 10, 169, 187, 162, 86, 253, 247, 32, 195, 39, + 39, 45, 170, 30, 99, 84, 17, 174, 77, 168, 40, 247, 109, 41, + 173, 8, 74, 185, 3, 127, 118, 175, 204, 176, 168, 41, 92, 81, + 32, 119, 228, 3, 97, 75, 26, 86, 9, 82, 125, 5, 107, 34, + 201, 48, 8, 180, 217, 17, 3, 166, 80, 46, 151, 116, 36, 208, + 115, 176, 36, 228, 180, 123, 166, 4, 192, 147, 98, 177, 54, 162, + 67, 39, 137, 143, 63, 162, 127, 157, 12, 36, 92, 124, 75, 167, + 60, 249, 142, 133, 98, 40, 133, 195, 139, 191, 143, 244, 230, 56, + 42, 132, 96, 30, 5, 200, 242, 31, 161, 190, 162, 234, 123, 25, + 248, 20, 7, 122, 220, 220, 35, 189, 236, 219, 246, 78, 65, 158, + 184, 140, 103, 39, 185, 33, 75, 199, 114, 211, 70, 61, 236, 37, + 73, 58, 15, 132, 155, 141, 160, 243, 110, 23, 158, 145, 32, 46, + 94, 46, 106, 60, 104, 65, 204, 246, 210, 97, 247, 116, 235, 200, + 59, 41, 13, 65, 174, 107, 40, 201, 112, 26, 239, 16, 148, 240, + 238, 65, 113, 32, 185, 96, 201, 17, 242, 135, 82, 164, 196, 2, + 4, 21, 154, 4, 200, 122, 60, 237, 98, 79, 153, 23, 177, 233, + 9, 233, 148, 17, 77, 89, 5, 229, 167, 165, 113, 34, 64, 16, + 68, 255, 181, 7, 254, 62, 40, 173, 79, 73, 255, 219, 206, 230, + 208, 125, 189, 179, 253, 129, 95, 230, 166, 198, 239, 145, 142, 85, + 27, 66, 70, 115, 122, 176, 232, 21, 224, 126, 53, 245, 151, 127, + 140, 227, 10, 143, 147, 53, 63, 206, 156, 233, 105, 225, 118, 89, + 184, 159, 204, 117, 7, 193, 24, 166, 58, 24, 216, 217, 36, 76, + 91, 81, 185, 157, 56, 134, 214, 57, 112, 15, 73, 55, 147, 66, + 158, 159, 248, 80, 148, 147, 174, 132, 71, 52, 94, 61, 187, 203, + 113, 122, 24, 169, 105, 113, 33, 132, 56, 56, 215, 58, 204, 193, + 245, 211, 64, 111, 173, 242, 7, 88, 48, 40, 45, 178, 129, 240, + 49, 93, 67, 45, 238, 197, 149, 4, 117, 12, 84, 6, 169, 141, + 115, 172, 20, 108, 57, 206, 182, 194, 70, 111, 10, 29, 131, 77, + 173, 78, 184, 242, 68, 19, 62, 159, 25, 175, 196, 255, 131, 1, + 184, 131, 3, 172, 215, 33, 59, 144, 243, 228, 44, 160, 211, 192, + 43, 42, 99, 123, 97, 182, 75, 249, 122, 226, 101, 121, 43, 3, + 255, 242, 106, 181, 165, 8, 123, 99, 174, 91, 254, 160, 80, 110, + 179, 48, 193, 65, 201, 93, 228, 227, 106, 48, 185, 96, 188, 82, + 158, 69, 177, 254, 117, 146, 82, 172, 37, 109, 103, 216, 74, 66, + 49, 30, 22, 231, 106, 184, 18, 110, 144, 186, 234, 235, 93, 177, + 225, 129, 113, 143, 172, 199, 226, 54, 79, 122, 31, 110, 177, 224, + 118, 6, 54, 46, 232, 239, 182, 103, 167, 82, 153, 128, 1, 215, + 162, 134, 87, 198, 226, 92, 99, 42, 217, 69, 158, 119, 15, 94, + 5, 236, 205, 166, 16, 238, 193, 137, 54, 27, 87, 129, 152, 254, + 183, 225, 27, 28, 207, 199, 100, 70, 112, 251, 97, 122, 145, 50, + 255, 84, 224, 229, 198, 43, 160, 141, 142, 249, 100, 177, 222, 146, + 1, 101, 13, 215, 121, 56, 247, 134, 21, 107, 118, 175, 11, 60, + 96, 152, 194, 62, 17, 122, 53, 249, 238, 245, 101, 108, 203, 87, + 112, 63, 109, 59, 157, 30, 210, 113, 11, 103, 212, 136, 82, 117, + 225, 82, 244, 101, 124, 165, 159, 125, 133, 13, 216, 229, 39, 63, + 236, 33, 57, 23, 0, 68, 182, 154, 35, 250, 179, 94, 99, 68, + 96, 79, 164, 235, 254, 121, 243, 53, 216, 6, 181, 190, 219, 165, + 70, 122, 64, 142, 30, 226, 21, 58, 44, 68, 142, 171, 81, 139, + 53, 42, 235, 240, 204, 126, 40, 167, 13, 106, 0, 5, 253, 240, + 147, 141, 114, 115, 246, 165, 48, 217, 6, 222, 119, 223, 214, 132, + 82, 157, 215, 236, 168, 31, 16, 84, 118, 70, 38, 11, 62, 128, + 180, 106, 46, 150, 132, 231, 177, 184, 206, 218, 74, 157, 254, 194, + 200, 58, 219, 139, 93, 243, 40, 157, 82, 100, 134, 114, 232, 5, + 97, 112, 254, 191, 242, 95, 137, 69, 94, 79, 173, 91, 172, 113, + 178, 158, 15, 14, 210, 144, 115, 252, 129, 142, 34, 32, 250, 195, + 141, 62, 99, 98, 127, 212, 248, 184, 36, 110, 203, 201, 178, 112, + 229, 111, 232, 7, 133, 192, 196, 217, 201, 166, 115, 42, 185, 126, + 158, 226, 150, 55, 167, 69, 251, 121, 16, 61, 158, 175, 5, 22, + 213, 197, 122, 255, 96, 51, 50, 233, 137, 178, 110, 13, 70, 241, + 235, 95, 124, 207, 213, 103, 118, 39, 65, 68, 16, 204, 149, 163, + 149, 104, 210, 170, 142, 221, 88, 21, 200, 243, 228, 199, 229, 92, + 132, 75, 190, 193, 205, 102, 167, 8, 27, 63, 45, 3, 144, 249, + 174, 14, 114, 230, 238, 43, 50, 19, 49, 161, 154, 86, 138, 179, + 38, 198, 22, 9, 156, 126, 60, 255, 233, 53, 183, 190, 218, 124, + 231, 230, 24, 170, 178, 93, 153, 121, 67, 180, 123, 88, 84, 223, + 170, 168, 50, 217, 74, 73, 181, 66, 109, 114, 2, 18, 26, 114, + 160, 8, 150, 34, 38, 154, 244, 141, 152, 254, 186, 111, 89, 38, + 154, 99, 41, 58, 148, 93, 33, 171, 72, 144, 77, 246, 93, 2, + 159, 206, 7, 244, 174, 140, 159, 3, 190, 255, 237, 202, 65, 96, + 162, 25, 245, 96, 252, 166, 92, 144, 108, 70, 239, 158, 21, 176, + 118, 43, 255, 70, 179, 20, 12, 141, 192, 196, 160, 228, 167, 109, + 176, 250, 243, 240, 239, 232, 73, 173, 148, 165, 249, 245, 227, 14, + 89, 71, 52, 124, 199, 60, 114, 243, 88, 127, 89, 231, 11, 111, + 80, 31, 253, 62, 56, 78, 166, 66, 63, 196, 103, 10, 242, 26, + 84, 103, 30, 46, 245, 46, 102, 50, 20, 70, 237, 34, 236, 9, + 242, 221, 210, 143, 239, 114, 57, 73, 103, 242, 54, 108, 172, 57, + 168, 126, 138, 48, 244, 41, 22, 60, 158, 121, 33, 109, 74, 168, + 251, 118, 86, 50, 184, 221, 60, 238, 165, 117, 116, 166, 210, 19, + 163, 99, 28, 67, 114, 183, 55, 161, 68, 22, 7, 124, 67, 161, + 75, 230, 151, 237, 118, 25, 251, 2, 96, 216, 9, 186, 12, 252, + 75, 140, 2, 8, 13, 95, 117, 25, 216, 227, 25, 219, 247, 52, + 20, 53, 207, 175, 176, 154, 149, 143, 0, 67, 114, 42, 101, 60, + 3, 226, 107, 244, 244, 94, 240, 243, 248, 122, 2, 61, 141, 184, + 241, 172, 92, 10, 112, 133, 75, 92, 3, 147, 168, 72, 39, 80, + 194, 152, 51, 233, 252, 21, 98, 78, 5, 134, 93, 254, 39, 207, + 30, 43, 8, 140, 197, 106, 27, 136, 61, 246, 204, 155, 80, 32, + 161, 247, 211, 237, 10, 28, 24, 231, 87, 82, 52, 216, 81, 155, + 141, 108, 221, 169, 92, 128, 221, 31, 116, 38, 31, 95, 142, 117, + 243, 107, 181, 143, 134, 189, 108, 207, 80, 44, 56, 199, 73, 219, + 23, 163, 97, 157, 37, 69, 230, 179, 137, 98, 19, 211, 250, 146, + 197, 170, 61, 172, 193, 80, 53, 56, 50, 109, 214, 250, 55, 149, + 96, 188, 37, 6, 63, 191, 90, 41, 103, 222, 230, 194, 167, 48, + 112, 180, 48, 192, 194, 198, 5, 80, 149, 4, 226, 253, 41, 218, + 37, 236, 39, 145, 8, 12, 179, 61, 91, 40, 76, 68, 134, 86, + 77, 64, 205, 249, 140, 156, 212, 53, 154, 115, 63, 97, 159, 124, + 94, 71, 108, 71, 182, 121, 221, 105, 98, 231, 101, 109, 198, 70, + 51, 220, 108, 64, 204, 150, 137, 117, 27, 81, 199, 14, 148, 219, + 158, 63, 232, 161, 39, 130, 38, 2, 105, 6, 136, 245, 14, 175, + 244, 230, 73, 181, 18, 79, 55, 207, 233, 58, 80, 34, 23, 64, + 61, 22, 12, 15, 232, 154, 99, 140, 107, 252, 215, 89, 4, 228, + 64, 55, 68, 168, 71, 233, 148, 18, 226, 79, 129, 118, 109, 130, + 4, 15, 85, 104, 161, 147, 78, 135, 225, 192, 138, 114, 230, 230, + 225, 118, 150, 169, 8, 243, 241, 204, 93, 222, 178, 131, 97, 145, + 211, 207, 233, 45, 38, 237, 93, 7, 215, 12, 27, 240, 142, 149, + 196, 147, 20, 236, 142, 77, 241, 249, 132, 218, 109, 182, 250, 241, + 125, 136, 149, 19, 196, 198, 4, 222, 72, 157, 222, 53, 185, 210, + 24, 100, 19, 146, 210, 122, 39, 173, 13, 183, 138, 26, 70, 43, + 235, 225, 47, 88, 56, 92, 1, 197, 236, 98, 210, 250, 35, 159, + 71, 198, 20, 217, 162, 182, 13, 72, 30, 152, 170, 173, 101, 40, + 78, 109, 126, 153, 40, 182, 62, 9, 217, 229, 206, 124, 62, 71, + 62, 18, 85, 173, 171, 251, 38, 234, 163, 214, 242, 207, 135, 48, + 78, 192, 125, 194, 164, 30, 162, 39, 5, 211, 160, 82, 66, 209, + 218, 8, 123, 104, 69, 92, 80, 241, 53, 209, 44, 10, 23, 147, + 91, 31, 71, 207, 240, 222, 243, 18, 4, 0, 248, 118, 2, 78, + 197, 120, 38, 42, 5, 248, 27, 245, 162, 73, 254, 254, 130, 106, + 164, 68, 188, 118, 180, 200, 6, 96, 42, 183, 153, 149, 176, 14, + 134, 78, 185, 34, 146, 203, 105, 207, 35, 56, 26, 176, 35, 17, + 81, 207, 105, 243, 40, 7, 118, 116, 209, 219, 247, 33, 228, 91, + 73, 193, 32, 146, 174, 100, 146, 40, 107, 44, 135, 127, 31, 93, + 142, 243, 128, 236, 47, 13, 115, 66, 35, 163, 236, 156, 250, 2, + 113, 60, 103, 106, 202, 42, 193, 12, 212, 201, 253, 135, 207, 252, + 74, 111, 123, 247, 5, 72, 41, 255, 234, 174, 187, 82, 175, 168, + 65, 68, 110, 14, 205, 79, 58, 80, 190, 105, 242, 176, 0, 187, + 202, 153, 248, 137, 237, 28, 135, 111, 80, 164, 118, 151, 93, 152, + 114, 77, 77, 3, 135, 25, 19, 214, 170, 94, 167, 206, 162, 50, + 1, 149, 21, 185, 222, 127, 240, 129, 137, 232, 213, 107, 199, 131, + 218, 92, 189, 63, 29, 6, 59, 230, 88, 168, 200, 9, 38, 85, + 222, 66, 35, 138, 230, 155, 176, 183, 230, 149, 236, 47, 74, 101, + 16, 53, 110, 140, 74, 27, 13, 237, 174, 127, 67, 231, 187, 235, + 153, 12, 153, 122, 216, 236, 140, 89, 131, 66, 129, 158, 192, 227, + 226, 159, 176, 62, 232, 157, 44, 91, 191, 142, 198, 8, 29, 75, + 40, 234, 106, 141, 94, 85, 165, 45, 252, 72, 169, 108, 149, 25, + 180, 218, 97, 190, 20, 161, 52, 114, 111, 4, 174, 23, 38, 6, + 11, 182, 2, 124, 232, 14, 50, 184, 99, 250, 38, 128, 245, 210, + 142, 177, 17, 251, 223, 10, 174, 49, 89, 164, 115, 49, 11, 207, + 11, 233, 91, 246, 77, 254, 93, 152, 186, 24, 195, 19, 50, 50, + 9, 31, 140, 31, 79, 55, 127, 91, 158, 30, 112, 245, 224, 222, + 200, 197, 178, 200, 14, 18, 151, 214, 171, 128, 222, 101, 117, 144, + 48, 42, 102, 22, 241, 61, 208, 94, 250, 245, 211, 246, 75, 46, + 226, 126, 111, 108, 30, 43, 110, 109, 55, 96, 63, 40, 128, 246, + 0, 30, 221, 208, 52, 89, 19, 117, 207, 16, 84, 168, 164, 16, + 89, 129, 86, 240, 49, 67, 209, 233, 195, 16, 47, 54, 1, 228, + 220, 140, 175, 87, 71, 33, 246, 85, 202, 127, 125, 130, 175, 233, + 53, 174, 49, 182, 62, 238, 236, 19, 13, 40, 177, 94, 164, 70, + 255, 21, 228, 28, 99, 119, 147, 226, 255, 19, 46, 135, 254, 48, + 207, 151, 166, 162, 133, 20, 124, 62, 244, 25, 5, 127, 159, 64, + 87, 160, 180, 222, 109, 127, 111, 85, 190, 40, 184, 230, 59, 89, + 141, 250, 189, 120, 184, 136, 97, 186, 86, 235, 103, 55, 130, 225, + 240, 110, 200, 73, 158, 79, 7, 40, 118, 181, 125, 32, 134, 67, + 133, 230, 220, 183, 104, 105, 201, 173, 109, 105, 193, 60, 16, 26, + 37, 32, 84, 41, 55, 195, 144, 116, 121, 48, 132, 179, 206, 150, + 145, 135, 152, 149, 107, 78, 15, 118, 112, 51, 145, 104, 128, 4, + 189, 247, 76, 109, 22, 86, 67, 40, 87, 206, 69, 228, 205, 102, + 105, 61, 51, 48, 103, 111, 14, 236, 35, 46, 93, 246, 133, 143, + 18, 249, 159, 156, 95, 121, 89, 11, 164, 106, 208, 106, 7, 84, + 197, 3, 129, 132, 8, 137, 39, 179, 49, 98, 112, 92, 136, 113, + 119, 213, 37, 38, 99, 36, 210, 132, 148, 114, 57, 249, 17, 148, + 125, 107, 37, 111, 18, 111, 40, 195, 94, 10, 245, 72, 244, 96, + 164, 158, 106, 246, 73, 183, 114, 170, 160, 109, 58, 111, 90, 127, + 70, 14, 177, 80, 66, 71, 63, 143, 215, 29, 54, 81, 220, 46, + 207, 195, 20, 44, 76, 221, 44, 91, 16, 99, 201, 62, 128, 156, + 214, 12, 135, 68, 47, 34, 136, 106, 169, 215, 127, 214, 255, 255, + 107, 111, 35, 220, 208, 28, 141, 236, 93, 142, 190, 119, 130, 65, + 122, 250, 193, 55, 203, 229, 241, 38, 4, 174, 86, 210, 197, 252, + 51, 18, 44, 181, 217, 204, 222, 217, 160, 145, 163, 122, 212, 150, + 221, 242, 34, 106, 188, 74, 218, 227, 123, 204, 40, 171, 181, 136, + 57, 116, 213, 63, 192, 26, 63, 12, 140, 230, 42, 124, 26, 176, + 175, 190, 68, 181, 241, 111, 235, 212, 12, 158, 106, 75, 171, 92, + 231, 74, 123, 20, 150, 155, 137, 6, 80, 26, 231, 181, 39, 11, + 241, 64, 172, 46, 9, 24, 131, 250, 69, 138, 5, 55, 14, 164, + 235, 142, 29, 226, 91, 32, 243, 196, 86, 27, 188, 174, 140, 217, + 169, 14, 62, 108, 217, 252, 144, 128, 206, 223, 222, 52, 1, 128, + 146, 231, 169, 174, 159, 202, 40, 127, 64, 238, 211, 246, 111, 43, + 173, 60, 181, 25, 20, 91, 67, 121, 233, 84, 111, 95, 196, 66, + 28, 217, 25, 28, 108, 19, 242, 139, 245, 238, 197, 97, 38, 86, + 221, 197, 43, 208, 87, 232, 25, 142, 34, 159, 136, 209, 97, 43, + 87, 86, 134, 219, 138, 100, 62, 11, 40, 129, 44, 41, 115, 62, + 210, 178, 120, 203, 242, 254, 223, 210, 54, 159, 10, 176, 90, 214, + 128, 178, 202, 22, 101, 146, 53, 175, 68, 230, 67, 10, 168, 89, + 189, 103, 247, 104, 197, 209, 57, 185, 27, 244, 20, 254, 62, 9, + 209, 77, 239, 251, 26, 155, 187, 7, 149, 246, 157, 47, 175, 203, + 224, 247, 145, 239, 213, 240, 97, 79, 183, 22, 17, 150, 227, 66, + 31, 127, 238, 153, 255, 41, 52, 130, 38, 73, 118, 1, 226, 165, + 224, 100, 223, 236, 141, 198, 235, 33, 240, 91, 201, 212, 134, 123, + 217, 213, 140, 146, 201, 190, 157, 252, 109, 174, 24, 34, 9, 49, + 229, 27, 57, 151, 49, 140, 99, 246, 235, 142, 127, 20, 70, 64, + 116, 126, 249, 178, 17, 152, 67, 201, 162, 150, 109, 55, 185, 184, + 100, 90, 214, 8, 133, 157, 30, 100, 139, 122, 121, 0, 211, 252, + 86, 48, 199, 75, 231, 148, 118, 54, 243, 25, 208, 106, 68, 20, + 80, 133, 69, 194, 29, 86, 56, 12, 151, 92, 241, 98, 249, 40, + 112, 248, 235, 169, 248, 236, 84, 62, 147, 161, 66, 29, 201, 167, + 236, 230, 123, 47, 202, 69, 188, 133, 121, 36, 254, 50, 217, 109, + 17, 67, 246, 19, 10, 124, 190, 162, 56, 105, 128, 254, 196, 242, + 13, 152, 44, 233, 68, 38, 187, 2, 244, 46, 122, 121, 199, 197, + 84, 66, 146, 68, 151, 7, 216, 201, 223, 136, 9, 132, 243, 141, + 14, 10, 65, 234, 13, 221, 90, 70, 246, 156, 183, 156, 210, 73, + 101, 118, 229, 43, 114, 237, 98, 162, 22, 196, 183, 93, 202, 58, + 220, 1, 25, 151, 60, 207, 82, 7, 233, 114, 116, 144, 255, 71, + 241, 90, 244, 116, 92, 111, 108, 13, 98, 25, 137, 24, 241, 187, + 82, 140, 170, 39, 81, 228, 185, 164, 143, 101, 46, 204, 129, 166, + 164, 38, 34, 100, 140, 55, 246, 6, 223, 182, 53, 199, 245, 109, + 76, 209, 112, 120, 42, 99, 58, 51, 85, 163, 185, 148, 209, 237, + 240, 75, 239, 102, 102, 11, 78, 215, 130, 23, 178, 33, 207, 63, + 247, 245, 243, 101, 230, 236, 251, 145, 25, 114, 222, 229, 117, 88, + 32, 139, 231, 27, 163, 225, 255, 247, 175, 40, 71, 182, 193, 28, + 236, 76, 55, 154, 82, 12, 42, 110, 135, 122, 33, 227, 242, 13, + 157, 35, 119, 73, 33, 76, 156, 120, 27, 74, 192, 92, 172, 135, + 5, 29, 7, 167, 61, 101, 73, 249, 66, 82, 223, 198, 182, 207, + 194, 183, 124, 228, 157, 30, 108, 128, 70, 186, 208, 16, 92, 8, + 137, 223, 150, 47, 228, 211, 34, 192, 228, 61, 82, 176, 93, 165, + 198, 100, 190, 137, 173, 48, 203, 117, 58, 70, 178, 198, 49, 40, + 61, 17, 171, 130, 127, 192, 45, 224, 184, 83, 131, 171, 18, 134, + 201, 90, 147, 218, 203, 150, 43, 221, 86, 206, 10, 9, 250, 20, + 147, 157, 173, 130, 30, 221, 228, 221, 65, 11, 78, 125, 204, 101, + 237, 209, 22, 187, 45, 154, 113, 146, 14, 171, 199, 224, 234, 51, + 201, 108, 25, 7, 38, 89, 47, 66, 61, 231, 206, 52, 150, 29, + 118, 27, 143, 162, 74, 153, 180, 216, 240, 94, 215, 29, 185, 221, + 107, 127, 172, 251, 115, 41, 25, 26, 97, 4, 152, 22, 192, 25, + 153, 64, 79, 30, 192, 152, 74, 185, 252, 96, 43, 173, 14, 34, + 119, 63, 62, 70, 52, 180, 35, 136, 118, 4, 132, 0, 147, 243, + 73, 45, 95, 209, 10, 143, 69, 11, 178, 17, 6, 254, 93, 165, + 89, 50, 198, 129, 157, 163, 50, 208, 25, 180, 170, 145, 46, 27, + 13, 17, 241, 155, 243, 121, 244, 34, 166, 175, 230, 30, 75, 195, + 242, 230, 148, 143, 104, 129, 58, 38, 13, 165, 248, 128, 4, 20, + 57, 15, 200, 163, 255, 200, 127, 166, 142, 176, 192, 10, 244, 150, + 251, 255, 252, 72, 204, 89, 237, 221, 19, 125, 248, 66, 221, 118, + 235, 237, 129, 157, 61, 232, 39, 243, 120, 234, 242, 200, 179, 252, + 223, 72, 3, 116, 133, 81, 219, 23, 142, 71, 24, 177, 49, 62, + 74, 39, 26, 251, 37, 181, 158, 230, 98, 117, 52, 3, 167, 54, + 3, 166, 8, 2, 92, 230, 1, 186, 194, 23, 252, 175, 6, 242, + 4, 52, 12, 202, 155, 114, 103, 207, 142, 209, 88, 67, 41, 41, + 91, 166, 220, 179, 182, 143, 205, 82, 241, 169, 128, 53, 90, 34, + 67, 103, 252, 250, 180, 152, 228, 59, 222, 159, 9, 22, 78, 129, + 11, 26, 66, 91, 111, 135, 7, 53, 117, 246, 218, 53, 221, 134, + 51, 138, 171, 240, 54, 18, 184, 134, 222, 127, 112, 243, 159, 54, + 204, 23, 161, 70, 111, 74, 92, 148, 83, 197, 215, 184, 66, 227, + 20, 99, 146, 84, 245, 240, 5, 123, 140, 248, 108, 167, 140, 137, + 78, 63, 117, 43, 225, 85, 69, 143, 165, 133, 165, 118, 1, 43, + 13, 157, 50, 193, 96, 140, 15, 188, 129, 219, 99, 249, 85, 123, + 84, 129, 101, 24, 215, 206, 215, 140, 118, 72, 125, 123, 49, 224, + 254, 87, 143, 21, 99, 105, 72, 126, 154, 13, 117, 145, 251, 237, + 60, 41, 164, 60, 64, 105, 135, 234, 19, 80, 154, 228, 35, 126, + 199, 251, 0, 124, 211, 209, 37, 74, 95, 171, 192, 187, 33, 226, + 50, 218, 95, 142, 189, 145, 63, 123, 218, 66, 228, 150, 149, 73, + 60, 49, 105, 153, 193, 177, 44, 168, 121, 151, 47, 190, 93, 138, + 6, 109, 253, 147, 97, 118, 141, 230, 198, 208, 111, 64, 254, 196, + 48, 93, 127, 35, 40, 162, 13, 13, 133, 49, 255, 232, 234, 52, + 123, 240, 57, 15, 185, 162, 204, 174, 140, 70, 139, 103, 227, 117, + 19, 207, 123, 0, 194, 53, 161, 10, 74, 148, 14, 170, 226, 68, + 157, 245, 100, 46, 83, 53, 70, 21, 251, 176, 105, 3, 66, 241, + 229, 7, 175, 48, 69, 24, 231, 48, 88, 108, 123, 90, 25, 200, + 214, 237, 11, 1, 76, 28, 138, 193, 44, 59, 90, 29, 77, 177, + 128, 62, 60, 80, 175, 7, 71, 92, 254, 67, 50, 95, 35, 16, + 124, 72, 210, 11, 226, 112, 174, 141, 145, 250, 212, 109, 217, 138, + 56, 187, 168, 207, 1, 194, 14, 54, 28, 194, 76, 33, 83, 85, + 51, 21, 30, 150, 19, 103, 10, 49, 23, 130, 99, 251, 88, 243, + 59, 191, 202, 180, 27, 199, 164, 101, 144, 240, 0, 215, 236, 72, + 148, 186, 207, 202, 13, 88, 174, 139, 86, 170, 131, 17, 199, 74, + 24, 192, 101, 160, 174, 250, 0, 176, 235, 62, 48, 38, 130, 23, + 205, 111, 165, 17, 173, 246, 242, 255, 129, 252, 93, 116, 245, 64, + 5, 64, 139, 12, 71, 247, 167, 181, 129, 204, 147, 154, 20, 152, + 70, 154, 250, 54, 180, 95, 81, 175, 97, 189, 185, 48, 192, 31, + 34, 143, 46, 158, 149, 172, 114, 104, 154, 141, 10, 146, 135, 10, + 156, 240, 67, 4, 2, 100, 40, 4, 29, 31, 176, 175, 50, 91, + 145, 95, 231, 65, 249, 241, 224, 19, 60, 9, 123, 181, 94, 135, + 234, 93, 31, 145, 125, 97, 120, 13, 99, 251, 231, 229, 197, 201, + 150, 38, 79, 245, 88, 211, 17, 98, 144, 56, 135, 207, 146, 146, + 232, 89, 103, 227, 162, 253, 186, 128, 236, 68, 114, 84, 38, 96, + 97, 220, 215, 176, 226, 215, 102, 18, 190, 152, 42, 139, 27, 210, + 212, 170, 227, 165, 246, 136, 197, 253, 226, 25, 52, 15, 111, 28, + 3, 247, 123, 46, 231, 32, 100, 182, 141, 142, 10, 226, 226, 2, + 185, 236, 10, 180, 83, 36, 242, 182, 115, 50, 38, 7, 44, 37, + 172, 209, 1, 18, 110, 85, 252, 253, 166, 147, 84, 219, 222, 78, + 101, 236, 106, 202, 151, 76, 13, 176, 154, 42, 141, 167, 180, 27, + 88, 35, 80, 140, 87, 126, 221, 210, 84, 254, 185, 81, 7, 44, + 196, 25, 49, 143, 254, 173, 195, 215, 239, 152, 119, 133, 83, 107, + 141, 200, 41, 64, 24, 83, 108, 0, 244, 21, 18, 182, 113, 148, + 20, 14, 25, 199, 4, 136, 144, 23, 46, 22, 22, 72, 247, 51, + 210, 248, 15, 140, 203, 131, 165, 52, 139, 224, 49, 97, 175, 231, + 13, 142, 233, 40, 199, 8, 238, 156, 127, 22, 9, 81, 31, 23, + 145, 242, 117, 96, 243, 8, 181, 198, 113, 30, 21, 255, 118, 207, + 140, 165, 190, 61, 142, 57, 77, 0, 153, 54, 57, 126, 201, 78, + 158, 100, 191, 109, 196, 15, 217, 76, 97, 6, 66, 5, 75, 15, + 235, 238, 185, 79, 145, 179, 143, 241, 227, 80, 89, 3, 58, 132, + 124, 85, 25, 190, 59, 187, 167, 115, 113, 197, 23, 95, 204, 210, + 144, 224, 5, 73, 63, 34, 10, 173, 86, 222, 18, 74, 59, 135, + 186, 111, 7, 188, 104, 1, 119, 153, 149, 234, 8, 174, 223, 172, + 213, 195, 89, 100, 3, 26, 221, 149, 149, 223, 119, 147, 20, 105, + 25, 129, 178, 226, 83, 54, 217, 186, 118, 73, 80, 114, 253, 248, + 37, 55, 19, 237, 188, 105, 35, 17, 97, 126, 226, 80, 125, 214, + 238, 139, 183, 3, 139, 36, 248, 44, 2, 24, 30, 137, 44, 25, + 72, 70, 51, 220, 79, 82, 157, 107, 34, 249, 111, 227, 125, 88, + 189, 189, 140, 114, 243, 40, 44, 164, 216, 106, 184, 17, 125, 5, + 240, 43, 110, 241, 183, 125, 21, 146, 44, 153, 207, 136, 174, 173, + 205, 91, 110, 11, 239, 251, 161, 141, 15, 225, 130, 217, 197, 164, + 31, 221, 82, 101, 154, 18, 52, 249, 155, 121, 207, 193, 195, 138, + 67, 90, 220, 15, 110, 233, 166, 24, 240, 107, 19, 138, 104, 133, + 157, 180, 5, 208, 48, 152, 154, 59, 101, 3, 254, 179, 69, 195, + 58, 185, 69, 251, 65, 107, 90, 128, 93, 238, 41, 36, 164, 10, + 73, 133, 207, 36, 237, 210, 115, 123, 147, 130, 22, 198, 67, 32, + 119, 129, 7, 78, 99, 166, 219, 229, 48, 135, 254, 175, 198, 59, + 129, 229, 101, 207, 195, 58, 244, 90, 222, 158, 14, 178, 237, 144, + 118, 227, 159, 82, 3, 44, 57, 92, 246, 152, 3, 183, 77, 71, + 39, 142, 82, 200, 122, 240, 71, 125, 12, 64, 171, 60, 56, 15, + 170, 85, 188, 188, 77, 71, 192, 85, 50, 83, 136, 227, 74, 195, + 31, 105, 153, 158, 171, 102, 90, 32, 241, 1, 201, 144, 225, 61, + 101, 36, 221, 137, 234, 228, 161, 150, 162, 251, 146, 114, 26, 215, + 121, 69, 178, 96, 150, 105, 223, 232, 161, 249, 221, 199, 135, 74, + 178, 236, 191, 16, 248, 171, 178, 74, 119, 155, 247, 226, 114, 17, + 108, 252, 142, 151, 161, 176, 137, 225, 110, 29, 124, 149, 49, 231, + 100, 237, 105, 165, 126, 191, 33, 45, 69, 69, 60, 37, 125, 238, + 194, 187, 161, 22, 27, 222, 68, 15, 142, 207, 237, 173, 68, 137, + 116, 207, 1, 108, 50, 75, 9, 143, 195, 127, 128, 56, 135, 229, + 34, 170, 67, 100, 146, 243, 166, 197, 210, 30, 185, 207, 201, 193, + 90, 102, 26, 100, 195, 216, 133, 178, 66, 29, 238, 25, 140, 226, + 0, 96, 18, 243, 91, 245, 154, 75, 172, 18, 49, 70, 24, 221, + 86, 86, 38, 224, 55, 231, 128, 103, 75, 222, 141, 179, 21, 175, + 11, 4, 225, 84, 198, 36, 123, 5, 196, 29, 51, 35, 226, 32, + 214, 198, 32, 128, 68, 155, 64, 130, 68, 236, 11, 96, 7, 247, + 198, 152, 9, 106, 202, 237, 50, 104, 72, 162, 62, 100, 65, 127, + 1, 218, 127, 252, 39, 118, 91, 29, 133, 130, 195, 242, 130, 147, + 196, 32, 227, 49, 200, 72, 95, 166, 74, 60, 164, 45, 79, 130, + 201, 61, 26, 172, 61, 81, 52, 221, 104, 204, 87, 14, 162, 62, + 26, 142, 158, 185, 242, 80, 33, 154, 155, 26, 63, 241, 1, 76, + 8, 251, 174, 93, 40, 98, 38, 35, 105, 46, 59, 83, 94, 245, + 104, 151, 232, 124, 81, 198, 31, 12, 238, 242, 165, 47, 131, 219, + 91, 58, 155, 47, 109, 51, 130, 176, 176, 62, 194, 78, 1, 179, + 34, 51, 19, 229, 194, 112, 12, 43, 102, 220, 240, 58, 60, 187, + 199, 9, 241, 26, 9, 136, 210, 211, 194, 127, 153, 34, 8, 164, + 120, 126, 19, 80, 234, 56, 40, 176, 120, 158, 135, 191, 202, 56, + 135, 82, 200, 206, 236, 60, 172, 240, 162, 7, 56, 83, 194, 74, + 103, 20, 245, 202, 75, 7, 30, 59, 221, 247, 254, 48, 117, 232, + 76, 174, 88, 151, 109, 219, 26, 118, 160, 103, 175, 191, 150, 176, + 184, 183, 211, 125, 48, 80, 144, 219, 11, 69, 171, 125, 185, 198, + 4, 59, 239, 241, 102, 154, 67, 252, 205, 49, 155, 230, 98, 87, + 117, 196, 67, 134, 90, 43, 40, 68, 107, 123, 143, 46, 133, 121, + 139, 243, 98, 121, 225, 93, 197, 99, 42, 112, 251, 13, 53, 162, + 62, 178, 104, 28, 47, 25, 10, 239, 6, 232, 30, 111, 176, 124, + 235, 117, 197, 13, 145, 161, 100, 175, 53, 128, 96, 134, 234, 118, + 83, 103, 29, 250, 4, 184, 16, 195, 52, 102, 44, 115, 15, 206, + 162, 184, 122, 105, 99, 166, 210, 108, 80, 139, 237, 172, 121, 96, + 40, 57, 22, 53, 75, 106, 51, 126, 17, 9, 150, 208, 144, 128, + 114, 182, 127, 65, 51, 91, 200, 124, 107, 44, 169, 62, 45, 167, + 57, 155, 198, 1, 1, 243, 184, 121, 200, 2, 185, 125, 187, 129, + 168, 163, 255, 101, 186, 232, 81, 53, 252, 16, 233, 168, 177, 243, + 229, 55, 43, 143, 247, 45, 238, 148, 235, 152, 29, 154, 222, 212, + 128, 188, 160, 190, 57, 123, 159, 3, 249, 49, 92, 198, 68, 230, + 74, 245, 115, 242, 244, 64, 229, 4, 140, 22, 131, 177, 55, 63, + 243, 154, 184, 15, 190, 212, 100, 244, 68, 122, 186, 17, 20, 159, + 115, 65, 153, 20, 71, 110, 44, 21, 38, 22, 159, 102, 149, 170, + 13, 42, 145, 237, 47, 78, 1, 195, 210, 68, 175, 250, 142, 163, + 167, 181, 244, 63, 179, 119, 232, 73, 118, 50, 120, 37, 6, 134, + 35, 22, 58, 124, 109, 197, 135, 82, 47, 219, 180, 26, 2, 32, + 247, 8, 236, 24, 206, 252, 132, 77, 90, 153, 185, 61, 179, 103, + 143, 254, 220, 48, 120, 23, 211, 186, 1, 10, 69, 14, 131, 76, + 196, 229, 216, 73, 198, 34, 240, 133, 174, 153, 190, 147, 175, 8, + 132, 126, 33, 211, 138, 147, 121, 230, 104, 40, 17, 16, 239, 219, + 71, 32, 98, 207, 238, 243, 107, 78, 232, 146, 5, 3, 239, 214, + 246, 80, 0, 25, 78, 134, 53, 77, 194, 21, 151, 213, 128, 114, + 203, 204, 138, 144, 80, 107, 69, 149, 132, 225, 156, 143, 147, 156, + 117, 71, 161, 196, 78, 21, 232, 162, 106, 58, 155, 70, 99, 187, + 24, 172, 99, 225, 75, 97, 68, 42, 2, 117, 51, 184, 155, 74, + 15, 59, 45, 221, 79, 231, 222, 102, 201, 26, 30, 214, 101, 240, + 205, 35, 229, 152, 116, 222, 185, 93, 125, 118, 139, 83, 16, 138, + 173, 176, 51, 87, 56, 14, 12, 159, 244, 96, 144, 110, 72, 52, + 239, 61, 236, 150, 30, 235, 25, 125, 246, 126, 127, 16, 170, 233, + 207, 156, 33, 91, 202, 222, 141, 118, 214, 199, 153, 219, 235, 177, + 227, 174, 16, 111, 85, 156, 192, 89, 177, 43, 246, 117, 183, 135, + 161, 184, 127, 54, 60, 82, 141, 135, 192, 1, 180, 244, 40, 11, + 213, 86, 16, 132, 134, 245, 55, 29, 170, 14, 14, 148, 206, 243, + 61, 213, 228, 82, 149, 218, 171, 76, 78, 8, 6, 219, 4, 226, + 230, 50, 19, 118, 85, 202, 194, 170, 53, 222, 71, 126, 167, 209, + 254, 21, 223, 90, 197, 154, 177, 253, 253, 71, 215, 187, 242, 175, + 10, 168, 6, 79, 92, 161, 204, 66, 148, 143, 232, 61, 52, 186, + 44, 149, 162, 184, 103, 132, 113, 173, 17, 24, 156, 1, 29, 180, + 56, 15, 234, 230, 200, 43, 164, 210, 184, 109, 146, 86, 35, 77, + 215, 212, 240, 44, 28, 174, 194, 2, 3, 175, 68, 1, 153, 179, + 254, 101, 87, 164, 101, 15, 105, 145, 0, 87, 86, 150, 6, 18, + 160, 75, 196, 224, 100, 160, 240, 140, 94, 222, 121, 87, 8, 89, + 170, 116, 84, 165, 102, 177, 37, 25, 5, 234, 107, 13, 159, 68, + 12, 95, 137, 165, 152, 48, 171, 193, 87, 135, 129, 51, 219, 95, + 66, 94, 125, 128, 17, 178, 208, 41, 155, 187, 189, 186, 252, 145, + 141, 199, 39, 115, 84, 57, 137, 58, 142, 94, 0, 59, 30, 225, + 41, 32, 228, 82, 153, 42, 59, 174, 164, 146, 179, 255, 134, 237, + 13, 66, 82, 110, 44, 35, 125, 58, 142, 212, 180, 69, 24, 211, + 170, 41, 91, 245, 247, 204, 241, 35, 5, 17, 156, 123, 138, 151, + 129, 109, 117, 148, 250, 172, 194, 46, 77, 214, 175, 143, 81, 174, + 171, 231, 132, 107, 12, 44, 103, 80, 113, 117, 12, 39, 25, 58, + 253, 168, 145, 180, 176, 55, 159, 160, 101, 109, 98, 231, 86, 129, + 185, 176, 87, 117, 9, 231, 233, 62, 90, 226, 61, 117, 6, 210, + 164, 117, 177, 179, 47, 16, 119, 197, 242, 195, 51, 88, 5, 203, + 42, 230, 175, 25, 240, 49, 96, 161, 183, 151, 115, 234, 130, 201, + 205, 188, 226, 107, 27, 191, 134, 199, 42, 59, 93, 122, 84, 94, + 110, 158, 172, 229, 18, 154, 244, 56, 30, 222, 187, 190, 233, 30, + 44, 110, 104, 175, 173, 240, 210, 191, 243, 94, 166, 38, 201, 12, + 117, 122, 213, 222, 35, 144, 213, 27, 235, 131, 73, 148, 232, 113, + 248, 171, 246, 178, 171, 112, 201, 189, 181, 152, 44, 5, 135, 161, + 137, 165, 1, 183, 67, 105, 14, 242, 173, 19, 166, 166, 165, 38, + 108, 28, 117, 75, 97, 198, 127, 37, 7, 224, 88, 228, 132, 149, + 192, 234, 177, 130, 247, 42, 54, 62, 133, 129, 154, 74, 6, 174, + 79, 211, 123, 196, 147, 105, 80, 247, 184, 198, 25, 121, 61, 158, + 137, 15, 95, 218, 15, 97, 183, 190, 45, 44, 51, 225, 164, 5, + 98, 78, 174, 56, 230, 58, 50, 139, 79, 93, 116, 83, 81, 125, + 75, 95, 122, 81, 138, 56, 40, 213, 106, 225, 124, 101, 7, 171, + 4, 62, 208, 115, 62, 25, 116, 143, 3, 116, 46, 162, 220, 48, + 23, 240, 239, 169, 186, 91, 184, 22, 181, 114, 242, 97, 44, 82, + 53, 2, 168, 209, 199, 20, 17, 167, 96, 101, 165, 140, 137, 179, + 128, 161, 226, 175, 87, 96, 199, 237, 76, 173, 128, 17, 191, 246, + 214, 158, 9, 132, 145, 132, 231, 70, 33, 141, 16, 213, 201, 0, + 53, 77, 211, 36, 33, 126, 76, 113, 59, 117, 65, 77, 20, 70, + 223, 36, 118, 25, 17, 160, 135, 39, 77, 88, 111, 148, 125, 164, + 100, 160, 147, 125, 63, 29, 124, 159, 119, 252, 28, 68, 150, 39, + 165, 115, 163, 177, 122, 152, 209, 200, 132, 153, 153, 144, 140, 29, + 75, 102, 196, 136, 97, 58, 126, 135, 82, 238, 161, 154, 241, 68, + 171, 120, 247, 33, 149, 253, 93, 109, 93, 91, 207, 192, 129, 79, + 187, 96, 174, 58, 229, 80, 247, 44, 156, 125, 18, 23, 188, 208, + 219, 115, 42, 88, 177, 36, 5, 111, 34, 184, 56, 175, 150, 102, + 219, 64, 37, 192, 32, 53, 77, 102, 61, 196, 235, 66, 189, 148, + 88, 120, 16, 194, 0, 90, 175, 165, 180, 87, 130, 29, 222, 148, + 215, 91, 181, 81, 214, 55, 102, 88, 176, 116, 32, 150, 32, 232, + 113, 33, 111, 87, 218, 175, 18, 159, 126, 108, 170, 142, 184, 91, + 0, 117, 14, 230, 77, 198, 80, 140, 220, 52, 46, 171, 176, 98, + 93, 237, 125, 105, 180, 59, 234, 228, 5, 195, 72, 124, 121, 126, + 40, 96, 248, 115, 231, 119, 231, 151, 206, 11, 144, 179, 45, 210, + 97, 36, 123, 213, 138, 197, 62, 126, 106, 41, 170, 169, 89, 115, + 178, 134, 55, 7, 60, 163, 99, 95, 217, 198, 186, 6, 79, 96, + 85, 196, 126, 163, 177, 249, 87, 222, 125, 205, 95, 162, 108, 131, + 144, 245, 154, 8, 107, 108, 172, 222, 3, 77, 212, 118, 245, 93, + 68, 175, 242, 102, 222, 15, 65, 31, 112, 110, 57, 191, 4, 74, + 51, 178, 34, 209, 87, 128, 180, 160, 107, 244, 140, 48, 184, 179, + 152, 201, 248, 188, 163, 204, 69, 169, 251, 227, 126, 169, 109, 69, + 93, 186, 234, 178, 175, 210, 207, 223, 67, 142, 127, 231, 159, 238, + 243, 78, 152, 211, 123, 167, 10, 161, 130, 33, 77, 117, 5, 169, + 113, 205, 25, 14, 78, 28, 198, 93, 76, 203, 113, 163, 126, 225, + 103, 230, 29, 163, 51, 156, 149, 40, 243, 149, 144, 167, 196, 174, + 3, 119, 222, 221, 126, 211, 90, 4, 203, 73, 234, 44, 94, 96, + 65, 56, 172, 239, 160, 60, 67, 111, 92, 180, 83, 163, 2, 246, + 61, 59, 184, 52, 106, 205, 246, 48, 106, 191, 14, 126, 146, 144, + 189, 14, 53, 172, 78, 135, 113, 187, 80, 179, 202, 47, 163, 14, + 12, 210, 5, 243, 126, 32, 16, 143, 172, 10, 196, 246, 135, 97, + 180, 74, 60, 17, 112, 57, 245, 66, 217, 167, 238, 86, 17, 124, + 138, 144, 226, 28, 211, 255, 193, 41, 30, 39, 141, 37, 63, 36, + 80, 151, 12, 3, 88, 74, 159, 32, 45, 175, 157, 103, 85, 240, + 84, 87, 148, 165, 90, 166, 188, 101, 162, 201, 162, 175, 9, 114, + 181, 53, 227, 48, 54, 137, 218, 252, 3, 234, 59, 98, 163, 186, + 151, 56, 119, 178, 156, 250, 115, 36, 112, 246, 115, 232, 63, 192, + 160, 86, 34, 188, 156, 139, 163, 147, 91, 23, 146, 252, 236, 164, + 240, 185, 53, 88, 234, 140, 40, 188, 83, 255, 45, 82, 180, 69, + 53, 101, 78, 197, 116, 177, 208, 126, 93, 204, 169, 46, 155, 204, + 207, 130, 63, 197, 246, 66, 6, 163, 210, 131, 140, 211, 205, 73, + 141, 59, 45, 189, 169, 90, 84, 69, 231, 140, 206, 19, 165, 55, + 34, 245, 245, 54, 15, 28, 98, 97, 63, 236, 42, 45, 208, 197, + 245, 98, 182, 61, 232, 127, 176, 14, 218, 156, 226, 20, 117, 253, + 200, 34, 118, 75, 207, 88, 100, 39, 150, 243, 23, 84, 66, 3, + 212, 8, 28, 103, 156, 175, 36, 241, 65, 150, 203, 207, 61, 51, + 135, 186, 205, 235, 204, 168, 159, 120, 171, 161, 135, 131, 231, 87, + 210, 56, 120, 100, 252, 81, 124, 16, 157, 179, 211, 119, 80, 68, + 50, 66, 148, 106, 208, 39, 4, 218, 132, 181, 155, 187, 190, 45, + 189, 154, 94, 51, 13, 0, 142, 115, 174, 5, 164, 191, 154, 50, + 44, 27, 135, 120, 250, 147, 190, 83, 226, 13, 88, 174, 89, 64, + 214, 66, 199, 32, 202, 73, 79, 81, 176, 215, 88, 178, 19, 51, + 181, 249, 176, 224, 170, 182, 69, 176, 148, 93, 255, 37, 190, 41, + 250, 122, 147, 23, 184, 218, 228, 139, 75, 171, 16, 100, 110, 163, + 200, 131, 146, 237, 156, 239, 201, 3, 89, 113, 93, 222, 180, 239, + 200, 137, 180, 212, 35, 142, 150, 50, 95, 212, 18, 246, 172, 79, + 156, 64, 24, 79, 11, 84, 175, 121, 148, 241, 197, 90, 233, 57, + 122, 192, 31, 152, 3, 55, 140, 105, 202, 225, 213, 245, 69, 129, + 61, 245, 242, 226, 156, 153, 123, 174, 182, 74, 55, 53, 158, 154, + 131, 77, 172, 78, 220, 27, 206, 181, 28, 164, 8, 226, 31, 7, + 34, 131, 234, 77, 214, 219, 16, 119, 168, 35, 73, 98, 21, 255, + 225, 87, 74, 39, 198, 31, 226, 237, 0, 66, 46, 168, 32, 157, + 47, 147, 2, 217, 29, 219, 76, 203, 47, 140, 216, 166, 236, 240, + 244, 22, 216, 70, 252, 226, 69, 96, 32, 62, 201, 21, 40, 230, + 160, 212, 72, 188, 234, 199, 4, 200, 215, 238, 96, 222, 58, 202, + 65, 182, 211, 9, 249, 176, 60, 197, 183, 15, 75, 91, 242, 211, + 17, 211, 236, 47, 73, 11, 37, 103, 250, 35, 117, 59, 210, 49, + 157, 10, 50, 96, 30, 102, 253, 169, 32, 165, 176, 77, 70, 36, + 48, 201, 125, 38, 27, 99, 91, 116, 217, 135, 231, 179, 40, 23, + 175, 196, 138, 107, 180, 161, 180, 191, 242, 67, 206, 128, 242, 27, + 247, 199, 160, 210, 210, 79, 98, 254, 154, 102, 114, 19, 212, 185, + 210, 109, 5, 31, 72, 43, 0, 254, 33, 141, 7, 240, 0, 18, + 222, 44, 128, 162, 209, 129, 107, 108, 82, 69, 30, 111, 252, 80, + 234, 141, 82, 46, 203, 113, 186, 41, 19, 21, 107, 64, 151, 187, + 124, 158, 242, 159, 143, 221, 238, 89, 192, 207, 174, 47, 17, 235, + 108, 226, 97, 169, 142, 203, 211, 5, 4, 60, 220, 154, 245, 200, + 48, 2, 217, 17, 241, 212, 145, 121, 177, 166, 186, 175, 236, 249, + 198, 55, 180, 141, 105, 236, 17, 101, 225, 148, 229, 62, 151, 148, + 150, 204, 101, 160, 114, 203, 144, 154, 226, 8, 62, 43, 208, 40, + 98, 22, 49, 238, 234, 119, 209, 106, 34, 178, 152, 21, 24, 238, + 247, 115, 26, 108, 51, 244, 89, 32, 7, 89, 66, 175, 2, 163, + 30, 184, 31, 106, 98, 40, 110, 95, 39, 145, 160, 188, 150, 73, + 91, 230, 61, 56, 9, 76, 152, 140, 15, 185, 236, 107, 216, 34, + 137, 48, 96, 225, 135, 113, 101, 79, 50, 142, 103, 250, 49, 124, + 23, 206, 186, 16, 153, 142, 94, 202, 100, 243, 151, 244, 20, 148, + 2, 183, 109, 111, 77, 111, 80, 138, 9, 214, 160, 217, 16, 108, + 72, 14, 79, 163, 156, 113, 130, 114, 55, 194, 28, 52, 218, 6, + 139, 72, 160, 158, 105, 63, 85, 234, 38, 192, 89, 35, 44, 227, + 154, 240, 23, 186, 140, 246, 118, 247, 253, 31, 35, 75, 130, 57, + 165, 146, 78, 214, 41, 204, 49, 83, 144, 3, 251, 108, 140, 104, + 174, 34, 79, 79, 143, 61, 73, 6, 193, 217, 50, 24, 158, 87, + 168, 82, 119, 157, 254, 121, 192, 119, 131, 107, 26, 192, 73, 135, + 53, 132, 134, 59, 190, 252, 3, 89, 33, 102, 181, 25, 237, 67, + 130, 207, 248, 240, 166, 114, 244, 41, 129, 65, 222, 24, 115, 72, + 78, 246, 15, 27, 211, 193, 6, 93, 171, 22, 196, 92, 27, 67, + 235, 149, 251, 39, 48, 169, 13, 179, 101, 171, 253, 229, 198, 247, + 175, 253, 87, 52, 76, 128, 227, 17, 199, 99, 251, 144, 252, 228, + 86, 119, 83, 11, 81, 137, 224, 121, 213, 246, 237, 115, 14, 33, + 72, 186, 8, 226, 53, 97, 126, 88, 214, 61, 175, 224, 214, 238, + 246, 171, 32, 203, 83, 125, 27, 146, 206, 116, 154, 252, 17, 72, + 96, 5, 159, 121, 70, 123, 201, 78, 19, 146, 174, 144, 116, 60, + 121, 190, 220, 254, 161, 4, 103, 155, 126, 239, 244, 243, 182, 8, + 27, 205, 130, 98, 90, 26, 133, 172, 53, 31, 17, 99, 120, 202, + 135, 107, 197, 242, 61, 208, 65, 236, 181, 184, 73, 185, 85, 90, + 167, 9, 228, 58, 240, 67, 89, 133, 236, 34, 118, 106, 50, 190, + 101, 240, 6, 141, 141, 19, 243, 10, 210, 232, 163, 141, 41, 151, + 119, 219, 74, 3, 146, 154, 77, 219, 170, 206, 89, 144, 228, 226, + 171, 61, 216, 0, 157, 178, 202, 230, 128, 166, 120, 45, 61, 165, + 142, 208, 11, 21, 164, 63, 10, 229, 132, 82, 36, 197, 177, 252, + 142, 81, 207, 143, 81, 65, 110, 221, 153, 198, 145, 162, 62, 165, + 106, 79, 133, 241, 17, 183, 115, 194, 137, 53, 77, 0, 167, 57, + 202, 75, 206, 118, 11, 166, 195, 13, 170, 242, 111, 66, 123, 48, + 240, 139, 118, 194, 45, 199, 7, 249, 127, 75, 51, 246, 192, 242, + 45, 183, 84, 1, 207, 205, 29, 175, 222, 156, 197, 18, 232, 200, + 61, 97, 156, 138, 125, 16, 180, 91, 149, 139, 36, 226, 197, 129, + 132, 159, 22, 49, 49, 104, 141, 124, 82, 80, 179, 55, 107, 25, + 149, 165, 14, 144, 61, 208, 75, 2, 203, 5, 203, 219, 111, 215, + 55, 53, 222, 59, 139, 253, 9, 200, 65, 71, 171, 177, 242, 30, + 83, 135, 50, 190, 99, 198, 32, 164, 243, 140, 145, 174, 49, 232, + 251, 152, 233, 202, 190, 31, 51, 160, 242, 176, 47, 119, 124, 236, + 2, 87, 26, 255, 224, 39, 202, 6, 202, 25, 216, 180, 118, 60, + 181, 89, 233, 208, 0, 69, 0, 187, 66, 36, 9, 66, 236, 158, + 251, 61, 18, 136, 197, 124, 13, 212, 159, 51, 169, 125, 102, 181, + 205, 88, 195, 190, 221, 236, 85, 167, 32, 42, 90, 27, 202, 107, + 192, 200, 68, 162, 40, 47, 79, 82, 48, 248, 57, 132, 78, 65, + 91, 30, 11, 158, 234, 102, 194, 155, 148, 154, 253, 210, 80, 228, + 17, 148, 148, 128, 40, 57, 169, 124, 176, 20, 62, 213, 198, 93, + 94, 7, 225, 195, 112, 112, 242, 122, 254, 151, 145, 41, 100, 228, + 168, 164, 18, 5, 84, 131, 151, 51, 173, 37, 226, 226, 252, 202, + 14, 140, 155, 13, 23, 7, 106, 37, 180, 37, 85, 244, 76, 7, + 117, 44, 57, 48, 95, 249, 126, 32, 168, 232, 189, 26, 162, 204, + 230, 117, 89, 235, 239, 85, 42, 118, 208, 95, 178, 137, 199, 48, + 25, 110, 70, 5, 168, 245, 231, 61, 134, 177, 71, 247, 176, 17, + 196, 159, 231, 200, 41, 105, 43, 62, 231, 25, 102, 156, 19, 134, + 172, 202, 207, 199, 163, 219, 100, 170, 117, 160, 113, 40, 172, 86, + 177, 227, 15, 159, 233, 149, 153, 246, 101, 111, 32, 96, 71, 150, + 132, 143, 68, 12, 8, 27, 34, 195, 72, 186, 223, 248, 118, 82, + 42, 35, 145, 100, 226, 164, 206, 163, 137, 154, 234, 66, 169, 112, + 173, 170, 70, 27, 159, 188, 249, 245, 221, 216, 198, 50, 152, 232, + 249, 223, 250, 86, 178, 236, 110, 189, 10, 111, 10, 30, 247, 192, + 185, 149, 12, 162, 209, 122, 145, 156, 37, 133, 137, 197, 246, 55, + 105, 48, 204, 158, 67, 22, 102, 3, 95, 241, 58, 4, 170, 86, + 185, 113, 244, 33, 199, 215, 20, 54, 248, 45, 121, 75, 149, 192, + 8, 160, 54, 71, 28, 176, 42, 134, 191, 147, 20, 117, 42, 142, + 107, 65, 179, 153, 250, 78, 17, 60, 105, 206, 72, 214, 204, 169, + 118, 196, 41, 48, 191, 125, 79, 193, 250, 212, 113, 41, 148, 245, + 1, 71, 130, 26, 68, 48, 14, 76, 225, 74, 231, 140, 76, 34, + 60, 31, 112, 19, 144, 65, 216, 245, 167, 181, 46, 175, 126, 243, + 111, 158, 132, 29, 79, 127, 16, 194, 45, 192, 101, 61, 127, 70, + 132, 162, 222, 92, 139, 187, 57, 166, 72, 242, 146, 254, 89, 102, + 57, 7, 148, 153, 241, 104, 249, 181, 46, 208, 249, 143, 149, 209, + 210, 188, 41, 109, 78, 184, 169, 177, 67, 36, 169, 29, 56, 121, + 112, 226, 234, 119, 138, 55, 113, 246, 6, 109, 160, 62, 99, 114, + 17, 231, 20, 132, 211, 211, 21, 8, 62, 120, 106, 104, 212, 136, + 150, 164, 111, 120, 147, 162, 49, 94, 168, 145, 40, 66, 173, 164, + 143, 54, 206, 180, 244, 200, 98, 122, 111, 206, 166, 92, 246, 108, + 21, 202, 56, 67, 119, 76, 205, 54, 61, 209, 230, 47, 45, 31, + 83, 75, 7, 137, 154, 169, 235, 143, 219, 160, 34, 104, 150, 161, + 160, 204, 103, 250, 174, 83, 68, 233, 8, 19, 29, 162, 88, 172, + 253, 126, 61, 199, 78, 43, 220, 46, 246, 171, 78, 233, 224, 20, + 112, 143, 197, 90, 25, 164, 156, 37, 11, 43, 94, 188, 44, 78, + 32, 182, 33, 132, 56, 56, 215, 56, 127, 53, 184, 190, 5, 136, + 19, 149, 79, 223, 104, 212, 58, 165, 129, 124, 140, 233, 109, 66, + 64, 117, 55, 128, 97, 106, 0, 26, 10, 51, 127, 150, 152, 111, + 166, 168, 222, 54, 159, 61, 138, 100, 56, 85, 15, 128, 79, 4, + 200, 151, 183, 149, 210, 147, 97, 140, 36, 217, 232, 198, 95, 73, + 9, 174, 106, 205, 241, 196, 187, 223, 211, 250, 199, 238, 122, 22, + 130, 111, 253, 156, 40, 137, 92, 96, 223, 235, 242, 45, 114, 207, + 211, 125, 236, 55, 189, 136, 208, 66, 199, 205, 92, 65, 175, 168, + 156, 123, 44, 75, 75, 29, 56, 108, 75, 226, 16, 240, 24, 37, + 75, 155, 254, 195, 182, 42, 239, 38, 255, 227, 17, 138, 161, 82, + 63, 191, 198, 117, 250, 133, 21, 169, 186, 212, 148, 55, 8, 199, + 131, 245, 89, 169, 131, 12, 239, 99, 211, 134, 211, 108, 91, 245, + 73, 184, 33, 156, 236, 44, 189, 183, 135, 214, 104, 145, 229, 94, + 21, 34, 237, 102, 220, 175, 167, 135, 180, 57, 84, 2, 49, 124, + 237, 238, 242, 39, 39, 160, 120, 128, 145, 148, 45, 27, 211, 148, + 163, 126, 234, 175, 35, 44, 59, 117, 248, 47, 69, 108, 164, 96, + 246, 198, 165, 82, 15, 123, 61, 63, 106, 23, 129, 189, 87, 205, + 63, 95, 134, 126, 236, 197, 156, 204, 6, 203, 77, 170, 190, 71, + 27, 239, 134, 221, 57, 145, 202, 60, 149, 237, 84, 7, 198, 25, + 243, 34, 34, 122, 219, 188, 216, 219, 107, 241, 222, 85, 169, 106, + 45, 220, 241, 67, 121, 94, 69, 90, 198, 64, 122, 104, 84, 255, + 25, 7, 151, 254, 155, 138, 174, 238, 18, 147, 127, 111, 7, 92, + 170, 45, 225, 23, 12, 120, 208, 184, 174, 121, 22, 0, 51, 15, + 47, 135, 44, 213, 83, 215, 75, 236, 148, 76, 114, 9, 113, 221, + 188, 114, 125, 96, 212, 60, 190, 99, 236, 100, 245, 132, 81, 121, + 30, 55, 142, 55, 209, 226, 173, 108, 48, 53, 163, 206, 138, 148, + 0, 152, 99, 215, 152, 206, 149, 238, 222, 199, 39, 157, 50, 59, + 33, 157, 125, 140, 210, 178, 216, 93, 58, 60, 20, 17, 114, 185, + 234, 133, 127, 167, 126, 25, 109, 199, 135, 92, 236, 86, 93, 86, + 50, 11, 119, 219, 155, 130, 229, 219, 97, 173, 68, 27, 27, 159, + 85, 210, 13, 95, 230, 27, 194, 201, 106, 211, 90, 99, 101, 50, + 219, 141, 120, 219, 42, 99, 121, 11, 184, 44, 104, 86, 142, 232, + 212, 15, 242, 83, 37, 76, 160, 238, 113, 9, 33, 0, 31, 27, + 49, 245, 142, 44, 93, 173, 66, 218, 63, 63, 96, 130, 77, 70, + 247, 130, 170, 203, 32, 49, 124, 255, 183, 81, 178, 106, 83, 6, + 17, 58, 189, 110, 95, 189, 65, 66, 136, 248, 185, 75, 73, 210, + 134, 91, 45, 196, 155, 240, 142, 218, 172, 180, 51, 92, 185, 6, + 148, 245, 35, 150, 56, 236, 210, 9, 193, 212, 185, 48, 170, 102, + 46, 125, 157, 245, 63, 33, 103, 210, 94, 84, 4, 204, 246, 116, + 2, 80, 223, 145, 200, 92, 84, 42, 7, 13, 61, 120, 69, 40, + 236, 39, 132, 208, 239, 51, 111, 197, 50, 142, 56, 196, 164, 37, + 22, 130, 7, 119, 63, 152, 165, 182, 195, 117, 208, 119, 118, 102, + 177, 64, 114, 68, 229, 233, 246, 27, 179, 146, 225, 146, 78, 4, + 231, 225, 205, 2, 31, 236, 218, 154, 162, 98, 95, 48, 114, 255, + 235, 55, 130, 73, 75, 211, 96, 226, 56, 39, 153, 246, 77, 35, + 177, 31, 55, 151, 58, 199, 232, 157, 106, 228, 170, 144, 187, 17, + 106, 181, 252, 190, 253, 87, 78, 90, 65, 152, 164, 85, 99, 184, + 133, 48, 180, 165, 164, 225, 72, 198, 180, 224, 225, 178, 177, 26, + 50, 29, 249, 15, 61, 192, 254, 130, 13, 212, 30, 155, 235, 62, + 88, 52, 102, 141, 6, 174, 123, 228, 244, 107, 6, 206, 77, 88, + 85, 36, 173, 87, 218, 12, 2, 177, 137, 108, 204, 178, 98, 109, + 197, 15, 20, 148, 69, 87, 96, 160, 107, 176, 6, 138, 101, 4, + 83, 23, 44, 39, 214, 207, 175, 9, 149, 36, 243, 78, 62, 244, + 104, 16, 190, 153, 103, 241, 199, 59, 33, 189, 180, 53, 96, 98, + 37, 128, 235, 204, 86, 26, 140, 144, 90, 225, 240, 237, 135, 60, + 229, 88, 60, 217, 199, 4, 70, 18, 232, 184, 162, 7, 178, 160, + 176, 47, 63, 89, 18, 40, 48, 114, 233, 209, 11, 133, 81, 165, + 195, 227, 136, 51, 22, 201, 16, 209, 171, 169, 16, 1, 135, 37, + 118, 60, 73, 151, 117, 183, 191, 174, 21, 127, 180, 165, 201, 208, + 129, 204, 141, 57, 239, 150, 244, 159, 178, 173, 168, 92, 241, 214, + 109, 14, 164, 136, 141, 25, 2, 45, 65, 94, 207, 228, 54, 251, + 5, 100, 60, 147, 217, 97, 187, 117, 248, 77, 100, 238, 74, 104, + 205, 68, 95, 141, 57, 145, 108, 32, 22, 85, 204, 199, 179, 46, + 96, 143, 116, 77, 96, 34, 227, 5, 201, 202, 125, 235, 171, 93, + 135, 18, 76, 34, 112, 30, 131, 162, 147, 10, 17, 75, 174, 250, + 118, 53, 139, 164, 62, 104, 221, 182, 79, 142, 42, 20, 126, 104, + 162, 205, 34, 74, 241, 57, 10, 160, 240, 224, 199, 163, 231, 6, + 206, 104, 129, 164, 2, 136, 247, 35, 211, 198, 203, 116, 130, 212, + 177, 3, 131, 17, 239, 154, 56, 40, 32, 98, 86, 22, 151, 121, + 229, 40, 51, 46, 3, 51, 132, 183, 127, 155, 228, 77, 157, 121, + 133, 213, 173, 87, 23, 155, 108, 193, 55, 214, 62, 95, 221, 178, + 169, 182, 197, 114, 176, 117, 82, 170, 234, 250, 142, 159, 39, 250, + 155, 160, 141, 246, 217, 252, 161, 42, 110, 144, 26, 33, 203, 63, + 186, 47, 164, 187, 195, 20, 173, 254, 80, 243, 68, 164, 20, 28, + 153, 142, 215, 95, 67, 230, 210, 130, 56, 172, 155, 120, 105, 141, + 246, 210, 2, 4, 19, 35, 216, 71, 174, 49, 234, 25, 142, 166, + 102, 229, 12, 45, 13, 178, 209, 205, 48, 40, 191, 58, 198, 216, + 133, 207, 127, 243, 16, 192, 8, 96, 43, 96, 49, 166, 87, 238, + 235, 71, 196, 151, 68, 22, 244, 187, 189, 60, 107, 181, 25, 178, + 159, 84, 21, 11, 233, 133, 217, 219, 61, 129, 253, 186, 174, 111, + 42, 55, 143, 119, 155, 122, 45, 242, 163, 132, 84, 5, 112, 56, + 164, 139, 128, 119, 57, 147, 8, 54, 78, 150, 200, 193, 83, 99, + 88, 133, 196, 234, 123, 95, 157, 160, 215, 28, 181, 252, 183, 62, + 217, 197, 187, 2, 181, 246, 183, 206, 178, 40, 91, 196, 110, 156, + 28, 129, 42, 170, 126, 244, 117, 169, 57, 96, 163, 45, 74, 80, + 28, 29, 203, 105, 131, 17, 210, 49, 61, 139, 26, 40, 179, 253, + 71, 194, 8, 107, 130, 201, 99, 77, 22, 156, 179, 19, 131, 54, + 192, 103, 108, 255, 89, 244, 115, 153, 101, 88, 63, 124, 34, 19, + 69, 248, 242, 161, 78, 103, 55, 31, 181, 53, 199, 44, 66, 70, + 171, 232, 167, 251, 46, 231, 177, 244, 6, 111, 88, 121, 133, 164, + 83, 78, 232, 78, 71, 164, 248, 134, 196, 39, 53, 66, 198, 167, + 239, 65, 17, 142, 239, 223, 67, 16, 15, 174, 217, 80, 2, 130, + 238, 145, 202, 194, 105, 14, 121, 185, 57, 51, 145, 208, 226, 74, + 46, 210, 171, 238, 10, 151, 181, 10, 163, 168, 52, 211, 234, 90, + 35, 75, 148, 76, 63, 68, 132, 37, 31, 255, 82, 175, 77, 228, + 237, 217, 117, 166, 175, 127, 223, 101, 189, 139, 70, 60, 64, 110, + 27, 86, 139, 183, 172, 17, 117, 140, 117, 67, 87, 133, 109, 254, + 83, 145, 214, 253, 148, 242, 53, 50, 252, 194, 223, 175, 77, 241, + 28, 63, 247, 27, 101, 28, 21, 151, 245, 49, 155, 33, 26, 155, + 160, 190, 98, 34, 191, 199, 96, 98, 47, 205, 183, 252, 86, 168, + 150, 63, 254, 8, 134, 195, 17, 68, 10, 249, 90, 109, 237, 219, + 168, 60, 252, 190, 133, 218, 220, 69, 25, 223, 3, 236, 74, 229, + 79, 218, 186, 199, 234, 17, 215, 145, 198, 228, 129, 239, 107, 4, + 229, 188, 212, 241, 204, 45, 201, 72, 17, 175, 136, 180, 122, 94, + 40, 239, 41, 91, 97, 253, 61, 244, 16, 29, 4, 248, 201, 175, + 1, 122, 0, 143, 62, 112, 132, 213, 46, 49, 98, 228, 94, 77, + 179, 46, 245, 160, 65, 179, 53, 0, 86, 139, 154, 79, 249, 177, + 6, 78, 184, 139, 143, 139, 240, 134, 109, 66, 1, 3, 180, 251, + 19, 3, 211, 36, 32, 79, 181, 249, 205, 25, 4, 168, 238, 50, + 75, 128, 97, 121, 94, 199, 92, 200, 241, 75, 136, 155, 109, 121, + 250, 15, 163, 173, 82, 26, 41, 86, 189, 61, 79, 137, 162, 129, + 12, 178, 217, 213, 0, 244, 81, 216, 64, 99, 174, 72, 44, 215, + 110, 88, 235, 152, 38, 64, 141, 88, 253, 95, 159, 151, 30, 73, + 48, 134, 145, 116, 77, 51, 246, 120, 221, 36, 241, 182, 159, 209, + 72, 29, 45, 120, 4, 98, 121, 19, 45, 231, 184, 252, 119, 181, + 222, 61, 2, 151, 138, 123, 119, 90, 6, 202, 85, 240, 239, 156, + 211, 83, 169, 127, 39, 111, 226, 90, 88, 91, 79, 197, 119, 26, + 29, 205, 176, 209, 254, 133, 195, 189, 208, 172, 218, 101, 198, 240, + 243, 84, 2, 103, 141, 229, 183, 137, 37, 128, 73, 32, 223, 198, + 165, 78, 253, 72, 83, 64, 232, 214, 251, 237, 204, 67, 181, 195, + 232, 104, 61, 1, 166, 79, 231, 227, 78, 178, 203, 67, 131, 141, + 194, 162, 141, 234, 238, 32, 23, 161, 112, 90, 181, 151, 228, 180, + 189, 144, 124, 177, 132, 40, 76, 149, 159, 118, 215, 110, 211, 204, + 72, 87, 12, 75, 112, 138, 198, 84, 56, 208, 171, 58, 222, 110, + 249, 191, 139, 31, 164, 206, 191, 235, 27, 117, 171, 46, 254, 157, + 212, 61, 216, 153, 179, 60, 224, 242, 26, 94, 229, 165, 235, 53, + 57, 28, 29, 1, 240, 145, 181, 15, 255, 26, 186, 32, 222, 75, + 250, 71, 221, 208, 72, 4, 245, 137, 182, 137, 38, 9, 22, 137, + 210, 87, 27, 164, 57, 141, 75, 249, 20, 182, 66, 177, 187, 143, + 169, 142, 189, 226, 114, 231, 129, 160, 174, 16, 83, 14, 247, 164, + 51, 48, 86, 47, 143, 107, 241, 211, 123, 188, 56, 103, 133, 160, + 0, 186, 59, 173, 121, 241, 159, 251, 227, 77, 239, 14, 85, 253, + 89, 108, 71, 58, 116, 41, 139, 141, 146, 48, 156, 218, 249, 57, + 142, 194, 241, 70, 170, 151, 39, 169, 240, 208, 29, 155, 186, 167, + 235, 48, 68, 83, 83, 57, 103, 128, 183, 14, 35, 219, 52, 80, + 107, 5, 68, 214, 10, 28, 127, 172, 240, 107, 153, 154, 73, 8, + 23, 45, 232, 78, 113, 102, 145, 70, 140, 111, 48, 5, 125, 173, + 137, 67, 19, 63, 49, 249, 149, 4, 140, 98, 161, 41, 221, 65, + 173, 56, 101, 177, 70, 111, 51, 89, 130, 210, 197, 95, 73, 26, + 200, 223, 178, 14, 85, 134, 87, 206, 204, 168, 157, 182, 14, 36, + 146, 48, 139, 68, 158, 181, 84, 61, 109, 160, 249, 13, 56, 156, + 232, 159, 188, 161, 157, 108, 201, 123, 224, 181, 30, 223, 186, 248, + 55, 218, 233, 25, 212, 14, 103, 83, 78, 243, 20, 123, 252, 246, + 203, 181, 65, 194, 130, 128, 50, 208, 45, 60, 177, 86, 163, 165, + 118, 97, 247, 218, 50, 211, 206, 116, 238, 138, 99, 61, 103, 84, + 184, 189, 10, 115, 191, 18, 14, 240, 255, 102, 172, 134, 52, 111, + 157, 8, 161, 76, 161, 133, 155, 253, 20, 216, 116, 149, 140, 79, + 27, 238, 66, 174, 153, 60, 132, 34, 86, 224, 223, 243, 42, 55, + 62, 216, 7, 246, 106, 206, 123, 240, 96, 220, 165, 200, 36, 219, + 222, 133, 199, 185, 122, 139, 245, 12, 191, 100, 61, 186, 60, 126, + 200, 177, 115, 102, 219, 218, 50, 233, 226, 95, 23, 208, 186, 233, + 45, 154, 104, 165, 51, 195, 50, 141, 138, 92, 54, 213, 243, 135, + 125, 17, 135, 38, 88, 109, 73, 31, 139, 34, 74, 122, 154, 236, + 242, 100, 127, 24, 227, 159, 29, 28, 198, 246, 197, 1, 211, 146, + 203, 185, 36, 37, 56, 182, 53, 234, 109, 0, 39, 49, 68, 252, + 71, 200, 198, 40, 94, 196, 143, 180, 43, 164, 91, 78, 160, 255, + 110, 134, 191, 184, 234, 100, 63, 0, 21, 129, 77, 65, 83, 96, + 200, 8, 49, 83, 8, 190, 226, 158, 98, 161, 158, 79, 134, 197, + 70, 1, 42, 11, 169, 105, 77, 237, 237, 161, 117, 242, 160, 113, + 73, 114, 88, 179, 85, 78, 26, 78, 170, 250, 16, 189, 110, 135, + 38, 72, 79, 175, 89, 80, 219, 215, 62, 230, 84, 217, 183, 240, + 124, 57, 127, 159, 100, 71, 208, 171, 195, 141, 165, 126, 208, 1, + 198, 137, 208, 180, 218, 81, 2, 12, 22, 184, 151, 67, 37, 180, + 90, 8, 202, 186, 154, 64, 15, 15, 135, 46, 31, 181, 146, 244, + 54, 55, 197, 52, 83, 18, 33, 233, 109, 9, 223, 183, 166, 134, + 43, 127, 134, 98, 159, 55, 38, 111, 117, 24, 128, 199, 113, 167, + 113, 64, 160, 247, 79, 106, 71, 240, 76, 63, 155, 31, 60, 41, + 230, 142, 107, 174, 106, 31, 72, 60, 208, 217, 75, 54, 33, 180, + 211, 82, 115, 143, 13, 7, 198, 31, 125, 243, 157, 124, 47, 98, + 246, 50, 179, 144, 12, 2, 51, 183, 144, 115, 210, 40, 225, 113, + 99, 252, 244, 150, 175, 93, 56, 244, 97, 249, 149, 110, 251, 128, + 152, 222, 186, 86, 86, 147, 124, 166, 74, 106, 230, 227, 247, 235, + 119, 106, 198, 182, 14, 100, 233, 218, 115, 71, 201, 89, 21, 162, + 58, 106, 140, 254, 190, 79, 36, 101, 102, 245, 165, 20, 194, 63, + 102, 14, 141, 196, 57, 169, 111, 241, 72, 239, 126, 142, 145, 253, + 166, 222, 94, 143, 169, 250, 104, 119, 51, 9, 255, 132, 197, 33, + 159, 220, 253, 122, 235, 66, 224, 120, 201, 209, 90, 113, 85, 162, + 221, 219, 39, 45, 77, 48, 95, 152, 225, 40, 3, 90, 109, 49, + 212, 44, 15, 82, 158, 42, 91, 127, 144, 237, 54, 70, 44, 104, + 2, 91, 90, 40, 24, 228, 122, 82, 15, 194, 211, 169, 107, 231, + 33, 18, 94, 79, 103, 70, 233, 140, 73, 187, 152, 190, 149, 216, + 220, 64, 220, 112, 170, 115, 16, 114, 108, 63, 10, 1, 158, 157, + 3, 127, 51, 154, 225, 49, 144, 201, 50, 139, 162, 106, 56, 253, + 81, 32, 137, 7, 236, 232, 50, 65, 40, 132, 31, 32, 125, 63, + 232, 229, 180, 118, 17, 136, 181, 66, 255, 213, 98, 246, 104, 51, + 4, 19, 27, 87, 110, 252, 247, 64, 83, 98, 131, 76, 115, 51, + 83, 26, 31, 205, 55, 4, 91, 90, 60, 133, 142, 39, 70, 73, + 179, 119, 84, 100, 50, 169, 166, 157, 148, 215, 121, 220, 166, 235, + 21, 237, 89, 222, 199, 177, 211, 242, 9, 208, 127, 109, 218, 224, + 146, 114, 137, 51, 128, 95, 166, 196, 105, 112, 135, 99, 227, 229, + 255, 153, 20, 80, 163, 60, 16, 8, 92, 210, 20, 207, 186, 187, + 175, 193, 125, 31, 221, 145, 0, 243, 222, 202, 54, 170, 160, 24, + 242, 255, 241, 217, 44, 178, 124, 147, 117, 0, 168, 33, 167, 80, + 101, 183, 205, 218, 249, 21, 151, 171, 251, 7, 120, 252, 223, 98, + 255, 66, 196, 89, 41, 51, 37, 41, 28, 183, 4, 202, 135, 117, + 84, 199, 176, 9, 176, 203, 239, 7, 219, 136, 226, 156, 198, 19, + 64, 243, 60, 39, 162, 26, 208, 239, 6, 3, 176, 22, 129, 244, + 40, 85, 253, 39, 92, 72, 65, 157, 69, 175, 205, 84, 43, 22, + 240, 242, 67, 86, 195, 58, 145, 136, 245, 40, 46, 190, 243, 231, + 206, 88, 134, 31, 136, 172, 57, 142, 250, 67, 60, 2, 136, 253, + 97, 187, 121, 50, 139, 189, 77, 113, 16, 126, 35, 247, 157, 1, + 134, 128, 127, 209, 239, 20, 204, 236, 50, 24, 28, 71, 18, 83, + 51, 48, 125, 2, 124, 229, 220, 97, 217, 133, 4, 241, 242, 63, + 123, 158, 201, 246, 232, 186, 237, 65, 9, 247, 66, 196, 15, 240, + 215, 22, 236, 233, 245, 9, 183, 218, 9, 1, 56, 242, 11, 184, + 117, 97, 248, 193, 219, 143, 245, 254, 154, 216, 183, 63, 126, 10, + 142, 252, 231, 211, 109, 198, 131, 248, 249, 125, 196, 74, 10, 178, + 12, 93, 73, 109, 248, 25, 69, 161, 187, 41, 7, 102, 235, 195, + 83, 181, 154, 164, 78, 251, 192, 82, 230, 229, 7, 175, 41, 39, + 204, 38, 161, 120, 93, 40, 66, 104, 248, 22, 46, 45, 203, 240, + 19, 111, 111, 49, 127, 226, 118, 246, 161, 210, 85, 145, 188, 91, + 200, 4, 11, 5, 224, 129, 234, 190, 181, 3, 9, 0, 95, 188, + 122, 1, 3, 169, 95, 142, 78, 60, 123, 36, 239, 231, 135, 22, + 156, 138, 63, 0, 12, 39, 126, 250, 157, 108, 188, 131, 81, 226, + 5, 190, 166, 230, 95, 92, 39, 138, 91, 23, 82, 23, 72, 240, + 109, 86, 228, 175, 26, 81, 117, 230, 135, 68, 162, 203, 110, 44, + 188, 24, 21, 153, 118, 29, 194, 181, 12, 209, 146, 202, 33, 49, + 80, 60, 100, 74, 13, 126, 209, 132, 43, 125, 242, 184, 132, 111, + 147, 59, 21, 67, 234, 222, 17, 232, 176, 147, 238, 115, 197, 226, + 248, 24, 51, 148, 97, 229, 38, 248, 43, 122, 45, 158, 158, 212, + 87, 123, 136, 48, 153, 170, 104, 203, 43, 111, 45, 64, 158, 249, + 37, 247, 139, 187, 118, 42, 185, 147, 181, 226, 129, 70, 166, 46, + 223, 252, 236, 164, 221, 10, 250, 74, 201, 112, 111, 198, 37, 95, + 104, 197, 107, 248, 214, 233, 243, 253, 26, 228, 26, 217, 255, 42, + 250, 104, 13, 4, 235, 217, 243, 36, 212, 184, 16, 44, 108, 189, + 253, 43, 113, 249, 161, 55, 173, 225, 88, 229, 248, 107, 134, 165, + 190, 59, 46, 6, 32, 15, 24, 37, 120, 83, 67, 122, 238, 34, + 235, 79, 144, 35, 84, 251, 58, 88, 141, 112, 147, 42, 130, 206, + 64, 22, 58, 129, 172, 74, 194, 161, 89, 141, 195, 202, 137, 152, + 14, 115, 244, 236, 132, 211, 0, 188, 58, 163, 209, 119, 103, 189, + 150, 188, 202, 136, 251, 205, 180, 115, 7, 41, 225, 227, 26, 22, + 27, 91, 122, 160, 205, 129, 29, 240, 220, 131, 157, 123, 122, 50, + 158, 30, 21, 74, 11, 186, 190, 103, 218, 27, 54, 57, 179, 228, + 207, 9, 51, 12, 204, 232, 60, 150, 147, 84, 36, 183, 1, 25, + 57, 177, 156, 1, 158, 226, 128, 33, 172, 3, 253, 114, 25, 102, + 125, 144, 238, 102, 106, 191, 105, 3, 135, 229, 200, 1, 215, 223, + 23, 231, 173, 27, 98, 25, 204, 107, 50, 90, 252, 223, 116, 186, + 216, 173, 121, 201, 151, 162, 73, 57, 131, 197, 173, 240, 102, 236, + 113, 125, 129, 198, 124, 71, 104, 249, 89, 5, 105, 53, 224, 215, + 238, 141, 78, 6, 176, 233, 133, 58, 0, 159, 231, 17, 159, 104, + 127, 239, 55, 41, 51, 173, 176, 118, 62, 108, 40, 12, 246, 234, + 218, 227, 218, 56, 142, 148, 172, 247, 86, 52, 253, 94, 60, 64, + 131, 204, 158, 107, 184, 170, 107, 155, 139, 239, 11, 152, 172, 216, + 107, 6, 171, 108, 51, 34, 168, 8, 45, 227, 149, 115, 15, 168, + 117, 249, 236, 51, 163, 202, 125, 145, 14, 231, 23, 21, 109, 244, + 136, 241, 212, 22, 62, 36, 157, 164, 209, 117, 183, 199, 114, 187, + 83, 244, 160, 150, 144, 208, 8, 155, 115, 92, 25, 141, 138, 105, + 179, 56, 207, 169, 11, 16, 97, 220, 40, 195, 125, 248, 155, 66, + 112, 139, 6, 63, 85, 112, 234, 58, 143, 46, 160, 176, 225, 27, + 51, 222, 96, 141, 177, 208, 174, 167, 218, 39, 19, 2, 56, 40, + 117, 230, 112, 11, 222, 230, 36, 209, 105, 177, 125, 186, 219, 168, + 34, 29, 178, 223, 65, 155, 221, 110, 186, 94, 160, 71, 201, 28, + 85, 200, 172, 161, 86, 155, 66, 139, 219, 7, 140, 192, 230, 63, + 224, 99, 198, 5, 0, 145, 161, 195, 199, 197, 133, 103, 137, 167, + 173, 27, 143, 60, 216, 24, 254, 183, 31, 40, 223, 97, 116, 22, + 191, 36, 77, 81, 102, 52, 25, 85, 6, 118, 83, 107, 188, 28, + 139, 25, 31, 84, 223, 115, 122, 40, 244, 159, 160, 201, 149, 34, + 39, 85, 17, 103, 196, 175, 176, 160, 88, 219, 188, 43, 136, 94, + 33, 186, 242, 243, 77, 173, 0, 70, 234, 2, 252, 129, 133, 201, + 23, 1, 214, 178, 247, 102, 28, 252, 185, 176, 243, 253, 3, 117, + 13, 132, 201, 101, 112, 68, 157, 205, 141, 126, 129, 154, 119, 76, + 47, 98, 252, 49, 72, 142, 83, 172, 53, 223, 20, 187, 12, 98, + 108, 220, 83, 19, 67, 165, 56, 64, 254, 248, 37, 123, 70, 50, + 11, 204, 214, 204, 75, 5, 201, 50, 135, 187, 224, 123, 68, 129, + 202, 22, 16, 117, 52, 235, 171, 1, 19, 176, 11, 239, 30, 192, + 188, 79, 165, 232, 8, 40, 162, 78, 95, 196, 4, 235, 251, 74, + 112, 169, 81, 251, 118, 95, 202, 217, 17, 107, 40, 110, 25, 133, + 0, 81, 79, 119, 74, 54, 75, 167, 229, 14, 222, 155, 115, 101, + 206, 26, 49, 74, 0, 165, 128, 90, 125, 8, 103, 131, 214, 80, + 111, 248, 39, 247, 73, 235, 166, 120, 221, 33, 64, 65, 99, 255, + 239, 197, 4, 180, 8, 86, 144, 135, 246, 8, 145, 123, 151, 188, + 30, 217, 67, 67, 239, 64, 130, 146, 59, 242, 193, 221, 133, 183, + 249, 137, 184, 45, 19, 25, 181, 255, 196, 29, 63, 117, 139, 46, + 67, 103, 48, 184, 4, 24, 27, 158, 224, 191, 88, 198, 157, 182, + 143, 195, 40, 145, 157, 121, 85, 199, 23, 40, 176, 171, 204, 236, + 65, 142, 67, 142, 169, 37, 156, 33, 8, 80, 127, 49, 17, 213, + 242, 162, 1, 3, 215, 120, 71, 241, 171, 13, 15, 160, 166, 66, + 252, 220, 244, 219, 13, 246, 14, 90, 1, 8, 66, 209, 223, 190, + 9, 200, 95, 55, 245, 187, 15, 250, 228, 102, 250, 50, 137, 82, + 122, 104, 199, 97, 210, 148, 170, 208, 23, 119, 133, 81, 20, 109, + 83, 149, 7, 213, 81, 204, 150, 85, 228, 158, 89, 55, 197, 225, + 149, 254, 29, 141, 94, 225, 151, 23, 44, 97, 67, 248, 43, 135, + 44, 13, 185, 27, 135, 249, 253, 77, 56, 166, 250, 86, 14, 207, + 116, 110, 234, 150, 49, 244, 245, 119, 82, 156, 77, 126, 28, 3, + 217, 195, 174, 91, 41, 144, 253, 113, 199, 125, 30, 81, 64, 146, + 167, 49, 120, 220, 208, 133, 33, 142, 125, 194, 32, 177, 20, 161, + 229, 31, 186, 201, 91, 169, 17, 159, 156, 165, 174, 125, 69, 178, + 196, 182, 51, 235, 11, 44, 54, 76, 33, 107, 228, 237, 148, 182, + 87, 34, 158, 77, 58, 230, 66, 121, 191, 114, 38, 139, 192, 120, + 140, 62, 160, 9, 7, 14, 113, 210, 173, 78, 186, 163, 249, 231, + 56, 205, 42, 215, 236, 70, 175, 104, 24, 88, 221, 219, 133, 232, + 34, 227, 132, 136, 204, 18, 141, 111, 121, 104, 39, 212, 105, 163, + 90, 18, 60, 54, 221, 177, 102, 26, 111, 171, 157, 54, 78, 25, + 136, 148, 83, 175, 20, 157, 238, 96, 148, 136, 163, 107, 40, 42, + 219, 254, 60, 82, 81, 80, 172, 187, 217, 181, 216, 69, 74, 236, + 97, 116, 228, 16, 144, 80, 75, 200, 33, 31, 44, 92, 23, 211, + 112, 81, 47, 235, 226, 101, 159, 79, 2, 190, 228, 224, 124, 32, + 166, 117, 20, 166, 182, 144, 170, 235, 222, 243, 110, 173, 152, 255, + 60, 56, 24, 205, 72, 114, 87, 42, 33, 99, 68, 17, 190, 146, + 79, 167, 75, 235, 110, 158, 101, 18, 154, 101, 126, 131, 250, 237, + 177, 5, 194, 25, 162, 29, 98, 252, 84, 74, 17, 209, 43, 123, + 136, 203, 100, 151, 109, 197, 224, 237, 115, 150, 38, 26, 128, 236, + 122, 213, 135, 26, 171, 46, 44, 152, 213, 174, 157, 82, 73, 252, + 122, 46, 87, 210, 215, 8, 197, 21, 34, 89, 247, 125, 187, 180, + 0, 86, 38, 78, 253, 185, 49, 204, 179, 192, 27, 130, 7, 204, + 93, 125, 146, 235, 80, 1, 146, 112, 20, 7, 247, 204, 39, 127, + 121, 5, 3, 96, 94, 137, 90, 198, 197, 237, 234, 78, 52, 95, + 229, 166, 225, 94, 83, 100, 53, 148, 134, 229, 228, 148, 233, 47, + 126, 51, 145, 157, 2, 72, 70, 110, 183, 0, 236, 27, 190, 186, + 221, 231, 215, 82, 70, 11, 239, 158, 19, 175, 59, 42, 246, 95, + 92, 155, 80, 77, 153, 180, 110, 157, 4, 10, 21, 56, 73, 113, + 5, 236, 214, 36, 90, 189, 229, 88, 184, 75, 197, 135, 221, 198, + 254, 151, 59, 47, 48, 222, 91, 226, 144, 23, 66, 176, 250, 111, + 80, 233, 38, 244, 248, 235, 243, 165, 226, 85, 131, 228, 9, 154, + 42, 214, 209, 208, 155, 204, 161, 151, 9, 251, 51, 3, 28, 66, + 83, 2, 245, 141, 46, 85, 69, 234, 70, 152, 245, 82, 100, 6, + 218, 244, 12, 84, 216, 10, 28, 194, 61, 54, 143, 183, 160, 126, + 108, 177, 61, 225, 153, 181, 204, 117, 132, 249, 161, 170, 108, 222, + 247, 205, 191, 160, 190, 123, 214, 85, 227, 85, 21, 148, 166, 70, + 202, 170, 38, 123, 204, 164, 245, 72, 24, 36, 220, 134, 188, 181, + 61, 91, 128, 1, 20, 2, 0, 0, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 99, 108, 101, 97, + 114, 116, 111, 109, 97, 114, 107, 13, 128, 3, +}; diff --git a/Rendering/fonts/face_courier_bold_italic.cxx b/Rendering/fonts/face_courier_bold_italic.cxx new file mode 100644 index 0000000..81a2879 --- /dev/null +++ b/Rendering/fonts/face_courier_bold_italic.cxx @@ -0,0 +1,2858 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Courier Bold Italic +// Courier 10 Pitch Bold Italic (c0611bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_courier_bold_italic_buffer_length = 39871; + +unsigned char face_courier_bold_italic_buffer[] = { + 128, 1, 235, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 84, + 104, 117, 32, 78, 111, 118, 32, 32, 56, 32, 49, 57, 58, 51, + 55, 58, 50, 48, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 67, + 111, 117, 114, 105, 101, 114, 32, 49, 48, 32, 80, 105, 116, 99, + 104, 32, 66, 111, 108, 100, 32, 73, 116, 97, 108, 105, 99, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 97, 109, 105, 108, 121, 78, 97, 109, 101, 32, + 40, 67, 111, 117, 114, 105, 101, 114, 32, 49, 48, 32, 80, 105, + 116, 99, 104, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, + 100, 101, 102, 13, 32, 32, 47, 87, 101, 105, 103, 104, 116, 32, + 40, 66, 111, 108, 100, 41, 32, 114, 101, 97, 100, 111, 110, 108, + 121, 32, 100, 101, 102, 13, 32, 32, 47, 73, 116, 97, 108, 105, + 99, 65, 110, 103, 108, 101, 32, 32, 49, 50, 46, 48, 48, 48, + 48, 32, 100, 101, 102, 13, 32, 32, 47, 105, 115, 70, 105, 120, + 101, 100, 80, 105, 116, 99, 104, 32, 116, 114, 117, 101, 32, 100, + 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, + 101, 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 57, 55, 32, + 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, + 110, 101, 84, 104, 105, 99, 107, 110, 101, 115, 115, 32, 57, 51, + 32, 100, 101, 102, 13, 101, 110, 100, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 78, + 97, 109, 101, 32, 47, 67, 111, 117, 114, 105, 101, 114, 49, 48, + 80, 105, 116, 99, 104, 66, 84, 45, 66, 111, 108, 100, 73, 116, + 97, 108, 105, 99, 32, 100, 101, 102, 13, 47, 80, 97, 105, 110, + 116, 84, 121, 112, 101, 32, 48, 32, 100, 101, 102, 13, 47, 70, + 111, 110, 116, 84, 121, 112, 101, 32, 49, 32, 100, 101, 102, 13, + 47, 70, 111, 110, 116, 77, 97, 116, 114, 105, 120, 32, 91, 48, + 46, 48, 48, 49, 32, 48, 32, 48, 32, 48, 46, 48, 48, 49, + 32, 48, 32, 48, 93, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 13, 47, 69, 110, 99, 111, 100, 105, 110, 103, + 32, 83, 116, 97, 110, 100, 97, 114, 100, 69, 110, 99, 111, 100, + 105, 110, 103, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 66, + 66, 111, 120, 32, 123, 45, 55, 56, 32, 45, 51, 48, 57, 32, + 54, 54, 52, 32, 56, 55, 53, 125, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 47, 85, 110, 105, 113, 117, + 101, 73, 68, 32, 49, 53, 53, 51, 48, 54, 49, 49, 32, 100, + 101, 102, 13, 99, 117, 114, 114, 101, 110, 116, 100, 105, 99, 116, + 32, 101, 110, 100, 13, 99, 117, 114, 114, 101, 110, 116, 102, 105, + 108, 101, 32, 101, 101, 120, 101, 99, 13, 128, 2, 172, 147, 0, + 0, 162, 149, 24, 64, 131, 138, 65, 51, 131, 156, 169, 210, 46, + 43, 153, 242, 182, 28, 118, 124, 214, 117, 8, 10, 172, 252, 178, + 78, 25, 205, 19, 54, 115, 155, 182, 73, 148, 197, 103, 55, 9, + 11, 76, 236, 146, 201, 148, 95, 240, 116, 94, 247, 255, 198, 27, + 176, 169, 163, 184, 73, 231, 233, 135, 64, 229, 108, 11, 90, 247, + 135, 85, 156, 198, 149, 106, 179, 30, 51, 207, 133, 83, 213, 92, + 11, 14, 129, 142, 245, 236, 107, 244, 129, 98, 234, 196, 46, 115, + 128, 202, 146, 29, 174, 28, 130, 179, 143, 214, 188, 242, 0, 26, + 187, 93, 0, 26, 86, 21, 112, 148, 207, 226, 125, 143, 78, 172, + 150, 147, 232, 131, 114, 210, 3, 88, 180, 126, 12, 56, 118, 85, + 142, 191, 117, 122, 31, 188, 92, 28, 221, 246, 43, 60, 87, 191, + 114, 126, 241, 196, 135, 148, 34, 193, 66, 160, 132, 209, 199, 70, + 42, 194, 147, 224, 151, 250, 190, 58, 62, 207, 205, 130, 113, 242, + 89, 131, 59, 172, 121, 18, 112, 114, 24, 236, 154, 48, 99, 191, + 115, 133, 224, 45, 140, 16, 88, 172, 6, 223, 0, 179, 59, 140, + 1, 135, 104, 178, 120, 1, 14, 177, 73, 121, 168, 84, 43, 148, + 74, 57, 52, 176, 223, 84, 220, 167, 232, 191, 175, 194, 55, 218, + 60, 41, 152, 44, 135, 35, 178, 8, 142, 143, 219, 13, 145, 97, + 65, 109, 39, 177, 176, 136, 119, 26, 218, 66, 143, 7, 178, 135, + 154, 197, 123, 104, 62, 117, 45, 67, 101, 127, 33, 70, 231, 147, + 233, 204, 217, 44, 237, 88, 163, 74, 216, 24, 79, 152, 2, 22, + 179, 84, 173, 146, 149, 227, 164, 35, 24, 59, 167, 148, 230, 147, + 223, 95, 163, 65, 179, 42, 8, 191, 195, 209, 75, 190, 6, 111, + 102, 96, 90, 122, 228, 20, 60, 179, 190, 22, 194, 173, 41, 144, + 234, 51, 197, 64, 1, 224, 200, 21, 110, 109, 232, 171, 106, 77, + 64, 167, 19, 124, 87, 189, 41, 19, 211, 116, 16, 75, 111, 225, + 213, 132, 154, 251, 213, 82, 170, 161, 86, 250, 100, 209, 88, 242, + 40, 178, 206, 40, 52, 117, 57, 74, 9, 70, 233, 82, 171, 19, + 234, 235, 54, 154, 45, 30, 248, 134, 10, 234, 242, 171, 0, 105, + 135, 137, 49, 14, 96, 62, 94, 5, 38, 32, 208, 209, 135, 179, + 75, 79, 231, 200, 78, 167, 90, 184, 153, 121, 158, 198, 54, 132, + 151, 203, 139, 211, 187, 88, 70, 63, 164, 185, 122, 18, 53, 40, + 215, 226, 175, 150, 216, 34, 184, 150, 133, 114, 153, 17, 175, 242, + 1, 105, 154, 235, 27, 254, 130, 123, 48, 149, 161, 209, 163, 86, + 11, 145, 212, 173, 98, 203, 24, 50, 212, 154, 166, 86, 252, 124, + 190, 61, 166, 172, 196, 158, 211, 4, 47, 5, 94, 251, 129, 105, + 191, 13, 195, 150, 157, 209, 227, 60, 59, 253, 87, 45, 34, 26, + 37, 132, 223, 108, 191, 31, 167, 94, 240, 43, 119, 56, 91, 207, + 146, 141, 236, 13, 100, 150, 99, 242, 64, 116, 240, 172, 124, 177, + 178, 183, 238, 231, 188, 140, 104, 37, 207, 148, 217, 118, 223, 149, + 156, 123, 227, 84, 120, 219, 98, 230, 230, 56, 60, 88, 44, 150, + 199, 201, 252, 47, 176, 1, 196, 144, 110, 143, 86, 244, 69, 115, + 83, 230, 45, 206, 242, 0, 24, 113, 101, 245, 83, 236, 198, 165, + 144, 95, 236, 39, 126, 17, 118, 240, 182, 49, 34, 194, 232, 253, + 45, 102, 95, 75, 226, 247, 25, 100, 135, 63, 92, 7, 152, 98, + 226, 65, 133, 87, 133, 103, 187, 173, 136, 54, 89, 96, 33, 36, + 124, 19, 60, 232, 127, 180, 52, 44, 6, 251, 88, 131, 247, 55, + 125, 149, 245, 59, 18, 219, 126, 48, 122, 253, 86, 165, 50, 106, + 250, 170, 183, 22, 69, 83, 90, 58, 111, 226, 177, 79, 37, 250, + 7, 89, 84, 81, 179, 191, 22, 150, 75, 179, 63, 196, 210, 107, + 41, 222, 142, 26, 15, 91, 33, 196, 51, 140, 188, 139, 34, 127, + 43, 83, 65, 56, 161, 213, 181, 122, 20, 107, 70, 10, 191, 241, + 241, 135, 203, 52, 94, 169, 3, 19, 225, 156, 93, 146, 160, 22, + 36, 63, 81, 137, 82, 225, 45, 216, 122, 205, 253, 83, 191, 38, + 18, 221, 211, 213, 166, 187, 20, 19, 247, 117, 8, 200, 82, 100, + 165, 177, 87, 121, 227, 151, 124, 76, 115, 7, 154, 66, 87, 63, + 234, 69, 221, 186, 70, 243, 211, 242, 75, 197, 33, 206, 23, 158, + 90, 147, 26, 154, 250, 89, 93, 117, 216, 5, 149, 114, 75, 0, + 69, 78, 96, 40, 169, 92, 18, 30, 44, 157, 208, 23, 249, 203, + 98, 29, 10, 23, 189, 195, 65, 245, 103, 106, 183, 167, 77, 8, + 225, 177, 88, 164, 0, 160, 47, 174, 54, 79, 7, 134, 250, 139, + 95, 54, 43, 255, 180, 106, 77, 59, 13, 2, 97, 120, 217, 101, + 0, 38, 17, 203, 76, 64, 146, 28, 192, 124, 190, 80, 48, 136, + 60, 17, 60, 46, 122, 160, 173, 72, 68, 252, 121, 112, 142, 215, + 75, 11, 123, 104, 186, 83, 132, 210, 202, 249, 24, 96, 45, 214, + 99, 64, 220, 43, 208, 221, 223, 193, 161, 203, 211, 215, 158, 144, + 100, 177, 238, 38, 216, 189, 250, 81, 115, 20, 130, 65, 217, 62, + 227, 141, 32, 243, 111, 174, 47, 138, 221, 108, 204, 70, 156, 50, + 173, 223, 104, 16, 23, 8, 215, 95, 125, 97, 216, 143, 23, 150, + 148, 26, 144, 58, 158, 240, 8, 70, 125, 185, 255, 197, 98, 127, + 244, 167, 98, 233, 41, 79, 132, 62, 254, 132, 127, 240, 187, 77, + 227, 201, 47, 159, 187, 225, 94, 83, 246, 244, 186, 179, 172, 200, + 116, 123, 202, 201, 126, 22, 19, 205, 252, 49, 233, 201, 55, 222, + 198, 224, 212, 53, 119, 245, 125, 92, 225, 43, 145, 161, 46, 28, + 5, 154, 66, 185, 204, 187, 4, 227, 169, 37, 52, 119, 163, 26, + 13, 141, 51, 166, 15, 180, 14, 26, 145, 107, 236, 165, 10, 139, + 20, 91, 123, 98, 173, 123, 18, 54, 75, 5, 107, 64, 115, 84, + 125, 121, 42, 1, 72, 136, 84, 177, 119, 95, 172, 36, 17, 151, + 130, 115, 102, 107, 26, 173, 119, 197, 232, 131, 90, 254, 181, 183, + 63, 235, 168, 230, 207, 165, 158, 145, 218, 80, 207, 20, 72, 63, + 2, 60, 14, 7, 235, 131, 6, 1, 44, 16, 115, 36, 243, 206, + 135, 60, 17, 195, 141, 80, 68, 45, 59, 15, 254, 162, 36, 242, + 238, 63, 75, 27, 114, 43, 47, 108, 44, 203, 2, 180, 62, 155, + 131, 34, 206, 0, 131, 179, 192, 203, 190, 249, 221, 196, 159, 159, + 37, 122, 72, 128, 154, 250, 30, 130, 6, 10, 174, 16, 147, 201, + 189, 195, 80, 55, 161, 218, 68, 26, 248, 66, 238, 56, 2, 123, + 245, 0, 198, 124, 105, 150, 105, 2, 194, 205, 7, 98, 58, 251, + 71, 76, 235, 81, 98, 151, 71, 132, 56, 197, 22, 189, 35, 250, + 146, 78, 107, 150, 15, 138, 97, 9, 17, 96, 223, 212, 169, 115, + 222, 249, 218, 45, 81, 103, 215, 193, 110, 80, 196, 67, 77, 209, + 219, 203, 197, 218, 249, 253, 63, 206, 227, 21, 136, 30, 34, 177, + 154, 59, 221, 96, 65, 60, 132, 145, 135, 73, 74, 78, 128, 255, + 22, 70, 24, 169, 155, 225, 49, 144, 201, 0, 18, 112, 109, 174, + 203, 114, 109, 173, 184, 206, 162, 91, 182, 76, 88, 184, 48, 88, + 22, 207, 131, 104, 55, 29, 82, 207, 252, 222, 105, 191, 148, 2, + 250, 105, 121, 66, 110, 37, 82, 128, 49, 91, 203, 227, 110, 69, + 241, 34, 234, 201, 53, 223, 138, 131, 114, 243, 91, 251, 96, 128, + 0, 26, 186, 12, 57, 254, 223, 43, 90, 141, 78, 174, 17, 120, + 84, 109, 238, 84, 1, 226, 122, 161, 179, 134, 183, 129, 214, 75, + 77, 220, 182, 79, 60, 205, 4, 219, 255, 81, 245, 160, 52, 109, + 64, 229, 161, 234, 55, 3, 145, 144, 129, 22, 12, 4, 125, 234, + 22, 40, 178, 115, 115, 82, 76, 63, 153, 244, 146, 217, 132, 23, + 235, 147, 14, 34, 41, 210, 142, 189, 8, 37, 72, 114, 77, 79, + 202, 130, 77, 177, 214, 202, 20, 195, 66, 163, 137, 101, 179, 159, + 158, 80, 128, 112, 197, 232, 228, 164, 200, 145, 151, 79, 45, 10, + 201, 126, 48, 8, 201, 48, 212, 178, 190, 242, 51, 105, 103, 88, + 120, 199, 237, 80, 201, 201, 121, 126, 18, 13, 167, 2, 72, 106, + 68, 65, 95, 35, 91, 208, 86, 213, 152, 21, 104, 63, 78, 105, + 43, 142, 132, 107, 191, 178, 179, 78, 231, 209, 37, 214, 73, 191, + 153, 216, 96, 188, 123, 248, 155, 121, 27, 243, 20, 27, 255, 17, + 55, 124, 114, 10, 23, 212, 79, 49, 130, 247, 112, 173, 10, 93, + 46, 69, 6, 13, 16, 216, 244, 75, 41, 197, 253, 39, 43, 16, + 123, 224, 161, 247, 185, 71, 113, 113, 33, 36, 52, 146, 120, 62, + 142, 43, 226, 189, 61, 141, 102, 52, 46, 65, 196, 168, 127, 41, + 239, 215, 150, 60, 175, 178, 128, 246, 117, 110, 113, 82, 174, 249, + 220, 222, 195, 113, 160, 247, 186, 198, 21, 126, 95, 161, 107, 32, + 81, 227, 150, 200, 81, 22, 169, 211, 238, 242, 3, 133, 41, 35, + 131, 3, 243, 182, 192, 117, 88, 28, 135, 12, 70, 253, 135, 12, + 99, 35, 149, 188, 245, 27, 124, 108, 24, 249, 252, 140, 121, 177, + 180, 244, 194, 214, 190, 99, 93, 86, 117, 102, 186, 64, 86, 231, + 124, 193, 201, 49, 72, 71, 80, 99, 75, 204, 15, 40, 79, 236, + 29, 30, 153, 148, 64, 45, 251, 142, 105, 141, 172, 214, 19, 46, + 161, 147, 99, 250, 66, 55, 109, 200, 66, 252, 45, 192, 80, 77, + 69, 138, 87, 54, 152, 119, 52, 28, 25, 214, 99, 1, 72, 136, + 76, 98, 127, 112, 161, 75, 174, 22, 17, 244, 146, 135, 58, 240, + 63, 24, 49, 7, 160, 103, 188, 95, 249, 174, 65, 152, 235, 204, + 200, 102, 58, 17, 22, 125, 237, 140, 48, 36, 32, 29, 163, 176, + 71, 63, 79, 170, 76, 156, 174, 225, 97, 140, 121, 174, 211, 253, + 181, 179, 9, 192, 104, 35, 226, 124, 125, 25, 138, 202, 243, 145, + 31, 70, 116, 57, 158, 187, 115, 20, 142, 136, 125, 60, 208, 209, + 54, 40, 68, 145, 207, 68, 255, 252, 113, 46, 62, 69, 111, 155, + 246, 69, 171, 182, 186, 14, 95, 17, 123, 74, 56, 82, 244, 45, + 168, 209, 217, 138, 96, 149, 45, 147, 173, 69, 4, 234, 233, 72, + 239, 12, 225, 210, 243, 54, 225, 139, 125, 39, 67, 223, 206, 33, + 147, 249, 101, 83, 35, 115, 70, 117, 111, 146, 176, 55, 58, 18, + 41, 198, 125, 91, 187, 232, 92, 163, 185, 223, 172, 79, 193, 211, + 78, 147, 108, 215, 234, 128, 162, 245, 217, 29, 37, 77, 15, 255, + 142, 209, 52, 90, 189, 72, 182, 171, 108, 224, 230, 219, 236, 109, + 245, 106, 195, 133, 20, 69, 45, 95, 39, 46, 221, 68, 178, 220, + 223, 102, 75, 166, 219, 44, 137, 94, 120, 123, 95, 56, 65, 129, + 102, 239, 34, 212, 227, 239, 96, 160, 201, 128, 54, 92, 110, 212, + 197, 96, 182, 75, 95, 108, 141, 205, 20, 74, 244, 162, 218, 159, + 52, 161, 177, 76, 51, 250, 250, 108, 213, 113, 15, 194, 23, 46, + 137, 72, 10, 15, 248, 133, 110, 209, 174, 217, 43, 86, 60, 31, + 223, 33, 205, 135, 182, 22, 93, 216, 90, 227, 243, 103, 69, 37, + 225, 125, 133, 151, 16, 147, 225, 16, 85, 184, 229, 132, 174, 162, + 75, 237, 162, 36, 248, 51, 1, 245, 159, 91, 199, 236, 84, 126, + 20, 199, 144, 55, 96, 121, 124, 20, 46, 220, 3, 160, 41, 78, + 220, 251, 52, 74, 163, 118, 112, 114, 227, 207, 109, 204, 146, 74, + 47, 6, 114, 81, 230, 252, 45, 166, 237, 15, 195, 80, 220, 181, + 50, 170, 192, 214, 149, 111, 246, 205, 189, 231, 56, 25, 182, 97, + 129, 82, 163, 156, 220, 44, 67, 206, 43, 211, 198, 1, 166, 188, + 46, 147, 51, 156, 192, 151, 106, 124, 63, 139, 87, 53, 212, 62, + 49, 2, 206, 156, 83, 123, 205, 239, 68, 22, 84, 21, 62, 164, + 7, 91, 109, 127, 56, 20, 88, 221, 125, 230, 201, 178, 218, 102, + 188, 181, 92, 221, 76, 44, 106, 131, 69, 80, 82, 78, 230, 122, + 65, 206, 80, 60, 169, 115, 67, 3, 7, 137, 101, 103, 38, 223, + 59, 69, 94, 76, 110, 218, 232, 136, 237, 19, 26, 52, 124, 223, + 180, 86, 98, 142, 86, 190, 36, 169, 240, 57, 137, 37, 254, 54, + 227, 224, 5, 35, 175, 38, 208, 1, 157, 176, 15, 51, 12, 251, + 6, 73, 110, 249, 180, 80, 65, 142, 47, 192, 137, 235, 203, 116, + 43, 123, 36, 235, 39, 138, 182, 162, 225, 70, 64, 117, 207, 57, + 133, 225, 63, 107, 197, 106, 120, 232, 200, 220, 232, 1, 56, 231, + 67, 78, 72, 206, 254, 164, 199, 182, 86, 75, 127, 67, 207, 218, + 187, 27, 202, 111, 238, 205, 146, 62, 104, 0, 16, 153, 83, 96, + 234, 36, 154, 58, 214, 6, 250, 238, 102, 83, 52, 56, 120, 37, + 182, 212, 158, 69, 65, 166, 77, 97, 107, 178, 212, 56, 176, 221, + 38, 31, 152, 250, 237, 97, 92, 237, 208, 242, 137, 123, 213, 100, + 149, 38, 249, 53, 95, 248, 198, 209, 84, 154, 138, 232, 28, 89, + 82, 156, 125, 217, 136, 199, 63, 185, 31, 134, 209, 139, 235, 220, + 230, 24, 247, 158, 140, 179, 65, 226, 224, 125, 208, 253, 91, 172, + 238, 216, 95, 101, 85, 223, 170, 116, 147, 63, 145, 188, 57, 151, + 9, 50, 151, 203, 210, 233, 158, 191, 180, 28, 72, 182, 71, 156, + 133, 34, 69, 254, 67, 187, 200, 18, 116, 221, 64, 46, 13, 66, + 135, 110, 188, 198, 74, 59, 99, 207, 121, 173, 84, 253, 210, 223, + 223, 165, 23, 111, 148, 140, 108, 23, 163, 208, 30, 41, 22, 58, + 168, 69, 119, 97, 165, 41, 49, 242, 94, 242, 29, 76, 184, 66, + 146, 105, 26, 5, 28, 27, 54, 35, 21, 61, 67, 251, 53, 126, + 115, 1, 212, 96, 92, 69, 181, 18, 229, 114, 193, 230, 227, 172, + 10, 102, 89, 43, 212, 72, 119, 71, 76, 246, 230, 23, 58, 120, + 232, 18, 74, 77, 50, 31, 44, 221, 52, 180, 129, 217, 201, 18, + 181, 98, 84, 180, 126, 130, 5, 48, 178, 36, 10, 110, 23, 243, + 89, 60, 214, 112, 61, 126, 212, 94, 27, 249, 44, 50, 106, 174, + 139, 55, 60, 180, 12, 184, 196, 92, 204, 1, 102, 57, 240, 88, + 16, 124, 105, 159, 54, 73, 172, 218, 226, 241, 244, 244, 57, 167, + 123, 164, 101, 146, 175, 62, 200, 176, 96, 86, 204, 237, 229, 26, + 48, 191, 51, 198, 89, 176, 252, 15, 62, 212, 206, 54, 72, 67, + 96, 245, 220, 63, 228, 105, 3, 196, 85, 245, 215, 165, 34, 53, + 158, 156, 158, 83, 238, 234, 6, 220, 212, 120, 61, 57, 53, 152, + 50, 32, 121, 100, 110, 98, 68, 111, 177, 147, 163, 224, 199, 18, + 200, 7, 200, 172, 140, 248, 1, 192, 8, 228, 153, 110, 144, 146, + 160, 234, 191, 132, 145, 122, 220, 105, 20, 94, 48, 218, 98, 20, + 40, 185, 0, 208, 29, 8, 207, 114, 220, 6, 70, 39, 49, 90, + 122, 54, 6, 67, 139, 228, 3, 139, 56, 27, 231, 26, 136, 175, + 123, 94, 50, 184, 226, 169, 146, 242, 12, 17, 76, 33, 252, 155, + 12, 75, 82, 212, 175, 95, 72, 45, 105, 68, 166, 187, 48, 243, + 36, 28, 120, 174, 117, 143, 85, 220, 43, 222, 108, 99, 236, 227, + 94, 92, 253, 96, 63, 108, 20, 7, 202, 42, 82, 247, 10, 85, + 3, 121, 254, 119, 168, 9, 14, 229, 99, 53, 94, 122, 172, 218, + 251, 239, 121, 153, 150, 87, 184, 176, 8, 141, 174, 5, 64, 215, + 101, 211, 10, 203, 81, 80, 4, 128, 57, 37, 98, 32, 84, 32, + 94, 142, 83, 49, 155, 111, 119, 80, 97, 62, 44, 108, 27, 145, + 182, 101, 125, 122, 52, 4, 92, 200, 171, 32, 11, 158, 44, 139, + 46, 30, 61, 204, 140, 157, 70, 203, 217, 244, 76, 43, 134, 88, + 246, 254, 106, 223, 120, 248, 54, 194, 116, 237, 77, 21, 146, 112, + 225, 169, 39, 3, 113, 114, 90, 126, 45, 142, 217, 125, 88, 123, + 218, 89, 176, 36, 27, 49, 28, 226, 4, 190, 124, 121, 90, 177, + 160, 147, 26, 16, 140, 24, 47, 210, 247, 124, 64, 6, 73, 50, + 181, 67, 192, 94, 23, 128, 100, 249, 32, 25, 211, 164, 211, 219, + 121, 203, 203, 83, 229, 183, 182, 82, 39, 117, 24, 114, 23, 40, + 27, 118, 195, 47, 93, 44, 111, 152, 252, 252, 209, 145, 89, 140, + 203, 218, 216, 143, 208, 109, 124, 251, 9, 32, 253, 126, 215, 61, + 191, 196, 108, 137, 148, 0, 108, 189, 126, 131, 129, 216, 175, 35, + 131, 107, 237, 125, 29, 157, 166, 122, 180, 146, 191, 251, 154, 219, + 148, 17, 217, 239, 19, 13, 166, 131, 88, 64, 166, 61, 62, 194, + 130, 113, 223, 67, 51, 85, 219, 217, 78, 138, 4, 188, 52, 144, + 1, 150, 9, 125, 14, 175, 104, 7, 78, 47, 180, 174, 185, 163, + 203, 105, 144, 12, 56, 227, 96, 10, 143, 157, 147, 127, 158, 92, + 94, 219, 217, 166, 189, 102, 85, 79, 28, 51, 82, 180, 153, 174, + 124, 201, 197, 188, 151, 227, 22, 3, 110, 124, 219, 150, 51, 222, + 30, 45, 111, 243, 239, 159, 117, 188, 157, 149, 169, 192, 77, 241, + 101, 175, 105, 3, 103, 129, 167, 194, 123, 42, 59, 98, 36, 6, + 46, 181, 115, 8, 2, 193, 48, 242, 225, 150, 173, 36, 170, 4, + 140, 224, 174, 43, 116, 128, 100, 5, 198, 35, 164, 207, 197, 185, + 26, 226, 32, 37, 46, 113, 113, 212, 92, 72, 16, 13, 67, 34, + 221, 120, 68, 23, 124, 165, 202, 169, 160, 17, 162, 31, 11, 195, + 198, 186, 113, 163, 127, 1, 138, 61, 21, 52, 157, 207, 175, 105, + 140, 218, 24, 230, 188, 168, 182, 154, 48, 215, 114, 39, 108, 51, + 125, 115, 47, 100, 116, 122, 75, 148, 10, 112, 32, 151, 184, 80, + 136, 43, 98, 68, 155, 47, 97, 4, 162, 102, 119, 110, 137, 158, + 250, 11, 177, 250, 156, 247, 244, 150, 43, 186, 10, 12, 87, 247, + 241, 187, 20, 96, 214, 203, 134, 28, 69, 68, 249, 158, 225, 230, + 70, 163, 54, 143, 85, 52, 21, 41, 216, 17, 174, 141, 138, 42, + 221, 134, 159, 98, 18, 92, 134, 165, 171, 4, 99, 135, 74, 123, + 250, 45, 180, 143, 35, 128, 193, 65, 156, 87, 246, 64, 93, 55, + 4, 37, 29, 180, 233, 228, 133, 221, 141, 91, 218, 62, 62, 4, + 125, 175, 15, 31, 101, 58, 248, 150, 9, 40, 224, 165, 33, 113, + 51, 32, 123, 210, 244, 129, 198, 157, 102, 152, 198, 224, 164, 85, + 165, 225, 237, 83, 0, 96, 21, 254, 22, 16, 81, 48, 21, 133, + 227, 177, 94, 120, 56, 112, 12, 234, 94, 89, 159, 239, 158, 184, + 46, 2, 189, 98, 211, 16, 76, 243, 46, 175, 221, 105, 225, 175, + 179, 118, 57, 152, 214, 19, 103, 58, 244, 106, 226, 59, 231, 182, + 234, 208, 12, 168, 128, 131, 232, 72, 43, 239, 177, 117, 14, 63, + 199, 60, 24, 155, 3, 90, 86, 12, 107, 24, 1, 165, 224, 96, + 52, 141, 128, 254, 109, 57, 91, 218, 196, 186, 24, 44, 122, 84, + 109, 120, 54, 85, 126, 204, 220, 27, 254, 81, 162, 209, 51, 154, + 70, 56, 107, 140, 11, 252, 179, 35, 14, 90, 23, 249, 28, 31, + 247, 104, 109, 152, 13, 34, 226, 124, 22, 251, 122, 43, 81, 180, + 56, 87, 47, 13, 155, 100, 250, 38, 161, 136, 219, 30, 91, 171, + 137, 126, 29, 75, 60, 62, 121, 60, 221, 141, 138, 233, 142, 70, + 67, 41, 20, 40, 54, 139, 138, 96, 228, 148, 231, 227, 211, 31, + 255, 50, 192, 151, 250, 56, 26, 44, 77, 148, 209, 227, 75, 192, + 176, 127, 105, 152, 130, 109, 20, 228, 243, 221, 189, 102, 164, 234, + 238, 248, 203, 225, 20, 159, 224, 7, 36, 93, 158, 30, 60, 206, + 48, 107, 138, 103, 31, 120, 249, 240, 58, 122, 71, 148, 213, 160, + 172, 243, 53, 175, 102, 210, 107, 154, 14, 194, 148, 164, 160, 174, + 106, 251, 215, 131, 208, 124, 18, 79, 126, 116, 199, 182, 55, 0, + 247, 85, 134, 136, 200, 162, 132, 61, 194, 101, 234, 129, 54, 65, + 199, 97, 149, 196, 175, 109, 117, 4, 158, 132, 243, 146, 13, 57, + 51, 59, 154, 125, 101, 244, 88, 26, 139, 96, 203, 16, 30, 151, + 51, 196, 146, 231, 120, 7, 60, 88, 107, 184, 56, 13, 44, 249, + 239, 217, 231, 46, 226, 190, 91, 91, 147, 137, 150, 235, 148, 199, + 110, 5, 170, 110, 77, 201, 66, 110, 144, 184, 246, 155, 195, 171, + 126, 136, 209, 121, 86, 241, 179, 10, 248, 79, 46, 183, 196, 169, + 105, 180, 85, 6, 93, 47, 117, 189, 131, 83, 193, 155, 137, 196, + 53, 16, 11, 199, 105, 171, 232, 105, 21, 188, 188, 13, 237, 102, + 39, 46, 74, 234, 163, 224, 88, 54, 32, 74, 144, 118, 6, 249, + 167, 159, 251, 5, 207, 231, 250, 5, 179, 148, 164, 34, 223, 149, + 213, 196, 198, 162, 186, 234, 8, 25, 194, 172, 180, 123, 241, 204, + 56, 167, 65, 109, 71, 90, 239, 179, 243, 111, 181, 80, 218, 31, + 13, 248, 20, 119, 250, 94, 104, 28, 238, 27, 136, 133, 196, 97, + 178, 205, 79, 74, 76, 200, 77, 111, 87, 192, 255, 65, 39, 202, + 173, 17, 226, 179, 195, 100, 52, 14, 221, 37, 188, 193, 194, 6, + 83, 80, 199, 174, 34, 86, 225, 159, 194, 198, 204, 70, 230, 239, + 228, 43, 223, 250, 135, 27, 60, 209, 184, 165, 252, 130, 107, 164, + 116, 93, 96, 107, 212, 218, 146, 89, 191, 10, 147, 170, 250, 31, + 173, 30, 254, 61, 31, 141, 234, 114, 144, 245, 149, 50, 121, 253, + 217, 52, 255, 212, 219, 119, 19, 47, 129, 211, 3, 175, 167, 126, + 233, 224, 53, 24, 68, 71, 212, 140, 171, 96, 72, 155, 166, 143, + 236, 156, 23, 237, 197, 204, 136, 46, 194, 63, 214, 243, 171, 150, + 210, 29, 55, 18, 250, 206, 197, 98, 64, 218, 97, 234, 210, 165, + 144, 237, 194, 0, 162, 52, 80, 131, 96, 174, 217, 6, 206, 27, + 75, 14, 16, 28, 90, 108, 115, 143, 197, 36, 166, 235, 27, 162, + 131, 146, 131, 54, 71, 157, 242, 110, 136, 161, 208, 22, 172, 134, + 230, 173, 201, 138, 116, 160, 84, 224, 59, 52, 194, 191, 61, 207, + 248, 141, 19, 18, 20, 201, 159, 173, 61, 255, 19, 161, 94, 53, + 110, 223, 75, 34, 217, 77, 176, 204, 191, 71, 82, 43, 145, 102, + 22, 253, 219, 51, 116, 114, 123, 53, 222, 206, 221, 192, 84, 203, + 12, 75, 228, 136, 127, 184, 232, 194, 67, 116, 217, 182, 97, 177, + 91, 80, 237, 246, 201, 221, 200, 18, 251, 213, 107, 243, 39, 226, + 127, 206, 13, 146, 2, 225, 145, 204, 218, 192, 199, 2, 221, 181, + 219, 68, 17, 234, 229, 26, 87, 36, 144, 121, 59, 237, 234, 9, + 165, 106, 94, 22, 35, 79, 27, 196, 57, 65, 217, 86, 47, 186, + 232, 81, 101, 235, 14, 237, 214, 116, 0, 187, 44, 149, 186, 2, + 108, 215, 251, 159, 200, 94, 103, 62, 223, 228, 117, 171, 0, 123, + 29, 138, 164, 15, 124, 49, 61, 139, 11, 189, 7, 137, 211, 134, + 207, 212, 123, 151, 226, 84, 52, 164, 89, 235, 139, 200, 93, 18, + 235, 226, 168, 189, 146, 240, 14, 66, 27, 241, 217, 57, 120, 212, + 140, 78, 17, 71, 115, 52, 207, 74, 143, 12, 14, 12, 3, 14, + 196, 146, 52, 119, 230, 41, 66, 40, 251, 48, 147, 191, 186, 237, + 138, 73, 183, 96, 243, 182, 18, 48, 198, 133, 209, 110, 241, 168, + 225, 201, 2, 77, 185, 157, 5, 2, 235, 203, 122, 234, 19, 55, + 75, 159, 2, 190, 211, 241, 171, 37, 55, 215, 18, 221, 163, 79, + 25, 133, 95, 42, 231, 129, 224, 62, 241, 51, 117, 217, 129, 142, + 243, 83, 20, 82, 55, 206, 167, 116, 185, 82, 253, 154, 230, 128, + 64, 26, 245, 53, 45, 131, 29, 212, 60, 10, 163, 135, 184, 200, + 109, 16, 169, 246, 156, 177, 145, 224, 21, 224, 118, 155, 144, 148, + 233, 182, 54, 68, 50, 95, 165, 40, 151, 14, 239, 252, 188, 67, + 45, 195, 34, 61, 6, 235, 34, 186, 69, 61, 225, 143, 228, 200, + 44, 178, 166, 213, 32, 20, 18, 56, 114, 107, 59, 9, 114, 81, + 206, 134, 212, 147, 221, 212, 190, 249, 40, 187, 91, 172, 114, 40, + 62, 83, 217, 67, 246, 168, 202, 14, 23, 190, 228, 199, 6, 51, + 39, 170, 140, 167, 37, 32, 104, 29, 82, 46, 224, 135, 156, 228, + 134, 62, 171, 243, 29, 240, 38, 21, 88, 178, 201, 249, 47, 125, + 17, 11, 253, 197, 234, 41, 71, 173, 20, 166, 38, 141, 6, 185, + 94, 192, 211, 94, 66, 64, 99, 29, 112, 48, 200, 33, 176, 45, + 22, 175, 15, 29, 207, 251, 98, 141, 103, 235, 137, 70, 104, 82, + 177, 19, 231, 202, 210, 41, 36, 112, 74, 118, 164, 174, 154, 135, + 189, 147, 91, 207, 25, 107, 78, 226, 178, 69, 175, 233, 2, 81, + 29, 118, 64, 184, 142, 130, 113, 186, 78, 168, 62, 99, 8, 114, + 178, 60, 146, 144, 56, 36, 65, 49, 14, 116, 66, 247, 121, 251, + 188, 129, 221, 203, 178, 177, 253, 75, 119, 178, 1, 150, 80, 42, + 99, 217, 136, 124, 160, 116, 202, 150, 83, 71, 174, 73, 242, 14, + 122, 223, 30, 167, 140, 159, 100, 192, 100, 86, 165, 84, 254, 6, + 39, 101, 99, 34, 31, 178, 47, 5, 166, 143, 18, 34, 137, 76, + 188, 96, 211, 146, 223, 29, 104, 77, 167, 65, 240, 91, 146, 137, + 135, 235, 68, 48, 12, 106, 91, 176, 187, 206, 59, 114, 107, 67, + 79, 130, 84, 178, 91, 188, 211, 122, 92, 26, 178, 23, 232, 143, + 55, 133, 165, 171, 189, 122, 86, 8, 153, 42, 94, 90, 225, 199, + 103, 113, 13, 196, 234, 241, 173, 205, 228, 107, 101, 183, 188, 101, + 97, 38, 5, 107, 231, 240, 210, 143, 206, 21, 30, 189, 16, 178, + 220, 70, 189, 53, 72, 79, 197, 175, 108, 105, 22, 45, 233, 106, + 53, 171, 73, 166, 49, 8, 121, 118, 14, 98, 5, 39, 163, 6, + 47, 140, 169, 186, 236, 240, 167, 163, 198, 55, 235, 70, 4, 1, + 23, 115, 87, 91, 10, 119, 214, 185, 43, 208, 149, 140, 181, 20, + 201, 144, 2, 247, 47, 215, 87, 206, 36, 114, 241, 67, 176, 200, + 4, 66, 103, 131, 66, 46, 71, 88, 76, 236, 36, 173, 139, 102, + 200, 169, 88, 93, 12, 40, 128, 172, 181, 66, 48, 102, 85, 51, + 227, 64, 6, 59, 14, 73, 55, 243, 109, 7, 233, 74, 225, 247, + 174, 137, 80, 225, 140, 129, 24, 254, 91, 156, 1, 40, 130, 79, + 178, 136, 20, 240, 4, 187, 225, 28, 61, 5, 185, 1, 232, 209, + 60, 81, 53, 104, 97, 176, 35, 56, 90, 107, 147, 172, 54, 179, + 214, 95, 176, 153, 131, 115, 151, 1, 41, 208, 125, 165, 248, 142, + 58, 185, 24, 73, 126, 247, 56, 223, 204, 132, 242, 111, 231, 187, + 0, 135, 247, 198, 199, 197, 1, 207, 25, 245, 112, 116, 117, 127, + 75, 84, 172, 181, 17, 121, 165, 120, 150, 160, 193, 109, 240, 251, + 90, 91, 118, 17, 214, 171, 169, 101, 157, 53, 57, 22, 190, 211, + 85, 168, 151, 19, 92, 120, 221, 125, 215, 227, 32, 69, 249, 115, + 135, 12, 179, 194, 13, 155, 97, 179, 240, 185, 231, 70, 100, 103, + 110, 63, 174, 225, 77, 35, 176, 224, 43, 213, 208, 3, 255, 196, + 171, 64, 34, 181, 126, 254, 158, 97, 143, 205, 245, 24, 240, 122, + 67, 172, 73, 18, 146, 229, 115, 238, 213, 87, 255, 241, 116, 3, + 12, 108, 95, 218, 208, 117, 51, 176, 9, 225, 130, 158, 239, 31, + 112, 78, 222, 10, 105, 58, 33, 41, 148, 147, 189, 229, 78, 206, + 24, 195, 152, 140, 135, 168, 199, 12, 181, 94, 7, 47, 77, 151, + 199, 234, 88, 192, 130, 173, 133, 223, 0, 221, 87, 84, 53, 40, + 194, 242, 185, 186, 117, 252, 4, 206, 66, 254, 151, 110, 121, 3, + 112, 100, 236, 231, 20, 33, 203, 171, 20, 229, 142, 234, 89, 195, + 223, 230, 244, 63, 3, 237, 249, 186, 211, 162, 247, 123, 169, 13, + 218, 219, 93, 130, 245, 71, 240, 227, 178, 195, 28, 59, 237, 156, + 226, 44, 251, 182, 141, 247, 77, 57, 142, 151, 250, 144, 247, 150, + 251, 18, 150, 249, 252, 225, 27, 5, 191, 255, 182, 69, 82, 170, + 62, 66, 187, 250, 5, 87, 95, 162, 145, 230, 5, 186, 72, 50, + 56, 14, 9, 93, 227, 31, 176, 43, 157, 53, 194, 155, 150, 42, + 101, 240, 86, 80, 5, 204, 222, 12, 218, 144, 30, 135, 137, 13, + 7, 165, 49, 167, 247, 201, 13, 246, 122, 228, 79, 117, 229, 84, + 239, 229, 227, 209, 132, 65, 117, 69, 126, 64, 230, 215, 64, 143, + 67, 199, 19, 254, 160, 145, 180, 68, 81, 96, 39, 192, 249, 20, + 143, 74, 228, 101, 50, 227, 233, 237, 248, 183, 186, 186, 191, 84, + 31, 178, 227, 58, 126, 211, 175, 202, 8, 135, 135, 134, 37, 0, + 52, 84, 28, 223, 236, 184, 47, 190, 222, 15, 104, 79, 107, 180, + 178, 159, 78, 194, 111, 99, 244, 114, 212, 44, 92, 239, 208, 16, + 81, 57, 91, 250, 44, 178, 47, 160, 97, 211, 49, 174, 243, 255, + 119, 4, 95, 201, 45, 74, 232, 145, 21, 85, 178, 171, 64, 246, + 142, 101, 5, 21, 149, 159, 56, 74, 246, 85, 129, 156, 183, 216, + 137, 104, 183, 23, 240, 160, 255, 111, 191, 6, 161, 126, 89, 72, + 37, 164, 231, 117, 83, 249, 199, 87, 138, 150, 107, 127, 49, 176, + 84, 32, 10, 133, 193, 197, 137, 86, 149, 168, 50, 123, 112, 54, + 240, 226, 89, 57, 21, 219, 2, 55, 176, 79, 119, 97, 50, 209, + 46, 254, 6, 22, 177, 185, 106, 86, 241, 74, 166, 59, 18, 115, + 74, 117, 32, 27, 42, 9, 3, 175, 109, 93, 94, 28, 234, 140, + 220, 239, 99, 206, 244, 78, 252, 87, 172, 230, 253, 25, 44, 180, + 97, 106, 201, 65, 190, 107, 164, 162, 248, 199, 78, 127, 17, 136, + 172, 39, 252, 152, 179, 191, 102, 102, 146, 9, 23, 38, 37, 19, + 39, 189, 157, 126, 88, 7, 251, 58, 3, 25, 159, 5, 148, 77, + 102, 141, 102, 167, 161, 212, 115, 178, 136, 209, 25, 89, 227, 226, + 182, 229, 75, 34, 132, 112, 44, 95, 107, 236, 91, 209, 232, 3, + 229, 164, 145, 164, 211, 37, 37, 196, 164, 225, 144, 28, 72, 151, + 59, 225, 166, 242, 130, 69, 140, 41, 10, 97, 184, 20, 128, 194, + 62, 147, 130, 13, 94, 252, 73, 13, 238, 218, 146, 110, 16, 88, + 163, 101, 70, 65, 66, 174, 86, 49, 213, 255, 131, 85, 131, 243, + 75, 104, 123, 71, 110, 224, 112, 144, 26, 160, 224, 215, 241, 1, + 0, 241, 135, 160, 88, 153, 71, 152, 246, 169, 186, 35, 247, 36, + 89, 52, 185, 230, 67, 27, 198, 12, 9, 203, 223, 247, 131, 216, + 252, 147, 113, 65, 228, 179, 117, 34, 20, 63, 166, 25, 248, 215, + 249, 68, 240, 30, 98, 76, 31, 237, 42, 208, 167, 184, 46, 48, + 54, 174, 95, 38, 128, 178, 93, 141, 40, 91, 249, 247, 37, 42, + 7, 31, 197, 187, 210, 6, 206, 21, 167, 95, 95, 74, 100, 226, + 10, 115, 226, 232, 6, 69, 7, 123, 200, 135, 187, 150, 212, 236, + 177, 116, 193, 103, 161, 167, 160, 129, 120, 135, 229, 109, 36, 162, + 178, 190, 247, 25, 187, 36, 175, 180, 50, 181, 46, 202, 153, 15, + 132, 62, 112, 3, 51, 119, 211, 168, 72, 71, 243, 193, 160, 131, + 176, 111, 90, 246, 110, 221, 43, 227, 240, 221, 102, 139, 223, 84, + 18, 39, 66, 100, 117, 29, 26, 210, 189, 224, 26, 237, 82, 17, + 237, 139, 127, 131, 210, 244, 215, 16, 67, 50, 87, 172, 172, 176, + 34, 210, 78, 180, 164, 172, 204, 89, 206, 12, 210, 49, 64, 200, + 82, 32, 19, 254, 38, 159, 205, 63, 251, 240, 17, 166, 37, 116, + 149, 91, 16, 175, 165, 115, 15, 201, 251, 43, 195, 109, 255, 86, + 168, 107, 139, 202, 52, 118, 103, 81, 183, 32, 218, 173, 164, 209, + 37, 140, 109, 164, 230, 140, 250, 12, 211, 58, 192, 236, 53, 223, + 72, 121, 195, 13, 27, 194, 18, 250, 243, 219, 60, 143, 73, 17, + 95, 32, 198, 203, 50, 17, 125, 131, 195, 199, 13, 221, 206, 91, + 170, 44, 249, 137, 71, 209, 35, 182, 155, 36, 126, 222, 26, 100, + 191, 2, 97, 154, 77, 101, 116, 88, 197, 38, 61, 140, 163, 17, + 23, 120, 125, 150, 112, 104, 209, 27, 157, 21, 139, 156, 162, 251, + 120, 254, 11, 143, 3, 85, 171, 222, 181, 108, 33, 96, 118, 108, + 77, 191, 222, 38, 44, 2, 72, 57, 79, 135, 117, 165, 126, 33, + 98, 154, 160, 17, 230, 82, 138, 214, 222, 236, 252, 213, 224, 168, + 128, 254, 52, 111, 74, 21, 161, 69, 167, 227, 188, 214, 163, 214, + 15, 36, 112, 4, 80, 113, 149, 136, 22, 16, 69, 71, 4, 238, + 193, 64, 0, 22, 214, 246, 114, 92, 71, 60, 54, 83, 106, 159, + 248, 250, 186, 138, 204, 77, 226, 216, 234, 47, 174, 183, 104, 42, + 233, 91, 205, 166, 19, 51, 0, 122, 237, 2, 103, 183, 12, 33, + 147, 17, 230, 56, 32, 132, 249, 229, 18, 130, 240, 213, 177, 227, + 248, 105, 43, 138, 205, 213, 124, 9, 50, 123, 235, 138, 147, 235, + 220, 202, 196, 17, 17, 109, 65, 236, 155, 98, 220, 227, 116, 92, + 21, 35, 85, 216, 127, 157, 146, 1, 146, 36, 142, 195, 235, 102, + 254, 104, 91, 31, 163, 20, 189, 144, 200, 135, 228, 106, 40, 62, + 235, 102, 66, 11, 156, 58, 149, 74, 118, 3, 239, 244, 248, 31, + 192, 88, 117, 97, 81, 148, 108, 136, 8, 97, 179, 98, 136, 120, + 91, 34, 46, 93, 228, 200, 85, 25, 52, 58, 115, 76, 111, 9, + 193, 22, 144, 144, 179, 123, 241, 61, 132, 156, 117, 100, 44, 188, + 124, 51, 214, 164, 215, 224, 175, 124, 122, 228, 46, 235, 131, 176, + 75, 238, 70, 255, 236, 33, 223, 241, 119, 85, 214, 149, 197, 6, + 200, 2, 92, 4, 10, 156, 5, 69, 69, 245, 249, 149, 23, 6, + 98, 27, 222, 112, 1, 99, 28, 49, 146, 23, 2, 213, 243, 113, + 87, 164, 116, 181, 11, 96, 178, 206, 107, 103, 44, 60, 4, 187, + 132, 245, 68, 67, 50, 12, 180, 151, 56, 230, 192, 3, 28, 5, + 27, 126, 153, 230, 57, 17, 83, 72, 248, 101, 93, 81, 30, 162, + 174, 151, 229, 83, 54, 76, 50, 27, 45, 113, 175, 120, 240, 125, + 150, 80, 106, 146, 1, 151, 251, 178, 50, 72, 126, 35, 199, 89, + 79, 162, 175, 68, 55, 5, 67, 156, 253, 78, 204, 134, 88, 254, + 194, 49, 146, 5, 41, 10, 232, 240, 239, 53, 224, 226, 79, 134, + 175, 224, 121, 103, 238, 30, 96, 58, 200, 195, 208, 116, 114, 89, + 40, 8, 192, 142, 241, 96, 70, 196, 136, 51, 198, 32, 243, 201, + 195, 123, 139, 2, 127, 43, 70, 150, 151, 142, 186, 45, 157, 46, + 228, 91, 27, 255, 179, 107, 13, 199, 87, 117, 33, 120, 142, 73, + 38, 228, 38, 106, 55, 141, 85, 74, 246, 158, 7, 6, 208, 36, + 196, 178, 98, 159, 193, 107, 83, 78, 172, 206, 118, 250, 27, 3, + 117, 237, 81, 153, 64, 105, 165, 63, 53, 83, 118, 245, 75, 169, + 45, 192, 198, 33, 25, 30, 235, 87, 88, 202, 25, 164, 204, 162, + 45, 200, 172, 106, 108, 176, 51, 213, 77, 106, 99, 197, 200, 173, + 191, 207, 54, 107, 176, 83, 212, 139, 113, 194, 30, 99, 83, 106, + 180, 19, 50, 235, 215, 16, 19, 59, 46, 145, 243, 91, 192, 206, + 146, 237, 39, 156, 182, 202, 240, 133, 217, 109, 57, 55, 255, 122, + 60, 171, 73, 197, 71, 184, 180, 242, 2, 251, 230, 165, 54, 193, + 191, 200, 162, 61, 80, 47, 247, 215, 115, 25, 91, 149, 106, 202, + 95, 12, 54, 130, 227, 116, 54, 67, 237, 166, 175, 5, 36, 201, + 51, 133, 171, 174, 213, 150, 239, 147, 221, 174, 107, 251, 190, 214, + 202, 145, 54, 120, 66, 246, 160, 171, 129, 36, 176, 50, 177, 152, + 28, 47, 63, 137, 209, 0, 117, 3, 220, 170, 236, 85, 174, 176, + 133, 207, 226, 81, 197, 200, 254, 102, 49, 238, 115, 187, 113, 193, + 251, 136, 114, 221, 191, 27, 195, 151, 10, 135, 116, 79, 132, 75, + 245, 132, 216, 187, 238, 150, 228, 251, 197, 222, 12, 190, 102, 235, + 33, 82, 163, 151, 83, 104, 238, 13, 212, 127, 185, 253, 141, 214, + 78, 203, 26, 121, 29, 0, 210, 49, 5, 205, 130, 152, 101, 26, + 66, 100, 221, 223, 199, 46, 242, 82, 63, 57, 242, 235, 53, 97, + 144, 175, 28, 83, 168, 129, 64, 211, 33, 100, 130, 184, 244, 166, + 176, 157, 243, 222, 134, 185, 110, 199, 209, 215, 19, 157, 79, 119, + 144, 246, 26, 70, 14, 143, 176, 36, 195, 4, 87, 125, 150, 214, + 13, 100, 16, 140, 193, 254, 251, 20, 35, 128, 198, 171, 47, 120, + 180, 81, 114, 2, 245, 28, 132, 91, 201, 188, 47, 228, 31, 244, + 53, 73, 113, 2, 247, 19, 116, 200, 44, 98, 145, 215, 104, 175, + 54, 147, 160, 90, 149, 223, 203, 197, 187, 237, 90, 88, 159, 56, + 19, 160, 122, 112, 103, 80, 44, 38, 69, 47, 33, 192, 187, 255, + 235, 240, 172, 62, 218, 21, 116, 179, 149, 16, 220, 223, 92, 160, + 244, 46, 128, 94, 170, 29, 55, 224, 189, 185, 8, 29, 4, 146, + 216, 80, 197, 113, 183, 170, 225, 108, 133, 239, 112, 66, 68, 24, + 153, 184, 118, 119, 176, 21, 31, 151, 206, 168, 168, 250, 234, 40, + 206, 10, 23, 218, 235, 19, 161, 138, 8, 204, 130, 165, 189, 148, + 91, 204, 35, 133, 130, 99, 211, 144, 83, 19, 86, 71, 90, 219, + 188, 88, 126, 59, 178, 251, 161, 69, 63, 206, 253, 97, 72, 247, + 12, 190, 71, 166, 126, 212, 195, 109, 246, 178, 221, 199, 175, 112, + 78, 93, 232, 173, 253, 96, 43, 14, 109, 163, 37, 112, 28, 167, + 141, 74, 32, 79, 115, 93, 164, 92, 131, 224, 162, 69, 164, 47, + 155, 83, 179, 182, 214, 10, 154, 203, 40, 8, 93, 63, 136, 30, + 238, 190, 209, 15, 195, 162, 122, 231, 4, 52, 175, 224, 85, 27, + 118, 105, 114, 95, 203, 132, 82, 223, 172, 82, 29, 33, 8, 229, + 6, 46, 115, 12, 112, 165, 155, 85, 98, 7, 104, 172, 64, 77, + 86, 155, 55, 126, 15, 93, 190, 210, 177, 217, 4, 58, 160, 182, + 168, 138, 199, 40, 168, 162, 117, 131, 146, 21, 181, 219, 251, 23, + 170, 106, 72, 56, 182, 154, 105, 33, 252, 104, 150, 226, 150, 95, + 210, 115, 209, 35, 254, 143, 203, 249, 12, 185, 29, 125, 201, 192, + 41, 77, 222, 44, 247, 67, 53, 145, 119, 163, 219, 70, 147, 55, + 43, 242, 150, 148, 193, 160, 195, 222, 8, 118, 84, 75, 172, 195, + 231, 35, 181, 21, 187, 150, 75, 72, 124, 230, 92, 241, 132, 82, + 255, 148, 70, 13, 48, 144, 102, 192, 136, 41, 237, 160, 105, 111, + 100, 197, 36, 194, 163, 22, 124, 219, 229, 239, 167, 182, 230, 202, + 164, 202, 231, 159, 103, 17, 100, 108, 75, 106, 57, 148, 101, 194, + 52, 8, 207, 91, 65, 59, 59, 61, 158, 133, 191, 99, 110, 253, + 115, 91, 247, 7, 39, 185, 78, 35, 254, 153, 112, 209, 23, 103, + 98, 46, 223, 168, 218, 200, 194, 244, 14, 180, 107, 17, 236, 192, + 186, 93, 223, 151, 207, 253, 65, 94, 15, 120, 249, 27, 94, 178, + 80, 121, 248, 162, 56, 21, 33, 202, 183, 161, 250, 122, 153, 152, + 12, 69, 46, 192, 88, 90, 122, 133, 85, 16, 248, 60, 226, 35, + 100, 33, 156, 117, 174, 202, 101, 92, 52, 151, 59, 232, 191, 96, + 251, 222, 15, 80, 78, 12, 214, 31, 116, 147, 24, 38, 161, 123, + 231, 126, 173, 84, 158, 204, 252, 183, 152, 24, 146, 174, 65, 158, + 108, 201, 227, 243, 169, 106, 93, 212, 98, 121, 26, 112, 205, 15, + 24, 7, 204, 174, 171, 33, 86, 229, 236, 83, 98, 107, 2, 47, + 225, 45, 61, 64, 180, 14, 149, 39, 136, 244, 172, 237, 235, 3, + 208, 198, 207, 47, 183, 6, 78, 153, 91, 212, 62, 197, 184, 82, + 37, 111, 121, 229, 128, 199, 128, 185, 94, 45, 134, 166, 66, 198, + 38, 73, 251, 149, 150, 171, 80, 31, 109, 22, 59, 0, 128, 241, + 135, 43, 112, 178, 87, 205, 168, 170, 57, 20, 61, 221, 80, 240, + 5, 66, 101, 208, 86, 1, 99, 143, 109, 132, 234, 127, 124, 233, + 14, 250, 127, 168, 112, 139, 26, 134, 77, 154, 119, 89, 67, 140, + 66, 150, 196, 29, 137, 46, 140, 47, 252, 199, 21, 141, 32, 173, + 32, 50, 201, 44, 195, 210, 128, 83, 152, 67, 203, 87, 221, 157, + 74, 138, 61, 234, 226, 191, 67, 26, 254, 89, 251, 196, 83, 163, + 63, 193, 109, 183, 158, 31, 189, 136, 235, 118, 84, 9, 22, 9, + 98, 140, 198, 212, 47, 124, 18, 195, 229, 191, 84, 136, 219, 57, + 76, 187, 193, 108, 128, 117, 28, 114, 146, 113, 149, 128, 58, 140, + 254, 184, 97, 245, 63, 70, 144, 144, 4, 107, 75, 252, 71, 128, + 90, 99, 210, 159, 48, 244, 54, 57, 77, 224, 254, 80, 231, 105, + 123, 156, 129, 64, 31, 114, 19, 131, 17, 156, 42, 156, 18, 230, + 41, 130, 254, 59, 7, 20, 93, 213, 88, 132, 139, 26, 30, 241, + 13, 116, 235, 23, 194, 118, 113, 105, 129, 101, 163, 207, 6, 2, + 20, 46, 165, 91, 187, 22, 233, 250, 248, 118, 150, 167, 98, 197, + 21, 27, 175, 183, 207, 108, 208, 97, 135, 218, 12, 69, 52, 239, + 225, 232, 228, 204, 158, 84, 80, 224, 17, 52, 2, 15, 189, 31, + 7, 51, 123, 192, 223, 71, 107, 203, 70, 215, 39, 166, 100, 253, + 1, 241, 230, 204, 3, 170, 252, 207, 23, 168, 126, 180, 11, 55, + 25, 156, 140, 229, 247, 145, 234, 251, 248, 166, 177, 80, 150, 165, + 41, 12, 181, 221, 197, 130, 53, 150, 47, 254, 146, 163, 77, 128, + 113, 171, 212, 203, 233, 209, 112, 89, 46, 163, 171, 0, 186, 214, + 222, 195, 186, 47, 250, 108, 32, 137, 214, 255, 76, 203, 52, 168, + 75, 86, 16, 83, 177, 223, 193, 79, 169, 61, 123, 29, 210, 124, + 105, 44, 196, 110, 7, 135, 91, 33, 216, 39, 247, 81, 190, 74, + 205, 97, 98, 208, 41, 39, 124, 171, 221, 72, 71, 238, 14, 6, + 163, 237, 134, 187, 174, 244, 128, 247, 40, 23, 109, 14, 148, 23, + 192, 172, 207, 167, 53, 101, 136, 82, 93, 159, 23, 13, 183, 199, + 101, 154, 163, 157, 190, 99, 215, 78, 42, 162, 227, 67, 120, 85, + 75, 158, 173, 65, 133, 252, 126, 214, 115, 67, 200, 32, 96, 228, + 230, 234, 157, 250, 49, 145, 135, 84, 119, 117, 149, 252, 76, 168, + 193, 83, 60, 85, 170, 52, 89, 220, 133, 142, 33, 171, 188, 27, + 85, 244, 162, 190, 175, 36, 135, 97, 35, 39, 68, 200, 169, 231, + 150, 215, 44, 172, 170, 105, 59, 85, 6, 155, 159, 142, 45, 198, + 245, 112, 224, 35, 67, 159, 101, 29, 100, 10, 130, 90, 189, 10, + 47, 157, 26, 101, 167, 246, 19, 96, 208, 123, 62, 54, 40, 241, + 30, 37, 245, 111, 194, 255, 248, 6, 56, 238, 247, 6, 189, 120, + 14, 47, 128, 58, 48, 177, 36, 102, 123, 252, 153, 117, 212, 75, + 95, 247, 19, 149, 138, 116, 156, 190, 91, 209, 226, 65, 81, 138, + 12, 143, 188, 240, 90, 30, 185, 135, 179, 80, 125, 185, 85, 103, + 162, 238, 130, 176, 244, 61, 235, 205, 240, 178, 76, 71, 254, 174, + 224, 174, 187, 176, 236, 201, 1, 181, 244, 19, 22, 179, 218, 181, + 51, 245, 1, 143, 187, 237, 151, 116, 128, 179, 66, 166, 51, 148, + 34, 21, 3, 199, 220, 166, 59, 181, 210, 175, 112, 176, 92, 38, + 246, 142, 167, 249, 239, 169, 91, 112, 220, 9, 98, 42, 164, 186, + 139, 219, 176, 102, 18, 91, 171, 175, 142, 184, 100, 21, 176, 147, + 117, 58, 239, 103, 233, 123, 86, 161, 157, 230, 133, 54, 25, 40, + 120, 28, 105, 64, 98, 9, 121, 32, 95, 167, 138, 231, 55, 108, + 149, 158, 177, 146, 47, 155, 132, 20, 172, 84, 241, 158, 55, 212, + 182, 90, 129, 237, 242, 200, 65, 36, 127, 159, 65, 151, 51, 211, + 7, 116, 17, 90, 8, 252, 122, 7, 207, 26, 187, 123, 152, 184, + 209, 79, 182, 167, 84, 186, 141, 72, 132, 37, 232, 3, 239, 83, + 34, 185, 169, 152, 102, 43, 203, 130, 182, 146, 36, 148, 244, 113, + 59, 62, 187, 232, 255, 46, 244, 10, 7, 17, 250, 149, 175, 205, + 218, 229, 225, 178, 201, 181, 36, 124, 111, 166, 43, 91, 21, 152, + 233, 247, 26, 174, 196, 104, 8, 67, 252, 251, 76, 108, 65, 134, + 85, 199, 9, 227, 68, 136, 19, 248, 167, 159, 225, 146, 114, 48, + 202, 35, 54, 25, 214, 95, 163, 126, 119, 106, 235, 104, 40, 32, + 251, 17, 14, 135, 112, 14, 80, 188, 237, 194, 75, 113, 127, 18, + 75, 59, 182, 222, 72, 58, 5, 238, 190, 199, 236, 196, 76, 0, + 26, 63, 167, 110, 115, 207, 44, 199, 14, 228, 253, 230, 61, 64, + 42, 13, 218, 120, 70, 27, 184, 183, 64, 45, 13, 59, 190, 184, + 223, 100, 10, 48, 189, 104, 93, 63, 23, 245, 210, 135, 195, 219, + 122, 104, 88, 112, 225, 196, 244, 115, 201, 130, 3, 224, 243, 14, + 50, 71, 27, 15, 163, 168, 201, 102, 43, 234, 66, 187, 18, 188, + 116, 62, 74, 161, 101, 251, 101, 208, 220, 98, 52, 213, 4, 40, + 117, 206, 171, 183, 121, 163, 11, 182, 87, 137, 184, 232, 189, 107, + 200, 146, 31, 222, 185, 188, 69, 73, 120, 61, 175, 212, 145, 249, + 141, 135, 161, 241, 225, 89, 249, 29, 96, 143, 152, 169, 28, 155, + 179, 58, 44, 24, 78, 114, 175, 21, 225, 219, 16, 171, 64, 187, + 200, 57, 200, 133, 187, 226, 52, 152, 75, 50, 71, 15, 23, 14, + 70, 88, 233, 23, 146, 231, 189, 82, 129, 15, 255, 62, 173, 86, + 247, 118, 146, 41, 184, 50, 78, 200, 220, 210, 237, 132, 17, 191, + 14, 25, 45, 150, 98, 199, 144, 91, 159, 48, 137, 169, 82, 175, + 157, 84, 55, 97, 234, 255, 22, 55, 226, 222, 103, 169, 150, 126, + 20, 143, 56, 25, 15, 239, 29, 190, 202, 129, 83, 78, 228, 0, + 224, 181, 63, 131, 251, 133, 225, 122, 171, 125, 225, 228, 7, 131, + 101, 150, 33, 254, 212, 240, 76, 185, 254, 25, 200, 184, 144, 183, + 157, 193, 35, 33, 158, 63, 241, 65, 192, 127, 205, 108, 193, 65, + 128, 38, 96, 23, 142, 218, 173, 112, 94, 201, 0, 19, 101, 168, + 58, 161, 78, 29, 198, 178, 12, 242, 247, 239, 181, 124, 228, 86, + 2, 10, 26, 130, 237, 195, 176, 250, 91, 48, 227, 24, 111, 53, + 130, 15, 230, 8, 194, 186, 172, 228, 248, 42, 118, 68, 48, 183, + 192, 249, 76, 212, 220, 124, 4, 40, 133, 154, 135, 154, 190, 14, + 146, 107, 140, 71, 161, 185, 177, 232, 59, 168, 90, 133, 121, 55, + 29, 119, 30, 20, 206, 96, 96, 56, 112, 102, 177, 108, 43, 60, + 208, 241, 36, 130, 255, 196, 171, 131, 27, 88, 170, 123, 153, 34, + 232, 193, 62, 13, 251, 133, 94, 141, 221, 5, 85, 104, 86, 126, + 93, 22, 153, 111, 149, 114, 228, 75, 12, 255, 23, 194, 81, 22, + 229, 192, 244, 37, 83, 84, 220, 22, 40, 0, 179, 127, 173, 11, + 180, 131, 71, 8, 101, 248, 63, 143, 215, 41, 42, 69, 251, 201, + 8, 97, 176, 207, 243, 104, 88, 252, 228, 181, 141, 84, 9, 180, + 182, 151, 13, 197, 26, 184, 63, 123, 175, 12, 242, 186, 211, 168, + 39, 214, 90, 119, 23, 1, 13, 146, 101, 181, 156, 80, 180, 68, + 238, 225, 10, 141, 95, 228, 255, 20, 49, 35, 189, 45, 120, 245, + 187, 216, 214, 176, 250, 70, 189, 25, 138, 101, 96, 161, 232, 184, + 93, 65, 129, 74, 63, 209, 111, 72, 254, 21, 22, 107, 56, 103, + 123, 123, 101, 92, 58, 55, 246, 255, 181, 235, 72, 186, 242, 102, + 24, 198, 216, 51, 122, 202, 22, 216, 58, 223, 118, 232, 138, 17, + 168, 16, 4, 0, 245, 132, 244, 173, 63, 94, 120, 3, 146, 143, + 15, 149, 208, 183, 242, 43, 143, 173, 218, 154, 131, 204, 199, 243, + 182, 211, 30, 74, 159, 214, 179, 177, 40, 81, 158, 76, 207, 38, + 15, 74, 236, 135, 6, 178, 47, 210, 153, 98, 103, 252, 106, 84, + 64, 18, 112, 244, 124, 53, 192, 15, 40, 68, 200, 85, 72, 137, + 26, 55, 218, 101, 23, 186, 232, 197, 202, 215, 227, 232, 42, 241, + 222, 68, 98, 14, 219, 225, 2, 204, 183, 3, 195, 61, 233, 127, + 114, 69, 58, 55, 209, 249, 100, 13, 81, 118, 255, 75, 252, 216, + 65, 52, 42, 246, 178, 123, 178, 85, 245, 134, 173, 167, 70, 110, + 196, 84, 221, 31, 183, 217, 166, 106, 157, 161, 203, 109, 201, 47, + 153, 11, 22, 251, 46, 91, 211, 97, 22, 54, 79, 6, 227, 67, + 177, 51, 169, 147, 165, 223, 2, 243, 67, 63, 3, 131, 219, 49, + 201, 36, 254, 101, 116, 227, 175, 13, 117, 238, 149, 66, 23, 55, + 67, 159, 33, 141, 218, 138, 93, 89, 79, 28, 161, 70, 55, 190, + 248, 136, 203, 243, 18, 63, 126, 50, 222, 198, 174, 155, 26, 173, + 214, 243, 216, 114, 218, 243, 169, 168, 193, 241, 189, 248, 248, 87, + 81, 212, 122, 220, 70, 24, 91, 40, 140, 76, 26, 102, 59, 191, + 29, 75, 204, 53, 24, 55, 71, 125, 31, 57, 241, 35, 160, 150, + 133, 174, 72, 158, 97, 246, 201, 137, 104, 214, 137, 104, 219, 79, + 144, 174, 30, 246, 30, 94, 160, 119, 211, 141, 129, 249, 149, 181, + 45, 246, 244, 17, 50, 0, 94, 240, 16, 93, 247, 234, 26, 190, + 237, 158, 38, 68, 163, 40, 73, 217, 1, 155, 189, 123, 31, 127, + 149, 46, 20, 64, 160, 147, 40, 244, 129, 148, 75, 20, 30, 159, + 166, 153, 178, 57, 144, 69, 162, 114, 225, 105, 129, 178, 175, 169, + 169, 109, 96, 188, 60, 239, 21, 239, 18, 88, 14, 245, 191, 125, + 179, 85, 80, 118, 128, 87, 123, 10, 189, 175, 104, 146, 145, 223, + 176, 126, 45, 31, 91, 144, 168, 189, 26, 253, 144, 42, 126, 165, + 142, 99, 94, 87, 95, 18, 17, 187, 79, 252, 25, 102, 165, 82, + 125, 41, 70, 251, 134, 235, 1, 239, 87, 207, 194, 47, 49, 142, + 225, 30, 196, 111, 102, 226, 219, 180, 140, 113, 209, 235, 21, 242, + 51, 47, 176, 60, 104, 214, 220, 133, 44, 12, 222, 49, 35, 50, + 157, 163, 144, 155, 251, 73, 250, 0, 108, 169, 50, 49, 14, 147, + 101, 103, 2, 122, 152, 70, 244, 87, 195, 192, 118, 56, 28, 163, + 21, 145, 222, 157, 248, 252, 251, 153, 204, 64, 92, 209, 139, 118, + 72, 228, 221, 53, 30, 111, 147, 25, 164, 236, 190, 12, 165, 234, + 162, 30, 244, 173, 48, 202, 51, 230, 45, 74, 53, 26, 209, 117, + 85, 200, 255, 27, 14, 185, 181, 32, 214, 26, 100, 29, 69, 218, + 157, 204, 240, 182, 108, 139, 251, 5, 86, 157, 12, 172, 96, 158, + 99, 64, 214, 222, 66, 123, 115, 192, 76, 49, 16, 141, 86, 214, + 119, 201, 233, 6, 180, 48, 219, 136, 84, 64, 20, 48, 17, 226, + 126, 99, 180, 67, 76, 25, 140, 165, 238, 56, 76, 254, 87, 240, + 93, 24, 36, 125, 195, 27, 83, 71, 178, 104, 19, 195, 182, 51, + 49, 136, 44, 107, 14, 34, 17, 128, 96, 26, 45, 39, 116, 28, + 236, 202, 8, 141, 178, 249, 36, 119, 80, 101, 55, 56, 205, 81, + 10, 136, 244, 108, 77, 118, 153, 50, 161, 144, 65, 11, 169, 235, + 132, 209, 244, 54, 199, 57, 116, 125, 75, 218, 150, 19, 18, 150, + 92, 74, 174, 34, 247, 190, 122, 246, 144, 120, 78, 183, 86, 1, + 53, 126, 130, 83, 89, 28, 52, 65, 164, 13, 159, 64, 186, 146, + 103, 109, 146, 251, 240, 181, 203, 116, 3, 218, 230, 247, 221, 148, + 26, 7, 82, 46, 248, 123, 182, 230, 203, 230, 30, 24, 53, 233, + 200, 176, 26, 87, 169, 91, 119, 173, 133, 86, 65, 19, 67, 0, + 66, 26, 154, 228, 176, 62, 104, 0, 121, 148, 228, 37, 236, 216, + 148, 245, 29, 186, 3, 45, 238, 117, 239, 35, 61, 244, 141, 16, + 3, 53, 43, 175, 121, 71, 234, 250, 73, 217, 205, 158, 182, 230, + 248, 238, 149, 166, 175, 41, 185, 236, 46, 165, 111, 115, 42, 201, + 67, 232, 25, 37, 80, 244, 204, 161, 86, 132, 45, 5, 160, 175, + 196, 141, 136, 60, 138, 14, 127, 81, 124, 0, 157, 111, 64, 250, + 115, 227, 128, 233, 94, 213, 110, 131, 93, 58, 53, 133, 172, 30, + 65, 75, 253, 94, 185, 176, 157, 240, 116, 33, 19, 131, 39, 243, + 31, 157, 23, 246, 43, 30, 224, 233, 198, 25, 185, 137, 240, 17, + 22, 178, 214, 160, 22, 187, 90, 50, 110, 106, 195, 169, 84, 83, + 39, 38, 66, 58, 40, 93, 250, 13, 227, 82, 156, 180, 181, 208, + 196, 250, 219, 209, 183, 17, 168, 70, 78, 165, 65, 236, 119, 70, + 11, 78, 217, 70, 147, 153, 121, 1, 10, 186, 134, 8, 41, 193, + 242, 77, 65, 45, 7, 168, 251, 193, 58, 31, 109, 160, 138, 46, + 209, 122, 178, 54, 167, 245, 7, 8, 131, 189, 244, 176, 206, 82, + 7, 167, 161, 84, 54, 37, 11, 34, 116, 100, 203, 70, 15, 123, + 205, 224, 191, 128, 35, 128, 191, 211, 247, 202, 103, 145, 136, 6, + 36, 170, 254, 7, 124, 130, 89, 210, 136, 178, 205, 151, 64, 20, + 101, 126, 182, 144, 45, 56, 165, 67, 120, 238, 150, 54, 118, 214, + 171, 43, 28, 110, 23, 227, 239, 124, 188, 74, 4, 155, 39, 87, + 29, 23, 87, 188, 5, 12, 20, 52, 12, 91, 184, 245, 97, 137, + 87, 252, 254, 75, 166, 82, 37, 78, 67, 55, 122, 195, 66, 28, + 99, 76, 175, 202, 192, 107, 120, 192, 118, 6, 21, 136, 221, 156, + 54, 163, 118, 224, 210, 155, 162, 94, 79, 245, 0, 186, 31, 62, + 102, 239, 132, 78, 204, 127, 35, 145, 149, 199, 247, 141, 229, 145, + 151, 180, 255, 222, 198, 180, 194, 233, 252, 203, 25, 2, 181, 197, + 91, 184, 0, 152, 7, 243, 86, 198, 96, 186, 164, 247, 152, 229, + 165, 194, 139, 39, 168, 115, 164, 4, 225, 128, 13, 127, 111, 193, + 79, 170, 27, 104, 112, 200, 94, 139, 137, 107, 182, 227, 196, 117, + 133, 20, 37, 51, 176, 226, 149, 0, 3, 6, 118, 36, 28, 236, + 145, 9, 228, 55, 195, 245, 255, 59, 133, 225, 181, 53, 72, 249, + 57, 16, 38, 136, 205, 175, 55, 226, 109, 47, 21, 249, 180, 29, + 208, 104, 247, 4, 79, 154, 123, 165, 214, 3, 85, 172, 3, 185, + 191, 85, 179, 199, 131, 174, 241, 71, 143, 47, 151, 176, 74, 88, + 56, 27, 202, 5, 56, 145, 244, 47, 153, 47, 225, 39, 233, 199, + 78, 124, 137, 238, 250, 38, 73, 147, 208, 85, 219, 93, 153, 230, + 7, 82, 128, 6, 54, 249, 214, 244, 115, 31, 246, 185, 118, 154, + 147, 107, 204, 93, 164, 34, 17, 182, 109, 114, 112, 10, 102, 59, + 176, 45, 164, 139, 132, 178, 238, 149, 155, 218, 11, 223, 211, 195, + 237, 255, 227, 197, 182, 163, 177, 19, 34, 148, 119, 249, 113, 159, + 121, 65, 228, 223, 179, 41, 150, 134, 237, 137, 150, 216, 46, 58, + 61, 216, 179, 211, 178, 159, 250, 116, 220, 69, 29, 190, 57, 202, + 29, 225, 87, 211, 151, 28, 96, 203, 237, 220, 88, 244, 70, 82, + 43, 200, 251, 250, 204, 203, 182, 15, 137, 10, 130, 13, 226, 28, + 48, 220, 211, 33, 32, 82, 224, 54, 190, 129, 249, 109, 165, 151, + 204, 118, 204, 245, 172, 85, 108, 229, 98, 246, 7, 175, 208, 237, + 37, 222, 17, 192, 242, 31, 99, 110, 91, 219, 185, 55, 39, 156, + 67, 129, 95, 55, 199, 211, 212, 246, 171, 38, 116, 245, 63, 134, + 99, 74, 96, 72, 254, 123, 94, 56, 113, 146, 130, 183, 227, 37, + 118, 237, 149, 156, 161, 176, 240, 185, 135, 217, 68, 17, 159, 20, + 56, 53, 221, 26, 12, 28, 166, 95, 228, 26, 65, 180, 226, 231, + 200, 203, 60, 102, 50, 149, 106, 103, 112, 183, 228, 207, 173, 105, + 51, 126, 217, 32, 108, 164, 117, 12, 19, 142, 98, 95, 55, 19, + 102, 227, 136, 156, 11, 115, 85, 232, 2, 88, 16, 137, 19, 238, + 199, 234, 66, 98, 161, 108, 87, 2, 175, 90, 119, 254, 59, 191, + 156, 29, 85, 143, 59, 129, 189, 136, 160, 218, 238, 161, 44, 54, + 225, 79, 213, 82, 140, 212, 43, 94, 237, 63, 225, 66, 37, 227, + 161, 209, 192, 39, 140, 252, 251, 215, 120, 174, 162, 2, 147, 146, + 48, 177, 3, 31, 10, 113, 251, 159, 243, 244, 64, 160, 97, 52, + 196, 93, 84, 74, 104, 237, 19, 108, 28, 88, 162, 84, 112, 60, + 199, 101, 148, 186, 53, 72, 176, 61, 133, 219, 153, 121, 100, 125, + 22, 50, 181, 184, 146, 96, 123, 48, 248, 161, 200, 129, 30, 118, + 73, 175, 204, 51, 218, 213, 231, 101, 152, 52, 186, 246, 250, 122, + 39, 94, 175, 26, 85, 118, 55, 241, 16, 206, 146, 162, 198, 87, + 0, 203, 118, 115, 136, 224, 150, 162, 35, 171, 113, 28, 210, 82, + 7, 84, 235, 169, 99, 254, 219, 62, 19, 223, 54, 215, 91, 191, + 237, 223, 247, 247, 221, 176, 65, 84, 173, 78, 177, 231, 167, 54, + 6, 217, 251, 106, 9, 23, 154, 174, 153, 14, 179, 189, 144, 25, + 9, 132, 208, 115, 139, 253, 78, 241, 62, 143, 103, 190, 98, 95, + 216, 179, 6, 41, 246, 186, 189, 203, 29, 100, 21, 252, 39, 214, + 161, 54, 225, 218, 114, 216, 54, 108, 35, 40, 234, 73, 10, 232, + 190, 154, 86, 246, 122, 214, 211, 59, 220, 70, 224, 1, 153, 144, + 75, 176, 168, 158, 182, 181, 196, 140, 182, 32, 249, 158, 235, 239, + 172, 1, 3, 16, 213, 179, 5, 143, 78, 30, 106, 220, 23, 76, + 39, 109, 255, 244, 65, 86, 228, 156, 104, 6, 72, 61, 116, 235, + 219, 144, 187, 192, 145, 237, 4, 80, 175, 69, 86, 38, 6, 128, + 233, 91, 108, 5, 102, 95, 145, 209, 97, 82, 6, 12, 189, 85, + 90, 6, 224, 167, 11, 204, 13, 49, 113, 69, 139, 44, 159, 30, + 50, 227, 48, 140, 6, 98, 71, 38, 27, 254, 210, 58, 178, 141, + 212, 33, 244, 143, 247, 239, 70, 129, 136, 231, 242, 252, 227, 234, + 140, 38, 126, 94, 73, 126, 223, 21, 148, 129, 139, 6, 5, 126, + 54, 237, 115, 21, 148, 17, 111, 12, 147, 141, 210, 31, 71, 205, + 102, 220, 130, 96, 159, 74, 53, 204, 77, 92, 34, 98, 132, 2, + 148, 74, 40, 209, 44, 137, 194, 152, 0, 220, 6, 184, 8, 95, + 155, 240, 73, 39, 202, 153, 207, 147, 39, 152, 203, 45, 128, 176, + 144, 213, 92, 70, 182, 103, 67, 222, 121, 116, 192, 192, 245, 20, + 218, 6, 156, 30, 63, 49, 83, 108, 250, 254, 112, 1, 218, 89, + 57, 16, 53, 227, 144, 154, 26, 127, 128, 213, 49, 233, 31, 158, + 152, 72, 179, 192, 108, 130, 183, 171, 146, 229, 150, 105, 30, 104, + 63, 252, 224, 38, 142, 96, 149, 135, 201, 217, 73, 159, 178, 176, + 54, 92, 111, 98, 232, 245, 23, 141, 93, 17, 208, 200, 176, 83, + 218, 147, 220, 255, 72, 10, 110, 11, 196, 144, 182, 54, 46, 142, + 232, 93, 202, 27, 255, 176, 180, 60, 201, 108, 251, 50, 47, 171, + 235, 251, 141, 87, 54, 77, 101, 96, 104, 9, 245, 86, 150, 30, + 176, 26, 198, 3, 99, 241, 74, 198, 128, 151, 236, 32, 136, 112, + 46, 186, 106, 167, 43, 179, 8, 55, 20, 62, 162, 35, 22, 178, + 20, 50, 112, 72, 36, 74, 115, 162, 232, 21, 218, 73, 28, 38, + 7, 64, 194, 17, 156, 125, 123, 12, 166, 177, 133, 38, 36, 6, + 170, 93, 127, 61, 207, 56, 157, 154, 228, 202, 226, 97, 132, 214, + 141, 65, 216, 239, 250, 139, 44, 184, 94, 46, 199, 233, 171, 178, + 82, 27, 4, 92, 103, 54, 165, 206, 66, 37, 121, 8, 71, 152, + 227, 117, 170, 173, 108, 98, 145, 184, 88, 124, 101, 201, 144, 141, + 15, 91, 190, 81, 48, 136, 207, 123, 143, 249, 29, 168, 147, 108, + 172, 248, 68, 165, 10, 189, 216, 29, 102, 78, 242, 113, 169, 30, + 64, 9, 71, 148, 36, 157, 226, 28, 183, 3, 173, 125, 10, 143, + 24, 0, 174, 127, 103, 94, 66, 89, 153, 28, 205, 122, 156, 137, + 123, 34, 211, 145, 25, 62, 97, 76, 50, 41, 91, 245, 186, 27, + 183, 231, 162, 40, 224, 70, 166, 246, 36, 155, 43, 246, 112, 6, + 77, 61, 188, 251, 189, 223, 192, 113, 59, 105, 173, 11, 105, 60, + 106, 255, 218, 214, 163, 192, 182, 31, 242, 21, 29, 96, 88, 114, + 39, 141, 19, 92, 33, 187, 233, 60, 239, 216, 60, 132, 237, 129, + 227, 221, 145, 82, 121, 245, 53, 21, 103, 51, 249, 168, 84, 157, + 39, 39, 220, 104, 142, 95, 127, 205, 201, 132, 167, 247, 45, 3, + 226, 91, 134, 255, 227, 46, 158, 53, 42, 165, 160, 248, 11, 14, + 127, 22, 167, 222, 120, 15, 67, 78, 23, 120, 139, 84, 206, 225, + 98, 237, 16, 169, 211, 45, 152, 196, 183, 62, 137, 225, 223, 53, + 103, 104, 245, 121, 123, 147, 72, 200, 25, 136, 223, 150, 153, 213, + 63, 163, 192, 194, 78, 220, 179, 95, 163, 11, 15, 178, 80, 242, + 71, 127, 33, 125, 238, 78, 16, 66, 90, 210, 252, 140, 61, 24, + 237, 142, 199, 142, 4, 47, 210, 194, 172, 2, 151, 165, 89, 138, + 98, 121, 80, 202, 206, 53, 158, 58, 142, 66, 195, 250, 223, 11, + 202, 139, 233, 117, 79, 66, 149, 9, 11, 140, 193, 162, 83, 145, + 41, 89, 147, 85, 115, 252, 213, 210, 137, 102, 83, 222, 227, 8, + 80, 71, 43, 129, 232, 119, 200, 18, 199, 72, 52, 67, 163, 27, + 74, 174, 118, 209, 4, 228, 74, 211, 242, 213, 46, 254, 191, 46, + 233, 129, 6, 201, 204, 191, 29, 144, 76, 101, 211, 202, 145, 184, + 135, 176, 163, 200, 153, 17, 25, 207, 247, 199, 51, 151, 178, 145, + 195, 101, 168, 233, 61, 249, 149, 80, 32, 95, 68, 192, 156, 247, + 55, 227, 117, 2, 168, 50, 17, 7, 70, 217, 26, 120, 67, 31, + 125, 64, 91, 92, 142, 54, 37, 141, 215, 231, 142, 240, 230, 152, + 206, 218, 78, 86, 180, 213, 15, 208, 228, 118, 91, 251, 178, 73, + 150, 184, 125, 221, 177, 82, 240, 220, 95, 123, 132, 244, 6, 213, + 226, 23, 156, 103, 233, 225, 38, 67, 142, 83, 86, 167, 111, 48, + 205, 49, 106, 248, 108, 16, 49, 134, 78, 61, 115, 114, 150, 250, + 252, 61, 47, 33, 62, 179, 160, 27, 9, 255, 250, 230, 241, 114, + 128, 136, 147, 43, 79, 57, 113, 62, 128, 35, 49, 65, 0, 87, + 222, 221, 112, 49, 205, 158, 41, 183, 9, 216, 193, 149, 202, 48, + 54, 130, 246, 63, 95, 187, 188, 247, 102, 113, 129, 229, 255, 249, + 94, 73, 105, 203, 51, 69, 166, 125, 225, 197, 187, 65, 140, 61, + 219, 221, 225, 16, 185, 26, 27, 205, 200, 55, 64, 248, 206, 201, + 112, 63, 7, 88, 53, 160, 14, 47, 86, 110, 115, 238, 46, 109, + 220, 135, 218, 214, 27, 177, 111, 134, 238, 150, 109, 164, 86, 174, + 13, 80, 206, 214, 249, 87, 156, 201, 98, 173, 55, 19, 104, 96, + 63, 219, 7, 51, 25, 107, 106, 212, 84, 100, 9, 130, 191, 146, + 113, 191, 121, 187, 105, 38, 77, 52, 2, 188, 220, 115, 9, 185, + 16, 202, 28, 70, 57, 249, 96, 71, 181, 193, 39, 190, 221, 50, + 161, 19, 152, 238, 3, 20, 185, 94, 154, 42, 248, 101, 111, 95, + 204, 154, 91, 109, 93, 146, 98, 36, 168, 247, 84, 235, 194, 153, + 88, 131, 228, 223, 57, 114, 246, 203, 44, 189, 194, 98, 53, 27, + 11, 148, 54, 159, 84, 42, 237, 180, 109, 98, 241, 42, 59, 197, + 148, 45, 149, 234, 193, 96, 5, 245, 80, 60, 74, 210, 131, 91, + 218, 174, 22, 73, 56, 2, 92, 137, 72, 92, 134, 177, 221, 180, + 9, 138, 111, 255, 51, 39, 100, 122, 226, 250, 246, 78, 233, 58, + 126, 93, 3, 142, 253, 94, 33, 164, 166, 244, 168, 14, 187, 253, + 233, 31, 33, 151, 42, 138, 5, 214, 90, 181, 131, 94, 227, 43, + 84, 189, 134, 13, 86, 239, 31, 2, 193, 121, 64, 234, 96, 134, + 105, 31, 184, 230, 168, 39, 210, 243, 95, 133, 80, 102, 104, 66, + 15, 96, 154, 115, 15, 249, 202, 156, 199, 236, 94, 212, 42, 159, + 97, 220, 117, 80, 225, 237, 109, 1, 36, 216, 81, 129, 119, 242, + 172, 169, 183, 196, 63, 205, 20, 243, 250, 59, 225, 152, 111, 72, + 135, 235, 89, 162, 147, 161, 63, 240, 152, 202, 167, 139, 158, 32, + 242, 109, 218, 63, 124, 140, 127, 111, 44, 231, 118, 163, 238, 188, + 15, 154, 199, 199, 12, 4, 255, 214, 88, 34, 154, 119, 138, 130, + 239, 74, 71, 72, 89, 235, 171, 252, 220, 219, 212, 84, 21, 187, + 227, 178, 68, 80, 152, 149, 202, 255, 30, 74, 186, 230, 124, 155, + 192, 177, 14, 220, 86, 161, 180, 84, 189, 217, 86, 166, 109, 62, + 252, 80, 191, 81, 22, 28, 52, 18, 36, 12, 188, 184, 50, 224, + 212, 197, 39, 150, 62, 118, 24, 35, 55, 58, 170, 90, 31, 165, + 57, 226, 101, 10, 211, 214, 59, 198, 170, 187, 155, 173, 211, 95, + 93, 57, 190, 135, 155, 103, 207, 29, 16, 204, 150, 169, 170, 237, + 219, 228, 116, 190, 178, 138, 226, 181, 181, 50, 152, 40, 202, 188, + 253, 106, 140, 213, 12, 54, 99, 29, 35, 189, 218, 57, 161, 166, + 229, 30, 179, 211, 69, 239, 119, 216, 63, 226, 40, 84, 146, 141, + 235, 203, 182, 130, 3, 255, 42, 209, 81, 140, 213, 228, 218, 118, + 130, 113, 155, 245, 248, 37, 162, 217, 28, 174, 235, 237, 62, 122, + 239, 231, 238, 8, 194, 51, 229, 39, 119, 242, 141, 254, 234, 95, + 20, 129, 9, 29, 150, 195, 243, 15, 244, 76, 222, 247, 148, 192, + 120, 177, 168, 168, 3, 16, 218, 162, 210, 210, 190, 45, 189, 137, + 151, 32, 9, 171, 129, 200, 95, 172, 123, 119, 151, 186, 184, 163, + 59, 75, 139, 59, 54, 213, 148, 215, 239, 154, 176, 50, 165, 81, + 50, 37, 163, 110, 13, 53, 151, 28, 43, 235, 216, 95, 62, 19, + 76, 64, 247, 122, 129, 168, 148, 243, 96, 145, 198, 43, 172, 29, + 234, 184, 133, 3, 140, 120, 62, 201, 85, 149, 72, 2, 183, 24, + 239, 100, 32, 99, 239, 132, 86, 162, 91, 251, 176, 57, 50, 178, + 191, 165, 167, 31, 210, 62, 176, 70, 146, 117, 27, 136, 53, 30, + 196, 182, 204, 216, 192, 80, 1, 35, 192, 60, 233, 228, 61, 236, + 88, 142, 130, 133, 222, 114, 248, 132, 88, 144, 137, 167, 240, 110, + 137, 17, 190, 222, 128, 190, 153, 124, 218, 100, 197, 23, 15, 220, + 121, 251, 204, 122, 60, 90, 60, 192, 67, 16, 156, 244, 168, 0, + 142, 147, 226, 61, 200, 240, 150, 160, 181, 251, 26, 253, 221, 128, + 53, 114, 222, 19, 94, 17, 70, 218, 255, 227, 118, 103, 30, 222, + 136, 2, 25, 132, 93, 102, 4, 196, 249, 130, 55, 246, 133, 232, + 204, 62, 140, 26, 114, 100, 129, 110, 114, 9, 197, 198, 146, 88, + 188, 124, 40, 198, 67, 130, 76, 221, 123, 124, 83, 105, 92, 103, + 92, 184, 67, 8, 160, 175, 127, 128, 217, 238, 133, 225, 66, 130, + 152, 67, 66, 239, 147, 67, 66, 202, 22, 63, 10, 114, 122, 201, + 124, 53, 122, 250, 67, 221, 58, 53, 207, 29, 201, 154, 248, 234, + 197, 149, 11, 96, 182, 121, 155, 70, 161, 133, 53, 192, 243, 30, + 211, 225, 167, 106, 100, 63, 239, 111, 218, 158, 126, 92, 144, 100, + 11, 8, 245, 221, 149, 170, 176, 211, 132, 133, 138, 253, 113, 103, + 90, 194, 240, 254, 96, 211, 126, 33, 30, 55, 114, 213, 26, 1, + 29, 217, 163, 166, 26, 144, 48, 111, 248, 115, 113, 205, 103, 209, + 21, 161, 70, 117, 80, 233, 158, 202, 124, 249, 30, 83, 54, 250, + 90, 202, 115, 214, 122, 69, 237, 98, 98, 62, 31, 178, 167, 243, + 207, 179, 206, 234, 163, 85, 144, 64, 118, 62, 40, 42, 114, 55, + 73, 3, 65, 233, 210, 189, 243, 202, 211, 165, 92, 211, 233, 153, + 240, 134, 238, 150, 153, 144, 63, 191, 38, 103, 80, 209, 61, 207, + 37, 121, 74, 206, 103, 199, 121, 37, 53, 206, 56, 14, 41, 70, + 3, 239, 252, 125, 205, 107, 253, 49, 55, 56, 209, 226, 163, 206, + 101, 220, 28, 144, 125, 103, 44, 2, 142, 126, 103, 30, 78, 234, + 163, 248, 125, 142, 209, 48, 88, 26, 130, 115, 241, 107, 100, 132, + 189, 97, 153, 165, 183, 55, 238, 17, 228, 69, 248, 165, 72, 26, + 111, 49, 82, 201, 84, 150, 119, 102, 230, 147, 106, 254, 216, 39, + 59, 103, 233, 213, 216, 70, 171, 2, 193, 21, 234, 223, 47, 64, + 155, 227, 143, 21, 242, 238, 13, 139, 119, 74, 211, 65, 117, 248, + 13, 88, 214, 86, 150, 126, 109, 223, 73, 250, 200, 213, 179, 243, + 14, 166, 140, 72, 41, 53, 63, 44, 88, 68, 59, 211, 250, 173, + 7, 177, 135, 127, 99, 216, 53, 105, 117, 176, 169, 136, 45, 250, + 88, 114, 201, 161, 221, 3, 101, 219, 95, 72, 8, 155, 153, 61, + 249, 131, 49, 206, 56, 223, 254, 219, 26, 128, 199, 31, 27, 157, + 20, 6, 190, 215, 35, 91, 203, 239, 135, 128, 238, 102, 250, 217, + 43, 152, 137, 198, 157, 166, 95, 145, 163, 231, 25, 120, 216, 134, + 166, 129, 75, 56, 243, 7, 217, 31, 115, 129, 139, 92, 210, 241, + 193, 213, 141, 237, 7, 217, 221, 212, 227, 18, 249, 85, 0, 79, + 213, 161, 208, 18, 31, 126, 108, 53, 48, 152, 43, 56, 178, 111, + 184, 32, 74, 155, 222, 31, 6, 203, 39, 84, 154, 105, 10, 156, + 231, 109, 46, 143, 146, 160, 205, 183, 167, 7, 123, 218, 156, 209, + 174, 53, 66, 235, 102, 188, 134, 73, 169, 163, 176, 222, 101, 178, + 127, 154, 132, 10, 17, 68, 49, 80, 105, 164, 169, 198, 79, 14, + 142, 6, 169, 65, 224, 167, 233, 182, 237, 115, 33, 226, 193, 195, + 142, 133, 109, 70, 103, 227, 115, 207, 181, 179, 203, 52, 140, 46, + 49, 31, 209, 255, 244, 52, 113, 89, 72, 91, 197, 227, 37, 231, + 40, 7, 84, 191, 140, 237, 222, 45, 98, 169, 84, 125, 197, 8, + 45, 140, 125, 104, 154, 246, 243, 195, 143, 9, 154, 152, 7, 55, + 46, 221, 144, 203, 236, 79, 150, 19, 2, 134, 175, 12, 81, 154, + 101, 199, 137, 75, 96, 44, 147, 205, 145, 56, 251, 6, 62, 157, + 254, 146, 87, 244, 43, 108, 29, 108, 212, 179, 77, 219, 18, 37, + 241, 1, 153, 10, 124, 37, 47, 0, 224, 226, 99, 195, 87, 232, + 93, 217, 181, 137, 96, 26, 193, 244, 112, 105, 78, 12, 105, 214, + 197, 247, 64, 25, 2, 170, 49, 235, 220, 157, 190, 123, 145, 233, + 121, 133, 46, 174, 153, 20, 106, 161, 90, 30, 68, 233, 140, 111, + 224, 77, 69, 84, 175, 239, 178, 244, 223, 146, 146, 160, 148, 35, + 186, 195, 255, 219, 129, 31, 248, 121, 164, 178, 214, 62, 204, 146, + 41, 168, 219, 222, 149, 232, 45, 170, 36, 150, 163, 3, 38, 147, + 203, 98, 65, 243, 198, 105, 184, 57, 234, 165, 250, 36, 137, 212, + 137, 181, 176, 189, 247, 202, 243, 120, 94, 27, 3, 77, 75, 116, + 80, 102, 252, 247, 92, 246, 132, 133, 219, 71, 81, 37, 78, 184, + 214, 113, 152, 226, 124, 37, 85, 81, 97, 187, 214, 47, 67, 77, + 127, 152, 205, 86, 164, 84, 164, 121, 163, 230, 159, 218, 112, 200, + 115, 39, 90, 225, 187, 124, 155, 147, 173, 146, 187, 113, 131, 238, + 161, 167, 195, 46, 17, 148, 93, 0, 36, 140, 182, 98, 202, 114, + 109, 10, 78, 144, 83, 157, 60, 230, 48, 195, 41, 107, 206, 234, + 36, 205, 222, 101, 81, 182, 64, 112, 32, 121, 114, 86, 117, 220, + 18, 224, 42, 151, 23, 238, 175, 35, 132, 12, 36, 27, 29, 100, + 103, 186, 235, 108, 120, 52, 182, 210, 55, 164, 147, 233, 54, 127, + 104, 17, 79, 16, 135, 82, 253, 114, 120, 158, 164, 187, 224, 123, + 6, 68, 142, 44, 195, 111, 140, 52, 31, 50, 241, 228, 113, 187, + 190, 173, 142, 9, 127, 105, 101, 73, 91, 178, 231, 203, 204, 1, + 47, 78, 110, 190, 26, 222, 69, 78, 35, 210, 250, 131, 208, 247, + 212, 184, 4, 107, 16, 118, 188, 118, 54, 79, 96, 211, 160, 58, + 171, 199, 173, 202, 161, 46, 180, 81, 13, 213, 152, 200, 34, 92, + 196, 0, 197, 142, 0, 151, 209, 71, 178, 175, 247, 91, 156, 8, + 149, 46, 253, 185, 93, 114, 227, 89, 5, 216, 226, 164, 124, 35, + 83, 254, 253, 162, 41, 111, 147, 218, 215, 179, 240, 74, 20, 137, + 223, 217, 118, 248, 68, 80, 254, 182, 141, 184, 198, 171, 226, 236, + 33, 38, 9, 68, 198, 6, 74, 149, 101, 135, 146, 113, 205, 95, + 72, 7, 96, 32, 22, 117, 228, 195, 101, 55, 73, 119, 69, 137, + 14, 178, 41, 46, 34, 215, 235, 134, 169, 233, 114, 75, 199, 76, + 247, 151, 227, 120, 143, 212, 14, 149, 106, 246, 183, 33, 199, 83, + 169, 196, 248, 105, 185, 214, 0, 176, 249, 91, 188, 47, 170, 178, + 82, 163, 70, 112, 10, 196, 161, 241, 71, 121, 206, 15, 150, 122, + 240, 147, 205, 38, 115, 232, 96, 93, 78, 248, 134, 113, 122, 82, + 26, 11, 117, 167, 206, 101, 36, 92, 92, 9, 81, 132, 131, 248, + 152, 134, 106, 211, 206, 69, 170, 249, 117, 250, 220, 146, 97, 84, + 237, 255, 183, 132, 186, 129, 18, 244, 191, 198, 202, 75, 59, 229, + 248, 8, 214, 57, 157, 108, 166, 75, 124, 193, 136, 138, 179, 23, + 123, 175, 102, 33, 227, 36, 114, 172, 34, 108, 53, 206, 38, 79, + 171, 103, 212, 220, 176, 3, 251, 232, 135, 68, 220, 142, 49, 166, + 112, 219, 186, 174, 132, 229, 10, 172, 46, 158, 94, 30, 55, 176, + 152, 27, 37, 71, 17, 159, 124, 138, 236, 55, 64, 86, 166, 161, + 47, 197, 146, 38, 244, 49, 171, 64, 198, 51, 122, 201, 172, 155, + 164, 138, 87, 36, 120, 43, 139, 224, 99, 88, 207, 246, 145, 246, + 19, 41, 145, 83, 118, 188, 24, 93, 21, 166, 200, 225, 197, 206, + 102, 186, 200, 251, 29, 91, 86, 64, 47, 82, 155, 116, 5, 167, + 182, 172, 145, 246, 236, 44, 68, 76, 254, 8, 222, 153, 193, 63, + 48, 51, 71, 19, 234, 197, 229, 169, 143, 69, 110, 149, 109, 243, + 56, 71, 115, 128, 205, 187, 189, 123, 205, 118, 109, 67, 167, 255, + 192, 158, 18, 40, 96, 27, 204, 64, 36, 116, 207, 156, 38, 200, + 48, 240, 179, 135, 182, 97, 52, 91, 228, 179, 140, 195, 228, 117, + 78, 31, 229, 28, 74, 156, 170, 26, 79, 11, 100, 163, 50, 92, + 192, 55, 138, 4, 11, 18, 195, 178, 53, 9, 105, 124, 102, 111, + 247, 62, 17, 133, 191, 140, 15, 83, 229, 225, 174, 254, 253, 169, + 95, 220, 90, 113, 208, 141, 143, 59, 176, 19, 158, 90, 128, 83, + 220, 215, 3, 238, 89, 62, 245, 86, 146, 77, 252, 249, 217, 184, + 72, 83, 110, 247, 92, 178, 228, 255, 56, 94, 82, 130, 168, 236, + 246, 153, 97, 19, 141, 229, 139, 196, 178, 41, 8, 151, 115, 253, + 120, 126, 84, 149, 183, 217, 236, 95, 33, 109, 33, 37, 116, 239, + 3, 57, 209, 59, 155, 238, 219, 90, 57, 144, 189, 42, 205, 118, + 101, 172, 10, 45, 27, 225, 52, 128, 121, 96, 193, 99, 125, 85, + 81, 182, 33, 111, 138, 133, 159, 115, 107, 38, 181, 93, 181, 18, + 121, 204, 242, 74, 180, 10, 135, 242, 20, 132, 23, 52, 39, 88, + 231, 225, 139, 80, 1, 33, 155, 23, 84, 160, 17, 81, 157, 124, + 40, 254, 95, 241, 114, 51, 187, 107, 149, 216, 127, 237, 68, 190, + 184, 10, 192, 34, 24, 133, 53, 203, 190, 19, 220, 37, 213, 171, + 30, 91, 60, 254, 57, 84, 26, 228, 179, 177, 17, 158, 173, 187, + 169, 253, 225, 30, 254, 43, 11, 148, 78, 13, 249, 28, 221, 54, + 71, 5, 48, 251, 216, 77, 31, 70, 166, 186, 183, 183, 43, 46, + 56, 79, 145, 138, 3, 186, 204, 12, 240, 17, 85, 170, 196, 36, + 84, 29, 119, 11, 178, 194, 238, 212, 124, 52, 207, 47, 253, 226, + 129, 106, 196, 20, 11, 1, 198, 104, 71, 142, 190, 40, 29, 197, + 135, 61, 3, 54, 0, 77, 215, 158, 65, 131, 57, 66, 27, 218, + 120, 82, 170, 0, 63, 89, 248, 203, 106, 223, 113, 209, 56, 123, + 8, 209, 154, 160, 122, 47, 64, 255, 43, 69, 57, 229, 91, 86, + 219, 69, 196, 161, 208, 241, 109, 255, 101, 141, 203, 189, 250, 24, + 157, 55, 79, 107, 234, 203, 124, 15, 107, 42, 98, 53, 141, 161, + 134, 169, 59, 25, 209, 205, 49, 116, 109, 3, 137, 56, 158, 82, + 116, 100, 243, 172, 85, 99, 15, 37, 72, 117, 223, 112, 80, 134, + 192, 243, 100, 102, 91, 26, 129, 181, 187, 160, 133, 121, 233, 150, + 88, 34, 129, 146, 64, 221, 211, 8, 168, 110, 61, 180, 152, 135, + 195, 24, 181, 95, 39, 255, 58, 154, 233, 61, 178, 4, 189, 129, + 247, 151, 96, 222, 60, 150, 216, 235, 241, 182, 99, 127, 68, 69, + 115, 202, 206, 82, 107, 27, 126, 151, 22, 216, 211, 84, 123, 58, + 214, 32, 152, 15, 60, 226, 127, 85, 64, 111, 177, 125, 71, 59, + 74, 78, 223, 143, 144, 250, 23, 10, 24, 143, 78, 48, 76, 150, + 146, 82, 177, 178, 196, 120, 35, 149, 172, 140, 156, 6, 17, 229, + 190, 60, 254, 72, 138, 134, 173, 80, 232, 246, 232, 158, 188, 226, + 32, 50, 139, 56, 208, 170, 219, 197, 13, 189, 246, 36, 134, 80, + 216, 174, 234, 69, 62, 66, 31, 8, 201, 211, 218, 7, 188, 98, + 180, 225, 189, 32, 118, 190, 24, 151, 134, 79, 206, 181, 106, 9, + 210, 165, 127, 151, 21, 164, 78, 90, 45, 69, 83, 188, 166, 242, + 72, 174, 229, 216, 182, 36, 156, 246, 54, 249, 254, 166, 248, 50, + 149, 72, 96, 136, 229, 158, 52, 98, 222, 170, 134, 58, 191, 24, + 184, 212, 97, 198, 175, 152, 160, 36, 120, 115, 60, 10, 65, 193, + 120, 146, 181, 129, 168, 192, 183, 81, 36, 117, 6, 109, 62, 204, + 32, 89, 6, 74, 123, 239, 232, 253, 90, 252, 238, 224, 228, 186, + 251, 104, 40, 44, 181, 97, 58, 109, 6, 186, 214, 208, 20, 14, + 58, 62, 186, 4, 221, 173, 159, 46, 23, 253, 18, 185, 18, 87, + 189, 53, 48, 164, 103, 253, 41, 238, 188, 234, 31, 212, 30, 68, + 154, 123, 85, 37, 53, 8, 32, 113, 227, 101, 50, 50, 249, 10, + 148, 110, 210, 171, 36, 202, 5, 103, 208, 31, 172, 16, 230, 141, + 173, 21, 48, 247, 155, 49, 187, 177, 244, 124, 171, 19, 150, 161, + 145, 1, 254, 66, 37, 106, 217, 55, 30, 6, 216, 150, 111, 10, + 190, 239, 26, 9, 119, 88, 45, 117, 184, 123, 52, 6, 210, 187, + 99, 233, 132, 110, 70, 141, 79, 112, 179, 98, 163, 122, 173, 222, + 100, 187, 53, 135, 83, 248, 96, 219, 170, 204, 29, 195, 13, 80, + 216, 144, 56, 227, 179, 9, 127, 142, 18, 1, 174, 202, 187, 109, + 191, 252, 58, 183, 49, 255, 153, 135, 211, 242, 164, 73, 109, 218, + 75, 209, 48, 224, 120, 81, 142, 163, 243, 132, 217, 51, 222, 22, + 193, 230, 64, 246, 178, 224, 250, 121, 18, 51, 75, 8, 22, 202, + 66, 123, 51, 87, 198, 62, 114, 228, 208, 83, 197, 84, 41, 129, + 23, 137, 49, 55, 211, 92, 70, 82, 132, 18, 106, 154, 56, 120, + 179, 177, 95, 172, 175, 131, 215, 123, 174, 79, 145, 203, 64, 237, + 156, 108, 193, 22, 72, 154, 109, 228, 125, 113, 3, 10, 44, 10, + 37, 89, 197, 81, 255, 20, 136, 155, 175, 237, 210, 65, 48, 92, + 192, 62, 103, 79, 42, 187, 207, 176, 70, 35, 130, 187, 28, 55, + 121, 134, 236, 156, 89, 156, 167, 24, 61, 184, 245, 246, 19, 163, + 27, 8, 118, 82, 213, 135, 192, 158, 78, 87, 78, 24, 216, 11, + 116, 40, 58, 138, 246, 236, 221, 83, 130, 19, 144, 32, 161, 135, + 61, 112, 80, 209, 39, 160, 212, 133, 238, 145, 164, 223, 25, 124, + 78, 104, 178, 22, 57, 131, 103, 129, 31, 116, 153, 49, 51, 166, + 8, 94, 146, 188, 190, 30, 49, 29, 251, 181, 205, 207, 148, 218, + 213, 62, 127, 40, 254, 255, 79, 206, 216, 12, 218, 15, 72, 37, + 97, 204, 142, 103, 184, 115, 43, 135, 202, 236, 214, 147, 34, 238, + 49, 238, 68, 142, 245, 9, 29, 22, 201, 130, 123, 149, 46, 192, + 60, 11, 136, 62, 34, 27, 75, 198, 101, 16, 221, 187, 139, 173, + 78, 120, 172, 13, 247, 213, 77, 145, 71, 126, 120, 149, 130, 128, + 94, 170, 106, 240, 124, 235, 39, 37, 42, 104, 18, 137, 25, 145, + 245, 180, 108, 255, 26, 214, 155, 49, 76, 97, 16, 208, 76, 222, + 39, 167, 224, 48, 146, 67, 100, 56, 18, 144, 42, 234, 116, 34, + 182, 1, 34, 8, 97, 40, 4, 140, 247, 58, 250, 163, 199, 185, + 43, 92, 232, 254, 1, 198, 24, 193, 197, 116, 107, 228, 139, 227, + 87, 68, 148, 40, 236, 205, 179, 3, 14, 18, 73, 91, 135, 169, + 214, 150, 65, 21, 49, 59, 7, 59, 223, 240, 252, 1, 96, 231, + 85, 94, 160, 3, 68, 33, 229, 134, 37, 217, 31, 78, 233, 197, + 217, 121, 4, 152, 47, 8, 72, 57, 31, 2, 180, 56, 17, 196, + 62, 82, 158, 103, 247, 47, 50, 101, 6, 11, 143, 233, 125, 153, + 118, 252, 53, 185, 84, 114, 144, 124, 254, 252, 185, 147, 132, 219, + 67, 145, 199, 142, 8, 145, 35, 125, 228, 4, 249, 225, 180, 57, + 112, 213, 5, 51, 97, 101, 129, 108, 215, 223, 236, 29, 119, 131, + 17, 145, 187, 10, 199, 0, 170, 193, 151, 223, 100, 23, 142, 190, + 215, 199, 212, 224, 127, 81, 209, 140, 193, 217, 94, 212, 94, 30, + 166, 134, 180, 156, 72, 127, 91, 151, 91, 62, 125, 181, 3, 131, + 103, 218, 196, 229, 180, 69, 9, 249, 115, 189, 218, 246, 80, 219, + 171, 203, 149, 75, 130, 58, 98, 176, 158, 2, 4, 30, 216, 141, + 110, 165, 62, 134, 18, 56, 151, 130, 83, 173, 247, 191, 211, 140, + 89, 84, 98, 145, 81, 130, 93, 72, 247, 195, 212, 169, 254, 82, + 29, 20, 231, 86, 52, 177, 234, 244, 233, 56, 183, 210, 122, 230, + 59, 46, 117, 8, 194, 18, 232, 60, 103, 58, 71, 183, 76, 225, + 155, 161, 229, 243, 172, 10, 129, 172, 109, 103, 187, 225, 100, 147, + 192, 85, 139, 98, 217, 156, 63, 27, 101, 160, 209, 204, 210, 27, + 140, 46, 46, 150, 247, 188, 131, 77, 138, 200, 79, 158, 223, 36, + 189, 182, 143, 136, 136, 103, 161, 158, 117, 60, 81, 149, 96, 35, + 13, 206, 124, 54, 20, 91, 137, 43, 34, 141, 164, 130, 155, 81, + 211, 30, 149, 166, 7, 159, 195, 30, 107, 232, 20, 69, 96, 223, + 115, 85, 76, 192, 217, 115, 8, 22, 153, 253, 243, 93, 52, 132, + 109, 107, 129, 90, 149, 208, 88, 246, 10, 71, 60, 7, 220, 7, + 241, 32, 174, 154, 57, 73, 100, 34, 112, 65, 142, 7, 78, 124, + 80, 47, 183, 101, 253, 37, 18, 79, 91, 177, 76, 94, 114, 73, + 173, 17, 131, 207, 54, 0, 44, 154, 26, 50, 233, 186, 3, 175, + 55, 110, 141, 108, 248, 24, 2, 184, 112, 47, 147, 117, 98, 177, + 183, 115, 155, 169, 128, 14, 230, 106, 98, 227, 52, 170, 195, 119, + 121, 76, 157, 56, 38, 36, 145, 140, 252, 129, 222, 178, 165, 237, + 97, 123, 169, 6, 113, 77, 106, 84, 98, 178, 201, 151, 161, 217, + 49, 165, 118, 17, 239, 71, 159, 12, 21, 14, 204, 105, 199, 78, + 109, 138, 248, 196, 90, 108, 1, 67, 70, 39, 208, 229, 149, 2, + 222, 198, 156, 93, 38, 118, 228, 2, 75, 14, 41, 203, 227, 233, + 148, 254, 58, 16, 200, 235, 83, 201, 183, 80, 77, 79, 24, 229, + 254, 238, 13, 178, 221, 19, 62, 126, 144, 229, 223, 236, 185, 52, + 73, 164, 154, 135, 133, 63, 228, 226, 241, 67, 4, 9, 129, 228, + 124, 140, 193, 86, 224, 54, 167, 203, 198, 137, 244, 35, 125, 70, + 48, 102, 97, 23, 129, 35, 185, 2, 43, 65, 164, 5, 84, 249, + 56, 57, 83, 93, 146, 15, 69, 173, 191, 48, 199, 183, 190, 118, + 159, 104, 180, 95, 240, 199, 106, 38, 146, 112, 27, 242, 53, 215, + 68, 84, 49, 10, 164, 154, 143, 54, 123, 109, 61, 175, 54, 57, + 253, 134, 44, 27, 16, 50, 251, 99, 84, 74, 217, 42, 239, 154, + 2, 182, 250, 187, 50, 56, 238, 34, 158, 49, 158, 157, 10, 202, + 82, 106, 127, 57, 168, 160, 152, 103, 215, 184, 57, 187, 100, 124, + 119, 84, 207, 118, 52, 71, 50, 141, 65, 162, 68, 135, 242, 90, + 174, 94, 220, 71, 96, 215, 199, 105, 16, 220, 205, 128, 172, 180, + 178, 206, 176, 168, 238, 23, 106, 245, 157, 200, 17, 213, 8, 168, + 50, 228, 132, 41, 198, 106, 154, 171, 145, 145, 132, 100, 56, 91, + 205, 73, 45, 16, 0, 103, 95, 207, 87, 158, 221, 41, 212, 96, + 7, 228, 225, 246, 1, 52, 196, 89, 97, 104, 147, 8, 221, 54, + 96, 43, 171, 189, 208, 181, 191, 124, 151, 136, 221, 21, 33, 136, + 187, 188, 228, 90, 148, 233, 157, 132, 85, 25, 73, 104, 190, 60, + 50, 106, 104, 78, 197, 231, 84, 81, 120, 195, 99, 108, 108, 87, + 232, 83, 255, 171, 156, 236, 133, 230, 11, 226, 226, 38, 180, 28, + 216, 100, 107, 176, 4, 52, 171, 81, 117, 198, 110, 223, 208, 180, + 12, 223, 237, 137, 216, 136, 44, 13, 182, 43, 2, 245, 163, 127, + 220, 184, 97, 102, 79, 239, 120, 209, 144, 71, 228, 9, 162, 154, + 237, 219, 226, 103, 8, 8, 50, 27, 148, 152, 52, 29, 76, 27, + 83, 68, 86, 253, 179, 132, 84, 127, 103, 144, 156, 193, 123, 53, + 151, 108, 43, 150, 4, 101, 99, 176, 82, 178, 38, 59, 47, 97, + 83, 44, 50, 188, 38, 176, 202, 119, 91, 136, 183, 44, 51, 251, + 219, 82, 48, 76, 219, 238, 35, 220, 47, 31, 228, 36, 116, 184, + 89, 172, 72, 29, 79, 175, 146, 28, 186, 247, 180, 2, 172, 158, + 196, 107, 215, 27, 214, 66, 89, 220, 31, 214, 103, 184, 90, 182, + 152, 106, 52, 190, 11, 97, 215, 192, 80, 93, 180, 220, 190, 145, + 108, 217, 115, 230, 153, 115, 224, 95, 136, 154, 103, 249, 127, 22, + 6, 240, 117, 244, 116, 229, 246, 71, 74, 28, 248, 213, 65, 67, + 52, 189, 145, 74, 219, 58, 17, 100, 239, 98, 241, 16, 238, 187, + 49, 33, 53, 144, 175, 9, 84, 136, 98, 35, 63, 165, 59, 102, + 89, 196, 226, 192, 144, 116, 32, 98, 144, 200, 205, 0, 37, 233, + 58, 19, 209, 175, 129, 83, 190, 6, 193, 210, 96, 216, 147, 141, + 221, 144, 74, 61, 90, 45, 168, 200, 40, 145, 103, 178, 21, 252, + 251, 61, 74, 225, 251, 32, 106, 29, 236, 96, 246, 67, 154, 216, + 27, 114, 48, 153, 67, 246, 13, 32, 111, 237, 64, 91, 148, 61, + 137, 214, 57, 22, 205, 55, 2, 22, 180, 221, 212, 110, 126, 221, + 93, 18, 141, 28, 66, 96, 5, 182, 174, 23, 201, 38, 84, 98, + 47, 202, 120, 202, 106, 159, 141, 132, 212, 177, 228, 51, 106, 70, + 120, 51, 158, 28, 170, 3, 67, 251, 148, 69, 29, 73, 44, 41, + 75, 198, 109, 186, 157, 9, 55, 227, 19, 185, 206, 21, 65, 125, + 217, 97, 109, 163, 99, 207, 143, 212, 229, 193, 195, 116, 98, 145, + 75, 83, 134, 56, 33, 140, 219, 155, 64, 219, 197, 66, 41, 163, + 177, 207, 174, 63, 29, 148, 124, 167, 198, 150, 33, 90, 84, 201, + 235, 247, 78, 247, 186, 64, 128, 67, 104, 225, 47, 185, 166, 62, + 200, 109, 95, 144, 162, 168, 203, 204, 136, 164, 201, 75, 159, 34, + 43, 95, 70, 125, 250, 55, 86, 65, 44, 5, 252, 191, 227, 205, + 94, 108, 82, 50, 149, 205, 94, 31, 92, 153, 23, 42, 64, 56, + 81, 61, 43, 234, 13, 53, 159, 102, 17, 105, 148, 25, 84, 49, + 189, 34, 86, 3, 146, 42, 253, 41, 239, 218, 142, 52, 218, 194, + 112, 66, 104, 172, 78, 49, 235, 244, 164, 71, 64, 82, 254, 237, + 55, 54, 219, 11, 132, 209, 171, 168, 46, 243, 232, 146, 151, 90, + 233, 130, 242, 69, 156, 227, 61, 120, 53, 139, 127, 249, 100, 7, + 127, 128, 204, 114, 203, 237, 210, 73, 246, 159, 241, 94, 224, 56, + 50, 74, 25, 173, 0, 69, 244, 185, 86, 177, 42, 163, 199, 35, + 230, 169, 54, 204, 229, 87, 5, 225, 60, 64, 55, 90, 54, 40, + 168, 249, 190, 128, 212, 147, 132, 46, 60, 24, 148, 0, 99, 10, + 102, 154, 232, 150, 96, 247, 122, 215, 99, 112, 203, 166, 118, 22, + 2, 132, 139, 147, 208, 254, 12, 163, 91, 84, 163, 141, 231, 147, + 77, 89, 231, 171, 51, 59, 56, 60, 171, 175, 229, 142, 7, 9, + 11, 99, 19, 56, 184, 33, 196, 168, 203, 101, 140, 159, 1, 207, + 207, 186, 192, 171, 42, 212, 192, 31, 105, 235, 174, 18, 243, 31, + 168, 44, 20, 219, 70, 76, 78, 202, 138, 156, 4, 29, 37, 201, + 96, 200, 95, 252, 99, 173, 16, 232, 194, 141, 242, 29, 129, 183, + 23, 22, 247, 191, 192, 253, 170, 97, 173, 214, 53, 93, 137, 132, + 186, 161, 102, 209, 162, 171, 243, 40, 197, 153, 5, 26, 77, 60, + 117, 159, 40, 111, 30, 159, 112, 102, 249, 156, 58, 202, 218, 146, + 52, 68, 192, 50, 133, 114, 189, 76, 0, 165, 187, 189, 181, 196, + 69, 51, 98, 46, 194, 40, 38, 20, 152, 24, 12, 152, 86, 220, + 9, 25, 191, 215, 56, 255, 205, 20, 148, 166, 107, 34, 184, 180, + 154, 194, 241, 153, 96, 75, 82, 148, 156, 22, 216, 81, 19, 40, + 61, 182, 124, 47, 148, 124, 84, 60, 22, 142, 238, 245, 236, 21, + 148, 142, 126, 92, 42, 229, 78, 87, 177, 194, 57, 171, 130, 36, + 127, 146, 148, 163, 63, 102, 37, 222, 27, 63, 135, 49, 179, 23, + 239, 18, 180, 90, 121, 23, 73, 173, 81, 65, 164, 10, 238, 38, + 69, 135, 114, 46, 93, 111, 80, 159, 204, 170, 55, 194, 242, 185, + 134, 84, 164, 179, 152, 209, 225, 101, 229, 79, 126, 237, 154, 64, + 195, 214, 55, 88, 166, 70, 172, 73, 8, 75, 232, 168, 123, 45, + 172, 38, 223, 46, 149, 167, 196, 212, 80, 4, 84, 47, 155, 150, + 134, 35, 56, 212, 223, 91, 26, 17, 103, 144, 163, 112, 192, 8, + 222, 17, 151, 23, 109, 79, 206, 142, 240, 99, 153, 1, 214, 66, + 237, 213, 150, 95, 124, 132, 88, 57, 78, 47, 1, 122, 238, 19, + 196, 38, 248, 26, 107, 136, 96, 76, 189, 208, 18, 94, 156, 88, + 212, 149, 81, 249, 130, 208, 151, 139, 49, 95, 74, 217, 236, 121, + 84, 182, 35, 67, 177, 189, 108, 59, 222, 236, 44, 197, 5, 151, + 115, 156, 42, 146, 142, 84, 237, 193, 94, 168, 218, 57, 135, 95, + 8, 110, 87, 180, 42, 105, 127, 238, 210, 199, 230, 230, 158, 182, + 221, 143, 228, 29, 158, 139, 81, 237, 18, 70, 95, 130, 206, 24, + 173, 188, 233, 91, 27, 71, 79, 96, 230, 227, 7, 102, 245, 240, + 211, 133, 50, 148, 126, 29, 241, 156, 237, 125, 170, 101, 66, 48, + 105, 95, 181, 230, 111, 196, 129, 1, 131, 17, 133, 64, 22, 66, + 220, 126, 53, 6, 228, 225, 235, 236, 242, 10, 107, 105, 82, 12, + 232, 24, 172, 7, 73, 35, 38, 21, 43, 221, 221, 167, 229, 76, + 35, 173, 104, 231, 136, 253, 150, 241, 120, 2, 190, 241, 64, 138, + 80, 110, 76, 134, 185, 53, 151, 232, 74, 189, 151, 95, 23, 77, + 8, 137, 215, 46, 51, 11, 28, 252, 79, 224, 217, 64, 160, 225, + 161, 2, 221, 12, 136, 221, 30, 66, 201, 176, 103, 183, 183, 80, + 243, 246, 91, 82, 107, 231, 52, 216, 99, 254, 82, 196, 4, 30, + 191, 247, 113, 232, 213, 69, 233, 131, 105, 196, 40, 74, 186, 169, + 38, 120, 212, 71, 103, 83, 140, 77, 33, 234, 37, 76, 210, 58, + 51, 250, 186, 123, 79, 248, 1, 233, 195, 83, 36, 48, 44, 18, + 119, 193, 47, 33, 117, 98, 20, 34, 111, 2, 238, 219, 54, 171, + 197, 133, 130, 207, 2, 196, 97, 168, 218, 246, 234, 243, 58, 126, + 157, 19, 134, 204, 179, 127, 204, 172, 177, 145, 146, 235, 247, 34, + 237, 19, 42, 219, 1, 97, 161, 8, 39, 90, 207, 70, 69, 215, + 16, 188, 178, 5, 203, 204, 103, 28, 240, 144, 46, 189, 95, 138, + 163, 50, 150, 22, 243, 147, 54, 247, 227, 107, 29, 26, 19, 234, + 31, 96, 245, 10, 203, 81, 173, 234, 144, 88, 203, 25, 67, 95, + 254, 54, 38, 226, 180, 240, 240, 190, 12, 90, 93, 0, 29, 203, + 218, 34, 108, 23, 25, 221, 54, 8, 180, 60, 231, 129, 225, 190, + 98, 43, 140, 226, 64, 20, 149, 197, 141, 191, 253, 52, 243, 50, + 213, 28, 61, 243, 202, 249, 156, 244, 88, 35, 49, 240, 220, 61, + 228, 169, 245, 74, 25, 83, 14, 197, 82, 238, 41, 231, 204, 37, + 144, 64, 181, 113, 180, 106, 43, 129, 229, 105, 188, 129, 172, 52, + 195, 93, 196, 159, 15, 10, 90, 19, 174, 235, 175, 202, 67, 160, + 132, 50, 237, 217, 82, 43, 10, 16, 243, 227, 151, 55, 75, 177, + 106, 222, 149, 228, 142, 234, 68, 244, 128, 78, 135, 155, 159, 43, + 161, 122, 164, 156, 35, 53, 104, 219, 92, 185, 1, 13, 202, 27, + 135, 241, 206, 121, 117, 193, 173, 87, 192, 213, 143, 113, 252, 160, + 244, 222, 66, 5, 99, 228, 152, 4, 216, 170, 240, 225, 10, 36, + 203, 72, 39, 219, 11, 150, 111, 113, 215, 189, 108, 70, 191, 135, + 96, 145, 153, 165, 124, 208, 116, 14, 15, 136, 118, 33, 47, 106, + 147, 239, 165, 169, 232, 182, 19, 226, 77, 67, 63, 47, 59, 20, + 97, 237, 190, 108, 55, 254, 61, 198, 242, 60, 244, 251, 234, 119, + 137, 205, 96, 156, 88, 50, 96, 42, 201, 105, 0, 222, 204, 108, + 140, 155, 180, 49, 195, 135, 44, 215, 204, 240, 8, 100, 47, 180, + 217, 201, 184, 3, 120, 54, 6, 116, 180, 187, 80, 153, 215, 61, + 106, 126, 249, 37, 219, 191, 47, 154, 148, 139, 177, 23, 64, 208, + 89, 123, 88, 173, 131, 181, 25, 162, 151, 72, 114, 207, 0, 203, + 14, 40, 255, 72, 235, 2, 231, 1, 8, 14, 5, 247, 15, 145, + 97, 65, 219, 118, 105, 26, 39, 107, 130, 183, 88, 54, 105, 224, + 220, 113, 38, 192, 156, 18, 38, 82, 90, 172, 243, 41, 104, 70, + 195, 93, 249, 11, 234, 255, 52, 14, 13, 130, 182, 25, 194, 241, + 60, 166, 185, 49, 74, 87, 31, 253, 125, 144, 168, 245, 235, 118, + 237, 57, 244, 18, 15, 109, 200, 150, 27, 131, 208, 114, 157, 1, + 46, 99, 154, 57, 36, 170, 22, 152, 103, 185, 109, 247, 6, 120, + 99, 18, 88, 64, 210, 60, 174, 170, 41, 217, 87, 230, 119, 230, + 103, 172, 26, 191, 61, 186, 155, 226, 73, 67, 87, 64, 147, 0, + 181, 42, 93, 222, 60, 44, 2, 254, 68, 238, 119, 162, 17, 200, + 232, 138, 125, 66, 177, 79, 129, 197, 70, 237, 4, 147, 188, 35, + 103, 87, 180, 234, 191, 118, 216, 9, 211, 143, 58, 253, 249, 112, + 42, 102, 236, 237, 209, 34, 75, 100, 171, 60, 166, 110, 116, 79, + 140, 138, 74, 69, 214, 160, 194, 173, 103, 195, 5, 5, 89, 124, + 138, 239, 136, 249, 2, 16, 222, 142, 50, 152, 178, 60, 97, 228, + 69, 35, 118, 9, 65, 94, 121, 64, 244, 69, 1, 5, 223, 101, + 70, 58, 125, 148, 201, 40, 16, 70, 134, 32, 149, 93, 3, 197, + 119, 52, 0, 163, 64, 252, 215, 53, 91, 163, 195, 66, 165, 157, + 45, 215, 86, 187, 14, 24, 149, 61, 161, 174, 193, 233, 131, 183, + 134, 43, 30, 229, 244, 182, 6, 68, 121, 8, 230, 32, 7, 23, + 253, 33, 184, 110, 135, 123, 214, 29, 46, 231, 39, 18, 156, 128, + 55, 135, 104, 111, 201, 133, 101, 34, 224, 90, 115, 247, 204, 76, + 107, 88, 230, 86, 69, 69, 145, 23, 15, 251, 16, 31, 149, 195, + 242, 80, 214, 126, 188, 130, 73, 24, 98, 125, 47, 132, 150, 40, + 70, 93, 113, 202, 0, 57, 178, 3, 126, 44, 33, 198, 57, 165, + 39, 238, 64, 153, 123, 113, 85, 6, 151, 121, 85, 159, 147, 128, + 4, 30, 43, 79, 110, 57, 84, 107, 48, 17, 230, 250, 110, 249, + 42, 151, 124, 69, 160, 44, 200, 54, 244, 62, 74, 59, 237, 26, + 198, 16, 138, 71, 54, 151, 89, 50, 57, 54, 141, 1, 142, 118, + 39, 242, 40, 44, 155, 182, 178, 77, 229, 238, 54, 66, 23, 108, + 66, 58, 8, 83, 41, 240, 216, 239, 164, 230, 6, 162, 220, 206, + 181, 199, 178, 213, 71, 84, 246, 156, 86, 170, 100, 111, 69, 251, + 224, 159, 218, 115, 69, 88, 160, 145, 152, 54, 219, 141, 75, 57, + 75, 190, 218, 96, 51, 194, 56, 20, 84, 207, 85, 78, 220, 224, + 152, 132, 93, 145, 120, 180, 55, 28, 30, 176, 4, 157, 250, 180, + 39, 89, 88, 22, 173, 221, 149, 197, 151, 78, 198, 130, 73, 187, + 51, 67, 64, 1, 15, 121, 50, 209, 34, 121, 90, 222, 40, 20, + 250, 107, 156, 242, 91, 169, 208, 86, 187, 244, 250, 157, 27, 200, + 82, 12, 78, 177, 154, 70, 126, 75, 212, 48, 103, 44, 162, 128, + 210, 106, 216, 61, 125, 154, 150, 145, 123, 163, 88, 193, 101, 99, + 81, 97, 200, 156, 248, 254, 147, 33, 18, 15, 191, 94, 45, 84, + 64, 177, 106, 151, 45, 120, 88, 32, 25, 97, 193, 7, 52, 18, + 0, 19, 69, 210, 4, 70, 120, 139, 10, 49, 90, 8, 73, 20, + 54, 232, 126, 204, 230, 130, 17, 126, 111, 97, 22, 168, 146, 252, + 196, 74, 50, 157, 240, 132, 69, 215, 67, 247, 80, 5, 200, 12, + 95, 97, 2, 221, 84, 99, 170, 148, 34, 40, 8, 78, 210, 125, + 62, 139, 92, 61, 16, 102, 30, 119, 51, 129, 123, 110, 110, 193, + 200, 128, 14, 134, 49, 56, 173, 207, 5, 232, 232, 179, 26, 72, + 158, 54, 96, 144, 215, 172, 87, 181, 15, 215, 215, 48, 209, 55, + 240, 11, 89, 241, 120, 103, 105, 112, 119, 147, 160, 84, 78, 169, + 163, 195, 241, 225, 53, 38, 243, 226, 214, 133, 18, 240, 106, 205, + 231, 99, 13, 130, 157, 243, 241, 180, 234, 240, 96, 247, 186, 243, + 95, 5, 194, 109, 151, 111, 85, 225, 19, 11, 28, 203, 76, 29, + 227, 146, 123, 124, 115, 112, 162, 102, 71, 42, 36, 111, 252, 173, + 53, 149, 47, 255, 245, 94, 46, 226, 95, 205, 7, 57, 147, 170, + 2, 114, 232, 228, 200, 243, 96, 123, 200, 119, 195, 67, 72, 142, + 180, 125, 156, 73, 81, 176, 158, 133, 198, 90, 61, 194, 73, 0, + 7, 179, 19, 47, 19, 243, 230, 173, 61, 151, 208, 33, 249, 6, + 8, 211, 73, 201, 132, 219, 95, 20, 86, 253, 210, 174, 94, 148, + 79, 119, 219, 106, 17, 157, 248, 172, 224, 237, 107, 172, 242, 51, + 48, 4, 1, 84, 51, 191, 224, 117, 179, 67, 163, 174, 209, 104, + 139, 118, 103, 140, 38, 119, 167, 218, 183, 102, 239, 251, 42, 79, + 74, 99, 44, 143, 181, 75, 144, 186, 16, 170, 251, 149, 143, 132, + 113, 136, 51, 124, 5, 38, 76, 50, 75, 145, 146, 133, 217, 187, + 89, 154, 158, 95, 153, 86, 231, 222, 69, 41, 96, 92, 248, 162, + 82, 40, 123, 208, 137, 152, 194, 127, 116, 138, 3, 18, 7, 150, + 200, 225, 134, 203, 219, 166, 197, 212, 53, 143, 80, 152, 9, 198, + 95, 41, 0, 8, 173, 172, 202, 190, 8, 56, 122, 39, 240, 179, + 147, 173, 129, 167, 87, 110, 187, 216, 78, 160, 118, 177, 248, 199, + 119, 78, 49, 36, 213, 56, 67, 227, 40, 157, 133, 201, 166, 145, + 24, 77, 145, 75, 125, 162, 255, 254, 63, 84, 25, 141, 84, 140, + 179, 136, 221, 177, 222, 63, 222, 184, 178, 236, 131, 59, 153, 8, + 180, 217, 178, 200, 145, 160, 30, 182, 116, 45, 251, 152, 230, 139, + 234, 63, 116, 180, 5, 3, 115, 16, 36, 80, 104, 139, 129, 58, + 216, 132, 111, 63, 100, 38, 240, 13, 174, 221, 181, 149, 44, 208, + 93, 138, 232, 106, 19, 79, 201, 145, 49, 120, 198, 159, 197, 199, + 83, 247, 87, 62, 51, 187, 39, 209, 23, 102, 210, 86, 223, 222, + 109, 223, 15, 86, 241, 144, 2, 89, 242, 225, 85, 19, 141, 174, + 200, 179, 9, 115, 204, 42, 247, 89, 183, 98, 250, 158, 41, 202, + 134, 249, 148, 191, 194, 106, 238, 25, 22, 190, 168, 230, 185, 122, + 179, 149, 99, 23, 17, 27, 34, 253, 164, 154, 154, 3, 23, 122, + 108, 49, 121, 129, 61, 229, 36, 69, 182, 65, 107, 205, 85, 122, + 23, 26, 42, 45, 10, 2, 28, 246, 250, 174, 133, 250, 7, 124, + 150, 235, 244, 30, 92, 34, 251, 91, 99, 5, 115, 13, 50, 166, + 148, 193, 144, 12, 10, 48, 88, 246, 80, 125, 197, 26, 198, 175, + 132, 28, 101, 77, 7, 74, 53, 146, 5, 20, 128, 8, 220, 254, + 132, 132, 150, 5, 242, 9, 240, 158, 116, 85, 156, 16, 15, 146, + 177, 252, 80, 46, 156, 190, 90, 195, 34, 106, 166, 219, 102, 12, + 222, 82, 255, 128, 105, 86, 65, 124, 107, 95, 109, 241, 25, 138, + 201, 81, 227, 121, 241, 103, 160, 55, 56, 218, 73, 192, 25, 11, + 189, 246, 2, 248, 19, 163, 196, 188, 116, 206, 24, 8, 249, 178, + 96, 29, 67, 147, 53, 246, 160, 74, 96, 179, 82, 220, 64, 226, + 28, 21, 229, 28, 78, 228, 189, 222, 114, 254, 189, 143, 215, 162, + 152, 139, 81, 254, 130, 80, 181, 20, 214, 153, 30, 212, 239, 221, + 112, 129, 62, 106, 167, 206, 238, 37, 34, 239, 232, 14, 240, 206, + 24, 11, 252, 14, 57, 22, 243, 180, 28, 149, 110, 62, 33, 174, + 2, 207, 238, 211, 255, 229, 60, 184, 240, 38, 68, 2, 196, 156, + 140, 119, 114, 106, 179, 207, 223, 218, 30, 73, 156, 94, 168, 13, + 109, 182, 131, 228, 9, 31, 52, 37, 108, 74, 245, 127, 136, 68, + 37, 120, 20, 209, 134, 152, 149, 121, 55, 194, 72, 35, 35, 79, + 247, 102, 206, 238, 7, 195, 224, 162, 4, 158, 219, 48, 218, 212, + 209, 191, 99, 249, 194, 218, 64, 188, 144, 211, 232, 198, 176, 144, + 192, 255, 93, 83, 105, 246, 17, 40, 205, 56, 70, 157, 18, 75, + 29, 104, 27, 125, 18, 80, 46, 81, 142, 101, 104, 42, 93, 149, + 150, 40, 99, 225, 145, 80, 23, 90, 186, 157, 22, 200, 9, 171, + 236, 216, 55, 74, 116, 212, 18, 36, 166, 118, 243, 161, 246, 100, + 123, 64, 75, 22, 70, 209, 227, 194, 39, 3, 223, 189, 228, 216, + 100, 49, 98, 157, 166, 25, 134, 123, 131, 192, 242, 80, 13, 16, + 162, 95, 194, 45, 162, 15, 14, 1, 165, 210, 17, 222, 67, 217, + 234, 135, 244, 31, 41, 135, 141, 50, 33, 210, 59, 241, 209, 165, + 235, 216, 107, 142, 108, 9, 181, 80, 180, 133, 194, 160, 17, 215, + 71, 197, 144, 155, 132, 170, 70, 181, 103, 135, 38, 44, 21, 94, + 55, 99, 137, 244, 154, 67, 105, 16, 157, 42, 179, 109, 204, 146, + 38, 93, 192, 84, 101, 29, 36, 47, 59, 220, 129, 195, 120, 116, + 75, 75, 163, 75, 187, 115, 68, 1, 222, 151, 206, 128, 58, 109, + 32, 204, 176, 255, 5, 206, 29, 182, 9, 22, 13, 4, 183, 41, + 240, 68, 127, 216, 44, 55, 70, 163, 156, 26, 222, 243, 125, 47, + 236, 48, 216, 144, 183, 144, 127, 116, 75, 248, 209, 195, 36, 249, + 170, 182, 151, 230, 247, 60, 210, 240, 49, 246, 3, 167, 222, 200, + 232, 163, 176, 123, 17, 122, 23, 16, 241, 142, 106, 21, 224, 104, + 88, 239, 180, 1, 246, 220, 70, 54, 76, 43, 137, 190, 114, 100, + 96, 231, 88, 85, 253, 6, 168, 175, 129, 105, 22, 186, 141, 104, + 139, 169, 210, 78, 178, 80, 69, 1, 53, 217, 8, 119, 85, 169, + 91, 69, 214, 137, 21, 39, 51, 12, 201, 219, 42, 141, 80, 41, + 15, 252, 143, 21, 113, 184, 67, 25, 97, 40, 73, 136, 42, 110, + 99, 240, 217, 91, 88, 224, 158, 170, 37, 168, 199, 213, 141, 120, + 91, 226, 66, 246, 6, 171, 252, 116, 157, 74, 126, 41, 69, 64, + 239, 232, 124, 54, 211, 113, 122, 74, 21, 63, 64, 159, 236, 216, + 214, 237, 44, 120, 157, 165, 170, 121, 139, 53, 197, 34, 90, 81, + 231, 172, 1, 86, 188, 184, 3, 26, 94, 7, 199, 69, 222, 215, + 66, 210, 116, 40, 34, 129, 198, 237, 13, 248, 40, 169, 85, 118, + 26, 220, 63, 61, 227, 190, 159, 122, 129, 87, 170, 6, 254, 71, + 76, 20, 44, 64, 238, 243, 151, 254, 124, 80, 246, 206, 58, 205, + 29, 206, 74, 241, 189, 151, 125, 106, 37, 56, 140, 218, 13, 206, + 184, 81, 255, 232, 234, 186, 242, 199, 178, 6, 126, 142, 149, 157, + 42, 79, 12, 146, 187, 169, 192, 176, 143, 153, 168, 90, 75, 189, + 152, 134, 3, 83, 237, 145, 243, 39, 28, 100, 183, 167, 28, 240, + 82, 8, 216, 177, 123, 192, 82, 49, 252, 113, 10, 215, 247, 190, + 172, 225, 135, 119, 246, 88, 213, 170, 118, 63, 142, 199, 80, 70, + 103, 166, 222, 172, 156, 73, 228, 30, 14, 57, 234, 154, 75, 107, + 50, 57, 172, 135, 129, 226, 230, 28, 114, 70, 0, 151, 99, 73, + 246, 236, 18, 24, 119, 16, 117, 222, 201, 189, 250, 226, 254, 4, + 29, 63, 164, 29, 241, 50, 225, 134, 13, 95, 123, 177, 17, 81, + 194, 201, 123, 68, 21, 132, 148, 102, 225, 174, 143, 87, 129, 6, + 102, 174, 14, 255, 252, 29, 150, 143, 166, 212, 79, 0, 110, 181, + 91, 182, 69, 153, 208, 143, 64, 35, 206, 17, 182, 199, 143, 114, + 85, 11, 139, 234, 113, 177, 212, 214, 129, 224, 145, 77, 246, 238, + 141, 16, 202, 87, 132, 116, 131, 33, 17, 130, 58, 109, 226, 221, + 80, 56, 61, 54, 80, 249, 192, 104, 84, 129, 251, 178, 190, 153, + 211, 192, 199, 251, 117, 131, 179, 179, 63, 185, 18, 22, 100, 174, + 220, 30, 197, 154, 87, 57, 230, 238, 25, 32, 252, 111, 159, 68, + 166, 47, 30, 136, 67, 224, 30, 10, 115, 165, 123, 59, 25, 149, + 120, 151, 234, 80, 122, 245, 251, 25, 237, 44, 28, 87, 88, 34, + 27, 84, 171, 15, 117, 230, 102, 229, 203, 158, 135, 76, 253, 74, + 183, 59, 246, 90, 23, 245, 189, 26, 71, 157, 23, 145, 8, 167, + 123, 1, 75, 72, 90, 50, 119, 71, 25, 26, 100, 41, 103, 100, + 84, 75, 133, 13, 1, 244, 103, 93, 99, 9, 144, 121, 170, 169, + 204, 147, 213, 216, 247, 255, 187, 242, 172, 16, 119, 10, 13, 152, + 210, 167, 55, 71, 122, 83, 39, 3, 184, 177, 246, 179, 97, 245, + 160, 156, 240, 7, 142, 183, 5, 209, 195, 251, 44, 119, 10, 35, + 68, 207, 161, 104, 139, 237, 69, 227, 70, 38, 127, 91, 250, 255, + 99, 1, 10, 77, 213, 23, 133, 213, 215, 187, 203, 212, 171, 197, + 204, 227, 190, 163, 220, 45, 124, 184, 240, 117, 34, 199, 58, 93, + 53, 19, 189, 116, 169, 151, 99, 154, 84, 15, 90, 3, 97, 240, + 218, 176, 135, 91, 111, 232, 167, 174, 34, 136, 181, 75, 194, 107, + 160, 149, 167, 87, 11, 86, 94, 78, 134, 7, 194, 91, 190, 221, + 86, 217, 134, 135, 130, 89, 124, 15, 241, 189, 94, 169, 31, 132, + 116, 37, 251, 220, 239, 213, 105, 100, 106, 181, 190, 145, 156, 65, + 144, 211, 22, 160, 184, 113, 0, 34, 208, 247, 145, 95, 71, 59, + 233, 27, 125, 44, 0, 47, 13, 175, 236, 154, 81, 29, 26, 166, + 116, 212, 98, 183, 135, 247, 110, 216, 172, 204, 12, 178, 66, 148, + 91, 9, 163, 199, 114, 43, 152, 87, 14, 19, 144, 176, 227, 161, + 31, 85, 115, 98, 2, 17, 97, 144, 222, 25, 134, 180, 115, 194, + 72, 157, 142, 95, 142, 105, 140, 6, 166, 224, 163, 204, 225, 135, + 107, 199, 134, 246, 89, 141, 53, 127, 96, 157, 95, 24, 42, 196, + 10, 149, 82, 168, 13, 85, 214, 249, 36, 212, 236, 51, 70, 30, + 159, 185, 240, 164, 108, 101, 7, 50, 142, 116, 181, 53, 190, 92, + 144, 199, 134, 33, 164, 72, 163, 156, 58, 169, 21, 41, 156, 36, + 103, 169, 162, 173, 165, 20, 115, 245, 194, 19, 235, 101, 20, 202, + 156, 39, 153, 55, 217, 26, 97, 0, 189, 120, 138, 153, 7, 160, + 81, 182, 201, 26, 78, 63, 191, 116, 140, 56, 54, 62, 213, 251, + 88, 204, 158, 215, 138, 120, 70, 1, 126, 183, 209, 50, 3, 125, + 201, 214, 243, 219, 213, 105, 150, 48, 222, 58, 219, 205, 72, 178, + 204, 114, 143, 139, 93, 186, 146, 202, 194, 192, 246, 55, 73, 250, + 40, 39, 25, 224, 140, 207, 231, 55, 148, 223, 42, 205, 221, 121, + 92, 79, 254, 185, 171, 17, 227, 112, 58, 225, 202, 188, 115, 4, + 124, 153, 188, 106, 154, 32, 148, 122, 86, 159, 162, 238, 97, 230, + 196, 83, 22, 125, 11, 4, 124, 204, 16, 16, 38, 110, 127, 50, + 191, 165, 154, 126, 163, 17, 101, 249, 97, 21, 246, 30, 22, 228, + 243, 115, 115, 27, 214, 117, 55, 66, 140, 25, 96, 33, 120, 248, + 134, 34, 40, 180, 46, 132, 5, 183, 79, 106, 239, 175, 177, 31, + 126, 2, 162, 66, 147, 125, 201, 5, 58, 135, 8, 248, 75, 13, + 203, 207, 7, 193, 213, 136, 154, 105, 64, 145, 7, 130, 34, 11, + 104, 186, 148, 43, 196, 75, 49, 31, 72, 16, 64, 137, 185, 166, + 190, 102, 25, 58, 230, 97, 25, 205, 99, 1, 133, 215, 72, 232, + 53, 238, 170, 96, 182, 21, 167, 141, 81, 75, 7, 166, 146, 75, + 154, 237, 245, 51, 198, 129, 90, 1, 203, 53, 67, 115, 125, 23, + 13, 71, 56, 79, 12, 160, 69, 186, 122, 132, 176, 184, 195, 208, + 232, 176, 168, 136, 15, 149, 229, 212, 26, 134, 225, 225, 70, 225, + 198, 46, 141, 94, 3, 131, 183, 34, 118, 82, 185, 38, 15, 184, + 129, 239, 101, 89, 85, 235, 202, 212, 78, 237, 28, 25, 254, 33, + 79, 164, 170, 190, 143, 235, 186, 86, 142, 65, 18, 189, 14, 141, + 134, 34, 66, 10, 230, 204, 14, 204, 174, 43, 49, 244, 214, 185, + 213, 17, 37, 212, 232, 53, 60, 24, 19, 248, 56, 104, 23, 118, + 47, 18, 241, 23, 72, 63, 41, 176, 249, 224, 35, 35, 219, 10, + 61, 207, 148, 192, 12, 196, 166, 175, 199, 211, 9, 181, 135, 156, + 158, 35, 12, 106, 201, 255, 240, 125, 2, 33, 139, 29, 64, 23, + 42, 113, 159, 98, 2, 254, 14, 85, 181, 22, 58, 116, 49, 94, + 247, 63, 165, 188, 14, 234, 113, 178, 133, 37, 73, 177, 157, 163, + 159, 230, 132, 250, 132, 191, 235, 26, 55, 207, 42, 90, 242, 123, + 235, 58, 96, 12, 212, 157, 195, 177, 215, 221, 41, 181, 142, 188, + 97, 219, 24, 214, 246, 89, 176, 178, 68, 101, 10, 5, 99, 125, + 225, 150, 136, 72, 248, 149, 63, 64, 46, 130, 221, 88, 213, 154, + 88, 76, 49, 22, 71, 17, 79, 57, 243, 141, 54, 82, 87, 225, + 15, 213, 153, 58, 18, 57, 155, 215, 251, 24, 105, 99, 214, 97, + 213, 157, 50, 78, 156, 38, 156, 121, 46, 19, 116, 4, 147, 210, + 77, 88, 146, 219, 63, 103, 47, 181, 31, 140, 102, 39, 40, 137, + 66, 204, 176, 29, 2, 105, 78, 87, 139, 213, 202, 10, 168, 159, + 161, 65, 216, 195, 240, 37, 250, 145, 8, 219, 43, 164, 185, 19, + 26, 197, 111, 8, 89, 68, 17, 3, 100, 93, 183, 69, 203, 38, + 126, 157, 6, 225, 52, 140, 73, 240, 74, 182, 193, 217, 202, 83, + 155, 217, 88, 183, 173, 91, 173, 214, 168, 62, 40, 21, 42, 70, + 16, 15, 77, 220, 110, 133, 157, 192, 6, 145, 179, 245, 95, 161, + 217, 41, 1, 94, 202, 3, 167, 2, 118, 250, 63, 66, 117, 225, + 250, 167, 38, 166, 145, 145, 250, 185, 26, 107, 160, 235, 125, 85, + 106, 146, 227, 115, 87, 2, 112, 161, 164, 115, 105, 183, 157, 192, + 92, 89, 221, 73, 142, 60, 67, 69, 87, 139, 90, 248, 1, 183, + 153, 72, 64, 202, 47, 9, 191, 208, 32, 126, 3, 237, 230, 110, + 36, 86, 85, 144, 10, 108, 255, 190, 94, 195, 30, 129, 71, 239, + 50, 182, 231, 116, 137, 74, 128, 121, 137, 205, 81, 176, 201, 137, + 9, 243, 82, 237, 83, 119, 73, 158, 73, 86, 15, 126, 101, 131, + 39, 220, 208, 37, 115, 169, 109, 192, 174, 100, 77, 162, 125, 153, + 124, 79, 125, 131, 169, 159, 253, 90, 188, 173, 27, 0, 215, 232, + 29, 189, 225, 2, 179, 88, 254, 155, 35, 108, 106, 67, 183, 16, + 189, 8, 248, 145, 172, 39, 185, 193, 147, 255, 180, 82, 59, 100, + 4, 23, 107, 221, 1, 143, 94, 37, 166, 61, 161, 205, 223, 168, + 19, 56, 72, 197, 63, 215, 202, 15, 37, 85, 111, 234, 253, 81, + 162, 147, 87, 77, 215, 93, 34, 177, 44, 191, 197, 12, 151, 125, + 176, 136, 90, 15, 250, 171, 92, 180, 115, 60, 10, 27, 102, 239, + 150, 135, 116, 155, 157, 191, 30, 31, 241, 148, 222, 245, 222, 239, + 44, 146, 174, 232, 219, 17, 107, 69, 15, 95, 212, 152, 58, 246, + 77, 198, 23, 210, 100, 195, 39, 211, 13, 7, 136, 52, 239, 115, + 1, 229, 241, 70, 23, 178, 26, 30, 145, 145, 67, 48, 222, 53, + 203, 236, 127, 241, 71, 96, 135, 128, 10, 86, 168, 146, 118, 116, + 171, 166, 122, 153, 193, 255, 92, 109, 178, 116, 37, 92, 187, 4, + 218, 5, 169, 56, 85, 69, 232, 102, 197, 45, 42, 138, 247, 16, + 221, 30, 108, 71, 91, 123, 199, 223, 156, 18, 110, 195, 132, 109, + 189, 12, 169, 188, 239, 106, 165, 17, 190, 194, 49, 60, 240, 205, + 96, 170, 216, 60, 135, 15, 133, 213, 126, 9, 97, 129, 209, 111, + 244, 80, 59, 78, 204, 224, 121, 73, 137, 99, 209, 136, 165, 244, + 176, 128, 86, 238, 122, 151, 91, 57, 167, 41, 69, 141, 24, 23, + 230, 61, 222, 108, 30, 214, 137, 218, 39, 148, 178, 160, 206, 134, + 22, 174, 231, 209, 119, 185, 254, 203, 50, 159, 53, 175, 227, 20, + 91, 79, 205, 247, 39, 11, 237, 105, 98, 255, 224, 248, 126, 58, + 87, 121, 174, 208, 159, 157, 34, 219, 219, 125, 174, 34, 48, 60, + 71, 28, 245, 238, 228, 163, 30, 245, 181, 49, 74, 199, 90, 13, + 144, 131, 206, 47, 122, 15, 190, 169, 154, 191, 243, 61, 207, 104, + 199, 38, 114, 143, 128, 144, 144, 125, 238, 6, 181, 61, 46, 82, + 197, 220, 144, 166, 232, 13, 243, 222, 89, 198, 178, 76, 35, 56, + 181, 212, 105, 122, 156, 231, 64, 90, 13, 27, 114, 227, 68, 209, + 13, 210, 115, 197, 100, 124, 32, 22, 112, 179, 71, 24, 34, 86, + 237, 70, 66, 245, 169, 57, 41, 114, 12, 179, 59, 17, 45, 6, + 143, 88, 216, 85, 92, 198, 175, 34, 224, 236, 158, 81, 158, 154, + 115, 135, 58, 50, 234, 75, 139, 146, 159, 73, 10, 216, 58, 124, + 166, 246, 157, 28, 193, 77, 17, 23, 38, 185, 204, 150, 201, 70, + 45, 221, 89, 55, 241, 157, 185, 156, 202, 130, 51, 235, 80, 127, + 168, 147, 222, 135, 74, 222, 183, 166, 202, 48, 219, 6, 112, 207, + 179, 2, 30, 251, 89, 204, 161, 46, 1, 118, 129, 240, 68, 233, + 251, 65, 116, 66, 182, 93, 85, 38, 166, 178, 2, 231, 11, 158, + 164, 197, 249, 195, 63, 219, 128, 187, 56, 113, 205, 47, 59, 63, + 206, 49, 50, 133, 198, 244, 12, 12, 181, 127, 104, 144, 114, 179, + 248, 101, 29, 179, 186, 246, 203, 227, 118, 156, 195, 49, 247, 58, + 201, 73, 155, 174, 71, 158, 229, 130, 58, 42, 3, 156, 246, 109, + 72, 12, 253, 81, 139, 218, 230, 21, 21, 226, 43, 97, 80, 163, + 251, 38, 209, 64, 7, 114, 179, 86, 255, 65, 43, 141, 33, 144, + 124, 236, 15, 40, 90, 249, 201, 187, 166, 201, 199, 23, 51, 235, + 85, 8, 232, 19, 153, 165, 230, 38, 207, 232, 57, 246, 202, 185, + 92, 117, 115, 218, 52, 59, 84, 55, 37, 110, 218, 102, 108, 174, + 115, 220, 161, 40, 182, 87, 29, 208, 180, 14, 147, 244, 146, 103, + 19, 36, 193, 179, 234, 93, 228, 40, 90, 17, 136, 199, 182, 11, + 91, 204, 91, 176, 140, 115, 179, 129, 86, 33, 202, 45, 171, 226, + 45, 98, 7, 139, 5, 151, 39, 118, 109, 246, 154, 28, 44, 58, + 57, 77, 186, 213, 83, 184, 242, 49, 138, 218, 119, 69, 254, 201, + 83, 52, 202, 116, 26, 184, 240, 13, 142, 86, 143, 157, 248, 80, + 112, 163, 72, 128, 84, 87, 206, 134, 144, 250, 40, 149, 0, 61, + 94, 20, 119, 42, 195, 248, 217, 40, 245, 217, 92, 242, 71, 113, + 70, 169, 48, 216, 249, 182, 145, 113, 253, 163, 234, 149, 33, 236, + 9, 236, 146, 189, 249, 110, 134, 252, 22, 25, 211, 196, 201, 114, + 107, 133, 209, 180, 31, 14, 191, 183, 180, 93, 209, 94, 133, 117, + 59, 88, 235, 76, 189, 3, 52, 220, 48, 136, 181, 217, 73, 33, + 51, 176, 71, 48, 187, 146, 124, 5, 150, 48, 93, 162, 196, 71, + 155, 199, 253, 6, 164, 98, 78, 1, 22, 205, 60, 33, 123, 51, + 15, 37, 67, 222, 147, 167, 191, 45, 160, 165, 184, 131, 129, 135, + 80, 124, 7, 20, 39, 9, 102, 46, 225, 190, 5, 249, 29, 37, + 230, 91, 199, 170, 59, 37, 221, 226, 54, 40, 129, 181, 90, 58, + 57, 10, 173, 196, 205, 214, 47, 67, 254, 70, 244, 194, 133, 166, + 122, 73, 255, 234, 82, 94, 58, 236, 9, 105, 17, 32, 32, 170, + 198, 109, 119, 249, 112, 251, 130, 146, 207, 17, 186, 146, 24, 99, + 154, 95, 27, 48, 198, 91, 83, 58, 205, 11, 120, 1, 64, 168, + 28, 95, 130, 136, 227, 148, 191, 133, 246, 183, 106, 247, 219, 3, + 122, 54, 173, 95, 10, 249, 77, 236, 37, 60, 240, 161, 24, 193, + 194, 196, 208, 33, 38, 103, 90, 111, 195, 113, 107, 141, 211, 64, + 163, 249, 144, 132, 2, 254, 85, 140, 237, 4, 122, 154, 14, 80, + 63, 12, 49, 32, 6, 165, 186, 202, 122, 116, 170, 77, 84, 121, + 230, 16, 236, 9, 43, 45, 164, 127, 3, 37, 40, 30, 125, 155, + 140, 49, 46, 73, 134, 193, 104, 254, 0, 87, 165, 129, 240, 51, + 24, 41, 224, 238, 246, 153, 193, 94, 195, 244, 188, 114, 34, 130, + 132, 123, 9, 151, 99, 48, 27, 188, 233, 185, 8, 222, 41, 252, + 149, 245, 118, 233, 197, 46, 84, 176, 216, 182, 224, 152, 60, 189, + 41, 95, 202, 110, 248, 70, 165, 96, 180, 101, 232, 112, 174, 48, + 26, 237, 148, 103, 57, 156, 59, 243, 19, 161, 224, 148, 214, 224, + 69, 198, 74, 51, 252, 31, 44, 97, 36, 178, 114, 202, 90, 224, + 156, 24, 186, 84, 114, 212, 95, 215, 81, 12, 119, 212, 253, 13, + 82, 132, 145, 135, 21, 82, 42, 70, 196, 30, 114, 145, 147, 174, + 2, 41, 142, 69, 131, 124, 192, 222, 207, 159, 95, 159, 63, 234, + 109, 33, 212, 56, 15, 204, 109, 25, 252, 39, 143, 108, 28, 176, + 117, 137, 188, 22, 71, 74, 191, 233, 211, 199, 85, 140, 59, 45, + 145, 70, 175, 2, 193, 11, 205, 141, 36, 205, 198, 1, 95, 50, + 175, 130, 5, 139, 161, 87, 210, 18, 195, 106, 164, 250, 78, 154, + 197, 2, 117, 126, 87, 54, 64, 85, 55, 154, 114, 136, 220, 187, + 14, 179, 42, 221, 50, 243, 128, 84, 92, 5, 124, 74, 18, 131, + 105, 115, 205, 226, 202, 137, 187, 35, 82, 164, 147, 205, 114, 207, + 75, 205, 137, 254, 134, 155, 201, 49, 228, 220, 196, 53, 79, 72, + 28, 24, 0, 107, 210, 90, 180, 48, 134, 204, 134, 246, 150, 113, + 235, 198, 22, 167, 105, 19, 123, 136, 225, 140, 67, 157, 111, 188, + 48, 161, 95, 144, 34, 202, 244, 111, 223, 8, 240, 35, 90, 182, + 249, 6, 160, 10, 218, 178, 216, 245, 195, 60, 224, 13, 136, 35, + 239, 123, 233, 48, 171, 155, 132, 122, 74, 136, 223, 150, 77, 43, + 254, 204, 36, 177, 106, 61, 99, 111, 22, 21, 198, 178, 22, 54, + 216, 67, 23, 49, 250, 4, 23, 206, 126, 208, 109, 81, 85, 213, + 171, 198, 20, 149, 98, 130, 22, 74, 31, 47, 68, 87, 243, 231, + 156, 161, 109, 23, 254, 151, 112, 35, 144, 232, 46, 128, 78, 93, + 18, 227, 6, 136, 226, 218, 209, 254, 167, 96, 57, 110, 87, 238, + 220, 98, 221, 119, 176, 180, 150, 248, 150, 200, 129, 240, 178, 81, + 166, 54, 242, 3, 15, 65, 154, 207, 236, 161, 57, 41, 168, 155, + 212, 94, 3, 197, 198, 205, 27, 133, 214, 160, 81, 77, 179, 15, + 242, 221, 44, 202, 36, 211, 35, 98, 74, 119, 235, 233, 246, 223, + 42, 179, 253, 35, 255, 44, 26, 253, 204, 92, 21, 117, 54, 35, + 184, 128, 63, 134, 73, 94, 8, 30, 130, 113, 224, 83, 149, 83, + 134, 145, 122, 204, 82, 67, 145, 27, 103, 217, 135, 135, 199, 95, + 108, 171, 247, 14, 78, 83, 204, 32, 214, 160, 46, 143, 66, 56, + 149, 160, 134, 144, 95, 150, 117, 66, 29, 148, 18, 75, 91, 22, + 253, 229, 97, 38, 227, 16, 33, 139, 222, 241, 27, 70, 3, 99, + 29, 12, 0, 172, 253, 59, 58, 38, 70, 154, 135, 109, 78, 190, + 160, 154, 186, 3, 172, 101, 81, 238, 34, 83, 76, 56, 142, 54, + 90, 204, 45, 123, 224, 143, 67, 243, 172, 239, 146, 123, 253, 93, + 235, 110, 73, 8, 179, 135, 26, 219, 236, 190, 186, 181, 118, 139, + 189, 180, 222, 111, 61, 30, 223, 51, 44, 235, 129, 94, 113, 89, + 14, 61, 154, 103, 221, 254, 136, 212, 153, 87, 13, 122, 207, 119, + 72, 165, 2, 146, 207, 149, 176, 9, 31, 201, 100, 208, 15, 160, + 164, 179, 160, 59, 98, 99, 226, 183, 88, 50, 250, 117, 11, 204, + 185, 62, 156, 232, 220, 77, 78, 9, 134, 184, 62, 59, 189, 97, + 100, 30, 8, 206, 57, 250, 88, 102, 170, 84, 75, 192, 181, 160, + 70, 151, 143, 167, 212, 83, 67, 221, 123, 103, 37, 162, 137, 214, + 57, 90, 100, 78, 27, 154, 112, 152, 76, 46, 155, 185, 225, 193, + 148, 132, 21, 30, 117, 224, 82, 53, 255, 13, 0, 138, 245, 251, + 41, 109, 176, 168, 97, 125, 131, 138, 165, 154, 77, 213, 179, 146, + 109, 92, 88, 227, 250, 114, 155, 253, 78, 255, 252, 88, 190, 185, + 233, 111, 59, 65, 238, 185, 143, 22, 226, 251, 225, 4, 182, 10, + 221, 227, 42, 203, 248, 252, 25, 116, 55, 105, 44, 64, 192, 24, + 126, 51, 244, 87, 89, 237, 86, 37, 106, 0, 187, 118, 240, 64, + 74, 168, 18, 45, 35, 50, 107, 185, 182, 104, 140, 30, 197, 202, + 101, 21, 51, 55, 53, 81, 108, 107, 255, 7, 190, 84, 14, 105, + 55, 31, 53, 210, 207, 138, 165, 244, 84, 70, 142, 169, 111, 217, + 18, 148, 46, 79, 142, 114, 222, 106, 104, 189, 189, 96, 241, 41, + 188, 24, 32, 201, 246, 208, 26, 199, 1, 150, 247, 208, 20, 155, + 87, 30, 131, 138, 90, 99, 25, 72, 171, 31, 197, 54, 163, 185, + 96, 236, 60, 113, 63, 113, 205, 189, 48, 116, 158, 71, 166, 161, + 185, 161, 24, 97, 74, 79, 199, 110, 238, 229, 143, 203, 20, 4, + 204, 203, 74, 157, 22, 78, 21, 24, 203, 217, 234, 87, 45, 231, + 34, 24, 84, 118, 177, 65, 138, 193, 3, 110, 195, 233, 145, 112, + 227, 60, 247, 253, 255, 190, 180, 155, 134, 174, 238, 124, 71, 78, + 73, 28, 198, 48, 157, 50, 147, 75, 135, 191, 5, 0, 190, 219, + 214, 22, 127, 218, 54, 104, 149, 48, 19, 76, 81, 178, 232, 21, + 160, 33, 46, 99, 49, 191, 227, 143, 56, 208, 151, 254, 140, 102, + 117, 200, 239, 205, 156, 172, 164, 59, 5, 249, 7, 191, 214, 73, + 202, 66, 50, 56, 12, 140, 48, 130, 56, 83, 44, 164, 98, 34, + 153, 170, 46, 149, 208, 125, 102, 39, 174, 247, 150, 213, 57, 10, + 16, 214, 55, 175, 136, 56, 110, 76, 40, 74, 6, 227, 32, 22, + 53, 238, 211, 249, 240, 189, 220, 20, 182, 40, 80, 111, 239, 180, + 246, 122, 52, 125, 116, 219, 14, 105, 111, 242, 254, 69, 77, 66, + 240, 222, 243, 66, 100, 54, 143, 255, 206, 52, 143, 21, 44, 34, + 202, 76, 16, 76, 135, 21, 98, 225, 116, 44, 76, 5, 7, 122, + 210, 50, 242, 171, 251, 204, 229, 176, 243, 167, 124, 61, 157, 177, + 26, 231, 228, 93, 179, 202, 1, 31, 95, 151, 44, 190, 128, 243, + 157, 190, 220, 12, 116, 194, 114, 118, 128, 68, 63, 44, 100, 142, + 80, 251, 199, 98, 194, 246, 206, 57, 54, 96, 137, 116, 247, 60, + 4, 68, 124, 108, 142, 184, 91, 159, 224, 159, 101, 202, 40, 208, + 181, 54, 230, 202, 225, 122, 211, 95, 29, 239, 171, 205, 17, 150, + 114, 110, 231, 212, 32, 41, 81, 78, 186, 153, 63, 217, 205, 104, + 90, 247, 5, 192, 24, 81, 249, 248, 122, 215, 1, 104, 220, 88, + 79, 56, 116, 183, 58, 108, 1, 129, 57, 44, 126, 2, 229, 216, + 72, 176, 81, 23, 73, 250, 129, 179, 81, 92, 9, 53, 37, 235, + 4, 68, 81, 186, 174, 51, 63, 50, 38, 233, 239, 238, 46, 239, + 66, 74, 200, 212, 219, 143, 88, 153, 217, 53, 35, 244, 10, 40, + 120, 235, 50, 238, 44, 64, 18, 37, 254, 231, 178, 245, 160, 42, + 181, 188, 14, 50, 104, 176, 165, 133, 223, 159, 205, 98, 21, 231, + 221, 85, 182, 93, 67, 250, 76, 61, 129, 113, 33, 139, 205, 28, + 3, 251, 62, 66, 200, 59, 126, 103, 96, 94, 34, 49, 103, 101, + 188, 20, 230, 8, 223, 21, 160, 110, 216, 81, 169, 255, 180, 133, + 131, 136, 15, 98, 194, 102, 77, 164, 121, 184, 84, 192, 86, 12, + 61, 64, 3, 107, 63, 170, 92, 187, 94, 179, 59, 86, 18, 104, + 45, 179, 81, 143, 65, 184, 30, 225, 173, 186, 184, 176, 191, 73, + 110, 105, 176, 250, 180, 191, 181, 45, 159, 234, 233, 112, 164, 8, + 235, 180, 163, 108, 6, 87, 45, 150, 15, 45, 29, 186, 214, 82, + 108, 59, 151, 19, 188, 39, 240, 108, 250, 84, 212, 12, 65, 174, + 247, 104, 29, 23, 59, 240, 55, 92, 177, 35, 195, 224, 72, 90, + 67, 28, 37, 143, 173, 56, 161, 99, 143, 175, 3, 176, 58, 246, + 169, 74, 189, 30, 129, 158, 79, 192, 243, 122, 100, 104, 212, 77, + 73, 95, 153, 233, 113, 163, 94, 34, 225, 40, 8, 132, 197, 178, + 10, 163, 207, 187, 145, 65, 147, 105, 202, 136, 221, 151, 148, 131, + 102, 46, 54, 96, 121, 28, 76, 182, 39, 244, 10, 182, 200, 212, + 128, 155, 78, 20, 18, 39, 102, 77, 128, 44, 6, 165, 113, 193, + 104, 89, 76, 171, 23, 18, 247, 229, 53, 145, 202, 184, 90, 112, + 158, 102, 252, 169, 89, 233, 201, 36, 55, 229, 32, 84, 73, 95, + 84, 206, 52, 239, 184, 69, 110, 213, 10, 244, 219, 238, 229, 198, + 210, 123, 172, 251, 87, 26, 92, 237, 157, 228, 255, 110, 151, 68, + 160, 220, 230, 18, 144, 243, 0, 190, 225, 25, 103, 168, 226, 213, + 250, 241, 137, 177, 227, 248, 7, 39, 151, 109, 174, 111, 187, 174, + 139, 50, 249, 240, 97, 33, 215, 193, 133, 48, 90, 210, 85, 202, + 21, 148, 116, 18, 138, 249, 237, 222, 178, 12, 66, 21, 122, 43, + 75, 188, 25, 43, 239, 179, 163, 218, 218, 101, 197, 246, 117, 250, + 56, 77, 168, 142, 2, 113, 9, 221, 154, 73, 242, 215, 247, 151, + 67, 158, 28, 173, 168, 211, 45, 103, 225, 110, 106, 81, 5, 104, + 75, 8, 54, 163, 96, 64, 212, 106, 222, 51, 182, 78, 13, 96, + 167, 43, 207, 249, 73, 150, 37, 104, 76, 26, 179, 106, 178, 99, + 40, 188, 227, 75, 52, 41, 134, 99, 141, 112, 20, 24, 105, 138, + 105, 104, 131, 74, 235, 77, 175, 164, 7, 49, 235, 210, 242, 47, + 175, 66, 34, 45, 186, 214, 109, 251, 169, 185, 17, 160, 239, 61, + 169, 10, 108, 36, 217, 255, 111, 158, 75, 223, 160, 184, 210, 222, + 151, 196, 196, 50, 179, 192, 128, 24, 200, 150, 224, 69, 175, 73, + 207, 141, 241, 25, 216, 163, 164, 81, 95, 35, 110, 238, 233, 181, + 169, 201, 165, 254, 215, 88, 207, 248, 115, 58, 191, 201, 19, 161, + 252, 31, 89, 235, 27, 47, 231, 53, 39, 155, 207, 28, 58, 226, + 153, 102, 114, 138, 246, 86, 11, 72, 22, 154, 250, 121, 182, 97, + 171, 200, 154, 163, 52, 31, 85, 84, 149, 169, 86, 189, 190, 219, + 112, 189, 171, 185, 95, 87, 72, 134, 238, 93, 120, 202, 27, 131, + 40, 141, 85, 247, 73, 75, 188, 42, 120, 67, 88, 238, 252, 101, + 78, 146, 195, 6, 22, 25, 149, 50, 126, 138, 216, 183, 36, 86, + 140, 186, 244, 27, 69, 148, 235, 93, 129, 242, 146, 189, 123, 219, + 170, 153, 8, 194, 230, 27, 90, 81, 240, 110, 86, 223, 65, 155, + 34, 173, 84, 183, 7, 234, 130, 124, 248, 9, 116, 104, 3, 5, + 100, 130, 69, 73, 200, 242, 193, 206, 127, 71, 105, 12, 120, 61, + 231, 178, 146, 240, 52, 192, 202, 138, 204, 45, 15, 214, 166, 101, + 66, 12, 202, 46, 169, 243, 127, 24, 165, 99, 168, 139, 161, 88, + 110, 129, 102, 137, 116, 72, 31, 3, 80, 239, 134, 171, 71, 174, + 207, 74, 121, 189, 156, 246, 147, 252, 165, 143, 207, 78, 151, 184, + 49, 235, 192, 124, 136, 90, 250, 102, 72, 59, 252, 33, 164, 252, + 176, 224, 71, 106, 169, 203, 74, 55, 59, 118, 237, 170, 229, 197, + 66, 140, 131, 95, 211, 223, 227, 149, 209, 6, 0, 84, 36, 109, + 221, 137, 188, 13, 60, 227, 103, 252, 60, 74, 173, 4, 223, 44, + 45, 188, 255, 148, 123, 92, 100, 40, 27, 170, 125, 138, 1, 250, + 149, 247, 221, 0, 149, 41, 167, 175, 160, 118, 66, 135, 19, 183, + 25, 166, 18, 78, 220, 33, 217, 155, 248, 217, 225, 79, 87, 57, + 179, 27, 7, 33, 165, 103, 83, 34, 14, 107, 70, 142, 159, 48, + 68, 178, 116, 192, 244, 107, 149, 195, 246, 15, 173, 180, 9, 115, + 186, 79, 146, 146, 68, 119, 53, 218, 201, 110, 153, 135, 13, 42, + 252, 249, 77, 92, 230, 215, 137, 84, 68, 8, 115, 16, 140, 243, + 37, 126, 110, 178, 134, 3, 138, 107, 18, 40, 140, 82, 188, 228, + 204, 17, 159, 63, 250, 202, 30, 151, 55, 32, 1, 105, 191, 152, + 65, 35, 237, 191, 83, 204, 75, 160, 81, 198, 160, 174, 203, 58, + 158, 108, 155, 102, 214, 241, 122, 111, 66, 157, 231, 184, 244, 130, + 24, 66, 139, 254, 1, 1, 3, 68, 71, 151, 13, 185, 65, 99, + 206, 95, 53, 198, 254, 218, 126, 187, 231, 140, 8, 207, 110, 240, + 81, 195, 177, 250, 254, 26, 238, 59, 218, 202, 47, 107, 206, 211, + 163, 237, 189, 213, 141, 135, 244, 252, 38, 80, 168, 199, 148, 19, + 101, 246, 174, 64, 254, 102, 56, 107, 15, 109, 95, 252, 235, 81, + 197, 211, 103, 225, 153, 92, 76, 128, 213, 8, 213, 169, 86, 149, + 235, 155, 97, 107, 37, 92, 137, 57, 142, 93, 21, 12, 179, 107, + 179, 72, 171, 164, 214, 140, 79, 95, 144, 188, 46, 216, 177, 195, + 74, 70, 238, 230, 118, 13, 242, 25, 244, 181, 93, 163, 63, 215, + 45, 188, 226, 209, 254, 92, 177, 63, 160, 128, 117, 49, 243, 175, + 72, 247, 65, 110, 64, 141, 20, 43, 95, 15, 91, 95, 51, 71, + 109, 172, 4, 127, 92, 17, 100, 201, 232, 73, 232, 41, 5, 8, + 163, 55, 220, 1, 72, 23, 2, 19, 122, 18, 144, 221, 45, 71, + 99, 16, 169, 146, 168, 169, 63, 39, 68, 151, 53, 149, 70, 223, + 27, 112, 54, 133, 83, 2, 77, 121, 228, 97, 121, 180, 182, 74, + 65, 120, 177, 31, 216, 164, 35, 79, 251, 179, 220, 240, 166, 129, + 241, 114, 69, 39, 170, 202, 164, 53, 161, 190, 224, 132, 17, 87, + 29, 134, 212, 19, 76, 140, 21, 133, 38, 43, 75, 48, 114, 82, + 84, 58, 135, 102, 22, 80, 30, 111, 230, 247, 208, 84, 94, 250, + 220, 23, 17, 242, 78, 62, 98, 185, 151, 88, 116, 195, 95, 193, + 171, 48, 88, 25, 131, 126, 133, 93, 92, 61, 68, 203, 183, 183, + 144, 16, 227, 28, 10, 154, 136, 194, 58, 172, 103, 163, 155, 121, + 249, 110, 129, 118, 93, 222, 225, 6, 132, 80, 135, 94, 167, 94, + 47, 52, 128, 140, 1, 228, 145, 115, 85, 96, 102, 186, 98, 144, + 32, 181, 255, 86, 90, 31, 29, 151, 37, 102, 93, 77, 163, 110, + 113, 202, 233, 238, 27, 220, 242, 1, 23, 175, 232, 231, 255, 72, + 44, 15, 214, 171, 199, 67, 190, 61, 102, 131, 168, 152, 176, 253, + 214, 63, 48, 235, 112, 211, 104, 96, 215, 186, 185, 168, 56, 173, + 107, 63, 32, 53, 68, 25, 68, 44, 243, 3, 149, 158, 90, 64, + 185, 25, 168, 157, 2, 152, 239, 18, 249, 33, 21, 227, 104, 115, + 153, 161, 66, 35, 65, 240, 34, 224, 12, 229, 143, 235, 92, 224, + 249, 121, 204, 99, 89, 140, 212, 171, 14, 96, 52, 92, 217, 148, + 3, 66, 254, 154, 54, 14, 161, 230, 231, 13, 174, 146, 219, 244, + 7, 63, 185, 146, 128, 33, 13, 164, 162, 194, 9, 57, 107, 255, + 11, 111, 119, 204, 239, 1, 248, 8, 119, 4, 13, 29, 122, 231, + 108, 111, 73, 231, 77, 179, 105, 91, 76, 247, 20, 162, 58, 105, + 142, 233, 245, 45, 32, 84, 145, 47, 119, 103, 246, 93, 93, 195, + 248, 211, 180, 166, 55, 79, 167, 228, 23, 86, 139, 154, 7, 28, + 56, 174, 59, 155, 14, 154, 151, 207, 221, 28, 144, 116, 34, 190, + 219, 102, 74, 85, 180, 155, 158, 22, 45, 243, 189, 59, 29, 77, + 127, 42, 99, 108, 128, 234, 40, 212, 38, 224, 71, 58, 157, 161, + 237, 107, 104, 53, 236, 223, 125, 74, 87, 25, 17, 76, 36, 150, + 252, 222, 111, 177, 124, 146, 36, 162, 159, 132, 68, 242, 252, 169, + 95, 115, 12, 105, 14, 197, 77, 41, 127, 66, 127, 24, 33, 68, + 214, 61, 220, 97, 141, 14, 255, 131, 211, 53, 197, 31, 115, 56, + 153, 255, 125, 6, 75, 209, 231, 137, 74, 107, 252, 18, 62, 218, + 166, 200, 194, 105, 129, 136, 128, 144, 7, 230, 101, 174, 184, 222, + 162, 165, 243, 156, 247, 160, 171, 156, 193, 68, 129, 126, 247, 249, + 70, 3, 57, 191, 157, 165, 134, 112, 234, 224, 236, 32, 89, 10, + 234, 161, 255, 149, 187, 47, 197, 82, 219, 176, 85, 10, 37, 43, + 85, 50, 227, 178, 98, 192, 44, 68, 188, 87, 85, 131, 45, 49, + 209, 140, 81, 37, 144, 120, 229, 128, 79, 31, 124, 21, 47, 244, + 28, 230, 210, 75, 145, 214, 118, 245, 2, 232, 159, 243, 224, 84, + 249, 189, 39, 108, 183, 77, 162, 44, 191, 151, 164, 235, 133, 144, + 22, 47, 129, 155, 232, 157, 134, 126, 63, 130, 223, 124, 236, 255, + 6, 101, 14, 4, 85, 6, 2, 74, 127, 90, 140, 59, 50, 166, + 54, 209, 97, 99, 93, 121, 114, 23, 16, 174, 192, 248, 66, 85, + 94, 55, 185, 42, 66, 25, 108, 128, 125, 71, 188, 114, 100, 111, + 206, 250, 163, 237, 121, 10, 19, 87, 139, 66, 188, 217, 103, 238, + 170, 75, 235, 73, 40, 76, 71, 27, 47, 9, 239, 120, 116, 96, + 30, 125, 162, 77, 162, 76, 149, 38, 190, 119, 183, 189, 231, 70, + 216, 163, 74, 133, 80, 37, 11, 177, 32, 6, 118, 236, 155, 17, + 191, 116, 140, 87, 108, 114, 36, 82, 104, 6, 207, 66, 223, 2, + 53, 62, 107, 4, 61, 200, 56, 114, 239, 107, 155, 202, 34, 255, + 104, 193, 164, 208, 42, 70, 149, 229, 252, 137, 89, 101, 83, 244, + 152, 202, 90, 40, 163, 149, 79, 49, 138, 35, 143, 36, 49, 26, + 134, 161, 173, 155, 153, 103, 242, 158, 230, 198, 80, 246, 63, 33, + 241, 252, 79, 204, 79, 134, 167, 117, 30, 39, 51, 247, 189, 103, + 150, 172, 19, 199, 81, 181, 181, 199, 254, 57, 71, 192, 240, 75, + 157, 171, 70, 113, 123, 13, 55, 232, 138, 41, 214, 205, 172, 214, + 24, 86, 244, 231, 189, 255, 18, 36, 81, 166, 62, 181, 221, 6, + 34, 173, 249, 91, 155, 148, 73, 62, 46, 185, 106, 133, 136, 58, + 20, 80, 1, 128, 121, 200, 18, 108, 20, 152, 153, 122, 234, 210, + 233, 253, 39, 51, 154, 236, 183, 150, 76, 54, 2, 21, 70, 5, + 64, 130, 153, 238, 36, 42, 112, 51, 196, 78, 196, 183, 164, 250, + 35, 188, 205, 71, 213, 241, 47, 4, 110, 51, 238, 243, 239, 181, + 163, 51, 64, 98, 133, 235, 42, 148, 132, 157, 175, 12, 68, 255, + 211, 98, 71, 115, 77, 19, 116, 222, 18, 228, 118, 79, 243, 10, + 147, 63, 254, 151, 84, 156, 62, 27, 22, 157, 208, 118, 6, 27, + 21, 21, 196, 52, 185, 190, 114, 230, 209, 136, 47, 99, 154, 92, + 96, 59, 189, 133, 11, 225, 158, 143, 148, 40, 241, 101, 73, 183, + 60, 8, 0, 200, 229, 77, 122, 22, 48, 130, 69, 25, 223, 48, + 205, 171, 195, 208, 188, 63, 151, 77, 27, 151, 89, 77, 41, 129, + 105, 21, 176, 217, 128, 29, 64, 138, 192, 74, 162, 254, 194, 19, + 110, 223, 246, 211, 64, 184, 138, 181, 167, 4, 248, 64, 107, 15, + 58, 239, 52, 47, 196, 170, 149, 55, 35, 117, 106, 186, 66, 4, + 242, 117, 170, 207, 189, 149, 118, 203, 163, 63, 18, 131, 255, 135, + 255, 29, 169, 163, 76, 120, 224, 116, 37, 169, 222, 74, 84, 190, + 194, 90, 66, 216, 112, 109, 7, 51, 200, 72, 126, 67, 238, 171, + 106, 71, 197, 236, 128, 77, 28, 38, 165, 78, 193, 239, 43, 164, + 119, 121, 0, 126, 145, 207, 179, 5, 74, 165, 53, 32, 69, 159, + 136, 112, 143, 32, 63, 132, 253, 13, 35, 177, 252, 25, 150, 108, + 104, 42, 30, 230, 214, 92, 98, 29, 224, 71, 75, 145, 32, 111, + 13, 42, 204, 105, 236, 124, 72, 104, 5, 37, 164, 226, 214, 192, + 76, 18, 160, 58, 35, 18, 149, 229, 135, 222, 13, 59, 108, 84, + 64, 35, 136, 240, 91, 234, 162, 112, 233, 181, 23, 147, 1, 232, + 122, 121, 68, 144, 136, 56, 212, 43, 228, 36, 103, 15, 198, 184, + 90, 231, 17, 192, 113, 27, 128, 90, 41, 137, 194, 100, 242, 43, + 55, 227, 55, 156, 114, 166, 58, 142, 45, 91, 25, 206, 137, 209, + 57, 252, 55, 79, 162, 168, 185, 58, 61, 113, 180, 135, 233, 113, + 199, 72, 182, 4, 187, 192, 93, 225, 225, 142, 229, 102, 159, 160, + 52, 179, 6, 186, 60, 202, 121, 48, 221, 91, 173, 160, 88, 44, + 219, 177, 237, 18, 185, 120, 25, 174, 18, 182, 238, 116, 68, 157, + 61, 26, 103, 189, 84, 192, 184, 96, 36, 147, 251, 15, 160, 166, + 247, 174, 45, 170, 197, 109, 24, 71, 242, 117, 194, 59, 243, 64, + 116, 101, 130, 122, 155, 171, 77, 80, 195, 233, 196, 92, 219, 214, + 123, 57, 165, 117, 137, 131, 91, 2, 100, 54, 30, 29, 43, 35, + 125, 53, 209, 58, 140, 11, 54, 189, 49, 111, 125, 226, 58, 12, + 167, 96, 214, 185, 76, 33, 63, 35, 223, 139, 125, 52, 188, 1, + 171, 54, 148, 165, 113, 231, 60, 140, 250, 241, 186, 0, 5, 19, + 202, 236, 100, 222, 25, 195, 157, 195, 155, 185, 132, 18, 126, 41, + 153, 128, 248, 100, 128, 217, 207, 235, 175, 180, 110, 224, 91, 152, + 135, 51, 89, 119, 214, 226, 68, 94, 14, 70, 45, 176, 40, 10, + 209, 52, 80, 208, 227, 5, 97, 248, 166, 224, 72, 109, 245, 122, + 149, 240, 212, 177, 168, 232, 143, 105, 212, 51, 128, 155, 202, 114, + 22, 240, 106, 240, 252, 71, 60, 57, 234, 163, 23, 156, 194, 45, + 96, 151, 144, 76, 236, 251, 172, 42, 29, 166, 211, 207, 57, 151, + 80, 3, 48, 208, 176, 124, 230, 133, 25, 134, 27, 67, 144, 206, + 61, 85, 56, 32, 105, 202, 87, 45, 115, 148, 83, 226, 39, 55, + 27, 197, 206, 148, 41, 30, 77, 172, 31, 89, 138, 57, 189, 109, + 118, 163, 40, 191, 190, 218, 196, 55, 38, 149, 244, 56, 113, 52, + 99, 148, 168, 179, 61, 205, 212, 232, 192, 64, 45, 60, 231, 96, + 237, 104, 255, 139, 175, 171, 55, 57, 228, 162, 184, 230, 39, 155, + 134, 194, 171, 37, 107, 186, 12, 179, 126, 175, 233, 140, 229, 80, + 94, 189, 124, 10, 110, 198, 202, 34, 44, 133, 174, 239, 11, 232, + 136, 126, 213, 100, 193, 203, 227, 37, 44, 149, 170, 120, 25, 216, + 0, 225, 155, 179, 15, 78, 55, 134, 178, 146, 233, 206, 115, 128, + 46, 119, 65, 105, 94, 160, 191, 10, 243, 227, 181, 29, 42, 141, + 35, 236, 100, 20, 152, 96, 33, 182, 140, 60, 24, 13, 233, 120, + 207, 87, 4, 156, 146, 227, 126, 62, 149, 85, 155, 114, 246, 229, + 9, 208, 57, 77, 218, 154, 48, 62, 191, 103, 132, 86, 163, 152, + 71, 84, 88, 203, 133, 252, 8, 236, 182, 142, 60, 12, 198, 178, + 73, 185, 201, 235, 48, 214, 209, 138, 136, 199, 219, 57, 210, 199, + 174, 238, 130, 29, 131, 176, 60, 149, 184, 239, 122, 218, 185, 129, + 159, 50, 132, 24, 120, 215, 80, 205, 251, 184, 124, 168, 166, 204, + 78, 61, 7, 120, 57, 95, 62, 57, 73, 181, 223, 240, 0, 131, + 87, 175, 8, 90, 48, 43, 86, 145, 159, 218, 82, 5, 39, 205, + 75, 121, 243, 93, 8, 189, 200, 32, 39, 73, 132, 71, 88, 135, + 207, 225, 1, 248, 215, 179, 50, 143, 230, 31, 159, 136, 2, 82, + 193, 9, 108, 24, 161, 47, 255, 41, 121, 142, 243, 141, 229, 204, + 197, 44, 223, 124, 152, 251, 61, 80, 41, 52, 50, 37, 93, 234, + 216, 230, 203, 24, 151, 171, 112, 93, 224, 255, 86, 186, 93, 4, + 186, 242, 170, 99, 116, 36, 29, 246, 78, 122, 41, 161, 242, 104, + 179, 99, 4, 185, 8, 74, 129, 156, 218, 150, 130, 10, 93, 31, + 155, 235, 194, 152, 55, 3, 227, 116, 173, 222, 224, 41, 48, 51, + 91, 114, 122, 184, 5, 185, 56, 121, 155, 3, 94, 115, 72, 200, + 37, 77, 160, 73, 113, 69, 46, 24, 152, 94, 248, 153, 49, 243, + 27, 229, 155, 114, 185, 168, 192, 44, 234, 250, 66, 91, 164, 140, + 139, 171, 4, 128, 128, 173, 248, 5, 152, 35, 199, 219, 204, 116, + 182, 135, 252, 195, 249, 126, 9, 9, 114, 147, 127, 40, 13, 214, + 208, 196, 83, 86, 93, 167, 6, 199, 163, 99, 45, 56, 195, 163, + 154, 250, 167, 193, 127, 161, 81, 122, 211, 189, 218, 172, 9, 174, + 41, 129, 200, 78, 86, 88, 243, 42, 53, 51, 115, 189, 156, 48, + 149, 3, 3, 247, 81, 66, 115, 155, 158, 93, 134, 100, 240, 152, + 40, 227, 233, 191, 146, 62, 203, 91, 4, 120, 118, 153, 37, 11, + 194, 37, 187, 12, 78, 185, 107, 215, 208, 83, 7, 73, 99, 126, + 30, 146, 228, 233, 0, 56, 220, 73, 172, 180, 19, 36, 137, 207, + 106, 82, 131, 27, 76, 85, 251, 73, 223, 91, 151, 37, 213, 239, + 5, 172, 64, 192, 242, 212, 48, 19, 81, 121, 167, 143, 228, 90, + 199, 122, 195, 156, 52, 159, 180, 87, 89, 155, 151, 239, 102, 164, + 95, 161, 171, 191, 159, 226, 13, 214, 157, 184, 135, 117, 243, 100, + 51, 127, 207, 117, 167, 49, 85, 191, 6, 37, 253, 23, 135, 205, + 102, 176, 81, 143, 71, 79, 70, 183, 28, 19, 219, 75, 99, 37, + 182, 130, 84, 215, 5, 210, 97, 6, 184, 186, 35, 156, 213, 244, + 66, 239, 51, 231, 57, 78, 30, 140, 182, 29, 179, 243, 204, 11, + 39, 89, 164, 73, 60, 239, 193, 27, 34, 122, 17, 203, 157, 56, + 76, 99, 119, 164, 5, 181, 0, 147, 174, 114, 200, 165, 43, 34, + 169, 88, 7, 151, 201, 192, 253, 217, 85, 145, 9, 128, 175, 247, + 243, 68, 194, 226, 166, 239, 137, 8, 163, 250, 213, 74, 227, 85, + 221, 30, 83, 211, 47, 145, 210, 22, 171, 114, 135, 167, 0, 48, + 130, 152, 119, 63, 237, 178, 246, 240, 151, 29, 23, 133, 196, 126, + 153, 82, 147, 36, 46, 227, 158, 167, 220, 248, 11, 172, 189, 233, + 170, 113, 115, 44, 85, 183, 209, 117, 177, 117, 68, 148, 148, 112, + 109, 84, 37, 21, 183, 158, 199, 104, 249, 12, 22, 186, 158, 55, + 226, 216, 185, 81, 206, 106, 121, 69, 158, 184, 6, 79, 26, 158, + 240, 43, 129, 5, 207, 54, 30, 226, 236, 234, 111, 246, 95, 63, + 27, 111, 158, 69, 152, 10, 76, 168, 156, 15, 55, 180, 89, 11, + 231, 1, 243, 178, 182, 227, 100, 38, 243, 159, 239, 82, 161, 18, + 150, 123, 181, 48, 153, 248, 132, 239, 127, 83, 35, 207, 156, 17, + 7, 245, 153, 243, 213, 165, 228, 220, 144, 99, 244, 197, 75, 115, + 124, 6, 58, 91, 98, 101, 207, 58, 68, 59, 177, 195, 125, 85, + 12, 249, 63, 214, 59, 118, 42, 30, 171, 50, 75, 61, 242, 13, + 12, 185, 204, 68, 63, 252, 142, 25, 50, 117, 21, 21, 128, 124, + 229, 11, 26, 210, 253, 135, 66, 60, 140, 43, 229, 147, 131, 234, + 156, 37, 220, 140, 166, 87, 145, 94, 234, 61, 69, 157, 43, 162, + 34, 113, 209, 213, 185, 133, 66, 140, 146, 81, 167, 236, 174, 152, + 93, 52, 169, 76, 225, 8, 165, 239, 36, 43, 142, 186, 135, 177, + 188, 142, 208, 75, 106, 79, 191, 209, 8, 193, 131, 201, 41, 232, + 1, 136, 199, 90, 140, 63, 79, 171, 157, 144, 168, 47, 11, 217, + 225, 3, 222, 106, 246, 127, 129, 149, 189, 151, 106, 213, 33, 232, + 58, 200, 166, 162, 196, 223, 148, 95, 182, 95, 238, 247, 213, 55, + 154, 178, 121, 229, 165, 219, 48, 210, 145, 174, 77, 27, 162, 177, + 51, 45, 50, 88, 207, 177, 213, 253, 186, 220, 75, 196, 146, 229, + 51, 170, 202, 245, 21, 172, 75, 133, 163, 158, 48, 190, 248, 240, + 30, 36, 61, 90, 212, 213, 248, 149, 247, 71, 161, 85, 22, 47, + 91, 61, 217, 195, 224, 179, 140, 30, 139, 189, 41, 200, 253, 196, + 70, 92, 135, 63, 129, 233, 150, 183, 130, 84, 183, 54, 100, 180, + 147, 47, 49, 116, 75, 245, 45, 109, 131, 75, 181, 135, 73, 183, + 128, 229, 192, 51, 107, 7, 128, 0, 249, 126, 57, 157, 149, 60, + 110, 136, 136, 198, 109, 176, 201, 186, 165, 187, 102, 123, 241, 198, + 90, 88, 11, 109, 41, 64, 68, 91, 208, 43, 216, 78, 67, 253, + 43, 141, 91, 152, 181, 220, 170, 93, 176, 125, 220, 29, 213, 100, + 149, 150, 123, 184, 240, 54, 255, 98, 238, 224, 52, 58, 17, 154, + 82, 51, 237, 43, 127, 117, 233, 232, 225, 210, 64, 85, 200, 20, + 122, 209, 132, 62, 181, 64, 97, 244, 170, 137, 103, 132, 92, 33, + 70, 176, 138, 126, 72, 183, 96, 255, 253, 184, 163, 38, 189, 49, + 229, 18, 70, 163, 252, 115, 224, 6, 250, 12, 84, 205, 58, 13, + 101, 91, 151, 157, 26, 248, 243, 121, 197, 167, 36, 148, 90, 169, + 135, 226, 11, 130, 106, 246, 38, 154, 149, 211, 201, 161, 65, 129, + 155, 0, 103, 110, 213, 245, 202, 196, 212, 128, 42, 80, 33, 217, + 99, 106, 47, 169, 66, 100, 163, 22, 155, 248, 193, 106, 243, 20, + 135, 155, 25, 126, 8, 33, 162, 81, 6, 213, 173, 202, 57, 172, + 25, 44, 155, 213, 89, 189, 135, 104, 112, 16, 25, 22, 42, 124, + 243, 194, 52, 243, 6, 132, 119, 100, 91, 245, 0, 82, 231, 161, + 105, 17, 127, 50, 26, 98, 113, 249, 126, 231, 73, 122, 204, 165, + 169, 68, 96, 57, 73, 40, 141, 220, 195, 148, 20, 1, 82, 29, + 106, 169, 171, 252, 7, 204, 149, 167, 68, 116, 28, 216, 227, 26, + 208, 123, 188, 26, 45, 221, 249, 175, 146, 126, 76, 71, 131, 46, + 31, 182, 176, 121, 43, 195, 152, 234, 174, 53, 116, 70, 195, 120, + 29, 50, 4, 90, 124, 125, 99, 66, 137, 100, 205, 8, 18, 138, + 22, 223, 239, 17, 210, 249, 84, 93, 91, 91, 45, 45, 67, 225, + 122, 207, 72, 159, 215, 92, 162, 223, 136, 34, 138, 120, 254, 216, + 218, 29, 97, 40, 82, 247, 179, 226, 110, 239, 96, 180, 64, 111, + 75, 74, 95, 240, 54, 46, 2, 159, 218, 184, 112, 227, 246, 5, + 78, 55, 132, 193, 67, 219, 9, 200, 191, 194, 61, 205, 176, 47, + 131, 177, 195, 36, 50, 13, 34, 112, 50, 31, 236, 24, 115, 239, + 130, 182, 15, 5, 129, 88, 1, 206, 38, 26, 70, 241, 243, 136, + 47, 72, 12, 233, 132, 27, 149, 53, 254, 251, 204, 144, 246, 8, + 238, 74, 73, 10, 57, 138, 83, 179, 133, 210, 137, 112, 113, 228, + 225, 116, 201, 88, 123, 119, 112, 188, 211, 77, 68, 242, 93, 159, + 117, 251, 8, 125, 103, 3, 74, 214, 206, 122, 0, 35, 73, 208, + 150, 91, 120, 229, 125, 225, 154, 171, 26, 133, 160, 81, 208, 94, + 63, 9, 221, 153, 61, 102, 144, 193, 21, 186, 144, 22, 245, 215, + 34, 152, 19, 185, 99, 74, 174, 125, 236, 26, 157, 186, 210, 161, + 11, 1, 228, 64, 77, 144, 135, 67, 12, 74, 185, 99, 6, 46, + 190, 81, 109, 162, 172, 166, 58, 213, 149, 213, 161, 213, 53, 111, + 61, 168, 180, 209, 138, 159, 179, 52, 122, 180, 30, 40, 135, 101, + 34, 74, 22, 76, 97, 112, 210, 172, 0, 195, 253, 186, 116, 30, + 97, 141, 32, 197, 58, 156, 116, 179, 158, 119, 218, 200, 28, 83, + 48, 153, 230, 249, 64, 116, 30, 87, 187, 190, 44, 155, 92, 79, + 17, 194, 123, 110, 188, 161, 40, 187, 104, 232, 67, 244, 211, 221, + 61, 82, 225, 1, 13, 58, 56, 5, 208, 103, 168, 252, 147, 155, + 125, 34, 231, 160, 246, 219, 62, 190, 196, 94, 59, 154, 28, 6, + 54, 13, 174, 143, 94, 254, 80, 253, 253, 90, 175, 162, 213, 125, + 241, 79, 101, 255, 182, 28, 7, 66, 244, 153, 207, 151, 123, 247, + 169, 55, 99, 33, 89, 194, 25, 61, 105, 117, 151, 152, 175, 69, + 73, 252, 124, 229, 101, 127, 224, 177, 2, 226, 185, 86, 227, 85, + 91, 89, 36, 168, 100, 230, 52, 173, 248, 197, 41, 23, 202, 240, + 43, 254, 218, 29, 17, 155, 227, 203, 191, 185, 216, 38, 220, 58, + 155, 115, 45, 89, 21, 145, 93, 13, 224, 207, 21, 208, 47, 246, + 101, 100, 177, 232, 93, 210, 23, 241, 99, 50, 202, 128, 177, 234, + 85, 117, 51, 165, 236, 105, 148, 224, 45, 158, 160, 147, 127, 220, + 200, 184, 202, 23, 94, 83, 122, 237, 246, 84, 237, 100, 16, 57, + 160, 179, 99, 142, 154, 100, 233, 83, 12, 125, 85, 202, 61, 224, + 181, 173, 61, 163, 57, 13, 21, 158, 92, 209, 191, 154, 102, 245, + 218, 195, 116, 233, 225, 191, 89, 246, 100, 90, 135, 48, 151, 153, + 251, 176, 143, 211, 108, 40, 109, 216, 109, 245, 212, 133, 190, 55, + 145, 127, 115, 102, 195, 138, 79, 151, 99, 0, 236, 55, 36, 71, + 204, 148, 153, 80, 62, 112, 1, 7, 110, 177, 32, 18, 41, 208, + 10, 110, 186, 164, 139, 44, 5, 215, 127, 216, 164, 213, 113, 83, + 85, 101, 75, 76, 126, 84, 11, 87, 150, 145, 26, 121, 217, 238, + 115, 111, 101, 158, 250, 154, 95, 182, 98, 93, 18, 109, 230, 22, + 142, 192, 6, 0, 143, 119, 16, 92, 216, 181, 129, 239, 58, 93, + 235, 183, 149, 6, 199, 9, 82, 144, 63, 68, 35, 110, 183, 123, + 157, 248, 66, 218, 145, 75, 157, 244, 179, 68, 29, 58, 251, 22, + 198, 126, 221, 131, 9, 217, 26, 87, 214, 156, 238, 194, 46, 132, + 254, 49, 162, 73, 201, 253, 246, 211, 53, 83, 218, 61, 12, 187, + 10, 139, 19, 31, 230, 56, 19, 59, 192, 228, 12, 202, 114, 13, + 45, 135, 85, 196, 24, 227, 250, 144, 68, 106, 127, 43, 151, 109, + 207, 95, 168, 254, 71, 31, 149, 185, 129, 241, 182, 214, 230, 11, + 217, 160, 109, 176, 192, 179, 5, 118, 66, 224, 29, 19, 88, 134, + 168, 87, 58, 112, 93, 221, 193, 246, 188, 200, 81, 132, 249, 192, + 121, 157, 195, 243, 254, 14, 144, 119, 213, 60, 98, 5, 28, 236, + 249, 7, 208, 125, 185, 244, 26, 247, 43, 225, 49, 94, 107, 237, + 18, 51, 132, 58, 42, 248, 37, 253, 35, 156, 14, 93, 49, 220, + 185, 238, 229, 253, 253, 161, 226, 61, 64, 170, 174, 110, 155, 117, + 192, 107, 208, 240, 224, 142, 97, 144, 251, 58, 216, 94, 80, 178, + 165, 2, 60, 75, 136, 86, 7, 197, 6, 216, 112, 106, 183, 226, + 252, 87, 140, 246, 32, 225, 63, 23, 203, 243, 155, 39, 131, 219, + 3, 159, 52, 63, 68, 98, 37, 63, 246, 97, 224, 40, 24, 201, + 172, 251, 135, 28, 245, 212, 107, 229, 153, 119, 25, 154, 47, 3, + 157, 9, 62, 171, 171, 41, 190, 13, 232, 41, 137, 151, 36, 98, + 41, 245, 213, 120, 251, 140, 239, 223, 23, 100, 127, 240, 248, 60, + 148, 195, 235, 139, 45, 88, 45, 217, 212, 86, 255, 113, 126, 187, + 234, 119, 152, 195, 230, 137, 85, 59, 53, 255, 11, 227, 251, 153, + 105, 144, 0, 126, 202, 42, 34, 134, 20, 227, 155, 55, 46, 199, + 180, 59, 88, 148, 205, 216, 150, 33, 27, 240, 88, 67, 204, 214, + 27, 215, 208, 188, 75, 198, 133, 8, 231, 149, 91, 70, 217, 248, + 188, 211, 212, 221, 165, 144, 224, 54, 72, 176, 147, 251, 13, 61, + 15, 167, 11, 144, 254, 92, 231, 24, 254, 22, 43, 168, 73, 81, + 208, 22, 93, 102, 79, 48, 208, 176, 209, 83, 143, 110, 226, 74, + 215, 239, 121, 150, 100, 242, 86, 141, 230, 221, 66, 69, 23, 17, + 123, 31, 66, 3, 133, 122, 68, 61, 142, 92, 186, 216, 41, 206, + 171, 94, 39, 209, 41, 13, 154, 155, 152, 40, 246, 127, 72, 199, + 85, 32, 122, 92, 66, 74, 200, 102, 51, 248, 252, 255, 182, 70, + 215, 85, 192, 75, 164, 23, 203, 205, 97, 131, 97, 187, 69, 111, + 170, 164, 129, 60, 118, 82, 1, 143, 21, 221, 49, 238, 216, 255, + 66, 178, 145, 184, 167, 175, 100, 188, 120, 252, 54, 179, 18, 188, + 38, 37, 20, 143, 217, 26, 160, 5, 48, 117, 107, 68, 143, 169, + 93, 72, 234, 48, 8, 38, 110, 59, 174, 112, 49, 94, 146, 36, + 140, 127, 183, 206, 207, 220, 218, 212, 4, 131, 29, 72, 142, 29, + 255, 220, 124, 249, 54, 146, 94, 28, 207, 53, 129, 74, 80, 127, + 205, 29, 178, 240, 110, 33, 39, 41, 237, 193, 218, 203, 92, 84, + 103, 167, 76, 91, 46, 165, 114, 85, 154, 59, 108, 164, 66, 98, + 222, 191, 136, 65, 67, 150, 43, 248, 212, 132, 46, 167, 203, 47, + 164, 70, 241, 159, 127, 139, 207, 160, 155, 181, 43, 38, 72, 37, + 196, 107, 250, 23, 217, 134, 95, 169, 128, 72, 59, 222, 175, 0, + 122, 51, 242, 240, 191, 118, 72, 117, 218, 220, 126, 212, 180, 221, + 210, 125, 53, 133, 200, 83, 58, 250, 193, 185, 191, 86, 162, 114, + 196, 87, 41, 159, 240, 211, 237, 76, 28, 131, 155, 11, 173, 59, + 232, 203, 41, 181, 228, 43, 48, 27, 214, 243, 105, 201, 195, 92, + 21, 41, 149, 54, 117, 14, 192, 103, 228, 242, 114, 149, 82, 188, + 253, 226, 181, 153, 150, 149, 2, 43, 110, 101, 239, 249, 223, 158, + 145, 69, 181, 15, 108, 56, 104, 132, 252, 152, 17, 164, 12, 34, + 33, 16, 118, 163, 228, 163, 252, 131, 243, 76, 37, 236, 145, 132, + 166, 241, 20, 61, 245, 30, 204, 54, 42, 73, 253, 22, 198, 177, + 80, 139, 111, 172, 93, 85, 154, 27, 184, 183, 76, 15, 180, 180, + 31, 88, 93, 39, 143, 227, 154, 87, 232, 68, 144, 103, 100, 177, + 182, 72, 136, 141, 150, 196, 208, 195, 109, 231, 69, 151, 130, 192, + 80, 141, 151, 105, 121, 238, 70, 73, 253, 194, 82, 79, 190, 135, + 8, 59, 207, 203, 237, 123, 218, 58, 224, 111, 186, 195, 6, 32, + 119, 137, 148, 61, 252, 9, 124, 231, 220, 151, 235, 52, 177, 168, + 217, 54, 228, 23, 216, 187, 76, 55, 27, 232, 218, 161, 180, 102, + 132, 63, 21, 109, 70, 141, 158, 113, 240, 179, 238, 15, 31, 87, + 0, 248, 52, 143, 41, 36, 163, 31, 76, 57, 250, 71, 12, 244, + 193, 212, 67, 194, 141, 1, 183, 60, 13, 113, 254, 57, 250, 133, + 124, 220, 51, 122, 76, 212, 107, 190, 67, 87, 108, 86, 131, 231, + 115, 30, 190, 52, 98, 14, 144, 37, 108, 232, 97, 153, 226, 3, + 142, 155, 243, 201, 48, 167, 63, 83, 108, 110, 194, 134, 243, 211, + 202, 164, 207, 25, 169, 165, 134, 106, 33, 4, 196, 30, 221, 195, + 166, 255, 150, 175, 27, 114, 13, 32, 56, 109, 178, 133, 76, 42, + 195, 87, 181, 249, 186, 139, 172, 189, 228, 156, 81, 45, 195, 212, + 214, 119, 203, 87, 135, 213, 163, 246, 170, 11, 78, 161, 150, 142, + 25, 43, 75, 152, 138, 184, 67, 240, 161, 243, 132, 194, 216, 144, + 245, 18, 97, 127, 66, 156, 221, 15, 60, 121, 163, 139, 245, 156, + 96, 108, 130, 197, 12, 238, 8, 107, 9, 239, 212, 209, 4, 30, + 73, 138, 44, 181, 88, 121, 195, 17, 185, 147, 88, 194, 255, 126, + 107, 125, 218, 90, 132, 185, 169, 204, 202, 42, 240, 219, 57, 150, + 8, 89, 192, 254, 57, 64, 192, 253, 143, 124, 24, 116, 57, 40, + 199, 144, 66, 175, 62, 162, 188, 93, 171, 150, 31, 251, 145, 70, + 248, 159, 246, 166, 73, 76, 20, 54, 117, 131, 176, 190, 173, 179, + 230, 49, 139, 140, 20, 198, 161, 100, 103, 194, 92, 163, 97, 235, + 80, 134, 91, 193, 26, 195, 102, 173, 192, 195, 243, 132, 57, 6, + 146, 133, 102, 167, 15, 21, 75, 171, 227, 19, 178, 247, 61, 219, + 44, 57, 136, 137, 30, 251, 227, 255, 75, 186, 48, 164, 131, 54, + 211, 251, 229, 136, 102, 156, 114, 34, 123, 138, 0, 22, 241, 149, + 60, 65, 197, 248, 251, 47, 96, 70, 137, 49, 148, 180, 119, 135, + 10, 176, 72, 55, 137, 49, 204, 96, 73, 187, 76, 78, 179, 113, + 31, 161, 242, 50, 127, 71, 198, 92, 188, 12, 24, 46, 38, 62, + 128, 113, 1, 238, 171, 87, 248, 180, 239, 164, 101, 32, 104, 103, + 207, 149, 246, 105, 123, 150, 17, 164, 80, 237, 250, 39, 171, 79, + 146, 188, 21, 60, 86, 210, 179, 246, 92, 21, 199, 130, 216, 239, + 54, 80, 78, 51, 189, 158, 86, 227, 172, 28, 140, 108, 77, 173, + 240, 153, 113, 132, 202, 104, 26, 52, 50, 153, 96, 237, 94, 254, + 106, 208, 183, 4, 112, 245, 192, 177, 233, 91, 158, 124, 145, 104, + 147, 251, 87, 82, 36, 127, 52, 237, 163, 215, 93, 96, 142, 57, + 113, 144, 230, 169, 228, 232, 234, 118, 84, 211, 111, 90, 125, 142, + 218, 253, 249, 30, 94, 114, 114, 224, 230, 100, 165, 211, 127, 6, + 158, 157, 104, 200, 226, 68, 38, 54, 69, 222, 141, 101, 180, 174, + 245, 169, 175, 100, 229, 102, 159, 103, 3, 151, 142, 151, 251, 178, + 153, 16, 228, 161, 56, 187, 86, 191, 5, 198, 49, 127, 250, 231, + 235, 155, 8, 98, 80, 161, 21, 165, 167, 228, 127, 148, 182, 67, + 135, 137, 167, 5, 91, 6, 129, 3, 119, 156, 55, 170, 202, 62, + 157, 180, 17, 91, 27, 103, 181, 170, 58, 102, 223, 136, 117, 7, + 22, 206, 156, 55, 226, 110, 49, 174, 39, 69, 145, 62, 18, 136, + 94, 235, 72, 15, 24, 1, 177, 216, 10, 124, 183, 189, 254, 222, + 123, 114, 167, 8, 154, 73, 144, 36, 241, 82, 246, 237, 53, 159, + 173, 241, 76, 178, 186, 169, 53, 192, 224, 214, 147, 34, 60, 114, + 218, 153, 181, 87, 94, 197, 52, 119, 141, 152, 152, 122, 210, 108, + 65, 118, 243, 89, 135, 18, 39, 111, 239, 37, 88, 25, 92, 229, + 232, 185, 150, 210, 22, 10, 125, 156, 215, 152, 128, 9, 130, 248, + 237, 107, 139, 165, 220, 233, 171, 60, 248, 40, 146, 14, 91, 29, + 131, 5, 126, 135, 11, 207, 216, 234, 174, 19, 28, 21, 214, 72, + 50, 150, 5, 199, 6, 242, 28, 153, 213, 175, 213, 222, 189, 46, + 192, 78, 162, 201, 210, 84, 254, 194, 141, 114, 163, 91, 142, 25, + 56, 66, 174, 127, 255, 242, 99, 147, 159, 253, 146, 6, 94, 10, + 111, 20, 49, 154, 170, 209, 11, 129, 153, 250, 152, 31, 66, 155, + 238, 41, 247, 63, 66, 150, 117, 158, 13, 9, 63, 173, 106, 16, + 112, 197, 248, 119, 113, 194, 234, 208, 240, 188, 2, 75, 23, 111, + 202, 171, 226, 146, 97, 0, 186, 55, 233, 153, 72, 128, 223, 205, + 92, 253, 24, 250, 138, 107, 233, 202, 55, 120, 107, 103, 157, 167, + 2, 1, 194, 180, 145, 193, 103, 146, 194, 200, 102, 174, 145, 192, + 122, 217, 58, 62, 25, 81, 13, 251, 90, 127, 206, 177, 45, 200, + 5, 49, 192, 96, 86, 135, 143, 183, 213, 106, 57, 92, 132, 220, + 21, 154, 49, 246, 127, 47, 112, 223, 146, 46, 48, 243, 125, 196, + 221, 20, 80, 109, 190, 82, 104, 250, 41, 158, 110, 198, 131, 145, + 30, 213, 249, 235, 190, 68, 98, 247, 54, 139, 163, 226, 189, 236, + 178, 149, 23, 238, 124, 84, 55, 31, 142, 104, 97, 146, 174, 152, + 163, 171, 184, 114, 184, 192, 251, 186, 224, 175, 240, 122, 210, 131, + 227, 136, 43, 65, 223, 144, 211, 159, 140, 121, 79, 8, 4, 147, + 17, 167, 99, 232, 179, 142, 223, 247, 51, 218, 47, 121, 75, 42, + 234, 225, 60, 183, 211, 75, 45, 89, 239, 2, 92, 18, 238, 38, + 89, 52, 15, 211, 65, 161, 89, 148, 187, 148, 95, 143, 72, 97, + 4, 208, 170, 158, 239, 189, 158, 253, 160, 75, 6, 154, 112, 68, + 204, 66, 193, 41, 16, 181, 146, 245, 32, 71, 44, 113, 169, 186, + 174, 189, 76, 143, 193, 114, 69, 26, 254, 200, 69, 21, 17, 204, + 211, 5, 241, 202, 64, 83, 198, 160, 69, 189, 61, 14, 75, 99, + 105, 88, 86, 212, 36, 239, 48, 107, 155, 205, 229, 118, 24, 248, + 192, 215, 40, 96, 28, 171, 139, 6, 239, 188, 55, 28, 143, 223, + 115, 88, 170, 53, 11, 145, 26, 151, 95, 185, 63, 111, 59, 167, + 212, 216, 125, 8, 79, 78, 155, 188, 166, 59, 103, 171, 1, 86, + 130, 6, 247, 126, 69, 73, 186, 34, 31, 130, 202, 213, 94, 207, + 153, 191, 105, 59, 144, 192, 159, 76, 193, 188, 39, 53, 201, 182, + 213, 218, 227, 133, 91, 37, 129, 231, 72, 127, 98, 117, 186, 244, + 160, 206, 19, 9, 203, 33, 93, 88, 97, 153, 115, 29, 249, 84, + 218, 175, 52, 150, 49, 232, 82, 213, 242, 76, 29, 43, 109, 98, + 4, 197, 78, 237, 98, 82, 67, 58, 209, 187, 101, 103, 50, 209, + 194, 140, 225, 6, 110, 238, 59, 192, 225, 77, 159, 225, 103, 159, + 234, 111, 128, 214, 174, 233, 155, 28, 212, 104, 37, 206, 93, 204, + 140, 177, 59, 120, 110, 85, 103, 95, 13, 164, 178, 1, 112, 224, + 42, 101, 41, 1, 74, 162, 132, 42, 219, 129, 213, 106, 48, 53, + 57, 11, 139, 67, 174, 107, 85, 31, 120, 113, 196, 60, 81, 13, + 64, 11, 93, 156, 56, 100, 140, 12, 236, 235, 66, 127, 129, 194, + 114, 106, 240, 37, 50, 243, 204, 199, 212, 105, 8, 153, 117, 158, + 248, 33, 133, 50, 201, 89, 108, 190, 202, 81, 210, 106, 249, 156, + 3, 47, 44, 196, 7, 86, 0, 80, 108, 107, 54, 123, 205, 28, + 40, 240, 13, 150, 11, 164, 151, 101, 86, 213, 213, 93, 107, 221, + 4, 145, 190, 87, 22, 37, 33, 127, 167, 29, 76, 1, 251, 251, + 205, 140, 154, 148, 60, 26, 234, 208, 115, 112, 44, 144, 58, 212, + 215, 242, 128, 236, 221, 10, 105, 9, 132, 1, 11, 21, 16, 237, + 0, 136, 16, 121, 34, 19, 254, 25, 196, 69, 236, 192, 184, 42, + 85, 244, 119, 249, 119, 158, 145, 24, 120, 163, 202, 120, 8, 92, + 0, 32, 54, 12, 207, 173, 181, 83, 150, 194, 173, 242, 149, 204, + 223, 61, 169, 223, 243, 177, 224, 133, 253, 203, 45, 1, 139, 1, + 32, 19, 31, 198, 115, 125, 232, 90, 58, 63, 159, 223, 89, 166, + 221, 11, 252, 211, 75, 31, 237, 250, 87, 159, 101, 139, 235, 194, + 168, 135, 189, 169, 187, 179, 67, 65, 146, 179, 114, 160, 138, 14, + 180, 159, 89, 189, 215, 119, 220, 89, 116, 88, 16, 236, 99, 212, + 106, 236, 242, 22, 132, 244, 6, 226, 194, 143, 11, 253, 238, 95, + 175, 121, 71, 1, 2, 146, 254, 233, 3, 119, 134, 0, 222, 11, + 135, 144, 141, 189, 76, 81, 128, 177, 98, 9, 117, 128, 80, 169, + 172, 22, 245, 197, 174, 1, 154, 8, 126, 167, 64, 86, 133, 106, + 233, 45, 20, 246, 227, 190, 115, 4, 232, 114, 130, 110, 227, 49, + 106, 84, 159, 248, 190, 29, 254, 64, 22, 108, 44, 38, 34, 216, + 238, 75, 65, 66, 238, 50, 112, 139, 183, 107, 164, 19, 255, 164, + 181, 249, 153, 134, 83, 117, 230, 239, 23, 85, 68, 149, 176, 194, + 176, 200, 108, 162, 108, 53, 143, 215, 164, 205, 166, 183, 33, 27, + 159, 211, 143, 186, 140, 115, 34, 231, 151, 90, 142, 204, 229, 99, + 210, 19, 250, 93, 3, 5, 194, 149, 7, 199, 54, 230, 101, 155, + 165, 108, 155, 144, 129, 163, 91, 186, 184, 148, 99, 56, 117, 63, + 189, 12, 160, 211, 23, 233, 123, 105, 10, 97, 255, 180, 0, 248, + 233, 62, 170, 76, 238, 158, 230, 115, 117, 132, 202, 135, 74, 61, + 58, 107, 29, 215, 70, 62, 102, 169, 220, 33, 7, 200, 190, 28, + 66, 179, 109, 89, 91, 44, 79, 213, 158, 253, 236, 248, 99, 138, + 22, 158, 45, 187, 225, 31, 134, 250, 102, 54, 242, 208, 34, 213, + 175, 195, 19, 53, 60, 181, 35, 185, 182, 174, 66, 128, 37, 208, + 188, 99, 214, 252, 59, 109, 18, 38, 209, 220, 32, 50, 217, 171, + 223, 120, 44, 142, 135, 221, 26, 11, 80, 52, 227, 242, 67, 133, + 71, 173, 108, 155, 77, 6, 77, 252, 77, 112, 55, 15, 221, 93, + 94, 145, 167, 66, 216, 90, 125, 136, 242, 99, 84, 128, 240, 212, + 157, 176, 102, 2, 251, 87, 74, 112, 16, 107, 183, 56, 4, 213, + 211, 252, 5, 161, 162, 205, 80, 137, 245, 75, 190, 14, 54, 188, + 128, 76, 55, 221, 70, 1, 105, 221, 82, 52, 138, 15, 135, 28, + 35, 16, 51, 46, 91, 215, 63, 115, 231, 142, 77, 232, 199, 192, + 183, 89, 115, 242, 217, 204, 52, 153, 46, 223, 87, 71, 193, 52, + 117, 50, 138, 52, 103, 73, 87, 87, 180, 3, 174, 36, 92, 157, + 186, 197, 156, 108, 227, 155, 10, 19, 103, 103, 230, 168, 252, 140, + 5, 176, 144, 249, 163, 206, 226, 53, 58, 90, 142, 200, 10, 200, + 47, 39, 114, 189, 42, 7, 231, 155, 19, 190, 164, 249, 240, 57, + 252, 185, 171, 148, 172, 255, 161, 0, 163, 91, 175, 48, 68, 197, + 42, 51, 208, 120, 209, 121, 205, 150, 170, 174, 179, 202, 141, 91, + 4, 116, 100, 164, 22, 34, 82, 100, 16, 186, 97, 126, 223, 18, + 53, 228, 34, 1, 219, 133, 217, 55, 183, 38, 127, 215, 105, 20, + 87, 101, 179, 113, 207, 78, 5, 57, 61, 213, 222, 251, 146, 128, + 55, 233, 123, 111, 162, 89, 8, 27, 49, 87, 249, 61, 200, 120, + 251, 225, 39, 166, 104, 206, 15, 174, 181, 13, 175, 115, 22, 141, + 134, 228, 222, 182, 106, 22, 21, 251, 67, 134, 154, 212, 161, 215, + 7, 216, 48, 38, 159, 109, 144, 67, 136, 20, 216, 47, 186, 94, + 90, 75, 158, 46, 55, 25, 190, 67, 135, 221, 220, 178, 117, 23, + 34, 212, 142, 244, 173, 0, 232, 17, 133, 45, 39, 137, 48, 14, + 59, 66, 207, 153, 154, 171, 245, 235, 202, 215, 102, 37, 142, 152, + 221, 204, 161, 28, 96, 131, 50, 216, 47, 183, 164, 56, 99, 90, + 138, 205, 31, 164, 50, 234, 180, 41, 159, 87, 34, 188, 120, 7, + 15, 190, 126, 193, 222, 134, 90, 160, 5, 39, 74, 213, 125, 161, + 126, 18, 16, 227, 100, 118, 27, 194, 45, 19, 16, 174, 194, 58, + 188, 50, 208, 247, 224, 160, 60, 211, 54, 56, 182, 218, 161, 143, + 60, 64, 135, 241, 121, 40, 28, 38, 231, 134, 34, 116, 80, 20, + 181, 46, 100, 84, 224, 205, 51, 219, 247, 249, 201, 98, 42, 65, + 11, 225, 69, 24, 210, 12, 28, 138, 175, 240, 17, 84, 250, 207, + 4, 115, 182, 239, 191, 217, 115, 72, 128, 222, 13, 237, 105, 67, + 47, 111, 234, 109, 192, 54, 207, 135, 197, 60, 186, 133, 48, 115, + 199, 43, 195, 153, 206, 229, 135, 221, 191, 39, 237, 28, 163, 244, + 106, 4, 24, 21, 54, 249, 252, 237, 110, 121, 85, 249, 151, 170, + 224, 26, 241, 120, 123, 243, 219, 98, 50, 233, 58, 104, 56, 32, + 8, 76, 191, 140, 117, 228, 68, 135, 127, 203, 94, 159, 224, 245, + 125, 62, 8, 117, 205, 187, 93, 120, 46, 149, 13, 119, 112, 100, + 187, 209, 128, 98, 111, 151, 233, 65, 2, 222, 52, 18, 205, 70, + 146, 82, 70, 169, 125, 107, 0, 240, 159, 108, 14, 103, 164, 228, + 17, 233, 54, 145, 59, 145, 12, 8, 10, 141, 95, 124, 108, 125, + 148, 119, 109, 19, 226, 106, 10, 56, 146, 93, 72, 239, 116, 42, + 79, 60, 109, 99, 141, 40, 249, 22, 114, 205, 75, 224, 166, 108, + 22, 29, 118, 108, 39, 42, 222, 130, 12, 10, 28, 100, 1, 161, + 62, 92, 208, 102, 232, 237, 239, 239, 139, 79, 238, 233, 202, 60, + 96, 0, 244, 84, 222, 60, 212, 233, 76, 181, 114, 25, 49, 173, + 32, 245, 171, 56, 255, 217, 43, 45, 149, 227, 64, 204, 255, 236, + 186, 91, 106, 124, 206, 14, 135, 145, 44, 7, 111, 202, 141, 248, + 129, 29, 160, 91, 191, 100, 137, 9, 136, 236, 24, 253, 229, 164, + 210, 4, 225, 125, 38, 253, 66, 156, 225, 48, 246, 160, 88, 0, + 139, 245, 193, 102, 253, 118, 153, 143, 26, 126, 117, 247, 4, 12, + 108, 128, 4, 104, 51, 152, 24, 53, 74, 164, 182, 144, 241, 9, + 169, 49, 146, 71, 184, 132, 32, 251, 167, 80, 101, 131, 194, 106, + 162, 168, 114, 55, 90, 212, 159, 60, 41, 101, 14, 80, 219, 128, + 212, 199, 106, 71, 194, 173, 141, 116, 56, 68, 250, 45, 205, 104, + 245, 137, 3, 99, 221, 220, 105, 243, 165, 15, 88, 59, 61, 201, + 81, 77, 50, 202, 22, 249, 139, 169, 179, 121, 251, 113, 216, 25, + 186, 95, 8, 2, 53, 114, 109, 110, 153, 223, 75, 91, 103, 13, + 19, 189, 199, 226, 110, 249, 129, 115, 48, 117, 225, 71, 202, 120, + 150, 242, 110, 193, 146, 129, 101, 11, 78, 167, 125, 51, 6, 193, + 87, 235, 72, 53, 95, 248, 183, 17, 40, 125, 50, 241, 150, 125, + 144, 106, 236, 144, 89, 226, 119, 187, 107, 68, 174, 230, 144, 171, + 155, 230, 49, 129, 22, 173, 213, 152, 146, 104, 33, 97, 235, 92, + 103, 247, 34, 240, 47, 243, 189, 193, 163, 180, 34, 182, 135, 6, + 129, 118, 33, 201, 250, 174, 147, 95, 148, 150, 204, 29, 80, 63, + 135, 230, 24, 171, 107, 232, 32, 43, 236, 187, 9, 121, 64, 140, + 204, 45, 195, 246, 158, 189, 76, 72, 62, 164, 60, 84, 133, 60, + 139, 97, 209, 81, 46, 91, 249, 227, 199, 149, 210, 108, 69, 29, + 254, 165, 100, 98, 190, 44, 151, 83, 252, 9, 72, 169, 172, 111, + 9, 220, 151, 12, 82, 160, 236, 239, 194, 231, 92, 107, 102, 166, + 205, 127, 186, 100, 174, 142, 46, 42, 113, 207, 35, 47, 116, 134, + 52, 111, 148, 106, 145, 197, 88, 14, 200, 102, 104, 242, 207, 186, + 200, 71, 130, 149, 185, 86, 10, 225, 149, 146, 138, 70, 12, 103, + 224, 122, 11, 110, 10, 214, 131, 35, 66, 89, 50, 158, 155, 39, + 140, 245, 150, 102, 177, 72, 174, 180, 32, 168, 200, 169, 248, 77, + 56, 228, 91, 20, 207, 32, 46, 79, 100, 173, 181, 69, 197, 205, + 249, 123, 203, 109, 90, 104, 200, 236, 129, 8, 16, 168, 152, 55, + 183, 54, 139, 183, 98, 121, 162, 143, 155, 140, 33, 237, 186, 81, + 62, 124, 179, 238, 104, 67, 181, 172, 136, 140, 2, 180, 159, 41, + 109, 173, 63, 117, 184, 13, 78, 228, 221, 219, 228, 33, 69, 133, + 103, 231, 113, 242, 233, 216, 249, 235, 247, 174, 3, 66, 113, 90, + 54, 139, 31, 61, 156, 99, 254, 156, 200, 194, 137, 61, 33, 17, + 41, 144, 178, 129, 57, 138, 46, 84, 60, 25, 65, 111, 203, 0, + 249, 38, 77, 145, 187, 85, 225, 218, 52, 197, 78, 37, 21, 208, + 157, 227, 207, 109, 219, 122, 234, 1, 104, 194, 15, 101, 206, 205, + 121, 69, 221, 238, 184, 249, 23, 106, 221, 162, 67, 182, 53, 163, + 153, 128, 87, 105, 71, 253, 1, 20, 112, 127, 157, 17, 26, 151, + 26, 124, 183, 192, 156, 170, 212, 82, 244, 232, 185, 78, 137, 243, + 155, 21, 110, 246, 100, 253, 25, 15, 172, 136, 109, 118, 114, 194, + 34, 24, 157, 75, 88, 239, 51, 223, 49, 96, 87, 219, 209, 243, + 144, 41, 20, 57, 220, 1, 154, 77, 116, 194, 3, 89, 199, 70, + 90, 60, 48, 64, 250, 228, 56, 236, 201, 28, 77, 201, 35, 77, + 162, 50, 200, 20, 253, 15, 161, 31, 150, 213, 28, 36, 136, 117, + 249, 214, 2, 149, 83, 62, 133, 223, 97, 0, 246, 157, 4, 169, + 90, 223, 67, 248, 74, 106, 159, 84, 53, 210, 83, 29, 118, 197, + 238, 39, 224, 206, 104, 191, 195, 51, 176, 170, 226, 23, 35, 115, + 19, 237, 44, 170, 190, 121, 102, 205, 225, 147, 105, 169, 86, 253, + 244, 237, 149, 242, 12, 73, 105, 132, 170, 200, 158, 78, 95, 153, + 40, 143, 216, 208, 103, 64, 61, 161, 68, 205, 85, 11, 95, 90, + 70, 212, 171, 243, 198, 254, 51, 135, 1, 176, 110, 150, 113, 79, + 85, 18, 210, 185, 64, 209, 218, 98, 131, 151, 143, 116, 246, 233, + 230, 150, 166, 139, 135, 4, 53, 90, 146, 98, 192, 115, 60, 23, + 209, 8, 196, 218, 61, 52, 58, 226, 70, 170, 254, 88, 251, 116, + 129, 248, 170, 54, 238, 199, 204, 185, 234, 38, 227, 147, 201, 231, + 227, 56, 112, 134, 92, 223, 168, 53, 34, 36, 60, 159, 143, 180, + 252, 52, 106, 80, 125, 231, 45, 29, 182, 155, 82, 71, 214, 9, + 117, 190, 219, 11, 162, 250, 158, 102, 252, 51, 124, 225, 13, 71, + 159, 221, 75, 117, 69, 134, 28, 121, 0, 56, 17, 170, 32, 175, + 190, 108, 249, 35, 113, 173, 232, 248, 72, 113, 247, 242, 107, 127, + 136, 70, 99, 215, 223, 53, 80, 93, 121, 133, 79, 10, 105, 129, + 252, 222, 188, 23, 247, 75, 79, 20, 195, 186, 86, 216, 84, 40, + 106, 144, 135, 110, 111, 76, 83, 145, 206, 146, 244, 213, 234, 209, + 138, 118, 171, 19, 197, 2, 119, 247, 124, 180, 221, 114, 176, 181, + 222, 3, 152, 79, 244, 72, 10, 161, 231, 253, 52, 184, 68, 78, + 85, 232, 200, 21, 47, 184, 32, 23, 66, 58, 247, 193, 54, 240, + 52, 194, 187, 177, 68, 127, 236, 103, 213, 58, 67, 156, 119, 75, + 142, 241, 111, 225, 212, 246, 28, 30, 210, 38, 145, 11, 37, 219, + 78, 156, 41, 146, 214, 39, 144, 151, 145, 187, 11, 88, 4, 215, + 94, 254, 230, 253, 33, 3, 94, 193, 193, 185, 201, 105, 109, 43, + 118, 0, 148, 201, 239, 44, 138, 209, 247, 150, 34, 255, 163, 76, + 125, 169, 169, 164, 214, 13, 74, 235, 107, 188, 0, 107, 155, 81, + 253, 238, 20, 99, 212, 173, 101, 65, 41, 67, 246, 72, 28, 35, + 42, 120, 14, 104, 147, 5, 84, 147, 224, 136, 134, 237, 146, 53, + 89, 17, 113, 172, 64, 15, 44, 221, 255, 98, 236, 104, 2, 21, + 241, 76, 203, 229, 100, 176, 74, 160, 231, 170, 172, 97, 154, 147, + 71, 52, 151, 57, 185, 14, 242, 103, 226, 61, 35, 44, 231, 86, + 149, 148, 35, 189, 134, 139, 112, 62, 239, 28, 97, 121, 168, 150, + 221, 37, 209, 81, 66, 175, 8, 219, 135, 185, 101, 50, 209, 124, + 200, 209, 157, 152, 235, 54, 199, 24, 242, 27, 2, 1, 75, 162, + 53, 102, 88, 114, 82, 108, 19, 82, 80, 18, 119, 230, 188, 218, + 57, 185, 183, 78, 13, 5, 80, 16, 230, 213, 29, 52, 208, 193, + 79, 91, 174, 29, 186, 204, 11, 36, 199, 255, 129, 138, 40, 191, + 114, 171, 196, 38, 233, 157, 86, 150, 35, 164, 70, 15, 13, 140, + 130, 222, 162, 112, 14, 121, 171, 91, 150, 98, 75, 165, 203, 191, + 92, 174, 192, 25, 177, 145, 248, 253, 63, 69, 71, 63, 238, 239, + 165, 128, 51, 0, 241, 199, 38, 161, 40, 129, 229, 18, 245, 217, + 3, 101, 232, 75, 165, 105, 40, 117, 119, 112, 135, 65, 225, 217, + 10, 136, 14, 58, 181, 62, 164, 221, 254, 118, 89, 124, 76, 72, + 88, 96, 45, 99, 239, 196, 141, 75, 103, 39, 3, 40, 48, 35, + 40, 17, 162, 1, 99, 143, 214, 210, 67, 5, 53, 196, 137, 51, + 188, 166, 82, 151, 112, 181, 100, 52, 216, 171, 199, 132, 186, 16, + 129, 208, 138, 183, 17, 51, 44, 205, 213, 165, 165, 17, 165, 31, + 255, 199, 20, 224, 125, 136, 214, 109, 189, 58, 252, 245, 130, 64, + 221, 189, 90, 156, 151, 60, 49, 234, 139, 187, 73, 242, 146, 4, + 4, 158, 51, 38, 19, 52, 215, 58, 197, 138, 40, 205, 95, 49, + 53, 215, 143, 198, 133, 70, 251, 66, 8, 107, 72, 20, 50, 40, + 7, 188, 19, 237, 32, 241, 92, 45, 218, 53, 225, 241, 201, 65, + 139, 23, 221, 1, 106, 16, 49, 177, 120, 79, 188, 173, 32, 216, + 162, 202, 2, 21, 1, 63, 137, 167, 17, 102, 67, 40, 2, 70, + 20, 236, 107, 49, 214, 7, 137, 74, 104, 53, 85, 243, 31, 233, + 188, 158, 139, 133, 140, 144, 65, 153, 159, 169, 100, 149, 241, 80, + 122, 221, 165, 54, 104, 160, 201, 224, 218, 207, 100, 68, 116, 176, + 7, 5, 32, 111, 52, 0, 108, 152, 234, 104, 38, 69, 79, 158, + 199, 41, 7, 181, 208, 143, 99, 50, 172, 59, 33, 115, 68, 100, + 134, 93, 75, 86, 33, 170, 198, 85, 191, 97, 82, 64, 61, 183, + 220, 41, 50, 128, 75, 35, 199, 248, 90, 118, 177, 148, 81, 126, + 234, 229, 101, 26, 124, 2, 134, 75, 21, 245, 77, 96, 46, 11, + 128, 198, 79, 166, 170, 226, 77, 171, 106, 169, 45, 212, 56, 45, + 24, 186, 72, 37, 185, 28, 176, 209, 197, 188, 44, 178, 225, 214, + 183, 204, 230, 48, 255, 173, 36, 159, 161, 108, 3, 143, 248, 58, + 251, 82, 99, 199, 245, 115, 169, 128, 212, 234, 132, 115, 73, 116, + 21, 95, 29, 81, 34, 85, 230, 179, 74, 170, 87, 111, 203, 107, + 37, 182, 129, 3, 3, 181, 238, 249, 107, 102, 250, 141, 15, 179, + 93, 139, 116, 54, 59, 222, 53, 28, 121, 4, 140, 238, 238, 211, + 66, 136, 48, 73, 87, 175, 187, 255, 23, 244, 21, 175, 166, 138, + 98, 160, 111, 212, 16, 54, 67, 146, 108, 10, 204, 42, 98, 220, + 67, 236, 35, 156, 140, 80, 15, 11, 32, 158, 24, 82, 92, 239, + 47, 234, 51, 182, 24, 97, 36, 232, 200, 28, 143, 107, 248, 134, + 136, 57, 14, 107, 149, 150, 225, 160, 74, 170, 225, 34, 91, 219, + 39, 138, 161, 31, 63, 97, 226, 216, 99, 8, 72, 70, 247, 237, + 39, 233, 106, 19, 157, 186, 12, 65, 133, 239, 170, 156, 121, 248, + 24, 21, 101, 167, 46, 141, 125, 31, 93, 204, 14, 252, 0, 88, + 168, 110, 10, 214, 50, 46, 85, 50, 230, 247, 193, 164, 255, 226, + 208, 17, 98, 49, 149, 126, 54, 27, 243, 33, 182, 109, 206, 79, + 84, 151, 31, 3, 15, 165, 252, 254, 163, 203, 199, 170, 240, 137, + 37, 188, 140, 188, 9, 152, 147, 8, 81, 159, 32, 24, 111, 78, + 249, 150, 247, 111, 126, 108, 37, 192, 201, 3, 248, 95, 126, 163, + 211, 46, 175, 88, 136, 162, 157, 21, 54, 217, 43, 66, 17, 164, + 72, 7, 167, 13, 182, 204, 55, 248, 102, 241, 100, 147, 141, 18, + 127, 82, 50, 162, 120, 140, 46, 83, 205, 246, 55, 255, 62, 167, + 116, 52, 3, 38, 160, 124, 110, 152, 110, 166, 23, 175, 211, 236, + 210, 157, 40, 67, 252, 129, 34, 14, 248, 88, 201, 254, 83, 11, + 176, 158, 3, 185, 141, 4, 246, 23, 242, 149, 161, 76, 184, 197, + 152, 217, 220, 145, 134, 153, 144, 235, 26, 28, 233, 84, 72, 23, + 239, 180, 28, 30, 205, 57, 178, 242, 90, 125, 211, 204, 236, 47, + 53, 46, 113, 65, 102, 200, 118, 164, 39, 188, 203, 5, 90, 182, + 161, 62, 132, 242, 60, 149, 5, 108, 180, 217, 108, 179, 145, 245, + 21, 219, 68, 116, 106, 77, 99, 89, 215, 82, 62, 123, 60, 199, + 180, 59, 98, 171, 111, 158, 208, 134, 147, 200, 81, 124, 159, 118, + 119, 234, 102, 146, 81, 76, 36, 149, 53, 89, 158, 181, 107, 11, + 220, 245, 104, 125, 152, 207, 6, 221, 95, 124, 246, 177, 199, 76, + 26, 49, 201, 162, 170, 65, 83, 120, 169, 53, 78, 78, 176, 82, + 158, 146, 216, 23, 24, 137, 165, 121, 152, 7, 14, 120, 224, 156, + 114, 61, 169, 96, 89, 14, 174, 133, 80, 233, 28, 218, 93, 127, + 217, 62, 49, 231, 160, 102, 159, 145, 177, 123, 228, 124, 195, 94, + 201, 255, 134, 115, 53, 172, 140, 163, 229, 131, 89, 186, 233, 65, + 222, 174, 115, 105, 193, 151, 137, 72, 237, 114, 35, 101, 127, 159, + 90, 106, 254, 155, 28, 59, 162, 134, 153, 217, 156, 240, 98, 182, + 56, 45, 198, 133, 179, 118, 147, 101, 155, 158, 35, 210, 102, 113, + 167, 8, 193, 72, 1, 118, 234, 255, 142, 23, 208, 223, 66, 112, + 191, 6, 158, 132, 238, 92, 134, 45, 113, 103, 0, 209, 237, 217, + 225, 185, 102, 228, 67, 197, 176, 109, 90, 109, 162, 40, 72, 162, + 79, 135, 19, 76, 232, 217, 170, 226, 232, 60, 3, 95, 7, 245, + 219, 210, 34, 219, 83, 2, 233, 255, 195, 98, 115, 13, 136, 205, + 145, 215, 115, 148, 214, 138, 130, 116, 52, 229, 218, 255, 230, 174, + 38, 57, 54, 6, 135, 1, 245, 222, 221, 38, 10, 70, 36, 112, + 133, 162, 171, 100, 81, 109, 225, 144, 60, 50, 137, 23, 162, 93, + 62, 202, 180, 119, 148, 109, 37, 84, 30, 187, 4, 95, 137, 248, + 51, 37, 178, 223, 123, 244, 94, 150, 171, 243, 42, 68, 166, 70, + 93, 110, 127, 12, 128, 216, 119, 248, 147, 15, 91, 244, 123, 61, + 178, 76, 134, 115, 75, 20, 149, 209, 62, 171, 45, 176, 96, 79, + 116, 193, 104, 189, 241, 129, 239, 187, 147, 57, 185, 130, 172, 79, + 89, 215, 26, 67, 93, 182, 116, 37, 251, 6, 76, 61, 39, 14, + 251, 248, 79, 178, 74, 157, 201, 219, 123, 193, 71, 14, 26, 51, + 70, 79, 131, 228, 87, 236, 143, 228, 237, 120, 226, 151, 242, 244, + 59, 37, 1, 253, 46, 7, 186, 157, 75, 150, 190, 147, 9, 76, + 38, 238, 149, 230, 97, 18, 226, 114, 189, 92, 244, 46, 194, 44, + 33, 27, 191, 93, 100, 138, 87, 1, 190, 84, 176, 151, 75, 87, + 201, 247, 143, 189, 251, 209, 1, 216, 207, 56, 12, 23, 189, 107, + 128, 94, 14, 101, 47, 124, 202, 57, 180, 62, 7, 240, 73, 16, + 88, 217, 115, 40, 226, 113, 135, 9, 194, 128, 228, 168, 157, 14, + 157, 98, 94, 242, 173, 157, 180, 183, 236, 140, 210, 24, 211, 6, + 118, 120, 135, 127, 226, 71, 156, 110, 101, 90, 215, 143, 142, 52, + 102, 181, 216, 129, 0, 218, 250, 158, 42, 224, 41, 224, 33, 236, + 84, 2, 33, 80, 32, 165, 198, 133, 220, 135, 147, 162, 24, 191, + 152, 211, 181, 113, 205, 159, 149, 61, 92, 98, 90, 168, 173, 6, + 238, 44, 31, 200, 2, 254, 250, 183, 213, 123, 26, 173, 41, 243, + 142, 226, 221, 80, 99, 234, 59, 88, 139, 60, 136, 153, 31, 58, + 174, 54, 23, 30, 8, 201, 30, 98, 10, 66, 22, 206, 14, 72, + 32, 241, 202, 238, 126, 191, 15, 147, 211, 118, 14, 158, 110, 220, + 142, 232, 8, 27, 237, 191, 115, 20, 83, 155, 168, 134, 244, 175, + 222, 158, 37, 230, 3, 148, 192, 224, 252, 236, 189, 173, 192, 20, + 75, 97, 81, 98, 215, 35, 159, 140, 138, 26, 70, 129, 231, 83, + 152, 47, 35, 133, 87, 232, 189, 21, 72, 101, 177, 45, 89, 183, + 68, 20, 180, 161, 46, 59, 62, 4, 174, 127, 239, 151, 164, 135, + 23, 166, 44, 38, 113, 15, 206, 191, 103, 236, 239, 106, 63, 127, + 98, 157, 155, 238, 233, 72, 214, 132, 130, 200, 27, 63, 142, 59, + 75, 181, 195, 218, 81, 219, 146, 238, 123, 200, 43, 204, 250, 177, + 27, 104, 33, 150, 116, 191, 109, 235, 244, 168, 49, 214, 195, 196, + 249, 66, 2, 210, 2, 254, 192, 158, 214, 234, 23, 172, 58, 116, + 65, 226, 151, 29, 45, 206, 32, 47, 124, 85, 84, 165, 167, 82, + 198, 120, 234, 69, 157, 48, 107, 68, 167, 163, 8, 156, 48, 201, + 48, 93, 57, 26, 170, 28, 144, 217, 195, 47, 35, 7, 161, 165, + 10, 231, 62, 90, 150, 10, 120, 155, 229, 212, 254, 150, 85, 43, + 79, 43, 221, 175, 29, 114, 140, 30, 174, 70, 125, 249, 102, 172, + 109, 57, 191, 71, 240, 138, 154, 207, 14, 82, 193, 4, 35, 163, + 117, 24, 43, 174, 69, 28, 123, 165, 104, 90, 0, 50, 49, 229, + 194, 96, 65, 156, 82, 235, 100, 112, 142, 23, 164, 142, 67, 178, + 57, 227, 14, 40, 143, 237, 12, 131, 1, 52, 31, 184, 182, 185, + 117, 164, 131, 252, 119, 145, 122, 153, 39, 6, 135, 65, 151, 140, + 205, 11, 28, 27, 112, 58, 66, 205, 223, 75, 178, 28, 242, 85, + 176, 158, 57, 166, 44, 6, 81, 32, 150, 5, 189, 197, 51, 81, + 238, 103, 217, 217, 93, 255, 106, 170, 24, 60, 3, 240, 0, 235, + 213, 29, 101, 97, 205, 198, 41, 135, 232, 30, 68, 232, 19, 149, + 169, 109, 32, 252, 153, 98, 131, 105, 57, 6, 162, 166, 112, 188, + 233, 192, 247, 28, 166, 192, 137, 217, 127, 227, 96, 209, 81, 108, + 195, 42, 230, 112, 252, 79, 141, 62, 119, 231, 176, 66, 36, 160, + 167, 240, 220, 146, 134, 233, 45, 137, 185, 181, 3, 34, 204, 196, + 83, 165, 49, 65, 165, 96, 19, 139, 201, 250, 135, 71, 19, 76, + 193, 109, 194, 128, 5, 70, 247, 177, 113, 143, 105, 116, 4, 32, + 152, 176, 89, 138, 129, 100, 232, 32, 253, 94, 190, 170, 179, 216, + 253, 87, 8, 11, 252, 85, 109, 55, 117, 216, 118, 234, 246, 187, + 178, 121, 118, 26, 172, 178, 95, 221, 19, 134, 59, 41, 0, 27, + 228, 194, 41, 59, 45, 20, 234, 189, 147, 39, 226, 3, 90, 120, + 203, 148, 27, 146, 63, 96, 67, 61, 242, 30, 66, 100, 15, 189, + 54, 163, 94, 133, 146, 201, 207, 33, 5, 213, 215, 95, 120, 119, + 125, 152, 226, 23, 144, 83, 22, 23, 150, 201, 212, 221, 242, 130, + 72, 176, 152, 181, 188, 216, 160, 3, 84, 74, 123, 90, 196, 241, + 195, 185, 144, 188, 26, 150, 212, 225, 192, 204, 122, 61, 219, 147, + 7, 162, 253, 255, 193, 2, 255, 100, 193, 215, 69, 253, 89, 240, + 112, 248, 217, 222, 237, 65, 137, 111, 136, 101, 186, 78, 17, 245, + 168, 201, 138, 23, 13, 156, 37, 240, 199, 12, 51, 172, 130, 34, + 68, 238, 245, 183, 200, 135, 240, 3, 44, 126, 135, 54, 190, 213, + 2, 122, 93, 221, 24, 4, 83, 1, 120, 45, 80, 77, 154, 167, + 102, 17, 53, 115, 147, 245, 18, 117, 153, 88, 95, 20, 70, 111, + 184, 101, 203, 12, 20, 36, 33, 35, 209, 204, 22, 53, 177, 55, + 236, 204, 175, 225, 42, 97, 228, 108, 193, 229, 16, 21, 224, 196, + 221, 238, 59, 251, 63, 195, 208, 234, 167, 213, 252, 1, 21, 116, + 90, 97, 171, 10, 52, 203, 184, 120, 241, 199, 238, 75, 71, 54, + 209, 226, 90, 37, 124, 173, 77, 161, 132, 19, 146, 133, 111, 131, + 3, 114, 177, 15, 29, 26, 0, 96, 248, 139, 66, 212, 142, 43, + 106, 124, 19, 35, 230, 209, 238, 95, 15, 172, 48, 51, 4, 147, + 254, 98, 218, 105, 79, 146, 227, 69, 152, 140, 208, 247, 107, 236, + 130, 84, 86, 163, 131, 136, 205, 238, 95, 233, 103, 152, 227, 106, + 7, 13, 190, 186, 235, 76, 205, 233, 73, 215, 80, 193, 108, 230, + 49, 236, 47, 14, 131, 40, 107, 241, 170, 219, 202, 248, 232, 25, + 45, 197, 24, 247, 90, 155, 204, 163, 94, 80, 216, 44, 8, 158, + 95, 133, 169, 21, 138, 159, 179, 62, 5, 202, 99, 49, 173, 107, + 56, 242, 165, 91, 56, 234, 169, 140, 121, 200, 217, 4, 126, 15, + 77, 30, 121, 135, 250, 60, 89, 36, 200, 130, 138, 150, 53, 27, + 249, 107, 223, 19, 46, 240, 92, 197, 177, 188, 252, 71, 7, 231, + 138, 199, 34, 26, 86, 226, 132, 125, 96, 11, 204, 37, 4, 218, + 113, 147, 8, 239, 79, 120, 19, 33, 110, 174, 102, 130, 123, 11, + 196, 168, 74, 118, 246, 221, 110, 215, 44, 12, 158, 56, 141, 193, + 111, 179, 57, 8, 5, 207, 154, 121, 152, 107, 166, 155, 141, 5, + 134, 10, 151, 106, 146, 41, 120, 117, 4, 224, 215, 3, 92, 185, + 161, 101, 69, 214, 15, 216, 175, 138, 11, 205, 138, 159, 235, 140, + 208, 54, 190, 102, 240, 193, 55, 110, 210, 74, 128, 220, 20, 218, + 220, 236, 199, 184, 29, 200, 151, 11, 126, 203, 140, 22, 99, 247, + 202, 250, 84, 19, 166, 255, 125, 25, 14, 104, 215, 235, 105, 108, + 22, 138, 17, 16, 172, 0, 249, 105, 209, 11, 177, 179, 228, 125, + 119, 115, 169, 24, 215, 32, 7, 91, 246, 178, 116, 139, 206, 120, + 238, 100, 237, 237, 227, 122, 169, 238, 123, 110, 190, 8, 59, 226, + 59, 4, 73, 137, 100, 41, 168, 172, 218, 3, 44, 118, 56, 80, + 239, 246, 173, 175, 36, 8, 32, 178, 134, 158, 234, 238, 233, 103, + 88, 43, 219, 181, 149, 100, 207, 18, 117, 221, 11, 116, 31, 210, + 69, 237, 69, 168, 253, 69, 140, 162, 80, 132, 214, 12, 41, 24, + 80, 41, 146, 83, 64, 232, 117, 225, 79, 165, 45, 207, 55, 231, + 246, 30, 209, 22, 14, 169, 143, 152, 111, 147, 97, 46, 188, 231, + 118, 252, 153, 43, 16, 219, 146, 83, 33, 212, 137, 219, 6, 1, + 129, 163, 38, 220, 227, 109, 109, 222, 67, 235, 154, 149, 89, 69, + 234, 248, 255, 220, 161, 95, 164, 168, 29, 249, 162, 142, 232, 143, + 198, 116, 32, 202, 232, 72, 76, 124, 223, 215, 162, 182, 213, 162, + 183, 232, 38, 240, 219, 63, 156, 139, 193, 34, 141, 188, 16, 241, + 241, 79, 251, 36, 75, 148, 104, 40, 179, 198, 242, 161, 171, 1, + 150, 244, 99, 254, 77, 83, 234, 165, 130, 158, 155, 83, 254, 18, + 0, 40, 18, 65, 11, 97, 130, 161, 27, 40, 63, 200, 45, 168, + 167, 187, 142, 190, 101, 6, 48, 145, 108, 191, 90, 130, 254, 19, + 76, 69, 86, 250, 56, 221, 237, 117, 168, 242, 83, 159, 197, 133, + 6, 218, 215, 114, 83, 199, 244, 223, 112, 176, 149, 13, 114, 141, + 239, 234, 139, 143, 2, 224, 180, 151, 174, 53, 222, 132, 255, 201, + 190, 136, 134, 79, 101, 31, 148, 140, 82, 223, 205, 213, 214, 234, + 166, 138, 243, 13, 138, 206, 93, 35, 69, 166, 100, 151, 171, 138, + 2, 34, 85, 21, 223, 90, 222, 7, 107, 208, 178, 83, 182, 196, + 176, 42, 203, 247, 33, 74, 146, 202, 116, 204, 0, 225, 58, 103, + 24, 44, 179, 12, 19, 15, 123, 89, 140, 245, 58, 250, 141, 227, + 247, 35, 253, 46, 40, 198, 132, 57, 102, 255, 96, 85, 213, 106, + 239, 131, 84, 80, 209, 42, 105, 69, 70, 235, 160, 67, 190, 238, + 138, 29, 66, 181, 239, 90, 124, 120, 125, 219, 104, 49, 173, 227, + 53, 189, 192, 119, 243, 184, 217, 199, 79, 189, 204, 154, 76, 65, + 32, 22, 187, 158, 175, 103, 254, 39, 26, 9, 36, 241, 64, 124, + 218, 183, 136, 244, 118, 9, 210, 49, 81, 14, 230, 146, 57, 113, + 9, 2, 70, 46, 157, 35, 6, 190, 180, 149, 151, 0, 81, 118, + 38, 227, 19, 124, 83, 148, 145, 79, 42, 66, 238, 46, 73, 77, + 23, 81, 16, 217, 88, 83, 97, 236, 195, 31, 19, 57, 34, 51, + 99, 27, 149, 36, 167, 60, 131, 177, 145, 149, 193, 193, 143, 62, + 207, 98, 25, 98, 2, 114, 226, 253, 214, 181, 156, 143, 224, 13, + 51, 100, 119, 119, 20, 253, 200, 149, 84, 21, 0, 166, 80, 5, + 206, 168, 70, 36, 196, 75, 65, 48, 184, 251, 6, 210, 35, 211, + 129, 246, 29, 212, 102, 172, 139, 17, 6, 213, 203, 222, 178, 140, + 126, 188, 236, 157, 193, 186, 122, 238, 12, 201, 247, 148, 162, 82, + 40, 117, 67, 129, 111, 129, 81, 33, 4, 132, 45, 37, 43, 49, + 203, 88, 120, 18, 252, 124, 37, 186, 189, 196, 46, 54, 57, 47, + 86, 84, 42, 113, 222, 127, 121, 92, 58, 188, 215, 190, 244, 155, + 167, 144, 13, 178, 136, 186, 104, 4, 153, 14, 217, 199, 7, 239, + 222, 91, 144, 132, 30, 92, 136, 216, 196, 119, 61, 211, 138, 75, + 64, 134, 123, 29, 50, 42, 209, 184, 120, 45, 38, 103, 73, 148, + 155, 100, 136, 150, 3, 177, 41, 92, 208, 48, 103, 51, 181, 154, + 212, 159, 221, 224, 182, 36, 251, 57, 181, 58, 86, 121, 230, 186, + 143, 22, 101, 77, 43, 5, 134, 215, 172, 78, 20, 159, 252, 102, + 103, 233, 250, 95, 146, 178, 8, 86, 91, 162, 146, 25, 163, 15, + 100, 118, 173, 121, 255, 11, 145, 120, 167, 123, 198, 201, 22, 145, + 78, 106, 110, 123, 35, 33, 23, 230, 213, 151, 173, 192, 251, 46, + 195, 193, 163, 30, 148, 83, 112, 64, 179, 46, 226, 152, 249, 39, + 246, 67, 112, 197, 241, 244, 253, 43, 20, 125, 9, 151, 193, 146, + 226, 42, 167, 209, 235, 116, 34, 24, 115, 39, 116, 138, 140, 207, + 222, 229, 15, 8, 48, 218, 242, 147, 21, 96, 139, 38, 197, 3, + 229, 32, 73, 92, 35, 219, 73, 76, 193, 121, 26, 18, 164, 241, + 43, 180, 154, 224, 7, 41, 209, 106, 211, 167, 150, 215, 31, 119, + 161, 254, 114, 77, 17, 103, 119, 8, 107, 171, 48, 79, 11, 106, + 54, 151, 128, 66, 217, 112, 11, 194, 210, 66, 209, 52, 205, 167, + 77, 247, 97, 183, 62, 95, 26, 236, 134, 224, 87, 61, 101, 142, + 21, 71, 195, 183, 180, 218, 123, 169, 244, 242, 62, 160, 65, 128, + 229, 79, 119, 200, 112, 2, 119, 89, 211, 197, 115, 146, 67, 196, + 206, 164, 33, 22, 79, 46, 233, 200, 184, 239, 48, 62, 83, 253, + 196, 211, 215, 204, 20, 40, 9, 161, 66, 25, 199, 132, 164, 124, + 131, 100, 209, 97, 93, 202, 210, 161, 216, 125, 26, 238, 158, 204, + 99, 243, 205, 102, 241, 72, 26, 114, 162, 16, 103, 183, 27, 58, + 244, 52, 61, 227, 141, 135, 175, 64, 83, 41, 240, 165, 4, 29, + 24, 169, 142, 201, 23, 193, 200, 37, 157, 219, 197, 159, 4, 0, + 239, 35, 37, 178, 205, 12, 160, 92, 12, 233, 48, 172, 71, 81, + 171, 105, 37, 28, 34, 131, 187, 193, 185, 193, 105, 243, 244, 16, + 194, 14, 233, 112, 179, 239, 152, 117, 226, 79, 64, 85, 17, 188, + 118, 222, 175, 90, 236, 211, 141, 125, 57, 9, 146, 207, 98, 189, + 91, 15, 61, 170, 187, 8, 100, 33, 7, 43, 252, 56, 57, 35, + 122, 235, 17, 175, 52, 52, 131, 234, 133, 168, 63, 232, 10, 144, + 242, 37, 121, 250, 157, 56, 170, 85, 107, 2, 175, 31, 46, 216, + 67, 168, 120, 237, 230, 83, 205, 214, 25, 198, 110, 70, 136, 185, + 4, 42, 230, 234, 199, 249, 194, 152, 76, 199, 212, 35, 144, 72, + 155, 209, 85, 166, 49, 145, 100, 11, 70, 121, 213, 108, 243, 227, + 26, 250, 247, 202, 2, 197, 90, 94, 49, 186, 151, 237, 95, 187, + 85, 251, 127, 20, 75, 120, 28, 113, 213, 173, 213, 219, 201, 172, + 251, 27, 132, 130, 208, 94, 204, 63, 71, 128, 60, 47, 6, 156, + 106, 42, 3, 234, 6, 238, 224, 14, 117, 13, 86, 66, 122, 6, + 105, 60, 86, 193, 76, 166, 120, 245, 38, 206, 141, 3, 107, 105, + 147, 225, 125, 237, 130, 88, 23, 9, 67, 7, 229, 0, 99, 215, + 54, 117, 216, 22, 86, 38, 93, 60, 64, 132, 244, 201, 229, 58, + 239, 3, 11, 174, 151, 162, 226, 61, 107, 108, 100, 32, 11, 17, + 115, 161, 243, 53, 131, 209, 61, 71, 73, 167, 57, 249, 151, 225, + 52, 205, 73, 58, 1, 47, 215, 255, 43, 241, 2, 10, 112, 187, + 158, 94, 148, 85, 185, 73, 203, 31, 29, 190, 53, 45, 86, 87, + 12, 79, 51, 33, 60, 204, 119, 6, 154, 190, 198, 241, 152, 97, + 9, 80, 250, 12, 239, 134, 91, 198, 183, 101, 33, 128, 166, 18, + 190, 152, 47, 4, 225, 221, 188, 171, 236, 17, 2, 165, 182, 201, + 66, 129, 40, 74, 78, 57, 14, 99, 115, 128, 4, 240, 186, 131, + 113, 252, 27, 1, 229, 234, 240, 150, 156, 202, 102, 251, 229, 79, + 168, 72, 26, 61, 127, 186, 121, 173, 51, 176, 193, 32, 81, 104, + 246, 226, 112, 160, 56, 78, 136, 206, 146, 120, 30, 133, 127, 241, + 128, 114, 218, 171, 24, 43, 95, 148, 13, 66, 123, 52, 196, 245, + 120, 107, 104, 211, 229, 124, 103, 234, 8, 38, 161, 170, 138, 150, + 85, 112, 64, 105, 100, 106, 140, 90, 10, 181, 231, 62, 235, 79, + 8, 151, 51, 17, 50, 175, 48, 217, 48, 240, 141, 142, 203, 23, + 18, 101, 139, 122, 47, 117, 1, 225, 196, 105, 235, 35, 28, 61, + 10, 228, 142, 231, 64, 96, 221, 21, 237, 151, 74, 33, 78, 199, + 198, 90, 236, 121, 209, 247, 25, 68, 85, 168, 226, 122, 96, 208, + 148, 175, 250, 177, 57, 36, 38, 147, 53, 238, 247, 195, 192, 56, + 129, 194, 10, 120, 220, 222, 144, 177, 110, 206, 245, 56, 237, 98, + 178, 144, 207, 164, 5, 14, 215, 0, 234, 107, 47, 26, 239, 143, + 105, 30, 190, 90, 0, 25, 159, 187, 219, 241, 9, 147, 74, 23, + 222, 97, 81, 41, 163, 134, 205, 92, 198, 46, 85, 31, 108, 222, + 125, 169, 202, 116, 41, 156, 227, 75, 107, 255, 139, 137, 121, 55, + 126, 200, 115, 127, 3, 244, 156, 90, 2, 44, 229, 203, 213, 132, + 220, 137, 169, 158, 170, 197, 249, 11, 229, 166, 156, 107, 164, 199, + 232, 0, 209, 27, 185, 201, 42, 83, 185, 107, 100, 246, 152, 43, + 52, 129, 148, 197, 46, 172, 3, 136, 9, 226, 15, 79, 56, 95, + 123, 237, 49, 34, 131, 51, 72, 30, 11, 11, 216, 129, 50, 112, + 95, 10, 53, 78, 32, 70, 220, 94, 9, 106, 140, 230, 155, 84, + 9, 221, 34, 92, 33, 47, 87, 26, 68, 65, 102, 78, 216, 120, + 162, 21, 168, 193, 56, 91, 79, 46, 166, 135, 95, 215, 243, 89, + 25, 195, 52, 152, 249, 179, 20, 247, 67, 205, 136, 220, 49, 178, + 146, 30, 74, 252, 199, 239, 178, 118, 55, 22, 108, 182, 122, 28, + 79, 162, 65, 141, 107, 234, 20, 21, 0, 66, 202, 206, 172, 167, + 183, 234, 227, 98, 27, 71, 83, 116, 74, 45, 112, 20, 204, 38, + 16, 119, 163, 96, 187, 12, 222, 179, 109, 5, 208, 66, 170, 173, + 241, 64, 84, 47, 94, 134, 56, 71, 113, 214, 115, 225, 198, 86, + 0, 64, 59, 35, 124, 79, 51, 19, 247, 255, 145, 59, 37, 6, + 190, 197, 121, 143, 195, 4, 125, 89, 66, 53, 112, 78, 236, 93, + 244, 97, 113, 141, 128, 131, 65, 56, 245, 16, 220, 7, 191, 37, + 98, 240, 35, 66, 190, 53, 228, 117, 125, 178, 243, 229, 45, 32, + 29, 242, 199, 32, 250, 229, 105, 51, 93, 129, 72, 28, 123, 1, + 171, 143, 124, 167, 26, 0, 180, 214, 222, 77, 208, 111, 41, 219, + 198, 57, 216, 104, 115, 177, 71, 176, 102, 75, 225, 157, 30, 8, + 150, 229, 48, 5, 145, 237, 156, 81, 75, 249, 229, 74, 4, 151, + 27, 23, 172, 1, 167, 198, 89, 37, 124, 5, 21, 252, 95, 35, + 102, 52, 141, 183, 74, 9, 153, 88, 118, 10, 177, 64, 99, 186, + 250, 127, 185, 64, 95, 152, 213, 47, 34, 252, 194, 204, 243, 154, + 194, 137, 145, 58, 95, 228, 68, 83, 185, 153, 42, 137, 195, 216, + 146, 49, 73, 160, 49, 187, 90, 237, 227, 119, 69, 171, 241, 177, + 197, 236, 102, 78, 207, 171, 251, 137, 97, 14, 98, 142, 115, 166, + 54, 120, 90, 106, 102, 15, 223, 134, 235, 220, 193, 134, 121, 142, + 57, 238, 198, 180, 0, 220, 52, 104, 247, 110, 245, 54, 140, 70, + 122, 73, 6, 168, 123, 74, 66, 162, 46, 164, 185, 35, 182, 185, + 240, 81, 242, 126, 50, 49, 178, 78, 29, 85, 50, 244, 141, 167, + 118, 228, 148, 126, 229, 200, 248, 149, 173, 5, 117, 149, 18, 97, + 161, 110, 240, 239, 68, 5, 222, 235, 164, 84, 64, 21, 212, 144, + 138, 177, 157, 37, 105, 15, 97, 165, 178, 40, 81, 19, 206, 102, + 138, 150, 86, 51, 211, 159, 185, 255, 151, 127, 132, 250, 131, 27, + 28, 28, 44, 89, 252, 17, 94, 105, 143, 76, 155, 200, 63, 171, + 34, 79, 84, 205, 156, 214, 111, 143, 175, 94, 151, 228, 45, 157, + 45, 247, 123, 243, 145, 46, 124, 247, 241, 33, 7, 40, 153, 72, + 150, 86, 135, 181, 94, 89, 186, 21, 102, 69, 224, 181, 187, 223, + 21, 202, 18, 142, 223, 21, 147, 212, 85, 27, 84, 69, 47, 9, + 231, 253, 70, 16, 170, 186, 44, 83, 32, 232, 26, 198, 232, 122, + 203, 133, 208, 40, 107, 121, 147, 224, 164, 7, 32, 9, 0, 7, + 138, 46, 116, 135, 102, 110, 222, 106, 195, 233, 186, 155, 204, 147, + 37, 44, 188, 13, 98, 246, 86, 25, 17, 72, 145, 89, 91, 159, + 170, 53, 235, 126, 246, 195, 83, 224, 173, 158, 64, 251, 139, 36, + 160, 152, 210, 152, 113, 100, 28, 46, 117, 140, 244, 96, 230, 105, + 21, 26, 98, 241, 117, 37, 146, 208, 168, 34, 126, 83, 157, 180, + 108, 43, 165, 76, 165, 219, 13, 10, 118, 141, 168, 217, 235, 146, + 20, 182, 131, 169, 200, 226, 55, 181, 87, 1, 42, 111, 191, 3, + 29, 89, 133, 166, 210, 106, 86, 242, 26, 200, 143, 125, 254, 76, + 52, 186, 97, 210, 73, 64, 107, 44, 2, 148, 98, 160, 162, 149, + 47, 64, 165, 157, 126, 205, 227, 245, 220, 198, 221, 131, 161, 138, + 10, 186, 202, 15, 128, 0, 114, 28, 228, 116, 239, 156, 134, 206, + 149, 245, 108, 130, 217, 99, 118, 136, 180, 105, 235, 20, 15, 228, + 57, 80, 181, 69, 249, 110, 9, 137, 163, 250, 209, 212, 23, 221, + 21, 12, 71, 235, 207, 47, 86, 93, 255, 123, 236, 57, 139, 167, + 123, 83, 20, 8, 8, 161, 102, 137, 128, 73, 88, 230, 109, 170, + 6, 91, 48, 45, 63, 214, 25, 99, 168, 31, 59, 240, 180, 20, + 28, 138, 150, 88, 57, 188, 82, 49, 54, 216, 246, 119, 66, 223, + 103, 73, 77, 160, 234, 81, 67, 142, 77, 147, 118, 97, 140, 166, + 254, 20, 35, 60, 237, 255, 166, 17, 148, 66, 5, 210, 110, 11, + 137, 183, 23, 72, 144, 133, 135, 44, 137, 190, 112, 2, 13, 192, + 145, 155, 38, 146, 89, 113, 151, 135, 216, 90, 245, 5, 97, 236, + 113, 197, 0, 50, 155, 211, 164, 238, 64, 57, 29, 184, 93, 254, + 197, 239, 194, 188, 176, 13, 214, 61, 204, 130, 156, 197, 198, 197, + 217, 218, 122, 23, 201, 137, 67, 36, 235, 97, 48, 233, 111, 203, + 63, 172, 154, 63, 195, 74, 16, 48, 186, 79, 213, 123, 170, 40, + 17, 251, 43, 54, 211, 56, 251, 166, 221, 176, 183, 204, 157, 175, + 73, 95, 53, 224, 155, 187, 223, 38, 131, 48, 192, 230, 108, 224, + 210, 134, 223, 12, 89, 106, 75, 133, 73, 53, 64, 106, 253, 234, + 104, 26, 68, 223, 157, 105, 213, 112, 80, 36, 238, 164, 163, 17, + 23, 8, 83, 73, 38, 181, 92, 184, 192, 143, 163, 122, 8, 19, + 45, 125, 8, 64, 34, 244, 248, 181, 54, 31, 103, 228, 131, 193, + 35, 155, 106, 98, 127, 20, 156, 14, 238, 254, 178, 241, 52, 146, + 146, 49, 209, 96, 19, 92, 23, 204, 226, 216, 67, 71, 247, 19, + 50, 199, 86, 176, 12, 143, 37, 198, 246, 105, 233, 52, 170, 190, + 137, 108, 180, 135, 14, 188, 92, 142, 235, 59, 93, 130, 54, 247, + 113, 224, 222, 223, 66, 221, 180, 123, 117, 163, 169, 163, 28, 21, + 132, 132, 145, 172, 198, 122, 234, 250, 68, 81, 66, 165, 68, 53, + 150, 214, 105, 3, 189, 229, 131, 208, 89, 88, 239, 125, 130, 97, + 186, 178, 226, 64, 129, 158, 147, 25, 192, 52, 39, 124, 197, 96, + 88, 251, 156, 71, 230, 234, 46, 16, 139, 206, 11, 196, 16, 246, + 7, 236, 242, 220, 28, 61, 164, 53, 60, 219, 207, 75, 146, 2, + 230, 124, 189, 3, 212, 71, 165, 6, 8, 12, 148, 143, 31, 197, + 174, 36, 214, 240, 124, 26, 95, 64, 170, 181, 56, 210, 175, 100, + 194, 27, 225, 16, 118, 10, 15, 11, 66, 113, 98, 2, 129, 117, + 38, 123, 85, 157, 17, 173, 13, 1, 129, 253, 138, 55, 55, 204, + 137, 240, 219, 210, 154, 65, 65, 93, 104, 83, 120, 167, 10, 0, + 124, 231, 51, 236, 230, 7, 28, 77, 179, 250, 152, 155, 67, 123, + 2, 246, 213, 87, 149, 14, 219, 192, 189, 90, 243, 66, 160, 159, + 74, 100, 11, 193, 215, 143, 152, 158, 109, 175, 202, 54, 42, 98, + 154, 50, 69, 4, 98, 37, 60, 129, 13, 0, 249, 74, 209, 66, + 109, 83, 29, 146, 69, 121, 125, 245, 128, 230, 196, 112, 152, 120, + 213, 170, 218, 95, 190, 25, 225, 147, 49, 67, 164, 91, 79, 15, + 150, 117, 2, 166, 23, 133, 162, 112, 150, 49, 99, 159, 156, 169, + 21, 47, 212, 57, 185, 38, 122, 199, 38, 105, 135, 14, 231, 239, + 12, 201, 216, 110, 40, 106, 124, 204, 206, 119, 136, 95, 103, 25, + 201, 90, 114, 27, 3, 205, 224, 161, 103, 44, 158, 89, 234, 234, + 23, 138, 56, 55, 108, 240, 5, 103, 58, 164, 181, 161, 131, 244, + 21, 229, 117, 26, 141, 138, 69, 161, 239, 194, 82, 180, 65, 179, + 206, 33, 191, 78, 0, 111, 108, 40, 237, 123, 85, 225, 118, 216, + 192, 120, 224, 252, 166, 70, 96, 112, 64, 75, 78, 180, 45, 60, + 52, 152, 14, 200, 154, 246, 213, 237, 158, 153, 173, 164, 51, 234, + 95, 154, 0, 84, 171, 189, 1, 233, 133, 43, 116, 241, 166, 147, + 167, 134, 78, 2, 144, 139, 199, 255, 178, 20, 245, 124, 90, 238, + 130, 77, 170, 193, 91, 184, 231, 210, 10, 181, 36, 30, 37, 236, + 122, 37, 61, 129, 236, 97, 179, 154, 53, 192, 78, 109, 10, 188, + 175, 182, 224, 189, 59, 186, 205, 206, 105, 170, 230, 63, 171, 204, + 22, 100, 107, 103, 41, 74, 197, 140, 131, 70, 27, 57, 81, 4, + 180, 77, 51, 93, 19, 214, 170, 41, 72, 9, 37, 108, 239, 251, + 194, 203, 251, 171, 23, 119, 10, 245, 37, 208, 42, 150, 33, 225, + 15, 196, 165, 58, 0, 215, 255, 133, 142, 150, 85, 214, 239, 71, + 253, 141, 61, 75, 163, 184, 53, 151, 52, 164, 112, 144, 204, 105, + 51, 85, 121, 151, 255, 94, 203, 14, 63, 222, 120, 101, 191, 8, + 55, 240, 17, 22, 60, 162, 104, 79, 110, 197, 110, 145, 91, 115, + 72, 157, 250, 187, 228, 20, 117, 224, 255, 44, 193, 78, 121, 199, + 255, 159, 68, 145, 91, 118, 146, 104, 93, 111, 253, 191, 225, 216, + 176, 65, 204, 219, 235, 255, 75, 121, 45, 73, 94, 125, 178, 210, + 230, 187, 158, 129, 190, 144, 99, 131, 134, 108, 128, 147, 214, 150, + 130, 135, 15, 42, 232, 102, 120, 113, 204, 164, 199, 10, 66, 185, + 31, 17, 156, 220, 78, 163, 79, 173, 60, 115, 255, 146, 9, 229, + 202, 54, 168, 84, 108, 118, 3, 119, 117, 82, 221, 17, 215, 82, + 6, 145, 209, 64, 40, 127, 177, 197, 22, 244, 250, 182, 216, 152, + 99, 38, 189, 112, 45, 174, 3, 206, 245, 147, 205, 91, 132, 105, + 187, 149, 146, 205, 18, 19, 245, 107, 177, 160, 174, 65, 5, 37, + 114, 93, 147, 172, 174, 47, 36, 231, 69, 106, 58, 100, 159, 50, + 58, 176, 199, 137, 9, 23, 156, 200, 235, 1, 9, 79, 196, 95, + 212, 53, 230, 183, 241, 91, 212, 66, 156, 191, 227, 79, 136, 204, + 38, 223, 31, 118, 104, 50, 94, 50, 130, 199, 186, 35, 33, 221, + 226, 205, 137, 239, 215, 12, 70, 192, 232, 217, 2, 153, 83, 44, + 35, 57, 215, 36, 131, 139, 53, 223, 29, 43, 29, 31, 199, 142, + 239, 218, 163, 205, 26, 99, 15, 73, 127, 193, 182, 7, 214, 172, + 188, 66, 224, 168, 40, 174, 63, 96, 250, 233, 131, 41, 34, 110, + 255, 124, 42, 25, 201, 115, 178, 34, 121, 11, 29, 45, 84, 195, + 100, 95, 207, 81, 12, 185, 29, 138, 36, 123, 114, 255, 20, 156, + 35, 203, 218, 149, 24, 43, 230, 239, 228, 78, 253, 108, 223, 204, + 128, 188, 20, 63, 150, 98, 184, 245, 79, 224, 117, 126, 57, 199, + 232, 172, 76, 29, 89, 124, 104, 240, 207, 162, 213, 159, 155, 33, + 181, 7, 217, 56, 241, 150, 204, 255, 118, 245, 94, 11, 245, 199, + 132, 54, 113, 39, 246, 66, 92, 154, 178, 46, 119, 230, 212, 77, + 55, 47, 166, 18, 19, 143, 118, 234, 122, 230, 59, 183, 129, 113, + 56, 52, 197, 191, 194, 49, 150, 133, 144, 155, 25, 73, 171, 252, + 244, 63, 172, 34, 55, 150, 197, 99, 17, 67, 171, 234, 97, 254, + 159, 168, 97, 64, 7, 39, 195, 202, 160, 185, 121, 25, 103, 180, + 233, 248, 181, 145, 130, 93, 134, 65, 213, 4, 32, 87, 164, 143, + 129, 114, 85, 193, 26, 231, 101, 146, 158, 71, 227, 4, 126, 131, + 11, 94, 191, 197, 1, 241, 165, 226, 212, 101, 28, 160, 237, 25, + 70, 6, 194, 120, 83, 113, 230, 254, 165, 86, 78, 24, 238, 223, + 99, 179, 185, 119, 241, 84, 148, 173, 123, 83, 65, 118, 213, 42, + 6, 232, 14, 200, 55, 191, 101, 224, 197, 96, 56, 101, 47, 88, + 48, 246, 210, 216, 27, 206, 4, 222, 42, 106, 217, 27, 150, 222, + 61, 248, 47, 80, 54, 150, 249, 15, 88, 52, 0, 69, 209, 153, + 188, 105, 156, 213, 1, 198, 163, 182, 120, 164, 215, 103, 2, 18, + 90, 61, 92, 192, 169, 248, 138, 67, 15, 170, 240, 24, 124, 37, + 10, 157, 124, 141, 226, 147, 72, 8, 86, 183, 229, 115, 215, 139, + 113, 168, 120, 158, 169, 36, 174, 159, 125, 77, 211, 95, 21, 85, + 173, 131, 177, 208, 66, 18, 16, 106, 99, 212, 225, 197, 171, 16, + 222, 182, 46, 183, 87, 104, 106, 126, 194, 96, 214, 92, 37, 232, + 98, 226, 246, 250, 123, 5, 156, 38, 176, 247, 204, 146, 206, 130, + 201, 126, 53, 211, 212, 181, 117, 68, 175, 71, 75, 100, 89, 227, + 105, 251, 209, 58, 88, 206, 161, 186, 231, 1, 67, 46, 80, 65, + 82, 37, 183, 175, 153, 174, 4, 35, 104, 23, 119, 151, 5, 69, + 11, 92, 122, 59, 83, 132, 55, 69, 248, 37, 214, 98, 87, 40, + 41, 253, 5, 50, 185, 76, 113, 23, 81, 92, 125, 181, 88, 221, + 236, 249, 113, 116, 72, 147, 242, 240, 76, 170, 160, 101, 227, 219, + 198, 209, 116, 221, 130, 98, 58, 117, 159, 87, 76, 66, 158, 77, + 238, 99, 63, 70, 84, 5, 221, 104, 128, 9, 158, 130, 87, 110, + 211, 73, 164, 164, 11, 206, 172, 61, 95, 209, 31, 154, 243, 232, + 3, 110, 186, 94, 227, 39, 97, 126, 243, 68, 189, 75, 21, 33, + 133, 24, 240, 175, 54, 113, 115, 222, 61, 219, 66, 51, 197, 87, + 120, 51, 43, 30, 89, 87, 180, 73, 100, 183, 252, 148, 200, 245, + 126, 20, 84, 151, 86, 99, 156, 100, 166, 218, 250, 232, 196, 185, + 51, 26, 204, 71, 174, 241, 169, 89, 101, 137, 186, 84, 103, 195, + 59, 135, 99, 151, 227, 7, 31, 35, 185, 95, 98, 185, 104, 203, + 83, 221, 70, 153, 57, 128, 1, 20, 2, 0, 0, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 99, + 108, 101, 97, 114, 116, 111, 109, 97, 114, 107, 13, 128, 3, +}; diff --git a/Rendering/fonts/face_courier_italic.cxx b/Rendering/fonts/face_courier_italic.cxx new file mode 100644 index 0000000..bfedb94 --- /dev/null +++ b/Rendering/fonts/face_courier_italic.cxx @@ -0,0 +1,2833 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Courier Italic +// Courier 10 Pitch Regular Italic (c0582bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_courier_italic_buffer_length = 39511; + +unsigned char face_courier_italic_buffer[] = { + 128, 1, 228, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 83, + 117, 110, 32, 78, 111, 118, 32, 32, 52, 32, 49, 57, 58, 50, + 52, 58, 50, 56, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 67, + 111, 117, 114, 105, 101, 114, 32, 49, 48, 32, 80, 105, 116, 99, + 104, 32, 73, 116, 97, 108, 105, 99, 41, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 70, 97, + 109, 105, 108, 121, 78, 97, 109, 101, 32, 40, 67, 111, 117, 114, + 105, 101, 114, 32, 49, 48, 32, 80, 105, 116, 99, 104, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, + 32, 47, 87, 101, 105, 103, 104, 116, 32, 40, 78, 111, 114, 109, + 97, 108, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, + 101, 102, 13, 32, 32, 47, 73, 116, 97, 108, 105, 99, 65, 110, + 103, 108, 101, 32, 32, 49, 50, 46, 48, 48, 48, 48, 32, 100, + 101, 102, 13, 32, 32, 47, 105, 115, 70, 105, 120, 101, 100, 80, + 105, 116, 99, 104, 32, 116, 114, 117, 101, 32, 100, 101, 102, 13, + 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 80, 111, + 115, 105, 116, 105, 111, 110, 32, 45, 57, 55, 32, 100, 101, 102, + 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, 101, 84, + 104, 105, 99, 107, 110, 101, 115, 115, 32, 56, 49, 32, 100, 101, + 102, 13, 101, 110, 100, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 78, 97, 109, 101, + 32, 47, 67, 111, 117, 114, 105, 101, 114, 49, 48, 80, 105, 116, + 99, 104, 66, 84, 45, 73, 116, 97, 108, 105, 99, 32, 100, 101, + 102, 13, 47, 80, 97, 105, 110, 116, 84, 121, 112, 101, 32, 48, + 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 84, 121, 112, 101, + 32, 49, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 77, 97, + 116, 114, 105, 120, 32, 91, 48, 46, 48, 48, 49, 32, 48, 32, + 48, 32, 48, 46, 48, 48, 49, 32, 48, 32, 48, 93, 32, 114, + 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 69, + 110, 99, 111, 100, 105, 110, 103, 32, 83, 116, 97, 110, 100, 97, + 114, 100, 69, 110, 99, 111, 100, 105, 110, 103, 32, 100, 101, 102, + 13, 47, 70, 111, 110, 116, 66, 66, 111, 120, 32, 123, 45, 57, + 49, 32, 45, 50, 57, 57, 32, 54, 54, 51, 32, 56, 53, 56, + 125, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 13, 47, 85, 110, 105, 113, 117, 101, 73, 68, 32, 49, 53, 53, + 51, 48, 53, 56, 50, 32, 100, 101, 102, 13, 99, 117, 114, 114, + 101, 110, 116, 100, 105, 99, 116, 32, 101, 110, 100, 13, 99, 117, + 114, 114, 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, 101, + 99, 13, 128, 2, 75, 146, 0, 0, 162, 149, 24, 64, 131, 138, + 65, 51, 131, 156, 169, 210, 46, 43, 153, 242, 182, 28, 118, 124, + 214, 117, 8, 10, 172, 252, 178, 78, 25, 205, 19, 54, 115, 155, + 182, 73, 148, 197, 103, 55, 9, 11, 76, 236, 146, 201, 148, 95, + 240, 116, 94, 247, 255, 198, 27, 176, 169, 163, 184, 73, 231, 233, + 135, 64, 229, 108, 11, 90, 247, 135, 85, 156, 198, 149, 106, 179, + 30, 51, 207, 133, 83, 213, 92, 11, 14, 129, 142, 245, 236, 107, + 244, 129, 98, 234, 196, 46, 115, 128, 202, 146, 29, 174, 28, 130, + 179, 143, 214, 188, 242, 0, 26, 187, 93, 0, 26, 86, 21, 112, + 148, 207, 226, 125, 143, 78, 172, 150, 147, 232, 131, 114, 210, 3, + 88, 180, 126, 12, 56, 118, 85, 142, 191, 117, 122, 31, 188, 92, + 28, 221, 246, 43, 60, 87, 191, 114, 126, 241, 196, 135, 148, 34, + 193, 66, 160, 132, 209, 199, 70, 42, 194, 147, 224, 151, 250, 190, + 58, 62, 207, 205, 130, 113, 242, 89, 131, 59, 172, 121, 18, 112, + 114, 24, 236, 154, 48, 99, 191, 115, 133, 224, 45, 140, 16, 88, + 172, 6, 223, 0, 179, 59, 140, 1, 135, 104, 178, 120, 1, 14, + 178, 127, 95, 64, 150, 82, 94, 68, 230, 177, 113, 71, 203, 255, + 22, 162, 255, 22, 219, 66, 116, 61, 41, 78, 228, 132, 128, 225, + 142, 176, 230, 250, 159, 93, 204, 96, 244, 214, 111, 33, 88, 8, + 51, 76, 239, 154, 142, 32, 126, 53, 154, 98, 188, 218, 84, 129, + 248, 53, 103, 252, 116, 134, 34, 124, 114, 142, 112, 4, 107, 132, + 72, 10, 163, 129, 244, 130, 140, 200, 44, 46, 172, 99, 196, 113, + 10, 90, 6, 1, 242, 201, 78, 74, 211, 61, 156, 102, 92, 88, + 216, 56, 244, 241, 43, 191, 47, 177, 241, 53, 121, 179, 231, 248, + 126, 121, 62, 213, 105, 158, 87, 4, 151, 27, 36, 153, 239, 19, + 205, 239, 16, 123, 176, 178, 109, 119, 52, 5, 201, 168, 122, 116, + 111, 91, 212, 247, 127, 97, 216, 246, 177, 107, 163, 219, 8, 119, + 68, 115, 31, 27, 53, 79, 144, 92, 225, 236, 39, 119, 0, 186, + 201, 86, 222, 169, 19, 236, 35, 114, 116, 129, 15, 38, 22, 176, + 204, 50, 38, 22, 109, 137, 45, 2, 195, 180, 0, 33, 195, 206, + 76, 231, 185, 175, 250, 201, 16, 188, 165, 117, 236, 151, 239, 89, + 182, 208, 95, 70, 66, 19, 241, 195, 231, 100, 162, 80, 154, 85, + 109, 34, 158, 79, 54, 22, 56, 137, 158, 228, 125, 144, 213, 147, + 87, 121, 254, 160, 159, 155, 111, 223, 124, 66, 105, 246, 17, 138, + 62, 217, 190, 84, 139, 35, 220, 223, 86, 28, 108, 242, 107, 199, + 9, 175, 168, 107, 238, 176, 15, 44, 39, 0, 10, 4, 87, 145, + 48, 186, 219, 110, 168, 255, 41, 190, 133, 105, 111, 61, 174, 77, + 34, 38, 2, 135, 12, 222, 88, 10, 254, 233, 131, 214, 143, 57, + 249, 160, 230, 63, 183, 20, 214, 211, 197, 15, 163, 113, 120, 70, + 181, 190, 149, 5, 128, 192, 168, 111, 204, 39, 176, 173, 135, 186, + 164, 48, 46, 158, 96, 254, 117, 113, 236, 141, 195, 30, 71, 138, + 234, 136, 221, 39, 21, 138, 118, 201, 200, 26, 13, 233, 123, 232, + 51, 151, 155, 238, 64, 88, 163, 25, 80, 250, 76, 219, 208, 142, + 41, 133, 245, 227, 160, 230, 4, 226, 124, 17, 30, 8, 25, 139, + 136, 90, 220, 35, 97, 93, 95, 10, 183, 233, 247, 38, 199, 152, + 242, 151, 141, 225, 164, 224, 134, 74, 155, 249, 134, 135, 202, 55, + 96, 89, 231, 153, 200, 9, 19, 35, 52, 121, 201, 136, 39, 80, + 249, 173, 93, 210, 0, 98, 106, 140, 197, 26, 176, 156, 98, 53, + 44, 91, 108, 143, 0, 3, 243, 216, 187, 247, 240, 76, 17, 99, + 123, 116, 74, 135, 64, 207, 132, 206, 150, 215, 81, 108, 1, 164, + 153, 26, 78, 62, 137, 70, 210, 147, 162, 238, 240, 48, 201, 9, + 215, 69, 127, 164, 63, 240, 44, 188, 80, 225, 247, 14, 180, 183, + 156, 37, 70, 78, 60, 131, 28, 221, 24, 130, 137, 242, 112, 217, + 143, 51, 194, 121, 91, 212, 249, 82, 196, 75, 125, 130, 16, 135, + 235, 247, 59, 101, 64, 131, 189, 179, 45, 146, 114, 80, 38, 116, + 205, 166, 242, 206, 28, 136, 151, 211, 80, 63, 152, 62, 7, 191, + 205, 76, 248, 71, 91, 142, 214, 164, 129, 123, 217, 119, 202, 208, + 150, 40, 207, 3, 1, 38, 193, 99, 198, 73, 102, 232, 255, 146, + 162, 33, 77, 244, 123, 19, 192, 71, 28, 24, 130, 76, 14, 49, + 1, 2, 128, 108, 16, 184, 251, 19, 17, 239, 223, 110, 47, 236, + 9, 167, 81, 173, 210, 107, 134, 146, 211, 87, 219, 194, 240, 169, + 79, 22, 65, 31, 51, 160, 17, 253, 157, 182, 83, 71, 77, 209, + 110, 70, 44, 187, 43, 114, 248, 15, 124, 245, 146, 86, 249, 151, + 10, 146, 81, 185, 229, 59, 34, 4, 155, 101, 34, 198, 199, 97, + 88, 139, 113, 38, 89, 102, 201, 104, 33, 226, 58, 49, 150, 233, + 193, 190, 96, 179, 174, 249, 185, 200, 200, 104, 251, 106, 250, 218, + 39, 208, 151, 136, 6, 172, 3, 161, 162, 140, 113, 50, 205, 31, + 125, 56, 107, 194, 243, 75, 249, 2, 244, 16, 13, 112, 140, 6, + 163, 30, 177, 16, 229, 150, 190, 32, 252, 181, 179, 126, 50, 252, + 141, 173, 158, 73, 188, 115, 187, 173, 134, 222, 153, 88, 245, 154, + 76, 176, 192, 201, 126, 78, 50, 11, 1, 149, 177, 178, 117, 218, + 31, 79, 136, 234, 27, 9, 209, 104, 35, 206, 109, 250, 25, 124, + 64, 160, 183, 3, 52, 81, 46, 214, 151, 235, 28, 62, 47, 71, + 178, 36, 78, 3, 169, 12, 131, 92, 152, 159, 70, 141, 125, 72, + 8, 205, 50, 252, 164, 91, 169, 240, 219, 87, 40, 153, 54, 55, + 88, 114, 143, 43, 42, 14, 174, 46, 251, 67, 100, 155, 171, 243, + 42, 68, 167, 134, 144, 140, 203, 13, 126, 247, 123, 195, 99, 24, + 186, 114, 57, 85, 100, 165, 75, 0, 5, 105, 64, 20, 216, 74, + 89, 193, 104, 251, 15, 3, 190, 212, 237, 144, 143, 179, 57, 69, + 165, 54, 120, 15, 199, 231, 14, 235, 12, 48, 163, 193, 216, 192, + 68, 111, 212, 51, 10, 50, 209, 126, 74, 207, 30, 255, 13, 58, + 45, 50, 188, 218, 252, 242, 199, 239, 13, 192, 180, 65, 129, 164, + 2, 231, 1, 202, 66, 112, 182, 196, 161, 144, 193, 171, 44, 122, + 225, 188, 218, 159, 91, 67, 131, 72, 33, 169, 4, 74, 197, 78, + 1, 95, 226, 138, 230, 136, 203, 127, 44, 85, 155, 16, 233, 57, + 137, 108, 35, 198, 133, 35, 9, 84, 227, 39, 98, 83, 15, 15, + 102, 19, 56, 72, 244, 193, 82, 73, 48, 91, 77, 41, 163, 197, + 209, 105, 142, 91, 87, 188, 50, 231, 103, 161, 121, 249, 27, 233, + 246, 31, 49, 146, 3, 110, 16, 243, 248, 83, 157, 34, 221, 216, + 130, 240, 249, 22, 213, 151, 135, 250, 158, 193, 3, 248, 2, 132, + 106, 104, 180, 251, 85, 142, 206, 197, 71, 159, 203, 30, 253, 203, + 146, 24, 23, 179, 196, 33, 199, 74, 200, 223, 193, 110, 151, 167, + 125, 195, 90, 170, 43, 234, 51, 110, 32, 49, 34, 218, 146, 156, + 180, 51, 196, 251, 103, 41, 42, 242, 51, 88, 244, 6, 137, 170, + 40, 255, 247, 135, 171, 43, 238, 157, 249, 251, 251, 68, 69, 105, + 42, 73, 20, 112, 228, 209, 81, 39, 218, 38, 237, 182, 123, 240, + 26, 60, 75, 126, 71, 215, 231, 231, 240, 152, 87, 5, 183, 5, + 181, 213, 62, 177, 142, 20, 128, 82, 50, 154, 35, 110, 27, 114, + 42, 2, 26, 46, 10, 97, 52, 135, 135, 218, 182, 72, 125, 199, + 110, 61, 234, 76, 164, 142, 108, 135, 18, 63, 45, 68, 178, 33, + 88, 184, 64, 98, 28, 211, 118, 105, 201, 105, 160, 158, 222, 7, + 60, 102, 252, 215, 73, 138, 62, 198, 61, 148, 218, 31, 64, 47, + 66, 212, 131, 104, 243, 103, 218, 250, 42, 133, 116, 83, 66, 242, + 234, 78, 105, 142, 51, 193, 241, 83, 78, 171, 247, 68, 1, 175, + 195, 125, 253, 53, 94, 160, 174, 198, 250, 10, 147, 3, 37, 165, + 239, 129, 160, 54, 7, 8, 113, 180, 99, 182, 249, 122, 161, 16, + 51, 211, 87, 182, 38, 19, 156, 88, 251, 1, 239, 96, 38, 119, + 233, 147, 7, 1, 88, 56, 222, 220, 44, 127, 78, 245, 43, 92, + 136, 131, 130, 199, 4, 237, 207, 231, 202, 240, 31, 55, 248, 229, + 27, 6, 27, 112, 200, 130, 133, 248, 0, 248, 59, 58, 200, 7, + 128, 47, 228, 221, 23, 119, 191, 2, 65, 2, 202, 146, 74, 96, + 100, 62, 242, 190, 133, 229, 191, 119, 15, 234, 230, 86, 19, 37, + 50, 58, 76, 152, 172, 189, 251, 0, 36, 42, 67, 211, 142, 233, + 46, 177, 178, 243, 161, 121, 252, 202, 166, 27, 31, 19, 130, 235, + 123, 147, 63, 117, 28, 9, 186, 217, 196, 136, 209, 254, 178, 232, + 39, 236, 65, 138, 85, 130, 215, 14, 68, 108, 76, 138, 71, 242, + 50, 234, 95, 109, 227, 88, 36, 76, 44, 84, 58, 78, 219, 85, + 141, 84, 33, 212, 7, 83, 222, 123, 192, 138, 200, 97, 246, 139, + 18, 67, 92, 230, 159, 20, 221, 255, 75, 51, 49, 209, 70, 70, + 46, 74, 198, 199, 240, 34, 234, 171, 2, 181, 200, 131, 180, 45, + 116, 198, 1, 182, 155, 134, 68, 196, 115, 29, 183, 212, 119, 201, + 171, 253, 26, 152, 197, 83, 216, 108, 44, 20, 143, 226, 174, 243, + 14, 246, 186, 209, 210, 86, 136, 161, 84, 192, 132, 8, 114, 34, + 85, 40, 9, 238, 134, 37, 204, 32, 246, 230, 106, 202, 116, 37, + 252, 137, 122, 254, 50, 9, 127, 185, 187, 225, 58, 132, 87, 205, + 191, 112, 96, 106, 72, 159, 101, 165, 27, 139, 57, 48, 248, 85, + 128, 50, 100, 172, 26, 2, 200, 185, 141, 250, 181, 147, 93, 236, + 210, 97, 193, 42, 168, 177, 128, 102, 75, 170, 85, 192, 127, 29, + 152, 10, 82, 195, 180, 244, 131, 8, 125, 168, 232, 29, 13, 129, + 82, 208, 243, 197, 137, 165, 46, 226, 216, 240, 195, 109, 122, 218, + 161, 221, 166, 214, 99, 133, 156, 185, 222, 146, 97, 35, 80, 114, + 233, 16, 86, 186, 15, 81, 41, 216, 107, 224, 23, 142, 81, 210, + 236, 15, 83, 65, 157, 102, 15, 146, 159, 248, 203, 7, 199, 241, + 82, 215, 142, 8, 85, 32, 209, 72, 172, 142, 177, 146, 156, 118, + 220, 206, 149, 159, 19, 64, 50, 71, 213, 131, 57, 152, 184, 226, + 225, 222, 142, 249, 150, 123, 26, 200, 191, 91, 82, 59, 124, 253, + 165, 38, 178, 202, 27, 235, 110, 33, 205, 41, 184, 218, 170, 151, + 169, 224, 120, 214, 1, 4, 45, 140, 228, 209, 244, 56, 239, 85, + 139, 111, 43, 173, 171, 113, 150, 45, 105, 72, 25, 234, 159, 219, + 149, 108, 172, 199, 251, 56, 174, 205, 213, 69, 233, 245, 109, 48, + 65, 25, 228, 209, 17, 143, 124, 17, 162, 162, 77, 57, 147, 223, + 58, 26, 249, 104, 131, 180, 209, 22, 44, 101, 79, 26, 238, 11, + 158, 148, 226, 76, 189, 143, 204, 105, 64, 138, 190, 83, 72, 112, + 140, 1, 188, 126, 150, 210, 147, 127, 205, 5, 150, 119, 206, 61, + 141, 206, 195, 124, 6, 19, 96, 106, 85, 117, 58, 43, 27, 69, + 118, 43, 34, 201, 96, 38, 236, 38, 127, 199, 198, 17, 237, 20, + 254, 114, 224, 99, 209, 48, 229, 122, 4, 63, 78, 213, 118, 235, + 227, 12, 56, 168, 155, 187, 145, 29, 188, 114, 226, 27, 237, 203, + 216, 113, 196, 201, 137, 184, 145, 154, 100, 167, 218, 55, 134, 205, + 175, 119, 14, 66, 155, 241, 37, 185, 76, 252, 2, 152, 16, 101, + 126, 211, 227, 10, 196, 84, 21, 214, 172, 237, 132, 47, 11, 185, + 39, 214, 62, 67, 77, 151, 219, 239, 61, 174, 232, 242, 178, 162, + 101, 222, 9, 177, 173, 71, 111, 187, 99, 87, 17, 35, 111, 70, + 240, 95, 124, 221, 179, 45, 234, 93, 142, 176, 177, 79, 47, 230, + 31, 4, 61, 92, 127, 207, 174, 255, 189, 132, 146, 161, 5, 29, + 99, 246, 200, 52, 188, 19, 227, 200, 58, 13, 146, 186, 181, 170, + 245, 44, 132, 233, 197, 42, 108, 115, 14, 1, 95, 57, 57, 196, + 159, 80, 160, 35, 57, 81, 57, 249, 118, 143, 211, 188, 128, 66, + 125, 21, 118, 246, 205, 94, 131, 123, 182, 136, 196, 78, 160, 144, + 68, 65, 160, 156, 26, 244, 249, 113, 4, 220, 190, 245, 149, 189, + 5, 43, 44, 136, 155, 20, 41, 135, 80, 84, 59, 52, 3, 190, + 71, 7, 231, 29, 212, 164, 241, 249, 174, 222, 57, 108, 174, 64, + 172, 246, 241, 75, 98, 204, 229, 104, 85, 177, 145, 169, 176, 192, + 103, 59, 243, 195, 92, 66, 125, 167, 190, 223, 34, 246, 247, 161, + 154, 100, 23, 37, 128, 185, 98, 238, 128, 137, 152, 185, 66, 214, + 179, 55, 8, 170, 55, 129, 207, 145, 234, 217, 50, 140, 43, 120, + 223, 201, 113, 111, 196, 182, 10, 241, 179, 97, 226, 172, 49, 80, + 33, 80, 188, 198, 232, 7, 242, 121, 194, 163, 161, 208, 102, 89, + 3, 186, 58, 115, 229, 133, 8, 156, 107, 31, 167, 16, 255, 158, + 207, 12, 31, 234, 72, 42, 68, 136, 138, 209, 227, 71, 253, 80, + 182, 240, 191, 35, 102, 127, 100, 176, 164, 133, 246, 127, 239, 184, + 184, 252, 209, 68, 155, 240, 116, 235, 228, 241, 47, 8, 252, 252, + 231, 18, 48, 157, 144, 148, 172, 165, 141, 207, 238, 173, 33, 95, + 195, 19, 52, 255, 138, 27, 1, 30, 120, 114, 5, 190, 48, 93, + 34, 191, 70, 186, 69, 9, 62, 237, 152, 73, 66, 17, 6, 146, + 24, 101, 37, 29, 197, 243, 97, 4, 7, 30, 67, 226, 9, 107, + 212, 33, 154, 71, 125, 66, 233, 19, 86, 252, 240, 34, 45, 176, + 49, 7, 74, 32, 209, 89, 192, 215, 243, 170, 97, 94, 114, 154, + 205, 213, 70, 168, 124, 25, 171, 186, 75, 81, 254, 28, 220, 127, + 160, 217, 13, 17, 158, 149, 19, 242, 14, 55, 159, 25, 113, 211, + 105, 99, 157, 31, 181, 4, 167, 41, 84, 132, 58, 52, 168, 254, + 59, 106, 40, 209, 78, 19, 3, 42, 91, 235, 112, 24, 144, 215, + 219, 112, 193, 97, 193, 242, 206, 247, 252, 200, 143, 127, 239, 7, + 41, 246, 166, 82, 218, 239, 187, 199, 162, 43, 241, 148, 33, 14, + 187, 156, 252, 163, 149, 232, 150, 165, 192, 81, 27, 7, 7, 98, + 75, 27, 154, 208, 220, 19, 29, 4, 220, 139, 231, 249, 191, 235, + 137, 176, 190, 37, 225, 81, 64, 117, 201, 152, 30, 82, 111, 72, + 75, 173, 200, 193, 119, 163, 239, 115, 42, 148, 155, 94, 70, 199, + 27, 117, 91, 28, 36, 74, 187, 177, 193, 43, 55, 160, 202, 175, + 67, 98, 200, 172, 120, 189, 40, 65, 21, 239, 238, 106, 75, 70, + 185, 31, 140, 63, 54, 141, 53, 34, 247, 247, 247, 145, 171, 19, + 87, 97, 32, 89, 98, 152, 87, 185, 252, 170, 79, 100, 110, 193, + 158, 96, 246, 150, 85, 132, 197, 233, 208, 125, 197, 139, 141, 159, + 108, 26, 11, 28, 244, 52, 14, 238, 133, 222, 67, 25, 87, 56, + 150, 111, 136, 227, 157, 167, 106, 40, 219, 22, 244, 152, 202, 21, + 86, 41, 103, 65, 120, 205, 183, 255, 44, 27, 94, 216, 200, 96, + 16, 191, 251, 10, 3, 114, 213, 1, 38, 236, 24, 185, 114, 68, + 128, 246, 182, 46, 57, 149, 219, 165, 173, 34, 245, 84, 67, 187, + 65, 26, 25, 179, 61, 24, 32, 27, 145, 195, 92, 93, 8, 142, + 150, 181, 188, 238, 23, 95, 237, 65, 133, 72, 132, 20, 123, 149, + 240, 219, 52, 115, 76, 228, 215, 146, 57, 117, 240, 226, 121, 113, + 45, 229, 64, 76, 53, 59, 44, 170, 13, 81, 29, 16, 176, 223, + 33, 96, 135, 158, 163, 253, 37, 72, 125, 110, 112, 151, 215, 8, + 224, 208, 220, 129, 87, 183, 75, 67, 45, 33, 141, 50, 217, 168, + 7, 133, 187, 218, 197, 121, 129, 83, 51, 80, 64, 57, 121, 197, + 76, 34, 97, 16, 169, 17, 173, 208, 168, 217, 212, 221, 97, 147, + 169, 227, 17, 254, 128, 64, 199, 6, 86, 242, 107, 62, 187, 175, + 36, 54, 100, 68, 230, 88, 140, 138, 153, 219, 222, 253, 119, 50, + 163, 179, 117, 219, 27, 254, 6, 223, 33, 104, 101, 212, 141, 64, + 51, 255, 176, 177, 99, 37, 43, 163, 153, 252, 13, 58, 147, 100, + 254, 42, 68, 184, 169, 127, 40, 228, 132, 117, 138, 209, 103, 99, + 21, 142, 100, 142, 182, 242, 253, 12, 192, 110, 241, 109, 170, 48, + 123, 176, 151, 139, 249, 118, 190, 83, 161, 140, 110, 86, 238, 8, + 51, 246, 175, 149, 134, 84, 152, 36, 105, 129, 93, 166, 71, 93, + 196, 236, 133, 215, 244, 113, 178, 34, 65, 177, 125, 219, 26, 133, + 189, 118, 214, 127, 198, 138, 181, 83, 106, 6, 82, 72, 52, 193, + 36, 148, 36, 51, 165, 11, 225, 12, 167, 63, 103, 69, 153, 78, + 232, 215, 168, 220, 125, 183, 252, 85, 220, 179, 189, 19, 65, 85, + 63, 223, 100, 241, 188, 202, 165, 74, 197, 234, 173, 174, 148, 1, + 64, 143, 181, 141, 235, 101, 144, 154, 147, 43, 243, 78, 189, 74, + 229, 176, 255, 173, 105, 87, 118, 101, 207, 166, 149, 136, 244, 142, + 58, 177, 182, 197, 115, 108, 200, 89, 155, 19, 231, 130, 121, 50, + 240, 23, 16, 120, 73, 127, 7, 195, 56, 119, 193, 166, 51, 223, + 149, 154, 214, 61, 210, 176, 134, 182, 21, 218, 241, 68, 166, 231, + 222, 69, 70, 207, 143, 93, 226, 195, 228, 183, 251, 224, 244, 58, + 105, 51, 150, 171, 50, 195, 151, 243, 234, 232, 1, 101, 96, 130, + 176, 4, 194, 5, 255, 128, 45, 101, 225, 101, 0, 46, 43, 55, + 172, 173, 120, 193, 195, 76, 94, 116, 103, 74, 4, 163, 199, 99, + 26, 154, 233, 125, 224, 107, 214, 106, 192, 37, 95, 220, 158, 61, + 89, 33, 38, 89, 242, 184, 118, 245, 167, 50, 137, 243, 32, 89, + 20, 198, 79, 16, 253, 45, 255, 63, 93, 45, 137, 139, 138, 3, + 216, 55, 49, 142, 98, 76, 36, 55, 177, 232, 237, 105, 87, 180, + 154, 149, 251, 182, 136, 241, 165, 237, 100, 42, 130, 5, 161, 138, + 65, 140, 173, 254, 224, 237, 18, 246, 136, 233, 0, 120, 191, 217, + 47, 67, 173, 8, 9, 255, 119, 169, 237, 225, 104, 46, 1, 129, + 234, 145, 190, 66, 44, 11, 27, 170, 86, 139, 96, 29, 149, 120, + 205, 81, 48, 250, 55, 35, 98, 12, 97, 170, 40, 152, 253, 83, + 232, 157, 126, 192, 233, 249, 211, 5, 121, 178, 227, 22, 193, 8, + 119, 184, 255, 59, 196, 72, 180, 55, 177, 191, 25, 32, 226, 21, + 212, 218, 43, 91, 75, 181, 185, 204, 23, 184, 5, 149, 170, 221, + 154, 155, 212, 116, 159, 199, 175, 190, 132, 14, 55, 167, 212, 202, + 198, 32, 36, 229, 48, 29, 4, 233, 51, 212, 249, 191, 122, 170, + 162, 174, 130, 29, 11, 243, 249, 180, 158, 117, 255, 237, 137, 139, + 191, 203, 59, 179, 155, 228, 2, 47, 164, 34, 119, 252, 8, 175, + 168, 94, 207, 101, 81, 118, 98, 204, 15, 110, 35, 97, 157, 97, + 141, 185, 162, 2, 102, 238, 82, 81, 23, 133, 10, 234, 45, 88, + 183, 129, 14, 149, 173, 200, 193, 196, 73, 126, 226, 121, 34, 216, + 113, 65, 72, 153, 113, 252, 140, 235, 43, 246, 37, 152, 3, 177, + 34, 6, 245, 147, 226, 56, 252, 36, 87, 220, 24, 45, 3, 62, + 90, 87, 115, 167, 150, 215, 172, 1, 25, 114, 19, 75, 201, 197, + 9, 125, 175, 6, 179, 222, 229, 138, 125, 61, 6, 53, 18, 160, + 52, 101, 41, 191, 206, 205, 155, 199, 32, 87, 218, 237, 33, 210, + 34, 97, 2, 102, 19, 132, 31, 43, 110, 96, 91, 149, 188, 7, + 63, 209, 106, 141, 40, 121, 137, 96, 26, 74, 45, 90, 152, 110, + 234, 137, 221, 54, 163, 178, 234, 51, 110, 107, 179, 143, 32, 121, + 117, 182, 220, 47, 96, 196, 120, 110, 73, 96, 158, 80, 143, 44, + 143, 104, 208, 59, 97, 66, 215, 75, 202, 57, 23, 110, 159, 54, + 130, 226, 139, 151, 68, 25, 76, 60, 200, 67, 147, 235, 152, 26, + 10, 118, 116, 82, 70, 87, 208, 112, 12, 146, 38, 171, 93, 47, + 19, 13, 33, 149, 176, 116, 88, 83, 51, 65, 99, 209, 214, 11, + 23, 130, 81, 170, 230, 177, 160, 39, 164, 176, 230, 216, 135, 143, + 71, 56, 73, 69, 153, 78, 232, 215, 168, 220, 125, 183, 252, 85, + 220, 179, 189, 19, 65, 85, 63, 220, 219, 214, 232, 232, 177, 160, + 28, 157, 98, 32, 80, 197, 16, 62, 160, 61, 55, 24, 187, 231, + 80, 128, 246, 28, 15, 75, 26, 181, 87, 254, 101, 200, 87, 148, + 133, 19, 232, 222, 214, 163, 231, 179, 254, 156, 102, 75, 80, 65, + 26, 78, 97, 227, 70, 63, 212, 176, 58, 7, 136, 195, 4, 46, + 94, 119, 20, 231, 209, 66, 119, 55, 46, 21, 209, 154, 228, 251, + 134, 219, 194, 35, 17, 15, 180, 31, 138, 153, 114, 2, 100, 203, + 194, 253, 205, 147, 227, 134, 108, 150, 140, 107, 252, 2, 118, 191, + 91, 102, 23, 151, 99, 254, 232, 21, 71, 42, 192, 193, 118, 185, + 187, 159, 242, 102, 35, 105, 190, 10, 97, 56, 18, 113, 242, 12, + 40, 95, 56, 145, 114, 122, 214, 249, 223, 74, 15, 150, 36, 153, + 162, 120, 241, 181, 246, 96, 162, 105, 196, 246, 140, 236, 218, 180, + 119, 137, 208, 252, 179, 83, 72, 50, 81, 13, 13, 70, 21, 54, + 158, 181, 174, 11, 149, 52, 254, 205, 67, 153, 60, 203, 74, 209, + 125, 35, 46, 189, 214, 85, 119, 211, 118, 13, 31, 129, 146, 65, + 44, 117, 179, 228, 122, 16, 12, 124, 207, 4, 224, 159, 196, 146, + 2, 148, 210, 118, 68, 158, 3, 29, 6, 54, 12, 193, 23, 52, + 216, 204, 164, 27, 4, 137, 83, 102, 33, 115, 64, 74, 162, 5, + 132, 186, 225, 240, 222, 231, 199, 61, 33, 195, 153, 221, 77, 3, + 129, 147, 151, 69, 205, 249, 56, 79, 106, 22, 173, 31, 199, 225, + 39, 140, 240, 174, 50, 91, 83, 212, 69, 51, 238, 236, 161, 243, + 226, 137, 79, 14, 90, 127, 48, 228, 143, 100, 79, 123, 51, 243, + 16, 144, 113, 222, 213, 68, 45, 113, 189, 10, 36, 193, 78, 226, + 243, 78, 94, 159, 117, 188, 157, 149, 169, 192, 77, 241, 101, 175, + 105, 3, 103, 129, 167, 194, 123, 40, 94, 102, 192, 244, 241, 15, + 31, 12, 211, 91, 81, 148, 186, 27, 10, 216, 231, 57, 124, 143, + 113, 126, 245, 248, 138, 250, 96, 75, 87, 169, 136, 127, 18, 247, + 248, 154, 8, 145, 208, 247, 155, 21, 18, 82, 49, 202, 112, 38, + 196, 2, 106, 13, 150, 54, 236, 85, 131, 80, 203, 11, 171, 235, + 116, 175, 147, 11, 166, 147, 169, 153, 75, 93, 107, 137, 151, 67, + 15, 229, 176, 0, 97, 71, 135, 111, 71, 53, 67, 24, 218, 255, + 25, 79, 181, 221, 41, 207, 73, 207, 4, 110, 117, 170, 144, 84, + 133, 19, 78, 28, 179, 252, 239, 26, 87, 154, 149, 87, 105, 46, + 183, 57, 204, 62, 175, 142, 175, 254, 232, 25, 194, 96, 209, 236, + 219, 57, 95, 21, 3, 36, 188, 200, 142, 101, 135, 153, 76, 3, + 23, 76, 175, 95, 173, 213, 162, 242, 98, 91, 35, 218, 18, 226, + 212, 210, 141, 2, 35, 11, 187, 113, 68, 208, 42, 59, 135, 179, + 219, 42, 198, 124, 127, 103, 57, 223, 69, 221, 68, 135, 183, 187, + 232, 117, 9, 34, 17, 122, 127, 64, 4, 183, 134, 243, 191, 162, + 47, 234, 214, 79, 157, 68, 194, 90, 116, 225, 161, 215, 239, 170, + 96, 21, 166, 91, 86, 93, 143, 91, 10, 128, 51, 25, 252, 116, + 138, 57, 122, 52, 196, 93, 228, 104, 75, 189, 106, 211, 68, 86, + 224, 96, 86, 185, 153, 215, 150, 116, 197, 200, 2, 107, 21, 203, + 156, 92, 88, 156, 250, 72, 15, 244, 170, 222, 1, 245, 1, 114, + 55, 130, 93, 167, 167, 183, 204, 96, 216, 112, 242, 155, 73, 242, + 37, 148, 187, 185, 221, 147, 249, 233, 211, 108, 153, 10, 48, 251, + 65, 122, 107, 80, 194, 223, 40, 112, 172, 175, 228, 104, 189, 104, + 121, 223, 225, 20, 222, 211, 116, 139, 142, 198, 181, 68, 94, 30, + 163, 210, 38, 252, 139, 173, 19, 36, 161, 171, 125, 239, 202, 50, + 202, 61, 51, 47, 136, 14, 242, 59, 150, 129, 145, 231, 183, 243, + 73, 108, 188, 43, 223, 98, 129, 115, 5, 140, 243, 117, 14, 207, + 73, 62, 169, 143, 251, 202, 129, 146, 13, 102, 7, 194, 217, 101, + 174, 92, 252, 231, 57, 173, 118, 114, 50, 233, 7, 43, 205, 216, + 136, 86, 149, 77, 35, 231, 33, 19, 39, 205, 9, 123, 232, 29, + 11, 251, 186, 8, 97, 135, 34, 112, 255, 48, 13, 250, 72, 247, + 208, 82, 14, 207, 222, 129, 249, 75, 114, 148, 201, 39, 97, 55, + 65, 250, 232, 16, 207, 104, 104, 247, 64, 106, 196, 41, 162, 151, + 59, 5, 182, 220, 201, 31, 171, 71, 203, 167, 144, 5, 244, 8, + 244, 96, 161, 189, 86, 9, 6, 81, 33, 214, 147, 110, 6, 58, + 134, 213, 102, 149, 19, 236, 14, 88, 172, 101, 154, 229, 54, 132, + 41, 87, 194, 182, 85, 177, 210, 217, 94, 56, 208, 157, 49, 169, + 191, 144, 236, 168, 45, 243, 3, 164, 9, 159, 231, 141, 9, 88, + 143, 160, 214, 38, 69, 125, 186, 230, 68, 160, 13, 26, 128, 120, + 149, 117, 84, 199, 58, 8, 97, 196, 199, 135, 27, 242, 109, 241, + 210, 159, 192, 140, 227, 228, 215, 127, 153, 69, 84, 174, 103, 72, + 167, 242, 105, 127, 61, 98, 65, 225, 101, 49, 211, 160, 62, 242, + 47, 65, 238, 216, 22, 156, 14, 234, 208, 182, 135, 250, 200, 9, + 209, 151, 129, 55, 103, 169, 116, 30, 250, 188, 35, 215, 184, 163, + 129, 160, 197, 120, 22, 46, 115, 46, 194, 161, 89, 170, 75, 8, + 233, 38, 53, 148, 48, 207, 89, 1, 78, 79, 225, 186, 157, 43, + 64, 248, 126, 227, 112, 223, 143, 187, 255, 115, 193, 132, 105, 102, + 4, 4, 157, 71, 41, 188, 146, 146, 10, 214, 147, 19, 17, 150, + 176, 201, 230, 58, 232, 92, 22, 37, 159, 59, 37, 152, 77, 181, + 157, 2, 45, 24, 202, 106, 34, 230, 113, 10, 193, 192, 74, 120, + 207, 136, 129, 172, 79, 215, 5, 226, 127, 129, 148, 249, 98, 86, + 237, 255, 245, 22, 128, 51, 136, 31, 70, 248, 254, 133, 186, 93, + 35, 155, 52, 28, 72, 66, 111, 182, 20, 242, 67, 151, 60, 108, + 145, 157, 157, 30, 121, 46, 17, 69, 35, 163, 75, 171, 98, 198, + 169, 235, 106, 11, 36, 136, 32, 144, 185, 185, 6, 109, 0, 137, + 120, 65, 20, 67, 82, 56, 148, 119, 85, 166, 159, 52, 166, 235, + 245, 246, 78, 248, 236, 0, 115, 17, 122, 111, 2, 249, 58, 93, + 117, 53, 103, 49, 6, 65, 22, 45, 59, 18, 106, 91, 29, 67, + 96, 253, 75, 159, 229, 229, 42, 175, 79, 52, 242, 83, 252, 165, + 204, 221, 207, 104, 150, 102, 81, 115, 41, 142, 41, 210, 99, 199, + 119, 3, 135, 249, 217, 124, 53, 71, 130, 200, 190, 190, 185, 163, + 36, 146, 20, 192, 56, 50, 247, 219, 253, 179, 86, 121, 90, 207, + 215, 181, 42, 194, 110, 165, 131, 74, 35, 245, 78, 138, 85, 106, + 126, 212, 130, 66, 134, 80, 133, 109, 54, 255, 94, 0, 170, 185, + 16, 145, 27, 54, 181, 181, 141, 38, 215, 36, 125, 53, 48, 11, + 192, 94, 79, 5, 175, 112, 47, 47, 183, 52, 211, 161, 130, 117, + 81, 202, 66, 87, 77, 145, 86, 109, 221, 174, 216, 223, 43, 72, + 56, 197, 123, 28, 100, 80, 59, 216, 93, 165, 155, 5, 219, 70, + 232, 61, 45, 180, 138, 171, 100, 188, 92, 232, 55, 147, 161, 164, + 40, 133, 70, 155, 142, 212, 243, 131, 8, 138, 1, 226, 31, 108, + 24, 221, 189, 186, 23, 118, 146, 217, 41, 253, 59, 87, 191, 164, + 55, 70, 74, 146, 215, 233, 239, 242, 174, 226, 51, 186, 238, 115, + 63, 194, 166, 180, 3, 193, 255, 103, 37, 87, 119, 145, 123, 159, + 109, 115, 109, 82, 206, 93, 48, 231, 195, 58, 127, 72, 220, 255, + 107, 72, 16, 67, 151, 11, 253, 31, 249, 61, 169, 7, 148, 0, + 183, 99, 81, 163, 55, 87, 245, 218, 250, 66, 73, 91, 233, 30, + 233, 234, 18, 180, 206, 227, 190, 50, 166, 229, 36, 221, 23, 67, + 148, 190, 175, 14, 183, 245, 80, 172, 220, 53, 13, 154, 18, 107, + 6, 64, 215, 19, 48, 95, 183, 13, 145, 245, 102, 204, 246, 125, + 136, 3, 237, 94, 99, 160, 31, 122, 36, 115, 212, 120, 244, 26, + 32, 130, 225, 153, 61, 55, 97, 195, 204, 36, 34, 124, 103, 49, + 161, 183, 102, 26, 153, 227, 189, 86, 235, 129, 167, 154, 59, 111, + 51, 107, 17, 4, 66, 164, 117, 212, 123, 33, 189, 189, 42, 36, + 70, 202, 135, 247, 207, 182, 167, 15, 96, 115, 206, 90, 203, 145, + 238, 52, 149, 160, 124, 191, 27, 238, 145, 73, 145, 99, 56, 232, + 6, 169, 91, 156, 250, 129, 98, 19, 164, 177, 28, 196, 215, 178, + 87, 200, 213, 62, 214, 123, 186, 236, 237, 138, 3, 19, 243, 57, + 254, 81, 17, 5, 20, 61, 114, 193, 75, 79, 39, 49, 93, 206, + 189, 44, 219, 190, 141, 178, 82, 246, 93, 178, 150, 248, 185, 200, + 92, 164, 28, 15, 16, 96, 155, 4, 23, 106, 204, 148, 12, 221, + 49, 78, 92, 33, 200, 194, 150, 186, 35, 144, 145, 179, 15, 174, + 67, 165, 189, 60, 138, 163, 5, 59, 154, 11, 115, 60, 223, 76, + 42, 1, 98, 236, 62, 162, 62, 10, 14, 202, 162, 215, 220, 140, + 64, 255, 204, 177, 44, 155, 92, 79, 91, 92, 166, 248, 153, 89, + 242, 116, 53, 50, 11, 170, 47, 19, 173, 61, 77, 75, 162, 41, + 168, 136, 96, 82, 108, 162, 169, 145, 77, 103, 19, 110, 100, 7, + 90, 138, 47, 55, 37, 107, 213, 105, 178, 186, 199, 129, 236, 46, + 71, 49, 251, 143, 30, 146, 233, 225, 8, 214, 28, 48, 208, 97, + 228, 218, 252, 185, 180, 70, 158, 89, 235, 66, 250, 27, 245, 173, + 93, 3, 137, 121, 184, 237, 161, 82, 217, 246, 201, 46, 149, 24, + 172, 19, 181, 150, 29, 197, 223, 130, 179, 249, 74, 2, 19, 50, + 18, 206, 95, 246, 0, 102, 17, 187, 174, 231, 148, 0, 15, 97, + 39, 49, 64, 158, 231, 240, 178, 118, 19, 63, 8, 220, 193, 104, + 185, 125, 64, 71, 106, 115, 168, 142, 51, 226, 203, 237, 174, 206, + 74, 73, 245, 99, 48, 96, 93, 253, 226, 100, 122, 215, 202, 78, + 207, 221, 205, 5, 84, 64, 48, 243, 101, 109, 141, 153, 205, 143, + 56, 146, 59, 87, 37, 101, 110, 187, 107, 95, 116, 201, 79, 38, + 240, 45, 122, 172, 114, 223, 242, 122, 164, 195, 23, 77, 210, 247, + 94, 89, 120, 147, 247, 249, 219, 120, 109, 126, 112, 228, 186, 241, + 172, 241, 42, 172, 242, 211, 23, 219, 52, 2, 125, 103, 151, 87, + 133, 100, 105, 246, 21, 235, 211, 5, 130, 91, 165, 71, 195, 156, + 43, 231, 65, 98, 7, 44, 97, 125, 123, 100, 128, 92, 221, 37, + 203, 192, 98, 50, 7, 93, 85, 15, 190, 78, 68, 126, 103, 166, + 143, 200, 150, 135, 188, 138, 20, 6, 10, 126, 9, 58, 45, 35, + 145, 95, 231, 181, 129, 181, 0, 54, 80, 5, 145, 147, 45, 31, + 153, 211, 226, 211, 173, 7, 55, 176, 108, 51, 247, 19, 3, 78, + 7, 65, 67, 186, 153, 161, 127, 192, 87, 247, 46, 62, 159, 28, + 158, 233, 121, 155, 47, 79, 75, 137, 164, 113, 197, 1, 98, 251, + 98, 218, 175, 180, 39, 148, 4, 77, 214, 61, 202, 245, 207, 72, + 70, 36, 54, 169, 164, 253, 63, 69, 113, 159, 235, 126, 198, 81, + 238, 110, 123, 171, 108, 221, 137, 155, 21, 4, 41, 148, 240, 195, + 33, 8, 239, 142, 115, 201, 171, 91, 111, 120, 91, 44, 149, 55, + 168, 114, 38, 188, 50, 114, 146, 70, 129, 171, 10, 225, 14, 174, + 160, 167, 220, 188, 115, 100, 77, 48, 62, 246, 190, 23, 131, 202, + 70, 238, 156, 119, 138, 53, 180, 205, 196, 180, 242, 246, 25, 15, + 134, 104, 159, 217, 166, 230, 142, 123, 115, 10, 207, 104, 239, 92, + 215, 135, 223, 76, 105, 253, 65, 243, 51, 159, 179, 74, 29, 242, + 84, 185, 66, 239, 146, 10, 163, 190, 17, 187, 233, 27, 197, 82, + 44, 105, 238, 210, 113, 106, 227, 207, 99, 47, 54, 30, 58, 104, + 22, 178, 53, 106, 30, 143, 72, 164, 98, 142, 195, 149, 206, 120, + 101, 47, 225, 201, 209, 187, 103, 200, 79, 35, 36, 135, 205, 221, + 88, 177, 158, 185, 240, 44, 67, 222, 111, 12, 167, 67, 210, 24, + 230, 188, 168, 182, 154, 48, 215, 114, 39, 108, 51, 125, 115, 47, + 100, 116, 122, 79, 234, 212, 214, 186, 20, 99, 215, 117, 167, 208, + 55, 55, 90, 114, 170, 176, 223, 66, 15, 125, 24, 196, 251, 161, + 72, 203, 4, 56, 28, 223, 134, 199, 198, 24, 37, 23, 191, 148, + 205, 10, 137, 199, 181, 122, 114, 56, 243, 124, 228, 56, 154, 236, + 206, 141, 84, 68, 181, 48, 224, 109, 142, 137, 218, 209, 107, 255, + 69, 236, 221, 138, 119, 75, 28, 233, 209, 251, 110, 181, 222, 246, + 90, 8, 151, 154, 90, 155, 180, 131, 129, 97, 174, 225, 17, 231, + 81, 110, 136, 46, 56, 237, 54, 95, 196, 224, 143, 213, 241, 23, + 237, 194, 159, 65, 9, 148, 38, 35, 132, 41, 180, 14, 217, 238, + 211, 72, 101, 167, 254, 35, 114, 178, 254, 134, 142, 144, 89, 142, + 17, 179, 119, 85, 161, 70, 216, 189, 40, 95, 49, 100, 222, 225, + 135, 223, 56, 228, 172, 233, 27, 161, 155, 23, 224, 207, 74, 58, + 96, 195, 160, 14, 37, 166, 209, 136, 251, 132, 255, 58, 132, 199, + 224, 240, 65, 95, 44, 108, 203, 201, 251, 34, 185, 39, 150, 75, + 45, 173, 182, 159, 133, 11, 33, 101, 243, 67, 88, 59, 97, 32, + 132, 241, 7, 144, 117, 75, 65, 129, 128, 119, 47, 247, 137, 233, + 107, 92, 162, 180, 161, 112, 174, 239, 201, 248, 233, 239, 71, 229, + 115, 233, 124, 67, 1, 65, 12, 213, 238, 79, 232, 237, 79, 230, + 230, 142, 119, 33, 57, 70, 144, 0, 251, 142, 78, 56, 95, 24, + 128, 235, 174, 106, 213, 161, 136, 96, 129, 184, 210, 76, 168, 136, + 101, 19, 142, 201, 57, 88, 205, 111, 68, 167, 96, 8, 52, 212, + 120, 90, 131, 130, 200, 191, 49, 91, 203, 207, 229, 236, 135, 51, + 170, 211, 95, 130, 20, 30, 69, 190, 247, 74, 239, 103, 39, 9, + 71, 221, 20, 187, 89, 140, 165, 217, 33, 107, 189, 127, 164, 225, + 201, 81, 78, 131, 193, 4, 42, 108, 49, 35, 193, 241, 4, 158, + 184, 156, 46, 182, 146, 108, 191, 157, 133, 82, 199, 207, 58, 122, + 248, 240, 250, 68, 197, 58, 238, 1, 27, 173, 104, 194, 155, 123, + 114, 92, 100, 7, 138, 97, 134, 27, 96, 255, 83, 202, 28, 221, + 169, 202, 239, 251, 234, 164, 35, 177, 125, 66, 2, 182, 204, 204, + 94, 251, 31, 44, 145, 8, 6, 67, 221, 250, 111, 39, 247, 99, + 102, 209, 84, 85, 63, 63, 249, 204, 212, 6, 106, 11, 214, 60, + 100, 127, 12, 215, 12, 128, 45, 66, 34, 209, 222, 198, 64, 178, + 15, 70, 235, 134, 92, 123, 187, 158, 106, 90, 48, 51, 203, 46, + 29, 187, 254, 142, 245, 104, 76, 250, 220, 44, 223, 249, 142, 105, + 159, 116, 54, 80, 34, 26, 51, 42, 76, 120, 31, 24, 89, 98, + 202, 227, 52, 91, 39, 158, 75, 225, 54, 21, 219, 56, 20, 246, + 139, 153, 142, 247, 38, 71, 116, 12, 207, 141, 177, 242, 34, 216, + 32, 127, 205, 6, 173, 237, 180, 0, 245, 1, 203, 45, 8, 127, + 73, 13, 35, 159, 29, 100, 135, 112, 3, 51, 24, 169, 135, 172, + 227, 195, 11, 127, 110, 53, 79, 18, 37, 134, 234, 102, 96, 147, + 202, 182, 181, 192, 233, 167, 181, 237, 251, 186, 118, 184, 19, 86, + 204, 226, 152, 121, 23, 241, 125, 153, 212, 180, 124, 122, 6, 224, + 90, 3, 65, 125, 192, 16, 208, 137, 99, 144, 120, 162, 147, 87, + 138, 80, 0, 193, 98, 73, 35, 245, 20, 17, 246, 84, 119, 170, + 144, 100, 183, 80, 203, 189, 31, 121, 233, 45, 54, 34, 115, 184, + 12, 33, 196, 44, 88, 102, 86, 175, 94, 104, 195, 97, 227, 243, + 129, 210, 207, 85, 8, 190, 229, 91, 74, 92, 112, 83, 117, 206, + 16, 235, 89, 240, 229, 25, 186, 220, 79, 192, 175, 194, 42, 30, + 163, 16, 252, 0, 161, 202, 61, 6, 125, 119, 189, 232, 98, 214, + 161, 167, 133, 170, 194, 165, 57, 149, 177, 55, 129, 72, 84, 190, + 138, 1, 122, 239, 65, 54, 76, 248, 188, 94, 202, 9, 180, 59, + 255, 93, 252, 244, 20, 198, 242, 242, 29, 47, 119, 242, 192, 57, + 35, 17, 69, 59, 62, 242, 41, 72, 204, 161, 36, 22, 88, 154, + 220, 184, 4, 199, 182, 143, 18, 199, 146, 130, 70, 163, 14, 24, + 88, 164, 243, 190, 150, 101, 221, 220, 109, 27, 88, 123, 215, 231, + 27, 169, 31, 50, 192, 145, 205, 60, 32, 240, 16, 60, 154, 255, + 108, 169, 132, 91, 31, 201, 137, 112, 225, 148, 72, 198, 187, 51, + 246, 233, 186, 183, 51, 246, 42, 245, 35, 99, 28, 161, 219, 99, + 141, 252, 197, 55, 227, 10, 116, 131, 148, 195, 234, 159, 70, 4, + 58, 100, 45, 102, 164, 248, 178, 181, 10, 13, 105, 208, 67, 169, + 146, 197, 47, 168, 109, 167, 201, 79, 52, 17, 89, 60, 78, 164, + 245, 104, 184, 141, 102, 148, 204, 242, 52, 100, 36, 0, 83, 220, + 56, 111, 254, 178, 118, 228, 228, 243, 223, 245, 207, 73, 46, 103, + 111, 190, 134, 228, 196, 15, 121, 165, 49, 183, 119, 44, 106, 168, + 180, 10, 33, 197, 179, 104, 146, 123, 10, 129, 88, 249, 56, 243, + 34, 234, 89, 137, 187, 191, 145, 62, 149, 61, 111, 49, 78, 198, + 182, 226, 35, 124, 109, 129, 56, 30, 197, 187, 169, 33, 224, 129, + 202, 151, 155, 105, 39, 10, 51, 168, 238, 139, 250, 127, 185, 198, + 232, 81, 125, 102, 252, 163, 140, 109, 87, 6, 111, 148, 179, 26, + 216, 201, 147, 245, 214, 225, 65, 160, 45, 100, 217, 222, 199, 85, + 115, 151, 170, 55, 235, 240, 129, 153, 91, 49, 13, 78, 114, 176, + 250, 133, 37, 56, 221, 199, 187, 210, 156, 170, 49, 248, 20, 11, + 180, 123, 176, 246, 222, 80, 247, 15, 252, 91, 243, 4, 167, 251, + 125, 228, 235, 126, 68, 154, 121, 22, 111, 3, 45, 38, 185, 62, + 75, 142, 199, 182, 87, 127, 11, 116, 168, 208, 223, 237, 170, 217, + 14, 216, 47, 165, 5, 166, 226, 222, 133, 144, 17, 52, 52, 54, + 56, 4, 18, 121, 203, 124, 167, 40, 199, 161, 248, 115, 227, 94, + 24, 5, 23, 76, 90, 84, 15, 152, 172, 222, 190, 169, 209, 163, + 166, 161, 250, 78, 49, 31, 226, 194, 23, 71, 42, 248, 122, 139, + 230, 59, 183, 205, 210, 46, 211, 211, 81, 130, 88, 143, 126, 127, + 114, 7, 32, 253, 253, 163, 208, 61, 173, 24, 7, 154, 240, 137, + 159, 235, 206, 66, 188, 121, 11, 107, 170, 129, 61, 34, 170, 217, + 161, 185, 228, 29, 243, 203, 211, 90, 255, 78, 31, 236, 131, 14, + 112, 118, 88, 20, 211, 203, 25, 59, 120, 40, 147, 140, 164, 12, + 26, 229, 10, 187, 0, 230, 115, 185, 107, 164, 27, 104, 198, 50, + 242, 187, 18, 104, 77, 221, 222, 186, 123, 198, 206, 35, 16, 21, + 220, 76, 176, 160, 69, 234, 84, 73, 4, 40, 210, 211, 135, 47, + 155, 17, 188, 165, 224, 101, 76, 123, 41, 116, 0, 92, 227, 90, + 109, 213, 250, 254, 104, 103, 53, 206, 162, 195, 253, 157, 223, 179, + 40, 244, 0, 78, 172, 196, 119, 157, 115, 63, 63, 87, 96, 226, + 113, 205, 84, 54, 240, 54, 20, 178, 13, 182, 208, 142, 149, 67, + 60, 136, 47, 243, 172, 132, 215, 93, 119, 53, 137, 75, 254, 44, + 106, 0, 243, 223, 140, 254, 88, 47, 220, 169, 232, 89, 201, 234, + 84, 111, 57, 197, 237, 26, 135, 81, 111, 105, 252, 42, 42, 148, + 177, 211, 33, 109, 170, 65, 30, 218, 201, 68, 49, 4, 32, 254, + 186, 233, 53, 24, 53, 213, 47, 44, 217, 136, 1, 67, 221, 11, + 233, 83, 171, 52, 27, 114, 15, 97, 189, 74, 106, 13, 193, 125, + 156, 224, 57, 100, 56, 182, 79, 96, 186, 125, 44, 12, 223, 89, + 237, 233, 32, 209, 10, 152, 40, 227, 177, 64, 202, 33, 116, 149, + 85, 66, 79, 64, 207, 199, 247, 152, 139, 149, 11, 102, 197, 116, + 9, 43, 200, 57, 82, 171, 91, 112, 68, 213, 93, 91, 120, 214, + 175, 99, 177, 61, 52, 133, 225, 61, 179, 128, 171, 184, 96, 129, + 131, 4, 153, 70, 48, 126, 118, 193, 94, 209, 130, 66, 107, 89, + 88, 83, 27, 179, 196, 67, 214, 123, 34, 110, 26, 85, 187, 83, + 79, 143, 166, 211, 78, 17, 195, 45, 42, 225, 172, 89, 130, 206, + 146, 198, 41, 170, 245, 179, 106, 85, 123, 26, 219, 233, 73, 41, + 242, 7, 92, 56, 13, 32, 178, 208, 208, 65, 215, 159, 234, 116, + 197, 42, 39, 45, 231, 78, 5, 60, 154, 54, 168, 64, 25, 179, + 115, 175, 67, 247, 61, 128, 171, 118, 228, 31, 62, 51, 234, 207, + 116, 246, 27, 205, 21, 175, 175, 53, 14, 96, 61, 181, 254, 95, + 122, 95, 245, 79, 142, 62, 55, 12, 17, 219, 240, 88, 219, 184, + 211, 176, 215, 191, 222, 20, 49, 108, 141, 237, 214, 145, 84, 48, + 136, 247, 116, 131, 247, 46, 157, 222, 212, 13, 91, 41, 231, 102, + 24, 108, 125, 123, 217, 12, 180, 181, 203, 200, 92, 174, 181, 223, + 240, 252, 168, 210, 197, 132, 168, 225, 100, 184, 130, 97, 102, 168, + 29, 147, 21, 41, 80, 117, 179, 34, 80, 103, 163, 111, 16, 92, + 156, 239, 189, 107, 130, 58, 106, 126, 118, 204, 246, 35, 176, 37, + 128, 119, 123, 104, 166, 147, 173, 214, 207, 140, 190, 162, 228, 37, + 214, 31, 176, 3, 143, 90, 233, 168, 137, 85, 11, 64, 98, 175, + 160, 124, 64, 50, 243, 127, 173, 230, 177, 204, 195, 122, 4, 136, + 133, 228, 202, 2, 65, 124, 236, 234, 94, 202, 80, 254, 30, 163, + 93, 136, 110, 31, 12, 74, 141, 33, 31, 228, 128, 221, 10, 159, + 151, 70, 28, 115, 105, 162, 201, 8, 93, 165, 183, 76, 184, 30, + 154, 172, 190, 122, 17, 174, 153, 17, 4, 253, 97, 228, 55, 145, + 245, 254, 124, 51, 143, 38, 182, 0, 106, 4, 159, 206, 115, 34, + 176, 191, 140, 195, 215, 70, 16, 82, 44, 225, 121, 148, 246, 209, + 124, 87, 195, 80, 199, 242, 84, 0, 169, 126, 236, 153, 131, 210, + 203, 5, 153, 178, 222, 225, 83, 145, 213, 114, 205, 234, 47, 102, + 152, 110, 71, 6, 128, 26, 119, 3, 99, 248, 82, 197, 198, 161, + 227, 202, 14, 47, 65, 109, 46, 59, 17, 211, 139, 25, 44, 66, + 200, 59, 212, 183, 124, 247, 80, 163, 206, 222, 68, 43, 82, 94, + 11, 222, 43, 168, 157, 12, 71, 229, 91, 197, 186, 229, 185, 14, + 52, 116, 97, 151, 164, 211, 135, 120, 23, 227, 93, 38, 153, 68, + 240, 5, 111, 209, 83, 135, 118, 66, 97, 44, 73, 225, 69, 109, + 74, 162, 62, 57, 147, 128, 8, 84, 39, 226, 207, 224, 125, 210, + 233, 74, 22, 161, 0, 25, 201, 55, 89, 217, 195, 161, 2, 125, + 177, 249, 92, 76, 254, 96, 138, 207, 21, 101, 195, 31, 89, 42, + 209, 251, 152, 161, 18, 187, 14, 96, 109, 51, 192, 115, 155, 136, + 93, 130, 215, 176, 186, 150, 128, 73, 100, 112, 60, 114, 212, 181, + 123, 81, 4, 163, 222, 24, 68, 3, 33, 205, 184, 97, 167, 72, + 198, 91, 213, 150, 88, 11, 64, 201, 101, 69, 228, 73, 139, 214, + 5, 223, 80, 188, 211, 45, 88, 192, 195, 225, 233, 195, 119, 161, + 212, 142, 119, 89, 52, 96, 89, 156, 211, 22, 38, 177, 225, 162, + 182, 24, 187, 13, 106, 212, 17, 146, 172, 60, 103, 82, 154, 137, + 72, 1, 239, 50, 34, 145, 200, 128, 31, 66, 171, 252, 205, 85, + 73, 119, 210, 89, 32, 167, 208, 226, 222, 131, 222, 114, 108, 85, + 156, 197, 29, 114, 190, 75, 192, 83, 235, 75, 86, 76, 8, 153, + 48, 53, 48, 175, 70, 212, 193, 154, 137, 224, 253, 219, 87, 9, + 229, 99, 7, 129, 208, 42, 57, 110, 80, 240, 65, 255, 2, 109, + 130, 50, 37, 54, 37, 38, 135, 216, 59, 223, 85, 202, 195, 112, + 220, 214, 247, 139, 30, 128, 243, 15, 19, 86, 199, 114, 15, 33, + 204, 194, 44, 114, 14, 139, 90, 152, 48, 191, 39, 248, 66, 87, + 197, 138, 76, 235, 210, 0, 225, 110, 23, 182, 181, 200, 151, 20, + 209, 160, 19, 187, 101, 254, 225, 203, 76, 149, 232, 167, 164, 156, + 117, 139, 106, 157, 57, 14, 247, 134, 106, 246, 199, 99, 22, 164, + 65, 237, 84, 107, 133, 130, 213, 155, 32, 175, 224, 34, 71, 214, + 221, 249, 3, 199, 181, 37, 15, 240, 187, 225, 134, 104, 139, 212, + 153, 248, 23, 131, 3, 166, 63, 128, 85, 194, 154, 230, 178, 51, + 51, 171, 202, 4, 188, 172, 238, 68, 20, 188, 217, 237, 44, 18, + 252, 176, 252, 48, 176, 131, 216, 247, 251, 90, 164, 27, 120, 239, + 240, 241, 216, 128, 255, 167, 167, 33, 45, 31, 90, 94, 35, 69, + 128, 12, 245, 167, 136, 100, 131, 197, 143, 21, 213, 152, 74, 142, + 31, 152, 123, 78, 234, 9, 218, 141, 11, 246, 26, 186, 158, 88, + 193, 132, 207, 0, 178, 210, 151, 2, 65, 92, 145, 192, 26, 82, + 6, 209, 18, 220, 58, 214, 7, 144, 253, 182, 107, 158, 13, 9, + 32, 247, 198, 248, 91, 99, 230, 227, 217, 118, 44, 145, 244, 83, + 75, 218, 196, 38, 7, 250, 150, 191, 99, 14, 216, 202, 73, 151, + 237, 3, 186, 75, 129, 217, 234, 84, 247, 4, 133, 190, 171, 190, + 52, 84, 255, 115, 80, 221, 86, 101, 176, 123, 160, 21, 240, 244, + 0, 101, 53, 142, 19, 164, 188, 217, 67, 40, 46, 208, 6, 89, + 18, 243, 114, 9, 1, 123, 160, 24, 178, 25, 87, 183, 239, 151, + 149, 235, 135, 195, 204, 246, 199, 180, 174, 75, 84, 41, 59, 1, + 136, 252, 148, 207, 219, 89, 99, 156, 22, 156, 249, 60, 57, 160, + 115, 220, 27, 228, 169, 213, 137, 49, 157, 59, 216, 149, 11, 117, + 221, 212, 90, 46, 43, 72, 28, 228, 24, 6, 52, 156, 204, 213, + 161, 219, 14, 2, 90, 200, 50, 151, 54, 156, 40, 33, 6, 114, + 60, 182, 57, 74, 75, 107, 189, 37, 130, 156, 61, 8, 171, 214, + 33, 20, 16, 251, 54, 97, 164, 227, 73, 16, 194, 38, 84, 123, + 238, 99, 251, 168, 251, 68, 175, 42, 5, 192, 4, 145, 138, 176, + 14, 211, 223, 61, 91, 6, 69, 129, 231, 178, 105, 247, 98, 77, + 64, 145, 237, 147, 217, 129, 8, 87, 68, 170, 43, 79, 156, 194, + 227, 115, 147, 202, 26, 104, 203, 54, 243, 164, 189, 82, 4, 160, + 235, 167, 223, 252, 125, 225, 44, 2, 165, 76, 211, 165, 242, 53, + 190, 41, 101, 106, 69, 226, 34, 143, 24, 61, 84, 124, 137, 98, + 9, 108, 224, 244, 164, 28, 22, 29, 120, 69, 239, 146, 221, 191, + 182, 88, 45, 169, 168, 232, 9, 65, 183, 25, 48, 220, 100, 23, + 68, 1, 65, 30, 58, 235, 115, 22, 27, 178, 224, 181, 143, 217, + 148, 42, 28, 122, 243, 221, 25, 142, 104, 154, 162, 34, 14, 242, + 243, 205, 231, 156, 77, 0, 63, 168, 97, 72, 217, 105, 180, 41, + 94, 127, 224, 41, 189, 57, 130, 201, 47, 152, 1, 150, 156, 184, + 161, 66, 75, 210, 44, 160, 162, 26, 129, 51, 95, 112, 134, 182, + 102, 7, 88, 172, 103, 131, 168, 152, 176, 162, 211, 20, 3, 191, + 204, 170, 121, 255, 214, 195, 203, 103, 27, 54, 247, 70, 201, 187, + 227, 37, 176, 222, 87, 218, 75, 150, 112, 172, 56, 114, 255, 2, + 237, 7, 75, 201, 230, 171, 4, 238, 137, 246, 241, 26, 189, 29, + 110, 91, 251, 25, 129, 49, 31, 27, 120, 231, 122, 231, 98, 16, + 106, 5, 114, 53, 102, 172, 53, 202, 106, 124, 61, 255, 164, 138, + 240, 1, 201, 49, 11, 20, 64, 227, 71, 79, 229, 119, 6, 20, + 52, 126, 173, 165, 151, 113, 112, 126, 139, 216, 96, 83, 224, 108, + 54, 176, 199, 105, 172, 107, 24, 177, 249, 103, 129, 98, 183, 91, + 106, 149, 104, 41, 43, 97, 93, 84, 107, 111, 181, 202, 197, 5, + 12, 142, 138, 230, 239, 210, 154, 189, 159, 52, 215, 156, 159, 169, + 124, 101, 101, 16, 144, 147, 38, 70, 81, 240, 70, 26, 209, 119, + 233, 235, 192, 143, 138, 10, 101, 240, 73, 60, 227, 195, 143, 193, + 132, 8, 102, 220, 251, 93, 144, 223, 80, 25, 234, 199, 168, 24, + 39, 109, 87, 207, 71, 218, 216, 149, 68, 113, 173, 162, 3, 22, + 246, 160, 64, 157, 9, 217, 171, 123, 101, 23, 124, 66, 120, 247, + 241, 189, 204, 126, 46, 203, 186, 207, 109, 236, 117, 18, 75, 181, + 220, 138, 255, 246, 90, 187, 98, 207, 78, 107, 58, 65, 131, 138, + 228, 33, 104, 91, 179, 238, 46, 76, 199, 188, 67, 84, 138, 243, + 81, 201, 17, 151, 162, 94, 119, 203, 124, 32, 136, 53, 23, 54, + 159, 1, 234, 87, 153, 4, 32, 169, 163, 10, 234, 42, 108, 162, + 103, 47, 122, 115, 145, 156, 187, 155, 226, 147, 51, 16, 47, 244, + 108, 228, 87, 181, 0, 5, 104, 136, 176, 210, 202, 12, 184, 203, + 142, 130, 145, 207, 125, 170, 93, 125, 184, 246, 102, 81, 195, 103, + 100, 64, 12, 157, 131, 49, 169, 49, 204, 167, 161, 196, 202, 171, + 88, 154, 175, 173, 236, 142, 224, 143, 171, 34, 38, 48, 250, 15, + 56, 5, 5, 115, 166, 173, 163, 97, 42, 156, 253, 150, 131, 227, + 176, 81, 244, 185, 120, 72, 146, 7, 162, 142, 254, 234, 121, 254, + 200, 204, 12, 11, 160, 62, 217, 46, 114, 9, 178, 160, 185, 224, + 157, 171, 40, 1, 187, 220, 106, 179, 224, 59, 21, 25, 192, 141, + 236, 206, 136, 67, 167, 168, 70, 200, 113, 43, 18, 184, 202, 161, + 69, 218, 77, 217, 62, 36, 30, 23, 102, 30, 35, 54, 249, 74, + 214, 80, 148, 48, 204, 235, 14, 251, 144, 90, 164, 202, 213, 43, + 8, 102, 118, 174, 118, 242, 125, 68, 145, 154, 248, 167, 6, 147, + 202, 182, 52, 206, 61, 162, 230, 246, 17, 240, 220, 24, 217, 77, + 197, 179, 125, 113, 164, 199, 187, 214, 179, 185, 14, 80, 130, 194, + 253, 124, 72, 29, 79, 123, 64, 229, 106, 174, 32, 197, 62, 14, + 120, 217, 78, 95, 211, 69, 165, 19, 150, 25, 202, 75, 72, 86, + 232, 186, 243, 149, 126, 24, 21, 251, 179, 207, 222, 168, 28, 5, + 216, 134, 204, 52, 215, 19, 94, 48, 242, 236, 2, 19, 49, 139, + 68, 151, 150, 103, 107, 90, 73, 94, 8, 133, 49, 83, 222, 164, + 195, 42, 146, 187, 230, 91, 93, 157, 185, 247, 76, 138, 168, 244, + 17, 3, 23, 90, 23, 104, 183, 187, 237, 187, 58, 235, 195, 72, + 180, 149, 238, 154, 78, 167, 215, 99, 196, 150, 225, 72, 33, 240, + 77, 171, 77, 253, 105, 209, 175, 214, 252, 102, 27, 219, 140, 126, + 206, 151, 124, 56, 69, 189, 180, 165, 210, 130, 228, 64, 48, 101, + 212, 199, 157, 18, 101, 236, 31, 140, 5, 239, 141, 213, 123, 1, + 57, 105, 145, 30, 16, 71, 217, 85, 150, 205, 218, 244, 176, 9, + 126, 201, 43, 16, 191, 153, 74, 49, 83, 133, 208, 176, 182, 231, + 245, 65, 93, 6, 55, 61, 25, 124, 43, 156, 201, 0, 235, 167, + 235, 32, 135, 56, 62, 142, 126, 34, 42, 116, 68, 144, 203, 84, + 213, 2, 204, 104, 70, 100, 104, 41, 170, 53, 39, 59, 249, 15, + 240, 13, 71, 8, 99, 251, 219, 63, 221, 233, 169, 138, 252, 216, + 166, 186, 24, 247, 234, 148, 18, 46, 30, 198, 65, 221, 26, 73, + 13, 11, 52, 122, 168, 234, 202, 37, 191, 39, 164, 146, 238, 77, + 114, 158, 188, 215, 182, 26, 141, 186, 91, 202, 45, 223, 152, 226, + 244, 238, 62, 251, 143, 94, 57, 113, 86, 101, 214, 199, 28, 74, + 10, 13, 48, 195, 66, 70, 143, 24, 28, 107, 151, 223, 206, 84, + 203, 153, 10, 221, 118, 88, 216, 107, 168, 213, 197, 6, 49, 34, + 187, 2, 117, 5, 44, 18, 62, 131, 121, 243, 188, 99, 248, 130, + 174, 213, 96, 142, 242, 137, 156, 242, 82, 52, 2, 65, 248, 140, + 214, 33, 104, 119, 242, 169, 213, 200, 232, 79, 39, 173, 61, 13, + 3, 9, 88, 235, 21, 19, 59, 61, 250, 107, 189, 202, 134, 121, + 152, 11, 145, 177, 195, 122, 201, 4, 242, 196, 97, 204, 234, 43, + 79, 181, 98, 235, 23, 138, 88, 130, 212, 23, 101, 42, 99, 234, + 228, 15, 40, 56, 119, 216, 110, 140, 212, 223, 55, 21, 128, 79, + 90, 97, 24, 104, 178, 188, 4, 35, 54, 247, 4, 232, 23, 210, + 66, 202, 56, 29, 243, 226, 133, 38, 146, 102, 131, 89, 42, 98, + 227, 201, 204, 21, 53, 247, 234, 224, 188, 211, 164, 55, 134, 173, + 23, 227, 171, 85, 138, 118, 105, 45, 97, 32, 173, 189, 237, 67, + 24, 13, 213, 170, 203, 249, 153, 176, 170, 107, 111, 235, 223, 109, + 245, 200, 219, 213, 189, 160, 254, 17, 48, 20, 195, 124, 189, 39, + 60, 29, 125, 53, 195, 255, 163, 124, 188, 199, 188, 151, 119, 103, + 104, 37, 132, 63, 15, 205, 248, 71, 60, 172, 229, 139, 234, 194, + 209, 46, 255, 145, 145, 19, 10, 159, 160, 204, 2, 117, 19, 132, + 78, 69, 176, 155, 242, 87, 73, 91, 159, 245, 224, 207, 176, 248, + 254, 11, 187, 56, 105, 76, 93, 233, 177, 105, 39, 170, 26, 124, + 21, 126, 90, 213, 234, 149, 62, 242, 3, 227, 66, 36, 157, 56, + 84, 72, 100, 50, 78, 107, 107, 188, 181, 37, 53, 72, 52, 44, + 156, 71, 142, 14, 159, 151, 2, 227, 196, 163, 121, 206, 181, 33, + 60, 156, 150, 69, 144, 208, 14, 0, 85, 234, 57, 136, 99, 40, + 3, 29, 43, 193, 91, 88, 24, 41, 142, 248, 101, 20, 153, 151, + 55, 198, 107, 49, 54, 59, 221, 106, 126, 199, 194, 233, 197, 64, + 152, 132, 240, 67, 120, 197, 148, 170, 89, 53, 170, 153, 171, 192, + 123, 232, 241, 43, 185, 112, 190, 84, 131, 190, 24, 133, 144, 142, + 27, 203, 217, 82, 251, 230, 101, 241, 86, 139, 221, 89, 84, 18, + 107, 216, 29, 253, 69, 33, 155, 109, 248, 41, 27, 15, 0, 42, + 9, 214, 171, 239, 71, 117, 239, 175, 83, 129, 28, 204, 223, 179, + 130, 131, 90, 95, 26, 76, 167, 132, 183, 106, 21, 23, 253, 2, + 125, 62, 51, 75, 106, 227, 118, 72, 253, 30, 156, 178, 154, 129, + 88, 39, 210, 137, 6, 57, 142, 160, 100, 188, 76, 148, 209, 86, + 147, 110, 150, 204, 96, 84, 205, 28, 92, 166, 85, 142, 46, 17, + 81, 102, 186, 54, 242, 28, 221, 251, 169, 48, 214, 25, 58, 16, + 242, 211, 207, 152, 222, 200, 163, 43, 106, 156, 133, 99, 170, 154, + 218, 64, 90, 232, 71, 111, 220, 28, 248, 26, 233, 152, 88, 91, + 142, 136, 240, 143, 150, 46, 117, 125, 74, 93, 98, 250, 22, 42, + 141, 169, 248, 181, 248, 98, 143, 209, 198, 239, 192, 171, 231, 69, + 254, 198, 16, 96, 129, 45, 120, 139, 223, 138, 114, 197, 3, 21, + 154, 104, 141, 78, 27, 177, 6, 121, 211, 201, 236, 123, 207, 41, + 116, 94, 170, 245, 100, 184, 98, 214, 107, 70, 151, 59, 114, 181, + 103, 208, 155, 45, 56, 151, 112, 172, 182, 82, 82, 161, 234, 51, + 105, 144, 123, 205, 167, 193, 0, 69, 41, 60, 34, 33, 242, 135, + 220, 177, 103, 188, 63, 23, 197, 182, 210, 135, 46, 15, 100, 251, + 137, 188, 70, 234, 24, 33, 245, 61, 29, 124, 207, 177, 134, 105, + 109, 181, 62, 209, 235, 253, 249, 101, 164, 184, 80, 3, 84, 32, + 182, 121, 72, 172, 199, 172, 131, 50, 142, 216, 19, 207, 202, 152, + 68, 148, 213, 253, 209, 105, 196, 47, 204, 177, 210, 133, 145, 140, + 138, 12, 140, 151, 31, 41, 83, 243, 41, 48, 224, 15, 111, 67, + 78, 47, 78, 160, 248, 232, 200, 150, 201, 229, 123, 88, 241, 52, + 150, 30, 206, 229, 184, 250, 154, 156, 13, 76, 125, 224, 243, 155, + 32, 23, 130, 13, 122, 216, 56, 68, 79, 230, 226, 62, 254, 196, + 158, 212, 212, 130, 183, 48, 222, 113, 99, 200, 141, 89, 75, 146, + 214, 129, 148, 229, 18, 159, 236, 34, 210, 44, 251, 27, 72, 225, + 205, 211, 134, 183, 70, 13, 178, 115, 247, 157, 30, 180, 207, 87, + 72, 66, 22, 127, 239, 250, 76, 169, 81, 158, 193, 47, 203, 86, + 148, 125, 95, 242, 159, 188, 59, 26, 82, 40, 241, 136, 22, 1, + 239, 35, 65, 157, 214, 67, 191, 164, 125, 87, 74, 122, 221, 145, + 255, 66, 73, 58, 48, 7, 218, 247, 204, 197, 245, 53, 240, 79, + 88, 139, 36, 249, 129, 108, 223, 135, 80, 190, 41, 81, 238, 25, + 14, 250, 36, 6, 253, 8, 83, 59, 14, 118, 3, 111, 48, 80, + 106, 230, 53, 152, 221, 226, 216, 186, 49, 29, 123, 80, 207, 210, + 19, 3, 210, 77, 178, 228, 223, 51, 192, 130, 95, 129, 216, 64, + 9, 150, 191, 227, 172, 35, 81, 50, 217, 255, 92, 246, 116, 175, + 243, 23, 176, 161, 18, 152, 61, 215, 95, 188, 21, 247, 185, 193, + 249, 133, 9, 56, 218, 176, 174, 235, 30, 67, 253, 26, 94, 210, + 136, 245, 166, 188, 223, 99, 180, 217, 165, 193, 92, 26, 88, 72, + 103, 118, 176, 19, 91, 117, 78, 46, 44, 153, 249, 157, 182, 247, + 111, 23, 58, 78, 146, 89, 75, 10, 77, 40, 137, 254, 59, 43, + 94, 144, 125, 9, 43, 180, 174, 231, 219, 142, 106, 242, 237, 185, + 7, 53, 206, 54, 164, 217, 228, 3, 46, 108, 0, 82, 113, 153, + 1, 113, 196, 148, 33, 154, 140, 217, 161, 176, 45, 123, 65, 124, + 35, 47, 14, 248, 81, 198, 192, 207, 207, 172, 19, 33, 210, 222, + 25, 38, 211, 35, 40, 254, 253, 32, 152, 136, 219, 59, 65, 104, + 119, 166, 121, 160, 210, 210, 152, 58, 37, 255, 202, 163, 73, 150, + 57, 207, 71, 34, 77, 197, 7, 105, 106, 209, 21, 53, 90, 239, + 30, 226, 103, 45, 52, 205, 34, 133, 174, 171, 37, 170, 224, 109, + 7, 183, 182, 14, 75, 114, 44, 116, 218, 103, 208, 133, 103, 157, + 93, 232, 149, 159, 82, 141, 0, 35, 148, 201, 235, 201, 100, 213, + 71, 143, 51, 112, 30, 219, 72, 37, 26, 147, 18, 41, 99, 227, + 31, 35, 87, 0, 112, 109, 79, 37, 68, 44, 226, 58, 184, 169, + 66, 116, 181, 205, 250, 90, 45, 85, 144, 112, 174, 167, 218, 131, + 44, 214, 49, 40, 48, 152, 23, 129, 57, 7, 209, 187, 146, 255, + 135, 224, 243, 104, 44, 56, 2, 250, 82, 177, 203, 101, 130, 130, + 49, 226, 103, 253, 217, 180, 181, 135, 85, 37, 102, 171, 214, 63, + 117, 188, 60, 26, 8, 81, 98, 59, 104, 74, 204, 235, 77, 234, + 64, 122, 151, 142, 198, 88, 217, 118, 134, 145, 130, 72, 85, 203, + 176, 154, 179, 36, 114, 33, 250, 93, 192, 28, 41, 53, 231, 123, + 63, 111, 188, 12, 143, 233, 105, 95, 26, 236, 252, 68, 248, 28, + 170, 178, 124, 88, 32, 206, 62, 230, 61, 160, 59, 195, 172, 153, + 212, 135, 59, 161, 55, 3, 129, 219, 101, 190, 30, 64, 172, 184, + 124, 25, 55, 220, 206, 206, 38, 30, 107, 204, 51, 70, 89, 207, + 167, 240, 230, 200, 68, 160, 225, 34, 45, 184, 122, 225, 245, 175, + 6, 184, 254, 161, 55, 139, 111, 20, 192, 123, 127, 20, 200, 14, + 129, 184, 30, 244, 51, 103, 207, 5, 255, 111, 1, 47, 81, 102, + 36, 219, 52, 227, 62, 179, 207, 146, 42, 171, 106, 202, 199, 10, + 225, 84, 195, 38, 235, 166, 78, 136, 231, 114, 221, 110, 166, 228, + 141, 113, 177, 84, 1, 162, 18, 55, 73, 188, 67, 0, 170, 120, + 253, 203, 59, 104, 255, 109, 142, 50, 81, 207, 39, 63, 142, 115, + 80, 180, 213, 123, 75, 59, 177, 176, 33, 192, 103, 76, 27, 7, + 67, 114, 238, 68, 57, 96, 94, 254, 200, 53, 90, 148, 163, 192, + 32, 25, 181, 42, 254, 176, 109, 135, 26, 95, 180, 119, 231, 44, + 247, 126, 56, 243, 17, 233, 36, 159, 104, 134, 22, 86, 226, 5, + 116, 205, 99, 84, 157, 207, 242, 113, 250, 87, 39, 44, 129, 171, + 70, 233, 57, 33, 0, 134, 140, 151, 146, 144, 211, 233, 42, 179, + 216, 132, 140, 141, 97, 173, 213, 105, 96, 112, 121, 94, 225, 100, + 142, 138, 116, 129, 198, 222, 212, 126, 12, 102, 224, 99, 88, 22, + 248, 81, 142, 251, 107, 247, 5, 112, 27, 219, 235, 123, 118, 158, + 7, 147, 13, 167, 154, 142, 48, 147, 135, 243, 72, 33, 135, 42, + 161, 247, 195, 56, 208, 162, 141, 184, 157, 192, 51, 0, 17, 123, + 88, 57, 19, 25, 228, 135, 108, 188, 211, 99, 250, 174, 131, 174, + 39, 124, 66, 10, 14, 242, 13, 251, 57, 162, 4, 11, 47, 50, + 188, 69, 123, 103, 60, 66, 115, 151, 23, 126, 176, 190, 233, 81, + 146, 102, 151, 253, 40, 156, 193, 180, 80, 10, 195, 55, 201, 114, + 40, 53, 27, 125, 238, 233, 150, 182, 119, 126, 79, 214, 102, 207, + 219, 217, 234, 94, 235, 249, 53, 206, 111, 23, 60, 148, 246, 198, + 200, 181, 201, 204, 81, 4, 54, 185, 78, 3, 174, 196, 155, 177, + 152, 164, 159, 118, 66, 223, 124, 204, 234, 172, 98, 248, 247, 105, + 112, 78, 107, 213, 51, 174, 108, 107, 235, 218, 164, 145, 65, 5, + 127, 59, 180, 245, 85, 210, 163, 160, 176, 253, 40, 99, 93, 210, + 250, 80, 113, 117, 7, 223, 182, 3, 56, 93, 187, 52, 131, 5, + 16, 241, 240, 57, 80, 122, 49, 234, 246, 119, 224, 61, 161, 197, + 255, 183, 72, 15, 80, 124, 173, 184, 49, 62, 80, 237, 2, 155, + 218, 240, 239, 54, 41, 158, 44, 65, 173, 73, 5, 7, 155, 209, + 50, 46, 115, 196, 171, 209, 78, 46, 225, 192, 164, 161, 3, 132, + 188, 213, 122, 209, 179, 105, 125, 45, 227, 229, 219, 174, 246, 157, + 85, 226, 128, 183, 98, 254, 80, 196, 104, 224, 31, 8, 245, 121, + 104, 153, 17, 223, 213, 183, 253, 246, 124, 14, 52, 143, 112, 114, + 95, 215, 245, 63, 116, 79, 211, 172, 38, 49, 87, 64, 81, 57, + 30, 149, 174, 25, 138, 66, 226, 203, 221, 86, 151, 128, 222, 219, + 119, 73, 194, 140, 124, 189, 41, 209, 148, 111, 158, 225, 179, 185, + 76, 51, 182, 83, 14, 31, 88, 251, 103, 33, 158, 237, 109, 103, + 93, 239, 33, 77, 93, 38, 86, 27, 165, 99, 176, 29, 213, 150, + 216, 171, 22, 181, 15, 35, 141, 237, 166, 227, 7, 37, 245, 105, + 104, 252, 58, 195, 252, 12, 208, 77, 113, 63, 122, 169, 201, 129, + 132, 158, 89, 251, 24, 245, 144, 230, 70, 191, 98, 109, 255, 203, + 80, 173, 155, 78, 227, 61, 166, 138, 235, 227, 147, 61, 32, 160, + 175, 198, 36, 76, 249, 217, 196, 83, 59, 157, 93, 194, 224, 241, + 67, 107, 194, 58, 201, 83, 225, 242, 247, 99, 158, 54, 150, 86, + 167, 239, 133, 124, 41, 203, 33, 146, 193, 184, 61, 5, 121, 145, + 33, 135, 61, 180, 58, 111, 22, 121, 61, 91, 138, 217, 159, 248, + 105, 8, 195, 27, 61, 240, 211, 40, 253, 105, 133, 59, 233, 228, + 214, 201, 232, 3, 130, 233, 233, 189, 106, 191, 180, 7, 8, 224, + 253, 67, 42, 156, 250, 243, 59, 165, 39, 83, 19, 42, 201, 183, + 194, 125, 24, 213, 148, 220, 255, 162, 137, 158, 50, 152, 211, 216, + 214, 112, 9, 94, 144, 155, 198, 3, 142, 66, 36, 37, 58, 60, + 80, 145, 59, 92, 127, 152, 231, 196, 193, 99, 9, 133, 176, 83, + 202, 52, 207, 191, 153, 247, 158, 30, 36, 235, 39, 91, 235, 65, + 242, 212, 33, 72, 129, 168, 244, 51, 82, 71, 109, 13, 120, 82, + 202, 93, 241, 43, 251, 66, 117, 167, 94, 93, 135, 145, 42, 240, + 185, 136, 59, 183, 163, 203, 128, 29, 68, 62, 254, 243, 233, 213, + 109, 196, 221, 59, 203, 236, 71, 231, 80, 154, 84, 125, 1, 180, + 212, 76, 229, 179, 114, 82, 207, 229, 60, 128, 250, 70, 179, 54, + 2, 7, 254, 121, 147, 5, 131, 173, 13, 167, 108, 98, 0, 230, + 100, 250, 118, 89, 206, 95, 205, 153, 147, 215, 207, 22, 241, 140, + 73, 162, 208, 174, 202, 138, 224, 143, 28, 239, 36, 6, 93, 133, + 219, 224, 177, 162, 70, 201, 248, 150, 203, 156, 253, 194, 250, 47, + 230, 203, 155, 148, 234, 232, 23, 167, 125, 98, 12, 239, 237, 32, + 47, 38, 249, 227, 183, 161, 171, 17, 91, 219, 101, 168, 215, 41, + 248, 118, 9, 22, 138, 215, 86, 79, 107, 197, 157, 136, 30, 47, + 195, 89, 240, 44, 28, 47, 46, 182, 12, 56, 80, 196, 3, 120, + 80, 132, 22, 171, 180, 92, 144, 196, 230, 16, 133, 255, 180, 225, + 64, 230, 56, 108, 233, 60, 99, 162, 108, 43, 246, 224, 240, 5, + 169, 192, 45, 66, 231, 25, 63, 224, 127, 255, 216, 100, 43, 225, + 127, 39, 146, 38, 124, 247, 94, 98, 156, 169, 143, 222, 25, 112, + 219, 176, 168, 70, 35, 60, 123, 82, 205, 12, 81, 51, 238, 228, + 68, 161, 110, 68, 130, 23, 92, 83, 217, 183, 43, 100, 240, 120, + 208, 14, 89, 206, 118, 179, 106, 197, 55, 69, 50, 122, 182, 235, + 159, 41, 186, 164, 123, 21, 82, 221, 252, 191, 127, 109, 196, 1, + 61, 243, 250, 191, 16, 255, 151, 255, 91, 118, 197, 145, 229, 181, + 71, 22, 17, 250, 18, 178, 253, 86, 38, 175, 129, 52, 146, 133, + 24, 118, 15, 226, 4, 79, 154, 146, 216, 142, 100, 80, 47, 178, + 153, 43, 184, 234, 88, 101, 189, 52, 0, 226, 10, 137, 9, 230, + 45, 211, 151, 122, 5, 44, 175, 238, 51, 152, 60, 235, 75, 231, + 70, 162, 137, 253, 130, 153, 234, 231, 157, 156, 5, 190, 1, 186, + 40, 172, 214, 196, 250, 122, 34, 54, 85, 74, 19, 135, 46, 231, + 27, 36, 178, 45, 78, 197, 170, 212, 165, 104, 122, 148, 185, 255, + 20, 133, 200, 172, 106, 43, 65, 37, 25, 28, 166, 120, 10, 26, + 33, 22, 112, 250, 217, 197, 22, 102, 53, 226, 162, 152, 36, 63, + 130, 191, 172, 148, 220, 214, 242, 200, 49, 220, 65, 203, 73, 164, + 62, 60, 205, 170, 247, 104, 155, 183, 135, 234, 249, 193, 151, 2, + 238, 57, 29, 38, 90, 97, 1, 163, 238, 204, 3, 233, 177, 226, + 255, 32, 62, 242, 9, 109, 117, 133, 208, 58, 96, 93, 174, 253, + 142, 49, 162, 115, 53, 242, 239, 176, 23, 156, 178, 30, 173, 164, + 26, 233, 120, 3, 77, 249, 114, 231, 163, 16, 37, 152, 174, 201, + 103, 54, 109, 57, 32, 15, 244, 116, 209, 124, 76, 94, 222, 87, + 56, 235, 103, 214, 74, 116, 171, 115, 188, 249, 237, 23, 0, 103, + 115, 177, 172, 250, 88, 98, 72, 169, 162, 79, 106, 155, 55, 73, + 80, 31, 146, 90, 222, 213, 229, 217, 57, 128, 120, 54, 162, 47, + 83, 207, 237, 1, 33, 80, 84, 186, 61, 80, 169, 21, 253, 15, + 189, 85, 210, 125, 144, 50, 112, 91, 77, 137, 77, 64, 57, 178, + 53, 76, 249, 220, 54, 139, 255, 207, 164, 9, 151, 179, 179, 15, + 206, 15, 158, 69, 129, 111, 144, 215, 14, 8, 226, 44, 30, 162, + 59, 69, 208, 167, 192, 179, 57, 111, 87, 69, 229, 80, 153, 129, + 3, 18, 82, 41, 255, 151, 211, 145, 6, 207, 222, 28, 167, 46, + 160, 16, 12, 243, 86, 102, 182, 17, 189, 41, 54, 46, 103, 70, + 94, 120, 209, 0, 188, 96, 57, 139, 19, 98, 187, 208, 59, 75, + 184, 40, 79, 188, 249, 1, 224, 42, 164, 195, 216, 161, 9, 76, + 102, 31, 227, 46, 247, 116, 60, 50, 45, 94, 180, 155, 215, 63, + 128, 94, 79, 7, 145, 119, 67, 120, 157, 232, 112, 113, 152, 29, + 75, 38, 225, 236, 37, 134, 186, 252, 221, 25, 96, 170, 119, 224, + 181, 22, 104, 62, 95, 14, 184, 166, 146, 17, 167, 218, 210, 126, + 31, 62, 242, 168, 192, 198, 243, 246, 165, 19, 49, 128, 31, 171, + 239, 220, 224, 89, 98, 10, 245, 44, 135, 146, 72, 208, 19, 62, + 191, 254, 234, 160, 208, 137, 3, 232, 187, 219, 26, 201, 26, 102, + 169, 68, 255, 173, 52, 161, 8, 54, 133, 93, 55, 251, 50, 191, + 155, 65, 153, 0, 164, 205, 153, 117, 195, 249, 0, 184, 63, 203, + 169, 201, 191, 196, 37, 45, 49, 145, 1, 139, 206, 24, 13, 234, + 56, 255, 179, 12, 194, 203, 37, 87, 99, 125, 240, 85, 47, 213, + 44, 19, 252, 89, 224, 46, 254, 176, 174, 98, 144, 24, 172, 28, + 81, 164, 131, 240, 221, 182, 161, 83, 57, 193, 9, 109, 135, 210, + 67, 9, 37, 4, 145, 136, 234, 128, 38, 92, 205, 110, 45, 13, + 43, 28, 180, 239, 131, 226, 217, 110, 217, 133, 77, 182, 44, 245, + 126, 240, 191, 105, 86, 207, 251, 244, 159, 64, 62, 197, 104, 91, + 81, 160, 100, 187, 30, 97, 170, 107, 81, 73, 242, 214, 202, 171, + 81, 77, 222, 193, 92, 183, 242, 64, 97, 124, 6, 65, 255, 33, + 77, 211, 216, 208, 49, 18, 183, 215, 191, 45, 76, 86, 49, 63, + 213, 12, 70, 82, 165, 234, 208, 64, 111, 244, 83, 141, 163, 190, + 160, 184, 137, 161, 70, 123, 37, 3, 26, 88, 61, 83, 47, 5, + 110, 66, 39, 199, 219, 131, 92, 255, 252, 141, 240, 151, 110, 250, + 30, 84, 148, 130, 12, 49, 220, 244, 101, 191, 133, 191, 228, 220, + 168, 88, 114, 5, 32, 70, 198, 71, 147, 238, 83, 92, 119, 156, + 209, 117, 178, 84, 31, 196, 147, 207, 195, 225, 123, 61, 32, 106, + 48, 77, 165, 168, 153, 155, 95, 237, 236, 16, 179, 252, 241, 124, + 100, 205, 79, 136, 5, 239, 71, 24, 213, 40, 82, 149, 126, 117, + 191, 168, 32, 193, 127, 131, 15, 131, 239, 107, 193, 0, 135, 86, + 185, 63, 25, 231, 236, 79, 165, 101, 165, 177, 101, 77, 189, 144, + 175, 112, 94, 2, 16, 132, 43, 154, 22, 172, 7, 200, 208, 0, + 222, 116, 167, 229, 131, 208, 77, 48, 144, 192, 95, 186, 208, 215, + 101, 59, 18, 22, 180, 163, 41, 225, 32, 152, 120, 100, 113, 227, + 25, 15, 141, 164, 151, 239, 191, 188, 107, 205, 124, 133, 89, 223, + 41, 100, 5, 216, 134, 7, 103, 204, 171, 0, 36, 13, 73, 242, + 197, 240, 36, 229, 212, 170, 58, 59, 21, 30, 139, 60, 9, 137, + 2, 172, 198, 69, 159, 1, 199, 97, 175, 248, 216, 186, 149, 70, + 110, 244, 168, 201, 110, 206, 51, 171, 1, 145, 117, 18, 5, 82, + 88, 164, 129, 175, 116, 240, 61, 61, 181, 251, 149, 157, 233, 220, + 228, 49, 153, 184, 157, 97, 163, 254, 187, 229, 188, 8, 43, 202, + 233, 141, 44, 35, 130, 242, 94, 136, 140, 88, 28, 144, 148, 75, + 182, 81, 242, 66, 92, 133, 112, 149, 205, 123, 212, 234, 220, 95, + 173, 108, 109, 109, 63, 127, 198, 84, 245, 13, 193, 248, 158, 178, + 131, 80, 233, 44, 6, 151, 253, 163, 238, 184, 236, 142, 222, 110, + 29, 218, 59, 7, 45, 249, 25, 253, 159, 238, 197, 130, 126, 95, + 253, 166, 48, 203, 121, 112, 45, 21, 49, 68, 63, 118, 74, 11, + 216, 225, 142, 0, 95, 20, 35, 44, 186, 41, 202, 223, 206, 92, + 244, 122, 203, 172, 218, 135, 217, 10, 157, 140, 1, 219, 159, 240, + 65, 154, 47, 73, 193, 52, 244, 71, 1, 46, 200, 187, 76, 245, + 176, 166, 173, 160, 227, 241, 88, 163, 57, 96, 146, 138, 186, 70, + 184, 8, 150, 131, 131, 14, 6, 98, 242, 255, 74, 199, 129, 249, + 54, 114, 5, 86, 214, 139, 169, 96, 254, 253, 144, 197, 162, 199, + 118, 189, 204, 49, 145, 237, 49, 79, 32, 16, 39, 199, 42, 18, + 62, 193, 77, 9, 8, 114, 59, 90, 120, 200, 228, 64, 26, 174, + 168, 235, 51, 215, 208, 188, 152, 138, 139, 119, 53, 149, 135, 244, + 249, 244, 26, 98, 234, 212, 227, 147, 187, 148, 201, 110, 195, 108, + 99, 204, 225, 56, 47, 71, 188, 193, 253, 127, 152, 106, 159, 121, + 13, 239, 34, 99, 12, 225, 252, 75, 160, 11, 58, 222, 5, 14, + 238, 207, 188, 204, 81, 3, 158, 177, 90, 3, 29, 51, 235, 15, + 38, 230, 77, 71, 24, 70, 247, 84, 249, 132, 83, 152, 248, 106, + 224, 39, 44, 17, 2, 151, 242, 158, 141, 110, 191, 100, 85, 132, + 165, 91, 4, 93, 67, 229, 89, 221, 135, 185, 170, 161, 212, 110, + 122, 254, 199, 219, 18, 216, 200, 208, 85, 181, 212, 188, 132, 216, + 155, 48, 223, 207, 89, 136, 155, 181, 3, 0, 184, 48, 99, 169, + 220, 102, 137, 189, 117, 128, 167, 149, 248, 189, 213, 27, 128, 88, + 28, 249, 11, 9, 42, 92, 182, 23, 21, 255, 60, 228, 156, 187, + 230, 136, 200, 185, 132, 175, 136, 118, 74, 164, 93, 8, 16, 105, + 93, 182, 96, 75, 205, 81, 26, 187, 161, 84, 222, 119, 6, 209, + 79, 94, 254, 127, 57, 232, 115, 152, 95, 145, 35, 57, 143, 46, + 177, 195, 51, 228, 30, 78, 81, 12, 121, 243, 71, 246, 120, 243, + 138, 189, 192, 203, 40, 184, 43, 179, 143, 109, 229, 183, 233, 167, + 131, 14, 174, 74, 28, 84, 129, 51, 221, 157, 65, 98, 186, 158, + 81, 87, 207, 186, 39, 100, 208, 58, 20, 61, 5, 96, 218, 204, + 222, 13, 67, 245, 49, 137, 18, 205, 240, 92, 82, 234, 67, 129, + 243, 121, 152, 85, 179, 180, 51, 80, 86, 242, 198, 198, 175, 235, + 44, 233, 62, 51, 186, 193, 78, 178, 201, 34, 232, 31, 187, 51, + 254, 77, 43, 177, 43, 0, 6, 92, 233, 211, 64, 64, 154, 78, + 104, 75, 30, 20, 137, 134, 217, 211, 10, 77, 143, 169, 66, 88, + 248, 114, 118, 113, 97, 134, 47, 93, 94, 79, 227, 120, 79, 144, + 236, 81, 248, 58, 159, 54, 88, 135, 136, 154, 92, 57, 165, 22, + 84, 154, 97, 15, 101, 235, 140, 72, 106, 207, 189, 204, 111, 56, + 146, 185, 223, 21, 173, 143, 64, 230, 15, 226, 118, 13, 25, 140, + 241, 214, 28, 35, 188, 240, 103, 156, 55, 48, 19, 142, 240, 225, + 250, 66, 240, 153, 243, 213, 24, 140, 94, 46, 157, 164, 49, 106, + 223, 36, 75, 65, 62, 156, 19, 236, 201, 140, 44, 172, 237, 175, + 197, 224, 139, 3, 146, 233, 80, 145, 141, 244, 6, 214, 219, 97, + 23, 252, 115, 105, 46, 24, 214, 207, 124, 246, 120, 21, 176, 128, + 166, 160, 197, 142, 8, 27, 214, 123, 75, 192, 146, 65, 51, 35, + 162, 174, 83, 129, 125, 138, 164, 183, 39, 139, 52, 46, 195, 218, + 99, 150, 98, 28, 106, 240, 176, 120, 40, 133, 172, 103, 56, 2, + 67, 71, 229, 52, 130, 150, 255, 105, 92, 108, 204, 74, 111, 1, + 38, 240, 192, 20, 9, 101, 1, 66, 28, 230, 218, 252, 0, 62, + 121, 195, 70, 165, 101, 193, 208, 72, 3, 129, 121, 86, 183, 197, + 11, 155, 58, 115, 219, 175, 234, 174, 198, 46, 170, 177, 56, 131, + 143, 169, 177, 191, 121, 130, 223, 121, 210, 57, 33, 130, 122, 198, + 234, 213, 177, 205, 57, 195, 19, 14, 230, 225, 125, 184, 191, 21, + 249, 24, 54, 162, 100, 85, 112, 250, 27, 93, 103, 184, 190, 238, + 92, 100, 209, 103, 231, 156, 24, 21, 37, 143, 81, 22, 155, 113, + 21, 62, 101, 92, 155, 219, 227, 127, 49, 16, 53, 106, 123, 206, + 57, 83, 50, 19, 219, 113, 218, 10, 18, 89, 97, 128, 156, 9, + 194, 165, 16, 191, 111, 138, 113, 207, 21, 27, 132, 194, 22, 246, + 38, 28, 95, 249, 185, 23, 63, 5, 229, 238, 107, 210, 124, 65, + 233, 144, 139, 155, 176, 152, 71, 112, 12, 64, 23, 102, 188, 144, + 206, 55, 243, 225, 124, 177, 110, 161, 109, 123, 231, 150, 205, 213, + 216, 207, 82, 185, 186, 134, 163, 171, 204, 46, 108, 198, 113, 234, + 236, 241, 38, 185, 59, 17, 137, 244, 91, 250, 177, 6, 128, 60, + 207, 71, 181, 244, 185, 93, 180, 184, 242, 217, 116, 225, 199, 249, + 67, 17, 255, 237, 153, 231, 150, 15, 178, 247, 114, 107, 57, 219, + 173, 247, 139, 72, 115, 56, 153, 124, 156, 124, 89, 0, 207, 176, + 144, 157, 165, 65, 197, 209, 218, 90, 0, 27, 19, 236, 196, 241, + 89, 126, 174, 62, 0, 44, 84, 133, 221, 228, 166, 21, 19, 180, + 176, 243, 212, 238, 114, 98, 82, 197, 182, 62, 240, 114, 237, 86, + 210, 112, 173, 17, 40, 149, 77, 227, 192, 175, 42, 156, 231, 144, + 101, 126, 18, 163, 116, 56, 41, 136, 13, 97, 120, 212, 86, 76, + 184, 140, 166, 111, 52, 125, 205, 177, 55, 49, 13, 127, 249, 75, + 225, 231, 6, 240, 224, 84, 106, 238, 124, 11, 80, 92, 238, 220, + 15, 52, 36, 173, 231, 47, 104, 108, 17, 210, 182, 149, 251, 103, + 179, 174, 98, 9, 9, 241, 73, 13, 191, 214, 102, 4, 21, 216, + 212, 50, 80, 162, 65, 187, 176, 240, 157, 138, 144, 214, 252, 207, + 52, 205, 77, 237, 101, 147, 8, 219, 58, 101, 75, 157, 55, 134, + 124, 233, 81, 13, 170, 2, 83, 112, 1, 210, 11, 14, 135, 51, + 203, 247, 140, 63, 240, 128, 18, 1, 227, 109, 55, 240, 233, 111, + 138, 251, 187, 174, 19, 35, 128, 34, 225, 68, 251, 230, 94, 240, + 193, 208, 218, 170, 35, 174, 58, 254, 6, 55, 119, 138, 73, 149, + 164, 133, 233, 252, 34, 191, 164, 223, 108, 240, 41, 204, 63, 113, + 217, 132, 63, 166, 211, 88, 145, 114, 102, 15, 48, 71, 124, 4, + 51, 191, 80, 145, 43, 130, 250, 131, 152, 220, 189, 232, 193, 54, + 44, 237, 223, 201, 198, 44, 116, 122, 201, 205, 178, 123, 37, 211, + 175, 252, 10, 124, 29, 42, 221, 38, 150, 71, 228, 179, 201, 245, + 173, 197, 136, 19, 120, 198, 130, 119, 189, 242, 232, 122, 148, 145, + 56, 11, 17, 9, 94, 46, 139, 7, 102, 98, 163, 39, 149, 175, + 35, 132, 209, 166, 21, 8, 49, 54, 8, 92, 96, 154, 190, 181, + 175, 244, 27, 33, 119, 63, 209, 36, 162, 172, 255, 174, 195, 199, + 84, 132, 163, 30, 2, 166, 207, 194, 246, 21, 251, 211, 124, 188, + 239, 38, 67, 64, 242, 3, 3, 26, 121, 140, 178, 183, 218, 130, + 195, 93, 36, 137, 209, 17, 214, 212, 51, 177, 182, 128, 153, 11, + 153, 119, 240, 244, 29, 126, 247, 80, 111, 120, 202, 148, 249, 84, + 159, 119, 252, 189, 148, 223, 120, 201, 207, 35, 79, 102, 231, 61, + 251, 118, 187, 164, 150, 128, 78, 127, 196, 211, 26, 84, 72, 135, + 101, 164, 179, 8, 22, 176, 92, 214, 95, 237, 47, 218, 118, 77, + 179, 225, 30, 36, 228, 58, 43, 170, 60, 40, 219, 220, 105, 120, + 65, 48, 33, 222, 140, 243, 203, 237, 171, 185, 95, 13, 115, 91, + 237, 19, 154, 192, 205, 121, 162, 92, 53, 141, 26, 105, 186, 118, + 84, 196, 140, 248, 171, 42, 71, 94, 203, 110, 215, 105, 165, 217, + 200, 192, 173, 235, 15, 59, 37, 14, 9, 234, 137, 130, 176, 25, + 120, 23, 170, 92, 179, 229, 10, 0, 181, 39, 20, 183, 81, 201, + 50, 44, 94, 22, 99, 122, 214, 27, 82, 215, 38, 222, 216, 19, + 106, 233, 124, 85, 216, 159, 15, 178, 37, 42, 87, 161, 73, 92, + 254, 176, 243, 171, 109, 23, 36, 135, 139, 163, 233, 246, 57, 19, + 242, 185, 52, 181, 136, 159, 107, 222, 60, 21, 218, 232, 67, 232, + 105, 153, 226, 120, 21, 205, 137, 96, 179, 71, 76, 178, 62, 72, + 198, 81, 66, 88, 61, 199, 85, 211, 65, 142, 26, 120, 105, 158, + 40, 107, 173, 158, 42, 186, 199, 246, 183, 148, 84, 25, 173, 118, + 240, 39, 247, 2, 143, 242, 206, 99, 252, 1, 72, 228, 132, 77, + 241, 57, 67, 20, 133, 149, 253, 40, 143, 120, 231, 44, 153, 149, + 45, 64, 140, 0, 201, 161, 182, 18, 202, 234, 141, 50, 49, 152, + 179, 24, 5, 39, 215, 139, 24, 171, 106, 231, 79, 43, 138, 118, + 65, 151, 59, 106, 91, 55, 34, 107, 162, 29, 104, 233, 115, 41, + 112, 67, 252, 121, 138, 252, 187, 22, 29, 168, 199, 211, 226, 146, + 0, 139, 156, 53, 231, 97, 152, 127, 44, 76, 184, 245, 46, 178, + 78, 41, 28, 149, 172, 224, 209, 80, 212, 190, 215, 232, 3, 109, + 57, 219, 117, 37, 137, 174, 38, 240, 137, 97, 125, 194, 82, 227, + 220, 82, 16, 134, 141, 40, 154, 182, 33, 55, 100, 10, 119, 164, + 132, 139, 64, 166, 207, 167, 220, 53, 197, 48, 122, 152, 22, 220, + 109, 110, 208, 221, 92, 104, 7, 82, 156, 18, 69, 174, 8, 38, + 225, 220, 170, 103, 84, 97, 54, 116, 53, 153, 76, 164, 154, 23, + 127, 247, 242, 248, 127, 84, 194, 20, 57, 242, 188, 121, 11, 13, + 56, 196, 151, 112, 128, 23, 112, 83, 120, 208, 69, 61, 206, 108, + 89, 3, 46, 160, 208, 7, 158, 183, 163, 174, 229, 220, 200, 82, + 94, 16, 129, 51, 248, 233, 137, 46, 217, 123, 56, 61, 133, 151, + 177, 54, 205, 82, 220, 233, 22, 136, 178, 89, 127, 54, 186, 134, + 71, 104, 9, 205, 224, 227, 195, 94, 248, 132, 122, 134, 124, 208, + 51, 60, 228, 58, 223, 133, 182, 157, 6, 29, 118, 241, 170, 169, + 223, 169, 48, 221, 140, 224, 103, 74, 188, 23, 155, 239, 78, 24, + 178, 95, 243, 181, 82, 66, 122, 142, 212, 235, 67, 61, 11, 40, + 39, 12, 138, 155, 242, 227, 177, 6, 55, 3, 113, 18, 14, 214, + 203, 208, 14, 115, 76, 132, 158, 54, 250, 139, 247, 100, 246, 63, + 9, 4, 229, 200, 112, 41, 35, 169, 9, 113, 157, 42, 91, 222, + 92, 141, 196, 151, 16, 2, 50, 190, 82, 70, 84, 207, 119, 98, + 111, 184, 184, 8, 97, 56, 207, 167, 152, 217, 95, 113, 13, 200, + 154, 166, 26, 142, 181, 80, 104, 65, 202, 193, 138, 183, 244, 234, + 222, 107, 188, 186, 115, 58, 194, 83, 158, 183, 199, 230, 67, 98, + 67, 177, 69, 48, 89, 237, 52, 47, 228, 72, 208, 202, 31, 155, + 110, 40, 122, 175, 249, 11, 106, 232, 148, 205, 12, 153, 25, 64, + 87, 214, 28, 181, 42, 250, 247, 54, 247, 174, 209, 166, 127, 145, + 197, 182, 112, 162, 129, 71, 235, 123, 34, 88, 37, 250, 206, 7, + 54, 149, 242, 7, 21, 247, 218, 34, 187, 50, 148, 35, 92, 95, + 125, 73, 117, 254, 226, 105, 6, 9, 199, 249, 119, 167, 202, 145, + 11, 228, 77, 168, 45, 6, 210, 225, 10, 111, 225, 48, 140, 48, + 163, 175, 143, 83, 178, 32, 207, 14, 216, 185, 99, 209, 242, 169, + 88, 145, 163, 171, 27, 39, 107, 12, 82, 230, 85, 97, 100, 107, + 55, 87, 0, 113, 117, 159, 185, 211, 1, 134, 15, 128, 79, 159, + 110, 37, 241, 86, 159, 241, 214, 109, 20, 201, 188, 254, 139, 183, + 60, 250, 34, 158, 241, 245, 244, 172, 196, 63, 82, 111, 104, 59, + 85, 138, 220, 130, 64, 184, 223, 88, 240, 227, 238, 134, 137, 220, + 3, 140, 86, 237, 212, 54, 73, 157, 241, 210, 238, 248, 117, 244, + 227, 72, 176, 249, 44, 157, 78, 106, 218, 73, 71, 172, 57, 241, + 160, 100, 97, 181, 78, 158, 209, 108, 205, 124, 127, 60, 88, 129, + 3, 176, 149, 191, 22, 173, 203, 42, 12, 104, 16, 105, 93, 248, + 170, 245, 150, 189, 30, 91, 15, 211, 181, 223, 57, 147, 123, 88, + 132, 6, 45, 18, 101, 79, 142, 30, 29, 135, 181, 13, 254, 84, + 88, 9, 201, 31, 3, 4, 93, 112, 157, 10, 43, 55, 135, 231, + 28, 169, 23, 69, 243, 42, 139, 41, 184, 159, 96, 46, 146, 169, + 40, 55, 170, 229, 63, 235, 137, 200, 90, 47, 98, 82, 216, 27, + 139, 24, 85, 191, 204, 160, 187, 162, 223, 79, 187, 0, 185, 102, + 251, 165, 253, 107, 61, 181, 182, 199, 76, 214, 60, 43, 145, 117, + 216, 232, 234, 232, 41, 122, 212, 62, 116, 192, 104, 39, 29, 157, + 186, 162, 199, 252, 198, 250, 182, 51, 102, 198, 93, 0, 14, 169, + 251, 226, 175, 199, 102, 70, 139, 124, 253, 161, 130, 138, 254, 241, + 199, 230, 59, 108, 2, 4, 123, 242, 53, 15, 152, 210, 102, 40, + 233, 37, 171, 203, 72, 198, 245, 62, 214, 167, 19, 232, 115, 248, + 30, 250, 84, 167, 191, 123, 121, 173, 24, 86, 9, 27, 3, 212, + 249, 20, 42, 116, 17, 212, 115, 248, 133, 169, 41, 111, 135, 25, + 40, 146, 200, 249, 194, 26, 72, 17, 155, 157, 231, 109, 39, 146, + 180, 8, 51, 138, 42, 18, 184, 247, 4, 22, 60, 246, 237, 145, + 83, 31, 78, 180, 53, 118, 254, 78, 216, 107, 39, 1, 63, 71, + 253, 198, 119, 77, 26, 184, 34, 226, 193, 0, 63, 115, 4, 70, + 197, 234, 174, 161, 198, 159, 182, 168, 122, 8, 172, 120, 187, 35, + 253, 234, 125, 207, 243, 135, 159, 165, 171, 117, 105, 89, 19, 193, + 33, 18, 130, 16, 214, 27, 163, 162, 40, 130, 193, 120, 132, 235, + 213, 50, 58, 216, 135, 184, 192, 248, 16, 75, 200, 243, 227, 129, + 157, 255, 237, 124, 115, 107, 128, 2, 221, 104, 251, 138, 135, 241, + 34, 116, 54, 43, 101, 99, 10, 170, 48, 199, 61, 209, 124, 171, + 211, 247, 157, 136, 94, 151, 253, 81, 116, 72, 89, 101, 253, 254, + 128, 246, 38, 38, 84, 251, 184, 137, 166, 237, 105, 81, 72, 252, + 195, 232, 244, 195, 174, 170, 37, 147, 74, 41, 95, 4, 238, 80, + 144, 206, 11, 176, 60, 72, 196, 217, 33, 25, 73, 12, 179, 48, + 185, 142, 139, 91, 85, 221, 121, 39, 85, 240, 31, 36, 35, 231, + 181, 111, 48, 142, 59, 56, 185, 20, 204, 121, 186, 214, 96, 198, + 174, 235, 64, 252, 88, 49, 145, 37, 48, 126, 1, 184, 102, 41, + 193, 50, 76, 238, 231, 234, 244, 50, 151, 85, 91, 194, 46, 118, + 82, 210, 97, 152, 231, 16, 177, 148, 124, 25, 124, 2, 153, 3, + 144, 135, 157, 130, 233, 158, 198, 255, 129, 62, 117, 5, 239, 31, + 146, 132, 202, 175, 92, 69, 131, 59, 172, 54, 63, 57, 240, 187, + 186, 49, 232, 197, 147, 206, 132, 27, 189, 31, 190, 217, 134, 28, + 171, 27, 218, 209, 102, 57, 145, 146, 219, 46, 134, 238, 193, 119, + 133, 27, 22, 137, 64, 222, 0, 193, 27, 172, 108, 207, 119, 236, + 50, 180, 95, 108, 67, 195, 244, 144, 249, 116, 131, 47, 231, 114, + 4, 244, 152, 56, 0, 209, 126, 252, 89, 32, 199, 159, 43, 49, + 132, 136, 57, 198, 136, 18, 74, 45, 2, 80, 53, 171, 33, 209, + 242, 246, 83, 114, 190, 208, 228, 200, 44, 153, 67, 154, 233, 134, + 186, 115, 98, 131, 214, 38, 59, 32, 248, 97, 67, 27, 125, 111, + 91, 249, 134, 133, 109, 112, 25, 138, 24, 122, 222, 63, 60, 99, + 187, 161, 115, 46, 180, 137, 154, 70, 195, 35, 92, 23, 18, 164, + 88, 132, 198, 31, 121, 201, 226, 95, 81, 142, 61, 228, 117, 73, + 160, 214, 147, 105, 69, 84, 118, 242, 73, 251, 162, 113, 240, 78, + 224, 172, 155, 178, 217, 113, 149, 45, 64, 130, 134, 129, 71, 249, + 205, 253, 172, 74, 101, 116, 160, 112, 143, 196, 206, 141, 101, 3, + 57, 41, 168, 131, 130, 61, 115, 244, 209, 204, 114, 243, 102, 110, + 151, 84, 174, 179, 144, 130, 130, 73, 90, 212, 142, 251, 178, 136, + 223, 158, 130, 137, 111, 106, 106, 21, 60, 204, 217, 56, 224, 171, + 250, 140, 160, 72, 56, 157, 133, 27, 211, 14, 62, 82, 14, 162, + 246, 131, 155, 163, 246, 96, 117, 213, 153, 129, 135, 113, 153, 156, + 124, 185, 255, 73, 3, 142, 66, 208, 221, 119, 90, 15, 117, 253, + 21, 171, 148, 231, 1, 199, 100, 172, 80, 143, 121, 148, 135, 208, + 61, 96, 155, 229, 234, 198, 186, 76, 83, 92, 250, 84, 195, 230, + 98, 211, 252, 61, 109, 164, 120, 238, 218, 73, 178, 111, 207, 154, + 85, 149, 13, 110, 95, 211, 141, 213, 245, 42, 196, 208, 130, 93, + 200, 145, 84, 142, 57, 41, 30, 179, 208, 77, 47, 243, 53, 163, + 52, 47, 97, 216, 174, 142, 188, 148, 138, 234, 169, 211, 70, 188, + 162, 115, 210, 109, 170, 107, 115, 183, 1, 69, 14, 54, 11, 88, + 92, 73, 164, 9, 155, 77, 230, 236, 105, 32, 106, 254, 254, 229, + 4, 82, 4, 92, 41, 175, 140, 250, 255, 175, 213, 92, 41, 3, + 206, 49, 166, 95, 212, 61, 194, 227, 65, 69, 85, 230, 58, 48, + 26, 17, 108, 31, 168, 181, 0, 21, 240, 117, 80, 31, 240, 207, + 104, 234, 195, 180, 151, 208, 87, 187, 71, 152, 9, 64, 152, 61, + 2, 175, 2, 116, 139, 24, 9, 219, 155, 146, 146, 175, 119, 255, + 114, 219, 220, 223, 125, 198, 193, 59, 83, 24, 92, 195, 143, 155, + 11, 250, 145, 102, 122, 84, 108, 3, 60, 194, 36, 123, 74, 126, + 146, 47, 6, 213, 145, 229, 232, 208, 100, 240, 140, 122, 16, 102, + 113, 220, 116, 228, 194, 94, 96, 183, 10, 109, 196, 61, 30, 3, + 114, 10, 131, 146, 254, 135, 170, 32, 165, 85, 239, 152, 128, 201, + 214, 20, 231, 185, 16, 81, 179, 21, 116, 213, 192, 222, 217, 111, + 103, 253, 244, 110, 229, 50, 12, 196, 182, 212, 145, 147, 210, 118, + 226, 205, 131, 124, 248, 50, 223, 195, 147, 57, 62, 118, 69, 206, + 174, 108, 53, 0, 72, 251, 58, 162, 4, 221, 115, 44, 90, 69, + 6, 66, 74, 186, 106, 173, 113, 207, 127, 125, 133, 138, 143, 65, + 96, 219, 66, 94, 164, 84, 60, 11, 178, 30, 181, 2, 206, 22, + 104, 91, 79, 18, 72, 251, 46, 127, 182, 169, 173, 214, 203, 78, + 22, 146, 172, 89, 209, 121, 214, 119, 194, 96, 253, 107, 20, 41, + 68, 145, 113, 162, 107, 102, 157, 137, 201, 203, 49, 156, 168, 216, + 99, 66, 112, 238, 61, 189, 85, 155, 11, 200, 63, 72, 39, 1, + 6, 151, 74, 23, 231, 133, 249, 67, 52, 26, 188, 7, 43, 168, + 120, 64, 110, 112, 196, 64, 180, 97, 38, 249, 177, 65, 193, 190, + 253, 90, 152, 140, 206, 71, 159, 182, 107, 100, 93, 45, 158, 191, + 98, 50, 42, 73, 29, 226, 59, 218, 8, 136, 63, 41, 173, 81, + 2, 229, 140, 114, 25, 193, 162, 165, 170, 73, 197, 124, 8, 76, + 69, 184, 151, 76, 144, 198, 45, 243, 79, 226, 112, 192, 114, 4, + 137, 202, 201, 48, 55, 34, 74, 71, 231, 124, 163, 181, 152, 208, + 223, 142, 54, 13, 190, 126, 26, 63, 126, 102, 18, 196, 31, 235, + 184, 77, 71, 93, 2, 130, 12, 38, 178, 29, 107, 91, 27, 199, + 92, 85, 204, 35, 110, 219, 8, 111, 5, 169, 78, 241, 122, 253, + 210, 104, 186, 212, 144, 33, 105, 141, 124, 224, 220, 122, 175, 245, + 250, 155, 52, 73, 228, 121, 65, 107, 2, 34, 36, 221, 149, 137, + 37, 216, 156, 175, 246, 189, 251, 179, 188, 209, 60, 231, 254, 35, + 111, 178, 59, 146, 225, 114, 46, 63, 29, 160, 19, 63, 94, 143, + 207, 18, 147, 80, 223, 134, 5, 76, 187, 18, 197, 246, 211, 2, + 36, 186, 104, 224, 92, 33, 142, 22, 67, 179, 101, 93, 94, 94, + 115, 61, 163, 253, 177, 132, 4, 135, 103, 8, 4, 101, 49, 111, + 38, 31, 0, 150, 13, 52, 116, 145, 209, 255, 247, 231, 86, 190, + 135, 29, 243, 49, 165, 139, 236, 39, 99, 216, 144, 58, 199, 51, + 41, 138, 8, 130, 30, 92, 114, 159, 193, 122, 98, 83, 113, 27, + 115, 147, 132, 194, 32, 135, 243, 170, 251, 99, 21, 48, 222, 216, + 16, 130, 194, 9, 133, 63, 92, 28, 160, 9, 138, 101, 147, 237, + 121, 216, 63, 152, 243, 225, 49, 31, 158, 69, 202, 156, 209, 154, + 170, 23, 171, 14, 82, 210, 240, 70, 47, 252, 47, 33, 213, 114, + 150, 93, 138, 231, 168, 152, 195, 45, 129, 94, 215, 122, 102, 225, + 123, 37, 227, 43, 130, 13, 234, 163, 216, 19, 3, 4, 153, 198, + 53, 61, 55, 170, 112, 0, 117, 88, 191, 126, 103, 16, 137, 161, + 150, 172, 168, 223, 129, 155, 29, 12, 123, 137, 168, 111, 3, 9, + 164, 34, 198, 154, 51, 231, 24, 1, 23, 36, 134, 155, 68, 112, + 120, 6, 112, 136, 222, 82, 21, 155, 247, 220, 115, 219, 78, 74, + 140, 210, 160, 217, 146, 5, 163, 98, 95, 214, 151, 31, 100, 118, + 216, 122, 155, 9, 203, 45, 225, 254, 29, 156, 242, 107, 114, 17, + 37, 12, 208, 88, 30, 187, 181, 122, 106, 248, 58, 26, 118, 41, + 180, 116, 69, 94, 78, 75, 64, 57, 144, 21, 140, 154, 113, 127, + 33, 219, 18, 113, 109, 3, 34, 54, 134, 148, 111, 103, 159, 173, + 43, 151, 42, 164, 49, 16, 106, 227, 181, 110, 220, 132, 210, 248, + 137, 56, 167, 122, 89, 76, 138, 124, 125, 145, 145, 243, 253, 99, + 230, 179, 83, 230, 160, 122, 5, 159, 132, 146, 217, 232, 87, 208, + 236, 134, 69, 211, 73, 166, 133, 7, 75, 249, 105, 157, 206, 90, + 32, 173, 132, 69, 95, 238, 93, 144, 97, 173, 124, 155, 220, 216, + 64, 47, 227, 111, 25, 246, 225, 215, 200, 152, 135, 36, 207, 242, + 41, 218, 99, 103, 215, 66, 232, 139, 82, 82, 154, 142, 86, 162, + 43, 194, 145, 191, 136, 64, 227, 212, 75, 206, 208, 36, 171, 70, + 65, 197, 129, 52, 129, 247, 36, 65, 117, 76, 114, 151, 225, 18, + 231, 75, 245, 195, 25, 72, 1, 39, 143, 215, 103, 133, 92, 144, + 28, 130, 80, 126, 5, 250, 165, 147, 211, 109, 245, 26, 41, 244, + 236, 18, 187, 178, 101, 206, 168, 228, 119, 61, 140, 234, 200, 90, + 149, 207, 36, 212, 79, 182, 100, 132, 251, 70, 69, 248, 183, 108, + 128, 101, 5, 96, 13, 246, 157, 214, 224, 133, 81, 47, 229, 100, + 31, 55, 4, 240, 144, 6, 48, 60, 107, 246, 177, 161, 38, 101, + 150, 231, 180, 182, 95, 224, 17, 46, 164, 229, 77, 208, 245, 173, + 218, 16, 69, 237, 130, 69, 161, 143, 47, 11, 9, 130, 89, 13, + 176, 241, 144, 164, 222, 15, 181, 111, 240, 119, 58, 113, 126, 232, + 240, 47, 223, 137, 48, 123, 16, 109, 220, 156, 51, 33, 10, 50, + 75, 232, 225, 249, 213, 36, 151, 61, 216, 79, 34, 28, 242, 191, + 13, 71, 211, 183, 98, 41, 169, 194, 163, 39, 17, 115, 63, 50, + 10, 237, 117, 145, 33, 170, 131, 120, 81, 157, 148, 30, 186, 172, + 45, 221, 162, 80, 63, 60, 67, 211, 82, 235, 31, 152, 204, 246, + 16, 102, 183, 132, 79, 1, 230, 235, 244, 213, 8, 248, 6, 169, + 11, 224, 180, 151, 125, 156, 208, 122, 31, 221, 58, 93, 185, 241, + 228, 191, 66, 120, 5, 85, 149, 109, 140, 100, 242, 73, 189, 221, + 239, 209, 27, 90, 186, 180, 223, 30, 88, 32, 63, 62, 116, 3, + 42, 149, 224, 7, 145, 144, 249, 229, 188, 158, 252, 180, 65, 221, + 162, 222, 62, 154, 20, 156, 222, 106, 2, 185, 213, 193, 85, 203, + 70, 163, 190, 50, 67, 6, 105, 39, 150, 79, 233, 80, 94, 100, + 160, 54, 190, 143, 38, 238, 74, 90, 192, 235, 164, 244, 25, 118, + 210, 106, 76, 156, 216, 243, 252, 191, 248, 199, 41, 95, 95, 255, + 116, 112, 123, 46, 200, 218, 116, 151, 78, 162, 161, 36, 166, 34, + 19, 82, 211, 185, 186, 205, 195, 142, 8, 156, 21, 119, 98, 164, + 191, 227, 239, 5, 232, 58, 47, 98, 22, 179, 139, 134, 6, 221, + 107, 173, 227, 239, 186, 145, 131, 147, 105, 141, 246, 250, 16, 211, + 237, 200, 161, 202, 23, 135, 109, 231, 237, 47, 15, 94, 186, 74, + 71, 18, 215, 131, 52, 8, 170, 88, 172, 46, 213, 25, 176, 88, + 167, 78, 64, 112, 221, 124, 147, 218, 119, 216, 86, 0, 94, 140, + 26, 235, 82, 52, 64, 71, 19, 44, 81, 32, 35, 62, 118, 42, + 199, 19, 166, 98, 216, 35, 94, 154, 142, 59, 233, 157, 209, 150, + 219, 151, 85, 43, 81, 140, 17, 140, 135, 59, 55, 37, 71, 94, + 212, 136, 16, 44, 144, 252, 209, 224, 255, 54, 127, 154, 191, 159, + 33, 255, 177, 228, 178, 10, 172, 195, 69, 90, 33, 204, 193, 67, + 228, 60, 167, 185, 202, 244, 130, 227, 139, 235, 84, 235, 3, 179, + 214, 226, 198, 137, 25, 198, 65, 10, 46, 10, 195, 41, 58, 87, + 126, 254, 97, 100, 169, 69, 136, 221, 240, 197, 1, 220, 36, 120, + 213, 86, 33, 136, 121, 185, 224, 142, 156, 142, 116, 142, 97, 50, + 86, 196, 66, 159, 73, 186, 186, 21, 54, 190, 232, 12, 60, 30, + 7, 37, 207, 118, 80, 150, 125, 34, 60, 167, 9, 40, 134, 10, + 204, 5, 23, 166, 181, 247, 176, 97, 21, 247, 120, 36, 181, 42, + 126, 63, 5, 188, 62, 212, 166, 16, 197, 41, 29, 108, 217, 57, + 226, 51, 159, 125, 127, 218, 230, 233, 38, 68, 206, 32, 64, 137, + 32, 93, 40, 2, 20, 227, 26, 42, 190, 112, 121, 246, 14, 87, + 243, 165, 143, 232, 40, 186, 164, 84, 215, 112, 75, 35, 168, 93, + 173, 170, 191, 252, 156, 199, 4, 140, 163, 196, 84, 220, 5, 142, + 235, 29, 199, 90, 136, 185, 151, 181, 153, 198, 141, 159, 188, 57, + 33, 102, 156, 13, 108, 174, 135, 174, 179, 58, 113, 226, 137, 217, + 20, 164, 87, 206, 27, 71, 31, 134, 113, 54, 137, 28, 117, 236, + 57, 230, 58, 84, 93, 176, 76, 80, 11, 149, 119, 135, 169, 176, + 240, 49, 109, 245, 186, 93, 206, 187, 129, 14, 47, 100, 222, 55, + 252, 44, 161, 0, 132, 245, 196, 122, 155, 82, 120, 127, 3, 19, + 233, 36, 147, 163, 223, 44, 15, 14, 178, 47, 241, 174, 206, 141, + 17, 34, 221, 35, 142, 98, 115, 200, 176, 103, 188, 175, 98, 120, + 240, 72, 91, 217, 106, 225, 110, 34, 50, 196, 39, 22, 8, 33, + 62, 224, 183, 156, 40, 123, 158, 63, 90, 114, 175, 13, 181, 213, + 64, 185, 238, 70, 203, 198, 212, 158, 215, 50, 34, 191, 25, 50, + 255, 121, 56, 110, 33, 237, 197, 113, 133, 62, 108, 113, 203, 197, + 14, 68, 218, 176, 6, 171, 76, 180, 228, 13, 129, 59, 114, 221, + 90, 32, 238, 244, 20, 69, 71, 81, 188, 20, 41, 36, 214, 120, + 113, 173, 17, 3, 52, 46, 127, 169, 162, 156, 237, 163, 38, 130, + 85, 8, 154, 84, 232, 235, 142, 90, 5, 133, 131, 192, 18, 53, + 78, 164, 169, 139, 234, 198, 85, 66, 92, 196, 130, 223, 90, 39, + 11, 19, 243, 116, 74, 24, 144, 103, 94, 212, 240, 15, 125, 185, + 95, 130, 79, 200, 155, 21, 62, 30, 216, 188, 74, 13, 58, 234, + 72, 153, 166, 198, 44, 51, 11, 43, 170, 213, 96, 39, 92, 194, + 205, 46, 249, 255, 75, 113, 31, 212, 68, 214, 40, 234, 114, 230, + 97, 143, 28, 99, 213, 191, 198, 76, 238, 45, 94, 191, 22, 94, + 158, 225, 11, 245, 133, 41, 169, 29, 22, 206, 192, 181, 72, 156, + 35, 189, 2, 42, 109, 67, 223, 251, 246, 160, 123, 254, 75, 8, + 97, 126, 60, 91, 238, 229, 115, 141, 79, 221, 76, 226, 180, 85, + 120, 72, 18, 90, 171, 224, 230, 223, 66, 128, 57, 159, 243, 126, + 24, 208, 27, 191, 133, 198, 218, 180, 122, 248, 71, 40, 136, 64, + 73, 156, 168, 192, 92, 34, 231, 24, 185, 254, 124, 226, 10, 154, + 105, 207, 163, 82, 52, 169, 118, 45, 57, 211, 150, 199, 177, 245, + 207, 56, 224, 206, 162, 208, 26, 199, 19, 54, 51, 126, 0, 46, + 113, 18, 255, 39, 14, 14, 145, 150, 176, 204, 75, 43, 89, 143, + 107, 217, 140, 193, 98, 218, 95, 244, 161, 201, 88, 61, 81, 247, + 181, 224, 63, 28, 78, 156, 91, 98, 211, 208, 40, 185, 132, 245, + 247, 176, 90, 246, 98, 86, 44, 180, 212, 120, 134, 228, 156, 34, + 25, 147, 142, 12, 137, 216, 218, 188, 104, 120, 59, 99, 143, 164, + 22, 87, 141, 57, 154, 254, 128, 239, 59, 127, 193, 92, 172, 195, + 45, 11, 118, 140, 78, 91, 217, 252, 26, 107, 170, 120, 191, 197, + 159, 115, 107, 70, 106, 209, 30, 86, 235, 100, 235, 18, 237, 135, + 157, 3, 191, 245, 2, 217, 210, 63, 228, 208, 65, 79, 61, 248, + 41, 143, 208, 202, 134, 1, 201, 231, 235, 204, 29, 7, 157, 18, + 229, 244, 86, 64, 22, 245, 185, 18, 81, 152, 98, 70, 14, 101, + 70, 170, 86, 104, 3, 44, 60, 118, 72, 224, 127, 169, 10, 37, + 79, 113, 146, 107, 64, 206, 148, 111, 7, 47, 129, 144, 197, 53, + 178, 220, 65, 76, 186, 124, 232, 62, 230, 26, 90, 225, 174, 55, + 151, 118, 23, 211, 102, 208, 185, 39, 146, 184, 127, 2, 154, 64, + 245, 65, 95, 2, 68, 6, 123, 60, 145, 138, 44, 20, 179, 242, + 13, 135, 24, 104, 26, 219, 206, 6, 54, 102, 243, 51, 230, 80, + 238, 5, 72, 199, 46, 239, 14, 181, 86, 41, 217, 193, 98, 50, + 4, 44, 223, 14, 84, 104, 29, 102, 6, 228, 147, 167, 231, 237, + 13, 84, 87, 156, 78, 96, 187, 196, 170, 159, 184, 139, 52, 64, + 147, 126, 130, 159, 219, 146, 25, 222, 27, 220, 70, 78, 121, 124, + 117, 75, 142, 17, 86, 235, 248, 161, 193, 18, 56, 179, 96, 172, + 94, 130, 76, 148, 250, 79, 158, 195, 133, 72, 0, 82, 209, 56, + 73, 237, 201, 40, 56, 212, 13, 12, 234, 255, 63, 89, 243, 212, + 206, 189, 122, 105, 200, 192, 77, 34, 42, 217, 184, 33, 59, 132, + 248, 162, 222, 75, 45, 12, 7, 113, 204, 101, 158, 91, 150, 134, + 241, 121, 54, 201, 104, 12, 142, 187, 91, 1, 9, 86, 40, 205, + 173, 103, 59, 74, 58, 88, 208, 251, 153, 54, 73, 231, 53, 83, + 181, 106, 138, 218, 189, 132, 92, 32, 57, 108, 26, 60, 37, 43, + 185, 170, 47, 230, 72, 31, 251, 10, 220, 113, 45, 45, 237, 92, + 127, 33, 217, 157, 144, 175, 21, 87, 153, 89, 166, 138, 58, 182, + 127, 20, 52, 181, 109, 101, 185, 116, 99, 235, 2, 224, 192, 107, + 75, 85, 82, 105, 214, 246, 22, 60, 153, 79, 14, 152, 218, 72, + 117, 177, 252, 171, 122, 38, 145, 154, 21, 234, 194, 152, 189, 181, + 174, 219, 210, 65, 75, 2, 211, 227, 199, 217, 86, 128, 164, 165, + 167, 156, 126, 110, 216, 247, 120, 7, 22, 119, 98, 201, 47, 202, + 3, 7, 240, 81, 158, 124, 108, 42, 190, 41, 60, 204, 144, 202, + 154, 92, 189, 81, 165, 37, 153, 44, 104, 94, 145, 190, 141, 225, + 234, 131, 137, 1, 169, 8, 200, 150, 92, 66, 124, 110, 28, 126, + 102, 43, 110, 165, 119, 83, 181, 132, 185, 176, 68, 116, 146, 73, + 88, 250, 133, 124, 208, 198, 102, 197, 161, 79, 255, 111, 73, 210, + 211, 0, 152, 61, 130, 172, 79, 243, 201, 19, 58, 140, 242, 95, + 221, 12, 194, 74, 95, 197, 207, 161, 47, 103, 21, 82, 52, 96, + 47, 31, 93, 19, 137, 222, 101, 230, 246, 82, 160, 100, 129, 178, + 165, 116, 44, 83, 141, 105, 128, 136, 136, 140, 144, 42, 2, 209, + 203, 154, 173, 70, 47, 148, 7, 173, 175, 204, 12, 91, 137, 159, + 222, 68, 122, 184, 125, 143, 56, 143, 205, 180, 158, 162, 141, 51, + 86, 86, 12, 85, 78, 237, 91, 132, 221, 167, 201, 152, 80, 191, + 236, 119, 44, 17, 228, 214, 72, 27, 75, 33, 86, 240, 4, 204, + 59, 236, 97, 228, 190, 48, 11, 66, 241, 219, 184, 180, 182, 119, + 161, 119, 65, 232, 188, 146, 110, 222, 187, 145, 203, 135, 160, 212, + 119, 174, 249, 233, 5, 105, 236, 236, 112, 94, 119, 28, 38, 243, + 242, 17, 120, 89, 104, 246, 161, 186, 123, 162, 204, 78, 32, 6, + 93, 110, 244, 124, 104, 252, 133, 70, 91, 5, 56, 78, 141, 225, + 235, 24, 214, 47, 41, 136, 205, 212, 254, 152, 42, 55, 81, 7, + 95, 24, 24, 148, 77, 128, 241, 226, 251, 86, 84, 40, 88, 165, + 28, 130, 72, 106, 120, 98, 65, 132, 244, 53, 253, 172, 68, 88, + 43, 215, 106, 1, 239, 176, 64, 129, 156, 141, 62, 12, 102, 199, + 181, 57, 53, 253, 86, 14, 164, 154, 8, 191, 107, 82, 15, 200, + 31, 239, 10, 100, 38, 196, 209, 109, 61, 135, 169, 149, 56, 243, + 60, 75, 78, 66, 213, 23, 79, 166, 249, 200, 232, 231, 7, 202, + 178, 77, 140, 239, 252, 86, 43, 183, 21, 58, 3, 185, 83, 124, + 125, 49, 242, 145, 186, 248, 163, 238, 29, 41, 100, 250, 248, 4, + 217, 160, 27, 89, 95, 205, 117, 178, 144, 158, 42, 242, 171, 81, + 156, 75, 236, 108, 107, 7, 39, 16, 102, 139, 188, 3, 254, 101, + 119, 228, 132, 66, 249, 16, 16, 54, 229, 224, 59, 218, 170, 248, + 15, 68, 33, 30, 30, 155, 22, 56, 72, 214, 84, 159, 54, 248, + 67, 39, 84, 176, 140, 70, 205, 234, 81, 8, 79, 158, 114, 127, + 72, 174, 99, 19, 153, 76, 165, 167, 147, 234, 119, 52, 232, 224, + 96, 2, 220, 231, 6, 203, 248, 124, 199, 209, 176, 235, 210, 63, + 23, 34, 90, 85, 172, 186, 189, 248, 159, 20, 211, 185, 121, 188, + 66, 225, 221, 185, 143, 103, 147, 15, 43, 95, 66, 42, 71, 200, + 165, 211, 97, 127, 208, 247, 200, 19, 200, 195, 173, 163, 137, 168, + 108, 70, 151, 96, 217, 200, 64, 124, 65, 129, 163, 80, 207, 212, + 44, 177, 21, 41, 0, 216, 27, 23, 74, 168, 207, 218, 35, 238, + 179, 232, 13, 35, 222, 67, 97, 183, 43, 13, 13, 137, 52, 206, + 80, 131, 226, 228, 178, 206, 92, 194, 87, 133, 55, 151, 136, 74, + 149, 58, 241, 217, 124, 160, 193, 54, 37, 197, 210, 215, 98, 28, + 155, 213, 119, 252, 63, 62, 177, 185, 172, 11, 205, 208, 92, 59, + 36, 175, 43, 229, 195, 130, 131, 96, 156, 20, 249, 50, 59, 199, + 231, 96, 89, 7, 211, 195, 88, 136, 200, 44, 159, 62, 68, 223, + 81, 188, 17, 31, 193, 253, 116, 122, 138, 153, 153, 18, 242, 84, + 240, 88, 82, 188, 228, 213, 70, 115, 110, 218, 106, 134, 121, 128, + 59, 64, 188, 123, 157, 48, 172, 165, 85, 226, 133, 65, 246, 103, + 93, 13, 231, 77, 90, 72, 37, 249, 46, 56, 249, 78, 100, 219, + 7, 147, 53, 246, 243, 125, 151, 248, 175, 16, 22, 29, 247, 60, + 123, 162, 244, 245, 139, 89, 104, 96, 238, 172, 131, 246, 86, 141, + 25, 1, 78, 233, 152, 90, 194, 118, 8, 141, 88, 177, 182, 3, + 26, 224, 171, 88, 109, 175, 176, 100, 96, 37, 218, 176, 241, 201, + 65, 11, 51, 208, 28, 36, 163, 2, 22, 104, 168, 23, 26, 244, + 230, 55, 249, 44, 100, 197, 185, 169, 207, 192, 137, 68, 94, 220, + 106, 167, 231, 9, 61, 152, 192, 118, 120, 87, 242, 24, 194, 121, + 188, 181, 77, 229, 40, 208, 171, 31, 212, 121, 145, 156, 187, 225, + 210, 187, 6, 170, 232, 84, 218, 136, 122, 141, 128, 85, 89, 241, + 114, 9, 243, 83, 155, 166, 102, 197, 172, 103, 100, 249, 43, 124, + 232, 185, 57, 179, 225, 180, 245, 180, 176, 252, 205, 67, 133, 92, + 130, 169, 132, 161, 52, 196, 54, 160, 165, 13, 179, 23, 85, 220, + 51, 149, 129, 18, 5, 140, 94, 32, 238, 139, 51, 189, 158, 48, + 34, 41, 117, 56, 149, 156, 8, 227, 189, 134, 253, 139, 104, 171, + 221, 164, 157, 235, 52, 164, 38, 185, 254, 220, 116, 234, 229, 94, + 252, 60, 119, 198, 116, 152, 223, 49, 152, 184, 229, 152, 28, 196, + 5, 114, 243, 93, 98, 255, 72, 232, 196, 235, 102, 47, 72, 116, + 233, 121, 174, 127, 98, 146, 238, 124, 63, 221, 251, 226, 68, 40, + 47, 237, 34, 119, 36, 193, 143, 242, 94, 21, 120, 77, 217, 235, + 196, 42, 132, 9, 181, 202, 219, 141, 239, 74, 201, 50, 99, 106, + 61, 178, 138, 50, 75, 204, 61, 93, 15, 29, 62, 208, 70, 172, + 54, 15, 254, 40, 58, 194, 51, 252, 235, 250, 228, 152, 174, 4, + 148, 63, 92, 149, 89, 106, 230, 116, 47, 232, 5, 32, 72, 83, + 137, 95, 56, 175, 63, 213, 134, 46, 194, 95, 89, 178, 197, 164, + 249, 29, 60, 66, 255, 122, 179, 27, 198, 121, 117, 155, 139, 239, + 5, 217, 228, 192, 33, 118, 211, 95, 30, 77, 219, 94, 136, 22, + 111, 53, 81, 85, 237, 245, 7, 121, 18, 153, 81, 20, 168, 87, + 134, 3, 127, 6, 164, 167, 186, 20, 237, 128, 216, 134, 15, 188, + 210, 172, 245, 150, 9, 188, 205, 204, 198, 37, 144, 27, 233, 230, + 15, 237, 72, 67, 26, 89, 2, 213, 68, 62, 11, 134, 102, 101, + 134, 177, 81, 45, 136, 193, 181, 54, 10, 242, 73, 236, 230, 25, + 222, 133, 122, 164, 186, 93, 52, 14, 17, 93, 248, 201, 250, 163, + 31, 246, 152, 112, 22, 209, 224, 252, 244, 205, 147, 151, 60, 8, + 193, 165, 127, 19, 143, 160, 182, 5, 215, 14, 166, 104, 27, 57, + 31, 62, 132, 157, 114, 140, 38, 77, 86, 194, 98, 118, 24, 194, + 222, 173, 212, 9, 77, 14, 207, 153, 215, 149, 136, 0, 43, 171, + 68, 139, 54, 77, 62, 204, 209, 116, 241, 43, 0, 15, 53, 46, + 158, 105, 187, 140, 134, 210, 23, 3, 60, 186, 206, 53, 147, 127, + 142, 103, 230, 210, 135, 30, 176, 96, 24, 19, 228, 116, 250, 68, + 216, 40, 127, 64, 19, 161, 108, 238, 57, 4, 184, 97, 67, 59, + 26, 18, 237, 73, 7, 5, 29, 82, 234, 52, 112, 15, 158, 58, + 238, 211, 94, 199, 72, 76, 202, 119, 175, 134, 197, 67, 170, 163, + 248, 7, 19, 197, 36, 84, 32, 111, 240, 185, 205, 146, 54, 186, + 236, 14, 201, 124, 201, 42, 165, 70, 114, 32, 188, 4, 192, 49, + 9, 79, 41, 8, 215, 203, 211, 182, 25, 198, 237, 187, 210, 97, + 108, 124, 3, 60, 239, 8, 251, 149, 98, 27, 236, 84, 122, 28, + 82, 20, 117, 199, 99, 205, 249, 255, 233, 177, 112, 107, 240, 34, + 174, 201, 19, 218, 176, 235, 228, 52, 40, 62, 39, 235, 254, 47, + 223, 247, 9, 65, 116, 141, 143, 220, 227, 231, 73, 236, 16, 33, + 4, 123, 27, 69, 166, 89, 17, 74, 136, 118, 57, 161, 188, 134, + 240, 3, 236, 65, 27, 235, 226, 102, 125, 122, 194, 76, 203, 47, + 92, 166, 249, 5, 170, 185, 96, 94, 118, 168, 27, 173, 14, 199, + 166, 73, 20, 223, 138, 178, 124, 241, 149, 17, 79, 17, 177, 179, + 141, 113, 28, 226, 125, 222, 221, 11, 185, 233, 251, 70, 227, 93, + 21, 229, 101, 244, 229, 145, 148, 51, 21, 7, 50, 56, 127, 11, + 200, 255, 237, 162, 191, 103, 21, 247, 170, 49, 159, 149, 217, 129, + 153, 236, 21, 144, 211, 142, 173, 59, 90, 99, 12, 146, 60, 56, + 29, 178, 112, 154, 70, 219, 94, 35, 175, 180, 50, 84, 107, 60, + 224, 198, 69, 38, 42, 13, 188, 171, 240, 182, 36, 36, 164, 3, + 132, 112, 43, 108, 29, 136, 236, 24, 99, 123, 21, 113, 237, 57, + 31, 125, 1, 122, 69, 229, 54, 202, 218, 161, 180, 56, 15, 11, + 35, 38, 98, 141, 202, 173, 249, 76, 184, 124, 191, 150, 250, 81, + 79, 124, 131, 165, 128, 125, 18, 127, 186, 225, 163, 43, 215, 55, + 95, 237, 27, 16, 35, 185, 192, 133, 7, 159, 160, 251, 144, 225, + 198, 39, 61, 84, 242, 91, 119, 67, 124, 151, 23, 2, 206, 239, + 214, 80, 21, 125, 11, 57, 202, 87, 149, 186, 70, 224, 61, 225, + 64, 47, 81, 15, 146, 151, 132, 108, 69, 185, 190, 137, 183, 110, + 218, 155, 18, 83, 49, 5, 110, 89, 67, 11, 24, 225, 50, 62, + 70, 235, 0, 31, 161, 87, 151, 235, 70, 216, 189, 96, 48, 246, + 51, 130, 154, 22, 248, 242, 84, 3, 173, 179, 32, 233, 105, 168, + 99, 44, 68, 105, 177, 226, 252, 234, 68, 203, 154, 251, 84, 250, + 125, 93, 6, 250, 114, 19, 36, 62, 96, 239, 75, 104, 42, 141, + 70, 121, 217, 218, 193, 76, 113, 159, 123, 13, 216, 20, 234, 90, + 96, 190, 16, 156, 235, 214, 228, 110, 47, 106, 111, 243, 42, 108, + 94, 117, 106, 209, 148, 55, 81, 138, 158, 21, 94, 232, 179, 140, + 187, 212, 214, 155, 219, 5, 231, 137, 19, 134, 205, 138, 87, 185, + 254, 18, 34, 0, 11, 136, 78, 100, 86, 179, 237, 78, 120, 228, + 235, 170, 248, 92, 43, 86, 46, 205, 70, 80, 220, 168, 67, 235, + 138, 246, 226, 38, 33, 50, 126, 236, 70, 96, 81, 223, 36, 159, + 100, 210, 254, 10, 234, 2, 208, 119, 40, 110, 237, 159, 155, 139, + 25, 12, 226, 247, 39, 228, 179, 71, 239, 150, 208, 8, 132, 86, + 150, 115, 232, 183, 110, 108, 225, 63, 232, 158, 244, 120, 3, 82, + 163, 220, 160, 91, 93, 165, 66, 81, 73, 37, 34, 52, 201, 58, + 36, 138, 83, 224, 47, 163, 69, 101, 50, 37, 114, 200, 106, 234, + 126, 108, 21, 235, 104, 58, 128, 211, 42, 144, 102, 114, 221, 99, + 6, 94, 114, 86, 29, 111, 92, 225, 253, 230, 131, 231, 69, 11, + 66, 36, 34, 117, 21, 65, 6, 115, 58, 107, 174, 174, 195, 233, + 169, 68, 80, 199, 78, 254, 2, 232, 114, 153, 42, 69, 106, 216, + 49, 89, 14, 249, 124, 215, 239, 250, 219, 125, 52, 56, 253, 0, + 254, 32, 108, 242, 179, 204, 37, 201, 90, 184, 232, 175, 122, 160, + 115, 32, 40, 251, 66, 34, 127, 129, 228, 24, 200, 179, 6, 162, + 189, 170, 214, 172, 134, 31, 43, 18, 49, 214, 187, 167, 98, 174, + 8, 93, 41, 124, 180, 152, 112, 92, 223, 68, 54, 156, 130, 243, + 101, 214, 50, 4, 65, 240, 29, 80, 175, 75, 88, 138, 58, 21, + 68, 83, 88, 42, 233, 26, 195, 25, 254, 158, 148, 121, 179, 108, + 230, 168, 69, 192, 66, 149, 4, 191, 41, 148, 130, 180, 175, 243, + 34, 98, 95, 53, 188, 56, 9, 107, 121, 6, 98, 139, 16, 54, + 55, 80, 202, 87, 32, 15, 154, 115, 153, 140, 10, 78, 205, 172, + 49, 193, 19, 239, 138, 189, 7, 253, 186, 18, 199, 107, 20, 210, + 125, 60, 21, 99, 169, 196, 165, 195, 1, 141, 74, 211, 212, 137, + 238, 133, 231, 181, 139, 6, 197, 149, 72, 212, 253, 165, 104, 130, + 176, 73, 15, 10, 223, 103, 112, 27, 23, 109, 150, 227, 105, 75, + 224, 42, 159, 143, 224, 31, 215, 54, 28, 225, 90, 224, 87, 59, + 220, 183, 91, 2, 122, 77, 216, 63, 217, 53, 63, 115, 41, 149, + 50, 47, 17, 158, 162, 56, 100, 1, 110, 63, 206, 46, 67, 226, + 166, 87, 2, 84, 47, 190, 47, 132, 206, 248, 143, 211, 172, 78, + 47, 49, 173, 103, 24, 208, 96, 99, 16, 192, 180, 199, 26, 49, + 159, 190, 101, 59, 98, 139, 38, 244, 55, 125, 158, 187, 117, 181, + 224, 151, 247, 89, 8, 139, 236, 213, 105, 223, 114, 128, 224, 178, + 159, 25, 14, 181, 220, 128, 108, 60, 132, 98, 28, 27, 155, 239, + 201, 159, 30, 215, 246, 98, 133, 212, 52, 98, 128, 147, 232, 9, + 83, 23, 13, 195, 227, 40, 246, 242, 85, 128, 64, 124, 197, 86, + 132, 213, 255, 138, 215, 99, 76, 124, 75, 224, 67, 111, 62, 244, + 14, 238, 199, 70, 208, 128, 198, 95, 219, 98, 27, 92, 18, 141, + 30, 185, 43, 116, 147, 62, 152, 16, 93, 186, 150, 214, 43, 123, + 126, 202, 17, 29, 250, 71, 244, 40, 45, 162, 60, 164, 235, 164, + 77, 136, 229, 241, 60, 33, 229, 122, 79, 39, 170, 60, 107, 3, + 37, 213, 181, 133, 236, 64, 46, 144, 175, 3, 102, 123, 189, 111, + 150, 85, 59, 246, 113, 108, 47, 203, 252, 153, 73, 166, 152, 120, + 220, 175, 241, 189, 21, 221, 167, 116, 213, 115, 170, 43, 140, 64, + 70, 75, 255, 230, 141, 210, 110, 14, 217, 129, 20, 92, 11, 27, + 86, 112, 223, 170, 121, 146, 135, 31, 77, 230, 249, 65, 89, 236, + 156, 69, 31, 228, 219, 11, 71, 4, 195, 46, 214, 209, 17, 86, + 108, 149, 113, 145, 17, 163, 200, 186, 180, 62, 81, 177, 240, 32, + 79, 156, 16, 87, 188, 43, 211, 161, 251, 95, 158, 13, 146, 30, + 208, 231, 100, 40, 175, 170, 186, 71, 94, 32, 186, 151, 38, 76, + 96, 22, 158, 168, 60, 87, 173, 140, 2, 71, 110, 246, 79, 84, + 132, 109, 121, 249, 145, 189, 244, 164, 153, 214, 118, 139, 9, 138, + 93, 59, 8, 44, 220, 254, 234, 14, 15, 93, 171, 219, 224, 174, + 17, 1, 238, 240, 38, 116, 150, 212, 18, 222, 27, 39, 72, 152, + 26, 175, 240, 161, 177, 16, 81, 154, 39, 152, 236, 2, 92, 57, + 40, 157, 180, 47, 15, 136, 42, 80, 51, 20, 18, 100, 199, 5, + 33, 94, 68, 173, 2, 238, 255, 101, 165, 2, 56, 118, 27, 124, + 107, 55, 236, 27, 130, 231, 1, 156, 154, 137, 151, 57, 251, 39, + 132, 76, 117, 151, 176, 132, 239, 26, 31, 100, 89, 123, 53, 42, + 108, 217, 35, 218, 130, 81, 186, 226, 143, 106, 67, 110, 182, 254, + 161, 163, 39, 52, 30, 250, 57, 14, 11, 109, 186, 238, 185, 246, + 101, 217, 34, 237, 172, 82, 30, 65, 191, 106, 190, 170, 190, 3, + 142, 78, 35, 39, 245, 121, 16, 48, 235, 96, 136, 225, 237, 196, + 25, 123, 3, 215, 44, 249, 126, 145, 96, 127, 228, 97, 233, 179, + 65, 128, 124, 87, 58, 92, 109, 30, 215, 70, 8, 215, 232, 51, + 250, 190, 5, 50, 213, 199, 142, 240, 174, 119, 34, 145, 146, 61, + 232, 5, 111, 142, 98, 161, 209, 36, 108, 241, 103, 53, 144, 126, + 41, 37, 81, 249, 12, 193, 181, 150, 219, 227, 59, 85, 101, 219, + 209, 236, 58, 136, 249, 196, 24, 55, 84, 213, 89, 61, 146, 146, + 68, 45, 191, 32, 251, 181, 134, 90, 58, 95, 124, 239, 182, 16, + 234, 47, 196, 145, 115, 78, 35, 145, 173, 180, 171, 240, 53, 111, + 25, 47, 245, 206, 148, 52, 235, 228, 89, 117, 91, 79, 93, 159, + 177, 78, 138, 55, 2, 14, 51, 117, 118, 207, 208, 71, 24, 243, + 84, 253, 26, 58, 242, 133, 114, 246, 147, 72, 138, 62, 229, 112, + 142, 66, 173, 238, 105, 214, 99, 224, 220, 126, 164, 47, 210, 46, + 182, 44, 187, 121, 66, 67, 88, 101, 254, 175, 13, 190, 20, 133, + 227, 141, 94, 141, 241, 226, 31, 160, 252, 166, 48, 33, 59, 140, + 138, 16, 135, 39, 123, 108, 107, 22, 216, 47, 233, 227, 58, 188, + 49, 159, 115, 118, 153, 118, 125, 79, 116, 164, 154, 242, 8, 230, + 71, 244, 126, 177, 115, 148, 2, 192, 40, 91, 209, 7, 37, 30, + 254, 241, 37, 71, 218, 154, 37, 114, 228, 205, 209, 237, 220, 162, + 86, 79, 122, 203, 119, 37, 201, 94, 92, 177, 60, 231, 99, 242, + 22, 114, 5, 119, 5, 163, 151, 203, 238, 160, 31, 6, 235, 146, + 143, 192, 51, 26, 222, 142, 248, 250, 79, 110, 247, 74, 8, 139, + 35, 218, 21, 193, 67, 248, 210, 109, 162, 101, 13, 211, 223, 52, + 37, 196, 5, 10, 145, 90, 67, 35, 143, 18, 191, 39, 212, 218, + 74, 31, 114, 128, 49, 252, 139, 135, 219, 109, 182, 52, 151, 36, + 178, 192, 252, 219, 196, 47, 245, 87, 73, 108, 69, 238, 19, 1, + 83, 222, 149, 83, 16, 252, 111, 188, 174, 14, 214, 44, 197, 174, + 152, 59, 125, 13, 31, 173, 191, 185, 191, 140, 243, 239, 87, 129, + 153, 153, 157, 59, 125, 111, 189, 0, 223, 67, 157, 124, 51, 33, + 202, 4, 81, 57, 13, 231, 60, 53, 51, 198, 254, 39, 70, 215, + 219, 226, 203, 61, 210, 187, 188, 249, 141, 247, 93, 57, 191, 79, + 29, 223, 195, 207, 91, 44, 19, 147, 169, 199, 148, 98, 184, 210, + 102, 7, 247, 178, 147, 75, 126, 81, 66, 52, 156, 166, 240, 126, + 200, 0, 52, 246, 154, 117, 101, 232, 53, 62, 175, 63, 135, 192, + 127, 195, 65, 198, 0, 196, 243, 58, 218, 0, 219, 81, 6, 126, + 125, 52, 84, 22, 223, 112, 5, 163, 93, 123, 109, 87, 183, 188, + 184, 5, 175, 199, 110, 12, 2, 118, 17, 190, 255, 3, 81, 20, + 10, 45, 65, 49, 135, 235, 212, 53, 37, 153, 122, 162, 190, 135, + 5, 116, 16, 45, 83, 48, 168, 236, 176, 52, 250, 240, 17, 8, + 40, 47, 123, 122, 50, 174, 232, 190, 196, 118, 49, 44, 136, 179, + 230, 80, 195, 253, 128, 5, 177, 148, 229, 155, 167, 81, 232, 188, + 35, 226, 87, 68, 151, 1, 36, 1, 164, 46, 197, 48, 155, 228, + 149, 13, 152, 61, 119, 232, 69, 131, 103, 210, 120, 203, 253, 116, + 51, 13, 188, 152, 129, 61, 187, 21, 13, 177, 193, 233, 136, 50, + 8, 95, 170, 17, 14, 102, 67, 122, 194, 212, 241, 209, 212, 145, + 189, 113, 76, 145, 177, 89, 73, 233, 27, 179, 177, 216, 183, 34, + 12, 208, 68, 130, 207, 147, 175, 62, 235, 135, 55, 44, 48, 242, + 93, 197, 131, 34, 217, 178, 250, 91, 155, 170, 142, 188, 101, 137, + 178, 197, 156, 41, 118, 179, 80, 194, 52, 235, 86, 240, 51, 238, + 218, 186, 224, 15, 14, 247, 36, 97, 33, 49, 97, 25, 172, 141, + 82, 220, 155, 80, 90, 45, 187, 95, 29, 208, 123, 27, 113, 2, + 10, 110, 66, 170, 206, 78, 24, 239, 43, 196, 208, 32, 34, 135, + 181, 45, 253, 66, 154, 132, 31, 151, 231, 32, 176, 158, 55, 53, + 103, 6, 50, 174, 121, 37, 97, 165, 200, 88, 220, 5, 136, 118, + 125, 21, 137, 75, 140, 48, 157, 103, 41, 83, 28, 31, 69, 30, + 224, 118, 226, 23, 108, 134, 197, 154, 201, 100, 231, 187, 162, 40, + 19, 117, 191, 81, 73, 213, 200, 211, 179, 101, 36, 220, 245, 51, + 233, 173, 28, 216, 138, 73, 129, 68, 138, 166, 215, 151, 10, 97, + 102, 117, 65, 2, 127, 81, 239, 166, 74, 224, 157, 61, 25, 243, + 70, 203, 48, 228, 242, 95, 86, 246, 196, 117, 224, 218, 194, 208, + 202, 118, 43, 109, 4, 89, 37, 208, 222, 59, 229, 96, 253, 14, + 240, 142, 173, 132, 187, 165, 10, 188, 250, 125, 128, 171, 122, 252, + 97, 100, 7, 124, 59, 47, 105, 165, 116, 175, 27, 140, 73, 175, + 34, 146, 115, 160, 85, 249, 198, 230, 175, 190, 246, 19, 63, 142, + 152, 121, 131, 101, 140, 33, 129, 128, 13, 254, 35, 83, 50, 198, + 184, 49, 83, 132, 243, 139, 159, 53, 220, 235, 201, 72, 116, 76, + 205, 46, 100, 47, 115, 163, 161, 161, 129, 192, 83, 90, 13, 225, + 138, 11, 148, 238, 138, 10, 92, 120, 132, 249, 161, 16, 228, 205, + 154, 181, 163, 13, 38, 23, 213, 236, 123, 1, 223, 227, 89, 5, + 184, 230, 99, 163, 242, 20, 2, 200, 47, 237, 209, 241, 222, 54, + 110, 65, 9, 87, 141, 183, 214, 8, 7, 50, 140, 139, 254, 121, + 46, 110, 185, 154, 199, 122, 135, 106, 121, 221, 224, 100, 215, 56, + 59, 49, 171, 69, 159, 128, 102, 54, 58, 173, 20, 34, 7, 131, + 114, 121, 205, 14, 6, 195, 185, 106, 116, 253, 71, 199, 121, 40, + 182, 117, 114, 58, 210, 149, 20, 64, 117, 234, 80, 127, 215, 73, + 112, 234, 203, 40, 54, 120, 220, 234, 113, 36, 65, 136, 14, 229, + 173, 101, 92, 84, 188, 91, 132, 153, 22, 119, 82, 44, 123, 227, + 171, 224, 85, 226, 1, 51, 140, 4, 46, 100, 253, 39, 100, 25, + 175, 216, 40, 187, 252, 93, 212, 197, 24, 223, 182, 99, 228, 81, + 3, 176, 18, 152, 195, 187, 67, 134, 24, 159, 51, 176, 163, 184, + 68, 106, 254, 158, 224, 22, 126, 69, 54, 164, 248, 27, 31, 131, + 250, 128, 83, 187, 72, 238, 230, 228, 95, 133, 247, 192, 103, 60, + 135, 100, 216, 209, 138, 141, 45, 67, 37, 181, 229, 94, 230, 225, + 145, 148, 100, 238, 59, 26, 16, 186, 215, 200, 17, 234, 238, 106, + 155, 165, 97, 201, 207, 4, 0, 104, 151, 57, 86, 47, 79, 232, + 145, 222, 73, 8, 212, 118, 168, 185, 52, 163, 1, 109, 255, 41, + 9, 99, 143, 78, 206, 9, 52, 96, 32, 101, 39, 218, 165, 201, + 139, 227, 187, 211, 162, 213, 73, 107, 249, 138, 6, 123, 34, 64, + 54, 220, 70, 187, 136, 109, 9, 119, 10, 6, 215, 225, 2, 135, + 118, 129, 86, 143, 6, 99, 52, 5, 151, 51, 45, 86, 187, 167, + 122, 224, 18, 24, 87, 83, 223, 142, 232, 37, 155, 110, 109, 33, + 99, 154, 91, 57, 43, 230, 212, 78, 23, 65, 74, 235, 86, 155, + 42, 211, 183, 30, 252, 106, 159, 181, 31, 8, 154, 154, 77, 36, + 204, 11, 65, 137, 79, 40, 154, 94, 56, 216, 161, 140, 42, 235, + 198, 112, 26, 145, 14, 247, 192, 188, 248, 31, 171, 46, 64, 9, + 105, 215, 166, 185, 227, 168, 56, 163, 157, 42, 167, 51, 212, 49, + 192, 98, 204, 116, 241, 82, 119, 89, 120, 159, 15, 122, 78, 126, + 24, 172, 157, 248, 227, 28, 56, 37, 147, 151, 125, 104, 25, 140, + 107, 161, 64, 105, 166, 62, 111, 24, 188, 71, 27, 81, 220, 16, + 174, 41, 201, 5, 77, 191, 199, 53, 255, 213, 83, 209, 254, 199, + 128, 184, 121, 186, 58, 41, 38, 190, 9, 21, 4, 67, 213, 225, + 0, 248, 208, 229, 184, 92, 210, 145, 165, 17, 138, 244, 79, 191, + 230, 109, 131, 153, 38, 170, 221, 140, 156, 98, 182, 200, 158, 112, + 46, 121, 73, 195, 226, 213, 58, 241, 53, 147, 79, 158, 232, 250, + 200, 240, 54, 79, 127, 111, 147, 1, 158, 217, 146, 14, 209, 53, + 53, 18, 10, 190, 255, 209, 142, 235, 196, 157, 177, 164, 229, 28, + 218, 91, 131, 58, 60, 76, 211, 200, 23, 60, 208, 193, 83, 63, + 65, 235, 239, 35, 169, 168, 179, 75, 93, 185, 79, 99, 72, 38, + 73, 41, 215, 87, 120, 37, 22, 231, 248, 164, 0, 181, 243, 100, + 49, 50, 131, 172, 138, 140, 9, 202, 78, 102, 109, 237, 79, 244, + 67, 81, 67, 181, 28, 85, 5, 62, 207, 5, 60, 44, 45, 110, + 148, 173, 63, 148, 245, 67, 173, 101, 205, 153, 156, 161, 42, 247, + 142, 224, 128, 170, 121, 240, 141, 220, 220, 254, 189, 113, 20, 132, + 21, 207, 163, 35, 220, 173, 104, 202, 106, 11, 75, 205, 126, 61, + 138, 145, 184, 191, 239, 13, 232, 194, 18, 17, 118, 28, 34, 236, + 13, 247, 54, 201, 119, 205, 79, 172, 239, 129, 190, 192, 196, 105, + 151, 255, 67, 221, 162, 0, 74, 165, 220, 238, 68, 202, 109, 193, + 11, 92, 109, 225, 151, 223, 212, 225, 227, 220, 233, 25, 119, 121, + 38, 224, 62, 254, 127, 234, 181, 233, 100, 62, 185, 69, 0, 205, + 238, 133, 141, 43, 111, 223, 223, 218, 65, 206, 14, 170, 196, 96, + 204, 29, 38, 55, 164, 136, 189, 52, 129, 47, 238, 198, 88, 106, + 223, 232, 66, 15, 176, 226, 102, 40, 255, 27, 49, 193, 45, 86, + 247, 178, 95, 145, 73, 199, 48, 194, 63, 20, 155, 105, 47, 142, + 119, 177, 159, 199, 174, 135, 82, 178, 79, 132, 243, 18, 16, 147, + 85, 113, 214, 117, 230, 78, 130, 226, 142, 116, 244, 76, 116, 61, + 221, 142, 72, 147, 120, 157, 248, 133, 66, 239, 195, 36, 237, 248, + 95, 219, 109, 92, 153, 172, 1, 169, 210, 174, 95, 194, 28, 2, + 77, 158, 77, 252, 193, 18, 158, 185, 94, 48, 83, 18, 74, 21, + 28, 179, 170, 82, 188, 172, 71, 52, 244, 68, 84, 46, 233, 163, + 218, 97, 119, 116, 147, 100, 202, 97, 4, 125, 23, 122, 118, 85, + 78, 73, 194, 14, 87, 232, 201, 182, 160, 9, 169, 3, 255, 229, + 92, 233, 135, 245, 58, 52, 233, 38, 143, 62, 109, 94, 123, 204, + 39, 27, 238, 48, 232, 111, 244, 85, 133, 252, 180, 119, 178, 191, + 205, 187, 187, 57, 120, 140, 177, 161, 7, 90, 251, 208, 206, 176, + 225, 17, 66, 162, 208, 9, 109, 174, 129, 233, 28, 136, 193, 80, + 19, 127, 248, 173, 112, 172, 153, 37, 216, 39, 17, 57, 251, 119, + 178, 197, 223, 62, 184, 87, 206, 178, 221, 116, 160, 57, 54, 37, + 54, 86, 60, 223, 184, 148, 10, 52, 205, 79, 68, 7, 233, 111, + 160, 191, 195, 66, 77, 62, 108, 173, 36, 237, 87, 13, 8, 96, + 235, 111, 220, 116, 65, 153, 14, 36, 157, 215, 119, 73, 187, 222, + 195, 106, 241, 90, 249, 22, 199, 96, 242, 240, 18, 199, 48, 143, + 143, 129, 8, 226, 137, 90, 39, 71, 41, 21, 132, 19, 27, 25, + 245, 102, 241, 248, 10, 189, 11, 86, 172, 168, 140, 87, 128, 215, + 34, 163, 182, 187, 182, 127, 16, 136, 13, 11, 179, 157, 224, 194, + 147, 247, 105, 233, 56, 67, 159, 54, 233, 121, 9, 85, 54, 106, + 174, 179, 214, 29, 222, 216, 103, 136, 55, 9, 29, 28, 241, 90, + 146, 55, 175, 8, 205, 172, 71, 76, 126, 96, 161, 130, 249, 128, + 123, 207, 65, 87, 56, 158, 187, 57, 60, 171, 172, 51, 149, 242, + 189, 129, 212, 203, 36, 220, 194, 198, 5, 250, 20, 198, 113, 225, + 111, 38, 140, 115, 2, 163, 59, 128, 128, 4, 11, 233, 33, 168, + 251, 145, 179, 75, 146, 68, 31, 215, 99, 153, 63, 163, 139, 87, + 82, 165, 39, 119, 175, 95, 218, 227, 157, 150, 49, 239, 128, 106, + 101, 232, 97, 130, 168, 83, 42, 21, 168, 196, 228, 161, 138, 126, + 12, 163, 220, 23, 139, 32, 229, 162, 237, 150, 32, 81, 86, 120, + 22, 0, 163, 225, 148, 252, 200, 212, 41, 28, 51, 234, 34, 176, + 54, 229, 247, 19, 243, 133, 219, 223, 168, 35, 58, 101, 163, 55, + 99, 5, 155, 84, 165, 97, 203, 40, 99, 222, 155, 38, 160, 29, + 37, 221, 167, 38, 63, 3, 21, 120, 42, 81, 98, 157, 190, 205, + 92, 73, 212, 176, 85, 95, 26, 75, 47, 36, 153, 132, 123, 66, + 151, 253, 205, 177, 17, 96, 164, 244, 179, 113, 205, 205, 189, 221, + 157, 177, 87, 165, 200, 90, 30, 233, 18, 166, 106, 249, 0, 10, + 159, 40, 217, 207, 227, 112, 87, 10, 31, 152, 202, 242, 116, 82, + 74, 169, 190, 55, 62, 105, 240, 101, 45, 224, 138, 122, 75, 155, + 202, 9, 98, 214, 0, 1, 10, 159, 1, 140, 225, 15, 243, 203, + 205, 25, 199, 81, 93, 234, 208, 179, 159, 154, 230, 249, 193, 156, + 64, 251, 126, 27, 216, 43, 103, 145, 118, 117, 247, 209, 60, 151, + 234, 75, 220, 80, 102, 29, 188, 0, 69, 113, 191, 179, 129, 105, + 217, 27, 92, 167, 191, 85, 231, 51, 168, 40, 137, 166, 47, 67, + 82, 4, 49, 138, 84, 235, 9, 159, 24, 69, 183, 157, 64, 159, + 207, 73, 168, 193, 30, 61, 11, 28, 12, 22, 202, 30, 50, 84, + 196, 85, 102, 57, 219, 185, 117, 11, 61, 229, 9, 220, 11, 225, + 198, 8, 239, 75, 149, 168, 64, 253, 120, 222, 158, 12, 34, 195, + 137, 156, 56, 30, 7, 214, 133, 154, 77, 125, 123, 122, 90, 175, + 116, 123, 207, 249, 157, 213, 69, 118, 109, 122, 210, 254, 75, 15, + 249, 244, 163, 143, 69, 124, 134, 202, 201, 185, 4, 137, 183, 7, + 18, 3, 122, 234, 243, 157, 190, 98, 91, 165, 229, 31, 11, 209, + 81, 2, 15, 204, 210, 185, 178, 188, 142, 252, 247, 173, 154, 213, + 100, 198, 198, 15, 53, 171, 212, 135, 54, 218, 117, 57, 213, 71, + 58, 85, 79, 40, 176, 84, 66, 140, 246, 165, 68, 214, 158, 52, + 129, 176, 195, 56, 72, 32, 219, 238, 74, 236, 17, 11, 114, 142, + 139, 189, 94, 97, 251, 108, 186, 119, 253, 57, 118, 99, 236, 161, + 228, 220, 28, 69, 242, 54, 93, 5, 149, 33, 167, 16, 74, 168, + 1, 135, 107, 214, 191, 105, 197, 232, 202, 141, 69, 230, 24, 69, + 83, 50, 45, 119, 39, 129, 50, 188, 244, 68, 249, 78, 197, 102, + 19, 170, 188, 75, 182, 83, 149, 94, 117, 170, 235, 254, 153, 204, + 73, 243, 165, 210, 76, 94, 213, 183, 220, 166, 8, 111, 135, 220, + 98, 92, 182, 168, 69, 173, 238, 243, 96, 59, 54, 182, 154, 209, + 19, 6, 110, 155, 6, 64, 185, 246, 21, 211, 128, 120, 91, 179, + 213, 226, 16, 4, 254, 68, 66, 231, 128, 134, 107, 83, 5, 186, + 115, 243, 54, 186, 129, 113, 185, 250, 246, 80, 146, 67, 35, 146, + 145, 216, 214, 43, 18, 244, 191, 59, 4, 188, 94, 16, 145, 228, + 90, 132, 211, 38, 79, 91, 24, 66, 130, 3, 107, 32, 56, 206, + 192, 12, 251, 97, 142, 247, 198, 147, 137, 55, 56, 96, 115, 243, + 170, 168, 8, 47, 56, 241, 51, 106, 130, 156, 61, 128, 228, 230, + 222, 84, 81, 39, 180, 243, 59, 25, 216, 4, 31, 79, 201, 95, + 10, 47, 245, 39, 12, 40, 53, 29, 113, 44, 6, 117, 254, 209, + 40, 30, 214, 192, 9, 6, 244, 20, 224, 158, 63, 84, 168, 253, + 221, 248, 70, 218, 24, 236, 103, 131, 127, 74, 109, 57, 97, 224, + 184, 2, 43, 54, 237, 187, 251, 85, 44, 155, 149, 195, 24, 237, + 190, 191, 24, 164, 19, 36, 191, 32, 223, 150, 90, 118, 206, 196, + 240, 208, 188, 133, 138, 40, 40, 254, 45, 120, 192, 139, 174, 163, + 72, 25, 51, 193, 73, 39, 177, 158, 10, 91, 84, 31, 236, 122, + 210, 147, 13, 208, 12, 236, 246, 35, 35, 175, 9, 168, 45, 97, + 95, 44, 153, 120, 111, 101, 248, 57, 75, 48, 203, 160, 221, 2, + 11, 61, 252, 25, 103, 147, 1, 237, 12, 154, 180, 19, 26, 226, + 118, 98, 210, 210, 38, 255, 17, 197, 53, 39, 23, 192, 234, 63, + 22, 191, 24, 154, 140, 17, 71, 208, 238, 248, 125, 135, 27, 92, + 0, 180, 225, 246, 14, 254, 249, 27, 183, 125, 86, 166, 91, 178, + 151, 168, 199, 178, 220, 212, 111, 32, 55, 167, 12, 30, 14, 159, + 166, 36, 190, 209, 147, 142, 122, 121, 30, 219, 172, 247, 189, 55, + 103, 187, 252, 78, 154, 71, 138, 108, 232, 178, 126, 76, 24, 152, + 206, 112, 195, 36, 213, 169, 212, 161, 145, 101, 6, 48, 34, 28, + 197, 165, 31, 144, 87, 196, 12, 204, 214, 27, 191, 248, 75, 16, + 111, 98, 50, 190, 57, 166, 47, 31, 2, 170, 212, 221, 31, 129, + 176, 247, 57, 250, 64, 228, 120, 53, 169, 61, 220, 71, 241, 234, + 175, 177, 65, 76, 176, 252, 157, 222, 246, 29, 89, 224, 198, 120, + 161, 175, 158, 13, 125, 174, 141, 135, 203, 64, 155, 149, 174, 47, + 130, 110, 124, 144, 192, 56, 78, 26, 123, 38, 217, 12, 248, 108, + 171, 251, 205, 14, 196, 153, 217, 180, 208, 128, 62, 161, 78, 209, + 12, 3, 81, 69, 28, 148, 187, 182, 183, 153, 73, 253, 198, 90, + 47, 180, 152, 13, 203, 78, 146, 239, 40, 184, 134, 158, 228, 60, + 111, 31, 211, 19, 223, 84, 0, 97, 202, 12, 187, 235, 71, 143, + 166, 41, 28, 48, 125, 244, 85, 213, 13, 51, 23, 255, 71, 235, + 51, 73, 133, 21, 20, 149, 255, 25, 6, 181, 144, 242, 119, 114, + 146, 252, 25, 200, 255, 24, 245, 242, 93, 72, 99, 94, 242, 188, + 6, 91, 8, 60, 243, 175, 244, 38, 40, 9, 192, 239, 72, 120, + 98, 110, 230, 241, 17, 250, 147, 40, 13, 252, 53, 59, 155, 7, + 198, 98, 209, 118, 26, 94, 150, 18, 16, 39, 129, 240, 221, 178, + 242, 18, 137, 2, 161, 18, 63, 162, 23, 2, 238, 247, 92, 158, + 161, 227, 79, 188, 119, 61, 63, 144, 124, 175, 86, 103, 82, 101, + 96, 148, 57, 136, 145, 51, 53, 204, 52, 30, 246, 249, 104, 60, + 168, 129, 100, 44, 120, 84, 138, 11, 104, 239, 209, 222, 184, 135, + 112, 83, 84, 89, 198, 0, 79, 117, 171, 214, 37, 109, 188, 85, + 168, 229, 126, 245, 62, 233, 80, 48, 34, 46, 62, 152, 163, 203, + 62, 151, 122, 40, 71, 242, 61, 173, 234, 241, 222, 1, 236, 44, + 226, 173, 191, 153, 50, 102, 20, 60, 165, 241, 252, 243, 103, 223, + 228, 94, 133, 79, 235, 218, 35, 205, 24, 211, 166, 248, 241, 18, + 79, 170, 159, 132, 225, 33, 91, 125, 161, 76, 112, 152, 125, 243, + 60, 134, 149, 113, 22, 63, 71, 187, 170, 10, 119, 154, 134, 147, + 79, 163, 44, 17, 182, 49, 115, 33, 182, 102, 161, 253, 49, 56, + 145, 7, 122, 145, 222, 79, 190, 215, 34, 201, 8, 156, 164, 48, + 163, 38, 18, 9, 5, 76, 21, 128, 17, 176, 61, 164, 56, 18, + 73, 52, 78, 68, 70, 183, 220, 193, 190, 214, 135, 179, 24, 52, + 75, 162, 54, 192, 134, 125, 147, 195, 175, 88, 25, 155, 26, 98, + 92, 238, 9, 61, 136, 241, 166, 111, 12, 35, 101, 186, 15, 213, + 18, 99, 217, 218, 233, 234, 191, 63, 140, 219, 71, 133, 81, 20, + 219, 55, 104, 4, 84, 119, 214, 118, 80, 78, 71, 197, 68, 76, + 159, 155, 173, 210, 141, 163, 34, 10, 157, 234, 141, 129, 239, 205, + 108, 43, 37, 156, 254, 92, 144, 101, 87, 227, 100, 69, 184, 152, + 127, 83, 157, 123, 119, 164, 148, 127, 151, 63, 191, 186, 173, 104, + 9, 162, 197, 94, 75, 218, 154, 230, 219, 213, 145, 48, 246, 215, + 62, 31, 82, 119, 176, 61, 74, 125, 21, 123, 94, 216, 207, 167, + 63, 161, 20, 197, 194, 59, 106, 80, 187, 46, 73, 59, 35, 194, + 245, 18, 43, 28, 80, 185, 69, 66, 242, 194, 48, 68, 90, 242, + 246, 122, 80, 189, 46, 182, 68, 72, 220, 116, 6, 9, 194, 64, + 35, 102, 251, 211, 231, 103, 47, 246, 167, 247, 116, 231, 179, 253, + 116, 153, 233, 52, 222, 111, 103, 168, 141, 188, 225, 19, 110, 182, + 78, 28, 79, 131, 62, 23, 124, 125, 39, 49, 57, 112, 98, 63, + 168, 53, 26, 82, 50, 192, 169, 50, 93, 75, 129, 75, 91, 138, + 194, 87, 210, 232, 103, 217, 25, 195, 124, 223, 162, 101, 129, 60, + 170, 101, 4, 18, 162, 98, 79, 145, 121, 177, 207, 13, 26, 43, + 246, 5, 240, 34, 124, 109, 204, 116, 73, 32, 185, 46, 198, 98, + 180, 36, 242, 40, 60, 236, 239, 159, 39, 9, 68, 119, 247, 194, + 54, 141, 66, 132, 186, 75, 107, 252, 101, 41, 45, 165, 0, 74, + 232, 216, 39, 183, 109, 131, 24, 117, 86, 187, 130, 237, 237, 23, + 129, 117, 115, 9, 34, 209, 159, 185, 11, 142, 196, 33, 133, 18, + 141, 100, 89, 163, 54, 59, 26, 239, 5, 225, 247, 188, 149, 150, + 250, 84, 108, 135, 21, 97, 199, 114, 159, 88, 82, 98, 37, 193, + 199, 182, 103, 126, 13, 197, 232, 86, 208, 14, 82, 113, 209, 95, + 43, 196, 2, 128, 27, 255, 124, 192, 158, 220, 214, 175, 158, 50, + 191, 141, 72, 197, 147, 146, 76, 59, 4, 88, 162, 124, 132, 111, + 218, 5, 23, 144, 26, 1, 2, 63, 205, 208, 199, 235, 126, 139, + 168, 194, 13, 188, 106, 199, 79, 149, 163, 132, 4, 238, 151, 145, + 113, 108, 218, 69, 235, 9, 101, 194, 129, 236, 195, 68, 67, 187, + 197, 100, 67, 248, 6, 135, 50, 188, 173, 255, 4, 176, 83, 248, + 191, 206, 104, 48, 176, 226, 65, 174, 24, 11, 116, 61, 6, 159, + 7, 84, 242, 92, 92, 99, 131, 84, 27, 218, 104, 97, 40, 90, + 88, 148, 15, 64, 105, 125, 230, 65, 234, 56, 56, 231, 59, 114, + 73, 182, 67, 158, 245, 245, 3, 93, 115, 191, 200, 141, 116, 172, + 98, 20, 43, 122, 226, 170, 196, 84, 191, 158, 234, 129, 165, 157, + 8, 30, 35, 136, 134, 255, 160, 153, 105, 158, 207, 151, 61, 255, + 126, 99, 120, 90, 89, 47, 169, 73, 181, 243, 220, 37, 152, 229, + 135, 180, 60, 95, 167, 149, 74, 239, 207, 140, 186, 181, 195, 79, + 106, 148, 66, 87, 10, 205, 64, 251, 239, 208, 25, 2, 59, 187, + 114, 19, 148, 152, 202, 224, 5, 69, 177, 178, 37, 185, 58, 98, + 16, 184, 60, 224, 228, 100, 85, 139, 140, 109, 109, 30, 94, 209, + 39, 224, 225, 242, 138, 215, 2, 189, 212, 170, 22, 205, 123, 217, + 80, 8, 235, 235, 184, 200, 62, 174, 255, 58, 10, 195, 5, 100, + 153, 114, 64, 194, 240, 188, 239, 35, 203, 3, 202, 33, 19, 144, + 136, 14, 117, 104, 3, 107, 115, 48, 203, 212, 243, 182, 85, 66, + 170, 42, 190, 24, 28, 157, 224, 159, 169, 116, 120, 179, 181, 7, + 139, 133, 133, 134, 248, 51, 67, 216, 64, 159, 215, 131, 161, 7, + 96, 189, 103, 221, 105, 103, 206, 60, 247, 33, 45, 204, 111, 135, + 191, 197, 110, 148, 202, 252, 48, 219, 235, 10, 12, 141, 189, 49, + 90, 24, 32, 232, 146, 128, 217, 65, 136, 124, 236, 66, 88, 123, + 147, 231, 56, 131, 175, 124, 143, 87, 81, 84, 19, 53, 57, 3, + 217, 62, 42, 64, 165, 20, 126, 238, 194, 254, 59, 66, 69, 136, + 70, 193, 130, 178, 16, 41, 120, 108, 20, 75, 137, 22, 202, 66, + 115, 212, 125, 229, 79, 40, 113, 119, 30, 67, 94, 113, 8, 101, + 86, 185, 141, 8, 167, 207, 140, 217, 86, 87, 128, 200, 112, 147, + 150, 151, 192, 46, 19, 232, 11, 99, 192, 249, 3, 222, 215, 17, + 97, 149, 128, 249, 22, 69, 215, 99, 191, 118, 41, 38, 42, 129, + 153, 211, 85, 251, 179, 10, 81, 98, 59, 220, 102, 102, 14, 63, + 80, 217, 188, 227, 206, 113, 230, 43, 162, 158, 250, 102, 100, 127, + 198, 104, 147, 189, 83, 114, 26, 241, 42, 24, 74, 103, 231, 132, + 206, 107, 38, 190, 233, 165, 116, 41, 55, 106, 23, 69, 178, 36, + 97, 40, 41, 33, 234, 103, 116, 146, 168, 94, 7, 36, 5, 89, + 153, 110, 119, 252, 66, 231, 211, 22, 231, 201, 164, 80, 150, 87, + 183, 23, 24, 15, 49, 135, 83, 207, 203, 183, 106, 42, 52, 30, + 171, 99, 79, 66, 52, 85, 149, 84, 158, 220, 22, 222, 116, 54, + 92, 49, 95, 37, 8, 157, 176, 22, 251, 140, 108, 188, 115, 75, + 168, 126, 200, 186, 230, 227, 64, 45, 84, 176, 4, 73, 124, 229, + 68, 135, 90, 3, 137, 107, 33, 252, 95, 227, 193, 113, 99, 96, + 235, 125, 56, 69, 108, 107, 252, 196, 203, 22, 182, 105, 34, 80, + 44, 252, 93, 174, 24, 30, 212, 91, 198, 110, 119, 128, 199, 55, + 159, 165, 180, 231, 54, 246, 171, 226, 148, 80, 47, 126, 111, 33, + 134, 106, 73, 121, 48, 127, 138, 83, 223, 101, 107, 241, 178, 32, + 22, 170, 210, 117, 109, 17, 226, 233, 249, 60, 204, 158, 23, 229, + 12, 208, 35, 171, 166, 112, 177, 202, 207, 103, 225, 157, 253, 230, + 76, 38, 222, 222, 248, 162, 203, 211, 199, 222, 230, 156, 139, 183, + 104, 25, 139, 194, 70, 80, 207, 52, 237, 164, 237, 202, 237, 105, + 156, 241, 164, 207, 114, 211, 59, 47, 145, 209, 252, 205, 26, 72, + 125, 44, 120, 126, 75, 126, 7, 211, 230, 162, 247, 246, 232, 217, + 169, 58, 16, 135, 58, 218, 224, 85, 244, 36, 44, 196, 0, 204, + 107, 174, 83, 163, 202, 250, 112, 42, 214, 232, 205, 129, 239, 96, + 190, 31, 169, 165, 140, 130, 159, 229, 28, 137, 231, 245, 246, 121, + 111, 108, 70, 45, 210, 242, 204, 29, 169, 213, 6, 163, 156, 140, + 50, 29, 115, 107, 38, 151, 175, 222, 141, 242, 86, 28, 198, 108, + 96, 11, 130, 159, 238, 14, 13, 171, 124, 25, 222, 110, 147, 27, + 131, 179, 108, 16, 148, 68, 230, 12, 83, 119, 108, 94, 192, 236, + 63, 209, 253, 99, 182, 158, 204, 86, 180, 20, 59, 91, 166, 36, + 219, 246, 0, 250, 121, 99, 109, 120, 103, 59, 86, 211, 174, 220, + 232, 62, 242, 155, 217, 144, 114, 119, 201, 192, 15, 187, 129, 104, + 179, 41, 184, 165, 113, 31, 93, 19, 102, 120, 209, 201, 28, 203, + 80, 108, 241, 30, 18, 19, 79, 135, 132, 176, 146, 234, 109, 26, + 48, 115, 178, 65, 146, 109, 207, 47, 18, 215, 77, 97, 150, 70, + 177, 83, 67, 123, 54, 146, 119, 175, 117, 253, 36, 240, 156, 175, + 94, 125, 11, 172, 86, 149, 55, 73, 93, 114, 219, 244, 140, 65, + 33, 129, 122, 247, 4, 239, 9, 220, 177, 195, 33, 20, 129, 197, + 199, 31, 129, 168, 136, 201, 214, 114, 122, 205, 199, 169, 136, 78, + 113, 4, 18, 53, 223, 211, 156, 229, 26, 83, 90, 36, 21, 120, + 243, 24, 142, 161, 83, 65, 35, 19, 125, 227, 50, 18, 76, 222, + 99, 212, 45, 166, 137, 120, 93, 67, 124, 153, 201, 30, 66, 190, + 181, 193, 147, 83, 224, 252, 143, 29, 190, 168, 32, 220, 239, 4, + 99, 204, 241, 46, 17, 99, 69, 38, 93, 34, 97, 218, 51, 127, + 43, 2, 215, 65, 16, 178, 14, 190, 235, 147, 142, 124, 66, 171, + 35, 195, 36, 190, 86, 106, 15, 18, 217, 227, 12, 4, 230, 172, + 205, 205, 59, 239, 134, 49, 149, 122, 31, 20, 228, 167, 11, 228, + 215, 6, 15, 187, 69, 104, 27, 90, 192, 33, 225, 176, 169, 183, + 159, 225, 147, 204, 165, 152, 213, 50, 252, 249, 216, 240, 145, 91, + 8, 203, 59, 194, 113, 244, 171, 216, 242, 125, 213, 56, 237, 12, + 76, 193, 78, 145, 90, 120, 45, 110, 229, 113, 125, 43, 229, 194, + 6, 224, 245, 200, 92, 36, 176, 163, 210, 213, 104, 95, 184, 235, + 124, 15, 36, 16, 251, 50, 8, 89, 59, 41, 237, 255, 216, 204, + 80, 192, 238, 226, 201, 208, 167, 198, 55, 251, 152, 44, 157, 239, + 180, 210, 202, 121, 214, 226, 64, 7, 44, 39, 47, 214, 203, 183, + 124, 60, 3, 23, 104, 181, 130, 191, 109, 49, 116, 95, 135, 156, + 129, 164, 122, 71, 139, 26, 80, 75, 250, 5, 27, 225, 7, 46, + 61, 45, 84, 119, 146, 93, 226, 102, 75, 151, 3, 10, 32, 198, + 67, 75, 34, 184, 155, 106, 6, 214, 53, 234, 118, 12, 111, 21, + 235, 18, 106, 26, 103, 40, 49, 79, 123, 31, 44, 84, 34, 171, + 215, 15, 17, 90, 212, 33, 23, 201, 216, 245, 133, 122, 249, 205, + 26, 216, 118, 159, 36, 88, 213, 39, 202, 149, 6, 148, 42, 202, + 11, 110, 27, 231, 153, 161, 95, 237, 179, 176, 123, 158, 40, 6, + 171, 113, 201, 140, 150, 204, 86, 95, 64, 112, 237, 157, 226, 177, + 99, 135, 146, 202, 238, 69, 139, 89, 113, 76, 170, 158, 183, 177, + 155, 29, 129, 57, 22, 211, 13, 77, 205, 178, 100, 49, 120, 24, + 89, 250, 81, 214, 31, 59, 84, 194, 78, 66, 128, 12, 175, 195, + 133, 92, 243, 178, 146, 34, 177, 227, 181, 67, 7, 209, 73, 204, + 20, 106, 87, 234, 186, 85, 234, 136, 127, 85, 18, 45, 227, 105, + 166, 251, 246, 41, 218, 35, 115, 148, 174, 183, 93, 192, 246, 198, + 148, 225, 68, 82, 88, 6, 106, 250, 145, 210, 225, 88, 2, 21, + 222, 3, 117, 9, 98, 108, 38, 196, 180, 214, 249, 33, 4, 186, + 65, 228, 247, 32, 238, 156, 136, 7, 237, 235, 163, 233, 222, 231, + 11, 76, 51, 183, 23, 242, 55, 102, 19, 163, 241, 250, 138, 210, + 190, 210, 6, 67, 61, 168, 246, 156, 228, 109, 44, 250, 113, 157, + 231, 70, 213, 115, 105, 173, 190, 62, 72, 33, 226, 138, 55, 41, + 73, 117, 49, 27, 50, 128, 200, 174, 130, 78, 127, 179, 251, 6, + 163, 221, 85, 171, 30, 60, 217, 4, 87, 56, 31, 230, 215, 145, + 222, 166, 243, 44, 44, 228, 21, 18, 110, 161, 118, 204, 13, 150, + 73, 189, 68, 70, 37, 12, 156, 11, 141, 253, 168, 222, 166, 70, + 30, 172, 209, 107, 122, 246, 56, 109, 106, 232, 185, 73, 22, 219, + 253, 115, 199, 181, 249, 14, 135, 233, 88, 183, 153, 44, 112, 171, + 133, 18, 51, 171, 116, 92, 97, 27, 126, 217, 29, 173, 234, 192, + 28, 170, 68, 88, 223, 21, 201, 33, 89, 115, 139, 171, 55, 46, + 46, 47, 201, 69, 196, 150, 215, 25, 105, 205, 193, 253, 12, 35, + 132, 10, 25, 149, 50, 115, 107, 187, 14, 82, 203, 169, 69, 254, + 96, 78, 102, 78, 232, 69, 58, 210, 132, 136, 146, 109, 240, 155, + 17, 248, 90, 227, 246, 188, 236, 41, 178, 254, 0, 219, 108, 169, + 69, 200, 173, 244, 40, 195, 171, 18, 107, 167, 11, 93, 205, 145, + 104, 103, 83, 163, 121, 33, 253, 147, 224, 193, 69, 184, 244, 234, + 104, 4, 65, 36, 253, 175, 228, 164, 51, 72, 87, 227, 120, 105, + 21, 150, 168, 127, 87, 115, 231, 57, 194, 207, 32, 201, 35, 34, + 68, 155, 77, 100, 224, 169, 155, 214, 89, 117, 119, 192, 154, 173, + 69, 53, 35, 170, 57, 191, 24, 15, 45, 60, 30, 176, 3, 132, + 127, 142, 215, 220, 127, 95, 185, 238, 36, 163, 24, 160, 240, 253, + 40, 127, 221, 45, 5, 106, 162, 88, 185, 144, 28, 197, 120, 216, + 18, 139, 175, 105, 253, 163, 67, 141, 46, 113, 87, 57, 80, 229, + 187, 142, 133, 16, 237, 66, 141, 229, 55, 239, 47, 143, 168, 33, + 236, 243, 61, 58, 168, 209, 247, 14, 50, 55, 37, 253, 189, 158, + 168, 63, 86, 14, 1, 53, 2, 62, 231, 99, 251, 84, 133, 231, + 52, 176, 38, 225, 56, 178, 11, 182, 157, 46, 7, 215, 139, 178, + 49, 203, 59, 40, 120, 224, 87, 34, 87, 169, 201, 93, 74, 0, + 40, 187, 248, 38, 200, 74, 207, 38, 8, 176, 91, 83, 208, 223, + 129, 168, 4, 115, 94, 159, 162, 196, 242, 62, 117, 248, 34, 38, + 181, 185, 129, 19, 202, 69, 215, 214, 168, 221, 127, 4, 250, 8, + 199, 160, 143, 144, 194, 215, 122, 163, 36, 4, 32, 35, 169, 152, + 10, 125, 27, 117, 142, 34, 149, 131, 120, 202, 249, 14, 69, 218, + 37, 172, 77, 217, 176, 183, 243, 8, 48, 81, 155, 52, 112, 13, + 18, 204, 236, 37, 98, 63, 124, 17, 91, 71, 66, 97, 27, 219, + 184, 83, 157, 126, 170, 125, 149, 193, 188, 136, 240, 205, 249, 224, + 112, 166, 21, 172, 136, 114, 87, 108, 76, 42, 162, 246, 120, 236, + 104, 185, 112, 173, 238, 72, 112, 209, 85, 81, 250, 1, 38, 205, + 126, 164, 38, 122, 55, 35, 225, 103, 87, 190, 149, 118, 236, 195, + 80, 149, 81, 171, 50, 149, 152, 223, 172, 251, 155, 249, 107, 198, + 111, 111, 53, 146, 237, 86, 10, 245, 205, 60, 186, 173, 217, 124, + 76, 127, 66, 100, 195, 49, 246, 202, 164, 216, 101, 84, 119, 110, + 66, 91, 72, 247, 63, 19, 116, 5, 228, 101, 73, 187, 205, 159, + 49, 83, 152, 146, 209, 137, 233, 101, 190, 159, 39, 223, 16, 145, + 77, 95, 171, 29, 158, 107, 202, 145, 62, 60, 169, 102, 102, 147, + 133, 8, 118, 29, 218, 20, 227, 167, 114, 44, 67, 234, 196, 227, + 255, 152, 131, 109, 142, 252, 233, 240, 21, 48, 4, 18, 35, 95, + 153, 44, 240, 78, 164, 74, 154, 117, 11, 59, 236, 204, 118, 138, + 240, 192, 133, 213, 252, 135, 64, 142, 195, 25, 72, 114, 56, 111, + 27, 94, 192, 5, 167, 150, 12, 227, 123, 90, 152, 143, 131, 193, + 92, 225, 116, 140, 28, 159, 61, 186, 84, 25, 233, 60, 195, 51, + 23, 104, 43, 22, 42, 30, 149, 93, 117, 154, 67, 146, 85, 235, + 44, 48, 132, 148, 137, 124, 18, 80, 108, 36, 165, 240, 211, 179, + 164, 159, 77, 121, 249, 129, 45, 200, 95, 35, 43, 246, 84, 68, + 83, 185, 154, 94, 247, 36, 247, 16, 103, 157, 209, 133, 176, 4, + 99, 168, 2, 116, 40, 107, 202, 44, 187, 61, 103, 50, 96, 140, + 193, 91, 209, 23, 156, 104, 229, 81, 132, 24, 55, 195, 90, 1, + 231, 0, 237, 212, 211, 148, 222, 164, 17, 5, 133, 28, 14, 137, + 44, 164, 7, 80, 160, 230, 196, 82, 180, 27, 222, 123, 43, 59, + 21, 249, 128, 183, 174, 195, 129, 24, 111, 45, 161, 125, 57, 176, + 14, 175, 119, 237, 190, 217, 179, 155, 121, 194, 87, 203, 210, 121, + 115, 209, 87, 15, 67, 43, 56, 38, 226, 146, 244, 30, 52, 112, + 249, 188, 247, 212, 157, 18, 142, 49, 178, 221, 176, 29, 78, 51, + 254, 40, 110, 80, 182, 5, 198, 92, 195, 106, 217, 28, 226, 44, + 157, 215, 197, 222, 240, 168, 66, 224, 114, 212, 116, 225, 82, 93, + 108, 85, 59, 120, 90, 233, 141, 135, 229, 173, 146, 106, 32, 197, + 246, 82, 245, 43, 19, 217, 191, 200, 2, 126, 185, 237, 248, 6, + 28, 37, 144, 83, 6, 115, 207, 124, 72, 225, 196, 125, 41, 83, + 40, 129, 221, 134, 146, 120, 3, 198, 120, 100, 168, 137, 254, 90, + 146, 242, 162, 53, 207, 111, 137, 251, 133, 161, 206, 43, 213, 203, + 118, 29, 41, 21, 135, 25, 185, 233, 54, 146, 141, 39, 79, 143, + 148, 164, 172, 231, 185, 0, 102, 83, 207, 11, 127, 17, 89, 88, + 185, 190, 31, 185, 246, 29, 117, 237, 140, 241, 77, 103, 17, 97, + 75, 192, 114, 0, 255, 73, 37, 207, 222, 87, 172, 126, 240, 202, + 96, 35, 240, 153, 64, 159, 131, 162, 173, 188, 218, 108, 124, 99, + 206, 234, 225, 87, 13, 122, 158, 105, 200, 218, 240, 62, 228, 193, + 77, 162, 238, 75, 27, 10, 235, 87, 243, 198, 230, 75, 201, 124, + 235, 79, 248, 112, 50, 141, 33, 76, 116, 47, 253, 57, 144, 128, + 35, 235, 151, 144, 36, 194, 113, 155, 33, 18, 34, 240, 184, 139, + 249, 4, 11, 158, 18, 222, 5, 119, 5, 176, 23, 48, 180, 35, + 180, 213, 228, 195, 23, 218, 46, 254, 196, 238, 248, 205, 97, 12, + 86, 64, 108, 43, 174, 206, 51, 84, 165, 11, 217, 212, 30, 89, + 207, 79, 77, 216, 224, 195, 180, 235, 143, 144, 217, 239, 7, 3, + 140, 111, 172, 99, 34, 90, 255, 83, 60, 215, 72, 102, 56, 43, + 187, 128, 163, 69, 126, 95, 1, 28, 194, 59, 154, 64, 217, 185, + 179, 25, 159, 161, 58, 197, 197, 232, 232, 127, 151, 163, 214, 79, + 41, 90, 239, 0, 18, 227, 115, 16, 255, 32, 188, 182, 171, 144, + 252, 147, 101, 197, 17, 81, 101, 209, 107, 29, 239, 236, 170, 233, + 102, 118, 220, 189, 64, 10, 116, 100, 65, 124, 88, 234, 50, 198, + 156, 238, 234, 8, 13, 24, 7, 179, 47, 42, 255, 19, 155, 64, + 165, 250, 183, 96, 31, 45, 95, 234, 172, 114, 168, 134, 230, 129, + 230, 206, 79, 185, 30, 27, 58, 198, 97, 151, 124, 45, 198, 112, + 212, 147, 53, 60, 18, 203, 138, 36, 84, 71, 32, 47, 33, 27, + 8, 48, 0, 71, 201, 7, 89, 176, 191, 60, 152, 63, 35, 24, + 46, 196, 7, 165, 4, 116, 199, 235, 87, 48, 165, 227, 97, 131, + 22, 70, 157, 75, 157, 239, 31, 5, 159, 242, 183, 25, 252, 112, + 189, 152, 255, 168, 164, 9, 243, 98, 82, 73, 122, 9, 30, 80, + 113, 101, 130, 115, 40, 232, 152, 37, 41, 145, 129, 179, 139, 7, + 115, 243, 163, 17, 159, 58, 142, 255, 4, 115, 127, 118, 251, 245, + 57, 105, 133, 210, 105, 170, 208, 144, 99, 12, 150, 215, 231, 119, + 13, 106, 215, 10, 119, 151, 206, 156, 228, 39, 113, 162, 46, 100, + 128, 42, 77, 115, 25, 65, 48, 169, 28, 37, 55, 118, 180, 115, + 214, 44, 54, 128, 170, 123, 239, 84, 225, 212, 214, 20, 238, 170, + 240, 110, 249, 20, 248, 45, 72, 168, 110, 35, 221, 26, 41, 243, + 226, 176, 186, 153, 185, 97, 15, 88, 219, 232, 141, 64, 223, 39, + 113, 235, 110, 215, 216, 242, 2, 236, 42, 158, 136, 28, 205, 99, + 202, 31, 10, 247, 214, 174, 40, 110, 254, 219, 21, 106, 247, 223, + 84, 25, 25, 71, 40, 88, 21, 90, 101, 204, 133, 200, 93, 149, + 156, 16, 81, 194, 68, 162, 99, 81, 17, 190, 82, 142, 55, 57, + 113, 86, 198, 54, 152, 127, 64, 195, 1, 88, 39, 105, 64, 120, + 68, 202, 93, 200, 96, 113, 101, 129, 22, 25, 248, 14, 126, 231, + 123, 199, 43, 122, 227, 48, 75, 21, 16, 63, 206, 69, 75, 100, + 196, 55, 237, 24, 192, 184, 245, 18, 1, 242, 144, 87, 50, 252, + 217, 237, 79, 52, 171, 147, 83, 150, 232, 170, 61, 248, 13, 239, + 148, 228, 208, 12, 166, 38, 23, 118, 14, 67, 37, 95, 20, 16, + 182, 157, 64, 86, 11, 156, 212, 169, 235, 67, 253, 140, 196, 195, + 240, 145, 5, 67, 215, 223, 71, 67, 123, 160, 90, 72, 255, 154, + 164, 98, 130, 158, 121, 91, 178, 238, 43, 24, 160, 89, 134, 163, + 0, 233, 139, 141, 55, 135, 35, 93, 85, 50, 227, 52, 178, 150, + 29, 220, 94, 152, 154, 82, 217, 146, 254, 218, 108, 251, 245, 34, + 115, 19, 171, 185, 131, 157, 10, 48, 226, 32, 14, 22, 186, 127, + 47, 2, 159, 198, 73, 103, 52, 7, 101, 233, 162, 83, 174, 208, + 96, 218, 171, 23, 234, 6, 25, 28, 245, 250, 248, 162, 166, 217, + 51, 126, 167, 111, 78, 136, 1, 218, 80, 215, 200, 174, 232, 228, + 8, 84, 178, 56, 127, 75, 246, 124, 103, 13, 187, 14, 171, 54, + 184, 75, 229, 73, 213, 46, 145, 181, 95, 174, 29, 102, 169, 178, + 128, 75, 224, 167, 16, 188, 192, 3, 244, 5, 87, 224, 216, 93, + 239, 73, 148, 2, 244, 158, 37, 212, 16, 254, 225, 42, 36, 113, + 223, 31, 38, 215, 255, 227, 153, 106, 61, 191, 106, 26, 55, 240, + 158, 192, 112, 209, 41, 37, 168, 81, 22, 169, 141, 189, 253, 214, + 65, 196, 31, 212, 75, 64, 54, 118, 183, 183, 49, 87, 4, 212, + 89, 216, 118, 33, 77, 230, 214, 196, 207, 225, 62, 235, 126, 251, + 202, 92, 26, 20, 130, 18, 142, 28, 141, 9, 191, 190, 218, 232, + 14, 189, 200, 76, 199, 176, 20, 88, 219, 57, 209, 184, 113, 192, + 157, 194, 94, 129, 26, 255, 228, 54, 26, 228, 119, 120, 3, 117, + 187, 196, 150, 219, 92, 228, 180, 209, 73, 10, 230, 18, 201, 233, + 75, 38, 234, 207, 45, 135, 47, 17, 200, 136, 110, 65, 190, 20, + 53, 96, 130, 254, 226, 98, 253, 1, 249, 245, 36, 47, 65, 30, + 102, 249, 178, 39, 97, 153, 113, 88, 192, 64, 244, 24, 84, 99, + 31, 56, 170, 112, 118, 68, 40, 34, 241, 77, 96, 131, 254, 18, + 125, 46, 116, 92, 129, 249, 168, 159, 53, 70, 202, 79, 26, 41, + 98, 182, 210, 86, 66, 120, 230, 151, 197, 19, 86, 141, 122, 173, + 18, 88, 212, 19, 91, 194, 209, 35, 48, 123, 229, 200, 32, 4, + 38, 124, 81, 41, 118, 214, 137, 71, 28, 189, 124, 156, 210, 174, + 149, 173, 239, 91, 154, 90, 38, 109, 17, 32, 152, 110, 25, 75, + 228, 107, 106, 157, 186, 136, 91, 79, 43, 178, 163, 225, 73, 68, + 214, 85, 95, 124, 40, 97, 219, 168, 251, 97, 234, 191, 191, 20, + 109, 244, 82, 219, 57, 5, 175, 197, 73, 184, 178, 172, 194, 7, + 220, 134, 172, 207, 175, 29, 213, 92, 206, 185, 170, 44, 247, 176, + 71, 98, 187, 241, 102, 126, 129, 229, 227, 74, 175, 40, 27, 237, + 126, 89, 44, 99, 30, 15, 4, 95, 54, 13, 60, 236, 244, 134, + 104, 3, 112, 92, 67, 195, 66, 105, 144, 27, 100, 127, 125, 161, + 114, 37, 131, 255, 35, 200, 191, 23, 27, 104, 254, 51, 59, 173, + 193, 76, 240, 197, 44, 231, 82, 70, 106, 31, 230, 107, 196, 210, + 96, 163, 21, 4, 140, 53, 6, 10, 167, 45, 158, 218, 71, 10, + 23, 20, 100, 110, 205, 117, 78, 19, 223, 80, 86, 221, 122, 35, + 107, 53, 144, 40, 93, 118, 117, 178, 200, 196, 31, 105, 197, 169, + 149, 60, 37, 198, 196, 188, 189, 53, 156, 36, 214, 254, 195, 120, + 106, 200, 75, 87, 25, 52, 242, 165, 225, 82, 162, 254, 172, 177, + 231, 245, 157, 83, 159, 220, 113, 24, 78, 152, 145, 206, 170, 179, + 106, 63, 151, 254, 120, 176, 77, 163, 51, 215, 19, 104, 110, 94, + 103, 70, 59, 250, 221, 53, 75, 104, 211, 118, 59, 157, 242, 85, + 177, 104, 237, 111, 147, 244, 47, 63, 62, 80, 31, 153, 232, 153, + 12, 124, 216, 130, 215, 231, 118, 103, 109, 138, 113, 233, 9, 180, + 145, 9, 117, 118, 42, 216, 79, 120, 223, 102, 159, 51, 150, 216, + 156, 129, 98, 89, 49, 143, 189, 47, 34, 181, 240, 150, 134, 154, + 17, 97, 21, 177, 3, 184, 44, 110, 56, 175, 199, 113, 8, 69, + 163, 212, 158, 168, 233, 128, 7, 202, 198, 65, 131, 203, 189, 248, + 241, 85, 156, 148, 106, 69, 80, 228, 155, 192, 134, 152, 150, 228, + 46, 5, 198, 82, 66, 202, 46, 97, 19, 179, 212, 24, 99, 29, + 239, 92, 101, 254, 34, 79, 108, 222, 28, 114, 7, 191, 184, 92, + 109, 242, 156, 10, 85, 196, 91, 238, 0, 103, 6, 229, 45, 188, + 246, 193, 53, 186, 161, 203, 218, 115, 65, 116, 183, 139, 200, 59, + 34, 11, 182, 51, 35, 115, 169, 100, 178, 35, 131, 203, 225, 58, + 234, 141, 143, 0, 132, 186, 147, 192, 199, 252, 94, 207, 237, 233, + 224, 70, 27, 104, 0, 38, 20, 24, 211, 155, 175, 118, 112, 170, + 29, 106, 79, 36, 53, 175, 170, 118, 234, 120, 15, 62, 66, 217, + 12, 144, 13, 155, 213, 46, 34, 30, 2, 225, 26, 177, 22, 203, + 219, 157, 141, 143, 103, 89, 195, 199, 168, 227, 71, 9, 48, 199, + 152, 153, 32, 226, 129, 190, 191, 206, 166, 186, 227, 28, 56, 251, + 42, 152, 213, 192, 227, 153, 28, 116, 67, 84, 89, 214, 37, 214, + 79, 191, 112, 146, 79, 223, 201, 140, 105, 30, 58, 137, 223, 73, + 112, 4, 208, 66, 243, 79, 79, 124, 210, 11, 190, 110, 97, 211, + 72, 211, 201, 67, 61, 79, 122, 73, 113, 200, 180, 241, 10, 114, + 201, 58, 218, 212, 221, 60, 75, 249, 58, 213, 111, 135, 83, 35, + 7, 174, 247, 162, 82, 155, 53, 170, 44, 41, 157, 53, 49, 33, + 224, 43, 226, 176, 87, 32, 97, 21, 87, 40, 98, 57, 157, 146, + 232, 99, 192, 181, 157, 167, 192, 82, 158, 86, 207, 4, 120, 183, + 83, 11, 203, 173, 184, 93, 131, 66, 140, 144, 134, 206, 223, 96, + 122, 111, 190, 180, 173, 248, 141, 250, 110, 69, 202, 107, 94, 63, + 42, 168, 109, 101, 51, 192, 120, 84, 78, 151, 123, 41, 12, 38, + 229, 133, 229, 158, 217, 65, 50, 13, 144, 94, 64, 185, 68, 85, + 247, 128, 131, 32, 234, 244, 62, 128, 245, 153, 149, 85, 82, 185, + 177, 71, 244, 8, 76, 168, 88, 105, 134, 80, 212, 129, 174, 187, + 71, 29, 116, 139, 247, 66, 24, 112, 58, 183, 106, 3, 26, 106, + 184, 144, 217, 226, 87, 75, 172, 106, 238, 193, 210, 113, 168, 207, + 188, 177, 0, 252, 15, 51, 240, 78, 131, 142, 23, 199, 236, 255, + 229, 188, 85, 62, 192, 30, 49, 43, 145, 247, 147, 212, 124, 200, + 174, 11, 23, 207, 188, 158, 130, 121, 135, 158, 35, 48, 34, 0, + 184, 187, 17, 218, 177, 11, 66, 6, 104, 54, 83, 59, 116, 87, + 219, 47, 97, 128, 59, 214, 239, 90, 196, 122, 144, 239, 230, 157, + 74, 185, 57, 210, 167, 229, 179, 8, 21, 149, 72, 46, 175, 152, + 19, 0, 253, 234, 9, 30, 203, 53, 26, 166, 157, 183, 99, 202, + 186, 203, 40, 79, 13, 109, 93, 165, 64, 35, 76, 148, 232, 187, + 39, 17, 147, 80, 20, 60, 27, 156, 43, 249, 127, 221, 48, 135, + 65, 29, 145, 190, 173, 97, 99, 106, 195, 88, 128, 60, 67, 83, + 56, 218, 65, 33, 226, 73, 245, 75, 250, 39, 190, 0, 194, 220, + 254, 13, 8, 190, 0, 14, 96, 232, 8, 86, 135, 0, 25, 84, + 188, 88, 227, 119, 200, 5, 90, 10, 158, 24, 34, 221, 92, 25, + 118, 177, 138, 26, 237, 250, 209, 146, 143, 78, 193, 21, 44, 81, + 105, 110, 120, 126, 12, 110, 76, 80, 33, 54, 24, 125, 16, 203, + 171, 13, 149, 96, 251, 179, 66, 182, 47, 210, 95, 186, 93, 99, + 87, 2, 4, 205, 55, 145, 29, 68, 122, 183, 130, 110, 44, 106, + 148, 59, 212, 113, 214, 63, 64, 99, 106, 105, 128, 168, 206, 127, + 214, 203, 35, 105, 144, 180, 102, 228, 61, 242, 203, 35, 114, 169, + 68, 4, 43, 61, 114, 211, 10, 93, 112, 71, 124, 88, 103, 105, + 199, 55, 196, 157, 187, 77, 255, 220, 17, 55, 129, 37, 116, 49, + 111, 159, 108, 231, 69, 23, 138, 30, 46, 220, 152, 44, 11, 44, + 70, 130, 170, 198, 177, 231, 182, 110, 32, 43, 210, 169, 135, 94, + 17, 234, 24, 170, 227, 78, 13, 198, 14, 149, 88, 106, 0, 255, + 48, 183, 225, 34, 35, 106, 169, 46, 209, 215, 158, 220, 126, 103, + 238, 130, 106, 198, 188, 109, 102, 121, 227, 8, 82, 170, 202, 71, + 180, 75, 32, 190, 14, 152, 49, 57, 75, 71, 38, 68, 80, 144, + 107, 60, 205, 62, 38, 153, 70, 68, 96, 31, 114, 164, 192, 223, + 51, 135, 123, 218, 14, 36, 107, 143, 131, 216, 27, 206, 194, 26, + 140, 45, 24, 167, 184, 181, 38, 166, 178, 100, 85, 114, 59, 55, + 1, 98, 142, 191, 12, 87, 106, 157, 175, 182, 11, 13, 199, 23, + 143, 202, 68, 151, 163, 149, 119, 125, 237, 92, 129, 160, 222, 149, + 79, 198, 200, 22, 139, 55, 167, 6, 10, 140, 198, 50, 217, 158, + 32, 100, 247, 226, 69, 130, 162, 22, 88, 155, 172, 172, 153, 173, + 212, 52, 184, 9, 66, 113, 106, 42, 212, 200, 114, 125, 97, 104, + 127, 68, 188, 36, 222, 78, 12, 210, 207, 241, 57, 111, 191, 108, + 40, 212, 107, 171, 165, 15, 4, 164, 254, 206, 199, 85, 16, 91, + 19, 18, 250, 156, 97, 150, 55, 69, 12, 249, 116, 74, 155, 11, + 161, 18, 8, 1, 88, 54, 242, 253, 27, 39, 180, 124, 247, 71, + 3, 174, 95, 123, 46, 90, 129, 118, 205, 25, 175, 136, 193, 23, + 152, 119, 163, 51, 101, 144, 137, 138, 247, 239, 62, 24, 247, 197, + 221, 160, 221, 171, 90, 148, 251, 89, 15, 225, 151, 131, 231, 3, + 238, 224, 207, 2, 9, 40, 80, 67, 68, 140, 6, 10, 182, 152, + 7, 154, 43, 17, 23, 13, 240, 7, 253, 41, 197, 16, 112, 196, + 145, 49, 206, 20, 87, 37, 48, 60, 71, 179, 72, 155, 4, 56, + 74, 93, 120, 242, 113, 198, 123, 165, 19, 142, 245, 8, 173, 195, + 242, 176, 76, 11, 43, 203, 5, 126, 214, 174, 87, 122, 14, 164, + 169, 25, 121, 145, 199, 224, 91, 118, 65, 94, 169, 78, 139, 7, + 231, 12, 71, 186, 89, 79, 234, 10, 166, 152, 83, 37, 61, 184, + 215, 52, 217, 132, 117, 150, 123, 17, 36, 177, 150, 70, 14, 47, + 155, 216, 5, 53, 158, 179, 249, 55, 169, 181, 201, 238, 237, 125, + 123, 164, 90, 33, 91, 150, 103, 70, 58, 171, 140, 240, 23, 135, + 69, 218, 191, 202, 205, 126, 176, 61, 243, 124, 226, 184, 244, 129, + 111, 108, 107, 42, 51, 63, 177, 213, 254, 27, 6, 168, 87, 177, + 199, 239, 229, 133, 252, 142, 94, 195, 93, 181, 173, 197, 145, 110, + 230, 31, 4, 51, 9, 13, 88, 212, 196, 190, 157, 80, 4, 193, + 235, 149, 7, 116, 208, 98, 52, 205, 136, 25, 215, 55, 237, 30, + 211, 171, 80, 230, 124, 124, 215, 32, 2, 99, 114, 22, 13, 188, + 113, 132, 176, 137, 127, 199, 74, 58, 236, 32, 130, 40, 207, 203, + 59, 248, 41, 136, 70, 125, 239, 21, 69, 83, 137, 63, 128, 124, + 45, 5, 17, 42, 129, 223, 8, 101, 134, 143, 174, 233, 126, 142, + 198, 186, 81, 162, 237, 106, 140, 255, 113, 205, 165, 41, 140, 185, + 12, 67, 62, 68, 111, 140, 141, 54, 63, 94, 46, 23, 184, 17, + 113, 168, 178, 141, 3, 191, 16, 87, 232, 210, 227, 26, 96, 30, + 50, 161, 104, 4, 26, 98, 34, 150, 66, 75, 41, 156, 54, 222, + 57, 194, 57, 186, 128, 159, 63, 57, 125, 238, 65, 21, 30, 205, + 135, 150, 246, 101, 114, 162, 81, 1, 126, 20, 15, 209, 240, 63, + 84, 161, 109, 61, 197, 39, 115, 124, 106, 174, 59, 62, 111, 201, + 199, 48, 226, 97, 238, 80, 47, 135, 216, 106, 93, 92, 99, 65, + 153, 22, 252, 42, 168, 229, 4, 172, 135, 249, 140, 242, 254, 96, + 166, 17, 80, 192, 175, 76, 208, 214, 228, 175, 168, 147, 63, 139, + 235, 247, 41, 221, 209, 54, 69, 70, 215, 109, 102, 50, 54, 70, + 127, 77, 103, 24, 124, 106, 76, 142, 201, 14, 40, 234, 36, 255, + 76, 42, 141, 172, 71, 74, 40, 166, 157, 205, 140, 152, 156, 201, + 5, 119, 82, 4, 118, 93, 31, 117, 84, 158, 75, 197, 151, 24, + 233, 33, 65, 251, 92, 177, 93, 212, 219, 181, 30, 165, 237, 129, + 87, 220, 128, 238, 59, 52, 190, 29, 244, 40, 239, 210, 227, 112, + 236, 61, 143, 52, 190, 75, 55, 141, 183, 87, 108, 187, 125, 77, + 221, 204, 207, 221, 54, 131, 140, 25, 38, 201, 200, 248, 121, 151, + 112, 102, 108, 55, 37, 60, 216, 227, 228, 95, 158, 166, 118, 173, + 172, 221, 135, 106, 210, 191, 87, 204, 96, 117, 3, 203, 79, 178, + 209, 16, 120, 203, 95, 40, 152, 236, 160, 226, 3, 170, 54, 151, + 111, 146, 248, 52, 218, 61, 100, 4, 185, 183, 16, 174, 246, 33, + 255, 126, 215, 109, 219, 12, 3, 196, 141, 253, 31, 19, 7, 156, + 66, 219, 223, 53, 219, 35, 215, 167, 255, 30, 201, 91, 229, 188, + 170, 88, 66, 1, 171, 185, 0, 65, 56, 178, 255, 80, 82, 114, + 213, 150, 233, 129, 252, 203, 30, 170, 138, 76, 13, 178, 128, 4, + 225, 6, 89, 245, 131, 63, 164, 210, 10, 46, 68, 2, 221, 223, + 79, 216, 79, 184, 206, 38, 190, 216, 49, 251, 40, 98, 121, 143, + 8, 216, 223, 131, 174, 250, 27, 226, 129, 244, 210, 187, 192, 188, + 54, 105, 186, 255, 185, 5, 131, 98, 203, 25, 54, 99, 35, 50, + 50, 116, 158, 95, 102, 145, 118, 113, 65, 160, 12, 116, 102, 153, + 235, 74, 115, 2, 206, 82, 34, 85, 101, 141, 200, 127, 183, 93, + 235, 240, 194, 13, 254, 31, 100, 58, 53, 117, 122, 137, 214, 234, + 145, 200, 247, 21, 153, 247, 247, 157, 40, 229, 137, 236, 49, 153, + 42, 185, 34, 230, 56, 92, 160, 39, 149, 37, 31, 215, 41, 57, + 215, 252, 64, 106, 248, 235, 122, 179, 19, 163, 241, 236, 140, 46, + 130, 177, 96, 44, 128, 39, 102, 112, 15, 67, 89, 153, 104, 202, + 168, 157, 223, 61, 126, 237, 178, 178, 211, 220, 112, 156, 113, 39, + 55, 70, 70, 205, 97, 144, 253, 85, 182, 225, 129, 76, 94, 122, + 220, 192, 51, 132, 139, 159, 184, 241, 185, 146, 11, 37, 5, 130, + 196, 240, 243, 198, 129, 53, 172, 254, 203, 143, 120, 213, 164, 123, + 30, 230, 39, 184, 52, 58, 202, 11, 98, 46, 6, 213, 157, 95, + 229, 127, 134, 49, 119, 212, 167, 78, 230, 188, 212, 240, 85, 65, + 223, 105, 186, 77, 8, 137, 59, 80, 179, 69, 247, 200, 80, 25, + 68, 15, 250, 188, 193, 39, 208, 242, 255, 165, 220, 99, 109, 189, + 235, 251, 64, 43, 135, 84, 139, 85, 169, 196, 28, 30, 130, 44, + 127, 17, 34, 64, 197, 119, 94, 115, 241, 45, 210, 39, 136, 180, + 167, 190, 242, 194, 7, 233, 120, 12, 142, 168, 192, 253, 94, 180, + 103, 94, 154, 231, 101, 147, 174, 150, 99, 208, 142, 233, 166, 184, + 223, 111, 104, 36, 192, 195, 135, 0, 213, 129, 90, 111, 80, 107, + 226, 133, 243, 175, 38, 187, 25, 202, 106, 169, 68, 14, 81, 42, + 17, 65, 255, 235, 23, 238, 72, 28, 5, 186, 235, 164, 81, 246, + 124, 8, 217, 12, 33, 33, 34, 98, 51, 46, 223, 198, 252, 50, + 5, 25, 101, 199, 92, 245, 223, 161, 71, 164, 104, 7, 23, 120, + 54, 104, 36, 223, 99, 227, 206, 81, 144, 62, 241, 226, 84, 87, + 117, 246, 68, 248, 216, 173, 213, 232, 113, 45, 44, 236, 1, 228, + 12, 51, 178, 92, 87, 118, 205, 69, 88, 11, 75, 233, 153, 157, + 253, 232, 195, 246, 5, 114, 77, 66, 76, 7, 164, 96, 182, 128, + 60, 183, 28, 18, 24, 124, 126, 243, 73, 160, 208, 109, 103, 242, + 98, 108, 201, 122, 113, 242, 65, 118, 201, 250, 45, 12, 211, 149, + 206, 177, 17, 148, 75, 141, 54, 147, 229, 127, 50, 68, 100, 103, + 2, 5, 226, 242, 170, 34, 217, 64, 197, 186, 106, 135, 89, 37, + 87, 193, 161, 166, 141, 116, 121, 143, 174, 162, 152, 25, 113, 71, + 46, 200, 78, 191, 30, 112, 192, 192, 159, 176, 39, 67, 192, 177, + 60, 125, 209, 3, 201, 190, 110, 221, 250, 210, 21, 149, 98, 0, + 23, 112, 97, 139, 60, 196, 213, 106, 116, 174, 188, 188, 79, 101, + 151, 48, 132, 245, 164, 41, 52, 119, 161, 251, 27, 23, 70, 100, + 175, 20, 243, 209, 21, 113, 56, 9, 225, 225, 188, 118, 60, 165, + 252, 195, 71, 34, 62, 31, 251, 98, 69, 31, 176, 247, 39, 28, + 226, 232, 39, 39, 138, 15, 177, 125, 141, 245, 74, 0, 125, 183, + 48, 32, 34, 238, 161, 122, 9, 81, 205, 205, 200, 237, 63, 216, + 240, 11, 91, 112, 140, 126, 176, 93, 230, 16, 94, 10, 29, 22, + 223, 206, 245, 99, 207, 137, 250, 15, 227, 99, 124, 197, 61, 83, + 101, 144, 98, 218, 88, 169, 167, 118, 2, 157, 91, 144, 141, 156, + 79, 229, 73, 71, 156, 107, 190, 160, 51, 225, 34, 117, 38, 28, + 21, 6, 197, 223, 177, 27, 145, 48, 133, 247, 213, 3, 163, 160, + 197, 199, 254, 124, 5, 106, 34, 168, 17, 193, 55, 176, 150, 58, + 207, 181, 71, 178, 49, 204, 16, 112, 250, 161, 239, 200, 88, 105, + 57, 69, 31, 134, 166, 197, 64, 169, 133, 167, 235, 157, 38, 60, + 51, 156, 93, 58, 45, 245, 246, 134, 106, 16, 39, 251, 103, 178, + 74, 49, 139, 120, 180, 146, 4, 147, 151, 114, 210, 87, 164, 187, + 241, 99, 115, 218, 113, 5, 222, 25, 226, 151, 167, 118, 250, 209, + 82, 190, 182, 44, 209, 85, 113, 246, 89, 201, 13, 180, 92, 44, + 26, 146, 145, 142, 48, 162, 120, 221, 33, 73, 45, 220, 54, 216, + 5, 140, 82, 133, 219, 22, 114, 45, 38, 163, 51, 240, 143, 26, + 105, 31, 205, 1, 21, 73, 200, 34, 232, 138, 200, 214, 49, 220, + 140, 217, 22, 31, 102, 53, 22, 75, 142, 85, 244, 114, 63, 176, + 127, 61, 198, 255, 61, 84, 230, 79, 97, 72, 254, 213, 224, 181, + 182, 166, 63, 177, 115, 174, 143, 47, 150, 235, 73, 207, 151, 229, + 143, 246, 176, 205, 40, 201, 47, 118, 243, 191, 242, 145, 81, 89, + 68, 57, 129, 202, 143, 64, 22, 235, 72, 162, 239, 86, 17, 95, + 57, 6, 190, 184, 247, 226, 179, 179, 5, 116, 40, 85, 228, 139, + 209, 217, 219, 171, 229, 125, 68, 238, 58, 111, 164, 243, 246, 213, + 191, 240, 16, 41, 101, 179, 205, 161, 208, 139, 140, 152, 156, 87, + 106, 107, 214, 32, 100, 5, 200, 147, 97, 174, 25, 28, 220, 16, + 122, 147, 108, 82, 219, 194, 92, 223, 231, 230, 108, 100, 141, 123, + 138, 192, 209, 61, 140, 239, 13, 141, 213, 15, 75, 110, 154, 24, + 4, 187, 249, 146, 205, 97, 193, 111, 47, 163, 228, 96, 99, 235, + 206, 26, 213, 84, 204, 152, 28, 232, 133, 251, 89, 247, 36, 101, + 196, 127, 65, 83, 164, 119, 128, 47, 185, 100, 165, 189, 253, 220, + 86, 116, 150, 238, 147, 253, 215, 92, 144, 210, 200, 102, 48, 69, + 41, 149, 202, 63, 14, 191, 194, 102, 183, 155, 176, 144, 167, 70, + 202, 60, 223, 253, 240, 67, 189, 229, 90, 239, 254, 116, 22, 148, + 193, 144, 66, 28, 53, 179, 207, 134, 193, 114, 3, 241, 205, 49, + 74, 244, 183, 149, 82, 112, 101, 181, 1, 220, 98, 72, 40, 196, + 28, 86, 137, 117, 12, 227, 122, 79, 70, 37, 235, 133, 204, 11, + 94, 165, 150, 74, 81, 189, 227, 94, 92, 42, 68, 22, 67, 135, + 40, 22, 159, 196, 178, 135, 109, 41, 67, 26, 59, 11, 225, 95, + 107, 231, 51, 93, 111, 186, 104, 214, 239, 71, 253, 141, 8, 6, + 82, 63, 55, 11, 97, 41, 66, 44, 76, 84, 79, 14, 249, 105, + 121, 165, 97, 163, 18, 14, 182, 56, 72, 156, 46, 179, 56, 176, + 191, 102, 91, 214, 27, 59, 63, 152, 208, 201, 213, 7, 73, 46, + 229, 248, 144, 46, 132, 34, 17, 233, 86, 74, 157, 31, 139, 70, + 134, 149, 31, 39, 147, 17, 8, 16, 69, 113, 152, 190, 128, 118, + 224, 76, 100, 253, 253, 171, 93, 71, 126, 89, 239, 112, 213, 86, + 127, 71, 171, 73, 193, 41, 244, 112, 60, 168, 30, 9, 69, 131, + 246, 255, 113, 169, 110, 212, 244, 26, 135, 37, 69, 205, 151, 196, + 183, 187, 240, 200, 26, 86, 171, 146, 186, 208, 169, 88, 76, 227, + 218, 105, 226, 83, 0, 133, 187, 251, 41, 78, 192, 190, 78, 225, + 73, 197, 28, 116, 23, 225, 94, 113, 62, 247, 219, 28, 65, 240, + 195, 201, 227, 183, 187, 51, 173, 140, 159, 71, 239, 134, 138, 203, + 247, 44, 245, 15, 17, 73, 40, 215, 204, 122, 81, 255, 84, 18, + 236, 157, 242, 78, 171, 147, 200, 107, 159, 107, 202, 242, 227, 222, + 166, 146, 62, 253, 255, 196, 118, 62, 90, 158, 215, 150, 39, 52, + 111, 193, 147, 25, 157, 144, 241, 226, 61, 180, 165, 92, 226, 86, + 179, 25, 52, 108, 0, 6, 119, 196, 60, 35, 233, 155, 140, 52, + 44, 242, 116, 226, 231, 1, 60, 163, 241, 107, 219, 210, 107, 105, + 176, 172, 189, 34, 25, 173, 226, 217, 53, 136, 177, 21, 114, 95, + 58, 146, 232, 143, 50, 46, 251, 181, 224, 182, 154, 60, 122, 126, + 78, 237, 110, 162, 101, 192, 46, 169, 165, 86, 82, 200, 185, 143, + 238, 73, 153, 45, 187, 243, 131, 224, 102, 4, 183, 175, 9, 146, + 15, 104, 11, 50, 196, 51, 22, 37, 176, 152, 63, 158, 152, 230, + 226, 96, 60, 135, 13, 110, 167, 15, 145, 221, 22, 175, 95, 21, + 1, 45, 25, 93, 24, 212, 160, 104, 44, 37, 102, 117, 49, 137, + 97, 59, 101, 162, 48, 122, 65, 158, 99, 185, 199, 159, 240, 219, + 220, 85, 174, 132, 193, 134, 176, 206, 117, 145, 170, 65, 91, 200, + 120, 59, 113, 46, 195, 95, 90, 16, 111, 56, 105, 182, 14, 5, + 220, 75, 96, 22, 182, 254, 217, 44, 21, 237, 70, 216, 250, 160, + 220, 3, 62, 153, 224, 168, 223, 215, 199, 119, 96, 169, 36, 51, + 15, 70, 113, 225, 224, 48, 97, 228, 202, 210, 42, 121, 178, 194, + 112, 154, 30, 129, 23, 177, 157, 10, 61, 169, 35, 124, 231, 252, + 133, 217, 246, 80, 203, 255, 110, 164, 183, 79, 120, 115, 241, 145, + 124, 163, 220, 61, 153, 78, 121, 154, 78, 214, 67, 226, 147, 119, + 224, 168, 151, 190, 172, 142, 91, 64, 31, 52, 219, 75, 8, 16, + 88, 131, 128, 81, 207, 5, 216, 218, 91, 46, 14, 104, 96, 61, + 160, 149, 234, 50, 208, 213, 160, 49, 115, 127, 120, 56, 90, 51, + 131, 111, 107, 242, 208, 177, 50, 103, 39, 145, 227, 190, 91, 204, + 188, 126, 146, 134, 205, 84, 124, 94, 68, 168, 186, 140, 201, 144, + 221, 178, 5, 37, 84, 214, 238, 157, 159, 98, 134, 179, 47, 3, + 252, 33, 91, 44, 84, 235, 108, 242, 143, 133, 114, 247, 99, 189, + 222, 0, 152, 75, 173, 251, 94, 221, 254, 127, 72, 147, 245, 205, + 214, 86, 184, 20, 141, 42, 86, 127, 74, 111, 167, 93, 192, 168, + 129, 226, 2, 251, 255, 196, 158, 40, 10, 10, 85, 229, 166, 27, + 16, 193, 166, 245, 139, 171, 27, 156, 246, 5, 43, 95, 190, 228, + 121, 37, 177, 69, 139, 204, 186, 79, 199, 222, 137, 29, 35, 159, + 44, 247, 225, 207, 100, 125, 141, 52, 5, 101, 4, 210, 239, 109, + 236, 61, 84, 68, 72, 200, 30, 29, 40, 17, 239, 140, 72, 202, + 203, 108, 205, 240, 114, 176, 97, 77, 168, 197, 140, 118, 87, 233, + 34, 12, 105, 110, 74, 88, 17, 219, 67, 201, 180, 25, 229, 235, + 99, 237, 178, 115, 57, 133, 3, 61, 197, 124, 196, 116, 155, 196, + 144, 77, 175, 178, 254, 206, 90, 137, 60, 203, 25, 184, 133, 211, + 186, 237, 15, 107, 170, 181, 191, 85, 38, 182, 33, 105, 92, 158, + 104, 194, 222, 235, 80, 250, 115, 145, 153, 193, 58, 227, 129, 12, + 1, 89, 219, 113, 68, 49, 114, 231, 63, 223, 246, 181, 146, 59, + 84, 87, 32, 173, 129, 166, 167, 68, 181, 233, 176, 178, 134, 140, + 18, 172, 98, 150, 74, 221, 238, 146, 194, 200, 220, 212, 223, 60, + 14, 145, 159, 61, 92, 17, 89, 233, 248, 187, 24, 15, 1, 217, + 204, 70, 85, 139, 120, 109, 155, 135, 12, 48, 230, 171, 249, 118, + 251, 154, 247, 52, 162, 254, 20, 223, 232, 41, 4, 254, 59, 100, + 243, 214, 150, 182, 130, 193, 155, 222, 203, 80, 221, 0, 127, 184, + 23, 111, 214, 136, 62, 34, 70, 183, 235, 246, 203, 33, 87, 105, + 32, 249, 3, 41, 64, 104, 83, 132, 234, 63, 63, 58, 243, 217, + 224, 44, 244, 81, 240, 67, 172, 61, 80, 202, 212, 24, 214, 140, + 123, 231, 153, 200, 26, 67, 90, 237, 3, 31, 122, 244, 57, 97, + 119, 216, 125, 117, 105, 25, 5, 36, 220, 131, 215, 210, 154, 5, + 148, 82, 86, 152, 53, 241, 69, 216, 9, 85, 49, 250, 4, 163, + 14, 75, 98, 162, 84, 32, 171, 90, 17, 159, 34, 212, 165, 33, + 128, 249, 152, 39, 167, 100, 171, 173, 30, 115, 197, 116, 70, 251, + 232, 195, 23, 255, 26, 23, 227, 229, 4, 0, 132, 135, 10, 51, + 64, 237, 99, 60, 128, 133, 249, 219, 137, 14, 40, 98, 108, 209, + 194, 103, 218, 142, 101, 67, 152, 181, 222, 169, 172, 6, 134, 160, + 253, 196, 47, 109, 234, 140, 128, 147, 19, 168, 66, 196, 186, 109, + 17, 44, 45, 64, 32, 50, 141, 168, 145, 124, 249, 212, 149, 217, + 164, 211, 29, 164, 41, 68, 171, 222, 110, 131, 223, 197, 176, 163, + 104, 213, 63, 116, 150, 139, 199, 30, 147, 196, 197, 205, 1, 61, + 249, 215, 146, 27, 228, 23, 185, 84, 163, 48, 124, 32, 89, 103, + 212, 226, 186, 163, 147, 233, 160, 113, 53, 92, 202, 240, 157, 8, + 143, 50, 107, 102, 221, 85, 179, 116, 166, 116, 56, 39, 33, 138, + 84, 101, 57, 134, 24, 87, 116, 125, 57, 157, 178, 183, 1, 2, + 147, 164, 0, 97, 21, 100, 16, 71, 143, 150, 65, 188, 237, 168, + 32, 143, 181, 194, 74, 118, 56, 134, 160, 35, 106, 34, 122, 150, + 114, 65, 71, 41, 211, 223, 170, 183, 99, 182, 103, 66, 251, 71, + 86, 51, 123, 168, 31, 211, 53, 207, 212, 144, 16, 46, 197, 228, + 83, 155, 67, 1, 176, 62, 199, 95, 33, 211, 44, 237, 246, 136, + 70, 200, 61, 123, 232, 92, 83, 143, 9, 97, 115, 1, 114, 172, + 95, 31, 216, 220, 60, 229, 74, 192, 34, 78, 221, 225, 112, 196, + 122, 196, 30, 182, 96, 62, 198, 198, 113, 131, 83, 76, 213, 6, + 209, 49, 192, 50, 233, 144, 179, 127, 176, 99, 125, 100, 77, 51, + 37, 24, 26, 50, 62, 130, 19, 120, 49, 103, 170, 6, 243, 209, + 31, 48, 195, 236, 164, 207, 47, 10, 174, 148, 193, 187, 189, 41, + 202, 190, 82, 214, 103, 68, 161, 231, 49, 98, 139, 0, 205, 221, + 68, 37, 13, 244, 40, 95, 17, 207, 251, 76, 152, 228, 237, 54, + 51, 58, 90, 215, 29, 26, 240, 48, 201, 94, 9, 99, 247, 48, + 0, 7, 96, 101, 196, 250, 140, 164, 131, 223, 10, 227, 207, 123, + 78, 97, 18, 205, 42, 70, 233, 107, 235, 227, 97, 18, 16, 84, + 204, 63, 87, 230, 91, 23, 67, 230, 182, 205, 240, 44, 158, 151, + 170, 60, 235, 99, 192, 161, 36, 152, 87, 56, 26, 243, 227, 141, + 48, 229, 6, 221, 89, 122, 130, 136, 73, 224, 255, 84, 251, 79, + 255, 204, 28, 75, 239, 220, 213, 233, 85, 99, 168, 84, 134, 154, + 16, 198, 70, 28, 234, 114, 166, 137, 71, 2, 213, 138, 40, 94, + 242, 97, 166, 30, 6, 155, 213, 112, 42, 215, 121, 103, 95, 170, + 15, 6, 80, 186, 120, 242, 26, 191, 119, 118, 185, 149, 223, 241, + 50, 69, 36, 125, 123, 6, 252, 34, 107, 155, 117, 61, 82, 141, + 8, 122, 246, 92, 6, 61, 122, 137, 82, 9, 185, 52, 186, 237, + 48, 92, 12, 130, 238, 58, 33, 141, 255, 17, 49, 173, 81, 113, + 102, 139, 126, 216, 220, 39, 249, 200, 241, 64, 41, 45, 56, 172, + 182, 254, 202, 25, 215, 220, 121, 16, 126, 88, 233, 168, 132, 151, + 10, 238, 60, 177, 55, 189, 212, 49, 216, 54, 56, 179, 249, 227, + 0, 42, 154, 65, 77, 62, 33, 192, 83, 250, 24, 79, 8, 61, + 8, 39, 59, 121, 120, 64, 67, 160, 65, 62, 138, 27, 111, 165, + 141, 117, 224, 161, 88, 232, 140, 213, 68, 86, 193, 164, 44, 253, + 208, 120, 167, 103, 166, 71, 173, 49, 172, 52, 108, 15, 36, 151, + 185, 76, 55, 208, 47, 250, 98, 23, 101, 121, 51, 184, 26, 228, + 103, 211, 37, 48, 84, 66, 129, 182, 45, 200, 196, 127, 152, 7, + 31, 89, 64, 34, 39, 135, 221, 171, 222, 53, 216, 244, 62, 190, + 107, 91, 206, 2, 124, 184, 89, 158, 232, 187, 86, 154, 243, 67, + 132, 55, 129, 30, 48, 93, 25, 52, 236, 204, 118, 138, 138, 131, + 34, 145, 186, 126, 169, 36, 20, 70, 144, 5, 117, 220, 177, 220, + 255, 69, 98, 79, 233, 27, 103, 87, 225, 215, 81, 124, 186, 244, + 215, 46, 110, 174, 69, 121, 229, 148, 195, 27, 59, 246, 55, 178, + 49, 156, 184, 72, 103, 68, 188, 116, 185, 255, 87, 74, 235, 62, + 177, 173, 253, 83, 160, 28, 116, 255, 255, 83, 145, 156, 161, 205, + 174, 132, 242, 30, 204, 234, 116, 196, 229, 202, 211, 118, 199, 225, + 140, 47, 74, 228, 138, 138, 50, 226, 213, 31, 109, 141, 216, 247, + 28, 31, 34, 218, 17, 213, 55, 230, 249, 68, 192, 126, 100, 155, + 81, 118, 92, 97, 97, 140, 53, 208, 0, 60, 135, 126, 181, 108, + 120, 152, 71, 203, 108, 246, 154, 86, 132, 28, 155, 114, 177, 25, + 239, 204, 76, 17, 173, 62, 8, 251, 138, 132, 13, 160, 234, 236, + 110, 20, 24, 169, 218, 125, 230, 14, 200, 228, 227, 16, 190, 38, + 119, 242, 241, 80, 153, 110, 35, 178, 154, 97, 84, 63, 207, 123, + 1, 215, 94, 220, 74, 36, 187, 6, 164, 218, 164, 75, 57, 117, + 18, 70, 188, 204, 192, 156, 214, 101, 211, 13, 216, 8, 169, 223, + 254, 225, 91, 137, 130, 29, 108, 190, 108, 201, 8, 147, 252, 31, + 120, 80, 242, 193, 96, 139, 84, 31, 210, 170, 164, 82, 8, 107, + 130, 252, 141, 0, 232, 17, 119, 6, 79, 128, 184, 223, 158, 103, + 13, 175, 55, 214, 205, 61, 112, 185, 171, 211, 150, 124, 112, 151, + 104, 243, 52, 107, 73, 246, 229, 213, 58, 70, 16, 46, 70, 120, + 145, 77, 97, 83, 41, 58, 194, 171, 76, 255, 27, 156, 159, 19, + 31, 211, 197, 62, 243, 87, 128, 44, 139, 126, 178, 188, 190, 120, + 231, 140, 187, 231, 47, 133, 6, 21, 136, 48, 7, 139, 44, 152, + 37, 216, 126, 254, 227, 3, 20, 172, 204, 37, 246, 169, 105, 79, + 103, 255, 191, 7, 100, 75, 142, 253, 200, 180, 156, 182, 177, 66, + 31, 74, 19, 180, 139, 80, 217, 175, 194, 82, 181, 225, 3, 220, + 220, 245, 156, 76, 199, 109, 58, 209, 179, 249, 85, 250, 42, 74, + 24, 140, 188, 179, 211, 53, 220, 240, 10, 210, 61, 51, 42, 54, + 35, 225, 230, 73, 204, 79, 152, 82, 194, 33, 78, 113, 203, 210, + 49, 194, 62, 128, 54, 43, 30, 56, 72, 120, 228, 135, 84, 28, + 6, 77, 160, 207, 128, 158, 95, 215, 174, 89, 201, 74, 85, 42, + 200, 13, 190, 197, 108, 205, 88, 208, 123, 136, 184, 182, 220, 58, + 104, 160, 137, 97, 222, 99, 198, 229, 42, 156, 116, 58, 140, 166, + 27, 211, 0, 9, 242, 72, 165, 39, 141, 242, 255, 231, 43, 121, + 0, 139, 242, 14, 79, 76, 30, 85, 8, 204, 34, 19, 101, 109, + 23, 181, 180, 134, 150, 88, 42, 162, 170, 63, 210, 182, 136, 223, + 69, 222, 227, 124, 226, 32, 165, 251, 242, 197, 182, 193, 4, 17, + 19, 66, 176, 196, 99, 145, 237, 30, 120, 154, 16, 194, 212, 184, + 249, 4, 28, 89, 246, 117, 177, 54, 32, 13, 135, 21, 170, 35, + 140, 77, 150, 252, 183, 238, 65, 45, 189, 6, 196, 202, 6, 30, + 181, 66, 214, 145, 239, 178, 120, 101, 178, 106, 43, 144, 32, 133, + 58, 38, 41, 249, 143, 63, 34, 144, 89, 236, 251, 239, 249, 177, + 69, 111, 130, 167, 212, 254, 8, 202, 146, 82, 21, 102, 86, 175, + 182, 244, 20, 26, 231, 115, 56, 131, 50, 68, 239, 84, 30, 122, + 32, 163, 190, 70, 225, 136, 209, 3, 234, 170, 173, 251, 225, 86, + 217, 115, 82, 218, 107, 113, 20, 38, 85, 125, 78, 110, 51, 148, + 126, 166, 10, 239, 201, 241, 29, 29, 112, 247, 172, 68, 96, 212, + 19, 183, 27, 127, 82, 221, 32, 242, 124, 6, 159, 60, 3, 16, + 65, 156, 28, 242, 35, 147, 54, 40, 40, 250, 66, 116, 115, 219, + 13, 58, 63, 90, 85, 126, 249, 245, 155, 149, 140, 235, 142, 120, + 71, 92, 69, 212, 71, 57, 166, 170, 11, 80, 42, 23, 201, 15, + 35, 73, 91, 142, 146, 147, 42, 136, 53, 72, 21, 121, 172, 90, + 197, 124, 181, 6, 207, 147, 248, 248, 152, 60, 170, 122, 59, 246, + 208, 197, 88, 101, 247, 15, 165, 18, 59, 80, 179, 176, 133, 40, + 17, 232, 166, 204, 149, 224, 224, 228, 46, 54, 72, 168, 103, 170, + 85, 241, 233, 115, 198, 203, 88, 188, 123, 130, 136, 55, 45, 27, + 41, 67, 178, 203, 211, 5, 4, 60, 220, 154, 245, 200, 48, 3, + 232, 167, 182, 200, 89, 92, 186, 138, 86, 20, 238, 208, 83, 20, + 116, 2, 151, 2, 142, 199, 182, 11, 148, 216, 136, 194, 109, 213, + 204, 50, 53, 167, 9, 189, 195, 112, 146, 156, 163, 207, 52, 142, + 62, 1, 4, 185, 120, 40, 144, 86, 181, 27, 192, 24, 129, 70, + 112, 190, 192, 193, 56, 165, 58, 102, 88, 120, 196, 89, 9, 206, + 18, 106, 191, 201, 105, 99, 60, 61, 244, 74, 14, 152, 63, 10, + 41, 252, 65, 32, 49, 98, 40, 85, 201, 144, 170, 37, 192, 200, + 145, 17, 24, 240, 118, 66, 206, 112, 238, 136, 144, 97, 254, 215, + 108, 65, 104, 218, 249, 51, 177, 163, 184, 176, 213, 247, 152, 219, + 140, 142, 193, 167, 60, 61, 10, 174, 92, 177, 110, 140, 53, 198, + 61, 68, 123, 112, 215, 156, 66, 72, 101, 113, 241, 63, 194, 132, + 24, 125, 154, 234, 252, 206, 100, 134, 167, 158, 36, 39, 229, 36, + 61, 105, 26, 114, 73, 200, 171, 0, 194, 110, 7, 251, 59, 13, + 134, 234, 67, 91, 220, 221, 172, 185, 180, 14, 171, 191, 52, 51, + 0, 137, 139, 5, 225, 99, 133, 199, 129, 216, 85, 96, 209, 60, + 219, 107, 117, 242, 9, 240, 214, 76, 53, 183, 107, 161, 75, 24, + 13, 109, 17, 235, 126, 115, 212, 206, 118, 109, 119, 1, 29, 94, + 81, 100, 22, 230, 214, 97, 92, 180, 85, 72, 55, 157, 107, 208, + 213, 45, 251, 95, 4, 98, 211, 42, 99, 218, 167, 206, 208, 122, + 108, 109, 158, 174, 249, 112, 249, 19, 81, 4, 58, 54, 190, 191, + 114, 220, 230, 134, 158, 132, 152, 23, 222, 204, 110, 230, 117, 114, + 225, 179, 209, 154, 31, 94, 234, 21, 58, 44, 210, 203, 229, 107, + 92, 218, 116, 234, 26, 47, 98, 133, 36, 101, 204, 101, 117, 213, + 85, 196, 239, 157, 250, 128, 246, 152, 254, 53, 249, 71, 83, 155, + 4, 79, 86, 73, 135, 81, 154, 243, 222, 49, 28, 96, 47, 51, + 129, 42, 69, 27, 79, 208, 80, 53, 160, 38, 185, 23, 192, 87, + 16, 31, 127, 232, 119, 73, 117, 252, 202, 67, 195, 162, 252, 75, + 166, 166, 129, 96, 173, 24, 106, 154, 48, 33, 209, 190, 239, 192, + 168, 42, 194, 195, 50, 91, 204, 18, 74, 164, 183, 102, 106, 73, + 77, 245, 232, 179, 212, 26, 63, 129, 41, 51, 181, 207, 39, 190, + 51, 13, 35, 159, 194, 129, 255, 196, 110, 107, 95, 240, 211, 60, + 93, 208, 139, 228, 207, 113, 155, 22, 167, 206, 74, 146, 138, 121, + 124, 154, 24, 73, 17, 13, 120, 201, 90, 172, 0, 18, 99, 189, + 150, 155, 177, 219, 225, 230, 165, 8, 42, 98, 114, 200, 117, 134, + 193, 152, 170, 92, 92, 7, 188, 149, 164, 117, 226, 159, 25, 16, + 15, 22, 184, 34, 220, 254, 212, 237, 6, 33, 224, 23, 213, 111, + 49, 109, 133, 241, 171, 238, 179, 173, 211, 82, 8, 30, 87, 39, + 175, 28, 228, 76, 133, 112, 58, 119, 152, 92, 18, 37, 64, 199, + 54, 78, 169, 239, 213, 112, 38, 37, 217, 89, 166, 98, 58, 239, + 161, 205, 12, 180, 59, 212, 104, 105, 63, 127, 162, 211, 204, 190, + 176, 222, 180, 142, 81, 211, 54, 198, 23, 165, 239, 121, 208, 235, + 213, 224, 98, 118, 44, 130, 92, 112, 252, 37, 239, 223, 233, 163, + 27, 243, 10, 254, 6, 250, 240, 226, 157, 31, 130, 89, 245, 176, + 244, 6, 43, 149, 221, 240, 172, 110, 192, 56, 153, 133, 203, 64, + 241, 211, 56, 45, 64, 116, 123, 131, 218, 202, 186, 164, 232, 35, + 254, 171, 87, 69, 74, 125, 174, 135, 171, 18, 195, 3, 109, 30, + 176, 84, 174, 102, 246, 211, 253, 4, 246, 2, 190, 204, 209, 231, + 225, 216, 216, 9, 164, 10, 59, 205, 62, 165, 106, 145, 157, 108, + 134, 86, 198, 10, 45, 46, 146, 163, 93, 202, 76, 163, 27, 231, + 238, 74, 223, 72, 83, 70, 72, 163, 143, 14, 8, 6, 10, 76, + 168, 219, 195, 119, 240, 17, 15, 213, 253, 9, 12, 255, 174, 66, + 59, 248, 63, 91, 195, 132, 245, 183, 79, 229, 46, 202, 112, 88, + 192, 158, 25, 149, 45, 168, 203, 104, 67, 185, 152, 212, 177, 124, + 228, 205, 129, 60, 136, 118, 91, 177, 218, 137, 218, 134, 127, 110, + 95, 152, 17, 113, 116, 164, 82, 98, 216, 125, 12, 121, 55, 206, + 55, 84, 160, 18, 2, 39, 42, 24, 33, 93, 59, 224, 153, 21, + 66, 220, 33, 113, 52, 181, 158, 5, 64, 9, 203, 220, 37, 124, + 190, 191, 13, 88, 178, 64, 251, 59, 116, 165, 82, 165, 80, 98, + 213, 98, 196, 78, 44, 100, 6, 112, 119, 17, 169, 2, 88, 92, + 42, 73, 84, 158, 212, 158, 143, 6, 97, 237, 217, 13, 166, 116, + 200, 16, 173, 96, 158, 249, 157, 229, 27, 22, 234, 32, 159, 134, + 141, 72, 44, 25, 85, 231, 239, 160, 122, 0, 244, 178, 156, 252, + 14, 25, 183, 239, 245, 79, 178, 81, 151, 243, 74, 92, 146, 175, + 179, 218, 158, 18, 106, 232, 206, 111, 118, 4, 12, 14, 99, 218, + 26, 200, 29, 172, 81, 146, 142, 228, 131, 68, 227, 255, 50, 58, + 216, 58, 15, 68, 106, 208, 203, 20, 218, 129, 190, 249, 120, 39, + 219, 69, 235, 17, 11, 227, 55, 209, 74, 127, 42, 223, 214, 63, + 39, 189, 252, 113, 158, 129, 39, 199, 162, 5, 36, 144, 76, 201, + 161, 159, 134, 242, 184, 23, 165, 114, 183, 166, 54, 112, 126, 232, + 144, 65, 188, 110, 122, 16, 77, 52, 93, 198, 116, 152, 183, 219, + 18, 96, 75, 252, 199, 65, 18, 50, 1, 34, 198, 142, 101, 218, + 68, 132, 66, 189, 119, 38, 31, 56, 27, 37, 137, 123, 102, 149, + 55, 107, 172, 199, 119, 98, 201, 242, 195, 150, 150, 49, 45, 182, + 252, 39, 98, 154, 118, 118, 172, 114, 214, 220, 126, 119, 21, 167, + 10, 145, 156, 206, 69, 117, 27, 233, 247, 98, 6, 168, 182, 74, + 249, 20, 123, 7, 194, 243, 208, 75, 173, 188, 75, 120, 11, 253, + 236, 203, 165, 124, 218, 123, 65, 197, 109, 212, 249, 194, 95, 98, + 143, 8, 124, 45, 31, 199, 25, 240, 87, 135, 204, 8, 125, 137, + 1, 213, 84, 20, 43, 76, 134, 10, 121, 234, 142, 112, 19, 114, + 25, 126, 14, 243, 67, 211, 204, 40, 52, 192, 54, 140, 114, 59, + 42, 156, 174, 206, 61, 24, 119, 138, 31, 64, 79, 73, 225, 180, + 210, 14, 128, 236, 147, 33, 189, 99, 26, 244, 31, 20, 251, 128, + 222, 186, 97, 175, 247, 134, 132, 9, 143, 87, 226, 18, 101, 148, + 127, 129, 81, 64, 191, 70, 173, 159, 216, 88, 127, 85, 58, 167, + 118, 201, 86, 212, 208, 148, 19, 23, 255, 156, 119, 245, 199, 243, + 215, 228, 177, 32, 17, 4, 22, 156, 109, 38, 196, 158, 246, 148, + 178, 154, 202, 61, 154, 87, 196, 75, 252, 243, 166, 27, 65, 94, + 202, 232, 127, 186, 243, 54, 163, 157, 171, 168, 84, 147, 34, 97, + 124, 110, 205, 62, 146, 171, 174, 224, 88, 168, 4, 182, 46, 54, + 148, 60, 179, 43, 31, 44, 133, 122, 33, 226, 145, 79, 251, 61, + 3, 144, 121, 146, 26, 169, 110, 23, 30, 50, 221, 220, 45, 253, + 222, 86, 251, 184, 176, 99, 106, 103, 22, 137, 74, 26, 250, 149, + 105, 142, 174, 26, 168, 84, 76, 248, 29, 151, 142, 5, 192, 58, + 78, 222, 2, 74, 43, 231, 80, 77, 55, 39, 127, 132, 219, 237, + 189, 194, 81, 140, 148, 14, 166, 136, 126, 96, 114, 153, 59, 242, + 19, 202, 60, 192, 70, 197, 28, 164, 14, 37, 136, 166, 178, 7, + 216, 92, 59, 34, 252, 210, 161, 80, 175, 142, 102, 227, 197, 61, + 193, 45, 176, 121, 13, 164, 6, 14, 112, 142, 179, 101, 45, 93, + 33, 102, 25, 209, 18, 63, 130, 249, 222, 195, 41, 253, 122, 239, + 117, 65, 45, 225, 45, 10, 40, 32, 54, 227, 96, 215, 112, 98, + 244, 45, 190, 18, 14, 185, 85, 228, 55, 231, 65, 85, 155, 190, + 78, 160, 131, 64, 21, 207, 110, 217, 255, 91, 137, 2, 117, 176, + 204, 134, 49, 95, 168, 49, 56, 5, 38, 146, 139, 50, 126, 30, + 70, 15, 210, 74, 201, 19, 20, 15, 230, 129, 78, 112, 83, 142, + 225, 156, 25, 144, 222, 150, 65, 148, 114, 37, 117, 12, 93, 236, + 12, 243, 103, 128, 186, 70, 122, 215, 1, 214, 225, 245, 246, 97, + 170, 119, 232, 194, 223, 161, 173, 189, 207, 123, 243, 63, 250, 36, + 239, 229, 199, 170, 108, 95, 8, 210, 140, 79, 8, 200, 190, 114, + 80, 200, 33, 185, 184, 177, 246, 169, 204, 23, 179, 255, 128, 11, + 207, 23, 144, 161, 247, 175, 33, 84, 92, 244, 116, 243, 93, 87, + 19, 221, 221, 195, 201, 35, 76, 16, 6, 82, 222, 182, 248, 149, + 28, 190, 110, 132, 159, 211, 108, 137, 125, 182, 204, 88, 14, 13, + 77, 89, 101, 64, 230, 135, 248, 1, 124, 236, 158, 138, 73, 73, + 25, 69, 141, 68, 131, 244, 215, 54, 75, 17, 67, 26, 94, 53, + 38, 74, 187, 62, 159, 174, 160, 209, 232, 149, 189, 73, 181, 18, + 242, 1, 88, 207, 57, 118, 49, 39, 3, 76, 119, 223, 228, 23, + 145, 63, 181, 248, 203, 187, 126, 221, 92, 237, 227, 120, 107, 220, + 255, 11, 77, 195, 203, 180, 150, 90, 241, 200, 58, 77, 34, 3, + 206, 85, 195, 5, 181, 183, 99, 79, 59, 179, 49, 28, 66, 63, + 96, 21, 97, 225, 51, 66, 148, 153, 83, 94, 139, 8, 78, 37, + 197, 247, 159, 255, 73, 134, 38, 216, 193, 131, 254, 99, 2, 174, + 197, 8, 25, 8, 37, 213, 225, 157, 56, 98, 121, 137, 206, 153, + 99, 103, 158, 245, 219, 60, 5, 116, 19, 249, 32, 46, 95, 131, + 88, 174, 139, 173, 159, 7, 65, 161, 20, 219, 115, 170, 6, 37, + 129, 28, 32, 212, 35, 179, 127, 235, 135, 3, 78, 75, 182, 101, + 59, 114, 123, 31, 159, 69, 181, 108, 145, 167, 215, 95, 243, 95, + 89, 122, 23, 7, 165, 254, 217, 38, 192, 181, 178, 41, 66, 56, + 214, 73, 16, 127, 8, 22, 187, 93, 38, 152, 216, 223, 58, 184, + 195, 69, 38, 102, 13, 107, 182, 233, 194, 76, 222, 135, 7, 91, + 219, 233, 14, 165, 118, 5, 212, 3, 107, 50, 106, 116, 142, 32, + 73, 15, 24, 72, 166, 255, 206, 92, 247, 236, 80, 152, 142, 174, + 28, 139, 6, 171, 8, 183, 117, 254, 84, 217, 187, 54, 245, 198, + 210, 51, 56, 221, 123, 27, 150, 45, 117, 130, 50, 76, 209, 54, + 142, 43, 198, 173, 19, 86, 117, 46, 9, 49, 35, 113, 254, 133, + 153, 216, 56, 56, 104, 192, 95, 57, 205, 24, 223, 127, 113, 19, + 62, 2, 6, 192, 44, 248, 4, 230, 249, 29, 77, 101, 20, 19, + 73, 59, 209, 13, 105, 136, 51, 215, 81, 146, 117, 173, 162, 14, + 244, 42, 183, 174, 26, 70, 191, 148, 62, 93, 35, 49, 255, 130, + 220, 135, 40, 86, 63, 178, 127, 218, 162, 71, 193, 163, 130, 231, + 185, 192, 255, 120, 252, 96, 105, 229, 237, 253, 119, 189, 243, 56, + 156, 54, 2, 101, 151, 95, 50, 240, 75, 67, 117, 117, 167, 130, + 186, 118, 192, 77, 243, 75, 151, 22, 150, 109, 216, 59, 69, 227, + 67, 199, 139, 140, 51, 58, 103, 66, 113, 226, 171, 251, 42, 89, + 74, 41, 150, 153, 221, 190, 89, 18, 38, 36, 85, 205, 153, 144, + 118, 234, 51, 3, 89, 250, 14, 246, 18, 239, 178, 209, 83, 153, + 189, 234, 91, 120, 198, 4, 41, 213, 108, 170, 53, 185, 108, 110, + 57, 14, 143, 59, 251, 199, 5, 254, 221, 13, 184, 114, 26, 208, + 115, 29, 238, 139, 6, 32, 99, 138, 156, 252, 39, 223, 48, 34, + 29, 35, 36, 20, 74, 1, 12, 28, 153, 197, 58, 124, 37, 12, + 148, 193, 15, 14, 89, 71, 90, 248, 143, 168, 149, 116, 95, 135, + 45, 199, 185, 44, 88, 175, 208, 242, 176, 64, 120, 146, 109, 89, + 254, 160, 59, 92, 47, 8, 76, 190, 150, 117, 66, 54, 191, 28, + 71, 142, 45, 128, 71, 187, 246, 71, 16, 200, 93, 177, 30, 210, + 43, 39, 84, 23, 22, 27, 33, 80, 99, 44, 152, 142, 40, 245, + 104, 190, 189, 82, 38, 153, 129, 175, 235, 212, 161, 202, 180, 153, + 172, 219, 61, 129, 59, 94, 205, 228, 196, 133, 45, 158, 163, 112, + 49, 50, 140, 149, 45, 84, 79, 240, 45, 203, 179, 155, 9, 137, + 225, 200, 5, 246, 129, 91, 145, 56, 57, 61, 120, 189, 231, 40, + 123, 100, 147, 227, 163, 156, 69, 35, 171, 185, 159, 8, 173, 187, + 238, 112, 17, 6, 93, 126, 93, 150, 241, 85, 106, 97, 118, 142, + 116, 25, 208, 158, 14, 207, 95, 88, 185, 116, 202, 109, 165, 15, + 38, 189, 42, 52, 2, 0, 29, 95, 208, 11, 77, 2, 72, 125, + 214, 65, 69, 191, 167, 187, 72, 140, 129, 100, 178, 208, 135, 159, + 0, 106, 99, 231, 143, 12, 185, 67, 246, 156, 177, 156, 232, 193, + 246, 67, 231, 253, 186, 193, 168, 119, 232, 208, 108, 253, 211, 5, + 96, 31, 48, 177, 196, 196, 157, 17, 93, 109, 184, 206, 255, 249, + 52, 56, 245, 69, 131, 65, 92, 233, 25, 205, 36, 104, 49, 104, + 56, 12, 134, 213, 155, 13, 183, 105, 217, 151, 165, 144, 13, 41, + 198, 217, 62, 69, 162, 251, 178, 120, 157, 83, 33, 31, 221, 210, + 55, 112, 30, 191, 244, 158, 55, 46, 252, 132, 21, 70, 182, 207, + 20, 151, 171, 81, 97, 106, 246, 147, 163, 123, 60, 251, 12, 17, + 49, 94, 135, 15, 28, 80, 75, 146, 57, 48, 70, 38, 199, 20, + 127, 72, 104, 40, 72, 68, 77, 21, 235, 47, 234, 220, 45, 187, + 95, 241, 77, 99, 217, 23, 68, 56, 22, 180, 24, 80, 159, 53, + 4, 23, 226, 90, 46, 195, 57, 43, 43, 167, 218, 20, 42, 35, + 138, 132, 220, 252, 174, 67, 163, 112, 232, 237, 135, 34, 27, 172, + 224, 216, 24, 3, 249, 41, 235, 150, 11, 54, 71, 206, 159, 50, + 94, 13, 183, 48, 214, 4, 170, 83, 236, 220, 200, 145, 86, 69, + 182, 115, 169, 71, 5, 99, 8, 33, 179, 60, 4, 36, 29, 190, + 238, 36, 226, 44, 205, 218, 157, 18, 210, 209, 196, 121, 93, 160, + 56, 229, 254, 249, 93, 34, 78, 43, 253, 218, 222, 223, 5, 65, + 235, 90, 117, 137, 104, 133, 36, 248, 53, 179, 172, 177, 216, 47, + 124, 184, 230, 244, 123, 158, 90, 23, 217, 204, 34, 127, 225, 92, + 109, 129, 31, 53, 80, 56, 162, 249, 174, 241, 88, 129, 33, 220, + 246, 209, 145, 214, 118, 27, 46, 3, 52, 72, 185, 157, 171, 116, + 39, 32, 123, 238, 138, 74, 46, 8, 7, 123, 249, 91, 14, 181, + 18, 182, 64, 32, 1, 167, 32, 8, 135, 78, 47, 190, 175, 100, + 50, 168, 105, 178, 58, 97, 45, 194, 147, 45, 63, 108, 190, 90, + 56, 27, 185, 252, 158, 141, 48, 238, 72, 248, 212, 0, 5, 140, + 81, 28, 81, 59, 29, 161, 138, 42, 6, 187, 129, 168, 184, 241, + 136, 122, 205, 180, 33, 48, 4, 170, 95, 110, 138, 100, 238, 41, + 109, 52, 100, 232, 9, 29, 119, 119, 78, 78, 21, 42, 7, 171, + 25, 222, 142, 76, 14, 212, 154, 196, 47, 70, 213, 224, 35, 250, + 138, 2, 40, 94, 222, 78, 207, 142, 161, 101, 95, 67, 221, 25, + 122, 77, 121, 135, 85, 185, 248, 51, 135, 232, 247, 69, 201, 218, + 158, 253, 55, 86, 64, 196, 163, 147, 4, 31, 94, 233, 41, 42, + 146, 30, 6, 135, 32, 39, 177, 100, 54, 148, 26, 86, 122, 239, + 74, 243, 133, 134, 180, 2, 119, 128, 229, 195, 210, 137, 215, 234, + 225, 62, 84, 3, 250, 77, 217, 252, 6, 114, 182, 45, 7, 217, + 105, 252, 99, 107, 98, 29, 106, 9, 110, 39, 235, 101, 13, 42, + 241, 246, 216, 85, 157, 133, 146, 179, 182, 93, 103, 161, 159, 177, + 246, 221, 228, 84, 30, 172, 236, 47, 56, 139, 143, 0, 63, 103, + 52, 200, 207, 6, 176, 162, 246, 37, 170, 164, 235, 63, 6, 132, + 63, 151, 199, 126, 243, 172, 213, 180, 254, 227, 25, 75, 68, 199, + 175, 15, 221, 241, 234, 136, 57, 160, 37, 78, 94, 206, 107, 14, + 155, 127, 127, 212, 251, 4, 117, 75, 155, 183, 104, 115, 27, 130, + 136, 126, 173, 152, 207, 73, 170, 108, 145, 147, 95, 168, 224, 255, + 254, 10, 163, 46, 211, 100, 141, 86, 197, 50, 171, 248, 237, 52, + 205, 40, 145, 116, 37, 12, 211, 212, 196, 187, 42, 68, 53, 167, + 211, 52, 195, 29, 213, 147, 162, 73, 76, 92, 21, 52, 157, 142, + 195, 17, 89, 206, 90, 252, 255, 242, 254, 25, 96, 239, 178, 255, + 147, 62, 123, 12, 146, 199, 213, 197, 66, 98, 186, 92, 136, 38, + 102, 110, 49, 195, 162, 145, 254, 216, 200, 75, 12, 68, 179, 110, + 24, 15, 218, 246, 155, 62, 194, 245, 28, 12, 224, 95, 240, 202, + 153, 5, 10, 125, 249, 253, 244, 134, 39, 99, 158, 22, 175, 75, + 141, 7, 46, 23, 185, 111, 69, 1, 122, 77, 26, 217, 246, 8, + 84, 216, 167, 153, 126, 118, 93, 128, 142, 60, 41, 208, 154, 79, + 205, 237, 35, 211, 130, 14, 109, 79, 188, 65, 163, 250, 7, 215, + 10, 53, 107, 14, 6, 49, 154, 113, 153, 81, 147, 9, 45, 167, + 85, 145, 227, 128, 152, 212, 124, 80, 83, 105, 44, 96, 65, 171, + 59, 160, 73, 41, 103, 132, 220, 36, 45, 181, 193, 22, 177, 94, + 49, 47, 218, 97, 74, 105, 0, 113, 101, 46, 241, 33, 63, 95, + 0, 154, 254, 75, 74, 230, 249, 58, 204, 204, 191, 96, 45, 147, + 92, 85, 156, 212, 13, 100, 141, 118, 235, 40, 206, 132, 185, 182, + 112, 230, 202, 109, 146, 201, 55, 174, 103, 195, 84, 112, 20, 85, + 125, 102, 241, 37, 84, 116, 6, 9, 63, 36, 81, 228, 233, 45, + 226, 196, 184, 239, 175, 198, 166, 205, 122, 165, 205, 92, 54, 1, + 227, 137, 196, 212, 18, 140, 146, 144, 222, 203, 136, 219, 154, 6, + 112, 19, 160, 96, 212, 26, 36, 176, 194, 254, 0, 70, 164, 91, + 123, 41, 80, 175, 230, 197, 75, 171, 150, 124, 29, 59, 137, 125, + 18, 67, 192, 174, 167, 252, 133, 158, 27, 8, 151, 69, 21, 44, + 15, 170, 45, 228, 64, 46, 74, 233, 99, 120, 236, 105, 130, 9, + 72, 235, 125, 52, 209, 63, 230, 234, 109, 104, 37, 163, 137, 72, + 85, 158, 237, 1, 90, 54, 83, 124, 0, 183, 124, 194, 64, 159, + 168, 186, 224, 65, 62, 230, 109, 217, 103, 169, 250, 54, 99, 148, + 158, 40, 201, 83, 124, 104, 154, 254, 103, 248, 129, 219, 67, 130, + 255, 86, 21, 116, 107, 213, 237, 8, 62, 83, 56, 62, 23, 151, + 30, 100, 28, 85, 218, 97, 233, 83, 121, 20, 48, 8, 19, 228, + 69, 26, 149, 70, 21, 179, 251, 128, 231, 156, 248, 112, 138, 174, + 113, 156, 116, 81, 96, 164, 12, 182, 20, 80, 133, 136, 185, 166, + 172, 125, 30, 20, 202, 81, 193, 181, 253, 114, 187, 14, 243, 131, + 233, 161, 59, 46, 194, 226, 14, 81, 200, 40, 238, 238, 120, 83, + 102, 191, 227, 14, 33, 145, 59, 10, 217, 47, 229, 20, 17, 148, + 80, 227, 243, 157, 84, 168, 74, 108, 147, 11, 20, 30, 63, 125, + 203, 238, 3, 15, 33, 254, 107, 242, 104, 195, 138, 175, 151, 88, + 223, 171, 239, 168, 19, 90, 76, 251, 221, 95, 45, 244, 196, 227, + 114, 42, 239, 233, 18, 62, 81, 140, 50, 232, 33, 207, 132, 171, + 59, 193, 252, 207, 28, 184, 242, 183, 149, 139, 221, 67, 24, 156, + 179, 252, 194, 114, 202, 67, 213, 250, 138, 203, 28, 2, 178, 46, + 164, 97, 199, 195, 237, 48, 134, 98, 166, 63, 75, 42, 46, 67, + 102, 224, 163, 68, 214, 153, 216, 188, 94, 213, 236, 172, 18, 22, + 30, 122, 132, 59, 118, 115, 189, 79, 223, 65, 127, 118, 224, 199, + 245, 30, 5, 254, 164, 143, 16, 127, 210, 116, 72, 130, 17, 179, + 63, 252, 161, 78, 137, 36, 202, 180, 231, 110, 233, 164, 162, 122, + 33, 135, 167, 90, 64, 196, 147, 118, 15, 22, 64, 130, 200, 62, + 71, 106, 54, 174, 118, 96, 94, 69, 177, 231, 83, 241, 199, 65, + 202, 89, 34, 209, 157, 204, 245, 183, 239, 103, 12, 35, 31, 220, + 50, 22, 6, 103, 22, 81, 6, 195, 183, 207, 7, 224, 155, 240, + 109, 85, 227, 157, 235, 101, 12, 47, 3, 189, 98, 11, 123, 121, + 62, 54, 213, 44, 125, 113, 207, 60, 166, 183, 28, 116, 165, 109, + 112, 107, 85, 238, 241, 114, 192, 237, 72, 158, 9, 87, 222, 191, + 246, 103, 66, 227, 133, 74, 251, 107, 37, 245, 26, 184, 216, 157, + 0, 145, 155, 46, 255, 154, 123, 247, 186, 93, 132, 115, 25, 136, + 200, 117, 163, 236, 240, 28, 36, 21, 166, 90, 156, 140, 213, 79, + 132, 48, 57, 117, 104, 31, 137, 14, 198, 113, 132, 32, 147, 21, + 110, 111, 29, 82, 149, 64, 30, 35, 118, 68, 212, 19, 22, 45, + 187, 16, 251, 238, 53, 124, 220, 25, 218, 235, 36, 207, 109, 100, + 8, 66, 67, 67, 94, 40, 13, 105, 77, 128, 1, 20, 2, 0, + 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 99, 108, 101, 97, 114, 116, 111, 109, 97, 114, 107, + 13, 128, 3, +}; diff --git a/Rendering/fonts/face_times.cxx b/Rendering/fonts/face_times.cxx new file mode 100644 index 0000000..887a90f --- /dev/null +++ b/Rendering/fonts/face_times.cxx @@ -0,0 +1,2501 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Times Normal +// Bitstream Charter (c0648bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_times_buffer_length = 34869; + +unsigned char face_times_buffer[] = { + 128, 1, 212, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 70, + 114, 105, 32, 78, 111, 118, 32, 32, 50, 32, 49, 57, 58, 48, + 48, 58, 49, 51, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 66, + 105, 116, 115, 116, 114, 101, 97, 109, 32, 67, 104, 97, 114, 116, + 101, 114, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, + 101, 102, 13, 32, 32, 47, 70, 97, 109, 105, 108, 121, 78, 97, + 109, 101, 32, 40, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 67, 104, 97, 114, 116, 101, 114, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 87, 101, 105, + 103, 104, 116, 32, 40, 78, 111, 114, 109, 97, 108, 41, 32, 114, + 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, + 47, 73, 116, 97, 108, 105, 99, 65, 110, 103, 108, 101, 32, 48, + 32, 100, 101, 102, 13, 32, 32, 47, 105, 115, 70, 105, 120, 101, + 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, 101, 32, 100, + 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, + 101, 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 49, 48, 57, + 32, 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, + 105, 110, 101, 84, 104, 105, 99, 107, 110, 101, 115, 115, 32, 54, + 49, 32, 100, 101, 102, 13, 101, 110, 100, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, + 78, 97, 109, 101, 32, 47, 67, 104, 97, 114, 116, 101, 114, 66, + 84, 45, 82, 111, 109, 97, 110, 32, 100, 101, 102, 13, 47, 80, + 97, 105, 110, 116, 84, 121, 112, 101, 32, 48, 32, 100, 101, 102, + 13, 47, 70, 111, 110, 116, 84, 121, 112, 101, 32, 49, 32, 100, + 101, 102, 13, 47, 70, 111, 110, 116, 77, 97, 116, 114, 105, 120, + 32, 91, 48, 46, 48, 48, 49, 32, 48, 32, 48, 32, 48, 46, + 48, 48, 49, 32, 48, 32, 48, 93, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 47, 69, 110, 99, 111, 100, + 105, 110, 103, 32, 83, 116, 97, 110, 100, 97, 114, 100, 69, 110, + 99, 111, 100, 105, 110, 103, 32, 100, 101, 102, 13, 47, 70, 111, + 110, 116, 66, 66, 111, 120, 32, 123, 45, 49, 54, 49, 32, 45, + 50, 51, 54, 32, 49, 49, 57, 51, 32, 57, 54, 51, 125, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, + 85, 110, 105, 113, 117, 101, 73, 68, 32, 49, 53, 53, 51, 48, + 54, 52, 56, 32, 100, 101, 102, 13, 99, 117, 114, 114, 101, 110, + 116, 100, 105, 99, 116, 32, 101, 110, 100, 13, 99, 117, 114, 114, + 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, 101, 99, 13, + 128, 2, 57, 128, 0, 0, 162, 149, 24, 64, 131, 138, 65, 51, + 131, 156, 169, 210, 46, 43, 153, 242, 182, 28, 118, 124, 214, 117, + 8, 10, 172, 252, 178, 78, 25, 205, 19, 54, 115, 155, 182, 73, + 148, 197, 103, 55, 9, 11, 76, 236, 146, 201, 148, 95, 240, 116, + 94, 247, 255, 198, 27, 176, 169, 163, 184, 73, 231, 233, 135, 64, + 229, 108, 11, 90, 247, 135, 85, 156, 198, 149, 106, 179, 30, 51, + 207, 133, 83, 213, 92, 11, 14, 129, 142, 245, 236, 107, 244, 129, + 98, 234, 196, 46, 115, 128, 202, 146, 29, 174, 28, 130, 179, 143, + 214, 188, 242, 0, 26, 187, 93, 0, 26, 86, 21, 112, 148, 207, + 226, 125, 143, 78, 172, 150, 147, 232, 131, 114, 210, 3, 88, 180, + 126, 12, 56, 118, 85, 142, 191, 117, 122, 31, 188, 92, 28, 221, + 246, 43, 60, 87, 191, 114, 126, 241, 196, 135, 148, 34, 193, 66, + 160, 132, 209, 199, 70, 42, 194, 147, 224, 151, 250, 190, 58, 62, + 207, 205, 130, 113, 242, 89, 131, 59, 172, 121, 18, 112, 114, 24, + 236, 154, 48, 99, 191, 115, 133, 224, 45, 140, 16, 88, 172, 6, + 223, 0, 179, 59, 140, 1, 135, 104, 178, 120, 1, 14, 177, 76, + 139, 251, 203, 112, 53, 193, 144, 96, 26, 105, 221, 239, 150, 122, + 51, 234, 163, 156, 235, 105, 209, 166, 3, 51, 139, 230, 249, 164, + 136, 153, 148, 244, 213, 88, 25, 130, 229, 89, 67, 116, 235, 183, + 86, 5, 45, 103, 204, 244, 110, 26, 174, 228, 209, 169, 158, 86, + 150, 67, 143, 228, 195, 128, 160, 77, 209, 99, 28, 137, 196, 219, + 149, 138, 87, 215, 29, 40, 252, 78, 82, 190, 167, 62, 117, 142, + 227, 185, 68, 47, 206, 140, 159, 10, 121, 80, 155, 127, 188, 162, + 94, 2, 69, 116, 42, 227, 82, 17, 66, 66, 2, 166, 146, 183, + 187, 184, 104, 174, 116, 31, 217, 246, 35, 249, 111, 222, 158, 235, + 170, 35, 46, 129, 65, 7, 60, 63, 157, 56, 42, 230, 140, 41, + 175, 242, 72, 170, 122, 119, 248, 105, 184, 247, 94, 36, 114, 62, + 8, 246, 71, 204, 103, 162, 21, 194, 190, 64, 184, 158, 4, 38, + 150, 4, 135, 118, 189, 115, 112, 197, 218, 149, 203, 197, 19, 196, + 126, 12, 140, 15, 27, 6, 18, 253, 162, 53, 64, 1, 0, 177, + 225, 60, 73, 230, 240, 208, 255, 6, 96, 194, 211, 172, 7, 236, + 157, 101, 225, 52, 73, 13, 68, 139, 186, 25, 170, 15, 1, 50, + 111, 63, 246, 111, 12, 45, 6, 123, 188, 198, 2, 19, 219, 235, + 7, 42, 112, 39, 147, 71, 103, 147, 235, 118, 92, 103, 78, 161, + 12, 176, 60, 45, 29, 1, 4, 228, 5, 62, 238, 15, 89, 39, + 104, 118, 12, 142, 64, 126, 218, 191, 135, 174, 44, 53, 201, 62, + 247, 130, 57, 63, 30, 52, 7, 75, 129, 235, 218, 50, 238, 88, + 123, 80, 192, 19, 20, 74, 195, 82, 250, 251, 104, 237, 222, 110, + 57, 146, 106, 214, 39, 81, 254, 196, 40, 95, 252, 25, 60, 197, + 57, 128, 69, 62, 16, 215, 152, 83, 214, 126, 217, 112, 131, 150, + 218, 61, 162, 140, 209, 97, 120, 248, 60, 133, 157, 143, 31, 118, + 151, 234, 53, 104, 15, 170, 111, 66, 200, 245, 144, 186, 243, 59, + 61, 191, 76, 205, 247, 19, 189, 129, 177, 93, 15, 1, 173, 58, + 10, 125, 253, 103, 27, 143, 253, 174, 207, 207, 231, 192, 122, 112, + 84, 184, 238, 166, 134, 173, 139, 11, 5, 66, 191, 206, 244, 99, + 103, 72, 50, 193, 66, 84, 205, 26, 137, 101, 148, 70, 223, 244, + 23, 72, 125, 74, 50, 253, 251, 7, 44, 96, 212, 15, 106, 48, + 128, 114, 97, 99, 81, 90, 186, 126, 96, 44, 226, 54, 130, 80, + 251, 80, 130, 29, 195, 215, 64, 231, 148, 197, 69, 141, 18, 48, + 232, 107, 36, 214, 20, 97, 232, 66, 102, 59, 182, 189, 230, 84, + 253, 101, 77, 80, 152, 122, 6, 12, 160, 18, 234, 21, 13, 38, + 188, 152, 99, 125, 184, 179, 149, 137, 6, 239, 206, 190, 33, 49, + 49, 147, 73, 252, 116, 105, 16, 216, 241, 210, 190, 93, 167, 228, + 105, 103, 32, 186, 83, 109, 152, 97, 117, 192, 58, 167, 231, 94, + 52, 88, 44, 91, 187, 56, 220, 0, 220, 69, 155, 107, 198, 89, + 162, 234, 185, 204, 229, 115, 120, 62, 0, 184, 191, 207, 184, 21, + 224, 47, 208, 247, 195, 231, 59, 155, 100, 66, 172, 34, 8, 249, + 189, 90, 194, 147, 120, 63, 98, 81, 245, 139, 176, 45, 15, 190, + 234, 179, 254, 65, 221, 119, 124, 66, 198, 216, 205, 19, 165, 134, + 120, 12, 112, 45, 236, 61, 153, 100, 145, 166, 245, 31, 199, 97, + 51, 7, 79, 235, 198, 173, 191, 207, 54, 17, 127, 156, 33, 162, + 198, 57, 177, 122, 5, 231, 249, 108, 110, 71, 70, 98, 112, 243, + 143, 151, 249, 116, 219, 231, 101, 79, 48, 137, 16, 214, 202, 202, + 236, 72, 162, 216, 45, 247, 115, 228, 183, 35, 85, 125, 144, 174, + 237, 9, 5, 184, 185, 84, 255, 235, 80, 68, 163, 188, 150, 69, + 133, 122, 252, 55, 206, 119, 33, 242, 202, 102, 67, 95, 184, 77, + 237, 191, 13, 63, 47, 175, 33, 130, 141, 125, 201, 88, 22, 2, + 197, 91, 209, 196, 93, 127, 204, 229, 185, 141, 94, 27, 32, 28, + 108, 142, 133, 101, 160, 75, 89, 146, 113, 210, 27, 20, 111, 123, + 150, 229, 70, 253, 207, 154, 0, 169, 142, 12, 122, 14, 236, 194, + 76, 136, 193, 219, 191, 134, 83, 201, 143, 129, 15, 25, 37, 59, + 199, 217, 38, 105, 88, 182, 117, 239, 25, 191, 184, 213, 160, 205, + 128, 99, 229, 171, 106, 28, 105, 232, 8, 14, 238, 153, 97, 134, + 103, 197, 223, 35, 57, 125, 203, 111, 249, 107, 3, 129, 36, 16, + 0, 50, 102, 114, 60, 12, 136, 63, 241, 169, 5, 198, 210, 170, + 96, 224, 122, 157, 210, 134, 19, 232, 40, 127, 88, 192, 179, 179, + 28, 108, 38, 22, 56, 140, 113, 100, 240, 187, 31, 130, 20, 85, + 155, 74, 23, 145, 209, 120, 118, 143, 135, 84, 63, 229, 89, 19, + 75, 37, 127, 99, 153, 89, 124, 23, 53, 33, 173, 61, 251, 229, + 111, 222, 147, 252, 108, 136, 47, 146, 7, 149, 115, 187, 151, 16, + 159, 191, 175, 176, 194, 78, 37, 13, 133, 78, 46, 167, 6, 170, + 195, 209, 136, 75, 216, 116, 19, 3, 228, 11, 49, 233, 123, 181, + 183, 200, 3, 58, 172, 166, 181, 57, 212, 60, 121, 185, 140, 151, + 36, 138, 144, 232, 158, 26, 154, 201, 78, 129, 76, 103, 136, 190, + 89, 231, 188, 77, 109, 128, 207, 69, 53, 167, 67, 145, 42, 203, + 86, 4, 219, 75, 58, 246, 39, 202, 211, 74, 224, 255, 94, 216, + 122, 216, 40, 4, 173, 83, 69, 34, 229, 153, 66, 184, 16, 145, + 65, 43, 153, 248, 100, 40, 94, 89, 206, 35, 196, 35, 3, 128, + 169, 211, 112, 213, 56, 46, 156, 185, 88, 54, 220, 237, 221, 37, + 222, 55, 88, 236, 130, 103, 191, 44, 204, 89, 142, 223, 195, 77, + 125, 173, 162, 143, 119, 173, 46, 43, 22, 213, 235, 201, 68, 30, + 22, 195, 245, 133, 248, 20, 112, 130, 41, 143, 168, 177, 18, 202, + 76, 112, 244, 167, 154, 241, 129, 103, 65, 178, 115, 116, 176, 172, + 42, 26, 21, 209, 130, 150, 162, 203, 204, 0, 213, 139, 167, 125, + 90, 136, 67, 161, 84, 3, 60, 122, 12, 224, 159, 164, 113, 25, + 163, 0, 84, 117, 29, 9, 9, 50, 176, 138, 39, 89, 104, 5, + 59, 154, 51, 200, 238, 188, 60, 51, 85, 203, 91, 216, 29, 207, + 168, 118, 15, 235, 25, 79, 230, 70, 18, 140, 208, 222, 57, 243, + 0, 66, 147, 75, 66, 122, 36, 205, 183, 46, 103, 184, 211, 92, + 26, 240, 79, 98, 95, 110, 36, 253, 6, 54, 234, 56, 156, 238, + 240, 155, 24, 36, 88, 138, 240, 116, 1, 245, 17, 147, 202, 60, + 243, 218, 209, 117, 238, 46, 122, 233, 29, 23, 79, 220, 6, 47, + 243, 97, 71, 116, 13, 228, 101, 110, 53, 160, 173, 251, 172, 135, + 122, 130, 14, 95, 196, 95, 208, 159, 156, 135, 156, 128, 52, 19, + 63, 117, 90, 182, 147, 107, 223, 20, 161, 178, 210, 174, 213, 206, + 74, 68, 53, 104, 4, 201, 216, 209, 55, 188, 195, 168, 64, 9, + 19, 33, 207, 45, 238, 198, 52, 210, 35, 125, 123, 132, 5, 164, + 51, 163, 219, 113, 104, 4, 48, 23, 179, 237, 145, 0, 205, 33, + 7, 13, 147, 19, 61, 180, 117, 181, 29, 30, 92, 147, 151, 1, + 215, 254, 208, 81, 240, 98, 136, 7, 173, 71, 95, 2, 187, 35, + 229, 169, 191, 121, 205, 95, 12, 234, 157, 242, 109, 14, 178, 153, + 154, 22, 72, 126, 218, 104, 28, 167, 248, 69, 44, 144, 40, 222, + 80, 50, 216, 142, 104, 96, 180, 112, 79, 38, 182, 43, 190, 102, + 19, 26, 52, 250, 25, 93, 210, 75, 96, 133, 197, 61, 74, 234, + 126, 88, 190, 121, 5, 139, 125, 80, 139, 207, 38, 206, 180, 133, + 59, 227, 247, 117, 192, 71, 134, 134, 115, 197, 173, 76, 234, 185, + 145, 131, 13, 13, 37, 26, 255, 175, 216, 101, 222, 80, 72, 181, + 5, 221, 92, 27, 186, 145, 27, 216, 45, 223, 167, 252, 85, 117, + 131, 223, 101, 193, 137, 162, 152, 183, 18, 136, 33, 52, 222, 42, + 233, 81, 100, 100, 127, 222, 132, 91, 124, 111, 174, 126, 104, 54, + 40, 6, 207, 154, 253, 213, 25, 114, 226, 168, 58, 171, 204, 27, + 175, 34, 233, 231, 225, 184, 204, 120, 149, 208, 189, 202, 191, 89, + 39, 243, 113, 99, 185, 88, 122, 55, 174, 5, 35, 238, 162, 139, + 237, 54, 186, 190, 136, 101, 212, 83, 145, 208, 252, 107, 121, 191, + 146, 223, 81, 16, 99, 44, 41, 205, 47, 13, 91, 126, 111, 64, + 91, 180, 128, 61, 159, 111, 28, 139, 75, 208, 16, 217, 69, 217, + 173, 51, 73, 4, 132, 71, 135, 169, 143, 135, 35, 5, 9, 75, + 149, 148, 75, 124, 211, 27, 104, 61, 5, 243, 183, 154, 177, 224, + 108, 249, 140, 26, 0, 164, 234, 42, 161, 233, 255, 43, 204, 155, + 169, 178, 144, 166, 250, 142, 56, 172, 165, 121, 40, 194, 20, 85, + 135, 42, 210, 164, 234, 8, 244, 104, 45, 60, 54, 130, 11, 189, + 146, 180, 179, 170, 157, 227, 225, 239, 210, 233, 152, 13, 3, 15, + 184, 14, 97, 65, 121, 1, 121, 2, 231, 236, 211, 161, 120, 155, + 116, 168, 62, 37, 134, 12, 128, 147, 59, 38, 98, 206, 22, 60, + 137, 251, 116, 193, 166, 217, 217, 7, 81, 86, 52, 216, 129, 154, + 186, 210, 54, 118, 111, 124, 68, 250, 154, 234, 18, 112, 162, 252, + 131, 138, 6, 187, 34, 78, 156, 178, 10, 97, 77, 142, 149, 73, + 29, 199, 120, 136, 95, 162, 221, 113, 68, 227, 214, 26, 205, 242, + 71, 92, 109, 214, 245, 94, 88, 156, 216, 112, 245, 86, 138, 141, + 158, 14, 26, 191, 249, 249, 231, 9, 121, 196, 117, 28, 174, 216, + 139, 38, 224, 17, 56, 53, 189, 39, 245, 91, 90, 146, 233, 226, + 148, 122, 111, 201, 61, 147, 211, 145, 125, 105, 158, 94, 184, 43, + 190, 217, 139, 93, 119, 27, 229, 75, 12, 65, 2, 32, 63, 48, + 183, 166, 160, 114, 30, 160, 7, 146, 124, 81, 12, 142, 124, 72, + 222, 253, 60, 44, 10, 68, 41, 37, 109, 77, 43, 60, 255, 45, + 161, 93, 174, 231, 108, 243, 145, 105, 230, 75, 111, 212, 236, 141, + 162, 28, 39, 23, 6, 171, 7, 203, 140, 201, 206, 195, 124, 6, + 19, 96, 106, 85, 117, 58, 43, 27, 69, 118, 43, 34, 201, 96, + 38, 238, 131, 178, 131, 192, 104, 148, 29, 170, 15, 81, 151, 179, + 160, 103, 70, 43, 233, 186, 80, 107, 120, 3, 59, 192, 149, 76, + 169, 171, 128, 70, 237, 31, 160, 60, 144, 211, 186, 186, 119, 138, + 48, 194, 140, 179, 59, 192, 90, 60, 117, 114, 73, 64, 164, 52, + 201, 190, 204, 80, 189, 100, 187, 196, 32, 2, 243, 232, 18, 199, + 97, 139, 142, 96, 107, 120, 109, 99, 23, 203, 228, 234, 155, 34, + 236, 99, 186, 20, 255, 54, 22, 175, 49, 157, 228, 211, 178, 31, + 35, 176, 251, 134, 171, 91, 76, 115, 250, 57, 85, 73, 145, 48, + 165, 124, 6, 109, 77, 133, 142, 145, 223, 143, 210, 243, 66, 60, + 46, 254, 31, 233, 44, 17, 210, 237, 91, 42, 108, 230, 9, 101, + 106, 213, 31, 65, 149, 113, 65, 113, 118, 170, 190, 52, 253, 59, + 103, 238, 109, 147, 48, 146, 47, 235, 81, 22, 86, 108, 185, 195, + 139, 168, 217, 180, 4, 192, 77, 37, 193, 70, 48, 118, 66, 238, + 174, 25, 94, 11, 183, 172, 255, 61, 103, 216, 126, 130, 16, 84, + 211, 59, 232, 186, 82, 167, 204, 205, 124, 96, 251, 208, 29, 29, + 129, 123, 249, 48, 5, 187, 138, 39, 29, 216, 47, 218, 71, 55, + 4, 180, 255, 162, 190, 47, 46, 183, 198, 97, 110, 20, 157, 60, + 169, 73, 214, 122, 98, 51, 228, 250, 42, 185, 165, 112, 249, 228, + 240, 20, 206, 19, 50, 125, 220, 93, 219, 248, 103, 48, 121, 68, + 175, 132, 161, 48, 253, 249, 246, 223, 219, 129, 146, 200, 90, 197, + 79, 211, 83, 11, 88, 155, 63, 9, 66, 38, 123, 136, 113, 33, + 212, 187, 202, 34, 11, 216, 217, 128, 231, 98, 51, 87, 77, 47, + 216, 168, 52, 201, 163, 237, 166, 251, 197, 191, 55, 158, 214, 71, + 20, 111, 80, 215, 1, 27, 173, 147, 179, 187, 13, 181, 254, 188, + 251, 217, 124, 144, 226, 116, 19, 200, 44, 124, 116, 192, 215, 179, + 202, 59, 238, 168, 49, 182, 183, 85, 95, 242, 242, 164, 244, 238, + 136, 230, 102, 219, 90, 137, 53, 60, 19, 41, 249, 111, 221, 192, + 96, 57, 54, 164, 27, 122, 229, 147, 144, 36, 237, 180, 148, 136, + 169, 237, 111, 223, 35, 17, 60, 9, 190, 21, 92, 224, 111, 11, + 60, 95, 55, 160, 178, 14, 135, 184, 19, 253, 129, 127, 216, 145, + 150, 47, 167, 35, 192, 254, 69, 226, 237, 16, 47, 233, 71, 29, + 135, 217, 215, 249, 170, 24, 253, 155, 32, 197, 225, 83, 225, 239, + 26, 223, 55, 173, 179, 195, 89, 227, 72, 34, 49, 118, 76, 240, + 107, 193, 195, 108, 114, 189, 155, 139, 69, 147, 131, 152, 39, 101, + 80, 67, 167, 153, 102, 88, 3, 235, 39, 254, 108, 136, 78, 137, + 182, 161, 207, 3, 145, 94, 173, 248, 81, 187, 99, 190, 87, 189, + 50, 171, 144, 16, 172, 168, 196, 30, 113, 92, 253, 248, 58, 13, + 81, 158, 12, 193, 190, 202, 160, 208, 95, 91, 176, 193, 201, 122, + 214, 18, 31, 241, 80, 0, 227, 215, 125, 222, 226, 244, 11, 253, + 240, 165, 241, 7, 154, 218, 253, 44, 69, 47, 121, 184, 80, 137, + 241, 158, 15, 53, 198, 147, 185, 252, 75, 46, 190, 137, 214, 186, + 232, 23, 85, 6, 194, 213, 22, 98, 198, 196, 181, 104, 15, 131, + 171, 28, 147, 82, 14, 254, 92, 70, 57, 39, 121, 246, 237, 153, + 113, 130, 186, 227, 200, 30, 32, 26, 214, 245, 37, 63, 153, 240, + 64, 134, 2, 179, 46, 84, 167, 210, 151, 39, 180, 128, 199, 17, + 91, 203, 227, 100, 206, 120, 123, 219, 198, 210, 51, 6, 52, 91, + 174, 84, 134, 45, 238, 66, 104, 42, 40, 158, 16, 39, 56, 49, + 246, 34, 166, 195, 116, 124, 60, 205, 252, 82, 137, 18, 41, 11, + 41, 86, 52, 243, 161, 147, 214, 171, 45, 53, 110, 97, 85, 66, + 253, 7, 160, 218, 90, 53, 128, 41, 227, 220, 58, 230, 120, 1, + 14, 198, 106, 116, 37, 103, 96, 159, 80, 21, 142, 129, 234, 50, + 209, 39, 41, 7, 69, 122, 3, 217, 194, 178, 120, 10, 29, 182, + 52, 32, 27, 124, 202, 84, 131, 233, 62, 227, 115, 178, 184, 53, + 201, 47, 58, 205, 232, 202, 111, 186, 50, 149, 181, 253, 82, 239, + 201, 139, 119, 20, 232, 168, 107, 70, 219, 230, 97, 221, 122, 227, + 85, 192, 100, 202, 89, 75, 113, 136, 13, 92, 118, 172, 82, 94, + 58, 21, 171, 224, 7, 157, 127, 168, 4, 160, 12, 235, 17, 42, + 230, 120, 243, 7, 230, 95, 237, 178, 49, 49, 38, 94, 39, 139, + 133, 225, 195, 8, 127, 127, 207, 8, 55, 67, 235, 77, 7, 234, + 15, 57, 209, 106, 253, 93, 22, 184, 94, 99, 254, 185, 38, 203, + 142, 230, 84, 26, 61, 182, 162, 237, 102, 138, 57, 237, 14, 6, + 139, 79, 7, 115, 233, 52, 105, 139, 67, 239, 249, 182, 222, 15, + 118, 152, 87, 76, 150, 150, 72, 120, 150, 233, 231, 132, 75, 229, + 10, 4, 155, 185, 188, 240, 250, 40, 4, 224, 188, 248, 31, 90, + 41, 249, 184, 140, 222, 86, 232, 214, 124, 43, 171, 55, 107, 156, + 143, 230, 21, 254, 101, 188, 240, 197, 213, 196, 94, 9, 196, 18, + 229, 184, 45, 18, 176, 67, 121, 48, 131, 164, 106, 97, 97, 249, + 169, 142, 107, 236, 89, 198, 55, 188, 135, 113, 146, 116, 146, 137, + 156, 191, 245, 61, 179, 87, 217, 37, 135, 160, 64, 200, 163, 62, + 110, 254, 84, 84, 100, 109, 145, 112, 190, 7, 115, 61, 141, 92, + 8, 50, 237, 139, 191, 68, 131, 159, 120, 49, 106, 211, 207, 129, + 44, 59, 59, 223, 111, 179, 146, 97, 94, 72, 134, 36, 47, 83, + 156, 192, 217, 101, 255, 124, 178, 188, 79, 234, 202, 243, 183, 120, + 169, 247, 143, 65, 9, 205, 71, 188, 6, 158, 83, 193, 108, 121, + 123, 188, 24, 60, 3, 93, 240, 184, 29, 115, 243, 201, 6, 156, + 38, 139, 92, 237, 184, 192, 52, 247, 217, 247, 76, 3, 242, 87, + 141, 134, 127, 22, 52, 141, 120, 133, 149, 88, 0, 210, 193, 132, + 88, 68, 206, 117, 170, 141, 86, 8, 76, 226, 114, 89, 253, 185, + 132, 133, 131, 237, 103, 23, 178, 157, 166, 150, 159, 26, 12, 210, + 144, 149, 253, 220, 222, 254, 169, 76, 156, 21, 71, 128, 211, 48, + 81, 135, 203, 138, 86, 89, 111, 44, 169, 11, 241, 59, 94, 9, + 26, 44, 116, 71, 113, 1, 220, 114, 243, 20, 145, 88, 189, 232, + 164, 200, 34, 123, 71, 184, 170, 175, 6, 122, 29, 215, 236, 210, + 164, 158, 208, 156, 35, 141, 136, 166, 254, 255, 79, 49, 93, 31, + 185, 140, 153, 158, 3, 68, 18, 47, 54, 112, 169, 6, 111, 68, + 151, 109, 87, 235, 160, 112, 160, 73, 104, 131, 215, 250, 158, 105, + 74, 135, 23, 69, 217, 238, 186, 120, 205, 176, 228, 222, 120, 9, + 50, 22, 147, 155, 135, 1, 90, 144, 208, 200, 87, 246, 152, 111, + 110, 73, 64, 182, 116, 221, 59, 68, 253, 231, 0, 208, 145, 186, + 75, 167, 75, 240, 211, 155, 94, 1, 182, 13, 161, 205, 128, 146, + 251, 178, 169, 242, 121, 132, 104, 133, 223, 249, 86, 174, 228, 102, + 193, 182, 52, 90, 143, 75, 97, 156, 86, 165, 198, 21, 154, 140, + 211, 21, 222, 206, 157, 105, 82, 18, 199, 122, 90, 207, 129, 96, + 29, 61, 243, 203, 82, 226, 29, 182, 60, 19, 27, 72, 205, 247, + 59, 89, 238, 177, 219, 57, 13, 92, 54, 32, 27, 75, 42, 255, + 41, 138, 76, 7, 99, 207, 58, 157, 152, 160, 56, 75, 139, 246, + 135, 149, 146, 72, 194, 30, 248, 218, 105, 60, 189, 214, 31, 60, + 53, 137, 79, 124, 31, 28, 8, 121, 55, 43, 221, 115, 222, 8, + 183, 47, 100, 150, 103, 220, 86, 147, 67, 254, 162, 51, 130, 7, + 131, 242, 168, 187, 3, 154, 98, 225, 194, 148, 31, 192, 26, 250, + 248, 152, 193, 196, 221, 85, 187, 136, 34, 219, 38, 108, 173, 51, + 131, 200, 243, 188, 162, 121, 111, 59, 28, 38, 104, 148, 75, 130, + 164, 255, 121, 3, 115, 152, 195, 21, 93, 58, 54, 119, 67, 227, + 1, 74, 215, 87, 51, 190, 116, 30, 59, 38, 57, 170, 156, 211, + 159, 136, 97, 42, 192, 209, 170, 102, 136, 232, 253, 118, 223, 194, + 142, 125, 10, 155, 32, 182, 28, 158, 11, 155, 107, 244, 46, 158, + 253, 129, 163, 44, 225, 41, 36, 75, 25, 192, 210, 214, 236, 170, + 27, 207, 148, 126, 0, 56, 41, 226, 90, 184, 228, 93, 44, 222, + 121, 119, 151, 161, 157, 185, 31, 119, 192, 147, 247, 197, 224, 230, + 3, 14, 74, 28, 89, 97, 63, 35, 232, 16, 227, 33, 152, 55, + 121, 226, 8, 97, 95, 16, 200, 50, 125, 152, 159, 132, 249, 208, + 223, 188, 11, 229, 251, 97, 192, 40, 169, 164, 185, 251, 57, 32, + 86, 230, 109, 192, 116, 118, 11, 122, 9, 98, 229, 8, 212, 88, + 229, 79, 37, 147, 183, 99, 109, 236, 148, 40, 49, 117, 48, 191, + 81, 42, 221, 233, 94, 160, 2, 139, 209, 30, 26, 30, 198, 138, + 7, 92, 138, 9, 15, 175, 194, 41, 189, 174, 231, 204, 70, 225, + 81, 250, 59, 42, 127, 144, 227, 199, 173, 24, 207, 60, 46, 135, + 189, 184, 189, 47, 135, 152, 161, 154, 31, 52, 166, 111, 182, 0, + 57, 30, 114, 219, 203, 39, 6, 29, 246, 214, 36, 198, 141, 195, + 101, 102, 215, 191, 93, 121, 160, 88, 58, 32, 27, 186, 46, 201, + 115, 46, 136, 110, 231, 64, 112, 226, 139, 165, 151, 77, 103, 67, + 218, 83, 222, 50, 191, 240, 196, 227, 68, 136, 95, 148, 76, 169, + 29, 88, 113, 34, 0, 13, 43, 53, 46, 33, 26, 201, 64, 157, + 99, 108, 44, 98, 43, 251, 65, 167, 162, 115, 79, 242, 69, 146, + 124, 141, 71, 242, 3, 75, 43, 15, 228, 231, 241, 205, 245, 239, + 231, 79, 199, 216, 24, 21, 252, 89, 235, 132, 158, 30, 102, 107, + 105, 220, 10, 214, 33, 51, 32, 118, 179, 56, 151, 58, 213, 14, + 236, 71, 18, 99, 211, 239, 30, 247, 195, 183, 149, 133, 176, 214, + 191, 38, 181, 138, 131, 154, 105, 85, 106, 47, 81, 199, 136, 162, + 236, 20, 193, 117, 95, 28, 69, 72, 106, 160, 196, 240, 210, 88, + 65, 223, 27, 174, 170, 43, 67, 170, 27, 215, 13, 79, 22, 232, + 252, 77, 73, 164, 214, 198, 147, 253, 107, 80, 205, 35, 64, 197, + 241, 193, 227, 90, 176, 214, 113, 83, 251, 153, 227, 148, 122, 26, + 165, 78, 10, 120, 118, 84, 206, 252, 42, 63, 157, 170, 100, 252, + 165, 204, 59, 39, 33, 111, 150, 194, 99, 110, 251, 104, 44, 99, + 135, 131, 19, 141, 24, 123, 136, 5, 23, 52, 194, 185, 196, 0, + 141, 47, 40, 115, 210, 84, 99, 59, 189, 144, 36, 174, 86, 212, + 218, 197, 114, 101, 220, 213, 105, 198, 72, 2, 117, 79, 1, 186, + 100, 134, 251, 10, 106, 13, 126, 250, 252, 126, 51, 2, 20, 171, + 172, 81, 163, 134, 252, 89, 149, 92, 185, 67, 174, 203, 23, 138, + 232, 94, 239, 145, 97, 52, 0, 93, 72, 239, 133, 174, 227, 142, + 238, 99, 235, 123, 122, 103, 213, 2, 115, 114, 181, 254, 46, 115, + 244, 51, 196, 7, 249, 86, 249, 78, 253, 189, 2, 107, 229, 157, + 170, 234, 182, 239, 166, 205, 5, 71, 176, 0, 190, 59, 177, 85, + 44, 36, 229, 71, 76, 145, 153, 66, 179, 67, 143, 230, 202, 83, + 50, 150, 20, 68, 181, 110, 153, 37, 62, 208, 243, 148, 61, 119, + 199, 127, 123, 5, 233, 44, 224, 82, 31, 188, 98, 38, 142, 29, + 132, 159, 168, 179, 100, 24, 1, 41, 83, 57, 178, 112, 42, 170, + 5, 137, 102, 44, 92, 153, 49, 101, 36, 19, 154, 206, 129, 125, + 164, 235, 56, 106, 97, 75, 87, 124, 43, 244, 166, 22, 76, 12, + 8, 31, 9, 244, 38, 189, 164, 190, 229, 86, 110, 232, 105, 56, + 209, 115, 71, 232, 255, 137, 109, 157, 108, 157, 252, 59, 214, 188, + 140, 133, 210, 211, 30, 73, 2, 182, 207, 120, 179, 168, 137, 194, + 115, 246, 50, 150, 127, 155, 252, 179, 185, 109, 103, 33, 50, 203, + 69, 158, 37, 224, 242, 134, 224, 74, 188, 90, 162, 161, 36, 40, + 115, 223, 73, 108, 165, 185, 164, 53, 130, 106, 77, 178, 90, 49, + 172, 213, 140, 190, 113, 47, 90, 87, 105, 217, 78, 22, 67, 151, + 156, 236, 53, 161, 27, 230, 156, 97, 176, 160, 39, 190, 167, 159, + 123, 124, 122, 81, 96, 234, 234, 55, 168, 54, 105, 17, 15, 28, + 145, 7, 142, 14, 98, 87, 167, 17, 220, 13, 82, 178, 55, 41, + 95, 45, 133, 37, 73, 159, 183, 209, 72, 144, 14, 99, 146, 95, + 238, 198, 3, 73, 36, 151, 186, 217, 101, 104, 79, 242, 97, 217, + 98, 68, 120, 215, 249, 39, 247, 94, 23, 24, 214, 180, 122, 14, + 39, 0, 92, 168, 238, 221, 69, 37, 214, 115, 34, 88, 71, 135, + 19, 148, 88, 85, 27, 233, 204, 159, 91, 126, 132, 17, 34, 42, + 8, 51, 130, 122, 243, 210, 227, 49, 244, 223, 193, 154, 182, 234, + 207, 243, 19, 126, 52, 3, 211, 52, 145, 216, 135, 69, 219, 240, + 238, 201, 4, 49, 51, 2, 203, 2, 161, 226, 10, 200, 90, 34, + 246, 211, 212, 8, 104, 187, 212, 227, 216, 44, 3, 206, 69, 89, + 17, 10, 86, 35, 17, 136, 103, 159, 94, 60, 63, 216, 69, 39, + 173, 2, 69, 35, 251, 173, 249, 111, 177, 89, 213, 123, 171, 171, + 27, 39, 107, 69, 231, 52, 155, 231, 106, 23, 5, 95, 81, 109, + 109, 155, 144, 228, 15, 70, 132, 12, 198, 51, 126, 128, 81, 214, + 182, 139, 119, 99, 237, 199, 67, 188, 192, 122, 206, 1, 177, 30, + 231, 153, 49, 116, 22, 3, 12, 96, 21, 197, 184, 128, 65, 115, + 117, 131, 69, 67, 65, 106, 159, 218, 167, 94, 33, 112, 97, 141, + 187, 191, 201, 209, 123, 65, 166, 137, 188, 139, 212, 67, 145, 16, + 159, 105, 26, 44, 52, 1, 227, 99, 0, 127, 178, 24, 167, 111, + 6, 33, 7, 57, 90, 93, 12, 118, 212, 18, 133, 135, 45, 234, + 241, 169, 181, 175, 122, 107, 222, 32, 108, 52, 94, 64, 38, 116, + 236, 43, 25, 197, 123, 31, 66, 22, 95, 13, 93, 143, 171, 127, + 24, 225, 140, 251, 163, 153, 189, 141, 27, 36, 239, 81, 34, 52, + 128, 6, 27, 187, 197, 148, 157, 253, 238, 7, 42, 71, 45, 108, + 245, 201, 37, 171, 185, 167, 157, 81, 9, 81, 80, 67, 78, 242, + 153, 206, 109, 224, 72, 255, 255, 93, 164, 19, 174, 98, 183, 57, + 194, 115, 30, 33, 66, 233, 172, 72, 172, 77, 4, 167, 246, 135, + 206, 178, 144, 76, 112, 15, 164, 129, 116, 104, 109, 40, 128, 104, + 36, 132, 36, 36, 224, 41, 238, 226, 27, 59, 214, 116, 135, 220, + 138, 60, 165, 251, 115, 96, 9, 101, 232, 221, 120, 88, 83, 38, + 130, 148, 160, 227, 62, 255, 74, 242, 19, 242, 246, 190, 190, 38, + 236, 97, 77, 79, 177, 18, 86, 158, 145, 229, 141, 244, 173, 128, + 7, 90, 226, 67, 221, 32, 252, 115, 215, 186, 72, 207, 116, 217, + 245, 212, 195, 247, 165, 249, 105, 210, 69, 238, 6, 218, 121, 243, + 91, 199, 112, 219, 112, 35, 98, 239, 38, 49, 37, 210, 166, 138, + 20, 2, 209, 45, 86, 118, 140, 180, 136, 175, 142, 144, 33, 47, + 206, 142, 194, 147, 154, 43, 151, 208, 9, 94, 245, 160, 230, 130, + 188, 161, 226, 248, 64, 214, 29, 147, 150, 29, 75, 149, 103, 130, + 25, 23, 86, 187, 132, 187, 106, 131, 143, 170, 182, 190, 38, 94, + 109, 221, 117, 223, 108, 196, 15, 67, 144, 113, 97, 124, 182, 14, + 14, 138, 99, 244, 236, 230, 4, 71, 208, 122, 43, 174, 87, 166, + 22, 4, 147, 75, 189, 98, 216, 1, 230, 75, 213, 215, 156, 140, + 50, 134, 253, 207, 41, 122, 215, 171, 156, 197, 48, 245, 99, 110, + 183, 187, 247, 192, 4, 18, 32, 24, 101, 153, 128, 244, 121, 216, + 184, 160, 73, 7, 76, 219, 9, 127, 233, 79, 63, 156, 202, 226, + 22, 220, 9, 126, 194, 89, 216, 102, 12, 244, 176, 162, 161, 153, + 79, 115, 101, 118, 23, 35, 143, 247, 80, 197, 6, 82, 226, 193, + 239, 182, 128, 63, 153, 89, 32, 145, 95, 243, 109, 240, 50, 227, + 94, 205, 196, 103, 185, 111, 31, 247, 242, 162, 80, 115, 255, 121, + 159, 222, 230, 85, 150, 164, 242, 144, 123, 51, 89, 112, 197, 152, + 37, 158, 171, 150, 98, 246, 77, 244, 188, 176, 180, 41, 220, 36, + 195, 206, 231, 30, 169, 98, 9, 174, 27, 139, 16, 120, 44, 15, + 192, 27, 11, 150, 65, 27, 112, 184, 197, 137, 101, 75, 97, 54, + 146, 38, 115, 67, 204, 16, 195, 6, 105, 55, 62, 34, 45, 232, + 218, 47, 150, 15, 156, 140, 87, 110, 128, 57, 253, 40, 37, 136, + 234, 211, 129, 60, 32, 249, 175, 120, 14, 95, 55, 41, 36, 49, + 44, 24, 47, 174, 251, 54, 189, 233, 5, 228, 147, 226, 85, 28, + 106, 197, 78, 124, 18, 189, 89, 174, 235, 158, 190, 217, 109, 38, + 139, 76, 62, 179, 89, 197, 191, 33, 194, 118, 200, 156, 50, 189, + 194, 13, 141, 241, 82, 169, 104, 14, 73, 17, 82, 233, 113, 168, + 50, 42, 223, 179, 13, 184, 192, 132, 82, 91, 61, 220, 250, 244, + 49, 155, 165, 85, 41, 191, 101, 223, 31, 29, 173, 21, 208, 137, + 83, 202, 101, 88, 182, 231, 141, 145, 232, 117, 235, 19, 37, 247, + 252, 232, 20, 139, 147, 44, 33, 62, 144, 64, 223, 188, 23, 233, + 215, 208, 185, 81, 219, 239, 100, 41, 59, 95, 191, 83, 33, 122, + 166, 133, 81, 93, 181, 36, 249, 85, 165, 106, 209, 180, 211, 159, + 126, 230, 183, 108, 6, 130, 8, 181, 255, 162, 118, 148, 175, 33, + 175, 88, 231, 50, 248, 151, 224, 206, 14, 35, 61, 177, 194, 141, + 210, 235, 182, 96, 254, 202, 71, 204, 43, 160, 33, 203, 4, 63, + 126, 35, 128, 175, 111, 137, 254, 150, 87, 25, 8, 130, 91, 180, + 23, 238, 238, 100, 0, 177, 186, 34, 74, 240, 138, 37, 182, 140, + 220, 161, 243, 33, 85, 113, 6, 90, 178, 240, 62, 53, 242, 212, + 153, 11, 207, 153, 241, 41, 149, 241, 12, 95, 222, 205, 242, 200, + 178, 227, 129, 55, 12, 99, 175, 192, 239, 7, 86, 126, 7, 240, + 18, 114, 110, 165, 14, 172, 241, 74, 139, 143, 244, 249, 92, 229, + 55, 234, 122, 80, 208, 40, 165, 32, 228, 23, 220, 208, 131, 87, + 214, 79, 245, 2, 27, 61, 22, 130, 131, 53, 27, 240, 61, 40, + 212, 222, 223, 76, 33, 218, 235, 32, 45, 63, 194, 192, 56, 159, + 129, 56, 144, 57, 204, 232, 186, 205, 194, 187, 100, 94, 124, 107, + 163, 104, 0, 125, 79, 81, 105, 40, 251, 190, 220, 101, 75, 197, + 66, 137, 226, 159, 36, 19, 222, 60, 108, 34, 78, 211, 62, 245, + 47, 36, 81, 72, 124, 58, 127, 187, 39, 80, 9, 134, 36, 48, + 11, 219, 222, 64, 90, 47, 147, 46, 60, 26, 126, 29, 122, 176, + 153, 106, 156, 1, 49, 62, 196, 215, 239, 145, 183, 213, 147, 34, + 86, 81, 99, 182, 170, 113, 222, 34, 204, 74, 73, 190, 231, 91, + 50, 76, 191, 157, 1, 0, 131, 45, 108, 8, 203, 46, 217, 179, + 7, 250, 180, 170, 239, 94, 170, 126, 201, 113, 88, 167, 201, 3, + 139, 64, 91, 105, 158, 30, 201, 84, 184, 41, 160, 132, 184, 91, + 73, 75, 73, 178, 228, 137, 84, 145, 154, 149, 187, 127, 202, 138, + 181, 244, 9, 130, 249, 139, 247, 45, 79, 165, 53, 64, 251, 163, + 111, 147, 166, 16, 242, 166, 229, 20, 31, 236, 229, 104, 11, 53, + 141, 198, 141, 25, 219, 227, 185, 205, 54, 83, 91, 75, 179, 138, + 92, 125, 19, 186, 145, 63, 173, 78, 226, 112, 160, 136, 179, 57, + 69, 165, 54, 112, 139, 38, 209, 245, 227, 101, 160, 4, 132, 142, + 91, 28, 62, 152, 241, 4, 228, 85, 229, 46, 175, 244, 83, 87, + 70, 105, 132, 229, 103, 235, 7, 224, 234, 253, 76, 215, 203, 33, + 240, 17, 23, 47, 160, 129, 175, 95, 64, 218, 47, 106, 21, 17, + 54, 80, 172, 21, 130, 114, 170, 201, 206, 189, 225, 61, 74, 89, + 24, 63, 40, 227, 78, 234, 165, 183, 217, 150, 5, 6, 253, 242, + 126, 227, 42, 129, 66, 38, 199, 26, 146, 12, 157, 202, 170, 194, + 79, 127, 46, 66, 226, 135, 72, 117, 68, 154, 66, 249, 148, 32, + 133, 231, 222, 142, 47, 238, 5, 212, 115, 86, 35, 107, 102, 199, + 72, 162, 244, 224, 150, 100, 182, 102, 201, 174, 100, 227, 101, 199, + 170, 215, 178, 79, 9, 102, 54, 216, 242, 41, 56, 152, 45, 127, + 162, 10, 205, 163, 69, 5, 93, 52, 238, 97, 35, 205, 191, 210, + 190, 236, 196, 192, 196, 226, 201, 184, 235, 78, 200, 228, 219, 40, + 7, 51, 76, 54, 109, 162, 118, 74, 254, 194, 74, 97, 220, 37, + 144, 196, 142, 168, 131, 250, 168, 85, 57, 65, 77, 3, 119, 128, + 224, 202, 59, 16, 232, 7, 80, 13, 79, 0, 176, 122, 32, 113, + 5, 35, 228, 84, 48, 143, 224, 254, 55, 86, 105, 176, 139, 25, + 104, 41, 174, 98, 143, 249, 131, 191, 94, 202, 131, 190, 70, 217, + 139, 0, 255, 133, 214, 48, 209, 103, 91, 56, 14, 102, 172, 89, + 139, 178, 181, 218, 131, 71, 130, 80, 226, 39, 251, 13, 107, 68, + 85, 135, 239, 235, 33, 16, 148, 100, 154, 121, 147, 137, 129, 62, + 247, 133, 11, 132, 120, 180, 80, 185, 92, 203, 50, 74, 81, 133, + 60, 134, 27, 2, 215, 40, 181, 171, 26, 48, 186, 58, 225, 6, + 27, 42, 30, 211, 155, 48, 18, 120, 50, 66, 60, 239, 70, 144, + 29, 36, 202, 38, 226, 160, 242, 184, 157, 204, 48, 174, 249, 91, + 96, 255, 219, 165, 200, 6, 183, 74, 132, 44, 20, 136, 60, 127, + 216, 194, 250, 123, 106, 67, 29, 75, 121, 135, 47, 78, 198, 127, + 166, 236, 161, 87, 120, 55, 230, 71, 7, 222, 195, 50, 248, 61, + 104, 32, 9, 131, 39, 185, 75, 68, 150, 118, 184, 19, 5, 87, + 194, 215, 162, 220, 24, 169, 179, 39, 140, 136, 14, 113, 187, 204, + 6, 12, 127, 202, 202, 134, 22, 116, 157, 112, 211, 217, 29, 194, + 41, 170, 186, 134, 184, 19, 244, 50, 66, 183, 242, 207, 86, 212, + 45, 30, 167, 201, 92, 163, 71, 50, 67, 180, 237, 13, 44, 109, + 100, 133, 21, 152, 114, 233, 163, 46, 148, 177, 182, 102, 248, 12, + 46, 213, 249, 184, 175, 77, 114, 133, 228, 90, 94, 99, 40, 25, + 160, 12, 218, 145, 174, 111, 84, 239, 114, 131, 233, 102, 153, 181, + 163, 23, 219, 112, 14, 117, 240, 252, 90, 226, 135, 191, 129, 233, + 134, 215, 130, 188, 223, 125, 214, 35, 220, 40, 255, 161, 155, 181, + 223, 29, 211, 102, 115, 27, 4, 211, 197, 166, 93, 115, 31, 218, + 134, 195, 95, 32, 255, 68, 7, 117, 225, 130, 142, 147, 99, 77, + 106, 48, 111, 237, 221, 57, 209, 42, 73, 243, 158, 100, 226, 150, + 248, 30, 86, 45, 175, 86, 96, 50, 61, 138, 220, 195, 35, 86, + 136, 110, 130, 184, 209, 91, 159, 50, 66, 209, 90, 46, 175, 71, + 82, 153, 24, 155, 131, 32, 146, 63, 201, 119, 87, 147, 120, 45, + 82, 216, 241, 228, 209, 1, 203, 245, 172, 86, 244, 176, 82, 109, + 112, 2, 148, 227, 211, 98, 35, 171, 237, 221, 195, 25, 241, 227, + 124, 209, 91, 194, 13, 111, 94, 181, 98, 250, 148, 209, 72, 58, + 122, 164, 209, 158, 193, 134, 141, 172, 255, 155, 110, 199, 15, 198, + 162, 110, 89, 63, 215, 156, 190, 251, 123, 208, 34, 221, 127, 181, + 184, 250, 110, 58, 46, 167, 213, 0, 229, 37, 21, 154, 115, 76, + 190, 34, 82, 159, 110, 94, 109, 68, 225, 234, 219, 230, 160, 186, + 142, 95, 153, 125, 205, 187, 5, 99, 44, 250, 225, 3, 81, 40, + 105, 24, 44, 4, 148, 99, 160, 68, 46, 43, 195, 177, 72, 181, + 5, 18, 100, 101, 209, 148, 213, 40, 52, 196, 135, 124, 48, 203, + 165, 126, 241, 185, 78, 122, 147, 170, 1, 92, 113, 175, 232, 84, + 102, 222, 129, 39, 62, 61, 87, 196, 62, 100, 113, 156, 0, 103, + 70, 164, 28, 221, 57, 158, 52, 47, 34, 246, 95, 5, 7, 20, + 173, 254, 213, 55, 163, 119, 97, 95, 196, 220, 61, 34, 192, 101, + 32, 215, 131, 111, 214, 137, 68, 240, 247, 153, 225, 196, 79, 122, + 125, 218, 157, 147, 49, 199, 40, 128, 214, 110, 181, 91, 138, 131, + 62, 32, 224, 80, 205, 182, 195, 212, 222, 133, 19, 29, 215, 2, + 208, 230, 179, 47, 7, 206, 234, 164, 23, 239, 113, 252, 105, 83, + 80, 231, 208, 225, 51, 134, 16, 93, 95, 139, 192, 232, 69, 220, + 233, 224, 63, 153, 204, 13, 203, 213, 17, 91, 220, 208, 110, 170, + 212, 59, 100, 200, 217, 233, 162, 79, 138, 123, 100, 72, 162, 44, + 23, 224, 82, 223, 217, 190, 253, 151, 248, 54, 144, 98, 140, 22, + 126, 161, 103, 236, 61, 124, 118, 67, 249, 84, 103, 71, 92, 112, + 12, 146, 0, 193, 165, 156, 244, 1, 208, 95, 160, 106, 3, 111, + 2, 195, 174, 198, 30, 192, 14, 233, 171, 163, 80, 233, 16, 182, + 214, 153, 219, 222, 253, 119, 50, 163, 179, 117, 219, 27, 254, 6, + 223, 33, 104, 101, 212, 137, 5, 38, 234, 247, 148, 141, 63, 245, + 46, 42, 225, 70, 161, 145, 140, 139, 105, 48, 252, 232, 68, 122, + 138, 36, 153, 172, 37, 202, 159, 58, 93, 28, 156, 132, 234, 195, + 190, 78, 7, 139, 233, 122, 37, 77, 252, 192, 93, 229, 168, 52, + 88, 53, 230, 85, 225, 115, 178, 9, 201, 98, 242, 133, 185, 198, + 138, 230, 63, 67, 217, 208, 143, 116, 174, 216, 196, 48, 70, 136, + 138, 200, 83, 155, 48, 234, 27, 72, 127, 16, 148, 167, 221, 92, + 25, 205, 31, 235, 67, 152, 199, 229, 82, 191, 61, 225, 238, 45, + 151, 158, 224, 100, 129, 8, 219, 69, 140, 63, 212, 80, 57, 125, + 33, 143, 93, 120, 158, 234, 178, 99, 250, 249, 37, 221, 237, 41, + 221, 163, 79, 122, 162, 191, 3, 41, 112, 51, 214, 152, 86, 114, + 179, 147, 216, 41, 78, 201, 124, 226, 237, 181, 22, 105, 96, 171, + 204, 206, 112, 67, 91, 153, 152, 64, 9, 19, 143, 215, 144, 99, + 108, 226, 212, 175, 57, 139, 218, 29, 255, 76, 122, 41, 233, 94, + 227, 187, 233, 138, 143, 225, 102, 200, 71, 231, 207, 193, 122, 214, + 1, 245, 115, 244, 209, 211, 77, 114, 138, 236, 117, 162, 206, 83, + 52, 24, 193, 45, 213, 248, 20, 42, 230, 197, 170, 148, 94, 187, + 238, 91, 245, 126, 195, 233, 250, 224, 208, 190, 237, 184, 39, 109, + 53, 232, 156, 230, 191, 52, 173, 101, 72, 208, 242, 243, 213, 169, + 110, 73, 9, 32, 44, 105, 138, 209, 225, 182, 93, 43, 177, 199, + 192, 21, 204, 143, 248, 179, 248, 64, 173, 181, 229, 27, 171, 28, + 177, 248, 24, 129, 187, 138, 170, 161, 215, 70, 62, 214, 156, 175, + 6, 47, 148, 24, 80, 39, 219, 2, 44, 42, 164, 198, 253, 210, + 123, 115, 249, 241, 51, 187, 19, 45, 91, 229, 56, 82, 235, 79, + 161, 165, 145, 116, 166, 144, 206, 108, 196, 253, 95, 192, 37, 174, + 247, 197, 249, 6, 157, 176, 15, 51, 126, 157, 31, 145, 69, 112, + 162, 140, 125, 89, 34, 121, 120, 12, 29, 239, 52, 175, 125, 180, + 217, 70, 144, 100, 150, 222, 229, 216, 11, 101, 73, 104, 87, 6, + 189, 100, 243, 87, 87, 195, 29, 150, 20, 167, 115, 194, 128, 111, + 43, 58, 121, 120, 11, 244, 204, 220, 226, 88, 12, 77, 161, 95, + 65, 44, 24, 174, 167, 126, 22, 208, 138, 71, 252, 68, 84, 2, + 168, 255, 93, 116, 252, 50, 166, 92, 166, 253, 207, 103, 152, 62, + 131, 44, 136, 38, 194, 219, 182, 254, 134, 34, 242, 242, 124, 99, + 227, 100, 24, 74, 62, 128, 155, 224, 226, 23, 223, 209, 216, 54, + 173, 2, 21, 27, 163, 96, 64, 118, 211, 1, 187, 17, 229, 139, + 8, 129, 62, 51, 92, 87, 71, 237, 83, 11, 11, 55, 76, 180, + 90, 144, 213, 3, 226, 240, 177, 135, 198, 236, 114, 108, 157, 200, + 39, 182, 108, 211, 50, 221, 84, 80, 2, 12, 0, 162, 100, 223, + 254, 110, 81, 28, 4, 192, 231, 32, 218, 29, 14, 205, 171, 84, + 145, 16, 145, 169, 75, 74, 187, 176, 37, 190, 255, 91, 180, 157, + 26, 71, 175, 191, 156, 211, 205, 172, 26, 28, 36, 91, 42, 83, + 24, 82, 153, 109, 203, 239, 156, 144, 238, 97, 33, 64, 156, 209, + 47, 39, 217, 225, 170, 45, 154, 21, 79, 21, 150, 251, 143, 11, + 124, 20, 19, 253, 188, 14, 232, 248, 101, 207, 234, 1, 228, 108, + 108, 209, 29, 67, 12, 196, 251, 192, 143, 214, 68, 28, 10, 234, + 108, 34, 33, 15, 99, 100, 13, 115, 76, 241, 202, 22, 235, 148, + 93, 38, 55, 186, 162, 209, 132, 154, 165, 12, 28, 96, 248, 4, + 105, 81, 171, 102, 36, 110, 134, 81, 57, 46, 115, 174, 249, 146, + 100, 113, 52, 139, 173, 240, 157, 83, 47, 245, 198, 220, 219, 178, + 89, 136, 93, 168, 51, 153, 243, 246, 151, 12, 227, 62, 186, 91, + 108, 204, 173, 185, 0, 24, 39, 17, 157, 34, 168, 182, 163, 56, + 78, 138, 22, 250, 51, 172, 49, 176, 118, 90, 207, 64, 201, 7, + 42, 26, 34, 128, 107, 166, 188, 190, 77, 57, 198, 242, 60, 244, + 133, 124, 36, 70, 149, 44, 35, 23, 47, 18, 78, 79, 25, 98, + 13, 122, 158, 39, 153, 49, 88, 232, 47, 59, 157, 209, 121, 239, + 6, 52, 84, 142, 131, 239, 59, 40, 6, 206, 147, 116, 164, 243, + 179, 218, 242, 9, 64, 7, 13, 153, 95, 66, 229, 56, 2, 105, + 125, 124, 106, 247, 249, 143, 131, 144, 8, 25, 19, 165, 34, 78, + 150, 68, 244, 205, 22, 42, 149, 224, 121, 151, 2, 155, 52, 224, + 241, 30, 184, 175, 87, 239, 125, 241, 70, 14, 21, 23, 228, 233, + 205, 90, 249, 145, 20, 224, 254, 181, 137, 77, 103, 138, 76, 222, + 183, 97, 250, 235, 174, 217, 135, 226, 22, 180, 168, 8, 9, 36, + 114, 182, 250, 27, 97, 206, 206, 240, 147, 99, 243, 49, 197, 44, + 113, 42, 109, 214, 37, 213, 206, 86, 245, 38, 234, 241, 91, 42, + 234, 54, 72, 197, 93, 122, 14, 107, 82, 60, 150, 235, 49, 196, + 231, 137, 127, 230, 53, 62, 180, 196, 253, 98, 250, 88, 27, 174, + 99, 80, 118, 79, 131, 134, 50, 240, 191, 161, 219, 115, 39, 47, + 27, 13, 73, 70, 21, 114, 227, 200, 84, 193, 255, 133, 44, 133, + 157, 244, 47, 3, 79, 16, 9, 11, 244, 139, 218, 14, 69, 64, + 132, 198, 113, 71, 228, 67, 212, 243, 233, 241, 135, 194, 8, 182, + 243, 63, 87, 230, 31, 197, 178, 109, 202, 95, 121, 240, 125, 36, + 169, 200, 109, 204, 117, 150, 23, 231, 11, 255, 91, 14, 13, 60, + 52, 75, 91, 63, 113, 16, 121, 95, 51, 157, 234, 208, 136, 22, + 126, 216, 102, 59, 159, 120, 236, 13, 105, 114, 35, 124, 153, 35, + 219, 48, 200, 31, 94, 229, 127, 164, 87, 105, 6, 153, 55, 247, + 49, 86, 121, 171, 39, 37, 232, 61, 121, 122, 254, 96, 30, 142, + 187, 79, 210, 26, 80, 252, 151, 26, 189, 37, 140, 249, 31, 225, + 78, 88, 85, 46, 116, 2, 243, 4, 33, 193, 119, 97, 123, 58, + 145, 240, 135, 25, 248, 145, 154, 18, 182, 61, 112, 92, 246, 239, + 231, 252, 45, 0, 80, 230, 90, 5, 237, 185, 21, 50, 194, 223, + 112, 14, 33, 247, 172, 89, 40, 166, 118, 1, 115, 166, 156, 28, + 208, 139, 87, 58, 99, 50, 224, 9, 205, 150, 174, 18, 202, 64, + 206, 79, 108, 104, 96, 144, 184, 2, 65, 20, 219, 172, 205, 40, + 19, 203, 25, 255, 191, 11, 97, 63, 8, 99, 45, 116, 147, 120, + 63, 166, 53, 48, 147, 10, 64, 54, 187, 164, 27, 208, 178, 65, + 72, 104, 110, 193, 150, 86, 125, 167, 202, 1, 19, 97, 45, 128, + 231, 227, 55, 48, 16, 168, 101, 161, 199, 35, 153, 32, 141, 68, + 6, 155, 155, 5, 217, 119, 135, 78, 102, 92, 13, 151, 124, 3, + 221, 188, 33, 98, 16, 240, 254, 26, 220, 59, 133, 142, 239, 116, + 211, 61, 84, 242, 245, 236, 249, 31, 218, 214, 29, 12, 168, 209, + 153, 18, 2, 16, 162, 104, 170, 54, 182, 45, 129, 180, 115, 37, + 247, 120, 249, 38, 141, 225, 244, 198, 25, 88, 34, 42, 63, 128, + 183, 122, 100, 128, 233, 117, 213, 98, 42, 209, 169, 19, 38, 140, + 164, 48, 124, 217, 209, 107, 56, 218, 37, 138, 218, 140, 189, 193, + 74, 30, 59, 15, 190, 182, 251, 114, 3, 224, 20, 103, 156, 68, + 84, 172, 217, 190, 97, 208, 250, 56, 161, 128, 46, 225, 118, 235, + 108, 158, 174, 178, 166, 140, 138, 171, 152, 6, 97, 195, 119, 229, + 120, 32, 227, 55, 7, 116, 54, 143, 171, 7, 98, 30, 113, 143, + 251, 228, 23, 21, 124, 183, 244, 116, 17, 234, 150, 150, 115, 56, + 187, 26, 162, 223, 180, 164, 1, 90, 144, 241, 91, 119, 31, 224, + 55, 178, 118, 193, 223, 198, 166, 162, 145, 12, 188, 7, 188, 9, + 2, 69, 111, 198, 106, 136, 35, 241, 158, 195, 117, 128, 115, 100, + 147, 90, 165, 83, 233, 12, 133, 165, 139, 77, 217, 108, 96, 51, + 148, 126, 166, 22, 136, 168, 32, 115, 152, 252, 140, 127, 23, 94, + 20, 38, 71, 113, 187, 1, 232, 28, 165, 25, 201, 38, 171, 185, + 214, 7, 75, 217, 247, 10, 214, 240, 146, 175, 109, 109, 70, 196, + 191, 153, 67, 134, 175, 117, 113, 159, 173, 95, 74, 90, 198, 64, + 51, 85, 47, 184, 79, 180, 122, 163, 114, 50, 94, 25, 145, 111, + 174, 27, 59, 48, 116, 197, 48, 222, 66, 32, 79, 126, 115, 193, + 69, 118, 198, 73, 128, 203, 79, 174, 22, 179, 69, 125, 91, 253, + 162, 104, 226, 157, 197, 85, 185, 117, 42, 124, 24, 108, 163, 67, + 39, 79, 19, 140, 57, 87, 169, 220, 83, 167, 210, 240, 78, 132, + 140, 84, 157, 164, 6, 20, 83, 28, 175, 129, 181, 204, 36, 117, + 116, 84, 97, 206, 24, 74, 43, 50, 192, 42, 51, 180, 95, 137, + 119, 157, 139, 54, 61, 47, 65, 246, 21, 182, 65, 9, 125, 86, + 143, 129, 114, 154, 81, 171, 252, 154, 9, 18, 226, 196, 175, 41, + 233, 100, 21, 165, 248, 222, 220, 136, 3, 152, 194, 80, 234, 233, + 7, 160, 50, 70, 80, 52, 131, 204, 63, 50, 237, 180, 40, 164, + 124, 34, 217, 41, 66, 43, 131, 17, 39, 152, 20, 207, 222, 205, + 247, 117, 70, 225, 8, 63, 149, 162, 200, 164, 128, 51, 220, 233, + 224, 195, 229, 32, 195, 38, 116, 192, 92, 228, 203, 229, 47, 175, + 219, 65, 84, 169, 37, 94, 13, 32, 127, 90, 152, 24, 170, 183, + 224, 34, 248, 144, 120, 70, 118, 215, 141, 182, 18, 177, 78, 107, + 183, 63, 73, 28, 151, 29, 28, 233, 41, 189, 246, 34, 5, 13, + 207, 72, 31, 202, 50, 51, 98, 118, 156, 183, 35, 101, 171, 83, + 20, 93, 198, 245, 28, 41, 105, 71, 165, 129, 164, 57, 167, 174, + 164, 148, 108, 41, 95, 114, 241, 231, 255, 84, 209, 70, 199, 175, + 84, 110, 174, 135, 198, 3, 226, 250, 38, 251, 119, 168, 24, 132, + 137, 35, 147, 57, 143, 6, 54, 84, 92, 231, 200, 186, 97, 79, + 98, 191, 87, 27, 233, 204, 159, 91, 126, 132, 105, 151, 192, 90, + 138, 65, 139, 2, 131, 189, 229, 191, 240, 213, 66, 185, 52, 29, + 81, 182, 16, 172, 85, 214, 203, 17, 149, 216, 124, 47, 113, 96, + 107, 36, 81, 59, 118, 99, 221, 52, 84, 11, 50, 227, 234, 154, + 249, 179, 130, 106, 172, 246, 228, 113, 98, 88, 110, 187, 240, 227, + 22, 35, 133, 147, 177, 49, 209, 20, 254, 228, 36, 98, 189, 57, + 148, 228, 84, 219, 114, 33, 248, 125, 76, 163, 138, 11, 105, 158, + 132, 202, 35, 15, 251, 80, 149, 249, 10, 97, 210, 106, 26, 251, + 2, 40, 99, 76, 104, 145, 245, 192, 22, 136, 7, 238, 93, 192, + 130, 246, 190, 228, 204, 20, 101, 231, 152, 80, 95, 118, 34, 108, + 151, 185, 243, 142, 206, 118, 215, 157, 44, 79, 219, 161, 97, 63, + 160, 156, 167, 41, 180, 191, 87, 164, 73, 215, 198, 187, 135, 13, + 18, 127, 98, 0, 197, 235, 177, 116, 46, 125, 98, 157, 47, 74, + 138, 87, 125, 24, 192, 245, 14, 60, 98, 216, 66, 168, 209, 77, + 69, 178, 190, 182, 207, 187, 189, 190, 62, 27, 161, 212, 157, 111, + 49, 48, 6, 198, 248, 224, 82, 226, 150, 111, 49, 53, 8, 154, + 226, 106, 141, 106, 87, 157, 231, 102, 255, 167, 26, 35, 128, 253, + 72, 206, 162, 130, 169, 61, 3, 2, 114, 63, 57, 43, 26, 196, + 250, 222, 222, 95, 180, 106, 82, 12, 253, 141, 218, 192, 171, 45, + 86, 85, 185, 186, 32, 105, 246, 0, 38, 52, 43, 49, 42, 24, + 188, 152, 170, 196, 25, 80, 197, 52, 136, 23, 116, 121, 124, 149, + 135, 164, 139, 7, 82, 117, 30, 119, 163, 22, 252, 197, 118, 143, + 4, 92, 66, 63, 96, 247, 137, 191, 238, 116, 47, 31, 225, 42, + 188, 162, 27, 171, 8, 75, 52, 29, 82, 29, 218, 244, 151, 10, + 47, 147, 158, 145, 117, 239, 121, 52, 179, 213, 222, 4, 98, 202, + 24, 65, 98, 90, 48, 160, 41, 90, 192, 160, 93, 52, 96, 218, + 209, 77, 127, 160, 217, 13, 17, 158, 149, 19, 242, 14, 55, 159, + 25, 113, 211, 105, 99, 157, 26, 76, 78, 157, 125, 153, 135, 123, + 74, 80, 54, 230, 138, 20, 236, 17, 110, 2, 15, 35, 231, 194, + 107, 82, 11, 187, 76, 126, 212, 166, 152, 172, 229, 144, 195, 183, + 245, 176, 113, 245, 67, 0, 34, 102, 140, 255, 88, 94, 10, 209, + 253, 175, 6, 87, 26, 0, 225, 133, 60, 19, 101, 245, 39, 160, + 196, 68, 240, 106, 125, 14, 41, 2, 167, 217, 36, 115, 104, 228, + 242, 157, 209, 160, 189, 28, 122, 47, 112, 135, 88, 55, 238, 222, + 204, 137, 197, 46, 23, 189, 170, 189, 235, 240, 96, 122, 196, 213, + 239, 122, 56, 138, 237, 210, 122, 249, 129, 24, 149, 210, 67, 91, + 31, 226, 85, 24, 227, 110, 219, 29, 251, 42, 196, 194, 145, 255, + 241, 197, 160, 245, 164, 253, 209, 10, 33, 202, 139, 115, 157, 1, + 71, 163, 248, 166, 209, 154, 187, 133, 44, 86, 110, 148, 78, 178, + 79, 130, 60, 120, 55, 10, 231, 21, 148, 196, 235, 203, 128, 179, + 206, 186, 161, 3, 115, 234, 234, 193, 205, 78, 67, 56, 170, 155, + 77, 241, 155, 221, 100, 251, 97, 103, 8, 245, 17, 209, 4, 89, + 188, 221, 229, 114, 15, 250, 172, 230, 247, 57, 200, 50, 204, 134, + 33, 122, 228, 7, 119, 144, 56, 40, 38, 34, 141, 164, 207, 27, + 241, 1, 40, 27, 207, 247, 198, 75, 254, 149, 129, 150, 220, 146, + 185, 119, 221, 26, 163, 80, 164, 167, 108, 126, 112, 93, 105, 119, + 82, 57, 254, 201, 219, 198, 251, 222, 35, 171, 26, 66, 188, 223, + 50, 165, 39, 238, 64, 172, 169, 153, 214, 9, 41, 197, 227, 9, + 9, 88, 183, 0, 151, 224, 47, 78, 114, 36, 133, 249, 57, 14, + 247, 250, 7, 171, 110, 84, 201, 160, 7, 159, 63, 23, 156, 63, + 222, 91, 176, 37, 83, 109, 115, 45, 164, 92, 22, 201, 80, 249, + 27, 58, 180, 255, 230, 97, 84, 8, 166, 223, 22, 146, 14, 46, + 150, 127, 251, 84, 251, 167, 131, 72, 106, 52, 206, 230, 195, 200, + 129, 207, 225, 95, 213, 168, 149, 51, 103, 58, 9, 24, 179, 76, + 113, 139, 190, 152, 102, 72, 72, 134, 124, 182, 153, 177, 127, 156, + 3, 131, 194, 60, 196, 128, 195, 162, 206, 30, 195, 70, 255, 203, + 56, 196, 73, 79, 199, 211, 3, 86, 96, 110, 12, 159, 114, 62, + 35, 18, 170, 200, 246, 125, 134, 160, 59, 185, 235, 201, 68, 139, + 139, 153, 213, 129, 100, 37, 73, 236, 230, 111, 148, 158, 3, 53, + 10, 211, 161, 169, 128, 93, 31, 126, 186, 52, 41, 23, 219, 7, + 156, 165, 148, 219, 136, 201, 97, 69, 15, 209, 70, 75, 19, 11, + 90, 203, 129, 63, 235, 113, 232, 130, 136, 216, 143, 94, 58, 2, + 35, 104, 99, 93, 139, 77, 88, 164, 159, 185, 101, 178, 197, 44, + 122, 163, 51, 2, 102, 131, 103, 113, 211, 134, 46, 199, 241, 194, + 41, 58, 21, 11, 174, 94, 170, 156, 185, 49, 202, 130, 25, 165, + 218, 121, 215, 198, 225, 123, 209, 255, 9, 94, 176, 112, 41, 167, + 124, 104, 146, 102, 24, 16, 213, 151, 63, 88, 119, 141, 72, 70, + 56, 165, 111, 95, 211, 65, 96, 43, 77, 74, 30, 108, 65, 248, + 12, 204, 230, 153, 158, 127, 169, 41, 220, 229, 184, 18, 86, 235, + 235, 13, 214, 67, 214, 25, 88, 108, 238, 242, 190, 41, 206, 65, + 4, 10, 244, 109, 160, 55, 149, 9, 147, 46, 45, 8, 196, 114, + 202, 208, 189, 220, 156, 1, 150, 75, 115, 218, 141, 116, 217, 8, + 173, 184, 57, 212, 0, 49, 238, 151, 13, 9, 239, 182, 12, 29, + 56, 248, 37, 234, 191, 82, 79, 187, 86, 25, 214, 103, 183, 49, + 149, 26, 173, 118, 153, 126, 208, 176, 37, 100, 57, 28, 32, 81, + 157, 235, 128, 23, 153, 52, 46, 193, 9, 36, 48, 29, 161, 66, + 231, 7, 117, 105, 13, 13, 146, 222, 149, 60, 204, 245, 182, 91, + 212, 156, 233, 33, 67, 247, 69, 172, 74, 12, 29, 29, 191, 143, + 165, 178, 7, 47, 134, 168, 197, 17, 82, 87, 110, 158, 110, 25, + 97, 164, 104, 64, 92, 169, 34, 168, 87, 131, 118, 247, 136, 196, + 155, 54, 237, 237, 49, 229, 90, 180, 57, 117, 43, 161, 149, 240, + 88, 221, 0, 20, 176, 60, 126, 151, 219, 224, 111, 194, 6, 75, + 196, 185, 154, 140, 177, 10, 134, 231, 157, 115, 13, 100, 192, 93, + 56, 240, 24, 199, 178, 155, 107, 177, 92, 56, 164, 216, 123, 188, + 152, 13, 105, 137, 199, 236, 156, 179, 205, 252, 88, 227, 119, 98, + 70, 203, 74, 77, 112, 12, 108, 38, 243, 105, 6, 31, 132, 237, + 98, 71, 128, 117, 226, 89, 235, 132, 117, 200, 214, 11, 200, 107, + 10, 35, 37, 93, 206, 77, 35, 135, 109, 14, 209, 144, 40, 76, + 184, 229, 5, 19, 88, 24, 102, 43, 133, 247, 112, 166, 223, 54, + 244, 197, 177, 98, 238, 126, 31, 166, 175, 186, 220, 131, 83, 117, + 237, 58, 216, 98, 205, 250, 156, 246, 136, 31, 116, 1, 134, 64, + 159, 36, 6, 192, 201, 251, 132, 49, 182, 37, 225, 99, 121, 54, + 197, 111, 38, 109, 82, 36, 252, 65, 72, 189, 26, 23, 174, 80, + 223, 73, 130, 177, 139, 245, 81, 89, 127, 11, 27, 243, 88, 158, + 108, 116, 104, 237, 76, 244, 20, 221, 210, 252, 50, 39, 208, 146, + 103, 109, 163, 200, 127, 130, 13, 179, 204, 232, 85, 177, 165, 3, + 127, 104, 106, 245, 210, 245, 18, 230, 86, 35, 39, 167, 167, 8, + 41, 74, 66, 95, 32, 7, 255, 162, 96, 102, 207, 128, 68, 113, + 81, 214, 212, 51, 158, 148, 103, 56, 197, 56, 131, 207, 52, 103, + 134, 65, 109, 64, 106, 219, 60, 225, 221, 251, 28, 220, 112, 238, + 211, 175, 100, 173, 246, 8, 139, 20, 29, 153, 68, 87, 203, 148, + 142, 225, 243, 50, 74, 8, 62, 201, 75, 71, 10, 106, 130, 65, + 32, 108, 116, 96, 149, 184, 182, 114, 54, 170, 42, 83, 92, 221, + 49, 117, 0, 42, 66, 17, 68, 44, 193, 163, 106, 89, 230, 224, + 96, 175, 186, 33, 204, 87, 151, 226, 31, 131, 144, 109, 235, 76, + 191, 94, 244, 94, 132, 206, 181, 0, 2, 191, 65, 29, 238, 227, + 77, 132, 183, 165, 201, 213, 119, 166, 216, 39, 1, 226, 240, 227, + 159, 37, 18, 7, 241, 133, 79, 92, 233, 102, 147, 168, 194, 207, + 50, 125, 196, 219, 243, 252, 25, 68, 129, 21, 109, 177, 190, 42, + 223, 89, 85, 149, 253, 122, 238, 4, 116, 142, 220, 246, 109, 3, + 220, 9, 79, 118, 254, 10, 152, 197, 36, 242, 244, 251, 245, 235, + 193, 80, 151, 33, 78, 101, 253, 181, 181, 2, 145, 25, 241, 166, + 96, 93, 74, 231, 222, 116, 225, 84, 137, 9, 205, 141, 161, 169, + 218, 157, 155, 135, 229, 140, 200, 5, 222, 229, 184, 120, 183, 133, + 48, 194, 181, 145, 8, 4, 75, 253, 141, 192, 143, 216, 232, 200, + 166, 167, 198, 20, 0, 191, 113, 149, 115, 139, 125, 51, 91, 114, + 79, 42, 50, 130, 188, 55, 139, 54, 254, 126, 87, 227, 169, 208, + 13, 170, 246, 179, 21, 159, 222, 203, 225, 233, 199, 175, 33, 218, + 126, 57, 107, 144, 228, 106, 169, 28, 98, 47, 12, 192, 43, 191, + 38, 77, 145, 152, 127, 141, 108, 61, 183, 105, 118, 232, 67, 80, + 152, 182, 22, 213, 169, 24, 116, 188, 236, 241, 135, 102, 79, 207, + 84, 3, 183, 12, 255, 191, 18, 235, 19, 173, 168, 210, 97, 110, + 184, 98, 112, 191, 14, 230, 158, 44, 203, 131, 252, 145, 25, 163, + 106, 52, 196, 156, 111, 43, 8, 56, 148, 128, 178, 214, 106, 88, + 180, 39, 101, 86, 7, 39, 126, 150, 56, 169, 114, 213, 49, 245, + 214, 5, 48, 54, 89, 251, 39, 207, 135, 167, 142, 219, 97, 49, + 246, 114, 140, 231, 223, 173, 20, 47, 251, 30, 54, 102, 189, 163, + 127, 61, 202, 66, 178, 86, 243, 22, 217, 252, 128, 207, 30, 141, + 133, 227, 248, 59, 79, 64, 145, 175, 88, 199, 168, 123, 241, 184, + 239, 210, 129, 150, 106, 45, 132, 5, 138, 107, 83, 27, 16, 200, + 211, 100, 12, 14, 51, 170, 240, 179, 161, 105, 93, 169, 222, 140, + 223, 83, 28, 199, 27, 118, 98, 107, 210, 16, 104, 59, 193, 94, + 55, 25, 147, 194, 232, 12, 229, 217, 235, 156, 14, 191, 122, 29, + 249, 216, 109, 231, 48, 247, 171, 109, 81, 243, 212, 140, 104, 43, + 228, 0, 124, 168, 91, 86, 93, 4, 109, 78, 121, 233, 122, 91, + 54, 119, 220, 100, 208, 76, 232, 156, 127, 171, 203, 89, 208, 240, + 220, 215, 20, 18, 248, 234, 139, 246, 16, 111, 36, 146, 187, 222, + 123, 249, 204, 55, 109, 188, 210, 36, 144, 48, 69, 174, 225, 221, + 54, 220, 152, 67, 103, 189, 151, 253, 227, 224, 250, 119, 17, 171, + 235, 77, 251, 186, 28, 174, 117, 133, 167, 126, 221, 71, 26, 56, + 223, 186, 175, 114, 151, 96, 115, 163, 253, 21, 247, 38, 154, 97, + 246, 21, 78, 139, 18, 203, 75, 72, 134, 42, 200, 4, 233, 45, + 103, 255, 252, 26, 116, 219, 208, 26, 39, 115, 244, 193, 11, 52, + 81, 229, 138, 238, 48, 99, 47, 242, 237, 44, 185, 44, 120, 240, + 166, 115, 25, 86, 7, 84, 32, 180, 240, 167, 240, 173, 17, 45, + 221, 173, 76, 164, 129, 112, 25, 62, 177, 248, 200, 136, 58, 241, + 235, 163, 70, 23, 61, 175, 8, 105, 179, 50, 42, 78, 80, 153, + 44, 201, 37, 36, 117, 86, 5, 207, 94, 172, 51, 99, 244, 182, + 20, 40, 115, 113, 179, 171, 59, 145, 202, 242, 34, 152, 165, 178, + 80, 48, 40, 112, 121, 225, 51, 63, 232, 53, 38, 139, 171, 173, + 10, 73, 42, 177, 164, 65, 91, 7, 245, 248, 150, 31, 187, 210, + 85, 95, 87, 147, 197, 81, 106, 172, 103, 103, 115, 5, 95, 215, + 56, 84, 254, 173, 247, 182, 109, 157, 168, 55, 238, 14, 152, 228, + 185, 103, 245, 36, 186, 162, 44, 212, 206, 203, 235, 59, 136, 80, + 18, 124, 4, 181, 168, 179, 61, 157, 50, 215, 89, 235, 33, 71, + 233, 242, 103, 159, 213, 128, 20, 205, 23, 203, 122, 155, 178, 103, + 128, 6, 117, 124, 123, 46, 186, 201, 143, 95, 114, 145, 159, 133, + 43, 58, 227, 123, 51, 2, 170, 106, 36, 28, 108, 59, 184, 97, + 167, 72, 198, 91, 213, 150, 88, 11, 64, 201, 101, 69, 228, 73, + 139, 214, 6, 137, 149, 189, 90, 160, 231, 24, 68, 15, 143, 2, + 122, 246, 210, 128, 118, 226, 221, 79, 193, 24, 173, 88, 162, 59, + 39, 205, 30, 235, 18, 69, 73, 143, 177, 48, 33, 58, 144, 67, + 118, 168, 96, 118, 175, 36, 167, 123, 62, 17, 69, 203, 147, 139, + 142, 30, 209, 133, 2, 255, 41, 237, 139, 79, 14, 7, 56, 102, + 171, 172, 77, 147, 49, 115, 32, 132, 123, 99, 92, 115, 240, 106, + 202, 214, 182, 170, 238, 61, 157, 93, 130, 27, 42, 92, 107, 181, + 11, 83, 128, 102, 123, 59, 111, 12, 248, 157, 187, 193, 46, 37, + 189, 231, 236, 228, 63, 162, 217, 13, 80, 237, 30, 152, 27, 171, + 153, 141, 49, 253, 235, 126, 92, 172, 63, 140, 31, 105, 175, 49, + 57, 174, 147, 94, 179, 238, 75, 116, 203, 226, 102, 65, 2, 160, + 207, 52, 3, 220, 76, 212, 83, 79, 220, 187, 235, 143, 193, 64, + 98, 244, 132, 222, 164, 96, 154, 131, 34, 156, 85, 178, 32, 232, + 31, 74, 151, 144, 30, 113, 31, 66, 186, 188, 69, 173, 45, 200, + 149, 166, 192, 61, 16, 192, 102, 205, 148, 104, 17, 236, 183, 166, + 204, 29, 248, 114, 106, 78, 130, 254, 62, 152, 241, 189, 207, 50, + 6, 143, 195, 101, 165, 106, 88, 64, 142, 89, 144, 224, 133, 21, + 183, 4, 87, 149, 109, 253, 19, 153, 38, 155, 95, 92, 8, 229, + 248, 213, 180, 245, 236, 251, 103, 225, 67, 65, 35, 154, 44, 10, + 96, 7, 180, 24, 126, 40, 77, 232, 240, 88, 254, 98, 78, 219, + 212, 4, 45, 47, 155, 196, 170, 15, 61, 117, 11, 237, 83, 123, + 209, 81, 51, 101, 123, 25, 126, 68, 137, 205, 24, 13, 117, 207, + 47, 201, 69, 154, 244, 183, 39, 16, 25, 221, 187, 221, 160, 145, + 39, 84, 111, 113, 30, 250, 78, 244, 183, 106, 183, 199, 15, 132, + 99, 41, 45, 106, 160, 156, 96, 99, 160, 149, 181, 2, 197, 129, + 223, 92, 85, 90, 227, 221, 45, 19, 181, 113, 228, 231, 24, 37, + 215, 155, 67, 106, 173, 2, 52, 153, 79, 115, 41, 152, 245, 67, + 177, 29, 103, 183, 66, 245, 243, 254, 232, 167, 57, 235, 62, 97, + 99, 104, 133, 195, 247, 186, 99, 105, 128, 235, 156, 88, 35, 198, + 36, 194, 22, 224, 203, 85, 145, 225, 207, 49, 138, 201, 173, 214, + 160, 107, 213, 65, 17, 25, 142, 103, 123, 255, 13, 179, 227, 22, + 180, 121, 157, 232, 4, 119, 5, 144, 98, 137, 69, 74, 137, 93, + 1, 238, 175, 234, 190, 153, 111, 49, 243, 186, 234, 203, 222, 135, + 100, 176, 123, 134, 182, 223, 67, 199, 92, 192, 190, 104, 206, 46, + 80, 79, 10, 221, 44, 246, 172, 120, 181, 218, 207, 117, 143, 144, + 137, 204, 27, 204, 151, 232, 111, 67, 66, 238, 63, 108, 180, 201, + 56, 2, 189, 200, 121, 14, 189, 124, 131, 30, 11, 174, 216, 40, + 254, 214, 213, 242, 151, 218, 92, 62, 119, 228, 13, 88, 149, 67, + 92, 167, 172, 7, 111, 94, 104, 115, 11, 126, 228, 40, 30, 62, + 109, 60, 118, 13, 25, 188, 241, 185, 230, 252, 102, 85, 242, 119, + 99, 158, 63, 207, 189, 45, 46, 74, 201, 218, 188, 212, 128, 255, + 116, 66, 4, 130, 8, 43, 33, 212, 119, 195, 145, 195, 164, 133, + 143, 12, 188, 128, 241, 229, 251, 201, 54, 160, 106, 96, 204, 41, + 139, 95, 76, 136, 43, 84, 95, 61, 47, 172, 14, 78, 236, 63, + 249, 175, 108, 88, 83, 116, 101, 158, 161, 69, 251, 53, 180, 67, + 134, 225, 165, 13, 22, 165, 142, 140, 156, 148, 223, 250, 37, 21, + 172, 20, 225, 18, 127, 240, 75, 231, 122, 177, 156, 146, 101, 103, + 218, 211, 36, 205, 103, 52, 177, 32, 219, 177, 161, 113, 195, 204, + 186, 221, 65, 189, 133, 221, 214, 45, 122, 2, 189, 170, 172, 113, + 211, 37, 129, 212, 245, 24, 250, 18, 32, 93, 170, 201, 107, 240, + 134, 131, 28, 108, 232, 174, 68, 56, 53, 55, 137, 91, 180, 131, + 136, 104, 254, 193, 182, 147, 138, 14, 195, 130, 4, 199, 196, 48, + 249, 28, 156, 116, 123, 93, 159, 164, 231, 34, 208, 50, 144, 34, + 49, 197, 200, 254, 229, 47, 200, 138, 88, 55, 108, 219, 59, 155, + 107, 20, 18, 102, 213, 112, 199, 211, 27, 165, 60, 68, 204, 111, + 114, 208, 44, 104, 184, 30, 190, 33, 153, 30, 8, 234, 91, 119, + 142, 207, 183, 103, 35, 79, 236, 135, 244, 53, 58, 70, 161, 92, + 190, 191, 156, 199, 176, 134, 199, 160, 186, 22, 62, 170, 229, 96, + 189, 40, 107, 103, 138, 1, 70, 140, 203, 249, 20, 129, 200, 232, + 139, 184, 110, 220, 200, 83, 46, 201, 152, 230, 101, 30, 30, 26, + 155, 102, 153, 136, 17, 206, 33, 124, 46, 123, 203, 67, 39, 60, + 115, 52, 4, 126, 98, 97, 213, 89, 206, 217, 30, 188, 216, 240, + 128, 140, 82, 37, 66, 247, 151, 174, 55, 216, 55, 120, 146, 80, + 188, 179, 228, 203, 229, 0, 191, 205, 128, 66, 28, 129, 221, 19, + 31, 250, 175, 23, 7, 64, 47, 156, 49, 70, 131, 116, 27, 7, + 5, 205, 123, 124, 64, 235, 67, 223, 5, 93, 0, 119, 235, 22, + 131, 240, 199, 185, 36, 191, 5, 239, 3, 203, 17, 14, 87, 34, + 62, 172, 16, 137, 48, 63, 48, 188, 39, 164, 170, 186, 86, 108, + 241, 168, 36, 2, 61, 17, 238, 156, 213, 56, 142, 190, 81, 206, + 253, 212, 220, 4, 60, 61, 20, 147, 155, 241, 102, 211, 103, 59, + 37, 200, 173, 197, 170, 123, 232, 157, 84, 57, 112, 228, 145, 199, + 131, 111, 167, 189, 195, 155, 174, 168, 161, 81, 243, 68, 147, 170, + 26, 54, 59, 106, 67, 68, 187, 5, 113, 214, 82, 251, 55, 38, + 139, 122, 88, 216, 14, 236, 166, 30, 245, 19, 250, 239, 115, 69, + 168, 255, 97, 254, 222, 173, 122, 16, 108, 131, 246, 218, 86, 113, + 105, 149, 96, 94, 246, 40, 66, 91, 37, 101, 89, 145, 135, 64, + 76, 201, 104, 1, 61, 200, 130, 188, 209, 15, 189, 109, 90, 236, + 253, 131, 180, 239, 10, 161, 89, 80, 7, 60, 223, 152, 22, 198, + 247, 45, 156, 61, 111, 60, 188, 203, 151, 80, 210, 166, 111, 4, + 108, 91, 37, 74, 109, 131, 62, 239, 229, 208, 217, 118, 93, 99, + 123, 48, 239, 199, 74, 109, 47, 118, 18, 254, 173, 90, 81, 97, + 50, 73, 47, 251, 40, 225, 190, 126, 144, 226, 166, 16, 41, 195, + 16, 211, 122, 9, 228, 131, 49, 21, 218, 227, 234, 174, 120, 177, + 12, 119, 252, 159, 134, 126, 195, 160, 245, 68, 142, 149, 141, 191, + 166, 47, 124, 193, 155, 91, 32, 172, 60, 227, 200, 124, 33, 135, + 184, 85, 64, 13, 245, 170, 104, 76, 27, 159, 149, 131, 205, 84, + 35, 186, 147, 63, 172, 164, 87, 32, 255, 157, 76, 18, 69, 98, + 21, 73, 210, 250, 144, 186, 208, 246, 4, 53, 70, 181, 12, 143, + 166, 193, 46, 137, 6, 219, 167, 241, 255, 234, 74, 217, 184, 72, + 225, 249, 191, 143, 54, 206, 76, 243, 27, 199, 240, 121, 133, 111, + 9, 208, 0, 68, 208, 197, 167, 13, 194, 63, 200, 114, 247, 172, + 112, 116, 139, 223, 155, 245, 237, 34, 20, 130, 119, 15, 114, 2, + 18, 157, 174, 214, 205, 136, 52, 47, 225, 228, 125, 162, 61, 171, + 111, 118, 199, 218, 200, 26, 135, 247, 143, 93, 140, 243, 150, 52, + 238, 174, 12, 53, 42, 154, 174, 42, 140, 83, 255, 160, 151, 126, + 161, 89, 158, 250, 137, 187, 144, 77, 174, 9, 66, 176, 152, 204, + 164, 188, 133, 113, 228, 238, 95, 189, 100, 130, 112, 228, 193, 158, + 251, 186, 210, 173, 245, 45, 197, 33, 106, 96, 29, 179, 136, 184, + 102, 248, 64, 251, 8, 59, 113, 133, 104, 59, 146, 153, 108, 63, + 95, 197, 109, 189, 191, 62, 17, 228, 76, 62, 247, 198, 221, 198, + 236, 25, 82, 197, 153, 96, 213, 56, 206, 85, 151, 109, 172, 3, + 210, 203, 72, 90, 50, 155, 207, 98, 204, 244, 35, 85, 249, 180, + 248, 9, 241, 26, 52, 107, 152, 206, 10, 20, 124, 201, 54, 112, + 80, 218, 34, 233, 35, 51, 49, 173, 63, 213, 165, 239, 130, 210, + 100, 206, 253, 158, 242, 29, 192, 122, 76, 152, 160, 219, 65, 165, + 233, 156, 217, 48, 117, 122, 132, 88, 177, 130, 97, 67, 183, 151, + 109, 109, 21, 93, 22, 42, 144, 130, 201, 180, 150, 225, 228, 1, + 1, 43, 219, 91, 195, 106, 144, 27, 42, 84, 82, 7, 58, 30, + 81, 101, 111, 216, 177, 108, 72, 111, 209, 73, 95, 150, 66, 96, + 109, 226, 11, 1, 98, 62, 174, 33, 104, 98, 71, 56, 190, 218, + 57, 157, 25, 88, 244, 35, 240, 43, 76, 195, 155, 170, 80, 143, + 108, 6, 22, 232, 107, 188, 86, 130, 39, 210, 42, 26, 185, 44, + 24, 211, 111, 202, 195, 37, 110, 113, 82, 233, 200, 183, 244, 156, + 10, 63, 149, 218, 29, 32, 255, 129, 225, 143, 204, 49, 51, 73, + 42, 41, 190, 255, 51, 224, 108, 220, 53, 101, 56, 242, 203, 144, + 58, 186, 115, 7, 26, 52, 200, 214, 48, 127, 135, 47, 157, 142, + 81, 185, 241, 234, 16, 117, 207, 250, 0, 60, 242, 71, 70, 170, + 175, 197, 67, 228, 252, 221, 156, 6, 11, 226, 114, 223, 38, 192, + 64, 5, 12, 222, 236, 151, 6, 195, 215, 207, 4, 57, 95, 16, + 255, 33, 226, 87, 67, 8, 66, 121, 130, 120, 243, 196, 24, 64, + 206, 74, 115, 50, 120, 8, 254, 11, 228, 115, 155, 235, 143, 173, + 224, 0, 166, 43, 184, 11, 118, 199, 61, 216, 251, 162, 3, 118, + 163, 38, 205, 34, 212, 81, 207, 220, 23, 158, 213, 234, 110, 25, + 30, 107, 112, 83, 51, 25, 93, 224, 131, 197, 99, 116, 63, 142, + 207, 41, 15, 43, 164, 159, 241, 67, 228, 254, 86, 181, 209, 242, + 187, 193, 104, 151, 51, 26, 24, 23, 143, 43, 75, 31, 176, 205, + 47, 156, 7, 188, 202, 128, 147, 236, 155, 73, 180, 31, 165, 233, + 38, 217, 115, 153, 60, 214, 192, 222, 164, 202, 73, 117, 109, 165, + 111, 153, 187, 148, 233, 7, 185, 88, 129, 57, 36, 153, 67, 154, + 119, 176, 135, 37, 25, 216, 145, 239, 42, 243, 86, 85, 143, 203, + 165, 40, 147, 5, 172, 57, 83, 27, 102, 121, 27, 39, 214, 106, + 55, 81, 179, 152, 156, 0, 64, 67, 198, 229, 48, 86, 180, 146, + 172, 195, 215, 228, 26, 64, 218, 41, 185, 75, 230, 220, 68, 242, + 107, 68, 51, 9, 209, 177, 145, 151, 71, 225, 2, 145, 12, 144, + 25, 42, 150, 214, 43, 51, 121, 218, 68, 4, 160, 163, 40, 50, + 40, 138, 121, 119, 130, 88, 43, 113, 229, 142, 113, 84, 190, 12, + 113, 65, 139, 148, 83, 151, 64, 243, 178, 30, 249, 32, 182, 27, + 35, 144, 108, 18, 142, 149, 231, 36, 199, 88, 177, 179, 101, 156, + 85, 229, 40, 134, 211, 113, 194, 183, 35, 73, 238, 183, 240, 140, + 142, 193, 32, 44, 26, 97, 58, 106, 242, 52, 140, 192, 102, 170, + 60, 168, 130, 216, 112, 133, 57, 42, 22, 212, 244, 115, 177, 160, + 146, 248, 69, 31, 113, 105, 130, 153, 205, 188, 207, 190, 245, 8, + 58, 25, 112, 138, 135, 111, 5, 159, 216, 110, 104, 215, 157, 48, + 202, 112, 136, 217, 85, 58, 241, 229, 94, 240, 45, 216, 214, 143, + 122, 29, 171, 33, 148, 187, 54, 4, 3, 51, 133, 135, 98, 108, + 64, 193, 0, 38, 208, 14, 235, 197, 84, 153, 177, 242, 204, 30, + 156, 232, 157, 211, 244, 96, 122, 221, 97, 186, 112, 137, 23, 246, + 211, 239, 43, 51, 13, 110, 235, 90, 182, 215, 69, 243, 14, 252, + 125, 198, 47, 119, 7, 175, 160, 172, 229, 11, 99, 12, 61, 239, + 237, 126, 100, 24, 16, 71, 185, 132, 153, 97, 228, 71, 28, 80, + 187, 73, 249, 192, 185, 56, 77, 81, 184, 81, 247, 98, 133, 31, + 73, 36, 34, 229, 168, 117, 235, 185, 20, 157, 8, 85, 158, 188, + 55, 43, 140, 214, 156, 56, 228, 71, 189, 134, 242, 224, 47, 48, + 102, 32, 179, 199, 88, 72, 166, 129, 61, 171, 145, 198, 87, 125, + 39, 132, 163, 29, 12, 238, 253, 73, 201, 35, 200, 57, 65, 75, + 238, 143, 100, 212, 238, 217, 128, 15, 152, 18, 243, 2, 50, 252, + 195, 126, 121, 21, 208, 249, 194, 211, 44, 53, 134, 154, 155, 31, + 200, 166, 63, 127, 72, 214, 189, 34, 18, 238, 197, 159, 22, 202, + 0, 221, 89, 139, 186, 80, 32, 234, 41, 228, 91, 13, 162, 80, + 219, 246, 158, 202, 14, 113, 62, 10, 214, 15, 240, 89, 183, 40, + 96, 27, 40, 123, 1, 47, 7, 219, 76, 121, 68, 62, 51, 211, + 85, 77, 88, 196, 161, 231, 246, 48, 222, 199, 51, 21, 65, 229, + 203, 190, 96, 121, 149, 211, 98, 225, 175, 36, 112, 233, 157, 65, + 172, 62, 8, 243, 28, 9, 5, 112, 50, 16, 14, 136, 130, 20, + 218, 68, 120, 162, 55, 58, 105, 112, 111, 116, 119, 229, 119, 32, + 209, 40, 50, 152, 97, 74, 219, 222, 52, 180, 131, 184, 159, 115, + 27, 206, 177, 246, 188, 61, 59, 63, 6, 122, 155, 151, 135, 51, + 152, 144, 242, 97, 201, 146, 42, 168, 221, 250, 28, 210, 136, 227, + 8, 205, 173, 50, 23, 217, 80, 232, 24, 191, 117, 107, 40, 129, + 161, 48, 46, 204, 255, 209, 23, 58, 80, 32, 94, 7, 174, 98, + 238, 21, 224, 250, 39, 22, 206, 9, 138, 0, 14, 202, 198, 29, + 131, 89, 195, 197, 45, 170, 219, 214, 140, 253, 102, 171, 94, 141, + 168, 39, 178, 124, 85, 30, 104, 190, 20, 0, 17, 154, 144, 7, + 37, 172, 101, 206, 7, 252, 133, 41, 20, 37, 175, 60, 37, 86, + 128, 252, 130, 141, 23, 75, 10, 192, 131, 140, 170, 208, 150, 97, + 231, 224, 27, 199, 187, 236, 71, 246, 191, 36, 180, 34, 125, 84, + 162, 15, 6, 140, 7, 134, 7, 247, 221, 67, 235, 85, 202, 250, + 112, 122, 95, 222, 169, 221, 227, 3, 135, 70, 207, 108, 86, 252, + 40, 113, 6, 152, 97, 121, 101, 111, 96, 251, 227, 196, 167, 156, + 4, 253, 110, 232, 126, 18, 172, 28, 103, 38, 253, 231, 21, 36, + 173, 28, 159, 122, 177, 81, 88, 191, 241, 39, 30, 251, 131, 156, + 51, 10, 42, 157, 185, 14, 196, 57, 34, 102, 77, 70, 111, 99, + 87, 112, 10, 45, 15, 98, 177, 237, 80, 106, 39, 181, 67, 231, + 100, 147, 134, 48, 162, 81, 252, 192, 1, 124, 73, 140, 153, 61, + 136, 150, 110, 43, 235, 46, 10, 197, 237, 96, 178, 89, 110, 92, + 5, 214, 3, 3, 246, 180, 73, 63, 48, 75, 85, 201, 130, 135, + 162, 167, 12, 127, 90, 243, 27, 159, 232, 238, 233, 179, 110, 232, + 190, 128, 56, 77, 107, 148, 229, 22, 192, 26, 253, 51, 230, 81, + 254, 83, 54, 226, 129, 64, 214, 69, 148, 252, 246, 211, 183, 84, + 41, 123, 222, 170, 67, 211, 76, 70, 66, 252, 54, 136, 178, 128, + 122, 124, 56, 99, 248, 80, 186, 175, 168, 154, 165, 140, 226, 95, + 251, 103, 209, 188, 159, 239, 167, 74, 183, 108, 120, 210, 40, 141, + 255, 120, 114, 199, 150, 121, 29, 209, 44, 65, 136, 172, 76, 186, + 146, 243, 31, 149, 180, 215, 177, 177, 208, 154, 45, 43, 23, 121, + 218, 174, 159, 231, 230, 25, 89, 140, 26, 141, 165, 190, 198, 72, + 197, 19, 58, 221, 107, 120, 22, 161, 31, 156, 172, 174, 106, 55, + 140, 50, 243, 59, 9, 193, 26, 131, 88, 183, 102, 107, 69, 136, + 230, 231, 197, 243, 145, 245, 198, 29, 155, 187, 68, 188, 239, 215, + 192, 101, 178, 184, 34, 107, 152, 168, 57, 130, 115, 83, 242, 253, + 171, 127, 124, 118, 248, 208, 74, 112, 134, 86, 149, 82, 0, 107, + 186, 121, 105, 23, 160, 126, 84, 158, 180, 33, 40, 216, 55, 208, + 46, 122, 126, 4, 148, 87, 127, 161, 97, 199, 61, 14, 196, 249, + 4, 195, 231, 126, 130, 246, 119, 171, 53, 243, 126, 159, 28, 104, + 174, 56, 142, 226, 199, 249, 18, 138, 84, 218, 167, 55, 225, 104, + 7, 218, 119, 187, 6, 114, 161, 208, 236, 19, 247, 58, 238, 0, + 137, 144, 197, 94, 85, 103, 58, 194, 81, 24, 106, 154, 206, 182, + 41, 15, 8, 77, 191, 158, 69, 248, 40, 85, 28, 25, 107, 168, + 232, 13, 63, 141, 38, 208, 70, 148, 85, 56, 26, 189, 0, 230, + 102, 41, 31, 162, 48, 190, 150, 132, 190, 220, 246, 20, 170, 238, + 2, 39, 238, 224, 18, 151, 103, 160, 252, 220, 82, 146, 19, 210, + 105, 146, 235, 142, 190, 190, 133, 238, 38, 28, 161, 135, 152, 5, + 15, 132, 38, 173, 205, 15, 95, 124, 41, 118, 10, 92, 237, 203, + 99, 196, 223, 168, 17, 32, 42, 252, 73, 154, 41, 162, 231, 39, + 117, 56, 56, 2, 233, 199, 127, 110, 183, 104, 231, 119, 198, 184, + 225, 46, 8, 4, 98, 213, 123, 111, 170, 200, 188, 234, 67, 44, + 175, 22, 160, 184, 98, 148, 146, 236, 15, 198, 46, 214, 175, 169, + 214, 51, 50, 111, 226, 141, 107, 164, 163, 179, 139, 6, 122, 232, + 214, 236, 31, 110, 221, 173, 138, 187, 191, 177, 230, 47, 104, 159, + 77, 100, 245, 196, 5, 183, 136, 248, 94, 19, 122, 206, 241, 10, + 169, 147, 25, 211, 222, 207, 7, 65, 12, 14, 153, 22, 118, 208, + 212, 156, 221, 128, 133, 250, 120, 104, 219, 41, 80, 38, 178, 79, + 241, 175, 30, 160, 238, 80, 169, 153, 178, 218, 88, 136, 205, 245, + 210, 171, 104, 104, 252, 58, 0, 215, 54, 1, 142, 254, 196, 128, + 250, 230, 108, 190, 245, 97, 85, 29, 189, 204, 114, 217, 222, 236, + 199, 253, 93, 44, 219, 119, 100, 158, 156, 173, 63, 77, 56, 68, + 145, 133, 223, 221, 212, 34, 141, 110, 184, 159, 155, 249, 177, 60, + 142, 121, 226, 208, 132, 253, 43, 122, 248, 182, 185, 155, 29, 26, + 59, 207, 219, 33, 104, 105, 125, 134, 187, 217, 37, 103, 73, 251, + 229, 186, 105, 233, 17, 235, 75, 11, 42, 8, 235, 59, 111, 59, + 46, 81, 135, 235, 248, 72, 193, 196, 87, 26, 133, 245, 30, 204, + 95, 16, 105, 94, 86, 138, 70, 74, 80, 109, 228, 14, 112, 89, + 191, 171, 16, 247, 9, 88, 27, 70, 156, 239, 185, 19, 6, 145, + 149, 116, 244, 161, 1, 156, 182, 167, 15, 162, 120, 75, 251, 188, + 247, 147, 152, 57, 116, 203, 62, 96, 170, 169, 167, 42, 118, 247, + 216, 56, 78, 166, 172, 92, 241, 96, 60, 68, 23, 220, 16, 136, + 213, 41, 0, 66, 170, 153, 207, 142, 176, 64, 99, 92, 93, 214, + 3, 230, 61, 91, 39, 93, 191, 200, 230, 135, 78, 225, 245, 38, + 83, 168, 39, 233, 250, 242, 116, 131, 32, 162, 254, 159, 134, 70, + 197, 57, 204, 169, 142, 249, 164, 14, 1, 182, 75, 3, 65, 81, + 240, 31, 69, 155, 208, 3, 238, 11, 6, 138, 52, 104, 162, 14, + 165, 171, 87, 254, 129, 200, 204, 226, 38, 121, 32, 116, 227, 203, + 5, 239, 175, 41, 241, 157, 62, 24, 186, 198, 127, 68, 192, 17, + 192, 174, 197, 209, 99, 152, 67, 208, 140, 156, 133, 159, 123, 39, + 136, 17, 120, 149, 69, 116, 148, 181, 247, 71, 81, 208, 63, 206, + 158, 249, 197, 0, 48, 63, 9, 133, 254, 28, 150, 143, 90, 141, + 231, 60, 153, 195, 243, 21, 177, 85, 27, 38, 171, 149, 244, 212, + 78, 60, 134, 98, 127, 50, 52, 54, 243, 183, 172, 80, 201, 65, + 210, 162, 81, 32, 85, 213, 237, 61, 168, 9, 186, 20, 61, 239, + 179, 130, 43, 143, 44, 63, 98, 21, 32, 180, 102, 50, 138, 172, + 64, 165, 18, 118, 45, 10, 16, 84, 44, 26, 62, 197, 11, 248, + 251, 240, 230, 188, 221, 28, 99, 23, 149, 248, 7, 231, 7, 8, + 118, 214, 215, 87, 39, 254, 53, 28, 48, 149, 62, 50, 50, 7, + 216, 60, 209, 16, 255, 214, 251, 167, 144, 53, 124, 112, 9, 213, + 58, 178, 55, 1, 202, 17, 43, 159, 19, 114, 105, 118, 153, 161, + 26, 23, 115, 171, 226, 128, 41, 175, 14, 35, 112, 168, 195, 97, + 10, 191, 121, 117, 84, 178, 211, 180, 120, 199, 187, 41, 10, 15, + 163, 35, 129, 223, 234, 191, 218, 130, 58, 194, 109, 113, 217, 58, + 76, 0, 224, 87, 128, 32, 197, 249, 149, 145, 126, 28, 90, 174, + 99, 70, 86, 55, 33, 189, 102, 165, 57, 193, 173, 72, 234, 132, + 203, 254, 19, 252, 251, 63, 194, 135, 187, 178, 171, 93, 133, 200, + 236, 156, 244, 143, 40, 222, 139, 108, 15, 125, 86, 116, 193, 62, + 189, 219, 162, 59, 204, 114, 151, 226, 56, 139, 180, 137, 148, 103, + 81, 194, 21, 141, 114, 32, 251, 38, 20, 72, 108, 193, 181, 179, + 164, 46, 232, 153, 2, 57, 216, 73, 32, 192, 59, 173, 76, 106, + 127, 218, 112, 18, 165, 248, 226, 57, 243, 189, 9, 79, 13, 27, + 20, 47, 156, 3, 213, 84, 65, 31, 231, 242, 156, 87, 252, 209, + 17, 36, 47, 90, 14, 26, 101, 249, 164, 150, 129, 45, 111, 231, + 72, 198, 156, 253, 55, 247, 37, 227, 225, 4, 94, 206, 175, 252, + 106, 51, 146, 126, 95, 18, 242, 8, 246, 161, 57, 31, 50, 212, + 249, 92, 203, 153, 116, 51, 149, 8, 132, 171, 17, 135, 187, 151, + 58, 56, 221, 157, 20, 48, 210, 195, 250, 36, 117, 127, 109, 84, + 120, 7, 135, 39, 36, 74, 224, 200, 153, 111, 15, 69, 23, 72, + 228, 16, 235, 69, 117, 176, 202, 164, 82, 100, 100, 165, 53, 59, + 192, 33, 59, 32, 187, 70, 197, 38, 249, 67, 86, 79, 141, 122, + 86, 185, 189, 50, 90, 178, 51, 228, 21, 215, 194, 40, 33, 236, + 95, 24, 42, 3, 240, 38, 164, 253, 135, 244, 250, 53, 45, 221, + 201, 49, 179, 136, 198, 124, 0, 241, 28, 149, 206, 88, 143, 4, + 215, 219, 130, 20, 92, 30, 199, 35, 25, 25, 104, 44, 252, 151, + 92, 192, 74, 181, 209, 151, 153, 106, 195, 56, 252, 249, 77, 234, + 44, 141, 87, 64, 119, 184, 189, 41, 204, 82, 115, 213, 23, 211, + 185, 217, 157, 97, 163, 240, 56, 74, 217, 179, 217, 29, 136, 97, + 14, 9, 160, 34, 52, 125, 205, 245, 166, 233, 3, 197, 23, 77, + 0, 161, 20, 177, 164, 150, 156, 173, 168, 55, 213, 27, 199, 98, + 131, 158, 5, 45, 79, 87, 137, 114, 134, 158, 33, 63, 159, 228, + 78, 137, 207, 195, 173, 187, 136, 87, 135, 64, 146, 44, 43, 98, + 208, 33, 215, 139, 195, 236, 218, 192, 143, 190, 147, 57, 144, 74, + 108, 155, 249, 35, 149, 43, 244, 131, 200, 207, 204, 175, 154, 226, + 25, 17, 243, 14, 182, 105, 51, 133, 226, 27, 68, 179, 155, 86, + 173, 118, 142, 3, 134, 162, 37, 111, 25, 112, 162, 197, 21, 60, + 165, 241, 252, 226, 172, 60, 82, 240, 6, 210, 57, 7, 73, 65, + 185, 228, 97, 47, 178, 236, 63, 54, 16, 37, 129, 11, 244, 104, + 39, 15, 222, 92, 146, 39, 10, 204, 76, 78, 32, 88, 215, 233, + 176, 16, 161, 71, 178, 14, 251, 223, 137, 123, 242, 187, 208, 66, + 138, 185, 153, 36, 150, 131, 36, 106, 243, 74, 24, 166, 85, 95, + 117, 189, 127, 193, 194, 99, 191, 6, 115, 248, 145, 45, 252, 134, + 131, 194, 64, 83, 189, 198, 75, 253, 19, 56, 107, 226, 241, 117, + 251, 239, 88, 44, 225, 55, 13, 24, 250, 8, 74, 200, 153, 25, + 123, 111, 17, 239, 225, 117, 50, 197, 203, 33, 131, 20, 220, 170, + 252, 255, 195, 195, 83, 185, 80, 67, 205, 138, 82, 22, 55, 65, + 124, 91, 102, 195, 24, 141, 226, 234, 65, 66, 249, 89, 151, 65, + 122, 245, 86, 199, 15, 192, 87, 131, 211, 192, 58, 105, 124, 104, + 184, 199, 136, 68, 117, 52, 55, 152, 95, 149, 81, 63, 166, 217, + 48, 51, 170, 223, 175, 199, 194, 86, 133, 186, 162, 17, 247, 228, + 62, 36, 188, 55, 89, 209, 194, 148, 238, 156, 16, 108, 169, 159, + 124, 135, 168, 251, 122, 247, 157, 105, 94, 164, 42, 103, 215, 152, + 78, 148, 185, 143, 124, 230, 117, 177, 90, 82, 217, 72, 132, 95, + 156, 10, 153, 83, 238, 241, 46, 190, 198, 131, 189, 54, 126, 65, + 174, 156, 162, 151, 132, 120, 59, 100, 141, 231, 127, 37, 41, 243, + 37, 209, 239, 7, 219, 112, 153, 106, 87, 23, 226, 31, 63, 103, + 28, 34, 142, 98, 224, 41, 70, 161, 10, 160, 88, 112, 140, 255, + 250, 140, 250, 236, 2, 49, 13, 92, 106, 173, 123, 137, 167, 36, + 249, 2, 251, 247, 86, 5, 223, 152, 9, 24, 121, 130, 224, 180, + 49, 109, 10, 240, 143, 142, 51, 74, 155, 81, 138, 211, 182, 105, + 56, 250, 113, 225, 195, 73, 72, 59, 80, 141, 71, 245, 13, 167, + 234, 189, 45, 161, 167, 109, 116, 104, 30, 107, 66, 205, 73, 65, + 163, 198, 242, 245, 195, 114, 62, 72, 109, 98, 241, 62, 27, 28, + 170, 87, 55, 193, 137, 110, 154, 110, 87, 57, 13, 197, 103, 241, + 187, 66, 189, 159, 206, 72, 109, 187, 174, 59, 153, 95, 162, 241, + 251, 229, 46, 114, 153, 224, 22, 53, 0, 194, 28, 28, 36, 165, + 47, 0, 172, 231, 208, 155, 180, 11, 168, 44, 68, 141, 198, 23, + 21, 233, 221, 211, 48, 31, 76, 200, 141, 197, 91, 10, 71, 123, + 231, 169, 58, 34, 103, 80, 173, 120, 238, 70, 40, 73, 162, 73, + 238, 48, 82, 216, 19, 173, 205, 14, 210, 94, 144, 210, 199, 199, + 248, 131, 225, 213, 121, 153, 48, 15, 103, 148, 64, 247, 45, 211, + 185, 168, 49, 87, 164, 96, 186, 202, 253, 125, 123, 223, 65, 48, + 165, 238, 104, 207, 166, 10, 237, 123, 73, 51, 109, 233, 221, 154, + 178, 8, 209, 45, 232, 29, 96, 178, 43, 20, 147, 91, 235, 26, + 235, 126, 149, 162, 103, 97, 106, 198, 168, 144, 174, 230, 92, 81, + 82, 158, 135, 146, 96, 105, 36, 63, 171, 14, 213, 211, 53, 105, + 63, 78, 29, 78, 241, 223, 137, 204, 234, 5, 18, 114, 238, 127, + 252, 156, 222, 115, 104, 192, 252, 47, 119, 32, 50, 47, 214, 35, + 149, 117, 15, 117, 240, 219, 85, 156, 204, 90, 100, 215, 131, 144, + 74, 97, 188, 86, 175, 80, 173, 68, 214, 241, 24, 153, 224, 32, + 44, 23, 1, 176, 27, 209, 90, 220, 105, 44, 103, 166, 212, 111, + 4, 238, 198, 65, 177, 5, 68, 120, 23, 192, 130, 164, 30, 191, + 63, 108, 152, 0, 141, 156, 199, 20, 132, 205, 95, 180, 89, 225, + 0, 2, 29, 249, 214, 175, 158, 89, 214, 62, 125, 221, 203, 132, + 125, 197, 152, 68, 16, 27, 27, 169, 166, 155, 127, 245, 131, 194, + 182, 188, 243, 56, 141, 65, 171, 198, 83, 57, 90, 84, 96, 117, + 11, 134, 66, 51, 235, 75, 247, 118, 130, 222, 175, 147, 149, 126, + 28, 208, 71, 40, 237, 223, 223, 125, 96, 168, 7, 28, 208, 136, + 102, 157, 54, 92, 171, 211, 87, 22, 233, 161, 65, 49, 47, 157, + 208, 161, 58, 46, 7, 181, 106, 240, 192, 34, 241, 9, 22, 221, + 88, 87, 30, 135, 40, 79, 135, 85, 226, 49, 109, 22, 74, 33, + 63, 167, 190, 203, 188, 87, 51, 142, 49, 63, 13, 47, 82, 3, + 64, 6, 235, 161, 13, 69, 117, 203, 234, 166, 70, 114, 139, 221, + 125, 58, 164, 239, 187, 45, 169, 42, 249, 25, 84, 233, 48, 230, + 203, 23, 82, 137, 73, 8, 9, 191, 92, 201, 43, 163, 103, 123, + 23, 3, 115, 219, 121, 177, 176, 57, 203, 96, 2, 193, 65, 185, + 65, 74, 97, 183, 18, 208, 162, 93, 180, 6, 16, 51, 79, 124, + 242, 47, 154, 25, 230, 75, 136, 27, 146, 196, 72, 107, 112, 105, + 26, 84, 174, 153, 128, 109, 69, 18, 77, 40, 206, 44, 75, 10, + 159, 44, 247, 209, 143, 141, 16, 247, 137, 226, 90, 7, 17, 146, + 65, 34, 41, 64, 237, 121, 187, 35, 192, 231, 103, 234, 209, 12, + 111, 91, 44, 29, 85, 48, 137, 212, 12, 182, 130, 41, 251, 4, + 47, 187, 68, 35, 149, 78, 116, 33, 234, 36, 108, 151, 181, 245, + 145, 228, 175, 214, 177, 105, 179, 101, 244, 58, 124, 19, 163, 184, + 53, 107, 209, 228, 95, 187, 57, 101, 221, 174, 34, 57, 53, 54, + 122, 192, 231, 120, 155, 135, 58, 193, 222, 245, 88, 46, 24, 172, + 221, 185, 10, 138, 178, 36, 180, 214, 237, 236, 87, 101, 211, 152, + 61, 211, 233, 1, 62, 64, 93, 61, 37, 11, 187, 254, 26, 174, + 137, 157, 73, 209, 191, 25, 29, 133, 137, 81, 176, 2, 104, 64, + 166, 46, 170, 48, 164, 131, 79, 40, 237, 177, 46, 29, 207, 65, + 246, 182, 225, 217, 62, 34, 250, 182, 177, 169, 79, 249, 248, 37, + 178, 216, 166, 215, 62, 26, 199, 97, 171, 147, 19, 220, 65, 181, + 57, 117, 153, 65, 28, 0, 98, 205, 221, 186, 212, 176, 119, 246, + 44, 166, 27, 216, 99, 110, 67, 143, 209, 69, 196, 166, 160, 193, + 8, 220, 132, 173, 164, 233, 14, 163, 34, 250, 142, 169, 156, 135, + 197, 206, 241, 60, 222, 201, 247, 133, 89, 22, 187, 224, 216, 161, + 157, 233, 206, 58, 29, 39, 53, 8, 142, 173, 61, 144, 187, 19, + 241, 172, 173, 252, 116, 70, 184, 73, 155, 223, 112, 66, 254, 58, + 81, 187, 76, 217, 2, 192, 246, 70, 21, 227, 102, 229, 112, 103, + 228, 149, 246, 212, 224, 56, 213, 168, 41, 221, 181, 12, 236, 76, + 130, 237, 165, 30, 186, 25, 128, 199, 63, 80, 220, 194, 141, 120, + 121, 152, 85, 51, 59, 135, 35, 59, 79, 20, 124, 4, 88, 189, + 82, 21, 181, 120, 89, 71, 49, 213, 198, 210, 205, 99, 75, 156, + 19, 77, 15, 84, 216, 57, 198, 87, 250, 162, 92, 172, 158, 13, + 212, 174, 32, 135, 156, 154, 117, 84, 157, 90, 224, 227, 174, 243, + 206, 83, 137, 53, 212, 211, 136, 166, 52, 70, 99, 251, 205, 45, + 241, 184, 32, 123, 134, 97, 144, 99, 50, 2, 209, 15, 40, 87, + 193, 92, 213, 231, 130, 21, 138, 84, 186, 139, 218, 126, 70, 46, + 223, 152, 90, 197, 67, 138, 49, 199, 197, 25, 96, 109, 51, 103, + 62, 65, 228, 53, 71, 101, 104, 34, 150, 175, 204, 38, 184, 35, + 156, 168, 92, 129, 154, 65, 107, 165, 195, 88, 178, 219, 75, 132, + 63, 253, 67, 226, 86, 128, 121, 205, 129, 16, 172, 254, 13, 120, + 188, 40, 178, 240, 205, 88, 126, 171, 194, 198, 45, 244, 114, 127, + 23, 63, 35, 174, 146, 38, 250, 199, 102, 153, 52, 142, 155, 162, + 222, 180, 89, 185, 180, 133, 183, 129, 96, 14, 176, 19, 211, 78, + 25, 241, 181, 121, 220, 188, 175, 12, 194, 156, 21, 26, 19, 155, + 208, 95, 197, 201, 77, 242, 50, 169, 226, 64, 149, 209, 178, 148, + 3, 175, 12, 201, 159, 110, 233, 43, 148, 240, 192, 234, 10, 229, + 107, 55, 133, 49, 57, 186, 247, 251, 150, 66, 27, 245, 206, 127, + 48, 224, 206, 39, 156, 149, 157, 80, 77, 125, 192, 188, 42, 149, + 26, 15, 109, 217, 211, 143, 184, 162, 226, 134, 53, 81, 240, 182, + 193, 31, 156, 52, 50, 184, 222, 182, 121, 183, 90, 98, 20, 189, + 111, 3, 135, 65, 254, 252, 81, 223, 202, 205, 58, 127, 187, 179, + 147, 198, 12, 111, 210, 82, 30, 35, 189, 10, 217, 23, 66, 38, + 111, 44, 209, 111, 38, 154, 184, 141, 142, 120, 2, 89, 172, 24, + 202, 242, 97, 145, 34, 89, 5, 135, 87, 95, 94, 13, 217, 64, + 217, 103, 123, 27, 222, 140, 66, 82, 51, 167, 186, 137, 109, 208, + 171, 129, 30, 246, 185, 69, 49, 59, 163, 69, 30, 79, 159, 183, + 242, 148, 190, 157, 27, 254, 158, 154, 202, 108, 110, 193, 36, 80, + 235, 11, 16, 32, 36, 239, 72, 234, 38, 192, 20, 141, 80, 13, + 95, 82, 211, 152, 10, 62, 52, 176, 78, 41, 123, 62, 20, 215, + 81, 164, 103, 40, 119, 181, 240, 185, 71, 126, 111, 35, 64, 182, + 58, 150, 252, 42, 28, 243, 240, 41, 7, 70, 127, 186, 87, 208, + 199, 106, 84, 83, 87, 242, 161, 21, 38, 126, 203, 177, 253, 188, + 187, 22, 187, 184, 116, 44, 98, 62, 228, 89, 116, 10, 10, 87, + 113, 242, 219, 109, 191, 24, 101, 158, 204, 47, 60, 178, 225, 14, + 106, 119, 252, 5, 41, 145, 151, 69, 91, 154, 182, 133, 61, 57, + 61, 153, 167, 213, 210, 204, 107, 117, 118, 190, 22, 208, 30, 143, + 78, 103, 94, 97, 48, 59, 246, 240, 207, 240, 111, 132, 148, 176, + 138, 131, 157, 118, 183, 22, 55, 156, 41, 1, 109, 118, 93, 35, + 33, 215, 130, 19, 242, 163, 116, 60, 145, 139, 166, 107, 25, 63, + 203, 192, 68, 124, 107, 134, 130, 111, 179, 106, 186, 210, 195, 37, + 224, 212, 139, 22, 113, 105, 155, 155, 219, 127, 15, 73, 207, 106, + 76, 73, 27, 94, 174, 214, 8, 160, 118, 241, 156, 21, 96, 50, + 162, 156, 252, 73, 41, 54, 6, 247, 155, 147, 238, 108, 203, 3, + 240, 17, 229, 19, 119, 75, 218, 151, 87, 217, 140, 113, 218, 92, + 77, 9, 131, 92, 69, 44, 178, 38, 165, 52, 223, 64, 147, 206, + 28, 74, 229, 113, 165, 223, 24, 68, 192, 87, 125, 19, 162, 92, + 171, 14, 186, 170, 137, 35, 203, 14, 182, 4, 43, 17, 114, 173, + 173, 117, 189, 230, 216, 101, 16, 118, 12, 241, 73, 231, 133, 157, + 91, 55, 114, 217, 11, 239, 185, 146, 223, 108, 116, 108, 112, 208, + 59, 84, 96, 206, 180, 223, 84, 89, 180, 229, 70, 240, 63, 189, + 154, 213, 108, 89, 225, 102, 12, 215, 5, 8, 14, 149, 23, 87, + 70, 25, 131, 126, 157, 145, 31, 84, 122, 78, 20, 10, 189, 128, + 213, 241, 157, 67, 0, 130, 44, 60, 34, 60, 253, 195, 159, 34, + 139, 148, 85, 119, 90, 237, 30, 107, 68, 46, 205, 8, 201, 59, + 254, 72, 64, 94, 46, 226, 56, 30, 47, 78, 115, 58, 179, 182, + 98, 126, 167, 181, 206, 215, 150, 73, 138, 143, 139, 6, 185, 158, + 109, 132, 248, 77, 84, 9, 179, 243, 121, 156, 75, 254, 165, 57, + 0, 127, 146, 131, 194, 110, 65, 116, 78, 212, 196, 56, 118, 206, + 80, 110, 94, 255, 73, 193, 45, 128, 59, 194, 58, 156, 153, 35, + 177, 39, 186, 93, 126, 231, 91, 222, 235, 47, 84, 160, 148, 121, + 214, 198, 75, 92, 155, 19, 95, 175, 71, 74, 122, 65, 142, 134, + 244, 123, 219, 176, 189, 245, 77, 80, 81, 137, 120, 92, 167, 214, + 82, 26, 170, 200, 16, 44, 33, 201, 151, 132, 213, 221, 29, 155, + 126, 129, 127, 187, 146, 223, 242, 125, 23, 151, 35, 125, 145, 159, + 153, 94, 201, 238, 88, 80, 121, 142, 176, 70, 5, 127, 41, 248, + 98, 3, 82, 95, 150, 48, 61, 39, 98, 177, 148, 81, 136, 217, + 243, 206, 142, 2, 72, 70, 221, 136, 192, 94, 192, 249, 199, 41, + 66, 194, 150, 121, 25, 34, 20, 242, 166, 26, 206, 244, 199, 162, + 21, 162, 172, 45, 25, 247, 74, 64, 149, 112, 33, 45, 167, 25, + 37, 128, 81, 193, 115, 173, 49, 193, 30, 222, 139, 20, 244, 169, + 33, 252, 158, 185, 86, 102, 206, 55, 94, 6, 155, 226, 171, 54, + 51, 73, 225, 37, 97, 3, 183, 229, 64, 178, 22, 169, 178, 67, + 226, 89, 131, 251, 39, 73, 54, 157, 21, 39, 119, 22, 138, 60, + 156, 236, 151, 238, 173, 187, 159, 35, 98, 117, 41, 59, 9, 170, + 188, 111, 107, 64, 143, 15, 91, 252, 172, 169, 129, 239, 183, 66, + 220, 253, 147, 29, 14, 210, 240, 111, 200, 235, 97, 115, 252, 86, + 37, 14, 243, 49, 235, 234, 36, 251, 14, 157, 145, 247, 151, 92, + 66, 75, 100, 151, 45, 148, 38, 188, 18, 83, 210, 106, 165, 169, + 185, 76, 75, 141, 224, 187, 60, 240, 67, 47, 130, 152, 38, 59, + 186, 86, 61, 188, 182, 219, 85, 232, 252, 104, 58, 86, 33, 212, + 222, 139, 61, 60, 230, 45, 253, 199, 97, 14, 255, 105, 122, 148, + 72, 104, 144, 12, 31, 107, 30, 21, 0, 212, 225, 218, 212, 213, + 1, 96, 130, 1, 83, 236, 79, 10, 115, 195, 243, 218, 115, 83, + 86, 53, 14, 8, 244, 136, 127, 131, 230, 2, 23, 49, 167, 216, + 25, 35, 139, 184, 93, 32, 246, 131, 156, 114, 248, 61, 204, 14, + 252, 0, 88, 189, 220, 250, 186, 44, 42, 91, 99, 174, 246, 158, + 149, 59, 106, 145, 91, 166, 181, 142, 61, 171, 131, 229, 112, 156, + 32, 109, 109, 12, 137, 92, 82, 78, 174, 35, 79, 151, 85, 97, + 53, 251, 114, 52, 6, 217, 254, 6, 139, 154, 81, 231, 218, 190, + 33, 103, 51, 200, 60, 238, 115, 96, 54, 73, 61, 120, 199, 137, + 144, 207, 161, 158, 203, 176, 104, 206, 225, 104, 91, 241, 229, 210, + 42, 47, 211, 31, 120, 63, 154, 10, 60, 238, 146, 164, 254, 208, + 208, 15, 94, 6, 36, 115, 151, 164, 73, 200, 72, 150, 190, 149, + 159, 82, 18, 223, 208, 198, 23, 98, 9, 130, 176, 71, 179, 77, + 35, 127, 121, 182, 28, 141, 248, 179, 104, 14, 93, 164, 245, 25, + 243, 133, 98, 119, 252, 41, 132, 178, 92, 172, 121, 5, 135, 160, + 187, 26, 159, 254, 186, 196, 153, 222, 102, 13, 192, 106, 220, 135, + 90, 67, 148, 104, 245, 224, 193, 123, 11, 206, 34, 141, 66, 211, + 181, 217, 48, 185, 23, 183, 175, 25, 25, 196, 206, 137, 178, 178, + 108, 128, 2, 41, 31, 98, 22, 215, 21, 77, 180, 187, 55, 185, + 39, 194, 66, 242, 209, 30, 216, 78, 141, 116, 105, 188, 233, 27, + 58, 74, 137, 173, 74, 220, 78, 154, 253, 136, 50, 202, 248, 180, + 243, 241, 203, 218, 12, 145, 151, 251, 9, 157, 53, 104, 214, 92, + 241, 236, 142, 125, 214, 199, 246, 148, 150, 25, 203, 167, 26, 54, + 136, 216, 198, 155, 150, 193, 28, 73, 115, 101, 225, 92, 121, 33, + 129, 2, 198, 116, 177, 142, 72, 77, 14, 69, 152, 37, 202, 231, + 174, 111, 158, 242, 58, 57, 20, 79, 4, 96, 166, 69, 200, 98, + 77, 61, 152, 159, 62, 246, 188, 19, 6, 42, 92, 243, 129, 240, + 7, 237, 0, 202, 28, 251, 63, 25, 247, 40, 182, 147, 227, 141, + 19, 158, 47, 20, 104, 238, 92, 18, 52, 104, 49, 254, 146, 60, + 209, 116, 172, 174, 231, 57, 38, 204, 236, 131, 5, 250, 67, 228, + 201, 163, 251, 9, 247, 11, 56, 117, 170, 215, 163, 146, 33, 192, + 115, 89, 82, 102, 55, 176, 146, 143, 109, 63, 64, 66, 102, 71, + 42, 0, 44, 123, 54, 86, 215, 157, 44, 79, 216, 189, 10, 254, + 179, 215, 73, 178, 63, 5, 16, 120, 112, 18, 26, 90, 74, 3, + 172, 16, 136, 41, 235, 219, 232, 28, 247, 13, 20, 245, 73, 36, + 41, 117, 28, 116, 115, 130, 175, 47, 178, 168, 64, 167, 87, 230, + 64, 68, 182, 55, 135, 42, 139, 160, 41, 144, 117, 131, 27, 56, + 56, 32, 115, 65, 176, 3, 28, 71, 136, 147, 18, 216, 41, 237, + 8, 215, 245, 104, 231, 109, 181, 217, 226, 183, 126, 102, 49, 173, + 49, 152, 249, 28, 84, 143, 35, 136, 67, 99, 161, 249, 3, 38, + 163, 34, 50, 231, 20, 139, 96, 236, 43, 28, 84, 249, 201, 127, + 160, 206, 52, 94, 44, 17, 92, 238, 207, 77, 247, 192, 107, 98, + 149, 16, 28, 8, 107, 178, 175, 163, 113, 188, 1, 27, 160, 236, + 252, 12, 209, 102, 161, 161, 90, 92, 154, 65, 176, 79, 236, 116, + 92, 112, 28, 223, 164, 204, 175, 128, 224, 30, 127, 120, 26, 79, + 30, 240, 203, 148, 19, 10, 145, 170, 39, 40, 177, 243, 74, 189, + 152, 57, 251, 166, 229, 215, 60, 54, 164, 165, 242, 57, 37, 42, + 79, 232, 182, 149, 139, 223, 124, 93, 16, 78, 219, 13, 103, 196, + 243, 184, 149, 137, 91, 222, 229, 170, 128, 22, 8, 24, 116, 110, + 249, 80, 240, 199, 28, 133, 14, 190, 119, 101, 110, 11, 12, 204, + 147, 188, 228, 213, 53, 161, 139, 32, 206, 236, 138, 7, 16, 189, + 22, 171, 121, 138, 122, 49, 106, 134, 83, 155, 52, 20, 39, 14, + 79, 166, 238, 89, 52, 236, 11, 244, 49, 150, 162, 18, 78, 67, + 189, 98, 235, 227, 49, 206, 115, 242, 158, 83, 234, 42, 249, 111, + 98, 24, 249, 195, 75, 65, 85, 191, 97, 48, 194, 241, 111, 182, + 240, 206, 181, 129, 203, 174, 157, 49, 162, 235, 151, 31, 132, 211, + 202, 201, 219, 51, 87, 137, 203, 116, 163, 27, 160, 71, 80, 165, + 101, 3, 88, 3, 225, 122, 66, 197, 10, 153, 240, 64, 86, 17, + 42, 156, 40, 252, 110, 234, 132, 237, 218, 95, 179, 226, 60, 154, + 40, 246, 90, 179, 150, 46, 26, 225, 106, 160, 13, 99, 122, 246, + 140, 81, 188, 168, 39, 70, 30, 9, 62, 218, 91, 190, 195, 155, + 132, 56, 27, 216, 114, 100, 247, 163, 244, 34, 189, 60, 192, 109, + 29, 119, 204, 144, 88, 119, 42, 184, 4, 33, 139, 28, 129, 14, + 217, 188, 160, 228, 67, 152, 50, 89, 106, 227, 5, 142, 118, 127, + 151, 98, 251, 140, 11, 214, 45, 104, 157, 9, 50, 5, 238, 9, + 235, 187, 154, 45, 94, 167, 163, 193, 253, 0, 241, 112, 34, 166, + 57, 56, 212, 190, 154, 249, 213, 25, 240, 164, 72, 128, 192, 236, + 222, 80, 220, 239, 164, 134, 161, 250, 2, 87, 230, 36, 54, 176, + 159, 116, 80, 230, 43, 80, 103, 71, 36, 89, 198, 5, 46, 134, + 171, 224, 120, 111, 190, 7, 244, 203, 241, 175, 48, 68, 156, 115, + 33, 191, 166, 227, 32, 134, 223, 45, 162, 212, 117, 131, 55, 11, + 36, 218, 0, 216, 130, 117, 236, 74, 230, 130, 143, 19, 255, 68, + 199, 238, 183, 158, 254, 51, 83, 200, 16, 129, 228, 132, 98, 125, + 109, 16, 164, 87, 156, 71, 101, 215, 177, 217, 3, 133, 94, 63, + 177, 199, 226, 70, 59, 63, 175, 131, 100, 144, 152, 197, 49, 75, + 183, 165, 46, 130, 251, 139, 179, 255, 192, 210, 119, 1, 111, 28, + 219, 54, 185, 228, 11, 155, 225, 155, 21, 198, 15, 14, 113, 150, + 137, 196, 4, 254, 36, 37, 115, 33, 124, 126, 64, 82, 180, 253, + 234, 42, 56, 252, 60, 135, 196, 202, 124, 47, 115, 236, 252, 221, + 162, 229, 160, 238, 87, 0, 191, 248, 98, 173, 197, 25, 59, 178, + 149, 255, 57, 229, 29, 228, 46, 246, 203, 166, 38, 29, 225, 187, + 45, 169, 241, 138, 132, 150, 226, 244, 32, 0, 40, 44, 8, 59, + 219, 28, 35, 120, 12, 247, 93, 28, 71, 163, 62, 69, 204, 118, + 234, 117, 146, 41, 187, 12, 62, 52, 110, 86, 240, 167, 246, 205, + 162, 108, 95, 196, 177, 122, 154, 46, 149, 18, 114, 128, 179, 204, + 192, 21, 151, 191, 107, 228, 140, 77, 48, 194, 95, 57, 216, 21, + 39, 139, 50, 131, 183, 162, 7, 122, 8, 62, 27, 205, 195, 74, + 109, 59, 144, 23, 139, 99, 215, 94, 126, 105, 23, 187, 241, 138, + 210, 8, 27, 32, 232, 87, 55, 46, 4, 119, 86, 166, 10, 237, + 75, 96, 182, 171, 192, 90, 13, 108, 62, 177, 207, 65, 88, 115, + 237, 89, 75, 18, 160, 141, 150, 148, 48, 245, 26, 240, 87, 86, + 22, 11, 24, 244, 16, 53, 82, 37, 113, 56, 23, 137, 34, 182, + 177, 31, 176, 171, 132, 66, 231, 31, 190, 61, 232, 49, 188, 215, + 83, 33, 141, 107, 214, 40, 165, 214, 14, 59, 25, 3, 208, 251, + 205, 23, 19, 104, 198, 180, 118, 93, 78, 66, 3, 109, 30, 96, + 24, 132, 194, 61, 103, 128, 57, 183, 5, 76, 126, 40, 125, 208, + 4, 58, 201, 158, 149, 64, 86, 17, 247, 0, 131, 81, 221, 204, + 200, 167, 227, 252, 100, 43, 163, 143, 220, 69, 217, 74, 1, 247, + 66, 95, 146, 125, 225, 171, 132, 8, 241, 142, 245, 148, 253, 249, + 30, 92, 241, 227, 108, 93, 200, 199, 147, 128, 226, 6, 204, 164, + 126, 184, 34, 214, 124, 111, 41, 237, 100, 134, 228, 169, 25, 164, + 92, 241, 186, 188, 166, 75, 21, 98, 113, 71, 135, 224, 3, 218, + 73, 143, 29, 92, 52, 130, 169, 0, 184, 188, 243, 175, 206, 172, + 150, 244, 232, 29, 59, 228, 152, 163, 5, 70, 103, 208, 140, 228, + 20, 163, 35, 26, 58, 222, 221, 165, 108, 121, 223, 217, 17, 146, + 1, 75, 197, 122, 102, 115, 82, 100, 145, 134, 239, 160, 44, 196, + 29, 205, 150, 198, 38, 16, 88, 60, 246, 73, 204, 34, 20, 67, + 81, 248, 77, 89, 14, 57, 205, 96, 204, 64, 68, 31, 23, 45, + 88, 195, 28, 187, 155, 74, 81, 214, 177, 108, 140, 146, 112, 54, + 97, 14, 216, 229, 18, 118, 75, 4, 114, 111, 98, 52, 45, 22, + 44, 243, 226, 146, 129, 196, 118, 248, 187, 252, 35, 149, 2, 218, + 143, 11, 241, 69, 108, 117, 36, 77, 86, 166, 197, 42, 229, 28, + 218, 74, 99, 155, 101, 30, 3, 193, 87, 40, 59, 214, 248, 138, + 83, 161, 117, 121, 36, 213, 223, 36, 51, 5, 140, 228, 60, 245, + 199, 35, 163, 46, 80, 206, 57, 101, 11, 51, 224, 236, 147, 252, + 10, 80, 126, 123, 138, 255, 99, 144, 212, 249, 139, 192, 23, 98, + 17, 40, 232, 7, 237, 211, 136, 55, 166, 5, 16, 246, 108, 211, + 27, 118, 154, 108, 77, 5, 27, 62, 170, 144, 178, 210, 124, 234, + 130, 159, 67, 102, 24, 211, 129, 118, 230, 110, 16, 205, 122, 62, + 250, 240, 67, 56, 246, 228, 123, 62, 67, 29, 50, 171, 42, 149, + 126, 196, 118, 3, 162, 59, 252, 69, 67, 77, 27, 184, 11, 85, + 82, 106, 36, 107, 5, 107, 21, 62, 141, 152, 13, 90, 6, 117, + 58, 109, 163, 39, 107, 27, 91, 217, 23, 3, 61, 104, 145, 242, + 222, 228, 224, 30, 188, 75, 59, 144, 253, 53, 141, 112, 246, 68, + 20, 0, 26, 16, 122, 162, 102, 252, 174, 45, 229, 248, 169, 45, + 65, 177, 206, 226, 120, 129, 160, 168, 147, 199, 146, 66, 56, 235, + 186, 225, 141, 161, 27, 122, 88, 4, 174, 50, 149, 230, 179, 126, + 71, 113, 173, 174, 125, 149, 196, 200, 46, 161, 84, 236, 44, 82, + 207, 122, 88, 159, 127, 207, 88, 136, 228, 16, 232, 61, 217, 16, + 168, 215, 17, 206, 225, 158, 51, 196, 192, 6, 42, 113, 167, 60, + 109, 129, 155, 113, 210, 182, 179, 1, 217, 200, 123, 22, 241, 73, + 207, 219, 40, 6, 220, 184, 235, 46, 227, 132, 217, 252, 12, 227, + 128, 213, 117, 88, 117, 253, 82, 185, 22, 163, 225, 45, 52, 163, + 226, 237, 150, 60, 61, 240, 215, 141, 2, 191, 177, 76, 20, 212, + 166, 246, 197, 158, 21, 65, 252, 137, 5, 34, 119, 220, 149, 12, + 153, 183, 245, 40, 160, 64, 188, 129, 73, 34, 177, 51, 98, 96, + 59, 99, 184, 174, 211, 20, 175, 202, 4, 179, 127, 203, 96, 178, + 13, 193, 207, 93, 212, 12, 35, 227, 193, 153, 142, 4, 248, 222, + 31, 237, 47, 86, 128, 207, 243, 47, 78, 169, 29, 180, 179, 172, + 75, 65, 145, 91, 61, 21, 103, 150, 114, 62, 167, 101, 83, 107, + 223, 217, 27, 241, 68, 140, 229, 117, 66, 30, 18, 217, 212, 57, + 168, 166, 196, 152, 161, 28, 35, 169, 85, 196, 91, 93, 172, 113, + 76, 176, 138, 204, 157, 125, 78, 156, 14, 31, 132, 88, 146, 203, + 4, 213, 164, 84, 187, 67, 60, 0, 39, 132, 194, 242, 204, 174, + 186, 117, 170, 24, 20, 41, 156, 160, 165, 0, 139, 207, 15, 70, + 50, 195, 52, 123, 58, 63, 180, 86, 157, 157, 179, 56, 124, 59, + 63, 105, 188, 60, 77, 127, 92, 18, 13, 104, 244, 120, 250, 184, + 180, 111, 203, 226, 168, 80, 104, 75, 138, 84, 230, 157, 218, 120, + 231, 224, 6, 227, 57, 20, 69, 64, 64, 211, 255, 229, 23, 195, + 55, 98, 234, 74, 181, 61, 52, 3, 120, 86, 253, 81, 125, 20, + 255, 24, 112, 204, 96, 252, 220, 32, 220, 33, 230, 29, 124, 18, + 204, 29, 9, 188, 75, 108, 158, 60, 119, 190, 221, 255, 58, 119, + 221, 104, 190, 68, 93, 104, 241, 170, 241, 76, 106, 104, 250, 149, + 247, 190, 171, 93, 204, 130, 136, 14, 128, 178, 27, 128, 97, 158, + 11, 153, 116, 184, 13, 198, 160, 19, 181, 77, 75, 219, 251, 36, + 121, 104, 151, 18, 1, 93, 189, 86, 149, 79, 189, 219, 109, 37, + 72, 187, 188, 155, 59, 64, 29, 221, 139, 227, 172, 207, 228, 168, + 125, 43, 123, 215, 242, 26, 222, 45, 68, 174, 220, 122, 26, 146, + 110, 14, 27, 33, 153, 140, 31, 180, 7, 237, 74, 157, 96, 70, + 105, 222, 14, 142, 93, 216, 142, 86, 227, 186, 130, 41, 145, 195, + 197, 85, 231, 48, 167, 175, 124, 92, 193, 43, 10, 201, 53, 134, + 18, 150, 69, 229, 25, 49, 183, 167, 204, 15, 229, 172, 162, 25, + 146, 99, 21, 197, 132, 55, 51, 176, 184, 22, 45, 47, 104, 143, + 160, 153, 130, 19, 5, 142, 175, 167, 191, 20, 121, 12, 78, 200, + 22, 116, 131, 228, 123, 216, 145, 87, 218, 77, 10, 9, 13, 0, + 160, 155, 202, 16, 80, 169, 75, 173, 240, 161, 38, 186, 246, 127, + 137, 196, 221, 147, 229, 122, 219, 228, 222, 148, 23, 110, 69, 45, + 109, 107, 71, 95, 74, 174, 6, 139, 108, 121, 210, 17, 93, 88, + 172, 100, 10, 185, 178, 221, 81, 46, 95, 247, 42, 99, 127, 34, + 118, 237, 111, 115, 128, 187, 57, 119, 87, 26, 159, 125, 254, 55, + 113, 104, 130, 188, 199, 66, 77, 32, 143, 59, 221, 9, 253, 93, + 197, 120, 154, 240, 26, 58, 168, 115, 50, 60, 165, 154, 90, 251, + 18, 46, 65, 125, 147, 145, 183, 47, 84, 202, 15, 27, 137, 121, + 84, 105, 52, 128, 86, 88, 170, 75, 67, 132, 10, 171, 163, 217, + 75, 125, 88, 217, 11, 5, 106, 167, 230, 92, 15, 49, 253, 11, + 171, 17, 32, 56, 210, 55, 33, 218, 215, 225, 94, 181, 69, 14, + 106, 60, 30, 241, 216, 242, 110, 144, 191, 253, 191, 110, 170, 206, + 119, 222, 21, 102, 107, 206, 38, 168, 127, 142, 43, 26, 92, 119, + 187, 109, 35, 220, 212, 34, 179, 23, 213, 148, 26, 61, 126, 56, + 220, 55, 101, 197, 58, 172, 185, 81, 169, 51, 109, 248, 225, 114, + 97, 171, 11, 160, 84, 120, 78, 142, 118, 246, 245, 79, 10, 156, + 107, 39, 226, 42, 112, 33, 48, 165, 33, 125, 119, 88, 144, 26, + 100, 194, 198, 106, 154, 213, 84, 73, 150, 227, 4, 200, 36, 81, + 230, 79, 3, 216, 49, 43, 50, 213, 240, 91, 132, 36, 7, 1, + 6, 68, 238, 114, 11, 143, 250, 13, 76, 52, 223, 229, 81, 26, + 53, 244, 213, 0, 92, 126, 166, 73, 237, 117, 169, 240, 147, 120, + 124, 81, 198, 229, 83, 31, 86, 152, 172, 126, 82, 53, 128, 150, + 47, 60, 186, 111, 2, 77, 217, 72, 42, 96, 138, 36, 96, 87, + 222, 203, 223, 47, 34, 9, 208, 153, 24, 190, 42, 108, 223, 206, + 222, 90, 54, 207, 152, 97, 38, 31, 202, 68, 202, 156, 185, 245, + 197, 14, 139, 58, 218, 117, 234, 66, 53, 1, 153, 1, 1, 118, + 105, 172, 110, 71, 44, 150, 136, 191, 198, 205, 54, 96, 217, 89, + 144, 31, 25, 33, 212, 143, 45, 82, 168, 231, 9, 7, 246, 85, + 36, 17, 243, 16, 119, 46, 138, 32, 232, 15, 181, 222, 95, 2, + 255, 197, 133, 91, 69, 57, 149, 190, 56, 54, 37, 205, 168, 247, + 134, 202, 158, 121, 103, 252, 147, 177, 158, 44, 226, 65, 153, 214, + 73, 146, 124, 83, 227, 3, 3, 226, 124, 233, 0, 247, 74, 185, + 38, 193, 197, 78, 80, 190, 216, 64, 11, 139, 147, 239, 149, 197, + 100, 47, 153, 210, 207, 113, 184, 95, 199, 153, 73, 80, 244, 236, + 252, 149, 217, 110, 181, 27, 177, 28, 126, 68, 114, 147, 166, 92, + 34, 114, 93, 255, 180, 239, 148, 23, 15, 25, 162, 222, 230, 176, + 49, 76, 152, 104, 155, 178, 23, 244, 66, 35, 200, 136, 16, 25, + 110, 67, 37, 144, 75, 68, 99, 11, 3, 203, 240, 93, 53, 223, + 139, 241, 101, 149, 94, 106, 212, 254, 21, 159, 58, 217, 138, 158, + 244, 181, 187, 93, 26, 221, 176, 134, 138, 132, 21, 139, 208, 30, + 52, 123, 60, 235, 101, 141, 211, 46, 208, 251, 95, 137, 187, 48, + 103, 75, 176, 3, 86, 73, 166, 70, 246, 94, 98, 213, 9, 184, + 145, 52, 228, 100, 149, 3, 167, 69, 225, 150, 5, 133, 142, 77, + 17, 73, 228, 240, 208, 221, 253, 91, 46, 59, 156, 13, 14, 127, + 224, 107, 54, 67, 172, 123, 108, 142, 173, 217, 45, 6, 133, 74, + 123, 217, 233, 122, 242, 157, 29, 64, 78, 149, 19, 5, 97, 49, + 116, 96, 197, 252, 12, 46, 213, 238, 208, 221, 137, 23, 218, 57, + 246, 1, 15, 92, 245, 80, 207, 106, 23, 206, 81, 218, 212, 233, + 241, 159, 81, 224, 205, 240, 177, 4, 126, 141, 100, 45, 95, 155, + 188, 199, 106, 70, 131, 33, 88, 37, 211, 178, 117, 239, 45, 171, + 130, 83, 71, 69, 213, 121, 181, 174, 123, 36, 182, 162, 249, 114, + 112, 191, 161, 142, 122, 69, 68, 101, 164, 176, 155, 170, 41, 159, + 116, 14, 221, 25, 42, 32, 155, 106, 209, 246, 126, 23, 159, 142, + 62, 199, 49, 121, 103, 8, 69, 142, 124, 183, 114, 29, 97, 144, + 14, 221, 168, 193, 184, 168, 226, 208, 4, 138, 124, 84, 144, 144, + 146, 157, 10, 122, 167, 77, 188, 184, 190, 208, 244, 29, 217, 136, + 209, 88, 135, 61, 177, 112, 176, 46, 84, 109, 134, 236, 4, 216, + 231, 169, 115, 134, 104, 174, 236, 221, 214, 172, 105, 100, 26, 241, + 128, 89, 154, 63, 172, 80, 168, 143, 185, 99, 128, 54, 125, 221, + 160, 11, 207, 83, 193, 177, 150, 20, 18, 231, 145, 135, 113, 2, + 237, 209, 218, 186, 191, 177, 121, 70, 65, 169, 253, 28, 93, 28, + 184, 115, 139, 65, 160, 111, 98, 173, 167, 38, 128, 24, 137, 205, + 217, 133, 3, 177, 127, 68, 192, 58, 71, 179, 176, 143, 147, 1, + 120, 167, 36, 62, 131, 18, 149, 128, 208, 23, 113, 229, 122, 184, + 120, 90, 99, 223, 155, 124, 174, 91, 39, 34, 109, 252, 124, 138, + 41, 34, 80, 0, 195, 37, 154, 92, 49, 140, 202, 33, 184, 132, + 18, 91, 212, 141, 252, 49, 89, 12, 42, 197, 34, 217, 212, 50, + 85, 193, 122, 132, 136, 255, 243, 129, 213, 85, 211, 149, 54, 156, + 133, 56, 84, 94, 72, 112, 63, 172, 144, 118, 67, 0, 179, 11, + 162, 204, 222, 13, 136, 208, 43, 37, 62, 119, 247, 79, 184, 15, + 157, 9, 17, 100, 112, 45, 173, 84, 137, 108, 200, 217, 112, 129, + 63, 1, 59, 83, 61, 181, 148, 10, 103, 45, 222, 89, 44, 127, + 121, 215, 177, 202, 46, 241, 198, 98, 123, 20, 206, 251, 8, 166, + 151, 16, 47, 106, 231, 20, 157, 198, 130, 211, 201, 34, 176, 0, + 94, 224, 84, 99, 14, 10, 77, 194, 148, 137, 150, 5, 76, 21, + 125, 106, 35, 122, 116, 21, 183, 90, 95, 176, 124, 90, 54, 8, + 230, 106, 195, 8, 83, 243, 88, 53, 10, 170, 8, 24, 61, 177, + 221, 79, 136, 238, 133, 184, 245, 141, 250, 34, 25, 95, 207, 191, + 51, 126, 173, 84, 131, 10, 253, 189, 198, 101, 203, 17, 78, 54, + 124, 241, 67, 23, 47, 169, 220, 226, 253, 93, 236, 53, 215, 103, + 137, 234, 105, 240, 167, 212, 253, 73, 34, 116, 0, 124, 77, 81, + 106, 34, 192, 141, 197, 219, 102, 55, 188, 239, 135, 227, 52, 77, + 150, 108, 254, 229, 246, 19, 150, 238, 75, 54, 103, 41, 137, 42, + 52, 223, 68, 125, 48, 71, 98, 176, 98, 249, 47, 232, 168, 234, + 111, 128, 214, 174, 247, 24, 116, 193, 142, 3, 133, 225, 80, 233, + 59, 140, 159, 143, 148, 238, 119, 95, 148, 52, 214, 146, 213, 153, + 138, 35, 197, 14, 164, 158, 133, 15, 54, 189, 69, 97, 59, 252, + 254, 95, 128, 96, 29, 224, 220, 107, 198, 106, 187, 59, 145, 99, + 9, 76, 243, 138, 196, 119, 103, 237, 131, 109, 120, 148, 209, 70, + 105, 34, 166, 138, 120, 255, 192, 110, 126, 176, 242, 172, 61, 37, + 185, 223, 161, 158, 156, 169, 25, 22, 157, 106, 23, 89, 209, 247, + 173, 101, 71, 140, 100, 76, 135, 240, 251, 119, 88, 180, 118, 17, + 133, 97, 37, 249, 10, 135, 94, 163, 7, 42, 90, 13, 210, 248, + 144, 94, 108, 175, 103, 193, 210, 193, 201, 42, 26, 197, 150, 113, + 239, 244, 153, 130, 120, 1, 115, 118, 98, 54, 13, 223, 23, 80, + 131, 205, 124, 93, 18, 47, 197, 169, 175, 209, 27, 224, 113, 228, + 106, 83, 73, 123, 210, 128, 16, 168, 245, 95, 93, 77, 115, 94, + 40, 200, 236, 73, 219, 7, 247, 174, 30, 69, 220, 149, 89, 204, + 233, 226, 108, 234, 174, 80, 24, 82, 124, 50, 49, 49, 182, 39, + 9, 160, 227, 55, 160, 190, 165, 22, 235, 15, 4, 231, 99, 14, + 194, 170, 61, 162, 66, 69, 58, 159, 45, 62, 91, 207, 107, 168, + 23, 133, 49, 59, 2, 233, 115, 104, 196, 173, 109, 114, 199, 18, + 153, 218, 227, 196, 124, 55, 42, 171, 153, 188, 58, 169, 11, 26, + 197, 239, 33, 47, 240, 7, 19, 210, 240, 7, 214, 17, 167, 110, + 103, 29, 214, 214, 202, 175, 197, 47, 155, 18, 96, 187, 253, 142, + 87, 206, 11, 162, 188, 160, 227, 6, 200, 53, 127, 130, 144, 197, + 148, 32, 126, 225, 14, 162, 118, 181, 118, 185, 73, 185, 117, 252, + 225, 249, 200, 65, 244, 120, 186, 0, 2, 217, 216, 139, 38, 172, + 86, 135, 26, 115, 138, 154, 211, 143, 227, 57, 22, 180, 16, 183, + 136, 242, 238, 230, 176, 225, 182, 78, 176, 209, 90, 52, 231, 183, + 218, 84, 123, 254, 21, 182, 179, 51, 9, 81, 254, 150, 166, 252, + 89, 121, 93, 200, 204, 198, 245, 223, 17, 147, 126, 144, 240, 93, + 155, 231, 17, 246, 183, 210, 20, 182, 150, 57, 63, 107, 244, 227, + 201, 84, 252, 14, 188, 90, 137, 159, 98, 156, 54, 243, 48, 215, + 113, 189, 13, 60, 194, 101, 165, 183, 159, 22, 167, 69, 77, 15, + 53, 173, 77, 111, 194, 196, 13, 9, 196, 218, 163, 1, 165, 26, + 139, 66, 125, 19, 196, 34, 220, 135, 108, 137, 249, 211, 143, 115, + 135, 157, 86, 89, 131, 159, 178, 217, 234, 155, 99, 138, 124, 12, + 52, 243, 67, 43, 104, 116, 113, 35, 242, 70, 180, 252, 148, 129, + 247, 25, 169, 107, 19, 189, 117, 242, 90, 166, 192, 23, 175, 133, + 7, 119, 100, 253, 48, 187, 146, 59, 145, 23, 233, 49, 165, 44, + 177, 120, 9, 140, 222, 25, 228, 162, 33, 127, 252, 237, 161, 84, + 228, 114, 110, 17, 73, 226, 245, 95, 129, 21, 251, 43, 101, 190, + 189, 3, 255, 182, 155, 208, 121, 212, 151, 151, 110, 193, 207, 244, + 36, 217, 92, 141, 37, 14, 81, 38, 223, 3, 139, 58, 49, 176, + 13, 162, 52, 60, 132, 79, 13, 227, 115, 21, 27, 141, 69, 39, + 219, 1, 237, 232, 73, 116, 201, 138, 160, 1, 217, 59, 75, 211, + 37, 24, 192, 121, 53, 202, 95, 68, 104, 216, 60, 144, 180, 85, + 32, 45, 196, 209, 23, 92, 191, 180, 216, 231, 106, 57, 63, 86, + 33, 87, 205, 241, 97, 48, 35, 105, 74, 152, 91, 239, 200, 254, + 32, 178, 56, 68, 82, 107, 208, 13, 30, 213, 232, 201, 48, 204, + 165, 37, 65, 198, 165, 84, 163, 58, 71, 158, 37, 220, 35, 206, + 111, 221, 167, 88, 172, 90, 104, 42, 126, 182, 103, 70, 9, 24, + 79, 220, 57, 157, 56, 182, 217, 162, 53, 48, 45, 23, 131, 116, + 150, 31, 107, 25, 3, 68, 157, 138, 211, 145, 232, 217, 159, 179, + 190, 105, 14, 76, 15, 178, 171, 128, 136, 255, 66, 134, 111, 136, + 154, 99, 122, 211, 124, 76, 59, 10, 82, 65, 90, 76, 128, 224, + 28, 91, 138, 207, 135, 86, 229, 162, 67, 231, 83, 196, 207, 55, + 253, 119, 223, 217, 148, 137, 54, 149, 245, 93, 72, 96, 136, 168, + 244, 70, 198, 1, 253, 2, 28, 203, 49, 7, 66, 68, 48, 27, + 201, 4, 79, 185, 141, 36, 65, 94, 192, 244, 242, 9, 18, 191, + 151, 124, 92, 215, 3, 88, 81, 175, 190, 228, 1, 186, 92, 45, + 221, 98, 26, 170, 193, 9, 111, 39, 99, 136, 6, 170, 66, 205, + 86, 244, 182, 115, 105, 86, 116, 175, 170, 71, 77, 222, 126, 120, + 190, 92, 195, 240, 154, 57, 245, 122, 136, 180, 75, 198, 132, 12, + 67, 91, 192, 249, 177, 249, 143, 69, 102, 196, 37, 19, 99, 210, + 66, 185, 127, 202, 73, 14, 4, 128, 125, 53, 86, 195, 221, 242, + 93, 179, 250, 163, 212, 204, 112, 85, 68, 56, 50, 226, 16, 157, + 131, 191, 176, 52, 184, 163, 78, 134, 75, 110, 48, 231, 42, 94, + 204, 61, 99, 154, 7, 53, 142, 128, 106, 54, 239, 159, 11, 183, + 99, 77, 113, 101, 60, 194, 156, 91, 127, 45, 131, 183, 229, 174, + 104, 40, 242, 116, 124, 84, 212, 186, 163, 184, 21, 15, 247, 141, + 51, 245, 2, 188, 158, 47, 107, 143, 244, 62, 240, 51, 193, 168, + 159, 32, 42, 132, 170, 132, 190, 201, 90, 158, 231, 61, 234, 32, + 19, 133, 48, 73, 140, 247, 49, 39, 106, 205, 242, 123, 134, 142, + 241, 223, 117, 242, 146, 99, 241, 65, 24, 38, 251, 60, 26, 80, + 75, 239, 111, 133, 165, 69, 103, 197, 90, 196, 18, 83, 92, 174, + 172, 231, 185, 0, 12, 235, 16, 34, 66, 113, 18, 144, 148, 106, + 44, 141, 123, 101, 13, 55, 151, 154, 199, 220, 221, 81, 95, 90, + 159, 91, 203, 123, 13, 99, 210, 185, 100, 62, 160, 187, 171, 58, + 198, 213, 28, 217, 193, 7, 40, 27, 33, 116, 62, 160, 233, 97, + 229, 189, 121, 85, 70, 30, 70, 124, 162, 45, 139, 234, 36, 46, + 40, 31, 60, 246, 49, 32, 229, 57, 9, 115, 123, 31, 90, 72, + 184, 47, 40, 24, 52, 130, 30, 71, 24, 99, 200, 213, 194, 106, + 110, 28, 160, 173, 208, 46, 130, 161, 54, 1, 241, 87, 170, 18, + 87, 253, 25, 113, 0, 121, 147, 239, 10, 110, 20, 147, 78, 208, + 122, 205, 172, 18, 56, 171, 47, 156, 46, 249, 74, 21, 48, 246, + 10, 111, 34, 65, 83, 246, 247, 41, 109, 195, 205, 192, 32, 78, + 100, 161, 137, 137, 91, 73, 117, 166, 119, 127, 146, 75, 62, 204, + 145, 37, 14, 23, 185, 147, 40, 89, 26, 56, 48, 72, 12, 127, + 82, 218, 61, 9, 158, 204, 208, 114, 196, 220, 71, 245, 120, 47, + 172, 74, 55, 72, 206, 9, 252, 147, 32, 126, 183, 4, 28, 69, + 236, 74, 43, 162, 183, 149, 126, 242, 70, 117, 121, 145, 255, 181, + 194, 79, 64, 205, 243, 147, 12, 46, 81, 179, 135, 181, 125, 205, + 26, 187, 200, 21, 70, 67, 220, 35, 170, 38, 54, 171, 6, 38, + 241, 46, 54, 183, 135, 175, 135, 192, 152, 34, 186, 185, 102, 124, + 244, 180, 90, 130, 128, 93, 239, 58, 25, 149, 183, 122, 81, 26, + 230, 239, 145, 187, 120, 245, 51, 77, 227, 90, 110, 119, 194, 230, + 76, 37, 185, 95, 175, 94, 219, 216, 13, 192, 228, 179, 198, 105, + 112, 230, 27, 68, 100, 20, 39, 149, 71, 13, 28, 199, 225, 235, + 13, 70, 202, 79, 176, 139, 223, 123, 141, 158, 148, 37, 246, 21, + 73, 107, 158, 16, 186, 148, 78, 98, 123, 76, 99, 158, 191, 170, + 93, 103, 151, 244, 234, 62, 3, 245, 41, 78, 132, 129, 148, 82, + 2, 187, 52, 133, 56, 191, 223, 7, 143, 175, 9, 217, 152, 10, + 1, 155, 242, 40, 65, 36, 76, 78, 224, 204, 242, 92, 116, 109, + 14, 159, 165, 228, 90, 222, 95, 203, 100, 59, 96, 76, 127, 162, + 29, 65, 212, 92, 169, 121, 195, 111, 104, 185, 200, 180, 222, 43, + 72, 72, 188, 143, 63, 169, 181, 118, 125, 54, 194, 62, 94, 73, + 145, 49, 235, 167, 185, 17, 29, 179, 183, 251, 93, 209, 19, 95, + 210, 228, 171, 177, 36, 49, 105, 68, 158, 74, 181, 129, 152, 94, + 33, 53, 148, 167, 50, 108, 117, 25, 170, 144, 20, 121, 99, 57, + 28, 229, 119, 171, 74, 48, 73, 84, 126, 144, 162, 59, 99, 194, + 94, 73, 138, 141, 241, 151, 95, 51, 232, 21, 188, 191, 145, 42, + 177, 17, 225, 207, 59, 41, 87, 8, 169, 138, 5, 184, 16, 153, + 162, 51, 211, 85, 140, 79, 186, 188, 90, 188, 100, 200, 243, 236, + 137, 139, 121, 34, 75, 194, 168, 22, 118, 73, 212, 75, 125, 185, + 190, 61, 55, 98, 5, 34, 43, 200, 144, 109, 144, 112, 142, 71, + 35, 102, 235, 107, 3, 203, 104, 104, 113, 225, 59, 123, 148, 200, + 51, 61, 134, 180, 182, 150, 111, 189, 220, 224, 108, 59, 227, 246, + 202, 186, 142, 76, 161, 112, 32, 212, 109, 15, 30, 37, 96, 202, + 127, 79, 139, 87, 242, 229, 96, 91, 37, 125, 109, 217, 117, 74, + 116, 128, 1, 74, 183, 242, 19, 216, 179, 139, 255, 67, 177, 226, + 186, 155, 11, 240, 228, 57, 198, 93, 33, 7, 115, 44, 115, 71, + 124, 46, 24, 187, 251, 203, 53, 120, 249, 67, 15, 222, 19, 169, + 11, 83, 225, 246, 227, 89, 20, 227, 165, 241, 27, 244, 125, 82, + 121, 3, 162, 43, 17, 88, 196, 100, 184, 209, 145, 225, 202, 202, + 241, 111, 95, 109, 200, 134, 58, 220, 238, 5, 245, 5, 185, 7, + 9, 72, 133, 216, 153, 3, 9, 111, 105, 140, 224, 120, 229, 234, + 20, 192, 16, 149, 155, 98, 191, 100, 53, 161, 134, 73, 226, 147, + 83, 174, 118, 185, 58, 125, 245, 104, 119, 204, 47, 193, 118, 57, + 83, 40, 221, 126, 73, 147, 124, 163, 79, 204, 233, 210, 88, 115, + 163, 247, 56, 20, 35, 201, 138, 230, 127, 230, 86, 162, 177, 192, + 108, 168, 175, 193, 100, 101, 148, 184, 22, 200, 203, 147, 76, 61, + 100, 175, 196, 247, 125, 121, 234, 226, 3, 43, 208, 168, 124, 175, + 42, 148, 248, 70, 21, 14, 37, 9, 139, 94, 91, 113, 22, 152, + 237, 132, 118, 73, 199, 250, 90, 62, 25, 178, 15, 31, 245, 145, + 63, 67, 231, 65, 86, 184, 144, 150, 106, 138, 64, 193, 250, 66, + 203, 230, 209, 115, 131, 98, 248, 109, 219, 5, 1, 104, 5, 15, + 152, 113, 156, 184, 249, 77, 117, 179, 218, 64, 48, 178, 135, 208, + 242, 23, 30, 144, 165, 238, 189, 50, 107, 90, 177, 251, 5, 58, + 82, 179, 206, 170, 190, 174, 128, 139, 180, 210, 127, 77, 145, 137, + 9, 140, 95, 155, 242, 54, 121, 194, 204, 71, 99, 191, 214, 89, + 155, 102, 247, 56, 224, 217, 210, 220, 45, 63, 225, 81, 145, 124, + 142, 135, 254, 21, 17, 80, 107, 176, 219, 149, 222, 40, 225, 51, + 116, 122, 182, 224, 4, 194, 203, 126, 154, 237, 77, 185, 229, 57, + 14, 216, 104, 54, 29, 91, 38, 16, 201, 162, 216, 168, 237, 169, + 32, 58, 34, 221, 109, 40, 65, 127, 9, 114, 127, 149, 121, 107, + 6, 43, 173, 125, 136, 190, 82, 194, 140, 4, 238, 210, 0, 78, + 100, 245, 254, 245, 219, 213, 125, 234, 60, 85, 210, 22, 90, 149, + 254, 4, 186, 195, 146, 217, 73, 210, 8, 73, 10, 76, 169, 208, + 214, 199, 56, 122, 53, 223, 82, 205, 244, 59, 154, 58, 249, 235, + 95, 142, 14, 120, 77, 46, 144, 58, 65, 47, 58, 85, 78, 182, + 143, 150, 55, 251, 185, 148, 122, 183, 230, 88, 33, 188, 29, 214, + 189, 163, 204, 35, 227, 44, 92, 139, 43, 155, 126, 172, 61, 73, + 217, 147, 65, 150, 178, 183, 179, 61, 135, 164, 197, 88, 173, 44, + 67, 135, 143, 141, 230, 172, 228, 8, 96, 67, 40, 47, 246, 37, + 130, 249, 194, 188, 64, 177, 92, 162, 32, 136, 152, 54, 67, 175, + 97, 166, 211, 96, 170, 110, 236, 209, 198, 189, 45, 181, 68, 138, + 95, 72, 73, 11, 19, 57, 1, 217, 89, 77, 125, 13, 72, 187, + 98, 138, 35, 146, 143, 134, 52, 210, 219, 209, 27, 229, 211, 56, + 203, 229, 19, 243, 79, 217, 94, 205, 90, 113, 40, 192, 94, 194, + 112, 211, 4, 46, 205, 179, 198, 106, 45, 54, 227, 210, 3, 108, + 96, 37, 137, 157, 161, 54, 203, 244, 229, 3, 96, 152, 167, 137, + 141, 213, 254, 145, 116, 59, 186, 3, 35, 95, 99, 201, 67, 100, + 63, 142, 93, 106, 116, 61, 49, 155, 81, 123, 17, 226, 166, 97, + 84, 124, 149, 207, 12, 52, 191, 46, 146, 113, 31, 135, 51, 28, + 115, 187, 244, 174, 67, 165, 76, 186, 239, 139, 196, 94, 238, 233, + 235, 93, 238, 213, 138, 156, 46, 6, 73, 207, 203, 203, 150, 91, + 206, 92, 17, 73, 101, 82, 242, 234, 175, 11, 44, 222, 234, 28, + 96, 35, 163, 147, 15, 105, 119, 1, 242, 136, 16, 37, 20, 130, + 220, 75, 85, 230, 24, 203, 170, 245, 98, 246, 159, 139, 30, 109, + 122, 111, 167, 76, 125, 192, 196, 4, 222, 227, 167, 45, 37, 61, + 99, 221, 7, 135, 63, 175, 69, 111, 157, 155, 230, 122, 234, 84, + 26, 34, 57, 54, 123, 19, 64, 94, 31, 122, 9, 25, 31, 76, + 191, 106, 211, 86, 1, 100, 120, 18, 37, 35, 162, 73, 12, 175, + 225, 135, 195, 116, 152, 37, 216, 50, 178, 96, 20, 137, 189, 241, + 29, 193, 242, 106, 254, 243, 204, 99, 147, 254, 165, 222, 107, 242, + 102, 206, 190, 210, 75, 125, 224, 51, 177, 29, 49, 100, 126, 12, + 189, 186, 192, 23, 213, 89, 78, 176, 33, 133, 176, 86, 47, 193, + 38, 152, 167, 35, 16, 61, 142, 73, 249, 56, 125, 138, 127, 251, + 158, 238, 208, 187, 60, 222, 111, 44, 142, 169, 14, 36, 244, 82, + 96, 129, 197, 105, 48, 122, 182, 255, 123, 184, 25, 66, 52, 175, + 57, 216, 125, 122, 154, 14, 23, 27, 202, 9, 124, 110, 69, 130, + 183, 134, 213, 228, 84, 51, 184, 20, 94, 52, 220, 247, 49, 126, + 168, 30, 162, 77, 180, 165, 2, 116, 20, 72, 87, 241, 236, 183, + 45, 218, 58, 103, 239, 46, 225, 84, 14, 7, 200, 2, 86, 25, + 4, 49, 74, 160, 87, 201, 34, 184, 25, 216, 221, 220, 250, 178, + 197, 131, 125, 96, 176, 134, 229, 145, 121, 247, 159, 225, 28, 58, + 86, 221, 160, 228, 230, 53, 80, 212, 63, 38, 141, 113, 125, 160, + 233, 118, 189, 187, 152, 11, 30, 181, 2, 118, 220, 107, 134, 214, + 47, 216, 114, 160, 194, 70, 3, 117, 183, 213, 179, 97, 218, 143, + 30, 58, 106, 71, 194, 130, 99, 254, 14, 58, 73, 136, 119, 125, + 232, 56, 79, 232, 17, 51, 17, 68, 145, 221, 88, 74, 116, 26, + 207, 31, 64, 86, 142, 221, 194, 112, 219, 91, 134, 151, 241, 79, + 88, 114, 163, 69, 227, 85, 80, 182, 207, 96, 105, 40, 158, 124, + 108, 255, 67, 29, 172, 134, 231, 211, 91, 49, 87, 50, 145, 139, + 126, 131, 115, 221, 149, 12, 103, 227, 97, 217, 11, 230, 155, 64, + 192, 95, 33, 137, 43, 18, 179, 242, 136, 47, 179, 49, 84, 176, + 224, 104, 146, 19, 175, 141, 197, 146, 201, 90, 48, 206, 22, 239, + 57, 127, 52, 203, 102, 146, 195, 225, 191, 210, 175, 206, 202, 11, + 58, 71, 242, 202, 107, 150, 169, 65, 59, 39, 31, 41, 79, 187, + 7, 242, 253, 223, 192, 44, 251, 64, 101, 41, 77, 41, 236, 247, + 235, 22, 14, 245, 117, 61, 215, 173, 124, 148, 203, 97, 32, 184, + 141, 110, 50, 119, 7, 228, 41, 186, 28, 26, 65, 146, 162, 176, + 225, 213, 25, 164, 222, 151, 120, 182, 188, 205, 135, 131, 55, 124, + 25, 103, 210, 210, 26, 161, 215, 34, 21, 112, 5, 100, 24, 26, + 127, 156, 56, 97, 149, 61, 182, 212, 107, 11, 22, 82, 5, 93, + 65, 211, 89, 87, 65, 189, 129, 66, 184, 233, 255, 128, 98, 95, + 80, 183, 54, 64, 222, 229, 203, 23, 212, 204, 103, 66, 148, 205, + 233, 184, 138, 163, 68, 39, 150, 44, 192, 78, 151, 226, 244, 87, + 14, 8, 248, 175, 101, 212, 216, 27, 249, 46, 134, 214, 44, 179, + 63, 8, 228, 93, 141, 97, 53, 183, 45, 118, 207, 148, 253, 240, + 22, 21, 200, 37, 226, 50, 91, 4, 32, 138, 201, 153, 168, 75, + 128, 79, 204, 228, 90, 190, 64, 242, 107, 213, 35, 10, 117, 224, + 115, 153, 16, 110, 103, 217, 197, 45, 173, 60, 14, 242, 47, 207, + 111, 5, 159, 75, 157, 253, 219, 74, 1, 181, 9, 218, 115, 142, + 58, 167, 161, 214, 212, 136, 7, 210, 194, 167, 79, 67, 202, 30, + 33, 174, 79, 207, 116, 88, 35, 33, 93, 240, 16, 112, 34, 245, + 237, 35, 107, 90, 162, 231, 249, 74, 136, 1, 222, 108, 37, 231, + 247, 193, 126, 203, 52, 234, 91, 150, 151, 142, 141, 155, 0, 145, + 25, 247, 130, 216, 187, 62, 192, 20, 170, 43, 175, 254, 204, 181, + 169, 202, 116, 71, 16, 28, 230, 200, 13, 114, 130, 20, 87, 143, + 69, 0, 254, 224, 232, 80, 51, 42, 176, 115, 165, 246, 225, 13, + 90, 57, 161, 222, 98, 137, 255, 59, 172, 52, 106, 55, 37, 80, + 112, 88, 156, 171, 80, 46, 12, 29, 69, 0, 137, 4, 228, 139, + 150, 114, 13, 41, 251, 44, 74, 35, 221, 161, 124, 88, 250, 148, + 133, 50, 228, 109, 33, 58, 18, 81, 183, 168, 111, 168, 244, 209, + 123, 144, 168, 245, 124, 160, 187, 111, 44, 144, 84, 201, 108, 239, + 188, 122, 149, 139, 175, 111, 73, 44, 28, 27, 217, 92, 4, 132, + 76, 105, 52, 29, 241, 234, 255, 75, 14, 99, 231, 13, 142, 204, + 47, 25, 112, 77, 89, 118, 69, 139, 171, 105, 183, 174, 105, 158, + 61, 62, 182, 26, 151, 172, 210, 122, 40, 184, 83, 33, 167, 76, + 199, 192, 58, 244, 6, 4, 161, 79, 13, 198, 129, 204, 60, 169, + 89, 77, 20, 172, 10, 86, 72, 128, 209, 226, 141, 194, 221, 73, + 129, 217, 248, 143, 216, 182, 113, 65, 38, 2, 107, 186, 250, 234, + 95, 179, 102, 68, 225, 76, 170, 11, 112, 192, 38, 133, 62, 142, + 123, 55, 144, 196, 20, 80, 31, 121, 208, 200, 88, 167, 109, 147, + 117, 146, 95, 130, 201, 118, 227, 187, 160, 47, 18, 55, 70, 70, + 30, 127, 98, 179, 154, 233, 46, 91, 80, 78, 169, 166, 15, 45, + 79, 164, 7, 68, 27, 197, 21, 160, 1, 181, 238, 228, 56, 1, + 188, 148, 253, 9, 25, 170, 235, 114, 88, 195, 197, 18, 244, 84, + 121, 0, 76, 36, 51, 149, 193, 207, 197, 122, 247, 210, 146, 21, + 77, 83, 51, 92, 234, 13, 128, 247, 48, 75, 51, 20, 186, 168, + 243, 180, 228, 217, 211, 87, 141, 115, 241, 103, 5, 157, 158, 191, + 164, 155, 160, 158, 118, 168, 135, 96, 73, 208, 36, 60, 188, 171, + 84, 53, 235, 249, 77, 17, 135, 253, 34, 217, 224, 179, 80, 95, + 23, 193, 5, 8, 140, 182, 165, 38, 239, 133, 253, 58, 104, 184, + 178, 12, 33, 150, 195, 52, 50, 249, 60, 93, 82, 35, 87, 207, + 17, 111, 95, 176, 160, 127, 35, 89, 49, 180, 133, 126, 251, 16, + 171, 26, 161, 66, 186, 205, 139, 118, 255, 68, 44, 108, 39, 136, + 208, 34, 92, 172, 23, 223, 213, 229, 67, 64, 180, 48, 237, 30, + 214, 166, 43, 61, 9, 3, 142, 6, 183, 31, 28, 130, 70, 221, + 79, 235, 7, 243, 20, 143, 92, 203, 91, 203, 69, 41, 37, 62, + 228, 133, 147, 85, 145, 234, 7, 25, 114, 18, 179, 189, 126, 95, + 151, 93, 66, 3, 200, 132, 189, 1, 11, 191, 79, 29, 218, 94, + 113, 78, 166, 79, 179, 126, 178, 14, 198, 0, 179, 234, 121, 107, + 95, 80, 187, 84, 197, 32, 119, 28, 106, 52, 242, 178, 39, 211, + 147, 168, 101, 76, 44, 188, 170, 136, 29, 204, 220, 177, 121, 222, + 151, 221, 47, 130, 56, 108, 187, 115, 69, 128, 45, 226, 86, 247, + 166, 110, 215, 138, 192, 235, 135, 229, 31, 47, 122, 48, 225, 133, + 188, 209, 46, 164, 27, 92, 209, 28, 152, 41, 198, 142, 176, 14, + 103, 81, 57, 226, 188, 17, 214, 190, 228, 84, 75, 91, 240, 225, + 208, 66, 229, 197, 221, 25, 28, 163, 229, 44, 241, 187, 230, 249, + 140, 140, 115, 249, 173, 91, 9, 110, 212, 31, 72, 94, 228, 69, + 205, 41, 209, 230, 53, 239, 185, 79, 210, 120, 100, 102, 174, 44, + 85, 233, 221, 20, 111, 156, 133, 178, 102, 186, 112, 15, 240, 63, + 121, 218, 49, 100, 108, 16, 228, 245, 160, 191, 210, 21, 253, 178, + 103, 81, 122, 194, 141, 217, 194, 162, 32, 29, 93, 27, 56, 141, + 156, 150, 6, 28, 3, 162, 181, 78, 39, 159, 187, 176, 210, 47, + 189, 56, 206, 22, 225, 117, 101, 192, 90, 226, 121, 19, 98, 144, + 232, 245, 250, 20, 224, 223, 171, 214, 14, 175, 87, 31, 129, 251, + 202, 165, 27, 35, 203, 63, 49, 87, 38, 215, 177, 33, 100, 190, + 187, 41, 228, 2, 68, 75, 72, 238, 4, 186, 138, 177, 200, 220, + 161, 149, 41, 136, 10, 95, 136, 64, 206, 174, 255, 218, 169, 102, + 149, 54, 218, 245, 71, 157, 212, 67, 99, 118, 151, 56, 121, 179, + 222, 248, 254, 29, 32, 170, 189, 240, 54, 26, 63, 245, 115, 110, + 211, 233, 97, 8, 13, 225, 30, 109, 70, 136, 212, 194, 144, 102, + 9, 79, 76, 93, 198, 94, 108, 32, 105, 98, 146, 142, 144, 103, + 158, 48, 160, 124, 150, 40, 58, 212, 48, 26, 141, 245, 91, 217, + 121, 185, 108, 91, 22, 13, 106, 34, 63, 132, 169, 114, 87, 153, + 163, 4, 160, 190, 79, 78, 43, 77, 103, 215, 155, 62, 172, 241, + 128, 185, 2, 88, 232, 134, 25, 5, 83, 43, 7, 68, 167, 114, + 41, 172, 16, 92, 252, 159, 222, 96, 15, 40, 169, 23, 91, 188, + 214, 73, 13, 220, 156, 200, 252, 149, 33, 237, 73, 146, 154, 68, + 227, 202, 203, 24, 235, 54, 88, 47, 186, 214, 137, 54, 14, 197, + 215, 91, 24, 223, 77, 231, 246, 126, 141, 157, 150, 104, 170, 106, + 79, 92, 76, 172, 167, 65, 128, 45, 252, 21, 25, 80, 109, 21, + 144, 160, 220, 109, 109, 28, 4, 141, 183, 36, 89, 142, 119, 61, + 216, 9, 70, 68, 20, 160, 115, 17, 51, 152, 253, 43, 59, 85, + 185, 131, 84, 25, 154, 43, 214, 207, 71, 13, 227, 126, 235, 66, + 155, 27, 12, 115, 135, 134, 63, 122, 102, 209, 51, 232, 167, 170, + 166, 164, 89, 0, 54, 15, 149, 72, 235, 41, 195, 31, 220, 253, + 170, 45, 112, 83, 48, 71, 50, 58, 78, 254, 143, 184, 190, 19, + 193, 118, 59, 75, 69, 69, 202, 59, 197, 188, 65, 163, 201, 185, + 40, 65, 152, 158, 142, 119, 66, 179, 115, 63, 14, 30, 56, 20, + 53, 142, 251, 85, 23, 182, 87, 173, 251, 7, 72, 210, 116, 254, + 163, 174, 134, 173, 84, 165, 120, 246, 59, 17, 136, 26, 142, 34, + 113, 199, 230, 198, 237, 49, 162, 184, 206, 30, 176, 92, 82, 174, + 154, 204, 225, 135, 156, 164, 205, 208, 108, 46, 190, 164, 167, 51, + 231, 23, 104, 215, 230, 58, 169, 66, 230, 190, 72, 66, 179, 201, + 179, 142, 115, 168, 251, 87, 33, 111, 209, 142, 8, 188, 119, 231, + 106, 227, 127, 218, 173, 164, 148, 151, 89, 32, 4, 82, 29, 42, + 104, 95, 8, 110, 156, 0, 223, 240, 151, 188, 29, 2, 76, 186, + 239, 245, 7, 86, 74, 244, 79, 128, 91, 64, 31, 52, 186, 78, + 234, 160, 59, 23, 160, 1, 119, 15, 120, 176, 0, 169, 147, 93, + 67, 52, 49, 83, 212, 70, 5, 202, 42, 50, 112, 235, 116, 97, + 194, 105, 174, 38, 92, 154, 135, 108, 153, 52, 208, 29, 127, 86, + 203, 222, 12, 8, 237, 17, 226, 156, 16, 32, 131, 52, 93, 4, + 46, 35, 220, 71, 205, 147, 160, 7, 19, 0, 127, 41, 64, 86, + 100, 9, 158, 183, 149, 164, 194, 130, 185, 24, 99, 14, 6, 237, + 22, 36, 249, 128, 136, 104, 222, 121, 135, 140, 122, 94, 160, 8, + 114, 249, 83, 92, 224, 253, 3, 235, 242, 50, 26, 210, 15, 167, + 138, 176, 3, 190, 88, 108, 136, 8, 22, 170, 20, 42, 212, 233, + 220, 37, 122, 22, 221, 84, 108, 152, 250, 30, 9, 174, 106, 232, + 62, 15, 254, 87, 142, 63, 89, 150, 176, 43, 85, 107, 154, 96, + 210, 185, 26, 43, 232, 204, 172, 123, 132, 100, 5, 43, 145, 108, + 81, 123, 247, 236, 39, 164, 181, 136, 246, 60, 39, 227, 78, 9, + 167, 226, 134, 142, 17, 122, 61, 105, 223, 23, 12, 124, 58, 246, + 236, 88, 121, 162, 6, 251, 156, 200, 95, 17, 66, 206, 97, 67, + 230, 141, 148, 137, 229, 54, 95, 118, 189, 211, 18, 230, 40, 116, + 221, 215, 22, 39, 41, 220, 153, 246, 19, 77, 71, 12, 203, 77, + 54, 150, 7, 212, 110, 81, 99, 71, 103, 240, 85, 162, 130, 224, + 62, 132, 42, 44, 182, 65, 53, 88, 65, 250, 134, 155, 30, 141, + 101, 239, 49, 121, 222, 116, 113, 96, 143, 17, 60, 78, 92, 219, + 255, 86, 186, 245, 204, 37, 130, 170, 166, 58, 13, 188, 21, 77, + 184, 193, 252, 42, 145, 113, 167, 72, 107, 200, 134, 45, 60, 216, + 199, 139, 199, 13, 178, 30, 228, 177, 64, 101, 188, 109, 2, 196, + 235, 68, 199, 136, 241, 4, 27, 166, 17, 138, 80, 1, 169, 42, + 226, 203, 180, 248, 84, 198, 13, 3, 172, 221, 95, 240, 34, 237, + 29, 124, 254, 137, 5, 136, 190, 225, 35, 154, 41, 233, 255, 201, + 189, 168, 22, 87, 143, 204, 152, 34, 10, 188, 76, 198, 132, 124, + 219, 146, 165, 11, 228, 147, 63, 47, 186, 205, 123, 95, 143, 224, + 6, 55, 218, 252, 244, 25, 107, 241, 105, 211, 24, 44, 128, 5, + 147, 147, 156, 33, 231, 214, 236, 202, 61, 98, 232, 65, 1, 113, + 200, 182, 109, 66, 124, 150, 187, 190, 23, 8, 80, 129, 57, 57, + 144, 143, 176, 139, 13, 220, 58, 228, 60, 137, 25, 120, 162, 253, + 5, 161, 8, 88, 3, 151, 107, 245, 179, 214, 191, 150, 146, 231, + 187, 5, 161, 111, 13, 10, 236, 242, 50, 42, 138, 33, 147, 79, + 26, 55, 208, 223, 251, 43, 7, 99, 17, 207, 255, 80, 28, 88, + 101, 76, 213, 216, 180, 185, 62, 155, 119, 137, 237, 122, 224, 9, + 122, 215, 49, 9, 71, 110, 128, 245, 204, 227, 3, 135, 144, 254, + 210, 156, 222, 227, 88, 144, 174, 63, 248, 178, 193, 37, 206, 245, + 111, 54, 200, 233, 88, 9, 57, 46, 26, 236, 233, 220, 171, 122, + 0, 81, 18, 82, 132, 126, 190, 50, 126, 57, 84, 67, 159, 145, + 202, 90, 91, 100, 253, 208, 246, 137, 225, 117, 54, 234, 73, 107, + 88, 224, 242, 132, 95, 62, 30, 234, 188, 199, 183, 58, 219, 189, + 138, 2, 3, 215, 71, 139, 106, 209, 146, 171, 206, 135, 117, 94, + 111, 184, 79, 11, 79, 198, 130, 165, 34, 63, 84, 115, 231, 253, + 255, 17, 85, 68, 131, 155, 171, 49, 7, 43, 156, 143, 139, 160, + 87, 142, 36, 63, 119, 138, 103, 180, 198, 246, 89, 192, 8, 25, + 192, 72, 168, 11, 217, 52, 240, 67, 185, 129, 114, 158, 66, 95, + 82, 165, 63, 205, 16, 255, 89, 248, 57, 195, 29, 127, 142, 202, + 192, 174, 50, 72, 42, 118, 51, 105, 143, 36, 199, 140, 119, 56, + 117, 112, 39, 105, 125, 170, 235, 40, 248, 160, 9, 17, 166, 209, + 121, 5, 191, 209, 48, 172, 137, 163, 33, 177, 114, 99, 200, 61, + 255, 154, 215, 70, 56, 164, 71, 112, 233, 239, 117, 216, 81, 189, + 212, 163, 232, 255, 28, 4, 68, 107, 54, 141, 98, 34, 81, 109, + 158, 100, 99, 245, 230, 137, 170, 184, 1, 83, 46, 200, 213, 137, + 229, 250, 138, 32, 245, 191, 130, 66, 174, 175, 80, 139, 207, 6, + 60, 87, 240, 4, 70, 48, 24, 170, 47, 205, 118, 153, 16, 226, + 87, 189, 85, 236, 90, 143, 79, 199, 32, 169, 110, 58, 20, 172, + 183, 96, 125, 107, 104, 160, 203, 0, 44, 247, 1, 182, 165, 187, + 253, 74, 60, 186, 84, 182, 178, 231, 225, 49, 188, 95, 44, 42, + 178, 105, 207, 19, 135, 182, 9, 168, 27, 248, 126, 18, 254, 193, + 120, 29, 216, 95, 172, 172, 189, 72, 240, 43, 21, 191, 243, 247, + 146, 65, 204, 151, 13, 106, 1, 156, 219, 1, 52, 119, 248, 189, + 229, 215, 225, 23, 10, 98, 217, 230, 35, 232, 91, 28, 0, 185, + 194, 26, 174, 236, 30, 161, 3, 25, 35, 146, 143, 163, 183, 81, + 57, 178, 7, 176, 166, 222, 139, 242, 24, 20, 20, 21, 247, 146, + 104, 119, 144, 66, 166, 144, 9, 143, 30, 233, 182, 106, 73, 151, + 85, 94, 65, 249, 221, 200, 189, 124, 237, 142, 70, 193, 189, 65, + 31, 89, 17, 89, 105, 79, 119, 136, 185, 201, 137, 197, 232, 64, + 95, 16, 79, 32, 167, 23, 206, 5, 217, 158, 78, 72, 50, 39, + 194, 149, 66, 207, 1, 141, 225, 180, 107, 105, 38, 0, 247, 231, + 234, 184, 125, 137, 146, 247, 18, 244, 216, 205, 95, 108, 48, 159, + 157, 97, 181, 253, 147, 18, 57, 119, 85, 35, 213, 105, 92, 246, + 69, 199, 135, 47, 220, 91, 124, 114, 229, 195, 43, 162, 17, 143, + 53, 157, 90, 107, 18, 86, 18, 223, 195, 75, 188, 95, 71, 178, + 10, 207, 254, 19, 85, 111, 215, 148, 221, 63, 203, 28, 162, 57, + 220, 179, 20, 134, 104, 131, 86, 89, 144, 13, 102, 250, 198, 193, + 27, 201, 26, 229, 40, 136, 162, 111, 224, 162, 118, 104, 135, 11, + 225, 62, 181, 240, 115, 125, 183, 219, 211, 101, 125, 136, 111, 235, + 186, 131, 99, 220, 237, 238, 189, 170, 201, 28, 199, 132, 42, 108, + 204, 76, 54, 182, 199, 11, 99, 25, 114, 148, 71, 214, 66, 129, + 172, 78, 29, 112, 156, 41, 201, 251, 169, 130, 255, 61, 151, 41, + 115, 8, 32, 65, 152, 164, 50, 141, 193, 19, 100, 197, 7, 109, + 140, 68, 66, 165, 52, 205, 45, 34, 39, 184, 56, 206, 26, 231, + 31, 40, 158, 136, 115, 155, 187, 185, 98, 169, 160, 164, 8, 221, + 135, 21, 181, 210, 214, 214, 239, 251, 214, 28, 232, 253, 178, 165, + 23, 75, 91, 205, 89, 42, 135, 183, 113, 220, 54, 50, 137, 228, + 56, 153, 210, 152, 5, 217, 39, 94, 89, 98, 106, 58, 134, 53, + 160, 218, 200, 131, 250, 172, 210, 27, 14, 240, 163, 162, 222, 13, + 60, 251, 43, 186, 241, 108, 84, 168, 224, 213, 50, 49, 190, 132, + 103, 82, 20, 82, 35, 69, 241, 196, 12, 2, 102, 219, 167, 192, + 114, 190, 136, 8, 14, 146, 198, 157, 238, 195, 18, 134, 146, 84, + 108, 86, 181, 93, 73, 188, 47, 234, 118, 89, 101, 73, 223, 180, + 67, 69, 114, 113, 252, 231, 200, 171, 112, 87, 243, 41, 173, 252, + 17, 58, 238, 224, 68, 157, 209, 186, 96, 64, 217, 124, 159, 58, + 233, 126, 172, 42, 210, 94, 10, 152, 39, 154, 31, 168, 213, 69, + 104, 164, 154, 50, 211, 125, 146, 96, 207, 186, 127, 101, 69, 191, + 164, 139, 0, 88, 204, 105, 255, 138, 75, 157, 159, 249, 19, 194, + 171, 80, 139, 155, 99, 145, 236, 99, 22, 118, 171, 172, 179, 13, + 25, 232, 224, 55, 228, 11, 66, 128, 39, 38, 166, 137, 210, 13, + 17, 220, 179, 231, 243, 45, 216, 234, 69, 4, 3, 139, 10, 201, + 12, 18, 169, 183, 64, 58, 129, 63, 70, 214, 6, 45, 236, 198, + 38, 87, 155, 163, 106, 150, 89, 109, 18, 133, 174, 180, 149, 173, + 41, 201, 149, 74, 63, 254, 72, 27, 146, 4, 183, 244, 12, 116, + 36, 40, 12, 88, 246, 115, 30, 206, 160, 48, 127, 7, 221, 77, + 217, 173, 225, 66, 40, 63, 6, 21, 81, 199, 19, 72, 21, 178, + 169, 134, 162, 163, 250, 60, 189, 109, 73, 158, 212, 5, 115, 198, + 32, 226, 12, 177, 25, 222, 237, 244, 109, 10, 160, 227, 64, 230, + 189, 82, 198, 226, 169, 96, 38, 181, 87, 23, 141, 63, 3, 100, + 211, 201, 113, 45, 31, 102, 120, 197, 26, 189, 238, 96, 12, 211, + 38, 175, 169, 167, 158, 49, 170, 177, 19, 107, 21, 81, 12, 2, + 2, 185, 168, 190, 10, 250, 69, 154, 101, 188, 64, 223, 41, 64, + 139, 114, 58, 198, 216, 53, 44, 201, 255, 91, 80, 159, 110, 139, + 16, 242, 18, 144, 35, 138, 168, 131, 92, 223, 75, 44, 32, 226, + 130, 229, 22, 45, 200, 145, 237, 85, 101, 153, 97, 134, 66, 70, + 156, 214, 9, 199, 196, 69, 75, 86, 209, 214, 202, 210, 34, 242, + 183, 132, 228, 130, 47, 83, 75, 45, 61, 102, 67, 96, 227, 180, + 213, 166, 151, 211, 136, 132, 83, 125, 74, 160, 102, 179, 125, 210, + 35, 140, 187, 73, 7, 79, 78, 175, 187, 110, 173, 198, 128, 143, + 54, 165, 36, 119, 188, 15, 179, 92, 240, 39, 125, 164, 38, 213, + 9, 173, 46, 107, 128, 124, 33, 25, 175, 194, 39, 241, 183, 49, + 202, 127, 252, 61, 46, 119, 228, 242, 200, 1, 10, 242, 114, 80, + 114, 135, 9, 216, 57, 222, 109, 89, 69, 229, 163, 40, 206, 74, + 197, 165, 108, 133, 157, 65, 165, 209, 36, 177, 27, 18, 90, 119, + 76, 182, 226, 96, 77, 2, 149, 216, 163, 117, 127, 184, 28, 81, + 146, 167, 213, 36, 117, 131, 144, 98, 1, 53, 65, 146, 102, 15, + 160, 56, 31, 169, 3, 107, 219, 21, 10, 68, 159, 11, 208, 104, + 221, 158, 107, 138, 213, 2, 85, 71, 62, 225, 151, 134, 138, 250, + 121, 229, 85, 122, 0, 123, 91, 234, 15, 228, 209, 195, 153, 39, + 192, 3, 184, 225, 30, 31, 217, 127, 196, 97, 64, 147, 7, 64, + 227, 139, 49, 37, 173, 206, 28, 199, 171, 76, 171, 15, 41, 151, + 197, 241, 22, 223, 150, 172, 140, 54, 145, 79, 94, 200, 145, 99, + 61, 194, 34, 26, 130, 4, 149, 191, 60, 105, 239, 24, 80, 155, + 194, 48, 167, 194, 56, 187, 72, 110, 77, 47, 7, 190, 13, 84, + 240, 40, 146, 21, 217, 102, 88, 163, 156, 229, 202, 117, 30, 7, + 75, 178, 190, 183, 26, 11, 106, 19, 120, 40, 183, 45, 36, 164, + 124, 103, 48, 146, 61, 145, 88, 230, 103, 61, 95, 38, 93, 7, + 4, 185, 101, 81, 180, 244, 54, 106, 192, 162, 117, 78, 131, 242, + 104, 36, 0, 88, 220, 111, 56, 80, 235, 28, 224, 221, 206, 124, + 66, 4, 207, 217, 161, 109, 145, 225, 174, 61, 78, 44, 243, 216, + 169, 195, 182, 142, 129, 169, 149, 151, 156, 52, 119, 103, 119, 85, + 50, 199, 40, 26, 76, 190, 23, 35, 203, 50, 74, 48, 251, 178, + 133, 175, 106, 235, 164, 208, 52, 145, 215, 161, 75, 177, 47, 176, + 142, 35, 224, 149, 171, 142, 181, 170, 94, 81, 25, 130, 234, 172, + 40, 130, 166, 149, 20, 163, 89, 26, 126, 109, 66, 70, 20, 15, + 190, 202, 72, 86, 147, 239, 210, 171, 66, 168, 226, 8, 99, 145, + 98, 22, 173, 70, 162, 157, 81, 216, 219, 215, 44, 128, 133, 24, + 134, 122, 36, 45, 167, 73, 71, 208, 55, 89, 247, 104, 10, 55, + 129, 40, 21, 18, 19, 208, 16, 88, 19, 87, 87, 235, 112, 142, + 234, 65, 50, 154, 39, 100, 7, 214, 111, 233, 159, 73, 36, 11, + 217, 90, 89, 123, 60, 77, 114, 201, 46, 226, 255, 105, 136, 246, + 15, 255, 140, 149, 200, 224, 131, 22, 216, 127, 9, 227, 83, 155, + 197, 81, 67, 99, 153, 111, 28, 243, 143, 144, 230, 56, 121, 198, + 255, 201, 99, 9, 192, 83, 49, 204, 15, 205, 21, 183, 12, 93, + 73, 109, 224, 128, 170, 235, 135, 127, 64, 12, 87, 33, 246, 65, + 190, 201, 123, 104, 39, 193, 211, 231, 68, 133, 174, 183, 241, 152, + 246, 41, 161, 2, 196, 131, 36, 238, 117, 196, 218, 14, 67, 222, + 85, 6, 33, 87, 206, 215, 141, 19, 138, 21, 167, 225, 239, 16, + 242, 41, 230, 207, 163, 131, 170, 47, 208, 129, 155, 230, 90, 67, + 9, 14, 239, 93, 112, 3, 123, 89, 234, 116, 98, 238, 46, 240, + 229, 154, 210, 48, 241, 70, 118, 69, 138, 229, 41, 89, 157, 171, + 202, 78, 198, 226, 112, 193, 212, 132, 135, 172, 137, 26, 206, 33, + 110, 42, 55, 218, 120, 190, 119, 211, 218, 248, 241, 13, 81, 157, + 134, 129, 124, 109, 218, 107, 55, 141, 193, 111, 121, 145, 62, 195, + 241, 45, 81, 112, 124, 162, 153, 25, 56, 146, 204, 76, 188, 167, + 253, 245, 16, 248, 20, 186, 56, 188, 221, 86, 78, 113, 116, 93, + 113, 60, 185, 142, 254, 94, 218, 184, 190, 219, 35, 248, 73, 247, + 150, 216, 109, 173, 41, 69, 224, 231, 182, 156, 108, 78, 14, 219, + 248, 188, 4, 216, 221, 45, 29, 128, 97, 81, 9, 84, 9, 115, + 118, 34, 132, 136, 126, 203, 243, 150, 238, 194, 195, 112, 122, 44, + 195, 102, 208, 21, 144, 49, 37, 236, 219, 166, 56, 93, 34, 167, + 86, 183, 78, 157, 25, 128, 169, 131, 17, 122, 70, 137, 102, 197, + 113, 76, 227, 144, 92, 89, 148, 177, 76, 25, 104, 164, 247, 163, + 140, 75, 70, 111, 200, 122, 25, 151, 184, 156, 237, 23, 223, 21, + 20, 91, 66, 31, 247, 18, 167, 22, 6, 190, 192, 119, 17, 218, + 188, 177, 201, 0, 81, 34, 89, 206, 166, 113, 7, 222, 212, 106, + 36, 255, 240, 245, 18, 28, 124, 191, 213, 205, 240, 15, 194, 39, + 157, 53, 87, 163, 118, 96, 226, 84, 20, 165, 19, 151, 47, 214, + 157, 162, 85, 65, 15, 37, 97, 185, 62, 194, 62, 6, 249, 139, + 74, 158, 198, 194, 170, 94, 255, 104, 170, 169, 26, 80, 226, 248, + 254, 29, 35, 141, 42, 33, 148, 114, 219, 47, 193, 3, 214, 226, + 190, 242, 9, 48, 6, 98, 209, 153, 201, 138, 191, 173, 67, 23, + 161, 80, 33, 137, 222, 158, 19, 251, 170, 6, 94, 105, 215, 149, + 19, 46, 52, 135, 117, 16, 150, 141, 152, 215, 178, 99, 73, 181, + 96, 85, 229, 109, 49, 236, 69, 204, 207, 133, 43, 187, 67, 95, + 194, 253, 208, 156, 151, 204, 82, 11, 243, 147, 219, 187, 76, 87, + 73, 148, 43, 122, 7, 89, 28, 236, 208, 33, 179, 134, 211, 49, + 255, 115, 227, 246, 227, 77, 106, 106, 250, 22, 9, 79, 46, 110, + 245, 69, 158, 156, 116, 206, 248, 77, 230, 38, 166, 161, 75, 116, + 69, 203, 67, 221, 39, 130, 227, 196, 135, 56, 174, 228, 43, 12, + 243, 74, 106, 32, 51, 181, 151, 132, 216, 1, 92, 165, 237, 190, + 215, 85, 66, 188, 81, 41, 10, 240, 168, 127, 97, 129, 49, 29, + 55, 15, 131, 43, 41, 182, 134, 66, 73, 46, 129, 98, 92, 197, + 190, 110, 26, 100, 210, 110, 75, 119, 224, 74, 169, 104, 194, 198, + 54, 26, 33, 117, 98, 205, 230, 205, 189, 172, 29, 76, 65, 236, + 230, 12, 122, 61, 37, 57, 83, 27, 113, 182, 98, 215, 99, 148, + 23, 222, 103, 119, 151, 143, 227, 190, 71, 124, 229, 225, 18, 223, + 170, 166, 128, 142, 23, 235, 48, 227, 190, 35, 48, 156, 42, 144, + 241, 244, 56, 133, 190, 26, 223, 217, 241, 70, 212, 128, 4, 48, + 136, 180, 39, 203, 204, 44, 120, 144, 144, 69, 137, 218, 63, 120, + 152, 17, 9, 110, 3, 138, 230, 51, 9, 112, 243, 249, 24, 223, + 155, 188, 147, 172, 8, 101, 226, 140, 37, 210, 219, 238, 69, 33, + 246, 78, 206, 197, 200, 104, 112, 57, 160, 212, 53, 103, 246, 113, + 253, 97, 216, 46, 221, 44, 49, 100, 33, 90, 139, 254, 212, 252, + 22, 44, 66, 142, 62, 222, 216, 51, 13, 150, 169, 24, 184, 36, + 61, 153, 63, 225, 233, 95, 133, 247, 17, 112, 43, 234, 25, 208, + 144, 67, 65, 221, 236, 127, 191, 153, 118, 247, 121, 204, 223, 46, + 2, 192, 135, 145, 206, 253, 148, 240, 46, 7, 147, 7, 207, 200, + 108, 154, 202, 36, 113, 46, 178, 97, 206, 129, 194, 30, 171, 75, + 66, 202, 232, 48, 226, 57, 1, 18, 95, 206, 90, 174, 222, 48, + 10, 116, 249, 72, 129, 174, 222, 11, 173, 242, 13, 179, 113, 20, + 116, 205, 99, 211, 95, 234, 25, 85, 192, 14, 186, 110, 108, 177, + 126, 245, 122, 158, 156, 58, 232, 120, 244, 32, 211, 44, 7, 34, + 66, 93, 48, 119, 140, 168, 14, 218, 79, 84, 218, 167, 132, 21, + 95, 108, 131, 86, 156, 71, 187, 249, 132, 79, 223, 122, 90, 54, + 28, 53, 221, 24, 36, 169, 30, 120, 4, 17, 48, 219, 167, 222, + 251, 139, 86, 85, 35, 118, 108, 46, 125, 28, 43, 220, 208, 9, + 68, 95, 217, 38, 160, 170, 248, 97, 118, 117, 9, 217, 61, 236, + 136, 104, 246, 129, 177, 36, 136, 162, 139, 71, 110, 111, 236, 255, + 239, 7, 76, 29, 111, 202, 88, 205, 158, 50, 22, 74, 151, 240, + 109, 129, 12, 6, 84, 58, 83, 226, 213, 118, 16, 66, 194, 49, + 44, 136, 188, 247, 117, 113, 137, 204, 148, 188, 201, 206, 130, 91, + 3, 72, 190, 113, 102, 165, 172, 95, 189, 141, 41, 120, 176, 131, + 232, 182, 11, 62, 57, 62, 30, 40, 157, 209, 193, 236, 148, 58, + 32, 241, 29, 199, 1, 193, 156, 26, 166, 137, 186, 127, 42, 139, + 211, 10, 60, 98, 235, 183, 1, 71, 18, 45, 254, 96, 164, 69, + 214, 40, 193, 232, 214, 252, 244, 221, 169, 40, 153, 120, 210, 42, + 183, 71, 9, 183, 57, 167, 45, 27, 215, 0, 99, 142, 170, 243, + 152, 164, 6, 174, 33, 246, 10, 101, 69, 54, 46, 176, 23, 74, + 184, 210, 91, 228, 5, 190, 100, 99, 142, 165, 191, 41, 40, 52, + 89, 2, 86, 15, 227, 129, 57, 214, 21, 105, 12, 167, 219, 200, + 66, 205, 21, 111, 71, 145, 148, 143, 202, 245, 114, 123, 194, 165, + 128, 244, 119, 208, 156, 242, 104, 71, 149, 185, 135, 178, 120, 19, + 74, 117, 107, 82, 227, 157, 137, 140, 78, 43, 128, 155, 236, 160, + 110, 90, 75, 252, 130, 179, 156, 79, 39, 180, 205, 223, 197, 219, + 84, 250, 123, 167, 149, 14, 92, 159, 145, 82, 139, 123, 17, 97, + 141, 118, 129, 219, 82, 209, 13, 115, 210, 241, 143, 35, 55, 72, + 88, 29, 69, 162, 79, 88, 97, 88, 181, 14, 227, 27, 40, 69, + 245, 79, 6, 41, 222, 85, 239, 202, 117, 100, 162, 19, 230, 125, + 232, 80, 75, 91, 10, 9, 120, 245, 92, 77, 9, 129, 240, 216, + 55, 224, 106, 88, 36, 221, 67, 113, 37, 55, 98, 244, 253, 44, + 105, 10, 54, 101, 29, 156, 182, 6, 109, 218, 178, 130, 156, 5, + 120, 242, 12, 200, 101, 153, 72, 181, 70, 218, 198, 243, 6, 152, + 132, 38, 45, 204, 170, 229, 193, 169, 206, 117, 189, 126, 115, 72, + 82, 185, 38, 47, 148, 242, 241, 34, 70, 142, 144, 53, 113, 234, + 176, 209, 170, 177, 36, 101, 205, 20, 24, 33, 183, 165, 174, 51, + 76, 50, 133, 228, 33, 96, 100, 46, 107, 110, 105, 202, 56, 217, + 44, 187, 149, 8, 231, 153, 98, 48, 224, 236, 15, 254, 222, 230, + 179, 183, 184, 74, 153, 244, 74, 140, 67, 73, 77, 73, 55, 30, + 195, 95, 35, 117, 192, 201, 248, 202, 94, 134, 61, 172, 208, 53, + 225, 181, 202, 72, 144, 152, 206, 61, 179, 110, 156, 135, 2, 253, + 16, 58, 195, 44, 127, 208, 204, 255, 1, 145, 204, 139, 156, 221, + 110, 126, 84, 127, 103, 196, 9, 164, 154, 250, 191, 217, 94, 211, + 251, 175, 21, 2, 69, 86, 232, 133, 56, 73, 191, 129, 55, 156, + 32, 98, 238, 197, 130, 228, 9, 151, 219, 73, 70, 247, 1, 100, + 239, 60, 171, 251, 204, 12, 166, 137, 143, 35, 26, 55, 27, 54, + 206, 62, 8, 107, 10, 23, 248, 174, 85, 245, 38, 170, 188, 207, + 22, 213, 64, 192, 45, 21, 38, 218, 125, 162, 156, 63, 20, 97, + 239, 114, 239, 33, 148, 164, 144, 145, 182, 163, 4, 128, 139, 188, + 26, 140, 79, 190, 253, 170, 223, 115, 220, 119, 68, 230, 26, 206, + 16, 41, 58, 161, 44, 144, 156, 111, 69, 199, 211, 193, 151, 12, + 154, 177, 135, 247, 163, 10, 191, 248, 65, 87, 49, 198, 168, 197, + 210, 209, 80, 81, 248, 200, 120, 166, 185, 237, 95, 58, 34, 169, + 125, 149, 131, 181, 165, 43, 234, 51, 110, 62, 38, 211, 160, 123, + 39, 255, 110, 119, 66, 131, 22, 159, 240, 70, 31, 32, 238, 125, + 241, 222, 128, 127, 232, 114, 209, 149, 75, 88, 98, 18, 227, 243, + 187, 174, 52, 26, 179, 125, 49, 9, 221, 79, 79, 180, 234, 31, + 98, 202, 19, 91, 208, 174, 199, 119, 116, 57, 64, 128, 67, 188, + 139, 154, 55, 241, 142, 186, 77, 206, 166, 198, 82, 28, 209, 239, + 216, 23, 53, 21, 178, 101, 247, 61, 11, 80, 248, 67, 159, 65, + 194, 12, 30, 83, 23, 100, 134, 246, 243, 214, 144, 253, 109, 179, + 106, 186, 208, 254, 189, 100, 205, 69, 121, 67, 205, 242, 213, 245, + 53, 235, 119, 180, 222, 35, 34, 193, 100, 151, 55, 124, 199, 62, + 208, 117, 199, 3, 121, 215, 39, 170, 63, 97, 120, 4, 43, 143, + 99, 32, 156, 227, 137, 234, 161, 118, 2, 114, 68, 2, 146, 122, + 81, 216, 249, 207, 92, 243, 63, 250, 206, 200, 242, 29, 75, 179, + 45, 126, 111, 202, 88, 24, 27, 126, 62, 96, 55, 59, 20, 8, + 124, 195, 88, 142, 30, 24, 182, 52, 105, 221, 244, 33, 1, 74, + 53, 46, 47, 24, 85, 64, 188, 1, 167, 16, 199, 94, 251, 234, + 92, 101, 4, 137, 13, 28, 91, 153, 230, 213, 65, 102, 180, 63, + 186, 39, 240, 147, 99, 171, 102, 11, 150, 16, 107, 111, 32, 241, + 110, 229, 113, 25, 94, 76, 8, 120, 39, 134, 195, 26, 195, 158, + 120, 168, 255, 139, 191, 174, 217, 82, 61, 77, 238, 42, 243, 137, + 205, 220, 45, 162, 22, 160, 198, 221, 83, 195, 251, 97, 245, 253, + 125, 27, 226, 234, 69, 32, 57, 115, 186, 92, 17, 99, 202, 46, + 27, 176, 184, 172, 84, 217, 63, 43, 221, 110, 62, 248, 185, 219, + 45, 250, 137, 74, 188, 168, 92, 225, 2, 143, 159, 15, 132, 64, + 187, 219, 169, 119, 100, 154, 4, 38, 12, 184, 248, 38, 197, 35, + 86, 136, 110, 246, 107, 119, 20, 135, 43, 181, 36, 195, 180, 147, + 81, 239, 219, 171, 154, 163, 225, 25, 9, 243, 255, 202, 130, 39, + 140, 65, 211, 201, 144, 201, 115, 70, 34, 15, 166, 118, 151, 113, + 230, 170, 152, 66, 72, 90, 40, 71, 82, 125, 235, 31, 148, 156, + 155, 168, 157, 173, 12, 240, 123, 97, 99, 147, 123, 74, 107, 48, + 167, 57, 93, 40, 223, 176, 254, 72, 189, 31, 183, 139, 150, 105, + 139, 7, 96, 207, 124, 124, 226, 226, 123, 29, 165, 0, 171, 172, + 38, 21, 189, 209, 82, 171, 177, 208, 91, 159, 55, 231, 201, 255, + 64, 188, 92, 158, 243, 154, 158, 94, 90, 13, 89, 76, 224, 96, + 240, 251, 176, 76, 197, 202, 234, 68, 194, 82, 205, 231, 73, 246, + 195, 155, 217, 28, 114, 78, 173, 70, 75, 153, 247, 38, 40, 106, + 71, 236, 71, 246, 153, 179, 136, 166, 175, 92, 154, 69, 61, 87, + 174, 98, 174, 133, 45, 172, 103, 103, 104, 155, 197, 73, 172, 220, + 205, 133, 233, 171, 99, 41, 231, 41, 118, 235, 107, 185, 60, 220, + 102, 198, 180, 1, 78, 72, 62, 214, 133, 114, 9, 16, 200, 207, + 143, 47, 146, 8, 237, 174, 42, 139, 50, 119, 7, 180, 2, 66, + 11, 129, 252, 115, 122, 8, 107, 138, 90, 186, 37, 32, 30, 63, + 234, 41, 102, 255, 87, 120, 148, 51, 52, 252, 59, 202, 33, 192, + 195, 23, 30, 180, 184, 131, 147, 211, 67, 177, 222, 156, 114, 49, + 121, 61, 56, 50, 108, 26, 209, 5, 218, 175, 153, 127, 113, 182, + 184, 97, 119, 187, 52, 202, 224, 50, 227, 47, 42, 199, 128, 206, + 234, 49, 105, 55, 143, 26, 56, 146, 209, 161, 145, 114, 55, 120, + 163, 119, 196, 197, 123, 56, 131, 85, 180, 253, 223, 12, 28, 232, + 62, 78, 28, 14, 135, 63, 132, 79, 199, 211, 31, 45, 120, 13, + 94, 24, 240, 217, 36, 30, 122, 245, 173, 16, 131, 214, 40, 86, + 70, 160, 100, 44, 43, 69, 187, 156, 169, 157, 224, 53, 127, 120, + 118, 26, 137, 83, 66, 210, 110, 73, 80, 181, 205, 236, 182, 168, + 234, 156, 191, 108, 249, 252, 115, 233, 207, 180, 212, 214, 68, 191, + 124, 180, 213, 101, 172, 124, 127, 247, 107, 38, 10, 98, 179, 102, + 244, 73, 147, 112, 39, 39, 11, 161, 232, 210, 50, 150, 250, 239, + 183, 109, 153, 11, 245, 165, 249, 147, 154, 41, 251, 130, 141, 203, + 22, 43, 172, 75, 33, 25, 159, 185, 240, 77, 128, 66, 171, 107, + 219, 80, 227, 23, 145, 204, 57, 40, 195, 8, 54, 175, 158, 73, + 226, 156, 4, 197, 243, 53, 50, 50, 234, 238, 184, 79, 177, 155, + 60, 112, 215, 94, 26, 104, 254, 140, 81, 177, 111, 82, 160, 121, + 147, 168, 88, 156, 231, 250, 125, 69, 78, 30, 239, 147, 233, 182, + 99, 101, 131, 215, 106, 135, 192, 187, 236, 244, 197, 176, 189, 110, + 12, 37, 77, 242, 176, 65, 99, 226, 11, 218, 166, 141, 166, 1, + 214, 33, 211, 201, 111, 78, 19, 232, 237, 53, 178, 225, 92, 241, + 168, 148, 149, 251, 135, 173, 248, 53, 52, 154, 159, 26, 104, 254, + 140, 81, 177, 106, 64, 40, 77, 63, 134, 224, 172, 59, 244, 128, + 104, 220, 126, 231, 167, 21, 34, 50, 205, 10, 5, 121, 96, 211, + 162, 25, 255, 42, 7, 241, 222, 65, 149, 237, 105, 220, 206, 226, + 67, 137, 200, 167, 101, 168, 176, 61, 129, 35, 70, 114, 226, 16, + 33, 188, 155, 0, 141, 111, 254, 58, 123, 89, 133, 10, 19, 149, + 144, 67, 65, 221, 236, 80, 134, 242, 56, 60, 159, 162, 22, 52, + 92, 170, 63, 188, 148, 126, 192, 233, 248, 149, 58, 7, 64, 240, + 167, 248, 247, 223, 16, 43, 121, 20, 173, 227, 19, 5, 220, 116, + 233, 4, 159, 120, 26, 107, 74, 198, 237, 162, 162, 229, 231, 224, + 4, 152, 14, 166, 193, 83, 129, 133, 61, 1, 24, 111, 67, 95, + 160, 220, 145, 13, 37, 111, 101, 153, 174, 139, 111, 251, 182, 40, + 14, 45, 30, 16, 191, 213, 105, 224, 134, 14, 187, 95, 206, 15, + 20, 39, 168, 55, 128, 200, 65, 138, 2, 229, 76, 37, 123, 229, + 119, 176, 159, 105, 40, 111, 146, 87, 117, 140, 25, 135, 6, 233, + 133, 154, 180, 18, 13, 235, 12, 125, 151, 185, 0, 185, 196, 7, + 0, 181, 174, 87, 210, 56, 91, 107, 82, 143, 225, 75, 178, 81, + 97, 42, 31, 38, 246, 132, 48, 187, 91, 71, 81, 81, 29, 38, + 254, 166, 161, 96, 157, 191, 179, 248, 99, 249, 62, 163, 219, 100, + 226, 197, 59, 8, 63, 119, 77, 16, 1, 148, 250, 203, 71, 218, + 212, 25, 65, 141, 161, 204, 94, 100, 182, 220, 224, 31, 223, 157, + 43, 127, 48, 58, 199, 223, 206, 226, 97, 111, 64, 122, 63, 100, + 46, 123, 149, 91, 125, 126, 118, 112, 84, 182, 182, 112, 243, 245, + 239, 246, 180, 3, 19, 34, 214, 65, 158, 136, 201, 97, 62, 135, + 149, 199, 177, 174, 176, 125, 247, 16, 197, 84, 93, 81, 16, 202, + 11, 23, 192, 78, 69, 181, 220, 21, 174, 204, 113, 59, 141, 82, + 230, 5, 46, 145, 108, 81, 119, 48, 154, 151, 199, 113, 227, 248, + 148, 38, 94, 142, 139, 190, 120, 128, 205, 116, 247, 219, 88, 215, + 15, 92, 165, 237, 153, 40, 68, 223, 73, 248, 218, 135, 171, 61, + 128, 9, 22, 12, 121, 125, 241, 58, 174, 65, 48, 185, 83, 10, + 164, 185, 225, 48, 196, 144, 118, 107, 25, 77, 223, 49, 161, 195, + 182, 90, 190, 154, 85, 136, 223, 30, 113, 226, 124, 168, 107, 50, + 62, 178, 85, 68, 104, 185, 48, 207, 10, 181, 104, 37, 223, 52, + 11, 196, 82, 229, 51, 109, 188, 42, 113, 97, 245, 183, 222, 65, + 222, 49, 187, 9, 102, 25, 174, 74, 80, 235, 192, 182, 141, 118, + 186, 137, 213, 200, 179, 190, 248, 29, 99, 94, 177, 204, 72, 248, + 170, 69, 133, 35, 76, 251, 2, 29, 52, 157, 59, 239, 253, 136, + 28, 13, 73, 144, 255, 94, 143, 222, 37, 86, 88, 70, 107, 231, + 163, 199, 228, 136, 211, 244, 198, 131, 9, 107, 220, 212, 12, 255, + 121, 181, 131, 12, 70, 188, 196, 136, 106, 17, 197, 206, 116, 192, + 167, 105, 3, 11, 168, 77, 138, 234, 126, 94, 85, 222, 247, 55, + 47, 216, 250, 202, 90, 40, 243, 56, 101, 190, 101, 147, 156, 208, + 127, 210, 85, 95, 43, 89, 118, 238, 57, 155, 171, 16, 211, 170, + 129, 27, 110, 178, 70, 199, 48, 130, 183, 218, 37, 134, 13, 216, + 8, 184, 81, 181, 72, 20, 64, 140, 150, 89, 62, 117, 146, 52, + 187, 196, 59, 149, 24, 5, 236, 105, 47, 226, 170, 114, 27, 37, + 195, 106, 111, 196, 112, 50, 68, 157, 136, 61, 50, 125, 38, 240, + 231, 181, 244, 143, 6, 68, 1, 162, 99, 249, 171, 112, 4, 250, + 105, 110, 92, 237, 170, 173, 85, 99, 50, 226, 247, 41, 78, 48, + 64, 192, 28, 50, 88, 215, 238, 109, 76, 179, 140, 173, 77, 78, + 247, 254, 220, 221, 169, 44, 57, 67, 183, 48, 84, 184, 216, 239, + 181, 185, 67, 69, 240, 209, 137, 140, 235, 162, 58, 243, 12, 233, + 221, 183, 88, 118, 215, 21, 82, 91, 117, 65, 97, 89, 246, 249, + 51, 225, 20, 124, 103, 250, 87, 181, 111, 232, 247, 17, 92, 214, + 115, 162, 255, 38, 35, 226, 225, 122, 174, 170, 164, 189, 157, 150, + 50, 242, 239, 16, 44, 196, 10, 172, 236, 64, 158, 249, 12, 13, + 186, 29, 151, 43, 127, 208, 232, 79, 229, 108, 170, 178, 112, 252, + 238, 193, 85, 230, 179, 195, 147, 5, 109, 114, 32, 243, 109, 183, + 106, 161, 47, 165, 107, 207, 129, 60, 252, 249, 214, 144, 144, 145, + 199, 100, 96, 161, 38, 150, 71, 34, 209, 8, 215, 140, 185, 8, + 235, 228, 163, 10, 151, 44, 198, 27, 177, 222, 208, 31, 155, 218, + 83, 133, 235, 84, 95, 133, 94, 75, 68, 149, 2, 140, 178, 37, + 2, 7, 184, 159, 155, 245, 192, 155, 48, 3, 191, 125, 9, 243, + 57, 152, 5, 227, 225, 215, 241, 120, 210, 46, 210, 182, 64, 24, + 187, 176, 54, 41, 110, 23, 142, 247, 127, 2, 210, 206, 13, 230, + 249, 135, 36, 113, 165, 213, 139, 210, 40, 206, 14, 70, 99, 250, + 205, 151, 12, 237, 59, 64, 65, 226, 138, 126, 14, 78, 136, 143, + 129, 230, 142, 11, 7, 196, 38, 15, 29, 162, 243, 180, 38, 215, + 213, 192, 128, 34, 181, 209, 49, 117, 253, 87, 74, 227, 114, 149, + 211, 53, 154, 75, 2, 196, 187, 137, 2, 185, 42, 107, 83, 208, + 175, 88, 119, 227, 227, 254, 217, 90, 7, 140, 35, 122, 19, 149, + 31, 142, 87, 160, 46, 10, 149, 214, 19, 30, 242, 212, 192, 200, + 138, 204, 144, 231, 144, 227, 96, 51, 3, 52, 239, 116, 95, 168, + 226, 171, 84, 7, 85, 63, 57, 52, 5, 136, 96, 28, 176, 55, + 24, 191, 172, 173, 36, 73, 100, 143, 120, 206, 150, 131, 146, 211, + 133, 152, 218, 117, 114, 101, 0, 218, 240, 119, 235, 22, 77, 210, + 179, 214, 163, 85, 193, 61, 64, 176, 248, 202, 255, 177, 154, 145, + 202, 189, 124, 101, 170, 35, 241, 232, 4, 132, 139, 11, 177, 73, + 169, 99, 102, 204, 184, 35, 235, 234, 211, 89, 196, 99, 49, 27, + 143, 174, 227, 140, 106, 198, 30, 251, 231, 147, 72, 84, 29, 112, + 131, 19, 15, 239, 196, 133, 104, 218, 137, 247, 86, 126, 123, 220, + 113, 238, 120, 143, 238, 254, 212, 3, 102, 108, 31, 160, 110, 77, + 4, 73, 173, 133, 11, 145, 22, 158, 33, 186, 231, 144, 141, 10, + 188, 119, 141, 84, 74, 141, 201, 227, 232, 48, 130, 105, 177, 184, + 47, 72, 95, 208, 79, 176, 253, 229, 188, 11, 49, 19, 101, 161, + 200, 79, 77, 63, 193, 156, 118, 2, 103, 124, 216, 13, 54, 230, + 13, 103, 55, 235, 192, 131, 195, 70, 58, 123, 5, 120, 20, 159, + 63, 216, 1, 12, 86, 237, 146, 149, 146, 10, 236, 31, 156, 90, + 142, 188, 171, 86, 127, 222, 184, 135, 189, 97, 18, 59, 218, 172, + 4, 67, 210, 197, 132, 87, 116, 193, 98, 44, 214, 26, 168, 174, + 16, 99, 128, 90, 65, 120, 227, 64, 127, 236, 238, 192, 87, 191, + 73, 189, 26, 107, 50, 112, 206, 197, 213, 38, 90, 240, 82, 208, + 67, 81, 27, 116, 143, 222, 105, 3, 48, 56, 251, 162, 19, 105, + 108, 136, 160, 92, 212, 82, 140, 174, 188, 141, 81, 30, 98, 196, + 151, 148, 146, 62, 80, 67, 154, 211, 191, 133, 200, 160, 188, 73, + 39, 11, 123, 32, 181, 143, 104, 38, 4, 55, 214, 82, 129, 25, + 176, 78, 229, 0, 152, 101, 157, 169, 23, 8, 178, 88, 225, 250, + 82, 101, 253, 4, 225, 76, 163, 75, 123, 181, 147, 45, 131, 202, + 4, 42, 222, 158, 103, 63, 106, 150, 47, 191, 141, 34, 55, 145, + 20, 212, 60, 123, 72, 59, 153, 189, 227, 245, 64, 147, 218, 208, + 49, 126, 18, 86, 93, 162, 69, 137, 249, 111, 252, 92, 89, 26, + 49, 171, 172, 12, 22, 38, 161, 143, 28, 30, 239, 158, 106, 63, + 177, 179, 72, 181, 131, 58, 113, 179, 170, 66, 53, 162, 123, 239, + 74, 233, 220, 216, 191, 22, 245, 56, 120, 143, 189, 104, 150, 105, + 156, 216, 207, 172, 250, 84, 78, 180, 200, 132, 70, 73, 70, 195, + 228, 208, 81, 124, 69, 236, 28, 190, 68, 37, 249, 143, 91, 154, + 81, 99, 93, 222, 56, 162, 250, 99, 253, 2, 223, 22, 128, 4, + 248, 181, 236, 252, 42, 34, 45, 78, 199, 250, 207, 96, 250, 84, + 156, 170, 123, 236, 34, 208, 23, 199, 178, 17, 66, 95, 82, 226, + 34, 201, 128, 187, 168, 0, 4, 81, 218, 80, 113, 183, 11, 25, + 227, 202, 144, 64, 171, 67, 87, 246, 120, 100, 162, 18, 76, 178, + 251, 165, 87, 242, 95, 235, 63, 110, 102, 51, 185, 158, 88, 218, + 211, 9, 117, 83, 221, 236, 100, 211, 218, 39, 98, 254, 47, 64, + 247, 228, 162, 241, 67, 4, 91, 69, 149, 225, 15, 251, 250, 91, + 109, 221, 253, 10, 234, 25, 122, 232, 15, 58, 212, 11, 187, 176, + 176, 181, 127, 162, 165, 58, 108, 14, 74, 22, 173, 249, 164, 95, + 79, 70, 245, 138, 60, 184, 204, 73, 183, 86, 199, 28, 189, 245, + 94, 177, 195, 132, 208, 128, 112, 73, 151, 131, 80, 197, 61, 177, + 161, 120, 163, 54, 209, 36, 150, 213, 132, 123, 146, 254, 1, 37, + 199, 57, 57, 183, 170, 36, 92, 117, 150, 231, 1, 78, 82, 169, + 2, 177, 131, 177, 15, 135, 3, 163, 206, 166, 168, 97, 63, 161, + 11, 193, 126, 170, 86, 154, 117, 223, 135, 128, 25, 166, 200, 4, + 184, 236, 114, 21, 103, 238, 211, 252, 64, 64, 99, 189, 123, 219, + 35, 56, 172, 91, 57, 195, 60, 223, 128, 15, 246, 102, 154, 93, + 37, 41, 255, 89, 21, 91, 116, 255, 13, 118, 252, 124, 194, 210, + 128, 187, 60, 66, 58, 144, 9, 43, 185, 242, 216, 202, 238, 99, + 6, 51, 171, 62, 253, 172, 92, 209, 5, 54, 89, 217, 168, 219, + 212, 114, 43, 255, 180, 118, 218, 113, 122, 1, 225, 142, 191, 168, + 104, 74, 105, 92, 84, 109, 194, 222, 166, 69, 48, 49, 243, 159, + 239, 225, 179, 166, 154, 228, 244, 94, 15, 23, 1, 200, 77, 241, + 26, 100, 31, 104, 13, 191, 131, 248, 111, 108, 193, 74, 45, 239, + 201, 66, 128, 229, 133, 123, 198, 35, 132, 125, 61, 102, 242, 58, + 12, 248, 51, 126, 143, 175, 173, 50, 105, 192, 129, 16, 100, 35, + 165, 38, 95, 85, 210, 252, 93, 59, 170, 71, 230, 192, 138, 82, + 187, 1, 120, 54, 248, 169, 8, 122, 152, 150, 56, 163, 36, 157, + 199, 20, 234, 183, 130, 69, 200, 229, 45, 47, 54, 4, 64, 136, + 250, 190, 65, 223, 173, 38, 74, 227, 243, 164, 66, 153, 150, 236, + 83, 13, 44, 50, 38, 139, 140, 173, 9, 137, 254, 234, 95, 84, + 84, 204, 136, 68, 91, 244, 208, 129, 53, 128, 40, 189, 109, 110, + 163, 198, 247, 112, 10, 50, 78, 54, 107, 118, 120, 85, 241, 61, + 27, 31, 213, 36, 29, 136, 253, 250, 110, 94, 209, 165, 231, 229, + 105, 51, 22, 89, 70, 199, 156, 50, 74, 190, 116, 162, 74, 171, + 231, 210, 179, 109, 35, 61, 64, 249, 36, 220, 88, 206, 226, 38, + 213, 59, 4, 247, 240, 53, 100, 210, 199, 175, 159, 253, 89, 173, + 199, 127, 44, 210, 115, 107, 86, 8, 151, 219, 27, 240, 239, 143, + 200, 58, 165, 189, 59, 255, 164, 206, 137, 184, 243, 217, 208, 125, + 162, 160, 224, 143, 215, 101, 208, 61, 5, 151, 5, 107, 189, 114, + 61, 1, 15, 207, 37, 26, 218, 182, 61, 93, 163, 75, 231, 202, + 52, 126, 32, 214, 152, 225, 87, 166, 14, 175, 157, 218, 245, 62, + 80, 62, 143, 20, 145, 243, 253, 94, 81, 165, 247, 95, 176, 69, + 182, 217, 194, 238, 119, 84, 162, 67, 68, 110, 81, 99, 215, 91, + 202, 185, 91, 79, 222, 175, 203, 133, 86, 13, 29, 5, 209, 118, + 53, 102, 198, 122, 75, 56, 12, 43, 70, 101, 22, 169, 67, 251, + 74, 162, 12, 54, 244, 227, 132, 13, 189, 66, 4, 124, 171, 135, + 174, 119, 110, 113, 136, 107, 131, 132, 126, 159, 67, 146, 209, 185, + 59, 27, 142, 236, 172, 126, 83, 147, 39, 115, 99, 205, 16, 159, + 224, 65, 60, 90, 119, 70, 253, 42, 180, 88, 190, 203, 79, 71, + 129, 57, 105, 173, 7, 135, 198, 32, 54, 211, 112, 127, 163, 195, + 76, 65, 208, 42, 171, 167, 189, 55, 130, 134, 38, 85, 5, 50, + 2, 239, 177, 16, 115, 81, 100, 147, 102, 147, 18, 138, 116, 58, + 250, 14, 137, 28, 237, 204, 120, 10, 55, 254, 158, 73, 224, 245, + 90, 225, 126, 190, 78, 181, 222, 39, 176, 20, 68, 186, 218, 123, + 146, 101, 19, 197, 39, 206, 197, 55, 114, 74, 175, 76, 52, 117, + 160, 229, 219, 236, 75, 243, 255, 97, 233, 74, 218, 181, 214, 163, + 159, 26, 237, 150, 123, 202, 255, 206, 96, 31, 161, 168, 187, 215, + 124, 117, 154, 97, 102, 41, 43, 212, 241, 9, 204, 157, 163, 46, + 104, 250, 240, 58, 235, 41, 43, 191, 189, 31, 182, 77, 177, 122, + 84, 207, 212, 143, 255, 53, 84, 90, 90, 194, 34, 99, 44, 215, + 222, 129, 60, 120, 131, 132, 164, 52, 143, 104, 86, 92, 240, 159, + 8, 171, 164, 59, 169, 199, 72, 192, 60, 27, 202, 82, 117, 145, + 35, 77, 12, 167, 165, 165, 242, 156, 59, 102, 4, 71, 55, 181, + 175, 209, 195, 225, 135, 245, 254, 100, 117, 213, 111, 184, 196, 241, + 124, 136, 204, 48, 119, 102, 24, 154, 34, 252, 82, 150, 83, 43, + 156, 212, 56, 217, 4, 41, 183, 162, 63, 50, 78, 129, 73, 77, + 143, 232, 72, 223, 153, 155, 157, 104, 140, 249, 69, 62, 89, 118, + 111, 66, 93, 169, 12, 108, 159, 43, 11, 13, 203, 251, 244, 214, + 145, 186, 42, 3, 172, 38, 242, 201, 96, 64, 187, 68, 181, 62, + 35, 192, 254, 90, 227, 71, 51, 254, 76, 200, 245, 222, 161, 170, + 164, 9, 204, 121, 187, 45, 185, 236, 95, 101, 214, 194, 236, 175, + 100, 247, 113, 33, 50, 243, 169, 5, 150, 217, 109, 91, 157, 92, + 30, 242, 69, 9, 109, 193, 98, 155, 107, 179, 101, 57, 132, 125, + 209, 60, 114, 136, 57, 208, 212, 95, 228, 214, 150, 181, 180, 159, + 201, 222, 135, 100, 230, 121, 0, 97, 56, 137, 10, 72, 31, 198, + 114, 149, 40, 182, 248, 95, 233, 215, 88, 15, 201, 130, 220, 58, + 31, 64, 203, 238, 112, 18, 47, 136, 222, 236, 38, 13, 199, 153, + 69, 248, 219, 76, 255, 75, 16, 31, 160, 158, 174, 56, 207, 187, + 143, 190, 38, 111, 160, 63, 192, 90, 20, 108, 160, 100, 114, 40, + 179, 190, 198, 68, 232, 168, 216, 51, 166, 23, 138, 59, 188, 48, + 49, 42, 43, 18, 88, 154, 64, 32, 222, 145, 149, 231, 83, 205, + 159, 232, 241, 58, 124, 95, 79, 136, 24, 46, 51, 123, 172, 225, + 183, 18, 149, 198, 246, 119, 26, 137, 192, 48, 159, 248, 111, 89, + 138, 197, 128, 183, 125, 143, 51, 8, 24, 93, 154, 94, 130, 39, + 226, 147, 2, 242, 147, 73, 84, 102, 69, 168, 135, 223, 253, 127, + 105, 75, 46, 187, 42, 102, 169, 70, 133, 153, 254, 243, 119, 228, + 156, 5, 244, 190, 7, 63, 62, 156, 227, 121, 59, 215, 11, 179, + 64, 187, 110, 155, 189, 2, 124, 242, 128, 232, 126, 254, 152, 113, + 128, 73, 83, 32, 165, 251, 27, 223, 146, 103, 65, 28, 58, 179, + 88, 34, 114, 58, 203, 86, 39, 217, 36, 185, 233, 11, 192, 132, + 34, 116, 220, 100, 254, 106, 216, 226, 53, 41, 234, 213, 197, 136, + 12, 54, 25, 205, 76, 203, 197, 137, 151, 76, 69, 47, 159, 201, + 4, 147, 115, 94, 137, 108, 76, 75, 18, 131, 1, 96, 78, 167, + 186, 190, 200, 59, 7, 84, 67, 168, 220, 255, 72, 3, 226, 210, + 91, 152, 198, 57, 37, 92, 253, 103, 73, 207, 241, 35, 108, 184, + 194, 135, 139, 243, 76, 104, 91, 242, 80, 62, 184, 26, 203, 241, + 130, 241, 107, 106, 204, 241, 38, 52, 173, 85, 102, 250, 158, 181, + 76, 99, 3, 83, 248, 29, 230, 182, 158, 147, 47, 233, 107, 220, + 69, 4, 112, 20, 48, 220, 150, 98, 201, 141, 230, 255, 40, 122, + 204, 102, 183, 154, 177, 147, 102, 75, 3, 26, 62, 92, 49, 221, + 29, 235, 34, 224, 162, 112, 32, 228, 215, 235, 83, 123, 36, 139, + 125, 4, 121, 147, 69, 116, 191, 187, 78, 65, 35, 243, 123, 229, + 152, 121, 141, 237, 138, 186, 180, 161, 130, 202, 41, 165, 180, 172, + 148, 44, 245, 230, 29, 163, 18, 64, 41, 199, 47, 227, 113, 72, + 222, 56, 124, 18, 21, 197, 94, 2, 171, 164, 200, 113, 226, 53, + 128, 116, 140, 153, 121, 175, 153, 151, 119, 94, 190, 215, 131, 36, + 7, 251, 178, 43, 196, 211, 92, 117, 168, 206, 191, 4, 222, 203, + 34, 166, 129, 119, 247, 127, 76, 243, 162, 57, 86, 65, 25, 56, + 105, 219, 224, 237, 125, 38, 212, 80, 253, 174, 29, 244, 198, 100, + 21, 86, 10, 101, 115, 145, 40, 48, 149, 213, 136, 30, 153, 72, + 71, 227, 66, 178, 24, 17, 23, 180, 166, 18, 54, 101, 187, 125, + 34, 212, 112, 157, 85, 136, 163, 217, 7, 55, 3, 149, 198, 239, + 69, 49, 17, 159, 82, 0, 234, 246, 125, 193, 92, 158, 118, 77, + 155, 209, 122, 218, 253, 230, 92, 69, 171, 40, 233, 205, 196, 172, + 166, 109, 244, 25, 249, 114, 134, 188, 123, 214, 247, 114, 165, 11, + 206, 138, 137, 10, 159, 37, 174, 87, 82, 209, 216, 3, 235, 98, + 24, 173, 162, 36, 44, 239, 113, 229, 250, 36, 210, 33, 123, 206, + 141, 240, 230, 87, 81, 244, 35, 159, 113, 21, 176, 3, 2, 233, + 47, 118, 237, 53, 35, 35, 98, 161, 233, 202, 191, 112, 176, 86, + 222, 116, 20, 90, 59, 154, 122, 195, 193, 195, 250, 182, 63, 143, + 140, 250, 133, 97, 234, 152, 123, 75, 172, 35, 129, 121, 106, 76, + 238, 205, 103, 22, 43, 254, 116, 95, 233, 217, 225, 38, 112, 35, + 29, 162, 168, 126, 162, 133, 86, 199, 20, 191, 118, 124, 105, 130, + 93, 168, 129, 215, 119, 201, 148, 39, 101, 35, 252, 49, 251, 118, + 58, 51, 157, 144, 63, 20, 53, 166, 188, 189, 87, 176, 108, 131, + 202, 158, 255, 160, 220, 209, 57, 10, 64, 74, 250, 166, 205, 136, + 122, 121, 214, 90, 51, 248, 218, 11, 6, 127, 112, 11, 179, 99, + 106, 162, 146, 21, 248, 168, 220, 177, 175, 108, 134, 117, 141, 158, + 54, 133, 13, 93, 224, 200, 177, 236, 240, 117, 27, 5, 0, 110, + 77, 220, 84, 22, 0, 88, 202, 58, 135, 196, 91, 217, 201, 237, + 33, 8, 235, 104, 165, 22, 24, 86, 0, 103, 94, 195, 44, 151, + 175, 254, 125, 21, 82, 72, 233, 235, 143, 37, 120, 53, 192, 153, + 53, 166, 228, 243, 135, 161, 243, 68, 149, 220, 118, 244, 102, 77, + 11, 203, 26, 193, 42, 170, 144, 105, 120, 51, 236, 148, 163, 113, + 42, 184, 2, 185, 21, 107, 43, 9, 48, 231, 24, 120, 116, 181, + 130, 86, 24, 42, 193, 150, 140, 100, 58, 133, 84, 181, 95, 147, + 15, 138, 167, 43, 245, 230, 62, 102, 219, 119, 37, 99, 53, 111, + 162, 218, 65, 236, 154, 215, 130, 34, 67, 109, 212, 105, 216, 154, + 212, 236, 203, 122, 144, 216, 245, 156, 62, 146, 85, 201, 237, 224, + 221, 115, 81, 126, 63, 175, 21, 94, 203, 81, 51, 142, 62, 209, + 169, 89, 169, 33, 94, 218, 6, 44, 121, 93, 137, 18, 21, 158, + 183, 250, 105, 212, 169, 28, 119, 133, 105, 73, 97, 132, 22, 203, + 34, 43, 181, 247, 146, 58, 14, 67, 117, 5, 216, 87, 17, 173, + 27, 92, 25, 15, 18, 168, 234, 51, 245, 65, 57, 56, 93, 17, + 177, 80, 128, 1, 77, 128, 159, 103, 79, 138, 154, 37, 27, 166, + 180, 93, 90, 173, 47, 102, 197, 130, 12, 11, 211, 42, 56, 240, + 192, 30, 139, 218, 96, 136, 60, 189, 195, 120, 78, 178, 184, 249, + 180, 209, 252, 11, 43, 58, 40, 144, 93, 71, 88, 190, 238, 223, + 240, 128, 1, 20, 2, 0, 0, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 13, 99, 108, 101, 97, 114, + 116, 111, 109, 97, 114, 107, 13, 128, 3, +}; diff --git a/Rendering/fonts/face_times_bold.cxx b/Rendering/fonts/face_times_bold.cxx new file mode 100644 index 0000000..c498ae0 --- /dev/null +++ b/Rendering/fonts/face_times_bold.cxx @@ -0,0 +1,2425 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Times Bold +// Bitstream Charter Bold (c0632bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_times_bold_buffer_length = 33799; + +unsigned char face_times_bold_buffer[] = { + 128, 1, 214, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 83, + 97, 116, 32, 78, 111, 118, 32, 32, 51, 32, 50, 50, 58, 51, + 50, 58, 50, 50, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 66, + 105, 116, 115, 116, 114, 101, 97, 109, 32, 67, 104, 97, 114, 116, + 101, 114, 32, 66, 111, 108, 100, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 70, 97, 109, + 105, 108, 121, 78, 97, 109, 101, 32, 40, 66, 105, 116, 115, 116, + 114, 101, 97, 109, 32, 67, 104, 97, 114, 116, 101, 114, 41, 32, + 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, + 32, 47, 87, 101, 105, 103, 104, 116, 32, 40, 66, 111, 108, 100, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 13, 32, 32, 47, 73, 116, 97, 108, 105, 99, 65, 110, 103, 108, + 101, 32, 48, 32, 100, 101, 102, 13, 32, 32, 47, 105, 115, 70, + 105, 120, 101, 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, + 101, 32, 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, + 108, 105, 110, 101, 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, + 49, 48, 57, 32, 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, + 101, 114, 108, 105, 110, 101, 84, 104, 105, 99, 107, 110, 101, 115, + 115, 32, 57, 48, 32, 100, 101, 102, 13, 101, 110, 100, 32, 114, + 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 70, + 111, 110, 116, 78, 97, 109, 101, 32, 47, 67, 104, 97, 114, 116, + 101, 114, 66, 84, 45, 66, 111, 108, 100, 32, 100, 101, 102, 13, + 47, 80, 97, 105, 110, 116, 84, 121, 112, 101, 32, 48, 32, 100, + 101, 102, 13, 47, 70, 111, 110, 116, 84, 121, 112, 101, 32, 49, + 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 77, 97, 116, 114, + 105, 120, 32, 91, 48, 46, 48, 48, 49, 32, 48, 32, 48, 32, + 48, 46, 48, 48, 49, 32, 48, 32, 48, 93, 32, 114, 101, 97, + 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 69, 110, 99, + 111, 100, 105, 110, 103, 32, 83, 116, 97, 110, 100, 97, 114, 100, + 69, 110, 99, 111, 100, 105, 110, 103, 32, 100, 101, 102, 13, 47, + 70, 111, 110, 116, 66, 66, 111, 120, 32, 123, 45, 49, 54, 54, + 32, 45, 50, 51, 54, 32, 49, 50, 54, 50, 32, 57, 54, 51, + 125, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 13, 47, 85, 110, 105, 113, 117, 101, 73, 68, 32, 49, 53, 53, + 51, 48, 54, 51, 50, 32, 100, 101, 102, 13, 99, 117, 114, 114, + 101, 110, 116, 100, 105, 99, 116, 32, 101, 110, 100, 13, 99, 117, + 114, 114, 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, 101, + 99, 13, 128, 2, 9, 124, 0, 0, 162, 149, 24, 64, 131, 138, + 65, 51, 131, 156, 169, 210, 46, 43, 153, 242, 182, 28, 118, 124, + 214, 117, 8, 10, 172, 252, 178, 78, 25, 205, 19, 54, 115, 155, + 182, 73, 148, 197, 103, 55, 9, 11, 76, 236, 146, 201, 148, 95, + 240, 116, 94, 247, 255, 198, 27, 176, 169, 163, 184, 73, 231, 233, + 135, 64, 229, 108, 11, 90, 247, 135, 85, 156, 198, 149, 106, 179, + 30, 51, 207, 133, 83, 213, 92, 11, 14, 129, 142, 245, 236, 107, + 244, 129, 98, 234, 196, 46, 115, 128, 202, 146, 29, 174, 28, 130, + 179, 143, 214, 188, 242, 0, 26, 187, 93, 0, 26, 86, 21, 112, + 148, 207, 226, 125, 143, 78, 172, 150, 147, 232, 131, 114, 210, 3, + 88, 180, 126, 12, 56, 118, 85, 142, 191, 117, 122, 31, 188, 92, + 28, 221, 246, 43, 60, 87, 191, 114, 126, 241, 196, 135, 148, 34, + 193, 66, 160, 132, 209, 199, 70, 42, 194, 147, 224, 151, 250, 190, + 58, 62, 207, 205, 130, 113, 242, 89, 131, 59, 172, 121, 18, 112, + 114, 24, 236, 154, 48, 99, 191, 115, 133, 224, 45, 140, 16, 88, + 172, 6, 223, 0, 179, 59, 140, 1, 135, 104, 178, 120, 1, 14, + 177, 75, 215, 169, 79, 76, 102, 156, 166, 184, 243, 32, 8, 74, + 111, 240, 206, 167, 168, 44, 107, 192, 30, 17, 158, 72, 233, 39, + 68, 252, 34, 234, 190, 88, 186, 193, 69, 131, 109, 181, 0, 170, + 215, 16, 28, 240, 228, 135, 228, 17, 247, 33, 40, 147, 252, 155, + 104, 144, 226, 124, 9, 248, 79, 25, 82, 77, 6, 178, 79, 177, + 8, 143, 235, 48, 129, 35, 235, 237, 64, 18, 15, 19, 179, 250, + 98, 33, 181, 68, 50, 40, 232, 106, 111, 184, 131, 245, 152, 175, + 254, 48, 171, 63, 40, 70, 212, 66, 191, 8, 98, 230, 111, 213, + 74, 158, 135, 184, 48, 230, 178, 232, 158, 225, 193, 206, 56, 174, + 34, 102, 128, 92, 240, 65, 114, 186, 105, 213, 231, 15, 16, 37, + 215, 221, 101, 118, 91, 130, 38, 148, 48, 228, 26, 102, 109, 93, + 57, 17, 24, 225, 199, 178, 174, 207, 34, 43, 122, 255, 225, 43, + 160, 106, 37, 145, 187, 175, 36, 223, 85, 204, 24, 33, 162, 181, + 47, 18, 80, 71, 140, 200, 190, 149, 159, 104, 130, 166, 128, 116, + 153, 31, 103, 216, 214, 241, 75, 253, 236, 171, 134, 120, 2, 144, + 24, 46, 85, 212, 166, 82, 138, 216, 43, 241, 70, 253, 195, 184, + 147, 50, 81, 102, 154, 148, 126, 215, 148, 170, 21, 112, 192, 234, + 37, 248, 246, 70, 193, 222, 173, 65, 141, 146, 6, 21, 225, 54, + 137, 130, 61, 55, 176, 70, 253, 81, 97, 124, 243, 226, 195, 199, + 120, 174, 94, 34, 0, 35, 56, 249, 107, 238, 3, 12, 152, 199, + 59, 254, 10, 251, 231, 72, 254, 23, 108, 3, 78, 178, 45, 163, + 115, 15, 146, 60, 182, 133, 165, 216, 209, 127, 32, 111, 72, 254, + 30, 107, 9, 142, 91, 63, 106, 194, 191, 123, 230, 83, 159, 97, + 80, 103, 59, 108, 200, 218, 196, 114, 180, 192, 72, 63, 47, 210, + 245, 101, 229, 142, 90, 125, 68, 228, 200, 204, 253, 212, 142, 15, + 71, 237, 191, 149, 237, 59, 182, 253, 234, 220, 32, 198, 169, 27, + 155, 188, 207, 85, 198, 243, 102, 77, 113, 229, 207, 243, 123, 119, + 9, 164, 253, 205, 125, 71, 174, 241, 241, 36, 38, 104, 48, 7, + 246, 79, 103, 6, 95, 239, 218, 196, 233, 226, 66, 104, 250, 176, + 75, 68, 249, 197, 14, 49, 81, 48, 165, 180, 164, 243, 130, 18, + 7, 194, 232, 125, 252, 167, 162, 47, 255, 24, 216, 41, 33, 168, + 210, 109, 12, 219, 151, 241, 100, 77, 0, 186, 135, 76, 228, 59, + 174, 71, 202, 7, 8, 94, 249, 251, 204, 42, 142, 73, 8, 114, + 3, 207, 24, 243, 73, 189, 25, 144, 13, 222, 119, 132, 41, 83, + 75, 27, 64, 104, 39, 131, 84, 216, 18, 247, 46, 137, 252, 5, + 93, 72, 56, 114, 240, 10, 14, 174, 106, 50, 148, 248, 161, 130, + 156, 173, 189, 108, 124, 14, 134, 17, 149, 238, 84, 51, 91, 239, + 139, 185, 14, 222, 2, 18, 189, 158, 83, 109, 134, 186, 21, 3, + 68, 8, 133, 144, 219, 161, 180, 250, 31, 217, 78, 82, 159, 166, + 6, 244, 73, 36, 233, 168, 202, 205, 204, 104, 98, 190, 189, 186, + 1, 157, 175, 164, 98, 232, 44, 14, 44, 18, 209, 5, 112, 214, + 125, 170, 212, 134, 128, 152, 32, 23, 5, 188, 85, 90, 203, 30, + 183, 194, 226, 198, 85, 37, 222, 57, 202, 109, 86, 192, 122, 3, + 43, 59, 244, 103, 135, 181, 29, 215, 245, 93, 215, 16, 182, 243, + 140, 10, 168, 48, 231, 186, 251, 116, 80, 121, 8, 2, 55, 212, + 228, 7, 114, 85, 135, 132, 127, 209, 4, 105, 185, 107, 184, 8, + 25, 31, 254, 69, 9, 111, 213, 207, 8, 100, 105, 40, 175, 30, + 130, 40, 9, 38, 36, 15, 8, 254, 159, 135, 57, 213, 233, 117, + 39, 160, 216, 119, 210, 85, 117, 138, 170, 23, 151, 39, 211, 51, + 77, 23, 216, 131, 46, 14, 89, 184, 112, 137, 72, 51, 82, 210, + 42, 70, 61, 224, 8, 180, 6, 72, 241, 68, 96, 148, 42, 207, + 14, 55, 103, 191, 132, 135, 36, 93, 197, 163, 158, 22, 251, 96, + 99, 104, 80, 234, 207, 54, 186, 243, 94, 213, 96, 180, 151, 26, + 253, 184, 118, 100, 240, 71, 164, 46, 255, 61, 109, 184, 159, 188, + 249, 15, 190, 99, 80, 238, 133, 145, 116, 116, 185, 169, 79, 127, + 53, 229, 43, 41, 160, 253, 49, 78, 29, 153, 81, 211, 249, 36, + 143, 94, 134, 151, 64, 26, 186, 132, 172, 4, 201, 38, 195, 206, + 16, 167, 48, 191, 105, 66, 37, 130, 51, 103, 161, 181, 36, 244, + 235, 54, 58, 184, 100, 64, 98, 96, 208, 121, 11, 179, 148, 46, + 60, 15, 254, 78, 24, 193, 247, 220, 127, 142, 204, 146, 53, 108, + 233, 16, 104, 76, 92, 197, 77, 181, 103, 153, 77, 88, 156, 34, + 186, 117, 185, 94, 246, 32, 70, 143, 228, 96, 246, 216, 211, 193, + 103, 27, 131, 253, 171, 35, 247, 195, 246, 78, 85, 57, 100, 229, + 237, 163, 2, 98, 160, 99, 79, 36, 162, 50, 219, 18, 85, 203, + 37, 69, 75, 87, 208, 121, 250, 40, 251, 252, 65, 186, 84, 123, + 103, 214, 180, 242, 172, 206, 45, 44, 22, 64, 181, 171, 180, 152, + 221, 244, 109, 193, 159, 231, 6, 31, 66, 50, 54, 189, 128, 239, + 105, 30, 33, 167, 243, 177, 197, 49, 91, 134, 1, 85, 185, 113, + 61, 131, 76, 172, 25, 240, 41, 68, 54, 239, 222, 84, 92, 131, + 217, 203, 23, 164, 243, 237, 158, 76, 72, 39, 188, 185, 106, 36, + 75, 99, 83, 241, 14, 41, 62, 109, 142, 32, 197, 30, 22, 143, + 122, 252, 109, 64, 164, 175, 248, 219, 0, 252, 71, 95, 220, 84, + 95, 123, 135, 190, 192, 9, 37, 179, 119, 116, 17, 204, 14, 222, + 127, 54, 26, 115, 66, 153, 208, 46, 69, 44, 84, 122, 167, 82, + 230, 201, 84, 86, 2, 73, 26, 56, 96, 55, 240, 239, 22, 143, + 6, 228, 121, 153, 7, 233, 248, 187, 163, 73, 118, 31, 26, 128, + 193, 90, 79, 183, 226, 253, 88, 164, 143, 152, 155, 236, 7, 175, + 201, 163, 65, 135, 228, 123, 241, 68, 176, 64, 229, 7, 194, 217, + 101, 174, 92, 252, 231, 57, 173, 118, 114, 50, 233, 7, 43, 205, + 216, 129, 137, 188, 56, 127, 66, 147, 33, 168, 219, 187, 90, 99, + 172, 217, 1, 211, 21, 59, 120, 121, 165, 6, 134, 200, 49, 190, + 155, 225, 175, 210, 185, 223, 191, 60, 20, 192, 195, 59, 90, 234, + 9, 243, 61, 124, 83, 156, 145, 243, 208, 255, 129, 54, 137, 108, + 65, 238, 86, 103, 244, 10, 126, 206, 187, 163, 255, 80, 108, 182, + 7, 199, 243, 84, 217, 80, 230, 19, 182, 175, 160, 231, 59, 80, + 2, 107, 89, 142, 159, 244, 53, 191, 152, 139, 57, 202, 15, 90, + 185, 79, 19, 216, 153, 174, 10, 145, 154, 87, 199, 117, 47, 209, + 150, 162, 191, 194, 89, 62, 196, 13, 209, 139, 11, 243, 191, 103, + 228, 15, 116, 77, 46, 146, 23, 84, 112, 1, 198, 11, 101, 118, + 221, 238, 20, 169, 79, 232, 249, 110, 38, 245, 210, 39, 217, 155, + 166, 118, 152, 242, 99, 164, 18, 182, 147, 198, 175, 66, 7, 66, + 235, 18, 116, 31, 63, 22, 166, 231, 230, 168, 99, 55, 3, 215, + 101, 113, 75, 161, 19, 56, 18, 70, 167, 23, 90, 40, 236, 160, + 92, 223, 72, 67, 224, 34, 75, 144, 100, 26, 45, 15, 194, 103, + 91, 229, 28, 57, 87, 213, 104, 74, 36, 239, 124, 114, 183, 133, + 153, 46, 226, 58, 195, 236, 151, 121, 116, 101, 13, 249, 243, 22, + 197, 193, 14, 185, 140, 241, 7, 72, 93, 179, 238, 206, 120, 43, + 217, 185, 53, 151, 221, 102, 64, 191, 84, 188, 172, 137, 191, 181, + 184, 79, 11, 174, 9, 253, 145, 184, 112, 109, 2, 173, 195, 234, + 68, 163, 190, 251, 240, 94, 184, 101, 167, 139, 57, 226, 22, 27, + 26, 113, 204, 58, 112, 137, 109, 85, 154, 95, 134, 155, 94, 152, + 118, 111, 202, 192, 86, 194, 165, 151, 43, 129, 61, 85, 131, 61, + 221, 36, 209, 140, 61, 131, 80, 221, 172, 119, 217, 211, 189, 137, + 83, 160, 213, 137, 81, 132, 55, 197, 12, 12, 153, 230, 221, 58, + 217, 221, 20, 85, 212, 4, 31, 41, 68, 105, 184, 137, 158, 235, + 10, 115, 141, 150, 85, 9, 77, 10, 10, 144, 111, 251, 246, 215, + 50, 177, 187, 233, 243, 62, 200, 130, 27, 83, 177, 49, 149, 83, + 36, 191, 64, 36, 80, 108, 80, 121, 252, 73, 53, 185, 107, 188, + 167, 218, 7, 205, 116, 165, 65, 3, 207, 148, 100, 138, 250, 223, + 67, 19, 170, 244, 135, 147, 100, 1, 24, 135, 54, 189, 23, 212, + 45, 218, 92, 10, 220, 65, 185, 153, 151, 40, 79, 57, 252, 60, + 99, 228, 99, 191, 17, 47, 135, 28, 142, 31, 55, 136, 103, 0, + 14, 115, 211, 171, 204, 244, 246, 118, 210, 228, 122, 151, 37, 239, + 133, 207, 242, 2, 43, 200, 161, 147, 42, 124, 111, 107, 52, 31, + 12, 150, 218, 109, 198, 145, 119, 199, 21, 46, 126, 82, 192, 205, + 224, 96, 31, 196, 42, 52, 103, 27, 199, 226, 212, 14, 148, 58, + 39, 198, 205, 231, 132, 50, 105, 50, 15, 50, 163, 221, 159, 247, + 21, 248, 32, 250, 186, 215, 42, 83, 194, 232, 29, 71, 57, 21, + 221, 95, 89, 107, 24, 134, 86, 194, 59, 146, 225, 123, 119, 98, + 171, 99, 2, 197, 228, 9, 90, 175, 75, 246, 222, 104, 145, 174, + 67, 116, 12, 228, 192, 223, 124, 205, 5, 145, 253, 64, 105, 217, + 228, 212, 202, 98, 76, 124, 245, 112, 103, 234, 180, 45, 230, 160, + 138, 105, 32, 191, 169, 220, 131, 4, 161, 224, 201, 105, 215, 254, + 149, 34, 10, 25, 117, 22, 167, 227, 189, 25, 55, 76, 230, 104, + 33, 17, 155, 253, 141, 3, 149, 52, 51, 100, 236, 136, 194, 220, + 218, 45, 125, 156, 72, 150, 32, 243, 130, 123, 75, 238, 160, 149, + 127, 237, 193, 18, 85, 130, 228, 177, 135, 176, 147, 137, 129, 144, + 60, 61, 106, 61, 30, 83, 102, 100, 55, 76, 252, 252, 139, 188, + 170, 228, 15, 30, 104, 150, 96, 167, 39, 15, 221, 32, 60, 108, + 191, 37, 223, 75, 7, 251, 224, 149, 33, 52, 221, 110, 103, 153, + 190, 216, 148, 183, 60, 209, 44, 166, 237, 58, 75, 0, 154, 240, + 20, 215, 91, 226, 225, 72, 156, 162, 64, 136, 174, 244, 229, 16, + 245, 188, 74, 171, 233, 5, 100, 225, 252, 126, 45, 76, 19, 112, + 38, 47, 109, 253, 178, 48, 157, 13, 12, 218, 109, 14, 111, 32, + 84, 21, 128, 240, 11, 245, 27, 27, 6, 77, 186, 220, 25, 173, + 169, 10, 163, 124, 124, 70, 158, 188, 18, 133, 150, 103, 47, 41, + 44, 105, 81, 67, 142, 61, 79, 227, 185, 60, 183, 170, 112, 195, + 45, 123, 179, 133, 221, 250, 131, 47, 157, 244, 2, 2, 81, 199, + 150, 180, 185, 144, 186, 125, 106, 188, 91, 107, 44, 33, 165, 141, + 25, 95, 250, 142, 53, 143, 37, 23, 36, 176, 240, 72, 187, 144, + 75, 215, 255, 47, 218, 228, 254, 243, 98, 110, 3, 143, 43, 19, + 77, 141, 140, 222, 254, 122, 137, 45, 68, 242, 191, 146, 95, 13, + 176, 75, 166, 161, 53, 158, 91, 23, 183, 143, 113, 77, 5, 34, + 43, 165, 9, 156, 138, 4, 223, 218, 167, 46, 69, 80, 116, 103, + 248, 144, 50, 62, 201, 170, 230, 152, 215, 29, 47, 117, 204, 17, + 234, 173, 90, 240, 152, 165, 227, 244, 42, 53, 20, 77, 208, 115, + 229, 70, 230, 115, 61, 253, 218, 215, 153, 157, 73, 197, 29, 171, + 119, 153, 45, 106, 88, 223, 207, 27, 39, 153, 121, 89, 30, 114, + 123, 151, 128, 62, 80, 201, 45, 178, 170, 233, 140, 32, 39, 216, + 74, 235, 96, 227, 199, 25, 190, 236, 108, 48, 230, 25, 178, 219, + 37, 155, 14, 37, 120, 34, 62, 105, 100, 93, 82, 192, 81, 191, + 37, 202, 52, 254, 242, 52, 121, 74, 78, 147, 241, 119, 103, 170, + 56, 87, 226, 9, 48, 234, 4, 151, 228, 12, 105, 44, 215, 110, + 253, 96, 18, 32, 208, 41, 83, 94, 105, 108, 138, 207, 44, 17, + 245, 36, 250, 4, 4, 169, 208, 165, 102, 254, 98, 110, 241, 250, + 130, 233, 138, 227, 35, 228, 246, 237, 232, 140, 223, 0, 49, 134, + 169, 142, 233, 180, 181, 249, 31, 106, 42, 34, 137, 67, 72, 38, + 194, 186, 141, 50, 106, 91, 175, 88, 91, 72, 190, 151, 100, 56, + 93, 228, 34, 60, 112, 184, 51, 81, 42, 30, 41, 43, 201, 233, + 66, 154, 124, 221, 38, 168, 113, 247, 49, 39, 158, 97, 89, 142, + 206, 93, 162, 220, 133, 109, 77, 180, 123, 128, 57, 45, 73, 193, + 247, 248, 156, 67, 164, 155, 242, 56, 9, 45, 207, 128, 152, 85, + 53, 165, 169, 21, 47, 182, 109, 246, 78, 117, 185, 200, 28, 238, + 50, 30, 124, 125, 188, 204, 18, 168, 163, 18, 106, 76, 155, 205, + 11, 194, 222, 43, 237, 242, 24, 190, 153, 78, 187, 206, 170, 176, + 211, 84, 228, 163, 100, 41, 154, 129, 114, 202, 36, 243, 124, 112, + 176, 231, 38, 108, 75, 137, 17, 88, 221, 171, 17, 173, 2, 105, + 142, 192, 55, 250, 206, 108, 153, 71, 238, 226, 185, 98, 125, 88, + 86, 68, 218, 169, 154, 30, 229, 60, 227, 3, 108, 144, 3, 4, + 10, 215, 255, 113, 127, 253, 67, 160, 76, 203, 196, 79, 112, 240, + 12, 123, 133, 97, 156, 152, 72, 240, 126, 241, 8, 192, 26, 87, + 192, 19, 12, 159, 70, 199, 113, 22, 177, 156, 111, 38, 24, 51, + 169, 150, 74, 131, 183, 147, 59, 20, 237, 82, 199, 128, 63, 1, + 7, 69, 187, 215, 94, 123, 246, 254, 234, 1, 203, 38, 4, 2, + 74, 188, 218, 38, 194, 198, 140, 26, 208, 72, 153, 158, 19, 33, + 194, 88, 70, 157, 102, 21, 226, 37, 84, 142, 69, 3, 154, 63, + 144, 8, 185, 117, 210, 40, 248, 234, 74, 114, 189, 86, 237, 245, + 250, 7, 7, 136, 41, 177, 136, 182, 245, 168, 190, 169, 217, 65, + 100, 195, 226, 61, 149, 149, 14, 181, 27, 65, 56, 75, 247, 188, + 240, 70, 210, 252, 124, 1, 210, 27, 247, 146, 25, 199, 93, 185, + 64, 199, 30, 39, 119, 70, 32, 40, 73, 143, 147, 106, 57, 150, + 243, 196, 246, 25, 109, 57, 223, 11, 219, 242, 141, 137, 234, 9, + 6, 193, 200, 242, 183, 153, 46, 142, 46, 60, 63, 252, 115, 132, + 209, 207, 31, 201, 233, 134, 97, 216, 120, 191, 238, 69, 190, 119, + 226, 73, 87, 226, 208, 188, 213, 193, 157, 54, 179, 59, 70, 77, + 60, 147, 126, 196, 238, 48, 186, 228, 96, 7, 85, 100, 64, 231, + 173, 8, 65, 26, 194, 89, 67, 215, 2, 174, 191, 11, 137, 36, + 237, 89, 123, 142, 59, 177, 177, 140, 103, 109, 251, 229, 70, 137, + 88, 105, 124, 150, 188, 38, 249, 9, 186, 16, 81, 167, 106, 75, + 9, 250, 39, 248, 151, 6, 168, 116, 87, 47, 204, 87, 5, 234, + 146, 66, 198, 165, 248, 55, 137, 177, 221, 43, 84, 75, 55, 202, + 174, 97, 34, 180, 241, 3, 109, 96, 136, 165, 229, 154, 126, 238, + 147, 80, 89, 98, 78, 76, 220, 212, 108, 207, 76, 171, 1, 196, + 75, 30, 197, 81, 38, 179, 59, 245, 170, 76, 168, 118, 195, 220, + 42, 50, 89, 83, 170, 61, 125, 147, 177, 239, 219, 62, 218, 16, + 239, 13, 97, 240, 253, 180, 150, 237, 114, 101, 36, 78, 37, 106, + 207, 57, 77, 74, 51, 50, 80, 86, 158, 241, 206, 250, 70, 144, + 10, 157, 234, 199, 11, 51, 150, 71, 11, 114, 65, 37, 38, 124, + 148, 177, 46, 161, 249, 200, 95, 58, 184, 49, 26, 150, 200, 218, + 19, 123, 105, 65, 94, 77, 157, 194, 62, 14, 235, 153, 120, 65, + 160, 63, 78, 207, 159, 125, 85, 15, 61, 71, 183, 219, 101, 220, + 40, 13, 44, 27, 221, 58, 68, 178, 114, 211, 11, 148, 7, 195, + 217, 86, 1, 250, 77, 115, 143, 90, 107, 46, 164, 171, 240, 14, + 201, 94, 161, 20, 156, 74, 67, 221, 82, 69, 195, 195, 163, 197, + 114, 58, 146, 208, 226, 96, 237, 24, 173, 190, 214, 25, 175, 124, + 49, 67, 111, 112, 163, 23, 13, 234, 105, 58, 243, 129, 148, 53, + 189, 186, 81, 104, 57, 158, 136, 232, 36, 174, 166, 49, 139, 188, + 235, 82, 65, 238, 49, 192, 111, 173, 9, 194, 33, 227, 84, 116, + 14, 177, 42, 64, 162, 68, 146, 252, 239, 121, 207, 143, 153, 169, + 11, 67, 226, 134, 135, 79, 129, 149, 64, 185, 188, 62, 14, 167, + 80, 26, 239, 188, 13, 207, 96, 77, 62, 147, 134, 215, 37, 139, + 233, 213, 88, 45, 119, 171, 146, 51, 51, 142, 31, 165, 234, 130, + 79, 176, 198, 5, 224, 197, 163, 149, 10, 36, 51, 148, 193, 129, + 38, 110, 49, 154, 113, 170, 45, 175, 177, 222, 50, 203, 88, 150, + 192, 213, 120, 11, 9, 203, 52, 89, 30, 2, 0, 207, 127, 142, + 111, 29, 254, 251, 141, 98, 25, 2, 198, 17, 189, 144, 158, 248, + 68, 13, 237, 215, 44, 5, 71, 173, 110, 207, 21, 223, 76, 136, + 152, 112, 231, 223, 216, 42, 25, 139, 141, 134, 56, 22, 143, 211, + 39, 159, 27, 248, 182, 87, 243, 35, 64, 252, 210, 227, 227, 157, + 121, 40, 80, 10, 127, 209, 189, 225, 190, 238, 121, 184, 121, 136, + 214, 95, 61, 184, 129, 119, 194, 62, 34, 254, 30, 33, 63, 159, + 8, 223, 197, 36, 175, 79, 222, 127, 201, 86, 60, 242, 104, 39, + 133, 80, 222, 62, 183, 150, 94, 189, 112, 98, 185, 239, 154, 111, + 134, 101, 38, 173, 75, 20, 194, 236, 103, 108, 198, 143, 163, 10, + 49, 233, 210, 63, 58, 108, 80, 137, 0, 202, 123, 170, 195, 109, + 27, 107, 61, 107, 21, 246, 49, 5, 63, 129, 113, 219, 41, 186, + 187, 112, 187, 185, 61, 65, 24, 232, 216, 139, 173, 79, 196, 95, + 203, 169, 185, 179, 202, 192, 187, 128, 90, 4, 143, 120, 218, 206, + 74, 206, 47, 129, 107, 180, 67, 123, 248, 254, 142, 35, 32, 249, + 133, 16, 214, 17, 58, 235, 24, 201, 227, 57, 67, 12, 139, 238, + 188, 150, 116, 17, 26, 96, 54, 219, 33, 227, 250, 87, 50, 17, + 87, 214, 2, 137, 203, 175, 79, 1, 48, 97, 190, 36, 226, 34, + 109, 181, 1, 35, 208, 124, 88, 164, 89, 210, 163, 144, 182, 216, + 219, 10, 236, 199, 253, 144, 59, 172, 171, 161, 39, 99, 223, 110, + 220, 114, 183, 215, 17, 162, 135, 54, 117, 143, 61, 67, 224, 172, + 253, 230, 80, 150, 192, 142, 52, 122, 21, 250, 115, 162, 165, 92, + 86, 80, 193, 52, 255, 51, 179, 43, 239, 170, 169, 53, 90, 166, + 115, 242, 104, 89, 255, 29, 14, 138, 91, 52, 11, 33, 177, 95, + 48, 177, 37, 65, 133, 99, 71, 111, 185, 58, 226, 253, 242, 159, + 229, 251, 15, 110, 207, 133, 138, 70, 187, 46, 203, 137, 72, 72, + 114, 45, 25, 133, 201, 245, 182, 189, 28, 42, 5, 65, 252, 122, + 140, 129, 209, 7, 65, 30, 92, 192, 239, 4, 155, 7, 201, 179, + 180, 51, 231, 61, 188, 241, 125, 72, 113, 88, 78, 108, 182, 189, + 55, 213, 240, 87, 4, 220, 127, 255, 139, 146, 84, 189, 82, 59, + 70, 251, 49, 217, 30, 151, 246, 65, 92, 135, 38, 183, 17, 201, + 86, 134, 135, 13, 124, 208, 121, 94, 119, 120, 170, 208, 157, 92, + 62, 126, 234, 19, 105, 68, 247, 103, 136, 238, 175, 124, 87, 228, + 44, 50, 21, 123, 183, 78, 57, 18, 50, 172, 33, 87, 225, 131, + 124, 154, 116, 104, 251, 249, 198, 163, 164, 236, 7, 172, 43, 210, + 189, 10, 94, 200, 215, 55, 84, 163, 128, 154, 33, 216, 36, 121, + 116, 191, 163, 252, 195, 39, 229, 186, 191, 22, 23, 98, 228, 125, + 18, 198, 117, 29, 225, 175, 254, 60, 176, 118, 37, 77, 234, 59, + 174, 30, 150, 48, 159, 119, 216, 228, 73, 44, 146, 193, 189, 64, + 234, 72, 38, 204, 53, 255, 184, 249, 78, 162, 124, 191, 84, 192, + 77, 87, 193, 193, 251, 63, 178, 138, 48, 34, 248, 87, 255, 32, + 29, 233, 206, 250, 208, 80, 59, 225, 111, 22, 239, 252, 219, 60, + 17, 81, 33, 76, 41, 172, 172, 50, 200, 111, 86, 160, 71, 46, + 109, 81, 140, 175, 155, 31, 227, 19, 145, 109, 252, 168, 236, 187, + 38, 192, 255, 183, 145, 16, 48, 130, 242, 113, 242, 148, 130, 27, + 84, 78, 140, 160, 94, 91, 223, 203, 33, 21, 150, 122, 69, 181, + 30, 60, 31, 228, 36, 127, 209, 25, 174, 14, 33, 177, 45, 31, + 113, 111, 199, 78, 83, 247, 171, 59, 34, 192, 125, 26, 239, 244, + 215, 158, 114, 251, 36, 36, 5, 246, 91, 48, 18, 225, 87, 192, + 25, 56, 148, 91, 163, 123, 244, 25, 56, 165, 250, 188, 216, 146, + 255, 65, 147, 222, 143, 203, 86, 47, 79, 205, 219, 53, 34, 58, + 212, 117, 181, 150, 224, 247, 197, 7, 29, 126, 184, 19, 4, 14, + 219, 38, 208, 146, 13, 170, 54, 241, 60, 155, 19, 210, 255, 165, + 205, 65, 68, 5, 170, 193, 152, 99, 230, 239, 98, 247, 247, 213, + 19, 25, 43, 179, 116, 223, 97, 179, 70, 89, 138, 164, 141, 229, + 86, 18, 12, 132, 95, 47, 77, 49, 70, 50, 177, 244, 60, 100, + 62, 84, 143, 249, 48, 241, 241, 210, 3, 5, 81, 63, 151, 147, + 175, 226, 96, 249, 243, 240, 87, 23, 255, 245, 136, 60, 182, 111, + 6, 129, 138, 234, 174, 59, 240, 82, 135, 108, 121, 234, 109, 12, + 193, 133, 6, 158, 223, 152, 42, 35, 240, 2, 115, 77, 26, 223, + 236, 70, 125, 8, 151, 61, 198, 124, 151, 155, 115, 248, 76, 232, + 22, 65, 215, 3, 159, 0, 149, 84, 117, 225, 48, 252, 189, 12, + 171, 248, 82, 128, 19, 78, 94, 164, 169, 214, 14, 232, 23, 35, + 203, 89, 73, 110, 145, 79, 42, 213, 53, 127, 1, 178, 131, 156, + 218, 236, 183, 114, 153, 131, 41, 36, 11, 204, 245, 64, 184, 241, + 140, 172, 131, 179, 116, 104, 61, 189, 100, 124, 187, 138, 0, 208, + 125, 103, 200, 245, 154, 213, 84, 94, 238, 69, 126, 160, 180, 28, + 131, 40, 225, 209, 223, 22, 190, 234, 68, 95, 11, 133, 241, 148, + 184, 214, 153, 139, 201, 111, 251, 212, 74, 33, 21, 225, 228, 231, + 246, 220, 159, 45, 185, 173, 61, 185, 164, 68, 101, 43, 22, 92, + 200, 38, 249, 119, 152, 55, 246, 93, 40, 210, 159, 211, 92, 190, + 246, 38, 91, 212, 150, 249, 80, 224, 50, 144, 254, 66, 122, 198, + 60, 192, 86, 11, 101, 240, 249, 233, 239, 184, 157, 238, 61, 74, + 13, 26, 12, 246, 33, 27, 183, 61, 234, 43, 142, 212, 207, 226, + 58, 101, 230, 62, 55, 40, 97, 56, 163, 211, 15, 141, 200, 12, + 147, 106, 128, 1, 105, 157, 212, 211, 9, 13, 85, 161, 239, 170, + 72, 197, 103, 106, 171, 24, 153, 148, 155, 224, 22, 21, 161, 56, + 177, 244, 174, 112, 125, 39, 38, 94, 6, 194, 171, 163, 63, 151, + 221, 51, 0, 249, 220, 209, 220, 244, 159, 249, 99, 241, 210, 212, + 81, 153, 68, 94, 217, 141, 115, 86, 183, 36, 70, 182, 192, 65, + 7, 101, 147, 116, 80, 158, 226, 78, 56, 154, 59, 100, 125, 45, + 42, 149, 52, 72, 56, 131, 154, 174, 199, 61, 206, 97, 64, 68, + 143, 230, 80, 65, 197, 255, 232, 246, 94, 238, 118, 254, 57, 255, + 235, 35, 112, 128, 123, 30, 218, 193, 97, 145, 43, 90, 244, 164, + 25, 246, 85, 67, 77, 107, 130, 108, 187, 162, 162, 156, 78, 82, + 10, 81, 65, 22, 92, 152, 194, 244, 243, 128, 99, 67, 80, 137, + 248, 150, 74, 235, 86, 98, 237, 250, 162, 88, 105, 114, 21, 12, + 161, 210, 177, 242, 13, 50, 12, 109, 213, 24, 36, 28, 8, 221, + 169, 236, 155, 184, 133, 149, 184, 211, 64, 34, 127, 154, 189, 225, + 233, 233, 117, 214, 42, 10, 171, 82, 17, 215, 74, 2, 109, 4, + 178, 74, 43, 30, 163, 78, 8, 67, 44, 42, 242, 232, 100, 217, + 169, 22, 130, 203, 86, 135, 14, 174, 218, 87, 88, 185, 162, 174, + 233, 41, 26, 93, 198, 117, 188, 14, 220, 66, 58, 250, 154, 198, + 173, 144, 190, 219, 113, 16, 26, 196, 150, 88, 188, 211, 11, 37, + 220, 171, 12, 101, 20, 19, 23, 117, 3, 64, 35, 18, 254, 39, + 87, 62, 111, 179, 140, 30, 22, 85, 57, 149, 225, 61, 202, 79, + 180, 12, 114, 46, 200, 6, 92, 188, 137, 244, 214, 79, 164, 103, + 60, 165, 145, 12, 110, 200, 149, 7, 50, 60, 160, 118, 247, 119, + 32, 172, 222, 41, 198, 195, 180, 45, 64, 51, 89, 169, 162, 1, + 21, 21, 174, 208, 114, 121, 56, 222, 43, 52, 159, 123, 49, 62, + 10, 59, 32, 133, 122, 81, 99, 214, 212, 114, 233, 99, 196, 242, + 28, 251, 27, 130, 62, 81, 117, 66, 228, 135, 83, 83, 240, 156, + 77, 121, 113, 74, 23, 87, 227, 150, 42, 164, 252, 193, 107, 151, + 164, 213, 230, 95, 221, 51, 249, 120, 100, 246, 78, 255, 74, 251, + 188, 55, 81, 29, 174, 80, 160, 17, 215, 160, 83, 182, 40, 78, + 226, 240, 40, 176, 17, 129, 79, 62, 171, 225, 87, 31, 58, 202, + 36, 18, 152, 62, 220, 166, 139, 93, 177, 108, 24, 244, 73, 172, + 157, 188, 116, 25, 228, 94, 198, 235, 14, 136, 59, 171, 64, 71, + 226, 94, 162, 200, 37, 46, 3, 197, 223, 229, 81, 167, 54, 77, + 250, 109, 242, 164, 106, 17, 81, 181, 194, 115, 229, 32, 253, 24, + 206, 33, 92, 118, 201, 114, 198, 252, 185, 66, 154, 52, 165, 64, + 204, 11, 137, 181, 107, 79, 72, 22, 95, 43, 110, 22, 243, 59, + 149, 203, 121, 52, 81, 226, 218, 217, 48, 8, 237, 33, 48, 71, + 198, 189, 211, 207, 40, 79, 51, 31, 160, 15, 6, 145, 109, 33, + 240, 181, 53, 198, 103, 122, 95, 96, 204, 239, 182, 39, 11, 189, + 219, 78, 99, 252, 189, 241, 132, 28, 79, 127, 118, 241, 125, 137, + 241, 118, 213, 209, 118, 2, 84, 255, 124, 194, 166, 238, 54, 229, + 90, 26, 252, 33, 71, 103, 235, 82, 24, 22, 105, 13, 31, 80, + 216, 24, 126, 220, 236, 116, 117, 206, 38, 138, 248, 3, 28, 81, + 40, 126, 70, 46, 6, 145, 96, 228, 25, 199, 102, 167, 226, 244, + 42, 195, 253, 48, 44, 42, 107, 156, 207, 38, 155, 106, 146, 71, + 74, 70, 26, 51, 66, 152, 87, 168, 106, 84, 86, 175, 158, 118, + 112, 15, 239, 236, 118, 88, 57, 60, 51, 146, 207, 211, 15, 204, + 98, 73, 201, 68, 175, 16, 74, 68, 41, 17, 243, 108, 151, 37, + 189, 52, 87, 227, 121, 254, 77, 80, 161, 142, 17, 191, 131, 77, + 243, 202, 104, 208, 74, 41, 121, 189, 131, 65, 203, 91, 42, 127, + 4, 239, 21, 55, 199, 192, 102, 239, 158, 87, 11, 25, 97, 132, + 77, 183, 64, 31, 137, 114, 92, 254, 206, 214, 19, 219, 64, 40, + 158, 164, 99, 194, 143, 47, 104, 225, 80, 20, 102, 127, 143, 137, + 94, 51, 145, 49, 118, 127, 119, 87, 194, 187, 17, 15, 33, 199, + 100, 186, 70, 138, 75, 175, 148, 74, 107, 102, 98, 68, 173, 172, + 36, 110, 6, 89, 217, 160, 23, 12, 193, 130, 166, 91, 182, 38, + 20, 215, 9, 173, 187, 30, 226, 82, 11, 85, 191, 109, 6, 167, + 30, 216, 223, 68, 122, 128, 137, 16, 76, 61, 143, 26, 228, 74, + 146, 214, 93, 93, 109, 159, 203, 140, 214, 122, 96, 200, 230, 51, + 193, 171, 95, 119, 178, 247, 225, 88, 156, 130, 109, 52, 194, 41, + 51, 139, 200, 83, 199, 59, 212, 18, 52, 0, 184, 73, 26, 228, + 191, 208, 57, 45, 192, 102, 228, 208, 164, 248, 114, 138, 244, 78, + 46, 228, 212, 15, 60, 147, 176, 93, 106, 32, 198, 68, 142, 244, + 82, 55, 190, 165, 52, 57, 95, 163, 8, 189, 202, 155, 21, 16, + 172, 164, 189, 100, 250, 93, 156, 91, 225, 253, 193, 127, 118, 142, + 13, 119, 56, 236, 173, 126, 91, 205, 97, 206, 39, 49, 146, 222, + 186, 119, 64, 65, 32, 203, 224, 17, 61, 61, 232, 68, 57, 49, + 58, 145, 246, 48, 209, 45, 2, 135, 20, 35, 240, 164, 174, 9, + 220, 245, 126, 244, 254, 126, 158, 103, 187, 219, 109, 37, 72, 198, + 99, 38, 93, 69, 225, 5, 8, 12, 164, 225, 6, 118, 171, 7, + 240, 196, 25, 4, 23, 53, 65, 169, 210, 77, 242, 209, 107, 52, + 102, 110, 102, 191, 24, 53, 207, 189, 1, 91, 163, 237, 87, 190, + 28, 141, 47, 114, 147, 25, 222, 217, 39, 223, 74, 231, 176, 173, + 3, 70, 207, 214, 234, 112, 188, 41, 109, 116, 15, 248, 137, 220, + 243, 151, 186, 63, 181, 247, 226, 40, 226, 101, 143, 238, 142, 20, + 21, 106, 38, 93, 110, 41, 105, 90, 21, 149, 66, 55, 0, 115, + 119, 211, 166, 246, 218, 135, 36, 151, 170, 163, 173, 196, 214, 235, + 67, 132, 57, 236, 183, 156, 58, 60, 87, 185, 199, 220, 156, 110, + 172, 185, 173, 67, 146, 126, 72, 95, 141, 103, 126, 221, 248, 251, + 4, 248, 22, 119, 75, 204, 120, 224, 187, 138, 185, 68, 55, 80, + 83, 36, 23, 48, 133, 55, 200, 217, 249, 186, 215, 224, 88, 244, + 92, 200, 50, 252, 177, 163, 23, 179, 174, 95, 152, 51, 123, 77, + 204, 13, 200, 224, 30, 253, 136, 130, 56, 110, 92, 195, 72, 135, + 74, 190, 95, 235, 202, 45, 218, 45, 138, 152, 222, 33, 204, 137, + 22, 37, 133, 147, 178, 61, 236, 149, 24, 155, 88, 136, 137, 83, + 205, 59, 9, 66, 41, 86, 248, 16, 95, 159, 223, 26, 124, 32, + 182, 21, 44, 41, 223, 219, 195, 105, 136, 152, 212, 179, 250, 221, + 250, 123, 10, 216, 206, 216, 70, 132, 97, 251, 54, 20, 183, 140, + 207, 18, 132, 51, 187, 57, 69, 26, 208, 61, 34, 171, 199, 194, + 40, 139, 226, 139, 201, 250, 40, 221, 100, 139, 16, 76, 153, 41, + 163, 97, 46, 230, 2, 45, 237, 142, 26, 245, 33, 177, 65, 77, + 207, 202, 51, 144, 142, 139, 140, 131, 47, 231, 200, 38, 79, 249, + 215, 56, 203, 74, 197, 85, 121, 53, 88, 70, 230, 73, 55, 165, + 129, 24, 224, 171, 162, 185, 183, 221, 245, 176, 18, 65, 60, 145, + 125, 203, 104, 75, 50, 179, 73, 67, 46, 106, 51, 167, 11, 241, + 9, 97, 57, 107, 164, 186, 247, 150, 44, 132, 109, 71, 123, 191, + 135, 43, 147, 5, 70, 54, 230, 233, 27, 207, 128, 182, 101, 60, + 144, 107, 50, 190, 142, 67, 20, 185, 239, 152, 230, 10, 96, 127, + 90, 161, 179, 70, 102, 22, 161, 163, 217, 117, 242, 185, 143, 198, + 169, 118, 136, 137, 163, 231, 8, 65, 231, 193, 66, 189, 84, 83, + 148, 86, 125, 151, 81, 64, 237, 128, 2, 211, 28, 167, 156, 129, + 181, 165, 137, 136, 147, 36, 52, 157, 51, 219, 152, 229, 121, 155, + 45, 87, 15, 166, 90, 146, 68, 170, 202, 125, 4, 197, 2, 156, + 216, 91, 106, 24, 30, 196, 136, 129, 96, 172, 226, 105, 29, 235, + 253, 236, 209, 105, 85, 51, 226, 189, 122, 2, 17, 24, 172, 180, + 55, 49, 44, 119, 129, 57, 31, 81, 232, 150, 211, 37, 37, 5, + 115, 188, 13, 185, 246, 232, 245, 74, 115, 225, 207, 203, 33, 59, + 94, 252, 14, 229, 73, 156, 185, 254, 40, 42, 228, 149, 211, 165, + 107, 61, 55, 94, 240, 83, 200, 171, 250, 222, 52, 36, 117, 42, + 167, 242, 132, 103, 37, 57, 212, 218, 53, 62, 215, 166, 163, 88, + 17, 70, 133, 95, 235, 209, 6, 235, 34, 186, 69, 61, 225, 143, + 228, 200, 44, 178, 166, 213, 32, 20, 18, 56, 123, 172, 194, 78, + 0, 67, 254, 199, 119, 57, 8, 59, 24, 101, 165, 158, 12, 31, + 20, 52, 64, 22, 0, 173, 113, 86, 240, 124, 123, 32, 241, 174, + 51, 218, 238, 142, 109, 240, 197, 19, 93, 226, 221, 24, 30, 206, + 149, 155, 162, 63, 82, 114, 244, 32, 43, 102, 104, 8, 171, 251, + 8, 127, 127, 139, 190, 161, 132, 85, 10, 224, 191, 137, 248, 146, + 107, 155, 208, 179, 10, 67, 47, 108, 244, 74, 134, 165, 235, 226, + 86, 203, 232, 137, 189, 112, 221, 65, 246, 146, 190, 16, 24, 242, + 97, 140, 220, 119, 117, 223, 78, 62, 133, 10, 76, 48, 16, 190, + 17, 53, 10, 152, 104, 189, 71, 99, 25, 195, 93, 222, 179, 106, + 51, 127, 186, 104, 251, 13, 68, 59, 119, 177, 30, 2, 120, 242, + 25, 140, 0, 10, 34, 216, 217, 147, 245, 95, 122, 241, 243, 216, + 103, 111, 222, 202, 173, 117, 4, 176, 124, 69, 167, 52, 123, 19, + 133, 238, 150, 123, 149, 239, 189, 25, 128, 239, 74, 43, 246, 170, + 229, 132, 76, 136, 196, 53, 0, 44, 191, 232, 106, 35, 171, 26, + 50, 73, 89, 102, 240, 65, 235, 180, 29, 137, 60, 68, 105, 154, + 143, 58, 255, 57, 179, 118, 231, 199, 186, 161, 8, 165, 99, 71, + 89, 189, 237, 37, 202, 33, 140, 9, 102, 220, 155, 90, 89, 131, + 143, 190, 91, 204, 82, 137, 220, 29, 1, 237, 44, 53, 215, 202, + 123, 88, 61, 189, 68, 2, 65, 174, 105, 14, 164, 155, 233, 246, + 18, 236, 83, 126, 10, 152, 88, 131, 97, 96, 63, 136, 113, 248, + 193, 106, 129, 153, 164, 143, 64, 116, 195, 60, 201, 28, 72, 189, + 55, 55, 192, 92, 91, 244, 28, 127, 142, 217, 151, 99, 136, 140, + 133, 30, 237, 234, 48, 183, 183, 44, 242, 146, 169, 229, 130, 202, + 117, 176, 0, 234, 138, 162, 51, 31, 207, 97, 148, 90, 182, 172, + 152, 79, 156, 122, 67, 75, 170, 14, 6, 103, 43, 165, 126, 64, + 37, 223, 189, 90, 69, 15, 231, 197, 85, 25, 107, 119, 92, 74, + 179, 150, 230, 196, 57, 212, 168, 146, 235, 252, 96, 50, 150, 210, + 97, 199, 59, 46, 147, 43, 207, 67, 190, 68, 219, 131, 33, 105, + 148, 192, 237, 25, 15, 42, 43, 100, 26, 42, 84, 166, 3, 197, + 206, 31, 224, 46, 32, 34, 204, 4, 254, 242, 93, 11, 178, 202, + 194, 105, 57, 10, 92, 39, 113, 227, 120, 168, 230, 244, 180, 159, + 240, 119, 121, 185, 197, 188, 77, 191, 22, 85, 232, 60, 173, 52, + 6, 37, 66, 48, 129, 150, 255, 242, 254, 68, 113, 72, 178, 68, + 174, 248, 205, 138, 26, 201, 229, 243, 136, 182, 85, 145, 153, 60, + 106, 67, 230, 90, 149, 194, 216, 60, 107, 207, 254, 140, 234, 123, + 176, 46, 20, 46, 9, 56, 226, 32, 114, 129, 5, 108, 38, 148, + 219, 192, 50, 43, 140, 230, 188, 24, 121, 211, 57, 184, 193, 86, + 92, 8, 196, 214, 224, 15, 98, 112, 105, 238, 57, 82, 176, 169, + 142, 140, 154, 179, 113, 79, 73, 177, 69, 16, 108, 114, 158, 144, + 38, 205, 36, 239, 37, 208, 27, 53, 142, 101, 139, 198, 49, 52, + 192, 114, 219, 253, 71, 240, 160, 238, 114, 193, 128, 13, 203, 43, + 119, 175, 235, 66, 156, 247, 121, 178, 119, 50, 196, 213, 63, 143, + 85, 52, 187, 83, 181, 136, 66, 164, 29, 128, 167, 15, 240, 206, + 190, 42, 104, 137, 21, 159, 64, 179, 238, 220, 47, 189, 118, 75, + 174, 140, 208, 172, 204, 176, 245, 11, 223, 2, 165, 158, 60, 169, + 54, 150, 112, 184, 136, 250, 57, 36, 175, 51, 64, 252, 116, 189, + 202, 178, 146, 49, 163, 138, 110, 21, 88, 195, 36, 197, 202, 233, + 151, 115, 138, 135, 94, 46, 155, 84, 74, 114, 140, 74, 85, 64, + 159, 39, 170, 194, 146, 112, 35, 119, 19, 246, 226, 38, 185, 243, + 142, 92, 246, 176, 209, 84, 127, 207, 159, 91, 48, 100, 9, 17, + 143, 188, 239, 228, 254, 123, 30, 177, 242, 138, 177, 153, 190, 199, + 205, 105, 78, 202, 180, 91, 25, 68, 102, 38, 189, 208, 172, 32, + 115, 77, 75, 117, 196, 92, 86, 196, 183, 125, 80, 0, 43, 110, + 181, 169, 110, 250, 246, 69, 102, 52, 13, 129, 248, 170, 217, 23, + 231, 243, 16, 116, 197, 67, 201, 33, 217, 207, 103, 204, 27, 19, + 9, 58, 22, 7, 167, 8, 31, 140, 198, 254, 112, 174, 219, 246, + 99, 244, 38, 72, 80, 69, 54, 70, 240, 83, 41, 150, 212, 248, + 81, 167, 27, 48, 166, 194, 139, 214, 101, 80, 172, 94, 73, 7, + 174, 79, 43, 118, 105, 240, 36, 2, 96, 221, 106, 104, 31, 180, + 208, 163, 121, 96, 201, 130, 4, 152, 199, 1, 39, 206, 240, 125, + 226, 125, 11, 208, 243, 216, 198, 235, 101, 62, 164, 214, 163, 178, + 229, 193, 195, 216, 59, 153, 224, 10, 6, 82, 5, 59, 153, 155, + 160, 140, 96, 78, 172, 170, 160, 76, 17, 14, 118, 251, 204, 55, + 30, 46, 170, 174, 193, 248, 20, 172, 2, 29, 4, 190, 241, 5, + 75, 135, 133, 110, 255, 51, 71, 128, 89, 79, 158, 226, 252, 99, + 37, 132, 174, 112, 85, 160, 98, 140, 126, 232, 205, 198, 68, 178, + 29, 252, 23, 42, 210, 196, 33, 191, 139, 144, 148, 217, 199, 227, + 38, 75, 242, 181, 16, 115, 220, 33, 160, 77, 70, 79, 95, 145, + 25, 228, 124, 174, 21, 190, 218, 143, 149, 244, 59, 75, 100, 60, + 230, 233, 15, 3, 188, 210, 139, 233, 135, 127, 186, 139, 200, 252, + 228, 48, 9, 81, 52, 254, 44, 170, 37, 245, 118, 50, 115, 30, + 148, 117, 127, 177, 119, 166, 146, 249, 74, 80, 24, 187, 68, 80, + 143, 46, 62, 60, 111, 226, 46, 88, 7, 204, 188, 177, 98, 222, + 38, 29, 134, 191, 55, 92, 35, 250, 106, 85, 224, 186, 20, 14, + 65, 179, 35, 214, 241, 38, 8, 233, 56, 201, 33, 87, 122, 3, + 181, 143, 8, 35, 181, 199, 101, 154, 163, 196, 57, 162, 67, 215, + 176, 95, 12, 109, 25, 175, 27, 142, 209, 185, 72, 216, 163, 157, + 42, 155, 54, 231, 145, 200, 178, 243, 78, 29, 183, 131, 147, 97, + 162, 164, 74, 212, 184, 171, 89, 215, 182, 74, 182, 52, 231, 224, + 164, 61, 165, 80, 249, 218, 141, 34, 83, 234, 90, 157, 139, 124, + 112, 91, 24, 12, 165, 89, 53, 11, 143, 145, 174, 79, 32, 123, + 128, 110, 8, 127, 110, 83, 200, 207, 78, 118, 138, 138, 124, 236, + 212, 189, 50, 27, 195, 69, 7, 96, 242, 114, 45, 100, 91, 10, + 148, 172, 176, 243, 239, 201, 204, 185, 15, 125, 189, 227, 245, 52, + 168, 58, 160, 98, 155, 175, 15, 121, 182, 248, 155, 251, 137, 105, + 209, 109, 51, 44, 12, 116, 15, 159, 237, 228, 69, 220, 172, 207, + 13, 1, 209, 133, 24, 156, 250, 182, 231, 31, 230, 100, 70, 120, + 215, 200, 118, 15, 49, 73, 39, 249, 118, 40, 214, 23, 48, 141, + 162, 8, 148, 2, 16, 32, 171, 138, 177, 255, 180, 94, 247, 62, + 121, 56, 152, 255, 114, 26, 44, 200, 98, 247, 204, 104, 2, 250, + 85, 77, 61, 207, 196, 135, 103, 52, 25, 248, 121, 57, 14, 242, + 170, 148, 252, 73, 210, 134, 8, 125, 225, 43, 61, 97, 176, 105, + 216, 241, 2, 46, 161, 219, 85, 255, 68, 98, 217, 59, 20, 188, + 97, 136, 9, 239, 164, 62, 186, 90, 58, 168, 102, 167, 131, 119, + 217, 130, 156, 45, 197, 204, 105, 27, 112, 93, 97, 196, 40, 179, + 129, 209, 119, 31, 173, 82, 210, 52, 184, 116, 228, 111, 24, 238, + 103, 184, 207, 241, 24, 5, 242, 142, 64, 209, 74, 27, 236, 59, + 25, 18, 182, 145, 128, 214, 110, 4, 200, 117, 107, 134, 15, 158, + 107, 113, 121, 102, 35, 90, 103, 210, 107, 163, 26, 237, 237, 154, + 42, 31, 168, 87, 11, 119, 56, 55, 47, 197, 88, 84, 27, 25, + 170, 30, 24, 6, 185, 112, 180, 76, 245, 133, 90, 81, 215, 48, + 73, 63, 247, 82, 44, 36, 65, 85, 137, 138, 78, 209, 176, 99, + 89, 142, 167, 107, 120, 58, 250, 233, 42, 23, 189, 223, 252, 109, + 242, 204, 56, 124, 46, 221, 246, 237, 18, 21, 113, 52, 126, 188, + 213, 158, 229, 120, 226, 78, 222, 230, 1, 32, 39, 133, 129, 75, + 5, 138, 188, 245, 105, 164, 37, 40, 232, 103, 136, 157, 141, 3, + 174, 187, 151, 74, 214, 196, 2, 250, 225, 6, 237, 223, 160, 238, + 107, 157, 188, 172, 56, 238, 28, 146, 34, 11, 187, 162, 103, 190, + 161, 218, 159, 249, 33, 107, 126, 82, 73, 92, 158, 5, 112, 3, + 15, 132, 239, 58, 44, 106, 8, 97, 4, 105, 94, 83, 135, 213, + 83, 55, 197, 47, 67, 235, 4, 120, 90, 222, 169, 220, 173, 46, + 253, 76, 32, 50, 37, 112, 180, 203, 249, 19, 44, 92, 16, 126, + 56, 146, 112, 24, 197, 100, 220, 55, 216, 83, 51, 137, 218, 54, + 4, 242, 193, 245, 116, 3, 110, 127, 113, 130, 30, 109, 17, 95, + 191, 44, 157, 80, 157, 49, 21, 252, 81, 60, 182, 229, 184, 41, + 18, 179, 162, 46, 218, 235, 198, 148, 103, 13, 65, 176, 235, 6, + 71, 140, 1, 145, 98, 233, 85, 180, 235, 43, 177, 29, 250, 60, + 250, 105, 85, 10, 211, 60, 79, 214, 247, 206, 91, 4, 76, 11, + 135, 6, 52, 114, 4, 227, 190, 80, 52, 4, 94, 80, 108, 244, + 21, 168, 149, 16, 190, 105, 163, 200, 196, 75, 174, 178, 252, 69, + 55, 198, 146, 58, 194, 28, 41, 211, 121, 201, 18, 247, 195, 81, + 26, 108, 68, 227, 5, 92, 208, 22, 207, 191, 11, 80, 161, 224, + 244, 226, 8, 33, 237, 4, 219, 176, 75, 78, 164, 249, 174, 71, + 69, 7, 24, 104, 164, 206, 58, 163, 30, 238, 238, 181, 176, 70, + 53, 212, 81, 230, 37, 223, 183, 224, 250, 254, 190, 254, 169, 161, + 114, 129, 92, 10, 155, 157, 235, 139, 44, 243, 51, 97, 80, 54, + 29, 187, 123, 149, 4, 91, 40, 75, 104, 198, 49, 103, 25, 126, + 104, 91, 253, 226, 6, 156, 168, 0, 121, 23, 205, 174, 179, 63, + 128, 62, 98, 6, 206, 158, 155, 74, 179, 140, 151, 159, 29, 58, + 196, 103, 220, 235, 157, 242, 181, 24, 31, 132, 54, 218, 149, 119, + 95, 66, 133, 185, 13, 112, 53, 130, 174, 216, 250, 217, 73, 221, + 52, 34, 148, 87, 169, 160, 154, 86, 38, 104, 170, 22, 13, 35, + 177, 115, 213, 140, 228, 226, 122, 208, 220, 38, 104, 71, 64, 166, + 245, 195, 90, 9, 200, 80, 225, 62, 164, 32, 156, 206, 72, 175, + 173, 238, 228, 70, 118, 5, 255, 139, 20, 158, 195, 172, 207, 248, + 245, 229, 58, 236, 75, 22, 54, 113, 156, 237, 180, 226, 175, 211, + 237, 155, 35, 184, 195, 137, 26, 147, 77, 141, 43, 109, 249, 129, + 216, 57, 184, 114, 158, 229, 213, 118, 118, 163, 92, 188, 25, 136, + 110, 127, 232, 254, 152, 125, 207, 230, 111, 164, 139, 82, 231, 161, + 227, 161, 215, 247, 30, 95, 39, 20, 227, 72, 168, 182, 189, 254, + 50, 13, 37, 147, 49, 253, 88, 92, 19, 253, 80, 6, 82, 84, + 210, 227, 235, 8, 225, 101, 1, 223, 80, 107, 203, 79, 199, 153, + 240, 2, 76, 130, 93, 80, 192, 33, 57, 10, 255, 105, 227, 1, + 143, 109, 241, 205, 54, 107, 225, 219, 185, 188, 223, 60, 61, 101, + 129, 191, 187, 223, 44, 65, 24, 31, 214, 50, 99, 76, 86, 7, + 96, 48, 249, 191, 117, 176, 1, 157, 243, 78, 128, 98, 205, 57, + 109, 49, 154, 16, 250, 150, 135, 83, 0, 94, 29, 62, 246, 83, + 191, 166, 186, 141, 222, 45, 153, 252, 114, 50, 192, 186, 206, 157, + 23, 83, 220, 197, 249, 225, 75, 29, 171, 160, 104, 40, 84, 155, + 106, 133, 151, 174, 100, 209, 147, 117, 162, 220, 76, 54, 153, 131, + 221, 225, 2, 254, 231, 253, 91, 180, 13, 230, 138, 51, 253, 3, + 95, 131, 56, 244, 182, 168, 101, 248, 22, 20, 177, 86, 199, 241, + 93, 211, 40, 210, 217, 105, 172, 181, 55, 239, 106, 30, 145, 71, + 145, 132, 237, 5, 96, 219, 47, 32, 49, 248, 214, 227, 191, 5, + 199, 198, 154, 32, 168, 80, 216, 9, 162, 97, 214, 213, 86, 60, + 250, 201, 42, 137, 38, 118, 38, 254, 59, 56, 225, 73, 230, 206, + 27, 70, 165, 234, 80, 14, 62, 7, 105, 243, 225, 175, 75, 160, + 243, 126, 248, 232, 19, 44, 8, 239, 89, 170, 181, 117, 64, 244, + 189, 130, 202, 72, 28, 103, 130, 57, 120, 42, 203, 228, 205, 98, + 70, 86, 101, 58, 53, 142, 211, 235, 121, 184, 252, 229, 189, 105, + 198, 8, 162, 79, 155, 224, 0, 70, 36, 144, 157, 136, 54, 94, + 123, 120, 120, 33, 219, 39, 239, 3, 162, 202, 97, 230, 6, 231, + 196, 202, 221, 56, 142, 13, 93, 119, 7, 183, 214, 204, 188, 32, + 142, 86, 239, 252, 216, 208, 166, 111, 181, 108, 81, 5, 213, 48, + 120, 50, 217, 166, 172, 134, 73, 136, 214, 172, 156, 128, 7, 77, + 124, 133, 174, 114, 179, 18, 245, 141, 233, 155, 180, 9, 13, 249, + 145, 101, 196, 250, 165, 144, 99, 211, 88, 189, 35, 215, 37, 86, + 92, 158, 144, 99, 21, 87, 37, 123, 166, 164, 17, 193, 183, 111, + 139, 224, 58, 181, 43, 146, 238, 193, 22, 145, 84, 196, 45, 212, + 201, 205, 9, 48, 177, 230, 107, 15, 145, 219, 226, 240, 148, 250, + 99, 153, 164, 40, 214, 6, 107, 202, 196, 11, 16, 103, 240, 220, + 14, 210, 188, 34, 69, 69, 5, 243, 157, 1, 68, 177, 137, 35, + 218, 131, 236, 225, 107, 182, 200, 127, 99, 242, 70, 81, 227, 8, + 131, 12, 181, 183, 114, 63, 173, 169, 187, 205, 194, 100, 62, 87, + 211, 128, 230, 66, 8, 208, 85, 9, 213, 226, 221, 39, 127, 194, + 58, 164, 129, 49, 12, 214, 191, 161, 109, 115, 190, 253, 117, 153, + 151, 158, 71, 236, 161, 172, 236, 64, 244, 14, 215, 157, 6, 149, + 175, 205, 107, 29, 213, 192, 215, 69, 164, 181, 145, 104, 67, 253, + 16, 24, 247, 124, 135, 56, 207, 167, 173, 191, 8, 123, 151, 73, + 192, 93, 115, 17, 59, 218, 151, 149, 37, 95, 24, 151, 193, 207, + 92, 214, 78, 122, 41, 24, 91, 196, 230, 237, 252, 54, 126, 238, + 159, 33, 128, 21, 16, 112, 0, 100, 157, 213, 181, 14, 148, 210, + 48, 163, 90, 142, 84, 30, 29, 178, 214, 230, 66, 177, 167, 136, + 129, 66, 212, 89, 53, 3, 165, 2, 57, 126, 118, 223, 18, 219, + 6, 65, 31, 187, 70, 189, 62, 145, 121, 117, 94, 78, 2, 207, + 252, 19, 64, 209, 137, 15, 219, 95, 46, 85, 165, 210, 235, 142, + 240, 14, 19, 41, 242, 210, 173, 149, 15, 145, 245, 173, 178, 102, + 192, 24, 65, 226, 222, 144, 141, 190, 81, 32, 164, 14, 240, 154, + 114, 139, 242, 8, 192, 19, 161, 147, 2, 40, 68, 63, 226, 192, + 128, 173, 50, 246, 227, 231, 28, 165, 222, 78, 39, 97, 254, 74, + 83, 22, 35, 147, 5, 142, 150, 42, 84, 199, 101, 56, 142, 235, + 144, 97, 15, 139, 83, 111, 93, 34, 91, 118, 203, 215, 102, 8, + 152, 176, 46, 196, 128, 29, 231, 121, 79, 3, 9, 239, 9, 38, + 28, 45, 116, 250, 246, 249, 183, 217, 244, 138, 30, 49, 102, 87, + 187, 137, 236, 230, 181, 137, 71, 218, 19, 111, 208, 194, 138, 148, + 23, 56, 184, 248, 64, 3, 103, 45, 100, 45, 32, 170, 40, 78, + 72, 115, 191, 32, 195, 52, 115, 93, 142, 190, 220, 186, 247, 25, + 134, 228, 135, 146, 101, 178, 72, 252, 225, 144, 132, 10, 98, 110, + 167, 184, 160, 79, 78, 11, 151, 183, 225, 89, 178, 190, 75, 10, + 109, 216, 249, 112, 49, 80, 79, 101, 115, 136, 135, 230, 188, 155, + 12, 132, 7, 14, 53, 66, 11, 75, 86, 199, 245, 31, 120, 250, + 71, 177, 63, 91, 238, 178, 98, 98, 64, 205, 180, 122, 117, 169, + 249, 162, 51, 254, 80, 119, 118, 82, 221, 188, 67, 71, 216, 63, + 192, 235, 207, 201, 32, 73, 14, 111, 55, 87, 131, 219, 42, 164, + 255, 52, 53, 235, 183, 188, 246, 150, 196, 201, 2, 116, 21, 2, + 133, 185, 235, 163, 83, 174, 66, 98, 117, 197, 99, 71, 73, 84, + 142, 17, 186, 217, 9, 213, 2, 63, 217, 196, 67, 219, 59, 119, + 236, 252, 240, 162, 26, 115, 237, 175, 215, 28, 138, 192, 197, 107, + 201, 201, 217, 67, 77, 78, 33, 253, 242, 218, 234, 236, 116, 22, + 90, 45, 244, 96, 224, 208, 190, 237, 184, 39, 109, 53, 232, 156, + 230, 191, 52, 173, 101, 72, 208, 242, 243, 209, 80, 0, 17, 150, + 167, 213, 221, 143, 56, 24, 18, 117, 255, 150, 87, 37, 19, 200, + 160, 173, 33, 244, 237, 184, 234, 253, 205, 245, 206, 34, 96, 175, + 43, 91, 21, 56, 56, 77, 27, 47, 21, 132, 98, 200, 51, 159, + 184, 88, 253, 22, 201, 80, 39, 137, 79, 220, 168, 145, 54, 190, + 201, 44, 245, 86, 23, 210, 27, 144, 105, 183, 129, 107, 251, 153, + 46, 233, 68, 196, 121, 31, 205, 109, 128, 216, 44, 20, 54, 142, + 43, 123, 22, 111, 246, 216, 95, 179, 154, 160, 93, 57, 82, 131, + 91, 109, 0, 73, 18, 114, 235, 191, 44, 63, 142, 214, 235, 151, + 121, 176, 48, 186, 244, 163, 34, 240, 156, 158, 184, 68, 8, 74, + 16, 217, 197, 195, 68, 122, 8, 134, 31, 189, 96, 80, 25, 164, + 205, 141, 118, 80, 42, 247, 44, 210, 32, 53, 194, 88, 140, 198, + 114, 132, 215, 19, 70, 177, 236, 148, 64, 23, 27, 151, 186, 149, + 100, 190, 190, 208, 34, 163, 192, 187, 170, 66, 25, 132, 79, 108, + 162, 188, 130, 98, 80, 149, 21, 177, 248, 219, 121, 109, 218, 196, + 82, 201, 90, 252, 150, 249, 186, 226, 94, 116, 205, 155, 241, 224, + 248, 104, 240, 97, 130, 162, 59, 43, 206, 50, 35, 152, 134, 60, + 242, 211, 195, 95, 162, 254, 55, 208, 142, 159, 138, 52, 94, 82, + 35, 25, 163, 92, 5, 248, 237, 37, 103, 70, 232, 206, 4, 151, + 220, 1, 7, 178, 15, 155, 29, 166, 79, 68, 24, 206, 224, 111, + 153, 44, 97, 190, 230, 71, 146, 185, 160, 72, 251, 195, 128, 12, + 58, 185, 235, 83, 222, 76, 204, 57, 20, 72, 210, 161, 98, 38, + 116, 86, 235, 106, 207, 31, 217, 123, 106, 187, 179, 164, 84, 44, + 13, 80, 184, 194, 86, 11, 203, 174, 168, 164, 153, 178, 203, 47, + 109, 124, 247, 129, 115, 97, 92, 147, 145, 68, 45, 187, 148, 45, + 24, 46, 134, 191, 175, 75, 114, 129, 92, 151, 18, 10, 206, 45, + 142, 224, 146, 118, 124, 102, 208, 88, 63, 76, 242, 47, 207, 244, + 98, 224, 171, 98, 115, 58, 131, 80, 38, 178, 186, 105, 132, 135, + 165, 127, 228, 120, 226, 226, 162, 6, 166, 43, 57, 134, 192, 194, + 76, 109, 171, 187, 70, 180, 137, 242, 138, 21, 123, 230, 47, 231, + 59, 28, 179, 128, 88, 80, 190, 68, 27, 13, 235, 30, 61, 17, + 81, 116, 147, 226, 186, 40, 186, 115, 114, 157, 185, 154, 76, 161, + 5, 159, 163, 96, 245, 179, 199, 235, 147, 196, 101, 5, 170, 102, + 108, 137, 201, 94, 86, 44, 84, 97, 176, 34, 244, 95, 139, 125, + 184, 136, 83, 116, 143, 241, 173, 244, 184, 14, 59, 10, 233, 149, + 245, 206, 255, 111, 141, 186, 140, 51, 193, 29, 150, 92, 118, 166, + 50, 193, 102, 125, 22, 147, 201, 35, 245, 74, 150, 77, 128, 235, + 24, 24, 212, 89, 98, 29, 123, 211, 129, 88, 4, 38, 200, 255, + 97, 115, 253, 86, 119, 245, 11, 197, 188, 70, 139, 220, 186, 137, + 148, 74, 64, 215, 39, 150, 47, 196, 208, 238, 107, 95, 198, 51, + 145, 138, 2, 3, 48, 115, 120, 167, 4, 151, 71, 148, 41, 62, + 225, 93, 146, 223, 3, 181, 81, 163, 139, 215, 94, 169, 64, 251, + 63, 90, 84, 59, 68, 96, 174, 53, 24, 246, 167, 250, 52, 52, + 94, 161, 138, 1, 46, 184, 80, 165, 164, 13, 100, 155, 128, 177, + 219, 56, 83, 15, 201, 173, 110, 185, 157, 1, 81, 120, 113, 5, + 34, 173, 61, 196, 63, 75, 52, 10, 247, 238, 158, 133, 239, 180, + 109, 157, 207, 94, 227, 168, 92, 208, 99, 82, 231, 224, 110, 180, + 155, 47, 220, 74, 72, 60, 223, 245, 86, 157, 156, 194, 123, 49, + 90, 199, 153, 244, 136, 11, 77, 71, 207, 219, 15, 36, 155, 171, + 217, 222, 223, 51, 225, 33, 175, 178, 97, 198, 233, 53, 113, 35, + 12, 169, 107, 176, 196, 190, 203, 41, 64, 41, 185, 67, 135, 17, + 236, 141, 38, 7, 29, 240, 5, 161, 90, 146, 134, 111, 93, 53, + 56, 108, 165, 56, 65, 66, 247, 47, 186, 170, 67, 152, 32, 160, + 7, 143, 47, 32, 153, 202, 170, 65, 159, 86, 20, 249, 186, 78, + 235, 208, 110, 216, 228, 38, 218, 14, 34, 16, 241, 139, 39, 172, + 0, 198, 196, 149, 83, 135, 140, 113, 218, 21, 235, 5, 232, 4, + 65, 136, 47, 73, 156, 253, 28, 163, 210, 203, 192, 36, 195, 242, + 41, 51, 198, 217, 28, 254, 4, 43, 96, 255, 122, 242, 100, 47, + 241, 146, 252, 32, 203, 8, 173, 32, 6, 4, 55, 158, 33, 172, + 131, 63, 107, 233, 184, 210, 36, 66, 96, 71, 214, 92, 213, 16, + 144, 185, 167, 222, 233, 128, 167, 18, 232, 1, 161, 151, 203, 52, + 116, 45, 184, 205, 6, 252, 48, 110, 101, 178, 225, 112, 140, 0, + 206, 44, 151, 104, 88, 216, 25, 128, 211, 226, 158, 66, 23, 0, + 47, 226, 81, 198, 131, 231, 58, 5, 71, 110, 165, 60, 92, 224, + 217, 250, 65, 83, 184, 11, 71, 221, 246, 17, 56, 138, 221, 75, + 220, 165, 10, 6, 226, 54, 216, 44, 108, 228, 210, 159, 16, 115, + 99, 73, 94, 252, 157, 234, 94, 98, 195, 213, 176, 198, 10, 27, + 122, 105, 54, 70, 245, 83, 186, 196, 147, 28, 36, 82, 49, 38, + 153, 41, 244, 253, 97, 48, 144, 95, 178, 49, 223, 170, 121, 9, + 42, 191, 76, 57, 168, 249, 139, 228, 57, 108, 144, 10, 121, 34, + 207, 210, 24, 179, 16, 140, 83, 205, 205, 124, 39, 86, 235, 166, + 184, 167, 45, 199, 136, 1, 143, 28, 157, 62, 44, 168, 49, 173, + 127, 149, 190, 0, 231, 209, 16, 251, 237, 232, 84, 119, 226, 154, + 56, 16, 253, 197, 81, 172, 182, 175, 133, 167, 215, 6, 86, 74, + 157, 60, 70, 52, 250, 154, 70, 59, 92, 204, 180, 4, 148, 185, + 131, 155, 238, 138, 142, 160, 197, 111, 117, 159, 162, 156, 237, 80, + 240, 101, 167, 42, 92, 213, 53, 11, 71, 109, 208, 171, 126, 101, + 4, 137, 146, 176, 82, 222, 79, 252, 112, 93, 48, 4, 102, 171, + 139, 186, 25, 225, 252, 162, 160, 153, 174, 182, 137, 83, 211, 9, + 52, 197, 147, 146, 160, 47, 13, 123, 143, 44, 146, 233, 131, 197, + 76, 138, 233, 1, 44, 129, 132, 54, 74, 188, 17, 141, 186, 172, + 199, 98, 38, 39, 81, 194, 99, 160, 164, 185, 5, 242, 162, 61, + 152, 106, 207, 23, 211, 36, 158, 54, 94, 123, 161, 72, 176, 67, + 56, 103, 121, 157, 75, 5, 215, 82, 216, 77, 11, 171, 252, 228, + 152, 13, 72, 92, 137, 21, 122, 88, 167, 141, 20, 66, 92, 50, + 236, 32, 101, 89, 120, 35, 179, 172, 103, 48, 32, 49, 36, 254, + 96, 201, 192, 56, 53, 163, 174, 49, 131, 102, 74, 239, 252, 108, + 13, 170, 34, 33, 206, 204, 184, 87, 56, 177, 179, 251, 37, 221, + 66, 224, 166, 224, 250, 32, 10, 115, 63, 22, 242, 37, 109, 30, + 179, 222, 198, 91, 177, 14, 35, 132, 130, 92, 81, 149, 249, 248, + 96, 127, 57, 153, 10, 230, 87, 89, 56, 34, 12, 234, 89, 4, + 19, 27, 50, 166, 69, 68, 116, 67, 137, 6, 170, 162, 55, 201, + 194, 99, 140, 199, 91, 204, 51, 55, 106, 17, 185, 136, 220, 28, + 82, 36, 65, 170, 108, 187, 241, 180, 189, 98, 31, 109, 143, 67, + 186, 65, 3, 73, 145, 88, 130, 118, 100, 144, 156, 124, 143, 41, + 140, 197, 28, 27, 235, 33, 103, 240, 102, 44, 183, 137, 237, 186, + 16, 225, 210, 4, 181, 103, 254, 238, 87, 142, 223, 47, 86, 10, + 206, 145, 136, 188, 232, 167, 71, 47, 227, 92, 88, 106, 241, 38, + 22, 241, 212, 70, 106, 245, 54, 164, 221, 135, 99, 227, 254, 248, + 246, 200, 94, 59, 141, 39, 52, 71, 234, 30, 52, 56, 199, 119, + 48, 133, 207, 44, 174, 252, 60, 104, 54, 219, 137, 12, 5, 86, + 54, 143, 144, 88, 13, 23, 91, 34, 188, 186, 94, 118, 198, 150, + 252, 85, 156, 182, 158, 189, 75, 226, 158, 99, 0, 111, 128, 20, + 226, 5, 0, 207, 50, 83, 17, 15, 41, 26, 94, 24, 24, 122, + 196, 243, 176, 24, 44, 147, 10, 140, 205, 205, 227, 21, 177, 87, + 248, 185, 126, 96, 21, 162, 51, 55, 238, 154, 121, 252, 123, 135, + 6, 76, 171, 242, 28, 118, 35, 212, 9, 145, 168, 16, 229, 146, + 252, 186, 203, 99, 244, 211, 153, 124, 81, 60, 101, 238, 130, 209, + 240, 43, 204, 230, 87, 177, 96, 237, 105, 81, 127, 75, 59, 215, + 218, 2, 177, 147, 221, 238, 70, 86, 198, 5, 190, 170, 99, 174, + 182, 175, 37, 203, 30, 74, 149, 17, 119, 197, 153, 145, 68, 204, + 156, 57, 196, 115, 7, 154, 108, 209, 180, 24, 124, 139, 120, 0, + 94, 201, 82, 192, 95, 136, 82, 221, 3, 104, 69, 123, 53, 220, + 34, 228, 74, 50, 3, 54, 177, 194, 216, 205, 13, 137, 205, 51, + 104, 85, 148, 95, 13, 30, 106, 144, 52, 220, 105, 254, 157, 213, + 243, 58, 246, 138, 103, 116, 97, 49, 144, 108, 13, 146, 225, 164, + 251, 174, 135, 128, 249, 255, 21, 5, 113, 148, 109, 232, 230, 243, + 40, 236, 71, 163, 111, 22, 25, 100, 140, 49, 34, 162, 110, 78, + 116, 110, 153, 19, 97, 148, 27, 116, 96, 120, 128, 145, 19, 193, + 97, 254, 160, 117, 34, 197, 42, 240, 203, 34, 29, 170, 134, 247, + 61, 168, 60, 38, 77, 52, 94, 55, 178, 27, 22, 3, 106, 181, + 151, 175, 181, 95, 10, 69, 143, 159, 193, 230, 27, 217, 49, 246, + 63, 4, 100, 28, 150, 43, 137, 90, 214, 115, 61, 115, 134, 165, + 244, 203, 129, 30, 109, 4, 242, 180, 190, 200, 90, 134, 213, 7, + 193, 94, 241, 25, 92, 116, 250, 148, 106, 192, 116, 159, 34, 183, + 19, 212, 119, 114, 91, 252, 204, 255, 70, 184, 8, 111, 249, 204, + 61, 198, 131, 131, 170, 231, 241, 108, 146, 194, 233, 100, 23, 42, + 23, 13, 194, 177, 246, 68, 251, 236, 113, 179, 255, 214, 188, 74, + 128, 176, 90, 144, 94, 168, 177, 44, 14, 13, 81, 111, 247, 143, + 186, 186, 41, 180, 27, 60, 202, 249, 4, 208, 204, 75, 230, 51, + 77, 238, 17, 238, 69, 0, 183, 158, 32, 151, 85, 28, 43, 92, + 194, 187, 255, 169, 183, 224, 15, 13, 214, 12, 118, 2, 101, 235, + 38, 243, 220, 187, 93, 91, 87, 97, 127, 246, 171, 72, 61, 53, + 253, 204, 195, 206, 73, 74, 229, 130, 78, 34, 170, 15, 205, 178, + 160, 204, 194, 118, 28, 128, 25, 87, 56, 174, 42, 74, 186, 226, + 241, 55, 189, 25, 243, 108, 248, 133, 80, 48, 229, 60, 116, 92, + 49, 143, 217, 229, 164, 197, 164, 225, 0, 203, 253, 103, 120, 40, + 172, 50, 216, 158, 129, 233, 246, 199, 84, 80, 55, 44, 149, 186, + 224, 127, 247, 254, 101, 141, 13, 41, 134, 68, 15, 172, 38, 68, + 194, 157, 10, 25, 152, 156, 255, 107, 2, 70, 222, 164, 118, 217, + 248, 190, 187, 74, 45, 36, 37, 248, 143, 66, 23, 57, 205, 147, + 53, 252, 154, 73, 147, 248, 126, 70, 151, 145, 26, 119, 202, 72, + 218, 179, 233, 67, 237, 150, 14, 97, 158, 212, 86, 238, 174, 255, + 207, 171, 103, 122, 145, 210, 226, 41, 11, 240, 28, 210, 172, 38, + 29, 14, 144, 14, 65, 118, 186, 54, 16, 30, 169, 251, 152, 117, + 93, 158, 131, 117, 158, 162, 238, 21, 164, 166, 173, 206, 46, 86, + 71, 113, 228, 155, 73, 22, 89, 1, 211, 241, 118, 155, 39, 94, + 94, 145, 190, 30, 218, 89, 98, 232, 27, 227, 7, 86, 30, 90, + 102, 181, 7, 200, 154, 30, 36, 248, 231, 13, 199, 211, 202, 116, + 231, 186, 106, 103, 26, 168, 112, 38, 61, 70, 50, 229, 246, 59, + 86, 105, 59, 114, 200, 118, 120, 14, 10, 243, 42, 86, 160, 101, + 13, 109, 17, 16, 134, 89, 2, 32, 252, 225, 111, 69, 124, 83, + 87, 154, 167, 145, 107, 208, 187, 147, 30, 69, 67, 198, 135, 165, + 186, 97, 147, 112, 50, 59, 46, 66, 108, 179, 42, 176, 215, 161, + 241, 153, 241, 86, 248, 181, 250, 14, 14, 74, 24, 88, 171, 225, + 137, 197, 66, 36, 17, 217, 77, 223, 98, 68, 160, 35, 192, 194, + 98, 247, 175, 38, 85, 205, 63, 164, 53, 188, 187, 255, 147, 1, + 5, 5, 178, 63, 76, 193, 190, 72, 108, 179, 60, 16, 58, 248, + 15, 13, 56, 110, 179, 188, 241, 51, 41, 94, 18, 131, 39, 32, + 69, 45, 125, 212, 200, 186, 116, 68, 6, 55, 82, 205, 26, 192, + 255, 228, 10, 238, 252, 132, 156, 94, 200, 13, 116, 87, 213, 135, + 246, 84, 27, 67, 82, 99, 157, 53, 97, 199, 176, 5, 118, 146, + 90, 124, 35, 53, 23, 122, 22, 75, 64, 94, 82, 205, 4, 218, + 44, 141, 58, 235, 199, 227, 13, 47, 145, 170, 184, 183, 26, 108, + 105, 187, 54, 130, 13, 104, 0, 42, 146, 33, 124, 40, 189, 236, + 10, 150, 55, 6, 252, 39, 4, 179, 254, 39, 124, 28, 169, 208, + 145, 210, 170, 58, 26, 104, 144, 62, 162, 208, 96, 122, 39, 16, + 229, 156, 172, 231, 98, 111, 183, 92, 55, 93, 134, 43, 33, 144, + 148, 19, 6, 6, 39, 137, 35, 244, 237, 183, 224, 182, 190, 86, + 118, 9, 85, 195, 181, 197, 145, 175, 245, 47, 130, 218, 109, 11, + 180, 243, 157, 45, 163, 58, 250, 16, 30, 225, 14, 28, 54, 88, + 212, 40, 239, 229, 227, 116, 95, 174, 72, 234, 73, 15, 105, 53, + 199, 190, 66, 208, 185, 203, 202, 61, 107, 199, 224, 228, 130, 90, + 70, 95, 5, 89, 157, 210, 11, 71, 74, 138, 28, 223, 60, 215, + 21, 94, 21, 128, 188, 47, 113, 92, 50, 234, 108, 102, 51, 88, + 176, 141, 88, 54, 1, 255, 79, 118, 145, 110, 44, 78, 27, 176, + 60, 47, 166, 36, 160, 71, 232, 185, 151, 158, 137, 77, 12, 176, + 242, 193, 125, 81, 97, 122, 44, 135, 140, 99, 223, 24, 144, 97, + 183, 26, 50, 100, 11, 234, 64, 20, 114, 156, 250, 222, 177, 225, + 154, 18, 120, 192, 217, 15, 188, 186, 216, 174, 245, 134, 19, 25, + 52, 60, 225, 94, 112, 61, 8, 101, 108, 21, 180, 9, 124, 44, + 64, 18, 220, 204, 23, 106, 221, 90, 86, 77, 193, 40, 114, 99, + 136, 163, 59, 132, 233, 43, 170, 232, 250, 132, 126, 146, 8, 38, + 116, 114, 205, 74, 76, 165, 69, 38, 119, 215, 41, 200, 250, 194, + 143, 172, 91, 73, 192, 117, 105, 155, 87, 26, 137, 195, 3, 63, + 210, 38, 242, 14, 177, 47, 123, 66, 161, 252, 151, 147, 133, 11, + 79, 107, 206, 223, 189, 208, 67, 104, 208, 205, 174, 78, 90, 170, + 127, 100, 242, 13, 34, 144, 202, 176, 75, 141, 70, 57, 7, 155, + 42, 84, 232, 219, 4, 49, 136, 139, 46, 129, 9, 160, 196, 135, + 119, 114, 200, 147, 140, 173, 119, 41, 78, 16, 237, 2, 207, 12, + 134, 111, 17, 138, 244, 140, 115, 86, 160, 25, 88, 10, 124, 36, + 215, 200, 178, 113, 77, 67, 88, 34, 23, 10, 116, 75, 46, 185, + 12, 25, 119, 248, 102, 220, 237, 148, 70, 150, 207, 242, 252, 122, + 168, 55, 207, 249, 156, 46, 11, 39, 37, 28, 223, 221, 58, 179, + 193, 68, 169, 255, 17, 173, 129, 17, 255, 34, 190, 58, 233, 154, + 124, 4, 50, 104, 24, 166, 101, 32, 150, 25, 8, 55, 21, 39, + 253, 107, 17, 96, 247, 1, 212, 81, 135, 191, 35, 67, 154, 48, + 114, 232, 160, 153, 133, 197, 224, 32, 51, 107, 172, 156, 45, 51, + 107, 214, 55, 235, 0, 79, 142, 219, 111, 199, 83, 177, 213, 198, + 0, 152, 109, 55, 57, 159, 86, 139, 231, 15, 118, 3, 230, 249, + 158, 126, 46, 207, 87, 228, 49, 124, 56, 180, 244, 212, 58, 243, + 28, 151, 229, 1, 228, 65, 104, 207, 67, 216, 126, 71, 55, 74, + 69, 79, 242, 176, 157, 1, 174, 134, 2, 146, 191, 3, 227, 165, + 47, 67, 68, 39, 225, 172, 201, 171, 215, 112, 68, 24, 137, 229, + 65, 93, 75, 41, 79, 238, 115, 245, 43, 202, 201, 28, 244, 34, + 205, 187, 221, 149, 184, 197, 0, 57, 223, 141, 94, 109, 181, 118, + 172, 63, 220, 102, 176, 198, 120, 205, 31, 78, 216, 75, 131, 106, + 76, 154, 144, 240, 168, 241, 22, 140, 140, 77, 62, 39, 91, 166, + 247, 34, 240, 236, 254, 250, 233, 194, 71, 202, 170, 77, 94, 83, + 247, 179, 170, 19, 34, 233, 221, 55, 163, 249, 184, 79, 32, 15, + 147, 200, 60, 167, 14, 87, 73, 61, 149, 54, 21, 159, 194, 112, + 138, 5, 95, 39, 191, 49, 156, 126, 9, 2, 122, 196, 141, 243, + 221, 9, 42, 222, 110, 176, 127, 21, 75, 168, 123, 43, 213, 171, + 116, 235, 190, 131, 154, 24, 39, 174, 254, 235, 54, 40, 16, 20, + 111, 170, 27, 105, 14, 184, 6, 92, 171, 8, 46, 186, 44, 222, + 63, 85, 185, 19, 94, 183, 104, 186, 64, 28, 138, 71, 251, 236, + 199, 12, 56, 218, 89, 88, 40, 139, 38, 23, 116, 221, 128, 127, + 94, 128, 105, 50, 7, 101, 87, 102, 134, 225, 154, 105, 154, 108, + 144, 3, 151, 145, 42, 25, 195, 135, 104, 127, 170, 52, 117, 176, + 31, 135, 11, 9, 26, 50, 27, 242, 63, 156, 179, 225, 6, 130, + 81, 12, 123, 212, 226, 233, 253, 124, 115, 12, 222, 150, 0, 125, + 189, 165, 57, 36, 250, 183, 10, 139, 131, 174, 46, 79, 199, 177, + 132, 89, 31, 56, 16, 37, 137, 185, 51, 80, 168, 116, 116, 38, + 249, 45, 170, 254, 249, 65, 22, 221, 12, 19, 71, 3, 216, 194, + 250, 63, 2, 65, 170, 229, 80, 150, 32, 191, 137, 241, 13, 32, + 131, 92, 240, 200, 217, 82, 71, 165, 72, 49, 16, 24, 84, 34, + 245, 147, 206, 209, 238, 47, 213, 140, 154, 182, 217, 219, 57, 139, + 244, 59, 201, 128, 22, 174, 123, 248, 21, 149, 170, 231, 55, 48, + 68, 192, 208, 22, 239, 75, 21, 79, 63, 17, 32, 205, 101, 170, + 81, 77, 74, 160, 217, 188, 26, 146, 149, 65, 231, 163, 46, 191, + 250, 250, 163, 48, 232, 27, 42, 253, 170, 14, 78, 63, 166, 173, + 237, 176, 103, 173, 145, 251, 35, 218, 3, 159, 175, 33, 56, 55, + 246, 237, 237, 238, 233, 140, 236, 74, 176, 69, 211, 118, 75, 93, + 255, 18, 228, 47, 100, 199, 70, 252, 31, 193, 120, 117, 129, 245, + 59, 155, 80, 22, 224, 8, 249, 227, 10, 251, 64, 48, 13, 150, + 248, 75, 46, 116, 63, 178, 41, 19, 107, 48, 212, 13, 173, 252, + 112, 80, 165, 8, 172, 36, 170, 61, 192, 137, 246, 110, 83, 92, + 154, 220, 4, 222, 222, 239, 128, 153, 98, 194, 111, 235, 129, 16, + 115, 193, 248, 181, 136, 113, 91, 9, 43, 39, 187, 89, 124, 241, + 252, 101, 161, 49, 83, 40, 64, 93, 251, 167, 127, 132, 98, 227, + 109, 120, 166, 7, 148, 149, 97, 227, 64, 47, 14, 88, 213, 125, + 255, 219, 179, 23, 41, 60, 161, 115, 161, 131, 79, 202, 179, 94, + 75, 212, 187, 148, 239, 86, 148, 168, 54, 98, 243, 85, 169, 78, + 107, 22, 36, 98, 208, 124, 55, 223, 127, 69, 48, 120, 137, 92, + 146, 210, 185, 10, 3, 189, 133, 247, 136, 218, 167, 154, 10, 106, + 87, 127, 216, 195, 47, 233, 246, 114, 244, 96, 210, 134, 252, 106, + 33, 169, 157, 135, 4, 17, 104, 103, 199, 56, 95, 246, 250, 170, + 147, 138, 226, 247, 29, 22, 210, 151, 145, 40, 237, 212, 204, 91, + 91, 98, 192, 93, 43, 90, 138, 119, 245, 191, 104, 237, 160, 240, + 76, 181, 109, 80, 180, 142, 128, 82, 105, 185, 168, 62, 104, 186, + 110, 149, 195, 216, 183, 53, 218, 71, 204, 222, 68, 123, 125, 155, + 8, 209, 193, 108, 147, 251, 75, 153, 223, 97, 104, 140, 71, 17, + 140, 204, 192, 89, 20, 185, 88, 40, 26, 240, 83, 212, 184, 66, + 161, 116, 144, 55, 186, 246, 187, 133, 71, 166, 126, 81, 241, 147, + 190, 68, 88, 175, 55, 195, 36, 188, 26, 237, 141, 215, 55, 221, + 207, 170, 109, 150, 231, 59, 207, 129, 183, 200, 87, 38, 2, 190, + 114, 48, 207, 4, 136, 112, 139, 145, 105, 75, 64, 88, 237, 177, + 123, 66, 174, 122, 195, 29, 37, 212, 40, 60, 37, 212, 188, 123, + 47, 6, 26, 148, 5, 54, 187, 92, 57, 103, 95, 203, 190, 195, + 192, 195, 206, 188, 3, 43, 96, 236, 58, 8, 52, 81, 136, 127, + 218, 109, 224, 80, 38, 45, 187, 39, 5, 68, 205, 205, 55, 206, + 248, 110, 71, 115, 62, 233, 102, 224, 136, 76, 239, 190, 106, 154, + 79, 127, 167, 226, 142, 67, 86, 65, 240, 65, 197, 158, 49, 25, + 234, 164, 14, 8, 181, 43, 102, 35, 56, 162, 226, 138, 128, 32, + 4, 155, 160, 224, 0, 98, 189, 15, 2, 66, 187, 54, 90, 89, + 44, 71, 88, 91, 91, 87, 100, 227, 123, 31, 194, 154, 180, 6, + 248, 198, 184, 62, 228, 167, 137, 23, 32, 127, 63, 209, 56, 159, + 202, 210, 164, 131, 84, 242, 138, 81, 170, 29, 204, 231, 105, 179, + 85, 188, 157, 113, 170, 163, 6, 201, 209, 60, 59, 62, 89, 168, + 15, 240, 130, 20, 137, 126, 122, 4, 202, 172, 10, 91, 8, 79, + 154, 231, 74, 155, 71, 90, 222, 64, 255, 239, 213, 9, 91, 137, + 119, 112, 36, 228, 27, 203, 5, 113, 221, 61, 226, 16, 233, 232, + 32, 172, 6, 132, 113, 140, 247, 0, 231, 102, 34, 13, 213, 117, + 197, 202, 253, 172, 18, 80, 202, 109, 150, 193, 183, 210, 14, 174, + 150, 118, 144, 208, 18, 107, 244, 136, 171, 231, 82, 74, 80, 165, + 47, 39, 25, 16, 128, 67, 241, 76, 56, 16, 55, 90, 201, 119, + 248, 5, 6, 105, 239, 200, 146, 203, 208, 18, 202, 17, 195, 228, + 183, 56, 36, 204, 218, 120, 21, 73, 53, 253, 75, 108, 29, 85, + 247, 206, 61, 48, 55, 78, 53, 186, 239, 1, 246, 11, 41, 152, + 7, 124, 216, 222, 63, 89, 237, 219, 240, 173, 26, 36, 33, 9, + 82, 138, 176, 228, 118, 87, 51, 52, 216, 32, 176, 228, 43, 226, + 59, 194, 170, 104, 154, 125, 2, 223, 63, 160, 82, 222, 171, 15, + 123, 58, 9, 113, 87, 255, 172, 228, 80, 153, 246, 225, 94, 130, + 61, 134, 58, 28, 227, 237, 59, 252, 132, 130, 2, 238, 236, 45, + 81, 98, 119, 139, 114, 237, 36, 224, 207, 221, 156, 212, 147, 192, + 40, 117, 101, 88, 51, 121, 170, 159, 138, 215, 213, 69, 177, 139, + 120, 193, 82, 191, 192, 180, 127, 143, 195, 202, 65, 154, 154, 92, + 134, 47, 81, 140, 157, 255, 109, 52, 47, 132, 110, 28, 180, 233, + 51, 181, 74, 165, 242, 52, 255, 224, 17, 79, 233, 139, 159, 126, + 229, 204, 85, 52, 59, 76, 147, 108, 43, 6, 38, 183, 43, 40, + 192, 243, 173, 115, 168, 238, 88, 117, 228, 104, 13, 34, 39, 197, + 88, 166, 80, 50, 184, 111, 4, 109, 23, 7, 122, 44, 173, 246, + 111, 211, 179, 23, 192, 43, 173, 241, 184, 218, 40, 57, 55, 250, + 236, 120, 76, 176, 91, 167, 222, 114, 232, 211, 17, 153, 83, 89, + 85, 228, 32, 128, 30, 79, 80, 35, 96, 164, 181, 40, 101, 55, + 215, 8, 124, 159, 202, 77, 84, 24, 94, 160, 67, 235, 177, 228, + 0, 213, 198, 177, 51, 154, 168, 125, 205, 83, 62, 9, 94, 239, + 181, 249, 31, 144, 211, 32, 2, 39, 20, 181, 244, 219, 113, 107, + 5, 174, 72, 68, 82, 159, 121, 81, 93, 160, 163, 108, 243, 33, + 249, 54, 196, 40, 151, 213, 32, 181, 248, 170, 221, 250, 98, 26, + 157, 69, 40, 70, 193, 210, 220, 250, 68, 234, 44, 102, 177, 63, + 147, 91, 118, 220, 154, 92, 230, 29, 31, 244, 225, 48, 3, 243, + 32, 4, 145, 22, 2, 90, 20, 79, 106, 185, 169, 220, 240, 252, + 87, 38, 143, 155, 32, 164, 248, 12, 160, 84, 208, 190, 120, 82, + 73, 62, 165, 76, 226, 29, 14, 73, 136, 128, 207, 235, 141, 3, + 170, 208, 154, 63, 61, 7, 237, 74, 252, 92, 40, 114, 87, 77, + 169, 34, 10, 204, 253, 55, 37, 108, 31, 255, 44, 67, 34, 233, + 254, 176, 178, 105, 107, 246, 139, 165, 84, 9, 143, 248, 194, 11, + 172, 181, 175, 228, 41, 167, 157, 78, 93, 214, 65, 184, 255, 211, + 216, 105, 56, 45, 93, 162, 201, 241, 71, 183, 112, 64, 131, 232, + 195, 32, 183, 105, 43, 96, 84, 176, 145, 199, 213, 155, 44, 229, + 172, 71, 182, 192, 200, 177, 23, 111, 14, 73, 223, 7, 182, 97, + 153, 71, 91, 10, 38, 224, 181, 80, 220, 171, 92, 135, 60, 160, + 163, 42, 3, 108, 128, 80, 12, 32, 183, 169, 136, 173, 139, 9, + 35, 109, 137, 142, 23, 97, 14, 188, 233, 105, 82, 64, 118, 174, + 165, 251, 242, 222, 150, 17, 99, 162, 152, 254, 224, 51, 155, 87, + 104, 67, 164, 244, 95, 238, 181, 119, 179, 86, 137, 20, 88, 224, + 198, 5, 42, 222, 90, 173, 202, 25, 248, 183, 244, 32, 72, 41, + 243, 62, 141, 93, 73, 171, 196, 144, 26, 2, 37, 15, 170, 149, + 113, 64, 135, 208, 63, 15, 87, 156, 10, 185, 127, 175, 211, 38, + 31, 21, 59, 167, 191, 105, 181, 213, 210, 156, 245, 103, 248, 190, + 213, 148, 132, 132, 223, 84, 195, 24, 210, 254, 141, 106, 252, 122, + 138, 162, 204, 9, 247, 196, 201, 189, 255, 115, 206, 134, 25, 105, + 121, 101, 136, 187, 163, 90, 177, 223, 246, 18, 57, 223, 234, 230, + 11, 105, 180, 171, 90, 210, 246, 166, 132, 150, 246, 211, 138, 131, + 61, 22, 45, 166, 72, 41, 162, 239, 240, 121, 255, 105, 22, 108, + 228, 150, 36, 45, 5, 94, 247, 19, 157, 118, 248, 4, 3, 24, + 101, 100, 177, 33, 244, 129, 193, 67, 69, 215, 28, 85, 140, 250, + 128, 134, 208, 91, 66, 18, 54, 192, 247, 226, 194, 173, 251, 148, + 171, 28, 57, 63, 241, 216, 137, 140, 128, 26, 240, 176, 126, 168, + 16, 145, 126, 213, 27, 138, 138, 70, 38, 6, 248, 115, 110, 129, + 21, 19, 242, 222, 109, 191, 228, 208, 115, 44, 229, 10, 250, 58, + 22, 188, 115, 9, 126, 79, 250, 15, 152, 235, 168, 64, 226, 174, + 253, 88, 23, 4, 187, 134, 253, 119, 163, 225, 98, 159, 58, 51, + 44, 117, 70, 138, 120, 99, 161, 207, 215, 61, 190, 119, 101, 180, + 17, 189, 245, 87, 55, 140, 63, 65, 9, 76, 19, 40, 114, 243, + 156, 1, 20, 240, 98, 54, 235, 212, 217, 193, 93, 234, 41, 144, + 246, 176, 100, 176, 94, 252, 10, 44, 10, 56, 51, 106, 23, 160, + 176, 118, 152, 35, 82, 71, 247, 222, 10, 166, 38, 186, 113, 95, + 160, 131, 99, 65, 14, 58, 85, 48, 234, 252, 9, 221, 33, 100, + 216, 9, 152, 30, 220, 222, 243, 95, 103, 140, 18, 246, 42, 119, + 102, 7, 143, 221, 35, 65, 246, 34, 89, 146, 19, 176, 5, 75, + 39, 84, 163, 68, 181, 155, 182, 67, 103, 145, 24, 67, 73, 111, + 127, 247, 183, 115, 112, 68, 130, 127, 63, 231, 2, 126, 236, 30, + 95, 142, 194, 9, 215, 29, 9, 145, 78, 13, 249, 254, 125, 172, + 42, 38, 101, 1, 93, 197, 26, 173, 103, 84, 20, 85, 50, 180, + 0, 108, 133, 93, 8, 129, 30, 154, 127, 144, 155, 14, 203, 164, + 215, 99, 155, 3, 134, 141, 127, 29, 234, 156, 147, 156, 91, 44, + 83, 233, 198, 154, 243, 164, 134, 130, 133, 142, 206, 44, 90, 93, + 255, 80, 91, 185, 120, 200, 87, 88, 137, 170, 87, 45, 67, 159, + 59, 2, 168, 171, 102, 169, 220, 221, 31, 216, 145, 67, 77, 56, + 165, 31, 43, 21, 120, 247, 115, 92, 122, 19, 209, 141, 86, 251, + 86, 48, 111, 112, 85, 220, 203, 21, 22, 31, 109, 198, 169, 63, + 22, 32, 72, 183, 250, 16, 95, 49, 67, 67, 186, 10, 190, 249, + 125, 117, 78, 208, 2, 50, 195, 204, 107, 44, 211, 144, 107, 170, + 41, 91, 94, 136, 150, 104, 77, 162, 117, 36, 229, 102, 133, 222, + 166, 109, 207, 184, 217, 142, 36, 235, 248, 33, 131, 74, 158, 242, + 178, 123, 182, 95, 224, 129, 82, 76, 174, 15, 153, 106, 120, 216, + 50, 240, 110, 192, 129, 136, 246, 208, 92, 7, 91, 97, 73, 132, + 25, 219, 79, 151, 248, 213, 246, 162, 192, 215, 239, 96, 56, 223, + 79, 93, 34, 88, 240, 144, 184, 217, 81, 24, 82, 122, 144, 75, + 206, 167, 139, 23, 219, 164, 244, 101, 33, 135, 52, 147, 149, 55, + 250, 177, 153, 187, 36, 237, 39, 70, 71, 41, 238, 33, 131, 14, + 171, 128, 209, 249, 248, 173, 192, 48, 75, 177, 119, 8, 91, 54, + 147, 102, 72, 226, 245, 58, 195, 87, 239, 126, 230, 45, 70, 20, + 172, 104, 15, 227, 253, 164, 93, 175, 111, 18, 12, 171, 243, 135, + 99, 47, 154, 2, 176, 85, 194, 248, 159, 186, 238, 118, 215, 84, + 136, 93, 17, 192, 46, 103, 46, 44, 205, 237, 230, 217, 254, 137, + 145, 218, 255, 106, 23, 127, 85, 249, 236, 66, 65, 178, 129, 32, + 72, 63, 138, 217, 252, 85, 153, 184, 145, 1, 110, 130, 48, 103, + 146, 191, 133, 29, 177, 198, 214, 47, 170, 107, 144, 33, 74, 195, + 208, 221, 108, 200, 182, 161, 46, 99, 219, 148, 251, 222, 26, 135, + 39, 37, 182, 232, 252, 9, 156, 146, 164, 3, 215, 211, 248, 9, + 205, 122, 208, 163, 68, 110, 207, 78, 228, 68, 1, 233, 191, 175, + 196, 17, 86, 195, 129, 22, 124, 250, 143, 91, 230, 110, 142, 179, + 2, 218, 184, 241, 136, 172, 29, 161, 152, 186, 224, 103, 3, 108, + 166, 152, 217, 203, 63, 168, 28, 74, 67, 176, 1, 219, 35, 133, + 105, 184, 243, 185, 15, 206, 94, 218, 78, 117, 12, 202, 108, 43, + 1, 235, 85, 208, 147, 145, 188, 193, 62, 114, 224, 34, 104, 14, + 122, 187, 216, 83, 17, 31, 89, 29, 102, 111, 213, 79, 127, 198, + 228, 163, 147, 159, 108, 1, 166, 183, 155, 103, 230, 209, 253, 59, + 140, 102, 20, 88, 138, 131, 200, 127, 141, 232, 50, 250, 201, 189, + 60, 67, 175, 139, 213, 180, 217, 129, 60, 113, 67, 137, 186, 105, + 181, 12, 8, 53, 65, 7, 153, 71, 144, 197, 219, 156, 1, 22, + 40, 244, 76, 173, 35, 54, 242, 177, 205, 47, 57, 152, 174, 147, + 15, 198, 206, 22, 81, 232, 217, 4, 32, 110, 230, 199, 118, 153, + 148, 102, 78, 158, 8, 134, 1, 251, 43, 73, 174, 91, 53, 133, + 180, 69, 82, 9, 37, 136, 135, 199, 247, 11, 205, 27, 185, 8, + 96, 34, 12, 96, 150, 218, 41, 72, 119, 183, 2, 85, 139, 56, + 123, 230, 25, 236, 118, 78, 159, 43, 62, 168, 0, 141, 250, 227, + 205, 150, 165, 55, 248, 108, 116, 198, 159, 193, 150, 218, 2, 230, + 227, 96, 203, 197, 21, 99, 144, 214, 189, 125, 55, 211, 175, 223, + 116, 52, 110, 198, 203, 165, 176, 139, 149, 175, 56, 44, 90, 19, + 69, 156, 137, 41, 71, 65, 15, 89, 243, 135, 129, 119, 172, 141, + 232, 32, 214, 114, 252, 185, 123, 171, 26, 130, 79, 178, 192, 23, + 148, 60, 74, 186, 156, 19, 92, 247, 153, 107, 83, 204, 6, 179, + 22, 18, 77, 26, 192, 92, 194, 155, 216, 156, 35, 234, 26, 84, + 55, 62, 208, 41, 112, 9, 84, 220, 213, 32, 67, 0, 29, 115, + 149, 160, 105, 167, 52, 19, 250, 237, 8, 0, 115, 172, 235, 55, + 20, 83, 16, 217, 116, 73, 206, 150, 226, 158, 141, 119, 79, 122, + 142, 193, 17, 159, 68, 148, 19, 125, 75, 70, 197, 227, 234, 161, + 90, 244, 111, 223, 97, 128, 38, 205, 74, 82, 188, 242, 40, 63, + 227, 150, 117, 227, 139, 1, 252, 198, 97, 103, 41, 124, 146, 141, + 236, 39, 138, 71, 3, 78, 18, 132, 242, 113, 216, 138, 1, 141, + 235, 110, 41, 225, 27, 26, 210, 76, 190, 91, 235, 188, 56, 101, + 198, 211, 184, 11, 10, 169, 186, 5, 42, 192, 72, 55, 17, 152, + 7, 108, 182, 95, 238, 192, 211, 77, 126, 46, 163, 30, 140, 23, + 19, 51, 6, 185, 148, 223, 82, 238, 133, 240, 191, 73, 253, 30, + 108, 111, 212, 112, 75, 162, 194, 149, 71, 73, 70, 231, 71, 252, + 251, 137, 137, 147, 93, 83, 166, 231, 228, 140, 101, 204, 51, 106, + 143, 32, 5, 194, 0, 148, 186, 74, 2, 237, 125, 9, 179, 137, + 220, 108, 149, 192, 29, 57, 107, 35, 13, 76, 231, 12, 127, 85, + 66, 151, 72, 38, 156, 187, 112, 109, 186, 130, 228, 112, 113, 141, + 85, 64, 162, 142, 122, 156, 226, 199, 178, 12, 68, 122, 135, 135, + 137, 245, 17, 254, 83, 126, 103, 92, 72, 29, 233, 68, 10, 231, + 98, 255, 65, 248, 40, 254, 171, 0, 121, 2, 52, 212, 144, 121, + 35, 59, 46, 138, 180, 218, 200, 87, 27, 133, 238, 23, 76, 230, + 150, 253, 136, 235, 16, 61, 86, 16, 171, 229, 206, 115, 187, 112, + 98, 85, 0, 38, 38, 127, 3, 19, 111, 177, 247, 97, 220, 201, + 151, 122, 136, 76, 239, 171, 175, 212, 162, 91, 31, 35, 191, 121, + 39, 216, 30, 235, 113, 27, 34, 50, 59, 28, 21, 60, 142, 9, + 171, 119, 91, 210, 250, 163, 128, 22, 59, 196, 95, 27, 85, 105, + 236, 222, 21, 70, 40, 173, 183, 1, 149, 183, 238, 192, 244, 129, + 163, 175, 190, 196, 152, 107, 159, 7, 188, 155, 240, 105, 126, 135, + 130, 24, 104, 38, 27, 12, 136, 74, 122, 190, 254, 86, 240, 161, + 205, 205, 27, 246, 86, 45, 150, 5, 209, 206, 119, 234, 49, 69, + 31, 226, 174, 26, 211, 140, 180, 249, 230, 207, 86, 18, 12, 163, + 25, 254, 155, 207, 81, 191, 133, 71, 71, 189, 151, 68, 144, 242, + 183, 178, 146, 214, 162, 167, 85, 199, 136, 240, 129, 38, 96, 148, + 217, 124, 213, 36, 131, 116, 160, 7, 209, 44, 12, 6, 72, 249, + 202, 129, 240, 44, 201, 12, 170, 127, 26, 61, 84, 90, 93, 107, + 98, 160, 244, 169, 75, 158, 162, 204, 53, 250, 249, 94, 162, 245, + 145, 29, 20, 188, 205, 181, 194, 13, 25, 24, 129, 102, 93, 75, + 218, 13, 123, 3, 200, 66, 4, 58, 42, 163, 219, 191, 81, 106, + 206, 230, 164, 185, 222, 59, 218, 136, 106, 124, 173, 42, 160, 156, + 14, 64, 38, 180, 226, 237, 229, 96, 244, 96, 103, 74, 24, 96, + 154, 232, 255, 7, 106, 145, 29, 15, 199, 131, 165, 183, 113, 34, + 236, 130, 165, 41, 8, 202, 42, 93, 11, 134, 168, 59, 161, 6, + 235, 208, 227, 35, 153, 188, 116, 238, 9, 235, 187, 154, 7, 250, + 68, 225, 103, 203, 108, 174, 248, 3, 71, 227, 68, 143, 32, 184, + 36, 87, 202, 58, 108, 16, 240, 192, 131, 189, 145, 201, 54, 181, + 153, 140, 14, 16, 147, 43, 80, 163, 59, 84, 185, 213, 228, 247, + 74, 242, 171, 228, 198, 47, 240, 41, 76, 253, 223, 166, 173, 249, + 169, 115, 128, 217, 159, 33, 206, 8, 124, 106, 255, 189, 34, 56, + 156, 242, 59, 99, 99, 169, 241, 168, 176, 210, 64, 221, 213, 232, + 192, 109, 237, 245, 7, 5, 196, 190, 97, 152, 82, 42, 180, 17, + 196, 76, 99, 196, 228, 179, 44, 145, 200, 148, 9, 7, 251, 229, + 96, 254, 144, 173, 142, 161, 238, 210, 146, 195, 250, 214, 62, 47, + 160, 119, 172, 129, 32, 170, 250, 204, 115, 112, 169, 87, 149, 13, + 75, 225, 189, 182, 59, 99, 153, 176, 149, 80, 112, 222, 121, 80, + 161, 188, 58, 165, 23, 160, 183, 31, 237, 197, 236, 222, 162, 134, + 133, 96, 151, 20, 112, 136, 198, 185, 149, 220, 10, 54, 203, 123, + 186, 1, 56, 61, 95, 141, 52, 245, 41, 179, 31, 208, 173, 213, + 181, 48, 103, 133, 112, 124, 150, 223, 97, 174, 16, 182, 79, 16, + 140, 9, 106, 150, 253, 40, 242, 77, 169, 125, 188, 163, 226, 1, + 236, 24, 154, 3, 14, 171, 175, 215, 55, 116, 174, 20, 148, 118, + 51, 84, 73, 40, 192, 28, 165, 241, 250, 33, 191, 212, 218, 208, + 64, 82, 167, 60, 32, 177, 10, 164, 139, 231, 90, 255, 153, 147, + 230, 13, 148, 235, 30, 10, 49, 171, 134, 48, 101, 72, 137, 23, + 239, 246, 134, 154, 20, 30, 27, 249, 10, 157, 125, 184, 236, 9, + 240, 16, 204, 239, 74, 211, 102, 160, 1, 36, 164, 244, 114, 17, + 95, 76, 249, 206, 55, 252, 64, 53, 244, 78, 51, 99, 6, 178, + 125, 72, 43, 123, 16, 77, 231, 169, 245, 190, 145, 174, 86, 107, + 231, 128, 251, 193, 34, 49, 243, 221, 241, 177, 60, 234, 224, 120, + 165, 86, 22, 15, 192, 167, 178, 241, 55, 226, 143, 171, 85, 38, + 30, 89, 138, 222, 63, 154, 11, 31, 206, 154, 101, 230, 80, 4, + 218, 151, 247, 160, 166, 201, 51, 239, 11, 204, 169, 248, 67, 20, + 28, 140, 193, 9, 29, 254, 110, 99, 113, 236, 5, 140, 236, 188, + 246, 214, 20, 19, 167, 215, 146, 212, 141, 181, 16, 131, 158, 46, + 113, 151, 26, 91, 146, 70, 200, 196, 147, 121, 150, 34, 174, 44, + 40, 70, 224, 51, 201, 146, 18, 32, 42, 198, 125, 23, 62, 133, + 12, 168, 164, 22, 242, 18, 122, 125, 53, 92, 117, 121, 198, 168, + 250, 236, 157, 80, 64, 164, 91, 193, 149, 163, 31, 229, 76, 3, + 83, 2, 237, 185, 176, 142, 198, 138, 23, 184, 90, 18, 35, 83, + 74, 139, 42, 66, 212, 215, 194, 88, 148, 86, 77, 43, 201, 26, + 95, 255, 98, 78, 233, 249, 132, 107, 53, 40, 10, 129, 149, 105, + 182, 180, 255, 119, 252, 33, 192, 37, 32, 147, 182, 45, 143, 193, + 140, 40, 214, 81, 31, 123, 173, 98, 164, 83, 14, 86, 65, 131, + 242, 3, 209, 222, 99, 220, 158, 135, 111, 153, 191, 148, 100, 20, + 220, 43, 68, 228, 69, 184, 95, 66, 17, 67, 6, 89, 15, 239, + 166, 98, 12, 64, 76, 139, 120, 206, 218, 20, 194, 42, 208, 57, + 217, 195, 228, 3, 32, 228, 185, 67, 158, 0, 183, 162, 143, 56, + 78, 98, 125, 203, 102, 64, 45, 187, 213, 166, 244, 135, 90, 98, + 88, 84, 205, 37, 192, 75, 174, 169, 170, 63, 230, 95, 63, 98, + 45, 191, 78, 202, 154, 128, 122, 196, 251, 243, 210, 247, 4, 188, + 19, 228, 161, 4, 187, 26, 251, 238, 42, 66, 130, 20, 164, 170, + 216, 177, 37, 254, 51, 109, 140, 64, 194, 235, 65, 93, 254, 24, + 114, 177, 26, 10, 158, 239, 11, 176, 161, 154, 33, 251, 253, 196, + 134, 0, 252, 181, 51, 41, 29, 226, 145, 87, 241, 152, 192, 219, + 80, 252, 3, 245, 83, 220, 192, 52, 212, 39, 152, 67, 189, 7, + 219, 143, 55, 124, 102, 17, 214, 10, 184, 53, 170, 52, 1, 52, + 212, 213, 117, 24, 65, 144, 209, 109, 130, 130, 45, 227, 166, 161, + 179, 158, 41, 199, 243, 34, 43, 251, 59, 18, 232, 238, 236, 60, + 111, 199, 149, 43, 10, 167, 84, 52, 243, 183, 131, 7, 110, 206, + 229, 195, 131, 255, 238, 39, 80, 125, 223, 191, 49, 227, 26, 45, + 194, 247, 188, 124, 6, 141, 248, 62, 86, 170, 225, 221, 70, 252, + 64, 201, 40, 74, 125, 221, 2, 168, 138, 3, 165, 184, 74, 54, + 141, 118, 118, 76, 192, 217, 39, 128, 8, 137, 221, 16, 94, 180, + 109, 22, 232, 188, 116, 115, 48, 197, 103, 28, 90, 208, 189, 143, + 172, 180, 118, 228, 23, 9, 85, 88, 23, 206, 55, 170, 140, 100, + 143, 123, 50, 64, 90, 231, 7, 68, 224, 182, 229, 210, 36, 17, + 82, 94, 50, 252, 74, 116, 86, 105, 45, 69, 39, 199, 167, 126, + 224, 94, 82, 71, 217, 244, 117, 42, 41, 151, 58, 232, 64, 91, + 103, 210, 167, 68, 61, 142, 66, 104, 59, 247, 41, 33, 27, 54, + 235, 245, 99, 211, 67, 60, 158, 78, 35, 17, 115, 119, 216, 79, + 218, 18, 89, 67, 191, 168, 185, 108, 146, 209, 97, 3, 176, 154, + 214, 230, 157, 169, 185, 204, 192, 218, 167, 48, 237, 11, 193, 108, + 253, 86, 70, 59, 211, 212, 57, 92, 22, 14, 90, 98, 183, 84, + 104, 103, 38, 161, 242, 70, 152, 183, 45, 98, 100, 75, 135, 217, + 4, 170, 117, 0, 181, 114, 199, 226, 173, 101, 63, 110, 181, 228, + 6, 98, 217, 74, 251, 165, 111, 244, 192, 213, 50, 8, 246, 234, + 241, 9, 130, 143, 163, 39, 55, 106, 145, 156, 239, 15, 163, 139, + 238, 230, 40, 125, 60, 101, 59, 223, 106, 144, 120, 50, 19, 96, + 64, 103, 103, 209, 186, 19, 136, 125, 137, 228, 4, 200, 28, 152, + 96, 254, 96, 167, 231, 224, 244, 90, 41, 75, 9, 250, 104, 134, + 240, 171, 197, 98, 34, 227, 143, 178, 87, 4, 175, 90, 58, 216, + 76, 130, 158, 78, 109, 64, 133, 104, 170, 45, 210, 94, 17, 101, + 23, 101, 53, 35, 166, 194, 33, 30, 116, 176, 14, 155, 16, 220, + 95, 158, 209, 122, 104, 227, 117, 19, 207, 111, 90, 233, 6, 25, + 74, 217, 246, 235, 236, 80, 168, 12, 238, 251, 231, 241, 110, 49, + 175, 78, 100, 20, 76, 235, 32, 89, 154, 216, 205, 223, 159, 90, + 54, 64, 122, 221, 169, 63, 118, 185, 243, 161, 250, 62, 5, 229, + 106, 202, 135, 100, 182, 57, 218, 134, 131, 29, 22, 61, 211, 251, + 190, 233, 88, 57, 43, 194, 156, 5, 62, 0, 205, 160, 24, 87, + 3, 117, 228, 102, 135, 96, 95, 240, 41, 119, 158, 173, 240, 139, + 199, 196, 19, 94, 79, 19, 188, 116, 171, 161, 245, 98, 190, 114, + 138, 65, 69, 106, 107, 238, 191, 59, 77, 48, 123, 173, 230, 47, + 50, 15, 244, 89, 253, 53, 23, 244, 105, 129, 113, 74, 156, 218, + 101, 42, 226, 193, 60, 101, 177, 191, 219, 127, 139, 186, 128, 212, + 181, 152, 57, 16, 6, 23, 248, 78, 252, 1, 144, 139, 120, 207, + 122, 104, 213, 206, 108, 96, 192, 56, 210, 38, 213, 93, 246, 146, + 96, 30, 184, 197, 27, 84, 242, 206, 224, 219, 173, 217, 190, 225, + 1, 233, 113, 175, 42, 132, 47, 122, 180, 244, 186, 68, 205, 196, + 79, 155, 39, 80, 166, 239, 225, 226, 73, 227, 62, 206, 249, 62, + 69, 236, 35, 184, 120, 94, 181, 251, 168, 57, 5, 78, 164, 248, + 132, 69, 89, 143, 29, 83, 87, 238, 183, 139, 70, 249, 91, 82, + 127, 83, 147, 237, 26, 70, 110, 118, 31, 237, 251, 227, 80, 194, + 189, 43, 118, 149, 105, 60, 173, 132, 165, 255, 231, 135, 56, 95, + 157, 224, 96, 227, 96, 119, 140, 209, 162, 226, 203, 189, 204, 40, + 193, 31, 204, 46, 235, 180, 194, 225, 237, 235, 232, 193, 204, 104, + 55, 196, 178, 153, 239, 150, 33, 139, 173, 246, 233, 11, 179, 156, + 196, 117, 24, 56, 124, 240, 196, 85, 186, 88, 2, 38, 215, 28, + 169, 168, 149, 9, 247, 231, 82, 118, 43, 236, 179, 39, 163, 193, + 44, 174, 65, 177, 95, 239, 215, 134, 34, 33, 226, 219, 179, 50, + 245, 140, 83, 129, 24, 148, 162, 199, 43, 88, 76, 73, 152, 112, + 151, 244, 1, 39, 171, 238, 116, 124, 153, 224, 224, 202, 249, 49, + 51, 206, 226, 155, 197, 16, 190, 238, 204, 197, 204, 21, 39, 16, + 119, 169, 153, 133, 190, 119, 252, 39, 92, 212, 134, 46, 81, 70, + 20, 162, 14, 103, 129, 186, 1, 71, 124, 30, 3, 251, 156, 40, + 56, 135, 202, 15, 206, 95, 252, 186, 114, 84, 67, 193, 51, 42, + 94, 222, 104, 162, 234, 87, 244, 113, 107, 119, 50, 66, 249, 68, + 135, 201, 208, 247, 180, 138, 98, 189, 1, 250, 160, 185, 228, 185, + 24, 150, 203, 71, 205, 175, 128, 171, 221, 80, 13, 163, 23, 32, + 191, 21, 123, 152, 232, 8, 100, 164, 232, 244, 186, 183, 120, 214, + 162, 12, 73, 149, 137, 142, 216, 50, 31, 155, 85, 146, 125, 199, + 10, 91, 49, 5, 40, 253, 131, 154, 168, 22, 5, 31, 70, 104, + 160, 175, 68, 177, 238, 19, 65, 217, 234, 138, 206, 213, 152, 195, + 65, 239, 83, 244, 120, 63, 165, 117, 8, 253, 189, 3, 95, 167, + 117, 72, 213, 190, 187, 100, 245, 20, 70, 26, 43, 53, 165, 94, + 114, 59, 88, 5, 50, 46, 124, 228, 46, 248, 60, 188, 99, 1, + 96, 133, 36, 131, 64, 137, 147, 104, 137, 233, 54, 22, 142, 235, + 214, 89, 81, 215, 157, 176, 123, 147, 243, 115, 109, 89, 211, 3, + 128, 97, 151, 136, 252, 32, 179, 153, 20, 209, 8, 119, 116, 160, + 46, 83, 202, 112, 181, 44, 7, 136, 50, 241, 131, 10, 223, 234, + 158, 3, 69, 195, 110, 21, 244, 211, 158, 201, 121, 230, 129, 155, + 198, 1, 52, 56, 176, 80, 196, 133, 90, 124, 139, 253, 84, 234, + 28, 196, 26, 41, 74, 212, 202, 78, 26, 135, 37, 148, 124, 63, + 235, 141, 8, 97, 239, 216, 2, 154, 109, 177, 15, 146, 58, 142, + 29, 118, 130, 187, 203, 192, 130, 76, 17, 62, 77, 80, 249, 43, + 223, 91, 235, 204, 137, 248, 37, 19, 244, 4, 87, 154, 147, 114, + 136, 14, 253, 147, 55, 228, 111, 243, 242, 18, 0, 192, 237, 223, + 229, 172, 11, 13, 110, 136, 243, 88, 157, 228, 5, 254, 246, 89, + 187, 50, 225, 33, 51, 9, 174, 120, 43, 49, 9, 48, 229, 119, + 7, 159, 103, 22, 174, 49, 115, 243, 203, 221, 251, 114, 58, 62, + 72, 60, 29, 120, 236, 54, 7, 253, 125, 105, 157, 24, 73, 27, + 31, 205, 25, 216, 103, 236, 130, 201, 33, 208, 227, 66, 119, 39, + 82, 211, 145, 196, 37, 183, 18, 253, 131, 64, 115, 225, 3, 249, + 8, 89, 228, 125, 207, 106, 162, 249, 216, 164, 210, 41, 44, 98, + 169, 161, 32, 214, 116, 121, 179, 76, 10, 246, 79, 64, 54, 131, + 126, 28, 78, 96, 251, 137, 213, 210, 112, 183, 65, 231, 134, 5, + 53, 108, 160, 244, 56, 157, 213, 106, 89, 5, 198, 192, 97, 216, + 31, 241, 190, 7, 234, 148, 50, 83, 196, 55, 79, 107, 132, 148, + 175, 63, 252, 197, 123, 172, 121, 97, 153, 218, 166, 83, 193, 77, + 109, 13, 68, 227, 57, 95, 63, 142, 92, 140, 18, 154, 144, 1, + 194, 97, 82, 147, 89, 66, 211, 95, 76, 95, 177, 1, 122, 84, + 252, 59, 14, 149, 156, 251, 224, 115, 59, 223, 107, 95, 63, 77, + 59, 111, 237, 35, 44, 59, 128, 156, 238, 91, 57, 173, 62, 27, + 209, 51, 18, 242, 141, 208, 214, 64, 233, 177, 85, 229, 216, 11, + 189, 118, 248, 132, 60, 104, 155, 69, 182, 169, 202, 169, 57, 63, + 127, 105, 66, 170, 78, 252, 115, 195, 126, 192, 78, 57, 146, 195, + 81, 164, 147, 88, 226, 179, 220, 29, 192, 201, 105, 39, 190, 33, + 40, 156, 187, 232, 85, 246, 105, 143, 172, 162, 247, 188, 116, 170, + 231, 186, 28, 199, 0, 111, 224, 115, 140, 17, 209, 227, 72, 136, + 40, 225, 190, 248, 251, 59, 93, 61, 59, 111, 176, 64, 22, 213, + 68, 121, 164, 202, 205, 211, 206, 27, 28, 179, 116, 31, 251, 105, + 86, 201, 228, 200, 223, 186, 200, 90, 95, 102, 79, 58, 70, 16, + 171, 30, 75, 78, 52, 36, 110, 220, 119, 203, 238, 144, 46, 193, + 205, 219, 224, 190, 255, 142, 67, 222, 84, 13, 154, 155, 207, 94, + 228, 76, 166, 206, 191, 12, 106, 152, 99, 24, 15, 193, 11, 113, + 139, 75, 14, 91, 64, 249, 163, 18, 44, 108, 198, 29, 104, 210, + 156, 251, 169, 58, 83, 113, 80, 103, 235, 140, 88, 3, 13, 94, + 107, 155, 194, 70, 160, 138, 233, 7, 50, 250, 93, 96, 112, 74, + 64, 178, 160, 214, 44, 210, 211, 221, 226, 252, 109, 184, 165, 168, + 57, 3, 134, 181, 142, 196, 172, 77, 182, 81, 207, 150, 135, 54, + 172, 120, 120, 253, 41, 96, 161, 184, 85, 253, 198, 14, 100, 143, + 27, 14, 85, 177, 218, 116, 239, 201, 233, 76, 143, 97, 221, 218, + 155, 111, 19, 21, 124, 176, 87, 17, 164, 162, 212, 201, 54, 157, + 3, 15, 212, 207, 116, 63, 100, 223, 164, 116, 157, 166, 155, 38, + 114, 110, 3, 104, 54, 61, 109, 242, 69, 128, 79, 250, 127, 74, + 20, 182, 14, 246, 87, 60, 82, 20, 196, 47, 58, 157, 38, 7, + 123, 38, 225, 97, 2, 112, 244, 51, 87, 3, 223, 249, 227, 49, + 130, 161, 220, 200, 111, 179, 107, 253, 23, 247, 204, 151, 151, 80, + 120, 228, 232, 234, 29, 171, 248, 197, 253, 106, 68, 125, 247, 215, + 186, 9, 66, 93, 50, 151, 179, 54, 92, 178, 143, 201, 28, 199, + 189, 12, 69, 89, 203, 182, 68, 7, 238, 82, 9, 6, 56, 158, + 0, 201, 58, 198, 127, 80, 138, 161, 174, 215, 240, 6, 207, 192, + 204, 240, 207, 234, 199, 59, 32, 125, 40, 160, 193, 31, 134, 190, + 143, 0, 158, 117, 142, 82, 252, 255, 93, 53, 204, 132, 14, 50, + 197, 39, 147, 220, 205, 154, 153, 160, 65, 218, 22, 235, 196, 244, + 76, 53, 199, 67, 58, 121, 113, 242, 134, 75, 204, 190, 91, 175, + 148, 27, 20, 145, 140, 26, 99, 215, 151, 212, 144, 11, 202, 133, + 183, 130, 62, 181, 19, 216, 197, 249, 206, 239, 167, 150, 62, 19, + 152, 202, 8, 193, 94, 70, 101, 230, 248, 157, 195, 166, 217, 177, + 49, 15, 54, 82, 143, 30, 248, 30, 27, 207, 155, 62, 223, 204, + 90, 122, 39, 1, 187, 51, 31, 175, 26, 165, 145, 38, 107, 0, + 198, 132, 117, 216, 136, 43, 153, 66, 136, 160, 95, 211, 1, 90, + 130, 40, 203, 224, 68, 245, 202, 180, 90, 54, 213, 77, 250, 216, + 128, 90, 161, 211, 225, 251, 116, 142, 14, 161, 27, 159, 34, 10, + 91, 126, 84, 179, 59, 172, 115, 59, 56, 168, 139, 137, 149, 72, + 227, 17, 103, 218, 66, 139, 235, 111, 237, 19, 17, 247, 1, 171, + 119, 0, 7, 231, 221, 197, 25, 247, 137, 124, 9, 29, 50, 224, + 166, 76, 93, 54, 19, 122, 71, 194, 230, 186, 197, 51, 39, 141, + 187, 60, 254, 234, 27, 91, 79, 128, 243, 67, 76, 245, 216, 108, + 206, 226, 244, 90, 108, 236, 51, 238, 38, 88, 134, 242, 224, 235, + 75, 114, 195, 124, 208, 1, 239, 90, 222, 138, 93, 15, 184, 168, + 171, 60, 44, 15, 145, 28, 238, 233, 169, 54, 34, 82, 95, 162, + 22, 192, 231, 39, 224, 17, 207, 73, 56, 163, 34, 204, 153, 250, + 58, 90, 156, 80, 25, 43, 128, 145, 2, 198, 67, 126, 243, 213, + 103, 220, 226, 207, 11, 204, 35, 118, 82, 143, 221, 178, 131, 87, + 178, 114, 162, 55, 198, 24, 15, 131, 106, 81, 58, 92, 250, 82, + 89, 1, 31, 4, 140, 26, 42, 236, 197, 221, 145, 196, 35, 248, + 254, 109, 147, 73, 23, 39, 230, 4, 178, 237, 30, 86, 127, 175, + 161, 47, 18, 59, 117, 37, 243, 92, 255, 28, 242, 227, 20, 132, + 65, 122, 173, 176, 7, 78, 191, 46, 103, 17, 85, 186, 63, 239, + 71, 93, 61, 94, 48, 86, 213, 21, 89, 91, 218, 86, 87, 2, + 206, 124, 154, 178, 118, 175, 43, 250, 106, 120, 251, 97, 126, 105, + 164, 168, 209, 246, 71, 242, 83, 52, 240, 49, 51, 224, 223, 148, + 169, 179, 98, 62, 255, 67, 70, 163, 69, 115, 149, 45, 232, 229, + 60, 37, 23, 69, 121, 198, 26, 32, 94, 235, 57, 20, 14, 182, + 175, 245, 5, 21, 160, 102, 106, 122, 128, 165, 124, 201, 7, 138, + 164, 34, 16, 93, 148, 100, 231, 1, 44, 196, 85, 227, 169, 206, + 213, 142, 146, 206, 20, 210, 140, 235, 102, 149, 184, 157, 155, 96, + 134, 150, 22, 168, 230, 242, 54, 120, 249, 77, 100, 203, 144, 239, + 22, 167, 188, 248, 126, 189, 41, 66, 62, 165, 238, 69, 84, 177, + 7, 170, 231, 2, 13, 71, 151, 23, 107, 167, 40, 216, 246, 210, + 167, 255, 178, 239, 7, 156, 120, 31, 143, 235, 243, 95, 112, 221, + 76, 177, 96, 206, 63, 0, 221, 207, 219, 239, 90, 181, 199, 247, + 148, 254, 101, 99, 133, 122, 69, 28, 127, 55, 132, 72, 5, 174, + 234, 246, 179, 25, 81, 51, 254, 195, 233, 67, 217, 49, 245, 249, + 1, 216, 195, 114, 134, 205, 195, 205, 160, 137, 78, 222, 34, 201, + 109, 195, 66, 117, 111, 240, 118, 136, 243, 235, 56, 168, 157, 186, + 80, 207, 45, 71, 243, 51, 51, 187, 177, 24, 149, 241, 251, 46, + 66, 243, 127, 162, 66, 123, 93, 184, 55, 104, 237, 85, 195, 205, + 175, 134, 85, 143, 25, 184, 208, 71, 196, 77, 46, 136, 167, 58, + 87, 87, 196, 121, 115, 174, 151, 175, 8, 145, 21, 19, 69, 238, + 235, 175, 158, 40, 75, 115, 45, 234, 159, 141, 188, 130, 133, 133, + 0, 178, 132, 138, 45, 73, 86, 242, 228, 208, 153, 111, 13, 78, + 175, 254, 116, 166, 62, 105, 155, 130, 182, 198, 253, 60, 255, 114, + 38, 9, 155, 255, 235, 218, 95, 113, 86, 127, 226, 221, 220, 186, + 119, 60, 46, 101, 220, 126, 242, 87, 84, 25, 248, 0, 126, 207, + 169, 122, 99, 235, 24, 201, 237, 113, 122, 220, 122, 41, 236, 72, + 115, 241, 133, 61, 55, 2, 57, 74, 37, 177, 243, 237, 150, 190, + 131, 153, 93, 129, 77, 65, 230, 39, 108, 75, 242, 102, 79, 239, + 43, 166, 52, 105, 137, 14, 155, 122, 226, 37, 183, 57, 116, 118, + 108, 202, 178, 58, 132, 97, 74, 17, 233, 210, 105, 75, 240, 71, + 224, 83, 234, 215, 83, 17, 98, 218, 3, 7, 135, 173, 68, 82, + 156, 205, 26, 84, 237, 0, 59, 148, 201, 52, 81, 75, 51, 1, + 28, 77, 45, 164, 164, 208, 87, 76, 203, 64, 244, 130, 154, 102, + 43, 235, 209, 98, 22, 98, 22, 249, 85, 238, 246, 211, 99, 69, + 36, 216, 213, 61, 28, 167, 76, 175, 67, 196, 82, 246, 232, 60, + 23, 29, 147, 21, 254, 165, 132, 143, 100, 19, 32, 11, 185, 230, + 174, 244, 248, 81, 232, 63, 223, 179, 86, 105, 2, 226, 243, 108, + 135, 122, 166, 20, 34, 85, 195, 81, 104, 120, 89, 213, 247, 63, + 127, 204, 203, 152, 119, 239, 108, 252, 209, 67, 197, 179, 9, 131, + 149, 128, 115, 152, 192, 159, 69, 73, 35, 77, 8, 133, 195, 169, + 110, 187, 132, 105, 252, 96, 101, 127, 188, 183, 29, 48, 31, 21, + 221, 53, 77, 118, 103, 241, 95, 21, 230, 24, 196, 14, 54, 156, + 77, 123, 65, 209, 153, 31, 41, 6, 167, 48, 107, 147, 63, 78, + 246, 197, 180, 138, 114, 205, 14, 97, 77, 177, 152, 47, 232, 150, + 27, 254, 40, 77, 243, 195, 31, 64, 188, 194, 151, 166, 23, 141, + 244, 235, 138, 35, 114, 65, 192, 48, 65, 182, 100, 91, 24, 27, + 193, 155, 224, 166, 227, 146, 36, 24, 103, 12, 206, 230, 71, 182, + 189, 210, 33, 196, 211, 218, 4, 226, 110, 232, 229, 34, 249, 197, + 101, 168, 237, 175, 248, 130, 47, 44, 205, 65, 109, 54, 176, 31, + 9, 132, 114, 241, 109, 20, 133, 216, 242, 236, 105, 24, 34, 108, + 16, 181, 89, 187, 168, 101, 0, 239, 158, 39, 16, 252, 119, 190, + 10, 116, 79, 5, 19, 73, 76, 250, 241, 228, 240, 251, 202, 227, + 248, 140, 157, 199, 45, 227, 116, 78, 172, 237, 110, 252, 80, 189, + 160, 255, 170, 243, 243, 121, 125, 87, 180, 231, 173, 58, 88, 99, + 27, 27, 27, 219, 120, 91, 49, 185, 93, 132, 230, 74, 109, 168, + 59, 2, 142, 2, 41, 45, 9, 207, 209, 175, 48, 125, 240, 217, + 16, 130, 30, 61, 111, 125, 3, 149, 21, 116, 27, 179, 17, 88, + 63, 146, 108, 19, 136, 188, 4, 43, 246, 55, 41, 221, 30, 211, + 72, 78, 241, 17, 99, 114, 68, 89, 176, 43, 215, 29, 185, 239, + 63, 186, 36, 112, 74, 87, 37, 186, 201, 231, 195, 119, 119, 125, + 0, 152, 126, 31, 50, 227, 54, 169, 136, 128, 205, 232, 194, 41, + 248, 108, 15, 16, 126, 112, 72, 54, 85, 48, 129, 250, 156, 172, + 122, 227, 232, 70, 90, 1, 93, 125, 129, 66, 92, 206, 11, 67, + 182, 47, 246, 29, 66, 213, 102, 174, 133, 53, 42, 29, 207, 23, + 37, 35, 100, 240, 80, 8, 66, 163, 122, 187, 251, 26, 146, 20, + 20, 27, 6, 123, 0, 95, 134, 114, 42, 179, 66, 106, 3, 206, + 112, 54, 202, 186, 183, 121, 63, 178, 49, 82, 199, 239, 185, 102, + 5, 194, 117, 45, 33, 91, 189, 63, 109, 134, 14, 15, 18, 21, + 81, 166, 38, 250, 95, 200, 191, 234, 162, 70, 86, 3, 225, 226, + 186, 183, 186, 210, 86, 251, 147, 71, 241, 17, 220, 122, 227, 98, + 252, 138, 36, 168, 134, 7, 209, 82, 223, 4, 30, 56, 105, 239, + 43, 11, 175, 161, 201, 84, 124, 44, 195, 236, 6, 167, 54, 42, + 64, 250, 117, 232, 140, 65, 73, 99, 16, 224, 184, 120, 75, 34, + 13, 10, 44, 16, 241, 23, 90, 48, 176, 43, 0, 233, 46, 98, + 113, 227, 29, 12, 75, 22, 150, 156, 203, 225, 198, 89, 193, 173, + 187, 178, 19, 5, 161, 246, 72, 80, 76, 122, 121, 80, 104, 197, + 111, 241, 141, 150, 202, 8, 8, 35, 137, 37, 32, 183, 117, 103, + 56, 203, 233, 211, 39, 15, 141, 200, 134, 200, 172, 150, 96, 146, + 30, 121, 249, 9, 131, 68, 63, 58, 138, 104, 63, 60, 26, 180, + 13, 121, 130, 195, 212, 20, 76, 248, 171, 23, 147, 12, 45, 87, + 172, 216, 17, 244, 179, 108, 30, 192, 252, 233, 167, 173, 88, 164, + 196, 58, 239, 86, 88, 226, 161, 49, 71, 71, 5, 180, 155, 138, + 152, 177, 157, 155, 44, 53, 115, 204, 171, 94, 249, 135, 160, 51, + 233, 240, 174, 109, 91, 161, 42, 181, 28, 137, 181, 73, 191, 193, + 171, 108, 223, 28, 167, 170, 83, 173, 14, 81, 199, 172, 142, 162, + 124, 21, 50, 154, 68, 29, 163, 43, 56, 102, 199, 60, 185, 84, + 73, 139, 17, 68, 156, 37, 176, 43, 143, 44, 145, 183, 184, 223, + 134, 24, 167, 94, 253, 6, 80, 233, 255, 23, 139, 172, 114, 245, + 105, 136, 7, 244, 10, 102, 157, 86, 89, 247, 200, 241, 77, 110, + 234, 13, 153, 133, 220, 167, 241, 168, 111, 95, 222, 35, 169, 159, + 239, 112, 63, 152, 99, 136, 249, 40, 211, 194, 208, 67, 69, 98, + 216, 227, 208, 218, 177, 201, 210, 226, 226, 122, 165, 32, 184, 113, + 184, 173, 208, 132, 57, 219, 45, 51, 213, 173, 54, 128, 14, 197, + 218, 156, 123, 158, 71, 174, 41, 16, 215, 79, 10, 165, 5, 29, + 35, 3, 109, 90, 29, 175, 137, 86, 43, 189, 37, 172, 147, 190, + 29, 18, 53, 207, 167, 52, 70, 86, 174, 189, 230, 81, 133, 41, + 150, 133, 201, 116, 137, 219, 212, 53, 160, 246, 148, 12, 94, 14, + 110, 122, 66, 164, 204, 96, 169, 105, 127, 182, 203, 225, 54, 245, + 200, 214, 203, 15, 200, 152, 165, 144, 35, 114, 237, 88, 156, 133, + 252, 183, 69, 215, 37, 18, 118, 99, 145, 107, 101, 209, 54, 184, + 9, 217, 10, 204, 172, 231, 104, 182, 158, 90, 236, 251, 182, 181, + 36, 81, 247, 109, 100, 149, 162, 172, 29, 248, 50, 214, 17, 217, + 123, 100, 36, 54, 14, 223, 177, 8, 7, 222, 94, 206, 114, 12, + 103, 27, 222, 15, 61, 66, 51, 60, 237, 219, 139, 160, 35, 156, + 225, 151, 11, 103, 129, 175, 163, 188, 216, 59, 244, 111, 236, 52, + 151, 210, 164, 123, 121, 40, 161, 239, 94, 32, 215, 125, 214, 41, + 216, 20, 41, 221, 64, 123, 134, 32, 51, 235, 193, 220, 2, 186, + 180, 162, 3, 105, 135, 202, 122, 157, 222, 65, 42, 61, 123, 143, + 165, 34, 232, 125, 25, 18, 213, 214, 115, 38, 72, 24, 50, 52, + 51, 44, 166, 2, 40, 49, 34, 119, 40, 164, 34, 11, 226, 95, + 254, 33, 241, 118, 130, 249, 110, 204, 204, 127, 27, 230, 3, 165, + 18, 145, 36, 200, 121, 21, 194, 89, 223, 26, 112, 157, 193, 40, + 27, 49, 4, 82, 75, 129, 34, 141, 174, 114, 123, 240, 248, 42, + 216, 139, 207, 198, 92, 253, 129, 32, 156, 14, 145, 254, 65, 173, + 74, 107, 226, 114, 67, 21, 233, 48, 125, 17, 236, 3, 206, 68, + 134, 169, 227, 188, 27, 223, 198, 19, 155, 35, 65, 92, 101, 161, + 247, 143, 166, 197, 81, 44, 118, 218, 144, 159, 150, 187, 178, 77, + 237, 113, 225, 78, 143, 43, 67, 82, 115, 251, 20, 0, 158, 195, + 106, 239, 7, 152, 129, 202, 130, 170, 184, 154, 201, 57, 237, 179, + 1, 234, 119, 214, 85, 114, 150, 177, 102, 190, 223, 221, 196, 1, + 61, 32, 73, 94, 10, 0, 77, 97, 39, 4, 92, 132, 199, 96, + 167, 109, 162, 236, 176, 62, 198, 148, 114, 51, 60, 14, 176, 170, + 244, 152, 251, 84, 239, 126, 192, 30, 207, 118, 75, 223, 109, 201, + 179, 167, 120, 119, 113, 204, 235, 122, 99, 102, 4, 180, 187, 91, + 197, 190, 70, 65, 216, 220, 71, 222, 254, 218, 65, 37, 107, 110, + 126, 92, 217, 243, 164, 134, 136, 235, 192, 170, 33, 214, 223, 230, + 215, 63, 4, 193, 218, 203, 6, 8, 58, 211, 16, 58, 194, 176, + 129, 14, 91, 154, 251, 76, 53, 2, 79, 217, 157, 240, 91, 36, + 185, 83, 175, 52, 237, 168, 114, 151, 6, 134, 177, 238, 12, 67, + 7, 59, 246, 18, 129, 123, 129, 74, 19, 111, 29, 246, 219, 98, + 186, 137, 198, 20, 91, 109, 142, 69, 11, 29, 129, 145, 29, 103, + 188, 101, 204, 158, 32, 106, 105, 136, 231, 157, 49, 80, 139, 74, + 120, 143, 164, 249, 52, 210, 206, 203, 67, 207, 114, 74, 0, 5, + 94, 188, 7, 146, 185, 99, 167, 7, 111, 97, 53, 241, 107, 228, + 237, 182, 84, 111, 214, 48, 191, 228, 8, 51, 2, 200, 98, 70, + 144, 103, 168, 24, 234, 128, 22, 34, 231, 236, 183, 231, 166, 15, + 83, 168, 100, 14, 112, 207, 150, 8, 132, 109, 39, 85, 201, 132, + 68, 78, 207, 236, 93, 34, 192, 210, 126, 48, 199, 64, 183, 19, + 39, 224, 253, 86, 199, 155, 173, 126, 6, 209, 213, 248, 167, 214, + 144, 249, 199, 4, 153, 219, 191, 105, 102, 4, 121, 205, 6, 28, + 166, 148, 76, 161, 168, 105, 136, 2, 46, 127, 59, 81, 156, 28, + 13, 179, 152, 129, 200, 110, 195, 60, 106, 6, 100, 0, 142, 219, + 15, 40, 131, 170, 86, 10, 155, 101, 66, 52, 118, 250, 94, 106, + 57, 5, 225, 6, 80, 51, 118, 49, 14, 184, 60, 157, 253, 103, + 253, 36, 242, 242, 200, 2, 221, 231, 119, 160, 206, 116, 255, 74, + 27, 127, 140, 231, 42, 218, 81, 211, 45, 214, 246, 220, 1, 14, + 22, 183, 180, 76, 182, 77, 51, 203, 243, 151, 169, 201, 33, 66, + 195, 137, 238, 22, 158, 43, 171, 220, 107, 17, 209, 81, 39, 86, + 58, 133, 170, 163, 253, 72, 47, 152, 161, 117, 125, 98, 227, 98, + 109, 78, 121, 253, 238, 160, 172, 46, 55, 73, 122, 16, 166, 150, + 160, 52, 204, 9, 154, 31, 249, 151, 54, 152, 73, 196, 134, 227, + 30, 246, 64, 44, 92, 194, 210, 106, 188, 22, 158, 37, 158, 216, + 74, 217, 156, 27, 236, 37, 216, 91, 47, 10, 181, 138, 15, 73, + 108, 142, 114, 30, 179, 192, 17, 123, 102, 90, 212, 248, 173, 63, + 64, 136, 255, 198, 203, 247, 132, 92, 123, 205, 106, 86, 197, 71, + 89, 35, 110, 19, 120, 38, 35, 36, 137, 129, 234, 182, 66, 10, + 19, 252, 19, 41, 42, 43, 211, 157, 178, 93, 48, 247, 27, 147, + 148, 7, 238, 189, 117, 217, 12, 220, 103, 74, 131, 13, 2, 209, + 62, 149, 94, 225, 14, 55, 158, 208, 230, 249, 51, 255, 91, 236, + 151, 251, 114, 50, 224, 248, 34, 150, 192, 95, 73, 1, 4, 15, + 169, 255, 193, 90, 134, 1, 252, 36, 118, 218, 253, 119, 53, 185, + 175, 154, 174, 82, 64, 208, 102, 91, 249, 45, 242, 156, 20, 202, + 172, 157, 211, 18, 35, 215, 70, 36, 5, 104, 108, 191, 50, 221, + 9, 229, 4, 240, 228, 174, 145, 77, 154, 255, 247, 223, 109, 201, + 62, 25, 33, 248, 224, 100, 145, 177, 174, 20, 154, 90, 249, 239, + 240, 2, 3, 7, 197, 86, 91, 130, 207, 26, 189, 48, 153, 233, + 221, 176, 160, 193, 121, 31, 116, 40, 247, 61, 230, 21, 161, 189, + 20, 244, 172, 53, 29, 170, 71, 162, 193, 139, 104, 0, 109, 212, + 55, 136, 72, 139, 115, 7, 190, 134, 180, 101, 205, 28, 246, 91, + 146, 90, 29, 238, 41, 112, 25, 68, 8, 159, 116, 222, 159, 171, + 204, 130, 41, 222, 241, 162, 219, 154, 202, 175, 83, 227, 120, 25, + 230, 44, 213, 225, 192, 152, 190, 193, 76, 118, 209, 74, 151, 186, + 156, 52, 255, 241, 127, 196, 46, 130, 226, 132, 183, 183, 122, 231, + 139, 242, 143, 235, 198, 147, 172, 122, 125, 107, 241, 105, 126, 12, + 165, 167, 159, 203, 252, 154, 163, 47, 165, 240, 118, 40, 27, 219, + 8, 126, 34, 154, 4, 243, 213, 107, 231, 223, 53, 252, 18, 211, + 189, 252, 9, 27, 32, 113, 56, 102, 151, 194, 124, 249, 254, 62, + 94, 180, 9, 119, 113, 108, 249, 145, 111, 179, 150, 120, 17, 91, + 29, 124, 224, 202, 252, 244, 52, 126, 18, 148, 153, 123, 5, 15, + 88, 147, 208, 43, 155, 220, 239, 33, 198, 246, 186, 55, 187, 83, + 173, 242, 63, 212, 201, 111, 180, 96, 29, 127, 208, 88, 112, 89, + 9, 130, 79, 219, 175, 171, 201, 63, 37, 4, 18, 173, 200, 251, + 55, 178, 36, 16, 35, 168, 255, 148, 63, 121, 224, 54, 115, 218, + 188, 24, 171, 133, 19, 9, 163, 61, 41, 111, 20, 228, 244, 7, + 31, 43, 94, 0, 209, 141, 183, 165, 137, 28, 40, 97, 1, 247, + 18, 60, 82, 166, 86, 177, 177, 104, 238, 110, 7, 222, 54, 88, + 48, 13, 109, 59, 246, 85, 168, 158, 218, 216, 244, 143, 141, 139, + 115, 128, 224, 239, 42, 189, 215, 101, 99, 218, 198, 139, 53, 63, + 9, 214, 105, 160, 199, 208, 239, 71, 68, 207, 245, 239, 118, 120, + 140, 167, 123, 227, 32, 88, 26, 9, 167, 20, 171, 179, 159, 174, + 55, 152, 14, 17, 164, 39, 162, 172, 87, 221, 133, 3, 63, 0, + 166, 156, 232, 238, 147, 73, 62, 110, 179, 46, 67, 145, 230, 221, + 176, 77, 149, 16, 142, 77, 58, 91, 222, 131, 67, 39, 233, 7, + 193, 46, 229, 102, 172, 27, 201, 27, 194, 137, 252, 132, 103, 150, + 247, 228, 241, 70, 251, 149, 47, 47, 86, 13, 25, 170, 148, 234, + 108, 119, 119, 220, 5, 219, 238, 57, 118, 65, 171, 131, 58, 251, + 230, 43, 169, 231, 244, 188, 172, 140, 248, 45, 186, 132, 96, 120, + 234, 51, 132, 230, 41, 238, 101, 165, 149, 216, 159, 198, 63, 226, + 171, 208, 82, 96, 42, 131, 128, 148, 243, 157, 250, 172, 126, 153, + 102, 199, 26, 180, 125, 232, 103, 90, 65, 254, 136, 175, 34, 64, + 53, 173, 71, 55, 102, 137, 196, 0, 229, 103, 144, 20, 105, 217, + 118, 62, 221, 241, 131, 42, 159, 252, 109, 150, 201, 187, 191, 196, + 185, 183, 226, 123, 85, 25, 186, 169, 182, 101, 117, 215, 162, 150, + 91, 132, 146, 245, 9, 87, 107, 233, 76, 127, 0, 46, 136, 16, + 48, 143, 28, 115, 121, 8, 193, 188, 68, 24, 167, 241, 48, 150, + 125, 199, 7, 153, 74, 130, 97, 3, 40, 229, 219, 199, 177, 67, + 57, 221, 173, 186, 142, 253, 157, 135, 24, 220, 116, 113, 243, 94, + 229, 254, 14, 101, 109, 173, 32, 86, 95, 189, 179, 158, 84, 37, + 230, 14, 235, 90, 3, 116, 85, 9, 246, 13, 81, 120, 8, 69, + 111, 67, 31, 209, 23, 156, 255, 237, 124, 115, 31, 47, 0, 4, + 92, 53, 111, 86, 123, 144, 78, 139, 255, 93, 224, 72, 59, 253, + 97, 49, 165, 40, 23, 249, 106, 78, 99, 236, 245, 33, 223, 31, + 230, 211, 44, 177, 245, 139, 55, 155, 230, 222, 234, 102, 251, 38, + 19, 202, 23, 185, 107, 47, 215, 39, 50, 32, 163, 176, 144, 76, + 148, 3, 151, 99, 64, 59, 254, 127, 204, 106, 93, 186, 57, 139, + 218, 82, 101, 175, 183, 160, 181, 78, 42, 179, 182, 143, 137, 184, + 19, 143, 52, 185, 38, 82, 54, 123, 127, 167, 64, 200, 66, 125, + 87, 202, 206, 34, 189, 177, 45, 30, 192, 187, 192, 57, 40, 143, + 134, 142, 32, 136, 15, 201, 184, 9, 73, 167, 191, 20, 162, 160, + 96, 32, 95, 56, 141, 18, 141, 211, 191, 72, 86, 210, 89, 76, + 52, 157, 187, 143, 157, 6, 101, 249, 38, 32, 180, 199, 147, 25, + 95, 110, 85, 98, 46, 211, 117, 149, 119, 65, 212, 192, 160, 58, + 42, 156, 66, 113, 100, 72, 225, 26, 3, 207, 48, 192, 22, 71, + 48, 173, 206, 62, 123, 58, 37, 135, 205, 23, 95, 218, 211, 195, + 71, 77, 187, 105, 105, 223, 44, 68, 114, 238, 90, 135, 156, 80, + 201, 230, 165, 161, 88, 197, 144, 133, 40, 192, 77, 184, 12, 108, + 172, 255, 175, 201, 111, 215, 192, 255, 107, 247, 82, 89, 178, 152, + 147, 97, 98, 154, 97, 115, 143, 245, 59, 84, 63, 151, 56, 3, + 146, 2, 165, 164, 84, 214, 78, 231, 14, 92, 136, 88, 132, 52, + 44, 135, 55, 45, 226, 116, 130, 87, 17, 253, 113, 127, 221, 152, + 56, 226, 132, 85, 203, 31, 52, 115, 176, 187, 95, 130, 201, 21, + 186, 156, 152, 75, 166, 213, 117, 205, 189, 238, 1, 146, 193, 192, + 26, 24, 0, 0, 165, 243, 207, 250, 254, 48, 217, 190, 228, 62, + 185, 3, 151, 110, 228, 183, 21, 173, 113, 140, 246, 42, 101, 30, + 68, 246, 219, 186, 220, 234, 187, 199, 213, 196, 7, 98, 0, 114, + 222, 136, 20, 236, 181, 70, 134, 32, 60, 243, 253, 14, 104, 29, + 115, 45, 238, 50, 190, 69, 159, 57, 58, 221, 109, 46, 255, 229, + 33, 155, 89, 78, 61, 130, 132, 146, 244, 242, 191, 131, 174, 41, + 115, 243, 138, 186, 50, 162, 45, 218, 79, 113, 137, 139, 238, 243, + 40, 199, 223, 202, 47, 146, 86, 69, 198, 155, 77, 227, 51, 47, + 14, 110, 170, 154, 92, 54, 251, 163, 121, 230, 51, 63, 219, 48, + 170, 241, 100, 104, 250, 146, 57, 77, 47, 214, 41, 172, 87, 188, + 83, 190, 221, 111, 134, 61, 121, 107, 71, 157, 81, 59, 211, 254, + 207, 162, 168, 117, 89, 102, 202, 12, 245, 129, 241, 94, 200, 88, + 76, 122, 173, 70, 111, 12, 130, 94, 120, 106, 225, 83, 180, 120, + 251, 227, 91, 145, 209, 187, 0, 157, 166, 54, 45, 246, 138, 78, + 46, 111, 202, 205, 171, 252, 203, 130, 93, 192, 239, 115, 56, 208, + 111, 108, 140, 97, 135, 221, 85, 60, 45, 27, 248, 113, 63, 97, + 186, 53, 236, 206, 244, 7, 20, 75, 78, 84, 56, 29, 174, 241, + 89, 222, 84, 158, 71, 255, 95, 85, 140, 207, 95, 39, 98, 55, + 91, 19, 206, 236, 76, 223, 69, 174, 160, 130, 246, 141, 161, 176, + 192, 249, 76, 95, 197, 53, 140, 22, 93, 193, 255, 120, 56, 80, + 152, 115, 22, 139, 188, 209, 5, 199, 192, 219, 126, 125, 151, 248, + 23, 90, 134, 25, 193, 39, 158, 137, 199, 12, 140, 144, 165, 24, + 143, 248, 49, 145, 123, 12, 235, 221, 20, 97, 250, 184, 57, 201, + 95, 202, 25, 15, 157, 186, 69, 194, 227, 166, 79, 31, 196, 21, + 236, 151, 40, 129, 150, 63, 190, 255, 111, 110, 59, 156, 159, 168, + 125, 115, 132, 161, 120, 125, 70, 131, 144, 144, 8, 14, 142, 203, + 113, 152, 104, 184, 19, 48, 81, 153, 238, 215, 159, 55, 58, 233, + 70, 124, 87, 129, 163, 208, 49, 17, 2, 141, 129, 32, 30, 55, + 60, 81, 179, 120, 182, 20, 49, 200, 211, 207, 99, 90, 31, 46, + 48, 19, 120, 58, 161, 226, 172, 218, 26, 84, 199, 92, 115, 199, + 196, 85, 241, 129, 176, 75, 254, 97, 143, 50, 6, 116, 226, 202, + 209, 176, 58, 74, 23, 162, 202, 58, 225, 102, 98, 113, 132, 70, + 20, 118, 162, 65, 114, 87, 185, 133, 102, 241, 83, 211, 102, 84, + 175, 113, 87, 160, 160, 45, 86, 155, 135, 69, 64, 248, 99, 104, + 151, 255, 62, 88, 155, 222, 185, 186, 136, 7, 124, 130, 238, 136, + 6, 246, 167, 190, 86, 177, 108, 27, 170, 136, 22, 102, 205, 124, + 157, 75, 199, 108, 37, 55, 11, 50, 91, 29, 94, 201, 46, 131, + 120, 169, 243, 127, 154, 247, 41, 173, 227, 17, 98, 131, 227, 177, + 244, 213, 101, 154, 12, 31, 146, 57, 124, 50, 242, 166, 238, 163, + 214, 47, 34, 192, 23, 59, 106, 154, 156, 212, 223, 125, 177, 26, + 31, 129, 242, 44, 189, 173, 194, 201, 53, 85, 49, 93, 139, 105, + 207, 21, 173, 153, 13, 224, 131, 68, 179, 163, 84, 8, 187, 231, + 58, 160, 203, 102, 14, 183, 180, 118, 143, 167, 145, 224, 222, 183, + 54, 63, 92, 4, 247, 50, 103, 123, 116, 212, 55, 54, 93, 154, + 130, 115, 32, 173, 235, 42, 35, 30, 38, 88, 101, 29, 64, 232, + 58, 90, 143, 173, 250, 214, 87, 87, 222, 89, 222, 11, 22, 186, + 167, 219, 42, 113, 129, 125, 13, 94, 15, 177, 93, 197, 16, 26, + 88, 45, 33, 247, 112, 180, 78, 81, 119, 52, 64, 227, 147, 80, + 92, 36, 96, 175, 7, 126, 14, 54, 205, 51, 73, 209, 106, 181, + 198, 209, 194, 32, 38, 160, 228, 58, 221, 116, 83, 143, 224, 137, + 54, 239, 115, 8, 107, 83, 208, 184, 130, 166, 187, 207, 144, 193, + 175, 4, 159, 84, 78, 192, 205, 246, 166, 160, 167, 32, 17, 251, + 45, 114, 183, 31, 5, 164, 9, 154, 20, 235, 21, 35, 72, 116, + 214, 143, 48, 78, 69, 21, 163, 155, 199, 8, 146, 67, 46, 60, + 124, 243, 68, 91, 246, 148, 151, 17, 158, 95, 127, 12, 138, 19, + 247, 104, 252, 242, 67, 54, 100, 182, 149, 62, 107, 181, 127, 16, + 224, 71, 191, 46, 184, 78, 8, 86, 82, 95, 130, 4, 154, 233, + 215, 175, 117, 144, 56, 2, 214, 223, 103, 180, 146, 212, 145, 138, + 247, 240, 94, 98, 84, 132, 198, 54, 171, 235, 136, 86, 51, 56, + 34, 183, 233, 137, 15, 235, 176, 0, 63, 25, 107, 162, 124, 32, + 225, 208, 121, 110, 108, 121, 41, 12, 124, 118, 140, 17, 252, 12, + 132, 209, 39, 26, 178, 168, 63, 48, 61, 214, 16, 224, 58, 192, + 113, 28, 66, 170, 28, 203, 24, 101, 230, 226, 153, 224, 192, 247, + 163, 215, 85, 253, 166, 86, 0, 39, 239, 255, 48, 202, 71, 29, + 221, 99, 169, 220, 250, 146, 246, 208, 147, 62, 236, 125, 188, 75, + 104, 164, 95, 43, 47, 151, 189, 241, 247, 198, 200, 10, 78, 58, + 13, 250, 103, 41, 43, 178, 83, 188, 194, 74, 47, 44, 182, 11, + 235, 2, 65, 4, 110, 181, 71, 35, 23, 168, 193, 100, 226, 46, + 209, 133, 203, 242, 116, 97, 187, 234, 189, 176, 135, 90, 63, 120, + 208, 201, 155, 144, 206, 37, 193, 209, 176, 104, 55, 146, 233, 7, + 5, 112, 171, 229, 28, 22, 80, 33, 34, 10, 109, 115, 44, 100, + 99, 6, 97, 121, 113, 211, 210, 106, 228, 84, 17, 186, 128, 238, + 27, 249, 234, 224, 92, 147, 72, 172, 238, 91, 36, 17, 3, 123, + 239, 230, 4, 77, 172, 119, 133, 73, 30, 91, 118, 100, 235, 88, + 240, 24, 108, 120, 195, 85, 115, 233, 245, 200, 199, 57, 69, 229, + 94, 77, 88, 158, 193, 162, 22, 229, 202, 12, 147, 221, 141, 91, + 4, 66, 113, 36, 243, 245, 177, 139, 218, 126, 11, 98, 89, 199, + 204, 177, 237, 26, 60, 104, 214, 253, 3, 114, 230, 122, 83, 106, + 201, 63, 9, 252, 211, 19, 224, 229, 116, 64, 74, 170, 3, 211, + 7, 221, 191, 57, 59, 156, 61, 16, 64, 121, 8, 87, 203, 246, + 144, 108, 154, 21, 247, 149, 236, 210, 143, 255, 66, 183, 40, 87, + 29, 19, 229, 174, 241, 194, 78, 55, 241, 36, 88, 12, 244, 193, + 94, 168, 148, 129, 27, 101, 105, 250, 186, 203, 213, 222, 244, 66, + 34, 58, 166, 47, 105, 25, 55, 240, 252, 129, 235, 41, 162, 7, + 116, 239, 44, 119, 135, 96, 250, 83, 87, 194, 29, 13, 136, 172, + 148, 233, 72, 98, 77, 98, 212, 194, 7, 232, 195, 226, 159, 50, + 231, 254, 215, 46, 45, 213, 26, 145, 45, 166, 219, 203, 84, 56, + 64, 103, 193, 99, 48, 239, 58, 77, 245, 135, 118, 184, 231, 112, + 142, 80, 162, 231, 31, 166, 223, 137, 17, 36, 202, 102, 253, 133, + 96, 112, 75, 91, 22, 1, 117, 184, 108, 186, 190, 35, 192, 25, + 194, 32, 12, 231, 90, 90, 93, 24, 196, 229, 92, 1, 156, 32, + 77, 12, 224, 194, 206, 155, 230, 248, 147, 100, 248, 172, 178, 144, + 39, 186, 212, 130, 214, 177, 193, 67, 69, 51, 82, 180, 158, 160, + 52, 76, 87, 111, 154, 229, 154, 175, 15, 30, 251, 173, 10, 14, + 163, 185, 171, 74, 22, 142, 188, 241, 242, 30, 21, 187, 126, 79, + 45, 33, 223, 54, 84, 2, 55, 67, 204, 241, 165, 138, 102, 236, + 131, 187, 193, 119, 194, 244, 237, 106, 66, 25, 135, 195, 88, 76, + 97, 131, 18, 136, 225, 7, 9, 194, 92, 7, 68, 75, 151, 73, + 152, 35, 65, 109, 5, 61, 15, 37, 224, 82, 120, 194, 208, 109, + 57, 9, 243, 83, 31, 202, 89, 98, 241, 193, 252, 40, 201, 24, + 107, 218, 216, 51, 121, 30, 202, 70, 220, 56, 125, 137, 254, 176, + 99, 233, 249, 254, 220, 176, 221, 18, 24, 205, 221, 22, 6, 241, + 74, 21, 5, 64, 41, 103, 118, 77, 165, 120, 24, 102, 122, 168, + 34, 22, 11, 140, 165, 76, 94, 49, 64, 18, 164, 254, 7, 230, + 202, 169, 252, 49, 132, 14, 192, 76, 198, 236, 149, 108, 133, 90, + 64, 223, 191, 63, 158, 36, 102, 105, 196, 35, 172, 45, 46, 207, + 184, 93, 213, 27, 62, 87, 208, 162, 92, 90, 35, 50, 37, 10, + 45, 186, 167, 198, 60, 166, 68, 65, 64, 113, 60, 165, 13, 150, + 55, 146, 222, 29, 45, 99, 233, 240, 38, 27, 84, 41, 2, 184, + 4, 45, 49, 92, 12, 181, 183, 212, 12, 140, 7, 50, 65, 216, + 225, 224, 137, 84, 244, 133, 250, 166, 231, 145, 194, 20, 239, 52, + 48, 71, 164, 22, 20, 111, 205, 20, 56, 11, 214, 211, 22, 1, + 228, 159, 252, 90, 37, 133, 228, 114, 63, 242, 115, 45, 119, 92, + 190, 50, 98, 205, 45, 28, 122, 85, 136, 65, 124, 72, 57, 96, + 18, 167, 18, 110, 31, 216, 177, 8, 132, 251, 2, 56, 140, 88, + 124, 137, 36, 189, 211, 224, 85, 178, 105, 15, 119, 93, 208, 243, + 121, 144, 101, 209, 121, 111, 155, 1, 64, 132, 24, 1, 213, 86, + 198, 131, 159, 120, 223, 212, 191, 130, 90, 102, 81, 191, 238, 82, + 127, 212, 72, 245, 157, 8, 165, 133, 47, 98, 194, 199, 233, 101, + 84, 149, 154, 67, 62, 132, 160, 162, 63, 149, 108, 12, 10, 122, + 244, 92, 192, 30, 92, 167, 176, 1, 95, 160, 137, 11, 32, 47, + 100, 17, 51, 210, 55, 51, 114, 154, 75, 225, 37, 84, 12, 222, + 95, 239, 54, 194, 102, 241, 50, 134, 20, 149, 203, 99, 92, 249, + 200, 130, 51, 103, 137, 121, 194, 216, 196, 247, 90, 88, 110, 206, + 246, 112, 73, 155, 43, 41, 228, 83, 200, 88, 179, 55, 24, 168, + 128, 50, 189, 16, 253, 104, 99, 155, 181, 102, 222, 88, 230, 66, + 254, 17, 206, 195, 190, 161, 50, 226, 194, 119, 134, 232, 195, 240, + 123, 143, 183, 213, 217, 115, 71, 205, 59, 47, 172, 17, 91, 236, + 101, 8, 158, 117, 250, 129, 222, 166, 196, 23, 142, 135, 185, 148, + 76, 36, 184, 166, 100, 136, 21, 85, 245, 62, 208, 114, 86, 89, + 88, 194, 252, 131, 41, 127, 72, 222, 108, 92, 113, 26, 103, 165, + 136, 78, 179, 150, 254, 200, 221, 98, 49, 186, 107, 72, 35, 97, + 151, 17, 48, 29, 202, 41, 103, 193, 1, 183, 104, 35, 214, 248, + 217, 10, 63, 4, 99, 61, 179, 242, 63, 243, 101, 85, 54, 80, + 158, 14, 72, 9, 228, 154, 107, 133, 165, 236, 214, 131, 168, 26, + 224, 59, 18, 244, 179, 101, 139, 49, 13, 165, 3, 243, 105, 20, + 152, 100, 39, 212, 193, 122, 100, 95, 217, 17, 1, 111, 144, 96, + 193, 210, 151, 30, 6, 100, 251, 95, 250, 225, 246, 209, 115, 224, + 83, 46, 145, 5, 211, 183, 143, 145, 172, 238, 252, 249, 44, 128, + 68, 191, 93, 240, 120, 69, 203, 8, 128, 200, 212, 232, 230, 50, + 100, 36, 222, 25, 21, 212, 95, 166, 219, 199, 144, 4, 238, 79, + 2, 169, 203, 70, 134, 166, 67, 130, 149, 192, 178, 48, 1, 80, + 243, 167, 27, 201, 179, 121, 110, 130, 210, 238, 212, 55, 146, 254, + 56, 162, 196, 131, 153, 197, 148, 28, 93, 167, 246, 140, 63, 194, + 253, 187, 145, 131, 101, 97, 189, 48, 145, 5, 89, 47, 105, 1, + 29, 91, 95, 49, 97, 134, 152, 117, 116, 187, 241, 187, 188, 39, + 40, 230, 70, 101, 239, 143, 193, 54, 69, 156, 101, 221, 21, 206, + 130, 186, 237, 42, 46, 170, 167, 86, 76, 182, 82, 88, 224, 203, + 56, 181, 87, 241, 114, 239, 250, 59, 219, 176, 35, 145, 112, 10, + 201, 118, 30, 35, 21, 211, 74, 199, 129, 38, 23, 115, 249, 55, + 201, 59, 33, 0, 198, 24, 188, 168, 63, 212, 204, 124, 140, 72, + 175, 59, 107, 15, 172, 90, 38, 79, 46, 58, 253, 96, 20, 85, + 13, 191, 116, 125, 90, 205, 225, 178, 69, 42, 210, 215, 243, 14, + 213, 242, 135, 49, 232, 181, 116, 79, 155, 85, 18, 227, 79, 85, + 22, 173, 20, 33, 204, 143, 71, 76, 219, 13, 163, 42, 121, 230, + 143, 170, 204, 58, 205, 197, 214, 20, 166, 16, 230, 89, 36, 227, + 68, 145, 185, 232, 74, 193, 228, 230, 23, 189, 86, 180, 3, 240, + 113, 236, 161, 68, 241, 83, 30, 201, 25, 113, 223, 29, 125, 195, + 72, 253, 184, 50, 4, 150, 154, 126, 196, 163, 225, 173, 231, 199, + 6, 88, 216, 76, 78, 173, 38, 16, 198, 251, 22, 248, 25, 39, + 94, 139, 245, 61, 149, 105, 34, 133, 121, 108, 155, 224, 189, 174, + 169, 232, 119, 61, 221, 52, 214, 180, 198, 87, 193, 91, 20, 145, + 199, 71, 131, 213, 220, 118, 209, 197, 180, 41, 199, 41, 28, 127, + 235, 70, 236, 81, 186, 144, 26, 50, 52, 74, 216, 197, 86, 2, + 96, 143, 52, 83, 47, 227, 208, 18, 171, 27, 31, 223, 69, 219, + 26, 14, 30, 188, 118, 45, 63, 32, 5, 232, 218, 50, 125, 254, + 228, 37, 97, 246, 255, 218, 210, 188, 173, 253, 81, 222, 171, 40, + 57, 147, 143, 194, 235, 182, 53, 120, 184, 135, 1, 26, 47, 29, + 92, 107, 138, 30, 38, 127, 239, 60, 230, 69, 111, 206, 245, 78, + 54, 225, 123, 169, 73, 172, 18, 131, 60, 146, 155, 254, 196, 218, + 100, 66, 84, 22, 179, 132, 220, 238, 153, 12, 111, 151, 229, 124, + 172, 92, 8, 196, 60, 40, 166, 10, 251, 85, 179, 24, 162, 246, + 107, 83, 170, 62, 121, 111, 228, 201, 17, 6, 67, 93, 77, 35, + 187, 244, 85, 92, 14, 37, 3, 146, 17, 70, 231, 129, 226, 163, + 28, 110, 153, 250, 173, 109, 161, 222, 244, 26, 241, 86, 63, 54, + 137, 3, 162, 123, 54, 119, 31, 177, 83, 252, 0, 212, 226, 49, + 94, 157, 90, 227, 156, 8, 184, 85, 148, 143, 114, 249, 130, 248, + 35, 43, 33, 239, 82, 108, 236, 176, 87, 151, 103, 56, 199, 90, + 5, 26, 217, 247, 130, 60, 87, 143, 185, 29, 100, 40, 239, 223, + 224, 216, 173, 26, 199, 233, 130, 41, 212, 111, 64, 11, 92, 249, + 106, 56, 161, 34, 55, 10, 193, 28, 187, 224, 155, 211, 116, 45, + 231, 106, 212, 193, 125, 206, 21, 241, 47, 188, 94, 3, 254, 206, + 223, 248, 240, 73, 27, 233, 89, 241, 254, 40, 20, 65, 42, 166, + 243, 221, 10, 229, 197, 43, 160, 124, 95, 46, 152, 235, 54, 146, + 250, 187, 146, 68, 191, 107, 100, 170, 189, 43, 166, 185, 205, 106, + 253, 176, 243, 182, 55, 166, 227, 5, 203, 176, 9, 230, 121, 137, + 154, 86, 224, 159, 189, 206, 100, 140, 139, 147, 124, 234, 252, 106, + 14, 252, 116, 32, 111, 232, 52, 87, 32, 231, 176, 51, 54, 234, + 34, 229, 130, 12, 167, 212, 136, 127, 88, 165, 135, 102, 25, 34, + 157, 255, 6, 23, 206, 157, 30, 226, 173, 64, 192, 221, 198, 101, + 67, 115, 132, 196, 204, 207, 63, 39, 101, 89, 149, 82, 35, 211, + 77, 161, 54, 206, 25, 235, 212, 106, 48, 55, 85, 13, 193, 103, + 59, 218, 234, 133, 146, 129, 16, 86, 65, 75, 23, 178, 130, 126, + 5, 142, 191, 134, 179, 126, 250, 136, 134, 86, 252, 252, 241, 207, + 163, 192, 162, 1, 72, 27, 35, 34, 195, 116, 205, 156, 70, 21, + 106, 111, 202, 219, 83, 125, 93, 139, 124, 138, 164, 85, 157, 254, + 27, 181, 62, 133, 171, 108, 4, 243, 208, 73, 125, 110, 103, 228, + 64, 147, 197, 1, 99, 135, 16, 199, 198, 114, 165, 49, 23, 121, + 113, 28, 79, 148, 82, 7, 200, 151, 8, 189, 165, 203, 102, 241, + 200, 211, 207, 251, 235, 71, 227, 130, 108, 227, 228, 92, 8, 192, + 140, 118, 58, 136, 243, 137, 47, 166, 31, 98, 95, 165, 96, 39, + 155, 35, 71, 182, 11, 14, 244, 95, 35, 117, 253, 74, 179, 33, + 30, 192, 89, 126, 130, 112, 41, 190, 86, 113, 174, 12, 247, 172, + 183, 17, 134, 35, 122, 217, 85, 41, 238, 173, 253, 125, 149, 110, + 123, 81, 241, 98, 34, 253, 183, 123, 12, 64, 178, 99, 122, 191, + 59, 154, 140, 222, 223, 50, 56, 58, 16, 230, 10, 35, 12, 177, + 99, 235, 145, 255, 215, 215, 148, 226, 111, 37, 18, 141, 93, 228, + 60, 223, 239, 169, 58, 200, 80, 6, 125, 28, 68, 165, 94, 102, + 102, 72, 10, 34, 51, 252, 120, 93, 62, 253, 32, 207, 149, 248, + 152, 232, 225, 244, 121, 12, 98, 35, 252, 54, 231, 255, 23, 58, + 18, 244, 248, 226, 157, 123, 159, 221, 25, 26, 236, 222, 165, 51, + 26, 66, 146, 178, 255, 83, 196, 73, 162, 172, 116, 89, 241, 21, + 114, 190, 197, 207, 194, 82, 37, 187, 53, 142, 11, 187, 77, 69, + 155, 194, 232, 130, 209, 202, 47, 66, 146, 156, 253, 237, 24, 13, + 57, 181, 174, 50, 33, 223, 73, 83, 97, 131, 35, 218, 138, 24, + 114, 191, 219, 147, 131, 255, 77, 85, 52, 21, 59, 75, 164, 31, + 142, 166, 219, 59, 140, 41, 90, 43, 24, 89, 215, 246, 197, 62, + 175, 219, 250, 112, 85, 104, 236, 53, 147, 90, 241, 89, 31, 162, + 150, 192, 187, 251, 4, 170, 196, 189, 122, 207, 190, 135, 53, 81, + 2, 247, 27, 253, 22, 220, 236, 216, 92, 121, 177, 82, 38, 234, + 157, 225, 165, 56, 218, 126, 64, 42, 31, 144, 68, 128, 68, 154, + 144, 149, 8, 131, 2, 183, 30, 123, 192, 82, 108, 90, 176, 146, + 81, 31, 24, 221, 222, 81, 62, 13, 1, 203, 60, 189, 37, 187, + 9, 137, 51, 71, 129, 4, 107, 5, 204, 146, 71, 14, 253, 31, + 29, 29, 91, 196, 37, 234, 76, 92, 27, 126, 143, 187, 38, 187, + 161, 113, 121, 122, 137, 214, 113, 238, 165, 102, 19, 6, 117, 45, + 9, 108, 17, 103, 64, 172, 138, 126, 59, 176, 45, 185, 58, 222, + 76, 97, 182, 60, 90, 207, 123, 226, 144, 111, 190, 234, 18, 120, + 226, 42, 198, 4, 244, 144, 18, 123, 152, 146, 237, 254, 157, 20, + 188, 26, 231, 177, 64, 216, 203, 246, 166, 134, 170, 56, 116, 172, + 193, 249, 35, 177, 204, 47, 142, 241, 193, 61, 211, 151, 100, 177, + 130, 30, 137, 45, 125, 15, 221, 202, 3, 222, 55, 223, 109, 217, + 90, 47, 199, 244, 202, 248, 242, 116, 212, 239, 37, 173, 119, 47, + 192, 163, 100, 182, 87, 189, 170, 42, 209, 65, 122, 184, 61, 206, + 176, 113, 146, 153, 101, 234, 243, 80, 182, 111, 158, 79, 171, 124, + 18, 34, 99, 231, 138, 77, 58, 13, 174, 230, 222, 16, 245, 97, + 104, 135, 16, 75, 210, 242, 6, 201, 48, 54, 99, 56, 253, 180, + 205, 85, 154, 93, 34, 10, 234, 245, 123, 124, 152, 242, 76, 60, + 182, 149, 33, 124, 186, 185, 123, 164, 170, 248, 174, 58, 17, 175, + 16, 29, 173, 38, 28, 32, 134, 222, 209, 163, 105, 119, 249, 149, + 177, 138, 195, 145, 246, 7, 7, 236, 83, 192, 15, 215, 146, 194, + 24, 146, 169, 112, 143, 43, 88, 80, 132, 147, 147, 11, 250, 64, + 101, 115, 46, 78, 128, 52, 203, 54, 1, 221, 9, 117, 196, 215, + 116, 151, 45, 244, 197, 207, 49, 30, 173, 149, 192, 139, 247, 73, + 1, 87, 162, 163, 3, 181, 127, 21, 95, 255, 130, 202, 47, 82, + 118, 135, 196, 63, 90, 184, 197, 14, 220, 18, 58, 106, 222, 216, + 4, 79, 204, 190, 197, 197, 246, 83, 66, 130, 244, 228, 204, 1, + 57, 244, 237, 38, 249, 136, 161, 37, 213, 8, 75, 34, 253, 89, + 209, 53, 228, 240, 228, 51, 48, 189, 218, 207, 103, 254, 123, 162, + 97, 174, 47, 194, 170, 24, 178, 121, 47, 205, 78, 253, 95, 178, + 132, 252, 30, 124, 87, 250, 12, 90, 247, 246, 140, 141, 156, 177, + 106, 138, 193, 235, 188, 130, 196, 113, 218, 223, 215, 132, 67, 255, + 1, 150, 115, 27, 84, 68, 128, 102, 60, 52, 181, 73, 142, 47, + 72, 231, 34, 153, 61, 68, 175, 52, 143, 9, 181, 63, 145, 139, + 176, 29, 246, 4, 96, 4, 131, 48, 41, 253, 81, 128, 247, 14, + 188, 251, 160, 174, 21, 202, 117, 13, 3, 13, 227, 121, 7, 47, + 42, 131, 13, 161, 190, 164, 237, 113, 88, 207, 227, 164, 162, 99, + 31, 66, 39, 253, 101, 163, 84, 226, 89, 235, 207, 14, 191, 8, + 249, 37, 8, 201, 172, 54, 113, 142, 79, 56, 202, 148, 66, 100, + 154, 49, 210, 252, 61, 19, 129, 85, 109, 235, 158, 250, 36, 7, + 122, 245, 230, 95, 255, 98, 179, 228, 8, 152, 59, 119, 110, 113, + 231, 16, 107, 132, 231, 45, 154, 154, 250, 65, 114, 234, 191, 246, + 156, 241, 105, 136, 219, 50, 159, 228, 63, 128, 248, 114, 157, 185, + 12, 254, 147, 253, 155, 80, 14, 130, 52, 142, 148, 81, 126, 227, + 238, 4, 125, 64, 158, 245, 39, 229, 116, 237, 23, 252, 246, 182, + 88, 170, 65, 228, 245, 187, 125, 52, 137, 175, 72, 194, 131, 194, + 200, 27, 248, 216, 13, 19, 197, 60, 67, 147, 3, 108, 120, 172, + 248, 125, 197, 169, 200, 177, 97, 45, 194, 176, 123, 163, 247, 142, + 232, 43, 105, 71, 87, 238, 197, 158, 252, 166, 67, 56, 234, 142, + 115, 84, 155, 174, 25, 20, 201, 184, 80, 250, 0, 241, 121, 234, + 154, 51, 152, 244, 82, 252, 151, 83, 219, 106, 254, 155, 224, 153, + 13, 68, 94, 127, 71, 3, 42, 92, 91, 253, 167, 192, 138, 99, + 63, 71, 216, 240, 227, 238, 141, 18, 66, 177, 38, 86, 164, 215, + 138, 208, 90, 194, 24, 114, 211, 253, 68, 108, 38, 176, 208, 230, + 71, 174, 28, 233, 49, 52, 48, 49, 193, 184, 115, 24, 112, 196, + 212, 141, 99, 0, 190, 152, 79, 9, 53, 197, 36, 133, 125, 206, + 18, 243, 245, 196, 144, 116, 36, 104, 92, 113, 100, 33, 103, 145, + 143, 150, 227, 187, 81, 183, 252, 106, 75, 131, 45, 72, 118, 223, + 69, 139, 253, 193, 135, 67, 113, 21, 129, 145, 106, 190, 181, 4, + 41, 167, 222, 222, 157, 75, 112, 7, 72, 223, 180, 189, 99, 98, + 56, 141, 137, 16, 108, 37, 132, 195, 14, 42, 102, 113, 99, 144, + 14, 176, 147, 148, 137, 85, 114, 37, 205, 125, 80, 187, 119, 82, + 211, 81, 66, 254, 244, 222, 128, 245, 136, 198, 106, 250, 49, 163, + 176, 241, 129, 107, 40, 150, 216, 80, 119, 252, 94, 19, 110, 58, + 206, 145, 148, 11, 229, 132, 64, 110, 216, 148, 68, 151, 113, 210, + 1, 73, 108, 96, 54, 236, 49, 88, 197, 77, 159, 181, 32, 4, + 153, 40, 176, 37, 188, 169, 205, 81, 73, 131, 47, 55, 31, 130, + 219, 197, 51, 221, 59, 190, 89, 229, 70, 40, 253, 1, 210, 241, + 144, 161, 223, 182, 215, 199, 27, 44, 156, 37, 206, 91, 219, 86, + 163, 190, 158, 102, 188, 241, 73, 121, 255, 52, 72, 97, 171, 237, + 94, 126, 203, 70, 5, 13, 25, 189, 208, 247, 103, 51, 77, 105, + 97, 118, 99, 104, 6, 142, 150, 145, 197, 20, 186, 221, 241, 177, + 73, 52, 56, 19, 164, 211, 252, 237, 199, 238, 184, 129, 196, 221, + 233, 19, 142, 223, 86, 117, 41, 101, 128, 178, 110, 95, 109, 192, + 169, 210, 118, 102, 135, 148, 29, 231, 246, 105, 47, 168, 140, 191, + 42, 6, 80, 218, 202, 158, 234, 209, 38, 166, 1, 227, 117, 57, + 33, 103, 93, 145, 61, 170, 206, 212, 235, 8, 70, 249, 61, 188, + 191, 84, 203, 155, 17, 206, 76, 63, 28, 130, 113, 14, 236, 96, + 249, 128, 8, 218, 4, 192, 163, 222, 17, 146, 111, 69, 65, 211, + 218, 183, 125, 181, 190, 93, 112, 141, 254, 28, 4, 106, 250, 8, + 127, 43, 212, 169, 219, 159, 177, 76, 120, 200, 173, 252, 122, 84, + 187, 55, 204, 179, 191, 200, 49, 61, 138, 170, 128, 149, 5, 199, + 108, 78, 188, 13, 2, 45, 124, 76, 76, 67, 26, 128, 207, 255, + 83, 25, 144, 231, 192, 205, 39, 196, 35, 51, 173, 4, 50, 205, + 18, 201, 91, 68, 138, 100, 115, 75, 79, 133, 110, 153, 168, 61, + 9, 59, 254, 189, 58, 41, 179, 222, 93, 81, 251, 125, 54, 73, + 197, 142, 1, 149, 205, 250, 250, 247, 16, 25, 157, 100, 42, 196, + 178, 144, 91, 37, 87, 2, 157, 63, 180, 67, 162, 60, 211, 123, + 239, 234, 39, 104, 103, 37, 17, 103, 152, 30, 59, 100, 0, 200, + 6, 27, 241, 51, 138, 248, 35, 160, 52, 195, 56, 102, 5, 96, + 135, 51, 32, 57, 239, 209, 111, 175, 39, 206, 146, 220, 216, 53, + 245, 122, 97, 204, 44, 1, 16, 140, 157, 128, 22, 130, 195, 117, + 3, 160, 51, 71, 245, 253, 127, 162, 204, 164, 46, 231, 46, 189, + 194, 48, 32, 238, 145, 89, 31, 119, 60, 4, 121, 63, 227, 236, + 86, 236, 199, 217, 114, 156, 32, 220, 48, 88, 8, 190, 131, 66, + 83, 186, 100, 67, 192, 152, 48, 224, 250, 27, 176, 172, 22, 48, + 159, 161, 7, 75, 223, 166, 51, 20, 18, 221, 206, 115, 18, 134, + 8, 0, 86, 181, 119, 249, 0, 234, 11, 240, 150, 70, 122, 186, + 202, 74, 237, 219, 43, 253, 191, 26, 108, 12, 16, 54, 47, 98, + 27, 9, 171, 148, 241, 182, 11, 79, 246, 128, 119, 134, 154, 207, + 74, 133, 182, 161, 37, 177, 125, 247, 130, 108, 160, 153, 189, 133, + 184, 156, 25, 23, 13, 131, 164, 37, 68, 83, 181, 109, 58, 50, + 209, 190, 93, 217, 239, 85, 158, 90, 46, 182, 154, 59, 84, 164, + 125, 71, 79, 220, 1, 99, 141, 55, 135, 177, 17, 66, 182, 5, + 86, 59, 212, 119, 211, 104, 193, 66, 130, 51, 184, 58, 143, 106, + 154, 15, 3, 226, 128, 210, 111, 30, 40, 34, 72, 200, 38, 139, + 126, 249, 16, 82, 115, 111, 7, 100, 42, 25, 7, 196, 141, 154, + 125, 202, 234, 253, 91, 99, 126, 3, 252, 133, 251, 112, 127, 205, + 251, 114, 66, 185, 134, 2, 98, 220, 196, 173, 203, 10, 150, 153, + 47, 54, 189, 38, 23, 104, 200, 9, 217, 16, 228, 88, 44, 188, + 157, 229, 127, 91, 102, 85, 54, 230, 247, 194, 169, 60, 67, 245, + 63, 171, 223, 51, 18, 242, 197, 126, 66, 233, 76, 214, 21, 92, + 202, 223, 164, 180, 90, 6, 154, 20, 253, 221, 22, 116, 206, 201, + 211, 113, 142, 50, 4, 227, 60, 217, 208, 164, 26, 40, 215, 43, + 70, 32, 146, 192, 13, 133, 112, 106, 167, 218, 195, 104, 139, 153, + 193, 77, 24, 102, 18, 59, 53, 20, 128, 9, 121, 118, 196, 148, + 246, 58, 29, 199, 117, 204, 32, 18, 34, 163, 150, 2, 166, 213, + 224, 231, 30, 232, 12, 144, 140, 89, 147, 129, 236, 111, 230, 11, + 148, 98, 128, 70, 24, 201, 37, 250, 245, 65, 222, 112, 53, 41, + 20, 3, 160, 168, 138, 3, 157, 138, 136, 221, 143, 124, 36, 116, + 178, 11, 148, 223, 163, 208, 184, 221, 8, 63, 223, 59, 92, 188, + 114, 63, 178, 188, 251, 208, 23, 218, 231, 178, 49, 237, 224, 25, + 163, 15, 42, 10, 4, 238, 127, 241, 136, 101, 247, 161, 247, 60, + 163, 40, 30, 61, 193, 33, 26, 52, 42, 241, 52, 24, 244, 153, + 184, 87, 178, 55, 41, 88, 156, 23, 86, 69, 233, 225, 26, 25, + 146, 38, 184, 93, 202, 217, 147, 81, 8, 227, 160, 93, 34, 131, + 228, 230, 227, 70, 57, 245, 253, 90, 190, 29, 220, 196, 205, 162, + 188, 93, 233, 243, 16, 174, 76, 80, 161, 241, 222, 128, 63, 42, + 191, 161, 28, 166, 173, 3, 203, 61, 211, 91, 189, 32, 23, 221, + 132, 155, 36, 138, 102, 21, 232, 27, 158, 69, 186, 66, 135, 143, + 29, 232, 116, 183, 146, 75, 129, 245, 148, 134, 247, 51, 204, 107, + 205, 55, 145, 61, 129, 149, 206, 62, 69, 24, 155, 206, 110, 201, + 40, 250, 128, 47, 86, 130, 5, 100, 173, 144, 110, 139, 167, 70, + 248, 185, 131, 148, 128, 18, 157, 88, 42, 48, 232, 217, 192, 53, + 18, 45, 240, 254, 218, 78, 35, 27, 236, 100, 127, 225, 238, 20, + 87, 173, 101, 214, 213, 242, 193, 111, 10, 232, 76, 209, 227, 161, + 146, 232, 99, 125, 103, 139, 28, 112, 209, 202, 30, 63, 168, 182, + 40, 114, 52, 118, 198, 105, 122, 225, 157, 23, 165, 232, 96, 58, + 16, 20, 156, 209, 16, 219, 190, 217, 62, 9, 61, 100, 93, 190, + 243, 160, 239, 246, 162, 195, 74, 67, 15, 30, 153, 12, 17, 76, + 237, 220, 2, 32, 60, 21, 118, 200, 97, 253, 18, 59, 30, 84, + 35, 43, 98, 82, 106, 47, 55, 84, 253, 61, 233, 239, 100, 163, + 70, 184, 166, 101, 124, 4, 241, 204, 62, 9, 65, 1, 204, 197, + 53, 239, 216, 123, 152, 21, 236, 120, 95, 4, 124, 55, 166, 165, + 86, 72, 59, 122, 43, 182, 245, 190, 226, 221, 47, 231, 129, 207, + 246, 64, 144, 33, 153, 106, 243, 32, 237, 163, 191, 123, 241, 217, + 229, 238, 254, 218, 188, 243, 214, 175, 225, 39, 146, 16, 20, 38, + 5, 48, 228, 151, 137, 166, 65, 243, 225, 146, 38, 45, 187, 122, + 63, 154, 253, 75, 126, 225, 220, 84, 234, 5, 154, 231, 104, 66, + 193, 120, 61, 62, 105, 131, 78, 154, 8, 214, 147, 198, 66, 47, + 211, 19, 51, 158, 124, 150, 10, 81, 85, 252, 35, 155, 7, 111, + 194, 245, 74, 213, 235, 39, 140, 216, 74, 102, 87, 81, 71, 57, + 211, 73, 35, 38, 39, 93, 95, 179, 92, 96, 43, 68, 160, 99, + 235, 18, 101, 31, 138, 123, 100, 155, 79, 2, 5, 81, 67, 247, + 37, 105, 255, 186, 3, 221, 76, 47, 117, 192, 13, 114, 86, 54, + 47, 60, 5, 44, 118, 81, 120, 184, 126, 118, 103, 121, 24, 222, + 42, 79, 244, 198, 25, 43, 69, 255, 19, 1, 239, 23, 157, 63, + 106, 246, 151, 11, 215, 110, 149, 198, 103, 24, 90, 186, 166, 54, + 35, 140, 48, 217, 62, 245, 74, 35, 206, 49, 100, 15, 5, 239, + 9, 156, 200, 182, 108, 80, 129, 34, 49, 195, 107, 147, 195, 149, + 48, 178, 171, 235, 223, 187, 84, 24, 208, 84, 226, 252, 73, 213, + 9, 27, 149, 120, 187, 237, 241, 38, 235, 226, 133, 253, 6, 149, + 152, 34, 135, 218, 30, 192, 252, 52, 252, 78, 144, 113, 244, 80, + 35, 64, 87, 76, 137, 136, 111, 222, 253, 183, 91, 225, 87, 107, + 63, 130, 215, 2, 121, 49, 25, 79, 182, 10, 31, 29, 150, 89, + 42, 86, 168, 14, 22, 34, 100, 36, 162, 206, 217, 46, 209, 167, + 194, 83, 70, 0, 165, 203, 2, 170, 172, 134, 74, 32, 118, 45, + 249, 14, 124, 242, 191, 48, 68, 248, 184, 101, 32, 82, 40, 96, + 82, 61, 132, 101, 219, 124, 96, 34, 208, 99, 241, 6, 140, 192, + 176, 10, 15, 118, 251, 140, 91, 74, 211, 93, 228, 4, 238, 255, + 4, 50, 174, 180, 98, 24, 30, 59, 48, 60, 153, 254, 196, 173, + 41, 77, 105, 180, 109, 43, 199, 136, 64, 87, 168, 25, 241, 73, + 213, 251, 159, 11, 73, 84, 16, 198, 28, 228, 143, 19, 234, 116, + 84, 120, 202, 132, 169, 95, 83, 102, 185, 219, 152, 1, 100, 230, + 175, 222, 40, 104, 84, 78, 188, 96, 90, 177, 163, 79, 59, 197, + 13, 173, 198, 106, 227, 91, 91, 160, 178, 190, 63, 134, 90, 104, + 142, 36, 243, 110, 78, 218, 228, 199, 141, 201, 24, 22, 60, 158, + 11, 239, 71, 126, 142, 165, 29, 79, 206, 235, 83, 138, 10, 26, + 137, 186, 127, 230, 251, 202, 212, 211, 95, 225, 149, 181, 141, 137, + 202, 202, 204, 89, 202, 34, 27, 142, 233, 61, 231, 189, 79, 26, + 99, 164, 78, 137, 231, 95, 120, 160, 112, 163, 142, 222, 200, 119, + 163, 243, 68, 120, 17, 243, 94, 98, 48, 29, 115, 143, 146, 198, + 137, 188, 198, 244, 142, 0, 225, 242, 139, 135, 181, 97, 19, 253, + 187, 47, 136, 212, 131, 32, 67, 74, 224, 42, 240, 163, 11, 33, + 194, 129, 82, 171, 161, 98, 16, 242, 125, 141, 36, 151, 209, 70, + 44, 6, 243, 69, 161, 180, 19, 167, 215, 0, 102, 186, 178, 221, + 174, 203, 220, 61, 92, 19, 12, 63, 13, 70, 246, 69, 190, 250, + 49, 12, 19, 23, 164, 82, 76, 218, 26, 3, 132, 185, 93, 243, + 85, 237, 213, 50, 213, 229, 138, 111, 8, 76, 67, 228, 146, 99, + 228, 224, 170, 19, 250, 128, 119, 19, 30, 137, 114, 58, 208, 131, + 52, 251, 246, 234, 212, 140, 203, 242, 167, 238, 242, 252, 160, 254, + 217, 248, 137, 88, 178, 51, 153, 217, 194, 104, 53, 66, 112, 171, + 116, 107, 243, 107, 153, 235, 52, 151, 31, 41, 79, 187, 250, 208, + 211, 115, 81, 246, 233, 66, 55, 23, 223, 101, 223, 182, 176, 34, + 53, 195, 96, 156, 113, 35, 175, 164, 73, 127, 179, 23, 161, 157, + 142, 223, 186, 183, 250, 53, 17, 246, 203, 149, 82, 225, 203, 245, + 204, 128, 26, 115, 90, 197, 205, 85, 217, 93, 207, 190, 238, 194, + 41, 161, 89, 148, 183, 250, 204, 247, 107, 255, 245, 169, 167, 225, + 43, 35, 233, 222, 130, 163, 34, 152, 21, 246, 55, 76, 58, 102, + 46, 50, 15, 111, 161, 130, 68, 86, 240, 78, 133, 255, 172, 213, + 138, 1, 226, 81, 249, 223, 19, 223, 115, 238, 140, 158, 198, 250, + 213, 83, 147, 180, 96, 11, 22, 163, 204, 52, 69, 26, 95, 77, + 180, 83, 215, 37, 120, 217, 223, 220, 50, 224, 224, 244, 150, 200, + 129, 248, 95, 185, 182, 152, 74, 125, 159, 198, 169, 1, 58, 72, + 23, 183, 30, 183, 234, 15, 173, 212, 246, 70, 66, 73, 167, 44, + 204, 105, 77, 109, 212, 218, 199, 13, 71, 152, 105, 247, 125, 157, + 82, 252, 76, 159, 162, 12, 139, 123, 37, 121, 61, 195, 69, 67, + 250, 255, 143, 138, 74, 172, 221, 40, 33, 44, 25, 137, 164, 8, + 12, 145, 94, 204, 79, 26, 202, 151, 106, 192, 85, 55, 252, 39, + 182, 117, 252, 92, 219, 178, 201, 206, 8, 107, 123, 201, 32, 42, + 169, 120, 153, 192, 63, 204, 196, 32, 96, 168, 224, 141, 45, 199, + 0, 224, 47, 102, 46, 78, 52, 158, 115, 247, 21, 175, 236, 167, + 142, 228, 71, 190, 128, 227, 196, 204, 169, 112, 85, 244, 90, 166, + 130, 112, 78, 217, 150, 150, 253, 240, 121, 187, 4, 51, 249, 174, + 17, 33, 248, 223, 122, 116, 170, 235, 116, 208, 205, 132, 45, 157, + 82, 150, 218, 208, 132, 28, 176, 103, 124, 217, 221, 65, 87, 248, + 74, 54, 242, 205, 148, 29, 125, 189, 34, 240, 97, 81, 222, 171, + 110, 244, 118, 146, 125, 22, 48, 144, 121, 165, 124, 120, 233, 87, + 253, 140, 52, 33, 35, 194, 222, 56, 194, 35, 39, 182, 25, 200, + 120, 234, 249, 124, 248, 215, 136, 255, 74, 215, 2, 196, 86, 163, + 159, 178, 238, 46, 251, 207, 234, 255, 147, 12, 26, 223, 58, 242, + 21, 164, 2, 153, 250, 108, 245, 203, 127, 124, 124, 60, 136, 61, + 225, 142, 96, 97, 69, 190, 146, 74, 140, 85, 40, 171, 135, 184, + 45, 112, 49, 15, 227, 181, 236, 244, 121, 49, 141, 13, 181, 233, + 143, 129, 148, 88, 44, 74, 77, 146, 37, 28, 122, 7, 149, 73, + 11, 123, 53, 184, 68, 231, 126, 115, 224, 139, 105, 149, 237, 242, + 187, 15, 6, 136, 12, 94, 183, 85, 25, 15, 53, 115, 34, 48, + 97, 12, 233, 91, 20, 174, 41, 93, 125, 140, 232, 160, 17, 161, + 11, 54, 218, 26, 205, 187, 198, 98, 240, 237, 33, 149, 63, 2, + 127, 106, 166, 220, 6, 214, 205, 244, 35, 96, 132, 59, 209, 178, + 16, 41, 59, 168, 12, 122, 129, 28, 3, 232, 241, 44, 151, 188, + 157, 88, 180, 109, 229, 208, 119, 33, 205, 235, 23, 188, 26, 145, + 177, 30, 227, 78, 78, 155, 149, 164, 143, 175, 121, 160, 92, 62, + 157, 142, 197, 247, 24, 106, 163, 107, 58, 177, 171, 43, 1, 128, + 107, 179, 161, 148, 101, 119, 95, 121, 161, 83, 198, 244, 110, 64, + 26, 50, 102, 157, 153, 106, 20, 110, 255, 21, 140, 47, 83, 190, + 45, 45, 160, 52, 60, 156, 164, 235, 55, 250, 194, 90, 28, 120, + 157, 54, 84, 163, 148, 137, 165, 90, 103, 28, 177, 66, 44, 68, + 179, 169, 202, 172, 100, 210, 200, 248, 196, 190, 71, 185, 246, 148, + 214, 8, 152, 9, 103, 181, 196, 162, 6, 49, 166, 218, 205, 229, + 91, 28, 253, 214, 205, 236, 4, 233, 15, 233, 164, 194, 100, 190, + 208, 85, 130, 122, 76, 44, 69, 157, 54, 54, 138, 223, 90, 174, + 159, 160, 120, 129, 8, 190, 121, 157, 56, 56, 109, 183, 40, 229, + 55, 203, 72, 218, 102, 71, 97, 68, 224, 247, 121, 25, 39, 194, + 208, 106, 19, 178, 4, 14, 159, 40, 145, 233, 155, 96, 7, 29, + 191, 160, 209, 222, 189, 60, 3, 243, 123, 122, 202, 33, 101, 230, + 16, 141, 229, 101, 201, 124, 5, 178, 184, 225, 177, 221, 198, 209, + 82, 23, 178, 232, 73, 37, 221, 120, 208, 50, 134, 95, 65, 10, + 6, 19, 167, 160, 226, 209, 202, 189, 140, 28, 145, 105, 134, 53, + 176, 144, 142, 170, 63, 85, 241, 213, 3, 99, 40, 254, 230, 113, + 27, 111, 60, 176, 221, 212, 132, 201, 239, 13, 155, 104, 18, 135, + 35, 108, 254, 223, 205, 156, 81, 69, 91, 98, 201, 236, 114, 55, + 116, 188, 11, 159, 190, 37, 246, 127, 121, 172, 181, 126, 125, 209, + 212, 5, 91, 78, 3, 62, 11, 119, 231, 218, 31, 174, 8, 250, + 94, 168, 200, 97, 3, 192, 234, 133, 104, 246, 151, 18, 71, 83, + 58, 87, 63, 170, 180, 238, 108, 221, 189, 203, 19, 178, 3, 217, + 7, 90, 171, 15, 114, 1, 26, 211, 38, 61, 131, 138, 151, 234, + 54, 182, 152, 45, 178, 246, 35, 45, 255, 229, 63, 221, 99, 223, + 66, 192, 219, 133, 143, 198, 24, 167, 217, 121, 190, 91, 21, 238, + 86, 176, 145, 180, 122, 158, 13, 138, 124, 142, 70, 162, 98, 196, + 100, 109, 70, 155, 215, 245, 53, 239, 1, 252, 39, 171, 197, 203, + 174, 98, 145, 79, 163, 207, 254, 18, 113, 188, 192, 200, 62, 151, + 211, 209, 83, 63, 0, 213, 233, 44, 6, 203, 93, 83, 18, 122, + 17, 104, 236, 151, 102, 179, 197, 20, 224, 254, 221, 149, 124, 15, + 208, 17, 234, 237, 86, 234, 21, 95, 137, 241, 110, 191, 46, 37, + 107, 82, 193, 124, 22, 59, 157, 67, 34, 16, 168, 43, 27, 77, + 220, 103, 94, 224, 85, 238, 37, 8, 217, 152, 220, 111, 125, 56, + 109, 85, 9, 71, 38, 157, 196, 103, 247, 248, 67, 200, 6, 195, + 161, 158, 170, 73, 14, 165, 39, 105, 154, 227, 105, 146, 92, 139, + 145, 227, 185, 182, 160, 251, 10, 132, 229, 24, 99, 75, 75, 253, + 26, 220, 222, 52, 125, 71, 77, 240, 83, 138, 253, 1, 88, 70, + 100, 40, 139, 162, 117, 206, 117, 251, 26, 196, 145, 0, 205, 79, + 213, 184, 151, 193, 240, 191, 161, 18, 103, 148, 223, 11, 15, 134, + 115, 246, 219, 184, 247, 169, 238, 80, 230, 152, 138, 160, 161, 216, + 135, 107, 159, 222, 16, 39, 249, 192, 50, 166, 57, 155, 33, 22, + 29, 7, 246, 2, 20, 175, 228, 185, 237, 15, 134, 37, 112, 162, + 174, 177, 164, 46, 234, 105, 5, 70, 127, 244, 163, 228, 13, 165, + 131, 99, 101, 25, 132, 156, 131, 15, 229, 246, 58, 113, 113, 98, + 60, 178, 203, 200, 67, 9, 97, 99, 54, 170, 148, 65, 108, 10, + 247, 197, 193, 249, 155, 207, 94, 139, 135, 93, 247, 192, 76, 94, + 24, 112, 159, 189, 212, 222, 116, 253, 58, 175, 118, 0, 44, 83, + 135, 26, 227, 92, 217, 132, 232, 11, 199, 219, 81, 196, 254, 233, + 251, 158, 31, 74, 56, 249, 10, 203, 61, 142, 193, 252, 253, 205, + 229, 206, 215, 0, 248, 140, 80, 121, 240, 167, 67, 220, 66, 213, + 59, 88, 247, 250, 73, 135, 189, 133, 160, 125, 161, 235, 109, 235, + 195, 237, 217, 130, 67, 233, 52, 199, 140, 57, 176, 7, 232, 208, + 158, 64, 136, 203, 97, 141, 227, 101, 215, 14, 117, 171, 233, 110, + 123, 234, 70, 208, 81, 247, 168, 164, 32, 217, 149, 107, 174, 79, + 173, 72, 105, 28, 18, 94, 241, 33, 132, 59, 111, 85, 254, 147, + 23, 233, 12, 142, 73, 170, 252, 112, 106, 245, 188, 97, 99, 153, + 1, 140, 119, 157, 212, 134, 99, 224, 10, 161, 56, 242, 182, 205, + 120, 72, 203, 82, 62, 141, 175, 241, 51, 244, 216, 166, 0, 19, + 113, 16, 120, 102, 11, 157, 138, 188, 176, 241, 52, 76, 70, 170, + 123, 174, 209, 200, 23, 81, 55, 69, 246, 179, 32, 61, 253, 123, + 85, 45, 90, 140, 179, 212, 193, 239, 215, 221, 224, 236, 152, 53, + 136, 158, 130, 78, 240, 103, 143, 16, 192, 99, 201, 185, 247, 119, + 81, 169, 12, 154, 240, 65, 46, 101, 191, 87, 238, 149, 88, 143, + 240, 129, 151, 236, 201, 166, 255, 7, 194, 164, 115, 96, 87, 82, + 152, 122, 124, 72, 251, 76, 13, 135, 134, 90, 5, 253, 14, 6, + 198, 87, 163, 171, 107, 133, 175, 217, 22, 246, 122, 169, 210, 125, + 16, 132, 53, 220, 140, 127, 174, 196, 218, 196, 14, 70, 71, 38, + 143, 227, 63, 234, 57, 239, 61, 3, 40, 106, 111, 8, 150, 161, + 109, 61, 197, 239, 93, 2, 183, 121, 25, 78, 235, 21, 108, 23, + 135, 248, 113, 12, 189, 184, 109, 95, 227, 235, 3, 245, 199, 228, + 176, 46, 52, 238, 122, 19, 28, 104, 138, 245, 158, 139, 223, 255, + 126, 134, 206, 23, 61, 1, 164, 249, 186, 97, 75, 175, 45, 103, + 167, 122, 213, 162, 84, 116, 146, 43, 187, 60, 163, 54, 58, 26, + 173, 160, 151, 185, 12, 15, 57, 212, 220, 194, 254, 200, 148, 206, + 156, 185, 32, 239, 26, 204, 90, 132, 227, 27, 182, 127, 34, 46, + 232, 7, 50, 117, 93, 229, 165, 48, 184, 210, 97, 113, 250, 103, + 196, 36, 3, 47, 209, 168, 233, 6, 230, 35, 2, 231, 143, 240, + 26, 173, 205, 52, 120, 68, 244, 43, 108, 19, 142, 72, 28, 220, + 107, 227, 253, 182, 88, 205, 42, 197, 244, 38, 173, 64, 195, 27, + 126, 229, 150, 32, 248, 210, 68, 207, 182, 103, 32, 143, 9, 219, + 25, 237, 2, 164, 25, 48, 227, 92, 144, 81, 102, 99, 64, 48, + 135, 105, 196, 127, 175, 22, 192, 58, 114, 155, 37, 156, 160, 56, + 42, 183, 219, 159, 78, 116, 114, 248, 181, 84, 122, 239, 251, 151, + 113, 180, 228, 38, 87, 93, 87, 133, 35, 233, 194, 233, 175, 64, + 233, 48, 66, 118, 149, 165, 75, 126, 173, 145, 65, 206, 148, 158, + 4, 6, 72, 91, 148, 140, 204, 175, 158, 183, 156, 102, 99, 114, + 155, 197, 33, 18, 208, 49, 215, 157, 93, 185, 104, 127, 176, 100, + 229, 128, 115, 208, 32, 251, 250, 22, 226, 105, 182, 239, 206, 155, + 239, 11, 222, 0, 146, 49, 33, 91, 194, 129, 49, 227, 92, 57, + 13, 17, 101, 152, 49, 126, 60, 72, 90, 167, 61, 14, 94, 20, + 226, 3, 117, 65, 238, 197, 11, 239, 226, 3, 109, 131, 181, 55, + 60, 206, 211, 173, 204, 53, 224, 189, 97, 255, 147, 31, 59, 96, + 138, 63, 182, 228, 189, 38, 254, 133, 123, 9, 203, 10, 30, 122, + 24, 123, 174, 202, 49, 99, 78, 243, 94, 239, 57, 215, 114, 211, + 52, 49, 152, 179, 24, 111, 65, 226, 53, 162, 133, 12, 91, 3, + 117, 149, 221, 18, 46, 173, 140, 252, 224, 43, 221, 241, 117, 108, + 193, 142, 136, 73, 32, 71, 166, 50, 100, 201, 72, 72, 39, 177, + 189, 58, 115, 227, 252, 48, 133, 131, 142, 235, 153, 237, 219, 10, + 96, 81, 92, 212, 171, 32, 127, 131, 231, 251, 47, 69, 165, 45, + 125, 116, 213, 11, 221, 8, 119, 104, 236, 48, 86, 177, 132, 146, + 107, 157, 64, 15, 88, 99, 156, 68, 133, 82, 203, 89, 31, 196, + 46, 242, 175, 246, 138, 228, 128, 209, 5, 232, 254, 57, 97, 168, + 44, 171, 121, 30, 211, 143, 108, 27, 40, 155, 147, 7, 160, 76, + 237, 121, 23, 246, 63, 14, 133, 181, 115, 46, 253, 254, 57, 129, + 209, 87, 85, 10, 66, 8, 215, 182, 204, 139, 105, 14, 75, 237, + 221, 130, 101, 106, 111, 131, 25, 119, 84, 2, 78, 89, 199, 219, + 189, 148, 128, 235, 246, 175, 28, 15, 19, 24, 237, 22, 140, 244, + 253, 143, 135, 76, 222, 168, 55, 22, 90, 214, 160, 248, 163, 87, + 226, 53, 232, 0, 207, 202, 205, 213, 253, 33, 201, 201, 229, 197, + 18, 15, 54, 240, 193, 131, 154, 190, 72, 84, 63, 43, 5, 230, + 31, 74, 216, 209, 203, 148, 245, 97, 146, 47, 198, 37, 251, 111, + 247, 29, 182, 101, 158, 108, 190, 140, 17, 148, 174, 35, 31, 198, + 202, 227, 23, 105, 178, 210, 121, 225, 8, 164, 249, 30, 35, 142, + 187, 214, 195, 248, 238, 113, 2, 100, 24, 153, 102, 165, 211, 202, + 190, 89, 88, 24, 67, 186, 172, 0, 186, 51, 42, 94, 246, 201, + 27, 179, 166, 191, 125, 93, 77, 109, 31, 215, 103, 49, 23, 155, + 37, 94, 49, 132, 72, 125, 49, 216, 80, 199, 174, 252, 132, 81, + 45, 99, 178, 5, 50, 48, 112, 184, 202, 55, 189, 34, 149, 136, + 90, 10, 229, 249, 35, 40, 148, 151, 148, 95, 69, 53, 175, 172, + 214, 6, 101, 254, 158, 228, 157, 94, 107, 231, 93, 156, 97, 182, + 224, 142, 229, 119, 35, 22, 99, 228, 83, 117, 154, 240, 101, 145, + 149, 223, 63, 205, 49, 152, 227, 103, 193, 97, 69, 116, 7, 253, + 193, 132, 244, 221, 45, 0, 173, 227, 153, 126, 35, 4, 61, 162, + 30, 163, 77, 208, 164, 101, 179, 7, 101, 173, 119, 233, 150, 162, + 23, 150, 113, 222, 143, 73, 242, 187, 168, 147, 201, 178, 138, 149, + 18, 64, 178, 233, 161, 206, 195, 67, 88, 101, 158, 154, 50, 206, + 118, 102, 191, 36, 67, 97, 221, 68, 142, 153, 84, 166, 241, 174, + 233, 65, 129, 169, 245, 9, 132, 219, 27, 175, 190, 239, 2, 31, + 141, 227, 103, 156, 197, 124, 164, 146, 51, 79, 104, 175, 3, 57, + 96, 194, 62, 196, 40, 125, 167, 189, 31, 86, 14, 124, 162, 178, + 168, 163, 94, 57, 220, 51, 32, 251, 209, 15, 65, 154, 175, 251, + 167, 90, 54, 239, 100, 120, 202, 245, 187, 121, 219, 216, 123, 246, + 114, 12, 116, 18, 131, 73, 216, 105, 38, 209, 178, 16, 183, 178, + 191, 84, 20, 106, 135, 167, 64, 2, 239, 97, 2, 66, 227, 20, + 170, 139, 184, 105, 9, 53, 252, 169, 172, 188, 152, 186, 130, 151, + 165, 218, 113, 66, 116, 248, 206, 64, 48, 25, 200, 37, 34, 165, + 20, 100, 193, 161, 106, 35, 7, 136, 107, 13, 212, 37, 11, 41, + 52, 186, 177, 122, 210, 211, 143, 150, 100, 241, 164, 162, 230, 204, + 70, 209, 143, 160, 90, 150, 56, 163, 26, 103, 81, 86, 52, 117, + 202, 167, 236, 187, 41, 68, 228, 77, 66, 81, 193, 88, 17, 155, + 88, 90, 53, 127, 105, 236, 43, 20, 47, 234, 66, 218, 80, 252, + 133, 24, 10, 53, 177, 3, 201, 214, 160, 107, 95, 110, 211, 213, + 3, 227, 148, 214, 225, 74, 232, 7, 154, 7, 155, 220, 86, 209, + 26, 165, 19, 204, 122, 122, 38, 0, 54, 55, 5, 78, 68, 220, + 186, 221, 215, 16, 171, 201, 45, 25, 148, 31, 165, 65, 115, 159, + 186, 53, 241, 106, 244, 138, 29, 131, 130, 246, 107, 72, 114, 188, + 136, 21, 78, 75, 188, 76, 134, 231, 183, 215, 250, 159, 202, 102, + 201, 85, 252, 185, 233, 136, 35, 169, 163, 111, 246, 56, 18, 107, + 190, 221, 32, 114, 213, 103, 252, 167, 57, 46, 109, 26, 84, 195, + 249, 140, 8, 71, 147, 118, 145, 73, 225, 100, 248, 49, 90, 220, + 128, 129, 206, 185, 226, 151, 132, 164, 190, 113, 146, 171, 52, 111, + 82, 209, 237, 44, 105, 25, 76, 118, 253, 231, 173, 209, 59, 32, + 16, 156, 109, 27, 9, 113, 22, 0, 125, 163, 80, 143, 150, 247, + 141, 2, 250, 121, 0, 185, 62, 49, 70, 76, 45, 32, 33, 185, + 238, 97, 21, 20, 32, 237, 144, 70, 196, 164, 247, 228, 133, 229, + 177, 176, 46, 11, 114, 135, 198, 225, 251, 188, 235, 45, 252, 229, + 158, 65, 247, 197, 241, 222, 225, 42, 223, 242, 117, 29, 2, 97, + 98, 81, 243, 67, 158, 70, 8, 147, 100, 129, 60, 158, 158, 100, + 14, 27, 90, 166, 10, 228, 124, 102, 44, 195, 190, 146, 119, 137, + 156, 59, 242, 170, 129, 125, 90, 228, 205, 82, 181, 229, 201, 242, + 76, 12, 142, 47, 112, 50, 144, 110, 57, 96, 240, 201, 191, 47, + 171, 92, 14, 3, 56, 110, 15, 120, 53, 42, 98, 224, 255, 254, + 147, 65, 199, 114, 82, 145, 0, 100, 228, 159, 254, 149, 123, 42, + 234, 66, 8, 171, 176, 54, 237, 86, 74, 160, 173, 232, 238, 202, + 102, 201, 28, 111, 151, 175, 97, 155, 58, 101, 132, 72, 56, 186, + 20, 83, 120, 232, 90, 220, 143, 105, 83, 109, 91, 50, 76, 144, + 133, 102, 212, 19, 151, 26, 91, 249, 14, 242, 151, 62, 152, 165, + 80, 243, 205, 224, 246, 95, 160, 132, 141, 197, 230, 202, 106, 145, + 15, 89, 178, 183, 212, 89, 92, 18, 30, 118, 83, 173, 70, 230, + 110, 239, 221, 66, 233, 155, 145, 195, 237, 122, 42, 166, 240, 156, + 92, 142, 93, 234, 111, 15, 227, 223, 146, 111, 46, 172, 124, 35, + 93, 172, 243, 190, 226, 0, 2, 102, 211, 210, 220, 237, 124, 186, + 231, 235, 6, 75, 148, 66, 252, 57, 12, 236, 79, 75, 154, 219, + 26, 39, 29, 88, 14, 3, 55, 48, 49, 4, 188, 168, 17, 244, + 98, 15, 255, 237, 28, 253, 161, 177, 54, 104, 97, 44, 33, 25, + 4, 15, 151, 201, 21, 199, 157, 9, 186, 230, 12, 36, 64, 136, + 114, 247, 142, 204, 189, 94, 35, 86, 113, 53, 43, 211, 78, 90, + 70, 10, 218, 71, 144, 115, 148, 103, 234, 110, 15, 241, 104, 239, + 127, 35, 43, 202, 232, 165, 109, 242, 182, 196, 88, 36, 220, 27, + 132, 58, 174, 112, 79, 65, 4, 229, 189, 41, 128, 116, 56, 169, + 178, 119, 57, 164, 252, 231, 96, 78, 97, 230, 168, 18, 9, 243, + 106, 98, 1, 223, 141, 134, 131, 188, 54, 136, 234, 12, 76, 241, + 231, 68, 71, 206, 129, 240, 245, 192, 247, 198, 24, 10, 246, 67, + 47, 12, 246, 183, 82, 192, 120, 151, 88, 10, 89, 38, 173, 247, + 159, 3, 222, 146, 209, 18, 113, 229, 46, 205, 252, 82, 78, 6, + 27, 79, 157, 143, 228, 92, 176, 136, 66, 107, 16, 238, 77, 72, + 76, 66, 145, 23, 244, 115, 187, 159, 190, 106, 43, 136, 121, 219, + 73, 156, 121, 77, 70, 190, 214, 111, 21, 204, 208, 185, 171, 114, + 11, 206, 34, 121, 46, 128, 227, 240, 155, 171, 71, 158, 251, 10, + 49, 236, 28, 126, 173, 199, 94, 80, 101, 37, 63, 255, 76, 125, + 237, 42, 208, 198, 147, 62, 165, 17, 115, 118, 97, 81, 166, 46, + 112, 142, 57, 193, 114, 246, 194, 184, 70, 63, 33, 142, 169, 37, + 185, 134, 50, 162, 117, 25, 83, 189, 207, 213, 20, 222, 119, 14, + 152, 4, 188, 250, 253, 45, 166, 147, 216, 30, 225, 155, 99, 157, + 67, 5, 29, 72, 228, 17, 24, 78, 52, 147, 105, 22, 12, 229, + 221, 36, 160, 86, 144, 209, 62, 245, 80, 15, 193, 94, 214, 39, + 38, 89, 239, 113, 21, 233, 53, 68, 101, 243, 234, 103, 96, 96, + 172, 165, 210, 22, 166, 220, 250, 41, 232, 127, 230, 142, 109, 76, + 114, 93, 137, 175, 227, 229, 62, 51, 158, 240, 152, 127, 103, 128, + 84, 133, 1, 213, 114, 229, 116, 242, 45, 246, 61, 73, 161, 106, + 26, 120, 84, 199, 93, 123, 198, 226, 251, 248, 81, 8, 118, 40, + 236, 124, 2, 55, 162, 175, 10, 93, 224, 41, 142, 169, 244, 26, + 216, 126, 226, 207, 172, 210, 110, 173, 54, 12, 21, 181, 79, 31, + 126, 250, 149, 22, 10, 136, 26, 173, 44, 107, 16, 142, 61, 17, + 73, 95, 245, 52, 200, 250, 7, 117, 173, 238, 138, 207, 203, 162, + 3, 220, 248, 230, 185, 99, 172, 196, 2, 168, 211, 137, 70, 245, + 97, 164, 141, 185, 8, 133, 136, 61, 9, 100, 33, 72, 6, 48, + 75, 170, 255, 146, 113, 120, 187, 99, 101, 72, 50, 165, 223, 151, + 230, 10, 108, 28, 21, 96, 116, 77, 90, 23, 88, 234, 115, 216, + 249, 63, 150, 56, 40, 72, 221, 184, 242, 65, 106, 249, 237, 124, + 170, 203, 152, 1, 143, 226, 192, 53, 249, 79, 160, 187, 173, 240, + 163, 160, 207, 184, 141, 190, 121, 243, 45, 133, 182, 122, 152, 19, + 167, 7, 125, 229, 155, 114, 7, 31, 225, 126, 159, 108, 205, 49, + 225, 191, 124, 209, 204, 137, 217, 237, 78, 183, 95, 60, 226, 104, + 162, 67, 128, 7, 5, 232, 203, 201, 145, 130, 247, 226, 180, 3, + 128, 140, 187, 247, 136, 82, 153, 220, 24, 11, 151, 230, 29, 136, + 146, 191, 218, 89, 53, 219, 1, 218, 72, 12, 68, 133, 226, 41, + 79, 14, 137, 109, 220, 70, 6, 105, 106, 165, 31, 22, 182, 251, + 128, 44, 70, 22, 210, 246, 217, 46, 56, 163, 82, 128, 181, 219, + 109, 234, 200, 123, 0, 102, 66, 96, 129, 39, 221, 5, 224, 171, + 6, 192, 113, 207, 145, 101, 2, 172, 33, 200, 27, 78, 147, 236, + 53, 121, 145, 254, 248, 106, 63, 54, 150, 68, 153, 175, 170, 159, + 142, 63, 41, 49, 13, 145, 8, 106, 174, 119, 229, 56, 171, 229, + 197, 87, 94, 15, 48, 197, 72, 0, 139, 98, 8, 79, 235, 254, + 9, 173, 11, 66, 49, 184, 181, 220, 28, 55, 88, 2, 4, 163, + 19, 78, 103, 125, 48, 81, 246, 136, 232, 195, 105, 167, 96, 238, + 121, 105, 45, 237, 249, 124, 177, 100, 108, 119, 183, 169, 105, 113, + 173, 73, 107, 62, 30, 79, 23, 46, 217, 138, 140, 114, 92, 236, + 190, 58, 173, 237, 241, 0, 105, 27, 39, 173, 74, 158, 212, 81, + 31, 105, 253, 215, 195, 125, 136, 187, 27, 172, 7, 41, 22, 198, + 216, 117, 182, 62, 116, 147, 142, 119, 64, 191, 232, 144, 183, 120, + 57, 224, 189, 151, 170, 196, 11, 160, 27, 195, 66, 202, 218, 111, + 254, 141, 139, 233, 162, 53, 31, 111, 29, 49, 143, 192, 187, 56, + 81, 79, 139, 88, 84, 149, 46, 195, 100, 89, 17, 117, 196, 202, + 128, 162, 237, 159, 30, 8, 56, 25, 111, 235, 31, 208, 3, 92, + 135, 40, 63, 167, 203, 75, 90, 3, 79, 201, 214, 220, 130, 202, + 125, 7, 245, 117, 58, 97, 231, 220, 179, 51, 184, 213, 4, 1, + 50, 173, 73, 213, 102, 125, 7, 166, 73, 40, 57, 225, 141, 254, + 36, 36, 236, 159, 47, 150, 226, 195, 91, 114, 71, 93, 219, 181, + 93, 123, 66, 180, 185, 246, 172, 198, 12, 189, 71, 125, 15, 185, + 16, 78, 111, 194, 85, 15, 34, 181, 228, 28, 0, 230, 194, 204, + 250, 104, 17, 206, 173, 31, 154, 65, 55, 193, 191, 192, 152, 139, + 72, 57, 246, 217, 0, 154, 29, 211, 33, 153, 189, 181, 97, 89, + 185, 188, 83, 101, 100, 165, 46, 42, 29, 107, 180, 98, 180, 227, + 88, 249, 216, 76, 77, 20, 150, 30, 202, 200, 112, 154, 79, 196, + 224, 73, 236, 223, 33, 181, 69, 43, 168, 197, 165, 43, 32, 152, + 76, 62, 173, 199, 234, 192, 212, 55, 238, 195, 20, 226, 141, 12, + 233, 250, 142, 17, 236, 230, 67, 130, 110, 101, 206, 106, 199, 19, + 98, 223, 11, 144, 202, 185, 34, 152, 223, 190, 144, 166, 108, 97, + 232, 49, 65, 14, 82, 34, 82, 164, 202, 47, 171, 243, 150, 226, + 228, 52, 168, 247, 205, 253, 76, 166, 67, 217, 110, 47, 101, 252, + 18, 104, 190, 215, 70, 198, 180, 200, 104, 182, 98, 124, 20, 77, + 24, 197, 249, 213, 218, 158, 87, 9, 131, 95, 156, 111, 238, 204, + 241, 124, 106, 194, 236, 56, 36, 48, 193, 214, 240, 206, 113, 251, + 9, 113, 6, 51, 237, 25, 254, 87, 87, 113, 150, 165, 123, 205, + 130, 242, 220, 248, 234, 96, 98, 121, 50, 219, 136, 104, 90, 89, + 149, 7, 238, 100, 8, 54, 26, 60, 179, 13, 55, 201, 208, 226, + 32, 56, 43, 124, 14, 58, 38, 110, 207, 61, 1, 250, 182, 115, + 81, 33, 81, 116, 153, 234, 223, 79, 78, 143, 20, 189, 73, 207, + 136, 30, 29, 205, 132, 24, 125, 211, 146, 2, 17, 150, 159, 68, + 59, 230, 32, 239, 60, 205, 27, 177, 147, 84, 151, 77, 104, 207, + 68, 177, 126, 111, 248, 122, 6, 35, 142, 161, 110, 220, 100, 82, + 242, 194, 39, 158, 131, 138, 71, 160, 240, 59, 23, 34, 217, 88, + 169, 211, 127, 119, 80, 27, 137, 102, 158, 184, 156, 55, 50, 239, + 205, 208, 233, 191, 230, 170, 110, 3, 40, 135, 212, 16, 39, 100, + 55, 67, 71, 218, 117, 177, 94, 31, 117, 243, 53, 125, 155, 22, + 176, 88, 96, 215, 9, 179, 133, 159, 254, 130, 31, 198, 19, 187, + 197, 11, 180, 167, 139, 145, 238, 67, 54, 32, 46, 248, 34, 116, + 27, 183, 213, 95, 209, 204, 94, 3, 33, 57, 95, 233, 139, 162, + 229, 106, 229, 94, 110, 177, 228, 9, 123, 122, 192, 5, 133, 162, + 53, 142, 44, 27, 59, 220, 129, 249, 91, 95, 90, 148, 71, 65, + 204, 116, 79, 169, 76, 39, 92, 126, 52, 223, 31, 116, 214, 159, + 22, 74, 78, 73, 249, 111, 186, 246, 245, 242, 185, 161, 19, 175, + 204, 7, 14, 248, 89, 47, 236, 144, 92, 119, 253, 58, 237, 78, + 73, 11, 169, 172, 132, 248, 30, 37, 50, 208, 253, 57, 202, 85, + 252, 141, 113, 237, 240, 3, 136, 121, 206, 8, 229, 128, 175, 180, + 233, 5, 221, 225, 244, 57, 36, 102, 10, 194, 192, 35, 243, 130, + 79, 242, 227, 59, 120, 26, 59, 231, 13, 80, 105, 148, 216, 192, + 252, 211, 9, 216, 158, 218, 235, 211, 162, 107, 71, 240, 189, 141, + 116, 171, 234, 16, 143, 95, 159, 2, 200, 218, 59, 143, 241, 19, + 239, 229, 83, 243, 109, 121, 104, 243, 115, 99, 117, 129, 26, 147, + 39, 201, 181, 206, 90, 188, 19, 239, 123, 82, 127, 202, 111, 24, + 32, 145, 84, 121, 206, 172, 128, 142, 89, 248, 197, 159, 120, 38, + 243, 35, 170, 80, 132, 65, 36, 112, 200, 244, 115, 7, 73, 70, + 102, 12, 36, 159, 216, 110, 57, 24, 109, 234, 175, 94, 21, 97, + 205, 113, 58, 92, 192, 213, 226, 95, 32, 94, 87, 254, 70, 72, + 57, 109, 236, 63, 168, 75, 25, 68, 235, 113, 94, 164, 204, 32, + 238, 184, 50, 110, 8, 233, 120, 209, 16, 108, 183, 242, 61, 151, + 223, 73, 139, 86, 199, 194, 30, 181, 177, 141, 149, 30, 79, 12, + 92, 18, 24, 134, 173, 126, 127, 129, 37, 137, 212, 138, 198, 109, + 210, 100, 133, 88, 163, 50, 239, 138, 120, 37, 241, 87, 191, 167, + 149, 211, 186, 251, 92, 209, 51, 120, 203, 222, 175, 246, 82, 68, + 176, 157, 36, 140, 7, 118, 164, 82, 178, 108, 172, 65, 162, 17, + 144, 190, 29, 73, 4, 209, 173, 127, 173, 127, 182, 230, 197, 37, + 63, 134, 30, 61, 181, 5, 184, 26, 172, 116, 204, 3, 107, 161, + 194, 47, 90, 73, 47, 149, 166, 226, 40, 234, 149, 246, 0, 161, + 159, 74, 130, 87, 127, 182, 238, 201, 29, 117, 120, 24, 122, 141, + 91, 215, 204, 227, 184, 125, 238, 218, 110, 98, 160, 19, 12, 85, + 89, 34, 127, 22, 43, 195, 49, 158, 226, 201, 159, 232, 242, 157, + 12, 213, 83, 187, 34, 253, 1, 178, 254, 185, 34, 70, 103, 36, + 249, 10, 226, 192, 165, 94, 155, 245, 116, 140, 106, 15, 62, 10, + 85, 52, 7, 98, 255, 11, 63, 36, 138, 218, 116, 73, 248, 163, + 213, 39, 108, 30, 108, 152, 162, 63, 101, 168, 53, 253, 19, 142, + 160, 115, 155, 208, 147, 31, 78, 161, 238, 91, 173, 46, 59, 46, + 72, 251, 217, 13, 69, 172, 210, 233, 153, 69, 227, 193, 206, 2, + 72, 140, 191, 16, 187, 70, 248, 104, 104, 67, 181, 150, 210, 85, + 181, 84, 193, 198, 184, 42, 131, 241, 100, 126, 251, 132, 112, 139, + 120, 237, 201, 49, 63, 208, 122, 249, 67, 32, 18, 82, 72, 16, + 80, 93, 221, 35, 224, 193, 220, 52, 248, 64, 162, 247, 119, 206, + 99, 211, 24, 215, 31, 112, 164, 15, 197, 128, 1, 20, 2, 0, + 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 99, 108, 101, 97, 114, 116, 111, 109, 97, 114, 107, + 13, 128, 3, +}; diff --git a/Rendering/fonts/face_times_bold_italic.cxx b/Rendering/fonts/face_times_bold_italic.cxx new file mode 100644 index 0000000..098847f --- /dev/null +++ b/Rendering/fonts/face_times_bold_italic.cxx @@ -0,0 +1,2527 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Times Bold Italic +// Bitstream Charter Bold Italic (c0633bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_times_bold_italic_buffer_length = 35229; + +unsigned char face_times_bold_italic_buffer[] = { + 128, 1, 234, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 83, + 97, 116, 32, 78, 111, 118, 32, 32, 51, 32, 50, 50, 58, 51, + 56, 58, 49, 52, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 66, + 105, 116, 115, 116, 114, 101, 97, 109, 32, 67, 104, 97, 114, 116, + 101, 114, 32, 66, 111, 108, 100, 32, 73, 116, 97, 108, 105, 99, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 13, 32, 32, 47, 70, 97, 109, 105, 108, 121, 78, 97, 109, 101, + 32, 40, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 67, 104, + 97, 114, 116, 101, 114, 41, 32, 114, 101, 97, 100, 111, 110, 108, + 121, 32, 100, 101, 102, 13, 32, 32, 47, 87, 101, 105, 103, 104, + 116, 32, 40, 66, 111, 108, 100, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 73, 116, 97, + 108, 105, 99, 65, 110, 103, 108, 101, 32, 32, 49, 49, 46, 48, + 48, 48, 48, 32, 100, 101, 102, 13, 32, 32, 47, 105, 115, 70, + 105, 120, 101, 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, + 101, 32, 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, + 108, 105, 110, 101, 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, + 49, 48, 57, 32, 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, + 101, 114, 108, 105, 110, 101, 84, 104, 105, 99, 107, 110, 101, 115, + 115, 32, 57, 48, 32, 100, 101, 102, 13, 101, 110, 100, 32, 114, + 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 70, + 111, 110, 116, 78, 97, 109, 101, 32, 47, 67, 104, 97, 114, 116, + 101, 114, 66, 84, 45, 66, 111, 108, 100, 73, 116, 97, 108, 105, + 99, 32, 100, 101, 102, 13, 47, 80, 97, 105, 110, 116, 84, 121, + 112, 101, 32, 48, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, + 84, 121, 112, 101, 32, 49, 32, 100, 101, 102, 13, 47, 70, 111, + 110, 116, 77, 97, 116, 114, 105, 120, 32, 91, 48, 46, 48, 48, + 49, 32, 48, 32, 48, 32, 48, 46, 48, 48, 49, 32, 48, 32, + 48, 93, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, + 102, 13, 47, 69, 110, 99, 111, 100, 105, 110, 103, 32, 83, 116, + 97, 110, 100, 97, 114, 100, 69, 110, 99, 111, 100, 105, 110, 103, + 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, 66, 66, 111, 120, + 32, 123, 45, 49, 57, 48, 32, 45, 50, 51, 54, 32, 49, 50, + 52, 51, 32, 57, 55, 49, 125, 32, 114, 101, 97, 100, 111, 110, + 108, 121, 32, 100, 101, 102, 13, 47, 85, 110, 105, 113, 117, 101, + 73, 68, 32, 49, 53, 53, 51, 48, 54, 51, 51, 32, 100, 101, + 102, 13, 99, 117, 114, 114, 101, 110, 116, 100, 105, 99, 116, 32, + 101, 110, 100, 13, 99, 117, 114, 114, 101, 110, 116, 102, 105, 108, + 101, 32, 101, 101, 120, 101, 99, 13, 128, 2, 139, 129, 0, 0, + 162, 149, 24, 64, 131, 138, 65, 51, 131, 156, 169, 210, 46, 43, + 153, 242, 182, 28, 118, 124, 214, 117, 8, 10, 172, 252, 178, 78, + 25, 205, 19, 54, 115, 155, 182, 73, 148, 197, 103, 55, 9, 11, + 76, 236, 146, 201, 148, 95, 240, 116, 94, 247, 255, 198, 27, 176, + 169, 163, 184, 73, 231, 233, 135, 64, 229, 108, 11, 90, 247, 135, + 85, 156, 198, 149, 106, 179, 30, 51, 207, 133, 83, 213, 92, 11, + 14, 129, 142, 245, 236, 107, 244, 129, 98, 234, 196, 46, 115, 128, + 202, 146, 29, 174, 28, 130, 179, 143, 214, 188, 242, 0, 26, 187, + 93, 0, 26, 86, 21, 112, 148, 207, 226, 125, 143, 78, 172, 150, + 147, 232, 131, 114, 210, 3, 88, 180, 126, 12, 56, 118, 85, 142, + 191, 117, 122, 31, 188, 92, 28, 221, 246, 43, 60, 87, 191, 114, + 126, 241, 196, 135, 148, 34, 193, 66, 160, 132, 209, 199, 70, 42, + 194, 147, 224, 151, 250, 190, 58, 62, 207, 205, 130, 113, 242, 89, + 131, 59, 172, 121, 18, 112, 114, 24, 236, 154, 48, 99, 191, 115, + 133, 224, 45, 140, 16, 88, 172, 6, 223, 0, 179, 59, 140, 1, + 135, 104, 178, 120, 1, 14, 177, 75, 214, 154, 28, 164, 67, 21, + 35, 37, 221, 151, 151, 228, 189, 157, 17, 1, 97, 17, 14, 185, + 227, 218, 196, 23, 66, 243, 73, 132, 77, 122, 78, 175, 238, 253, + 152, 24, 10, 30, 233, 197, 14, 38, 3, 205, 224, 147, 195, 221, + 229, 7, 113, 104, 50, 212, 65, 254, 67, 98, 139, 81, 5, 16, + 172, 164, 168, 18, 240, 152, 187, 29, 1, 251, 92, 239, 200, 143, + 21, 177, 250, 244, 148, 128, 82, 8, 216, 237, 64, 67, 147, 255, + 29, 216, 55, 205, 52, 251, 69, 31, 14, 134, 191, 212, 157, 250, + 8, 119, 217, 88, 75, 182, 26, 173, 66, 112, 4, 195, 76, 68, + 15, 156, 149, 213, 172, 187, 77, 227, 121, 90, 183, 128, 178, 60, + 34, 102, 97, 138, 49, 117, 112, 195, 74, 59, 183, 131, 114, 149, + 16, 154, 141, 253, 63, 99, 186, 106, 186, 42, 114, 244, 10, 251, + 115, 209, 100, 116, 119, 65, 150, 197, 224, 38, 103, 27, 248, 195, + 30, 119, 146, 157, 252, 6, 228, 178, 10, 58, 183, 227, 43, 185, + 234, 155, 173, 218, 94, 108, 52, 118, 123, 156, 24, 110, 121, 232, + 217, 87, 226, 80, 134, 114, 194, 123, 74, 69, 177, 97, 49, 9, + 206, 206, 199, 54, 77, 176, 149, 62, 119, 64, 169, 149, 238, 116, + 66, 241, 25, 6, 149, 45, 215, 138, 194, 185, 82, 186, 226, 156, + 56, 119, 151, 92, 218, 7, 229, 17, 21, 248, 73, 173, 214, 120, + 103, 72, 74, 210, 216, 159, 123, 93, 246, 55, 137, 16, 16, 151, + 208, 172, 69, 161, 82, 141, 171, 11, 182, 7, 213, 13, 135, 35, + 205, 34, 204, 20, 60, 105, 181, 169, 80, 155, 193, 135, 255, 152, + 100, 241, 93, 74, 146, 210, 93, 211, 38, 230, 185, 135, 248, 145, + 26, 172, 98, 25, 205, 141, 205, 207, 117, 39, 218, 125, 47, 199, + 247, 199, 115, 19, 207, 61, 65, 58, 127, 233, 226, 7, 209, 158, + 56, 203, 50, 129, 245, 45, 54, 72, 80, 181, 81, 25, 61, 226, + 127, 134, 237, 15, 38, 103, 134, 254, 41, 146, 112, 65, 52, 115, + 65, 33, 151, 246, 24, 185, 76, 239, 58, 254, 103, 75, 50, 161, + 115, 109, 220, 116, 74, 227, 176, 179, 75, 201, 56, 76, 199, 4, + 75, 102, 20, 213, 142, 96, 85, 212, 22, 61, 23, 124, 217, 137, + 166, 75, 143, 169, 189, 204, 107, 147, 106, 177, 50, 105, 40, 27, + 23, 145, 13, 118, 234, 255, 146, 53, 55, 152, 11, 144, 151, 235, + 141, 145, 5, 250, 181, 126, 131, 245, 105, 62, 37, 37, 148, 174, + 192, 182, 255, 33, 60, 151, 234, 229, 127, 228, 237, 67, 31, 174, + 14, 142, 40, 107, 9, 96, 159, 101, 40, 228, 215, 177, 221, 242, + 244, 172, 195, 81, 131, 77, 220, 93, 155, 24, 131, 158, 216, 21, + 4, 130, 33, 164, 115, 19, 133, 5, 47, 106, 133, 241, 48, 125, + 64, 86, 51, 7, 180, 224, 46, 91, 146, 17, 40, 48, 189, 214, + 172, 220, 118, 92, 45, 185, 118, 174, 26, 140, 70, 21, 230, 13, + 196, 24, 182, 94, 216, 207, 34, 211, 175, 0, 76, 53, 143, 231, + 21, 79, 192, 93, 216, 162, 12, 157, 173, 166, 150, 21, 226, 29, + 187, 135, 61, 29, 52, 105, 97, 23, 196, 214, 129, 249, 55, 250, + 183, 154, 105, 94, 137, 182, 111, 179, 133, 162, 34, 34, 72, 127, + 249, 197, 193, 69, 162, 209, 214, 224, 129, 89, 243, 141, 224, 113, + 0, 161, 127, 226, 233, 73, 68, 28, 53, 140, 47, 165, 84, 57, + 69, 24, 155, 216, 215, 237, 211, 95, 234, 122, 20, 225, 142, 142, + 32, 129, 12, 211, 52, 59, 53, 98, 151, 73, 166, 130, 31, 121, + 204, 157, 162, 79, 132, 76, 153, 19, 15, 164, 79, 8, 39, 99, + 228, 35, 184, 206, 208, 153, 67, 57, 199, 162, 108, 115, 142, 215, + 249, 18, 160, 6, 80, 186, 161, 9, 140, 209, 212, 75, 217, 244, + 187, 90, 44, 220, 120, 68, 175, 110, 10, 243, 243, 207, 142, 145, + 214, 105, 13, 72, 140, 191, 16, 161, 41, 179, 154, 85, 136, 223, + 42, 160, 189, 17, 254, 29, 76, 205, 38, 211, 199, 235, 182, 242, + 109, 39, 183, 47, 56, 38, 99, 40, 62, 235, 94, 37, 87, 207, + 165, 23, 195, 9, 159, 62, 223, 62, 30, 249, 90, 49, 35, 144, + 99, 127, 134, 43, 88, 69, 246, 161, 92, 123, 142, 89, 204, 180, + 17, 91, 168, 155, 79, 38, 199, 186, 130, 123, 156, 140, 195, 42, + 112, 89, 232, 223, 217, 28, 50, 99, 46, 222, 76, 215, 69, 162, + 97, 155, 13, 85, 103, 155, 210, 81, 12, 138, 89, 167, 17, 198, + 72, 62, 67, 223, 58, 1, 98, 123, 124, 25, 89, 76, 83, 34, + 160, 234, 130, 178, 195, 76, 141, 32, 162, 60, 195, 114, 48, 36, + 226, 49, 121, 109, 165, 207, 235, 158, 51, 151, 80, 4, 151, 73, + 139, 187, 51, 10, 85, 238, 142, 139, 99, 41, 239, 9, 28, 177, + 63, 173, 251, 90, 133, 19, 43, 127, 141, 107, 128, 151, 29, 116, + 42, 100, 20, 15, 40, 75, 1, 73, 186, 186, 34, 74, 240, 138, + 37, 182, 202, 178, 91, 224, 71, 201, 18, 61, 97, 225, 110, 115, + 248, 253, 136, 64, 230, 70, 1, 75, 138, 72, 144, 73, 175, 169, + 13, 193, 196, 83, 156, 9, 220, 82, 226, 38, 137, 0, 162, 81, + 50, 226, 6, 136, 102, 226, 222, 169, 196, 96, 151, 233, 129, 236, + 41, 47, 234, 147, 242, 136, 16, 221, 91, 221, 46, 33, 88, 34, + 56, 253, 189, 109, 122, 203, 138, 23, 217, 181, 63, 104, 226, 231, + 249, 200, 47, 229, 43, 38, 174, 183, 29, 230, 187, 114, 84, 178, + 74, 193, 50, 31, 204, 226, 44, 2, 210, 19, 174, 104, 146, 230, + 195, 164, 151, 13, 173, 219, 128, 162, 37, 183, 196, 22, 8, 169, + 212, 179, 109, 21, 91, 242, 152, 193, 102, 111, 122, 26, 222, 72, + 51, 96, 37, 97, 149, 79, 130, 73, 2, 251, 81, 207, 64, 163, + 33, 11, 172, 224, 39, 75, 105, 226, 77, 22, 175, 1, 88, 231, + 158, 224, 141, 44, 35, 130, 221, 180, 114, 198, 182, 9, 111, 122, + 117, 55, 184, 149, 251, 202, 221, 38, 71, 159, 142, 131, 142, 60, + 37, 203, 174, 235, 121, 163, 21, 83, 91, 96, 207, 29, 120, 62, + 229, 37, 216, 247, 17, 187, 68, 195, 98, 254, 128, 191, 46, 84, + 133, 184, 135, 166, 115, 156, 220, 188, 139, 234, 94, 157, 118, 81, + 114, 213, 200, 55, 85, 49, 222, 200, 124, 6, 222, 40, 91, 166, + 68, 1, 239, 121, 173, 121, 50, 200, 176, 78, 131, 29, 88, 224, + 233, 122, 127, 146, 156, 216, 103, 230, 40, 35, 238, 171, 223, 139, + 116, 109, 77, 206, 162, 22, 99, 40, 82, 74, 159, 179, 129, 161, + 231, 53, 116, 62, 41, 95, 99, 135, 254, 240, 255, 173, 113, 170, + 17, 67, 226, 55, 90, 114, 201, 228, 20, 33, 152, 17, 97, 129, + 59, 53, 215, 206, 38, 79, 3, 66, 125, 86, 202, 171, 4, 153, + 67, 12, 187, 35, 92, 9, 63, 161, 131, 154, 25, 24, 219, 79, + 179, 143, 216, 228, 116, 55, 204, 94, 209, 244, 255, 95, 45, 202, + 155, 193, 92, 57, 144, 106, 194, 212, 240, 143, 15, 145, 203, 32, + 244, 35, 108, 65, 83, 56, 171, 187, 41, 191, 214, 109, 72, 49, + 54, 173, 122, 3, 178, 134, 11, 221, 100, 139, 135, 223, 37, 163, + 62, 193, 40, 254, 108, 143, 183, 237, 246, 87, 174, 105, 138, 248, + 253, 62, 59, 66, 105, 110, 197, 224, 158, 8, 82, 37, 59, 221, + 231, 170, 34, 222, 194, 107, 246, 239, 25, 135, 184, 162, 151, 24, + 42, 57, 133, 83, 178, 212, 66, 138, 94, 139, 110, 236, 33, 235, + 186, 144, 86, 12, 217, 43, 194, 57, 33, 17, 190, 208, 126, 159, + 29, 102, 52, 245, 210, 177, 132, 217, 38, 180, 119, 43, 15, 61, + 169, 120, 131, 143, 74, 189, 53, 74, 124, 227, 70, 201, 198, 17, + 237, 20, 186, 122, 19, 135, 165, 94, 192, 57, 183, 19, 24, 143, + 17, 83, 176, 33, 25, 18, 114, 16, 140, 161, 226, 211, 13, 102, + 19, 32, 216, 80, 72, 71, 145, 34, 59, 115, 228, 247, 150, 144, + 167, 213, 221, 143, 57, 135, 174, 196, 15, 224, 228, 94, 157, 12, + 38, 163, 78, 219, 100, 93, 52, 217, 180, 138, 0, 35, 168, 129, + 57, 158, 233, 245, 119, 80, 222, 19, 77, 21, 23, 86, 106, 152, + 61, 73, 80, 148, 116, 137, 79, 20, 193, 90, 202, 93, 237, 116, + 73, 20, 3, 255, 153, 137, 98, 93, 185, 228, 66, 84, 145, 144, + 18, 122, 117, 25, 227, 67, 202, 199, 201, 10, 249, 102, 48, 203, + 250, 204, 229, 30, 53, 22, 42, 239, 151, 224, 137, 236, 200, 122, + 120, 120, 125, 254, 250, 183, 104, 7, 224, 208, 110, 203, 13, 213, + 128, 253, 127, 87, 112, 176, 128, 214, 23, 150, 144, 73, 166, 175, + 101, 29, 66, 89, 86, 186, 160, 151, 36, 188, 112, 8, 211, 167, + 109, 96, 160, 63, 46, 159, 82, 3, 251, 205, 205, 177, 184, 74, + 190, 66, 209, 46, 138, 186, 166, 111, 129, 197, 158, 31, 96, 202, + 90, 77, 40, 198, 39, 48, 57, 75, 248, 28, 83, 73, 81, 3, + 67, 17, 182, 59, 205, 30, 56, 43, 162, 41, 89, 134, 220, 21, + 141, 62, 112, 180, 10, 118, 187, 185, 165, 183, 244, 140, 75, 116, + 49, 147, 214, 124, 24, 9, 144, 61, 75, 145, 42, 204, 174, 172, + 192, 114, 152, 49, 61, 252, 243, 217, 115, 231, 207, 137, 87, 2, + 190, 43, 88, 171, 200, 74, 55, 106, 242, 234, 0, 215, 73, 242, + 156, 214, 166, 154, 101, 164, 7, 223, 59, 199, 208, 209, 35, 123, + 63, 211, 158, 9, 18, 234, 84, 238, 20, 165, 17, 17, 46, 212, + 76, 77, 235, 142, 148, 98, 82, 255, 127, 196, 25, 152, 70, 184, + 0, 171, 185, 96, 247, 98, 160, 51, 90, 116, 78, 252, 174, 226, + 218, 51, 231, 153, 119, 86, 39, 173, 62, 80, 147, 133, 172, 26, + 127, 173, 248, 171, 104, 31, 53, 223, 241, 34, 245, 205, 82, 57, + 138, 42, 89, 198, 90, 202, 90, 72, 217, 59, 128, 158, 224, 252, + 39, 247, 212, 44, 163, 97, 11, 61, 35, 57, 20, 240, 55, 229, + 82, 50, 0, 182, 116, 223, 193, 160, 104, 80, 175, 75, 97, 174, + 162, 116, 79, 242, 190, 166, 229, 122, 161, 144, 232, 181, 11, 115, + 131, 113, 109, 195, 33, 7, 87, 251, 10, 175, 47, 49, 138, 32, + 98, 65, 168, 25, 49, 1, 220, 140, 236, 73, 24, 159, 155, 207, + 78, 247, 72, 229, 38, 234, 85, 174, 247, 85, 39, 8, 250, 112, + 139, 138, 18, 63, 203, 253, 130, 61, 211, 192, 79, 86, 110, 136, + 128, 213, 217, 47, 12, 168, 226, 118, 181, 255, 111, 13, 142, 32, + 255, 146, 92, 66, 114, 187, 104, 44, 80, 13, 75, 193, 176, 249, + 202, 219, 213, 111, 97, 34, 53, 62, 20, 50, 128, 198, 95, 178, + 164, 2, 90, 63, 91, 217, 238, 151, 115, 1, 128, 240, 198, 195, + 1, 101, 232, 126, 76, 49, 118, 136, 248, 163, 88, 154, 151, 15, + 31, 131, 107, 51, 207, 50, 208, 36, 105, 85, 112, 83, 246, 101, + 206, 74, 20, 247, 20, 247, 35, 38, 182, 212, 25, 148, 2, 47, + 84, 83, 162, 128, 220, 72, 33, 240, 177, 9, 108, 60, 215, 212, + 147, 176, 146, 91, 5, 230, 15, 28, 178, 81, 3, 198, 66, 104, + 220, 120, 24, 67, 122, 120, 76, 85, 225, 36, 99, 196, 54, 51, + 140, 219, 144, 212, 224, 229, 19, 76, 153, 8, 140, 252, 141, 183, + 90, 11, 65, 80, 18, 215, 29, 228, 132, 126, 24, 141, 69, 209, + 228, 33, 148, 164, 144, 145, 97, 206, 146, 140, 224, 181, 251, 194, + 147, 26, 211, 23, 53, 169, 26, 248, 11, 248, 61, 144, 139, 108, + 197, 83, 129, 120, 245, 142, 168, 213, 36, 57, 65, 217, 8, 89, + 52, 73, 227, 98, 152, 99, 120, 132, 172, 169, 252, 186, 131, 106, + 115, 80, 81, 64, 33, 237, 6, 163, 43, 40, 128, 122, 22, 141, + 19, 141, 223, 166, 48, 41, 104, 222, 237, 230, 252, 169, 74, 47, + 62, 43, 128, 184, 48, 231, 214, 247, 230, 44, 22, 214, 180, 147, + 130, 143, 2, 224, 180, 138, 34, 46, 189, 181, 150, 167, 74, 144, + 237, 30, 210, 71, 83, 181, 197, 23, 68, 247, 199, 79, 164, 166, + 237, 77, 220, 252, 30, 207, 131, 185, 12, 164, 213, 33, 9, 180, + 208, 6, 48, 40, 215, 96, 20, 118, 42, 28, 209, 42, 136, 197, + 11, 22, 59, 150, 215, 90, 251, 214, 100, 51, 75, 240, 180, 205, + 134, 52, 136, 100, 201, 111, 82, 129, 150, 183, 229, 137, 111, 178, + 156, 234, 98, 89, 53, 70, 0, 0, 38, 145, 168, 125, 12, 149, + 153, 146, 171, 248, 230, 253, 223, 4, 15, 223, 83, 2, 122, 162, + 163, 211, 170, 54, 143, 1, 133, 203, 84, 16, 42, 175, 42, 17, + 117, 161, 156, 255, 189, 37, 204, 198, 198, 116, 248, 195, 63, 236, + 33, 5, 59, 66, 91, 216, 42, 19, 66, 222, 103, 254, 226, 149, + 4, 81, 136, 95, 98, 200, 214, 138, 204, 37, 166, 255, 124, 166, + 231, 106, 31, 171, 188, 137, 213, 46, 97, 213, 189, 242, 141, 38, + 182, 48, 84, 177, 1, 80, 186, 16, 55, 66, 50, 66, 203, 75, + 217, 26, 213, 84, 157, 241, 143, 232, 140, 24, 254, 140, 120, 253, + 174, 246, 203, 131, 188, 111, 120, 78, 189, 63, 189, 224, 201, 86, + 33, 207, 152, 97, 135, 200, 35, 160, 162, 152, 4, 218, 180, 17, + 225, 244, 9, 36, 249, 47, 183, 28, 32, 174, 9, 146, 111, 195, + 107, 61, 40, 67, 71, 25, 135, 204, 212, 131, 17, 16, 25, 30, + 207, 22, 104, 77, 86, 213, 216, 172, 162, 231, 21, 211, 74, 125, + 115, 195, 174, 40, 124, 228, 214, 247, 89, 214, 162, 32, 160, 176, + 164, 230, 64, 6, 65, 113, 152, 86, 66, 42, 201, 98, 250, 253, + 243, 121, 150, 96, 189, 136, 116, 33, 238, 200, 190, 203, 40, 178, + 159, 237, 39, 115, 53, 105, 226, 248, 12, 212, 143, 16, 179, 5, + 220, 199, 140, 165, 14, 247, 241, 169, 215, 7, 82, 166, 104, 2, + 13, 243, 67, 133, 133, 124, 118, 216, 4, 236, 61, 242, 82, 69, + 201, 165, 71, 243, 123, 43, 71, 180, 233, 72, 147, 208, 186, 10, + 136, 172, 31, 145, 248, 173, 13, 57, 72, 164, 223, 85, 237, 108, + 214, 66, 20, 198, 219, 192, 79, 2, 39, 169, 250, 146, 66, 246, + 203, 196, 89, 120, 101, 174, 156, 159, 166, 90, 19, 200, 32, 136, + 206, 232, 61, 11, 87, 129, 185, 36, 162, 153, 69, 16, 253, 242, + 170, 47, 71, 187, 181, 187, 16, 150, 213, 98, 241, 231, 99, 97, + 170, 156, 137, 149, 163, 118, 170, 228, 164, 117, 59, 204, 119, 216, + 72, 230, 208, 148, 248, 119, 255, 202, 61, 17, 71, 253, 35, 202, + 153, 233, 240, 78, 184, 149, 76, 63, 81, 119, 10, 209, 72, 0, + 26, 22, 104, 41, 178, 35, 146, 11, 49, 237, 18, 117, 248, 254, + 48, 54, 121, 162, 17, 33, 125, 125, 164, 141, 18, 217, 116, 49, + 96, 66, 170, 29, 154, 56, 98, 199, 55, 82, 41, 78, 204, 212, + 179, 25, 194, 5, 85, 193, 41, 185, 157, 110, 229, 94, 101, 119, + 160, 61, 161, 179, 166, 84, 199, 196, 57, 97, 43, 232, 128, 38, + 196, 202, 172, 24, 251, 39, 184, 57, 122, 64, 234, 31, 226, 218, + 163, 107, 119, 223, 163, 145, 144, 103, 224, 206, 64, 23, 249, 118, + 82, 146, 108, 25, 0, 29, 238, 119, 133, 120, 97, 244, 38, 191, + 114, 236, 240, 17, 154, 169, 172, 47, 147, 170, 74, 36, 13, 155, + 43, 160, 173, 238, 204, 141, 3, 96, 255, 232, 106, 183, 108, 4, + 25, 21, 111, 249, 144, 210, 228, 9, 108, 87, 23, 107, 251, 149, + 39, 179, 193, 161, 176, 94, 254, 75, 141, 230, 85, 214, 221, 77, + 252, 61, 157, 115, 81, 139, 39, 31, 135, 15, 51, 195, 122, 233, + 16, 225, 25, 73, 90, 12, 125, 142, 229, 203, 145, 122, 225, 108, + 183, 176, 94, 218, 166, 57, 32, 61, 109, 62, 248, 27, 173, 13, + 143, 51, 244, 127, 30, 137, 240, 13, 196, 250, 65, 211, 178, 36, + 249, 20, 118, 5, 35, 55, 110, 54, 72, 5, 54, 129, 188, 251, + 182, 62, 237, 61, 20, 121, 29, 230, 88, 131, 50, 212, 188, 44, + 141, 33, 205, 63, 84, 221, 65, 91, 24, 222, 202, 18, 190, 88, + 126, 174, 5, 197, 162, 130, 115, 213, 168, 36, 170, 201, 156, 122, + 216, 100, 122, 19, 211, 3, 174, 239, 192, 31, 167, 248, 33, 194, + 150, 58, 21, 22, 7, 226, 28, 157, 99, 111, 36, 31, 170, 202, + 149, 206, 139, 216, 148, 125, 206, 132, 8, 39, 239, 144, 218, 106, + 34, 62, 145, 193, 196, 229, 11, 199, 78, 67, 180, 244, 112, 172, + 101, 180, 159, 175, 254, 229, 95, 89, 144, 222, 105, 8, 46, 252, + 209, 141, 153, 98, 219, 60, 72, 128, 63, 183, 234, 210, 171, 26, + 137, 75, 72, 202, 47, 85, 61, 193, 45, 114, 181, 166, 3, 219, + 136, 115, 30, 129, 81, 128, 8, 48, 206, 86, 216, 16, 180, 199, + 109, 25, 212, 154, 56, 219, 74, 235, 23, 45, 223, 52, 104, 199, + 226, 135, 207, 165, 180, 175, 202, 196, 211, 218, 26, 45, 231, 13, + 153, 45, 50, 97, 38, 71, 221, 235, 45, 204, 215, 173, 4, 220, + 94, 39, 33, 55, 171, 114, 22, 229, 168, 39, 6, 199, 135, 254, + 149, 251, 237, 14, 72, 169, 61, 38, 121, 89, 251, 247, 58, 63, + 236, 196, 244, 103, 90, 55, 28, 66, 141, 12, 147, 172, 110, 228, + 79, 140, 169, 45, 214, 71, 38, 102, 93, 65, 227, 195, 51, 177, + 169, 100, 103, 211, 178, 87, 48, 17, 237, 32, 239, 189, 28, 105, + 94, 237, 66, 224, 43, 62, 56, 181, 46, 206, 39, 131, 212, 159, + 112, 36, 108, 77, 241, 164, 163, 128, 64, 249, 209, 17, 150, 239, + 145, 90, 30, 130, 194, 196, 206, 178, 210, 239, 79, 167, 33, 253, + 184, 85, 185, 65, 147, 2, 247, 228, 59, 131, 163, 139, 34, 218, + 12, 6, 215, 189, 198, 135, 181, 237, 19, 215, 81, 245, 0, 43, + 232, 159, 125, 196, 22, 75, 36, 139, 0, 35, 91, 16, 39, 200, + 128, 140, 88, 122, 187, 94, 139, 68, 56, 147, 224, 224, 15, 69, + 119, 101, 59, 84, 202, 39, 64, 254, 231, 88, 250, 54, 221, 76, + 70, 207, 38, 168, 138, 239, 45, 12, 105, 108, 116, 146, 198, 78, + 127, 193, 139, 128, 183, 226, 158, 22, 101, 51, 246, 187, 88, 93, + 156, 115, 25, 31, 105, 10, 108, 175, 229, 245, 76, 87, 130, 101, + 44, 105, 191, 115, 252, 108, 82, 209, 56, 120, 123, 33, 206, 59, + 45, 208, 44, 135, 219, 155, 145, 47, 235, 23, 226, 200, 36, 169, + 216, 124, 101, 190, 170, 210, 106, 219, 165, 194, 245, 17, 105, 92, + 170, 76, 198, 39, 191, 73, 34, 154, 245, 69, 105, 147, 11, 94, + 3, 126, 119, 100, 237, 99, 185, 51, 62, 111, 250, 103, 149, 17, + 146, 59, 5, 12, 206, 136, 39, 1, 152, 160, 235, 149, 177, 58, + 123, 153, 119, 213, 93, 184, 163, 210, 130, 89, 15, 63, 154, 231, + 98, 168, 185, 179, 153, 118, 32, 187, 41, 144, 187, 210, 172, 25, + 52, 228, 117, 155, 30, 76, 179, 111, 218, 2, 146, 133, 172, 145, + 128, 93, 77, 216, 172, 10, 4, 174, 77, 41, 236, 223, 148, 0, + 109, 93, 24, 101, 255, 117, 78, 20, 216, 144, 246, 130, 187, 14, + 144, 74, 252, 138, 224, 216, 68, 236, 195, 4, 109, 91, 129, 189, + 47, 116, 23, 49, 195, 15, 97, 151, 58, 178, 221, 194, 100, 224, + 19, 8, 108, 168, 36, 28, 72, 106, 239, 172, 217, 121, 156, 142, + 211, 139, 118, 59, 222, 86, 149, 76, 98, 113, 137, 249, 8, 77, + 78, 222, 237, 43, 7, 67, 0, 91, 247, 164, 89, 138, 198, 55, + 186, 74, 204, 160, 157, 97, 87, 252, 128, 255, 43, 164, 200, 252, + 236, 199, 225, 161, 18, 111, 54, 246, 117, 57, 223, 126, 112, 200, + 17, 59, 218, 189, 122, 171, 153, 74, 96, 252, 75, 159, 184, 98, + 216, 19, 190, 113, 94, 206, 72, 50, 38, 49, 68, 110, 54, 233, + 18, 104, 141, 164, 226, 150, 211, 71, 122, 91, 134, 191, 21, 224, + 74, 217, 174, 235, 242, 82, 241, 5, 83, 169, 141, 143, 47, 231, + 217, 122, 164, 1, 219, 69, 75, 201, 13, 225, 215, 218, 141, 213, + 8, 103, 130, 163, 126, 253, 228, 32, 153, 119, 221, 74, 216, 203, + 232, 253, 78, 10, 41, 141, 136, 37, 140, 68, 215, 32, 188, 131, + 204, 61, 70, 144, 140, 65, 230, 61, 104, 206, 201, 50, 18, 251, + 11, 30, 112, 220, 165, 224, 193, 41, 62, 128, 186, 97, 159, 241, + 14, 42, 127, 101, 146, 231, 24, 172, 210, 27, 16, 68, 220, 171, + 190, 144, 59, 132, 86, 78, 24, 83, 105, 219, 179, 142, 66, 105, + 19, 201, 91, 19, 144, 114, 171, 16, 62, 102, 157, 153, 106, 14, + 19, 161, 210, 196, 83, 255, 145, 247, 108, 246, 168, 178, 207, 11, + 43, 210, 115, 211, 83, 212, 206, 142, 53, 185, 1, 154, 212, 24, + 110, 193, 174, 164, 73, 37, 49, 229, 190, 52, 208, 138, 138, 164, + 101, 159, 47, 124, 237, 36, 226, 17, 86, 119, 33, 224, 234, 92, + 109, 100, 75, 184, 232, 98, 194, 94, 182, 137, 45, 5, 168, 63, + 84, 252, 114, 205, 251, 108, 81, 79, 240, 19, 115, 236, 21, 224, + 175, 51, 57, 240, 67, 176, 252, 182, 51, 243, 12, 30, 254, 45, + 173, 199, 102, 63, 243, 123, 54, 247, 159, 90, 61, 77, 29, 76, + 206, 108, 148, 150, 139, 51, 119, 9, 163, 74, 205, 84, 98, 235, + 2, 37, 76, 202, 143, 133, 203, 251, 194, 121, 91, 35, 175, 86, + 169, 181, 115, 123, 60, 98, 64, 217, 93, 60, 74, 160, 238, 45, + 107, 53, 167, 81, 134, 255, 51, 82, 116, 217, 112, 78, 60, 8, + 6, 36, 146, 143, 108, 230, 27, 128, 173, 159, 147, 65, 250, 74, + 222, 179, 44, 94, 166, 162, 68, 67, 183, 41, 198, 164, 175, 187, + 81, 98, 151, 155, 241, 33, 4, 100, 17, 23, 144, 229, 80, 225, + 91, 12, 145, 156, 89, 74, 163, 150, 219, 61, 130, 145, 48, 231, + 50, 34, 47, 204, 254, 203, 84, 59, 164, 132, 3, 108, 238, 128, + 68, 110, 141, 10, 181, 136, 219, 210, 85, 118, 158, 93, 131, 40, + 209, 154, 255, 230, 84, 231, 11, 89, 87, 2, 72, 43, 167, 7, + 39, 135, 113, 110, 233, 235, 86, 223, 26, 50, 135, 198, 127, 18, + 251, 233, 186, 189, 67, 106, 216, 105, 119, 45, 217, 138, 46, 194, + 186, 96, 247, 95, 172, 209, 145, 167, 31, 30, 7, 175, 114, 27, + 158, 255, 172, 133, 55, 179, 52, 35, 110, 80, 183, 195, 49, 60, + 63, 125, 255, 21, 78, 75, 121, 177, 110, 226, 227, 127, 119, 207, + 163, 222, 199, 95, 211, 140, 211, 179, 167, 207, 220, 238, 42, 140, + 71, 105, 126, 220, 195, 222, 83, 202, 58, 64, 11, 37, 87, 99, + 13, 17, 203, 138, 207, 7, 133, 222, 153, 148, 164, 252, 193, 6, + 216, 62, 214, 114, 48, 236, 243, 158, 42, 8, 166, 21, 147, 187, + 133, 231, 67, 167, 60, 119, 88, 239, 87, 180, 164, 96, 90, 110, + 114, 195, 1, 140, 60, 137, 110, 83, 77, 101, 4, 58, 44, 64, + 248, 165, 14, 108, 252, 107, 156, 189, 73, 56, 83, 208, 96, 211, + 55, 58, 246, 181, 11, 116, 42, 210, 228, 55, 55, 255, 45, 86, + 1, 3, 224, 153, 197, 183, 67, 121, 38, 255, 224, 91, 238, 213, + 77, 204, 164, 107, 225, 53, 16, 200, 151, 5, 58, 182, 152, 118, + 72, 138, 250, 150, 63, 160, 205, 211, 83, 255, 15, 114, 106, 231, + 158, 222, 149, 85, 97, 254, 147, 172, 186, 188, 61, 124, 112, 255, + 106, 20, 5, 200, 160, 128, 133, 26, 26, 207, 214, 219, 213, 174, + 109, 118, 139, 23, 106, 150, 223, 98, 142, 18, 146, 175, 236, 196, + 65, 120, 136, 76, 29, 164, 201, 128, 109, 58, 229, 254, 72, 22, + 50, 227, 8, 106, 132, 29, 141, 223, 86, 8, 74, 248, 55, 234, + 124, 10, 28, 217, 217, 5, 211, 6, 57, 1, 23, 198, 102, 94, + 139, 213, 133, 206, 50, 141, 0, 229, 226, 66, 7, 255, 228, 132, + 160, 180, 104, 196, 27, 112, 211, 95, 7, 189, 113, 40, 235, 78, + 47, 192, 30, 173, 83, 165, 155, 126, 145, 246, 206, 50, 246, 238, + 104, 17, 107, 96, 60, 226, 96, 170, 176, 7, 89, 180, 87, 218, + 156, 129, 152, 162, 3, 237, 175, 236, 136, 152, 37, 58, 200, 114, + 226, 34, 36, 124, 193, 64, 73, 210, 19, 223, 69, 72, 128, 45, + 240, 230, 236, 13, 9, 93, 89, 86, 253, 102, 119, 248, 16, 68, + 228, 179, 250, 53, 146, 101, 64, 110, 70, 37, 215, 84, 236, 81, + 94, 159, 178, 165, 63, 117, 128, 153, 180, 233, 36, 177, 28, 92, + 66, 148, 97, 255, 33, 173, 73, 41, 179, 12, 167, 38, 253, 105, + 39, 174, 131, 188, 50, 214, 142, 181, 225, 20, 102, 30, 246, 124, + 174, 211, 255, 60, 136, 63, 207, 52, 251, 119, 138, 51, 200, 20, + 6, 223, 101, 163, 55, 251, 81, 123, 103, 152, 146, 104, 62, 243, + 150, 99, 75, 7, 80, 189, 185, 85, 1, 194, 190, 251, 109, 225, + 226, 190, 44, 153, 154, 86, 95, 170, 222, 38, 224, 55, 121, 104, + 19, 54, 40, 209, 127, 220, 237, 245, 114, 202, 115, 248, 123, 90, + 110, 154, 83, 189, 27, 121, 98, 155, 40, 110, 193, 44, 130, 59, + 200, 112, 12, 66, 241, 38, 223, 77, 169, 232, 162, 209, 39, 9, + 84, 12, 210, 230, 183, 188, 27, 115, 188, 4, 17, 33, 64, 90, + 168, 155, 139, 79, 149, 108, 83, 204, 211, 114, 189, 142, 48, 227, + 235, 36, 142, 42, 118, 1, 237, 207, 127, 2, 26, 152, 187, 78, + 152, 25, 159, 161, 202, 137, 122, 197, 74, 48, 250, 149, 171, 61, + 29, 242, 120, 196, 33, 245, 83, 71, 216, 165, 190, 99, 157, 199, + 47, 176, 237, 40, 24, 108, 41, 208, 132, 15, 219, 227, 239, 101, + 40, 115, 149, 158, 190, 227, 27, 201, 169, 131, 187, 191, 220, 106, + 176, 13, 120, 61, 86, 228, 60, 165, 197, 84, 133, 86, 166, 110, + 70, 166, 159, 110, 145, 43, 21, 232, 74, 228, 37, 2, 69, 105, + 161, 23, 234, 159, 92, 86, 32, 113, 59, 2, 87, 3, 193, 23, + 247, 33, 161, 221, 2, 122, 105, 85, 157, 179, 176, 53, 89, 206, + 133, 156, 203, 125, 12, 222, 23, 163, 19, 24, 33, 178, 248, 91, + 49, 206, 10, 92, 236, 34, 103, 30, 10, 68, 172, 145, 37, 216, + 146, 233, 25, 104, 228, 108, 193, 229, 78, 108, 68, 102, 102, 211, + 63, 196, 235, 163, 207, 46, 240, 210, 8, 29, 213, 8, 167, 215, + 201, 198, 111, 158, 110, 164, 218, 174, 174, 194, 162, 217, 10, 247, + 59, 107, 164, 205, 214, 23, 162, 185, 232, 228, 69, 221, 17, 189, + 8, 251, 210, 58, 27, 157, 167, 54, 86, 60, 166, 34, 130, 125, + 89, 32, 133, 237, 161, 173, 192, 188, 78, 149, 238, 206, 155, 31, + 38, 160, 174, 234, 181, 192, 48, 167, 210, 252, 241, 1, 83, 247, + 82, 222, 228, 154, 113, 209, 5, 5, 159, 141, 82, 90, 50, 128, + 33, 33, 34, 251, 1, 235, 184, 65, 79, 172, 233, 32, 154, 158, + 1, 34, 197, 130, 155, 245, 13, 10, 77, 68, 172, 153, 121, 235, + 189, 76, 19, 243, 140, 52, 80, 45, 3, 13, 189, 86, 98, 253, + 36, 69, 9, 250, 212, 217, 183, 163, 203, 202, 235, 214, 184, 193, + 93, 198, 20, 248, 81, 92, 217, 220, 192, 119, 115, 31, 127, 178, + 180, 136, 128, 149, 231, 45, 49, 243, 205, 157, 17, 24, 149, 148, + 52, 5, 75, 144, 185, 220, 1, 254, 77, 195, 214, 82, 116, 65, + 239, 79, 192, 214, 154, 175, 156, 3, 38, 176, 216, 38, 76, 252, + 175, 9, 96, 169, 130, 210, 253, 123, 47, 72, 102, 80, 76, 40, + 201, 139, 102, 168, 199, 171, 127, 245, 91, 139, 160, 255, 223, 251, + 129, 223, 222, 190, 58, 110, 137, 142, 82, 22, 225, 235, 174, 99, + 212, 164, 172, 169, 119, 184, 51, 48, 19, 110, 56, 31, 46, 201, + 157, 42, 108, 91, 150, 78, 62, 159, 69, 128, 2, 219, 133, 92, + 77, 254, 25, 81, 65, 6, 217, 162, 41, 210, 117, 225, 89, 164, + 197, 201, 137, 230, 157, 178, 201, 171, 152, 91, 115, 213, 234, 218, + 130, 101, 96, 207, 158, 221, 85, 80, 97, 237, 249, 229, 25, 64, + 181, 14, 94, 236, 121, 107, 106, 159, 59, 100, 183, 15, 71, 162, + 97, 235, 220, 56, 64, 159, 158, 91, 39, 6, 250, 56, 216, 71, + 41, 19, 203, 44, 159, 121, 231, 73, 77, 177, 227, 188, 31, 159, + 88, 6, 145, 183, 97, 142, 192, 101, 32, 43, 156, 243, 27, 47, + 44, 145, 121, 171, 66, 177, 112, 173, 70, 146, 75, 125, 41, 31, + 58, 123, 96, 173, 64, 182, 128, 101, 241, 0, 72, 89, 64, 202, + 154, 1, 107, 88, 82, 200, 56, 135, 7, 214, 236, 223, 41, 177, + 104, 52, 82, 203, 62, 8, 65, 163, 128, 212, 140, 12, 46, 186, + 67, 11, 104, 243, 26, 194, 243, 71, 19, 226, 111, 71, 11, 234, + 144, 88, 110, 39, 146, 76, 212, 248, 20, 96, 167, 180, 40, 180, + 168, 55, 185, 255, 103, 18, 79, 160, 36, 167, 225, 105, 131, 164, + 234, 224, 35, 104, 90, 44, 222, 26, 197, 12, 161, 223, 206, 162, + 130, 223, 98, 4, 40, 114, 96, 224, 181, 102, 148, 81, 37, 139, + 134, 251, 97, 188, 106, 26, 182, 114, 28, 22, 209, 204, 133, 113, + 55, 46, 193, 212, 253, 56, 219, 24, 122, 237, 194, 30, 53, 98, + 165, 65, 68, 195, 1, 73, 129, 234, 88, 116, 251, 156, 160, 0, + 1, 35, 55, 250, 58, 248, 81, 215, 169, 157, 29, 39, 177, 81, + 162, 185, 210, 244, 108, 47, 230, 53, 199, 168, 150, 161, 39, 44, + 124, 19, 151, 184, 143, 162, 245, 24, 114, 42, 85, 161, 92, 130, + 152, 5, 89, 220, 24, 67, 74, 72, 176, 61, 118, 205, 222, 200, + 79, 50, 212, 97, 98, 146, 191, 239, 241, 9, 162, 230, 68, 205, + 206, 23, 2, 2, 168, 212, 97, 206, 194, 47, 5, 62, 236, 125, + 52, 163, 119, 180, 230, 114, 26, 61, 40, 7, 72, 186, 52, 134, + 20, 193, 109, 254, 142, 68, 113, 194, 213, 110, 48, 103, 168, 32, + 196, 76, 143, 84, 240, 124, 253, 44, 149, 195, 235, 115, 140, 197, + 99, 24, 195, 119, 82, 144, 217, 43, 253, 188, 5, 48, 200, 167, + 67, 135, 42, 99, 118, 26, 137, 83, 32, 62, 58, 173, 151, 7, + 120, 154, 155, 95, 204, 218, 74, 208, 127, 96, 244, 91, 181, 169, + 102, 32, 28, 145, 92, 201, 215, 29, 15, 190, 34, 246, 55, 142, + 87, 101, 165, 137, 107, 148, 216, 167, 71, 157, 217, 27, 43, 193, + 63, 179, 236, 21, 95, 84, 213, 188, 85, 150, 66, 30, 73, 12, + 61, 34, 46, 9, 33, 91, 217, 70, 73, 87, 67, 166, 17, 220, + 47, 250, 207, 206, 47, 255, 72, 47, 17, 67, 188, 12, 137, 189, + 38, 211, 139, 255, 92, 185, 148, 173, 192, 24, 212, 204, 3, 175, + 42, 249, 144, 160, 224, 227, 30, 216, 154, 177, 115, 209, 164, 108, + 100, 204, 175, 123, 82, 54, 77, 54, 242, 175, 178, 238, 128, 67, + 33, 38, 235, 208, 242, 83, 170, 137, 43, 224, 65, 244, 242, 223, + 49, 164, 154, 138, 252, 34, 123, 5, 234, 15, 100, 57, 49, 238, + 184, 249, 218, 145, 76, 66, 254, 202, 255, 217, 231, 212, 103, 10, + 22, 3, 199, 229, 34, 70, 93, 188, 151, 84, 123, 57, 15, 135, + 131, 55, 2, 138, 23, 56, 173, 153, 203, 64, 157, 33, 129, 198, + 192, 240, 253, 125, 227, 61, 156, 10, 54, 186, 40, 128, 192, 7, + 197, 90, 227, 135, 19, 74, 25, 175, 183, 250, 253, 111, 232, 68, + 9, 167, 63, 51, 112, 177, 141, 98, 35, 58, 134, 153, 185, 221, + 226, 49, 151, 234, 141, 179, 253, 42, 161, 95, 144, 91, 19, 213, + 9, 52, 65, 154, 215, 5, 212, 65, 101, 44, 238, 119, 94, 150, + 48, 63, 61, 65, 82, 35, 38, 100, 2, 177, 202, 253, 157, 133, + 255, 117, 19, 176, 166, 210, 20, 59, 15, 130, 205, 46, 96, 55, + 170, 206, 203, 159, 153, 205, 65, 238, 220, 110, 109, 49, 113, 242, + 163, 151, 130, 169, 144, 15, 204, 17, 106, 35, 243, 202, 207, 143, + 29, 185, 181, 66, 67, 175, 13, 90, 155, 229, 134, 30, 54, 56, + 249, 93, 7, 199, 180, 185, 102, 148, 193, 251, 24, 204, 54, 203, + 129, 56, 241, 68, 182, 140, 253, 176, 216, 207, 219, 130, 126, 76, + 189, 170, 124, 195, 200, 81, 165, 91, 83, 4, 59, 15, 153, 149, + 236, 8, 240, 198, 193, 47, 127, 0, 157, 111, 64, 253, 216, 13, + 6, 254, 85, 117, 52, 2, 229, 120, 227, 229, 145, 141, 131, 143, + 71, 201, 161, 115, 22, 29, 13, 163, 149, 55, 91, 140, 170, 159, + 62, 241, 72, 226, 87, 34, 167, 175, 5, 135, 212, 208, 5, 203, + 152, 252, 32, 48, 95, 111, 81, 129, 40, 55, 166, 4, 38, 252, + 134, 80, 5, 49, 182, 125, 106, 133, 139, 206, 109, 89, 175, 228, + 194, 52, 118, 93, 57, 35, 131, 53, 42, 146, 214, 29, 13, 103, + 148, 135, 204, 131, 212, 114, 202, 183, 195, 90, 166, 168, 32, 58, + 53, 64, 132, 41, 229, 54, 86, 235, 125, 135, 87, 222, 47, 236, + 216, 142, 232, 37, 253, 231, 116, 184, 168, 120, 162, 111, 131, 74, + 150, 99, 139, 98, 73, 161, 37, 183, 113, 221, 29, 171, 160, 79, + 121, 9, 30, 77, 108, 195, 231, 205, 156, 124, 117, 72, 50, 53, + 203, 123, 132, 198, 249, 112, 170, 131, 118, 32, 173, 175, 31, 179, + 216, 91, 211, 114, 13, 175, 124, 43, 35, 29, 97, 65, 192, 47, + 209, 244, 241, 179, 47, 178, 209, 134, 102, 170, 240, 69, 44, 188, + 105, 41, 234, 81, 211, 28, 236, 30, 125, 135, 34, 9, 46, 30, + 108, 239, 164, 209, 137, 175, 71, 67, 84, 49, 221, 29, 255, 199, + 118, 221, 78, 6, 42, 16, 208, 196, 43, 82, 13, 36, 86, 213, + 141, 211, 25, 76, 57, 177, 107, 199, 24, 35, 253, 55, 27, 176, + 17, 197, 164, 36, 105, 128, 50, 220, 119, 183, 129, 239, 6, 9, + 204, 230, 96, 243, 176, 211, 201, 121, 52, 68, 104, 182, 55, 60, + 2, 131, 153, 76, 135, 191, 116, 93, 161, 254, 36, 90, 193, 193, + 22, 97, 228, 31, 43, 87, 77, 214, 152, 238, 183, 103, 177, 93, + 42, 255, 10, 102, 70, 126, 177, 3, 138, 139, 234, 75, 84, 57, + 108, 95, 158, 118, 84, 60, 36, 104, 52, 29, 91, 10, 129, 252, + 90, 239, 61, 214, 139, 248, 30, 32, 91, 72, 43, 3, 251, 20, + 4, 179, 193, 56, 217, 177, 103, 97, 65, 222, 97, 249, 169, 117, + 248, 185, 4, 209, 236, 5, 64, 31, 250, 71, 27, 57, 236, 172, + 214, 143, 109, 241, 38, 244, 42, 223, 173, 224, 176, 243, 28, 197, + 217, 183, 172, 192, 182, 250, 54, 41, 51, 148, 66, 110, 84, 183, + 225, 172, 31, 103, 255, 212, 214, 158, 37, 114, 181, 192, 97, 197, + 69, 40, 42, 147, 238, 5, 31, 44, 36, 78, 249, 204, 234, 18, + 47, 152, 221, 210, 77, 103, 222, 200, 102, 207, 136, 132, 171, 208, + 137, 23, 247, 16, 212, 184, 207, 177, 119, 25, 190, 240, 57, 243, + 86, 124, 49, 5, 177, 163, 152, 14, 134, 141, 52, 95, 173, 242, + 41, 215, 99, 114, 75, 201, 169, 252, 246, 202, 72, 142, 203, 7, + 127, 94, 87, 180, 150, 211, 50, 95, 135, 88, 3, 255, 138, 194, + 10, 13, 135, 186, 231, 180, 207, 9, 151, 43, 143, 234, 207, 199, + 238, 250, 235, 115, 238, 10, 173, 79, 171, 77, 109, 216, 68, 153, + 234, 108, 62, 248, 112, 10, 226, 127, 50, 165, 234, 22, 192, 186, + 31, 42, 236, 197, 138, 161, 193, 243, 73, 33, 85, 130, 175, 211, + 161, 50, 102, 135, 228, 162, 245, 79, 198, 236, 252, 232, 43, 182, + 45, 174, 59, 19, 174, 159, 232, 182, 97, 121, 51, 131, 250, 227, + 131, 17, 236, 101, 88, 163, 165, 165, 199, 121, 45, 140, 73, 144, + 250, 9, 172, 160, 46, 77, 165, 43, 50, 220, 231, 112, 206, 172, + 114, 214, 198, 243, 225, 10, 107, 42, 80, 7, 101, 195, 243, 254, + 83, 85, 210, 189, 18, 178, 167, 145, 146, 236, 10, 202, 232, 51, + 173, 135, 130, 82, 170, 69, 172, 169, 6, 12, 34, 102, 111, 243, + 120, 145, 24, 32, 159, 210, 228, 218, 226, 198, 154, 38, 130, 183, + 246, 66, 14, 81, 71, 233, 16, 96, 164, 132, 72, 244, 132, 211, + 72, 2, 55, 44, 9, 37, 48, 2, 233, 161, 39, 201, 221, 88, + 136, 73, 99, 141, 116, 235, 70, 4, 1, 23, 115, 87, 91, 10, + 119, 214, 185, 43, 208, 149, 140, 181, 20, 192, 85, 23, 220, 191, + 67, 113, 228, 43, 247, 164, 216, 245, 242, 39, 84, 187, 159, 253, + 218, 54, 2, 74, 179, 224, 141, 135, 91, 103, 179, 87, 25, 241, + 37, 158, 243, 243, 151, 214, 34, 162, 23, 159, 126, 50, 204, 220, + 14, 153, 18, 37, 2, 164, 82, 137, 21, 237, 18, 82, 57, 0, + 250, 236, 151, 231, 12, 112, 226, 253, 74, 49, 34, 140, 0, 101, + 83, 243, 140, 70, 68, 196, 225, 102, 147, 49, 101, 226, 39, 83, + 176, 127, 150, 205, 120, 252, 16, 176, 195, 112, 28, 17, 100, 50, + 138, 68, 241, 171, 235, 153, 232, 34, 182, 137, 25, 171, 150, 98, + 152, 97, 17, 112, 163, 84, 161, 241, 191, 239, 243, 218, 204, 217, + 89, 55, 6, 30, 187, 141, 132, 29, 230, 241, 179, 35, 14, 90, + 5, 234, 99, 120, 124, 204, 52, 65, 118, 103, 66, 163, 37, 222, + 49, 150, 114, 58, 8, 112, 51, 45, 175, 150, 173, 150, 177, 213, + 241, 49, 81, 62, 186, 52, 235, 33, 15, 212, 49, 31, 123, 181, + 252, 209, 30, 157, 114, 232, 21, 38, 10, 40, 125, 83, 135, 204, + 118, 253, 171, 220, 133, 37, 119, 191, 111, 223, 19, 67, 69, 234, + 186, 19, 235, 251, 210, 240, 12, 26, 187, 67, 123, 54, 95, 203, + 58, 134, 139, 138, 209, 67, 88, 114, 17, 137, 133, 98, 233, 216, + 212, 155, 80, 48, 0, 215, 200, 161, 112, 222, 78, 222, 103, 180, + 157, 106, 158, 20, 230, 119, 111, 211, 2, 115, 224, 232, 53, 134, + 84, 118, 122, 138, 27, 202, 169, 219, 164, 54, 97, 76, 237, 226, + 229, 96, 5, 87, 216, 193, 30, 65, 107, 136, 247, 126, 63, 168, + 53, 230, 16, 21, 72, 140, 217, 160, 162, 58, 160, 246, 114, 201, + 23, 233, 197, 43, 194, 230, 18, 144, 149, 221, 112, 210, 136, 64, + 204, 211, 190, 224, 210, 220, 169, 48, 7, 113, 225, 176, 196, 230, + 252, 76, 251, 120, 178, 137, 194, 250, 98, 73, 204, 19, 168, 157, + 200, 17, 132, 184, 73, 187, 228, 79, 202, 67, 192, 205, 10, 254, + 190, 157, 144, 24, 214, 56, 53, 164, 241, 230, 23, 239, 224, 185, + 90, 109, 224, 229, 85, 237, 10, 180, 84, 97, 137, 48, 71, 32, + 88, 71, 233, 81, 46, 23, 17, 245, 119, 185, 222, 64, 181, 98, + 172, 5, 243, 82, 183, 51, 245, 135, 83, 46, 61, 108, 238, 30, + 243, 58, 211, 11, 30, 252, 126, 35, 82, 170, 99, 27, 134, 136, + 180, 158, 167, 122, 255, 208, 180, 62, 239, 112, 101, 180, 144, 19, + 61, 9, 129, 145, 94, 181, 236, 240, 77, 145, 221, 168, 140, 155, + 67, 181, 217, 58, 255, 249, 219, 168, 214, 208, 166, 201, 149, 78, + 140, 175, 197, 43, 186, 156, 80, 138, 87, 254, 144, 68, 88, 72, + 59, 200, 21, 40, 9, 3, 185, 101, 241, 142, 126, 254, 67, 28, + 151, 234, 51, 18, 217, 18, 110, 216, 154, 91, 23, 58, 14, 83, + 58, 101, 49, 162, 151, 177, 250, 249, 21, 97, 243, 230, 32, 62, + 72, 112, 24, 145, 220, 233, 121, 146, 118, 89, 111, 233, 79, 184, + 187, 25, 179, 183, 84, 108, 186, 40, 227, 36, 17, 78, 5, 247, + 50, 84, 148, 99, 247, 133, 74, 5, 76, 160, 103, 51, 83, 244, + 98, 12, 204, 19, 103, 147, 169, 144, 48, 26, 40, 208, 220, 97, + 63, 55, 138, 81, 177, 78, 171, 30, 159, 166, 141, 63, 155, 22, + 96, 152, 212, 225, 241, 123, 70, 207, 205, 163, 123, 17, 161, 45, + 5, 61, 69, 13, 180, 177, 230, 237, 227, 15, 188, 194, 232, 233, + 7, 58, 63, 117, 95, 219, 224, 167, 17, 77, 105, 209, 250, 199, + 120, 172, 154, 21, 136, 41, 70, 140, 94, 85, 183, 101, 18, 225, + 233, 123, 253, 28, 23, 147, 69, 53, 229, 81, 206, 222, 32, 192, + 1, 181, 210, 170, 46, 127, 110, 28, 99, 99, 220, 239, 191, 241, + 136, 181, 124, 131, 68, 164, 179, 52, 204, 195, 12, 164, 229, 177, + 29, 88, 231, 153, 196, 40, 4, 4, 204, 9, 198, 121, 141, 151, + 175, 147, 107, 253, 63, 175, 212, 76, 212, 245, 199, 228, 47, 200, + 26, 166, 66, 202, 185, 182, 18, 2, 34, 117, 12, 226, 21, 38, + 21, 69, 115, 160, 235, 135, 103, 120, 221, 214, 150, 111, 198, 55, + 172, 96, 229, 51, 204, 44, 248, 131, 10, 29, 148, 236, 149, 38, + 202, 128, 136, 15, 95, 102, 101, 152, 66, 167, 226, 208, 157, 151, + 225, 83, 71, 230, 186, 69, 120, 57, 86, 230, 239, 6, 243, 78, + 132, 38, 62, 22, 111, 191, 74, 234, 158, 156, 37, 96, 48, 121, + 10, 201, 45, 40, 134, 53, 213, 3, 80, 13, 139, 88, 147, 63, + 144, 152, 241, 24, 106, 23, 128, 103, 176, 245, 53, 243, 200, 68, + 139, 163, 12, 3, 136, 215, 45, 63, 10, 252, 90, 0, 151, 196, + 151, 122, 171, 188, 71, 114, 140, 179, 30, 1, 157, 39, 164, 39, + 143, 185, 184, 225, 45, 37, 237, 130, 134, 180, 175, 174, 6, 167, + 100, 191, 142, 36, 220, 76, 24, 14, 5, 73, 219, 186, 82, 110, + 24, 55, 183, 232, 3, 29, 42, 248, 188, 234, 99, 37, 40, 105, + 108, 140, 251, 209, 208, 87, 52, 243, 26, 121, 175, 214, 238, 206, + 79, 227, 43, 226, 21, 87, 230, 252, 139, 31, 145, 219, 36, 194, + 102, 108, 220, 108, 32, 27, 146, 231, 4, 84, 96, 121, 94, 111, + 230, 25, 77, 3, 1, 105, 47, 236, 246, 127, 97, 194, 194, 185, + 242, 23, 121, 115, 60, 49, 78, 107, 113, 102, 178, 116, 154, 188, + 6, 240, 7, 162, 55, 176, 20, 70, 213, 141, 2, 180, 129, 145, + 169, 149, 223, 91, 115, 50, 69, 254, 16, 207, 158, 244, 136, 159, + 106, 253, 162, 245, 134, 163, 180, 46, 37, 3, 178, 138, 217, 117, + 253, 208, 226, 131, 225, 234, 58, 77, 221, 98, 133, 75, 181, 10, + 19, 220, 135, 79, 85, 110, 208, 8, 67, 188, 102, 214, 51, 172, + 204, 245, 81, 135, 192, 112, 88, 186, 207, 127, 188, 238, 66, 237, + 218, 19, 126, 51, 209, 179, 189, 92, 50, 156, 53, 35, 150, 74, + 68, 255, 51, 162, 37, 124, 16, 99, 245, 170, 144, 24, 55, 73, + 69, 181, 72, 119, 221, 114, 172, 185, 11, 148, 26, 32, 79, 122, + 203, 50, 202, 110, 79, 74, 219, 10, 104, 157, 29, 46, 218, 149, + 16, 231, 76, 187, 103, 160, 80, 182, 62, 243, 221, 48, 115, 244, + 68, 187, 20, 119, 29, 6, 191, 85, 125, 126, 62, 59, 238, 65, + 230, 138, 177, 197, 240, 208, 199, 35, 194, 19, 30, 132, 254, 194, + 26, 207, 5, 126, 205, 186, 239, 91, 131, 160, 7, 23, 21, 15, + 112, 128, 205, 134, 222, 70, 175, 74, 144, 210, 21, 241, 96, 237, + 140, 115, 9, 206, 62, 28, 66, 195, 44, 233, 185, 206, 102, 117, + 246, 175, 95, 225, 233, 226, 120, 248, 24, 67, 102, 223, 13, 33, + 203, 18, 190, 55, 96, 152, 82, 155, 127, 230, 158, 149, 194, 15, + 143, 247, 112, 81, 219, 16, 175, 55, 55, 10, 245, 16, 117, 211, + 246, 220, 62, 14, 230, 88, 74, 253, 80, 167, 7, 19, 174, 27, + 221, 128, 89, 161, 147, 71, 12, 42, 218, 39, 159, 96, 20, 53, + 122, 64, 225, 30, 147, 154, 38, 110, 92, 131, 160, 231, 137, 127, + 133, 91, 22, 232, 39, 153, 248, 203, 139, 51, 216, 214, 95, 211, + 196, 29, 168, 237, 48, 24, 44, 2, 73, 133, 85, 25, 123, 14, + 58, 199, 105, 184, 123, 71, 79, 35, 173, 184, 211, 19, 108, 219, + 81, 38, 47, 42, 11, 78, 209, 11, 59, 208, 164, 241, 138, 110, + 239, 169, 184, 206, 227, 129, 154, 195, 142, 109, 166, 240, 19, 98, + 52, 49, 213, 14, 145, 193, 248, 6, 130, 148, 251, 197, 140, 154, + 81, 210, 122, 129, 204, 234, 201, 180, 200, 181, 73, 122, 146, 41, + 7, 229, 50, 83, 100, 58, 99, 26, 71, 141, 92, 29, 40, 207, + 204, 248, 139, 150, 20, 50, 0, 160, 1, 188, 193, 88, 9, 55, + 220, 90, 150, 52, 154, 165, 250, 169, 105, 240, 47, 28, 117, 110, + 71, 134, 154, 100, 230, 58, 5, 144, 97, 231, 118, 82, 228, 97, + 209, 91, 5, 185, 122, 106, 238, 37, 232, 134, 2, 197, 189, 219, + 52, 109, 1, 178, 49, 254, 109, 178, 183, 188, 151, 240, 114, 4, + 112, 40, 205, 190, 136, 203, 36, 214, 26, 117, 162, 179, 64, 245, + 187, 107, 253, 231, 224, 96, 205, 39, 159, 175, 135, 255, 22, 71, + 165, 195, 218, 5, 149, 163, 231, 7, 32, 93, 158, 156, 78, 221, + 126, 102, 98, 134, 94, 9, 25, 165, 150, 138, 224, 98, 217, 172, + 208, 59, 67, 212, 84, 36, 59, 45, 25, 42, 62, 217, 236, 65, + 174, 123, 117, 107, 205, 106, 162, 51, 255, 162, 115, 242, 102, 216, + 236, 26, 201, 227, 221, 244, 158, 4, 223, 211, 159, 126, 230, 183, + 108, 6, 130, 8, 181, 255, 162, 118, 148, 175, 33, 175, 88, 231, + 53, 5, 181, 23, 238, 184, 81, 31, 152, 10, 123, 245, 157, 85, + 137, 105, 253, 28, 44, 11, 134, 207, 248, 80, 146, 85, 121, 89, + 19, 205, 61, 140, 224, 8, 121, 139, 195, 92, 127, 90, 47, 77, + 125, 99, 171, 187, 146, 110, 106, 122, 242, 191, 170, 26, 218, 238, + 10, 11, 82, 203, 136, 170, 10, 75, 211, 164, 240, 183, 209, 71, + 213, 254, 91, 204, 233, 9, 79, 223, 226, 228, 33, 204, 204, 5, + 130, 105, 202, 19, 121, 58, 81, 204, 34, 62, 253, 25, 60, 81, + 164, 16, 130, 45, 162, 170, 139, 137, 224, 139, 156, 179, 173, 203, + 24, 37, 176, 116, 244, 35, 157, 12, 30, 180, 195, 212, 14, 147, + 132, 29, 74, 208, 78, 79, 198, 205, 15, 41, 197, 34, 239, 67, + 200, 22, 125, 168, 118, 165, 141, 53, 222, 72, 45, 247, 124, 8, + 53, 55, 87, 158, 65, 231, 109, 104, 40, 236, 135, 121, 84, 124, + 68, 158, 177, 183, 85, 236, 32, 97, 42, 118, 56, 253, 203, 80, + 79, 61, 241, 80, 204, 3, 162, 22, 206, 159, 86, 192, 200, 79, + 25, 223, 62, 92, 152, 124, 41, 182, 54, 6, 194, 221, 107, 5, + 86, 185, 79, 73, 225, 3, 94, 13, 42, 159, 46, 45, 18, 59, + 0, 145, 112, 132, 7, 147, 141, 44, 153, 74, 155, 127, 49, 189, + 235, 255, 165, 155, 44, 221, 119, 19, 139, 68, 69, 109, 99, 64, + 30, 114, 211, 77, 65, 208, 32, 68, 238, 121, 26, 85, 114, 168, + 127, 137, 170, 62, 70, 94, 232, 108, 41, 123, 16, 217, 68, 26, + 53, 39, 233, 104, 232, 150, 63, 77, 209, 202, 198, 117, 174, 126, + 234, 121, 41, 107, 191, 25, 154, 110, 218, 26, 241, 172, 110, 103, + 153, 15, 94, 109, 91, 33, 159, 135, 158, 133, 43, 18, 174, 86, + 110, 21, 242, 19, 105, 147, 80, 132, 117, 158, 219, 205, 34, 117, + 205, 43, 234, 38, 238, 142, 193, 210, 218, 204, 148, 249, 33, 160, + 176, 98, 60, 149, 201, 93, 57, 11, 206, 128, 252, 31, 156, 26, + 17, 79, 102, 244, 176, 85, 249, 135, 239, 202, 169, 117, 151, 118, + 103, 120, 180, 16, 40, 216, 14, 55, 235, 49, 160, 193, 120, 64, + 235, 215, 112, 109, 53, 132, 136, 145, 228, 51, 189, 26, 172, 249, + 107, 194, 188, 146, 20, 223, 175, 8, 132, 123, 105, 112, 130, 82, + 150, 52, 49, 28, 116, 90, 242, 225, 70, 241, 78, 188, 95, 158, + 151, 197, 153, 121, 42, 214, 105, 233, 41, 106, 213, 70, 94, 168, + 51, 76, 151, 79, 195, 124, 183, 104, 212, 125, 64, 18, 232, 194, + 58, 252, 128, 195, 240, 216, 255, 50, 238, 105, 135, 71, 79, 123, + 175, 169, 38, 225, 102, 170, 213, 7, 223, 238, 179, 90, 208, 85, + 249, 95, 45, 188, 72, 47, 90, 154, 56, 161, 196, 6, 117, 176, + 35, 121, 114, 98, 142, 53, 42, 249, 89, 9, 171, 130, 134, 40, + 24, 23, 165, 66, 201, 38, 38, 95, 153, 150, 22, 202, 153, 221, + 63, 24, 137, 114, 169, 143, 97, 168, 239, 74, 254, 160, 189, 77, + 171, 169, 188, 6, 222, 105, 31, 106, 123, 176, 0, 123, 92, 9, + 137, 24, 110, 79, 153, 222, 96, 224, 174, 135, 147, 12, 129, 166, + 66, 30, 78, 56, 5, 180, 71, 7, 185, 41, 156, 90, 191, 6, + 72, 94, 151, 59, 174, 16, 131, 155, 97, 231, 194, 52, 146, 119, + 91, 114, 9, 164, 94, 205, 195, 227, 92, 33, 197, 158, 154, 213, + 9, 13, 59, 197, 174, 82, 243, 82, 182, 213, 92, 231, 50, 102, + 191, 188, 234, 103, 144, 89, 161, 64, 161, 210, 101, 170, 118, 70, + 20, 190, 124, 149, 52, 160, 110, 111, 70, 187, 229, 233, 134, 139, + 242, 161, 149, 69, 17, 8, 199, 8, 228, 83, 193, 100, 243, 251, + 74, 214, 241, 198, 14, 30, 185, 92, 207, 95, 127, 204, 42, 178, + 73, 24, 183, 184, 139, 159, 218, 154, 139, 197, 72, 86, 1, 49, + 172, 45, 94, 173, 156, 240, 149, 210, 212, 130, 204, 255, 251, 4, + 4, 95, 202, 79, 241, 75, 191, 21, 183, 251, 21, 105, 83, 33, + 56, 43, 116, 57, 119, 54, 71, 118, 24, 139, 123, 152, 2, 3, + 255, 176, 195, 27, 152, 43, 67, 191, 162, 90, 214, 92, 141, 94, + 50, 18, 255, 134, 167, 19, 35, 102, 49, 165, 5, 83, 218, 50, + 197, 40, 246, 139, 30, 214, 64, 59, 250, 163, 243, 152, 198, 85, + 108, 110, 145, 103, 16, 229, 123, 185, 18, 226, 246, 180, 93, 210, + 87, 240, 81, 60, 157, 253, 191, 9, 132, 165, 247, 225, 45, 251, + 61, 249, 113, 221, 173, 193, 83, 11, 114, 102, 56, 9, 150, 62, + 17, 228, 159, 217, 155, 250, 239, 221, 225, 221, 26, 174, 143, 97, + 114, 158, 144, 38, 165, 137, 28, 35, 184, 146, 23, 98, 34, 54, + 126, 120, 185, 166, 241, 145, 9, 197, 186, 113, 20, 119, 126, 58, + 255, 138, 183, 86, 79, 46, 166, 221, 197, 149, 239, 236, 117, 228, + 173, 182, 218, 19, 120, 172, 108, 61, 239, 254, 128, 44, 213, 13, + 6, 200, 190, 138, 185, 32, 211, 238, 226, 131, 84, 219, 254, 24, + 57, 49, 167, 94, 90, 62, 58, 7, 174, 230, 59, 160, 96, 143, + 160, 8, 108, 225, 208, 240, 112, 119, 168, 28, 198, 7, 127, 4, + 1, 226, 42, 171, 194, 35, 231, 184, 96, 221, 135, 68, 204, 175, + 74, 93, 250, 216, 158, 230, 52, 51, 126, 118, 73, 97, 156, 80, + 20, 28, 130, 247, 204, 206, 227, 41, 232, 52, 205, 15, 222, 7, + 246, 200, 81, 182, 71, 12, 225, 88, 64, 118, 179, 130, 222, 82, + 215, 172, 144, 252, 106, 244, 207, 151, 227, 145, 22, 94, 117, 225, + 153, 224, 5, 216, 152, 174, 56, 206, 95, 32, 172, 206, 99, 54, + 209, 38, 55, 123, 54, 123, 34, 127, 98, 84, 249, 244, 33, 208, + 226, 56, 222, 180, 172, 246, 155, 118, 130, 45, 110, 130, 82, 48, + 84, 132, 250, 189, 253, 142, 45, 161, 217, 229, 221, 83, 154, 86, + 134, 12, 161, 57, 5, 16, 89, 17, 219, 86, 235, 212, 152, 93, + 225, 60, 235, 106, 28, 97, 58, 222, 249, 255, 194, 17, 23, 39, + 77, 209, 86, 137, 152, 83, 45, 112, 160, 130, 150, 36, 56, 83, + 48, 45, 181, 128, 16, 220, 36, 35, 166, 228, 71, 229, 5, 234, + 229, 3, 96, 14, 173, 6, 152, 57, 193, 254, 101, 135, 15, 100, + 121, 191, 161, 67, 146, 105, 148, 169, 129, 178, 234, 45, 91, 175, + 48, 227, 183, 10, 50, 25, 101, 225, 135, 67, 64, 2, 123, 131, + 81, 72, 220, 128, 195, 26, 7, 251, 131, 239, 150, 99, 169, 57, + 237, 29, 113, 113, 243, 226, 136, 254, 139, 54, 180, 69, 251, 127, + 184, 187, 9, 163, 191, 91, 42, 214, 0, 19, 102, 145, 46, 90, + 112, 30, 107, 137, 183, 219, 100, 233, 194, 90, 223, 53, 236, 92, + 63, 179, 218, 118, 47, 212, 94, 124, 41, 226, 115, 160, 249, 115, + 133, 131, 70, 139, 51, 211, 183, 82, 142, 102, 132, 133, 189, 0, + 211, 103, 63, 121, 204, 156, 235, 142, 81, 50, 84, 142, 80, 51, + 173, 231, 156, 215, 172, 7, 25, 181, 126, 174, 108, 98, 98, 244, + 65, 230, 7, 241, 4, 187, 4, 179, 218, 35, 17, 50, 142, 98, + 226, 53, 7, 61, 41, 170, 12, 156, 201, 60, 191, 72, 210, 157, + 16, 38, 191, 40, 122, 68, 150, 114, 126, 172, 220, 32, 133, 242, + 88, 131, 213, 113, 33, 166, 131, 165, 228, 235, 76, 116, 94, 4, + 224, 136, 133, 6, 250, 7, 179, 182, 67, 232, 111, 136, 230, 49, + 143, 117, 236, 36, 115, 218, 224, 188, 104, 88, 87, 150, 193, 91, + 215, 110, 24, 3, 85, 103, 35, 193, 217, 81, 27, 28, 150, 252, + 150, 148, 74, 30, 223, 136, 250, 151, 41, 171, 197, 221, 17, 13, + 32, 254, 71, 150, 96, 213, 79, 254, 122, 92, 234, 181, 173, 160, + 223, 206, 104, 28, 64, 146, 243, 125, 79, 149, 185, 92, 158, 93, + 39, 166, 143, 85, 115, 228, 162, 196, 154, 132, 221, 92, 114, 27, + 244, 159, 81, 44, 231, 243, 39, 82, 228, 148, 125, 153, 24, 153, + 230, 5, 235, 242, 165, 36, 215, 79, 194, 125, 140, 106, 135, 38, + 119, 46, 174, 229, 141, 230, 197, 116, 53, 82, 68, 116, 193, 139, + 50, 43, 203, 255, 238, 141, 22, 39, 0, 188, 154, 16, 89, 145, + 147, 130, 133, 52, 80, 45, 3, 121, 247, 174, 30, 187, 140, 210, + 41, 175, 127, 231, 33, 116, 153, 153, 166, 180, 237, 111, 4, 196, + 217, 96, 239, 141, 122, 23, 135, 245, 173, 25, 61, 10, 59, 73, + 105, 168, 120, 44, 108, 20, 7, 202, 42, 82, 247, 10, 85, 3, + 121, 254, 119, 168, 9, 14, 229, 99, 51, 251, 143, 230, 167, 62, + 254, 144, 52, 229, 98, 41, 4, 229, 162, 157, 62, 170, 179, 65, + 206, 58, 174, 80, 153, 18, 9, 225, 73, 63, 178, 88, 110, 112, + 103, 65, 212, 18, 21, 124, 235, 67, 153, 172, 216, 188, 17, 45, + 44, 85, 25, 125, 145, 84, 212, 139, 241, 102, 75, 232, 248, 147, + 35, 5, 211, 181, 160, 169, 84, 90, 207, 46, 231, 41, 162, 182, + 142, 74, 106, 26, 69, 53, 118, 114, 92, 186, 15, 161, 205, 51, + 2, 201, 99, 142, 138, 169, 189, 206, 120, 113, 218, 245, 70, 54, + 44, 215, 147, 154, 204, 48, 132, 251, 213, 124, 20, 213, 158, 107, + 212, 52, 142, 108, 139, 37, 121, 215, 172, 148, 44, 49, 205, 46, + 201, 193, 246, 21, 52, 155, 41, 172, 74, 218, 208, 49, 64, 255, + 224, 36, 82, 127, 225, 213, 151, 163, 80, 231, 150, 148, 135, 176, + 128, 88, 122, 218, 232, 35, 126, 71, 191, 76, 20, 48, 214, 177, + 199, 128, 52, 63, 125, 213, 26, 172, 148, 9, 152, 188, 239, 163, + 9, 62, 15, 148, 174, 187, 249, 55, 249, 147, 190, 117, 5, 255, + 163, 154, 159, 156, 36, 225, 1, 35, 211, 16, 117, 28, 36, 236, + 28, 138, 16, 182, 103, 82, 206, 90, 71, 114, 0, 220, 238, 134, + 31, 172, 140, 55, 79, 33, 112, 125, 250, 100, 246, 18, 39, 80, + 198, 186, 28, 244, 150, 187, 199, 218, 127, 95, 90, 23, 160, 69, + 69, 21, 135, 240, 41, 216, 165, 41, 34, 43, 178, 32, 3, 23, + 40, 99, 181, 255, 217, 36, 8, 111, 1, 165, 187, 130, 213, 164, + 87, 11, 225, 44, 28, 18, 43, 49, 151, 115, 240, 111, 112, 74, + 168, 190, 141, 53, 255, 91, 108, 72, 157, 255, 78, 43, 172, 242, + 229, 222, 203, 198, 58, 253, 147, 28, 70, 168, 70, 108, 165, 34, + 153, 163, 46, 217, 136, 112, 74, 63, 238, 160, 96, 191, 62, 153, + 113, 244, 74, 42, 153, 165, 105, 186, 15, 194, 7, 149, 27, 131, + 47, 151, 20, 38, 225, 72, 18, 203, 74, 172, 99, 44, 32, 224, + 201, 248, 14, 151, 184, 155, 208, 28, 175, 60, 48, 68, 64, 4, + 186, 117, 248, 56, 129, 87, 7, 249, 88, 64, 25, 255, 248, 98, + 114, 119, 252, 168, 1, 130, 107, 253, 44, 134, 99, 56, 55, 69, + 63, 3, 237, 158, 15, 41, 9, 44, 213, 98, 13, 191, 120, 223, + 84, 246, 224, 67, 224, 51, 242, 77, 183, 37, 237, 56, 106, 149, + 231, 104, 26, 153, 85, 211, 97, 60, 167, 52, 31, 138, 81, 78, + 92, 23, 136, 136, 61, 79, 25, 175, 83, 114, 37, 68, 207, 196, + 240, 70, 72, 26, 232, 14, 72, 173, 244, 20, 192, 19, 132, 244, + 199, 180, 34, 57, 169, 204, 178, 183, 33, 67, 251, 95, 100, 71, + 98, 140, 10, 110, 112, 191, 90, 54, 0, 153, 109, 168, 222, 148, + 89, 100, 208, 112, 151, 209, 168, 100, 55, 125, 110, 195, 111, 91, + 112, 176, 126, 204, 97, 30, 174, 21, 115, 210, 157, 196, 114, 239, + 172, 245, 20, 147, 54, 123, 166, 194, 84, 36, 235, 25, 108, 27, + 94, 214, 121, 77, 88, 203, 105, 39, 57, 190, 131, 181, 41, 132, + 222, 185, 99, 63, 81, 234, 212, 31, 10, 23, 82, 206, 0, 204, + 215, 60, 127, 199, 40, 214, 166, 43, 148, 149, 138, 42, 197, 174, + 93, 52, 253, 234, 212, 63, 76, 223, 4, 190, 83, 185, 49, 158, + 195, 212, 44, 31, 216, 160, 145, 147, 54, 78, 250, 84, 69, 201, + 12, 5, 14, 94, 164, 22, 62, 40, 198, 111, 88, 123, 141, 28, + 241, 128, 34, 247, 240, 53, 138, 11, 122, 88, 8, 167, 83, 250, + 166, 65, 153, 111, 112, 21, 0, 34, 236, 210, 77, 237, 19, 138, + 195, 15, 6, 13, 126, 54, 224, 30, 241, 1, 137, 207, 121, 151, + 150, 103, 213, 51, 15, 252, 239, 142, 26, 194, 191, 54, 48, 18, + 80, 249, 142, 201, 60, 110, 14, 224, 169, 4, 77, 62, 231, 127, + 131, 181, 137, 62, 43, 183, 3, 17, 87, 227, 198, 14, 207, 95, + 95, 250, 18, 75, 91, 192, 69, 161, 189, 202, 242, 105, 153, 157, + 139, 139, 84, 186, 117, 48, 238, 124, 114, 79, 87, 218, 174, 52, + 0, 4, 155, 98, 141, 6, 238, 44, 170, 196, 84, 217, 32, 96, + 100, 195, 76, 235, 89, 41, 246, 83, 202, 77, 232, 224, 164, 120, + 253, 161, 90, 225, 71, 2, 168, 189, 201, 151, 140, 89, 185, 206, + 121, 211, 172, 128, 163, 172, 180, 135, 132, 173, 0, 238, 49, 98, + 28, 154, 196, 211, 98, 132, 84, 79, 56, 191, 212, 67, 239, 153, + 149, 100, 174, 220, 31, 208, 207, 164, 175, 198, 107, 102, 55, 146, + 113, 102, 30, 251, 35, 68, 214, 212, 226, 43, 230, 178, 161, 255, + 208, 163, 48, 230, 28, 192, 10, 189, 202, 226, 86, 105, 122, 103, + 32, 231, 133, 201, 233, 103, 183, 250, 69, 83, 86, 244, 4, 33, + 182, 206, 83, 128, 108, 152, 98, 148, 33, 149, 43, 117, 117, 106, + 138, 38, 127, 90, 101, 111, 246, 7, 171, 67, 174, 80, 17, 120, + 90, 99, 147, 145, 36, 118, 28, 79, 106, 15, 233, 71, 149, 5, + 194, 228, 220, 168, 153, 211, 47, 241, 215, 65, 135, 121, 153, 59, + 159, 214, 116, 221, 142, 180, 171, 79, 216, 48, 212, 107, 223, 9, + 253, 238, 214, 81, 163, 198, 202, 230, 229, 245, 215, 60, 49, 2, + 211, 104, 115, 213, 206, 9, 17, 226, 218, 132, 188, 218, 15, 128, + 178, 190, 38, 96, 2, 123, 9, 53, 187, 121, 16, 123, 106, 30, + 186, 4, 191, 13, 151, 33, 203, 106, 103, 37, 41, 228, 228, 235, + 222, 232, 124, 52, 229, 125, 249, 68, 156, 25, 230, 214, 161, 112, + 127, 21, 90, 118, 171, 108, 169, 131, 169, 86, 230, 244, 211, 141, + 191, 101, 222, 186, 198, 194, 150, 101, 183, 175, 242, 60, 218, 226, + 56, 33, 249, 178, 40, 229, 125, 181, 152, 73, 86, 244, 109, 255, + 117, 113, 252, 207, 84, 165, 181, 154, 98, 171, 39, 116, 228, 199, + 249, 152, 191, 228, 119, 252, 87, 176, 14, 75, 68, 21, 163, 47, + 47, 32, 72, 105, 33, 113, 213, 35, 158, 218, 54, 144, 41, 185, + 171, 90, 91, 112, 185, 107, 84, 112, 251, 153, 193, 129, 203, 37, + 223, 15, 240, 139, 164, 233, 36, 132, 196, 241, 227, 60, 17, 246, + 15, 13, 138, 252, 102, 56, 47, 15, 43, 36, 146, 57, 252, 167, + 145, 138, 236, 101, 156, 82, 187, 75, 147, 85, 15, 92, 139, 38, + 254, 248, 76, 203, 119, 103, 173, 223, 49, 10, 80, 25, 105, 217, + 76, 151, 15, 55, 86, 47, 146, 151, 112, 222, 15, 239, 216, 255, + 54, 66, 84, 70, 36, 176, 178, 205, 155, 41, 103, 100, 1, 14, + 64, 235, 252, 237, 44, 139, 237, 1, 120, 104, 164, 119, 32, 200, + 168, 135, 163, 41, 81, 160, 231, 220, 65, 110, 217, 202, 96, 251, + 72, 202, 95, 12, 64, 56, 196, 172, 154, 27, 88, 134, 133, 175, + 34, 99, 223, 6, 148, 44, 10, 24, 229, 226, 5, 149, 63, 89, + 213, 17, 41, 32, 219, 236, 57, 249, 57, 88, 212, 222, 144, 159, + 127, 238, 105, 216, 5, 218, 119, 145, 56, 138, 239, 124, 63, 134, + 73, 132, 224, 176, 88, 195, 142, 70, 39, 13, 61, 43, 230, 104, + 175, 172, 162, 172, 168, 71, 118, 26, 154, 30, 59, 244, 142, 113, + 61, 220, 101, 228, 129, 9, 2, 229, 136, 60, 103, 151, 164, 106, + 214, 17, 146, 211, 64, 181, 216, 74, 0, 16, 152, 122, 32, 200, + 59, 237, 59, 155, 95, 215, 242, 115, 7, 44, 175, 125, 216, 189, + 95, 187, 16, 162, 123, 124, 36, 151, 171, 89, 28, 126, 12, 70, + 147, 233, 70, 28, 191, 146, 103, 10, 180, 155, 127, 22, 161, 39, + 69, 141, 50, 77, 33, 146, 56, 190, 86, 199, 42, 239, 232, 141, + 165, 56, 98, 74, 17, 86, 122, 12, 13, 200, 22, 220, 207, 39, + 203, 14, 236, 118, 65, 81, 57, 39, 253, 119, 173, 227, 96, 212, + 105, 201, 234, 113, 202, 208, 204, 164, 116, 227, 78, 249, 108, 77, + 131, 19, 238, 201, 177, 247, 63, 73, 204, 26, 93, 102, 253, 78, + 187, 202, 213, 3, 182, 251, 185, 191, 247, 207, 83, 167, 51, 31, + 110, 96, 175, 210, 208, 4, 29, 162, 42, 4, 87, 248, 185, 222, + 116, 231, 27, 11, 248, 122, 102, 234, 83, 167, 180, 100, 226, 4, + 137, 166, 248, 58, 161, 99, 201, 255, 56, 44, 144, 201, 112, 99, + 9, 176, 163, 60, 236, 25, 210, 131, 165, 61, 37, 230, 191, 168, + 28, 20, 212, 242, 71, 147, 10, 140, 60, 171, 57, 241, 17, 248, + 204, 60, 3, 46, 51, 174, 136, 38, 203, 74, 97, 203, 215, 150, + 164, 255, 225, 149, 188, 76, 249, 38, 189, 198, 25, 101, 249, 59, + 82, 77, 183, 125, 171, 154, 90, 5, 133, 30, 237, 84, 159, 158, + 154, 228, 143, 215, 104, 205, 78, 140, 189, 27, 17, 232, 139, 72, + 114, 251, 230, 100, 177, 195, 191, 38, 8, 46, 26, 146, 146, 96, + 229, 153, 10, 214, 239, 149, 160, 87, 60, 234, 128, 195, 102, 1, + 74, 57, 31, 199, 246, 107, 106, 5, 168, 129, 144, 129, 184, 37, + 183, 132, 215, 117, 92, 122, 236, 26, 45, 183, 70, 191, 55, 3, + 191, 201, 214, 116, 78, 112, 128, 199, 110, 122, 151, 169, 57, 135, + 66, 246, 51, 4, 162, 190, 29, 250, 22, 210, 63, 11, 212, 126, + 97, 76, 182, 82, 171, 3, 92, 27, 151, 108, 97, 245, 255, 150, + 164, 146, 28, 239, 221, 207, 36, 5, 215, 90, 125, 252, 108, 215, + 90, 91, 55, 136, 250, 58, 49, 153, 254, 114, 20, 64, 195, 103, + 40, 244, 248, 195, 224, 33, 191, 195, 200, 130, 104, 100, 237, 233, + 239, 78, 30, 175, 154, 65, 44, 26, 245, 94, 169, 0, 190, 88, + 22, 125, 131, 23, 43, 76, 146, 160, 60, 154, 69, 1, 210, 182, + 56, 109, 79, 51, 13, 216, 200, 77, 179, 1, 11, 110, 89, 86, + 37, 66, 0, 37, 216, 2, 140, 127, 108, 169, 60, 50, 168, 230, + 58, 147, 203, 207, 178, 77, 41, 127, 100, 45, 141, 252, 21, 88, + 35, 64, 115, 181, 151, 101, 182, 212, 174, 176, 210, 236, 157, 224, + 238, 104, 120, 21, 62, 71, 241, 155, 179, 19, 181, 156, 25, 247, + 149, 108, 219, 251, 210, 54, 227, 161, 197, 186, 234, 151, 195, 219, + 240, 250, 39, 185, 222, 113, 202, 99, 116, 77, 130, 42, 203, 90, + 121, 73, 184, 193, 102, 42, 127, 19, 13, 79, 219, 40, 255, 194, + 46, 111, 186, 238, 4, 8, 165, 175, 45, 215, 224, 39, 130, 95, + 79, 134, 215, 131, 0, 253, 92, 108, 130, 11, 15, 60, 58, 21, + 98, 209, 210, 148, 90, 101, 242, 204, 153, 192, 134, 82, 48, 225, + 65, 65, 204, 110, 71, 166, 43, 15, 172, 248, 106, 8, 43, 80, + 148, 1, 244, 141, 41, 23, 31, 137, 150, 104, 43, 25, 195, 121, + 234, 51, 161, 192, 176, 113, 201, 128, 23, 16, 119, 136, 109, 247, + 141, 214, 237, 236, 107, 29, 206, 122, 5, 233, 132, 88, 146, 208, + 35, 239, 75, 96, 155, 68, 204, 64, 143, 253, 77, 241, 19, 23, + 220, 245, 123, 147, 110, 154, 50, 33, 218, 138, 93, 92, 221, 208, + 212, 48, 213, 154, 200, 203, 182, 92, 188, 182, 205, 234, 215, 25, + 104, 192, 212, 129, 149, 163, 17, 219, 228, 64, 119, 49, 168, 23, + 174, 101, 46, 138, 241, 186, 46, 247, 40, 40, 91, 98, 20, 60, + 138, 47, 210, 142, 92, 118, 228, 237, 196, 29, 57, 228, 33, 28, + 9, 9, 222, 25, 195, 124, 83, 192, 196, 158, 21, 233, 44, 77, + 40, 165, 103, 228, 241, 234, 249, 86, 210, 98, 205, 26, 208, 189, + 215, 226, 172, 53, 197, 0, 59, 115, 248, 29, 81, 135, 142, 173, + 158, 16, 108, 251, 128, 208, 112, 206, 1, 65, 138, 219, 169, 249, + 55, 68, 78, 30, 145, 83, 12, 106, 180, 94, 166, 245, 61, 230, + 229, 42, 199, 135, 135, 236, 103, 106, 31, 78, 91, 74, 195, 21, + 251, 111, 185, 181, 148, 71, 183, 157, 127, 76, 20, 121, 131, 176, + 110, 117, 29, 75, 7, 249, 113, 196, 205, 205, 6, 105, 32, 65, + 52, 38, 19, 122, 238, 67, 170, 120, 203, 13, 147, 158, 210, 180, + 147, 6, 229, 138, 52, 49, 72, 246, 166, 47, 233, 116, 108, 137, + 212, 87, 140, 87, 37, 181, 8, 103, 155, 121, 77, 176, 233, 240, + 36, 85, 139, 169, 64, 163, 254, 63, 183, 244, 73, 83, 133, 44, + 26, 122, 9, 83, 73, 56, 162, 249, 92, 51, 63, 76, 60, 220, + 190, 165, 34, 3, 229, 55, 142, 143, 168, 229, 82, 109, 164, 76, + 9, 175, 116, 248, 110, 85, 41, 75, 16, 231, 21, 51, 159, 7, + 118, 9, 139, 216, 11, 131, 233, 20, 102, 151, 35, 239, 154, 85, + 95, 234, 216, 18, 98, 104, 94, 119, 158, 17, 154, 74, 2, 43, + 63, 23, 160, 197, 191, 90, 123, 144, 184, 98, 17, 196, 5, 80, + 134, 36, 9, 66, 23, 65, 24, 212, 250, 159, 141, 145, 152, 217, + 110, 242, 2, 178, 250, 79, 98, 191, 151, 42, 106, 190, 115, 47, + 151, 252, 196, 167, 197, 213, 131, 44, 250, 159, 240, 177, 232, 248, + 93, 59, 234, 120, 107, 40, 2, 115, 19, 59, 57, 120, 6, 76, + 228, 25, 47, 115, 140, 53, 38, 28, 60, 64, 245, 65, 141, 224, + 121, 179, 84, 157, 178, 175, 38, 162, 140, 45, 33, 158, 203, 173, + 230, 7, 55, 97, 233, 107, 192, 110, 15, 172, 67, 166, 45, 231, + 254, 204, 32, 3, 52, 131, 71, 107, 255, 181, 190, 21, 216, 99, + 188, 197, 79, 150, 58, 23, 254, 67, 74, 108, 238, 190, 42, 225, + 226, 218, 13, 133, 186, 33, 45, 155, 204, 75, 84, 217, 66, 61, + 223, 4, 237, 146, 23, 197, 100, 123, 149, 215, 119, 65, 169, 42, + 230, 5, 222, 203, 110, 88, 146, 7, 250, 43, 75, 52, 100, 89, + 186, 28, 244, 140, 113, 187, 150, 192, 145, 3, 33, 36, 226, 147, + 244, 129, 41, 156, 252, 3, 135, 86, 119, 124, 190, 233, 131, 37, + 98, 107, 79, 137, 78, 128, 215, 86, 128, 18, 175, 87, 64, 198, + 60, 49, 59, 90, 198, 64, 230, 211, 224, 244, 218, 1, 110, 228, + 158, 19, 15, 142, 249, 21, 139, 39, 215, 48, 89, 53, 103, 59, + 222, 25, 201, 194, 63, 86, 131, 94, 130, 240, 183, 207, 174, 74, + 49, 250, 161, 124, 34, 222, 174, 154, 154, 115, 84, 255, 253, 220, + 255, 167, 253, 11, 191, 66, 22, 193, 101, 179, 250, 110, 255, 244, + 91, 247, 12, 25, 98, 131, 170, 108, 251, 207, 154, 255, 216, 199, + 189, 69, 183, 228, 244, 26, 15, 68, 115, 213, 55, 192, 223, 234, + 31, 107, 121, 122, 231, 200, 63, 80, 113, 21, 152, 124, 160, 209, + 51, 154, 253, 211, 224, 165, 204, 215, 159, 228, 119, 246, 75, 57, + 56, 222, 137, 237, 178, 171, 229, 246, 117, 243, 229, 62, 52, 130, + 228, 54, 176, 188, 103, 228, 217, 130, 9, 234, 179, 122, 110, 20, + 99, 174, 84, 161, 133, 248, 230, 74, 110, 76, 11, 116, 16, 238, + 3, 8, 73, 91, 193, 6, 154, 18, 22, 183, 88, 123, 47, 148, + 87, 82, 25, 96, 118, 198, 31, 134, 232, 242, 230, 113, 40, 223, + 239, 242, 150, 47, 181, 129, 150, 59, 104, 99, 252, 68, 56, 76, + 252, 51, 199, 109, 212, 133, 152, 222, 40, 112, 201, 24, 152, 76, + 254, 200, 40, 101, 41, 117, 12, 143, 151, 17, 78, 100, 45, 27, + 57, 76, 51, 17, 220, 222, 131, 104, 88, 243, 98, 117, 255, 167, + 95, 20, 137, 3, 19, 65, 61, 25, 175, 219, 252, 3, 39, 178, + 128, 1, 231, 187, 176, 239, 45, 5, 158, 21, 228, 29, 236, 156, + 172, 1, 21, 133, 21, 206, 207, 214, 181, 78, 202, 190, 248, 105, + 212, 19, 46, 191, 13, 237, 15, 60, 248, 84, 28, 170, 190, 51, + 107, 205, 61, 222, 73, 28, 179, 165, 80, 206, 157, 159, 241, 250, + 230, 36, 49, 120, 82, 171, 208, 176, 70, 18, 65, 239, 212, 5, + 133, 156, 110, 193, 237, 114, 69, 188, 245, 69, 96, 237, 242, 198, + 5, 28, 40, 83, 91, 224, 126, 23, 4, 194, 11, 196, 64, 53, + 82, 190, 172, 106, 88, 88, 185, 216, 91, 184, 253, 12, 243, 122, + 40, 98, 38, 60, 48, 63, 56, 168, 185, 22, 178, 40, 182, 159, + 162, 109, 107, 167, 85, 42, 228, 232, 176, 79, 225, 21, 244, 70, + 227, 70, 96, 253, 89, 180, 232, 254, 101, 170, 203, 150, 133, 137, + 71, 67, 225, 201, 212, 99, 223, 26, 47, 57, 253, 173, 252, 238, + 155, 197, 92, 91, 104, 99, 49, 169, 123, 46, 70, 52, 159, 240, + 70, 218, 129, 142, 61, 120, 17, 98, 177, 28, 82, 124, 171, 162, + 124, 105, 122, 187, 237, 3, 19, 49, 132, 179, 211, 236, 157, 45, + 78, 206, 185, 207, 83, 252, 181, 147, 9, 82, 10, 72, 171, 250, + 17, 16, 18, 236, 174, 184, 110, 57, 100, 80, 94, 141, 31, 210, + 74, 192, 183, 251, 119, 204, 95, 245, 51, 189, 49, 0, 197, 56, + 54, 140, 92, 92, 43, 124, 63, 34, 183, 175, 182, 248, 109, 55, + 113, 162, 167, 193, 45, 28, 177, 148, 130, 76, 214, 47, 76, 215, + 49, 108, 199, 17, 182, 149, 62, 208, 98, 140, 77, 166, 253, 187, + 126, 31, 41, 47, 14, 75, 58, 126, 27, 122, 248, 154, 170, 168, + 177, 184, 194, 232, 194, 91, 247, 194, 4, 77, 93, 63, 207, 2, + 243, 96, 236, 107, 163, 26, 106, 86, 122, 133, 113, 218, 118, 246, + 228, 0, 62, 146, 39, 110, 250, 78, 72, 149, 185, 243, 25, 16, + 212, 10, 221, 138, 59, 17, 67, 189, 223, 28, 56, 41, 206, 4, + 137, 6, 25, 45, 141, 52, 93, 209, 251, 228, 18, 132, 180, 203, + 18, 107, 235, 24, 240, 224, 150, 208, 230, 20, 230, 158, 112, 160, + 14, 231, 73, 82, 148, 54, 80, 33, 52, 163, 177, 129, 180, 122, + 148, 160, 164, 209, 237, 18, 58, 70, 34, 122, 242, 243, 157, 8, + 243, 43, 210, 254, 173, 247, 103, 137, 136, 118, 74, 50, 68, 221, + 85, 215, 91, 67, 134, 76, 87, 87, 227, 184, 23, 68, 95, 166, + 63, 245, 97, 119, 206, 129, 22, 167, 180, 75, 199, 108, 164, 158, + 129, 245, 57, 191, 246, 136, 89, 40, 147, 181, 237, 154, 91, 231, + 83, 130, 133, 8, 197, 97, 227, 17, 133, 115, 221, 176, 80, 66, + 142, 243, 230, 3, 59, 25, 62, 93, 62, 155, 177, 173, 41, 7, + 229, 7, 241, 252, 89, 105, 50, 75, 168, 132, 202, 160, 246, 226, + 180, 136, 28, 203, 51, 70, 229, 83, 240, 163, 125, 125, 62, 210, + 56, 84, 140, 22, 138, 4, 15, 33, 113, 34, 16, 218, 121, 21, + 13, 109, 144, 30, 14, 6, 115, 249, 67, 105, 29, 110, 48, 58, + 112, 6, 112, 68, 222, 13, 128, 184, 217, 122, 48, 149, 155, 165, + 45, 7, 58, 64, 14, 115, 200, 1, 229, 193, 161, 185, 164, 98, + 4, 72, 138, 194, 97, 7, 112, 66, 63, 143, 48, 109, 239, 25, + 109, 73, 124, 187, 25, 202, 106, 114, 50, 103, 195, 5, 8, 51, + 140, 70, 200, 27, 134, 97, 49, 96, 135, 131, 201, 54, 121, 104, + 9, 55, 1, 111, 230, 173, 27, 154, 31, 254, 56, 122, 164, 234, + 166, 59, 154, 74, 253, 18, 151, 60, 91, 29, 75, 220, 14, 155, + 94, 129, 163, 197, 233, 113, 51, 46, 191, 65, 66, 194, 223, 125, + 176, 202, 198, 96, 253, 237, 194, 152, 193, 213, 22, 232, 185, 149, + 29, 218, 202, 114, 144, 18, 252, 216, 8, 218, 149, 146, 68, 135, + 182, 73, 64, 129, 226, 156, 147, 252, 183, 128, 223, 104, 74, 188, + 42, 210, 82, 81, 24, 109, 244, 159, 36, 87, 120, 122, 49, 22, + 28, 191, 236, 249, 18, 239, 69, 89, 168, 187, 242, 97, 203, 241, + 19, 181, 240, 159, 39, 157, 95, 223, 148, 107, 210, 9, 248, 128, + 203, 173, 238, 172, 25, 76, 191, 101, 180, 154, 251, 24, 0, 249, + 21, 176, 105, 113, 110, 177, 221, 123, 208, 21, 128, 253, 103, 127, + 247, 215, 70, 201, 144, 193, 109, 115, 103, 143, 222, 166, 184, 240, + 65, 148, 27, 188, 14, 249, 69, 79, 18, 251, 93, 155, 9, 223, + 90, 81, 238, 205, 177, 75, 63, 112, 244, 133, 172, 123, 109, 76, + 92, 179, 173, 100, 115, 132, 70, 145, 149, 244, 47, 221, 94, 147, + 24, 192, 231, 14, 51, 194, 52, 24, 123, 83, 142, 224, 104, 242, + 244, 98, 145, 83, 54, 217, 45, 127, 139, 250, 130, 63, 241, 25, + 7, 216, 117, 189, 70, 10, 183, 169, 144, 54, 109, 108, 8, 125, + 222, 34, 33, 124, 100, 223, 249, 134, 25, 214, 139, 133, 246, 27, + 41, 248, 157, 203, 31, 38, 1, 50, 51, 210, 21, 218, 23, 214, + 209, 123, 34, 183, 168, 119, 172, 71, 44, 245, 191, 35, 114, 37, + 96, 220, 138, 133, 11, 148, 128, 102, 25, 78, 69, 156, 33, 131, + 62, 51, 189, 139, 249, 234, 147, 186, 116, 160, 79, 199, 34, 57, + 106, 151, 55, 102, 70, 166, 219, 230, 236, 194, 50, 32, 90, 173, + 29, 39, 115, 10, 173, 2, 82, 9, 131, 204, 0, 31, 35, 85, + 34, 252, 206, 37, 28, 103, 172, 126, 55, 62, 209, 34, 214, 80, + 158, 61, 225, 174, 232, 13, 231, 172, 203, 195, 161, 78, 43, 225, + 148, 0, 251, 99, 208, 140, 161, 223, 12, 54, 110, 78, 231, 175, + 207, 127, 159, 140, 126, 96, 69, 214, 64, 43, 47, 126, 127, 224, + 110, 157, 159, 77, 7, 73, 7, 241, 132, 132, 146, 172, 33, 253, + 143, 226, 18, 154, 105, 131, 134, 113, 196, 32, 107, 183, 65, 60, + 129, 120, 91, 45, 118, 11, 63, 252, 53, 34, 111, 236, 145, 75, + 50, 234, 181, 72, 155, 150, 64, 89, 52, 238, 228, 71, 18, 202, + 197, 85, 68, 108, 173, 19, 93, 188, 4, 31, 50, 85, 228, 47, + 93, 233, 252, 159, 171, 110, 218, 29, 120, 189, 127, 95, 44, 92, + 107, 200, 172, 119, 88, 116, 243, 203, 36, 2, 123, 184, 118, 245, + 89, 213, 3, 111, 228, 0, 204, 139, 90, 6, 39, 219, 110, 12, + 171, 48, 167, 181, 108, 133, 94, 135, 84, 227, 10, 102, 23, 217, + 217, 66, 207, 33, 247, 136, 140, 223, 131, 117, 3, 122, 125, 19, + 180, 131, 222, 28, 220, 118, 50, 145, 158, 40, 207, 43, 2, 134, + 67, 108, 38, 133, 243, 205, 97, 23, 239, 236, 97, 237, 233, 254, + 155, 222, 200, 229, 165, 29, 99, 246, 130, 206, 45, 116, 199, 230, + 137, 213, 248, 47, 60, 231, 124, 179, 228, 2, 235, 126, 195, 214, + 102, 241, 241, 225, 100, 81, 185, 220, 136, 227, 56, 247, 209, 97, + 110, 227, 224, 187, 235, 33, 159, 209, 92, 174, 81, 214, 54, 39, + 131, 131, 236, 206, 107, 177, 3, 242, 98, 120, 207, 75, 29, 190, + 131, 196, 198, 188, 75, 175, 126, 28, 114, 111, 11, 138, 5, 21, + 11, 87, 196, 138, 78, 235, 190, 77, 250, 58, 240, 70, 15, 251, + 235, 3, 30, 114, 250, 83, 78, 91, 117, 184, 34, 125, 215, 218, + 4, 56, 20, 106, 30, 240, 152, 220, 207, 41, 59, 42, 219, 47, + 36, 51, 189, 196, 202, 76, 182, 163, 98, 50, 70, 177, 125, 23, + 108, 222, 27, 109, 184, 185, 99, 168, 138, 76, 191, 53, 128, 137, + 197, 33, 12, 41, 247, 80, 238, 53, 126, 231, 133, 223, 164, 17, + 210, 149, 204, 21, 198, 196, 109, 230, 186, 98, 243, 150, 220, 208, + 227, 136, 138, 160, 199, 255, 240, 143, 240, 208, 188, 41, 255, 219, + 171, 3, 204, 127, 72, 8, 37, 174, 191, 132, 96, 246, 133, 214, + 101, 197, 69, 152, 17, 46, 59, 68, 120, 223, 110, 135, 24, 133, + 115, 50, 11, 136, 218, 119, 250, 32, 137, 111, 207, 2, 43, 127, + 198, 195, 241, 172, 125, 220, 28, 61, 3, 168, 116, 224, 72, 120, + 6, 114, 46, 238, 199, 222, 38, 27, 190, 144, 177, 166, 135, 83, + 132, 98, 52, 120, 65, 236, 196, 177, 118, 73, 14, 138, 88, 145, + 214, 172, 251, 210, 15, 207, 59, 125, 238, 90, 39, 231, 245, 144, + 127, 155, 38, 95, 214, 45, 197, 77, 1, 77, 212, 47, 51, 5, + 222, 154, 103, 245, 14, 80, 186, 96, 159, 43, 69, 171, 134, 109, + 99, 132, 254, 237, 157, 223, 60, 223, 44, 161, 196, 132, 230, 102, + 246, 10, 208, 140, 70, 73, 113, 33, 151, 174, 64, 211, 236, 206, + 194, 63, 164, 13, 23, 242, 66, 242, 49, 106, 75, 95, 132, 218, + 152, 114, 156, 35, 192, 39, 122, 218, 124, 218, 150, 101, 180, 166, + 197, 15, 188, 229, 77, 29, 20, 101, 242, 159, 160, 65, 91, 130, + 243, 81, 253, 154, 204, 71, 217, 147, 147, 254, 248, 203, 212, 58, + 203, 172, 135, 216, 62, 236, 25, 3, 7, 247, 222, 29, 189, 172, + 177, 140, 188, 143, 157, 25, 0, 181, 30, 148, 254, 62, 193, 156, + 89, 194, 241, 161, 67, 65, 56, 120, 61, 134, 163, 228, 230, 154, + 22, 127, 5, 71, 165, 61, 58, 7, 161, 61, 173, 252, 2, 150, + 17, 149, 37, 175, 32, 152, 228, 125, 159, 150, 233, 139, 53, 9, + 128, 59, 191, 35, 98, 52, 158, 201, 157, 171, 22, 10, 23, 247, + 180, 244, 230, 25, 26, 99, 116, 3, 206, 150, 203, 9, 30, 93, + 143, 0, 216, 53, 209, 67, 131, 40, 205, 75, 121, 158, 104, 125, + 193, 152, 244, 244, 204, 78, 245, 124, 14, 114, 80, 196, 225, 196, + 155, 234, 101, 151, 164, 120, 140, 62, 252, 242, 254, 111, 89, 227, + 235, 140, 109, 170, 216, 68, 11, 66, 26, 83, 60, 124, 199, 91, + 52, 147, 150, 136, 207, 131, 196, 23, 14, 50, 98, 69, 215, 255, + 139, 3, 72, 152, 40, 133, 4, 161, 29, 156, 29, 8, 53, 154, + 228, 217, 169, 117, 74, 96, 60, 130, 25, 78, 32, 235, 31, 144, + 38, 195, 213, 37, 109, 91, 165, 47, 232, 199, 76, 121, 123, 15, + 229, 41, 213, 189, 128, 55, 192, 4, 237, 179, 247, 3, 244, 45, + 173, 226, 161, 171, 90, 28, 213, 25, 137, 131, 49, 162, 208, 242, + 202, 91, 78, 124, 103, 0, 104, 255, 158, 189, 32, 119, 101, 25, + 171, 190, 233, 30, 186, 197, 35, 73, 90, 170, 247, 163, 105, 80, + 52, 35, 185, 49, 20, 248, 156, 27, 105, 149, 30, 156, 172, 83, + 163, 52, 27, 132, 185, 226, 55, 233, 168, 11, 132, 255, 153, 45, + 189, 112, 92, 6, 101, 234, 255, 244, 227, 158, 90, 169, 220, 225, + 223, 56, 217, 238, 0, 219, 82, 177, 175, 226, 52, 229, 171, 108, + 174, 79, 61, 232, 177, 53, 20, 105, 75, 219, 56, 44, 177, 72, + 212, 187, 73, 100, 225, 247, 163, 32, 146, 83, 153, 128, 14, 87, + 47, 243, 194, 176, 235, 67, 44, 195, 92, 69, 246, 152, 126, 22, + 247, 179, 39, 226, 22, 8, 242, 186, 52, 241, 53, 100, 113, 134, + 70, 121, 104, 251, 141, 74, 225, 134, 239, 122, 43, 123, 142, 116, + 7, 151, 20, 139, 151, 166, 142, 123, 232, 223, 246, 79, 201, 64, + 193, 25, 169, 188, 255, 173, 169, 154, 113, 7, 35, 75, 51, 175, + 197, 125, 213, 157, 41, 19, 226, 142, 183, 250, 207, 194, 137, 238, + 85, 116, 48, 33, 89, 55, 131, 252, 28, 174, 157, 249, 195, 140, + 254, 11, 101, 231, 49, 115, 110, 11, 148, 188, 67, 159, 164, 35, + 6, 93, 6, 170, 73, 239, 1, 19, 30, 63, 125, 88, 39, 44, + 6, 134, 232, 216, 192, 162, 212, 39, 24, 94, 144, 12, 13, 15, + 105, 234, 244, 181, 241, 208, 73, 35, 59, 120, 208, 218, 192, 249, + 31, 213, 35, 99, 39, 177, 226, 0, 69, 201, 182, 87, 172, 203, + 148, 170, 46, 156, 111, 79, 219, 139, 36, 155, 117, 92, 161, 190, + 113, 47, 160, 227, 102, 176, 58, 78, 51, 108, 69, 163, 191, 177, + 140, 252, 189, 220, 64, 167, 129, 170, 6, 220, 109, 217, 2, 7, + 31, 70, 140, 94, 4, 93, 171, 82, 158, 208, 124, 133, 48, 108, + 74, 161, 18, 126, 140, 249, 201, 16, 87, 125, 130, 200, 130, 46, + 229, 164, 90, 145, 13, 243, 228, 221, 7, 158, 110, 92, 158, 168, + 166, 22, 112, 172, 93, 108, 2, 23, 245, 172, 239, 186, 82, 24, + 177, 240, 51, 223, 44, 111, 57, 250, 119, 248, 74, 5, 147, 138, + 82, 226, 141, 94, 241, 181, 10, 131, 28, 15, 47, 79, 203, 100, + 90, 159, 49, 0, 18, 86, 107, 1, 247, 72, 31, 14, 95, 130, + 91, 180, 196, 95, 153, 200, 190, 8, 204, 210, 163, 60, 143, 249, + 69, 149, 19, 154, 178, 49, 165, 113, 219, 231, 22, 214, 170, 162, + 70, 66, 46, 120, 197, 193, 215, 35, 59, 61, 165, 131, 0, 73, + 122, 49, 199, 35, 43, 145, 115, 8, 197, 14, 255, 229, 171, 237, + 194, 200, 207, 163, 79, 193, 245, 190, 228, 82, 240, 97, 249, 222, + 101, 186, 89, 100, 36, 89, 154, 203, 143, 175, 67, 164, 176, 157, + 112, 6, 122, 124, 16, 143, 140, 98, 65, 185, 52, 180, 28, 170, + 242, 107, 45, 155, 201, 182, 219, 82, 55, 222, 226, 149, 58, 197, + 59, 185, 170, 23, 199, 0, 218, 154, 24, 72, 223, 165, 185, 103, + 72, 82, 235, 210, 86, 46, 241, 96, 110, 193, 248, 224, 156, 124, + 125, 225, 185, 216, 198, 68, 29, 48, 130, 69, 160, 224, 103, 242, + 158, 122, 215, 183, 146, 46, 34, 82, 24, 121, 168, 150, 6, 97, + 146, 174, 216, 208, 240, 14, 32, 217, 56, 75, 118, 126, 46, 217, + 77, 196, 250, 153, 232, 23, 50, 119, 165, 204, 23, 39, 244, 161, + 148, 72, 39, 102, 118, 111, 249, 191, 45, 222, 155, 99, 151, 52, + 235, 1, 8, 57, 137, 121, 122, 85, 159, 23, 64, 227, 34, 82, + 143, 144, 135, 230, 66, 89, 104, 67, 90, 113, 66, 32, 91, 153, + 137, 9, 72, 145, 41, 59, 94, 45, 0, 11, 72, 26, 133, 113, + 62, 12, 182, 48, 11, 227, 81, 240, 123, 97, 152, 53, 236, 71, + 142, 164, 190, 74, 221, 216, 92, 195, 16, 201, 5, 4, 144, 202, + 221, 28, 50, 61, 234, 238, 193, 236, 64, 148, 112, 91, 228, 36, + 78, 92, 200, 144, 146, 212, 194, 247, 225, 104, 113, 245, 76, 161, + 103, 123, 176, 84, 233, 187, 239, 20, 125, 158, 246, 224, 193, 138, + 109, 10, 62, 0, 33, 242, 43, 122, 34, 130, 149, 179, 59, 218, + 56, 127, 53, 175, 210, 250, 45, 78, 88, 74, 220, 158, 184, 240, + 162, 89, 196, 4, 63, 223, 49, 53, 25, 252, 23, 234, 221, 79, + 135, 151, 131, 30, 223, 88, 69, 101, 211, 128, 57, 126, 155, 212, + 221, 111, 0, 54, 53, 164, 230, 47, 173, 27, 233, 202, 224, 197, + 120, 53, 238, 49, 225, 175, 35, 80, 224, 57, 211, 11, 205, 93, + 108, 154, 238, 136, 151, 158, 84, 48, 186, 13, 47, 37, 3, 162, + 163, 63, 84, 188, 113, 164, 229, 31, 212, 239, 137, 17, 179, 204, + 234, 199, 130, 55, 156, 87, 83, 178, 221, 118, 74, 231, 162, 49, + 51, 19, 143, 93, 236, 113, 108, 111, 55, 37, 213, 13, 37, 77, + 236, 69, 247, 43, 198, 166, 140, 190, 157, 118, 245, 89, 119, 254, + 216, 127, 69, 147, 135, 77, 29, 76, 11, 16, 84, 234, 156, 136, + 82, 51, 50, 110, 135, 62, 255, 152, 228, 32, 109, 252, 1, 90, + 84, 154, 172, 253, 159, 47, 49, 132, 29, 180, 87, 10, 139, 117, + 110, 8, 8, 208, 30, 28, 58, 84, 183, 38, 12, 231, 33, 61, + 154, 34, 235, 171, 59, 72, 106, 225, 241, 36, 147, 116, 2, 7, + 88, 77, 178, 185, 50, 96, 165, 188, 4, 109, 236, 133, 113, 227, + 240, 99, 23, 103, 123, 240, 62, 80, 235, 33, 0, 111, 152, 190, + 16, 61, 178, 78, 236, 160, 136, 146, 185, 34, 218, 146, 119, 233, + 23, 68, 237, 166, 211, 247, 52, 70, 41, 237, 67, 169, 69, 35, + 162, 61, 192, 78, 77, 56, 182, 127, 52, 179, 132, 27, 62, 213, + 63, 153, 137, 138, 15, 26, 183, 139, 125, 146, 104, 183, 166, 54, + 86, 30, 65, 40, 175, 4, 157, 188, 10, 73, 19, 241, 186, 156, + 109, 198, 18, 47, 237, 67, 235, 95, 8, 46, 180, 70, 233, 108, + 85, 52, 52, 156, 186, 224, 47, 250, 84, 120, 236, 173, 3, 251, + 248, 17, 209, 239, 46, 30, 117, 15, 207, 76, 83, 143, 252, 80, + 180, 197, 228, 13, 245, 207, 70, 7, 9, 227, 214, 122, 102, 191, + 173, 17, 248, 36, 220, 226, 43, 116, 58, 108, 220, 68, 125, 179, + 28, 48, 113, 17, 62, 155, 135, 145, 234, 98, 68, 100, 15, 240, + 73, 84, 233, 184, 215, 16, 185, 236, 117, 152, 138, 30, 52, 237, + 165, 23, 55, 121, 216, 100, 244, 57, 89, 48, 239, 196, 56, 121, + 239, 91, 84, 55, 167, 26, 197, 184, 219, 103, 134, 93, 135, 127, + 85, 105, 214, 110, 103, 190, 56, 139, 11, 184, 160, 180, 78, 134, + 51, 79, 148, 189, 187, 30, 16, 41, 74, 235, 197, 90, 59, 166, + 7, 99, 247, 156, 84, 78, 25, 11, 210, 70, 30, 137, 233, 188, + 150, 58, 206, 118, 195, 251, 60, 168, 4, 167, 131, 30, 222, 92, + 213, 126, 133, 187, 137, 49, 93, 97, 253, 253, 220, 98, 208, 57, + 66, 118, 53, 172, 59, 171, 32, 96, 188, 140, 158, 92, 218, 213, + 215, 69, 227, 216, 47, 123, 189, 60, 189, 43, 170, 220, 188, 115, + 145, 146, 184, 112, 104, 154, 59, 95, 253, 227, 212, 187, 205, 219, + 37, 146, 1, 205, 59, 13, 193, 116, 219, 209, 77, 216, 241, 28, + 94, 166, 39, 217, 201, 231, 125, 181, 179, 239, 16, 103, 149, 122, + 184, 254, 106, 239, 168, 230, 185, 184, 236, 192, 149, 120, 130, 113, + 156, 164, 214, 169, 16, 226, 135, 166, 184, 187, 106, 41, 205, 97, + 192, 161, 6, 213, 62, 229, 187, 199, 189, 50, 250, 26, 193, 162, + 173, 143, 27, 205, 186, 234, 164, 25, 211, 171, 72, 119, 82, 60, + 64, 154, 129, 60, 89, 109, 150, 59, 40, 226, 6, 11, 48, 139, + 72, 27, 248, 53, 97, 205, 139, 105, 214, 176, 44, 78, 22, 131, + 157, 72, 153, 204, 157, 112, 38, 76, 83, 186, 136, 254, 97, 112, + 139, 70, 85, 251, 45, 201, 82, 157, 181, 232, 76, 156, 210, 248, + 125, 129, 142, 24, 86, 202, 109, 41, 95, 159, 76, 164, 13, 103, + 58, 217, 90, 173, 134, 243, 142, 43, 23, 83, 237, 108, 19, 227, + 120, 238, 107, 87, 1, 75, 173, 83, 244, 52, 180, 215, 56, 213, + 94, 240, 107, 225, 122, 159, 10, 106, 181, 240, 171, 45, 123, 245, + 36, 53, 32, 73, 187, 102, 142, 85, 236, 141, 30, 115, 45, 200, + 33, 152, 208, 88, 129, 225, 85, 177, 125, 5, 184, 107, 3, 171, + 96, 65, 61, 118, 90, 92, 246, 47, 5, 139, 107, 78, 255, 136, + 6, 246, 176, 73, 206, 29, 249, 64, 240, 174, 51, 40, 84, 239, + 124, 80, 219, 251, 210, 90, 20, 56, 115, 147, 121, 195, 62, 155, + 59, 20, 20, 165, 109, 75, 141, 213, 51, 35, 80, 17, 40, 83, + 197, 24, 86, 124, 87, 225, 218, 19, 222, 123, 180, 188, 37, 59, + 61, 169, 94, 98, 1, 150, 122, 112, 127, 88, 16, 137, 27, 228, + 241, 122, 29, 46, 115, 244, 129, 91, 65, 128, 18, 117, 145, 110, + 64, 246, 223, 117, 154, 104, 132, 116, 91, 253, 174, 95, 196, 117, + 20, 10, 221, 235, 163, 80, 171, 16, 118, 36, 56, 211, 194, 192, + 232, 135, 40, 105, 41, 135, 167, 163, 29, 211, 230, 20, 42, 148, + 41, 138, 177, 141, 240, 186, 86, 196, 132, 175, 137, 109, 159, 176, + 212, 127, 117, 206, 218, 203, 175, 207, 211, 198, 213, 159, 182, 238, + 18, 94, 55, 125, 218, 78, 152, 17, 218, 131, 111, 16, 223, 73, + 80, 143, 105, 155, 21, 165, 9, 87, 37, 32, 46, 12, 72, 249, + 160, 39, 123, 132, 107, 94, 153, 56, 54, 137, 47, 59, 208, 40, + 144, 32, 220, 128, 129, 133, 142, 193, 200, 120, 189, 13, 60, 139, + 225, 16, 186, 78, 198, 63, 102, 139, 83, 209, 124, 4, 204, 237, + 188, 55, 206, 121, 227, 47, 135, 74, 89, 96, 139, 78, 68, 177, + 63, 4, 144, 22, 155, 121, 148, 94, 110, 231, 250, 111, 222, 179, + 229, 69, 203, 45, 141, 218, 169, 112, 133, 145, 235, 214, 55, 22, + 179, 146, 130, 204, 81, 42, 98, 127, 112, 175, 22, 192, 178, 144, + 72, 152, 115, 186, 96, 203, 203, 83, 148, 34, 60, 194, 92, 34, + 76, 145, 232, 230, 122, 49, 26, 112, 240, 92, 219, 232, 92, 212, + 210, 52, 180, 139, 69, 56, 110, 166, 106, 46, 214, 169, 152, 27, + 60, 185, 237, 204, 12, 174, 27, 218, 173, 73, 59, 95, 153, 150, + 105, 18, 95, 176, 10, 170, 23, 55, 179, 142, 109, 253, 102, 92, + 4, 95, 193, 176, 174, 224, 169, 8, 61, 254, 50, 14, 92, 202, + 88, 138, 87, 185, 164, 23, 91, 164, 70, 237, 197, 226, 80, 1, + 6, 222, 15, 173, 149, 57, 157, 108, 221, 165, 99, 125, 75, 184, + 197, 201, 229, 181, 27, 228, 175, 21, 133, 127, 121, 228, 8, 223, + 215, 107, 171, 54, 58, 216, 26, 249, 181, 107, 42, 145, 145, 165, + 123, 94, 230, 106, 219, 102, 4, 127, 197, 89, 239, 157, 15, 65, + 232, 111, 10, 142, 42, 1, 178, 44, 104, 232, 167, 5, 48, 100, + 169, 154, 219, 191, 44, 210, 200, 11, 47, 46, 136, 119, 108, 22, + 196, 220, 243, 116, 65, 15, 149, 44, 164, 204, 233, 2, 86, 145, + 242, 133, 206, 81, 151, 120, 36, 158, 66, 71, 207, 210, 88, 156, + 95, 103, 31, 182, 238, 214, 151, 13, 2, 157, 132, 221, 235, 179, + 135, 137, 166, 129, 93, 54, 119, 184, 46, 0, 130, 4, 55, 242, + 37, 1, 187, 153, 171, 149, 36, 212, 136, 180, 64, 20, 206, 170, + 86, 217, 207, 196, 140, 153, 133, 141, 108, 74, 6, 143, 103, 76, + 181, 228, 175, 128, 188, 1, 134, 249, 67, 246, 127, 144, 93, 153, + 56, 66, 50, 48, 13, 198, 88, 123, 2, 153, 77, 135, 70, 70, + 79, 158, 14, 17, 50, 211, 41, 178, 149, 79, 7, 135, 194, 43, + 165, 60, 57, 156, 50, 9, 222, 100, 13, 146, 195, 196, 74, 169, + 117, 251, 148, 170, 141, 201, 207, 133, 146, 34, 9, 54, 245, 140, + 8, 95, 99, 154, 115, 186, 24, 227, 11, 181, 12, 169, 122, 42, + 34, 131, 106, 49, 243, 20, 163, 46, 101, 35, 45, 214, 99, 207, + 104, 109, 34, 60, 12, 151, 177, 136, 244, 75, 40, 201, 225, 243, + 122, 93, 111, 205, 58, 10, 68, 69, 143, 39, 121, 14, 214, 168, + 57, 120, 250, 183, 56, 84, 230, 202, 17, 163, 238, 94, 105, 130, + 183, 8, 119, 188, 147, 138, 198, 105, 71, 70, 174, 74, 3, 67, + 218, 19, 73, 255, 137, 253, 67, 58, 228, 83, 239, 13, 177, 182, + 28, 246, 195, 82, 39, 56, 184, 22, 243, 62, 78, 71, 94, 156, + 35, 52, 2, 70, 75, 113, 60, 190, 93, 250, 237, 221, 144, 194, + 74, 76, 42, 89, 145, 48, 210, 139, 7, 57, 121, 230, 68, 107, + 227, 249, 69, 120, 90, 4, 218, 255, 105, 234, 13, 149, 30, 147, + 137, 49, 136, 58, 151, 124, 165, 78, 10, 30, 235, 34, 40, 160, + 34, 53, 22, 183, 218, 58, 159, 36, 238, 16, 198, 153, 176, 211, + 206, 108, 238, 61, 38, 217, 99, 36, 44, 84, 202, 206, 178, 183, + 254, 178, 54, 216, 101, 215, 182, 210, 61, 161, 12, 212, 168, 133, + 217, 232, 212, 127, 211, 58, 232, 205, 106, 235, 79, 31, 123, 249, + 212, 154, 179, 127, 202, 235, 204, 111, 80, 22, 86, 9, 253, 216, + 224, 43, 32, 19, 163, 150, 241, 43, 241, 118, 8, 84, 194, 192, + 102, 65, 84, 138, 55, 65, 125, 253, 232, 183, 251, 178, 236, 185, + 96, 72, 246, 114, 19, 165, 58, 184, 48, 148, 231, 169, 188, 136, + 57, 193, 252, 203, 173, 91, 24, 142, 15, 12, 111, 198, 159, 210, + 115, 58, 91, 212, 65, 154, 41, 241, 140, 179, 235, 132, 238, 53, + 49, 75, 178, 2, 254, 250, 21, 91, 106, 166, 0, 132, 119, 208, + 243, 88, 153, 231, 147, 34, 66, 121, 209, 120, 65, 169, 134, 20, + 81, 230, 115, 10, 141, 146, 110, 190, 235, 187, 201, 102, 96, 67, + 27, 29, 99, 39, 25, 173, 24, 230, 140, 176, 107, 84, 95, 172, + 73, 234, 232, 119, 55, 122, 220, 181, 240, 247, 190, 231, 251, 113, + 7, 156, 166, 82, 224, 226, 218, 117, 232, 20, 2, 133, 118, 128, + 216, 6, 230, 229, 82, 217, 112, 55, 128, 192, 175, 153, 219, 189, + 70, 122, 64, 84, 102, 220, 100, 114, 81, 156, 176, 212, 214, 80, + 87, 239, 228, 209, 131, 30, 231, 70, 214, 22, 131, 231, 205, 157, + 184, 46, 219, 109, 182, 127, 58, 198, 48, 218, 30, 181, 8, 244, + 160, 166, 64, 66, 207, 162, 142, 11, 60, 129, 137, 209, 53, 38, + 125, 161, 121, 130, 157, 143, 177, 152, 209, 159, 135, 248, 26, 224, + 214, 169, 167, 208, 76, 121, 238, 36, 179, 43, 95, 75, 98, 75, + 253, 16, 91, 2, 217, 254, 212, 57, 131, 154, 84, 13, 95, 110, + 115, 96, 240, 88, 165, 141, 92, 173, 205, 19, 213, 121, 102, 31, + 51, 75, 144, 106, 170, 27, 124, 254, 77, 59, 53, 83, 246, 48, + 237, 247, 60, 236, 234, 215, 83, 109, 146, 59, 232, 135, 26, 251, + 145, 196, 80, 212, 217, 244, 159, 214, 62, 41, 96, 232, 208, 42, + 190, 179, 111, 149, 53, 76, 22, 9, 240, 84, 148, 4, 118, 179, + 52, 116, 136, 114, 67, 203, 37, 8, 192, 174, 100, 212, 106, 223, + 134, 102, 74, 96, 159, 94, 222, 37, 209, 68, 248, 182, 94, 47, + 37, 79, 37, 27, 87, 22, 183, 158, 64, 161, 27, 159, 224, 161, + 159, 119, 79, 156, 116, 137, 194, 9, 125, 211, 228, 54, 61, 48, + 199, 79, 204, 93, 107, 67, 149, 37, 77, 42, 185, 109, 178, 41, + 215, 14, 9, 180, 134, 76, 198, 25, 215, 244, 105, 104, 33, 175, + 174, 220, 45, 74, 71, 230, 21, 148, 192, 239, 116, 22, 155, 18, + 8, 226, 148, 198, 98, 232, 1, 250, 195, 42, 165, 191, 160, 108, + 23, 33, 103, 86, 198, 230, 160, 95, 233, 197, 33, 65, 43, 248, + 135, 204, 195, 225, 191, 81, 103, 5, 251, 125, 203, 91, 11, 30, + 40, 224, 3, 63, 140, 185, 96, 83, 141, 127, 195, 9, 208, 1, + 111, 218, 117, 186, 200, 176, 254, 231, 21, 191, 37, 164, 172, 134, + 218, 225, 8, 41, 148, 131, 27, 140, 157, 83, 99, 103, 14, 21, + 141, 46, 165, 197, 77, 46, 98, 66, 117, 38, 24, 152, 61, 6, + 222, 63, 71, 175, 225, 26, 193, 159, 49, 239, 53, 198, 153, 43, + 30, 203, 26, 149, 250, 40, 242, 177, 219, 99, 232, 82, 5, 221, + 97, 102, 2, 111, 215, 119, 228, 74, 43, 243, 12, 82, 239, 103, + 189, 229, 224, 168, 203, 139, 58, 217, 248, 135, 102, 108, 200, 136, + 131, 227, 42, 117, 64, 182, 120, 253, 85, 3, 37, 0, 62, 13, + 244, 137, 81, 71, 205, 100, 32, 28, 15, 14, 178, 46, 202, 132, + 146, 114, 203, 34, 238, 195, 174, 24, 234, 108, 65, 118, 193, 57, + 113, 251, 142, 58, 221, 220, 11, 136, 83, 83, 5, 191, 73, 19, + 34, 185, 35, 192, 110, 107, 143, 37, 15, 227, 206, 74, 254, 225, + 8, 47, 200, 163, 35, 101, 122, 241, 25, 178, 73, 220, 151, 11, + 84, 243, 172, 8, 152, 217, 165, 66, 238, 80, 125, 240, 215, 67, + 118, 139, 245, 245, 142, 161, 217, 170, 55, 42, 206, 66, 124, 73, + 156, 255, 226, 59, 146, 179, 5, 131, 44, 249, 71, 180, 70, 190, + 43, 200, 218, 130, 76, 75, 28, 28, 64, 137, 52, 35, 40, 104, + 81, 215, 198, 66, 76, 245, 62, 88, 154, 192, 137, 189, 21, 223, + 65, 51, 251, 47, 4, 119, 213, 115, 97, 132, 166, 168, 245, 239, + 129, 64, 154, 246, 194, 170, 103, 102, 38, 170, 148, 79, 49, 23, + 45, 121, 122, 81, 120, 196, 160, 149, 61, 81, 38, 15, 122, 121, + 144, 206, 70, 63, 35, 102, 237, 45, 144, 61, 131, 205, 39, 96, + 210, 102, 228, 57, 26, 245, 151, 127, 154, 35, 97, 28, 164, 142, + 63, 181, 38, 19, 128, 205, 246, 73, 24, 153, 84, 98, 63, 125, + 160, 51, 95, 3, 130, 32, 178, 203, 229, 239, 59, 144, 228, 130, + 112, 28, 46, 104, 230, 178, 122, 123, 254, 45, 10, 175, 170, 72, + 17, 240, 104, 230, 194, 160, 181, 97, 150, 213, 81, 8, 4, 118, + 64, 144, 238, 178, 194, 240, 189, 61, 83, 159, 177, 186, 87, 109, + 90, 203, 42, 253, 78, 94, 20, 151, 203, 118, 221, 156, 84, 115, + 188, 167, 155, 238, 219, 50, 139, 146, 24, 126, 233, 128, 76, 107, + 50, 55, 43, 10, 91, 186, 21, 67, 190, 101, 111, 42, 211, 61, + 85, 175, 76, 142, 166, 234, 252, 248, 121, 129, 74, 234, 100, 231, + 239, 111, 108, 77, 211, 18, 65, 121, 172, 192, 96, 149, 231, 105, + 82, 220, 195, 247, 208, 218, 95, 40, 45, 121, 94, 39, 233, 23, + 192, 190, 197, 5, 209, 243, 138, 99, 195, 166, 4, 50, 31, 228, + 196, 14, 221, 109, 133, 212, 180, 76, 211, 102, 191, 229, 168, 140, + 131, 128, 219, 210, 210, 171, 27, 92, 181, 19, 108, 116, 161, 185, + 52, 55, 203, 87, 240, 107, 219, 245, 121, 206, 242, 189, 51, 38, + 104, 211, 187, 44, 237, 56, 9, 11, 5, 106, 128, 5, 220, 127, + 66, 128, 115, 201, 37, 86, 97, 176, 67, 229, 144, 92, 12, 217, + 254, 97, 199, 195, 59, 232, 153, 129, 122, 173, 118, 232, 178, 187, + 82, 149, 235, 222, 200, 218, 0, 10, 172, 76, 229, 171, 96, 197, + 8, 207, 41, 208, 175, 146, 164, 63, 187, 58, 62, 41, 4, 238, + 109, 67, 151, 74, 67, 164, 152, 255, 11, 204, 144, 68, 234, 183, + 198, 246, 238, 22, 34, 217, 235, 173, 124, 39, 1, 101, 88, 157, + 82, 255, 14, 206, 211, 179, 136, 124, 100, 54, 136, 230, 17, 14, + 207, 231, 95, 176, 18, 36, 30, 87, 104, 139, 213, 215, 56, 181, + 206, 44, 193, 249, 6, 158, 187, 92, 26, 52, 183, 52, 232, 233, + 180, 21, 9, 173, 46, 40, 85, 14, 24, 209, 24, 5, 205, 59, + 86, 245, 221, 229, 247, 44, 141, 70, 223, 101, 90, 100, 135, 248, + 252, 31, 3, 168, 12, 22, 50, 243, 207, 72, 21, 81, 103, 12, + 201, 84, 249, 72, 18, 207, 190, 56, 100, 249, 230, 110, 176, 6, + 146, 109, 237, 38, 106, 120, 190, 99, 213, 18, 219, 52, 32, 49, + 131, 45, 72, 140, 123, 250, 9, 162, 83, 150, 212, 65, 89, 188, + 48, 94, 78, 40, 191, 57, 161, 248, 198, 112, 231, 154, 31, 147, + 148, 195, 105, 45, 39, 186, 224, 232, 24, 175, 182, 201, 3, 130, + 28, 34, 189, 134, 125, 64, 35, 121, 212, 23, 233, 180, 177, 119, + 228, 252, 237, 106, 227, 53, 19, 127, 239, 148, 180, 157, 98, 135, + 119, 255, 86, 115, 95, 216, 179, 228, 165, 188, 211, 164, 152, 209, + 249, 69, 117, 111, 166, 68, 247, 219, 167, 221, 198, 46, 20, 246, + 185, 22, 0, 238, 56, 107, 162, 168, 91, 234, 52, 84, 76, 2, + 122, 92, 142, 52, 172, 123, 239, 56, 126, 110, 131, 143, 131, 103, + 156, 138, 28, 139, 76, 101, 194, 99, 232, 75, 156, 152, 58, 145, + 247, 224, 99, 253, 114, 74, 26, 189, 159, 47, 68, 62, 172, 91, + 30, 69, 84, 9, 221, 115, 80, 183, 199, 168, 67, 180, 237, 176, + 85, 142, 242, 103, 232, 51, 244, 26, 89, 41, 202, 151, 155, 226, + 151, 206, 127, 254, 113, 176, 70, 62, 75, 165, 111, 30, 238, 207, + 219, 8, 129, 139, 13, 163, 76, 14, 0, 153, 250, 219, 178, 20, + 241, 131, 236, 172, 169, 200, 198, 184, 172, 1, 238, 118, 166, 254, + 214, 135, 99, 192, 74, 196, 138, 52, 196, 210, 64, 230, 129, 145, + 64, 29, 179, 76, 52, 164, 252, 161, 35, 90, 209, 119, 81, 62, + 133, 67, 37, 74, 183, 71, 221, 236, 54, 7, 154, 168, 242, 127, + 238, 144, 32, 13, 93, 89, 134, 68, 85, 59, 89, 64, 12, 157, + 218, 109, 130, 153, 54, 123, 163, 210, 66, 155, 98, 133, 186, 236, + 111, 63, 165, 130, 121, 89, 189, 147, 223, 213, 253, 152, 77, 170, + 160, 201, 33, 179, 90, 228, 154, 234, 59, 63, 15, 109, 251, 65, + 159, 106, 101, 6, 37, 189, 200, 5, 24, 157, 20, 209, 50, 160, + 196, 242, 64, 118, 127, 64, 105, 46, 128, 197, 144, 9, 245, 236, + 227, 155, 248, 116, 108, 120, 37, 4, 45, 91, 100, 66, 174, 192, + 82, 164, 236, 248, 95, 142, 206, 80, 130, 12, 60, 186, 167, 218, + 12, 6, 155, 59, 207, 225, 115, 209, 54, 184, 100, 74, 129, 117, + 229, 35, 5, 202, 94, 21, 176, 112, 1, 164, 202, 108, 151, 140, + 111, 174, 42, 223, 120, 91, 41, 38, 176, 140, 217, 239, 54, 6, + 92, 178, 36, 231, 202, 102, 98, 222, 223, 123, 206, 1, 58, 181, + 55, 16, 189, 127, 139, 156, 169, 90, 121, 59, 206, 124, 160, 233, + 50, 224, 40, 154, 188, 181, 123, 72, 81, 242, 154, 236, 59, 129, + 73, 72, 87, 56, 210, 214, 89, 180, 239, 103, 51, 22, 167, 90, + 164, 84, 105, 143, 92, 178, 86, 18, 203, 13, 179, 46, 110, 134, + 3, 137, 146, 27, 132, 206, 7, 112, 196, 245, 179, 132, 227, 33, + 36, 70, 231, 99, 28, 4, 167, 53, 230, 15, 33, 40, 179, 184, + 201, 7, 20, 65, 84, 123, 251, 12, 101, 42, 206, 109, 118, 156, + 167, 193, 112, 9, 31, 144, 105, 247, 86, 25, 184, 38, 196, 214, + 56, 158, 144, 222, 93, 103, 173, 72, 84, 124, 186, 207, 115, 215, + 222, 138, 35, 135, 190, 133, 242, 190, 195, 248, 32, 198, 255, 124, + 133, 58, 200, 242, 127, 180, 246, 247, 95, 128, 183, 64, 233, 79, + 158, 40, 136, 246, 150, 197, 83, 90, 214, 94, 50, 139, 242, 201, + 249, 128, 43, 17, 229, 10, 138, 133, 10, 80, 181, 188, 232, 101, + 1, 171, 103, 96, 244, 74, 117, 8, 82, 31, 155, 54, 81, 81, + 99, 212, 221, 209, 197, 11, 46, 171, 158, 70, 192, 172, 42, 91, + 125, 69, 8, 149, 82, 10, 85, 200, 131, 168, 248, 153, 66, 255, + 196, 243, 55, 51, 205, 212, 0, 243, 107, 141, 99, 96, 122, 147, + 83, 133, 7, 134, 235, 246, 93, 251, 149, 7, 115, 217, 207, 164, + 160, 45, 218, 60, 1, 46, 18, 76, 89, 69, 69, 168, 114, 242, + 8, 72, 35, 179, 72, 105, 78, 194, 16, 209, 66, 171, 252, 182, + 181, 71, 46, 91, 67, 102, 41, 251, 136, 234, 236, 166, 142, 6, + 84, 178, 175, 186, 215, 239, 240, 191, 182, 159, 93, 98, 79, 135, + 169, 75, 9, 196, 202, 52, 233, 100, 142, 212, 160, 233, 202, 251, + 106, 243, 191, 68, 126, 78, 250, 241, 172, 4, 84, 19, 204, 104, + 200, 184, 105, 60, 136, 208, 202, 37, 251, 42, 13, 215, 104, 157, + 131, 48, 133, 175, 163, 111, 104, 165, 43, 207, 200, 46, 205, 128, + 93, 44, 201, 213, 111, 17, 239, 243, 109, 124, 246, 89, 126, 212, + 96, 49, 30, 117, 115, 191, 106, 211, 33, 43, 50, 187, 52, 56, + 252, 41, 1, 138, 109, 245, 111, 128, 156, 195, 215, 36, 107, 2, + 92, 160, 63, 226, 115, 166, 128, 234, 121, 18, 24, 70, 168, 110, + 33, 37, 19, 125, 70, 8, 222, 229, 85, 65, 65, 207, 231, 128, + 235, 215, 163, 127, 60, 206, 152, 10, 248, 126, 255, 150, 140, 243, + 45, 164, 169, 198, 118, 50, 112, 146, 173, 111, 214, 99, 107, 99, + 16, 12, 148, 179, 79, 156, 78, 52, 249, 40, 2, 138, 102, 157, + 205, 149, 152, 154, 30, 192, 171, 76, 158, 203, 150, 178, 128, 129, + 70, 254, 11, 165, 49, 106, 198, 56, 231, 113, 193, 247, 122, 34, + 10, 126, 188, 34, 244, 71, 109, 207, 171, 9, 35, 84, 118, 157, + 229, 208, 220, 7, 171, 233, 13, 216, 223, 42, 169, 211, 181, 134, + 214, 54, 42, 125, 62, 45, 177, 127, 182, 150, 251, 103, 123, 97, + 30, 103, 107, 171, 1, 117, 121, 212, 206, 97, 95, 0, 61, 22, + 83, 10, 136, 28, 250, 127, 119, 86, 25, 112, 52, 37, 169, 103, + 47, 189, 170, 250, 251, 14, 131, 216, 229, 92, 85, 38, 4, 17, + 61, 88, 165, 80, 171, 32, 14, 118, 119, 202, 23, 191, 255, 72, + 94, 251, 120, 100, 193, 110, 88, 45, 168, 55, 149, 85, 175, 207, + 111, 182, 206, 200, 232, 10, 51, 181, 66, 7, 9, 40, 115, 223, + 70, 8, 166, 171, 239, 66, 225, 46, 41, 79, 23, 32, 141, 72, + 3, 3, 4, 92, 234, 125, 52, 216, 191, 138, 214, 198, 13, 180, + 149, 62, 99, 100, 27, 24, 195, 31, 190, 146, 163, 123, 89, 152, + 191, 219, 227, 100, 187, 170, 203, 23, 148, 64, 72, 218, 253, 158, + 17, 22, 117, 150, 6, 173, 195, 2, 62, 8, 3, 49, 49, 100, + 163, 125, 181, 9, 143, 168, 137, 174, 98, 248, 91, 26, 254, 12, + 50, 5, 136, 82, 111, 57, 143, 44, 165, 18, 163, 52, 215, 127, + 86, 115, 249, 19, 182, 214, 175, 129, 194, 183, 87, 105, 148, 146, + 166, 14, 226, 187, 29, 130, 163, 62, 35, 79, 71, 88, 169, 201, + 21, 106, 199, 69, 66, 161, 242, 253, 200, 227, 189, 110, 23, 127, + 134, 210, 123, 128, 150, 40, 184, 36, 39, 0, 169, 149, 184, 161, + 41, 232, 58, 91, 164, 172, 133, 20, 177, 115, 150, 16, 198, 165, + 211, 42, 229, 0, 204, 57, 166, 206, 247, 186, 173, 157, 201, 129, + 227, 132, 16, 64, 217, 50, 87, 118, 184, 46, 126, 19, 124, 146, + 218, 151, 46, 115, 70, 129, 86, 140, 25, 217, 76, 97, 66, 241, + 254, 230, 4, 44, 30, 104, 109, 214, 187, 149, 25, 145, 87, 136, + 190, 13, 138, 82, 216, 39, 144, 247, 181, 183, 211, 155, 30, 113, + 94, 52, 144, 116, 179, 198, 242, 112, 168, 191, 39, 24, 124, 66, + 29, 76, 140, 186, 69, 247, 136, 207, 172, 175, 192, 93, 190, 11, + 209, 208, 80, 53, 39, 186, 69, 174, 32, 31, 21, 218, 48, 161, + 73, 8, 159, 151, 74, 155, 219, 124, 71, 54, 96, 229, 8, 20, + 0, 88, 186, 228, 7, 32, 185, 150, 103, 126, 32, 173, 171, 218, + 151, 226, 81, 110, 100, 203, 184, 54, 35, 231, 128, 146, 121, 191, + 231, 27, 233, 11, 183, 213, 230, 23, 149, 141, 37, 67, 156, 132, + 69, 192, 29, 59, 143, 104, 174, 226, 159, 110, 108, 46, 121, 222, + 254, 131, 101, 37, 172, 170, 55, 242, 47, 248, 44, 17, 45, 65, + 29, 215, 74, 96, 185, 120, 81, 231, 173, 79, 117, 94, 163, 231, + 28, 249, 234, 117, 79, 137, 185, 23, 202, 92, 247, 156, 36, 194, + 56, 221, 21, 28, 25, 188, 214, 224, 43, 126, 228, 129, 246, 26, + 114, 1, 152, 82, 62, 237, 214, 255, 60, 243, 134, 253, 31, 67, + 71, 158, 40, 79, 115, 10, 58, 97, 187, 197, 82, 120, 252, 18, + 126, 13, 67, 168, 16, 51, 206, 48, 34, 113, 108, 207, 38, 148, + 219, 29, 183, 168, 165, 197, 220, 90, 71, 231, 11, 169, 64, 26, + 213, 35, 36, 91, 118, 149, 166, 139, 201, 4, 159, 33, 137, 241, + 106, 91, 180, 188, 14, 163, 77, 86, 60, 166, 7, 132, 125, 122, + 139, 210, 221, 107, 58, 212, 47, 201, 37, 23, 204, 95, 166, 28, + 174, 125, 202, 8, 72, 97, 88, 190, 221, 216, 51, 115, 188, 185, + 250, 244, 101, 165, 92, 162, 238, 30, 39, 163, 63, 230, 30, 174, + 142, 241, 26, 187, 138, 240, 207, 250, 248, 42, 48, 151, 249, 209, + 129, 43, 113, 246, 36, 119, 23, 130, 110, 163, 19, 209, 255, 67, + 28, 137, 30, 35, 23, 23, 177, 222, 213, 159, 204, 146, 96, 126, + 96, 227, 179, 54, 81, 235, 3, 112, 115, 86, 99, 104, 190, 238, + 242, 223, 181, 139, 30, 128, 193, 204, 51, 48, 218, 128, 77, 178, + 245, 140, 250, 253, 253, 195, 127, 14, 88, 99, 64, 163, 94, 219, + 8, 3, 212, 59, 55, 65, 203, 75, 221, 79, 53, 3, 82, 42, + 181, 12, 148, 228, 84, 242, 170, 208, 106, 194, 108, 41, 165, 252, + 72, 64, 254, 45, 161, 52, 60, 68, 90, 153, 67, 36, 249, 111, + 201, 181, 118, 156, 191, 140, 138, 238, 186, 10, 239, 80, 10, 197, + 95, 153, 56, 61, 118, 36, 155, 139, 52, 127, 250, 30, 92, 15, + 10, 31, 101, 141, 229, 83, 4, 67, 147, 146, 2, 139, 103, 39, + 6, 109, 76, 33, 78, 14, 58, 216, 137, 23, 201, 230, 41, 189, + 207, 80, 201, 74, 213, 240, 30, 163, 165, 93, 197, 17, 86, 2, + 48, 5, 5, 168, 96, 247, 42, 111, 99, 70, 162, 164, 4, 229, + 182, 197, 119, 194, 147, 132, 124, 9, 225, 40, 25, 63, 106, 165, + 33, 124, 72, 30, 216, 90, 94, 157, 215, 243, 214, 63, 113, 241, + 77, 180, 8, 202, 0, 145, 153, 109, 128, 53, 67, 24, 243, 132, + 77, 47, 127, 209, 127, 193, 166, 133, 31, 37, 202, 224, 234, 38, + 47, 111, 34, 210, 123, 149, 224, 71, 225, 111, 137, 225, 99, 212, + 41, 93, 43, 107, 20, 251, 206, 131, 223, 202, 188, 20, 145, 4, + 145, 69, 81, 159, 188, 72, 128, 158, 24, 38, 122, 70, 36, 25, + 20, 208, 164, 106, 146, 184, 102, 52, 60, 97, 141, 174, 2, 59, + 103, 55, 36, 245, 101, 156, 242, 82, 84, 59, 40, 78, 24, 170, + 240, 238, 73, 115, 214, 221, 114, 93, 25, 25, 211, 107, 80, 232, + 216, 174, 125, 189, 14, 93, 71, 99, 196, 23, 218, 8, 169, 68, + 235, 213, 166, 40, 178, 231, 69, 59, 29, 33, 47, 89, 57, 225, + 118, 89, 206, 238, 80, 5, 43, 7, 192, 79, 222, 164, 253, 174, + 15, 197, 216, 219, 216, 225, 247, 94, 207, 11, 52, 173, 170, 69, + 129, 85, 16, 9, 180, 101, 42, 254, 119, 150, 39, 243, 55, 24, + 216, 221, 191, 195, 109, 111, 58, 36, 188, 51, 26, 237, 163, 66, + 243, 212, 23, 212, 110, 73, 37, 144, 181, 32, 182, 113, 54, 43, + 16, 207, 167, 237, 210, 122, 252, 121, 146, 115, 25, 170, 94, 114, + 204, 73, 158, 158, 162, 126, 57, 128, 139, 150, 30, 217, 217, 164, + 54, 141, 22, 254, 143, 214, 164, 237, 81, 187, 170, 73, 84, 145, + 122, 253, 143, 250, 210, 229, 26, 237, 158, 194, 53, 100, 174, 152, + 52, 81, 224, 131, 108, 250, 52, 116, 58, 53, 213, 197, 40, 84, + 144, 175, 34, 163, 106, 12, 63, 6, 255, 222, 46, 46, 132, 28, + 159, 20, 54, 244, 178, 231, 123, 68, 16, 247, 99, 248, 14, 252, + 154, 112, 207, 100, 158, 52, 23, 90, 155, 152, 199, 234, 178, 45, + 204, 52, 142, 145, 53, 177, 111, 167, 6, 116, 24, 52, 151, 116, + 183, 71, 144, 188, 123, 145, 87, 137, 202, 103, 63, 30, 186, 51, + 129, 114, 44, 35, 70, 106, 109, 204, 72, 7, 112, 231, 119, 139, + 126, 247, 22, 122, 20, 196, 71, 49, 125, 203, 134, 95, 140, 238, + 161, 45, 128, 127, 203, 72, 48, 91, 173, 220, 29, 68, 111, 112, + 91, 75, 216, 201, 62, 217, 127, 185, 82, 56, 39, 220, 254, 117, + 114, 221, 239, 15, 117, 250, 24, 145, 255, 104, 64, 105, 63, 150, + 47, 19, 109, 36, 237, 237, 138, 1, 31, 225, 200, 113, 67, 27, + 104, 47, 244, 2, 228, 209, 170, 157, 172, 26, 143, 106, 174, 219, + 45, 106, 46, 183, 151, 26, 7, 39, 194, 128, 100, 253, 206, 35, + 236, 58, 220, 213, 120, 108, 156, 171, 57, 246, 78, 107, 10, 22, + 188, 155, 75, 89, 85, 67, 103, 0, 111, 191, 219, 111, 206, 242, + 164, 165, 90, 251, 117, 211, 252, 41, 205, 148, 9, 233, 237, 63, + 126, 153, 245, 189, 16, 124, 147, 19, 58, 36, 195, 35, 89, 208, + 134, 45, 174, 51, 211, 182, 182, 53, 164, 10, 95, 126, 159, 159, + 19, 252, 18, 177, 149, 30, 66, 238, 229, 178, 209, 71, 198, 101, + 251, 13, 61, 184, 244, 151, 150, 158, 100, 171, 89, 248, 64, 237, + 113, 100, 196, 220, 113, 135, 7, 56, 2, 83, 104, 240, 167, 50, + 48, 178, 109, 33, 216, 225, 138, 143, 41, 215, 81, 237, 42, 237, + 5, 127, 46, 123, 116, 42, 77, 141, 172, 106, 163, 161, 12, 20, + 120, 120, 231, 42, 54, 215, 216, 146, 62, 226, 3, 60, 79, 91, + 104, 57, 192, 122, 210, 61, 200, 21, 31, 154, 35, 69, 80, 179, + 230, 219, 68, 28, 37, 208, 221, 109, 243, 231, 12, 173, 184, 74, + 167, 55, 230, 89, 251, 247, 174, 149, 10, 112, 27, 226, 41, 107, + 255, 101, 222, 125, 246, 210, 186, 21, 22, 252, 18, 60, 79, 9, + 230, 179, 29, 253, 4, 21, 20, 0, 48, 133, 76, 236, 153, 107, + 198, 137, 83, 39, 154, 90, 93, 121, 226, 74, 58, 157, 196, 43, + 94, 234, 66, 197, 198, 238, 119, 194, 165, 79, 231, 7, 95, 13, + 91, 132, 140, 100, 67, 204, 7, 217, 47, 211, 67, 200, 51, 11, + 163, 172, 210, 84, 43, 128, 35, 76, 7, 208, 73, 223, 123, 76, + 26, 138, 23, 67, 78, 38, 225, 39, 162, 227, 146, 43, 88, 127, + 39, 171, 150, 30, 185, 187, 109, 5, 3, 203, 181, 164, 98, 146, + 202, 136, 194, 29, 200, 118, 182, 231, 210, 223, 230, 132, 18, 151, + 61, 195, 164, 162, 69, 50, 6, 47, 161, 239, 3, 195, 252, 128, + 232, 201, 157, 5, 41, 45, 246, 151, 130, 190, 64, 244, 53, 29, + 15, 173, 192, 173, 91, 102, 139, 91, 125, 76, 75, 46, 211, 50, + 83, 117, 212, 171, 245, 100, 134, 83, 60, 1, 249, 75, 6, 58, + 87, 115, 204, 118, 183, 118, 58, 219, 196, 118, 238, 80, 128, 209, + 70, 22, 164, 116, 245, 104, 130, 30, 230, 17, 48, 131, 112, 124, + 16, 69, 31, 132, 171, 1, 146, 249, 208, 189, 216, 76, 109, 146, + 223, 114, 33, 201, 181, 129, 93, 115, 192, 96, 238, 252, 173, 97, + 77, 165, 93, 64, 96, 160, 185, 99, 8, 148, 172, 175, 212, 80, + 224, 164, 189, 32, 119, 23, 74, 47, 146, 141, 128, 232, 56, 57, + 120, 113, 104, 163, 250, 11, 66, 99, 14, 81, 222, 137, 234, 46, + 33, 188, 169, 5, 1, 210, 44, 135, 229, 169, 75, 8, 67, 109, + 220, 104, 168, 226, 225, 244, 4, 214, 13, 112, 82, 173, 171, 103, + 100, 82, 170, 213, 42, 58, 200, 215, 97, 198, 123, 132, 104, 72, + 76, 143, 172, 28, 217, 155, 207, 19, 228, 130, 120, 188, 121, 28, + 203, 69, 31, 172, 20, 156, 90, 201, 65, 25, 132, 214, 53, 224, + 217, 229, 132, 52, 22, 2, 148, 97, 198, 43, 7, 219, 137, 139, + 156, 128, 136, 187, 48, 28, 193, 38, 63, 98, 36, 102, 0, 166, + 213, 85, 43, 20, 52, 231, 214, 83, 152, 61, 92, 48, 169, 54, + 48, 94, 241, 188, 235, 61, 65, 55, 16, 88, 19, 149, 123, 142, + 207, 85, 169, 119, 210, 176, 61, 103, 250, 37, 92, 230, 43, 24, + 240, 46, 54, 224, 200, 154, 138, 234, 132, 189, 214, 81, 192, 111, + 126, 15, 237, 16, 200, 166, 37, 65, 125, 82, 99, 210, 43, 168, + 239, 140, 0, 163, 168, 86, 126, 77, 42, 24, 161, 58, 128, 4, + 145, 105, 194, 52, 24, 160, 139, 41, 168, 32, 144, 95, 248, 141, + 211, 28, 199, 177, 72, 3, 185, 9, 52, 185, 47, 0, 213, 173, + 191, 249, 255, 219, 79, 88, 17, 37, 207, 99, 157, 75, 227, 117, + 174, 239, 207, 122, 199, 207, 69, 218, 60, 36, 14, 105, 209, 172, + 105, 208, 129, 145, 73, 149, 105, 19, 86, 170, 13, 61, 127, 84, + 90, 91, 179, 157, 47, 155, 187, 138, 145, 111, 66, 131, 46, 190, + 185, 169, 203, 197, 46, 187, 100, 52, 122, 90, 227, 35, 87, 26, + 144, 167, 115, 216, 240, 155, 154, 93, 157, 112, 40, 76, 65, 126, + 91, 113, 53, 16, 8, 24, 81, 253, 229, 86, 75, 23, 41, 36, + 140, 49, 119, 136, 175, 243, 31, 18, 117, 228, 247, 240, 166, 188, + 169, 186, 94, 94, 238, 189, 233, 160, 5, 118, 41, 92, 77, 119, + 49, 53, 146, 68, 212, 93, 186, 67, 135, 156, 179, 217, 114, 148, + 91, 242, 193, 106, 182, 22, 180, 1, 86, 46, 15, 74, 118, 218, + 139, 85, 245, 222, 207, 210, 165, 45, 34, 189, 86, 145, 239, 26, + 174, 233, 192, 210, 111, 175, 118, 208, 30, 134, 58, 41, 170, 8, + 137, 150, 128, 158, 174, 123, 180, 31, 116, 180, 238, 2, 12, 43, + 214, 191, 37, 237, 19, 28, 179, 91, 80, 206, 253, 165, 192, 103, + 251, 78, 152, 189, 194, 169, 122, 133, 170, 53, 31, 17, 86, 112, + 161, 78, 245, 183, 124, 176, 131, 29, 59, 104, 74, 118, 214, 197, + 244, 146, 146, 40, 135, 78, 120, 81, 241, 173, 16, 97, 31, 209, + 213, 35, 152, 73, 49, 25, 173, 224, 115, 4, 193, 159, 245, 25, + 147, 146, 7, 59, 150, 128, 106, 29, 14, 125, 233, 151, 232, 83, + 227, 212, 37, 8, 153, 194, 130, 38, 203, 150, 122, 42, 61, 215, + 45, 246, 251, 123, 65, 49, 3, 163, 206, 71, 161, 207, 209, 226, + 194, 45, 38, 122, 30, 201, 136, 69, 212, 128, 55, 219, 19, 34, + 24, 101, 204, 36, 100, 189, 245, 167, 38, 131, 39, 180, 102, 70, + 92, 203, 83, 112, 161, 64, 40, 212, 140, 68, 220, 79, 95, 238, + 188, 96, 20, 16, 76, 103, 32, 207, 112, 235, 142, 185, 86, 54, + 182, 17, 73, 135, 217, 37, 202, 14, 151, 125, 157, 190, 28, 8, + 207, 149, 80, 196, 73, 21, 249, 176, 223, 59, 113, 183, 241, 90, + 160, 166, 72, 143, 192, 120, 76, 141, 96, 131, 211, 240, 196, 6, + 140, 145, 150, 122, 250, 160, 45, 96, 1, 103, 81, 167, 107, 45, + 83, 42, 23, 213, 130, 198, 234, 37, 99, 151, 34, 83, 181, 68, + 113, 83, 1, 3, 31, 48, 208, 132, 138, 124, 60, 133, 235, 68, + 92, 93, 216, 119, 175, 25, 133, 62, 139, 37, 253, 91, 228, 128, + 99, 91, 188, 172, 29, 173, 189, 88, 74, 121, 215, 148, 1, 130, + 192, 33, 113, 184, 5, 123, 153, 27, 178, 36, 106, 64, 144, 49, + 225, 41, 132, 104, 148, 210, 171, 93, 170, 208, 56, 223, 65, 71, + 253, 60, 251, 36, 202, 33, 20, 92, 202, 241, 229, 144, 107, 15, + 132, 105, 100, 140, 205, 57, 26, 62, 16, 13, 177, 16, 8, 249, + 87, 159, 170, 31, 185, 20, 103, 126, 114, 24, 69, 78, 12, 112, + 173, 150, 149, 177, 100, 187, 16, 147, 9, 233, 76, 194, 2, 91, + 207, 50, 54, 97, 143, 42, 12, 31, 176, 16, 78, 70, 114, 148, + 109, 106, 245, 178, 107, 225, 79, 129, 178, 194, 39, 33, 203, 143, + 194, 48, 22, 240, 229, 243, 14, 234, 234, 8, 100, 58, 70, 192, + 198, 44, 208, 125, 60, 29, 200, 178, 12, 189, 93, 23, 49, 189, + 67, 15, 86, 8, 202, 173, 230, 157, 239, 43, 126, 151, 19, 124, + 41, 11, 54, 197, 190, 75, 97, 218, 68, 45, 172, 68, 155, 236, + 170, 218, 54, 191, 101, 243, 19, 198, 187, 107, 196, 168, 25, 201, + 51, 122, 244, 105, 12, 182, 174, 212, 240, 29, 99, 43, 10, 204, + 92, 207, 176, 116, 64, 78, 241, 64, 234, 43, 10, 79, 180, 234, + 121, 15, 139, 179, 79, 0, 130, 25, 129, 18, 35, 154, 25, 66, + 255, 89, 67, 74, 243, 14, 171, 81, 89, 92, 198, 139, 13, 117, + 241, 136, 224, 173, 98, 203, 243, 52, 121, 71, 73, 5, 230, 139, + 94, 0, 201, 138, 86, 177, 196, 141, 100, 106, 190, 115, 6, 205, + 64, 253, 171, 250, 56, 234, 153, 182, 158, 0, 131, 144, 231, 49, + 71, 130, 58, 48, 251, 99, 155, 163, 58, 233, 22, 149, 9, 166, + 82, 78, 189, 198, 254, 239, 136, 202, 108, 169, 98, 97, 215, 212, + 232, 230, 239, 34, 6, 145, 121, 150, 69, 42, 130, 44, 13, 163, + 222, 188, 222, 175, 136, 96, 168, 74, 97, 35, 86, 250, 233, 47, + 2, 160, 208, 222, 124, 132, 194, 241, 46, 90, 67, 108, 176, 140, + 198, 49, 54, 99, 128, 224, 60, 214, 120, 21, 146, 212, 245, 109, + 142, 237, 184, 28, 119, 105, 10, 192, 239, 219, 85, 78, 50, 230, + 107, 63, 227, 60, 104, 85, 53, 148, 106, 196, 148, 139, 113, 151, + 135, 199, 92, 242, 237, 113, 10, 163, 89, 11, 191, 23, 32, 71, + 137, 239, 187, 170, 76, 94, 149, 212, 59, 233, 113, 30, 154, 171, + 81, 159, 241, 159, 18, 233, 179, 92, 185, 93, 239, 243, 96, 18, + 66, 216, 100, 212, 36, 96, 73, 87, 60, 2, 166, 27, 169, 145, + 241, 190, 119, 150, 182, 7, 113, 75, 252, 251, 182, 81, 215, 201, + 112, 108, 211, 169, 198, 199, 128, 125, 58, 69, 38, 223, 149, 186, + 53, 21, 183, 253, 144, 130, 135, 154, 0, 164, 109, 203, 167, 129, + 11, 75, 228, 187, 162, 130, 159, 96, 76, 116, 184, 75, 197, 110, + 57, 15, 15, 76, 71, 60, 60, 142, 126, 247, 41, 22, 57, 45, + 45, 239, 123, 192, 52, 105, 78, 167, 17, 61, 83, 240, 88, 255, + 182, 90, 191, 181, 25, 157, 186, 226, 95, 25, 61, 55, 97, 81, + 35, 90, 35, 181, 19, 25, 77, 150, 99, 32, 113, 78, 182, 85, + 157, 115, 135, 219, 176, 241, 148, 226, 235, 183, 124, 112, 96, 130, + 202, 152, 137, 11, 243, 210, 184, 107, 186, 197, 28, 253, 127, 252, + 87, 242, 70, 234, 80, 53, 57, 106, 15, 231, 87, 66, 234, 168, + 113, 112, 60, 255, 109, 79, 218, 37, 175, 218, 143, 52, 140, 149, + 21, 113, 15, 108, 138, 47, 40, 69, 144, 168, 142, 50, 5, 180, + 130, 107, 222, 225, 184, 46, 69, 168, 16, 250, 253, 190, 71, 208, + 137, 21, 166, 138, 67, 34, 236, 19, 176, 29, 200, 214, 157, 8, + 102, 166, 104, 217, 24, 14, 94, 29, 48, 81, 196, 185, 61, 135, + 228, 30, 53, 139, 124, 24, 144, 109, 184, 28, 87, 74, 216, 163, + 47, 135, 244, 241, 171, 206, 95, 63, 124, 173, 91, 209, 135, 103, + 81, 196, 118, 156, 239, 164, 242, 165, 223, 116, 176, 2, 169, 37, + 9, 79, 14, 188, 93, 7, 128, 159, 58, 36, 183, 94, 167, 29, + 163, 190, 67, 234, 227, 17, 57, 48, 223, 245, 134, 183, 28, 179, + 173, 232, 171, 53, 1, 193, 136, 50, 50, 125, 180, 61, 191, 189, + 213, 127, 191, 111, 55, 84, 38, 60, 92, 105, 114, 185, 252, 224, + 106, 162, 25, 10, 244, 147, 83, 67, 205, 14, 93, 150, 67, 185, + 55, 104, 72, 21, 1, 247, 47, 194, 29, 252, 113, 13, 111, 18, + 244, 44, 137, 176, 134, 73, 57, 134, 162, 62, 224, 60, 101, 53, + 195, 16, 199, 137, 136, 113, 251, 226, 216, 128, 176, 177, 66, 221, + 57, 8, 163, 175, 68, 234, 254, 240, 94, 73, 73, 146, 16, 79, + 159, 77, 73, 119, 68, 66, 150, 203, 80, 106, 84, 197, 236, 218, + 159, 130, 230, 142, 66, 214, 187, 130, 178, 116, 46, 8, 91, 34, + 76, 218, 106, 1, 114, 175, 171, 31, 186, 9, 149, 174, 31, 125, + 22, 139, 131, 22, 174, 200, 77, 84, 54, 29, 253, 36, 52, 26, + 112, 65, 43, 74, 0, 230, 209, 198, 33, 218, 85, 49, 126, 113, + 240, 98, 21, 65, 150, 145, 14, 38, 211, 230, 244, 164, 7, 195, + 91, 55, 33, 39, 170, 195, 198, 203, 145, 80, 50, 243, 74, 6, + 223, 148, 181, 36, 41, 141, 140, 15, 177, 20, 189, 186, 15, 58, + 106, 228, 54, 65, 85, 139, 236, 234, 121, 129, 249, 95, 156, 41, + 9, 78, 232, 41, 39, 219, 125, 103, 45, 218, 105, 122, 8, 168, + 230, 232, 52, 5, 42, 175, 144, 59, 140, 11, 134, 140, 122, 3, + 20, 232, 149, 158, 119, 229, 177, 145, 98, 60, 212, 83, 70, 102, + 112, 79, 215, 163, 222, 3, 39, 157, 166, 115, 227, 65, 201, 42, + 86, 19, 204, 102, 199, 171, 184, 145, 130, 31, 38, 241, 198, 148, + 1, 152, 232, 7, 101, 140, 160, 188, 172, 248, 68, 165, 10, 169, + 253, 43, 142, 196, 74, 19, 11, 123, 195, 59, 221, 131, 250, 202, + 185, 236, 149, 169, 171, 39, 66, 233, 44, 16, 165, 146, 40, 17, + 166, 3, 194, 61, 238, 10, 64, 185, 170, 153, 99, 154, 20, 166, + 165, 112, 103, 142, 214, 212, 8, 63, 170, 25, 237, 177, 118, 224, + 30, 189, 198, 124, 85, 25, 152, 9, 153, 184, 93, 38, 230, 4, + 97, 199, 180, 210, 186, 221, 104, 27, 156, 91, 16, 196, 18, 126, + 112, 209, 110, 93, 114, 130, 216, 137, 203, 41, 22, 126, 66, 51, + 103, 140, 82, 235, 64, 224, 148, 111, 136, 26, 49, 87, 56, 255, + 120, 0, 141, 204, 81, 143, 180, 141, 173, 103, 79, 196, 43, 38, + 154, 158, 249, 234, 118, 65, 116, 123, 204, 84, 115, 195, 100, 3, + 15, 247, 132, 24, 94, 88, 102, 86, 89, 225, 159, 113, 123, 203, + 148, 5, 8, 94, 155, 72, 117, 72, 115, 117, 158, 3, 199, 135, + 170, 107, 128, 185, 114, 118, 138, 32, 226, 111, 69, 174, 179, 246, + 35, 173, 250, 9, 86, 186, 132, 39, 157, 76, 132, 234, 230, 78, + 157, 221, 192, 89, 39, 62, 131, 127, 62, 34, 174, 139, 209, 199, + 115, 189, 138, 37, 154, 132, 228, 5, 44, 38, 64, 11, 154, 165, + 112, 190, 188, 48, 231, 52, 3, 178, 27, 73, 23, 71, 24, 165, + 39, 235, 68, 201, 97, 10, 158, 178, 132, 143, 88, 21, 252, 234, + 182, 178, 58, 6, 44, 134, 58, 191, 150, 173, 236, 245, 253, 114, + 115, 26, 34, 207, 84, 92, 29, 107, 244, 200, 228, 98, 25, 150, + 202, 185, 249, 139, 94, 192, 138, 143, 243, 140, 20, 44, 233, 33, + 36, 227, 14, 214, 51, 157, 2, 99, 60, 191, 207, 14, 178, 6, + 132, 32, 35, 73, 60, 84, 185, 170, 93, 18, 202, 204, 86, 148, + 142, 136, 11, 44, 91, 49, 53, 213, 6, 250, 14, 40, 6, 180, + 37, 65, 163, 61, 3, 4, 14, 29, 242, 134, 72, 113, 148, 116, + 138, 11, 93, 21, 111, 19, 179, 254, 147, 219, 92, 10, 6, 133, + 128, 56, 78, 240, 138, 70, 47, 92, 187, 239, 85, 109, 85, 132, + 56, 215, 254, 82, 115, 147, 17, 20, 73, 89, 170, 210, 130, 120, + 104, 31, 91, 204, 68, 24, 212, 250, 128, 243, 71, 11, 33, 95, + 98, 219, 141, 46, 121, 240, 19, 47, 113, 233, 245, 108, 170, 23, + 182, 221, 249, 139, 92, 23, 131, 171, 255, 228, 210, 149, 43, 154, + 97, 36, 90, 90, 61, 100, 147, 214, 142, 198, 52, 75, 5, 227, + 136, 123, 89, 125, 136, 221, 201, 245, 25, 49, 61, 66, 36, 165, + 154, 215, 41, 24, 178, 252, 62, 98, 219, 135, 102, 225, 80, 127, + 26, 235, 57, 93, 230, 163, 191, 85, 6, 16, 249, 251, 254, 29, + 250, 103, 41, 163, 117, 167, 31, 8, 235, 159, 60, 165, 123, 142, + 192, 231, 98, 150, 87, 244, 102, 47, 90, 128, 46, 106, 20, 212, + 99, 159, 58, 22, 31, 109, 11, 172, 86, 74, 144, 94, 232, 102, + 161, 36, 115, 136, 38, 6, 33, 34, 72, 131, 239, 97, 245, 161, + 172, 92, 226, 185, 71, 200, 177, 113, 39, 120, 171, 48, 48, 136, + 32, 69, 203, 81, 232, 44, 205, 62, 89, 221, 169, 188, 227, 21, + 90, 251, 158, 74, 53, 195, 3, 198, 133, 13, 243, 112, 44, 148, + 203, 227, 129, 201, 82, 138, 249, 210, 204, 63, 32, 168, 78, 57, + 30, 65, 242, 39, 30, 90, 147, 104, 121, 143, 62, 227, 183, 109, + 70, 205, 14, 40, 8, 74, 198, 88, 51, 220, 217, 40, 90, 135, + 77, 216, 167, 172, 151, 15, 2, 42, 107, 105, 54, 198, 152, 225, + 115, 204, 97, 64, 251, 186, 81, 183, 16, 243, 168, 233, 4, 68, + 11, 14, 95, 13, 224, 92, 224, 130, 195, 236, 176, 22, 176, 159, + 76, 49, 106, 197, 19, 169, 182, 124, 242, 198, 138, 239, 152, 81, + 239, 144, 25, 13, 255, 120, 77, 148, 59, 224, 110, 125, 106, 174, + 135, 128, 218, 38, 79, 53, 180, 120, 55, 62, 128, 127, 103, 48, + 230, 51, 250, 67, 194, 162, 135, 33, 95, 39, 133, 129, 211, 189, + 228, 20, 178, 246, 136, 94, 83, 73, 174, 241, 169, 121, 42, 128, + 139, 49, 81, 121, 146, 107, 85, 108, 138, 6, 163, 19, 227, 156, + 205, 48, 178, 215, 101, 122, 25, 172, 96, 5, 156, 8, 161, 228, + 114, 188, 78, 148, 238, 145, 17, 56, 201, 89, 234, 153, 47, 33, + 180, 141, 18, 68, 193, 97, 115, 243, 2, 45, 12, 142, 32, 254, + 201, 13, 92, 116, 216, 124, 230, 227, 130, 196, 155, 175, 227, 252, + 243, 46, 75, 10, 154, 173, 85, 188, 228, 170, 4, 65, 228, 123, + 84, 84, 115, 179, 10, 23, 90, 149, 181, 66, 87, 118, 214, 89, + 80, 150, 142, 249, 153, 214, 238, 83, 56, 48, 102, 58, 0, 250, + 75, 189, 162, 164, 22, 102, 75, 81, 37, 62, 222, 253, 235, 29, + 121, 186, 240, 252, 87, 35, 81, 94, 96, 194, 105, 45, 247, 4, + 207, 194, 247, 34, 67, 61, 180, 77, 176, 81, 74, 167, 122, 27, + 7, 144, 50, 182, 104, 116, 21, 136, 147, 196, 24, 73, 135, 129, + 230, 172, 223, 28, 228, 196, 180, 52, 201, 135, 199, 236, 118, 48, + 130, 130, 222, 130, 44, 24, 120, 58, 250, 244, 231, 68, 165, 16, + 113, 250, 215, 124, 74, 111, 10, 81, 46, 78, 210, 188, 33, 38, + 3, 197, 51, 163, 148, 38, 243, 45, 223, 47, 108, 219, 53, 11, + 175, 46, 207, 174, 121, 229, 241, 71, 42, 126, 157, 100, 250, 43, + 107, 119, 129, 251, 174, 49, 212, 239, 202, 35, 28, 26, 116, 203, + 181, 129, 122, 231, 156, 10, 54, 218, 229, 208, 240, 183, 84, 133, + 254, 151, 70, 58, 56, 129, 179, 126, 225, 178, 207, 28, 152, 51, + 87, 29, 215, 164, 193, 73, 7, 237, 19, 29, 167, 19, 214, 168, + 160, 46, 77, 165, 38, 170, 12, 146, 251, 132, 91, 224, 64, 196, + 74, 65, 151, 247, 103, 225, 253, 51, 123, 254, 213, 250, 211, 62, + 188, 48, 129, 118, 172, 124, 178, 136, 218, 0, 252, 40, 70, 230, + 31, 25, 152, 111, 10, 61, 74, 237, 17, 139, 233, 160, 12, 12, + 100, 66, 83, 61, 154, 146, 87, 121, 214, 100, 93, 107, 176, 64, + 208, 44, 218, 190, 154, 251, 40, 23, 189, 133, 113, 203, 177, 203, + 4, 18, 230, 132, 158, 229, 32, 237, 170, 218, 96, 169, 231, 103, + 102, 86, 125, 170, 29, 88, 43, 29, 92, 184, 187, 173, 194, 103, + 16, 182, 109, 240, 9, 53, 188, 197, 200, 224, 221, 140, 48, 245, + 159, 229, 141, 56, 231, 233, 88, 249, 218, 78, 73, 12, 80, 131, + 167, 143, 52, 50, 235, 151, 243, 140, 210, 155, 223, 94, 29, 227, + 12, 129, 52, 10, 223, 139, 136, 89, 118, 113, 247, 171, 238, 227, + 56, 143, 251, 81, 172, 160, 21, 75, 192, 10, 8, 43, 152, 240, + 114, 55, 209, 104, 8, 159, 0, 43, 49, 155, 57, 244, 152, 27, + 165, 81, 185, 190, 224, 178, 51, 106, 27, 4, 6, 200, 210, 80, + 57, 247, 11, 90, 139, 68, 86, 203, 120, 89, 233, 143, 135, 93, + 177, 134, 224, 142, 167, 220, 193, 53, 198, 229, 114, 90, 13, 147, + 124, 229, 249, 222, 179, 174, 253, 144, 0, 68, 182, 203, 238, 50, + 93, 38, 157, 103, 200, 83, 249, 114, 227, 141, 181, 220, 5, 56, + 175, 70, 225, 148, 230, 14, 245, 178, 217, 126, 189, 218, 36, 214, + 131, 177, 129, 25, 161, 24, 237, 14, 187, 165, 196, 1, 57, 112, + 122, 55, 111, 241, 33, 37, 221, 237, 47, 30, 38, 59, 196, 25, + 0, 51, 253, 104, 194, 105, 106, 230, 141, 104, 134, 174, 223, 14, + 92, 225, 32, 72, 62, 157, 142, 19, 197, 204, 12, 115, 58, 85, + 159, 75, 139, 128, 46, 132, 145, 94, 138, 38, 128, 40, 184, 37, + 68, 240, 84, 140, 20, 187, 190, 241, 116, 103, 122, 80, 20, 92, + 56, 19, 123, 49, 223, 240, 6, 82, 220, 63, 64, 207, 95, 13, + 208, 35, 148, 69, 233, 28, 244, 16, 195, 77, 165, 186, 173, 84, + 32, 55, 102, 2, 5, 86, 199, 143, 42, 150, 19, 192, 83, 48, + 10, 241, 246, 47, 211, 35, 65, 216, 139, 141, 10, 50, 78, 75, + 51, 51, 26, 243, 152, 234, 159, 130, 116, 90, 81, 9, 144, 15, + 29, 187, 46, 105, 137, 77, 137, 228, 210, 84, 172, 95, 127, 226, + 162, 221, 160, 38, 218, 5, 115, 42, 70, 227, 218, 64, 142, 96, + 19, 33, 133, 159, 193, 160, 249, 243, 33, 10, 114, 131, 186, 102, + 93, 93, 251, 212, 110, 176, 136, 184, 167, 138, 200, 76, 218, 157, + 213, 66, 162, 156, 253, 179, 61, 61, 237, 105, 114, 138, 231, 100, + 107, 71, 167, 86, 52, 10, 244, 185, 144, 42, 204, 251, 140, 87, + 137, 255, 228, 30, 118, 7, 222, 172, 249, 16, 6, 81, 57, 0, + 152, 137, 130, 210, 158, 191, 86, 205, 101, 202, 208, 236, 204, 69, + 156, 196, 118, 188, 23, 253, 70, 170, 98, 100, 25, 24, 135, 213, + 230, 39, 24, 64, 211, 163, 46, 176, 243, 126, 251, 28, 14, 124, + 61, 48, 176, 238, 219, 230, 6, 65, 187, 156, 164, 40, 160, 132, + 46, 202, 100, 190, 18, 54, 55, 45, 112, 215, 217, 112, 227, 63, + 7, 65, 7, 25, 64, 76, 215, 66, 84, 86, 243, 4, 241, 65, + 9, 234, 230, 212, 150, 176, 101, 14, 55, 189, 83, 101, 21, 64, + 175, 37, 44, 34, 83, 64, 184, 126, 76, 127, 32, 50, 35, 39, + 164, 29, 28, 197, 0, 48, 95, 194, 180, 194, 200, 66, 191, 2, + 162, 198, 20, 72, 133, 95, 200, 9, 63, 47, 186, 119, 189, 165, + 53, 225, 39, 74, 79, 210, 176, 52, 178, 160, 104, 104, 203, 120, + 71, 31, 176, 57, 137, 192, 14, 205, 11, 148, 90, 215, 26, 170, + 101, 91, 131, 143, 5, 152, 74, 208, 102, 87, 113, 153, 116, 43, + 238, 68, 45, 100, 213, 200, 100, 121, 140, 76, 153, 186, 56, 185, + 70, 88, 155, 79, 64, 45, 109, 224, 103, 250, 133, 101, 181, 211, + 171, 90, 20, 51, 206, 128, 228, 201, 168, 175, 142, 130, 98, 179, + 51, 101, 119, 105, 166, 190, 190, 210, 34, 67, 171, 229, 52, 101, + 242, 93, 73, 141, 93, 157, 147, 220, 38, 245, 4, 44, 172, 149, + 202, 245, 230, 253, 180, 14, 160, 6, 67, 169, 181, 51, 219, 196, + 193, 102, 80, 118, 197, 119, 160, 232, 133, 125, 71, 236, 214, 233, + 250, 234, 211, 138, 26, 81, 160, 53, 60, 250, 177, 92, 114, 185, + 116, 54, 159, 27, 73, 142, 67, 77, 152, 184, 127, 115, 110, 167, + 161, 160, 105, 136, 52, 190, 52, 131, 26, 117, 228, 192, 68, 40, + 28, 58, 247, 57, 123, 106, 55, 141, 29, 175, 0, 156, 188, 177, + 241, 158, 161, 54, 140, 103, 106, 106, 237, 210, 143, 109, 49, 28, + 168, 143, 111, 191, 169, 41, 30, 117, 180, 254, 76, 4, 159, 188, + 63, 235, 40, 4, 21, 7, 181, 189, 18, 223, 83, 187, 67, 72, + 137, 103, 164, 87, 158, 166, 136, 228, 50, 82, 107, 216, 243, 35, + 112, 195, 238, 45, 6, 52, 56, 120, 57, 137, 56, 35, 54, 78, + 126, 71, 0, 126, 178, 204, 103, 134, 153, 51, 110, 198, 188, 187, + 75, 63, 163, 155, 253, 14, 87, 121, 219, 20, 71, 13, 130, 151, + 89, 91, 135, 41, 128, 190, 86, 241, 113, 132, 88, 123, 243, 91, + 173, 7, 58, 136, 70, 160, 191, 221, 240, 30, 121, 135, 250, 60, + 81, 160, 181, 253, 67, 140, 30, 205, 150, 69, 171, 248, 168, 57, + 112, 207, 83, 246, 168, 113, 207, 234, 82, 28, 184, 145, 135, 248, + 124, 180, 31, 9, 88, 51, 47, 7, 121, 74, 184, 167, 34, 88, + 72, 234, 17, 191, 107, 255, 241, 38, 86, 65, 32, 180, 5, 55, + 183, 41, 28, 47, 64, 10, 145, 176, 235, 71, 63, 178, 166, 33, + 215, 252, 106, 221, 94, 5, 113, 24, 237, 73, 233, 139, 212, 142, + 220, 31, 70, 134, 241, 254, 103, 59, 124, 113, 19, 175, 32, 96, + 242, 88, 222, 219, 126, 171, 80, 80, 12, 8, 6, 217, 230, 10, + 199, 143, 40, 220, 118, 160, 41, 211, 83, 134, 250, 189, 144, 219, + 76, 107, 67, 56, 247, 254, 166, 83, 176, 133, 210, 65, 83, 84, + 208, 137, 45, 89, 195, 244, 196, 216, 248, 94, 49, 49, 110, 118, + 142, 32, 199, 214, 168, 103, 250, 106, 40, 200, 210, 162, 52, 26, + 116, 167, 5, 54, 124, 130, 169, 203, 255, 250, 29, 175, 224, 249, + 125, 87, 202, 19, 106, 251, 148, 133, 67, 58, 157, 79, 169, 195, + 214, 181, 118, 138, 17, 161, 165, 184, 165, 136, 32, 38, 13, 59, + 40, 206, 98, 187, 86, 26, 116, 135, 253, 201, 131, 109, 152, 187, + 156, 224, 79, 114, 202, 59, 178, 51, 66, 122, 193, 209, 121, 68, + 57, 52, 175, 107, 190, 89, 210, 167, 16, 172, 54, 43, 230, 125, + 24, 83, 165, 246, 74, 113, 23, 223, 107, 35, 197, 106, 0, 19, + 134, 157, 56, 153, 39, 114, 50, 32, 21, 98, 221, 109, 102, 156, + 135, 99, 6, 153, 9, 215, 248, 235, 161, 6, 68, 174, 35, 164, + 79, 159, 126, 171, 165, 251, 110, 79, 139, 102, 242, 6, 90, 45, + 224, 20, 88, 80, 62, 133, 137, 82, 149, 248, 145, 229, 166, 143, + 74, 176, 160, 102, 113, 38, 90, 107, 38, 21, 208, 22, 110, 93, + 122, 166, 141, 161, 30, 45, 231, 5, 96, 187, 50, 11, 55, 181, + 26, 224, 233, 148, 119, 126, 8, 35, 213, 113, 5, 141, 133, 227, + 248, 38, 58, 230, 36, 150, 233, 222, 82, 155, 234, 101, 213, 235, + 198, 233, 44, 145, 194, 92, 85, 253, 113, 96, 18, 143, 245, 206, + 20, 173, 231, 155, 115, 215, 82, 74, 252, 185, 118, 216, 197, 198, + 20, 111, 82, 129, 153, 109, 123, 170, 126, 52, 164, 27, 254, 102, + 229, 212, 167, 226, 19, 142, 88, 20, 45, 144, 139, 162, 245, 141, + 80, 216, 216, 35, 143, 197, 219, 37, 113, 14, 254, 198, 242, 208, + 142, 53, 84, 118, 124, 210, 166, 229, 208, 132, 167, 57, 30, 39, + 102, 110, 177, 108, 155, 150, 108, 234, 76, 105, 167, 125, 20, 249, + 227, 208, 172, 121, 135, 34, 0, 172, 162, 39, 92, 182, 237, 216, + 38, 193, 226, 53, 122, 233, 46, 193, 230, 84, 117, 81, 228, 54, + 76, 226, 252, 130, 3, 248, 119, 128, 72, 69, 128, 252, 236, 183, + 124, 67, 39, 49, 102, 156, 117, 75, 71, 139, 240, 33, 83, 192, + 198, 93, 124, 99, 116, 179, 49, 112, 232, 196, 11, 235, 82, 1, + 146, 158, 55, 112, 187, 144, 67, 40, 69, 143, 235, 122, 243, 185, + 183, 211, 103, 126, 110, 113, 232, 179, 185, 38, 2, 101, 154, 35, + 63, 18, 129, 239, 161, 34, 183, 46, 168, 231, 31, 54, 180, 8, + 81, 153, 121, 229, 188, 36, 85, 131, 209, 114, 248, 16, 251, 175, + 188, 100, 187, 147, 32, 123, 73, 160, 204, 158, 33, 117, 157, 195, + 21, 45, 125, 140, 36, 251, 212, 31, 51, 96, 96, 244, 167, 35, + 179, 24, 205, 79, 64, 189, 193, 248, 158, 194, 52, 35, 172, 108, + 112, 101, 230, 61, 129, 111, 28, 120, 213, 1, 133, 48, 222, 208, + 193, 141, 78, 197, 234, 152, 151, 145, 44, 89, 182, 70, 13, 75, + 30, 166, 88, 172, 224, 196, 145, 20, 158, 121, 110, 215, 201, 143, + 5, 72, 73, 50, 209, 208, 165, 162, 143, 188, 172, 115, 129, 17, + 186, 104, 250, 59, 54, 87, 37, 87, 159, 198, 201, 58, 44, 6, + 72, 42, 64, 78, 21, 109, 84, 176, 97, 113, 207, 38, 221, 187, + 26, 223, 217, 81, 227, 43, 215, 183, 191, 38, 70, 117, 137, 103, + 252, 178, 92, 2, 208, 198, 24, 253, 0, 75, 124, 150, 154, 180, + 154, 184, 192, 121, 131, 175, 170, 76, 32, 94, 69, 52, 254, 186, + 145, 252, 20, 57, 0, 102, 124, 13, 174, 196, 60, 205, 171, 39, + 86, 220, 227, 136, 99, 142, 143, 75, 92, 186, 125, 47, 5, 214, + 42, 191, 111, 118, 159, 224, 81, 142, 23, 80, 111, 15, 67, 150, + 220, 73, 253, 109, 168, 68, 242, 190, 86, 205, 14, 141, 224, 51, + 241, 205, 205, 182, 234, 57, 240, 119, 60, 139, 157, 138, 63, 233, + 33, 175, 87, 223, 154, 208, 97, 218, 8, 56, 187, 30, 155, 251, + 70, 164, 194, 204, 89, 187, 204, 171, 49, 168, 254, 168, 33, 204, + 250, 68, 56, 211, 41, 139, 210, 73, 52, 120, 56, 164, 177, 132, + 245, 70, 19, 230, 116, 34, 27, 125, 157, 162, 253, 142, 230, 196, + 219, 92, 235, 171, 150, 4, 67, 66, 109, 92, 95, 72, 50, 96, + 228, 139, 101, 217, 167, 37, 77, 27, 75, 120, 151, 157, 152, 33, + 10, 185, 149, 128, 179, 92, 160, 103, 34, 92, 142, 44, 143, 150, + 216, 238, 246, 226, 61, 206, 167, 132, 39, 162, 66, 253, 90, 5, + 149, 48, 94, 128, 149, 26, 241, 81, 111, 153, 83, 43, 176, 105, + 47, 93, 239, 125, 246, 177, 200, 35, 207, 77, 206, 118, 84, 225, + 87, 225, 119, 177, 215, 249, 47, 61, 239, 28, 83, 166, 11, 24, + 203, 163, 250, 48, 232, 173, 120, 196, 224, 50, 9, 218, 47, 155, + 243, 196, 0, 233, 90, 30, 62, 83, 60, 103, 74, 177, 219, 225, + 51, 110, 241, 196, 150, 13, 214, 61, 124, 93, 0, 242, 219, 5, + 181, 24, 76, 64, 214, 14, 176, 219, 137, 2, 128, 188, 229, 182, + 28, 23, 47, 102, 167, 195, 210, 214, 182, 184, 152, 217, 32, 111, + 28, 161, 197, 249, 13, 15, 187, 194, 211, 239, 155, 151, 243, 208, + 85, 90, 198, 254, 106, 130, 170, 106, 96, 152, 58, 121, 235, 82, + 240, 111, 210, 138, 232, 237, 62, 24, 124, 58, 130, 14, 156, 182, + 252, 220, 235, 246, 245, 251, 87, 61, 188, 168, 161, 121, 151, 40, + 134, 238, 174, 45, 123, 89, 15, 55, 57, 226, 234, 154, 143, 100, + 75, 5, 207, 224, 38, 67, 206, 255, 7, 157, 96, 19, 69, 48, + 41, 173, 224, 251, 107, 136, 85, 233, 172, 39, 14, 135, 55, 47, + 24, 183, 23, 48, 105, 240, 7, 196, 66, 111, 246, 105, 208, 201, + 25, 190, 84, 30, 76, 192, 209, 39, 168, 185, 221, 177, 194, 90, + 157, 94, 83, 69, 2, 219, 40, 231, 253, 213, 104, 75, 238, 234, + 17, 226, 109, 49, 38, 194, 147, 75, 13, 23, 34, 79, 189, 16, + 121, 96, 94, 68, 201, 209, 240, 182, 185, 10, 127, 208, 222, 95, + 69, 128, 213, 95, 76, 178, 114, 183, 237, 54, 204, 104, 148, 49, + 102, 230, 20, 55, 93, 60, 82, 117, 55, 198, 176, 255, 159, 83, + 162, 18, 52, 185, 231, 76, 136, 70, 208, 187, 218, 51, 150, 159, + 178, 226, 53, 171, 243, 173, 21, 117, 68, 93, 216, 182, 245, 46, + 53, 59, 95, 129, 175, 141, 144, 44, 245, 193, 203, 111, 120, 61, + 165, 67, 58, 237, 191, 164, 129, 240, 69, 222, 239, 24, 139, 37, + 3, 37, 145, 1, 62, 8, 130, 255, 122, 160, 84, 74, 1, 159, + 1, 50, 186, 153, 247, 190, 45, 50, 98, 17, 186, 224, 95, 223, + 95, 127, 84, 57, 232, 9, 250, 114, 190, 165, 27, 16, 214, 95, + 215, 225, 157, 65, 152, 138, 26, 14, 234, 214, 40, 180, 135, 185, + 47, 189, 199, 131, 138, 139, 126, 144, 123, 161, 162, 134, 71, 38, + 11, 5, 133, 144, 108, 170, 186, 50, 24, 202, 168, 95, 212, 65, + 194, 47, 148, 87, 83, 102, 214, 65, 112, 213, 254, 227, 105, 58, + 235, 43, 69, 128, 24, 45, 215, 85, 130, 42, 79, 89, 120, 79, + 68, 48, 241, 131, 148, 223, 229, 131, 152, 158, 134, 88, 59, 32, + 82, 95, 25, 248, 118, 186, 151, 168, 232, 144, 211, 229, 0, 174, + 115, 40, 247, 188, 160, 222, 254, 106, 224, 104, 150, 98, 236, 119, + 12, 119, 139, 203, 56, 191, 141, 220, 146, 252, 37, 43, 177, 28, + 20, 187, 158, 239, 121, 249, 28, 62, 205, 12, 65, 212, 28, 100, + 83, 242, 50, 66, 50, 6, 139, 133, 219, 166, 65, 145, 243, 29, + 97, 131, 224, 142, 192, 99, 152, 71, 51, 29, 87, 246, 152, 94, + 140, 27, 172, 116, 125, 77, 9, 111, 35, 26, 189, 241, 164, 91, + 215, 5, 31, 216, 159, 116, 41, 253, 253, 202, 114, 118, 44, 181, + 129, 116, 98, 77, 124, 148, 61, 50, 97, 71, 45, 247, 20, 232, + 50, 186, 93, 191, 215, 131, 62, 151, 0, 126, 37, 203, 172, 109, + 151, 45, 22, 92, 155, 84, 241, 198, 137, 214, 197, 229, 140, 195, + 127, 163, 20, 235, 127, 147, 117, 88, 78, 105, 192, 192, 250, 14, + 149, 99, 39, 40, 139, 150, 50, 62, 194, 107, 62, 248, 101, 3, + 24, 33, 107, 136, 174, 30, 92, 175, 66, 55, 68, 142, 247, 163, + 56, 59, 110, 186, 156, 135, 254, 209, 127, 139, 16, 239, 121, 146, + 79, 149, 231, 74, 166, 140, 132, 159, 8, 170, 103, 237, 101, 83, + 134, 179, 101, 111, 172, 58, 238, 147, 38, 192, 58, 68, 226, 110, + 161, 82, 40, 81, 139, 174, 97, 187, 119, 79, 217, 226, 238, 57, + 84, 137, 76, 47, 204, 18, 185, 174, 48, 148, 85, 203, 9, 26, + 11, 230, 118, 42, 214, 30, 154, 116, 7, 88, 133, 116, 115, 77, + 42, 246, 179, 144, 56, 237, 221, 130, 61, 175, 248, 249, 89, 222, + 217, 106, 65, 213, 203, 144, 128, 170, 174, 220, 123, 140, 37, 151, + 228, 57, 110, 57, 204, 148, 127, 165, 53, 48, 99, 246, 167, 157, + 233, 157, 55, 214, 198, 151, 113, 31, 110, 92, 11, 208, 160, 130, + 213, 29, 24, 170, 79, 12, 205, 77, 171, 50, 192, 179, 240, 109, + 154, 243, 42, 27, 68, 233, 10, 186, 205, 123, 132, 60, 60, 68, + 154, 246, 200, 242, 22, 127, 182, 229, 132, 187, 146, 169, 181, 81, + 17, 156, 148, 25, 147, 192, 125, 168, 23, 61, 211, 168, 102, 238, + 74, 154, 241, 153, 65, 249, 219, 151, 232, 24, 5, 221, 212, 20, + 23, 140, 247, 183, 249, 147, 251, 199, 234, 151, 73, 27, 252, 56, + 103, 66, 253, 154, 174, 126, 27, 31, 196, 31, 196, 112, 66, 113, + 195, 167, 73, 246, 80, 19, 187, 254, 13, 229, 203, 165, 12, 224, + 25, 253, 107, 26, 67, 115, 191, 223, 18, 234, 172, 171, 123, 190, + 142, 64, 27, 126, 78, 95, 3, 187, 11, 48, 46, 99, 235, 227, + 226, 47, 155, 26, 219, 23, 150, 249, 187, 1, 113, 250, 207, 74, + 254, 72, 17, 240, 30, 30, 156, 20, 225, 239, 106, 108, 122, 117, + 47, 237, 47, 148, 225, 5, 228, 142, 227, 126, 123, 124, 46, 155, + 126, 100, 188, 219, 105, 72, 59, 237, 38, 148, 14, 144, 101, 0, + 1, 59, 141, 86, 225, 163, 8, 98, 163, 7, 25, 75, 167, 110, + 71, 23, 186, 217, 222, 196, 34, 252, 255, 231, 90, 72, 220, 231, + 58, 129, 101, 116, 176, 40, 180, 147, 249, 212, 78, 21, 254, 121, + 126, 6, 196, 81, 202, 86, 54, 144, 43, 207, 144, 14, 33, 88, + 95, 214, 34, 190, 65, 108, 210, 194, 112, 159, 44, 112, 48, 75, + 46, 172, 8, 44, 63, 45, 42, 66, 30, 150, 170, 226, 167, 97, + 181, 217, 99, 2, 154, 109, 137, 203, 165, 120, 77, 238, 109, 113, + 20, 233, 247, 188, 192, 71, 160, 143, 20, 193, 155, 165, 73, 165, + 155, 36, 166, 230, 209, 88, 54, 228, 234, 207, 241, 134, 33, 168, + 76, 69, 234, 20, 9, 85, 179, 65, 91, 186, 112, 144, 183, 22, + 114, 102, 181, 237, 73, 248, 233, 64, 96, 53, 62, 185, 170, 135, + 159, 240, 126, 51, 76, 36, 77, 206, 152, 3, 94, 89, 112, 238, + 203, 165, 233, 136, 144, 6, 226, 35, 110, 230, 234, 145, 130, 53, + 21, 98, 246, 131, 30, 132, 48, 66, 11, 218, 47, 72, 117, 208, + 86, 41, 139, 142, 74, 78, 209, 31, 112, 142, 102, 177, 91, 235, + 107, 172, 0, 164, 183, 117, 202, 126, 186, 49, 13, 214, 112, 184, + 112, 134, 64, 181, 48, 147, 175, 236, 125, 131, 76, 58, 81, 14, + 229, 228, 201, 136, 49, 134, 120, 87, 184, 68, 84, 125, 247, 254, + 254, 128, 205, 116, 86, 121, 211, 2, 181, 194, 147, 50, 161, 212, + 242, 39, 65, 192, 225, 82, 112, 6, 76, 11, 219, 200, 23, 123, + 116, 143, 105, 37, 195, 9, 204, 35, 45, 166, 132, 196, 133, 204, + 224, 166, 70, 5, 133, 17, 236, 181, 183, 34, 147, 81, 207, 133, + 226, 204, 143, 193, 12, 14, 223, 23, 110, 212, 228, 105, 240, 95, + 125, 66, 177, 217, 129, 43, 7, 139, 44, 179, 182, 177, 129, 32, + 120, 25, 35, 26, 56, 66, 233, 117, 238, 231, 240, 148, 176, 87, + 239, 109, 243, 29, 112, 152, 172, 252, 109, 47, 254, 163, 250, 201, + 210, 202, 46, 42, 82, 8, 38, 149, 64, 86, 124, 202, 153, 234, + 76, 207, 155, 55, 189, 76, 88, 131, 182, 129, 230, 123, 206, 14, + 183, 30, 32, 65, 175, 180, 248, 20, 11, 219, 42, 192, 226, 96, + 149, 233, 213, 127, 255, 15, 145, 73, 36, 245, 110, 175, 213, 204, + 16, 70, 47, 135, 215, 86, 179, 135, 147, 251, 154, 81, 101, 224, + 90, 73, 83, 166, 228, 252, 216, 83, 145, 119, 241, 178, 110, 251, + 135, 230, 210, 196, 249, 230, 162, 45, 242, 221, 236, 112, 210, 102, + 76, 233, 86, 125, 120, 119, 1, 61, 17, 72, 199, 82, 64, 139, + 63, 141, 163, 122, 74, 104, 227, 135, 38, 70, 5, 51, 232, 59, + 253, 128, 46, 50, 157, 30, 177, 158, 246, 75, 2, 224, 203, 23, + 204, 146, 80, 141, 90, 92, 5, 126, 191, 245, 89, 40, 113, 17, + 177, 73, 235, 47, 206, 65, 68, 146, 242, 210, 9, 82, 148, 207, + 18, 242, 96, 39, 5, 184, 0, 66, 133, 48, 49, 200, 162, 93, + 156, 120, 150, 157, 146, 136, 117, 215, 202, 123, 167, 53, 182, 2, + 199, 130, 191, 224, 23, 255, 22, 147, 33, 154, 116, 136, 76, 182, + 102, 184, 188, 204, 15, 111, 4, 146, 5, 20, 200, 12, 217, 182, + 225, 10, 119, 83, 123, 64, 245, 4, 87, 33, 108, 24, 181, 173, + 45, 55, 12, 246, 237, 61, 114, 44, 159, 217, 135, 202, 179, 33, + 74, 2, 71, 105, 41, 102, 18, 32, 177, 211, 161, 153, 169, 32, + 47, 34, 203, 27, 7, 94, 173, 192, 74, 197, 255, 155, 187, 189, + 150, 207, 91, 146, 99, 177, 205, 7, 146, 20, 192, 4, 27, 193, + 210, 174, 178, 27, 66, 204, 9, 180, 19, 243, 48, 150, 235, 197, + 253, 107, 151, 243, 114, 164, 27, 55, 12, 75, 253, 244, 39, 211, + 146, 167, 66, 68, 191, 4, 253, 25, 127, 117, 86, 223, 141, 205, + 212, 97, 175, 109, 43, 168, 146, 68, 58, 21, 191, 206, 87, 51, + 66, 107, 15, 75, 85, 207, 222, 14, 58, 200, 179, 6, 40, 19, + 173, 80, 118, 25, 35, 230, 49, 38, 193, 113, 85, 61, 2, 31, + 155, 15, 175, 76, 38, 94, 249, 133, 153, 172, 230, 156, 56, 254, + 245, 205, 65, 209, 87, 228, 123, 17, 82, 160, 214, 195, 7, 65, + 230, 98, 194, 70, 107, 243, 220, 82, 253, 216, 27, 227, 174, 133, + 242, 158, 151, 192, 41, 57, 96, 225, 68, 49, 153, 195, 20, 245, + 83, 210, 113, 148, 143, 255, 86, 168, 204, 51, 200, 57, 207, 44, + 91, 28, 107, 0, 198, 77, 6, 241, 140, 71, 65, 101, 38, 243, + 74, 31, 63, 70, 135, 224, 171, 70, 84, 249, 20, 168, 248, 138, + 106, 248, 181, 129, 102, 129, 121, 230, 166, 135, 219, 14, 184, 214, + 139, 181, 132, 155, 140, 169, 140, 125, 243, 139, 222, 92, 31, 222, + 170, 71, 225, 44, 29, 162, 168, 103, 132, 112, 0, 134, 10, 79, + 194, 163, 213, 99, 53, 42, 252, 243, 162, 174, 11, 61, 8, 230, + 157, 20, 21, 62, 84, 53, 185, 178, 148, 221, 96, 35, 111, 118, + 162, 204, 42, 56, 222, 14, 144, 40, 97, 216, 171, 174, 71, 31, + 42, 16, 3, 91, 34, 165, 148, 247, 53, 202, 166, 82, 177, 8, + 109, 245, 6, 30, 17, 195, 15, 69, 122, 133, 177, 178, 213, 23, + 218, 143, 201, 248, 36, 106, 8, 96, 19, 151, 172, 90, 152, 94, + 191, 237, 1, 93, 230, 176, 108, 64, 30, 42, 118, 119, 101, 104, + 43, 234, 180, 33, 87, 221, 48, 73, 232, 253, 47, 217, 5, 19, + 182, 126, 123, 220, 106, 90, 87, 205, 76, 79, 184, 70, 123, 64, + 213, 234, 220, 87, 98, 145, 16, 212, 145, 219, 159, 71, 207, 37, + 164, 170, 113, 213, 82, 29, 48, 52, 98, 183, 176, 95, 117, 20, + 212, 143, 131, 7, 98, 238, 185, 124, 149, 36, 68, 53, 43, 134, + 171, 232, 182, 177, 35, 102, 154, 29, 99, 72, 35, 47, 83, 180, + 71, 114, 20, 85, 160, 60, 46, 42, 170, 149, 24, 154, 107, 160, + 76, 107, 55, 254, 142, 98, 195, 131, 255, 84, 204, 129, 49, 39, + 153, 164, 241, 105, 23, 6, 117, 42, 244, 220, 207, 101, 144, 59, + 176, 184, 168, 75, 245, 94, 207, 88, 138, 236, 138, 32, 86, 114, + 193, 227, 16, 222, 1, 2, 17, 94, 141, 24, 167, 199, 9, 54, + 241, 228, 198, 59, 222, 205, 213, 146, 189, 92, 20, 142, 78, 3, + 56, 212, 207, 166, 61, 198, 64, 180, 166, 99, 182, 138, 16, 64, + 229, 215, 222, 145, 19, 142, 204, 161, 143, 241, 140, 63, 135, 120, + 187, 128, 101, 139, 115, 208, 192, 50, 200, 96, 221, 136, 13, 171, + 220, 245, 60, 189, 244, 249, 29, 154, 233, 72, 105, 181, 165, 177, + 71, 221, 91, 126, 90, 177, 114, 51, 11, 74, 19, 114, 109, 140, + 109, 194, 50, 226, 113, 16, 60, 11, 233, 42, 24, 138, 216, 193, + 255, 132, 1, 219, 150, 73, 235, 196, 176, 106, 228, 182, 91, 36, + 83, 158, 154, 147, 230, 20, 84, 180, 51, 179, 169, 160, 35, 211, + 135, 184, 208, 25, 92, 161, 217, 52, 119, 39, 29, 168, 131, 119, + 175, 178, 168, 19, 255, 7, 23, 136, 94, 198, 186, 106, 35, 14, + 171, 114, 106, 130, 206, 47, 41, 230, 202, 231, 150, 29, 227, 188, + 54, 223, 77, 205, 46, 146, 86, 169, 20, 4, 104, 2, 144, 80, + 84, 236, 8, 240, 110, 139, 157, 247, 118, 67, 88, 119, 58, 60, + 74, 86, 61, 242, 243, 175, 54, 251, 189, 234, 177, 26, 178, 215, + 225, 173, 205, 108, 38, 15, 238, 213, 217, 241, 79, 178, 254, 242, + 99, 57, 150, 121, 194, 136, 209, 144, 175, 26, 84, 112, 178, 135, + 83, 59, 225, 62, 100, 56, 15, 243, 249, 225, 251, 71, 28, 82, + 17, 128, 58, 20, 183, 89, 52, 64, 12, 4, 104, 154, 149, 105, + 206, 23, 74, 250, 84, 228, 38, 134, 57, 1, 70, 201, 43, 241, + 150, 189, 255, 50, 227, 243, 225, 187, 204, 95, 18, 236, 173, 49, + 45, 191, 34, 161, 103, 34, 190, 155, 191, 196, 161, 175, 168, 49, + 9, 108, 124, 239, 49, 250, 73, 66, 69, 2, 132, 135, 10, 68, + 111, 136, 16, 244, 156, 179, 200, 215, 78, 204, 137, 187, 202, 64, + 44, 74, 167, 255, 226, 154, 252, 93, 217, 46, 191, 220, 25, 20, + 9, 90, 86, 74, 45, 247, 111, 57, 253, 82, 75, 76, 244, 180, + 84, 144, 160, 152, 54, 54, 161, 136, 196, 210, 191, 89, 162, 46, + 171, 58, 15, 130, 120, 167, 193, 43, 90, 43, 247, 153, 121, 84, + 42, 235, 190, 100, 233, 62, 54, 222, 109, 101, 110, 97, 91, 243, + 130, 204, 67, 220, 242, 213, 3, 189, 212, 171, 81, 154, 251, 9, + 202, 50, 184, 43, 165, 219, 69, 174, 218, 223, 137, 148, 186, 180, + 14, 42, 229, 196, 104, 112, 88, 13, 2, 151, 2, 65, 98, 69, + 96, 37, 205, 236, 229, 27, 119, 231, 141, 36, 197, 63, 163, 119, + 140, 99, 149, 225, 85, 64, 18, 27, 70, 87, 51, 242, 111, 100, + 203, 40, 186, 165, 31, 43, 40, 98, 134, 224, 74, 111, 124, 121, + 89, 67, 231, 30, 68, 175, 28, 170, 9, 125, 122, 142, 86, 229, + 252, 221, 214, 38, 240, 26, 248, 254, 39, 33, 164, 150, 208, 143, + 171, 58, 111, 20, 89, 214, 246, 87, 243, 208, 125, 12, 129, 15, + 105, 34, 38, 75, 149, 223, 131, 114, 106, 130, 206, 47, 37, 42, + 206, 16, 14, 254, 169, 32, 211, 109, 38, 139, 76, 86, 117, 157, + 169, 13, 182, 225, 240, 214, 178, 198, 121, 87, 132, 85, 43, 126, + 168, 147, 226, 58, 46, 3, 80, 51, 60, 174, 228, 186, 208, 237, + 39, 193, 88, 185, 131, 247, 123, 63, 243, 228, 50, 134, 21, 24, + 215, 77, 245, 127, 71, 230, 29, 108, 47, 202, 218, 199, 125, 165, + 251, 181, 122, 239, 103, 223, 82, 109, 207, 92, 32, 0, 243, 94, + 186, 202, 23, 215, 142, 181, 175, 30, 128, 124, 225, 200, 31, 18, + 92, 154, 60, 241, 5, 163, 66, 186, 24, 133, 245, 149, 230, 78, + 57, 201, 100, 36, 205, 55, 80, 2, 93, 183, 223, 71, 84, 10, + 4, 208, 229, 87, 210, 203, 75, 102, 211, 73, 193, 61, 213, 175, + 200, 180, 24, 36, 9, 102, 69, 178, 21, 86, 206, 116, 100, 131, + 75, 12, 154, 171, 57, 233, 84, 98, 188, 231, 163, 114, 153, 201, + 254, 32, 86, 107, 217, 119, 137, 229, 174, 109, 75, 55, 148, 126, + 34, 60, 225, 226, 91, 180, 97, 81, 145, 182, 53, 192, 50, 155, + 77, 132, 53, 134, 254, 255, 94, 128, 165, 197, 56, 179, 154, 177, + 23, 168, 221, 104, 38, 90, 250, 216, 107, 228, 231, 176, 173, 172, + 64, 119, 152, 242, 7, 59, 171, 14, 34, 229, 153, 222, 191, 127, + 40, 166, 61, 11, 161, 102, 31, 5, 144, 169, 159, 186, 176, 254, + 237, 204, 80, 183, 32, 251, 192, 36, 238, 138, 157, 92, 153, 240, + 250, 127, 220, 89, 210, 74, 194, 222, 184, 59, 250, 36, 85, 210, + 164, 114, 72, 252, 53, 122, 66, 200, 154, 243, 107, 134, 39, 96, + 1, 109, 121, 5, 83, 191, 232, 108, 118, 99, 102, 52, 224, 99, + 250, 115, 86, 38, 210, 68, 89, 252, 186, 65, 19, 82, 174, 120, + 120, 67, 7, 55, 4, 12, 32, 165, 98, 71, 54, 142, 41, 65, + 190, 85, 120, 85, 30, 172, 153, 24, 110, 19, 46, 251, 133, 49, + 27, 23, 190, 153, 83, 125, 22, 81, 126, 213, 131, 228, 149, 196, + 116, 197, 144, 4, 224, 3, 233, 169, 226, 248, 75, 156, 229, 82, + 151, 96, 37, 65, 67, 225, 79, 223, 16, 200, 156, 48, 138, 33, + 202, 147, 139, 118, 31, 19, 101, 14, 44, 43, 66, 108, 143, 43, + 7, 0, 135, 74, 68, 136, 210, 14, 200, 221, 229, 215, 232, 125, + 170, 168, 34, 53, 225, 164, 202, 200, 235, 95, 234, 253, 222, 250, + 240, 92, 157, 183, 87, 218, 109, 83, 68, 48, 197, 211, 84, 154, + 122, 45, 201, 211, 95, 72, 206, 187, 164, 182, 195, 234, 155, 77, + 232, 113, 253, 216, 134, 140, 63, 80, 154, 80, 177, 83, 125, 120, + 239, 15, 21, 251, 246, 11, 28, 157, 154, 70, 18, 223, 182, 185, + 143, 137, 230, 202, 4, 221, 175, 50, 77, 104, 15, 30, 202, 179, + 85, 165, 232, 185, 61, 163, 92, 156, 219, 93, 241, 142, 193, 67, + 251, 171, 44, 74, 71, 171, 170, 195, 34, 128, 87, 240, 128, 214, + 176, 221, 92, 80, 80, 212, 234, 226, 30, 42, 254, 220, 211, 15, + 232, 224, 220, 151, 161, 160, 185, 175, 92, 234, 116, 98, 70, 109, + 239, 206, 154, 195, 178, 234, 199, 65, 143, 194, 107, 93, 245, 120, + 205, 243, 45, 72, 113, 232, 63, 235, 125, 138, 122, 164, 17, 188, + 190, 146, 59, 90, 209, 6, 35, 123, 41, 25, 253, 20, 137, 42, + 88, 233, 239, 92, 140, 125, 252, 247, 106, 63, 148, 215, 177, 156, + 120, 26, 70, 191, 228, 102, 48, 33, 250, 185, 116, 204, 134, 56, + 179, 243, 82, 148, 217, 161, 47, 78, 97, 127, 154, 13, 233, 146, + 18, 137, 208, 116, 212, 58, 243, 98, 49, 234, 161, 140, 118, 169, + 128, 13, 154, 34, 51, 154, 27, 54, 28, 250, 252, 79, 223, 122, + 62, 156, 164, 69, 113, 25, 46, 178, 124, 138, 101, 114, 225, 137, + 53, 143, 196, 35, 101, 33, 81, 76, 193, 197, 229, 111, 88, 194, + 68, 166, 93, 68, 17, 16, 99, 11, 167, 160, 33, 209, 24, 172, + 190, 148, 67, 14, 11, 193, 76, 78, 245, 132, 225, 68, 48, 219, + 197, 18, 20, 165, 186, 243, 113, 106, 170, 210, 95, 137, 85, 49, + 231, 36, 66, 18, 200, 221, 117, 41, 15, 236, 189, 130, 209, 149, + 253, 103, 175, 105, 161, 157, 102, 108, 156, 234, 8, 73, 60, 51, + 153, 74, 93, 255, 167, 143, 63, 122, 35, 36, 181, 194, 11, 48, + 166, 82, 69, 65, 3, 137, 198, 182, 15, 5, 54, 105, 44, 33, + 140, 183, 252, 204, 132, 150, 150, 89, 49, 205, 142, 93, 91, 254, + 91, 184, 180, 17, 87, 6, 216, 20, 42, 134, 222, 43, 21, 20, + 132, 168, 149, 123, 241, 255, 39, 90, 10, 109, 176, 218, 216, 225, + 213, 103, 189, 175, 99, 52, 252, 248, 122, 218, 226, 219, 110, 189, + 65, 179, 94, 95, 145, 94, 103, 60, 143, 51, 57, 217, 9, 30, + 48, 4, 61, 159, 67, 83, 32, 155, 28, 203, 145, 232, 181, 3, + 146, 36, 126, 161, 223, 197, 25, 179, 61, 109, 188, 82, 14, 84, + 5, 200, 36, 9, 58, 28, 75, 116, 5, 66, 44, 254, 113, 162, + 47, 98, 29, 53, 81, 2, 135, 187, 78, 216, 103, 125, 175, 240, + 252, 219, 20, 154, 50, 112, 41, 227, 212, 118, 82, 93, 123, 145, + 137, 174, 216, 232, 34, 236, 39, 59, 46, 125, 21, 48, 96, 168, + 204, 184, 216, 123, 252, 31, 142, 13, 57, 140, 106, 43, 0, 75, + 107, 173, 190, 61, 158, 129, 60, 156, 190, 72, 164, 88, 237, 207, + 87, 247, 74, 230, 104, 110, 209, 161, 157, 144, 29, 252, 176, 71, + 12, 242, 3, 64, 120, 209, 156, 161, 16, 2, 20, 7, 31, 26, + 184, 15, 77, 0, 228, 93, 97, 59, 231, 167, 165, 199, 185, 164, + 21, 148, 18, 64, 141, 72, 58, 251, 168, 174, 32, 201, 78, 237, + 15, 144, 87, 247, 64, 8, 23, 92, 199, 223, 243, 174, 144, 120, + 172, 187, 191, 173, 39, 28, 181, 130, 74, 63, 117, 50, 17, 180, + 143, 217, 139, 172, 86, 51, 130, 105, 91, 175, 248, 141, 105, 229, + 19, 25, 224, 189, 99, 15, 126, 80, 166, 37, 38, 234, 182, 140, + 29, 167, 28, 221, 245, 224, 41, 123, 212, 221, 149, 152, 236, 152, + 131, 195, 45, 85, 101, 127, 4, 76, 150, 157, 182, 157, 98, 97, + 20, 223, 168, 179, 19, 9, 187, 51, 56, 247, 117, 179, 190, 87, + 206, 107, 185, 215, 118, 75, 39, 163, 26, 200, 137, 153, 77, 79, + 76, 195, 137, 147, 253, 47, 223, 143, 220, 20, 154, 225, 250, 234, + 123, 245, 249, 128, 8, 82, 40, 51, 117, 6, 168, 211, 31, 32, + 142, 132, 154, 230, 172, 218, 56, 17, 174, 8, 143, 99, 60, 82, + 182, 167, 247, 149, 103, 153, 178, 94, 29, 245, 235, 5, 209, 177, + 160, 30, 63, 186, 163, 33, 180, 47, 203, 37, 1, 219, 97, 26, + 47, 108, 55, 91, 50, 6, 74, 52, 137, 74, 63, 32, 0, 172, + 165, 51, 226, 2, 188, 232, 241, 248, 216, 203, 227, 2, 132, 46, + 11, 212, 113, 126, 31, 136, 234, 154, 38, 130, 147, 143, 250, 180, + 117, 187, 131, 161, 58, 29, 227, 174, 134, 84, 18, 232, 176, 166, + 208, 143, 230, 153, 42, 19, 210, 51, 38, 253, 156, 199, 185, 4, + 214, 111, 2, 53, 118, 119, 151, 169, 215, 100, 162, 233, 141, 41, + 122, 212, 186, 27, 83, 138, 39, 109, 143, 86, 176, 1, 50, 99, + 79, 112, 232, 12, 89, 217, 117, 3, 176, 199, 182, 40, 107, 180, + 61, 26, 14, 83, 171, 218, 202, 137, 70, 15, 130, 99, 113, 183, + 160, 232, 5, 161, 79, 136, 247, 176, 10, 21, 180, 223, 192, 192, + 85, 16, 134, 2, 91, 206, 101, 129, 249, 98, 119, 163, 54, 149, + 198, 10, 180, 224, 133, 191, 197, 254, 68, 131, 176, 56, 71, 15, + 217, 34, 74, 189, 127, 227, 27, 78, 101, 2, 253, 45, 47, 36, + 134, 241, 8, 5, 11, 197, 11, 126, 146, 59, 127, 14, 197, 180, + 122, 199, 104, 26, 26, 234, 12, 152, 88, 163, 219, 68, 181, 142, + 14, 151, 151, 122, 31, 22, 82, 210, 192, 248, 123, 196, 106, 111, + 221, 7, 107, 217, 58, 37, 241, 39, 202, 209, 118, 64, 33, 43, + 126, 58, 87, 227, 141, 220, 90, 108, 175, 47, 11, 246, 136, 37, + 191, 177, 8, 133, 155, 3, 252, 245, 232, 200, 240, 178, 223, 152, + 131, 110, 120, 149, 51, 161, 209, 147, 168, 250, 186, 101, 226, 140, + 57, 231, 94, 39, 57, 66, 238, 68, 87, 71, 254, 224, 196, 255, + 94, 98, 221, 141, 142, 45, 158, 162, 252, 103, 112, 193, 208, 162, + 129, 65, 88, 58, 30, 109, 61, 182, 218, 136, 226, 149, 41, 134, + 104, 83, 64, 32, 143, 89, 29, 120, 171, 110, 24, 76, 96, 172, + 173, 21, 174, 138, 247, 149, 38, 19, 171, 84, 126, 46, 165, 236, + 136, 87, 107, 158, 68, 26, 163, 159, 14, 242, 202, 0, 153, 123, + 137, 201, 236, 26, 107, 142, 121, 70, 47, 27, 59, 47, 22, 111, + 174, 130, 115, 114, 151, 8, 78, 155, 154, 239, 248, 230, 158, 187, + 30, 217, 50, 115, 155, 82, 248, 188, 182, 157, 86, 208, 219, 169, + 81, 72, 62, 147, 90, 25, 173, 35, 147, 143, 197, 44, 95, 42, + 104, 193, 22, 185, 170, 41, 121, 30, 204, 143, 78, 160, 37, 221, + 211, 96, 87, 175, 44, 42, 253, 94, 132, 36, 231, 17, 38, 179, + 153, 80, 7, 212, 73, 34, 69, 90, 5, 219, 157, 20, 183, 248, + 84, 236, 128, 4, 173, 233, 201, 48, 21, 131, 98, 25, 44, 83, + 35, 117, 89, 238, 37, 93, 98, 183, 34, 237, 118, 75, 14, 20, + 52, 202, 23, 80, 89, 178, 103, 190, 215, 71, 88, 175, 38, 123, + 79, 4, 207, 201, 44, 61, 146, 199, 73, 137, 47, 43, 115, 172, + 123, 194, 55, 246, 107, 75, 176, 69, 110, 166, 104, 93, 101, 10, + 106, 116, 107, 14, 238, 45, 80, 82, 166, 11, 14, 160, 96, 192, + 251, 113, 168, 63, 255, 105, 251, 244, 205, 56, 33, 19, 183, 63, + 214, 54, 61, 2, 35, 14, 166, 81, 107, 90, 105, 87, 64, 200, + 32, 135, 13, 14, 112, 228, 45, 60, 197, 247, 0, 75, 1, 93, + 185, 149, 237, 243, 87, 29, 19, 152, 116, 61, 134, 216, 76, 47, + 197, 231, 89, 45, 56, 96, 63, 252, 214, 124, 85, 45, 233, 108, + 74, 9, 37, 143, 235, 151, 95, 140, 249, 251, 225, 213, 162, 190, + 205, 27, 183, 147, 179, 134, 195, 75, 255, 35, 90, 103, 180, 182, + 131, 175, 69, 95, 61, 9, 167, 81, 79, 47, 240, 129, 193, 86, + 177, 123, 240, 54, 230, 39, 194, 111, 11, 65, 85, 226, 56, 123, + 99, 176, 233, 116, 193, 114, 40, 58, 121, 181, 19, 222, 238, 16, + 184, 222, 241, 222, 133, 85, 91, 192, 194, 75, 135, 196, 114, 78, + 215, 97, 87, 237, 64, 4, 248, 37, 161, 71, 188, 156, 238, 204, + 139, 31, 126, 226, 35, 248, 2, 4, 27, 13, 203, 74, 60, 183, + 103, 109, 237, 159, 196, 154, 212, 100, 45, 72, 196, 219, 177, 21, + 142, 173, 6, 81, 12, 96, 160, 99, 49, 146, 101, 45, 172, 66, + 239, 4, 155, 189, 132, 206, 72, 72, 225, 18, 241, 236, 122, 234, + 114, 89, 107, 192, 161, 198, 161, 186, 139, 59, 168, 79, 234, 107, + 165, 199, 154, 110, 83, 3, 44, 19, 200, 42, 34, 46, 163, 139, + 207, 182, 49, 228, 217, 79, 115, 90, 234, 48, 214, 97, 186, 212, + 223, 63, 88, 206, 65, 30, 1, 0, 26, 136, 116, 5, 4, 9, + 238, 16, 252, 32, 78, 29, 28, 57, 205, 86, 157, 171, 108, 118, + 98, 121, 223, 186, 208, 186, 24, 18, 210, 91, 178, 111, 116, 192, + 166, 110, 191, 107, 192, 13, 238, 236, 55, 89, 66, 184, 55, 172, + 213, 228, 69, 160, 154, 81, 88, 193, 173, 19, 113, 93, 223, 59, + 54, 121, 252, 56, 193, 186, 194, 158, 75, 122, 51, 178, 26, 91, + 183, 254, 237, 95, 238, 245, 15, 105, 254, 144, 76, 92, 236, 108, + 113, 218, 200, 183, 107, 185, 149, 24, 223, 107, 133, 218, 45, 85, + 40, 227, 161, 146, 114, 197, 116, 186, 204, 232, 79, 87, 177, 237, + 253, 191, 165, 229, 56, 223, 104, 232, 5, 137, 168, 129, 229, 247, + 64, 125, 78, 126, 134, 125, 243, 229, 135, 172, 242, 123, 16, 125, + 209, 72, 40, 93, 240, 127, 168, 127, 160, 11, 101, 107, 107, 125, + 91, 201, 159, 206, 1, 190, 76, 78, 91, 90, 174, 15, 158, 222, + 177, 189, 76, 69, 231, 9, 46, 109, 239, 135, 187, 203, 51, 171, + 156, 248, 228, 155, 157, 219, 67, 55, 161, 227, 120, 83, 20, 58, + 159, 248, 82, 124, 157, 36, 29, 253, 148, 78, 121, 2, 103, 149, + 193, 167, 77, 165, 86, 198, 198, 83, 74, 239, 191, 220, 28, 102, + 155, 52, 50, 192, 66, 250, 80, 71, 121, 18, 14, 146, 228, 131, + 43, 113, 122, 163, 94, 80, 67, 205, 177, 17, 144, 164, 175, 17, + 172, 88, 191, 55, 55, 109, 96, 186, 9, 179, 61, 156, 238, 150, + 195, 11, 114, 101, 252, 137, 244, 237, 76, 91, 65, 204, 202, 124, + 49, 20, 9, 248, 2, 155, 11, 178, 90, 3, 181, 165, 252, 126, + 230, 67, 69, 224, 71, 78, 3, 92, 84, 221, 108, 97, 58, 48, + 145, 45, 216, 234, 99, 25, 24, 83, 222, 140, 116, 198, 154, 135, + 65, 153, 226, 179, 47, 35, 55, 230, 194, 12, 143, 203, 89, 54, + 252, 202, 52, 56, 173, 90, 27, 199, 87, 37, 91, 160, 85, 206, + 38, 251, 218, 55, 77, 204, 103, 200, 195, 229, 174, 235, 162, 154, + 22, 186, 53, 167, 218, 215, 84, 137, 140, 108, 105, 226, 243, 205, + 100, 122, 30, 23, 253, 170, 12, 155, 139, 17, 155, 154, 119, 151, + 169, 35, 214, 56, 148, 230, 7, 223, 26, 245, 6, 153, 130, 36, + 65, 143, 122, 188, 238, 161, 123, 159, 234, 245, 76, 133, 242, 138, + 128, 116, 168, 184, 122, 115, 2, 182, 221, 40, 243, 51, 26, 98, + 220, 123, 254, 70, 69, 161, 5, 125, 32, 117, 87, 33, 107, 132, + 242, 196, 4, 51, 173, 133, 174, 215, 32, 218, 50, 44, 111, 24, + 131, 55, 51, 76, 170, 95, 32, 180, 238, 95, 181, 139, 234, 236, + 125, 80, 232, 124, 20, 38, 4, 42, 95, 42, 209, 152, 135, 95, + 166, 99, 116, 186, 222, 165, 60, 228, 241, 12, 19, 41, 178, 247, + 136, 225, 244, 163, 250, 37, 146, 165, 103, 232, 147, 50, 252, 52, + 41, 14, 70, 114, 191, 129, 14, 122, 162, 55, 163, 166, 49, 237, + 50, 161, 9, 221, 147, 145, 43, 81, 152, 44, 194, 88, 49, 144, + 211, 128, 174, 5, 122, 82, 79, 84, 119, 196, 42, 130, 223, 93, + 63, 151, 23, 104, 2, 171, 206, 95, 44, 62, 244, 55, 174, 244, + 23, 2, 48, 218, 248, 92, 195, 236, 230, 114, 76, 162, 65, 184, + 187, 186, 115, 194, 244, 35, 212, 9, 99, 226, 136, 28, 123, 93, + 239, 111, 250, 208, 17, 30, 31, 103, 238, 212, 85, 195, 147, 86, + 57, 129, 148, 148, 14, 247, 109, 141, 91, 176, 39, 195, 209, 40, + 25, 12, 225, 159, 242, 24, 221, 245, 53, 229, 112, 71, 50, 178, + 109, 199, 232, 8, 111, 208, 163, 65, 237, 70, 243, 117, 142, 249, + 105, 69, 80, 237, 240, 128, 221, 6, 144, 197, 7, 153, 240, 192, + 117, 33, 166, 5, 68, 91, 163, 150, 126, 86, 216, 80, 11, 205, + 117, 130, 173, 209, 156, 62, 215, 97, 245, 27, 15, 59, 252, 179, + 100, 130, 225, 181, 90, 106, 34, 148, 129, 23, 48, 95, 226, 240, + 221, 24, 142, 158, 245, 83, 26, 84, 131, 85, 206, 54, 121, 188, + 67, 235, 73, 46, 34, 255, 188, 36, 95, 158, 182, 89, 151, 235, + 134, 48, 75, 44, 11, 100, 194, 90, 205, 81, 3, 143, 108, 49, + 183, 217, 65, 19, 122, 52, 24, 17, 142, 220, 254, 53, 196, 22, + 14, 100, 173, 122, 206, 195, 3, 200, 134, 76, 244, 221, 209, 25, + 234, 135, 252, 82, 114, 127, 152, 76, 239, 63, 93, 56, 12, 150, + 248, 175, 156, 14, 219, 82, 165, 237, 228, 172, 138, 71, 36, 24, + 142, 153, 63, 70, 62, 130, 185, 1, 168, 167, 210, 67, 20, 210, + 35, 10, 36, 206, 9, 13, 165, 67, 65, 13, 47, 1, 181, 80, + 159, 35, 192, 124, 123, 114, 4, 34, 73, 134, 203, 154, 11, 204, + 202, 81, 168, 148, 180, 151, 106, 161, 140, 188, 147, 195, 174, 106, + 89, 49, 98, 77, 138, 158, 118, 183, 68, 159, 126, 208, 42, 208, + 229, 212, 28, 64, 30, 44, 93, 101, 91, 179, 233, 122, 130, 226, + 75, 205, 207, 185, 146, 58, 117, 196, 55, 142, 59, 86, 137, 46, + 87, 46, 122, 59, 51, 122, 255, 87, 178, 112, 129, 223, 107, 120, + 220, 246, 156, 224, 15, 56, 19, 121, 18, 157, 190, 49, 128, 61, + 60, 237, 23, 81, 179, 79, 14, 134, 75, 114, 101, 166, 245, 230, + 33, 5, 61, 240, 116, 102, 145, 0, 55, 161, 182, 213, 34, 219, + 189, 52, 243, 177, 112, 109, 191, 230, 219, 93, 231, 101, 154, 84, + 159, 207, 86, 137, 195, 238, 139, 4, 187, 92, 91, 117, 48, 51, + 11, 230, 254, 96, 30, 74, 109, 195, 93, 43, 210, 101, 8, 103, + 99, 53, 190, 46, 191, 51, 88, 10, 85, 189, 101, 222, 98, 176, + 191, 246, 248, 90, 148, 69, 222, 138, 18, 5, 52, 164, 245, 3, + 252, 110, 161, 78, 34, 163, 115, 75, 255, 137, 9, 67, 67, 108, + 218, 2, 129, 246, 121, 203, 144, 225, 54, 106, 49, 171, 125, 153, + 218, 232, 62, 75, 143, 212, 116, 212, 48, 135, 123, 250, 122, 21, + 135, 157, 33, 83, 197, 92, 53, 38, 121, 146, 95, 2, 164, 220, + 227, 188, 246, 23, 77, 154, 139, 124, 63, 63, 174, 85, 85, 89, + 248, 45, 108, 178, 224, 83, 206, 137, 121, 0, 3, 52, 238, 7, + 214, 80, 206, 37, 210, 97, 138, 196, 218, 61, 103, 224, 247, 23, + 91, 236, 9, 174, 124, 57, 104, 237, 250, 118, 107, 175, 51, 219, + 237, 200, 133, 149, 242, 193, 157, 179, 170, 114, 121, 113, 253, 252, + 188, 60, 151, 71, 232, 51, 160, 176, 81, 118, 129, 210, 57, 160, + 161, 203, 118, 194, 136, 134, 157, 207, 232, 119, 254, 137, 141, 114, + 190, 142, 227, 222, 71, 20, 44, 127, 159, 145, 147, 143, 229, 244, + 201, 83, 92, 194, 144, 254, 58, 57, 85, 238, 63, 244, 236, 204, + 137, 16, 17, 213, 249, 85, 165, 167, 173, 110, 13, 180, 68, 30, + 67, 3, 40, 244, 244, 125, 111, 32, 252, 42, 140, 3, 245, 207, + 97, 248, 175, 83, 83, 50, 171, 217, 142, 142, 216, 143, 107, 172, + 168, 25, 101, 217, 107, 127, 125, 50, 222, 21, 238, 172, 156, 157, + 207, 254, 133, 158, 222, 191, 227, 202, 233, 91, 40, 84, 131, 8, + 74, 169, 219, 80, 71, 164, 88, 151, 109, 67, 146, 61, 124, 222, + 72, 207, 17, 106, 62, 124, 55, 193, 236, 210, 93, 61, 129, 36, + 132, 146, 242, 77, 1, 76, 232, 236, 189, 137, 132, 70, 40, 200, + 233, 124, 171, 105, 106, 57, 37, 66, 157, 173, 250, 153, 10, 19, + 151, 170, 27, 114, 54, 48, 6, 24, 169, 151, 208, 71, 109, 237, + 55, 62, 77, 114, 110, 123, 27, 112, 193, 68, 70, 220, 100, 192, + 61, 102, 220, 32, 229, 162, 231, 68, 164, 12, 174, 247, 249, 101, + 26, 240, 176, 123, 155, 89, 84, 29, 220, 106, 92, 29, 178, 47, + 105, 150, 227, 53, 158, 161, 40, 35, 156, 160, 2, 88, 216, 20, + 124, 69, 92, 111, 183, 241, 74, 211, 158, 32, 237, 252, 23, 235, + 177, 178, 172, 242, 160, 124, 75, 172, 84, 15, 197, 103, 127, 149, + 101, 237, 15, 152, 236, 66, 146, 3, 71, 47, 229, 121, 253, 146, + 198, 79, 217, 60, 161, 166, 221, 244, 241, 155, 231, 121, 86, 6, + 152, 58, 250, 217, 125, 36, 195, 14, 34, 103, 63, 67, 205, 148, + 87, 184, 249, 44, 89, 211, 204, 98, 117, 160, 246, 146, 146, 24, + 159, 234, 100, 34, 23, 161, 177, 221, 108, 23, 229, 140, 233, 169, + 92, 163, 145, 109, 113, 78, 131, 149, 30, 8, 188, 155, 102, 171, + 3, 9, 189, 125, 226, 14, 249, 38, 119, 75, 101, 140, 246, 223, + 235, 147, 171, 53, 165, 81, 129, 14, 106, 71, 90, 157, 250, 72, + 116, 18, 165, 115, 235, 245, 182, 250, 1, 79, 165, 54, 11, 59, + 247, 62, 249, 143, 152, 233, 255, 216, 26, 30, 18, 238, 30, 13, + 78, 85, 49, 203, 187, 113, 7, 164, 39, 236, 156, 194, 220, 171, + 56, 125, 184, 172, 167, 7, 127, 120, 127, 62, 176, 23, 163, 177, + 3, 141, 151, 120, 92, 200, 183, 141, 20, 81, 115, 225, 69, 241, + 138, 226, 94, 234, 174, 2, 207, 46, 58, 247, 152, 224, 13, 196, + 36, 18, 75, 239, 197, 191, 27, 186, 56, 181, 69, 153, 57, 24, + 51, 182, 29, 203, 241, 90, 18, 137, 46, 253, 190, 238, 52, 196, + 171, 16, 210, 220, 208, 76, 183, 44, 54, 102, 42, 196, 221, 198, + 42, 105, 14, 120, 229, 167, 36, 133, 23, 53, 102, 149, 252, 134, + 204, 77, 166, 66, 206, 2, 188, 38, 17, 110, 183, 242, 9, 21, + 5, 198, 121, 142, 153, 191, 138, 64, 49, 217, 77, 114, 161, 10, + 185, 248, 229, 27, 168, 94, 128, 202, 135, 2, 146, 249, 218, 117, + 20, 91, 185, 243, 6, 177, 242, 46, 171, 113, 171, 231, 60, 62, + 151, 84, 37, 246, 140, 201, 112, 188, 96, 243, 227, 121, 98, 39, + 246, 81, 144, 231, 59, 22, 3, 224, 18, 70, 186, 235, 241, 242, + 10, 181, 194, 224, 230, 52, 1, 46, 234, 74, 68, 142, 172, 36, + 139, 70, 193, 162, 127, 213, 1, 146, 234, 98, 143, 245, 147, 38, + 238, 74, 200, 191, 34, 224, 128, 232, 37, 120, 191, 239, 219, 87, + 63, 240, 153, 136, 229, 88, 77, 138, 242, 60, 12, 215, 181, 141, + 78, 167, 77, 225, 95, 1, 126, 49, 96, 161, 211, 160, 175, 117, + 231, 1, 43, 70, 232, 87, 217, 86, 236, 89, 38, 130, 16, 6, + 248, 77, 121, 187, 221, 200, 197, 236, 11, 226, 165, 30, 216, 23, + 212, 218, 199, 224, 136, 80, 99, 207, 216, 80, 62, 82, 229, 33, + 41, 52, 58, 98, 167, 83, 253, 129, 20, 211, 46, 55, 104, 27, + 51, 144, 221, 29, 97, 1, 81, 249, 189, 55, 134, 129, 69, 78, + 227, 199, 211, 213, 100, 166, 7, 92, 212, 102, 100, 145, 237, 149, + 128, 34, 79, 60, 229, 135, 39, 56, 151, 195, 84, 51, 82, 145, + 140, 87, 247, 72, 229, 125, 70, 255, 195, 62, 180, 80, 86, 27, + 166, 6, 107, 223, 17, 225, 74, 69, 21, 23, 105, 96, 36, 116, + 196, 34, 37, 171, 136, 238, 124, 116, 45, 127, 51, 164, 180, 130, + 195, 53, 15, 137, 250, 207, 202, 107, 146, 152, 229, 211, 6, 165, + 156, 50, 97, 13, 63, 218, 184, 127, 251, 179, 108, 242, 74, 242, + 129, 5, 201, 125, 55, 16, 115, 20, 244, 160, 53, 234, 170, 193, + 137, 201, 111, 199, 170, 235, 22, 203, 9, 231, 172, 144, 107, 64, + 228, 22, 56, 62, 27, 230, 247, 17, 11, 37, 239, 96, 116, 69, + 79, 223, 30, 68, 212, 20, 23, 96, 240, 13, 74, 159, 236, 135, + 37, 115, 185, 248, 13, 33, 55, 40, 71, 224, 219, 81, 206, 249, + 162, 156, 101, 204, 206, 190, 187, 132, 59, 170, 146, 93, 56, 93, + 251, 169, 210, 233, 81, 183, 105, 248, 103, 121, 16, 3, 45, 252, + 115, 81, 54, 169, 131, 128, 88, 239, 198, 194, 26, 16, 244, 146, + 16, 21, 135, 82, 80, 58, 165, 100, 126, 127, 155, 25, 44, 15, + 43, 0, 128, 29, 18, 21, 252, 233, 119, 251, 88, 95, 199, 231, + 106, 144, 153, 197, 137, 187, 166, 83, 163, 174, 3, 215, 163, 166, + 220, 27, 183, 230, 247, 36, 86, 184, 107, 243, 224, 217, 173, 147, + 122, 81, 97, 227, 29, 163, 59, 148, 169, 202, 200, 9, 168, 216, + 13, 195, 48, 242, 77, 53, 216, 168, 105, 233, 155, 108, 183, 76, + 234, 134, 222, 135, 212, 22, 145, 34, 127, 240, 122, 180, 200, 240, + 247, 255, 135, 177, 122, 241, 155, 117, 53, 205, 167, 134, 98, 21, + 47, 252, 40, 192, 88, 196, 164, 117, 172, 85, 106, 192, 111, 106, + 23, 59, 100, 144, 78, 216, 2, 85, 4, 9, 91, 94, 232, 21, + 38, 162, 23, 25, 101, 46, 179, 178, 171, 219, 158, 229, 76, 118, + 206, 113, 11, 212, 0, 230, 144, 56, 64, 239, 73, 145, 195, 189, + 210, 109, 62, 27, 51, 211, 179, 21, 212, 127, 70, 233, 213, 14, + 110, 154, 212, 204, 211, 3, 118, 172, 254, 3, 184, 193, 122, 77, + 169, 254, 189, 159, 207, 89, 145, 190, 92, 68, 40, 127, 252, 146, + 186, 66, 174, 176, 192, 227, 239, 128, 216, 237, 169, 185, 84, 106, + 173, 123, 137, 184, 11, 207, 58, 108, 178, 193, 93, 56, 51, 207, + 70, 44, 128, 48, 84, 66, 114, 28, 83, 252, 213, 88, 139, 108, + 182, 152, 90, 168, 180, 146, 67, 152, 27, 26, 116, 90, 177, 184, + 44, 99, 232, 145, 62, 248, 41, 141, 54, 211, 193, 72, 96, 200, + 134, 136, 39, 86, 37, 143, 241, 151, 239, 177, 232, 246, 49, 42, + 24, 114, 172, 165, 244, 101, 170, 35, 133, 124, 207, 28, 117, 145, + 42, 39, 150, 7, 127, 75, 18, 20, 137, 113, 61, 73, 73, 200, + 18, 103, 191, 27, 189, 192, 20, 42, 161, 204, 187, 248, 9, 250, + 39, 172, 79, 8, 115, 113, 206, 134, 203, 34, 181, 151, 186, 213, + 112, 170, 223, 214, 205, 206, 180, 193, 158, 197, 249, 72, 9, 66, + 228, 97, 109, 8, 10, 204, 167, 250, 57, 189, 68, 160, 133, 19, + 242, 108, 99, 217, 253, 9, 67, 121, 3, 135, 29, 224, 79, 248, + 129, 222, 61, 80, 65, 47, 87, 131, 81, 216, 117, 200, 17, 83, + 178, 177, 21, 115, 34, 180, 179, 110, 121, 33, 199, 39, 123, 52, + 104, 139, 109, 83, 193, 49, 6, 200, 189, 226, 246, 15, 178, 177, + 239, 7, 85, 203, 201, 80, 172, 106, 25, 195, 222, 255, 221, 159, + 158, 220, 113, 26, 126, 221, 247, 184, 5, 80, 42, 128, 165, 110, + 72, 214, 159, 66, 78, 228, 41, 42, 140, 179, 194, 160, 205, 193, + 32, 83, 37, 243, 89, 73, 6, 124, 229, 105, 150, 124, 168, 116, + 229, 129, 157, 225, 4, 148, 189, 156, 127, 235, 69, 3, 241, 238, + 140, 12, 210, 138, 235, 62, 222, 93, 5, 34, 177, 8, 43, 147, + 249, 152, 115, 80, 202, 134, 86, 201, 215, 246, 109, 228, 217, 129, + 234, 47, 53, 179, 142, 195, 229, 79, 247, 12, 135, 184, 26, 144, + 239, 151, 2, 69, 162, 89, 172, 141, 211, 201, 172, 21, 24, 131, + 97, 92, 65, 116, 13, 192, 4, 52, 165, 251, 189, 71, 164, 69, + 197, 201, 67, 230, 223, 30, 253, 110, 153, 40, 121, 122, 91, 34, + 7, 105, 176, 247, 214, 23, 32, 106, 212, 132, 105, 231, 61, 196, + 63, 152, 232, 185, 65, 55, 140, 195, 107, 226, 205, 174, 13, 241, + 188, 198, 216, 207, 92, 24, 121, 74, 247, 8, 247, 128, 1, 20, + 2, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 13, 99, 108, 101, 97, 114, 116, 111, 109, 97, + 114, 107, 13, 128, 3, +}; diff --git a/Rendering/fonts/face_times_italic.cxx b/Rendering/fonts/face_times_italic.cxx new file mode 100644 index 0000000..ec707b7 --- /dev/null +++ b/Rendering/fonts/face_times_italic.cxx @@ -0,0 +1,2519 @@ +#include "vtkEmbeddedFonts.h" + +// VTK: Times Italic +// Bitstream Charter Regular Italic (c0649bt_.pfb) +// Contributed by Bitstream (XFree86) + +size_t face_times_italic_buffer_length = 35118; + +unsigned char face_times_italic_buffer[] = { + 128, 1, 227, 5, 0, 0, 37, 33, 80, 83, 45, 65, 100, 111, + 98, 101, 70, 111, 110, 116, 45, 49, 46, 48, 13, 37, 37, 67, + 114, 101, 97, 116, 105, 111, 110, 68, 97, 116, 101, 58, 32, 70, + 114, 105, 32, 78, 111, 118, 32, 32, 50, 32, 49, 57, 58, 48, + 51, 58, 53, 52, 32, 49, 57, 57, 48, 13, 37, 32, 66, 105, + 116, 115, 116, 114, 101, 97, 109, 32, 84, 121, 112, 101, 32, 49, + 32, 70, 111, 110, 116, 32, 80, 114, 111, 103, 114, 97, 109, 13, + 37, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 49, 57, + 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, 112, 117, 98, + 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, 32, 98, 121, + 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, 99, + 46, 44, 32, 67, 97, 109, 98, 114, 105, 100, 103, 101, 44, 32, + 77, 65, 46, 13, 37, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 13, 37, + 32, 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 32, + 97, 110, 100, 32, 112, 114, 111, 112, 114, 105, 101, 116, 97, 114, + 121, 32, 116, 111, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 73, 110, 99, 46, 13, 37, 32, 85, 46, 83, 46, 32, 71, + 79, 86, 69, 82, 78, 77, 69, 78, 84, 32, 82, 69, 83, 84, + 82, 73, 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 13, + 37, 32, 84, 104, 105, 115, 32, 115, 111, 102, 116, 119, 97, 114, + 101, 32, 116, 121, 112, 101, 102, 97, 99, 101, 32, 112, 114, 111, + 100, 117, 99, 116, 32, 105, 115, 32, 112, 114, 111, 118, 105, 100, + 101, 100, 32, 119, 105, 116, 104, 32, 82, 69, 83, 84, 82, 73, + 67, 84, 69, 68, 32, 82, 73, 71, 72, 84, 83, 46, 32, 85, + 115, 101, 44, 13, 37, 32, 100, 117, 112, 108, 105, 99, 97, 116, + 105, 111, 110, 32, 111, 114, 32, 100, 105, 115, 99, 108, 111, 115, + 117, 114, 101, 32, 98, 121, 32, 116, 104, 101, 32, 71, 111, 118, + 101, 114, 110, 109, 101, 110, 116, 32, 105, 115, 32, 115, 117, 98, + 106, 101, 99, 116, 32, 116, 111, 32, 114, 101, 115, 116, 114, 105, + 99, 116, 105, 111, 110, 115, 13, 37, 32, 97, 115, 32, 115, 101, + 116, 32, 102, 111, 114, 116, 104, 32, 105, 110, 32, 116, 104, 101, + 32, 108, 105, 99, 101, 110, 115, 101, 32, 97, 103, 114, 101, 101, + 109, 101, 110, 116, 32, 97, 110, 100, 32, 105, 110, 32, 70, 65, + 82, 32, 53, 50, 46, 50, 50, 55, 45, 49, 57, 32, 40, 99, + 41, 32, 40, 50, 41, 32, 40, 77, 97, 121, 44, 32, 49, 57, + 56, 55, 41, 44, 13, 37, 32, 119, 104, 101, 110, 32, 97, 112, + 112, 108, 105, 99, 97, 98, 108, 101, 44, 32, 111, 114, 32, 116, + 104, 101, 32, 97, 112, 112, 108, 105, 99, 97, 98, 108, 101, 32, + 112, 114, 111, 118, 105, 115, 105, 111, 110, 115, 32, 111, 102, 32, + 116, 104, 101, 32, 68, 79, 68, 32, 70, 65, 82, 32, 115, 117, + 112, 112, 108, 101, 109, 101, 110, 116, 13, 37, 32, 50, 53, 50, + 46, 50, 50, 55, 45, 55, 48, 49, 51, 32, 115, 117, 98, 100, + 105, 118, 105, 115, 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, + 53, 41, 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, + 56, 41, 32, 111, 114, 32, 115, 117, 98, 100, 105, 118, 105, 115, + 105, 111, 110, 32, 40, 97, 41, 32, 40, 49, 55, 41, 13, 37, + 32, 40, 65, 112, 114, 105, 108, 44, 32, 49, 57, 56, 56, 41, + 46, 32, 32, 67, 111, 110, 116, 114, 97, 99, 116, 111, 114, 47, + 109, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 32, 105, + 115, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 44, 13, 37, 32, 50, 49, 53, 32, 70, 105, 114, 115, + 116, 32, 83, 116, 114, 101, 101, 116, 44, 32, 67, 97, 109, 98, + 114, 105, 100, 103, 101, 44, 32, 77, 65, 32, 48, 50, 49, 52, + 50, 46, 13, 37, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, + 32, 105, 115, 32, 97, 32, 114, 101, 103, 105, 115, 116, 101, 114, + 101, 100, 32, 116, 114, 97, 100, 101, 109, 97, 114, 107, 32, 111, + 102, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, 73, 110, + 99, 46, 13, 49, 49, 32, 100, 105, 99, 116, 32, 98, 101, 103, + 105, 110, 13, 47, 70, 111, 110, 116, 73, 110, 102, 111, 32, 57, + 32, 100, 105, 99, 116, 32, 100, 117, 112, 32, 98, 101, 103, 105, + 110, 13, 32, 32, 47, 118, 101, 114, 115, 105, 111, 110, 32, 40, + 50, 46, 48, 45, 49, 46, 48, 41, 32, 114, 101, 97, 100, 111, + 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 78, 111, 116, + 105, 99, 101, 32, 40, 67, 111, 112, 121, 114, 105, 103, 104, 116, + 32, 49, 57, 57, 48, 32, 97, 115, 32, 97, 110, 32, 117, 110, + 112, 117, 98, 108, 105, 115, 104, 101, 100, 32, 119, 111, 114, 107, + 32, 98, 121, 32, 66, 105, 116, 115, 116, 114, 101, 97, 109, 32, + 73, 110, 99, 46, 32, 32, 65, 108, 108, 32, 114, 105, 103, 104, + 116, 115, 32, 114, 101, 115, 101, 114, 118, 101, 100, 46, 32, 32, + 67, 111, 110, 102, 105, 100, 101, 110, 116, 105, 97, 108, 46, 41, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 32, 32, 47, 70, 117, 108, 108, 78, 97, 109, 101, 32, 40, 66, + 105, 116, 115, 116, 114, 101, 97, 109, 32, 67, 104, 97, 114, 116, + 101, 114, 32, 73, 116, 97, 108, 105, 99, 41, 32, 114, 101, 97, + 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, 32, 32, 47, 70, + 97, 109, 105, 108, 121, 78, 97, 109, 101, 32, 40, 66, 105, 116, + 115, 116, 114, 101, 97, 109, 32, 67, 104, 97, 114, 116, 101, 114, + 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, + 13, 32, 32, 47, 87, 101, 105, 103, 104, 116, 32, 40, 78, 111, + 114, 109, 97, 108, 41, 32, 114, 101, 97, 100, 111, 110, 108, 121, + 32, 100, 101, 102, 13, 32, 32, 47, 73, 116, 97, 108, 105, 99, + 65, 110, 103, 108, 101, 32, 32, 49, 49, 46, 48, 48, 48, 48, + 32, 100, 101, 102, 13, 32, 32, 47, 105, 115, 70, 105, 120, 101, + 100, 80, 105, 116, 99, 104, 32, 102, 97, 108, 115, 101, 32, 100, + 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, 105, 110, + 101, 80, 111, 115, 105, 116, 105, 111, 110, 32, 45, 49, 48, 57, + 32, 100, 101, 102, 13, 32, 32, 47, 85, 110, 100, 101, 114, 108, + 105, 110, 101, 84, 104, 105, 99, 107, 110, 101, 115, 115, 32, 54, + 49, 32, 100, 101, 102, 13, 101, 110, 100, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 70, 111, 110, 116, + 78, 97, 109, 101, 32, 47, 67, 104, 97, 114, 116, 101, 114, 66, + 84, 45, 73, 116, 97, 108, 105, 99, 32, 100, 101, 102, 13, 47, + 80, 97, 105, 110, 116, 84, 121, 112, 101, 32, 48, 32, 100, 101, + 102, 13, 47, 70, 111, 110, 116, 84, 121, 112, 101, 32, 49, 32, + 100, 101, 102, 13, 47, 70, 111, 110, 116, 77, 97, 116, 114, 105, + 120, 32, 91, 48, 46, 48, 48, 49, 32, 48, 32, 48, 32, 48, + 46, 48, 48, 49, 32, 48, 32, 48, 93, 32, 114, 101, 97, 100, + 111, 110, 108, 121, 32, 100, 101, 102, 13, 47, 69, 110, 99, 111, + 100, 105, 110, 103, 32, 83, 116, 97, 110, 100, 97, 114, 100, 69, + 110, 99, 111, 100, 105, 110, 103, 32, 100, 101, 102, 13, 47, 70, + 111, 110, 116, 66, 66, 111, 120, 32, 123, 45, 50, 50, 54, 32, + 45, 50, 51, 54, 32, 49, 49, 55, 52, 32, 57, 56, 48, 125, + 32, 114, 101, 97, 100, 111, 110, 108, 121, 32, 100, 101, 102, 13, + 47, 85, 110, 105, 113, 117, 101, 73, 68, 32, 49, 53, 53, 51, + 48, 54, 52, 57, 32, 100, 101, 102, 13, 99, 117, 114, 114, 101, + 110, 116, 100, 105, 99, 116, 32, 101, 110, 100, 13, 99, 117, 114, + 114, 101, 110, 116, 102, 105, 108, 101, 32, 101, 101, 120, 101, 99, + 13, 128, 2, 35, 129, 0, 0, 162, 149, 24, 64, 131, 138, 65, + 51, 131, 156, 169, 210, 46, 43, 153, 242, 182, 28, 118, 124, 214, + 117, 8, 10, 172, 252, 178, 78, 25, 205, 19, 54, 115, 155, 182, + 73, 148, 197, 103, 55, 9, 11, 76, 236, 146, 201, 148, 95, 240, + 116, 94, 247, 255, 198, 27, 176, 169, 163, 184, 73, 231, 233, 135, + 64, 229, 108, 11, 90, 247, 135, 85, 156, 198, 149, 106, 179, 30, + 51, 207, 133, 83, 213, 92, 11, 14, 129, 142, 245, 236, 107, 244, + 129, 98, 234, 196, 46, 115, 128, 202, 146, 29, 174, 28, 130, 179, + 143, 214, 188, 242, 0, 26, 187, 93, 0, 26, 86, 21, 112, 148, + 207, 226, 125, 143, 78, 172, 150, 147, 232, 131, 114, 210, 3, 88, + 180, 126, 12, 56, 118, 85, 142, 191, 117, 122, 31, 188, 92, 28, + 221, 246, 43, 60, 87, 191, 114, 126, 241, 196, 135, 148, 34, 193, + 66, 160, 132, 209, 199, 70, 42, 194, 147, 224, 151, 250, 190, 58, + 62, 207, 205, 130, 113, 242, 89, 131, 59, 172, 121, 18, 112, 114, + 24, 236, 154, 48, 99, 191, 115, 133, 224, 45, 140, 16, 88, 172, + 6, 223, 0, 179, 59, 140, 1, 135, 104, 178, 120, 1, 14, 177, + 76, 138, 45, 157, 229, 245, 52, 98, 65, 225, 84, 87, 79, 5, + 197, 212, 222, 191, 106, 184, 185, 27, 157, 151, 190, 59, 16, 36, + 174, 38, 255, 73, 175, 226, 101, 194, 34, 162, 243, 132, 53, 232, + 146, 182, 246, 32, 230, 172, 209, 98, 108, 228, 176, 0, 164, 145, + 13, 39, 189, 179, 211, 33, 139, 26, 41, 200, 70, 116, 210, 205, + 212, 115, 51, 54, 135, 212, 78, 179, 65, 225, 221, 116, 56, 111, + 44, 157, 16, 27, 239, 43, 74, 216, 76, 156, 225, 61, 205, 94, + 169, 50, 113, 185, 72, 158, 127, 173, 193, 118, 254, 113, 157, 143, + 84, 15, 241, 10, 63, 136, 180, 59, 18, 99, 155, 151, 127, 159, + 120, 89, 3, 185, 96, 69, 108, 47, 199, 101, 99, 111, 1, 200, + 16, 188, 242, 50, 244, 160, 231, 180, 103, 224, 230, 162, 5, 195, + 100, 185, 163, 99, 110, 227, 100, 251, 93, 162, 199, 201, 210, 153, + 153, 141, 232, 81, 80, 255, 32, 43, 249, 150, 188, 187, 26, 131, + 72, 192, 27, 153, 77, 229, 226, 160, 69, 232, 133, 47, 93, 140, + 123, 89, 88, 50, 219, 53, 248, 17, 125, 95, 44, 60, 97, 114, + 185, 219, 41, 143, 128, 83, 118, 176, 193, 107, 8, 248, 153, 3, + 106, 151, 244, 108, 104, 42, 212, 133, 35, 205, 111, 137, 28, 66, + 70, 167, 183, 36, 86, 254, 206, 248, 195, 186, 198, 84, 109, 151, + 54, 176, 201, 83, 0, 216, 224, 161, 103, 231, 22, 7, 0, 72, + 128, 145, 91, 54, 237, 70, 117, 53, 55, 193, 4, 150, 125, 85, + 222, 109, 147, 212, 182, 245, 150, 65, 7, 162, 167, 187, 7, 12, + 148, 23, 143, 66, 80, 138, 36, 153, 230, 140, 67, 182, 233, 153, + 97, 131, 153, 170, 75, 58, 13, 122, 14, 194, 186, 94, 68, 229, + 154, 218, 174, 238, 174, 34, 180, 181, 61, 159, 246, 189, 90, 58, + 105, 130, 236, 25, 24, 240, 221, 188, 238, 223, 76, 45, 245, 137, + 247, 107, 122, 241, 87, 110, 50, 2, 5, 232, 61, 183, 177, 70, + 119, 87, 191, 154, 121, 57, 24, 140, 184, 171, 128, 71, 220, 166, + 216, 174, 217, 110, 239, 62, 210, 50, 83, 83, 40, 104, 172, 115, + 187, 183, 160, 67, 114, 74, 16, 146, 135, 177, 181, 48, 8, 158, + 39, 80, 170, 99, 122, 130, 20, 152, 101, 24, 216, 238, 190, 108, + 142, 71, 27, 183, 83, 177, 4, 218, 238, 219, 199, 50, 24, 112, + 241, 216, 208, 176, 179, 186, 183, 58, 120, 8, 88, 37, 14, 83, + 185, 192, 44, 103, 171, 158, 69, 137, 197, 185, 33, 139, 14, 243, + 231, 26, 87, 154, 149, 87, 105, 46, 183, 57, 204, 42, 220, 85, + 31, 245, 254, 239, 27, 164, 111, 199, 70, 0, 250, 154, 101, 38, + 182, 52, 75, 154, 121, 107, 115, 37, 252, 239, 180, 176, 243, 113, + 143, 77, 185, 203, 139, 175, 17, 202, 168, 41, 121, 54, 114, 138, + 196, 7, 207, 50, 212, 47, 33, 189, 55, 74, 64, 110, 152, 147, + 96, 15, 47, 146, 198, 184, 116, 225, 80, 205, 8, 207, 49, 150, + 68, 40, 171, 60, 154, 99, 3, 5, 137, 225, 121, 196, 32, 176, + 228, 96, 49, 183, 98, 86, 17, 85, 173, 63, 129, 158, 222, 88, + 111, 204, 120, 173, 132, 54, 154, 95, 102, 93, 192, 82, 7, 10, + 150, 215, 234, 35, 183, 214, 206, 202, 241, 42, 234, 46, 61, 63, + 110, 50, 149, 102, 199, 54, 189, 200, 166, 88, 243, 120, 24, 255, + 242, 119, 7, 243, 49, 103, 120, 232, 157, 214, 27, 119, 211, 111, + 133, 59, 88, 133, 62, 225, 157, 35, 186, 23, 89, 248, 147, 235, + 1, 113, 23, 136, 128, 219, 133, 206, 102, 55, 23, 202, 104, 250, + 86, 89, 60, 23, 51, 213, 85, 110, 252, 86, 136, 137, 93, 182, + 254, 174, 237, 215, 23, 79, 199, 17, 115, 227, 176, 139, 74, 93, + 123, 85, 236, 124, 232, 54, 73, 249, 111, 74, 198, 182, 164, 117, + 209, 187, 58, 84, 176, 130, 174, 114, 157, 48, 157, 227, 171, 221, + 205, 125, 28, 18, 67, 62, 138, 167, 71, 21, 15, 119, 39, 33, + 252, 17, 110, 33, 49, 60, 34, 127, 189, 64, 22, 42, 190, 212, + 48, 11, 236, 158, 68, 191, 141, 97, 117, 78, 92, 128, 68, 224, + 88, 148, 209, 109, 236, 145, 157, 131, 129, 249, 227, 169, 50, 244, + 241, 17, 143, 249, 35, 151, 46, 190, 191, 78, 26, 239, 103, 43, + 105, 248, 225, 80, 83, 189, 208, 164, 77, 102, 189, 13, 6, 225, + 114, 119, 145, 250, 219, 156, 24, 222, 72, 213, 110, 1, 248, 226, + 121, 132, 140, 151, 169, 128, 222, 172, 127, 68, 178, 193, 145, 243, + 118, 1, 13, 122, 238, 132, 170, 33, 255, 90, 192, 2, 160, 227, + 118, 125, 113, 84, 210, 168, 142, 54, 238, 113, 113, 17, 196, 91, + 170, 167, 130, 118, 28, 137, 10, 141, 248, 161, 79, 115, 242, 130, + 35, 72, 121, 178, 72, 78, 104, 32, 135, 171, 188, 249, 252, 67, + 114, 42, 239, 116, 172, 251, 150, 190, 59, 249, 144, 162, 178, 80, + 73, 221, 80, 48, 207, 58, 129, 254, 51, 94, 219, 73, 244, 211, + 50, 52, 139, 89, 127, 100, 230, 235, 5, 207, 193, 122, 235, 72, + 76, 79, 252, 49, 65, 188, 72, 14, 19, 8, 199, 210, 35, 124, + 247, 50, 55, 195, 171, 109, 194, 167, 66, 69, 67, 243, 16, 40, + 114, 182, 63, 31, 152, 181, 63, 110, 185, 117, 182, 64, 24, 116, + 65, 128, 109, 88, 216, 132, 21, 226, 115, 86, 35, 80, 67, 245, + 251, 43, 25, 114, 84, 44, 221, 230, 255, 229, 202, 145, 42, 23, + 177, 29, 169, 80, 242, 216, 168, 142, 29, 238, 87, 89, 46, 203, + 156, 245, 103, 12, 252, 41, 199, 39, 138, 117, 14, 194, 151, 181, + 116, 66, 221, 29, 68, 32, 39, 75, 250, 120, 243, 202, 167, 11, + 89, 201, 173, 247, 208, 205, 31, 249, 199, 97, 201, 20, 226, 39, + 73, 19, 170, 182, 232, 244, 163, 23, 92, 169, 234, 164, 89, 110, + 8, 233, 148, 3, 51, 181, 194, 88, 92, 4, 80, 93, 67, 5, + 157, 118, 129, 1, 43, 248, 64, 253, 109, 176, 90, 160, 2, 59, + 53, 76, 228, 34, 35, 13, 2, 227, 16, 191, 134, 41, 162, 155, + 201, 169, 236, 241, 221, 144, 156, 192, 184, 254, 243, 101, 118, 62, + 196, 182, 57, 100, 167, 225, 65, 124, 0, 124, 82, 115, 213, 142, + 48, 236, 187, 48, 118, 225, 51, 234, 36, 15, 143, 67, 237, 44, + 226, 137, 123, 190, 3, 228, 17, 52, 223, 231, 17, 233, 136, 11, + 240, 238, 136, 100, 41, 59, 44, 6, 199, 183, 208, 55, 220, 254, + 35, 222, 91, 124, 138, 251, 96, 83, 234, 87, 25, 130, 5, 149, + 255, 64, 28, 201, 100, 98, 183, 54, 119, 151, 150, 169, 27, 217, + 142, 192, 162, 199, 192, 66, 232, 121, 67, 205, 202, 216, 88, 163, + 33, 221, 244, 114, 133, 92, 75, 99, 5, 186, 79, 233, 30, 242, + 71, 135, 193, 171, 23, 159, 173, 87, 118, 203, 248, 88, 159, 72, + 181, 245, 9, 163, 234, 253, 80, 33, 201, 32, 75, 156, 24, 220, + 243, 98, 190, 38, 216, 36, 208, 196, 175, 44, 139, 92, 52, 94, + 151, 241, 29, 30, 27, 107, 251, 207, 107, 99, 150, 219, 126, 9, + 252, 80, 25, 231, 181, 176, 17, 112, 97, 78, 203, 110, 93, 160, + 185, 208, 46, 138, 57, 186, 66, 182, 217, 240, 152, 164, 114, 235, + 75, 219, 163, 65, 156, 99, 69, 103, 224, 178, 164, 30, 189, 132, + 163, 225, 14, 248, 136, 137, 65, 188, 61, 182, 238, 209, 98, 47, + 17, 112, 208, 115, 57, 124, 150, 147, 20, 140, 114, 74, 62, 111, + 4, 27, 71, 6, 41, 36, 250, 25, 103, 97, 144, 255, 155, 13, + 146, 118, 205, 144, 133, 6, 199, 174, 125, 49, 146, 94, 231, 211, + 65, 52, 221, 105, 82, 123, 26, 170, 43, 122, 245, 222, 14, 89, + 164, 255, 124, 248, 126, 56, 42, 157, 172, 12, 64, 174, 126, 230, + 38, 174, 222, 111, 38, 164, 13, 23, 72, 154, 88, 237, 74, 82, + 26, 213, 88, 153, 147, 15, 212, 148, 184, 11, 8, 181, 223, 56, + 29, 31, 251, 241, 238, 57, 85, 249, 250, 218, 2, 34, 241, 154, + 0, 112, 41, 67, 159, 14, 205, 64, 107, 197, 249, 220, 60, 251, + 48, 202, 14, 62, 174, 241, 114, 100, 39, 139, 157, 139, 46, 178, + 40, 174, 12, 61, 80, 40, 247, 31, 215, 97, 228, 227, 167, 120, + 130, 114, 220, 163, 172, 229, 242, 156, 180, 169, 51, 2, 21, 173, + 207, 81, 216, 113, 15, 107, 129, 133, 182, 154, 2, 185, 150, 197, + 128, 82, 153, 248, 114, 6, 160, 43, 231, 125, 63, 54, 101, 81, + 166, 131, 74, 101, 23, 96, 42, 41, 57, 95, 112, 90, 59, 251, + 14, 161, 30, 254, 86, 123, 89, 39, 157, 24, 241, 36, 31, 87, + 244, 205, 39, 42, 243, 106, 115, 22, 137, 247, 35, 52, 0, 132, + 161, 150, 156, 27, 170, 133, 108, 246, 26, 39, 176, 227, 162, 247, + 206, 35, 227, 221, 176, 126, 26, 30, 21, 4, 251, 202, 68, 9, + 0, 52, 23, 205, 37, 151, 141, 221, 32, 138, 107, 193, 134, 113, + 24, 127, 196, 43, 119, 227, 40, 44, 204, 191, 234, 1, 65, 151, + 223, 254, 56, 177, 46, 57, 109, 114, 153, 236, 243, 40, 27, 207, + 3, 164, 22, 43, 249, 138, 239, 48, 67, 86, 168, 150, 141, 192, + 215, 186, 103, 14, 16, 28, 72, 234, 163, 71, 115, 77, 228, 143, + 130, 111, 171, 143, 89, 254, 48, 18, 222, 109, 50, 50, 205, 136, + 191, 32, 69, 58, 156, 158, 56, 38, 166, 130, 125, 55, 252, 217, + 185, 1, 231, 198, 87, 248, 184, 130, 6, 105, 62, 204, 205, 162, + 16, 180, 223, 138, 100, 67, 81, 39, 179, 31, 141, 245, 140, 83, + 200, 242, 127, 165, 144, 43, 234, 196, 254, 9, 32, 97, 210, 228, + 73, 217, 218, 110, 72, 117, 183, 32, 113, 16, 132, 1, 78, 47, + 84, 123, 124, 54, 59, 215, 250, 188, 130, 202, 159, 91, 126, 132, + 24, 114, 93, 252, 1, 202, 28, 206, 184, 218, 231, 231, 207, 35, + 13, 215, 216, 110, 187, 190, 168, 121, 118, 156, 69, 159, 129, 108, + 97, 103, 112, 96, 65, 218, 92, 163, 141, 111, 74, 198, 11, 101, + 69, 94, 118, 3, 253, 79, 178, 238, 211, 159, 151, 157, 21, 225, + 107, 18, 190, 116, 161, 9, 170, 111, 253, 208, 75, 157, 179, 222, + 184, 48, 236, 82, 109, 68, 88, 250, 184, 133, 211, 151, 200, 65, + 191, 206, 193, 75, 62, 16, 9, 103, 234, 186, 26, 73, 153, 143, + 225, 234, 47, 26, 57, 128, 67, 1, 48, 81, 73, 10, 90, 18, + 10, 160, 147, 134, 160, 205, 209, 147, 223, 36, 202, 141, 244, 226, + 211, 3, 84, 45, 125, 222, 118, 155, 169, 62, 60, 115, 2, 97, + 108, 72, 53, 68, 29, 209, 179, 3, 39, 106, 163, 88, 229, 140, + 16, 134, 133, 167, 121, 79, 144, 129, 101, 177, 135, 195, 232, 187, + 118, 135, 8, 40, 229, 214, 4, 138, 68, 16, 167, 150, 122, 87, + 72, 118, 245, 45, 101, 204, 163, 181, 68, 63, 125, 58, 249, 22, + 48, 163, 44, 210, 168, 187, 172, 120, 187, 160, 163, 222, 128, 184, + 237, 72, 101, 64, 61, 188, 205, 107, 241, 61, 226, 206, 101, 167, + 199, 96, 248, 250, 46, 209, 104, 255, 145, 59, 104, 27, 87, 251, + 74, 216, 40, 84, 56, 224, 185, 217, 199, 169, 72, 207, 129, 60, + 104, 81, 215, 198, 122, 184, 9, 181, 207, 42, 167, 208, 32, 163, + 140, 39, 53, 177, 78, 114, 19, 231, 189, 227, 127, 196, 165, 44, + 45, 251, 37, 173, 36, 102, 76, 156, 135, 89, 238, 203, 202, 81, + 43, 130, 255, 55, 25, 206, 138, 146, 104, 212, 228, 153, 153, 17, + 159, 58, 134, 38, 210, 106, 151, 185, 13, 9, 187, 242, 240, 179, + 9, 200, 172, 195, 5, 247, 185, 119, 96, 210, 19, 223, 10, 91, + 247, 104, 88, 197, 236, 248, 113, 72, 100, 186, 42, 76, 229, 245, + 197, 9, 138, 160, 78, 119, 188, 175, 184, 116, 110, 37, 12, 52, + 74, 219, 151, 70, 227, 248, 232, 130, 180, 40, 4, 233, 110, 184, + 236, 71, 104, 57, 207, 16, 117, 42, 201, 39, 240, 12, 164, 155, + 214, 158, 25, 240, 190, 107, 231, 167, 229, 71, 87, 25, 27, 199, + 40, 111, 99, 1, 203, 55, 109, 109, 13, 123, 53, 227, 208, 72, + 130, 163, 227, 110, 108, 20, 138, 201, 14, 113, 19, 46, 174, 219, + 193, 34, 161, 203, 175, 148, 238, 5, 136, 22, 48, 133, 168, 27, + 245, 206, 2, 217, 243, 20, 195, 66, 13, 95, 222, 126, 249, 131, + 254, 34, 56, 69, 77, 35, 109, 17, 179, 68, 154, 37, 214, 62, + 146, 8, 47, 98, 80, 206, 222, 141, 135, 12, 174, 47, 72, 15, + 200, 3, 159, 224, 200, 246, 20, 122, 200, 169, 208, 109, 222, 210, + 186, 200, 76, 170, 130, 213, 111, 249, 235, 24, 169, 148, 181, 12, + 25, 38, 163, 123, 93, 250, 126, 53, 221, 185, 30, 202, 98, 190, + 85, 135, 64, 174, 85, 180, 51, 49, 27, 75, 5, 208, 21, 126, + 59, 56, 52, 254, 166, 193, 171, 239, 57, 84, 221, 173, 174, 210, + 199, 216, 233, 188, 60, 101, 76, 79, 21, 227, 48, 249, 137, 13, + 238, 112, 200, 71, 251, 110, 14, 42, 87, 251, 164, 171, 181, 139, + 49, 212, 188, 95, 188, 103, 105, 90, 43, 236, 0, 119, 218, 253, + 168, 167, 66, 230, 21, 232, 99, 121, 207, 173, 5, 83, 145, 249, + 101, 221, 127, 172, 175, 100, 137, 148, 92, 150, 231, 131, 62, 90, + 201, 77, 253, 46, 231, 148, 41, 52, 235, 47, 227, 154, 236, 195, + 74, 52, 10, 107, 228, 164, 147, 15, 201, 190, 120, 178, 129, 85, + 229, 244, 191, 81, 18, 77, 18, 171, 35, 12, 5, 24, 216, 9, + 201, 10, 9, 5, 36, 4, 223, 236, 186, 195, 72, 209, 226, 110, + 22, 101, 152, 1, 88, 117, 234, 27, 15, 17, 140, 222, 169, 251, + 164, 234, 42, 138, 123, 178, 3, 41, 203, 194, 175, 161, 44, 104, + 162, 30, 249, 249, 35, 58, 120, 232, 96, 41, 25, 92, 195, 143, + 200, 34, 132, 123, 233, 145, 207, 17, 12, 33, 80, 20, 102, 18, + 186, 162, 149, 67, 245, 38, 190, 42, 19, 207, 101, 86, 159, 224, + 79, 244, 177, 178, 119, 17, 133, 86, 74, 158, 16, 243, 188, 182, + 18, 19, 39, 149, 16, 238, 152, 144, 236, 146, 173, 26, 61, 191, + 145, 249, 37, 175, 253, 226, 32, 192, 181, 149, 239, 222, 162, 158, + 119, 249, 85, 92, 143, 53, 155, 196, 97, 15, 84, 248, 113, 78, + 66, 104, 41, 31, 159, 31, 29, 59, 29, 234, 166, 112, 207, 166, + 4, 86, 180, 243, 107, 143, 242, 137, 202, 252, 81, 64, 163, 86, + 213, 123, 15, 52, 139, 154, 253, 73, 70, 251, 30, 137, 112, 249, + 44, 230, 112, 63, 184, 38, 241, 149, 106, 186, 222, 39, 20, 138, + 32, 165, 228, 11, 132, 184, 40, 162, 172, 172, 20, 246, 22, 91, + 41, 9, 174, 247, 227, 160, 95, 5, 186, 223, 41, 1, 135, 200, + 37, 201, 227, 191, 217, 106, 78, 139, 179, 190, 251, 42, 174, 68, + 88, 48, 77, 150, 36, 166, 37, 137, 219, 184, 243, 146, 244, 244, + 116, 13, 13, 243, 108, 53, 169, 134, 69, 151, 169, 173, 140, 65, + 204, 149, 193, 45, 64, 3, 122, 35, 119, 51, 198, 18, 84, 25, + 131, 132, 48, 6, 47, 124, 63, 226, 69, 150, 23, 199, 180, 29, + 114, 22, 143, 207, 47, 158, 160, 123, 24, 51, 69, 51, 65, 219, + 6, 1, 71, 141, 167, 73, 99, 132, 89, 27, 163, 83, 102, 177, + 215, 112, 29, 12, 127, 189, 143, 144, 245, 69, 76, 23, 126, 79, + 104, 186, 112, 245, 162, 38, 22, 24, 47, 78, 205, 196, 134, 62, + 2, 136, 149, 3, 252, 236, 14, 176, 30, 234, 27, 175, 55, 112, + 166, 86, 194, 71, 255, 197, 89, 152, 22, 244, 253, 99, 35, 47, + 110, 203, 23, 237, 129, 77, 45, 34, 248, 79, 132, 160, 212, 139, + 229, 128, 179, 4, 190, 202, 69, 85, 145, 193, 31, 56, 243, 114, + 181, 147, 36, 194, 188, 170, 37, 103, 109, 71, 152, 28, 134, 81, + 164, 95, 83, 102, 161, 243, 235, 180, 224, 143, 6, 194, 241, 106, + 16, 173, 216, 171, 251, 169, 138, 41, 117, 20, 55, 204, 92, 2, + 121, 115, 215, 205, 187, 110, 243, 251, 177, 22, 206, 179, 37, 224, + 200, 30, 48, 125, 178, 92, 43, 128, 34, 243, 115, 232, 71, 188, + 16, 165, 186, 107, 75, 118, 198, 107, 222, 180, 200, 2, 39, 217, + 230, 124, 171, 234, 249, 158, 20, 255, 146, 129, 45, 3, 8, 217, + 58, 12, 197, 163, 75, 59, 204, 213, 105, 255, 115, 247, 207, 23, + 83, 50, 237, 158, 22, 221, 81, 189, 233, 232, 83, 227, 244, 103, + 174, 62, 24, 128, 31, 190, 243, 41, 187, 226, 12, 152, 216, 189, + 228, 43, 56, 187, 150, 42, 94, 187, 60, 61, 27, 110, 11, 138, + 231, 106, 240, 43, 16, 73, 169, 168, 122, 7, 172, 245, 25, 10, + 182, 158, 38, 113, 162, 18, 14, 38, 169, 42, 17, 235, 209, 164, + 142, 160, 211, 134, 63, 227, 47, 186, 198, 27, 253, 248, 124, 65, + 137, 163, 228, 21, 37, 76, 166, 60, 67, 51, 84, 162, 232, 13, + 224, 221, 197, 98, 134, 113, 162, 111, 124, 91, 235, 14, 100, 239, + 227, 84, 97, 18, 208, 122, 112, 156, 201, 221, 208, 73, 158, 86, + 223, 148, 244, 67, 136, 23, 255, 178, 57, 52, 29, 253, 16, 59, + 134, 89, 205, 173, 216, 118, 192, 97, 190, 19, 95, 96, 192, 174, + 247, 238, 149, 11, 11, 134, 239, 164, 222, 82, 70, 193, 51, 0, + 177, 60, 206, 154, 147, 160, 149, 198, 245, 203, 234, 34, 57, 202, + 26, 5, 22, 34, 152, 184, 112, 165, 34, 42, 55, 108, 161, 224, + 190, 198, 75, 129, 122, 39, 57, 239, 121, 188, 253, 203, 120, 169, + 247, 150, 16, 231, 65, 190, 131, 73, 243, 105, 153, 143, 104, 165, + 185, 20, 224, 68, 84, 124, 38, 250, 169, 103, 59, 146, 60, 200, + 96, 161, 152, 163, 168, 163, 5, 187, 249, 10, 0, 22, 63, 77, + 237, 172, 233, 217, 49, 91, 91, 85, 123, 75, 202, 205, 14, 222, + 34, 202, 100, 84, 188, 17, 49, 227, 110, 5, 77, 214, 104, 208, + 17, 118, 166, 101, 202, 182, 210, 33, 123, 123, 74, 4, 64, 171, + 17, 4, 92, 73, 27, 95, 32, 84, 249, 195, 242, 98, 252, 202, + 77, 177, 173, 160, 76, 11, 189, 122, 57, 104, 50, 169, 179, 227, + 71, 116, 86, 34, 22, 54, 165, 93, 226, 81, 53, 89, 149, 198, + 50, 157, 116, 123, 183, 18, 229, 143, 191, 60, 189, 26, 47, 20, + 163, 161, 98, 86, 165, 53, 97, 131, 119, 171, 229, 224, 61, 201, + 227, 222, 187, 4, 4, 137, 20, 254, 17, 192, 206, 178, 9, 50, + 44, 210, 0, 69, 0, 222, 223, 234, 98, 103, 226, 68, 141, 178, + 100, 65, 149, 19, 214, 56, 188, 12, 37, 57, 98, 147, 170, 184, + 50, 62, 45, 210, 14, 30, 200, 149, 153, 148, 165, 195, 74, 251, + 247, 83, 57, 120, 235, 50, 29, 142, 206, 37, 165, 120, 173, 59, + 98, 247, 14, 242, 170, 88, 218, 50, 47, 182, 184, 77, 58, 132, + 77, 102, 234, 205, 204, 108, 229, 228, 43, 252, 213, 228, 52, 199, + 63, 245, 76, 0, 70, 47, 116, 162, 253, 174, 13, 6, 17, 59, + 160, 201, 214, 114, 221, 166, 10, 210, 84, 157, 146, 30, 168, 237, + 227, 169, 234, 94, 237, 134, 136, 142, 238, 93, 148, 148, 63, 31, + 38, 171, 209, 134, 81, 128, 106, 78, 48, 169, 125, 206, 46, 111, + 88, 179, 48, 53, 196, 86, 80, 26, 110, 207, 34, 168, 46, 232, + 111, 16, 134, 227, 216, 119, 236, 90, 100, 12, 0, 44, 98, 133, + 68, 187, 143, 179, 228, 203, 29, 253, 250, 246, 37, 183, 16, 213, + 250, 36, 5, 53, 214, 227, 220, 35, 49, 20, 122, 218, 228, 239, + 20, 229, 76, 170, 189, 216, 4, 8, 201, 250, 146, 128, 132, 150, + 234, 195, 116, 4, 101, 214, 162, 38, 150, 44, 144, 132, 96, 162, + 55, 178, 253, 77, 92, 52, 14, 226, 128, 78, 186, 52, 134, 20, + 213, 158, 182, 250, 226, 150, 44, 45, 14, 187, 125, 210, 13, 193, + 76, 145, 93, 180, 247, 85, 128, 57, 53, 96, 149, 195, 202, 234, + 179, 143, 37, 61, 178, 235, 109, 154, 144, 205, 69, 201, 133, 249, + 210, 255, 98, 154, 235, 200, 238, 252, 187, 17, 217, 117, 115, 250, + 200, 162, 55, 18, 16, 207, 161, 240, 142, 219, 26, 153, 208, 77, + 132, 15, 69, 5, 30, 41, 82, 31, 94, 52, 84, 67, 48, 169, + 169, 188, 94, 48, 40, 48, 58, 191, 101, 115, 75, 246, 97, 75, + 150, 166, 175, 153, 188, 201, 246, 158, 57, 53, 85, 30, 81, 154, + 110, 169, 202, 159, 86, 243, 197, 219, 137, 122, 37, 192, 2, 222, + 238, 80, 9, 133, 141, 62, 253, 150, 207, 109, 75, 23, 6, 75, + 193, 46, 44, 134, 193, 254, 180, 232, 27, 238, 38, 115, 41, 198, + 245, 45, 95, 196, 192, 240, 42, 51, 144, 103, 67, 87, 97, 161, + 100, 140, 13, 187, 204, 191, 234, 194, 80, 62, 220, 177, 184, 155, + 77, 32, 176, 214, 27, 194, 223, 127, 75, 246, 54, 239, 171, 198, + 76, 48, 2, 130, 192, 181, 241, 249, 38, 219, 86, 43, 165, 84, + 83, 145, 247, 196, 52, 230, 220, 65, 183, 252, 20, 119, 174, 247, + 239, 191, 198, 136, 244, 205, 163, 141, 68, 99, 185, 251, 14, 25, + 89, 193, 119, 154, 182, 34, 181, 64, 227, 209, 7, 102, 80, 60, + 205, 24, 224, 120, 239, 67, 163, 23, 27, 181, 212, 49, 104, 92, + 62, 122, 172, 48, 202, 107, 237, 104, 177, 189, 85, 67, 86, 219, + 140, 57, 134, 226, 39, 37, 246, 12, 51, 48, 195, 236, 150, 173, + 81, 135, 121, 134, 160, 120, 52, 82, 79, 193, 85, 21, 115, 31, + 27, 62, 186, 45, 74, 136, 188, 71, 117, 116, 252, 201, 104, 240, + 141, 207, 72, 251, 241, 159, 214, 153, 114, 3, 235, 155, 187, 166, + 188, 226, 231, 255, 99, 37, 9, 76, 215, 234, 211, 58, 199, 2, + 176, 77, 235, 96, 174, 237, 160, 183, 6, 91, 215, 238, 118, 235, + 158, 242, 8, 177, 226, 140, 150, 111, 59, 196, 56, 211, 223, 181, + 184, 250, 251, 27, 18, 240, 87, 138, 114, 184, 38, 114, 165, 250, + 23, 239, 77, 122, 86, 75, 14, 204, 85, 197, 1, 169, 125, 109, + 125, 85, 186, 253, 214, 167, 226, 169, 207, 27, 147, 239, 18, 66, + 202, 121, 51, 93, 188, 209, 87, 64, 212, 165, 148, 232, 194, 212, + 18, 178, 147, 98, 189, 161, 161, 31, 232, 59, 205, 49, 220, 90, + 50, 209, 219, 115, 229, 219, 236, 163, 24, 43, 215, 104, 66, 19, + 4, 185, 52, 8, 160, 62, 175, 178, 148, 124, 141, 255, 26, 58, + 28, 15, 255, 28, 79, 166, 212, 22, 43, 57, 144, 70, 24, 212, + 206, 174, 96, 241, 26, 180, 183, 84, 46, 106, 183, 130, 42, 133, + 41, 216, 78, 110, 0, 131, 157, 181, 7, 109, 218, 85, 210, 220, + 194, 98, 73, 149, 25, 167, 156, 164, 237, 251, 255, 131, 242, 81, + 146, 149, 10, 52, 51, 208, 155, 198, 202, 214, 156, 61, 119, 147, + 73, 63, 107, 13, 105, 134, 140, 25, 118, 218, 107, 53, 120, 177, + 76, 45, 83, 90, 30, 37, 253, 87, 91, 36, 133, 221, 26, 134, + 114, 155, 162, 189, 254, 138, 17, 104, 150, 62, 0, 21, 223, 253, + 73, 123, 241, 255, 97, 136, 8, 14, 219, 73, 162, 218, 172, 207, + 120, 18, 175, 45, 15, 101, 94, 17, 157, 93, 210, 167, 156, 235, + 38, 15, 97, 235, 218, 211, 205, 149, 206, 11, 34, 130, 20, 239, + 147, 214, 152, 223, 6, 136, 159, 253, 162, 37, 112, 207, 247, 161, + 38, 166, 225, 103, 10, 187, 186, 104, 118, 182, 100, 234, 211, 185, + 49, 68, 220, 62, 147, 50, 108, 156, 25, 242, 42, 139, 124, 206, + 197, 33, 23, 164, 54, 161, 231, 176, 49, 46, 253, 245, 79, 68, + 73, 77, 148, 221, 56, 136, 57, 136, 5, 254, 118, 172, 122, 255, + 125, 91, 202, 129, 79, 160, 153, 80, 205, 120, 89, 129, 159, 187, + 91, 109, 42, 80, 181, 120, 104, 201, 95, 134, 83, 84, 163, 67, + 82, 23, 204, 118, 49, 78, 16, 17, 158, 135, 251, 36, 7, 251, + 149, 230, 195, 213, 47, 100, 179, 246, 42, 66, 106, 139, 89, 69, + 77, 133, 124, 236, 35, 59, 54, 243, 194, 154, 140, 255, 63, 208, + 28, 19, 38, 70, 173, 238, 183, 207, 15, 107, 67, 146, 242, 33, + 251, 253, 25, 77, 133, 175, 2, 65, 233, 239, 102, 33, 3, 18, + 93, 57, 2, 44, 30, 59, 157, 214, 87, 89, 220, 159, 218, 132, + 247, 195, 96, 82, 20, 31, 218, 156, 210, 190, 108, 39, 59, 215, + 206, 211, 108, 200, 172, 231, 125, 111, 153, 216, 14, 20, 133, 29, + 189, 105, 120, 218, 117, 141, 206, 70, 248, 150, 52, 68, 229, 112, + 176, 76, 116, 71, 4, 78, 235, 63, 238, 9, 6, 157, 60, 41, + 6, 137, 41, 18, 166, 203, 146, 59, 110, 71, 166, 35, 238, 154, + 218, 0, 148, 34, 115, 162, 173, 0, 61, 207, 3, 203, 220, 53, + 1, 122, 126, 21, 245, 99, 133, 182, 173, 154, 16, 16, 119, 60, + 64, 4, 13, 92, 53, 109, 189, 80, 120, 38, 161, 54, 214, 236, + 153, 173, 112, 221, 54, 169, 164, 193, 244, 65, 197, 143, 189, 171, + 145, 230, 171, 184, 101, 141, 120, 209, 27, 89, 104, 181, 168, 199, + 23, 35, 185, 74, 59, 197, 119, 94, 199, 135, 66, 181, 128, 106, + 78, 199, 31, 45, 169, 6, 85, 141, 71, 174, 46, 67, 195, 239, + 184, 194, 67, 50, 167, 33, 199, 160, 131, 243, 247, 0, 170, 170, + 49, 105, 183, 123, 95, 72, 197, 90, 157, 147, 37, 93, 60, 113, + 89, 210, 158, 105, 210, 103, 82, 245, 113, 13, 241, 140, 216, 34, + 53, 142, 91, 197, 12, 13, 130, 116, 114, 137, 173, 125, 69, 30, + 18, 161, 37, 246, 182, 152, 129, 27, 226, 31, 84, 118, 227, 147, + 67, 95, 96, 82, 59, 192, 46, 149, 75, 39, 255, 167, 96, 190, + 212, 61, 65, 211, 252, 126, 66, 130, 225, 183, 243, 9, 204, 11, + 192, 111, 252, 97, 189, 102, 20, 9, 191, 96, 190, 237, 114, 233, + 136, 102, 58, 67, 150, 243, 113, 3, 223, 185, 113, 84, 195, 49, + 216, 123, 178, 68, 96, 31, 84, 6, 42, 33, 168, 222, 245, 81, + 8, 14, 3, 161, 155, 233, 80, 187, 124, 35, 187, 99, 250, 92, + 18, 120, 129, 210, 128, 234, 150, 203, 251, 76, 233, 31, 178, 52, + 62, 120, 229, 50, 240, 68, 41, 87, 125, 18, 133, 107, 14, 11, + 29, 228, 73, 10, 255, 242, 125, 124, 40, 228, 222, 190, 118, 85, + 202, 99, 184, 41, 13, 161, 73, 127, 193, 100, 130, 75, 1, 90, + 174, 106, 11, 178, 132, 34, 200, 15, 221, 99, 41, 80, 93, 211, + 126, 251, 161, 108, 159, 234, 106, 125, 222, 130, 110, 118, 95, 230, + 183, 245, 92, 89, 246, 149, 106, 75, 164, 87, 21, 128, 149, 85, + 13, 6, 77, 147, 197, 200, 226, 134, 150, 185, 89, 127, 208, 53, + 9, 183, 238, 9, 110, 87, 167, 62, 143, 242, 122, 213, 218, 84, + 161, 123, 85, 53, 41, 135, 55, 111, 110, 60, 181, 70, 101, 237, + 10, 243, 179, 253, 114, 30, 48, 111, 247, 172, 233, 152, 122, 21, + 143, 133, 77, 6, 18, 193, 252, 214, 25, 199, 225, 85, 82, 241, + 31, 33, 83, 161, 119, 156, 150, 46, 111, 22, 113, 167, 1, 126, + 232, 190, 202, 93, 90, 130, 19, 77, 0, 123, 168, 197, 160, 194, + 236, 17, 46, 162, 31, 70, 118, 204, 100, 98, 195, 203, 75, 237, + 194, 137, 70, 32, 74, 162, 228, 163, 146, 175, 38, 231, 157, 240, + 100, 31, 4, 7, 16, 171, 225, 85, 131, 7, 66, 249, 157, 24, + 248, 212, 12, 67, 192, 118, 81, 159, 87, 203, 3, 185, 58, 17, + 101, 75, 170, 139, 239, 148, 183, 10, 134, 176, 15, 44, 161, 0, + 212, 109, 58, 56, 249, 239, 182, 253, 236, 177, 84, 146, 59, 16, + 214, 73, 47, 121, 23, 188, 247, 11, 16, 64, 21, 138, 55, 229, + 12, 143, 21, 96, 201, 8, 127, 226, 5, 176, 127, 156, 3, 131, + 194, 60, 196, 128, 195, 162, 206, 30, 195, 78, 8, 179, 172, 111, + 160, 65, 55, 90, 95, 194, 100, 190, 220, 152, 120, 60, 71, 42, + 246, 94, 98, 139, 167, 216, 69, 194, 30, 246, 80, 198, 129, 55, + 239, 221, 111, 76, 40, 94, 244, 175, 21, 195, 68, 78, 39, 94, + 233, 1, 101, 71, 48, 0, 84, 112, 152, 32, 145, 136, 7, 29, + 106, 30, 70, 127, 25, 132, 198, 127, 81, 193, 109, 58, 0, 255, + 254, 189, 1, 228, 66, 169, 91, 84, 216, 150, 193, 173, 145, 216, + 213, 131, 73, 221, 140, 252, 43, 152, 75, 211, 236, 22, 58, 133, + 101, 218, 211, 164, 207, 3, 1, 3, 209, 118, 59, 248, 244, 32, + 81, 70, 53, 62, 14, 80, 182, 69, 23, 203, 172, 219, 131, 251, + 30, 211, 154, 71, 137, 150, 108, 101, 43, 189, 60, 160, 223, 29, + 65, 191, 2, 230, 191, 234, 167, 116, 221, 93, 115, 229, 246, 87, + 194, 73, 248, 222, 204, 145, 232, 118, 3, 47, 51, 80, 65, 87, + 241, 29, 98, 54, 190, 204, 243, 120, 92, 127, 93, 28, 153, 75, + 74, 174, 152, 175, 74, 66, 92, 212, 252, 24, 229, 88, 180, 120, + 80, 28, 129, 225, 219, 224, 227, 183, 245, 11, 87, 231, 10, 88, + 194, 163, 88, 160, 43, 222, 122, 111, 80, 173, 146, 224, 109, 81, + 198, 208, 171, 224, 96, 248, 147, 144, 199, 51, 95, 216, 245, 177, + 164, 100, 69, 83, 131, 200, 62, 83, 223, 185, 199, 207, 95, 93, + 167, 44, 214, 170, 15, 12, 37, 172, 43, 83, 241, 81, 240, 167, + 58, 250, 197, 110, 217, 153, 147, 131, 239, 238, 148, 149, 253, 217, + 13, 167, 100, 204, 46, 73, 129, 66, 73, 195, 176, 26, 41, 54, + 209, 126, 158, 5, 15, 16, 84, 204, 50, 177, 246, 42, 227, 52, + 64, 156, 47, 188, 31, 164, 232, 82, 73, 193, 164, 119, 155, 228, + 122, 83, 31, 16, 109, 54, 6, 194, 49, 189, 216, 41, 146, 125, + 137, 162, 253, 76, 104, 213, 245, 251, 112, 79, 134, 119, 162, 139, + 183, 83, 253, 31, 77, 49, 247, 252, 135, 197, 110, 244, 35, 53, + 124, 222, 134, 238, 111, 35, 174, 48, 237, 203, 13, 85, 78, 127, + 144, 209, 14, 224, 38, 248, 190, 63, 163, 35, 187, 223, 249, 12, + 37, 144, 253, 117, 184, 37, 216, 132, 139, 45, 172, 153, 16, 35, + 60, 174, 44, 166, 34, 224, 226, 29, 185, 52, 192, 80, 197, 169, + 39, 162, 211, 249, 20, 98, 148, 183, 244, 218, 106, 129, 37, 221, + 183, 231, 117, 239, 56, 66, 157, 205, 195, 172, 237, 40, 113, 34, + 89, 90, 240, 45, 225, 170, 214, 100, 243, 247, 51, 45, 236, 57, + 208, 228, 141, 174, 147, 134, 163, 36, 43, 205, 109, 29, 161, 228, + 56, 199, 216, 170, 190, 182, 146, 11, 77, 5, 38, 63, 231, 136, + 118, 179, 182, 194, 83, 15, 199, 74, 59, 76, 40, 250, 122, 239, + 4, 97, 92, 150, 153, 150, 137, 79, 195, 232, 10, 162, 119, 98, + 16, 161, 7, 178, 158, 229, 93, 81, 217, 246, 109, 120, 216, 206, + 214, 104, 130, 155, 202, 48, 35, 153, 5, 45, 53, 38, 120, 71, + 93, 211, 138, 33, 190, 43, 153, 115, 89, 41, 213, 218, 219, 90, + 145, 60, 7, 78, 154, 72, 68, 9, 95, 198, 198, 217, 48, 191, + 118, 135, 167, 96, 184, 135, 243, 103, 112, 82, 87, 192, 166, 178, + 187, 246, 15, 204, 82, 36, 66, 169, 112, 84, 204, 36, 222, 103, + 244, 38, 175, 57, 64, 224, 101, 167, 94, 39, 60, 112, 131, 32, + 130, 36, 233, 222, 254, 213, 159, 29, 235, 224, 41, 43, 243, 238, + 36, 144, 168, 169, 158, 79, 31, 73, 204, 227, 154, 17, 199, 209, + 56, 8, 125, 98, 176, 66, 222, 33, 10, 222, 250, 194, 198, 203, + 216, 21, 237, 23, 5, 89, 203, 8, 150, 160, 72, 29, 37, 234, + 88, 187, 229, 98, 254, 94, 88, 204, 153, 203, 226, 90, 12, 135, + 126, 52, 77, 159, 179, 183, 72, 255, 206, 159, 106, 243, 145, 105, + 230, 126, 253, 155, 57, 166, 166, 69, 246, 151, 142, 205, 199, 155, + 117, 134, 105, 158, 223, 222, 180, 92, 252, 109, 113, 3, 109, 166, + 162, 16, 191, 222, 123, 211, 62, 209, 138, 8, 111, 33, 104, 182, + 239, 163, 197, 3, 134, 8, 76, 95, 231, 45, 81, 62, 124, 207, + 63, 21, 30, 91, 234, 58, 14, 241, 43, 119, 128, 144, 182, 200, + 187, 132, 48, 63, 193, 162, 171, 133, 168, 153, 170, 219, 76, 51, + 223, 160, 211, 156, 20, 168, 201, 132, 247, 170, 5, 153, 199, 218, + 123, 37, 242, 165, 171, 243, 130, 79, 189, 59, 7, 158, 190, 161, + 141, 148, 124, 122, 224, 246, 0, 116, 229, 118, 253, 213, 187, 208, + 218, 94, 18, 121, 183, 33, 88, 150, 63, 16, 167, 30, 252, 127, + 37, 244, 40, 71, 186, 54, 24, 167, 12, 56, 152, 27, 103, 228, + 9, 134, 206, 124, 214, 120, 190, 203, 249, 16, 167, 90, 96, 95, + 66, 206, 92, 68, 42, 71, 86, 94, 67, 164, 104, 149, 117, 146, + 159, 16, 8, 215, 113, 247, 32, 123, 223, 40, 186, 246, 218, 36, + 200, 86, 221, 87, 71, 84, 121, 60, 96, 136, 110, 208, 107, 55, + 134, 27, 187, 3, 112, 24, 253, 47, 45, 66, 233, 115, 93, 29, + 248, 103, 249, 142, 38, 133, 56, 240, 59, 189, 64, 122, 13, 150, + 60, 172, 19, 229, 188, 254, 130, 211, 41, 211, 174, 69, 143, 214, + 78, 124, 46, 230, 196, 82, 213, 117, 174, 129, 28, 181, 11, 145, + 189, 241, 128, 105, 190, 55, 197, 1, 144, 139, 111, 5, 6, 144, + 83, 252, 175, 76, 167, 132, 250, 228, 157, 124, 113, 230, 137, 110, + 151, 150, 211, 49, 3, 242, 31, 47, 193, 20, 15, 48, 63, 193, + 247, 225, 64, 37, 178, 204, 195, 110, 63, 46, 98, 94, 57, 96, + 52, 134, 34, 157, 65, 105, 90, 203, 244, 137, 139, 182, 19, 221, + 129, 212, 147, 93, 108, 211, 34, 196, 251, 95, 111, 128, 75, 232, + 193, 223, 110, 52, 217, 198, 0, 185, 65, 106, 131, 183, 219, 227, + 99, 230, 93, 74, 200, 94, 131, 217, 79, 20, 110, 171, 68, 38, + 150, 92, 170, 172, 46, 55, 22, 158, 145, 34, 251, 114, 121, 250, + 88, 202, 69, 247, 15, 223, 189, 16, 107, 87, 99, 29, 252, 80, + 1, 211, 20, 15, 69, 17, 130, 206, 104, 5, 161, 152, 34, 152, + 102, 223, 191, 170, 237, 83, 138, 47, 137, 87, 69, 3, 120, 187, + 245, 106, 140, 185, 149, 176, 63, 200, 54, 146, 202, 193, 77, 60, + 44, 204, 225, 254, 20, 159, 218, 115, 180, 95, 119, 131, 78, 109, + 16, 125, 255, 109, 18, 138, 215, 164, 153, 238, 95, 6, 221, 214, + 236, 221, 33, 129, 38, 149, 119, 9, 182, 184, 250, 182, 84, 231, + 4, 174, 169, 38, 190, 236, 124, 48, 120, 251, 204, 20, 199, 155, + 204, 105, 39, 176, 234, 191, 114, 153, 80, 13, 56, 254, 142, 214, + 72, 118, 21, 180, 196, 190, 152, 252, 139, 8, 142, 141, 178, 213, + 218, 92, 38, 143, 236, 107, 182, 105, 197, 11, 153, 98, 114, 90, + 185, 244, 200, 32, 185, 232, 110, 27, 175, 194, 34, 103, 116, 96, + 126, 51, 59, 131, 182, 138, 53, 33, 144, 142, 206, 130, 177, 13, + 22, 165, 197, 155, 198, 175, 196, 229, 125, 176, 98, 86, 56, 68, + 67, 245, 108, 77, 37, 98, 0, 45, 70, 230, 71, 194, 3, 202, + 143, 208, 218, 250, 208, 180, 165, 136, 110, 2, 109, 205, 54, 239, + 100, 66, 54, 22, 200, 151, 160, 23, 112, 113, 108, 180, 55, 48, + 237, 183, 34, 145, 104, 35, 173, 100, 156, 240, 228, 206, 228, 251, + 128, 48, 202, 160, 184, 247, 239, 62, 226, 221, 16, 79, 193, 198, + 204, 115, 86, 73, 124, 212, 190, 144, 211, 71, 211, 149, 58, 241, + 131, 124, 113, 75, 174, 255, 207, 190, 122, 140, 163, 147, 241, 100, + 26, 192, 71, 17, 126, 18, 201, 9, 245, 72, 37, 3, 201, 172, + 231, 68, 194, 30, 133, 141, 2, 136, 115, 245, 196, 103, 7, 196, + 131, 106, 212, 208, 126, 94, 135, 28, 103, 107, 227, 146, 157, 62, + 113, 8, 180, 103, 209, 140, 181, 79, 138, 101, 191, 68, 87, 33, + 241, 128, 205, 9, 98, 49, 68, 87, 7, 220, 60, 101, 141, 53, + 166, 2, 247, 45, 234, 186, 41, 62, 236, 51, 105, 200, 175, 186, + 229, 56, 164, 30, 43, 60, 88, 250, 127, 75, 20, 204, 94, 150, + 207, 54, 18, 188, 146, 100, 179, 166, 212, 52, 131, 209, 3, 66, + 230, 100, 219, 12, 92, 37, 247, 254, 116, 193, 48, 53, 189, 242, + 59, 31, 247, 74, 224, 158, 116, 235, 24, 65, 253, 148, 175, 64, + 193, 213, 88, 240, 26, 87, 168, 242, 97, 93, 161, 214, 244, 69, + 76, 96, 249, 120, 24, 179, 128, 47, 106, 201, 109, 213, 108, 15, + 150, 86, 227, 161, 160, 37, 213, 80, 8, 185, 44, 158, 165, 194, + 95, 119, 231, 1, 126, 29, 33, 97, 33, 158, 186, 147, 112, 225, + 86, 126, 95, 60, 251, 67, 207, 235, 90, 117, 110, 116, 97, 248, + 72, 220, 181, 220, 87, 153, 67, 104, 237, 53, 218, 180, 6, 238, + 108, 86, 7, 67, 161, 46, 107, 22, 213, 223, 198, 163, 86, 58, + 98, 214, 15, 123, 92, 5, 42, 234, 1, 248, 207, 161, 136, 228, + 58, 25, 166, 44, 184, 63, 188, 0, 178, 182, 125, 100, 171, 189, + 66, 43, 227, 164, 241, 7, 118, 208, 63, 92, 21, 115, 247, 235, + 251, 242, 145, 169, 220, 235, 96, 35, 244, 219, 87, 125, 162, 126, + 71, 84, 241, 197, 93, 109, 150, 105, 205, 214, 78, 72, 232, 19, + 19, 186, 70, 218, 119, 67, 54, 73, 237, 174, 5, 176, 41, 67, + 92, 146, 6, 244, 13, 8, 102, 180, 228, 160, 100, 251, 32, 133, + 54, 16, 194, 118, 73, 133, 194, 158, 190, 3, 196, 39, 144, 151, + 145, 157, 2, 135, 16, 140, 15, 26, 56, 153, 122, 10, 163, 179, + 121, 195, 27, 1, 32, 205, 231, 252, 142, 30, 253, 187, 27, 219, + 37, 228, 240, 102, 13, 108, 248, 33, 80, 95, 36, 240, 88, 50, + 140, 45, 42, 237, 216, 150, 196, 106, 140, 162, 139, 68, 172, 10, + 236, 44, 215, 29, 21, 227, 66, 7, 191, 106, 151, 233, 206, 239, + 214, 122, 189, 224, 21, 207, 102, 158, 10, 222, 49, 190, 250, 146, + 169, 178, 31, 55, 139, 159, 149, 54, 144, 32, 52, 84, 56, 17, + 144, 66, 153, 171, 216, 234, 120, 31, 123, 7, 2, 216, 151, 219, + 46, 180, 123, 89, 117, 92, 198, 64, 55, 144, 176, 62, 150, 112, + 145, 184, 212, 200, 84, 133, 141, 26, 198, 84, 103, 231, 49, 26, + 15, 55, 139, 248, 155, 251, 152, 245, 53, 207, 238, 212, 251, 249, + 25, 0, 4, 5, 123, 249, 220, 48, 43, 88, 160, 44, 69, 83, + 10, 215, 106, 25, 52, 22, 248, 58, 13, 172, 67, 29, 183, 182, + 40, 18, 70, 82, 116, 115, 109, 197, 147, 230, 17, 130, 205, 121, + 52, 28, 237, 157, 236, 168, 104, 36, 125, 245, 227, 11, 56, 68, + 184, 222, 112, 159, 100, 201, 165, 7, 57, 253, 162, 191, 92, 232, + 108, 250, 120, 43, 71, 185, 126, 28, 26, 201, 38, 69, 27, 40, + 140, 96, 91, 71, 238, 103, 74, 92, 252, 71, 176, 155, 76, 214, + 52, 198, 151, 159, 247, 164, 125, 220, 189, 16, 253, 232, 242, 117, + 126, 212, 36, 138, 40, 100, 124, 64, 1, 67, 35, 26, 154, 72, + 110, 171, 179, 202, 30, 69, 241, 254, 53, 123, 19, 208, 189, 107, + 169, 32, 201, 108, 155, 0, 105, 179, 147, 173, 40, 177, 204, 240, + 21, 176, 129, 234, 177, 72, 182, 115, 130, 177, 35, 231, 133, 127, + 83, 252, 212, 224, 234, 212, 240, 147, 99, 80, 54, 39, 118, 177, + 173, 179, 6, 74, 242, 192, 194, 133, 230, 214, 141, 51, 186, 205, + 15, 45, 22, 73, 82, 179, 20, 238, 237, 38, 71, 124, 3, 75, + 152, 182, 136, 214, 89, 228, 96, 4, 29, 100, 242, 52, 52, 229, + 19, 205, 39, 218, 60, 185, 9, 6, 184, 122, 98, 72, 167, 135, + 236, 108, 221, 162, 212, 129, 11, 100, 55, 158, 31, 63, 79, 5, + 252, 238, 126, 241, 109, 248, 237, 225, 131, 200, 64, 218, 89, 208, + 118, 93, 192, 23, 39, 82, 135, 16, 201, 87, 217, 24, 32, 64, + 167, 42, 13, 159, 100, 45, 153, 251, 8, 33, 246, 111, 178, 43, + 96, 19, 109, 228, 98, 86, 104, 50, 127, 46, 220, 99, 133, 217, + 111, 131, 24, 122, 190, 3, 55, 74, 52, 122, 58, 245, 61, 131, + 122, 216, 123, 128, 159, 169, 2, 61, 110, 1, 201, 145, 149, 150, + 76, 213, 236, 7, 252, 64, 127, 48, 39, 129, 134, 30, 214, 94, + 32, 134, 66, 110, 52, 239, 44, 228, 250, 41, 112, 227, 41, 227, + 131, 217, 204, 186, 204, 22, 42, 205, 174, 107, 1, 37, 247, 16, + 228, 58, 112, 222, 66, 212, 198, 58, 181, 125, 151, 193, 181, 183, + 83, 51, 237, 164, 68, 234, 13, 238, 248, 77, 224, 224, 157, 222, + 246, 32, 231, 37, 160, 201, 48, 60, 79, 103, 200, 223, 196, 167, + 99, 75, 248, 0, 65, 96, 46, 172, 91, 4, 132, 144, 255, 221, + 85, 100, 148, 251, 140, 184, 114, 168, 26, 164, 98, 164, 71, 248, + 15, 155, 73, 142, 2, 198, 149, 98, 119, 106, 86, 45, 109, 35, + 112, 32, 52, 29, 12, 137, 195, 78, 239, 141, 64, 99, 25, 215, + 32, 142, 84, 176, 89, 107, 224, 215, 199, 54, 135, 117, 65, 234, + 114, 240, 165, 111, 68, 24, 185, 90, 183, 193, 65, 37, 5, 21, + 93, 14, 7, 26, 107, 81, 216, 161, 239, 146, 63, 55, 106, 217, + 64, 158, 151, 119, 105, 76, 244, 224, 83, 133, 217, 196, 107, 92, + 70, 17, 254, 151, 167, 6, 193, 205, 13, 238, 221, 24, 55, 59, + 21, 60, 124, 30, 144, 112, 105, 181, 104, 174, 80, 37, 23, 181, + 7, 202, 113, 23, 42, 225, 165, 71, 165, 194, 246, 149, 15, 3, + 124, 137, 64, 108, 122, 125, 195, 51, 152, 151, 71, 65, 147, 12, + 43, 33, 140, 135, 183, 129, 27, 96, 190, 67, 220, 182, 167, 13, + 160, 220, 183, 167, 205, 171, 56, 103, 233, 121, 115, 213, 228, 212, + 66, 227, 242, 81, 222, 219, 57, 59, 85, 45, 94, 233, 241, 178, + 28, 80, 23, 84, 190, 235, 4, 100, 113, 138, 162, 87, 207, 38, + 248, 247, 45, 62, 136, 16, 244, 77, 46, 102, 217, 227, 1, 82, + 221, 98, 204, 36, 43, 71, 175, 236, 163, 28, 28, 28, 81, 245, + 252, 78, 179, 19, 113, 44, 170, 251, 143, 160, 34, 159, 251, 5, + 207, 231, 250, 5, 179, 148, 164, 34, 223, 149, 213, 196, 198, 162, + 186, 237, 156, 110, 88, 206, 54, 202, 255, 128, 127, 24, 162, 81, + 231, 236, 128, 255, 145, 223, 85, 236, 135, 168, 188, 21, 96, 77, + 187, 78, 212, 100, 214, 13, 179, 235, 223, 38, 70, 203, 251, 46, + 212, 122, 90, 218, 98, 112, 109, 78, 202, 73, 138, 136, 218, 15, + 210, 70, 6, 175, 152, 251, 65, 18, 186, 241, 203, 78, 111, 154, + 0, 245, 215, 94, 47, 52, 227, 207, 178, 191, 71, 104, 70, 91, + 97, 59, 62, 118, 6, 158, 255, 69, 190, 224, 117, 195, 159, 239, + 139, 71, 224, 5, 218, 122, 246, 67, 49, 26, 89, 141, 162, 176, + 247, 244, 241, 192, 3, 174, 22, 198, 178, 26, 248, 150, 214, 249, + 156, 188, 249, 227, 222, 211, 50, 233, 145, 38, 187, 15, 8, 72, + 182, 28, 138, 122, 151, 219, 200, 186, 19, 231, 91, 179, 157, 157, + 190, 99, 250, 13, 162, 21, 244, 69, 128, 207, 7, 107, 1, 190, + 63, 137, 242, 146, 18, 234, 34, 140, 142, 79, 142, 209, 238, 117, + 34, 235, 91, 62, 70, 170, 203, 86, 184, 2, 181, 21, 149, 115, + 175, 170, 148, 225, 13, 212, 25, 10, 150, 2, 172, 95, 47, 76, + 221, 229, 203, 170, 195, 5, 44, 179, 240, 234, 244, 210, 141, 97, + 195, 111, 165, 239, 78, 210, 213, 255, 97, 144, 200, 137, 238, 92, + 196, 34, 56, 142, 50, 51, 254, 127, 34, 239, 47, 108, 106, 112, + 21, 60, 146, 93, 199, 45, 223, 227, 36, 102, 238, 242, 50, 211, + 89, 97, 120, 246, 157, 151, 40, 222, 28, 254, 95, 55, 143, 16, + 164, 250, 6, 21, 20, 61, 79, 92, 2, 161, 91, 191, 10, 231, + 39, 87, 186, 125, 186, 103, 239, 158, 133, 186, 223, 3, 231, 199, + 224, 153, 62, 82, 111, 86, 128, 246, 165, 182, 182, 117, 75, 26, + 224, 144, 252, 193, 41, 244, 230, 40, 113, 13, 193, 148, 122, 0, + 224, 199, 201, 240, 184, 216, 175, 172, 65, 244, 120, 4, 215, 154, + 115, 68, 86, 124, 86, 172, 92, 213, 212, 149, 5, 64, 193, 144, + 28, 169, 183, 59, 84, 172, 76, 9, 55, 44, 40, 177, 53, 85, + 14, 220, 119, 75, 98, 66, 41, 44, 93, 183, 122, 112, 163, 136, + 91, 144, 248, 99, 126, 111, 177, 129, 221, 103, 14, 221, 250, 148, + 35, 31, 140, 13, 89, 110, 16, 155, 97, 156, 4, 203, 15, 65, + 172, 105, 163, 54, 23, 85, 165, 1, 192, 206, 187, 31, 133, 105, + 146, 44, 189, 25, 174, 21, 211, 255, 0, 251, 58, 200, 144, 105, + 69, 30, 178, 165, 42, 221, 246, 234, 153, 71, 85, 84, 238, 36, + 71, 76, 184, 119, 10, 78, 81, 23, 246, 243, 37, 113, 99, 131, + 73, 187, 108, 100, 245, 79, 218, 241, 19, 243, 117, 174, 200, 145, + 240, 150, 193, 140, 137, 116, 238, 114, 255, 220, 246, 183, 128, 57, + 13, 67, 189, 115, 190, 11, 190, 78, 55, 185, 251, 155, 36, 254, + 206, 117, 54, 186, 215, 30, 30, 218, 182, 54, 68, 59, 19, 42, + 231, 8, 2, 196, 63, 93, 243, 156, 5, 37, 142, 176, 119, 184, + 163, 45, 203, 98, 125, 168, 208, 102, 126, 186, 97, 41, 27, 160, + 25, 36, 112, 84, 163, 254, 38, 92, 75, 147, 64, 96, 140, 195, + 211, 197, 185, 82, 134, 239, 49, 87, 237, 116, 229, 168, 131, 216, + 80, 244, 247, 155, 103, 238, 184, 100, 177, 239, 188, 175, 41, 7, + 114, 204, 219, 172, 126, 10, 205, 33, 20, 96, 194, 231, 52, 197, + 159, 244, 194, 77, 202, 137, 139, 170, 76, 32, 205, 188, 130, 164, + 84, 131, 134, 78, 190, 194, 198, 75, 118, 236, 127, 70, 26, 69, + 160, 66, 120, 200, 15, 25, 232, 118, 177, 35, 8, 161, 180, 82, + 112, 183, 107, 18, 92, 200, 167, 22, 75, 195, 182, 39, 19, 61, + 118, 109, 33, 105, 11, 13, 28, 122, 145, 253, 224, 218, 174, 88, + 240, 120, 3, 116, 23, 97, 183, 10, 85, 8, 103, 3, 79, 228, + 119, 124, 195, 110, 226, 19, 147, 66, 16, 1, 217, 123, 200, 177, + 79, 20, 198, 18, 9, 221, 19, 187, 72, 229, 212, 215, 117, 27, + 200, 140, 103, 177, 38, 53, 209, 127, 105, 86, 6, 93, 12, 151, + 199, 190, 153, 16, 45, 179, 203, 224, 119, 220, 179, 223, 208, 224, + 29, 211, 234, 123, 209, 184, 48, 143, 11, 110, 68, 146, 18, 24, + 14, 78, 28, 118, 35, 234, 235, 245, 88, 93, 125, 33, 116, 188, + 59, 217, 119, 36, 88, 210, 193, 248, 146, 221, 230, 87, 201, 125, + 174, 130, 240, 202, 192, 22, 146, 217, 199, 33, 146, 222, 213, 155, + 173, 231, 242, 253, 160, 32, 158, 183, 44, 76, 130, 54, 0, 224, + 231, 159, 236, 143, 124, 152, 185, 232, 149, 232, 171, 104, 92, 31, + 222, 32, 131, 245, 3, 186, 96, 244, 38, 203, 157, 193, 161, 26, + 14, 69, 84, 94, 39, 14, 222, 0, 69, 197, 239, 247, 125, 196, + 0, 84, 244, 185, 97, 249, 91, 5, 233, 73, 121, 198, 167, 98, + 104, 192, 50, 34, 83, 71, 145, 218, 163, 227, 60, 87, 165, 23, + 129, 122, 254, 137, 39, 248, 147, 196, 41, 42, 82, 125, 41, 181, + 43, 38, 124, 221, 50, 16, 170, 54, 72, 170, 178, 29, 43, 8, + 204, 39, 20, 152, 76, 37, 143, 245, 68, 134, 169, 173, 216, 12, + 86, 47, 137, 148, 79, 172, 113, 98, 162, 127, 18, 64, 7, 236, + 250, 121, 217, 237, 129, 76, 165, 201, 52, 231, 145, 22, 144, 41, + 21, 51, 196, 82, 25, 150, 119, 135, 37, 60, 220, 26, 169, 180, + 1, 125, 150, 17, 251, 211, 130, 84, 154, 134, 174, 126, 91, 77, + 10, 154, 139, 226, 207, 211, 140, 161, 135, 158, 102, 96, 36, 105, + 194, 9, 241, 213, 130, 15, 24, 87, 159, 169, 230, 227, 59, 4, + 92, 121, 6, 49, 176, 231, 57, 205, 111, 53, 5, 119, 210, 46, + 171, 176, 31, 82, 10, 32, 150, 173, 69, 160, 35, 94, 144, 241, + 121, 12, 153, 103, 73, 74, 90, 242, 247, 241, 159, 25, 202, 174, + 11, 40, 200, 178, 195, 27, 152, 43, 67, 191, 162, 36, 201, 123, + 30, 141, 111, 246, 84, 241, 186, 187, 213, 161, 83, 153, 134, 62, + 206, 94, 17, 24, 5, 68, 7, 8, 19, 115, 146, 62, 141, 94, + 10, 184, 111, 251, 76, 127, 59, 47, 195, 47, 211, 27, 119, 34, + 61, 53, 192, 127, 48, 33, 155, 46, 73, 111, 67, 38, 64, 64, + 27, 33, 36, 250, 169, 150, 248, 183, 202, 203, 91, 206, 110, 106, + 1, 35, 175, 196, 124, 38, 234, 185, 38, 160, 82, 143, 9, 130, + 183, 236, 58, 175, 167, 48, 132, 231, 206, 88, 85, 85, 201, 74, + 237, 228, 34, 0, 78, 227, 90, 171, 200, 122, 134, 64, 181, 23, + 14, 216, 42, 188, 11, 99, 220, 67, 136, 13, 107, 252, 218, 179, + 196, 51, 205, 48, 147, 224, 114, 172, 184, 245, 23, 132, 158, 173, + 210, 84, 200, 248, 89, 191, 173, 24, 172, 240, 79, 93, 63, 155, + 200, 244, 183, 238, 9, 110, 87, 167, 62, 143, 242, 122, 213, 218, + 84, 161, 123, 85, 53, 41, 143, 186, 252, 219, 204, 27, 238, 137, + 141, 157, 23, 38, 132, 129, 81, 27, 113, 118, 118, 48, 199, 252, + 205, 179, 233, 223, 183, 99, 64, 67, 246, 222, 136, 111, 16, 192, + 164, 5, 92, 30, 26, 58, 218, 201, 110, 11, 239, 187, 211, 151, + 21, 243, 130, 80, 97, 93, 118, 173, 88, 79, 173, 11, 167, 126, + 193, 251, 152, 249, 25, 243, 56, 242, 133, 97, 223, 119, 34, 232, + 138, 142, 128, 118, 186, 166, 61, 98, 87, 156, 68, 95, 102, 214, + 176, 105, 195, 159, 54, 187, 164, 102, 189, 148, 81, 211, 11, 96, + 176, 74, 134, 12, 142, 26, 180, 57, 244, 145, 0, 81, 227, 247, + 68, 27, 78, 154, 170, 195, 177, 178, 193, 167, 190, 64, 11, 134, + 31, 246, 213, 15, 61, 28, 117, 80, 20, 51, 26, 112, 70, 17, + 120, 148, 236, 157, 173, 18, 226, 112, 234, 143, 233, 107, 93, 13, + 174, 65, 141, 116, 197, 209, 223, 113, 199, 108, 137, 51, 19, 117, + 134, 252, 72, 176, 141, 217, 101, 250, 189, 99, 247, 188, 153, 116, + 107, 194, 43, 221, 94, 209, 48, 106, 87, 242, 54, 193, 56, 219, + 227, 50, 198, 222, 176, 20, 48, 230, 29, 101, 122, 233, 187, 168, + 176, 95, 255, 213, 88, 109, 184, 118, 123, 38, 229, 182, 102, 106, + 149, 168, 181, 42, 181, 12, 67, 34, 133, 137, 76, 76, 95, 34, + 176, 248, 137, 21, 246, 18, 169, 92, 146, 219, 41, 225, 152, 130, + 181, 163, 5, 25, 15, 51, 63, 218, 10, 11, 38, 171, 172, 89, + 147, 200, 16, 131, 218, 2, 153, 173, 188, 157, 149, 61, 99, 129, + 229, 0, 174, 135, 206, 170, 35, 56, 236, 241, 170, 59, 201, 65, + 120, 64, 236, 108, 174, 132, 126, 172, 164, 56, 104, 1, 227, 153, + 49, 243, 109, 78, 251, 192, 157, 60, 34, 71, 199, 55, 28, 251, + 26, 244, 93, 182, 11, 45, 239, 113, 100, 123, 171, 62, 240, 41, + 74, 253, 241, 156, 228, 99, 87, 5, 110, 194, 190, 64, 101, 216, + 19, 199, 237, 130, 140, 136, 106, 135, 224, 11, 138, 104, 222, 45, + 211, 119, 41, 205, 65, 238, 197, 76, 1, 120, 240, 107, 29, 51, + 229, 111, 205, 82, 209, 160, 19, 30, 221, 195, 119, 17, 244, 38, + 28, 67, 130, 94, 114, 8, 100, 150, 140, 175, 159, 159, 207, 71, + 182, 102, 252, 150, 130, 143, 68, 65, 227, 175, 107, 221, 120, 31, + 129, 77, 135, 189, 161, 12, 206, 93, 49, 46, 142, 70, 210, 174, + 103, 117, 133, 126, 231, 51, 73, 116, 185, 245, 93, 122, 151, 228, + 115, 68, 179, 14, 237, 47, 49, 186, 183, 99, 198, 72, 179, 40, + 97, 218, 115, 68, 2, 68, 215, 124, 231, 228, 138, 20, 61, 97, + 112, 233, 101, 59, 227, 27, 52, 236, 195, 128, 85, 134, 119, 167, + 242, 30, 202, 59, 155, 132, 156, 64, 113, 107, 192, 213, 55, 56, + 77, 32, 98, 66, 15, 156, 205, 18, 29, 186, 79, 46, 197, 238, + 25, 184, 143, 203, 177, 135, 68, 212, 216, 148, 48, 150, 110, 54, + 153, 243, 176, 91, 129, 76, 106, 90, 231, 164, 235, 94, 202, 143, + 123, 145, 0, 82, 158, 202, 237, 53, 147, 88, 99, 142, 58, 83, + 204, 229, 213, 91, 194, 120, 204, 248, 149, 238, 255, 250, 144, 159, + 155, 108, 28, 93, 97, 27, 34, 119, 50, 3, 241, 51, 97, 115, + 183, 67, 55, 225, 112, 36, 165, 240, 8, 60, 249, 237, 232, 94, + 255, 176, 33, 64, 207, 233, 93, 214, 132, 95, 27, 45, 154, 51, + 75, 195, 10, 42, 26, 56, 143, 175, 185, 214, 251, 13, 54, 75, + 155, 186, 139, 148, 158, 171, 204, 54, 81, 104, 117, 200, 114, 56, + 95, 54, 141, 162, 69, 154, 105, 86, 247, 251, 2, 6, 223, 192, + 149, 197, 78, 3, 117, 146, 118, 210, 91, 2, 216, 140, 216, 52, + 100, 48, 203, 106, 21, 83, 179, 148, 44, 37, 102, 47, 23, 122, + 28, 30, 116, 167, 143, 19, 117, 142, 234, 45, 200, 40, 191, 249, + 163, 216, 188, 196, 42, 21, 13, 134, 123, 90, 27, 118, 0, 114, + 227, 245, 16, 227, 121, 228, 180, 178, 236, 159, 151, 249, 159, 206, + 129, 107, 48, 191, 252, 122, 164, 92, 153, 153, 85, 27, 129, 15, + 244, 55, 184, 224, 38, 107, 44, 141, 105, 90, 183, 191, 143, 3, + 22, 81, 224, 219, 39, 33, 67, 253, 39, 91, 101, 17, 7, 20, + 205, 75, 155, 35, 99, 186, 88, 7, 118, 239, 23, 122, 15, 232, + 90, 3, 115, 200, 206, 106, 191, 127, 231, 132, 250, 182, 95, 184, + 46, 138, 242, 108, 168, 245, 177, 14, 8, 117, 203, 15, 85, 45, + 130, 15, 182, 7, 155, 111, 94, 188, 19, 1, 62, 132, 88, 227, + 159, 81, 54, 30, 39, 19, 147, 159, 195, 95, 81, 2, 24, 182, + 63, 232, 78, 182, 197, 106, 7, 248, 98, 179, 12, 239, 95, 89, + 153, 225, 210, 168, 56, 145, 249, 206, 31, 26, 57, 89, 176, 241, + 195, 233, 132, 238, 177, 116, 18, 48, 107, 165, 168, 119, 23, 63, + 115, 222, 6, 172, 80, 177, 211, 158, 42, 97, 151, 33, 179, 147, + 160, 42, 5, 118, 2, 180, 206, 0, 208, 22, 49, 60, 40, 50, + 43, 180, 39, 182, 66, 155, 112, 201, 167, 33, 35, 140, 227, 49, + 72, 24, 154, 175, 165, 152, 119, 118, 55, 83, 243, 93, 137, 106, + 20, 137, 39, 173, 11, 166, 220, 57, 103, 217, 164, 10, 49, 99, + 147, 128, 26, 238, 151, 244, 22, 157, 249, 166, 154, 159, 45, 250, + 211, 103, 99, 130, 57, 80, 30, 170, 91, 1, 154, 133, 231, 156, + 131, 122, 167, 17, 74, 74, 39, 2, 200, 27, 4, 63, 151, 149, + 192, 176, 86, 232, 147, 113, 211, 254, 217, 206, 252, 89, 72, 221, + 117, 207, 125, 241, 163, 210, 250, 54, 170, 117, 163, 17, 24, 64, + 191, 225, 58, 24, 255, 52, 114, 47, 241, 89, 204, 141, 98, 181, + 185, 59, 212, 187, 125, 56, 170, 223, 162, 7, 154, 4, 31, 9, + 211, 59, 81, 56, 31, 137, 78, 149, 162, 119, 12, 51, 163, 56, + 233, 8, 240, 43, 91, 88, 103, 194, 142, 29, 148, 181, 50, 56, + 223, 47, 40, 205, 174, 235, 89, 91, 186, 164, 201, 157, 79, 71, + 126, 186, 39, 158, 209, 85, 148, 246, 44, 92, 41, 207, 128, 226, + 227, 35, 217, 39, 209, 100, 91, 104, 52, 160, 37, 23, 60, 35, + 189, 195, 88, 133, 115, 127, 193, 203, 77, 245, 172, 196, 121, 193, + 70, 44, 199, 53, 76, 193, 141, 252, 170, 124, 54, 135, 178, 100, + 203, 86, 30, 215, 208, 183, 206, 4, 35, 170, 131, 59, 102, 205, + 159, 32, 234, 229, 208, 202, 77, 156, 123, 142, 149, 144, 29, 138, + 13, 240, 141, 177, 15, 82, 69, 120, 246, 217, 60, 223, 134, 58, + 138, 63, 134, 118, 168, 87, 123, 21, 203, 6, 24, 46, 75, 192, + 22, 182, 134, 132, 100, 225, 209, 2, 147, 65, 82, 55, 31, 250, + 21, 63, 136, 118, 91, 43, 0, 88, 96, 108, 25, 22, 213, 146, + 145, 210, 226, 202, 183, 241, 178, 152, 64, 0, 226, 54, 30, 48, + 53, 159, 215, 39, 73, 64, 101, 103, 231, 115, 200, 69, 41, 85, + 182, 37, 149, 149, 245, 228, 83, 179, 48, 52, 189, 96, 5, 97, + 197, 79, 222, 33, 29, 108, 60, 186, 246, 237, 14, 55, 42, 51, + 7, 41, 180, 177, 115, 148, 87, 153, 73, 108, 249, 53, 74, 3, + 129, 83, 31, 130, 82, 31, 17, 38, 75, 171, 130, 173, 145, 141, + 248, 156, 57, 155, 151, 73, 182, 82, 111, 215, 217, 100, 110, 129, + 77, 6, 229, 236, 164, 96, 159, 72, 248, 87, 79, 197, 183, 86, + 36, 206, 16, 91, 95, 128, 103, 22, 60, 134, 183, 60, 30, 53, + 133, 218, 161, 27, 107, 8, 162, 181, 186, 44, 196, 16, 56, 90, + 65, 41, 108, 54, 60, 126, 219, 202, 5, 177, 177, 211, 225, 186, + 102, 80, 108, 90, 134, 13, 235, 37, 71, 62, 6, 160, 185, 132, + 67, 213, 242, 121, 42, 157, 93, 159, 73, 210, 49, 44, 52, 11, + 155, 127, 101, 1, 119, 246, 122, 115, 24, 95, 103, 251, 240, 95, + 15, 133, 28, 59, 36, 247, 118, 236, 193, 255, 52, 156, 58, 173, + 242, 115, 207, 110, 30, 17, 132, 62, 175, 219, 183, 7, 77, 244, + 50, 151, 49, 127, 78, 210, 185, 54, 50, 235, 9, 169, 23, 118, + 137, 229, 171, 65, 13, 4, 141, 30, 146, 239, 152, 152, 68, 83, + 207, 123, 161, 238, 10, 165, 40, 126, 21, 229, 237, 192, 119, 56, + 191, 147, 185, 254, 88, 16, 131, 55, 146, 24, 64, 235, 141, 220, + 216, 115, 225, 6, 180, 21, 134, 133, 210, 170, 164, 177, 98, 141, + 237, 84, 232, 253, 28, 122, 143, 159, 59, 3, 202, 163, 76, 190, + 81, 124, 74, 136, 160, 102, 204, 220, 65, 194, 14, 97, 169, 72, + 135, 193, 54, 113, 192, 209, 200, 174, 66, 100, 187, 211, 124, 147, + 171, 188, 187, 185, 42, 122, 109, 148, 169, 39, 236, 201, 29, 245, + 223, 187, 204, 21, 40, 31, 174, 220, 231, 118, 142, 96, 165, 8, + 12, 141, 71, 52, 121, 108, 132, 116, 214, 11, 114, 128, 143, 39, + 19, 230, 39, 248, 74, 192, 206, 247, 253, 227, 46, 41, 250, 135, + 96, 63, 25, 155, 216, 11, 119, 61, 192, 90, 245, 90, 230, 78, + 248, 78, 95, 199, 0, 197, 170, 181, 249, 2, 34, 74, 15, 61, + 37, 74, 251, 218, 134, 253, 103, 251, 88, 151, 255, 226, 201, 236, + 53, 13, 132, 104, 35, 152, 39, 144, 226, 4, 231, 47, 199, 140, + 161, 89, 225, 224, 89, 93, 38, 242, 161, 119, 43, 73, 231, 150, + 18, 191, 56, 235, 31, 112, 220, 35, 239, 156, 55, 226, 112, 204, + 62, 42, 14, 240, 134, 66, 109, 35, 56, 162, 182, 180, 99, 233, + 88, 60, 204, 10, 230, 196, 48, 170, 13, 69, 17, 10, 213, 235, + 206, 185, 197, 79, 136, 142, 164, 114, 48, 100, 222, 234, 177, 119, + 36, 128, 144, 147, 68, 20, 35, 218, 39, 89, 38, 44, 134, 93, + 38, 157, 85, 179, 117, 62, 56, 217, 194, 2, 169, 65, 228, 6, + 237, 243, 71, 63, 111, 148, 203, 68, 216, 246, 213, 215, 166, 29, + 93, 229, 33, 117, 227, 43, 176, 218, 25, 201, 76, 55, 84, 97, + 30, 164, 12, 100, 78, 120, 195, 33, 8, 86, 107, 193, 37, 214, + 210, 159, 210, 4, 51, 161, 217, 71, 90, 146, 230, 50, 54, 89, + 26, 52, 65, 38, 50, 190, 159, 231, 189, 51, 8, 128, 109, 113, + 165, 80, 211, 83, 116, 189, 170, 205, 153, 216, 41, 44, 74, 98, + 133, 71, 248, 231, 38, 121, 238, 14, 101, 44, 144, 81, 195, 88, + 18, 116, 177, 64, 121, 152, 26, 232, 160, 137, 252, 67, 199, 170, + 63, 251, 15, 225, 18, 244, 225, 136, 211, 233, 125, 37, 185, 235, + 97, 62, 245, 234, 228, 166, 243, 128, 197, 67, 53, 137, 110, 190, + 113, 221, 121, 73, 225, 126, 41, 146, 251, 35, 88, 55, 228, 216, + 48, 187, 208, 57, 227, 154, 19, 242, 80, 156, 239, 177, 12, 153, + 20, 37, 16, 118, 115, 216, 115, 248, 122, 233, 12, 241, 193, 166, + 195, 186, 234, 115, 140, 73, 112, 79, 151, 140, 14, 114, 116, 239, + 137, 6, 234, 172, 66, 118, 220, 8, 2, 190, 226, 191, 24, 55, + 225, 24, 143, 79, 95, 85, 74, 52, 159, 106, 30, 57, 64, 147, + 225, 16, 165, 107, 185, 115, 131, 57, 155, 146, 52, 240, 38, 92, + 112, 186, 99, 240, 176, 223, 63, 126, 116, 232, 133, 221, 154, 28, + 255, 146, 29, 241, 248, 184, 182, 147, 26, 101, 37, 173, 249, 185, + 44, 215, 65, 23, 78, 218, 109, 71, 217, 113, 205, 246, 210, 2, + 201, 117, 200, 24, 217, 187, 56, 5, 73, 62, 184, 97, 151, 230, + 195, 168, 187, 95, 18, 123, 12, 98, 90, 100, 28, 43, 28, 180, + 225, 90, 43, 218, 244, 206, 192, 187, 253, 32, 159, 177, 48, 242, + 173, 243, 76, 8, 220, 186, 176, 53, 237, 216, 180, 97, 200, 36, + 122, 25, 5, 31, 143, 216, 232, 225, 231, 148, 30, 208, 122, 185, + 215, 154, 96, 233, 29, 204, 119, 148, 44, 82, 111, 5, 148, 25, + 229, 191, 69, 123, 103, 210, 158, 5, 86, 72, 155, 102, 169, 184, + 1, 85, 124, 157, 29, 250, 159, 17, 143, 29, 154, 195, 135, 145, + 47, 57, 36, 163, 111, 192, 14, 221, 133, 139, 233, 25, 47, 185, + 32, 32, 153, 132, 181, 253, 2, 40, 39, 75, 25, 73, 112, 131, + 102, 38, 206, 138, 225, 22, 60, 7, 183, 35, 152, 34, 193, 91, + 168, 180, 211, 121, 238, 13, 147, 188, 90, 181, 82, 236, 204, 144, + 67, 152, 158, 73, 49, 224, 189, 164, 8, 180, 195, 146, 137, 196, + 5, 171, 164, 62, 58, 248, 149, 75, 12, 144, 97, 151, 75, 39, + 46, 87, 182, 170, 107, 6, 242, 197, 32, 169, 74, 161, 209, 212, + 212, 207, 202, 173, 95, 239, 156, 53, 215, 157, 220, 60, 96, 105, + 162, 126, 246, 58, 198, 86, 241, 75, 92, 142, 164, 181, 138, 169, + 200, 25, 105, 252, 7, 206, 18, 137, 53, 212, 200, 48, 159, 34, + 33, 169, 239, 209, 177, 239, 4, 24, 142, 43, 141, 94, 206, 185, + 75, 116, 185, 131, 100, 39, 157, 74, 72, 254, 57, 220, 241, 214, + 75, 141, 166, 126, 207, 8, 250, 225, 4, 189, 239, 175, 47, 184, + 143, 147, 85, 85, 35, 85, 171, 199, 91, 113, 195, 111, 53, 240, + 230, 162, 99, 33, 50, 186, 107, 156, 53, 171, 43, 78, 176, 191, + 67, 107, 223, 141, 83, 53, 65, 234, 90, 230, 255, 174, 162, 40, + 84, 71, 183, 139, 247, 75, 223, 193, 7, 121, 219, 158, 79, 110, + 211, 229, 45, 239, 159, 104, 198, 166, 50, 93, 133, 38, 14, 87, + 58, 230, 247, 180, 126, 100, 109, 13, 222, 50, 78, 17, 138, 226, + 42, 245, 207, 239, 129, 188, 30, 6, 153, 42, 67, 34, 199, 133, + 40, 103, 90, 97, 29, 188, 251, 44, 171, 227, 161, 14, 221, 15, + 209, 49, 180, 145, 92, 193, 149, 34, 49, 48, 193, 131, 56, 6, + 38, 107, 142, 248, 35, 37, 115, 156, 112, 79, 157, 44, 21, 132, + 128, 86, 135, 179, 91, 188, 184, 84, 185, 230, 242, 55, 176, 192, + 127, 173, 249, 91, 236, 3, 24, 104, 158, 238, 236, 38, 83, 172, + 90, 105, 163, 0, 205, 77, 247, 21, 200, 81, 8, 202, 240, 185, + 158, 53, 133, 178, 124, 148, 125, 162, 87, 80, 92, 236, 192, 214, + 6, 244, 233, 191, 80, 106, 13, 13, 48, 125, 106, 208, 212, 11, + 28, 15, 127, 252, 45, 183, 215, 76, 28, 19, 75, 183, 183, 127, + 6, 94, 142, 65, 26, 67, 6, 63, 238, 94, 115, 123, 60, 247, + 1, 178, 55, 37, 185, 76, 128, 172, 23, 4, 158, 189, 10, 203, + 199, 169, 24, 99, 80, 145, 9, 44, 157, 35, 91, 103, 29, 127, + 19, 159, 3, 109, 232, 168, 6, 169, 237, 158, 155, 131, 250, 31, + 251, 35, 151, 0, 159, 16, 67, 239, 65, 227, 159, 23, 250, 93, + 144, 41, 202, 176, 70, 146, 171, 136, 157, 185, 190, 145, 59, 105, + 106, 237, 149, 30, 217, 217, 123, 145, 102, 99, 74, 42, 164, 94, + 3, 91, 53, 168, 190, 166, 112, 149, 118, 8, 210, 76, 188, 247, + 17, 31, 122, 48, 109, 52, 127, 237, 2, 213, 124, 214, 162, 175, + 70, 34, 227, 178, 197, 164, 249, 29, 45, 37, 1, 1, 4, 231, + 217, 59, 72, 27, 234, 181, 56, 85, 163, 130, 41, 155, 211, 191, + 185, 33, 65, 57, 20, 77, 60, 221, 94, 245, 12, 159, 77, 133, + 17, 204, 95, 195, 90, 250, 219, 224, 166, 114, 66, 88, 34, 63, + 104, 126, 209, 74, 135, 29, 234, 78, 46, 235, 224, 135, 45, 100, + 3, 57, 60, 31, 153, 63, 4, 178, 5, 238, 118, 63, 210, 20, + 137, 18, 118, 37, 154, 147, 247, 3, 239, 169, 9, 251, 89, 195, + 119, 49, 23, 242, 32, 77, 36, 136, 147, 26, 155, 176, 156, 96, + 233, 94, 76, 149, 90, 36, 18, 249, 92, 55, 42, 181, 247, 204, + 18, 159, 175, 71, 146, 52, 107, 118, 20, 13, 186, 154, 171, 8, + 16, 107, 96, 43, 55, 244, 84, 142, 201, 8, 65, 152, 139, 165, + 165, 181, 218, 68, 94, 2, 155, 83, 173, 58, 193, 64, 253, 130, + 33, 98, 212, 127, 126, 33, 229, 102, 169, 90, 195, 162, 84, 108, + 113, 1, 228, 49, 14, 93, 5, 127, 172, 193, 155, 88, 9, 48, + 16, 190, 14, 116, 155, 137, 10, 217, 18, 211, 105, 148, 190, 127, + 17, 177, 176, 210, 137, 236, 202, 126, 29, 93, 36, 111, 123, 78, + 108, 194, 60, 31, 134, 205, 18, 60, 220, 122, 127, 14, 151, 234, + 66, 2, 120, 101, 23, 208, 225, 96, 53, 32, 91, 58, 164, 165, + 140, 195, 16, 128, 156, 204, 62, 190, 19, 150, 124, 183, 23, 13, + 162, 45, 49, 17, 52, 33, 139, 202, 24, 144, 80, 166, 24, 49, + 144, 89, 145, 0, 189, 255, 108, 189, 149, 75, 32, 132, 111, 237, + 241, 215, 159, 41, 225, 254, 204, 155, 111, 122, 34, 141, 23, 195, + 77, 57, 149, 4, 140, 218, 104, 254, 88, 21, 13, 184, 234, 27, + 119, 118, 97, 217, 105, 197, 100, 198, 2, 93, 251, 3, 109, 240, + 142, 19, 88, 65, 34, 58, 104, 88, 250, 38, 67, 44, 96, 84, + 118, 176, 196, 56, 172, 190, 120, 113, 43, 252, 178, 202, 124, 79, + 118, 125, 242, 30, 9, 39, 206, 82, 144, 93, 201, 156, 213, 223, + 1, 21, 222, 90, 230, 70, 187, 254, 251, 39, 202, 131, 235, 13, + 242, 165, 70, 237, 209, 15, 167, 255, 179, 245, 28, 49, 150, 132, + 12, 201, 87, 90, 75, 193, 223, 234, 40, 227, 237, 155, 123, 116, + 13, 36, 23, 222, 54, 235, 215, 115, 243, 175, 7, 82, 95, 245, + 235, 16, 11, 37, 165, 247, 211, 214, 7, 244, 161, 133, 157, 90, + 46, 229, 14, 214, 67, 37, 199, 182, 116, 156, 142, 41, 98, 54, + 203, 240, 122, 158, 254, 84, 190, 135, 15, 15, 33, 80, 185, 224, + 167, 210, 190, 238, 128, 135, 124, 68, 153, 2, 247, 69, 122, 69, + 186, 57, 14, 113, 87, 236, 179, 62, 44, 191, 227, 112, 88, 44, + 35, 37, 169, 12, 229, 17, 29, 175, 250, 39, 75, 80, 92, 62, + 65, 42, 188, 33, 135, 27, 140, 65, 25, 179, 162, 211, 90, 70, + 229, 39, 85, 168, 82, 96, 101, 111, 128, 124, 69, 19, 22, 94, + 76, 22, 207, 62, 201, 222, 235, 1, 205, 231, 186, 219, 160, 225, + 135, 250, 119, 71, 215, 116, 85, 172, 94, 119, 168, 86, 31, 193, + 220, 25, 101, 186, 243, 46, 105, 202, 47, 106, 14, 193, 30, 107, + 186, 2, 96, 83, 209, 223, 81, 95, 200, 20, 238, 198, 223, 0, + 4, 242, 30, 66, 238, 159, 163, 129, 254, 82, 56, 226, 248, 65, + 25, 136, 96, 247, 6, 31, 112, 231, 219, 201, 151, 27, 19, 194, + 243, 236, 106, 46, 252, 177, 204, 41, 0, 109, 160, 76, 4, 143, + 194, 167, 9, 233, 84, 183, 232, 2, 68, 90, 255, 5, 133, 68, + 172, 214, 43, 175, 119, 214, 246, 67, 181, 65, 180, 250, 247, 32, + 30, 175, 178, 74, 192, 160, 144, 222, 7, 134, 212, 243, 117, 81, + 194, 48, 32, 232, 62, 85, 35, 114, 136, 196, 67, 115, 246, 182, + 43, 64, 165, 253, 180, 78, 102, 246, 208, 140, 72, 241, 209, 5, + 7, 194, 78, 229, 202, 165, 251, 227, 74, 142, 155, 30, 2, 178, + 197, 80, 123, 162, 230, 198, 157, 175, 15, 7, 211, 117, 186, 61, + 138, 206, 182, 80, 200, 138, 47, 236, 136, 237, 68, 170, 81, 168, + 99, 122, 79, 229, 222, 94, 46, 208, 162, 110, 36, 199, 247, 12, + 125, 109, 93, 120, 81, 137, 212, 195, 119, 40, 118, 156, 208, 52, + 70, 213, 209, 157, 94, 35, 230, 76, 248, 241, 50, 213, 204, 245, + 230, 113, 38, 205, 232, 175, 34, 39, 189, 223, 28, 244, 231, 190, + 254, 221, 56, 8, 206, 53, 50, 87, 180, 172, 204, 198, 148, 194, + 63, 29, 234, 225, 39, 201, 178, 225, 228, 36, 40, 196, 51, 85, + 173, 60, 84, 199, 27, 173, 128, 97, 200, 121, 17, 43, 82, 85, + 151, 238, 179, 157, 105, 216, 113, 209, 165, 146, 212, 229, 189, 119, + 157, 84, 158, 6, 169, 116, 138, 236, 137, 162, 231, 78, 84, 93, + 245, 183, 123, 168, 229, 21, 77, 100, 232, 176, 174, 121, 113, 31, + 81, 193, 177, 211, 254, 172, 247, 180, 206, 133, 184, 200, 209, 72, + 16, 190, 209, 154, 49, 187, 125, 246, 110, 203, 212, 30, 53, 33, + 4, 97, 168, 255, 60, 34, 158, 27, 211, 13, 74, 125, 94, 134, + 83, 7, 1, 199, 32, 78, 183, 36, 231, 62, 150, 136, 227, 236, + 64, 17, 124, 129, 56, 77, 13, 92, 93, 102, 237, 248, 190, 157, + 114, 238, 127, 90, 23, 171, 232, 240, 147, 135, 195, 251, 62, 210, + 212, 135, 164, 54, 244, 84, 185, 72, 222, 94, 39, 79, 132, 125, + 186, 99, 173, 96, 67, 148, 187, 199, 145, 59, 111, 164, 252, 28, + 120, 208, 250, 104, 242, 227, 29, 170, 36, 47, 219, 25, 144, 121, + 102, 24, 127, 6, 131, 184, 29, 190, 91, 191, 113, 15, 244, 138, + 192, 74, 2, 55, 27, 86, 96, 120, 227, 46, 79, 146, 64, 61, + 211, 199, 56, 159, 21, 235, 156, 148, 250, 49, 217, 72, 162, 249, + 64, 164, 24, 176, 133, 46, 116, 135, 135, 13, 101, 27, 117, 174, + 194, 17, 216, 180, 163, 171, 138, 222, 60, 108, 205, 2, 241, 105, + 125, 218, 228, 185, 75, 20, 66, 70, 226, 111, 222, 168, 199, 40, + 40, 229, 182, 245, 113, 65, 72, 188, 55, 172, 236, 145, 96, 245, + 221, 180, 163, 185, 249, 105, 236, 198, 249, 2, 14, 163, 173, 185, + 25, 149, 78, 229, 73, 136, 28, 179, 20, 44, 52, 42, 55, 237, + 108, 155, 225, 200, 53, 119, 125, 223, 49, 231, 156, 202, 142, 115, + 203, 239, 2, 88, 113, 2, 93, 190, 174, 137, 121, 248, 108, 247, + 101, 80, 95, 19, 32, 225, 107, 253, 64, 167, 132, 110, 3, 82, + 144, 232, 1, 161, 233, 139, 0, 220, 77, 122, 25, 21, 60, 54, + 126, 151, 47, 120, 55, 176, 75, 81, 214, 174, 147, 102, 254, 113, + 185, 101, 207, 220, 159, 210, 121, 74, 124, 224, 45, 151, 194, 54, + 25, 78, 86, 15, 169, 254, 4, 50, 87, 62, 179, 27, 187, 203, + 6, 252, 141, 128, 164, 104, 166, 141, 20, 163, 142, 99, 94, 87, + 125, 168, 30, 72, 199, 141, 89, 169, 248, 243, 152, 140, 186, 176, + 12, 31, 101, 206, 136, 49, 251, 4, 71, 236, 124, 46, 233, 112, + 208, 127, 28, 254, 80, 193, 145, 130, 88, 228, 87, 6, 146, 7, + 15, 101, 165, 235, 143, 223, 168, 158, 138, 93, 41, 13, 26, 187, + 53, 85, 217, 97, 19, 108, 125, 255, 252, 39, 121, 3, 119, 83, + 92, 126, 198, 228, 96, 227, 16, 164, 17, 93, 57, 241, 46, 100, + 206, 33, 186, 43, 9, 236, 1, 149, 110, 105, 255, 45, 73, 146, + 43, 190, 89, 113, 126, 235, 176, 172, 98, 167, 244, 117, 68, 100, + 179, 85, 207, 29, 164, 68, 240, 221, 37, 110, 209, 224, 34, 214, + 92, 225, 59, 168, 101, 21, 229, 142, 52, 182, 151, 67, 4, 222, + 112, 139, 243, 158, 49, 234, 21, 135, 6, 8, 221, 220, 102, 57, + 61, 66, 70, 105, 18, 68, 134, 155, 17, 238, 9, 72, 185, 177, + 220, 221, 7, 240, 220, 42, 88, 226, 75, 202, 137, 72, 129, 130, + 59, 90, 127, 101, 134, 68, 154, 254, 14, 23, 5, 185, 17, 177, + 44, 65, 8, 71, 173, 254, 188, 100, 169, 213, 104, 219, 216, 12, + 142, 128, 193, 195, 216, 214, 147, 100, 11, 42, 22, 203, 70, 156, + 145, 188, 39, 167, 16, 248, 6, 228, 79, 37, 40, 72, 94, 31, + 253, 120, 67, 16, 255, 88, 52, 72, 210, 95, 178, 155, 8, 203, + 229, 150, 20, 59, 233, 192, 121, 154, 131, 253, 134, 63, 141, 36, + 223, 166, 191, 30, 96, 10, 39, 167, 31, 187, 184, 172, 248, 51, + 92, 68, 102, 180, 239, 52, 250, 5, 55, 252, 206, 55, 145, 74, + 101, 82, 255, 85, 220, 160, 140, 84, 0, 180, 91, 147, 53, 43, + 49, 31, 14, 147, 250, 99, 231, 27, 138, 233, 52, 4, 103, 20, + 154, 53, 16, 199, 162, 88, 109, 92, 191, 194, 147, 7, 208, 11, + 205, 53, 88, 127, 3, 21, 228, 111, 149, 76, 79, 213, 45, 31, + 128, 110, 64, 78, 246, 69, 77, 69, 128, 57, 64, 226, 147, 204, + 66, 110, 232, 14, 135, 137, 104, 205, 32, 209, 13, 90, 15, 173, + 177, 101, 137, 205, 95, 183, 232, 249, 125, 129, 193, 62, 217, 117, + 186, 214, 246, 249, 3, 109, 79, 12, 104, 1, 52, 119, 135, 138, + 228, 57, 237, 64, 177, 61, 91, 255, 210, 25, 253, 250, 223, 27, + 185, 89, 126, 10, 233, 19, 95, 9, 243, 190, 13, 253, 204, 226, + 63, 136, 224, 112, 192, 220, 215, 161, 129, 98, 69, 24, 122, 33, + 208, 125, 115, 119, 251, 223, 235, 176, 128, 75, 189, 55, 155, 161, + 86, 126, 110, 222, 64, 171, 155, 130, 241, 148, 153, 70, 74, 3, + 160, 213, 137, 73, 10, 222, 112, 15, 184, 217, 201, 193, 201, 10, + 135, 215, 119, 7, 167, 202, 101, 55, 62, 96, 131, 106, 127, 197, + 67, 146, 4, 237, 81, 168, 232, 90, 83, 165, 48, 234, 92, 37, + 34, 185, 216, 26, 76, 75, 205, 110, 67, 51, 89, 22, 101, 175, + 76, 185, 174, 8, 170, 106, 170, 252, 235, 13, 232, 87, 218, 103, + 223, 250, 192, 244, 51, 24, 88, 52, 189, 118, 159, 20, 1, 181, + 213, 64, 129, 172, 168, 230, 177, 96, 225, 203, 68, 1, 48, 239, + 8, 169, 159, 117, 199, 50, 20, 71, 183, 56, 17, 115, 221, 246, + 255, 52, 161, 241, 238, 237, 166, 1, 241, 151, 89, 124, 200, 1, + 73, 190, 4, 215, 93, 168, 29, 103, 177, 77, 230, 109, 177, 202, + 227, 1, 157, 52, 22, 181, 54, 41, 209, 37, 47, 188, 194, 95, + 187, 172, 2, 255, 11, 20, 107, 236, 28, 13, 49, 121, 57, 2, + 131, 101, 250, 206, 228, 124, 174, 43, 93, 228, 31, 90, 212, 165, + 4, 150, 56, 150, 85, 166, 206, 79, 89, 197, 210, 4, 92, 55, + 96, 105, 196, 223, 178, 198, 241, 255, 77, 165, 244, 139, 50, 203, + 147, 215, 232, 216, 90, 74, 60, 91, 27, 7, 248, 2, 159, 157, + 76, 230, 130, 91, 168, 136, 31, 83, 44, 34, 60, 31, 210, 157, + 8, 215, 170, 1, 197, 5, 143, 99, 146, 107, 104, 115, 67, 185, + 42, 22, 102, 129, 31, 238, 240, 182, 248, 178, 100, 24, 156, 74, + 5, 5, 63, 17, 111, 186, 98, 178, 26, 85, 171, 73, 145, 113, + 84, 248, 107, 238, 130, 37, 186, 10, 46, 183, 172, 144, 185, 98, + 253, 58, 130, 120, 209, 227, 75, 58, 186, 97, 49, 37, 227, 225, + 0, 146, 67, 40, 239, 9, 243, 39, 211, 161, 92, 157, 88, 67, + 115, 145, 74, 225, 22, 213, 139, 117, 102, 129, 98, 189, 137, 100, + 20, 46, 222, 209, 15, 57, 192, 21, 237, 71, 196, 88, 235, 63, + 13, 57, 87, 56, 66, 3, 77, 7, 95, 192, 114, 115, 121, 3, + 222, 118, 207, 108, 214, 89, 118, 247, 45, 231, 174, 223, 175, 7, + 210, 250, 74, 151, 180, 62, 140, 254, 147, 90, 115, 23, 145, 204, + 68, 151, 198, 162, 217, 145, 40, 60, 65, 179, 119, 47, 120, 213, + 141, 159, 123, 94, 52, 102, 233, 146, 152, 183, 27, 45, 156, 89, + 153, 109, 130, 16, 223, 9, 186, 87, 153, 83, 226, 213, 92, 212, + 146, 59, 96, 100, 36, 16, 80, 112, 43, 22, 160, 178, 151, 204, + 83, 96, 22, 6, 225, 166, 87, 187, 164, 255, 100, 6, 107, 108, + 210, 172, 130, 226, 208, 66, 35, 240, 88, 153, 122, 1, 180, 135, + 3, 46, 163, 85, 215, 219, 209, 157, 146, 12, 254, 145, 2, 78, + 153, 29, 248, 206, 108, 20, 100, 226, 53, 119, 129, 156, 21, 100, + 223, 209, 154, 123, 247, 55, 240, 176, 46, 29, 97, 33, 217, 234, + 215, 206, 253, 196, 220, 64, 40, 204, 107, 11, 91, 40, 35, 159, + 119, 36, 51, 164, 52, 177, 29, 63, 44, 222, 82, 51, 250, 24, + 205, 66, 236, 237, 155, 6, 13, 61, 248, 13, 108, 51, 187, 210, + 12, 215, 206, 71, 197, 127, 104, 76, 134, 233, 83, 233, 17, 236, + 100, 131, 116, 198, 84, 222, 175, 182, 96, 116, 177, 176, 155, 146, + 173, 5, 245, 21, 218, 54, 83, 110, 167, 163, 132, 67, 247, 216, + 154, 164, 58, 185, 94, 183, 187, 107, 68, 55, 106, 65, 95, 242, + 217, 108, 85, 236, 89, 235, 117, 42, 239, 149, 55, 97, 61, 187, + 157, 161, 255, 135, 215, 23, 10, 227, 64, 79, 118, 120, 12, 9, + 223, 4, 49, 6, 58, 129, 51, 195, 169, 30, 157, 90, 242, 217, + 227, 135, 168, 223, 186, 55, 192, 166, 79, 221, 144, 200, 217, 49, + 248, 110, 217, 211, 148, 27, 216, 173, 91, 205, 246, 185, 54, 238, + 72, 185, 136, 68, 229, 160, 218, 163, 91, 187, 19, 164, 51, 28, + 105, 125, 104, 197, 187, 248, 189, 88, 38, 19, 235, 163, 236, 181, + 222, 24, 62, 136, 230, 248, 246, 56, 229, 130, 241, 251, 140, 190, + 209, 151, 220, 41, 53, 56, 29, 165, 88, 228, 18, 210, 106, 88, + 170, 159, 201, 127, 71, 188, 110, 19, 188, 112, 194, 239, 121, 208, + 26, 161, 238, 215, 22, 74, 84, 31, 252, 166, 54, 230, 66, 112, + 129, 134, 37, 96, 183, 83, 223, 27, 172, 212, 176, 147, 168, 115, + 162, 171, 190, 189, 89, 90, 177, 20, 157, 38, 38, 5, 16, 199, + 34, 149, 134, 26, 160, 213, 71, 187, 140, 88, 204, 19, 137, 128, + 199, 152, 195, 51, 140, 0, 39, 88, 158, 26, 23, 213, 56, 19, + 84, 4, 162, 100, 111, 163, 39, 115, 122, 85, 146, 86, 226, 38, + 95, 126, 2, 54, 240, 196, 87, 255, 85, 108, 144, 192, 23, 141, + 211, 232, 198, 127, 141, 206, 0, 34, 169, 99, 84, 21, 84, 116, + 99, 201, 166, 14, 30, 2, 203, 237, 243, 36, 117, 211, 131, 189, + 164, 40, 101, 73, 139, 95, 234, 203, 29, 82, 72, 131, 144, 255, + 37, 104, 82, 62, 15, 218, 137, 91, 126, 179, 27, 95, 136, 44, + 109, 179, 221, 141, 100, 85, 244, 185, 95, 38, 32, 112, 187, 84, + 58, 218, 205, 230, 113, 169, 69, 73, 227, 14, 101, 99, 139, 113, + 87, 204, 117, 10, 236, 46, 44, 19, 10, 137, 129, 185, 135, 3, + 173, 154, 177, 17, 146, 213, 160, 116, 151, 15, 86, 143, 116, 199, + 196, 47, 204, 23, 151, 123, 202, 48, 146, 244, 142, 43, 231, 161, + 170, 115, 38, 206, 41, 123, 23, 17, 165, 190, 52, 84, 157, 60, + 78, 221, 2, 134, 227, 131, 185, 148, 153, 171, 48, 72, 7, 105, + 44, 3, 228, 129, 9, 28, 124, 173, 61, 143, 14, 219, 8, 161, + 205, 228, 243, 186, 64, 97, 128, 189, 35, 47, 139, 33, 19, 27, + 218, 224, 174, 112, 189, 19, 232, 228, 93, 71, 127, 238, 110, 104, + 156, 72, 129, 230, 148, 162, 110, 39, 56, 87, 202, 158, 254, 212, + 85, 192, 38, 157, 200, 252, 213, 219, 75, 173, 242, 89, 218, 148, + 136, 180, 207, 5, 145, 66, 65, 81, 236, 208, 206, 77, 238, 54, + 34, 27, 101, 24, 178, 150, 172, 213, 212, 221, 95, 175, 252, 64, + 188, 43, 195, 89, 139, 54, 69, 125, 150, 22, 152, 180, 230, 140, + 181, 24, 33, 76, 235, 180, 65, 6, 1, 131, 158, 130, 149, 174, + 56, 253, 189, 80, 249, 95, 5, 166, 180, 220, 82, 124, 61, 47, + 35, 2, 199, 20, 1, 180, 186, 225, 195, 153, 107, 227, 17, 179, + 4, 149, 113, 227, 121, 119, 177, 195, 201, 226, 24, 154, 97, 197, + 218, 58, 133, 188, 146, 55, 156, 79, 215, 90, 16, 61, 189, 45, + 215, 229, 124, 248, 47, 7, 158, 134, 56, 148, 213, 227, 190, 3, + 69, 171, 158, 182, 135, 162, 85, 99, 186, 151, 95, 201, 86, 224, + 85, 45, 113, 49, 29, 161, 17, 252, 140, 6, 131, 121, 89, 177, + 4, 163, 31, 61, 182, 226, 252, 242, 71, 10, 219, 64, 19, 4, + 118, 58, 175, 156, 81, 231, 85, 250, 128, 143, 167, 132, 180, 2, + 37, 222, 214, 131, 234, 232, 17, 182, 253, 176, 166, 179, 117, 165, + 135, 52, 202, 225, 11, 16, 39, 43, 206, 38, 26, 66, 4, 236, + 117, 139, 229, 164, 93, 191, 199, 17, 122, 75, 80, 98, 175, 77, + 53, 64, 64, 205, 156, 195, 152, 80, 8, 130, 25, 131, 57, 28, + 228, 242, 112, 122, 217, 83, 235, 220, 58, 131, 3, 154, 249, 1, + 26, 247, 118, 178, 212, 89, 150, 121, 248, 193, 95, 10, 83, 79, + 155, 224, 224, 139, 161, 31, 236, 176, 38, 61, 219, 18, 157, 192, + 253, 193, 214, 145, 62, 144, 111, 58, 128, 80, 53, 188, 150, 19, + 8, 217, 10, 215, 166, 144, 214, 86, 74, 146, 173, 162, 185, 33, + 78, 74, 166, 56, 225, 229, 32, 219, 75, 94, 243, 48, 104, 84, + 55, 13, 161, 133, 228, 224, 121, 10, 206, 26, 8, 19, 115, 244, + 7, 146, 176, 66, 140, 200, 224, 137, 79, 63, 254, 6, 205, 72, + 151, 214, 202, 234, 169, 15, 1, 239, 110, 240, 182, 25, 44, 239, + 127, 121, 16, 15, 55, 43, 149, 76, 146, 41, 176, 46, 29, 4, + 54, 35, 49, 8, 70, 209, 156, 152, 120, 143, 86, 28, 170, 150, + 26, 243, 98, 38, 152, 169, 138, 250, 189, 176, 62, 105, 157, 107, + 165, 7, 40, 34, 19, 234, 81, 121, 227, 196, 20, 234, 61, 252, + 91, 32, 156, 79, 248, 153, 1, 254, 225, 5, 127, 98, 49, 175, + 145, 66, 0, 89, 165, 142, 45, 125, 63, 127, 250, 105, 94, 249, + 130, 175, 245, 125, 131, 227, 237, 96, 31, 231, 245, 130, 25, 173, + 8, 69, 152, 47, 34, 70, 3, 233, 218, 216, 71, 114, 102, 221, + 125, 7, 199, 254, 88, 120, 133, 122, 95, 247, 91, 25, 203, 191, + 230, 92, 229, 19, 78, 141, 225, 242, 2, 218, 254, 182, 229, 91, + 207, 59, 186, 209, 195, 89, 212, 23, 97, 212, 77, 165, 130, 66, + 38, 186, 58, 38, 153, 159, 74, 221, 252, 81, 103, 97, 82, 128, + 255, 122, 205, 202, 248, 89, 24, 252, 214, 124, 44, 34, 169, 78, + 111, 87, 231, 90, 60, 211, 198, 205, 0, 90, 67, 126, 25, 72, + 78, 178, 238, 53, 89, 29, 51, 199, 38, 195, 77, 218, 213, 82, + 58, 199, 203, 231, 16, 181, 30, 240, 87, 77, 72, 128, 250, 205, + 70, 188, 15, 112, 209, 196, 129, 29, 214, 224, 164, 103, 95, 184, + 32, 119, 6, 198, 87, 107, 150, 148, 139, 117, 80, 76, 70, 10, + 91, 1, 119, 29, 18, 62, 131, 65, 158, 105, 244, 139, 182, 239, + 88, 12, 254, 144, 213, 17, 45, 151, 8, 109, 119, 75, 70, 236, + 114, 10, 152, 188, 7, 171, 99, 9, 125, 79, 60, 216, 238, 225, + 75, 248, 72, 210, 14, 181, 15, 181, 82, 90, 128, 230, 211, 107, + 254, 54, 65, 70, 217, 13, 173, 25, 243, 80, 161, 214, 255, 126, + 61, 28, 129, 199, 168, 114, 18, 67, 30, 33, 15, 189, 113, 80, + 115, 203, 128, 192, 109, 164, 164, 138, 175, 38, 151, 217, 83, 201, + 236, 245, 47, 57, 86, 214, 218, 120, 237, 193, 156, 113, 106, 1, + 33, 18, 21, 4, 238, 76, 161, 133, 111, 62, 98, 206, 89, 175, + 61, 235, 19, 201, 137, 143, 205, 47, 47, 143, 60, 236, 116, 184, + 8, 208, 156, 37, 72, 215, 108, 100, 66, 100, 212, 206, 152, 93, + 57, 251, 21, 150, 192, 112, 136, 115, 138, 185, 154, 183, 38, 14, + 150, 44, 9, 231, 185, 204, 245, 202, 161, 118, 48, 163, 207, 43, + 54, 4, 138, 62, 253, 238, 42, 239, 224, 169, 53, 155, 80, 67, + 233, 38, 152, 145, 81, 166, 121, 167, 224, 167, 175, 182, 0, 68, + 195, 13, 228, 134, 167, 210, 17, 209, 22, 95, 124, 78, 220, 216, + 97, 95, 13, 164, 178, 65, 242, 222, 138, 184, 222, 116, 214, 53, + 130, 229, 99, 166, 47, 50, 235, 140, 190, 239, 93, 76, 201, 40, + 135, 65, 224, 242, 236, 38, 191, 29, 111, 191, 174, 250, 240, 206, + 12, 136, 51, 9, 248, 152, 201, 75, 92, 189, 125, 156, 101, 130, + 182, 74, 226, 47, 92, 10, 60, 7, 46, 239, 56, 171, 134, 105, + 142, 227, 11, 225, 196, 197, 42, 207, 181, 164, 48, 72, 7, 94, + 46, 152, 59, 201, 131, 94, 254, 225, 69, 200, 179, 144, 253, 37, + 176, 84, 216, 90, 30, 90, 153, 236, 134, 236, 133, 66, 147, 86, + 182, 60, 90, 247, 69, 79, 30, 228, 223, 135, 222, 137, 8, 85, + 223, 22, 26, 170, 61, 178, 250, 69, 246, 88, 244, 30, 63, 80, + 96, 167, 204, 7, 235, 193, 63, 13, 83, 121, 172, 3, 149, 128, + 94, 234, 240, 13, 154, 81, 155, 174, 51, 183, 53, 234, 239, 71, + 164, 30, 46, 168, 188, 89, 118, 163, 92, 95, 57, 188, 158, 226, + 181, 55, 96, 203, 23, 15, 69, 142, 38, 19, 106, 245, 75, 78, + 99, 167, 62, 234, 107, 39, 141, 74, 216, 226, 217, 210, 69, 95, + 255, 160, 57, 199, 62, 149, 66, 12, 75, 131, 32, 146, 177, 156, + 173, 56, 141, 237, 177, 20, 13, 204, 172, 29, 208, 235, 22, 188, + 10, 235, 147, 54, 255, 172, 240, 169, 72, 192, 186, 187, 24, 223, + 53, 77, 164, 4, 30, 197, 111, 72, 100, 142, 204, 75, 144, 81, + 82, 172, 250, 86, 47, 242, 223, 129, 45, 4, 215, 103, 199, 51, + 213, 154, 126, 244, 89, 218, 151, 161, 19, 136, 22, 89, 153, 76, + 137, 177, 177, 207, 171, 134, 225, 181, 182, 223, 214, 244, 99, 199, + 206, 93, 122, 5, 202, 217, 48, 99, 55, 143, 21, 42, 95, 234, + 219, 157, 77, 103, 154, 137, 48, 95, 114, 237, 200, 8, 149, 107, + 105, 248, 104, 237, 155, 167, 50, 96, 100, 253, 74, 171, 71, 123, + 95, 39, 169, 224, 10, 110, 63, 178, 225, 100, 205, 73, 28, 189, + 223, 238, 45, 208, 115, 146, 233, 230, 76, 179, 185, 96, 49, 15, + 86, 208, 200, 174, 197, 154, 245, 245, 225, 18, 145, 47, 15, 83, + 165, 13, 47, 237, 11, 80, 11, 225, 161, 224, 105, 75, 47, 17, + 192, 218, 203, 102, 184, 103, 5, 135, 168, 247, 187, 172, 175, 63, + 173, 205, 248, 204, 71, 246, 50, 230, 144, 125, 94, 59, 93, 235, + 244, 138, 74, 219, 231, 150, 198, 55, 74, 248, 51, 190, 108, 202, + 35, 253, 181, 55, 143, 34, 95, 201, 231, 86, 199, 235, 178, 161, + 98, 168, 14, 55, 33, 142, 132, 74, 180, 85, 132, 171, 75, 16, + 49, 125, 214, 28, 86, 36, 3, 167, 227, 250, 182, 149, 151, 123, + 46, 210, 172, 214, 201, 53, 55, 163, 174, 176, 116, 152, 159, 22, + 123, 116, 237, 82, 162, 209, 171, 245, 85, 23, 184, 166, 107, 210, + 187, 47, 170, 240, 77, 96, 205, 111, 221, 135, 253, 241, 158, 52, + 168, 15, 248, 239, 154, 115, 243, 119, 231, 171, 218, 193, 195, 228, + 107, 155, 222, 219, 96, 93, 35, 201, 177, 158, 255, 203, 167, 95, + 217, 64, 211, 153, 118, 69, 233, 176, 49, 12, 87, 222, 29, 214, + 7, 92, 35, 11, 94, 46, 76, 251, 210, 174, 30, 238, 70, 214, + 19, 99, 111, 36, 170, 148, 149, 198, 35, 140, 179, 220, 20, 246, + 168, 84, 234, 179, 250, 67, 134, 107, 89, 193, 113, 219, 0, 55, + 42, 39, 139, 216, 33, 205, 229, 141, 91, 73, 185, 217, 222, 29, + 105, 208, 205, 24, 227, 197, 61, 91, 10, 223, 163, 115, 242, 6, + 185, 222, 212, 112, 31, 88, 57, 182, 66, 139, 47, 233, 28, 199, + 211, 249, 199, 161, 40, 130, 161, 189, 243, 58, 183, 108, 151, 45, + 89, 91, 208, 128, 138, 108, 168, 118, 79, 220, 146, 218, 254, 80, + 56, 119, 241, 236, 92, 189, 11, 129, 135, 186, 42, 50, 205, 207, + 197, 140, 13, 28, 27, 56, 38, 53, 56, 133, 103, 195, 213, 195, + 82, 242, 212, 145, 98, 62, 154, 213, 77, 148, 113, 3, 220, 183, + 214, 229, 15, 143, 158, 134, 172, 154, 153, 227, 125, 4, 6, 132, + 162, 131, 202, 186, 175, 229, 218, 156, 53, 40, 22, 125, 161, 96, + 131, 143, 80, 72, 197, 18, 71, 65, 175, 144, 12, 22, 251, 183, + 236, 175, 153, 144, 96, 206, 168, 205, 96, 147, 117, 158, 209, 115, + 215, 84, 59, 172, 146, 163, 141, 86, 33, 5, 69, 183, 213, 218, + 72, 188, 233, 254, 68, 73, 9, 206, 93, 123, 58, 15, 254, 188, + 97, 191, 36, 81, 109, 24, 179, 158, 71, 132, 234, 224, 166, 148, + 141, 172, 163, 42, 190, 134, 212, 225, 250, 1, 169, 160, 217, 143, + 66, 244, 214, 119, 237, 20, 223, 71, 11, 221, 69, 199, 103, 88, + 119, 171, 135, 152, 45, 164, 231, 63, 158, 174, 190, 67, 43, 6, + 96, 52, 35, 32, 84, 111, 7, 92, 181, 87, 233, 215, 192, 110, + 34, 16, 224, 43, 51, 210, 121, 23, 78, 214, 158, 207, 40, 67, + 89, 65, 28, 238, 202, 98, 97, 252, 254, 197, 131, 90, 37, 123, + 129, 227, 116, 172, 107, 221, 140, 163, 205, 133, 144, 14, 133, 29, + 147, 13, 80, 147, 213, 39, 125, 126, 221, 96, 55, 237, 72, 214, + 210, 227, 0, 91, 95, 58, 62, 109, 255, 230, 195, 73, 14, 148, + 235, 226, 158, 170, 45, 111, 197, 171, 136, 155, 109, 85, 42, 222, + 219, 133, 89, 222, 232, 125, 156, 65, 133, 118, 136, 241, 137, 27, + 94, 121, 32, 59, 178, 4, 116, 50, 147, 215, 137, 151, 113, 128, + 122, 241, 205, 221, 66, 210, 91, 132, 54, 243, 78, 211, 93, 144, + 189, 118, 158, 213, 171, 235, 45, 2, 228, 188, 159, 173, 217, 197, + 180, 25, 30, 151, 49, 79, 224, 55, 121, 93, 106, 155, 22, 150, + 98, 48, 201, 59, 1, 34, 161, 155, 71, 143, 206, 5, 148, 88, + 214, 22, 193, 73, 24, 245, 26, 154, 149, 81, 181, 133, 174, 32, + 90, 208, 216, 195, 185, 75, 128, 128, 55, 220, 229, 150, 98, 43, + 219, 186, 34, 88, 159, 45, 189, 57, 189, 200, 136, 178, 152, 222, + 86, 190, 118, 143, 216, 104, 84, 95, 165, 207, 190, 10, 166, 48, + 29, 130, 174, 100, 113, 135, 97, 168, 58, 81, 148, 173, 69, 224, + 27, 144, 220, 147, 19, 110, 31, 38, 13, 65, 183, 52, 42, 162, + 32, 133, 176, 13, 52, 183, 207, 38, 71, 132, 150, 221, 84, 192, + 64, 11, 70, 24, 41, 75, 246, 44, 211, 207, 137, 12, 197, 108, + 160, 18, 223, 205, 253, 124, 6, 10, 31, 174, 42, 250, 16, 188, + 184, 43, 225, 207, 92, 151, 121, 224, 129, 201, 91, 151, 190, 247, + 10, 235, 153, 70, 194, 240, 144, 161, 211, 128, 59, 171, 35, 14, + 132, 239, 249, 203, 34, 160, 36, 36, 153, 215, 175, 71, 90, 41, + 26, 100, 44, 200, 50, 75, 237, 45, 150, 205, 41, 144, 183, 179, + 192, 117, 232, 201, 42, 161, 115, 197, 226, 181, 2, 230, 196, 27, + 47, 236, 88, 183, 129, 52, 73, 3, 242, 137, 120, 67, 244, 98, + 106, 165, 54, 139, 249, 221, 67, 234, 193, 197, 8, 39, 134, 63, + 70, 126, 124, 144, 138, 196, 147, 26, 55, 149, 72, 138, 248, 183, + 108, 179, 106, 108, 142, 68, 176, 109, 132, 124, 111, 123, 89, 151, + 3, 45, 224, 136, 133, 89, 129, 149, 206, 84, 191, 78, 21, 93, + 38, 46, 92, 5, 174, 247, 241, 118, 199, 249, 42, 183, 67, 120, + 217, 226, 196, 156, 241, 241, 77, 31, 167, 13, 90, 181, 246, 228, + 155, 41, 64, 159, 33, 28, 88, 166, 45, 202, 243, 197, 78, 63, + 108, 241, 132, 71, 74, 17, 80, 235, 68, 218, 192, 71, 84, 200, + 45, 12, 189, 66, 189, 197, 5, 231, 113, 16, 227, 122, 171, 49, + 21, 127, 39, 169, 63, 100, 1, 6, 205, 56, 21, 236, 74, 16, + 111, 142, 80, 166, 70, 115, 95, 185, 245, 153, 77, 25, 88, 4, + 86, 189, 215, 69, 118, 91, 70, 124, 252, 139, 22, 50, 120, 77, + 24, 164, 51, 28, 133, 156, 206, 103, 66, 217, 130, 223, 56, 176, + 215, 20, 221, 137, 225, 232, 189, 76, 19, 89, 128, 59, 94, 140, + 18, 175, 124, 21, 30, 208, 198, 111, 29, 209, 167, 147, 127, 243, + 82, 143, 167, 35, 182, 210, 68, 248, 179, 216, 200, 178, 74, 73, + 245, 13, 137, 179, 45, 228, 58, 211, 238, 99, 160, 52, 19, 54, + 63, 89, 65, 32, 91, 29, 91, 89, 241, 61, 158, 88, 230, 207, + 154, 199, 234, 161, 52, 206, 20, 45, 177, 177, 229, 0, 220, 216, + 64, 192, 219, 249, 69, 125, 99, 37, 209, 69, 208, 56, 205, 254, + 245, 137, 155, 18, 70, 135, 117, 187, 131, 56, 171, 237, 123, 84, + 238, 164, 184, 204, 36, 20, 9, 91, 86, 154, 164, 232, 242, 245, + 247, 55, 108, 25, 187, 162, 88, 95, 158, 248, 167, 186, 248, 252, + 226, 186, 181, 165, 117, 87, 201, 117, 172, 102, 198, 102, 238, 175, + 95, 220, 175, 103, 46, 20, 239, 128, 45, 107, 231, 92, 195, 189, + 60, 54, 129, 66, 10, 191, 206, 96, 105, 156, 245, 211, 115, 5, + 89, 125, 9, 26, 108, 59, 207, 253, 18, 239, 142, 68, 13, 130, + 132, 249, 123, 149, 108, 37, 250, 110, 163, 117, 82, 123, 142, 119, + 9, 248, 238, 245, 88, 181, 72, 219, 128, 1, 115, 63, 248, 111, + 166, 254, 189, 12, 191, 151, 106, 219, 111, 29, 214, 32, 108, 189, + 17, 139, 233, 237, 86, 191, 79, 150, 188, 40, 167, 9, 11, 39, + 210, 109, 190, 90, 203, 77, 150, 21, 113, 95, 87, 85, 240, 20, + 169, 234, 8, 241, 154, 178, 56, 181, 170, 3, 197, 194, 48, 24, + 166, 199, 23, 187, 253, 214, 181, 100, 206, 151, 243, 52, 86, 184, + 107, 217, 77, 52, 64, 130, 152, 97, 117, 188, 171, 188, 42, 92, + 138, 234, 46, 215, 164, 87, 209, 159, 123, 204, 161, 147, 143, 107, + 68, 51, 67, 29, 148, 132, 155, 150, 122, 188, 108, 188, 73, 49, + 141, 252, 174, 94, 204, 228, 57, 115, 223, 111, 50, 125, 243, 46, + 103, 48, 65, 217, 39, 40, 36, 71, 71, 95, 38, 41, 178, 225, + 117, 193, 75, 194, 223, 177, 123, 134, 234, 168, 216, 226, 185, 159, + 31, 145, 181, 2, 148, 249, 169, 99, 189, 196, 200, 117, 162, 55, + 113, 24, 237, 32, 134, 122, 138, 175, 245, 252, 175, 207, 12, 122, + 159, 141, 67, 58, 248, 116, 22, 57, 33, 41, 53, 189, 159, 186, + 141, 203, 198, 221, 144, 129, 205, 13, 122, 41, 233, 77, 197, 252, + 68, 14, 177, 2, 48, 113, 98, 58, 98, 28, 181, 155, 231, 234, + 96, 61, 217, 63, 177, 239, 17, 243, 133, 120, 114, 183, 130, 17, + 202, 85, 123, 73, 96, 14, 243, 120, 60, 152, 66, 188, 198, 185, + 19, 145, 82, 197, 37, 246, 103, 111, 108, 120, 12, 27, 107, 161, + 127, 186, 203, 36, 2, 26, 219, 206, 48, 119, 3, 89, 182, 191, + 55, 129, 247, 31, 220, 158, 166, 115, 170, 145, 136, 60, 60, 214, + 226, 110, 147, 0, 179, 144, 34, 247, 76, 77, 198, 138, 254, 4, + 142, 49, 225, 81, 113, 232, 49, 125, 117, 192, 39, 180, 109, 123, + 108, 218, 101, 25, 157, 16, 150, 130, 152, 112, 77, 230, 196, 182, + 62, 69, 17, 76, 84, 52, 73, 137, 116, 123, 9, 104, 108, 25, + 243, 77, 39, 44, 104, 172, 101, 3, 222, 162, 58, 254, 150, 192, + 185, 153, 182, 6, 182, 45, 73, 204, 65, 85, 105, 36, 204, 189, + 226, 168, 4, 206, 133, 122, 227, 61, 41, 173, 133, 125, 92, 104, + 58, 82, 156, 132, 146, 114, 68, 247, 142, 185, 247, 193, 251, 143, + 117, 81, 251, 45, 171, 117, 120, 146, 186, 76, 33, 132, 60, 194, + 134, 122, 69, 56, 246, 3, 195, 91, 160, 124, 239, 228, 103, 226, + 108, 186, 93, 123, 156, 46, 84, 218, 167, 181, 13, 145, 186, 39, + 100, 177, 134, 237, 248, 241, 125, 44, 40, 150, 59, 176, 230, 116, + 0, 245, 97, 49, 124, 232, 176, 226, 3, 25, 109, 20, 120, 87, + 45, 115, 19, 138, 170, 140, 58, 180, 82, 18, 25, 143, 51, 157, + 54, 123, 24, 109, 13, 167, 11, 156, 48, 134, 209, 54, 43, 120, + 168, 144, 218, 110, 173, 157, 214, 251, 183, 65, 33, 248, 219, 228, + 73, 241, 108, 130, 46, 92, 248, 70, 122, 224, 133, 111, 104, 159, + 217, 62, 129, 22, 163, 220, 91, 177, 78, 84, 51, 182, 51, 84, + 164, 191, 76, 131, 49, 219, 5, 57, 193, 188, 84, 223, 177, 193, + 131, 5, 212, 112, 189, 99, 197, 55, 8, 146, 157, 22, 171, 127, + 80, 70, 35, 241, 14, 67, 28, 215, 254, 183, 222, 195, 255, 250, + 254, 126, 133, 230, 1, 29, 62, 126, 167, 172, 23, 208, 140, 200, + 123, 33, 77, 20, 9, 15, 175, 137, 116, 105, 150, 66, 155, 202, + 240, 22, 131, 59, 41, 89, 196, 74, 218, 225, 188, 90, 249, 197, + 190, 185, 248, 247, 101, 221, 193, 42, 77, 208, 139, 62, 72, 238, + 105, 29, 143, 129, 142, 155, 152, 255, 118, 240, 174, 21, 1, 225, + 238, 207, 106, 142, 73, 222, 250, 129, 13, 9, 233, 156, 17, 36, + 186, 221, 63, 57, 2, 94, 4, 162, 30, 153, 171, 19, 128, 173, + 145, 214, 236, 71, 50, 167, 123, 220, 193, 51, 115, 135, 90, 165, + 98, 89, 117, 195, 101, 212, 233, 233, 216, 90, 213, 139, 189, 189, + 102, 228, 253, 57, 181, 150, 12, 212, 159, 139, 48, 195, 185, 152, + 104, 68, 61, 98, 1, 127, 223, 77, 68, 76, 74, 212, 249, 73, + 135, 52, 4, 50, 175, 175, 189, 219, 58, 191, 117, 114, 122, 24, + 33, 232, 19, 219, 123, 118, 186, 168, 102, 29, 90, 245, 177, 232, + 188, 130, 136, 10, 164, 112, 228, 120, 40, 38, 187, 107, 131, 151, + 210, 2, 119, 45, 202, 21, 2, 87, 77, 239, 154, 253, 148, 146, + 175, 214, 46, 66, 151, 8, 5, 202, 33, 198, 64, 183, 242, 226, + 182, 92, 48, 131, 55, 225, 141, 35, 243, 194, 70, 71, 160, 73, + 159, 119, 15, 76, 20, 222, 160, 94, 224, 66, 54, 213, 20, 74, + 3, 254, 47, 218, 25, 255, 132, 215, 239, 114, 227, 132, 201, 240, + 149, 102, 25, 61, 149, 26, 160, 152, 227, 56, 205, 22, 9, 138, + 170, 162, 172, 178, 184, 85, 48, 220, 68, 82, 87, 106, 103, 99, + 206, 254, 150, 206, 185, 104, 174, 233, 253, 60, 217, 79, 29, 254, + 211, 21, 176, 141, 37, 150, 245, 86, 226, 139, 174, 124, 205, 138, + 155, 147, 152, 175, 2, 16, 235, 149, 49, 210, 171, 26, 187, 32, + 85, 201, 154, 30, 211, 242, 109, 130, 30, 100, 120, 174, 87, 31, + 87, 1, 80, 80, 97, 87, 19, 198, 103, 12, 143, 26, 241, 251, + 72, 79, 73, 116, 238, 167, 242, 33, 103, 5, 92, 83, 4, 29, + 203, 236, 221, 94, 130, 240, 169, 61, 205, 126, 133, 140, 150, 157, + 51, 105, 67, 185, 29, 159, 4, 130, 252, 178, 73, 17, 67, 139, + 17, 240, 44, 129, 123, 197, 210, 158, 58, 220, 248, 233, 10, 86, + 49, 149, 74, 160, 203, 147, 224, 187, 14, 47, 149, 90, 150, 244, + 23, 162, 127, 110, 181, 106, 90, 243, 52, 133, 139, 34, 127, 228, + 92, 69, 251, 48, 230, 177, 121, 60, 87, 52, 65, 65, 240, 59, + 242, 156, 35, 225, 49, 86, 61, 97, 147, 117, 227, 157, 108, 207, + 44, 179, 18, 167, 6, 42, 24, 56, 181, 99, 24, 88, 129, 88, + 167, 174, 57, 145, 146, 245, 39, 170, 86, 87, 42, 82, 39, 151, + 16, 94, 254, 129, 206, 21, 214, 208, 24, 114, 8, 97, 239, 22, + 238, 74, 122, 164, 76, 251, 46, 10, 17, 152, 200, 63, 44, 215, + 78, 210, 21, 1, 12, 136, 21, 255, 167, 50, 53, 138, 177, 45, + 198, 97, 22, 247, 209, 254, 227, 236, 214, 90, 202, 13, 209, 163, + 13, 219, 129, 198, 43, 15, 225, 140, 118, 240, 133, 242, 211, 93, + 249, 125, 68, 246, 130, 84, 184, 142, 160, 202, 59, 207, 29, 195, + 38, 108, 169, 248, 189, 80, 151, 174, 140, 205, 147, 110, 44, 143, + 4, 97, 142, 191, 122, 40, 209, 14, 87, 132, 196, 8, 14, 45, + 196, 152, 139, 161, 20, 52, 254, 44, 15, 239, 95, 17, 130, 123, + 189, 97, 248, 61, 214, 96, 185, 162, 81, 10, 32, 173, 142, 133, + 123, 166, 156, 218, 82, 8, 63, 61, 52, 11, 211, 173, 207, 29, + 139, 177, 37, 150, 9, 34, 124, 211, 26, 213, 237, 70, 43, 28, + 191, 83, 229, 22, 156, 50, 3, 27, 239, 34, 43, 129, 80, 81, + 22, 80, 40, 143, 179, 105, 213, 253, 209, 158, 179, 232, 175, 57, + 163, 38, 239, 241, 216, 69, 226, 212, 77, 16, 237, 242, 206, 72, + 126, 177, 185, 68, 68, 131, 204, 129, 100, 30, 169, 214, 192, 124, + 210, 231, 188, 136, 204, 22, 67, 113, 159, 154, 56, 112, 141, 220, + 215, 91, 157, 26, 19, 219, 51, 236, 171, 230, 170, 150, 19, 226, + 12, 248, 35, 84, 254, 107, 246, 56, 249, 84, 237, 95, 68, 198, + 145, 79, 117, 99, 16, 174, 10, 171, 155, 30, 167, 202, 54, 186, + 3, 108, 163, 126, 159, 103, 231, 123, 185, 72, 106, 34, 218, 221, + 40, 201, 164, 78, 240, 161, 102, 156, 155, 129, 180, 53, 1, 28, + 125, 91, 246, 140, 188, 201, 2, 75, 16, 240, 222, 82, 33, 81, + 20, 15, 113, 201, 214, 20, 15, 104, 19, 160, 146, 89, 82, 180, + 215, 141, 97, 167, 43, 215, 105, 5, 232, 15, 24, 191, 117, 231, + 27, 115, 121, 51, 253, 197, 40, 175, 206, 128, 115, 131, 145, 11, + 243, 154, 119, 154, 73, 103, 246, 45, 113, 45, 135, 22, 134, 155, + 74, 223, 226, 203, 104, 10, 89, 93, 127, 182, 108, 118, 110, 41, + 85, 197, 147, 9, 107, 66, 202, 165, 35, 106, 163, 202, 16, 73, + 132, 171, 153, 153, 220, 150, 189, 223, 56, 222, 92, 111, 241, 252, + 247, 77, 202, 222, 2, 242, 94, 35, 225, 88, 64, 173, 10, 215, + 208, 74, 106, 210, 208, 49, 165, 111, 146, 54, 166, 226, 197, 159, + 249, 140, 238, 213, 171, 233, 198, 149, 128, 154, 241, 34, 34, 253, + 62, 122, 35, 49, 34, 164, 214, 63, 207, 195, 5, 162, 179, 98, + 237, 214, 204, 246, 191, 94, 146, 87, 217, 86, 116, 164, 113, 238, + 247, 130, 9, 139, 220, 200, 94, 77, 161, 18, 137, 222, 28, 135, + 227, 36, 170, 103, 130, 199, 204, 24, 22, 51, 42, 227, 204, 118, + 73, 243, 95, 67, 249, 232, 229, 79, 209, 225, 96, 52, 5, 174, + 172, 67, 15, 23, 207, 212, 182, 230, 6, 249, 15, 240, 151, 25, + 82, 37, 15, 54, 182, 209, 114, 159, 143, 137, 97, 190, 95, 95, + 182, 177, 69, 45, 32, 132, 108, 48, 25, 186, 83, 115, 34, 124, + 232, 214, 45, 248, 161, 150, 206, 129, 77, 93, 181, 253, 47, 33, + 194, 41, 60, 115, 43, 120, 63, 84, 147, 124, 65, 58, 184, 50, + 47, 76, 198, 248, 58, 175, 100, 196, 39, 97, 31, 106, 147, 66, + 198, 44, 214, 116, 177, 8, 255, 235, 166, 126, 239, 143, 243, 11, + 141, 11, 0, 26, 124, 189, 164, 16, 164, 170, 112, 87, 148, 242, + 246, 238, 116, 134, 26, 153, 201, 185, 242, 2, 51, 87, 0, 166, + 105, 229, 68, 129, 33, 21, 152, 142, 132, 200, 248, 222, 136, 194, + 222, 204, 67, 193, 138, 103, 215, 139, 26, 110, 131, 157, 129, 226, + 45, 252, 204, 131, 63, 77, 36, 123, 44, 4, 119, 163, 218, 128, + 195, 203, 155, 84, 96, 56, 172, 201, 173, 251, 243, 50, 232, 119, + 174, 57, 181, 125, 220, 20, 90, 221, 245, 171, 124, 21, 14, 153, + 180, 49, 201, 168, 61, 152, 53, 56, 39, 181, 13, 49, 33, 148, + 200, 6, 3, 39, 122, 60, 48, 49, 102, 83, 136, 195, 222, 224, + 80, 46, 142, 167, 254, 127, 163, 103, 134, 110, 52, 123, 174, 81, + 197, 79, 165, 128, 86, 207, 45, 57, 99, 154, 255, 125, 189, 241, + 73, 103, 16, 226, 89, 93, 141, 179, 54, 35, 240, 196, 111, 121, + 163, 185, 209, 226, 49, 37, 223, 145, 206, 227, 71, 132, 119, 37, + 36, 141, 207, 103, 51, 215, 238, 35, 115, 152, 188, 107, 216, 234, + 213, 87, 232, 36, 253, 110, 135, 125, 189, 140, 124, 209, 44, 204, + 132, 232, 221, 30, 225, 142, 211, 236, 250, 163, 42, 63, 178, 200, + 129, 221, 220, 166, 244, 234, 106, 149, 82, 71, 203, 206, 28, 26, + 76, 123, 13, 90, 126, 174, 175, 212, 226, 205, 213, 84, 56, 202, + 170, 86, 0, 149, 0, 37, 221, 204, 186, 190, 227, 118, 170, 120, + 182, 192, 214, 7, 213, 253, 13, 37, 131, 95, 17, 99, 228, 76, + 147, 221, 207, 17, 226, 55, 223, 78, 192, 23, 101, 126, 138, 16, + 95, 177, 22, 188, 70, 140, 26, 21, 147, 163, 158, 118, 157, 187, + 238, 111, 108, 236, 136, 71, 34, 25, 70, 205, 71, 89, 156, 127, + 95, 69, 138, 143, 116, 241, 225, 127, 124, 150, 127, 122, 105, 28, + 221, 29, 236, 242, 64, 244, 224, 14, 196, 142, 119, 40, 146, 38, + 16, 179, 56, 110, 160, 243, 61, 54, 34, 69, 58, 122, 114, 43, + 217, 158, 234, 248, 232, 195, 128, 81, 131, 119, 202, 230, 225, 41, + 58, 214, 124, 193, 93, 86, 92, 12, 47, 208, 121, 77, 52, 37, + 253, 104, 99, 59, 57, 184, 1, 226, 203, 49, 199, 252, 35, 101, + 185, 91, 230, 157, 128, 232, 84, 244, 154, 53, 243, 218, 151, 17, + 69, 220, 95, 110, 186, 10, 113, 201, 97, 110, 47, 22, 45, 182, + 39, 192, 21, 98, 16, 136, 83, 3, 215, 221, 122, 145, 233, 100, + 132, 25, 170, 35, 27, 5, 96, 56, 189, 37, 62, 79, 142, 195, + 119, 242, 115, 177, 44, 219, 123, 134, 144, 245, 64, 97, 194, 138, + 239, 154, 164, 45, 130, 36, 90, 6, 30, 138, 188, 94, 254, 141, + 43, 219, 162, 43, 69, 58, 7, 19, 74, 160, 12, 176, 21, 156, + 81, 172, 233, 51, 100, 146, 61, 234, 223, 6, 24, 225, 93, 155, + 246, 107, 20, 239, 142, 149, 107, 16, 56, 199, 232, 123, 97, 184, + 193, 37, 197, 27, 31, 64, 196, 88, 228, 3, 117, 12, 71, 145, + 169, 45, 202, 180, 2, 120, 59, 68, 9, 122, 113, 81, 4, 223, + 236, 174, 52, 76, 50, 31, 174, 137, 186, 109, 193, 196, 114, 62, + 167, 84, 127, 93, 174, 158, 138, 141, 200, 162, 193, 56, 176, 36, + 39, 24, 36, 54, 105, 33, 102, 83, 158, 153, 64, 114, 119, 227, + 111, 23, 146, 234, 29, 64, 120, 182, 179, 140, 108, 43, 92, 109, + 169, 53, 231, 17, 112, 75, 134, 203, 53, 40, 42, 85, 213, 36, + 104, 197, 231, 3, 183, 127, 251, 104, 73, 251, 149, 193, 65, 198, + 144, 28, 138, 153, 250, 23, 50, 81, 170, 25, 130, 152, 105, 115, + 22, 241, 163, 125, 64, 111, 167, 85, 59, 254, 21, 198, 62, 132, + 20, 104, 14, 10, 88, 112, 69, 137, 197, 210, 200, 230, 156, 14, + 60, 101, 115, 182, 254, 89, 224, 180, 125, 30, 185, 54, 80, 97, + 135, 117, 77, 113, 196, 52, 14, 45, 212, 119, 99, 13, 110, 98, + 117, 35, 47, 14, 248, 83, 126, 41, 218, 79, 200, 52, 26, 194, + 174, 21, 161, 2, 94, 98, 184, 188, 94, 46, 73, 98, 20, 81, + 186, 129, 191, 37, 59, 22, 154, 90, 29, 230, 169, 107, 234, 34, + 10, 54, 88, 133, 129, 7, 113, 94, 81, 251, 249, 139, 53, 38, + 61, 221, 7, 193, 254, 6, 208, 115, 3, 26, 32, 190, 145, 61, + 211, 165, 222, 56, 135, 72, 221, 93, 4, 78, 61, 2, 93, 145, + 4, 163, 219, 52, 18, 166, 29, 211, 192, 57, 99, 14, 244, 177, + 24, 6, 26, 98, 220, 182, 151, 85, 250, 92, 78, 72, 97, 137, + 157, 100, 179, 48, 81, 179, 50, 13, 220, 171, 190, 219, 153, 156, + 254, 198, 60, 61, 103, 9, 169, 156, 100, 225, 95, 50, 80, 69, + 255, 251, 112, 49, 10, 224, 70, 22, 193, 73, 75, 45, 120, 251, + 116, 253, 77, 188, 164, 120, 50, 152, 219, 171, 4, 163, 214, 71, + 253, 86, 71, 75, 103, 211, 165, 76, 222, 81, 102, 143, 120, 148, + 61, 56, 95, 230, 206, 199, 234, 202, 31, 14, 89, 128, 63, 213, + 156, 75, 75, 53, 81, 5, 191, 202, 78, 212, 160, 126, 246, 134, + 73, 233, 197, 136, 6, 92, 201, 212, 91, 123, 250, 236, 199, 53, + 66, 254, 166, 125, 109, 159, 15, 147, 227, 175, 30, 57, 191, 188, + 6, 0, 222, 6, 81, 221, 250, 167, 51, 25, 55, 115, 82, 205, + 107, 176, 149, 198, 74, 187, 102, 42, 208, 202, 243, 100, 219, 77, + 233, 46, 235, 78, 214, 210, 241, 74, 184, 221, 132, 235, 89, 42, + 249, 108, 249, 42, 112, 92, 8, 77, 177, 0, 232, 73, 98, 204, + 207, 220, 158, 175, 155, 199, 196, 226, 206, 66, 78, 64, 191, 166, + 0, 223, 248, 15, 20, 44, 48, 252, 42, 87, 125, 185, 98, 39, + 96, 64, 4, 96, 66, 59, 125, 16, 74, 225, 0, 230, 39, 207, + 137, 183, 24, 68, 133, 68, 84, 47, 133, 164, 230, 188, 167, 132, + 118, 140, 208, 106, 125, 90, 203, 83, 126, 112, 179, 194, 211, 97, + 241, 42, 147, 130, 33, 240, 223, 118, 54, 150, 128, 106, 29, 101, + 155, 164, 73, 77, 235, 243, 126, 233, 143, 250, 155, 80, 185, 122, + 128, 132, 50, 150, 164, 189, 194, 126, 86, 57, 235, 111, 194, 56, + 89, 254, 118, 26, 184, 179, 214, 234, 181, 147, 121, 79, 3, 8, + 208, 79, 250, 193, 247, 193, 185, 137, 3, 120, 35, 159, 110, 246, + 248, 245, 213, 205, 151, 48, 197, 92, 126, 58, 54, 14, 203, 180, + 14, 223, 146, 131, 177, 121, 255, 188, 231, 168, 234, 237, 244, 178, + 27, 192, 75, 105, 232, 183, 49, 50, 168, 89, 195, 187, 57, 137, + 129, 219, 103, 119, 36, 181, 78, 37, 61, 142, 89, 225, 236, 27, + 46, 116, 18, 213, 179, 23, 4, 211, 223, 228, 142, 237, 110, 245, + 30, 121, 56, 191, 250, 178, 144, 198, 25, 208, 161, 93, 206, 117, + 20, 228, 117, 145, 147, 50, 44, 197, 28, 234, 173, 216, 91, 178, + 232, 207, 173, 216, 24, 42, 21, 194, 255, 230, 131, 34, 231, 170, + 174, 190, 193, 64, 76, 223, 120, 107, 246, 234, 122, 1, 235, 191, + 206, 50, 35, 61, 49, 142, 217, 51, 189, 213, 91, 233, 86, 12, + 174, 235, 190, 21, 228, 129, 30, 114, 73, 76, 127, 57, 163, 199, + 241, 8, 109, 126, 136, 146, 210, 131, 173, 203, 85, 8, 221, 5, + 219, 43, 40, 132, 205, 7, 153, 67, 58, 0, 226, 28, 114, 155, + 68, 188, 24, 135, 3, 35, 88, 185, 27, 165, 232, 248, 165, 54, + 184, 93, 49, 61, 65, 23, 88, 137, 79, 248, 120, 206, 249, 15, + 130, 140, 196, 161, 47, 44, 173, 38, 148, 195, 94, 218, 172, 243, + 35, 93, 70, 112, 63, 39, 224, 77, 19, 227, 28, 134, 205, 165, + 46, 100, 47, 77, 26, 252, 19, 186, 111, 202, 59, 207, 226, 133, + 63, 24, 39, 38, 45, 127, 222, 132, 66, 147, 35, 235, 223, 226, + 141, 242, 107, 56, 72, 174, 186, 38, 33, 121, 222, 126, 102, 42, + 75, 6, 119, 243, 198, 27, 51, 87, 235, 143, 95, 84, 29, 87, + 0, 11, 96, 107, 57, 96, 124, 101, 180, 40, 96, 206, 108, 51, + 40, 6, 205, 220, 151, 253, 52, 104, 189, 190, 116, 46, 86, 62, + 146, 36, 65, 215, 66, 9, 61, 237, 163, 152, 174, 233, 160, 216, + 167, 152, 14, 137, 196, 32, 44, 100, 118, 245, 236, 19, 241, 121, + 93, 144, 107, 241, 96, 125, 53, 254, 210, 141, 48, 188, 205, 23, + 66, 18, 227, 98, 163, 57, 61, 135, 238, 212, 148, 77, 223, 111, + 64, 58, 233, 30, 219, 31, 247, 228, 19, 137, 243, 214, 96, 36, + 16, 88, 53, 45, 241, 84, 126, 77, 142, 64, 25, 149, 70, 126, + 188, 152, 232, 88, 65, 211, 97, 104, 149, 92, 208, 82, 124, 20, + 94, 252, 109, 168, 4, 146, 41, 69, 5, 101, 136, 74, 250, 243, + 200, 132, 82, 98, 76, 215, 112, 185, 106, 193, 6, 12, 171, 166, + 96, 97, 253, 223, 20, 4, 56, 31, 206, 128, 48, 113, 238, 115, + 11, 59, 158, 44, 90, 239, 120, 115, 86, 65, 228, 55, 181, 83, + 163, 160, 210, 62, 194, 185, 17, 155, 253, 224, 174, 161, 101, 83, + 59, 144, 160, 108, 146, 165, 18, 251, 27, 63, 78, 180, 133, 121, + 147, 108, 46, 253, 224, 16, 204, 46, 29, 248, 175, 147, 200, 222, + 216, 154, 184, 137, 97, 162, 72, 205, 14, 124, 220, 143, 135, 253, + 14, 189, 27, 87, 125, 71, 130, 8, 104, 136, 101, 248, 93, 37, + 82, 21, 6, 211, 51, 185, 163, 219, 101, 190, 214, 6, 51, 203, + 55, 252, 42, 141, 61, 101, 74, 215, 6, 206, 238, 228, 9, 238, + 38, 155, 104, 183, 134, 165, 30, 4, 154, 250, 52, 237, 163, 32, + 142, 91, 233, 57, 2, 30, 150, 51, 91, 82, 180, 110, 58, 57, + 113, 198, 73, 188, 41, 93, 97, 223, 80, 228, 121, 219, 245, 64, + 138, 190, 144, 166, 107, 31, 215, 89, 161, 78, 147, 84, 238, 68, + 53, 47, 171, 204, 24, 207, 29, 220, 182, 101, 222, 93, 5, 119, + 193, 222, 221, 210, 201, 51, 226, 228, 151, 177, 174, 114, 127, 129, + 241, 4, 228, 0, 1, 147, 105, 122, 179, 84, 0, 152, 87, 147, + 27, 115, 44, 250, 7, 245, 249, 21, 234, 219, 215, 53, 113, 111, + 151, 29, 159, 116, 5, 61, 238, 164, 107, 176, 52, 111, 254, 53, + 207, 132, 30, 28, 33, 58, 90, 118, 133, 142, 50, 51, 10, 8, + 38, 199, 69, 196, 173, 50, 59, 249, 167, 104, 119, 119, 86, 54, + 198, 3, 245, 72, 178, 37, 7, 215, 213, 37, 240, 26, 167, 101, + 92, 163, 182, 55, 28, 100, 208, 181, 76, 58, 69, 148, 156, 6, + 107, 153, 89, 176, 37, 98, 167, 193, 160, 111, 2, 193, 170, 34, + 43, 167, 60, 162, 188, 68, 148, 72, 136, 33, 80, 61, 225, 210, + 28, 182, 88, 159, 194, 159, 79, 1, 49, 146, 75, 218, 232, 157, + 47, 178, 236, 10, 146, 166, 211, 128, 213, 158, 171, 67, 48, 83, + 117, 251, 180, 61, 54, 213, 16, 96, 207, 121, 66, 225, 40, 13, + 98, 128, 71, 150, 186, 153, 96, 189, 135, 228, 104, 92, 74, 35, + 135, 11, 76, 121, 57, 34, 169, 184, 97, 236, 53, 60, 43, 89, + 23, 21, 202, 42, 27, 179, 113, 128, 168, 62, 133, 236, 78, 195, + 47, 215, 48, 161, 170, 142, 71, 249, 99, 66, 153, 226, 90, 158, + 122, 162, 105, 127, 112, 202, 239, 117, 45, 79, 101, 117, 149, 15, + 223, 9, 136, 156, 149, 191, 87, 184, 54, 167, 14, 49, 32, 194, + 49, 3, 210, 44, 190, 91, 6, 91, 202, 166, 68, 205, 92, 167, + 46, 101, 46, 195, 207, 182, 51, 29, 46, 249, 220, 140, 102, 137, + 214, 239, 79, 76, 251, 67, 219, 19, 104, 212, 21, 196, 213, 33, + 185, 216, 50, 227, 167, 214, 135, 127, 184, 60, 116, 11, 245, 20, + 92, 134, 166, 235, 60, 16, 102, 122, 105, 106, 28, 88, 224, 57, + 191, 150, 153, 97, 173, 214, 198, 184, 23, 160, 140, 164, 7, 198, + 117, 194, 147, 219, 147, 64, 26, 240, 255, 124, 150, 225, 102, 36, + 236, 1, 227, 188, 60, 55, 36, 124, 149, 200, 234, 194, 252, 245, + 61, 163, 184, 197, 163, 17, 86, 215, 30, 67, 16, 250, 57, 227, + 70, 207, 140, 61, 198, 193, 27, 177, 245, 132, 199, 134, 168, 175, + 45, 148, 184, 146, 32, 45, 215, 190, 70, 74, 152, 24, 255, 146, + 139, 174, 219, 39, 7, 211, 130, 125, 212, 39, 54, 31, 24, 122, + 50, 251, 187, 242, 17, 217, 95, 28, 242, 63, 206, 164, 228, 235, + 43, 0, 126, 188, 220, 246, 160, 193, 79, 185, 46, 230, 225, 238, + 166, 159, 195, 169, 30, 87, 188, 10, 233, 115, 46, 128, 186, 168, + 225, 248, 8, 206, 110, 211, 71, 37, 48, 11, 190, 234, 138, 43, + 45, 119, 54, 200, 19, 189, 43, 52, 49, 86, 133, 233, 16, 153, + 240, 150, 234, 101, 1, 35, 46, 151, 162, 131, 169, 226, 231, 144, + 6, 215, 219, 42, 126, 254, 14, 205, 23, 0, 255, 16, 155, 107, + 52, 139, 222, 123, 251, 48, 57, 12, 25, 86, 133, 146, 253, 230, + 223, 216, 153, 43, 81, 160, 132, 109, 239, 124, 11, 15, 135, 217, + 16, 72, 9, 113, 99, 80, 196, 230, 118, 158, 140, 158, 147, 226, + 57, 220, 46, 30, 41, 78, 46, 125, 132, 185, 28, 223, 13, 15, + 52, 97, 105, 168, 188, 69, 247, 175, 72, 241, 232, 65, 66, 159, + 192, 89, 90, 96, 201, 7, 160, 87, 9, 238, 156, 59, 19, 228, + 192, 92, 145, 125, 7, 76, 127, 78, 0, 114, 123, 6, 223, 4, + 254, 204, 100, 126, 17, 38, 180, 201, 164, 184, 178, 252, 65, 207, + 234, 62, 21, 186, 145, 139, 192, 123, 179, 174, 115, 239, 219, 134, + 227, 201, 109, 113, 6, 92, 208, 58, 182, 105, 142, 246, 10, 34, + 199, 25, 51, 97, 132, 191, 193, 196, 234, 52, 76, 224, 208, 158, + 97, 53, 147, 132, 30, 127, 1, 211, 217, 69, 100, 62, 103, 103, + 18, 192, 217, 172, 37, 151, 185, 16, 145, 52, 84, 93, 240, 87, + 226, 95, 153, 119, 106, 35, 41, 69, 139, 13, 224, 183, 162, 59, + 205, 35, 219, 144, 165, 106, 71, 8, 147, 102, 109, 239, 220, 193, + 3, 244, 117, 31, 70, 234, 97, 2, 22, 169, 6, 245, 52, 49, + 58, 245, 111, 200, 87, 11, 177, 78, 138, 230, 81, 204, 146, 20, + 186, 12, 181, 36, 142, 7, 28, 64, 236, 210, 242, 174, 17, 118, + 47, 132, 238, 18, 240, 7, 215, 2, 137, 85, 166, 187, 233, 242, + 141, 25, 65, 133, 141, 180, 197, 65, 77, 238, 148, 239, 47, 121, + 237, 131, 78, 226, 8, 12, 82, 30, 9, 53, 253, 231, 196, 253, + 196, 43, 47, 72, 38, 194, 70, 12, 15, 227, 6, 35, 106, 230, + 181, 229, 139, 215, 105, 81, 127, 13, 160, 66, 54, 14, 213, 200, + 33, 96, 235, 33, 139, 50, 138, 253, 90, 224, 37, 7, 216, 28, + 216, 162, 77, 152, 164, 193, 68, 104, 252, 72, 158, 142, 254, 138, + 1, 139, 72, 193, 113, 236, 144, 62, 140, 237, 221, 167, 3, 107, + 16, 244, 29, 101, 51, 74, 246, 6, 7, 50, 151, 229, 187, 14, + 105, 95, 66, 60, 193, 221, 76, 115, 78, 147, 19, 54, 19, 98, + 101, 38, 55, 219, 18, 173, 106, 142, 180, 105, 244, 168, 16, 68, + 12, 126, 99, 174, 191, 59, 33, 187, 239, 177, 150, 102, 233, 31, + 143, 182, 245, 152, 10, 224, 118, 146, 58, 51, 153, 94, 133, 1, + 0, 228, 84, 19, 24, 92, 5, 111, 151, 183, 146, 51, 7, 219, + 164, 212, 209, 139, 130, 70, 52, 227, 10, 44, 89, 155, 140, 76, + 1, 66, 98, 251, 115, 124, 239, 39, 230, 2, 198, 82, 129, 132, + 70, 243, 121, 234, 238, 124, 53, 246, 119, 77, 105, 141, 123, 55, + 214, 88, 128, 45, 145, 147, 24, 70, 130, 206, 174, 148, 46, 154, + 198, 113, 238, 183, 6, 235, 41, 27, 39, 153, 52, 26, 94, 238, + 81, 151, 161, 80, 41, 68, 9, 201, 140, 23, 139, 71, 177, 154, + 98, 41, 139, 33, 138, 27, 131, 244, 78, 180, 38, 41, 93, 157, + 87, 40, 66, 114, 213, 59, 175, 48, 228, 217, 85, 138, 54, 43, + 162, 150, 135, 240, 131, 19, 64, 187, 190, 6, 55, 1, 63, 103, + 237, 225, 167, 68, 65, 70, 22, 201, 118, 155, 157, 27, 65, 18, + 119, 19, 125, 104, 126, 98, 195, 113, 138, 8, 184, 146, 72, 21, + 47, 86, 221, 242, 78, 244, 219, 124, 178, 167, 141, 161, 86, 194, + 194, 2, 142, 249, 226, 93, 74, 207, 178, 62, 14, 14, 20, 139, + 214, 45, 146, 233, 244, 55, 41, 182, 176, 113, 29, 155, 194, 115, + 131, 224, 30, 96, 97, 39, 73, 213, 100, 162, 66, 141, 5, 119, + 48, 137, 12, 16, 9, 175, 200, 71, 33, 86, 109, 62, 216, 53, + 61, 104, 245, 15, 184, 208, 118, 103, 27, 227, 152, 38, 152, 236, + 76, 215, 138, 209, 90, 205, 84, 93, 174, 228, 85, 29, 54, 199, + 162, 6, 51, 213, 67, 1, 128, 16, 196, 6, 86, 25, 0, 152, + 79, 253, 217, 146, 162, 133, 178, 1, 238, 235, 208, 86, 57, 0, + 44, 74, 34, 23, 52, 116, 115, 16, 200, 133, 97, 34, 80, 85, + 146, 181, 34, 185, 156, 137, 53, 108, 213, 51, 227, 131, 142, 49, + 34, 218, 188, 64, 64, 13, 11, 38, 132, 96, 131, 65, 217, 90, + 168, 109, 205, 124, 43, 230, 227, 18, 36, 239, 241, 17, 245, 121, + 13, 187, 238, 38, 28, 138, 161, 151, 157, 43, 77, 186, 160, 228, + 174, 71, 75, 71, 225, 193, 227, 100, 159, 237, 9, 126, 137, 4, + 135, 235, 195, 107, 196, 209, 104, 78, 115, 212, 34, 49, 24, 232, + 237, 175, 64, 117, 183, 219, 40, 123, 64, 12, 18, 249, 115, 93, + 170, 254, 0, 177, 234, 250, 67, 152, 149, 116, 59, 67, 73, 146, + 125, 118, 180, 58, 31, 46, 81, 57, 125, 246, 62, 16, 236, 45, + 213, 18, 214, 16, 98, 10, 187, 107, 155, 184, 251, 103, 190, 237, + 248, 36, 196, 232, 202, 196, 180, 199, 92, 124, 224, 45, 101, 41, + 221, 229, 181, 95, 171, 228, 90, 182, 193, 9, 189, 94, 207, 1, + 220, 129, 208, 32, 100, 51, 11, 203, 187, 206, 10, 25, 74, 129, + 201, 35, 228, 22, 10, 168, 239, 218, 50, 22, 13, 224, 143, 138, + 235, 253, 229, 246, 9, 235, 3, 77, 246, 228, 103, 136, 172, 80, + 11, 115, 96, 233, 51, 90, 62, 184, 188, 194, 237, 89, 135, 135, + 71, 228, 188, 85, 51, 78, 231, 252, 21, 177, 63, 211, 199, 45, + 219, 122, 132, 245, 6, 36, 92, 139, 113, 85, 33, 25, 158, 180, + 175, 63, 225, 95, 179, 58, 172, 252, 207, 232, 21, 151, 70, 145, + 111, 18, 167, 27, 78, 142, 137, 250, 146, 110, 201, 206, 151, 119, + 6, 27, 244, 90, 146, 190, 138, 177, 16, 147, 208, 154, 125, 9, + 244, 198, 67, 80, 180, 39, 218, 49, 28, 219, 31, 62, 201, 248, + 135, 86, 139, 244, 98, 55, 1, 197, 208, 120, 195, 38, 143, 185, + 102, 109, 201, 157, 114, 101, 130, 178, 90, 188, 89, 37, 58, 186, + 230, 53, 81, 209, 187, 224, 66, 125, 76, 122, 42, 184, 89, 119, + 51, 9, 93, 19, 42, 237, 140, 34, 119, 128, 31, 254, 91, 58, + 8, 17, 155, 229, 225, 33, 254, 109, 190, 155, 160, 204, 161, 63, + 92, 148, 27, 197, 56, 189, 44, 143, 192, 224, 203, 214, 215, 33, + 183, 22, 106, 175, 178, 125, 154, 14, 91, 128, 76, 108, 135, 204, + 71, 78, 170, 155, 20, 64, 142, 8, 155, 25, 75, 11, 82, 234, + 75, 254, 112, 24, 138, 163, 254, 111, 2, 11, 80, 202, 211, 164, + 27, 192, 254, 83, 24, 36, 78, 99, 184, 211, 48, 102, 78, 160, + 42, 109, 124, 198, 251, 191, 39, 107, 116, 187, 36, 3, 121, 158, + 94, 185, 27, 209, 129, 61, 248, 253, 235, 185, 209, 204, 209, 102, + 172, 24, 0, 66, 46, 44, 194, 138, 246, 77, 198, 197, 37, 146, + 116, 222, 202, 18, 110, 54, 249, 63, 154, 171, 138, 86, 87, 28, + 168, 183, 42, 70, 255, 0, 245, 97, 4, 83, 67, 100, 212, 178, + 47, 199, 13, 190, 250, 177, 107, 213, 188, 36, 42, 163, 235, 126, + 167, 10, 19, 139, 159, 181, 116, 105, 250, 165, 60, 203, 152, 66, + 18, 15, 241, 228, 169, 36, 48, 104, 192, 34, 115, 59, 37, 178, + 143, 191, 211, 41, 202, 253, 143, 165, 177, 119, 158, 38, 149, 96, + 128, 89, 126, 196, 11, 245, 73, 147, 126, 231, 32, 105, 165, 1, + 61, 164, 245, 30, 238, 84, 242, 35, 60, 194, 45, 243, 46, 56, + 245, 235, 75, 65, 161, 244, 57, 218, 6, 29, 73, 9, 196, 117, + 64, 181, 53, 200, 59, 162, 137, 70, 15, 14, 235, 52, 9, 68, + 78, 133, 195, 98, 62, 38, 62, 228, 174, 18, 208, 121, 143, 174, + 106, 155, 156, 123, 173, 238, 197, 151, 69, 62, 39, 84, 103, 226, + 205, 254, 105, 229, 190, 145, 50, 235, 164, 196, 171, 22, 4, 8, + 27, 223, 255, 160, 181, 100, 83, 11, 134, 145, 87, 214, 8, 44, + 58, 144, 31, 23, 93, 211, 62, 84, 235, 4, 158, 85, 24, 162, + 52, 104, 162, 16, 162, 142, 175, 214, 2, 103, 21, 58, 46, 80, + 138, 212, 133, 237, 50, 114, 37, 88, 162, 232, 179, 181, 194, 237, + 83, 197, 152, 179, 135, 32, 210, 2, 53, 194, 39, 226, 127, 207, + 150, 110, 104, 168, 153, 244, 80, 26, 223, 199, 170, 60, 159, 36, + 85, 168, 56, 15, 136, 239, 209, 231, 148, 250, 219, 216, 219, 71, + 198, 219, 180, 91, 66, 182, 103, 147, 26, 89, 98, 112, 26, 58, + 203, 30, 65, 13, 150, 44, 97, 221, 134, 252, 78, 0, 60, 144, + 215, 95, 240, 12, 162, 72, 98, 30, 219, 10, 228, 71, 109, 17, + 205, 194, 48, 208, 180, 192, 210, 58, 162, 86, 233, 143, 149, 75, + 155, 51, 168, 80, 137, 20, 202, 152, 15, 181, 34, 183, 196, 170, + 42, 169, 255, 59, 210, 105, 190, 140, 163, 148, 98, 36, 252, 182, + 99, 200, 17, 13, 208, 190, 147, 180, 78, 142, 247, 177, 182, 209, + 5, 106, 29, 157, 91, 218, 213, 80, 4, 185, 166, 101, 206, 160, + 235, 171, 243, 172, 169, 213, 89, 189, 167, 170, 106, 52, 204, 147, + 17, 51, 141, 68, 250, 188, 204, 217, 26, 202, 93, 222, 229, 244, + 7, 67, 168, 80, 53, 175, 186, 220, 207, 248, 8, 249, 88, 15, + 153, 7, 139, 113, 14, 107, 58, 6, 76, 185, 91, 207, 54, 175, + 152, 66, 56, 53, 186, 135, 14, 234, 156, 199, 218, 193, 121, 83, + 50, 180, 71, 20, 57, 224, 202, 105, 129, 24, 69, 207, 217, 168, + 28, 129, 231, 160, 247, 64, 20, 145, 175, 198, 206, 99, 39, 27, + 147, 34, 101, 163, 255, 94, 204, 173, 223, 132, 111, 239, 1, 234, + 197, 62, 206, 146, 90, 108, 38, 246, 8, 16, 252, 219, 7, 55, + 131, 214, 164, 107, 231, 161, 244, 83, 71, 91, 167, 80, 67, 123, + 1, 194, 229, 212, 202, 139, 166, 155, 126, 246, 174, 8, 107, 233, + 63, 37, 157, 28, 57, 165, 134, 202, 27, 49, 71, 183, 230, 131, + 176, 164, 232, 40, 171, 62, 172, 94, 34, 153, 137, 36, 186, 71, + 93, 23, 248, 66, 84, 140, 31, 175, 177, 221, 100, 15, 160, 114, + 57, 91, 84, 244, 75, 104, 35, 153, 196, 56, 210, 252, 217, 187, + 219, 58, 202, 107, 255, 69, 4, 114, 54, 218, 10, 203, 57, 236, + 224, 233, 226, 116, 54, 114, 146, 130, 119, 119, 178, 52, 235, 237, + 177, 81, 13, 52, 71, 235, 139, 244, 147, 142, 255, 200, 207, 2, + 83, 244, 251, 167, 171, 3, 165, 48, 172, 251, 218, 123, 205, 125, + 223, 55, 170, 157, 164, 90, 85, 82, 138, 90, 62, 208, 129, 172, + 170, 156, 1, 248, 236, 113, 26, 34, 228, 205, 95, 73, 146, 200, + 102, 110, 112, 155, 25, 95, 126, 249, 230, 225, 90, 217, 135, 42, + 158, 132, 94, 101, 163, 20, 35, 217, 251, 27, 130, 199, 168, 124, + 165, 227, 66, 142, 244, 113, 40, 106, 65, 220, 249, 126, 167, 227, + 224, 234, 108, 108, 134, 179, 253, 33, 226, 240, 64, 102, 133, 190, + 178, 210, 125, 234, 120, 75, 133, 144, 151, 170, 179, 201, 15, 123, + 143, 163, 179, 102, 167, 63, 55, 230, 70, 47, 252, 189, 31, 40, + 73, 68, 240, 105, 195, 32, 216, 18, 135, 239, 197, 207, 32, 111, + 94, 205, 76, 28, 62, 183, 237, 143, 1, 130, 53, 15, 169, 4, + 233, 114, 18, 3, 52, 33, 250, 119, 49, 236, 201, 161, 254, 199, + 230, 146, 219, 1, 73, 21, 64, 94, 176, 57, 162, 1, 229, 59, + 77, 199, 114, 84, 64, 255, 49, 118, 93, 65, 7, 188, 243, 124, + 239, 196, 224, 213, 116, 169, 223, 244, 67, 137, 179, 78, 71, 136, + 255, 37, 45, 195, 215, 101, 128, 156, 102, 104, 73, 137, 61, 101, + 37, 68, 43, 153, 148, 248, 120, 213, 240, 90, 18, 33, 171, 47, + 206, 130, 91, 3, 72, 153, 93, 246, 111, 156, 112, 75, 136, 180, + 103, 235, 149, 197, 108, 85, 8, 78, 187, 166, 233, 148, 154, 27, + 39, 143, 194, 104, 29, 131, 236, 31, 13, 140, 141, 164, 50, 87, + 204, 206, 158, 142, 9, 70, 31, 231, 129, 26, 97, 130, 31, 174, + 85, 152, 41, 149, 51, 146, 115, 237, 91, 215, 172, 253, 200, 174, + 246, 97, 27, 117, 246, 153, 157, 43, 158, 143, 85, 72, 122, 122, + 219, 4, 84, 146, 35, 136, 77, 74, 31, 64, 139, 159, 247, 161, + 28, 102, 86, 92, 199, 59, 161, 253, 202, 62, 129, 47, 209, 51, + 24, 173, 192, 165, 158, 56, 228, 126, 123, 196, 43, 1, 247, 133, + 152, 113, 128, 203, 46, 119, 236, 150, 34, 127, 42, 154, 24, 138, + 97, 84, 228, 3, 117, 123, 224, 95, 8, 59, 122, 23, 189, 203, + 150, 47, 160, 214, 205, 131, 128, 63, 159, 28, 64, 154, 245, 115, + 49, 185, 234, 64, 160, 185, 35, 226, 51, 238, 58, 186, 209, 194, + 191, 160, 102, 144, 157, 198, 118, 58, 209, 170, 53, 58, 46, 98, + 20, 174, 31, 254, 45, 110, 235, 183, 184, 5, 215, 120, 22, 66, + 1, 133, 150, 175, 83, 89, 233, 205, 178, 226, 64, 51, 212, 178, + 186, 22, 20, 236, 197, 215, 241, 125, 150, 61, 199, 94, 93, 208, + 241, 106, 161, 230, 45, 30, 124, 114, 106, 0, 72, 10, 27, 68, + 19, 248, 22, 167, 78, 38, 111, 31, 169, 188, 17, 248, 79, 113, + 236, 117, 188, 120, 236, 168, 241, 136, 233, 51, 60, 29, 173, 148, + 26, 73, 198, 230, 56, 104, 191, 230, 134, 189, 175, 124, 50, 189, + 174, 18, 95, 1, 215, 61, 91, 18, 177, 195, 98, 49, 84, 147, + 16, 85, 84, 48, 57, 96, 156, 212, 10, 106, 109, 200, 200, 24, + 215, 46, 140, 254, 234, 226, 190, 100, 94, 13, 63, 114, 43, 92, + 19, 181, 234, 162, 130, 170, 107, 17, 233, 171, 253, 221, 44, 197, + 79, 111, 169, 126, 132, 195, 192, 139, 213, 49, 155, 143, 213, 252, + 22, 64, 130, 146, 99, 183, 174, 15, 50, 2, 101, 233, 195, 60, + 81, 65, 49, 92, 55, 152, 221, 28, 38, 149, 81, 164, 133, 216, + 164, 21, 217, 59, 209, 216, 106, 226, 115, 103, 201, 15, 123, 88, + 50, 53, 18, 63, 60, 11, 193, 212, 250, 197, 197, 54, 229, 65, + 134, 174, 105, 129, 54, 240, 249, 187, 139, 169, 171, 20, 191, 75, + 119, 207, 212, 177, 97, 186, 21, 169, 221, 240, 231, 231, 140, 179, + 152, 46, 151, 51, 73, 135, 206, 176, 232, 19, 44, 33, 116, 135, + 236, 131, 55, 251, 175, 231, 252, 96, 157, 202, 236, 187, 216, 108, + 24, 110, 254, 144, 46, 157, 137, 186, 53, 67, 246, 100, 168, 162, + 121, 100, 195, 244, 179, 144, 75, 169, 51, 54, 242, 156, 166, 95, + 74, 80, 146, 172, 48, 18, 110, 239, 21, 238, 56, 41, 6, 62, + 71, 131, 61, 140, 175, 225, 182, 2, 81, 7, 239, 157, 194, 18, + 55, 91, 133, 71, 243, 43, 208, 183, 47, 132, 163, 3, 195, 234, + 89, 44, 147, 228, 122, 17, 24, 224, 196, 214, 81, 160, 74, 178, + 142, 74, 59, 10, 184, 9, 232, 161, 140, 190, 115, 136, 157, 55, + 0, 186, 174, 214, 152, 104, 243, 21, 22, 43, 77, 85, 135, 112, + 223, 112, 210, 177, 71, 99, 130, 80, 120, 47, 126, 131, 255, 71, + 159, 123, 127, 74, 229, 92, 155, 128, 176, 94, 23, 159, 114, 37, + 243, 17, 87, 25, 128, 96, 84, 176, 170, 121, 144, 158, 51, 49, + 215, 232, 84, 216, 98, 30, 36, 194, 20, 33, 245, 126, 150, 91, + 12, 169, 131, 253, 217, 150, 94, 37, 156, 96, 68, 98, 212, 245, + 118, 124, 12, 215, 203, 126, 13, 171, 76, 26, 65, 91, 69, 185, + 234, 38, 99, 105, 151, 103, 126, 153, 246, 20, 82, 182, 88, 159, + 95, 160, 132, 24, 149, 216, 63, 106, 226, 176, 40, 174, 42, 226, + 124, 20, 87, 121, 230, 100, 142, 165, 102, 15, 34, 9, 68, 55, + 53, 0, 101, 121, 142, 38, 163, 111, 226, 102, 144, 223, 209, 205, + 41, 250, 6, 243, 63, 246, 171, 205, 104, 8, 61, 181, 65, 58, + 241, 143, 254, 112, 250, 55, 91, 156, 103, 18, 238, 166, 71, 123, + 204, 248, 201, 193, 143, 106, 178, 66, 210, 238, 0, 138, 162, 168, + 0, 225, 211, 210, 129, 118, 82, 87, 163, 107, 41, 5, 104, 254, + 114, 194, 95, 113, 109, 27, 232, 192, 23, 13, 252, 47, 102, 45, + 94, 128, 250, 144, 176, 128, 119, 29, 54, 57, 136, 189, 94, 45, + 71, 166, 190, 40, 75, 245, 66, 19, 82, 163, 90, 24, 86, 64, + 255, 2, 137, 164, 241, 231, 203, 36, 96, 216, 149, 78, 109, 23, + 23, 49, 172, 24, 56, 41, 75, 59, 13, 10, 5, 240, 75, 142, + 71, 151, 89, 91, 70, 161, 61, 113, 31, 230, 37, 97, 9, 227, + 202, 118, 193, 213, 232, 108, 91, 125, 24, 174, 156, 250, 160, 242, + 168, 93, 131, 107, 104, 138, 237, 11, 169, 168, 154, 114, 225, 18, + 172, 236, 81, 190, 180, 36, 107, 140, 27, 10, 36, 188, 239, 120, + 188, 204, 13, 36, 10, 99, 94, 7, 73, 168, 123, 218, 144, 239, + 11, 171, 1, 87, 28, 137, 119, 174, 34, 135, 82, 214, 174, 182, + 130, 66, 109, 215, 234, 133, 50, 46, 206, 94, 85, 66, 243, 42, + 189, 114, 77, 200, 232, 225, 171, 136, 107, 48, 248, 79, 254, 53, + 15, 245, 137, 65, 88, 10, 142, 95, 27, 187, 175, 150, 211, 23, + 77, 91, 53, 78, 146, 111, 91, 31, 197, 115, 191, 189, 187, 88, + 203, 31, 102, 64, 11, 52, 207, 177, 82, 239, 255, 41, 194, 180, + 54, 107, 246, 158, 20, 59, 55, 132, 57, 104, 67, 243, 74, 55, + 241, 193, 247, 161, 212, 31, 86, 210, 161, 26, 176, 191, 86, 71, + 177, 184, 233, 30, 198, 6, 134, 196, 34, 60, 189, 112, 149, 78, + 100, 52, 9, 120, 147, 144, 79, 28, 52, 94, 222, 141, 82, 236, + 187, 233, 17, 72, 127, 176, 42, 249, 105, 111, 137, 53, 253, 3, + 72, 123, 115, 196, 142, 30, 213, 73, 252, 186, 56, 154, 118, 210, + 20, 150, 65, 208, 131, 38, 104, 34, 124, 205, 163, 171, 22, 101, + 237, 134, 72, 213, 237, 79, 251, 62, 184, 17, 171, 12, 176, 201, + 105, 250, 108, 54, 39, 79, 185, 254, 38, 11, 140, 22, 243, 148, + 132, 173, 96, 27, 216, 228, 56, 133, 201, 130, 108, 191, 36, 102, + 49, 125, 12, 161, 165, 216, 227, 215, 24, 12, 118, 95, 171, 7, + 36, 147, 19, 212, 242, 197, 222, 155, 128, 177, 213, 135, 213, 79, + 150, 217, 212, 40, 235, 65, 192, 73, 86, 60, 33, 224, 0, 107, + 208, 9, 119, 16, 88, 65, 206, 160, 30, 166, 48, 114, 204, 201, + 234, 117, 139, 157, 81, 144, 22, 172, 122, 1, 220, 67, 203, 40, + 160, 37, 241, 195, 26, 84, 76, 80, 145, 60, 11, 41, 254, 153, + 37, 204, 140, 239, 213, 145, 5, 254, 3, 206, 132, 104, 33, 225, + 22, 182, 120, 23, 40, 73, 233, 182, 111, 227, 48, 57, 222, 183, + 134, 32, 82, 49, 74, 245, 93, 11, 151, 9, 159, 75, 13, 215, + 16, 187, 48, 105, 237, 16, 235, 204, 70, 106, 106, 55, 112, 199, + 172, 134, 123, 242, 14, 2, 157, 69, 215, 149, 205, 65, 7, 193, + 138, 220, 197, 125, 83, 244, 48, 48, 138, 151, 69, 63, 16, 142, + 177, 118, 161, 215, 163, 171, 120, 52, 235, 121, 44, 107, 99, 139, + 132, 240, 172, 151, 83, 204, 60, 1, 174, 254, 77, 194, 94, 80, + 17, 125, 14, 163, 64, 50, 155, 27, 200, 80, 241, 167, 243, 143, + 178, 187, 119, 84, 32, 84, 34, 59, 149, 69, 50, 163, 60, 50, + 5, 85, 5, 182, 194, 224, 121, 109, 190, 98, 134, 104, 235, 89, + 66, 63, 138, 89, 69, 184, 99, 6, 4, 224, 166, 85, 152, 44, + 131, 134, 35, 162, 223, 160, 212, 230, 97, 187, 168, 104, 148, 166, + 208, 1, 11, 142, 146, 192, 160, 45, 78, 35, 230, 8, 188, 110, + 0, 254, 209, 166, 84, 111, 114, 202, 108, 64, 68, 225, 149, 175, + 250, 187, 98, 107, 84, 86, 1, 238, 105, 237, 241, 170, 75, 149, + 223, 151, 84, 182, 235, 75, 169, 80, 33, 146, 14, 147, 190, 136, + 194, 252, 196, 152, 64, 80, 131, 114, 92, 61, 25, 35, 250, 142, + 172, 0, 184, 88, 170, 216, 204, 195, 244, 227, 236, 20, 36, 169, + 110, 143, 68, 17, 175, 205, 198, 33, 154, 187, 150, 148, 109, 4, + 52, 16, 233, 75, 78, 113, 185, 141, 218, 201, 8, 94, 130, 3, + 6, 236, 201, 63, 198, 76, 91, 149, 26, 144, 133, 186, 76, 155, + 203, 184, 152, 40, 137, 129, 231, 79, 247, 199, 142, 178, 125, 132, + 255, 226, 97, 248, 212, 84, 6, 208, 172, 214, 67, 76, 213, 209, + 65, 53, 175, 191, 70, 26, 8, 195, 91, 46, 146, 55, 180, 33, + 115, 61, 6, 151, 158, 162, 91, 48, 141, 91, 16, 107, 198, 43, + 231, 54, 152, 21, 35, 13, 137, 66, 247, 202, 113, 139, 26, 172, + 114, 58, 247, 194, 196, 148, 44, 123, 132, 211, 251, 187, 217, 233, + 61, 16, 90, 137, 123, 0, 132, 36, 116, 31, 240, 183, 212, 39, + 53, 178, 21, 136, 6, 205, 191, 247, 193, 72, 169, 211, 50, 28, + 126, 97, 27, 102, 122, 110, 43, 73, 108, 5, 240, 210, 143, 17, + 161, 213, 187, 40, 216, 144, 102, 201, 196, 85, 164, 77, 11, 255, + 118, 67, 232, 172, 207, 210, 187, 99, 233, 132, 98, 240, 223, 140, + 52, 123, 200, 252, 4, 80, 85, 241, 14, 58, 143, 117, 211, 125, + 150, 60, 238, 172, 86, 118, 212, 58, 90, 19, 173, 174, 64, 195, + 127, 203, 194, 155, 128, 231, 63, 63, 130, 219, 22, 240, 65, 253, + 249, 45, 52, 152, 3, 74, 45, 89, 48, 153, 173, 255, 146, 52, + 145, 173, 244, 31, 90, 221, 119, 75, 103, 162, 76, 32, 215, 190, + 97, 48, 161, 82, 78, 223, 172, 71, 163, 17, 108, 5, 195, 79, + 26, 202, 151, 62, 199, 34, 207, 73, 137, 40, 233, 63, 48, 95, + 220, 109, 101, 39, 207, 243, 227, 121, 145, 139, 5, 72, 116, 181, + 36, 34, 154, 41, 122, 254, 239, 204, 117, 102, 11, 55, 134, 171, + 7, 6, 149, 142, 108, 131, 123, 50, 120, 140, 43, 47, 121, 19, + 168, 62, 27, 209, 51, 122, 237, 163, 108, 62, 77, 0, 105, 226, + 47, 241, 70, 174, 91, 8, 191, 237, 135, 44, 18, 165, 197, 8, + 247, 173, 251, 69, 159, 87, 175, 217, 78, 173, 181, 141, 247, 253, + 203, 104, 200, 8, 101, 164, 114, 85, 36, 151, 74, 75, 78, 254, + 155, 96, 63, 84, 148, 140, 31, 77, 52, 208, 123, 55, 105, 102, + 72, 93, 144, 219, 177, 225, 78, 132, 14, 229, 243, 154, 115, 141, + 191, 21, 147, 243, 197, 234, 117, 92, 108, 115, 241, 177, 254, 148, + 189, 222, 191, 124, 117, 232, 177, 103, 25, 243, 179, 193, 112, 247, + 46, 67, 154, 238, 255, 43, 92, 110, 75, 27, 207, 55, 227, 74, + 36, 41, 54, 60, 117, 235, 122, 95, 235, 155, 59, 190, 0, 98, + 102, 225, 153, 73, 159, 21, 104, 79, 79, 218, 89, 167, 11, 1, + 69, 165, 79, 56, 13, 29, 178, 133, 21, 136, 229, 103, 219, 57, + 121, 244, 108, 174, 84, 82, 108, 137, 78, 16, 199, 14, 242, 105, + 121, 41, 229, 119, 43, 176, 77, 90, 123, 254, 40, 231, 235, 50, + 172, 196, 239, 207, 171, 123, 136, 15, 234, 83, 121, 251, 247, 122, + 41, 135, 204, 173, 71, 29, 188, 97, 146, 73, 192, 170, 11, 109, + 122, 202, 148, 218, 17, 194, 213, 57, 97, 122, 203, 40, 186, 105, + 2, 56, 197, 209, 70, 36, 27, 150, 205, 180, 72, 24, 64, 29, + 210, 205, 232, 128, 151, 43, 50, 88, 30, 46, 79, 146, 176, 145, + 199, 84, 124, 45, 229, 91, 126, 162, 122, 170, 80, 184, 32, 76, + 193, 135, 2, 148, 161, 216, 177, 185, 27, 186, 27, 108, 12, 141, + 176, 99, 72, 186, 12, 205, 98, 217, 146, 252, 32, 57, 33, 23, + 127, 225, 242, 11, 139, 74, 164, 165, 79, 83, 149, 16, 158, 60, + 175, 144, 217, 140, 64, 95, 10, 243, 13, 19, 220, 219, 85, 49, + 90, 250, 158, 202, 8, 169, 37, 203, 163, 104, 103, 156, 212, 235, + 70, 55, 116, 243, 82, 238, 21, 163, 82, 232, 243, 196, 120, 92, + 75, 108, 242, 230, 136, 82, 80, 223, 81, 53, 16, 251, 134, 107, + 61, 50, 1, 199, 194, 174, 119, 123, 162, 36, 239, 36, 162, 223, + 47, 111, 106, 89, 245, 11, 102, 201, 124, 170, 48, 192, 162, 164, + 104, 25, 168, 200, 85, 224, 58, 111, 132, 34, 254, 215, 248, 70, + 184, 39, 156, 180, 28, 214, 213, 250, 170, 188, 116, 182, 106, 182, + 102, 73, 219, 174, 87, 27, 250, 134, 71, 194, 132, 179, 71, 191, + 76, 68, 198, 131, 74, 189, 222, 143, 192, 2, 48, 37, 105, 85, + 79, 72, 49, 204, 41, 181, 248, 214, 197, 121, 93, 6, 141, 1, + 56, 187, 205, 113, 79, 238, 120, 199, 128, 222, 41, 162, 155, 75, + 122, 197, 236, 54, 53, 214, 252, 148, 8, 103, 230, 132, 211, 144, + 175, 226, 96, 249, 141, 146, 115, 16, 205, 211, 98, 209, 198, 220, + 7, 218, 128, 40, 227, 80, 44, 248, 241, 135, 158, 254, 141, 35, + 60, 218, 1, 102, 9, 81, 229, 44, 95, 202, 56, 196, 63, 120, + 251, 93, 229, 237, 229, 114, 29, 159, 101, 50, 109, 83, 174, 119, + 63, 161, 183, 153, 107, 153, 221, 67, 248, 241, 221, 181, 116, 211, + 15, 19, 173, 159, 40, 95, 129, 48, 118, 75, 29, 57, 9, 181, + 230, 21, 171, 237, 106, 85, 109, 49, 90, 245, 162, 72, 76, 87, + 216, 30, 104, 12, 43, 137, 71, 13, 111, 31, 191, 224, 94, 150, + 186, 32, 25, 58, 52, 162, 100, 78, 101, 247, 121, 38, 169, 235, + 121, 31, 67, 254, 129, 38, 44, 123, 87, 170, 34, 5, 66, 93, + 82, 119, 83, 59, 216, 202, 109, 33, 124, 52, 249, 100, 164, 219, + 121, 4, 1, 0, 176, 53, 68, 155, 92, 16, 180, 1, 85, 61, + 17, 212, 211, 110, 222, 32, 138, 239, 108, 235, 230, 173, 77, 108, + 38, 171, 59, 197, 28, 200, 106, 246, 146, 9, 222, 202, 1, 183, + 226, 134, 134, 106, 234, 192, 34, 170, 60, 206, 177, 125, 205, 231, + 187, 116, 35, 56, 125, 106, 20, 112, 40, 243, 62, 129, 215, 87, + 182, 178, 250, 177, 200, 101, 90, 191, 29, 113, 50, 53, 154, 229, + 70, 250, 216, 44, 171, 126, 229, 85, 74, 174, 77, 205, 56, 0, + 16, 39, 223, 133, 225, 40, 54, 192, 228, 193, 202, 153, 183, 214, + 63, 11, 29, 39, 129, 63, 154, 246, 152, 149, 139, 152, 188, 124, + 237, 126, 107, 126, 11, 27, 177, 53, 210, 2, 111, 163, 93, 225, + 96, 114, 49, 75, 35, 159, 44, 62, 141, 204, 10, 106, 167, 1, + 106, 229, 21, 188, 45, 237, 95, 170, 26, 74, 155, 154, 226, 254, + 179, 193, 5, 61, 80, 123, 204, 204, 138, 193, 247, 215, 24, 174, + 31, 68, 192, 183, 31, 240, 77, 191, 86, 26, 108, 211, 56, 139, + 121, 135, 73, 223, 127, 168, 55, 199, 180, 81, 228, 205, 154, 203, + 112, 93, 184, 92, 124, 237, 111, 76, 191, 211, 184, 99, 61, 243, + 253, 88, 105, 149, 149, 153, 216, 118, 60, 40, 127, 59, 53, 74, + 15, 155, 199, 143, 20, 122, 232, 100, 239, 197, 215, 84, 189, 206, + 177, 117, 167, 111, 86, 134, 79, 192, 188, 31, 56, 179, 102, 173, + 77, 81, 56, 63, 42, 34, 72, 149, 61, 148, 52, 37, 224, 68, + 102, 33, 222, 108, 34, 21, 37, 175, 10, 188, 191, 99, 1, 171, + 181, 230, 234, 129, 46, 251, 142, 107, 25, 238, 69, 44, 80, 111, + 251, 88, 246, 14, 77, 222, 90, 168, 149, 218, 44, 40, 210, 111, + 20, 200, 205, 199, 203, 100, 128, 183, 136, 233, 71, 9, 5, 26, + 101, 20, 80, 49, 142, 44, 208, 25, 33, 39, 28, 176, 148, 99, + 209, 252, 51, 162, 161, 160, 105, 204, 57, 237, 67, 255, 241, 103, + 166, 85, 139, 40, 198, 36, 191, 149, 191, 232, 253, 119, 59, 220, + 52, 94, 229, 44, 122, 227, 119, 250, 16, 87, 94, 75, 27, 139, + 71, 54, 122, 106, 8, 3, 165, 48, 89, 99, 16, 102, 217, 61, + 105, 201, 59, 40, 240, 99, 168, 100, 157, 37, 3, 126, 28, 40, + 255, 227, 123, 174, 119, 187, 226, 188, 174, 80, 3, 53, 224, 254, + 190, 77, 151, 48, 100, 15, 215, 240, 210, 183, 154, 23, 40, 252, + 7, 178, 83, 10, 143, 189, 66, 37, 13, 208, 203, 156, 36, 43, + 33, 233, 66, 6, 254, 17, 173, 115, 17, 193, 44, 111, 8, 56, + 138, 161, 67, 115, 14, 76, 104, 252, 198, 121, 110, 63, 147, 61, + 133, 144, 153, 122, 52, 125, 110, 101, 107, 171, 108, 55, 122, 200, + 190, 29, 73, 8, 114, 184, 10, 95, 188, 76, 142, 155, 187, 108, + 185, 233, 60, 239, 135, 39, 217, 118, 117, 56, 169, 250, 207, 186, + 96, 40, 63, 102, 14, 83, 185, 162, 246, 65, 147, 23, 136, 156, + 191, 240, 105, 111, 147, 250, 219, 236, 50, 113, 16, 119, 117, 175, + 87, 157, 209, 161, 105, 133, 177, 13, 21, 82, 171, 91, 121, 70, + 92, 12, 164, 240, 108, 248, 111, 97, 38, 222, 6, 138, 12, 158, + 18, 109, 127, 149, 84, 56, 58, 185, 80, 111, 133, 73, 26, 65, + 169, 194, 12, 139, 176, 145, 24, 183, 106, 127, 244, 246, 117, 107, + 148, 72, 99, 37, 88, 51, 254, 184, 250, 8, 13, 187, 25, 200, + 253, 215, 244, 174, 109, 95, 216, 142, 70, 41, 134, 227, 31, 27, + 63, 180, 204, 65, 223, 189, 187, 145, 4, 172, 209, 24, 227, 234, + 95, 235, 221, 248, 3, 133, 241, 240, 11, 123, 16, 217, 220, 103, + 228, 156, 93, 186, 253, 137, 178, 229, 174, 218, 38, 114, 50, 230, + 254, 211, 87, 209, 171, 5, 38, 191, 201, 217, 238, 140, 198, 81, + 10, 234, 224, 40, 184, 21, 3, 156, 9, 224, 218, 232, 45, 116, + 58, 102, 193, 148, 100, 83, 248, 171, 125, 137, 16, 48, 67, 19, + 22, 177, 225, 115, 81, 73, 146, 177, 85, 103, 33, 137, 66, 104, + 31, 59, 44, 99, 68, 251, 157, 60, 133, 84, 82, 3, 40, 242, + 28, 89, 220, 247, 137, 114, 149, 237, 239, 14, 197, 178, 201, 101, + 19, 231, 144, 246, 152, 95, 216, 236, 12, 213, 212, 14, 164, 75, + 74, 223, 244, 139, 107, 248, 127, 233, 83, 234, 152, 98, 184, 56, + 241, 79, 106, 129, 126, 113, 36, 36, 160, 73, 245, 97, 54, 83, + 255, 10, 69, 151, 221, 151, 102, 112, 135, 123, 11, 143, 94, 74, + 239, 215, 113, 204, 97, 120, 214, 160, 4, 192, 23, 33, 2, 255, + 155, 170, 24, 179, 91, 198, 33, 49, 199, 8, 232, 203, 34, 233, + 229, 191, 6, 34, 82, 95, 226, 249, 36, 243, 185, 129, 11, 40, + 149, 66, 254, 236, 89, 216, 195, 181, 164, 238, 70, 128, 95, 26, + 178, 209, 37, 86, 26, 207, 125, 205, 206, 8, 84, 82, 245, 11, + 218, 185, 159, 228, 78, 50, 174, 136, 172, 66, 166, 43, 112, 75, + 174, 224, 34, 69, 10, 166, 168, 234, 52, 160, 59, 97, 136, 14, + 203, 245, 127, 142, 203, 115, 249, 166, 33, 91, 218, 72, 228, 40, + 112, 49, 102, 30, 107, 45, 38, 124, 127, 115, 241, 174, 45, 48, + 104, 125, 110, 27, 69, 34, 124, 26, 72, 4, 122, 78, 170, 38, + 200, 217, 26, 87, 66, 155, 77, 18, 169, 37, 93, 239, 202, 226, + 58, 89, 5, 64, 88, 105, 176, 229, 179, 29, 132, 182, 216, 82, + 45, 59, 131, 90, 188, 81, 73, 229, 230, 18, 155, 206, 25, 243, + 135, 99, 27, 178, 188, 22, 179, 75, 175, 10, 127, 3, 169, 227, + 29, 11, 216, 250, 216, 244, 91, 152, 23, 235, 121, 101, 253, 44, + 248, 40, 196, 146, 149, 162, 158, 55, 111, 240, 36, 120, 68, 45, + 38, 250, 220, 13, 155, 72, 242, 89, 241, 210, 92, 255, 51, 180, + 158, 115, 71, 248, 42, 106, 107, 46, 127, 128, 89, 109, 12, 38, + 103, 86, 110, 44, 155, 51, 80, 146, 72, 25, 144, 15, 70, 70, + 120, 215, 120, 188, 38, 102, 221, 102, 100, 160, 23, 21, 98, 105, + 178, 174, 252, 81, 3, 224, 14, 158, 130, 181, 65, 81, 54, 220, + 162, 127, 254, 74, 248, 165, 7, 221, 101, 39, 98, 172, 114, 107, + 114, 224, 201, 133, 194, 1, 30, 167, 238, 210, 244, 144, 88, 165, + 145, 237, 233, 35, 163, 109, 169, 155, 23, 32, 17, 240, 237, 140, + 216, 126, 191, 82, 114, 111, 44, 96, 169, 159, 40, 19, 97, 151, + 141, 81, 143, 6, 182, 49, 171, 12, 125, 12, 136, 195, 54, 34, + 57, 255, 6, 150, 122, 235, 203, 201, 147, 1, 66, 201, 122, 245, + 228, 19, 84, 224, 162, 245, 67, 160, 126, 190, 51, 184, 6, 71, + 192, 105, 149, 90, 5, 130, 46, 248, 38, 242, 86, 125, 195, 43, + 255, 35, 249, 253, 111, 64, 251, 158, 98, 92, 206, 154, 217, 61, + 188, 227, 227, 47, 56, 70, 179, 8, 194, 4, 20, 144, 72, 191, + 128, 211, 168, 76, 168, 99, 116, 137, 19, 70, 61, 110, 131, 53, + 31, 20, 114, 93, 243, 241, 184, 251, 247, 106, 29, 21, 119, 126, + 253, 219, 130, 135, 12, 75, 195, 42, 184, 81, 133, 88, 23, 80, + 173, 52, 65, 53, 170, 155, 172, 29, 13, 75, 71, 173, 174, 247, + 96, 98, 202, 159, 50, 42, 118, 170, 74, 176, 6, 160, 202, 84, + 14, 106, 139, 79, 94, 205, 53, 118, 197, 107, 222, 224, 60, 121, + 33, 8, 56, 168, 108, 137, 208, 23, 79, 199, 67, 0, 3, 249, + 173, 135, 64, 119, 106, 180, 79, 155, 173, 230, 238, 205, 194, 73, + 126, 100, 171, 89, 225, 44, 19, 25, 175, 113, 110, 11, 166, 225, + 108, 104, 74, 236, 160, 195, 136, 186, 204, 76, 246, 11, 178, 57, + 162, 112, 47, 40, 254, 250, 192, 108, 125, 2, 167, 212, 38, 46, + 19, 93, 208, 196, 245, 129, 227, 232, 119, 62, 67, 7, 219, 139, + 251, 205, 84, 145, 28, 191, 202, 178, 163, 36, 62, 95, 115, 184, + 154, 41, 157, 247, 36, 34, 130, 199, 177, 201, 13, 183, 151, 64, + 59, 92, 41, 252, 70, 73, 59, 227, 73, 6, 159, 188, 97, 116, + 255, 115, 194, 189, 228, 125, 62, 114, 106, 51, 29, 157, 145, 72, + 149, 113, 199, 121, 112, 148, 56, 40, 165, 250, 100, 108, 209, 53, + 145, 11, 35, 145, 253, 118, 150, 226, 201, 218, 197, 95, 116, 156, + 183, 77, 33, 211, 201, 170, 208, 112, 49, 188, 42, 28, 114, 128, + 250, 136, 190, 173, 63, 103, 106, 187, 103, 255, 171, 103, 11, 123, + 119, 121, 163, 124, 120, 201, 158, 9, 151, 186, 184, 215, 78, 60, + 5, 89, 16, 163, 187, 253, 15, 169, 103, 91, 240, 177, 111, 115, + 35, 190, 75, 34, 95, 16, 138, 8, 150, 90, 239, 166, 149, 214, + 178, 178, 101, 114, 175, 40, 235, 0, 18, 67, 36, 185, 33, 101, + 225, 200, 241, 37, 200, 35, 127, 155, 160, 97, 98, 146, 50, 163, + 155, 33, 251, 110, 212, 135, 160, 58, 70, 12, 112, 168, 251, 244, + 55, 33, 155, 88, 210, 171, 50, 1, 56, 111, 248, 249, 137, 131, + 187, 67, 88, 94, 194, 220, 174, 51, 174, 193, 128, 147, 108, 48, + 120, 165, 128, 154, 110, 225, 199, 250, 56, 41, 76, 45, 76, 193, + 254, 51, 164, 221, 95, 24, 6, 95, 162, 198, 29, 190, 61, 63, + 67, 190, 144, 191, 145, 197, 206, 109, 103, 167, 60, 159, 250, 93, + 193, 171, 112, 155, 178, 127, 194, 206, 130, 73, 162, 166, 235, 14, + 242, 87, 49, 135, 180, 65, 39, 174, 151, 152, 222, 166, 234, 222, + 187, 118, 250, 235, 34, 139, 31, 19, 51, 113, 81, 17, 25, 35, + 50, 42, 220, 241, 53, 59, 73, 236, 71, 69, 250, 169, 141, 84, + 27, 136, 229, 238, 8, 124, 237, 31, 109, 30, 142, 95, 4, 175, + 177, 235, 203, 201, 132, 163, 11, 89, 121, 134, 61, 223, 222, 176, + 41, 41, 155, 209, 126, 186, 28, 234, 73, 152, 90, 111, 235, 50, + 140, 144, 77, 210, 227, 154, 247, 173, 247, 230, 175, 14, 199, 10, + 135, 180, 177, 199, 127, 129, 111, 57, 124, 87, 25, 91, 122, 200, + 233, 89, 152, 194, 143, 59, 234, 121, 171, 46, 74, 249, 239, 96, + 145, 170, 248, 123, 170, 126, 52, 164, 62, 180, 29, 0, 167, 164, + 229, 144, 249, 114, 25, 206, 2, 220, 146, 162, 86, 227, 239, 86, + 182, 204, 58, 156, 113, 37, 241, 249, 200, 119, 172, 42, 21, 10, + 224, 226, 140, 116, 208, 241, 121, 248, 187, 121, 167, 17, 151, 60, + 54, 183, 170, 112, 195, 89, 111, 67, 93, 115, 11, 75, 197, 88, + 24, 8, 43, 121, 127, 90, 151, 27, 118, 203, 181, 0, 92, 76, + 27, 46, 25, 222, 131, 236, 230, 181, 98, 203, 148, 194, 189, 4, + 125, 73, 249, 185, 220, 8, 104, 239, 73, 241, 206, 146, 25, 163, + 180, 156, 39, 216, 194, 89, 53, 134, 99, 7, 32, 12, 219, 129, + 78, 92, 192, 21, 1, 169, 70, 236, 47, 161, 244, 145, 1, 7, + 204, 18, 161, 27, 185, 90, 131, 26, 131, 49, 105, 94, 31, 133, + 139, 80, 86, 99, 47, 59, 98, 227, 196, 174, 202, 233, 72, 183, + 190, 100, 122, 58, 97, 40, 237, 203, 128, 43, 165, 208, 8, 243, + 10, 37, 152, 89, 234, 16, 116, 166, 231, 212, 64, 247, 212, 82, + 177, 250, 53, 13, 168, 60, 117, 83, 241, 148, 13, 129, 130, 86, + 20, 198, 229, 113, 1, 148, 230, 82, 222, 125, 13, 194, 222, 43, + 22, 58, 39, 116, 136, 82, 111, 74, 134, 69, 47, 150, 81, 69, + 62, 249, 203, 156, 173, 192, 226, 97, 183, 191, 78, 133, 12, 212, + 30, 102, 196, 168, 66, 154, 3, 196, 53, 92, 31, 100, 251, 25, + 35, 56, 20, 206, 60, 219, 169, 169, 137, 88, 25, 35, 171, 191, + 195, 1, 159, 94, 14, 108, 17, 47, 61, 52, 48, 52, 151, 96, + 13, 153, 161, 33, 225, 43, 225, 185, 182, 71, 115, 255, 98, 201, + 159, 4, 31, 174, 254, 64, 115, 17, 87, 221, 46, 81, 212, 55, + 213, 72, 77, 178, 140, 64, 22, 119, 46, 110, 203, 117, 172, 122, + 183, 161, 233, 241, 221, 213, 120, 112, 182, 8, 221, 67, 217, 196, + 82, 63, 173, 114, 148, 141, 182, 31, 12, 57, 118, 118, 136, 113, + 103, 13, 247, 83, 128, 74, 27, 158, 140, 17, 219, 99, 63, 132, + 8, 116, 24, 15, 158, 240, 90, 217, 117, 158, 96, 88, 233, 110, + 132, 238, 107, 72, 10, 255, 192, 183, 169, 80, 196, 12, 137, 94, + 121, 35, 182, 229, 237, 234, 65, 239, 13, 140, 117, 180, 95, 1, + 91, 80, 240, 107, 164, 158, 34, 70, 241, 240, 98, 143, 107, 95, + 42, 86, 44, 253, 137, 229, 68, 142, 81, 53, 100, 144, 11, 64, + 60, 171, 119, 250, 190, 103, 44, 18, 162, 97, 167, 136, 224, 142, + 208, 240, 65, 126, 135, 81, 47, 49, 151, 247, 66, 236, 83, 142, + 73, 185, 96, 43, 116, 120, 112, 11, 101, 120, 149, 175, 15, 125, + 205, 30, 251, 93, 51, 224, 212, 81, 186, 108, 166, 80, 23, 138, + 56, 29, 152, 184, 192, 205, 244, 224, 150, 224, 187, 182, 157, 186, + 154, 196, 185, 132, 52, 52, 14, 184, 50, 14, 23, 100, 241, 232, + 215, 240, 255, 126, 133, 60, 106, 228, 14, 16, 175, 33, 195, 182, + 62, 65, 20, 30, 189, 118, 12, 145, 247, 166, 13, 177, 119, 195, + 94, 245, 34, 16, 155, 89, 254, 65, 29, 233, 241, 136, 184, 219, + 121, 156, 249, 58, 96, 92, 100, 42, 50, 206, 16, 100, 50, 119, + 177, 255, 1, 49, 21, 89, 90, 70, 218, 190, 51, 156, 39, 198, + 13, 196, 118, 27, 115, 134, 155, 99, 16, 146, 76, 91, 106, 16, + 189, 70, 12, 44, 154, 91, 103, 32, 83, 229, 153, 214, 5, 165, + 215, 141, 172, 16, 251, 111, 40, 120, 146, 141, 95, 163, 192, 251, + 87, 188, 230, 22, 209, 157, 119, 135, 169, 173, 60, 27, 117, 230, + 64, 92, 126, 80, 121, 105, 161, 84, 3, 21, 218, 108, 133, 164, + 77, 81, 242, 177, 106, 184, 64, 243, 153, 28, 96, 158, 209, 175, + 194, 97, 204, 64, 2, 13, 105, 149, 185, 134, 204, 227, 14, 132, + 244, 242, 109, 130, 181, 185, 246, 5, 223, 13, 25, 120, 0, 209, + 122, 62, 224, 171, 94, 106, 20, 55, 156, 132, 226, 65, 122, 237, + 192, 77, 133, 251, 238, 31, 79, 173, 16, 164, 112, 171, 38, 150, + 116, 106, 73, 154, 70, 62, 70, 59, 240, 193, 184, 204, 0, 100, + 229, 193, 234, 194, 63, 153, 150, 27, 72, 31, 248, 160, 185, 143, + 54, 11, 254, 212, 57, 131, 154, 122, 69, 34, 192, 228, 193, 32, + 127, 105, 99, 202, 226, 197, 17, 100, 5, 154, 145, 91, 222, 143, + 28, 51, 180, 204, 114, 243, 216, 212, 206, 118, 12, 216, 193, 190, + 132, 84, 70, 89, 33, 22, 50, 2, 130, 216, 176, 236, 148, 149, + 10, 140, 64, 248, 148, 220, 79, 129, 9, 68, 236, 81, 66, 6, + 34, 218, 225, 169, 68, 83, 175, 117, 192, 161, 16, 200, 237, 212, + 216, 96, 61, 176, 55, 210, 78, 214, 60, 238, 188, 217, 79, 217, + 43, 45, 183, 253, 46, 182, 116, 0, 169, 82, 253, 234, 69, 226, + 253, 199, 144, 26, 56, 220, 195, 255, 242, 133, 222, 149, 185, 244, + 231, 240, 171, 31, 43, 114, 87, 5, 225, 158, 123, 245, 179, 140, + 26, 142, 213, 29, 78, 61, 148, 169, 100, 127, 46, 114, 202, 83, + 191, 79, 172, 253, 186, 50, 219, 68, 5, 70, 80, 184, 173, 2, + 45, 247, 68, 206, 127, 102, 231, 130, 37, 7, 41, 172, 248, 116, + 59, 220, 16, 241, 149, 37, 35, 59, 220, 26, 110, 14, 99, 241, + 5, 175, 50, 228, 111, 150, 96, 0, 31, 4, 221, 93, 101, 180, + 60, 207, 29, 47, 254, 90, 145, 225, 159, 198, 104, 2, 90, 80, + 0, 83, 14, 16, 206, 56, 204, 123, 79, 43, 150, 221, 156, 84, + 85, 66, 102, 138, 2, 192, 16, 184, 219, 179, 96, 202, 35, 3, + 158, 209, 212, 208, 46, 115, 3, 216, 236, 174, 152, 106, 4, 207, + 87, 176, 43, 0, 109, 151, 222, 99, 153, 243, 248, 174, 90, 238, + 83, 31, 23, 50, 100, 163, 85, 158, 205, 10, 60, 200, 81, 157, + 86, 94, 248, 219, 127, 173, 142, 17, 96, 181, 12, 24, 108, 141, + 132, 229, 90, 22, 117, 68, 229, 42, 235, 162, 243, 213, 209, 146, + 201, 250, 80, 239, 32, 244, 64, 57, 178, 231, 160, 30, 62, 198, + 76, 118, 156, 110, 83, 211, 154, 198, 132, 102, 107, 98, 31, 17, + 114, 247, 110, 38, 227, 71, 1, 202, 227, 251, 135, 97, 242, 148, + 72, 164, 187, 6, 226, 117, 77, 51, 245, 163, 27, 3, 228, 57, + 186, 204, 218, 95, 223, 159, 189, 155, 223, 95, 125, 202, 89, 237, + 66, 93, 175, 129, 158, 248, 183, 68, 94, 27, 221, 190, 97, 232, + 83, 159, 32, 107, 110, 0, 123, 215, 180, 81, 133, 194, 170, 149, + 74, 138, 23, 63, 80, 18, 45, 84, 138, 190, 152, 1, 13, 249, + 184, 254, 189, 247, 203, 28, 61, 225, 132, 230, 206, 88, 115, 50, + 72, 143, 166, 193, 133, 80, 4, 76, 61, 159, 125, 103, 23, 186, + 4, 224, 149, 222, 180, 48, 214, 123, 202, 174, 211, 98, 127, 131, + 41, 106, 173, 225, 168, 245, 62, 173, 82, 144, 161, 171, 119, 185, + 51, 223, 125, 116, 101, 190, 161, 232, 101, 229, 30, 211, 112, 70, + 34, 247, 216, 235, 24, 144, 237, 144, 147, 227, 183, 199, 131, 199, + 156, 246, 226, 182, 165, 217, 156, 40, 148, 164, 140, 163, 36, 36, + 57, 60, 230, 114, 69, 190, 117, 63, 17, 231, 45, 217, 164, 134, + 90, 231, 100, 148, 122, 241, 56, 29, 232, 221, 47, 66, 205, 187, + 48, 138, 245, 236, 124, 68, 178, 137, 19, 130, 178, 128, 176, 163, + 193, 98, 128, 95, 3, 6, 204, 211, 100, 191, 200, 177, 159, 99, + 144, 140, 0, 166, 18, 126, 66, 31, 255, 209, 169, 4, 111, 125, + 48, 7, 100, 198, 120, 37, 17, 34, 48, 27, 189, 13, 183, 161, + 142, 59, 250, 100, 11, 7, 250, 225, 93, 178, 185, 101, 236, 245, + 106, 136, 190, 160, 131, 174, 72, 204, 175, 17, 92, 80, 109, 63, + 126, 82, 28, 132, 26, 19, 120, 153, 86, 127, 85, 19, 122, 152, + 76, 152, 105, 105, 103, 5, 215, 101, 245, 51, 77, 84, 244, 138, + 10, 252, 94, 224, 108, 127, 126, 149, 107, 11, 155, 183, 41, 149, + 168, 186, 254, 80, 247, 199, 156, 147, 82, 110, 179, 8, 84, 25, + 9, 87, 181, 131, 143, 243, 63, 57, 148, 48, 28, 7, 214, 123, + 170, 169, 163, 236, 89, 75, 27, 251, 41, 99, 76, 174, 96, 192, + 108, 6, 168, 209, 187, 254, 79, 138, 173, 130, 246, 58, 43, 103, + 33, 84, 48, 167, 227, 251, 102, 141, 215, 53, 171, 222, 248, 102, + 59, 71, 195, 159, 248, 205, 84, 164, 70, 214, 232, 157, 139, 132, + 86, 96, 147, 82, 31, 208, 191, 192, 93, 62, 48, 40, 115, 67, + 234, 228, 166, 213, 21, 198, 125, 202, 64, 161, 97, 71, 88, 134, + 26, 195, 48, 73, 18, 34, 103, 211, 84, 225, 180, 250, 251, 95, + 92, 11, 44, 132, 155, 197, 85, 194, 243, 52, 62, 136, 39, 121, + 24, 0, 3, 231, 61, 203, 7, 66, 135, 56, 108, 205, 232, 146, + 238, 129, 10, 42, 5, 199, 168, 225, 80, 228, 208, 193, 76, 132, + 95, 76, 179, 116, 157, 153, 116, 221, 44, 144, 253, 56, 63, 229, + 225, 15, 140, 23, 179, 161, 97, 141, 189, 209, 191, 66, 19, 89, + 94, 191, 246, 89, 87, 86, 188, 67, 53, 38, 105, 181, 241, 161, + 26, 134, 125, 220, 132, 31, 197, 241, 128, 43, 227, 65, 26, 159, + 163, 103, 169, 83, 195, 169, 204, 87, 43, 209, 199, 182, 210, 173, + 34, 45, 221, 170, 69, 89, 234, 30, 182, 87, 15, 40, 56, 215, + 207, 162, 175, 230, 195, 107, 116, 243, 37, 169, 90, 23, 235, 233, + 229, 176, 138, 140, 2, 119, 38, 33, 179, 153, 66, 248, 210, 49, + 164, 178, 210, 32, 179, 1, 227, 199, 178, 4, 225, 104, 238, 23, + 46, 33, 40, 90, 233, 0, 127, 54, 76, 64, 120, 185, 203, 106, + 53, 19, 4, 60, 103, 97, 138, 221, 172, 22, 13, 7, 62, 202, + 165, 230, 233, 150, 38, 161, 149, 133, 41, 118, 209, 109, 95, 9, + 160, 248, 170, 100, 77, 174, 1, 64, 55, 195, 116, 238, 118, 161, + 201, 191, 127, 158, 55, 105, 139, 209, 4, 188, 243, 12, 63, 73, + 101, 60, 120, 2, 236, 131, 61, 78, 205, 130, 44, 193, 37, 94, + 192, 51, 29, 212, 143, 5, 229, 39, 48, 241, 5, 88, 124, 240, + 166, 94, 152, 198, 201, 51, 139, 26, 35, 47, 83, 244, 160, 240, + 197, 212, 19, 76, 132, 241, 254, 229, 172, 71, 216, 66, 208, 60, + 99, 247, 90, 89, 49, 9, 125, 6, 143, 158, 207, 126, 241, 29, + 202, 19, 217, 159, 169, 66, 132, 224, 29, 179, 46, 120, 159, 79, + 187, 128, 98, 51, 212, 179, 21, 22, 76, 145, 240, 160, 30, 15, + 26, 205, 24, 252, 246, 237, 2, 130, 252, 113, 243, 181, 4, 221, + 11, 237, 159, 127, 179, 174, 243, 103, 65, 150, 13, 95, 83, 191, + 251, 201, 127, 31, 124, 41, 44, 213, 255, 0, 112, 119, 49, 17, + 196, 178, 103, 240, 217, 40, 120, 204, 119, 71, 118, 76, 245, 205, + 9, 84, 243, 33, 183, 82, 164, 180, 206, 128, 24, 6, 148, 254, + 216, 98, 120, 172, 137, 146, 187, 87, 241, 37, 23, 203, 147, 15, + 207, 200, 20, 21, 39, 213, 75, 44, 149, 161, 21, 176, 221, 118, + 212, 167, 201, 76, 196, 19, 211, 136, 83, 252, 188, 37, 26, 42, + 183, 133, 60, 163, 66, 233, 140, 140, 2, 225, 143, 61, 188, 198, + 234, 246, 147, 244, 232, 208, 40, 87, 146, 175, 243, 39, 46, 162, + 223, 195, 154, 208, 149, 224, 230, 255, 140, 207, 66, 163, 53, 70, + 144, 35, 235, 121, 80, 154, 93, 114, 42, 96, 97, 169, 142, 48, + 86, 243, 96, 134, 7, 227, 118, 154, 131, 184, 225, 0, 242, 115, + 224, 221, 53, 104, 160, 134, 78, 10, 102, 227, 191, 64, 50, 28, + 227, 16, 112, 138, 82, 146, 44, 96, 124, 21, 75, 255, 150, 10, + 75, 3, 71, 120, 122, 236, 124, 162, 187, 53, 201, 125, 173, 13, + 165, 146, 191, 190, 37, 144, 177, 120, 165, 146, 181, 39, 181, 222, + 3, 162, 247, 253, 151, 224, 44, 233, 230, 113, 170, 241, 9, 66, + 179, 197, 249, 172, 155, 69, 216, 23, 48, 18, 174, 214, 33, 77, + 184, 226, 234, 170, 254, 150, 184, 34, 103, 88, 56, 110, 19, 147, + 71, 42, 58, 193, 143, 161, 22, 155, 173, 71, 29, 57, 185, 197, + 220, 152, 3, 206, 238, 152, 200, 120, 210, 158, 118, 205, 25, 173, + 150, 196, 193, 194, 73, 113, 12, 104, 154, 12, 76, 226, 172, 116, + 16, 223, 219, 195, 148, 174, 122, 249, 185, 143, 45, 55, 45, 86, + 50, 18, 178, 230, 43, 223, 152, 103, 170, 109, 74, 161, 22, 19, + 135, 81, 20, 114, 78, 240, 224, 223, 33, 64, 235, 249, 14, 137, + 3, 56, 112, 93, 162, 249, 43, 147, 4, 59, 188, 56, 254, 248, + 63, 125, 111, 167, 161, 113, 26, 2, 165, 12, 93, 130, 104, 221, + 67, 233, 201, 187, 64, 220, 82, 40, 174, 105, 116, 178, 162, 207, + 8, 164, 207, 138, 246, 217, 245, 11, 94, 236, 43, 38, 251, 70, + 236, 21, 228, 169, 77, 12, 80, 122, 139, 43, 74, 87, 28, 183, + 51, 165, 206, 123, 244, 236, 254, 255, 96, 229, 181, 90, 151, 103, + 206, 221, 107, 31, 15, 67, 118, 194, 204, 113, 72, 213, 225, 20, + 249, 162, 15, 213, 200, 173, 13, 214, 183, 69, 5, 142, 203, 233, + 39, 249, 215, 192, 156, 46, 162, 30, 196, 9, 213, 253, 195, 39, + 190, 254, 194, 176, 176, 98, 86, 69, 30, 40, 242, 225, 34, 42, + 57, 139, 122, 140, 247, 62, 169, 130, 15, 17, 201, 163, 172, 80, + 172, 127, 184, 226, 8, 107, 240, 43, 209, 7, 186, 203, 198, 104, + 166, 135, 196, 146, 251, 6, 66, 23, 220, 135, 14, 250, 108, 32, + 7, 188, 182, 4, 176, 135, 249, 251, 227, 111, 88, 202, 167, 155, + 60, 96, 180, 11, 193, 75, 42, 134, 106, 37, 2, 238, 1, 95, + 243, 214, 83, 177, 168, 116, 214, 153, 47, 2, 1, 224, 23, 68, + 11, 39, 206, 151, 219, 171, 184, 44, 185, 158, 248, 151, 149, 218, + 106, 30, 253, 72, 16, 147, 230, 12, 138, 145, 95, 159, 222, 145, + 183, 75, 143, 43, 11, 45, 129, 249, 138, 248, 129, 70, 54, 218, + 154, 234, 245, 162, 208, 211, 163, 202, 208, 110, 4, 237, 80, 41, + 184, 122, 81, 150, 64, 95, 146, 128, 202, 134, 201, 98, 152, 190, + 103, 129, 18, 170, 60, 156, 174, 18, 158, 238, 32, 124, 20, 42, + 238, 65, 147, 243, 35, 250, 220, 40, 222, 198, 17, 15, 233, 134, + 50, 155, 57, 46, 143, 77, 235, 84, 218, 172, 166, 233, 139, 115, + 198, 138, 19, 53, 231, 93, 122, 188, 226, 233, 52, 92, 192, 62, + 226, 37, 167, 104, 253, 25, 43, 139, 72, 118, 223, 28, 43, 32, + 35, 62, 6, 133, 250, 192, 121, 147, 249, 73, 183, 158, 138, 213, + 214, 153, 212, 112, 199, 66, 109, 13, 19, 241, 104, 66, 214, 121, + 218, 14, 123, 96, 168, 6, 48, 53, 140, 201, 223, 234, 116, 126, + 88, 213, 94, 5, 190, 86, 21, 83, 104, 10, 78, 27, 72, 13, + 156, 26, 204, 5, 108, 226, 85, 138, 159, 93, 216, 230, 182, 253, + 25, 70, 215, 249, 227, 46, 227, 80, 81, 205, 169, 104, 102, 67, + 234, 191, 243, 28, 74, 161, 173, 90, 209, 133, 221, 119, 8, 45, + 172, 31, 143, 225, 195, 64, 151, 102, 8, 187, 252, 142, 189, 122, + 18, 230, 145, 74, 54, 178, 139, 157, 76, 93, 103, 22, 222, 162, + 133, 12, 247, 89, 99, 240, 40, 165, 155, 193, 13, 2, 154, 202, + 210, 240, 12, 179, 250, 244, 7, 139, 32, 161, 238, 113, 215, 50, + 164, 16, 248, 245, 124, 183, 90, 74, 48, 142, 206, 206, 182, 237, + 243, 133, 221, 133, 173, 3, 251, 134, 15, 71, 9, 152, 171, 240, + 208, 144, 188, 113, 81, 59, 74, 97, 168, 16, 80, 53, 126, 160, + 64, 204, 188, 170, 139, 6, 212, 231, 219, 170, 19, 75, 86, 82, + 118, 105, 6, 179, 149, 166, 92, 55, 250, 104, 222, 148, 85, 141, + 18, 95, 6, 242, 247, 37, 34, 101, 236, 26, 233, 115, 94, 15, + 28, 169, 254, 165, 97, 74, 203, 230, 172, 59, 226, 112, 39, 159, + 182, 200, 50, 207, 68, 177, 99, 0, 113, 83, 242, 158, 39, 42, + 2, 75, 25, 84, 63, 178, 71, 219, 142, 74, 127, 154, 131, 160, + 15, 212, 88, 155, 223, 61, 130, 68, 211, 197, 52, 92, 193, 188, + 201, 109, 72, 109, 35, 11, 80, 151, 250, 221, 79, 179, 156, 220, + 159, 99, 172, 132, 138, 174, 179, 115, 173, 130, 124, 7, 74, 250, + 91, 214, 128, 80, 134, 235, 15, 46, 237, 254, 34, 131, 31, 29, + 181, 209, 200, 146, 109, 82, 96, 111, 60, 117, 237, 12, 111, 9, + 86, 157, 176, 90, 238, 91, 152, 111, 212, 223, 14, 103, 141, 137, + 185, 62, 59, 239, 212, 130, 62, 109, 67, 180, 85, 20, 249, 115, + 230, 171, 216, 214, 58, 75, 107, 80, 232, 83, 150, 199, 210, 137, + 210, 133, 27, 100, 201, 157, 204, 129, 24, 119, 135, 248, 24, 194, + 180, 182, 191, 197, 16, 74, 149, 115, 73, 198, 76, 35, 184, 25, + 172, 206, 91, 143, 144, 157, 169, 149, 17, 160, 34, 14, 240, 119, + 176, 2, 61, 186, 244, 152, 76, 58, 138, 63, 198, 18, 245, 238, + 245, 103, 116, 101, 41, 53, 174, 203, 249, 27, 7, 6, 35, 94, + 144, 101, 137, 41, 15, 155, 62, 102, 61, 86, 178, 100, 127, 95, + 47, 230, 42, 54, 4, 90, 45, 133, 243, 202, 165, 252, 95, 86, + 238, 107, 64, 130, 90, 187, 189, 187, 36, 51, 40, 198, 36, 194, + 30, 115, 40, 150, 237, 71, 31, 16, 47, 91, 8, 237, 86, 219, + 148, 208, 119, 168, 133, 91, 143, 179, 22, 91, 93, 71, 22, 65, + 143, 148, 93, 78, 160, 110, 109, 224, 212, 176, 247, 70, 247, 4, + 93, 41, 187, 158, 243, 183, 15, 106, 89, 161, 45, 101, 68, 186, + 164, 153, 82, 2, 63, 160, 17, 214, 41, 97, 81, 68, 159, 165, + 7, 21, 183, 151, 73, 80, 147, 67, 55, 50, 235, 67, 135, 59, + 86, 186, 180, 30, 108, 182, 203, 173, 254, 43, 229, 250, 71, 174, + 54, 108, 101, 103, 59, 78, 39, 129, 194, 57, 111, 123, 145, 199, + 49, 207, 97, 203, 84, 184, 78, 10, 254, 39, 135, 2, 103, 23, + 104, 172, 36, 133, 150, 149, 16, 81, 214, 7, 236, 89, 146, 150, + 6, 111, 81, 58, 248, 161, 26, 156, 131, 208, 62, 146, 25, 8, + 181, 68, 155, 203, 54, 167, 168, 124, 216, 36, 133, 20, 209, 32, + 116, 110, 131, 49, 63, 233, 155, 125, 156, 235, 60, 226, 29, 225, + 243, 90, 79, 245, 119, 72, 14, 138, 231, 95, 98, 15, 229, 154, + 19, 100, 47, 204, 149, 166, 197, 10, 83, 24, 169, 225, 200, 3, + 241, 18, 203, 106, 220, 87, 237, 106, 96, 204, 137, 223, 106, 144, + 51, 47, 47, 107, 250, 11, 25, 5, 18, 58, 134, 189, 233, 115, + 53, 159, 103, 238, 67, 116, 7, 105, 119, 85, 237, 160, 2, 79, + 37, 18, 99, 180, 78, 158, 39, 234, 241, 129, 192, 54, 114, 159, + 57, 208, 141, 220, 233, 208, 5, 219, 146, 4, 25, 62, 11, 213, + 66, 189, 101, 2, 59, 74, 92, 133, 87, 53, 219, 228, 132, 139, + 19, 171, 205, 217, 33, 112, 84, 190, 38, 117, 227, 158, 140, 41, + 215, 119, 28, 152, 109, 123, 11, 10, 215, 96, 253, 238, 108, 171, + 101, 233, 97, 98, 221, 111, 52, 174, 166, 2, 140, 61, 160, 246, + 137, 168, 122, 182, 87, 44, 197, 74, 47, 111, 90, 89, 2, 125, + 98, 115, 98, 49, 146, 249, 191, 178, 94, 240, 16, 211, 131, 182, + 208, 138, 66, 180, 148, 118, 134, 98, 44, 76, 190, 87, 51, 49, + 95, 94, 221, 237, 23, 231, 236, 188, 217, 199, 208, 28, 238, 225, + 84, 24, 185, 49, 142, 205, 175, 193, 63, 249, 17, 0, 49, 139, + 190, 130, 178, 2, 19, 206, 5, 165, 14, 146, 141, 183, 148, 238, + 108, 221, 16, 54, 8, 183, 93, 110, 78, 6, 227, 196, 117, 138, + 22, 98, 212, 252, 248, 1, 23, 98, 252, 198, 11, 175, 239, 37, + 171, 249, 208, 202, 216, 241, 120, 208, 137, 144, 97, 163, 206, 250, + 178, 238, 203, 178, 145, 241, 0, 77, 251, 65, 142, 58, 249, 5, + 17, 126, 84, 250, 106, 62, 94, 171, 88, 248, 66, 52, 225, 238, + 240, 254, 111, 95, 129, 139, 16, 68, 146, 13, 153, 191, 178, 184, + 224, 60, 12, 249, 240, 90, 233, 106, 181, 39, 143, 104, 244, 223, + 230, 215, 216, 233, 201, 125, 119, 218, 172, 65, 168, 137, 216, 98, + 37, 76, 154, 139, 58, 203, 58, 2, 1, 199, 54, 203, 163, 185, + 221, 108, 37, 130, 156, 109, 252, 96, 3, 149, 29, 134, 228, 61, + 3, 143, 112, 114, 149, 133, 127, 97, 81, 236, 192, 7, 64, 185, + 237, 59, 64, 50, 168, 125, 32, 12, 223, 180, 229, 0, 92, 208, + 127, 55, 116, 213, 254, 237, 176, 234, 26, 74, 67, 2, 26, 210, + 220, 103, 181, 229, 208, 247, 229, 135, 81, 185, 160, 58, 131, 23, + 207, 22, 108, 203, 159, 56, 158, 61, 108, 234, 69, 109, 60, 121, + 226, 110, 128, 176, 57, 196, 3, 123, 75, 211, 251, 35, 252, 85, + 208, 178, 155, 183, 172, 199, 117, 151, 157, 113, 239, 205, 164, 198, + 74, 153, 87, 77, 153, 172, 254, 83, 136, 181, 27, 204, 53, 126, + 3, 73, 2, 186, 89, 180, 182, 208, 116, 10, 138, 71, 80, 191, + 96, 17, 168, 179, 45, 64, 58, 202, 96, 236, 212, 74, 103, 186, + 154, 20, 64, 109, 183, 13, 173, 200, 158, 102, 156, 59, 225, 241, + 137, 209, 255, 251, 122, 110, 84, 89, 109, 11, 120, 86, 208, 14, + 231, 199, 169, 49, 114, 253, 179, 97, 33, 95, 16, 163, 255, 133, + 196, 201, 209, 59, 41, 137, 103, 70, 15, 11, 222, 30, 58, 251, + 33, 190, 150, 221, 36, 171, 89, 252, 23, 111, 177, 245, 170, 155, + 96, 182, 189, 232, 90, 130, 196, 179, 184, 125, 156, 167, 26, 232, + 132, 245, 72, 161, 30, 36, 176, 203, 220, 187, 98, 15, 100, 100, + 130, 191, 147, 114, 208, 99, 97, 218, 166, 34, 181, 30, 56, 175, + 176, 183, 93, 144, 137, 172, 138, 245, 135, 171, 139, 146, 242, 78, + 33, 104, 6, 98, 166, 150, 179, 78, 79, 234, 163, 230, 184, 79, + 168, 179, 198, 169, 101, 22, 169, 34, 141, 107, 154, 162, 87, 126, + 47, 29, 238, 151, 125, 100, 244, 227, 140, 210, 146, 162, 30, 174, + 202, 178, 128, 234, 97, 65, 233, 79, 24, 190, 192, 157, 115, 196, + 224, 98, 109, 30, 209, 102, 188, 158, 160, 200, 157, 94, 223, 174, + 92, 155, 166, 99, 94, 196, 81, 148, 46, 137, 243, 169, 126, 67, + 42, 167, 45, 34, 125, 133, 234, 194, 5, 71, 139, 212, 128, 75, + 151, 32, 93, 49, 243, 168, 118, 29, 88, 149, 122, 70, 145, 167, + 2, 18, 118, 59, 128, 194, 41, 145, 194, 143, 242, 5, 119, 122, + 178, 241, 110, 230, 181, 253, 189, 23, 222, 82, 59, 127, 66, 65, + 213, 109, 176, 102, 85, 117, 127, 119, 34, 205, 181, 6, 221, 137, + 83, 83, 12, 246, 223, 116, 69, 3, 126, 242, 104, 71, 92, 183, + 89, 67, 67, 38, 231, 115, 214, 101, 237, 209, 250, 51, 82, 86, + 127, 41, 116, 7, 186, 96, 113, 97, 130, 137, 116, 197, 144, 20, + 230, 234, 82, 185, 154, 64, 96, 54, 191, 39, 114, 16, 168, 207, + 172, 72, 107, 9, 44, 86, 123, 238, 115, 27, 219, 105, 135, 82, + 50, 219, 40, 233, 19, 88, 63, 177, 163, 109, 50, 205, 241, 74, + 36, 158, 142, 234, 139, 70, 165, 72, 18, 37, 167, 252, 179, 29, + 96, 238, 214, 44, 248, 4, 159, 69, 26, 143, 49, 119, 137, 102, + 154, 114, 102, 23, 225, 81, 170, 19, 100, 122, 44, 214, 145, 87, + 21, 208, 43, 191, 127, 101, 115, 176, 78, 207, 252, 188, 250, 63, + 29, 146, 66, 110, 232, 145, 244, 235, 156, 216, 45, 159, 93, 183, + 44, 208, 19, 33, 165, 103, 19, 47, 158, 162, 134, 92, 41, 132, + 84, 43, 7, 6, 19, 68, 170, 42, 50, 54, 3, 10, 241, 236, + 75, 177, 105, 238, 80, 123, 185, 43, 120, 21, 145, 74, 150, 83, + 148, 201, 36, 195, 223, 131, 249, 35, 62, 133, 156, 135, 122, 214, + 133, 235, 201, 239, 124, 97, 227, 14, 81, 114, 158, 47, 170, 44, + 246, 162, 85, 225, 59, 57, 32, 10, 60, 89, 96, 58, 179, 144, + 213, 13, 229, 0, 105, 179, 201, 119, 168, 98, 82, 59, 216, 138, + 83, 154, 61, 206, 120, 132, 47, 157, 207, 199, 44, 185, 216, 150, + 164, 106, 179, 207, 55, 81, 125, 21, 124, 70, 68, 248, 48, 112, + 110, 21, 229, 127, 112, 94, 101, 52, 111, 59, 50, 66, 237, 220, + 226, 167, 197, 112, 104, 115, 94, 246, 163, 91, 223, 13, 15, 27, + 215, 220, 230, 163, 22, 183, 255, 9, 2, 97, 136, 61, 4, 16, + 22, 30, 136, 133, 10, 180, 234, 41, 215, 214, 48, 151, 251, 190, + 148, 100, 204, 2, 176, 143, 230, 93, 204, 68, 126, 10, 17, 182, + 242, 43, 14, 159, 47, 136, 8, 137, 165, 86, 128, 104, 229, 144, + 104, 36, 41, 189, 58, 179, 106, 111, 77, 124, 115, 74, 17, 75, + 70, 52, 157, 200, 190, 104, 111, 10, 163, 164, 130, 217, 31, 106, + 144, 170, 120, 122, 201, 161, 132, 235, 66, 243, 200, 117, 201, 235, + 84, 32, 185, 36, 74, 173, 251, 243, 143, 110, 79, 166, 97, 44, + 187, 128, 38, 216, 127, 81, 110, 144, 141, 78, 242, 112, 167, 194, + 155, 205, 178, 193, 188, 68, 38, 156, 17, 73, 215, 38, 79, 4, + 13, 142, 184, 99, 87, 158, 48, 65, 13, 97, 8, 25, 87, 196, + 138, 196, 149, 115, 77, 39, 102, 13, 29, 68, 108, 141, 36, 252, + 27, 88, 121, 205, 7, 63, 58, 144, 86, 5, 1, 243, 47, 158, + 30, 214, 151, 253, 88, 83, 87, 226, 53, 166, 107, 113, 43, 190, + 129, 5, 209, 12, 82, 14, 61, 207, 119, 203, 148, 38, 68, 151, + 196, 82, 211, 50, 238, 242, 85, 242, 108, 146, 236, 182, 251, 13, + 207, 83, 205, 19, 151, 19, 143, 3, 238, 18, 157, 104, 71, 232, + 104, 213, 119, 7, 128, 185, 197, 43, 122, 5, 16, 104, 62, 9, + 122, 120, 72, 18, 147, 191, 167, 92, 148, 44, 159, 33, 93, 62, + 252, 217, 232, 12, 143, 242, 88, 131, 65, 227, 174, 251, 14, 122, + 62, 126, 165, 106, 13, 22, 44, 110, 192, 233, 73, 111, 214, 162, + 158, 131, 154, 126, 133, 114, 97, 108, 132, 217, 150, 172, 46, 213, + 54, 207, 152, 18, 255, 164, 60, 211, 246, 166, 19, 125, 132, 108, + 95, 234, 107, 100, 48, 136, 61, 109, 146, 125, 98, 166, 248, 48, + 25, 221, 5, 129, 255, 218, 36, 214, 110, 60, 192, 27, 217, 44, + 187, 155, 250, 120, 47, 99, 140, 171, 196, 138, 92, 125, 51, 67, + 82, 181, 174, 115, 17, 62, 103, 109, 238, 30, 148, 137, 58, 147, + 131, 146, 237, 249, 189, 64, 99, 39, 229, 40, 22, 70, 30, 11, + 61, 103, 123, 118, 14, 64, 27, 18, 3, 5, 104, 159, 237, 18, + 42, 193, 23, 216, 189, 101, 226, 180, 198, 191, 219, 227, 122, 84, + 3, 44, 207, 214, 150, 241, 243, 96, 136, 21, 143, 139, 139, 230, + 123, 130, 106, 66, 132, 253, 255, 250, 210, 175, 235, 255, 24, 251, + 3, 15, 198, 37, 94, 178, 160, 29, 49, 24, 53, 28, 2, 236, + 102, 169, 67, 11, 220, 162, 182, 3, 160, 28, 167, 13, 241, 203, + 247, 58, 66, 153, 155, 134, 105, 3, 165, 115, 238, 162, 219, 186, + 104, 228, 45, 228, 93, 2, 34, 91, 114, 211, 213, 161, 174, 221, + 214, 120, 178, 187, 179, 55, 94, 14, 242, 217, 118, 29, 252, 172, + 36, 164, 180, 216, 107, 132, 2, 185, 62, 199, 71, 217, 33, 13, + 181, 42, 237, 87, 70, 37, 149, 87, 123, 250, 18, 25, 101, 84, + 200, 84, 172, 146, 229, 234, 161, 7, 8, 106, 9, 209, 132, 249, + 64, 49, 210, 103, 118, 75, 236, 131, 115, 217, 25, 102, 205, 178, + 11, 164, 177, 231, 167, 77, 80, 186, 150, 150, 203, 249, 190, 126, + 104, 191, 102, 242, 75, 211, 137, 216, 0, 113, 170, 108, 107, 63, + 7, 1, 182, 2, 52, 130, 2, 51, 16, 221, 237, 60, 23, 11, + 98, 111, 222, 105, 123, 189, 101, 144, 38, 107, 106, 88, 227, 229, + 34, 55, 153, 32, 143, 122, 233, 78, 230, 70, 195, 206, 255, 25, + 94, 36, 174, 65, 13, 75, 11, 153, 203, 186, 56, 221, 66, 158, + 38, 144, 163, 185, 101, 242, 192, 140, 136, 71, 137, 147, 57, 32, + 100, 135, 115, 147, 245, 233, 97, 40, 26, 114, 5, 206, 27, 184, + 199, 49, 42, 154, 178, 165, 152, 151, 212, 222, 104, 131, 20, 55, + 195, 255, 136, 159, 141, 153, 201, 92, 250, 199, 170, 247, 182, 157, + 70, 169, 99, 177, 207, 90, 155, 253, 122, 88, 68, 142, 103, 210, + 13, 205, 148, 24, 105, 164, 176, 125, 192, 188, 64, 158, 56, 3, + 242, 180, 53, 88, 254, 64, 252, 170, 86, 198, 218, 72, 7, 21, + 134, 67, 213, 89, 173, 252, 234, 33, 127, 117, 133, 99, 109, 23, + 193, 44, 46, 80, 10, 145, 163, 238, 180, 127, 233, 196, 63, 142, + 248, 56, 91, 121, 146, 97, 12, 161, 29, 133, 14, 4, 189, 33, + 7, 166, 0, 223, 94, 168, 254, 218, 13, 9, 65, 223, 65, 86, + 23, 151, 192, 115, 171, 137, 42, 189, 205, 23, 141, 192, 95, 151, + 238, 146, 239, 232, 170, 100, 224, 211, 166, 55, 72, 56, 173, 168, + 100, 152, 1, 6, 147, 99, 81, 238, 49, 235, 140, 179, 16, 235, + 177, 105, 74, 28, 2, 241, 80, 24, 21, 17, 122, 85, 1, 64, + 9, 48, 136, 217, 12, 102, 137, 249, 154, 32, 179, 71, 234, 137, + 139, 241, 244, 179, 216, 202, 174, 113, 214, 15, 20, 10, 3, 234, + 245, 114, 202, 115, 239, 205, 249, 90, 128, 9, 181, 222, 71, 8, + 146, 79, 100, 66, 161, 112, 35, 149, 115, 208, 0, 132, 119, 208, + 185, 27, 164, 211, 67, 203, 94, 27, 239, 66, 247, 99, 187, 47, + 118, 7, 23, 179, 78, 9, 194, 157, 167, 127, 195, 188, 13, 217, + 236, 127, 250, 213, 63, 5, 123, 209, 154, 131, 115, 204, 139, 205, + 50, 182, 4, 156, 66, 173, 82, 220, 164, 231, 72, 220, 164, 155, + 234, 251, 190, 32, 60, 234, 150, 69, 118, 121, 36, 134, 111, 183, + 197, 241, 196, 172, 50, 73, 200, 82, 243, 152, 73, 182, 128, 1, + 20, 2, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 13, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 13, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 13, 99, 108, 101, 97, 114, 116, 111, 109, + 97, 114, 107, 13, 128, 3, +}; diff --git a/Rendering/fonts/vtkEmbeddedFonts.h b/Rendering/fonts/vtkEmbeddedFonts.h new file mode 100644 index 0000000..ea10305 --- /dev/null +++ b/Rendering/fonts/vtkEmbeddedFonts.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEmbeddedFonts.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __vtkEmbeddedFonts_h +#define __vtkEmbeddedFonts_h + +#include + +// ----------------------------------------------------------------------- +// VTK: Arial Normal +// Gothic L Book (uagk8a.pfb) +// Contributed by URW + +extern size_t face_arial_buffer_length; +extern unsigned char face_arial_buffer[]; + +// VTK: Arial Bold +// Gothic L Demi (uagd8a.pfb) +// Contributed by URW + +extern size_t face_arial_bold_buffer_length; +extern unsigned char face_arial_bold_buffer[]; + +// VTK: Arial Bold Italic +// Gothic L Demi Oblique (uagdo8a.pfb) +// Contributed by URW + +extern size_t face_arial_bold_italic_buffer_length; +extern unsigned char face_arial_bold_italic_buffer[]; + +// VTK: Arial Italic +// Gothic L Book Oblique (uagko8a.pfb) +// Contributed by URW + +extern size_t face_arial_italic_buffer_length; +extern unsigned char face_arial_italic_buffer[]; + +// ----------------------------------------------------------------------- +// VTK: Courier Normal +// Courier 10 Pitch (c0419bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_courier_buffer_length; +extern unsigned char face_courier_buffer[]; + +// VTK: Courier Bold +// Courier 10 Pitch Bold (c0583bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_courier_bold_buffer_length; +extern unsigned char face_courier_bold_buffer[]; + +// VTK: Courier Bold Italic +// Courier 10 Pitch Bold Italic (c0611bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_courier_bold_italic_buffer_length; +extern unsigned char face_courier_bold_italic_buffer[]; + +// VTK: Courier Italic +// Courier 10 Pitch Regular Italic (c0582bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_courier_italic_buffer_length; +extern unsigned char face_courier_italic_buffer[]; + +// ----------------------------------------------------------------------- +// VTK: Times Normal +// Bitstream Charter (c0648bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_times_buffer_length; +extern unsigned char face_times_buffer[]; + +// VTK: Times Bold +// Bitstream Charter Bold (c0632bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_times_bold_buffer_length; +extern unsigned char face_times_bold_buffer[]; + +// VTK: Times Bold Italic +// Bitstream Charter Bold Italic (c0633bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_times_bold_italic_buffer_length; +extern unsigned char face_times_bold_italic_buffer[]; + +// VTK: Times Italic +// Bitstream Charter Regular Italic (c0649bt_.pfb) +// Contributed by Bitstream (XFree86) + +extern size_t face_times_italic_buffer_length; +extern unsigned char face_times_italic_buffer[]; + +#endif diff --git a/Rendering/vtkAbstractMapper3D.cxx b/Rendering/vtkAbstractMapper3D.cxx new file mode 100644 index 0000000..96a9ac1 --- /dev/null +++ b/Rendering/vtkAbstractMapper3D.cxx @@ -0,0 +1,67 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractMapper3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAbstractMapper3D.h" +#include "vtkDataSet.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkAbstractMapper3D, "$Revision: 1.19 $"); + +// Construct with initial range (0,1). +vtkAbstractMapper3D::vtkAbstractMapper3D() +{ + vtkMath::UninitializeBounds(this->Bounds); + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; +} + +// Get the bounds for this Prop as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +void vtkAbstractMapper3D::GetBounds(double bounds[6]) +{ + this->GetBounds(); + for (int i=0; i<6; i++) + { + bounds[i] = this->Bounds[i]; + } +} + +double *vtkAbstractMapper3D::GetCenter() +{ + this->GetBounds(); + for (int i=0; i<3; i++) + { + this->Center[i] = (this->Bounds[2*i+1] + this->Bounds[2*i]) / 2.0; + } + return this->Center; +} + +double vtkAbstractMapper3D::GetLength() +{ + double diff, l=0.0; + int i; + + this->GetBounds(); + for (i=0; i<3; i++) + { + diff = this->Bounds[2*i+1] - this->Bounds[2*i]; + l += diff * diff; + } + + return sqrt(l); +} + +void vtkAbstractMapper3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Rendering/vtkAbstractMapper3D.h b/Rendering/vtkAbstractMapper3D.h new file mode 100644 index 0000000..d080370 --- /dev/null +++ b/Rendering/vtkAbstractMapper3D.h @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractMapper3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAbstractMapper3D - abstract class specifies interface to map 3D data +// .SECTION Description +// vtkAbstractMapper3D is an abstract class to specify interface between 3D +// data and graphics primitives or software rendering techniques. Subclasses +// of vtkAbstractMapper3D can be used for rendering geometry or rendering +// volumetric data. +// +// This class also defines an API to support hardware clipping planes (at most +// six planes can be defined). It also provides geometric data about the input +// data it maps, such as the bounding box and center. +// +// .SECTION See Also +// vtkAbstractMapper vtkMapper vtkPolyDataMapper vtkVolumeMapper + +#ifndef __vtkAbstractMapper3D_h +#define __vtkAbstractMapper3D_h + +#include "vtkAbstractMapper.h" + +class vtkWindow; +class vtkDataSet; + +class VTK_RENDERING_EXPORT vtkAbstractMapper3D : public vtkAbstractMapper +{ +public: + vtkTypeRevisionMacro(vtkAbstractMapper3D,vtkAbstractMapper); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return bounding box (array of six doubles) of data expressed as + // (xmin,xmax, ymin,ymax, zmin,zmax). + virtual double *GetBounds()=0; + + // Description: + // Get the bounds for this mapper as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). + virtual void GetBounds(double bounds[6]); + + // Description: + // Return the Center of this mapper's data. + double *GetCenter(); + void GetCenter(double center[3]) + { + double *rc = this->GetCenter(); + center[0] = rc[0]; center[1] = rc[1]; center[2] = rc[2]; + }; + + // Description: + // Return the diagonal length of this mappers bounding box. + double GetLength(); + + // Description: + // Is this a ray cast mapper? A subclass would return 1 if the + // ray caster is needed to generate an image from this mapper. + virtual int IsARayCastMapper() {return 0;}; + + // Description: + // Is this a "render into image" mapper? A subclass would return 1 if the + // mapper produces an image by rendering into a software image buffer. + virtual int IsARenderIntoImageMapper() {return 0;}; + +protected: + vtkAbstractMapper3D(); + ~vtkAbstractMapper3D() {}; + + double Bounds[6]; + double Center[3]; + +private: + vtkAbstractMapper3D(const vtkAbstractMapper3D&); // Not implemented. + void operator=(const vtkAbstractMapper3D&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkAbstractPicker.cxx b/Rendering/vtkAbstractPicker.cxx new file mode 100644 index 0000000..3960b86 --- /dev/null +++ b/Rendering/vtkAbstractPicker.cxx @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractPicker.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAbstractPicker.h" + +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkAbstractPicker, "$Revision: 1.11 $"); + +// Construct object with initial tolerance of 1/40th of window. There are no +// pick methods and picking is performed from the renderer's actors. +vtkAbstractPicker::vtkAbstractPicker() +{ + this->Renderer = NULL; + + this->SelectionPoint[0] = 0.0; + this->SelectionPoint[1] = 0.0; + this->SelectionPoint[2] = 0.0; + + this->PickPosition[0] = 0.0; + this->PickPosition[1] = 0.0; + this->PickPosition[2] = 0.0; + + this->PickFromList = 0; + this->PickList = vtkPropCollection::New(); +} + +vtkAbstractPicker::~vtkAbstractPicker() +{ + this->PickList->Delete(); +} + +// Initialize the picking process. +void vtkAbstractPicker::Initialize() +{ + this->Renderer = NULL; + + this->SelectionPoint[0] = 0.0; + this->SelectionPoint[1] = 0.0; + this->SelectionPoint[2] = 0.0; + + this->PickPosition[0] = 0.0; + this->PickPosition[1] = 0.0; + this->PickPosition[2] = 0.0; +} + +// Initialize list of actors in pick list. +void vtkAbstractPicker::InitializePickList() +{ + this->Modified(); + this->PickList->RemoveAllItems(); +} + +// Add an actor to the pick list. +void vtkAbstractPicker::AddPickList(vtkProp *a) +{ + this->Modified(); + this->PickList->AddItem(a); +} + +// Delete an actor from the pick list. +void vtkAbstractPicker::DeletePickList(vtkProp *a) +{ + this->Modified(); + this->PickList->RemoveItem(a); +} + +void vtkAbstractPicker::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->PickFromList ) + { + os << indent << "Picking from list\n"; + } + else + { + os << indent << "Picking from renderer's prop list\n"; + } + + os << indent << "Renderer: " << this->Renderer << "\n"; + + os << indent << "Selection Point: (" << this->SelectionPoint[0] << "," + << this->SelectionPoint[1] << "," + << this->SelectionPoint[2] << ")\n"; + + os << indent << "Pick Position: (" << this->PickPosition[0] << "," + << this->PickPosition[1] << "," + << this->PickPosition[2] << ")\n"; +} diff --git a/Rendering/vtkAbstractPicker.h b/Rendering/vtkAbstractPicker.h new file mode 100644 index 0000000..955632c --- /dev/null +++ b/Rendering/vtkAbstractPicker.h @@ -0,0 +1,141 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractPicker.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAbstractPicker - define API for picking subclasses +// .SECTION Description +// vtkAbstractPicker is an abstract superclass that defines a minimal API +// for its concrete subclasses. The minimum functionality of a picker is +// to return the x-y-z global coordinate position of a pick (the pick +// itself is defined in display coordinates). +// +// The API to this class is to invoke the Pick() method with a selection +// point (in display coordinates - pixels) and a renderer. Then get the +// resulting pick position in global coordinates with the GetPickPosition() +// method. +// +// vtkPicker fires events during the picking process. These +// events are StartPickEvent, PickEvent, and EndPickEvent which are +// invoked prior to picking, when something is picked, and after all picking +// candidates have been tested. Note that during the pick process the +// PickEvent of vtkProp (and its subclasses such as vtkActor) is fired +// prior to the PickEvent of vtkPicker. + +// .SECTION Caveats +// vtkAbstractPicker and its subclasses will not pick props that are +// "unpickable" (see vtkProp) or are fully transparent (if transparency +// is a property of the vtkProp). +// +// There are two classes of pickers: those that pick using geometric methods +// (typically a ray cast); and those that use rendering hardware. Geometric +// methods return more information but are slower. Hardware methods are much +// faster and return minimal information. Examples of geometric pickers +// include vtkPicker, vtkCellPicker, and vtkPointPicker. Examples of hardware +// pickers include vtkWorldPointPicker and vtkPropPicker. + +// .SECTION See Also +// vtkPropPicker uses hardware acceleration to pick an instance of vtkProp. +// (This means that 2D and 3D props can be picked, and it's relatively fast.) +// If you need to pick cells or points, you might wish to use vtkCellPicker +// or vtkPointPicker. vtkWorldPointPicker is the fastest picker, returning +// an x-y-z coordinate value using the hardware z-buffer. vtkPicker can be +// used to pick the bounding box of 3D props. + +#ifndef __vtkAbstractPicker_h +#define __vtkAbstractPicker_h + +#include "vtkObject.h" + +class vtkRenderer; +class vtkProp; +class vtkPropCollection; + +class VTK_RENDERING_EXPORT vtkAbstractPicker : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkAbstractPicker,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the renderer in which pick event occurred. + vtkGetObjectMacro(Renderer,vtkRenderer); + + // Description: + // Get the selection point in screen (pixel) coordinates. The third + // value is related to z-buffer depth. (Normally should be =0.) + vtkGetVectorMacro(SelectionPoint,double,3); + + // Description: + // Return position in global coordinates of pick point. + vtkGetVectorMacro(PickPosition,double,3); + + // Description: + // Perform pick operation with selection point provided. Normally the + // first two values for the selection point are x-y pixel coordinate, and + // the third value is =0. Return non-zero if something was successfully + // picked. + virtual int Pick(double selectionX, double selectionY, double selectionZ, + vtkRenderer *renderer) = 0; + + // Description: Perform pick operation with selection point + // provided. Normally the first two values for the selection point + // are x-y pixel coordinate, and the third value is =0. Return + // non-zero if something was successfully picked. + int Pick(double selectionPt[3], vtkRenderer *ren) + {return this->Pick(selectionPt[0],selectionPt[1],selectionPt[2],ren);}; + + // Description: + // Use these methods to control whether to limit the picking to this list + // (rather than renderer's actors). Make sure that the pick list contains + // actors that referred to by the picker's renderer. + vtkSetMacro(PickFromList,int); + vtkGetMacro(PickFromList,int); + vtkBooleanMacro(PickFromList,int); + + // Description: + // Initialize list of actors in pick list. + void InitializePickList(); + + // Description: + // Add an actor to the pick list. + void AddPickList(vtkProp *); + + // Description: + // Delete an actor from the pick list. + void DeletePickList(vtkProp *); + + // Description: + // Return the list of actors in the PickList. + vtkPropCollection *GetPickList() {return this->PickList;} + +protected: + vtkAbstractPicker(); + ~vtkAbstractPicker(); + + virtual void Initialize(); + + vtkRenderer *Renderer; //pick occurred in this renderer's viewport + double SelectionPoint[3]; //selection point in window (pixel) coordinates + double PickPosition[3]; //selection point in world coordinates + + // use the following to control picking from a list + int PickFromList; + vtkPropCollection *PickList; +private: + vtkAbstractPicker(const vtkAbstractPicker&); // Not implemented. + void operator=(const vtkAbstractPicker&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkAbstractPropPicker.cxx b/Rendering/vtkAbstractPropPicker.cxx new file mode 100644 index 0000000..1fdc8f9 --- /dev/null +++ b/Rendering/vtkAbstractPropPicker.cxx @@ -0,0 +1,191 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractPropPicker.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAbstractPropPicker.h" + +#include "vtkActor.h" +#include "vtkActor2D.h" +#include "vtkAssembly.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkObjectFactory.h" +#include "vtkPropAssembly.h" +#include "vtkVolume.h" + +vtkCxxRevisionMacro(vtkAbstractPropPicker, "$Revision: 1.10.12.1 $"); + +vtkCxxSetObjectMacro(vtkAbstractPropPicker,Path,vtkAssemblyPath); + +vtkAbstractPropPicker::vtkAbstractPropPicker() +{ + this->Path = NULL; +} + +vtkAbstractPropPicker::~vtkAbstractPropPicker() +{ + if ( this->Path ) + { + this->Path->Delete(); + } +} + +// set up for a pick +void vtkAbstractPropPicker::Initialize() +{ + this->vtkAbstractPicker::Initialize(); + if ( this->Path ) + { + this->Path->Delete(); + this->Path = NULL; + } +} + +//---------------------------------------------------------------------------- +vtkProp* vtkAbstractPropPicker::GetViewProp() +{ + if ( this->Path != NULL ) + { + return this->Path->GetFirstNode()->GetViewProp(); + } + else + { + return NULL; + } +} + +vtkProp3D *vtkAbstractPropPicker::GetProp3D() +{ + if ( this->Path != NULL ) + { + vtkProp *prop = this->Path->GetFirstNode()->GetViewProp(); + return vtkProp3D::SafeDownCast(prop); + } + else + { + return NULL; + } +} + +vtkActor *vtkAbstractPropPicker::GetActor() +{ + if ( this->Path != NULL ) + { + vtkProp *prop = this->Path->GetFirstNode()->GetViewProp(); + return vtkActor::SafeDownCast(prop); + } + else + { + return NULL; + } +} + +vtkActor2D *vtkAbstractPropPicker::GetActor2D() +{ + if ( this->Path != NULL ) + { + vtkProp *prop = this->Path->GetFirstNode()->GetViewProp(); + return vtkActor2D::SafeDownCast(prop); + } + else + { + return NULL; + } +} + +vtkVolume *vtkAbstractPropPicker::GetVolume() +{ + if ( this->Path != NULL ) + { + vtkProp *prop = this->Path->GetFirstNode()->GetViewProp(); + return vtkVolume::SafeDownCast(prop); + } + else + { + return NULL; + } +} + +vtkAssembly *vtkAbstractPropPicker::GetAssembly() +{ + if ( this->Path != NULL ) + { + vtkProp *prop = this->Path->GetFirstNode()->GetViewProp(); + return vtkAssembly::SafeDownCast(prop); + } + else + { + return NULL; + } +} + +vtkPropAssembly *vtkAbstractPropPicker::GetPropAssembly() +{ + if ( this->Path != NULL ) + { + vtkProp *prop = this->Path->GetFirstNode()->GetViewProp(); + return vtkPropAssembly::SafeDownCast(prop); + } + else + { + return NULL; + } +} + +void vtkAbstractPropPicker::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + if ( this->Path ) + { + os << indent << "Path: " << this->Path << endl; + } + else + { + os << indent << "Path: (none)" << endl; + } +} + +//---------------------------------------------------------------------------- + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (disable:858) +#endif + +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetProp +vtkProp* const vtkAbstractPropPicker::GetPropA() +{ + VTK_LEGACY_REPLACED_BODY(vtkAbstractPropPicker::GetProp, "VTK 5.0", + vtkAbstractPropPicker::GetViewProp); + return this->GetViewProp(); +} +vtkProp* const vtkAbstractPropPicker::GetPropW() +{ + VTK_LEGACY_REPLACED_BODY(vtkAbstractPropPicker::GetProp, "VTK 5.0", + vtkAbstractPropPicker::GetViewProp); + return this->GetViewProp(); +} +# endif +vtkProp* const vtkAbstractPropPicker::GetProp() +{ + VTK_LEGACY_REPLACED_BODY(vtkAbstractPropPicker::GetProp, "VTK 5.0", + vtkAbstractPropPicker::GetViewProp); + return this->GetViewProp(); +} +#endif diff --git a/Rendering/vtkAbstractPropPicker.h b/Rendering/vtkAbstractPropPicker.h new file mode 100644 index 0000000..afe78b4 --- /dev/null +++ b/Rendering/vtkAbstractPropPicker.h @@ -0,0 +1,178 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractPropPicker.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAbstractPropPicker - abstract API for pickers that can pick an instance of vtkProp +// .SECTION Description +// vtkAbstractPropPicker is an abstract superclass for pickers that can pick +// an instance of vtkProp. Some pickers, like vtkWorldPointPicker (not a +// subclass of this class), cannot identify the prop that is +// picked. Subclasses of vtkAbstractPropPicker return a prop in the form of a +// vtkAssemblyPath when a pick is invoked. Note that an vtkAssemblyPath +// contain a list of vtkAssemblyNodes, each of which in turn contains a +// reference to a vtkProp and a 4x4 transformation matrix. The path fully +// describes the entire pick path, so you can pick assemblies or portions of +// assemblies, or just grab the tail end of the vtkAssemblyPath (which is the +// picked prop). + +// .SECTION Caveats +// Because a vtkProp can be placed into different assemblies, or even in +// different leaf positions of the same assembly, the vtkAssemblyPath is +// used to fully qualify exactly which use of the vtkProp was picked, +// including its position (since vtkAssemblyPath includes a transformation +// matrix per node). +// +// The class returns information about picked actors, props, etc. Note that +// what is returned by these methods is the top level of the assembly +// path. This can cause a lot of confusion! For example, if you pick a +// vtkAssembly, and the returned vtkAssemblyPath has as a leaf a vtkActor, +// then if you invoke GetActor(), you will get NULL, even though an actor was +// indeed picked. (GetAssembly() will return something.) Note that the safest +// thing to do is to do a GetViewProp(), which will always return something if +// something was picked. A better way to manage picking is to work with +// vtkAssemblyPath, since this completely defines the pick path from top to +// bottom in a assembly hierarchy, and avoids confusion when the same prop is +// used in different assemblies. +// +// The returned assembly paths refer to assembly nodes that in turn refer +// to vtkProp and vtkMatrix. This association to vtkProp is not a reference +// counted association, meaning that dangling references are possible if +// you do a pick, get an assembly path, and then delete a vtkProp. (Reason: +// assembly paths create many self-referencing loops that destroy reference +// counting.) + +// .SECTION See Also +// vtkPropPicker vtkPicker vtkWorldPointPicker vtkCellPicker vtkPointPicker +// vtkAssemblyPath vtkAssemblyNode vtkAssemblyPaths vtkAbstractPicker +// vtkRenderer + +#ifndef __vtkAbstractPropPicker_h +#define __vtkAbstractPropPicker_h + +#include "vtkAbstractPicker.h" + +class vtkProp; +class vtkPropAssembly; +class vtkAssembly; +class vtkActor; +class vtkVolume; +class vtkProp3D; +class vtkAssemblyPath; +class vtkActor2D; + +class VTK_RENDERING_EXPORT vtkAbstractPropPicker : public vtkAbstractPicker +{ +public: + vtkTypeRevisionMacro(vtkAbstractPropPicker,vtkAbstractPicker); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the vtkAssemblyPath that has been picked. The assembly path lists + // all the vtkProps that form an assembly. If no assembly is present, then + // the assembly path will have one node (which is the picked prop). The + // set method is used internally to set the path. (Note: the structure of + // an assembly path is a collection of vtkAssemblyNode, each node pointing + // to a vtkProp and (possibly) a transformation matrix.) + virtual void SetPath(vtkAssemblyPath*); + vtkGetObjectMacro(Path,vtkAssemblyPath); + + // The following are convenience methods to maintain API with older + // versions of VTK, and to allow query for the return type of a pick. Note: + // the functionality of these methods can also be obtained by using the + // returned vtkAssemblyPath and using the IsA() to determine type. + + // Description: + // Return the vtkProp that has been picked. If NULL, nothing was picked. + // If anything at all was picked, this method will return something. + virtual vtkProp* GetViewProp(); + + // Description: + // Return the vtkProp that has been picked. If NULL, no vtkProp3D was picked. + virtual vtkProp3D *GetProp3D(); + + // Description: + // Return the vtkActor that has been picked. If NULL, no actor was picked. + virtual vtkActor *GetActor(); + + // Description: + // Return the vtkActor2D that has been picked. If NULL, no actor2D was + // picked. + virtual vtkActor2D *GetActor2D(); + + // Description: + // Return the vtkVolume that has been picked. If NULL, no volume was picked. + virtual vtkVolume *GetVolume(); + + // Description: + // Return the vtkAssembly that has been picked. If NULL, no assembly + // was picked. (Note: the returned assembly is the first node in the + // assembly path. If the path is one node long, then the assembly and + // the prop are the same, assuming that the first node is a vtkAssembly.) + virtual vtkAssembly *GetAssembly(); + + // Description: + // Return the vtkPropAssembly that has been picked. If NULL, no prop + // assembly was picked. (Note: the returned prop assembly is the first node + // in the assembly path. If the path is one node long, then the prop + // assembly and the prop are the same, assuming that the first node is a + // vtkPropAssembly.) + virtual vtkPropAssembly *GetPropAssembly(); + +// Disable warnings about qualifiers on return types. +#if defined(_COMPILER_VERSION) +# pragma set woff 3303 +#endif +#if defined(__INTEL_COMPILER) +# pragma warning (push) +# pragma warning (disable:858) +#endif + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define GetPropA GetProp +# define GetPropW GetProp +#endif + + // Description: + // @deprecated Replaced by vtkAbstractPicker::GetViewProp() as of VTK 5.0. + VTK_LEGACY(virtual vtkProp* const GetProp()); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetPropW +# undef GetPropA + //BTX + VTK_LEGACY(virtual vtkProp* const GetPropA()); + VTK_LEGACY(virtual vtkProp* const GetPropW()); + //ETX +#endif + +// Reset disabled warning about qualifiers on return types. +#if defined(__INTEL_COMPILER) +# pragma warning (pop) +#endif +#if defined(_COMPILER_VERSION) +# pragma reset woff 3303 +#endif + +protected: + vtkAbstractPropPicker(); + ~vtkAbstractPropPicker(); + + void Initialize(); + + vtkAssemblyPath *Path; //this is what is picked, and includes the prop +private: + vtkAbstractPropPicker(const vtkAbstractPropPicker&); // Not implemented. + void operator=(const vtkAbstractPropPicker&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkAbstractVolumeMapper.cxx b/Rendering/vtkAbstractVolumeMapper.cxx new file mode 100644 index 0000000..8053925 --- /dev/null +++ b/Rendering/vtkAbstractVolumeMapper.cxx @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractVolumeMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAbstractVolumeMapper.h" + +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkAbstractVolumeMapper, "$Revision: 1.6 $"); + +// Construct a vtkAbstractVolumeMapper +vtkAbstractVolumeMapper::vtkAbstractVolumeMapper() +{ + vtkMath::UninitializeBounds(this->Bounds); + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; +} + +vtkAbstractVolumeMapper::~vtkAbstractVolumeMapper() +{ +} + +// Get the bounds for the input of this mapper as +// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkAbstractVolumeMapper::GetBounds() +{ + static double bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0}; + + if ( ! this->GetDataSetInput() ) + { + return bounds; + } + else + { + this->Update(); + this->GetDataSetInput()->GetBounds(this->Bounds); + return this->Bounds; + } +} + +vtkDataSet *vtkAbstractVolumeMapper::GetDataSetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkDataSet::SafeDownCast(this->GetExecutive()->GetInputData(0, 0)); +} + +void vtkAbstractVolumeMapper::SetInput( vtkDataSet *vtkNotUsed(input) ) +{ + vtkErrorMacro("Cannot set the input on the abstract volume mapper" + " - must be set on a subclass" ); +} + +//---------------------------------------------------------------------------- +int vtkAbstractVolumeMapper::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +// Print the vtkAbstractVolumeMapper +void vtkAbstractVolumeMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/Rendering/vtkAbstractVolumeMapper.h b/Rendering/vtkAbstractVolumeMapper.h new file mode 100644 index 0000000..4f48e49 --- /dev/null +++ b/Rendering/vtkAbstractVolumeMapper.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAbstractVolumeMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAbstractVolumeMapper - Abstract class for a volume mapper + +// .SECTION Description +// vtkAbstractVolumeMapper is the abstract definition of a volume mapper. +// Specific subclasses deal with different specific types of data input + +// .SECTION see also +// vtkVolumeMapper vtkUnstructuredGridVolumeMapper + +#ifndef __vtkAbstractVolumeMapper_h +#define __vtkAbstractVolumeMapper_h + +#include "vtkAbstractMapper3D.h" + +class vtkRenderer; +class vtkVolume; +class vtkWindow; +class vtkDataSet; + +class VTK_RENDERING_EXPORT vtkAbstractVolumeMapper : public vtkAbstractMapper3D +{ +public: + vtkTypeRevisionMacro(vtkAbstractVolumeMapper,vtkAbstractMapper3D); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set/Get the input data + virtual void SetInput( vtkDataSet * ); + vtkDataSet *GetDataSetInput(); + + // Description: + // Return bounding box (array of six doubles) of data expressed as + // (xmin,xmax, ymin,ymax, zmin,zmax). + virtual double *GetBounds(); + virtual void GetBounds(double bounds[6]) + { this->vtkAbstractMapper3D::GetBounds(bounds); }; + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + virtual float GetGradientMagnitudeScale() {return 1.0;}; + virtual float GetGradientMagnitudeBias() {return 0.0;}; + virtual float GetGradientMagnitudeScale(int) {return 1.0;}; + virtual float GetGradientMagnitudeBias(int) {return 0.0;}; + + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol)=0; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *) {}; + +//ETX + +protected: + vtkAbstractVolumeMapper(); + ~vtkAbstractVolumeMapper(); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkAbstractVolumeMapper(const vtkAbstractVolumeMapper&); // Not implemented. + void operator=(const vtkAbstractVolumeMapper&); // Not implemented. +}; + + +#endif + + diff --git a/Rendering/vtkActor.cxx b/Rendering/vtkActor.cxx new file mode 100644 index 0000000..cf51253 --- /dev/null +++ b/Rendering/vtkActor.cxx @@ -0,0 +1,523 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" + +#include "vtkAssemblyPaths.h" +#include "vtkGraphicsFactory.h" +#include "vtkImageData.h" +#include "vtkLinearTransform.h" +#include "vtkMapper.h" +#include "vtkMath.h" +#include "vtkPointData.h" +#include "vtkPropCollection.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTexture.h" +#include "vtkTransform.h" + +#include + +vtkCxxRevisionMacro(vtkActor, "$Revision: 1.126 $"); + +vtkCxxSetObjectMacro(vtkActor,Texture,vtkTexture); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkActor); + + +// Creates an actor with the following defaults: origin(0,0,0) +// position=(0,0,0) scale=(1,1,1) visibility=1 pickable=1 dragable=1 +// orientation=(0,0,0). No user defined matrix and no texture map. +vtkActor::vtkActor() +{ + this->Mapper = NULL; + this->Property = NULL; + this->BackfaceProperty = NULL; + this->Texture = NULL; + + // The mapper bounds are cache to know when the bounds must be recomputed + // from the mapper bounds. + vtkMath::UninitializeBounds(this->MapperBounds); +} + +vtkActor::~vtkActor() +{ + if ( this->Property != NULL) + { + this->Property->UnRegister(this); + this->Property = NULL; + } + + if ( this->BackfaceProperty != NULL) + { + this->BackfaceProperty->UnRegister(this); + this->BackfaceProperty = NULL; + } + + if (this->Mapper) + { + this->Mapper->UnRegister(this); + this->Mapper = NULL; + } + this->SetTexture(NULL); +} + +// Shallow copy of an actor. +void vtkActor::ShallowCopy(vtkProp *prop) +{ + vtkActor *a = vtkActor::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetMapper(a->GetMapper()); + this->SetProperty(a->GetProperty()); + this->SetBackfaceProperty(a->GetBackfaceProperty()); + this->SetTexture(a->GetTexture()); + } + + // Now do superclass + this->vtkProp3D::ShallowCopy(prop); +} + +// return the correct type of Actor +vtkActor *vtkActor::New() +{ + // First try to create the object from the vtkGraphicsFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkActor"); + return (vtkActor*)ret; +} + +void vtkActor::GetActors(vtkPropCollection *ac) +{ + ac->AddItem(this); +} + +// should be called from the render methods only +int vtkActor::GetIsOpaque() +{ + if (this->Property->GetOpacity() >= 1.0) + { + if (this->Texture && this->Texture->GetInput()) + { + this->Texture->GetInput()->UpdateInformation(); + this->Texture->GetInput()->SetUpdateExtent(this->Texture->GetInput()->GetWholeExtent()); + this->Texture->GetInput()->PropagateUpdateExtent(); + this->Texture->GetInput()->TriggerAsynchronousUpdate(); + this->Texture->GetInput()->UpdateData(); + if (this->Texture->GetInput()->GetPointData()->GetScalars() == NULL) + { // Handle gracefully. What should it return? + return 1; + } + if (this->Texture->GetInput()->GetPointData()->GetScalars()->GetNumberOfComponents()%2) + { + return 1; + } + } + else + { + return 1; + } + } + return 0; +} + + +// This causes the actor to be rendered. It in turn will render the actor's +// property, texture map and then mapper. If a property hasn't been +// assigned, then the actor will create one automatically. Note that a +// side effect of this method is that the visualization network is updated. +int vtkActor::RenderOpaqueGeometry(vtkViewport *vp) +{ + int renderedSomething = 0; + vtkRenderer* ren = static_cast(vp); + + if ( ! this->Mapper ) + { + return 0; + } + + // make sure we have a property + if (!this->Property) + { + // force creation of a property + this->GetProperty(); + } + + // is this actor opaque ? + if (this->GetIsOpaque()) + { + this->Property->Render(this, ren); + + // render the backface property + if (this->BackfaceProperty) + { + this->BackfaceProperty->BackfaceRender(this, ren); + } + + // render the texture + if (this->Texture) + { + this->Texture->Render(ren); + } + this->Render(ren,this->Mapper); + this->EstimatedRenderTime += this->Mapper->GetTimeToDraw(); + + renderedSomething = 1; + } + + return renderedSomething; +} + +int vtkActor::RenderTranslucentGeometry(vtkViewport *vp) +{ + int renderedSomething = 0; + vtkRenderer* ren = static_cast(vp); + + if ( ! this->Mapper ) + { + return 0; + } + + // make sure we have a property + if (!this->Property) + { + // force creation of a property + this->GetProperty(); + } + + // is this actor opaque ? + if (!this->GetIsOpaque()) + { + this->Property->Render(this, ren); + + // render the backface property + if (this->BackfaceProperty) + { + this->BackfaceProperty->BackfaceRender(this, ren); + } + + // render the texture + if (this->Texture) + { + this->Texture->Render(ren); + } + this->Render(ren,this->Mapper); + this->EstimatedRenderTime += this->Mapper->GetTimeToDraw(); + + renderedSomething = 1; + } + + return renderedSomething; +} + +void vtkActor::ReleaseGraphicsResources(vtkWindow *win) +{ + vtkRenderWindow *renWin = (vtkRenderWindow *)win; + + // pass this information onto the mapper + if (this->Mapper) + { + this->Mapper->ReleaseGraphicsResources(renWin); + } + + // pass this information onto the texture + if (this->Texture) + { + this->Texture->ReleaseGraphicsResources(renWin); + } +} + +void vtkActor::SetProperty(vtkProperty *lut) +{ + if ( this->Property == lut) + { + return; + } + if ( this->Property != NULL) + { + this->Property->UnRegister(this); + this->Property = NULL; + } + if ( lut != NULL) + { + lut->Register(this); + } + + this->Property = lut; + this->Modified(); +} + +vtkProperty* vtkActor::MakeProperty() +{ + return vtkProperty::New(); +} + + +vtkProperty *vtkActor::GetProperty() +{ + if ( this->Property == NULL ) + { + vtkProperty *p = this->MakeProperty(); + this->SetProperty(p); + p->Delete(); + } + return this->Property; +} + +void vtkActor::SetBackfaceProperty(vtkProperty *lut) +{ + if ( this->BackfaceProperty == lut) + { + return; + } + if ( this->BackfaceProperty != NULL) + { + this->BackfaceProperty->UnRegister(this); + this->BackfaceProperty = NULL; + } + if ( lut != NULL) + { + lut->Register(this); + } + + this->BackfaceProperty = lut; + this->Modified(); +} + +vtkProperty *vtkActor::GetBackfaceProperty() +{ + return this->BackfaceProperty; +} + +// Get the bounds for this Actor as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkActor::GetBounds() +{ + int i,n; + double *bounds, bbox[24], *fptr; + + vtkDebugMacro( << "Getting Bounds" ); + + // get the bounds of the Mapper if we have one + if (!this->Mapper) + { + return this->Bounds; + } + + bounds = this->Mapper->GetBounds(); + // Check for the special case when the mapper's bounds are unknown + if (!bounds) + { + return bounds; + } + + // Check for the special case when the actor is empty. + if (!vtkMath::AreBoundsInitialized(bounds)) + { + memcpy( this->MapperBounds, bounds, 6*sizeof(double) ); + vtkMath::UninitializeBounds(this->Bounds); + this->BoundsMTime.Modified(); + return this->Bounds; + } + + // Check if we have cached values for these bounds - we cache the + // values returned by this->Mapper->GetBounds() and we store the time + // of caching. If the values returned this time are different, or + // the modified time of this class is newer than the cached time, + // then we need to rebuild. + if ( ( memcmp( this->MapperBounds, bounds, 6*sizeof(double) ) != 0 ) || + ( this->GetMTime() > this->BoundsMTime ) ) + { + vtkDebugMacro( << "Recomputing bounds..." ); + + memcpy( this->MapperBounds, bounds, 6*sizeof(double) ); + + // fill out vertices of a bounding box + bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5]; + bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5]; + bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5]; + bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5]; + bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4]; + bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4]; + bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4]; + bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4]; + + // save the old transform + this->Transform->Push(); + this->Transform->SetMatrix(this->GetMatrix()); + + // and transform into actors coordinates + fptr = bbox; + for (n = 0; n < 8; n++) + { + this->Transform->TransformPoint(fptr,fptr); + fptr += 3; + } + + this->Transform->Pop(); + + // now calc the new bounds + this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX; + this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX; + for (i = 0; i < 8; i++) + { + for (n = 0; n < 3; n++) + { + if (bbox[i*3+n] < this->Bounds[n*2]) + { + this->Bounds[n*2] = bbox[i*3+n]; + } + if (bbox[i*3+n] > this->Bounds[n*2+1]) + { + this->Bounds[n*2+1] = bbox[i*3+n]; + } + } + } + this->BoundsMTime.Modified(); + } + + return this->Bounds; +} + +unsigned long int vtkActor::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Property != NULL ) + { + time = this->Property->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->BackfaceProperty != NULL ) + { + time = this->BackfaceProperty->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->Texture != NULL ) + { + time = this->Texture->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +unsigned long int vtkActor::GetRedrawMTime() +{ + unsigned long mTime=this->GetMTime(); + unsigned long time; + + if ( this->Mapper != NULL ) + { + time = this->Mapper->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + if (this->GetMapper()->GetInput() != NULL) + { + this->GetMapper()->GetInput()->Update(); + time = this->Mapper->GetInput()->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + } + + return mTime; +} + +void vtkActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Mapper ) + { + os << indent << "Mapper:\n"; + this->Mapper->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Mapper: (none)\n"; + } + + if ( this->Property ) + { + os << indent << "Property:\n"; + this->Property->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Property: (none)\n"; + } + + if ( this->Texture ) + { + os << indent << "Texture: " << this->Texture << "\n"; + } + else + { + os << indent << "Texture: (none)\n"; + } + +} + +// Compatibility methods...to be deprecated in the future. +#include "vtkAssemblyNode.h" +void vtkActor::InitPartTraversal() +{ + this->InitPathTraversal(); +} + +vtkActor *vtkActor::GetNextPart() +{ + vtkAssemblyPath *path = this->GetNextPath(); + if ( !path ) + { + return NULL; + } + else + { + vtkAssemblyNode *node = path->GetLastNode(); + if ( node && node->GetViewProp()->IsA("vtkActor") ) + { + return (vtkActor *)node->GetViewProp(); + } + } + return NULL; +} + +int vtkActor::GetNumberOfParts() +{ + return this->GetNumberOfPaths(); +} + + +void vtkActor::SetMapper(vtkMapper *args) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this + << "): setting Mapper to " << args ); + if (this->Mapper != args) + { + if (this->Mapper != NULL) + { + this->Mapper->UnRegister(this); + } + this->Mapper = args; + if (this->Mapper != NULL) + { + this->Mapper->Register(this); + } + this->Modified(); + } +} diff --git a/Rendering/vtkActor.h b/Rendering/vtkActor.h new file mode 100644 index 0000000..911bb5d --- /dev/null +++ b/Rendering/vtkActor.h @@ -0,0 +1,180 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkActor - represents an object (geometry & properties) in a rendered scene +// .SECTION Description +// +// vtkActor is used to represent an entity in a rendering scene. It inherits +// functions related to the actors position, and orientation from +// vtkProp. The actor also has scaling and maintains a reference to the +// defining geometry (i.e., the mapper), rendering properties, and possibly a +// texture map. vtkActor combines these instance variables into one 4x4 +// transformation matrix as follows: [x y z 1] = [x y z 1] Translate(-origin) +// Scale(scale) Rot(y) Rot(x) Rot (z) Trans(origin) Trans(position) + +// .SECTION See Also +// vtkProperty vtkTexture vtkMapper vtkAssembly vtkFollower vtkLODActor + +#ifndef __vtkActor_h +#define __vtkActor_h + +#include "vtkProp3D.h" + +class vtkRenderer; +class vtkPropCollection; +class vtkActorCollection; +class vtkTexture; +class vtkMapper; +class vtkProperty; + +class VTK_RENDERING_EXPORT vtkActor : public vtkProp3D +{ +public: + vtkTypeRevisionMacro(vtkActor,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates an actor with the following defaults: origin(0,0,0) + // position=(0,0,0) scale=(1,1,1) visibility=1 pickable=1 dragable=1 + // orientation=(0,0,0). No user defined matrix and no texture map. + static vtkActor *New(); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. These methods + // are used in that process. + virtual void GetActors(vtkPropCollection *); + + // Description: + // Support the standard render methods. + virtual int RenderOpaqueGeometry(vtkViewport *viewport); + virtual int RenderTranslucentGeometry(vtkViewport *viewport); + + // Description: + // This causes the actor to be rendered. It in turn will render the actor's + // property, texture map and then mapper. If a property hasn't been + // assigned, then the actor will create one automatically. Note that a side + // effect of this method is that the pipeline will be updated. + virtual void Render(vtkRenderer *, vtkMapper *) {}; + + // Description: + // Shallow copy of an actor. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Set/Get the property object that controls this actors surface + // properties. This should be an instance of a vtkProperty object. Every + // actor must have a property associated with it. If one isn't specified, + // then one will be generated automatically. Multiple actors can share one + // property object. + void SetProperty(vtkProperty *lut); + vtkProperty *GetProperty(); + + // Description: + // Create a new property sutible for use with this type of Actor. + // For example, a vtkMesaActor should create a vtkMesaProperty + // in this function. The default is to just call vtkProperty::New. + virtual vtkProperty* MakeProperty(); + + // Description: + // Set/Get the property object that controls this actors backface surface + // properties. This should be an instance of a vtkProperty object. If one + // isn't specified, then the front face properties will be used. Multiple + // actors can share one property object. + void SetBackfaceProperty(vtkProperty *lut); + vtkProperty *GetBackfaceProperty(); + + // Description: + // Set/Get the texture object to control rendering texture maps. This will + // be a vtkTexture object. An actor does not need to have an associated + // texture map and multiple actors can share one texture. + virtual void SetTexture(vtkTexture*); + vtkGetObjectMacro(Texture,vtkTexture); + + // Description: + // This is the method that is used to connect an actor to the end of a + // visualization pipeline, i.e. the mapper. This should be a subclass + // of vtkMapper. Typically vtkPolyDataMapper and vtkDataSetMapper will + // be used. + virtual void SetMapper(vtkMapper *); + + // Description: + // Returns the Mapper that this actor is getting its data from. + vtkGetObjectMacro(Mapper,vtkMapper); + + // Description: + // Get the bounds for this Actor as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). (The + // method GetBounds(double bounds[6]) is available from the superclass.) + void GetBounds(double bounds[6]) {this->vtkProp3D::GetBounds( bounds );}; + double *GetBounds(); + + // Description: + // Apply the current properties to all parts that compose this actor. + // This method is overloaded in vtkAssembly to apply the assemblies' + // properties to all its parts in a recursive manner. Typically the + // use of this method is to set the desired properties in the assembly, + // and then push the properties down to the assemblies parts with + // ApplyProperties(). + virtual void ApplyProperties() {return;}; + + // Description: + // Get the actors mtime plus consider its properties and texture if set. + unsigned long int GetMTime(); + + // Description: + // Return the mtime of anything that would cause the rendered image to + // appear differently. Usually this involves checking the mtime of the + // prop plus anything else it depends on such as properties, textures + // etc. + virtual unsigned long GetRedrawMTime(); + + // Description: + // The following methods are for compatibility. The methods will be deprecated + // in the near future. Use vtkProp::GetNextPath() (and related functionality) + // to get the parts in an assembly (or more correctly, the paths in the + // assembly). + virtual void InitPartTraversal(); + virtual vtkActor *GetNextPart(); + virtual int GetNumberOfParts(); + +protected: + vtkActor(); + ~vtkActor(); + + vtkProperty *Property; + vtkProperty *BackfaceProperty; + vtkTexture *Texture; + vtkMapper *Mapper; + + // is this actor opaque + int GetIsOpaque(); + + // Bounds are cached in an actor - the MapperBounds are also cache to + // help know when the Bounds need to be recomputed. + double MapperBounds[6]; + vtkTimeStamp BoundsMTime; + +private: + vtkActor(const vtkActor&); // Not implemented. + void operator=(const vtkActor&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkActorCollection.cxx b/Rendering/vtkActorCollection.cxx new file mode 100644 index 0000000..01be8ad --- /dev/null +++ b/Rendering/vtkActorCollection.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActorCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActorCollection.h" + +#include "vtkObjectFactory.h" +#include "vtkProperty.h" + +vtkCxxRevisionMacro(vtkActorCollection, "$Revision: 1.12 $"); +vtkStandardNewMacro(vtkActorCollection); + +void vtkActorCollection::ApplyProperties(vtkProperty *p) +{ + vtkActor *actor; + + if ( p == NULL ) + { + return; + } + + vtkCollectionSimpleIterator ait; + for ( this->InitTraversal(ait); (actor=this->GetNextActor(ait)); ) + { + actor->GetProperty()->DeepCopy(p); + } +} + +//---------------------------------------------------------------------------- +void vtkActorCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkActorCollection.h b/Rendering/vtkActorCollection.h new file mode 100644 index 0000000..c890f4b --- /dev/null +++ b/Rendering/vtkActorCollection.h @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkActorCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkActorCollection - a list of actors +// .SECTION Description +// vtkActorCollection represents and provides methods to manipulate a list of +// actors (i.e., vtkActor and subclasses). The list is unsorted and duplicate +// entries are not prevented. + +// .SECTION see also +// vtkActor vtkCollection + +#ifndef __vtkActorC_h +#define __vtkActorC_h + +#include "vtkPropCollection.h" +#include "vtkActor.h" // For inline methods + +class vtkProperty; + +class VTK_RENDERING_EXPORT vtkActorCollection : public vtkPropCollection +{ +public: + static vtkActorCollection *New(); + vtkTypeRevisionMacro(vtkActorCollection,vtkPropCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add an actor to the list. + void AddItem(vtkActor *a); + + // Description: + // Get the next actor in the list. + vtkActor *GetNextActor(); + + // Description: + // Get the last actor in the list. + vtkActor *GetLastActor(); + + // Description: + // Access routines that are provided for compatibility with previous + // version of VTK. Please use the GetNextActor(), GetLastActor() variants + // where possible. + vtkActor *GetNextItem(); + vtkActor *GetLastItem(); + + // Description: + // Apply properties to all actors in this collection. + void ApplyProperties(vtkProperty *p); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkActor *GetNextActor(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkActorCollection() {}; + ~vtkActorCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + void AddItem(vtkProp *o) { this->vtkPropCollection::AddItem(o); }; + +private: + vtkActorCollection(const vtkActorCollection&); // Not implemented. + void operator=(const vtkActorCollection&); // Not implemented. +}; + +inline void vtkActorCollection::AddItem(vtkActor *a) +{ + this->vtkCollection::AddItem((vtkObject *)a); +} + +inline vtkActor *vtkActorCollection::GetNextActor() +{ + return static_cast(this->GetNextItemAsObject()); +} + +inline vtkActor *vtkActorCollection::GetLastActor() +{ + if ( this->Bottom == NULL ) + { + return NULL; + } + else + { + return static_cast(this->Bottom->Item); + } +} + +inline vtkActor *vtkActorCollection::GetNextItem() +{ + return this->GetNextActor(); +} + +inline vtkActor *vtkActorCollection::GetLastItem() +{ + return this->GetLastActor(); +} + +#endif + + + + + diff --git a/Rendering/vtkAssembly.cxx b/Rendering/vtkAssembly.cxx new file mode 100644 index 0000000..ac4791f --- /dev/null +++ b/Rendering/vtkAssembly.cxx @@ -0,0 +1,378 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssembly.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAssembly.h" +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPaths.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkProp3DCollection.h" +#include "vtkRenderWindow.h" +#include "vtkVolume.h" + +vtkCxxRevisionMacro(vtkAssembly, "$Revision: 1.57 $"); +vtkStandardNewMacro(vtkAssembly); + +// Construct object with no children. +vtkAssembly::vtkAssembly() +{ + this->Parts = vtkProp3DCollection::New(); +} + +vtkAssembly::~vtkAssembly() +{ + this->Parts->Delete(); + this->Parts = NULL; +} + +// Add a part to the list of Parts. +void vtkAssembly::AddPart(vtkProp3D *prop) +{ + if ( ! this->Parts->IsItemPresent(prop) ) + { + this->Parts->AddItem(prop); + this->Modified(); + } +} + +// Remove a part from the list of parts, +void vtkAssembly::RemovePart(vtkProp3D *prop) +{ + if ( this->Parts->IsItemPresent(prop) ) + { + this->Parts->RemoveItem(prop); + this->Modified(); + } +} + +// Shallow copy another assembly. +void vtkAssembly::ShallowCopy(vtkProp *prop) +{ + vtkAssembly *a = vtkAssembly::SafeDownCast(prop); + if ( a != NULL ) + { + this->Parts->RemoveAllItems(); + vtkCollectionSimpleIterator pit; + a->Parts->InitTraversal(pit); + for (int i=0; i<0; i++) + { + this->Parts->AddItem(a->Parts->GetNextProp3D(pit)); + } + } + + // Now do superclass + this->vtkProp3D::ShallowCopy(prop); +} + +// Render this assembly and all its Parts. The rendering process is recursive. +// Note that a mapper need not be defined. If not defined, then no geometry +// will be drawn for this assembly. This allows you to create "logical" +// assemblies; that is, assemblies that only serve to group and transform +// its Parts. +int vtkAssembly::RenderTranslucentGeometry(vtkViewport *ren) +{ + vtkProp3D *prop3D; + vtkAssemblyPath *path; + double fraction; + int renderedSomething = 0; + + this->UpdatePaths(); + + // for allocating render time between components + // simple equal allocation + fraction = this->AllocatedRenderTime + / (double)(this->Paths->GetNumberOfItems()); + + // render the Paths + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp(); + if ( prop3D->GetVisibility() ) + { + prop3D->SetAllocatedRenderTime(fraction, ren); + prop3D->PokeMatrix(path->GetLastNode()->GetMatrix()); + renderedSomething += prop3D->RenderTranslucentGeometry(ren); + prop3D->PokeMatrix(NULL); + } + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + + return renderedSomething; +} + + +// Render this assembly and all its Parts. The rendering process is recursive. +// Note that a mapper need not be defined. If not defined, then no geometry +// will be drawn for this assembly. This allows you to create "logical" +// assemblies; that is, assemblies that only serve to group and transform +// its Parts. +int vtkAssembly::RenderOpaqueGeometry(vtkViewport *ren) +{ + vtkProp3D *prop3D; + vtkAssemblyPath *path; + double fraction; + int renderedSomething = 0; + + this->UpdatePaths(); + + // for allocating render time between components + // simple equal allocation + fraction = this->AllocatedRenderTime + / (double)(this->Paths->GetNumberOfItems()); + + // render the Paths + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp(); + if ( prop3D->GetVisibility() ) + { + prop3D->PokeMatrix(path->GetLastNode()->GetMatrix()); + prop3D->SetAllocatedRenderTime(fraction, ren); + renderedSomething += prop3D->RenderOpaqueGeometry(ren); + prop3D->PokeMatrix(NULL); + } + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + + return renderedSomething; +} + +void vtkAssembly::ReleaseGraphicsResources(vtkWindow *renWin) +{ + vtkProp3D *prop3D; + + vtkCollectionSimpleIterator pit; + for ( this->Parts->InitTraversal(pit); + (prop3D = this->Parts->GetNextProp3D(pit)); ) + { + prop3D->ReleaseGraphicsResources(renWin); + } +} + +void vtkAssembly::GetActors(vtkPropCollection *ac) +{ + vtkProp3D *prop3D; + vtkActor *actor; + vtkAssemblyPath *path; + + this->UpdatePaths(); + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp(); + if ( (actor = vtkActor::SafeDownCast(prop3D)) != NULL ) + { + ac->AddItem(actor); + } + } +} + +void vtkAssembly::GetVolumes(vtkPropCollection *ac) +{ + vtkProp3D *prop3D; + vtkVolume *volume; + vtkAssemblyPath *path; + + this->UpdatePaths(); + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp(); + if ( (volume = vtkVolume::SafeDownCast(prop3D)) != NULL ) + { + ac->AddItem(volume); + } + } +} + +void vtkAssembly::InitPathTraversal() +{ + this->UpdatePaths(); + this->Paths->InitTraversal(); +} + +// Return the next part in the hierarchy of assembly Parts. This method +// returns a properly transformed and updated actor. +vtkAssemblyPath *vtkAssembly::GetNextPath() +{ + if ( this->Paths ) + { + return this->Paths->GetNextItem(); + } + else + { + return NULL; + } +} + +int vtkAssembly::GetNumberOfPaths() +{ + this->UpdatePaths(); + return this->Paths->GetNumberOfItems(); +} + +// Build the assembly paths if necessary. UpdatePaths() +// is only called when the assembly is at the root +// of the hierarchy; otherwise UpdatePaths() is called. +void vtkAssembly::UpdatePaths() +{ + if ( this->GetMTime() > this->PathTime || + (this->Paths != NULL && this->Paths->GetMTime() > this->PathTime) ) + { + if ( this->Paths != NULL ) + { + this->Paths->Delete(); + this->Paths = NULL; + } + + // Create the list to hold all the paths + this->Paths = vtkAssemblyPaths::New(); + vtkAssemblyPath *path = vtkAssemblyPath::New(); + + //add ourselves to the path to start things off + path->AddNode(this,this->GetMatrix()); + + // Add nodes as we proceed down the hierarchy + vtkProp3D *prop3D; + vtkCollectionSimpleIterator pit; + for ( this->Parts->InitTraversal(pit); + (prop3D = this->Parts->GetNextProp3D(pit)); ) + { + path->AddNode(prop3D,prop3D->GetMatrix()); + + // dive into the hierarchy + prop3D->BuildPaths(this->Paths,path); + + // when returned, pop the last node off of the + // current path + path->DeleteLastNode(); + } + + path->Delete(); + this->PathTime.Modified(); + } +} + +// Build assembly paths from this current assembly. A path consists of +// an ordered sequence of props, with transformations properly concatenated. +void vtkAssembly::BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path) +{ + vtkProp3D *prop3D; + + vtkCollectionSimpleIterator pit; + for ( this->Parts->InitTraversal(pit); + (prop3D = this->Parts->GetNextProp3D(pit)); ) + { + path->AddNode(prop3D,prop3D->GetMatrix()); + + // dive into the hierarchy + prop3D->BuildPaths(paths,path); + + // when returned, pop the last node off of the + // current path + path->DeleteLastNode(); + } +} + +// Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkAssembly::GetBounds() +{ + vtkProp3D *prop3D; + vtkAssemblyPath *path; + int i, n; + double *bounds, bbox[24]; + int propVisible=0; + + this->UpdatePaths(); + + // now calculate the new bounds + this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX; + this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX; + + vtkCollectionSimpleIterator sit; + for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); ) + { + prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp(); + if ( prop3D->GetVisibility() ) + { + propVisible = 1; + prop3D->PokeMatrix(path->GetLastNode()->GetMatrix()); + bounds = prop3D->GetBounds(); + prop3D->PokeMatrix(NULL); + + // fill out vertices of a bounding box + bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5]; + bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5]; + bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5]; + bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5]; + bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4]; + bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4]; + bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4]; + bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4]; + + for (i = 0; i < 8; i++) + { + for (n = 0; n < 3; n++) + { + if (bbox[i*3+n] < this->Bounds[n*2]) + { + this->Bounds[n*2] = bbox[i*3+n]; + } + if (bbox[i*3+n] > this->Bounds[n*2+1]) + { + this->Bounds[n*2+1] = bbox[i*3+n]; + } + }//for each coordinate axis + }//for each point of box + }//if visible && prop3d + }//for each path + + if ( ! propVisible ) + { + vtkMath::UninitializeBounds(this->Bounds); + } + + return this->Bounds; +} + +unsigned long int vtkAssembly::GetMTime() +{ + unsigned long mTime=this->vtkProp3D::GetMTime(); + unsigned long time; + vtkProp3D *prop; + + vtkCollectionSimpleIterator pit; + for (this->Parts->InitTraversal(pit); + (prop = this->Parts->GetNextProp3D(pit)); ) + { + time = prop->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +void vtkAssembly::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "There are: " << this->Parts->GetNumberOfItems() + << " parts in this assembly\n"; +} + diff --git a/Rendering/vtkAssembly.h b/Rendering/vtkAssembly.h new file mode 100644 index 0000000..a1c7525 --- /dev/null +++ b/Rendering/vtkAssembly.h @@ -0,0 +1,169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAssembly.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAssembly - create hierarchies of vtkProp3Ds (transformable props) +// .SECTION Description +// vtkAssembly is an object that groups vtkProp3Ds, its subclasses, and +// other assemblies into a tree-like hierarchy. The vtkProp3Ds and +// assemblies can then be transformed together by transforming just the root +// assembly of the hierarchy. +// +// A vtkAssembly object can be used in place of an vtkProp3D since it is a +// subclass of vtkProp3D. The difference is that vtkAssembly maintains a list +// of vtkProp3D instances (its "parts") that form the assembly. Then, any +// operation that transforms (i.e., scales, rotates, translates) the parent +// assembly will transform all its parts. Note that this process is +// recursive: you can create groups consisting of assemblies and/or +// vtkProp3Ds to arbitrary depth. +// +// To add an assembly to the renderer's list of props, you only need to +// add the root of the assembly. During rendering, the parts of the +// assembly are rendered during a hierarchical traversal process. + +// .SECTION Caveats +// Collections of assemblies are slower to render than an equivalent list +// of actors. This is because to support arbitrary nesting of assemblies, +// the state of the assemblies (i.e., transformation matrices) must +// be propagated through the assembly hierarchy. +// +// Assemblies can consist of hierarchies of assemblies, where one actor or +// assembly used in one hierarchy is also used in other hierarchies. However, +// make that there are no cycles (e.g., parent->child->parent), this will +// cause program failure. +// +// If you wish to create assemblies without any transformation (using the +// assembly strictly as a grouping mechanism), then you may wish to +// consider using vtkPropAssembly. + +// .SECTION See Also +// vtkActor vtkTransform vtkMapper vtkPolyDataMapper vtkPropAssembly + +#ifndef __vtkAssembly_h +#define __vtkAssembly_h + +#include "vtkProp3D.h" + +class vtkAssemblyPaths; +class vtkProp3DCollection; +class vtkMapper; +class vtkProperty; +class vtkActor; + +class VTK_RENDERING_EXPORT vtkAssembly : public vtkProp3D +{ +public: + static vtkAssembly *New(); + + vtkTypeRevisionMacro(vtkAssembly,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a part to the list of parts. + void AddPart(vtkProp3D *); + + // Description: + // Remove a part from the list of parts, + void RemovePart(vtkProp3D *); + + // Description: + // Return the parts (direct descendants) of this assembly. + vtkProp3DCollection *GetParts(); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. These methods + // are used in that process. + void GetActors(vtkPropCollection *); + void GetVolumes(vtkPropCollection *); + + // Description: + // Render this assembly and all its parts. + // The rendering process is recursive. + // Note that a mapper need not be defined. If not defined, then no geometry + // will be drawn for this assembly. This allows you to create "logical" + // assemblies; that is, assemblies that only serve to group and transform + // its parts. + int RenderOpaqueGeometry(vtkViewport *ren); + int RenderTranslucentGeometry(vtkViewport *ren); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Methods to traverse the parts of an assembly. Each part (starting from + // the root) will appear properly transformed and with the correct + // properties (depending upon the ApplyProperty and ApplyTransform ivars). + // Note that the part appears as an instance of vtkProp. These methods + // should be contrasted to those that traverse the list of parts using + // GetParts(). GetParts() returns a list of children of this assembly, not + // necessarily with the correct transformation or properties. To use the + // methods below - first invoke InitPathTraversal() followed by repeated + // calls to GetNextPath(). GetNextPath() returns a NULL pointer when the + // list is exhausted. + void InitPathTraversal(); + vtkAssemblyPath *GetNextPath(); + int GetNumberOfPaths(); + + // Description: + // Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). + void GetBounds(double bounds[6]) {this->vtkProp3D::GetBounds( bounds );}; + double *GetBounds(); + + // Description: + // Override default GetMTime method to also consider all of the + // assembly's parts. + unsigned long int GetMTime(); + + // Description: + // Shallow copy of an assembly. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE DO NOT USE THIS + // METHOD OUTSIDE OF THE RENDERING PROCESS Overload the superclass' vtkProp + // BuildPaths() method. Paths consist of an ordered sequence of actors, + // with transformations properly concatenated. + void BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path); +//ETX + +protected: + vtkAssembly(); + ~vtkAssembly(); + + // Keep a list of direct descendants of the assembly hierarchy + vtkProp3DCollection *Parts; + + // Support the BuildPaths() method. Caches last paths built for + // performance. + vtkTimeStamp PathTime; + virtual void UpdatePaths(); //apply transformations and properties recursively + +private: + vtkAssembly(const vtkAssembly&); // Not implemented. + void operator=(const vtkAssembly&); // Not implemented. +}; + +// Description: +// Get the list of parts for this assembly. +inline vtkProp3DCollection *vtkAssembly::GetParts() {return this->Parts;} + +#endif + + + + diff --git a/Rendering/vtkAxisActor2D.cxx b/Rendering/vtkAxisActor2D.cxx new file mode 100644 index 0000000..be4899f --- /dev/null +++ b/Rendering/vtkAxisActor2D.cxx @@ -0,0 +1,921 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAxisActor2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAxisActor2D.h" + +#include "vtkCellArray.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" +#include "vtkWindow.h" + +vtkCxxRevisionMacro(vtkAxisActor2D, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkAxisActor2D); + +vtkCxxSetObjectMacro(vtkAxisActor2D,LabelTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(vtkAxisActor2D,TitleTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Instantiate this object. +vtkAxisActor2D::vtkAxisActor2D() +{ + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.0, 0.0); + + this->Position2Coordinate->SetCoordinateSystemToNormalizedViewport(); + this->Position2Coordinate->SetValue(0.75, 0.0); + this->Position2Coordinate->SetReferenceCoordinate(NULL); + + this->NumberOfLabels = 5; + + this->Title = NULL; + + this->AdjustLabels = 1; + + this->TickLength = 5; + this->TickOffset = 2; + + this->Range[0] = 0.0; + this->Range[1] = 1.0; + + this->FontFactor = 1.0; + this->LabelFactor = 0.75; + + this->LabelTextProperty = vtkTextProperty::New(); + this->LabelTextProperty->SetBold(1); + this->LabelTextProperty->SetItalic(1); + this->LabelTextProperty->SetShadow(1); + this->LabelTextProperty->SetFontFamilyToArial(); + + this->TitleTextProperty = vtkTextProperty::New(); + this->TitleTextProperty->ShallowCopy(this->LabelTextProperty); + + this->LabelFormat = new char[8]; + sprintf(this->LabelFormat,"%s","%-#6.3g"); + + this->TitleMapper = vtkTextMapper::New(); + this->TitleActor = vtkActor2D::New(); + this->TitleActor->SetMapper(this->TitleMapper); + + // To avoid deleting/rebuilding create once up front + + this->NumberOfLabelsBuilt = 0; + this->LabelMappers = new vtkTextMapper * [VTK_MAX_LABELS]; + this->LabelActors = new vtkActor2D * [VTK_MAX_LABELS]; + for ( int i=0; i < VTK_MAX_LABELS; i++) + { + this->LabelMappers[i] = vtkTextMapper::New(); + this->LabelActors[i] = vtkActor2D::New(); + this->LabelActors[i]->SetMapper(this->LabelMappers[i]); + } + + this->Axis = vtkPolyData::New(); + this->AxisMapper = vtkPolyDataMapper2D::New(); + this->AxisMapper->SetInput(this->Axis); + this->AxisActor = vtkActor2D::New(); + this->AxisActor->SetMapper(this->AxisMapper); + + this->AxisVisibility = 1; + this->TickVisibility = 1; + this->LabelVisibility = 1; + this->TitleVisibility = 1; + + this->LastPosition[0] = this->LastPosition[1] = 0; + this->LastPosition2[0] = this->LastPosition2[1] = 0; + + this->LastSize[0] = this->LastSize[1] = 0; + this->LastMaxLabelSize[0] = this->LastMaxLabelSize[1] = 0; +} + +//---------------------------------------------------------------------------- +vtkAxisActor2D::~vtkAxisActor2D() +{ + if (this->LabelFormat) + { + delete [] this->LabelFormat; + this->LabelFormat = NULL; + } + + this->TitleMapper->Delete(); + this->TitleActor->Delete(); + + if (this->Title) + { + delete [] this->Title; + this->Title = NULL; + } + + if (this->LabelMappers != NULL ) + { + for (int i=0; i < VTK_MAX_LABELS; i++) + { + this->LabelMappers[i]->Delete(); + this->LabelActors[i]->Delete(); + } + delete [] this->LabelMappers; + delete [] this->LabelActors; + } + + this->Axis->Delete(); + this->AxisMapper->Delete(); + this->AxisActor->Delete(); + + this->SetLabelTextProperty(NULL); + this->SetTitleTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +// Build the axis, ticks, title, and labels and render. + +int vtkAxisActor2D::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int i, renderedSomething=0; + + this->BuildAxis(viewport); + + // Everything is built, just have to render + if ( this->Title != NULL && this->Title[0] != 0 && this->TitleVisibility ) + { + renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport); + } + + if ( this->AxisVisibility || this->TickVisibility ) + { + renderedSomething += this->AxisActor->RenderOpaqueGeometry(viewport); + } + + if ( this->LabelVisibility ) + { + for (i=0; iNumberOfLabelsBuilt; i++) + { + renderedSomething += + this->LabelActors[i]->RenderOpaqueGeometry(viewport); + } + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +// Render the axis, ticks, title, and labels. + +int vtkAxisActor2D::RenderOverlay(vtkViewport *viewport) +{ + int i, renderedSomething=0; + + // Everything is built, just have to render + if ( this->Title != NULL && this->Title[0] != 0 && this->TitleVisibility ) + { + renderedSomething += this->TitleActor->RenderOverlay(viewport); + } + + if ( this->AxisVisibility || this->TickVisibility ) + { + renderedSomething += this->AxisActor->RenderOverlay(viewport); + } + + if ( this->LabelVisibility ) + { + for (i=0; iNumberOfLabelsBuilt; i++) + { + renderedSomething += this->LabelActors[i]->RenderOverlay(viewport); + } + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkAxisActor2D::ReleaseGraphicsResources(vtkWindow *win) +{ + this->TitleActor->ReleaseGraphicsResources(win); + for (int i=0; i < VTK_MAX_LABELS; i++) + { + this->LabelActors[i]->ReleaseGraphicsResources(win); + } + this->AxisActor->ReleaseGraphicsResources(win); +} + +//---------------------------------------------------------------------------- +void vtkAxisActor2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->TitleTextProperty) + { + os << indent << "Title Text Property:\n"; + this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Title Text Property: (none)\n"; + } + + if (this->LabelTextProperty) + { + os << indent << "Label Text Property:\n"; + this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Label Text Property: (none)\n"; + } + + os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n"; + os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n"; + os << indent << "Number Of Labels Built: " + << this->NumberOfLabelsBuilt << "\n"; + os << indent << "Range: (" << this->Range[0] + << ", " << this->Range[1] << ")\n"; + + os << indent << "Label Format: " << this->LabelFormat << "\n"; + os << indent << "Font Factor: " << this->FontFactor << "\n"; + os << indent << "Label Factor: " << this->LabelFactor << "\n"; + os << indent << "Tick Length: " << this->TickLength << "\n"; + os << indent << "Tick Offset: " << this->TickOffset << "\n"; + + os << indent << "Adjust Labels: " + << (this->AdjustLabels ? "On\n" : "Off\n"); + + os << indent << "Axis Visibility: " + << (this->AxisVisibility ? "On\n" : "Off\n"); + + os << indent << "Tick Visibility: " + << (this->TickVisibility ? "On\n" : "Off\n"); + + os << indent << "Label Visibility: " + << (this->LabelVisibility ? "On\n" : "Off\n"); + + os << indent << "Title Visibility: " + << (this->TitleVisibility ? "On\n" : "Off\n"); +} + +//---------------------------------------------------------------------------- +#define VTK_AA2D_DEBUG 0 + +void vtkAxisActor2D::BuildAxis(vtkViewport *viewport) +{ + int i, *x, viewportSizeHasChanged, positionsHaveChanged; + vtkIdType ptIds[2]; + double p1[3], p2[3], offset; + double interval, deltaX, deltaY; + double xTick[3]; + double theta, val; + int *size, stringSize[2]; + char string[512]; + + if (this->TitleVisibility && !this->TitleTextProperty) + { + vtkErrorMacro(<<"Need title text property to render axis actor"); + return; + } + + if (this->LabelVisibility && !this->LabelTextProperty) + { + vtkErrorMacro(<<"Need label text property to render axis actor"); + return; + } + + positionsHaveChanged = 0; + if (viewport->GetMTime() > this->BuildTime || + (viewport->GetVTKWindow() && + viewport->GetVTKWindow()->GetMTime() > this->BuildTime)) + { + // Check to see whether we have to rebuild everything + // Viewport change may not require rebuild + int *lastPosition = + this->PositionCoordinate->GetComputedViewportValue(viewport); + int *lastPosition2 = + this->Position2Coordinate->GetComputedViewportValue(viewport); + if (lastPosition[0] != this->LastPosition[0] || + lastPosition[1] != this->LastPosition[1] || + lastPosition2[0] != this->LastPosition2[0] || + lastPosition2[1] != this->LastPosition2[1] ) + { + positionsHaveChanged = 1; + } + } + + size = viewport->GetSize(); + + // See whether fonts have to be rebuilt (font size depends on viewport size) + + if (this->LastSize[0] != size[0] || this->LastSize[1] != size[1]) + { + viewportSizeHasChanged = 1; + this->LastSize[0] = size[0]; + this->LastSize[1] = size[1]; + } + else + { + viewportSizeHasChanged = 0; + } + + if (!positionsHaveChanged && !viewportSizeHasChanged && + this->GetMTime() < this->BuildTime && + (!this->LabelVisibility || + this->LabelTextProperty->GetMTime() < this->BuildTime) && + (!this->TitleVisibility || + this->TitleTextProperty->GetMTime() < this->BuildTime)) + { + return; + } + +#if VTK_AA2D_DEBUG + printf ("vtkAxisActor2D::BuildAxis: Rebuilding axis\n"); +#endif + + vtkDebugMacro(<<"Rebuilding axis"); + + // Initialize and get important info + + this->Axis->Initialize(); + this->AxisActor->SetProperty(this->GetProperty()); + this->TitleActor->SetProperty(this->GetProperty()); + + // Compute the location of tick marks and labels + + this->UpdateAdjustedRange(); + + interval = (this->AdjustedRange[1] - this->AdjustedRange[0]) / (this->AdjustedNumberOfLabels - 1); + + this->NumberOfLabelsBuilt = this->AdjustedNumberOfLabels; + + // Generate the axis and tick marks. + // We'll do our computation in viewport coordinates. First determine the + // location of the endpoints. + + x = this->PositionCoordinate->GetComputedViewportValue(viewport); + p1[0] = (double)x[0]; + p1[1] = (double)x[1]; + p1[2] = 0.0; + this->LastPosition[0] = x[0]; + this->LastPosition[1] = x[1]; + + x = this->Position2Coordinate->GetComputedViewportValue(viewport); + p2[0] = (double)x[0]; + p2[1] = (double)x[1]; + p2[2] = 0.0; + this->LastPosition2[0] = x[0]; + this->LastPosition2[1] = x[1]; + + vtkPoints *pts = vtkPoints::New(); + vtkCellArray *lines = vtkCellArray::New(); + this->Axis->SetPoints(pts); + this->Axis->SetLines(lines); + pts->Delete(); + lines->Delete(); + + // Generate point along axis (as well as tick points) + + deltaX = p2[0] - p1[0]; + deltaY = p2[1] - p1[1]; + + if (deltaX == 0. && deltaY == 0.) + { + theta = 0.; + } + else + { + theta = atan2(deltaY, deltaX); + } + + // First axis point + + ptIds[0] = pts->InsertNextPoint(p1); + xTick[0] = p1[0] + this->TickLength*sin(theta); + xTick[1] = p1[1] - this->TickLength*cos(theta); + xTick[2] = 0.0; + + pts->InsertNextPoint(xTick); + for (i = 1; i < this->AdjustedNumberOfLabels - 1; i++) + { + xTick[0] = p1[0] + i * (p2[0] - p1[0]) / (this->AdjustedNumberOfLabels - 1); + xTick[1] = p1[1] + i * (p2[1] - p1[1]) / (this->AdjustedNumberOfLabels - 1); + pts->InsertNextPoint(xTick); + xTick[0] = xTick[0] + this->TickLength * sin(theta); + xTick[1] = xTick[1] - this->TickLength * cos(theta); + pts->InsertNextPoint(xTick); + } + + // Last axis point + + ptIds[1] = pts->InsertNextPoint(p2); + xTick[0] = p2[0] + this->TickLength*sin(theta); + xTick[1] = p2[1] - this->TickLength*cos(theta); + pts->InsertNextPoint(xTick); + + if (this->AxisVisibility) + { + lines->InsertNextCell(2, ptIds); + } + + // Create points and lines + + if (this->TickVisibility) + { + for (i = 0; i < this->AdjustedNumberOfLabels; i++) + { + ptIds[0] = 2*i; + ptIds[1] = 2*i + 1; + lines->InsertNextCell(2, ptIds); + } + } + + // Build the labels + + if (this->LabelVisibility) + { + +#if VTK_AA2D_DEBUG + printf ("vtkAxisActor2D::BuildAxis: Rebuilding axis => labels\n"); +#endif + + // Update the labels text. Do it only if the range has been adjusted, + // i.e. if we think that new labels must be created. + // WARNING: if LabelFormat has changed, they should be recreated too + // but at this point the check on LabelFormat is "included" in + // UpdateAdjustedRange(), which is the function that update + // AdjustedRangeBuildTime or not. + + unsigned long labeltime = this->AdjustedRangeBuildTime; + if (this->AdjustedRangeBuildTime > this->BuildTime) + { + for (i = 0; i < this->AdjustedNumberOfLabels; i++) + { + val = this->AdjustedRange[0] + (double)i * interval; + sprintf(string, this->LabelFormat, val); + this->LabelMappers[i]->SetInput(string); + + // Check if the label text has changed + + if (this->LabelMappers[i]->GetMTime() > labeltime) + { + labeltime = this->LabelMappers[i]->GetMTime(); + } + } + } + + // Copy prop and text prop eventually + + for (i = 0; i < this->AdjustedNumberOfLabels; i++) + { + this->LabelActors[i]->SetProperty(this->GetProperty()); + if (this->LabelTextProperty->GetMTime() > this->BuildTime) + { + // Shallow copy here so that the size of the label prop is not + // affected by the automatic adjustment of its text mapper's + // size (i.e. its mapper's text property is identical except + // for the font size which will be modified later). This + // allows text actors to share the same text property, and in + // that case specifically allows the title and label text prop + // to be the same. + this->LabelMappers[i]->GetTextProperty()->ShallowCopy( + this->LabelTextProperty); + } + } + + // Resize the mappers if needed (i.e. viewport has changed, than + // font size should be changed, or label text property has changed, + // or some of the labels have changed (got bigger for example) + + if (viewportSizeHasChanged || + this->LabelTextProperty->GetMTime() > this->BuildTime || + labeltime > this->BuildTime) + { + this->SetMultipleFontSize(viewport, + this->LabelMappers, + this->AdjustedNumberOfLabels, + size, + this->FontFactor * this->LabelFactor, + this->LastMaxLabelSize); + } + + // Position the mappers + + for (i = 0; i < this->AdjustedNumberOfLabels; i++) + { + pts->GetPoint(2 * i + 1, xTick); + this->LabelMappers[i]->GetSize(viewport, stringSize); + this->SetOffsetPosition(xTick, + theta, + this->LastMaxLabelSize[0], + this->LastMaxLabelSize[1], + this->TickOffset, + this->LabelActors[i]); + } + } // If labels visible + + // Now build the title + + if (this->Title != NULL && this->Title[0] != 0 && this->TitleVisibility) + { +#if VTK_AA2D_DEBUG + printf ("vtkAxisActor2D::BuildAxis: Rebuilding axis => title\n"); +#endif + + this->TitleMapper->SetInput(this->Title); + + if (this->TitleTextProperty->GetMTime() > this->BuildTime) + { + // Shallow copy here so that the size of the title prop is not + // affected by the automatic adjustment of its text mapper's + // size (i.e. its mapper's text property is identical except for + // the font size which will be modified later). This allows text + // actors to share the same text property, and in that case + // specifically allows the title and label text prop to be the same. + this->TitleMapper->GetTextProperty()->ShallowCopy( + this->TitleTextProperty); + } + + if (viewportSizeHasChanged || + this->TitleTextProperty->GetMTime() > this->BuildTime) + { + this->SetFontSize(viewport, + this->TitleMapper, + size, + this->FontFactor, + stringSize); + } + else + { + this->TitleMapper->GetSize(viewport, stringSize); + } + + xTick[0] = p1[0] + (p2[0] - p1[0]) / 2.0; + xTick[1] = p1[1] + (p2[1] - p1[1]) / 2.0; + xTick[0] = xTick[0] + (this->TickLength + this->TickOffset) * sin(theta); + xTick[1] = xTick[1] - (this->TickLength + this->TickOffset) * cos(theta); + + offset = 0.0; + if (this->LabelVisibility) + { + offset = this->ComputeStringOffset(this->LastMaxLabelSize[0], + this->LastMaxLabelSize[1], + theta); + } + + this->SetOffsetPosition(xTick, + theta, + stringSize[0], + stringSize[1], + static_cast(offset), + this->TitleActor); + } // If title visible + + this->BuildTime.Modified(); +} + +//---------------------------------------------------------------------------- +#define VTK_AA2D_FACTOR 0.015 + +int vtkAxisActor2D::SetFontSize(vtkViewport *viewport, + vtkTextMapper *textMapper, + int *targetSize, + double factor, + int *stringSize) +{ + int fontSize, targetWidth, targetHeight; + + // Find the best size for the font + // WARNING: check that the above values are in sync with the above + // similar function. + + targetWidth = targetSize [0] > targetSize[1] ? targetSize[0] : targetSize[1]; + + targetHeight = (int)(VTK_AA2D_FACTOR * factor * targetSize[0] + + VTK_AA2D_FACTOR * factor * targetSize[1]); + + fontSize = textMapper->SetConstrainedFontSize(viewport, + targetWidth, targetHeight); + + textMapper->GetSize(viewport, stringSize); + + return fontSize; +} + +//---------------------------------------------------------------------------- +int vtkAxisActor2D::SetMultipleFontSize(vtkViewport *viewport, + vtkTextMapper **textMappers, + int nbOfMappers, + int *targetSize, + double factor, + int *stringSize) +{ + int fontSize, targetWidth, targetHeight; + + // Find the best size for the font + // WARNING: check that the below values are in sync with the above + // similar function. + + targetWidth = targetSize [0] > targetSize[1] ? targetSize[0] : targetSize[1]; + + targetHeight = (int)(VTK_AA2D_FACTOR * factor * targetSize[0] + + VTK_AA2D_FACTOR * factor * targetSize[1]); + + fontSize = + vtkTextMapper::SetMultipleConstrainedFontSize(viewport, + targetWidth, targetHeight, + textMappers, + nbOfMappers, + stringSize); + + return fontSize; +} +#undef VTK_AA2D_FACTOR + +//---------------------------------------------------------------------------- +void vtkAxisActor2D::UpdateAdjustedRange() +{ + // Try not to update/adjust the range to often, do not update it + // if the object has not been modified. + // Nevertheless, try the following optimization: there is no need to + // update the range if the position coordinate of this actor have + // changed. But since vtkActor2D::GetMTime() includes the check for + // both Position and Position2 coordinates, we will have to bypass + // it. + + if (this->vtkActor2D::Superclass::GetMTime() <= this->AdjustedRangeBuildTime) + { + return; + } + + if ( this->AdjustLabels ) + { + double interval; + this->ComputeRange(this->Range, + this->AdjustedRange, + this->NumberOfLabels, + this->AdjustedNumberOfLabels, + interval); + } + else + { + this->AdjustedNumberOfLabels = this->NumberOfLabels; + this->AdjustedRange[0] = this->Range[0]; + this->AdjustedRange[1] = this->Range[1]; + } + this->AdjustedRangeBuildTime.Modified(); +} + +// this is a helper function that computes some useful functions +// for an axis. It returns the number of ticks +int vtkAxisActor2DComputeTicks(double sRange[2], double &interval, + double &root) +{ + // first we try assuming the first value is reasonable + int numTicks; + double range = fabs(sRange[1]-sRange[0]); + int rootPower = static_cast(floor(log10(range)-1)); + root = pow(10.0,rootPower); + // val will be between 10 and 100 inclusive of 10 but not 100 + double val = range/root; + // first we check for an exact match + for (numTicks = 5; numTicks < 9; ++numTicks) + { + if (fabs(val/(numTicks-1.0) - floor(val/(numTicks-1.0))) < .0001) + { + interval = val*root/(numTicks-1.0); + return numTicks; + } + } + + // if there isn't an exact match find a reasonable value + int newIntScale = 10; + if (val > 10) + { + newIntScale = 12; + } + if (val > 12) + { + newIntScale = 15; + } + if (val > 15) + { + newIntScale = 18; + } + if (val > 18) + { + newIntScale = 20; + } + if (val > 20) + { + newIntScale = 25; + } + if (val > 25) + { + newIntScale = 30; + } + if (val > 30) + { + newIntScale = 40; + } + if (val > 40) + { + newIntScale = 50; + } + if (val > 50) + { + newIntScale = 60; + } + if (val > 60) + { + newIntScale = 70; + } + if (val > 70) + { + newIntScale = 80; + } + if (val > 80) + { + newIntScale = 90; + } + if (val > 90) + { + newIntScale = 100; + } + + // how many ticks should we have + switch (newIntScale) + { + case 12: + case 20: + case 40: + case 80: + numTicks = 5; + break; + case 18: + case 30: + case 60: + case 90: + numTicks = 7; + break; + case 10: + case 15: + case 25: + case 50: + case 100: + numTicks = 6; + break; + case 70: + numTicks = 8; + break; + } + + interval = newIntScale*root/(numTicks-1.0); + return numTicks; +} + +//---------------------------------------------------------------------------- +//this method takes an initial range and an initial number of ticks and then +//computes a final range and number of ticks so that two properties are +//satisfied. First the final range includes at least the initial range, and +//second the final range divided by the number of ticks (minus one) will be a +//reasonable interval +void vtkAxisActor2D::ComputeRange(double inRange[2], + double outRange[2], + int vtkNotUsed(inNumTicks), + int &numTicks, + double &interval) +{ + // Handle the range + double sRange[2]; + if ( inRange[0] < inRange[1] ) + { + sRange[0] = inRange[0]; + sRange[1] = inRange[1]; + } + else if ( inRange[0] > inRange[1] ) + { + sRange[1] = inRange[0]; + sRange[0] = inRange[1]; + } + else // they're equal, so perturb them by 1 percent + { + double perturb = 100.; + if (inRange[0] == 0.0) + { // if they are both zero, then just perturb about zero + sRange[0] = -1/perturb; + sRange[1] = 1/perturb; + } + else + { + sRange[0] = inRange[0] - inRange[0]/perturb; + sRange[1] = inRange[0] + inRange[0]/perturb; + } + } + + double root; + numTicks = vtkAxisActor2DComputeTicks(sRange, interval, root); + + // is the starting point reasonable? + if (fabs(sRange[0]/root - floor(sRange[0]/root)) < 0.01) + { + outRange[0] = sRange[0]; + outRange[1] = outRange[0] + (numTicks-1.0)*interval; + } + else + { + // OK the starting point is not a good number, so we must widen the range + // First see if the current range will handle moving the start point + outRange[0] = floor(sRange[0]/root)*root; + if (outRange[0]+(numTicks-1.0)*interval <= sRange[1]) + { + outRange[1] = outRange[0] + (numTicks-1.0)*interval; + } + else + { + // Finally in this case we must switch to a larger range to + // have reasonable starting and ending values + sRange[0] = outRange[0]; + numTicks = vtkAxisActor2DComputeTicks(sRange, interval, root); + outRange[1] = outRange[0] + (numTicks-1.0)*interval; + } + } + + // Adust if necessary + if ( inRange[0] > inRange[1] ) + { + sRange[0] = outRange[1]; + outRange[1] = outRange[0]; + outRange[0] = sRange[0]; + interval = -interval; + } + +} + +//---------------------------------------------------------------------------- +// Position text with respect to a point (xTick) where the angle of the line +// from the point to the center of the text is given by theta. The offset +// is the spacing between ticks and labels. +void vtkAxisActor2D::SetOffsetPosition(double xTick[3], double theta, + int stringWidth, int stringHeight, + int offset, vtkActor2D *actor) +{ + double x, y, center[2]; + int pos[2]; + + x = stringWidth/2.0 + offset; + y = stringHeight/2.0 + offset; + + center[0] = xTick[0] + x*sin(theta); + center[1] = xTick[1] - y*cos(theta); + + pos[0] = (int)(center[0] - stringWidth/2.0); + pos[1] = (int)(center[1] - stringHeight/2.0); + + actor->SetPosition(pos[0], pos[1]); +} + +//---------------------------------------------------------------------------- +double vtkAxisActor2D::ComputeStringOffset(double width, double height, + double theta) +{ + double f1 = height*cos(theta); + double f2 = width*sin(theta); + return (1.2 * sqrt(f1*f1 + f2*f2)); +} + +//---------------------------------------------------------------------------- +void vtkAxisActor2D::ShallowCopy(vtkProp *prop) +{ + vtkAxisActor2D *a = vtkAxisActor2D::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetRange(a->GetRange()); + this->SetNumberOfLabels(a->GetNumberOfLabels()); + this->SetLabelFormat(a->GetLabelFormat()); + this->SetAdjustLabels(a->GetAdjustLabels()); + this->SetTitle(a->GetTitle()); + this->SetTickLength(a->GetTickLength()); + this->SetTickOffset(a->GetTickOffset()); + this->SetAxisVisibility(a->GetAxisVisibility()); + this->SetTickVisibility(a->GetTickVisibility()); + this->SetLabelVisibility(a->GetLabelVisibility()); + this->SetTitleVisibility(a->GetTitleVisibility()); + this->SetFontFactor(a->GetFontFactor()); + this->SetLabelFactor(a->GetLabelFactor()); + this->SetLabelTextProperty(a->GetLabelTextProperty()); + this->SetTitleTextProperty(a->GetTitleTextProperty()); + } + + // Now do superclass + this->vtkActor2D::ShallowCopy(prop); +} diff --git a/Rendering/vtkAxisActor2D.h b/Rendering/vtkAxisActor2D.h new file mode 100644 index 0000000..f18b9d5 --- /dev/null +++ b/Rendering/vtkAxisActor2D.h @@ -0,0 +1,316 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkAxisActor2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkAxisActor2D - Create an axis with tick marks and labels +// .SECTION Description +// vtkAxisActor2D creates an axis with tick marks, labels, and/or a title, +// depending on the particular instance variable settings. vtkAxisActor2D is +// a 2D actor; that is, it is drawn on the overlay plane and is not +// occluded by 3D geometry. To use this class, you typically specify two +// points defining the start and end points of the line (x-y definition using +// vtkCoordinate class), the number of labels, and the data range +// (min,max). You can also control what parts of the axis are visible +// including the line, the tick marks, the labels, and the title. You can +// also specify the label format (a printf style format). +// +// This class decides what font size to use and how to locate the labels. It +// also decides how to create reasonable tick marks and labels. The number +// of labels and the range of values may not match the number specified, but +// should be close. +// +// Labels are drawn on the "right" side of the axis. The "right" side is +// the side of the axis on the right as you move from Position to Position2. +// The way the labels and title line up with the axis and tick marks depends on +// whether the line is considered horizontal or vertical. +// +// The vtkActor2D instance variables Position and Position2 are instances of +// vtkCoordinate. Note that the Position2 is an absolute position in that +// class (it was by default relative to Position in vtkActor2D). +// +// What this means is that you can specify the axis in a variety of coordinate +// systems. Also, the axis does not have to be either horizontal or vertical. +// The tick marks are created so that they are perpendicular to the axis. +// +// Set the text property/attributes of the title and the labels through the +// vtkTextProperty objects associated to this actor. +// +// .SECTION See Also +// vtkCubeAxesActor2D can be used to create axes in world coordinate space. +// +// vtkActor2D vtkTextMapper vtkPolyDataMapper2D vtkScalarBarActor +// vtkCoordinate vtkTextProperty + +#ifndef __vtkAxisActor2D_h +#define __vtkAxisActor2D_h + +#include "vtkActor2D.h" + +class vtkPolyDataMapper2D; +class vtkPolyData; +class vtkTextMapper; +class vtkTextProperty; + +#define VTK_MAX_LABELS 25 + +class VTK_RENDERING_EXPORT vtkAxisActor2D : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkAxisActor2D,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object. + static vtkAxisActor2D *New(); + + // Description: + // Specify the position of the first point defining the axis. + // Note: backward compatibility only, use vtkActor2D's Position instead. + virtual vtkCoordinate *GetPoint1Coordinate() + { return this->GetPositionCoordinate(); }; + virtual void SetPoint1(double x[2]) { this->SetPosition(x); }; + virtual void SetPoint1(double x, double y) { this->SetPosition(x,y); }; + virtual double *GetPoint1() { return this->GetPosition(); }; + + // Description: + // Specify the position of the second point defining the axis. Note that + // the order from Point1 to Point2 controls which side the tick marks + // are drawn on (ticks are drawn on the right, if visible). + // Note: backward compatibility only, use vtkActor2D's Position2 instead. + virtual vtkCoordinate *GetPoint2Coordinate() + { return this->GetPosition2Coordinate(); }; + virtual void SetPoint2(double x[2]) { this->SetPosition2(x); }; + virtual void SetPoint2(double x, double y) { this->SetPosition2(x,y); }; + virtual double *GetPoint2() { return this->GetPosition2(); }; + + // Description: + // Specify the (min,max) axis range. This will be used in the generation + // of labels, if labels are visible. + vtkSetVector2Macro(Range,double); + vtkGetVectorMacro(Range,double,2); + + // Description: + // Set/Get the number of annotation labels to show. + vtkSetClampMacro(NumberOfLabels, int, 2, VTK_MAX_LABELS); + vtkGetMacro(NumberOfLabels, int); + + // Description: + // Set/Get the format with which to print the labels on the scalar + // bar. + vtkSetStringMacro(LabelFormat); + vtkGetStringMacro(LabelFormat); + + // Description: + // Set/Get the flag that controls whether the labels and ticks are + // adjusted for "nice" numerical values to make it easier to read + // the labels. The adjustment is based in the Range instance variable. + // Call GetAdjustedRange and GetAdjustedNumberOfLabels to get the adjusted + // range and number of labels. + vtkSetMacro(AdjustLabels, int); + vtkGetMacro(AdjustLabels, int); + vtkBooleanMacro(AdjustLabels, int); + virtual double *GetAdjustedRange() + { + this->UpdateAdjustedRange(); + return this->AdjustedRange; + } + virtual void GetAdjustedRange(double &_arg1, double &_arg2) + { + this->UpdateAdjustedRange(); + _arg1 = this->AdjustedRange[0]; + _arg2 = this->AdjustedRange[1]; + }; + virtual void GetAdjustedRange(double _arg[2]) + { + this->GetAdjustedRange(_arg[0], _arg[1]); + } + virtual int GetAdjustedNumberOfLabels() + { + this->UpdateAdjustedRange(); + return this->AdjustedNumberOfLabels; + } + + // Description: + // Set/Get the title of the scalar bar actor, + vtkSetStringMacro(Title); + vtkGetStringMacro(Title); + + // Description: + // Set/Get the title text property. + virtual void SetTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the labels text property. + virtual void SetLabelTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(LabelTextProperty,vtkTextProperty); + + // Description: + // Set/Get the length of the tick marks (expressed in pixels or display + // coordinates). + vtkSetClampMacro(TickLength, int, 0, 100); + vtkGetMacro(TickLength, int); + + // Description: + // Set/Get the offset of the labels (expressed in pixels or display + // coordinates). The offset is the distance of labels from tick marks + // or other objects. + vtkSetClampMacro(TickOffset, int, 0, 100); + vtkGetMacro(TickOffset, int); + + // Description: + // Set/Get visibility of the axis line. + vtkSetMacro(AxisVisibility, int); + vtkGetMacro(AxisVisibility, int); + vtkBooleanMacro(AxisVisibility, int); + + // Description: + // Set/Get visibility of the axis tick marks. + vtkSetMacro(TickVisibility, int); + vtkGetMacro(TickVisibility, int); + vtkBooleanMacro(TickVisibility, int); + + // Description: + // Set/Get visibility of the axis labels. + vtkSetMacro(LabelVisibility, int); + vtkGetMacro(LabelVisibility, int); + vtkBooleanMacro(LabelVisibility, int); + + // Description: + // Set/Get visibility of the axis title. + vtkSetMacro(TitleVisibility, int); + vtkGetMacro(TitleVisibility, int); + vtkBooleanMacro(TitleVisibility, int); + + // Description: + // Set/Get the factor that controls the overall size of the fonts used + // to label and title the axes. This ivar used in conjunction with + // the LabelFactor can be used to control font sizes. + vtkSetClampMacro(FontFactor, double, 0.1, 2.0); + vtkGetMacro(FontFactor, double); + + // Description: + // Set/Get the factor that controls the relative size of the axis labels + // to the axis title. + vtkSetClampMacro(LabelFactor, double, 0.1, 2.0); + vtkGetMacro(LabelFactor, double); + + // Description: + // Draw the axis. + int RenderOverlay(vtkViewport* viewport); + int RenderOpaqueGeometry(vtkViewport* viewport); + int RenderTranslucentGeometry(vtkViewport *) {return 0;} + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // This method computes the range of the axis given an input range. + // It also computes the number of tick marks given a suggested number. + // (The number of tick marks includes end ticks as well.) + // The number of tick marks computed (in conjunction with the output + // range) will yield "nice" tick values. For example, if the input range + // is (0.25,96.7) and the number of ticks requested is 10, the output range + // will be (0,100) with the number of computed ticks to 11 to yield tick + // values of (0,10,20,...,100). + static void ComputeRange(double inRange[2], + double outRange[2], + int inNumTicks, + int &outNumTicks, + double &interval); + + // Description: + // General method to computes font size from a representative size on the + // viewport (given by size[2]). The method returns the font size (in points) + // and the string height/width (in pixels). It also sets the font size of the + // instance of vtkTextMapper provided. The factor is used when you're trying + // to create text of different size-factor (it is usually = 1 but you can + // adjust the font size by making factor larger or smaller). + static int SetFontSize(vtkViewport *viewport, + vtkTextMapper *textMapper, + int *targetSize, + double factor, + int *stringSize); + static int SetMultipleFontSize(vtkViewport *viewport, + vtkTextMapper **textMappers, + int nbOfMappers, + int *targetSize, + double factor, + int *stringSize); + + // Description: + // Shallow copy of an axis actor. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + +protected: + vtkAxisActor2D(); + ~vtkAxisActor2D(); + + vtkTextProperty *TitleTextProperty; + vtkTextProperty *LabelTextProperty; + + char *Title; + double Range[2]; + int NumberOfLabels; + char *LabelFormat; + int AdjustLabels; + double FontFactor; + double LabelFactor; + int TickLength; + int TickOffset; + + double AdjustedRange[2]; + int AdjustedNumberOfLabels; + int NumberOfLabelsBuilt; + + int AxisVisibility; + int TickVisibility; + int LabelVisibility; + int TitleVisibility; + + int LastPosition[2]; + int LastPosition2[2]; + + int LastSize[2]; + int LastMaxLabelSize[2]; + + virtual void BuildAxis(vtkViewport *viewport); + static double ComputeStringOffset(double width, double height, double theta); + static void SetOffsetPosition(double xTick[3], double theta, + int stringHeight, int stringWidth, + int offset, vtkActor2D *actor); + virtual void UpdateAdjustedRange(); + + vtkTextMapper *TitleMapper; + vtkActor2D *TitleActor; + + vtkTextMapper **LabelMappers; + vtkActor2D **LabelActors; + + vtkPolyData *Axis; + vtkPolyDataMapper2D *AxisMapper; + vtkActor2D *AxisActor; + + vtkTimeStamp AdjustedRangeBuildTime; + vtkTimeStamp BuildTime; + +private: + vtkAxisActor2D(const vtkAxisActor2D&); // Not implemented. + void operator=(const vtkAxisActor2D&); // Not implemented. +}; + + +#endif diff --git a/Rendering/vtkCamera.cxx b/Rendering/vtkCamera.cxx new file mode 100644 index 0000000..e54f8f6 --- /dev/null +++ b/Rendering/vtkCamera.cxx @@ -0,0 +1,994 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCamera.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCamera.h" + +#include "vtkMath.h" +#include "vtkTimeStamp.h" +#include "vtkGraphicsFactory.h" +#include "vtkPerspectiveTransform.h" +#include "vtkTransform.h" + +#include + +vtkCxxRevisionMacro(vtkCamera, "$Revision: 1.109 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkCamera); + +//---------------------------------------------------------------------------- +// Construct camera instance with its focal point at the origin, +// and position=(0,0,1). The view up is along the y-axis, +// view angle is 30 degrees, and the clipping range is (.1,1000). +vtkCamera::vtkCamera() +{ + this->FocalPoint[0] = 0.0; + this->FocalPoint[1] = 0.0; + this->FocalPoint[2] = 0.0; + + this->Position[0] = 0.0; + this->Position[1] = 0.0; + this->Position[2] = 1.0; + + this->ViewUp[0] = 0.0; + this->ViewUp[1] = 1.0; + this->ViewUp[2] = 0.0; + + this->DirectionOfProjection[0] = 0.0; + this->DirectionOfProjection[1] = 0.0; + this->DirectionOfProjection[2] = 0.0; + + this->ViewAngle = 30.0; + this->UseHorizontalViewAngle = 0; + + this->ClippingRange[0] = 0.01; + this->ClippingRange[1] = 1000.01; + this->Thickness = 1000.0; + + this->ParallelProjection = 0; + this->ParallelScale = 1.0; + + this->EyeAngle = 2.0; + this->Stereo = 0; + this->LeftEye = 1; + + this->WindowCenter[0] = 0.0; + this->WindowCenter[1] = 0.0; + + this->ViewShear[0] = 0.0; + this->ViewShear[1] = 0.0; + this->ViewShear[2] = 1.0; + + this->FocalDisk = 1.0; + + this->Transform = vtkPerspectiveTransform::New(); + this->ViewTransform = vtkTransform::New(); + this->PerspectiveTransform = vtkPerspectiveTransform::New(); + this->CameraLightTransform = vtkTransform::New(); + this->UserTransform = NULL; + + // initialize the ViewTransform + this->ComputeViewTransform(); + this->ComputeDistance(); + this->ComputeCameraLightTransform(); +} + +//---------------------------------------------------------------------------- +vtkCamera::~vtkCamera() +{ + this->Transform->Delete(); + this->ViewTransform->Delete(); + this->PerspectiveTransform->Delete(); + this->CameraLightTransform->Delete(); + if (this->UserTransform) + { + this->UserTransform->UnRegister(this); + this->UserTransform = NULL; + } +} + +//---------------------------------------------------------------------------- +// return the correct type of Camera +vtkCamera *vtkCamera::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkCamera"); + return (vtkCamera*)ret; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// The first set of methods deal exclusively with the ViewTransform, which +// is the only transform which is set up entirely in the camera. The +// perspective transform must be set up by the Renderer because the +// Camera doesn't know the Renderer's aspect ratio. +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +void vtkCamera::SetPosition(double x, double y, double z) +{ + if (x == this->Position[0] && + y == this->Position[1] && + z == this->Position[2]) + { + return; + } + + this->Position[0] = x; + this->Position[1] = y; + this->Position[2] = z; + + vtkDebugMacro(<< " Position set to ( " << this->Position[0] << ", " + << this->Position[1] << ", " << this->Position[2] << ")"); + + this->ComputeViewTransform(); + // recompute the focal distance + this->ComputeDistance(); + this->ComputeCameraLightTransform(); + + this->Modified(); +} + +void vtkCamera::SetUserTransform(vtkHomogeneousTransform *transform) +{ + if (transform == this->UserTransform) + { + return; + } + if (this->UserTransform) + { + this->UserTransform->Delete(); + this->UserTransform = NULL; + } + if (transform) + { + this->UserTransform = transform; + this->UserTransform->Register(this); + } + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetFocalPoint(double x, double y, double z) +{ + if (x == this->FocalPoint[0] && + y == this->FocalPoint[1] && + z == this->FocalPoint[2]) + { + return; + } + + this->FocalPoint[0] = x; + this->FocalPoint[1] = y; + this->FocalPoint[2] = z; + + vtkDebugMacro(<< " FocalPoint set to ( " << this->FocalPoint[0] << ", " << this->FocalPoint[1] << ", " << this->FocalPoint[2] << ")"); + + this->ComputeViewTransform(); + // recompute the focal distance + this->ComputeDistance(); + this->ComputeCameraLightTransform(); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetViewUp(double x, double y, double z) +{ + // normalize ViewUp, but do _not_ orthogonalize it by default + double norm = sqrt(x*x + y*y + z*z); + + if(norm != 0) + { + x /= norm; + y /= norm; + z /= norm; + } + else + { + x = 0; + y = 1; + z = 0; + } + + if (x == this->ViewUp[0] && + y == this->ViewUp[1] && + z == this->ViewUp[2]) + { + return; + } + + this->ViewUp[0] = x; + this->ViewUp[1] = y; + this->ViewUp[2] = z; + + vtkDebugMacro(<< " ViewUp set to ( " << this->ViewUp[0] << ", " << this->ViewUp[1] << ", " << this->ViewUp[2] << ")"); + + this->ComputeViewTransform(); + this->ComputeCameraLightTransform(); + this->Modified(); +} + +//---------------------------------------------------------------------------- +// The ViewTransform depends on only three ivars: the Position, the +// FocalPoint, and the ViewUp vector. All the other methods are there +// simply for the sake of the users' convenience. +void vtkCamera::ComputeViewTransform() +{ + // main view through the camera + this->Transform->Identity(); + this->Transform->SetupCamera(this->Position, this->FocalPoint, this->ViewUp); + this->ViewTransform->SetMatrix(this->Transform->GetMatrix()); +} + +//---------------------------------------------------------------------------- +void vtkCamera::ComputeCameraLightTransform() +{ + vtkTransform *t; + double d; + + // assumes a valid view transform and valid camera distance + + t = this->CameraLightTransform; + t->Identity(); + t->SetMatrix(this->ViewTransform->GetMatrix()); + t->Inverse(); + + d = this->Distance; + t->Scale(d, d, d); + t->Translate(0.0, 0.0, -1.0); +} + +//---------------------------------------------------------------------------- +void vtkCamera::OrthogonalizeViewUp() +{ + // the orthogonalized ViewUp is just the second row of the view matrix + vtkMatrix4x4 *matrix = this->ViewTransform->GetMatrix(); + this->ViewUp[0] = matrix->GetElement(1,0); + this->ViewUp[1] = matrix->GetElement(1,1); + this->ViewUp[2] = matrix->GetElement(1,2); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Set the distance of the focal point from the camera. The focal point is +// modified accordingly. This should be positive. +void vtkCamera::SetDistance(double d) +{ + if (this->Distance == d) + { + return; + } + + this->Distance = d; + + // Distance should be greater than .0002 + if (this->Distance < 0.0002) + { + this->Distance = 0.0002; + vtkDebugMacro(<< " Distance is set to minimum."); + } + + // we want to keep the camera pointing in the same direction + double *vec = this->DirectionOfProjection; + + // recalculate FocalPoint + this->FocalPoint[0] = this->Position[0] + vec[0]*this->Distance; + this->FocalPoint[1] = this->Position[1] + vec[1]*this->Distance; + this->FocalPoint[2] = this->Position[2] + vec[2]*this->Distance; + + vtkDebugMacro(<< " Distance set to ( " << this->Distance << ")"); + + this->ComputeViewTransform(); + this->ComputeCameraLightTransform(); + this->Modified(); +} + +//---------------------------------------------------------------------------- +// This method must be called when the focal point or camera position changes +void vtkCamera::ComputeDistance() +{ + double dx = this->FocalPoint[0] - this->Position[0]; + double dy = this->FocalPoint[1] - this->Position[1]; + double dz = this->FocalPoint[2] - this->Position[2]; + + this->Distance = sqrt(dx*dx + dy*dy + dz*dz); + + if (this->Distance < 0.0002) + { + this->Distance = 0.0002; + vtkDebugMacro(<< " Distance is set to minimum."); + + double *vec = this->DirectionOfProjection; + + // recalculate FocalPoint + this->FocalPoint[0] = this->Position[0] + vec[0]*this->Distance; + this->FocalPoint[1] = this->Position[1] + vec[1]*this->Distance; + this->FocalPoint[2] = this->Position[2] + vec[2]*this->Distance; + } + + this->DirectionOfProjection[0] = dx/this->Distance; + this->DirectionOfProjection[1] = dy/this->Distance; + this->DirectionOfProjection[2] = dz/this->Distance; + + this->ComputeViewPlaneNormal(); +} + +//---------------------------------------------------------------------------- +// Move the position of the camera along the view plane normal. Moving +// towards the focal point (e.g., > 1) is a dolly-in, moving away +// from the focal point (e.g., < 1) is a dolly-out. +void vtkCamera::Dolly(double amount) +{ + if (amount <= 0.0) + { + return; + } + + // dolly moves the camera towards the focus + double d = this->Distance/amount; + + this->SetPosition(this->FocalPoint[0] - d*this->DirectionOfProjection[0], + this->FocalPoint[1] - d*this->DirectionOfProjection[1], + this->FocalPoint[2] - d*this->DirectionOfProjection[2]); +} + +//---------------------------------------------------------------------------- +// Set the roll angle of the camera about the direction of projection +void vtkCamera::SetRoll(double roll) +{ + // roll is a rotation of camera view up about the direction of projection + vtkDebugMacro(<< " Setting Roll to " << roll << ""); + + // subtract the current roll + roll -= this->GetRoll(); + + if (fabs(roll) < 0.00001) + { + return; + } + + this->Roll(roll); +} + +//---------------------------------------------------------------------------- +// Returns the roll of the camera. +double vtkCamera::GetRoll() +{ + double orientation[3]; + this->ViewTransform->GetOrientation(orientation); + return orientation[2]; +} + +//---------------------------------------------------------------------------- +// Rotate the camera around the view plane normal. +void vtkCamera::Roll(double angle) +{ + double newViewUp[3]; + this->Transform->Identity(); + + // rotate ViewUp about the Direction of Projection + this->Transform->RotateWXYZ(angle,this->DirectionOfProjection); + + // okay, okay, TransformPoint shouldn't be used on vectors -- but + // the transform is rotation with no translation so this works fine. + this->Transform->TransformPoint(this->ViewUp,newViewUp); + this->SetViewUp(newViewUp); +} + +//---------------------------------------------------------------------------- +// Rotate the focal point about the view up vector centered at the camera's +// position. +void vtkCamera::Yaw(double angle) +{ + double newFocalPoint[3]; + double *pos = this->Position; + this->Transform->Identity(); + + // translate the camera to the origin, + // rotate about axis, + // translate back again + this->Transform->Translate(+pos[0],+pos[1],+pos[2]); + this->Transform->RotateWXYZ(angle,this->ViewUp); + this->Transform->Translate(-pos[0],-pos[1],-pos[2]); + + // now transform focal point + this->Transform->TransformPoint(this->FocalPoint,newFocalPoint); + this->SetFocalPoint(newFocalPoint); +} + +//---------------------------------------------------------------------------- +// Rotate the focal point about the cross product of the view up vector +// and the negative of the , centered at the camera's position. +void vtkCamera::Pitch(double angle) +{ + double axis[3], newFocalPoint[3]; + double *pos = this->Position; + this->Transform->Identity(); + + // the axis is the first row of the view transform matrix + axis[0] = this->ViewTransform->GetMatrix()->GetElement(0,0); + axis[1] = this->ViewTransform->GetMatrix()->GetElement(0,1); + axis[2] = this->ViewTransform->GetMatrix()->GetElement(0,2); + + // translate the camera to the origin, + // rotate about axis, + // translate back again + this->Transform->Translate(+pos[0],+pos[1],+pos[2]); + this->Transform->RotateWXYZ(angle,axis); + this->Transform->Translate(-pos[0],-pos[1],-pos[2]); + + // now transform focal point + this->Transform->TransformPoint(this->FocalPoint,newFocalPoint); + this->SetFocalPoint(newFocalPoint); +} + +//---------------------------------------------------------------------------- +// Rotate the camera about the view up vector centered at the focal point. +void vtkCamera::Azimuth(double angle) +{ + double newPosition[3]; + double *fp = this->FocalPoint; + this->Transform->Identity(); + + // translate the focal point to the origin, + // rotate about view up, + // translate back again + this->Transform->Translate(+fp[0],+fp[1],+fp[2]); + this->Transform->RotateWXYZ(angle,this->ViewUp); + this->Transform->Translate(-fp[0],-fp[1],-fp[2]); + + // apply the transform to the position + this->Transform->TransformPoint(this->Position,newPosition); + this->SetPosition(newPosition); +} + +//---------------------------------------------------------------------------- +// Rotate the camera about the cross product of the negative of the +// direction of projection and the view up vector centered on the focal point. +void vtkCamera::Elevation(double angle) +{ + double axis[3], newPosition[3]; + double *fp = this->FocalPoint; + this->Transform->Identity(); + + // snatch the axis from the view transform matrix + axis[0] = -this->ViewTransform->GetMatrix()->GetElement(0,0); + axis[1] = -this->ViewTransform->GetMatrix()->GetElement(0,1); + axis[2] = -this->ViewTransform->GetMatrix()->GetElement(0,2); + + // translate the focal point to the origin, + // rotate about axis, + // translate back again + this->Transform->Translate(+fp[0],+fp[1],+fp[2]); + this->Transform->RotateWXYZ(angle,axis); + this->Transform->Translate(-fp[0],-fp[1],-fp[2]); + + // now transform position + this->Transform->TransformPoint(this->Position,newPosition); + this->SetPosition(newPosition); +} + +//---------------------------------------------------------------------------- +// Apply Transform to camera +void vtkCamera::ApplyTransform(vtkTransform *t) { + + double posOld[4], posNew[4], fpOld[4], fpNew[4], vuOld[4], vuNew[4]; + + this->GetPosition(posOld); + this->GetFocalPoint(fpOld); + this->GetViewUp(vuOld); + + posOld[3] = 1.0; + fpOld[3] = 1.0; + vuOld[3] = 1.0; + + vuOld[0] += posOld[0]; + vuOld[1] += posOld[1]; + vuOld[2] += posOld[2]; + + t->MultiplyPoint(posOld, posNew); + t->MultiplyPoint(fpOld, fpNew); + t->MultiplyPoint(vuOld, vuNew); + + vuNew[0] -= posNew[0]; + vuNew[1] -= posNew[1]; + vuNew[2] -= posNew[2]; + + this->SetPosition(posNew); + this->SetFocalPoint(fpNew); + this->SetViewUp(vuNew); + +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// The following methods set up the information that the Renderer needs +// to set up the perspective transform. The transformation matrix is +// created using the GetPerspectiveTransformMatrix method. +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +void vtkCamera::SetParallelProjection(int flag) +{ + if ( this->ParallelProjection != flag ) + { + this->ParallelProjection = flag; + this->Modified(); + this->ViewingRaysModified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetViewAngle(double angle) +{ + double min = 0.00000001; + double max = 179.0; + + if ( this->ViewAngle != angle ) + { + this->ViewAngle = (anglemax?max:angle)); + this->Modified(); + this->ViewingRaysModified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetUseHorizontalViewAngle(int flag) +{ + if (flag == this->UseHorizontalViewAngle) + { + return; + } + this->UseHorizontalViewAngle = flag; + this->Modified(); + this->ViewingRaysModified(); +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetParallelScale(double scale) +{ + if ( this->ParallelScale != scale ) + { + this->ParallelScale = scale; + this->Modified(); + this->ViewingRaysModified(); + } +} + +//---------------------------------------------------------------------------- +// Change the ViewAngle (for perspective) or the ParallelScale (for parallel) +// so that more or less of a scene occupies the viewport. A value > 1 is a +// zoom-in. A value < 1 is a zoom-out. +void vtkCamera::Zoom(double amount) +{ + if (amount <= 0.0) + { + return; + } + + if (this->ParallelProjection) + { + this->SetParallelScale(this->ParallelScale/amount); + } + else + { + this->SetViewAngle(this->ViewAngle/amount); + } +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetClippingRange(double nearz, double farz) +{ + double thickness; + + // check the order + if ( nearz > farz ) + { + vtkDebugMacro(<< " Front and back clipping range reversed"); + double temp = nearz; + nearz = farz; + farz = temp; + } + + // front should be greater than 0.0001 + if (nearz < 0.0001) + { + farz += 0.0001 - nearz; + nearz = 0.0001; + vtkDebugMacro(<< " Front clipping range is set to minimum."); + } + + thickness = farz - nearz; + + // thickness should be greater than 0.0001 + if (thickness < 0.0001) + { + thickness = 0.0001; + vtkDebugMacro(<< " ClippingRange thickness is set to minimum."); + + // set back plane + farz = nearz + thickness; + } + + if (nearz == this->ClippingRange[0] && + farz == this->ClippingRange[1] && + this->Thickness == thickness) + { + return; + } + + this->ClippingRange[0] = nearz; + this->ClippingRange[1] = farz; + this->Thickness = thickness; + + vtkDebugMacro(<< " ClippingRange set to ( " << this->ClippingRange[0] << ", " << this->ClippingRange[1] << ")"); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// Set the distance between clipping planes. +// This method adjusts the back clipping plane to the specified thickness +// behind the front clipping plane +void vtkCamera::SetThickness(double s) +{ + if (this->Thickness == s) + { + return; + } + + this->Thickness = s; + + // thickness should be greater than 0.0001 + if (this->Thickness < 0.0001) + { + this->Thickness = 0.0001; + vtkDebugMacro(<< " ClippingRange thickness is set to minimum."); + } + + // set back plane + this->ClippingRange[1] = this->ClippingRange[0] + this->Thickness; + + vtkDebugMacro(<< " ClippingRange set to ( " << this->ClippingRange[0] << ", " << this->ClippingRange[1] << ")"); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetWindowCenter(double x, double y) +{ + if (this->WindowCenter[0] != x || this->WindowCenter[1] != y) + { + this->Modified(); + this->ViewingRaysModified(); + this->WindowCenter[0] = x; + this->WindowCenter[1] = y; + } +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetObliqueAngles(double alpha, double beta) +{ + alpha *= vtkMath::DoubleDegreesToRadians(); + beta *= vtkMath::DoubleDegreesToRadians(); + + double cotbeta = cos(beta) / sin(beta); + double dxdz = cos(alpha) * cotbeta; + double dydz = sin(alpha) * cotbeta; + + this->SetViewShear(dxdz, dydz, 1.0); +} + +//---------------------------------------------------------------------------- +// Set the shear transform of the viewing frustum. Parameters are +// dx/dz, dy/dz, and center. center is a factor that describes where +// to shear around. The distance dshear from the camera where +// no shear occurs is given by (dshear = center * FocalDistance). +// +void vtkCamera::SetViewShear(double dxdz, double dydz, double center) +{ + if(dxdz != this->ViewShear[0] || + dydz != this->ViewShear[1] || + center != this->ViewShear[2]) + { + this->Modified(); + this->ViewingRaysModified(); + + this->ViewShear[0] = dxdz; + this->ViewShear[1] = dydz; + this->ViewShear[2] = center; + + this->ComputeViewPlaneNormal(); + } +} +//---------------------------------------------------------------------------- + +void vtkCamera::SetViewShear(double d[3]) +{ + this->SetViewShear(d[0], d[1], d[2]); +} + +//---------------------------------------------------------------------------- +// Compute the perspective transform matrix. This is used in converting +// between view and world coordinates. +void vtkCamera::ComputePerspectiveTransform(double aspect, + double nearz, double farz) +{ + this->PerspectiveTransform->Identity(); + + // apply user defined transform last if there is one + if (this->UserTransform) + { + this->PerspectiveTransform->Concatenate(this->UserTransform->GetMatrix()); + } + + // adjust Z-buffer range + this->PerspectiveTransform->AdjustZBuffer(-1, +1, nearz, farz); + + if (this->ParallelProjection) + { + // set up a rectangular parallelipiped + + double width = this->ParallelScale*aspect; + double height = this->ParallelScale; + + double xmin = (this->WindowCenter[0]-1.0)*width; + double xmax = (this->WindowCenter[0]+1.0)*width; + double ymin = (this->WindowCenter[1]-1.0)*height; + double ymax = (this->WindowCenter[1]+1.0)*height; + + this->PerspectiveTransform->Ortho(xmin,xmax,ymin,ymax, + this->ClippingRange[0], + this->ClippingRange[1]); + } + else + { + // set up a perspective frustum + + double tmp = tan(this->ViewAngle*vtkMath::DoubleDegreesToRadians()/2); + double width; + double height; + if (this->UseHorizontalViewAngle) + { + width = this->ClippingRange[0]*tmp; + height = this->ClippingRange[0]*tmp/aspect; + } + else + { + width = this->ClippingRange[0]*tmp*aspect; + height = this->ClippingRange[0]*tmp; + } + + double xmin = (this->WindowCenter[0]-1.0)*width; + double xmax = (this->WindowCenter[0]+1.0)*width; + double ymin = (this->WindowCenter[1]-1.0)*height; + double ymax = (this->WindowCenter[1]+1.0)*height; + + this->PerspectiveTransform->Frustum(xmin, xmax, ymin, ymax, + this->ClippingRange[0], + this->ClippingRange[1]); + } + + if (this->Stereo) + { + // set up a shear for stereo views + if (this->LeftEye) + { + this->PerspectiveTransform->Stereo(-this->EyeAngle/2, + this->Distance); + } + else + { + this->PerspectiveTransform->Stereo(+this->EyeAngle/2, + this->Distance); + } + } + + if (this->ViewShear[0] != 0.0 || this->ViewShear[1] != 0.0) + { + this->PerspectiveTransform->Shear(this->ViewShear[0], + this->ViewShear[1], + this->ViewShear[2]*this->Distance); + } + +} + +//---------------------------------------------------------------------------- +// Return the perspective transform matrix. See ComputePerspectiveTransform. +vtkMatrix4x4 *vtkCamera::GetPerspectiveTransformMatrix(double aspect, + double nearz, + double farz) +{ + this->ComputePerspectiveTransform(aspect, nearz, farz); + + // return the transform + return this->PerspectiveTransform->GetMatrix(); +} + +//---------------------------------------------------------------------------- +// Return the perspective transform matrix. See ComputePerspectiveTransform. +vtkMatrix4x4 *vtkCamera::GetCompositePerspectiveTransformMatrix(double aspect, + double nearz, + double farz) +{ + // turn off stereo, the CompositePerspectiveTransformMatrix is used for + // picking, not for rendering. + int stereo = this->Stereo; + this->Stereo = 0; + + this->Transform->Identity(); + this->Transform->Concatenate(this->GetPerspectiveTransformMatrix(aspect, + nearz, + farz)); + this->Transform->Concatenate(this->GetViewTransformMatrix()); + + this->Stereo = stereo; + + // return the transform + return this->Transform->GetMatrix(); +} + +//---------------------------------------------------------------------------- +// Return the attached light transform matrix. +vtkMatrix4x4 *vtkCamera::GetCameraLightTransformMatrix() +{ + // return the transform + return this->CameraLightTransform->GetMatrix(); +} + + +//---------------------------------------------------------------------------- +void vtkCamera::ComputeViewPlaneNormal() +{ + if (this->ViewShear[0] != 0.0 || this->ViewShear[1] != 0.0) + { + // set the VPN in camera coordinates + this->ViewPlaneNormal[0] = this->ViewShear[0]; + this->ViewPlaneNormal[1] = this->ViewShear[1]; + this->ViewPlaneNormal[2] = 1.0; + // transform the VPN to world coordinates using inverse of view transform + this->ViewTransform->GetLinearInverse()->TransformNormal( + this->ViewPlaneNormal, + this->ViewPlaneNormal); + } + else + { + // VPN is -DOP + this->ViewPlaneNormal[0] = -this->DirectionOfProjection[0]; + this->ViewPlaneNormal[1] = -this->DirectionOfProjection[1]; + this->ViewPlaneNormal[2] = -this->DirectionOfProjection[2]; + } +} + +//---------------------------------------------------------------------------- +void vtkCamera::SetViewPlaneNormal(double vtkNotUsed(x), + double vtkNotUsed(y), + double vtkNotUsed(z)) +{ + vtkWarningMacro(<< "SetViewPlaneNormal: This method is deprecated, the view plane normal is calculated automatically."); +} + +//---------------------------------------------------------------------------- +// Return the 6 planes (Ax + By + Cz + D = 0) that bound +// the view frustum. +void vtkCamera::GetFrustumPlanes(double aspect, double planes[24]) +{ + int i; + double f, normals[6][4], matrix[4][4]; + + // set up the normals + for (i = 0; i < 6; i++) + { + normals[i][0] = 0.0; + normals[i][1] = 0.0; + normals[i][2] = 0.0; + normals[i][3] = 1.0; + // if i is even set to -1, if odd set to +1 + normals[i][i/2] = 1 - (i%2)*2; + } + + // get the composite perspective matrix + vtkMatrix4x4::DeepCopy( + *matrix, + this->GetCompositePerspectiveTransformMatrix(aspect,-1,+1)); + + // transpose the matrix for use with normals + vtkMatrix4x4::Transpose(*matrix,*matrix); + + // transform the normals to world coordinates + for (i = 0; i < 6; i++) + { + vtkMatrix4x4::MultiplyPoint(*matrix,normals[i],normals[i]); + + f = 1.0/sqrt(normals[i][0]*normals[i][0] + + normals[i][1]*normals[i][1] + + normals[i][2]*normals[i][2]); + + planes[4*i + 0] = normals[i][0]*f; + planes[4*i + 1] = normals[i][1]*f; + planes[4*i + 2] = normals[i][2]*f; + planes[4*i + 3] = normals[i][3]*f; + } +} + +//---------------------------------------------------------------------------- +unsigned long int vtkCamera::GetViewingRaysMTime() +{ + return this->ViewingRaysMTime.GetMTime(); +} + +//---------------------------------------------------------------------------- +void vtkCamera::ViewingRaysModified() +{ + this->ViewingRaysMTime.Modified(); +} + +//---------------------------------------------------------------------------- +void vtkCamera::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ClippingRange: (" << this->ClippingRange[0] << ", " + << this->ClippingRange[1] << ")\n"; + os << indent << "DirectionOfProjection: (" << this->DirectionOfProjection[0] + << ", " << this->DirectionOfProjection[1] + << ", " << this->DirectionOfProjection[2] << ")\n"; + os << indent << "Distance: " << this->Distance << "\n"; + os << indent << "EyeAngle: " << this->EyeAngle << "\n"; + os << indent << "FocalDisk: " << this->FocalDisk << "\n"; + os << indent << "FocalPoint: (" << this->FocalPoint[0] << ", " + << this->FocalPoint[1] << ", " << this->FocalPoint[2] << ")\n"; + os << indent << "ViewShear: (" << this->ViewShear[0] + << ", " << this->ViewShear[1] + << ", " << this->ViewShear[2] << ")\n"; + os << indent << "ParallelProjection: " << + (this->ParallelProjection ? "On\n" : "Off\n"); + os << indent << "ParallelScale: " << this->ParallelScale << "\n"; + os << indent << "Position: (" << this->Position[0] << ", " + << this->Position[1] << ", " << this->Position[2] << ")\n"; + os << indent << "Stereo: " << (this->Stereo ? "On\n" : "Off\n"); + os << indent << "Thickness: " << this->Thickness << "\n"; + os << indent << "ViewAngle: " << this->ViewAngle << "\n"; + os << indent << "UseHorizontalViewAngle: " << this->UseHorizontalViewAngle << "\n"; + os << indent << "UserTransform: "; + if (this->UserTransform) + { + os << this->UserTransform << "\n"; + } + else + { + os << "(none)\n"; + } + os << indent << "ViewPlaneNormal: (" << this->ViewPlaneNormal[0] + << ", " << this->ViewPlaneNormal[1] + << ", " << this->ViewPlaneNormal[2] << ")\n"; + os << indent << "ViewUp: (" << this->ViewUp[0] << ", " + << this->ViewUp[1] << ", " << this->ViewUp[2] << ")\n"; + os << indent << "WindowCenter: (" << this->WindowCenter[0] << ", " + << this->WindowCenter[1] << ")\n"; +} + +vtkMatrix4x4 *vtkCamera::GetViewTransformMatrix() +{ return this->ViewTransform->GetMatrix(); } + +double *vtkCamera::GetOrientation() +{ return this->ViewTransform->GetOrientation(); }; + +double *vtkCamera::GetOrientationWXYZ() +{ return this->ViewTransform->GetOrientationWXYZ(); }; diff --git a/Rendering/vtkCamera.h b/Rendering/vtkCamera.h new file mode 100644 index 0000000..ef2e3fd --- /dev/null +++ b/Rendering/vtkCamera.h @@ -0,0 +1,387 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCamera.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCamera - a virtual camera for 3D rendering +// .SECTION Description +// vtkCamera is a virtual camera for 3D rendering. It provides methods +// to position and orient the view point and focal point. Convenience +// methods for moving about the focal point also are provided. More +// complex methods allow the manipulation of the computer graphics +// model including view up vector, clipping planes, and +// camera perspective. +// .SECTION See Also +// vtkPerspectiveTransform + +#ifndef __vtkCamera_h +#define __vtkCamera_h + +#include "vtkObject.h" + +class vtkMatrix4x4; +class vtkPerspectiveTransform; +class vtkRenderer; +class vtkTransform; +class vtkHomogeneousTransform; + +class VTK_RENDERING_EXPORT vtkCamera : public vtkObject +{ + public: + void PrintSelf(ostream& os, vtkIndent indent); + vtkTypeRevisionMacro(vtkCamera,vtkObject); + + // Description: + // Construct camera instance with its focal point at the origin, + // and position=(0,0,1). The view up is along the y-axis, + // view angle is 30 degrees, and the clipping range is (.1,1000). + static vtkCamera *New(); + + // Description: + // Set/Get the position of the camera in world coordinates. + // The default position is (0,0,1). + void SetPosition(double x, double y, double z); + void SetPosition(const double a[3]) { + this->SetPosition(a[0], a[1], a[2]); }; + vtkGetVector3Macro(Position,double); + + // Description: + // Set/Get the focal of the camera in world coordinates. + // The default focal point is the origin. + void SetFocalPoint(double x, double y, double z); + void SetFocalPoint(const double a[3]) { + this->SetFocalPoint(a[0], a[1], a[2]);}; + vtkGetVector3Macro(FocalPoint,double); + + // Description: + // Set/Get the view up direction for the camera. The default + // is (0,1,0). + void SetViewUp(double vx, double vy, double vz); + void SetViewUp(const double a[3]) { + this->SetViewUp(a[0], a[1], a[2]); } + vtkGetVector3Macro(ViewUp,double); + + // Description: + // Recompute the ViewUp vector to force it to be perpendicular to + // camera->focalpoint vector. Unless you are going to use + // Yaw or Azimuth on the camera, there is no need to do this. + void OrthogonalizeViewUp(); + + // Description: + // Move the focal point so that it is the specified distance from + // the camera position. This distance must be positive. + void SetDistance(double); + + // Description: + // Return the distance from the camera position to the focal point. + // This distance is positive. + vtkGetMacro(Distance,double); + + // Description: + // Get the vector in the direction from the camera position to the + // focal point. This is usually the opposite of the ViewPlaneNormal, + // the vector perpendicular to the screen, unless the view is oblique. + vtkGetVector3Macro(DirectionOfProjection,double); + + // Description: + // Move the position of the camera along the direction of projection. Moving + // towards the focal point (e.g., greater than 1) is a dolly-in, moving away + // from the focal point (e.g., less than 1) is a dolly-out. + void Dolly(double distance); + + // Description: + // Set the roll angle of the camera about the direction of projection. + void SetRoll(double angle); + double GetRoll(); + + // Description: + // Rotate the camera about the direction of projection. + void Roll(double angle); + + // Description: + // Rotate the camera about the view up vector centered at the focal point. + // Note that the view up vector is not necessarily perpendicular to the + // direction of projection. + void Azimuth(double angle); + + // Description: + // Rotate the focal point about the view up vector centered at the camera's + // position. Note that the view up vector is not necessarily perpendicular + // to the direction of projection. + void Yaw(double angle); + + // Description: + // Rotate the camera about the cross product of the direction of projection + // and the view up vector centered on the focal point. + void Elevation(double angle); + + // Description: + // Rotate the focal point about the cross product of the view up vector + // and the direction of projection, centered at the camera's position. + void Pitch(double angle); + + // Description: + // Set/Get the value of the ParallelProjection instance variable. This + // determines if the camera should do a perspective or parallel projection. + void SetParallelProjection(int flag); + vtkGetMacro(ParallelProjection,int); + vtkBooleanMacro(ParallelProjection,int); + + // Description: + // Set/Get the value of the UseHorizontalViewAngle instance variable. If + // set, the camera's view angle represents a horizontal view angle, rather + // than the default vertical view angle. This is useful if the application + // uses a display device which whose specs indicate a particular horizontal + // view angle, or if the application varies the window height but wants to + // keep the perspective transform unchanges. + void SetUseHorizontalViewAngle(int flag); + vtkGetMacro(UseHorizontalViewAngle, int); + vtkBooleanMacro(UseHorizontalViewAngle, int); + + // Description: + // Set/Get the camera view angle, which is the angular height of the + // camera view measured in degrees. The default angle is 30 degrees. + // This method has no effect in parallel projection mode. + // The formula for setting the angle up for perfect perspective viewing + // is: angle = 2*atan((h/2)/d) where h is the height of the RenderWindow + // (measured in mm by holding a ruler up to your screen) and d is the + // distance from your eyes to the screen. + void SetViewAngle(double angle); + vtkGetMacro(ViewAngle,double); + + // Description: + // Set/Get the scaling used for a parallel projection, i.e. the height + // of the viewport in world-coordinate distances. The default is 1. + // Note that the "scale" parameter works as an "inverse scale" --- + // larger numbers produce smaller images. + // This method has no effect in perspective projection mode. + void SetParallelScale(double scale); + vtkGetMacro(ParallelScale,double); + + // Description: + // In perspective mode, decrease the view angle by the specified factor. + // In parallel mode, decrease the parallel scale by the specified factor. + // A value greater than 1 is a zoom-in, a value less than 1 is a zoom-out. + void Zoom(double factor); + + // Description: + // Set/Get the location of the near and far clipping planes along the + // direction of projection. Both of these values must be positive. + // How the clipping planes are set can have a large impact on how + // well z-buffering works. In particular the front clipping + // plane can make a very big difference. Setting it to 0.01 when it + // really could be 1.0 can have a big impact on your z-buffer resolution + // farther away. The default clipping range is (0.1,1000). + void SetClippingRange(double dNear, double dFar); + void SetClippingRange(const double a[2]) { + this->SetClippingRange(a[0], a[1]); }; + vtkGetVector2Macro(ClippingRange,double); + + // Description: + // Set the distance between clipping planes. This method adjusts the + // far clipping plane to be set a distance 'thickness' beyond the + // near clipping plane. + void SetThickness(double); + vtkGetMacro(Thickness,double); + + // Description: + // Set/Get the center of the window in viewport coordinates. + // The viewport coordinate range is ([-1,+1],[-1,+1]). This method + // is for if you have one window which consists of several viewports, + // or if you have several screens which you want to act together as + // one large screen. + void SetWindowCenter(double x, double y); + vtkGetVector2Macro(WindowCenter,double); + + // Description: + // Get/Set the oblique viewing angles. The first angle, alpha, is the + // angle (measured from the horizontal) that rays along the direction + // of projection will follow once projected onto the 2D screen. + // The second angle, beta, is the angle between the view plane and + // the direction of projection. This creates a shear transform + // x' = x + dz*cos(alpha)/tan(beta), y' = dz*sin(alpha)/tan(beta) + // where dz is the distance of the point from the focal plane. + // The angles are (45,90) by default. Oblique projections + // commonly use (30,63.435). + void SetObliqueAngles(double alpha, double beta); + + // Description: + // Apply a transform to the camera. The camera position, focal-point, + // and view-up are re-calulated using the transform's matrix to + // multiply the old points by the new transform. + void ApplyTransform(vtkTransform *t); + + // Description: + // Get the ViewPlaneNormal. This vector will point opposite to + // the direction of projection, unless you have created an sheared output + // view using SetViewShear/SetObliqueAngles. + vtkGetVector3Macro(ViewPlaneNormal,double); + + // Description: + // Set/get the shear transform of the viewing frustum. Parameters are + // dx/dz, dy/dz, and center. center is a factor that describes where + // to shear around. The distance dshear from the camera where + // no shear occurs is given by (dshear = center * FocalDistance). + void SetViewShear(double dxdz, double dydz, double center); + void SetViewShear(double d[3]); + vtkGetVector3Macro(ViewShear, double); + + // Description: + // Set/Get the separation between eyes (in degrees). This is used + // when generating stereo images. + vtkSetMacro(EyeAngle,double); + vtkGetMacro(EyeAngle,double); + + // Description: + // Set the size of the cameras lens in world coordinates. This is only + // used when the renderer is doing focal depth rendering. When that is + // being done the size of the focal disk will effect how significant the + // depth effects will be. + vtkSetMacro(FocalDisk,double); + vtkGetMacro(FocalDisk,double); + + // Description: + // Return the matrix of the view transform. + virtual vtkMatrix4x4 *GetViewTransformMatrix(); + + // Description: + // Return the perspective transform matrix, which converts from camera + // coordinates to viewport coordinates. The 'aspect' is the + // width/height for the viewport, and the nearz and farz are the + // Z-buffer values that map to the near and far clipping planes. + // The viewport coordinates are in the range ([-1,+1],[-1,+1],[nearz,farz]). + virtual vtkMatrix4x4 *GetPerspectiveTransformMatrix(double aspect, + double nearz, + double farz); + + // Description: + // Return the concatenation of the ViewTransform and the + // PerspectiveTransform. This transform will convert world + // coordinates to view coordinates. The 'aspect' is the + // width/height for the viewport, and the nearz and farz are the + // Z-buffer values that map to the near and far clipping planes. + // The view coordinates are in the range ([-1,+1],[-1,+1],[nearz,farz]). + virtual vtkMatrix4x4 *GetCompositePerspectiveTransformMatrix(double aspect, + double nearz, + double farz); + + // Description: + // In addition to the instance variables such as position and orientation, + // you can add an additional transformation for your own use. This + // transformation is concatenated to the camera's PerspectiveTransform + void SetUserTransform(vtkHomogeneousTransform *transform); + vtkGetObjectMacro(UserTransform,vtkHomogeneousTransform); + + // Description: + // This method causes the camera to set up whatever is required for + // viewing the scene. This is actually handled by an subclass of + // vtkCamera, which is created through New() + virtual void Render(vtkRenderer *) {}; + + // Description: + // Return the MTime that concerns recomputing the view rays of the camera. + unsigned long GetViewingRaysMTime(); + + // Description: + // Mark that something has changed which requires the view rays + // to be recomputed. + void ViewingRaysModified(); + + // Description: + // Get the plane equations that bound the view frustum. + // The plane normals point inward. The planes array contains six + // plane equations of the form (Ax+By+Cz+D=0), the first four + // values are (A,B,C,D) which repeats for each of the planes. + // The aspect of the viewport is needed to correctly compute the planes + virtual void GetFrustumPlanes(double aspect, double planes[24]); + + // Description: + // Get the orientation of the camera. + double *GetOrientation(); + double *GetOrientationWXYZ(); + + // Description: + // These methods have been deprecated. The view plane normal is + // automatically set from the DirectionOfProjection according to + // the ViewShear. + void SetViewPlaneNormal(double x, double y, double z); + void SetViewPlaneNormal(const double a[3]) { + this->SetViewPlaneNormal(a[0], a[1], a[2]); }; + + // Description: + // This method is called automatically whenever necessary, it + // should never be used outside of vtkCamera.cxx. + void ComputeViewPlaneNormal(); + + // Description: + // Returns a transformation matrix for a coordinate frame attached to + // the camera, where the camera is located at (0, 0, 1) looking at the + // focal point at (0, 0, 0), with up being (0, 1, 0). + vtkMatrix4x4 *GetCameraLightTransformMatrix(); + + // Description: + // Update the viewport + virtual void UpdateViewport(vtkRenderer *vtkNotUsed(ren)) {} + + virtual vtkTransform *GetViewTransformObject() {return this->ViewTransform;}; + +protected: + vtkCamera(); + ~vtkCamera(); + + // Description: + // These methods should only be used within vtkCamera.cxx. + void ComputeDistance(); + void ComputeViewTransform(); + void ComputePerspectiveTransform(double aspect, double nearz, double farz); + void ComputeCompositePerspectiveTransform(double aspect, + double nearz, double farz); + void ComputeCameraLightTransform(); + + double WindowCenter[2]; + double ObliqueAngles[2]; + double FocalPoint[3]; + double Position[3]; + double ViewUp[3]; + double ViewAngle; + double ClippingRange[2]; + double EyeAngle; + int ParallelProjection; + double ParallelScale; + int Stereo; + int LeftEye; + double Thickness; + double Distance; + double DirectionOfProjection[3]; + double ViewPlaneNormal[3]; + double ViewShear[3]; + int UseHorizontalViewAngle; + vtkHomogeneousTransform *UserTransform; + + vtkTransform *ViewTransform; + vtkPerspectiveTransform *PerspectiveTransform; + vtkPerspectiveTransform *Transform; + vtkTransform *CameraLightTransform; + + double FocalDisk; + + // ViewingRaysMtime keeps track of camera modifications which will + // change the calculation of viewing rays for the camera before it is + // transformed to the camera's location and orientation. + vtkTimeStamp ViewingRaysMTime; +private: + vtkCamera(const vtkCamera&); // Not implemented. + void operator=(const vtkCamera&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkCameraInterpolator.cxx b/Rendering/vtkCameraInterpolator.cxx new file mode 100644 index 0000000..7973217 --- /dev/null +++ b/Rendering/vtkCameraInterpolator.cxx @@ -0,0 +1,570 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCameraInterpolator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCameraInterpolator.h" +#include "vtkObjectFactory.h" +#include "vtkCamera.h" +#include "vtkTransform.h" +#include "vtkTupleInterpolator.h" +#include + +vtkCxxRevisionMacro(vtkCameraInterpolator, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkCameraInterpolator); + +// PIMPL STL encapsulation for list of cameras. This just keeps track of all +// the data the user specifies, which is later dumped into the interpolators. +struct vtkICamera +{ + double Time; //Parameter t + double P[3]; //Position + double FP[3]; //Focal point + double VUP[3];//ViewUp + double CR[2]; //Clipping range + double VA[1]; //View angle + double PS[1]; //Parallel scale + + vtkICamera() + { + this->Time = 0.0; + this->P[0] = this->P[1] = this->P[2] = 0.0; + this->FP[0] = this->FP[1] = this->FP[2] = 0.0; + this->VUP[0] = this->VUP[1] = this->VUP[2] = 0.0; + this->CR[0] = 1.0; this->CR[0] = 1000.0; + this->VA[0] = 30.0; + this->PS[0] = 1.0; + } + vtkICamera(double t, vtkCamera *camera) + { + this->Time = t; + if ( camera ) + { + camera->GetPosition(this->P); + camera->GetFocalPoint(this->FP); + camera->GetViewUp(this->VUP); + camera->GetClippingRange(this->CR); + this->VA[0] = camera->GetViewAngle(); + this->PS[0] = camera->GetParallelScale(); + } + else + { + this->P[0] = this->P[1] = this->P[2] = 0.0; + this->FP[0] = this->FP[1] = this->FP[2] = 0.0; + this->VUP[0] = this->VUP[1] = this->VUP[2] = 0.0; + this->CR[0] = 1.0; this->CR[0] = 1000.0; + this->VA[0] = 30.0; + this->PS[0] = 1.0; + } + } +}; + +// The list is arranged in increasing order in T +class vtkCameraList : public vtkstd::list {}; +typedef vtkCameraList::iterator CameraListIterator; + + +//---------------------------------------------------------------------------- +vtkCameraInterpolator::vtkCameraInterpolator() +{ + // Set up the interpolation + this->InterpolationType = INTERPOLATION_TYPE_SPLINE; + + // Spline interpolation + this->PositionInterpolator = vtkTupleInterpolator::New(); + this->FocalPointInterpolator = vtkTupleInterpolator::New(); + this->ViewUpInterpolator = vtkTupleInterpolator::New(); + this->ViewAngleInterpolator = vtkTupleInterpolator::New(); + this->ParallelScaleInterpolator = vtkTupleInterpolator::New(); + this->ClippingRangeInterpolator = vtkTupleInterpolator::New(); + + // Track the important camera parameters + this->CameraList = new vtkCameraList; + this->Initialized = 0; +} + +//---------------------------------------------------------------------------- +vtkCameraInterpolator::~vtkCameraInterpolator() +{ + delete this->CameraList; + + this->SetPositionInterpolator(NULL); + this->SetFocalPointInterpolator(NULL); + this->SetViewUpInterpolator(NULL); + this->SetViewAngleInterpolator(NULL); + this->SetParallelScaleInterpolator(NULL); + this->SetClippingRangeInterpolator(NULL); +} + +//---------------------------------------------------------------------------- +unsigned long vtkCameraInterpolator::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long posMTime, fpMTime, vupMTime, vaMTime, psMTime, crMTime; + + if ( this->PositionInterpolator ) + { + posMTime = this->PositionInterpolator->GetMTime(); + mTime = (posMTime > mTime ? posMTime : mTime); + } + if ( this->FocalPointInterpolator ) + { + fpMTime = this->FocalPointInterpolator->GetMTime(); + mTime = (fpMTime > mTime ? fpMTime : mTime); + } + if ( this->ViewUpInterpolator ) + { + vupMTime = this->ViewUpInterpolator->GetMTime(); + mTime = (vupMTime > mTime ? vupMTime : mTime); + } + if ( this->ViewAngleInterpolator ) + { + vaMTime = this->ViewAngleInterpolator->GetMTime(); + mTime = (vaMTime > mTime ? vaMTime : mTime); + } + if ( this->ParallelScaleInterpolator ) + { + psMTime = this->ParallelScaleInterpolator->GetMTime(); + mTime = (psMTime > mTime ? psMTime : mTime); + } + if ( this->ClippingRangeInterpolator ) + { + crMTime = this->ClippingRangeInterpolator->GetMTime(); + mTime = (crMTime > mTime ? crMTime : mTime); + } + + return mTime; +} + + +//---------------------------------------------------------------------------- +int vtkCameraInterpolator::GetNumberOfCameras() +{ + return this->CameraList->size(); +} + + +//---------------------------------------------------------------------------- +double vtkCameraInterpolator::GetMinimumT() +{ + if ( this->CameraList->empty() ) + { + return -VTK_LARGE_FLOAT; + } + else + { + return this->CameraList->front().Time; + } +} + + +//---------------------------------------------------------------------------- +double vtkCameraInterpolator::GetMaximumT() +{ + if ( this->CameraList->empty() ) + { + return VTK_LARGE_FLOAT; + } + else + { + return this->CameraList->back().Time; + } +} + + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::Initialize() +{ + this->CameraList->clear(); + this->Initialized = 0; +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::AddCamera(double t, vtkCamera *camera) +{ + int size = this->CameraList->size(); + + // Check special cases: t at beginning or end of list + if ( size <= 0 || t < this->CameraList->front().Time ) + { + this->CameraList->push_front(vtkICamera(t,camera)); + return; + } + else if ( t > this->CameraList->back().Time ) + { + this->CameraList->push_back(vtkICamera(t,camera)); + return; + } + else if ( size == 1 && t == this->CameraList->back().Time ) + { + this->CameraList->front() = vtkICamera(t,camera); + return; + } + + // Okay, insert in sorted order + CameraListIterator iter = this->CameraList->begin(); + CameraListIterator nextIter = ++(this->CameraList->begin()); + for (int i=0; i < (size-1); i++, ++iter, ++nextIter) + { + if ( t == iter->Time ) + { + (*iter) = vtkICamera(t,camera); + } + else if ( t > iter->Time && t < nextIter->Time ) + { + this->CameraList->insert(nextIter, vtkICamera(t,camera)); + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::RemoveCamera(double t) +{ + if ( t < this->CameraList->front().Time || + t > this->CameraList->back().Time ) + { + return; + } + + CameraListIterator iter = this->CameraList->begin(); + for ( ; iter->Time != t && iter != this->CameraList->end(); ++iter ) + { + } + if ( iter != this->CameraList->end() ) + { + this->CameraList->erase(iter); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::SetPositionInterpolator(vtkTupleInterpolator *pi) +{ + if ( this->PositionInterpolator != pi ) + { + if ( this->PositionInterpolator != NULL ) + { + this->PositionInterpolator->Delete(); + } + this->PositionInterpolator = pi; + if ( this->PositionInterpolator != NULL ) + { + this->PositionInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::SetFocalPointInterpolator(vtkTupleInterpolator *fpi) +{ + if ( this->FocalPointInterpolator != fpi ) + { + if ( this->FocalPointInterpolator != NULL ) + { + this->FocalPointInterpolator->Delete(); + } + this->FocalPointInterpolator = fpi; + if ( this->FocalPointInterpolator != NULL ) + { + this->FocalPointInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::SetViewUpInterpolator(vtkTupleInterpolator *vupi) +{ + if ( this->ViewUpInterpolator != vupi ) + { + if ( this->ViewUpInterpolator != NULL ) + { + this->ViewUpInterpolator->Delete(); + } + this->ViewUpInterpolator = vupi; + if ( this->ViewUpInterpolator != NULL ) + { + this->ViewUpInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::SetClippingRangeInterpolator(vtkTupleInterpolator *cri) +{ + if ( this->ClippingRangeInterpolator != cri ) + { + if ( this->ClippingRangeInterpolator != NULL ) + { + this->ClippingRangeInterpolator->Delete(); + } + this->ClippingRangeInterpolator = cri; + if ( this->ClippingRangeInterpolator != NULL ) + { + this->ClippingRangeInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::SetParallelScaleInterpolator(vtkTupleInterpolator *psi) +{ + if ( this->ParallelScaleInterpolator != psi ) + { + if ( this->ParallelScaleInterpolator != NULL ) + { + this->ParallelScaleInterpolator->Delete(); + } + this->ParallelScaleInterpolator = psi; + if ( this->ParallelScaleInterpolator != NULL ) + { + this->ParallelScaleInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::SetViewAngleInterpolator(vtkTupleInterpolator *vai) +{ + if ( this->ViewAngleInterpolator != vai ) + { + if ( this->ViewAngleInterpolator != NULL ) + { + this->ViewAngleInterpolator->Delete(); + } + this->ViewAngleInterpolator = vai; + if ( this->ViewAngleInterpolator != NULL ) + { + this->ViewAngleInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::InitializeInterpolation() +{ + if ( this->CameraList->empty() ) + { + return; + } + + // Set up the interpolators if we need to + if ( !this->Initialized || this->GetMTime() > this->InitializeTime ) + { + if ( !this->PositionInterpolator ) + { + this->PositionInterpolator = vtkTupleInterpolator::New(); + } + if ( !this->FocalPointInterpolator ) + { + this->FocalPointInterpolator = vtkTupleInterpolator::New(); + } + if ( !this->ViewUpInterpolator ) + { + this->ViewUpInterpolator = vtkTupleInterpolator::New(); + } + if ( !this->ClippingRangeInterpolator ) + { + this->ClippingRangeInterpolator = vtkTupleInterpolator::New(); + } + if ( !this->ParallelScaleInterpolator ) + { + this->ParallelScaleInterpolator = vtkTupleInterpolator::New(); + } + if ( !this->ViewAngleInterpolator ) + { + this->ViewAngleInterpolator = vtkTupleInterpolator::New(); + } + + this->PositionInterpolator->Initialize(); + this->FocalPointInterpolator->Initialize(); + this->ViewUpInterpolator->Initialize(); + this->ClippingRangeInterpolator->Initialize(); + this->ParallelScaleInterpolator->Initialize(); + this->ViewAngleInterpolator->Initialize(); + + this->PositionInterpolator->SetNumberOfComponents(3); + this->FocalPointInterpolator->SetNumberOfComponents(3); + this->ViewUpInterpolator->SetNumberOfComponents(3); + this->ClippingRangeInterpolator->SetNumberOfComponents(2); + this->ParallelScaleInterpolator->SetNumberOfComponents(1); + this->ViewAngleInterpolator->SetNumberOfComponents(1); + + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + this->PositionInterpolator->SetInterpolationTypeToLinear(); + this->FocalPointInterpolator->SetInterpolationTypeToLinear(); + this->ViewUpInterpolator->SetInterpolationTypeToLinear(); + this->ClippingRangeInterpolator->SetInterpolationTypeToLinear(); + this->ParallelScaleInterpolator->SetInterpolationTypeToLinear(); + this->ViewAngleInterpolator->SetInterpolationTypeToLinear(); + } + else if ( this->InterpolationType == INTERPOLATION_TYPE_SPLINE ) + { + this->PositionInterpolator->SetInterpolationTypeToSpline(); + this->FocalPointInterpolator->SetInterpolationTypeToSpline(); + this->ViewUpInterpolator->SetInterpolationTypeToSpline(); + this->ClippingRangeInterpolator->SetInterpolationTypeToSpline(); + this->ParallelScaleInterpolator->SetInterpolationTypeToSpline(); + this->ViewAngleInterpolator->SetInterpolationTypeToSpline(); + } + else + { + ; //manual override, user manipulates interpolators directly + } + + // Okay, now we can load the interpolators with data + CameraListIterator iter = this->CameraList->begin(); + for ( ; iter != this->CameraList->end(); ++iter) + { + this->PositionInterpolator->AddTuple(iter->Time,iter->P); + this->FocalPointInterpolator->AddTuple(iter->Time,iter->FP); + this->ViewUpInterpolator->AddTuple(iter->Time,iter->VUP); + this->ClippingRangeInterpolator->AddTuple(iter->Time,iter->CR); + this->ViewAngleInterpolator->AddTuple(iter->Time,iter->VA); + this->ParallelScaleInterpolator->AddTuple(iter->Time,iter->PS); + } + + this->Initialized = 1; + this->InitializeTime.Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::InterpolateCamera(double t, vtkCamera *camera) +{ + if ( this->CameraList->empty() ) + { + return; + } + + // Make sure the camera and this class are initialized properly + this->InitializeInterpolation(); + + // Evaluate the interpolators + if ( t < this->CameraList->front().Time ) + { + t = this->CameraList->front().Time; + } + + else if ( t > this->CameraList->back().Time ) + { + t = this->CameraList->back().Time; + } + + double P[3],FP[3],VUP[3],CR[2],VA[1],PS[1]; + this->PositionInterpolator->InterpolateTuple(t,P); + this->FocalPointInterpolator->InterpolateTuple(t,FP); + this->ViewUpInterpolator->InterpolateTuple(t,VUP); + this->ClippingRangeInterpolator->InterpolateTuple(t,CR); + this->ViewAngleInterpolator->InterpolateTuple(t,VA); + this->ParallelScaleInterpolator->InterpolateTuple(t,PS); + + camera->SetPosition(P); + camera->SetFocalPoint(FP); + camera->SetViewUp(VUP); + camera->SetClippingRange(CR); + camera->SetViewAngle(VA[0]); + camera->SetParallelScale(PS[0]); +} + +//---------------------------------------------------------------------------- +void vtkCameraInterpolator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "There are " << this->GetNumberOfCameras() + << " cameras to be interpolated\n"; + + os << indent << "Interpolation Type: "; + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + os << "Linear\n"; + } + else if ( this->InterpolationType == INTERPOLATION_TYPE_SPLINE ) + { + os << "Spline\n"; + } + else //if ( this->InterpolationType == INTERPOLATION_TYPE_MANUAL ) + { + os << "Manual\n"; + } + + os << indent << "Position Interpolator: "; + if ( this->PositionInterpolator ) + { + os << this->PositionInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } + + os << indent << "Focal Point Interpolator: "; + if ( this->FocalPointInterpolator ) + { + os << this->FocalPointInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } + + os << indent << "View Up Interpolator: "; + if ( this->ViewUpInterpolator ) + { + os << this->ViewUpInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } + + os << indent << "Clipping Range Interpolator: "; + if ( this->ClippingRangeInterpolator ) + { + os << this->ClippingRangeInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } + + os << indent << "View Angle Interpolator: "; + if ( this->ViewAngleInterpolator ) + { + os << this->ViewAngleInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } + + os << indent << "Parallel Scale Interpolator: "; + if ( this->ParallelScaleInterpolator ) + { + os << this->ParallelScaleInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } +} + + + diff --git a/Rendering/vtkCameraInterpolator.h b/Rendering/vtkCameraInterpolator.h new file mode 100644 index 0000000..372d12e --- /dev/null +++ b/Rendering/vtkCameraInterpolator.h @@ -0,0 +1,189 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCameraInterpolator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCameraInterpolator - interpolate a series of cameras to update a new camera +// .SECTION Description +// This class is used to interpolate a series of cameras to update a +// specified camera. Either linear interpolation or spline interpolation may +// be used. The instance variables currently interpolated include position, +// focal point, view up, view angle, parallel scale, and clipping range. +// +// To use this class, specify the type of interpolation to use, and add a +// series of cameras at various times "t" to the list of cameras from which to +// interpolate. Then to interpolate in between cameras, simply invoke the +// function InterpolateCamera(t,camera) where "camera" is the camera to be +// updated with interpolated values. Note that "t" should be in the range +// (min,max) times specified with the AddCamera() method. If outside this +// range, the interpolation is clamped. This class copies the camera information +// (as compared to referencing the cameras) so you do not need to keep separate +// instances of the camera around for each camera added to the list of cameras +// to interpolate. +// +// .SECTION Caveats +// The interpolator classes are initialized the first time InterpolateCamera() +// is called. Any later changes to the interpolators, or additions to the list of +// cameras to be interpolated, causes a reinitialization of the +// interpolators the next time InterpolateCamera() is invoked. Thus the +// best performance is obtained by 1) configuring the interpolators, 2) adding +// all the cameras, and 3) finally performing interpolation. +// +// Currently position, focal point and view up are interpolated to define +// the orientation of the camera. Quaternion interpolation may be added in the +// future as an alternative interpolation method for camera orientation. + + +#ifndef __vtkCameraInterpolator_h +#define __vtkCameraInterpolator_h + +#include "vtkObject.h" + +class vtkCamera; +class vtkCameraList; +class vtkTupleInterpolator; +class vtkCameraList; + + +class VTK_RENDERING_EXPORT vtkCameraInterpolator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCameraInterpolator, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the class. + static vtkCameraInterpolator* New(); + + // Description: + // Return the number of cameras in the list of cameras. + int GetNumberOfCameras(); + + // Description: + // Obtain some information about the interpolation range. The numbers + // returned are undefined if the list of cameras is empty. + double GetMinimumT(); + double GetMaximumT(); + + // Description: + // Clear the list of cameras. + void Initialize(); + + // Description: + // Add another camera to the list of cameras defining + // the camera function. Note that using the same time t value + // more than once replaces the previous camera value at t. + // At least one camera must be added to define a function. + void AddCamera(double t, vtkCamera *camera); + + // Description: + // Delete the camera at a particular parameter t. If there is no + // camera defined at location t, then the method does nothing. + void RemoveCamera(double t); + + // Description: + // Interpolate the list of cameras and determine a new camera (i.e., + // fill in the camera provided). If t is outside the range of + // (min,max) values, then t is clamped to lie within this range. + void InterpolateCamera(double t, vtkCamera *camera); + +//BTX + // Description: + // Enums to control the type of interpolation to use. + enum {INTERPOLATION_TYPE_LINEAR=0, + INTERPOLATION_TYPE_SPLINE, + INTERPOLATION_TYPE_MANUAL + }; +//ETX + + // Description: + // These are convenience methods to switch between linear and spline + // interpolation. The methods simply forward the request for linear or + // spline interpolation to the instance variable interpolators (i.e., + // position, focal point, clipping range, orientation, etc.) + // interpolators. Note that if the InterpolationType is set to "Manual", + // then the interpolators are expected to be directly manipulated and this + // class does not forward the request for interpolation type to its + // interpolators. + vtkSetClampMacro(InterpolationType,int, INTERPOLATION_TYPE_LINEAR, + INTERPOLATION_TYPE_MANUAL); + vtkGetMacro(InterpolationType,int); + void SetInterpolationTypeToLinear() + {this->SetInterpolationType(INTERPOLATION_TYPE_LINEAR);} + void SetInterpolationTypeToSpline() + {this->SetInterpolationType(INTERPOLATION_TYPE_SPLINE);} + void SetInterpolationTypeToManual() + {this->SetInterpolationType(INTERPOLATION_TYPE_MANUAL);} + + // Description: + // Set/Get the tuple interpolator used to interpolate the position portion + // of the camera. Note that you can modify the behavior of the interpolator + // (linear vs spline interpolation; change spline basis) by manipulating + // the interpolator instances directly. + virtual void SetPositionInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(PositionInterpolator,vtkTupleInterpolator); + + // Description: + virtual void SetFocalPointInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(FocalPointInterpolator,vtkTupleInterpolator); + + // Description: + virtual void SetViewUpInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(ViewUpInterpolator,vtkTupleInterpolator); + + // Description: + virtual void SetViewAngleInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(ViewAngleInterpolator,vtkTupleInterpolator); + + // Description: + virtual void SetParallelScaleInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(ParallelScaleInterpolator,vtkTupleInterpolator); + + // Description: + virtual void SetClippingRangeInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(ClippingRangeInterpolator,vtkTupleInterpolator); + + // Description: + // Override GetMTime() because we depend on the interpolators which may be + // modified outside of this class. + unsigned long GetMTime(); + +protected: + vtkCameraInterpolator(); + virtual ~vtkCameraInterpolator(); + + // Control the interpolation type + int InterpolationType; + + // These perform the interpolation + vtkTupleInterpolator *PositionInterpolator; + vtkTupleInterpolator *FocalPointInterpolator; + vtkTupleInterpolator *ViewUpInterpolator; + vtkTupleInterpolator *ViewAngleInterpolator; + vtkTupleInterpolator *ParallelScaleInterpolator; + vtkTupleInterpolator *ClippingRangeInterpolator; + + // Initialize the interpolating splines + int Initialized; + vtkTimeStamp InitializeTime; + void InitializeInterpolation(); + + // Hold the list of cameras. PIMPL'd STL list. + vtkCameraList *CameraList; + +private: + vtkCameraInterpolator(const vtkCameraInterpolator&); // Not implemented. + void operator=(const vtkCameraInterpolator&); // Not implemented. + +}; + +#endif diff --git a/Rendering/vtkCarbonRenderWindow.cxx b/Rendering/vtkCarbonRenderWindow.cxx new file mode 100644 index 0000000..6819d6a --- /dev/null +++ b/Rendering/vtkCarbonRenderWindow.cxx @@ -0,0 +1,1202 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCarbonRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCarbonRenderWindow.h" + +#include "vtkCarbonRenderWindowInteractor.h" +#include "vtkIdList.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLActor.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLPolyDataMapper.h" +#include "vtkOpenGLProperty.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLTexture.h" +#include "vtkRendererCollection.h" + +#include + +vtkCxxRevisionMacro(vtkCarbonRenderWindow, "$Revision: 1.39 $"); +vtkStandardNewMacro(vtkCarbonRenderWindow); + +//---------------------------------------------------------------------------- +// Dump agl errors to string, return error code +OSStatus aglReportError () +{ + GLenum err = aglGetError(); + if (AGL_NO_ERROR != err) + cout << ((char *)aglErrorString(err)); + // ensure we are returning an OSStatus noErr if no error condition + if (err == AGL_NO_ERROR) + return noErr; + else + return (OSStatus) err; +} + +//---------------------------------------------------------------------------- +// if error dump gl errors, return error +OSStatus glReportError () +{ + GLenum err = glGetError(); + switch (err) + { + case GL_NO_ERROR: + break; + case GL_INVALID_ENUM: + cout << "GL Error: Invalid enumeration\n"; + break; + case GL_INVALID_VALUE: + cout << "GL Error: Invalid value\n"; + break; + case GL_INVALID_OPERATION: + cout << "GL Error: Invalid operation\n"; + break; + case GL_STACK_OVERFLOW: + cout << "GL Error: Stack overflow\n"; + break; + case GL_STACK_UNDERFLOW: + cout << "GL Error: Stack underflow\n"; + break; + case GL_OUT_OF_MEMORY: + cout << "GL Error: Out of memory\n"; + break; + } + // ensure we are returning an OSStatus noErr if no error condition + if (err == GL_NO_ERROR) + return noErr; + else + return (OSStatus) err; +} + +//---------------------------------------------------------------------------- +// CheckRenderer +// looks at renderer attributes it has at least the VRAM is accelerated +// Inputs: hGD: GDHandle to device to look at +// pVRAM: pointer to VRAM in bytes required; out is actual VRAM if +// a renderer was found, otherwise it is the input parameter +// pTextureRAM: pointer to texture RAM in bytes required; out is same +// (implementation assume VRAM returned by card is total +// so we add texture and VRAM) +// fAccelMust: do we check for acceleration +// Returns: true if renderer for the requested device complies, false otherwise +static Boolean CheckRenderer (GDHandle hGD, long* pVRAM, long* pTextureRAM, + GLint* pDepthSizeSupport, Boolean fAccelMust) +{ + AGLRendererInfo info, head_info; + GLint inum; + GLint dAccel = 0; + GLint dVRAM = 0, dMaxVRAM = 0; + Boolean canAccel = false, found = false; + head_info = aglQueryRendererInfo(&hGD, 1); + aglReportError(); + if(!head_info) + { + cout << "aglQueryRendererInfo error.\n"; + return false; + } + else + { + info = head_info; + inum = 0; + // Check for accelerated renderer, if so ignore non-accelerated ones + // Prevents returning info on software renderer when get a hardware one + while (info) + { + aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel); + aglReportError (); + if (dAccel) + canAccel = true; + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + + info = head_info; + inum = 0; + while (info) + { + aglDescribeRenderer (info, AGL_ACCELERATED, &dAccel); + aglReportError (); + // if we can accel then we will choose the accelerated renderer + // how about compliant renderers??? + if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel))) + { + aglDescribeRenderer (info, AGL_VIDEO_MEMORY, &dVRAM); + // we assume that VRAM returned is total thus add + // texture and VRAM required + aglReportError (); + if (dVRAM >= (*pVRAM + *pTextureRAM)) + { + if (dVRAM >= dMaxVRAM) // find card with max VRAM + { + aglDescribeRenderer (info, AGL_DEPTH_MODES, pDepthSizeSupport); + // which depth buffer modes are supported + aglReportError (); + dMaxVRAM = dVRAM; // store max + found = true; + } + } + } + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + } + aglDestroyRendererInfo(head_info); + if (found) // if found a card with enough VRAM and meets the accel criteria + { + *pVRAM = dMaxVRAM; // return VRAM + return true; + } + // VRAM will remain to same as it did when sent in + return false; +} + +//---------------------------------------------------------------------------- +// CheckAllDeviceRenderers +// looks at renderer attributes and each device must have at least one +// renderer that fits the profile. +// Inputs: pVRAM: pointer to VRAM in bytes required; +// out is actual min VRAM of all renderers found, +// otherwise it is the input parameter +// pTextureRAM: pointer to texture RAM in bytes required; +// out is same (implementation assumes VRAM returned +// by card is total so we add texture and VRAM) +// fAccelMust: do we check fro acceleration +// Returns: true if any renderer on each device complies (not necessarily +// the same renderer), false otherwise + +static Boolean CheckAllDeviceRenderers (long* pVRAM, long* pTextureRAM, + GLint* pDepthSizeSupport, + Boolean fAccelMust) +{ + AGLRendererInfo info, head_info; + GLint inum; + GLint dAccel = 0; + GLint dVRAM = 0, dMaxVRAM = 0; + Boolean canAccel = false, found = false, goodCheck = true; + long MinVRAM = 0x8FFFFFFF; // max long + GDHandle hGD = GetDeviceList (); // get the first screen + while (hGD && goodCheck) + { + head_info = aglQueryRendererInfo(&hGD, 1); + aglReportError (); + if(!head_info) + { + cout << "aglQueryRendererInfo error"; + return false; + } + else + { + info = head_info; + inum = 0; + // if accelerated renderer, ignore non-accelerated ones + // prevents returning info on software renderer when get hardware one + while (info) + { + aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel); + aglReportError (); + if (dAccel) + canAccel = true; + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + + info = head_info; + inum = 0; + while (info) + { + aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel); + aglReportError (); + // if we can accel then we will choose the accelerated renderer + // how about compliant renderers??? + if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel))) + { + aglDescribeRenderer(info, AGL_VIDEO_MEMORY, &dVRAM); + aglReportError (); + if (dVRAM >= (*pVRAM + *pTextureRAM)) + { + if (dVRAM >= dMaxVRAM) // find card with max VRAM + {// which depth buffer modes are supported + aglDescribeRenderer(info, AGL_DEPTH_MODES, pDepthSizeSupport); + aglReportError (); + dMaxVRAM = dVRAM; // store max + found = true; + } + } + } + info = aglNextRendererInfo(info); + aglReportError (); + inum++; + } + } + aglDestroyRendererInfo(head_info); + if (found) // found card with enough VRAM and meets the accel criteria + { + if (MinVRAM > dMaxVRAM) + { + MinVRAM = dMaxVRAM; // return VRAM + } + } + else + goodCheck = false; // one device failed thus entire requirement fails + hGD = GetNextDevice (hGD); // get next device + } // while + if (goodCheck) // we check all devices and each was good + { + *pVRAM = MinVRAM; // return VRAM + return true; + } + return false; //at least one device failed to have mins +} + +//-------------------------------------------------------------------------- +// FindGDHandleFromWindow +// Inputs: a valid WindowPtr +// Outputs: the GDHandle that that window is mostly on +// returns the number of devices that the windows content touches +short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice) +{ + GrafPtr pgpSave; + Rect rectWind, rectSect; + long greatestArea, sectArea; + short numDevices = 0; + GDHandle hgdNthDevice; + + if (!pWindow || !phgdOnThisDevice) + return 0; + + *phgdOnThisDevice = NULL; + + GetPort (&pgpSave); + SetPortWindowPort (pWindow); + + GetWindowPortBounds (pWindow, &rectWind); + LocalToGlobal ((Point*)& rectWind.top); + LocalToGlobal ((Point*)& rectWind.bottom); + hgdNthDevice = GetDeviceList (); + greatestArea = 0; + // check window against all gdRects in gDevice list and remember + // which gdRect contains largest area of window + while (hgdNthDevice) + { + if (TestDeviceAttribute (hgdNthDevice, screenDevice)) + if (TestDeviceAttribute (hgdNthDevice, screenActive)) + { + // The SectRect routine calculates the intersection + // of the window rectangle and this gDevice + // rectangle and returns TRUE if the rectangles intersect, + // FALSE if they don't. + SectRect (&rectWind, &(**hgdNthDevice).gdRect, &rectSect); + // determine which screen holds greatest window area + // first, calculate area of rectangle on current device + sectArea = (long) ((rectSect.right - rectSect.left) * + (rectSect.bottom - rectSect.top)); + if (sectArea > 0) + numDevices++; + if (sectArea > greatestArea) + { + greatestArea = sectArea; // set greatest area so far + *phgdOnThisDevice = hgdNthDevice; // set zoom device + } + hgdNthDevice = GetNextDevice(hgdNthDevice); + } + } + SetPort (pgpSave); + return numDevices; +} + +//-------------------------------------------------------------------------- +vtkCarbonRenderWindow::vtkCarbonRenderWindow() +{ + this->ApplicationInitialized = 0; + this->ContextId = 0; + this->MultiSamples = 8; + this->WindowId = 0; + this->ParentId = 0; + this->RootWindow = 0; + this->SetWindowName("Visualization Toolkit - Carbon"); + this->CursorHidden = 0; + this->ForceMakeCurrent = 0; + this->RegionEventHandlerUPP = 0; + this->RegionEventHandler = 0; +} + +// -------------------------------------------------------------------------- +vtkCarbonRenderWindow::~vtkCarbonRenderWindow() +{ + this->Finalize(); +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindow::Clean() +{ + GLuint txId; + + /* finish OpenGL rendering */ + if (this->ContextId) + { + this->MakeCurrent(); + + /* now delete all textures */ + glDisable(GL_TEXTURE_2D); + for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++) + { + txId = (GLuint) this->TextureResourceIds->GetId(i); +#ifdef GL_VERSION_1_1 + if (glIsTexture(txId)) + { + glDeleteTextures(1, &txId); + } +#else + if (glIsList(txId)) + { + glDeleteLists(txId,1); + } +#endif + } + + // tell each of the renderers that this render window/graphics context + // is being removed (the RendererCollection is removed by vtkRenderWindow's + // destructor) + vtkCollectionSimpleIterator rsit; + vtkRenderer *ren; + for ( this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(NULL); + } + + aglSetCurrentContext(this->ContextId); + aglDestroyContext(this->ContextId); + this->ContextId = NULL; + } +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetWindowName( const char * _arg ) +{ + vtkWindow::SetWindowName(_arg); + + if(this->OwnWindow) + { + CFStringRef newTitle = + CFStringCreateWithCString(kCFAllocatorDefault, _arg, + kCFStringEncodingASCII); + SetWindowTitleWithCFString(this->RootWindow, newTitle); + CFRelease(newTitle); + } +} + +//-------------------------------------------------------------------------- +int vtkCarbonRenderWindow::GetEventPending() +{ + return 0; +} + +//-------------------------------------------------------------------------- +// Set the window id to a pre-existing window. +void vtkCarbonRenderWindow::SetParentId(HIViewRef arg) +{ + vtkDebugMacro(<< "Setting ParentId to " << arg << "\n"); + + this->ParentId = arg; +} + +//-------------------------------------------------------------------------- +// Begin the rendering process. +void vtkCarbonRenderWindow::Start() +{ + // if the renderer has not been initialized, do so now + if (!this->ContextId) + { + this->Initialize(); + } + + // set the current window + this->MakeCurrent(); +} + +// -------------------------------------------------------------------------- +void vtkCarbonRenderWindow::MakeCurrent() +{ + if (this->ContextId || this->ForceMakeCurrent) + { + aglSetCurrentContext(this->ContextId); + this->ForceMakeCurrent = 0; + } +} + +// -------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetForceMakeCurrent() +{ + this->ForceMakeCurrent = 1; +} + +// -------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetSize(int a[2]) +{ + this->SetSize(a[0], a[1]); +} + +void vtkCarbonRenderWindow::UpdateGLRegion() +{ + // if WindowId is a child window + if(this->WindowId) + { + // Determine the AGL_BUFFER_RECT for the view. The coordinate + // system for this rectangle is relative to the owning window, with + // the origin at the bottom left corner and the y-axis inverted. + HIRect viewBounds, winBounds; + HIViewGetBounds(this->WindowId, &viewBounds); + HIViewRef root = HIViewGetRoot(this->GetRootWindow()); + HIViewRef content_root; + HIViewFindByID(root, kHIViewWindowContentID, &content_root); + + HIViewGetBounds(content_root, &winBounds); + HIViewConvertRect(&viewBounds, this->WindowId, content_root); + GLint bufferRect[4] = { GLint(viewBounds.origin.x), + GLint((winBounds.size.height) - (viewBounds.origin.y + viewBounds.size.height)), + GLint(viewBounds.size.width), + GLint(viewBounds.size.height) }; + if(!HIViewIsVisible(this->WindowId)) + { + bufferRect[0] = 0; + bufferRect[1] = 0; + bufferRect[2] = 0; + bufferRect[3] = 0; + } + + // Associate the OpenGL context with the control's window, and establish the buffer rect. + aglSetDrawable(this->ContextId, GetWindowPort(this->GetRootWindow())); + aglSetInteger(this->ContextId, AGL_BUFFER_RECT, bufferRect); + aglEnable(this->ContextId, AGL_BUFFER_RECT); + + // Establish the clipping region for the OpenGL context. To properly handle clipping + // within the view hierarchy, walk the hierarchy to determine the intersection + // of this view's bounds with its children, siblings, and parents also taking into + // account z-ordering of the views + RgnHandle rgn = NewRgn(); + RgnHandle tmp_rgn = NewRgn(); + + GetControlRegion(this->WindowId, kControlStructureMetaPart, rgn); + HIViewConvertRegion(rgn, this->WindowId, content_root); + + HIViewRef current_view = NULL; + HIViewRef child = NULL; + HIViewRef last = NULL; + + for(current_view = this->WindowId; + (current_view != NULL); + current_view = HIViewGetSuperview(current_view)) + { + if(last) + { + // clip view within parent bounds + GetControlRegion(current_view, kControlStructureMetaPart, tmp_rgn); + HIViewConvertRegion(tmp_rgn, current_view, content_root); + DiffRgn(rgn, tmp_rgn, tmp_rgn); + DiffRgn(rgn, tmp_rgn, rgn); + } + for(child = HIViewGetFirstSubview(current_view); + (child != last) && (child != NULL); + child = HIViewGetNextView(child)) + { + if(child != last && HIViewIsVisible(child)) + { + GetControlRegion(child, kControlStructureMetaPart, tmp_rgn); + HIViewConvertRegion(tmp_rgn, child, content_root); + DiffRgn(rgn, tmp_rgn, rgn); + } + } + last = current_view; + } + + GetControlRegion(this->WindowId, kControlStructureMetaPart, tmp_rgn); + + if(EqualRgn(rgn,tmp_rgn)) + { + if(aglIsEnabled(this->ContextId, AGL_CLIP_REGION)) + aglDisable(this->ContextId, AGL_CLIP_REGION); + } + else + { + if(!aglIsEnabled(this->ContextId, AGL_CLIP_REGION)) + aglEnable(this->ContextId, AGL_CLIP_REGION); + aglSetInteger(this->ContextId, AGL_CLIP_REGION, reinterpret_cast(rgn)); + } + + DisposeRgn(rgn); + DisposeRgn(tmp_rgn); + + } + // this is provided for backwards compatibility + else if(this->WindowId == 0 && this->RootWindow && this->ParentId) + { + GLint bufRect[4]; + Rect windowRect; + GetWindowBounds(this->RootWindow, kWindowContentRgn, &windowRect); + bufRect[0] = this->Position[0]; + bufRect[1] = (int) (windowRect.bottom-windowRect.top) + - (this->Position[1]+this->Size[1]); + bufRect[2] = this->Size[0]; + bufRect[3] = this->Size[1]; + aglEnable(this->ContextId, AGL_BUFFER_RECT); + aglSetInteger(this->ContextId, AGL_BUFFER_RECT, bufRect); + } + + aglUpdateContext(this->ContextId); + +} + +// -------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetSize(int x, int y) +{ + static int resizing = 0; + + if ((this->Size[0] != x) || (this->Size[1] != y)) + { + this->Modified(); + this->Size[0] = x; + this->Size[1] = y; + if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + if(this->ParentId && this->RootWindow && !this->WindowId) + { + // backwards compatiblity with Tk and who else? + UpdateGLRegion(); + } + else if(this->OwnWindow || !this->WindowId) + { + SizeWindow(this->RootWindow, x, y, TRUE); + } + resizing = 0; + } + } + } +} + +// -------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetPosition(int a[2]) +{ + this->SetPosition(a[0], a[1]); +} + +// -------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetPosition(int x, int y) +{ + static int resizing = 0; + + if ((this->Position[0] != x) || (this->Position[1] != y)) + { + this->Modified(); + this->Position[0] = x; + this->Position[1] = y; + if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + if(this->ParentId && this->RootWindow && !this->WindowId) + { + // backwards compatiblity with Tk and who else? + UpdateGLRegion(); + } + else if(this->OwnWindow || !this->WindowId) + { + MoveWindow(this->RootWindow, x, y, FALSE); + } + + resizing = 0; + } + } + } +} + + +//-------------------------------------------------------------------------- +// End the rendering process and display the image. +void vtkCarbonRenderWindow::Frame() +{ + if (!this->AbortRender && this->DoubleBuffer) + { + aglSwapBuffers(this->ContextId); + vtkDebugMacro(<< " SwapBuffers\n"); + } +} + +//-------------------------------------------------------------------------- +// Specify various window parameters. +void vtkCarbonRenderWindow::WindowConfigure() +{ + // this is all handled by the desiredVisualInfo method +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetupPixelFormat(void*, void*, int, int, int) +{ + cout << "vtkCarbonRenderWindow::SetupPixelFormat - IMPLEMENT\n"; +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindow::SetupPalette(void*) +{ + cout << "vtkCarbonRenderWindow::SetupPalette - IMPLEMENT\n"; +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindow::InitializeApplication() +{ + if (!this->ApplicationInitialized) + { + if (this->OwnWindow) + { // Initialize the Toolbox managers if we are running the show + InitCursor(); + DrawMenuBar(); + this->ApplicationInitialized=1; + } + } +} + +//-------------------------------------------------------------------------- +// Initialize the window for rendering. +void vtkCarbonRenderWindow::CreateAWindow(int vtkNotUsed(x), int vtkNotUsed(y), + int vtkNotUsed(width), int vtkNotUsed(height)) +{ + GDHandle hGD = NULL; + GLint depthSizeSupport; + static int count = 1; + short i; + char *windowName; + short numDevices; // number of graphics devices our window covers + + if ((this->Size[0]+this->Size[1])==0) + { + this->Size[0]=300; + this->Size[1]=300; + } + if ((this->Position[0]+this->Position[1])==0) + { + this->Position[0]=50; + this->Position[1]=50; + } + + // Rect is defined as {top, left, bottom, right} (really) + Rect rectWin = {this->Position[1], this->Position[0], + this->Position[1]+this->Size[1], + this->Position[0]+this->Size[0]}; + + // if a Window and HIView wasn't given, make a Window and HIView + if (!this->WindowId && !this->RootWindow) + { + WindowAttributes windowAttrs = (kWindowStandardDocumentAttributes | + kWindowLiveResizeAttribute | + kWindowStandardHandlerAttribute | + kWindowCompositingAttribute); + + if (noErr != CreateNewWindow (kDocumentWindowClass, + windowAttrs, + &rectWin, &(this->RootWindow))) + { + vtkErrorMacro("Could not create window, serious error!"); + return; + } + + // get the content view + HIViewFindByID(HIViewGetRoot(this->RootWindow), + kHIViewWindowContentID, + &this->WindowId); + + int len = (strlen("vtkX - Carbon #") + + (int) ceil((double)log10((double)(count+1))) + + 1); + windowName = new char [ len ]; + sprintf(windowName,"vtkX - Carbon #%i",count++); + this->SetWindowName(windowName); + delete [] windowName; + this->OwnWindow = 1; + + ShowWindow(this->RootWindow); + } + + + // install event handler for updating gl region + // this works for a supplied HIView and an HIView made here + if(this->WindowId && !this->RegionEventHandler) + { + EventTypeSpec region_events [] = + { + { kEventClassControl, kEventControlOwningWindowChanged}, + { kEventClassControl, kEventControlVisibilityChanged }, + { kEventClassControl, kEventControlBoundsChanged } + }; + this->RegionEventHandlerUPP = NewEventHandlerUPP(vtkCarbonRenderWindow::RegionEventProcessor); + InstallControlEventHandler(this->WindowId, this->RegionEventHandlerUPP, + GetEventTypeCount(region_events), region_events, + reinterpret_cast(this), &this->RegionEventHandler); + } + + SetPortWindowPort(this->GetRootWindow()); + this->fAcceleratedMust = false; //must renderer be accelerated? + this->VRAM = 0 * 1048576; // minimum VRAM + this->textureRAM = 0 * 1048576; // minimum texture RAM + this->fmt = 0; // output pixel format + i = 0; + this->aglAttributes [i++] = AGL_RGBA; + this->aglAttributes [i++] = AGL_DOUBLEBUFFER; + this->aglAttributes [i++] = AGL_DEPTH_SIZE; + this->aglAttributes [i++] = 32; + this->aglAttributes [i++] = AGL_PIXEL_SIZE; + this->aglAttributes [i++] = 32; + this->aglAttributes [i++] = AGL_ACCELERATED; + if (this->AlphaBitPlanes) + { + this->aglAttributes [i++] = AGL_ALPHA_SIZE; + this->aglAttributes [i++] = 8; + } + this->aglAttributes [i++] = AGL_NONE; + this->draggable = true; + + numDevices = FindGDHandleFromWindow(this->GetRootWindow(), &hGD); + if (!this->draggable) + { + if ((numDevices > 1) || (numDevices == 0)) // multiple or no devices + { + // software renderer + // infinite VRAM, infinite textureRAM, not accelerated + if (this->fAcceleratedMust) + { + vtkErrorMacro ("Window spans multiple devices-no HW accel"); + return; + } + } + else // not draggable on single device + { + if (!CheckRenderer (hGD, &(this->VRAM), &(this->textureRAM), + &depthSizeSupport, this->fAcceleratedMust)) + { + vtkErrorMacro ("Renderer check failed"); + return; + } + } + } + // else if draggable - must check all devices for presence of + // at least one renderer that meets the requirements + else if(!CheckAllDeviceRenderers(&(this->VRAM), &(this->textureRAM), + &depthSizeSupport, this->fAcceleratedMust)) + { + vtkErrorMacro ("Renderer check failed"); + return; + } + + // do agl + if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) + { + vtkErrorMacro ("OpenGL not installed"); + return; + } + // we successfully passed the renderer checks! + + if ((!this->draggable && (numDevices == 1))) + {// not draggable on a single device + this->fmt = aglChoosePixelFormat (&hGD, 1, this->aglAttributes); + } + else + { + this->fmt = aglChoosePixelFormat (NULL, 0, this->aglAttributes); + } + aglReportError (); // cough up any errors encountered + if (NULL == this->fmt) + { + vtkErrorMacro("Could not find valid pixel format"); + return; + } + + this->ContextId = aglCreateContext (this->fmt, 0); // create without sharing + aglReportError (); // cough up errors + if (NULL == this->ContextId) + { + vtkErrorMacro ("Could not create context"); + return; + } + // attach the CGrafPtr to the context + if (!aglSetDrawable (this->ContextId, GetWindowPort (this->GetRootWindow()))) + { + aglReportError(); + return; + } + + if(!aglSetCurrentContext (this->ContextId)) + // make the context the current context + { + aglReportError(); + return; + } + + this->OpenGLInit(); + this->Mapped = 1; + UpdateGLRegion(); +} + +//-------------------------------------------------------------------------- +// Initialize the window for rendering. +void vtkCarbonRenderWindow::WindowInitialize() +{ + int x, y, width, height; + x = ((this->Position[0] >= 0) ? this->Position[0] : 5); + y = ((this->Position[1] >= 0) ? this->Position[1] : 5); + height = ((this->Size[1] > 0) ? this->Size[1] : 300); + width = ((this->Size[0] > 0) ? this->Size[0] : 300); + + // create our own window if not already set + this->OwnWindow = 0; + this->InitializeApplication(); + this->CreateAWindow(x,y,width,height); + + // tell our renderers about us + vtkRenderer* ren; + for (this->Renderers->InitTraversal(); + (ren = this->Renderers->GetNextItem());) + { + ren->SetRenderWindow(0); + ren->SetRenderWindow(this); + } + + // set the DPI + this->SetDPI(72); // this may need to be more clever some day +} + +//-------------------------------------------------------------------------- +// Initialize the rendering window. +void vtkCarbonRenderWindow::Initialize () +{ + // make sure we havent already been initialized + + if (this->ContextId) + { + return; + } + + this->WindowInitialize(); +} + +void vtkCarbonRenderWindow::Finalize(void) +{ + if (this->CursorHidden) + { + this->ShowCursor(); + } + + if (this->OffScreenRendering) // does not exist yet + { + //this->CleanUpOffScreenRendering() + } + + this->Clean(); + + // remove event filters if we have them + if(this->RegionEventHandler) + { + RemoveEventHandler(this->RegionEventHandler); + DisposeEventHandlerUPP(this->RegionEventHandlerUPP); + this->RegionEventHandler = 0; + this->RegionEventHandlerUPP = 0; + } + + if (this->RootWindow && this->OwnWindow) + { + DisposeWindow(this->RootWindow); + } +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindow::UpdateSizeAndPosition(int xPos, int yPos, + int xSize, int ySize) +{ + this->Size[0]=xSize; + this->Size[1]=ySize; + this->Position[0]=xPos; + this->Position[1]=yPos; + this->Modified(); +} + +//-------------------------------------------------------------------------- +// Get the current size of the window. +int *vtkCarbonRenderWindow::GetSize() +{ + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Superclass::GetSize(); + } + + if(this->WindowId) + { + HIRect viewBounds; + HIViewGetBounds(this->WindowId, &viewBounds); + this->Size[0] = (int)viewBounds.size.width; + this->Size[1] = (int)viewBounds.size.height; + } + + return this->Superclass::GetSize(); +} + +//-------------------------------------------------------------------------- +// Get the current size of the screen. +int *vtkCarbonRenderWindow::GetScreenSize() +{ + cout << "Inside vtkCarbonRenderWindow::GetScreenSize - MUST IMPLEMENT\n"; + this->Size[0] = 0; + this->Size[1] = 0; + + return this->Size; +} + +//-------------------------------------------------------------------------- +// Get the position in screen coordinates of the window. +int *vtkCarbonRenderWindow::GetPosition() +{ + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Position; + } + + if(!this->WindowId && !this->ParentId) + { + // Find the current window position + Rect windowRect; + GetWindowBounds(this->GetRootWindow(), kWindowContentRgn, &windowRect); + this->Position[0] = windowRect.left; + this->Position[1] = windowRect.top; + } + else + { + HIRect viewBounds; + HIViewGetBounds(this->WindowId, &viewBounds); + Rect windowRect; + GetWindowBounds(this->GetRootWindow(), kWindowContentRgn, &windowRect); + this->Position[0] = ((int)viewBounds.origin.x) + windowRect.left; + this->Position[1] = ((int)viewBounds.origin.y) + windowRect.top; + } + + return this->Position; +} + +//-------------------------------------------------------------------------- +// Change the window to fill the entire screen. +void vtkCarbonRenderWindow::SetFullScreen(int arg) +{ + int *temp; + + if (this->FullScreen == arg) + { + return; + } + + if (!this->Mapped) + { + this->PrefFullScreen(); + return; + } + + // set the mode + this->FullScreen = arg; + if (this->FullScreen <= 0) + { + this->Position[0] = this->OldScreen[0]; + this->Position[1] = this->OldScreen[1]; + this->Size[0] = this->OldScreen[2]; + this->Size[1] = this->OldScreen[3]; + this->Borders = this->OldScreen[4]; + } + else + { + // if window already up get its values + if (this->WindowId) + { + temp = this->GetPosition(); + this->OldScreen[0] = temp[0]; + this->OldScreen[1] = temp[1]; + + this->OldScreen[4] = this->Borders; + this->PrefFullScreen(); + } + } + + // remap the window + this->WindowRemap(); + + this->Modified(); +} + +//-------------------------------------------------------------------------- +// Set the variable that indicates that we want a stereo capable window +// be created. This method can only be called before a window is realized. +void vtkCarbonRenderWindow::SetStereoCapableWindow(int capable) +{ + if (this->WindowId == 0) + { + vtkRenderWindow::SetStereoCapableWindow(capable); + } + else + { + vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed " + << "before the window is realized, i.e. before a render."); + } +} + +//-------------------------------------------------------------------------- +// Set the preferred window size to full screen. +void vtkCarbonRenderWindow::PrefFullScreen() +{ + vtkWarningMacro(<< "Can't get full screen window."); +} + +//-------------------------------------------------------------------------- +// Remap the window. +void vtkCarbonRenderWindow::WindowRemap() +{ + vtkWarningMacro(<< "Can't remap the window."); +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ContextId: " << this->ContextId << "\n"; + os << indent << "MultiSamples: " << this->MultiSamples << "\n"; +} + +//-------------------------------------------------------------------------- +int vtkCarbonRenderWindow::GetDepthBufferSize() +{ + GLint size; + + if ( this->Mapped ) + { + size = 0; + glGetIntegerv( GL_DEPTH_BITS, &size ); + return (int) size; + } + else + { + vtkDebugMacro(<< "Window is not mapped yet!" ); + return 24; + } +} + +//-------------------------------------------------------------------------- +// Get the window id. +HIViewRef vtkCarbonRenderWindow::GetWindowId() +{ + vtkDebugMacro(<< "Returning WindowId of " << this->WindowId << "\n"); + return this->WindowId; +} + +//-------------------------------------------------------------------------- +// Set the window id to a pre-existing window. +void vtkCarbonRenderWindow::SetWindowId(HIViewRef theWindow) +{ + vtkDebugMacro(<< "Setting WindowId to " << theWindow << "\n"); + this->WindowId = theWindow; +} + +//-------------------------------------------------------------------------- +// Set this RenderWindow's Carbon window id to a pre-existing window. +void vtkCarbonRenderWindow::SetWindowInfo(char *info) +{ + long tmp; + + sscanf(info,"%ld",&tmp); + + this->WindowId = (HIViewRef)tmp; + vtkDebugMacro(<< "Setting WindowId to " << this->WindowId << "\n"); +} + +void vtkCarbonRenderWindow::SetRootWindow(WindowPtr win) +{ + vtkDebugMacro(<< "Setting RootWindow to " << win << "\n"); + this->RootWindow = win; +} + +WindowPtr vtkCarbonRenderWindow::GetRootWindow() +{ + // take into account whether the user set the root window or not. + // if not, then WindowId is set and we're using HIViews. + // Instead of storing the RootWindow, we ask for it in case of a dynamic + // GUI where the root window can change + return this->RootWindow ? this->RootWindow : HIViewGetWindow(this->WindowId); +} + +//---------------------------------------------------------------------------- +void vtkCarbonRenderWindow::HideCursor() +{ + if (this->CursorHidden) + { + return; + } + this->CursorHidden = 1; + HideCursor(); +} + +//---------------------------------------------------------------------------- +void vtkCarbonRenderWindow::ShowCursor() +{ + if (!this->CursorHidden) + { + return; + } + this->CursorHidden = 0; + ShowCursor(); +} + +OSStatus vtkCarbonRenderWindow::RegionEventProcessor(EventHandlerCallRef, + EventRef event, void* win) +{ + vtkCarbonRenderWindow* vtk_win = reinterpret_cast(win); + UInt32 event_kind = GetEventKind(event); + UInt32 event_class = GetEventClass(event); + + switch(event_class) + { + case kEventClassControl: + { + switch (event_kind) + { + case kEventControlVisibilityChanged: + case kEventControlOwningWindowChanged: + case kEventControlBoundsChanged: + vtk_win->UpdateGLRegion(); + break; + default: + break; + } + } + break; + default: + break; + } + + return eventNotHandledErr; +} + diff --git a/Rendering/vtkCarbonRenderWindow.h b/Rendering/vtkCarbonRenderWindow.h new file mode 100644 index 0000000..f59c9b4 --- /dev/null +++ b/Rendering/vtkCarbonRenderWindow.h @@ -0,0 +1,250 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCarbonRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCarbonRenderWindow - Carbon OpenGL rendering window +// +// .SECTION Description +// vtkCarbonRenderWindow is a concrete implementation of the abstract +// class vtkOpenGLRenderWindow. vtkCarbonRenderWindow interfaces to the +// OpenGL graphics library using the Carbon API on Mac OSX. + +#ifndef __vtkCarbonRenderWindow_h +#define __vtkCarbonRenderWindow_h + +#include "vtkOpenGLRenderWindow.h" + +#include // Carbon and MAC specific +#include // Carbon and MAC specific + +class VTK_RENDERING_EXPORT vtkCarbonRenderWindow : public vtkOpenGLRenderWindow +{ +public: + static vtkCarbonRenderWindow *New(); + vtkTypeRevisionMacro(vtkCarbonRenderWindow,vtkOpenGLRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Begin the rendering process. + void Start(); + + // Description: + // End the rendering process and display the image. + void Frame(); + + // Description: + // Specify various window parameters. + virtual void WindowConfigure(); + + // Description: + // Create the window. + virtual void WindowInitialize(); + + // Description: + // Initialize the rendering window. This will setup all system-specific + // resources. This method and Finalize() must be symmetric and it + // should be possible to call them multiple times, even changing WindowId + // in-between. This is what WindowRemap does. + virtual void Initialize(); + + // Description: + // Finalize the rendering window. This will shutdown all system-specifc + // resources. After having called this, it should be possible to destroy + // a window that was used for a SetWindowId() call without any ill effects. + virtual void Finalize(); + + // Description: + // Change the window to fill the entire screen. + virtual void SetFullScreen(int); + + // Description: + // Remap the window. + virtual void WindowRemap(); + + // Description: + // Set the preferred window size to full screen. + virtual void PrefFullScreen(); + + // Description: + // Set the size of the window. + virtual void SetSize(int a[2]); + virtual void SetSize(int,int); + + // Description: + // Get the current size of the window. + virtual int *GetSize(); + + // Description: + // Set the position of the window. + virtual void SetPosition(int*); + virtual void SetPosition(int,int); + + // Description: + // Return the scrren size. + virtual int *GetScreenSize(); + + // Description: + // Get the position in screen coordinates of the window. + virtual int *GetPosition(); + + // Description: + // Set the name of the window. This appears at the top of the window + // normally. + virtual void SetWindowName(const char *); + + // Description: + // Set this RenderWindow's window id to a pre-existing window. + void SetWindowInfo(char *); + + void SetNextWindowInfo(char *) + { + vtkWarningMacro("SetNextWindowInfo not implemented (WindowRemap not implemented)."); + } + + //BTX + virtual void *GetGenericDisplayId() {return NULL;}; + virtual void *GetGenericWindowId() {return (void *)this->WindowId;}; + virtual void *GetGenericParentId() {return (void *)this->ParentId;}; + virtual AGLContext GetContextId() {return this->ContextId;}; + virtual void *GetGenericContext() {return (void *)this->ContextId;}; + virtual void SetDisplayId(void *) {}; + + virtual void* GetGenericDrawable() + { + vtkWarningMacro("GetGenericDrawable Method not implemented."); + return 0; + } + + void SetParentInfo(char*) + { + vtkWarningMacro("SetParentInfo Method not implemented."); + } + + // Description: + // Get the HIView window pointer. + virtual HIViewRef GetWindowId(); + // Set the HIView window pointer. + void SetWindowId(void *foo) {this->SetWindowId((HIViewRef)foo);}; + void SetNextWindowId(void*) + { + vtkWarningMacro("SetNextWindowId not implemented (WindowRemap not implemented)."); + } + + // Description: + // Set the parent HIView. + virtual void SetParentId(HIViewRef); + void SetParentId(void *foo) {this->SetParentId((HIViewRef)foo);}; + + // Description: + // Set the HIVIew pointer to a pre-existing window. + virtual void SetWindowId(HIViewRef); + + // Description: + // Set the root window id. Use this when using non-HIView GUIs. + void SetRootWindow(WindowPtr win); + WindowPtr GetRootWindow(); + + //ETX + + // supply base class virtual function + vtkSetMacro(MultiSamples,int); + vtkGetMacro(MultiSamples,int); + + // Description: + // Prescribe that the window be created in a stereo-capable mode. This + // method must be called before the window is realized. This method + // overrrides the superclass method since this class can actually check + // whether the window has been realized yet. + virtual void SetStereoCapableWindow(int capable); + + // Description: + // Make this windows OpenGL context the current context. + void MakeCurrent(); + + // Description: + // If called, allow MakeCurrent() to skip cache-check when called. + // MakeCurrent() reverts to original behavior of cache-checking + // on the next render. + void SetForceMakeCurrent(); + + // Description: + // Check to see if an event is pending for this window. + // This is a useful check to abort a long render. + virtual int GetEventPending(); + + // Description: + // Initialize OpenGL for this window. + virtual void SetupPalette(void *hDC); + virtual void SetupPixelFormat(void *hDC, void *dwFlags, int debug, + int bpp=16, int zbpp=16); + + // Description: + // Clean up device contexts, rendering contexts, etc. + void Clean(); + + // Description: + // Get the size of the depth buffer. + int GetDepthBufferSize(); + + // Description: + // Hide or Show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + void HideCursor(); + void ShowCursor(); + + void UpdateSizeAndPosition(int xPos, int yPos, int xSize, int ySize); + + // Description: + // Fix the GL region. The AGL_BUFFER_RECT and AGL_CLIP_REGION will be updated + void UpdateGLRegion(); + + +protected: + vtkCarbonRenderWindow(); + ~vtkCarbonRenderWindow(); + + int ApplicationInitialized; // Toolboxen initialized? + Boolean fAcceleratedMust; // input: must renderer be accelerated? + Boolean draggable; // input: is the window draggable? + GLint aglAttributes[64]; // input: pixel format attributes always required + // (reset to what was actually allocated) + SInt32 VRAM; // input: minimum VRAM; output: actual + // (if successful otherwise input) + SInt32 textureRAM; // input: amount of texture RAM required on card; + // output: same (used in allocation) + AGLPixelFormat fmt; // input: none; output pixel format... + AGLContext ContextId; + HIViewRef WindowId; + HIViewRef ParentId; + WindowPtr RootWindow; + int OwnWindow; + int ScreenSize[2]; + + int CursorHidden; + int ForceMakeCurrent; + + + // data and handlers to keep the GL view coincident with the HIView + EventHandlerUPP RegionEventHandlerUPP; + EventHandlerRef RegionEventHandler; + static OSStatus RegionEventProcessor(EventHandlerCallRef er, EventRef event, void*); + + void CreateAWindow(int x, int y, int width, int height); + void InitializeApplication(); + +private: + vtkCarbonRenderWindow(const vtkCarbonRenderWindow&); // Not implemented. + void operator=(const vtkCarbonRenderWindow&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkCarbonRenderWindowInteractor.cxx b/Rendering/vtkCarbonRenderWindowInteractor.cxx new file mode 100644 index 0000000..3a8fab3 --- /dev/null +++ b/Rendering/vtkCarbonRenderWindowInteractor.cxx @@ -0,0 +1,464 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCarbonRenderWindowInteractor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include +#include +#include +#include + +#include "vtkActor.h" +#include "vtkCarbonRenderWindow.h" +#include "vtkCarbonRenderWindowInteractor.h" +#include "vtkCommand.h" +#include "vtkInteractorStyle.h" +#include "vtkObjectFactory.h" + +#import + +vtkCxxRevisionMacro(vtkCarbonRenderWindowInteractor, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkCarbonRenderWindowInteractor); + +void (*vtkCarbonRenderWindowInteractor::ClassExitMethod)(void *) + = (void (*)(void *))NULL; +void *vtkCarbonRenderWindowInteractor::ClassExitMethodArg = (void *)NULL; +void (*vtkCarbonRenderWindowInteractor::ClassExitMethodArgDelete)(void *) + = (void (*)(void *))NULL; + +//-------------------------------------------------------------------------- +// callback routine to handle all window-related events +// The WindowPtr of the associated window is passed in userData +static pascal OSStatus myWinEvtHndlr(EventHandlerCallRef, + EventRef event, void* userData) +{ + OSStatus result = eventNotHandledErr; + Point mouseLoc; + vtkCarbonRenderWindow *ren; + vtkCarbonRenderWindowInteractor *me; + UInt32 eventClass = GetEventClass(event); + UInt32 eventKind = GetEventKind (event); + + ren = (vtkCarbonRenderWindow *)userData; + + if (NULL == ren) + { + return 0; + } + + me = (vtkCarbonRenderWindowInteractor *)ren->GetInteractor(); + if (NULL == me) + { + return 0; + } + + UInt32 modifierKeys; + GetEventParameter(event, kEventParamKeyModifiers,typeUInt32, NULL, + sizeof(modifierKeys), NULL, &modifierKeys); + int controlDown = (modifierKeys & controlKey); + int shiftDown = (modifierKeys & shiftKey); + + switch (eventClass) + { + case kEventClassControl: + { + switch (eventKind) + { + case kEventControlDraw: + { + ren->Render(); + result = noErr; + break; + } + case kEventControlBoundsChanged: + { + if(ren->GetWindowId()) + { + HIRect viewBounds; + HIViewGetBounds(ren->GetWindowId(), &viewBounds); + me->UpdateSize((int)viewBounds.size.width, (int)viewBounds.size.height); + if (me->GetEnabled()) + { + me->InvokeEvent(vtkCommand::ConfigureEvent,NULL); + } + result = noErr; + } + break; + } + } + break; + } + + case kEventClassKeyboard: + { + SInt8 charCode; + GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar,NULL, + sizeof(charCode),NULL,&charCode); + switch (GetEventKind(event)) + { + case kEventRawKeyDown: + { + me->SetKeyEventInformation(controlDown, shiftDown, + (int)charCode,1,(char*)&charCode); + me->InvokeEvent(vtkCommand::KeyPressEvent, NULL); + me->InvokeEvent(vtkCommand::CharEvent, NULL); + result = noErr; + break; + } + case kEventRawKeyRepeat: + { + me->SetKeyEventInformation(controlDown, shiftDown, + (int)charCode,1,(char*)&charCode); + me->InvokeEvent(vtkCommand::KeyPressEvent, NULL); + me->InvokeEvent(vtkCommand::CharEvent, NULL); + result = noErr; + break; + } + case kEventRawKeyUp: + { + me->SetKeyEventInformation(controlDown, shiftDown, + (int)charCode,1,(char*)&charCode); + me->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL); + result = noErr; + break; + } + } + break; + } + + case kEventClassMouse: + { + // see if the event is for this view + HIViewRef view_for_mouse; + HIViewGetViewForMouseEvent(HIViewGetRoot(ren->GetRootWindow()), event, &view_for_mouse); + if(view_for_mouse != ren->GetWindowId()) + return eventNotHandledErr; + + GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, + NULL, sizeof(Point), NULL, &mouseLoc); + SetPortWindowPort(FrontWindow()); + GlobalToLocal(&mouseLoc); + GetEventParameter(event, kEventParamKeyModifiers,typeUInt32, NULL, + sizeof(modifierKeys), NULL, &modifierKeys); + UInt16 buttonNumber; + GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, + sizeof(buttonNumber), NULL, &buttonNumber); + me->SetEventInformationFlipY(mouseLoc.h, mouseLoc.v, + (modifierKeys & controlKey), + (modifierKeys & shiftKey)); + switch (GetEventKind(event)) + { + case kEventMouseDown: + { + switch (buttonNumber) + { + case 1: + { + me->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); + break; + } + case 2: + { + me->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL); + break; + } + case 3: + { + me->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL); + break; + } + } + result = noErr; + break; + } + case kEventMouseUp: + { + switch (buttonNumber) + { + case 1: + { + me->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL); + break; + } + case 2: + { + me->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL); + break; + } + case 3: + { + me->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL); + break; + } + } + result = noErr; + break; + } + case kEventMouseMoved: + { + me->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); + result = noErr; + break; + } + case kEventMouseDragged: + { + me->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); + result = noErr; + break; + } + case kEventMouseWheelMoved: + { + EventMouseWheelAxis axis; + SInt32 delta; + GetEventParameter( event, kEventParamMouseWheelAxis, + typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis ); + GetEventParameter( event, kEventParamMouseWheelDelta, + typeLongInteger, NULL, sizeof(delta), NULL, &delta ); + if ( axis == kEventMouseWheelAxisY ) + { + if( delta > 0) + { + me->InvokeEvent(vtkCommand::MouseWheelForwardEvent, NULL); + } + else + { + me->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, NULL); + } + } + result = noErr; + break; + } + default: + { + } + } + } + } + + return result; +} + +//-------------------------------------------------------------------------- +// Construct object so that light follows camera motion. +vtkCarbonRenderWindowInteractor::vtkCarbonRenderWindowInteractor() +{ + this->TimerId = 0; + this->InstallMessageProc = 1; + this->ViewProcUPP = NULL; + this->WindowProcUPP = NULL; +} + +//-------------------------------------------------------------------------- +vtkCarbonRenderWindowInteractor::~vtkCarbonRenderWindowInteractor() +{ + this->Enabled = 0; +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindowInteractor::Start() +{ + // Let the compositing handle the event loop if it wants to. + if (this->HasObserver(vtkCommand::StartEvent)) + { + this->InvokeEvent(vtkCommand::StartEvent,NULL); + return; + } + + // No need to do anything if this is a 'mapped' interactor + if (!this->Enabled || !this->InstallMessageProc) + { + return; + } + RunApplicationEventLoop(); +} + +//-------------------------------------------------------------------------- +// Fill in some local variables (most of this routine could probably go) +void vtkCarbonRenderWindowInteractor::Initialize() +{ + vtkCarbonRenderWindow *ren; + int *size; + + // make sure we have a RenderWindow and camera + if ( ! this->RenderWindow) + { + vtkErrorMacro(<<"No renderer defined!"); + return; + } + if (this->Initialized) + { + return; + } + this->Initialized = 1; + // get the info we need from the RenderingWindow + ren = (vtkCarbonRenderWindow *)(this->RenderWindow); + + ren->Start(); + size = ren->GetSize(); + ren->GetPosition(); + this->Enable(); + this->Size[0] = size[0]; + this->Size[1] = size[1]; +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindowInteractor::Enable() +{ + if (this->Enabled) + { + return; + } + + + if (this->InstallMessageProc) + { + // set up the event handling + // specify which events we want to hear about + OSStatus err = noErr; + EventTypeSpec view_event_list[] = {{ kEventClassControl, kEventControlDraw }, + { kEventClassControl, kEventControlBoundsChanged }}; + + EventTypeSpec window_event_list[] ={{ kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseDragged }, + { kEventClassMouse, kEventMouseWheelMoved }, + { kEventClassKeyboard, kEventRawKeyDown }, + { kEventClassKeyboard, kEventRawKeyRepeat }, + { kEventClassKeyboard, kEventRawKeyUp }}; + + this->WindowProcUPP = NewEventHandlerUPP(myWinEvtHndlr); + this->ViewProcUPP = NewEventHandlerUPP(myWinEvtHndlr); + if(!this->WindowProcUPP || !ViewProcUPP) + err = memFullErr; + + if(!err) + { + vtkCarbonRenderWindow* ren = static_cast(this->RenderWindow); + err = InstallControlEventHandler(ren->GetWindowId(), this->ViewProcUPP, + GetEventTypeCount(view_event_list), view_event_list, ren, NULL); + err = InstallWindowEventHandler(ren->GetRootWindow(), this->WindowProcUPP, + GetEventTypeCount(window_event_list), window_event_list, ren, NULL); + } + } + this->Enabled = 1; + this->Modified(); +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindowInteractor::Disable() +{ + if (!this->Enabled) + { + return; + } + this->Enabled = 0; + this->Modified(); +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindowInteractor::TerminateApp(void) +{ + cout << "vtkCarbonRenderWindowInteractor::TerminateApp\n"; +} + +//-------------------------------------------------------------------------- +pascal void TimerAction (EventLoopTimerRef, void* userData) +{ + if (NULL != userData) + { + ((vtkCarbonRenderWindowInteractor *)userData)-> + InvokeEvent(vtkCommand::TimerEvent,NULL); + } +} + +//-------------------------------------------------------------------------- +int vtkCarbonRenderWindowInteractor::CreateTimer(int timertype) +{ + EventLoopRef mainLoop = GetMainEventLoop(); + EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(TimerAction); + + if (timertype == VTKI_TIMER_FIRST) + { + InstallEventLoopTimer (mainLoop, + 10*kEventDurationMillisecond, + 10*kEventDurationMillisecond, + timerUPP, + this, + &this->TimerId); + } + return 1; +} + +//-------------------------------------------------------------------------- +int vtkCarbonRenderWindowInteractor::DestroyTimer(void) +{ + RemoveEventLoopTimer(this->TimerId); + return 1; +} + +//-------------------------------------------------------------------------- +// Specify the default function to be called when an interactor needs to exit. +// This callback is overridden by an instance ExitMethod that is defined. +void vtkCarbonRenderWindowInteractor::SetClassExitMethod(void (*f)(void *), + void *arg) +{ + if (f != vtkCarbonRenderWindowInteractor::ClassExitMethod + || arg != vtkCarbonRenderWindowInteractor::ClassExitMethodArg) + { + // delete the current arg if there is a delete method + if ((vtkCarbonRenderWindowInteractor::ClassExitMethodArg) && + (vtkCarbonRenderWindowInteractor::ClassExitMethodArgDelete)) + { + (*vtkCarbonRenderWindowInteractor::ClassExitMethodArgDelete) + (vtkCarbonRenderWindowInteractor::ClassExitMethodArg); + } + vtkCarbonRenderWindowInteractor::ClassExitMethod = f; + vtkCarbonRenderWindowInteractor::ClassExitMethodArg = arg; + + // no call to this->Modified() since this is a class member function + } +} + +//-------------------------------------------------------------------------- +// Set the arg delete method. This is used to free user memory. +void +vtkCarbonRenderWindowInteractor::SetClassExitMethodArgDelete(void (*f)(void *)) +{ + if (f != vtkCarbonRenderWindowInteractor::ClassExitMethodArgDelete) + { + vtkCarbonRenderWindowInteractor::ClassExitMethodArgDelete = f; + + // no call to this->Modified() since this is a class member function + } +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkRenderWindowInteractor::PrintSelf(os,indent); + os << indent << "InstallMessageProc: " << this->InstallMessageProc << endl; +} + +//-------------------------------------------------------------------------- +void vtkCarbonRenderWindowInteractor::ExitCallback() +{ + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent,NULL); + } + else if (this->ClassExitMethod) + { + (*this->ClassExitMethod)(this->ClassExitMethodArg); + } + this->TerminateApp(); +} diff --git a/Rendering/vtkCarbonRenderWindowInteractor.h b/Rendering/vtkCarbonRenderWindowInteractor.h new file mode 100644 index 0000000..9ef8f66 --- /dev/null +++ b/Rendering/vtkCarbonRenderWindowInteractor.h @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCarbonRenderWindowInteractor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCarbonRenderWindowInteractor - implements Carbon specific functions +// required by vtkRenderWindowInteractor. +// +// .SECTION Description +// The interactor interfaces with vtkCarbonWindow.mm and vtkCarbonGLView.mm +// to trap messages from the Carbon window manager and send them to vtk. +// +#ifndef __vtkCarbonRenderWindowInteractor_h +#define __vtkCarbonRenderWindowInteractor_h + +#include "vtkRenderWindowInteractor.h" + +#include // Needed for Carbon types + + +class VTK_RENDERING_EXPORT vtkCarbonRenderWindowInteractor : public vtkRenderWindowInteractor { +public: + // Description: + // Construct object so that light follows camera motion. + static vtkCarbonRenderWindowInteractor *New(); + + vtkTypeRevisionMacro(vtkCarbonRenderWindowInteractor,vtkRenderWindowInteractor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initialize the even handler + virtual void Initialize(); + + // Description: + // Enable/Disable interactions. By default interactors are enabled when + // initialized. Initialize() must be called prior to enabling/disabling + // interaction. These methods are used when a window/widget is being + // shared by multiple renderers and interactors. This allows a "modal" + // display where one interactor is active when its data is to be displayed + // and all other interactors associated with the widget are disabled + // when their data is not displayed. + virtual void Enable(); + virtual void Disable(); + + // Description: + // This will start up the event loop and never return. If you + // call this method it will loop processing events until the + // application is exited. + virtual void Start(); + + // Description: + // By default the interactor installs a MessageProc callback which + // intercepts windows messages to the window and controls interactions. + // MFC or BCB programs can prevent this and instead directly route any mouse/key + // messages into the event bindings by setting InstallMessgeProc to false. + vtkSetMacro(InstallMessageProc,int); + vtkGetMacro(InstallMessageProc,int); + vtkBooleanMacro(InstallMessageProc,int); + + // Description: + // Carbon specific application terminate, calls ClassExitMethod then + // calls PostQuitMessage(0) to terminate app. An application can Specify + // ExitMethod for alternative behaviour (i.e. suppresion of keyboard exit) + void TerminateApp(void); + + // Description: + // Carbon timer methods + int CreateTimer(int timertype); + int DestroyTimer(void); + + // Description: + // Methods to set the default exit method for the class. This method is + // only used if no instance level ExitMethod has been defined. It is + // provided as a means to control how an interactor is exited given + // the various language bindings (tcl, Carbon, etc.). + static void SetClassExitMethod(void (*f)(void *), void *arg); + static void SetClassExitMethodArgDelete(void (*f)(void *)); + + // Description: + // These methods correspond to the the Exit, User and Pick + // callbacks. They allow for the Style to invoke them. + virtual void ExitCallback(); + +protected: + vtkCarbonRenderWindowInteractor(); + ~vtkCarbonRenderWindowInteractor(); + + EventLoopTimerRef TimerId; + EventHandlerUPP ViewProcUPP; + EventHandlerUPP WindowProcUPP; + int InstallMessageProc; + + //BTX + // Description: + // Class variables so an exit method can be defined for this class + // (used to set different exit methods for various language bindings, + // i.e. tcl, java, Carbon) + static void (*ClassExitMethod)(void *); + static void (*ClassExitMethodArgDelete)(void *); + static void *ClassExitMethodArg; + //ETX + +private: + vtkCarbonRenderWindowInteractor(const vtkCarbonRenderWindowInteractor&); // Not implemented. + void operator=(const vtkCarbonRenderWindowInteractor&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkCellPicker.cxx b/Rendering/vtkCellPicker.cxx new file mode 100644 index 0000000..b93362e --- /dev/null +++ b/Rendering/vtkCellPicker.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellPicker.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCellPicker.h" + +#include "vtkGenericCell.h" +#include "vtkImageData.h" +#include "vtkMapper.h" +#include "vtkObjectFactory.h" +#include "vtkAbstractVolumeMapper.h" + +vtkCxxRevisionMacro(vtkCellPicker, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkCellPicker); + +vtkCellPicker::vtkCellPicker() +{ + this->CellId = -1; + this->SubId = -1; + for (int i=0; i<3; i++) + { + this->PCoords[i] = 0.0; + } + this->Cell = vtkGenericCell::New(); +} + +vtkCellPicker::~vtkCellPicker() +{ + this->Cell->Delete(); +} + +double vtkCellPicker::IntersectWithLine(double p1[3], double p2[3], double tol, + vtkAssemblyPath *path, + vtkProp3D *prop3D, + vtkAbstractMapper3D *m) +{ + vtkIdType numCells, cellId, minCellId; + int i, minSubId, subId; + double x[3], tMin, t, pcoords[3], minXYZ[3], minPcoords[3]; + vtkDataSet *input; + vtkMapper *mapper; + vtkAbstractVolumeMapper *volumeMapper; + + // Get the underlying dataset + if ( (mapper=vtkMapper::SafeDownCast(m)) != NULL ) + { + input = mapper->GetInput(); + } + else if ( (volumeMapper=vtkAbstractVolumeMapper::SafeDownCast(m)) != NULL ) + { + input = volumeMapper->GetDataSetInput(); + } + else + { + return VTK_DOUBLE_MAX; + } + + if ( (numCells = input->GetNumberOfCells()) < 1 ) + { + return 2.0; + } + + // Intersect each cell with ray. Keep track of one closest to + // the eye (within the tolerance tol) and within the clipping range). + // Note that we fudge the "closest to" (tMin+this->Tolerance) a little and + // keep track of the cell with the best pick based on parametric + // coordinate (pick the minimum, maximum parametric distance). This + // breaks ties in a reasonable way when cells are the same distance + // from the eye (like cells lying on a 2D plane). + // + minCellId = -1; + minSubId = -1; + pcoords[0] = pcoords[1] = pcoords[2] = 0; + double pDistMin=VTK_DOUBLE_MAX, pDist; + for (tMin=VTK_DOUBLE_MAX,cellId=0; cellIdGetCell(cellId, this->Cell); + + if ( this->Cell->IntersectWithLine(p1, p2, tol, t, x, pcoords, subId) + && t <= (tMin+this->Tolerance) ) + { + pDist = this->Cell->GetParametricDistance(pcoords); + if ( pDist < pDistMin || (pDist == pDistMin && t < tMin) ) + { + minCellId = cellId; + minSubId = subId; + for (i=0; i<3; i++) + { + minXYZ[i] = x[i]; + minPcoords[i] = pcoords[i]; + } + tMin = t; + pDistMin = pDist; + }//if minimum, maximum + }//if a close cell + }//for all cells + + // Now compare this against other actors. + // + if ( minCellId>(-1) && tMin < this->GlobalTMin ) + { + this->MarkPicked(path, prop3D, m, tMin, minXYZ); + this->CellId = minCellId; + this->SubId = minSubId; + for (i=0; i<3; i++) + { + this->PCoords[i] = minPcoords[i]; + } + vtkDebugMacro("Picked cell id= " << minCellId); + } + return tMin; +} + +void vtkCellPicker::Initialize() +{ + this->CellId = (-1); + this->SubId = (-1); + for (int i=0; i<3; i++) + { + this->PCoords[i] = 0.0; + } + this->vtkPicker::Initialize(); +} + +void vtkCellPicker::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cell Id: " << this->CellId << "\n"; + os << indent << "SubId: " << this->SubId << "\n"; + os << indent << "PCoords: (" << this->PCoords[0] << ", " + << this->PCoords[1] << ", " << this->PCoords[2] << ")\n"; +} diff --git a/Rendering/vtkCellPicker.h b/Rendering/vtkCellPicker.h new file mode 100644 index 0000000..079f2d5 --- /dev/null +++ b/Rendering/vtkCellPicker.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCellPicker.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCellPicker - select a cell by shooting a ray into graphics window +// .SECTION Description +// vtkCellPicker is used to select a cell by shooting a ray into graphics +// window and intersecting with actor's defining geometry - specifically +// its cells. Beside returning coordinates, actor and mapper, vtkCellPicker +// returns the id of the closest cell within the tolerance along the pick +// ray, and the dataset that was picked. +// .SECTION See Also +// vtkPicker vtkPointPicker + +#ifndef __vtkCellPicker_h +#define __vtkCellPicker_h + +#include "vtkPicker.h" + +class vtkGenericCell; + +class VTK_RENDERING_EXPORT vtkCellPicker : public vtkPicker +{ +public: + static vtkCellPicker *New(); + vtkTypeRevisionMacro(vtkCellPicker,vtkPicker); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the id of the picked cell. If CellId = -1, nothing was picked. + vtkGetMacro(CellId, vtkIdType); + + // Description: + // Get the subId of the picked cell. If SubId = -1, nothing was picked. + vtkGetMacro(SubId, int); + + // Description: + // Get the parametric coordinates of the picked cell. Only valid if + // pick was made. + vtkGetVectorMacro(PCoords, double,3); + +protected: + vtkCellPicker(); + ~vtkCellPicker(); + + vtkIdType CellId; // picked cell + int SubId; // picked cell subId + double PCoords[3]; // picked cell parametric coordinates + + virtual double IntersectWithLine(double p1[3], double p2[3], double tol, + vtkAssemblyPath *path, vtkProp3D *p, + vtkAbstractMapper3D *m); + void Initialize(); + +private: + vtkGenericCell *Cell; //used to accelerate picking + +private: + vtkCellPicker(const vtkCellPicker&); // Not implemented. + void operator=(const vtkCellPicker&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkCocoaGLView.h b/Rendering/vtkCocoaGLView.h new file mode 100644 index 0000000..f6d089d --- /dev/null +++ b/Rendering/vtkCocoaGLView.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaGLView.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCocoaGLView - Cocoa OpenGL rendering context +// +// .SECTION Description +// This class is a subclass of Cocoa's NSView; it uses Objective-C++. +// This class overrides several NSView methods. It overrides keyDown and +// keyUp to provide the usual VTK keyboard user interface. It overrides +// mouseMoved, scrollWheel, mouseDown, rightMouseDown, and otherMouseDown +// to provide the usual VTK mouse user interface. It overrides drawRect +// to render and draw onscreen. +// Note that this class was previously a subclass of NSOpenGLView, +// but is now a subclass of NSView. +// +// .SECTION See Also +// vtkCocoaRenderWindow vtkCocoaRenderWindowInteractor + +#import + +// Forward declarations +class vtkCocoaRenderWindow; +class vtkCocoaRenderWindowInteractor; + +@interface vtkCocoaGLView : NSView +{ + @private + vtkCocoaRenderWindow *myVTKRenderWindow; +} + +- (vtkCocoaRenderWindow *)getVTKRenderWindow; +- (void)setVTKRenderWindow:(vtkCocoaRenderWindow *)theVTKRenderWindow; + +- (vtkCocoaRenderWindowInteractor *)getInteractor; + +@end diff --git a/Rendering/vtkCocoaGLView.mm b/Rendering/vtkCocoaGLView.mm new file mode 100644 index 0000000..1142bb2 --- /dev/null +++ b/Rendering/vtkCocoaGLView.mm @@ -0,0 +1,350 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaGLView.mm,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#import "vtkCocoaGLView.h" +#import "vtkCocoaRenderWindow.h" +#import "vtkCocoaRenderWindowInteractor.h" +#import "vtkCommand.h" + + +@implementation vtkCocoaGLView + +//---------------------------------------------------------------------------- +- (vtkCocoaRenderWindow *)getVTKRenderWindow +{ + return myVTKRenderWindow; +} + +//---------------------------------------------------------------------------- +- (void)setVTKRenderWindow:(vtkCocoaRenderWindow *)theVTKRenderWindow +{ + myVTKRenderWindow = theVTKRenderWindow; +} + +//---------------------------------------------------------------------------- +- (vtkCocoaRenderWindowInteractor *)getInteractor +{ + if (myVTKRenderWindow) + { + return (vtkCocoaRenderWindowInteractor*)myVTKRenderWindow->GetInteractor(); + } + else + { + return NULL; + } +} + + +//---------------------------------------------------------------------------- +- (void)drawRect:(NSRect)theRect +{ + (void)theRect; + + if ( myVTKRenderWindow && myVTKRenderWindow->GetMapped() ) + { + myVTKRenderWindow->Render(); + } +} + +//---------------------------------------------------------------------------- +- (BOOL)acceptsFirstResponder +{ + return YES; +} + +//---------------------------------------------------------------------------- +- (void)keyDown:(NSEvent *)theEvent +{ + vtkCocoaRenderWindowInteractor *interactor = [self getInteractor]; + if (!interactor) + return; + + // Get the location of the mouse event relative to this NSView's bottom left corner + // Since this is a NOT mouseevent, we can not use locationInWindow + // Instead we get the mouse location at this instant, which may not be the exact + // location of the mouse at the time of the keypress, but should be quite close. + // There seems to be no better way. And, yes, vtk does sometimes need the mouse + // location even for key events, example: pressing 'p' to pick the actor under + // the mouse. Also note that 'mouseLoc' may have nonsense values if a key is + // pressed while the mouse in not actually in the vtk view but the view is + // first responder. + NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream]; + mouseLoc = [self convertPoint:mouseLoc fromView:nil]; + + int shiftDown = ([theEvent modifierFlags] & NSShiftKeyMask); + int controlDown = ([theEvent modifierFlags] & NSControlKeyMask); + + // Get the characters associated with the key event as a utf8 string. + // This pointer is only valid for the duration of the current autorelease context! + const char* keyedChars = [[theEvent characters] UTF8String]; + + // Since vtk only supports ascii, we just blindly pass the first element + // of the above string, hoping it's ascii + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown, + (unsigned short)keyedChars[0], 1, keyedChars); + + interactor->InvokeEvent(vtkCommand::KeyPressEvent, NULL); + interactor->InvokeEvent(vtkCommand::CharEvent, NULL); +} + +//---------------------------------------------------------------------------- +- (void)keyUp:(NSEvent *)theEvent +{ + vtkCocoaRenderWindowInteractor *interactor = [self getInteractor]; + if (!interactor) + return; + + // Get the location of the mouse event relative to this NSView's bottom left corner + // Since this is a NOT mouseevent, we can not use locationInWindow + // Instead we get the mouse location at this instant, which may not be the exact + // location of the mouse at the time of the keypress, but should be quite close. + // There seems to be no better way. And, yes, vtk does sometimes need the mouse + // location even for key events, example: pressing 'p' to pick the actor under + // the mouse. Also note that 'mouseLoc' may have nonsense values if a key is + // pressed while the mouse in not actually in the vtk view but the view is + // first responder. + NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream]; + mouseLoc = [self convertPoint:mouseLoc fromView:nil]; + + int shiftDown = ([theEvent modifierFlags] & NSShiftKeyMask); + int controlDown = ([theEvent modifierFlags] & NSControlKeyMask); + + // Get the characters associated with the key event as a utf8 string. + // This pointer is only valid for the duration of the current autorelease context! + const char* keyedChars = [[theEvent characters] UTF8String]; + + // Since vtk only supports ascii, we just blindly pass the first element + // of the above string, hoping it's ascii + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown, + (unsigned short)keyedChars[0], 1, keyedChars); + + interactor->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL); +} + + +//---------------------------------------------------------------------------- +- (void)mouseMoved:(NSEvent *)theEvent +{ + // Note: this method will only be called if this view's NSWindow + // is set to receive mouse moved events. See setAcceptsMouseMovedEvents: + // An NSWindow created by vtk automatically does accept such events. + + vtkCocoaRenderWindowInteractor *interactor = [self getInteractor]; + if (!interactor) + return; + + // Get the location of the mouse event relative to this NSView's bottom left corner + // Since this is a mouseevent, we can use locationInWindow + NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + int shiftDown = ([theEvent modifierFlags] & NSShiftKeyMask); + int controlDown = ([theEvent modifierFlags] & NSControlKeyMask); + + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + interactor->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); +} + +//---------------------------------------------------------------------------- +- (void)scrollWheel:(NSEvent *)theEvent +{ + vtkCocoaRenderWindowInteractor *interactor = [self getInteractor]; + if (!interactor) + return; + + // Get the location of the mouse event relative to this NSView's bottom left corner + // Since this is a mouseevent, we can use locationInWindow + NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + int shiftDown = ([theEvent modifierFlags] & NSShiftKeyMask); + int controlDown = ([theEvent modifierFlags] & NSControlKeyMask); + + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + if( [theEvent deltaY] > 0) + { + interactor->InvokeEvent(vtkCommand::MouseWheelForwardEvent, NULL); + } + else + { + interactor->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, NULL); + } +} + + +//---------------------------------------------------------------------------- +- (void)mouseDown:(NSEvent *)theEvent +{ + vtkCocoaRenderWindowInteractor *interactor = [self getInteractor]; + if (!interactor) + return; + + BOOL keepOn = YES; + + // Get the location of the mouse event relative to this NSView's bottom left corner + // Since this is a mouseevent, we can use locationInWindow + NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + int shiftDown = ([theEvent modifierFlags] & NSShiftKeyMask); + int controlDown = ([theEvent modifierFlags] & NSControlKeyMask); + + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + + interactor->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); + + NSDate* infinity = [NSDate distantFuture]; + do + { + theEvent = + [NSApp nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask + untilDate: infinity + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + if (theEvent) + { + mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + switch ([theEvent type]) + { + case NSLeftMouseDragged: + interactor->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); + break; + case NSLeftMouseUp: + interactor->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, NULL); + keepOn = NO; + default: + break; + } + } + else + { + keepOn = NO; + } + } + while (keepOn); +} + +//---------------------------------------------------------------------------- +- (void)rightMouseDown:(NSEvent *)theEvent +{ + vtkCocoaRenderWindowInteractor *interactor = [self getInteractor]; + if (!interactor) + return; + + BOOL keepOn = YES; + + // Get the location of the mouse event relative to this NSView's bottom left corner + // Since this is a mouseevent, we can use locationInWindow + NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + int shiftDown = ([theEvent modifierFlags] & NSShiftKeyMask); + int controlDown = ([theEvent modifierFlags] & NSControlKeyMask); + + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + + interactor->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL); + + NSDate* infinity = [NSDate distantFuture]; + do + { + theEvent = + [NSApp nextEventMatchingMask: NSRightMouseUpMask | NSRightMouseDraggedMask + untilDate: infinity + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + if (theEvent) + { + mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + switch ([theEvent type]) + { + case NSRightMouseDragged: + interactor->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); + break; + case NSRightMouseUp: + interactor->InvokeEvent(vtkCommand::RightButtonReleaseEvent, NULL); + keepOn = NO; + default: + break; + } + } + else + { + keepOn = NO; + } + } + while (keepOn); +} + +//---------------------------------------------------------------------------- +- (void)otherMouseDown:(NSEvent *)theEvent +{ + vtkCocoaRenderWindowInteractor *interactor = [self getInteractor]; + if (!interactor) + return; + + BOOL keepOn = YES; + + // Get the location of the mouse event relative to this NSView's bottom left corner + // Since this is a mouseevent, we can use locationInWindow + NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + int shiftDown = ([theEvent modifierFlags] & NSShiftKeyMask); + int controlDown = ([theEvent modifierFlags] & NSControlKeyMask); + + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + + interactor->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL); + + NSDate* infinity = [NSDate distantFuture]; + do + { + theEvent = + [NSApp nextEventMatchingMask: NSOtherMouseUpMask | NSOtherMouseDraggedMask + untilDate: infinity + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + if (theEvent) + { + mouseLoc = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + interactor->SetEventInformation( + (int)mouseLoc.x, (int)mouseLoc.y, controlDown, shiftDown); + switch ([theEvent type]) + { + case NSOtherMouseDragged: + interactor->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); + break; + case NSOtherMouseUp: + interactor->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, NULL); + keepOn = NO; + default: + break; + } + } + else + { + keepOn = NO; + } + } + while (keepOn); +} + +@end diff --git a/Rendering/vtkCocoaRenderWindow.h b/Rendering/vtkCocoaRenderWindow.h new file mode 100644 index 0000000..3684e5d --- /dev/null +++ b/Rendering/vtkCocoaRenderWindow.h @@ -0,0 +1,263 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCocoaRenderWindow - Cocoa OpenGL rendering window +// +// .SECTION Description +// vtkCocoaRenderWindow is a concrete implementation of the abstract +// class vtkOpenGLRenderWindow. It uses Objective-C++, and the OpenGL and +// Cocoa APIs. This class's default behaviour is to create an NSWindow and +// a vtkCocoaGLView which are used together to draw all vtk stuff into. +// If you already have an NSWindow and vtkCocoaGLView and you want this +// class to use them you must call both SetWindowId() and SetDisplayId() +// early on (before WindowInitialize() is executed). +// +// .SECTION See Also +// vtkOpenGLRenderWindow vtkCocoaGLView + +// .SECTION Warning +// This header must be in C++ only because it is included by .cxx files. +// That means no Objective-C may be used. That's why some instance variables +// are void* instead of what they really should be. + +#ifndef __vtkCocoaRenderWindow_h +#define __vtkCocoaRenderWindow_h + +#include "vtkOpenGLRenderWindow.h" + +class VTK_RENDERING_EXPORT vtkCocoaRenderWindow : public vtkOpenGLRenderWindow +{ +public: + static vtkCocoaRenderWindow *New(); + vtkTypeRevisionMacro(vtkCocoaRenderWindow,vtkOpenGLRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Begin the rendering process. + virtual void Start(); + + // Description: + // Finish the rendering process. + virtual void Frame(); + + // Description: + // Specify various window parameters. + virtual void WindowConfigure(); + + // Description: + // Initialize the window for rendering. + virtual void WindowInitialize(); + + // Description: + // Initialize the rendering window. + virtual void Initialize(); + + // Description: + // Change the window to fill the entire screen. + virtual void SetFullScreen(int); + + // Description: + // Remap the window. + virtual void WindowRemap(); + + // Description: + // Set the preferred window size to full screen. + virtual void PrefFullScreen(); + + // Description: + // Set the size of the window. + virtual void SetSize(int*); + virtual void SetSize(int,int); + + // Description: + // Get the current size of the window. + virtual int *GetSize(); + + // Description: + // Set the position of the window. + virtual void SetPosition(int*); + virtual void SetPosition(int,int); + + // Description: + // Return the scrren size. + virtual int *GetScreenSize(); + + // Description: + // Get the position in screen coordinates of the window. + virtual int *GetPosition(); + + // Description: + // Set the name of the window. This appears at the top of the window + // normally. + virtual void SetWindowName(const char *); + + void SetNextWindowInfo(char *) + { + vtkWarningMacro("SetNextWindowInfo not implemented (WindowRemap not implemented)."); + } + + virtual void *GetGenericDisplayId() {return this->NSViewId;} + virtual void *GetGenericWindowId() {return this->WindowId;} + virtual void *GetGenericContext() {return this->ContextId;} + + // Description: + // Returns the NSView* associated with this vtkRenderWindow. + virtual void* GetDisplayId(); + + // Description: + // Sets the NSView* associated with this vtkRenderWindow. This class' default + // behaviour, that is, if you never call this SetDisplayId()/SetWindowId() is + // to create an NSWindow and a vtkCocoaGLView (NSView subclass) which are used + // together to draw all vtk stuff into. If you already have an NSWindow and + // NSView and you want this class to use them you must call both SetWindowId() + // and SetDisplayId() early on (before WindowInitialize() is executed). In the + // case of Java, you should call only SetDisplayId(). + virtual void SetDisplayId(void *); + + virtual void SetParentId(void *) + { + vtkWarningMacro("Method not implemented."); + } + virtual void* GetGenericParentId() + { + vtkWarningMacro("Method not implemented."); + return 0; + } + virtual void* GetGenericDrawable() + { + vtkWarningMacro("Method not implemented."); + return 0; + } + virtual void SetWindowInfo(char*) + { + vtkWarningMacro("Method not implemented."); + } + virtual void SetParentInfo(char*) + { + vtkWarningMacro("Method not implemented."); + } + + // Description: + // Returns the NSWindow* associated with this vtkRenderWindow. + virtual void *GetWindowId(); + + // Description: + // Sets the NSWindow* associated with this vtkRenderWindow. This class' default + // behaviour, that is, if you never call this SetDisplayId()/SetWindowId() is + // to create an NSWindow and a vtkCocoaGLView (NSView subclass) which are used + // together to draw all vtk stuff into. If you already have an NSWindow and + // NSView and you want this class to use them you must call both SetWindowId() + // and SetDisplayId() early on (before WindowInitialize() is executed). In the + // case of Java, you should call only SetDisplayId(). + virtual void SetWindowId(void *); + + void SetNextWindowId(void*) + { + vtkWarningMacro("SetNextWindowId not implemented (WindowRemap not implemented)."); + } + + + // Description: + // Update system if needed due to stereo rendering. + virtual void StereoUpdate(); + + // Description: + // Prescribe that the window be created in a stereo-capable mode. This + // method must be called before the window is realized. This method + // overrrides the superclass method since this class can actually check + // whether the window has been realized yet. + virtual void SetStereoCapableWindow(int capable); + + // Description: + // Make this windows OpenGL context the current context. + virtual void MakeCurrent(); + + // Description: + // Update this window's OpenGL context, e.g. when the window is resized. + void UpdateContext(); + + // Description: + // Get report of capabilities for the render window + const char *ReportCapabilities(); + + // Description: + // Does this render window support OpenGL? 0-false, 1-true + int SupportsOpenGL(); + + // Description: + // Is this render window using hardware acceleration? 0-false, 1-true + int IsDirect(); + + // Description: + // If called, allow MakeCurrent() to skip cache-check when called. + // MakeCurrent() reverts to original behavior of cache-checking + // on the next render. + virtual void SetForceMakeCurrent(); + + // Description: + // Check to see if an event is pending for this window. + // This is a useful check to abort a long render. + virtual int GetEventPending(); + + // Description: + // Initialize OpenGL for this window. + virtual void SetupPalette(void *hDC); + virtual void SetupPixelFormat(void *hDC, void *dwFlags, int debug, + int bpp=16, int zbpp=16); + + // Description: + // Clean up device contexts, rendering contexts, etc. + void Finalize(); + + // Description: + // Register a texture name with this render window + void RegisterTextureResource (GLuint id); + + // Description: + // Get the size of the depth buffer. + int GetDepthBufferSize(); + + // Description: + // Hide or Show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + virtual void HideCursor(); + virtual void ShowCursor(); + + +protected: + vtkCocoaRenderWindow(); + ~vtkCocoaRenderWindow(); + + void CreateGLContext(); + +private: + vtkCocoaRenderWindow(const vtkCocoaRenderWindow&); // Not implemented. + void operator=(const vtkCocoaRenderWindow&); // Not implemented. + +private: + void *ContextId; // really an NSOpenGLContext* + void *WindowId; // really an NSWindow* + void *NSViewId; // really an NSView* (usually but not necessarily a vtkCocoaGLView*) + void *PixelFormat; // really an NSOpenGLPixelFormat* + + int WindowCreated; + int ViewCreated; + int CursorHidden; + + void *AutoreleasePool; // really an NSAutoreleasePool* + int ForceMakeCurrent; + char *Capabilities; +}; + +#endif diff --git a/Rendering/vtkCocoaRenderWindow.mm b/Rendering/vtkCocoaRenderWindow.mm new file mode 100644 index 0000000..6904eab --- /dev/null +++ b/Rendering/vtkCocoaRenderWindow.mm @@ -0,0 +1,771 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaRenderWindow.mm,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#import "vtkCocoaRenderWindow.h" +#import "vtkCocoaRenderWindowInteractor.h" +#import "vtkIdList.h" +#import "vtkObjectFactory.h" +#import "vtkRendererCollection.h" +#import "vtkCocoaWindow.h" +#import "vtkCocoaGLView.h" + +#ifndef MAC_OS_X_VERSION_10_4 +#define MAC_OS_X_VERSION_10_4 1040 +#endif + +vtkCxxRevisionMacro(vtkCocoaRenderWindow, "$Revision: 1.30.4.1 $"); +vtkStandardNewMacro(vtkCocoaRenderWindow); + +//---------------------------------------------------------------------------- +vtkCocoaRenderWindow::vtkCocoaRenderWindow() +{ + // Create an autorelease pool that lives for as long as this object, + // which should be more or less the life of the application. + this->AutoreleasePool = [[NSAutoreleasePool alloc] init]; + + this->WindowCreated = 0; + this->ViewCreated = 0; + this->ContextId = 0; + this->MultiSamples = 8; + this->WindowId = 0; + this->NSViewId = 0; + this->SetWindowName("Visualization Toolkit - Cocoa"); + this->CursorHidden = 0; + this->ForceMakeCurrent = 0; + this->Capabilities = 0; +} + +//---------------------------------------------------------------------------- +vtkCocoaRenderWindow::~vtkCocoaRenderWindow() +{ + if (this->CursorHidden) + { + this->ShowCursor(); + } + this->Finalize(); + + if (this->Capabilities) + { + delete[] this->Capabilities; + this->Capabilities = 0; + } + + if (this->NSViewId && this->ViewCreated) + { + // If this class created the view, then this class must release it. + // Note that this doesn't remove it from the window, as the window + // has retained it. + [(NSView *)this->NSViewId release]; + } + this->NSViewId = NULL; + + if (this->WindowId && this->WindowCreated) + { + // If this class created the window, then this class must close + // it (this will also release its memory) + [(NSWindow *)this->WindowId close]; + } + this->WindowId = NULL; + + [(NSAutoreleasePool*)this->AutoreleasePool release]; + this->AutoreleasePool = 0; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::Finalize() +{ + GLuint txId; + + // finish OpenGL rendering + if (this->ContextId) + { + this->MakeCurrent(); + + // now delete all textures + glDisable(GL_TEXTURE_2D); + for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++) + { + txId = (GLuint) this->TextureResourceIds->GetId(i); +#ifdef GL_VERSION_1_1 + if (glIsTexture(txId)) + { + glDeleteTextures(1, &txId); + } +#else + if (glIsList(txId)) + { + glDeleteLists(txId,1); + } +#endif + } + + // tell each of the renderers that this render window/graphics context + // is being removed (the RendererCollection is removed by vtkRenderWindow's + // destructor) + vtkCollectionSimpleIterator rsit; + vtkRenderer *ren; + for ( this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(NULL); + } + + [(NSOpenGLContext*)this->ContextId release]; + [(NSOpenGLPixelFormat*)this->PixelFormat release]; + + this->ContextId = NULL; + this->PixelFormat = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetWindowName( const char * _arg ) +{ + vtkWindow::SetWindowName(_arg); + if (this->WindowId) + { + NSString* winTitleStr; + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4 + winTitleStr = [NSString stringWithCString:_arg encoding:NSASCIIStringEncoding]; +#else + winTitleStr = [NSString stringWithCString:_arg]; +#endif + + [(NSWindow*)this->WindowId setTitle:winTitleStr]; + } +} + +//---------------------------------------------------------------------------- +int vtkCocoaRenderWindow::GetEventPending() +{ + return 0; +} + +//---------------------------------------------------------------------------- +// Initialize the rendering process. +void vtkCocoaRenderWindow::Start() +{ + // if the renderer has not been initialized, do so now + if (!this->ContextId) + { + this->Initialize(); + } + + NSOpenGLContext* context = (NSOpenGLContext*)this->ContextId; + + // the error "invalid drawable" in the console from this call can appear + // but only early in the app's lifetime (ie sometime during launch) + + [context setView:(NSView*)this->NSViewId]; + + [context update]; + + // set the current window + this->MakeCurrent(); +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::MakeCurrent() +{ + if (this->ContextId) + { + [(NSOpenGLContext*)this->ContextId makeCurrentContext]; + } +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::UpdateContext() +{ + if (this->ContextId) + { + [(NSOpenGLContext*)this->ContextId update]; + } +} + +//---------------------------------------------------------------------------- +const char* vtkCocoaRenderWindow::ReportCapabilities() +{ + this->MakeCurrent(); + + const char* glVendor = (const char*) glGetString(GL_VENDOR); + const char* glRenderer = (const char*) glGetString(GL_RENDERER); + const char* glVersion = (const char*) glGetString(GL_VERSION); + const char* glExtensions = (const char*) glGetString(GL_EXTENSIONS); + + ostrstream strm; + strm << "OpenGL vendor string: " << glVendor + << "\nOpenGL renderer string: " << glRenderer + << "\nOpenGL version string: " << glVersion + << "\nOpenGL extensions: " << glExtensions << endl; + + // Obtain the OpenGL context in order to keep track of the current screen. + NSOpenGLContext* context = (NSOpenGLContext*)this->ContextId; + int currentScreen = [context currentVirtualScreen]; + + // The NSOpenGLPixelFormat can only be queried for one particular + // attribute at a time. Just make repeated queries to get the + // pertinent settings. + NSOpenGLPixelFormat* pixelFormat = (NSOpenGLPixelFormat*)this->PixelFormat; + strm << "PixelFormat Descriptor:" << endl; + long pfd; + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAColorSize forVirtualScreen: currentScreen]; + strm << " colorSize: " << pfd << endl; + + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: currentScreen]; + strm << " alphaSize: " << pfd << endl; + + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: currentScreen]; + strm << " stencilSize: " << pfd << endl; + + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFADepthSize forVirtualScreen: currentScreen]; + strm << " depthSize: " << pfd << endl; + + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: currentScreen]; + strm << " accumSize: " << pfd << endl; + + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: currentScreen]; + strm << " double buffer: " << (pfd == YES ? "Yes" : "No") << endl; + + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAStereo forVirtualScreen: currentScreen]; + strm << " stereo: " << (pfd == YES ? "Yes" : "No") << endl; + + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: currentScreen]; + strm << " hardware acceleration:: " << (pfd == YES ? "Yes" : "No") << endl; + + strm << ends; + delete[] this->Capabilities; + this->Capabilities = new char[strlen(strm.str()) + 1]; + strcpy(this->Capabilities, strm.str()); + return this->Capabilities; +} + +//---------------------------------------------------------------------------- +int vtkCocoaRenderWindow::SupportsOpenGL() +{ + this->MakeCurrent(); + if (!this->ContextId || !this->PixelFormat) + { + return 0; + } + + NSOpenGLContext* context = (NSOpenGLContext*)this->ContextId; + int currentScreen = [context currentVirtualScreen]; + + NSOpenGLPixelFormat* pixelFormat = (NSOpenGLPixelFormat*)this->PixelFormat; + long pfd; + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFACompliant forVirtualScreen: currentScreen]; + + return (pfd == YES ? 1 : 0); +} + +//---------------------------------------------------------------------------- +int vtkCocoaRenderWindow::IsDirect() +{ + this->MakeCurrent(); + if (!this->ContextId || !this->PixelFormat) + { + return 0; + } + + NSOpenGLContext* context = (NSOpenGLContext*)this->ContextId; + int currentScreen = [context currentVirtualScreen]; + + NSOpenGLPixelFormat* pixelFormat = (NSOpenGLPixelFormat*)this->PixelFormat; + long pfd; + [pixelFormat getValues: &pfd forAttribute: NSOpenGLPFAFullScreen forVirtualScreen: currentScreen]; + + return (pfd == YES ? 1 : 0); +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetSize(int* a) +{ + this->SetSize( a[0], a[1] ); +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetSize(int x, int y) +{ + static int resizing = 0; + + if ((this->Size[0] != x) || (this->Size[1] != y)) + { + this->Modified(); + this->Size[0] = x; + this->Size[1] = y; + if (this->WindowId && this->Mapped) + { + if (!resizing) + { + resizing = 1; + NSSize theSize = NSMakeSize((float)x, (float)y); + [(NSWindow*)this->WindowId setContentSize:theSize]; + resizing = 0; + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetForceMakeCurrent() +{ + this->ForceMakeCurrent = 1; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetPosition(int* a) +{ + this->SetPosition( a[0], a[1] ); +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetPosition(int x, int y) +{ + static int resizing = 0; + + if ((this->Position[0] != x) || (this->Position[1] != y)) + { + this->Modified(); + this->Position[0] = x; + this->Position[1] = y; + if (this->WindowId && this->Mapped) + { + if (!resizing) + { + resizing = 1; + NSPoint origin = NSMakePoint((float)x, (float)y); + [(NSWindow*)this->WindowId setFrameOrigin:origin]; + resizing = 0; + } + } + } +} + +//---------------------------------------------------------------------------- +// End the rendering process and display the image. +void vtkCocoaRenderWindow::Frame() +{ + this->MakeCurrent(); + [(NSOpenGLContext*)this->ContextId flushBuffer]; +} + +//---------------------------------------------------------------------------- +// Update system if needed due to stereo rendering. +void vtkCocoaRenderWindow::StereoUpdate() +{ + // if stereo is on and it wasn't before + if (this->StereoRender && (!this->StereoStatus)) + { + switch (this->StereoType) + { + case VTK_STEREO_CRYSTAL_EYES: + this->StereoStatus = 1; + break; + case VTK_STEREO_RED_BLUE: + this->StereoStatus = 1; + break; + case VTK_STEREO_ANAGLYPH: + this->StereoStatus = 1; + break; + case VTK_STEREO_DRESDEN: + this->StereoStatus = 1; + break; + case VTK_STEREO_INTERLACED: + this->StereoStatus = 1; + break; + } + } + else if ((!this->StereoRender) && this->StereoStatus) + { + switch (this->StereoType) + { + case VTK_STEREO_CRYSTAL_EYES: + this->StereoStatus = 0; + break; + case VTK_STEREO_RED_BLUE: + this->StereoStatus = 0; + break; + case VTK_STEREO_ANAGLYPH: + this->StereoStatus = 0; + break; + case VTK_STEREO_DRESDEN: + this->StereoStatus = 0; + break; + case VTK_STEREO_INTERLACED: + this->StereoStatus = 0; + break; + } + } +} + +//---------------------------------------------------------------------------- +// Specify various window parameters. +void vtkCocoaRenderWindow::WindowConfigure() +{ + // this is all handled by the desiredVisualInfo method +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetupPixelFormat(void*, void*, int, int, int) +{ + vtkErrorMacro(<< "vtkCocoaRenderWindow::SetupPixelFormat - IMPLEMENT\n"); +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::SetupPalette(void*) +{ + vtkErrorMacro(<< "vtkCocoaRenderWindow::SetupPalette - IMPLEMENT\n"); +} + +//---------------------------------------------------------------------------- +// Initialize the window for rendering. +void vtkCocoaRenderWindow::WindowInitialize () +{ + static int count = 1; + + // Due to the crossplatform nature of vtk, NSApplicationMain() is never + // called. Ideally, this should be fixed one day. Until then, we call + // +sharedApplication which has the side effect of doing some Cocoa + // initialisation; we are not actually interested in the return value. + // This call is intentionally delayed until this WindowInitialize call + // to prevent Cocoa-window related stuff from happening in scenarios + // where vtkRenderWindows are created but never shown. + (void)[NSApplication sharedApplication]; + + // create an NSWindow only if neither an NSView nor an NSWindow have + // been specified already + if (!this->WindowId && !this->NSViewId) + { + if ((this->Size[0]+this->Size[1])==0) + { + this->Size[0] = 300; + this->Size[1] = 300; + } + if ((this->Position[0]+this->Position[1])==0) + { + this->Position[0] = 50; + this->Position[1] = 50; + } + NSRect ctRect = NSMakeRect((float)this->Position[0], + (float)this->Position[1], + (float)this->Size[0], + (float)this->Size[1]); + + vtkCocoaWindow* theWindow = [[vtkCocoaWindow alloc] + initWithContentRect:ctRect + styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + if (!theWindow) + { + vtkErrorMacro("Could not create window, serious error!"); + return; + } + + [theWindow makeKeyAndOrderFront:nil]; + + [theWindow setAcceptsMouseMovedEvents:YES]; + + this->SetWindowId(theWindow); + this->WindowCreated = 1; + } + + // create a vtkCocoaGLView if one has not been specified + if (!this->NSViewId) + { + NSRect glRect = + NSMakeRect(0.0, 0.0, (float)this->Size[0], (float)this->Size[1]); + vtkCocoaGLView *glView = [[vtkCocoaGLView alloc] initWithFrame:glRect]; + [(NSWindow*)this->GetWindowId() setContentView:glView]; + + this->SetDisplayId(glView); + this->ViewCreated = 1; + [glView setVTKRenderWindow:this]; + } + + this->CreateGLContext(); + + // Set the window title *after* CreateGLContext. We cannot do it earlier + // because of a bug in panther's java library (OSX 10.3.9, Java 1.4.2_09) + // + // Details on Apple bug: + // http://lists.apple.com/archives/Quartz-dev/2005/Apr/msg00043.html + // Appears to be fixed in Mac OSX 10.4, but we workaround it here anyhow + // so that we can still work on 10.3... + // + NSString * winName = [NSString stringWithFormat:@"Visualization Toolkit - Cocoa #%i", count++]; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4 + this->SetWindowName([winName cStringUsingEncoding:NSASCIIStringEncoding]); +#else + this->SetWindowName([winName cString]); +#endif + + this->MakeCurrent(); + this->OpenGLInit(); + this->Mapped = 1; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::CreateGLContext() +{ + NSOpenGLPixelFormatAttribute attribs[] = + { + NSOpenGLPFAAccelerated, + NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)32, + this->DoubleBuffer? NSOpenGLPFADoubleBuffer : (NSOpenGLPixelFormatAttribute)nil, + (NSOpenGLPixelFormatAttribute)nil + }; + + NSOpenGLPixelFormat* pixelFormat = + (NSOpenGLPixelFormat*)[[NSOpenGLPixelFormat alloc] + initWithAttributes:attribs]; + NSOpenGLContext* context = (NSOpenGLContext*)[[NSOpenGLContext alloc] + initWithFormat:pixelFormat + shareContext:nil]; + + this->PixelFormat = (void*)pixelFormat; + this->ContextId = (void*)context; +} + +//---------------------------------------------------------------------------- +// Initialize the rendering window. +void vtkCocoaRenderWindow::Initialize () +{ + // make sure we havent already been initialized + if (this->ContextId) + { + return; + } + + // now initialize the window + this->WindowInitialize(); +} + +//---------------------------------------------------------------------------- +// Get the current size of the window. +int *vtkCocoaRenderWindow::GetSize() +{ + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Superclass::GetSize(); + } + + // We want to return the size of 'the window'. But the term 'window' + // is overloaded. It's really the NSView that vtk draws into, so we + // return its size. + NSRect frameRect = [(NSView *)this->NSViewId frame]; + this->Size[0] = (int)NSWidth(frameRect); + this->Size[1] = (int)NSHeight(frameRect); + return this->Superclass::GetSize(); +} + +//---------------------------------------------------------------------------- +// Get the current size of the screen. +int *vtkCocoaRenderWindow::GetScreenSize() +{ + NSOpenGLContext* context = (NSOpenGLContext*)this->ContextId; + int currentScreen = [context currentVirtualScreen]; + + NSScreen* screen = [[NSScreen screens] objectAtIndex: currentScreen]; + NSRect screenRect = [screen frame]; + this->Size[0] = (int)NSWidth(screenRect); + this->Size[1] = (int)NSHeight(screenRect); + return this->Size; +} + +//---------------------------------------------------------------------------- +// Get the position in screen coordinates of the window. +int *vtkCocoaRenderWindow::GetPosition() +{ + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Position; + } + + // We want to return the position of 'the window'. But the term 'window' + // is overloaded. In this case, it's the position of the NSWindow itself + // on the screen that we return. We don't much care where the NSView is + // within the NSWindow. + NSRect winFrameRect = [(NSWindow*)this->WindowId frame]; + this->Position[0] = (int)NSMinX(winFrameRect); + this->Position[1] = (int)NSMinY(winFrameRect); + return this->Position; +} + +//---------------------------------------------------------------------------- +// Change the window to fill the entire screen. +void vtkCocoaRenderWindow::SetFullScreen(int arg) +{ + int *pos; + + if (this->FullScreen == arg) + { + return; + } + + if (!this->Mapped) + { + this->PrefFullScreen(); + return; + } + + // set the mode + this->FullScreen = arg; + if (this->FullScreen <= 0) + { + this->Position[0] = this->OldScreen[0]; + this->Position[1] = this->OldScreen[1]; + this->Size[0] = this->OldScreen[2]; + this->Size[1] = this->OldScreen[3]; + this->Borders = this->OldScreen[4]; + } + else + { + // if window already up get its values + if (this->WindowId) + { + pos = this->GetPosition(); + this->OldScreen[0] = pos[0]; + this->OldScreen[1] = pos[1]; + + this->OldScreen[4] = this->Borders; + this->PrefFullScreen(); + } + } + + // remap the window + this->WindowRemap(); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// +// Set the variable that indicates that we want a stereo capable window +// be created. This method can only be called before a window is realized. +// +void vtkCocoaRenderWindow::SetStereoCapableWindow(int capable) +{ + if (this->WindowId == 0) + { + vtkRenderWindow::SetStereoCapableWindow(capable); + } + else + { + vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed " + << "before the window is realized, i.e. before a render."); + } +} + +//---------------------------------------------------------------------------- +// Set the preferred window size to full screen. +void vtkCocoaRenderWindow::PrefFullScreen() +{ + int *size = this->GetScreenSize(); + vtkWarningMacro(<< "Can't get full screen window of size " + << size[0] << 'x' << size[1] << "."); +} + +//---------------------------------------------------------------------------- +// Remap the window. +void vtkCocoaRenderWindow::WindowRemap() +{ + vtkWarningMacro(<< "Can't remap the window."); + // Aquire the display and capture the screen. + // Create the full-screen window. + // Add the context. +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ContextId: " << this->ContextId << "\n"; + os << indent << "MultiSamples: " << this->MultiSamples << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkCocoaRenderWindow::GetDepthBufferSize() +{ + GLint size; + + if ( this->Mapped ) + { + size = 0; + glGetIntegerv( GL_DEPTH_BITS, &size ); + return (int) size; + } + else + { + vtkDebugMacro(<< "Window is not mapped yet!" ); + return 24; + } +} + +//---------------------------------------------------------------------------- +// Returns the NSWindow* associated with this vtkRenderWindow. +void *vtkCocoaRenderWindow::GetWindowId() +{ + return this->WindowId; +} + +//---------------------------------------------------------------------------- +// Sets the NSWindow* associated with this vtkRenderWindow. +void vtkCocoaRenderWindow::SetWindowId(void *arg) +{ + this->WindowId = arg; +} + +//---------------------------------------------------------------------------- +// Returns the NSView* associated with this vtkRenderWindow. +void* vtkCocoaRenderWindow::GetDisplayId() +{ + return this->NSViewId; +} + +//---------------------------------------------------------------------------- +// Sets the NSView* associated with this vtkRenderWindow. +void vtkCocoaRenderWindow::SetDisplayId(void *arg) +{ + this->NSViewId = arg; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::HideCursor() +{ + if (this->CursorHidden) + { + return; + } + this->CursorHidden = 1; + + [NSCursor hide]; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindow::ShowCursor() +{ + if (!this->CursorHidden) + { + return; + } + this->CursorHidden = 0; + + [NSCursor unhide]; +} diff --git a/Rendering/vtkCocoaRenderWindowInteractor.h b/Rendering/vtkCocoaRenderWindowInteractor.h new file mode 100644 index 0000000..2f2363e --- /dev/null +++ b/Rendering/vtkCocoaRenderWindowInteractor.h @@ -0,0 +1,121 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaRenderWindowInteractor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCocoaRenderWindowInteractor - implements Cocoa specific functions +// required by vtkRenderWindowInteractor. +// +// .SECTION Description +// The interactor interfaces with vtkCocoaRenderWindow and vtkCocoaGLView +// to trap messages from the Cocoa window manager and send them to vtk. + +// IMPORTANT: This header must be in C++ only because it is included by .cxx files. +// That means no Objective C may be used. That's why some instance variables are +// void* instead of what they really should be. Pitty. + +#ifndef __vtkCocoaRenderWindowInteractor_h +#define __vtkCocoaRenderWindowInteractor_h + +#include "vtkRenderWindowInteractor.h" + + +class VTK_RENDERING_EXPORT vtkCocoaRenderWindowInteractor : public vtkRenderWindowInteractor +{ +public: + // Description: + // Construct object so that light follows camera motion. + static vtkCocoaRenderWindowInteractor *New(); + + vtkTypeRevisionMacro(vtkCocoaRenderWindowInteractor,vtkRenderWindowInteractor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initialize the even handler + virtual void Initialize(); + + // Description: + // Enable/Disable interactions. By default interactors are enabled when + // initialized. Initialize() must be called prior to enabling/disabling + // interaction. These methods are used when a window/widget is being + // shared by multiple renderers and interactors. This allows a "modal" + // display where one interactor is active when its data is to be displayed + // and all other interactors associated with the widget are disabled + // when their data is not displayed. + virtual void Enable(); + virtual void Disable(); + + // Description: + // This will start up the event loop and never return. If you + // call this method it will loop processing events until the + // application is exited. + virtual void Start(); + + // Description: + // By default the interactor installs a MessageProc callback which + // intercepts windows messages to the window and controls interactions. + // MFC or BCB programs can prevent this and instead directly route any mouse/key + // messages into the event bindings by setting InstallMessgeProc to false. + vtkSetMacro(InstallMessageProc,int); + vtkGetMacro(InstallMessageProc,int); + vtkBooleanMacro(InstallMessageProc,int); + + // Description: + // Cocoa specific application terminate, calls ClassExitMethod then + // calls PostQuitMessage(0) to terminate app. An application can Specify + // ExitMethod for alternative behaviour (i.e. suppresion of keyboard exit) + void TerminateApp(); + + // Description: + // Cocoa timer methods + int CreateTimer(int timertype); + int DestroyTimer(); + + // Description: + // Methods to set the default exit method for the class. This method is + // only used if no instance level ExitMethod has been defined. It is + // provided as a means to control how an interactor is exited given + // the various language bindings (tcl, Cocoa, etc.). + static void SetClassExitMethod(void (*f)(void *), void *arg); + static void SetClassExitMethodArgDelete(void (*f)(void *)); + + // Description: + // These methods correspond to the the Exit, User and Pick + // callbacks. They allow for the Style to invoke them. + virtual void ExitCallback(); + +// int GetButtonDown(); +// void SetButtonDown(int button); + +protected: + vtkCocoaRenderWindowInteractor(); + ~vtkCocoaRenderWindowInteractor(); + + int InstallMessageProc; + void* Timer; // really a vtkCocoaTimer* + + //BTX + // Description: + // Class variables so an exit method can be defined for this class + // (used to set different exit methods for various language bindings, + // i.e. tcl, java, Cocoa) + static void (*ClassExitMethod)(void *); + static void (*ClassExitMethodArgDelete)(void *); + static void *ClassExitMethodArg; + //ETX + +private: + vtkCocoaRenderWindowInteractor(const vtkCocoaRenderWindowInteractor&); // Not implemented. + void operator=(const vtkCocoaRenderWindowInteractor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkCocoaRenderWindowInteractor.mm b/Rendering/vtkCocoaRenderWindowInteractor.mm new file mode 100644 index 0000000..d9897e6 --- /dev/null +++ b/Rendering/vtkCocoaRenderWindowInteractor.mm @@ -0,0 +1,266 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaRenderWindowInteractor.mm,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#import "vtkCocoaRenderWindowInteractor.h" +#import "vtkCocoaRenderWindow.h" +#import "vtkCommand.h" +#import "vtkObjectFactory.h" + +#import +#import + +#ifndef MAC_OS_X_VERSION_10_4 +#define MAC_OS_X_VERSION_10_4 1040 +#endif + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkCocoaRenderWindowInteractor, "$Revision: 1.8.4.1 $"); +vtkStandardNewMacro(vtkCocoaRenderWindowInteractor); + +//---------------------------------------------------------------------------- +void (*vtkCocoaRenderWindowInteractor::ClassExitMethod)(void *) = (void (*)(void *))NULL; +void *vtkCocoaRenderWindowInteractor::ClassExitMethodArg = (void *)NULL; +void (*vtkCocoaRenderWindowInteractor::ClassExitMethodArgDelete)(void *) = (void (*)(void *))NULL; + +// This is a private class and an implementation detail, do not use it. +//---------------------------------------------------------------------------- +@interface vtkCocoaTimer : NSObject +{ + NSTimer *timer; + vtkCocoaRenderWindowInteractor *interactor; +} + +- (id)initWithInteractor:(vtkCocoaRenderWindowInteractor *)myInteractor; +- (void)startTimer; +- (void)stopTimer; +- (void)timerFired:(NSTimer *)myTimer; + +@end + +//---------------------------------------------------------------------------- +@implementation vtkCocoaTimer + +- (id)initWithInteractor:(vtkCocoaRenderWindowInteractor *)myInteractor +{ + self = [super init]; + if (self) + { + interactor = myInteractor; + } + return self; +} + +- (void)timerFired:(NSTimer *)myTimer +{ + (void)myTimer; + interactor->InvokeEvent(vtkCommand::TimerEvent,NULL); +} + +- (void)startTimer +{ + timer = [NSTimer timerWithTimeInterval:0.01 + target:self + selector:@selector(timerFired:) + userInfo:nil + repeats:YES]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; + [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode]; +} + +- (void)stopTimer +{ + [timer invalidate]; +} + +@end + + + +//---------------------------------------------------------------------------- +// Construct object so that light follows camera motion. +vtkCocoaRenderWindowInteractor::vtkCocoaRenderWindowInteractor() +{ + this->InstallMessageProc = 1; +} + +//---------------------------------------------------------------------------- +vtkCocoaRenderWindowInteractor::~vtkCocoaRenderWindowInteractor() +{ + this->Enabled = 0; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindowInteractor::Start() +{ + // Let the compositing handle the event loop if it wants to. + if (this->HasObserver(vtkCommand::StartEvent)) + { + this->InvokeEvent(vtkCommand::StartEvent,NULL); + return; + } + + // No need to do anything if this is a 'mapped' interactor + if (!this->Enabled || !this->InstallMessageProc) + { + return; + } + + (void)[NSApplication sharedApplication]; //make sure the app is initialized + [NSApp run]; +} + +//---------------------------------------------------------------------------- +// Begin processing keyboard strokes. +void vtkCocoaRenderWindowInteractor::Initialize() +{ + vtkCocoaRenderWindow *renWin; + int *size; + + // make sure we have a RenderWindow and camera + if ( !this->RenderWindow ) + { + vtkErrorMacro(<<"No renderer defined!"); + return; + } + if (this->Initialized) + { + return; + } + this->Initialized = 1; + // get the info we need from the RenderingWindow + renWin = (vtkCocoaRenderWindow *)(this->RenderWindow); + renWin->Start(); + size = renWin->GetSize(); + + renWin->GetPosition(); // update values of this->Position[2] + + this->Enable(); + this->Size[0] = size[0]; + this->Size[1] = size[1]; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindowInteractor::Enable() +{ + if (this->Enabled) + { + return; + } + + // Set the RenderWindow's interactor so that when the vtkCocoaGLView tries + // to handle events from the OS it will either handle them or ignore them + this->GetRenderWindow()->SetInteractor(this); + + this->Enabled = 1; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindowInteractor::Disable() +{ + if (!this->Enabled) + { + return; + } + + // Set the RenderWindow's interactor so that when the vtkCocoaGLView tries + // to handle events from the OS it will either handle them or ignore them + this->GetRenderWindow()->SetInteractor(NULL); + + this->Enabled = 0; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindowInteractor::TerminateApp() +{ + [NSApp terminate:NSApp]; +} + +//---------------------------------------------------------------------------- +int vtkCocoaRenderWindowInteractor::CreateTimer(int timertype) +{ + if (timertype==VTKI_TIMER_FIRST) + { + this->Timer = (void*)[[vtkCocoaTimer alloc] initWithInteractor:this]; + [(vtkCocoaTimer*)this->Timer startTimer]; + } + return 1; +} + +//---------------------------------------------------------------------------- +int vtkCocoaRenderWindowInteractor::DestroyTimer() +{ + [(vtkCocoaTimer*)this->Timer stopTimer]; + [(vtkCocoaTimer*)this->Timer release]; + this->Timer = 0; + return 1; +} + +//---------------------------------------------------------------------------- +// Specify the default function to be called when an interactor needs to exit. +// This callback is overridden by an instance ExitMethod that is defined. +void vtkCocoaRenderWindowInteractor::SetClassExitMethod(void (*f)(void *),void *arg) +{ + if ( f != vtkCocoaRenderWindowInteractor::ClassExitMethod + || arg != vtkCocoaRenderWindowInteractor::ClassExitMethodArg) + { + // delete the current arg if there is a delete method + if ((vtkCocoaRenderWindowInteractor::ClassExitMethodArg) + && (vtkCocoaRenderWindowInteractor::ClassExitMethodArgDelete)) + { + (*vtkCocoaRenderWindowInteractor::ClassExitMethodArgDelete) + (vtkCocoaRenderWindowInteractor::ClassExitMethodArg); + } + vtkCocoaRenderWindowInteractor::ClassExitMethod = f; + vtkCocoaRenderWindowInteractor::ClassExitMethodArg = arg; + + // no call to this->Modified() since this is a class member function + } +} + + +//---------------------------------------------------------------------------- +// Set the arg delete method. This is used to free user memory. +void vtkCocoaRenderWindowInteractor::SetClassExitMethodArgDelete(void (*f)(void *)) +{ + if (f != vtkCocoaRenderWindowInteractor::ClassExitMethodArgDelete) + { + vtkCocoaRenderWindowInteractor::ClassExitMethodArgDelete = f; + + // no call to this->Modified() since this is a class member function + } +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "InstallMessageProc: " << this->InstallMessageProc << endl; +} + +//---------------------------------------------------------------------------- +void vtkCocoaRenderWindowInteractor::ExitCallback() +{ + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent,NULL); + } + else if (this->ClassExitMethod) + { + (*this->ClassExitMethod)(this->ClassExitMethodArg); + } + this->TerminateApp(); +} + diff --git a/Rendering/vtkCocoaWindow.h b/Rendering/vtkCocoaWindow.h new file mode 100644 index 0000000..76991c1 --- /dev/null +++ b/Rendering/vtkCocoaWindow.h @@ -0,0 +1,34 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCocoaWindow - Access Cocoa NSWindow context +// +// .SECTION Description +// This class is a subclass of Cocoa's NSWindow; it uses Objective-C++. +// A vtkCocoaWindow is created automatically by vtk by default, but the +// programmer can override this behaviour. See vtkCocoaRenderWindow's +// SetWindowId() and WindowInitialize(). +// Note that this class previously contained much more functionality +// but that functionality has been moved to other classes. + +// .SECTION See Also +// vtkCocoaGLView vtkCocoaRenderWindow + +#import + +@interface vtkCocoaWindow : NSWindow +{ +} + +@end diff --git a/Rendering/vtkCocoaWindow.mm b/Rendering/vtkCocoaWindow.mm new file mode 100644 index 0000000..93ea76e --- /dev/null +++ b/Rendering/vtkCocoaWindow.mm @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCocoaWindow.mm,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#import "vtkCocoaWindow.h" + +@implementation vtkCocoaWindow + +//---------------------------------------------------------------------------- +- (void)close +{ + [super close]; +} + +@end diff --git a/Rendering/vtkCuller.cxx b/Rendering/vtkCuller.cxx new file mode 100644 index 0000000..60f6d6b --- /dev/null +++ b/Rendering/vtkCuller.cxx @@ -0,0 +1,31 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCuller.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCuller.h" + +vtkCxxRevisionMacro(vtkCuller, "$Revision: 1.4 $"); + +vtkCuller::vtkCuller() +{ +} + +vtkCuller::~vtkCuller() +{ +} + +//---------------------------------------------------------------------------- +void vtkCuller::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkCuller.h b/Rendering/vtkCuller.h new file mode 100644 index 0000000..bca6c71 --- /dev/null +++ b/Rendering/vtkCuller.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCuller.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCuller - a superclass for prop cullers +// .SECTION Description +// A culler has a cull method called by the vtkRenderer. The cull +// method is called before any rendering is performed, +// and it allows the culler to do some processing on the props and +// to modify their AllocatedRenderTime and re-order them in the prop list. + +// .SECTION see also +// vtkFrustumCoverageCuller + +#ifndef __vtkCuller_h +#define __vtkCuller_h + +#include "vtkObject.h" + +class vtkProp; +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkCuller : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkCuller,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is called outside the render loop by vtkRenderer + virtual double Cull( vtkRenderer *ren, vtkProp **propList, + int& listLength, int& initialized )=0; + +protected: + vtkCuller(); + ~vtkCuller(); +private: + vtkCuller(const vtkCuller&); // Not implemented. + void operator=(const vtkCuller&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkCullerCollection.cxx b/Rendering/vtkCullerCollection.cxx new file mode 100644 index 0000000..b88588b --- /dev/null +++ b/Rendering/vtkCullerCollection.cxx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCullerCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCullerCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkCullerCollection, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkCullerCollection); + +//---------------------------------------------------------------------------- +void vtkCullerCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkCullerCollection.h b/Rendering/vtkCullerCollection.h new file mode 100644 index 0000000..0645e34 --- /dev/null +++ b/Rendering/vtkCullerCollection.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkCullerCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkCullerCollection - a list of Cullers +// .SECTION Description +// vtkCullerCollection represents and provides methods to manipulate a list +// of Cullers (i.e., vtkCuller and subclasses). The list is unsorted and +// duplicate entries are not prevented. + +// .SECTION see also +// vtkCuller vtkCollection + +#ifndef __vtkCullerC_h +#define __vtkCullerC_h + +#include "vtkCollection.h" +#include "vtkCuller.h" // for inline functions + +class VTK_RENDERING_EXPORT vtkCullerCollection : public vtkCollection +{ + public: + static vtkCullerCollection *New(); + vtkTypeRevisionMacro(vtkCullerCollection,vtkCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add an Culler to the list. + void AddItem(vtkCuller *a) { + this->vtkCollection::AddItem((vtkObject *)a);}; + + // Description: + // Get the next Culler in the list. + vtkCuller *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + // Description: + // Get the last Culler in the list. + vtkCuller *GetLastItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkCuller *GetNextCuller(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkCullerCollection() {}; + ~vtkCullerCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkCullerCollection(const vtkCullerCollection&); // Not implemented. + void operator=(const vtkCullerCollection&); // Not implemented. +}; + + +inline vtkCuller *vtkCullerCollection::GetLastItem() +{ + if ( this->Bottom == NULL ) + { + return NULL; + } + else + { + return static_cast(this->Bottom->Item); + } +} + +#endif + + + + + diff --git a/Rendering/vtkDataSetMapper.cxx b/Rendering/vtkDataSetMapper.cxx new file mode 100644 index 0000000..2a87b4f --- /dev/null +++ b/Rendering/vtkDataSetMapper.cxx @@ -0,0 +1,219 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDataSetMapper.h" + +#include "vtkDataSet.h" +#include "vtkDataSetSurfaceFilter.h" +#include "vtkExecutive.h" +#include "vtkGarbageCollector.h" +#include "vtkInformation.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" + +vtkCxxRevisionMacro(vtkDataSetMapper, "$Revision: 1.70 $"); +vtkStandardNewMacro(vtkDataSetMapper); + +//---------------------------------------------------------------------------- +vtkDataSetMapper::vtkDataSetMapper() +{ + this->GeometryExtractor = NULL; + this->PolyDataMapper = NULL; +} + +//---------------------------------------------------------------------------- +vtkDataSetMapper::~vtkDataSetMapper() +{ + // delete internally created objects. + if ( this->GeometryExtractor ) + { + this->GeometryExtractor->Delete(); + } + if ( this->PolyDataMapper ) + { + this->PolyDataMapper->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkDataSetMapper::SetInput(vtkDataSet *input) +{ + if(input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(0, 0); + } +} + +//---------------------------------------------------------------------------- +vtkDataSet *vtkDataSetMapper::GetInput() +{ + return this->Superclass::GetInputAsDataSet(); +} + +//---------------------------------------------------------------------------- +void vtkDataSetMapper::ReleaseGraphicsResources( vtkWindow *renWin ) +{ + if (this->PolyDataMapper) + { + this->PolyDataMapper->ReleaseGraphicsResources( renWin ); + } +} + +//---------------------------------------------------------------------------- +// Receives from Actor -> maps data to primitives +// +void vtkDataSetMapper::Render(vtkRenderer *ren, vtkActor *act) +{ + // make sure that we've been properly initialized + // + if ( !this->GetInput() ) + { + vtkErrorMacro(<< "No input!\n"); + return; + } + + // Need a lookup table + // + if ( this->LookupTable == NULL ) + { + this->CreateDefaultLookupTable(); + } + this->LookupTable->Build(); + + // Now can create appropriate mapper + // + if ( this->PolyDataMapper == NULL ) + { + vtkDataSetSurfaceFilter *gf = vtkDataSetSurfaceFilter::New(); + vtkPolyDataMapper *pm = vtkPolyDataMapper::New(); + pm->SetInput(gf->GetOutput()); + + this->GeometryExtractor = gf; + this->PolyDataMapper = pm; + } + + // share clipping planes with the PolyDataMapper + // + if (this->ClippingPlanes != this->PolyDataMapper->GetClippingPlanes()) + { + this->PolyDataMapper->SetClippingPlanes(this->ClippingPlanes); + } + + // For efficiency: if input type is vtkPolyData, there's no need to + // pass it thru the geometry filter. + // + if ( this->GetInput()->GetDataObjectType() == VTK_POLY_DATA ) + { + this->PolyDataMapper->SetInput(static_cast(this->GetInput())); + } + else + { + this->GeometryExtractor->SetInput(this->GetInput()); + this->PolyDataMapper->SetInput(this->GeometryExtractor->GetOutput()); + } + + // update ourselves in case something has changed + this->PolyDataMapper->SetLookupTable(this->GetLookupTable()); + this->PolyDataMapper->SetScalarVisibility(this->GetScalarVisibility()); + this->PolyDataMapper->SetUseLookupTableScalarRange( + this->GetUseLookupTableScalarRange()); + this->PolyDataMapper->SetScalarRange(this->GetScalarRange()); + this->PolyDataMapper->SetImmediateModeRendering( + this->GetImmediateModeRendering()); + this->PolyDataMapper->SetColorMode(this->GetColorMode()); + this->PolyDataMapper->SetInterpolateScalarsBeforeMapping( + this->GetInterpolateScalarsBeforeMapping()); + + this->PolyDataMapper->SetScalarMode(this->GetScalarMode()); + if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA || + this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + if ( this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID ) + { + this->PolyDataMapper->ColorByArrayComponent(this->ArrayId,ArrayComponent); + } + else + { + this->PolyDataMapper->ColorByArrayComponent(this->ArrayName,ArrayComponent); + } + } + + this->PolyDataMapper->Render(ren,act); + this->TimeToDraw = this->PolyDataMapper->GetTimeToDraw(); +} + +//---------------------------------------------------------------------------- +void vtkDataSetMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->PolyDataMapper ) + { + os << indent << "Poly Mapper: (" << this->PolyDataMapper << ")\n"; + } + else + { + os << indent << "Poly Mapper: (none)\n"; + } + + if ( this->GeometryExtractor ) + { + os << indent << "Geometry Extractor: (" << this->GeometryExtractor << ")\n"; + } + else + { + os << indent << "Geometry Extractor: (none)\n"; + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkDataSetMapper::GetMTime() +{ + unsigned long mTime=this->vtkMapper::GetMTime(); + unsigned long time; + + if ( this->LookupTable != NULL ) + { + time = this->LookupTable->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +//---------------------------------------------------------------------------- +int vtkDataSetMapper::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkDataSetMapper::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->GeometryExtractor, + "GeometryExtractor"); + vtkGarbageCollectorReport(collector, this->PolyDataMapper, + "PolyDataMapper"); +} diff --git a/Rendering/vtkDataSetMapper.h b/Rendering/vtkDataSetMapper.h new file mode 100644 index 0000000..10778b0 --- /dev/null +++ b/Rendering/vtkDataSetMapper.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDataSetMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkDataSetMapper - map vtkDataSet and derived classes to graphics primitives +// .SECTION Description +// vtkDataSetMapper is a mapper to map data sets (i.e., vtkDataSet and +// all derived classes) to graphics primitives. The mapping procedure +// is as follows: all 0D, 1D, and 2D cells are converted into points, +// lines, and polygons/triangle strips and then mapped to the graphics +// system. The 2D faces of 3D cells are mapped only if they are used by +// only one cell, i.e., on the boundary of the data set. + +#ifndef __vtkDataSetMapper_h +#define __vtkDataSetMapper_h + +#include "vtkMapper.h" + +class vtkPolyDataMapper; +class vtkDataSetSurfaceFilter; + +class VTK_RENDERING_EXPORT vtkDataSetMapper : public vtkMapper +{ +public: + static vtkDataSetMapper *New(); + vtkTypeRevisionMacro(vtkDataSetMapper,vtkMapper); + void PrintSelf(ostream& os, vtkIndent indent); + void Render(vtkRenderer *ren, vtkActor *act); + + // Description: + // Get the internal poly data mapper used to map data set to graphics system. + vtkGetObjectMacro(PolyDataMapper, vtkPolyDataMapper); + + // Description: + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Get the mtime also considering the lookup table. + unsigned long GetMTime(); + + // Description: + // Set the Input of this mapper. + void SetInput(vtkDataSet *input); + vtkDataSet *GetInput(); + +protected: + vtkDataSetMapper(); + ~vtkDataSetMapper(); + + vtkDataSetSurfaceFilter *GeometryExtractor; + vtkPolyDataMapper *PolyDataMapper; + + virtual void ReportReferences(vtkGarbageCollector*); + + // see algorithm for more info + virtual int FillInputPortInformation(int port, vtkInformation* info); + +private: + vtkDataSetMapper(const vtkDataSetMapper&); // Not implemented. + void operator=(const vtkDataSetMapper&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkExporter.cxx b/Rendering/vtkExporter.cxx new file mode 100644 index 0000000..20384c3 --- /dev/null +++ b/Rendering/vtkExporter.cxx @@ -0,0 +1,180 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkExporter.h" + +#include "vtkRenderWindow.h" + +vtkCxxRevisionMacro(vtkExporter, "$Revision: 1.19 $"); + +vtkCxxSetObjectMacro(vtkExporter,RenderWindow,vtkRenderWindow); + + +// Construct with no start and end write methods or arguments. +vtkExporter::vtkExporter() +{ + this->RenderWindow = NULL; + this->StartWrite = NULL; + this->StartWriteArgDelete = NULL; + this->StartWriteArg = NULL; + this->EndWrite = NULL; + this->EndWriteArgDelete = NULL; + this->EndWriteArg = NULL; +} + +vtkExporter::~vtkExporter() +{ + this->SetRenderWindow(NULL); + + if ((this->StartWriteArg)&&(this->StartWriteArgDelete)) + { + (*this->StartWriteArgDelete)(this->StartWriteArg); + } + if ((this->EndWriteArg)&&(this->EndWriteArgDelete)) + { + (*this->EndWriteArgDelete)(this->EndWriteArg); + } +} + + +// Write data to output. Method executes subclasses WriteData() method, as +// well as StartWrite() and EndWrite() methods. +void vtkExporter::Write() +{ + // make sure input is available + if ( !this->RenderWindow ) + { + vtkErrorMacro(<< "No render window provided!"); + return; + } + + if ( this->StartWrite ) + { + (*this->StartWrite)(this->StartWriteArg); + } + this->WriteData(); + if ( this->EndWrite ) + { + (*this->EndWrite)(this->EndWriteArg); + } +} + +// Convenient alias for Write() method. +void vtkExporter::Update() +{ + this->Write(); +} + +// Specify a function to be called before data is written. +// Function will be called with argument provided. +void vtkExporter::SetStartWrite(void (*f)(void *), void *arg) +{ + if ( f != this->StartWrite ) + { + // delete the current arg if there is one and a delete meth + if ((this->StartWriteArg)&&(this->StartWriteArgDelete)) + { + (*this->StartWriteArgDelete)(this->StartWriteArg); + } + this->StartWrite = f; + this->StartWriteArg = arg; + this->Modified(); + } +} + + +// Set the arg delete method. This is used to free user memory. +void vtkExporter::SetStartWriteArgDelete(void (*f)(void *)) +{ + if ( f != this->StartWriteArgDelete) + { + this->StartWriteArgDelete = f; + this->Modified(); + } +} + +// Set the arg delete method. This is used to free user memory. +void vtkExporter::SetEndWriteArgDelete(void (*f)(void *)) +{ + if ( f != this->EndWriteArgDelete) + { + this->EndWriteArgDelete = f; + this->Modified(); + } +} + +// Specify a function to be called after data is written. +// Function will be called with argument provided. +void vtkExporter::SetEndWrite(void (*f)(void *), void *arg) +{ + if ( f != this->EndWrite ) + { + // delete the current arg if there is one and a delete meth + if ((this->EndWriteArg)&&(this->EndWriteArgDelete)) + { + (*this->EndWriteArgDelete)(this->EndWriteArg); + } + this->EndWrite = f; + this->EndWriteArg = arg; + this->Modified(); + } +} + +void vtkExporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->RenderWindow ) + { + os << indent << "Render Window: (" << (void *)this->RenderWindow << ")\n"; + } + else + { + os << indent << "Render Window: (none)\n"; + } + + if ( this->StartWrite ) + { + os << indent << "Start Write: (" << (void *)this->StartWrite << ")\n"; + } + else + { + os << indent << "Start Write: (none)\n"; + } + + if ( this->EndWrite ) + { + os << indent << "End Write: (" << (void *)this->EndWrite << ")\n"; + } + else + { + os << indent << "End Write: (none)\n"; + } +} + +unsigned long int vtkExporter::GetMTime() +{ + unsigned long mTime=this-> vtkObject::GetMTime(); + unsigned long time; + + if ( this->RenderWindow != NULL ) + { + time = this->RenderWindow->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + return mTime; +} + + + diff --git a/Rendering/vtkExporter.h b/Rendering/vtkExporter.h new file mode 100644 index 0000000..1f8e28f --- /dev/null +++ b/Rendering/vtkExporter.h @@ -0,0 +1,110 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkExporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkExporter - abstract class to write a scene to a file +// .SECTION Description +// vtkExporter is an abstract class that exports a scene to a file. It +// is very similar to vtkWriter except that a writer only writes out +// the geometric and topological data for an object, where an exporter +// can write out material properties, lighting, camera parameters etc. +// The concrete subclasses of this class may not write out all of this +// information. For example vtkOBJExporter writes out Wavefront obj files +// which do not include support for camera parameters. +// +// vtkExporter provides the convenience methods StartWrite() and EndWrite(). +// These methods are executed before and after execution of the Write() +// method. You can also specify arguments to these methods. +// This class defines SetInput and GetInput methods which take or return +// a vtkRenderWindow. +// .SECTION Caveats +// Every subclass of vtkExporter must implement a WriteData() method. + +// .SECTION See Also +// vtkOBJExporter vtkRenderWindow vtkWriter + +#ifndef __vtkExporter_h +#define __vtkExporter_h + +#include "vtkObject.h" +class vtkRenderWindow; + +class VTK_RENDERING_EXPORT vtkExporter : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkExporter,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Write data to output. Method executes subclasses WriteData() method, as + // well as StartWrite() and EndWrite() methods. + virtual void Write(); + + // Description: + // Convenient alias for Write() method. + void Update(); + + // Description: + // Set/Get the rendering window that contains the scene to be written. + virtual void SetRenderWindow(vtkRenderWindow*); + vtkGetObjectMacro(RenderWindow,vtkRenderWindow); + + // Description: + // These methods are provided for backward compatibility. Will disappear + // soon. + void SetInput(vtkRenderWindow *renWin) {this->SetRenderWindow(renWin);}; + vtkRenderWindow *GetInput() {return this->GetRenderWindow();}; + + // Description: + // Specify a function to be called before data is written. Function will + // be called with argument provided. + void SetStartWrite(void (*f)(void *), void *arg); + + // Description: + // Specify a function to be called after data is written. + // Function will be called with argument provided. + void SetEndWrite(void (*f)(void *), void *arg); + + // Description: + // Set the arg delete method. This is used to free user memory. + void SetStartWriteArgDelete(void (*f)(void *)); + + // Description: + // Set the arg delete method. This is used to free user memory. + void SetEndWriteArgDelete(void (*f)(void *)); + + // Description: + // Returns the MTime also considering the RenderWindow. + unsigned long GetMTime(); + +protected: + vtkExporter(); + ~vtkExporter(); + + vtkRenderWindow *RenderWindow; + virtual void WriteData() = 0; + + void (*StartWrite)(void *); + void (*StartWriteArgDelete)(void *); + void *StartWriteArg; + void (*EndWrite)(void *); + void (*EndWriteArgDelete)(void *); + void *EndWriteArg; +private: + vtkExporter(const vtkExporter&); // Not implemented. + void operator=(const vtkExporter&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkFollower.cxx b/Rendering/vtkFollower.cxx new file mode 100644 index 0000000..9dea92c --- /dev/null +++ b/Rendering/vtkFollower.cxx @@ -0,0 +1,262 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFollower.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkFollower.h" + +#include "vtkCamera.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkTexture.h" +#include "vtkTransform.h" + +#include + +vtkCxxRevisionMacro(vtkFollower, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkFollower); + +vtkCxxSetObjectMacro(vtkFollower,Camera,vtkCamera); + +// Creates a follower with no camera set +vtkFollower::vtkFollower() +{ + this->Camera = NULL; + this->Device = vtkActor::New(); +} + +vtkFollower::~vtkFollower() +{ + if (this->Camera) + { + this->Camera->UnRegister(this); + } + + this->Device->Delete(); +} + +// Copy the follower's composite 4x4 matrix into the matrix provided. +void vtkFollower::GetMatrix(vtkMatrix4x4 *result) +{ + double *pos, *vup; + double Rx[3], Ry[3], Rz[3], p1[3]; + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + int i; + double distance; + + this->GetOrientation(); + this->Transform->Push(); + this->Transform->PostMultiply(); + this->Transform->Identity(); + + // apply user defined matrix last if there is one + if (this->UserMatrix) + { + this->Transform->Concatenate(this->UserMatrix); + } + + this->Transform->Translate(-this->Origin[0], + -this->Origin[1], + -this->Origin[2]); + // scale + this->Transform->Scale(this->Scale[0], + this->Scale[1], + this->Scale[2]); + + // rotate + this->Transform->RotateY(this->Orientation[1]); + this->Transform->RotateX(this->Orientation[0]); + this->Transform->RotateZ(this->Orientation[2]); + + if (this->Camera) + { + // do the rotation + // first rotate y + pos = this->Camera->GetPosition(); + vup = this->Camera->GetViewUp(); + + if (this->Camera->GetParallelProjection()) + { + this->Camera->GetDirectionOfProjection(Rz); + Rz[0] = -Rz[0]; + Rz[1] = -Rz[1]; + Rz[2] = -Rz[2]; + } + else + { + distance = sqrt( + (pos[0] - this->Position[0])*(pos[0] - this->Position[0]) + + (pos[1] - this->Position[1])*(pos[1] - this->Position[1]) + + (pos[2] - this->Position[2])*(pos[2] - this->Position[2])); + for (i = 0; i < 3; i++) + { + Rz[i] = (pos[i] - this->Position[i])/distance; + } + } + + // We cannot directly use the vup angle since it can be aligned with Rz: + //vtkMath::Cross(vup,Rz,Rx); + //vtkMath::Normalize(Rx); + //vtkMath::Cross(Rz,Rx,Ry); + + //instead use the view right angle: + double dop[3], vur[3]; + this->Camera->GetDirectionOfProjection(dop); + + vtkMath::Cross(dop,vup,vur); + vtkMath::Normalize(vur); + + vtkMath::Cross(Rz, vur, Ry); + vtkMath::Normalize(Ry); + vtkMath::Cross(Ry,Rz,Rx); + + matrix->Element[0][0] = Rx[0]; + matrix->Element[1][0] = Rx[1]; + matrix->Element[2][0] = Rx[2]; + matrix->Element[0][1] = Ry[0]; + matrix->Element[1][1] = Ry[1]; + matrix->Element[2][1] = Ry[2]; + matrix->Element[0][2] = Rz[0]; + matrix->Element[1][2] = Rz[1]; + matrix->Element[2][2] = Rz[2]; + + this->Transform->Concatenate(matrix); + } + + // translate to projection reference point PRP + // this is the camera's position blasted through + // the current matrix + p1[0] = this->Origin[0] + this->Position[0]; + p1[1] = this->Origin[1] + this->Position[1]; + p1[2] = this->Origin[2] + this->Position[2]; + + this->Transform->Translate(p1[0],p1[1],p1[2]); + this->Transform->GetMatrix(result); + + matrix->Delete(); + this->Transform->Pop(); +} + +void vtkFollower::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Camera ) + { + os << indent << "Camera:\n"; + this->Camera->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Camera: (none)\n"; + } +} + +int vtkFollower::RenderOpaqueGeometry(vtkViewport *vp) +{ + if ( ! this->Mapper ) + { + return 0; + } + + if (!this->Property) + { + // force creation of a property + this->GetProperty(); + } + + if (this->GetIsOpaque()) + { + vtkRenderer *ren = static_cast(vp); + this->Render(ren); + return 1; + } + return 0; +} + +int vtkFollower::RenderTranslucentGeometry(vtkViewport *vp) +{ + if ( ! this->Mapper ) + { + return 0; + } + + if (!this->Property) + { + // force creation of a property + this->GetProperty(); + } + + if (!this->GetIsOpaque()) + { + vtkRenderer *ren = static_cast(vp); + this->Render(ren); + return 1; + } + return 0; +} + +// This causes the actor to be rendered. It, in turn, will render the actor's +// property and then mapper. +void vtkFollower::Render(vtkRenderer *ren) +{ + this->Property->Render(this, ren); + + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + + this->Device->SetProperty (this->Property); + this->Property->Render(this, ren); + if (this->BackfaceProperty) + { + this->BackfaceProperty->BackfaceRender(this, ren); + this->Device->SetBackfaceProperty(this->BackfaceProperty); + } + + /* render the texture */ + if (this->Texture) + { + this->Texture->Render(ren); + } + + // make sure the device has the same matrix + this->GetMatrix(matrix); + this->Device->SetUserMatrix(matrix); + + this->Device->Render(ren,this->Mapper); + + matrix->Delete(); +} + +void vtkFollower::GetMatrix(double m[16]) +{ + this->GetMatrix(this->Matrix); + vtkMatrix4x4::DeepCopy(m,this->Matrix); +} + +void vtkFollower::ShallowCopy(vtkProp *prop) +{ + vtkFollower *f = vtkFollower::SafeDownCast(prop); + if ( f != NULL ) + { + this->SetCamera(f->GetCamera()); + } + + // Now do superclass + this->vtkActor::ShallowCopy(prop); +} + + + diff --git a/Rendering/vtkFollower.h b/Rendering/vtkFollower.h new file mode 100644 index 0000000..0997f4c --- /dev/null +++ b/Rendering/vtkFollower.h @@ -0,0 +1,88 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFollower.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFollower - a subclass of actor that always faces the camera +// .SECTION Description +// vtkFollower is a subclass of vtkActor that always follows its specified +// camera. More specifically it will not change its position or scale, +// but it will continually update its orientation so that it is right side +// up and facing the camera. This is typically used for text labels in a +// scene. All of the adjustments that can be made to an actor also will +// take effect with a follower. So, if you change the orientation of the +// follower by 90 degrees, then it will follow the camera, but be off by +// 90 degrees. + +// .SECTION see also +// vtkActor vtkCamera + +#ifndef __vtkFollower_h +#define __vtkFollower_h + +#include "vtkActor.h" + +class vtkCamera; + +class VTK_RENDERING_EXPORT vtkFollower : public vtkActor +{ + public: + vtkTypeRevisionMacro(vtkFollower,vtkActor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates a follower with no camera set + static vtkFollower *New(); + + // Description: + // Set/Get the camera to follow. If this is not set, then the follower + // won't know who to follow. + virtual void SetCamera(vtkCamera*); + vtkGetObjectMacro(Camera,vtkCamera); + + // Description: + // This causes the actor to be rendered. It in turn will render the actor's + // property, texture map and then mapper. If a property hasn't been + // assigned, then the actor will create one automatically. + virtual int RenderOpaqueGeometry(vtkViewport *viewport); + virtual int RenderTranslucentGeometry(vtkViewport *viewport); + virtual void Render(vtkRenderer *ren); + + // Description: + // Copy the follower's composite 4x4 matrix into the matrix provided. + virtual void GetMatrix(vtkMatrix4x4 *m); + virtual void GetMatrix(double m[16]); + virtual vtkMatrix4x4* GetMatrix() + {return this->vtkActor::GetMatrix();} + + // Description: + // Shallow copy of a follower. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + +protected: + vtkFollower(); + ~vtkFollower(); + + vtkCamera *Camera; + vtkActor *Device; +private: + // hide the two parameter Render() method from the user and the compiler. + virtual void Render(vtkRenderer *, vtkMapper *) {}; +private: + vtkFollower(const vtkFollower&); // Not implemented. + void operator=(const vtkFollower&); // Not implemented. +}; + +#endif + + + diff --git a/Rendering/vtkFreeTypeUtilities.cxx b/Rendering/vtkFreeTypeUtilities.cxx new file mode 100644 index 0000000..cf6c63f --- /dev/null +++ b/Rendering/vtkFreeTypeUtilities.cxx @@ -0,0 +1,1622 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFreeTypeUtilities.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkFreeTypeUtilities.h" + +#include "vtkTextProperty.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include "vtkImageData.h" +//#include "vtkDebugLeaks.h" + +// FTGL + +#include "vtkftglConfig.h" +#include "FTLibrary.h" +#include "FTGLPixmapFont.h" + +// The embedded fonts + +#include "fonts/vtkEmbeddedFonts.h" + +#include + +// Print debug info + +#define VTK_FTFC_DEBUG 0 +#define VTK_FTFC_DEBUG_CD 0 + +//---------------------------------------------------------------------------- +vtkCxxRevisionMacro(vtkFreeTypeUtilities, "$Revision: 1.12 $"); +vtkInstantiatorNewMacro(vtkFreeTypeUtilities); + +//---------------------------------------------------------------------------- +// The singleton, and the singleton cleanup + +vtkFreeTypeUtilities* vtkFreeTypeUtilities::Instance = NULL; +vtkFreeTypeUtilitiesCleanup vtkFreeTypeUtilities::Cleanup; + +//---------------------------------------------------------------------------- +// The embedded fonts +// Create a lookup table between the text mapper attributes +// and the font buffers. + +struct EmbeddedFontStruct +{ + size_t length; + unsigned char *ptr; +}; + +//---------------------------------------------------------------------------- +// This callback will be called by the FTGLibrary singleton cleanup destructor +// if it happens to be destroyed before our singleton (this order is not +// deterministic). It will destroy our singleton, if needed. + +void vtkFreeTypeUtilitiesCleanupCallback () +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilitiesCleanupCallback\n"); +#endif + vtkFreeTypeUtilities::SetInstance(NULL); +} + +//---------------------------------------------------------------------------- +// Create the singleton cleanup +// Register our singleton cleanup callback against the FTLibrary so that +// it might be called before the FTLibrary singleton is destroyed. + +vtkFreeTypeUtilitiesCleanup::vtkFreeTypeUtilitiesCleanup() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilitiesCleanup::vtkFreeTypeUtilitiesCleanup\n"); +#endif + FTLibraryCleanup::AddDependency(&vtkFreeTypeUtilitiesCleanupCallback); +} + +//---------------------------------------------------------------------------- +// Delete the singleton cleanup +// The callback called here might have been called by the FTLibrary singleton +// cleanup first (depending on the destruction order), but in case ours is +// destroyed first, let's call it too. + +vtkFreeTypeUtilitiesCleanup::~vtkFreeTypeUtilitiesCleanup() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilitiesCleanup::~vtkFreeTypeUtilitiesCleanup\n"); +#endif + vtkFreeTypeUtilitiesCleanupCallback(); +} + +//---------------------------------------------------------------------------- +vtkFreeTypeUtilities* vtkFreeTypeUtilities::GetInstance() +{ + if (!vtkFreeTypeUtilities::Instance) + { + vtkFreeTypeUtilities::Instance = (vtkFreeTypeUtilities*) + vtkObjectFactory::CreateInstance("vtkFreeTypeUtilities"); + if (!vtkFreeTypeUtilities::Instance) + { +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass("vtkFreeTypeUtilities"); +#endif + vtkFreeTypeUtilities::Instance = new vtkFreeTypeUtilities; + } + } + return vtkFreeTypeUtilities::Instance; +} + +//---------------------------------------------------------------------------- +void vtkFreeTypeUtilities::SetInstance(vtkFreeTypeUtilities* instance) +{ + if (vtkFreeTypeUtilities::Instance == instance) + { + return; + } + + if (vtkFreeTypeUtilities::Instance) + { + vtkFreeTypeUtilities::Instance->Delete(); + } + + vtkFreeTypeUtilities::Instance = instance; + + // User will call ->Delete() after setting instance + + if (instance) + { + instance->Register(NULL); + } +} + +//---------------------------------------------------------------------------- +vtkFreeTypeUtilities* vtkFreeTypeUtilities::New() +{ + vtkFreeTypeUtilities* ret = vtkFreeTypeUtilities::GetInstance(); + ret->Register(NULL); + return ret; +} + +//---------------------------------------------------------------------------- +vtkFreeTypeUtilities::vtkFreeTypeUtilities() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::vtkFreeTypeUtilities\n"); +#endif + + this->MaximumNumberOfFaces = 30; // combinations of family+bold+italic + this->MaximumNumberOfSizes = this->MaximumNumberOfFaces * 20; // sizes + this->MaximumNumberOfBytes = 300000UL * this->MaximumNumberOfSizes; + + this->CacheManager = NULL; + this->ImageCache = NULL; + this->CMapCache = NULL; + + this->NumberOfEntries = 0; + this->InitializeCache(); +} + +//---------------------------------------------------------------------------- +vtkFreeTypeUtilities::~vtkFreeTypeUtilities() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::~vtkFreeTypeUtilities\n"); +#endif + + this->ReleaseCache(); + this->ReleaseCacheManager(); +} + +//---------------------------------------------------------------------------- +FT_Library* vtkFreeTypeUtilities::GetLibrary() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::GetLibrary\n"); +#endif + + FTLibrary *ftgl_lib = FTLibrary::GetInstance(); + if (ftgl_lib) + { + return ftgl_lib->GetLibrary(); + } + + return NULL; +} + +//---------------------------------------------------------------------------- +FTC_Manager* vtkFreeTypeUtilities::GetCacheManager() +{ + if (!this->CacheManager) + { + this->InitializeCacheManager(); + } + + return this->CacheManager; +} + +//---------------------------------------------------------------------------- +FTC_ImageCache* vtkFreeTypeUtilities::GetImageCache() +{ + if (!this->ImageCache) + { + this->InitializeCacheManager(); + } + + return this->ImageCache; +} + +//---------------------------------------------------------------------------- +FTC_CMapCache* vtkFreeTypeUtilities::GetCMapCache() +{ + if (!this->CMapCache) + { + this->InitializeCacheManager(); + } + + return this->CMapCache; +} + +//---------------------------------------------------------------------------- +void vtkFreeTypeUtilities::MapTextPropertyToId(vtkTextProperty *tprop, + unsigned long *id) +{ + if (!tprop || !id) + { + vtkErrorMacro(<< "Wrong parameters, one of them is NULL"); + return; + } + + // Set the first bit to avoid id = 0 + // (the id will be mapped to a pointer, FTC_FaceID, so let's avoid NULL) + + *id = 1; + int bits = 1; + + // The font family is in 4 bits (= 5 bits so far) + // (2 would be enough right now, but who knows, it might grow) + + int fam = (tprop->GetFontFamily() - tprop->GetFontFamilyMinValue()) << bits; + bits += 4; + + // Bold is in 1 bit (= 6 bits so far) + + int bold = (tprop->GetBold() ? 1 : 0) << bits; + bits++; + + // Italic is in 1 bit (= 7 bits so far) + + int italic = (tprop->GetItalic() ? 1 : 0) << bits; + bits++; + + // Orientation (in degrees) + // We need 9 bits for 0 to 360. What do we need for more precisions: + // - 1/10th degree: 12 bits (11.8) + + int angle = (vtkMath::Round(tprop->GetOrientation() * 10.0) % 3600) << bits; + + // We really should not use more than 32 bits + + // Now final id + + *id |= fam | bold | italic | angle; +} + +//---------------------------------------------------------------------------- +void vtkFreeTypeUtilities::MapIdToTextProperty(unsigned long id, + vtkTextProperty *tprop) +{ + if (!tprop) + { + vtkErrorMacro(<< "Wrong parameters, one of them is NULL"); + return; + } + + // The first was set to avoid id = 0 + + int bits = 1; + + // The font family is in 4 bits + // (2 would be enough right now, but who knows, it might grow) + + int fam = id >> bits; + bits += 4; + tprop->SetFontFamily((fam & ((1 << 4) - 1))+ tprop->GetFontFamilyMinValue()); + + // Bold is in 1 bit + + int bold = id >> bits; + bits++; + tprop->SetBold(bold & 0x1); + + // Italic is in 1 bit + + int italic = id >> bits; + bits++; + tprop->SetItalic(italic & 0x1); + + // Orientation (in degrees) + // We need 9 bits for 0 to 360. What do we need for more precisions: + // - 1/10th degree: 12 bits (11.8) + + int angle = id >> bits; + tprop->SetOrientation((float)(angle & ((1 << 12) - 1)) / 10.0); + + // We really should not use more than 32 bits +} + +//---------------------------------------------------------------------------- +FT_CALLBACK_DEF(FT_Error) +vtkFreeTypeUtilitiesFaceRequester(FTC_FaceID face_id, + FT_Library lib, + FT_Pointer request_data, + FT_Face* face) +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilitiesFaceRequester()\n"); +#endif + + FT_UNUSED(request_data); + + vtkFreeTypeUtilities *self = + reinterpret_cast(request_data); + + // Map the ID to a text property + + vtkTextProperty *tprop = vtkTextProperty::New(); + self->MapIdToTextProperty(reinterpret_cast(face_id), tprop); + + // Fonts, organized by [Family][Bold][Italic] + + static EmbeddedFontStruct EmbeddedFonts[3][2][2] = + { + { + { + { // VTK_ARIAL: Bold [ ] Italic [ ] + + face_arial_buffer_length, face_arial_buffer + }, + { // VTK_ARIAL: Bold [ ] Italic [x] + face_arial_italic_buffer_length, face_arial_italic_buffer + } + }, + { + { // VTK_ARIAL: Bold [x] Italic [ ] + face_arial_bold_buffer_length, face_arial_bold_buffer + }, + { // VTK_ARIAL: Bold [x] Italic [x] + face_arial_bold_italic_buffer_length, face_arial_bold_italic_buffer + } + } + }, + { + { + { // VTK_COURIER: Bold [ ] Italic [ ] + face_courier_buffer_length, face_courier_buffer + }, + { // VTK_COURIER: Bold [ ] Italic [x] + face_courier_italic_buffer_length, face_courier_italic_buffer + } + }, + { + { // VTK_COURIER: Bold [x] Italic [ ] + face_courier_bold_buffer_length, face_courier_bold_buffer + }, + { // VTK_COURIER: Bold [x] Italic [x] + face_courier_bold_italic_buffer_length, + face_courier_bold_italic_buffer + } + } + }, + { + { + { // VTK_TIMES: Bold [ ] Italic [ ] + face_times_buffer_length, face_times_buffer + }, + { // VTK_TIMES: Bold [ ] Italic [x] + face_times_italic_buffer_length, face_times_italic_buffer + } + }, + { + { // VTK_TIMES: Bold [x] Italic [ ] + face_times_bold_buffer_length, face_times_bold_buffer + }, + { // VTK_TIMES: Bold [x] Italic [x] + face_times_bold_italic_buffer_length, face_times_bold_italic_buffer + } + } + } + }; + + FT_Long length = EmbeddedFonts + [tprop->GetFontFamily()][tprop->GetBold()][tprop->GetItalic()].length; + FT_Byte *ptr = EmbeddedFonts + [tprop->GetFontFamily()][tprop->GetBold()][tprop->GetItalic()].ptr; + + // Create a new face + + FT_Error error = FT_New_Memory_Face(lib, ptr, length, 0, face); + if (error) + { + vtkErrorWithObjectMacro( + tprop, + << "Unable to create font !" << " (family: " << tprop->GetFontFamily() + << ", bold: " << tprop->GetBold() << ", italic: " << tprop->GetItalic() + << ", length: " << length << ")"); + } + else + { +#if VTK_FTFC_DEBUG + cout << "Requested: " << *face + << " (F: " << tprop->GetFontFamily() + << ", B: " << tprop->GetBold() + << ", I: " << tprop->GetItalic() + << ", O: " << tprop->GetOrientation() << ")" << endl; +#endif + if (tprop->GetOrientation() != 0.0) + { + // FreeType documentation says that the transform should not be set + // but we cache faces also by transform, so that there is a unique + // (face, orientation) cache entry + + FT_Matrix matrix; + float angle = vtkMath::DegreesToRadians() * tprop->GetOrientation(); + matrix.xx = (FT_Fixed)( cos(angle) * 0x10000L); + matrix.xy = (FT_Fixed)(-sin(angle) * 0x10000L); + matrix.yx = (FT_Fixed)( sin(angle) * 0x10000L); + matrix.yy = (FT_Fixed)( cos(angle) * 0x10000L); + FT_Set_Transform(*face, &matrix, NULL); + } + } + + tprop->Delete(); + + return error; +} + +//---------------------------------------------------------------------------- +void vtkFreeTypeUtilities::InitializeCacheManager() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::InitializeCacheManager()\n"); +#endif + + this->ReleaseCacheManager(); + + FT_Error error; + + // Create the cache manager itself + + this->CacheManager = new FTC_Manager; + + error = FTC_Manager_New(*this->GetLibrary(), + this->MaximumNumberOfFaces, + this->MaximumNumberOfSizes, + this->MaximumNumberOfBytes, + vtkFreeTypeUtilitiesFaceRequester, + (FT_Pointer)this, + this->CacheManager); + + if (error) + { + vtkErrorMacro(<< "Failed allocating a new FreeType Cache Manager"); + } + + // The image cache + + this->ImageCache = new FTC_ImageCache; + + error = FTC_ImageCache_New(*this->CacheManager, this->ImageCache); + + if (error) + { + vtkErrorMacro(<< "Failed allocating a new FreeType Image Cache"); + } + + // The charmap cache + + this->CMapCache = new FTC_CMapCache; + + error = FTC_CMapCache_New(*this->CacheManager, this->CMapCache); + + if (error) + { + vtkErrorMacro(<< "Failed allocating a new FreeType CMap Cache"); + } +} + +//---------------------------------------------------------------------------- +void vtkFreeTypeUtilities::ReleaseCacheManager() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::ReleaseCacheManager()\n"); +#endif + + if (this->CacheManager) + { + FTC_Manager_Done(*this->CacheManager); + + delete this->CacheManager; + this->CacheManager = NULL; + } + + if (this->ImageCache) + { + delete this->ImageCache; + this->ImageCache = NULL; + } + + if (this->CMapCache) + { + delete this->CMapCache; + this->CMapCache = NULL; + } +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetSize(unsigned long tprop_cache_id, + int font_size, + FT_Size *size) +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::GetSize()\n"); +#endif + + if (!size || font_size <= 0) + { + vtkErrorMacro(<< "Wrong parameters, size is NULL or invalid font size"); + return 0; + } + + FTC_Manager *manager = this->GetCacheManager(); + if (!manager) + { + vtkErrorMacro(<< "Failed querying the cache manager !"); + return 0; + } + + // Map the id of a text property in the cache to a FTC_FaceID + +#if (FREETYPE_MAJOR >=2 && FREETYPE_MINOR >= 1 && FREETYPE_PATCH >= 9) + FTC_FaceID face_id = reinterpret_cast(tprop_cache_id); + + FTC_ScalerRec scaler_rec; + scaler_rec.face_id = face_id; + scaler_rec.width = font_size; + scaler_rec.height = font_size; + scaler_rec.pixel = 1; + + FT_Error error = FTC_Manager_LookupSize(*manager, &scaler_rec, size); + if (error) + { + vtkErrorMacro(<< "Failed looking up a FreeType Size"); + } + + return error ? 0 : 1; +#else + return 0; +#endif +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetSize(vtkTextProperty *tprop, + FT_Size *size) +{ + if (!tprop) + { + vtkErrorMacro(<< "Wrong parameters, text property is NULL"); + return 0; + } + + // Map the text property to a unique id that will be used as face id + + unsigned long tprop_cache_id; + this->MapTextPropertyToId(tprop, &tprop_cache_id); + + return this->GetSize(tprop_cache_id, tprop->GetFontSize(), size); +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetFace(unsigned long tprop_cache_id, + FT_Face *face) +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::GetFace()\n"); +#endif + + if (!face) + { + vtkErrorMacro(<< "Wrong parameters, face is NULL"); + return 0; + } + + FTC_Manager *manager = this->GetCacheManager(); + if (!manager) + { + vtkErrorMacro(<< "Failed querying the cache manager !"); + return 0; + } + + // Map the id of a text property in the cache to a FTC_FaceID + + FTC_FaceID face_id = reinterpret_cast(tprop_cache_id); + + FT_Error error = FTC_Manager_LookupFace(*manager, face_id, face); + if (error) + { + vtkErrorMacro(<< "Failed looking up a FreeType Face"); + } + + return error ? 0 : 1; +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetFace(vtkTextProperty *tprop, + FT_Face *face) +{ + if (!tprop) + { + vtkErrorMacro(<< "Wrong parameters, face is NULL"); + return 0; + } + + // Map the text property to a unique id that will be used as face id + + unsigned long tprop_cache_id; + this->MapTextPropertyToId(tprop, &tprop_cache_id); + + return this->GetFace(tprop_cache_id, face); +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetGlyphIndex(unsigned long tprop_cache_id, + char c, + FT_UInt *gindex) +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::GetGlyphIndex()\n"); +#endif + + if (!gindex) + { + vtkErrorMacro(<< "Wrong parameters, gindex is NULL"); + return 0; + } + + FTC_CMapCache *cmap_cache = this->GetCMapCache(); + if (!cmap_cache) + { + vtkErrorMacro(<< "Failed querying the charmap cache manager !"); + return 0; + } + + // Map the id of a text property in the cache to a FTC_FaceID + + FTC_FaceID face_id = reinterpret_cast(tprop_cache_id); + + // Lookup the glyph index + +#if (FREETYPE_MAJOR >=2 && FREETYPE_MINOR >= 1 && FREETYPE_PATCH >= 9) + *gindex = FTC_CMapCache_Lookup(*cmap_cache, face_id, 0, c); + + return *gindex ? 1 : 0; +#else + return 0; +#endif +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetGlyphIndex(vtkTextProperty *tprop, + char c, + FT_UInt *gindex) +{ + if (!tprop) + { + vtkErrorMacro(<< "Wrong parameters, text property is NULL"); + return 0; + } + + // Map the text property to a unique id that will be used as face id + + unsigned long tprop_cache_id; + this->MapTextPropertyToId(tprop, &tprop_cache_id); + + return this->GetGlyphIndex(tprop_cache_id, c, gindex); +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetGlyph(unsigned long tprop_cache_id, + int font_size, + FT_UInt gindex, + FT_Glyph *glyph, + int request) +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::GetGlyph()\n"); +#endif + + if (!glyph) + { + vtkErrorMacro(<< "Wrong parameters, one of them is NULL"); + return 0; + } + + FTC_ImageCache *image_cache = this->GetImageCache(); + if (!image_cache) + { + vtkErrorMacro(<< "Failed querying the image cache manager !"); + return 0; + } + + // Map the id of a text property in the cache to a FTC_FaceID + + FTC_FaceID face_id = reinterpret_cast(tprop_cache_id); + + // Which font are we looking for + +#if (FREETYPE_MAJOR >=2 && FREETYPE_MINOR >= 1 && FREETYPE_PATCH >= 9) + FTC_ImageTypeRec image_type_rec; + image_type_rec.face_id = face_id; + image_type_rec.width = font_size; + image_type_rec.height = font_size; + image_type_rec.flags = FT_LOAD_DEFAULT; + if (request == GLYPH_REQUEST_BITMAP) + { + image_type_rec.flags |= FT_LOAD_RENDER; + } + else if (request == GLYPH_REQUEST_OUTLINE) + { + image_type_rec.flags |= FT_LOAD_NO_BITMAP; + } + + // Lookup the glyph + + FT_Error error = FTC_ImageCache_Lookup( + *image_cache, &image_type_rec, gindex, glyph, NULL); + + return error ? 0 : 1; +#else + return 0; +#endif +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetGlyph(vtkTextProperty *tprop, + char c, + FT_Glyph *glyph, + int request) +{ + if (!tprop) + { + vtkErrorMacro(<< "Wrong parameters, text property is NULL"); + return 0; + } + + // Map the text property to a unique id that will be used as face id + + unsigned long tprop_cache_id; + this->MapTextPropertyToId(tprop, &tprop_cache_id); + + // Get the character/glyph index + + FT_UInt gindex; + if (!this->GetGlyphIndex(tprop_cache_id, c, &gindex)) + { + vtkErrorMacro(<< "Failed querying a glyph index"); + return 0; + } + + // Get the glyph + + return this->GetGlyph( + tprop_cache_id, tprop->GetFontSize(), gindex, glyph, request); +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::IsBoundingBoxValid(int bbox[4]) +{ + return (!bbox || + bbox[0] == VTK_INT_MAX || bbox[1] == VTK_INT_MIN || + bbox[2] == VTK_INT_MAX || bbox[3] == VTK_INT_MIN) ? 0 : 1; +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::GetBoundingBox(vtkTextProperty *tprop, + const char *str, + int bbox[4]) +{ + // We need the tprop and bbox + + if (!tprop || !bbox) + { + vtkErrorMacro(<< "Wrong parameters, one of them is NULL or zero"); + return 0; + } + + // Initialize bbox to some large values + + bbox[0] = bbox[2] = VTK_INT_MAX; + bbox[1] = bbox[3] = VTK_INT_MIN; + + // No string to render, bail out now + + if (!str) + { + return 1; + } + + // Map the text property to a unique id that will be used as face id + + unsigned long tprop_cache_id; + this->MapTextPropertyToId(tprop, &tprop_cache_id); + + // Get the face + + FT_Face face; + if (!this->GetFace(tprop_cache_id, &face)) + { + vtkErrorMacro(<< "Failed retrieving the face"); + return 0; + } + + int face_has_kerning = FT_HAS_KERNING(face); + + // Iterate char by char + + FT_Glyph glyph; + FT_BitmapGlyph bitmap_glyph; + FT_Bitmap *bitmap; + FT_UInt gindex, previous_gindex = 0; + FT_Vector kerning_delta; + + int x = 0, y = 0; + + for (; *str; str++) + { + // Get the glyph index + + if (!this->GetGlyphIndex(tprop_cache_id, *str, &gindex)) + { + continue; + } + + // Get the glyph as a bitmap + + if (!this->GetGlyph(tprop_cache_id, + tprop->GetFontSize(), + gindex, + &glyph, + vtkFreeTypeUtilities::GLYPH_REQUEST_BITMAP) || + glyph->format != FT_GLYPH_FORMAT_BITMAP) + { + continue; + } + + bitmap_glyph = reinterpret_cast(glyph); + bitmap = &bitmap_glyph->bitmap; + + if (bitmap->width && bitmap->rows) + { + // Starting position given the bearings + + // Substract 1 to the bearing Y, because this is the vertical distance + // from the glyph origin (0,0) to the topmost pixel of the glyph bitmap + // (more precisely, to the pixel just above the bitmap). This distance is + // expressed in integer pixels, and is positive for upwards y. + + int pen_x = x + bitmap_glyph->left; + int pen_y = y + bitmap_glyph->top - 1; + + // Add the kerning + + if (face_has_kerning && previous_gindex && gindex) + { + FT_Get_Kerning( + face, previous_gindex, gindex, FT_KERNING_DEFAULT, &kerning_delta); + pen_x += kerning_delta.x >> 6; + pen_y += kerning_delta.y >> 6; + } + + previous_gindex = gindex; + + // Update bounding box + + if (pen_x < bbox[0]) + { + bbox[0] = pen_x; + } + if (pen_x > bbox[1]) + { + bbox[1] = pen_x; + } + if (pen_y < bbox[2]) + { + bbox[2] = pen_y; + } + if (pen_y > bbox[3]) + { + bbox[3] = pen_y; + } + + pen_x += (bitmap->width - 1); + pen_y -= (bitmap->rows - 1); + + if (pen_x < bbox[0]) + { + bbox[0] = pen_x; + } + if (pen_x > bbox[1]) + { + bbox[1] = pen_x; + } + if (pen_y < bbox[2]) + { + bbox[2] = pen_y; + } + if (pen_y > bbox[3]) + { + bbox[3] = pen_y; + } + } + + // Advance to next char + + x += (bitmap_glyph->root.advance.x + 0x8000) >> 16; + y += (bitmap_glyph->root.advance.y + 0x8000) >> 16; + } + + // Margin for shadow (x + 1, y - 1) + + if (tprop->GetShadow() && this->IsBoundingBoxValid(bbox)) + { + bbox[1]++; + bbox[2]--; + } + + return 1; +} + +//---------------------------------------------------------------------------- +template +int vtkFreeTypeUtilitiesRenderString( + vtkFreeTypeUtilities *self, + vtkTextProperty *tprop, + const char *str, + int x, int y, + vtkImageData *data, + T *vtkNotUsed(ptr), + int use_shadow_color) +{ + // Map the text property to a unique id that will be used as face id + + unsigned long tprop_cache_id; + self->MapTextPropertyToId(tprop, &tprop_cache_id); + + // Get the face + + FT_Face face; + if (!self->GetFace(tprop_cache_id, &face)) + { + vtkErrorWithObjectMacro(self, << "Failed retrieving the face"); + return 0; + } + + int face_has_kerning = FT_HAS_KERNING(face); + + // Text property size and opacity + + int tprop_font_size = tprop->GetFontSize(); + + float tprop_opacity = tprop->GetOpacity(); + + // Text color (get the shadow color if we are actually drawing the shadow) + // Also compute the luminance, if we are drawing to a grayscale image + + double color[3]; + if (use_shadow_color) + { + tprop->GetShadowColor(color); + } + else + { + tprop->GetColor(color); + } + float tprop_r = color[0]; + float tprop_g = color[1]; + float tprop_b = color[2]; + + float tprop_l = 0.3 * tprop_r + 0.59 * tprop_g + 0.11 * tprop_b; + + // Image params (comps, increments, range) + + int data_nb_comp = data->GetNumberOfScalarComponents(); + + vtkIdType data_inc_x, data_inc_y, data_inc_z; + data->GetIncrements(data_inc_x, data_inc_y, data_inc_z); + + double data_min, data_max; + if (data->GetScalarType() == VTK_DOUBLE || + data->GetScalarType() == VTK_FLOAT) + { + data_min = 0.0; + data_max = 1.0; + } + else + { + data_min = data->GetScalarTypeMin(); + data_max = data->GetScalarTypeMax(); + } + double data_range = (data_max - data_min); + + // Render char by char + + FT_Glyph glyph; + FT_BitmapGlyph bitmap_glyph; + FT_Bitmap *bitmap; + FT_UInt gindex, previous_gindex = 0; + FT_Vector kerning_delta; + + for (; *str; str++) + { + // Get the glyph index + + if (!self->GetGlyphIndex(tprop_cache_id, *str, &gindex)) + { + continue; + } + + // Get the glyph as a bitmap + + if (!self->GetGlyph(tprop_cache_id, + tprop_font_size, + gindex, + &glyph, + vtkFreeTypeUtilities::GLYPH_REQUEST_BITMAP) || + glyph->format != FT_GLYPH_FORMAT_BITMAP) + { + continue; + } + + bitmap_glyph = reinterpret_cast(glyph); + bitmap = &bitmap_glyph->bitmap; + + if (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY) + { + continue; + } + + if (bitmap->width && bitmap->rows) + { + // Starting position given the bearings + + // Substract 1 to the bearing Y, because this is the vertical distance + // from the glyph origin (0,0) to the topmost pixel of the glyph bitmap + // (more precisely, to the pixel just above the bitmap). This distance is + // expressed in integer pixels, and is positive for upwards y. + +#if VTK_FTFC_DEBUG + cout << *str << ", orient: " << tprop->GetOrientation() << ", x: " << x << ", y: " << y << ", left: " << bitmap_glyph->left << ", top: " << bitmap_glyph->top << ", width: " << bitmap->width << ", rows: " << bitmap->rows << endl; +#endif + + int pen_x = x + bitmap_glyph->left; + int pen_y = y + bitmap_glyph->top - 1; + + // Add the kerning + + if (face_has_kerning && previous_gindex && gindex) + { + FT_Get_Kerning( + face, previous_gindex, gindex, FT_KERNING_DEFAULT, &kerning_delta); + pen_x += kerning_delta.x >> 6; + pen_y += kerning_delta.y >> 6; + } + + previous_gindex = gindex; + + // Render + + T *data_ptr = (T*)data->GetScalarPointer(pen_x, pen_y, 0); + + int data_pitch = (-data->GetDimensions()[0] - bitmap->width) * data_inc_x; + + unsigned char *glyph_ptr_row = bitmap->buffer; + unsigned char *glyph_ptr; + + float t_alpha, t_1_m_alpha, data_alpha; + + int i, j; + for (j = 0; j < bitmap->rows; j++) + { + glyph_ptr = glyph_ptr_row; + + // That loop should probably be located inside the switch for efficency + + for (i = 0; i < bitmap->width; i++) + { + t_alpha = tprop_opacity * (*glyph_ptr / 255.0); + t_1_m_alpha = 1.0 - t_alpha; + + switch (data_nb_comp) + { + // L + + case 1: + *data_ptr = (T)( + (data_min + data_range * tprop_l * t_alpha) + + *data_ptr * t_1_m_alpha); + glyph_ptr++; + data_ptr++; + break; + + // L,A + // TOFIX: that code is so wrong (alpha) + + case 2: + data_alpha = (data_ptr[1] - data_min) / data_range; + *data_ptr = (T)( + (data_min + data_range * tprop_l * t_alpha) + + (*data_ptr * data_alpha) * t_1_m_alpha); + data_ptr++; + *data_ptr = (T)( + data_min + data_range * (t_alpha + data_alpha * t_1_m_alpha)); + data_ptr++; + glyph_ptr++; + break; + + // RGB + + case 3: + *data_ptr = (T)( + (data_min + data_range * tprop_r * t_alpha) + + *data_ptr * t_1_m_alpha); + data_ptr++; + *data_ptr = (T)( + (data_min + data_range * tprop_g * t_alpha) + + *data_ptr * t_1_m_alpha); + data_ptr++; + *data_ptr = (T)( + (data_min + data_range * tprop_b * t_alpha) + + *data_ptr * t_1_m_alpha); + data_ptr++; + glyph_ptr++; + break; + + // RGB,A + // TOFIX: that code is so wrong (alpha) + + case 4: + data_alpha = (data_ptr[1] - data_min) / data_range; + *data_ptr = (T)( + (data_min + data_range * tprop_r * t_alpha) + + (*data_ptr * data_alpha) * t_1_m_alpha); + data_ptr++; + *data_ptr = (T)( + (data_min + data_range * tprop_g * t_alpha) + + (*data_ptr * data_alpha) * t_1_m_alpha); + data_ptr++; + *data_ptr = (T)( + (data_min + data_range * tprop_b * t_alpha) + + (*data_ptr * data_alpha) * t_1_m_alpha); + data_ptr++; + *data_ptr = (T)( + data_min + data_range * (t_alpha + data_alpha * t_1_m_alpha)); + data_ptr++; + glyph_ptr++; + break; + } + } + glyph_ptr_row += bitmap->pitch; + data_ptr += data_pitch; + } + } + + // Advance to next char + + x += (bitmap_glyph->root.advance.x + 0x8000) >> 16; + y += (bitmap_glyph->root.advance.y + 0x8000) >> 16; + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkFreeTypeUtilities::RenderString(vtkTextProperty *tprop, + const char *str, + int x, int y, + vtkImageData *data) +{ + // Check + + if (!tprop || !str || !data) + { + vtkErrorMacro(<< "Wrong parameters, one of them is NULL or zero"); + return 0; + } + + if (data->GetNumberOfScalarComponents() > 4) + { + vtkErrorMacro("The image data must have a maximum of four components"); + return 0; + } + + // Execute shadow + + int res = 1; + + if (tprop->GetShadow()) + { + switch (data->GetScalarType()) + { + vtkTemplateMacro(res &= vtkFreeTypeUtilitiesRenderString( + this, + tprop, + str, + x + 1, y - 1, + data, + (VTK_TT *)(NULL), + 1)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 0; + } + } + + // Execute text + + switch (data->GetScalarType()) + { + vtkTemplateMacro(res &= vtkFreeTypeUtilitiesRenderString( + this, + tprop, + str, + x, y, + data, + (VTK_TT *)(NULL), + 0)); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return 0; + } + + return res; +} + +//---------------------------------------------------------------------------- +void vtkFreeTypeUtilities::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "MaximumNumberOfFaces: " + << this->MaximumNumberOfFaces << endl; + + os << indent << "MaximumNumberOfSizes: " + << this->MaximumNumberOfSizes << endl; + + os << indent << "MaximumNumberOfBytes: " + << this->MaximumNumberOfBytes << endl; +} + +//---------------------------------------------------------------------------- +// Print entry + +void vtkFreeTypeUtilities::PrintEntry(int i, char *msg) +{ + if (!this->Entries[i]) + { + return; + } + + printf("%s: [%2d] =", msg, i); + + vtkTextProperty *tprop = this->Entries[i]->TextProperty; + if (tprop) + { + printf(" [S: %2d]", tprop->GetFontSize()); + + double *color = tprop->GetColor(); + if (color) + { + printf(" [RGBA: %.2f/%.2f/%.2f (%.2f)]", + color[0], color[1], color[2], tprop->GetOpacity()); + } + + /* + if (tprop->GetFaceFileName()) + { + printf(" [F: %s]", tprop->GetFaceFileName()); + } + else + */ + { + printf(" [F: %d] [I: %d] [B: %d]", + tprop->GetFontFamily(), tprop->GetItalic(), tprop->GetBold()); + } + } + + if (this->Entries[i]->Font) + { + printf(" [F: %p]", (void*)this->Entries[i]->Font); + printf("\n [f: %p]", + (void*)*(this->Entries[i]->Font->Face()->Face())); + } + + printf("\n"); + fflush(stdout); +} + +//---------------------------------------------------------------------------- +// Release entry + +void vtkFreeTypeUtilities::ReleaseEntry(int i) +{ + if (!this->Entries[i]) + { + return; + } + +#if VTK_FTFC_DEBUG + this->PrintEntry(this->NumberOfEntries, "Rl"); +#endif + + if (this->Entries[i]->TextProperty) + { + this->Entries[i]->TextProperty->Delete(); + this->Entries[i]->TextProperty = NULL; + } + + if (this->Entries[i]->Font) + { + delete this->Entries[i]->Font; + this->Entries[i]->Font = NULL; + } + + delete this->Entries[i]; + this->Entries[i] = NULL; +} + +//---------------------------------------------------------------------------- +// Initialize cache + +void vtkFreeTypeUtilities::InitializeCache() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::InitializeCache()\n"); +#endif + this->ReleaseCache(); + + int i; + for (i = 0; i < VTK_FTFC_CACHE_CAPACITY; i++) + { + this->Entries[i] = NULL; + } +} + +//---------------------------------------------------------------------------- +// Release cache + +void vtkFreeTypeUtilities::ReleaseCache() +{ +#if VTK_FTFC_DEBUG_CD + printf("vtkFreeTypeUtilities::ReleaseCache()\n"); +#endif + + int i; + for (i = 0; i < this->NumberOfEntries; i++) + { +#if VTK_FTFC_DEBUG + this->PrintEntry(i, "Rl"); +#endif + this->ReleaseEntry(i); + } + + this->NumberOfEntries = 0; +} + +//---------------------------------------------------------------------------- +// Get a font from the cache given the text property. If no font is +// found in the cache, one is created and stored with the given color +// parameters. If override_color is true, then red, green, blue are used as +// text color instead of the colors found in the vtkTextProperty. + +vtkFreeTypeUtilities::Entry* +vtkFreeTypeUtilities::GetFont(vtkTextProperty *tprop, + double override_color[3]) +{ + int i, j; + + // Get the requested color and opacity + + double tprop_color[3]; + for (i = 0; i < 3; i++) + { + tprop_color[i] = override_color ? override_color[i] : tprop->GetColor()[i]; + if (tprop_color[i] < 0.0) + { + tprop_color[i] = 0.0; + } + } + + float tprop_opacity = + (tprop->GetOpacity() < 0.0) ? 1.0 : tprop->GetOpacity(); + + // Has the font been cached ? + + for (i = 0; i < this->NumberOfEntries; i++) + { + vtkTextProperty *entry_tprop = this->Entries[i]->TextProperty; + double *entry_tprop_color = entry_tprop->GetColor(); + + if ( + // If a face file name has been specified, it overrides the + // font family as well as italic and bold attributes + + (( + /* + !entry_tprop->GetFaceFileName() && !tprop->GetFaceFileName() && + */ + entry_tprop->GetFontFamily() == tprop->GetFontFamily() && + entry_tprop->GetItalic() == tprop->GetItalic() && + entry_tprop->GetBold() == tprop->GetBold()) + /* + || (entry_tprop->GetFaceFileName() && tprop->GetFaceFileName() && + !strcmp(entry_tprop->GetFaceFileName(), tprop->GetFaceFileName())) + */ + ) + + && (entry_tprop_color[0] == tprop_color[0] && + entry_tprop_color[1] == tprop_color[1] && + entry_tprop_color[2] == tprop_color[2] && + entry_tprop->GetOpacity() == tprop_opacity) + + && entry_tprop->GetFontSize() == tprop->GetFontSize()) + { + // Make this the most recently used + if (i != 0) + { + vtkFreeTypeUtilities::Entry *tmp = this->Entries[i]; + for (j = i - 1; j >= 0; j--) + { + this->Entries[j+1] = this->Entries[j]; + } + this->Entries[0] = tmp; + } + return this->Entries[0]; + } + } + + // OK the font is not cached, try to create one + + FTFont *font = new FTGLPixmapFont; + + // A face file name has been provided, try to load it, otherwise + // just use the embedded fonts (i.e. font family, bold and italic attribs) + + /* + if (tprop->GetFaceFileName()) + { + if (!font->Open(tprop->GetFaceFileName(), false)) + { + vtkErrorWithObjectMacro( + tprop, + << "Unable to load font " << tprop->GetFaceFileName()); + delete font; + return 0; + } + + // Try to load an AFM metrics file for the PFB/PFA Postscript fonts + + int length = strlen(tprop->GetFaceFileName()); + if (length > 4 && + (!strcmp(tprop->GetFaceFileName() + length - 4, ".pfb") || + !strcmp(tprop->GetFaceFileName() + length - 4, ".pfa"))) + { + char *metrics = new char[length + 1]; + strncpy(metrics, tprop->GetFaceFileName(), length - 3); + strcpy(metrics + length - 3, "afm"); + struct stat fs; + if (stat(metrics, &fs) == 0) + { + font->Attach(metrics); + } + delete [] metrics; + } + } + else + */ + { + // Fonts, organized by [Family][Bold][Italic] + + static EmbeddedFontStruct EmbeddedFonts[3][2][2] = + { + { + { + { // VTK_ARIAL: Bold [ ] Italic [ ] + + face_arial_buffer_length, face_arial_buffer + }, + { // VTK_ARIAL: Bold [ ] Italic [x] + face_arial_italic_buffer_length, face_arial_italic_buffer + } + }, + { + { // VTK_ARIAL: Bold [x] Italic [ ] + face_arial_bold_buffer_length, face_arial_bold_buffer + }, + { // VTK_ARIAL: Bold [x] Italic [x] + face_arial_bold_italic_buffer_length, face_arial_bold_italic_buffer + } + } + }, + { + { + { // VTK_COURIER: Bold [ ] Italic [ ] + face_courier_buffer_length, face_courier_buffer + }, + { // VTK_COURIER: Bold [ ] Italic [x] + face_courier_italic_buffer_length, face_courier_italic_buffer + } + }, + { + { // VTK_COURIER: Bold [x] Italic [ ] + face_courier_bold_buffer_length, face_courier_bold_buffer + }, + { // VTK_COURIER: Bold [x] Italic [x] + face_courier_bold_italic_buffer_length, + face_courier_bold_italic_buffer + } + } + }, + { + { + { // VTK_TIMES: Bold [ ] Italic [ ] + face_times_buffer_length, face_times_buffer + }, + { // VTK_TIMES: Bold [ ] Italic [x] + face_times_italic_buffer_length, face_times_italic_buffer + } + }, + { + { // VTK_TIMES: Bold [x] Italic [ ] + face_times_bold_buffer_length, face_times_bold_buffer + }, + { // VTK_TIMES: Bold [x] Italic [x] + face_times_bold_italic_buffer_length, face_times_bold_italic_buffer + } + } + } + }; + + size_t length = EmbeddedFonts + [tprop->GetFontFamily()][tprop->GetBold()][tprop->GetItalic()].length; + unsigned char *ptr = EmbeddedFonts + [tprop->GetFontFamily()][tprop->GetBold()][tprop->GetItalic()].ptr; + + if (!font->Open(ptr, length, false)) + { + vtkErrorWithObjectMacro( + tprop, + << "Unable to create font !" << " (family: " << tprop->GetFontFamily() + << ", bold: " << tprop->GetBold() << ", italic: " << tprop->GetItalic() + << ", length: " << length << ")"); + delete font; + return 0; + } + } + + // Set face size + + font->FaceSize(tprop->GetFontSize()); + + // We need to make room for a new font + + if (this->NumberOfEntries == VTK_FTFC_CACHE_CAPACITY) + { +#if VTK_FTFC_DEBUG + printf("Cache is full, deleting last!\n"); +#endif + this->NumberOfEntries--; + } + + // Add the new font + + if (this->Entries[this->NumberOfEntries]) + { + this->ReleaseEntry(this->NumberOfEntries); + } + this->Entries[this->NumberOfEntries] = new vtkFreeTypeUtilities::Entry; + + // Set the other info + + this->Entries[this->NumberOfEntries]->TextProperty = vtkTextProperty::New(); + + vtkTextProperty *entry_tprop = + this->Entries[this->NumberOfEntries]->TextProperty; + + entry_tprop->ShallowCopy(tprop); + entry_tprop->SetOpacity(tprop_opacity); + entry_tprop->SetColor(tprop_color); + + this->Entries[this->NumberOfEntries]->Font = font; + + this->Entries[this->NumberOfEntries]->LargestAscender = + this->Entries[this->NumberOfEntries]->LargestDescender = -1; + +#if VTK_FTFC_DEBUG + this->PrintEntry(this->NumberOfEntries, "Cr"); +#endif + + vtkFreeTypeUtilities::Entry *tmp = this->Entries[this->NumberOfEntries]; + + this->NumberOfEntries++; + return tmp; +} diff --git a/Rendering/vtkFreeTypeUtilities.h b/Rendering/vtkFreeTypeUtilities.h new file mode 100644 index 0000000..bc0b56c --- /dev/null +++ b/Rendering/vtkFreeTypeUtilities.h @@ -0,0 +1,248 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFreeTypeUtilities.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFreeTypeUtilities - FreeType library support +// .SECTION Description +// vtkFreeTypeUtilities provides low-level interface to the FreeType library, +// including font-cache, rasterizing and vectorizing. Internal use only. +// EXPERIMENTAL for the moment. Also include the old cache. + +#ifndef __vtkFreeTypeUtilities_h +#define __vtkFreeTypeUtilities_h + +#define VTK_FTFC_CACHE_CAPACITY 150 + +#include "vtkObject.h" + +class vtkImageData; +class vtkTextProperty; + +// FreeType + +#include "vtk_freetype.h" //since ft2build.h could be in the path +#include FT_FREETYPE_H +#include FT_CACHE_H +#include FT_CACHE_IMAGE_H +#include FT_CACHE_CHARMAP_H + +// FTGL + +class FTFont; + +//---------------------------------------------------------------------------- +// Singleton cleanup + +class VTK_RENDERING_EXPORT vtkFreeTypeUtilitiesCleanup +{ +public: + vtkFreeTypeUtilitiesCleanup(); + ~vtkFreeTypeUtilitiesCleanup(); +}; + +//---------------------------------------------------------------------------- +// Singleton font cache + +class VTK_RENDERING_EXPORT vtkFreeTypeUtilities : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkFreeTypeUtilities, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This is a singleton pattern New. There will be only ONE reference + // to a vtkFreeTypeUtilities object per process. Clients that + // call this method must use Delete() on the object so that reference + // counting will work. The single instance will be unreferenced when + // the program exits. You should just use the static GetInstance() method + // anyway to get the singleton. + static vtkFreeTypeUtilities *New(); + + // Description: + // Return the singleton instance with no reference counting. + static vtkFreeTypeUtilities* GetInstance(); + + // Description: + // Supply a user defined instance. Call Delete() on the supplied + // instance after setting it to fix the reference count. + static void SetInstance(vtkFreeTypeUtilities *instance); + + // Description: + // Get the FreeType library singleton. + FT_Library* GetLibrary(); + + // Description: + // Set/Get the maximum number of faces (FT_Face), sizes (FT_Size) and + // bytes used by the cache. These settings can be changed as long as + // it is done prior to accessing any of the caches or the cache manager. + vtkSetClampMacro(MaximumNumberOfFaces,unsigned int,1,VTK_UNSIGNED_INT_MAX); + vtkGetMacro(MaximumNumberOfFaces, unsigned int); + vtkSetClampMacro(MaximumNumberOfSizes,unsigned int,1,VTK_UNSIGNED_INT_MAX); + vtkGetMacro(MaximumNumberOfSizes, unsigned int); + vtkSetClampMacro(MaximumNumberOfBytes,unsigned long,1,VTK_UNSIGNED_LONG_MAX); + vtkGetMacro(MaximumNumberOfBytes, unsigned long); + + // Description: + // Get the FreeType cache manager, image cache and charmap cache + FTC_Manager* GetCacheManager(); + FTC_ImageCache* GetImageCache(); + FTC_CMapCache* GetCMapCache(); + + // Description: + // Given a text property, get the corresponding FreeType size object + // (a structure storing both a face and a specific size metric). + // The size setting of the text property is used to set the size's face + // to the corresponding size. + // Return true on success, false otherwise + int GetSize(vtkTextProperty *tprop, FT_Size *size); + + // Description: + // Given a text property, get the corresponding FreeType face. + // The size parameter of the text property is ignored and a face with + // unknown current size is returned. Use GetSize() to get a specific size. + // Return true on success, false otherwise + int GetFace(vtkTextProperty *tprop, FT_Face *face); + + // Description: + // Given a text property and a character, get the corresponding FreeType + // glyph index. + // Return true on success, false otherwise + int GetGlyphIndex(vtkTextProperty *tprop, char c, FT_UInt *gindex); + + // Description: + // Given a text property and a character, get the corresponding FreeType + // glyph. The 'request' parameter can be used to request the glyph to be + // in a specific format. If GLYPH_REQUEST_DEFAULT, the glyph might be either + // an outline (most of the time) or a bitmap if the face includes a set of + // pre-rendered glyphs (called "strikes") for a given size. + // If GLYPH_REQUEST_BITMAP, the glyph is rendered immediately and can + // be safely cast to a FT_BitmapGlyph. If GLYPH_REQUEST_OUTLINE, no + // pre-rendered "strike" is considered, the glyph is an outline and can be + // safely cast to a FT_OutlineGlyph. + // Return true on success, false otherwise + //BTX + enum + { + GLYPH_REQUEST_DEFAULT = 0, + GLYPH_REQUEST_BITMAP = 1, + GLYPH_REQUEST_OUTLINE = 2 + }; + //ETX + int GetGlyph(vtkTextProperty *tprop, + char c, + FT_Glyph *glyph, + int request = GLYPH_REQUEST_DEFAULT); + + // Description: + // Given a text property and a string, get the bounding box [xmin, xmax] x + // [ymin, ymax]. Note that this is the bounding box of the area + // where actual pixels will be written, given a text/pen/baseline location + // of (0,0). + // For example, if the string starts with a 'space', or depending on the + // orientation, you can end up with a [-20, -10] x [5, 10] bbox (the math + // to get the real bbox is straightforward). + // Return 1 on success, 0 otherwise. + // You can use IsBoundingBoxValid() to test if the computed bbox + // is valid (it may not if GetBoundingBox() failed or if the string + // was empty). + int GetBoundingBox(vtkTextProperty *tprop, const char *str, int bbox[4]); + int IsBoundingBoxValid(int bbox[4]); + + // Description: + // Given a text property and a string, render it at coordinates (x, y) in + // an vtkImageData. + // WARNING: writing to a L,A or RGB,A vtkImageData needs to be fixed. + // Also, *no* bounds checking are performed for the moment, i.e. no + // cropping, the text has to fit in the buffer (use GetBoundingBox()). + int RenderString(vtkTextProperty *tprop, + const char *str, + int x, int y, + vtkImageData *data); + + // Description: + // For internal use only. + // Given a text property 'tprop', get its unique ID in our cache framework. + // In the same way, given a unique ID in our cache, retrieve the + // corresponding text property and assign its parameters to 'tprop'. + // Warning: there is no one to one mapping between a single text property + // the corresponding ID, and vice-versa. The ID is just a fast hash, a + // binary mask concatenating the attributes of the text property that are + // relevant to our cache (Color, Opacity, Justification setting are not + // stored). + void MapTextPropertyToId(vtkTextProperty *tprop, unsigned long *tprop_cache_id); + void MapIdToTextProperty(unsigned long tprop_cache_id, vtkTextProperty *tprop); + + // Description: + // For internal use only. + int GetSize(unsigned long tprop_cache_id, int font_size, FT_Size *size); + int GetFace(unsigned long tprop_cache_id, FT_Face *face); + int GetGlyphIndex(unsigned long tprop_cache_id, char c, FT_UInt *gindex); + int GetGlyph(unsigned long tprop_cache_id, + int font_size, + FT_UInt gindex, + FT_Glyph *glyph, + int request = GLYPH_REQUEST_DEFAULT); + + // Old Code + // Cache entry + + struct Entry + { + vtkTextProperty *TextProperty; + FTFont *Font; + float LargestAscender; + float LargestDescender; + }; + + vtkFreeTypeUtilities::Entry* GetFont(vtkTextProperty *tprop, + double override_color[3] = NULL); + +protected: + vtkFreeTypeUtilities(); + virtual ~vtkFreeTypeUtilities(); + +private: + vtkFreeTypeUtilities(const vtkFreeTypeUtilities&); // Not implemented. + void operator=(const vtkFreeTypeUtilities&); // Not implemented. + + // The singleton instance and the singleton cleanup instance + + static vtkFreeTypeUtilities* Instance; + static vtkFreeTypeUtilitiesCleanup Cleanup; + + // The cache manager, image cache and charmap cache + + FTC_Manager *CacheManager; + FTC_ImageCache *ImageCache; + FTC_CMapCache *CMapCache; + + unsigned int MaximumNumberOfFaces; + unsigned int MaximumNumberOfSizes; + unsigned long MaximumNumberOfBytes; + + void InitializeCacheManager(); + void ReleaseCacheManager(); + + // Old Code + + void PrintEntry(int i, char *msg = 0); + void ReleaseEntry(int i); + + void InitializeCache(); + void ReleaseCache(); + + Entry *Entries[VTK_FTFC_CACHE_CAPACITY]; + int NumberOfEntries; +}; + +#endif diff --git a/Rendering/vtkFrustumCoverageCuller.cxx b/Rendering/vtkFrustumCoverageCuller.cxx new file mode 100644 index 0000000..4ab4bb0 --- /dev/null +++ b/Rendering/vtkFrustumCoverageCuller.cxx @@ -0,0 +1,365 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFrustumCoverageCuller.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFrustumCoverageCuller.h" + +#include "vtkCamera.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkProp.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkFrustumCoverageCuller, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkFrustumCoverageCuller); + +// Create a frustum coverage culler with default values +vtkFrustumCoverageCuller::vtkFrustumCoverageCuller() +{ + this->MinimumCoverage = 0.0; + this->MaximumCoverage = 1.0; + this->SortingStyle = VTK_CULLER_SORT_NONE; +} + +// The coverage is computed for each prop, and a resulting allocated +// render time is computed. This is multiplied by the current allocated +// render time of the prop. After this, props with no allocated time are +// removed from the list (and the list length is shortened) to make sure +// that they are not considered again by another culler or for rendering. +double vtkFrustumCoverageCuller::Cull( vtkRenderer *ren, + vtkProp **propList, + int& listLength, + int& initialized ) +{ + vtkProp *prop; + double total_time; + double *bounds, center[3]; + double radius = 0.0; + double planes[24], d; + double coverage, screen_bounds[4]; + double previous_time; + int i, propLoop; + double full_w, full_h, part_w, part_h; + double *allocatedTimeList; + double *distanceList; + int index1, index2; + double tmp; + + // We will create a center distance entry for each prop in the list + // If SortingStyle is set to BackToFront or FrontToBack we will then + // sort the props that have a non-zero AllocatedRenderTime by their + // center distance + distanceList = new double[listLength]; + + // We will return the total time of all props. This is used for + // normalization. + total_time = 0; + + // Get the view frustum planes from the active camera + ren->GetActiveCamera()->GetFrustumPlanes( + ren->GetTiledAspectRatio(), planes ); + + // Keep a list of allocated times to help with sorting / removing + // props later + allocatedTimeList = new double[listLength]; + + // For each prop, compute coverage + for ( propLoop = 0; propLoop < listLength; propLoop++ ) + { + // Get the prop out of the list + prop = propList[propLoop]; + + // If allocated render time has not been initialized yet (if this + // is the first culler, it hasn't) then the previous time is set + // to 0.0 + if ( !initialized ) + { + previous_time = 1.0; + } + else + { + previous_time = prop->GetRenderTimeMultiplier(); + } + + // Get the bounds of the prop and compute an enclosing sphere + bounds = prop->GetBounds(); + + // We start with a coverage of 1.0 and set it to zero if the prop + // is culled during the plane tests + coverage = 1.0; + // make sure the bounds are defined - they won't be for a 2D prop which + // means that they will never be culled. Maybe this should be changed in + // the future? + if (bounds) + { + // a duff dataset like a polydata with no cells will have bad bounds + if (!vtkMath::AreBoundsInitialized(bounds)) + { + coverage = 0.0; + } + else + { + center[0] = (bounds[0] + bounds[1]) / 2.0; + center[1] = (bounds[2] + bounds[3]) / 2.0; + center[2] = (bounds[4] + bounds[5]) / 2.0; + radius = 0.5 * sqrt( (double) + ( bounds[1] - bounds[0] ) * + ( bounds[1] - bounds[0] ) + + ( bounds[3] - bounds[2] ) * + ( bounds[3] - bounds[2] ) + + ( bounds[5] - bounds[4] ) * + ( bounds[5] - bounds[4] ) ); + for ( i = 0; i < 6; i++ ) + { + // Compute how far the center of the sphere is from this plane + d = + planes[i*4 + 0] * center[0] + + planes[i*4 + 1] * center[1] + + planes[i*4 + 2] * center[2] + + planes[i*4 + 3]; + // If d < -radius the prop is not within the view frustum + if ( d < -radius ) + { + coverage = 0.0; + i = 7; + } + // The first four planes are the ones bounding the edges of the + // view plane (the last two are the near and far planes) The + // distance from the edge of the sphere to these planes is stored + // to compute coverage. + if ( i < 4 ) + { + screen_bounds[i] = d - radius; + } + // The fifth plane is the near plane - use the distance to + // the center (d) as the value to sort by + if ( i == 4 ) + { + distanceList[propLoop] = d; + } + } + } + // If the prop wasn't culled during the plane tests... + if ( coverage > 0.0 ) + { + // Compute the width and height of this slice through the + // view frustum that contains the center of the sphere + full_w = screen_bounds[0] + screen_bounds[1] + 2.0 * radius; + full_h = screen_bounds[2] + screen_bounds[3] + 2.0 * radius; + // Subtract from the full width to get the width of the square + // enclosing the circle slice from the sphere in the plane + // through the center of the sphere. If the screen bounds for + // the left and right planes (0,1) are greater than zero, then + // the edge of the sphere was a positive distance away from the + // plane, so there is a gap between the edge of the plane and + // the edge of the box. + part_w = full_w; + if ( screen_bounds[0] > 0.0 ) + { + part_w -= screen_bounds[0]; + } + if ( screen_bounds[1] > 0.0 ) + { + part_w -= screen_bounds[1]; + } + // Do the same thing for the height with the top and bottom + // planes (2,3). + part_h = full_h; + if ( screen_bounds[2] > 0.0 ) + { + part_h -= screen_bounds[2]; + } + if ( screen_bounds[3] > 0.0 ) + { + part_h -= screen_bounds[3]; + } + + // Prevent a single point from being culled if we + // are not culling based on screen coverage + if ( ((full_w*full_h == 0.0) || + (part_w*part_h/(full_w*full_h) <= 0.0)) && this->MinimumCoverage == 0.0 ) + { + coverage = 0.0001; + } + // Compute the fraction of coverage + else if ((full_w * full_h)!=0.0) + { + coverage = (part_w * part_h) / (full_w * full_h); + } + else + { + coverage = 0; + } + // Convert this to an allocated render time - coverage less than + // the minumum result in 0.0 time, greater than the maximum result in + // 1.0 time, and in between a linear ramp is used + if ( coverage < this->MinimumCoverage ) + { + coverage = 0; + } + else if ( coverage > this->MaximumCoverage ) + { + coverage = 1.0; + } + else + { + coverage = (coverage-this->MinimumCoverage) / + this->MaximumCoverage; + } + } + } + // This is a 2D prop - keep them at the beginning of the list in the same + // order they came in (by giving them all the same distance) and set + // the coverage to something small so that they won't get much + // allocated render time (because they aren't LOD it doesn't matter, + // and they generally do draw fast so you don't want to take too much + // time away from the 3D prop because you added a title to your + // window for example) They are put at the beginning of the list so + // that when sorted back to front they will be rendered last. + else + { + distanceList[propLoop] = -VTK_DOUBLE_MAX; + coverage = 0.001; + } + // Multiply the new allocated time by the previous allocated time + coverage *= previous_time; + prop->SetRenderTimeMultiplier( coverage ); + + // Save this in our array of allocated times which matches the + // prop array. Also save the center distance + allocatedTimeList[propLoop] = coverage; + + // Add the time for this prop to the total time + total_time += coverage; + } + + // Now traverse the list from the beginning, swapping any zero entries back + // in the list, while preserving the order of the non-zero entries. This + // requires two indices for the two items we are comparing at any step. + // The second index always moves back by one, but the first index moves back + // by one only when it is pointing to something that has a non-zero value. + index1 = 0; + for ( index2 = 1; index2 < listLength; index2++ ) + { + if ( allocatedTimeList[index1] == 0.0 ) + { + if ( allocatedTimeList[index2] != 0.0 ) + { + allocatedTimeList[index1] = allocatedTimeList[index2]; + distanceList[index1] = distanceList[index2]; + propList[index1] = propList[index2]; + propList[index2] = NULL; + allocatedTimeList[index2] = 0.0; + distanceList[index2] = 0.0; + } + else + { + propList[index1] = propList[index2] = NULL; + allocatedTimeList[index1] = allocatedTimeList[index2] = 0.0; + distanceList[index1] = distanceList[index2] = 0.0; + } + } + if ( allocatedTimeList[index1] != 0.0 ) + { + index1++; + } + } + + // Compute the new list length - index1 is always pointing to the + // first 0.0 entry or the last entry if none were zero (in which case + // we won't change the list length) + listLength = (allocatedTimeList[index1] == 0.0)?(index1):listLength; + + // Now reorder the list if sorting is on + // Do it by a simple bubble sort - there probably aren't that + // many props.... + + if ( this->SortingStyle == VTK_CULLER_SORT_FRONT_TO_BACK ) + { + for ( propLoop = 1; propLoop < listLength; propLoop++ ) + { + index1 = propLoop; + while ( (index1 - 1) >= 0 && + distanceList[index1] < distanceList[index1-1] ) + { + tmp = distanceList[index1-1]; + distanceList[index1-1] = distanceList[index1]; + distanceList[index1] = tmp; + prop = propList[index1-1]; + propList[index1-1] = propList[index1]; + propList[index1] = prop; + index1--; + } + } + } + if ( this->SortingStyle == VTK_CULLER_SORT_BACK_TO_FRONT ) + { + for ( propLoop = 1; propLoop < listLength; propLoop++ ) + { + index1 = propLoop; + while ( (index1 - 1) >= 0 && + distanceList[index1] > distanceList[index1-1] ) + { + tmp = distanceList[index1-1]; + distanceList[index1-1] = distanceList[index1]; + distanceList[index1] = tmp; + prop = propList[index1-1]; + propList[index1-1] = propList[index1]; + propList[index1] = prop; + index1--; + } + } + } + // The allocated render times are now initialized + initialized = 1; + delete [] allocatedTimeList; + delete [] distanceList; + return total_time; +} + +// Description: +// Return the sorting style as a descriptive character string. +const char *vtkFrustumCoverageCuller::GetSortingStyleAsString(void) +{ + if( this->SortingStyle == VTK_CULLER_SORT_NONE ) + { + return "None"; + } + if( this->SortingStyle == VTK_CULLER_SORT_FRONT_TO_BACK ) + { + return "Front To Back"; + } + if( this->SortingStyle == VTK_CULLER_SORT_BACK_TO_FRONT ) + { + return "Back To Front"; + } + else + { + return "Unknown"; + } +} + +void vtkFrustumCoverageCuller::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Minimum Coverage: " + << this->MinimumCoverage << endl; + + os << indent << "Maximum Coverage: " + << this->MaximumCoverage << endl; + + os << indent << "Sorting Style: " + << this->GetSortingStyleAsString() << endl; + +} diff --git a/Rendering/vtkFrustumCoverageCuller.h b/Rendering/vtkFrustumCoverageCuller.h new file mode 100644 index 0000000..7410663 --- /dev/null +++ b/Rendering/vtkFrustumCoverageCuller.h @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFrustumCoverageCuller.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFrustumCoverageCuller - cull props based on frustum coverage +// .SECTION Description +// vtkFrustumCoverageCuller will cull props based on the coverage in +// the view frustum. The coverage is computed by enclosing the prop in +// a bounding sphere, projecting that to the viewing coordinate system, then +// taking a slice through the view frustum at the center of the sphere. This +// results in a circle on the plane slice through the view frustum. This +// circle is enclosed in a squared, and the fraction of the plane slice that +// this square covers is the coverage. This is a number between 0 and 1. +// If the number is less than the MinumumCoverage, the allocated render time +// for that prop is set to zero. If it is greater than the MaximumCoverage, +// the allocated render time is set to 1.0. In between, a linear ramp is used +// to convert coverage into allocated render time. + + +// .SECTION see also +// vtkCuller + +#ifndef __vtkFrustumCoverageCuller_h +#define __vtkFrustumCoverageCuller_h + +#include "vtkCuller.h" + +#define VTK_CULLER_SORT_NONE 0 +#define VTK_CULLER_SORT_FRONT_TO_BACK 1 +#define VTK_CULLER_SORT_BACK_TO_FRONT 2 + +class vtkProp; +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkFrustumCoverageCuller : public vtkCuller +{ +public: + static vtkFrustumCoverageCuller *New(); + vtkTypeRevisionMacro(vtkFrustumCoverageCuller,vtkCuller); + void PrintSelf(ostream& os,vtkIndent indent); + + // Description: + // Set/Get the minimum coverage - props with less coverage than this + // are given no time to render (they are culled) + vtkSetMacro( MinimumCoverage, double ); + vtkGetMacro( MinimumCoverage, double ); + + // Description: + // Set/Get the maximum coverage - props with more coverage than this are + // given an allocated render time of 1.0 (the maximum) + vtkSetMacro( MaximumCoverage, double ); + vtkGetMacro( MaximumCoverage, double ); + + // Description: + // Set the sorting style - none, front-to-back or back-to-front + // The default is none + vtkSetClampMacro( SortingStyle, int, + VTK_CULLER_SORT_NONE, VTK_CULLER_SORT_BACK_TO_FRONT ); + vtkGetMacro(SortingStyle,int); + void SetSortingStyleToNone() + {this->SetSortingStyle(VTK_CULLER_SORT_NONE);}; + void SetSortingStyleToBackToFront() + {this->SetSortingStyle(VTK_CULLER_SORT_BACK_TO_FRONT);}; + void SetSortingStyleToFrontToBack() + {this->SetSortingStyle(VTK_CULLER_SORT_FRONT_TO_BACK);}; + const char *GetSortingStyleAsString(void); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THESE METHODS OUTSIDE OF THE RENDERING PROCESS + // Perform the cull operation + // This method should only be called by vtkRenderer as part of + // the render process + double Cull( vtkRenderer *ren, vtkProp **propList, + int& listLength, int& initialized ); +//ETX + +protected: + vtkFrustumCoverageCuller(); + ~vtkFrustumCoverageCuller() {}; + + double MinimumCoverage; + double MaximumCoverage; + int SortingStyle; +private: + vtkFrustumCoverageCuller(const vtkFrustumCoverageCuller&); // Not implemented. + void operator=(const vtkFrustumCoverageCuller&); // Not implemented. +}; + + +#endif diff --git a/Rendering/vtkGL2PSExporter.cxx b/Rendering/vtkGL2PSExporter.cxx new file mode 100644 index 0000000..e64b5ee --- /dev/null +++ b/Rendering/vtkGL2PSExporter.cxx @@ -0,0 +1,459 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGL2PSExporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkGL2PSExporter.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkRendererCollection.h" +#include "vtkRenderer.h" +#include "vtkActorCollection.h" +#include "vtkActor.h" +#include "vtkActor2DCollection.h" +#include "vtkActor2D.h" +#include "vtkVolumeCollection.h" +#include "vtkVolume.h" +#include "vtkIntArray.h" +#include "gl2ps.h" + + +void _SavePropVisibility(vtkRendererCollection *renCol, + vtkIntArray *volVis, vtkIntArray *actVis, + vtkIntArray *act2dVis) +{ + int nRen = renCol->GetNumberOfItems(); + vtkRenderer *ren; + vtkVolumeCollection *vCol; + vtkActorCollection *aCol; + vtkActor2DCollection *a2Col; + vtkVolume *vol; + vtkActor *act; + vtkActor2D *act2d; + int j; + + volVis->SetNumberOfComponents(nRen); + actVis->SetNumberOfComponents(nRen); + act2dVis->SetNumberOfComponents(nRen); + + renCol->InitTraversal(); + for (int i=0; iGetNextItem(); + vCol = ren->GetVolumes(); + aCol = ren->GetActors(); + a2Col = ren->GetActors2D(); + + volVis->SetNumberOfTuples(vCol->GetNumberOfItems()); + for (vCol->InitTraversal(), j=0; (vol = vCol->GetNextVolume()); ++j) + { + volVis->SetComponent(i, j, vol->GetVisibility()); + } + + actVis->SetNumberOfTuples(aCol->GetNumberOfItems()); + for (aCol->InitTraversal(), j=0; (act = aCol->GetNextActor()); ++j) + { + actVis->SetComponent(i, j, act->GetVisibility()); + } + + act2dVis->SetNumberOfTuples(a2Col->GetNumberOfItems()); + for (a2Col->InitTraversal(), j=0; (act2d = a2Col->GetNextActor2D()); + ++j) + { + act2dVis->SetComponent(i, j, act2d->GetVisibility()); + } + } +} + +void _Turn3DPropsOff(vtkRendererCollection *renCol) +{ + vtkRenderer *ren; + vtkVolumeCollection *vCol; + vtkActorCollection *aCol; + vtkVolume *vol; + vtkActor *act; + + for (renCol->InitTraversal(); (ren = renCol->GetNextItem());) + { + vCol = ren->GetVolumes(); + aCol = ren->GetActors(); + for (vCol->InitTraversal(); (vol = vCol->GetNextVolume());) + { + vol->SetVisibility(0); + } + + for (aCol->InitTraversal(); (act = aCol->GetNextActor());) + { + act->SetVisibility(0); + } + } +} + +void _Turn3DPropsOn(vtkRendererCollection *renCol, vtkIntArray *volVis, + vtkIntArray *actVis) +{ + int nRen = renCol->GetNumberOfItems(); + vtkRenderer *ren; + vtkVolumeCollection *vCol; + vtkActorCollection *aCol; + vtkVolume *vol; + vtkActor *act; + int j; + + renCol->InitTraversal(); + for (int i=0; iGetNextItem(); + vCol = ren->GetVolumes(); + aCol = ren->GetActors(); + + for (vCol->InitTraversal(), j=0; (vol = vCol->GetNextVolume()); ++j) + { + vol->SetVisibility(static_cast(volVis->GetComponent(i, j))); + } + + for (aCol->InitTraversal(), j=0; (act = aCol->GetNextActor()); ++j) + { + act->SetVisibility(static_cast(actVis->GetComponent(i, j))); + } + } +} + +void _Turn2DPropsOff(vtkRendererCollection *renCol) +{ + vtkRenderer *ren; + vtkActor2DCollection *a2Col; + vtkActor2D *act2d; + + for (renCol->InitTraversal(); (ren = renCol->GetNextItem());) + { + a2Col = ren->GetActors2D(); + for (a2Col->InitTraversal(); (act2d = a2Col->GetNextActor2D());) + { + act2d->SetVisibility(0); + } + } +} + +void _Turn2DPropsOn(vtkRendererCollection *renCol, vtkIntArray *act2dVis) +{ + int nRen = renCol->GetNumberOfItems(); + vtkRenderer *ren; + vtkActor2DCollection *a2Col; + vtkActor2D *act2d; + int j; + + renCol->InitTraversal(); + for (int i=0; iGetNextItem(); + a2Col = ren->GetActors2D(); + + for (a2Col->InitTraversal(), j=0; (act2d = a2Col->GetNextActor2D()); + ++j) + { + act2d->SetVisibility(static_cast(act2dVis->GetComponent(i, j))); + } + } +} + +vtkCxxRevisionMacro(vtkGL2PSExporter, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkGL2PSExporter); + +static float vtkGL2PSExporterGlobalPointSizeFactor = 5.0/7.0; +static float vtkGL2PSExporterGlobalLineWidthFactor = 5.0/7.0; + +vtkGL2PSExporter::vtkGL2PSExporter() +{ + this->FilePrefix = NULL; + this->FileFormat = EPS_FILE; + this->Sort = SIMPLE_SORT; + this->Compress = 1; + this->DrawBackground = 1; + this->SimpleLineOffset = 1; + this->Silent = 0; + this->BestRoot = 1; + this->Text = 1; + this->Landscape = 0; + this->PS3Shading = 1; + this->OcclusionCull = 1; + this->Write3DPropsAsRasterImage = 0; +} + +vtkGL2PSExporter::~vtkGL2PSExporter() +{ + if ( this->FilePrefix ) + { + delete [] this->FilePrefix; + } +} + +void vtkGL2PSExporter::SetGlobalPointSizeFactor(float val) +{ + vtkGL2PSExporterGlobalPointSizeFactor = fabs(val); +} + +float vtkGL2PSExporter::GetGlobalPointSizeFactor() +{ + return vtkGL2PSExporterGlobalPointSizeFactor; +} + +void vtkGL2PSExporter::SetGlobalLineWidthFactor(float val) +{ + vtkGL2PSExporterGlobalLineWidthFactor = fabs(val); +} + +float vtkGL2PSExporter::GetGlobalLineWidthFactor() +{ + return vtkGL2PSExporterGlobalLineWidthFactor; +} + +void vtkGL2PSExporter::WriteData() +{ + FILE *fpObj; + char *fName; + GLint format = GL2PS_EPS; + GLint sort; + GLint options = GL2PS_NONE; + int buffsize = 0; + int state = GL2PS_OVERFLOW; + GLint viewport[4]; + int *winsize = this->RenderWindow->GetSize(); + + vtkRendererCollection *renCol = this->RenderWindow->GetRenderers(); + // Stores visibility of actors/volumes. + vtkIntArray *volVis = vtkIntArray::New(); + vtkIntArray *actVis = vtkIntArray::New(); + vtkIntArray *act2dVis = vtkIntArray::New(); + float *floatpixels = 0; // for writing 3d props as an image. + + // Setting this to the entire window size for now. + viewport[0] = 0; + viewport[1] = 0; + viewport[2] = winsize[0]; + viewport[3] = winsize[1]; + + // make sure the user specified a file prefix + if (this->FilePrefix == NULL) + { + vtkErrorMacro(<< "Please specify a file prefix to use"); + return; + } + + // Set the options based on user's choices. + if (this->Sort == NO_SORT) + { + sort = GL2PS_NO_SORT; + } + else if (this->Sort == SIMPLE_SORT) + { + sort = GL2PS_SIMPLE_SORT; + } + else + { + sort = GL2PS_BSP_SORT; + } + + if (this->Compress == 1) + { + options = options | GL2PS_COMPRESS; + } + if (this->DrawBackground == 1) + { + options = options | GL2PS_DRAW_BACKGROUND; + } + if (this->SimpleLineOffset == 1) + { + options = options | GL2PS_SIMPLE_LINE_OFFSET; + } + if (this->Silent == 1) + { + options = options | GL2PS_SILENT; + } + if (this->BestRoot == 1) + { + options = options | GL2PS_BEST_ROOT; + } + if (this->Text == 0) + { + options = options | GL2PS_NO_TEXT; + } + if (this->Landscape == 1) + { + options = options | GL2PS_LANDSCAPE; + } + if (this->PS3Shading == 0) + { + options = options | GL2PS_NO_PS3_SHADING; + } + if (this->OcclusionCull == 1) + { + options = options | GL2PS_OCCLUSION_CULL; + } + + // Setup the file. + fName = new char [strlen(this->FilePrefix) + 5] ; + if (this->FileFormat == PS_FILE) + { + sprintf(fName, "%s.ps", this->FilePrefix); + format = GL2PS_PS; + } + else if (this->FileFormat == EPS_FILE) + { + sprintf(fName, "%s.eps", this->FilePrefix); + format = GL2PS_EPS; + } + else if (this->FileFormat == PDF_FILE) + { + sprintf(fName, "%s.pdf", this->FilePrefix); + format = GL2PS_PDF; + } + else if (this->FileFormat == TEX_FILE) + { + sprintf(fName, "%s.tex", this->FilePrefix); + format = GL2PS_TEX; + } + + fpObj = fopen(fName, "wb"); + if (!fpObj) + { + vtkErrorMacro(<< "unable to open file: " << fName); + return; + } + + // Ready to write file. + + // Need to render once before rendering into the feedback buffer to + // prevent problems. + this->RenderWindow->Render(); + + // Write out a raster image without the 2d actors + if (this->Write3DPropsAsRasterImage) + { + _SavePropVisibility(renCol, volVis, actVis, act2dVis); + _Turn2DPropsOff(renCol); + + int numpix= winsize[0]*winsize[1]*3; + floatpixels = new float [numpix]; + unsigned char *charpixels; + int offscreen = this->RenderWindow->GetOffScreenRendering(); + + this->RenderWindow->OffScreenRenderingOn(); + this->RenderWindow->Render(); + charpixels = this->RenderWindow->GetPixelData(0, 0, winsize[0] - 1, + winsize[1] - 1, 1); + + for (int i=0; iRenderWindow->SetOffScreenRendering(offscreen); + delete [] charpixels; + } + + // Writing the file using GL2PS. + vtkDebugMacro(<<"Writing file using GL2PS"); + + // Call gl2ps to generate the file. + while(state == GL2PS_OVERFLOW) + { + buffsize += 2048*2048; + gl2psBeginPage(this->RenderWindow->GetWindowName(), "VTK", viewport, + format, sort, options, GL_RGBA, 0, + NULL, 0, 0, 0, buffsize, fpObj, fName); + + if (this->Write3DPropsAsRasterImage) + { + // Dump the rendered image without 2d actors as a raster image. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glPushMatrix(); + glRasterPos3f(-1.0, -1.0, -1.0); + gl2psDrawPixels(winsize[0], winsize[1], 0, 0, GL_RGB, + GL_FLOAT, floatpixels); + glPopMatrix(); + + // Render the 2d actors alone in a vector graphic format. + _Turn3DPropsOff(renCol); + _Turn2DPropsOn(renCol, act2dVis); + this->RenderWindow->Render(); + } + else + { + this->RenderWindow->Render(); + } + + state = gl2psEndPage(); + } + fclose(fpObj); + + // Clean up. + if (this->Write3DPropsAsRasterImage) + { + // Reset the visibility. + _Turn3DPropsOn(renCol, volVis, actVis); + // memory + delete [] floatpixels; + // Re-render the scene to show all actors. + this->RenderWindow->Render(); + } + delete[] fName; + volVis->Delete(); + actVis->Delete(); + act2dVis->Delete(); + + vtkDebugMacro(<<"Finished writing file using GL2PS"); +} + +void vtkGL2PSExporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->FilePrefix) + { + os << indent << "FilePrefix: " << this->FilePrefix << "\n"; + } + else + { + os << indent << "FilePrefix: (null)\n"; + } + + os << indent << "FileFormat: " + << this->GetFileFormatAsString() << "\n"; + os << indent << "Sort: " + << this->GetSortAsString() << "\n"; + os << indent << "Compress: " + << (this->Compress ? "On\n" : "Off\n"); + os << indent << "DrawBackground: " + << (this->DrawBackground ? "On\n" : "Off\n"); + os << indent << "SimpleLineOffset: " + << (this->SimpleLineOffset ? "On\n" : "Off\n"); + os << indent << "Silent: " + << (this->Silent ? "On\n" : "Off\n"); + os << indent << "BestRoot: " + << (this->BestRoot ? "On\n" : "Off\n"); + os << indent << "Text: " + << (this->Text ? "On\n" : "Off\n"); + os << indent << "Landscape: " + << (this->Landscape ? "On\n" : "Off\n"); + os << indent << "PS3Shading: " + << (this->PS3Shading ? "On\n" : "Off\n"); + os << indent << "OcclusionCull: " + << (this->OcclusionCull ? "On\n" : "Off\n"); + os << indent << "Write3DPropsAsRasterImage: " + << (this->Write3DPropsAsRasterImage ? "On\n" : "Off\n"); + os << indent << "GlobalPointSizeFactor:" + << vtkGL2PSExporterGlobalPointSizeFactor << endl; + os << indent << "GlobalLineWidthFactor:" + << vtkGL2PSExporterGlobalLineWidthFactor << endl; +} diff --git a/Rendering/vtkGL2PSExporter.h b/Rendering/vtkGL2PSExporter.h new file mode 100644 index 0000000..f5e1e1e --- /dev/null +++ b/Rendering/vtkGL2PSExporter.h @@ -0,0 +1,303 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGL2PSExporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGL2PSExporter - export a scene as a PostScript file using GL2PS. +// .SECTION Description +// vtkGL2PSExporter is a concrete subclass of vtkExporter that writes +// high quality vector PostScript (PS/EPS) or PDF files by using +// GL2PS. GL2PS can be obtained at: http://www.geuz.org/gl2ps/. This +// can be very useful when one requires publication quality pictures. +// This class works best with simple 3D scenes and most 2D plots. +// Please note that GL2PS has its limitations since PostScript is not +// an ideal language to represent complex 3D scenes. However, this +// class does allow one to write mixed vector/raster files by using +// the Write3DPropsAsRasterImage ivar. Please do read the caveats +// section of this documentation. +// +// By default vtkGL2PSExporter generates Encapsulated PostScript (EPS) +// output along with the text in portrait orientation with the +// background color of the window being drawn. The generated output +// is also compressed using zlib. The various other options are set to +// sensible defaults. +// +// The output file format (FileFormat) can be either PostScript (PS), +// Encapsulated PostScript (EPS), PDF or TeX. The file extension is +// generated automatically depending on the FileFormat. The default +// is EPS. When TeX output is chosen, only the text strings in the +// plot are generated and put into a picture environment. One can +// turn on and off the text when generating PS/EPS/PDF files by using +// the Text boolean variable. By default the text is drawn. The +// background color of the renderwindow is drawn by default. To make +// the background white instead use the DrawBackgroundOff function. +// Landscape figures can be generated by using the LandscapeOn +// function. Portrait orientation is used by default. Several of the +// GL2PS options can be set. The names of the ivars for these options +// are similar to the ones that GL2PS provides. Compress, +// SimpleLineOffset, Silent, BestRoot, PS3Shading and OcclusionCull +// are similar to the options provided by GL2PS. Please read the +// function documentation or the GL2PS documentation for more details. +// The ivar Write3DPropsAsRasterImage allows one to generate mixed +// vector/raster images. All the 3D props in the scene will be +// written as a raster image and all 2D actors will be written as +// vector graphic primitives. This makes it possible to handle +// transparency and complex 3D scenes. This ivar is set to Off by +// default. When drawing lines and points the OpenGL point size and +// line width are multiplied by a factor in order to generate +// PostScript lines and points of the right size. The +// Get/SetGlobalPointSizeFactor and Get/SetGlobalLineWidthFactor let +// one customize this ratio. The default value is such that the +// PostScript output looks close to what is seen on screen. +// +// To use this class you need to turn on VTK_USE_GL2PS when +// configuring VTK. + +// .SECTION Caveats +// By default (with Write3DPropsAsRasterImage set to Off) exporting +// complex 3D scenes can take a long while and result in huge output +// files. Generating correct vector graphics output for scenes with +// transparency is almost impossible. However, one can set +// Write3DPropsAsRasterImageOn and generate mixed vector/raster files. +// This should work fine with complex scenes along with transparent +// actors. + +// .SECTION See Also +// vtkExporter + +// .SECTION Thanks +// Thanks to Goodwin Lawlor and Prabhu Ramachandran for this class. + + +#ifndef __vtkGL2PSExporter_h +#define __vtkGL2PSExporter_h + +#include "vtkExporter.h" + +class VTK_RENDERING_EXPORT vtkGL2PSExporter : public vtkExporter +{ +public: + static vtkGL2PSExporter *New(); + vtkTypeRevisionMacro(vtkGL2PSExporter,vtkExporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the prefix of the files to write out. The resulting filenames + // will have .ps or .eps or .tex appended to them depending on the + // other options chosen. + vtkSetStringMacro(FilePrefix); + vtkGetStringMacro(FilePrefix); + +//BTX + enum OutputFormat + { + PS_FILE, + EPS_FILE, + PDF_FILE, + TEX_FILE + }; +//ETX + + // Description: + // Specify the format of file to write out. This can be one of: + // PS_FILE, EPS_FILE, PDF_FILE, TEX_FILE. Defaults to EPS_FILE. + // Depending on the option chosen it generates the appropriate file + // (with correct extension) when the Write function is called. + vtkSetClampMacro(FileFormat, int, PS_FILE, TEX_FILE); + vtkGetMacro(FileFormat, int); + void SetFileFormatToPS() + {this->SetFileFormat(PS_FILE);}; + void SetFileFormatToEPS() + {this->SetFileFormat(EPS_FILE);}; + void SetFileFormatToPDF() + {this->SetFileFormat(PDF_FILE);}; + void SetFileFormatToTeX() + {this->SetFileFormat(TEX_FILE);}; + char *GetFileFormatAsString(); + +//BTX + enum SortScheme + { + NO_SORT=0, + SIMPLE_SORT=1, + BSP_SORT=2 + }; +//ETX + + // Description: + // Set the the type of sorting algorithm to order primitives from + // back to front. Successive algorithms are more memory + // intensive. Simple is the default but BSP is perhaps the best. + vtkSetClampMacro(Sort, int, NO_SORT, BSP_SORT); + vtkGetMacro(Sort,int); + void SetSortToOff() + {this->SetSort(NO_SORT);}; + void SetSortToSimple() + {this->SetSort(SIMPLE_SORT);}; + void SetSortToBSP() + {this->SetSort(BSP_SORT);}; + char *GetSortAsString(); + + // Description: + // Turn on/off compression when generating PostScript or PDF + // output. By default compression is on. + vtkSetMacro(Compress, int); + vtkGetMacro(Compress, int); + vtkBooleanMacro(Compress, int); + + // Description: + // Turn on/off drawing the background frame. If off the background + // is treated as white. By default the background is drawn. + vtkSetMacro(DrawBackground, int); + vtkGetMacro(DrawBackground, int); + vtkBooleanMacro(DrawBackground, int); + + // Description: + // Turn on/off the GL2PS_SIMPLE_LINE_OFFSET option. When enabled a + // small offset is added in the z-buffer to all the lines in the + // plot. This results in an anti-aliasing like solution. Defaults to + // on. + vtkSetMacro(SimpleLineOffset, int); + vtkGetMacro(SimpleLineOffset, int); + vtkBooleanMacro(SimpleLineOffset, int); + + // Description: + // Turn on/off GL2PS messages sent to stderr (GL2PS_SILENT). When + // enabled GL2PS messages are suppressed. Defaults to off. + vtkSetMacro(Silent, int); + vtkGetMacro(Silent, int); + vtkBooleanMacro(Silent, int); + + // Description: + // Turn on/off the GL2PS_BEST_ROOT option. When enabled the + // construction of the BSP tree is optimized by choosing the root + // primitives leading to the minimum number of splits. Defaults to + // on. + vtkSetMacro(BestRoot, int); + vtkGetMacro(BestRoot, int); + vtkBooleanMacro(BestRoot, int); + + // Description: + // Turn on/off drawing the text. If on (default) the text is drawn. + // If the FileFormat is set to TeX output then a LaTeX picture is + // generated with the text strings. If off text output is + // suppressed. + vtkSetMacro(Text, int); + vtkGetMacro(Text, int); + vtkBooleanMacro(Text, int); + + // Description: + // Turn on/off landscape orientation. If off (default) the + // orientation is set to portrait. + vtkSetMacro(Landscape, int); + vtkGetMacro(Landscape, int); + vtkBooleanMacro(Landscape, int); + + // Description: + // Turn on/off the GL2PS_PS3_SHADING option. When enabled the + // shfill PostScript level 3 operator is used. Read the GL2PS + // documentation for more details. Defaults to on. + vtkSetMacro(PS3Shading, int); + vtkGetMacro(PS3Shading, int); + vtkBooleanMacro(PS3Shading, int); + + // Description: + // Turn on/off culling of occluded polygons (GL2PS_OCCLUSION_CULL). + // When enabled hidden polygons are removed. This reduces file size + // considerably. Defaults to on. + vtkSetMacro(OcclusionCull, int); + vtkGetMacro(OcclusionCull, int); + vtkBooleanMacro(OcclusionCull, int); + + // Description: + // Turn on/off writing 3D props as raster images. 2D props are + // rendered using vector graphics primitives. If you have hi-res + // actors and are using transparency you probably need to turn this + // on. Defaults to Off. + vtkSetMacro(Write3DPropsAsRasterImage, int); + vtkGetMacro(Write3DPropsAsRasterImage, int); + vtkBooleanMacro(Write3DPropsAsRasterImage, int); + + // Description: + // Set the ratio between the OpenGL PointSize and that used by GL2PS + // to generate PostScript. Defaults to a ratio of 5/7. + static void SetGlobalPointSizeFactor(float val); + static float GetGlobalPointSizeFactor(); + + // Description: + // Set the ratio between the OpenGL LineWidth and that used by GL2PS + // to generate PostScript. Defaults to a ratio of 5/7. + static void SetGlobalLineWidthFactor(float val); + static float GetGlobalLineWidthFactor(); + +protected: + vtkGL2PSExporter(); + ~vtkGL2PSExporter(); + + void WriteData(); + + char *FilePrefix; + int FileFormat; + int Sort; + int Compress; + int DrawBackground; + int SimpleLineOffset; + int Silent; + int BestRoot; + int Text; + int Landscape; + int PS3Shading; + int OcclusionCull; + int Write3DPropsAsRasterImage; + +private: + vtkGL2PSExporter(const vtkGL2PSExporter&); // Not implemented + void operator=(const vtkGL2PSExporter&); // Not implemented +}; + +inline char *vtkGL2PSExporter::GetSortAsString(void) +{ + if ( this->Sort == NO_SORT ) + { + return (char *)"Off"; + } + else if ( this->Sort == SIMPLE_SORT ) + { + return (char *)"Simple"; + } + else + { + return (char *)"BSP"; + } +} + +inline char *vtkGL2PSExporter::GetFileFormatAsString(void) +{ + if ( this->FileFormat == PS_FILE ) + { + return (char *)"PS"; + } + else if ( this->FileFormat == EPS_FILE ) + { + return (char *)"EPS"; + } + else if ( this->FileFormat == PDF_FILE ) + { + return (char *)"PDF"; + } + else + { + return (char *)"TeX"; + } +} + +#endif diff --git a/Rendering/vtkGenericRenderWindowInteractor.cxx b/Rendering/vtkGenericRenderWindowInteractor.cxx new file mode 100644 index 0000000..0d9eb9d --- /dev/null +++ b/Rendering/vtkGenericRenderWindowInteractor.cxx @@ -0,0 +1,219 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericRenderWindowInteractor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkGenericRenderWindowInteractor.h" +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + +vtkCxxRevisionMacro(vtkGenericRenderWindowInteractor, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkGenericRenderWindowInteractor); +// Construct object so that light follows camera motion. +vtkGenericRenderWindowInteractor::vtkGenericRenderWindowInteractor() +{ +} + +void vtkGenericRenderWindowInteractor::MouseMoveEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::RightButtonPressEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::RightButtonPressEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::RightButtonReleaseEvent() +{ + if (!this->Enabled) + { + return; + } + + this->InvokeEvent(vtkCommand::RightButtonReleaseEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::LeftButtonPressEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::LeftButtonPressEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::LeftButtonReleaseEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::MiddleButtonPressEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::MiddleButtonPressEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::MiddleButtonReleaseEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::MouseWheelForwardEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::MouseWheelForwardEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::MouseWheelBackwardEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::ExposeEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::ExposeEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::ConfigureEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::ConfigureEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::EnterEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::EnterEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::LeaveEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::LeaveEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::TimerEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::TimerEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::KeyPressEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::KeyPressEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::KeyReleaseEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::CharEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::CharEvent, NULL); +} + +void vtkGenericRenderWindowInteractor::ExitEvent() +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::ExitEvent, NULL); +} + + +vtkGenericRenderWindowInteractor::~vtkGenericRenderWindowInteractor() +{ +} + + + +void vtkGenericRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +int vtkGenericRenderWindowInteractor::CreateTimer(int ) +{ + if(this->HasObserver(vtkCommand::CreateTimerEvent)) + { + this->InvokeEvent(vtkCommand::CreateTimerEvent, NULL); + return 1; + } + return 0; +} + +int vtkGenericRenderWindowInteractor::DestroyTimer() +{ + if(this->HasObserver(vtkCommand::DestroyTimerEvent)) + { + this->InvokeEvent(vtkCommand::DestroyTimerEvent, NULL); + return 1; + } + return 0; +} diff --git a/Rendering/vtkGenericRenderWindowInteractor.h b/Rendering/vtkGenericRenderWindowInteractor.h new file mode 100644 index 0000000..bce1736 --- /dev/null +++ b/Rendering/vtkGenericRenderWindowInteractor.h @@ -0,0 +1,74 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGenericRenderWindowInteractor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGenericRenderWindowInteractor - platform-independent programmable render window interactor. + +// .SECTION Description +// vtkGenericRenderWindowInteractor provides a way to translate native +// mouse and keyboard events into vtk Events. By calling the methods on +// this class, vtk events will be invoked. This will allow scripting +// languages to use vtkInteractorStyles and 3D widgets. + + + +#ifndef __vtkGenericRenderWindowInteractor_h +#define __vtkGenericRenderWindowInteractor_h + +#include "vtkRenderWindowInteractor.h" + +class VTK_RENDERING_EXPORT vtkGenericRenderWindowInteractor : public vtkRenderWindowInteractor +{ +public: + static vtkGenericRenderWindowInteractor *New(); + vtkTypeRevisionMacro(vtkGenericRenderWindowInteractor,vtkRenderWindowInteractor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Fire various events, SetEventInformation should be called just prior + // to calling any of these methods. This methods will Invoke the + // corresponding vtk event. + virtual void MouseMoveEvent(); + virtual void RightButtonPressEvent(); + virtual void RightButtonReleaseEvent(); + virtual void LeftButtonPressEvent(); + virtual void LeftButtonReleaseEvent(); + virtual void MiddleButtonPressEvent(); + virtual void MiddleButtonReleaseEvent(); + virtual void MouseWheelForwardEvent(); + virtual void MouseWheelBackwardEvent(); + virtual void ExposeEvent(); + virtual void ConfigureEvent(); + virtual void EnterEvent(); + virtual void LeaveEvent(); + virtual void TimerEvent(); + virtual void KeyPressEvent(); + virtual void KeyReleaseEvent(); + virtual void CharEvent(); + virtual void ExitEvent(); + + // Description: + // Allow users of the class to add callbacks to handle the creation and + // destruction of timers. CreateTimer should create a timer event of 10 milliseconds, + // and at the end of that time, it should call TimerEvent on this class. + virtual int CreateTimer(int ); + virtual int DestroyTimer(); +protected: + vtkGenericRenderWindowInteractor(); + ~vtkGenericRenderWindowInteractor(); +private: + vtkGenericRenderWindowInteractor(const vtkGenericRenderWindowInteractor&); // Not implemented. + void operator=(const vtkGenericRenderWindowInteractor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkGraphicsFactory.cxx b/Rendering/vtkGraphicsFactory.cxx new file mode 100644 index 0000000..12c8b4f --- /dev/null +++ b/Rendering/vtkGraphicsFactory.cxx @@ -0,0 +1,341 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGraphicsFactory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkObjectFactory.h" + +#include "vtkGraphicsFactory.h" +#include "vtkToolkits.h" +#include "vtkDebugLeaks.h" + +// if using some sort of opengl, then include these files +#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON) +#include "vtkOpenGLActor.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLImageActor.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLProperty.h" +#include "vtkOpenGLPolyDataMapper.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLTexture.h" +#endif + +// Win32 specific stuff +#ifdef _WIN32 +# ifndef VTK_USE_OGLR +# include "vtkWin32OpenGLRenderWindow.h" +# include "vtkWin32RenderWindowInteractor.h" +# define VTK_DISPLAY_WIN32_OGL +# endif // VTK_USE_OGLR +#endif + +// Apple OSX stuff +#ifdef VTK_USE_CARBON +# include "vtkCarbonRenderWindow.h" +# include "vtkCarbonRenderWindowInteractor.h" +# define VTK_DISPLAY_CARBON +#endif + +#ifdef VTK_USE_COCOA +# include "vtkCocoaRenderWindow.h" +# include "vtkCocoaRenderWindowInteractor.h" +# define VTK_DISPLAY_COCOA +#endif + +// X OpenGL stuff +#ifdef VTK_USE_OGLR +# include "vtkXRenderWindowInteractor.h" +# include "vtkXOpenGLRenderWindow.h" +# define VTK_DISPLAY_X11_OGL +#endif + +#if defined(VTK_USE_MANGLED_MESA) +#include "vtkMesaActor.h" +#include "vtkMesaCamera.h" +#include "vtkMesaImageActor.h" +#include "vtkMesaLight.h" +#include "vtkMesaProperty.h" +#include "vtkMesaPolyDataMapper.h" +#include "vtkMesaRenderer.h" +#include "vtkMesaTexture.h" +#include "vtkXMesaRenderWindow.h" +#endif + +#include "vtkCriticalSection.h" + +#include "stdlib.h" + +static vtkSimpleCriticalSection vtkUseMesaClassesCriticalSection; +static vtkSimpleCriticalSection vtkOffScreenOnlyModeCriticalSection; +int vtkGraphicsFactory::UseMesaClasses = 0; + +#ifdef VTK_USE_OFFSCREEN +int vtkGraphicsFactory::OffScreenOnlyMode = 1; +#else +int vtkGraphicsFactory::OffScreenOnlyMode = 0; +#endif + +vtkCxxRevisionMacro(vtkGraphicsFactory, "$Revision: 1.38 $"); +vtkStandardNewMacro(vtkGraphicsFactory); + +const char *vtkGraphicsFactory::GetRenderLibrary() +{ + const char *temp; + + // first check the environment variable + temp = getenv("VTK_RENDERER"); + + // Backward compatibility + if ( temp ) + { + if (!strcmp("oglr",temp)) + { + temp = "OpenGL"; + } + else if (!strcmp("woglr",temp)) + { + temp = "Win32OpenGL"; + } + else if (strcmp("OpenGL",temp) && + strcmp("Win32OpenGL",temp)) + { + vtkGenericWarningMacro(<<"VTK_RENDERER set to unsupported type:" << temp); + temp = NULL; + } + } + + // if nothing is set then work down the list of possible renderers + if ( !temp ) + { +#ifdef VTK_DISPLAY_X11_OGL + temp = "OpenGL"; +#endif +#ifdef VTK_DISPLAY_WIN32_OGL + temp = "Win32OpenGL"; +#endif +#ifdef VTK_DISPLAY_CARBON + temp = "CarbonOpenGL"; +#endif +#ifdef VTK_DISPLAY_COCOA + temp = "CocoaOpenGL"; +#endif + } + + return temp; +} + +vtkObject* vtkGraphicsFactory::CreateInstance(const char* vtkclassname ) +{ + // first check the object factory + vtkObject *ret = vtkObjectFactory::CreateInstance(vtkclassname); + if (ret) + { + return ret; + } + // if the factory failed to create the object, + // then destroy it now, as vtkDebugLeaks::ConstructClass was called + // with vtkclassname, and not the real name of the class +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass(vtkclassname); +#endif + const char *rl = vtkGraphicsFactory::GetRenderLibrary(); + +#ifdef VTK_USE_OGLR + if (!strcmp("OpenGL",rl)) + { + if(strcmp(vtkclassname, "vtkRenderWindow") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkXMesaRenderWindow::New(); + } +#endif + return vtkXOpenGLRenderWindow::New(); + } + } + if ( !vtkGraphicsFactory::GetOffScreenOnlyMode() ) + { + if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0) + { + return vtkXRenderWindowInteractor::New(); + } + } +#endif + +#ifdef VTK_DISPLAY_WIN32_OGL + if ( !vtkGraphicsFactory::GetOffScreenOnlyMode() ) + { + if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0) + { + return vtkWin32RenderWindowInteractor::New(); + } + } + if (!strcmp("Win32OpenGL",rl)) + { + if(strcmp(vtkclassname, "vtkRenderWindow") == 0) + { + return vtkWin32OpenGLRenderWindow::New(); + } + } +#endif + +#ifdef VTK_USE_CARBON + if ( !vtkGraphicsFactory::GetOffScreenOnlyMode() ) + { + if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0) + { + return vtkCarbonRenderWindowInteractor::New(); + } + } + if(strcmp(vtkclassname, "vtkRenderWindow") == 0) + { + return vtkCarbonRenderWindow::New(); + } +#endif +#ifdef VTK_USE_COCOA + if ( !vtkGraphicsFactory::GetOffScreenOnlyMode() ) + { + if(strcmp(vtkclassname, "vtkRenderWindowInteractor") == 0) + { + return vtkCocoaRenderWindowInteractor::New(); + } + } + if(strcmp(vtkclassname, "vtkRenderWindow") == 0) + { + return vtkCocoaRenderWindow::New(); + } +#endif + +#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON) + if (!strcmp("OpenGL",rl) || !strcmp("Win32OpenGL",rl) || !strcmp("CarbonOpenGL",rl) || !strcmp("CocoaOpenGL",rl)) + { + if(strcmp(vtkclassname, "vtkActor") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaActor::New(); + } +#endif + return vtkOpenGLActor::New(); + } + if(strcmp(vtkclassname, "vtkCamera") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaCamera::New(); + } +#endif + return vtkOpenGLCamera::New(); + } + if(strcmp(vtkclassname, "vtkImageActor") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaImageActor::New(); + } +#endif + return vtkOpenGLImageActor::New(); + } + if(strcmp(vtkclassname, "vtkLight") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaLight::New(); + } +#endif + return vtkOpenGLLight::New(); + } + if(strcmp(vtkclassname, "vtkProperty") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaProperty::New(); + } +#endif + return vtkOpenGLProperty::New(); + } + if(strcmp(vtkclassname, "vtkPolyDataMapper") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaPolyDataMapper::New(); + } +#endif + return vtkOpenGLPolyDataMapper::New(); + } + if(strcmp(vtkclassname, "vtkRenderer") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaRenderer::New(); + } +#endif + return vtkOpenGLRenderer::New(); + } + if(strcmp(vtkclassname, "vtkTexture") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::UseMesaClasses ) + { + return vtkMesaTexture::New(); + } +#endif + return vtkOpenGLTexture::New(); + } + } +#endif + + return 0; +} + +//---------------------------------------------------------------------------- +void vtkGraphicsFactory::SetUseMesaClasses(int use) +{ + vtkUseMesaClassesCriticalSection.Lock(); + vtkGraphicsFactory::UseMesaClasses = use; + vtkUseMesaClassesCriticalSection.Unlock(); +} + +//---------------------------------------------------------------------------- +int vtkGraphicsFactory::GetUseMesaClasses() +{ + return vtkGraphicsFactory::UseMesaClasses; +} + +//---------------------------------------------------------------------------- +void vtkGraphicsFactory::SetOffScreenOnlyMode(int use) +{ + vtkOffScreenOnlyModeCriticalSection.Lock(); + vtkGraphicsFactory::OffScreenOnlyMode = use; + vtkOffScreenOnlyModeCriticalSection.Unlock(); +} + +//---------------------------------------------------------------------------- +int vtkGraphicsFactory::GetOffScreenOnlyMode() +{ + return vtkGraphicsFactory::OffScreenOnlyMode; +} + +//---------------------------------------------------------------------------- +void vtkGraphicsFactory::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkGraphicsFactory.h b/Rendering/vtkGraphicsFactory.h new file mode 100644 index 0000000..bda1748 --- /dev/null +++ b/Rendering/vtkGraphicsFactory.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkGraphicsFactory.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkGraphicsFactory - +// .SECTION Description + +#ifndef __vtkGraphicsFactory_h +#define __vtkGraphicsFactory_h + +#include "vtkObject.h" + +class VTK_RENDERING_EXPORT vtkGraphicsFactory : public vtkObject +{ +public: + static vtkGraphicsFactory *New(); + vtkTypeRevisionMacro(vtkGraphicsFactory,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create and return an instance of the named vtk object. + // This method first checks the vtkObjectFactory to support + // dynamic loading. + static vtkObject* CreateInstance(const char* vtkclassname); + + // Description: + // What rendering library has the user requested + static const char *GetRenderLibrary(); + + // Description: + // This option enables the creation of Mesa classes + // instead of the OpenGL classes when using mangled Mesa. + static void SetUseMesaClasses(int use); + static int GetUseMesaClasses(); + + // Description: + // This option enables the off-screen only mode. In this mode no X calls will + // be made even when interactor is used. + static void SetOffScreenOnlyMode(int use); + static int GetOffScreenOnlyMode(); + +protected: + vtkGraphicsFactory() {}; + + static int UseMesaClasses; + static int OffScreenOnlyMode; + +private: + vtkGraphicsFactory(const vtkGraphicsFactory&); // Not implemented. + void operator=(const vtkGraphicsFactory&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkHierarchicalPolyDataMapper.cxx b/Rendering/vtkHierarchicalPolyDataMapper.cxx new file mode 100644 index 0000000..d3a70d0 --- /dev/null +++ b/Rendering/vtkHierarchicalPolyDataMapper.cxx @@ -0,0 +1,306 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalPolyDataMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkInformation.h" +#include "vtkMapper.h" +#include "vtkExecutive.h" +#include "vtkCompositeDataPipeline.h" +#include "vtkCompositeDataSet.h" +#include "vtkCompositeDataIterator.h" +#include "vtkHierarchicalDataSet.h" +#include "vtkPolyDataMapper.h" +#include "vtkObjectFactory.h" +#include "vtkHierarchicalPolyDataMapper.h" +#include "vtkPolyData.h" +#include "vtkMath.h" +#include "vtkGarbageCollector.h" + +#include + +vtkCxxRevisionMacro(vtkHierarchicalPolyDataMapper, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkHierarchicalPolyDataMapper); + +class vtkHierarchicalPolyDataMapperInternals +{ +public: + vtkstd::vector Mappers; +}; + +vtkHierarchicalPolyDataMapper::vtkHierarchicalPolyDataMapper() +{ + this->Internal = new vtkHierarchicalPolyDataMapperInternals; +} + +vtkHierarchicalPolyDataMapper::~vtkHierarchicalPolyDataMapper() +{ + for(unsigned int i=0;iInternal->Mappers.size();i++) + { + this->Internal->Mappers[i]->UnRegister(this); + } + this->Internal->Mappers.clear(); + + delete this->Internal; +} + +// Specify the type of data this mapper can handle. If we are +// working with a regular (not hierarchical) pipeline, then we +// need vtkPolyData. For composite data pipelines, then +// vtkHierarchicalDataSet is required, and we'll check when +// building our structure whether all the part of the composite +// data set are polydata. +int vtkHierarchicalPolyDataMapper::FillInputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + info->Set(vtkCompositeDataPipeline::INPUT_REQUIRED_COMPOSITE_DATA_TYPE(), + "vtkHierarchicalDataSet"); + return 1; +} + +// When the structure is out-of-date, recreate it by +// creating a mapper for each input data. +void vtkHierarchicalPolyDataMapper::BuildPolyDataMapper() +{ + int warnOnce = 0; + + //Delete pdmappers if they already exist. + for(unsigned int i=0;iInternal->Mappers.size();i++) + { + this->Internal->Mappers[i]->UnRegister(this); + } + this->Internal->Mappers.clear(); + + //Get the HierarchicalDataSet from the input + vtkInformation* inInfo = this->GetExecutive()->GetInputInformation(0,0); + vtkHierarchicalDataSet *input = vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + // If it isn't hierarchical, maybe it is just a plain vtkPolyData + if(!input) + { + vtkPolyData *pd = vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); + if ( pd ) + { + // Make a copy of the data to break the pipeline here + vtkPolyData *newpd = vtkPolyData::New(); + newpd->ShallowCopy(pd); + vtkPolyDataMapper *pdmapper = vtkPolyDataMapper::New(); + pdmapper->Register( this ); + pdmapper->SetInput(newpd); + this->Internal->Mappers.push_back(pdmapper); + newpd->Delete(); + pdmapper->Delete(); + } + } + else + { + //for each data set build a vtkPolyDataMapper + vtkCompositeDataIterator* iter = input->NewIterator(); + iter->GoToFirstItem(); + while (!iter->IsDoneWithTraversal()) + { + vtkPolyData* pd = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject()); + if (pd) + { + // Make a copy of the data to break the pipeline here + vtkPolyData *newpd = vtkPolyData::New(); + newpd->ShallowCopy(pd); + vtkPolyDataMapper *pdmapper = vtkPolyDataMapper::New(); + pdmapper->Register(this); + pdmapper->SetInput(newpd); + this->Internal->Mappers.push_back(pdmapper); + newpd->Delete(); + pdmapper->Delete(); + } + // This is not polydata - warn the user that there are non-polydata + // parts to this data set which will not be rendered by this mapper + else + { + if ( !warnOnce ) + { + vtkErrorMacro("All data in the hierachical dataset must be polydata."); + warnOnce = 1; + } + } + iter->GoToNextItem(); + } + iter->Delete(); + } + + this->InternalMappersBuildTime.Modified(); + +} + +void vtkHierarchicalPolyDataMapper::Render(vtkRenderer *ren, vtkActor *a) +{ + //If the PolyDataMappers are not up-to-date then rebuild them + vtkCompositeDataPipeline * executive = + vtkCompositeDataPipeline::SafeDownCast(this->GetExecutive()); + + if(executive->GetPipelineMTime() > this->InternalMappersBuildTime.GetMTime()) + { + this->BuildPolyDataMapper(); + } + + this->TimeToDraw = 0; + //Call Render() on each of the PolyDataMappers + for(unsigned int i=0;iInternal->Mappers.size();i++) + { + if ( this->ClippingPlanes != + this->Internal->Mappers[i]->GetClippingPlanes() ) + { + this->Internal->Mappers[i]->SetClippingPlanes( this->ClippingPlanes ); + } + + this->Internal->Mappers[i]->SetLookupTable( + this->GetLookupTable()); + this->Internal->Mappers[i]->SetScalarVisibility( + this->GetScalarVisibility()); + this->Internal->Mappers[i]->SetUseLookupTableScalarRange( + this->GetUseLookupTableScalarRange()); + this->Internal->Mappers[i]->SetScalarRange( + this->GetScalarRange()); + this->Internal->Mappers[i]->SetImmediateModeRendering( + this->GetImmediateModeRendering()); + this->Internal->Mappers[i]->SetColorMode(this->GetColorMode()); + this->Internal->Mappers[i]->SetInterpolateScalarsBeforeMapping( + this->GetInterpolateScalarsBeforeMapping()); + + this->Internal->Mappers[i]->SetScalarMode(this->GetScalarMode()); + if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA || + this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + if ( this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID ) + { + this->Internal->Mappers[i]->ColorByArrayComponent( + this->ArrayId,ArrayComponent); + } + else + { + this->Internal->Mappers[i]->ColorByArrayComponent( + this->ArrayName,ArrayComponent); + } + } + + this->Internal->Mappers[i]->Render(ren,a); + this->TimeToDraw += this->Internal->Mappers[i]->GetTimeToDraw(); + } +} +vtkExecutive* vtkHierarchicalPolyDataMapper::CreateDefaultExecutive() +{ + return vtkCompositeDataPipeline::New(); +} + +//Looks at each DataSet and finds the union of all the bounds +void vtkHierarchicalPolyDataMapper::ComputeBounds() +{ + vtkMath::UninitializeBounds(this->Bounds); + + vtkInformation* inInfo = this->GetExecutive()->GetInputInformation(0,0); + vtkHierarchicalDataSet *input = vtkHierarchicalDataSet::SafeDownCast( + inInfo->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET())); + + // If we don't have hierarchical data, test to see if we have + // plain old polydata. In this case, the bounds are simply + // the bounds of the input polydata. + if(!input) + { + vtkPolyData *pd = vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); + if ( pd ) + { + pd->GetBounds( this->Bounds ); + } + return; + } + + // We do have hierarchical data - so we need to loop over + // it and get the total bounds. + vtkCompositeDataIterator* iter = input->NewIterator(); + iter->GoToFirstItem(); + double bounds[6]; + int i; + + while (!iter->IsDoneWithTraversal()) + { + vtkPolyData *pd = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject()); + if (pd) + { + // If this isn't the first time through, expand bounds + // we've compute so far based on the bounds of this + // block + if ( vtkMath::AreBoundsInitialized(this->Bounds) ) + { + pd->GetBounds(bounds); + for(i=0; i<3; i++) + { + this->Bounds[i*2] = + (bounds[i*2]Bounds[i*2])? + (bounds[i*2]):(this->Bounds[i*2]); + this->Bounds[i*2+1] = + (bounds[i*2+1]>this->Bounds[i*2+1])? + (bounds[i*2+1]):(this->Bounds[i*2+1]); + } + } + // If this is our first time through, just get the bounds + // of the data as the initial bounds + else + { + pd->GetBounds(this->Bounds); + } + } + iter->GoToNextItem(); + } + iter->Delete(); + this->BoundsMTime.Modified(); +} + +double* vtkHierarchicalPolyDataMapper::GetBounds() +{ + static double bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0}; + + if ( ! this->GetInput() ) + { + return bounds; + } + else + { + + this->Update(); + + //only compute bounds when the input data has changed + vtkCompositeDataPipeline * executive = vtkCompositeDataPipeline::SafeDownCast(this->GetExecutive()); + if( executive->GetPipelineMTime() > this->BoundsMTime.GetMTime() ) + { + ComputeBounds(); + } + + return this->Bounds; + } +} + +void vtkHierarchicalPolyDataMapper::ReleaseGraphicsResources( vtkWindow *win ) +{ + for(unsigned int i=0;iInternal->Mappers.size();i++) + { + this->Internal->Mappers[i]->ReleaseGraphicsResources( win ); + } +} + +void vtkHierarchicalPolyDataMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkHierarchicalPolyDataMapper.h b/Rendering/vtkHierarchicalPolyDataMapper.h new file mode 100644 index 0000000..862beb9 --- /dev/null +++ b/Rendering/vtkHierarchicalPolyDataMapper.h @@ -0,0 +1,103 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkHierarchicalPolyDataMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkHierarchicalPolyDataMapper - a class that renders hierarchical polygonal data +// .SECTION Description +// This class uses a set of vtkPolyDataMappers to render input data +// which may be hierarchical. The input to this mapper may be +// either vtkPolyData or a vtkHierarchicalDataSet built from +// polydata. If something other than vtkPolyData is encountered, +// an error message will be produced. +// +// .SECTION see also +// vtkPolyDataMapper + +#ifndef __vtkHierarchicalPolyDataMapper_h +#define __vtkHierarchicalPolyDataMapper_h + +#include "vtkMapper.h" + +class vtkPolyDataMapper; +class vtkInformation; +class vtkRenderer; +class vtkActor; +class vtkHierarchicalPolyDataMapperInternals; + +class VTK_RENDERING_EXPORT vtkHierarchicalPolyDataMapper : public vtkMapper +{ + +public: + static vtkHierarchicalPolyDataMapper *New(); + vtkTypeRevisionMacro(vtkHierarchicalPolyDataMapper, vtkMapper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Standard method for rendering a mapper. This method will be + // called by the actor. + void Render(vtkRenderer *ren, vtkActor *a); + + // Description: + // Standard vtkProp method to get 3D bounds of a 3D prop + double *GetBounds(); + void GetBounds(double bounds[6]) { this->Superclass::GetBounds( bounds ); }; + + // Description: + // Release the underlying resources associated with this mapper + void ReleaseGraphicsResources(vtkWindow *); + + +protected: + vtkHierarchicalPolyDataMapper(); + ~vtkHierarchicalPolyDataMapper(); + + // Description: + // We need to override this method because the standard streaming + // demand driven pipeline is not what we want - we are expecting + // hierarchical data as input + vtkExecutive* CreateDefaultExecutive(); + + // Description: + // Need to define the type of data handled by this mapper. + virtual int FillInputPortInformation(int port, vtkInformation* info); + + // Description: + // This is the build method for creating the internal polydata + // mapper that do the actual work + void BuildPolyDataMapper(); + + // Description: + // Need to loop over the hierarchy to compute bounds + void ComputeBounds(); + + // Description: + // Time stamp for computation of bounds. + vtkTimeStamp BoundsMTime; + + // Description: + // These are the internal polydata mapper that do the + // rendering. We save then so that they can keep their + // display lists. + vtkHierarchicalPolyDataMapperInternals *Internal; + + // Description: + // Time stamp for when we need to update the + // internal mappers + vtkTimeStamp InternalMappersBuildTime; + +private: + vtkHierarchicalPolyDataMapper(const vtkHierarchicalPolyDataMapper&); // Not implemented. + void operator=(const vtkHierarchicalPolyDataMapper&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkIVExporter.cxx b/Rendering/vtkIVExporter.cxx new file mode 100644 index 0000000..fef026a --- /dev/null +++ b/Rendering/vtkIVExporter.cxx @@ -0,0 +1,715 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIVExporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkIVExporter.h" + +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkGeometryFilter.h" +#include "vtkImageData.h" +#include "vtkLight.h" +#include "vtkLightCollection.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRendererCollection.h" +#include "vtkTexture.h" +#include "vtkTransform.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkIVExporter, "$Revision: 1.62 $"); +vtkStandardNewMacro(vtkIVExporter); + +vtkIVExporter::vtkIVExporter() +{ + this->FileName = NULL; +} + +vtkIVExporter::~vtkIVExporter() +{ + if ( this->FileName ) + { + delete [] this->FileName; + } +} + +static char indent[256]; +int indent_now = 0; +#define VTK_INDENT_MORE { indent[indent_now] = ' '; \ + indent_now += 4; \ + indent[indent_now] = 0; } +#define VTK_INDENT_LESS { indent[indent_now] = ' '; \ + indent_now -= 4; \ + indent[indent_now] = 0; } + +void vtkIVExporter::WriteData() +{ + vtkRenderer *ren; + FILE *fp; + vtkActorCollection *ac; + vtkActor *anActor, *aPart; + vtkLightCollection *lc; + vtkLight *aLight; + vtkCamera *cam; + double *tempd; + + for (int i=0;i<256;i++) + { + indent[i] = ' '; + } + indent[indent_now] = 0; + + // make sure the user specified a filename + if ( this->FileName == NULL) + { + vtkErrorMacro(<< "Please specify FileName to use"); + return; + } + + // first make sure there is only one renderer in this rendering window + if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1) + { + vtkErrorMacro(<< "OpenInventor files only support one renderer per window."); + return; + } + + // get the renderer + ren = this->RenderWindow->GetRenderers()->GetFirstRenderer(); + + // make sure it has at least one actor + if (ren->GetActors()->GetNumberOfItems() < 1) + { + vtkErrorMacro(<< "no actors found for writing OpenInventor file."); + return; + } + + // try opening the files + fp = fopen(this->FileName,"w"); + if (!fp) + { + vtkErrorMacro(<< "unable to open OpenInventor file " << this->FileName); + return; + } + + // + // Write header + // + vtkDebugMacro("Writing OpenInventor file"); + fprintf(fp,"#Inventor V2.0 ascii\n"); + fprintf(fp,"# OpenInventor file written by the visualization toolkit\n\n"); + + fprintf(fp, "Separator {\n"); + VTK_INDENT_MORE; + + // do the camera + cam = ren->GetActiveCamera(); + if (cam->GetParallelProjection()) + { + fprintf(fp,"%sOrthographicCamera\n%s{\n", indent, indent); + } + else + { + // this assumes the aspect ratio is 1 + fprintf(fp,"%sPerspectiveCamera\n%s{\n%s heightAngle %f\n", + indent, indent, indent, + cam->GetViewAngle()*3.1415926/180.0); + } + VTK_INDENT_MORE; + fprintf(fp,"%snearDistance %f\n",indent, cam->GetClippingRange()[0]); + fprintf(fp,"%sfarDistance %f\n",indent, cam->GetClippingRange()[1]); + fprintf(fp,"%sfocalDistance %f\n",indent, cam->GetDistance()); + fprintf(fp,"%sposition %f %f %f\n", indent, cam->GetPosition()[0], + cam->GetPosition()[1], cam->GetPosition()[2]); + tempd = cam->GetOrientationWXYZ(); + fprintf(fp,"%sorientation %g %g %g %g\n%s}\n", indent, + tempd[1], tempd[2], tempd[3], tempd[0]*3.1415926/180.0, indent); + VTK_INDENT_LESS; + + // do the lights first the ambient then the others + fprintf(fp,"# The following environment information is disabled\n"); + fprintf(fp,"# because a popular viewer (Template Graphics Software SceneViewer) has\n"); + fprintf(fp,"# trouble (access violations under Windows NT) with it.\n"); + fprintf(fp,"#%sEnvironment {\n", indent); + // couldn't figure out a way to do headlight -- seems to be a property of the + // viewer not the model + VTK_INDENT_MORE; + fprintf(fp,"#%sambientIntensity 1.0 # ambient light\n", indent); + fprintf(fp,"#%sambientColor %f %f %f }\n\n", indent, + ren->GetAmbient()[0], ren->GetAmbient()[1], ren->GetAmbient()[2]); + VTK_INDENT_LESS; + + // make sure we have a default light + // if we dont then use a headlight + lc = ren->GetLights(); + vtkCollectionSimpleIterator lsit; + for (lc->InitTraversal(lsit); (aLight = lc->GetNextLight(lsit)); ) + { + this->WriteALight(aLight, fp); + } + + // do the actors now + ac = ren->GetActors(); + vtkAssemblyPath *apath; + vtkCollectionSimpleIterator ait; + for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); ) + { + for (anActor->InitPathTraversal(); (apath=anActor->GetNextPath()); ) + { + aPart=(vtkActor *)apath->GetLastNode()->GetViewProp(); + this->WriteAnActor(aPart, fp); + } + } + + VTK_INDENT_LESS; + fprintf(fp, "}\n"); // close Separator + + fclose(fp); +} + +void vtkIVExporter::WriteALight(vtkLight *aLight, FILE *fp) +{ + double *pos, *focus, *color; + float dir[3]; + + pos = aLight->GetPosition(); + focus = aLight->GetFocalPoint(); + color = aLight->GetColor(); + + dir[0] = focus[0] - pos[0]; + dir[1] = focus[1] - pos[1]; + dir[2] = focus[2] - pos[2]; + vtkMath::Normalize(dir); + + if (aLight->GetPositional()) + { + double *attn; + + if (aLight->GetConeAngle() >= 180.0) + { + fprintf(fp,"%sPointLight {\n", indent); + VTK_INDENT_MORE; + } + else + { + fprintf(fp,"%sSpotLight {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%sdirection %f %f %f\n", indent, dir[0], dir[1], dir[2]); + fprintf(fp,"%scutOffAngle %f\n", indent, aLight->GetConeAngle()); + // the following ignores linear and quadratic attenuation values + attn = aLight->GetAttenuationValues(); + fprintf(fp,"%sdropOffRate %f\n", indent, attn[0]); + } + fprintf(fp,"%slocation %f %f %f\n", indent, pos[0], pos[1], pos[2]); + } + else + { + fprintf(fp,"%sDirectionalLight {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%sdirection %f %f %f\n", indent, dir[0], dir[1], dir[2]); + } + + fprintf(fp,"%scolor %f %f %f\n", indent, color[0], color[1], color[2]); + fprintf(fp,"%sintensity %f\n", indent, aLight->GetIntensity()); + if (aLight->GetSwitch()) + { + fprintf(fp,"%son TRUE\n%s}\n", indent, indent); + } + else + { + fprintf(fp,"%son FALSE\n%s}\n", indent, indent); + } + VTK_INDENT_LESS; +} + +void vtkIVExporter::WriteAnActor(vtkActor *anActor, FILE *fp) +{ + vtkDataSet *ds; + vtkPolyData *pd; + vtkGeometryFilter *gf = NULL; + vtkPointData *pntData; + vtkPoints *points; + vtkDataArray *normals = NULL; + vtkDataArray *tcoords = NULL; + int i; + vtkProperty *prop; + double *tempd; + vtkCellArray *cells; + vtkIdType npts = 0; + vtkIdType *indx = 0; + float tempf2; + vtkPolyDataMapper *pm; + vtkUnsignedCharArray *colors; + double *p; + unsigned char *c; + vtkTransform *trans; + + // see if the actor has a mapper. it could be an assembly + if (anActor->GetMapper() == NULL) + { + return; + } + + fprintf(fp,"%sSeparator {\n", indent); + VTK_INDENT_MORE; + + // first stuff out the transform + trans = vtkTransform::New(); + trans->SetMatrix(anActor->vtkProp3D::GetMatrix()); + + fprintf(fp,"%sTransform {\n", indent); + VTK_INDENT_MORE; + tempd = trans->GetPosition(); + fprintf(fp,"%stranslation %g %g %g\n", indent, tempd[0], tempd[1], tempd[2]); + tempd = trans->GetOrientationWXYZ(); + fprintf(fp,"%srotation %g %g %g %g\n", indent, tempd[1], tempd[2], + tempd[3], tempd[0]*3.1415926/180.0); + tempd = trans->GetScale(); + fprintf(fp,"%sscaleFactor %g %g %g\n", indent, tempd[0], tempd[1], tempd[2]); + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + trans->Delete(); + + // get the mappers input and matrix + ds = anActor->GetMapper()->GetInput(); + + // we really want polydata + if ( ds->GetDataObjectType() != VTK_POLY_DATA ) + { + gf = vtkGeometryFilter::New(); + gf->SetInput(ds); + gf->Update(); + pd = gf->GetOutput(); + } + else + { + ds->Update(); + pd = (vtkPolyData *)ds; + } + + pm = vtkPolyDataMapper::New(); + pm->SetInput(pd); + pm->SetScalarRange(anActor->GetMapper()->GetScalarRange()); + pm->SetScalarVisibility(anActor->GetMapper()->GetScalarVisibility()); + pm->SetLookupTable(anActor->GetMapper()->GetLookupTable()); + + points = pd->GetPoints(); + pntData = pd->GetPointData(); + normals = pntData->GetNormals(); + tcoords = pntData->GetTCoords(); + colors = pm->MapScalars(1.0); + + fprintf(fp,"%sMaterial {\n", indent); + VTK_INDENT_MORE; + + // write out the material properties to the mat file + prop = anActor->GetProperty(); + // the following is based on a guess about how VTK's GetAmbient + // property corresponds to SoMaterial's ambientColor + tempf2 = prop->GetAmbient(); + tempd = prop->GetAmbientColor(); + fprintf(fp,"%sambientColor %g %g %g\n", indent, + tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); + tempf2 = prop->GetDiffuse(); + tempd = prop->GetDiffuseColor(); + fprintf(fp,"%sdiffuseColor %g %g %g\n", indent, + tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); + tempf2 = prop->GetSpecular(); + tempd = prop->GetSpecularColor(); + fprintf(fp,"%sspecularColor %g %g %g\n", indent, + tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); + fprintf(fp,"%sshininess %g\n", indent,prop->GetSpecularPower()/128.0); + fprintf(fp,"%stransparency %g\n", indent,1.0 - prop->GetOpacity()); + fprintf(fp,"%s}\n", indent); // close matrial + VTK_INDENT_LESS; + + // is there a texture map + if (anActor->GetTexture()) + { + vtkTexture *aTexture = anActor->GetTexture(); + int *size, xsize, ysize, bpp; + vtkDataArray *scalars; + vtkUnsignedCharArray *mappedScalars; + unsigned char *txtrData; + int totalValues; + + // make sure it is updated and then get some info + if (aTexture->GetInput() == NULL) + { + vtkErrorMacro(<< "texture has no input!\n"); + return; + } + aTexture->GetInput()->Update(); + size = aTexture->GetInput()->GetDimensions(); + scalars = aTexture->GetInput()->GetPointData()->GetScalars(); + + // make sure scalars are non null + if (!scalars) + { + vtkErrorMacro(<< "No scalar values found for texture input!\n"); + return; + } + + // make sure using unsigned char data of color scalars type + if (aTexture->GetMapColorScalarsThroughLookupTable () || + (scalars->GetDataType() != VTK_UNSIGNED_CHAR) ) + { + mappedScalars = aTexture->GetMappedScalars (); + } + else + { + mappedScalars = static_cast(scalars); + } + + // we only support 2d texture maps right now + // so one of the three sizes must be 1, but it + // could be any of them, so lets find it + if (size[0] == 1) + { + xsize = size[1]; ysize = size[2]; + } + else + { + xsize = size[0]; + if (size[1] == 1) + { + ysize = size[2]; + } + else + { + ysize = size[1]; + if (size[2] != 1) + { + vtkErrorMacro(<< "3D texture maps currently are not supported!\n"); + return; + } + } + } + + fprintf(fp, "%sTexture2 {\n", indent); + VTK_INDENT_MORE; + bpp = mappedScalars->GetNumberOfComponents(); + fprintf(fp, "%simage %d %d %d\n", indent, xsize, ysize, bpp); + VTK_INDENT_MORE; + txtrData = static_cast(mappedScalars)->GetPointer(0); + totalValues = xsize*ysize; + fprintf(fp,"%s",indent); + for (i = 0; i < totalValues; i++) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + if (bpp > 1) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (bpp > 2) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (bpp > 3) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (i%8 == 0) + { + fprintf(fp,"\n%s ", indent); + } + else + { + fprintf(fp," "); + } + } + VTK_INDENT_LESS; + fprintf(fp, "%s}\n", indent); + VTK_INDENT_LESS; + } + + // write out point data if any + this->WritePointData(points, normals, tcoords, colors, fp); + + // write out polys if any + if (pd->GetNumberOfPolys() > 0) + { + fprintf(fp,"%sIndexedFaceSet {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%scoordIndex [\n", indent); + VTK_INDENT_MORE; + + cells = pd->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp,"%s", indent); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ",(int)indx[i]); + if (((i+1)%10) == 0) + { + fprintf(fp, "\n%s ", indent); + } + } + fprintf(fp,"-1,\n"); + } + fprintf(fp,"%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + } + + // write out tstrips if any + if (pd->GetNumberOfStrips() > 0) + { + fprintf(fp,"%sIndexedTriangleStripSet {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%scoordIndex [\n", indent); + VTK_INDENT_MORE; + cells = pd->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp,"%s", indent); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + if (((i+1)%10) == 0) + { + fprintf(fp, "\n%s ", indent); + } + } + fprintf(fp,"-1,\n"); + } + fprintf(fp,"%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + } + + // write out lines if any + if (pd->GetNumberOfLines() > 0) + { + fprintf(fp,"%sIndexedLineSet {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%scoordIndex [\n", indent); + VTK_INDENT_MORE; + cells = pd->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp,"%s", indent); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + if (((i+1)%10) == 0) + { + fprintf(fp, "\n%s ", indent); + } + } + fprintf(fp,"-1,\n"); + } + fprintf(fp,"%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + } + + // write out verts if any + // (more complex because there is no IndexedPointSet) + if (pd->GetNumberOfVerts() > 0) + { + fprintf(fp, "%sSeparator {\n", indent); + VTK_INDENT_MORE; + fprintf(fp, "%sCoordinate3 {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%spoint [", indent); + VTK_INDENT_MORE; + cells = pd->GetVerts(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + for (i = 0; i < npts; i++) + { + p = points->GetPoint(indx[i]); + fprintf (fp,"%s%g %g %g,\n", indent, p[0], p[1], p[2]); + } + } + fprintf(fp,"%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + if (colors) + { + fprintf(fp,"%sPackedColor {", indent); + VTK_INDENT_MORE; + fprintf(fp,"%srgba [\n", indent); + VTK_INDENT_MORE; + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp,"%s", indent); + for (i = 0; i < npts; i++) + { + c = colors->GetPointer(4*indx[i]); + fprintf (fp,"%#lx, ", + ((unsigned long)c[3] << 24) | + (((unsigned long)c[2])<<16) | + (((unsigned long)c[1])<<8) | + ((unsigned long)c[0])); + + if (((i+1)%5) == 0) + { + fprintf(fp, "\n%s", indent); + } + } + } + fprintf(fp,"\n%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%sMaterialBinding { value PER_VERTEX_INDEXED }\n", indent); + } + + fprintf(fp, "%sPointSet {\n", indent); + VTK_INDENT_MORE; + // treating vtkIdType as int + fprintf(fp, "%snumPoints %d\n", indent, (int)npts); + VTK_INDENT_MORE; + fprintf(fp, "%s}\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); // close the Separator + VTK_INDENT_LESS; + } + fprintf(fp, "%s}\n", indent); + VTK_INDENT_LESS; + if (gf) + { + gf->Delete(); + } + pm->Delete(); +} + +void vtkIVExporter::WritePointData(vtkPoints *points, vtkDataArray *normals, + vtkDataArray *tcoords, + vtkUnsignedCharArray *colors, FILE *fp) +{ + double *p; + int i; + unsigned char *c; + + // write out the points + fprintf(fp,"%sCoordinate3 {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%spoint [\n", indent); + VTK_INDENT_MORE; + for (i = 0; i < points->GetNumberOfPoints(); i++) + { + p = points->GetPoint(i); + fprintf (fp,"%s%g %g %g,\n", indent, p[0], p[1], p[2]); + } + fprintf(fp,"%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + + // write out the point data + if (normals) + { + fprintf(fp,"%sNormal {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%svector [\n", indent); + VTK_INDENT_MORE; + for (i = 0; i < normals->GetNumberOfTuples(); i++) + { + p = normals->GetTuple(i); + fprintf (fp,"%s%g %g %g,\n", indent, p[0], p[1], p[2]); + } + fprintf(fp,"%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + } + + // write out the point data + if (tcoords) + { + fprintf(fp,"%sTextureCoordinateBinding {\n",indent); + VTK_INDENT_MORE; + fprintf(fp,"%svalue PER_VERTEX_INDEXED\n",indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n",indent); + fprintf(fp,"%sTextureCoordinate2 {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%spoint [\n", indent); + VTK_INDENT_MORE; + for (i = 0; i < tcoords->GetNumberOfTuples(); i++) + { + p = tcoords->GetTuple(i); + fprintf (fp,"%s%g %g,\n", indent, p[0], p[1]); + } + fprintf(fp,"%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + } + + // write out the point data + if (colors) + { + fprintf(fp,"%sPackedColor {\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%srgba [\n", indent); + VTK_INDENT_MORE; + fprintf(fp,"%s", indent); + for (i = 0; i < colors->GetNumberOfTuples(); i++) + { + c = colors->GetPointer(4*i); + fprintf (fp,"%#lx, ", + ((unsigned long)c[3] << 24) | + (((unsigned long)c[2])<<16) | + (((unsigned long)c[1])<<8) | + ((unsigned long)c[0])); + + if (((i+1)%5)==0) + { + fprintf(fp, "\n%s", indent); + } + } + fprintf(fp,"\n%s]\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%s}\n", indent); + VTK_INDENT_LESS; + fprintf(fp,"%sMaterialBinding { value PER_VERTEX_INDEXED }\n", indent); + } +} + + +void vtkIVExporter::PrintSelf(ostream& os, vtkIndent ind) +{ + this->Superclass::PrintSelf(os,ind); + + if (this->FileName) + { + os << ind << "FileName: " << this->FileName << "\n"; + } + else + { + os << ind << "FileName: (null)\n"; + } +} + diff --git a/Rendering/vtkIVExporter.h b/Rendering/vtkIVExporter.h new file mode 100644 index 0000000..21b662f --- /dev/null +++ b/Rendering/vtkIVExporter.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkIVExporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkIVExporter - export a scene into OpenInventor 2.0 format. +// .SECTION Description +// vtkIVExporter is a concrete subclass of vtkExporter that writes +// OpenInventor 2.0 files. +// +// .SECTION See Also +// vtkExporter + + +#ifndef __vtkIVExporter_h +#define __vtkIVExporter_h + +#include "vtkExporter.h" + +class vtkLight; +class vtkActor; +class vtkPoints; +class vtkDataArray; +class vtkUnsignedCharArray; + +class VTK_RENDERING_EXPORT vtkIVExporter : public vtkExporter +{ +public: + static vtkIVExporter *New(); + vtkTypeRevisionMacro(vtkIVExporter,vtkExporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the name of the OpenInventor file to write. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkIVExporter(); + ~vtkIVExporter(); + + void WriteData(); + void WriteALight(vtkLight *aLight, FILE *fp); + void WriteAnActor(vtkActor *anActor, FILE *fp); + void WritePointData(vtkPoints *points, vtkDataArray *normals, + vtkDataArray *tcoords, vtkUnsignedCharArray *colors, + FILE *fp); + char *FileName; +private: + vtkIVExporter(const vtkIVExporter&); // Not implemented. + void operator=(const vtkIVExporter&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkImageActor.cxx b/Rendering/vtkImageActor.cxx new file mode 100644 index 0000000..4068b02 --- /dev/null +++ b/Rendering/vtkImageActor.cxx @@ -0,0 +1,375 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageActor.h" + +#include "vtkGraphicsFactory.h" +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkImageActor, "$Revision: 1.19 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkImageActor); + +//---------------------------------------------------------------------------- +vtkImageActor* vtkImageActor::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkImageActor"); + return (vtkImageActor*)ret; +} + +vtkImageActor::vtkImageActor() +{ + this->Input = NULL; + this->Interpolate = 1; + this->Opacity = 1.0; + this->DisplayExtent[0] = -1; + this->DisplayExtent[1] = 0; + this->DisplayExtent[2] = 0; + this->DisplayExtent[3] = 0; + this->DisplayExtent[4] = 0; + this->DisplayExtent[5] = 0; + + vtkMath::UninitializeBounds(this->DisplayBounds); +} + +vtkImageActor::~vtkImageActor() +{ + if (this->Input) + { + this->GetInput()->UnRegister(this); + this->Input = NULL; + } +} + +int vtkImageActor::GetSliceNumber() +{ + // find the first axis with a one pixel extent and return + // its value + if (this->DisplayExtent[0] == this->DisplayExtent[1]) + { + return this->DisplayExtent[0]; + } + if (this->DisplayExtent[2] == this->DisplayExtent[3]) + { + return this->DisplayExtent[2]; + } + return this->DisplayExtent[4]; +} + +//---------------------------------------------------------------------------- +void vtkImageActor::SetDisplayExtent(int extent[6]) +{ + int idx, modified = 0; + + for (idx = 0; idx < 6; ++idx) + { + if (this->DisplayExtent[idx] != extent[idx]) + { + this->DisplayExtent[idx] = extent[idx]; + modified = 1; + } + } + + if (modified) + { + this->Modified(); + } +} +//---------------------------------------------------------------------------- +void vtkImageActor::SetDisplayExtent(int minX, int maxX, + int minY, int maxY, + int minZ, int maxZ) +{ + int extent[6]; + + extent[0] = minX; extent[1] = maxX; + extent[2] = minY; extent[3] = maxY; + extent[4] = minZ; extent[5] = maxZ; + this->SetDisplayExtent(extent); +} + + +//---------------------------------------------------------------------------- +void vtkImageActor::GetDisplayExtent(int extent[6]) +{ + int idx; + + for (idx = 0; idx < 6; ++idx) + { + extent[idx] = this->DisplayExtent[idx]; + } +} + +// Renders an actor2D's property and then it's mapper. +int vtkImageActor::RenderTranslucentGeometry(vtkViewport* viewport) +{ + vtkDebugMacro(<< "vtkImageActor::RenderTranslucentGeometry"); + + vtkImageData *input = this->GetInput(); + if (!input) + { + return 0; + } + + // render the texture map + if ( input->GetScalarType() == VTK_UNSIGNED_CHAR ) + { + if (!(this->Opacity >= 1.0 && input->GetNumberOfScalarComponents() % 2)) + { + this->Render(vtkRenderer::SafeDownCast(viewport)); + return 1; + } + } + + return 0; +} + +int vtkImageActor::RenderOpaqueGeometry(vtkViewport* viewport) +{ + vtkDebugMacro(<< "vtkImageActor::RenderOpaqueGeometry"); + + vtkImageData *input = this->GetInput(); + if (!input) + { + return 0; + } + // make sure the data is available + input->UpdateInformation(); + + // if the display extent has not been set, then compute one + int *wExtent = input->GetWholeExtent(); + if (this->DisplayExtent[0] == -1) + { + this->DisplayExtent[0] = wExtent[0]; + this->DisplayExtent[1] = wExtent[1]; + this->DisplayExtent[2] = wExtent[2]; + this->DisplayExtent[3] = wExtent[3]; + this->DisplayExtent[4] = wExtent[4]; + this->DisplayExtent[5] = wExtent[4]; + } + input->SetUpdateExtent(this->DisplayExtent); + input->PropagateUpdateExtent(); + input->UpdateData(); + + // render the texture map + if ( input->GetScalarType() == VTK_UNSIGNED_CHAR ) + { + if (this->Opacity >= 1.0 && input->GetNumberOfScalarComponents() % 2) + { + this->Render(vtkRenderer::SafeDownCast(viewport)); + return 1; + } + } + else + { + vtkErrorMacro(<<"This filter requires unsigned char scalars as input"); + } + + return 0; +} + +// Get the bounds for this Volume as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkImageActor::GetDisplayBounds() +{ + if (!this->Input) + { + return this->DisplayBounds; + } + this->Input->UpdateInformation(); + double *spacing = this->Input->GetSpacing(); + double *origin = this->Input->GetOrigin(); + + // if the display extent has not been set, then compute one + int *wExtent = this->Input->GetWholeExtent(); + if (this->DisplayExtent[0] == -1) + { + this->DisplayExtent[0] = wExtent[0]; + this->DisplayExtent[1] = wExtent[1]; + this->DisplayExtent[2] = wExtent[2]; + this->DisplayExtent[3] = wExtent[3]; + this->DisplayExtent[4] = wExtent[4]; + this->DisplayExtent[5] = wExtent[4]; + } + if (spacing[0] >= 0) + { + this->DisplayBounds[0] = this->DisplayExtent[0]*spacing[0] + origin[0]; + this->DisplayBounds[1] = this->DisplayExtent[1]*spacing[0] + origin[0]; + } + else + { + this->DisplayBounds[0] = this->DisplayExtent[1]*spacing[0] + origin[0]; + this->DisplayBounds[1] = this->DisplayExtent[0]*spacing[0] + origin[0]; + } + if (spacing[1] >= 0) + { + this->DisplayBounds[2] = this->DisplayExtent[2]*spacing[1] + origin[1]; + this->DisplayBounds[3] = this->DisplayExtent[3]*spacing[1] + origin[1]; + } + else + { + this->DisplayBounds[2] = this->DisplayExtent[3]*spacing[1] + origin[1]; + this->DisplayBounds[3] = this->DisplayExtent[2]*spacing[1] + origin[1]; + } + if (spacing[2] >= 0) + { + this->DisplayBounds[4] = this->DisplayExtent[4]*spacing[2] + origin[2]; + this->DisplayBounds[5] = this->DisplayExtent[5]*spacing[2] + origin[2]; + } + else + { + this->DisplayBounds[4] = this->DisplayExtent[5]*spacing[2] + origin[2]; + this->DisplayBounds[5] = this->DisplayExtent[4]*spacing[2] + origin[2]; + } + + return this->DisplayBounds; +} + +// Get the bounds for the displayed data as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +void vtkImageActor::GetDisplayBounds(double bounds[6]) +{ + this->GetDisplayBounds(); + for (int i=0; i<6; i++) + { + bounds[i] = this->DisplayBounds[i]; + } +} + +// Get the bounds for this Prop3D as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkImageActor::GetBounds() +{ + int i,n; + double *bounds, bbox[24], *fptr; + + bounds = this->GetDisplayBounds(); + // Check for the special case when the data bounds are unknown + if (!bounds) + { + return bounds; + } + + // fill out vertices of a bounding box + bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5]; + bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5]; + bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5]; + bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5]; + bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4]; + bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4]; + bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4]; + bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4]; + + // save the old transform + this->Transform->Push(); + this->Transform->SetMatrix(this->GetMatrix()); + + // and transform into actors coordinates + fptr = bbox; + for (n = 0; n < 8; n++) + { + this->Transform->TransformPoint(fptr,fptr); + fptr += 3; + } + + this->Transform->Pop(); + + // now calc the new bounds + this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX; + this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX; + for (i = 0; i < 8; i++) + { + for (n = 0; n < 3; n++) + { + if (bbox[i*3+n] < this->Bounds[n*2]) + { + this->Bounds[n*2] = bbox[i*3+n]; + } + if (bbox[i*3+n] > this->Bounds[n*2+1]) + { + this->Bounds[n*2+1] = bbox[i*3+n]; + } + } + } + + return this->Bounds; +} + +void vtkImageActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Input: " << this->Input << "\n"; + os << indent << "Interpolate: " << (this->Interpolate ? "On\n" : "Off\n"); + os << indent << "Opacity: " << this->Opacity << "\n"; + + int idx; + os << indent << "DisplayExtent: (" << this->DisplayExtent[0]; + for (idx = 1; idx < 6; ++idx) + { + os << ", " << this->DisplayExtent[idx]; + } + os << ")\n"; +} + +//---------------------------------------------------------------------------- +int vtkImageActor::GetWholeZMin() +{ + int *extent; + + if ( ! this->GetInput()) + { + return 0; + } + this->GetInput()->UpdateInformation(); + extent = this->GetInput()->GetWholeExtent(); + return extent[4]; +} + +//---------------------------------------------------------------------------- +int vtkImageActor::GetWholeZMax() +{ + int *extent; + + if ( ! this->GetInput()) + { + return 0; + } + this->GetInput()->UpdateInformation(); + extent = this->GetInput()->GetWholeExtent(); + return extent[5]; +} + +void vtkImageActor::SetInput(vtkImageData *args) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this + << "): setting Input to " << args ); + if (this->Input != args) + { + if (this->Input != NULL) + { + this->Input->UnRegister(this); + } + this->Input = args; + if (this->Input != NULL) + { + this->Input->Register(this); + } + this->Modified(); + } +} + diff --git a/Rendering/vtkImageActor.h b/Rendering/vtkImageActor.h new file mode 100644 index 0000000..aeb9b83 --- /dev/null +++ b/Rendering/vtkImageActor.h @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageActor - draw an image (data & properties) in a rendered 3D scene +// .SECTION Description +// vtkImageActor is used to render an image in a 3D scene. The image +// is placed at the origin of the image, and its size is controlled by the +// image dimensions and image spacing. The orientation of the image is +// orthogonal to one of the x-y-z axes depending on which plane the +// image is defined in. vtkImageActor duplicates the functionality +// of combinations of other VTK classes in a convenient, single class. + +// .SECTION Caveats +// vtkImageData requires the image to be of type unsigned char. Use a +// filter like vtkImageShiftScale to convert to unsigned char (the +// method to use is SetOutputTypeToUnsignedChar()). + +// .SECTION See Also +// vtkImageData vtkProp vtkImageShiftScale + +#ifndef __vtkImageActor_h +#define __vtkImageActor_h + +#include "vtkProp3D.h" + +class vtkPropCollection; +class vtkRenderer; +class vtkImageData; + +class VTK_RENDERING_EXPORT vtkImageActor : public vtkProp3D +{ +public: + vtkTypeRevisionMacro(vtkImageActor,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the image actor. + static vtkImageActor *New(); + + // Description: + // Set/Get the image data input for the image actor. + virtual void SetInput(vtkImageData *); + vtkGetObjectMacro(Input,vtkImageData); + + // Description: + // Turn on/off linear interpolation of the image when rendering. + vtkGetMacro(Interpolate,int); + vtkSetMacro(Interpolate,int); + vtkBooleanMacro(Interpolate,int); + + // Description: + // Set/Get the object's opacity. 1.0 is totally opaque and 0.0 is completely + // transparent. + vtkSetClampMacro(Opacity,double,0.0,1.0); + vtkGetMacro(Opacity,double); + + // Description: + // The image extent is generally set explicitly, but if not set + // it will be determined from the input image data. + void SetDisplayExtent(int extent[6]); + void SetDisplayExtent(int minX, int maxX, int minY, int maxY, + int minZ, int maxZ); + void GetDisplayExtent(int extent[6]); + int *GetDisplayExtent() {return this->DisplayExtent;} + + // Description: + // Get the bounds of this image actor. Either copy the bounds + // into a user provided array or return a pointer to an array. + // In either case the boudns is expressed as a 6-vector + // (xmin,xmax, ymin,ymax, zmin,zmax). + double *GetBounds(); + void GetBounds(double bounds[6]) { this->Superclass::GetBounds(bounds); }; + + // Description: + // Get the bounds of the data that is displayed by this image + // actor. If the transformation matrix for this actor is the + // identity matrix, this will return the same value as + // GetBounds. + double *GetDisplayBounds(); + void GetDisplayBounds(double bounds[6]); + + // Description: + // Return a slice number computed from the display extent. + int GetSliceNumber(); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Support the standard render methods. + int RenderTranslucentGeometry(vtkViewport *viewport); + int RenderOpaqueGeometry(vtkViewport *viewport); + virtual void Render(vtkRenderer *) {}; +//ETX + + // Description: + // Set/Get the current slice number. The axis Z in ZSlice does not + // necessarily have any relation to the z axis of the data on disk. + // It is simply the axis orthogonal to the x,y, display plane. + // GetWholeZMax and Min are convenience methods for obtaining + // the number of slices that can be displayed. Again the number + // of slices is in reference to the display z axis, which is not + // necessarily the z axis on disk. (due to reformatting etc) + void SetZSlice(int z) {this->SetDisplayExtent( + this->DisplayExtent[0], this->DisplayExtent[1], + this->DisplayExtent[2], this->DisplayExtent[3], z, z); + }; + + int GetZSlice() { return this->DisplayExtent[4];}; + int GetWholeZMin(); + int GetWholeZMax(); + +protected: + vtkImageActor(); + ~vtkImageActor(); + + int Interpolate; + double Opacity; + vtkImageData* Input; + int DisplayExtent[6]; + double DisplayBounds[6]; + +private: + vtkImageActor(const vtkImageActor&); // Not implemented. + void operator=(const vtkImageActor&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkImageMapper.cxx b/Rendering/vtkImageMapper.cxx new file mode 100644 index 0000000..1aba78e --- /dev/null +++ b/Rendering/vtkImageMapper.cxx @@ -0,0 +1,282 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkImageMapper.h" + +#include "vtkActor2D.h" +#include "vtkExecutive.h" +#include "vtkImageData.h" +#include "vtkImagingFactory.h" +#include "vtkInformation.h" +#include "vtkViewport.h" +#include "vtkWindow.h" + + +vtkCxxRevisionMacro(vtkImageMapper, "$Revision: 1.52 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkImageMapper); + +//---------------------------------------------------------------------------- + +#define VTK_RINT(x) ((x > 0.0) ? (int)(x + 0.5) : (int)(x - 0.5)) + +vtkImageMapper::vtkImageMapper() +{ + vtkDebugMacro(<< "vtkImageMapper::vtkImageMapper" ); + + this->ColorWindow = 2000; + this->ColorLevel = 1000; + + this->DisplayExtent[0] = this->DisplayExtent[1] = 0; + this->DisplayExtent[2] = this->DisplayExtent[3] = 0; + this->DisplayExtent[4] = this->DisplayExtent[5] = 0; + this->ZSlice = 0; + + this->RenderToRectangle = 0; + this->UseCustomExtents = 0; + this->CustomDisplayExtents[0] = this->CustomDisplayExtents[1] = 0; + this->CustomDisplayExtents[2] = this->CustomDisplayExtents[3] = 0; + +} + +vtkImageMapper::~vtkImageMapper() +{ +} + +//---------------------------------------------------------------------------- +void vtkImageMapper::SetInput(vtkImageData *input) +{ + if(input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(0, 0); + } +} + +//---------------------------------------------------------------------------- +vtkImageData *vtkImageMapper::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +unsigned long int vtkImageMapper::GetMTime() +{ + unsigned long mTime=this->vtkMapper2D::GetMTime(); + return mTime; +} + +void vtkImageMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Color Window: " << this->ColorWindow << "\n"; + os << indent << "Color Level: " << this->ColorLevel << "\n"; + os << indent << "ZSlice: " << this->ZSlice << "\n"; + os << indent << "RenderToRectangle: " << this->RenderToRectangle << "\n"; + os << indent << "UseCustomExtents: " << this->UseCustomExtents << "\n"; + os << indent << "CustomDisplayExtents: " << + this->CustomDisplayExtents[0] << " " << + this->CustomDisplayExtents[1] << " " << + this->CustomDisplayExtents[2] << " " << + this->CustomDisplayExtents[3] << "\n"; + // +} + +vtkImageMapper* vtkImageMapper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkImagingFactory::CreateInstance("vtkImageMapper"); + return (vtkImageMapper*)ret; +} + +double vtkImageMapper::GetColorShift() +{ + return this->ColorWindow /2.0 - this->ColorLevel; +} + +double vtkImageMapper::GetColorScale() +{ + return 255.0 / this->ColorWindow; +} + +void vtkImageMapper::RenderStart(vtkViewport* viewport, vtkActor2D* actor) +{ + vtkDebugMacro(<< "vtkImageMapper::RenderOverlay"); + + vtkImageData *data; + + if (!viewport) + { + vtkErrorMacro (<< "vtkImageMapper::Render - Null viewport argument"); + return; + } + + if (!actor) + { + vtkErrorMacro (<<"vtkImageMapper::Render - Null actor argument"); + return; + } + + + if (!this->GetInput()) + { + vtkDebugMacro(<< "vtkImageMapper::Render - Please Set the input."); + return; + } + + this->GetInput()->UpdateInformation(); + + if (!this->UseCustomExtents) + { + // start with the wholeExtent + int wholeExtent[6]; + memcpy(wholeExtent,this->GetInput()->GetWholeExtent(),6*sizeof(int)); + memcpy(this->DisplayExtent, + this->GetInput()->GetWholeExtent(),6*sizeof(int)); + // Set The z values to the zslice + this->DisplayExtent[4] = this->ZSlice; + this->DisplayExtent[5] = this->ZSlice; + + // scale currently not handled + //double *scale = actor->GetScale(); + + // get the position + int *pos = + actor->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + // Get the viewport coordinates + double vCoords[4]; + vCoords[0] = 0.0; + vCoords[1] = 0.0; + vCoords[2] = 1.0; + vCoords[3] = 1.0; + viewport->NormalizedViewportToViewport(vCoords[0],vCoords[1]); + viewport->NormalizedViewportToViewport(vCoords[2],vCoords[3]); + int *vSize = viewport->GetSize(); + + // the basic formula is that the draw pos equals + // the pos + extentPos + clippedAmount + // The concrete subclass will get the pos in display + // coordinates so we need to provide the extentPos plus + // clippedAmount in the PositionAdjustment variable + + // Now clip to imager extents + if (pos[0] + wholeExtent[0] < 0) + { + this->DisplayExtent[0] = -pos[0]; + } + if ((pos[0]+wholeExtent[1]) > vSize[0]) + { + this->DisplayExtent[1] = vSize[0] - pos[0]; + } + if (pos[1] + wholeExtent[2] < 0) + { + this->DisplayExtent[2] = -pos[1]; + } + if ((pos[1]+wholeExtent[3]) > vSize[1]) + { + this->DisplayExtent[3] = vSize[1] - pos[1]; + } + + // check for the condition where no pixels are visible. + if (this->DisplayExtent[0] > wholeExtent[1] || + this->DisplayExtent[1] < wholeExtent[0] || + this->DisplayExtent[2] > wholeExtent[3] || + this->DisplayExtent[3] < wholeExtent[2] || + this->DisplayExtent[4] > wholeExtent[5] || + this->DisplayExtent[5] < wholeExtent[4]) + { + return; + } + + this->GetInput()->SetUpdateExtent(this->DisplayExtent); + + // set the position adjustment + this->PositionAdjustment[0] = this->DisplayExtent[0]; + this->PositionAdjustment[1] = this->DisplayExtent[2]; + } + else // UseCustomExtents + { + this->DisplayExtent[0] = this->CustomDisplayExtents[0]; + this->DisplayExtent[1] = this->CustomDisplayExtents[1]; + this->DisplayExtent[2] = this->CustomDisplayExtents[2]; + this->DisplayExtent[3] = this->CustomDisplayExtents[3]; + this->DisplayExtent[4] = this->ZSlice; + this->DisplayExtent[5] = this->ZSlice; + // + this->GetInput()->SetUpdateExtentToWholeExtent(); + // clear the position adjustment + this->PositionAdjustment[0] = 0; + this->PositionAdjustment[1] = 0; + } + + // Get the region from the input + this->GetInput()->Update(); + data = this->GetInput(); + if ( !data) + { + vtkErrorMacro(<< "Render: Could not get data from input."); + return; + } + + this->RenderData(viewport, data, actor); +} + +//---------------------------------------------------------------------------- +int vtkImageMapper::GetWholeZMin() +{ + int *extent; + + if ( ! this->GetInput()) + { + return 0; + } + this->GetInput()->UpdateInformation(); + extent = this->GetInput()->GetWholeExtent(); + return extent[4]; +} + +//---------------------------------------------------------------------------- +int vtkImageMapper::GetWholeZMax() +{ + int *extent; + + if ( ! this->GetInput()) + { + return 0; + } + this->GetInput()->UpdateInformation(); + extent = this->GetInput()->GetWholeExtent(); + return extent[5]; +} + +//---------------------------------------------------------------------------- +int vtkImageMapper::FillInputPortInformation( + int vtkNotUsed( port ), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} diff --git a/Rendering/vtkImageMapper.h b/Rendering/vtkImageMapper.h new file mode 100644 index 0000000..7c99f43 --- /dev/null +++ b/Rendering/vtkImageMapper.h @@ -0,0 +1,137 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageMapper - 2D image display +// .SECTION Description +// vtkImageMapper provides 2D image display support for vtk. +// It is a Mapper2D subclass that can be associated with an Actor2D +// and placed within a RenderWindow or ImageWindow. + +// .SECTION See Also +// vtkMapper2D vtkActor2D + +#ifndef __vtkImageMapper_h +#define __vtkImageMapper_h + +#include "vtkMapper2D.h" + +class vtkWindow; +class vtkViewport; +class vtkActor2D; +class vtkImageData; + +class VTK_RENDERING_EXPORT vtkImageMapper : public vtkMapper2D +{ +public: + vtkTypeRevisionMacro(vtkImageMapper,vtkMapper2D); + static vtkImageMapper *New(); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Override Modifiedtime as we have added a lookuptable + unsigned long int GetMTime(); + + // Description: + // Set/Get the window value for window/level + vtkSetMacro(ColorWindow, double); + vtkGetMacro(ColorWindow, double); + + // Description: + // Set/Get the level value for window/level + vtkSetMacro(ColorLevel, double); + vtkGetMacro(ColorLevel, double); + + // Description: + // Set/Get the current slice number. The axis Z in ZSlice does not + // necessarily have any relation to the z axis of the data on disk. + // It is simply the axis orthogonal to the x,y, display plane. + // GetWholeZMax and Min are convenience methods for obtaining + // the number of slices that can be displayed. Again the number + // of slices is in reference to the display z axis, which is not + // necessarily the z axis on disk. (due to reformatting etc) + vtkSetMacro(ZSlice,int); + vtkGetMacro(ZSlice,int); + int GetWholeZMin(); + int GetWholeZMax(); + + // Description: + // Draw the image to the screen. + void RenderStart(vtkViewport* viewport, vtkActor2D* actor); + + // Description: + // Function called by Render to actually draw the image to to the screen + virtual void RenderData(vtkViewport*, vtkImageData*, vtkActor2D* )=0; + + // Description: + // Methods used internally for performing the Window/Level mapping. + double GetColorShift(); + double GetColorScale(); + + // Public for templated functions. * * Should remove this * * + int DisplayExtent[6]; + + // Description: + // Set the Input of a filter. + virtual void SetInput(vtkImageData *input); + vtkImageData *GetInput(); + + // Description: + // If RenderToRectangle is set (by default not), then the imagemapper + // will render the image into the rectangle supplied by the Actor2D's + // PositionCoordinate and Position2Coordinate + vtkSetMacro(RenderToRectangle,int); + vtkGetMacro(RenderToRectangle,int); + vtkBooleanMacro(RenderToRectangle,int); + + // Description: + // Usually, the entire image is displayed, if UseCustomExtents + // is set (by default not), then the region supplied in the + // CustomDisplayExtents is used in preference. + // Note that the Custom extents are x,y only and the zslice is still + // applied + vtkSetMacro(UseCustomExtents,int); + vtkGetMacro(UseCustomExtents,int); + vtkBooleanMacro(UseCustomExtents,int); + + // Description: + // The image extents which should be displayed with UseCustomExtents + // Note that the Custom extents are x,y only and the zslice is still + // applied + vtkSetVectorMacro(CustomDisplayExtents,int,4); + vtkGetVectorMacro(CustomDisplayExtents,int,4); + +protected: + vtkImageMapper(); + ~vtkImageMapper(); + + double ColorWindow; + double ColorLevel; + + int PositionAdjustment[2]; + int ZSlice; + int UseCustomExtents; + int CustomDisplayExtents[4]; + int RenderToRectangle; + + virtual int FillInputPortInformation(int, vtkInformation*); +private: + vtkImageMapper(const vtkImageMapper&); // Not implemented. + void operator=(const vtkImageMapper&); // Not implemented. +}; + + + +#endif + + diff --git a/Rendering/vtkImageViewer.cxx b/Rendering/vtkImageViewer.cxx new file mode 100644 index 0000000..5c19e57 --- /dev/null +++ b/Rendering/vtkImageViewer.cxx @@ -0,0 +1,300 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageViewer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageViewer.h" + +#include "vtkActor2D.h" +#include "vtkCommand.h" +#include "vtkImageData.h" +#include "vtkInteractorStyleImage.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkImageViewer, "$Revision: 1.51 $"); +vtkStandardNewMacro(vtkImageViewer); + +//---------------------------------------------------------------------------- +vtkImageViewer::vtkImageViewer() +{ + this->RenderWindow = vtkRenderWindow::New(); + this->Renderer = vtkRenderer::New(); + this->ImageMapper = vtkImageMapper::New(); + this->Actor2D = vtkActor2D::New(); + + // setup the pipeline + this->Actor2D->SetMapper(this->ImageMapper); + this->Renderer->AddActor2D(this->Actor2D); + this->RenderWindow->AddRenderer(this->Renderer); + + this->FirstRender = 1; + + this->Interactor = 0; + this->InteractorStyle = 0; +} + + +//---------------------------------------------------------------------------- +vtkImageViewer::~vtkImageViewer() +{ + this->ImageMapper->Delete(); + this->Actor2D->Delete(); + this->RenderWindow->Delete(); + this->Renderer->Delete(); + + if (this->Interactor) + { + this->Interactor->Delete(); + } + if (this->InteractorStyle) + { + this->InteractorStyle->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageViewer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "ImageMapper:\n"; + this->ImageMapper->PrintSelf(os, indent.GetNextIndent()); + os << indent << "RenderWindow:\n"; + this->RenderWindow->PrintSelf(os, indent.GetNextIndent()); + os << indent << "Renderer:\n"; + this->Renderer->PrintSelf(os, indent.GetNextIndent()); + os << indent << "Actor2D:\n"; + this->Actor2D->PrintSelf(os, indent.GetNextIndent()); +} + + + +//---------------------------------------------------------------------------- +void vtkImageViewer::SetSize(int a[2]) +{ + this->SetSize(a[0],a[1]); +} +//---------------------------------------------------------------------------- +void vtkImageViewer::SetPosition(int a[2]) +{ + this->SetPosition(a[0],a[1]); +} + +//---------------------------------------------------------------------------- +class vtkImageViewerCallback : public vtkCommand +{ +public: + static vtkImageViewerCallback *New() { return new vtkImageViewerCallback; } + + void Execute(vtkObject *caller, + unsigned long event, + void *vtkNotUsed(callData)) + { + if (this->IV->GetInput() == NULL) + { + return; + } + + // Reset + + if (event == vtkCommand::ResetWindowLevelEvent) + { + this->IV->GetInput()->UpdateInformation(); + this->IV->GetInput()->SetUpdateExtent + (this->IV->GetInput()->GetWholeExtent()); + this->IV->GetInput()->Update(); + double *range = this->IV->GetInput()->GetScalarRange(); + this->IV->SetColorWindow(range[1] - range[0]); + this->IV->SetColorLevel(0.5 * (range[1] + range[0])); + this->IV->Render(); + return; + } + + // Start + + if (event == vtkCommand::StartWindowLevelEvent) + { + this->InitialWindow = this->IV->GetColorWindow(); + this->InitialLevel = this->IV->GetColorLevel(); + return; + } + + // Adjust the window level here + + vtkInteractorStyleImage *isi = + static_cast(caller); + + int *size = this->IV->GetRenderWindow()->GetSize(); + double window = this->InitialWindow; + double level = this->InitialLevel; + + // Compute normalized delta + + double dx = 4.0 * (isi->GetWindowLevelCurrentPosition()[0] - + isi->GetWindowLevelStartPosition()[0]) / size[0]; + double dy = 4.0 * (isi->GetWindowLevelStartPosition()[1] - + isi->GetWindowLevelCurrentPosition()[1]) / size[1]; + + // Scale by current values + + if (fabs(window) > 0.01) + { + dx = dx * window; + } + else + { + dx = dx * (window < 0 ? -0.01 : 0.01); + } + if (fabs(level) > 0.01) + { + dy = dy * level; + } + else + { + dy = dy * (level < 0 ? -0.01 : 0.01); + } + + // Abs so that direction does not flip + + if (window < 0.0) + { + dx = -1*dx; + } + if (level < 0.0) + { + dy = -1*dy; + } + + // Compute new window level + + double newWindow = dx + window; + double newLevel; + newLevel = level - dy; + + // Stay away from zero and really + + if (fabs(newWindow) < 0.01) + { + newWindow = 0.01*(newWindow < 0 ? -1 : 1); + } + if (fabs(newLevel) < 0.01) + { + newLevel = 0.01*(newLevel < 0 ? -1 : 1); + } + + this->IV->SetColorWindow(newWindow); + this->IV->SetColorLevel(newLevel); + this->IV->Render(); + } + + vtkImageViewer *IV; + double InitialWindow; + double InitialLevel; +}; + +//---------------------------------------------------------------------------- +void vtkImageViewer::SetupInteractor(vtkRenderWindowInteractor *rwi) +{ + if (this->Interactor && rwi != this->Interactor) + { + this->Interactor->Delete(); + } + if (!this->InteractorStyle) + { + this->InteractorStyle = vtkInteractorStyleImage::New(); + vtkImageViewerCallback *cbk = vtkImageViewerCallback::New(); + cbk->IV = this; + this->InteractorStyle->AddObserver(vtkCommand::WindowLevelEvent, cbk); + this->InteractorStyle->AddObserver(vtkCommand::StartWindowLevelEvent, cbk); + this->InteractorStyle->AddObserver(vtkCommand::ResetWindowLevelEvent, cbk); + cbk->Delete(); + } + + if (!this->Interactor) + { + this->Interactor = rwi; + rwi->Register(this); + } + this->Interactor->SetInteractorStyle(this->InteractorStyle); + this->Interactor->SetRenderWindow(this->RenderWindow); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer::Render() +{ + if (this->FirstRender) + { + // initialize the size if not set yet + if (this->RenderWindow->GetSize()[0] == 0 && this->ImageMapper->GetInput()) + { + // get the size from the mappers input + this->ImageMapper->GetInput()->UpdateInformation(); + int *ext = this->ImageMapper->GetInput()->GetWholeExtent(); + // if it would be smaller than 150 by 100 then limit to 150 by 100 + int xs = ext[1] - ext[0] + 1; + int ys = ext[3] - ext[2] + 1; + this->RenderWindow->SetSize(xs < 150 ? 150 : xs, + ys < 100 ? 100 : ys); + } + this->FirstRender = 0; + } + this->RenderWindow->Render(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer::SetOffScreenRendering(int i) +{ + this->RenderWindow->SetOffScreenRendering(i); +} + +//---------------------------------------------------------------------------- +int vtkImageViewer::GetOffScreenRendering() +{ + return this->RenderWindow->GetOffScreenRendering(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer::OffScreenRenderingOn() +{ + this->SetOffScreenRendering(1); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer::OffScreenRenderingOff() +{ + this->SetOffScreenRendering(0); +} + +#ifndef VTK_LEGACY_REMOVE +int vtkImageViewer::GetGrayScaleHint() +{ + vtkWarningMacro("GetGrayScaleHint deprecated, not required anymore"); + return 0; +} + +void vtkImageViewer::SetGrayScaleHint(int vtkNotUsed(a)) +{ + vtkWarningMacro("SetGrayScaleHint deprecated, not required anymore"); +} + +void vtkImageViewer::GrayScaleHintOn() +{ + vtkWarningMacro("GrayScaleHintOn deprecated, not required anymore"); +} + +void vtkImageViewer::GrayScaleHintOff() +{ + vtkWarningMacro("GrayScaleHintOff deprecated, not required anymore"); +} +#endif + diff --git a/Rendering/vtkImageViewer.h b/Rendering/vtkImageViewer.h new file mode 100644 index 0000000..719ed7f --- /dev/null +++ b/Rendering/vtkImageViewer.h @@ -0,0 +1,141 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageViewer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageViewer - Display a 2d image. +// .SECTION Description +// vtkImageViewer is a convenience class for displaying a 2d image. It +// packages up the functionality found in vtkRenderWindow, vtkRenderer, +// vtkActor2D and vtkImageMapper into a single easy to use class. Behind the +// scenes these four classes are actually used to to provide the required +// functionality. vtkImageViewer is simply a wrapper around them. + +// .SECTION See Also +// vtkRenderWindow vtkRenderer vtkImageMapper vtkActor2D + +#ifndef __vtkImageViewer_h +#define __vtkImageViewer_h + +#include "vtkObject.h" + +#include "vtkImageMapper.h" // For all the inline methods +#include "vtkRenderWindow.h" // For all the inline methods + +class vtkInteractorStyleImage; + +class VTK_RENDERING_EXPORT vtkImageViewer : public vtkObject +{ +public: + static vtkImageViewer *New(); + + vtkTypeRevisionMacro(vtkImageViewer,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get name of rendering window + char *GetWindowName() {return this->RenderWindow->GetWindowName();}; + + // Description: + // Render the resulting image. + virtual void Render(void); + + // Description: + // Set/Get the input to the viewer. + void SetInput(vtkImageData *in) {this->ImageMapper->SetInput(in);}; + vtkImageData *GetInput() { return this->ImageMapper->GetInput();}; + virtual void SetInputConnection(vtkAlgorithmOutput* input) { + this->ImageMapper->SetInputConnection(input);}; + + // Description: + // What is the possible Min/ Max z slices available. + int GetWholeZMin() {return this->ImageMapper->GetWholeZMin();}; + int GetWholeZMax() {return this->ImageMapper->GetWholeZMax();}; + + // Description: + // Set/Get the current Z Slice to display + int GetZSlice() {return this->ImageMapper->GetZSlice();}; + void SetZSlice(int s) {this->ImageMapper->SetZSlice(s);}; + + // Description: + // Sets window/level for mapping pixels to colors. + double GetColorWindow() {return this->ImageMapper->GetColorWindow();}; + double GetColorLevel() {return this->ImageMapper->GetColorLevel();}; + void SetColorWindow(double s) {this->ImageMapper->SetColorWindow(s);}; + void SetColorLevel(double s) {this->ImageMapper->SetColorLevel(s);}; + + // Description: + // These are here for using a tk window. + void SetDisplayId(void *a) {this->RenderWindow->SetDisplayId(a);}; + void SetWindowId(void *a) {this->RenderWindow->SetWindowId(a);}; + void SetParentId(void *a) {this->RenderWindow->SetParentId(a);}; + + // Description: + // By default this is a color viewer. GrayScaleHintOn will improve the + // appearance of gray scale images on some systems. + VTK_LEGACY(int GetGrayScaleHint()); + VTK_LEGACY(void SetGrayScaleHint(int vtkNotUsed(a))); + VTK_LEGACY(void GrayScaleHintOn()); + VTK_LEGACY(void GrayScaleHintOff()); + + // Description: + // Set/Get the position in screen coordinates of the rendering window. + int *GetPosition() {return this->RenderWindow->GetPosition();}; + void SetPosition(int a,int b) {this->RenderWindow->SetPosition(a,b);}; + virtual void SetPosition(int a[2]); + + // Description: + // Set/Get the size of the window in screen coordinates. + int *GetSize() {return this->RenderWindow->GetSize();}; + void SetSize(int a,int b) {this->RenderWindow->SetSize(a,b);}; + virtual void SetSize(int a[2]); + + // Description: + // Get the internal objects + vtkGetObjectMacro(RenderWindow,vtkRenderWindow); + vtkGetObjectMacro(Renderer, vtkRenderer); + vtkGetObjectMacro(ImageMapper,vtkImageMapper); + vtkGetObjectMacro(Actor2D,vtkActor2D); + + // Description: + // Create and attach an interactor for this window + void SetupInteractor(vtkRenderWindowInteractor *); + + // Description: + // Create a window in memory instead of on the screen. This may not + // be supported for every type of window and on some windows you may + // need to invoke this prior to the first render. + void SetOffScreenRendering(int); + int GetOffScreenRendering(); + void OffScreenRenderingOn(); + void OffScreenRenderingOff(); + +protected: + vtkImageViewer(); + ~vtkImageViewer(); + + vtkRenderWindow *RenderWindow; + vtkRenderer *Renderer; + vtkImageMapper *ImageMapper; + vtkActor2D *Actor2D; + int FirstRender; + vtkRenderWindowInteractor *Interactor; + vtkInteractorStyleImage *InteractorStyle; + +private: + vtkImageViewer(const vtkImageViewer&); // Not implemented. + void operator=(const vtkImageViewer&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkImageViewer2.cxx b/Rendering/vtkImageViewer2.cxx new file mode 100644 index 0000000..8087fb1 --- /dev/null +++ b/Rendering/vtkImageViewer2.cxx @@ -0,0 +1,780 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageViewer2.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageViewer2.h" + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkImageActor.h" +#include "vtkImageData.h" +#include "vtkImageData.h" +#include "vtkImageMapToWindowLevelColors.h" +#include "vtkInteractorStyleImage.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkImageViewer2, "$Revision: 1.32.2.1 $"); +vtkStandardNewMacro(vtkImageViewer2); + +//---------------------------------------------------------------------------- +vtkImageViewer2::vtkImageViewer2() +{ + this->RenderWindow = NULL; + this->Renderer = NULL; + this->ImageActor = vtkImageActor::New(); + this->WindowLevel = vtkImageMapToWindowLevelColors::New(); + this->Interactor = NULL; + this->InteractorStyle = NULL; + + this->Slice = 0; + this->FirstRender = 1; + this->SliceOrientation = vtkImageViewer2::SLICE_ORIENTATION_XY; + + // Setup the pipeline + + vtkRenderWindow *renwin = vtkRenderWindow::New(); + this->SetRenderWindow(renwin); + renwin->Delete(); + + vtkRenderer *ren = vtkRenderer::New(); + this->SetRenderer(ren); + ren->Delete(); + + this->InstallPipeline(); +} + +//---------------------------------------------------------------------------- +vtkImageViewer2::~vtkImageViewer2() +{ + if (this->WindowLevel) + { + this->WindowLevel->Delete(); + this->WindowLevel = NULL; + } + + if (this->ImageActor) + { + this->ImageActor->Delete(); + this->ImageActor = NULL; + } + + if (this->Renderer) + { + this->Renderer->Delete(); + this->Renderer = NULL; + } + + if (this->RenderWindow) + { + this->RenderWindow->Delete(); + this->RenderWindow = NULL; + } + + if (this->Interactor) + { + this->Interactor->Delete(); + this->Interactor = NULL; + } + + if (this->InteractorStyle) + { + this->InteractorStyle->Delete(); + this->InteractorStyle = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetupInteractor(vtkRenderWindowInteractor *arg) +{ + if (this->Interactor == arg) + { + return; + } + + this->UnInstallPipeline(); + + if (this->Interactor) + { + this->Interactor->UnRegister(this); + } + + this->Interactor = arg; + + if (this->Interactor) + { + this->Interactor->Register(this); + } + + this->InstallPipeline(); + + if (this->Renderer) + { + this->Renderer->GetActiveCamera()->ParallelProjectionOn(); + } +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetRenderWindow(vtkRenderWindow *arg) +{ + if (this->RenderWindow == arg) + { + return; + } + + this->UnInstallPipeline(); + + if (this->RenderWindow) + { + this->RenderWindow->UnRegister(this); + } + + this->RenderWindow = arg; + + if (this->RenderWindow) + { + this->RenderWindow->Register(this); + } + + this->InstallPipeline(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetRenderer(vtkRenderer *arg) +{ + if (this->Renderer == arg) + { + return; + } + + this->UnInstallPipeline(); + + if (this->Renderer) + { + this->Renderer->UnRegister(this); + } + + this->Renderer = arg; + + if (this->Renderer) + { + this->Renderer->Register(this); + } + + this->InstallPipeline(); + this->UpdateOrientation(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetSize(int a,int b) +{ + this->RenderWindow->SetSize(a, b); +} + +//---------------------------------------------------------------------------- +int* vtkImageViewer2::GetSize() +{ + return this->RenderWindow->GetSize(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::GetSliceRange(int &min, int &max) +{ + vtkImageData *input = this->GetInput(); + if (input) + { + input->UpdateInformation(); + int *w_ext = input->GetWholeExtent(); + min = w_ext[this->SliceOrientation * 2]; + max = w_ext[this->SliceOrientation * 2 + 1]; + } +} + +//---------------------------------------------------------------------------- +int* vtkImageViewer2::GetSliceRange() +{ + vtkImageData *input = this->GetInput(); + if (input) + { + input->UpdateInformation(); + return input->GetWholeExtent() + this->SliceOrientation * 2; + } + return NULL; +} + +//---------------------------------------------------------------------------- +int vtkImageViewer2::GetSliceMin() +{ + int *range = this->GetSliceRange(); + if (range) + { + return range[0]; + } + return 0; +} + +//---------------------------------------------------------------------------- +int vtkImageViewer2::GetSliceMax() +{ + int *range = this->GetSliceRange(); + if (range) + { + return range[1]; + } + return 0; +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetSlice(int slice) +{ + int *range = this->GetSliceRange(); + if (range) + { + if (slice < range[0]) + { + slice = range[0]; + } + else if (slice > range[1]) + { + slice = range[1]; + } + } + + if (this->Slice == slice) + { + return; + } + + this->Slice = slice; + this->Modified(); + + this->UpdateDisplayExtent(); + this->Render(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetSliceOrientation(int orientation) +{ + if (orientation < vtkImageViewer2::SLICE_ORIENTATION_YZ || + orientation > vtkImageViewer2::SLICE_ORIENTATION_XY) + { + vtkErrorMacro("Error - invalid slice orientation " << orientation); + return; + } + + if (this->SliceOrientation == orientation) + { + return; + } + + this->SliceOrientation = orientation; + + // Update the viewer + + int *range = this->GetSliceRange(); + if (range) + { + this->Slice = static_cast((range[0] + range[1]) * 0.5); + } + + this->UpdateOrientation(); + this->UpdateDisplayExtent(); + + if (this->Renderer && this->GetInput()) + { + double scale = this->Renderer->GetActiveCamera()->GetParallelScale(); + this->Renderer->ResetCamera(); + this->Renderer->GetActiveCamera()->SetParallelScale(scale); + } + + this->Render(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::UpdateOrientation() +{ + // Set the camera position + + vtkCamera *cam = this->Renderer ? this->Renderer->GetActiveCamera() : NULL; + if (cam) + { + switch (this->SliceOrientation) + { + case vtkImageViewer2::SLICE_ORIENTATION_XY: + cam->SetFocalPoint(0,0,0); + cam->SetPosition(0,0,1); // -1 if medical ? + cam->SetViewUp(0,1,0); + break; + + case vtkImageViewer2::SLICE_ORIENTATION_XZ: + cam->SetFocalPoint(0,0,0); + cam->SetPosition(0,-1,0); // 1 if medical ? + cam->SetViewUp(0,0,1); + break; + + case vtkImageViewer2::SLICE_ORIENTATION_YZ: + cam->SetFocalPoint(0,0,0); + cam->SetPosition(1,0,0); // -1 if medical ? + cam->SetViewUp(0,0,1); + break; + } + } +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::UpdateDisplayExtent() +{ + vtkImageData *input = this->GetInput(); + if (!input || !this->ImageActor) + { + return; + } + + input->UpdateInformation(); + int *w_ext = input->GetWholeExtent(); + + // Is the slice in range ? If not, fix it + + int slice_min = w_ext[this->SliceOrientation * 2]; + int slice_max = w_ext[this->SliceOrientation * 2 + 1]; + if (this->Slice < slice_min || this->Slice > slice_max) + { + this->Slice = static_cast((slice_min + slice_max) * 0.5); + } + + // Set the image actor + + switch (this->SliceOrientation) + { + case vtkImageViewer2::SLICE_ORIENTATION_XY: + this->ImageActor->SetDisplayExtent( + w_ext[0], w_ext[1], w_ext[2], w_ext[3], this->Slice, this->Slice); + break; + + case vtkImageViewer2::SLICE_ORIENTATION_XZ: + this->ImageActor->SetDisplayExtent( + w_ext[0], w_ext[1], this->Slice, this->Slice, w_ext[4], w_ext[5]); + break; + + case vtkImageViewer2::SLICE_ORIENTATION_YZ: + this->ImageActor->SetDisplayExtent( + this->Slice, this->Slice, w_ext[2], w_ext[3], w_ext[4], w_ext[5]); + break; + } + + // Figure out the correct clipping range + + if (this->Renderer) + { + if (this->InteractorStyle && + this->InteractorStyle->GetAutoAdjustCameraClippingRange()) + { + this->Renderer->ResetCameraClippingRange(); + } + else + { + vtkCamera *cam = this->Renderer->GetActiveCamera(); + if (cam) + { + double bounds[6]; + this->ImageActor->GetBounds(bounds); + double spos = (double)bounds[this->SliceOrientation * 2]; + double cpos = (double)cam->GetPosition()[this->SliceOrientation]; + double range = fabs(spos - cpos); + double *spacing = input->GetSpacing(); + double avg_spacing = + ((double)spacing[0] + (double)spacing[1] + (double)spacing[2]) / 3.0; + cam->SetClippingRange( + range - avg_spacing * 3.0, range + avg_spacing * 3.0); + } + } + } +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetPosition(int a,int b) +{ + this->RenderWindow->SetPosition(a, b); +} + +//---------------------------------------------------------------------------- +int* vtkImageViewer2::GetPosition() +{ + return this->RenderWindow->GetPosition(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetDisplayId(void *a) +{ + this->RenderWindow->SetDisplayId(a); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetWindowId(void *a) +{ + this->RenderWindow->SetWindowId(a); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetParentId(void *a) +{ + this->RenderWindow->SetParentId(a); +} + +//---------------------------------------------------------------------------- +double vtkImageViewer2::GetColorWindow() +{ + return this->WindowLevel->GetWindow(); +} + +//---------------------------------------------------------------------------- +double vtkImageViewer2::GetColorLevel() +{ + return this->WindowLevel->GetLevel(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetColorWindow(double s) +{ + this->WindowLevel->SetWindow(s); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetColorLevel(double s) +{ + this->WindowLevel->SetLevel(s); +} + +//---------------------------------------------------------------------------- +class vtkImageViewer2Callback : public vtkCommand +{ +public: + static vtkImageViewer2Callback *New() { return new vtkImageViewer2Callback; } + + void Execute(vtkObject *caller, + unsigned long event, + void *vtkNotUsed(callData)) + { + if (this->IV->GetInput() == NULL) + { + return; + } + + // Reset + + if (event == vtkCommand::ResetWindowLevelEvent) + { + this->IV->GetInput()->UpdateInformation(); + this->IV->GetInput()->SetUpdateExtent + (this->IV->GetInput()->GetWholeExtent()); + this->IV->GetInput()->Update(); + double *range = this->IV->GetInput()->GetScalarRange(); + this->IV->SetColorWindow(range[1] - range[0]); + this->IV->SetColorLevel(0.5 * (range[1] + range[0])); + this->IV->Render(); + return; + } + + // Start + + if (event == vtkCommand::StartWindowLevelEvent) + { + this->InitialWindow = this->IV->GetColorWindow(); + this->InitialLevel = this->IV->GetColorLevel(); + return; + } + + // Adjust the window level here + + vtkInteractorStyleImage *isi = + static_cast(caller); + + int *size = this->IV->GetRenderWindow()->GetSize(); + double window = this->InitialWindow; + double level = this->InitialLevel; + + // Compute normalized delta + + double dx = 4.0 * + (isi->GetWindowLevelCurrentPosition()[0] - + isi->GetWindowLevelStartPosition()[0]) / size[0]; + double dy = 4.0 * + (isi->GetWindowLevelStartPosition()[1] - + isi->GetWindowLevelCurrentPosition()[1]) / size[1]; + + // Scale by current values + + if (fabs(window) > 0.01) + { + dx = dx * window; + } + else + { + dx = dx * (window < 0 ? -0.01 : 0.01); + } + if (fabs(level) > 0.01) + { + dy = dy * level; + } + else + { + dy = dy * (level < 0 ? -0.01 : 0.01); + } + + // Abs so that direction does not flip + + if (window < 0.0) + { + dx = -1*dx; + } + if (level < 0.0) + { + dy = -1*dy; + } + + // Compute new window level + + double newWindow = dx + window; + double newLevel; + newLevel = level - dy; + + // Stay away from zero and really + + if (fabs(newWindow) < 0.01) + { + newWindow = 0.01*(newWindow < 0 ? -1 : 1); + } + if (fabs(newLevel) < 0.01) + { + newLevel = 0.01*(newLevel < 0 ? -1 : 1); + } + + this->IV->SetColorWindow(newWindow); + this->IV->SetColorLevel(newLevel); + this->IV->Render(); + } + + vtkImageViewer2 *IV; + double InitialWindow; + double InitialLevel; +}; + +//---------------------------------------------------------------------------- +void vtkImageViewer2::InstallPipeline() +{ + if (this->RenderWindow && this->Renderer) + { + this->RenderWindow->AddRenderer(this->Renderer); + } + + if (this->Interactor) + { + if (!this->InteractorStyle) + { + this->InteractorStyle = vtkInteractorStyleImage::New(); + vtkImageViewer2Callback *cbk = vtkImageViewer2Callback::New(); + cbk->IV = this; + this->InteractorStyle->AddObserver( + vtkCommand::WindowLevelEvent, cbk); + this->InteractorStyle->AddObserver( + vtkCommand::StartWindowLevelEvent, cbk); + this->InteractorStyle->AddObserver( + vtkCommand::ResetWindowLevelEvent, cbk); + cbk->Delete(); + } + + this->Interactor->SetInteractorStyle(this->InteractorStyle); + this->Interactor->SetRenderWindow(this->RenderWindow); + } + + if (this->Renderer && this->ImageActor) + { + this->Renderer->AddViewProp(this->ImageActor); + } + + if (this->ImageActor && this->WindowLevel) + { + this->ImageActor->SetInput(this->WindowLevel->GetOutput()); + } +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::UnInstallPipeline() +{ + if (this->ImageActor) + { + this->ImageActor->SetInput(NULL); + } + + if (this->Renderer && this->ImageActor) + { + this->Renderer->RemoveViewProp(this->ImageActor); + } + + if (this->RenderWindow && this->Renderer) + { + this->RenderWindow->RemoveRenderer(this->Renderer); + } + + if (this->Interactor) + { + this->Interactor->SetInteractorStyle(NULL); + this->Interactor->SetRenderWindow(NULL); + } +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::Render() +{ + if (this->FirstRender) + { + // Initialize the size if not set yet + + vtkImageData *input = this->GetInput(); + if (this->RenderWindow->GetSize()[0] == 0 && input) + { + input->UpdateInformation(); + int *w_ext = input->GetWholeExtent(); + int xs = 0, ys = 0; + + switch (this->SliceOrientation) + { + case vtkImageViewer2::SLICE_ORIENTATION_XY: + default: + xs = w_ext[1] - w_ext[0] + 1; + ys = w_ext[3] - w_ext[2] + 1; + break; + + case vtkImageViewer2::SLICE_ORIENTATION_XZ: + xs = w_ext[1] - w_ext[0] + 1; + ys = w_ext[5] - w_ext[4] + 1; + break; + + case vtkImageViewer2::SLICE_ORIENTATION_YZ: + xs = w_ext[3] - w_ext[2] + 1; + ys = w_ext[5] - w_ext[4] + 1; + break; + } + + // if it would be smaller than 150 by 100 then limit to 150 by 100 + this->RenderWindow->SetSize( + xs < 150 ? 150 : xs, ys < 100 ? 100 : ys); + + if (this->Renderer) + { + this->Renderer->ResetCamera(); + this->Renderer->GetActiveCamera()->SetParallelScale( + xs < 150 ? 75 : (xs - 1 ) / 2.0); + } + this->FirstRender = 0; + } + } + if (this->GetInput()) + { + this->RenderWindow->Render(); + } +} + +//---------------------------------------------------------------------------- +char* vtkImageViewer2::GetWindowName() +{ + return this->RenderWindow->GetWindowName(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetOffScreenRendering(int i) +{ + this->RenderWindow->SetOffScreenRendering(i); +} + +//---------------------------------------------------------------------------- +int vtkImageViewer2::GetOffScreenRendering() +{ + return this->RenderWindow->GetOffScreenRendering(); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetInput(vtkImageData *in) +{ + this->WindowLevel->SetInput(in); + this->UpdateDisplayExtent(); +} +//---------------------------------------------------------------------------- +vtkImageData* vtkImageViewer2::GetInput() +{ + return vtkImageData::SafeDownCast(this->WindowLevel->GetInput()); +} + +//---------------------------------------------------------------------------- +void vtkImageViewer2::SetInputConnection(vtkAlgorithmOutput* input) +{ + this->WindowLevel->SetInputConnection(input); + this->UpdateDisplayExtent(); +}; + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +int vtkImageViewer2::GetWholeZMin() +{ + VTK_LEGACY_REPLACED_BODY(vtkImageViewer2::GetWholeZMin, "VTK 5.0", + vtkImageViewer2::GetSliceMin); + return this->GetSliceMin(); +} +int vtkImageViewer2::GetWholeZMax() +{ + VTK_LEGACY_REPLACED_BODY(vtkImageViewer2::GetWholeZMax, "VTK 5.0", + vtkImageViewer2::GetSliceMax); + return this->GetSliceMax(); +} +int vtkImageViewer2::GetZSlice() +{ + VTK_LEGACY_REPLACED_BODY(vtkImageViewer2::GetZSlice, "VTK 5.0", + vtkImageViewer2::GetSlice); + return this->GetSlice(); +} +void vtkImageViewer2::SetZSlice(int s) +{ + VTK_LEGACY_REPLACED_BODY(vtkImageViewer2::SetZSlice, "VTK 5.0", + vtkImageViewer2::SetSlice); + this->SetSlice(s); +} +#endif + +//---------------------------------------------------------------------------- +void vtkImageViewer2::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "RenderWindow:\n"; + this->RenderWindow->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Renderer:\n"; + this->Renderer->PrintSelf(os,indent.GetNextIndent()); + os << indent << "ImageActor:\n"; + this->ImageActor->PrintSelf(os,indent.GetNextIndent()); + os << indent << "WindowLevel:\n" << endl; + this->WindowLevel->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Slice: " << this->Slice << endl; + os << indent << "SliceOrientation: " << this->SliceOrientation << endl; + os << indent << "InteractorStyle: " << endl; + if (this->InteractorStyle) + { + os << "\n"; + this->InteractorStyle->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << "None"; + } +} diff --git a/Rendering/vtkImageViewer2.h b/Rendering/vtkImageViewer2.h new file mode 100644 index 0000000..d7ec3e1 --- /dev/null +++ b/Rendering/vtkImageViewer2.h @@ -0,0 +1,219 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageViewer2.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageViewer2 - Display a 2D image. +// .SECTION Description +// vtkImageViewer2 is a convenience class for displaying a 2D image. It +// packages up the functionality found in vtkRenderWindow, vtkRenderer, +// vtkImageActor and vtkImageMapToWindowLevelColors into a single easy to use +// class. This class also creates an image interactor style +// (vtkInteractorStyleImage) that allows zooming and panning of images, and +// supports interactive window/level operations on the image. Note that +// vtkImageViewer2 is simply a wrapper around these classes. +// +// vtkImageViewer2 uses the 3D rendering and texture mapping engine +// to draw an image on a plane. This allows for rapid rendering, +// zooming, and panning. The image is placed in the 3D scene at a +// depth based on the z-coordinate of the particular image slice. Each +// call to SetSlice() changes the image data (slice) displayed AND +// changes the depth of the displayed slice in the 3D scene. This can +// be controlled by the AutoAdjustCameraClippingRange ivar of the +// InteractorStyle member. +// +// It is possible to mix images and geometry, using the methods: +// +// viewer->SetInput( myImage ); +// viewer->GetRenderer()->AddActor( myActor ); +// +// This can be used to annotate an image with a PolyData of "edges" or +// or highlight sections of an image or display a 3D isosurface +// with a slice from the volume, etc. Any portions of your geometry +// that are in front of the displayed slice will be visible; any +// portions of your geometry that are behind the displayed slice will +// be obscured. A more general framework (with respect to viewing +// direction) for achieving this effect is provided by the +// vtkImagePlaneWidget . +// +// Note that pressing 'r' will reset the window/level and pressing +// shift+'r' or control+'r' will reset the camera. +// +// .SECTION See Also +// vtkRenderWindow vtkRenderer vtkImageActor vtkImageMapToWindowLevelColors + +#ifndef __vtkImageViewer2_h +#define __vtkImageViewer2_h + +#include "vtkObject.h" + +class vtkAlgorithmOutput; +class vtkImageActor; +class vtkImageData; +class vtkImageMapToWindowLevelColors; +class vtkInteractorStyleImage; +class vtkRenderWindow; +class vtkRenderer; +class vtkRenderWindowInteractor; + +class VTK_RENDERING_EXPORT vtkImageViewer2 : public vtkObject +{ +public: + static vtkImageViewer2 *New(); + vtkTypeRevisionMacro(vtkImageViewer2,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the name of rendering window. + virtual char *GetWindowName(); + + // Description: + // Render the resulting image. + virtual void Render(void); + + // Description: + // Set/Get the input image to the viewer. + virtual void SetInput(vtkImageData *in); + virtual vtkImageData *GetInput(); + virtual void SetInputConnection(vtkAlgorithmOutput* input); + + // Description: + // Set/get the slice orientation + //BTX + enum + { + SLICE_ORIENTATION_YZ = 0, + SLICE_ORIENTATION_XZ = 1, + SLICE_ORIENTATION_XY = 2 + }; + //ETX + vtkGetMacro(SliceOrientation, int); + virtual void SetSliceOrientation(int orientation); + virtual void SetSliceOrientationToXY() + { this->SetSliceOrientation(vtkImageViewer2::SLICE_ORIENTATION_XY); }; + virtual void SetSliceOrientationToYZ() + { this->SetSliceOrientation(vtkImageViewer2::SLICE_ORIENTATION_YZ); }; + virtual void SetSliceOrientationToXZ() + { this->SetSliceOrientation(vtkImageViewer2::SLICE_ORIENTATION_XZ); }; + + // Description: + // Set/Get the current slice to display (depending on the orientation + // this can be in X, Y or Z). + vtkGetMacro(Slice, int); + virtual void SetSlice(int s); + + // Description: + // Return the minimum and maximum slice values (depending on the orientation + // this can be in X, Y or Z). + virtual int GetSliceMin(); + virtual int GetSliceMax(); + virtual void GetSliceRange(int range[2]) + { this->GetSliceRange(range[0], range[1]); } + virtual void GetSliceRange(int &min, int &max); + virtual int* GetSliceRange(); + + // Description: + // Set window and level for mapping pixels to colors. + virtual double GetColorWindow(); + virtual double GetColorLevel(); + virtual void SetColorWindow(double s); + virtual void SetColorLevel(double s); + + // Description: + // These are here when using a Tk window. + virtual void SetDisplayId(void *a); + virtual void SetWindowId(void *a); + virtual void SetParentId(void *a); + + // Description: + // Set/Get the position in screen coordinates of the rendering window. + virtual int* GetPosition(); + virtual void SetPosition(int a,int b); + virtual void SetPosition(int a[2]) { this->SetPosition(a[0],a[1]); } + + // Description: + // Set/Get the size of the window in screen coordinates. + virtual int* GetSize(); + virtual void SetSize(int a, int b); + virtual void SetSize(int a[2]) { this->SetSize(a[0],a[1]); } + + // Description: + // Get the internal render window, renderer, image actor, and + // image map instances. + vtkGetObjectMacro(RenderWindow,vtkRenderWindow); + vtkGetObjectMacro(Renderer, vtkRenderer); + vtkGetObjectMacro(ImageActor,vtkImageActor); + vtkGetObjectMacro(WindowLevel,vtkImageMapToWindowLevelColors); + vtkGetObjectMacro(InteractorStyle,vtkInteractorStyleImage); + + // Description: + // Set your own renderwindow and renderer + virtual void SetRenderWindow(vtkRenderWindow *arg); + virtual void SetRenderer(vtkRenderer *arg); + + // Description: + // Attach an interactor for the internal render window. + virtual void SetupInteractor(vtkRenderWindowInteractor*); + + // Description: + // Create a window in memory instead of on the screen. This may not + // be supported for every type of window and on some windows you may + // need to invoke this prior to the first render. + virtual void SetOffScreenRendering(int); + virtual int GetOffScreenRendering(); + vtkBooleanMacro(OffScreenRendering,int); + + // Description: + // @deprecated Replaced by vtkImageViewer2::GetSliceMin() as of VTK 5.0. + VTK_LEGACY(int GetWholeZMin()); + + // Description: + // @deprecated Replaced by vtkImageViewer2::GetSliceMax() as of VTK 5.0. + VTK_LEGACY(int GetWholeZMax()); + + // Description: + // @deprecated Replaced by vtkImageViewer2::GetSlice() as of VTK 5.0. + VTK_LEGACY(int GetZSlice()); + + // Description: + // @deprecated Replaced by vtkImageViewer2::SetSlice() as of VTK 5.0. + VTK_LEGACY(void SetZSlice(int)); + +protected: + vtkImageViewer2(); + ~vtkImageViewer2(); + + virtual void InstallPipeline(); + virtual void UnInstallPipeline(); + + vtkImageMapToWindowLevelColors *WindowLevel; + vtkRenderWindow *RenderWindow; + vtkRenderer *Renderer; + vtkImageActor *ImageActor; + vtkRenderWindowInteractor *Interactor; + vtkInteractorStyleImage *InteractorStyle; + + int SliceOrientation; + int FirstRender; + int Slice; + + virtual void UpdateOrientation(); + virtual void UpdateDisplayExtent(); + +private: + vtkImageViewer2(const vtkImageViewer2&); // Not implemented. + void operator=(const vtkImageViewer2&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkImagingFactory.cxx b/Rendering/vtkImagingFactory.cxx new file mode 100644 index 0000000..861d6f2 --- /dev/null +++ b/Rendering/vtkImagingFactory.cxx @@ -0,0 +1,236 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagingFactory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkObjectFactory.h" +#include "vtkImagingFactory.h" +#include "vtkToolkits.h" +#include "vtkDebugLeaks.h" + +#ifdef VTK_USE_OGLR +#include "vtkOpenGLImageMapper.h" +#include "vtkOpenGLPolyDataMapper2D.h" +#include "vtkOpenGLFreeTypeTextMapper.h" +#endif + +#if defined(VTK_USE_MANGLED_MESA) +#include "vtkMesaImageMapper.h" +#include "vtkMesaPolyDataMapper2D.h" +#include "vtkMesaFreeTypeTextMapper.h" +#endif + +#ifdef _WIN32 +#include "vtkOpenGLImageMapper.h" +#include "vtkOpenGLPolyDataMapper2D.h" +#include "vtkOpenGLFreeTypeTextMapper.h" +#else +#ifdef VTK_USE_QUARTZ +#include "vtkOpenGLImageMapper.h" +#include "vtkOpenGLPolyDataMapper2D.h" +#include "vtkQuartzImageMapper.h" +#include "vtkOpenGLFreeTypeTextMapper.h" +#endif +#endif + +#ifdef VTK_USE_CARBON +#include "vtkOpenGLImageMapper.h" +#include "vtkOpenGLPolyDataMapper2D.h" +#include "vtkOpenGLFreeTypeTextMapper.h" +#endif + +#ifdef VTK_USE_COCOA +#include "vtkOpenGLImageMapper.h" +#include "vtkOpenGLPolyDataMapper2D.h" +#include "vtkOpenGLFreeTypeTextMapper.h" +#endif + +#include "vtkCriticalSection.h" +static vtkSimpleCriticalSection vtkUseMesaClassesCriticalSection; +int vtkImagingFactory::UseMesaClasses = 0; + +vtkCxxRevisionMacro(vtkImagingFactory, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkImagingFactory); + +const char *vtkImagingFactoryGetRenderLibrary() +{ + const char *temp; + + // first check the environment variable + temp = getenv("VTK_RENDERER"); + + // Backward compatibility + if ( temp ) + { + if (!strcmp("oglr",temp)) + { + temp = "OpenGL"; + } + else if (!strcmp("woglr",temp)) + { + temp = "Win32OpenGL"; + } + else if (strcmp("Mesa",temp) && strcmp("OpenGL",temp) && + strcmp("Win32OpenGL",temp)) + { + vtkGenericWarningMacro(<<"VTK_RENDERER set to unsupported type:" << temp); + temp = NULL; + } + } + + // if nothing is set then work down the list of possible renderers + if ( !temp ) + { +#ifdef VTK_USE_OGLR + temp = "OpenGL"; +#endif +#ifdef _WIN32 + temp = "Win32OpenGL"; +#endif +#ifdef VTK_USE_CARBON + temp = "CarbonOpenGL"; +#endif +#ifdef VTK_USE_COCOA + temp = "CocoaOpenGL"; +#endif + } + + return temp; +} + +vtkObject* vtkImagingFactory::CreateInstance(const char* vtkclassname ) +{ + // first check the object factory + vtkObject *ret = vtkObjectFactory::CreateInstance(vtkclassname); + if (ret) + { + return ret; + } + // if the factory failed to create the object, + // then destroy it now, as vtkDebugLeaks::ConstructClass was called + // with vtkclassname, and not the real name of the class +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass(vtkclassname); +#endif + + const char *rl = vtkImagingFactoryGetRenderLibrary(); + +#ifdef VTK_USE_OGLR + if (!strcmp("OpenGL",rl)) + { + if(strcmp(vtkclassname, "vtkTextMapper") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkImagingFactory::UseMesaClasses ) + { + return vtkMesaFreeTypeTextMapper::New(); + } +#endif + return vtkOpenGLFreeTypeTextMapper::New(); + } + if(strcmp(vtkclassname, "vtkImageMapper") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkImagingFactory::UseMesaClasses ) + { + return vtkMesaImageMapper::New(); + } +#endif + return vtkOpenGLImageMapper::New(); + } + if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkImagingFactory::UseMesaClasses ) + { + return vtkMesaPolyDataMapper2D::New(); + } +#endif + return vtkOpenGLPolyDataMapper2D::New(); + } + } +#endif + +#ifdef _WIN32 + if (!strcmp("Win32OpenGL",rl)) + { + if(strcmp(vtkclassname, "vtkTextMapper") == 0) + { + return vtkOpenGLFreeTypeTextMapper::New(); + } + if(strcmp(vtkclassname, "vtkImageMapper") == 0) + { + return vtkOpenGLImageMapper::New(); + } + if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0) + { + return vtkOpenGLPolyDataMapper2D::New(); + } + } +#endif + +#ifdef VTK_USE_CARBON + if (!strcmp("CarbonOpenGL",rl)) + { + if(strcmp(vtkclassname, "vtkTextMapper") == 0) + { + return vtkOpenGLFreeTypeTextMapper::New(); + } + if(strcmp(vtkclassname, "vtkImageMapper") == 0) + { + return vtkOpenGLImageMapper::New(); + } + if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0) + { + return vtkOpenGLPolyDataMapper2D::New(); + } + } +#endif +#ifdef VTK_USE_COCOA + if (!strcmp("CocoaOpenGL",rl)) + { + if(strcmp(vtkclassname, "vtkTextMapper") == 0) + { + return vtkOpenGLFreeTypeTextMapper::New(); + } + if(strcmp(vtkclassname, "vtkImageMapper") == 0) + { + return vtkOpenGLImageMapper::New(); + } + if(strcmp(vtkclassname, "vtkPolyDataMapper2D") == 0) + { + return vtkOpenGLPolyDataMapper2D::New(); + } + } +#endif + + return 0; +} + +void vtkImagingFactory::SetUseMesaClasses(int use) +{ + vtkUseMesaClassesCriticalSection.Lock(); + vtkImagingFactory::UseMesaClasses = use; + vtkUseMesaClassesCriticalSection.Unlock(); +} + +int vtkImagingFactory::GetUseMesaClasses() +{ + return vtkImagingFactory::UseMesaClasses; +} + +//---------------------------------------------------------------------------- +void vtkImagingFactory::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkImagingFactory.h b/Rendering/vtkImagingFactory.h new file mode 100644 index 0000000..1047309 --- /dev/null +++ b/Rendering/vtkImagingFactory.h @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagingFactory.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImagingFactory - +// .SECTION Description + +#ifndef __vtkImagingFactory_h +#define __vtkImagingFactory_h + +#include "vtkObject.h" + +class VTK_RENDERING_EXPORT vtkImagingFactory : public vtkObject +{ +public: + static vtkImagingFactory *New(); + vtkTypeRevisionMacro(vtkImagingFactory,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create and return an instance of the named vtk object. + // This method first checks the vtkObjectFactory to support + // dynamic loading. + static vtkObject* CreateInstance(const char* vtkclassname); + + // Description: + // This option enables the creation of Mesa classes + // instead of the OpenGL classes when using mangled Mesa. + static void SetUseMesaClasses(int use); + static int GetUseMesaClasses(); + +protected: + vtkImagingFactory() {}; + + static int UseMesaClasses; + +private: + vtkImagingFactory(const vtkImagingFactory&); // Not implemented. + void operator=(const vtkImagingFactory&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkImporter.cxx b/Rendering/vtkImporter.cxx new file mode 100644 index 0000000..89eb813 --- /dev/null +++ b/Rendering/vtkImporter.cxx @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImporter.h" +#include "vtkRendererCollection.h" +#include "vtkRenderWindow.h" + +vtkCxxRevisionMacro(vtkImporter, "$Revision: 1.23 $"); + +vtkCxxSetObjectMacro(vtkImporter,RenderWindow,vtkRenderWindow); + +vtkImporter::vtkImporter () +{ + this->Renderer = NULL; + this->RenderWindow = NULL; +} + +vtkImporter::~vtkImporter () +{ + this->SetRenderWindow(NULL); + + if (this->Renderer) + { + this->Renderer->UnRegister( NULL ); + this->Renderer = NULL; + } + +} + +void vtkImporter::ReadData() +{ + // this->Import actors, cameras, lights and properties + this->ImportActors (this->Renderer); + this->ImportCameras (this->Renderer); + this->ImportLights (this->Renderer); + this->ImportProperties (this->Renderer); +} + +void vtkImporter::Read () +{ + vtkRenderer *renderer; + + // if there is no render window, create one + if (this->RenderWindow == NULL) + { + vtkDebugMacro( <<"Creating a RenderWindow\n"); + this->RenderWindow = vtkRenderWindow::New (); + } + + // Get the first renderer in the render window + renderer = this->RenderWindow->GetRenderers()->GetFirstRenderer(); + if (renderer == NULL) + { + vtkDebugMacro( <<"Creating a Renderer\n"); + this->Renderer = vtkRenderer::New (); + renderer = this->Renderer; + this->RenderWindow->AddRenderer (renderer); + } + else + { + this->Renderer = renderer; + this->Renderer->Register( this ); + } + + if (this->ImportBegin ()) + { + this->ReadData(); + this->ImportEnd(); + } +} + +void vtkImporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Render Window: "; + if ( this->RenderWindow ) + { + os << this->RenderWindow << "\n"; + } + else + { + os << "(none)\n"; + } + + os << indent << "Renderer: "; + if ( this->Renderer ) + { + os << this->Renderer << "\n"; + } + else + { + os << "(none)\n"; + } + +} + + + + + + diff --git a/Rendering/vtkImporter.h b/Rendering/vtkImporter.h new file mode 100644 index 0000000..0bd1ee7 --- /dev/null +++ b/Rendering/vtkImporter.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImporter - importer abstract class +// .SECTION Description +// vtkImporter is an abstract class that specifies the protocol for +// importing actors, cameras, lights and properties into a +// vtkRenderWindow. The following takes place: +// 1) Create a RenderWindow and Renderer if none is provided. +// 2) Call ImportBegin, if ImportBegin returns False, return +// 3) Call ReadData, which calls: +// a) Import the Actors +// b) Import the cameras +// c) Import the lights +// d) Import the Properties +// 7) Call ImportEnd +// +// Subclasses optionally implement the ImportActors, ImportCameras, +// ImportLights and ImportProperties or ReadData methods. An ImportBegin and +// ImportEnd can optionally be provided to perform Importer-specific +// initialization and termination. The Read method initiates the import +// process. If a RenderWindow is provided, its Renderer will contained +// the imported objects. If the RenderWindow has no Renderer, one is +// created. If no RenderWindow is provided, both a RenderWindow and +// Renderer will be created. Both the RenderWindow and Renderer can be +// accessed using Get methods. + +// .SECTION See Also +// vtk3DSImporter vtkExporter + +#ifndef __vtkImporter_h +#define __vtkImporter_h + +#include "vtkObject.h" + +class vtkRenderWindow; +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkImporter : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkImporter,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + + // Description + // Get the renderer that contains the imported actors, cameras and + // lights. + vtkGetObjectMacro(Renderer,vtkRenderer); + + // Description + // Set the vtkRenderWindow to contain the imported actors, cameras and + // lights, If no vtkRenderWindow is set, one will be created and can be + // obtained with the GetRenderWindow method. If the vtkRenderWindow has been + // specified, the first vtkRenderer it has will be used to import the + // objects. If the vtkRenderWindow has no Renderer, one will be created and + // can be accessed using GetRenderer. + virtual void SetRenderWindow(vtkRenderWindow*); + vtkGetObjectMacro(RenderWindow,vtkRenderWindow); + + + // Description + // Import the actors, cameras, lights and properties into a vtkRenderWindow. + void Read(); + void Update() {this->Read();}; + + +protected: + vtkImporter(); + ~vtkImporter(); + + virtual int ImportBegin () {return 1;}; + virtual void ImportEnd () {}; + virtual void ImportActors (vtkRenderer*) {}; + virtual void ImportCameras (vtkRenderer*) {}; + virtual void ImportLights (vtkRenderer*) {}; + virtual void ImportProperties (vtkRenderer*) {}; + + vtkRenderer *Renderer; + vtkRenderWindow *RenderWindow; + + virtual void ReadData(); + +private: + vtkImporter(const vtkImporter&); // Not implemented. + void operator=(const vtkImporter&); // Not implemented. +}; + +#endif + + + + diff --git a/Rendering/vtkInteractorEventRecorder.cxx b/Rendering/vtkInteractorEventRecorder.cxx new file mode 100644 index 0000000..fe6d83a --- /dev/null +++ b/Rendering/vtkInteractorEventRecorder.cxx @@ -0,0 +1,391 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorEventRecorder.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorEventRecorder.h" +#include "vtkCallbackCommand.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindowInteractor.h" + +vtkCxxRevisionMacro(vtkInteractorEventRecorder, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkInteractorEventRecorder); + +float vtkInteractorEventRecorder::StreamVersion = 1.0; + +vtkInteractorEventRecorder::vtkInteractorEventRecorder() +{ + //take over the processing of delete and keypress events from the superclass + this->KeyPressCallbackCommand->SetCallback( + vtkInteractorEventRecorder::ProcessCharEvent); + + this->Priority = VTK_LARGE_FLOAT; //get events first + this->EventCallbackCommand->SetCallback( + vtkInteractorEventRecorder::ProcessEvents); + + this->FileName = NULL; + + this->State = vtkInteractorEventRecorder::Start; + this->InputStream = NULL; + this->OutputStream = NULL; + + this->ReadFromInputString = 0; + this->InputString = NULL; +} + +vtkInteractorEventRecorder::~vtkInteractorEventRecorder() +{ + this->SetInteractor(0); + + if ( this->FileName ) + { + delete [] this->FileName; + } + + if ( this->InputStream ) + { + delete this->InputStream; + this->InputStream = NULL; + } + + if ( this->OutputStream ) + { + delete this->OutputStream; + this->OutputStream = NULL; + } + + if ( this->InputString ) + { + delete [] this->InputString; + this->InputString = NULL; + } +} + +void vtkInteractorEventRecorder::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //---------------------------------------------------------- + { + vtkDebugMacro(<<"Enabling widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + this->Enabled = 1; + + // listen to any event + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::AnyEvent, this->EventCallbackCommand, + this->Priority); + + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling----------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + } +} + +void vtkInteractorEventRecorder::Record() +{ + if ( this->State == vtkInteractorEventRecorder::Start ) + { + if ( ! this->OutputStream ) //need to open file + { + this->OutputStream = new ofstream(this->FileName, ios::out); + if (this->OutputStream->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + delete this->OutputStream; + return; + } + *this->OutputStream << "# StreamVersion " + << vtkInteractorEventRecorder::StreamVersion << "\n"; + } + + vtkDebugMacro(<<"Recording"); + this->State = vtkInteractorEventRecorder::Recording; + } +} + +void vtkInteractorEventRecorder::Play() +{ + if ( this->State == vtkInteractorEventRecorder::Start ) + { + if ( this->ReadFromInputString ) + { + vtkDebugMacro(<< "Reading from InputString"); + int len; + if ( this->InputString == NULL || (len = strlen(this->InputString) <= 0) ) + { + vtkErrorMacro(<< "No input string specified"); + return; + } + this->InputStream = new istrstream(this->InputString, len); + if (this->InputStream->fail()) + { + vtkErrorMacro(<< "Unable to read from string"); + delete this->InputStream; + return; + } + } + else + { + if ( ! this->InputStream ) //need to open file + { + this->InputStream = new ifstream(this->FileName, ios::in); + if (this->InputStream->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + delete this->InputStream; + return; + } + } + } + + vtkDebugMacro(<<"Playing"); + this->State = vtkInteractorEventRecorder::Playing; + + // Read events and invoke them on the object in question + char event[128], keySym[64], buffer[512]; + int pos[2], ctrlKey, shiftKey, keyCode, repeatCount; + float stream_version = 0.0, tempf; + + while ( ! this->InputStream->eof() ) + { + this->InputStream->width(256); + *this->InputStream >> event; + + // Quick skip comment + if (*event == '#') + { + this->InputStream->getline(buffer, 512); + + // Parse the StreamVersion (not using >> since comment could be empty) + // Expecting: # StreamVersion x.y + + if (strlen(buffer) > 15 && !strncmp(buffer, " StreamVersion ", 15)) + { + int res = sscanf(buffer + 15, "%f", &tempf); + if (res && res != EOF) + { + stream_version = tempf; + } + } + } + else + { + unsigned long ievent = vtkCommand::GetEventIdFromString(event); + if (ievent == vtkCommand::NoEvent) + { + this->InputStream->ignore(512, '\n'); + } + else + { + if (stream_version >= 1.1) + { + // We could grab the time info here + } + *this->InputStream >> pos[0]; + *this->InputStream >> pos[1]; + *this->InputStream >> ctrlKey; + *this->InputStream >> shiftKey; + *this->InputStream >> keyCode; + *this->InputStream >> repeatCount; + *this->InputStream >> keySym; + + this->Interactor->SetEventPosition(pos); + this->Interactor->SetControlKey(ctrlKey); + this->Interactor->SetShiftKey(shiftKey); + this->Interactor->SetKeyCode(keyCode); + this->Interactor->SetRepeatCount(repeatCount); + this->Interactor->SetKeySym(keySym); + + this->Interactor->InvokeEvent(ievent, NULL); + } + } + } + } + + this->State = vtkInteractorEventRecorder::Start; +} + +void vtkInteractorEventRecorder::Stop() +{ + this->State = vtkInteractorEventRecorder::Start; + this->Modified(); +} + +void vtkInteractorEventRecorder::Rewind() +{ + if ( ! this->InputStream ) //need to already have an open file + { + vtkGenericWarningMacro(<<"No input file opened to rewind..."); + } + this->InputStream->clear(); + this->InputStream->seekg(0); +} + +// This adds the keypress event observer and the delete event observer +void vtkInteractorEventRecorder::SetInteractor(vtkRenderWindowInteractor* i) +{ + if (i == this->Interactor) + { + return; + } + + // if we already have an Interactor then stop observing it + if (this->Interactor) + { + this->SetEnabled(0); //disable the old interactor + this->Interactor->RemoveObserver(this->KeyPressCallbackCommand); + } + + this->Interactor = i; + + // add observers for each of the events handled in ProcessEvents + if (i) + { + i->AddObserver(vtkCommand::CharEvent, + this->KeyPressCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::DeleteEvent, + this->KeyPressCallbackCommand, this->Priority); + } + + this->Modified(); +} + +void vtkInteractorEventRecorder::ProcessCharEvent(vtkObject* object, + unsigned long event, + void* clientData, + void* vtkNotUsed(callData)) +{ + vtkInteractorEventRecorder* self = + reinterpret_cast( clientData ); + vtkRenderWindowInteractor* rwi = + static_cast( object ); + + switch(event) + { + case vtkCommand::DeleteEvent: + // if the interactor is being deleted then remove the event handlers + self->SetInteractor(0); + break; + + case vtkCommand::CharEvent: + if ( self->KeyPressActivation ) + { + if (rwi->GetKeyCode() == self->KeyPressActivationValue ) + { + if ( !self->Enabled ) + { + self->On(); + } + else + { + self->Off(); + } + }//event not aborted + }//if activation enabled + } +} + +void vtkInteractorEventRecorder::ProcessEvents(vtkObject* object, + unsigned long event, + void* clientData, + void* vtkNotUsed(callData)) +{ + vtkInteractorEventRecorder* self = + reinterpret_cast( clientData ); + vtkRenderWindowInteractor* rwi = + static_cast( object ); + + // all events are processed + if ( self->State == vtkInteractorEventRecorder::Recording ) + { + switch(event) + { + case vtkCommand::ModifiedEvent: //dont want these + break; + + default: + self->WriteEvent(vtkCommand::GetStringFromEventId(event), + rwi->GetEventPosition(), rwi->GetControlKey(), + rwi->GetShiftKey(), rwi->GetKeyCode(), + rwi->GetRepeatCount(), rwi->GetKeySym()); + } + self->OutputStream->flush(); + } +} + +void vtkInteractorEventRecorder::WriteEvent(const char* event, int pos[2], + int ctrlKey, int shiftKey, + int keyCode, int repeatCount, + char* keySym) +{ + *this->OutputStream << event << " " << pos[0] << " " << pos[1] << " " + << ctrlKey << " " << shiftKey << " " + << keyCode << " " << repeatCount << " " + << keySym << "\n"; +} + +void vtkInteractorEventRecorder::ReadEvent() +{ +} + +void vtkInteractorEventRecorder::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->FileName) + { + os << indent << "File Name: " << this->FileName << "\n"; + } + + os << indent << "ReadFromInputString: " + << (this->ReadFromInputString ? "On\n" : "Off\n"); + + if ( this->InputString ) + { + os << indent << "Input String: " << this->InputString << "\n"; + } + else + { + os << indent << "Input String: (None)\n"; + } +} + + + + + + diff --git a/Rendering/vtkInteractorEventRecorder.h b/Rendering/vtkInteractorEventRecorder.h new file mode 100644 index 0000000..3ee757c --- /dev/null +++ b/Rendering/vtkInteractorEventRecorder.h @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorEventRecorder.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorEventRecorder - record and play VTK events passing through a vtkRenderWindowInteractor + +// .SECTION Description +// vtkInteractorEventRecorder records all VTK events invoked from a +// vtkRenderWindowInteractor. The events are recorded to a +// file. vtkInteractorEventRecorder can also be used to play those events +// back and invoke them on an vtkRenderWindowInteractor. (Note: the events +// can also be played back from a file or string.) +// +// The format of the event file is simple. It is: +// EventName X Y ctrl shift keycode repeatCount keySym +// The format also allows "#" comments. + +// .SECTION See Also +// vtkInteractorObserver vtkCallback + +#ifndef __vtkInteractorEventRecorder_h +#define __vtkInteractorEventRecorder_h + +#include "vtkInteractorObserver.h" + +// The superclass that all commands should be subclasses of +class VTK_RENDERING_EXPORT vtkInteractorEventRecorder : public vtkInteractorObserver +{ +public: + static vtkInteractorEventRecorder *New(); + vtkTypeRevisionMacro(vtkInteractorEventRecorder,vtkInteractorObserver); + void PrintSelf(ostream& os, vtkIndent indent); + + // Satisfy the superclass API. Enable/disable listening for events. + virtual void SetEnabled(int); + virtual void SetInteractor(vtkRenderWindowInteractor* iren); + + // Description: + // Set/Get the name of a file events should be written to/from. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Invoke this method to begin recording events. The events will be + // recorded to the filename indicated. + void Record(); + + // Description: + // Invoke this method to begin playing events from the current position. + // The events will be played back from the filename indicated. + void Play(); + + // Description: + // Invoke this method to stop recording/playing events. + void Stop(); + + // Description: + // Rewind to the beginning of the file. + void Rewind(); + + // Description: + // Enable reading from an InputString as compared to the default + // behavior, which is to read from a file. + vtkSetMacro(ReadFromInputString,int); + vtkGetMacro(ReadFromInputString,int); + vtkBooleanMacro(ReadFromInputString,int); + + // Description: + // Set/Get the string to read from. + vtkSetStringMacro(InputString); + vtkGetStringMacro(InputString); + +protected: + vtkInteractorEventRecorder(); + ~vtkInteractorEventRecorder(); + + // file to read/write from + char *FileName; + + // control whether to read from string + int ReadFromInputString; + char *InputString; + + // for reading and writing + istream *InputStream; + ostream *OutputStream; + + //methods for processing events + static void ProcessCharEvent(vtkObject* object, unsigned long event, + void* clientdata, void* calldata); + static void ProcessEvents(vtkObject* object, unsigned long event, + void* clientdata, void* calldata); + + virtual void WriteEvent(const char* event, int pos[2], int ctrlKey, + int shiftKey, int keyCode, int repeatCount, + char* keySym); + + virtual void ReadEvent(); + +//BTX - manage the state of the recorder + int State; + enum WidgetState + { + Start=0, + Playing, + Recording + }; +//ETX + + static float StreamVersion; + +private: + vtkInteractorEventRecorder(const vtkInteractorEventRecorder&); // Not implemented. + void operator=(const vtkInteractorEventRecorder&); // Not implemented. + +}; + +#endif /* __vtkInteractorEventRecorder_h */ + diff --git a/Rendering/vtkInteractorObserver.cxx b/Rendering/vtkInteractorObserver.cxx new file mode 100644 index 0000000..a16d3e4 --- /dev/null +++ b/Rendering/vtkInteractorObserver.cxx @@ -0,0 +1,298 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorObserver.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorObserver.h" + +#include "vtkCallbackCommand.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" + +vtkCxxRevisionMacro(vtkInteractorObserver, "$Revision: 1.32 $"); + +vtkCxxSetObjectMacro(vtkInteractorObserver,DefaultRenderer,vtkRenderer); + +//---------------------------------------------------------------------------- +vtkInteractorObserver::vtkInteractorObserver() +{ + this->Enabled = 0; + + this->Interactor = NULL; + + this->EventCallbackCommand = vtkCallbackCommand::New(); + this->EventCallbackCommand->SetClientData(this); + + //subclass has to invoke SetCallback() + + this->KeyPressCallbackCommand = vtkCallbackCommand::New(); + this->KeyPressCallbackCommand->SetClientData(this); + this->KeyPressCallbackCommand->SetCallback(vtkInteractorObserver::ProcessEvents); + + this->CurrentRenderer = NULL; + this->DefaultRenderer = NULL; + + this->Priority = 0.0; + + this->KeyPressActivation = 1; + this->KeyPressActivationValue = 'i'; + + this->CharObserverTag = 0; + this->DeleteObserverTag = 0; +} + +//---------------------------------------------------------------------------- +vtkInteractorObserver::~vtkInteractorObserver() +{ + this->SetEnabled(0); + this->SetCurrentRenderer(NULL); + this->SetDefaultRenderer(NULL); + this->EventCallbackCommand->Delete(); + this->KeyPressCallbackCommand->Delete(); + this->SetInteractor(0); +} + +//---------------------------------------------------------------------------- +void vtkInteractorObserver::SetCurrentRenderer(vtkRenderer *_arg) +{ + if (this->CurrentRenderer == _arg) + { + return; + } + + if (this->CurrentRenderer != NULL) + { + this->CurrentRenderer->UnRegister(this); + } + + // WARNING: see .h, if the DefaultRenderer is set, whatever the value + // of _arg (except NULL), we are going to use DefaultRenderer + // Normally when the widget is activated (SetEnabled(1) or when + // keypress activation takes place), the renderer over which the mouse + // pointer is positioned is used to call SetCurrentRenderer(). + // Alternatively, we may want to specify a user-defined renderer to bind the + // interactor to when the interactor observer is activated. + // The problem is that in many 3D widgets, when SetEnabled(0) is called, + // the CurrentRender is set to NULL. In that case, the next time + // SetEnabled(1) is called, the widget will try to set CurrentRenderer + // to the renderer over which the mouse pointer is positioned, and we + // will use our user-defined renderer. To solve that, we introduced the + // DefaultRenderer ivar, which will be used to force the value of + // CurrentRenderer each time SetCurrentRenderer is called (i.e., no matter + // if SetCurrentRenderer is called with the renderer that was poked at + // the mouse coords, the DefaultRenderer will be used). + + if (_arg && this->DefaultRenderer) + { + _arg = this->DefaultRenderer; + } + + this->CurrentRenderer = _arg; + + if (this->CurrentRenderer != NULL) + { + this->CurrentRenderer->Register(this); + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +// This adds the keypress event observer and the delete event observer +void vtkInteractorObserver::SetInteractor(vtkRenderWindowInteractor* i) +{ + if (i == this->Interactor) + { + return; + } + + // if we already have an Interactor then stop observing it + if (this->Interactor) + { + this->SetEnabled(0); //disable the old interactor + this->Interactor->RemoveObserver(this->CharObserverTag); + this->CharObserverTag = 0; + this->Interactor->RemoveObserver(this->DeleteObserverTag); + this->DeleteObserverTag = 0; + } + + this->Interactor = i; + + // add observers for each of the events handled in ProcessEvents + if (i) + { + this->CharObserverTag = i->AddObserver(vtkCommand::CharEvent, + this->KeyPressCallbackCommand, + this->Priority); + this->DeleteObserverTag = i->AddObserver(vtkCommand::DeleteEvent, + this->KeyPressCallbackCommand, + this->Priority); + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorObserver::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + if (event == vtkCommand::CharEvent || + event == vtkCommand::DeleteEvent) + { + vtkObject *vobj = reinterpret_cast( clientdata ); + vtkInteractorObserver* self + = vtkInteractorObserver::SafeDownCast(vobj); + if (self) + { + if (event == vtkCommand::CharEvent) + { + self->OnChar(); + } + else // delete event + { + self->SetInteractor(0); + } + } + else + { + vtkGenericWarningMacro("Process Events received a bad client data. The client data class name was " << vobj->GetClassName()); + } + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorObserver::StartInteraction() +{ + this->Interactor->GetRenderWindow()->SetDesiredUpdateRate(this->Interactor->GetDesiredUpdateRate()); +} + +//---------------------------------------------------------------------------- +void vtkInteractorObserver::EndInteraction() +{ + this->Interactor->GetRenderWindow()->SetDesiredUpdateRate(this->Interactor->GetStillUpdateRate()); +} + +//---------------------------------------------------------------------------- +// Description: +// Transform from display to world coordinates. +// WorldPt has to be allocated as 4 vector +void vtkInteractorObserver::ComputeDisplayToWorld(vtkRenderer *ren, + double x, + double y, + double z, + double worldPt[4]) +{ + ren->SetDisplayPoint(x, y, z); + ren->DisplayToWorld(); + ren->GetWorldPoint(worldPt); + if (worldPt[3]) + { + worldPt[0] /= worldPt[3]; + worldPt[1] /= worldPt[3]; + worldPt[2] /= worldPt[3]; + worldPt[3] = 1.0; + } +} + + +//---------------------------------------------------------------------------- +// Description: +// Transform from world to display coordinates. +// displayPt has to be allocated as 3 vector +void vtkInteractorObserver::ComputeWorldToDisplay(vtkRenderer *ren, + double x, + double y, + double z, + double displayPt[3]) +{ + ren->SetWorldPoint(x, y, z, 1.0); + ren->WorldToDisplay(); + ren->GetDisplayPoint(displayPt); +} + +//---------------------------------------------------------------------------- +// Description: +// Transform from display to world coordinates. +// WorldPt has to be allocated as 4 vector +void vtkInteractorObserver::ComputeDisplayToWorld(double x, + double y, + double z, + double worldPt[4]) +{ + if ( !this->CurrentRenderer ) + { + return; + } + + this->ComputeDisplayToWorld(this->CurrentRenderer, x, y, z, worldPt); +} + + +//---------------------------------------------------------------------------- +// Description: +// Transform from world to display coordinates. +// displayPt has to be allocated as 3 vector +void vtkInteractorObserver::ComputeWorldToDisplay(double x, + double y, + double z, + double displayPt[3]) +{ + if ( !this->CurrentRenderer ) + { + return; + } + + this->ComputeWorldToDisplay(this->CurrentRenderer, x, y, z, displayPt); +} + +//---------------------------------------------------------------------------- +void vtkInteractorObserver::OnChar() +{ + // catch additional keycodes otherwise + if ( this->KeyPressActivation ) + { + if (this->Interactor->GetKeyCode() == this->KeyPressActivationValue ) + { + if ( !this->Enabled ) + { + this->On(); + } + else + { + this->Off(); + } + this->KeyPressCallbackCommand->SetAbortFlag(1); + } + }//if activation enabled +} + +//---------------------------------------------------------------------------- +void vtkInteractorObserver::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Current Renderer: " << this->CurrentRenderer << "\n"; + os << indent << "Default Renderer: " << this->DefaultRenderer << "\n"; + os << indent << "Enabled: " << this->Enabled << "\n"; + os << indent << "Priority: " << this->Priority << "\n"; + os << indent << "Interactor: " << this->Interactor << "\n"; + os << indent << "Key Press Activation: " + << (this->KeyPressActivation ? "On" : "Off") << "\n"; + os << indent << "Key Press Activation Value: " + << this->KeyPressActivationValue << "\n"; +} + + diff --git a/Rendering/vtkInteractorObserver.h b/Rendering/vtkInteractorObserver.h new file mode 100644 index 0000000..afb552e --- /dev/null +++ b/Rendering/vtkInteractorObserver.h @@ -0,0 +1,197 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorObserver.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorObserver - an abstract superclass for classes observing events invoked by vtkRenderWindowInteractor +// .SECTION Description +// vtkInteractorObserver is an abstract superclass for subclasses that observe +// events invoked by vtkRenderWindowInteractor. These subclasses are +// typically things like 3D widgets; objects that interact with actors +// in the scene, or interactively probe the scene for information. +// +// vtkInteractorObserver defines the method SetInteractor() and enables and +// disables the processing of events by the vtkInteractorObserver. Use the +// methods EnabledOn() or SetEnabled(1) to turn on the interactor observer, +// and the methods EnabledOff() or SetEnabled(0) to turn off the interactor. +// +// To support interactive manipulation of objects, this class (and +// subclasses) invoke the events StartInteractionEvent, InteractionEvent, and +// EndInteractionEvent. These events are invoked when the +// vtkInteractorObserver enters a state where rapid response is desired: +// mouse motion, etc. The events can be used, for example, to set the desired +// update frame rate (StartInteractionEvent), operate on data or update a +// pipeline (InteractionEvent), and set the desired frame rate back to normal +// values (EndInteractionEvent). Two other events, EnableEvent and +// DisableEvent, are invoked when the interactor observer is enabled or +// disabled. + +// .SECTION See Also +// vtk3DWidget vtkBoxWidget vtkLineWidget + +#ifndef __vtkInteractorObserver_h +#define __vtkInteractorObserver_h + +#include "vtkObject.h" + +class vtkRenderWindowInteractor; +class vtkRenderer; +class vtkCallbackCommand; + +class VTK_RENDERING_EXPORT vtkInteractorObserver : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkInteractorObserver,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods for turning the interactor observer on and off, and determining + // its state. All subclasses must provide the SetEnabled() method. + // Enabling a vtkInteractorObserver has the side effect of adding + // observers; disabling it removes the observers. Prior to enabling the + // vtkInteractorObserver you must set the render window interactor (via + // SetInteractor()). + virtual void SetEnabled(int) {}; + int GetEnabled() {return this->Enabled;} + void EnabledOn() {this->SetEnabled(1);} + void EnabledOff() {this->SetEnabled(0);} + void On() {this->SetEnabled(1);} + void Off() {this->SetEnabled(0);} + + // Description: + // This method is used to associate the widget with the render window + // interactor. Observers of the appropriate events invoked in the render + // window interactor are set up as a result of this method invocation. + // The SetInteractor() method must be invoked prior to enabling the + // vtkInteractorObserver. + virtual void SetInteractor(vtkRenderWindowInteractor* iren); + vtkGetObjectMacro(Interactor, vtkRenderWindowInteractor); + + // Description: + // Set/Get the priority at which events are processed. This is used when + // multiple interactor observers are used simultaneously. The default value + // is 0.0 (lowest priority.) Note that when multiple interactor observer + // have the same priority, then the last observer added will process the + // event first. (Note: once the SetInteractor() method has been called, + // changing the priority does not effect event processing. You will have + // to SetInteractor(NULL), change priority, and then SetInteractor(iren) + // to have the priority take effect.) + vtkSetClampMacro(Priority,float,0.0f,1.0f); + vtkGetMacro(Priority,float); + + // Description: + // Enable/Disable of the use of a keypress to turn on and off the + // interactor observer. (By default, the keypress is 'i' for "interactor + // observer".) Set the KeyPressActivationValue to change which key + // activates the widget.) + vtkSetMacro(KeyPressActivation,int); + vtkGetMacro(KeyPressActivation,int); + vtkBooleanMacro(KeyPressActivation,int); + + // Description: + // Specify which key press value to use to activate the interactor observer + // (if key press activation is enabled). By default, the key press + // activation value is 'i'. Note: once the SetInteractor() method is + // invoked, changing the key press activation value will not affect the key + // press until SetInteractor(NULL)/SetInteractor(iren) is called. + vtkSetMacro(KeyPressActivationValue,char); + vtkGetMacro(KeyPressActivationValue,char); + + // Description: + // Set/Get the default renderer to use when activating the interactor + // observer. Normally when the widget is activated (SetEnabled(1) or when + // keypress activation takes place), the renderer over which the mouse + // pointer is positioned is used. Alternatively, you can specify the + // renderer to bind the interactor to when the interactor observer is + // activated. + vtkGetObjectMacro(DefaultRenderer,vtkRenderer); + virtual void SetDefaultRenderer(vtkRenderer*); + + // Description: + // Set/Get the current renderer. Normally when the widget is activated + // (SetEnabled(1) or when keypress activation takes place), the renderer + // over which the mouse pointer is positioned is used and assigned to + // this Ivar. Alternatively, you might want to set the CurrentRenderer + // explicitly. + // WARNING: note that if the DefaultRenderer Ivar is set (see above), + // it will always override the parameter passed to SetCurrentRenderer, + // unless it is NULL. + // (i.e., SetCurrentRenderer(foo) = SetCurrentRenderer(DefaultRenderer). + vtkGetObjectMacro(CurrentRenderer,vtkRenderer); + virtual void SetCurrentRenderer(vtkRenderer*); + + // Sets up the keypress-i event. + virtual void OnChar(); + + // Convenience methods for outside classes. Make sure that the + // parameter "ren" is not-null. + static void ComputeDisplayToWorld(vtkRenderer *ren, double x, double y, + double z, double worldPt[4]); + static void ComputeWorldToDisplay(vtkRenderer *ren, double x, double y, + double z, double displayPt[3]); + +protected: + vtkInteractorObserver(); + ~vtkInteractorObserver(); + + // Description: + // Utility routines used to start and end interaction. + // For example, it switches the display update rate. It does not invoke + // the corresponding events. + virtual void StartInteraction(); + virtual void EndInteraction(); + + // Description: + // Handles the char widget activation event. Also handles the delete event. + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // Description: + // Helper method for subclasses. + void ComputeDisplayToWorld(double x, double y, double z, + double worldPt[4]); + void ComputeWorldToDisplay(double x, double y, double z, + double displayPt[3]); + + // The state of the widget, whether on or off (observing events or not) + int Enabled; + + // Used to process events + vtkCallbackCommand* EventCallbackCommand; //subclasses use one + vtkCallbackCommand* KeyPressCallbackCommand; //listens to key activation + + // Priority at which events are processed + float Priority; + + // Keypress activation controls + int KeyPressActivation; + char KeyPressActivationValue; + + // Used to associate observers with the interactor + vtkRenderWindowInteractor *Interactor; + + // Internal ivars for processing events + vtkRenderer *CurrentRenderer; + vtkRenderer *DefaultRenderer; + + unsigned long CharObserverTag; + unsigned long DeleteObserverTag; + +private: + vtkInteractorObserver(const vtkInteractorObserver&); // Not implemented. + void operator=(const vtkInteractorObserver&); // Not implemented. + +}; + +#endif diff --git a/Rendering/vtkInteractorStyle.cxx b/Rendering/vtkInteractorStyle.cxx new file mode 100644 index 0000000..6dcad70 --- /dev/null +++ b/Rendering/vtkInteractorStyle.cxx @@ -0,0 +1,1072 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyle.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyle.h" + +#include "vtkActor.h" +#include "vtkActor2D.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCellPicker.h" +#include "vtkCommand.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkProperty2D.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkTextProperty.h" + +vtkCxxRevisionMacro(vtkInteractorStyle, "$Revision: 1.99 $"); +vtkStandardNewMacro(vtkInteractorStyle); + +//---------------------------------------------------------------------------- +vtkInteractorStyle::vtkInteractorStyle() +{ + this->State = VTKIS_NONE; + this->AnimState = VTKIS_ANIM_OFF; + + this->HandleObservers = 1; + this->UseTimers = 0; + + this->AutoAdjustCameraClippingRange = 1; + + this->Interactor = NULL; + + this->EventCallbackCommand->SetCallback(vtkInteractorStyle::ProcessEvents); + + // These widgets are not activated with a key + + this->KeyPressActivation = 0; + + this->Outline = vtkOutlineSource::New(); + this->OutlineActor = NULL; + this->OutlineMapper = vtkPolyDataMapper::New(); + + this->OutlineMapper->SetInput(this->Outline->GetOutput()); + + this->PickedRenderer = NULL; + this->CurrentProp = NULL; + this->PropPicked = 0; + + this->PickColor[0] = 1.0; + this->PickColor[1] = 0.0; + this->PickColor[2] = 0.0; + this->PickedActor2D = NULL; + + this->MouseWheelMotionFactor = 1.0; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyle::~vtkInteractorStyle() +{ + // Remove observers + + this->SetInteractor(0); + + // Remove any highlight + + this->HighlightProp(NULL); + + if ( this->OutlineActor ) + { + this->OutlineActor->Delete(); + } + + if ( this->OutlineMapper ) + { + this->OutlineMapper->Delete(); + } + + this->Outline->Delete(); + this->Outline = NULL; + + this->SetCurrentRenderer(NULL); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //---------------------------------------------------------- + { + vtkDebugMacro(<<"Enabling widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + this->Enabled = 1; + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling------------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + this->HighlightProp(NULL); + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + } +} + +//---------------------------------------------------------------------------- +// NOTE!!! This does not do any reference counting!!! +// This is to avoid some ugly reference counting loops +// and the benefit of being able to hold only an entire +// renderwindow from an interactor style doesn't seem worth the +// mess. Instead the vtkInteractorStyle sets up a DeleteEvent callback, so +// that it can tell when the vtkRenderWindowInteractor is going away. + +void vtkInteractorStyle::SetInteractor(vtkRenderWindowInteractor *i) +{ + if(i == this->Interactor) + { + return; + } + + // if we already have an Interactor then stop observing it + if(this->Interactor) + { + this->Interactor->RemoveObserver(this->EventCallbackCommand); + } + this->Interactor = i; + + // add observers for each of the events handled in ProcessEvents + if(i) + { + i->AddObserver(vtkCommand::EnterEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::LeaveEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::MouseMoveEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::MouseWheelForwardEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::MouseWheelBackwardEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::ExposeEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::ConfigureEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::TimerEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::KeyPressEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::KeyReleaseEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::CharEvent, + this->EventCallbackCommand, + this->Priority); + + i->AddObserver(vtkCommand::DeleteEvent, + this->EventCallbackCommand, + this->Priority); + } +} + + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::FindPokedRenderer(int x,int y) +{ + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(x,y)); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::HighlightProp(vtkProp *prop) +{ + this->CurrentProp = prop; + + if ( prop != NULL ) + { + vtkActor2D *actor2D; + vtkProp3D *prop3D; + if ( (prop3D=vtkProp3D::SafeDownCast(prop)) != NULL ) + { + this->HighlightProp3D(prop3D); + } + else if ( (actor2D=vtkActor2D::SafeDownCast(prop)) != NULL ) + { + this->HighlightActor2D(actor2D); + } + } + else + {//unhighlight everything, both 2D & 3D + this->HighlightProp3D(NULL); + this->HighlightActor2D(NULL); + } + + if (this->Interactor) + { + this->Interactor->Render(); + } +} + +//---------------------------------------------------------------------------- +// When pick action successfully selects a vtkProp3Dactor, this method +// highlights the vtkProp3D appropriately. Currently this is done by placing a +// bounding box around the vtkProp3D. +void vtkInteractorStyle::HighlightProp3D(vtkProp3D *prop3D) +{ + //no prop picked now + if ( ! prop3D) + { + //was there previously? + if (this->PickedRenderer != NULL && this->OutlineActor) + { + this->PickedRenderer->RemoveActor(this->OutlineActor); + this->PickedRenderer = NULL; + } + } + //prop picked now + else + { + if ( ! this->OutlineActor ) + { + // have to defer creation to get right type + this->OutlineActor = vtkActor::New(); + this->OutlineActor->PickableOff(); + this->OutlineActor->DragableOff(); + this->OutlineActor->SetMapper(this->OutlineMapper); + this->OutlineActor->GetProperty()->SetColor(this->PickColor); + this->OutlineActor->GetProperty()->SetAmbient(1.0); + this->OutlineActor->GetProperty()->SetDiffuse(0.0); + } + + //check if picked in different renderer to previous pick + if (this->CurrentRenderer != this->PickedRenderer) + { + if (this->PickedRenderer != NULL && this->OutlineActor) + { + this->PickedRenderer->RemoveActor(this->OutlineActor); + } + this->CurrentRenderer->AddActor(this->OutlineActor); + this->PickedRenderer = this->CurrentRenderer; + } + this->Outline->SetBounds(prop3D->GetBounds()); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::HighlightActor2D(vtkActor2D *actor2D) +{ + // If nothing has changed, just return + if ( actor2D == this->PickedActor2D ) + { + return; + } + + if ( actor2D ) + { + if ( this->PickedActor2D ) + { + actor2D->GetProperty()->SetColor( + this->PickedActor2D->GetProperty()->GetColor()); + this->PickedActor2D->GetProperty()->SetColor(this->PickColor); + } + else + { + double tmpColor[3]; + actor2D->GetProperty()->GetColor(tmpColor); + actor2D->GetProperty()->SetColor(this->PickColor); + this->PickColor[0] = tmpColor[0]; + this->PickColor[1] = tmpColor[1]; + this->PickColor[2] = tmpColor[2]; + } + } + else + { + if ( this->PickedActor2D ) + { + double tmpColor[3]; + this->PickedActor2D->GetProperty()->GetColor(tmpColor); + this->PickedActor2D->GetProperty()->SetColor(this->PickColor); + this->PickColor[0] = tmpColor[0]; + this->PickColor[1] = tmpColor[1]; + this->PickColor[2] = tmpColor[2]; + } + } + + this->PickedActor2D = actor2D; +} + +//---------------------------------------------------------------------------- +// Implementation of motion state control methods +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartState(int newstate) +{ + this->State = newstate; + if (this->AnimState == VTKIS_ANIM_OFF) + { + vtkRenderWindowInteractor *rwi = this->Interactor; + rwi->GetRenderWindow()->SetDesiredUpdateRate(rwi->GetDesiredUpdateRate()); + this->InvokeEvent(vtkCommand::StartInteractionEvent, NULL); + if (this->UseTimers && !rwi->CreateTimer(VTKI_TIMER_FIRST)) + { + vtkErrorMacro(<< "Timer start failed"); + this->State = VTKIS_NONE; + } + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StopState() +{ + this->State = VTKIS_NONE; + if (this->AnimState == VTKIS_ANIM_OFF) + { + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkRenderWindow *renwin = rwi->GetRenderWindow(); + renwin->SetDesiredUpdateRate(rwi->GetStillUpdateRate()); + if (this->UseTimers && !rwi->DestroyTimer()) + { + vtkErrorMacro(<< "Timer stop failed"); + } + this->InvokeEvent(vtkCommand::EndInteractionEvent, NULL); + rwi->Render(); + } +} + +//---------------------------------------------------------------------------- +// JCP animation control +void vtkInteractorStyle::StartAnimate() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + this->AnimState = VTKIS_ANIM_ON; + if (this->State == VTKIS_NONE) + { + rwi->GetRenderWindow()->SetDesiredUpdateRate(rwi->GetDesiredUpdateRate()); + if (this->UseTimers && !rwi->CreateTimer(VTKI_TIMER_FIRST) ) + { + vtkErrorMacro(<< "Timer start failed"); + } + } + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StopAnimate() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + this->AnimState = VTKIS_ANIM_OFF; + if (this->State == VTKIS_NONE) + { + rwi->GetRenderWindow()->SetDesiredUpdateRate(rwi->GetStillUpdateRate()); + if (this->UseTimers && !rwi->DestroyTimer() ) + { + vtkErrorMacro(<< "Timer stop failed"); + } + } +} + +// JCP Animation control +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartRotate() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_ROTATE); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::EndRotate() +{ + if (this->State != VTKIS_ROTATE) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartZoom() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_ZOOM); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::EndZoom() +{ + if (this->State != VTKIS_ZOOM) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartPan() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_PAN); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::EndPan() +{ + if (this->State != VTKIS_PAN) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartSpin() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_SPIN); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::EndSpin() +{ + if (this->State != VTKIS_SPIN) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartDolly() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_DOLLY); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::EndDolly() +{ + if (this->State != VTKIS_DOLLY) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartUniformScale() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_USCALE); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::EndUniformScale() +{ + if (this->State != VTKIS_USCALE) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::StartTimer() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_TIMER); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::EndTimer() +{ + if (this->State != VTKIS_TIMER) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +// By overriding the Rotate, Rotate members we can +// use this timer routine for Joystick or Trackball - quite tidy +//---------------------------------------------------------------------------- +void vtkInteractorStyle::OnTimer() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + + switch (this->State) + { + case VTKIS_NONE: + if (this->AnimState == VTKIS_ANIM_ON) + { + if (this->UseTimers) + { + rwi->DestroyTimer(); + } + rwi->Render(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_FIRST); + } + } + break; + + case VTKIS_ROTATE: + this->Rotate(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + case VTKIS_PAN: + this->Pan(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + case VTKIS_SPIN: + this->Spin(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + case VTKIS_DOLLY: + this->Dolly(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + case VTKIS_ZOOM: + this->Zoom(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + case VTKIS_USCALE: + this->UniformScale(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + case VTKIS_TIMER: + rwi->Render(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + default: + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::OnChar() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + + switch (rwi->GetKeyCode()) + { + case 'm' : + case 'M' : + if (this->AnimState == VTKIS_ANIM_OFF) + { + this->StartAnimate(); + } + else + { + this->StopAnimate(); + } + break; + + case 'Q' : + case 'q' : + case 'e' : + case 'E' : + rwi->ExitCallback(); + break; + + case 'f' : + case 'F' : + { + this->AnimState = VTKIS_ANIM_ON; + vtkAssemblyPath *path = NULL; + this->FindPokedRenderer(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1]); + rwi->GetPicker()->Pick(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1], + 0.0, + this->CurrentRenderer); + vtkAbstractPropPicker *picker; + if ((picker=vtkAbstractPropPicker::SafeDownCast(rwi->GetPicker()))) + { + path = picker->GetPath(); + } + if (path != NULL) + { + rwi->FlyTo(this->CurrentRenderer, picker->GetPickPosition()); + } + this->AnimState = VTKIS_ANIM_OFF; + } + break; + + case 'u' : + case 'U' : + rwi->UserCallback(); + break; + + case 'r' : + case 'R' : + this->FindPokedRenderer(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1]); + this->CurrentRenderer->ResetCamera(); + rwi->Render(); + break; + + case 'w' : + case 'W' : + { + vtkActorCollection *ac; + vtkActor *anActor, *aPart; + vtkAssemblyPath *path; + this->FindPokedRenderer(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1]); + ac = this->CurrentRenderer->GetActors(); + vtkCollectionSimpleIterator ait; + for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); ) + { + for (anActor->InitPathTraversal(); (path=anActor->GetNextPath()); ) + { + aPart=(vtkActor *)path->GetLastNode()->GetViewProp(); + aPart->GetProperty()->SetRepresentationToWireframe(); + } + } + rwi->Render(); + } + break; + + case 's' : + case 'S' : + { + vtkActorCollection *ac; + vtkActor *anActor, *aPart; + vtkAssemblyPath *path; + this->FindPokedRenderer(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1]); + ac = this->CurrentRenderer->GetActors(); + vtkCollectionSimpleIterator ait; + for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); ) + { + for (anActor->InitPathTraversal(); (path=anActor->GetNextPath()); ) + { + aPart=(vtkActor *)path->GetLastNode()->GetViewProp(); + aPart->GetProperty()->SetRepresentationToSurface(); + } + } + rwi->Render(); + } + break; + + case '3' : + if (rwi->GetRenderWindow()->GetStereoRender()) + { + rwi->GetRenderWindow()->StereoRenderOff(); + } + else + { + rwi->GetRenderWindow()->StereoRenderOn(); + } + rwi->Render(); + break; + + case 'p' : + case 'P' : + if (this->State == VTKIS_NONE) + { + vtkAssemblyPath *path = NULL; + int *eventPos = rwi->GetEventPosition(); + this->FindPokedRenderer(eventPos[0], eventPos[1]); + rwi->StartPickCallback(); + vtkAbstractPropPicker *picker = + vtkAbstractPropPicker::SafeDownCast(rwi->GetPicker()); + if ( picker != NULL ) + { + picker->Pick(eventPos[0], eventPos[1], + 0.0, this->CurrentRenderer); + path = picker->GetPath(); + } + if ( path == NULL ) + { + this->HighlightProp(NULL); + this->PropPicked = 0; + } + else + { + this->HighlightProp(path->GetFirstNode()->GetViewProp()); + this->PropPicked = 1; + } + rwi->EndPickCallback(); + } + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Auto Adjust Camera Clipping Range " + << (this->AutoAdjustCameraClippingRange ? "On\n" : "Off\n"); + + os << indent << "Pick Color: (" << this->PickColor[0] << ", " + << this->PickColor[1] << ", " + << this->PickColor[2] << ")\n"; + + os << indent << "CurrentRenderer: " << this->CurrentRenderer << "\n"; + if ( this->PickedRenderer ) + { + os << indent << "Picked Renderer: " << this->PickedRenderer << "\n"; + } + else + { + os << indent << "Picked Renderer: (none)\n"; + } + if ( this->CurrentProp ) + { + os << indent << "Current Prop: " << this->CurrentProp << "\n"; + } + else + { + os << indent << "Current Actor: (none)\n"; + } + + os << indent << "Interactor: " << this->Interactor << "\n"; + os << indent << "Prop Picked: " << + (this->PropPicked ? "Yes\n" : "No\n"); + + os << indent << "State: " << this->State << endl; + os << indent << "UseTimers: " << this->UseTimers << endl; + os << indent << "HandleObservers: " << this->HandleObservers << endl; + os << indent << "MouseWheelMotionFactor: " << this->MouseWheelMotionFactor << endl; +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyle::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkInteractorStyle* self + = reinterpret_cast( clientdata ); + + switch(event) + { + case vtkCommand::ExposeEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::ExposeEvent)) + { + self->InvokeEvent(vtkCommand::ExposeEvent,NULL); + } + else + { + self->OnExpose(); + } + break; + + case vtkCommand::ConfigureEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::ConfigureEvent)) + { + self->InvokeEvent(vtkCommand::ConfigureEvent,NULL); + } + else + { + self->OnConfigure(); + } + break; + + case vtkCommand::EnterEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::EnterEvent)) + { + self->InvokeEvent(vtkCommand::EnterEvent, NULL); + } + else + { + self->OnEnter(); + } + break; + + case vtkCommand::LeaveEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::LeaveEvent)) + { + self->InvokeEvent(vtkCommand::LeaveEvent,NULL); + } + else + { + self->OnLeave(); + } + break; + + case vtkCommand::TimerEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::TimerEvent)) + { + self->InvokeEvent(vtkCommand::TimerEvent,NULL); + } + else + { + self->OnTimer(); + } + break; + + case vtkCommand::MouseMoveEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::MouseMoveEvent)) + { + self->InvokeEvent(vtkCommand::MouseMoveEvent,NULL); + } + else + { + self->OnMouseMove(); + } + break; + + case vtkCommand::LeftButtonPressEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::LeftButtonPressEvent)) + { + self->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); + } + else + { + self->OnLeftButtonDown(); + } + break; + + case vtkCommand::LeftButtonReleaseEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::LeftButtonReleaseEvent)) + { + self->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL); + } + else + { + self->OnLeftButtonUp(); + } + break; + + case vtkCommand::MiddleButtonPressEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::MiddleButtonPressEvent)) + { + self->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL); + } + else + { + self->OnMiddleButtonDown(); + } + break; + + case vtkCommand::MiddleButtonReleaseEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::MiddleButtonReleaseEvent)) + { + self->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL); + } + else + { + self->OnMiddleButtonUp(); + } + break; + + case vtkCommand::RightButtonPressEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::RightButtonPressEvent)) + { + self->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL); + } + else + { + self->OnRightButtonDown(); + } + break; + + case vtkCommand::RightButtonReleaseEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::RightButtonReleaseEvent)) + { + self->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL); + } + else + { + self->OnRightButtonUp(); + } + break; + + case vtkCommand::MouseWheelForwardEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::MouseWheelForwardEvent)) + { + self->InvokeEvent(vtkCommand::MouseWheelForwardEvent,NULL); + } + else + { + self->OnMouseWheelForward(); + } + break; + + case vtkCommand::MouseWheelBackwardEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::MouseWheelBackwardEvent)) + { + self->InvokeEvent(vtkCommand::MouseWheelBackwardEvent,NULL); + } + else + { + self->OnMouseWheelBackward(); + } + break; + + case vtkCommand::KeyPressEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::KeyPressEvent)) + { + self->InvokeEvent(vtkCommand::KeyPressEvent,NULL); + } + else + { + self->OnKeyDown(); + self->OnKeyPress(); + } + break; + + case vtkCommand::KeyReleaseEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::KeyReleaseEvent)) + { + self->InvokeEvent(vtkCommand::KeyReleaseEvent,NULL); + } + else + { + self->OnKeyUp(); + self->OnKeyRelease(); + } + break; + + case vtkCommand::CharEvent: + if (self->HandleObservers && + self->HasObserver(vtkCommand::CharEvent)) + { + self->InvokeEvent(vtkCommand::CharEvent,NULL); + } + else + { + self->OnChar(); + } + break; + + case vtkCommand::DeleteEvent: + self->SetInteractor(0); + break; + } +} + diff --git a/Rendering/vtkInteractorStyle.h b/Rendering/vtkInteractorStyle.h new file mode 100644 index 0000000..40d1d2c --- /dev/null +++ b/Rendering/vtkInteractorStyle.h @@ -0,0 +1,306 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyle.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyle - provide event-driven interface to the rendering window (defines trackball mode) +// .SECTION Description +// vtkInteractorStyle is a base class implementing the majority of motion +// control routines and defines an event driven interface to support +// vtkRenderWindowInteractor. vtkRenderWindowInteractor implements +// platform dependent key/mouse routing and timer control, which forwards +// events in a neutral form to vtkInteractorStyle. +// +// vtkInteractorStyle implements the "joystick" style of interaction. That +// is, holding down the mouse keys generates a stream of events that cause +// continuous actions (e.g., rotate, translate, pan, zoom). (The class +// vtkInteractorStyleTrackball implements a grab and move style.) The event +// bindings for this class include the following: +// - Keypress j / Keypress t: toggle between joystick (position sensitive) and +// trackball (motion sensitive) styles. In joystick style, motion occurs +// continuously as long as a mouse button is pressed. In trackball style, +// motion occurs when the mouse button is pressed and the mouse pointer +// moves. +// - Keypress c / Keypress a: toggle between camera and actor modes. In +// camera mode, mouse events affect the camera position and focal point. In +// actor mode, mouse events affect the actor that is under the mouse pointer. +// - Button 1: rotate the camera around its focal point (if camera mode) or +// rotate the actor around its origin (if actor mode). The rotation is in the +// direction defined from the center of the renderer's viewport towards +// the mouse position. In joystick mode, the magnitude of the rotation is +// determined by the distance the mouse is from the center of the render +// window. +// - Button 2: pan the camera (if camera mode) or translate the actor (if +// actor mode). In joystick mode, the direction of pan or translation is +// from the center of the viewport towards the mouse position. In trackball +// mode, the direction of motion is the direction the mouse moves. (Note: +// with 2-button mice, pan is defined as -Button 1.) +// - Button 3: zoom the camera (if camera mode) or scale the actor (if +// actor mode). Zoom in/increase scale if the mouse position is in the top +// half of the viewport; zoom out/decrease scale if the mouse position is in +// the bottom half. In joystick mode, the amount of zoom is controlled by the +// distance of the mouse pointer from the horizontal centerline of the +// window. +// - Keypress 3: toggle the render window into and out of stereo mode. By +// default, red-blue stereo pairs are created. Some systems support Crystal +// Eyes LCD stereo glasses; you have to invoke SetStereoTypeToCrystalEyes() +// on the rendering window. +// - Keypress e: exit the application. +// - Keypress f: fly to the picked point +// - Keypress p: perform a pick operation. The render window interactor has +// an internal instance of vtkCellPicker that it uses to pick. +// - Keypress r: reset the camera view along the current view +// direction. Centers the actors and moves the camera so that all actors are +// visible. +// - Keypress s: modify the representation of all actors so that they are +// surfaces. +// - Keypress u: invoke the user-defined function. Typically, +// this keypress will bring up an interactor that you can type commands in. +// - Keypress w: modify the representation of all actors so that they are +// wireframe. +// +// vtkInteractorStyle can be subclassed to provide new interaction styles and +// a facility to override any of the default mouse/key operations which +// currently handle trackball or joystick styles is provided. Note that this +// class will fire a variety of events that can be watched using an observer, +// such as LeftButtonPressEvent, LeftButtonReleaseEvent, +// MiddleButtonPressEvent, MiddleButtonReleaseEvent, RightButtonPressEvent, +// RightButtonReleaseEvent, EnterEvent, LeaveEvent, KeyPressEvent, +// KeyReleaseEvent, CharEvent, ExposeEvent, ConfigureEvent, TimerEvent, +// MouseMoveEvent, + + +// +// .SECTION See Also +// vtkInteractorStyleTrackball + +#ifndef __vtkInteractorStyle_h +#define __vtkInteractorStyle_h + +#include "vtkInteractorObserver.h" + +// Motion flags + +#define VTKIS_START 0 +#define VTKIS_NONE 0 + +#define VTKIS_ROTATE 1 +#define VTKIS_PAN 2 +#define VTKIS_SPIN 3 +#define VTKIS_DOLLY 4 +#define VTKIS_ZOOM 5 +#define VTKIS_USCALE 6 +#define VTKIS_TIMER 7 +#define VTKIS_FORWARDFLY 8 +#define VTKIS_REVERSEFLY 9 + +#define VTKIS_ANIM_OFF 0 +#define VTKIS_ANIM_ON 1 + +class vtkActor2D; +class vtkActor; +class vtkCallbackCommand; +class vtkOutlineSource; +class vtkPolyDataMapper; +class vtkProp3D; +class vtkProp; + +class VTK_RENDERING_EXPORT vtkInteractorStyle : public vtkInteractorObserver +{ +public: + // Description: + // This class must be supplied with a vtkRenderWindowInteractor wrapper or + // parent. This class should not normally be instantiated by application + // programmers. + static vtkInteractorStyle *New(); + + vtkTypeRevisionMacro(vtkInteractorStyle,vtkInteractorObserver); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the Interactor wrapper being controlled by this object. + // (Satisfy superclass API.) + virtual void SetInteractor(vtkRenderWindowInteractor *interactor); + + // Description: + // Turn on/off this interactor. Interactor styles operate a little + // bit differently than other types of interactor observers. When + // the SetInteractor() method is invoked, the automatically enable + // themselves. This is a legacy requirement, and convenient for the + // user. + virtual void SetEnabled(int); + + // Description: + // If AutoAdjustCameraClippingRange is on, then before each render the + // camera clipping range will be adjusted to "fit" the whole scene. Clipping + // will still occur if objects in the scene are behind the camera or + // come very close. If AutoAdjustCameraClippingRange is off, no adjustment + // will be made per render, but the camera clipping range will still + // be reset when the camera is reset. + vtkSetClampMacro(AutoAdjustCameraClippingRange, int, 0, 1 ); + vtkGetMacro(AutoAdjustCameraClippingRange, int ); + vtkBooleanMacro(AutoAdjustCameraClippingRange, int ); + + // Description: + // When an event occurs, we must determine which Renderer the event + // occurred within, since one RenderWindow may contain multiple + // renderers. + void FindPokedRenderer(int,int); + + // Description: + // Some useful information for interaction + vtkGetMacro(State,int); + + // Description: + // Set/Get timer hint + vtkGetMacro(UseTimers,int); + vtkSetMacro(UseTimers,int); + vtkBooleanMacro(UseTimers,int); + + // Description: + // Does ProcessEvents handle observers on this class or not + vtkSetMacro(HandleObservers,int); + vtkGetMacro(HandleObservers,int); + vtkBooleanMacro(HandleObservers,int); + + // Description: + // Generic event bindings must be overridden in subclasses + virtual void OnMouseMove() {}; + virtual void OnLeftButtonDown() {}; + virtual void OnLeftButtonUp() {}; + virtual void OnMiddleButtonDown() {}; + virtual void OnMiddleButtonUp() {}; + virtual void OnRightButtonDown() {}; + virtual void OnRightButtonUp() {}; + virtual void OnMouseWheelForward() {}; + virtual void OnMouseWheelBackward() {}; + + // Description: + // OnChar implements keyboard functions, but subclasses can override this + // behavior + virtual void OnChar(); + virtual void OnKeyDown() {}; + virtual void OnKeyUp() {}; + virtual void OnKeyPress() {}; + virtual void OnKeyRelease() {}; + + // Description: + // These are more esoteric events, but are useful in some cases. + virtual void OnExpose() {}; + virtual void OnConfigure() {}; + virtual void OnEnter() {}; + virtual void OnLeave() {}; + + // Description: + // OnTimer calls Rotate, Rotate etc which should be overridden by + // style subclasses. + virtual void OnTimer(); + + // Description: + // These methods for the different interactions in different modes + // are overridden in subclasses to perform the correct motion. Since + // they might be called from OnTimer, they do not have mouse coord parameters + // (use interactor's GetEventPosition and GetLastEventPosition) + virtual void Rotate() {}; + virtual void Spin() {}; + virtual void Pan() {}; + virtual void Dolly() {}; + virtual void Zoom() {}; + virtual void UniformScale() {}; + + // Description: + // utility routines used by state changes + virtual void StartState(int newstate); + virtual void StopState(); + + // Description: + // Interaction mode entry points used internally. + virtual void StartAnimate(); + virtual void StopAnimate(); + virtual void StartRotate(); + virtual void EndRotate(); + virtual void StartZoom(); + virtual void EndZoom(); + virtual void StartPan(); + virtual void EndPan(); + virtual void StartSpin(); + virtual void EndSpin(); + virtual void StartDolly(); + virtual void EndDolly(); + virtual void StartUniformScale(); + virtual void EndUniformScale(); + virtual void StartTimer(); + virtual void EndTimer(); + + // Description: + // When picking successfully selects an actor, this method highlights the + // picked prop appropriately. Currently this is done by placing a bounding + // box around a picked vtkProp3D, and using the PickColor to highlight a + // vtkProp2D. + virtual void HighlightProp(vtkProp *prop); + virtual void HighlightActor2D(vtkActor2D *actor2D); + virtual void HighlightProp3D(vtkProp3D *prop3D); + + // Description: + // Set/Get the pick color (used by default to color vtkActor2D's). + // The color is expressed as red/green/blue values between (0.0,1.0). + vtkSetVector3Macro(PickColor,double); + vtkGetVectorMacro(PickColor, double, 3); + + // Description: + // Set/Get the mouse wheel motion factor. Default to 1.0. Set it to a + // different value to emphasize or de-emphasize the action triggered by + // mouse wheel motion. + vtkSetMacro(MouseWheelMotionFactor, double); + vtkGetMacro(MouseWheelMotionFactor, double); + +protected: + vtkInteractorStyle(); + ~vtkInteractorStyle(); + + // Description: + // Main process event method + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // Keep track of current state + + int State; + int AnimState; + + // Should observers be handled here, should we fire timers + + int HandleObservers; + int UseTimers; + + int AutoAdjustCameraClippingRange; + + // For picking and highlighting props + + vtkOutlineSource *Outline; + vtkPolyDataMapper *OutlineMapper; + vtkActor *OutlineActor; + vtkRenderer *PickedRenderer; + vtkProp *CurrentProp; + vtkActor2D *PickedActor2D; + int PropPicked; // bool: prop picked? + double PickColor[3]; // support 2D picking + double MouseWheelMotionFactor; + +private: + vtkInteractorStyle(const vtkInteractorStyle&); // Not implemented. + void operator=(const vtkInteractorStyle&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleFlight.cxx b/Rendering/vtkInteractorStyleFlight.cxx new file mode 100644 index 0000000..1495275 --- /dev/null +++ b/Rendering/vtkInteractorStyleFlight.cxx @@ -0,0 +1,809 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleFlight.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleFlight.h" + +#include "vtkCamera.h" +#include "vtkPerspectiveTransform.h" +#include "vtkRenderer.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkCommand.h" +#include "vtkWindows.h" + +vtkCxxRevisionMacro(vtkInteractorStyleFlight, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkInteractorStyleFlight); + +class CPIDControl +{ +public: + int m_iDeltaT; + int m_iDeltaTf; + double m_dPrevX; + double m_dKp; + double m_dKd; + double m_dKi; + double m_dXSum; + double m_dDelta; + + double m_dVelSum; + int m_iVelCount; + double m_dVelAvg; +public: + CPIDControl(double dKp, double dKd, double dKi); + double PIDCalc(double dX,double dFinalX); + void SetCoefficients(double dKp, double dKd, double dKi); +}; + +CPIDControl::CPIDControl(double dKp, double dKd, double dKi) +{ + m_dXSum = 0.0; + m_dPrevX = 0.0; + m_dDelta = 0.0; + m_iDeltaT = 0; + m_iDeltaTf = 0; + m_dVelSum = 0.0; + m_iVelCount = 0; + m_dVelAvg = 0.0; + this->SetCoefficients(dKp, dKd, dKi); +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +double CPIDControl::PIDCalc(double dX, double dFinalX) +{ + double dVal = dX - dFinalX; + m_dXSum = m_dXSum + dVal; + // Calculate the velocity + dVal = m_dPrevX - dX; + // Average the velocity + m_dVelSum += dVal; + m_iVelCount++; + if(m_iVelCount >= 10) + { + m_dVelAvg = m_dVelSum/(double)m_iVelCount; + m_iVelCount = 0; + m_dVelSum = 0.0; + } + m_dDelta = m_dKp*dX + m_dKd*m_dVelAvg + m_dKi*m_dXSum; + m_dPrevX = dX; + + return m_dDelta; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CPIDControl::SetCoefficients(double dKp, double dKd, double dKi) +{ + m_dKp = dKp; + m_dKd = dKd; + m_dKi = dKi; + // should reset internal params here, but no need for this simple usage +} + + +//--------------------------------------------------------------------------- +vtkInteractorStyleFlight::vtkInteractorStyleFlight() +{ + this->KeysDown = 0; + this->UseTimers = 1; + + this->DiagonalLength = 1.0; + this->MotionStepSize = 1.0/250.0; + this->MotionUserScale = 1.0; // +/- key adjustment + this->MotionAccelerationFactor = 10.0; + this->AngleStepSize = 1.0; + this->AngleAccelerationFactor = 5.0; + + this->DisableMotion = 0; + this->RestoreUpVector = 1; + this->DefaultUpVector[0] = 0; + this->DefaultUpVector[1] = 0; + this->DefaultUpVector[2] = 1; + // + PID_Yaw = new CPIDControl(-0.05, 0.0, -0.0008); + PID_Pitch = new CPIDControl(-0.05, 0.0, -0.0008); + Transform = vtkPerspectiveTransform::New(); +} + +//--------------------------------------------------------------------------- +vtkInteractorStyleFlight::~vtkInteractorStyleFlight() +{ + Transform->Delete(); + delete PID_Yaw; + delete PID_Pitch; +} +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::ForwardFly() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + // + if (this->KeysDown) + { + this->FlyByKey(camera); + } + else + { + this->UpdateSteering(camera); + this->FlyByMouse(camera); + } + // + this->FinishCamera(camera); +} +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::ReverseFly() +{ + // The code is the same, just the state variable that is tracked... + ForwardFly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleFlight::StartForwardFly() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_FORWARDFLY); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleFlight::EndForwardFly() +{ + if (this->State != VTKIS_FORWARDFLY) + { + return; + } + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleFlight::StartReverseFly() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_REVERSEFLY); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleFlight::EndReverseFly() +{ + if (this->State != VTKIS_REVERSEFLY) + { + return; + } + this->StopState(); +} + +//--------------------------------------------------------------------------- +// All actual motion is performed in the timer +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnTimer() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + + switch (this->State) + { + case VTKIS_FORWARDFLY: + this->ForwardFly(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + case VTKIS_REVERSEFLY: + this->ReverseFly(); + if (this->UseTimers) + { + rwi->CreateTimer(VTKI_TIMER_UPDATE); + } + break; + + default: + break; + } +} + +//--------------------------------------------------------------------------- +// Mouse event handlers +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->FindPokedRenderer(x, y); + vtkCamera* cam = this->CurrentRenderer->GetActiveCamera(); + switch (this->State) + { + case VTKIS_FORWARDFLY: + case VTKIS_REVERSEFLY: + this->UpdateMouseSteering(cam); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnLeftButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->FindPokedRenderer(x, y); + if (this->CurrentRenderer == NULL) + { + return; + } + // + vtkCamera* cam = this->CurrentRenderer->GetActiveCamera(); + switch (this->State) + { + case VTKIS_REVERSEFLY: + this->State = VTKIS_FORWARDFLY; + break; + default : + this->SetupMotionVars(cam); + this->StartForwardFly(); + break; + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnLeftButtonUp() +{ + switch (this->State) + { + case VTKIS_FORWARDFLY: + this->EndForwardFly(); + break; + default : + break; + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnMiddleButtonDown() +{ +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnMiddleButtonUp() +{ +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnRightButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->FindPokedRenderer(x, y); + if (this->CurrentRenderer == NULL) + { + return; + } + // + vtkCamera* cam = this->CurrentRenderer->GetActiveCamera(); + switch (this->State) + { + case VTKIS_FORWARDFLY: + this->State = VTKIS_REVERSEFLY; + break; + default : + this->SetupMotionVars(cam); + this->StartReverseFly(); + break; + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnRightButtonUp() +{ + switch (this->State) + { + case VTKIS_REVERSEFLY: + this->EndReverseFly(); + break; + default : + break; + } +} + +//--------------------------------------------------------------------------- +// Keyboard event handlers +// Note, OnChar is a key press down and then up event +// Note, OnKeyDown/OnKeyUp are more sensitive for controlling motion +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnKeyDown() +{ + // New Flight mode behaviour + // Note that we'll need #defines for ARROW key defs under non win32 OS +#ifdef _WIN32 + switch (this->Interactor->GetKeyCode()) + { + case VK_LEFT : this->KeysDown |=1; break; + case VK_RIGHT : this->KeysDown |=2; break; + case VK_UP : this->KeysDown |=4; break; + case VK_DOWN : this->KeysDown |=8; break; + case 'a': + case 'A' : this->KeysDown |=16; break; + case 'z': + case 'Z' : this->KeysDown |=32; break; + } + if ((this->KeysDown & (32+16)) == (32+16)) + { + if (this->State==VTKIS_FORWARDFLY) + { + this->EndForwardFly(); + } + if (this->State==VTKIS_REVERSEFLY) + { + this->EndReverseFly(); + } + } + else if ((this->KeysDown & 32) == 32) + { + if (this->State==VTKIS_FORWARDFLY) + { + this->EndForwardFly(); + } + this->StartReverseFly(); + } + else if ((this->KeysDown & 16) == 16) + { + if (this->State==VTKIS_REVERSEFLY) + { + this->EndReverseFly(); + } + this->StartForwardFly(); + } +#else + // the following if statement is a dummy one to prevent keycode not used + // warnings under unix, (until the correct keycodes are supplied) + if (this->Interactor->GetKeyCode() == 0x7F) + { + vtkWarningMacro(<<"Dummy test to prevent compiler warning"); + } +#endif +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnKeyUp() +{ +#ifdef _WIN32 + switch (this->Interactor->GetKeyCode()) + { + case VK_LEFT : this->KeysDown &= ~1; break; + case VK_RIGHT : this->KeysDown &= ~2; break; + case VK_UP : this->KeysDown &= ~4; break; + case VK_DOWN : this->KeysDown &= ~8; break; + case 'a': + case 'A' : this->KeysDown &= ~16; break; + case 'z': + case 'Z' : this->KeysDown &= ~32; break; + } + switch (this->State) + { + case VTKIS_FORWARDFLY: + if ((this->KeysDown & 16) == 0) + { + this->EndForwardFly(); + } + break; + case VTKIS_REVERSEFLY: + if ((this->KeysDown & 32) == 0) + { + this->EndReverseFly(); + } + break; + } +#else + // the following if statement is a dummy one to prevent keycode not used + // warnings under unix, (until the correct keycodes are supplied) + if (this->Interactor->GetKeyCode() == 0x7F) + { + vtkWarningMacro(<<"Dummy test to prevent compiler warning"); + } +#endif +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::OnChar() +{ + switch (this->Interactor->GetKeyCode()) + { + case '+' : + this->MotionUserScale *= 2.0; + break; + case '-' : + this->MotionUserScale *= 0.5; + break; + default: + this->Superclass::OnChar(); + break; + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::JumpTo(double campos[3], double focpos[3]) +{ + if (this->CurrentRenderer == NULL) + { + return; + } + vtkCamera* cam = this->CurrentRenderer->GetActiveCamera(); + cam->SetPosition(campos); + cam->SetFocalPoint(focpos); + FinishCamera(cam); + this->Interactor->Render(); +} + +void vtkInteractorStyleFlight::FinishCamera(vtkCamera* cam) +{ + cam->OrthogonalizeViewUp(); + if (this->RestoreUpVector) + { + double delta[3]; + cam->GetViewUp(delta); + double weight = vtkMath::Dot(this->DefaultUpVector,delta); + // only correct up if we're close to it already... + if (weight>0.3) { + weight = 0.25*fabs(weight); + delta[0] = delta[0] + (this->DefaultUpVector[0]-delta[0])*weight; + delta[1] = delta[1] + (this->DefaultUpVector[1]-delta[1])*weight; + delta[2] = delta[2] + (this->DefaultUpVector[2]-delta[2])*weight; + cam->SetViewUp(delta); + } + } + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + if (this->Interactor->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } +} + +//--------------------------------------------------------------------------- +// Use this mouse pos and last mouse pos to get the amount of motion +// Compute an "Ideal" focal point, The flight will sterr towards this ideal +// point, but will be damped in Yaw/Pitch by our PID Controllers. +// The damping and motion is done in the timer event. +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::UpdateMouseSteering(vtkCamera *cam) +{ + int *thispos = this->Interactor->GetEventPosition(); + int *lastpos = this->Interactor->GetLastEventPosition(); + + double aspeed = this->AngleStepSize*(this->Interactor->GetShiftKey() ? + this->AngleAccelerationFactor : 1.0); + // + // we want to steer by an amount proportional to window viewangle and size + // compute dx and dy increments relative to last mouse click + int *size = this->Interactor->GetSize(); + double scalefactor = 5*cam->GetViewAngle()/(double)size[0]; + double dx = - (thispos[0] - lastpos[0])*scalefactor*aspeed; + double dy = (thispos[1] - lastpos[1])*scalefactor*aspeed; + + // Temporary until I get smooth flight working + this->DeltaPitch = dy; + this->DeltaYaw = dx; +/* + Not happy with smooth flight yet, please levae this code here + until I get around to experimenting : JB July 2002 + + // dx and dy need to be converted to a new 'ideal' camera focal point + // we maintain an actual FocalPoint and an IdealFocalPoint so that we can + // smooth the motion using our PID controllers (one for yaw, one for pitch). + cam->OrthogonalizeViewUp(); + double LRaxis[3]; + double *ViewUp = cam->GetViewUp(); + double *Position = cam->GetPosition(); + double *FocalPoint = cam->GetFocalPoint(); + this->GetLRVector(LRaxis, cam); + // + this->Transform->Identity(); + this->Transform->Translate(+Position[0],+Position[1],+Position[2]); + this->Transform->RotateWXYZ(dx, ViewUp); + this->Transform->RotateWXYZ(dy, LRaxis); + this->Transform->Translate(-Position[0],-Position[1],-Position[2]); + this->Transform->TransformPoint(this->IdealFocalPoint,this->IdealFocalPoint); +*/ +} + +#define D2R 0.01745329251994329576923690768 // degrees to radians +#define R2D 57.2957795130823208767981548141 // radians to degrees + +// We know the ideal and actual focal points. We now want to reduce these +// to a 2D Yaw+Pitch form so that we can smooth the motion on each +void vtkInteractorStyleFlight::UpdateSteering(vtkCamera *vtkNotUsed(cam)) +{ +/* + Not happy with smooth flight yet, please levae this code here + until I get around to experimenting : JB July 2002 + + cam->OrthogonalizeViewUp(); + double *Position = cam->GetPosition(); + double *FocalPoint = cam->GetFocalPoint(); + double vec1[3], vec2[3], norm1[3], norm2[3]; + vec1[0] = FocalPoint[0]-Position[0]; + vec1[1] = FocalPoint[1]-Position[1]; + vec1[2] = FocalPoint[2]-Position[2]; + vec2[0] = this->IdealFocalPoint[0]-Position[0]; + vec2[1] = this->IdealFocalPoint[1]-Position[1]; + vec2[2] = this->IdealFocalPoint[2]-Position[2]; + // what's the azimuthal angle between the Ideal and actual focal points + // angle between planes given by Up/Focus and Up/IdealFocus + double *ViewUp = cam->GetViewUp(); + vtkMath::Cross(vec1, ViewUp, norm1); + vtkMath::Cross(vec2, ViewUp, norm2); + vtkMath::Normalize(norm1); + vtkMath::Normalize(norm2); + // + double dot = vtkMath::Dot(norm1, norm2); + if (dot>1.0) { + dot = 1.0; + } + else if (dot<-1.0) { + dot =-1.0; + } + double yaw = R2D*acos(dot); + // we know the angle, but is it +ve or -ve (which side is new focal point) + double d1,d2; + d1 = vtkMath::Dot(norm1,this->IdealFocalPoint); + d2 = vtkMath::Dot(norm1,FocalPoint); + if (d1-d2>0) yaw = -yaw; + // + // what's the elevation angle between the Ideal and actual focal points + // angle between planes given by LR/Focus and LR/IdealFocus + double LRaxis[3]; + this->GetLRVector(LRaxis, cam); + vtkMath::Cross(vec1, LRaxis, norm1); + vtkMath::Cross(vec2, LRaxis, norm2); + vtkMath::Normalize(norm1); + vtkMath::Normalize(norm2); + // + dot = vtkMath::Dot(norm1, norm2); + if (dot>1.0) { + dot = 1.0; + } else if (dot<-1.0) { + dot =-1.0; + } + double pitch = R2D*acos(dot); + d1 = vtkMath::Dot(norm1,this->IdealFocalPoint); + d2 = vtkMath::Dot(norm1,FocalPoint); + if (d1-d2>0) pitch = -pitch; + + // use our motion dampers to reduce the yaw/pitch errors to zero gradually +// this->DeltaYaw = PID_Yaw->PIDCalc(yaw, 0); +// this->DeltaPitch = PID_Pitch->PIDCalc(pitch, 0); + + this->DeltaPitch = 0.75*pitch + 0.25*lPitch; + lPitch = pitch; + + this->DeltaYaw = 0.75*yaw + 0.25*lYaw; + lYaw = yaw; + +*/ +} + +//--------------------------------------------------------------------------- +// useful utility functions +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::SetupMotionVars(vtkCamera *cam) +{ + lPitch = 0; + lYaw = 0; + cam->GetFocalPoint(IdealFocalPoint); + + double bounds[6]; + this->CurrentRenderer->ComputeVisiblePropBounds( bounds ); + if ( !vtkMath::AreBoundsInitialized(bounds) ) + { + this->DiagonalLength = 1.0; + } + else + { + this->DiagonalLength = + sqrt( (bounds[0] - bounds[1]) * (bounds[0] - bounds[1]) + + (bounds[2] - bounds[3]) * (bounds[2] - bounds[3]) + + (bounds[4] - bounds[5]) * (bounds[4] - bounds[5]) ); + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::MotionAlongVector(double vector[3], + double amount, vtkCamera* cam) +{ + double oldcampos[3], oldcamfoc[3]; + cam->GetPosition(oldcampos); + cam->GetFocalPoint(oldcamfoc); + // move camera and focus along DirectionOfProjection + cam->SetPosition( + oldcampos[0] - amount * vector[0], + oldcampos[1] - amount * vector[1], + oldcampos[2] - amount * vector[2]); + cam->SetFocalPoint( + oldcamfoc[0] - amount * vector[0], + oldcamfoc[1] - amount * vector[1], + oldcamfoc[2] - amount * vector[2]); +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::GetLRVector(double vector[3], vtkCamera* cam) +{ + vtkMatrix4x4 *vtm; + vtm = cam->GetViewTransformMatrix(); + vector[0] = vtm->GetElement(0,0); + vector[1] = vtm->GetElement(0,1); + vector[2] = vtm->GetElement(0,2); +} + +//--------------------------------------------------------------------------- +// Perform the motion +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::FlyByMouse(vtkCamera* cam) +{ + double a_vector[3]; + double speed = this->DiagonalLength * this->MotionStepSize * this->MotionUserScale; + speed = speed * ( this->Interactor->GetShiftKey() ? this->MotionAccelerationFactor : 1.0); + if (this->DisableMotion) + { + speed = 0; + } + // Sidestep (convert steering angles to left right movement : + // only because I added this after doing the angles earlier + if (this->Interactor->GetControlKey()) + { + if (this->DeltaYaw!=0.0) + { + this->GetLRVector(a_vector, cam); + this->MotionAlongVector(a_vector,-this->DeltaYaw*speed/2.0, cam); + } + if (this->DeltaPitch!=0.0) + { + cam->GetViewUp(a_vector); + this->MotionAlongVector(a_vector,-this->DeltaPitch*speed/2.0, cam); + } + } + else + { + cam->Yaw(this->DeltaYaw); + cam->Pitch(this->DeltaPitch); + this->DeltaYaw = 0; + this->DeltaPitch = 0; + // cam->SetFocalPoint(this->IdealFocalPoint); + } + // + if (!this->Interactor->GetControlKey()) + { + cam->GetDirectionOfProjection(a_vector); // reversed (use -speed) + switch (this->State) + { + case VTKIS_FORWARDFLY: + this->MotionAlongVector(a_vector, -speed, cam); + break; + case VTKIS_REVERSEFLY: + this->MotionAlongVector(a_vector, speed, cam); + break; + } + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::FlyByKey(vtkCamera* cam) +{ + double speed = this->DiagonalLength * this->MotionStepSize * this->MotionUserScale; + speed = speed * ( this->Interactor->GetShiftKey() ? this->MotionAccelerationFactor : 1.0); + if (this->DisableMotion) + { + speed = 0; + } + // + double aspeed = this->AngleStepSize* (this->Interactor->GetShiftKey() ? this->AngleAccelerationFactor : 1.0); + double a_vector[3]; + // Left and right + if (this->Interactor->GetControlKey()) + { // Sidestep + this->GetLRVector(a_vector, cam); + if (this->KeysDown & 1) + { + this->MotionAlongVector(a_vector,-speed, cam); + } + if (this->KeysDown & 2) + { + this->MotionAlongVector(a_vector, speed, cam); + } + } + else + { + if (this->KeysDown & 1) + { + cam->Yaw( aspeed); + } + if (this->KeysDown & 2) + { + cam->Yaw(-aspeed); + } + } + + // Up and Down + if (this->Interactor->GetControlKey()) + { // Sidestep + cam->GetViewUp(a_vector); + if (this->KeysDown & 4) + { + this->MotionAlongVector(a_vector,-speed, cam); + } + if (this->KeysDown & 8) + { + this->MotionAlongVector(a_vector, speed, cam); + } + } + else + { + if (this->KeysDown & 4) + { + cam->Pitch(-aspeed); + } + if (this->KeysDown & 8) + { + cam->Pitch( aspeed); + } + } + + // forward and backward + cam->GetDirectionOfProjection(a_vector); + if (this->KeysDown & 16) + { + this->MotionAlongVector(a_vector, speed, cam); + } + if (this->KeysDown & 32) + { + this->MotionAlongVector(a_vector,-speed, cam); + } +} + +//--------------------------------------------------------------------------- +void vtkInteractorStyleFlight::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "MotionStepSize: " + << this->MotionStepSize << "\n"; + os << indent << "MotionAccelerationFactor: " + << this->MotionAccelerationFactor << "\n"; + os << indent << "AngleStepSize: " + << this->AngleStepSize << "\n"; + os << indent << "AngleAccelerationFactor: " + << this->AngleAccelerationFactor << "\n"; + os << indent << "MotionUserScale: " + << this->MotionUserScale << "\n"; + os << indent << "DisableMotion: " + << this->DisableMotion << "\n"; + os << indent << "RestoreUpVector: " + << this->RestoreUpVector << "\n"; + os << indent << "DefaultUpVector: " + << this->DefaultUpVector[0] << " " + << this->DefaultUpVector[1] << " " + << this->DefaultUpVector[2] << "\n"; +} + + diff --git a/Rendering/vtkInteractorStyleFlight.h b/Rendering/vtkInteractorStyleFlight.h new file mode 100644 index 0000000..2f5cc9a --- /dev/null +++ b/Rendering/vtkInteractorStyleFlight.h @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleFlight.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkInteractorStyleFlight - provides flight motion routines +// +// .SECTION Description +// Left mouse button press produces forward motion. +// Right mouse button press produces reverse motion. +// Moving mouse during motion steers user in desired direction. +// Keyboard controls are: +// Left/Right/Up/Down Arrows for steering direction +// 'A' forward, 'Z' reverse motion +// Ctrl Key causes sidestep instead of steering in mouse and key modes +// Shift key is accelerator in mouse and key modes +// Ctrl and Shift together causes Roll in mouse and key modes +// +// By default, one "step" of motion corresponds to 1/250th of the diagonal +// of bounding box of visible actors, '+' and '-' keys allow user to +// increase or decrease step size. + +#ifndef __vtkInteractorStyleFlight_h +#define __vtkInteractorStyleFlight_h + +#include "vtkInteractorStyle.h" +class vtkCamera; +class vtkPerspectiveTransform; +//BTX +class CPIDControl; +//ETX + +class VTK_RENDERING_EXPORT vtkInteractorStyleFlight : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleFlight *New(); + vtkTypeRevisionMacro(vtkInteractorStyleFlight,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Move the Eye/Camera to a specific location (no intermediate + // steps are taken + void JumpTo(double campos[3], double focpos[3]); + + // Description: + // Set the basic unit step size : by default 1/250 of bounding diagonal + vtkSetMacro(MotionStepSize,double); + vtkGetMacro(MotionStepSize,double); + + // Description: + // Set acceleration factor when shift key is applied : default 10 + vtkSetMacro(MotionAccelerationFactor,double); + vtkGetMacro(MotionAccelerationFactor,double); + + // Description: + // Set the basic angular unit for turning : default 1 degree + vtkSetMacro(AngleStepSize,double); + vtkGetMacro(AngleStepSize,double); + + // Description: + // Set angular acceleration when shift key is applied : default 5 + vtkSetMacro(AngleAccelerationFactor,double); + vtkGetMacro(AngleAccelerationFactor,double); + + // Description: + // Disable motion (temporarily - for viewing etc) + vtkSetMacro(DisableMotion,int); + vtkGetMacro(DisableMotion,int); + vtkBooleanMacro(DisableMotion,int); + + // Description: + // When flying, apply a restorative force to the "Up" vector. + // This is activated when the current 'up' is close to the actual 'up' + // (as defined in DefaultUpVector). This prevents excessive twisting forces + // when viewing from arbitrary angles, but keep the horizon level when + // the user is flying over terrain. + vtkSetMacro(RestoreUpVector,int); + vtkGetMacro(RestoreUpVector,int); + vtkBooleanMacro(RestoreUpVector,int); + + // Specify "up" (by default {0,0,1} but can be changed) + vtkGetVectorMacro(DefaultUpVector,double,3); + vtkSetVectorMacro(DefaultUpVector,double,3); + + // Description: + // Concrete implementation of Mouse event bindings for flight + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // Description: + // Concrete implementation of Keyboard event bindings for flight + virtual void OnChar(); + virtual void OnKeyDown(); + virtual void OnKeyUp(); + virtual void OnTimer(); + // + virtual void ForwardFly(); + virtual void ReverseFly(); + // + virtual void StartForwardFly(); + virtual void EndForwardFly(); + virtual void StartReverseFly(); + virtual void EndReverseFly(); + +protected: + vtkInteractorStyleFlight(); + ~vtkInteractorStyleFlight(); + + // Description: + // Routines used internally for computing motion and steering + void UpdateSteering(vtkCamera *cam); + void UpdateMouseSteering(vtkCamera *cam); + void FlyByMouse(vtkCamera* cam); + void FlyByKey(vtkCamera* cam); + void GetLRVector(double vector[3], vtkCamera* cam); + void MotionAlongVector(double vector[3], double amount, vtkCamera* cam); + void SetupMotionVars(vtkCamera *cam); + void FinishCamera(vtkCamera* cam); + // + // + unsigned char KeysDown; + int DisableMotion; + int RestoreUpVector; + double DiagonalLength; + double MotionStepSize; + double MotionUserScale; + double MotionAccelerationFactor; + double AngleStepSize; + double AngleAccelerationFactor; + double DefaultUpVector[3]; + double AzimuthStepSize; + double IdealFocalPoint[3]; + vtkPerspectiveTransform *Transform; + double DeltaYaw; + double lYaw; + double DeltaPitch; + double lPitch; +//BTX + CPIDControl *PID_Yaw; + CPIDControl *PID_Pitch; +//ETX +private: + vtkInteractorStyleFlight(const vtkInteractorStyleFlight&); // Not implemented. + void operator=(const vtkInteractorStyleFlight&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleImage.cxx b/Rendering/vtkInteractorStyleImage.cxx new file mode 100644 index 0000000..00c926c --- /dev/null +++ b/Rendering/vtkInteractorStyleImage.cxx @@ -0,0 +1,277 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleImage.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleImage.h" + +#include "vtkAbstractPropPicker.h" +#include "vtkAssemblyPath.h" +#include "vtkCommand.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindowInteractor.h" + +vtkCxxRevisionMacro(vtkInteractorStyleImage, "$Revision: 1.25 $"); +vtkStandardNewMacro(vtkInteractorStyleImage); + +//---------------------------------------------------------------------------- +vtkInteractorStyleImage::vtkInteractorStyleImage() +{ + this->WindowLevelStartPosition[0] = 0; + this->WindowLevelStartPosition[1] = 0; + + this->WindowLevelCurrentPosition[0] = 0; + this->WindowLevelCurrentPosition[1] = 0; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleImage::~vtkInteractorStyleImage() +{ +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::StartWindowLevel() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_WINDOW_LEVEL); + this->InvokeEvent(vtkCommand::StartWindowLevelEvent,this); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::EndWindowLevel() +{ + if (this->State != VTKIS_WINDOW_LEVEL) + { + return; + } + this->InvokeEvent(vtkCommand::EndWindowLevelEvent, this); + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::StartPick() +{ + if (this->State != VTKIS_NONE) + { + return; + } + this->StartState(VTKIS_PICK); + this->InvokeEvent(vtkCommand::StartPickEvent, this); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::EndPick() +{ + if (this->State != VTKIS_PICK) + { + return; + } + this->InvokeEvent(vtkCommand::EndPickEvent, this); + this->StopState(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + switch (this->State) + { + case VTKIS_WINDOW_LEVEL: + this->FindPokedRenderer(x, y); + this->WindowLevel(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_PICK: + this->FindPokedRenderer(x, y); + this->Pick(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + } + + // Call parent to handle all other states and perform additional work + + this->Superclass::OnMouseMove(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::OnLeftButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + if (this->CurrentRenderer == NULL) + { + return; + } + + // Redefine this button to handle window/level + + if (!this->Interactor->GetShiftKey() && !this->Interactor->GetControlKey()) + { + this->WindowLevelStartPosition[0] = x; + this->WindowLevelStartPosition[1] = y; + this->StartWindowLevel(); + } + + // The rest of the button + key combinations remain the same + + else + { + this->Superclass::OnLeftButtonDown(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::OnLeftButtonUp() +{ + switch (this->State) + { + case VTKIS_WINDOW_LEVEL: + this->EndWindowLevel(); + break; + } + + // Call parent to handle all other states and perform additional work + + this->Superclass::OnLeftButtonUp(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::OnRightButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + if (this->CurrentRenderer == NULL) + { + return; + } + + // Redefine this button + shift to handle pick + + if (this->Interactor->GetShiftKey()) + { + this->StartPick(); + } + + // The rest of the button + key combinations remain the same + + else + { + this->Superclass::OnRightButtonDown(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::OnRightButtonUp() +{ + switch (this->State) + { + case VTKIS_PICK: + this->EndPick(); + break; + } + + // Call parent to handle all other states and perform additional work + + this->Superclass::OnRightButtonUp(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::OnChar() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + + switch (rwi->GetKeyCode()) + { + case 'f' : + case 'F' : + { + this->AnimState = VTKIS_ANIM_ON; + vtkAssemblyPath *path=NULL; + this->FindPokedRenderer(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1]); + rwi->GetPicker()->Pick(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1], 0.0, + this->CurrentRenderer); + vtkAbstractPropPicker *picker; + if ( (picker=vtkAbstractPropPicker::SafeDownCast(rwi->GetPicker())) ) + { + path = picker->GetPath(); + } + if ( path != NULL ) + { + rwi->FlyToImage(this->CurrentRenderer,picker->GetPickPosition()); + } + this->AnimState = VTKIS_ANIM_OFF; + break; + } + + case 'r' : + case 'R' : + // Allow either shift/ctrl to trigger the usual 'r' binding + // otherwise trigger reset window level event + if (rwi->GetShiftKey() || rwi->GetControlKey()) + { + this->Superclass::OnChar(); + } + else + { + this->InvokeEvent(vtkCommand::ResetWindowLevelEvent, this); + } + break; + + default: + this->Superclass::OnChar(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::WindowLevel() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + + this->WindowLevelCurrentPosition[0] = rwi->GetEventPosition()[0]; + this->WindowLevelCurrentPosition[1] = rwi->GetEventPosition()[1]; + + this->InvokeEvent(vtkCommand::WindowLevelEvent, this); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::Pick() +{ + this->InvokeEvent(vtkCommand::PickEvent, this); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleImage::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Window Level Current Position: (" + << this->WindowLevelCurrentPosition[0] << ", " + << this->WindowLevelCurrentPosition[1] << ")" << endl; + + os << indent << "Window Level Start Position: (" + << this->WindowLevelStartPosition[0] << ", " + << this->WindowLevelStartPosition[1] << ")" << endl; +} diff --git a/Rendering/vtkInteractorStyleImage.h b/Rendering/vtkInteractorStyleImage.h new file mode 100644 index 0000000..d1c7138 --- /dev/null +++ b/Rendering/vtkInteractorStyleImage.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleImage.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleImage - interactive manipulation of the camera specialized for images +// .SECTION Description +// vtkInteractorStyleImage allows the user to interactively manipulate +// (rotate, pan, zoomm etc.) the camera. vtkInteractorStyleImage is specially +// designed to work with images that are being rendered with +// vtkImageActor. Several events are overloaded from its superclass +// vtkInteractorStyle, hence the mouse bindings are different. (The bindings +// keep the camera's view plane normal perpendicular to the x-y plane.) In +// summary the mouse events are as follows: +// + Left Mouse button triggers window level events +// + CTRL Left Mouse spins the camera around its view plane normal +// + SHIFT Left Mouse pans the camera +// + CTRL SHIFT Left Mouse dollys (a positional zoom) the camera +// + Middle mouse button pans the camera +// + Right mouse button dollys the camera. +// + SHIFT Right Mouse triggers pick events +// +// Note that the renderer's actors are not moved; instead the camera is moved. + +// .SECTION See Also +// vtkInteractorStyle vtkInteractorStyleTrackballActor +// vtkInteractorStyleJoystickCamera vtkInteractorStyleJoystickActor + +#ifndef __vtkInteractorStyleImage_h +#define __vtkInteractorStyleImage_h + +#include "vtkInteractorStyleTrackballCamera.h" + +// Motion flags + +#define VTKIS_WINDOW_LEVEL 1024 +#define VTKIS_PICK 1025 + +class VTK_RENDERING_EXPORT vtkInteractorStyleImage : public vtkInteractorStyleTrackballCamera +{ +public: + static vtkInteractorStyleImage *New(); + vtkTypeRevisionMacro(vtkInteractorStyleImage, vtkInteractorStyleTrackballCamera); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Some useful information for handling window level + vtkGetVector2Macro(WindowLevelStartPosition,int); + vtkGetVector2Macro(WindowLevelCurrentPosition,int); + + // Description: + // Event bindings controlling the effects of pressing mouse buttons + // or moving the mouse. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // Description: + // Override the "fly-to" (f keypress) for images. + virtual void OnChar(); + + // These methods for the different interactions in different modes + // are overridden in subclasses to perform the correct motion. Since + // they might be called from OnTimer, they do not have mouse coord parameters + // (use interactor's GetEventPosition and GetLastEventPosition) + virtual void WindowLevel(); + virtual void Pick(); + + // Interaction mode entry points used internally. + virtual void StartWindowLevel(); + virtual void EndWindowLevel(); + virtual void StartPick(); + virtual void EndPick(); + +protected: + vtkInteractorStyleImage(); + ~vtkInteractorStyleImage(); + + int WindowLevelStartPosition[2]; + int WindowLevelCurrentPosition[2]; + +private: + vtkInteractorStyleImage(const vtkInteractorStyleImage&); // Not implemented. + void operator=(const vtkInteractorStyleImage&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleJoystickActor.cxx b/Rendering/vtkInteractorStyleJoystickActor.cxx new file mode 100644 index 0000000..02d9455 --- /dev/null +++ b/Rendering/vtkInteractorStyleJoystickActor.cxx @@ -0,0 +1,607 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleJoystickActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleJoystickActor.h" + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkProp3D.h" +#include "vtkRenderer.h" +#include "vtkCellPicker.h" +#include "vtkTransform.h" +#include "vtkMatrix4x4.h" + +vtkCxxRevisionMacro(vtkInteractorStyleJoystickActor, "$Revision: 1.31 $"); +vtkStandardNewMacro(vtkInteractorStyleJoystickActor); + +//---------------------------------------------------------------------------- +vtkInteractorStyleJoystickActor::vtkInteractorStyleJoystickActor() +{ + this->MotionFactor = 10.0; + this->InteractionProp = NULL; + this->InteractionPicker = vtkCellPicker::New(); + this->InteractionPicker->SetTolerance(0.001); + + // Use timers to handle continous interaction + this->UseTimers = 1; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleJoystickActor::~vtkInteractorStyleJoystickActor() +{ + this->InteractionPicker->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + switch (this->State) + { + case VTKIS_ROTATE: + case VTKIS_PAN: + case VTKIS_DOLLY: + case VTKIS_SPIN: + case VTKIS_USCALE: + this->FindPokedRenderer(x, y); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::OnLeftButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + this->FindPickedActor(x, y); + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + if (this->Interactor->GetShiftKey()) + { + this->StartPan(); + } + else if (this->Interactor->GetControlKey()) + { + this->StartSpin(); + } + else + { + this->StartRotate(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::OnLeftButtonUp() +{ + switch (this->State) + { + case VTKIS_PAN: + this->EndPan(); + break; + + case VTKIS_SPIN: + this->EndSpin(); + break; + + case VTKIS_ROTATE: + this->EndRotate(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::OnMiddleButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + this->FindPickedActor(x, y); + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + if (this->Interactor->GetControlKey()) + { + this->StartDolly(); + } + else + { + this->StartPan(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::OnMiddleButtonUp() +{ + switch (this->State) + { + case VTKIS_DOLLY: + this->EndDolly(); + break; + + case VTKIS_PAN: + this->EndPan(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::OnRightButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + this->FindPickedActor(x, y); + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + this->StartUniformScale(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::OnRightButtonUp() +{ + switch (this->State) + { + case VTKIS_USCALE: + this->EndUniformScale(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::Rotate() +{ + if ( this->CurrentRenderer == NULL || this->InteractionProp == NULL ) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + + // First get the origin of the assembly + double *obj_center = this->InteractionProp->GetCenter(); + + // GetLength gets the length of the diagonal of the bounding box + double boundRadius = this->InteractionProp->GetLength() * 0.5; + + // Get the view up and view right vectors + double view_up[3], view_look[3], view_right[3]; + + cam->OrthogonalizeViewUp(); + cam->ComputeViewPlaneNormal(); + cam->GetViewUp(view_up); + vtkMath::Normalize(view_up); + cam->GetViewPlaneNormal(view_look); + vtkMath::Cross(view_up, view_look, view_right); + vtkMath::Normalize(view_right); + + // Get the furtherest point from object bounding box center + double outsidept[3]; + + outsidept[0] = obj_center[0] + view_right[0] * boundRadius; + outsidept[1] = obj_center[1] + view_right[1] * boundRadius; + outsidept[2] = obj_center[2] + view_right[2] * boundRadius; + + // Convert to display coord + double disp_obj_center[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2], + disp_obj_center); + + this->ComputeWorldToDisplay(outsidept[0], outsidept[1], outsidept[2], + outsidept); + + double radius = sqrt(vtkMath::Distance2BetweenPoints(disp_obj_center, + outsidept)); + + double nxf = + ((double)rwi->GetEventPosition()[0] - (double)disp_obj_center[0]) / radius; + + double nyf = + ((double)rwi->GetEventPosition()[1] - (double)disp_obj_center[1]) / radius; + + if (nxf > 1.0) + { + nxf = 1.0; + } + else if (nxf < -1.0) + { + nxf = -1.0; + } + + if (nyf > 1.0) + { + nyf = 1.0; + } + else if (nyf < -1.0) + { + nyf = -1.0; + } + + double newXAngle = + asin(nxf) * vtkMath::RadiansToDegrees() / this->MotionFactor; + + double newYAngle = + asin(nyf) * vtkMath::RadiansToDegrees() / this->MotionFactor; + + double scale[3]; + scale[0] = scale[1] = scale[2] = 1.0; + + double **rotate = new double*[2]; + + rotate[0] = new double[4]; + rotate[1] = new double[4]; + + rotate[0][0] = newXAngle; + rotate[0][1] = view_up[0]; + rotate[0][2] = view_up[1]; + rotate[0][3] = view_up[2]; + + rotate[1][0] = -newYAngle; + rotate[1][1] = view_right[0]; + rotate[1][2] = view_right[1]; + rotate[1][3] = view_right[2]; + + this->Prop3DTransform(this->InteractionProp, + obj_center, + 2, + rotate, + scale); + + delete [] rotate[0]; + delete [] rotate[1]; + delete [] rotate; + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::Spin() +{ + if ( this->CurrentRenderer == NULL || this->InteractionProp == NULL ) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + + // Get the axis to rotate around = vector from eye to origin + double *obj_center = this->InteractionProp->GetCenter(); + + double motion_vector[3]; + double view_point[3]; + + if (cam->GetParallelProjection()) + { + // If parallel projection, want to get the view plane normal... + cam->ComputeViewPlaneNormal(); + cam->GetViewPlaneNormal(motion_vector); + } + else + { + // Perspective projection, get vector from eye to center of actor + cam->GetPosition(view_point); + motion_vector[0] = view_point[0] - obj_center[0]; + motion_vector[1] = view_point[1] - obj_center[1]; + motion_vector[2] = view_point[2] - obj_center[2]; + vtkMath::Normalize(motion_vector); + } + + double disp_obj_center[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1],obj_center[2], + disp_obj_center); + + double *center = this->CurrentRenderer->GetCenter(); + + double yf = + ((double)rwi->GetEventPosition()[1] - (double)disp_obj_center[1]) / (double)center[1]; + + if (yf > 1.0) + { + yf = 1.0; + } + else if (yf < -1.0) + { + yf = -1.0; + } + + double newAngle = + asin(yf) * vtkMath::RadiansToDegrees() / this->MotionFactor; + + double scale[3]; + scale[0] = scale[1] = scale[2] = 1.0; + + double **rotate = new double*[1]; + rotate[0] = new double[4]; + + rotate[0][0] = newAngle; + rotate[0][1] = motion_vector[0]; + rotate[0][2] = motion_vector[1]; + rotate[0][3] = motion_vector[2]; + + this->Prop3DTransform(this->InteractionProp, + obj_center, + 1, + rotate, + scale); + + delete [] rotate[0]; + delete [] rotate; + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::Pan() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + // Use initial center as the origin from which to pan + double *obj_center = this->InteractionProp->GetCenter(); + + double disp_obj_center[3], new_pick_point[4], motion_vector[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2], + disp_obj_center); + + this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0], + (double)rwi->GetEventPosition()[1], + disp_obj_center[2], + new_pick_point); + + // Compute a translation vector, moving everything 1/10 + // the distance to the cursor. (Arbitrary scale factor) + motion_vector[0] = (new_pick_point[0] - obj_center[0]) / this->MotionFactor; + motion_vector[1] = (new_pick_point[1] - obj_center[1]) / this->MotionFactor; + motion_vector[2] = (new_pick_point[2] - obj_center[2]) / this->MotionFactor; + + if (this->InteractionProp->GetUserMatrix() != NULL) + { + vtkTransform *t = vtkTransform::New(); + t->PostMultiply(); + t->SetMatrix(this->InteractionProp->GetUserMatrix()); + t->Translate(motion_vector[0], motion_vector[1], motion_vector[2]); + this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix()); + t->Delete(); + } + else + { + this->InteractionProp->AddPosition(motion_vector[0], + motion_vector[1], + motion_vector[2]); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::Dolly() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + + // Dolly is based on distance from center of screen, + // and the upper half is positive, lower half is negative + double view_point[3], view_focus[3]; + double motion_vector[3]; + + cam->GetPosition(view_point); + cam->GetFocalPoint(view_focus); + + // Use initial center as the origin from which to pan + double *obj_center = this->InteractionProp->GetCenter(); + + double disp_obj_center[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2], + disp_obj_center); + + double *center = this->CurrentRenderer->GetCenter(); + + double yf = + ((double)rwi->GetEventPosition()[1] - (double)disp_obj_center[1]) / (double)center[1]; + double dollyFactor = pow((double)1.1, yf); + + dollyFactor -= 1.0; + motion_vector[0] = (view_point[0] - view_focus[0]) * dollyFactor; + motion_vector[1] = (view_point[1] - view_focus[1]) * dollyFactor; + motion_vector[2] = (view_point[2] - view_focus[2]) * dollyFactor; + + if (this->InteractionProp->GetUserMatrix() != NULL) + { + vtkTransform *t = vtkTransform::New(); + t->PostMultiply(); + t->SetMatrix(this->InteractionProp->GetUserMatrix()); + t->Translate(motion_vector[0], motion_vector[1], motion_vector[2]); + this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix()); + t->Delete(); + } + else + { + this->InteractionProp->AddPosition(motion_vector[0], + motion_vector[1], + motion_vector[2]); + } + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::UniformScale() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + // Uniform scale is based on distance from center of screen, + // and the upper half is positive, lower half is negative + // use bounding box center as the origin from which to pan + double *obj_center = this->InteractionProp->GetCenter(); + + double disp_obj_center[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2], + disp_obj_center); + + double *center = this->CurrentRenderer->GetCenter(); + + double yf = + ((double)rwi->GetEventPosition()[1] - (double)disp_obj_center[1]) / (double)center[1]; + double scaleFactor = pow((double)1.1, yf); + + double **rotate = NULL; + + double scale[3]; + scale[0] = scale[1] = scale[2] = scaleFactor; + + this->Prop3DTransform(this->InteractionProp, + obj_center, + 0, + rotate, + scale); + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::FindPickedActor(int x, int y) +{ + this->InteractionPicker->Pick(x, y, 0.0, this->CurrentRenderer); + vtkProp *prop = this->InteractionPicker->GetViewProp(); + if (prop != NULL) + { + this->InteractionProp = vtkProp3D::SafeDownCast(prop); + } + else + { + this->InteractionProp = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickActor::Prop3DTransform(vtkProp3D *prop3D, + double *boxCenter, + int numRotation, + double **rotate, + double *scale) +{ + vtkMatrix4x4 *oldMatrix = vtkMatrix4x4::New(); + prop3D->GetMatrix(oldMatrix); + + double orig[3]; + prop3D->GetOrigin(orig); + + vtkTransform *newTransform = vtkTransform::New(); + newTransform->PostMultiply(); + if (prop3D->GetUserMatrix() != NULL) + { + newTransform->SetMatrix(prop3D->GetUserMatrix()); + } + else + { + newTransform->SetMatrix(oldMatrix); + } + + newTransform->Translate(-(boxCenter[0]), -(boxCenter[1]), -(boxCenter[2])); + + for (int i = 0; i < numRotation; i++) + { + newTransform->RotateWXYZ(rotate[i][0], rotate[i][1], + rotate[i][2], rotate[i][3]); + } + + if ((scale[0] * scale[1] * scale[2]) != 0.0) + { + newTransform->Scale(scale[0], scale[1], scale[2]); + } + + newTransform->Translate(boxCenter[0], boxCenter[1], boxCenter[2]); + + // now try to get the composit of translate, rotate, and scale + newTransform->Translate(-(orig[0]), -(orig[1]), -(orig[2])); + newTransform->PreMultiply(); + newTransform->Translate(orig[0], orig[1], orig[2]); + + if (prop3D->GetUserMatrix() != NULL) + { + newTransform->GetMatrix(prop3D->GetUserMatrix()); + } + else + { + prop3D->SetPosition(newTransform->GetPosition()); + prop3D->SetScale(newTransform->GetScale()); + prop3D->SetOrientation(newTransform->GetOrientation()); + } + oldMatrix->Delete(); + newTransform->Delete(); +} diff --git a/Rendering/vtkInteractorStyleJoystickActor.h b/Rendering/vtkInteractorStyleJoystickActor.h new file mode 100644 index 0000000..5951c25 --- /dev/null +++ b/Rendering/vtkInteractorStyleJoystickActor.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleJoystickActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleJoystickActor - manipulate objects in the scene independently of one another +// .SECTION Description +// The class vtkInteractorStyleJoystickActor allows the user to interact +// with (rotate, zoom, etc.) separate objects in the scene independent of +// each other. The position of the mouse relative to the center of the +// object determines the speed of the object's motion. The mouse's velocity +// detemines the acceleration of the object's motion, so the object will +// continue moving even when the mouse is not moving. +// For a 3-button mouse, the left button is for rotation, the right button +// for zooming, the middle button for panning, and ctrl + left button for +// spinning. (With fewer mouse buttons, ctrl + shift + left button is +// for zooming, and shift + left button is for panning.) +// .SECTION See Also +// vtkInteractorStyleJoystickCamera vtkInteractorStyleTrackballActor +// vtkInteractorStyleTrackballCamera + +#ifndef __vtkInteractorStyleJoystickActor_h +#define __vtkInteractorStyleJoystickActor_h + +#include "vtkInteractorStyle.h" + +class vtkCellPicker; + +// motion flags + +class VTK_RENDERING_EXPORT vtkInteractorStyleJoystickActor : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleJoystickActor *New(); + + vtkTypeRevisionMacro(vtkInteractorStyleJoystickActor,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Event bindings controlling the effects of pressing mouse buttons + // or moving the mouse. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // These methods for the different interactions in different modes + // are overridden in subclasses to perform the correct motion. Since + // they might be called from OnTimer, they do not have mouse coord parameters + // (use interactor's GetEventPosition and GetLastEventPosition) + virtual void Rotate(); + virtual void Spin(); + virtual void Pan(); + virtual void Dolly(); + virtual void UniformScale(); + +protected: + vtkInteractorStyleJoystickActor(); + ~vtkInteractorStyleJoystickActor(); + + void FindPickedActor(int x, int y); + + void Prop3DTransform(vtkProp3D *prop3D, + double *boxCenter, + int numRotation, + double **rotate, + double *scale); + + double MotionFactor; + + vtkProp3D *InteractionProp; + vtkCellPicker *InteractionPicker; + +private: + vtkInteractorStyleJoystickActor(const vtkInteractorStyleJoystickActor&); // Not implemented. + void operator=(const vtkInteractorStyleJoystickActor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleJoystickCamera.cxx b/Rendering/vtkInteractorStyleJoystickCamera.cxx new file mode 100644 index 0000000..d3b0905 --- /dev/null +++ b/Rendering/vtkInteractorStyleJoystickCamera.cxx @@ -0,0 +1,378 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleJoystickCamera.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleJoystickCamera.h" + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkRenderWindowInteractor.h" + +vtkCxxRevisionMacro(vtkInteractorStyleJoystickCamera, "$Revision: 1.30 $"); +vtkStandardNewMacro(vtkInteractorStyleJoystickCamera); + +//---------------------------------------------------------------------------- +vtkInteractorStyleJoystickCamera::vtkInteractorStyleJoystickCamera() +{ + // Use timers to handle continous interaction + + this->UseTimers = 1; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleJoystickCamera::~vtkInteractorStyleJoystickCamera() +{ +} + +//---------------------------------------------------------------------------- +// Mouse events +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + switch (this->State) + { + case VTKIS_ROTATE: + case VTKIS_PAN: + case VTKIS_DOLLY: + case VTKIS_SPIN: + this->FindPokedRenderer(x, y); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnLeftButtonDown() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + if (this->Interactor->GetShiftKey()) + { + if (this->Interactor->GetControlKey()) + { + this->StartDolly(); + } + else + { + this->StartPan(); + } + } + else + { + if (this->Interactor->GetControlKey()) + { + this->StartSpin(); + } + else + { + this->StartRotate(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnLeftButtonUp() +{ + switch (this->State) + { + case VTKIS_DOLLY: + this->EndDolly(); + break; + + case VTKIS_PAN: + this->EndPan(); + break; + + case VTKIS_SPIN: + this->EndSpin(); + break; + + case VTKIS_ROTATE: + this->EndRotate(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnMiddleButtonDown() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartPan(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnMiddleButtonUp() +{ + switch (this->State) + { + case VTKIS_PAN: + this->EndPan(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnRightButtonDown() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartDolly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnRightButtonUp() +{ + switch (this->State) + { + case VTKIS_DOLLY: + this->EndDolly(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnMouseWheelForward() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartDolly(); + double factor = 10.0 * 0.2 * this->MouseWheelMotionFactor; + this->Dolly(pow((double)1.1, factor)); + this->EndDolly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::OnMouseWheelBackward() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartDolly(); + double factor = 10.0 * -0.2 * this->MouseWheelMotionFactor; + this->Dolly(pow((double)1.1, factor)); + this->EndDolly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::Rotate() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + double *center = this->CurrentRenderer->GetCenter(); + + double dx = (double)rwi->GetEventPosition()[0] - center[0]; + double dy = (double)rwi->GetEventPosition()[1] - center[1]; + + double *vp = this->CurrentRenderer->GetViewport(); + int *size = rwi->GetSize(); + + double delta_elevation = -20.0/((vp[3] - vp[1])*size[1]); + double delta_azimuth = -20.0/((vp[2] - vp[0])*size[0]); + + double rxf = (double)dx * delta_azimuth; + double ryf = (double)dy * delta_elevation; + + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->Azimuth(rxf); + camera->Elevation(ryf); + camera->OrthogonalizeViewUp(); + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + if (rwi->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::Spin() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + double *center = this->CurrentRenderer->GetCenter(); + + // Spin is based on y value + + double yf = ((double)rwi->GetEventPosition()[1] - (double)center[1]) + / (double)(center[1]); + + if (yf > 1) + { + yf = 1; + } + else if (yf < -1) + { + yf = -1; + } + + double newAngle = asin(yf) * vtkMath::RadiansToDegrees(); + + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->Roll(newAngle); + camera->OrthogonalizeViewUp(); + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::Pan() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + double ViewFocus[4]; + double NewPickPoint[4]; + + // Calculate the focal depth since we'll be using it a lot + + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetFocalPoint(ViewFocus); + this->ComputeWorldToDisplay(ViewFocus[0], ViewFocus[1], ViewFocus[2], + ViewFocus); + double focalDepth = ViewFocus[2]; + + this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0], + (double)rwi->GetEventPosition()[1], + focalDepth, + NewPickPoint); + + // Get the current focal point and position + + camera->GetFocalPoint(ViewFocus); + double *ViewPoint = camera->GetPosition(); + + // Compute a translation vector, moving everything 1/10 + // the distance to the cursor. (Arbitrary scale factor) + + double MotionVector[3]; + MotionVector[0] = 0.1 * (ViewFocus[0] - NewPickPoint[0]); + MotionVector[1] = 0.1 * (ViewFocus[1] - NewPickPoint[1]); + MotionVector[2] = 0.1 * (ViewFocus[2] - NewPickPoint[2]); + + camera->SetFocalPoint(MotionVector[0] + ViewFocus[0], + MotionVector[1] + ViewFocus[1], + MotionVector[2] + ViewFocus[2]); + + camera->SetPosition(MotionVector[0] + ViewPoint[0], + MotionVector[1] + ViewPoint[1], + MotionVector[2] + ViewPoint[2]); + + if (rwi->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::Dolly() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + double *center = this->CurrentRenderer->GetCenter(); + double dy = (double)rwi->GetEventPosition()[1] - (double)center[1]; + double dyf = 0.5 * dy / (double)center[1]; + this->Dolly(pow((double)1.1, dyf)); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::Dolly(double factor) +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + if (camera->GetParallelProjection()) + { + camera->SetParallelScale(camera->GetParallelScale() / factor); + } + else + { + camera->Dolly(factor); + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + } + + if (this->Interactor->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + this->Interactor->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleJoystickCamera::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkInteractorStyleJoystickCamera.h b/Rendering/vtkInteractorStyleJoystickCamera.h new file mode 100644 index 0000000..8b16380 --- /dev/null +++ b/Rendering/vtkInteractorStyleJoystickCamera.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleJoystickCamera.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleJoystickCamera - interactive manipulation of the camera + +// .SECTION Description +// vtkInteractorStyleJoystickCamera allows the user to move (rotate, pan, +// etc.) the camera, the point of view for the scene. The position of the +// mouse relative to the center of the scene determines the speed at which +// the camera moves, and the speed of the mouse movement determines the +// acceleration of the camera, so the camera continues to move even if the +// mouse if not moving. +// For a 3-button mouse, the left button is for rotation, the right button +// for zooming, the middle button for panning, and ctrl + left button for +// spinning. (With fewer mouse buttons, ctrl + shift + left button is +// for zooming, and shift + left button is for panning.) + +// .SECTION See Also +// vtkInteractorStyleJoystickActor vtkInteractorStyleTrackballCamera +// vtkInteractorStyleTrackballActor + +#ifndef __vtkInteractorStyleJoystickCamera_h +#define __vtkInteractorStyleJoystickCamera_h + +#include "vtkInteractorStyle.h" + +class VTK_RENDERING_EXPORT vtkInteractorStyleJoystickCamera : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleJoystickCamera *New(); + vtkTypeRevisionMacro(vtkInteractorStyleJoystickCamera,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Event bindings controlling the effects of pressing mouse buttons + // or moving the mouse. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + virtual void OnMouseWheelForward(); + virtual void OnMouseWheelBackward(); + + // These methods for the different interactions in different modes + // are overridden in subclasses to perform the correct motion. Since + // they are called by OnTimer, they do not have mouse coord parameters + // (use interactor's GetEventPosition and GetLastEventPosition) + virtual void Rotate(); + virtual void Spin(); + virtual void Pan(); + virtual void Dolly(); + +protected: + vtkInteractorStyleJoystickCamera(); + ~vtkInteractorStyleJoystickCamera(); + + virtual void Dolly(double factor); + +private: + vtkInteractorStyleJoystickCamera(const vtkInteractorStyleJoystickCamera&); // Not implemented. + void operator=(const vtkInteractorStyleJoystickCamera&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleRubberBandZoom.cxx b/Rendering/vtkInteractorStyleRubberBandZoom.cxx new file mode 100644 index 0000000..eeccac2 --- /dev/null +++ b/Rendering/vtkInteractorStyleRubberBandZoom.cxx @@ -0,0 +1,210 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleRubberBandZoom.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleRubberBandZoom.h" + +#include "vtkCamera.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkInteractorStyleRubberBandZoom, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkInteractorStyleRubberBandZoom); + +vtkInteractorStyleRubberBandZoom::vtkInteractorStyleRubberBandZoom() +{ + this->StartPosition[0] = this->StartPosition[1] = 0; + this->EndPosition[0] = this->EndPosition[1] = 0; + this->Moving = 0; + this->PixelArray = vtkUnsignedCharArray::New(); +} + +vtkInteractorStyleRubberBandZoom::~vtkInteractorStyleRubberBandZoom() +{ + this->PixelArray->Delete(); +} + +void vtkInteractorStyleRubberBandZoom::OnMouseMove() +{ + if (!this->Interactor || !this->Moving) + { + return; + } + + this->EndPosition[0] = this->Interactor->GetEventPosition()[0]; + this->EndPosition[1] = this->Interactor->GetEventPosition()[1]; + + vtkUnsignedCharArray *tmpPixelArray = vtkUnsignedCharArray::New(); + tmpPixelArray->DeepCopy(this->PixelArray); + + unsigned char *pixels = tmpPixelArray->GetPointer(0); + + int min[2], max[2]; + min[0] = this->StartPosition[0] <= this->EndPosition[0] ? + this->StartPosition[0] : this->EndPosition[0]; + min[1] = this->StartPosition[1] <= this->EndPosition[1] ? + this->StartPosition[1] : this->EndPosition[1]; + max[0] = this->EndPosition[0] > this->StartPosition[0] ? + this->EndPosition[0] : this->StartPosition[0]; + max[1] = this->EndPosition[1] > this->StartPosition[1] ? + this->EndPosition[1] : this->StartPosition[1]; + + int *size = this->Interactor->GetRenderWindow()->GetSize(); + + int i; + for (i = min[0]; i <= max[0]; i++) + { + pixels[3*(min[1]*size[0]+i)] = 255 ^ pixels[3*(min[1]*size[0]+i)]; + pixels[3*(min[1]*size[0]+i)+1] = 255 ^ pixels[3*(min[1]*size[0]+i)+1]; + pixels[3*(min[1]*size[0]+i)+2] = 255 ^ pixels[3*(min[1]*size[0]+i)+2]; + pixels[3*(max[1]*size[0]+i)] = 255 ^ pixels[3*(max[1]*size[0]+i)]; + pixels[3*(max[1]*size[0]+i)+1] = 255 ^ pixels[3*(max[1]*size[0]+i)+1]; + pixels[3*(max[1]*size[0]+i)+2] = 255 ^ pixels[3*(max[1]*size[0]+i)+2]; + } + for (i = min[1]+1; i < max[1]; i++) + { + pixels[3*(i*size[0]+min[0])] = 255 ^ pixels[3*(i*size[0]+min[0])]; + pixels[3*(i*size[0]+min[0])+1] = 255 ^ pixels[3*(i*size[0]+min[0])+1]; + pixels[3*(i*size[0]+min[0])+2] = 255 ^ pixels[3*(i*size[0]+min[0])+2]; + pixels[3*(i*size[0]+max[0])] = 255 ^ pixels[3*(i*size[0]+max[0])]; + pixels[3*(i*size[0]+max[0])+1] = 255 ^ pixels[3*(i*size[0]+max[0])+1]; + pixels[3*(i*size[0]+max[0])+2] = 255 ^ pixels[3*(i*size[0]+max[0])+2]; + } + + this->Interactor->GetRenderWindow()->SetPixelData(0, 0, size[0]-1, size[1]-1, pixels, 1); + + tmpPixelArray->Delete(); +} + +void vtkInteractorStyleRubberBandZoom::OnLeftButtonDown() +{ + if (!this->Interactor) + { + return; + } + this->Moving = 1; + + vtkRenderWindow *renWin = this->Interactor->GetRenderWindow(); + + this->StartPosition[0] = this->Interactor->GetEventPosition()[0]; + this->StartPosition[1] = this->Interactor->GetEventPosition()[1]; + this->EndPosition[0] = this->StartPosition[0]; + this->EndPosition[1] = this->StartPosition[1]; + + this->PixelArray->Initialize(); + this->PixelArray->SetNumberOfComponents(3); + int *size = renWin->GetSize(); + this->PixelArray->SetNumberOfTuples(size[0]*size[1]); + + renWin->GetPixelData(0, 0, size[0]-1, size[1]-1, 1, this->PixelArray); + + this->FindPokedRenderer(this->StartPosition[0], this->StartPosition[1]); +} + +void vtkInteractorStyleRubberBandZoom::OnLeftButtonUp() +{ + if (!this->Interactor || !this->Moving) + { + return; + } + + if ( (this->StartPosition[0] != this->EndPosition[0]) + || (this->StartPosition[1] != this->EndPosition[1]) ) + { + this->Zoom(); + } + this->Moving = 0; +} + +void vtkInteractorStyleRubberBandZoom::Zoom() +{ + int width, height; + width = abs(this->EndPosition[0] - this->StartPosition[0]); + height = abs(this->EndPosition[1] - this->StartPosition[1]); + int *size = this->CurrentRenderer->GetSize(); + int *origin = this->CurrentRenderer->GetOrigin(); + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + + int min[2]; + double rbcenter[3]; + min[0] = this->StartPosition[0] < this->EndPosition[0] ? + this->StartPosition[0] : this->EndPosition[0]; + min[1] = this->StartPosition[1] < this->EndPosition[1] ? + this->StartPosition[1] : this->EndPosition[1]; + + rbcenter[0] = min[0] + 0.5*width; + rbcenter[1] = min[1] + 0.5*height; + rbcenter[2] = 0; + + this->CurrentRenderer->SetDisplayPoint(rbcenter); + this->CurrentRenderer->DisplayToView(); + this->CurrentRenderer->ViewToWorld(); + + double invw; + double worldRBCenter[4]; + this->CurrentRenderer->GetWorldPoint(worldRBCenter); + invw = 1.0/worldRBCenter[3]; + worldRBCenter[0] *= invw; + worldRBCenter[1] *= invw; + worldRBCenter[2] *= invw; + + double winCenter[3]; + winCenter[0] = origin[0] + 0.5*size[0]; + winCenter[1] = origin[1] + 0.5*size[1]; + winCenter[2] = 0; + + this->CurrentRenderer->SetDisplayPoint(winCenter); + this->CurrentRenderer->DisplayToView(); + this->CurrentRenderer->ViewToWorld(); + + double worldWinCenter[4]; + this->CurrentRenderer->GetWorldPoint(worldWinCenter); + invw = 1.0/worldWinCenter[3]; + worldWinCenter[0] *= invw; + worldWinCenter[1] *= invw; + worldWinCenter[2] *= invw; + + double translation[3]; + translation[0] = worldRBCenter[0] - worldWinCenter[0]; + translation[1] = worldRBCenter[1] - worldWinCenter[1]; + translation[2] = worldRBCenter[2] - worldWinCenter[2]; + + double pos[3], fp[3]; + cam->GetPosition(pos); + cam->GetFocalPoint(fp); + + pos[0] += translation[0]; pos[1] += translation[1]; pos[2] += translation[2]; + fp[0] += translation[0]; fp[1] += translation[1]; fp[2] += translation[2]; + + cam->SetPosition(pos); + cam->SetFocalPoint(fp); + + if (width > height) + { + cam->Zoom(size[0] / (float)width); + } + else + { + cam->Zoom(size[1] / (float)height); + } + + this->Interactor->Render(); +} + +void vtkInteractorStyleRubberBandZoom::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} diff --git a/Rendering/vtkInteractorStyleRubberBandZoom.h b/Rendering/vtkInteractorStyleRubberBandZoom.h new file mode 100644 index 0000000..fbae735 --- /dev/null +++ b/Rendering/vtkInteractorStyleRubberBandZoom.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleRubberBandZoom.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleRubberBandZoom - zoom in by amount indicated by rubber band box +// .SECTION Description +// This interactor style allows the user to draw a rectangle in the render +// window using the left mouse button. When the mouse button is released, +// the current camera zooms by an amount determined from the shorter side of +// the drawn rectangle. + +#ifndef __vtkInteractorStyleRubberBandZoom_h +#define __vtkInteractorStyleRubberBandZoom_h + +#include "vtkInteractorStyle.h" + +class vtkUnsignedCharArray; + +class VTK_RENDERING_EXPORT vtkInteractorStyleRubberBandZoom : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleRubberBandZoom *New(); + vtkTypeRevisionMacro(vtkInteractorStyleRubberBandZoom, vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Event bindings + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + +protected: + vtkInteractorStyleRubberBandZoom(); + ~vtkInteractorStyleRubberBandZoom(); + + virtual void Zoom(); + + int StartPosition[2]; + int EndPosition[2]; + + int Moving; + + vtkUnsignedCharArray *PixelArray; + +private: + vtkInteractorStyleRubberBandZoom(const vtkInteractorStyleRubberBandZoom&); // Not implemented + void operator=(const vtkInteractorStyleRubberBandZoom&); // Not implemented +}; + +#endif diff --git a/Rendering/vtkInteractorStyleSwitch.cxx b/Rendering/vtkInteractorStyleSwitch.cxx new file mode 100644 index 0000000..5f749e4 --- /dev/null +++ b/Rendering/vtkInteractorStyleSwitch.cxx @@ -0,0 +1,268 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleSwitch.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleSwitch.h" + +#include "vtkCallbackCommand.h" +#include "vtkCommand.h" +#include "vtkInteractorStyleJoystickActor.h" +#include "vtkInteractorStyleJoystickCamera.h" +#include "vtkInteractorStyleTrackballActor.h" +#include "vtkInteractorStyleTrackballCamera.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindowInteractor.h" + +vtkCxxRevisionMacro(vtkInteractorStyleSwitch, "$Revision: 1.24 $"); +vtkStandardNewMacro(vtkInteractorStyleSwitch); + +//---------------------------------------------------------------------------- +vtkInteractorStyleSwitch::vtkInteractorStyleSwitch() +{ + this->JoystickActor = vtkInteractorStyleJoystickActor::New(); + this->JoystickCamera = vtkInteractorStyleJoystickCamera::New(); + this->TrackballActor = vtkInteractorStyleTrackballActor::New(); + this->TrackballCamera = vtkInteractorStyleTrackballCamera::New(); + this->JoystickOrTrackball = VTKIS_JOYSTICK; + this->CameraOrActor = VTKIS_CAMERA; + this->CurrentStyle = 0; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleSwitch::~vtkInteractorStyleSwitch() +{ + this->JoystickActor->Delete(); + this->JoystickActor = NULL; + + this->JoystickCamera->Delete(); + this->JoystickCamera = NULL; + + this->TrackballActor->Delete(); + this->TrackballActor = NULL; + + this->TrackballCamera->Delete(); + this->TrackballCamera = NULL; +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetAutoAdjustCameraClippingRange( int value ) +{ + if ( value == this->AutoAdjustCameraClippingRange ) + { + return; + } + + if ( value < 0 || value > 1 ) + { + vtkErrorMacro("Value must be between 0 and 1 for" << + " SetAutoAdjustCameraClippingRange"); + return; + } + + this->AutoAdjustCameraClippingRange = value; + this->JoystickActor->SetAutoAdjustCameraClippingRange( value ); + this->JoystickCamera->SetAutoAdjustCameraClippingRange( value ); + this->TrackballActor->SetAutoAdjustCameraClippingRange( value ); + this->TrackballCamera->SetAutoAdjustCameraClippingRange( value ); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetCurrentStyleToJoystickActor() +{ + this->JoystickOrTrackball = VTKIS_JOYSTICK; + this->CameraOrActor = VTKIS_ACTOR; + this->SetCurrentStyle(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetCurrentStyleToJoystickCamera() +{ + this->JoystickOrTrackball = VTKIS_JOYSTICK; + this->CameraOrActor = VTKIS_CAMERA; + this->SetCurrentStyle(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetCurrentStyleToTrackballActor() +{ + this->JoystickOrTrackball = VTKIS_TRACKBALL; + this->CameraOrActor = VTKIS_ACTOR; + this->SetCurrentStyle(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetCurrentStyleToTrackballCamera() +{ + this->JoystickOrTrackball = VTKIS_TRACKBALL; + this->CameraOrActor = VTKIS_CAMERA; + this->SetCurrentStyle(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::OnChar() +{ + switch (this->Interactor->GetKeyCode()) + { + case 'j': + case 'J': + this->JoystickOrTrackball = VTKIS_JOYSTICK; + this->EventCallbackCommand->SetAbortFlag(1); + break; + case 't': + case 'T': + this->JoystickOrTrackball = VTKIS_TRACKBALL; + this->EventCallbackCommand->SetAbortFlag(1); + break; + case 'c': + case 'C': + this->CameraOrActor = VTKIS_CAMERA; + this->EventCallbackCommand->SetAbortFlag(1); + break; + case 'a': + case 'A': + this->CameraOrActor = VTKIS_ACTOR; + this->EventCallbackCommand->SetAbortFlag(1); + break; + } + // Set the CurrentStyle pointer to the picked style + this->SetCurrentStyle(); +} + +//---------------------------------------------------------------------------- +// this will do nothing if the CurrentStyle matchs +// JoystickOrTrackball and CameraOrActor +// It should! If the this->Interactor was changed (using SetInteractor()), +// and the currentstyle should not change. +void vtkInteractorStyleSwitch::SetCurrentStyle() +{ + // if the currentstyle does not match JoystickOrTrackball + // and CameraOrActor ivars, then call SetInteractor(0) + // on the Currentstyle to remove all of the observers. + // Then set the Currentstyle and call SetInteractor with + // this->Interactor so the callbacks are set for the + // currentstyle. + if (this->JoystickOrTrackball == VTKIS_JOYSTICK && + this->CameraOrActor == VTKIS_CAMERA) + { + if(this->CurrentStyle != this->JoystickCamera) + { + if(this->CurrentStyle) + { + this->CurrentStyle->SetInteractor(0); + } + this->CurrentStyle = this->JoystickCamera; + } + } + else if (this->JoystickOrTrackball == VTKIS_JOYSTICK && + this->CameraOrActor == VTKIS_ACTOR) + { + if(this->CurrentStyle != this->JoystickActor) + { + if(this->CurrentStyle) + { + this->CurrentStyle->SetInteractor(0); + } + this->CurrentStyle = this->JoystickActor; + } + } + else if (this->JoystickOrTrackball == VTKIS_TRACKBALL && + this->CameraOrActor == VTKIS_CAMERA) + { + if(this->CurrentStyle != this->TrackballCamera) + { + if(this->CurrentStyle) + { + this->CurrentStyle->SetInteractor(0); + } + this->CurrentStyle = this->TrackballCamera; + } + } + else if (this->JoystickOrTrackball == VTKIS_TRACKBALL && + this->CameraOrActor == VTKIS_ACTOR) + { + if(this->CurrentStyle != this->TrackballActor) + { + if(this->CurrentStyle) + { + this->CurrentStyle->SetInteractor(0); + } + this->CurrentStyle = this->TrackballActor; + } + } + if (this->CurrentStyle) + { + this->CurrentStyle->SetInteractor(this->Interactor); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetInteractor(vtkRenderWindowInteractor *iren) +{ + if(iren == this->Interactor) + { + return; + } + // if we already have an Interactor then stop observing it + if(this->Interactor) + { + this->Interactor->RemoveObserver(this->EventCallbackCommand); + } + this->Interactor = iren; + // add observers for each of the events handled in ProcessEvents + if(iren) + { + iren->AddObserver(vtkCommand::CharEvent, + this->EventCallbackCommand, + this->Priority); + + iren->AddObserver(vtkCommand::DeleteEvent, + this->EventCallbackCommand, + this->Priority); + } + this->SetCurrentStyle(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "CurrentStyle " << this->CurrentStyle << "\n"; + if (this->CurrentStyle) + { + vtkIndent next_indent = indent.GetNextIndent(); + os << next_indent << this->CurrentStyle->GetClassName() << "\n"; + this->CurrentStyle->PrintSelf(os, indent.GetNextIndent()); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetDefaultRenderer(vtkRenderer* renderer) +{ + this->vtkInteractorStyle::SetDefaultRenderer(renderer); + this->JoystickActor->SetDefaultRenderer(renderer); + this->JoystickCamera->SetDefaultRenderer(renderer); + this->TrackballActor->SetDefaultRenderer(renderer); + this->TrackballCamera->SetDefaultRenderer(renderer); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleSwitch::SetCurrentRenderer(vtkRenderer* renderer) +{ + this->vtkInteractorStyle::SetCurrentRenderer(renderer); + this->JoystickActor->SetCurrentRenderer(renderer); + this->JoystickCamera->SetCurrentRenderer(renderer); + this->TrackballActor->SetCurrentRenderer(renderer); + this->TrackballCamera->SetCurrentRenderer(renderer); +} diff --git a/Rendering/vtkInteractorStyleSwitch.h b/Rendering/vtkInteractorStyleSwitch.h new file mode 100644 index 0000000..c9dac43 --- /dev/null +++ b/Rendering/vtkInteractorStyleSwitch.h @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleSwitch.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleSwitch - class to swap between interactory styles +// .SECTION Description +// The class vtkInteractorStyleSwitch allows handles interactively switching +// between four interactor styles -- joystick actor, joystick camera, +// trackball actor, and trackball camera. Type 'j' or 't' to select +// joystick or trackball, and type 'c' or 'a' to select camera or actor. +// The default interactor style is joystick camera. +// .SECTION See Also +// vtkInteractorStyleJoystickActor vtkInteractorStyleJoystickCamera +// vtkInteractorStyleTrackballActor vtkInteractorStyleTrackballCamera + +#ifndef __vtkInteractorStyleSwitch_h +#define __vtkInteractorStyleSwitch_h + +#include "vtkInteractorStyle.h" + +#define VTKIS_JOYSTICK 0 +#define VTKIS_TRACKBALL 1 + +#define VTKIS_CAMERA 0 +#define VTKIS_ACTOR 1 + +class vtkInteractorStyleJoystickActor; +class vtkInteractorStyleJoystickCamera; +class vtkInteractorStyleTrackballActor; +class vtkInteractorStyleTrackballCamera; + +class VTK_RENDERING_EXPORT vtkInteractorStyleSwitch : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleSwitch *New(); + vtkTypeRevisionMacro(vtkInteractorStyleSwitch, vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // The sub styles need the interactor too. + void SetInteractor(vtkRenderWindowInteractor *iren); + + // Description: + // We must override this method in order to pass the setting down to + // the underlying styles + void SetAutoAdjustCameraClippingRange( int value ); + + // Description: + // Set/Get current style + vtkGetObjectMacro(CurrentStyle, vtkInteractorStyle); + void SetCurrentStyleToJoystickActor(); + void SetCurrentStyleToJoystickCamera(); + void SetCurrentStyleToTrackballActor(); + void SetCurrentStyleToTrackballCamera(); + + // Description: + // Only care about the char event, which is used to switch between + // different styles. + virtual void OnChar(); + + // Description: + // Overridden from vtkInteractorObserver because the interactor styles + // used by this class must also be updated. + virtual void SetDefaultRenderer(vtkRenderer*); + virtual void SetCurrentRenderer(vtkRenderer*); + +protected: + vtkInteractorStyleSwitch(); + ~vtkInteractorStyleSwitch(); + + void SetCurrentStyle(); + + vtkInteractorStyleJoystickActor *JoystickActor; + vtkInteractorStyleJoystickCamera *JoystickCamera; + vtkInteractorStyleTrackballActor *TrackballActor; + vtkInteractorStyleTrackballCamera *TrackballCamera; + vtkInteractorStyle* CurrentStyle; + + int JoystickOrTrackball; + int CameraOrActor; + +private: + vtkInteractorStyleSwitch(const vtkInteractorStyleSwitch&); // Not implemented. + void operator=(const vtkInteractorStyleSwitch&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleTerrain.cxx b/Rendering/vtkInteractorStyleTerrain.cxx new file mode 100644 index 0000000..6d858e7 --- /dev/null +++ b/Rendering/vtkInteractorStyleTerrain.cxx @@ -0,0 +1,416 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTerrain.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleTerrain.h" + +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkExtractEdges.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" + +vtkCxxRevisionMacro(vtkInteractorStyleTerrain, "$Revision: 1.9 $"); +vtkStandardNewMacro(vtkInteractorStyleTerrain); + +//---------------------------------------------------------------------------- +vtkInteractorStyleTerrain::vtkInteractorStyleTerrain() +{ + this->LatLongLines = 0; + + this->LatLongSphere = NULL; + this->LatLongExtractEdges = NULL; + this->LatLongMapper = NULL; + this->LatLongActor = NULL; + + this->MotionFactor = 10.0; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleTerrain::~vtkInteractorStyleTerrain() +{ + if (this->LatLongSphere != NULL) + { + this->LatLongSphere->Delete(); + } + + if (this->LatLongMapper != NULL) + { + this->LatLongMapper->Delete(); + } + + if (this->LatLongActor != NULL) + { + this->LatLongActor->Delete(); + } + + if (this->LatLongExtractEdges != NULL) + { + this->LatLongExtractEdges->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + switch (this->State) + { + case VTKIS_ROTATE: + this->FindPokedRenderer(x, y); + this->Rotate(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_PAN: + this->FindPokedRenderer(x, y); + this->Pan(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_DOLLY: + this->FindPokedRenderer(x, y); + this->Dolly(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnLeftButtonDown () +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartRotate(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnLeftButtonUp () +{ + switch (this->State) + { + case VTKIS_ROTATE: + this->EndRotate(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnMiddleButtonDown () +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartPan(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnMiddleButtonUp () +{ + switch (this->State) + { + case VTKIS_PAN: + this->EndPan(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnRightButtonDown () +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartDolly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnRightButtonUp () +{ + switch (this->State) + { + case VTKIS_DOLLY: + this->EndDolly(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::Rotate() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + int dx = - (rwi->GetEventPosition()[0] - rwi->GetLastEventPosition()[0]); + int dy = - (rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]); + + int *size = this->CurrentRenderer->GetRenderWindow()->GetSize(); + + double a = (double)dx / (double)size[0] * (double)180.0; + double e = (double)dy / (double)size[1] * (double)180.0; + + if (rwi->GetShiftKey()) + { + if (fabs((double)dx) >= fabs((double)dy)) + { + e = (double)0.0; + } + else + { + a = (double)0.0; + } + } + + // Move the camera. + // Make sure that we don't hit the north pole singularity. + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + camera->Azimuth(a); + + double dop[3], vup[3]; + + camera->GetDirectionOfProjection(dop); + vtkMath::Normalize(dop); + camera->GetViewUp(vup); + vtkMath::Normalize(vup); + + double angle = + acos(vtkMath::Dot(dop, vup)) / vtkMath::DoubleDegreesToRadians(); + if ((angle + e) > (double)179.0 || + (angle + e) < (double)1.0) + { + e = (double)0.0; + } + + camera->Elevation(e); + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::Pan() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + // Get the vector of motion + + double fp[3], focalPoint[3], pos[3], v[3], p1[4], p2[4]; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetPosition(pos); + camera->GetFocalPoint(fp); + + this->ComputeWorldToDisplay(fp[0], fp[1], fp[2], + focalPoint); + + this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0], + (double)rwi->GetEventPosition()[1], + focalPoint[2], + p1); + + this->ComputeDisplayToWorld((double)rwi->GetLastEventPosition()[0], + (double)rwi->GetLastEventPosition()[1], + focalPoint[2], + p2); + + for (int i=0; i<3; i++) + { + v[i] = p2[i] - p1[i]; + pos[i] += v[i]; + fp[i] += v[i]; + } + + camera->SetPosition(pos); + camera->SetFocalPoint(fp); + + if (rwi->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::Dolly() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + double *center = this->CurrentRenderer->GetCenter(); + + int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; + double dyf = this->MotionFactor * (double)(dy) / (double)(center[1]); + double zoomFactor = pow((double)1.1, dyf); + + if (camera->GetParallelProjection()) + { + camera->SetParallelScale(camera->GetParallelScale() / zoomFactor); + } + else + { + camera->Dolly(zoomFactor); + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + } + + if (rwi->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::OnChar() +{ + vtkRenderWindowInteractor *rwi = this->Interactor; + + switch (rwi->GetKeyCode()) + { + case 'l': + this->FindPokedRenderer(rwi->GetEventPosition()[0], + rwi->GetEventPosition()[1]); + this->CreateLatLong(); + if (this->LatLongLines) + { + this->LatLongLinesOff(); + } + else + { + double bounds[6]; + this->CurrentRenderer->ComputeVisiblePropBounds(bounds); + double radius = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])) /2.0; + this->LatLongSphere->SetRadius(radius); + this->LatLongSphere->SetCenter((bounds[0]+bounds[1])/2.0, + (bounds[2]+bounds[3])/2.0, + (bounds[4]+bounds[5])/2.0); + this->LatLongLinesOn(); + } + this->SelectRepresentation(); + rwi->Render(); + break; + + default: + this->Superclass::OnChar(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::CreateLatLong() +{ + if (this->LatLongSphere == NULL) + { + this->LatLongSphere = vtkSphereSource::New(); + this->LatLongSphere->SetPhiResolution(13); + this->LatLongSphere->SetThetaResolution(25); + this->LatLongSphere->LatLongTessellationOn(); + } + + if (this->LatLongExtractEdges == NULL) + { + this->LatLongExtractEdges = vtkExtractEdges::New(); + this->LatLongExtractEdges->SetInput(this->LatLongSphere->GetOutput()); + } + + if (this->LatLongMapper == NULL) + { + this->LatLongMapper = vtkPolyDataMapper::New(); + this->LatLongMapper->SetInput(this->LatLongExtractEdges->GetOutput()); + } + + if (this->LatLongActor == NULL) + { + this->LatLongActor = vtkActor::New(); + this->LatLongActor->SetMapper(this->LatLongMapper); + this->LatLongActor->PickableOff(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::SelectRepresentation() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + this->CurrentRenderer->RemoveActor(this->LatLongActor); + + if (this->LatLongLines) + { + this->CurrentRenderer->AddActor(this->LatLongActor); + this->LatLongActor->VisibilityOn(); + } + else + { + this->LatLongActor->VisibilityOff(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTerrain::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Latitude/Longitude Lines: " + << (this->LatLongLines ? "On\n" : "Off\n"); +} + + diff --git a/Rendering/vtkInteractorStyleTerrain.h b/Rendering/vtkInteractorStyleTerrain.h new file mode 100644 index 0000000..21effb4 --- /dev/null +++ b/Rendering/vtkInteractorStyleTerrain.h @@ -0,0 +1,116 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTerrain.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleTerrain - manipulate camera in scene with natural view up (e.g., terrain) +// .SECTION Description +// vtkInteractorStyleTerrain is used to manipulate a camera which is viewing +// a scene with a natural view up, e.g., terrain. The camera in such a +// scene is manipulated by specifying azimuth (angle around the view +// up vector) and elevation (the angle from the horizon). +// +// The mouse binding for this class is as follows. Left mouse click followed +// rotates the camera around the focal point using both elevation and azimuth +// invocations on the camera. Left mouse motion in the horizontal direction +// results in azimuth motion; left mouse motion in the vertical direction +// results in elevation motion. Therefore, diagonal motion results in a +// combination of azimuth and elevation. (If the shift key is held during +// motion, then only one of elevation or azimuth is invoked, depending on the +// whether the mouse motion is primarily horizontal or vertical.) Middle +// mouse button pans the camera across the scene (again the shift key has a +// similar effect on limiting the motion to the vertical or horizontal +// direction. The right mouse is used to dolly (e.g., a type of zoom) towards +// or away from the focal point. +// +// The class also supports some keypress events. The "r" key resets the +// camera. The "e" key invokes the exit callback and by default exits the +// program. The "f" key sets a new camera focal point and flys towards that +// point. The "u" key invokes the user event. The "3" key toggles between +// stereo and non-stero mode. The "l" key toggles on/off a latitude/longitude +// markers that can be used to estimate/control position. +// + +// .SECTION See Also +// vtkInteractorObserver vtkInteractorStyle vtk3DWidget + +#ifndef __vtkInteractorStyleTerrain_h +#define __vtkInteractorStyleTerrain_h + +#include "vtkInteractorStyle.h" + +class vtkPolyDataMapper; +class vtkSphereSource; +class vtkExtractEdges; + +class VTK_RENDERING_EXPORT vtkInteractorStyleTerrain : public vtkInteractorStyle +{ +public: + // Description: + // Instantiate the object. + static vtkInteractorStyleTerrain *New(); + + vtkTypeRevisionMacro(vtkInteractorStyleTerrain,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Event bindings controlling the effects of pressing mouse buttons + // or moving the mouse. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // Description: + // Override the "fly-to" (f keypress) for images. + virtual void OnChar(); + + // These methods for the different interactions in different modes + // are overridden in subclasses to perform the correct motion. + virtual void Rotate(); + virtual void Pan(); + virtual void Dolly(); + + // Description: + // Turn on/off the latitude/longitude lines. + vtkSetMacro(LatLongLines,int); + vtkGetMacro(LatLongLines,int); + vtkBooleanMacro(LatLongLines,int); + +protected: + vtkInteractorStyleTerrain(); + ~vtkInteractorStyleTerrain(); + + // Internal helper attributes + int LatLongLines; + + vtkSphereSource *LatLongSphere; + vtkPolyDataMapper *LatLongMapper; + vtkActor *LatLongActor; + vtkExtractEdges *LatLongExtractEdges; + + void SelectRepresentation(); + void CreateLatLong(); + + double MotionFactor; + +private: + vtkInteractorStyleTerrain(const vtkInteractorStyleTerrain&); // Not implemented. + void operator=(const vtkInteractorStyleTerrain&); // Not implemented. + +}; + +#endif + diff --git a/Rendering/vtkInteractorStyleTrackball.cxx b/Rendering/vtkInteractorStyleTrackball.cxx new file mode 100644 index 0000000..50123c1 --- /dev/null +++ b/Rendering/vtkInteractorStyleTrackball.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTrackball.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleTrackball.h" +#include "vtkMath.h" +#include "vtkPropPicker.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + +vtkCxxRevisionMacro(vtkInteractorStyleTrackball, "$Revision: 1.27 $"); +vtkStandardNewMacro(vtkInteractorStyleTrackball); + +//---------------------------------------------------------------------------- +vtkInteractorStyleTrackball::vtkInteractorStyleTrackball() +{ + vtkWarningMacro("vtkInteractorStyleTrackball will be deprecated in" << endl + << "the next release after VTK 4.0. Please use" << endl + << "vtkInteractorStyleSwitch instead." ); +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleTrackball::~vtkInteractorStyleTrackball() +{ +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackball::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkInteractorStyleTrackball.h b/Rendering/vtkInteractorStyleTrackball.h new file mode 100644 index 0000000..ea7fec5 --- /dev/null +++ b/Rendering/vtkInteractorStyleTrackball.h @@ -0,0 +1,46 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTrackball.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleTrackball - provides trackball motion control + +// .SECTION Description +// vtkInteractorStyleTrackball is an implementation of vtkInteractorStyle +// that defines the trackball style. It is now deprecated and as such a +// subclass of vtkInteractorStyleSwitch + +// .SECTION See Also +// vtkInteractorStyleSwitch vtkInteractorStyleTrackballActor vtkInteractorStyleJoystickCamera + +#ifndef __vtkInteractorStyleTrackball_h +#define __vtkInteractorStyleTrackball_h + +#include "vtkInteractorStyleSwitch.h" + +class VTK_RENDERING_EXPORT vtkInteractorStyleTrackball : public vtkInteractorStyleSwitch +{ +public: + static vtkInteractorStyleTrackball *New(); + vtkTypeRevisionMacro(vtkInteractorStyleTrackball,vtkInteractorStyleSwitch); + void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkInteractorStyleTrackball(); + ~vtkInteractorStyleTrackball(); + +private: + vtkInteractorStyleTrackball(const vtkInteractorStyleTrackball&); // Not implemented. + void operator=(const vtkInteractorStyleTrackball&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleTrackballActor.cxx b/Rendering/vtkInteractorStyleTrackballActor.cxx new file mode 100644 index 0000000..523a46a --- /dev/null +++ b/Rendering/vtkInteractorStyleTrackballActor.cxx @@ -0,0 +1,603 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTrackballActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleTrackballActor.h" + +#include "vtkCamera.h" +#include "vtkCellPicker.h" +#include "vtkCommand.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkProp3D.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkInteractorStyleTrackballActor, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkInteractorStyleTrackballActor); + +//---------------------------------------------------------------------------- +vtkInteractorStyleTrackballActor::vtkInteractorStyleTrackballActor() +{ + this->MotionFactor = 10.0; + this->InteractionProp = NULL; + this->InteractionPicker = vtkCellPicker::New(); + this->InteractionPicker->SetTolerance(0.001); +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleTrackballActor::~vtkInteractorStyleTrackballActor() +{ + this->InteractionPicker->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + switch (this->State) + { + case VTKIS_ROTATE: + this->FindPokedRenderer(x, y); + this->Rotate(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_PAN: + this->FindPokedRenderer(x, y); + this->Pan(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_DOLLY: + this->FindPokedRenderer(x, y); + this->Dolly(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_SPIN: + this->FindPokedRenderer(x, y); + this->Spin(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_USCALE: + this->FindPokedRenderer(x, y); + this->UniformScale(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::OnLeftButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + this->FindPickedActor(x, y); + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + if (this->Interactor->GetShiftKey()) + { + this->StartPan(); + } + else if (this->Interactor->GetControlKey()) + { + this->StartSpin(); + } + else + { + this->StartRotate(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::OnLeftButtonUp() +{ + switch (this->State) + { + case VTKIS_PAN: + this->EndPan(); + break; + + case VTKIS_SPIN: + this->EndSpin(); + break; + + case VTKIS_ROTATE: + this->EndRotate(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::OnMiddleButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + this->FindPickedActor(x, y); + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + if (this->Interactor->GetControlKey()) + { + this->StartDolly(); + } + else + { + this->StartPan(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::OnMiddleButtonUp() +{ + switch (this->State) + { + case VTKIS_DOLLY: + this->EndDolly(); + break; + + case VTKIS_PAN: + this->EndPan(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::OnRightButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->FindPokedRenderer(x, y); + this->FindPickedActor(x, y); + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + this->StartUniformScale(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::OnRightButtonUp() +{ + switch (this->State) + { + case VTKIS_USCALE: + this->EndUniformScale(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::Rotate() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + + // First get the origin of the assembly + double *obj_center = this->InteractionProp->GetCenter(); + + // GetLength gets the length of the diagonal of the bounding box + double boundRadius = this->InteractionProp->GetLength() * 0.5; + + // Get the view up and view right vectors + double view_up[3], view_look[3], view_right[3]; + + cam->OrthogonalizeViewUp(); + cam->ComputeViewPlaneNormal(); + cam->GetViewUp(view_up); + vtkMath::Normalize(view_up); + cam->GetViewPlaneNormal(view_look); + vtkMath::Cross(view_up, view_look, view_right); + vtkMath::Normalize(view_right); + + // Get the furtherest point from object position+origin + double outsidept[3]; + + outsidept[0] = obj_center[0] + view_right[0] * boundRadius; + outsidept[1] = obj_center[1] + view_right[1] * boundRadius; + outsidept[2] = obj_center[2] + view_right[2] * boundRadius; + + // Convert them to display coord + double disp_obj_center[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2], + disp_obj_center); + + this->ComputeWorldToDisplay(outsidept[0], outsidept[1], outsidept[2], + outsidept); + + double radius = sqrt(vtkMath::Distance2BetweenPoints(disp_obj_center, + outsidept)); + double nxf = + ((double)rwi->GetEventPosition()[0] - (double)disp_obj_center[0]) / radius; + + double nyf = + ((double)rwi->GetEventPosition()[1] - (double)disp_obj_center[1]) / radius; + + double oxf = + ((double)rwi->GetLastEventPosition()[0] - (double)disp_obj_center[0]) / radius; + + double oyf = + ((double)rwi->GetLastEventPosition()[1] - (double)disp_obj_center[1]) / radius; + + if (((nxf * nxf + nyf * nyf) <= 1.0) && + ((oxf * oxf + oyf * oyf) <= 1.0)) + { + double newXAngle = asin(nxf) * vtkMath::RadiansToDegrees(); + double newYAngle = asin(nyf) * vtkMath::RadiansToDegrees(); + double oldXAngle = asin(oxf) * vtkMath::RadiansToDegrees(); + double oldYAngle = asin(oyf) * vtkMath::RadiansToDegrees(); + + double scale[3]; + scale[0] = scale[1] = scale[2] = 1.0; + + double **rotate = new double*[2]; + + rotate[0] = new double[4]; + rotate[1] = new double[4]; + + rotate[0][0] = newXAngle - oldXAngle; + rotate[0][1] = view_up[0]; + rotate[0][2] = view_up[1]; + rotate[0][3] = view_up[2]; + + rotate[1][0] = oldYAngle - newYAngle; + rotate[1][1] = view_right[0]; + rotate[1][2] = view_right[1]; + rotate[1][3] = view_right[2]; + + + this->Prop3DTransform(this->InteractionProp, + obj_center, + 2, + rotate, + scale); + + delete [] rotate[0]; + delete [] rotate[1]; + delete [] rotate; + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::Spin() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + + // Get the axis to rotate around = vector from eye to origin + + double *obj_center = this->InteractionProp->GetCenter(); + + double motion_vector[3]; + double view_point[3]; + + if (cam->GetParallelProjection()) + { + // If parallel projection, want to get the view plane normal... + cam->ComputeViewPlaneNormal(); + cam->GetViewPlaneNormal(motion_vector); + } + else + { + // Perspective projection, get vector from eye to center of actor + cam->GetPosition(view_point); + motion_vector[0] = view_point[0] - obj_center[0]; + motion_vector[1] = view_point[1] - obj_center[1]; + motion_vector[2] = view_point[2] - obj_center[2]; + vtkMath::Normalize(motion_vector); + } + + double disp_obj_center[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2], + disp_obj_center); + + double newAngle = + atan2((double)rwi->GetEventPosition()[1] - (double)disp_obj_center[1], + (double)rwi->GetEventPosition()[0] - (double)disp_obj_center[0]); + + double oldAngle = + atan2((double)rwi->GetLastEventPosition()[1] - (double)disp_obj_center[1], + (double)rwi->GetLastEventPosition()[0] - (double)disp_obj_center[0]); + + newAngle *= vtkMath::RadiansToDegrees(); + oldAngle *= vtkMath::RadiansToDegrees(); + + double scale[3]; + scale[0] = scale[1] = scale[2] = 1.0; + + double **rotate = new double*[1]; + rotate[0] = new double[4]; + + rotate[0][0] = newAngle - oldAngle; + rotate[0][1] = motion_vector[0]; + rotate[0][2] = motion_vector[1]; + rotate[0][3] = motion_vector[2]; + + this->Prop3DTransform(this->InteractionProp, + obj_center, + 1, + rotate, + scale); + + delete [] rotate[0]; + delete [] rotate; + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::Pan() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + // Use initial center as the origin from which to pan + + double *obj_center = this->InteractionProp->GetCenter(); + + double disp_obj_center[3], new_pick_point[4]; + double old_pick_point[4], motion_vector[3]; + + this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2], + disp_obj_center); + + this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0], + (double)rwi->GetEventPosition()[1], + disp_obj_center[2], + new_pick_point); + + this->ComputeDisplayToWorld(double(rwi->GetLastEventPosition()[0]), + double(rwi->GetLastEventPosition()[1]), + disp_obj_center[2], + old_pick_point); + + motion_vector[0] = new_pick_point[0] - old_pick_point[0]; + motion_vector[1] = new_pick_point[1] - old_pick_point[1]; + motion_vector[2] = new_pick_point[2] - old_pick_point[2]; + + if (this->InteractionProp->GetUserMatrix() != NULL) + { + vtkTransform *t = vtkTransform::New(); + t->PostMultiply(); + t->SetMatrix(this->InteractionProp->GetUserMatrix()); + t->Translate(motion_vector[0], motion_vector[1], motion_vector[2]); + this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix()); + t->Delete(); + } + else + { + this->InteractionProp->AddPosition(motion_vector[0], + motion_vector[1], + motion_vector[2]); + } + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::Dolly() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + + double view_point[3], view_focus[3]; + double motion_vector[3]; + + cam->GetPosition(view_point); + cam->GetFocalPoint(view_focus); + + double *center = this->CurrentRenderer->GetCenter(); + + int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; + double yf = (double)dy / (double)center[1] * this->MotionFactor; + double dollyFactor = pow((double)1.1, yf); + + dollyFactor -= 1.0; + motion_vector[0] = (view_point[0] - view_focus[0]) * dollyFactor; + motion_vector[1] = (view_point[1] - view_focus[1]) * dollyFactor; + motion_vector[2] = (view_point[2] - view_focus[2]) * dollyFactor; + + if (this->InteractionProp->GetUserMatrix() != NULL) + { + vtkTransform *t = vtkTransform::New(); + t->PostMultiply(); + t->SetMatrix(this->InteractionProp->GetUserMatrix()); + t->Translate(motion_vector[0], motion_vector[1], + motion_vector[2]); + this->InteractionProp->GetUserMatrix()->DeepCopy(t->GetMatrix()); + t->Delete(); + } + else + { + this->InteractionProp->AddPosition(motion_vector); + } + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::UniformScale() +{ + if (this->CurrentRenderer == NULL || this->InteractionProp == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; + + double *obj_center = this->InteractionProp->GetCenter(); + double *center = this->CurrentRenderer->GetCenter(); + + double yf = (double)dy / (double)center[1] * this->MotionFactor; + double scaleFactor = pow((double)1.1, yf); + + double **rotate = NULL; + + double scale[3]; + scale[0] = scale[1] = scale[2] = scaleFactor; + + this->Prop3DTransform(this->InteractionProp, + obj_center, + 0, + rotate, + scale); + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::FindPickedActor(int x, int y) +{ + this->InteractionPicker->Pick(x, y, 0.0, this->CurrentRenderer); + vtkProp *prop = this->InteractionPicker->GetViewProp(); + if (prop != NULL) + { + this->InteractionProp = vtkProp3D::SafeDownCast(prop); + } + else + { + this->InteractionProp = NULL; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballActor::Prop3DTransform(vtkProp3D *prop3D, + double *boxCenter, + int numRotation, + double **rotate, + double *scale) +{ + vtkMatrix4x4 *oldMatrix = vtkMatrix4x4::New(); + prop3D->GetMatrix(oldMatrix); + + double orig[3]; + prop3D->GetOrigin(orig); + + vtkTransform *newTransform = vtkTransform::New(); + newTransform->PostMultiply(); + if (prop3D->GetUserMatrix() != NULL) + { + newTransform->SetMatrix(prop3D->GetUserMatrix()); + } + else + { + newTransform->SetMatrix(oldMatrix); + } + + newTransform->Translate(-(boxCenter[0]), -(boxCenter[1]), -(boxCenter[2])); + + for (int i = 0; i < numRotation; i++) + { + newTransform->RotateWXYZ(rotate[i][0], rotate[i][1], + rotate[i][2], rotate[i][3]); + } + + if ((scale[0] * scale[1] * scale[2]) != 0.0) + { + newTransform->Scale(scale[0], scale[1], scale[2]); + } + + newTransform->Translate(boxCenter[0], boxCenter[1], boxCenter[2]); + + // now try to get the composit of translate, rotate, and scale + newTransform->Translate(-(orig[0]), -(orig[1]), -(orig[2])); + newTransform->PreMultiply(); + newTransform->Translate(orig[0], orig[1], orig[2]); + + if (prop3D->GetUserMatrix() != NULL) + { + newTransform->GetMatrix(prop3D->GetUserMatrix()); + } + else + { + prop3D->SetPosition(newTransform->GetPosition()); + prop3D->SetScale(newTransform->GetScale()); + prop3D->SetOrientation(newTransform->GetOrientation()); + } + oldMatrix->Delete(); + newTransform->Delete(); +} + diff --git a/Rendering/vtkInteractorStyleTrackballActor.h b/Rendering/vtkInteractorStyleTrackballActor.h new file mode 100644 index 0000000..41a5aa5 --- /dev/null +++ b/Rendering/vtkInteractorStyleTrackballActor.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTrackballActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleTrackballActor - manipulate objects in the scene independent of each other +// .SECTION Description +// vtkInteractorStyleTrackballActor allows the user to interact with (rotate, +// pan, etc.) objects in the scene indendent of each other. In trackball +// interaction, the magnitude of the mouse motion is proportional to the +// actor motion associated with a particular mouse binding. For example, +// small left-button motions cause small changes in the rotation of the +// actor around its center point. +// +// The mouse bindings are as follows. For a 3-button mouse, the left button +// is for rotation, the right button for zooming, the middle button for +// panning, and ctrl + left button for spinning. (With fewer mouse buttons, +// ctrl + shift + left button is for zooming, and shift + left button is for +// panning.) + +// .SECTION See Also +// vtkInteractorStyleTrackballCamera vtkInteractorStyleJoystickActor +// vtkInteractorStyleJoystickCamera + +#ifndef __vtkInteractorStyleTrackballActor_h +#define __vtkInteractorStyleTrackballActor_h + +#include "vtkInteractorStyle.h" + +class vtkCellPicker; + +class VTK_RENDERING_EXPORT vtkInteractorStyleTrackballActor : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleTrackballActor *New(); + vtkTypeRevisionMacro(vtkInteractorStyleTrackballActor,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Event bindings controlling the effects of pressing mouse buttons + // or moving the mouse. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // These methods for the different interactions in different modes + // are overridden in subclasses to perform the correct motion. Since + // they might be called from OnTimer, they do not have mouse coord parameters + // (use interactor's GetEventPosition and GetLastEventPosition) + virtual void Rotate(); + virtual void Spin(); + virtual void Pan(); + virtual void Dolly(); + virtual void UniformScale(); + +protected: + vtkInteractorStyleTrackballActor(); + ~vtkInteractorStyleTrackballActor(); + + void FindPickedActor(int x, int y); + + void Prop3DTransform(vtkProp3D *prop3D, + double *boxCenter, + int NumRotation, + double **rotate, + double *scale); + + double MotionFactor; + + vtkProp3D *InteractionProp; + vtkCellPicker *InteractionPicker; + +private: + vtkInteractorStyleTrackballActor(const vtkInteractorStyleTrackballActor&); // Not implemented. + void operator=(const vtkInteractorStyleTrackballActor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleTrackballCamera.cxx b/Rendering/vtkInteractorStyleTrackballCamera.cxx new file mode 100644 index 0000000..009cf24 --- /dev/null +++ b/Rendering/vtkInteractorStyleTrackballCamera.cxx @@ -0,0 +1,388 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTrackballCamera.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleTrackballCamera.h" + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkInteractorStyleTrackballCamera, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkInteractorStyleTrackballCamera); + +//---------------------------------------------------------------------------- +vtkInteractorStyleTrackballCamera::vtkInteractorStyleTrackballCamera() +{ + this->MotionFactor = 10.0; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleTrackballCamera::~vtkInteractorStyleTrackballCamera() +{ +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + switch (this->State) + { + case VTKIS_ROTATE: + this->FindPokedRenderer(x, y); + this->Rotate(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_PAN: + this->FindPokedRenderer(x, y); + this->Pan(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_DOLLY: + this->FindPokedRenderer(x, y); + this->Dolly(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + + case VTKIS_SPIN: + this->FindPokedRenderer(x, y); + this->Spin(); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnLeftButtonDown() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + if (this->Interactor->GetShiftKey()) + { + if (this->Interactor->GetControlKey()) + { + this->StartDolly(); + } + else + { + this->StartPan(); + } + } + else + { + if (this->Interactor->GetControlKey()) + { + this->StartSpin(); + } + else + { + this->StartRotate(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnLeftButtonUp() +{ + switch (this->State) + { + case VTKIS_DOLLY: + this->EndDolly(); + break; + + case VTKIS_PAN: + this->EndPan(); + break; + + case VTKIS_SPIN: + this->EndSpin(); + break; + + case VTKIS_ROTATE: + this->EndRotate(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnMiddleButtonDown() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartPan(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnMiddleButtonUp() +{ + switch (this->State) + { + case VTKIS_PAN: + this->EndPan(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnRightButtonDown() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartDolly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnRightButtonUp() +{ + switch (this->State) + { + case VTKIS_DOLLY: + this->EndDolly(); + break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnMouseWheelForward() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartDolly(); + double factor = this->MotionFactor * 0.2 * this->MouseWheelMotionFactor; + this->Dolly(pow((double)1.1, factor)); + this->EndDolly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::OnMouseWheelBackward() +{ + this->FindPokedRenderer(this->Interactor->GetEventPosition()[0], + this->Interactor->GetEventPosition()[1]); + if (this->CurrentRenderer == NULL) + { + return; + } + + this->StartDolly(); + double factor = this->MotionFactor * -0.2 * this->MouseWheelMotionFactor; + this->Dolly(pow((double)1.1, factor)); + this->EndDolly(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::Rotate() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + int dx = rwi->GetEventPosition()[0] - rwi->GetLastEventPosition()[0]; + int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; + + int *size = this->CurrentRenderer->GetRenderWindow()->GetSize(); + + double delta_elevation = -20.0 / size[1]; + double delta_azimuth = -20.0 / size[0]; + + double rxf = (double)dx * delta_azimuth * this->MotionFactor; + double ryf = (double)dy * delta_elevation * this->MotionFactor; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + camera->Azimuth(rxf); + camera->Elevation(ryf); + camera->OrthogonalizeViewUp(); + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + + if (rwi->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::Spin() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + double *center = this->CurrentRenderer->GetCenter(); + + double newAngle = + atan2((double)rwi->GetEventPosition()[1] - (double)center[1], + (double)rwi->GetEventPosition()[0] - (double)center[0]); + + double oldAngle = + atan2((double)rwi->GetLastEventPosition()[1] - (double)center[1], + (double)rwi->GetLastEventPosition()[0] - (double)center[0]); + + newAngle *= vtkMath::RadiansToDegrees(); + oldAngle *= vtkMath::RadiansToDegrees(); + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + camera->Roll(newAngle - oldAngle); + camera->OrthogonalizeViewUp(); + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::Pan() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + + double viewFocus[4], focalDepth, viewPoint[3]; + double newPickPoint[4], oldPickPoint[4], motionVector[3]; + + // Calculate the focal depth since we'll be using it a lot + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetFocalPoint(viewFocus); + this->ComputeWorldToDisplay(viewFocus[0], viewFocus[1], viewFocus[2], + viewFocus); + focalDepth = viewFocus[2]; + + this->ComputeDisplayToWorld((double)rwi->GetEventPosition()[0], + (double)rwi->GetEventPosition()[1], + focalDepth, + newPickPoint); + + // Has to recalc old mouse point since the viewport has moved, + // so can't move it outside the loop + + this->ComputeDisplayToWorld((double)rwi->GetLastEventPosition()[0], + (double)rwi->GetLastEventPosition()[1], + focalDepth, + oldPickPoint); + + // Camera motion is reversed + + motionVector[0] = oldPickPoint[0] - newPickPoint[0]; + motionVector[1] = oldPickPoint[1] - newPickPoint[1]; + motionVector[2] = oldPickPoint[2] - newPickPoint[2]; + + camera->GetFocalPoint(viewFocus); + camera->GetPosition(viewPoint); + camera->SetFocalPoint(motionVector[0] + viewFocus[0], + motionVector[1] + viewFocus[1], + motionVector[2] + viewFocus[2]); + + camera->SetPosition(motionVector[0] + viewPoint[0], + motionVector[1] + viewPoint[1], + motionVector[2] + viewPoint[2]); + + if (rwi->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + rwi->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::Dolly() +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + double *center = this->CurrentRenderer->GetCenter(); + int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; + double dyf = this->MotionFactor * (double)(dy) / (double)(center[1]); + this->Dolly(pow((double)1.1, dyf)); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::Dolly(double factor) +{ + if (this->CurrentRenderer == NULL) + { + return; + } + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if (camera->GetParallelProjection()) + { + camera->SetParallelScale(camera->GetParallelScale() / factor); + } + else + { + camera->Dolly(factor); + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } + } + + if (this->Interactor->GetLightFollowCamera()) + { + this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + } + + this->Interactor->Render(); +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleTrackballCamera::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + +} + diff --git a/Rendering/vtkInteractorStyleTrackballCamera.h b/Rendering/vtkInteractorStyleTrackballCamera.h new file mode 100644 index 0000000..7830c61 --- /dev/null +++ b/Rendering/vtkInteractorStyleTrackballCamera.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleTrackballCamera.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkInteractorStyleTrackballCamera - interactive manipulation of the camera +// .SECTION Description +// vtkInteractorStyleTrackballCamera allows the user to interactively +// manipulate (rotate, pan, etc.) the camera, the viewpoint of the scene. In +// trackball interaction, the magnitude of the mouse motion is proportional +// to the camera motion associated with a particular mouse binding. For +// example, small left-button motions cause small changes in the rotation of +// the camera around its focal point. For a 3-button mouse, the left button +// is for rotation, the right button for zooming, the middle button for +// panning, and ctrl + left button for spinning. (With fewer mouse buttons, +// ctrl + shift + left button is for zooming, and shift + left button is for +// panning.) + +// .SECTION See Also +// vtkInteractorStyleTrackballActor vtkInteractorStyleJoystickCamera +// vtkInteractorStyleJoystickActor + +#ifndef __vtkInteractorStyleTrackballCamera_h +#define __vtkInteractorStyleTrackballCamera_h + +#include "vtkInteractorStyle.h" + +class VTK_RENDERING_EXPORT vtkInteractorStyleTrackballCamera : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleTrackballCamera *New(); + vtkTypeRevisionMacro(vtkInteractorStyleTrackballCamera,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Event bindings controlling the effects of pressing mouse buttons + // or moving the mouse. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + virtual void OnMouseWheelForward(); + virtual void OnMouseWheelBackward(); + + // These methods for the different interactions in different modes + // are overridden in subclasses to perform the correct motion. Since + // they are called by OnTimer, they do not have mouse coord parameters + // (use interactor's GetEventPosition and GetLastEventPosition) + virtual void Rotate(); + virtual void Spin(); + virtual void Pan(); + virtual void Dolly(); + +protected: + vtkInteractorStyleTrackballCamera(); + ~vtkInteractorStyleTrackballCamera(); + + double MotionFactor; + + virtual void Dolly(double factor); + +private: + vtkInteractorStyleTrackballCamera(const vtkInteractorStyleTrackballCamera&); // Not implemented. + void operator=(const vtkInteractorStyleTrackballCamera&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkInteractorStyleUnicam.cxx b/Rendering/vtkInteractorStyleUnicam.cxx new file mode 100644 index 0000000..7016285 --- /dev/null +++ b/Rendering/vtkInteractorStyleUnicam.cxx @@ -0,0 +1,682 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleUnicam.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * This work was produced under a grant from the Department of Energy to Brown + * University. Neither Brown University nor the authors assert any copyright + * with respect to this work and it may be used, reproduced, and distributed + * without permission. + */ + +#include "vtkInteractorStyleUnicam.h" + +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" +#include "vtkWorldPointPicker.h" + +vtkCxxRevisionMacro(vtkInteractorStyleUnicam, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkInteractorStyleUnicam); + +// define 'TheTime()' function-- returns time in elapsed seconds +#if defined(_WIN32) || defined(WIN32) +# include "vtkWindows.h" + +static double TheTime() + {return double(GetTickCount())/1000.0;} +#else +#include + +static double TheTime() +{ + struct timeval ts; struct timezone tz; + gettimeofday(&ts, &tz); + return (double)(ts.tv_sec + ts.tv_usec/1e6); +} +#endif + +vtkInteractorStyleUnicam::vtkInteractorStyleUnicam() +{ + // use z-buffer picking + this->InteractionPicker = vtkWorldPointPicker::New(); + + // set to default modes + this->IsDot = 0; + this->ButtonDown = VTK_UNICAM_NONE; + state = 0; // which camera mode is being used? + + // create focus sphere actor + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(6); + sphere->SetPhiResolution(6); + vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New(); + sphereMapper->SetInput(sphere->GetOutput()); + sphere->Delete(); + + // XXX - would like to make the focus sphere not be affected by + // XXX - the lights-- i.e., always be easily easily seen. i'm not sure + // XXX - how to do that. + this->FocusSphere = vtkActor::New(); + this->FocusSphere->SetMapper(sphereMapper); + this->FocusSphere->GetProperty()->SetColor(0.8900,0.6600,0.4100); + this->FocusSphere->GetProperty()->SetRepresentationToWireframe(); + sphereMapper->Delete(); + + // set WorldUpVector to be z-axis by default + WorldUpVector[0] = 0; + WorldUpVector[1] = 0; + WorldUpVector[2] = 1; +} + +vtkInteractorStyleUnicam::~vtkInteractorStyleUnicam() +{ + this->InteractionPicker->Delete(); + this->FocusSphere->Delete(); +} + +void vtkInteractorStyleUnicam::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Interaction Picker: " << this->InteractionPicker; +// os << indent << "WorldUpVector: " << this->WorldUpVector; +} + +void vtkInteractorStyleUnicam::OnTimer() +{ + if (this->ButtonDown != VTK_UNICAM_NONE) + { + // restart timer-- we want to keep getting 'OnMouseMove' events + if (this->UseTimers) + { + this->Interactor->CreateTimer(VTKI_TIMER_UPDATE); + } + } +} + +void vtkInteractorStyleUnicam::SetWorldUpVector(double x, double y, double z) +{ + WorldUpVector[0] = x; + WorldUpVector[1] = y; + WorldUpVector[2] = z; +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::OnLeftButtonDown() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->ButtonDown = VTK_UNICAM_BUTTON_LEFT; + if (this->UseTimers) + { + this->Interactor->CreateTimer(VTKI_TIMER_UPDATE); + } + + this->DTime = TheTime(); + this->Dist = 0; + + // cam manip init + double curpt[2]; + this->NormalizeMouseXY(x, y, &curpt[0], &curpt[1]); + this->LastPos[0] = curpt[0]; + this->LastPos[1] = curpt[1]; + + this->StartPix[0] = this->LastPix[0] = x; + this->StartPix[1] = this->LastPix[1] = y; + + // Find 'this->DownPt' (point in world space under the cursor tip) + // + // Note: If no object has been rendered to the pixel (X, Y), then + // vtkWorldPointPicker will return a z-value with depth equal + // to the distance from the camera's position to the focal point. + // This seems like an arbitrary, but perhaps reasonable, default value. + // + this->FindPokedRenderer(x, y); + this->InteractionPicker->Pick(x, y, 0.0, this->CurrentRenderer); + this->InteractionPicker->GetPickPosition(this->DownPt); + + // if someone has already clicked to make a dot and they're not clicking + // on it now, OR if the user is clicking on the perimeter of the screen, + // then we want to go into rotation mode. + if ((fabs(curpt[0]) > .85 || fabs(curpt[1]) > .9) || this->IsDot) + { + if (this->IsDot) + { + this->FocusSphere->GetPosition(this->Center); + } + state = VTK_UNICAM_CAM_INT_ROT; + } + else + { + state = VTK_UNICAM_CAM_INT_CHOOSE; + } +} + +//---------------------------------------------------------------------------- +double vtkInteractorStyleUnicam::WindowAspect() +{ + double w = Interactor->GetRenderWindow()->GetSize()[0]; + double h = Interactor->GetRenderWindow()->GetSize()[1]; + + return w/h; +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::NormalizeMouseXY(int X, int Y, + double *NX, double *NY) +{ + double w = Interactor->GetRenderWindow()->GetSize()[0]; + double h = Interactor->GetRenderWindow()->GetSize()[1]; + + *NX = -1.0 + 2.0 * double(X) / w; + *NY = -1.0 + 2.0 * double(Y) / h; +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::OnMouseMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + // filter out any repeated events + static int last_X = 0; + static int last_Y = 0; + if (x == last_X && y == last_Y) + { + return; + } + + // channel event to right method handler. + switch (this->ButtonDown) + { + case VTK_UNICAM_BUTTON_LEFT: + OnLeftButtonMove(); + break; + } + + last_X = x; + last_Y = y; + + this->Interactor->Render(); // re-draw scene.. it should have changed +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::OnLeftButtonUp() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + this->ButtonDown = VTK_UNICAM_NONE; + + if (state == VTK_UNICAM_CAM_INT_ROT && this->IsDot ) + { + this->FocusSphereRenderer->RemoveActor(this->FocusSphere); + this->IsDot = 0; + } + else if (state == VTK_UNICAM_CAM_INT_CHOOSE) + { + if (this->IsDot) + { + this->FocusSphereRenderer->RemoveActor(this->FocusSphere); + this->IsDot = 0; + } + else + { + this->FocusSphere->SetPosition(this->DownPt[0], + this->DownPt[1], + this->DownPt[2]); + + double from[3]; + this->FindPokedRenderer(x, y); + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetPosition(from); + + double vec[3]; + vec[0] = this->DownPt[0] - from[0]; + vec[1] = this->DownPt[1] - from[1]; + vec[2] = this->DownPt[2] - from[2]; + + double at_v[4]; + camera->GetDirectionOfProjection(at_v); + vtkMath::Normalize(at_v); + + // calculate scale so focus sphere always is the same size on the screen + double s = 0.02 * vtkMath::Dot(at_v, vec); + + this->FocusSphere->SetScale (s, s, s); + + this->FindPokedRenderer(x, y); + this->FocusSphereRenderer = this->CurrentRenderer; + this->FocusSphereRenderer->AddActor(this->FocusSphere); + + this->IsDot = 1; + } + this->Interactor->Render(); + } + + vtkRenderWindowInteractor *rwi = this->Interactor; + rwi->GetRenderWindow()->SetDesiredUpdateRate(rwi->GetStillUpdateRate()); + rwi->Render(); + if (this->UseTimers) + { + rwi->DestroyTimer(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::OnLeftButtonMove() +{ + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + + switch (state) + { + case VTK_UNICAM_CAM_INT_CHOOSE: this->ChooseXY(x, y); break; + case VTK_UNICAM_CAM_INT_ROT: this->RotateXY(x, y); break; + case VTK_UNICAM_CAM_INT_PAN: this->PanXY(x, y); break; + case VTK_UNICAM_CAM_INT_DOLLY: this->DollyXY(x, y); break; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::ChooseXY( int X, int Y ) +{ + int te[2]; // pixel location + te[0] = X; + te[1] = Y; + + double curpt[2]; + this->NormalizeMouseXY(X, Y, &curpt[0], &curpt[1]); + + double delta[2]; + delta[0] = curpt[0] - this->LastPos[0]; + delta[1] = curpt[1] - this->LastPos[1]; + this->LastPos[0] = te[0]; + this->LastPos[1] = te[1]; + + double tdelt(TheTime() - this->DTime); + + this->Dist += sqrt(delta[0] * delta[0] + delta[1] * delta[1]); + + double sdelt[2]; + sdelt[0] = te[0] - this->StartPix[0]; + sdelt[1] = te[1] - this->StartPix[1]; + + int xa=0,ya=1; + if (getenv("FLIP_CAM_MANIP")) + { + int tmp = xa; + xa = ya; + ya = tmp; + } + + double len = sqrt(sdelt[0] * sdelt[0] + sdelt[1] * sdelt[1]); + if (fabs(sdelt[ya])/len > 0.9 && tdelt > 0.05) + { + state = VTK_UNICAM_CAM_INT_DOLLY; + } + else if (tdelt < 0.1 && this->Dist < 0.03) + { + return; + } + else + { + if (fabs(sdelt[xa])/len > 0.6 ) + { + state = VTK_UNICAM_CAM_INT_PAN; + } + else + { + state = VTK_UNICAM_CAM_INT_DOLLY; + } + } +} + +// define some utilty functions +template +inline Type clamp(const Type a, + const Type b, + const Type c) { return a > b ? (a < c ? a : c) : b ; } +inline int Sign (double a) { return a > 0 ? 1 : a < 0 ? -1 : 0; } + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::RotateXY( int X, int Y ) +{ + double cpt[3]; + double center[3]; + this->FocusSphere->GetPosition(center); + this->ComputeWorldToDisplay(center[0], center[1], center[2], cpt); + this->NormalizeMouseXY(static_cast(cpt[0]), static_cast(cpt[1]), + &cpt[0], &cpt[1]); + + double radsq = pow(1.0+fabs(cpt[0]),2.0); // squared rad of virtual cylinder + + double tp[2], te[2]; + this->NormalizeMouseXY(static_cast(this->LastPix[0]), + static_cast(this->LastPix[1]), &tp[0], &tp[1]); + this->NormalizeMouseXY(X, Y, &te[0], &te[1]); + this->LastPix[0] = X; + this->LastPix[1] = Y; + + double op[3], oe[3]; + op[0] = tp[0]; + op[1] = 0; + op[2] = 0; + oe[0] = te[0]; + oe[1] = 0; + oe[2] = 0; + + double opsq = op[0] * op[0], oesq = oe[0] * oe[0]; + + double lop = opsq > radsq ? 0 : sqrt(radsq - opsq); + double loe = oesq > radsq ? 0 : sqrt(radsq - oesq); + + double nop[3], noe[3]; + nop[0] = op[0]; + nop[1] = 0; + nop[2] = lop; + vtkMath::Normalize(nop); + noe[0] = oe[0]; + noe[1] = 0; + noe[2] = loe; + vtkMath::Normalize(noe); + + double dot = vtkMath::Dot(nop, noe); + + if (fabs(dot) > 0.0001) + { + this->FindPokedRenderer(X, Y); + + double angle = -2*acos(clamp(dot,(double)-1.0,(double)1.0)) * Sign(te[0]-tp[0]); + + double UPvec[3]; + UPvec[0] = WorldUpVector[0]; + UPvec[1] = WorldUpVector[1]; + UPvec[2] = WorldUpVector[2]; + vtkMath::Normalize(UPvec); + + MyRotateCamera(center[0], center[1], center[2], + UPvec[0], UPvec[1], UPvec[2], + angle); + + double dvec[3]; + double from[3]; + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetPosition(from); + for(int i=0; i<3; i++) + { + dvec[i] = from[i] - center[i]; + } + + double rdist = te[1]-tp[1]; + vtkMath::Normalize(dvec); + + double atV[4], upV[4], rightV[4]; + camera->GetViewPlaneNormal(atV); + camera->GetViewUp(upV); + vtkMath::Cross(upV, atV, rightV); + vtkMath::Normalize(rightV); + + // + // The following two tests try to prevent chaotic camera movement + // that results from rotating over the poles defined by the + // "WorldUpVector". The problem is the constraint to keep the + // camera's up vector in line w/ the WorldUpVector is at odds with + // the action of rotating tover the top of the virtual sphere used + // for rotation. The solution here is to prevent the user from + // rotating the last bit required to "go over the top"-- as a + // consequence, you can never look directly down on the poles. + // + // The "0.99" value is somewhat arbitrary, but seems to produce + // reasonable results. (Theoretically, some sort of clamping + // function could probably be used rather than a hard cutoff, but + // time constraints prevent figuring that out right now.) + // + const double OVER_THE_TOP_THRESHOLD = 0.99; + if (vtkMath::Dot(UPvec, atV) > OVER_THE_TOP_THRESHOLD && rdist < 0) + rdist = 0; + if (vtkMath::Dot(UPvec, atV) < -OVER_THE_TOP_THRESHOLD && rdist > 0) + rdist = 0; + + MyRotateCamera(center[0], center[1], center[2], + rightV[0], rightV[1], rightV[2], + rdist); + + camera->SetViewUp(UPvec[0], UPvec[1], UPvec[2]); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUnicam::DollyXY( int X, int Y ) +{ + int i; + double cn[2], ln[2]; + this->NormalizeMouseXY(X, Y, &cn[0], &cn[1]); + this->NormalizeMouseXY(static_cast(this->LastPix[0]), + static_cast(this->LastPix[1]), &ln[0], &ln[1]); + + double delta[2]; + delta[0] = cn[0] - ln[0]; + delta[1] = cn[1] - ln[1]; + this->LastPix[0] = X; + this->LastPix[1] = Y; + + // 1. handle dollying + // XXX - assume perspective projection for now. + double from[3]; + this->FindPokedRenderer(X, Y); + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetPosition(from); + + double movec[3]; + for(i=0; i<3; i++) + { + movec[i] = this->DownPt[i] - from[i]; + } + + double offset1[3]; + for(i=0; i<3; i++) + { + offset1[i] = movec[i] * delta[1] * -4; + } + + this->MyTranslateCamera(offset1); + + + // 2. now handle side-to-side panning + double rightV[3], upV[3]; + this->GetRightVandUpV(this->DownPt, camera, + rightV, upV); + + double offset2[3]; + for(i=0; i<3; i++) + { + offset2[i] = (-delta[0] * rightV[i]); + } + + this->MyTranslateCamera(offset2); +} + +//---------------------------------------------------------------------------- +// +// Transform mouse horizontal & vertical movements to a world +// space offset for the camera that maintains pick correlation. +// +void vtkInteractorStyleUnicam::PanXY( int X, int Y ) +{ + double delta[2]; + double cn[2], ln[2]; + int i; + + this->NormalizeMouseXY(X, Y, &cn[0], &cn[1]); + this->NormalizeMouseXY(static_cast(this->LastPix[0]), + static_cast(this->LastPix[1]), &ln[0], &ln[1]); + delta[0] = cn[0] - ln[0]; + delta[1] = cn[1] - ln[1]; + this->LastPix[0] = X; + this->LastPix[1] = Y; + + // XXX - assume perspective projection for now + + this->FindPokedRenderer(X, Y); + + double rightV[3], upV[3]; + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + this->GetRightVandUpV(this->DownPt, camera, + rightV, upV); + + double offset[3]; + for(i=0; i<3; i++) + { + offset[i] = (-delta[0] * rightV[i] + + -delta[1] * upV [i]); + } + + this->MyTranslateCamera(offset); +} + +// +// Given a 3D point & a vtkCamera, compute the vectors that extend +// from the projection of the center of projection to the center of +// the right-edge and the center of the top-edge onto the plane +// containing the 3D point & with normal parallel to the camera's +// projection plane. +// +void vtkInteractorStyleUnicam::GetRightVandUpV(double *p, vtkCamera *cam, + double *rightV, double *upV) +{ + int i; + + // Compute the horizontal & vertical scaling ('scalex' and 'scaley') + // factors as function of the down point & camera params. + double from[3]; + cam->GetPosition(from); + + // construct a vector from the viewing position to the picked point + double vec[3]; + for(i=0; i<3; i++) + { + vec[i] = p[i] - from[i]; + } + + // Get shortest distance 'l' between the viewing position and + // plane parallel to the projection plane that contains the 'DownPt'. + double atV[4]; + cam->GetViewPlaneNormal(atV); + vtkMath::Normalize(atV); + double l = -vtkMath::Dot(vec, atV); + + double view_angle = cam->GetViewAngle() * vtkMath::Pi() / 180.0; + double w = Interactor->GetRenderWindow()->GetSize()[0]; + double h = Interactor->GetRenderWindow()->GetSize()[1]; + double scalex = w/h*((2*l*tan(view_angle/2))/2); + double scaley = ((2*l*tan(view_angle/2))/2); + + // construct the camera offset vector as function of delta mouse X & Y. + cam->GetViewUp(upV); + vtkMath::Cross(upV, atV, rightV); + vtkMath::Cross(atV, rightV, upV); // (make sure 'upV' is orthogonal + // to 'atV' & 'rightV') + vtkMath::Normalize(rightV); + vtkMath::Normalize(upV); + + + for(i=0; i<3; i++) + { + rightV[i] = rightV[i] * scalex; + upV [i] = upV [i] * scaley; + } +} + +// +// Rotate the camera by 'angle' degrees about the point +// and around the vector/axis . +// +void vtkInteractorStyleUnicam::MyRotateCamera(double cx, double cy, double cz, + double ax, double ay, double az, + double angle) +{ + angle *= 180.0 / vtkMath::Pi(); // vtk uses degrees, not radians + + double p[4], f[4], u[4]; + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetPosition (p); + camera->GetFocalPoint(f); + camera->GetViewUp (u); + p[3] = f[3] = 1.0; // (points) + u[3] = 0.0; // (a vector) + + vtkTransform *t = vtkTransform::New(); + t->PostMultiply(); + t->Identity(); + t->Translate(-cx, -cy, -cz); + t->RotateWXYZ(angle, ax, ay, az); + t->Translate( cx, cy, cz); + + double new_p[4], new_f[4]; + t->MultiplyPoint(p, new_p); + t->MultiplyPoint(f, new_f); + + double new_u[4]; + t->Identity(); + t->RotateWXYZ(angle, ax, ay, az); + t->MultiplyPoint(u, new_u); + + camera->SetPosition (new_p[0], new_p[1], new_p[2]); + camera->SetFocalPoint(new_f[0], new_f[1], new_f[2]); + camera->SetViewUp (new_u[0], new_u[1], new_u[2]); + + // IMPORTANT! If you don't re-compute view plane normal, the camera + // view gets all messed up. + camera->ComputeViewPlaneNormal(); + + t->Delete(); +} + +// Translate the camera by the offset . Update +// the camera clipping range. +// +void vtkInteractorStyleUnicam::MyTranslateCamera(double v[3]) +{ + double p[3], f[3]; + vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); + camera->GetPosition (p); + camera->GetFocalPoint(f); + + double newP[3], newF[3]; + for(int i=0;i<3;i++) + { + newP[i] = p[i] + v[i]; + newF[i] = f[i] + v[i]; + } + + camera->SetPosition (newP); + camera->SetFocalPoint(newF); + + if (this->AutoAdjustCameraClippingRange) + { + this->CurrentRenderer->ResetCameraClippingRange(); + } +} + diff --git a/Rendering/vtkInteractorStyleUnicam.h b/Rendering/vtkInteractorStyleUnicam.h new file mode 100644 index 0000000..b28a091 --- /dev/null +++ b/Rendering/vtkInteractorStyleUnicam.h @@ -0,0 +1,184 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleUnicam.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * This work (vtkInteractorStyleUnicam.h) was produced under a grant from + * the Department of Energy to Brown University. Neither Brown University + * nor the authors assert any copyright with respect to this work and it may + * be used, reproduced, and distributed without permission. + */ + +// .NAME vtkInteractorStyleUnicam - provides Unicam navigation style +// .SECTION Description +// UniCam is a camera interactor. Here, just the primary features of the +// UniCam technique are implemented. UniCam requires just one mouse button +// and supports context sensitive dollying, panning, and rotation. (In this +// implementation, it uses the right mouse button, leaving the middle and +// left available for other functions.) For more information, see the paper +// at: +// +// ftp://ftp.cs.brown.edu/pub/papers/graphics/research/unicam.pdf +// +// The following is a brief description of the UniCam Camera Controls. You +// can perform 3 operations on the camera: rotate, pan, and dolly the camera. +// All operations are reached through the right mouse button & mouse +// movements. +// +// IMPORTANT: UniCam assumes there is an axis that makes sense as a "up" +// vector for the world. By default, this axis is defined to be the +// vector <0,0,1>. You can set it explicitly for the data you are +// viewing with the 'SetWorldUpVector(..)' method in C++, or similarly +// in Tcl/Tk (or other interpreted languages). +// +// 1. ROTATE: +// +// Position the cursor over the point you wish to rotate around and press and +// release the left mouse button. A 'focus dot' appears indicating the +// point that will be the center of rotation. To rotate, press and hold the +// left mouse button and drag the mouse.. release the button to complete the +// rotation. +// +// Rotations can be done without placing a focus dot first by moving the +// mouse cursor to within 10% of the window border & pressing and holding the +// left button followed by dragging the mouse. The last focus dot position +// will be re-used. +// +// 2. PAN: +// +// Click and hold the left mouse button, and initially move the mouse left +// or right. The point under the initial pick will pick correlate w/ the +// mouse tip-- (i.e., direct manipulation). +// +// 3. DOLLY (+ PAN): +// +// Click and hold the left mouse button, and initially move the mouse up or +// down. Moving the mouse down will dolly towards the picked point, and moving +// the mouse up will dolly away from it. Dollying occurs relative to the +// picked point which simplifies the task of dollying towards a region of +// interest. Left and right mouse movements will pan the camera left and right. +// +// .SECTION Caveats +// (NOTE: This implementation of Unicam assumes a perspective camera. It +// could be modified relatively easily to also support an orthographic +// projection.) + + +#ifndef __vtkInteractorStyleUnicam_h +#define __vtkInteractorStyleUnicam_h + +#include "vtkInteractorStyle.h" + +class vtkCamera; +class vtkWorldPointPicker; + +// +// XXX - would have preferred to make these enumerations within the class, +// enum { NONE=0, BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT }; +// enum {CAM_INT_ROT, CAM_INT_CHOOSE, CAM_INT_PAN, CAM_INT_DOLLY}; +// but vtkWrapTcl signaled a "syntax error" when it parsed the 'enum' line. +// So, am making them defines which is what the other classes that want +// to have constants appear to do. +// +// buttons pressed +#define VTK_UNICAM_NONE 0 +#define VTK_UNICAM_BUTTON_LEFT 1 +#define VTK_UNICAM_BUTTON_MIDDLE 2 +#define VTK_UNICAM_BUTTON_RIGHT 3 +// +// camera modes +#define VTK_UNICAM_CAM_INT_ROT 0 +#define VTK_UNICAM_CAM_INT_CHOOSE 1 +#define VTK_UNICAM_CAM_INT_PAN 2 +#define VTK_UNICAM_CAM_INT_DOLLY 3 + +class VTK_RENDERING_EXPORT vtkInteractorStyleUnicam : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleUnicam *New(); + vtkTypeRevisionMacro(vtkInteractorStyleUnicam,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + void SetWorldUpVector(double a[3]) {this->SetWorldUpVector(a[0],a[1],a[2]);} + void SetWorldUpVector(double x, double y, double z); + vtkGetVectorMacro(WorldUpVector, double, 3); + + // Description: + // Concrete implementation of event bindings + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnLeftButtonMove(); + + // Description: + // OnTimer calls RotateCamera, RotateActor etc which should be overridden by + // style subclasses. + virtual void OnTimer(); + +protected: + vtkInteractorStyleUnicam(); + virtual ~vtkInteractorStyleUnicam(); + + vtkWorldPointPicker *InteractionPicker; + + int ButtonDown; // which button is down + double DTime; // time mouse button was pressed + double Dist; // distance the mouse has moved since button press + double StartPix[2]; // pixel mouse movement started at + double LastPos[2]; // normalized position of mouse last frame + double LastPix[2]; // pixel position of mouse last frame + double DownPt[3]; // 3D point under cursor when mouse button pressed + double Center [3]; // center of camera rotation + + double WorldUpVector[3]; // what the world thinks the 'up' vector is + + vtkActor *FocusSphere; // geometry for indicating center of rotation + int IsDot; // flag-- is the FocusSphere being displayed? + vtkRenderer *FocusSphereRenderer; // renderer for 'FocusSphere' + + int state; // which navigation mode was selected? + + void ChooseXY( int X, int Y ); // method for choosing type of navigation + void RotateXY( int X, int Y ); // method for rotating + void DollyXY( int X, int Y ); // method for dollying + void PanXY( int X, int Y ); // method for panning + + // conveinence methods for translating & rotating the camera + void MyTranslateCamera(double v[3]); + void MyRotateCamera(double cx, double cy, double cz, + double ax, double ay, double az, + double angle); + + // Given a 3D point & a vtkCamera, compute the vectors that extend + // from the projection of the center of projection to the center of + // the right-edge and the center of the top-edge onto the plane + // containing the 3D point & with normal parallel to the camera's + // projection plane. + void GetRightVandUpV(double *p, vtkCamera *cam, + double *rightV, double *upV); + + // takes in pixels, returns normalized window coordinates + void NormalizeMouseXY(int X, int Y, double *NX, double *NY); + + // return the aspect ratio of the current window + double WindowAspect(); +private: + vtkInteractorStyleUnicam(const vtkInteractorStyleUnicam&); // Not implemented. + void operator=(const vtkInteractorStyleUnicam&); // Not implemented. +}; + +#endif // __vtkInteractorStyleUnicam_h + + + diff --git a/Rendering/vtkInteractorStyleUser.cxx b/Rendering/vtkInteractorStyleUser.cxx new file mode 100644 index 0000000..d4186b3 --- /dev/null +++ b/Rendering/vtkInteractorStyleUser.cxx @@ -0,0 +1,349 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleUser.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkInteractorStyleUser.h" +#include "vtkMath.h" +#include "vtkCellPicker.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + + +vtkCxxRevisionMacro(vtkInteractorStyleUser, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkInteractorStyleUser); + +//---------------------------------------------------------------------------- +vtkInteractorStyleUser::vtkInteractorStyleUser() +{ + // Tell the parent class not to handle observers + // that has to be done here + this->HandleObserversOff(); + this->LastPos[0] = this->LastPos[1] = 0; + this->OldPos[0] = this->OldPos[1] = 0; + this->ShiftKey = 0; + this->CtrlKey = 0; + this->Char = '\0'; + this->KeySym = (char *) ""; + this->Button = 0; +} + +//---------------------------------------------------------------------------- +vtkInteractorStyleUser::~vtkInteractorStyleUser() +{ +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "LastPos: (" << this->LastPos[0] << ", " + << this->LastPos[1] << ")\n"; + os << indent << "OldPos: (" << this->OldPos[0] << ", " + << this->OldPos[1] << ")\n"; + os << indent << "ShiftKey: " << this->ShiftKey << "\n"; + os << indent << "CtrlKey: " << this->CtrlKey << "\n"; + os << indent << "Char: " << this->Char << "\n"; + os << indent << "KeySym: " << this->KeySym << "\n"; + os << indent << "Button: " << this->Button << "\n"; +} + +//---------------------------------------------------------------------------- +// checks for USERINTERACTION state, then defers to the superclass modes +void vtkInteractorStyleUser::OnTimer() +{ + if (this->HasObserver(vtkCommand::TimerEvent)) + { + this->InvokeEvent(vtkCommand::TimerEvent,NULL); + } + + if (this->State == VTKIS_USERINTERACTION) + { + if (this->HasObserver(vtkCommand::UserEvent)) + { + this->InvokeEvent(vtkCommand::UserEvent,NULL); + this->OldPos[0] = this->LastPos[0]; + this->OldPos[1] = this->LastPos[1]; + if (this->UseTimers) + { + this->Interactor->CreateTimer(VTKI_TIMER_UPDATE); + } + } + } + else if (!(this->HasObserver(vtkCommand::MouseMoveEvent) && + (this->Button == 0 || + (this->HasObserver(vtkCommand::LeftButtonPressEvent) && this->Button == 1) || + (this->HasObserver(vtkCommand::MiddleButtonPressEvent) && this->Button == 2) || + (this->HasObserver(vtkCommand::RightButtonPressEvent) && this->Button == 3)))) + { + this->vtkInteractorStyle::OnTimer(); + } + else if (this->HasObserver(vtkCommand::TimerEvent)) + { + if (this->UseTimers) + { + this->Interactor->CreateTimer(VTKI_TIMER_UPDATE); + } + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnKeyPress() +{ + if (this->HasObserver(vtkCommand::KeyPressEvent)) + { + this->ShiftKey = this->Interactor->GetShiftKey(); + this->CtrlKey = this->Interactor->GetControlKey(); + this->KeySym = this->Interactor->GetKeySym(); + this->Char = this->Interactor->GetKeyCode(); + this->InvokeEvent(vtkCommand::KeyPressEvent, NULL); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnKeyRelease() +{ + if (this->HasObserver(vtkCommand::KeyReleaseEvent)) + { + this->ShiftKey = this->Interactor->GetShiftKey(); + this->CtrlKey = this->Interactor->GetControlKey(); + this->KeySym = this->Interactor->GetKeySym(); + this->Char = this->Interactor->GetKeyCode(); + + this->InvokeEvent(vtkCommand::KeyReleaseEvent,NULL); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnChar() +{ + // otherwise pass the OnChar to the vtkInteractorStyle. + if (this->HasObserver(vtkCommand::CharEvent)) + { + this->ShiftKey = this->Interactor->GetShiftKey(); + this->CtrlKey = this->Interactor->GetControlKey(); + this->Char = this->Interactor->GetKeyCode(); + + this->InvokeEvent(vtkCommand::CharEvent,NULL); + } + else + { + this->vtkInteractorStyle::OnChar(); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnRightButtonDown() +{ + this->Button = 3; + + if (this->HasObserver(vtkCommand::RightButtonPressEvent)) + { + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->CtrlKey = this->Interactor->GetControlKey(); + this->ShiftKey = this->Interactor->GetShiftKey(); + this->LastPos[0] = x; + this->LastPos[1] = y; + this->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL); + this->OldPos[0] = x; + this->OldPos[1] = y; + } + else + { + this->vtkInteractorStyle::OnRightButtonDown(); + } +} +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnRightButtonUp() +{ + if (this->HasObserver(vtkCommand::RightButtonReleaseEvent)) + { + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->CtrlKey = this->Interactor->GetControlKey(); + this->ShiftKey = this->Interactor->GetShiftKey(); + this->LastPos[0] = x; + this->LastPos[1] = y; + this->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL); + this->OldPos[0] = x; + this->OldPos[1] = y; + } + else + { + this->vtkInteractorStyle::OnRightButtonUp(); + } + + if (this->Button == 3) + { + this->Button = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnMiddleButtonDown() +{ + this->Button = 2; + + if (this->HasObserver(vtkCommand::MiddleButtonPressEvent)) + { + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->CtrlKey = this->Interactor->GetControlKey(); + this->ShiftKey = this->Interactor->GetShiftKey(); + this->LastPos[0] = x; + this->LastPos[1] = y; + this->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL); + this->OldPos[0] = x; + this->OldPos[1] = y; + } + else + { + this->vtkInteractorStyle::OnMiddleButtonDown(); + } +} +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnMiddleButtonUp() +{ + if (this->HasObserver(vtkCommand::MiddleButtonReleaseEvent)) + { + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->CtrlKey = this->Interactor->GetControlKey(); + this->ShiftKey = this->Interactor->GetShiftKey(); + this->LastPos[0] = x; + this->LastPos[1] = y; + this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL); + this->OldPos[0] = x; + this->OldPos[1] = y; + } + else + { + this->vtkInteractorStyle::OnMiddleButtonUp(); + } + + if (this->Button == 2) + { + this->Button = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnLeftButtonDown() +{ + this->Button = 1; + + if (this->HasObserver(vtkCommand::LeftButtonPressEvent)) + { + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->CtrlKey = this->Interactor->GetControlKey(); + this->ShiftKey = this->Interactor->GetShiftKey(); + this->LastPos[0] = x; + this->LastPos[1] = y; + this->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); + this->OldPos[0] = x; + this->OldPos[1] = y; + } + else + { + this->vtkInteractorStyle::OnLeftButtonDown(); + } +} +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnLeftButtonUp() +{ + if (this->HasObserver(vtkCommand::LeftButtonReleaseEvent)) + { + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->CtrlKey = this->Interactor->GetControlKey(); + this->ShiftKey = this->Interactor->GetShiftKey(); + this->LastPos[0] = x; + this->LastPos[1] = y; + this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL); + this->OldPos[0] = x; + this->OldPos[1] = y; + } + else + { + this->vtkInteractorStyle::OnLeftButtonUp(); + } + + if (this->Button == 1) + { + this->Button = 0; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnMouseMove() +{ + this->vtkInteractorStyle::OnMouseMove(); + + int x = this->Interactor->GetEventPosition()[0]; + int y = this->Interactor->GetEventPosition()[1]; + this->LastPos[0] = x; + this->LastPos[1] = y; + this->ShiftKey = this->Interactor->GetShiftKey(); + this->CtrlKey = this->Interactor->GetControlKey(); + + if (this->HasObserver(vtkCommand::MouseMoveEvent)) + { + this->InvokeEvent(vtkCommand::MouseMoveEvent,NULL); + this->OldPos[0] = x; + this->OldPos[1] = y; + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnExpose() +{ + if (this->HasObserver(vtkCommand::ExposeEvent)) + { + this->InvokeEvent(vtkCommand::ExposeEvent,NULL); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnConfigure() +{ + if (this->HasObserver(vtkCommand::ConfigureEvent)) + { + this->InvokeEvent(vtkCommand::ConfigureEvent,NULL); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnEnter() +{ + if (this->HasObserver(vtkCommand::EnterEvent)) + { + this->LastPos[0] = this->Interactor->GetEventPosition()[0]; + this->LastPos[1] = this->Interactor->GetEventPosition()[1]; + this->InvokeEvent(vtkCommand::EnterEvent,NULL); + } +} + +//---------------------------------------------------------------------------- +void vtkInteractorStyleUser::OnLeave() +{ + if (this->HasObserver(vtkCommand::LeaveEvent)) + { + this->LastPos[0] = this->Interactor->GetEventPosition()[0]; + this->LastPos[1] = this->Interactor->GetEventPosition()[1]; + this->InvokeEvent(vtkCommand::LeaveEvent,NULL); + } +} + diff --git a/Rendering/vtkInteractorStyleUser.h b/Rendering/vtkInteractorStyleUser.h new file mode 100644 index 0000000..3cdb0ad --- /dev/null +++ b/Rendering/vtkInteractorStyleUser.h @@ -0,0 +1,122 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkInteractorStyleUser.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkInteractorStyleUser - provides customizable interaction routines +// +// .SECTION Description +// The most common way to customize user interaction is to write a subclass +// of vtkInteractorStyle: vtkInteractorStyleUser allows you to customize +// the interaction to without subclassing vtkInteractorStyle. This is +// particularly useful for setting up custom interaction modes in +// scripting languages such as Tcl and Python. This class allows you +// to hook into the MouseMove, ButtonPress/Release, KeyPress/Release, +// etc. events. If you want to hook into just a single mouse button, +// but leave the interaction modes for the others unchanged, you +// must use e.g. SetMiddleButtonPressMethod() instead of the more +// general SetButtonPressMethod(). + +#ifndef __vtkInteractorStyleUser_h +#define __vtkInteractorStyleUser_h + +#include "vtkInteractorStyle.h" + +// new motion flag +#define VTKIS_USERINTERACTION 8 + +class VTK_RENDERING_EXPORT vtkInteractorStyleUser : public vtkInteractorStyle +{ +public: + static vtkInteractorStyleUser *New(); + vtkTypeRevisionMacro(vtkInteractorStyleUser,vtkInteractorStyle); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the most recent mouse position during mouse motion. + // In your user interaction method, you must use this to track + // the mouse movement. Do not use GetEventPosition(), which records + // the last position where a mouse button was pressed. + vtkGetVector2Macro(LastPos,int); + + // Description: + // Get the previous mouse position during mouse motion, or after + // a key press. This can be used to calculate the relative + // displacement of the mouse. + vtkGetVector2Macro(OldPos,int); + + // Description: + // Test whether modifiers were held down when mouse button or key + // was pressed + vtkGetMacro(ShiftKey,int); + vtkGetMacro(CtrlKey,int); + + // Description: + // Get the character for a Char event. + vtkGetMacro(Char,int); + + // Description: + // Get the KeySym (in the same format as Tk KeySyms) for a + // KeyPress or KeyRelease method. + vtkGetStringMacro(KeySym); + + // Description: + // Get the mouse button that was last pressed inside the window + // (returns zero when the button is released). + vtkGetMacro(Button,int); + + // Description: + // Generic event bindings + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // Description: + // Keyboard functions + virtual void OnChar(); + virtual void OnKeyPress(); + virtual void OnKeyRelease(); + + // Description: + // These are more esoteric events, but are useful in some cases. + virtual void OnExpose(); + virtual void OnConfigure(); + virtual void OnEnter(); + virtual void OnLeave(); + + virtual void OnTimer(); + +protected: + + vtkInteractorStyleUser(); + ~vtkInteractorStyleUser(); + + int LastPos[2]; + int OldPos[2]; + + int ShiftKey; + int CtrlKey; + int Char; + char *KeySym; + int Button; + +private: + vtkInteractorStyleUser(const vtkInteractorStyleUser&); // Not implemented. + void operator=(const vtkInteractorStyleUser&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkLODActor.cxx b/Rendering/vtkLODActor.cxx new file mode 100644 index 0000000..b999ff4 --- /dev/null +++ b/Rendering/vtkLODActor.cxx @@ -0,0 +1,379 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLODActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLODActor.h" + +#include "vtkMapperCollection.h" +#include "vtkMaskPoints.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineFilter.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTexture.h" +#include "vtkTimerLog.h" + +#include + +vtkCxxRevisionMacro(vtkLODActor, "$Revision: 1.66 $"); +vtkStandardNewMacro(vtkLODActor); + +//---------------------------------------------------------------------------- +vtkLODActor::vtkLODActor() +{ + vtkMatrix4x4 *m; + + // get a hardware dependent actor and mappers + this->Device = vtkActor::New(); + m = vtkMatrix4x4::New(); + this->Device->SetUserMatrix(m); + m->Delete(); + + this->LODMappers = vtkMapperCollection::New(); + // stuff for creating own LODs + this->MaskPoints = NULL; + this->OutlineFilter = NULL; + this->NumberOfCloudPoints = 150; + this->LowMapper = NULL; + this->MediumMapper = NULL; +} + +//---------------------------------------------------------------------------- +vtkLODActor::~vtkLODActor() +{ + this->Device->Delete(); + this->DeleteOwnLODs(); + this->LODMappers->Delete(); +} + + +//---------------------------------------------------------------------------- +void vtkLODActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cloud Points: " << this->NumberOfCloudPoints << endl; + + // how should we print out the LODMappers? + os << indent << "Number Of LOD Mappers: " + << this->LODMappers->GetNumberOfItems() << endl; +} + + +//---------------------------------------------------------------------------- +void vtkLODActor::Render(vtkRenderer *ren, vtkMapper *vtkNotUsed(m)) +{ + float myTime, bestTime, tempTime; + vtkMatrix4x4 *matrix; + vtkMapper *mapper, *bestMapper; + + if (this->Mapper == NULL) + { + vtkErrorMacro("No mapper for actor."); + return; + } + + // first time through create lods if non have been added + if (this->LODMappers->GetNumberOfItems() == 0) + { + this->CreateOwnLODs(); + } + + // If the actor has changed or the primary mapper has changed ... + // Is this the correct test? + if (this->MediumMapper) + { + if (this->GetMTime() > this->BuildTime || + this->Mapper->GetMTime() > this->BuildTime) + { + this->UpdateOwnLODs(); + } + } + + // figure out how much time we have to render + myTime = this->AllocatedRenderTime; + + // Figure out which resolution to use + // none is a valid resolution. Do we want to have a lowest: + // bbox, single point, ... + // There is no order to the list, so it is assumed that mappers that take + // longer to render are better quality. + // Timings might become out of date, but we rely on + + bestMapper = this->Mapper; + bestTime = bestMapper->GetTimeToDraw(); + if (bestTime > myTime) + { + vtkCollectionSimpleIterator mit; + this->LODMappers->InitTraversal(mit); + while ((mapper = this->LODMappers->GetNextMapper(mit)) != NULL && + bestTime != 0.0) + { + tempTime = mapper->GetTimeToDraw(); + + // If the LOD has never been rendered, select it! + if (tempTime == 0.0) + { + bestMapper = mapper; + bestTime = 0.0; + } + else + { + if (bestTime > myTime && tempTime < bestTime) + { + bestMapper = mapper; + bestTime = tempTime; + } + if (tempTime > bestTime && tempTime < myTime) + { + bestMapper = mapper; + bestTime = tempTime; + } + } + } + } + + // render the property + if (!this->Property) + { + // force creation of a property + this->GetProperty(); + } + this->Property->Render(this, ren); + if (this->BackfaceProperty) + { + this->BackfaceProperty->BackfaceRender(this, ren); + this->Device->SetBackfaceProperty(this->BackfaceProperty); + } + this->Device->SetProperty(this->Property); + + + // render the texture + if (this->Texture) + { + this->Texture->Render(ren); + } + + // make sure the device has the same matrix + matrix = this->Device->GetUserMatrix(); + this->GetMatrix(matrix); + + // Store information on time it takes to render. + // We might want to estimate time from the number of polygons in mapper. + this->Device->Render(ren,bestMapper); + this->EstimatedRenderTime = bestMapper->GetTimeToDraw(); +} + +int vtkLODActor::RenderOpaqueGeometry(vtkViewport *vp) +{ + int renderedSomething = 0; + vtkRenderer* ren = static_cast(vp); + + if ( ! this->Mapper ) + { + return 0; + } + + // make sure we have a property + if (!this->Property) + { + // force creation of a property + this->GetProperty(); + } + + // is this actor opaque ? + if (this->GetIsOpaque()) + { + this->Property->Render(this, ren); + + // render the backface property + if (this->BackfaceProperty) + { + this->BackfaceProperty->BackfaceRender(this, ren); + } + + // render the texture + if (this->Texture) + { + this->Texture->Render(ren); + } + this->Render(ren,this->Mapper); + + renderedSomething = 1; + } + + return renderedSomething; +} + +void vtkLODActor::ReleaseGraphicsResources(vtkWindow *renWin) +{ + vtkMapper *mapper; + + vtkActor::ReleaseGraphicsResources(renWin); + + // broadcast the message down to the individual LOD mappers + vtkCollectionSimpleIterator mit; + for ( this->LODMappers->InitTraversal(mit); + (mapper = this->LODMappers->GetNextMapper(mit)); ) + { + mapper->ReleaseGraphicsResources(renWin); + } +} + + +//---------------------------------------------------------------------------- +// does not matter if mapper is in mapper collection. +void vtkLODActor::AddLODMapper(vtkMapper *mapper) +{ + if (this->MediumMapper) + { + this->DeleteOwnLODs(); + } + + if (this->Mapper == NULL) + { + this->SetMapper(mapper); + } + + this->LODMappers->AddItem(mapper); +} + + +//---------------------------------------------------------------------------- +// Can only be used if no LOD mappers have been added. +// Maybe we should remove this exculsive feature. +void vtkLODActor::CreateOwnLODs() +{ + if (this->MediumMapper) + { + return; + } + + if ( this->Mapper == NULL) + { + vtkErrorMacro("Cannot create LODs with out a mapper."); + return; + } + + // There are ways of getting arround this limitation ... + if ( this->LODMappers->GetNumberOfItems() > 0 ) + { + vtkErrorMacro(<< + "Cannot generate LOD mappers when some have been added already"); + return; + } + + // create filters and mappers + this->MaskPoints = vtkMaskPoints::New(); + this->MaskPoints->RandomModeOn(); + this->MaskPoints->GenerateVerticesOn(); + this->MediumMapper = vtkPolyDataMapper::New(); + + this->OutlineFilter = vtkOutlineFilter::New(); + this->LowMapper = vtkPolyDataMapper::New(); + + this->LODMappers->AddItem(this->MediumMapper); + this->LODMappers->AddItem(this->LowMapper); + + this->UpdateOwnLODs(); +} + + +//---------------------------------------------------------------------------- +void vtkLODActor::UpdateOwnLODs() +{ + if ( this->Mapper == NULL) + { + vtkErrorMacro("Cannot create LODs with out a mapper."); + return; + } + + if (this->MediumMapper == NULL) + { + this->CreateOwnLODs(); + if (this->MediumMapper == NULL) + { // could not create the LODs + return; + } + } + + // connect the filters to the mapper, and set parameters + this->MaskPoints->SetInput(this->Mapper->GetInput()); + this->MaskPoints->SetMaximumNumberOfPoints(this->NumberOfCloudPoints); + this->OutlineFilter->SetInput(this->Mapper->GetInput()); + + // copy all parameters including LUTs, scalar range, etc. + this->MediumMapper->ShallowCopy(this->Mapper); + this->MediumMapper->SetInput(this->MaskPoints->GetOutput()); + this->LowMapper->ShallowCopy(this->Mapper); + this->LowMapper->ScalarVisibilityOff(); + this->LowMapper->SetInput(this->OutlineFilter->GetOutput()); + + this->BuildTime.Modified(); +} + + +//---------------------------------------------------------------------------- +// Deletes Mappers and filters created by this object. +// (number two and three) +void vtkLODActor::DeleteOwnLODs() +{ + if (this->MediumMapper == NULL) + { + return; + } + + // remove the mappers from the LOD collection + this->LODMappers->RemoveItem(this->LowMapper); + this->LODMappers->RemoveItem(this->MediumMapper); + + // delete the filters used to create the LODs ... + // The NULL check should not be necessary, but for sanity ... + this->MaskPoints->Delete(); + this->MaskPoints = NULL; + this->OutlineFilter->Delete(); + this->OutlineFilter = NULL; + this->LowMapper->Delete(); + this->LowMapper = NULL; + this->MediumMapper->Delete(); + this->MediumMapper = NULL; +} + +//---------------------------------------------------------------------------- +void vtkLODActor::Modified() +{ + this->Device->Modified(); + this->vtkActor::Modified(); +} + +void vtkLODActor::ShallowCopy(vtkProp *prop) +{ + vtkLODActor *a = vtkLODActor::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetNumberOfCloudPoints(a->GetNumberOfCloudPoints()); + vtkMapperCollection *c = a->GetLODMappers(); + vtkMapper *map; + vtkCollectionSimpleIterator mit; + for ( c->InitTraversal(mit); (map=c->GetNextMapper(mit)); ) + { + this->AddLODMapper(map); + } + } + + // Now do superclass + this->vtkActor::ShallowCopy(prop); +} diff --git a/Rendering/vtkLODActor.h b/Rendering/vtkLODActor.h new file mode 100644 index 0000000..0a87f3b --- /dev/null +++ b/Rendering/vtkLODActor.h @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLODActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLODActor - an actor that supports multiple levels of detail +// .SECTION Description +// vtkLODActor is an actor that stores multiple levels of detail (LOD) and +// can automatically switch between them. It selects which level of detail to +// use based on how much time it has been allocated to render. Currently a +// very simple method of TotalTime/NumberOfActors is used. (In the future +// this should be modified to dynamically allocate the rendering time between +// different actors based on their needs.) +// +// There are three levels of detail by default. The top level is just the +// normal data. The lowest level of detail is a simple bounding box outline +// of the actor. The middle level of detail is a point cloud of a fixed +// number of points that have been randomly sampled from the mapper's input +// data. Point attributes are copied over to the point cloud. These two +// lower levels of detail are accomplished by creating instances of a +// vtkOutlineFilter (low-res) and vtkMaskPoints (medium-res). Additional +// levels of detail can be add using the AddLODMapper() method. +// +// To control the frame rate, you typically set the vtkRenderWindowInteractor +// DesiredUpdateRate and StillUpdateRate. This then will cause vtkLODActor +// to adjust its LOD to fulfill the requested update rate. +// +// For greater control on levels of detail, see also vtkLODProp3D. That +// class allows arbitrary definition of each LOD. + +// .SECTION Caveats +// If you provide your own mappers, you are responsible for setting its +// ivars correctly, such as ScalarRange, LookupTable, and so on. +// +// On some systems the point cloud rendering (the default, medium level of +// detail) can result in points so small that they can hardly be seen. In +// this case, use the GetProperty()->SetPointSize() method to increase the +// rendered size of the points. + +// .SECTION see also +// vtkActor vtkRenderer vtkLODProp3D + +#ifndef __vtkLODActor_h +#define __vtkLODActor_h + +#include "vtkActor.h" + +class vtkMapper; +class vtkMapperCollection; +class vtkMaskPoints; +class vtkOutlineFilter; +class vtkPolyDataMapper; +class vtkRenderer; +class vtkViewport; +class vtkWindow; + +class VTK_RENDERING_EXPORT vtkLODActor : public vtkActor +{ +public: + vtkTypeRevisionMacro(vtkLODActor,vtkActor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates a vtkLODActor with the following defaults: origin(0,0,0) + // position=(0,0,0) scale=(1,1,1) visibility=1 pickable=1 dragable=1 + // orientation=(0,0,0). NumberOfCloudPoints is set to 150. + static vtkLODActor *New(); + + // Description: + // This causes the actor to be rendered. It, in turn, will render the actor's + // property and then mapper. + virtual void Render(vtkRenderer *, vtkMapper *); + + // Description: + // This method is used internally by the rendering process. We overide + // the superclass method to properly set the estimated render time. + int RenderOpaqueGeometry(vtkViewport *viewport); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Add another level of detail. They do not have to be in any order + // of complexity. + void AddLODMapper(vtkMapper *mapper); + + // Description: + // Set/Get the number of random points for the point cloud. + vtkGetMacro(NumberOfCloudPoints,int); + vtkSetMacro(NumberOfCloudPoints,int); + + // Description: + // All the mappers for different LODs are stored here. + // The order is not important. + vtkGetObjectMacro(LODMappers, vtkMapperCollection); + + // Description: + // When this objects gets modified, this method also modifies the object. + void Modified(); + + // Description: + // Shallow copy of an LOD actor. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + +protected: + vtkLODActor(); + ~vtkLODActor(); + + vtkActor *Device; + vtkMapperCollection *LODMappers; + + // stuff for creating our own LOD mappers + vtkMaskPoints *MaskPoints; + vtkOutlineFilter *OutlineFilter; + vtkTimeStamp BuildTime; + int NumberOfCloudPoints; + vtkPolyDataMapper *LowMapper; + vtkPolyDataMapper *MediumMapper; + + virtual void CreateOwnLODs(); + virtual void UpdateOwnLODs(); + virtual void DeleteOwnLODs(); + +private: + vtkLODActor(const vtkLODActor&); // Not implemented. + void operator=(const vtkLODActor&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkLODProp3D.cxx b/Rendering/vtkLODProp3D.cxx new file mode 100644 index 0000000..b03f11b --- /dev/null +++ b/Rendering/vtkLODProp3D.cxx @@ -0,0 +1,1148 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLODProp3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLODProp3D.h" + +#include "vtkActor.h" +#include "vtkCommand.h" +#include "vtkMapper.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPropCollection.h" +#include "vtkVolume.h" +#include "vtkAbstractVolumeMapper.h" +#include "vtkLinearTransform.h" + +#include + +vtkCxxRevisionMacro(vtkLODProp3D, "$Revision: 1.43 $"); +vtkStandardNewMacro(vtkLODProp3D); + +#define VTK_INDEX_NOT_IN_USE -1 + +#define VTK_INVALID_LOD_INDEX -2 + +#define VTK_LOD_ACTOR_TYPE 1 +#define VTK_LOD_VOLUME_TYPE 2 + +class vtkLODProp3DCallback : public vtkCommand +{ +public: + // generic new method + static vtkLODProp3DCallback *New() + { return new vtkLODProp3DCallback; } + + // the execute + virtual void Execute(vtkObject *caller, + unsigned long event, void* vtkNotUsed(v)) + { + vtkProp *po = vtkProp::SafeDownCast(caller); + if (event == vtkCommand::PickEvent && po) + { + this->Self->InvokeEvent(vtkCommand::PickEvent,NULL); + } + } + + // some ivars that should be set + vtkLODProp3D *Self; +}; + + +// Construct a new vtkLODProp3D. Automatic LOD selection is on, there are +// no LODs. +vtkLODProp3D::vtkLODProp3D() +{ + this->NumberOfEntries = 0; + this->NumberOfLODs = 0; + this->LODs = NULL; + this->CurrentIndex = 1000; + this->AutomaticLODSelection = 1; + this->SelectedLODID = 1000; + this->SelectedLODIndex = -1; + this->SelectedPickLODID = 1000; + this->AutomaticPickLODSelection = 1; + this->PickCallback = vtkLODProp3DCallback::New(); + this->PickCallback->Self = this; +} + +// Destruct the vtkLODProp3D. Delete the vtkProp3Ds that were created +// for the LODs. Delete the array of LODs. +vtkLODProp3D::~vtkLODProp3D() +{ + int i; + + // Delete the vtkProp3D objects that were created + for ( i = 0; i < this->NumberOfEntries; i++ ) + { + if ( this->LODs[i].ID != VTK_INDEX_NOT_IN_USE ) + { + this->LODs[i].Prop3D->RemoveObserver(this->PickCallback); + this->LODs[i].Prop3D->Delete(); + } + } + + // Delete the array of LODs + if ( this->NumberOfEntries > 0 ) + { + delete [] this->LODs; + } + + this->PickCallback->Delete(); +} + +int vtkLODProp3D::ConvertIDToIndex( int id ) +{ + int index=0; + + while ( index < this->NumberOfEntries && this->LODs[index].ID != id ) + { + index++; + } + if ( index == this->NumberOfEntries ) + { + vtkErrorMacro( << "Could not locate ID: " << id ); + index = VTK_INVALID_LOD_INDEX; + } + + return index; +} + + +// Get the next available entry index +int vtkLODProp3D::GetNextEntryIndex() +{ + int index; + int i; + int amount; + vtkLODProp3DEntry *newLODs; + + // Search for an available index + index = 0; + while ( index < this->NumberOfEntries && this->LODs[index].ID != + VTK_INDEX_NOT_IN_USE ) + { + index++; + } + + // If an available index was not found, we need more entries + if ( index >= this->NumberOfEntries ) + { + // If we have no entries, create 10. If we already have some, create + // twice as many as we already have. + amount = (this->NumberOfEntries)?(this->NumberOfEntries*2):(10); + + // Make the new array + newLODs = new vtkLODProp3DEntry[amount]; + + // Copy the old entries into the new array + for ( i = 0; i < this->NumberOfEntries; i++ ) + { + newLODs[i].Prop3D = this->LODs[i].Prop3D; + newLODs[i].Prop3DType = this->LODs[i].Prop3DType; + newLODs[i].ID = this->LODs[i].ID; + newLODs[i].EstimatedTime = this->LODs[i].EstimatedTime; + newLODs[i].Level = this->LODs[i].Level; + newLODs[i].State = this->LODs[i].State; + } + + // This is the index that we will return - one past the old entries + index = i; + + // Initialize the new entries to default values + for ( ; i < amount; i++ ) + { + newLODs[i].Prop3D = NULL; + newLODs[i].ID = VTK_INDEX_NOT_IN_USE; + } + + // Delete the old array and set the pointer to the new one + delete [] this->LODs; + this->LODs = newLODs; + + // Set the new number of entries that we have + this->NumberOfEntries = amount; + } + return index; +} + +// Get the bounds of this prop. This is just the max bounds of all LODs +double *vtkLODProp3D::GetBounds() +{ + double newBounds[6]; + int i; + int first = 1; + + // Loop through all valid entries + for ( i = 0; i < this->NumberOfEntries; i++ ) + { + if ( this->LODs[i].ID != VTK_INDEX_NOT_IN_USE ) + { + vtkProp3D *p = this->LODs[i].Prop3D; + if ( p->GetMTime() < this->GetMTime() ) + { + p->SetUserMatrix( this->GetMatrix() ); + } + + // Get the bounds of this entry + p->GetBounds(newBounds); + + // If this is the first entry, this is the current bounds + if ( first ) + { + memcpy( this->Bounds, newBounds, 6*sizeof(double) ); + first = 0; + } + // If this is not the first entry, compare these bounds with the + // current bounds expanding the current ones as necessary + else + { + this->Bounds[0] = + (newBounds[0] < this->Bounds[0])?(newBounds[0]):(this->Bounds[0]); + this->Bounds[1] = + (newBounds[1] > this->Bounds[1])?(newBounds[1]):(this->Bounds[1]); + this->Bounds[2] = + (newBounds[2] < this->Bounds[2])?(newBounds[2]):(this->Bounds[2]); + this->Bounds[3] = + (newBounds[3] > this->Bounds[3])?(newBounds[3]):(this->Bounds[3]); + this->Bounds[4] = + (newBounds[4] < this->Bounds[4])?(newBounds[4]):(this->Bounds[4]); + this->Bounds[5] = + (newBounds[5] > this->Bounds[5])?(newBounds[5]):(this->Bounds[5]); + } + } + } + + return this->Bounds; +} + +// Method to remove a LOD based on an ID +void vtkLODProp3D::RemoveLOD( int id ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + this->LODs[index].Prop3D->RemoveObserver(this->PickCallback); + this->LODs[index].Prop3D->Delete(); + this->LODs[index].ID = VTK_INDEX_NOT_IN_USE; + this->NumberOfLODs--; +} + + +// Convenience method to get the ID of the LOD that was used +// during the last render +int vtkLODProp3D::GetLastRenderedLODID( ) +{ + // Check if the selected index is in range + if ( this->SelectedLODIndex < 0 || + this->SelectedLODIndex >= this->NumberOfEntries ) + { + return -1; + } + + // Check if the selected index is valid + if ( this->LODs[this->SelectedLODIndex].ID == VTK_INDEX_NOT_IN_USE ) + { + return -1; + } + + return this->LODs[this->SelectedLODIndex].ID; +} + +// Convenience method to get the estimated render time for a given LOD +// based on an ID (the number returned when the LOD was added) +double vtkLODProp3D::GetLODEstimatedRenderTime( int id ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index != VTK_INVALID_LOD_INDEX ) + { + return this->GetLODIndexEstimatedRenderTime( index ); + } + else + { + return 0.0; + } +} + +double vtkLODProp3D::GetLODIndexEstimatedRenderTime( int index ) +{ + if ( this->SelectedLODIndex < 0 || + this->SelectedLODIndex >= this->NumberOfEntries ) + { + return 0; + } + + return this->LODs[index].EstimatedTime; +} + +// Convenience method to set an actor LOD without a texture, or a +// backface property. Needed from tcl (for example) where null pointers +// are not possible +int vtkLODProp3D::AddLOD( vtkMapper *m, vtkProperty *p, double time ) +{ + return this->AddLOD( m, p, (vtkProperty *) NULL, (vtkTexture *)NULL, time ); +} + +// Convenience method to set an actor LOD without a texture. +// Needed from tcl (for example) where null pointers are not possible +int vtkLODProp3D::AddLOD( vtkMapper *m, vtkProperty *p, + vtkProperty *back, double time ) +{ + return this->AddLOD( m, p, back, (vtkTexture *)NULL, time ); +} + +// Convenience method to set an actor LOD without a backface property. +// Needed from tcl (for example) where null pointers are not possible +int vtkLODProp3D::AddLOD( vtkMapper *m, vtkProperty *p, + vtkTexture *t, double time ) +{ + return this->AddLOD( m, p, (vtkProperty *)NULL, t, time ); +} + +// Convenience method to set an actor LOD without a property. +// Needed from tcl (for example) where null pointers are not possible +int vtkLODProp3D::AddLOD( vtkMapper *m, vtkTexture *t, double time ) +{ + return this->AddLOD( m, (vtkProperty *)NULL, (vtkProperty *)NULL, t, time ); +} + +// Convenience method to set an actor LOD without a texture or a property. +// Needed from tcl (for example) where null pointers are not possible +int vtkLODProp3D::AddLOD( vtkMapper *m, double time ) +{ + return this->AddLOD( m, (vtkProperty *)NULL, (vtkProperty *)NULL, + (vtkTexture *)NULL, time ); +} + +// The real method for adding an actor LOD. +int vtkLODProp3D::AddLOD( vtkMapper *m, vtkProperty *p, + vtkProperty *back, vtkTexture *t, double time ) +{ + int index; + vtkActor *actor; + vtkMatrix4x4 *matrix; + + index = this->GetNextEntryIndex(); + + actor = vtkActor::New(); + matrix = vtkMatrix4x4::New(); + this->GetMatrix( matrix ); + actor->SetUserMatrix( matrix ); + matrix->Delete(); + actor->SetMapper( m ); + if ( p ) + { + actor->SetProperty( p ); + } + + if ( back ) + { + actor->SetBackfaceProperty(back); + } + + if ( t ) + { + actor->SetTexture( t ); + } + + this->LODs[index].Prop3D = (vtkProp3D *)actor; + this->LODs[index].Prop3DType = VTK_LOD_ACTOR_TYPE; + this->LODs[index].ID = this->CurrentIndex++; + this->LODs[index].EstimatedTime = time; + this->LODs[index].Level = 0.0; + this->LODs[index].State = 1; + this->LODs[index].Prop3D->AddObserver(vtkCommand::PickEvent, + this->PickCallback); + this->NumberOfLODs++; + + actor->SetEstimatedRenderTime(time); + + return this->LODs[index].ID; +} + +// Convenience method to set a volume LOD without a property. +// Needed from tcl (for example) where null pointers are not possible +int vtkLODProp3D::AddLOD( vtkAbstractVolumeMapper *m, double time ) +{ + return this->AddLOD( m, (vtkVolumeProperty *)NULL, time ); +} + +// The real method for adding a volume LOD. +int vtkLODProp3D::AddLOD( vtkAbstractVolumeMapper *m, vtkVolumeProperty *p, + double time ) +{ + int index; + vtkVolume *volume; + vtkMatrix4x4 *matrix; + + index = this->GetNextEntryIndex(); + + volume = vtkVolume::New(); + matrix = vtkMatrix4x4::New(); + this->GetMatrix(matrix); + volume->SetUserMatrix( matrix ); + matrix->Delete(); + volume->SetMapper( m ); + if ( p ) + { + volume->SetProperty( p ); + } + + this->LODs[index].Prop3D = (vtkProp3D *)volume; + this->LODs[index].Prop3DType = VTK_LOD_VOLUME_TYPE; + this->LODs[index].ID = this->CurrentIndex++; + this->LODs[index].EstimatedTime = time; + this->LODs[index].Level = 0.0; + this->LODs[index].State = 1; + this->LODs[index].Prop3D->AddObserver(vtkCommand::PickEvent, + this->PickCallback); + this->NumberOfLODs++; + + volume->SetEstimatedRenderTime(time); + + return this->LODs[index].ID; +} + +// Set the mapper for an LOD that is an actor +void vtkLODProp3D::SetLODMapper( int id, vtkMapper *m ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot set an actor mapper on a non-actor!"); + return; + } + + ((vtkActor *)this->LODs[index].Prop3D)->SetMapper( m ); +} + +// Get the mapper for an LOD that is an actor +void vtkLODProp3D::GetLODMapper( int id, vtkMapper **m ) +{ + *m = NULL; + + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot get an actor mapper on a non-actor!"); + + return; + } + + *m = ((vtkActor *)this->LODs[index].Prop3D)->GetMapper(); +} + +// Set the mapper for an LOD that is a volume +void vtkLODProp3D::SetLODMapper( int id, vtkAbstractVolumeMapper *m ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_VOLUME_TYPE ) + { + vtkErrorMacro( << "Error: Cannot set a volume mapper on a non-volume!"); + return; + } + + ((vtkVolume *)this->LODs[index].Prop3D)->SetMapper( m ); +} + +// Get the mapper for an LOD that is an actor +void vtkLODProp3D::GetLODMapper( int id, vtkAbstractVolumeMapper **m ) +{ + *m = NULL; + + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_VOLUME_TYPE ) + { + vtkErrorMacro( << "Error: Cannot get a volume mapper on a non-volume!"); + return; + } + + *m = ((vtkVolume *)this->LODs[index].Prop3D)->GetMapper(); +} + +// Get the mapper for an LOD that is an AbstractMapper3D +vtkAbstractMapper3D *vtkLODProp3D::GetLODMapper( int id ) +{ + vtkAbstractMapper3D *m = NULL; + + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return m; + } + + if ( this->LODs[index].Prop3DType == VTK_LOD_ACTOR_TYPE ) + { + m = ((vtkActor *)this->LODs[index].Prop3D)->GetMapper(); + } + else if ( this->LODs[index].Prop3DType == VTK_LOD_VOLUME_TYPE ) + { + m = ((vtkVolume *)this->LODs[index].Prop3D)->GetMapper(); + } + + return m; +} + + +// Set the property for an LOD that is an actor +void vtkLODProp3D::SetLODProperty( int id, vtkProperty *p ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot set an actor property on a non-actor!"); + return; + } + + ((vtkActor *)this->LODs[index].Prop3D)->SetProperty( p ); +} + +// Get the property for an LOD that is an actor +void vtkLODProp3D::GetLODProperty( int id, vtkProperty **p ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot get an actor property on a non-actor!"); + return; + } + + *p = ((vtkActor *)this->LODs[index].Prop3D)->GetProperty(); +} + +// Set the property for an LOD that is a volume +void vtkLODProp3D::SetLODProperty( int id, vtkVolumeProperty *p ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_VOLUME_TYPE ) + { + vtkErrorMacro( << "Error: Cannot set a volume property on a non-volume!"); + return; + } + + ((vtkVolume *)this->LODs[index].Prop3D)->SetProperty( p ); +} + +// Get the property for an LOD that is an actor +void vtkLODProp3D::GetLODProperty( int id, vtkVolumeProperty **p ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_VOLUME_TYPE ) + { + vtkErrorMacro( << "Error: Cannot get a volume property on a non-volume!"); + return; + } + + *p = ((vtkVolume *)this->LODs[index].Prop3D)->GetProperty(); +} + +// Set the texture for an LOD that is an actor +void vtkLODProp3D::SetLODTexture( int id, vtkTexture *t ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot set an actor texture on a non-actor!"); + return; + } + + ((vtkActor *)this->LODs[index].Prop3D)->SetTexture( t ); +} + +// Get the texture for an LOD that is an actor +void vtkLODProp3D::GetLODTexture( int id, vtkTexture **t ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot get an actor texture on a non-actor!"); + return; + } + + *t = ((vtkActor *)this->LODs[index].Prop3D)->GetTexture(); +} + +// Set the backface property for an LOD that is an actor +void vtkLODProp3D::SetLODBackfaceProperty( int id, vtkProperty *t ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot set an actor backface property on a non-actor!"); + return; + } + + ((vtkActor *)this->LODs[index].Prop3D)->SetBackfaceProperty( t ); +} + +// Get the backface property for an LOD that is an actor +void vtkLODProp3D::GetLODBackfaceProperty( int id, vtkProperty **t ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX ) + { + return; + } + + if ( this->LODs[index].Prop3DType != VTK_LOD_ACTOR_TYPE ) + { + vtkErrorMacro( << "Error: Cannot get an actor backface property on a non-actor!"); + return; + } + + *t = ((vtkActor *)this->LODs[index].Prop3D)->GetBackfaceProperty(); +} + +void vtkLODProp3D::EnableLOD( int id ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX || index == VTK_INDEX_NOT_IN_USE ) + { + return; + } + + this->LODs[index].State = 1; +} + +void vtkLODProp3D::DisableLOD( int id ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX || index == VTK_INDEX_NOT_IN_USE ) + { + return; + } + + this->LODs[index].State = 0; +} + +int vtkLODProp3D::IsLODEnabled( int id ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX || index == VTK_INDEX_NOT_IN_USE ) + { + return 0; + } + + return this->LODs[index].State; +} + +void vtkLODProp3D::SetLODLevel( int id, double level ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX || index == VTK_INDEX_NOT_IN_USE ) + { + return; + } + + this->LODs[index].Level = level; +} + +double vtkLODProp3D::GetLODLevel( int id ) +{ + int index = this->ConvertIDToIndex( id ); + + if ( index == VTK_INVALID_LOD_INDEX || index == VTK_INDEX_NOT_IN_USE ) + { + return -1; + } + + return this->LODs[index].Level; +} + +double vtkLODProp3D::GetLODIndexLevel( int index ) +{ + + if ( index == VTK_INVALID_LOD_INDEX || index == VTK_INDEX_NOT_IN_USE ) + { + return -1; + } + + return this->LODs[index].Level; +} + +// Release any graphics resources that any of the LODs might be using +// for a particular window (such as display lists). +void vtkLODProp3D::ReleaseGraphicsResources(vtkWindow *w) +{ + int i; + + // Loop through all LODs and pass this message along + for ( i = 0; i < this->NumberOfEntries; i++ ) + { + if ( this->LODs[i].ID != VTK_INDEX_NOT_IN_USE ) + { + this->LODs[i].Prop3D->ReleaseGraphicsResources( w ); + } + } +} + +// Standard render method - render any opaque geometry in the selected LOD +int vtkLODProp3D::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int retval; + + // Check if the selected index is in range + if ( this->SelectedLODIndex < 0 || + this->SelectedLODIndex >= this->NumberOfEntries ) + { + vtkErrorMacro( << "Index out of range!" ); + return 0; + } + + // Check if the selected index is valid + if ( this->LODs[this->SelectedLODIndex].ID == VTK_INDEX_NOT_IN_USE ) + { + vtkErrorMacro( << "Index not valid!" ); + return 0; + } + + // Actually do the rendering + retval = + this->LODs[this->SelectedLODIndex].Prop3D->RenderOpaqueGeometry(viewport); + + this->EstimatedRenderTime += + this->LODs[this->SelectedLODIndex].Prop3D->GetEstimatedRenderTime(); + + return retval; +} + +// Standard render method - render any translucent geometry in the selected LOD +int vtkLODProp3D::RenderTranslucentGeometry(vtkViewport *viewport) +{ + int retval; + + // Check if the selected index is in range + if ( this->SelectedLODIndex < 0 || + this->SelectedLODIndex >= this->NumberOfEntries ) + { + vtkErrorMacro( << "Index out of range!" ); + return 0; + } + + // Check if the selected index is valid + if ( this->LODs[this->SelectedLODIndex].ID == VTK_INDEX_NOT_IN_USE ) + { + vtkErrorMacro( << "Index not valid!" ); + return 0; + } + + // Actually do the rendering + retval = this->LODs[this->SelectedLODIndex].Prop3D-> + RenderTranslucentGeometry(viewport); + + this->EstimatedRenderTime += + this->LODs[this->SelectedLODIndex].Prop3D->GetEstimatedRenderTime(); + + return retval; +} + + +// Override the method from vtkProp - add to both this prop and the prop of +// the selected LOD +void vtkLODProp3D::AddEstimatedRenderTime( double t, vtkViewport *vp ) +{ + // Add to this prop's estimated render time + this->EstimatedRenderTime += t; + + // Check if the selected index is in range + if ( this->SelectedLODIndex < 0 || + this->SelectedLODIndex >= this->NumberOfEntries ) + { + vtkErrorMacro( << "Index out of range!" ); + return; + } + + // Check if the selected index is valid + if ( this->LODs[this->SelectedLODIndex].ID == VTK_INDEX_NOT_IN_USE ) + { + vtkErrorMacro( << "Index not valid!" ); + return; + } + + // Now that error checking is done, add to the estimated render time + // of the selected LOD + this->LODs[this->SelectedLODIndex].Prop3D->AddEstimatedRenderTime(t, vp); +} + +void vtkLODProp3D::RestoreEstimatedRenderTime() +{ + // restore the EstimatedTime of the last LOD to be rendered + if ( this->SelectedLODIndex >= 0 && + this->SelectedLODIndex < this->NumberOfEntries ) + { + this->LODs[this->SelectedLODIndex].Prop3D->RestoreEstimatedRenderTime(); + } +} + +// Set the allocated render time - this is where the decision is made +// as to which LOD to select +void vtkLODProp3D::SetAllocatedRenderTime( double t, vtkViewport *vp ) +{ + int i; + int index = -1; + double bestTime; + double bestLevel = 0; + double targetTime; + double estimatedTime; + double newTime; + + // update the EstimatedTime of the last LOD to be rendered + if ( this->SelectedLODIndex >= 0 && + this->SelectedLODIndex < this->NumberOfEntries && + this->LODs[this->SelectedLODIndex].ID != VTK_INDEX_NOT_IN_USE ) + { + // For stability, blend in the new time - 25% old + 75% new + newTime = + this->LODs[this->SelectedLODIndex].Prop3D->GetEstimatedRenderTime(vp); + this->LODs[this->SelectedLODIndex].EstimatedTime = + 0.25 * this->LODs[this->SelectedLODIndex].EstimatedTime + + 0.75 * newTime; + } + + this->SavedEstimatedRenderTime = this->EstimatedRenderTime; + + if ( this->AutomaticLODSelection ) + { + bestTime = -1.0; + + targetTime = t; + + for ( i = 0; i < this->NumberOfEntries; i++ ) + { + if ( this->LODs[i].ID != VTK_INDEX_NOT_IN_USE && + this->LODs[i].State == 1 ) + { + // Gather some information + estimatedTime = this->GetLODIndexEstimatedRenderTime(i); + + // If we've never rendered this LOD and we have no info on it, + // then try it out + if ( estimatedTime == 0.0 ) + { + index = i; + bestTime = 0.0; + bestLevel = this->GetLODIndexLevel(i); + break; + } + + // If we do have at least a guess as to the render time, and + // this seems like the best we have so far, pick it. + // It is the best we have if + // + // 1) our estimated time is less than what we are looking for, + // but greater than any we have selected so far. + // + // 2) we have not selected anything else yet + // (regardless of what the estimated time is) + // + // 3) it is less than the time of the currently selected LOD + // if that LOD's time is greater than the time we are targeting. + // + if ( estimatedTime > 0.0 && + ( ( estimatedTime > bestTime && estimatedTime < targetTime ) || + ( bestTime == -1.0 ) || + ( estimatedTime < bestTime && bestTime > targetTime ) ) ) + { + index = i; + bestTime = estimatedTime; + bestLevel = this->GetLODIndexLevel(i); + } + } + } + + // If we aren't trying some level for the first time with 0.0 bestTime, + // make sure there isn't a LOD that can be rendered faster and has a + // higher level + double level; + if ( bestTime != 0.0 ) + { + for ( i = 0; i < this->NumberOfEntries; i++ ) + { + if ( this->LODs[i].ID != VTK_INDEX_NOT_IN_USE && + this->LODs[i].State == 1 ) + { + // Gather some information + estimatedTime = this->GetLODIndexEstimatedRenderTime(i); + level = this->GetLODIndexLevel(i); + + // Update the index and the level, but not the time. This is + // so that we find the best level that can be rendered + // faster than the LOD selected above. + if ( estimatedTime <= bestTime && level < bestLevel ) + { + index = i; + bestLevel = level; + } + } + } + } + } + else + { + index = 0; + while ( index < this->NumberOfEntries && this->LODs[index].ID != + this->SelectedLODID ) + { + index++; + } + if ( index == this->NumberOfEntries ) + { + vtkErrorMacro( << "Could not render selected LOD ID: " << + this->SelectedLODID ); + index = 0; + while ( index < this->NumberOfEntries && this->LODs[index].ID != + VTK_INDEX_NOT_IN_USE ) + { + index++; + } + } + + } + + this->SelectedLODIndex = index; + this->LODs[this->SelectedLODIndex].Prop3D->SetAllocatedRenderTime( t, vp ); + this->EstimatedRenderTime = 0.0; + this->AllocatedRenderTime = t; + + // Push the matrix down into the selected LOD + vtkProp3D *p = this->LODs[this->SelectedLODIndex].Prop3D; + // Getting our matrix here triggers a ComputeMatrix, if necessary, + // which updates our MatrixMTime + vtkMatrix4x4 *mat = this->GetMatrix(); + if ( p->GetUserTransformMatrixMTime() < this->MatrixMTime ) + { + p->SetUserMatrix(mat) ; + } + +} + + +void vtkLODProp3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of LODs: " << this->NumberOfLODs << endl; + + os << indent << "Selected LOD ID: " << this->SelectedLODID << endl; + + os << indent << "AutomaticLODSelection: " + << (this->AutomaticLODSelection ? "On\n" : "Off\n"); + + os << indent << "AutomaticPickLODSelection: " + << (this->AutomaticPickLODSelection ? "On\n" : "Off\n"); + + os << indent << "SelectedPickLODID: " << this->SelectedPickLODID << endl; + + os << indent << "CurrentIndex: " << this->CurrentIndex << endl; +} + +void vtkLODProp3D::GetActors(vtkPropCollection *ac) +{ + vtkDebugMacro(<< "vtkLODProp3D::GetActors"); + int index; + int lodID; + + lodID = this->GetPickLODID(); + index = this->ConvertIDToIndex(lodID); + + if (index == VTK_INVALID_LOD_INDEX) + { + return; + } + + if (! this->LODs[index].Prop3D->IsA("vtkVolume")) + { + ac->AddItem(this->LODs[index].Prop3D); + } +} + +int vtkLODProp3D::GetAutomaticPickPropIndex() +{ + double bestTime = -1.0; + int index = 0; + double targetTime = 0; + double estimatedTime; + + for (int i = 0; i < this->NumberOfEntries; i++ ) + { + if ( this->LODs[i].ID != VTK_INDEX_NOT_IN_USE ) + { + // Gather some information + estimatedTime = this->GetLODIndexEstimatedRenderTime(i); + + // If we've never rendered this LOD and we have no info on it, + // then try it out + if ( estimatedTime == 0.0 ) + { + index = i; + break; + } + + // If we do have at least a guess as to the render time, and + // this seems like the best we have so far, pick it. + // It is the best we have if + // + // 1) our estimated time is less than what we are looking for, + // but greater than any we have selected so far. + // + // 2) we have not selected anything else yet + // (regardless of what the estimated time is) + // + // 3) it is less than the time of the currently selected LOD + // if that LOD's time is greater than the time we are targeting. + // + if ( estimatedTime > 0.0 && + ( ( estimatedTime > bestTime && estimatedTime < targetTime ) || + ( bestTime == -1.0 ) || + ( estimatedTime < bestTime && bestTime > targetTime ) ) ) + { + index = i; + bestTime = estimatedTime; + } + } + } + return index; +} + + +int vtkLODProp3D::GetPickLODID(void) +{ + int lodID; + + vtkDebugMacro(<< "vtkLODProp3D::GetPickLODID"); + int index; + if (this->AutomaticPickLODSelection) + { + if ( this->SelectedLODIndex < 0 || + this->SelectedLODIndex >= this->NumberOfEntries ) + { + index = this->GetAutomaticPickPropIndex(); + } + else + { + index = this->SelectedLODIndex; + } + lodID = this->LODs[index].ID; + } + else + { + lodID = this->SelectedPickLODID; + } + + return lodID; +} + + +void vtkLODProp3D::SetSelectedPickLODID(int id) +{ + this->SelectedPickLODID = id; + this->Modified(); +} + +void vtkLODProp3D::ShallowCopy(vtkProp *prop) +{ + vtkLODProp3D *a = vtkLODProp3D::SafeDownCast(prop); + + if ( a != NULL ) + { + this->SetAutomaticLODSelection(a->GetAutomaticLODSelection()); + this->SetAutomaticPickLODSelection(a->GetAutomaticPickLODSelection()); + this->SetSelectedLODID(a->GetSelectedLODID()); + this->NumberOfLODs = a->NumberOfLODs; + for(int i=0; iNumberOfLODs; i++) + { + } + } + + // Now do superclass + this->vtkProp3D::ShallowCopy(prop); +} + + diff --git a/Rendering/vtkLODProp3D.h b/Rendering/vtkLODProp3D.h new file mode 100644 index 0000000..08d6d0c --- /dev/null +++ b/Rendering/vtkLODProp3D.h @@ -0,0 +1,269 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLODProp3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLODProp3D - level of detail 3D prop +// .SECTION Description +// vtkLODProp3D is a class to support level of detail rendering for Prop3D. +// Any number of mapper/property/texture items can be added to this object. +// Render time will be measured, and will be used to select a LOD based on +// the AllocatedRenderTime of this Prop3D. Depending on the type of the +// mapper/property, a vtkActor or a vtkVolume will be created behind the +// scenes. + +// .SECTION See Also +// vtkProp3D vtkActor vtkVolume vtkLODActor + +#ifndef __vtkLODProp3D_h +#define __vtkLODProp3D_h + +#include "vtkProp3D.h" + +class vtkRenderer; +class vtkMapper; +class vtkAbstractVolumeMapper; +class vtkAbstractMapper3D; +class vtkProperty; +class vtkVolumeProperty; +class vtkTexture; +class vtkLODProp3DCallback; + +typedef struct +{ + vtkProp3D *Prop3D; + int Prop3DType; + int ID; + double EstimatedTime; + int State; + double Level; +} vtkLODProp3DEntry; + +class VTK_RENDERING_EXPORT vtkLODProp3D : public vtkProp3D +{ +public: + // Description: + // Create an instance of this class. + static vtkLODProp3D *New(); + + vtkTypeRevisionMacro(vtkLODProp3D,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Standard vtkProp method to get 3D bounds of a 3D prop + double *GetBounds(); + void GetBounds(double bounds[6]) { this->vtkProp3D::GetBounds( bounds ); }; + + // Description: + // Add a level of detail with a given mapper, property, backface property, + // texture, and guess of rendering time. The property and texture fields + // can be set to NULL (the other methods are included for script access + // where null variables are not allowed). The time field can be set to 0.0 + // indicating that no initial guess for rendering time is being supplied. + // The returned integer value is an ID that can be used later to delete + // this LOD, or set it as the selected LOD. + int AddLOD( vtkMapper *m, vtkProperty *p, vtkProperty *back, + vtkTexture *t, double time ); + int AddLOD( vtkMapper *m, vtkProperty *p, vtkTexture *t, double time ); + int AddLOD( vtkMapper *m, vtkProperty *p, vtkProperty *back, double time ); + int AddLOD( vtkMapper *m, vtkProperty *p, double time ); + int AddLOD( vtkMapper *m, vtkTexture *t, double time ); + int AddLOD( vtkMapper *m, double time ); + int AddLOD( vtkAbstractVolumeMapper *m, vtkVolumeProperty *p, double time ); + int AddLOD( vtkAbstractVolumeMapper *m, double time ); + + // Description: + // Get the current number of LODs. + vtkGetMacro(NumberOfLODs, int); + + // Description: + // Get the current index, used to determine the ID of the next LOD that is + // added. Useful for guessing what IDs have been used (with NumberOfLODs, + // without depending on the constructor initialization to 1000. + vtkGetMacro(CurrentIndex, int); + + // Description: + // Delete a level of detail given an ID. This is the ID returned by the + // AddLOD method + void RemoveLOD( int id ); + + // Description: + // Methods to set / get the property of an LOD. Since the LOD could be + // a volume or an actor, you have to pass in the pointer to the property + // to get it. The returned property will be NULL if the id is not valid, + // or the property is of the wrong type for the corresponding Prop3D. + void SetLODProperty( int id, vtkProperty *p ); + void GetLODProperty( int id, vtkProperty **p ); + void SetLODProperty( int id, vtkVolumeProperty *p ); + void GetLODProperty( int id, vtkVolumeProperty **p ); + + // Description: + // Methods to set / get the mapper of an LOD. Since the LOD could be + // a volume or an actor, you have to pass in the pointer to the mapper + // to get it. The returned mapper will be NULL if the id is not valid, + // or the mapper is of the wrong type for the corresponding Prop3D. + void SetLODMapper( int id, vtkMapper *m ); + void GetLODMapper( int id, vtkMapper **m ); + void SetLODMapper( int id, vtkAbstractVolumeMapper *m ); + void GetLODMapper( int id, vtkAbstractVolumeMapper **m ); + + // Description: + // Get the LODMapper as an vtkAbstractMapper3D. It is the user's + // respondibility to safe down cast this to a vtkMapper or vtkVolumeMapper + // as appropriate. + vtkAbstractMapper3D *GetLODMapper(int id); + + // Description: + // Methods to set / get the backface property of an LOD. This method is only + // valid for LOD ids that are Actors (not Volumes) + void SetLODBackfaceProperty( int id, vtkProperty *t ); + void GetLODBackfaceProperty( int id, vtkProperty **t ); + + // Description: + // Methods to set / get the texture of an LOD. This method is only + // valid for LOD ids that are Actors (not Volumes) + void SetLODTexture( int id, vtkTexture *t ); + void GetLODTexture( int id, vtkTexture **t ); + + // Description: + // Enable / disable a particular LOD. If it is disabled, it will not + // be used during automatic selection, but can be selected as the + // LOD if automatic LOD selection is off. + void EnableLOD( int id ); + void DisableLOD( int id ); + int IsLODEnabled( int id ); + + // Description: + // Set the level of a particular LOD. When a LOD is selected for + // rendering because it has the largest render time that fits within + // the allocated time, all LOD are then checked to see if any one can + // render faster but has a lower (more resolution/better) level. + // This quantity is a double to ensure that a level can be inserted + // between 2 and 3. + void SetLODLevel( int id, double level ); + double GetLODLevel( int id ); + double GetLODIndexLevel( int index ); + + // Description: + // Access method that can be used to find out the estimated render time + // (the thing used to select an LOD) for a given LOD ID or index. + // Value is returned in seconds. + double GetLODEstimatedRenderTime( int id ); + double GetLODIndexEstimatedRenderTime( int index ); + + // Description: + // Turn on / off automatic selection of LOD. + // This is on by default. If it is off, then the SelectedLODID is + // rendered regardless of rendering time or desired update rate. + vtkSetClampMacro( AutomaticLODSelection, int, 0, 1 ); + vtkGetMacro( AutomaticLODSelection, int ); + vtkBooleanMacro( AutomaticLODSelection, int ); + + // Description: + // Set the id of the LOD that is to be drawn when automatic LOD selection + // is turned off. + vtkSetMacro( SelectedLODID, int ); + vtkGetMacro( SelectedLODID, int ); + + // Description: + // Get the ID of the previously (during the last render) selected LOD index + int GetLastRenderedLODID(); + + // Description: + // Get the ID of the appropriate pick LOD index + int GetPickLODID(void); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. These methods + // are used in that process. + virtual void GetActors(vtkPropCollection *); + + // Description: + // Set the id of the LOD that is to be used for picking when automatic + // LOD pick selection is turned off. + void SetSelectedPickLODID(int id); + vtkGetMacro( SelectedPickLODID, int ); + + // Description: + // Turn on / off automatic selection of picking LOD. + // This is on by default. If it is off, then the SelectedLODID is + // rendered regardless of rendering time or desired update rate. + vtkSetClampMacro( AutomaticPickLODSelection, int, 0, 1 ); + vtkGetMacro( AutomaticPickLODSelection, int ); + vtkBooleanMacro( AutomaticPickLODSelection, int ); + + // Description: + // Shallow copy of this vtkLODProp3D. + void ShallowCopy(vtkProp *prop); + +//BTX + + // Description: + // Support the standard render methods. + int RenderOpaqueGeometry(vtkViewport *viewport); + int RenderTranslucentGeometry(vtkViewport *viewport); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Used by the culler / renderer to set the allocated render time for this + // prop. This is based on the desired update rate, and possibly some other + // properties such as potential screen coverage of this prop. + void SetAllocatedRenderTime( double t, vtkViewport *vp ); + + // Description: + // Used when the render process is aborted to restore the previous + // estimated render time. Overridden here to allow previous time for a + // particular LOD to be restored - otherwise the time for the last rendered + // LOD will be copied into the currently selected LOD. + void RestoreEstimatedRenderTime( ); + + // Description: + // Override method from vtkProp in order to push this call down to the + // selected LOD as well. + virtual void AddEstimatedRenderTime( double t, vtkViewport *vp ); + +//ETX + +protected: + vtkLODProp3D(); + ~vtkLODProp3D(); + + int GetAutomaticPickPropIndex(void); + + vtkLODProp3DEntry *LODs; + int NumberOfEntries; + int NumberOfLODs; + int CurrentIndex; + + int GetNextEntryIndex(); + int ConvertIDToIndex( int id ); + int SelectedLODIndex; + + int AutomaticLODSelection; + int SelectedLODID; + int SelectedPickLODID; + int AutomaticPickLODSelection; + vtkLODProp3DCallback *PickCallback; + +private: + vtkLODProp3D(const vtkLODProp3D&); // Not implemented. + void operator=(const vtkLODProp3D&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkLabeledDataMapper.cxx b/Rendering/vtkLabeledDataMapper.cxx new file mode 100644 index 0000000..5b7bf8a --- /dev/null +++ b/Rendering/vtkLabeledDataMapper.cxx @@ -0,0 +1,389 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLabeledDataMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLabeledDataMapper.h" + +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkActor2D.h" +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" + +vtkCxxRevisionMacro(vtkLabeledDataMapper, "$Revision: 1.40 $"); +vtkStandardNewMacro(vtkLabeledDataMapper); + +vtkCxxSetObjectMacro(vtkLabeledDataMapper,LabelTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Creates a new label mapper + +vtkLabeledDataMapper::vtkLabeledDataMapper() +{ + this->Input = NULL; + this->LabelMode = VTK_LABEL_IDS; + + this->LabelFormat = new char[8]; + strcpy(this->LabelFormat,"%g"); + + this->LabeledComponent = (-1); + this->FieldDataArray = 0; + + this->NumberOfLabels = 0; + this->NumberOfLabelsAllocated = 50; + + this->TextMappers = new vtkTextMapper * [this->NumberOfLabelsAllocated]; + for (int i=0; iNumberOfLabelsAllocated; i++) + { + this->TextMappers[i] = vtkTextMapper::New(); + } + + this->LabelTextProperty = vtkTextProperty::New(); + this->LabelTextProperty->SetFontSize(12); + this->LabelTextProperty->SetBold(1); + this->LabelTextProperty->SetItalic(1); + this->LabelTextProperty->SetShadow(1); + this->LabelTextProperty->SetFontFamilyToArial(); +} + +//---------------------------------------------------------------------------- +vtkLabeledDataMapper::~vtkLabeledDataMapper() +{ + if (this->LabelFormat) + { + delete [] this->LabelFormat; + } + + if (this->TextMappers != NULL ) + { + for (int i=0; i < this->NumberOfLabelsAllocated; i++) + { + this->TextMappers[i]->Delete(); + } + delete [] this->TextMappers; + } + + this->SetLabelTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +void vtkLabeledDataMapper::SetInput(vtkDataSet *input) +{ + if (input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(0, 0); + } +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkDataSet *vtkLabeledDataMapper::GetInput() +{ + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this mapper. +void vtkLabeledDataMapper::ReleaseGraphicsResources(vtkWindow *win) +{ + if (this->TextMappers != NULL ) + { + for (int i=0; i < this->NumberOfLabelsAllocated; i++) + { + this->TextMappers[i]->ReleaseGraphicsResources(win); + } + } +} + +//---------------------------------------------------------------------------- +void vtkLabeledDataMapper::RenderOverlay(vtkViewport *viewport, + vtkActor2D *actor) +{ + int i; + double x[3]; + vtkDataSet *input=this->GetInput(); + + if ( ! input ) + { + vtkErrorMacro(<<"Need input data to render labels"); + return; + } + for (i=0; iNumberOfLabels; i++) + { + input->GetPoint(i,x); + actor->GetPositionCoordinate()->SetCoordinateSystemToWorld(); + actor->GetPositionCoordinate()->SetValue(x); + this->TextMappers[i]->RenderOverlay(viewport, actor); + } +} + +//---------------------------------------------------------------------------- +void vtkLabeledDataMapper::RenderOpaqueGeometry(vtkViewport *viewport, + vtkActor2D *actor) +{ + int i, j, numComp = 0, pointIdLabels, activeComp = 0; + char string[1024], format[1024]; + double val, x[3]; + vtkDataArray *data; + vtkDataSet *input=this->GetInput(); + + if ( ! input ) + { + vtkErrorMacro(<<"Need input data to render labels"); + return; + } + + vtkPointData *pd=input->GetPointData(); + vtkTextProperty *tprop = this->LabelTextProperty; + if (!tprop) + { + vtkErrorMacro(<<"Need text property to render labels"); + return; + } + + input->Update(); + + // Check to see whether we have to rebuild everything + if ( this->GetMTime() > this->BuildTime || + input->GetMTime() > this->BuildTime || + tprop->GetMTime() > this->BuildTime) + { + vtkDebugMacro(<<"Rebuilding labels"); + + // figure out what to label, and if we can label it + pointIdLabels = 0; + data = NULL; + switch (this->LabelMode) + { + case VTK_LABEL_IDS: + pointIdLabels = 1; + break; + case VTK_LABEL_SCALARS: + if ( pd->GetScalars() ) + { + data = pd->GetScalars(); + } + break; + case VTK_LABEL_VECTORS: + if ( pd->GetVectors() ) + { + data = pd->GetVectors(); + } + break; + case VTK_LABEL_NORMALS: + if ( pd->GetNormals() ) + { + data = pd->GetNormals(); + } + break; + case VTK_LABEL_TCOORDS: + if ( pd->GetTCoords() ) + { + data = pd->GetTCoords(); + } + break; + case VTK_LABEL_TENSORS: + if ( pd->GetTensors() ) + { + data = pd->GetTensors(); + } + break; + case VTK_LABEL_FIELD_DATA: + int arrayNum = (this->FieldDataArray < pd->GetNumberOfArrays() ? + this->FieldDataArray : pd->GetNumberOfArrays() - 1); + data = pd->GetArray(arrayNum); + break; + } + + // determine number of components and check input + if ( pointIdLabels ) + { + ; + } + else if ( data ) + { + numComp = data->GetNumberOfComponents(); + activeComp = 0; + if ( this->LabeledComponent >= 0 ) + { + activeComp = (this->LabeledComponent < numComp ? + this->LabeledComponent : numComp - 1); + numComp = 1; + } + } + else + { + vtkErrorMacro(<<"Need input data to render labels"); + return; + } + + this->NumberOfLabels = input->GetNumberOfPoints(); + if ( this->NumberOfLabels > this->NumberOfLabelsAllocated ) + { + // delete old stuff + for (i=0; i < this->NumberOfLabelsAllocated; i++) + { + this->TextMappers[i]->Delete(); + } + delete [] this->TextMappers; + + this->NumberOfLabelsAllocated = this->NumberOfLabels; + this->TextMappers = new vtkTextMapper * [this->NumberOfLabelsAllocated]; + for (i=0; iNumberOfLabelsAllocated; i++) + { + this->TextMappers[i] = vtkTextMapper::New(); + } + }//if we have to allocate new text mappers + + for (i=0; i < this->NumberOfLabels; i++) + { + if ( pointIdLabels ) + { + val = (float)i; + sprintf(string, this->LabelFormat, val); + } + else + { + if ( numComp == 1) + { + if (data->GetDataType() == VTK_CHAR) + { + if (strcmp(this->LabelFormat,"%c") != 0) + { + vtkErrorMacro(<<"Label format must be %c to use with char"); + return; + } + sprintf(string, this->LabelFormat, + (char)data->GetComponent(i, activeComp)); + } + else + { + sprintf(string, this->LabelFormat, + data->GetComponent(i, activeComp)); + } + } + else + { + strcpy(format, "("); strcat(format, this->LabelFormat); + for (j=0; j<(numComp-1); j++) + { + sprintf(string, format, data->GetComponent(i, j)); + strcpy(format,string); strcat(format,", "); + strcat(format, this->LabelFormat); + } + sprintf(string, format, data->GetComponent(i, numComp-1)); + strcat(string, ")"); + } + } + this->TextMappers[i]->SetInput(string); + this->TextMappers[i]->SetTextProperty(tprop); + } + + this->BuildTime.Modified(); + } + + for (i=0; iNumberOfLabels; i++) + { + input->GetPoint(i,x); + actor->GetPositionCoordinate()->SetCoordinateSystemToWorld(); + actor->GetPositionCoordinate()->SetValue(x); + this->TextMappers[i]->RenderOpaqueGeometry(viewport, actor); + } +} + +//---------------------------------------------------------------------------- +int vtkLabeledDataMapper::FillInputPortInformation( + int vtkNotUsed( port ), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkLabeledDataMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Input ) + { + os << indent << "Input: (" << this->Input << ")\n"; + } + else + { + os << indent << "Input: (none)\n"; + } + + if (this->LabelTextProperty) + { + os << indent << "Label Text Property:\n"; + this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Label Text Property: (none)\n"; + } + + os << indent << "Label Mode: "; + if ( this->LabelMode == VTK_LABEL_IDS ) + { + os << "Label Ids\n"; + } + else if ( this->LabelMode == VTK_LABEL_SCALARS ) + { + os << "Label Scalars\n"; + } + else if ( this->LabelMode == VTK_LABEL_VECTORS ) + { + os << "Label Vectors\n"; + } + else if ( this->LabelMode == VTK_LABEL_NORMALS ) + { + os << "Label Normals\n"; + } + else if ( this->LabelMode == VTK_LABEL_TCOORDS ) + { + os << "Label TCoords\n"; + } + else if ( this->LabelMode == VTK_LABEL_TENSORS ) + { + os << "Label Tensors\n"; + } + else + { + os << "Label Field Data\n"; + } + + os << indent << "Label Format: " << this->LabelFormat << "\n"; + + os << indent << "Labeled Component: "; + if ( this->LabeledComponent < 0 ) + { + os << "(All Components)\n"; + } + else + { + os << this->LabeledComponent << "\n"; + } + + os << indent << "Field Data Array: " << this->FieldDataArray << "\n"; +} diff --git a/Rendering/vtkLabeledDataMapper.h b/Rendering/vtkLabeledDataMapper.h new file mode 100644 index 0000000..59efae9 --- /dev/null +++ b/Rendering/vtkLabeledDataMapper.h @@ -0,0 +1,157 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLabeledDataMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLabeledDataMapper - draw text labels at dataset points +// .SECTION Description +// vtkLabeledDataMapper is a mapper that renders text at dataset +// points. Various items can be labeled including point ids, scalars, +// vectors, normals, texture coordinates, tensors, and field data components. +// +// The format with which the label is drawn is specified using a +// printf style format string. The font attributes of the text can +// be set through the vtkTextProperty associated to this mapper. +// +// By default, all the components of multi-component data such as +// vectors, normals, texture coordinates, tensors, and multi-component +// scalars are labeled. However, you can specify a single component if +// you prefer. (Note: the label format specifies the format to use for +// a single component. The label is creating by looping over all components +// and using the label format to render each component.) + +// .SECTION Caveats +// Use this filter in combination with vtkSelectVisiblePoints if you want +// to label only points that are visible. If you want to label cells rather +// than points, use the filter vtkCellCenters to generate points at the +// center of the cells. Also, you can use the class vtkIdFilter to +// generate ids as scalars or field data, which can then be labeled. + +// .SECTION See Also +// vtkMapper2D vtkActor2D vtkTextMapper vtkTextProperty vtkSelectVisiblePoints +// vtkIdFilter vtkCellCenters + +#ifndef __vtkLabeledDataMapper_h +#define __vtkLabeledDataMapper_h + +#include "vtkMapper2D.h" + +class vtkDataSet; +class vtkTextMapper; +class vtkTextProperty; + +#define VTK_LABEL_IDS 0 +#define VTK_LABEL_SCALARS 1 +#define VTK_LABEL_VECTORS 2 +#define VTK_LABEL_NORMALS 3 +#define VTK_LABEL_TCOORDS 4 +#define VTK_LABEL_TENSORS 5 +#define VTK_LABEL_FIELD_DATA 6 + +class VTK_RENDERING_EXPORT vtkLabeledDataMapper : public vtkMapper2D +{ +public: + // Description: + // Instantiate object with %%-#6.3g label format. By default, point ids + // are labeled. + static vtkLabeledDataMapper *New(); + + vtkTypeRevisionMacro(vtkLabeledDataMapper,vtkMapper2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the format with which to print the labels. The format needs + // to change depending on what you're trying to print. For example, if + // you're printing a vector, 3 values are printed, whereas when printing an + // id only one value is printed. See also the ivar LabeledComponent which + // can be used to specify the component to print if you want to only print + // one of several. + vtkSetStringMacro(LabelFormat); + vtkGetStringMacro(LabelFormat); + + // Description: + // Set/Get the component number to label if the data to print has + // more than one component. For example, all the components of + // scalars, vectors, normals, etc. are labeled by default + // (LabeledComponent=(-1)). However, if this ivar is nonnegative, + // then only the one component specified is labeled. + vtkSetMacro(LabeledComponent,int); + vtkGetMacro(LabeledComponent,int); + + // Description: + // Set/Get the field data array to label. This instance variable is + // only applicable if field data is labeled. + vtkSetClampMacro(FieldDataArray,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(FieldDataArray,int); + + // Description: + // Set the input dataset to the mapper. This mapper handles any type of data. + virtual void SetInput(vtkDataSet*); + vtkDataSet *GetInput(); + + // Description: + // Specify which data to plot: scalars, vectors, normals, texture coords, + // tensors, or field data. If the data has more than one component, use + // the method SetLabeledComponent to control which components to plot. + vtkSetMacro(LabelMode, int); + vtkGetMacro(LabelMode, int); + void SetLabelModeToLabelIds() {this->SetLabelMode(VTK_LABEL_IDS);}; + void SetLabelModeToLabelScalars() {this->SetLabelMode(VTK_LABEL_SCALARS);}; + void SetLabelModeToLabelVectors() {this->SetLabelMode(VTK_LABEL_VECTORS);}; + void SetLabelModeToLabelNormals() {this->SetLabelMode(VTK_LABEL_NORMALS);}; + void SetLabelModeToLabelTCoords() {this->SetLabelMode(VTK_LABEL_TCOORDS);}; + void SetLabelModeToLabelTensors() {this->SetLabelMode(VTK_LABEL_TENSORS);}; + void SetLabelModeToLabelFieldData() + {this->SetLabelMode(VTK_LABEL_FIELD_DATA);}; + + // Description: + // Set/Get the text property. + virtual void SetLabelTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(LabelTextProperty,vtkTextProperty); + + // Description: + // Draw the text to the screen at each input point. + void RenderOpaqueGeometry(vtkViewport* viewport, vtkActor2D* actor); + void RenderOverlay(vtkViewport* viewport, vtkActor2D* actor); + + // Description: + // Release any graphics resources that are being consumed by this actor. + virtual void ReleaseGraphicsResources(vtkWindow *); + +protected: + vtkLabeledDataMapper(); + ~vtkLabeledDataMapper(); + + vtkDataSet *Input; + vtkTextProperty *LabelTextProperty; + + char *LabelFormat; + int LabelMode; + int LabeledComponent; + int FieldDataArray; + + vtkTimeStamp BuildTime; + +private: + int NumberOfLabels; + int NumberOfLabelsAllocated; + vtkTextMapper **TextMappers; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkLabeledDataMapper(const vtkLabeledDataMapper&); // Not implemented. + void operator=(const vtkLabeledDataMapper&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkLight.cxx b/Rendering/vtkLight.cxx new file mode 100644 index 0000000..42f9ba0 --- /dev/null +++ b/Rendering/vtkLight.cxx @@ -0,0 +1,330 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLight.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLight.h" + +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkGraphicsFactory.h" + +vtkCxxRevisionMacro(vtkLight, "$Revision: 1.52 $"); + +vtkCxxSetObjectMacro(vtkLight,TransformMatrix,vtkMatrix4x4); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkLight); + +// Create a light with the focal point at the origin and its position +// set to (0,0,1). The lights color is white, intensity=1, and the light +// is turned on. +vtkLight::vtkLight() +{ + this->FocalPoint[0] = 0.0; + this->FocalPoint[1] = 0.0; + this->FocalPoint[2] = 0.0; + + this->Position[0] = 0.0; + this->Position[1] = 0.0; + this->Position[2] = 1.0; + + // GL default. + this->AmbientColor[0] = 0.0; + this->AmbientColor[1] = 0.0; + this->AmbientColor[2] = 0.0; + + this->DiffuseColor[0] = 1.0; + this->DiffuseColor[1] = 1.0; + this->DiffuseColor[2] = 1.0; + + this->SpecularColor[0] = 1.0; + this->SpecularColor[1] = 1.0; + this->SpecularColor[2] = 1.0; + + this->Switch = 1; + + this->Intensity = 1.0; + this->Positional = 0; + this->ConeAngle = 30; + this->AttenuationValues[0] = 1; + this->AttenuationValues[1] = 0; + this->AttenuationValues[2] = 0; + this->Exponent = 1; + + this->LightType = VTK_LIGHT_TYPE_SCENE_LIGHT; + + this->TransformMatrix = (vtkMatrix4x4 *)NULL; +} + +vtkLight::~vtkLight() +{ + if(this->TransformMatrix != NULL) + { + this->TransformMatrix->UnRegister(this); + this->TransformMatrix = NULL; + } +} + +void vtkLight::SetDirectionAngle(double elevation, double azimuth) +{ + elevation *= vtkMath::DegreesToRadians(); + azimuth *= vtkMath::DegreesToRadians(); + + this->SetPosition(cos(elevation)*sin(azimuth), + sin(elevation), + cos(elevation)*cos(azimuth)); + + this->SetFocalPoint(0.0, 0.0, 0.0); + this->SetPositional(0); +} + + +// return the correct type of light +vtkLight *vtkLight::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkLight"); + return (vtkLight*)ret; +} + +// Preserve VTK's old way of setting light color +// which affected only diffuse and specular components. +void vtkLight::SetColor(double R, double G, double B) +{ + this->SetDiffuseColor(R, G, B); + this->SetSpecularColor(R, G, B); +} + +// This method assumes that the SetColor() method was called which sets both +// the specular and diffuse colors to the same value. In the future, we may +// want to change this to compute the composite light color, similar to +// vtkProperty. +double *vtkLight::GetColor() +{ + return this->DiffuseColor; +} + +void vtkLight::GetColor(double rgb[3]) +{ + // May want to change this to compute the composite + // light color, similar to vtkProperty. + rgb[0] = this->DiffuseColor[0]; + rgb[1] = this->DiffuseColor[1]; + rgb[2] = this->DiffuseColor[2]; +} + +int vtkLight::LightTypeIsHeadlight() +{ + return this->LightType == VTK_LIGHT_TYPE_HEADLIGHT; +} + +int vtkLight::LightTypeIsCameraLight() +{ + return this->LightType == VTK_LIGHT_TYPE_CAMERA_LIGHT; +} + +int vtkLight::LightTypeIsSceneLight() +{ + return this->LightType == VTK_LIGHT_TYPE_SCENE_LIGHT; +} + +void vtkLight::GetTransformedPosition(double a[3]) +{ + if(this->TransformMatrix) + { + double f[4]; + f[0] = this->Position[0]; + f[1] = this->Position[1]; + f[2] = this->Position[2]; + f[3] = 1.0; + + this->TransformMatrix->MultiplyPoint(f, f); + + a[0] = f[0]; + a[1] = f[1]; + a[2] = f[2]; + } + else + { + a[0] = this->Position[0]; + a[1] = this->Position[1]; + a[2] = this->Position[2]; + } +} + +void vtkLight::GetTransformedPosition(double &x, double &y, double &z) +{ + double a[3]; + + this->GetTransformedPosition(a); + x = a[0]; + y = a[1]; + z = a[2]; +} + +double *vtkLight::GetTransformedPosition() +{ + this->GetTransformedPosition(this->TransformedPositionReturn); + return this->TransformedPositionReturn; +} + +void vtkLight::GetTransformedFocalPoint(double a[3]) +{ + if(this->TransformMatrix) + { + double f[4]; + f[0] = this->FocalPoint[0]; + f[1] = this->FocalPoint[1]; + f[2] = this->FocalPoint[2]; + f[3] = 1.0; + + this->TransformMatrix->MultiplyPoint(f, f); + + a[0] = f[0]; + a[1] = f[1]; + a[2] = f[2]; + } + else + { + a[0] = this->FocalPoint[0]; + a[1] = this->FocalPoint[1]; + a[2] = this->FocalPoint[2]; + } +} + +void vtkLight::GetTransformedFocalPoint(double &x, double &y, double &z) +{ + double a[3]; + + this->GetTransformedFocalPoint(a); + x = a[0]; + y = a[1]; + z = a[2]; +} + +double *vtkLight::GetTransformedFocalPoint() +{ + this->GetTransformedFocalPoint(this->TransformedFocalPointReturn); + return this->TransformedFocalPointReturn; +} + +void vtkLight::DeepCopy(vtkLight *light) +{ + this->SetFocalPoint(light->GetFocalPoint()); + this->SetPosition(light->GetPosition()); + this->SetIntensity(light->GetIntensity()); + this->SetAmbientColor(light->GetAmbientColor()); + this->SetDiffuseColor(light->GetDiffuseColor()); + this->SetSpecularColor(light->GetSpecularColor()); + this->SetSwitch(light->GetSwitch()); + this->SetPositional(light->GetPositional()); + this->SetExponent(light->GetExponent()); + this->SetConeAngle(light->GetConeAngle()); + this->SetAttenuationValues(light->GetAttenuationValues()); +} + +void vtkLight::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "AttenuationValues: (" << this->AttenuationValues[0] << ", " + << this->AttenuationValues[1] << ", " + << this->AttenuationValues[2] << ")\n"; + os << indent << "AmbientColor: (" << this->AmbientColor[0] << ", " + << this->AmbientColor[1] << ", " << this->AmbientColor[2] << ")\n"; + os << indent << "DiffuseColor: (" << this->DiffuseColor[0] << ", " + << this->DiffuseColor[1] << ", " << this->DiffuseColor[2] << ")\n"; + os << indent << "SpecularColor: (" << this->SpecularColor[0] << ", " + << this->SpecularColor[1] << ", " << this->SpecularColor[2] << ")\n"; + os << indent << "Cone Angle: " << this->ConeAngle << "\n"; + os << indent << "Exponent: " << this->Exponent << "\n"; + os << indent << "Focal Point: (" << this->FocalPoint[0] << ", " + << this->FocalPoint[1] << ", " << this->FocalPoint[2] << ")\n"; + os << indent << "Intensity: " << this->Intensity << "\n"; + os << indent << "Position: (" << this->Position[0] << ", " + << this->Position[1] << ", " << this->Position[2] << ")\n"; + os << indent << "Positional: " << (this->Positional ? "On\n" : "Off\n"); + os << indent << "Switch: " << (this->Switch ? "On\n" : "Off\n"); + + os << indent << "LightType: "; + if (this->LightType == VTK_LIGHT_TYPE_HEADLIGHT) + { + os << "Headlight\n"; + } + else if (this->LightType == VTK_LIGHT_TYPE_CAMERA_LIGHT) + { + os << "CameraLight\n"; + } + else if (this->LightType == VTK_LIGHT_TYPE_SCENE_LIGHT) + { + os << "SceneLight\n"; + } + else + { + os << "(unknown light type)\n"; + } + + os << indent << "TransformMatrix: "; + if(this->TransformMatrix != NULL) + { + os << this->TransformMatrix << "\n"; + } + else + { + os << "(none)\n"; + } +} + +void vtkLight::WriteSelf(ostream& os) +{ + os << this->FocalPoint[0] << " " << this->FocalPoint[1] << " " + << this->FocalPoint[2] << " "; + os << this->Position[0] << " " << this->Position[1] << " " + << this->Position[2] << " "; + os << this->Intensity << " "; + os << this->AmbientColor[0] << " " << this->AmbientColor[1] << " " + << this->AmbientColor[2] << " "; + os << this->DiffuseColor[0] << " " << this->DiffuseColor[1] << " " + << this->DiffuseColor[2] << " "; + os << this->SpecularColor[0] << " " << this->SpecularColor[1] << " " + << this->SpecularColor[2] << " "; + os << this->Switch << " "; + os << this->Switch << " "; + os << this->Positional << " "; + os << this->Exponent << " "; + os << this->ConeAngle << " "; + os << this->AttenuationValues[0] << " " << this->AttenuationValues[1] << " " + << this->AttenuationValues[2] << " "; + // XXX - LightType, TransformMatrix ??? +} + +void vtkLight::ReadSelf(istream& is) +{ + is >> this->FocalPoint[0] >> this->FocalPoint[1] >> this->FocalPoint[2] ; + is >> this->Position[0] >> this->Position[1] >> this->Position[2]; + is >> this->Intensity; + is >> this->AmbientColor[0] >> this->AmbientColor[1] >> this->AmbientColor[2]; + is >> this->DiffuseColor[0] >> this->DiffuseColor[1] >> this->DiffuseColor[2]; + is >> this->SpecularColor[0] >> this->SpecularColor[1] >> this->SpecularColor[2]; + is >> this->Switch; + is >> this->Positional; + is >> this->Exponent; + is >> this->ConeAngle; + is >> this->AttenuationValues[0] >> this->AttenuationValues[1] + >> this->AttenuationValues[2]; + // XXX - LightType, TransformMatrix ??? +} + + + diff --git a/Rendering/vtkLight.h b/Rendering/vtkLight.h new file mode 100644 index 0000000..8e4bb07 --- /dev/null +++ b/Rendering/vtkLight.h @@ -0,0 +1,237 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLight.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLight - a virtual light for 3D rendering +// .SECTION Description +// vtkLight is a virtual light for 3D rendering. It provides methods to locate +// and point the light, turn it on and off, and set its brightness and color. +// In addition to the basic infinite distance point light source attributes, +// you also can specify the light attenuation values and cone angle. +// These attributes are only used if the light is a positional light. +// The default is a directional light (e.g. infinite point light source). +// +// Lights have a type that describes how the light should move with respect +// to the camera. A Headlight is always located at the current camera position +// and shines on the camera's focal point. A CameraLight also moves with +// the camera, but may not be coincident to it. CameraLights are defined +// in a normalized coordinate space where the camera is located at (0, 0, 1), +// the camera is looking at (0, 0, 0), and up is (0, 1, 0). Finally, a +// SceneLight is part of the scene itself and does not move with the camera. +// (Renderers are responsible for moving the light based on its type.) +// +// Lights have a transformation matrix that describes the space in which +// they are positioned. A light's world space position and focal point +// are defined by their local position and focal point, transformed by +// their transformation matrix (if it exists). + +#ifndef __vtkLight_h +#define __vtkLight_h + +#include "vtkObject.h" + +/* need for virtual function */ +class vtkRenderer; +class vtkMatrix4x4; + +#define VTK_LIGHT_TYPE_HEADLIGHT 1 +#define VTK_LIGHT_TYPE_CAMERA_LIGHT 2 +#define VTK_LIGHT_TYPE_SCENE_LIGHT 3 + +class VTK_RENDERING_EXPORT vtkLight : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkLight,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a light with the focal point at the origin and its position + // set to (0,0,1). The light is a SceneLight, its color is white, + // intensity=1, and the light is turned on. + static vtkLight *New(); + + // Description: + // Abstract interface to renderer. Each concrete subclass of vtkLight + // will load its data into the graphics system in response to this method + // invocation. The actual loading is performed by a vtkLightDevice + // subclass, which will get created automatically. + virtual void Render(vtkRenderer *, int) {}; + + // Description: + // Set/Get the color of the light. It is possible to set the ambient, + // diffuse and specular colors separately. The SetColor() method sets + // the diffuse and specular colors to the same color (this is a feature + // to preserve backward compatbility.) + vtkSetVector3Macro(AmbientColor,double); + vtkGetVectorMacro(AmbientColor,double,3); + vtkSetVector3Macro(DiffuseColor,double); + vtkGetVectorMacro(DiffuseColor,double,3); + vtkSetVector3Macro(SpecularColor,double); + vtkGetVectorMacro(SpecularColor,double,3); + void SetColor(double, double, double); + void SetColor(double a[3]) { this->SetColor(a[0], a[1], a[2]); } + void GetColor(double rgb[3]); + double *GetColor(); + + // Description: + // Set/Get the position of the light. + // Note: The position of the light is defined in the coordinate + // space indicated by its transformation matrix (if it exists). + // Thus, to get the light's world space position, use + // vtkGetTransformedPosition() instead of vtkGetPosition(). + vtkSetVector3Macro(Position,double); + vtkGetVectorMacro(Position,double,3); + void SetPosition(float *a) {this->SetPosition(a[0],a[1],a[2]);}; + + // Description: + // Set/Get the point at which the light is shining. + // Note: The focal point of the light is defined in the coordinate + // space indicated by its transformation matrix (if it exists). + // Thus, to get the light's world space focal point, use + // vtkGetTransformedFocalPoint() instead of vtkGetFocalPoint(). + vtkSetVector3Macro(FocalPoint,double); + vtkGetVectorMacro(FocalPoint,double,3); + void SetFocalPoint(float *a) {this->SetFocalPoint(a[0],a[1],a[2]);}; + + // Description: + // Set/Get the brightness of the light (from one to zero). + vtkSetMacro(Intensity,double); + vtkGetMacro(Intensity,double); + + // Description: + // Turn the light on or off. + vtkSetMacro(Switch,int); + vtkGetMacro(Switch,int); + vtkBooleanMacro(Switch,int); + + // Description: + // Turn positional lighting on or off. + vtkSetMacro(Positional,int); + vtkGetMacro(Positional,int); + vtkBooleanMacro(Positional,int); + + // Description: + // Set/Get the exponent of the cosine used in positional lighting. + vtkSetMacro(Exponent,double); + vtkGetMacro(Exponent,double); + + // Description: + // Set/Get the lighting cone angle of a positional light in degrees. + // A value of 180 indicates that you want no spot lighting effects + // just a positional light. + vtkSetMacro(ConeAngle,double); + vtkGetMacro(ConeAngle,double); + + // Description: + // Set/Get the quadratic attenuation constants. They are specified as + // constant, linear, and quadratic, in that order. + vtkSetVector3Macro(AttenuationValues,double); + vtkGetVectorMacro(AttenuationValues,double,3); + + // Description: + // Set/Get the light's transformation matrix. If a matrix is set for + // a light, the light's parameters (position and focal point) are + // transformed by the matrix before being rendered. + virtual void SetTransformMatrix(vtkMatrix4x4*); + vtkGetObjectMacro(TransformMatrix,vtkMatrix4x4); + + // Description: + // Get the position of the light, modified by the transformation matrix + // (if it exists). + void GetTransformedPosition(double &a0, double &a1, double &a2); + void GetTransformedPosition(double a[3]); + double *GetTransformedPosition(); + + // Description: + // Get the focal point of the light, modified by the transformation matrix + // (if it exists). + void GetTransformedFocalPoint(double &a0, double &a1, double &a2); + void GetTransformedFocalPoint(double a[3]); + double *GetTransformedFocalPoint(); + + // Description: + // Set the position and focal point of a light based on elevation and + // azimuth. The light is moved so it is shining from the given angle. + // Angles are given in degrees. If the light is a + // positional light, it is made directional instead. + void SetDirectionAngle(double elevation, double azimuth); + void SetDirectionAngle(double ang[2]) { + this->SetDirectionAngle(ang[0], ang[1]); }; + + // Description: + // Perform deep copy of this light. + void DeepCopy(vtkLight *light); + + // Description: + // Set/Get the type of the light. + // A SceneLight is a light located in the world coordinate space. A light + // is initially created as a scene light. + // + // A Headlight is always located at the camera and is pointed at the + // camera's focal point. The renderer is free to modify the position and + // focal point of the camera at any time. + // + // A CameraLight is also attached to the camera, but is not necessarily + // located at the camera's position. CameraLights are defined in a + // coordinate space where the camera is located at (0, 0, 1), looking + // towards (0, 0, 0) at a distance of 1, with up being (0, 1, 0). + // + // Note: Use SetLightTypeToSceneLight, rather than SetLightType(3), since + // the former clears the light's transform matrix. + vtkSetMacro(LightType, int); + vtkGetMacro(LightType, int); + void SetLightTypeToHeadlight() + {this->SetLightType(VTK_LIGHT_TYPE_HEADLIGHT);} + void SetLightTypeToSceneLight() + { + this->SetTransformMatrix(NULL); + this->SetLightType(VTK_LIGHT_TYPE_SCENE_LIGHT); + } + void SetLightTypeToCameraLight() + {this->SetLightType(VTK_LIGHT_TYPE_CAMERA_LIGHT);} + + // Description: + // Query the type of the light. + int LightTypeIsHeadlight(); + int LightTypeIsSceneLight(); + int LightTypeIsCameraLight(); + + void ReadSelf(istream& is); + void WriteSelf(ostream& os); + +protected: + vtkLight(); + ~vtkLight(); + + double FocalPoint[3]; + double Position[3]; + double Intensity; + double AmbientColor[3]; + double DiffuseColor[3]; + double SpecularColor[3]; + int Switch; + int Positional; + double Exponent; + double ConeAngle; + double AttenuationValues[3]; + vtkMatrix4x4 *TransformMatrix; + double TransformedFocalPointReturn[3]; + double TransformedPositionReturn[3]; + int LightType; + +private: + vtkLight(const vtkLight&); // Not implemented. + void operator=(const vtkLight&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkLightCollection.cxx b/Rendering/vtkLightCollection.cxx new file mode 100644 index 0000000..d33eeb0 --- /dev/null +++ b/Rendering/vtkLightCollection.cxx @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLightCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLightCollection.h" + +#include "vtkObjectFactory.h" +#include "vtkLight.h" + +#include + +vtkCxxRevisionMacro(vtkLightCollection, "$Revision: 1.16 $"); +vtkStandardNewMacro(vtkLightCollection); + +// Add a light to the list. +void vtkLightCollection::AddItem(vtkLight *a) +{ + this->vtkCollection::AddItem((vtkObject *)a); +} + +// Get the next light in the list. NULL is returned when the collection is +// exhausted. +vtkLight *vtkLightCollection::GetNextItem() +{ + return static_cast(this->GetNextItemAsObject()); +} + +vtkLight *vtkLightCollection::GetNextLight( + vtkCollectionSimpleIterator &cookie) +{ + return static_cast(this->GetNextItemAsObject(cookie)); +} + +//---------------------------------------------------------------------------- +void vtkLightCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkLightCollection.h b/Rendering/vtkLightCollection.h new file mode 100644 index 0000000..e834bc0 --- /dev/null +++ b/Rendering/vtkLightCollection.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLightCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLightCollection - a list of lights +// .SECTION Description +// vtkLightCollection represents and provides methods to manipulate a list of +// lights (i.e., vtkLight and subclasses). The list is unsorted and duplicate +// entries are not prevented. + +// .SECTION see also +// vtkCollection vtkLight + +#ifndef __vtkLightC_h +#define __vtkLightC_h + +#include "vtkCollection.h" + +class vtkLight; + +class VTK_RENDERING_EXPORT vtkLightCollection : public vtkCollection +{ + public: + static vtkLightCollection *New(); + vtkTypeRevisionMacro(vtkLightCollection,vtkCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a light to the list. + void AddItem(vtkLight *a); + + // Description: + // Get the next light in the list. NULL is returned when the collection is + // exhausted. + vtkLight *GetNextItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkLight *GetNextLight(vtkCollectionSimpleIterator &cookie); + //ETX + +protected: + vtkLightCollection() {}; + ~vtkLightCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkLightCollection(const vtkLightCollection&); // Not implemented. + void operator=(const vtkLightCollection&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkLightKit.cxx b/Rendering/vtkLightKit.cxx new file mode 100644 index 0000000..d286ee3 --- /dev/null +++ b/Rendering/vtkLightKit.cxx @@ -0,0 +1,518 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLightKit.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLightKit.h" + +#include "vtkObjectFactory.h" +#include "vtkLight.h" +#include "vtkPiecewiseFunction.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkLightKit, "$Revision: 1.25.6.1 $"); +vtkStandardNewMacro(vtkLightKit); + +static const char *vtkLightKitTypeStrings[] = { + "KeyLight", + "FillLight", + "BackLight", + "HeadLight", + NULL +}; + +static const char *vtkLightKitSubTypeStrings[] = { + "Warmth", + "Intensity", + "Elevation", + "Azimuth", + "K:F Ratio", + "K:B Ratio", + "K:H Ratio", + NULL +}; + +// These are the same as vtkLightKitSubTypeStrings but shorter +// usefull for a GUI with minimum space +static const char *vtkLightKitSubTypeShortStrings[] = { + "War.", + "Int. ", + "Ele.", + "Azi.", + "K:F", + "K:B", + "K:H", + NULL +}; + + +//---------------------------------------------------------------------------- +vtkLightKit::vtkLightKit() +{ + // create members + this->KeyLight = vtkLight::New(); + this->FillLight = vtkLight::New(); + this->HeadLight = vtkLight::New(); + this->BackLight0 = vtkLight::New(); + this->BackLight1 = vtkLight::New(); + + for(int i = 0; i < 4; i++) + { + this->WarmthFunction[i] = vtkPiecewiseFunction::New(); + } + this->InitializeWarmthFunctions(); + + // initialize values + this->KeyLight->SetLightTypeToCameraLight(); + this->FillLight->SetLightTypeToCameraLight(); + this->BackLight0->SetLightTypeToCameraLight(); + this->BackLight1->SetLightTypeToCameraLight(); + + this->HeadLight->SetLightTypeToHeadlight(); + + this->SetKeyLightAngle(50.0, 10.0); + this->SetFillLightAngle(-75.0, -10.0); + this->SetBackLightAngle(0.0, 110.0); + + this->KeyLightWarmth = 0.6; + this->FillLightWarmth = 0.4; + this->HeadLightWarmth = 0.5; + this->BackLightWarmth = 0.5; + + this->KeyLightIntensity = 0.75; + this->KeyToFillRatio = 3.0; + this->KeyToBackRatio = 3.5; + this->KeyToHeadRatio = 3.0; + + this->MaintainLuminance = 0; + this->Update(); +} + +//---------------------------------------------------------------------------- +vtkLightKit::~vtkLightKit() +{ + this->KeyLight->Delete(); + this->FillLight->Delete(); + this->HeadLight->Delete(); + this->BackLight0->Delete(); + this->BackLight1->Delete(); + + for(int i = 0; i < 4; i++) + { + this->WarmthFunction[i]->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkLightKit::SetKeyLightAngle(double elevation, double azimuth) +{ + this->KeyLightAngle[0] = elevation; + this->KeyLightAngle[1] = azimuth; + + this->KeyLight->SetDirectionAngle(elevation, azimuth); +} + +//---------------------------------------------------------------------------- +void vtkLightKit::SetFillLightAngle(double elevation, double azimuth) +{ + this->FillLightAngle[0] = elevation; + this->FillLightAngle[1] = azimuth; + + this->FillLight->SetDirectionAngle(elevation, azimuth); +} + +//---------------------------------------------------------------------------- +void vtkLightKit::SetBackLightAngle(double elevation, double azimuth) +{ + this->BackLightAngle[0] = elevation; + this->BackLightAngle[1] = azimuth; + + this->BackLight0->SetDirectionAngle(elevation, azimuth); + this->BackLight1->SetDirectionAngle(elevation, -azimuth); +} + +//---------------------------------------------------------------------------- +void vtkLightKit::WarmthToRGB(double w, double rgb[3]) +{ + rgb[0] = this->WarmthFunction[0]->GetValue(w); + rgb[1] = this->WarmthFunction[1]->GetValue(w); + rgb[2] = this->WarmthFunction[2]->GetValue(w); +} + +//---------------------------------------------------------------------------- +double vtkLightKit::WarmthToIntensity(double w) +{ + return this->WarmthFunction[3]->GetValue(w); +} + +//---------------------------------------------------------------------------- +void vtkLightKit::WarmthToRGBI(double w, double rgb[3], double& i) +{ + rgb[0] = this->WarmthFunction[0]->GetValue(w); + rgb[1] = this->WarmthFunction[1]->GetValue(w); + rgb[2] = this->WarmthFunction[2]->GetValue(w); + i = this->WarmthFunction[3]->GetValue(w); +} + +//---------------------------------------------------------------------------- +void vtkLightKit::AddLightsToRenderer(vtkRenderer *renderer) +{ + if(renderer != NULL) + { + renderer->AddLight(this->HeadLight); + renderer->AddLight(this->KeyLight); + renderer->AddLight(this->FillLight); + renderer->AddLight(this->BackLight0); + renderer->AddLight(this->BackLight1); + } +} + +//---------------------------------------------------------------------------- +void vtkLightKit::RemoveLightsFromRenderer(vtkRenderer *renderer) +{ + if(renderer != NULL) + { + renderer->RemoveLight(this->HeadLight); + renderer->RemoveLight(this->KeyLight); + renderer->RemoveLight(this->FillLight); + renderer->RemoveLight(this->BackLight0); + renderer->RemoveLight(this->BackLight1); + } +} + +//---------------------------------------------------------------------------- +void vtkLightKit::Modified() +{ + this->Update(); + this->MTime.Modified(); +} + +//---------------------------------------------------------------------------- +void vtkLightKit::Update() +{ + double *fillLightColor = this->FillLightColor; + double fillLightPI; + + double *keyLightColor = this->KeyLightColor; + double keyLightPI; + + double *headlightColor = this->HeadLightColor; + double headlightPI; + + double *backLightColor = this->BackLightColor; + double backLightPI; + + double fillLightIntensity, keyLightIntensity, headlightIntensity; + double backLightIntensity; + + this->WarmthToRGBI(this->KeyLightWarmth, keyLightColor, keyLightPI); + this->WarmthToRGBI(this->FillLightWarmth, fillLightColor, fillLightPI); + this->WarmthToRGBI(this->HeadLightWarmth, headlightColor, headlightPI); + this->WarmthToRGBI(this->BackLightWarmth, backLightColor, backLightPI); + + keyLightIntensity = this->KeyLightIntensity; + + fillLightIntensity = keyLightIntensity / this->KeyToFillRatio; + headlightIntensity = keyLightIntensity / this->KeyToHeadRatio; + backLightIntensity = keyLightIntensity / this->KeyToBackRatio; + + // This is sort of interesting: the fill light intensity is weighted + // by the perceptual brightness of the color of each light. Since + // the fill light will often be a cooler color than the key light, + // the bluer color would otherwise seem less bright than the neutral + // and this bias the key-to-fill ratio. This factor compensates for + // this problem. Note we always do this correction, no matter what + // the MaintainLuminance flag says. That flag's for controlling + // the intensity of the entire scene, not just the fill light. + + if(this->MaintainLuminance) + { + fillLightIntensity /= fillLightPI; + headlightIntensity /= headlightPI; + keyLightIntensity /= keyLightPI; + backLightIntensity /= backLightPI; + } + this->KeyLight->SetColor(keyLightColor); + this->KeyLight->SetIntensity(keyLightIntensity); + + this->FillLight->SetColor(fillLightColor); + this->FillLight->SetIntensity(fillLightIntensity); + + this->HeadLight->SetColor(headlightColor); + this->HeadLight->SetIntensity(headlightIntensity); + + this->BackLight0->SetColor(backLightColor); + this->BackLight0->SetIntensity(backLightIntensity); + + this->BackLight1->SetColor(backLightColor); + this->BackLight1->SetIntensity(backLightIntensity); +} + +//---------------------------------------------------------------------------- +void vtkLightKit::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "KeyLightIntensity: " << this->KeyLightIntensity << "\n"; + os << indent << "KeyToFillRatio: " << this->KeyToFillRatio << "\n"; + os << indent << "KeyToHeadRatio: " << this->KeyToHeadRatio << "\n"; + os << indent << "KeyToBackRatio: " << this->KeyToBackRatio << "\n"; + + os << indent << "KeyLightWarmth: " << this->KeyLightWarmth << "\n"; + os << indent << "KeyLightAngle: (" + << this->KeyLightAngle[0] << ", " + << this->KeyLightAngle[1] << ")\n"; + + os << indent << "FillLightWarmth: " << this->FillLightWarmth << "\n"; + os << indent << "FillLightAngle: (" + << this->FillLightAngle[0] << ", " + << this->FillLightAngle[1] << ")\n"; + + os << indent << "BackLightWarmth: " << this->BackLightWarmth << "\n"; + os << indent << "BackLightAngle: (" + << this->BackLightAngle[0] << ", " + << this->BackLightAngle[1] << ")\n"; + + os << indent << "HeadLightWarmth: " << this->HeadLightWarmth << "\n"; + + os << indent << "MaintainLuminance: " << + (this->MaintainLuminance ? "On" : "Off") << "\n"; + + // here, but commented out to satisfy validation tests.... + // os << indent << "KeyLightColor: (" + // << this->KeyLightColor[0] << ", " + // << this->KeyLightColor[1] << ", " + // << this->KeyLightColor[2] << ")\n"; + + // os << indent << "FillLightColor: (" + // << this->FillLightColor[0] << ", " + // << this->FillLightColor[1] << ", " + // << this->FillLightColor[2] << ")\n"; + + // os << indent << "HeadLightColor: (" + // << this->HeadLightColor[0] << ", " + // << this->HeadLightColor[1] << ", " + // << this->HeadLightColor[2] << ")\n"; + + // os << indent << "BackLightColor: (" + // << this->BackLightColor[0] << ", " + // << this->BackLightColor[1] << ", " + // << this->BackLightColor[2] << ")\n"; +} + +//---------------------------------------------------------------------------- +void vtkLightKit::DeepCopy( vtkLightKit *k ) +{ + this->KeyLightIntensity = k->KeyLightIntensity; + this->KeyToFillRatio = k->KeyToFillRatio; + this->KeyToHeadRatio = k->KeyToHeadRatio; + this->KeyToBackRatio = k->KeyToBackRatio; + + this->KeyLightWarmth = k->KeyLightWarmth; + this->FillLightWarmth = k->FillLightWarmth; + this->HeadLightWarmth = k->HeadLightWarmth; + this->BackLightWarmth = k->BackLightWarmth; + + this->KeyLightAngle[0] = k->KeyLightAngle[0]; + this->KeyLightAngle[1] = k->KeyLightAngle[1]; + + this->FillLightAngle[0] = k->FillLightAngle[0]; + this->FillLightAngle[1] = k->FillLightAngle[1]; + + this->BackLightAngle[0] = k->BackLightAngle[0]; + this->BackLightAngle[1] = k->BackLightAngle[1]; + + this->MaintainLuminance = k->MaintainLuminance; + + this->KeyLight->DeepCopy(k->KeyLight); + this->FillLight->DeepCopy(k->FillLight); + this->HeadLight->DeepCopy(k->HeadLight); + this->BackLight0->DeepCopy(k->BackLight0); + this->BackLight1->DeepCopy(k->BackLight1); +} + +//---------------------------------------------------------------------------- +// r, g, b, sqrt(color length) +static double warmthTable[] = { + 0.1674, 0.3065, 1.0000, 0.5865, + 0.1798, 0.3204, 1.0000, 0.5965, + 0.1935, 0.3352, 1.0000, 0.6071, + 0.2083, 0.3511, 1.0000, 0.6184, + 0.2245, 0.3679, 1.0000, 0.6302, + 0.2422, 0.3859, 1.0000, 0.6426, + 0.2614, 0.4050, 1.0000, 0.6556, + 0.2822, 0.4252, 1.0000, 0.6693, + 0.3049, 0.4467, 1.0000, 0.6837, + 0.3293, 0.4695, 1.0000, 0.6986, + 0.3557, 0.4935, 1.0000, 0.7142, + 0.3841, 0.5188, 1.0000, 0.7303, + 0.4144, 0.5454, 1.0000, 0.7470, + 0.4468, 0.5731, 1.0000, 0.7642, + 0.4811, 0.6020, 1.0000, 0.7818, + 0.5173, 0.6320, 1.0000, 0.7998, + 0.5551, 0.6628, 1.0000, 0.8179, + 0.5943, 0.6942, 1.0000, 0.8362, + 0.6346, 0.7261, 1.0000, 0.8544, + 0.6756, 0.7581, 1.0000, 0.8724, + 0.7168, 0.7898, 1.0000, 0.8899, + 0.7575, 0.8209, 1.0000, 0.9068, + 0.7972, 0.8508, 1.0000, 0.9229, + 0.8351, 0.8791, 1.0000, 0.9379, + 0.8705, 0.9054, 1.0000, 0.9517, + 0.9026, 0.9290, 1.0000, 0.9640, + 0.9308, 0.9497, 1.0000, 0.9746, + 0.9546, 0.9671, 1.0000, 0.9834, + 0.9734, 0.9808, 1.0000, 0.9903, + 0.9872, 0.9907, 1.0000, 0.9954, + 0.9958, 0.9970, 1.0000, 0.9985, + 0.9996, 0.9997, 1.0000, 0.9999, + 1.0000, 0.9999, 0.9996, 0.9999, + 1.0000, 0.9988, 0.9958, 0.9994, + 1.0000, 0.9964, 0.9871, 0.9982, + 1.0000, 0.9925, 0.9730, 0.9962, + 1.0000, 0.9869, 0.9532, 0.9935, + 1.0000, 0.9796, 0.9275, 0.9898, + 1.0000, 0.9705, 0.8959, 0.9853, + 1.0000, 0.9595, 0.8584, 0.9798, + 1.0000, 0.9466, 0.8150, 0.9734, + 1.0000, 0.9317, 0.7660, 0.9660, + 1.0000, 0.9147, 0.7116, 0.9576, + 1.0000, 0.8956, 0.6522, 0.9482, + 1.0000, 0.8742, 0.5881, 0.9377, + 1.0000, 0.8506, 0.5199, 0.9261, + 1.0000, 0.8247, 0.4483, 0.9134, + 1.0000, 0.7964, 0.3739, 0.8995, + 1.0000, 0.7656, 0.2975, 0.8845, + 1.0000, 0.7324, 0.2201, 0.8683, + 1.0000, 0.6965, 0.1426, 0.8509, + 1.0000, 0.6580, 0.0662, 0.8323, + 1.0000, 0.6179, 0.0000, 0.8134, + 1.0000, 0.5832, 0.0000, 0.8008, + 1.0000, 0.5453, 0.0000, 0.7868, + 1.0000, 0.5042, 0.0000, 0.7713, + 1.0000, 0.4595, 0.0000, 0.7541, + 1.0000, 0.4111, 0.0000, 0.7350, + 1.0000, 0.3588, 0.0000, 0.7139, + 1.0000, 0.3025, 0.0000, 0.6904, + 1.0000, 0.2423, 0.0000, 0.6643, + 1.0000, 0.1782, 0.0000, 0.6353, + 1.0000, 0.1104, 0.0000, 0.6032, + 1.0000, 0.0396, 0.0000, 0.5677, +}; + +//---------------------------------------------------------------------------- +void vtkLightKit::InitializeWarmthFunctions() +{ + const int len = sizeof(warmthTable) / sizeof(double) / 4; + + for(int i = 0; i < 4; i++) + { + this->WarmthFunction[i]->BuildFunctionFromTable(0.0, 1.0, len, + &warmthTable[i], 4); + } +} + +//---------------------------------------------------------------------------- +const char *vtkLightKit::GetStringFromType(int type) +{ + static const int n = sizeof(vtkLightKitTypeStrings)/sizeof(char*); + if( type < n ) + { + return vtkLightKitTypeStrings[type]; + } + else + { + return NULL; + } +} + +//---------------------------------------------------------------------------- +const char *vtkLightKit::GetStringFromSubType(int subtype) +{ + static const int n = sizeof(vtkLightKitSubTypeStrings)/sizeof(char*); + if( subtype < n ) + { + return vtkLightKitSubTypeStrings[subtype]; + } + else + { + return NULL; + } +} + +//---------------------------------------------------------------------------- +const char *vtkLightKit::GetShortStringFromSubType(int subtype) +{ + static const int n = sizeof(vtkLightKitSubTypeShortStrings)/sizeof(char*); + if( subtype < n ) + { + return vtkLightKitSubTypeShortStrings[subtype]; + } + else + { + return NULL; + } +} +//---------------------------------------------------------------------------- +vtkLightKit::LightKitSubType vtkLightKit::GetSubType(vtkLightKit::LightKitType type, int i) +{ + //return subtype + const LightKitSubType KeyLightSubType[4] = { Warmth, Intensity, Elevation, Azimuth }; + const LightKitSubType FillLightSubType[4] = { Warmth, KFRatio, Elevation, Azimuth }; + const LightKitSubType BackLightSubType[4] = { Warmth, KBRatio, Elevation, Azimuth }; + const LightKitSubType HeadLightSubType[2] = { Warmth, KHRatio }; + + LightKitSubType subtype = Warmth; // please VS6 + switch(type) + { + case TKeyLight: + subtype = KeyLightSubType[i]; + break; + case TFillLight: + subtype = FillLightSubType[i]; + break; + case TBackLight: + subtype = BackLightSubType[i]; + break; + case THeadLight: + subtype = HeadLightSubType[i]; + break; + } + + return subtype; +} + +// The following methods are deprecated: + +#ifndef VTK_LEGACY_REMOVE +void vtkLightKit::SetHeadlightWarmth(double v) +{ + VTK_LEGACY_REPLACED_BODY(vtkLightKit::SetHeadlightWarmth, "VTK 5.0", + vtkLightKit::SetHeadLightWarmth); + this->SetHeadLightWarmth(v); +} + +double vtkLightKit::GetHeadlightWarmth() +{ + VTK_LEGACY_REPLACED_BODY(vtkLightKit::GetHeadlightWarmth, "VTK 5.0", + vtkLightKit::GetHeadLightWarmth); + return this->GetHeadLightWarmth(); +} + +void vtkLightKit::GetHeadlightColor(double *color) +{ + VTK_LEGACY_REPLACED_BODY(vtkLightKit::SetHeadlightColor, "VTK 5.0", + vtkLightKit::SetHeadLightColor); + this->GetHeadLightColor(color); +} +#endif + diff --git a/Rendering/vtkLightKit.h b/Rendering/vtkLightKit.h new file mode 100644 index 0000000..77d556a --- /dev/null +++ b/Rendering/vtkLightKit.h @@ -0,0 +1,350 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLightKit.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLightKit - a simple but quality lighting kit +// .SECTION Description +// vtkLightKit is designed to make general purpose lighting of vtk +// scenes simple, flexible, and attractive (or at least not horribly +// ugly without significant effort). Use a LightKit when you want +// more control over your lighting than you can get with the default +// vtk light, which is a headlight located at the camera. (HeadLights +// are very simple to use, but they don't show the shape of objects very +// well, don't give a good sense of "up" and "down", and don't evenly +// light the object.) +// +// A LightKit consists of three lights, a key light, a fill light, and +// a headlight. The main light is the key light. It is usually +// positioned so that it appears like an overhead light (like the sun, +// or a ceiling light). It is generally positioned to shine down on the +// scene from about a 45 degree angle vertically and at least a little +// offset side to side. The key light usually at least about twice as +// bright as the total of all other lights in the scene to provide good +// modeling of object features. +// +// The other lights in the kit (the fill light, headlight, and a pair of +// back lights) are weaker sources that provide extra +// illumination to fill in the spots that the key light misses. The +// fill light is usually positioned across from or opposite from the +// key light (though still on the same side of the object as the +// camera) in order to simulate diffuse reflections from other objects +// in the scene. The headlight, always located at the position of the +// camera, reduces the contrast between areas lit by the key and fill +// light. The two back lights, one on the left of the object as seen +// from the observer and one on the right, fill on the high-contrast +// areas behind the object. To enforce the relationship between the +// different lights, the intensity of the fill, back and headlights +// are set as a ratio to the key light brightness. Thus, the +// brightness of all the lights in the scene can be changed by +// changing the key light intensity. +// +// All lights are directional lights (infinitely far away with no +// falloff). Lights move with the camera. +// +// For simplicity, the position of lights in the LightKit can only be +// specified using angles: the elevation (latitude) and azimuth +// (longitude) of each light with respect to the camera, expressed in +// degrees. (Lights always shine on the camera's lookat point.) For +// example, a light at (elevation=0, azimuth=0) is located at the +// camera (a headlight). A light at (elevation=90, azimuth=0) is +// above the lookat point, shining down. Negative azimuth values move +// the lights clockwise as seen above, positive values +// counter-clockwise. So, a light at (elevation=45, azimuth=-20) is +// above and in front of the object and shining slightly from the left +// side. +// +// vtkLightKit limits the colors that can be assigned to any light to +// those of incandescent sources such as light bulbs and sunlight. It +// defines a special color spectrum called "warmth" from which light +// colors can be chosen, where 0 is cold blue, 0.5 is neutral white, +// and 1 is deep sunset red. Colors close to 0.5 are "cool whites" and +// "warm whites," respectively. +// +// Since colors far from white on the warmth scale appear less bright, +// key-to-fill and key-to-headlight ratios are skewed by +// key, fill, and headlight colors. If the flag MaintainLuminance +// is set, vtkLightKit will attempt to compensate for these perceptual +// differences by increasing the brightness of more saturated colors. +// +// A LightKit is not explicitly part of the vtk pipeline. Rather, it +// is a composite object that controls the behavior of lights using a +// unified user interface. Every time a parameter of vtkLightKit is +// adjusted, the properties of its lights are modified. +// +// .SECTION Credits +// vtkLightKit was originally written and contributed to vtk by +// Michael Halle (mhalle@bwh.harvard.edu) at the Surgical Planning +// Lab, Brigham and Women's Hospital. + +#ifndef __vtkLightKit_h +#define __vtkLightKit_h + +#include "vtkObject.h" + +class vtkLight; +class vtkPiecewiseFunction; +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkLightKit : public vtkObject +{ +public: + static vtkLightKit *New(); + vtkTypeRevisionMacro(vtkLightKit, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + //BTX + enum LightKitType { + TKeyLight, + TFillLight, + TBackLight, + THeadLight + }; + + enum LightKitSubType { + Warmth, + Intensity, + Elevation, + Azimuth, + KFRatio, + KBRatio, + KHRatio + }; + + //ETX + + // Description: + // Set/Get the intensity of the key light. The key light is the + // brightest light in the scene. The intensities of the other two + // lights are ratios of the key light's intensity. + vtkSetMacro(KeyLightIntensity, double); + vtkGetMacro(KeyLightIntensity, double); + + // Description: + // Set/Get the key-to-fill ratio. This ratio controls + // how bright the fill light is compared to the key light: larger + // values correspond to a dimmer fill light. The purpose of the + // fill light is to light parts of the object not lit by the key + // light, while still maintaining constrast. This type of lighting + // may correspond to indirect illumination from the key light, bounced + // off a wall, floor, or other object. The fill light should never + // be brighter than the key light: a good range for the key-to-fill + // ratio is between 2 and 10. + vtkSetClampMacro(KeyToFillRatio, double, 0.5, VTK_FLOAT_MAX); + vtkGetMacro(KeyToFillRatio, double); + + // Description: + // Set/Get the key-to-headlight ratio. Similar to the key-to-fill + // ratio, this ratio controls how bright the headlight light is + // compared to the key light: larger values correspond to a dimmer + // headlight light. The headlight is special kind of fill light, + // lighting only the parts of the object that the camera can see. + // As such, a headlight tends to reduce the contrast of a scene. It + // can be used to fill in "shadows" of the object missed by the key + // and fill lights. The headlight should always be significantly + // dimmer than the key light: ratios of 2 to 15 are typical. + vtkSetClampMacro(KeyToHeadRatio, double, 0.5, VTK_FLOAT_MAX); + vtkGetMacro(KeyToHeadRatio, double); + + // Description: + // Set/Get the key-to-back light ratio. This ratio controls + // how bright the back lights are compared to the key light: larger + // values correspond to dimmer back lights. The back lights fill + // in the remaining high-contrast regions behind the object. + // Values between 2 and 10 are good. + vtkSetClampMacro(KeyToBackRatio, double, 0.5, VTK_FLOAT_MAX); + vtkGetMacro(KeyToBackRatio, double); + + // Description: + // Set the warmth of each the lights. Warmth is a parameter that + // varies from 0 to 1, where 0 is "cold" (looks icy or lit by a very + // blue sky), 1 is "warm" (the red of a very red sunset, or the + // embers of a campfire), and 0.5 is a neutral white. The warmth + // scale is non-linear. Warmth values close to 0.5 are subtly + // "warmer" or "cooler," much like a warmer tungsten incandescent + // bulb, a cooler halogen, or daylight (cooler still). Moving + // further away from 0.5, colors become more quickly varying towards + // blues and reds. With regards to aesthetics, extremes of warmth + // should be used sparingly. + vtkSetMacro(KeyLightWarmth, double); + vtkGetMacro(KeyLightWarmth, double); + + vtkSetMacro(FillLightWarmth, double); + vtkGetMacro(FillLightWarmth, double); + + vtkSetMacro(HeadLightWarmth, double); + vtkGetMacro(HeadLightWarmth, double); + + vtkSetMacro(BackLightWarmth, double); + vtkGetMacro(BackLightWarmth, double); + + // Description: + // Returns the floating-point RGB values of each of the light's color. + vtkGetVectorMacro(KeyLightColor, double, 3); + vtkGetVectorMacro(FillLightColor, double, 3); + vtkGetVectorMacro(HeadLightColor, double, 3); + vtkGetVectorMacro(BackLightColor, double, 3); + + // Description: + // To maintain a deprecation API: + VTK_LEGACY(void SetHeadlightWarmth(double v)); + VTK_LEGACY(double GetHeadlightWarmth()); + VTK_LEGACY(void GetHeadlightColor(double *color)); + + // Description: + // If MaintainLuminance is set, the LightKit will attempt to maintain + // the apparent intensity of lights based on their perceptual brightnesses. + // By default, MaintainLuminance is off. + vtkBooleanMacro(MaintainLuminance, int); + vtkGetMacro(MaintainLuminance, int); + vtkSetMacro(MaintainLuminance, int); + + // Description: + // Get/Set the position of the key, fill, and back lights + // using angular methods. Elevation corresponds to latitude, + // azimuth to longitude. It is recommended that the key light + // always be on the viewer's side of the object and above the + // object, while the fill light generally lights the part of the object + // not lit by the fill light. The headlight, which is always located + // at the viewer, can then be used to reduce the contrast in the image. + // There are a pair of back lights. They are located at the same + // elevation and at opposing azimuths (ie, one to the left, and one to + // the right). They are generally set at the equator (elevation = 0), + // and at approximately 120 degrees (lighting from each side and behind). + void SetKeyLightAngle(double elevation, double azimuth); + void SetKeyLightAngle(double angle[2]) { + this->SetKeyLightAngle(angle[0], angle[1]); }; + + void SetKeyLightElevation(double x) { + this->SetKeyLightAngle(x, this->KeyLightAngle[1]); }; + + void SetKeyLightAzimuth(double x) { + this->SetKeyLightAngle(this->KeyLightAngle[0], x); }; + + vtkGetVectorMacro(KeyLightAngle, double, 2); + double GetKeyLightElevation() { + double ang[2]; this->GetKeyLightAngle(ang); return ang[0]; }; + + double GetKeyLightAzimuth() { + double ang[2]; this->GetKeyLightAngle(ang); return ang[1]; }; + + void SetFillLightAngle(double elevation, double azimuth); + void SetFillLightAngle(double angle[2]) { + this->SetFillLightAngle(angle[0], angle[1]); }; + + void SetFillLightElevation(double x) { + this->SetFillLightAngle(x, this->FillLightAngle[1]); }; + + void SetFillLightAzimuth(double x) { + this->SetFillLightAngle(this->FillLightAngle[0], x); }; + + vtkGetVectorMacro(FillLightAngle, double, 2); + double GetFillLightElevation() { + double ang[2]; this->GetFillLightAngle(ang); return ang[0]; }; + + double GetFillLightAzimuth() { + double ang[2]; this->GetFillLightAngle(ang); return ang[1]; }; + + void SetBackLightAngle(double elevation, double azimuth); + void SetBackLightAngle(double angle[2]) { + this->SetBackLightAngle(angle[0], angle[1]); }; + + void SetBackLightElevation(double x) { + this->SetBackLightAngle(x, this->BackLightAngle[1]); }; + + void SetBackLightAzimuth(double x) { + this->SetBackLightAngle(this->BackLightAngle[0], x); }; + + vtkGetVectorMacro(BackLightAngle, double, 2); + double GetBackLightElevation() { + double ang[2]; this->GetBackLightAngle(ang); return ang[0]; }; + + double GetBackLightAzimuth() { + double ang[2]; this->GetBackLightAngle(ang); return ang[1]; }; + + // Description: + // Add lights to, or remove lights from, a renderer. + // Lights may be added to more than one renderer, if desired. + void AddLightsToRenderer(vtkRenderer *renderer); + void RemoveLightsFromRenderer(vtkRenderer *renderer); + + void DeepCopy(vtkLightKit *kit); + + void Modified(); + void Update(); + + // Description: + // Helper method to go from a enum type to a string type + static const char *GetStringFromType(int type); + + // Description: + // Helper method to go from a enum subtype to a string subtype + static const char *GetStringFromSubType(int type); + + // Description: + // Helper method to go from a enum subtype to a string subtype + // The difference from GetStringFromSubType is that it returns + // a shorter strings (usefull for GUI with minimun space) + static const char *GetShortStringFromSubType(int subtype); + + // Description: + // Return the possible subtype from a given type. You have to pass + // in a number i [0,3] no check is done. + static LightKitSubType GetSubType(LightKitType type, int i); + +protected: + vtkLightKit(); + ~vtkLightKit(); + + void WarmthToRGBI(double w, double rgb[3], double& i); + void WarmthToRGB(double w, double rgb[3]); + void InitializeWarmthFunctions(); + double WarmthToIntensity(double w); + + + double KeyLightIntensity; + double KeyToFillRatio; + double KeyToHeadRatio; + double KeyToBackRatio; + + vtkLight *KeyLight; + double KeyLightWarmth; + double KeyLightAngle[2]; + double KeyLightColor[3]; + + vtkLight *FillLight; + double FillLightWarmth; + double FillLightAngle[2]; + double FillLightColor[3]; + + double BackLightWarmth; + double BackLightColor[3]; + + vtkLight *BackLight0; + vtkLight *BackLight1; + + double BackLightAngle[2]; + + vtkLight *HeadLight; + double HeadLightWarmth; + double HeadLightColor[3]; + + int MaintainLuminance; + + vtkPiecewiseFunction *WarmthFunction[4]; // r, g, b, perceptual length + +private: + vtkLightKit(const vtkLightKit&); // Not implemented. + void operator=(const vtkLightKit&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMapper.cxx b/Rendering/vtkMapper.cxx new file mode 100644 index 0000000..47e2b8b --- /dev/null +++ b/Rendering/vtkMapper.cxx @@ -0,0 +1,704 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMapper.h" + +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkLookupTable.h" +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkPointData.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkMapper, "$Revision: 1.120 $"); + +// Initialize static member that controls global immediate mode rendering +static int vtkMapperGlobalImmediateModeRendering = 0; + +// Initialize static member that controls global coincidence resolution +static int vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF; +static double vtkMapperGlobalResolveCoincidentTopologyZShift = 0.01; +static double vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = 1.0; +static double vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = 1.0; + +// Construct with initial range (0,1). +vtkMapper::vtkMapper() +{ + this->Colors = 0; + this->Static = 0; + this->LookupTable = 0; + + this->ScalarVisibility = 1; + this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0; + this->UseLookupTableScalarRange = 0; + + this->ImmediateModeRendering = 0; + + this->ColorMode = VTK_COLOR_MODE_DEFAULT; + this->ScalarMode = VTK_SCALAR_MODE_DEFAULT; + this->ScalarMaterialMode = VTK_MATERIALMODE_DEFAULT; + + vtkMath::UninitializeBounds(this->Bounds); + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + + this->RenderTime = 0.0; + + strcpy(this->ArrayName, ""); + this->ArrayId = -1; + this->ArrayComponent = 0; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; + + this->InterpolateScalarsBeforeMapping = 0; + this->ColorCoordinates = 0; + this->ColorTextureMap = 0; +} + +vtkMapper::~vtkMapper() +{ + if (this->LookupTable) + { + this->LookupTable->UnRegister(this); + } + if ( this->Colors != 0 ) + { + this->Colors->UnRegister(this); + } + if ( this->ColorCoordinates != 0 ) + { + this->ColorCoordinates->UnRegister(this); + } + if ( this->ColorTextureMap != 0 ) + { + this->ColorTextureMap->UnRegister(this); + } +} + +// Get the bounds for the input of this mapper as +// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkMapper::GetBounds() +{ + static double bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0}; + + vtkDataSet *input = this->GetInput(); + if ( ! input ) + { + return bounds; + } + else + { + if (!this->Static) + { + this->Update(); + } + input->GetBounds(this->Bounds); + return this->Bounds; + } +} + +vtkDataSet *vtkMapper::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkDataSet::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +void vtkMapper::SetGlobalImmediateModeRendering(int val) +{ + if (val == vtkMapperGlobalImmediateModeRendering) + { + return; + } + vtkMapperGlobalImmediateModeRendering = val; +} + +int vtkMapper::GetGlobalImmediateModeRendering() +{ + return vtkMapperGlobalImmediateModeRendering; +} + +void vtkMapper::SetResolveCoincidentTopology(int val) +{ + if (val == vtkMapperGlobalResolveCoincidentTopology) + { + return; + } + vtkMapperGlobalResolveCoincidentTopology = val; +} + +int vtkMapper::GetResolveCoincidentTopology() +{ + return vtkMapperGlobalResolveCoincidentTopology; +} + +void vtkMapper::SetResolveCoincidentTopologyToDefault() +{ + vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF; +} + +void vtkMapper::SetResolveCoincidentTopologyZShift(double val) +{ + if (val == vtkMapperGlobalResolveCoincidentTopologyZShift) + { + return; + } + vtkMapperGlobalResolveCoincidentTopologyZShift = val; +} + +double vtkMapper::GetResolveCoincidentTopologyZShift() +{ + return vtkMapperGlobalResolveCoincidentTopologyZShift; +} + +void vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters( + double factor, double units) +{ + if (factor == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor && + units == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits ) + { + return; + } + vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = factor; + vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = units; +} + +void vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters( + double& factor, double& units) +{ + factor = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor; + units = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits; +} + +// Overload standard modified time function. If lookup table is modified, +// then this object is modified as well. +unsigned long vtkMapper::GetMTime() +{ + //unsigned long mTime=this->MTime.GetMTime(); + unsigned long mTime=vtkAbstractMapper::GetMTime(); + unsigned long lutMTime; + + if ( this->LookupTable != NULL ) + { + lutMTime = this->LookupTable->GetMTime(); + mTime = ( lutMTime > mTime ? lutMTime : mTime ); + } + + return mTime; +} + +void vtkMapper::ShallowCopy(vtkAbstractMapper *mapper) +{ + vtkMapper *m = vtkMapper::SafeDownCast(mapper); + if ( m != NULL ) + { + this->SetLookupTable(m->GetLookupTable()); + this->SetScalarVisibility(m->GetScalarVisibility()); + this->SetScalarRange(m->GetScalarRange()); + this->SetColorMode(m->GetColorMode()); + this->SetScalarMode(m->GetScalarMode()); + this->SetScalarMaterialMode(m->GetScalarMaterialMode()); + this->SetImmediateModeRendering(m->GetImmediateModeRendering()); + this->SetUseLookupTableScalarRange(m->GetUseLookupTableScalarRange()); + if ( m->GetArrayAccessMode() == VTK_GET_ARRAY_BY_ID ) + { + this->ColorByArrayComponent(m->GetArrayId(),m->GetArrayComponent()); + } + else + { + this->ColorByArrayComponent(m->GetArrayName(),m->GetArrayComponent()); + } + } + + // Now do superclass + this->vtkAbstractMapper3D::ShallowCopy(mapper); + +} + +// a side effect of this is that this->Colors is also set +// to the return value +vtkUnsignedCharArray *vtkMapper::MapScalars(double alpha) +{ + int cellFlag = 0; + + vtkDataArray *scalars = vtkAbstractMapper:: + GetScalars(this->GetInput(), this->ScalarMode, this->ArrayAccessMode, + this->ArrayId, this->ArrayName, cellFlag); + + // This is for a legacy feature: selection of the array component to color by + // from the mapper. It is now in the lookuptable. When this feature + // is removed, we can remove this condition. + if (scalars == 0 || scalars->GetNumberOfComponents() <= this->ArrayComponent) + { + this->ArrayComponent = 0; + } + + if ( !this->ScalarVisibility || scalars==0 || this->GetInput()==0) + { // No scalar colors. + if ( this->ColorCoordinates ) + { + this->ColorCoordinates->UnRegister(this); + this->ColorCoordinates = 0; + } + if ( this->ColorTextureMap ) + { + this->ColorTextureMap->UnRegister(this); + this->ColorTextureMap = 0; + } + if ( this->Colors ) + { + this->Colors->UnRegister(this); + this->Colors = 0; + } + return 0; + } + + // Get the lookup table. + if ( scalars->GetLookupTable() ) + { + this->SetLookupTable(scalars->GetLookupTable()); + } + else + { + // make sure we have a lookup table + if ( this->LookupTable == 0 ) + { + this->CreateDefaultLookupTable(); + } + this->LookupTable->Build(); + } + if ( !this->UseLookupTableScalarRange ) + { + this->LookupTable->SetRange(this->ScalarRange); + } + + // Decide betweeen texture color or vertex color. + // Cell data always uses vertext color. + // Only point data can use both texture and vertext coloring. + if (this->InterpolateScalarsBeforeMapping && ! cellFlag) + { + // Only use texture color if we are mapping scalars. + // Directly coloring with RGB unsigned chars should not use texture. + if ( this->ColorMode != VTK_COLOR_MODE_DEFAULT || + (vtkUnsignedCharArray::SafeDownCast(scalars)) == 0 ) + { // Texture color option. + this->MapScalarsToTexture(scalars, alpha); + return 0; + } + } + + // Vertex colors are being used. + // Get rid of texure Color arrays. Only texture or vertex coloring + // can be active at one time. The existence of the array is the + // signal to use that technique. + if ( this->ColorCoordinates ) + { + this->ColorCoordinates->UnRegister(this); + this->ColorCoordinates = 0; + } + if ( this->ColorTextureMap ) + { + this->ColorTextureMap->UnRegister(this); + this->ColorTextureMap = 0; + } + + // Lets try to resuse the old colors. + if (this->Colors) + { + if (this->LookupTable && this->LookupTable->GetAlpha() == alpha) + { + if (this->GetMTime() < this->Colors->GetMTime() && + this->GetInput()->GetMTime() < this->Colors->GetMTime() && + this->LookupTable->GetMTime() < this->Colors->GetMTime()) + { + return this->Colors; + } + } + } + + // Get rid of old colors + if ( this->Colors ) + { + this->Colors->UnRegister(this); + this->Colors = 0; + } + + // map scalars + this->LookupTable->SetAlpha(alpha); + this->Colors = this->LookupTable-> + MapScalars(scalars, this->ColorMode, this->ArrayComponent); + // Consistent register and unregisters + this->Colors->Register(this); + this->Colors->Delete(); + + return this->Colors; +} + + +void vtkMapper::SelectColorArray(int arrayNum) +{ + this->ColorByArrayComponent(arrayNum, -1); +} + + +void vtkMapper::SelectColorArray(const char* arrayName) +{ + this->ColorByArrayComponent(arrayName, -1); +} + + +void vtkMapper::ColorByArrayComponent(int arrayNum, int component) +{ + if (this->ArrayId == arrayNum && component == this->ArrayComponent && + this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + return; + } + this->Modified(); + + this->ArrayId = arrayNum; + this->ArrayComponent = component; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +void vtkMapper::ColorByArrayComponent(const char* arrayName, int component) +{ + if (!arrayName || + ( strcmp(this->ArrayName, arrayName) == 0 && + component == this->ArrayComponent && + this->ArrayAccessMode == VTK_GET_ARRAY_BY_NAME )) + { + return; + } + this->Modified(); + + strcpy(this->ArrayName, arrayName); + this->ArrayComponent = component; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME; +} + +// Specify a lookup table for the mapper to use. +void vtkMapper::SetLookupTable(vtkScalarsToColors *lut) +{ + if ( this->LookupTable != lut ) + { + if ( this->LookupTable) + { + this->LookupTable->UnRegister(this); + } + this->LookupTable = lut; + if (lut) + { + lut->Register(this); + } + this->Modified(); + } +} + +vtkScalarsToColors *vtkMapper::GetLookupTable() +{ + if ( this->LookupTable == 0 ) + { + this->CreateDefaultLookupTable(); + } + return this->LookupTable; +} + +void vtkMapper::CreateDefaultLookupTable() +{ + if ( this->LookupTable) + { + this->LookupTable->UnRegister(this); + } + this->LookupTable = vtkLookupTable::New(); + // Consistent Register/UnRegisters. + this->LookupTable->Register(this); + this->LookupTable->Delete(); +} + +// Return the method of coloring scalar data. +const char *vtkMapper::GetColorModeAsString(void) +{ + if ( this->ColorMode == VTK_COLOR_MODE_MAP_SCALARS ) + { + return "MapScalars"; + } + else + { + return "Default"; + } +} + +// Return the method for obtaining scalar data. +const char *vtkMapper::GetScalarModeAsString(void) +{ + if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ) + { + return "UseCellData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA ) + { + return "UsePointFieldData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + return "UseCellFieldData"; + } + else + { + return "Default"; + } +} + +const char *vtkMapper::GetScalarMaterialModeAsString(void) +{ + if ( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ) + { + return "Ambient"; + } + else if ( this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ) + { + return "Diffuse"; + } + else if ( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE ) + { + return "Ambient and Diffuse"; + } + else + { + return "Default"; + } +} + + +template +void vtkMapperCreateColorTextureCoordinates(T* input, float* output, + vtkIdType num, int numComps, + int component, double* range) +{ + double tmp, sum; + double k = 1.0 / (range[1]-range[0]); + vtkIdType i; + int j; + + if (component < 0 || component >= numComps) + { + for (i = 0; i < num; ++i) + { + sum = 0; + for (j = 0; j < numComps; ++j) + { + tmp = (double)(*input); + sum += (tmp * tmp); + ++input; + } + output[i] = k * (sqrt(sum) - range[0]); + if (output[i] > 1.0) + { + output[i] = 1.0; + } + if (output[i] < 0.0) + { + output[i] = 0.0; + } + } + } + else + { + input += component; + for (i = 0; i < num; ++i) + { + output[i] = k * ((float)(*input) - range[0]); + if (output[i] > 1.0) + { + output[i] = 1.0; + } + if (output[i] < 0.0) + { + output[i] = 0.0; + } + input = input + numComps; + } + } +} + + +#define ColorTextureMapSize 256 +// a side effect of this is that this->ColorCoordinates and +// this->ColorTexture are set. +void vtkMapper::MapScalarsToTexture(vtkDataArray* scalars, double alpha) +{ + double* range = this->LookupTable->GetRange(); + + // Get rid of vertex color array. Only texture or vertex coloring + // can be active at one time. The existence of the array is the + // signal to use that technique. + if ( this->Colors ) + { + this->Colors->UnRegister(this); + this->Colors = 0; + } + + // If the lookup table has changed, the recreate the color texture map. + // Set a new lookup table changes this->MTime. + if (this->ColorTextureMap == 0 || + this->GetMTime() > this->ColorTextureMap->GetMTime() || + this->LookupTable->GetMTime() > this->ColorTextureMap->GetMTime() || + this->LookupTable->GetAlpha() != alpha) + { + this->LookupTable->SetAlpha(alpha); + if ( this->ColorTextureMap ) + { + this->ColorTextureMap->UnRegister(this); + this->ColorTextureMap = 0; + } + // Get the texture map from the lookup table. + // Create a dummy ramp of scalars. + // In the future, we could extend vtkScalarsToColors. + double k = (range[1]-range[0]) / (double)(ColorTextureMapSize-1); + vtkFloatArray* tmp = vtkFloatArray::New(); + tmp->SetNumberOfTuples(ColorTextureMapSize); + float* ptr = tmp->GetPointer(0); + for (int i = 0; i < ColorTextureMapSize; ++i) + { + *ptr = range[0] + ((float)(i)) * k; + ++ptr; + } + this->ColorTextureMap = vtkImageData::New(); + this->ColorTextureMap->SetExtent(0,ColorTextureMapSize-1, + 0,0, 0,0); + this->ColorTextureMap->SetNumberOfScalarComponents(4); + this->ColorTextureMap->SetScalarTypeToUnsignedChar(); + this->ColorTextureMap->GetPointData()->SetScalars( + this->LookupTable->MapScalars(tmp, this->ColorMode, 0)); + // Do we need to delete the scalars? + this->ColorTextureMap->GetPointData()->GetScalars()->Delete(); + // Consistent register and unregisters + this->ColorTextureMap->Register(this); + this->ColorTextureMap->Delete(); + tmp->Delete(); + } + + // Create new coordinates if necessary. + // Need to compare lookup table incase the range has changed. + if (this->ColorCoordinates == 0 || + this->GetMTime() > this->ColorCoordinates->GetMTime() || + this->GetInput()->GetMTime() > this->ColorCoordinates->GetMTime() || + this->LookupTable->GetMTime() > this->ColorCoordinates->GetMTime()) + { + // Get rid of old colors + if ( this->ColorCoordinates ) + { + this->ColorCoordinates->UnRegister(this); + this->ColorCoordinates = 0; + } + + // Now create the color texture coordinates. + int numComps = scalars->GetNumberOfComponents(); + void* input = scalars->GetVoidPointer(0); + vtkIdType num = scalars->GetNumberOfTuples(); + this->ColorCoordinates = vtkFloatArray::New(); + this->ColorCoordinates->SetNumberOfTuples(num); + float* output = this->ColorCoordinates->GetPointer(0); + int scalarComponent; + // Although I like the feature of applying magnitude to single component + // scalars, it is not how the old MapScalars for vertex coloring works. + if (this->LookupTable->GetVectorMode() == vtkScalarsToColors::MAGNITUDE && + scalars->GetNumberOfComponents() > 1) + { + scalarComponent = -1; + } + else + { + scalarComponent = this->LookupTable->GetVectorComponent(); + } + switch (scalars->GetDataType()) + { + vtkTemplateMacro( + vtkMapperCreateColorTextureCoordinates(static_cast(input), + output, num, numComps, + scalarComponent, range) + ); + case VTK_BIT: + vtkErrorMacro("Cannot color by bit array."); + break; + default: + vtkErrorMacro(<< "Unknown input ScalarType"); + return; + } + } +} + +void vtkMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->LookupTable ) + { + os << indent << "Lookup Table:\n"; + this->LookupTable->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Lookup Table: (none)\n"; + } + + os << indent << "Immediate Mode Rendering: " + << (this->ImmediateModeRendering ? "On\n" : "Off\n"); + os << indent << "Global Immediate Mode Rendering: " << + (vtkMapperGlobalImmediateModeRendering ? "On\n" : "Off\n"); + + os << indent << "Scalar Visibility: " + << (this->ScalarVisibility ? "On\n" : "Off\n"); + + os << indent << "Static: " + << (this->Static ? "On\n" : "Off\n"); + + double *range = this->GetScalarRange(); + os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n"; + + os << indent << "UseLookupTableScalarRange: " + << this->UseLookupTableScalarRange << "\n"; + + os << indent << "Color Mode: " << this->GetColorModeAsString() << endl; + os << indent << "InterpolateScalarsBeforeMapping: " + << (this->InterpolateScalarsBeforeMapping ? "On\n" : "Off\n"); + + os << indent << "Scalar Mode: " << this->GetScalarModeAsString() << endl; + + os << indent << "LM Color Mode: " + << this->GetScalarMaterialModeAsString() << endl; + + os << indent << "RenderTime: " << this->RenderTime << endl; + + os << indent << "Resolve Coincident Topology: "; + if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_OFF ) + { + os << "Off" << endl; + } + else if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_POLYGON_OFFSET ) + { + os << "Polygon Offset" << endl; + } + else + { + os << "Shift Z-Buffer" << endl; + } +} diff --git a/Rendering/vtkMapper.h b/Rendering/vtkMapper.h new file mode 100644 index 0000000..4f3e5a1 --- /dev/null +++ b/Rendering/vtkMapper.h @@ -0,0 +1,384 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMapper - abstract class specifies interface to map data to graphics primitives +// .SECTION Description +// vtkMapper is an abstract class to specify interface between data and +// graphics primitives. Subclasses of vtkMapper map data through a +// lookuptable and control the creation of rendering primitives that +// interface to the graphics library. The mapping can be controlled by +// supplying a lookup table and specifying a scalar range to map data +// through. +// +// There are several important control mechanisms affecting the behavior of +// this object. The ScalarVisibility flag controls whether scalar data (if +// any) controls the color of the associated actor(s) that refer to the +// mapper. The ScalarMode ivar is used to determine whether scalar point data +// or cell data is used to color the object. By default, point data scalars +// are used unless there are none, in which cell scalars are used. Or you can +// explicitly control whether to use point or cell scalar data. Finally, the +// mapping of scalars through the lookup table varies depending on the +// setting of the ColorMode flag. See the documentation for the appropriate +// methods for an explanation. +// +// Another important feature of this class is whether to use immediate mode +// rendering (ImmediateModeRenderingOn) or display list rendering +// (ImmediateModeRenderingOff). If display lists are used, a data structure +// is constructed (generally in the rendering library) which can then be +// rapidly traversed and rendered by the rendering library. The disadvantage +// of display lists is that they require additionally memory which may affect +// the performance of the system. +// +// Another important feature of the mapper is the ability to shift the +// z-buffer to resolve coincident topology. For example, if you'd like to +// draw a mesh with some edges a different color, and the edges lie on the +// mesh, this feature can be useful to get nice looking lines. (See the +// ResolveCoincidentTopology-related methods.) + +// .SECTION See Also +// vtkDataSetMapper vtkPolyDataMapper + +#ifndef __vtkMapper_h +#define __vtkMapper_h + +#include "vtkAbstractMapper3D.h" +#include "vtkScalarsToColors.h" // For VTK_COLOR_MODE_DEFAULT and _MAP_SCALARS + +#define VTK_RESOLVE_OFF 0 +#define VTK_RESOLVE_POLYGON_OFFSET 1 +#define VTK_RESOLVE_SHIFT_ZBUFFER 2 + +#define VTK_GET_ARRAY_BY_ID 0 +#define VTK_GET_ARRAY_BY_NAME 1 + +#define VTK_MATERIALMODE_DEFAULT 0 +#define VTK_MATERIALMODE_AMBIENT 1 +#define VTK_MATERIALMODE_DIFFUSE 2 +#define VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE 3 + +class vtkWindow; +class vtkRenderer; +class vtkActor; +class vtkDataSet; +class vtkFloatArray; +class vtkImageData; + +class VTK_RENDERING_EXPORT vtkMapper : public vtkAbstractMapper3D +{ +public: + vtkTypeRevisionMacro(vtkMapper,vtkAbstractMapper3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Make a shallow copy of this mapper. + void ShallowCopy(vtkAbstractMapper *m); + + // Description: + // Overload standard modified time function. If lookup table is modified, + // then this object is modified as well. + unsigned long GetMTime(); + + // Description: + // Method initiates the mapping process. Generally sent by the actor + // as each frame is rendered. + virtual void Render(vtkRenderer *ren, vtkActor *a) = 0; + + // Description: + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *) {}; + + // Description: + // Specify a lookup table for the mapper to use. + void SetLookupTable(vtkScalarsToColors *lut); + vtkScalarsToColors *GetLookupTable(); + + // Description: + // Create default lookup table. Generally used to create one when none + // is available with the scalar data. + virtual void CreateDefaultLookupTable(); + + // Description: + // Turn on/off flag to control whether scalar data is used to color objects. + vtkSetMacro(ScalarVisibility,int); + vtkGetMacro(ScalarVisibility,int); + vtkBooleanMacro(ScalarVisibility,int); + + // Description: + // Turn on/off flag to control whether the mapper's data is static. Static data + // means that the mapper does not propagate updates down the pipeline, greatly + // decreasing the time it takes to update many mappers. This should only be + // used if the data never changes. + vtkSetMacro(Static,int); + vtkGetMacro(Static,int); + vtkBooleanMacro(Static,int); + + // Description: + // Control how the scalar data is mapped to colors. By default + // (ColorModeToDefault), unsigned char scalars are treated as colors, and + // NOT mapped through the lookup table, while everything else is. Setting + // ColorModeToMapScalars means that all scalar data will be mapped through + // the lookup table. (Note that for multi-component scalars, the + // particular component to use for mapping can be specified using the + // SelectColorArray() method.) + vtkSetMacro(ColorMode,int); + vtkGetMacro(ColorMode,int); + void SetColorModeToDefault() + {this->SetColorMode(VTK_COLOR_MODE_DEFAULT);}; + void SetColorModeToMapScalars() + {this->SetColorMode(VTK_COLOR_MODE_MAP_SCALARS);}; + + // Description: + // Return the method of coloring scalar data. + const char *GetColorModeAsString(); + + // Description: + // By default, vertex color is used to map colors to a surface. + // Colors are interpolated after being mapped. + // This option avoids color interpolation by using a one dimensional + // texture map for the colors. + vtkSetMacro(InterpolateScalarsBeforeMapping,int); + vtkGetMacro(InterpolateScalarsBeforeMapping,int); + vtkBooleanMacro(InterpolateScalarsBeforeMapping,int); + + // Description: + // Control whether the mapper sets the lookuptable range based on its + // own ScalarRange, or whether it will use the LookupTable ScalarRange + // regardless of it's own setting. By default the Mapper is allowed to set + // the LookupTable range, but users who are sharing LookupTables between + // mappers/actors will probably wish to force the mapper to use the + // LookupTable unchanged. + vtkSetMacro(UseLookupTableScalarRange,int); + vtkGetMacro(UseLookupTableScalarRange,int); + vtkBooleanMacro(UseLookupTableScalarRange,int); + + // Description: + // Specify range in terms of scalar minimum and maximum (smin,smax). These + // values are used to map scalars into lookup table. Has no effect when + // UseLookupTableScalarRange is true. + vtkSetVector2Macro(ScalarRange,double); + vtkGetVectorMacro(ScalarRange,double,2); + + // Description: + // Turn on/off flag to control whether data is rendered using + // immediate mode or note. Immediate mode rendering + // tends to be slower but it can handle larger datasets. + // The default value is immediate mode off. If you are + // having problems rendering a large dataset you might + // want to consider using immediate more rendering. + vtkSetMacro(ImmediateModeRendering,int); + vtkGetMacro(ImmediateModeRendering,int); + vtkBooleanMacro(ImmediateModeRendering,int); + + // Description: + // Turn on/off flag to control whether data is rendered using + // immediate mode or note. Immediate mode rendering + // tends to be slower but it can handle larger datasets. + // The default value is immediate mode off. If you are + // having problems rendering a large dataset you might + // want to consider using immediate more rendering. + static void SetGlobalImmediateModeRendering(int val); + static void GlobalImmediateModeRenderingOn() + {vtkMapper::SetGlobalImmediateModeRendering(1);}; + static void GlobalImmediateModeRenderingOff() + {vtkMapper::SetGlobalImmediateModeRendering(0);}; + static int GetGlobalImmediateModeRendering(); + + // Description: + // Control how the filter works with scalar point data and cell attribute + // data. By default (ScalarModeToDefault), the filter will use point data, + // and if no point data is available, then cell data is used. Alternatively + // you can explicitly set the filter to use point data + // (ScalarModeToUsePointData) or cell data (ScalarModeToUseCellData). + // You can also choose to get the scalars from an array in point field + // data (ScalarModeToUsePointFieldData) or cell field data + // (ScalarModeToUseCellFieldData). If scalars are coming from a field + // data array, you must call SelectColorArray before you call + // GetColors. + // When ScalarMode is set to use Field Data (ScalarModeToFieldData), you + // must call SelectColorArray to choose the field data array to be used to + // color cells. In this mode, if the poly data has triangle strips, + // the field data is treated as the celldata for each mini-cell formed by + // a triangle in the strip rather than the entire strip. + vtkSetMacro(ScalarMode,int); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToDefault() { + this->SetScalarMode(VTK_SCALAR_MODE_DEFAULT);}; + void SetScalarModeToUsePointData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA);}; + void SetScalarModeToUseCellData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_DATA);}; + void SetScalarModeToUsePointFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA);}; + void SetScalarModeToUseCellFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA);}; + void SetScalarModeToUseFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_FIELD_DATA); } + + // Description: + // When ScalarMode is set to UsePointFileData or UseCellFieldData, + // you can specify which array to use for coloring using these methods. + // The lookup table will decide how to convert vectors to colors. + void SelectColorArray(int arrayNum); + void SelectColorArray(const char* arrayName); + + // Description: + // Legacy: + // These methods used to be used to specify the array component. + // It is better to do this in the lookup table. + void ColorByArrayComponent(int arrayNum, int component); + void ColorByArrayComponent(const char* arrayName, int component); + + // Description: + // Get the array name or number and component to color by. + char* GetArrayName() { return this->ArrayName; } + int GetArrayId() { return this->ArrayId; } + int GetArrayAccessMode() { return this->ArrayAccessMode; } + int GetArrayComponent() { return this->ArrayComponent; } + + // Description: + // Return the method for obtaining scalar data. + const char *GetScalarModeAsString(); + + // Description: + // Set/Get a global flag that controls whether coincident topology (e.g., a + // line on top of a polygon) is shifted to avoid z-buffer resolution (and + // hence rendering problems). If not off, there are two methods to choose + // from. PolygonOffset uses graphics systems calls to shift polygons, but + // does not distinguish vertices and lines from one another. ShiftZBuffer + // remaps the z-buffer to distinguish vertices, lines, and polygons, but + // does not always produce acceptable results. If you use the ShiftZBuffer + // approach, you may also want to set the ResolveCoincidentTopologyZShift + // value. (Note: not all mappers/graphics systems implement this + // functionality.) + static void SetResolveCoincidentTopology(int val); + static int GetResolveCoincidentTopology(); + static void SetResolveCoincidentTopologyToDefault(); + static void SetResolveCoincidentTopologyToOff() + {SetResolveCoincidentTopology(VTK_RESOLVE_OFF);} + static void SetResolveCoincidentTopologyToPolygonOffset() + {SetResolveCoincidentTopology(VTK_RESOLVE_POLYGON_OFFSET);} + static void SetResolveCoincidentTopologyToShiftZBuffer() + {SetResolveCoincidentTopology(VTK_RESOLVE_SHIFT_ZBUFFER);} + + // Description: + // Used to set the polygon offset scale factor and units. + // Used when ResolveCoincidentTopology is set to PolygonOffset. + // These are global variables. + static void SetResolveCoincidentTopologyPolygonOffsetParameters( + double factor, double units); + static void GetResolveCoincidentTopologyPolygonOffsetParameters( + double& factor, double& units); + + // Description: + // Used to set the z-shift if ResolveCoincidentTopology is set to + // ShiftZBuffer. This is a global variable. + static void SetResolveCoincidentTopologyZShift(double val); + static double GetResolveCoincidentTopologyZShift(); + + // Description: + // Return bounding box (array of six doubles) of data expressed as + // (xmin,xmax, ymin,ymax, zmin,zmax). + virtual double *GetBounds(); + virtual void GetBounds(double bounds[6]) + {this->vtkAbstractMapper3D::GetBounds(bounds);}; + + // Description: + // This instance variable is used by vtkLODActor to determine which + // mapper to use. It is an estimate of the time necessary to render. + // Setting the render time does not modify the mapper. + void SetRenderTime(double time) {this->RenderTime = time;} + vtkGetMacro(RenderTime, double); + + //BTX + // Description: + // Get the input as a vtkDataSet. This method is overridden in + // the specialized mapper classes to return more specific data types. + vtkDataSet *GetInput(); + //ETX + + // Description: + // Get the input to this mapper as a vtkDataSet, instead of as a + // more specialized data type that the subclass may return from + // GetInput(). This method is provided for use in the wrapper languages, + // C++ programmers should use GetInput() instead. + vtkDataSet *GetInputAsDataSet() + {return this->GetInput();} + + // Description: + // Map the scalars (if there are any scalars and ScalarVisibility is on) + // through the lookup table, returning an unsigned char RGBA array. This is + // typically done as part of the rendering process. The alpha parameter + // allows the blending of the scalars with an additional alpha (typically + // which comes from a vtkActor, etc.) + vtkUnsignedCharArray *MapScalars(double alpha); + + // Description: + // Set/Get the light-model color mode. + vtkSetMacro(ScalarMaterialMode,int); + vtkGetMacro(ScalarMaterialMode,int); + void SetScalarMaterialModeToDefault() + {this->SetScalarMaterialMode(VTK_MATERIALMODE_DEFAULT);}; + void SetScalarMaterialModeToAmbient() + {this->SetScalarMaterialMode(VTK_MATERIALMODE_AMBIENT);}; + void SetScalarMaterialModeToDiffuse() + {this->SetScalarMaterialMode(VTK_MATERIALMODE_DIFFUSE);}; + void SetScalarMaterialModeToAmbientAndDiffuse() + {this->SetScalarMaterialMode(VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE);}; + + // Description: + // Return the light-model color mode. + const char *GetScalarMaterialModeAsString(); + +protected: + vtkMapper(); + ~vtkMapper(); + + vtkUnsignedCharArray *Colors; + + // Use texture coordinates for coloring. + int InterpolateScalarsBeforeMapping; + // Coordinate for each point. + vtkFloatArray *ColorCoordinates; + // 1D ColorMap used for the texture image. + vtkImageData* ColorTextureMap; + void MapScalarsToTexture(vtkDataArray* scalars, double alpha); + + vtkScalarsToColors *LookupTable; + int ScalarVisibility; + vtkTimeStamp BuildTime; + double ScalarRange[2]; + int UseLookupTableScalarRange; + int ImmediateModeRendering; + int ColorMode; + int ScalarMode; + int ScalarMaterialMode; + + double RenderTime; + + // for coloring by a component of a field data array + int ArrayId; + char ArrayName[256]; + int ArrayComponent; + int ArrayAccessMode; + + int Static; + +private: + vtkMapper(const vtkMapper&); // Not implemented. + void operator=(const vtkMapper&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMapperCollection.cxx b/Rendering/vtkMapperCollection.cxx new file mode 100644 index 0000000..ebeaf29 --- /dev/null +++ b/Rendering/vtkMapperCollection.cxx @@ -0,0 +1,24 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMapperCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkMapperCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkMapperCollection, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkMapperCollection); + +void vtkMapperCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkMapperCollection.h b/Rendering/vtkMapperCollection.h new file mode 100644 index 0000000..9a15808 --- /dev/null +++ b/Rendering/vtkMapperCollection.h @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMapperCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMapperCollection - a list of mappers +// .SECTION Description +// vtkMapperCollection represents and provides methods to manipulate a list of +// mappers (i.e., vtkMapper and subclasses). The list is unsorted and duplicate +// entries are not prevented. + +// .SECTION see also +// vtkMapper vtkCollection + +#ifndef __vtkMapperC_h +#define __vtkMapperC_h + +#include "vtkCollection.h" +#include "vtkMapper.h" // Needed for direct access to mapper methods in + // inline functions + +class VTK_RENDERING_EXPORT vtkMapperCollection : public vtkCollection +{ + public: + static vtkMapperCollection *New(); + vtkTypeRevisionMacro(vtkMapperCollection,vtkCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add an mapper to the list. + void AddItem(vtkMapper *a) { + this->vtkCollection::AddItem(static_cast(a));}; + + // Description: + // Get the next mapper in the list. + vtkMapper *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + // Description: + // Get the last mapper in the list. + vtkMapper *GetLastItem(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkMapper *GetNextMapper(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkMapperCollection() {}; + ~vtkMapperCollection() {}; + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkMapperCollection(const vtkMapperCollection&); // Not implemented. + void operator=(const vtkMapperCollection&); // Not implemented. +}; + + +inline vtkMapper *vtkMapperCollection::GetLastItem() +{ + if ( this->Bottom == NULL ) + { + return NULL; + } + else + { + return static_cast(this->Bottom->Item); + } +} + +#endif + + + + + diff --git a/Rendering/vtkMesaActor.cxx b/Rendering/vtkMesaActor.cxx new file mode 100644 index 0000000..3929853 --- /dev/null +++ b/Rendering/vtkMesaActor.cxx @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This keeps the New method from being defined in included cxx file. +#define VTK_IMPLEMENT_MESA_CXX +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaActor.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaActor classes defined. +#include "vtkOpenGLActor.h" +#include "vtkMesaActor.h" + +// Make sure vtkMesaActor is a copy of vtkOpenGLActor +// with vtkOpenGLActor replaced with vtkMesaActor +#define vtkOpenGLActor vtkMesaActor +#include "vtkOpenGLActor.cxx" +#undef vtkOpenGLActor + +vtkCxxRevisionMacro(vtkMesaActor, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkMesaActor); + +vtkProperty* vtkMesaActor::MakeProperty() +{ + return vtkMesaProperty::New(); +} diff --git a/Rendering/vtkMesaActor.h b/Rendering/vtkMesaActor.h new file mode 100644 index 0000000..392369a --- /dev/null +++ b/Rendering/vtkMesaActor.h @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaActor - Mesa actor +// .SECTION Description +// vtkMesaActor is a concrete implementation of the abstract class vtkActor. +// vtkMesaActor interfaces to the Mesa rendering library. + +#ifndef __vtkMesaActor_h +#define __vtkMesaActor_h + +#include "vtkActor.h" + +class vtkMesaRenderer; + +class VTK_RENDERING_EXPORT vtkMesaActor : public vtkActor +{ +protected: + +public: + static vtkMesaActor *New(); + vtkTypeRevisionMacro(vtkMesaActor,vtkActor); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Actual actor render method. + void Render(vtkRenderer *ren, vtkMapper *mapper); + + // Description: + // Create a vtkMesaProperty, used by the super class to + // create a compatible class with the vtkMesaActor. + vtkProperty* MakeProperty(); +protected: + vtkMesaActor() {}; + ~vtkMesaActor() {}; + +private: + vtkMesaActor(const vtkMesaActor&); // Not implemented. + void operator=(const vtkMesaActor&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkMesaCamera.cxx b/Rendering/vtkMesaCamera.cxx new file mode 100644 index 0000000..e78f4db --- /dev/null +++ b/Rendering/vtkMesaCamera.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaCamera.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This keeps the New method from being defined in included cxx file. +#define VTK_IMPLEMENT_MESA_CXX +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaCamera.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaCamera classes defined. +#include "vtkOpenGLCamera.h" +#include "vtkMesaCamera.h" + +// Make sure vtkMesaCamera is a copy of vtkOpenGLCamera +// with vtkOpenGLCamera replaced with vtkMesaCamera +#define vtkOpenGLCamera vtkMesaCamera +#include "vtkOpenGLCamera.cxx" +#undef vtkOpenGLCamera + +vtkCxxRevisionMacro(vtkMesaCamera, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkMesaCamera); diff --git a/Rendering/vtkMesaCamera.h b/Rendering/vtkMesaCamera.h new file mode 100644 index 0000000..30aa89d --- /dev/null +++ b/Rendering/vtkMesaCamera.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaCamera.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaCamera - Mesa camera +// .SECTION Description +// vtkMesaCamera is a concrete implementation of the abstract class +// vtkCamera. vtkMesaCamera interfaces to the Mesa rendering library. + +#ifndef __vtkMesaCamera_h +#define __vtkMesaCamera_h + +#include "vtkCamera.h" + +class vtkMesaRenderer; + +class VTK_RENDERING_EXPORT vtkMesaCamera : public vtkCamera +{ +public: + static vtkMesaCamera *New(); + vtkTypeRevisionMacro(vtkMesaCamera,vtkCamera); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Render(vtkRenderer *ren); + + void UpdateViewport(vtkRenderer *ren); + +protected: + vtkMesaCamera() {}; + ~vtkMesaCamera() {}; +private: + vtkMesaCamera(const vtkMesaCamera&); // Not implemented. + void operator=(const vtkMesaCamera&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMesaFreeTypeTextMapper.cxx b/Rendering/vtkMesaFreeTypeTextMapper.cxx new file mode 100644 index 0000000..9c4c432 --- /dev/null +++ b/Rendering/vtkMesaFreeTypeTextMapper.cxx @@ -0,0 +1,44 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaFreeTypeTextMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" + +#include "vtkMesaFreeTypeTextMapper.h" + +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaFreeTypeTextMapper classes defined. +#include "vtkOpenGLFreeTypeTextMapper.h" +#include "vtkMesaFreeTypeTextMapper.h" + +// Make sure vtkMesaFreeTypeTextMapper is a copy of vtkOpenGLFreeTypeTextMapper +// with vtkOpenGLFreeTypeTextMapper replaced with vtkMesaFreeTypeTextMapper +#define vtkOpenGLFreeTypeTextMapper vtkMesaFreeTypeTextMapper +#include "vtkOpenGLFreeTypeTextMapper.cxx" +#undef vtkOpenGLFreeTypeTextMapper + +vtkCxxRevisionMacro(vtkMesaFreeTypeTextMapper, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkMesaFreeTypeTextMapper); diff --git a/Rendering/vtkMesaFreeTypeTextMapper.h b/Rendering/vtkMesaFreeTypeTextMapper.h new file mode 100644 index 0000000..abd5247 --- /dev/null +++ b/Rendering/vtkMesaFreeTypeTextMapper.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaFreeTypeTextMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaFreeTypeTextMapper - 2D Text annotation support +// .SECTION Description +// vtkMesaFreeTypeTextMapper provides 2D text annotation support for VTK +// using the FreeType and FTGL libraries. Normally the user should use +// vtktextMapper which in turn will use this class. + +// .SECTION See Also +// vtkTextMapper + +#ifndef __vtkMesaFreeTypeTextMapper_h +#define __vtkMesaFreeTypeTextMapper_h + +#include "vtkTextMapper.h" + +//BTX +class FTFont; +//ETX + +class VTK_RENDERING_EXPORT vtkMesaFreeTypeTextMapper : public vtkTextMapper +{ +public: + vtkTypeRevisionMacro(vtkMesaFreeTypeTextMapper,vtkTextMapper); + static vtkMesaFreeTypeTextMapper *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Actally draw the text. + void RenderOverlay(vtkViewport* viewport, vtkActor2D* actor); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // What is the size of the rectangle required to draw this + // mapper ? + virtual void GetSize(vtkViewport* viewport, int size[2]); + +protected: + vtkMesaFreeTypeTextMapper(); + ~vtkMesaFreeTypeTextMapper(); + + vtkTimeStamp SizeBuildTime; + int LastSize[2]; + int LastLargestDescender; + +private: + vtkMesaFreeTypeTextMapper(const vtkMesaFreeTypeTextMapper&); // Not implemented. + void operator=(const vtkMesaFreeTypeTextMapper&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMesaImageActor.cxx b/Rendering/vtkMesaImageActor.cxx new file mode 100644 index 0000000..9b6214c --- /dev/null +++ b/Rendering/vtkMesaImageActor.cxx @@ -0,0 +1,44 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaImageActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This keeps the New method from being defined in included cxx file. +#define VTK_IMPLEMENT_MESA_CXX +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaImageActor.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaImageActor classes defined. +#include "vtkOpenGLImageActor.h" +#include "vtkMesaImageActor.h" + +// Make sure vtkMesaImageActor is a copy of vtkOpenGLImageActor +// with vtkOpenGLImageActor replaced with vtkMesaImageActor +#define vtkOpenGLImageActor vtkMesaImageActor +#define vtkOpenGLRenderWindow vtkMesaRenderWindow +#include "vtkOpenGLImageActor.cxx" +#undef vtkOpenGLImageActor +#undef vtkOpenGLRenderWindow + +vtkCxxRevisionMacro(vtkMesaImageActor, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkMesaImageActor); diff --git a/Rendering/vtkMesaImageActor.h b/Rendering/vtkMesaImageActor.h new file mode 100644 index 0000000..922f4cb --- /dev/null +++ b/Rendering/vtkMesaImageActor.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaImageActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaImageActor - Mesa texture map +// .SECTION Description +// vtkMesaImageActor is a concrete implementation of the abstract class +// vtkImageActor. vtkMesaImageActor interfaces to the Mesa rendering library. + +#ifndef __vtkMesaImageActor_h +#define __vtkMesaImageActor_h + +#include "vtkImageActor.h" + +class vtkWindow; +class vtkMesaRenderer; +class vtkRenderWindow; + +class VTK_RENDERING_EXPORT vtkMesaImageActor : public vtkImageActor +{ +public: + static vtkMesaImageActor *New(); + vtkTypeRevisionMacro(vtkMesaImageActor,vtkImageActor); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Load(vtkRenderer *ren); + + // Description: + // Implement base class method. + void Render(vtkRenderer *ren); + + // Description: + // Release any graphics resources that are being consumed by this texture. + // The parameter window could be used to determine which graphic + // resources to release. Using the same texture object in multiple + // render windows is NOT currently supported. + void ReleaseGraphicsResources(vtkWindow *); + +protected: + vtkMesaImageActor(); + ~vtkMesaImageActor(); + + unsigned char *MakeDataSuitable(int &xsize, int &ysize, + int &release, int &reuseTexture); + + vtkTimeStamp LoadTime; + long Index; + static long GlobalIndex; + vtkRenderWindow *RenderWindow; // RenderWindow used for previous render + double Coords[12]; + double TCoords[8]; + int TextureSize[2]; + + // Non-recursive internal method + void InternalRender(vtkRenderer *ren); + + // Is a certain size texture supported? + int TextureSizeOK( int size[2] ); + +private: + vtkMesaImageActor(const vtkMesaImageActor&); // Not implemented. + void operator=(const vtkMesaImageActor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMesaImageMapper.cxx b/Rendering/vtkMesaImageMapper.cxx new file mode 100644 index 0000000..e54561b --- /dev/null +++ b/Rendering/vtkMesaImageMapper.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaImageMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// This keeps the New method from being defined in included cxx file. +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaImageMapper.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaImageMapper classes defined. +#include "vtkOpenGLImageMapper.h" +#include "vtkMesaImageMapper.h" + +// Make sure vtkMesaImageMapper is a copy of vtkOpenGLImageMapper +// with vtkOpenGLImageMapper replaced with vtkMesaImageMapper +#define vtkOpenGLImageMapper vtkMesaImageMapper +#include "vtkOpenGLImageMapper.cxx" +#undef vtkOpenGLImageMapper + +vtkCxxRevisionMacro(vtkMesaImageMapper, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkMesaImageMapper); diff --git a/Rendering/vtkMesaImageMapper.h b/Rendering/vtkMesaImageMapper.h new file mode 100644 index 0000000..05aaf63 --- /dev/null +++ b/Rendering/vtkMesaImageMapper.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaImageMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaImageMapper - 2D image display support for Mesa +// .SECTION Description +// vtkMesaImageMapper is a concrete subclass of vtkImageMapper that +// renders images under Mesa + +// .SECTION See Also +// vtkImageMapper + +#ifndef __vtkMesaImageMapper_h +#define __vtkMesaImageMapper_h + + +#include "vtkImageMapper.h" +class vtkActor2D; + + +class VTK_RENDERING_EXPORT vtkMesaImageMapper : public vtkImageMapper +{ +public: + static vtkMesaImageMapper *New(); + vtkTypeRevisionMacro(vtkMesaImageMapper,vtkImageMapper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Handle the render method. + void RenderOpaqueGeometry(vtkViewport* viewport, vtkActor2D* actor) { + this->RenderStart(viewport,actor);} + + // Description: + // Called by the Render function in vtkImageMapper. Actually draws + // the image to the screen. + void RenderData(vtkViewport* viewport, vtkImageData* data, + vtkActor2D* actor); + +protected: + vtkMesaImageMapper(); + ~vtkMesaImageMapper(); + +private: + vtkMesaImageMapper(const vtkMesaImageMapper&); // Not implemented. + void operator=(const vtkMesaImageMapper&); // Not implemented. +}; + + +#endif + + + + + + + + + diff --git a/Rendering/vtkMesaLight.cxx b/Rendering/vtkMesaLight.cxx new file mode 100644 index 0000000..b7d269c --- /dev/null +++ b/Rendering/vtkMesaLight.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaLight.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaLight.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaLight classes defined. +#include "vtkOpenGLLight.h" +#include "vtkMesaLight.h" + +// Make sure vtkMesaLight is a copy of vtkOpenGLLight +// with vtkOpenGLLight replaced with vtkMesaLight +#define vtkOpenGLLight vtkMesaLight +#include "vtkOpenGLLight.cxx" +#undef vtkOpenGLLight + +vtkCxxRevisionMacro(vtkMesaLight, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkMesaLight); diff --git a/Rendering/vtkMesaLight.h b/Rendering/vtkMesaLight.h new file mode 100644 index 0000000..91ac295 --- /dev/null +++ b/Rendering/vtkMesaLight.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaLight.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaLight - Mesa light +// .SECTION Description +// vtkMesaLight is a concrete implementation of the abstract class vtkLight. +// vtkMesaLight interfaces to the Mesa rendering library. + +#ifndef __vtkMesaLight_h +#define __vtkMesaLight_h + +#include "vtkLight.h" + +class vtkMesaRenderer; + +class VTK_RENDERING_EXPORT vtkMesaLight : public vtkLight +{ +public: + static vtkMesaLight *New(); + vtkTypeRevisionMacro(vtkMesaLight,vtkLight); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Render(vtkRenderer *ren,int light_index); + +protected: + vtkMesaLight() {}; + ~vtkMesaLight() {}; +private: + vtkMesaLight(const vtkMesaLight&); // Not implemented. + void operator=(const vtkMesaLight&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkMesaPolyDataMapper.cxx b/Rendering/vtkMesaPolyDataMapper.cxx new file mode 100644 index 0000000..aaf0a14 --- /dev/null +++ b/Rendering/vtkMesaPolyDataMapper.cxx @@ -0,0 +1,52 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaPolyDataMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkMesaPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" +#include "vtkToolkits.h" + + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaPolyDataMapper classes defined. +#include "vtkOpenGLPolyDataMapper.h" +#include "vtkMesaPolyDataMapper.h" + +// Make sure vtkMesaPolyDataMapper is a copy of vtkOpenGLPolyDataMapper +// with vtkOpenGLPolyDataMapper replaced with vtkMesaPolyDataMapper +#define vtkOpenGLPolyDataMapper vtkMesaPolyDataMapper +#define vtkOpenGLPolyDataMapperDrawPoints vtkMesaPolyDataMapperDrawPoints +#define vtkOpenGLPolyDataMapperDrawLines vtkMesaPolyDataMapperDrawLines +#define vtkOpenGLPolyDataMapperDrawPolygons vtkMesaPolyDataMapperDrawPolygons +#define vtkOpenGLPolyDataMapperDrawTStrips vtkMesaPolyDataMapperDrawTStrips +#define vtkOpenGLPolyDataMapperDrawTStripLines vtkMesaPolyDataMapperDrawTStripLines +#include "vtkOpenGLPolyDataMapper.cxx" +#undef vtkOpenGLPolyDataMapperDrawTStripLines +#undef vtkOpenGLPolyDataMapperDrawTStrips +#undef vtkOpenGLPolyDataMapperDrawPolygons +#undef vtkOpenGLPolyDataMapperDrawLines +#undef vtkOpenGLPolyDataMapper + +vtkCxxRevisionMacro(vtkMesaPolyDataMapper, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkMesaPolyDataMapper); diff --git a/Rendering/vtkMesaPolyDataMapper.h b/Rendering/vtkMesaPolyDataMapper.h new file mode 100644 index 0000000..f25d15f --- /dev/null +++ b/Rendering/vtkMesaPolyDataMapper.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaPolyDataMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaPolyDataMapper - a PolyDataMapper for the Mesa library +// .SECTION Description +// vtkMesaPolyDataMapper is a subclass of vtkPolyDataMapper. +// vtkMesaPolyDataMapper is a geometric PolyDataMapper for the Mesa +// rendering library. + +#ifndef __vtkMesaPolyDataMapper_h +#define __vtkMesaPolyDataMapper_h + +#include "vtkPolyDataMapper.h" +#include "MangleMesaInclude/gl.h" // Needed for GLenum + +class vtkCellArray; +class vtkPoints; +class vtkProperty; +class vtkRenderWindow; +class vtkMesaRenderer; +class vtkTimerLog; +class vtkOpenGLTexture; + +class VTK_RENDERING_EXPORT vtkMesaPolyDataMapper : public vtkPolyDataMapper +{ +public: + static vtkMesaPolyDataMapper *New(); + vtkTypeRevisionMacro(vtkMesaPolyDataMapper,vtkPolyDataMapper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement superclass render method. + virtual void RenderPiece(vtkRenderer *ren, vtkActor *a); + + // Description: + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Draw method for Mesa. + virtual int Draw(vtkRenderer *ren, vtkActor *a); + +protected: + vtkMesaPolyDataMapper(); + ~vtkMesaPolyDataMapper(); + + void DrawPoints(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *ca, + vtkRenderer *ren); + + void DrawLines(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *ca, + vtkRenderer *ren); + + void DrawPolygons(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + GLenum rep, + vtkCellArray *ca, + vtkRenderer *ren); + + void DrawTStrips(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + GLenum rep, + vtkCellArray *ca, + vtkRenderer *ren); + + vtkIdType TotalCells; + int ListId; + vtkOpenGLTexture* InternalColorTexture; + vtkRenderWindow *RenderWindow; // RenderWindow used for the previous render +private: + vtkMesaPolyDataMapper(const vtkMesaPolyDataMapper&); // Not implemented. + void operator=(const vtkMesaPolyDataMapper&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMesaPolyDataMapper2D.cxx b/Rendering/vtkMesaPolyDataMapper2D.cxx new file mode 100644 index 0000000..92667f7 --- /dev/null +++ b/Rendering/vtkMesaPolyDataMapper2D.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaPolyDataMapper2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaPolyDataMapper2D.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaPolyDataMapper2D classes defined. +#include "vtkOpenGLPolyDataMapper2D.h" +#include "vtkMesaPolyDataMapper2D.h" + +// Make sure vtkMesaPolyDataMapper2D is a copy of vtkOpenGLPolyDataMapper2D +// with vtkOpenGLPolyDataMapper2D replaced with vtkMesaPolyDataMapper2D +#define vtkOpenGLPolyDataMapper2D vtkMesaPolyDataMapper2D +#include "vtkOpenGLPolyDataMapper2D.cxx" +#undef vtkOpenGLPolyDataMapper2D + +vtkCxxRevisionMacro(vtkMesaPolyDataMapper2D, "$Revision: 1.13 $"); +vtkStandardNewMacro(vtkMesaPolyDataMapper2D); diff --git a/Rendering/vtkMesaPolyDataMapper2D.h b/Rendering/vtkMesaPolyDataMapper2D.h new file mode 100644 index 0000000..d4d33d4 --- /dev/null +++ b/Rendering/vtkMesaPolyDataMapper2D.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaPolyDataMapper2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaPolyDataMapper2D - 2D PolyData support for Mesa +// .SECTION Description +// vtkMesaPolyDataMapper2D provides 2D PolyData annotation support for +// vtk under Mesa. Normally the user should use vtkPolyDataMapper2D +// which in turn will use this class. + +// .SECTION See Also +// vtkPolyDataMapper2D + +#ifndef __vtkMesaPolyDataMapper2D_h +#define __vtkMesaPolyDataMapper2D_h + +#include "vtkPolyDataMapper2D.h" + +class VTK_RENDERING_EXPORT vtkMesaPolyDataMapper2D : public vtkPolyDataMapper2D +{ +public: + vtkTypeRevisionMacro(vtkMesaPolyDataMapper2D,vtkPolyDataMapper2D); + static vtkMesaPolyDataMapper2D *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Actually draw the poly data. + void RenderOverlay(vtkViewport* viewport, vtkActor2D* actor); + +protected: + vtkMesaPolyDataMapper2D() {}; + ~vtkMesaPolyDataMapper2D() {}; + +private: + vtkMesaPolyDataMapper2D(const vtkMesaPolyDataMapper2D&); // Not implemented. + void operator=(const vtkMesaPolyDataMapper2D&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkMesaProperty.cxx b/Rendering/vtkMesaProperty.cxx new file mode 100644 index 0000000..5f204d8 --- /dev/null +++ b/Rendering/vtkMesaProperty.cxx @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaProperty.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include "vtkToolkits.h" +#include "vtkMesaProperty.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + +#include + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaMesaProperty classes defined. +#include "vtkOpenGLProperty.h" +#include "vtkMesaProperty.h" + +// Make sure vtkMesaMesaProperty is a copy of vtkOpenGLProperty +// with vtkOpenGLProperty replaced with vtkMesaMesaProperty +#define vtkOpenGLProperty vtkMesaProperty +#include "vtkOpenGLProperty.cxx" +#undef vtkOpenGLProperty + +vtkCxxRevisionMacro(vtkMesaProperty, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkMesaProperty); diff --git a/Rendering/vtkMesaProperty.h b/Rendering/vtkMesaProperty.h new file mode 100644 index 0000000..f0bc70b --- /dev/null +++ b/Rendering/vtkMesaProperty.h @@ -0,0 +1,50 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaProperty.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaProperty - Mesa property +// .SECTION Description +// vtkMesaProperty is a concrete implementation of the abstract class +// vtkProperty. vtkMesaProperty interfaces to the Mesa rendering library. + +#ifndef __vtkMesaProperty_h +#define __vtkMesaProperty_h + +#include "vtkProperty.h" + +class vtkMesaRenderer; + +class VTK_RENDERING_EXPORT vtkMesaProperty : public vtkProperty +{ +public: + static vtkMesaProperty *New(); + vtkTypeRevisionMacro(vtkMesaProperty,vtkProperty); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Render(vtkActor *a, vtkRenderer *ren); + + // Description: + // Implement base class method. + void BackfaceRender(vtkActor *a, vtkRenderer *ren); + +protected: + vtkMesaProperty() {}; + ~vtkMesaProperty() {}; +private: + vtkMesaProperty(const vtkMesaProperty&); // Not implemented. + void operator=(const vtkMesaProperty&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMesaRenderWindow.cxx b/Rendering/vtkMesaRenderWindow.cxx new file mode 100644 index 0000000..8c625da --- /dev/null +++ b/Rendering/vtkMesaRenderWindow.cxx @@ -0,0 +1,29 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Probably not needed for abstract classes without new methods. +#define VTK_IMPLEMENT_MESA_CXX +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include "vtkOpenGLRenderWindow.h" +#include "vtkXMesaRenderWindow.h" + +// Make sure vtkMesaRenderWindow is a copy of vtkOpenGLRenderWindow +// with vtkOpenGLRenderWindow replaced with vtkMesaRenderWindow +#define vtkOpenGLRenderWindow vtkMesaRenderWindow +#include "vtkOpenGLRenderWindow.cxx" +#undef vtkOpenGLRenderWindow + +vtkCxxRevisionMacro(vtkMesaRenderWindow, "$Revision: 1.31 $"); diff --git a/Rendering/vtkMesaRenderWindow.h b/Rendering/vtkMesaRenderWindow.h new file mode 100644 index 0000000..25dbdcf --- /dev/null +++ b/Rendering/vtkMesaRenderWindow.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaRenderWindow - Mesa rendering window +// .SECTION Description +// vtkMesaRenderWindow is a concrete implementation of the abstract class +// vtkRenderWindow. It uses the mangle openGL namespace mgl, so Mesa render +// windows can be created in the same program as openGL render windows. + +#ifndef __vtkMesaRenderWindow_h +#define __vtkMesaRenderWindow_h + +#include "vtkRenderWindow.h" + +#include "MangleMesaInclude/gl_mangle.h" // Needed for GLuint +#include // Needed for GLuint + +class vtkIdList; + +class VTK_RENDERING_EXPORT vtkMesaRenderWindow : public vtkRenderWindow +{ +protected: + int MultiSamples; + long OldMonitorSetting; + +public: + vtkTypeRevisionMacro(vtkMesaRenderWindow,vtkRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the maximum number of multisamples + static void SetGlobalMaximumNumberOfMultiSamples(int val); + static int GetGlobalMaximumNumberOfMultiSamples(); + + // Description: + // Set / Get the number of multisamples to use for hardware antialiasing. + vtkSetMacro(MultiSamples,int); + vtkGetMacro(MultiSamples,int); + + // Description: + // Update system if needed due to stereo rendering. + virtual void StereoUpdate(); + + // Description: + // Set/Get the pixel data of an image, transmitted as RGBRGB... + virtual unsigned char *GetPixelData(int x,int y,int x2,int y2,int front); + virtual int GetPixelData(int x,int y,int x2,int y2, int front, + vtkUnsignedCharArray*); + virtual int SetPixelData(int x,int y,int x2,int y2,unsigned char *, + int front); + virtual int SetPixelData(int x,int y,int x2,int y2, vtkUnsignedCharArray*, + int front); + + // Description: + // Set/Get the pixel data of an image, transmitted as RGBARGBA... + virtual float *GetRGBAPixelData(int x,int y,int x2,int y2,int front); + virtual int GetRGBAPixelData(int x,int y,int x2,int y2, int front, + vtkFloatArray* data); + virtual int SetRGBAPixelData(int x,int y,int x2,int y2,float *,int front, + int blend=0); + virtual int SetRGBAPixelData(int x,int y,int x2,int y2, vtkFloatArray*, + int front, int blend=0); + virtual void ReleaseRGBAPixelData(float *data); + virtual unsigned char *GetRGBACharPixelData(int x,int y,int x2,int y2, + int front); + virtual int GetRGBACharPixelData(int x,int y,int x2,int y2, int front, + vtkUnsignedCharArray* data); + virtual int SetRGBACharPixelData(int x,int y,int x2,int y2,unsigned char *, + int front, int blend=0); + virtual int SetRGBACharPixelData(int x,int y,int x2,int y2, + vtkUnsignedCharArray *, + int front, int blend=0); + + // Description: + // Set/Get the zbuffer data from an image + virtual float *GetZbufferData( int x1, int y1, int x2, int y2 ); + virtual int GetZbufferData( int x1, int y1, int x2, int y2, float *buffer ); + virtual int GetZbufferData( int x1, int y1, int x2, int y2, + vtkFloatArray* z ); + virtual int SetZbufferData( int x1, int y1, int x2, int y2, float *buffer ); + virtual int SetZbufferData( int x1, int y1, int x2, int y2, + vtkFloatArray *buffer ); + + // Description: + // Make this window the current Mesa context. + void MakeCurrent() = 0; + + // Description: + // Register a texture name with this render window. + void RegisterTextureResource (GLuint id); + + // Description: + // Get the size of the depth buffer. + int GetDepthBufferSize(); + + // Description: + // Initialize OpenGL for this window. + virtual void OpenGLInit(); + +protected: + vtkMesaRenderWindow(); + ~vtkMesaRenderWindow(); + + vtkIdList *TextureResourceIds; + + int GetPixelData(int x,int y,int x2,int y2,int front, unsigned char* data); + int GetRGBAPixelData(int x,int y,int x2,int y2, int front, float* data); + int GetRGBACharPixelData(int x,int y,int x2,int y2, int front, + unsigned char* data); + +private: + vtkMesaRenderWindow(const vtkMesaRenderWindow&); // Not implemented. + void operator=(const vtkMesaRenderWindow&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMesaRenderer.cxx b/Rendering/vtkMesaRenderer.cxx new file mode 100644 index 0000000..6d55c58 --- /dev/null +++ b/Rendering/vtkMesaRenderer.cxx @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaRenderer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaRenderer classes defined. +#include "vtkOpenGLRenderer.h" +#include "vtkMesaRenderer.h" + +// Make sure vtkMesaRenderer is a copy of vtkOpenGLRenderer +// with vtkOpenGLRenderer replaced with vtkMesaRenderer +#define vtkOpenGLRenderer vtkMesaRenderer +#include "vtkOpenGLRenderer.cxx" +#undef vtkOpenGLRenderer + +vtkCxxRevisionMacro(vtkMesaRenderer, "$Revision: 1.14 $"); +vtkStandardNewMacro(vtkMesaRenderer); + +vtkCamera *vtkMesaRenderer::MakeCamera() +{ + return vtkMesaCamera::New(); +} + +vtkLight *vtkMesaRenderer::MakeLight() +{ + return vtkMesaLight::New(); +} diff --git a/Rendering/vtkMesaRenderer.h b/Rendering/vtkMesaRenderer.h new file mode 100644 index 0000000..9c1c243 --- /dev/null +++ b/Rendering/vtkMesaRenderer.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaRenderer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaRenderer - OpenGL renderer +// .SECTION Description +// vtkMesaRenderer is a concrete implementation of the abstract class +// vtkRenderer. vtkMesaRenderer interfaces to the mesa graphics library. +// This file is created, by a copy of vtkOpenGLRenderer + +#ifndef __vtkMesaRenderer_h +#define __vtkMesaRenderer_h + +#include "vtkRenderer.h" + +class VTK_RENDERING_EXPORT vtkMesaRenderer : public vtkRenderer +{ +protected: + int NumberOfLightsBound; + +public: + static vtkMesaRenderer *New(); + vtkTypeRevisionMacro(vtkMesaRenderer,vtkRenderer); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Concrete open gl render method. + void DeviceRender(void); + + // Description: + // Internal method temporarily removes lights before reloading them + // into graphics pipeline. + void ClearLights(void); + + void Clear(void); + + // Description: + // Ask lights to load themselves into graphics pipeline. + int UpdateLights(void); + + + + // Create a vtkMesaCamera, will be used by the super class + // to create the correct camera object. + virtual vtkCamera* MakeCamera(); + + // Create a vtkMesaLight, will be used by the super class + // to create the correct light object. + virtual vtkLight* MakeLight(); + +protected: + vtkMesaRenderer(); + ~vtkMesaRenderer(); + + //BTX + // Picking functions to be implemented by sub-classes + virtual void DevicePickRender(); + virtual void StartPick(unsigned int pickFromSize); + virtual void UpdatePickId(); + virtual void DonePick(); + virtual unsigned int GetPickedId(); + virtual double GetPickedZ(); + // Ivars used in picking + class vtkGLPickInfo* PickInfo; + //ETX + double PickedZ; +private: + vtkMesaRenderer(const vtkMesaRenderer&); // Not implemented. + void operator=(const vtkMesaRenderer&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkMesaTexture.cxx b/Rendering/vtkMesaTexture.cxx new file mode 100644 index 0000000..aaa9b1a --- /dev/null +++ b/Rendering/vtkMesaTexture.cxx @@ -0,0 +1,44 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaTexture.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include +#include "vtkToolkits.h" +#include "vtkMesaTexture.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaTexture classes defined. +#include "vtkOpenGLTexture.h" +#include "vtkMesaTexture.h" + +// Make sure vtkMesaTexture is a copy of vtkOpenGLTexture +// with vtkOpenGLTexture replaced with vtkMesaTexture +#define vtkOpenGLTexture vtkMesaTexture +#define vtkOpenGLRenderWindow vtkMesaRenderWindow +#include "vtkOpenGLTexture.cxx" +#undef vtkOpenGLTexture +#undef vtkOpenGLRenderWindow + +vtkCxxRevisionMacro(vtkMesaTexture, "$Revision: 1.15 $"); +vtkStandardNewMacro(vtkMesaTexture); diff --git a/Rendering/vtkMesaTexture.h b/Rendering/vtkMesaTexture.h new file mode 100644 index 0000000..47e2e20 --- /dev/null +++ b/Rendering/vtkMesaTexture.h @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaTexture.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaTexture - Mesa texture map +// .SECTION Description +// vtkMesaTexture is a concrete implementation of the abstract class +// vtkTexture. vtkMesaTexture interfaces to the Mesa rendering library. + +#ifndef __vtkMesaTexture_h +#define __vtkMesaTexture_h + +#include "vtkTexture.h" + +class vtkWindow; +class vtkMesaRenderer; +class vtkRenderWindow; + +class VTK_RENDERING_EXPORT vtkMesaTexture : public vtkTexture +{ +public: + static vtkMesaTexture *New(); + vtkTypeRevisionMacro(vtkMesaTexture,vtkTexture); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Load(vtkRenderer *ren); + + // Description: + // Release any graphics resources that are being consumed by this texture. + // The parameter window could be used to determine which graphic + // resources to release. Using the same texture object in multiple + // render windows is NOT currently supported. + void ReleaseGraphicsResources(vtkWindow *); + +protected: + vtkMesaTexture(); + ~vtkMesaTexture(); + + unsigned char *ResampleToPowerOfTwo(int &xsize, int &ysize, + unsigned char *dptr, int bpp); + + vtkTimeStamp LoadTime; + long Index; + static long GlobalIndex; + vtkRenderWindow *RenderWindow; // RenderWindow used for previous render +private: + vtkMesaTexture(const vtkMesaTexture&); // Not implemented. + void operator=(const vtkMesaTexture&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkOBJExporter.cxx b/Rendering/vtkOBJExporter.cxx new file mode 100644 index 0000000..57de2fa --- /dev/null +++ b/Rendering/vtkOBJExporter.cxx @@ -0,0 +1,399 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBJExporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOBJExporter.h" + +#include "vtkActorCollection.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkFloatArray.h" +#include "vtkGeometryFilter.h" +#include "vtkMapper.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRendererCollection.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkOBJExporter, "$Revision: 1.57 $"); +vtkStandardNewMacro(vtkOBJExporter); + +vtkOBJExporter::vtkOBJExporter() +{ + this->FilePrefix = NULL; +} + +vtkOBJExporter::~vtkOBJExporter() +{ + if ( this->FilePrefix ) + { + delete [] this->FilePrefix; + } +} + +void vtkOBJExporter::WriteData() +{ + vtkRenderer *ren; + FILE *fpObj, *fpMtl; + vtkActorCollection *ac; + vtkActor *anActor, *aPart; + char nameObj[80]; + char nameMtl[80]; + int idStart = 1; + + // make sure the user specified a filename + if ( this->FilePrefix == NULL) + { + vtkErrorMacro(<< "Please specify file prefix to use"); + return; + } + + // first make sure there is only one renderer in this rendering window + if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1) + { + vtkErrorMacro(<< "obj files only support on renderer per window."); + return; + } + + // get the renderer + ren = this->RenderWindow->GetRenderers()->GetFirstRenderer(); + + // make sure it has at least one actor + if (ren->GetActors()->GetNumberOfItems() < 1) + { + vtkErrorMacro(<< "no actors found for writing .obj file."); + return; + } + + // try opening the files + sprintf(nameObj,"%s.obj",this->FilePrefix); + sprintf(nameMtl,"%s.mtl",this->FilePrefix); + fpObj = fopen(nameObj,"w"); + fpMtl = fopen(nameMtl,"w"); + if (!fpObj || !fpMtl) + { + vtkErrorMacro(<< "unable to open .obj and .mtl files "); + return; + } + + // + // Write header + // + vtkDebugMacro("Writing wavefront files"); + fprintf(fpObj, + "# wavefront obj file written by the visualization toolkit\n\n"); + fprintf(fpObj, "mtllib %s\n\n", nameMtl); + fprintf(fpMtl, + "# wavefront mtl file written by the visualization toolkit\n\n"); + + ac = ren->GetActors(); + vtkAssemblyPath *apath; + vtkCollectionSimpleIterator ait; + for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); ) + { + for (anActor->InitPathTraversal(); (apath=anActor->GetNextPath()); ) + { + aPart=(vtkActor *)apath->GetLastNode()->GetViewProp(); + this->WriteAnActor(aPart, fpObj, fpMtl, idStart); + } + } + + fclose(fpObj); + fclose(fpMtl); +} + +void vtkOBJExporter::WriteAnActor(vtkActor *anActor, FILE *fpObj, FILE *fpMtl, + int &idStart) +{ + vtkDataSet *ds; + vtkPolyData *pd; + vtkGeometryFilter *gf = NULL; + vtkPointData *pntData; + vtkPoints *points; + vtkDataArray *normals = NULL; + vtkDataArray *tcoords; + int i, i1, i2, idNext; + vtkProperty *prop; + double *tempd; + double *p; + vtkCellArray *cells; + vtkTransform *trans = vtkTransform::New(); + vtkIdType npts = 0; + vtkIdType *indx = 0; + + // see if the actor has a mapper. it could be an assembly + if (anActor->GetMapper() == NULL) + { + return; + } + + // write out the material properties to the mat file + prop = anActor->GetProperty(); + fprintf(fpMtl,"newmtl mtl%i\n",idStart); + tempd = prop->GetAmbientColor(); + fprintf(fpMtl,"Ka %g %g %g\n",tempd[0], tempd[1], tempd[2]); + tempd = prop->GetDiffuseColor(); + fprintf(fpMtl,"Kd %g %g %g\n",tempd[0], tempd[1], tempd[2]); + tempd = prop->GetSpecularColor(); + fprintf(fpMtl,"Ks %g %g %g\n",tempd[0], tempd[1], tempd[2]); + fprintf(fpMtl,"Ns %g\n",prop->GetSpecularPower()); + fprintf(fpMtl,"Tf %g %g %g\n",1.0 - prop->GetOpacity(), + 1.0 - prop->GetOpacity(),1.0 - prop->GetOpacity()); + fprintf(fpMtl,"illum 3\n\n"); + + // get the mappers input and matrix + ds = anActor->GetMapper()->GetInput(); + // see if the mapper has an input. + if (ds == NULL) + { + return; + } + ds->Update(); + trans->SetMatrix(anActor->vtkProp3D::GetMatrix()); + + // we really want polydata + if ( ds->GetDataObjectType() != VTK_POLY_DATA ) + { + gf = vtkGeometryFilter::New(); + gf->SetInput(ds); + gf->Update(); + pd = gf->GetOutput(); + } + else + { + pd = (vtkPolyData *)ds; + } + + // write out the points + points = vtkPoints::New(); + trans->TransformPoints(pd->GetPoints(),points); + for (i = 0; i < points->GetNumberOfPoints(); i++) + { + p = points->GetPoint(i); + fprintf (fpObj, "v %g %g %g\n", p[0], p[1], p[2]); + } + idNext = idStart + (int)(points->GetNumberOfPoints()); + points->Delete(); + + // write out the point data + pntData = pd->GetPointData(); + if (pntData->GetNormals()) + { + normals = vtkFloatArray::New(); + normals->SetNumberOfComponents(3); + trans->TransformNormals(pntData->GetNormals(),normals); + for (i = 0; i < normals->GetNumberOfTuples(); i++) + { + p = normals->GetTuple(i); + fprintf (fpObj, "vn %g %g %g\n", p[0], p[1], p[2]); + } + } + + tcoords = pntData->GetTCoords(); + if (tcoords) + { + for (i = 0; i < tcoords->GetNumberOfTuples(); i++) + { + p = tcoords->GetTuple(i); + fprintf (fpObj, "vt %g %g\n", p[0], p[1]); + } + } + + // write out a group name and material + fprintf (fpObj, "\ng grp%i\n", idStart); + fprintf (fpObj, "usemtl mtl%i\n", idStart); + + // write out verts if any + if (pd->GetNumberOfVerts() > 0) + { + cells = pd->GetVerts(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fpObj,"p "); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fpObj,"%i ", ((int)indx[i])+idStart); + } + fprintf(fpObj,"\n"); + } + } + + // write out lines if any + if (pd->GetNumberOfLines() > 0) + { + cells = pd->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fpObj,"l "); + if (tcoords) + { + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fpObj,"%i/%i ",((int)indx[i])+idStart, + ((int)indx[i]) + idStart); + } + } + else + { + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fpObj,"%i ", ((int)indx[i])+idStart); + } + } + fprintf(fpObj,"\n"); + } + } + + // write out polys if any + if (pd->GetNumberOfPolys() > 0) + { + cells = pd->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fpObj,"f "); + for (i = 0; i < npts; i++) + { + if (normals) + { + if (tcoords) + { + // treating vtkIdType as int + fprintf(fpObj,"%i/%i/%i ", ((int)indx[i])+idStart, + ((int)indx[i]) + idStart, ((int)indx[i]) + idStart); + } + else + { + // treating vtkIdType as int + fprintf(fpObj,"%i//%i ",((int)indx[i])+idStart, + ((int)indx[i]) + idStart); + } + } + else + { + if (tcoords) + { + // treating vtkIdType as int + fprintf(fpObj,"%i/%i ", ((int)indx[i])+idStart, + ((int)indx[i]) + idStart); + } + else + { + // treating vtkIdType as int + fprintf(fpObj,"%i ", ((int)indx[i])+idStart); + } + } + } + fprintf(fpObj,"\n"); + } + } + + // write out tstrips if any + if (pd->GetNumberOfStrips() > 0) + { + cells = pd->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + for (i = 2; i < npts; i++) + { + if (i%2) + { + i1 = i - 1; + i2 = i - 2; + } + else + { + i1 = i - 1; + i2 = i - 2; + } + if (normals) + { + if (tcoords) + { + // treating vtkIdType as int + fprintf(fpObj,"f %i/%i/%i ", ((int)indx[i1]) + idStart, + ((int)indx[i1]) + idStart, ((int)indx[i1]) + idStart); + fprintf(fpObj,"%i/%i/%i ", ((int)indx[i2])+ idStart, + ((int)indx[i2]) + idStart, ((int)indx[i2]) + idStart); + fprintf(fpObj,"%i/%i/%i\n", ((int)indx[i]) + idStart, + ((int)indx[i]) + idStart, ((int)indx[i]) + idStart); + } + else + { + // treating vtkIdType as int + fprintf(fpObj,"f %i//%i ", ((int)indx[i1]) + idStart, + ((int)indx[i1]) + idStart); + fprintf(fpObj,"%i//%i ", ((int)indx[i2]) + idStart, + ((int)indx[i2]) + idStart); + fprintf(fpObj,"%i//%i\n",((int)indx[i]) + idStart, + ((int)indx[i]) + idStart); + } + } + else + { + if (tcoords) + { + // treating vtkIdType as int + fprintf(fpObj,"f %i/%i ", ((int)indx[i1]) + idStart, + ((int)indx[i1]) + idStart); + fprintf(fpObj,"%i/%i ", ((int)indx[i2]) + idStart, + ((int)indx[i2]) + idStart); + fprintf(fpObj,"%i/%i\n", ((int)indx[i]) + idStart, + ((int)indx[i]) + idStart); + } + else + { + // treating vtkIdType as int + fprintf(fpObj,"f %i %i %i\n", ((int)indx[i1]) + idStart, + ((int)indx[i2]) + idStart, ((int)indx[i]) + idStart); + } + } + } + } + } + + idStart = idNext; + trans->Delete(); + if (normals) + { + normals->Delete(); + } + if (gf) + { + gf->Delete(); + } +} + + + +void vtkOBJExporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->FilePrefix) + { + os << indent << "FilePrefix: " << this->FilePrefix << "\n"; + } + else + { + os << indent << "FilePrefix: (null)\n"; + } +} + diff --git a/Rendering/vtkOBJExporter.h b/Rendering/vtkOBJExporter.h new file mode 100644 index 0000000..dd120d7 --- /dev/null +++ b/Rendering/vtkOBJExporter.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOBJExporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOBJExporter - export a scene into Wavefront format. +// .SECTION Description +// vtkOBJExporter is a concrete subclass of vtkExporter that writes wavefront +// .OBJ files in ASCII form. It also writes out a mtl file that contains the +// material properties. The filenames are derived by appending the .obj and +// .mtl suffix onto the user specified FilePrefix. +// +// .SECTION See Also +// vtkExporter + + +#ifndef __vtkOBJExporter_h +#define __vtkOBJExporter_h + +#include "vtkExporter.h" + +class vtkActor; + +class VTK_RENDERING_EXPORT vtkOBJExporter : public vtkExporter +{ +public: + static vtkOBJExporter *New(); + vtkTypeRevisionMacro(vtkOBJExporter,vtkExporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the prefix of the files to write out. The resulting filenames + // will have .obj and .mtl appended to them. + vtkSetStringMacro(FilePrefix); + vtkGetStringMacro(FilePrefix); + +protected: + vtkOBJExporter(); + ~vtkOBJExporter(); + + void WriteData(); + void WriteAnActor(vtkActor *anActor, FILE *fpObj, FILE *fpMat, int &id); + char *FilePrefix; +private: + vtkOBJExporter(const vtkOBJExporter&); // Not implemented. + void operator=(const vtkOBJExporter&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkOOGLExporter.cxx b/Rendering/vtkOOGLExporter.cxx new file mode 100644 index 0000000..7952927 --- /dev/null +++ b/Rendering/vtkOOGLExporter.cxx @@ -0,0 +1,713 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOOGLExporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOOGLExporter.h" + +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkGeometryFilter.h" +#include "vtkImageData.h" +#include "vtkLight.h" +#include "vtkLightCollection.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRendererCollection.h" +#include "vtkSystemIncludes.h" +#include "vtkTexture.h" +#include "vtkTransform.h" +#include "vtkTriangleStrip.h" + +vtkCxxRevisionMacro(vtkOOGLExporter, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkOOGLExporter); + +vtkOOGLExporter::vtkOOGLExporter() +{ + this->FileName = NULL; +} + +vtkOOGLExporter::~vtkOOGLExporter() +{ + this->SetFileName( 0 ); +} + +static char indent[256]; +static int indent_now = 0; + +#define VTK_INDENT_MORE { indent[indent_now] = ' '; \ + indent_now += 4; \ + indent[indent_now] = 0; } +#define VTK_INDENT_LESS { indent[indent_now] = ' '; \ + indent_now -= 4; \ + indent[indent_now] = 0; } + +void vtkOOGLExporter::WriteData() +{ + vtkRenderer *ren; + FILE *fp; + int i, j; + vtkActorCollection *ac; + vtkActor *anActor, *aPart; + vtkLightCollection *lc; + vtkLight *aLight; + vtkCamera *cam; + int count; + vtkMatrix4x4 *mat; + + for (i=0;i<256;i++) + { + indent[i] = ' '; + } + indent[indent_now] = 0; + + // make sure the user specified a filename + if ( this->FileName == NULL) + { + vtkErrorMacro(<< "Please specify FileName to use"); + return; + } + + // first make sure there is only one renderer in this rendering window + if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1) + { + vtkErrorMacro(<< "Support for only one renderer per window."); + return; + } + + // get the renderer + ren = this->RenderWindow->GetRenderers()->GetFirstRenderer(); + + // make sure it has at least one actor + if (ren->GetActors()->GetNumberOfItems() < 1) + { + vtkErrorMacro(<< "no actors found for writing Geomview OOGL file."); + return; + } + + // try opening the files + fp = fopen(this->FileName,"w"); + if (!fp) + { + vtkErrorMacro(<< "unable to open Geomview OOGL file " << this->FileName); + return; + } + + // + // Write header + // + vtkDebugMacro("Writing Geomview OOGL file"); + fprintf(fp,"# Geomview OOGL file written by the visualization toolkit\n\n"); + fprintf(fp,"%s( progn\n", indent); + + + VTK_INDENT_MORE; + + // + // Write out the camera + // + cam = ren->GetActiveCamera(); + + fprintf(fp, "%s(camera \"Camera\" camera {\n", indent); + + VTK_INDENT_MORE; + + mat = cam->GetViewTransformMatrix(); + fprintf(fp, "%sworldtocam transform {\n", indent); + + VTK_INDENT_MORE; + + for (i=0; i<4;i++) + { + fprintf(fp, "%s", indent); + for (j=0; j < 4; j++) + { + fprintf(fp, "%f ", mat->GetElement(j,i)); + } + fprintf(fp, "\n"); + } + + VTK_INDENT_LESS; + fprintf(fp, "%s}\n", indent); + + + fprintf(fp, "%sperspective %d stereo %d\n", indent, + !cam->GetParallelProjection(), 0); + fprintf(fp, "%sfov 40\n", indent); + fprintf(fp, "%sframeaspect 1\n", indent); + fprintf(fp, "%sfocus %f\n", indent, cam->GetDistance()); + fprintf(fp, "%snear %f\n", indent, cam->GetClippingRange()[0]); + fprintf(fp, "%sfar %f\n", indent, cam->GetClippingRange()[1]); + + VTK_INDENT_LESS; + + fprintf(fp, "%s}\n", indent); + + VTK_INDENT_LESS; + + fprintf(fp, "%s)\n", indent); + + + // + // Write the background colour + // + + fprintf(fp, "( backcolor \"Camera\" %f %f %f )\n", ren->GetBackground()[0], + ren->GetBackground()[1], + ren->GetBackground()[2]); + + // + // Write out default properties + // + + fprintf(fp, "( merge-baseap appearance {\n"); + + VTK_INDENT_MORE; + + fprintf(fp, "%sface\n%s-edge\n%svect\n%s-transparent\n%severt\n" + "%sshading flat\n%s-normal\n%snormscale 1\n%slinewidth 1\n" + "%spatchdice 10 10\n", + indent, indent, indent, indent, indent, + indent, indent, indent, indent, indent); + fprintf(fp, "%slighting {\n", indent); + + VTK_INDENT_MORE; + + fprintf(fp, "%sambient %f %f %f\n", indent, ren->GetAmbient()[0], + ren->GetAmbient()[1], ren->GetAmbient()[2]); + fprintf(fp, "%slocalviewer 1\n%sattenconst 1\n%sattenmult 0\n" + "%s#replacelights\n", + indent, indent, indent, indent); + + // make sure we have a default light + // if we dont then use a headlight + lc = ren->GetLights(); + vtkCollectionSimpleIterator sit; + for (lc->InitTraversal(sit); (aLight = lc->GetNextLight(sit)); ) + { + this->WriteALight(aLight, fp); + } + + VTK_INDENT_LESS; + + fprintf(fp, "%s}\n", indent); + + VTK_INDENT_LESS; + + fprintf(fp, "%s})\n", indent); + + + // do the actors now + ac = ren->GetActors(); + vtkAssemblyPath *apath; + count = 0; + vtkCollectionSimpleIterator ait; + for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); ) + { + for (anActor->InitPathTraversal(); (apath=anActor->GetNextPath()); ) + { + count++; + aPart=(vtkActor *)apath->GetLastNode()->GetViewProp(); + this->WriteAnActor(aPart, fp, count); + } + } + + VTK_INDENT_LESS; + + fclose(fp); +} + +void vtkOOGLExporter::WriteALight(vtkLight *aLight, FILE *fp) +{ + double *pos, *focus, *color; + float dir[3]; + + pos = aLight->GetPosition(); + focus = aLight->GetFocalPoint(); + color = aLight->GetColor(); + + dir[0] = focus[0] - pos[0]; + dir[1] = focus[1] - pos[1]; + dir[2] = focus[2] - pos[2]; + vtkMath::Normalize(dir); + + fprintf(fp, "%slight {\n", indent); + + VTK_INDENT_MORE; + + fprintf(fp, "%sambient 0.00 0.00 0.00\n", indent); + fprintf(fp, "%scolor %f %f %f\n", indent, color[0], color[1], color[2]); + fprintf(fp, "%sposition %f %f %f %f\n", indent, pos[0], pos[1], pos[2], + 0.0); + + VTK_INDENT_LESS; + + fprintf(fp, "%s}\n", indent); + + return; +} + +void vtkOOGLExporter::WriteAnActor(vtkActor *anActor, FILE *fp, int count) +{ + vtkDataSet *ds; + vtkPolyData *pd; + vtkGeometryFilter *gf = NULL; + vtkPoints *points; + int i; + vtkProperty *prop; + static double defcolor[3] = { 1.0, 1.0, 1.0 }; + double *tempd = defcolor; + vtkCellArray *cells; + vtkIdType npts = 0; + vtkIdType *indx = 0; + double tempf2=0; + vtkPolyDataMapper *pm; + vtkUnsignedCharArray *colors; + + double p[3]; + unsigned char *c; + + // see if the actor has a mapper. it could be an assembly + if (anActor->GetMapper() == NULL) + { + return; + } + + fprintf(fp,"%s(new-geometry \"[g%d]\"\n", indent, count); + + VTK_INDENT_MORE; + + // get the mappers input and matrix + ds = anActor->GetMapper()->GetInput(); + + // we really want polydata + if ( ds->GetDataObjectType() != VTK_POLY_DATA ) + { + gf = vtkGeometryFilter::New(); + gf->SetInput(ds); + gf->Update(); + pd = gf->GetOutput(); + } + else + { + ds->Update(); + pd = (vtkPolyData *)ds; + } + + pm = vtkPolyDataMapper::New(); + pm->SetInput(pd); + pm->SetScalarRange(anActor->GetMapper()->GetScalarRange()); + pm->SetScalarVisibility(anActor->GetMapper()->GetScalarVisibility()); + pm->SetLookupTable(anActor->GetMapper()->GetLookupTable()); + + points = pd->GetPoints(); + + // usage of GetColors() has been deprecated in VTK 4.0 + colors = pm->MapScalars(1.0); + + // Get the material properties + prop = anActor->GetProperty(); + + // is there a texture map (for the moment, we don't deal with textures) + if ( 1 == 2 /*anActor->GetTexture()*/) + { + vtkTexture *aTexture = anActor->GetTexture(); + int *size, xsize, ysize, bpp; + vtkDataArray *scalars; + vtkUnsignedCharArray *mappedScalars; + unsigned char *txtrData; + int totalValues; + + // make sure it is updated and then get some info + if (aTexture->GetInput() == NULL) + { + vtkErrorMacro(<< "texture has no input!\n"); + return; + } + aTexture->GetInput()->Update(); + size = aTexture->GetInput()->GetDimensions(); + scalars = aTexture->GetInput()->GetPointData()->GetScalars(); + + // make sure scalars are non null + if (!scalars) + { + vtkErrorMacro(<< "No scalar values found for texture input!\n"); + return; + } + + // make sure using unsigned char data of color scalars type + if (aTexture->GetMapColorScalarsThroughLookupTable () || + (scalars->GetDataType() != VTK_UNSIGNED_CHAR) ) + { + mappedScalars = aTexture->GetMappedScalars (); + } + else + { + mappedScalars = static_cast(scalars); + } + + // we only support 2d texture maps right now + // so one of the three sizes must be 1, but it + // could be any of them, so lets find it + if (size[0] == 1) + { + xsize = size[1]; ysize = size[2]; + } + else + { + xsize = size[0]; + if (size[1] == 1) + { + ysize = size[2]; + } + else + { + ysize = size[1]; + if (size[2] != 1) + { + vtkErrorMacro(<< "3D texture maps currently are not supported!\n"); + return; + } + } + } + + fprintf(fp, "%sTexture2 {\n", indent); + VTK_INDENT_MORE; + bpp = mappedScalars->GetNumberOfComponents(); + fprintf(fp, "%simage %d %d %d\n", indent, xsize, ysize, bpp); + VTK_INDENT_MORE; + txtrData = static_cast(mappedScalars)->GetPointer(0); + totalValues = xsize*ysize; + fprintf(fp,"%s",indent); + for (i = 0; i < totalValues; i++) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + if (bpp > 1) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (bpp > 2) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (bpp > 3) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (i%8 == 0) + { + fprintf(fp,"\n%s ", indent); + } + else + { + fprintf(fp," "); + } + } + VTK_INDENT_LESS; + fprintf(fp, "%s}\n", indent); + VTK_INDENT_LESS; + } + + // start an INST object + fprintf(fp, "%s{ INST\n", indent); + + VTK_INDENT_MORE + + // start a LIST object + fprintf(fp, "%sgeom { LIST\n", indent); + + VTK_INDENT_MORE; + + // extract vector information + if (pd->GetNumberOfLines()) + { + fprintf(fp, "%s{ VECT\n", indent); + + VTK_INDENT_MORE; + + // write out the header line + cells = pd->GetLines(); + i = 0; + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + i += npts; + } + fprintf(fp, "%s%d %d %d\n", indent, (int) pd->GetNumberOfLines(), i, 1); + cells = pd->GetLines(); + fprintf(fp, "%s", indent); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp, "%d ", (int) npts); + } + fprintf(fp, "\n"); + + // write out # of color information + fprintf(fp, "%s1 ", indent); + for (i=1; iGetNumberOfLines(); i++) + { + fprintf(fp, "0 "); + } + fprintf(fp, "\n"); + + + // write out points + cells = pd->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp, "%s", indent); + for (i=0;iGetPoint(indx[i]); + fprintf(fp, "%s%f %f %f ", indent, pt[0], pt[1], pt[2]); + } + fprintf(fp, "\n"); + } + + // write out color indices + tempd = prop->GetColor(); + fprintf(fp, "%f %f %f 1\n", tempd[0], tempd[1], tempd[2]); + fprintf(fp, "}\n"); + + VTK_INDENT_LESS; + } + + // extract polygon information (includes triangle strips) + + if (pd->GetNumberOfPolys() || pd->GetNumberOfStrips()) + { + fprintf(fp, "%s{ %sOFF\n", indent, (colors) ? "C" : ""); + + VTK_INDENT_MORE; + + // write header + if (pd->GetNumberOfPolys()) + { + fprintf(fp, "%s%d %d %d\n", indent, (int) points->GetNumberOfPoints(), + (int) pd->GetNumberOfPolys(), 0); + } + else + { + // Handle triangle strips + // + i = 0; + cells = pd->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + i += (npts-2); + } + fprintf(fp, "%s%d %d %d\n", indent, (int) points->GetNumberOfPoints(), i, 0); + } + + // write points + if (colors) + { + for (i = 0; i < points->GetNumberOfPoints(); i++) + { + double *pt = points->GetPoint(i); + c = (unsigned char *)colors->GetPointer(4*i); + + fprintf (fp,"%s%g %g %g %g %g %g %g\n", indent, + pt[0], pt[1], pt[2], + c[0]/255., c[1]/255., c[2]/255., c[3]/255.); + } + } + else + { + for (i = 0; i < points->GetNumberOfPoints(); i++) + { + double *pt = points->GetPoint(i); + fprintf (fp,"%s%g %g %g\n", indent, pt[0], pt[1], pt[2]); + } + } + + // write polys + if (pd->GetNumberOfPolys()) + { + cells = pd->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp, "%s%i ", indent, (int) npts); + for (i = 0; i < npts; i++) + { +#ifdef VTK_USE_64BIT_IDS + fprintf(fp, "%lld ", indx[i]); +#else // VTK_USE_64BIT_IDS + fprintf(fp, "%d ", indx[i]); +#endif // VTK_USE_64BIT_IDS + } + fprintf(fp, "\n"); + } + fprintf(fp, "%s}\n", indent); // finish of polygon list + + VTK_INDENT_LESS; + + } + + else if (pd->GetNumberOfStrips()) + { // write triangle strips + cells = pd->GetStrips(); + + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + int pt1, pt2, pt3; + + pt1 = indx[0]; + pt2 = indx[1]; + + for (i = 0; i < (npts - 2); i++) + { + pt3 = indx[i+2]; + if (i % 2) + { + fprintf(fp, "%s3 %d %d %d\n", indent, pt2, pt1, pt3); + } + else + { + fprintf(fp, "%s3 %d %d %d\n", indent, pt1, pt2, pt3); + } + pt1 = pt2; + pt2 = pt3; + } + } + fprintf(fp, "%s}\n", indent); // Finish off triangle strips + + VTK_INDENT_LESS; + } + } + + fprintf(fp, "%s}\n", indent); // End of list object + + VTK_INDENT_LESS; + + // Get the actor's position + anActor->GetPosition(p); + + fprintf(fp, "transform {1 0 0 0 0 1 0 0 0 0 1 0 %f %f %f 1}\n", p[0], p[1], p[2]); + + VTK_INDENT_LESS; + + fprintf(fp, "%s}\n", indent); // Finish off INST command + + VTK_INDENT_LESS; + + fprintf(fp, "%s)\n", indent); // Finish off new-geometry command + + // turn off the bounding box, set normalization to none + fprintf(fp, "( bbox-draw \"[g%d]\" off )\n", count); + fprintf(fp, "( normalization \"[g%d]\" none )\n", count); + + fprintf(fp, "( merge-ap \"[g%d]\" appearance {\n", count); + + VTK_INDENT_MORE; + + // Set shading model + if (prop->GetInterpolation() > 0) + { + fprintf(fp, "%sshading smooth\n", indent); + } + + // Set transparency + if (prop->GetOpacity() < 1) + { + fprintf(fp, "%s+transparent\n", indent); + } + + // Set representation - no way to render points + if (prop->GetRepresentation() != 2) + { + fprintf(fp, "%s+edge\n%s-face\n", indent, indent); + } + + // Set edge information + fprintf(fp, "%slinewidth %d\n", indent, (int) prop->GetLineWidth()); + + // Now the material information + fprintf(fp, "%smaterial {\n", indent); + + VTK_INDENT_MORE; + + // Indicate whether edges are shown or not + if (prop->GetEdgeVisibility()) + { + tempd = prop->GetEdgeColor(); + } + if (prop->GetRepresentation() != 2) + { + tempd = prop->GetColor(); + } + if (prop->GetEdgeVisibility() || (prop->GetRepresentation() != 2)) + { + fprintf(fp, "%sedgecolor %f %f %f\n", indent, + tempd[0], tempd[1], tempd[2]); + } + + tempf2 = prop->GetAmbient(); + tempd = prop->GetAmbientColor(); + fprintf(fp, "%ska %f\n", indent, tempf2); + fprintf(fp, "%sambient %f %f %f\n", indent, tempd[0], tempd[1], tempd[2]); + tempf2 = prop->GetDiffuse(); + tempd = prop->GetDiffuseColor(); + fprintf(fp, "%skd %f\n", indent, tempf2); + fprintf(fp, "%sdiffuse %f %f %f\n", indent, tempd[0], tempd[1], tempd[2]); + tempf2 = prop->GetSpecular(); + tempd = prop->GetSpecularColor(); + fprintf(fp, "%sks %f\n", indent, tempf2); + fprintf(fp, "%sspecular %f %f %f\n", indent, tempd[0], tempd[1], tempd[2]); + if (prop->GetOpacity() < 1) + { + fprintf(fp, "%salpha %f\n", indent, prop->GetOpacity()); + } + + fprintf(fp, "%s}\n", indent); + + VTK_INDENT_LESS; + + fprintf(fp, "%s}\n", indent); + + VTK_INDENT_LESS; + + fprintf(fp, ")\n"); + + if (gf) + { + gf->Delete(); + } + pm->Delete(); +} + + + +void vtkOOGLExporter::PrintSelf(ostream& os, vtkIndent ind) +{ + vtkExporter::PrintSelf(os,ind); + + if (this->FileName) + { + os << ind << "FileName: " << this->FileName << "\n"; + } + else + { + os << ind << "FileName: (null)\n"; + } +} + diff --git a/Rendering/vtkOOGLExporter.h b/Rendering/vtkOOGLExporter.h new file mode 100644 index 0000000..5417f86 --- /dev/null +++ b/Rendering/vtkOOGLExporter.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOOGLExporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkOOGLExporter - export a scene into Geomview OOGL format. +// .SECTION Description +// vtkOOGLExporter is a concrete subclass of vtkExporter that writes +// Geomview OOGL files. +// +// .SECTION See Also +// vtkExporter + + +#ifndef __vtkOOGLExporter_h +#define __vtkOOGLExporter_h + +#include "vtkExporter.h" + +class vtkLight; +class vtkActor; + +class VTK_RENDERING_EXPORT vtkOOGLExporter : public vtkExporter +{ +public: + static vtkOOGLExporter *New(); + vtkTypeRevisionMacro(vtkOOGLExporter,vtkExporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the name of the Geomview file to write. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + +protected: + vtkOOGLExporter(); + ~vtkOOGLExporter(); + + void WriteData(); + void WriteALight(vtkLight *aLight, FILE *fp); + void WriteAnActor(vtkActor *anActor, FILE *fp, int count); + char *FileName; + +private: + vtkOOGLExporter(const vtkOOGLExporter&); // Not implemented + void operator=(const vtkOOGLExporter&); // Not implemented +}; + +#endif + diff --git a/Rendering/vtkOpenGL.h b/Rendering/vtkOpenGL.h new file mode 100644 index 0000000..4b0304b --- /dev/null +++ b/Rendering/vtkOpenGL.h @@ -0,0 +1,27 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGL.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkOpenGL_h +#define __vtkOpenGL_h + +#include "vtkConfigure.h" + +#if defined(__APPLE__) && (defined(VTK_USE_CARBON) || defined(VTK_USE_COCOA)) +# include // Include OpenGL API. +#else +# include "vtkWindows.h" // Needed to include OpenGL header on Windows. +# include // Include OpenGL API. +#endif + +#endif diff --git a/Rendering/vtkOpenGLActor.cxx b/Rendering/vtkOpenGLActor.cxx new file mode 100644 index 0000000..e805304 --- /dev/null +++ b/Rendering/vtkOpenGLActor.cxx @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLActor.h" + +#include "vtkMapper.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderer.h" +#include "vtkProperty.h" + +#include "vtkOpenGL.h" +#include + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLActor, "$Revision: 1.29 $"); +vtkStandardNewMacro(vtkOpenGLActor); +#endif + +// Actual actor render method. +void vtkOpenGLActor::Render(vtkRenderer *ren, vtkMapper *mapper) +{ + float opacity; + + // get opacity + opacity = this->GetProperty()->GetOpacity(); + if (opacity == 1.0) + { + glDepthMask (GL_TRUE); + } + else + { + // add this check here for GL_SELECT mode + // If we are not picking, then don't write to the zbuffer + // because we probably haven't sorted the polygons. If we + // are picking, then translucency doesn't matter - we want to + // pick the thing closest to us. + GLint param[1]; + glGetIntegerv(GL_RENDER_MODE, param); + if(param[0] == GL_SELECT ) + { + glDepthMask(GL_TRUE); + } + else + { + glDepthMask (GL_FALSE); + } + } + + // build transformation + if (!this->IsIdentity) + { + double *mat = this->GetMatrix()->Element[0]; + double mat2[16]; + mat2[0] = mat[0]; + mat2[1] = mat[4]; + mat2[2] = mat[8]; + mat2[3] = mat[12]; + mat2[4] = mat[1]; + mat2[5] = mat[5]; + mat2[6] = mat[9]; + mat2[7] = mat[13]; + mat2[8] = mat[2]; + mat2[9] = mat[6]; + mat2[10] = mat[10]; + mat2[11] = mat[14]; + mat2[12] = mat[3]; + mat2[13] = mat[7]; + mat2[14] = mat[11]; + mat2[15] = mat[15]; + + // insert model transformation + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glMultMatrixd(mat2); + } + + // send a render to the mapper; update pipeline + mapper->Render(ren,this); + + // pop transformation matrix + if (!this->IsIdentity) + { + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + } + + if (opacity != 1.0) + { + glDepthMask (GL_TRUE); + } +} + +//---------------------------------------------------------------------------- +void vtkOpenGLActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLActor.h b/Rendering/vtkOpenGLActor.h new file mode 100644 index 0000000..43aa84d --- /dev/null +++ b/Rendering/vtkOpenGLActor.h @@ -0,0 +1,50 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLActor - OpenGL actor +// .SECTION Description +// vtkOpenGLActor is a concrete implementation of the abstract class vtkActor. +// vtkOpenGLActor interfaces to the OpenGL rendering library. + +#ifndef __vtkOpenGLActor_h +#define __vtkOpenGLActor_h + +#include "vtkActor.h" + +class vtkOpenGLRenderer; + +class VTK_RENDERING_EXPORT vtkOpenGLActor : public vtkActor +{ +protected: + +public: + static vtkOpenGLActor *New(); + vtkTypeRevisionMacro(vtkOpenGLActor,vtkActor); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Actual actor render method. + void Render(vtkRenderer *ren, vtkMapper *mapper); + +protected: + vtkOpenGLActor() {}; + ~vtkOpenGLActor() {}; + +private: + vtkOpenGLActor(const vtkOpenGLActor&); // Not implemented. + void operator=(const vtkOpenGLActor&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkOpenGLCamera.cxx b/Rendering/vtkOpenGLCamera.cxx new file mode 100644 index 0000000..0cc293c --- /dev/null +++ b/Rendering/vtkOpenGLCamera.cxx @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLCamera.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLCamera.h" + +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOutputWindow.h" +#include "vtkRenderWindow.h" +#include "vtkgluPickMatrix.h" + +#include "vtkOpenGL.h" + +#include + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLCamera, "$Revision: 1.63 $"); +vtkStandardNewMacro(vtkOpenGLCamera); +#endif + +// Implement base class method. +void vtkOpenGLCamera::Render(vtkRenderer *ren) +{ + double aspect[2]; + int lowerLeft[2]; + int usize, vsize; + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + + // find out if we should stereo render + this->Stereo = (ren->GetRenderWindow())->GetStereoRender(); + ren->GetTiledSizeAndOrigin(&usize,&vsize,lowerLeft,lowerLeft+1); + + // if were on a stereo renderer draw to special parts of screen + if (this->Stereo) + { + switch ((ren->GetRenderWindow())->GetStereoType()) + { + case VTK_STEREO_CRYSTAL_EYES: + if (this->LeftEye) + { + glDrawBuffer(GL_BACK_LEFT); + } + else + { + glDrawBuffer(GL_BACK_RIGHT); + } + break; + case VTK_STEREO_LEFT: + this->LeftEye = 1; + break; + case VTK_STEREO_RIGHT: + this->LeftEye = 0; + break; + default: + break; + } + } + else + { + if (ren->GetRenderWindow()->GetDoubleBuffer()) + { + glDrawBuffer(GL_BACK); + } + else + { + glDrawBuffer(GL_FRONT); + } + } + + glViewport(lowerLeft[0],lowerLeft[1], usize, vsize); + glEnable( GL_SCISSOR_TEST ); + glScissor(lowerLeft[0],lowerLeft[1], usize, vsize); + + // some renderer subclasses may have more complicated computations for the + // aspect ratio. SO take that into account by computing the difference + // between our simple aspect ratio and what the actual renderer is + // reporting. + ren->ComputeAspect(); + ren->GetAspect(aspect); + double aspect2[2]; + ren->vtkViewport::ComputeAspect(); + ren->vtkViewport::GetAspect(aspect2); + double aspectModification = aspect[0]*aspect2[1]/(aspect[1]*aspect2[0]); + + glMatrixMode( GL_PROJECTION); + if(usize && vsize) + { + matrix->DeepCopy(this->GetPerspectiveTransformMatrix( + aspectModification*usize/vsize, -1,1)); + matrix->Transpose(); + } + if(ren->GetIsPicking()) + { + int size[2]; size[0] = usize; size[1] = vsize; + glLoadIdentity(); + vtkgluPickMatrix(ren->GetPickX(), ren->GetPickY(), 1, 1, lowerLeft, size); + glMultMatrixd(matrix->Element[0]); + } + else + { + // insert camera view transformation + glLoadMatrixd(matrix->Element[0]); + } + + // push the model view matrix onto the stack, make sure we + // adjust the mode first + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + matrix->DeepCopy(this->GetViewTransformMatrix()); + matrix->Transpose(); + + // insert camera view transformation + glMultMatrixd(matrix->Element[0]); + + if ((ren->GetRenderWindow())->GetErase() && ren->GetErase()) + { + ren->Clear(); + } + + // if we have a stereo renderer, draw other eye next time + if (this->Stereo) + { + if (this->LeftEye) + { + this->LeftEye = 0; + } + else + { + this->LeftEye = 1; + } + } + + matrix->Delete(); +} + +void vtkOpenGLCamera::UpdateViewport(vtkRenderer *ren) +{ + int lowerLeft[2]; + int usize, vsize; + ren->GetTiledSizeAndOrigin(&usize,&vsize,lowerLeft,lowerLeft+1); + + glViewport(lowerLeft[0],lowerLeft[1], usize, vsize); + glEnable( GL_SCISSOR_TEST ); + glScissor(lowerLeft[0],lowerLeft[1], usize, vsize); +} + +//---------------------------------------------------------------------------- +void vtkOpenGLCamera::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLCamera.h b/Rendering/vtkOpenGLCamera.h new file mode 100644 index 0000000..21e8804 --- /dev/null +++ b/Rendering/vtkOpenGLCamera.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLCamera.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLCamera - OpenGL camera +// .SECTION Description +// vtkOpenGLCamera is a concrete implementation of the abstract class +// vtkCamera. vtkOpenGLCamera interfaces to the OpenGL rendering library. + +#ifndef __vtkOpenGLCamera_h +#define __vtkOpenGLCamera_h + +#include "vtkCamera.h" + +class vtkOpenGLRenderer; + +class VTK_RENDERING_EXPORT vtkOpenGLCamera : public vtkCamera +{ +public: + static vtkOpenGLCamera *New(); + vtkTypeRevisionMacro(vtkOpenGLCamera,vtkCamera); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Render(vtkRenderer *ren); + + void UpdateViewport(vtkRenderer *ren); + +protected: + vtkOpenGLCamera() {}; + ~vtkOpenGLCamera() {}; +private: + vtkOpenGLCamera(const vtkOpenGLCamera&); // Not implemented. + void operator=(const vtkOpenGLCamera&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkOpenGLExtensionManager.cxx b/Rendering/vtkOpenGLExtensionManager.cxx new file mode 100644 index 0000000..098ba4a --- /dev/null +++ b/Rendering/vtkOpenGLExtensionManager.cxx @@ -0,0 +1,403 @@ +// -*- c++ -*- + +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLExtensionManager.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + + Copyright 2003 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +#include "vtkOpenGLExtensionManager.h" +#include "vtkOpenGLExtensionManagerConfigure.h" +#include "vtkgl.h" + +#include "vtkRenderWindow.h" +#include "vtkObjectFactory.h" + +#include + +#include + +#ifdef VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE +extern "C" vtkglX::__GLXextFuncPtr glXGetProcAddressARB(const GLubyte *); +#endif //VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE + +#ifdef VTK_USE_VTK_DYNAMIC_LOADER +#include "vtkDynamicLoader.h" +#include +#include +#endif + +#ifdef VTK_USE_APPLE_LOADER +#include +#endif //VTK_USE_APPLE_LOADER + +// GLU is currently not linked in VTK. We do not support it here. +#define GLU_SUPPORTED 0 + +vtkCxxRevisionMacro(vtkOpenGLExtensionManager, "$Revision: 1.12.4.1 $"); +vtkStandardNewMacro(vtkOpenGLExtensionManager); + +vtkOpenGLExtensionManager::vtkOpenGLExtensionManager() +{ + this->RenderWindow = NULL; + this->ExtensionsString = NULL; + + this->Modified(); +} + +vtkOpenGLExtensionManager::~vtkOpenGLExtensionManager() +{ + this->SetRenderWindow(NULL); + if (this->ExtensionsString) + { + delete[] this->ExtensionsString; + } +} + +void vtkOpenGLExtensionManager::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "RenderWindow: (" << this->RenderWindow << ")" << endl; + os << indent << "BuildTime: " << this->BuildTime << endl; + os << indent << "ExtensionsString: " + << (this->ExtensionsString ? this->ExtensionsString : "(NULL)") << endl; +} + +void vtkOpenGLExtensionManager::SetRenderWindow(vtkRenderWindow *renwin) +{ + if (renwin == this->RenderWindow) + { + return; + } + + vtkDebugMacro("Setting RenderWindow to " << renwin); + + if (this->RenderWindow) + { + this->RenderWindow->UnRegister(this); + } + + this->RenderWindow = renwin; + if (this->RenderWindow) + { + this->RenderWindow->Register(this); + } + + this->Modified(); +} + +void vtkOpenGLExtensionManager::Update() +{ + if (this->BuildTime > this->MTime) + { + return; + } + + vtkDebugMacro("Update"); + + if (this->ExtensionsString) + { + delete[] this->ExtensionsString; + this->ExtensionsString = NULL; + } + + this->ReadOpenGLExtensions(); + + this->BuildTime.Modified(); +} + +int vtkOpenGLExtensionManager::ExtensionSupported(const char *name) +{ + this->Update(); + + const char *p = this->ExtensionsString; + int NameLen = strlen(name); + int result = 0; + + for(;;) + { + int n; + while (*p == ' ') p++; + if (*p == '\0') + { + result = 0; + break; + } + n = strcspn(p, " "); + if ((NameLen == n) && (strncmp(name, p, n) == 0)) + { + result = 1; + break; + } + p += n; + } + return result; +} + +vtkOpenGLExtensionManagerFunctionPointer +vtkOpenGLExtensionManager::GetProcAddress(const char *fname) +{ + vtkDebugMacro(<< "Trying to load OpenGL function " << fname); + +#ifdef VTK_USE_WGL_GET_PROC_ADDRESS + return reinterpret_cast(wglGetProcAddress(fname)); +#endif //VTK_USE_WGL_GET_PROC_ADDRESS + + +#ifdef VTK_USE_APPLE_LOADER + NSSymbol symbol = NULL; + char *mangled_fname = new char[strlen(fname)+2]; + // Prepend a '_' to the function name. + strcpy(mangled_fname+1, fname); + mangled_fname[0] = '_'; + if (NSIsSymbolNameDefined(mangled_fname)) + { + symbol = NSLookupAndBindSymbol(mangled_fname); + } + else + { + vtkDebugMacro("Could not load " << mangled_fname); + } + delete[] mangled_fname; + if (symbol) + { + return (vtkOpenGLExtensionManagerFunctionPointer)NSAddressOfSymbol(symbol); + } + else + { + vtkDebugMacro("Could not load " << mangled_fname); + return NULL; + } +#endif //VTK_USE_APPLE_LOADER + + +#ifdef VTK_USE_GLX_GET_PROC_ADDRESS + return glXGetProcAddress((const GLubyte *)fname); +#endif //VTK_USE_GLX_GET_PROC_ADDRESS +#ifdef VTK_USE_GLX_GET_PROC_ADDRESS_ARB + return glXGetProcAddressARB((const GLubyte *)fname); +#endif //VTK_USE_GLX_GET_PROC_ADDRESS_ARB + + +#ifdef VTK_USE_VTK_DYNAMIC_LOADER + // If the GLX implementation cannot load procedures for us, load them + // directly from the dynamic libraries. + static vtkstd::list ogl_libraries; + + if (ogl_libraries.empty()) + { + const char *ext = vtkDynamicLoader::LibExtension(); + vtkstd::string::size_type ext_size = strlen(ext); + // Must be the first function we tried to load. Fill this list with + // the OpenGL libraries we linked against. + vtkstd::string l(OPENGL_LIBRARIES); + vtkstd::string::size_type filename_start = 0; + while (1) + { + vtkstd::string::size_type filename_end = l.find(';', filename_start); + if (filename_end == vtkstd::string::npos) + { + break; + } + vtkstd::string possible_file = l.substr(filename_start, + filename_end-filename_start); + // Make sure this is actually a library. Do this by making sure it + // has an appropriate extension. This is by no means definitive, but + // it1 should do. + if ( (possible_file.length() > ext_size) + && (possible_file.substr(possible_file.length()-ext_size) == ext) ) + { + ogl_libraries.push_back(possible_file); + } + + filename_start = filename_end + 1; + } + } + + // Look for the function in each library. + for (vtkstd::list::iterator i = ogl_libraries.begin(); + i != ogl_libraries.end(); i++) + { + vtkLibHandle lh = vtkDynamicLoader::OpenLibrary((*i).c_str()); + void *f = vtkDynamicLoader::GetSymbolAddress(lh, fname); + vtkDynamicLoader::CloseLibrary(lh); + if (f) return (vtkOpenGLExtensionManagerFunctionPointer)f; + } + + // Could not find the function. + return NULL; +#endif //VTK_USE_VTK_DYNAMIC_LOADER + +#ifdef VTK_NO_EXTENSION_LOADING + return NULL; +#endif //VTK_NO_EXTENSION_LOADING +} + +void vtkOpenGLExtensionManager::LoadExtension(const char *name) +{ + if (!this->ExtensionSupported(name)) + { + vtkWarningMacro("Attempting to load " << name + << ", which is not supported."); + } + + int success = vtkgl::LoadExtension(name, this); + + if (!success) + { + vtkErrorMacro("Extension " << name << " could not be loaded."); + } +} + +void vtkOpenGLExtensionManager::ReadOpenGLExtensions() +{ + vtkDebugMacro("ReadOpenGLExtensions"); + +#ifdef VTK_NO_EXTENSION_LOADING + + this->ExtensionsString = new char[1]; + this->ExtensionsString[0] = '\0'; + return; + +#else //!VTK_NO_EXTENSION_LOADING + + if (this->RenderWindow) + { + if (!this->RenderWindow->IsA("vtkOpenGLRenderWindow")) + { + // If the render window is not OpenGL, then it obviously has no + // extensions. + this->ExtensionsString = new char[1]; + this->ExtensionsString[0] = '\0'; + return; + } + if (this->RenderWindow->GetNeverRendered()) + { + this->RenderWindow->Render(); + } + this->RenderWindow->MakeCurrent(); + } + + vtkstd::string extensions_string; + + const char *gl_extensions; + const char *glu_extensions = ""; + const char *win_extensions; + + gl_extensions = (const char *)glGetString(GL_EXTENSIONS); + + if (gl_extensions == NULL) + { + gl_extensions = ""; + } + + if (!this->RenderWindow && (gl_extensions[0] == '\0')) + { + vtkDebugMacro("No window active? Attaching default render window."); + vtkRenderWindow *renwin = vtkRenderWindow::New(); + renwin->SetSize(1, 1); + this->SetRenderWindow(renwin); + renwin->Delete(); + this->ReadOpenGLExtensions(); + return; + } + + extensions_string = gl_extensions; + +#if GLU_SUPPORTED + glu_extensions = (const char *)gluGetString(GLU_EXTENSIONS); +#endif + if (glu_extensions != NULL) + { + extensions_string += " "; + extensions_string += glu_extensions; + } + +#if defined(WIN32) + // Don't use this->LoadExtension or we will go into an infinite loop. + vtkgl::LoadExtension("WGL_ARB_extensions_string", this); + if (vtkwgl::GetExtensionsStringARB) + { + win_extensions = vtkwgl::GetExtensionsStringARB(wglGetCurrentDC()); + } + else + { + vtkWarningMacro("Could not query WGL extensions."); + win_extensions = ""; + } +#elif defined(__APPLE__) +// vtkWarningMacro("Does APPLE have a windows extension string?"); + win_extensions = ""; +#else + win_extensions = glXGetClientString(glXGetCurrentDisplay(), + GLX_EXTENSIONS); +#endif + + if (win_extensions != NULL) + { + extensions_string += " "; + extensions_string += win_extensions; + } + + // We build special extension identifiers for OpenGL versions. Check to + // see which are supported. + vtkstd::string version_extensions; + vtkstd::string::size_type beginpos, endpos; + + version_extensions = vtkgl::GLVersionExtensionsString(); + endpos = 0; + while (endpos != vtkstd::string::npos) + { + beginpos = version_extensions.find_first_not_of(' ', endpos); + if (beginpos == vtkstd::string::npos) break; + endpos = version_extensions.find_first_of(' ', beginpos); + + vtkstd::string ve = version_extensions.substr(beginpos, endpos-beginpos); + if (vtkgl::LoadExtension(ve.c_str(), this)) + { + extensions_string += " "; + extensions_string += ve; + } + } + +#ifdef VTK_USE_X + version_extensions = vtkgl::GLXVersionExtensionsString(); + endpos = 0; + while (endpos != vtkstd::string::npos) + { + beginpos = version_extensions.find_first_not_of(' ', endpos); + if (beginpos == vtkstd::string::npos) break; + endpos = version_extensions.find_first_of(' ', beginpos); + + vtkstd::string ve = version_extensions.substr(beginpos, endpos-beginpos); + if (vtkgl::LoadExtension(ve.c_str(), this)) + { + extensions_string += " "; + extensions_string += ve; + } + } +#endif //VTK_USE_X + + // Store extensions string. + this->ExtensionsString = new char[extensions_string.length()+1]; + strcpy(this->ExtensionsString, extensions_string.c_str()); + +#endif //!VTK_NO_EXTENSION_LOADING +} diff --git a/Rendering/vtkOpenGLExtensionManager.h b/Rendering/vtkOpenGLExtensionManager.h new file mode 100644 index 0000000..bd9af7b --- /dev/null +++ b/Rendering/vtkOpenGLExtensionManager.h @@ -0,0 +1,177 @@ +// -*- c++ -*- + +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLExtensionManager.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + + Copyright 2003 Sandia Corporation. + Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + license for use of this work by or on behalf of the + U.S. Government. Redistribution and use in source and binary forms, with + or without modification, are permitted provided that this Notice and any + statement of authorship are reproduced on all copies. + +=========================================================================*/ + +// .NAME vtkOpenGLExtensionManager - Interface class for querying and using OpenGL extensions. +// +// .SECTION Description +// +// vtkOpenGLExtensionManager acts as an interface to OpenGL extensions. It +// provides methods to query OpenGL extensions on the current or a given +// render window and to load extension function pointers. Currently does +// not support GLU extensions since the GLU library is not linked to VTK. +// +// Before using vtkOpenGLExtensionManager, an OpenGL context must be created. +// This is generally done with a vtkRenderWindow. Note that simply creating +// the vtkRenderWindow is not sufficient. Usually you have to call Render +// before the actual OpenGL context is created. You can specify the +// RenderWindow with the SetRenderWindow method. +// \code +// vtkOpenGLExtensionManager *extensions = vtkOpenGLExtensionManager::New(); +// extensions->SetRenderWindow(renwin); +// \endcode +// If no vtkRenderWindow is specified, the current OpenGL context (if any) +// is used. +// +// Generally speaking, when using OpenGL extensions, you will need an +// vtkOpenGLExtensionManager and the prototypes defined in vtkgl.h. +// \code +// #include "vtkOpenGLExtensionManager.h" +// #include "vtkgl.h" +// \endcode +// The vtkgl.h include file contains all the constants and function +// pointers required for using OpenGL extensions in a portable and +// namespace safe way. vtkgl.h is built from parsed glext.h, glxext.h, and +// wglext.h files. Snapshots of these files are distributed with vtkSNL, +// but you can also set CMake options to use other files. +// +// To use an OpenGL extension, you first need to make an instance of +// vtkOpenGLExtensionManager and give it a vtkRenderWindow. You can then +// query the vtkOpenGLExtensionManager to see if the extension is supported +// with the ExtensionSupported method. Valid names for extensions are +// given in the OpenGL extension registry at +// \ref http://oss.sgi.com/projects/ogl-sample/registry/ . +// You can also grep vtkgl.h (which will be in the binary build directory +// if vtkSNL is not installed) for appropriate names. There are also +// special extensions GL_VERSION_X_X (where X_X is replaced with a major +// and minor version, respectively) which contain all the constants and +// functions for OpenGL versions for which the gl.h header file is of an +// older version than the driver. +// +// \code +// if ( !extensions->ExtensionSupported("GL_VERSION_1_2") +// || !extensions->ExtensionSupported("GL_ARB_multitexture") ) { +// { +// vtkErrorMacro("Required extensions not supported!"); +// } +// \endcode +// +// Once you have verified that the extensions you want exist, before you +// use them you have to loaded them with the LoadExtension method. +// +// \code +// extensions->LoadExtension("GL_VERSION_1_2"); +// extensions->LoadExtension("GL_ARB_multitexture"); +// \endcode +// +// Once you have queried and loaded all of the extensions you need, you can +// delete the vtkExtensionManager. To use a constant of an extension, simply +// replace the "GL_" prefix with "vtkgl::". Likewise, replace the "gl" prefix +// of functions with "vtkgl::". In rare cases, an extension will add a type. +// In this case, add vtkgl:: to the type (i.e. vtkgl::GLchar). +// +// \code +// extensions->Delete(); +// ... +// vtkgl::ActiveTexture(vtkgl::TEXTURE0_ARB); +// \endcode +// For wgl extensions, replace the "WGL_" and "wgl" prefixes with +// "vtkwgl::". For glX extensions, replace the "GLX_" and "glX" prefixes +// with "vtkglX::". +// + +#ifndef __vtkOpenGLExtensionManager +#define __vtkOpenGLExtensionManager + +#include + +class vtkRenderWindow; + +//BTX +extern "C" { +#ifdef _WIN32 +#include // Needed for WINAPI + typedef int (WINAPI *vtkOpenGLExtensionManagerFunctionPointer)(void); +#else + typedef void (*vtkOpenGLExtensionManagerFunctionPointer)(void); +#endif +} +//ETX + +class VTK_RENDERING_EXPORT vtkOpenGLExtensionManager : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkOpenGLExtensionManager, vtkObject); + static vtkOpenGLExtensionManager *New(); + void PrintSelf(ostream &os, vtkIndent indent); + + // Description: + // Set/Get the render window to query extensions on. If set to null, + // justs queries the current render window. + vtkGetObjectMacro(RenderWindow, vtkRenderWindow); + virtual void SetRenderWindow(vtkRenderWindow *renwin); + + // Description: + // Updates the extensions string. + virtual void Update(); + + // Description: + // Returns a string listing all available extensions. Call Update first + // to validate this string. + vtkGetStringMacro(ExtensionsString); + + // Description: + // Returns true if the extension is supported, false otherwise. + virtual int ExtensionSupported(const char *name); + +//BTX + // Description: + // Returns a function pointer to the OpenGL extension function with the + // given name. Returns NULL if the function could not be retrieved. + virtual vtkOpenGLExtensionManagerFunctionPointer GetProcAddress(const char *fname); +//ETX + + // Description: + // Loads all the functions associated with the given extension into the + // appropriate static members of vtkgl. + virtual void LoadExtension(const char *name); + +protected: + vtkOpenGLExtensionManager(); + virtual ~vtkOpenGLExtensionManager(); + + vtkRenderWindow *RenderWindow; + + char *ExtensionsString; + + vtkTimeStamp BuildTime; + + virtual void ReadOpenGLExtensions(); + +private: + vtkOpenGLExtensionManager(const vtkOpenGLExtensionManager&); // Not implemented + void operator=(const vtkOpenGLExtensionManager&); // Not implemented +}; + +#endif //__vtkOpenGLExtensionManager + diff --git a/Rendering/vtkOpenGLExtensionManagerConfigure.h.in b/Rendering/vtkOpenGLExtensionManagerConfigure.h.in new file mode 100644 index 0000000..60d661d --- /dev/null +++ b/Rendering/vtkOpenGLExtensionManagerConfigure.h.in @@ -0,0 +1,36 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLExtensionManagerConfigure.h.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#cmakedefine VTK_USE_WGL_GET_PROC_ADDRESS +#cmakedefine VTK_USE_APPLE_LOADER +#cmakedefine VTK_USE_GLX_GET_PROC_ADDRESS +#cmakedefine VTK_USE_GLX_GET_PROC_ADDRESS_ARB +#cmakedefine VTK_USE_VTK_DYNAMIC_LOADER +#cmakedefine VTK_NO_EXTENSION_LOADING + +#cmakedefine VTK_DEFINE_GLX_GET_PROC_ADDRESS_PROTOTYPE + +// If using vtkDynamicLoader, we need to know where the libraries are. +#define OPENGL_LIBRARIES "@OPENGL_LIBRARIES@" + diff --git a/Rendering/vtkOpenGLFreeTypeTextMapper.cxx b/Rendering/vtkOpenGLFreeTypeTextMapper.cxx new file mode 100644 index 0000000..7268311 --- /dev/null +++ b/Rendering/vtkOpenGLFreeTypeTextMapper.cxx @@ -0,0 +1,482 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLFreeTypeTextMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLFreeTypeTextMapper.h" + +#include "vtkActor2D.h" +#include "vtkObjectFactory.h" +#include "vtkProperty2D.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" +#include "vtkWindow.h" +#include "vtkToolkits.h" // for VTK_USE_GL2PS + +#include "vtkFreeTypeUtilities.h" +#include "vtkftglConfig.h" + +#include "vtkgluPickMatrix.h" + +#include "FTFont.h" + +#ifdef VTK_USE_GL2PS +#include "gl2ps.h" +#endif // VTK_USE_GL2PS + + +//---------------------------------------------------------------------------- +// Print debug info + +#define VTK_FTTM_DEBUG 0 +#define VTK_FTTM_DEBUG_CD 0 + +//---------------------------------------------------------------------------- +// GL2PS related internal helper functions. + +#ifdef VTK_USE_GL2PS +static void +vtkOpenGLFreeTypeTextMapper_GetGL2PSFontName(vtkTextProperty *tprop, + char *ps_font) +{ + // For speed we use ARIAL == 0, COURIER == 1, TIMES == 2 + static char const *family[] = {"Helvetica", "Courier", "Times"}; + static char const *italic[] = {"Oblique", "Oblique", "Italic"}; + static char const *base[] = {"", "", "-Roman"}; + + int font = tprop->GetFontFamily(); + + if (font > 2) + { + sprintf(ps_font, "%s", tprop->GetFontFamilyAsString()); + if (tprop->GetBold()) + { + sprintf(ps_font, "%s%s", ps_font, "Bold"); + } + if (tprop->GetItalic()) + { + sprintf(ps_font, "%s%s", ps_font, "Italic"); + } + return; + } + + if (tprop->GetBold()) + { + sprintf(ps_font, "%s-%s", family[font], "Bold"); + if (tprop->GetItalic()) + { + sprintf(ps_font, "%s%s", ps_font, italic[font]); + } + } + else if (tprop->GetItalic()) + { + sprintf(ps_font, "%s-%s", family[font], italic[font]); + } + else + { + sprintf(ps_font, "%s%s", family[font], base[font]); + } +} +#endif + +//---------------------------------------------------------------------------- +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLFreeTypeTextMapper, "$Revision: 1.45 $"); +vtkStandardNewMacro(vtkOpenGLFreeTypeTextMapper); +#endif + +//---------------------------------------------------------------------------- +vtkOpenGLFreeTypeTextMapper::vtkOpenGLFreeTypeTextMapper() +{ + this->LastSize[0] = 0; + this->LastSize[1] = 0; +} + +//---------------------------------------------------------------------------- +vtkOpenGLFreeTypeTextMapper::~vtkOpenGLFreeTypeTextMapper() +{ + if (this->LastWindow) + { + this->ReleaseGraphicsResources(this->LastWindow); + } +} + +//---------------------------------------------------------------------------- +void vtkOpenGLFreeTypeTextMapper::ReleaseGraphicsResources(vtkWindow *vtkNotUsed(win)) +{ +#if VTK_FTTM_DEBUG + printf("vtkOpenGLFreeTypeTextMapper::ReleaseGraphicsResources\n"); +#endif + + this->LastWindow = NULL; + + // Very important + // the release of graphics resources indicates that significant changes have + // occurred. Old fonts, cached sizes etc are all no longer valid, so we send + // ourselves a general modified message. + + // this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkOpenGLFreeTypeTextMapper::GetSize(vtkViewport* viewport, int *size) +{ + // Check for multiline + + if (this->NumberOfLines > 1) + { + this->GetMultiLineSize(viewport, size); + return; + } + + // Check for input + + if (this->Input == NULL || this->Input[0] == '\0') + { + size[0] = size[1] = 0; + return; + } + + vtkTextProperty *tprop = this->GetTextProperty(); + if (!tprop) + { + vtkErrorMacro(<< "Need a text property to get size"); + size[0] = size[1] = 0; + return; + } + + // Check to see whether we have to rebuild anything + + if (this->GetMTime() < this->SizeBuildTime && + tprop->GetMTime() < this->SizeBuildTime) + { +#if VTK_FTTM_DEBUG + printf("vtkOpenGLFreeTypeTextMapper::GetSize: In cache!\n"); +#endif + + size[0] = this->LastSize[0]; + size[1] = this->LastSize[1]; + return; + } + + // Check for font and try to set the size + + vtkFreeTypeUtilities::Entry *entry = + vtkFreeTypeUtilities::GetInstance()->GetFont(tprop); + FTFont *font = entry ? entry->Font : NULL; + if (!font) + { + vtkErrorMacro(<< "Render - No font"); + size[0] = size[1] = 0; + return; + } + + // The font global ascender and descender might just be too high + // for given a face. Let's get a compromise by computing these values + // from some usual ascii chars. + + if (entry->LargestAscender < 0 || entry->LargestDescender < 0) + { + float llx, lly, llz, urx, ury, urz; + font->BBox("_/7Agfy", llx, lly, llz, urx, ury, urz); + entry->LargestAscender = ury; + entry->LargestDescender = lly; + } + + this->LastSize[0] = size[0] = (int)font->Advance(this->Input); + this->LastSize[1] = size[1] = + (int)(entry->LargestAscender - entry->LargestDescender); + this->LastLargestDescender = (int)entry->LargestDescender; + + this->SizeBuildTime.Modified(); +} + +//---------------------------------------------------------------------------- +void vtkOpenGLFreeTypeTextMapper::RenderOverlay(vtkViewport* viewport, + vtkActor2D* actor) +{ + vtkDebugMacro (<< "RenderOverlay"); + + // Check for input + + if (this->Input == NULL || this->Input[0] == '\0') + { + return; + } + + // Check for multi-lines + + if (this->NumberOfLines > 1) + { + this->RenderOverlayMultipleLines(viewport, actor); + return; + } + + // Get text property + + vtkTextProperty *tprop = this->GetTextProperty(); + if (!tprop) + { + vtkErrorMacro(<< "Need a text property to render mapper"); + return; + } + + // Get the window information for display + + vtkWindow* window = viewport->GetVTKWindow(); + if (this->LastWindow && this->LastWindow != window) + { + this->ReleaseGraphicsResources(this->LastWindow); + } + this->LastWindow = window; + + // Get size of text + + int size[2]; + this->GetSize(viewport, size); + + // Get the position of the text actor + + int* actorPos; + actorPos= + actor->GetActualPositionCoordinate()->GetComputedViewportValue(viewport); + + // Define bounding rectangle + + int pos[2]; + pos[0] = actorPos[0]; + pos[1] = (int)(actorPos[1] - tprop->GetLineOffset()); + + switch (tprop->GetJustification()) + { + case VTK_TEXT_LEFT: + break; + case VTK_TEXT_CENTERED: + pos[0] = pos[0] - size[0] / 2; + break; + case VTK_TEXT_RIGHT: + pos[0] = pos[0] - size[0]; + break; + } + + switch (tprop->GetVerticalJustification()) + { + case VTK_TEXT_TOP: + pos[1] = pos[1] - size[1] - this->LastLargestDescender; + break; + case VTK_TEXT_CENTERED: + pos[1] = pos[1] - size[1] / 2 - this->LastLargestDescender / 2; + break; + case VTK_TEXT_BOTTOM: + break; + } + + // Push a 2D matrix on the stack + + int *vsize = viewport->GetSize(); + double *vport = viewport->GetViewport(); + double *tileViewport = viewport->GetVTKWindow()->GetTileViewport(); + double visVP[4]; + + visVP[0] = (vport[0] >= tileViewport[0]) ? vport[0] : tileViewport[0]; + visVP[1] = (vport[1] >= tileViewport[1]) ? vport[1] : tileViewport[1]; + visVP[2] = (vport[2] <= tileViewport[2]) ? vport[2] : tileViewport[2]; + visVP[3] = (vport[3] <= tileViewport[3]) ? vport[3] : tileViewport[3]; + + if (visVP[0] == visVP[2] || visVP[1] == visVP[3]) + { + return; + } + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + if(viewport->GetIsPicking()) + { + vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(), + 1, 1, viewport->GetOrigin(), viewport->GetSize()); + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glDisable(GL_LIGHTING); + glDepthFunc(GL_ALWAYS); + + if (actor->GetProperty()->GetDisplayLocation() == VTK_FOREGROUND_LOCATION) + { + glOrtho(0, vsize[0] - 1, 0, vsize[1] - 1, 0, 1); + } + else + { + glOrtho(0, vsize[0] - 1, 0, vsize[1] - 1, -1, 0); + } + + int *winSize = viewport->GetVTKWindow()->GetSize(); + + int xoff = static_cast(pos[0] - winSize[0] * (visVP[0] - vport[0])); + int yoff = static_cast(pos[1] - winSize[1] * (visVP[1] - vport[1])); + + // When picking draw the bounds of the text as a rectangle, + // as text only picks when the pick point is exactly on the + // origin of the text + + if(viewport->GetIsPicking()) + { + float x1 = 2.0 * (float)actorPos[0] / vsize[0] - 1; + float y1 = 2.0 * ((float)actorPos[1] - tprop->GetLineOffset())/vsize[1] - 1; + float width = 2.0 * (float)size[0] / vsize[0]; + float height = 2.0 * (float)size[1] / vsize[1]; + glRectf(x1, y1, x1 + width, y1 + height); + + // Clean up and return after drawing the rectangle + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glEnable(GL_LIGHTING); + glDepthFunc(GL_LEQUAL); + + return; + } + + double* tprop_color = tprop->GetColor(); + double tprop_opacity = tprop->GetOpacity(); + + // Get the font + + vtkFreeTypeUtilities::Entry *entry = + vtkFreeTypeUtilities::GetInstance()->GetFont(tprop, tprop_color); + FTFont *font = entry ? entry->Font : NULL; + if (!font) + { + vtkErrorMacro(<< "Render - No font"); + return; + } + + struct FTGLRenderContext *ftgl_context = 0; + +#ifdef VTK_IMPLEMENT_MESA_CXX + // If we support Mangle Mesa, VTK_IMPLEMENT_MESA_CXX will be defined to + // compile this unit as a Mesa text mapper. In that case, provide a + // context to FTGL to switch dynamically to Mangle Mesa rendering. + struct FTGLRenderContext ftgl_context_mesa; + ftgl_context_mesa.UseMangleMesa = 1; + ftgl_context = &ftgl_context_mesa; +#endif + + // Setup the fonts for GL2PS output. + +#ifdef VTK_USE_GL2PS + char ps_font[64]; + vtkOpenGLFreeTypeTextMapper_GetGL2PSFontName(tprop, ps_font); +#endif // VTK_USE_GL2PS + + // Set up the shadow color + + if (tprop->GetShadow()) + { + double shadow_color[3], rgb; + rgb = ((tprop_color[0] + tprop_color[1] + tprop_color[2]) / 3.0 > 0.5) + ? 0.0 : 1.0; + shadow_color[0] = shadow_color[1] = shadow_color[2] = rgb; + + // Get the shadow font + + vtkFreeTypeUtilities::Entry *shadow_entry = + vtkFreeTypeUtilities::GetInstance()->GetFont(tprop, shadow_color); + FTFont *shadow_font = shadow_entry ? shadow_entry->Font : NULL; + if (!shadow_font) + { + vtkErrorMacro(<< "Render - No shadow font"); + return; + } + + // Set the color here since load/render glyphs is done + // on demand and this color has to be consistent for a given font entry. + + glColor4ub((unsigned char)(shadow_color[0] * 255.0), + (unsigned char)(shadow_color[1] * 255.0), + (unsigned char)(shadow_color[2] * 255.0), + (unsigned char)(tprop_opacity * 255.0)); + + // Required for clipping to work correctly + + glRasterPos2i(0, 0); + glBitmap(0, 0, 0, 0, + xoff + tprop->GetShadowOffset()[0], + yoff + tprop->GetShadowOffset()[1], NULL); + + // Draw the shadow text + + shadow_font->render(this->Input, ftgl_context); + + // Get the font again, Duh, since it may have been freed from the + // cache by the shadow font + + font = vtkFreeTypeUtilities::GetInstance()->GetFont( + tprop, tprop_color)->Font; + if (!font) + { + vtkErrorMacro(<< "Render - No font"); + return; + } + + // Shadow text for GL2PS. + +#ifdef VTK_USE_GL2PS + glRasterPos2i(xoff + tprop->GetShadowOffset()[0], + yoff + tprop->GetShadowOffset()[1]); + gl2psText(this->Input, ps_font, tprop->GetFontSize()); +#endif // VTK_USE_GL2PS + } + + // Set the color here since load/render glyphs is done + // on demand and this color has to be consistent for a given font entry. + + glColor4ub((unsigned char)(tprop_color[0] * 255.0), + (unsigned char)(tprop_color[1] * 255.0), + (unsigned char)(tprop_color[2] * 255.0), + (unsigned char)(tprop_opacity * 255.0)); + + // Required for clipping to work correctly + + glRasterPos2i(0, 0); + glBitmap(0, 0, 0, 0, xoff, yoff, NULL); + + // Display a string + + font->render(this->Input, ftgl_context); + + glFlush(); + + // Normal text for GL2PS. + +#ifdef VTK_USE_GL2PS + glRasterPos2i(xoff, yoff); + gl2psText(this->Input, ps_font, tprop->GetFontSize()); +#endif // VTK_USE_GL2PS + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glEnable(GL_LIGHTING); + glDepthFunc(GL_LEQUAL); +} + +void vtkOpenGLFreeTypeTextMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLFreeTypeTextMapper.h b/Rendering/vtkOpenGLFreeTypeTextMapper.h new file mode 100644 index 0000000..e423d34 --- /dev/null +++ b/Rendering/vtkOpenGLFreeTypeTextMapper.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLFreeTypeTextMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLFreeTypeTextMapper - 2D Text annotation support +// .SECTION Description +// vtkOpenGLFreeTypeTextMapper provides 2D text annotation support for VTK +// using the FreeType and FTGL libraries. Normally the user should use +// vtktextMapper which in turn will use this class. + +// .SECTION See Also +// vtkTextMapper + +#ifndef __vtkOpenGLFreeTypeTextMapper_h +#define __vtkOpenGLFreeTypeTextMapper_h + +#include "vtkTextMapper.h" + +//BTX +class FTFont; +//ETX + +class VTK_RENDERING_EXPORT vtkOpenGLFreeTypeTextMapper : public vtkTextMapper +{ +public: + vtkTypeRevisionMacro(vtkOpenGLFreeTypeTextMapper,vtkTextMapper); + static vtkOpenGLFreeTypeTextMapper *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Actally draw the text. + void RenderOverlay(vtkViewport* viewport, vtkActor2D* actor); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // What is the size of the rectangle required to draw this + // mapper ? + virtual void GetSize(vtkViewport* viewport, int size[2]); + +protected: + vtkOpenGLFreeTypeTextMapper(); + ~vtkOpenGLFreeTypeTextMapper(); + + vtkTimeStamp SizeBuildTime; + int LastSize[2]; + int LastLargestDescender; + +private: + vtkOpenGLFreeTypeTextMapper(const vtkOpenGLFreeTypeTextMapper&); // Not implemented. + void operator=(const vtkOpenGLFreeTypeTextMapper&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkOpenGLImageActor.cxx b/Rendering/vtkOpenGLImageActor.cxx new file mode 100644 index 0000000..8f2e433 --- /dev/null +++ b/Rendering/vtkOpenGLImageActor.cxx @@ -0,0 +1,674 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLImageActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLImageActor.h" + +#include "vtkMapper.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkImageData.h" +#include "vtkMatrix4x4.h" +#include "vtkOpenGLRenderWindow.h" + +#include + +#include "vtkOpenGL.h" + +#ifndef GL_MAX_TEXTURE_SIZE +#define GL_MAX_TEXTURE_SIZE 1024 +#endif + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLImageActor, "$Revision: 1.31.6.1 $"); +vtkStandardNewMacro(vtkOpenGLImageActor); +#endif + +// Initializes an instance, generates a unique index. +vtkOpenGLImageActor::vtkOpenGLImageActor() +{ + this->Index = 0; + this->RenderWindow = 0; + this->TextureSize[0] = 0; + this->TextureSize[1] = 0; +} + +vtkOpenGLImageActor::~vtkOpenGLImageActor() +{ + this->RenderWindow = NULL; +} + +// Release the graphics resources used by this texture. +void vtkOpenGLImageActor::ReleaseGraphicsResources(vtkWindow *renWin) +{ + if (this->Index && renWin) + { + ((vtkRenderWindow *) renWin)->MakeCurrent(); +#ifdef GL_VERSION_1_1 + // free any textures + if (glIsTexture(this->Index)) + { + GLuint tempIndex; + tempIndex = this->Index; + // NOTE: Sun's OpenGL seems to require disabling of texture before delete + glDisable(GL_TEXTURE_2D); + glDeleteTextures(1, &tempIndex); + } +#else + if (glIsList(this->Index)) + { + glDeleteLists(this->Index,1); + } +#endif + this->TextureSize[0] = 0; + this->TextureSize[1] = 0; + } + this->Index = 0; + this->RenderWindow = NULL; + this->Modified(); +} + +unsigned char *vtkOpenGLImageActor::MakeDataSuitable(int &xsize, int &ysize, + int &release, + int &reuseTexture) +{ + int contiguous = 0; + unsigned short xs,ys; + int powOfTwo = 0; + int numComp = this->Input->GetNumberOfScalarComponents(); + int xdim, ydim; + + reuseTexture = 0; + + // it must be a power of two and contiguous + // find the two used dimensions + // this assumes a 2D image, no lines here folk + if (this->DisplayExtent[0] != this->DisplayExtent[1]) + { + xdim = 0; + if (this->DisplayExtent[2] != this->DisplayExtent[3]) + { + ydim = 1; + } + else + { + ydim = 2; + } + } + else + { + xdim = 1; + ydim = 2; + } + + double *spacing = this->Input->GetSpacing(); + double *origin = this->Input->GetOrigin(); + + // compute the world coordinates + this->Coords[0] = this->DisplayExtent[0]*spacing[0] + origin[0]; + this->Coords[1] = this->DisplayExtent[2]*spacing[1] + origin[1]; + this->Coords[2] = this->DisplayExtent[4]*spacing[2] + origin[2]; + this->Coords[3] = this->DisplayExtent[1]*spacing[0] + origin[0]; + this->Coords[4] = + this->DisplayExtent[2 + (xdim == 1)]*spacing[1] + origin[1]; + this->Coords[5] = this->DisplayExtent[4]*spacing[2] + origin[2]; + this->Coords[6] = this->DisplayExtent[1]*spacing[0] + origin[0]; + this->Coords[7] = this->DisplayExtent[3]*spacing[1] + origin[1]; + this->Coords[8] = this->DisplayExtent[5]*spacing[2] + origin[2]; + this->Coords[9] = this->DisplayExtent[0]*spacing[0] + origin[0]; + this->Coords[10] = + this->DisplayExtent[2 + (ydim == 1)]*spacing[1] + origin[1]; + this->Coords[11] = this->DisplayExtent[5]*spacing[2] + origin[2]; + + // now contiguous would require that xdim = 0 and ydim = 1 + // OR xextent = 1 pixel and xdim = 1 and ydim = 2 + // OR xdim = 0 and ydim = 2 and yextent = i pixel. In addition + // the corresponding x display extents must match the + // extent of the data + int *ext = this->Input->GetExtent(); + + if ( ( xdim == 0 && ydim == 1 && + this->DisplayExtent[0] == ext[0] && + this->DisplayExtent[1] == ext[1] )|| + ( ext[0] == ext[1] && xdim == 1 && + this->DisplayExtent[2] == ext[2] && + this->DisplayExtent[3] == ext[3] ) || + ( ext[2] == ext[3] && xdim == 0 && ydim == 2 && + this->DisplayExtent[0] == ext[0] && + this->DisplayExtent[1] == ext[1] ) ) + { + contiguous = 1; + } + + // if contiguous is it a pow of 2 + if (contiguous) + { + xsize = ext[xdim*2+1] - ext[xdim*2] + 1; + // xsize and ysize must be a power of 2 in OpenGL + xs = (unsigned short)xsize; + while (!(xs & 0x01)) + { + xs = xs >> 1; + } + if (xs == 1) + { + powOfTwo = 1; + } + } + + if (contiguous && powOfTwo) + { + // can we make y a power of two also ? + ysize = this->DisplayExtent[ydim*2+1] - this->DisplayExtent[ydim*2] + 1; + ys = (unsigned short)ysize; + while (!(ys & 0x01)) + { + ys = ys >> 1; + } + // yes it is a power of two already + if (ys == 1) + { + release = 0; + this->TCoords[0] = (this->DisplayExtent[xdim*2] - ext[xdim*2] + 0.5)/xsize; + this->TCoords[1] = 0.5/ysize; + this->TCoords[2] = (this->DisplayExtent[xdim*2+1] - ext[xdim*2] + 0.5)/xsize; + this->TCoords[3] = this->TCoords[1]; + this->TCoords[4] = this->TCoords[2]; + this->TCoords[5] = 1.0 - 0.5/ysize; + this->TCoords[6] = this->TCoords[0]; + this->TCoords[7] = this->TCoords[5]; + +#ifdef GL_VERSION_1_1 + // if texture size hasn't changed, reuse old texture + if (xsize == this->TextureSize[0] && ysize == this->TextureSize[1]) + { + reuseTexture = 1; + } +#endif + return (unsigned char *) + this->Input->GetScalarPointerForExtent(this->DisplayExtent); + } + } + + // if we made it here then we must copy the data and possibly pad + // it as well + + // find the target size + xsize = 1; + while (xsize < + this->DisplayExtent[xdim*2+1] - this->DisplayExtent[xdim*2] + 1) + { + xsize *= 2; + } + ysize = 1; + while (ysize < + this->DisplayExtent[ydim*2+1] - this->DisplayExtent[ydim*2] + 1) + { + ysize *= 2; + } + + // compute the tcoords + this->TCoords[0] = 0.5/xsize; + this->TCoords[1] = 0.5/ysize; + this->TCoords[2] = (this->DisplayExtent[xdim*2+1] - this->DisplayExtent[xdim*2] + 0.5)/xsize; + this->TCoords[3] = this->TCoords[1]; + this->TCoords[4] = this->TCoords[2]; + this->TCoords[5] = (this->DisplayExtent[ydim*2+1] - this->DisplayExtent[ydim*2] + 0.5)/ysize; + this->TCoords[6] = this->TCoords[0]; + this->TCoords[7] = this->TCoords[5]; + +#ifdef GL_VERSION_1_1 + // reuse texture if texture size has not changed + if (xsize == this->TextureSize[0] && ysize == this->TextureSize[1]) + { + reuseTexture = 1; + xsize = this->DisplayExtent[xdim*2+1] - this->DisplayExtent[xdim*2] + 1; + ysize = this->DisplayExtent[ydim*2+1] - this->DisplayExtent[ydim*2] + 1; + } +#endif + + // if contiguous and texture size hasn't changed, don't copy or pad + if (reuseTexture && contiguous) + { + release = 0; + return (unsigned char *) + this->Input->GetScalarPointerForExtent(this->DisplayExtent); + } + + // allocate the memory + unsigned char *res = new unsigned char [ysize*xsize*numComp]; + release = 1; + + // copy the input data to the memory + vtkIdType inIncX, inIncY, inIncZ; + int idxZ, idxY, idxR; + unsigned char *inPtr = (unsigned char *) + this->Input->GetScalarPointerForExtent(this->DisplayExtent); + this->Input->GetContinuousIncrements(this->DisplayExtent, + inIncX, inIncY, inIncZ); + int rowLength = numComp*(this->DisplayExtent[1] -this->DisplayExtent[0] +1); + unsigned char *outPtr = res; + vtkIdType outIncY, outIncZ; + if (ydim == 2) + { + if (xdim == 0) + { + outIncZ = numComp * + (xsize - (this->DisplayExtent[1] - this->DisplayExtent[0] + 1)); + } + else + { + outIncZ = numComp * + (xsize - (this->DisplayExtent[3] - this->DisplayExtent[2] + 1)); + } + outIncY = 0; + } + else + { + outIncY = numComp * + (xsize - (this->DisplayExtent[1] - this->DisplayExtent[0] + 1)); + outIncZ = 0; + } + + + for (idxZ = this->DisplayExtent[4]; idxZ <= this->DisplayExtent[5]; idxZ++) + { + for (idxY = this->DisplayExtent[2]; idxY <= this->DisplayExtent[3]; idxY++) + { + for (idxR = 0; idxR < rowLength; idxR++) + { + // Pixel operation + *outPtr = *inPtr; + outPtr++; + inPtr++; + } + outPtr += outIncY; + inPtr += inIncY; + } + outPtr += outIncZ; + inPtr += inIncZ; + } + + return res; +} + +// Implement base class method. +void vtkOpenGLImageActor::Load(vtkRenderer *ren) +{ + GLenum format = GL_LUMINANCE; + + // need to reload the texture + if (this->GetMTime() > this->LoadTime.GetMTime() || + this->Input->GetMTime() > this->LoadTime.GetMTime() || + ren->GetRenderWindow() != this->RenderWindow) + { + int xsize, ysize; + int release, reuseTexture; + unsigned char *data = this->MakeDataSuitable(xsize,ysize, + release, reuseTexture); + int bytesPerPixel = this->Input->GetNumberOfScalarComponents(); + GLuint tempIndex=0; + + if (reuseTexture) + { +#ifdef GL_VERSION_1_1 + glBindTexture(GL_TEXTURE_2D, this->Index); +#endif + } + else + { + // free any old display lists + this->ReleaseGraphicsResources(ren->GetRenderWindow()); + this->RenderWindow = ren->GetRenderWindow(); + + // define a display list for this texture + // get a unique display list id +#ifdef GL_VERSION_1_1 + glGenTextures(1, &tempIndex); + this->Index = (long) tempIndex; + glBindTexture(GL_TEXTURE_2D, this->Index); +#else + this->Index = glGenLists(1); + glDeleteLists ((GLuint) this->Index, (GLsizei) 0); + glNewList ((GLuint) this->Index, GL_COMPILE); +#endif + + ((vtkOpenGLRenderWindow *)(ren->GetRenderWindow()))->RegisterTextureResource( this->Index ); + } + + if (this->Interpolate) + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR ); + } + else + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + } + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + + int internalFormat = bytesPerPixel; + switch (bytesPerPixel) + { + case 1: format = GL_LUMINANCE; break; + case 2: format = GL_LUMINANCE_ALPHA; break; + case 3: format = GL_RGB; break; + case 4: format = GL_RGBA; break; + } + // if we are using OpenGL 1.1, you can force 32 or16 bit textures +#ifdef GL_VERSION_1_1 + switch (bytesPerPixel) + { + case 1: internalFormat = GL_LUMINANCE8; break; + case 2: internalFormat = GL_LUMINANCE8_ALPHA8; break; + case 3: internalFormat = GL_RGB8; break; + case 4: internalFormat = GL_RGBA8; break; + } +#endif + + if (reuseTexture) + { +#ifdef GL_VERSION_1_1 + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0); + glTexSubImage2D( GL_TEXTURE_2D, 0, + 0, 0, xsize, ysize, format, + GL_UNSIGNED_BYTE, (const GLvoid *)data ); +#endif + } + else + { + glTexImage2D( GL_TEXTURE_2D, 0, internalFormat, + xsize, ysize, 0, format, + GL_UNSIGNED_BYTE, (const GLvoid *)data ); + this->TextureSize[0] = xsize; + this->TextureSize[1] = ysize; + } + +#ifndef GL_VERSION_1_1 + glEndList (); +#endif + // modify the load time to the current time + this->LoadTime.Modified(); + if (release) + { + delete [] data; + } + } + + // execute the display list that uses creates the texture +#ifdef GL_VERSION_1_1 + glBindTexture(GL_TEXTURE_2D, this->Index); +#else + glCallList ((GLuint) this->Index); +#endif + + // don't accept fragments if they have zero opacity. this will stop the + // zbuffer from be blocked by totally transparent texture fragments. + glAlphaFunc (GL_GREATER, (GLclampf) 0); + glEnable (GL_ALPHA_TEST); + + // now bind it + glEnable(GL_TEXTURE_2D); + + // draw the quad + if ( vtkMapper::GetResolveCoincidentTopology() ) + { + if ( vtkMapper::GetResolveCoincidentTopology() == + VTK_RESOLVE_SHIFT_ZBUFFER ) + { + } + else + { +#ifdef GL_VERSION_1_1 + double f, u; + glEnable(GL_POLYGON_OFFSET_FILL); + vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(f,u); + glPolygonOffset(f,u); +#endif + } + } + glDisable(GL_COLOR_MATERIAL); + glDisable (GL_CULL_FACE); + glDisable( GL_LIGHTING ); + glColor4f( 1.0, 1.0, 1.0, this->Opacity ); + glBegin( GL_QUADS ); + for (int i = 0; i < 4; i++ ) + { + glTexCoord2dv( this->TCoords + i*2 ); + glVertex3dv(this->Coords + i*3); + } + glEnd(); + // Turn lighting back on + glEnable( GL_LIGHTING ); +} + +// Determine if a given texture size is supported by the +// video card +int vtkOpenGLImageActor::TextureSizeOK( int size[2] ) +{ + // In version 1.1 or later, use proxy texture to figure out if + // the texture is too big +#ifdef GL_VERSION_1_1 + + // Do a quick test to see if we are too large + if ( size[0] > GL_MAX_TEXTURE_SIZE || + size[1] > GL_MAX_TEXTURE_SIZE ) + { + return 0; + } + + // Test the texture to see if it fits in memory + glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, + size[0], size[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)NULL ); + + GLint params = 0; + glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, + ¶ms ); + + // if it does, we will render it later. define the texture here + if ( params == 0 ) + { + // Can't use that texture + return 0; + } + else + { + return 1; + } +#else + + // Otherwise we are version 1.0 and we'll just assume the card can do 1024x1024 + if ( size[0] > 1024 || size[1] > 1024 ) + { + return 0; + } + else + { + return 1; + } +#endif +} + + +// Actual actor render method. +// Recursive to handle larger textures than can be rendered by +// a given video card. Assumes all video cards can render a texture +// of 256x256 so will fail if card reports that it cannot render +// a texture of this size rather than recursing further +void vtkOpenGLImageActor::Render(vtkRenderer *ren) +{ + // Save the current display extent since we might change it + int savedDisplayExtent[6]; + this->GetDisplayExtent( savedDisplayExtent ); + + // What is the power of two texture big enough to fit the display extent? + // This should be 1 in some direction. + int i; + int pow2[3] = {1,1,1}; + int baseSize[3]; + for ( i = 0; i < 3; i++ ) + { + baseSize[i] = this->DisplayExtent[i*2+1] - this->DisplayExtent[i*2] + 1; + while( pow2[i] < baseSize[i] ) + { + pow2[i] *= 2; + } + } + + // Find the 2d texture in the 3d pow2 structure + int size[2]; + if ( pow2[0] == 1 ) + { + size[0] = pow2[1]; + size[1] = pow2[2]; + } + else if ( pow2[1] == 1 ) + { + size[0] = pow2[0]; + size[1] = pow2[2]; + } + else + { + size[0] = pow2[0]; + size[1] = pow2[1]; + } + + // Check if we can fit this texture in memory + if ( this->TextureSizeOK(size) ) + { + // We can fit it - render + this->InternalRender( ren ); + } + else + { + // If we can't handle a 256x256 or smaller texture, + // just give up and don't render anything. Something + // must be horribly wrong... + if ( size[0] <= 256 && size[1] <= 256 ) + { + return; + } + + // We can't fit it - subdivide + int newDisplayExtent[6]; + int idx; + + // Find the biggest side + if ( baseSize[0] >= baseSize[1] && baseSize[0] >= baseSize[2] ) + { + idx = 0; + } + else if ( baseSize[1] >= baseSize[0] && baseSize[1] >= baseSize[2] ) + { + idx = 1; + } + else + { + idx = 2; + } + + // For the other two sides, just copy in the display extent + for ( i = 0; i < 3; i++ ) + { + if ( i != idx ) + { + newDisplayExtent[i*2] = this->DisplayExtent[i*2]; + newDisplayExtent[i*2+1] = this->DisplayExtent[i*2+1]; + } + } + + // For the biggest side - divide the power of two size in 1/2 + // This is the first half + newDisplayExtent[idx*2] = savedDisplayExtent[idx*2]; + newDisplayExtent[idx*2+1] = + this->DisplayExtent[idx*2] + baseSize[idx]/2 - 1; + + + // Set it as the display extent and render + this->SetDisplayExtent( newDisplayExtent ); + this->Render(ren); + + // This is the remaining side (since the display extent is not + // necessarily a power of 2, this is likely to be less than half + newDisplayExtent[idx*2] = + this->DisplayExtent[idx*2] + baseSize[idx]/2 - 1; + newDisplayExtent[idx*2+1] = savedDisplayExtent[idx*2+1]; + + // Set it as the display extent and render + this->SetDisplayExtent( newDisplayExtent ); + this->Render(ren); + } + + // Restore the old display extent + this->SetDisplayExtent( savedDisplayExtent ); +} + +// This is the non-recursive render that will not check the +// size of the image (it has already been determined to +// be fine) +void vtkOpenGLImageActor::InternalRender(vtkRenderer *ren) +{ + + // for picking + glDepthMask (GL_TRUE); + + // build transformation + if (!this->IsIdentity) + { + double *mat = this->GetMatrix()->Element[0]; + double mat2[16]; + mat2[0] = mat[0]; + mat2[1] = mat[4]; + mat2[2] = mat[8]; + mat2[3] = mat[12]; + mat2[4] = mat[1]; + mat2[5] = mat[5]; + mat2[6] = mat[9]; + mat2[7] = mat[13]; + mat2[8] = mat[2]; + mat2[9] = mat[6]; + mat2[10] = mat[10]; + mat2[11] = mat[14]; + mat2[12] = mat[3]; + mat2[13] = mat[7]; + mat2[14] = mat[11]; + mat2[15] = mat[15]; + + // insert model transformation + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glMultMatrixd(mat2); + } + + // Render the texture + this->Load(ren); + + // pop transformation matrix + if (!this->IsIdentity) + { + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } +} + +void vtkOpenGLImageActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLImageActor.h b/Rendering/vtkOpenGLImageActor.h new file mode 100644 index 0000000..7ead377 --- /dev/null +++ b/Rendering/vtkOpenGLImageActor.h @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLImageActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLImageActor - OpenGL texture map +// .SECTION Description +// vtkOpenGLImageActor is a concrete implementation of the abstract class +// vtkImageActor. vtkOpenGLImageActor interfaces to the OpenGL rendering library. + +#ifndef __vtkOpenGLImageActor_h +#define __vtkOpenGLImageActor_h + +#include "vtkImageActor.h" + +class vtkWindow; +class vtkOpenGLRenderer; +class vtkRenderWindow; + +class VTK_RENDERING_EXPORT vtkOpenGLImageActor : public vtkImageActor +{ +public: + static vtkOpenGLImageActor *New(); + vtkTypeRevisionMacro(vtkOpenGLImageActor,vtkImageActor); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Load(vtkRenderer *ren); + + // Description: + // Implement base class method. + void Render(vtkRenderer *ren); + + // Description: + // Release any graphics resources that are being consumed by this texture. + // The parameter window could be used to determine which graphic + // resources to release. Using the same texture object in multiple + // render windows is NOT currently supported. + void ReleaseGraphicsResources(vtkWindow *); + +protected: + vtkOpenGLImageActor(); + ~vtkOpenGLImageActor(); + + unsigned char *MakeDataSuitable(int &xsize, int &ysize, + int &release, int &reuseTexture); + + vtkTimeStamp LoadTime; + long Index; + vtkRenderWindow *RenderWindow; // RenderWindow used for previous render + double Coords[12]; + double TCoords[8]; + int TextureSize[2]; + + // Non-recursive internal method + void InternalRender(vtkRenderer *ren); + + // Is a certain size texture supported? + int TextureSizeOK( int size[2] ); + +private: + vtkOpenGLImageActor(const vtkOpenGLImageActor&); // Not implemented. + void operator=(const vtkOpenGLImageActor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkOpenGLImageMapper.cxx b/Rendering/vtkOpenGLImageMapper.cxx new file mode 100644 index 0000000..ce52a87 --- /dev/null +++ b/Rendering/vtkOpenGLImageMapper.cxx @@ -0,0 +1,692 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLImageMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLImageMapper.h" + +#include "vtkActor2D.h" +#include "vtkImageData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkProperty2D.h" +#include "vtkViewport.h" +#include "vtkWindow.h" +#include "vtkgluPickMatrix.h" + +#include "vtkOpenGL.h" +#include + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLImageMapper, "$Revision: 1.62 $"); +vtkStandardNewMacro(vtkOpenGLImageMapper); +#endif + +vtkOpenGLImageMapper::vtkOpenGLImageMapper() +{ +} + +vtkOpenGLImageMapper::~vtkOpenGLImageMapper() +{ +} + +//---------------------------------------------------------------------------- +// I know #define can be evil, but this macro absolutely ensures +// that the code will be inlined. The macro expects 'val' to +// be predefined to the same type as y + +#define vtkClampToUnsignedChar(x,y) \ +{ \ + val = (y); \ + if (val < 0) \ + { \ + val = 0; \ + } \ + if (val > 255) \ + { \ + val = 255; \ + } \ + (x) = (unsigned char)(val); \ +} +/* should do proper rounding, as follows: + (x) = (unsigned char)(val + 0.5f); \ +*/ + +// the bit-shift must be done after the comparison to zero +// because bit-shift is implemenation dependant for negative numbers +#define vtkClampIntToUnsignedChar(x,y,shift) \ +{ \ + val = (y); \ + if (val < 0) \ + { \ + val = 0; \ + } \ + val >>= shift; \ + if (val > 255) \ + { \ + val = 255; \ + } \ + (x) = (unsigned char)(val); \ +} + +// pad an integer to a multiply of four, for OpenGL +inline int vtkPadToFour(int n) +{ + return (((n+3)/4)*4); +} + +//--------------------------------------------------------------- +// render the image by doing the following: +// 1) apply shift and scale to pixel values +// 2) clamp to [0,255] and convert to unsigned char +// 3) draw using glDrawPixels + +template +void vtkOpenGLImageMapperRenderDouble(vtkOpenGLImageMapper *self, vtkImageData *data, + T *dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, int *vsize) +{ + int inMin0 = self->DisplayExtent[0]; + int inMax0 = self->DisplayExtent[1]; + int inMin1 = self->DisplayExtent[2]; + int inMax1 = self->DisplayExtent[3]; + + int width = inMax0 - inMin0 + 1; + int height = inMax1 - inMin1 + 1; + + vtkIdType* tempIncs = data->GetIncrements(); + vtkIdType inInc1 = tempIncs[1]; + + int bpp = data->GetNumberOfScalarComponents(); + double range[2]; + data->GetPointData()->GetScalars()->GetDataTypeRange( range ); + + // the value .999 is sensitive to z-buffer depth + glRasterPos3f((2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1), + (2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1), + (front)?(-1):(.999)); + + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + + // reformat data into unsigned char + + T *inPtr = (T *)dataPtr; + T *inPtr1 = inPtr; + + int i; + int j = height; + + unsigned char *newPtr; + if (bpp < 4) + { + newPtr = new unsigned char[vtkPadToFour(3*width*height)]; + } + else + { + newPtr = new unsigned char[4*width*height]; + } + + unsigned char *ptr = newPtr; + double val; + unsigned char tmp; + + while (--j >= 0) + { + inPtr = inPtr1; + i = width; + switch (bpp) + { + case 1: + while (--i >= 0) + { + vtkClampToUnsignedChar(tmp,((*inPtr++ + shift)*scale)); + *ptr++ = tmp; + *ptr++ = tmp; + *ptr++ = tmp; + } + break; + + case 2: + while (--i >= 0) + { + vtkClampToUnsignedChar(tmp,((*inPtr++ + shift)*scale)); + *ptr++ = tmp; + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + *ptr++ = tmp; + } + break; + + case 3: + while (--i >= 0) + { + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + } + break; + + default: + while (--i >= 0) + { + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + vtkClampToUnsignedChar(*ptr++,((*inPtr++ + shift)*scale)); + inPtr += bpp-4; + } + break; + } + inPtr1 += inInc1; + } + + if (self->GetRenderToRectangle()) + { + int rectwidth = (actorPos2[0] - actorPos[0]) + 1; + int rectheight = (actorPos2[1] - actorPos[1]) + 1; + float xscale = (float)rectwidth/width; + float yscale = (float)rectheight/height; + glPixelZoom(xscale, yscale); + } + + glDrawPixels(width, height, ((bpp < 4) ? GL_RGB : GL_RGBA), + GL_UNSIGNED_BYTE, (void *)newPtr); + + if (self->GetRenderToRectangle()) + { + // restore zoom to 1,1 otherwise other glDrawPixels cals may be affected + glPixelZoom(1.0, 1.0); + } + delete [] newPtr; +} + +//--------------------------------------------------------------- +// Same as above, but uses fixed-point math for shift and scale. +// The number of bits used for the fraction is determined from the +// scale. Enough bits are always left over for the integer that +// overflow cannot occur. + +template +void vtkOpenGLImageMapperRenderShort(vtkOpenGLImageMapper *self, vtkImageData *data, + T *dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, + int *vsize) +{ + int inMin0 = self->DisplayExtent[0]; + int inMax0 = self->DisplayExtent[1]; + int inMin1 = self->DisplayExtent[2]; + int inMax1 = self->DisplayExtent[3]; + + int width = inMax0 - inMin0 + 1; + int height = inMax1 - inMin1 + 1; + + vtkIdType* tempIncs = data->GetIncrements(); + vtkIdType inInc1 = tempIncs[1]; + + int bpp = data->GetNumberOfScalarComponents(); + + double range[2]; + data->GetPointData()->GetScalars()->GetDataTypeRange( range ); + + // the value .999 is sensitive to z-buffer depth + glRasterPos3f((2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1), + (2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1), + (front)?(-1):(.999)); + + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + + // Find the number of bits to use for the fraction: + // continue increasing the bits until there is an overflow + // in the worst case, then decrease by 1. + // The "*2.0" and "*1.0" ensure that the comparison is done + // with double-precision math. + int bitShift = 0; + double absScale = ((scale < 0) ? -scale : scale); + + while (((long)(1 << bitShift)*absScale)*2.0*USHRT_MAX < INT_MAX*1.0) + { + bitShift++; + } + bitShift--; + + long sscale = (long) (scale*(1 << bitShift)); + long sshift = (long) (sscale*shift); + /* should do proper rounding, as follows: + long sscale = (long) floor(scale*(1 << bitShift) + 0.5); + long sshift = (long) floor((scale*shift + 0.5)*(1 << bitShift)); + */ + long val; + unsigned char tmp; + + T *inPtr = (T *)dataPtr; + T *inPtr1 = inPtr; + + int i; + int j = height; + + unsigned char *newPtr; + if (bpp < 4) + { + newPtr = new unsigned char[vtkPadToFour(3*width*height)]; + } + else + { + newPtr = new unsigned char[4*width*height]; + } + + unsigned char *ptr = newPtr; + + while (--j >= 0) + { + inPtr = inPtr1; + i = width; + + switch (bpp) + { + case 1: + while (--i >= 0) + { + vtkClampIntToUnsignedChar(tmp,(*inPtr++*sscale+sshift),bitShift); + *ptr++ = tmp; + *ptr++ = tmp; + *ptr++ = tmp; + } + break; + + case 2: + while (--i >= 0) + { + vtkClampIntToUnsignedChar(tmp,(*inPtr++*sscale+sshift),bitShift); + *ptr++ = tmp; + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + *ptr++ = tmp; + } + break; + + case 3: + while (--i >= 0) + { + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + } + break; + + default: + while (--i >= 0) + { + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + vtkClampIntToUnsignedChar(*ptr++,(*inPtr++*sscale+sshift),bitShift); + inPtr += bpp-4; + } + break; + } + inPtr1 += inInc1; + } + + if (self->GetRenderToRectangle()) + { + int rectwidth = (actorPos2[0] - actorPos[0]) + 1; + int rectheight = (actorPos2[1] - actorPos[1]) + 1; + float xscale = (float)rectwidth/width; + float yscale = (float)rectheight/height; + glPixelZoom(xscale, yscale); + } + + glDrawPixels(width, height, ((bpp < 4) ? GL_RGB : GL_RGBA), + GL_UNSIGNED_BYTE, (void *)newPtr); + + if (self->GetRenderToRectangle()) + { + // restore zoom to 1,1 otherwise other glDrawPixels cals may be affected + glPixelZoom(1.0, 1.0); + } + delete [] newPtr; +} + +//--------------------------------------------------------------- +// render unsigned char data without any shift/scale + +template +void vtkOpenGLImageMapperRenderChar(vtkOpenGLImageMapper *self, vtkImageData *data, + T *dataPtr, int *actorPos, int *actorPos2, + int front, int *vsize) +{ + int inMin0 = self->DisplayExtent[0]; + int inMax0 = self->DisplayExtent[1]; + int inMin1 = self->DisplayExtent[2]; + int inMax1 = self->DisplayExtent[3]; + + int width = inMax0 - inMin0 + 1; + int height = inMax1 - inMin1 + 1; + + vtkIdType* tempIncs = data->GetIncrements(); + vtkIdType inInc1 = tempIncs[1]; + + int bpp = data->GetPointData()->GetScalars()->GetNumberOfComponents(); + + double range[2]; + data->GetPointData()->GetScalars()->GetDataTypeRange( range ); + + // the value .999 is sensitive to z-buffer depth + glRasterPos3f((2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1), + (2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1), + (front)?(-1):(.999)); + + + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + + if (self->GetRenderToRectangle()) + { + int rectwidth = (actorPos2[0] - actorPos[0]) + 1; + int rectheight = (actorPos2[1] - actorPos[1]) + 1; + float xscale = (float)rectwidth/width; + float yscale = (float)rectheight/height; + glPixelZoom(xscale, yscale); + } + // + if (bpp == 3) + { // feed through RGB bytes without reformatting + if (inInc1 != width*bpp) + { + glPixelStorei( GL_UNPACK_ROW_LENGTH, inInc1/bpp ); + } + glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, (void *)dataPtr); + } + else if (bpp == 4) + { // feed through RGBA bytes without reformatting + if (inInc1 != width*bpp) + { + glPixelStorei( GL_UNPACK_ROW_LENGTH, inInc1/bpp ); + } + glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void *)dataPtr); + } + else + { // feed through other bytes without reformatting + T *inPtr = (T *)dataPtr; + T *inPtr1 = inPtr; + unsigned char tmp; + + int i; + int j = height; + + unsigned char *newPtr; + if (bpp < 4) + { + newPtr = new unsigned char[vtkPadToFour(3*width*height)]; + } + else + { + newPtr = new unsigned char[4*width*height]; + } + + unsigned char *ptr = newPtr; + + while (--j >= 0) + { + inPtr = inPtr1; + i = width; + + switch (bpp) + { + case 1: + while (--i >= 0) + { + *ptr++ = tmp = *inPtr++; + *ptr++ = tmp; + *ptr++ = tmp; + } + break; + + case 2: + while (--i >= 0) + { + *ptr++ = tmp = *inPtr++; + *ptr++ = *inPtr++; + *ptr++ = tmp; + } + break; + + case 3: + while (--i >= 0) + { + *ptr++ = *inPtr++; + *ptr++ = *inPtr++; + *ptr++ = *inPtr++; + } + break; + + default: + while (--i >= 0) + { + *ptr++ = *inPtr++; + *ptr++ = *inPtr++; + *ptr++ = *inPtr++; + *ptr++ = *inPtr++; + inPtr += bpp-4; + } + break; + } + inPtr1 += inInc1; + } + + glDrawPixels(width, height, ((bpp < 4) ? GL_RGB : GL_RGBA), + GL_UNSIGNED_BYTE, (void *)newPtr); + + delete [] newPtr; + } + + if (self->GetRenderToRectangle()) + { + // restore zoom to 1,1 otherwise other glDrawPixels cals may be affected + glPixelZoom(1.0, 1.0); + } + + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0); +} + +//---------------------------------------------------------------------------- +// Define overloads to help the template macro below dispatch to a +// suitable implementation for each type. The last argument is of +// type "long" for the template and of type "int" for the +// non-templates. The template macro's call to this function always +// passes a literal "1" as the last argument, which requires a +// conversion to produce a long. This helps broken compilers select +// the non-template even when the template is otherwise an equal +// match. +template +void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data, + T *dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, int *vsize, + long) +{ + vtkOpenGLImageMapperRenderDouble(self, data, dataPtr, shift, scale, + actorPos, actorPos2, front, vsize); +} + +void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data, + char* dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, int *vsize, + int) +{ + if(shift == 0.0 && scale == 1.0) + { + vtkOpenGLImageMapperRenderChar(self, data, dataPtr, + actorPos, actorPos2, front, vsize); + } + else + { + vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale, + actorPos, actorPos2, front, vsize); + } +} +void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data, + unsigned char* dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, int *vsize, + int) +{ + if(shift == 0.0 && scale == 1.0) + { + vtkOpenGLImageMapperRenderChar(self, data, dataPtr, + actorPos, actorPos2, front, vsize); + } + else + { + vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale, + actorPos, actorPos2, front, vsize); + } +} +void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data, + signed char* dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, int *vsize, + int) +{ + if(shift == 0.0 && scale == 1.0) + { + vtkOpenGLImageMapperRenderChar(self, data, dataPtr, + actorPos, actorPos2, front, vsize); + } + else + { + vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale, + actorPos, actorPos2, front, vsize); + } +} + +void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data, + short* dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, int *vsize, + int) +{ + vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale, + actorPos, actorPos2, front, vsize); +} + +void vtkOpenGLImageMapperRender(vtkOpenGLImageMapper *self, vtkImageData *data, + unsigned short* dataPtr, double shift, double scale, + int *actorPos, int *actorPos2, int front, int *vsize, + int) +{ + vtkOpenGLImageMapperRenderShort(self, data, dataPtr, shift, scale, + actorPos, actorPos2, front, vsize); +} + +//---------------------------------------------------------------------------- +// Expects data to be X, Y, components + +void vtkOpenGLImageMapper::RenderData(vtkViewport* viewport, + vtkImageData *data, vtkActor2D *actor) +{ + void *ptr0; + double shift, scale; + + vtkWindow* window = (vtkWindow *) viewport->GetVTKWindow(); + if (!window) + { + vtkErrorMacro (<<"vtkOpenGLImageMapper::RenderData - no window set for viewport"); + return; + } + + // Make this window current. May have become not current due to + // data updates since the render started. + window->MakeCurrent(); + + shift = this->GetColorShift(); + scale = this->GetColorScale(); + + ptr0 = data->GetScalarPointer(this->DisplayExtent[0], + this->DisplayExtent[2], + this->DisplayExtent[4]); + + // push a 2D matrix on the stack + int *vsize = viewport->GetSize(); + glMatrixMode( GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + if(viewport->GetIsPicking()) + { + vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(), + 1, 1, viewport->GetOrigin(), vsize); + } + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + // If picking then set up a model view matrix + if(viewport->GetIsPicking()) + { + glOrtho(0,vsize[0] -1, 0, vsize[1] -1, 0, 1); + } + + glDisable( GL_LIGHTING); + + // Get the position of the text actor + int* actorPos = + actor->GetPositionCoordinate()->GetComputedViewportValue(viewport); + int* actorPos2 = + actor->GetPosition2Coordinate()->GetComputedViewportValue(viewport); + // negative positions will already be clipped to viewport + actorPos[0] += this->PositionAdjustment[0]; + actorPos[1] += this->PositionAdjustment[1]; + // if picking then only draw a polygon, since an image can not be picked + if(viewport->GetIsPicking()) + { + int inMin0 = this->DisplayExtent[0]; + int inMax0 = this->DisplayExtent[1]; + int inMin1 = this->DisplayExtent[2]; + int inMax1 = this->DisplayExtent[3]; + + float width = inMax0 - inMin0 + 1; + float height = inMax1 - inMin1 + 1; + float x1 = (2.0 * (GLfloat)(actorPos[0]) / vsize[0] - 1); + float y1 = (2.0 * (GLfloat)(actorPos[1]) / vsize[1] - 1); + glRectf(x1, y1, x1+width, y1+height); + // clean up and return + glMatrixMode( GL_PROJECTION); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW); + glPopMatrix(); + glEnable( GL_LIGHTING); + return; + } + + int front = + (actor->GetProperty()->GetDisplayLocation() == VTK_FOREGROUND_LOCATION); + +#if defined(sparc) && defined(GL_VERSION_1_1) + glDisable(GL_BLEND); +#endif + switch (data->GetPointData()->GetScalars()->GetDataType()) + { + vtkTemplateMacro( + vtkOpenGLImageMapperRender(this, data, static_cast(ptr0), + shift, scale, actorPos, actorPos2, front, vsize, + 1) + ); + default: + vtkErrorMacro ( << "Unsupported image type: " << data->GetScalarType()); + } + + glMatrixMode( GL_PROJECTION); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW); + glPopMatrix(); + glEnable( GL_LIGHTING); +#if defined(sparc) && defined(GL_VERSION_1_1) + glEnable(GL_BLEND); +#endif +} + +void vtkOpenGLImageMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLImageMapper.h b/Rendering/vtkOpenGLImageMapper.h new file mode 100644 index 0000000..efa183c --- /dev/null +++ b/Rendering/vtkOpenGLImageMapper.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLImageMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLImageMapper - 2D image display support for OpenGL +// .SECTION Description +// vtkOpenGLImageMapper is a concrete subclass of vtkImageMapper that +// renders images under OpenGL + +// .SECTION See Also +// vtkImageMapper + +#ifndef __vtkOpenGLImageMapper_h +#define __vtkOpenGLImageMapper_h + + +#include "vtkImageMapper.h" +class vtkActor2D; + + +class VTK_RENDERING_EXPORT vtkOpenGLImageMapper : public vtkImageMapper +{ +public: + static vtkOpenGLImageMapper *New(); + vtkTypeRevisionMacro(vtkOpenGLImageMapper,vtkImageMapper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Handle the render method. + void RenderOverlay(vtkViewport* viewport, vtkActor2D* actor) { + this->RenderStart(viewport,actor);} + + // Description: + // Called by the Render function in vtkImageMapper. Actually draws + // the image to the screen. + void RenderData(vtkViewport* viewport, vtkImageData* data, + vtkActor2D* actor); + +protected: + // + // + vtkOpenGLImageMapper(); + ~vtkOpenGLImageMapper(); + +private: + vtkOpenGLImageMapper(const vtkOpenGLImageMapper&); // Not implemented. + void operator=(const vtkOpenGLImageMapper&); // Not implemented. +}; + + +#endif + + + + + + + + + diff --git a/Rendering/vtkOpenGLLight.cxx b/Rendering/vtkOpenGLLight.cxx new file mode 100644 index 0000000..c9a4e79 --- /dev/null +++ b/Rendering/vtkOpenGLLight.cxx @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLLight.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLLight.h" + +#include "vtkOpenGLRenderer.h" +#include "vtkObjectFactory.h" +#include "vtkMatrix4x4.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif + +#include + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLLight, "$Revision: 1.23 $"); +vtkStandardNewMacro(vtkOpenGLLight); +#endif + +// Implement base class method. +void vtkOpenGLLight::Render(vtkRenderer *vtkNotUsed(ren),int light_index) +{ + float dx, dy, dz; + float color[4]; + float Info[4]; + vtkMatrix4x4 *xform = NULL; + + // get required info from light + + dx = this->FocalPoint[0] - this->Position[0]; + dy = this->FocalPoint[1] - this->Position[1]; + dz = this->FocalPoint[2] - this->Position[2]; + + if(this->TransformMatrix != NULL) + { + xform = vtkMatrix4x4::New(); + xform->DeepCopy(this->TransformMatrix); + xform->Transpose(); + + // code assumes that we're already in GL_MODELVIEW matrix mode + glPushMatrix(); + glMultMatrixd(xform->Element[0]); + } + + color[0] = this->Intensity * this->AmbientColor[0]; + color[1] = this->Intensity * this->AmbientColor[1]; + color[2] = this->Intensity * this->AmbientColor[2]; + color[3] = 1.0; + glLightfv((GLenum)light_index, GL_AMBIENT, color); + + color[0] = this->Intensity * this->DiffuseColor[0]; + color[1] = this->Intensity * this->DiffuseColor[1]; + color[2] = this->Intensity * this->DiffuseColor[2]; + glLightfv((GLenum)light_index, GL_DIFFUSE, color); + + color[0] = this->Intensity * this->SpecularColor[0]; + color[1] = this->Intensity * this->SpecularColor[1]; + color[2] = this->Intensity * this->SpecularColor[2]; + glLightfv((GLenum)light_index, GL_SPECULAR, color); + + // define the light source + if (!this->Positional) + { + Info[0] = -dx; + Info[1] = -dy; + Info[2] = -dz; + Info[3] = 0.0; + + glLightf((GLenum)light_index, GL_SPOT_EXPONENT, 0); + glLightf((GLenum)light_index, GL_SPOT_CUTOFF, 180); + + glLightfv((GLenum)light_index, GL_POSITION, Info ); + } + else + { + // specify position and attenuation + Info[0] = this->Position[0]; + Info[1] = this->Position[1]; + Info[2] = this->Position[2]; + Info[3] = 1.0; + glLightfv((GLenum)light_index, GL_POSITION, Info ); + + glLightf((GLenum)light_index, + GL_CONSTANT_ATTENUATION, this->AttenuationValues[0]); + glLightf((GLenum)light_index, + GL_LINEAR_ATTENUATION, this->AttenuationValues[1]); + glLightf((GLenum)light_index, + GL_QUADRATIC_ATTENUATION, this->AttenuationValues[2]); + + // set up spot parameters if neccesary + if (this->ConeAngle < 180.0) + { + Info[0] = dx; + Info[1] = dy; + Info[2] = dz; + glLightfv((GLenum)light_index, GL_SPOT_DIRECTION, Info ); + glLightf((GLenum)light_index, GL_SPOT_EXPONENT, this->Exponent); + glLightf((GLenum)light_index, GL_SPOT_CUTOFF, this->ConeAngle); + } + else + { + glLighti((GLenum)light_index, GL_SPOT_CUTOFF, 180); + } + } + + if(this->TransformMatrix != NULL) + { + glPopMatrix(); + xform->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkOpenGLLight::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLLight.h b/Rendering/vtkOpenGLLight.h new file mode 100644 index 0000000..bc98e19 --- /dev/null +++ b/Rendering/vtkOpenGLLight.h @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLLight.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLLight - OpenGL light +// .SECTION Description +// vtkOpenGLLight is a concrete implementation of the abstract class vtkLight. +// vtkOpenGLLight interfaces to the OpenGL rendering library. + +#ifndef __vtkOpenGLLight_h +#define __vtkOpenGLLight_h + +#include "vtkLight.h" + +class vtkOpenGLRenderer; + +class VTK_RENDERING_EXPORT vtkOpenGLLight : public vtkLight +{ +public: + static vtkOpenGLLight *New(); + vtkTypeRevisionMacro(vtkOpenGLLight,vtkLight); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Render(vtkRenderer *ren,int light_index); + +protected: + vtkOpenGLLight() {}; + ~vtkOpenGLLight() {}; +private: + vtkOpenGLLight(const vtkOpenGLLight&); // Not implemented. + void operator=(const vtkOpenGLLight&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkOpenGLPolyDataMapper.cxx b/Rendering/vtkOpenGLPolyDataMapper.cxx new file mode 100644 index 0000000..4a4826c --- /dev/null +++ b/Rendering/vtkOpenGLPolyDataMapper.cxx @@ -0,0 +1,1938 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLPolyDataMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLPolyDataMapper.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkCommand.h" +#include "vtkDataArray.h" +#include "vtkFloatArray.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderer.h" +#include "vtkPlane.h" +#include "vtkPlaneCollection.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolygon.h" +#include "vtkProperty.h" +#include "vtkTimerLog.h" +#include "vtkTriangle.h" +#include "vtkOpenGLRenderWindow.h" +#include "vtkOpenGLTexture.h" +#include "vtkImageData.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif + +#include + + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLPolyDataMapper, "$Revision: 1.106 $"); +vtkStandardNewMacro(vtkOpenGLPolyDataMapper); +#endif + +// some definitions for what the polydata has in it +#define VTK_PDM_NORMALS 0x01 +#define VTK_PDM_COLORS 0x02 +#define VTK_PDM_TCOORDS 0x04 +#define VTK_PDM_CELL_COLORS 0x08 +#define VTK_PDM_CELL_NORMALS 0x10 +#define VTK_PDM_POINT_TYPE_FLOAT 0x20 +#define VTK_PDM_POINT_TYPE_DOUBLE 0x40 +#define VTK_PDM_NORMAL_TYPE_FLOAT 0x80 +#define VTK_PDM_NORMAL_TYPE_DOUBLE 0x100 +#define VTK_PDM_TCOORD_TYPE_FLOAT 0x200 +#define VTK_PDM_TCOORD_TYPE_DOUBLE 0x400 +#define VTK_PDM_TCOORD_1D 0x800 +#define VTK_PDM_OPAQUE_COLORS 0x1000 +#define VTK_PDM_USE_FIELD_DATA 0x2000 + +// Construct empty object. +vtkOpenGLPolyDataMapper::vtkOpenGLPolyDataMapper() +{ + this->ListId = 0; + this->TotalCells = 0; + this->InternalColorTexture = 0; +} + +// Destructor (don't call ReleaseGraphicsResources() since it is virtual +vtkOpenGLPolyDataMapper::~vtkOpenGLPolyDataMapper() +{ + if (this->LastWindow) + { + this->ReleaseGraphicsResources(this->LastWindow); + } + if (this->InternalColorTexture) + { // Resources released previously. + this->InternalColorTexture->Delete(); + this->InternalColorTexture = 0; + } +} + +// Release the graphics resources used by this mapper. In this case, release +// the display list if any. +void vtkOpenGLPolyDataMapper::ReleaseGraphicsResources(vtkWindow *win) +{ + if (this->ListId && win) + { + win->MakeCurrent(); + glDeleteLists(this->ListId,1); + this->ListId = 0; + } + this->LastWindow = NULL; + // We may not want to do this here. + if (this->InternalColorTexture) + { + this->InternalColorTexture->ReleaseGraphicsResources(win); + } +} + +// +// Receives from Actor -> maps data to primitives +// +void vtkOpenGLPolyDataMapper::RenderPiece(vtkRenderer *ren, vtkActor *act) +{ + vtkPolyData *input= this->GetInput(); + vtkPlaneCollection *clipPlanes; + vtkPlane *plane; + int i, numClipPlanes; + double planeEquation[4]; + + // + // make sure that we've been properly initialized + // + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + return; + } + + if ( input == NULL ) + { + vtkErrorMacro(<< "No input!"); + return; + } + else + { + this->InvokeEvent(vtkCommand::StartEvent,NULL); + if (!this->Static) + { + input->Update(); + } + this->InvokeEvent(vtkCommand::EndEvent,NULL); + + vtkIdType numPts = input->GetNumberOfPoints(); + if (numPts == 0) + { + vtkDebugMacro(<< "No points!"); + return; + } + } + + if ( this->LookupTable == NULL ) + { + this->CreateDefaultLookupTable(); + } + + // make sure our window is current + ren->GetRenderWindow()->MakeCurrent(); + + clipPlanes = this->ClippingPlanes; + + if (clipPlanes == NULL) + { + numClipPlanes = 0; + } + else + { + numClipPlanes = clipPlanes->GetNumberOfItems(); + if (numClipPlanes > 6) + { + vtkErrorMacro(<< "OpenGL guarantees at most 6 additional clipping planes"); + } + } + + for (i = 0; i < numClipPlanes; i++) + { + glEnable((GLenum)(GL_CLIP_PLANE0+i)); + } + + if ( clipPlanes ) + { + vtkMatrix4x4 *actorMatrix = vtkMatrix4x4::New(); + act->GetMatrix( actorMatrix ); + actorMatrix->Invert(); + + double origin[4], normal[3], point[4]; + + for (i = 0; i < numClipPlanes; i++) + { + plane = (vtkPlane *)clipPlanes->GetItemAsObject(i); + + plane->GetOrigin(origin); + plane->GetNormal(normal); + + point[0] = origin[0] + normal[0]; + point[1] = origin[1] + normal[1]; + point[2] = origin[2] + normal[2]; + + origin[3] = point[3] = 1.0; + + actorMatrix->MultiplyPoint( origin, origin ); + actorMatrix->MultiplyPoint( point, point ); + + if ( origin[3] != 1.0 ) + { + origin[0] /= origin[3]; + origin[1] /= origin[3]; + origin[2] /= origin[3]; + } + + if ( point[3] != 1.0 ) + { + point[0] /= point[3]; + point[1] /= point[3]; + point[2] /= point[3]; + } + + normal[0] = point[0] - origin[0]; + normal[1] = point[1] - origin[1]; + normal[2] = point[2] - origin[2]; + + planeEquation[0] = normal[0]; + planeEquation[1] = normal[1]; + planeEquation[2] = normal[2]; + planeEquation[3] = -(planeEquation[0]*origin[0]+ + planeEquation[1]*origin[1]+ + planeEquation[2]*origin[2]); + glClipPlane((GLenum)(GL_CLIP_PLANE0+i),planeEquation); + } + + actorMatrix->Delete(); + } + + // For vertex coloring, this sets this->Colors as side effect. + // For texture map coloring, this sets ColorCoordinates + // and ColorTextureMap as a side effect. + // I moved this out of the conditional because it is fast. + // Color arrays are cached. If nothing has changed, + // then the scalars do not have to be regenerted. + this->MapScalars(act->GetProperty()->GetOpacity()); + // If we are coloring by texture, then load the texture map. + if (this->ColorTextureMap) + { + if (this->InternalColorTexture == 0) + { + this->InternalColorTexture = vtkOpenGLTexture::New(); + this->InternalColorTexture->RepeatOff(); + } + this->InternalColorTexture->SetInput(this->ColorTextureMap); + // Keep color from interacting with texture. + float info[4]; + info[0] = info[1] = info[2] = info[3] = 1.0; + glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, info ); + } + + // + // if something has changed regenerate colors and display lists + // if required + // + int noAbort=1; + if ( this->GetMTime() > this->BuildTime || + input->GetMTime() > this->BuildTime || + act->GetProperty()->GetMTime() > this->BuildTime || + ren->GetRenderWindow() != this->LastWindow) + { + if (!this->ImmediateModeRendering && + !this->GetGlobalImmediateModeRendering()) + { + this->ReleaseGraphicsResources(ren->GetRenderWindow()); + this->LastWindow = ren->GetRenderWindow(); + + // If we are coloring by texture, then load the texture map. + // Use Map as indicator, because texture hangs around. + if (this->ColorTextureMap) + { + this->InternalColorTexture->Load(ren); + } + + // get a unique display list id + this->ListId = glGenLists(1); + glNewList(this->ListId,GL_COMPILE); + + noAbort = this->Draw(ren,act); + glEndList(); + + // Time the actual drawing + this->Timer->StartTimer(); + glCallList(this->ListId); + this->Timer->StopTimer(); + } + else + { + this->ReleaseGraphicsResources(ren->GetRenderWindow()); + this->LastWindow = ren->GetRenderWindow(); + } + if (noAbort) + { + this->BuildTime.Modified(); + } + } + // if nothing changed but we are using display lists, draw it + else + { + if (!this->ImmediateModeRendering && + !this->GetGlobalImmediateModeRendering()) + { + // If we are coloring by texture, then load the texture map. + // Use Map as indicator, because texture hangs around. + if (this->ColorTextureMap) + { + this->InternalColorTexture->Load(ren); + } + + // Time the actual drawing + this->Timer->StartTimer(); + glCallList(this->ListId); + this->Timer->StopTimer(); + } + } + + // if we are in immediate mode rendering we always + // want to draw the primitives here + if (this->ImmediateModeRendering || + this->GetGlobalImmediateModeRendering()) + { + // If we are coloring by texture, then load the texture map. + // Use Map as indicator, because texture hangs around. + if (this->ColorTextureMap) + { + this->InternalColorTexture->Load(ren); + } + // Time the actual drawing + this->Timer->StartTimer(); + this->Draw(ren,act); + this->Timer->StopTimer(); + } + + this->TimeToDraw = (float)this->Timer->GetElapsedTime(); + + // If the timer is not accurate enough, set it to a small + // time so that it is not zero + if ( this->TimeToDraw == 0.0 ) + { + this->TimeToDraw = 0.0001; + } + + for (i = 0; i < numClipPlanes; i++) + { + glDisable((GLenum)(GL_CLIP_PLANE0+i)); + } +} + + +// +// Helper routine which starts a poly, triangle or quad based upon +// the number of points in the polygon and whether triangles or quads +// were the last thing being drawn (we can get better performance if we +// can draw several triangles within a single glBegin(GL_TRIANGLES) or +// several quads within a single glBegin(GL_QUADS). +// +static void vtkOpenGLBeginPolyTriangleOrQuad(GLenum aGlFunction, + GLenum &previousGlFunction, + int npts) +{ + if (aGlFunction == GL_POLYGON) + { + switch (npts) + { + case 3: // Need to draw a triangle. + if (previousGlFunction != GL_TRIANGLES) + { + // we were not already drawing triangles, were we drawing quads? + if (previousGlFunction == GL_QUADS) + { + // we were previously drawing quads, close down the quads. + glEnd(); + } + // start drawing triangles + previousGlFunction = GL_TRIANGLES; + glBegin(GL_TRIANGLES); + } + break; + case 4: // Need to draw a quad + if (previousGlFunction != GL_QUADS) + { + // we were not already drawing quads, were we drawing triangles? + if (previousGlFunction == GL_TRIANGLES) + { + // we were previously drawing triangles, close down the triangles. + glEnd(); + } + // start drawing quads + previousGlFunction = GL_QUADS; + glBegin(GL_QUADS); + } + break; + default: + // if we were supposed to be drawing polygons but were really + // drawing triangles or quads, then we need to close down the + // triangles or quads and begin a polygon + if (previousGlFunction != GL_INVALID_VALUE + && previousGlFunction != GL_POLYGON) + { + glEnd(); + } + previousGlFunction = GL_POLYGON; + glBegin(aGlFunction); + break; + } + } + else if (aGlFunction == GL_POINTS) + { + // we are supposed to be drawing points + if (previousGlFunction != GL_POINTS) + { + // We were not drawing points before this, switch to points. + // We don't need to worry about switching from triangles or quads + // since draw all points before drawing any polygons (i.e. in the polys + // case we switch to triangles and quads as an optimization, there is + // nothing to switch to that is below points). + previousGlFunction = GL_POINTS; + glBegin(GL_POINTS); + } + } + else + { + previousGlFunction = aGlFunction; + glBegin(aGlFunction); + } +} + + +#define vtkDrawPointsMacro(ptype,ntype,glVertFuncs,glInitFuncs) \ +{ \ + vtkIdType nPts; unsigned short count = 0; \ + ptype *points = (ptype *)voidPoints; \ + glInitFuncs \ + glBegin(GL_POINTS); \ + while (ptIds < endPtIds) \ + { \ + nPts = *ptIds; \ + ++ptIds; \ + while (nPts > 0) \ + { \ + glVertFuncs \ + ++ptIds; \ + --nPts; \ + } \ + if (++count == 10000) \ + { \ + cellNum += 10000; \ + count = 0; \ + this->UpdateProgress((double)cellNum/this->TotalCells); \ + if (ren->GetRenderWindow()->CheckAbortStatus()) \ + { \ + noAbort = 0; \ + break; \ + } \ + } \ + } \ + cellNum += count; \ + glEnd(); \ +} + +#define vtkDrawPrimsMacro(ptype,ntype,prim,glVertFuncs,glInitFuncs) \ +{ \ + vtkIdType nPts; unsigned short count = 0; \ + ptype *points = (ptype *)voidPoints; \ + glInitFuncs \ + while (ptIds < endPtIds) \ + { \ + nPts = *ptIds; \ + ++ptIds; \ + glBegin(prim); \ + while (nPts > 0) \ + { \ + glVertFuncs \ + ++ptIds; \ + --nPts; \ + } \ + glEnd(); \ + if (++count == 10000) \ + { \ + cellNum += 10000; \ + count = 0; \ + this->UpdateProgress((double)cellNum/this->TotalCells); \ + if (ren->GetRenderWindow()->CheckAbortStatus()) \ + { \ + noAbort = 0; \ + break; \ + } \ + } \ + } \ + cellNum += count; \ +} + +#define vtkDrawPolysMacro(ptype,ntype,ttype,prim,glVertFuncs,glCellFuncs,glInitFuncs) \ +{ \ + vtkIdType nPts; unsigned short count = 0; \ + ptype *points = (ptype *)voidPoints; \ + GLenum previousGlFunction=GL_INVALID_VALUE; \ + glInitFuncs \ + while (ptIds < endPtIds) \ + { \ + nPts = *ptIds; \ + ++ptIds; \ + vtkOpenGLBeginPolyTriangleOrQuad( prim, previousGlFunction, nPts ); \ + glCellFuncs \ + while (nPts > 0) \ + { \ + glVertFuncs \ + ++ptIds; \ + --nPts; \ + } \ + if (++count == 10000) \ + { \ + cellNum += 10000; \ + count = 0; \ + this->UpdateProgress((double)cellNum/this->TotalCells); \ + if (ren->GetRenderWindow()->CheckAbortStatus()) \ + { \ + noAbort = 0; \ + break; \ + } \ + } \ + if ((previousGlFunction != GL_TRIANGLES) \ + && (previousGlFunction != GL_QUADS) \ + && (previousGlFunction != GL_POINTS)) \ + { \ + glEnd(); \ + } \ + } \ + cellNum += count; \ + if ((previousGlFunction == GL_TRIANGLES) \ + || (previousGlFunction == GL_QUADS) \ + || (previousGlFunction == GL_POINTS)) \ + { \ + glEnd(); \ + } \ +} + +#define vtkDrawStripLinesMacro(ptype,ntype,ttype,prim,glVertFuncs,glCellFuncs,glInitFuncs) \ +{ \ + vtkIdType nPts; \ + ptype *points = (ptype *)voidPoints; \ + vtkIdType *savedPtIds = ptIds; \ + glInitFuncs \ + while (ptIds < endPtIds) \ + { \ + glBegin(prim); \ + nPts = *ptIds; \ + ++ptIds; \ + glCellFuncs \ + while (nPts > 0) \ + { \ + glVertFuncs \ + ptIds += 2; \ + nPts -= 2; \ + } \ + glEnd(); \ + ptIds += nPts; /* nPts could be 0 or -1 here */ \ + } \ + ptIds = savedPtIds; \ + while (ptIds < endPtIds) \ + { \ + glBegin(prim); \ + nPts = *ptIds; \ + ++ptIds; \ + glCellFuncs \ + ++ptIds; \ + --nPts; \ + while (nPts > 0) \ + { \ + glVertFuncs \ + ptIds += 2; \ + nPts -= 2; \ + } \ + glEnd(); \ + ptIds += nPts; /* nPts could be 0 or -1 here */ \ + } \ +} + +void vtkOpenGLPolyDataMapper::DrawPoints(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *ca, + vtkRenderer *ren) +{ + void *voidPoints = p->GetVoidPointer(0); + void *voidNormals = 0; + unsigned char *colors = 0; + if (ca->GetNumberOfCells() == 0) + { + return; + } + if (n) + { + voidNormals = n->GetVoidPointer(0); + } + if (c) + { + colors = c->GetPointer(0); + } + + vtkIdType *ptIds = ca->GetPointer(); + vtkIdType *endPtIds = ptIds + ca->GetNumberOfConnectivityEntries(); + + // draw all the elements, use fast path if available + switch (idx) + { + case VTK_PDM_POINT_TYPE_FLOAT: + vtkDrawPointsMacro(float, float, glVertex3fv(points + 3**ptIds);,;); + break; + case VTK_PDM_POINT_TYPE_DOUBLE: + vtkDrawPointsMacro(double, float, glVertex3dv(points + 3**ptIds);,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT|VTK_PDM_NORMAL_TYPE_FLOAT|VTK_PDM_NORMALS: + vtkDrawPointsMacro(float, float, + glNormal3fv(normals + 3**ptIds); + glVertex3fv(points + 3**ptIds);, + float *normals = (float *)voidNormals;); + + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS: + vtkDrawPointsMacro(float, float, + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;); + + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPointsMacro(float, float, + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS: + vtkDrawPointsMacro(float, float, + glNormal3fv(normals + 3**ptIds); + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPointsMacro(float, float, + glNormal3fv(normals + 3**ptIds); + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + float *normals = (float *)voidNormals;); + break; + default: + { + int j; + vtkIdType *pts = 0; + vtkIdType npts = 0; + unsigned short count = 0; + glBegin(GL_POINTS); + for (ca->InitTraversal(); noAbort && ca->GetNextCell(npts,pts); + count++) + { + for (j = 0; j < npts; j++) + { + if (c) + { + if (idx & 0x08) + { + glColor4ubv(c->GetPointer(cellNum << 2)); + } + else + { + glColor4ubv(c->GetPointer(pts[j]<< 2)); + } + } + if (t) + { + if (idx & VTK_PDM_TCOORD_1D) + { + glTexCoord1dv(t->GetTuple(pts[j])); + } + else + { + glTexCoord2dv(t->GetTuple(pts[j])); + } + } + if (n) + { + if (idx & 0x10) + { + glNormal3dv(n->GetTuple(cellNum)); + } + else + { + glNormal3dv(n->GetTuple(pts[j])); + } + } + glVertex3dv(p->GetPoint(pts[j])); + } + + // check for abort condition + if (count == 10000) + { + count = 0; + // report progress + this->UpdateProgress((double)cellNum/this->TotalCells); + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + noAbort = 0; + } + } + ++cellNum; + } + glEnd(); + } + } +} + + +void vtkOpenGLPolyDataMapper::DrawLines(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *ca, + vtkRenderer *ren) +{ + void *voidPoints = p->GetVoidPointer(0); + void *voidNormals = 0; + void *voidTCoords = 0; + unsigned char *colors = 0; + if (ca->GetNumberOfCells() == 0) + { + return; + } + if (n) + { + voidNormals = n->GetVoidPointer(0); + } + if (t) + { + voidTCoords = t->GetVoidPointer(0); + } + if (c) + { + colors = c->GetPointer(0); + } + vtkIdType *ptIds = ca->GetPointer(); + vtkIdType *endPtIds = ptIds + ca->GetNumberOfConnectivityEntries(); + + // draw all the elements, use fast path if available + switch (idx) + { + case VTK_PDM_POINT_TYPE_FLOAT: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glVertex3fv(points + 3**ptIds);,;); + break; + case VTK_PDM_POINT_TYPE_DOUBLE: + vtkDrawPrimsMacro(double, float, GL_LINE_STRIP, + glVertex3dv(points + 3**ptIds);,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT|VTK_PDM_NORMAL_TYPE_FLOAT|VTK_PDM_NORMALS: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glNormal3fv(normals + 3**ptIds); + glVertex3fv(points + 3**ptIds);, + float *normals = (float *)voidNormals;); + + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glNormal3fv(normals + 3**ptIds); + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + float *normals = (float *)voidNormals; + ); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glNormal3fv(normals + 3**ptIds); + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + float *normals = (float *)voidNormals; + ); + break; + case VTK_PDM_POINT_TYPE_FLOAT | + VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORD_1D | VTK_PDM_TCOORDS: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glTexCoord1fv(tcoords + *ptIds); + glVertex3fv(points + 3**ptIds);, + float *tcoords = (float *)voidTCoords; + ); + break; + case VTK_PDM_POINT_TYPE_FLOAT | + VTK_PDM_NORMAL_TYPE_FLOAT | VTK_PDM_NORMALS | + VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORD_1D | VTK_PDM_TCOORDS: + vtkDrawPrimsMacro(float, float, GL_LINE_STRIP, + glNormal3fv(normals + 3**ptIds); + glTexCoord1fv(tcoords + *ptIds); + glVertex3fv(points + 3**ptIds);, + float *tcoords = (float *)voidTCoords; + float *normals = (float *)voidNormals; + ); + break; + default: + { + int j; + vtkIdType *pts = 0; + vtkIdType npts = 0; + unsigned short count = 0; + for (ca->InitTraversal(); noAbort && ca->GetNextCell(npts,pts); + count++) + { + glBegin(GL_LINE_STRIP); + for (j = 0; j < npts; j++) + { + if (c) + { + if (idx & 0x08) + { + glColor4ubv(c->GetPointer(cellNum << 2)); + } + else + { + glColor4ubv(c->GetPointer(pts[j] << 2)); + } + } + if (t) + { + if (idx & VTK_PDM_TCOORD_1D) + { + glTexCoord1dv(t->GetTuple(pts[j])); + } + else + { + glTexCoord2dv(t->GetTuple(pts[j])); + } + } + if (n) + { + if (idx & 0x10) + { + glNormal3dv(n->GetTuple(cellNum)); + } + else + { + glNormal3dv(n->GetTuple(pts[j])); + } + } + glVertex3dv(p->GetPoint(pts[j])); + } + glEnd(); + + // check for abort condition + if (count == 10000) + { + count = 0; + // report progress + this->UpdateProgress((double)cellNum/this->TotalCells); + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + noAbort = 0; + } + } + ++cellNum; + } + } + } +} + + + + + + + + + +#define PolyNormal \ +{ double polyNorm[3]; vtkPolygon::ComputeNormal(p,nPts,ptIds,polyNorm); glNormal3dv(polyNorm); } + +void vtkOpenGLPolyDataMapper::DrawPolygons(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + GLenum rep, + vtkCellArray *ca, + vtkRenderer *ren) +{ + void *voidPoints = p->GetVoidPointer(0); + void *voidNormals = 0; + void *voidTCoords = 0; + unsigned char *colors = 0; + if (ca->GetNumberOfCells() == 0) + { + return; + } + if (n) + { + voidNormals = n->GetVoidPointer(0); + } + if (c) + { + colors = c->GetPointer(0); + // if these are cell colors then advance to the first cell + if (idx & VTK_PDM_CELL_COLORS) + { + colors = colors + cellNum*4; + } + } + if (t) + { + voidTCoords = t->GetVoidPointer(0); + } + vtkIdType *ptIds = ca->GetPointer(); + vtkIdType *endPtIds = ptIds + ca->GetNumberOfConnectivityEntries(); + + // draw all the elements, use fast path if available + switch (idx) + { + case VTK_PDM_POINT_TYPE_FLOAT: + vtkDrawPolysMacro(float, float, float, rep, + glVertex3fv(points + 3**ptIds);, + PolyNormal,;); + break; + case VTK_PDM_POINT_TYPE_DOUBLE: + vtkDrawPolysMacro(double, float, float, rep, + glVertex3dv(points + 3**ptIds);, + PolyNormal,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT|VTK_PDM_NORMAL_TYPE_FLOAT|VTK_PDM_NORMALS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + PolyNormal,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + PolyNormal,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | VTK_PDM_NORMALS | + VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORD_1D | VTK_PDM_TCOORDS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glTexCoord1fv(tcoords + *ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals; + float *tcoords = (float *)voidTCoords;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | VTK_PDM_CELL_NORMALS | + VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORD_1D | VTK_PDM_TCOORDS: + vtkDrawPolysMacro(float, float, float, rep, + glTexCoord1fv(tcoords + *ptIds); + glVertex3fv(points + 3**ptIds);, + glNormal3fv(normals); normals += 3;, + float *tcoords = (float *)voidTCoords; + float *normals = (float *)voidNormals; + normals += cellNum*3;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | + VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORD_1D | VTK_PDM_TCOORDS: + vtkDrawPolysMacro(float, float, float, rep, + glTexCoord1fv(tcoords + *ptIds); + glVertex3fv(points + 3**ptIds);, + PolyNormal;, + float *tcoords = (float *)voidTCoords;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORDS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glTexCoord2fv(tcoords + 2**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals; + float *tcoords = (float *)voidTCoords;); + break; + case VTK_PDM_POINT_TYPE_FLOAT|VTK_PDM_NORMAL_TYPE_FLOAT| + VTK_PDM_CELL_NORMALS: + vtkDrawPolysMacro(float, float, float, rep, + glVertex3fv(points + 3**ptIds);, + glNormal3fv(normals); normals += 3;, + float *normals = (float *)voidNormals; + normals += cellNum*3;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + glNormal3fv(normals); normals += 3;, + float *normals = (float *)voidNormals; + normals += cellNum*3;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + glNormal3fv(normals); normals += 3;, + float *normals = (float *)voidNormals; + normals += cellNum*3;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_CELL_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glVertex3fv(points + 3**ptIds);, + glColor4ubv(colors); colors += 4;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS | + VTK_PDM_CELL_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glVertex3fv(points + 3**ptIds);, + glColor3ubv(colors); colors += 4;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_CELL_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glVertex3fv(points + 3**ptIds);, + glNormal3fv(normals); normals += 3; + glColor4ubv(colors); colors += 4;, + float *normals = (float *)voidNormals; + normals += cellNum*3;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_CELL_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS | + VTK_PDM_CELL_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glVertex3fv(points + 3**ptIds);, + glNormal3fv(normals); normals += 3; + glColor3ubv(colors); colors += 4;, + float *normals = (float *)voidNormals; + normals += cellNum*3;); + break; + default: + { + int j; + vtkIdType *pts = 0; + vtkIdType npts = 0; + unsigned short count = 0; + for (ca->InitTraversal(); noAbort && ca->GetNextCell(npts,pts); + count++) + { + glBegin(rep); + if (!n) + { + double polyNorm[3]; + vtkPolygon::ComputeNormal(p,npts,pts,polyNorm); + glNormal3dv(polyNorm); + } + for (j = 0; j < npts; j++) + { + if (c) + { + if (idx & VTK_PDM_CELL_COLORS) + { + glColor4ubv(c->GetPointer(cellNum << 2)); + } + else + { + glColor4ubv(c->GetPointer(pts[j] << 2)); + } + } + if (t) + { + if (idx & VTK_PDM_TCOORD_1D) + { + glTexCoord1dv(t->GetTuple(pts[j])); + } + else + { + glTexCoord2dv(t->GetTuple(pts[j])); + } + } + if (n) + { + if (idx & VTK_PDM_CELL_NORMALS) + { + glNormal3dv(n->GetTuple(cellNum)); + } + else + { + glNormal3dv(n->GetTuple(pts[j])); + } + } + glVertex3dv(p->GetPoint(pts[j])); + } + glEnd(); + + // check for abort condition + if (count == 10000) + { + count = 0; + // report progress + this->UpdateProgress((double)cellNum/this->TotalCells); + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + noAbort = 0; + } + } + ++cellNum; + } + } + } +} + +// fix refs here +#define TStripNormal \ +if ( vcount > 2) \ +{ \ + if (vcount % 2) \ + { \ + normIdx[0] = ptIds[-2]; normIdx[1] = ptIds[0]; normIdx[2] = ptIds[-1]; \ + vtkTriangle::ComputeNormal(p, 3, normIdx, polyNorm); \ + } \ + else \ + { \ + normIdx[0] = ptIds[-2]; normIdx[1] = ptIds[-1]; normIdx[2] = ptIds[0]; \ + vtkTriangle::ComputeNormal(p, 3, normIdx, polyNorm); \ + } \ + glNormal3dv(polyNorm); \ +} \ +vcount++; + +#define TStripNormalStart \ + vtkTriangle::ComputeNormal(p, 3, ptIds, polyNorm); \ + glNormal3dv(polyNorm); int vcount = 0; + +void vtkOpenGLPolyDataMapper::DrawTStrips(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + GLenum rep, + vtkCellArray *ca, + vtkRenderer *ren) +{ + void *voidPoints = p->GetVoidPointer(0); + void *voidNormals = 0; + void *voidTCoords = 0; + unsigned char *colors = 0; + double polyNorm[3]; + vtkIdType normIdx[3]; + + if (ca->GetNumberOfCells() == 0) + { + return; + } + if (n) + { + voidNormals = n->GetVoidPointer(0); + } + if (c) + { + colors = c->GetPointer(0); + } + if (t) + { + voidTCoords = t->GetVoidPointer(0); + } + vtkIdType *ptIds = ca->GetPointer(); + vtkIdType *endPtIds = ptIds + ca->GetNumberOfConnectivityEntries(); + + // draw all the elements, use fast path if available + switch (idx) + { + case VTK_PDM_POINT_TYPE_FLOAT: + vtkDrawPolysMacro(float, float, float, rep, + TStripNormal glVertex3fv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_DOUBLE: + vtkDrawPolysMacro(double, float, float, rep, + TStripNormal glVertex3dv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT|VTK_PDM_NORMAL_TYPE_FLOAT|VTK_PDM_NORMALS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + TStripNormal + glColor4ubv(colors + (*ptIds << 2)); + glVertex3fv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + TStripNormal + glColor3ubv(colors + (*ptIds << 2)); + glVertex3fv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glColor4ubv(colors + (*ptIds << 2)); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glColor3ubv(colors + (*ptIds << 2)); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | VTK_PDM_NORMALS | + VTK_PDM_TCOORD_1D | VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORDS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glTexCoord1fv(tcoords + *ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals; + float *tcoords = (float *)voidTCoords;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORDS: + vtkDrawPolysMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glTexCoord2fv(tcoords + 2**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals; + float *tcoords = (float *)voidTCoords;); + break; + default: + { + int j; + vtkIdType nPts = 0; + unsigned short count = 0; + unsigned long coloroffset = cellNum; + for (ca->InitTraversal(); noAbort && ca->GetNextCell(nPts,ptIds); + count++) + { + glBegin(rep); + vtkTriangle::ComputeNormal(p, 3, ptIds, polyNorm); + glNormal3dv(polyNorm); + for (j = 0; j < nPts; j++) + { + if (c) + { + if ( (idx & VTK_PDM_USE_FIELD_DATA) && j>=2 ) + { + glColor4ubv(c->GetPointer(coloroffset << 2)); + coloroffset++; + } + else if (idx & VTK_PDM_CELL_COLORS) + { + glColor4ubv(c->GetPointer(cellNum << 2)); + } + else + { + glColor4ubv(c->GetPointer(ptIds[j] << 2)); + } + } + if (t) + { + if (idx & VTK_PDM_TCOORD_1D) + { + glTexCoord1dv(t->GetTuple(ptIds[j])); + } + else + { + glTexCoord2dv(t->GetTuple(ptIds[j])); + } + } + if (n) + { + if (idx & VTK_PDM_CELL_NORMALS) + { + glNormal3dv(n->GetTuple(cellNum)); + } + else + { + glNormal3dv(n->GetTuple(ptIds[j])); + } + } + else + { + if (j >= 2) + { + if (j % 2) + { + normIdx[0] = ptIds[j-2]; normIdx[1] = ptIds[j]; + normIdx[2] = ptIds[j-1]; + vtkTriangle::ComputeNormal(p, 3, normIdx, polyNorm); + } + else + { + normIdx[0] = ptIds[j-2]; normIdx[1] = ptIds[j-1]; + normIdx[2] = ptIds[j]; + vtkTriangle::ComputeNormal(p, 3, normIdx, polyNorm); + } + } + glNormal3dv(polyNorm); + } + glVertex3dv(p->GetPoint(ptIds[j])); + } + glEnd(); + + // check for abort condition + if (count == 10000) + { + count = 0; + // report progress + this->UpdateProgress((double)cellNum/this->TotalCells); + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + noAbort = 0; + } + } + ++cellNum; + } + } + } +} + +void vtkOpenGLPolyDataMapperDrawTStripLines(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + GLenum rep, + vtkCellArray *ca, + vtkRenderer *ren) +{ + void *voidPoints = p->GetVoidPointer(0); + void *voidNormals = 0; + void *voidTCoords = 0; + unsigned char *colors = 0; + double polyNorm[3]; + vtkIdType normIdx[3]; + + if (n) + { + voidNormals = n->GetVoidPointer(0); + } + if (c) + { + colors = c->GetPointer(0); + } + if (t) + { + voidTCoords = t->GetVoidPointer(0); + } + vtkIdType *ptIds = ca->GetPointer(); + vtkIdType *endPtIds = ptIds + ca->GetNumberOfConnectivityEntries(); + + // draw all the elements, use fast path if available + switch (idx) + { + case VTK_PDM_POINT_TYPE_FLOAT: + vtkDrawStripLinesMacro(float, float, float, rep, + TStripNormal; glVertex3fv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_DOUBLE: + vtkDrawStripLinesMacro(double, float, float, rep, + TStripNormal glVertex3dv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT|VTK_PDM_NORMAL_TYPE_FLOAT|VTK_PDM_NORMALS: + vtkDrawStripLinesMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS: + vtkDrawStripLinesMacro(float, float, float, rep, + TStripNormal; + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawStripLinesMacro(float, float, float, rep, + TStripNormal; + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);, + TStripNormalStart,;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS: + vtkDrawStripLinesMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glColor4ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_COLORS | VTK_PDM_OPAQUE_COLORS: + vtkDrawStripLinesMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glColor3ubv(colors + 4**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | VTK_PDM_NORMALS | + VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORD_1D | VTK_PDM_TCOORDS: + vtkDrawStripLinesMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glTexCoord1fv(tcoords + *ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals; + float *tcoords = (float *)voidTCoords;); + break; + case VTK_PDM_POINT_TYPE_FLOAT | VTK_PDM_NORMAL_TYPE_FLOAT | + VTK_PDM_NORMALS | VTK_PDM_TCOORD_TYPE_FLOAT | VTK_PDM_TCOORDS: + vtkDrawStripLinesMacro(float, float, float, rep, + glNormal3fv(normals + 3**ptIds); + glTexCoord2fv(tcoords + 2**ptIds); + glVertex3fv(points + 3**ptIds);,;, + float *normals = (float *)voidNormals; + float *tcoords = (float *)voidTCoords;); + break; + default: + { + int j; + vtkIdType nPts = 0; + int count = 0; + unsigned long coloroffset = cellNum; + for (ca->InitTraversal(); noAbort && ca->GetNextCell(nPts,ptIds); + count++) + { + glBegin(rep); + for (j = 0; j < nPts; j += 2) + { + if (c) + { + if ( (idx & VTK_PDM_USE_FIELD_DATA) && j >= 2) + { + glColor4ubv(c->GetPointer((coloroffset+j) << 2)); + } + else if (idx & VTK_PDM_CELL_COLORS) + { + glColor4ubv(c->GetPointer(cellNum << 2)); + } + else + { + glColor4ubv(c->GetPointer(ptIds[j] << 2)); + } + } + if (t) + { + if (idx & VTK_PDM_TCOORD_1D) + { + glTexCoord1dv(t->GetTuple(ptIds[j])); + } + else + { + glTexCoord2dv(t->GetTuple(ptIds[j])); + } + } + if (n) + { + if (idx & VTK_PDM_CELL_NORMALS) + { + glNormal3dv(n->GetTuple(cellNum)); + } + else + { + glNormal3dv(n->GetTuple(ptIds[j])); + } + } + else + { + if ( j == 0 ) + { + vtkTriangle::ComputeNormal(p, 3, ptIds, polyNorm); + } + else + { + normIdx[0] = ptIds[j-2]; normIdx[1] = ptIds[j-1]; + normIdx[2] = ptIds[j]; + vtkTriangle::ComputeNormal(p, 3, normIdx, polyNorm); + } + glNormal3dv(polyNorm); + } + glVertex3dv(p->GetPoint(ptIds[j])); + } + glEnd(); + + glBegin(rep); + for (j = 1; j < nPts; j += 2) + { + if (c) + { + if ( (idx & VTK_PDM_USE_FIELD_DATA) && j >= 2) + { + glColor4ubv(c->GetPointer((coloroffset+j) << 2)); + } + else if (idx & VTK_PDM_CELL_COLORS) + { + glColor4ubv(c->GetPointer(cellNum << 2)); + } + else + { + glColor4ubv(c->GetPointer(ptIds[j] << 2)); + } + } + if (t) + { + if (idx & VTK_PDM_TCOORD_1D) + { + glTexCoord1dv(t->GetTuple(ptIds[j])); + } + else + { + glTexCoord2dv(t->GetTuple(ptIds[j])); + } + } + if (n) + { + if (idx & VTK_PDM_CELL_NORMALS) + { + glNormal3dv(n->GetTuple(cellNum)); + } + else + { + glNormal3dv(n->GetTuple(ptIds[j])); + } + } + else + { + if (j == 1) + { + vtkTriangle::ComputeNormal(p, 3, ptIds, polyNorm); + } + else + { + normIdx[0] = ptIds[j-2]; normIdx[1] = ptIds[j]; + normIdx[2] = ptIds[j-1]; + vtkTriangle::ComputeNormal(p, 3, normIdx, polyNorm); + } + glNormal3dv(polyNorm); + } + glVertex3dv(p->GetPoint(ptIds[j])); + } + glEnd(); + + // check for abort condition + if (count == 100) + { + count = 0; + if (ren->GetRenderWindow()->CheckAbortStatus()) + { + noAbort = 0; + } + } + ++cellNum; + coloroffset += (nPts >= 2)? (nPts - 2) : 0; + } + } + } +} + +// Draw method for OpenGL. +int vtkOpenGLPolyDataMapper::Draw(vtkRenderer *aren, vtkActor *act) +{ + vtkOpenGLRenderer *ren = (vtkOpenGLRenderer *)aren; + int rep, interpolation; + float tran; + vtkProperty *prop; + vtkPoints *p; + vtkUnsignedCharArray *c=NULL; + vtkDataArray *n; + vtkDataArray *t; + int tDim; + int noAbort = 1; + vtkPolyData *input = this->GetInput(); + int cellScalars = 0; + vtkIdType cellNum = 0; + int cellNormals; + int resolve=0, zResolve=0; + double zRes = 0.0; + + // get the property + prop = act->GetProperty(); + + // get the transparency + tran = prop->GetOpacity(); + + // if the primitives are invisable then get out of here + if (tran <= 0.0) + { + return noAbort; + } + + // get the representation (e.g., surface / wireframe / points) + rep = prop->GetRepresentation(); + + // get the shading interpolation + interpolation = prop->GetInterpolation(); + + // and draw the display list + p = input->GetPoints(); + + // are they cell or point scalars + if ( this->Colors ) + { + c = this->Colors; + if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA || + this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA || + this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA || + !input->GetPointData()->GetScalars() ) + && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA) + { + cellScalars = 1; + } + } + + n = input->GetPointData()->GetNormals(); + if (interpolation == VTK_FLAT) + { + n = 0; + } + + cellNormals = 0; + if (n == 0 && input->GetCellData()->GetNormals()) + { + cellNormals = 1; + n = input->GetCellData()->GetNormals(); + } + + // if we are doing vertex colors then set lmcolor to adjust + // the current materials ambient and diffuse values using + // vertex color commands otherwise tell it not to. + glDisable( GL_COLOR_MATERIAL ); + if (c) + { + GLenum lmcolorMode; + if (this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT) + { + if (prop->GetAmbient() > prop->GetDiffuse()) + { + lmcolorMode = GL_AMBIENT; + } + else + { + lmcolorMode = GL_DIFFUSE; + } + } + else if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE) + { + lmcolorMode = GL_AMBIENT_AND_DIFFUSE; + } + else if (this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT) + { + lmcolorMode = GL_AMBIENT; + } + else // if (this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE) + { + lmcolorMode = GL_DIFFUSE; + } + glColorMaterial( GL_FRONT_AND_BACK, lmcolorMode); + glEnable( GL_COLOR_MATERIAL ); + } + + unsigned long idx = 0; + if (n && !cellNormals) + { + idx |= VTK_PDM_NORMALS; + } + if (c) + { + idx |= VTK_PDM_COLORS; + if (c->GetName()) + { // In the future, I will look at the number of components. + // All paths will have to handle 3 componet colors. + idx |= VTK_PDM_OPAQUE_COLORS; + } + } + if (cellScalars) + { + idx |= VTK_PDM_CELL_COLORS; + } + if (cellNormals) + { + idx |= VTK_PDM_CELL_NORMALS; + } + if (this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA) + { + idx |= VTK_PDM_USE_FIELD_DATA; + } + + // store the types in the index + if (p->GetDataType() == VTK_FLOAT) + { + idx |= VTK_PDM_POINT_TYPE_FLOAT; + } + else if (p->GetDataType() == VTK_DOUBLE) + { + idx |= VTK_PDM_POINT_TYPE_DOUBLE; + } + if (n) + { + if (n->GetDataType() == VTK_FLOAT) + { + idx |= VTK_PDM_NORMAL_TYPE_FLOAT; + } + else if (n->GetDataType() == VTK_DOUBLE) + { + idx |= VTK_PDM_NORMAL_TYPE_DOUBLE; + } + } + + // Texture and color by texture + t = input->GetPointData()->GetTCoords(); + if ( t ) + { + tDim = t->GetNumberOfComponents(); + if (tDim > 2) + { + vtkDebugMacro(<< "Currently only 1d and 2d textures are supported.\n"); + t = NULL; + } + } + // Set the texture if we are going to use texture + // for coloring with a point attribute. + // fixme ... make the existance of the coordinate array the signal. + if (this->InterpolateScalarsBeforeMapping && this->ColorCoordinates && + ! (idx & VTK_PDM_CELL_COLORS)) + { + t = this->ColorCoordinates; + } + // Set the flags + if (t) + { + idx |= VTK_PDM_TCOORDS; + if (t->GetDataType() == VTK_FLOAT) + { + idx |= VTK_PDM_TCOORD_TYPE_FLOAT; + } + else if (t->GetDataType() == VTK_DOUBLE) + { + idx |= VTK_PDM_TCOORD_TYPE_DOUBLE; + } + if (t->GetNumberOfComponents() == 1) + { + idx |= VTK_PDM_TCOORD_1D; + } + // Not 1D assumes 2D texture coordinates. + } + + if ( this->GetResolveCoincidentTopology() ) + { + resolve = 1; + if ( this->GetResolveCoincidentTopology() == VTK_RESOLVE_SHIFT_ZBUFFER ) + { + zResolve = 1; + zRes = this->GetResolveCoincidentTopologyZShift(); + } + else + { +#ifdef GL_VERSION_1_1 + double f, u; + glEnable(GL_POLYGON_OFFSET_FILL); + this->GetResolveCoincidentTopologyPolygonOffsetParameters(f,u); + glPolygonOffset(f,u); +#endif + } + } + + // we need to know the total number of cells so that we can report progress + this->TotalCells = + input->GetVerts()->GetNumberOfCells() + + input->GetLines()->GetNumberOfCells() + + input->GetPolys()->GetNumberOfCells() + + input->GetStrips()->GetNumberOfCells(); + + // For verts or lines that have no normals, disable shading. + // This will fall back on the color set in the glColor4fv() + // call in vtkOpenGLProperty::Render() - the color returned + // by vtkProperty::GetColor() with alpha set to 1.0. + if (!n) + { + glDisable( GL_LIGHTING); + } + + this->DrawPoints(idx,p,n,c,t,cellNum,noAbort,input->GetVerts(), ren); + + // do lines + if ( zResolve ) + { + glDepthRange(zRes, 1.); + } + if (rep == VTK_POINTS) + { + this->DrawPoints(idx,p,n,c,t,cellNum, noAbort,input->GetLines(), ren); + } + else + { + this->DrawLines(idx,p,n,c,t,cellNum, noAbort, input->GetLines(), ren); + } + + // reset the lighting if we turned it off + if (!n) + { + glEnable( GL_LIGHTING); + } + + // disable shading if we are rendering points, but have no normals + if (!n && rep == VTK_POINTS) + { + glDisable( GL_LIGHTING); + } + + // do polys + if (rep == VTK_POINTS && !prop->GetBackfaceCulling() && !prop->GetFrontfaceCulling() ) + { + this->DrawPoints(idx,p,n,c,t,cellNum, noAbort, input->GetPolys(), ren); + } + else if (rep == VTK_WIREFRAME && !prop->GetBackfaceCulling() && !prop->GetFrontfaceCulling()) + { + this->DrawPolygons(idx,p,n,c,t,cellNum, noAbort, + GL_LINE_LOOP, input->GetPolys(), ren); + } + else + { + this->DrawPolygons(idx,p,n,c,t,cellNum, noAbort, + GL_POLYGON, input->GetPolys(), ren); + } + + + // do tstrips + if ( zResolve ) + { + glDepthRange(2*zRes, 1.); + } + if (rep == VTK_POINTS && !prop->GetBackfaceCulling() && !prop->GetFrontfaceCulling() ) + { + this->DrawPoints(idx,p,n,c,t,cellNum, noAbort, input->GetStrips(), ren); + } + else if (rep == VTK_WIREFRAME && !prop->GetBackfaceCulling() && !prop->GetFrontfaceCulling()) + { + vtkIdType oldCellNum = cellNum; + this->DrawTStrips(idx,p,n,c,t,cellNum, noAbort, + GL_LINE_STRIP, input->GetStrips(), ren); + vtkOpenGLPolyDataMapperDrawTStripLines(idx,p,n,c,t,oldCellNum, noAbort, + GL_LINE_STRIP, input->GetStrips(), + ren); + } + else + { + this->DrawTStrips(idx,p,n,c,t,cellNum, noAbort, + GL_TRIANGLE_STRIP, input->GetStrips(), ren); + } + + // enable lighting again if necessary + if (!n && rep == VTK_POINTS) + { + glEnable( GL_LIGHTING); + } + + if (resolve) + { + if ( zResolve ) + { + glDepthRange(0., 1.); + } + else + { +#ifdef GL_VERSION_1_1 + glDisable(GL_POLYGON_OFFSET_FILL); +#endif + } + } + + this->UpdateProgress(1.0); + return noAbort; +} + +void vtkOpenGLPolyDataMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + + + + + + + + + + + + + diff --git a/Rendering/vtkOpenGLPolyDataMapper.h b/Rendering/vtkOpenGLPolyDataMapper.h new file mode 100644 index 0000000..33c9642 --- /dev/null +++ b/Rendering/vtkOpenGLPolyDataMapper.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLPolyDataMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLPolyDataMapper - a PolyDataMapper for the OpenGL library +// .SECTION Description +// vtkOpenGLPolyDataMapper is a subclass of vtkPolyDataMapper. +// vtkOpenGLPolyDataMapper is a geometric PolyDataMapper for the OpenGL +// rendering library. + +#ifndef __vtkOpenGLPolyDataMapper_h +#define __vtkOpenGLPolyDataMapper_h + +#include "vtkPolyDataMapper.h" + +#include "vtkOpenGL.h" // Needed for GLenum + +class vtkCellArray; +class vtkPoints; +class vtkProperty; +class vtkRenderWindow; +class vtkOpenGLRenderer; +class vtkOpenGLTexture; + +class VTK_RENDERING_EXPORT vtkOpenGLPolyDataMapper : public vtkPolyDataMapper +{ +public: + static vtkOpenGLPolyDataMapper *New(); + vtkTypeRevisionMacro(vtkOpenGLPolyDataMapper,vtkPolyDataMapper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement superclass render method. + virtual void RenderPiece(vtkRenderer *ren, vtkActor *a); + + // Description: + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Draw method for OpenGL. + virtual int Draw(vtkRenderer *ren, vtkActor *a); + +protected: + vtkOpenGLPolyDataMapper(); + ~vtkOpenGLPolyDataMapper(); + + void DrawPoints(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *ca, + vtkRenderer *ren); + + void DrawLines(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + vtkCellArray *ca, + vtkRenderer *ren); + + void DrawPolygons(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + GLenum rep, + vtkCellArray *ca, + vtkRenderer *ren); + + void DrawTStrips(int idx, + vtkPoints *p, + vtkDataArray *n, + vtkUnsignedCharArray *c, + vtkDataArray *t, + vtkIdType &cellNum, + int &noAbort, + GLenum rep, + vtkCellArray *ca, + vtkRenderer *ren); + + vtkIdType TotalCells; + int ListId; + vtkOpenGLTexture* InternalColorTexture; + +private: + vtkOpenGLPolyDataMapper(const vtkOpenGLPolyDataMapper&); // Not implemented. + void operator=(const vtkOpenGLPolyDataMapper&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkOpenGLPolyDataMapper2D.cxx b/Rendering/vtkOpenGLPolyDataMapper2D.cxx new file mode 100644 index 0000000..a3e40d0 --- /dev/null +++ b/Rendering/vtkOpenGLPolyDataMapper2D.cxx @@ -0,0 +1,379 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLPolyDataMapper2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLPolyDataMapper2D.h" + +#include "vtkActor2D.h" +#include "vtkCellArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPlaneCollection.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkProperty2D.h" +#include "vtkScalarsToColors.h" +#include "vtkUnsignedCharArray.h" +#include "vtkViewport.h" +#include "vtkWindow.h" +#include "vtkgluPickMatrix.h" +#include "vtkToolkits.h" // for VTK_USE_GL2PS + +#ifdef VTK_USE_GL2PS +#include "gl2ps.h" +#include "vtkGL2PSExporter.h" +#endif // VTK_USE_GL2PS + +#include + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLPolyDataMapper2D, "$Revision: 1.55 $"); +vtkStandardNewMacro(vtkOpenGLPolyDataMapper2D); +#endif + +void vtkOpenGLPolyDataMapper2D::RenderOverlay(vtkViewport* viewport, + vtkActor2D* actor) +{ + int numPts; + vtkPolyData *input= (vtkPolyData *)this->GetInput(); + int j; + vtkPoints *p, *displayPts; + vtkCellArray *aPrim; + vtkUnsignedCharArray *c=NULL; + unsigned char *rgba; + unsigned char color[4]; + vtkIdType *pts = 0; + vtkIdType npts = 0; + int cellScalars = 0; + int cellNum = 0; + vtkPlaneCollection *clipPlanes; + vtkPlane *plane; + int i,numClipPlanes; + double planeEquation[4]; + + vtkDebugMacro (<< "vtkOpenGLPolyDataMapper2D::Render"); + + if ( input == NULL ) + { + vtkErrorMacro(<< "No input!"); + return; + } + else + { + input->Update(); + numPts = input->GetNumberOfPoints(); + } + + if (numPts == 0) + { + vtkDebugMacro(<< "No points!"); + return; + } + + if ( this->LookupTable == NULL ) + { + this->CreateDefaultLookupTable(); + } + + // if something has changed regenrate colors and display lists + // if required + // + if ( this->GetMTime() > this->BuildTime || + input->GetMTime() > this->BuildTime || + this->LookupTable->GetMTime() > this->BuildTime || + actor->GetProperty()->GetMTime() > this->BuildTime) + { + // sets this->Colors as side effect + this->MapScalars(actor->GetProperty()->GetOpacity()); + this->BuildTime.Modified(); + } + + // Get the position of the actor + int size[2]; + size[0] = viewport->GetSize()[0]; + size[1] = viewport->GetSize()[1]; + double *vport = viewport->GetViewport(); + int* actorPos = + actor->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + // get window info + double *tileViewPort = viewport->GetVTKWindow()->GetTileViewport(); + double visVP[4]; + visVP[0] = (vport[0] >= tileViewPort[0]) ? vport[0] : tileViewPort[0]; + visVP[1] = (vport[1] >= tileViewPort[1]) ? vport[1] : tileViewPort[1]; + visVP[2] = (vport[2] <= tileViewPort[2]) ? vport[2] : tileViewPort[2]; + visVP[3] = (vport[3] <= tileViewPort[3]) ? vport[3] : tileViewPort[3]; + if (visVP[0] >= visVP[2]) + { + return; + } + if (visVP[1] >= visVP[3]) + { + return; + } + size[0] = + vtkMath::Round(size[0]*(visVP[2] - visVP[0])/(vport[2] - vport[0])); + size[1] = + vtkMath::Round(size[1]*(visVP[3] - visVP[1])/(vport[3] - vport[1])); + + // Set up the font color from the text actor + double* actorColor = actor->GetProperty()->GetColor(); + color[0] = (unsigned char) (actorColor[0] * 255.0); + color[1] = (unsigned char) (actorColor[1] * 255.0); + color[2] = (unsigned char) (actorColor[2] * 255.0); + color[3] = (unsigned char) (255.0*actor->GetProperty()->GetOpacity()); + + // Transform the points, if necessary + p = input->GetPoints(); + if ( this->TransformCoordinate ) + { + int *itmp; + numPts = p->GetNumberOfPoints(); + displayPts = vtkPoints::New(); + displayPts->SetNumberOfPoints(numPts); + for ( j=0; j < numPts; j++ ) + { + this->TransformCoordinate->SetValue(p->GetPoint(j)); + itmp = this->TransformCoordinate->GetComputedViewportValue(viewport); + displayPts->SetPoint(j,itmp[0], itmp[1], 0.0); + } + p = displayPts; + } + + // Set up the coloring + if ( this->Colors ) + { + c = this->Colors; + if (!input->GetPointData()->GetScalars()) + { + cellScalars = 1; + } + } + vtkDebugMacro(<< c); + vtkDebugMacro(<< cellScalars); + + // set the colors for the foreground + glColor4ubv(color); + + // push a 2D matrix on the stack + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + if(viewport->GetIsPicking()) + { + vtkgluPickMatrix(viewport->GetPickX(), viewport->GetPickY(), + 1, 1, viewport->GetOrigin(), viewport->GetSize()); + } + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + + glDisable( GL_TEXTURE_2D ); + glDisable( GL_LIGHTING ); + + // Assume we want to do Zbuffering for now. + // we may turn this off later + glDepthMask(GL_TRUE); + + int *winSize = viewport->GetVTKWindow()->GetSize(); + + int xoff = static_cast(actorPos[0] - (visVP[0] - vport[0])* + winSize[0]); + int yoff = static_cast(actorPos[1] - (visVP[1] - vport[1])* + winSize[1]); + + if ( actor->GetProperty()->GetDisplayLocation() == + VTK_FOREGROUND_LOCATION ) + { + glOrtho(-xoff,-xoff + size[0], + -yoff, -yoff +size[1], 0, 1); + } + else + { + glOrtho(-xoff,-xoff + size[0], + -yoff, -yoff + size[1], -1, 0); + } + + // Clipping plane stuff + clipPlanes = this->ClippingPlanes; + + if (clipPlanes == NULL) + { + numClipPlanes = 0; + } + else + { + numClipPlanes = clipPlanes->GetNumberOfItems(); + if (numClipPlanes > 4) + { + vtkErrorMacro(<< "Only 4 clipping planes are used with 2D mappers"); + } + } + + for (i = 0; i < numClipPlanes; i++) + { + glEnable((GLenum)(GL_CLIP_PLANE0+i)); + } + + for (i = 0; i < numClipPlanes; i++) + { + plane = (vtkPlane *)clipPlanes->GetItemAsObject(i); + + planeEquation[0] = plane->GetNormal()[0]; + planeEquation[1] = plane->GetNormal()[1]; + planeEquation[2] = plane->GetNormal()[2]; + planeEquation[3] = -(planeEquation[0]*plane->GetOrigin()[0]+ + planeEquation[1]*plane->GetOrigin()[1]+ + planeEquation[2]*plane->GetOrigin()[2]); + glClipPlane((GLenum)(GL_CLIP_PLANE0+i),planeEquation); + } + + // Set the PointSize + glPointSize(actor->GetProperty()->GetPointSize()); + + double *dptr; + aPrim = input->GetVerts(); + glBegin(GL_POINTS); + for (aPrim->InitTraversal(); aPrim->GetNextCell(npts,pts); cellNum++) + { + for (j = 0; j < npts; j++) + { + if (c) + { + if (cellScalars) + { + rgba = c->GetPointer(4*cellNum); + } + else + { + rgba = c->GetPointer(4*pts[j]); + } + glColor4ubv(rgba); + } + // this is done to work around an OpenGL bug, otherwise we could just + // call glVertex2dv + dptr = p->GetPoint(pts[j]); + glVertex3d(dptr[0],dptr[1],0); + } + } + glEnd(); + + // Set pointsize and linewidth for GL2PS output. +#ifdef VTK_USE_GL2PS + gl2psPointSize(actor->GetProperty()->GetPointSize()* + vtkGL2PSExporter::GetGlobalPointSizeFactor()); + gl2psLineWidth(actor->GetProperty()->GetLineWidth()* + vtkGL2PSExporter::GetGlobalLineWidthFactor()); +#endif // VTK_USE_GL2PS + + // Set the LineWidth + glLineWidth(actor->GetProperty()->GetLineWidth()); + + // Set the LineStipple + if (actor->GetProperty()->GetLineStipplePattern() != 0xFFFF) + { + glEnable (GL_LINE_STIPPLE); +#ifdef VTK_USE_GL2PS + gl2psEnable(GL2PS_LINE_STIPPLE); +#endif // VTK_USE_GL2PS + glLineStipple (actor->GetProperty()->GetLineStippleRepeatFactor(), + actor->GetProperty()->GetLineStipplePattern()); + } + else + { + glDisable (GL_LINE_STIPPLE); +#ifdef VTK_USE_GL2PS + gl2psDisable(GL2PS_LINE_STIPPLE); +#endif // VTK_USE_GL2PS + } + + aPrim = input->GetLines(); + for (aPrim->InitTraversal(); aPrim->GetNextCell(npts,pts); cellNum++) + { + glBegin(GL_LINE_STRIP); + for (j = 0; j < npts; j++) + { + if (c) + { + if (cellScalars) + { + rgba = c->GetPointer(4*cellNum); + } + else + { + rgba = c->GetPointer(4*pts[j]); + } + glColor4ubv(rgba); + } + // this is done to work around an OpenGL bug, otherwise we could just + // call glVertex2dv + dptr = p->GetPoint(pts[j]); + glVertex3d(dptr[0],dptr[1],0); + } + glEnd(); + } + + aPrim = input->GetPolys(); + for (aPrim->InitTraversal(); aPrim->GetNextCell(npts,pts); cellNum++) + { + glBegin(GL_POLYGON); + for (j = 0; j < npts; j++) + { + if (c) + { + if (cellScalars) + { + rgba = c->GetPointer(4*cellNum); + } + else + { + rgba = c->GetPointer(4*pts[j]); + } + glColor4ubv(rgba); + } + // this is done to work around an OpenGL bug, otherwise we could just + // call glVertex2dv + dptr = p->GetPoint(pts[j]); + glVertex3d(dptr[0],dptr[1],0); + } + glEnd(); + } + + if ( this->TransformCoordinate ) + { + p->Delete(); + } + + for (i = 0; i < numClipPlanes; i++) + { + glDisable((GLenum)(GL_CLIP_PLANE0+i)); + } + + // push a 2D matrix on the stack + glMatrixMode( GL_PROJECTION); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW); + glPopMatrix(); + glEnable( GL_LIGHTING); + + // Turn it back on in case we've turned it off + glDepthMask( GL_TRUE ); +} + +//---------------------------------------------------------------------------- +void vtkOpenGLPolyDataMapper2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLPolyDataMapper2D.h b/Rendering/vtkOpenGLPolyDataMapper2D.h new file mode 100644 index 0000000..c2e2c62 --- /dev/null +++ b/Rendering/vtkOpenGLPolyDataMapper2D.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLPolyDataMapper2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLPolyDataMapper2D - 2D PolyData support for OpenGL +// .SECTION Description +// vtkOpenGLPolyDataMapper2D provides 2D PolyData annotation support for +// vtk under OpenGL. Normally the user should use vtkPolyDataMapper2D +// which in turn will use this class. + +// .SECTION See Also +// vtkPolyDataMapper2D + +#ifndef __vtkOpenGLPolyDataMapper2D_h +#define __vtkOpenGLPolyDataMapper2D_h + +#include "vtkPolyDataMapper2D.h" + +class VTK_RENDERING_EXPORT vtkOpenGLPolyDataMapper2D : public vtkPolyDataMapper2D +{ +public: + vtkTypeRevisionMacro(vtkOpenGLPolyDataMapper2D,vtkPolyDataMapper2D); + static vtkOpenGLPolyDataMapper2D *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Actually draw the poly data. + void RenderOverlay(vtkViewport* viewport, vtkActor2D* actor); + +protected: + vtkOpenGLPolyDataMapper2D() {}; + ~vtkOpenGLPolyDataMapper2D() {}; + +private: + vtkOpenGLPolyDataMapper2D(const vtkOpenGLPolyDataMapper2D&); // Not implemented. + void operator=(const vtkOpenGLPolyDataMapper2D&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkOpenGLProperty.cxx b/Rendering/vtkOpenGLProperty.cxx new file mode 100644 index 0000000..05255cb --- /dev/null +++ b/Rendering/vtkOpenGLProperty.cxx @@ -0,0 +1,213 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLProperty.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLProperty.h" +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif +#include "vtkObjectFactory.h" +#include "vtkToolkits.h" // for VTK_USE_GL2PS + +#ifdef VTK_USE_GL2PS +#include "gl2ps.h" +#include "vtkGL2PSExporter.h" +#endif // VTK_USE_GL2PS + + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLProperty, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkOpenGLProperty); +#endif + + + +// Implement base class method. +void vtkOpenGLProperty::Render(vtkActor *vtkNotUsed(anActor), + vtkRenderer *vtkNotUsed(ren)) +{ + int i; + GLenum method; + float Info[4]; + GLenum Face; + double color[4]; + + // unbind any textures for starters + glDisable(GL_TEXTURE_2D); + + // disable alpha testing (this may have been enabled + // by another actor in OpenGLTexture) + glDisable (GL_ALPHA_TEST); + + glDisable(GL_COLOR_MATERIAL); + + Face = GL_FRONT_AND_BACK; + // turn on/off backface culling + if ( ! this->BackfaceCulling && ! this->FrontfaceCulling) + { + glDisable (GL_CULL_FACE); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + else if ( this->BackfaceCulling) + { + glCullFace (GL_BACK); + glEnable (GL_CULL_FACE); + if (this->GetRepresentation() == VTK_WIREFRAME) + { + glPolygonMode(GL_FRONT, GL_LINE); + } + else if (this->GetRepresentation() == VTK_SURFACE) + { + glPolygonMode(GL_FRONT, GL_FILL); + } + else + { + glPolygonMode(GL_FRONT, GL_POINT); + } + } + else //if both front & back culling on, will fall into backface culling + { //if you really want both front and back, use the Actor's visibility flag + glCullFace (GL_FRONT); + glEnable (GL_CULL_FACE); + if (this->GetRepresentation() == VTK_WIREFRAME) + { + glPolygonMode(GL_BACK, GL_LINE); + } + else if (this->GetRepresentation() == VTK_SURFACE) + { + glPolygonMode(GL_BACK, GL_FILL); + } + else + { + glPolygonMode(GL_BACK, GL_POINT); + } + } + + Info[3] = this->Opacity; + + for (i=0; i < 3; i++) + { + Info[i] = static_cast(this->Ambient*this->AmbientColor[i]); + } + glMaterialfv( Face, GL_AMBIENT, Info ); + for (i=0; i < 3; i++) + { + Info[i] = static_cast(this->Diffuse*this->DiffuseColor[i]); + } + glMaterialfv( Face, GL_DIFFUSE, Info ); + for (i=0; i < 3; i++) + { + Info[i] = static_cast(this->Specular*this->SpecularColor[i]); + } + glMaterialfv( Face, GL_SPECULAR, Info ); + + Info[0] = static_cast(this->SpecularPower); + glMaterialfv( Face, GL_SHININESS, Info ); + + // set interpolation + switch (this->Interpolation) + { + case VTK_FLAT: + method = GL_FLAT; + break; + case VTK_GOURAUD: + case VTK_PHONG: + method = GL_SMOOTH; + break; + default: + method = GL_SMOOTH; + break; + } + + glShadeModel(method); + + // The material properties set above are used if shading is + // enabled. This color set here is used if shading is + // disabled. Shading is disabled in the + // vtkOpenGLPolyDataMapper::Draw() method if points or lines + // are encountered without normals. + this->GetColor( color ); + color[3] = this->Opacity; + glColor4dv( color ); + + // Set the PointSize + glPointSize (this->PointSize); + + // Set the LineWidth + glLineWidth (this->LineWidth); + + // Set pointsize and linewidth for GL2PS output. +#ifdef VTK_USE_GL2PS + gl2psPointSize(this->PointSize* + vtkGL2PSExporter::GetGlobalPointSizeFactor()); + gl2psLineWidth(this->LineWidth* + vtkGL2PSExporter::GetGlobalLineWidthFactor()); +#endif // VTK_USE_GL2PS + + // Set the LineStipple + if (this->LineStipplePattern != 0xFFFF) + { + glEnable (GL_LINE_STIPPLE); +#ifdef VTK_USE_GL2PS + gl2psEnable(GL2PS_LINE_STIPPLE); +#endif // VTK_USE_GL2PS + glLineStipple (this->LineStippleRepeatFactor, this->LineStipplePattern); + } + else + { + glDisable (GL_LINE_STIPPLE); +#ifdef VTK_USE_GL2PS + gl2psDisable(GL2PS_LINE_STIPPLE); +#endif // VTK_USE_GL2PS + } +} + +// Implement base class method. +void vtkOpenGLProperty::BackfaceRender(vtkActor *vtkNotUsed(anActor), + vtkRenderer *vtkNotUsed(ren)) +{ + int i; + float Info[4]; + GLenum Face; + + Face = GL_BACK; + + Info[3] = this->Opacity; + + for (i=0; i < 3; i++) + { + Info[i] = static_cast(this->Ambient*this->AmbientColor[i]); + } + glMaterialfv( Face, GL_AMBIENT, Info ); + for (i=0; i < 3; i++) + { + Info[i] = static_cast(this->Diffuse*this->DiffuseColor[i]); + } + glMaterialfv( Face, GL_DIFFUSE, Info ); + for (i=0; i < 3; i++) + { + Info[i] = static_cast(this->Specular*this->SpecularColor[i]); + } + glMaterialfv( Face, GL_SPECULAR, Info ); + + Info[0] = static_cast(this->SpecularPower); + glMaterialfv( Face, GL_SHININESS, Info ); + +} + +//---------------------------------------------------------------------------- +void vtkOpenGLProperty::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLProperty.h b/Rendering/vtkOpenGLProperty.h new file mode 100644 index 0000000..2a01074 --- /dev/null +++ b/Rendering/vtkOpenGLProperty.h @@ -0,0 +1,50 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLProperty.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLProperty - OpenGL property +// .SECTION Description +// vtkOpenGLProperty is a concrete implementation of the abstract class +// vtkProperty. vtkOpenGLProperty interfaces to the OpenGL rendering library. + +#ifndef __vtkOpenGLProperty_h +#define __vtkOpenGLProperty_h + +#include "vtkProperty.h" + +class vtkOpenGLRenderer; + +class VTK_RENDERING_EXPORT vtkOpenGLProperty : public vtkProperty +{ +public: + static vtkOpenGLProperty *New(); + vtkTypeRevisionMacro(vtkOpenGLProperty,vtkProperty); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Render(vtkActor *a, vtkRenderer *ren); + + // Description: + // Implement base class method. + void BackfaceRender(vtkActor *a, vtkRenderer *ren); + +protected: + vtkOpenGLProperty() {}; + ~vtkOpenGLProperty() {}; +private: + vtkOpenGLProperty(const vtkOpenGLProperty&); // Not implemented. + void operator=(const vtkOpenGLProperty&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkOpenGLRenderWindow.cxx b/Rendering/vtkOpenGLRenderWindow.cxx new file mode 100644 index 0000000..d60278a --- /dev/null +++ b/Rendering/vtkOpenGLRenderWindow.cxx @@ -0,0 +1,1303 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLRenderWindow.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLProperty.h" +#include "vtkOpenGLTexture.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLActor.h" +#include "vtkOpenGLPolyDataMapper.h" +#include "vtkIdList.h" +#include "vtkObjectFactory.h" +#include "vtkFloatArray.h" +#include "vtkUnsignedCharArray.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLRenderWindow, "$Revision: 1.68 $"); +#endif + +#define MAX_LIGHTS 8 + +// Initialize static member that controls global maximum number of multisamples +static int vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = 8; + +void vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(int val) +{ + if (val == vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples) return; + vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = val; +} + +int vtkOpenGLRenderWindow::GetGlobalMaximumNumberOfMultiSamples() +{ + return vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples; +} + +vtkOpenGLRenderWindow::vtkOpenGLRenderWindow() +{ + this->MultiSamples = vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples; + this->TextureResourceIds = vtkIdList::New(); + if ( this->WindowName ) + delete [] this->WindowName; + this->WindowName = new char[strlen("Visualization Toolkit - OpenGL")+1]; + strcpy( this->WindowName, "Visualization Toolkit - OpenGL" ); +} + +// free up memory & close the window +vtkOpenGLRenderWindow::~vtkOpenGLRenderWindow() +{ + this->TextureResourceIds->Delete(); +} + +// Update system if needed due to stereo rendering. +void vtkOpenGLRenderWindow::StereoUpdate(void) +{ + // if stereo is on and it wasn't before + if (this->StereoRender && (!this->StereoStatus)) + { + switch (this->StereoType) + { + case VTK_STEREO_CRYSTAL_EYES: + // not clear this is supposed to be empty, + // but it has been that way forever. + break; + case VTK_STEREO_RED_BLUE: + this->StereoStatus = 1; + break; + case VTK_STEREO_ANAGLYPH: + this->StereoStatus = 1; + break; + case VTK_STEREO_DRESDEN: + this->StereoStatus = 1; + break; + case VTK_STEREO_INTERLACED: + this->StereoStatus = 1; + } + } + else if ((!this->StereoRender) && this->StereoStatus) + { + switch (this->StereoType) + { + case VTK_STEREO_CRYSTAL_EYES: + this->StereoStatus = 0; + break; + case VTK_STEREO_RED_BLUE: + this->StereoStatus = 0; + break; + case VTK_STEREO_ANAGLYPH: + this->StereoStatus = 0; + break; + case VTK_STEREO_DRESDEN: + this->StereoStatus = 0; + break; + case VTK_STEREO_INTERLACED: + this->StereoStatus = 0; + break; + } + } +} + + +void vtkOpenGLRenderWindow::OpenGLInit() +{ + glMatrixMode( GL_MODELVIEW ); + glDepthFunc( GL_LEQUAL ); + glEnable( GL_DEPTH_TEST ); + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + + // initialize blending for transparency + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glEnable(GL_BLEND); + + if (this->PointSmoothing) + { + glEnable(GL_POINT_SMOOTH); + } + else + { + glDisable(GL_POINT_SMOOTH); + } + + if (this->LineSmoothing) + { + glEnable(GL_LINE_SMOOTH); + } + else + { + glDisable(GL_LINE_SMOOTH); + } + + if (this->PolygonSmoothing) + { + glEnable(GL_POLYGON_SMOOTH); + } + else + { + glDisable(GL_POLYGON_SMOOTH); + } + + glEnable(GL_NORMALIZE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); +} + + +void vtkOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "MultiSamples: " << this->MultiSamples << "\n"; +} + +int vtkOpenGLRenderWindow::GetDepthBufferSize() +{ + GLint size; + + if ( this->Mapped ) + { + this->MakeCurrent(); + size = 0; + glGetIntegerv( GL_DEPTH_BITS, &size ); + return (int) size; + } + else + { + vtkDebugMacro(<< "Window is not mapped yet!" ); + return 24; + } +} + +unsigned char* vtkOpenGLRenderWindow::GetPixelData(int x1, int y1, + int x2, int y2, + int front) +{ + int y_low, y_hi; + int x_low, x_hi; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + unsigned char *data = + new unsigned char[(x_hi - x_low + 1)*(y_hi - y_low + 1)*3]; + this->GetPixelData(x1, y1, x2, y2, front, data); + return data; +} + +int vtkOpenGLRenderWindow::GetPixelData(int x1, int y1, + int x2, int y2, + int front, + vtkUnsignedCharArray* data) +{ + int y_low, y_hi; + int x_low, x_hi; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + int width = abs(x_hi - x_low) + 1; + int height = abs(y_hi - y_low) + 1; + int size = 3*width*height; + + if ( data->GetMaxId()+1 != size) + { + vtkDebugMacro("Resizing array."); + data->SetNumberOfComponents(3); + data->SetNumberOfValues(size); + } + return this->GetPixelData(x1, y1, x2, y2, front, data->GetPointer(0)); + +} + +int vtkOpenGLRenderWindow::GetPixelData(int x1, int y1, + int x2, int y2, + int front, unsigned char* data) +{ + int y_low, y_hi; + int x_low, x_hi; + + // set the current window + this->MakeCurrent(); + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + if (front) + { + glReadBuffer(GL_FRONT); + } + else + { + glReadBuffer(GL_BACK); + } + + glDisable( GL_SCISSOR_TEST ); + +#if defined(sparc) && !defined(GL_VERSION_1_2) + // We need to read the image data one row at a time and convert it + // from RGBA to RGB to get around a bug in Sun OpenGL 1.1 + long xloop, yloop; + unsigned char *buffer; + unsigned char *p_data = NULL; + + buffer = new unsigned char [4*(x_hi - x_low + 1)]; + p_data = data; + for (yloop = y_low; yloop <= y_hi; yloop++) + { + // read in a row of pixels + glReadPixels(x_low,yloop,(x_hi-x_low+1),1, + GL_RGBA, GL_UNSIGNED_BYTE, buffer); + for (xloop = 0; xloop <= x_hi-x_low; xloop++) + { + *p_data = buffer[xloop*4]; p_data++; + *p_data = buffer[xloop*4+1]; p_data++; + *p_data = buffer[xloop*4+2]; p_data++; + } + } + + delete [] buffer; +#else + // If the Sun bug is ever fixed, then we could use the following + // technique which provides a vast speed improvement on the SGI + + // Turn of texturing in case it is on - some drivers have a problem + // getting / setting pixels with texturing enabled. + glDisable( GL_TEXTURE_2D ); + + // Calling pack alignment ensures that we can grab the any size window + glPixelStorei( GL_PACK_ALIGNMENT, 1 ); + glReadPixels(x_low, y_low, x_hi-x_low+1, y_hi-y_low+1, GL_RGB, + GL_UNSIGNED_BYTE, data); +#endif + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } + +} + +int vtkOpenGLRenderWindow::SetPixelData(int x1, int y1, int x2, int y2, + vtkUnsignedCharArray *data, int front) +{ + int y_low, y_hi; + int x_low, x_hi; + + if (y1 < y2) + { + + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + int width = abs(x_hi - x_low) + 1; + int height = abs(y_hi - y_low) + 1; + int size = 3*width*height; + + if ( data->GetMaxId()+1 != size) + { + vtkErrorMacro("Buffer is of wrong size."); + return VTK_ERROR; + } + return this->SetPixelData(x1, y1, x2, y2, data->GetPointer(0), front); + +} + +int vtkOpenGLRenderWindow::SetPixelData(int x1, int y1, int x2, int y2, + unsigned char *data, int front) +{ + int y_low, y_hi; + int x_low, x_hi; + + // set the current window + this->MakeCurrent(); + + // Error checking + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + if (front) + { + glDrawBuffer(GL_FRONT); + } + else + { + glDrawBuffer(GL_BACK); + } + + if (y1 < y2) + { + + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + glDisable( GL_SCISSOR_TEST ); + +#if defined(sparc) && !defined(GL_VERSION_1_2) + // We need to read the image data one row at a time and convert it + // from RGBA to RGB to get around a bug in Sun OpenGL 1.1 + long xloop, yloop; + unsigned char *buffer; + unsigned char *p_data = NULL; + + buffer = new unsigned char [4*(x_hi - x_low + 1)]; + + // now write the binary info one row at a time + glDisable(GL_BLEND); + p_data = data; + for (yloop = y_low; yloop <= y_hi; yloop++) + { + for (xloop = 0; xloop <= x_hi - x_low; xloop++) + { + buffer[xloop*4] = *p_data; p_data++; + buffer[xloop*4+1] = *p_data; p_data++; + buffer[xloop*4+2] = *p_data; p_data++; + buffer[xloop*4+3] = 0xff; + } + /* write out a row of pixels */ + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glRasterPos3f( (2.0 * (GLfloat)(x_low) / this->Size[0] - 1), + (2.0 * (GLfloat)(yloop) / this->Size[1] - 1), + -1.0 ); + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + glDrawPixels((x_hi-x_low+1),1, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + } + + // This seems to be necessary for the image to show up + glFlush(); + + glEnable(GL_BLEND); +#else + // If the Sun bug is ever fixed, then we could use the following + // technique which provides a vast speed improvement on the SGI + + // Turn of texturing in case it is on - some drivers have a problem + // getting / setting pixels with texturing enabled. + glDisable( GL_TEXTURE_2D ); + + // now write the binary info + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glRasterPos3f( (2.0 * (GLfloat)(x_low) / this->Size[0] - 1), + (2.0 * (GLfloat)(y_low) / this->Size[1] - 1), + -1.0 ); + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + glViewport(0,0, this->Size[0], this->Size[1]); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + glDisable(GL_BLEND); + glDrawPixels((x_hi-x_low+1), (y_hi - y_low + 1), + GL_RGB, GL_UNSIGNED_BYTE, data); + glEnable(GL_BLEND); + + // This seems to be necessary for the image to show up + glFlush(); +#endif + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } +} + +float* vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2, + int front) +{ + + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + width = abs(x_hi - x_low) + 1; + height = abs(y_hi - y_low) + 1; + + float *data = new float[ (width*height*4) ]; + this->GetRGBAPixelData(x1, y1, x2, y2, front, data); + + return data; + +} + +int vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2, + int front, vtkFloatArray* data) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + width = abs(x_hi - x_low) + 1; + height = abs(y_hi - y_low) + 1; + + int size = 4*width*height; + + if ( data->GetMaxId()+1 != size) + { + vtkDebugMacro("Resizing array."); + data->SetNumberOfComponents(4); + data->SetNumberOfValues(size); + } + return this->GetRGBAPixelData(x1, y1, x2, y2, front, data->GetPointer(0)); + +} + +int vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2, + int front, float* data) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + // set the current window + this->MakeCurrent(); + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + // Error checking + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + if (front) + { + glReadBuffer(GL_FRONT); + } + else + { + glReadBuffer(GL_BACK); + } + + width = abs(x_hi - x_low) + 1; + height = abs(y_hi - y_low) + 1; + + + // Turn of texturing in case it is on - some drivers have a problem + // getting / setting pixels with texturing enabled. + glDisable( GL_TEXTURE_2D ); + + glPixelStorei( GL_PACK_ALIGNMENT, 1 ); + glReadPixels( x_low, y_low, width, height, GL_RGBA, GL_FLOAT, data); + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } +} + +void vtkOpenGLRenderWindow::ReleaseRGBAPixelData(float *data) +{ + delete[] data; +} + +int vtkOpenGLRenderWindow::SetRGBAPixelData(int x1, int y1, int x2, int y2, + vtkFloatArray *data, int front, + int blend) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + width = abs(x_hi-x_low) + 1; + height = abs(y_hi-y_low) + 1; + + int size = 4*width*height; + if ( data->GetMaxId()+1 != size ) + { + vtkErrorMacro("Buffer is of wrong size."); + return VTK_ERROR; + } + + return this->SetRGBAPixelData(x1, y1, x2, y2, data->GetPointer(0), front, + blend); +} + +int vtkOpenGLRenderWindow::SetRGBAPixelData(int x1, int y1, int x2, int y2, + float *data, int front, int blend) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + // set the current window + this->MakeCurrent(); + + // Error checking + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + if (front) + { + glDrawBuffer(GL_FRONT); + } + else + { + glDrawBuffer(GL_BACK); + } + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + width = abs(x_hi-x_low) + 1; + height = abs(y_hi-y_low) + 1; + + /* write out a row of pixels */ + glDisable( GL_SCISSOR_TEST ); + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glRasterPos3f( (2.0 * (GLfloat)(x_low) / this->Size[0] - 1), + (2.0 * (GLfloat)(y_low) / this->Size[1] - 1), + -1.0 ); + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + + if (!blend) + { + glDisable(GL_BLEND); + glDrawPixels( width, height, GL_RGBA, GL_FLOAT, data); + glEnable(GL_BLEND); + } + else + { + glDrawPixels( width, height, GL_RGBA, GL_FLOAT, data); + } + + // This seems to be necessary for the image to show up + glFlush(); + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } +} + +unsigned char *vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1, + int x2, int y2, + int front) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + width = abs(x_hi - x_low) + 1; + height = abs(y_hi - y_low) + 1; + + unsigned char *data = new unsigned char[ (width*height)*4 ]; + this->GetRGBACharPixelData(x1, y1, x2, y2, front, data); + + return data; +} + +int vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1, + int x2, int y2, + int front, + vtkUnsignedCharArray* data) +{ + int y_low, y_hi; + int x_low, x_hi; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + int width = abs(x_hi - x_low) + 1; + int height = abs(y_hi - y_low) + 1; + int size = 4*width*height; + + if ( data->GetMaxId()+1 != size) + { + vtkDebugMacro("Resizing array."); + data->SetNumberOfComponents(4); + data->SetNumberOfValues(size); + } + return this->GetRGBACharPixelData(x1, y1, x2, y2, front, + data->GetPointer(0)); +} + +int vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1, + int x2, int y2, + int front, + unsigned char* data) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + + // set the current window + this->MakeCurrent(); + + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + if (front) + { + glReadBuffer(GL_FRONT); + } + else + { + glReadBuffer(GL_BACK); + } + + width = abs(x_hi - x_low) + 1; + height = abs(y_hi - y_low) + 1; + + glDisable( GL_SCISSOR_TEST ); + + // Turn of texturing in case it is on - some drivers have a problem + // getting / setting pixels with texturing enabled. + glDisable( GL_TEXTURE_2D ); + + glReadPixels( x_low, y_low, width, height, GL_RGBA, GL_UNSIGNED_BYTE, + data); + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } + +} + + +int vtkOpenGLRenderWindow::SetRGBACharPixelData(int x1,int y1,int x2,int y2, + vtkUnsignedCharArray *data, + int front, int blend) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + width = abs(x_hi-x_low) + 1; + height = abs(y_hi-y_low) + 1; + + int size = 4*width*height; + if ( data->GetMaxId()+1 != size ) + { + vtkErrorMacro("Buffer is of wrong size. It is " << data->GetMaxId()+1 + << ", it should be: " << size); + return VTK_ERROR; + } + + return this->SetRGBACharPixelData(x1, y1, x2, y2, data->GetPointer(0), + front, blend); + +} + +int vtkOpenGLRenderWindow::SetRGBACharPixelData(int x1, int y1, int x2, + int y2, unsigned char *data, + int front, int blend) +{ + int y_low, y_hi; + int x_low, x_hi; + int width, height; + + + // set the current window + this->MakeCurrent(); + + + // Error checking + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + if (front) + { + glDrawBuffer(GL_FRONT); + } + else + { + glDrawBuffer(GL_BACK); + } + + + if (y1 < y2) + { + y_low = y1; + y_hi = y2; + } + else + { + y_low = y2; + y_hi = y1; + } + + + if (x1 < x2) + { + x_low = x1; + x_hi = x2; + } + else + { + x_low = x2; + x_hi = x1; + } + + + width = abs(x_hi-x_low) + 1; + height = abs(y_hi-y_low) + 1; + + + /* write out a row of pixels */ + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glRasterPos3f( (2.0 * (GLfloat)(x_low) / this->Size[0] - 1), + (2.0 * (GLfloat)(y_low) / this->Size[1] - 1), + -1.0 ); + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + + glDisable( GL_SCISSOR_TEST ); + + // Turn of texturing in case it is on - some drivers have a problem + // getting / setting pixels with texturing enabled. + glDisable( GL_TEXTURE_2D ); + + if (!blend) + { + glDisable(GL_BLEND); + glDrawPixels( width, height, GL_RGBA, GL_UNSIGNED_BYTE, + data); + glEnable(GL_BLEND); + } + else + { + glDrawPixels( width, height, GL_RGBA, GL_UNSIGNED_BYTE, + data); + } + + // This seems to be necessary for the image to show up + glFlush(); + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } +} + + +int vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2, + float* z_data ) +{ + int y_low; + int x_low; + int width, height; + + // set the current window + this->MakeCurrent(); + + if (y1 < y2) + { + y_low = y1; + } + else + { + y_low = y2; + } + + if (x1 < x2) + { + x_low = x1; + } + else + { + x_low = x2; + } + + width = abs(x2 - x1)+1; + height = abs(y2 - y1)+1; + + // Error checking + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + // Turn of texturing in case it is on - some drivers have a problem + // getting / setting pixels with texturing enabled. + glDisable( GL_TEXTURE_2D ); + glDisable( GL_SCISSOR_TEST ); + glPixelStorei( GL_PACK_ALIGNMENT, 1 ); + + glReadPixels( x_low, y_low, + width, height, + GL_DEPTH_COMPONENT, GL_FLOAT, + z_data ); + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } +} + +float *vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2 ) +{ + float *z_data; + + int width, height; + width = abs(x2 - x1)+1; + height = abs(y2 - y1)+1; + + z_data = new float[width*height]; + this->GetZbufferData(x1, y1, x2, y2, z_data); + + return z_data; +} + +int vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2, + vtkFloatArray *buffer ) +{ + int width, height; + width = abs(x2 - x1)+1; + height = abs(y2 - y1)+1; + int size = width*height; + if ( buffer->GetMaxId()+1 != size) + { + vtkDebugMacro("Resizing array."); + buffer->SetNumberOfComponents(1); + buffer->SetNumberOfValues(size); + } + return this->GetZbufferData(x1, y1, x2, y2, buffer->GetPointer(0)); +} + +int vtkOpenGLRenderWindow::SetZbufferData( int x1, int y1, int x2, int y2, + vtkFloatArray *buffer ) +{ + int width, height; + width = abs(x2 - x1)+1; + height = abs(y2 - y1)+1; + int size = width*height; + if ( buffer->GetMaxId()+1 != size ) + { + vtkErrorMacro("Buffer is of wrong size."); + return VTK_ERROR; + } + return this->SetZbufferData(x1, y1, x2, y2, buffer->GetPointer(0)); +} + +int vtkOpenGLRenderWindow::SetZbufferData( int x1, int y1, int x2, int y2, + float *buffer ) +{ + int y_low; + int x_low; + int width, height; + + // set the current window + this->MakeCurrent(); + + if (y1 < y2) + { + y_low = y1; + } + else + { + y_low = y2; + } + + if (x1 < x2) + { + x_low = x1; + } + else + { + x_low = x2; + } + + width = abs(x2 - x1)+1; + height = abs(y2 - y1)+1; + + // Error checking + // Must clear previous errors first. + while(glGetError() != GL_NO_ERROR); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + glRasterPos2f( 2.0 * (GLfloat)(x_low) / this->Size[0] - 1, + 2.0 * (GLfloat)(y_low) / this->Size[1] - 1); + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + // Turn of texturing in case it is on - some drivers have a problem + // getting / setting pixels with texturing enabled. + glDisable( GL_SCISSOR_TEST ); + glDisable( GL_TEXTURE_2D ); + glPixelStorei( GL_PACK_ALIGNMENT, 1 ); + + glDrawPixels( width, height, GL_DEPTH_COMPONENT, GL_FLOAT, buffer); + + // This seems to be necessary for the image to show up + glFlush(); + + if (glGetError() != GL_NO_ERROR) + { + return VTK_ERROR; + } + else + { + return VTK_OK; + } +} + + +void vtkOpenGLRenderWindow::RegisterTextureResource (GLuint id) +{ + this->TextureResourceIds->InsertNextId ((int) id); +} + + diff --git a/Rendering/vtkOpenGLRenderWindow.h b/Rendering/vtkOpenGLRenderWindow.h new file mode 100644 index 0000000..0603ad1 --- /dev/null +++ b/Rendering/vtkOpenGLRenderWindow.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLRenderWindow - OpenGL rendering window +// .SECTION Description +// vtkOpenGLRenderWindow is a concrete implementation of the abstract class +// vtkRenderWindow. vtkOpenGLRenderer interfaces to the OpenGL graphics +// library. Application programmers should normally use vtkRenderWindow +// instead of the OpenGL specific version. + +#ifndef __vtkOpenGLRenderWindow_h +#define __vtkOpenGLRenderWindow_h + +#include "vtkRenderWindow.h" + +#include "vtkOpenGL.h" // Needed for GLuint. + +class vtkIdList; + +class VTK_RENDERING_EXPORT vtkOpenGLRenderWindow : public vtkRenderWindow +{ +protected: + int MultiSamples; + long OldMonitorSetting; + +public: + vtkTypeRevisionMacro(vtkOpenGLRenderWindow,vtkRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/Get the maximum number of multisamples + static void SetGlobalMaximumNumberOfMultiSamples(int val); + static int GetGlobalMaximumNumberOfMultiSamples(); + + // Description: + // Set / Get the number of multisamples to use for hardware antialiasing. + vtkSetMacro(MultiSamples,int); + vtkGetMacro(MultiSamples,int); + + // Description: + // Update system if needed due to stereo rendering. + virtual void StereoUpdate(); + + // Description: + // Set/Get the pixel data of an image, transmitted as RGBRGB... + virtual unsigned char *GetPixelData(int x,int y,int x2,int y2,int front); + virtual int GetPixelData(int x,int y,int x2,int y2, int front, + vtkUnsignedCharArray*); + virtual int SetPixelData(int x,int y,int x2,int y2,unsigned char *, + int front); + virtual int SetPixelData(int x,int y,int x2,int y2, vtkUnsignedCharArray*, + int front); + + // Description: + // Set/Get the pixel data of an image, transmitted as RGBARGBA... + virtual float *GetRGBAPixelData(int x,int y,int x2,int y2,int front); + virtual int GetRGBAPixelData(int x,int y,int x2,int y2, int front, + vtkFloatArray* data); + virtual int SetRGBAPixelData(int x,int y,int x2,int y2,float *,int front, + int blend=0); + virtual int SetRGBAPixelData(int x,int y,int x2,int y2, vtkFloatArray*, + int front, int blend=0); + virtual void ReleaseRGBAPixelData(float *data); + virtual unsigned char *GetRGBACharPixelData(int x,int y,int x2,int y2, + int front); + virtual int GetRGBACharPixelData(int x,int y,int x2,int y2, int front, + vtkUnsignedCharArray* data); + virtual int SetRGBACharPixelData(int x,int y,int x2,int y2,unsigned char *, + int front, int blend=0); + virtual int SetRGBACharPixelData(int x,int y,int x2,int y2, + vtkUnsignedCharArray *, + int front, int blend=0); + + // Description: + // Set/Get the zbuffer data from an image + virtual float *GetZbufferData( int x1, int y1, int x2, int y2 ); + virtual int GetZbufferData( int x1, int y1, int x2, int y2, float* z ); + virtual int GetZbufferData( int x1, int y1, int x2, int y2, + vtkFloatArray* z ); + virtual int SetZbufferData( int x1, int y1, int x2, int y2, float *buffer ); + virtual int SetZbufferData( int x1, int y1, int x2, int y2, + vtkFloatArray *buffer ); + + // Description: + // Make this window the current OpenGL context. + void MakeCurrent() = 0; + + // Description: + // Register a texture name with this render window. + void RegisterTextureResource (GLuint id); + + // Description: + // Get the size of the depth buffer. + int GetDepthBufferSize(); + + // Description: + // Initialize OpenGL for this window. + virtual void OpenGLInit(); + +protected: + vtkOpenGLRenderWindow(); + ~vtkOpenGLRenderWindow(); + + vtkIdList *TextureResourceIds; + + int GetPixelData(int x,int y,int x2,int y2,int front, unsigned char* data); + int GetRGBAPixelData(int x,int y,int x2,int y2, int front, float* data); + int GetRGBACharPixelData(int x,int y,int x2,int y2, int front, + unsigned char* data); + +private: + vtkOpenGLRenderWindow(const vtkOpenGLRenderWindow&); // Not implemented. + void operator=(const vtkOpenGLRenderWindow&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkOpenGLRenderer.cxx b/Rendering/vtkOpenGLRenderer.cxx new file mode 100644 index 0000000..f937880 --- /dev/null +++ b/Rendering/vtkOpenGLRenderer.cxx @@ -0,0 +1,334 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLRenderer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLRenderer.h" + +#include "vtkCuller.h" +#include "vtkLightCollection.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLProperty.h" +#include "vtkRenderWindow.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif + +#include + +class vtkGLPickInfo +{ +public: + GLuint* PickBuffer; + GLuint PickedId; +}; + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLRenderer, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkOpenGLRenderer); +#endif + +#define VTK_MAX_LIGHTS 8 + +vtkOpenGLRenderer::vtkOpenGLRenderer() +{ + this->PickInfo = new vtkGLPickInfo; + this->NumberOfLightsBound = 0; + this->PickInfo->PickBuffer = 0; + this->PickInfo->PickedId = 0; + this->PickedZ = 0; +} + +// Internal method temporarily removes lights before reloading them +// into graphics pipeline. +void vtkOpenGLRenderer::ClearLights (void) +{ + short curLight; + float Info[4]; + + // define a lighting model and set up the ambient light. + // use index 11 for the heck of it. Doesn't matter except for 0. + + // update the ambient light + Info[0] = this->Ambient[0]; + Info[1] = this->Ambient[1]; + Info[2] = this->Ambient[2]; + Info[3] = 1.0; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Info); + + if ( this->TwoSidedLighting ) + { + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + } + else + { + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); + } + + // now delete all the old lights + for (curLight = GL_LIGHT0; curLight < GL_LIGHT0 + VTK_MAX_LIGHTS; curLight++) + { + glDisable((GLenum)curLight); + } + + this->NumberOfLightsBound = 0; +} + +// Ask lights to load themselves into graphics pipeline. +int vtkOpenGLRenderer::UpdateLights () +{ + vtkLight *light; + short curLight; + float status; + int count; + + // Check if a light is on. If not then make a new light. + count = 0; + curLight= this->NumberOfLightsBound + GL_LIGHT0; + + vtkCollectionSimpleIterator sit; + for(this->Lights->InitTraversal(sit); + (light = this->Lights->GetNextLight(sit)); ) + { + status = light->GetSwitch(); + if ((status > 0.0)&& (curLight < (GL_LIGHT0+VTK_MAX_LIGHTS))) + { + curLight++; + count++; + } + } + + if( !count ) + { + vtkDebugMacro(<<"No lights are on, creating one."); + this->CreateLight(); + } + + count = 0; + curLight= this->NumberOfLightsBound + GL_LIGHT0; + + // set the matrix mode for lighting. ident matrix on viewing stack + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + for(this->Lights->InitTraversal(sit); + (light = this->Lights->GetNextLight(sit)); ) + { + + status = light->GetSwitch(); + + // if the light is on then define it and bind it. + // also make sure we still have room. + if ((status > 0.0)&& (curLight < (GL_LIGHT0+VTK_MAX_LIGHTS))) + { + light->Render((vtkRenderer *)this,curLight); + glEnable((GLenum)curLight); + // increment the current light by one + curLight++; + count++; + } + } + + this->NumberOfLightsBound = curLight - GL_LIGHT0; + + glPopMatrix(); + glEnable(GL_LIGHTING); + return count; +} + +// Concrete open gl render method. +void vtkOpenGLRenderer::DeviceRender(void) +{ + // Do not remove this MakeCurrent! Due to Start / End methods on + // some objects which get executed during a pipeline update, + // other windows might get rendered since the last time + // a MakeCurrent was called. + this->RenderWindow->MakeCurrent(); + + // standard render method + this->ClearLights(); + + this->UpdateCamera(); + this->UpdateLightGeometry(); + this->UpdateLights(); + + // set matrix mode for actors + glMatrixMode(GL_MODELVIEW); + + this->UpdateGeometry(); + + // clean up the model view matrix set up by the camera + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + + +void vtkOpenGLRenderer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number Of Lights Bound: " << + this->NumberOfLightsBound << "\n"; + os << indent << "PickBuffer " << this->PickInfo->PickBuffer << "\n"; + os << indent << "PickedId" << this->PickInfo->PickedId<< "\n"; + os << indent << "PickedZ " << this->PickedZ << "\n"; +} + + +void vtkOpenGLRenderer::Clear(void) +{ + GLbitfield clear_mask = 0; + + if (! this->Transparent()) + { + glClearColor( ((GLclampf)(this->Background[0])), + ((GLclampf)(this->Background[1])), + ((GLclampf)(this->Background[2])), + ((GLclampf)(0.0)) ); + clear_mask |= GL_COLOR_BUFFER_BIT; + } + + glClearDepth( (GLclampd)( 1.0 ) ); + clear_mask |= GL_DEPTH_BUFFER_BIT; + + vtkDebugMacro(<< "glClear\n"); + glClear(clear_mask); +} + +void vtkOpenGLRenderer::StartPick(unsigned int pickFromSize) +{ + + int bufferSize = pickFromSize * 4; + + // Do not remove this MakeCurrent! Due to Start / End methods on + // some objects which get executed during a pipeline update, + // other windows might get rendered since the last time + // a MakeCurrent was called. + this->RenderWindow->MakeCurrent(); + this->RenderWindow->IsPickingOn(); + this->PickInfo->PickBuffer = new GLuint[bufferSize]; + glSelectBuffer(bufferSize, this->PickInfo->PickBuffer); + // change to selection mode + (void)glRenderMode(GL_SELECT); + // initialize the pick names and add a 0 name, for no pick + glInitNames(); + glPushName(0); +} + + + +void vtkOpenGLRenderer::UpdatePickId() +{ + glLoadName(this->CurrentPickId++); +} + + +void vtkOpenGLRenderer::DevicePickRender() +{ + // Do not remove this MakeCurrent! Due to Start / End methods on + // some objects which get executed during a pipeline update, + // other windows might get rendered since the last time + // a MakeCurrent was called. + this->RenderWindow->MakeCurrent(); + + // standard render method + this->ClearLights(); + + this->UpdateCamera(); + this->UpdateLightGeometry(); + this->UpdateLights(); + + // set matrix mode for actors + glMatrixMode(GL_MODELVIEW); + + this->PickGeometry(); + + // clean up the model view matrix set up by the camera + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} + + +void vtkOpenGLRenderer::DonePick() +{ + glFlush(); + GLuint hits = glRenderMode(GL_RENDER); + unsigned int depth = (unsigned int)-1; + GLuint* ptr = this->PickInfo->PickBuffer; + this->PickInfo->PickedId = 0; + for(unsigned int k =0; k < hits; k++) + { + int num_names = *ptr; + int save = 0; + ptr++; // move to first depth value + if(*ptr <= depth) + { + depth = *ptr; + save = 1; + } + ptr++; // move to next depth value + if(*ptr <= depth) + { + depth = *ptr; + save = 1; + } + // move to first name picked + ptr++; + if(save) + { + this->PickInfo->PickedId = *ptr; + } + // skip additonal names + ptr += num_names; + } + // If there was a pick, then get the Z value + if(this->PickInfo->PickedId) + { + // convert from pick depth described as: + // Returned depth values are mapped such that the largest unsigned + // integer value corresponds to window coordinate depth 1.0, + // and zero corresponds to window coordinate depth 0.0. + + this->PickedZ = ((double)depth / (double)VTK_UNSIGNED_INT_MAX); + + // Clamp to range [0,1] + this->PickedZ = (this->PickedZ < 0.0) ? 0.0 : this->PickedZ; + this->PickedZ = (this->PickedZ > 1.0) ? 1.0: this->PickedZ; + } + delete [] this->PickInfo->PickBuffer; + this->PickInfo->PickBuffer = 0; + this->RenderWindow->IsPickingOff(); +} + +double vtkOpenGLRenderer::GetPickedZ() +{ + return this->PickedZ; +} + +unsigned int vtkOpenGLRenderer::GetPickedId() +{ + return (unsigned int)this->PickInfo->PickedId; +} + +vtkOpenGLRenderer::~vtkOpenGLRenderer() +{ + if (this->PickInfo->PickBuffer) + { + delete [] this->PickInfo->PickBuffer; + this->PickInfo->PickBuffer = 0; + } + delete this->PickInfo; +} + diff --git a/Rendering/vtkOpenGLRenderer.h b/Rendering/vtkOpenGLRenderer.h new file mode 100644 index 0000000..5e58588 --- /dev/null +++ b/Rendering/vtkOpenGLRenderer.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLRenderer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLRenderer - OpenGL renderer +// .SECTION Description +// vtkOpenGLRenderer is a concrete implementation of the abstract class +// vtkRenderer. vtkOpenGLRenderer interfaces to the OpenGL graphics library. + +#ifndef __vtkOpenGLRenderer_h +#define __vtkOpenGLRenderer_h + +#include "vtkRenderer.h" + +class VTK_RENDERING_EXPORT vtkOpenGLRenderer : public vtkRenderer +{ +protected: + int NumberOfLightsBound; + +public: + static vtkOpenGLRenderer *New(); + vtkTypeRevisionMacro(vtkOpenGLRenderer,vtkRenderer); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Concrete open gl render method. + void DeviceRender(void); + + // Description: + // Internal method temporarily removes lights before reloading them + // into graphics pipeline. + void ClearLights(void); + + void Clear(void); + + // Description: + // Ask lights to load themselves into graphics pipeline. + int UpdateLights(void); + +protected: + vtkOpenGLRenderer(); + ~vtkOpenGLRenderer(); + + //BTX + // Picking functions to be implemented by sub-classes + virtual void DevicePickRender(); + virtual void StartPick(unsigned int pickFromSize); + virtual void UpdatePickId(); + virtual void DonePick(); + virtual unsigned int GetPickedId(); + virtual double GetPickedZ(); + // Ivars used in picking + class vtkGLPickInfo* PickInfo; + //ETX + double PickedZ; +private: + vtkOpenGLRenderer(const vtkOpenGLRenderer&); // Not implemented. + void operator=(const vtkOpenGLRenderer&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkOpenGLStateCache.cxx b/Rendering/vtkOpenGLStateCache.cxx new file mode 100644 index 0000000..cad5001 --- /dev/null +++ b/Rendering/vtkOpenGLStateCache.cxx @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLStateCache.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +//************************************************************************* +/* + GlStateCache_Cache============================================ + This simply checks for redundancies in state-change requests and + only calls the real OpenGL call if there has in fact been a change. + This cannot, however, fix problems with the ordering of calls. +*/ + +#include "vtkWin32Header.h" +#include "vtkSystemIncludes.h" +#include "vtkOpenGLStateCache.h" + +// only one of these defined, so lets define it here +vtkOpenGLStateCache *vtkOpenGLStateCache::CurrentGLCache = 0; + +vtkOpenGLStateCache::vtkOpenGLStateCache() +{ + this->Initialize(); +} + +vtkOpenGLStateCache::~vtkOpenGLStateCache() +{ +} + +void vtkOpenGLStateCache::Initialize() +{ // when the context gets destroyed + int i; + for(i=0;i<8;i++) + { + Enable_GL_LIGHT_buckets[i]=-1; + Enable_GL_CLIP_PLANE_buckets[i]=-1; + } + + for(i=0;i<(0xDE1-0xB10);i++) + { + Enable_buckets[i]=-1; + } + + AlphaFunc_bucket=-1.0; + BlendFunc_bucket=(GLenum)0; + DepthFunc_bucket=(GLenum)0; + TexEnvf_MODE_bucket=-1.0; + LightModeli_LIGHT_MODEL_TWO_SIDE_bucket=-1; + LightModelfv_LIGHT_MODEL_AMBIENT_bucket[0]=-1.0f; + + for(i=0;i<8*4*8;i++) + { + Lightfv_buckets[i]=-1.0f; + } + + for(i=0;i<8*8;i++) + { + Lightf_buckets[i]=-1.0f; + } + + for(i=0;i<8;i++) + { + Lighti_SPOT_CUTOFF_buckets[i]=-1; + } + + for(i=0;i<8*8*4;i++) + { + Materialfv_buckets[i]=-1.0f; + } + + ShadeModel_bucket=(GLenum)0; + for(i=0;i<4;i++) + { + ClearColor_buckets[i]=-1.0f; + } + ClearDepth_bucket=-1.0; + DepthMask_bucket=-1.0f; + CullFace_bucket=(GLenum)0; + DrawBuffer_bucket=(GLenum)0; + MatrixMode_bucket=(GLenum)0; + + for(i=0;i<4;i++) + { + Viewport_bucket[i]=-1; + Scissor_bucket[i]=-1; + } + for(i=0;i<4*GL_MAX_CLIP_PLANES;i++) + { + ClipPlane_bucket[i]=-1.0; + } + + for(i=0;i<8;i++) + { + ColorMaterial_bucket[i]=(GLenum)0; + } + + PointSize_bucket=-1.0; + LineWidth_bucket=-1.0; + LineStipple_FACTOR_bucket=-1; + LineStipple_PATTERN_bucket=0; + DepthRange_NEAR_bucket=-1.0; + DepthRange_FAR_bucket=-1.0; + compile_and_exec=0; + listnum=0; +} + diff --git a/Rendering/vtkOpenGLStateCache.h b/Rendering/vtkOpenGLStateCache.h new file mode 100644 index 0000000..b1df8ae --- /dev/null +++ b/Rendering/vtkOpenGLStateCache.h @@ -0,0 +1,581 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLStateCache.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLStateCache - checks for redundancies in state-change requests +// .SECTION Description +// This simply checks for redundancies in state-change requests and +// only calls the real OpenGL call if there has in fact been a change. +// This cannot, however, fix problems with the ordering of calls. + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" // Needed for GL api types. +#endif + +#define vtkOpenGLCall_glEnable vtkOpenGLStateCache::CurrentGLCache->glEnable +#define vtkOpenGLCall_glDisable vtkOpenGLStateCache::CurrentGLCache->glDisable +#define vtkOpenGLCall_glAlphaFunc vtkOpenGLStateCache::CurrentGLCache->glAlphaFunc +#define vtkOpenGLCall_glBlendFunc vtkOpenGLStateCache::CurrentGLCache->glBlendFunc +#define vtkOpenGLCall_glDepthFunc vtkOpenGLStateCache::CurrentGLCache->glDepthFunc +#define vtkOpenGLCall_glTexEnvf vtkOpenGLStateCache::CurrentGLCache->glTexEnvf +#define vtkOpenGLCall_glLightModeli vtkOpenGLStateCache::CurrentGLCache->glLightModeli +#define vtkOpenGLCall_glLightModelfv vtkOpenGLStateCache::CurrentGLCache->glLightMOdelfv +#define vtkOpenGLCall_glLightfv vtkOpenGLStateCache::CurrentGLCache->glLightfv +#define vtkOpenGLCall_glLightf vtkOpenGLStateCache::CurrentGLCache->glLightf +#define vtkOpenGLCall_glLighti vtkOpenGLStateCache::CurrentGLCache->glLighti +#define vtkOpenGLCall_glMaterialfv vtkOpenGLStateCache::CurrentGLCache->glMaterialfv +#define vtkOpenGLCall_glShadeModel vtkOpenGLStateCache::CurrentGLCache->glShadeModel +#define vtkOpenGLCall_glClearColor vtkOpenGLStateCache::CurrentGLCache->glClearColor +#define vtkOpenGLCall_glClearDepth vtkOpenGLStateCache::CurrentGLCache->glClearDepth +#define vtkOpenGLCall_glDepthMask vtkOpenGLStateCache::CurrentGLCache->glDepthMask +#define vtkOpenGLCall_glCullFace vtkOpenGLStateCache::CurrentGLCache->glCullFace +#define vtkOpenGLCall_glClear vtkOpenGLStateCache::CurrentGLCache->glClear +#define vtkOpenGLCall_glDrawBuffer vtkOpenGLStateCache::CurrentGLCache->glDrawBuffer +#define vtkOpenGLCall_glMatrixMode vtkOpenGLStateCache::CurrentGLCache->glMatrixMode +#define vtkOpenGLCall_glViewport vtkOpenGLStateCache::CurrentGLCache->glViewport +#define vtkOpenGLCall_glScissor vtkOpenGLStateCache::CurrentGLCache->glScissor +#define vtkOpenGLCall_glClipPlane vtkOpenGLStateCache::CurrentGLCache->glClipPlane +#define vtkOpenGLCall_glColorMaterial vtkOpenGLStateCache::CurrentGLCache->glColorMaterial +#define vtkOpenGLCall_glPointSize vtkOpenGLStateCache::CurrentGLCache->glPointSize +#define vtkOpenGLCall_glLineWidth vtkOpenGLStateCache::CurrentGLCache->glLineWidth +#define vtkOpenGLCall_glLineStipple vtkOpenGLStateCache::CurrentGLCache->glLineStipple +#define vtkOpenGLCall_glDepthRange vtkOpenGLStateCache::CurrentGLCache->glDepthRange +#define vtkOpenGLCall_glPolygonOffset vtkOpenGLStateCache::CurrentGLCache->glPolygonOffset + +#define vtkOpenGLCall_glPushMatrix glPushMatrix +#define vtkOpenGLCall_glPopMatrix glPopMatrix +#define vtkOpenGLCall_glMultMatrixd glMultMatrixd +#define vtkOpenGLCall_glLoadMatrixd glLoadMatrixd +#define vtkOpenGLCall_glLoadIdentity glLoadIdentity +#define vtkOpenGLCall_glSelectBuffer glSelectBuffer +#define vtkOpenGLCall_glRenderMode glRenderMode +#define vtkOpenGLCall_glInitNames glInitNames +#define vtkOpenGLCall_glPushName glPushName +#define vtkOpenGLCall_glLoadName glLoadName +#define vtkOpenGLCall_glGetIntegerv glGetIntegerv +#define vtkOpenGLCall_glIsTexture glIsTexture +#define vtkOpenGLCall_glDeleteTextures glDeleteTexture +#define vtkOpenGLCall_glGenTextures glGenTextures +#define vtkOpenGLCall_glBindTexture glBindTexture +#define vtkOpenGLCall_glTexParameterf glTextParameterf +#define vtkOpenGLCall_glTexCoord2fv glTexCoord2fv +#define vtkOpenGLCall_glVertex3fv glVertex3fv +#define vtkOpenGLCall_glNormal3fv glNormal3fv +#define vtkOpenGLCall_glColor3f glColor3f +#define vtkOpenGLCall_glColor4ubv glColor4ubv +#define vtkOpenGLCall_glColor4fv glColor4fv +#define vtkOpenGLCall_glBegin glBegin +#define vtkOpenGLCall_glEnd glEnd +#define vtkOpenGLCall_glTexImage2D glTextImage2D +#define vtkOpenGLCall_glDeleteLists glDeleteLists +#define vtkOpenGLCall_glIsList glIsList +#define vtkOpenGLCall_glGenLists glGenLists +#define vtkOpenGLCall_glCallList glCallList +#define vtkOpenGLCall_glReadBuffer glReadBuffer +#define vtkOpenGLCall_glPixelStorei glPixelStorei +#define vtkOpenGLCall_glReadPixels glReadPixels +#define vtkOpenGLCall_glRasterPos3f glRasterPos3f +#define vtkOpenGLCall_glDrawPixels glDrawPixels +#define vtkOpenGLCall_glRasterPos2f glRasterPos2f +#define vtkOpenGLCall_glNewList glNewList +#define vtkOpenGLCall_glEndList glEndList + +class vtkOpenGLStateCache +{ +public: + static vtkOpenGLStateCache *CurrentGLCache; // recursive definition + + vtkOpenGLStateCache(); // set all members to initial values + ~vtkOpenGLStateCache(); // delete any dynamic objects + void Initialize(); + + // GL_BLEND = 0x0BE2 + // GL_POINT_SMOOTH = 0x0B10 + // GL_LINE_SMOOTH = 0x0B20 + // GL_POLYGON_SMOOTH= 0x0B41 + // GL_DEPTH_TEST = 0x0B71 + // GL_ALPHA_TEST = 0x0BC0 + // GL_TEXTURE_2D = 0x0DE1 + // GL_CLIP_PLANE0+i = 0x3000 + // GL_LIGHTING = 0x0B50 + // GL_COLOR_MATERIAL= 0x0B57 + // GL_NORMALIZE = 0x0BA1 + // GL_CULL_FACE = 0x0B44 + // GL_SCISSOR_TEST = 0x0C11 + // GL_POLYGON_OFFSET_FILL = 0x8037 + // GL_LINE_STIPPLE = 0x0B24 + // GL_LIGHT+i = 0x4000 + char Enable_buckets[0xDE1-0xB10+1]; // 0xB10-0xDE1 + char Enable_GL_LIGHT_buckets[8]; // 0x4000 + i (0=0xB10 && e<=0xDE1) + { + ex=e-0xB10; + val=Enable_buckets+ex; + } + else + { + printf("Error: glEnable of 0x%X failed\n",e); + } + } + } + if(val && *val!=1) + { + *val=1; + ::glEnable(e); + } + } + inline void glDisable(GLenum e) + { + register int ex; + register char *val=0; + if(e&0x4000) + { + ex=e-0x4000; + if(ex<8) { val=Enable_GL_LIGHT_buckets+ex; } + } + else + { + if(e&0x8000) + { + ex=e-0x8000; + if(ex<8) { val=Enable_GL_CLIP_PLANE_buckets+ex; } + } + else + { + if(e>=0xB10 && e<=0xDE1) + { + ex=e-0xB10; + val=Enable_buckets+ex; + } + else + { + printf("Error: glEnable of 0x%X failed\n",e); + } + } + } + if(val && *val!=0) + { + *val=0; + ::glDisable(e); + } + } + + // GL_GREATER = 0x0204, (GLclampf) 0 + GLclampf AlphaFunc_bucket; + inline void glAlphaFunc(GLenum e,GLclampf cf) + { + if(e==GL_GREATER && cf!=AlphaFunc_bucket) + { + AlphaFunc_bucket=cf; + ::glAlphaFunc(e,cf); + } + } + + // GL_SRC_ALPHA = 0x0302, GL_ONE_MINUS_SRC_ALPHA = 0x0303 + GLenum BlendFunc_bucket; // multibucket if any other blendfunc is used + inline void glBlendFunc(GLenum e,GLenum e1) + { + if(e==GL_SRC_ALPHA && e1!=BlendFunc_bucket) + { + BlendFunc_bucket=e1; + ::glBlendFunc(e,e1); + } + } + + // GL_GREATER = 0x0204 + // GL_LESS = 0x0201 + // GL_LEQUAL = 0x0203 + GLenum DepthFunc_bucket; + inline void glDepthFunc(GLenum e) + { + if(e!=DepthFunc_bucket) + { + DepthFunc_bucket=e; + ::glDepthFunc(e); + } + } + + // GL_TEXTURE_ENV = 0x2300, GL_TEXTURE_ENV_MODE = 0x2200, GL_MODULATE = 0x2100 + GLfloat TexEnvf_MODE_bucket; // total kludge right now + inline void glTexEnvf(GLenum e,GLenum e1,GLfloat f) + { + if(e==GL_TEXTURE_ENV && e1==GL_TEXTURE_ENV_MODE) + { + if(f!=TexEnvf_MODE_bucket) + { + TexEnvf_MODE_bucket=f; + ::glTexEnvf(e,e1,f); + } + } + } + + // GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE/FALSE + // GL_LIGHT_MODEL_TWO_SIDE, 0 + GLint LightModeli_LIGHT_MODEL_TWO_SIDE_bucket; // shoudld check other modes + inline void glLightModeli(GLenum e,GLint i) + { + if(e==GL_LIGHT_MODEL_TWO_SIDE && i!=LightModeli_LIGHT_MODEL_TWO_SIDE_bucket){ + LightModeli_LIGHT_MODEL_TWO_SIDE_bucket=i; + ::glLightModeli(e,i); + } + } + + // GL_LIGHT_MODEL_AMBIENT, fvect(amb color), A=1.0 + // GL_LIGHT_MODEL_AMBIENT = 0x0B53 + GLfloat LightModelfv_LIGHT_MODEL_AMBIENT_bucket[3]; + inline void glLightModelfv(GLenum e,GLfloat *fv) + { + if(e==GL_LIGHT_MODEL_AMBIENT && + (fv[0]!=LightModelfv_LIGHT_MODEL_AMBIENT_bucket[0] || + fv[1]!=LightModelfv_LIGHT_MODEL_AMBIENT_bucket[1] || + fv[2]!=LightModelfv_LIGHT_MODEL_AMBIENT_bucket[2])){ + fv[0]=LightModelfv_LIGHT_MODEL_AMBIENT_bucket[0]; + fv[1]=LightModelfv_LIGHT_MODEL_AMBIENT_bucket[1]; + fv[2]=LightModelfv_LIGHT_MODEL_AMBIENT_bucket[2]; + ::glLightModelfv(e,fv); + } + } + + // light=GL_LIGHT index + // pname= lighting type + // GL_DIFFUSE = 0x1201 + // GL_SPECULAR = 0x1202 + // GL_POSITION = 0x1203 + // GL_SPOT_DIRECTION = 0x1204 + GLfloat Lightfv_buckets[8*4*8]; + inline void glLightfv( GLenum light, GLenum pname, const GLfloat *params) + { + register GLfloat *val = Lightfv_buckets + ((((int)(pname-0x1201))|((int)(light-GL_LIGHT0)<<3))<<2); + if(params[0]!=val[0] || + params[1]!=val[1] || + params[2]!=val[2] || + params[3]!=val[3]) + { + val[0]=params[0]; + val[1]=params[1]; + val[2]=params[2]; + val[3]=params[3]; + ::glLightfv(light,pname,params); + } + } + + // light=GL_LIGHT index + // pname= lighting parameter + // GL_SPOT_EXPONENT = 0x1205 + // GL_SPOT_CUTOFF = 0x1206 + // GL_CONSTANT_ATTENUATION = 0x1207 + // GL_LINEAR_ATTENUATION = 0x1208 + // GL_QUADRATIC_ATTENUATION= 0x1209 + GLfloat Lightf_buckets[8*8]; + GLint Lighti_SPOT_CUTOFF_buckets[8]; + inline void glLightf( GLenum light, GLenum pname, GLfloat f){ + register GLfloat *val=Lightf_buckets+(((int)(light-GL_LIGHT0)<<3)|((int)(pname-0x1205))); + if(val[0]!=f) + { + val[0]=f; + ::glLightf(light,pname,f); + if(pname==GL_SPOT_CUTOFF) // invalidate integer spot cutoff + Lighti_SPOT_CUTOFF_buckets[light-GL_LIGHT0]=-1; + } + } + + // light=GL_LIGHT index + // pname=lighting parameter + // GL_SPOT_CUTOFF = 0x1206 + // needs to invalidate the float light cutoff + inline void glLighti( GLenum light, GLenum pname, GLint f) + { + if(pname==GL_SPOT_CUTOFF && f!=Lighti_SPOT_CUTOFF_buckets[light-GL_LIGHT0]){ + Lighti_SPOT_CUTOFF_buckets[light-GL_LIGHT0]=f; + ::glLighti(light,pname,f); + // need to invalidate the float cutoff + Lightf_buckets[((int)(light-GL_LIGHT0)<<3)|0x02] = -1.0f; + } + } + + // Face, GL_AMBIENT, float Info[4] + // GL_FRONT = 0x0404 + // GL_BACK = 0x0405 + // GL_FRONT_AND_BACK = 0x0408 + // GL_AMBIENT = 0x1200 + // GL_DIFFUSE = 0x1201 + // GL_SPECULAR = 0x1202 + // GL_EMISSION = 0x1600 + // GL_SHININESS = 0x1601 + // GL_AMBIENT_AND_DIFFUSE = 0x1602 + // GL_COLOR_INDEXES = 0x1603 + GLfloat Materialfv_buckets[8*8*4]; + inline void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params ) + { + register int idx; + register GLfloat *val; + if(pname>=0x1600) + { + idx=pname-0x1600 + 4; // put it just past the 120x buckets + } + else + { + idx=pname-0x1200; + } + // FRONT/BACK and FRONT_AND_BACK should do both. + // or perhaps should be a separate state key? + // For now, we will treat FRONT_AND_BACK independently + // because from a practical standpoint, that's how + // it tends to get used. + val = Materialfv_buckets + ((((face-0x0404)<<3)|idx)<<2); + if(val[0]!=params[0] || + val[1]!=params[1] || + val[2]!=params[2] || + val[3]!=params[3]) + { + val[0]=params[0]; + val[1]=params[1]; + val[2]=params[2]; + val[3]=params[3]; + ::glMaterialfv(face,pname,params); + } + } + + /* + a=0; + a|=(val[0]^params[0]) + a|=(val[1]^params[1]) + a|=(val[2]^params[2]) + a|=(val[3]^params[3]) + */ + // GL_FLAT = 0x1D00 + // GL_SMOOTH = 0x1D01 + GLenum ShadeModel_bucket; + inline void glShadeModel(GLenum e) + { + if(ShadeModel_bucket!=e) + { + ShadeModel_bucket=e; + ::glShadeModel(e); + } + } + + GLclampf ClearColor_buckets[4]; + inline void glClearColor(GLclampf r,GLclampf g,GLclampf b,GLclampf a) + { + register GLclampf *c=ClearColor_buckets; + if(c[0]!=r || + c[1]!=g || + c[2]!=b || + c[3]!=a) + { + c[0]=r; + c[1]=g; + c[2]=b; + c[3]=a; + ::glClearColor(r,g,b,a); + } + } + + GLclampd ClearDepth_bucket; + inline void glClearDepth(GLclampd d) + { + if(d!=ClearDepth_bucket) + { + ClearDepth_bucket=d; + ::glClearDepth(d); + } + } + + GLclampf DepthMask_bucket; + inline void glDepthMask(GLenum e) + { + if(DepthMask_bucket!=e) + { + DepthMask_bucket=e; + ::glDepthMask(e); + } + } + + // GL_FRONT = 0x0404 + // GL_BACK = 0x0405 + GLenum CullFace_bucket; + inline void glCullFace(GLenum e) + { + if(CullFace_bucket!=e) + { + CullFace_bucket=e; + ::glCullFace(e); + } + } + + // well, lets go ahead and let it clear when it wants to + inline void glClear(GLbitfield b) { ::glClear(b);} + // GL_BACK_LEFT = 0x0402 + // GL_BACK_RIGHT = 0x0403 + // GL_FRONT = 0x0404 + // GL_BACK = 0x0405 + GLenum DrawBuffer_bucket; + inline void glDrawBuffer(GLenum e) { + if(e!=DrawBuffer_bucket){ + DrawBuffer_bucket=e; + ::glDrawBuffer(e); + } + } + //============Matrix Ops (behave different for deferred ops)=== + // GL_MODELVIEW=0x1700 + // GL_PROJECTION=0x1701 + GLenum MatrixMode_bucket; + inline void glMatrixMode(GLenum e) { + if(e!=MatrixMode_bucket){ + MatrixMode_bucket=e; + ::glMatrixMode(e); + } + } + + GLint Viewport_bucket[4]; + inline void glViewport(GLint llx,GLint lly,GLint u,GLint v){ + register GLint *val=Viewport_bucket; + if(val[0]!=llx || + val[1]!=lly || + val[2]!=u || + val[3]!=v){ + val[0]=llx; + val[1]=lly; + val[2]=u; + val[3]=v; + ::glViewport(llx,lly,u,v); + } + } + // only needs to be called if scissor changes (and it usually won't) + GLint Scissor_bucket[4]; + inline void glScissor(GLint llx,GLint lly,GLint u,GLint v){ + register GLint *val=Scissor_bucket; + if(val[0]!=llx || + val[1]!=lly || + val[2]!=u || + val[3]!=v){ + val[0]=llx; + val[1]=lly; + val[2]=u; + val[3]=v; + ::glScissor(llx,lly,u,v); + } + } + + // what is the order of the clip plane eqn??? + // GL_CLIP_PLANE0 = 0x3000 + GLdouble ClipPlane_bucket[4*GL_MAX_CLIP_PLANES]; + inline void glClipPlane(GLenum e,const GLdouble *eqn){ + register GLdouble *val=ClipPlane_bucket + ((e-0x3000)<<2); + if(val[0]!=eqn[0] || + val[1]!=eqn[1] || + val[2]!=eqn[2] || + val[3]!=eqn[3]){ + val[0]=eqn[0]; + val[1]=eqn[1]; + val[2]=eqn[2]; + val[3]=eqn[3]; + ::glClipPlane(e,eqn); + } + } + + // face= + // GL_FRONT = 0x0404 + // GL_BACK = 0x0405 + // GL_FRONT_AND_BACK = 0x0408 + GLenum ColorMaterial_bucket[8]; + inline void glColorMaterial(GLenum face,GLenum mode ){ + register GLenum *val= ColorMaterial_bucket + (face-0x0404); + if(*val!=mode){ + *val=mode; + ::glColorMaterial(face,mode); + } + } + GLfloat PointSize_bucket; + inline void glPointSize(GLfloat f) { + if(f!=PointSize_bucket){ + PointSize_bucket=f; + ::glPointSize(f); + } + } + GLfloat LineWidth_bucket; + inline void glLineWidth(GLfloat f){ + if(f!=LineWidth_bucket){ + LineWidth_bucket=f; + ::glPointSize(f); + } + } + GLint LineStipple_FACTOR_bucket; + GLushort LineStipple_PATTERN_bucket; + inline void glLineStipple(GLint factor, GLushort pattern ) + { + if(factor!=LineStipple_FACTOR_bucket || + pattern!=LineStipple_PATTERN_bucket) + { + LineStipple_FACTOR_bucket=factor; + LineStipple_PATTERN_bucket=pattern; + ::glLineStipple(factor,pattern); + } + } + + GLclampd DepthRange_NEAR_bucket; + GLclampd DepthRange_FAR_bucket; + inline void glDepthRange(GLclampd nearval,GLclampd farval ) + { + if(DepthRange_NEAR_bucket!=nearval || + DepthRange_FAR_bucket!=farval) + { + DepthRange_NEAR_bucket=nearval; + DepthRange_FAR_bucket=farval; + ::glDepthRange(nearval,farval); + } + } + +#ifdef GL_VERSION_1_1 + // enable GL_POLYGON_OFFSET_FILL = 0x8037 + GLfloat PolygonOffset_bucket[2]; + inline void glPolygonOffset( GLfloat f,GLfloat u) { + if(PolygonOffset_bucket[0]!=f || + PolygonOffset_bucket[1]!=u){ + PolygonOffset_bucket[0]=f; + PolygonOffset_bucket[1]=u; + ::glPolygonOffset(f,u); + } + } +#endif +}; + + +//#ifdef vtkOpenGLStateCache_Cache +//#undef vtkOpenGLStateCache_Cache +//#endif diff --git a/Rendering/vtkOpenGLTexture.cxx b/Rendering/vtkOpenGLTexture.cxx new file mode 100644 index 0000000..c85e8a5 --- /dev/null +++ b/Rendering/vtkOpenGLTexture.cxx @@ -0,0 +1,425 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLTexture.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLTexture.h" + +#include "vtkImageData.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderer.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkOpenGLRenderWindow.h" + +#include "vtkOpenGL.h" + +#include + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLTexture, "$Revision: 1.56 $"); +vtkStandardNewMacro(vtkOpenGLTexture); +#endif + +// Initializes an instance, generates a unique index. +vtkOpenGLTexture::vtkOpenGLTexture() +{ + this->Index = 0; + this->RenderWindow = 0; +} + +vtkOpenGLTexture::~vtkOpenGLTexture() +{ + this->RenderWindow = NULL; +} + +// Release the graphics resources used by this texture. +void vtkOpenGLTexture::ReleaseGraphicsResources(vtkWindow *renWin) +{ + if (this->Index && renWin) + { + ((vtkRenderWindow *) renWin)->MakeCurrent(); +#ifdef GL_VERSION_1_1 + // free any textures + if (glIsTexture(this->Index)) + { + GLuint tempIndex; + tempIndex = this->Index; + // NOTE: Sun's OpenGL seems to require disabling of texture before delete + glDisable(GL_TEXTURE_2D); + glDeleteTextures(1, &tempIndex); + } +#else + if (glIsList(this->Index)) + { + glDeleteLists(this->Index,1); + } +#endif + } + this->Index = 0; + this->RenderWindow = NULL; + this->Modified(); +} + +// Implement base class method. +void vtkOpenGLTexture::Load(vtkRenderer *ren) +{ + GLenum format = GL_LUMINANCE; + vtkImageData *input = this->GetInput(); + + // need to reload the texture + if (this->GetMTime() > this->LoadTime.GetMTime() || + input->GetMTime() > this->LoadTime.GetMTime() || + (this->GetLookupTable() && this->GetLookupTable()->GetMTime () > + this->LoadTime.GetMTime()) || + ren->GetRenderWindow() != this->RenderWindow) + { + int bytesPerPixel; + int *size; + vtkDataArray *scalars; + unsigned char *dataPtr; + int rowLength; + unsigned char *resultData=NULL; + int xsize, ysize; + unsigned short xs,ys; + GLuint tempIndex=0; + + // get some info + size = input->GetDimensions(); + scalars = input->GetPointData()->GetScalars(); + + // make sure scalars are non null + if (!scalars) + { + vtkErrorMacro(<< "No scalar values found for texture input!"); + return; + } + + bytesPerPixel = scalars->GetNumberOfComponents(); + + // make sure using unsigned char data of color scalars type + if (this->MapColorScalarsThroughLookupTable || + scalars->GetDataType() != VTK_UNSIGNED_CHAR ) + { + dataPtr = this->MapScalarsToColors (scalars); + bytesPerPixel = 4; + } + else + { + dataPtr = static_cast(scalars)->GetPointer(0); + } + + // we only support 2d texture maps right now + // so one of the three sizes must be 1, but it + // could be any of them, so lets find it + if (size[0] == 1) + { + xsize = size[1]; ysize = size[2]; + } + else + { + xsize = size[0]; + if (size[1] == 1) + { + ysize = size[2]; + } + else + { + ysize = size[1]; + if (size[2] != 1) + { + vtkErrorMacro(<< "3D texture maps currently are not supported!"); + return; + } + } + } + + // xsize and ysize must be a power of 2 in OpenGL + xs = (unsigned short)xsize; + ys = (unsigned short)ysize; + while (!(xs & 0x01)) + { + xs = xs >> 1; + } + while (!(ys & 0x01)) + { + ys = ys >> 1; + } + + // -- decide whether the texture needs to be resampled -- + int resampleNeeded = 0; + // if not a power of two then resampling is required + if ((xs > 1)||(ys > 1)) + { + resampleNeeded = 1; + } + GLint maxDimGL; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxDimGL); + // if larger than permitted by the graphics library then must resample + if ( xsize > maxDimGL || ysize > maxDimGL ) + { + vtkDebugMacro( "Texture too big for gl, maximum is " << maxDimGL); + resampleNeeded = 1; + } + + if ( resampleNeeded ) + { + vtkDebugMacro(<< "Resampling texture to power of two for OpenGL"); + resultData = this->ResampleToPowerOfTwo(xsize, ysize, dataPtr, + bytesPerPixel); + } + + // format the data so that it can be sent to opengl + // each row must be a multiple of 4 bytes in length + // the best idea is to make your size a multiple of 4 + // so that this conversion will never be done. + rowLength = ((xsize*bytesPerPixel +3 )/4)*4; + if (rowLength == xsize*bytesPerPixel) + { + if ( resultData == NULL ) + { + resultData = dataPtr; + } + } + else + { + int col; + unsigned char *src,*dest; + int srcLength; + + srcLength = xsize*bytesPerPixel; + resultData = new unsigned char [rowLength*ysize]; + + src = dataPtr; + dest = resultData; + + for (col = 0; col < ysize; col++) + { + memcpy(dest,src,srcLength); + src += srcLength; + dest += rowLength; + } + } + + // free any old display lists (from the old context) + if (this->RenderWindow) + { + this->ReleaseGraphicsResources(this->RenderWindow); + } + + this->RenderWindow = ren->GetRenderWindow(); + + // make the new context current before we mess with opengl + this->RenderWindow->MakeCurrent(); + + // define a display list for this texture + // get a unique display list id +#ifdef GL_VERSION_1_1 + glGenTextures(1, &tempIndex); + this->Index = (long) tempIndex; + glBindTexture(GL_TEXTURE_2D, this->Index); +#else + this->Index = glGenLists(1); + glDeleteLists ((GLuint) this->Index, (GLsizei) 0); + glNewList ((GLuint) this->Index, GL_COMPILE); +#endif + + ((vtkOpenGLRenderWindow *)(ren->GetRenderWindow()))->RegisterTextureResource( this->Index ); + + if (this->Interpolate) + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR ); + } + else + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + } + if (this->Repeat) + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } + else + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + } + int internalFormat = bytesPerPixel; + switch (bytesPerPixel) + { + case 1: format = GL_LUMINANCE; break; + case 2: format = GL_LUMINANCE_ALPHA; break; + case 3: format = GL_RGB; break; + case 4: format = GL_RGBA; break; + } + // if we are using OpenGL 1.1, you can force 32 or16 bit textures +#ifdef GL_VERSION_1_1 + if (this->Quality == VTK_TEXTURE_QUALITY_32BIT) + { + switch (bytesPerPixel) + { + case 1: internalFormat = GL_LUMINANCE8; break; + case 2: internalFormat = GL_LUMINANCE8_ALPHA8; break; + case 3: internalFormat = GL_RGB8; break; + case 4: internalFormat = GL_RGBA8; break; + } + } + else if (this->Quality == VTK_TEXTURE_QUALITY_16BIT) + { + switch (bytesPerPixel) + { + case 1: internalFormat = GL_LUMINANCE4; break; + case 2: internalFormat = GL_LUMINANCE4_ALPHA4; break; + case 3: internalFormat = GL_RGB4; break; + case 4: internalFormat = GL_RGBA4; break; + } + } +#endif + glTexImage2D( GL_TEXTURE_2D, 0 , internalFormat, + xsize, ysize, 0, format, + GL_UNSIGNED_BYTE, (const GLvoid *)resultData ); +#ifndef GL_VERSION_1_1 + glEndList (); +#endif + // modify the load time to the current time + this->LoadTime.Modified(); + + // free memory + if (resultData != dataPtr) + { + delete [] resultData; + } + } + + // execute the display list that uses creates the texture +#ifdef GL_VERSION_1_1 + glBindTexture(GL_TEXTURE_2D, this->Index); +#else + glCallList ((GLuint) this->Index); +#endif + + // don't accept fragments if they have zero opacity. this will stop the + // zbuffer from be blocked by totally transparent texture fragments. + glAlphaFunc (GL_GREATER, (GLclampf) 0); + glEnable (GL_ALPHA_TEST); + + // now bind it + glEnable(GL_TEXTURE_2D); +} + + + +static int FindPowerOfTwo(int i) +{ + int size; + + for ( i--, size=1; i > 0; size*=2 ) + { + i /= 2; + } + + // [these lines added by Tim Hutton (implementing Joris Vanden Wyngaerd's suggestions)] + // limit the size of the texture to the maximum allowed by OpenGL + // (slightly more graceful than texture failing but not ideal) + GLint maxDimGL; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxDimGL); + if ( size > maxDimGL ) + { + size = maxDimGL ; + } + // end of Tim's additions + + return size; +} + +// Creates resampled unsigned char texture map that is a power of two in bith x and y. +unsigned char *vtkOpenGLTexture::ResampleToPowerOfTwo(int &xs, int &ys, unsigned char *dptr, + int bpp) +{ + unsigned char *tptr, *p, *p1, *p2, *p3, *p4; + int xsize, ysize, i, j, k, jOffset, iIdx, jIdx; + float pcoords[3], hx, hy, rm, sm, w0, w1, w2, w3; + + xsize = FindPowerOfTwo(xs); + ysize = FindPowerOfTwo(ys); + + hx = (float)(xs - 1.0) / (xsize - 1.0); + hy = (float)(ys - 1.0) / (ysize - 1.0); + + tptr = p = new unsigned char[xsize*ysize*bpp]; + + //Resample from the previous image. Compute parametric coordinates and interpolate + for (j=0; j < ysize; j++) + { + pcoords[1] = j*hy; + + jIdx = (int)pcoords[1]; + if ( jIdx >= (ys-1) ) //make sure to interpolate correctly at edge + { + jIdx = ys - 2; + pcoords[1] = 1.0; + } + else + { + pcoords[1] = pcoords[1] - jIdx; + } + jOffset = jIdx*xs; + sm = 1.0 - pcoords[1]; + + for (i=0; i < xsize; i++) + { + pcoords[0] = i*hx; + iIdx = (int)pcoords[0]; + if ( iIdx >= (xs-1) ) + { + iIdx = xs - 2; + pcoords[0] = 1.0; + } + else + { + pcoords[0] = pcoords[0] - iIdx; + } + rm = 1.0 - pcoords[0]; + + // Get pointers to 4 surrounding pixels + p1 = dptr + bpp*(iIdx + jOffset); + p2 = p1 + bpp; + p3 = p1 + bpp*xs; + p4 = p3 + bpp; + + // Compute interpolation weights interpolate components + w0 = rm*sm; + w1 = pcoords[0]*sm; + w2 = rm*pcoords[1]; + w3 = pcoords[0]*pcoords[1]; + for (k=0; k < bpp; k++) + { + *p++ = (unsigned char) (p1[k]*w0 + p2[k]*w1 + p3[k]*w2 + p4[k]*w3); + } + } + } + + xs = xsize; + ys = ysize; + + return tptr; +} + +void vtkOpenGLTexture::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkOpenGLTexture.h b/Rendering/vtkOpenGLTexture.h new file mode 100644 index 0000000..9b6b3ed --- /dev/null +++ b/Rendering/vtkOpenGLTexture.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLTexture.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLTexture - OpenGL texture map +// .SECTION Description +// vtkOpenGLTexture is a concrete implementation of the abstract class +// vtkTexture. vtkOpenGLTexture interfaces to the OpenGL rendering library. + +#ifndef __vtkOpenGLTexture_h +#define __vtkOpenGLTexture_h + +#include "vtkTexture.h" + +class vtkWindow; +class vtkOpenGLRenderer; +class vtkRenderWindow; + +class VTK_RENDERING_EXPORT vtkOpenGLTexture : public vtkTexture +{ +public: + static vtkOpenGLTexture *New(); + vtkTypeRevisionMacro(vtkOpenGLTexture,vtkTexture); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Load(vtkRenderer *ren); + + // Description: + // Release any graphics resources that are being consumed by this texture. + // The parameter window could be used to determine which graphic + // resources to release. Using the same texture object in multiple + // render windows is NOT currently supported. + void ReleaseGraphicsResources(vtkWindow *); + +protected: + vtkOpenGLTexture(); + ~vtkOpenGLTexture(); + + unsigned char *ResampleToPowerOfTwo(int &xsize, int &ysize, + unsigned char *dptr, int bpp); + + vtkTimeStamp LoadTime; + long Index; + vtkRenderWindow *RenderWindow; // RenderWindow used for previous render +private: + vtkOpenGLTexture(const vtkOpenGLTexture&); // Not implemented. + void operator=(const vtkOpenGLTexture&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkParallelCoordinatesActor.cxx b/Rendering/vtkParallelCoordinatesActor.cxx new file mode 100644 index 0000000..5515576 --- /dev/null +++ b/Rendering/vtkParallelCoordinatesActor.cxx @@ -0,0 +1,560 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParallelCoordinatesActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkParallelCoordinatesActor.h" + +#include "vtkAxisActor2D.h" +#include "vtkCellArray.h" +#include "vtkFieldData.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" +#include "vtkWindow.h" + +vtkCxxRevisionMacro(vtkParallelCoordinatesActor, "$Revision: 1.32 $"); +vtkStandardNewMacro(vtkParallelCoordinatesActor); + +vtkCxxSetObjectMacro(vtkParallelCoordinatesActor,Input,vtkDataObject); +vtkCxxSetObjectMacro(vtkParallelCoordinatesActor,LabelTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(vtkParallelCoordinatesActor,TitleTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Instantiate object +vtkParallelCoordinatesActor::vtkParallelCoordinatesActor() +{ + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.1,0.1); + + this->Position2Coordinate->SetValue(0.9, 0.8); + + this->IndependentVariables = VTK_IV_COLUMN; + this->N = 0; + + this->Input = NULL; + this->Axes = NULL; + this->Mins = NULL; + this->Maxs = NULL; + this->Xs = NULL; + + this->Title = NULL; + + this->TitleMapper = vtkTextMapper::New(); + + this->TitleActor = vtkActor2D::New(); + this->TitleActor->SetMapper(this->TitleMapper); + this->TitleActor->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + + this->PlotData = vtkPolyData::New(); + + this->PlotMapper = vtkPolyDataMapper2D::New(); + this->PlotMapper->SetInput(this->PlotData); + + this->PlotActor = vtkActor2D::New(); + this->PlotActor->SetMapper(this->PlotMapper); + + this->NumberOfLabels = 2; + + this->LabelTextProperty = vtkTextProperty::New(); + this->LabelTextProperty->SetBold(1); + this->LabelTextProperty->SetItalic(1); + this->LabelTextProperty->SetShadow(1); + this->LabelTextProperty->SetFontFamilyToArial(); + + this->TitleTextProperty = vtkTextProperty::New(); + this->TitleTextProperty->ShallowCopy(this->LabelTextProperty); + + this->LabelFormat = new char[8]; + sprintf(this->LabelFormat,"%s","%-#6.3g"); + + this->LastPosition[0] = + this->LastPosition[1] = + this->LastPosition2[0] = + this->LastPosition2[1] = 0; +} + +//---------------------------------------------------------------------------- +vtkParallelCoordinatesActor::~vtkParallelCoordinatesActor() +{ + this->TitleMapper->Delete(); + this->TitleMapper = NULL; + this->TitleActor->Delete(); + this->TitleActor = NULL; + + if ( this->Input ) + { + this->Input->Delete(); + this->Input = NULL; + } + + this->Initialize(); + + this->PlotData->Delete(); + this->PlotMapper->Delete(); + this->PlotActor->Delete(); + + if (this->Title) + { + delete [] this->Title; + this->Title = NULL; + } + + if (this->LabelFormat) + { + delete [] this->LabelFormat; + this->LabelFormat = NULL; + } + + this->SetLabelTextProperty(NULL); + this->SetTitleTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +// Free-up axes and related stuff +void vtkParallelCoordinatesActor::Initialize() +{ + if ( this->Axes ) + { + for (int i=0; iN; i++) + { + this->Axes[i]->Delete(); + } + delete [] this->Axes; + this->Axes = NULL; + delete [] this->Mins; + this->Mins = NULL; + delete [] this->Maxs; + this->Maxs = NULL; + delete [] this->Xs; + this->Xs = NULL; + } + this->N = 0; +} + +//---------------------------------------------------------------------------- +// Plot scalar data for each input dataset. +int vtkParallelCoordinatesActor::RenderOverlay(vtkViewport *viewport) +{ + int renderedSomething=0; + + // Make sure input is up to date. + if ( this->Input == NULL || this->N <= 0 ) + { + vtkErrorMacro(<< "Nothing to plot!"); + return 0; + } + + if ( this->Title != NULL ) + { + renderedSomething += this->TitleActor->RenderOverlay(viewport); + } + + this->PlotActor->SetProperty(this->GetProperty()); + renderedSomething += this->PlotActor->RenderOverlay(viewport); + + for (int i=0; iN; i++) + { + renderedSomething += this->Axes[i]->RenderOverlay(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +int vtkParallelCoordinatesActor::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int renderedSomething = 0; + + // Initialize + + vtkDebugMacro(<<"Plotting parallel coordinates"); + + // Make sure input is up to date, and that the data is the correct shape to + // plot. + + if (!this->Input) + { + vtkErrorMacro(<< "Nothing to plot!"); + return renderedSomething; + } + + if (!this->TitleTextProperty) + { + vtkErrorMacro(<<"Need title text property to render plot"); + return renderedSomething; + } + + if (!this->LabelTextProperty) + { + vtkErrorMacro(<<"Need label text property to render plot"); + return renderedSomething; + } + + // Viewport change may not require rebuild + + int positionsHaveChanged = 0; + if (viewport->GetMTime() > this->BuildTime || + (viewport->GetVTKWindow() && + viewport->GetVTKWindow()->GetMTime() > this->BuildTime)) + { + int *lastPosition = + this->PositionCoordinate->GetComputedViewportValue(viewport); + int *lastPosition2 = + this->Position2Coordinate->GetComputedViewportValue(viewport); + if (lastPosition[0] != this->LastPosition[0] || + lastPosition[1] != this->LastPosition[1] || + lastPosition2[0] != this->LastPosition2[0] || + lastPosition2[1] != this->LastPosition2[1] ) + { + this->LastPosition[0] = lastPosition[0]; + this->LastPosition[1] = lastPosition[1]; + this->LastPosition2[0] = lastPosition2[0]; + this->LastPosition2[1] = lastPosition2[1]; + positionsHaveChanged = 1; + } + } + + // Check modified time to see whether we have to rebuild. + + this->Input->Update(); + + if (positionsHaveChanged || + this->GetMTime() > this->BuildTime || + this->Input->GetMTime() > this->BuildTime || + this->LabelTextProperty->GetMTime() > this->BuildTime || + this->TitleTextProperty->GetMTime() > this->BuildTime) + { + int *size = viewport->GetSize(); + int stringSize[2]; + + vtkDebugMacro(<<"Rebuilding plot"); + + // Build axes + + if (!this->PlaceAxes(viewport, size)) + { + return renderedSomething; + } + + // Build title + + this->TitleMapper->SetInput(this->Title); + + if (this->TitleTextProperty->GetMTime() > this->BuildTime) + { + // Shallow copy here since the justification is changed but we still + // want to allow actors to share the same text property, and in that case + // specifically allow the title and label text prop to be the same. + this->TitleMapper->GetTextProperty()->ShallowCopy( + this->TitleTextProperty); + this->TitleMapper->GetTextProperty()->SetJustificationToCentered(); + } + + // We could do some caching here, but hey, that's just the title + + vtkAxisActor2D::SetFontSize(viewport, + this->TitleMapper, + size, + 1.0, + stringSize); + + this->TitleActor->GetPositionCoordinate()-> + SetValue((this->Xs[0]+this->Xs[this->N-1])/2.0,this->YMax+stringSize[1]/2.0); + this->TitleActor->SetProperty(this->GetProperty()); + + this->BuildTime.Modified(); + + } // If need to rebuild the plot + + if ( this->Title != NULL ) + { + renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport); + } + + this->PlotActor->SetProperty(this->GetProperty()); + renderedSomething += this->PlotActor->RenderOpaqueGeometry(viewport); + + for (int i=0; iN; i++) + { + renderedSomething += this->Axes[i]->RenderOpaqueGeometry(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +int vtkParallelCoordinatesActor::PlaceAxes(vtkViewport *viewport, int *vtkNotUsed(size)) +{ + vtkIdType i, j, ptId; + vtkDataObject *input = this->GetInput(); + vtkFieldData *field = input->GetFieldData(); + double v; + + this->Initialize(); + + if ( ! field ) + { + return 0; + } + + // Determine the shape of the field + int numColumns = field->GetNumberOfComponents(); //number of "columns" + vtkIdType numRows = VTK_LARGE_ID; //figure out number of rows + vtkIdType numTuples; + vtkDataArray *array; + for (i=0; iGetNumberOfArrays(); i++) + { + array = field->GetArray(i); + numTuples = array->GetNumberOfTuples(); + if ( numTuples < numRows ) + { + numRows = numTuples; + } + } + + // Determine the number of independent variables + if ( this->IndependentVariables == VTK_IV_COLUMN ) + { + this->N = numColumns; + } + else //row + { + this->N = numRows; + } + + if ( this->N <= 0 || this->N >= VTK_LARGE_ID ) + { + this->N = 0; + vtkErrorMacro(<<"No field data to plot"); + return 0; + } + + // We need to loop over the field to determine the range of + // each independent variable. + this->Mins = new double [this->N]; + this->Maxs = new double [this->N]; + for (i=0; iN; i++) + { + this->Mins[i] = VTK_DOUBLE_MAX; + this->Maxs[i] = -VTK_DOUBLE_MAX; + } + + if ( this->IndependentVariables == VTK_IV_COLUMN ) + { + for (j=0; jGetComponent(i,j); + if ( v < this->Mins[j] ) + { + this->Mins[j] = v; + } + if ( v > this->Maxs[j] ) + { + this->Maxs[j] = v; + } + } + } + } + else //row + { + for (j=0; jGetComponent(j,i); + if ( v < this->Mins[j] ) + { + this->Mins[j] = v; + } + if ( v > this->Maxs[j] ) + { + this->Maxs[j] = v; + } + } + } + } + + // Allocate space and create axes + + // TODO: this should be optimized, maybe by keeping a list of allocated + // objects, in order to avoid creation/destruction of axis actors + // and their underlying text properties (i.e. each time an axis is + // created, text properties are created and shallow-assigned a + // font size which value might be "far" from the target font size). + + this->Axes = new vtkAxisActor2D* [this->N]; + for (i=0; iN; i++) + { + this->Axes[i] = vtkAxisActor2D::New(); + this->Axes[i]->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + this->Axes[i]->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); + this->Axes[i]->SetRange(this->Mins[i],this->Maxs[i]); + this->Axes[i]->AdjustLabelsOff(); + this->Axes[i]->SetNumberOfLabels(this->NumberOfLabels); + this->Axes[i]->SetLabelFormat(this->LabelFormat); + this->Axes[i]->SetProperty(this->GetProperty()); + // We do not need shallow copy here since we do not modify any attributes + // in that class and we know that vtkAxisActor2D use ShallowCopy internally + // so that the size of the text prop is not affected by the automatic + // adjustment of its text mapper's size. + this->Axes[i]->SetLabelTextProperty(this->LabelTextProperty); + } + this->Xs = new int [this->N]; + + // Get the location of the corners of the box + int *p1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + int *p2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + + // Specify the positions for the axes + this->YMin = p1[1]; + this->YMax = p2[1]; + for (i=0; iN; i++) + { + this->Xs[i] = (int) (p1[0] + (double)i/((double)this->N) * (p2[0]-p1[0])); + this->Axes[i]->GetPositionCoordinate()->SetValue((double)this->Xs[i], + this->YMin); + this->Axes[i]->GetPosition2Coordinate()->SetValue((double)this->Xs[i], + this->YMax); + } + + // Now generate the lines to plot + this->PlotData->Initialize(); //remove old polydata, if any + vtkPoints *pts = vtkPoints::New(); + pts->Allocate(numRows*numColumns); + vtkCellArray *lines = vtkCellArray::New(); + this->PlotData->SetPoints(pts); + this->PlotData->SetLines(lines); + + double x[3]; x[2] = 0.0; + if ( this->IndependentVariables == VTK_IV_COLUMN ) + { + lines->Allocate(lines->EstimateSize(numRows,numColumns)); + for (j=0; jInsertNextCell(numColumns); + for (i=0; iXs[i]; + v = field->GetComponent(j,i); + if ( (this->Maxs[i]-this->Mins[i]) == 0.0 ) + { + x[1] = 0.5 * (this->YMax - this->YMin); + } + else + { + x[1] = this->YMin + + ((v - this->Mins[i]) / (this->Maxs[i] - this->Mins[i])) * + (this->YMax - this->YMin); + } + ptId = pts->InsertNextPoint(x); + lines->InsertCellPoint(ptId); + } + } + } + else //row + { + lines->Allocate(lines->EstimateSize(numColumns,numRows)); + for (j=0; jInsertNextCell(numColumns); + for (i=0; iXs[i]; + v = field->GetComponent(i,j); + if ( (this->Maxs[i]-this->Mins[i]) == 0.0 ) + { + x[1] = 0.5 * (this->YMax - this->YMin); + } + else + { + x[1] = this->YMin + + ((v - this->Mins[i]) / (this->Maxs[i] - this->Mins[i])) * + (this->YMax - this->YMin); + } + ptId = pts->InsertNextPoint(x); + lines->InsertCellPoint(ptId); + } + } + } + + pts->Delete(); + lines->Delete(); + + return 1; +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkParallelCoordinatesActor::ReleaseGraphicsResources(vtkWindow *win) +{ + this->TitleActor->ReleaseGraphicsResources(win); + for (int i=0; this->Axes && iN; i++) + { + this->Axes[i]->ReleaseGraphicsResources(win); + } +} + +//---------------------------------------------------------------------------- +void vtkParallelCoordinatesActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->TitleTextProperty) + { + os << indent << "Title Text Property:\n"; + this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Title Text Property: (none)\n"; + } + + if (this->LabelTextProperty) + { + os << indent << "Label Text Property:\n"; + this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Label Text Property: (none)\n"; + } + + os << indent << "Input: " << this->Input << "\n"; + os << indent << "Position2 Coordinate: " + << this->Position2Coordinate << "\n"; + this->Position2Coordinate->PrintSelf(os, indent.GetNextIndent()); + + os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n"; + os << indent << "Number Of Independent Variables: " << this->N << "\n"; + os << indent << "Independent Variables: "; + if ( this->IndependentVariables == VTK_IV_COLUMN ) + { + os << "Columns\n"; + } + else + { + os << "Rows\n"; + } + + os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n"; + + os << indent << "Label Format: " << this->LabelFormat << "\n"; +} diff --git a/Rendering/vtkParallelCoordinatesActor.h b/Rendering/vtkParallelCoordinatesActor.h new file mode 100644 index 0000000..ef19a52 --- /dev/null +++ b/Rendering/vtkParallelCoordinatesActor.h @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParallelCoordinatesActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkParallelCoordinatesActor - create parallel coordinate display from input field +// .SECTION Description +// vtkParallelCoordinatesActor generates a parallel coordinates plot from an +// input field (i.e., vtkDataObject). Parallel coordinates represent +// N-dimensional data by using a set of N parallel axes (not orthogonal like +// the usual x-y-z Cartesian axes). Each N-dimensional point is plotted as a +// polyline, were each of the N components of the point lie on one of the +// N axes, and the components are connected by straight lines. +// +// To use this class, you must specify an input data object. You'll probably +// also want to specify the position of the plot be setting the Position and +// Position2 instance variables, which define a rectangle in which the plot +// lies. Another important parameter is the IndependentVariables ivar, which +// tells the instance how to interpret the field data (independent variables +// as the rows or columns of the field). There are also many other instance +// variables that control the look of the plot includes its title, +// attributes, number of ticks on the axes, etc. +// +// Set the text property/attributes of the title and the labels through the +// vtkTextProperty objects associated to this actor. + +// .SECTION Caveats +// Field data is not necessarily "rectangular" in shape. In these cases, some +// of the data may not be plotted. +// +// The early implementation lacks many features that could be added in the +// future. +// This includes the ability to "brush" data (choose regions along an axis and +// highlight any points/lines passing through the region); efficiency is really +// bad; more control over the properties of the plot (separate properties for +// each axes,title,etc.; and using the labels found in the field to label each +// of the axes. +// +// .SECTION See Also +// vtkAxisActor3D can be used to create axes in world coordinate space. +// vtkActor2D vtkTextMapper vtkPolyDataMapper2D vtkScalarBarActor +// vtkCoordinate vtkTextProperty + +#ifndef __vtkParallelCoordinatesActor_h +#define __vtkParallelCoordinatesActor_h + +#include "vtkActor2D.h" + +class vtkAxisActor2D; +class vtkDataObject; +class vtkPolyData; +class vtkPolyDataMapper2D; +class vtkTextMapper; +class vtkTextProperty; + +#define VTK_IV_COLUMN 0 +#define VTK_IV_ROW 1 + +class VTK_RENDERING_EXPORT vtkParallelCoordinatesActor : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkParallelCoordinatesActor,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with autorange computation; + // the number of labels set to 5 for the x and y axes; + // a label format of "%-#6.3g"; and x coordinates computed from point + // ids. + static vtkParallelCoordinatesActor *New(); + + // Description: + // Specify whether to use the rows or columns as independent variables. + // If columns, then each row represents a separate point. If rows, then + // each column represents a separate point. + vtkSetClampMacro(IndependentVariables,int,VTK_IV_COLUMN, VTK_IV_ROW); + vtkGetMacro(IndependentVariables,int); + void SetIndependentVariablesToColumns() + {this->SetIndependentVariables(VTK_IV_COLUMN);}; + void SetIndependentVariablesToRows() + {this->SetIndependentVariables(VTK_IV_ROW);}; + + // Description: + // Set/Get the title of the parallel coordinates plot. + vtkSetStringMacro(Title); + vtkGetStringMacro(Title); + + // Description: + // Set/Get the number of annotation labels to show along each axis. + // This values is a suggestion: the number of labels may vary depending + // on the particulars of the data. + vtkSetClampMacro(NumberOfLabels, int, 0, 50); + vtkGetMacro(NumberOfLabels, int); + + // Description: + // Set/Get the format with which to print the labels on the axes. + vtkSetStringMacro(LabelFormat); + vtkGetStringMacro(LabelFormat); + + // Description: + // Set/Get the title text property. + virtual void SetTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the labels text property. + virtual void SetLabelTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(LabelTextProperty,vtkTextProperty); + + // Description: + // Draw the parallel coordinates plot. + int RenderOpaqueGeometry(vtkViewport*); + int RenderOverlay(vtkViewport*); + int RenderTranslucentGeometry(vtkViewport *) {return 0;} + + // Description: + // Set the input to the parallel coordinates actor. + virtual void SetInput(vtkDataObject*); + + // Description: + // Remove a dataset from the list of data to append. + vtkGetObjectMacro(Input,vtkDataObject); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + +protected: + vtkParallelCoordinatesActor(); + ~vtkParallelCoordinatesActor(); + +private: + vtkDataObject *Input; // List of data sets to plot + + int IndependentVariables; // Use column or row + vtkIdType N; // The number of independent variables + double *Mins; // Minimum data value along this row/column + double *Maxs; // Maximum data value along this row/column + int *Xs; // Axes x-values (in viewport coordinates) + int YMin; // Axes y-min-value (in viewport coordinates) + int YMax; // Axes y-max-value (in viewport coordinates) + int NumberOfLabels; // Along each axis + char *LabelFormat; + char *Title; + + vtkAxisActor2D **Axes; + vtkTextMapper *TitleMapper; + vtkActor2D *TitleActor; + + vtkTextProperty *TitleTextProperty; + vtkTextProperty *LabelTextProperty; + + vtkPolyData *PlotData; // The lines drawn within the axes + vtkPolyDataMapper2D *PlotMapper; + vtkActor2D *PlotActor; + + vtkTimeStamp BuildTime; + + int LastPosition[2]; + int LastPosition2[2]; + + void Initialize(); + int PlaceAxes(vtkViewport *viewport, int *size); + +private: + vtkParallelCoordinatesActor(const vtkParallelCoordinatesActor&); // Not implemented. + void operator=(const vtkParallelCoordinatesActor&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkPicker.cxx b/Rendering/vtkPicker.cxx new file mode 100644 index 0000000..cd4e6aa --- /dev/null +++ b/Rendering/vtkPicker.cxx @@ -0,0 +1,542 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPicker.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPicker.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkImageData.h" +#include "vtkLODProp3D.h" +#include "vtkMapper.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkProp3DCollection.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkVertex.h" +#include "vtkVolume.h" +#include "vtkAbstractVolumeMapper.h" +#include "vtkBox.h" +#include "vtkImageActor.h" + +vtkCxxRevisionMacro(vtkPicker, "$Revision: 1.93 $"); +vtkStandardNewMacro(vtkPicker); + +// Construct object with initial tolerance of 1/40th of window. There are no +// pick methods and picking is performed from the renderer's actors. +vtkPicker::vtkPicker() +{ + this->Tolerance = 0.025; // 1/40th of the renderer window + + this->MapperPosition[0] = 0.0; + this->MapperPosition[1] = 0.0; + this->MapperPosition[2] = 0.0; + + this->Mapper = NULL; + this->DataSet = NULL; + this->GlobalTMin = VTK_DOUBLE_MAX; + this->Actors = vtkActorCollection::New(); + this->Prop3Ds = vtkProp3DCollection::New(); + this->PickedPositions = vtkPoints::New(); + this->Transform = vtkTransform::New(); +} + +vtkPicker::~vtkPicker() +{ + this->Actors->Delete(); + this->Prop3Ds->Delete(); + this->PickedPositions->Delete(); + this->Transform->Delete(); +} + +// Update state when prop3D is picked. +void vtkPicker::MarkPicked(vtkAssemblyPath *path, vtkProp3D *prop3D, + vtkAbstractMapper3D *m, + double tMin, double mapperPos[3]) +{ + int i; + vtkMapper *mapper; + vtkAbstractVolumeMapper *volumeMapper; + + this->SetPath(path); + this->GlobalTMin = tMin; + + for (i=0; i < 3; i++) + { + this->MapperPosition[i] = mapperPos[i]; + } + if ( (mapper=vtkMapper::SafeDownCast(m)) != NULL ) + { + this->DataSet = mapper->GetInput(); + this->Mapper = mapper; + } + else if ( (volumeMapper=vtkAbstractVolumeMapper::SafeDownCast(m)) != NULL ) + { + this->DataSet = volumeMapper->GetDataSetInput(); + this->Mapper = volumeMapper; } + else + { + this->DataSet = NULL; + } + + // The point has to be transformed back into world coordinates. + // Note: it is assumed that the transform is in the correct state. + this->Transform->TransformPoint(mapperPos,this->PickPosition); + + // Invoke pick method if one defined - actor goes first + prop3D->Pick(); + this->InvokeEvent(vtkCommand::PickEvent,NULL); + +} + +// Perform pick operation with selection point provided. Normally the +// first two values for the selection point are x-y pixel coordinate, and +// the third value is =0. Return non-zero if something was successfully picked. +int vtkPicker::Pick(double selectionX, double selectionY, double selectionZ, + vtkRenderer *renderer) +{ + int i; + vtkProp *prop; + vtkCamera *camera; + vtkAbstractMapper3D *mapper = NULL; + double p1World[4], p2World[4], p1Mapper[4], p2Mapper[4]; + int picked=0; + int *winSize; + double x, y, t; + double *viewport; + double cameraPos[4], cameraFP[4]; + double *displayCoords, *worldCoords; + double *clipRange; + double ray[3], rayLength; + int pickable; + int LODId; + double windowLowerLeft[4], windowUpperRight[4]; + double bounds[6], tol; + double tF, tB; + double hitPosition[3]; + double cameraDOP[3]; + + // Initialize picking process + this->Initialize(); + this->Renderer = renderer; + this->SelectionPoint[0] = selectionX; + this->SelectionPoint[1] = selectionY; + this->SelectionPoint[2] = selectionZ; + + // Invoke start pick method if defined + this->InvokeEvent(vtkCommand::StartPickEvent,NULL); + + if ( renderer == NULL ) + { + vtkErrorMacro(<<"Must specify renderer!"); + return 0; + } + + // Get camera focal point and position. Convert to display (screen) + // coordinates. We need a depth value for z-buffer. + // + camera = renderer->GetActiveCamera(); + camera->GetPosition((double *)cameraPos); cameraPos[3] = 1.0; + camera->GetFocalPoint((double *)cameraFP); cameraFP[3] = 1.0; + + renderer->SetWorldPoint(cameraFP[0],cameraFP[1],cameraFP[2],cameraFP[3]); + renderer->WorldToDisplay(); + displayCoords = renderer->GetDisplayPoint(); + selectionZ = displayCoords[2]; + + // Convert the selection point into world coordinates. + // + renderer->SetDisplayPoint(selectionX, selectionY, selectionZ); + renderer->DisplayToWorld(); + worldCoords = renderer->GetWorldPoint(); + if ( worldCoords[3] == 0.0 ) + { + vtkErrorMacro(<<"Bad homogeneous coordinates"); + return 0; + } + for (i=0; i < 3; i++) + { + this->PickPosition[i] = worldCoords[i] / worldCoords[3]; + } + + // Compute the ray endpoints. The ray is along the line running from + // the camera position to the selection point, starting where this line + // intersects the front clipping plane, and terminating where this + // line intersects the back clipping plane. + for (i=0; i<3; i++) + { + ray[i] = this->PickPosition[i] - cameraPos[i]; + } + for (i=0; i<3; i++) + { + cameraDOP[i] = cameraFP[i] - cameraPos[i]; + } + + vtkMath::Normalize(cameraDOP); + + if (( rayLength = vtkMath::Dot(cameraDOP,ray)) == 0.0 ) + { + vtkWarningMacro("Cannot process points"); + return 0; + } + + clipRange = camera->GetClippingRange(); + + if ( camera->GetParallelProjection() ) + { + tF = clipRange[0] - rayLength; + tB = clipRange[1] - rayLength; + for (i=0; i<3; i++) + { + p1World[i] = this->PickPosition[i] + tF*cameraDOP[i]; + p2World[i] = this->PickPosition[i] + tB*cameraDOP[i]; + } + } + else + { + tF = clipRange[0] / rayLength; + tB = clipRange[1] / rayLength; + for (i=0; i<3; i++) + { + p1World[i] = cameraPos[i] + tF*ray[i]; + p2World[i] = cameraPos[i] + tB*ray[i]; + } + } + p1World[3] = p2World[3] = 1.0; + + // Compute the tolerance in world coordinates. Do this by + // determining the world coordinates of the diagonal points of the + // window, computing the width of the window in world coordinates, and + // multiplying by the tolerance. + // + viewport = renderer->GetViewport(); + winSize = renderer->GetRenderWindow()->GetSize(); + x = winSize[0] * viewport[0]; + y = winSize[1] * viewport[1]; + renderer->SetDisplayPoint(x, y, selectionZ); + renderer->DisplayToWorld(); + renderer->GetWorldPoint(windowLowerLeft); + + x = winSize[0] * viewport[2]; + y = winSize[1] * viewport[3]; + renderer->SetDisplayPoint(x, y, selectionZ); + renderer->DisplayToWorld(); + renderer->GetWorldPoint(windowUpperRight); + + for (tol=0.0,i=0; i<3; i++) + { + tol += (windowUpperRight[i] - windowLowerLeft[i]) * + (windowUpperRight[i] - windowLowerLeft[i]); + } + + tol = sqrt (tol) * this->Tolerance; + + // Loop over all props. Transform ray (defined from position of + // camera to selection point) into coordinates of mapper (not + // transformed to actors coordinates! Reduces overall computation!!!). + // Note that only vtkProp3D's can be picked by vtkPicker. + // + vtkPropCollection *props; + vtkProp *propCandidate; + if ( this->PickFromList ) + { + props = this->GetPickList(); + } + else + { + props = renderer->GetViewProps(); + } + + vtkActor *actor; + vtkLODProp3D *prop3D; + vtkVolume *volume; + vtkImageActor *imageActor = 0; + vtkAssemblyPath *path; + vtkProperty *tempProperty; + this->Transform->PostMultiply(); + vtkCollectionSimpleIterator pit; + double scale[3]; + for ( props->InitTraversal(pit); (prop=props->GetNextProp(pit)); ) + { + for ( prop->InitPathTraversal(); (path=prop->GetNextPath()); ) + { + pickable = 0; + actor = NULL; + propCandidate = path->GetLastNode()->GetViewProp(); + if ( propCandidate->GetPickable() && propCandidate->GetVisibility() ) + { + pickable = 1; + if ( (actor=vtkActor::SafeDownCast(propCandidate)) != NULL ) + { + mapper = actor->GetMapper(); + if ( actor->GetProperty()->GetOpacity() <= 0.0 ) + { + pickable = 0; + } + } + else if ( (prop3D=vtkLODProp3D::SafeDownCast(propCandidate)) != NULL ) + { + LODId = prop3D->GetPickLODID(); + mapper = prop3D->GetLODMapper(LODId); + + // if the mapper is a vtkMapper (as opposed to a vtkVolumeMapper), + // then check the transparency to see if the object is pickable + if ( vtkMapper::SafeDownCast(mapper) != NULL) + { + prop3D->GetLODProperty(LODId, &tempProperty); + if ( tempProperty->GetOpacity() <= 0.0 ) + { + pickable = 0; + } + } + } + else if ( (volume=vtkVolume::SafeDownCast(propCandidate)) != NULL ) + { + mapper = volume->GetMapper(); + } + else if ( (imageActor=vtkImageActor::SafeDownCast(propCandidate)) ) + { + mapper = 0; + } + else + { + pickable = 0; //only vtkProp3D's (actors and volumes) can be picked + } + } + + // If actor can be picked, get its composite matrix, invert it, and + // use the inverted matrix to transform the ray points into mapper + // coordinates. + if ( pickable && mapper != NULL ) + { + vtkMatrix4x4 *LastMatrix = path->GetLastNode()->GetMatrix(); + if (LastMatrix == NULL) + { + vtkErrorMacro (<< "Pick: Null matrix."); + return 0; + } + this->Transform->SetMatrix(LastMatrix); + this->Transform->Push(); + this->Transform->Inverse(); + this->Transform->GetScale(scale); //need to scale the tolerance + + this->Transform->TransformPoint(p1World,p1Mapper); + this->Transform->TransformPoint(p2World,p2Mapper); + + for (i=0; i<3; i++) + { + ray[i] = p2Mapper[i] - p1Mapper[i]; + } + + this->Transform->Pop(); + + // Have the ray endpoints in mapper space, now need to compare this + // with the mapper bounds to see whether intersection is possible. + // + // Get the bounding box of the modeller. Note that the tolerance is + // added to the bounding box to make sure things on the edge of the + // bounding box are picked correctly. + mapper->GetBounds(bounds); + bounds[0] -= tol; bounds[1] += tol; + bounds[2] -= tol; bounds[3] += tol; + bounds[4] -= tol; bounds[5] += tol; + if ( vtkBox::IntersectBox(bounds, (double *)p1Mapper, + ray, hitPosition, t) ) + { + t = this->IntersectWithLine((double *)p1Mapper, (double *)p2Mapper, + tol*0.333*(scale[0]+scale[1]+scale[2]), path, + (vtkProp3D *)propCandidate, mapper); + if ( t < VTK_DOUBLE_MAX ) + { + picked = 1; + if ( ! this->Prop3Ds->IsItemPresent(prop) ) + { + this->Prop3Ds->AddItem((vtkProp3D *)prop); + } + this->PickedPositions->InsertNextPoint + ((1.0 - t)*p1World[0] + t*p2World[0], + (1.0 - t)*p1World[1] + t*p2World[1], + (1.0 - t)*p1World[2] + t*p2World[2]); + + // backwards compatibility: also add to this->Actors + if (actor) + { + this->Actors->AddItem(actor); + } + } + } + } + else if ( pickable && imageActor ) + { // special case for imageActor, which has no mapper + vtkMatrix4x4 *LastMatrix = path->GetLastNode()->GetMatrix(); + if (LastMatrix == NULL) + { + vtkErrorMacro (<< "Pick: Null matrix."); + return 0; + } + this->Transform->SetMatrix(LastMatrix); + this->Transform->Push(); + this->Transform->Inverse(); + + this->Transform->TransformPoint(p1World,p1Mapper); + this->Transform->TransformPoint(p2World,p2Mapper); + + this->Transform->Pop(); + + // Have the ray endpoints in data space, now need to compare this + // with the displayed image bounds. + imageActor->GetDisplayBounds(bounds); + + t = VTK_DOUBLE_MAX; + + for (i = 0; i < 3; i++) + { + if (bounds[2*i] == bounds[2*i+1] && p2Mapper[i] != p1Mapper[i]) + { + t = (p2World[i] - bounds[2*i])/(p2Mapper[i] - p1Mapper[i]); + break; + } + } + + if (t < VTK_DOUBLE_MAX) + { + hitPosition[0] = (1.0 - t)*p1Mapper[0] + t*p2Mapper[0]; + hitPosition[1] = (1.0 - t)*p1Mapper[1] + t*p2Mapper[1]; + hitPosition[2] = (1.0 - t)*p1Mapper[2] + t*p2Mapper[2]; + if ((bounds[0] == bounds[1] || (hitPosition[0] >= bounds[0]-tol && + hitPosition[0] <= bounds[1]+tol)) && + (bounds[2] == bounds[3] || (hitPosition[1] >= bounds[2]-tol && + hitPosition[1] <= bounds[3]+tol)) && + (bounds[4] == bounds[5] || (hitPosition[2] >= bounds[4]-tol && + hitPosition[2] <= bounds[5]+tol))) + { + picked = 1; + + // the following code is handled in MarkPicked for other Prop3Ds + this->Mapper = mapper; // mapper is null + this->DataSet = imageActor->GetInput(); + this->MapperPosition[0] = hitPosition[0]; + this->MapperPosition[1] = hitPosition[1]; + this->MapperPosition[2] = hitPosition[2]; + this->Transform->TransformPoint(hitPosition,this->PickPosition); + imageActor->Pick(); + this->InvokeEvent(vtkCommand::PickEvent,NULL); + + this->Prop3Ds->AddItem(imageActor); + this->PickedPositions->InsertNextPoint + ((1.0 - t)*p1World[0] + t*p2World[0], + (1.0 - t)*p1World[1] + t*p2World[1], + (1.0 - t)*p1World[2] + t*p2World[2]); + } + } + }//if visible and pickable not transparent and has mapper + }//for all parts + }//for all actors + + // Invoke end pick method if defined + this->InvokeEvent(vtkCommand::EndPickEvent,NULL); + + return picked; +} + +// Intersect data with specified ray. +double vtkPicker::IntersectWithLine(double p1[3], double p2[3], + double vtkNotUsed(tol), + vtkAssemblyPath *path, + vtkProp3D *prop3D, + vtkAbstractMapper3D *mapper) +{ + int i; + double center[3], t, ray[3], rayFactor; + + // Get the data from the modeler + mapper->GetCenter(center); + + for (i=0; i<3; i++) + { + ray[i] = p2[i] - p1[i]; + } + if (( rayFactor = vtkMath::Dot(ray,ray)) == 0.0 ) + { + return 2.0; + } + + // Project the center point onto the ray and determine its parametric value + // + t = (ray[0]*(center[0]-p1[0]) + ray[1]*(center[1]-p1[1]) + + ray[2]*(center[2]-p1[2])) / rayFactor; + + if ( t >= 0.0 && t <= 1.0 && t < this->GlobalTMin ) + { + this->MarkPicked(path, prop3D, mapper, t, center); + } + return t; +} + +// Initialize the picking process. +void vtkPicker::Initialize() +{ + this->vtkAbstractPropPicker::Initialize(); + + this->Actors->RemoveAllItems(); + this->Prop3Ds->RemoveAllItems(); + this->PickedPositions->Reset(); + + this->MapperPosition[0] = 0.0; + this->MapperPosition[1] = 0.0; + this->MapperPosition[2] = 0.0; + + this->Mapper = NULL; + this->GlobalTMin = VTK_DOUBLE_MAX; +} + + +vtkActorCollection *vtkPicker::GetActors() +{ + if (this->Actors->GetNumberOfItems() != + this->PickedPositions->GetNumberOfPoints()) + { + vtkWarningMacro(<<"Not all Prop3Ds are actors, use GetProp3Ds instead"); + } + return this->Actors; +} + + +void vtkPicker::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->DataSet ) + { + os << indent << "DataSet: " << this->DataSet << "\n"; + } + else + { + os << indent << "DataSet: (none)"; + } + + os << indent << "Mapper: " << this->Mapper << "\n"; + + os << indent << "Tolerance: " << this->Tolerance << "\n"; + + os << indent << "Mapper Position: (" << this->MapperPosition[0] << "," + << this->MapperPosition[1] << "," + << this->MapperPosition[2] << ")\n"; +} diff --git a/Rendering/vtkPicker.h b/Rendering/vtkPicker.h new file mode 100644 index 0000000..c1d7011 --- /dev/null +++ b/Rendering/vtkPicker.h @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPicker.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPicker - superclass for 3D geometric pickers (uses ray cast) +// .SECTION Description +// vtkPicker is used to select instances of vtkProp3D by shooting a ray +// into a graphics window and intersecting with the actor's bounding box. +// The ray is defined from a point defined in window (or pixel) coordinates, +// and a point located from the camera's position. +// +// vtkPicker may return more than one vtkProp3D, since more than one bounding +// box may be intersected. vtkPicker returns the list of props that were hit, +// the pick coordinates in world and untransformed mapper space, and the +// prop (vtkProp3D) and mapper that are "closest" to the camera. The closest +// prop is the one whose center point (i.e., center of bounding box) +// projected on the ray is closest to the camera. + +// .SECTION See Also +// vtkPicker is used for quick geometric picking. If you desire to pick +// points or cells, use the subclass vtkPointPicker or vtkCellPicker, +// respectively. Or you may use hardware picking to pick any type of vtkProp +// - see vtkPropPicker or vtkWorldPointPicker. + +#ifndef __vtkPicker_h +#define __vtkPicker_h + +#include "vtkAbstractPropPicker.h" + +class vtkAbstractMapper3D; +class vtkDataSet; +class vtkTransform; +class vtkActorCollection; +class vtkProp3DCollection; +class vtkPoints; + +class VTK_RENDERING_EXPORT vtkPicker : public vtkAbstractPropPicker +{ +public: + static vtkPicker *New(); + vtkTypeRevisionMacro(vtkPicker,vtkAbstractPropPicker); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify tolerance for performing pick operation. Tolerance is specified + // as fraction of rendering window size. (Rendering window size is measured + // across diagonal.) + vtkSetMacro(Tolerance,double); + vtkGetMacro(Tolerance,double); + + // Description: + // Return position in mapper (i.e., non-transformed) coordinates of + // pick point. + vtkGetVectorMacro(MapperPosition,double,3); + + // Description: + // Return mapper that was picked (if any). + vtkGetObjectMacro(Mapper,vtkAbstractMapper3D); + + // Description: + // Get a pointer to the dataset that was picked (if any). If nothing + // was picked then NULL is returned. + vtkGetObjectMacro(DataSet,vtkDataSet); + + // Description: + // Return a collection of all the prop 3D's that were intersected + // by the pick ray. This collection is not sorted. + vtkProp3DCollection *GetProp3Ds() {return this->Prop3Ds;}; + + // Description: + // Return a collection of all the actors that were intersected. + // This collection is not sorted. (This is a convenience method + // to maintain backward compatibility.) + vtkActorCollection *GetActors(); + + // Description: + // Return a list of the points the the actors returned by GetActors + // were intersected at. The order of this list will match the order of + // GetActors. + vtkPoints *GetPickedPositions() {return this->PickedPositions;}; + + // Description: + // Perform pick operation with selection point provided. Normally the + // first two values for the selection point are x-y pixel coordinate, and + // the third value is =0. Return non-zero if something was successfully + // picked. + virtual int Pick(double selectionX, double selectionY, double selectionZ, + vtkRenderer *renderer); + + // Description: + // Perform pick operation with selection point provided. Normally the first + // two values for the selection point are x-y pixel coordinate, and the + // third value is =0. Return non-zero if something was successfully picked. + int Pick(double selectionPt[3], vtkRenderer *ren) + {return this->Pick(selectionPt[0], selectionPt[1], selectionPt[2], ren);}; + +protected: + vtkPicker(); + ~vtkPicker(); + + void MarkPicked(vtkAssemblyPath *path, vtkProp3D *p, vtkAbstractMapper3D *m, + double tMin, double mapperPos[3]); + virtual double IntersectWithLine(double p1[3], double p2[3], double tol, + vtkAssemblyPath *path, vtkProp3D *p, + vtkAbstractMapper3D *m); + virtual void Initialize(); + + double Tolerance; //tolerance for computation (% of window) + double MapperPosition[3]; //selection point in untransformed coordinates + + vtkAbstractMapper3D *Mapper; //selected mapper (if the prop has a mapper) + vtkDataSet *DataSet; //selected dataset (if there is one) + + double GlobalTMin; //parametric coordinate along pick ray where hit occured + vtkTransform *Transform; //use to perform ray transformation + vtkActorCollection *Actors; //candidate actors (based on bounding box) + vtkProp3DCollection *Prop3Ds; //candidate actors (based on bounding box) + vtkPoints *PickedPositions; // candidate positions + +private: + vtkPicker(const vtkPicker&); // Not implemented. + void operator=(const vtkPicker&); // Not implemented. +}; + + +#endif + + diff --git a/Rendering/vtkPointPicker.cxx b/Rendering/vtkPointPicker.cxx new file mode 100644 index 0000000..8b0b380 --- /dev/null +++ b/Rendering/vtkPointPicker.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointPicker.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointPicker.h" + +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkMapper.h" +#include "vtkAbstractVolumeMapper.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPointPicker, "$Revision: 1.34 $"); +vtkStandardNewMacro(vtkPointPicker); + +vtkPointPicker::vtkPointPicker() +{ + this->PointId = -1; +} + +double vtkPointPicker::IntersectWithLine(double p1[3], double p2[3], double tol, + vtkAssemblyPath *path, vtkProp3D *p, + vtkAbstractMapper3D *m) +{ + vtkIdType numPts; + vtkIdType ptId, minPtId; + int i; + double ray[3], rayFactor, tMin, x[3], t, projXYZ[3], minXYZ[3]; + vtkDataSet *input; + vtkMapper *mapper; + vtkAbstractVolumeMapper *volumeMapper; + + // Get the underlying dataset + // + if ( (mapper=vtkMapper::SafeDownCast(m)) != NULL ) + { + input = mapper->GetInput(); + } + else if ( (volumeMapper=vtkAbstractVolumeMapper::SafeDownCast(m)) != NULL ) + { + input = volumeMapper->GetDataSetInput(); + } + else + { + return 2.0; + } + + if ( (numPts = input->GetNumberOfPoints()) < 1 ) + { + return 2.0; + } + + // Determine appropriate info + // + for (i=0; i<3; i++) + { + ray[i] = p2[i] - p1[i]; + } + if (( rayFactor = vtkMath::Dot(ray,ray)) == 0.0 ) + { + vtkErrorMacro("Cannot process points"); + return 2.0; + } + + // Project each point onto ray. Keep track of the one within the + // tolerance and closest to the eye (and within the clipping range). + // + double dist, maxDist, minPtDist=VTK_DOUBLE_MAX; + for (minPtId=(-1),tMin=VTK_DOUBLE_MAX,ptId=0; ptIdGetPoint(ptId,x); + + t = (ray[0]*(x[0]-p1[0]) + ray[1]*(x[1]-p1[1]) + ray[2]*(x[2]-p1[2])) + / rayFactor; + + // If we find a point closer than we currently have, see whether it + // lies within the pick tolerance and clipping planes. We keep track + // of the point closest to the line (use a fudge factor for points + // nearly the same distance away.) + // + if ( t >= 0.0 && t <= 1.0 && t <= (tMin+this->Tolerance) ) + { + for(maxDist=0.0, i=0; i<3; i++) + { + projXYZ[i] = p1[i] + t*ray[i]; + dist = fabs(x[i]-projXYZ[i]); + if ( dist > maxDist ) + { + maxDist = dist; + } + } + if ( maxDist <= tol && maxDist < minPtDist ) // within tolerance + { + minPtId = ptId; + minXYZ[0]=x[0]; minXYZ[1]=x[1]; minXYZ[2]=x[2]; + minPtDist = maxDist; + tMin = t; + } + } + } + + // Now compare this against other actors. + // + if ( minPtId>(-1) && tMin < this->GlobalTMin ) + { + this->MarkPicked(path, p, m, tMin, minXYZ); + this->PointId = minPtId; + vtkDebugMacro("Picked point id= " << minPtId); + } + + return tMin; +} + +void vtkPointPicker::Initialize() +{ + this->PointId = (-1); + this->vtkPicker::Initialize(); +} + +void vtkPointPicker::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Point Id: " << this->PointId << "\n"; +} diff --git a/Rendering/vtkPointPicker.h b/Rendering/vtkPointPicker.h new file mode 100644 index 0000000..022f726 --- /dev/null +++ b/Rendering/vtkPointPicker.h @@ -0,0 +1,64 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointPicker.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointPicker - select a point by shooting a ray into a graphics window +// .SECTION Description + +// vtkPointPicker is used to select a point by shooting a ray into a graphics +// window and intersecting with actor's defining geometry - specifically its +// points. Beside returning coordinates, actor, and mapper, vtkPointPicker +// returns the id of the point projecting closest onto the ray (within the +// specified tolerance). Ties are broken (i.e., multiple points all +// projecting within the tolerance along the pick ray) by choosing the point +// closest to the ray. +// + +// .SECTION See Also +// vtkPicker vtkCellPicker. + +#ifndef __vtkPointPicker_h +#define __vtkPointPicker_h + +#include "vtkPicker.h" + +class VTK_RENDERING_EXPORT vtkPointPicker : public vtkPicker +{ +public: + static vtkPointPicker *New(); + vtkTypeRevisionMacro(vtkPointPicker,vtkPicker); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the id of the picked point. If PointId = -1, nothing was picked. + vtkGetMacro(PointId, vtkIdType); + +protected: + vtkPointPicker(); + ~vtkPointPicker() {}; + + vtkIdType PointId; //picked point + + double IntersectWithLine(double p1[3], double p2[3], double tol, + vtkAssemblyPath *path, vtkProp3D *p, + vtkAbstractMapper3D *m); + void Initialize(); + +private: + vtkPointPicker(const vtkPointPicker&); // Not implemented. + void operator=(const vtkPointPicker&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkPolyDataMapper.cxx b/Rendering/vtkPolyDataMapper.cxx new file mode 100644 index 0000000..a76f5e6 --- /dev/null +++ b/Rendering/vtkPolyDataMapper.cxx @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataMapper.h" + +#include "vtkExecutive.h" +#include "vtkGraphicsFactory.h" +#include "vtkInformation.h" +#include "vtkMath.h" +#include "vtkPolyData.h" +#include "vtkRenderWindow.h" + +vtkCxxRevisionMacro(vtkPolyDataMapper, "$Revision: 1.38 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkPolyDataMapper); + +//---------------------------------------------------------------------------- +// return the correct type of PolyDataMapper +vtkPolyDataMapper *vtkPolyDataMapper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkPolyDataMapper"); + return (vtkPolyDataMapper*)ret; +} + + +//---------------------------------------------------------------------------- +vtkPolyDataMapper::vtkPolyDataMapper() +{ + this->Piece = 0; + this->NumberOfPieces = 1; + this->NumberOfSubPieces = 1; + this->GhostLevel = 0; +} + +void vtkPolyDataMapper::Render(vtkRenderer *ren, vtkActor *act) +{ + if (this->Static) + { + this->RenderPiece(ren,act); + return; + } + + int currentPiece, nPieces; + vtkPolyData *input = this->GetInput(); + + if (input == NULL) + { + vtkErrorMacro("Mapper has no input."); + return; + } + + nPieces = this->NumberOfPieces * this->NumberOfSubPieces; + + for(int i=0; iNumberOfSubPieces; i++) + { + // If more than one pieces, render in loop. + currentPiece = this->NumberOfSubPieces * this->Piece + i; + input->SetUpdateExtent(currentPiece, nPieces, this->GhostLevel); + this->RenderPiece(ren, act); + } +} + +//---------------------------------------------------------------------------- +void vtkPolyDataMapper::SetInput(vtkPolyData *input) +{ + if(input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(0, 0); + } +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkPolyData *vtkPolyDataMapper::GetInput() +{ + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +// Update the network connected to this mapper. +void vtkPolyDataMapper::Update() +{ + if (this->Static) + { + return; + } + + int currentPiece, nPieces = this->NumberOfPieces; + vtkPolyData* input = this->GetInput(); + + // If the estimated pipeline memory usage is larger than + // the memory limit, break the current piece into sub-pieces. + if (input) + { + currentPiece = this->NumberOfSubPieces * this->Piece; + input->SetUpdateExtent(currentPiece, this->NumberOfSubPieces*nPieces, + this->GhostLevel); + } + + this->vtkMapper::Update(); +} + +// Get the bounds for the input of this mapper as +// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkPolyDataMapper::GetBounds() +{ + static double bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0}; + + // do we have an input + if ( ! this->GetNumberOfInputConnections(0)) + { + return bounds; + } + else + { + if (!this->Static) + { + this->Update(); + this->GetInput()->GetBounds(this->Bounds); + } + // if the bounds indicate NAN and subpieces are being used then + // return NULL + if (!vtkMath::AreBoundsInitialized(this->Bounds) + && this->NumberOfSubPieces > 1) + { + return NULL; + } + return this->Bounds; + } +} + +void vtkPolyDataMapper::ShallowCopy(vtkAbstractMapper *mapper) +{ + vtkPolyDataMapper *m = vtkPolyDataMapper::SafeDownCast(mapper); + if ( m != NULL ) + { + this->SetInput(m->GetInput()); + this->SetGhostLevel(m->GetGhostLevel()); + this->SetNumberOfPieces(m->GetNumberOfPieces()); + this->SetNumberOfSubPieces(m->GetNumberOfSubPieces()); + } + + // Now do superclass + this->vtkMapper::ShallowCopy(mapper); +} + +void vtkPolyDataMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Piece : " << this->Piece << endl; + os << indent << "NumberOfPieces : " << this->NumberOfPieces << endl; + os << indent << "GhostLevel: " << this->GhostLevel << endl; + os << indent << "Number of sub pieces: " << this->NumberOfSubPieces + << endl; +} + +//---------------------------------------------------------------------------- +int vtkPolyDataMapper::FillInputPortInformation( + int vtkNotUsed( port ), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} diff --git a/Rendering/vtkPolyDataMapper.h b/Rendering/vtkPolyDataMapper.h new file mode 100644 index 0000000..b622abf --- /dev/null +++ b/Rendering/vtkPolyDataMapper.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataMapper - map vtkPolyData to graphics primitives +// .SECTION Description +// vtkPolyDataMapper is a class that maps polygonal data (i.e., vtkPolyData) +// to graphics primitives. vtkPolyDataMapper serves as a superclass for +// device-specific poly data mappers, that actually do the mapping to the +// rendering/graphics hardware/software. +// It is now possible to set a memory limit for the pipeline in the mapper. +// If the total estimated memory usage of the pipeline is larger than +// this limit, the mapper will divide the data into pieces and render +// each in a for loop. + +#ifndef __vtkPolyDataMapper_h +#define __vtkPolyDataMapper_h + +#include "vtkMapper.h" + +class vtkPolyData; +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkPolyDataMapper : public vtkMapper +{ +public: + static vtkPolyDataMapper *New(); + vtkTypeRevisionMacro(vtkPolyDataMapper,vtkMapper); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implemented by sub classes. Actual rendering is done here. + virtual void RenderPiece(vtkRenderer *ren, vtkActor *act) = 0; + + // Description: + // This calls RenderPiece (in a for loop is streaming is necessary). + virtual void Render(vtkRenderer *ren, vtkActor *act); + + // Description: + // Specify the input data to map. + void SetInput(vtkPolyData *in); + vtkPolyData *GetInput(); + + // Description: + // Update that sets the update piece first. + void Update(); + + // Description: + // If you want only a part of the data, specify by setting the piece. + vtkSetMacro(Piece, int); + vtkGetMacro(Piece, int); + vtkSetMacro(NumberOfPieces, int); + vtkGetMacro(NumberOfPieces, int); + vtkSetMacro(NumberOfSubPieces, int); + vtkGetMacro(NumberOfSubPieces, int); + + // Description: + // Set the number of ghost cells to return. + vtkSetMacro(GhostLevel, int); + vtkGetMacro(GhostLevel, int); + + // Description: + // Return bounding box (array of six doubles) of data expressed as + // (xmin,xmax, ymin,ymax, zmin,zmax). + virtual double *GetBounds(); + virtual void GetBounds(double bounds[6]) + {this->Superclass::GetBounds(bounds);}; + + // Description: + // Make a shallow copy of this mapper. + void ShallowCopy(vtkAbstractMapper *m); + +protected: + vtkPolyDataMapper(); + ~vtkPolyDataMapper() {}; + + int Piece; + int NumberOfPieces; + int NumberOfSubPieces; + int GhostLevel; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkPolyDataMapper(const vtkPolyDataMapper&); // Not implemented. + void operator=(const vtkPolyDataMapper&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkPolyDataMapper2D.cxx b/Rendering/vtkPolyDataMapper2D.cxx new file mode 100644 index 0000000..3248a48 --- /dev/null +++ b/Rendering/vtkPolyDataMapper2D.cxx @@ -0,0 +1,340 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataMapper2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPolyDataMapper2D.h" + +#include "vtkCoordinate.h" +#include "vtkExecutive.h" +#include "vtkImagingFactory.h" +#include "vtkLookupTable.h" +#include "vtkPolyData.h" + +vtkCxxRevisionMacro(vtkPolyDataMapper2D, "$Revision: 1.43 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkPolyDataMapper2D); +//---------------------------------------------------------------------------- + +vtkCxxSetObjectMacro(vtkPolyDataMapper2D,TransformCoordinate,vtkCoordinate); + +vtkPolyDataMapper2D::vtkPolyDataMapper2D() +{ + this->Colors = NULL; + + this->LookupTable = NULL; + + this->ScalarVisibility = 1; + this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0; + this->UseLookupTableScalarRange = 0; + + this->ColorMode = VTK_COLOR_MODE_DEFAULT; + this->ScalarMode = VTK_SCALAR_MODE_DEFAULT; + + this->TransformCoordinate = NULL; + + strcpy(this->ArrayName, ""); + this->ArrayId = -1; + this->ArrayComponent = 0; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +void vtkPolyDataMapper2D::ShallowCopy(vtkAbstractMapper *mapper) +{ + vtkPolyDataMapper2D *m = vtkPolyDataMapper2D::SafeDownCast(mapper); + if ( m != NULL ) + { + this->SetLookupTable(m->GetLookupTable()); + this->SetScalarVisibility(m->GetScalarVisibility()); + this->SetScalarRange(m->GetScalarRange()); + this->SetColorMode(m->GetColorMode()); + this->SetScalarMode(m->GetScalarMode()); + this->SetUseLookupTableScalarRange(m->GetUseLookupTableScalarRange()); + this->ColorByArrayComponent(m->GetArrayName(),m->GetArrayComponent()); + this->ColorByArrayComponent(m->GetArrayId(),m->GetArrayComponent()); + this->SetTransformCoordinate(m->GetTransformCoordinate()); + } + + // Now do superclass + this->vtkMapper2D::ShallowCopy(mapper); + +} + +vtkPolyDataMapper2D::~vtkPolyDataMapper2D() +{ + if (this->TransformCoordinate) + { + this->TransformCoordinate->UnRegister(this); + } + if (this->LookupTable) + { + this->LookupTable->UnRegister(this); + } + if ( this->Colors != NULL ) + { + this->Colors->UnRegister(this); + } +} + +//---------------------------------------------------------------------------- +void vtkPolyDataMapper2D::SetInput(vtkPolyData *input) +{ + if(input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(0, 0); + } +} + +//---------------------------------------------------------------------------- +// Specify the input data or filter. +vtkPolyData *vtkPolyDataMapper2D::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkPolyData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + +vtkPolyDataMapper2D *vtkPolyDataMapper2D::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkImagingFactory::CreateInstance("vtkPolyDataMapper2D"); + return (vtkPolyDataMapper2D*)ret; +} + + +// Overload standard modified time function. If lookup table is modified, +// then this object is modified as well. +unsigned long vtkPolyDataMapper2D::GetMTime() +{ + unsigned long mTime = this->MTime; + unsigned long lutMTime; + + if ( this->LookupTable != NULL ) + { + lutMTime = this->LookupTable->GetMTime(); + mTime = ( lutMTime > mTime ? lutMTime : mTime ); + } + + return mTime; +} + +// a side effect of this is that this->Colors is also set +// to the return value +vtkUnsignedCharArray *vtkPolyDataMapper2D::MapScalars(double alpha) +{ + // Since we are not supporting the texture color option in this mapper, + // the cell flag does nothing. + int cellFlag = 0; + + // Get rid of old colors + if ( this->Colors ) + { + this->Colors->UnRegister(this); + this->Colors = NULL; + } + + // map scalars if necessary + if ( this->ScalarVisibility ) + { + vtkDataArray *scalars = vtkAbstractMapper:: + GetScalars(this->GetInput(), this->ScalarMode, this->ArrayAccessMode, + this->ArrayId, this->ArrayName, cellFlag); + // This is for a legacy feature: selection of the array component to color by + // from the mapper. It is now in the lookuptable. When this feature + // is removed, we can remove this condition. + if (scalars == NULL || scalars->GetNumberOfComponents() <= this->ArrayComponent) + { + this->ArrayComponent = 0; + } + + if ( scalars ) + { + if ( scalars->GetLookupTable() ) + { + this->SetLookupTable(scalars->GetLookupTable()); + } + else + { + // make sure we have a lookup table + if ( this->LookupTable == NULL ) + { + this->CreateDefaultLookupTable(); + } + this->LookupTable->Build(); + } + if ( !this->UseLookupTableScalarRange ) + { + this->LookupTable->SetRange(this->ScalarRange); + } + this->LookupTable->SetAlpha(alpha); + // Map Scalar constructs a array and returns it. + // Not having "New" or "Make" in the name breaks VTK conventions but, ... + this->Colors = this->LookupTable-> + MapScalars(scalars, this->ColorMode, this->ArrayComponent); + this->Colors->Register(this); + this->Colors->Delete(); + } + } + + return this->Colors; +} + +void vtkPolyDataMapper2D::ColorByArrayComponent(int arrayNum, int component) +{ + if (this->ArrayId == arrayNum && component == this->ArrayComponent && + this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + return; + } + this->Modified(); + + this->ArrayId = arrayNum; + this->ArrayComponent = component; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +void vtkPolyDataMapper2D::ColorByArrayComponent(char* arrayName, int component) +{ + if (strcmp(this->ArrayName, arrayName) == 0 && + component == this->ArrayComponent && + this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + return; + } + this->Modified(); + + strcpy(this->ArrayName, arrayName); + this->ArrayComponent = component; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME; +} + +// Specify a lookup table for the mapper to use. +void vtkPolyDataMapper2D::SetLookupTable(vtkScalarsToColors *lut) +{ + if ( this->LookupTable != lut ) + { + if (lut) + { + lut->Register(this); + } + if ( this->LookupTable ) + { + this->LookupTable->UnRegister(this); + } + this->LookupTable = lut; + this->Modified(); + } +} + +vtkScalarsToColors *vtkPolyDataMapper2D::GetLookupTable() +{ + if ( this->LookupTable == NULL ) + { + this->CreateDefaultLookupTable(); + } + return this->LookupTable; +} + +void vtkPolyDataMapper2D::CreateDefaultLookupTable() +{ + if ( this->LookupTable ) + { + this->LookupTable->UnRegister(this); + } + this->LookupTable = vtkLookupTable::New(); + this->LookupTable->Register(this); + this->LookupTable->Delete(); +} + +// Return the method of coloring scalar data. +const char *vtkPolyDataMapper2D::GetColorModeAsString(void) +{ + if ( this->ColorMode == VTK_COLOR_MODE_MAP_SCALARS ) + { + return "MapScalars"; + } + else + { + return "Default"; + } +} + +void vtkPolyDataMapper2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->LookupTable ) + { + os << indent << "Lookup Table:\n"; + this->LookupTable->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Lookup Table: (none)\n"; + } + + os << indent << "Scalar Visibility: " + << (this->ScalarVisibility ? "On\n" : "Off\n"); + + os << indent << "Scalar Mode: "; + switch ( this->ScalarMode ) + { + case VTK_SCALAR_MODE_DEFAULT: + os << "Default" << endl; + break; + case VTK_SCALAR_MODE_USE_POINT_DATA: + os << "Use point data" << endl; + break; + case VTK_SCALAR_MODE_USE_CELL_DATA: + os << "Use cell data" << endl; + break; + case VTK_SCALAR_MODE_USE_POINT_FIELD_DATA: + os << "Use point field data" << endl; + break; + case VTK_SCALAR_MODE_USE_CELL_FIELD_DATA: + os << "Use cell field data" << endl; + break; + } + + double *range = this->GetScalarRange(); + os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n"; + os << indent << "UseLookupTableScalarRange: " << this->UseLookupTableScalarRange << "\n"; + + os << indent << "Color Mode: " << this->GetColorModeAsString() << endl; + + if ( this->TransformCoordinate ) + { + os << indent << "Transform Coordinate: " + << this->TransformCoordinate << "\n"; + this->TransformCoordinate->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << indent << "No Transform Coordinate\n"; + } +} + +void vtkPolyDataMapper2D::SetColorModeToDefault() +{this->SetColorMode(VTK_COLOR_MODE_DEFAULT);}; + +void vtkPolyDataMapper2D::SetColorModeToMapScalars() +{this->SetColorMode(VTK_COLOR_MODE_MAP_SCALARS);}; diff --git a/Rendering/vtkPolyDataMapper2D.h b/Rendering/vtkPolyDataMapper2D.h new file mode 100644 index 0000000..5001e2f --- /dev/null +++ b/Rendering/vtkPolyDataMapper2D.h @@ -0,0 +1,192 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataMapper2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataMapper2D - draw vtkPolyData onto the image plane +// .SECTION Description +// vtkPolyDataMapper2D is a mapper that renders 3D polygonal data +// (vtkPolyData) onto the 2D image plane (i.e., the renderer's viewport). +// By default, the 3D data is transformed into 2D data by ignoring the +// z-coordinate of the 3D points in vtkPolyData, and taking the x-y values +// as local display values (i.e., pixel coordinates). Alternatively, you +// can provide a vtkCoordinate object that will transform the data into +// local display coordinates (use the vtkCoordinate::SetCoordinateSystem() +// methods to indicate which coordinate system you are transforming the +// data from). + +// .SECTION See Also +// vtkMapper2D vtkActor2D + +#ifndef __vtkPolyDataMapper2D_h +#define __vtkPolyDataMapper2D_h + + +#include "vtkMapper2D.h" + +class vtkCoordinate; +class vtkPolyData; +class vtkScalarsToColors; +class vtkUnsignedCharArray; + +class VTK_RENDERING_EXPORT vtkPolyDataMapper2D : public vtkMapper2D +{ +public: + vtkTypeRevisionMacro(vtkPolyDataMapper2D,vtkMapper2D); + static vtkPolyDataMapper2D *New(); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the input to the mapper. + void SetInput(vtkPolyData *in); + vtkPolyData *GetInput(); + + // Description: + // Specify a lookup table for the mapper to use. + void SetLookupTable(vtkScalarsToColors *lut); + vtkScalarsToColors *GetLookupTable(); + + // Description: + // Create default lookup table. Generally used to create one when none + // is available with the scalar data. + virtual void CreateDefaultLookupTable(); + + // Description: + // Turn on/off flag to control whether scalar data is used to color objects. + vtkSetMacro(ScalarVisibility,int); + vtkGetMacro(ScalarVisibility,int); + vtkBooleanMacro(ScalarVisibility,int); + + // Description: + // Control how the scalar data is mapped to colors. By default + // (ColorModeToDefault), unsigned char scalars are treated as colors, and + // NOT mapped through the lookup table, while everything else is. Setting + // ColorModeToMapScalars means that all scalar data will be mapped through + // the lookup table. (Note that for multi-component scalars, the + // particular component to use for mapping can be specified using the + // ColorByArrayComponent() method.) + vtkSetMacro(ColorMode,int); + vtkGetMacro(ColorMode,int); + void SetColorModeToDefault(); + void SetColorModeToMapScalars(); + + // Description: + // Return the method of coloring scalar data. + const char *GetColorModeAsString(); + + // Description: + // Control whether the mapper sets the lookuptable range based on its + // own ScalarRange, or whether it will use the LookupTable ScalarRange + // regardless of it's own setting. By default the Mapper is allowed to set + // the LookupTable range, but users who are sharing LookupTables between + // mappers/actors will probably wish to force the mapper to use the + // LookupTable unchanged. + vtkSetMacro(UseLookupTableScalarRange,int); + vtkGetMacro(UseLookupTableScalarRange,int); + vtkBooleanMacro(UseLookupTableScalarRange,int); + + // Description: + // Specify range in terms of scalar minimum and maximum (smin,smax). These + // values are used to map scalars into lookup table. Has no effect when + // UseLookupTableScalarRange is true. + vtkSetVector2Macro(ScalarRange,double); + vtkGetVectorMacro(ScalarRange,double,2); + + // Description: + // Control how the filter works with scalar point data and cell attribute + // data. By default (ScalarModeToDefault), the filter will use point data, + // and if no point data is available, then cell data is used. Alternatively + // you can explicitly set the filter to use point data + // (ScalarModeToUsePointData) or cell data (ScalarModeToUseCellData). + // You can also choose to get the scalars from an array in point field + // data (ScalarModeToUsePointFieldData) or cell field data + // (ScalarModeToUseCellFieldData). If scalars are coming from a field + // data array, you must call ColorByArrayComponent before you call + // GetColors. + vtkSetMacro(ScalarMode,int); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToDefault() { + this->SetScalarMode(VTK_SCALAR_MODE_DEFAULT);}; + void SetScalarModeToUsePointData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA);}; + void SetScalarModeToUseCellData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_DATA);}; + void SetScalarModeToUsePointFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA);}; + void SetScalarModeToUseCellFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA);}; + + // Description: + // Choose which component of which field data array to color by. + void ColorByArrayComponent(int arrayNum, int component); + void ColorByArrayComponent(char* arrayName, int component); + + // Description: + // Get the array name or number and component to color by. + char* GetArrayName() { return this->ArrayName; } + int GetArrayId() { return this->ArrayId; } + int GetArrayAccessMode() { return this->ArrayAccessMode; } + int GetArrayComponent() { return this->ArrayComponent; } + + // Description: + // Overload standard modified time function. If lookup table is modified, + // then this object is modified as well. + virtual unsigned long GetMTime(); + + // Description: + // Specify a vtkCoordinate object to be used to transform the vtkPolyData + // point coordinates. By default (no vtkCoordinate specified), the point + // coordinates are taken as local display coordinates. + virtual void SetTransformCoordinate(vtkCoordinate*); + vtkGetObjectMacro(TransformCoordinate, vtkCoordinate); + + // Description: + // Map the scalars (if there are any scalars and ScalarVisibility is on) + // through the lookup table, returning an unsigned char RGBA array. This is + // typically done as part of the rendering process. The alpha parameter + // allows the blending of the scalars with an additional alpha (typically + // which comes from a vtkActor, etc.) + vtkUnsignedCharArray *MapScalars(double alpha); + + // Description: + // Make a shallow copy of this mapper. + void ShallowCopy(vtkAbstractMapper *m); + +protected: + vtkPolyDataMapper2D(); + ~vtkPolyDataMapper2D(); + + vtkUnsignedCharArray *Colors; + + vtkScalarsToColors *LookupTable; + int ScalarVisibility; + vtkTimeStamp BuildTime; + double ScalarRange[2]; + int UseLookupTableScalarRange; + int ColorMode; + int ScalarMode; + + vtkCoordinate *TransformCoordinate; + + // for coloring by a component of a field data array + int ArrayId; + char ArrayName[256]; + int ArrayComponent; + int ArrayAccessMode; +private: + vtkPolyDataMapper2D(const vtkPolyDataMapper2D&); // Not implemented. + void operator=(const vtkPolyDataMapper2D&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkProp3D.cxx b/Rendering/vtkProp3D.cxx new file mode 100644 index 0000000..df3e7b1 --- /dev/null +++ b/Rendering/vtkProp3D.cxx @@ -0,0 +1,622 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProp3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProp3D.h" + +#include "vtkActor.h" +#include "vtkAssemblyPaths.h" +#include "vtkMath.h" +#include "vtkMatrixToLinearTransform.h" +#include "vtkTransform.h" + +#include + +typedef double (*SqMatPtr)[4]; + +vtkCxxRevisionMacro(vtkProp3D, "$Revision: 1.36 $"); + +// Construct with the following defaults: origin(0,0,0) +// position=(0,0,0) and orientation=(0,0,0). No user defined +// matrix and no texture map. +vtkProp3D::vtkProp3D() +{ + this->Origin[0] = 0.0; + this->Origin[1] = 0.0; + this->Origin[2] = 0.0; + + this->Position[0] = 0.0; + this->Position[1] = 0.0; + this->Position[2] = 0.0; + + this->Orientation[0] = 0.0; + this->Orientation[1] = 0.0; + this->Orientation[2] = 0.0; + + this->Scale[0] = 1.0; + this->Scale[1] = 1.0; + this->Scale[2] = 1.0; + + vtkMath::UninitializeBounds(this->Bounds); + + this->Center[0] = this->Center[1] = this->Center[2] = 0.0; + + this->UserMatrix = NULL; + this->UserTransform = NULL; + this->Matrix = vtkMatrix4x4::New(); + this->Transform = vtkTransform::New(); + + this->CachedProp3D = NULL; + this->IsIdentity = 1; +} + +vtkProp3D::~vtkProp3D() +{ + this->Matrix->Delete(); + this->Transform->Delete(); + if (this->UserMatrix) + { + this->UserMatrix->UnRegister(this); + this->UserMatrix = NULL; + } + if (this->CachedProp3D) + { + this->CachedProp3D->Delete(); + this->CachedProp3D = NULL; + } + if (this->UserTransform) + { + this->UserTransform->UnRegister(this); + this->UserTransform = NULL; + } +} + +unsigned long int vtkProp3D::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + time = this->GetUserTransformMatrixMTime(); + mTime = ( time > mTime ? time : mTime ); + + return mTime; +} + +unsigned long int vtkProp3D::GetUserTransformMatrixMTime() +{ + unsigned long mTime = 0; + unsigned long time; + + // Factored out of GetMTime because there are times we want + // just this information, without being influenced by other + // changes that affect this class's or a subclass's mtime. + // (E.g. see vtkLODProp3D) + if ( this->UserMatrix != NULL ) + { + mTime = this->UserMatrix->GetMTime(); + } + + if ( this->UserTransform != NULL ) + { + time = this->UserTransform->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + + return mTime; +} + +// Incrementally change the position of the Prop3D. +void vtkProp3D::AddPosition (double deltaX,double deltaY,double deltaZ) +{ + double position[3]; + + position[0] = this->Position[0] + deltaX; + position[1] = this->Position[1] + deltaY; + position[2] = this->Position[2] + deltaZ; + + this->SetPosition(position); + this->IsIdentity = 0; +} + +void vtkProp3D::AddPosition (double deltaPosition[3]) +{ + this->AddPosition (deltaPosition[0], deltaPosition[1], deltaPosition[2]); + this->IsIdentity = 0; +} + +// Sets the orientation of the Prop3D. Orientation is specified as X,Y and Z +// rotations in that order, but they are performed as RotateZ, RotateX, and +// finally RotateY. +void vtkProp3D::SetOrientation (double x,double y,double z) +{ + // compute the orientation of the transformation matrix + // as is done in GetOrientation to make sure we are consistent + this->Transform->GetOrientation(this->Orientation); + + if (x == this->Orientation[0] && y == this->Orientation[1] + && z == this->Orientation[2]) + { + return; + } + this->IsIdentity = 0; + + // store the coordinates + this->Orientation[0] = x; + this->Orientation[1] = y; + this->Orientation[2] = z; + + vtkDebugMacro(<< " Orientation set to ( " + << this->Orientation[0] << ", " + << this->Orientation[1] << ", " + << this->Orientation[2] << ")\n"); + + this->Transform->Identity(); + this->Transform->PreMultiply (); + this->Transform->RotateZ(this->Orientation[2]); + this->Transform->RotateX(this->Orientation[0]); + this->Transform->RotateY(this->Orientation[1]); + + this->Modified(); +} +void vtkProp3D::SetOrientation(double a[3]) +{ + this->SetOrientation(a[0],a[1],a[2]); +} + +// Returns the orientation of the Prop3D as s vector of X,Y and Z rotation. +// The ordering in which these rotations must be done to generate the same +// matrix is RotateZ, RotateX, and finally RotateY. See also SetOrientation. +double *vtkProp3D::GetOrientation () +{ + // return the orientation of the transformation matrix + this->Transform->GetOrientation(this->Orientation); + + vtkDebugMacro(<< " Returning Orientation of ( " << this->Orientation[0] + << ", " << this->Orientation[1] << ", " << this->Orientation[2] << ")\n"); + + return this->Orientation; +} // vtkProp3D::Getorientation + +void vtkProp3D::GetOrientation (double o[3]) +{ + // return the orientation of the transformation matrix + this->Transform->GetOrientation(o); + vtkDebugMacro(<< " Returning Orientation of ( " << o[0] + << ", " << o[1] << ", " << o[2] << ")\n"); + +} // vtkProp3D::Getorientation + +// Returns the WXYZ orientation of the Prop3D. +double *vtkProp3D::GetOrientationWXYZ() +{ + return this->Transform->GetOrientationWXYZ(); +} + +// Add to the current orientation. See SetOrientation and GetOrientation for +// more details. This basically does a GetOrientation, adds the passed in +// arguments, and then calls SetOrientation. +void vtkProp3D::AddOrientation (double a1,double a2,double a3) +{ + double orient[3]; + + this->GetOrientation(orient); + this->SetOrientation(orient[0] + a1, + orient[1] + a2, + orient[2] + a3); +} +void vtkProp3D::AddOrientation(double a[3]) +{ + this->AddOrientation(a[0],a[1],a[2]); +} + +// Rotate the Prop3D in degrees about the X axis using the right hand +// rule. The axis is the Prop3D's X axis, which can change as other rotations +// are performed. To rotate about the world X axis use RotateWXYZ (angle, 1, +// 0, 0). This rotation is applied before all others in the current +// transformation matrix. +void vtkProp3D::RotateX (double angle) +{ + this->IsIdentity = 0; + this->Transform->PreMultiply (); + this->Transform->RotateX(angle); + this->Modified(); +} + +// Rotate the Prop3D in degrees about the Y axis using the right hand +// rule. The axis is the Prop3D's Y axis, which can change as other rotations +// are performed. To rotate about the world Y axis use RotateWXYZ (angle, 0, +// 1, 0). This rotation is applied before all others in the current +// transformation matrix. +void vtkProp3D::RotateY (double angle) +{ + this->IsIdentity = 0; + this->Transform->PreMultiply (); + this->Transform->RotateY(angle); + this->Modified(); +} + +// Rotate the Prop3D in degrees about the Z axis using the right hand +// rule. The axis is the Prop3D's Z axis, which can change as other rotations +// are performed. To rotate about the world Z axis use RotateWXYZ (angle, 0, +// 0, 1). This rotation is applied before all others in the current +// transformation matrix. + +void vtkProp3D::RotateZ (double angle) +{ + this->IsIdentity = 0; + this->Transform->PreMultiply (); + this->Transform->RotateZ(angle); + this->Modified(); +} + +// Rotate the Prop3D in degrees about an arbitrary axis specified by the +// last three arguments. The axis is specified in world coordinates. To +// rotate an about its model axes, use RotateX, RotateY, RotateZ. +void vtkProp3D::RotateWXYZ (double degree, double x, double y, double z) +{ + this->IsIdentity = 0; + this->Transform->PostMultiply(); + this->Transform->RotateWXYZ(degree,x,y,z); + this->Transform->PreMultiply(); + this->Modified(); +} + +void vtkProp3D::SetUserTransform(vtkLinearTransform *transform) +{ + this->IsIdentity = 0; + if (transform == this->UserTransform) + { + return; + } + if (this->UserTransform) + { + this->UserTransform->Delete(); + this->UserTransform = NULL; + } + if (this->UserMatrix) + { + this->UserMatrix->Delete(); + this->UserMatrix = NULL; + } + if (transform) + { + this->UserTransform = transform; + this->UserTransform->Register(this); + this->UserMatrix = transform->GetMatrix(); + this->UserMatrix->Register(this); + } + this->Modified(); +} + +void vtkProp3D::SetUserMatrix(vtkMatrix4x4 *matrix) +{ + this->IsIdentity = 0; + if (matrix == this->UserMatrix) + { + return; + } + if (this->UserTransform) + { + this->UserTransform->Delete(); + this->UserTransform = NULL; + } + if (this->UserMatrix) + { + this->UserMatrix->Delete(); + this->UserMatrix = NULL; + } + if (matrix) + { + this->UserMatrix = matrix; + this->UserMatrix->Register(this); + vtkMatrixToLinearTransform *transform = vtkMatrixToLinearTransform::New(); + // Consistent Register and UnRegisters. + transform->Register(this); + transform->Delete(); + transform->SetInput(matrix); + this->UserTransform = transform; + } + this->Modified(); +} + +void vtkProp3D::GetMatrix(vtkMatrix4x4 *result) +{ + this->GetMatrix(&result->Element[0][0]); + result->Modified(); +} + +void vtkProp3D::GetMatrix(double result[16]) +{ + this->ComputeMatrix(); + vtkMatrix4x4::DeepCopy(result,this->Matrix); +} + +void vtkProp3D::ComputeMatrix() +{ + if (this->IsIdentity) + { + return; + } + + // check whether or not need to rebuild the matrix + if ( this->GetMTime() > this->MatrixMTime ) + { + this->GetOrientation(); + this->Transform->Push(); + this->Transform->Identity(); + this->Transform->PostMultiply(); + + // shift back to actor's origin + this->Transform->Translate(-this->Origin[0], + -this->Origin[1], + -this->Origin[2]); + + // scale + this->Transform->Scale(this->Scale[0], + this->Scale[1], + this->Scale[2]); + + // rotate + this->Transform->RotateY(this->Orientation[1]); + this->Transform->RotateX(this->Orientation[0]); + this->Transform->RotateZ(this->Orientation[2]); + + // move back from origin and translate + this->Transform->Translate(this->Origin[0] + this->Position[0], + this->Origin[1] + this->Position[1], + this->Origin[2] + this->Position[2]); + + // apply user defined transform last if there is one + if (this->UserTransform) + { + this->Transform->Concatenate(this->UserTransform->GetMatrix()); + } + + this->Transform->PreMultiply(); + this->Transform->GetMatrix(this->Matrix); + this->MatrixMTime.Modified(); + this->Transform->Pop(); + } +} + + +// Get the bounds for this Prop3D as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +void vtkProp3D::GetBounds(double bounds[6]) +{ + this->GetBounds(); + for (int i=0; i<6; i++) + { + bounds[i] = this->Bounds[i]; + } +} + +// Get the center of the bounding box in world coordinates. +double *vtkProp3D::GetCenter() +{ + this->GetBounds(); + this->Center[0] = (this->Bounds[1] + this->Bounds[0])/2.0; + this->Center[1] = (this->Bounds[3] + this->Bounds[2])/2.0; + this->Center[2] = (this->Bounds[5] + this->Bounds[4])/2.0; + + return this->Center; +} + +// Get the length of the diagonal of the bounding box. +double vtkProp3D::GetLength() +{ + double diff, l=0.0; + int i; + + this->GetBounds(); + for (i=0; i<3; i++) + { + diff = this->Bounds[2*i+1] - this->Bounds[2*i]; + l += diff * diff; + } + + return (double)sqrt(l); +} + +// Get the Prop3D's x range in world coordinates. +double *vtkProp3D::GetXRange() +{ + this->GetBounds(); + return this->Bounds; +} + +// Get the Prop3D's y range in world coordinates. +double *vtkProp3D::GetYRange() +{ + this->GetBounds(); + return &(this->Bounds[2]); +} + +// Get the Prop3D's z range in world coordinates. +double *vtkProp3D::GetZRange() +{ + this->GetBounds(); + return &(this->Bounds[4]); +} + +// Shallow copy of vtkProp3D. +void vtkProp3D::ShallowCopy(vtkProp *prop) +{ + int i; + vtkProp3D *p = vtkProp3D::SafeDownCast(prop); + + if ( p != NULL ) + { + for (i=0; i < 3; i++) + { + this->Origin[i] = p->Origin[i]; + this->Position[i] = p->Position[i]; + this->Orientation[i] = p->Orientation[i]; + this->Center[i] = p->Center[i]; + this->Scale[i] = p->Scale[i]; + } + this->Transform->DeepCopy(p->Transform); + + for (i=0; i < 6; i++) + { + this->Bounds[i] = p->Bounds[i]; + } + + this->SetUserTransform(p->UserTransform); + } + + // Now do superclass + this->vtkProp::ShallowCopy(prop); +} + +// Backdoor allows temporary replacement of matrix in vtkProp3D +void vtkProp3D::PokeMatrix(vtkMatrix4x4 *matrix) +{ + // If non-NULL matrix is provided, then we set ourselves up to + // have a state consistent with the provided matrix. (The idea + // is to make sure the GetMatrix() call works properly.) + if ( matrix != NULL ) //set a new transformation + { + if ( this->CachedProp3D == NULL ) + { + this->CachedProp3D = vtkActor::New(); + } + + //The cached Prop3D stores our current values + //Note: the orientation ivar is not used since the + //orientation is determined from the transform. + if ( this->UserTransform && + this->UserTransform->GetMatrix() == this->UserMatrix ) + { + this->CachedProp3D->SetUserTransform(this->UserTransform); + } + else + { + this->CachedProp3D->SetUserMatrix(this->UserMatrix); + } + this->CachedProp3D->SetOrigin(this->Origin); + this->CachedProp3D->SetPosition(this->Position); + this->CachedProp3D->SetOrientation(this->Orientation); + this->CachedProp3D->SetScale(this->Scale); + this->CachedProp3D->Transform->SetMatrix(this->Transform->GetMatrix()); + + //Set the current transformation variables to "non-transformed" + this->Origin[0] = 0.0; this->Origin[1] = 0.0; this->Origin[2] = 0.0; + this->Position[0] = 0.0; this->Position[1] = 0.0; this->Position[2] = 0.0; + this->Scale[0] = 1.0; this->Scale[1] = 1.0; this->Scale[2] = 1.0; + this->Transform->Identity(); + + //the poked matrix is set as the UserMatrix. Since everything else is + //"non-transformed", this is the final transformation. + this->SetUserMatrix(matrix); + } + else //we restore our original state + { + this->CachedProp3D->GetOrigin(this->Origin); + this->CachedProp3D->GetPosition(this->Position); + this->CachedProp3D->GetScale(this->Scale); + if ( this->CachedProp3D->UserTransform && + this->CachedProp3D->UserTransform->GetMatrix() == + this->CachedProp3D->UserMatrix ) + { + this->SetUserTransform(this->CachedProp3D->UserTransform); + } + else + { + this->SetUserMatrix(this->CachedProp3D->UserMatrix); + } + this->CachedProp3D->SetUserTransform(NULL); + this->Transform->SetMatrix(this->CachedProp3D->GetMatrix()); + this->Modified(); + } +} + +void vtkProp3D::InitPathTraversal() +{ + if ( this->Paths ) + { + this->Paths->Delete(); + } + this->Paths = vtkAssemblyPaths::New(); + vtkAssemblyPath *path = vtkAssemblyPath::New(); + path->AddNode(this,this->GetMatrix()); + this->BuildPaths(this->Paths,path); + path->Delete(); + + this->Paths->InitTraversal(); +} + +vtkMatrix4x4* vtkProp3D::GetUserMatrix() +{ + if (this->UserTransform) + { + this->UserTransform->Update(); + } + return this->UserMatrix; +} + +void vtkProp3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "IsIdentity: " << (this->IsIdentity ? "true" : "false") << "\n"; + + os << indent << "Position: (" << this->Position[0] << ", " + << this->Position[1] << ", " << this->Position[2] << ")\n"; + + os << indent << "Orientation: (" << this->Orientation[0] << ", " + << this->Orientation[1] << ", " << this->Orientation[2] << ")\n"; + + os << indent << "Origin: (" << this->Origin[0] << ", " + << this->Origin[1] << ", " << this->Origin[2] << ")\n"; + + os << indent << "Scale: (" << this->Scale[0] << ", " + << this->Scale[1] << ", " << this->Scale[2] << ")\n"; + + double *bounds = this->GetBounds(); + if ( bounds != NULL ) + { + os << indent << "Bounds: \n"; + os << indent << " Xmin,Xmax: (" + << this->Bounds[0] << ", " << this->Bounds[1] << ")\n"; + os << indent << " Ymin,Ymax: (" + << this->Bounds[2] << ", " << this->Bounds[3] << ")\n"; + os << indent << " Zmin,Zmax: (" + << this->Bounds[4] << ", " << this->Bounds[5] << ")\n"; + } + else + { + os << indent << "Bounds: (not defined)\n"; + } + + os << indent << "UserTransform: "; + if (this->UserTransform) + { + os << this->UserTransform << "\n"; + } + else + { + os << "(none)\n"; + } + + os << indent << "UserMatrix: "; + if (this->UserMatrix) + { + os << this->UserMatrix << "\n"; + } + else + { + os << "(none)\n"; + } +} + diff --git a/Rendering/vtkProp3D.h b/Rendering/vtkProp3D.h new file mode 100644 index 0000000..a846ade --- /dev/null +++ b/Rendering/vtkProp3D.h @@ -0,0 +1,315 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProp3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProp3D - represents an 3D object for placement in a rendered scene +// .SECTION Description +// vtkProp3D is an abstract class used to represent an entity in a rendering +// scene (i.e., vtkProp3D is a vtkProp with an associated transformation +// matrix). It handles functions related to the position, orientation and +// scaling. It combines these instance variables into one 4x4 transformation +// matrix as follows: [x y z 1] = [x y z 1] Translate(-origin) Scale(scale) +// Rot(y) Rot(x) Rot (z) Trans(origin) Trans(position). Both vtkActor and +// vtkVolume are specializations of class vtkProp. The constructor defaults +// to: origin(0,0,0) position=(0,0,0) orientation=(0,0,0), no user defined +// matrix or transform, and no texture map. + +// .SECTION See Also +// vtkProp vtkActor vtkAssembly vtkVolume + +#ifndef __vtkProp3D_h +#define __vtkProp3D_h + +#include "vtkProp.h" + +class vtkRenderer; +class vtkTransform; +class vtkLinearTransform; + +class VTK_RENDERING_EXPORT vtkProp3D : public vtkProp +{ +public: + vtkTypeRevisionMacro(vtkProp3D,vtkProp); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Shallow copy of this vtkProp3D. + void ShallowCopy(vtkProp *prop); + + // Description: + // Set/Get/Add the position of the Prop3D in world coordinates. + virtual void SetPosition(double _arg1, double _arg2, double _arg3) + { + vtkDebugMacro(<< this->GetClassName() << " (" << this << + "): setting Position to (" << _arg1 << "," << _arg2 << "," << + _arg3 << ")"); + if ((this->Position[0] != _arg1)|| + (this->Position[1] != _arg2)|| + (this->Position[2] != _arg3)) + { + this->Position[0] = _arg1; + this->Position[1] = _arg2; + this->Position[2] = _arg3; + this->Modified(); + this->IsIdentity = 0; + } + }; + virtual void SetPosition (double _arg[3]) + { + this->SetPosition (_arg[0], _arg[1], _arg[2]); + } + vtkGetVectorMacro(Position,double,3); + void AddPosition(double deltaPosition[3]); + void AddPosition(double deltaX,double deltaY,double deltaZ); + + // Description: + // Set/Get the origin of the Prop3D. This is the point about which all + // rotations take place. + virtual void SetOrigin(double _arg1, double _arg2, double _arg3) + { + vtkDebugMacro(<< this->GetClassName() << " (" << this << + "): setting Origin to (" << _arg1 << "," << _arg2 << "," << + _arg3 << ")"); + if ((this->Origin[0] != _arg1)|| + (this->Origin[1] != _arg2)|| + (this->Origin[2] != _arg3)) + { + this->Origin[0] = _arg1; + this->Origin[1] = _arg2; + this->Origin[2] = _arg3; + this->Modified(); + this->IsIdentity = 0; + } + }; + virtual void SetOrigin(double _arg[3]) + { + this->SetOrigin (_arg[0], _arg[1], _arg[2]); + } + vtkGetVectorMacro(Origin,double,3); + + // Description: + // Set/Get the scale of the actor. Scaling in performed independently on the + // X, Y and Z axis. A scale of zero is illegal and will be replaced with one. + virtual void SetScale(double _arg1, double _arg2, double _arg3) + { + vtkDebugMacro(<< this->GetClassName() << " (" << this << + "): setting Scale to (" << _arg1 << "," << _arg2 << "," << + _arg3 << ")"); + if ((this->Scale[0] != _arg1)|| + (this->Scale[1] != _arg2)|| + (this->Scale[2] != _arg3)) + { + this->Scale[0] = _arg1; + this->Scale[1] = _arg2; + this->Scale[2] = _arg3; + this->Modified(); + this->IsIdentity = 0; + } + }; + virtual void SetScale (double _arg[3]) + { + this->SetScale (_arg[0], _arg[1], _arg[2]); + } + vtkGetVectorMacro(Scale,double,3); + + // Description: + // Method to set the scale isotropically + void SetScale(double s) {this->SetScale(s,s,s);}; + + // Description: + // In addition to the instance variables such as position and orientation, + // you can add an additional transformation for your own use. This + // transformation is concatenated with the actor's internal transformation, + // which you implicitly create through the use of SetPosition(), + // SetOrigin() and SetOrientation(). + //

If the internal transformation + // is identity (i.e. if you don't set the Position, Origin, or + // Orientation) then the actors final transformation will be the + // UserTransform, concatenated with the UserMatrix if the UserMatrix + // is present. + void SetUserTransform(vtkLinearTransform *transform); + vtkGetObjectMacro(UserTransform,vtkLinearTransform); + + // Description: + // The UserMatrix can be used in place of UserTransform. + void SetUserMatrix(vtkMatrix4x4 *matrix); + vtkMatrix4x4 *GetUserMatrix(); + + // Description: + // Return a reference to the Prop3D's 4x4 composite matrix. + // Get the matrix from the position, origin, scale and orientation This + // matrix is cached, so multiple GetMatrix() calls will be efficient. + virtual void GetMatrix(vtkMatrix4x4 *m); + virtual void GetMatrix(double m[16]); + + // Description: + // Return a reference to the Prop3D's composite transform. + + // Description: + // Get the bounds for this Prop3D as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). + void GetBounds(double bounds[6]); + virtual double *GetBounds() = 0; + + // Description: + // Get the center of the bounding box in world coordinates. + double *GetCenter(); + + // Description: + // Get the Prop3D's x range in world coordinates. + double *GetXRange(); + + // Description: + // Get the Prop3D's y range in world coordinates. + double *GetYRange(); + + // Description: + // Get the Prop3D's z range in world coordinates. + double *GetZRange(); + + // Description: + // Get the length of the diagonal of the bounding box. + double GetLength(); + + // Description: + // Rotate the Prop3D in degrees about the X axis using the right hand + // rule. The axis is the Prop3D's X axis, which can change as other + // rotations are performed. To rotate about the world X axis use + // RotateWXYZ (angle, 1, 0, 0). This rotation is applied before all + // others in the current transformation matrix. + void RotateX(double); + + // Description: + // Rotate the Prop3D in degrees about the Y axis using the right hand + // rule. The axis is the Prop3D's Y axis, which can change as other + // rotations are performed. To rotate about the world Y axis use + // RotateWXYZ (angle, 0, 1, 0). This rotation is applied before all + // others in the current transformation matrix. + void RotateY(double); + + // Description: + // Rotate the Prop3D in degrees about the Z axis using the right hand + // rule. The axis is the Prop3D's Z axis, which can change as other + // rotations are performed. To rotate about the world Z axis use + // RotateWXYZ (angle, 0, 0, 1). This rotation is applied before all + // others in the current transformation matrix. + void RotateZ(double); + + // Description: + // Rotate the Prop3D in degrees about an arbitrary axis specified by + // the last three arguments. The axis is specified in world + // coordinates. To rotate an about its model axes, use RotateX, + // RotateY, RotateZ. + void RotateWXYZ(double,double,double,double); + + // Description: + // Sets the orientation of the Prop3D. Orientation is specified as + // X,Y and Z rotations in that order, but they are performed as + // RotateZ, RotateX, and finally RotateY. + void SetOrientation(double,double,double); + + // Description: + // Sets the orientation of the Prop3D. Orientation is specified as + // X,Y and Z rotations in that order, but they are performed as + // RotateZ, RotateX, and finally RotateY. + void SetOrientation(double a[3]); + + // Description: + // Returns the orientation of the Prop3D as s vector of X,Y and Z rotation. + // The ordering in which these rotations must be done to generate the + // same matrix is RotateZ, RotateX, and finally RotateY. See also + // SetOrientation. + double *GetOrientation(); + void GetOrientation(double o[3]); + + // Description: + // Returns the WXYZ orientation of the Prop3D. + double *GetOrientationWXYZ(); + + // Description: + // Add to the current orientation. See SetOrientation and + // GetOrientation for more details. This basically does a + // GetOrientation, adds the passed in arguments, and then calls + // SetOrientation. + void AddOrientation(double,double,double); + + // Description: + // Add to the current orientation. See SetOrientation and + // GetOrientation for more details. This basically does a + // GetOrientation, adds the passed in arguments, and then calls + // SetOrientation. + void AddOrientation(double a[3]); + + // Description: + // This method modifies the vtkProp3D so that its transformation + // state is set to the matrix specified. The method does this by + // setting appropriate transformation-related ivars to initial + // values (i.e., not transformed), and placing the user-supplied + // matrix into the UserMatrix of this vtkProp3D. If the method is + // called again with a NULL matrix, then the original state of the + // vtkProp3D will be restored. This method is used to support + // picking and assembly structures. + void PokeMatrix(vtkMatrix4x4 *matrix); + + // Description: + // Overload vtkProp's method for setting up assembly paths. See + // the documentation for vtkProp. + void InitPathTraversal(); + + // Description: + // Get the vtkProp3D's mtime + unsigned long int GetMTime(); + + // Description: + // Get the modified time of the user matrix or user transform. + unsigned long int GetUserTransformMatrixMTime(); + + // Description: + // Generate the matrix based on ivars + virtual void ComputeMatrix(); + + // Description: + // Get a pointer to an internal vtkMatrix4x4. that represents + vtkMatrix4x4 *GetMatrix() + { + this->ComputeMatrix(); + return this->Matrix; + } + + // Description: + // Is the matrix for this actor identity + vtkGetMacro(IsIdentity,int); + +protected: + vtkProp3D(); + ~vtkProp3D(); + + vtkLinearTransform *UserTransform; + vtkMatrix4x4 *UserMatrix; + vtkMatrix4x4 *Matrix; + vtkTimeStamp MatrixMTime; + double Origin[3]; + double Position[3]; + double Orientation[3]; + double Scale[3]; + double Center[3]; + vtkTransform *Transform; + double Bounds[6]; + vtkProp3D *CachedProp3D; //support the PokeMatrix() method + int IsIdentity; +private: + vtkProp3D(const vtkProp3D&); // Not implemented. + void operator=(const vtkProp3D&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkProp3DCollection.cxx b/Rendering/vtkProp3DCollection.cxx new file mode 100644 index 0000000..ff43bb9 --- /dev/null +++ b/Rendering/vtkProp3DCollection.cxx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProp3DCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProp3DCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkProp3DCollection, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkProp3DCollection); + +//---------------------------------------------------------------------------- +void vtkProp3DCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkProp3DCollection.h b/Rendering/vtkProp3DCollection.h new file mode 100644 index 0000000..e197fae --- /dev/null +++ b/Rendering/vtkProp3DCollection.h @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProp3DCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProp3DCollection - a list of 3D props +// .SECTION Description +// vtkProp3DCollection represents and provides methods to manipulate a list of +// 3D props (i.e., vtkProp3D and subclasses). The list is unsorted and +// duplicate entries are not prevented. + +// .SECTION see also +// vtkProp3D vtkCollection + +#ifndef __vtkProp3DCollection_h +#define __vtkProp3DCollection_h + +#include "vtkPropCollection.h" +#include "vtkProp3D.h" // Needed for inline methods + +class VTK_RENDERING_EXPORT vtkProp3DCollection : public vtkPropCollection +{ +public: + static vtkProp3DCollection *New(); + vtkTypeRevisionMacro(vtkProp3DCollection,vtkPropCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add an actor to the list. + void AddItem(vtkProp3D *p); + + // Description: + // Get the next actor in the list. + vtkProp3D *GetNextProp3D(); + + // Description: + // Get the last actor in the list. + vtkProp3D *GetLastProp3D(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkProp3D *GetNextProp3D(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkProp3DCollection() {}; + ~vtkProp3DCollection() {}; + + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + void AddItem(vtkProp *o) { this->vtkPropCollection::AddItem(o); }; + +private: + vtkProp3DCollection(const vtkProp3DCollection&); // Not implemented. + void operator=(const vtkProp3DCollection&); // Not implemented. +}; + +inline void vtkProp3DCollection::AddItem(vtkProp3D *a) +{ + this->vtkCollection::AddItem((vtkObject *)a); +} + +inline vtkProp3D *vtkProp3DCollection::GetNextProp3D() +{ + return static_cast(this->GetNextItemAsObject()); +} + +inline vtkProp3D *vtkProp3DCollection::GetLastProp3D() +{ + if ( this->Bottom == NULL ) + { + return NULL; + } + else + { + return static_cast(this->Bottom->Item); + } +} + +#endif + + + + + diff --git a/Rendering/vtkPropPicker.cxx b/Rendering/vtkPropPicker.cxx new file mode 100644 index 0000000..ae12134 --- /dev/null +++ b/Rendering/vtkPropPicker.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPropPicker.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPropPicker.h" + +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCommand.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkWorldPointPicker.h" + +vtkCxxRevisionMacro(vtkPropPicker, "$Revision: 1.25 $"); +vtkStandardNewMacro(vtkPropPicker); + +vtkPropPicker::vtkPropPicker() +{ + this->PickFromProps = NULL; + this->WorldPointPicker = vtkWorldPointPicker::New(); +} + +vtkPropPicker::~vtkPropPicker() +{ + this->WorldPointPicker->Delete(); +} + +// set up for a pick +void vtkPropPicker::Initialize() +{ + this->vtkAbstractPropPicker::Initialize(); +} + +// Pick from the given collection +int vtkPropPicker::Pick(double selectionX, double selectionY, + double vtkNotUsed(z), vtkRenderer *renderer) +{ + return this->PickProp(selectionX, selectionY, renderer); +} + + +// Pick from the given collection +int vtkPropPicker::PickProp(double selectionX, double selectionY, + vtkRenderer *renderer, vtkPropCollection* pickfrom) +{ + this->PickFromProps = pickfrom; + int ret = this->PickProp(selectionX, selectionY, renderer); + this->PickFromProps = NULL; + return ret; +} + + + +// Perform pick operation with selection point provided. The z location +// is recovered from the zBuffer. Always returns 0 since no actors are picked. +int vtkPropPicker::PickProp(double selectionX, double selectionY, + vtkRenderer *renderer) +{ + // Initialize picking process + this->Initialize(); + this->Renderer = renderer; + this->SelectionPoint[0] = selectionX; + this->SelectionPoint[1] = selectionY; + this->SelectionPoint[2] = 0; + + // Invoke start pick method if defined + this->InvokeEvent(vtkCommand::StartPickEvent,NULL); + + // Have the renderer do the hardware pick + this->SetPath( + renderer->PickPropFrom(selectionX, selectionY, this->PickFromProps)); + + // If there was a pick then find the world x,y,z for the pick, and invoke + // its pick method. + if ( this->Path ) + { + this->WorldPointPicker->Pick(selectionX, selectionY, 0, renderer); + this->WorldPointPicker->GetPickPosition(this->PickPosition); + this->Path->GetLastNode()->GetViewProp()->Pick(); + this->InvokeEvent(vtkCommand::PickEvent,NULL); + } + + this->InvokeEvent(vtkCommand::EndPickEvent,NULL); + + // Call Pick on the Prop that was picked, and return 1 for success + if ( this->Path ) + { + return 1; + } + else + { + return 0; + } +} + +void vtkPropPicker::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + if (this->PickFromProps) + { + os << indent << "PickFrom List: " << this->PickFromProps << endl; + } + else + { + os << indent << "PickFrom List: (none)" << endl; + } + +} diff --git a/Rendering/vtkPropPicker.h b/Rendering/vtkPropPicker.h new file mode 100644 index 0000000..5f100af --- /dev/null +++ b/Rendering/vtkPropPicker.h @@ -0,0 +1,81 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPropPicker.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPropPicker - pick an actor/prop using graphics hardware +// .SECTION Description +// vtkPropPicker is used to pick an actor/prop given a selection +// point (in display coordinates) and a renderer. This class uses +// graphics hardware/rendering system to pick rapidly (as compared +// to using ray casting as does vtkCellPicker and vtkPointPicker). +// This class determines the actor/prop and pick position in world +// coordinates; point and cell ids are not determined. + +// .SECTION See Also +// vtkPicker vtkWorldPointPicker vtkCellPicker vtkPointPicker + +#ifndef __vtkPropPicker_h +#define __vtkPropPicker_h + +#include "vtkAbstractPropPicker.h" + +class vtkProp; +class vtkWorldPointPicker; + +class VTK_RENDERING_EXPORT vtkPropPicker : public vtkAbstractPropPicker +{ +public: + static vtkPropPicker *New(); + + vtkTypeRevisionMacro(vtkPropPicker,vtkAbstractPropPicker); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Perform the pick and set the PickedProp ivar. If something is picked, a + // 1 is returned, otherwise 0 is returned. Use the GetViewProp() method + // to get the instance of vtkProp that was picked. Props are picked from + // the renderers list of pickable Props. + int PickProp(double selectionX, double selectionY, vtkRenderer *renderer); + + // Description: + // Perform a pick from the user-provided list of vtkProps and not from the + // list of vtkProps that the render maintains. + int PickProp(double selectionX, double selectionY, vtkRenderer *renderer, + vtkPropCollection* pickfrom); + + // Description: + // Overide superclasses' Pick() method. + int Pick(double selectionX, double selectionY, double selectionZ, + vtkRenderer *renderer); + int Pick(double selectionPt[3], vtkRenderer *renderer) + { return this->Pick( selectionPt[0], + selectionPt[1], selectionPt[2], renderer); }; + +protected: + vtkPropPicker(); + ~vtkPropPicker(); + + void Initialize(); + + vtkPropCollection* PickFromProps; + + // Used to get x-y-z pick position + vtkWorldPointPicker *WorldPointPicker; +private: + vtkPropPicker(const vtkPropPicker&); // Not implemented. + void operator=(const vtkPropPicker&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkProperty.cxx b/Rendering/vtkProperty.cxx new file mode 100644 index 0000000..fb59374 --- /dev/null +++ b/Rendering/vtkProperty.cxx @@ -0,0 +1,193 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProperty.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkActor.h" +#include "vtkGraphicsFactory.h" + +#include + +vtkCxxRevisionMacro(vtkProperty, "$Revision: 1.55 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkProperty); +//---------------------------------------------------------------------------- + +// Construct object with object color, ambient color, diffuse color, +// specular color, and edge color white; ambient coefficient=0; diffuse +// coefficient=0; specular coefficient=0; specular power=1; Gouraud shading; +// and surface representation. Backface and frontface culling are off. +vtkProperty::vtkProperty() +{ + this->AmbientColor[0] = 1; + this->AmbientColor[1] = 1; + this->AmbientColor[2] = 1; + + this->DiffuseColor[0] = 1; + this->DiffuseColor[1] = 1; + this->DiffuseColor[2] = 1; + + this->SpecularColor[0] = 1; + this->SpecularColor[1] = 1; + this->SpecularColor[2] = 1; + + this->EdgeColor[0] = 1; + this->EdgeColor[1] = 1; + this->EdgeColor[2] = 1; + + this->Ambient = 0.0; + this->Diffuse = 1.0; + this->Specular = 0.0; + this->SpecularPower = 1.0; + this->Opacity = 1.0; + this->Interpolation = VTK_GOURAUD; + this->Representation = VTK_SURFACE; + this->EdgeVisibility = 0; + this->BackfaceCulling = 0; + this->FrontfaceCulling = 0; + this->PointSize = 1.0; + this->LineWidth = 1.0; + this->LineStipplePattern = 0xFFFF; + this->LineStippleRepeatFactor = 1; +} + +// Assign one property to another. +void vtkProperty::DeepCopy(vtkProperty *p) +{ + if ( p != NULL ) + { + this->SetColor(p->GetColor()); + this->SetAmbientColor(p->GetAmbientColor()); + this->SetDiffuseColor(p->GetDiffuseColor()); + this->SetSpecularColor(p->GetSpecularColor()); + this->SetEdgeColor(p->GetEdgeColor()); + this->SetAmbient(p->GetAmbient()); + this->SetDiffuse(p->GetDiffuse()); + this->SetSpecular(p->GetSpecular()); + this->SetSpecularPower(p->GetSpecularPower()); + this->SetOpacity(p->GetOpacity()); + this->SetInterpolation(p->GetInterpolation()); + this->SetRepresentation(p->GetRepresentation()); + this->SetEdgeVisibility(p->GetEdgeVisibility()); + this->SetBackfaceCulling(p->GetBackfaceCulling()); + this->SetFrontfaceCulling(p->GetFrontfaceCulling()); + this->SetPointSize(p->GetPointSize()); + this->SetLineWidth(p->GetLineWidth()); + this->SetLineStipplePattern(p->GetLineStipplePattern()); + this->SetLineStippleRepeatFactor(p->GetLineStippleRepeatFactor()); + } +} + +// return the correct type of Property +vtkProperty *vtkProperty::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkProperty"); + return (vtkProperty*)ret; +} + +void vtkProperty::SetColor(double R,double G,double B) +{ + // Use Set macros to insure proper modified time behavior + this->SetAmbientColor(R,G,B); + this->SetDiffuseColor(R,G,B); + this->SetSpecularColor(R,G,B); +} + +// Return composite color of object (ambient + diffuse + specular). Return value +// is a pointer to rgb values. +double *vtkProperty::GetColor() +{ + double norm; + int i; + + if ((this->Ambient + this->Diffuse + this->Specular)>0) + { + norm = 1.0 / (this->Ambient + this->Diffuse + this->Specular); + } + else + { + norm = 0.0; + } + + for (i = 0; i < 3; i ++) + { + this->Color[i] = this->AmbientColor[i]*this->Ambient*norm; + this->Color[i] = this->Color[i] + this->DiffuseColor[i]*this->Diffuse*norm; + this->Color[i] = this->Color[i] + this->SpecularColor[i]*this->Specular*norm; + } + + return this->Color; +} + +// Copy composite color of object (ambient + diffuse + specular) into array +// provided. +void vtkProperty::GetColor(double rgb[3]) +{ + this->GetColor(); + + rgb[0] = this->Color[0]; + rgb[1] = this->Color[1]; + rgb[2] = this->Color[2]; +} + + +void vtkProperty::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Ambient: " << this->Ambient << "\n"; + os << indent << "Ambient Color: (" << this->AmbientColor[0] << ", " + << this->AmbientColor[1] << ", " << this->AmbientColor[2] << ")\n"; + os << indent << "Diffuse: " << this->Diffuse << "\n"; + os << indent << "Diffuse Color: (" << this->DiffuseColor[0] << ", " + << this->DiffuseColor[1] << ", " << this->DiffuseColor[2] << ")\n"; + os << indent << "Edge Color: (" << this->EdgeColor[0] << ", " + << this->EdgeColor[1] << ", " << this->EdgeColor[2] << ")\n"; + os << indent << "Edge Visibility: " + << (this->EdgeVisibility ? "On\n" : "Off\n"); + os << indent << "Interpolation: "; + switch (this->Interpolation) + { + case VTK_FLAT: os << "VTK_FLAT\n"; break; + case VTK_GOURAUD: os << "VTK_GOURAUD\n"; break; + case VTK_PHONG: os << "VTK_PHONG\n"; break; + default: os << "unknown\n"; + } + os << indent << "Opacity: " << this->Opacity << "\n"; + os << indent << "Representation: "; + switch (this->Representation) + { + case VTK_POINTS: os << "VTK_POINTS\n"; break; + case VTK_WIREFRAME: os << "VTK_WIREFRAME\n"; break; + case VTK_SURFACE: os << "VTK_SURFACE\n"; break; + default: os << "unknown\n"; + } + os << indent << "Specular: " << this->Specular << "\n"; + os << indent << "Specular Color: (" << this->SpecularColor[0] << ", " + << this->SpecularColor[1] << ", " << this->SpecularColor[2] << ")\n"; + os << indent << "Specular Power: " << this->SpecularPower << "\n"; + os << indent << "Backface Culling: " + << (this->BackfaceCulling ? "On\n" : "Off\n"); + os << indent << "Frontface Culling: " + << (this->FrontfaceCulling ? "On\n" : "Off\n"); + os << indent << "Point size: " << this->PointSize << "\n"; + os << indent << "Line width: " << this->LineWidth << "\n"; + os << indent << "Line stipple pattern: " << this->LineStipplePattern << "\n"; + os << indent << "Line stipple repeat factor: " << this->LineStippleRepeatFactor << "\n"; + +} diff --git a/Rendering/vtkProperty.h b/Rendering/vtkProperty.h new file mode 100644 index 0000000..a7a00a9 --- /dev/null +++ b/Rendering/vtkProperty.h @@ -0,0 +1,272 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProperty.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkProperty - represent surface properties of a geometric object +// .SECTION Description +// vtkProperty is an object that represents lighting and other surface +// properties of a geometric object. The primary properties that can be +// set are colors (overall, ambient, diffuse, specular, and edge color); +// specular power; opacity of the object; the representation of the +// object (points, wireframe, or surface); and the shading method to be +// used (flat, Gouraud, and Phong). Also, some special graphics features +// like backface properties can be set and manipulated with this object. + +// .SECTION See Also +// vtkActor vtkPropertyDevice + +#ifndef __vtkProperty_h +#define __vtkProperty_h + +#include "vtkObject.h" + +// shading models +#define VTK_FLAT 0 +#define VTK_GOURAUD 1 +#define VTK_PHONG 2 + +// representation models +#define VTK_POINTS 0 +#define VTK_WIREFRAME 1 +#define VTK_SURFACE 2 + +class vtkRenderer; +class vtkActor; + +class VTK_RENDERING_EXPORT vtkProperty : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkProperty,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct object with object color, ambient color, diffuse color, + // specular color, and edge color white; ambient coefficient=0; diffuse + // coefficient=0; specular coefficient=0; specular power=1; Gouraud shading; + // and surface representation. Backface and frontface culling are off. + static vtkProperty *New(); + + // Description: + // Assign one property to another. + void DeepCopy(vtkProperty *p); + + // Description: + // This method causes the property to set up whatever is required for + // its instance variables. This is actually handled by a subclass of + // vtkProperty, which is created automatically. This + // method includes the invoking actor as an argument which can + // be used by property devices that require the actor. + virtual void Render(vtkActor *,vtkRenderer *) {}; + + // Description: + // This method renders the property as a backface property. TwoSidedLighting + // must be turned off to see any backface properties. Note that only + // colors and opacity are used for backface properties. Other properties + // such as Representation, Culling are specified by the Property. + virtual void BackfaceRender(vtkActor *,vtkRenderer *) {}; + + // Description: + // Set the shading interpolation method for an object. + vtkSetClampMacro(Interpolation,int,VTK_FLAT,VTK_PHONG); + vtkGetMacro(Interpolation,int); + void SetInterpolationToFlat() {this->SetInterpolation(VTK_FLAT);}; + void SetInterpolationToGouraud() {this->SetInterpolation(VTK_GOURAUD);}; + void SetInterpolationToPhong() {this->SetInterpolation(VTK_PHONG);}; + char *GetInterpolationAsString(); + + // Description: + // Control the surface geometry representation for the object. + vtkSetClampMacro(Representation,int,VTK_POINTS,VTK_SURFACE); + vtkGetMacro(Representation,int); + void SetRepresentationToPoints() {this->SetRepresentation(VTK_POINTS);}; + void SetRepresentationToWireframe() { + this->SetRepresentation(VTK_WIREFRAME);}; + void SetRepresentationToSurface() {this->SetRepresentation(VTK_SURFACE);}; + char *GetRepresentationAsString(); + + // Description: + // Set the color of the object. Has the side effect of setting the + // ambient diffuse and specular colors as well. This is basically + // a quick overall color setting method. + void SetColor(double r,double g,double b); + void SetColor(double a[3]) { this->SetColor(a[0], a[1], a[2]); }; + double *GetColor(); + void GetColor(double rgb[3]); + + // Description: + // Set/Get the ambient lighting coefficient. + vtkSetClampMacro(Ambient,double,0.0,1.0); + vtkGetMacro(Ambient,double); + + // Description: + // Set/Get the diffuse lighting coefficient. + vtkSetClampMacro(Diffuse,double,0.0,1.0); + vtkGetMacro(Diffuse,double); + + // Description: + // Set/Get the specular lighting coefficient. + vtkSetClampMacro(Specular,double,0.0,1.0); + vtkGetMacro(Specular,double); + + // Description: + // Set/Get the specular power. + vtkSetClampMacro(SpecularPower,double,0.0,100.0); + vtkGetMacro(SpecularPower,double); + + // Description: + // Set/Get the object's opacity. 1.0 is totally opaque and 0.0 is completely + // transparent. + vtkSetClampMacro(Opacity,double,0.0,1.0); + vtkGetMacro(Opacity,double); + + // Description: + // Set/Get the ambient surface color. Not all renderers support separate + // ambient and diffuse colors. From a physical standpoint it really + // doesn't make too much sense to have both. For the rendering + // libraries that don't support both, the diffuse color is used. + vtkSetVector3Macro(AmbientColor,double); + vtkGetVectorMacro(AmbientColor,double,3); + + // Description: + // Set/Get the diffuse surface color. + vtkSetVector3Macro(DiffuseColor,double); + vtkGetVectorMacro(DiffuseColor,double,3); + + // Description: + // Set/Get the specular surface color. + vtkSetVector3Macro(SpecularColor,double); + vtkGetVectorMacro(SpecularColor,double,3); + + // Description: + // Turn on/off the visibility of edges. On some renderers it is + // possible to render the edges of geometric primitives separately + // from the interior. + vtkGetMacro(EdgeVisibility,int); + vtkSetMacro(EdgeVisibility,int); + vtkBooleanMacro(EdgeVisibility,int); + + // Description: + // Set/Get the color of primitive edges (if edge visibility is enabled). + vtkSetVector3Macro(EdgeColor,double); + vtkGetVectorMacro(EdgeColor,double,3); + + // Description: + // Set/Get the width of a Line. The width is expressed in screen units. + // This is only implemented for OpenGL. The default is 1.0. + vtkSetClampMacro(LineWidth,float,0,VTK_LARGE_FLOAT); + vtkGetMacro(LineWidth,float); + + // Description: + // Set/Get the stippling pattern of a Line, as a 16-bit binary pattern + // (1 = pixel on, 0 = pixel off). + // This is only implemented for OpenGL. The default is 0xFFFF. + vtkSetMacro(LineStipplePattern,int); + vtkGetMacro(LineStipplePattern,int); + + // Description: + // Set/Get the stippling repeat factor of a Line, which specifies how + // many times each bit in the pattern is to be repeated. + // This is only implemented for OpenGL. The default is 1. + vtkSetClampMacro(LineStippleRepeatFactor,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(LineStippleRepeatFactor,int); + + // Description: + // Set/Get the diameter of a point. The size is expressed in screen units. + // This is only implemented for OpenGL. The default is 1.0. + vtkSetClampMacro(PointSize,float,0,VTK_LARGE_FLOAT); + vtkGetMacro(PointSize,float); + + // Description: + // Turn on/off fast culling of polygons based on orientation of normal + // with respect to camera. If backface culling is on, polygons facing + // away from camera are not drawn. + vtkGetMacro(BackfaceCulling,int); + vtkSetMacro(BackfaceCulling,int); + vtkBooleanMacro(BackfaceCulling,int); + + // Description: + // Turn on/off fast culling of polygons based on orientation of normal + // with respect to camera. If frontface culling is on, polygons facing + // towards camera are not drawn. + vtkGetMacro(FrontfaceCulling,int); + vtkSetMacro(FrontfaceCulling,int); + vtkBooleanMacro(FrontfaceCulling,int); + +protected: + vtkProperty(); + ~vtkProperty() {}; + + double Color[3]; + double AmbientColor[3]; + double DiffuseColor[3]; + double SpecularColor[3]; + double EdgeColor[3]; + double Ambient; + double Diffuse; + double Specular; + double SpecularPower; + double Opacity; + float PointSize; + float LineWidth; + int LineStipplePattern; + int LineStippleRepeatFactor; + int Interpolation; + int Representation; + int EdgeVisibility; + int BackfaceCulling; + int FrontfaceCulling; +private: + vtkProperty(const vtkProperty&); // Not implemented. + void operator=(const vtkProperty&); // Not implemented. +}; + +// Description: +// Return the method of shading as a descriptive character string. +inline char *vtkProperty::GetInterpolationAsString(void) +{ + if ( this->Interpolation == VTK_FLAT ) + { + return (char *)"Flat"; + } + else if ( this->Interpolation == VTK_GOURAUD ) + { + return (char *)"Gouraud"; + } + else + { + return (char *)"Phong"; + } +} + + +// Description: +// Return the method of shading as a descriptive character string. +inline char *vtkProperty::GetRepresentationAsString(void) +{ + if ( this->Representation == VTK_POINTS ) + { + return (char *)"Points"; + } + else if ( this->Representation == VTK_WIREFRAME ) + { + return (char *)"Wireframe"; + } + else + { + return (char *)"Surface"; + } +} + + + +#endif diff --git a/Rendering/vtkQuaternionInterpolator.cxx b/Rendering/vtkQuaternionInterpolator.cxx new file mode 100644 index 0000000..0ced268 --- /dev/null +++ b/Rendering/vtkQuaternionInterpolator.cxx @@ -0,0 +1,430 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuaternionInterpolator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkQuaternionInterpolator.h" +#include "vtkObjectFactory.h" +#include "vtkMath.h" +#include + +vtkCxxRevisionMacro(vtkQuaternionInterpolator, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkQuaternionInterpolator); + +//---------------------------------------------------------------------------- +// PIMPL STL encapsulation for list of quaternions. The list is sorted on +// the spline paramter T (or Time) using a STL list. +// Here we define a quaternion class that includes extra information including +// a unit quaternion representation. +struct vtkQuaternion +{ + double Time; + double Q[4]; //VTK's quaternion: unit rotation axis with angles in degrees + double QUnit[4]; //Unit quaternion (i.e., normalized) + + vtkQuaternion() + { + this->Time = 0.0; + this->Q[0] = this->Q[1] = this->Q[2] = this->Q[3] = 0.0; + this->QUnit[0] = this->QUnit[1] = this->QUnit[2] = this->QUnit[3] = 0.0; + } + vtkQuaternion(double t, double q[4]) + { + this->Time = t; + this->Q[0] = this->QUnit[0] = q[0]; + this->Q[1] = this->QUnit[1] = q[1]; + this->Q[2] = this->QUnit[2] = q[2]; + this->Q[3] = this->QUnit[3] = q[3]; + + // determine theta, sin(theta), cos(theta) for unit quaternion + this->QUnit[0] *= vtkMath::DegreesToRadians(); //convert to radians + vtkQuaternion::Normalize(this->QUnit); + } + static void Add(double q0[4], double q1[4], double q[4]) + { + q[0] = q0[0] + q1[0]; + q[1] = q0[1] + q1[1]; + q[2] = q0[2] + q1[2]; + q[3] = q0[3] + q1[3]; + } + static void Product(double q0[4], double q1[4], double q[4]) + { + q[0] = q0[0]*q1[0] - q0[1]*q1[1] - q0[2]*q1[2] - q0[3]*q1[3]; + q[1] = q0[0]*q1[1] + q0[1]*q1[0] + q0[2]*q1[3] - q0[3]*q1[2]; + q[2] = q0[0]*q1[2] - q0[1]*q1[3] + q0[2]*q1[0] + q0[3]*q1[1]; + q[3] = q0[0]*q1[3] + q0[1]*q1[2] - q0[2]*q1[1] + q0[3]*q1[0]; + } + static void Conjugate(double q[4], double qConj[4]) + { + qConj[0] = q[0]; + qConj[1] = -q[1]; + qConj[2] = -q[2]; + qConj[3] = -q[3]; + } + static void Inverse(double q[4], double qInv[4]) + { + vtkQuaternion::Conjugate(q,qInv); + double norm2 = vtkQuaternion::Norm2(q); + if ( norm2 != 0.0 ) + { + qInv[0] /= norm2; + qInv[1] /= norm2; + qInv[2] /= norm2; + qInv[3] /= norm2; + } + } + static double Norm2(double q[4]) + { + return (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + } + static double Normalize(double q[4]) + { + double norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + if ( norm != 0.0 ) + { + q[0] /= norm; + q[1] /= norm; + q[2] /= norm; + q[3] /= norm; + } + return norm; + } + // convert a unit quaternion to a VTK quaternion (angle in degrees;unit axis) + static void UnitToVTK(double q[4]) + { + double vNorm = sqrt(q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + if ( vNorm != 0.0 ) + { + q[0] /= vNorm; + q[1] /= vNorm; + q[2] /= vNorm; + q[3] /= vNorm; + } + q[0] *= vtkMath::RadiansToDegrees(); + } + // compute unit vector where q is a unit quaternion + static void UnitVector(double q[4], double &theta, double &sinTheta, + double &cosTheta, double v[3]) + { + double norm = sqrt(q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + v[0] = q[1]/norm; + v[1] = q[2]/norm; + v[2] = q[3]/norm; + int maxI = (q[1] > q[2] ? (q[1] > q[3] ? 1 : 3) : (q[2] > q[3] ? 2 : 3)); + if (q[maxI] != 0.0 ) + { + sinTheta = q[maxI] / v[maxI-1]; + theta = asin(sinTheta); + cosTheta = cos(theta); + } + } + // log(q) where q is a unit (normalized) quaternion + static void UnitLog(double q[4], double qLog[4]) + { + double theta, sinTheta, cosTheta, v[3]; + vtkQuaternion::UnitVector(q,theta,sinTheta,cosTheta,v); + qLog[0] = 0.0; + qLog[1] = theta * v[0]; + qLog[2] = theta * v[1]; + qLog[3] = theta * v[2]; + } + // exp(q) where q is a unit quaternion + static void UnitExp(double q[4], double qExp[4]) + { + double theta, sinTheta, cosTheta, v[3]; + vtkQuaternion::UnitVector(q,theta,sinTheta,cosTheta,v); + qExp[0] = cosTheta; + qExp[1] = sinTheta * v[0]; + qExp[2] = sinTheta * v[1]; + qExp[3] = sinTheta * v[2]; + } +}; + +// The list is arranged in increasing order in T +class vtkQuaternionList : public vtkstd::vector {}; +typedef vtkQuaternionList::iterator QuaternionListIterator; + +//---------------------------------------------------------------------------- +vtkQuaternionInterpolator::vtkQuaternionInterpolator() +{ + // Set up the interpolation + this->QuaternionList = new vtkQuaternionList; + this->InterpolationType = INTERPOLATION_TYPE_SPLINE; +} + +//---------------------------------------------------------------------------- +vtkQuaternionInterpolator::~vtkQuaternionInterpolator() +{ + this->Initialize(); + delete this->QuaternionList; +} + +//---------------------------------------------------------------------------- +int vtkQuaternionInterpolator::GetNumberOfQuaternions() +{ + return this->QuaternionList->size(); +} + + +//---------------------------------------------------------------------------- +double vtkQuaternionInterpolator::GetMinimumT() +{ + if (this->QuaternionList->size() > 0) + { + return this->QuaternionList->front().Time; + } + else + { + return 0.0; + } +} + + +//---------------------------------------------------------------------------- +double vtkQuaternionInterpolator::GetMaximumT() +{ + if (this->QuaternionList->size() > 0) + { + return this->QuaternionList->back().Time; + } + else + { + return 0.0; + } +} + + +//---------------------------------------------------------------------------- +void vtkQuaternionInterpolator::Initialize() +{ + // Wipe out old data + this->QuaternionList->clear(); +} + + +//---------------------------------------------------------------------------- +void vtkQuaternionInterpolator::AddQuaternion(double t, double q[4]) +{ + int size = this->QuaternionList->size(); + + // Check special cases: t at beginning or end of list + if ( size <= 0 || t < this->QuaternionList->front().Time ) + { + this->QuaternionList->insert(this->QuaternionList->begin(),vtkQuaternion(t,q)); + return; + } + else if ( t > this->QuaternionList->back().Time ) + { + this->QuaternionList->push_back(vtkQuaternion(t,q)); + return; + } + else if ( size == 1 && t == this->QuaternionList->front().Time ) + { + this->QuaternionList->front() = vtkQuaternion(t,q); + return; + } + + // Okay, insert in sorted order + QuaternionListIterator iter = this->QuaternionList->begin(); + QuaternionListIterator nextIter = iter + 1; + for (int i=0; i < (size-1); i++, ++iter, ++nextIter) + { + if ( t == iter->Time ) + { + (*iter) = vtkQuaternion(t,q); //overwrite + break; + } + else if ( t > iter->Time && t < nextIter->Time ) + { + this->QuaternionList->insert(nextIter, vtkQuaternion(t,q)); + break; + } + }//for not in the right spot + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkQuaternionInterpolator::RemoveQuaternion(double t) +{ + if ( t < this->QuaternionList->front().Time || + t > this->QuaternionList->back().Time ) + { + return; + } + + QuaternionListIterator iter = this->QuaternionList->begin(); + for ( ; iter->Time != t && iter != this->QuaternionList->end(); ++iter ) + { + } + if ( iter != this->QuaternionList->end() ) + { + this->QuaternionList->erase(iter); + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +//Interpolate using spherical linear interpolation between the quaternions q0 +//and q1 to produce the output q. The parametric coordinate t is [0,1] and +//lies between (q0,q1). +void vtkQuaternionInterpolator::Slerp(double t, double q0[4], double q1[4], + double q[4]) +{ + double theta = acos( vtkMath::Dot(q0+1,q1+1) ); + double t1 = sin((1.0-t)*theta)/sin(theta); + double t2 = sin(t*theta)/sin(theta); + q[0] = q0[0]*t1 + q1[0]*t2; + q[1] = q0[1]*t1 + q1[1]*t2; + q[2] = q0[2]*t1 + q1[2]*t2; + q[3] = q0[3]*t1 + q1[3]*t2; +} + + +//---------------------------------------------------------------------------- +void vtkQuaternionInterpolator::InnerPoint(double q0[4], double q1[4], + double q2[4], double q[4]) +{ + double qInv[4], qL[4], qR[4]; + vtkQuaternion::Inverse(q1,qInv); + vtkQuaternion::Product(qInv,q2,qL); + vtkQuaternion::Product(qInv,q0,qR); + + double qLLog[4], qRLog[4], qSum[4], qExp[4]; + vtkQuaternion::UnitLog(qL, qLLog); + vtkQuaternion::UnitLog(qR, qRLog); + vtkQuaternion::Add(qLLog,qRLog,qSum); + qSum[1] /= -4.0; + qSum[2] /= -4.0; + qSum[3] /= -4.0; + vtkQuaternion::UnitExp(qSum,qExp); + vtkQuaternion::Product(q1,qExp,q); +} + + +//---------------------------------------------------------------------------- +void vtkQuaternionInterpolator::InterpolateQuaternion(double t, double q[4]) +{ + // The quaternion may be clamped if it is outside the range specified + if ( t <= this->QuaternionList->front().Time ) + { + vtkQuaternion &Q = this->QuaternionList->front(); + q[0] = Q.Q[0]; q[1] = Q.Q[1]; q[2] = Q.Q[2]; q[3] = Q.Q[3]; + return; + } + + else if ( t >= this->QuaternionList->back().Time ) + { + vtkQuaternion &Q = this->QuaternionList->back(); + q[0] = Q.Q[0]; q[1] = Q.Q[1]; q[2] = Q.Q[2]; q[3] = Q.Q[3]; + return; + } + + // Depending on the interpolation type we do the right thing. + // The code above guarantees that there are at least two quaternions defined. + int numQuats = this->GetNumberOfQuaternions(); + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR || numQuats < 3 ) + { + QuaternionListIterator iter = this->QuaternionList->begin(); + QuaternionListIterator nextIter = iter + 1; + for ( ; nextIter != this->QuaternionList->end(); ++iter, ++nextIter) + { + if ( iter->Time <= t && t <= nextIter->Time ) + { + double T = (t - iter->Time) / (nextIter->Time - iter->Time); + this->Slerp(T,iter->Q,nextIter->Q,q); + break; + } + } + }//if linear quaternion interpolation + + else // this->InterpolationType == INTERPOLATION_TYPE_SPLINE + { + QuaternionListIterator iter = this->QuaternionList->begin(); + QuaternionListIterator nextIter = iter + 1; + QuaternionListIterator iter0, iter1, iter2, iter3; + + //find the interval + double T=0.0; + int i; + for (i=0; nextIter != this->QuaternionList->end(); ++iter, ++nextIter, ++i) + { + if ( iter->Time <= t && t <= nextIter->Time ) + { + T = (t - iter->Time) / (nextIter->Time - iter->Time); + break; + } + } + + double ai[4], bi[4], qc[4], qd[4]; + if ( i == 0 ) //initial interval + { + iter1 = iter; + iter2 = nextIter; + iter3 = nextIter + 1; + + ai[0] = iter1->QUnit[0]; //just duplicate first quaternion + ai[1] = iter1->QUnit[1]; + ai[2] = iter1->QUnit[2]; + ai[3] = iter1->QUnit[3]; + + this->InnerPoint(iter1->QUnit, iter2->QUnit, iter3->QUnit, bi); + } + else if ( i == (numQuats-2) ) //final interval + { + iter0 = iter - 1; + iter1 = iter; + iter2 = nextIter; + + this->InnerPoint(iter0->QUnit, iter1->QUnit, iter2->QUnit, ai); + + bi[0] = iter2->QUnit[0]; //just duplicate last quaternion + bi[1] = iter2->QUnit[1]; + bi[2] = iter2->QUnit[2]; + bi[3] = iter2->QUnit[3]; + } + else //in a middle interval somewhere + { + iter0 = iter - 1; + iter1 = iter; + iter2 = nextIter; + iter3 = nextIter + 1; + this->InnerPoint(iter0->QUnit, iter1->QUnit, iter2->QUnit, ai); + this->InnerPoint(iter1->QUnit, iter2->QUnit, iter3->QUnit, bi); + } + + // These three Slerp operations implement a Squad interpolation + this->Slerp(T,iter1->QUnit,iter2->QUnit,qc); + this->Slerp(T,ai,bi,qd); + this->Slerp(2.0*T*(1.0-T),qc,qd,q); + vtkQuaternion::UnitToVTK(q); + } + + return; +} + +//---------------------------------------------------------------------------- +void vtkQuaternionInterpolator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "There are " << this->GetNumberOfQuaternions() + << " quaternions to be interpolated\n"; + + os << indent << "Interpolation Type: " + << (this->InterpolationType == INTERPOLATION_TYPE_LINEAR ? + "Linear\n" : "Spline\n"); +} + + + diff --git a/Rendering/vtkQuaternionInterpolator.h b/Rendering/vtkQuaternionInterpolator.h new file mode 100644 index 0000000..4be7010 --- /dev/null +++ b/Rendering/vtkQuaternionInterpolator.h @@ -0,0 +1,148 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkQuaternionInterpolator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkQuaternionInterpolator - interpolate a quaternion +// .SECTION Description +// This class is used to interpolate a series of quaternions representing +// the rotations of a 3D object. The interpolation may be linear in form +// (using spherical linear interpolation SLERP), or via spline interpolation +// (using SQUAD). In either case the interpolation is specialized to +// quaternions since the interpolation occurs on the surface of the unit +// quaternion sphere. +// +// To use this class, specify at least two pairs of (t,q[4]) with the +// AddQuaternion() method. Next interpolate the tuples with the +// InterpolateQuaternion(t,q[4]) method, where "t" must be in the range of +// (t_min,t_max) parameter values specified by the AddQuaternion() method (t +// is clamped otherwise), and q[4] is filled in by the method. +// +// There are several important background references. Ken Shoemake described +// the practical application of quaternions for the interpolation of rotation +// (K. Shoemake, "Animating rotation with quaternion curves", Computer +// Graphics (Siggraph '85) 19(3):245--254, 1985). Another fine reference +// (available on-line) is E. B. Dam, M. Koch, and M. Lillholm, Technical +// Report DIKU-TR-98/5, Dept. of Computer Science, University of Copenhagen, +// Denmark. +// +// .SECTION Caveats +// Note that for two or less quaternions, Slerp (linear) interpolation is +// performed even if spline interpolation is requested. Also, the tangents to +// the first and last segments of spline interpolation are (arbitrarily) +// defined by repeating the first and last quaternions. +// +// There are several methods particular to quaternions (norms, products, +// etc.) implemented interior to this class. These may be moved to a separate +// quaternion class at some point. + + +#ifndef __vtkQuaternionInterpolator_h +#define __vtkQuaternionInterpolator_h + +#include "vtkObject.h" + +struct vtkQuaternion; +class vtkQuaternionList; + + +class VTK_RENDERING_EXPORT vtkQuaternionInterpolator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkQuaternionInterpolator, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the class. + static vtkQuaternionInterpolator* New(); + + // Description: + // Return the number of quaternions in the list of quaternions to be + // interpolated. + int GetNumberOfQuaternions(); + + // Description: + // Obtain some information about the interpolation range. The numbers + // returned (corresponding to parameter t, usually thought of as time) + // are undefined if the list of transforms is empty. This is a convenience + // method for interpolation. + double GetMinimumT(); + double GetMaximumT(); + + // Description: + // Reset the class so that it contains no data; i.e., the array of (t,q[4]) + // information is discarded. + void Initialize(); + + // Description: + // Add another quaternion to the list of quaternions to be interpolated. + // Note that using the same time t value more than once replaces the + // previous quaternion at t. At least one quaternions must be added to + // define an interpolation functios. + void AddQuaternion(double t, double q[4]); + + // Description: + // Delete the quaternion at a particular parameter t. If there is no + // quaternion tuple defined at t, then the method does nothing. + void RemoveQuaternion(double t); + + // Description: + // Interpolate the list of quaternions and determine a new quaternion + // (i.e., fill in the quaternion provided). If t is outside the range of + // (min,max) values, then t is clamped to lie within the range. + void InterpolateQuaternion(double t, double q[4]); + +//BTX + // Description: + // Enums to control the type of interpolation to use. + enum {INTERPOLATION_TYPE_LINEAR=0, + INTERPOLATION_TYPE_SPLINE + }; +//ETX + + // Description: + // Specify which type of function to use for interpolation. By default + // (SetInterpolationFunctionToSpline()), cubic spline interpolation using a + // modifed Kochanek basis is employed. Otherwise, if + // SetInterpolationFunctionToLinear() is invoked, linear spherical interpolation + // is used between each pair of quaternions. + vtkSetClampMacro(InterpolationType,int,INTERPOLATION_TYPE_LINEAR, + INTERPOLATION_TYPE_SPLINE); + vtkGetMacro(InterpolationType,int); + void SetInterpolationTypeToLinear() + {this->SetInterpolationType(INTERPOLATION_TYPE_LINEAR);} + void SetInterpolationTypeToSpline() + {this->SetInterpolationType(INTERPOLATION_TYPE_SPLINE);} + +protected: + vtkQuaternionInterpolator(); + virtual ~vtkQuaternionInterpolator(); + + // Specify the type of interpolation to use + int InterpolationType; + + // Internal variables for interpolation functions + vtkQuaternionList *QuaternionList; //used for linear quaternion interpolation + + // Internal method for spherical, linear interpolation + void Slerp(double t, double q0[4], double q1[4], double q[4]); + + // Internal methods supporting spline interpolation + static void InnerPoint(double q0[4], double q1[4], double q2[4], double q[4]); + +private: + vtkQuaternionInterpolator(const vtkQuaternionInterpolator&); // Not implemented. + void operator=(const vtkQuaternionInterpolator&); // Not implemented. + +}; + +#endif diff --git a/Rendering/vtkRenderWindow.cxx b/Rendering/vtkRenderWindow.cxx new file mode 100644 index 0000000..e41146d --- /dev/null +++ b/Rendering/vtkRenderWindow.cxx @@ -0,0 +1,1109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRenderWindow.h" + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkGraphicsFactory.h" +#include "vtkMath.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRendererCollection.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkRenderWindow, "$Revision: 1.144 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkRenderWindow); +//---------------------------------------------------------------------------- + +// Construct an instance of vtkRenderWindow with its screen size +// set to 300x300, borders turned on, positioned at (0,0), double +// buffering turned on, stereo capable off. +vtkRenderWindow::vtkRenderWindow() +{ + this->IsPicking = 0; + this->Borders = 1; + this->FullScreen = 0; + this->OldScreen[0] = this->OldScreen[1] = 0; + this->OldScreen[2] = this->OldScreen[3] = 300; + this->OldScreen[4] = 1; + this->DoubleBuffer = 1; + this->PointSmoothing = 0; + this->LineSmoothing = 0; + this->PolygonSmoothing = 0; + this->StereoRender = 0; + this->StereoType = VTK_STEREO_RED_BLUE; + this->StereoStatus = 0; + this->StereoCapableWindow = 0; + this->AlphaBitPlanes = 0; + this->Interactor = NULL; + this->AAFrames = 0; + this->FDFrames = 0; + this->SubFrames = 0; + this->AccumulationBuffer = NULL; + this->AccumulationBufferSize = 0; + this->CurrentSubFrame = 0; + this->DesiredUpdateRate = 0.0001; + this->ResultFrame = NULL; + this->SwapBuffers = 1; + this->AbortRender = 0; + this->InAbortCheck = 0; + this->InRender = 0; + this->NeverRendered = 1; + this->Renderers = vtkRendererCollection::New(); + this->NumberOfLayers = 1; + this->CurrentCursor = VTK_CURSOR_DEFAULT; + this->AnaglyphColorSaturation = 0.65; + this->AnaglyphColorMask[0] = 4; // red + this->AnaglyphColorMask[1] = 3; // cyan +} + +vtkRenderWindow::~vtkRenderWindow() +{ + this->SetInteractor(NULL); + + if (this->AccumulationBuffer) + { + delete [] this->AccumulationBuffer; + this->AccumulationBuffer = NULL; + this->AccumulationBufferSize = 0; + } + if (this->ResultFrame) + { + delete [] this->ResultFrame; + this->ResultFrame = NULL; + } + this->Renderers->Delete(); +} + +// return the correct type of RenderWindow +vtkRenderWindow *vtkRenderWindow::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkRenderWindow"); + return (vtkRenderWindow*)ret; +} + +// Create an interactor that will work with this renderer. +vtkRenderWindowInteractor *vtkRenderWindow::MakeRenderWindowInteractor() +{ + this->Interactor = vtkRenderWindowInteractor::New(); + this->Interactor->SetRenderWindow(this); + return this->Interactor; +} + +// Set the interactor that will work with this renderer. +void vtkRenderWindow::SetInteractor(vtkRenderWindowInteractor *rwi) +{ + if (this->Interactor != rwi) + { + // to avoid destructor recursion + vtkRenderWindowInteractor *temp = this->Interactor; + this->Interactor = rwi; + if (temp != NULL) {temp->UnRegister(this);} + if (this->Interactor != NULL) + { + this->Interactor->Register(this); + if (this->Interactor->GetRenderWindow() != this) + { + this->Interactor->SetRenderWindow(this); + } + } + } +} + +void vtkRenderWindow::SetSubFrames(int subFrames) +{ + if (this->SubFrames != subFrames) + { + this->SubFrames = subFrames; + if (this->CurrentSubFrame >= this->SubFrames) + { + this->CurrentSubFrame = 0; + } + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting SubFrames to " << subFrames); + this->Modified(); + } +} + +void vtkRenderWindow::SetDesiredUpdateRate(double rate) +{ + vtkRenderer *aren; + + if (this->DesiredUpdateRate != rate) + { + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (aren = this->Renderers->GetNextRenderer(rsit)); ) + { + aren->SetAllocatedRenderTime(1.0/ + (rate*this->Renderers->GetNumberOfItems())); + } + this->DesiredUpdateRate = rate; + this->Modified(); + } +} + + +// +// Set the variable that indicates that we want a stereo capable window +// be created. This method can only be called before a window is realized. +// +void vtkRenderWindow::SetStereoCapableWindow(int capable) +{ + if (this->StereoCapableWindow != capable) + { + this->StereoCapableWindow = capable; + this->Modified(); + } +} + +// Turn on stereo rendering +void vtkRenderWindow::SetStereoRender(int stereo) +{ + if (stereo == this->StereoRender) + { + return; + } + + if (this->StereoCapableWindow || + (!this->StereoCapableWindow + && this->StereoType != VTK_STEREO_CRYSTAL_EYES)) + { + if (stereo != this->StereoRender) + { + this->StereoRender = stereo; + this->Modified(); + } + } + else + { + vtkWarningMacro(<< "Adjusting stereo mode on a window that does not " + << "support stereo type " << this->GetStereoTypeAsString() + << " is not possible."); + } +} + + + +// Ask each renderer owned by this RenderWindow to render its image and +// synchronize this process. +void vtkRenderWindow::Render() +{ + int *size; + int x,y; + float *p1; + + // if we are in the middle of an abort check then return now + if (this->InAbortCheck) + { + return; + } + + // if we are in a render already from somewhere else abort now + if (this->InRender) + { + return; + } + + // reset the Abort flag + this->AbortRender = 0; + this->InRender = 1; + + vtkDebugMacro(<< "Starting Render Method.\n"); + this->InvokeEvent(vtkCommand::StartEvent,NULL); + + this->NeverRendered = 0; + + if ( this->Interactor && ! this->Interactor->GetInitialized() ) + { + this->Interactor->Initialize(); + } + + // if there is a reason for an AccumulationBuffer + if ( this->SubFrames || this->AAFrames || this->FDFrames) + { + // check the current size + size = this->GetSize(); + unsigned int bufferSize = 3*size[0]*size[1]; + // If there is not a buffer or the size is too small + // re-allocate it + if( !this->AccumulationBuffer + || bufferSize > this->AccumulationBufferSize) + { + // it is OK to delete null, no sense in two if's + delete [] this->AccumulationBuffer; + // Save the size of the buffer + this->AccumulationBufferSize = 3*size[0]*size[1]; + this->AccumulationBuffer = new float [this->AccumulationBufferSize]; + memset(this->AccumulationBuffer,0,this->AccumulationBufferSize*sizeof(float)); + } + } + + // handle any sub frames + if (this->SubFrames) + { + // get the size + size = this->GetSize(); + + // draw the images + this->DoAARender(); + + // now accumulate the images + if ((!this->AAFrames) && (!this->FDFrames)) + { + p1 = this->AccumulationBuffer; + unsigned char *p2; + unsigned char *p3; + if (this->ResultFrame) + { + p2 = this->ResultFrame; + } + else + { + p2 = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + } + p3 = p2; + for (y = 0; y < size[1]; y++) + { + for (x = 0; x < size[0]; x++) + { + *p1 += *p2; p1++; p2++; + *p1 += *p2; p1++; p2++; + *p1 += *p2; p1++; p2++; + } + } + delete [] p3; + } + + // if this is the last sub frame then convert back into unsigned char + this->CurrentSubFrame++; + if (this->CurrentSubFrame >= this->SubFrames) + { + double num; + unsigned char *p2 = new unsigned char [3*size[0]*size[1]]; + + num = this->SubFrames; + if (this->AAFrames) + { + num *= this->AAFrames; + } + if (this->FDFrames) + { + num *= this->FDFrames; + } + + this->ResultFrame = p2; + p1 = this->AccumulationBuffer; + for (y = 0; y < size[1]; y++) + { + for (x = 0; x < size[0]; x++) + { + *p2 = (unsigned char)(*p1/num); p1++; p2++; + *p2 = (unsigned char)(*p1/num); p1++; p2++; + *p2 = (unsigned char)(*p1/num); p1++; p2++; + } + } + + this->CurrentSubFrame = 0; + this->CopyResultFrame(); + + // free any memory + delete [] this->AccumulationBuffer; + this->AccumulationBuffer = NULL; + } + } + else // no subframes + { + // get the size + size = this->GetSize(); + + this->DoAARender(); + // if we had some accumulation occur + if (this->AccumulationBuffer) + { + double num; + unsigned char *p2 = new unsigned char [3*size[0]*size[1]]; + + if (this->AAFrames) + { + num = this->AAFrames; + } + else + { + num = 1; + } + if (this->FDFrames) + { + num *= this->FDFrames; + } + + this->ResultFrame = p2; + p1 = this->AccumulationBuffer; + for (y = 0; y < size[1]; y++) + { + for (x = 0; x < size[0]; x++) + { + *p2 = (unsigned char)(*p1/num); p1++; p2++; + *p2 = (unsigned char)(*p1/num); p1++; p2++; + *p2 = (unsigned char)(*p1/num); p1++; p2++; + } + } + + delete [] this->AccumulationBuffer; + this->AccumulationBuffer = NULL; + } + + this->CopyResultFrame(); + } + + if (this->ResultFrame) + { + delete [] this->ResultFrame; + this->ResultFrame = NULL; + } + + this->InRender = 0; + this->InvokeEvent(vtkCommand::EndEvent,NULL); +} + +// Handle rendering any antialiased frames. +void vtkRenderWindow::DoAARender() +{ + int i; + + // handle any anti aliasing + if (this->AAFrames) + { + int *size; + int x,y; + float *p1; + vtkRenderer *aren; + vtkCamera *acam; + double *dpoint; + double offsets[2]; + double origfocus[4]; + double worldOffset[3]; + + // get the size + size = this->GetSize(); + + origfocus[3] = 1.0; + + for (i = 0; i < this->AAFrames; i++) + { + // jitter the cameras + offsets[0] = vtkMath::Random() - 0.5; + offsets[1] = vtkMath::Random() - 0.5; + + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (aren = this->Renderers->GetNextRenderer(rsit)); ) + { + acam = aren->GetActiveCamera(); + + // calculate the amount to jitter + acam->GetFocalPoint(origfocus); + aren->SetWorldPoint(origfocus); + aren->WorldToDisplay(); + dpoint = aren->GetDisplayPoint(); + aren->SetDisplayPoint(dpoint[0] + offsets[0], + dpoint[1] + offsets[1], + dpoint[2]); + aren->DisplayToWorld(); + dpoint = aren->GetWorldPoint(); + dpoint[0] /= dpoint[3]; + dpoint[1] /= dpoint[3]; + dpoint[2] /= dpoint[3]; + acam->SetFocalPoint(dpoint); + + worldOffset[0] = dpoint[0] - origfocus[0]; + worldOffset[1] = dpoint[1] - origfocus[1]; + worldOffset[2] = dpoint[2] - origfocus[2]; + + acam->GetPosition(dpoint); + acam->SetPosition(dpoint[0]+worldOffset[0], + dpoint[1]+worldOffset[1], + dpoint[2]+worldOffset[2]); + } + + // draw the images + this->DoFDRender(); + + // restore the jitter to normal + for (this->Renderers->InitTraversal(rsit); + (aren = this->Renderers->GetNextRenderer(rsit)); ) + { + acam = aren->GetActiveCamera(); + + // calculate the amount to jitter + acam->GetFocalPoint(origfocus); + aren->SetWorldPoint(origfocus); + aren->WorldToDisplay(); + dpoint = aren->GetDisplayPoint(); + aren->SetDisplayPoint(dpoint[0] - offsets[0], + dpoint[1] - offsets[1], + dpoint[2]); + aren->DisplayToWorld(); + dpoint = aren->GetWorldPoint(); + dpoint[0] /= dpoint[3]; + dpoint[1] /= dpoint[3]; + dpoint[2] /= dpoint[3]; + acam->SetFocalPoint(dpoint); + + worldOffset[0] = dpoint[0] - origfocus[0]; + worldOffset[1] = dpoint[1] - origfocus[1]; + worldOffset[2] = dpoint[2] - origfocus[2]; + + acam->GetPosition(dpoint); + acam->SetPosition(dpoint[0]+worldOffset[0], + dpoint[1]+worldOffset[1], + dpoint[2]+worldOffset[2]); + } + + + // now accumulate the images + p1 = this->AccumulationBuffer; + if (!this->FDFrames) + { + unsigned char *p2; + unsigned char *p3; + if (this->ResultFrame) + { + p2 = this->ResultFrame; + } + else + { + p2 = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + } + p3 = p2; + for (y = 0; y < size[1]; y++) + { + for (x = 0; x < size[0]; x++) + { + *p1 += (float)*p2; p1++; p2++; + *p1 += (float)*p2; p1++; p2++; + *p1 += (float)*p2; p1++; p2++; + } + } + delete [] p3; + } + } + } + else + { + this->DoFDRender(); + } +} + + +// Handle rendering any focal depth frames. +void vtkRenderWindow::DoFDRender() +{ + int i; + + // handle any focal depth + if (this->FDFrames) + { + int *size; + int x,y; + unsigned char *p2; + unsigned char *p3; + float *p1; + vtkRenderer *aren; + vtkCamera *acam; + double focalDisk; + double *vpn, *dpoint; + double vec[3]; + vtkTransform *aTrans = vtkTransform::New(); + double offsets[2]; + double *orig; + vtkCollectionSimpleIterator rsit; + + // get the size + size = this->GetSize(); + + orig = new double [3*this->Renderers->GetNumberOfItems()]; + + for (i = 0; i < this->FDFrames; i++) + { + int j = 0; + + offsets[0] = vtkMath::Random(); // radius + offsets[1] = vtkMath::Random()*360.0; // angle + + // store offsets for each renderer + for (this->Renderers->InitTraversal(rsit); + (aren = this->Renderers->GetNextRenderer(rsit)); ) + { + acam = aren->GetActiveCamera(); + focalDisk = acam->GetFocalDisk()*offsets[0]; + + vpn = acam->GetViewPlaneNormal(); + aTrans->Identity(); + aTrans->Scale(focalDisk,focalDisk,focalDisk); + aTrans->RotateWXYZ(-offsets[1],vpn[0],vpn[1],vpn[2]); + aTrans->TransformVector(acam->GetViewUp(),vec); + + dpoint = acam->GetPosition(); + + // store the position for later + memcpy(orig + j*3,dpoint,3 * sizeof (double)); + j++; + + acam->SetPosition(dpoint[0]+vec[0], + dpoint[1]+vec[1], + dpoint[2]+vec[2]); + } + + // draw the images + this->DoStereoRender(); + + // restore the jitter to normal + j = 0; + for (this->Renderers->InitTraversal(rsit); + (aren = this->Renderers->GetNextRenderer(rsit)); ) + { + acam = aren->GetActiveCamera(); + acam->SetPosition(orig + j*3); + j++; + } + + // get the pixels for accumulation + // now accumulate the images + p1 = this->AccumulationBuffer; + if (this->ResultFrame) + { + p2 = this->ResultFrame; + } + else + { + p2 = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + } + p3 = p2; + for (y = 0; y < size[1]; y++) + { + for (x = 0; x < size[0]; x++) + { + *p1 += (float)*p2; p1++; p2++; + *p1 += (float)*p2; p1++; p2++; + *p1 += (float)*p2; p1++; p2++; + } + } + delete [] p3; + } + + // free memory + delete [] orig; + aTrans->Delete(); + } + else + { + this->DoStereoRender(); + } +} + + +// Handle rendering the two different views for stereo rendering. +void vtkRenderWindow::DoStereoRender() +{ + this->Start(); + this->StereoUpdate(); + if (this->StereoType != VTK_STEREO_RIGHT) + { // render the left eye + this->Renderers->Render(); + } + + if (this->StereoRender) + { + this->StereoMidpoint(); + if (this->StereoType != VTK_STEREO_LEFT) + { // render the right eye + this->Renderers->Render(); + } + this->StereoRenderComplete(); + } +} + +// Add a renderer to the list of renderers. +void vtkRenderWindow::AddRenderer(vtkRenderer *ren) +{ + if (this->HasRenderer(ren)) + { + return; + } + // we are its parent + this->MakeCurrent(); + ren->SetRenderWindow(this); + this->Renderers->AddItem(ren); + vtkRenderer *aren; + vtkCollectionSimpleIterator rsit; + + for (this->Renderers->InitTraversal(rsit); + (aren = this->Renderers->GetNextRenderer(rsit)); ) + { + aren->SetAllocatedRenderTime + (1.0/(this->DesiredUpdateRate*this->Renderers->GetNumberOfItems())); + } +} + +// Remove a renderer from the list of renderers. +void vtkRenderWindow::RemoveRenderer(vtkRenderer *ren) +{ + // we are its parent + this->Renderers->RemoveItem(ren); +} + +int vtkRenderWindow::HasRenderer(vtkRenderer *ren) +{ + return (ren && this->Renderers->IsItemPresent(ren)); +} + +int vtkRenderWindow::CheckAbortStatus() +{ + if (!this->InAbortCheck) + { + this->InAbortCheck = 1; + this->InvokeEvent(vtkCommand::AbortCheckEvent,NULL); + this->InAbortCheck = 0; + } + return this->AbortRender; +} + +void vtkRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Borders: " << (this->Borders ? "On\n":"Off\n"); + os << indent << "IsPicking: " << (this->IsPicking ? "On\n":"Off\n"); + os << indent << "Double Buffer: " << (this->DoubleBuffer ? "On\n":"Off\n"); + os << indent << "Full Screen: " << (this->FullScreen ? "On\n":"Off\n"); + os << indent << "Renderers:\n"; + this->Renderers->PrintSelf(os,indent.GetNextIndent()); + os << indent << "Stereo Capable Window Requested: " + << (this->StereoCapableWindow ? "Yes\n":"No\n"); + os << indent << "Stereo Render: " + << (this->StereoRender ? "On\n":"Off\n"); + + os << indent << "Point Smoothing: " + << (this->PointSmoothing ? "On\n":"Off\n"); + os << indent << "Line Smoothing: " + << (this->LineSmoothing ? "On\n":"Off\n"); + os << indent << "Polygon Smoothing: " + << (this->PolygonSmoothing ? "On\n":"Off\n"); + os << indent << "Anti Aliased Frames: " << this->AAFrames << "\n"; + os << indent << "Abort Render: " << this->AbortRender << "\n"; + os << indent << "Current Cursor: " << this->CurrentCursor << "\n"; + os << indent << "Desired Update Rate: " << this->DesiredUpdateRate << "\n"; + os << indent << "Focal Depth Frames: " << this->FDFrames << "\n"; + os << indent << "In Abort Check: " << this->InAbortCheck << "\n"; + os << indent << "NeverRendered: " << this->NeverRendered << "\n"; + os << indent << "Interactor: " << this->Interactor << "\n"; + os << indent << "Motion Blur Frames: " << this->SubFrames << "\n"; + os << indent << "Swap Buffers: " << (this->SwapBuffers ? "On\n":"Off\n"); + os << indent << "Stereo Type: " << this->GetStereoTypeAsString() << "\n"; + os << indent << "Number of Layers: " << this->NumberOfLayers << "\n"; + os << indent << "AccumulationBuffer Size " << this->AccumulationBufferSize << "\n"; + os << indent << "AlphaBitPlanes: " << (this->AlphaBitPlanes ? "On" : "Off") + << endl; + + os << indent << "AnaglyphColorSaturation: " + << this->AnaglyphColorSaturation << "\n"; + os << indent << "AnaglyphColorMask: " + << this->AnaglyphColorMask[0] << " , " + << this->AnaglyphColorMask[1] << "\n"; +} + + +// Update the system, if needed, due to stereo rendering. For some stereo +// methods, subclasses might need to switch some hardware settings here. +void vtkRenderWindow::StereoUpdate(void) +{ + // if stereo is on and it wasn't before + if (this->StereoRender && (!this->StereoStatus)) + { + switch (this->StereoType) + { + case VTK_STEREO_RED_BLUE: + this->StereoStatus = 1; + break; + case VTK_STEREO_ANAGLYPH: + this->StereoStatus = 1; + break; + case VTK_STEREO_DRESDEN: + this->StereoStatus = 1; + break; + case VTK_STEREO_INTERLACED: + this->StereoStatus = 1; + } + } + else if ((!this->StereoRender) && this->StereoStatus) + { + switch (this->StereoType) + { + case VTK_STEREO_RED_BLUE: + this->StereoStatus = 0; + break; + case VTK_STEREO_ANAGLYPH: + this->StereoStatus = 0; + break; + case VTK_STEREO_DRESDEN: + this->StereoStatus = 0; + break; + case VTK_STEREO_INTERLACED: + this->StereoStatus = 0; + break; + } + } +} + +// Intermediate method performs operations required between the rendering +// of the left and right eye. +void vtkRenderWindow::StereoMidpoint(void) +{ + vtkRenderer * aren; + /* For IceT stereo */ + for (Renderers->InitTraversal() ; (aren = Renderers->GetNextItem()) ; ) + { + aren->StereoMidpoint(); + } + if ((this->StereoType == VTK_STEREO_RED_BLUE) || + (this->StereoType == VTK_STEREO_INTERLACED) || + (this->StereoType == VTK_STEREO_DRESDEN) || + (this->StereoType == VTK_STEREO_ANAGLYPH)) + { + int *size; + // get the size + size = this->GetSize(); + // get the data + this->StereoBuffer = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + } +} + +// Handles work required once both views have been rendered when using +// stereo rendering. +void vtkRenderWindow::StereoRenderComplete(void) +{ + switch (this->StereoType) + { + case VTK_STEREO_RED_BLUE: + { + unsigned char *buff; + unsigned char *p1, *p2, *p3; + unsigned char* result; + int *size; + int x,y; + int res; + + // get the size + size = this->GetSize(); + // get the data + buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + p1 = this->StereoBuffer; + p2 = buff; + + // allocate the result + result = new unsigned char [size[0]*size[1]*3]; + if (!result) + { + vtkErrorMacro(<<"Couldn't allocate memory for RED BLUE stereo."); + return; + } + p3 = result; + + // now merge the two images + for (x = 0; x < size[0]; x++) + { + for (y = 0; y < size[1]; y++) + { + res = p1[0] + p1[1] + p1[2]; + p3[0] = res/3; + res = p2[0] + p2[1] + p2[2]; + p3[1] = 0; + p3[2] = res/3; + + p1 += 3; + p2 += 3; + p3 += 3; + } + } + this->ResultFrame = result; + delete [] this->StereoBuffer; + this->StereoBuffer = NULL; + delete [] buff; + } + break; + case VTK_STEREO_ANAGLYPH: + { + unsigned char *buff; + unsigned char *p0, *p1, *p2; + unsigned char* result; + int *size; + int x,y; + int m0, m1, ave0, ave1; + int avecolor[256][3], satcolor[256]; + float a; + + // get the size + size = this->GetSize(); + // get the data + buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + p0 = this->StereoBuffer; + p1 = buff; + + // allocate the result + result = new unsigned char [size[0]*size[1]*3]; + if (!result) + { + vtkErrorMacro(<<"Couldn't allocate memory for ANAGLYPH stereo."); + return; + } + p2 = result; + + // build some tables + a = this->AnaglyphColorSaturation; + m0 = this->AnaglyphColorMask[0]; + m1 = this->AnaglyphColorMask[1]; + + for(x = 0; x < 256; x++) + { + avecolor[x][0] = int((1.0-a)*x*0.3086); + avecolor[x][1] = int((1.0-a)*x*0.6094); + avecolor[x][2] = int((1.0-a)*x*0.0820); + + satcolor[x] = int(a*x); + } + + // now merge the two images + for (x = 0; x < size[0]; x++) + { + for (y = 0; y < size[1]; y++) + { + ave0 = avecolor[p0[0]][0] + avecolor[p0[1]][1] + avecolor[p0[2]][2]; + ave1 = avecolor[p1[0]][0] + avecolor[p1[1]][1] + avecolor[p1[2]][2]; + if (m0 & 0x4) + { + p2[0] = satcolor[p0[0]] + ave0; + } + if (m0 & 0x2) + { + p2[1] = satcolor[p0[1]] + ave0; + } + if (m0 & 0x1) + { + p2[2] = satcolor[p0[2]] + ave0; + } + if (m1 & 0x4) + { + p2[0] = satcolor[p1[0]] + ave1; + } + if (m1 & 0x2) + { + p2[1] = satcolor[p1[1]] + ave1; + } + if (m1 & 0x1) + { + p2[2] = satcolor[p1[2]] + ave1; + } + p0 += 3; + p1 += 3; + p2 += 3; + } + } + this->ResultFrame = result; + delete [] this->StereoBuffer; + this->StereoBuffer = NULL; + delete [] buff; + } + break; + case VTK_STEREO_INTERLACED: + { + unsigned char *buff; + unsigned char *p1, *p2, *p3; + unsigned char* result; + int *size, line; + int x,y; + + // get the size + size = this->GetSize(); + // get the data + buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + p1 = this->StereoBuffer; + p2 = buff; + line = size[0] * 3; + + // allocate the result + result = new unsigned char [size[0]*size[1]*3]; + if (!result) + { + vtkErrorMacro(<<"Couldn't allocate memory for interlaced stereo."); + return; + } + + // now merge the two images + p3 = result; + for (y = 0; y < size[1]; y += 2) + { + for (x = 0; x < size[0]; x++) + { + *p3++ = *p1++; + *p3++ = *p1++; + *p3++ = *p1++; + } + // skip a line + p3 += line; + p1 += line; + } + // now the other eye + p3 = result + line; + p2 += line; + for (y = 1; y < size[1]; y += 2) + { + for (x = 0; x < size[0]; x++) + { + *p3++ = *p2++; + *p3++ = *p2++; + *p3++ = *p2++; + } + // skip a line + p3 += line; + p2 += line; + } + + this->ResultFrame = result; + delete [] this->StereoBuffer; + this->StereoBuffer = NULL; + delete [] buff; + } + break; + + case VTK_STEREO_DRESDEN: + { + unsigned char *buff; + unsigned char *p1, *p2, *p3; + unsigned char* result; + int *size; + int x,y; + + // get the size + size = this->GetSize(); + // get the data + buff = this->GetPixelData(0,0,size[0]-1,size[1]-1,!this->DoubleBuffer); + p1 = this->StereoBuffer; + p2 = buff; + + // allocate the result + result = new unsigned char [size[0]*size[1]*3]; + if (!result) + { + vtkErrorMacro( + <<"Couldn't allocate memory for dresden display stereo."); + return; + } + + // now merge the two images + p3 = result; + + for (y = 0; y < size[1]; y++ ) + { + for (x = 0; x < size[0]; x+=2) + { + *p3++ = *p1++; + *p3++ = *p1++; + *p3++ = *p1++; + + p3+=3; + p1+=3; + } + if( size[0] % 2 == 1 ) + { + p3 -= 3; + p1 -= 3; + } + } + + // now the other eye + p3 = result + 3; + p2 += 3; + + for (y = 0; y < size[1]; y++) + { + for (x = 1; x < size[0]; x+=2) + { + *p3++ = *p2++; + *p3++ = *p2++; + *p3++ = *p2++; + + p3+=3; + p2+=3; + } + if( size[0] % 2 == 1 ) + { + p3 += 3; + p2 += 3; + } + } + + this->ResultFrame = result; + delete [] this->StereoBuffer; + this->StereoBuffer = NULL; + delete [] buff; + } + break; + } +} + + +void vtkRenderWindow::CopyResultFrame(void) +{ + if (this->ResultFrame) + { + int *size; + + // get the size + size = this->GetSize(); + this->SetPixelData(0,0,size[0]-1,size[1]-1,this->ResultFrame,!this->DoubleBuffer); + } + + this->Frame(); +} + + +// treat renderWindow and interactor as one object. +// it might be easier if the GetReference count method were redefined. +void vtkRenderWindow::UnRegister(vtkObjectBase *o) +{ + if (this->Interactor && this->Interactor->GetRenderWindow() == this && + this->Interactor != o) + { + if (this->GetReferenceCount() + this->Interactor->GetReferenceCount() == 3) + { + this->vtkObject::UnRegister(o); + vtkRenderWindowInteractor *tmp = this->Interactor; + tmp->Register(0); + this->Interactor->SetRenderWindow(NULL); + tmp->UnRegister(0); + return; + } + } + + this->vtkObject::UnRegister(o); +} + +const char *vtkRenderWindow::GetRenderLibrary() +{ + return vtkGraphicsFactory::GetRenderLibrary(); +} diff --git a/Rendering/vtkRenderWindow.h b/Rendering/vtkRenderWindow.h new file mode 100644 index 0000000..ec29e35 --- /dev/null +++ b/Rendering/vtkRenderWindow.h @@ -0,0 +1,525 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRenderWindow - create a window for renderers to draw into +// .SECTION Description +// vtkRenderWindow is an abstract object to specify the behavior of a +// rendering window. A rendering window is a window in a graphical user +// interface where renderers draw their images. Methods are provided to +// synchronize the rendering process, set window size, and control double +// buffering. The window also allows rendering in stereo. The interlaced +// render stereo type is for output to a VRex stereo projector. All of the +// odd horizontal lines are from the left eye, and the even lines are from +// the right eye. The user has to make the render window aligned with the +// VRex projector, or the eye will be swapped. + +// .SECTION Caveats +// In VTK versions 4 and later, the vtkWindowToImageFilter class is +// part of the canonical way to output an image of a window to a file +// (replacing the obsolete SaveImageAsPPM method for vtkRenderWindows +// that existed in 3.2 and earlier). Connect one of these filters to +// the output of the window, and filter's output to a writer such as +// vtkPNGWriter. + +// .SECTION see also +// vtkRenderer vtkRenderWindowInteractor vtkWindowToImageFilter + +#ifndef __vtkRenderWindow_h +#define __vtkRenderWindow_h + +#include "vtkWindow.h" + +class vtkFloatArray; +class vtkRenderWindowInteractor; +class vtkRenderer; +class vtkRendererCollection; +class vtkUnsignedCharArray; + +// lets define the different types of stereo +#define VTK_STEREO_CRYSTAL_EYES 1 +#define VTK_STEREO_RED_BLUE 2 +#define VTK_STEREO_INTERLACED 3 +#define VTK_STEREO_LEFT 4 +#define VTK_STEREO_RIGHT 5 +#define VTK_STEREO_DRESDEN 6 +#define VTK_STEREO_ANAGLYPH 7 + +#define VTK_CURSOR_DEFAULT 0 +#define VTK_CURSOR_ARROW 1 +#define VTK_CURSOR_SIZENE 2 +#define VTK_CURSOR_SIZENW 3 +#define VTK_CURSOR_SIZESW 4 +#define VTK_CURSOR_SIZESE 5 +#define VTK_CURSOR_SIZENS 6 +#define VTK_CURSOR_SIZEWE 7 +#define VTK_CURSOR_SIZEALL 8 +#define VTK_CURSOR_HAND 9 + +class VTK_RENDERING_EXPORT vtkRenderWindow : public vtkWindow +{ +public: + vtkTypeRevisionMacro(vtkRenderWindow,vtkWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Construct an instance of vtkRenderWindow with its screen size + // set to 300x300, borders turned on, positioned at (0,0), double + // buffering turned on. + static vtkRenderWindow *New(); + + // Description: + // Add a renderer to the list of renderers. + virtual void AddRenderer(vtkRenderer *); + + // Description: + // Remove a renderer from the list of renderers. + void RemoveRenderer(vtkRenderer *); + + // Description: + // Query if a renderer is in the list of renderers. + int HasRenderer(vtkRenderer *); + + // Description: + // What rendering library has the user requested + static const char *GetRenderLibrary(); + + // Description: + // Return the collection of renderers in the render window. + vtkRendererCollection *GetRenderers() {return this->Renderers;}; + + // Description: + // Ask each renderer owned by this RenderWindow to render its image and + // synchronize this process. + virtual void Render(); + + // Description: + // Initialize the rendering process. + virtual void Start() = 0; + + // Description: + // Finalize the rendering process. + virtual void Finalize() = 0; + + // Description: + // A termination method performed at the end of the rendering process + // to do things like swapping buffers (if necessary) or similar actions. + virtual void Frame() = 0; + + // Description: + // Performed at the end of the rendering process to generate image. + // This is typically done right before swapping buffers. + virtual void CopyResultFrame(); + + // Description: + // Create an interactor to control renderers in this window. We need + // to know what type of interactor to create, because we might be in + // X Windows or MS Windows. + virtual vtkRenderWindowInteractor *MakeRenderWindowInteractor(); + + // Description: + // Hide or Show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + // Set cursor position in window (note that (0,0) is the lower left + // corner). + virtual void HideCursor() = 0; + virtual void ShowCursor() = 0; + virtual void SetCursorPosition(int , int ) {}; + + // Description: + // Change the shape of the cursor + vtkSetMacro(CurrentCursor,int); + vtkGetMacro(CurrentCursor,int); + + // Description: + // Turn on/off rendering full screen window size. + virtual void SetFullScreen(int) = 0; + vtkGetMacro(FullScreen,int); + vtkBooleanMacro(FullScreen,int); + + // Description: + // Turn on/off window manager borders. Typically, you shouldn't turn the + // borders off, because that bypasses the window manager and can cause + // undesirable behavior. + vtkSetMacro(Borders,int); + vtkGetMacro(Borders,int); + vtkBooleanMacro(Borders,int); + + // Description: + // Prescribe that the window be created in a stereo-capable mode. This + // method must be called before the window is realized. Default is off. + vtkGetMacro(StereoCapableWindow,int); + vtkBooleanMacro(StereoCapableWindow,int); + virtual void SetStereoCapableWindow(int capable); + + // Description: + // Turn on/off stereo rendering. + vtkGetMacro(StereoRender,int); + void SetStereoRender(int stereo); + vtkBooleanMacro(StereoRender,int); + + // Description: + // Turn on/off the use of alpha bitplanes. + vtkSetMacro(AlphaBitPlanes, int); + vtkGetMacro(AlphaBitPlanes, int); + vtkBooleanMacro(AlphaBitPlanes, int); + + // Description: + // Turn on/off point smoothing. Default is off. + // This must be applied before the first Render. + vtkSetMacro(PointSmoothing,int); + vtkGetMacro(PointSmoothing,int); + vtkBooleanMacro(PointSmoothing,int); + + // Description: + // Turn on/off line smoothing. Default is off. + // This must be applied before the first Render. + vtkSetMacro(LineSmoothing,int); + vtkGetMacro(LineSmoothing,int); + vtkBooleanMacro(LineSmoothing,int); + + // Description: + // Turn on/off polygon smoothing. Default is off. + // This must be applied before the first Render. + vtkSetMacro(PolygonSmoothing,int); + vtkGetMacro(PolygonSmoothing,int); + vtkBooleanMacro(PolygonSmoothing,int); + + // Description: + // Set/Get what type of stereo rendering to use. CrystalEyes + // mode uses frame-sequential capabilities available in OpenGL + // to drive LCD shutter glasses and stereo projectors. RedBlue + // mode is a simple type of stereo for use with red-blue glasses. + // Anaglyph mode is a superset of RedBlue mode, but the color + // output channels can be configured using the AnaglyphColorMask + // and the color of the original image can be (somewhat) maintained + // using AnaglyphColorSaturation; the default colors for Anaglyph + // mode is red-cyan. Interlaced stereo mode produces a composite + // image where horizontal lines alternate between left and right + // views. StereoLeft and StereoRight modes choose one or the other + // stereo view. Dresden mode is yet another stereoscopic + // interleaving. + vtkGetMacro(StereoType,int); + vtkSetMacro(StereoType,int); + void SetStereoTypeToCrystalEyes() + {this->SetStereoType(VTK_STEREO_CRYSTAL_EYES);}; + void SetStereoTypeToRedBlue() + {this->SetStereoType(VTK_STEREO_RED_BLUE);}; + void SetStereoTypeToInterlaced() + {this->SetStereoType(VTK_STEREO_INTERLACED);}; + void SetStereoTypeToLeft() + {this->SetStereoType(VTK_STEREO_LEFT);}; + void SetStereoTypeToRight() + {this->SetStereoType(VTK_STEREO_RIGHT);}; + void SetStereoTypeToDresden() + {this->SetStereoType(VTK_STEREO_DRESDEN);}; + void SetStereoTypeToAnaglyph() + {this->SetStereoType(VTK_STEREO_ANAGLYPH);}; + char *GetStereoTypeAsString(); + + // Description: + // Update the system, if needed, due to stereo rendering. For some stereo + // methods, subclasses might need to switch some hardware settings here. + virtual void StereoUpdate(); + + // Description: + // Intermediate method performs operations required between the rendering + // of the left and right eye. + virtual void StereoMidpoint(); + + // Description: + // Handles work required once both views have been rendered when using + // stereo rendering. + virtual void StereoRenderComplete(); + + //Description: + // Set/get the anaglyph color saturation factor. This number ranges from + // 0.0 to 1.0: 0.0 means that no color from the original object is + // maintained, 1.0 means all of the color is maintained. The default + // value is 0.65. Too much saturation can produce uncomfortable 3D + // viewing because anaglyphs also use color to encode 3D. + vtkSetClampMacro(AnaglyphColorSaturation,float, 0.0, 1.0); + vtkGetMacro(AnaglyphColorSaturation,float); + + //Description: + // Set/get the anaglyph color mask values. These two numbers are bits + // mask that control which color channels of the original stereo + // images are used to produce the final anaglyph image. The first + // value is the color mask for the left view, the second the mask + // for the right view. If a bit in the mask is on for a particular + // color for a view, that color is passed on to the final view; if + // it is not set, that channel for that view is ignored. + // The bits are arranged as r, g, and b, so r = 4, g = 2, and b = 1. + // By default, the first value (the left view) is set to 4, and the + // second value is set to 3. That means that the red output channel + // comes from the left view, and the green and blue values come from + // the right view. + vtkSetVector2Macro(AnaglyphColorMask,int); + vtkGetVectorMacro(AnaglyphColorMask,int,2); + + // Description: + // Remap the rendering window. This probably only works on UNIX right now. + // It is useful for changing properties that can't normally be changed + // once the window is up. + virtual void WindowRemap() = 0; + + // Description: + // Turn on/off buffer swapping between images. + vtkSetMacro(SwapBuffers,int); + vtkGetMacro(SwapBuffers,int); + vtkBooleanMacro(SwapBuffers,int); + + // Description: + // Set/Get the pixel data of an image, transmitted as RGBRGBRGB. The + // front argument indicates if the front buffer should be used or the back + // buffer. It is the caller's responsibility to delete the resulting + // array. It is very important to realize that the memory in this array + // is organized from the bottom of the window to the top. The origin + // of the screen is in the lower left corner. The y axis increases as + // you go up the screen. So the storage of pixels is from left to right + // and from bottom to top. + virtual int SetPixelData(int, int, int, int, unsigned char *,int) = 0; + virtual int SetPixelData(int, int, int, int, vtkUnsignedCharArray*, + int ) = 0; + + // Description: + // Same as Get/SetPixelData except that the image also contains an alpha + // component. The image is transmitted as RGBARGBARGBA... each of which is a + // float value. The "blend" parameter controls whether the SetRGBAPixelData + // method blends the data with the previous contents of the frame buffer + // or completely replaces the frame buffer data. + virtual float *GetRGBAPixelData(int ,int ,int ,int ,int ) = 0; + virtual int GetRGBAPixelData(int, int, int, int, int, vtkFloatArray* ) = 0; + virtual int SetRGBAPixelData(int ,int ,int ,int ,float *,int, + int blend=0) = 0; + virtual int SetRGBAPixelData(int, int, int, int, vtkFloatArray*, + int, int blend=0) = 0; + virtual void ReleaseRGBAPixelData(float *data)=0; + virtual unsigned char *GetRGBACharPixelData(int ,int ,int ,int ,int ) = 0; + virtual int GetRGBACharPixelData(int ,int, int, int, int, + vtkUnsignedCharArray*) = 0; + virtual int SetRGBACharPixelData(int ,int ,int ,int ,unsigned char *, int, + int blend=0) = 0; + virtual int SetRGBACharPixelData(int, int, int, int, + vtkUnsignedCharArray *, + int, int blend=0) = 0; + + // Description: + // Set/Get the zbuffer data from the frame buffer. + virtual float *GetZbufferData(int, int, int, int ) = 0; + virtual int GetZbufferData( int, int, int, int, float*) = 0; + virtual int GetZbufferData( int, int, int, int, vtkFloatArray*) = 0; + virtual int SetZbufferData(int, int, int, int, float *) = 0; + virtual int SetZbufferData( int, int, int, int, vtkFloatArray * ) = 0; + + // Description: + // Set the number of frames for doing antialiasing. The default is + // zero. Typically five or six will yield reasonable results without + // taking too long. + vtkGetMacro(AAFrames,int); + vtkSetMacro(AAFrames,int); + + // Description: + // Set the number of frames for doing focal depth. The default is zero. + // Depending on how your scene is organized you can get away with as + // few as four frames for focal depth or you might need thirty. + // One thing to note is that if you are using focal depth frames, + // then you will not need many (if any) frames for antialiasing. + vtkGetMacro(FDFrames,int); + vtkSetMacro(FDFrames,int); + + // Description: + // Set the number of sub frames for doing motion blur. The default is zero. + // Once this is set greater than one, you will no longer see a new frame + // for every Render(). If you set this to five, you will need to do + // five Render() invocations before seeing the result. This isn't + // very impressive unless something is changing between the Renders. + // Changing this value may reset the current subframe count. + vtkGetMacro(SubFrames,int); + virtual void SetSubFrames(int subFrames); + + // Description: + // This flag is set if the window hasn't rendered since it was created + vtkGetMacro(NeverRendered,int); + + // Description: + // This is a flag that can be set to interrupt a rendering that is in + // progress. + vtkGetMacro(AbortRender,int); + vtkSetMacro(AbortRender,int); + vtkGetMacro(InAbortCheck,int); + vtkSetMacro(InAbortCheck,int); + virtual int CheckAbortStatus(); + + vtkGetMacro(IsPicking,int); + vtkSetMacro(IsPicking,int); + vtkBooleanMacro(IsPicking,int); + + // Description: + // Check to see if a mouse button has been pressed. All other events + // are ignored by this method. Ideally, you want to abort the render + // on any event which causes the DesiredUpdateRate to switch from + // a high-quality rate to a more interactive rate. + virtual int GetEventPending() = 0; + + // Description: + // Are we rendering at the moment + virtual int CheckInRenderStatus() { return this->InRender; } + + // Description: + // Clear status (after an exception was thrown for example) + virtual void ClearInRenderStatus() { this->InRender = 0; } + + // Description: + // Set/Get the desired update rate. This is used with + // the vtkLODActor class. When using level of detail actors you + // need to specify what update rate you require. The LODActors then + // will pick the correct resolution to meet your desired update rate + // in frames per second. A value of zero indicates that they can use + // all the time they want to. + virtual void SetDesiredUpdateRate(double); + vtkGetMacro(DesiredUpdateRate,double); + + // Description: + // Get the number of layers for renderers. Each renderer should have + // its layer set individually. Some algorithms iterate through all layers, + // so it is not wise to set the number of layers to be exorbitantly large + // (say bigger than 100). + vtkGetMacro(NumberOfLayers, int); + vtkSetClampMacro(NumberOfLayers, int, 1, VTK_LARGE_INTEGER); + + // Description: + // Get the interactor associated with this render window + vtkGetObjectMacro(Interactor,vtkRenderWindowInteractor); + + // Description: + // Set the interactor to the render window + void SetInteractor(vtkRenderWindowInteractor *); + + // Description: + // This Method detects loops of RenderWindow<->Interactor, + // so objects are freed properly. + virtual void UnRegister(vtkObjectBase *o); + + // Description: + // Dummy stubs for vtkWindow API. + virtual void SetDisplayId(void *) = 0; + virtual void SetWindowId(void *) = 0; + virtual void SetNextWindowId(void *) = 0; + virtual void SetParentId(void *) = 0; + virtual void *GetGenericDisplayId() = 0; + virtual void *GetGenericWindowId() = 0; + virtual void *GetGenericParentId() = 0; + virtual void *GetGenericContext() = 0; + virtual void *GetGenericDrawable() = 0; + virtual void SetWindowInfo(char *) = 0; + virtual void SetNextWindowInfo(char *) = 0; + virtual void SetParentInfo(char *) = 0; + + // Description: + // Make this the current window. + virtual void MakeCurrent() = 0; + + // Description: + // If called, allow MakeCurrent() to skip cache-check when called. + // MakeCurrent() reverts to original behavior of cache-checking + // on the next render. + virtual void SetForceMakeCurrent() {}; + + // Description: + // Get report of capabilities for the render window + virtual const char *ReportCapabilities() { return "Not Implemented";}; + + // Description: + // Does this render window support OpenGL? 0-false, 1-true + virtual int SupportsOpenGL() { return 0;}; + + // Description: + // Is this render window using hardware acceleration? 0-false, 1-true + virtual int IsDirect() { return 0;}; + + // Description: + // This method should be defined by the subclass. How many bits of + // precision are there in the zbuffer? + virtual int GetDepthBufferSize() = 0; + +protected: + vtkRenderWindow(); + ~vtkRenderWindow(); + + virtual void DoStereoRender(); + virtual void DoFDRender(); + virtual void DoAARender(); + + vtkRendererCollection *Renderers; + int Borders; + int FullScreen; + int OldScreen[5]; + int PointSmoothing; + int LineSmoothing; + int PolygonSmoothing; + int StereoRender; + int StereoType; + int StereoStatus; // used for keeping track of what's going on + int StereoCapableWindow; + int AlphaBitPlanes; + vtkRenderWindowInteractor *Interactor; + unsigned char* StereoBuffer; // used for red blue stereo + float *AccumulationBuffer; // used for many techniques + unsigned int AccumulationBufferSize; + int AAFrames; + int FDFrames; + int SubFrames; // number of sub frames + int CurrentSubFrame; // what one are we on + unsigned char *ResultFrame; // used for any non immediate rendering + int SwapBuffers; + double DesiredUpdateRate; + int AbortRender; + int InAbortCheck; + int InRender; + int NeverRendered; + int NumberOfLayers; + int CurrentCursor; + int IsPicking; + float AnaglyphColorSaturation; + int AnaglyphColorMask[2]; + +private: + vtkRenderWindow(const vtkRenderWindow&); // Not implemented. + void operator=(const vtkRenderWindow&); // Not implemented. +}; + +// Description: +// Return the stereo type as a character string. +inline char *vtkRenderWindow::GetStereoTypeAsString(void) +{ + switch ( this->StereoType ) + { + case VTK_STEREO_CRYSTAL_EYES: + return (char *)"CrystalEyes"; + case VTK_STEREO_RED_BLUE: + return (char *)"RedBlue"; + case VTK_STEREO_LEFT: + return (char *)"Left"; + case VTK_STEREO_RIGHT: + return (char *)"Right"; + case VTK_STEREO_DRESDEN: + return (char *)"DresdenDisplay"; + case VTK_STEREO_ANAGLYPH: + return (char *)"Anaglyph"; + default: + return (char *)""; + } +} + +#endif diff --git a/Rendering/vtkRenderWindowCollection.cxx b/Rendering/vtkRenderWindowCollection.cxx new file mode 100644 index 0000000..bb4b271 --- /dev/null +++ b/Rendering/vtkRenderWindowCollection.cxx @@ -0,0 +1,24 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderWindowCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRenderWindowCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkRenderWindowCollection, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkRenderWindowCollection); + +void vtkRenderWindowCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkRenderWindowCollection.h b/Rendering/vtkRenderWindowCollection.h new file mode 100644 index 0000000..1a29b56 --- /dev/null +++ b/Rendering/vtkRenderWindowCollection.h @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderWindowCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRenderWindowCollection - a list of RenderWindows +// .SECTION Description +// vtkRenderWindowCollection represents and provides methods to manipulate a +// list of RenderWindows. The list is unsorted and duplicate entries are +// not prevented. + +// .SECTION see also +// vtkRenderWindow vtkCollection + +#ifndef __vtkRenderWindowCollection_h +#define __vtkRenderWindowCollection_h + +#include "vtkCollection.h" +#include "vtkRenderWindow.h" // Needed for static cast + +class VTK_RENDERING_EXPORT vtkRenderWindowCollection : public vtkCollection +{ + public: + static vtkRenderWindowCollection *New(); + vtkTypeRevisionMacro(vtkRenderWindowCollection,vtkCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a RenderWindow to the list. + void AddItem(vtkRenderWindow *a) { + this->vtkCollection::AddItem((vtkObject *)a);}; + + // Description: + // Get the next RenderWindow in the list. Return NULL when at the end of the + // list. + vtkRenderWindow *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkRenderWindow *GetNextRenderWindow(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkRenderWindowCollection() {}; + ~vtkRenderWindowCollection() {}; + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkRenderWindowCollection(const vtkRenderWindowCollection&); // Not implemented. + void operator=(const vtkRenderWindowCollection&); // Not implemented. +}; + + +#endif diff --git a/Rendering/vtkRenderWindowInteractor.cxx b/Rendering/vtkRenderWindowInteractor.cxx new file mode 100644 index 0000000..2604bc0 --- /dev/null +++ b/Rendering/vtkRenderWindowInteractor.cxx @@ -0,0 +1,391 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderWindowInteractor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRenderWindowInteractor.h" + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkGraphicsFactory.h" +#include "vtkInteractorStyleSwitch.h" +#include "vtkMath.h" +#include "vtkPropPicker.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkRendererCollection.h" +#include "vtkDebugLeaks.h" + +vtkCxxRevisionMacro(vtkRenderWindowInteractor, "$Revision: 1.108 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkRenderWindowInteractor); +//---------------------------------------------------------------------------- + +vtkCxxSetObjectMacro(vtkRenderWindowInteractor,Picker,vtkAbstractPicker); + +// Construct object so that light follows camera motion. +vtkRenderWindowInteractor::vtkRenderWindowInteractor() +{ + this->RenderWindow = NULL; + this->InteractorStyle = NULL; + this->SetInteractorStyle(vtkInteractorStyleSwitch::New()); + this->InteractorStyle->Delete(); + + this->LightFollowCamera = 1; + this->Initialized = 0; + this->Enabled = 0; + this->DesiredUpdateRate = 15; + // default limit is 3 hours per frame + this->StillUpdateRate = 0.0001; + + this->Picker = this->CreateDefaultPicker(); + this->Picker->Register(this); + this->Picker->Delete(); + + this->EventPosition[0] = this->LastEventPosition[0] = 0; + this->EventPosition[1] = this->LastEventPosition[1] = 0; + + this->EventSize[0] = 0; + this->EventSize[1] = 0; + + this->Size[0] = 0; + this->Size[1] = 0; + + this->NumberOfFlyFrames = 15; + this->Dolly = 0.30; + + this->ControlKey = 0; + this->ShiftKey = 0; + this->KeyCode = 0; + this->RepeatCount = 0; + this->KeySym = 0; +} + +vtkRenderWindowInteractor::~vtkRenderWindowInteractor() +{ + if (this->InteractorStyle != NULL) + { + this->InteractorStyle->UnRegister(this); + } + if ( this->Picker) + { + this->Picker->UnRegister(this); + } + if ( this->KeySym ) + { + delete [] this->KeySym; + } +} + +vtkRenderWindowInteractor *vtkRenderWindowInteractor::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = + vtkGraphicsFactory::CreateInstance("vtkRenderWindowInteractor"); + if ( ret ) + { + return (vtkRenderWindowInteractor *)ret; + } +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::ConstructClass("vtkRenderWindowInteractor"); +#endif + return new vtkRenderWindowInteractor; +} + +void vtkRenderWindowInteractor::Render() +{ + if (this->RenderWindow && this->Enabled) + { + this->RenderWindow->Render(); + } + // outside the above test so that third-party code can redirect + // the render to the appropriate class + this->InvokeEvent(vtkCommand::RenderEvent, NULL); +} + +// treat renderWindow and interactor as one object. +// it might be easier if the GetReference count method were redefined. +void vtkRenderWindowInteractor::UnRegister(vtkObjectBase *o) +{ + if (this->RenderWindow && this->RenderWindow->GetInteractor() == this && + this->RenderWindow != o) + { + if (this->GetReferenceCount()+this->RenderWindow->GetReferenceCount() == 3) + { + this->RenderWindow->SetInteractor(NULL); + this->SetRenderWindow(NULL); + } + } + + this->vtkObject::UnRegister(o); +} + +void vtkRenderWindowInteractor::SetRenderWindow(vtkRenderWindow *aren) +{ + if (this->RenderWindow != aren) + { + // to avoid destructor recursion + vtkRenderWindow *temp = this->RenderWindow; + this->RenderWindow = aren; + if (temp != NULL) + { + temp->UnRegister(this); + } + if (this->RenderWindow != NULL) + { + this->RenderWindow->Register(this); + if (this->RenderWindow->GetInteractor() != this) + { + this->RenderWindow->SetInteractor(this); + } + } + } +} + +void vtkRenderWindowInteractor::SetInteractorStyle(vtkInteractorObserver *style) +{ + if (this->InteractorStyle != style) + { + // to avoid destructor recursion + vtkInteractorObserver *temp = this->InteractorStyle; + this->InteractorStyle = style; + if (temp != NULL) + { + temp->SetInteractor(0); + temp->UnRegister(this); + } + if (this->InteractorStyle != NULL) + { + this->InteractorStyle->Register(this); + if (this->InteractorStyle->GetInteractor() != this) + { + this->InteractorStyle->SetInteractor(this); + } + } + } +} + +void vtkRenderWindowInteractor::UpdateSize(int x,int y) +{ + // if the size changed send this on to the RenderWindow + if ((x != this->Size[0])||(y != this->Size[1])) + { + this->Size[0] = this->EventSize[0] = x; + this->Size[1] = this->EventSize[1] = y; + this->RenderWindow->SetSize(x,y); + } +} + +// Creates an instance of vtkPropPicker by default +vtkAbstractPropPicker *vtkRenderWindowInteractor::CreateDefaultPicker() +{ + return vtkPropPicker::New(); +} + +void vtkRenderWindowInteractor::ExitCallback() +{ + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent,NULL); + } + else + { + this->TerminateApp(); + } +} + +void vtkRenderWindowInteractor::UserCallback() +{ + this->InvokeEvent(vtkCommand::UserEvent,NULL); +} + +void vtkRenderWindowInteractor::StartPickCallback() +{ + this->InvokeEvent(vtkCommand::StartPickEvent,NULL); +} + +void vtkRenderWindowInteractor::EndPickCallback() +{ + this->InvokeEvent(vtkCommand::EndPickEvent,NULL); +} + +void vtkRenderWindowInteractor::FlyTo(vtkRenderer *ren, double x, double y, double z) +{ + double flyFrom[3], flyTo[3]; + double d[3], focalPt[3]; + int i, j; + + flyTo[0]=x; flyTo[1]=y; flyTo[2]=z; + ren->GetActiveCamera()->GetFocalPoint(flyFrom); + for (i=0; i<3; i++) + { + d[i] = flyTo[i] - flyFrom[i]; + } + double distance = vtkMath::Normalize(d); + double delta = distance/this->NumberOfFlyFrames; + + for (i=1; i<=NumberOfFlyFrames; i++) + { + for (j=0; j<3; j++) + { + focalPt[j] = flyFrom[j] + d[j]*i*delta; + } + ren->GetActiveCamera()->SetFocalPoint(focalPt); + ren->GetActiveCamera()->Dolly(this->Dolly/this->NumberOfFlyFrames + 1.0); + ren->GetActiveCamera()->OrthogonalizeViewUp(); + ren->ResetCameraClippingRange(); + this->Render(); + } +} + +void vtkRenderWindowInteractor::FlyToImage(vtkRenderer *ren, double x, double y) +{ + double flyFrom[3], flyTo[3]; + double d[3], focalPt[3], position[3], positionFrom[3]; + int i, j; + + flyTo[0]=x; flyTo[1]=y; + ren->GetActiveCamera()->GetFocalPoint(flyFrom); flyTo[2] = flyFrom[2]; + ren->GetActiveCamera()->GetPosition(positionFrom); + for (i=0; i<2; i++) + { + d[i] = flyTo[i] - flyFrom[i]; + } + d[2] = 0.0; + double distance = vtkMath::Normalize(d); + double delta = distance/this->NumberOfFlyFrames; + + for (i=1; i<=NumberOfFlyFrames; i++) + { + for (j=0; j<3; j++) + { + focalPt[j] = flyFrom[j] + d[j]*i*delta; + position[j] = positionFrom[j] + d[j]*i*delta; + } + ren->GetActiveCamera()->SetFocalPoint(focalPt); + ren->GetActiveCamera()->SetPosition(position); + ren->GetActiveCamera()->Dolly(this->Dolly/this->NumberOfFlyFrames + 1.0); + ren->ResetCameraClippingRange(); + this->Render(); + } +} + +//---------------------------------------------------------------------------- +vtkRenderer* vtkRenderWindowInteractor::FindPokedRenderer(int x,int y) +{ + vtkRendererCollection *rc; + vtkRenderer *aren; + vtkRenderer *currentRenderer=NULL, *interactiveren=NULL, *viewportren=NULL; + int numRens, i; + + rc = this->RenderWindow->GetRenderers(); + numRens = rc->GetNumberOfItems(); + + for (i = numRens -1; (i >= 0) && !currentRenderer; i--) + { + aren = (vtkRenderer *)rc->GetItemAsObject(i); + if (aren->IsInViewport(x,y) && aren->GetInteractive()) + { + currentRenderer = aren; + } + + if (interactiveren == NULL && aren->GetInteractive()) + { + // Save this renderer in case we can't find one in the viewport that + // is interactive. + interactiveren = aren; + } + if (viewportren == NULL && aren->IsInViewport(x, y)) + { + // Save this renderer in case we can't find one in the viewport that + // is interactive. + viewportren = aren; + } + }//for all renderers + + // We must have a value. If we found an interactive renderer before, that's + // better than a non-interactive renderer. + if ( currentRenderer == NULL ) + { + currentRenderer = interactiveren; + } + + // We must have a value. If we found a renderer that is in the viewport, + // that is better than any old viewport (but not as good as an interactive + // one). + if ( currentRenderer == NULL ) + { + currentRenderer = viewportren; + } + + // We must have a value - take anything. + if ( currentRenderer == NULL) + { + aren = rc->GetFirstRenderer(); + currentRenderer = aren; + } + + return currentRenderer; +} + +//---------------------------------------------------------------------------- +void vtkRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "InteractorStyle: " << this->InteractorStyle << "\n"; + os << indent << "RenderWindow: " << this->RenderWindow << "\n"; + if ( this->Picker ) + { + os << indent << "Picker: " << this->Picker << "\n"; + } + else + { + os << indent << "Picker: (none)\n"; + } + os << indent << "LightFollowCamera: " << (this->LightFollowCamera ? "On\n" : "Off\n"); + os << indent << "DesiredUpdateRate: " << this->DesiredUpdateRate << "\n"; + os << indent << "StillUpdateRate: " << this->StillUpdateRate << "\n"; + os << indent << "Initialized: " << this->Initialized << "\n"; + os << indent << "Enabled: " << this->Enabled << "\n"; + os << indent << "EventPosition: " << "( " << this->EventPosition[0] << + ", " << this->EventPosition[1] << " )\n"; + os << indent << "LastEventPosition: " << "( " << this->LastEventPosition[0] + << ", " << this->LastEventPosition[1] << " )\n"; + os << indent << "EventSize: " << "( " << this->EventSize[0] << + ", " << this->EventSize[1] << " )\n"; + os << indent << "Viewport Size: " << "( " << this->Size[0] << + ", " << this->Size[1] << " )\n"; + os << indent << "Number of Fly Frames: " << this->NumberOfFlyFrames <<"\n"; + os << indent << "Dolly: " << this->Dolly <<"\n"; + os << indent << "ControlKey: " << this->ControlKey << "\n"; + os << indent << "ShiftKey: " << this->ShiftKey << "\n"; + os << indent << "KeyCode: " << this->KeyCode << "\n"; + os << indent << "KeySym: " << (this->KeySym ? this->KeySym : "(null)") + << "\n"; + os << indent << "RepeatCount: " << this->RepeatCount << "\n"; +} + +void vtkRenderWindowInteractor::Initialize() +{ + this->Initialized=1; + this->Enable(); + this->Render(); +} + +void vtkRenderWindowInteractor::HideCursor() +{ this->RenderWindow->HideCursor(); }; +void vtkRenderWindowInteractor::ShowCursor() +{ this->RenderWindow->ShowCursor(); }; + diff --git a/Rendering/vtkRenderWindowInteractor.h b/Rendering/vtkRenderWindowInteractor.h new file mode 100644 index 0000000..72bb787 --- /dev/null +++ b/Rendering/vtkRenderWindowInteractor.h @@ -0,0 +1,363 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderWindowInteractor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRenderWindowInteractor - platform-independent render window interaction including picking and frame rate control. + +// .SECTION Description +// vtkRenderWindowInteractor provides a platform-independent interaction +// mechanism for mouse/key/time events. It serves as a base class for +// platform-dependent implementations that handle routing of mouse/key/timer +// messages to vtkInteractorStyle and its subclasses. +// vtkRenderWindowInteractor also provides controls for picking, +// rendering frame rate, and headlights. +// +// vtkRenderWindowInteractor has changed from previous implementations and +// now serves only as a shell to hold user preferences and route messages +// to vtkInteractorStyle. Callbacks are available for many Events. +// Platform specific subclasses should provide methods for +// CreateTimer/DestroyTimer, TerminateApp, and an event loop if required +// via Initialize/Start/Enable/Disable. + +#ifndef __vtkRenderWindowInteractor_h +#define __vtkRenderWindowInteractor_h + +#include "vtkObject.h" + +// Timer flags for win32/X compatibility +#define VTKI_TIMER_FIRST 0 +#define VTKI_TIMER_UPDATE 1 + +class vtkAbstractPicker; +class vtkAbstractPropPicker; +class vtkInteractorObserver; +class vtkInteractorObserver; +class vtkRenderWindow; +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkRenderWindowInteractor : public vtkObject +{ +public: + static vtkRenderWindowInteractor *New(); + vtkTypeRevisionMacro(vtkRenderWindowInteractor,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Prepare for handling events. This must be called before the + // interactor will work. + virtual void Initialize(); + void ReInitialize() { this->Initialized = 0; this->Enabled = 0; + this->Initialize(); } + + // Description: + // This Method detects loops of RenderWindow-Interactor, + // so objects are freed properly. + virtual void UnRegister(vtkObjectBase *o); + + // Description: + // Start the event loop. This is provided so that you do not have to + // implement your own event loop. You still can use your own + // event loop if you want. Initialize should be called before Start. + virtual void Start() {}; + + // Description: + // Enable/Disable interactions. By default interactors are enabled when + // initialized. Initialize() must be called prior to enabling/disabling + // interaction. These methods are used when a window/widget is being + // shared by multiple renderers and interactors. This allows a "modal" + // display where one interactor is active when its data is to be displayed + // and all other interactors associated with the widget are disabled + // when their data is not displayed. + virtual void Enable() { this->Enabled = 1; this->Modified();}; + virtual void Disable() { this->Enabled = 0; this->Modified();}; + vtkGetMacro(Enabled, int); + + // Description: + // Set/Get the rendering window being controlled by this object. + void SetRenderWindow(vtkRenderWindow *aren); + vtkGetObjectMacro(RenderWindow,vtkRenderWindow); + + // Description: + // Event loop notification member for Window size change + virtual void UpdateSize(int x,int y); + + // Description: + // Timer methods must be overridden by platform dependent subclasses. + // flag is passed to indicate if this is first timer set or an update + // as Win32 uses repeating timers, whereas X uses One shot more timer + // if flag==VTKXI_TIMER_FIRST Win32 and X should createtimer + // otherwise Win32 should exit and X should perform AddTimeOut() + virtual int CreateTimer(int ) { return 1; }; + virtual int DestroyTimer() { return 1; }; + + // Description: + // This function is called on 'q','e' keypress if exitmethod is not + // specified and should be overridden by platform dependent subclasses + // to provide a termination procedure if one is required. + virtual void TerminateApp(void) {}; + + // Description: + // External switching between joystick/trackball/new? modes. + virtual void SetInteractorStyle(vtkInteractorObserver *); + vtkGetObjectMacro(InteractorStyle,vtkInteractorObserver); + + // Description: + // Turn on/off the automatic repositioning of lights as the camera moves. + vtkSetMacro(LightFollowCamera,int); + vtkGetMacro(LightFollowCamera,int); + vtkBooleanMacro(LightFollowCamera,int); + + // Description: + // Set/Get the desired update rate. This is used by vtkLODActor's to tell + // them how quickly they need to render. This update is in effect only + // when the camera is being rotated, or zoomed. When the interactor is + // still, the StillUpdateRate is used instead. + vtkSetClampMacro(DesiredUpdateRate,double,0.0001,VTK_LARGE_FLOAT); + vtkGetMacro(DesiredUpdateRate,double); + + // Description: + // Set/Get the desired update rate when movement has stopped. + // See the SetDesiredUpdateRate method. + vtkSetClampMacro(StillUpdateRate,double,0.0001,VTK_LARGE_FLOAT); + vtkGetMacro(StillUpdateRate,double); + + // Description: + // See whether interactor has been initialized yet. + vtkGetMacro(Initialized,int); + + // Description: + // Set/Get the object used to perform pick operations. In order to + // pick instances of vtkProp, the picker must be a subclass of + // vtkAbstractPropPicker, meaning that it can identify a particular + // instance of vtkProp. + virtual void SetPicker(vtkAbstractPicker*); + vtkGetObjectMacro(Picker,vtkAbstractPicker); + + // Description: + // Create default picker. Used to create one when none is specified. + // Default is an instance of vtkPropPicker. + virtual vtkAbstractPropPicker *CreateDefaultPicker(); + + // Description: + // These methods correspond to the the Exit, User and Pick + // callbacks. They allow for the Style to invoke them. + virtual void ExitCallback(); + virtual void UserCallback(); + virtual void StartPickCallback(); + virtual void EndPickCallback(); + + // Description: + // Get the current position of the mouse. + virtual void GetMousePosition(int *x, int *y) { *x = 0 ; *y = 0; } + + // Description: + // Hide or show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + void HideCursor(); + void ShowCursor(); + + // Description: + // Render the scene. Just pass the render call on to the + // associated vtkRenderWindow. + virtual void Render(); + + // Description: + // Given a position x, move the current camera's focal point to x. + // The movement is animated over the number of frames specified in + // NumberOfFlyFrames. The LOD desired frame rate is used. + void FlyTo(vtkRenderer *ren, double x, double y, double z); + void FlyTo(vtkRenderer *ren, double *x) + {this->FlyTo(ren, x[0], x[1], x[2]);} + void FlyToImage(vtkRenderer *ren, double x, double y); + void FlyToImage(vtkRenderer *ren, double *x) + {this->FlyToImage(ren, x[0], x[1]);} + + // Description: + // Set the number of frames to fly to when FlyTo is invoked. + vtkSetClampMacro(NumberOfFlyFrames,int,1,VTK_LARGE_INTEGER); + vtkGetMacro(NumberOfFlyFrames,int); + + // Description: + // Set the total Dolly value to use when flying to (FlyTo()) a + // specified point. Negative values fly away from the point. + vtkSetMacro(Dolly,double); + vtkGetMacro(Dolly,double); + + // Description: + // Set/Get information about the current event. + // The current x,y position is in the EventPosition, and the previous + // event position is in LastEventPosition, updated automatically each + // time EventPosition is set using its Set() method. + // The other information is about key board input. + vtkGetVector2Macro(EventPosition,int); + vtkGetVector2Macro(LastEventPosition,int); + vtkSetVector2Macro(LastEventPosition,int); + virtual void SetEventPosition(int x, int y) + { + vtkDebugMacro(<< this->GetClassName() << " (" << this + << "): setting EventPosition to (" << x << "," << y << ")"); + if (this->EventPosition[0] != x || this->EventPosition[1] != y) + { + this->LastEventPosition[0] = this->EventPosition[0]; + this->LastEventPosition[1] = this->EventPosition[1]; + this->EventPosition[0] = x; + this->EventPosition[1] = y; + this->Modified(); + } + }; + virtual void SetEventPosition(int pos[2]) + { + this->SetEventPosition(pos[0], pos[1]); + } + virtual void SetEventPositionFlipY(int x, int y) + { + this->SetEventPosition(x, this->Size[1] - y - 1); + } + virtual void SetEventPositionFlipY(int pos[2]) + { + this->SetEventPositionFlipY(pos[0], pos[1]); + } + vtkSetMacro(ControlKey, int); + vtkGetMacro(ControlKey, int); + vtkSetMacro(ShiftKey, int); + vtkGetMacro(ShiftKey, int); + vtkSetMacro(KeyCode, char); + vtkGetMacro(KeyCode, char); + vtkSetMacro(RepeatCount, int); + vtkGetMacro(RepeatCount, int); + vtkSetStringMacro(KeySym); + vtkGetStringMacro(KeySym); + + // Description: + // Set all the event information in one call. + void SetEventInformation(int x, + int y, + int ctrl=0, + int shift=0, + char keycode=0, + int repeatcount=0, + const char* keysym=0) + { + this->LastEventPosition[0] = this->EventPosition[0]; + this->LastEventPosition[1] = this->EventPosition[1]; + this->EventPosition[0] = x; + this->EventPosition[1] = y; + this->ControlKey = ctrl; + this->ShiftKey = shift; + this->KeyCode = keycode; + this->RepeatCount = repeatcount; + if(keysym) + { + this->SetKeySym(keysym); + } + this->Modified(); + } + + // Description: + // Calls SetEventInformation, but flips the Y based on the current Size[1] + // value (i.e. y = this->Size[1] - y - 1). + void SetEventInformationFlipY(int x, + int y, + int ctrl=0, + int shift=0, + char keycode=0, + int repeatcount=0, + const char* keysym=0) + { + this->SetEventInformation(x, + this->Size[1] - y - 1, + ctrl, + shift, + keycode, + repeatcount, + keysym); + } + + // Description: + // Set all the keyboard-related event information in one call. + void SetKeyEventInformation(int ctrl=0, + int shift=0, + char keycode=0, + int repeatcount=0, + const char* keysym=0) + { + this->ControlKey = ctrl; + this->ShiftKey = shift; + this->KeyCode = keycode; + this->RepeatCount = repeatcount; + if(keysym) + { + this->SetKeySym(keysym); + } + this->Modified(); + } + + // Description: + // This methods sets the Size ivar of the interactor without + // actually changing the size of the window. Normally + // application programmers would use UpdateSize if anything. + // This is useful for letting someone else change the size of + // the rendering window and just letting the interactor + // know about the change. + // The current event width/height (if any) is in EventSize + // (Expose event, for example). + vtkSetVector2Macro(Size,int); + vtkGetVector2Macro(Size,int); + vtkSetVector2Macro(EventSize,int); + vtkGetVector2Macro(EventSize,int); + + // Description: + // When an event occurs, we must determine which Renderer the event + // occurred within, since one RenderWindow may contain multiple + // renderers. + virtual vtkRenderer *FindPokedRenderer(int,int); + +protected: + vtkRenderWindowInteractor(); + ~vtkRenderWindowInteractor(); + + vtkRenderWindow *RenderWindow; + vtkInteractorObserver *InteractorStyle; + + // Used as a helper object to pick instances of vtkProp + vtkAbstractPicker *Picker; + + int Initialized; + int Enabled; + int Style; + int LightFollowCamera; + int ActorMode; + double DesiredUpdateRate; + double StillUpdateRate; + + // Event information + int ControlKey; + int ShiftKey; + char KeyCode; + int RepeatCount; + char* KeySym; + int EventPosition[2]; + int LastEventPosition[2]; + int EventSize[2]; + int Size[2]; + + // control the fly to + int NumberOfFlyFrames; + double Dolly; + +private: + vtkRenderWindowInteractor(const vtkRenderWindowInteractor&); // Not implemented. + void operator=(const vtkRenderWindowInteractor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkRenderer.cxx b/Rendering/vtkRenderer.cxx new file mode 100644 index 0000000..1372416 --- /dev/null +++ b/Rendering/vtkRenderer.cxx @@ -0,0 +1,1485 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRenderer.h" + +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkCuller.h" +#include "vtkCullerCollection.h" +#include "vtkFrustumCoverageCuller.h" +#include "vtkGraphicsFactory.h" +#include "vtkLight.h" +#include "vtkLightCollection.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkOutputWindow.h" +#include "vtkPicker.h" +#include "vtkProp3DCollection.h" +#include "vtkRenderWindow.h" +#include "vtkTimerLog.h" +#include "vtkVolume.h" + +vtkCxxRevisionMacro(vtkRenderer, "$Revision: 1.219 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkRenderer); +//---------------------------------------------------------------------------- + +// Create a vtkRenderer with a black background, a white ambient light, +// two-sided lighting turned on, a viewport of (0,0,1,1), and backface culling +// turned off. +vtkRenderer::vtkRenderer() +{ + this->PickedProp = NULL; + this->ActiveCamera = NULL; + + this->Ambient[0] = 1; + this->Ambient[1] = 1; + this->Ambient[2] = 1; + + this->AllocatedRenderTime = 100; + this->TimeFactor = 1.0; + + this->CreatedLight = NULL; + this->AutomaticLightCreation = 1; + + this->TwoSidedLighting = 1; + this->BackingStore = 0; + this->BackingImage = NULL; + this->BackingStoreSize[0] = -1; + this->BackingStoreSize[1] = -1; + this->LastRenderTimeInSeconds = -1.0; + + this->RenderWindow = NULL; + this->Lights = vtkLightCollection::New(); + this->Actors = vtkActorCollection::New(); + this->Volumes = vtkVolumeCollection::New(); + + this->LightFollowCamera = 1; + + this->NumberOfPropsRendered = 0; + + this->PropArray = NULL; + this->PropArrayCount = 0; + + this->PathArray = NULL; + this->PathArrayCount = 0; + + this->Layer = 0; + + this->ComputedVisiblePropBounds[0] = VTK_DOUBLE_MAX; + this->ComputedVisiblePropBounds[1] = -VTK_DOUBLE_MAX; + this->ComputedVisiblePropBounds[2] = VTK_DOUBLE_MAX; + this->ComputedVisiblePropBounds[3] = -VTK_DOUBLE_MAX; + this->ComputedVisiblePropBounds[4] = VTK_DOUBLE_MAX; + this->ComputedVisiblePropBounds[5] = -VTK_DOUBLE_MAX; + + this->Interactive = 1; + this->Cullers = vtkCullerCollection::New(); + vtkFrustumCoverageCuller *cull = vtkFrustumCoverageCuller::New(); + this->Cullers->AddItem(cull); + cull->Delete(); + + // a value of 0 indicates it is uninitialized + this->NearClippingPlaneTolerance = 0; + + this->Erase = 1; +} + +vtkRenderer::~vtkRenderer() +{ + this->SetRenderWindow( NULL ); + + if (this->ActiveCamera) + { + this->ActiveCamera->UnRegister(this); + this->ActiveCamera = NULL; + } + + if (this->CreatedLight) + { + this->CreatedLight->UnRegister(this); + this->CreatedLight = NULL; + } + + if (this->BackingImage) + { + delete [] this->BackingImage; + } + + this->Actors->Delete(); + this->Actors = NULL; + this->Volumes->Delete(); + this->Volumes = NULL; + this->Lights->Delete(); + this->Lights = NULL; + this->Cullers->Delete(); + this->Cullers = NULL; +} + +// return the correct type of Renderer +vtkRenderer *vtkRenderer::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkRenderer"); + return (vtkRenderer *)ret; +} + +// Concrete render method. +void vtkRenderer::Render(void) +{ + double t1, t2; + int i; + vtkProp *aProp; + int *size; + + t1 = vtkTimerLog::GetUniversalTime(); + + this->InvokeEvent(vtkCommand::StartEvent,NULL); + + size = this->RenderWindow->GetSize(); + + // if backing store is on and we have a stored image + if (this->BackingStore && this->BackingImage && + this->MTime < this->RenderTime && + this->ActiveCamera->GetMTime() < this->RenderTime && + this->RenderWindow->GetMTime() < this->RenderTime && + this->BackingStoreSize[0] == size[0] && + this->BackingStoreSize[1] == size[1]) + { + int mods = 0; + vtkLight *light; + + // now we just need to check the lights and actors + vtkCollectionSimpleIterator sit; + for(this->Lights->InitTraversal(sit); + (light = this->Lights->GetNextLight(sit)); ) + { + if (light->GetSwitch() && + light->GetMTime() > this->RenderTime) + { + mods = 1; + goto completed_mod_check; + } + } + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + // if it's invisible, we can skip the rest + if (aProp->GetVisibility()) + { + if (aProp->GetRedrawMTime() > this->RenderTime) + { + mods = 1; + goto completed_mod_check; + } + } + } + + completed_mod_check: + + if (!mods) + { + int rx1, ry1, rx2, ry2; + + // backing store should be OK, lets use it + // calc the pixel range for the renderer + rx1 = (int)(this->Viewport[0]*(this->RenderWindow->GetSize()[0] - 1)); + ry1 = (int)(this->Viewport[1]*(this->RenderWindow->GetSize()[1] - 1)); + rx2 = (int)(this->Viewport[2]*(this->RenderWindow->GetSize()[0] - 1)); + ry2 = (int)(this->Viewport[3]*(this->RenderWindow->GetSize()[1] - 1)); + this->RenderWindow->SetPixelData(rx1,ry1,rx2,ry2,this->BackingImage,0); + this->InvokeEvent(vtkCommand::EndEvent,NULL); + return; + } + } + + // Create the initial list of visible props + // This will be passed through AllocateTime(), where + // a time is allocated for each prop, and the list + // maybe re-ordered by the cullers. Also create the + // sublists for the props that need ray casting, and + // the props that need to be rendered into an image. + // Fill these in later (in AllocateTime) - get a + // count of them there too + if ( this->Props->GetNumberOfItems() > 0 ) + { + this->PropArray = new vtkProp *[this->Props->GetNumberOfItems()]; + } + else + { + this->PropArray = NULL; + } + + this->PropArrayCount = 0; + vtkCollectionSimpleIterator pit; + for ( this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + if ( aProp->GetVisibility() ) + { + this->PropArray[this->PropArrayCount++] = aProp; + } + } + + if ( this->PropArrayCount == 0 ) + { + vtkDebugMacro( << "There are no visible props!" ); + } + else + { + // Call all the culling methods to set allocated time + // for each prop and re-order the prop list if desired + + this->AllocateTime(); + } + + // do the render library specific stuff + this->DeviceRender(); + + // If we aborted, restore old estimated times + // Setting the allocated render time to zero also sets the + // estimated render time to zero, so that when we add back + // in the old value we have set it correctly. + if ( this->RenderWindow->GetAbortRender() ) + { + for ( i = 0; i < this->PropArrayCount; i++ ) + { + this->PropArray[i]->RestoreEstimatedRenderTime(); + } + } + + // Clean up the space we allocated before. If the PropArray exists, + // they all should exist + if ( this->PropArray) + { + delete [] this->PropArray; + this->PropArray = NULL; + } + + if (this->BackingStore) + { + if (this->BackingImage) + { + delete [] this->BackingImage; + } + + int rx1, ry1, rx2, ry2; + + // backing store should be OK, lets use it + // calc the pixel range for the renderer + rx1 = (int)(this->Viewport[0]*(size[0] - 1)); + ry1 = (int)(this->Viewport[1]*(size[1] - 1)); + rx2 = (int)(this->Viewport[2]*(size[0] - 1)); + ry2 = (int)(this->Viewport[3]*(size[1] - 1)); + this->BackingImage = this->RenderWindow->GetPixelData(rx1,ry1,rx2,ry2,0); + this->BackingStoreSize[0] = size[0]; + this->BackingStoreSize[1] = size[1]; + } + + + // If we aborted, do not record the last render time. + // Lets play around with determining the acuracy of the + // EstimatedRenderTimes. We can try to adjust for bad + // estimates with the TimeFactor. + if ( ! this->RenderWindow->GetAbortRender() ) + { + // Measure the actual RenderTime + t2 = vtkTimerLog::GetUniversalTime(); + this->LastRenderTimeInSeconds = (double) (t2 - t1); + + if (this->LastRenderTimeInSeconds == 0.0) + { + this->LastRenderTimeInSeconds = 0.0001; + } + this->TimeFactor = this->AllocatedRenderTime/this->LastRenderTimeInSeconds; + } +} + +double vtkRenderer::GetAllocatedRenderTime() +{ + return this->AllocatedRenderTime; +} + +double vtkRenderer::GetTimeFactor() +{ + return this->TimeFactor; +} + +// Ask active camera to load its view matrix. +int vtkRenderer::UpdateCamera () +{ + if (!this->ActiveCamera) + { + vtkDebugMacro(<< "No cameras are on, creating one."); + // the get method will automagically create a camera + // and reset it since one hasn't been specified yet + this->GetActiveCameraAndEventuallyReset(); + } + + // update the viewing transformation + this->ActiveCamera->Render((vtkRenderer *)this); + + return 1; +} + +int vtkRenderer::UpdateLightsGeometryToFollowCamera() +{ + vtkCamera *camera; + vtkLight *light; + vtkMatrix4x4 *lightMatrix; + + // only update the light's geometry if this Renderer is tracking + // this lights. That allows one renderer to view the lights that + // another renderer is setting up. + camera = this->GetActiveCameraAndEventuallyReset(); + lightMatrix = camera->GetCameraLightTransformMatrix(); + + vtkCollectionSimpleIterator sit; + for(this->Lights->InitTraversal(sit); + (light = this->Lights->GetNextLight(sit)); ) + { + if (light->LightTypeIsSceneLight()) + { + // Do nothing. Don't reset the transform matrix because applications + // may have set a custom matrix. Only reset the transform matrix in + // vtkLight::SetLightTypeToSceneLight() + } + else if (light->LightTypeIsHeadlight()) + { + // update position and orientation of light to match camera. + light->SetPosition(camera->GetPosition()); + light->SetFocalPoint(camera->GetFocalPoint()); + } + else if (light->LightTypeIsCameraLight()) + { + light->SetTransformMatrix(lightMatrix); + } + else + { + vtkErrorMacro(<< "light has unknown light type"); + } + } + return 1; +} + +int vtkRenderer::UpdateLightGeometry() +{ + if (this->LightFollowCamera) + { + // only update the light's geometry if this Renderer is tracking + // this lights. That allows one renderer to view the lights that + // another renderer is setting up. + + return this->UpdateLightsGeometryToFollowCamera(); + } + + return 1; +} + +// Do all outer culling to set allocated time for each prop. +// Possibly re-order the actor list. +void vtkRenderer::AllocateTime() +{ + int initialized = 0; + double renderTime; + double totalTime; + int i; + vtkCuller *aCuller; + vtkProp *aProp; + + // Give each of the cullers a chance to modify allocated rendering time + // for the entire set of props. Each culler returns the total time given + // by AllocatedRenderTime for all props. Each culler is required to + // place any props that have an allocated render time of 0.0 + // at the end of the list. The PropArrayCount value that is + // returned is the number of non-zero, visible actors. + // Some cullers may do additional sorting of the list (by distance, + // importance, etc). + // + // The first culler will initialize all the allocated render times. + // Any subsequent culling will multiply the new render time by the + // existing render time for an actor. + + totalTime = this->PropArrayCount; + this->ComputeAspect(); + + // It is very likely that the culler framework will call our + // GetActiveCamera (say, to get the view frustrum planes for example). + // This does not reset the camera anymore. If no camera has been + // created though, we want it not only to be created but also reset + // so that it behaves nicely for people who never bother with the camera + // (i.e. neither call GetActiveCamera or ResetCamera) + + if ( this->Cullers->GetNumberOfItems()) + { + this->GetActiveCameraAndEventuallyReset(); + } + + vtkCollectionSimpleIterator sit; + for (this->Cullers->InitTraversal(sit); + (aCuller=this->Cullers->GetNextCuller(sit));) + { + totalTime = + aCuller->Cull((vtkRenderer *)this, + this->PropArray, this->PropArrayCount, + initialized ); + } + + // loop through all props and set the AllocatedRenderTime + for ( i = 0; i < this->PropArrayCount; i++ ) + { + aProp = this->PropArray[i]; + + // If we don't have an outer cull method in any of the cullers, + // then the allocated render time has not yet been initialized + renderTime = (initialized)?(aProp->GetRenderTimeMultiplier()):(1.0); + + // We need to divide by total time so that the total rendering time + // (all prop's AllocatedRenderTime added together) would be equal + // to the renderer's AllocatedRenderTime. + aProp-> + SetAllocatedRenderTime(( renderTime / totalTime ) * + this->AllocatedRenderTime, + this ); + } +} + +// Ask actors to render themselves. As a side effect will cause +// visualization network to update. +int vtkRenderer::UpdateGeometry() +{ + int i; + + this->NumberOfPropsRendered = 0; + + if ( this->PropArrayCount == 0 ) + { + this->InvokeEvent(vtkCommand::EndEvent,NULL); + return 0; + } + + // We can render everything because if it was + // not visible it would not have been put in the + // list in the first place, and if it was allocated + // no time (culled) it would have been removed from + // the list + + // loop through props and give them a chance to + // render themselves as opaque geometry + for ( i = 0; i < this->PropArrayCount; i++ ) + { + this->NumberOfPropsRendered += + this->PropArray[i]->RenderOpaqueGeometry(this); + } + + + // loop through props and give them a chance to + // render themselves as translucent geometry + for ( i = 0; i < this->PropArrayCount; i++ ) + { + this->NumberOfPropsRendered += + this->PropArray[i]->RenderTranslucentGeometry(this); + } + + // loop through props and give them a chance to + // render themselves as an overlay (or underlay) + for ( i = 0; i < this->PropArrayCount; i++ ) + { + this->NumberOfPropsRendered += + this->PropArray[i]->RenderOverlay(this); + } + + this->InvokeEvent(vtkCommand::EndEvent,NULL); + this->RenderTime.Modified(); + + vtkDebugMacro( << "Rendered " << + this->NumberOfPropsRendered << " actors" ); + + return this->NumberOfPropsRendered; +} + +vtkWindow *vtkRenderer::GetVTKWindow() +{ + return this->RenderWindow; +} + +// Specify the camera to use for this renderer. +void vtkRenderer::SetActiveCamera(vtkCamera *cam) +{ + if (this->ActiveCamera == cam) + { + return; + } + + if (this->ActiveCamera) + { + this->ActiveCamera->UnRegister(this); + this->ActiveCamera = NULL; + } + if (cam) + { + cam->Register(this); + } + + this->ActiveCamera = cam; + this->Modified(); +} + +//---------------------------------------------------------------------------- +vtkCamera* vtkRenderer::MakeCamera() +{ + return vtkCamera::New(); +} + +//---------------------------------------------------------------------------- +vtkCamera *vtkRenderer::GetActiveCamera() +{ + if ( this->ActiveCamera == NULL ) + { + vtkCamera *cam = this->MakeCamera(); + this->SetActiveCamera(cam); + cam->Delete(); + // The following line has been commented out as it has a lot of + // side effects (like computing the bounds of all props, which will + // eventually call UpdateInformation() on data objects, etc). + // Instead, the rendering code has been updated to internally use + // GetActiveCameraAndEventuallyReset which will reset the camera + // if it gets created + // this->ResetCamera(); + } + + return this->ActiveCamera; +} + +//---------------------------------------------------------------------------- +vtkCamera *vtkRenderer::GetActiveCameraAndEventuallyReset() +{ + if (this->ActiveCamera == NULL) + { + this->GetActiveCamera(); + this->ResetCamera(); + } + return this->ActiveCamera; +} + +//---------------------------------------------------------------------------- +void vtkRenderer::AddActor(vtkProp* p) +{ + this->AddViewProp(p); +} + +//---------------------------------------------------------------------------- +void vtkRenderer::AddVolume(vtkProp* p) +{ + this->AddViewProp(p); +} + +//---------------------------------------------------------------------------- +void vtkRenderer::RemoveActor(vtkProp* p) +{ + this->Actors->RemoveItem(p); + this->RemoveViewProp(p); +} + +//---------------------------------------------------------------------------- +void vtkRenderer::RemoveVolume(vtkProp* p) +{ + this->Volumes->RemoveItem(p); + this->RemoveViewProp(p); +} + +// Add a light to the list of lights. +void vtkRenderer::AddLight(vtkLight *light) +{ + this->Lights->AddItem(light); +} + +// look through the props and get all the actors +vtkActorCollection *vtkRenderer::GetActors() +{ + vtkProp *aProp; + + // clear the collection first + this->Actors->RemoveAllItems(); + + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + aProp->GetActors(this->Actors); + } + return this->Actors; +} + +// look through the props and get all the volumes +vtkVolumeCollection *vtkRenderer::GetVolumes() +{ + vtkProp *aProp; + + // clear the collection first + this->Volumes->RemoveAllItems(); + + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + aProp->GetVolumes(this->Volumes); + } + return this->Volumes; +} + +// Remove a light from the list of lights. +void vtkRenderer::RemoveLight(vtkLight *light) +{ + this->Lights->RemoveItem(light); +} + +// Add an culler to the list of cullers. +void vtkRenderer::AddCuller(vtkCuller *culler) +{ + this->Cullers->AddItem(culler); +} + +// Remove an actor from the list of cullers. +void vtkRenderer::RemoveCuller(vtkCuller *culler) +{ + this->Cullers->RemoveItem(culler); +} + +vtkLight *vtkRenderer::MakeLight() +{ + return vtkLight::New(); +} + +void vtkRenderer::CreateLight(void) +{ + if ( !this->AutomaticLightCreation ) + { + return; + } + + if (this->CreatedLight) + { + this->CreatedLight->UnRegister(this); + this->CreatedLight = NULL; + } + + // I do not see why UnRegister is used on CreatedLight, but lets be + // consistent. + vtkLight *l = this->MakeLight(); + this->CreatedLight = l; + this->CreatedLight->Register(this); + this->AddLight(this->CreatedLight); + l->Delete(); + + this->CreatedLight->SetLightTypeToHeadlight(); + + // set these values just to have a good default should LightFollowCamera + // be turned off. + this->CreatedLight->SetPosition(this->GetActiveCamera()->GetPosition()); + this->CreatedLight->SetFocalPoint(this->GetActiveCamera()->GetFocalPoint()); +} + +// Compute the bounds of the visible props +void vtkRenderer::ComputeVisiblePropBounds( double allBounds[6] ) +{ + vtkProp *prop; + double *bounds; + int nothingVisible=1; + + allBounds[0] = allBounds[2] = allBounds[4] = VTK_DOUBLE_MAX; + allBounds[1] = allBounds[3] = allBounds[5] = -VTK_DOUBLE_MAX; + + // loop through all props + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (prop = this->Props->GetNextProp(pit)); ) + { + // if it's invisible, or has no geometry, we can skip the rest + if ( prop->GetVisibility() ) + { + bounds = prop->GetBounds(); + // make sure we haven't got bogus bounds + if ( bounds != NULL && vtkMath::AreBoundsInitialized(bounds)) + { + nothingVisible = 0; + + if (bounds[0] < allBounds[0]) + { + allBounds[0] = bounds[0]; + } + if (bounds[1] > allBounds[1]) + { + allBounds[1] = bounds[1]; + } + if (bounds[2] < allBounds[2]) + { + allBounds[2] = bounds[2]; + } + if (bounds[3] > allBounds[3]) + { + allBounds[3] = bounds[3]; + } + if (bounds[4] < allBounds[4]) + { + allBounds[4] = bounds[4]; + } + if (bounds[5] > allBounds[5]) + { + allBounds[5] = bounds[5]; + } + }//not bogus + } + } + + if ( nothingVisible ) + { + vtkMath::UninitializeBounds(allBounds); + vtkDebugMacro(<< "Can't compute bounds, no 3D props are visible"); + return; + } +} + +double *vtkRenderer::ComputeVisiblePropBounds() + { + this->ComputeVisiblePropBounds(this->ComputedVisiblePropBounds); + return this->ComputedVisiblePropBounds; + } + +// Automatically set up the camera based on the visible actors. +// The camera will reposition itself to view the center point of the actors, +// and move along its initial view plane normal (i.e., vector defined from +// camera position to focal point) so that all of the actors can be seen. +void vtkRenderer::ResetCamera() +{ + double allBounds[6]; + + this->ComputeVisiblePropBounds( allBounds ); + + if (!vtkMath::AreBoundsInitialized(allBounds)) + { + vtkDebugMacro( << "Cannot reset camera!" ); + } + else + { + this->ResetCamera(allBounds); + } + + // Here to let parallel/distributed compositing intercept + // and do the right thing. + this->InvokeEvent(vtkCommand::ResetCameraEvent,this); +} + +// Automatically set the clipping range of the camera based on the +// visible actors +void vtkRenderer::ResetCameraClippingRange() +{ + double allBounds[6]; + + this->ComputeVisiblePropBounds( allBounds ); + + if (!vtkMath::AreBoundsInitialized(allBounds)) + { + vtkDebugMacro( << "Cannot reset camera clipping range!" ); + } + else + { + this->ResetCameraClippingRange(allBounds); + } + + // Here to let parallel/distributed compositing intercept + // and do the right thing. + this->InvokeEvent(vtkCommand::ResetCameraClippingRangeEvent,this); +} + + +// Automatically set up the camera based on a specified bounding box +// (xmin,xmax, ymin,ymax, zmin,zmax). Camera will reposition itself so +// that its focal point is the center of the bounding box, and adjust its +// distance and position to preserve its initial view plane normal +// (i.e., vector defined from camera position to focal point). Note: is +// the view plane is parallel to the view up axis, the view up axis will +// be reset to one of the three coordinate axes. +void vtkRenderer::ResetCamera(double bounds[6]) +{ + double center[3]; + double distance; + double vn[3], *vup; + + this->GetActiveCamera(); + if ( this->ActiveCamera != NULL ) + { + this->ActiveCamera->GetViewPlaneNormal(vn); + } + else + { + vtkErrorMacro(<< "Trying to reset non-existant camera"); + return; + } + + center[0] = (bounds[0] + bounds[1])/2.0; + center[1] = (bounds[2] + bounds[3])/2.0; + center[2] = (bounds[4] + bounds[5])/2.0; + + double w1 = bounds[1] - bounds[0]; + double w2 = bounds[3] - bounds[2]; + double w3 = bounds[5] - bounds[4]; + w1 *= w1; + w2 *= w2; + w3 *= w3; + double radius = w1 + w2 + w3; + + // If we have just a single point, pick a radius of 1.0 + radius = (radius==0)?(1.0):(radius); + + // compute the radius of the enclosing sphere + radius = sqrt(radius)*0.5; + + // default so that the bounding sphere fits within the view fustrum + + // compute the distance from the intersection of the view frustum with the + // bounding sphere. Basically in 2D draw a circle representing the bounding + // sphere in 2D then draw a horizontal line going out from the center of + // the circle. That is the camera view. Then draw a line from the camera + // position to the point where it intersects the circle. (it will be tangent + // to the circle at this point, this is important, only go to the tangent + // point, do not draw all the way to the view plane). Then draw the radius + // from the tangent point to the center of the circle. You will note that + // this forms a right triangle with one side being the radius, another being + // the target distance for the camera, then just find the target dist using + // a sin. + distance = + radius/sin(this->ActiveCamera->GetViewAngle()*vtkMath::Pi()/360.0); + + // check view-up vector against view plane normal + vup = this->ActiveCamera->GetViewUp(); + if ( fabs(vtkMath::Dot(vup,vn)) > 0.999 ) + { + vtkWarningMacro(<<"Resetting view-up since view plane normal is parallel"); + this->ActiveCamera->SetViewUp(-vup[2], vup[0], vup[1]); + } + + // update the camera + this->ActiveCamera->SetFocalPoint(center[0],center[1],center[2]); + this->ActiveCamera->SetPosition(center[0]+distance*vn[0], + center[1]+distance*vn[1], + center[2]+distance*vn[2]); + + this->ResetCameraClippingRange( bounds ); + + // setup default parallel scale + this->ActiveCamera->SetParallelScale(radius); +} + +// Alternative version of ResetCamera(bounds[6]); +void vtkRenderer::ResetCamera(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) +{ + double bounds[6]; + + bounds[0] = xmin; + bounds[1] = xmax; + bounds[2] = ymin; + bounds[3] = ymax; + bounds[4] = zmin; + bounds[5] = zmax; + + this->ResetCamera(bounds); +} + +// Reset the camera clipping range to include this entire bounding box +void vtkRenderer::ResetCameraClippingRange( double bounds[6] ) +{ + double vn[3], position[3], a, b, c, d; + double range[2], dist; + int i, j, k; + + // Don't reset the clipping range when we don't have any 3D visible props + if (!vtkMath::AreBoundsInitialized(bounds)) + { + return; + } + + this->GetActiveCameraAndEventuallyReset(); + if ( this->ActiveCamera == NULL ) + { + vtkErrorMacro(<< "Trying to reset clipping range of non-existant camera"); + return; + } + + // Find the plane equation for the camera view plane + this->ActiveCamera->GetViewPlaneNormal(vn); + this->ActiveCamera->GetPosition(position); + a = -vn[0]; + b = -vn[1]; + c = -vn[2]; + d = -(a*position[0] + b*position[1] + c*position[2]); + + // Set the max near clipping plane and the min far clipping plane + range[0] = a*bounds[0] + b*bounds[2] + c*bounds[4] + d; + range[1] = 1e-18; + + // Find the closest / farthest bounding box vertex + for ( k = 0; k < 2; k++ ) + { + for ( j = 0; j < 2; j++ ) + { + for ( i = 0; i < 2; i++ ) + { + dist = a*bounds[i] + b*bounds[2+j] + c*bounds[4+k] + d; + range[0] = (distrange[1])?(dist):(range[1]); + } + } + } + + // Do not let the range behind the camera throw off the calculation. + if (range[0] < 0.0) + { + range[0] = 0.0; + } + + // Give ourselves a little breathing room + range[0] = 0.99*range[0] - (range[1] - range[0])*0.5; + range[1] = 1.01*range[1] + (range[1] - range[0])*0.5; + + // Make sure near is not bigger than far + range[0] = (range[0] >= range[1])?(0.01*range[1]):(range[0]); + + // Make sure near is at least some fraction of far - this prevents near + // from being behind the camera or too close in front. How close is too + // close depends on the resolution of the depth buffer + if (!this->NearClippingPlaneTolerance) + { + this->NearClippingPlaneTolerance = 0.01; + if (this->RenderWindow) + { + int ZBufferDepth = this->RenderWindow->GetDepthBufferSize(); + if ( ZBufferDepth > 16 ) + { + this->NearClippingPlaneTolerance = 0.001; + } + } + } + + // make sure the front clipping range is not too far from the far clippnig + // range, this is to make sure that the zbuffer resolution is effectively + // used + if (range[0] < this->NearClippingPlaneTolerance*range[1]) + { + range[0] = this->NearClippingPlaneTolerance*range[1]; + } + + this->ActiveCamera->SetClippingRange( range ); +} + +// Alternative version of ResetCameraClippingRange(bounds[6]); +void vtkRenderer::ResetCameraClippingRange(double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax) +{ + double bounds[6]; + + bounds[0] = xmin; + bounds[1] = xmax; + bounds[2] = ymin; + bounds[3] = ymax; + bounds[4] = zmin; + bounds[5] = zmax; + + this->ResetCameraClippingRange(bounds); +} + +// Specify the rendering window in which to draw. This is automatically set +// when the renderer is created by MakeRenderer. The user probably +// shouldn't ever need to call this method. +// no reference counting! +void vtkRenderer::SetRenderWindow(vtkRenderWindow *renwin) +{ + vtkProp *aProp; + + if (renwin != this->RenderWindow) + { + // This renderer is be dis-associated with its previous render window. + // this information needs to be passed to the renderer's actors and + // volumes so they can release and render window specific (or graphics + // context specific) information (such as display lists and texture ids) + vtkCollectionSimpleIterator pit; + this->Props->InitTraversal(pit); + for ( aProp = this->Props->GetNextProp(pit); + aProp != NULL; + aProp = this->Props->GetNextProp(pit) ) + { + aProp->ReleaseGraphicsResources(this->RenderWindow); + } + // what about lights? + // what about cullers? + + } + this->VTKWindow = renwin; + this->RenderWindow = renwin; +} + +// Given a pixel location, return the Z value +double vtkRenderer::GetZ (int x, int y) +{ + float *zPtr; + double z; + + zPtr = this->RenderWindow->GetZbufferData (x, y, x, y); + if (zPtr) + { + z = *zPtr; + delete [] zPtr; + } + else + { + z = 1.0; + } + return z; +} + + +// Convert view point coordinates to world coordinates. +void vtkRenderer::ViewToWorld() +{ + double result[4]; + result[0] = this->ViewPoint[0]; + result[1] = this->ViewPoint[1]; + result[2] = this->ViewPoint[2]; + result[3] = 1.0; + this->ViewToWorld(result[0],result[1],result[2]); + this->SetWorldPoint(result); +} + +void vtkRenderer::ViewToWorld(double &x, double &y, double &z) +{ + vtkMatrix4x4 *mat = vtkMatrix4x4::New(); + double result[4]; + + // get the perspective transformation from the active camera + mat->DeepCopy(this->ActiveCamera-> + GetCompositePerspectiveTransformMatrix( + this->GetTiledAspectRatio(),0,1)); + + // use the inverse matrix + mat->Invert(); + + // Transform point to world coordinates + result[0] = x; + result[1] = y; + result[2] = z; + result[3] = 1.0; + + mat->MultiplyPoint(result,result); + + // Get the transformed vector & set WorldPoint + // while we are at it try to keep w at one + if (result[3]) + { + x = result[0] / result[3]; + y = result[1] / result[3]; + z = result[2] / result[3]; + } + mat->Delete(); +} + +// Convert world point coordinates to view coordinates. +void vtkRenderer::WorldToView() +{ + double result[3]; + result[0] = this->WorldPoint[0]; + result[1] = this->WorldPoint[1]; + result[2] = this->WorldPoint[2]; + this->WorldToView(result[0], result[1], result[2]); + this->SetViewPoint(result[0], result[1], result[2]); +} + +// Convert world point coordinates to view coordinates. +void vtkRenderer::WorldToView(double &x, double &y, double &z) +{ + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + double view[4]; + + // get the perspective transformation from the active camera + matrix->DeepCopy(this->ActiveCamera-> + GetCompositePerspectiveTransformMatrix( + this->GetTiledAspectRatio(),0,1)); + + view[0] = x*matrix->Element[0][0] + y*matrix->Element[0][1] + + z*matrix->Element[0][2] + matrix->Element[0][3]; + view[1] = x*matrix->Element[1][0] + y*matrix->Element[1][1] + + z*matrix->Element[1][2] + matrix->Element[1][3]; + view[2] = x*matrix->Element[2][0] + y*matrix->Element[2][1] + + z*matrix->Element[2][2] + matrix->Element[2][3]; + view[3] = x*matrix->Element[3][0] + y*matrix->Element[3][1] + + z*matrix->Element[3][2] + matrix->Element[3][3]; + + if (view[3] != 0.0) + { + x = view[0]/view[3]; + y = view[1]/view[3]; + z = view[2]/view[3]; + } + matrix->Delete(); +} + +void vtkRenderer::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Near Clipping Plane Tolerance: " + << this->NearClippingPlaneTolerance << "\n"; + + os << indent << "Ambient: (" << this->Ambient[0] << ", " + << this->Ambient[1] << ", " << this->Ambient[2] << ")\n"; + + os << indent << "Backing Store: " << (this->BackingStore ? "On\n":"Off\n"); + os << indent << "Display Point: (" << this->DisplayPoint[0] << ", " + << this->DisplayPoint[1] << ", " << this->DisplayPoint[2] << ")\n"; + os << indent << "Lights:\n"; + this->Lights->PrintSelf(os,indent.GetNextIndent()); + + os << indent << "Light Follow Camera: " + << (this->LightFollowCamera ? "On\n" : "Off\n"); + + os << indent << "View Point: (" << this->ViewPoint[0] << ", " + << this->ViewPoint[1] << ", " << this->ViewPoint[2] << ")\n"; + + os << indent << "Two Sided Lighting: " + << (this->TwoSidedLighting ? "On\n" : "Off\n"); + + os << indent << "Automatic Light Creation: " + << (this->AutomaticLightCreation ? "On\n" : "Off\n"); + + os << indent << "Layer = " << this->Layer << "\n"; + os << indent << "Interactive = " << (this->Interactive ? "On" : "Off") + << "\n"; + + os << indent << "Allocated Render Time: " << this->AllocatedRenderTime + << "\n"; + + os << indent << "Last Time To Render (Seconds): " + << this->LastRenderTimeInSeconds << endl; + os << indent << "TimeFactor: " << this->TimeFactor << endl; + + os << indent << "Erase: " + << (this->Erase ? "On\n" : "Off\n"); + + // I don't want to print this since it is used just internally + // os << indent << this->NumberOfPropsRendered; +} + +int vtkRenderer::VisibleActorCount() +{ + vtkProp *aProp; + int count = 0; + + // loop through Props + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + if (aProp->GetVisibility()) + { + count++; + } + } + return count; +} + +int vtkRenderer::VisibleVolumeCount() +{ + int count = 0; + vtkProp *aProp; + + // loop through volumes + vtkCollectionSimpleIterator pit; + for (this->Props->InitTraversal(pit); + (aProp = this->Props->GetNextProp(pit)); ) + { + if (aProp->GetVisibility()) + { + count++; + } + } + return count; +} + +unsigned long int vtkRenderer::GetMTime() +{ + unsigned long mTime=this-> vtkViewport::GetMTime(); + unsigned long time; + + if ( this->ActiveCamera != NULL ) + { + time = this->ActiveCamera ->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + if ( this->CreatedLight != NULL ) + { + time = this->CreatedLight ->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + + +vtkAssemblyPath* vtkRenderer::PickProp(double selectionX, double selectionY) +{ + // initialize picking information + this->CurrentPickId = 1; // start at 1, so 0 can be a no pick + this->PickX = selectionX; + this->PickY = selectionY; + int numberPickFrom; + vtkPropCollection *props; + + // Initialize the pick (we're picking a path, the path + // includes info about nodes) + if (this->PickFromProps) + { + props = this->PickFromProps; + } + else + { + props = this->Props; + } + // number determined from number of rendering passes plus reserved "0" slot + numberPickFrom = 2*props->GetNumberOfPaths()*3 + 1; + + this->IsPicking = 1; // turn on picking + this->StartPick(numberPickFrom); + this->PathArray = new vtkAssemblyPath *[numberPickFrom]; + this->PathArrayCount = 0; + + // Actually perform the pick + this->PickRender(props); // do the pick render + this->IsPicking = 0; // turn off picking + this->DonePick(); + vtkDebugMacro(<< "z value for pick " << this->GetPickedZ() << "\n"); + vtkDebugMacro(<< "pick time " << this->LastRenderTimeInSeconds << "\n"); + + // Get the pick id of the object that was picked + if ( this->PickedProp != NULL ) + { + this->PickedProp->UnRegister(this); + this->PickedProp = NULL; + } + unsigned int pickedId = this->GetPickedId(); + if ( pickedId != 0 ) + { + pickedId--; // pick ids start at 1, so move back one + + // wrap around, as there are twice as many pickid's as PropArrayCount, + // because each Prop has both RenderOpaqueGeometry and + // RenderTranslucentGeometry called on it + pickedId = pickedId % this->PathArrayCount; + this->PickedProp = this->PathArray[pickedId]; + this->PickedProp->Register(this); + } + + // Clean up stuff from picking after we use it + delete [] this->PathArray; + this->PathArray = NULL; + + // Return the pick! + return this->PickedProp; //returns an assembly path +} + +// Do a render in pick mode. This is normally done with rendering turned off. +// Before each Prop is rendered the pick id is incremented +void vtkRenderer::PickRender(vtkPropCollection *props) +{ + vtkProp *aProp; + vtkAssemblyPath *path; + + this->InvokeEvent(vtkCommand::StartEvent,NULL); + if( props->GetNumberOfItems() <= 0) + { + return; + } + + // Create a place to store all props that remain after culling + vtkPropCollection* pickFrom = vtkPropCollection::New(); + + // Extract all the prop3D's out of the props collection. + // This collection will be further culled by using a bounding box + // pick later (vtkPicker). Things that are not vtkProp3D will get + // put into the Paths list directly. + vtkCollectionSimpleIterator pit; + for ( props->InitTraversal(pit); (aProp = props->GetNextProp(pit)); ) + { + if ( aProp->GetPickable() && aProp->GetVisibility() ) + { + if ( aProp->IsA("vtkProp3D") ) + { + pickFrom->AddItem(aProp); + } + else //must be some other type of prop (e.g., vtkActor2D) + { + for ( aProp->InitPathTraversal(); (path=aProp->GetNextPath()); ) + { + this->PathArray[this->PathArrayCount++] = path; + } + } + }//pickable & visible + }//for all props + + // For a first pass at the pick process, just use a vtkPicker to + // intersect with bounding boxes of the objects. This should greatly + // reduce the number of polygons that the hardware has to pick from, and + // speeds things up substantially. + // + // Create a picker to do the culling process + vtkPicker* cullPicker = vtkPicker::New(); + // Add each of the Actors from the pickFrom list into the picker + for ( pickFrom->InitTraversal(pit); (aProp = pickFrom->GetNextProp(pit)); ) + { + cullPicker->AddPickList(aProp); + } + + // make sure this selects from the pickers list and not the renderers list + cullPicker->PickFromListOn(); + + // do the pick + cullPicker->Pick(this->PickX, this->PickY, 0, this); + vtkProp3DCollection* cullPicked = cullPicker->GetProp3Ds(); + + // Put all the ones that were picked by the cull process + // into the PathArray to be picked from + vtkCollectionSimpleIterator p3dit; + for (cullPicked->InitTraversal(p3dit); + (aProp = cullPicked->GetNextProp3D(p3dit));) + { + if ( aProp != NULL ) + { + for ( aProp->InitPathTraversal(); (path=aProp->GetNextPath()); ) + { + this->PathArray[this->PathArrayCount++] = path; + } + } + } + + // Clean picking support objects up + pickFrom->Delete(); + cullPicker->Delete(); + + if ( this->PathArrayCount == 0 ) + { + vtkDebugMacro( << "There are no visible props!" ); + return; + } + + // do the render library specific pick render + this->DevicePickRender(); +} + +void vtkRenderer::PickGeometry() +{ + int i; + + this->NumberOfPropsRendered = 0; + + if ( this->PathArrayCount == 0 ) + { + return ; + } + + // We can render everything because if it was + // not visible it would not have been put in the + // list in the first place, and if it was allocated + // no time (culled) it would have been removed from + // the list + + // loop through props and give them a change to + // render themselves as opaque geometry + vtkProp *prop; + vtkMatrix4x4 *matrix; + for ( i = 0; i < this->PathArrayCount; i++ ) + { + this->UpdatePickId(); + prop = this->PathArray[i]->GetLastNode()->GetViewProp(); + matrix = this->PathArray[i]->GetLastNode()->GetMatrix(); + prop->PokeMatrix(matrix); + this->NumberOfPropsRendered += prop->RenderOpaqueGeometry(this); + prop->PokeMatrix(NULL); + } + + // loop through props and give them a chance to + // render themselves as translucent geometry + for ( i = 0; i < this->PathArrayCount; i++ ) + { + this->UpdatePickId(); + prop = this->PathArray[i]->GetLastNode()->GetViewProp(); + matrix = this->PathArray[i]->GetLastNode()->GetMatrix(); + prop->PokeMatrix(matrix); + this->NumberOfPropsRendered += + prop->RenderTranslucentGeometry(this); + prop->PokeMatrix(NULL); + } + + for ( i = 0; i < this->PathArrayCount; i++ ) + { + this->UpdatePickId(); + prop = this->PathArray[i]->GetLastNode()->GetViewProp(); + matrix = this->PathArray[i]->GetLastNode()->GetMatrix(); + prop->PokeMatrix(matrix); + this->NumberOfPropsRendered += + prop->RenderOverlay(this); + prop->PokeMatrix(NULL); + } + + vtkDebugMacro( << "Pick Rendered " << + this->NumberOfPropsRendered << " actors" ); + +} + + +int vtkRenderer::Transparent() +{ + // If our layer is the 0th layer, then we are not transparent, else we are. + return (this->Layer == 0 ? 0 : 1); +} + +double vtkRenderer::GetTiledAspectRatio() +{ + int usize, vsize; + this->GetTiledSize(&usize,&vsize); + + // some renderer subclasses may have more complicated computations for the + // aspect ratio. SO take that into account by computing the difference + // between our simple aspect ratio and what the actual renderer is + // reporting. + double aspect[2]; + this->ComputeAspect(); + this->GetAspect(aspect); + double aspect2[2]; + this->vtkViewport::ComputeAspect(); + this->vtkViewport::GetAspect(aspect2); + double aspectModification = aspect[0]*aspect2[1]/(aspect[1]*aspect2[0]); + + double finalAspect = 1.0; + if(vsize && usize) + { + finalAspect = aspectModification*usize/vsize; + } + return finalAspect; +} diff --git a/Rendering/vtkRenderer.h b/Rendering/vtkRenderer.h new file mode 100644 index 0000000..d349ccf --- /dev/null +++ b/Rendering/vtkRenderer.h @@ -0,0 +1,474 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRenderer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRenderer - abstract specification for renderers +// .SECTION Description +// vtkRenderer provides an abstract specification for renderers. A renderer +// is an object that controls the rendering process for objects. Rendering +// is the process of converting geometry, a specification for lights, and +// a camera view into an image. vtkRenderer also performs coordinate +// transformation between world coordinates, view coordinates (the computer +// graphics rendering coordinate system), and display coordinates (the +// actual screen coordinates on the display device). Certain advanced +// rendering features such as two-sided lighting can also be controlled. + +// .SECTION See Also +// vtkRenderWindow vtkActor vtkCamera vtkLight vtkVolume + +#ifndef __vtkRenderer_h +#define __vtkRenderer_h + +#include "vtkViewport.h" + +#include "vtkVolumeCollection.h" // Needed for access in inline members +#include "vtkActorCollection.h" // Needed for access in inline members + +class vtkRenderWindow; +class vtkVolume; +class vtkCuller; +class vtkActor; +class vtkActor2D; +class vtkCamera; +class vtkLightCollection; +class vtkCullerCollection; +class vtkLight; + +class VTK_RENDERING_EXPORT vtkRenderer : public vtkViewport +{ +public: + vtkTypeRevisionMacro(vtkRenderer,vtkViewport); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create a vtkRenderer with a black background, a white ambient light, + // two-sided lighting turned on, a viewport of (0,0,1,1), and backface + // culling turned off. + static vtkRenderer *New(); + + // Description: + // Add/Remove different types of props to the renderer. + // These methods are all synonyms to AddViewProp and RemoveViewProp. + // They are here for convenience and backwards compatibility. + void AddActor(vtkProp *p); + void AddVolume(vtkProp *p); + void RemoveActor(vtkProp *p); + void RemoveVolume(vtkProp *p); + + // Description: + // Add a light to the list of lights. + void AddLight(vtkLight *); + + // Description: + // Remove a light from the list of lights. + void RemoveLight(vtkLight *); + + // Description: + // Return the collection of lights. + vtkLightCollection *GetLights(); + + // Description: + // Create and add a light to renderer. + void CreateLight(void); + + // Description: + // Create a new Light sutible for use with this type of Renderer. + // For example, a vtkMesaRenderer should create a vtkMesaLight + // in this function. The default is to just call vtkLight::New. + virtual vtkLight *MakeLight(); + + // Description: + // Turn on/off two-sided lighting of surfaces. If two-sided lighting is + // off, then only the side of the surface facing the light(s) will be lit, + // and the other side dark. If two-sided lighting on, both sides of the + // surface will be lit. + vtkGetMacro(TwoSidedLighting,int); + vtkSetMacro(TwoSidedLighting,int); + vtkBooleanMacro(TwoSidedLighting,int); + + // Description: + // Turn on/off the automatic repositioning of lights as the camera moves. + // If LightFollowCamera is on, lights that are designated as Headlights + // or CameraLights will be adjusted to move with this renderer's camera. + // If LightFollowCamera is off, the lights will not be adjusted. + // + // (Note: In previous versions of vtk, this light-tracking + // functionality was part of the interactors, not the renderer. For + // backwards compatibility, the older, more limited interactor + // behavior is enabled by default. To disable this mode, turn the + // interactor's LightFollowCamera flag OFF, and leave the renderer's + // LightFollowCamera flag ON.) + vtkSetMacro(LightFollowCamera,int); + vtkGetMacro(LightFollowCamera,int); + vtkBooleanMacro(LightFollowCamera,int); + + // Description: + // Turn on/off a flag which disables the automatic light creation capability. + // Normally in VTK if no lights are associated with the renderer, then a light + // is automatically created. However, in special circumstances this feature is + // undesirable, so the following boolean is provided to disable automatic + // light creation. (Turn AutomaticLightCreation off if you do not want lights + // to be created.) + vtkGetMacro(AutomaticLightCreation,int); + vtkSetMacro(AutomaticLightCreation,int); + vtkBooleanMacro(AutomaticLightCreation,int); + + // Description: + // Ask the lights in the scene that are not in world space + // (for instance, Headlights or CameraLights that are attached to the + // camera) to update their geometry to match the active camera. + virtual int UpdateLightsGeometryToFollowCamera(void); + + // Description: + // Return the collection of volumes. + vtkVolumeCollection *GetVolumes(); + + // Description: + // Return any actors in this renderer. + vtkActorCollection *GetActors(); + + // Description: + // Specify the camera to use for this renderer. + void SetActiveCamera(vtkCamera *); + + // Description: + // Get the current camera. If there is not camera assigned to the + // renderer already, a new one is created automatically. + // This does *not* reset the camera. + vtkCamera *GetActiveCamera(); + + // Description: + // Create a new Camera sutible for use with this type of Renderer. + // For example, a vtkMesaRenderer should create a vtkMesaCamera + // in this function. The default is to just call vtkCamera::New. + virtual vtkCamera *MakeCamera(); + + // Description: + // When this flag is off, the renderer will not erase the background + // or the Zbuffer. It is used to have overlapping renderers. + // Both the RenderWindow Erase and Render Erase must be on + // for the camera to clear the renderer. By default, Erase is on. + vtkSetMacro(Erase, int); + vtkGetMacro(Erase, int); + vtkBooleanMacro(Erase, int); + + // Description: + // Add an culler to the list of cullers. + void AddCuller(vtkCuller *); + + // Description: + // Remove an actor from the list of cullers. + void RemoveCuller(vtkCuller *); + + // Description: + // Return the collection of cullers. + vtkCullerCollection *GetCullers(); + + // Description: + // Set the intensity of ambient lighting. + vtkSetVector3Macro(Ambient,double); + vtkGetVectorMacro(Ambient,double,3); + + // Description: + // Set/Get the amount of time this renderer is allowed to spend + // rendering its scene. This is used by vtkLODActor's. + vtkSetMacro(AllocatedRenderTime,double); + virtual double GetAllocatedRenderTime(); + + // Description: + // Get the ratio between allocated time and actual render time. + // TimeFactor has been taken out of the render process. + // It is still computed in case someone finds it useful. + // It may be taken away in the future. + virtual double GetTimeFactor(); + + // Description: + // Create an image. This is a superclass method which will in turn + // call the DeviceRender method of Subclasses of vtkRenderer + virtual void Render(); + + // Description: + // Create an image. Subclasses of vtkRenderer must implement this method. + virtual void DeviceRender() =0; + + // Description: + // Clear the image to the background color. + virtual void Clear() {}; + + // Description: + // Returns the number of visible actors. + int VisibleActorCount(); + + // Description: + // Returns the number of visible volumes. + int VisibleVolumeCount(); + + // Description: + // Compute the bounding box of all the visible props + // Used in ResetCamera() and ResetCameraClippingRange() + void ComputeVisiblePropBounds( double bounds[6] ); + + // Description: + // Wrapper-friendly version of ComputeVisiblePropBounds + double *ComputeVisiblePropBounds(); + + // Description: + // Reset the camera clipping range based on the bounds of the + // visible actors. This ensures that no props are cut off + void ResetCameraClippingRange(); + + // Description: + // Reset the camera clipping range based on a bounding box. + // This method is called from ResetCameraClippingRange() + void ResetCameraClippingRange( double bounds[6] ); + void ResetCameraClippingRange( double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax); + + // Description: + // Specify tolerance for near clipping plane distance to the camera as a + // percentage of the far clipping plane distance. By default this will be + // set to 0.01 for 16 bit zbuffers and 0.001 for higher depth z buffers + vtkSetClampMacro(NearClippingPlaneTolerance,double,0,0.99); + vtkGetMacro(NearClippingPlaneTolerance,double); + + // Description: + // Automatically set up the camera based on the visible actors. + // The camera will reposition itself to view the center point of the actors, + // and move along its initial view plane normal (i.e., vector defined from + // camera position to focal point) so that all of the actors can be seen. + void ResetCamera(); + + // Description: + // Automatically set up the camera based on a specified bounding box + // (xmin,xmax, ymin,ymax, zmin,zmax). Camera will reposition itself so + // that its focal point is the center of the bounding box, and adjust its + // distance and position to preserve its initial view plane normal + // (i.e., vector defined from camera position to focal point). Note: is + // the view plane is parallel to the view up axis, the view up axis will + // be reset to one of the three coordinate axes. + void ResetCamera(double bounds[6]); + + // Description: + // Alternative version of ResetCamera(bounds[6]); + void ResetCamera(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax); + + // Description: + // Specify the rendering window in which to draw. This is automatically set + // when the renderer is created by MakeRenderer. The user probably + // shouldn't ever need to call this method. + void SetRenderWindow(vtkRenderWindow *); + vtkRenderWindow *GetRenderWindow() {return this->RenderWindow;}; + virtual vtkWindow *GetVTKWindow(); + + // Description: + // Turn on/off using backing store. This may cause the re-rendering + // time to be slightly slower when the view changes. But it is + // much faster when the image has not changed, such as during an + // expose event. + vtkSetMacro(BackingStore,int); + vtkGetMacro(BackingStore,int); + vtkBooleanMacro(BackingStore,int); + + // Description: + // Turn on/off interactive status. An interactive renderer is one that + // can receive events from an interactor. Should only be set if + // there are multiple renderers in the same section of the viewport. + vtkSetMacro(Interactive,int); + vtkGetMacro(Interactive,int); + vtkBooleanMacro(Interactive,int); + + // Description: + // Set/Get the layer that this renderer belongs to. This is only used if + // there are layered renderers. + vtkSetMacro(Layer, int); + vtkGetMacro(Layer, int); + + // Description: + // Returns a boolean indicating if this renderer is transparent. It is + // transparent if it is not in the deepest layer of its render window. + int Transparent(); + + // Description: + // Convert world point coordinates to view coordinates. + void WorldToView(); + + // Description: + // Convert view point coordinates to world coordinates. + void ViewToWorld(); + virtual void ViewToWorld(double &wx, double &wy, double &wz); + + // Description: + // Convert world point coordinates to view coordinates. + virtual void WorldToView(double &wx, double &wy, double &wz); + + // Description: + // Given a pixel location, return the Z value. The z value is + // normalized (0,1) between the front and back clipping planes. + double GetZ (int x, int y); + + // Description: + // Return the MTime of the renderer also considering its ivars. + unsigned long GetMTime(); + + // Description: + // Get the time required, in seconds, for the last Render call. + vtkGetMacro( LastRenderTimeInSeconds, double ); + + // Description: + // Should be used internally only during a render + // Get the number of props that were rendered using a + // RenderOpaqueGeometry or RenderTranslucentGeometry call. + // This is used to know if something is in the frame buffer. + vtkGetMacro( NumberOfPropsRendered, int ); + + // Description: + // Return the prop (via a vtkAssemblyPath) that has the highest z value + // at the given x, y position in the viewport. Basically, the top most + // prop that renders the pixel at selectionX, selectionY will be returned. + // If nothing was picked then NULL is returned. This method selects from + // the renderers Prop list. + vtkAssemblyPath* PickProp(double selectionX, double selectionY); + + // Description: + // Do anything necessary between rendering the left and right viewpoints + // in a stereo render. Doesn't do anything except in the derived + // vtkIceTRenderer in ParaView. + virtual void StereoMidpoint() { return; }; + + // Description: + // Compute the aspect ratio of this renderer for the current tile. When + // tiled displays are used the aspect ratio of the renderer for a given + // tile may be diferent that the aspect ratio of the renderer when rendered + // in it entirity + double GetTiledAspectRatio(); + +protected: + vtkRenderer(); + ~vtkRenderer(); + + // internal method for doing a render for picking purposes + virtual void PickRender(vtkPropCollection *props); + virtual void PickGeometry(); + + vtkCamera *ActiveCamera; + vtkLight *CreatedLight; + + vtkLightCollection *Lights; + vtkCullerCollection *Cullers; + + vtkActorCollection *Actors; + vtkVolumeCollection *Volumes; + + double Ambient[3]; + vtkRenderWindow *RenderWindow; + double AllocatedRenderTime; + double TimeFactor; + int TwoSidedLighting; + int AutomaticLightCreation; + int BackingStore; + unsigned char *BackingImage; + int BackingStoreSize[2]; + vtkTimeStamp RenderTime; + + double LastRenderTimeInSeconds; + + int LightFollowCamera; + + // Allocate the time for each prop + void AllocateTime(); + + // Internal variables indicating the number of props + // that have been or will be rendered in each category. + int NumberOfPropsRendered; + + // A temporary list of props used for culling, and traversal + // of all props when rendering + vtkProp **PropArray; + int PropArrayCount; + + // A temporary list used for picking + vtkAssemblyPath **PathArray; + int PathArrayCount; + + // Indicates if the renderer should receive events from an interactor. + // Typically only used in conjunction with transparent renderers. + int Interactive; + + // Shows what layer this renderer belongs to. Only of interested when + // there are layered renderers. + int Layer; + + // Holds the result of ComputeVisiblePropBounds so that it is visible from + // wrapped languages + double ComputedVisiblePropBounds[6]; + + // Description: + // Specifies the minimum distance of the near clipping + // plane as a percentage of the far clipping plane distance. Values below + // this threshold are clipped to NearClippingPlaneTolerance*range[1]. + // Note that values which are too small may cause problems on systems + // with low z-buffer resolution. + double NearClippingPlaneTolerance; + + // Description: + // When this flag is off, the renderer will not erase the background + // or the Zbuffer. It is used to have overlapping renderers. + // Both the RenderWindow Erase and Render Erase must be on + // for the camera to clear the renderer. By default, Erase is on. + int Erase; + + // Description: + // Ask all props to update and draw any opaque and translucent + // geometry. This includes both vtkActors and vtkVolumes + // Returns the number of props that rendered geometry. + virtual int UpdateGeometry(void); + + // Description: + // Ask the active camera to do whatever it needs to do prior to rendering. + // Creates a camera if none found active. + virtual int UpdateCamera(void); + + // Description: + // Update the geometry of the lights in the scene that are not in world + // space (for instance, Headlights or CameraLights that are attached to the + // camera). + virtual int UpdateLightGeometry(void); + + // Description: + // Ask all lights to load themselves into rendering pipeline. + // This method will return the actual number of lights that were on. + virtual int UpdateLights(void) {return 0;}; + + // Description: + // Get the current camera and eventually reset it if it gets created + // automatically (see GetActiveCamera). + // This is mainly used internally. + vtkCamera *GetActiveCameraAndEventuallyReset(); + +private: + vtkRenderer(const vtkRenderer&); // Not implemented. + void operator=(const vtkRenderer&); // Not implemented. +}; + +inline vtkLightCollection *vtkRenderer::GetLights() { + return this->Lights; +} + +// Description: +// Get the list of cullers for this renderer. +inline vtkCullerCollection *vtkRenderer::GetCullers(){return this->Cullers;} + + +#endif diff --git a/Rendering/vtkRendererCollection.cxx b/Rendering/vtkRendererCollection.cxx new file mode 100644 index 0000000..c1bc814 --- /dev/null +++ b/Rendering/vtkRendererCollection.cxx @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRendererCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRendererCollection.h" +#include "vtkRenderWindow.h" +#include "vtkObjectFactory.h" + +#include + +vtkCxxRevisionMacro(vtkRendererCollection, "$Revision: 1.33 $"); +vtkStandardNewMacro(vtkRendererCollection); + +// Forward the Render() method to each renderer in the list. +void vtkRendererCollection::Render() +{ + vtkRenderer *ren, *firstRen; + vtkRenderWindow *renWin; + int numLayers, i; + + vtkCollectionSimpleIterator rsit; + this->InitTraversal(rsit); + firstRen = this->GetNextRenderer(rsit); + if (firstRen == NULL) + { + // We cannot determine the number of layers because there are no + // renderers. No problem, just return. + return; + } + renWin = firstRen->GetRenderWindow(); + numLayers = renWin->GetNumberOfLayers(); + + // Only have the renderers render from back to front. This is necessary + // because transparent renderers clear the z-buffer before each render and + // then overlay their image. + for (i = 0; i < numLayers; i++) + { + for (this->InitTraversal(rsit); (ren = this->GetNextRenderer(rsit)); ) + { + if (ren->GetLayer() == i) + { + ren->Render(); + } + } + } + + // Let the user know if they have put a renderer at an unused layer. + for (this->InitTraversal(rsit); (ren = this->GetNextRenderer(rsit)); ) + { + if (ren->GetLayer() < 0 || ren->GetLayer() >= numLayers) + { + vtkErrorMacro(<< "Invalid layer for renderer: not rendered."); + } + } +} + +vtkRenderer *vtkRendererCollection::GetFirstRenderer() +{ + if ( this->Top == NULL ) + { + return NULL; + } + else + { + return static_cast(this->Top->Item); + } +} + +//---------------------------------------------------------------------------- +void vtkRendererCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkRendererCollection.h b/Rendering/vtkRendererCollection.h new file mode 100644 index 0000000..1bba541 --- /dev/null +++ b/Rendering/vtkRendererCollection.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRendererCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRendererCollection - a list of renderers +// .SECTION Description +// vtkRendererCollection represents and provides methods to manipulate a list +// of renderers (i.e., vtkRenderer and subclasses). The list is unsorted and +// duplicate entries are not prevented. + +// .SECTION see also +// vtkRenderer vtkCollection + +#ifndef __vtkRendererCollection_h +#define __vtkRendererCollection_h + +#include "vtkCollection.h" +#include "vtkRenderer.h" // Needed for static cast + +class VTK_RENDERING_EXPORT vtkRendererCollection : public vtkCollection +{ + public: + static vtkRendererCollection *New(); + vtkTypeRevisionMacro(vtkRendererCollection,vtkCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a Renderer to the list. + void AddItem(vtkRenderer *a) { + this->vtkCollection::AddItem((vtkObject *)a);}; + + // Description: + // Get the next Renderer in the list. Return NULL when at the end of the + // list. + vtkRenderer *GetNextItem() { + return static_cast(this->GetNextItemAsObject());}; + + // Description: + // Forward the Render() method to each renderer in the list. + void Render(); + + // Description: + // Get the first Renderer in the list. Return NULL when at the end of the + // list. + vtkRenderer *GetFirstRenderer(); + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkRenderer *GetNextRenderer(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkRendererCollection() {}; + ~vtkRendererCollection() {}; + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + +private: + vtkRendererCollection(const vtkRendererCollection&); // Not implemented. + void operator=(const vtkRendererCollection&); // Not implemented. +}; + + +#endif diff --git a/Rendering/vtkRendererSource.cxx b/Rendering/vtkRendererSource.cxx new file mode 100644 index 0000000..2730393 --- /dev/null +++ b/Rendering/vtkRendererSource.cxx @@ -0,0 +1,354 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRendererSource.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRendererSource.h" + +#include "vtkCommand.h" +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMapper.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkStreamingDemandDrivenPipeline.h" +#include "vtkUnsignedCharArray.h" + +vtkCxxRevisionMacro(vtkRendererSource, "$Revision: 1.62 $"); +vtkStandardNewMacro(vtkRendererSource); + +vtkCxxSetObjectMacro(vtkRendererSource,Input,vtkRenderer); + +vtkRendererSource::vtkRendererSource() +{ + this->Input = NULL; + this->WholeWindow = 0; + this->RenderFlag = 0; + this->DepthValues = 0; + this->DepthValuesInScalars = 0; + + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); +} + + +vtkRendererSource::~vtkRendererSource() +{ + if (this->Input) + { + this->Input->UnRegister(this); + this->Input = NULL; + } +} + +void vtkRendererSource::RequestData(vtkInformation*, + vtkInformationVector**, + vtkInformationVector* outputVector) +{ + int numOutPts; + float x1,y1,x2,y2; + unsigned char *pixels, *ptr; + int dims[3]; + + vtkInformation* info = outputVector->GetInformationObject(0); + vtkImageData *output = + vtkImageData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT())); + int uExtent[6]; + info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent); + output->SetExtent(uExtent); + + output->AllocateScalars(); + vtkUnsignedCharArray *outScalars = + vtkUnsignedCharArray::SafeDownCast(output->GetPointData()->GetScalars()); + + if (this->Input == NULL) + { + return; + } + + if (this->DepthValuesInScalars) + { + outScalars->SetName("RGBValues"); + } + else + { + outScalars->SetName("RGBZValues"); + } + vtkRenderWindow *renWin; + + vtkDebugMacro(<<"Converting points"); + + if (this->Input == NULL ) + { + vtkErrorMacro(<<"Please specify a renderer as input!"); + return; + } + + renWin = this->Input->GetRenderWindow(); + if (renWin == NULL) + { + return; + } + + if (this->RenderFlag) + { + renWin->Render(); + } + + // calc the pixel range for the renderer + x1 = this->Input->GetViewport()[0]* + ((this->Input->GetRenderWindow())->GetSize()[0] - 1); + y1 = this->Input->GetViewport()[1]* + ((this->Input->GetRenderWindow())->GetSize()[1] - 1); + x2 = this->Input->GetViewport()[2]* + ((this->Input->GetRenderWindow())->GetSize()[0] - 1); + y2 = this->Input->GetViewport()[3]* + ((this->Input->GetRenderWindow())->GetSize()[1] - 1); + + if (this->WholeWindow) + { + x1 = 0; + y1 = 0; + x2 = (this->Input->GetRenderWindow())->GetSize()[0] - 1; + y2 = (this->Input->GetRenderWindow())->GetSize()[1] - 1; + } + + // Get origin, aspect ratio and dimensions from this->Input + dims[0] = (int)(x2 - x1 + 1); dims[1] = (int)(y2 -y1 + 1); dims[2] = 1; + output->SetDimensions(dims); + + // Allocate data. Scalar type is FloatScalars. + numOutPts = dims[0] * dims[1]; + + pixels = (this->Input->GetRenderWindow())->GetPixelData((int)x1,(int)y1, + (int)x2,(int)y2,1); + + // allocate scalars + int nb_comp = output->GetNumberOfScalarComponents(); + ptr = outScalars->WritePointer(0, numOutPts * nb_comp); + + // copy scalars over (if only RGB is requested, use the pixels directly) + if (!this->DepthValuesInScalars) + { + memcpy(ptr, pixels, numOutPts * nb_comp); + } + + // Lets get the ZBuffer also, if requested. + if (this->DepthValues || this->DepthValuesInScalars) + { + float *zBuf = (this->Input->GetRenderWindow())->GetZbufferData( + (int)x1,(int)y1, (int)x2,(int)y2); + + // If RGBZ is requested, intermix RGB with shift/scaled Z + if (this->DepthValuesInScalars) + { + float *zptr = zBuf, *zptr_end = zBuf + numOutPts; + float min = *zBuf, max = *zBuf; + while (zptr < zptr_end) + { + if (min < *zptr) { min = *zptr; } + if (max > *zptr) { max = *zptr; } + zptr++; + } + float scale = 255.0 / (max - min); + + zptr = zBuf; + unsigned char *ppixels = pixels; + while (zptr < zptr_end) + { + *ptr++ = *ppixels++; + *ptr++ = *ppixels++; + *ptr++ = *ppixels++; + *ptr++ = static_cast((*zptr++ - min) * scale); + } + } + + // If Z is requested as independent array, create it + if (this->DepthValues) + { + vtkFloatArray *zArray = vtkFloatArray::New(); + zArray->Allocate(numOutPts); + zArray->SetNumberOfTuples(numOutPts); + float *zPtr = zArray->WritePointer(0, numOutPts); + memcpy(zPtr,zBuf,numOutPts*sizeof(float)); + zArray->SetName("ZBuffer"); + output->GetPointData()->AddArray(zArray); + zArray->Delete(); + } + + delete [] zBuf; + } + + delete [] pixels; +} + +void vtkRendererSource::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "RenderFlag: " << (this->RenderFlag ? "On\n" : "Off\n"); + + if ( this->Input ) + { + os << indent << "Input:\n"; + this->Input->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Input: (none)\n"; + } + + os << indent << "Whole Window: " << (this->WholeWindow ? "On\n" : "Off\n"); + os << indent << "Depth Values: " << (this->DepthValues ? "On\n" : "Off\n"); + os << indent << "Depth Values In Scalars: " << (this->DepthValuesInScalars ? "On\n" : "Off\n"); +} + + +unsigned long vtkRendererSource::GetMTime() +{ + vtkRenderer *ren = this->GetInput(); + unsigned long t1 = this->MTime.GetMTime(); + unsigned long t2; + + if (!ren) + { + return t1; + } + + // Update information on the input and + // compute information that is general to vtkDataObject. + t2 = ren->GetMTime(); + if (t2 > t1) + { + t1 = t2; + } + vtkActorCollection *actors = ren->GetActors(); + vtkCollectionSimpleIterator ait; + actors->InitTraversal(ait); + vtkActor *actor; + vtkMapper *mapper; + vtkDataSet *data; + while ( (actor = actors->GetNextActor(ait)) ) + { + t2 = actor->GetMTime(); + if (t2 > t1) + { + t1 = t2; + } + mapper = actor->GetMapper(); + if (mapper) + { + t2 = mapper->GetMTime(); + if (t2 > t1) + { + t1 = t2; + } + data = mapper->GetInput(); + if (data) + { + data->UpdateInformation(); + } + t2 = data->GetMTime(); + if (t2 > t1) + { + t1 = t2; + } + t2 = data->GetPipelineMTime(); + if (t2 > t1) + { + t1 = t2; + } + } + } + + return t1; +} + + +//---------------------------------------------------------------------------- +void vtkRendererSource::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + vtkRenderer *ren = this->GetInput(); + if (ren == NULL || ren->GetRenderWindow() == NULL) + { + vtkErrorMacro("The input renderer has not been set yet!!!"); + return; + } + + // calc the pixel range for the renderer + float x1,y1,x2,y2; + x1 = ren->GetViewport()[0] * ((ren->GetRenderWindow())->GetSize()[0] - 1); + y1 = ren->GetViewport()[1] * ((ren->GetRenderWindow())->GetSize()[1] - 1); + x2 = ren->GetViewport()[2] * ((ren->GetRenderWindow())->GetSize()[0] - 1); + y2 = ren->GetViewport()[3] *((ren->GetRenderWindow())->GetSize()[1] - 1); + if (this->WholeWindow) + { + x1 = 0; + y1 = 0; + x2 = (this->Input->GetRenderWindow())->GetSize()[0] - 1; + y2 = (this->Input->GetRenderWindow())->GetSize()[1] - 1; + } + int extent[6] = {0, static_cast(x2-x1), + 0, static_cast(y2-y1), + 0, 0}; + + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6); + + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, + 3 + (this->DepthValuesInScalars ? 1:0)); +} + +//---------------------------------------------------------------------------- +int vtkRendererSource::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->RequestData(request, inputVector, outputVector); + return 1; + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + this->RequestInformation(request, inputVector, outputVector); + return 1; + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkRendererSource::GetOutput() +{ + return vtkImageData::SafeDownCast(this->GetOutputDataObject(0)); +} + +int vtkRendererSource::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} diff --git a/Rendering/vtkRendererSource.h b/Rendering/vtkRendererSource.h new file mode 100644 index 0000000..81d6c9e --- /dev/null +++ b/Rendering/vtkRendererSource.h @@ -0,0 +1,125 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRendererSource.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkRendererSource - take a renderer into the pipeline +// .SECTION Description +// vtkRendererSource is a source object that gets its input from a +// renderer and converts it to structured points. This can then be +// used in a visualization pipeline. You must explicitly send a +// Modify() to this object to get it to reload its data from the +// renderer. Consider using vtkWindowToImageFilter instead of this +// class. +// +// The data placed into the output is the renderer's image rgb values. +// Optionally, you can also grab the image depth (e.g., z-buffer) values, and +// place then into the output (point) field data. + +// .SECTION see also +// vtkWindowToImageFilter vtkRenderer vtkStructuredPoints + +#ifndef __vtkRendererSource_h +#define __vtkRendererSource_h + +#include "vtkAlgorithm.h" +#include "vtkImageData.h" // makes things a bit easier + +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkRendererSource : public vtkAlgorithm +{ +public: + static vtkRendererSource *New(); + vtkTypeRevisionMacro(vtkRendererSource,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Return the MTime also considering the Renderer. + unsigned long GetMTime(); + + // Description: + // Indicates what renderer to get the pixel data from. + void SetInput(vtkRenderer*); + + // Description: + // Returns which renderer is being used as the source for the pixel data. + vtkGetObjectMacro(Input,vtkRenderer); + + // Description: + // Use the entire RenderWindow as a data source or just the Renderer. + // The default is zero, just the Renderer. + vtkSetMacro(WholeWindow,int); + vtkGetMacro(WholeWindow,int); + vtkBooleanMacro(WholeWindow,int); + + // Description: + // If this flag is on, the Executing causes a render first. + vtkSetMacro(RenderFlag, int); + vtkGetMacro(RenderFlag, int); + vtkBooleanMacro(RenderFlag, int); + + // Description: + // A boolean value to control whether to grab z-buffer + // (i.e., depth values) along with the image data. The z-buffer data + // is placed into a field data attributes named "ZBuffer" . + vtkSetMacro(DepthValues,int); + vtkGetMacro(DepthValues,int); + vtkBooleanMacro(DepthValues,int); + + // Description: + // A boolean value to control whether to grab z-buffer + // (i.e., depth values) along with the image data. The z-buffer data + // is placed in the scalars as a fourth Z component (shift and scaled + // to map the full 0..255 range). + vtkSetMacro(DepthValuesInScalars,int); + vtkGetMacro(DepthValuesInScalars,int); + vtkBooleanMacro(DepthValuesInScalars,int); + + // Description: + // Get the output data object for a port on this algorithm. + vtkImageData* GetOutput(); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkRendererSource(); + ~vtkRendererSource(); + + void RequestData(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + virtual void RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + vtkRenderer *Input; + int WholeWindow; + int RenderFlag; + int DepthValues; + int DepthValuesInScalars; + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + +private: + vtkRendererSource(const vtkRendererSource&); // Not implemented. + void operator=(const vtkRendererSource&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkScalarBarActor.cxx b/Rendering/vtkScalarBarActor.cxx new file mode 100644 index 0000000..21d1eb4 --- /dev/null +++ b/Rendering/vtkScalarBarActor.cxx @@ -0,0 +1,664 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarBarActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkScalarBarActor.h" + +#include "vtkCellArray.h" +#include "vtkCellData.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkScalarsToColors.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" +#include "vtkWindow.h" +#include "vtkLookupTable.h" + +vtkCxxRevisionMacro(vtkScalarBarActor, "$Revision: 1.56 $"); +vtkStandardNewMacro(vtkScalarBarActor); + +vtkCxxSetObjectMacro(vtkScalarBarActor,LookupTable,vtkScalarsToColors); +vtkCxxSetObjectMacro(vtkScalarBarActor,LabelTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(vtkScalarBarActor,TitleTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label +// format, no title, and vertical orientation. The initial scalar bar +// size is (0.05 x 0.8) of the viewport size. +vtkScalarBarActor::vtkScalarBarActor() +{ + this->LookupTable = NULL; + this->Position2Coordinate->SetValue(0.17, 0.8); + + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.82,0.1); + + this->MaximumNumberOfColors = 64; + this->NumberOfLabels = 5; + this->NumberOfLabelsBuilt = 0; + this->Orientation = VTK_ORIENT_VERTICAL; + this->Title = NULL; + + this->LabelTextProperty = vtkTextProperty::New(); + this->LabelTextProperty->SetFontSize(12); + this->LabelTextProperty->SetBold(1); + this->LabelTextProperty->SetItalic(1); + this->LabelTextProperty->SetShadow(1); + this->LabelTextProperty->SetFontFamilyToArial(); + + this->TitleTextProperty = vtkTextProperty::New(); + this->TitleTextProperty->ShallowCopy(this->LabelTextProperty); + + this->LabelFormat = new char[8]; + sprintf(this->LabelFormat,"%s","%-#6.3g"); + + this->TitleMapper = vtkTextMapper::New(); + this->TitleActor = vtkActor2D::New(); + this->TitleActor->SetMapper(this->TitleMapper); + this->TitleActor->GetPositionCoordinate()-> + SetReferenceCoordinate(this->PositionCoordinate); + + this->TextMappers = NULL; + this->TextActors = NULL; + + this->ScalarBar = vtkPolyData::New(); + this->ScalarBarMapper = vtkPolyDataMapper2D::New(); + this->ScalarBarMapper->SetInput(this->ScalarBar); + this->ScalarBarActor = vtkActor2D::New(); + this->ScalarBarActor->SetMapper(this->ScalarBarMapper); + this->ScalarBarActor->GetPositionCoordinate()-> + SetReferenceCoordinate(this->PositionCoordinate); + this->LastOrigin[0] = 0; + this->LastOrigin[1] = 0; + this->LastSize[0] = 0; + this->LastSize[1] = 0; +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkScalarBarActor::ReleaseGraphicsResources(vtkWindow *win) +{ + this->TitleActor->ReleaseGraphicsResources(win); + if (this->TextMappers != NULL ) + { + for (int i=0; i < this->NumberOfLabelsBuilt; i++) + { + this->TextActors[i]->ReleaseGraphicsResources(win); + } + } + this->ScalarBarActor->ReleaseGraphicsResources(win); +} + +//---------------------------------------------------------------------------- +vtkScalarBarActor::~vtkScalarBarActor() +{ + if (this->LabelFormat) + { + delete [] this->LabelFormat; + this->LabelFormat = NULL; + } + + this->TitleMapper->Delete(); + this->TitleActor->Delete(); + + if (this->TextMappers != NULL ) + { + for (int i=0; i < this->NumberOfLabelsBuilt; i++) + { + this->TextMappers[i]->Delete(); + this->TextActors[i]->Delete(); + } + delete [] this->TextMappers; + delete [] this->TextActors; + } + + this->ScalarBar->Delete(); + this->ScalarBarMapper->Delete(); + this->ScalarBarActor->Delete(); + + if (this->Title) + { + delete [] this->Title; + this->Title = NULL; + } + + this->SetLookupTable(NULL); + this->SetLabelTextProperty(NULL); + this->SetTitleTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +int vtkScalarBarActor::RenderOverlay(vtkViewport *viewport) +{ + int renderedSomething = 0; + int i; + + // Everything is built, just have to render + if (this->Title != NULL) + { + renderedSomething += this->TitleActor->RenderOverlay(viewport); + } + this->ScalarBarActor->RenderOverlay(viewport); + if( this->TextActors == NULL) + { + vtkWarningMacro(<<"Need a mapper to render a scalar bar"); + return renderedSomething; + } + + for (i=0; iNumberOfLabels; i++) + { + renderedSomething += this->TextActors[i]->RenderOverlay(viewport); + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +int vtkScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int renderedSomething = 0; + int i; + int size[2]; + + if (!this->LookupTable) + { + vtkWarningMacro(<<"Need a mapper to render a scalar bar"); + return 0; + } + + if (!this->TitleTextProperty) + { + vtkErrorMacro(<<"Need title text property to render a scalar bar"); + return 0; + } + + if (!this->LabelTextProperty) + { + vtkErrorMacro(<<"Need label text property to render a scalar bar"); + return 0; + } + + // Check to see whether we have to rebuild everything + int positionsHaveChanged = 0; + if (viewport->GetMTime() > this->BuildTime || + (viewport->GetVTKWindow() && + viewport->GetVTKWindow()->GetMTime() > this->BuildTime)) + { + // if the viewport has changed we may - or may not need + // to rebuild, it depends on if the projected coords chage + int *barOrigin; + barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport); + size[0] = + this->Position2Coordinate->GetComputedViewportValue(viewport)[0] - + barOrigin[0]; + size[1] = + this->Position2Coordinate->GetComputedViewportValue(viewport)[1] - + barOrigin[1]; + if (this->LastSize[0] != size[0] || + this->LastSize[1] != size[1] || + this->LastOrigin[0] != barOrigin[0] || + this->LastOrigin[1] != barOrigin[1]) + { + positionsHaveChanged = 1; + } + } + + // Check to see whether we have to rebuild everything + if (positionsHaveChanged || + this->GetMTime() > this->BuildTime || + this->LookupTable->GetMTime() > this->BuildTime || + this->LabelTextProperty->GetMTime() > this->BuildTime || + this->TitleTextProperty->GetMTime() > this->BuildTime) + { + vtkDebugMacro(<<"Rebuilding subobjects"); + + // Delete previously constructed objects + // + if (this->TextMappers != NULL ) + { + for (i=0; i < this->NumberOfLabelsBuilt; i++) + { + this->TextMappers[i]->Delete(); + this->TextActors[i]->Delete(); + } + delete [] this->TextMappers; + delete [] this->TextActors; + } + + // Build scalar bar object; determine its type + // + // is this a vtkLookupTable or a subclass of vtkLookupTable + // with its scale set to log + // NOTE: it's possible we could to without the 'lut' variable + // later in the code, but if the vtkLookupTableSafeDownCast operation + // fails for some reason, this code will break in new ways. So, the 'LUT' + // variable is used for this operation only + vtkLookupTable *LUT = vtkLookupTable::SafeDownCast( this->LookupTable ); + int isLogTable = 0; + if ( LUT ) + { + if ( LUT->GetScale() == VTK_SCALE_LOG10 ) + { + isLogTable = 1; + } + } + + // we hard code how many steps to display + vtkScalarsToColors *lut = this->LookupTable; + int numColors = this->MaximumNumberOfColors; + double *range = lut->GetRange(); + + int numPts = 2*(numColors + 1); + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(numPts); + vtkCellArray *polys = vtkCellArray::New(); + polys->Allocate(polys->EstimateSize(numColors,4)); + vtkUnsignedCharArray *colors = vtkUnsignedCharArray::New(); + colors->SetNumberOfComponents(3); + colors->SetNumberOfTuples(numColors); + + this->ScalarBarActor->SetProperty(this->GetProperty()); + this->ScalarBar->Initialize(); + this->ScalarBar->SetPoints(pts); + this->ScalarBar->SetPolys(polys); + this->ScalarBar->GetCellData()->SetScalars(colors); + pts->Delete(); polys->Delete(); colors->Delete(); + + // get the viewport size in display coordinates + int *barOrigin, barWidth, barHeight; + barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport); + size[0] = + this->Position2Coordinate->GetComputedViewportValue(viewport)[0] - + barOrigin[0]; + size[1] = + this->Position2Coordinate->GetComputedViewportValue(viewport)[1] - + barOrigin[1]; + this->LastOrigin[0] = barOrigin[0]; + this->LastOrigin[1] = barOrigin[1]; + this->LastSize[0] = size[0]; + this->LastSize[1] = size[1]; + + // Update all the composing objects + this->TitleActor->SetProperty(this->GetProperty()); + this->TitleMapper->SetInput(this->Title); + if (this->TitleTextProperty->GetMTime() > this->BuildTime) + { + // Shallow copy here so that the size of the title prop is not affected + // by the automatic adjustment of its text mapper's size (i.e. its + // mapper's text property is identical except for the font size + // which will be modified later). This allows text actors to + // share the same text property, and in that case specifically allows + // the title and label text prop to be the same. + this->TitleMapper->GetTextProperty()->ShallowCopy(this->TitleTextProperty); + this->TitleMapper->GetTextProperty()->SetJustificationToCentered(); + } + + // find the best size for the title font + int titleSize[2]; + this->SizeTitle(titleSize, size, viewport); + + // find the best size for the ticks + int labelSize[2]; + this->AllocateAndSizeLabels(labelSize, size, viewport,range); + this->NumberOfLabelsBuilt = this->NumberOfLabels; + + // generate points + double x[3]; x[2] = 0.0; + double delta; + if ( this->Orientation == VTK_ORIENT_VERTICAL ) + { + barWidth = size[0] - 4 - labelSize[0]; + barHeight = (int)(0.86*size[1]); + delta=(double)barHeight/numColors; + for (i=0; iSetPoint(2*i,x); + x[0] = barWidth; + pts->SetPoint(2*i+1,x); + } + } + else + { + barWidth = size[0]; + barHeight = (int)(0.4*size[1]); + delta=(double)barWidth/numColors; + for (i=0; iSetPoint(2*i,x); + x[1] = 0; + pts->SetPoint(2*i+1,x); + } + } + + //polygons & cell colors + unsigned char *rgba, *rgb; + vtkIdType ptIds[4]; + for (i=0; iInsertNextCell(4,ptIds); + + if ( isLogTable ) + { + double rgbval = log10(range[0]) + + i*(log10(range[1])-log10(range[0]))/(numColors -1); + rgba = lut->MapValue(pow(10.0,rgbval)); + } + else + { + rgba = lut->MapValue(range[0] + (range[1] - range[0])* + ((double)i /(numColors-1.0))); + } + + rgb = colors->GetPointer(3*i); //write into array directly + rgb[0] = rgba[0]; + rgb[1] = rgba[1]; + rgb[2] = rgba[2]; + } + + // Now position everything properly + // + double val; + if (this->Orientation == VTK_ORIENT_VERTICAL) + { + int sizeTextData[2]; + + // center the title + this->TitleActor->SetPosition(size[0]/2, 0.9*size[1]); + + for (i=0; i < this->NumberOfLabels; i++) + { + if (this->NumberOfLabels > 1) + { + val = (double)i/(this->NumberOfLabels-1) *barHeight; + } + else + { + val = 0.5*barHeight; + } + this->TextMappers[i]->GetSize(viewport,sizeTextData); + this->TextMappers[i]->GetTextProperty()->SetJustificationToLeft(); + this->TextActors[i]->SetPosition(barWidth+3, + val - sizeTextData[1]/2); + } + } + else + { + this->TitleActor->SetPosition(size[0]/2, + barHeight + labelSize[1] + 0.1*size[1]); + for (i=0; i < this->NumberOfLabels; i++) + { + this->TextMappers[i]->GetTextProperty()->SetJustificationToCentered(); + if (this->NumberOfLabels > 1) + { + val = (double)i/(this->NumberOfLabels-1) * barWidth; + } + else + { + val = 0.5*barWidth; + } + this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]); + } + } + + this->BuildTime.Modified(); + } + + // Everything is built, just have to render + if (this->Title != NULL) + { + renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport); + } + this->ScalarBarActor->RenderOpaqueGeometry(viewport); + for (i=0; iNumberOfLabels; i++) + { + renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport); + } + + renderedSomething = (renderedSomething > 0)?(1):(0); + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +void vtkScalarBarActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->LookupTable ) + { + os << indent << "Lookup Table:\n"; + this->LookupTable->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Lookup Table: (none)\n"; + } + + if (this->TitleTextProperty) + { + os << indent << "Title Text Property:\n"; + this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Title Text Property: (none)\n"; + } + + if (this->LabelTextProperty) + { + os << indent << "Label Text Property:\n"; + this->LabelTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Label Text Property: (none)\n"; + } + + os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n"; + os << indent << "Maximum Number Of Colors: " + << this->MaximumNumberOfColors << "\n"; + os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n"; + os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n"; + + os << indent << "Orientation: "; + if ( this->Orientation == VTK_ORIENT_HORIZONTAL ) + { + os << "Horizontal\n"; + } + else + { + os << "Vertical\n"; + } + + os << indent << "Label Format: " << this->LabelFormat << "\n"; +} + +//---------------------------------------------------------------------------- +void vtkScalarBarActor::ShallowCopy(vtkProp *prop) +{ + vtkScalarBarActor *a = vtkScalarBarActor::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetPosition2(a->GetPosition2()); + this->SetLookupTable(a->GetLookupTable()); + this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors()); + this->SetOrientation(a->GetOrientation()); + this->SetLabelTextProperty(a->GetLabelTextProperty()); + this->SetTitleTextProperty(a->GetTitleTextProperty()); + this->SetLabelFormat(a->GetLabelFormat()); + this->SetTitle(a->GetTitle()); + this->GetPositionCoordinate()->SetCoordinateSystem( + a->GetPositionCoordinate()->GetCoordinateSystem()); + this->GetPositionCoordinate()->SetValue( + a->GetPositionCoordinate()->GetValue()); + this->GetPosition2Coordinate()->SetCoordinateSystem( + a->GetPosition2Coordinate()->GetCoordinateSystem()); + this->GetPosition2Coordinate()->SetValue( + a->GetPosition2Coordinate()->GetValue()); + } + + // Now do superclass + this->vtkActor2D::ShallowCopy(prop); +} + +//---------------------------------------------------------------------------- +void vtkScalarBarActor::AllocateAndSizeLabels(int *labelSize, + int *size, + vtkViewport *viewport, + double *range) +{ + labelSize[0] = labelSize[1] = 0; + + this->TextMappers = new vtkTextMapper * [this->NumberOfLabels]; + this->TextActors = new vtkActor2D * [this->NumberOfLabels]; + + char string[512]; + + double val; + int i; + + // TODO: this should be optimized, maybe by keeping a list of + // allocated mappers, in order to avoid creation/destruction of + // their underlying text properties (i.e. each time a mapper is + // created, text properties are created and shallow-assigned a font size + // which value might be "far" from the target font size). + + // is this a vtkLookupTable or a subclass of vtkLookupTable + // with its scale set to log + vtkLookupTable *LUT = vtkLookupTable::SafeDownCast( this->LookupTable ); + int isLogTable = 0; + if ( LUT ) + { + if ( LUT->GetScale() == VTK_SCALE_LOG10 ) + { + isLogTable = 1; + } + } + + for (i=0; i < this->NumberOfLabels; i++) + { + this->TextMappers[i] = vtkTextMapper::New(); + + if ( isLogTable ) + { + double lval; + if (this->NumberOfLabels > 1) + { + lval = log10(range[0]) + (double)i/(this->NumberOfLabels-1) * + (log10(range[1])-log10(range[0])); + } + else + { + lval = log10(range[0]) + 0.5*(log10(range[1])-log10(range[0])); + } + val = pow(10.0,lval); + } + else + { + if (this->NumberOfLabels > 1) + { + val = range[0] + + (double)i/(this->NumberOfLabels-1) * (range[1]-range[0]); + } + else + { + val = range[0] + 0.5*(range[1]-range[0]); + } + } + + sprintf(string, this->LabelFormat, val); + this->TextMappers[i]->SetInput(string); + + // Shallow copy here so that the size of the label prop is not affected + // by the automatic adjustment of its text mapper's size (i.e. its + // mapper's text property is identical except for the font size + // which will be modified later). This allows text actors to + // share the same text property, and in that case specifically allows + // the title and label text prop to be the same. + this->TextMappers[i]->GetTextProperty()->ShallowCopy( + this->LabelTextProperty); + + this->TextActors[i] = vtkActor2D::New(); + this->TextActors[i]->SetMapper(this->TextMappers[i]); + this->TextActors[i]->SetProperty(this->GetProperty()); + this->TextActors[i]->GetPositionCoordinate()-> + SetReferenceCoordinate(this->PositionCoordinate); + } + + if (this->NumberOfLabels) + { + int targetWidth, targetHeight; + + if ( this->Orientation == VTK_ORIENT_VERTICAL ) + { + targetWidth = (int)(0.6*size[0]); + targetHeight = (int)(0.86*size[1]/this->NumberOfLabels); + } + else + { + targetWidth = (int)(size[0]*0.8/this->NumberOfLabels); + targetHeight = (int)(0.25*size[1]); + } + + vtkTextMapper::SetMultipleConstrainedFontSize(viewport, + targetWidth, + targetHeight, + this->TextMappers, + this->NumberOfLabels, + labelSize); + } +} + +//---------------------------------------------------------------------------- +void vtkScalarBarActor::SizeTitle(int *titleSize, + int *size, + vtkViewport *viewport) +{ + titleSize[0] = titleSize[1] = 0; + + if (this->Title == NULL || !strlen(this->Title)) + { + return; + } + + int targetWidth, targetHeight; + + targetWidth = size[0]; + if ( this->Orientation == VTK_ORIENT_VERTICAL ) + { + targetHeight = (int)(0.1*size[1]); + } + else + { + targetHeight = (int)(0.25*size[1]); + } + + this->TitleMapper->SetConstrainedFontSize( + viewport, targetWidth, targetHeight); + + this->TitleMapper->GetSize(viewport, titleSize); +} diff --git a/Rendering/vtkScalarBarActor.h b/Rendering/vtkScalarBarActor.h new file mode 100644 index 0000000..3a35ae2 --- /dev/null +++ b/Rendering/vtkScalarBarActor.h @@ -0,0 +1,185 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarBarActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkScalarBarActor - Create a scalar bar with labels +// .SECTION Description +// vtkScalarBarActor creates a scalar bar with annotation text. A scalar +// bar is a legend that indicates to the viewer the correspondence between +// color value and data value. The legend consists of a rectangular bar +// made of rectangular pieces each colored a constant value. Since +// vtkScalarBarActor is a subclass of vtkActor2D, it is drawn in the image +// plane (i.e., in the renderer's viewport) on top of the 3D graphics window. +// +// To use vtkScalarBarActor you must associate a vtkScalarsToColors (or +// subclass) with it. The lookup table defines the colors and the +// range of scalar values used to map scalar data. Typically, the +// number of colors shown in the scalar bar is not equal to the number +// of colors in the lookup table, in which case sampling of +// the lookup table is performed. +// +// Other optional capabilities include specifying the fraction of the +// viewport size (both x and y directions) which will control the size +// of the scalar bar and the number of annotation labels. The actual position +// of the scalar bar on the screen is controlled by using the +// vtkActor2D::SetPosition() method (by default the scalar bar is +// centered in the viewport). Other features include the ability to +// orient the scalar bar horizontally of vertically and controlling +// the format (printf style) with which to print the labels on the +// scalar bar. Also, the vtkScalarBarActor's property is applied to +// the scalar bar and annotation (including layer, and +// compositing operator). +// +// Set the text property/attributes of the title and the labels through the +// vtkTextProperty objects associated to this actor. +// +// .SECTION Caveats +// If a vtkLogLookupTable is specified as the lookup table to use, then the +// labels are created using a logarithmic scale. +// +// .SECTION See Also +// vtkActor2D vtkTextProperty vtkTextMapper vtkPolyDataMapper2D + +#ifndef __vtkScalarBarActor_h +#define __vtkScalarBarActor_h + +#include "vtkActor2D.h" + +class vtkPolyData; +class vtkPolyDataMapper2D; +class vtkScalarsToColors; +class vtkTextMapper; +class vtkTextProperty; + +#define VTK_ORIENT_HORIZONTAL 0 +#define VTK_ORIENT_VERTICAL 1 + +class VTK_RENDERING_EXPORT vtkScalarBarActor : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkScalarBarActor,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label + // format, no title, and vertical orientation. The initial scalar bar + // size is (0.05 x 0.8) of the viewport size. + static vtkScalarBarActor *New(); + + // Description: + // Draw the scalar bar and annotation text to the screen. + int RenderOpaqueGeometry(vtkViewport* viewport); + int RenderTranslucentGeometry(vtkViewport*) { return 0; }; + int RenderOverlay(vtkViewport* viewport); + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // Set/Get the vtkLookupTable to use. The lookup table specifies the number + // of colors to use in the table (if not overridden), as well as the scalar + // range. + virtual void SetLookupTable(vtkScalarsToColors*); + vtkGetObjectMacro(LookupTable,vtkScalarsToColors); + + // Description: + // Set/Get the maximum number of scalar bar segments to show. This may + // differ from the number of colors in the lookup table, in which case + // the colors are samples from the lookup table. + vtkSetClampMacro(MaximumNumberOfColors, int, 2, VTK_LARGE_INTEGER); + vtkGetMacro(MaximumNumberOfColors, int); + + // Description: + // Set/Get the number of annotation labels to show. + vtkSetClampMacro(NumberOfLabels, int, 0, 64); + vtkGetMacro(NumberOfLabels, int); + + // Description: + // Control the orientation of the scalar bar. + vtkSetClampMacro(Orientation,int,VTK_ORIENT_HORIZONTAL, VTK_ORIENT_VERTICAL); + vtkGetMacro(Orientation, int); + void SetOrientationToHorizontal() + {this->SetOrientation(VTK_ORIENT_HORIZONTAL);}; + void SetOrientationToVertical() {this->SetOrientation(VTK_ORIENT_VERTICAL);}; + + // Description: + // Set/Get the title text property. + virtual void SetTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the labels text property. + virtual void SetLabelTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(LabelTextProperty,vtkTextProperty); + + // Description: + // Set/Get the format with which to print the labels on the scalar + // bar. + vtkSetStringMacro(LabelFormat); + vtkGetStringMacro(LabelFormat); + + // Description: + // Set/Get the title of the scalar bar actor, + vtkSetStringMacro(Title); + vtkGetStringMacro(Title); + + // Description: + // Shallow copy of a scalar bar actor. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + +protected: + vtkScalarBarActor(); + ~vtkScalarBarActor(); + + vtkScalarsToColors *LookupTable; + vtkTextProperty *TitleTextProperty; + vtkTextProperty *LabelTextProperty; + + int MaximumNumberOfColors; + int NumberOfLabels; + int NumberOfLabelsBuilt; + int Orientation; + char *Title; + char *LabelFormat; + + vtkTextMapper **TextMappers; + virtual void AllocateAndSizeLabels(int *labelSize, int *size, + vtkViewport *viewport, double *range); + +private: + vtkTextMapper *TitleMapper; + vtkActor2D *TitleActor; + + vtkActor2D **TextActors; + + vtkPolyData *ScalarBar; + vtkPolyDataMapper2D *ScalarBarMapper; + vtkActor2D *ScalarBarActor; + + vtkTimeStamp BuildTime; + int LastSize[2]; + int LastOrigin[2]; + + void SizeTitle(int *titleSize, int *size, vtkViewport *viewport); + +private: + vtkScalarBarActor(const vtkScalarBarActor&); // Not implemented. + void operator=(const vtkScalarBarActor&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkScaledTextActor.cxx b/Rendering/vtkScaledTextActor.cxx new file mode 100644 index 0000000..d98c075 --- /dev/null +++ b/Rendering/vtkScaledTextActor.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScaledTextActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkScaledTextActor.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkScaledTextActor, "$Revision: 1.28 $"); +vtkStandardNewMacro(vtkScaledTextActor); + +vtkScaledTextActor::vtkScaledTextActor() +{ + this->Position2Coordinate->SetValue(0.6, 0.1); + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.2,0.85); + this->SetScaledText(1); +} + +void vtkScaledTextActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkScaledTextActor.h b/Rendering/vtkScaledTextActor.h new file mode 100644 index 0000000..055bad6 --- /dev/null +++ b/Rendering/vtkScaledTextActor.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScaledTextActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkScaledTextActor - create text that will scale as needed +// .SECTION Description +// vtkScaledTextActor is deprecated. New code should use vtkTextActor with +// the Scaled = true option. +// +// .SECTION See Also +// vtkTextActor vtkActor2D vtkTextMapper + +#ifndef __vtkScaledTextActor_h +#define __vtkScaledTextActor_h + +#include "vtkTextActor.h" + +class VTK_RENDERING_EXPORT vtkScaledTextActor : public vtkTextActor +{ +public: + vtkTypeRevisionMacro(vtkScaledTextActor,vtkTextActor); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with a rectangle in normaled view coordinates + // of (0.2,0.85, 0.8, 0.95). + static vtkScaledTextActor *New(); + +protected: + vtkScaledTextActor(); +private: + vtkScaledTextActor(const vtkScaledTextActor&); // Not implemented. + void operator=(const vtkScaledTextActor&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkSelectVisiblePoints.cxx b/Rendering/vtkSelectVisiblePoints.cxx new file mode 100644 index 0000000..ea37d15 --- /dev/null +++ b/Rendering/vtkSelectVisiblePoints.cxx @@ -0,0 +1,245 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSelectVisiblePoints.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSelectVisiblePoints.h" + +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkDataSet.h" +#include "vtkMatrix4x4.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkSelectVisiblePoints, "$Revision: 1.36 $"); +vtkStandardNewMacro(vtkSelectVisiblePoints); + +// Instantiate object with no renderer; window selection turned off; +// tolerance set to 0.01; and select invisible off. +vtkSelectVisiblePoints::vtkSelectVisiblePoints() +{ + this->Renderer = NULL; + this->SelectionWindow = 0; + this->Selection[0] = this->Selection[2] = 0; + this->Selection[1] = this->Selection[3] = 1600; + this->Tolerance = 0.01; + this->SelectInvisible = 0; +} + +vtkSelectVisiblePoints::~vtkSelectVisiblePoints() +{ + this->SetRenderer(NULL); +} + +int vtkSelectVisiblePoints::RequestData( + vtkInformation *vtkNotUsed(request), + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + // get the info objects + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outputVector->GetInformationObject(0); + + // get the input and ouptut + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkIdType ptId, cellId; + int visible; + vtkPoints *outPts; + vtkCellArray *outputVertices; + vtkPointData *inPD=input->GetPointData(); + vtkPointData *outPD=output->GetPointData(); + vtkIdType numPts=input->GetNumberOfPoints(); + double x[4]; + double dx[3], z; + int selection[4]; + + if ( this->Renderer == NULL ) + { + vtkErrorMacro(<<"Renderer must be set"); + return 0; + } + + if ( numPts < 1 ) + { + return 0; + } + + outPts = vtkPoints::New(); + outPts->Allocate(numPts/2+1); + outPD->CopyAllocate(inPD); + + outputVertices = vtkCellArray::New(); + output->SetVerts(outputVertices); + outputVertices->Delete(); + + int *size = this->Renderer->GetRenderWindow()->GetSize(); + + // specify a selection window to avoid querying + if ( this->SelectionWindow ) + { + for (int i=0; i<4; i++) + { + selection[i] = this->Selection[i]; + } + } + else + { + selection[0] = selection[2] = 0; + selection[1] = size[0] - 1; + selection[3] = size[1] - 1; + } + + // Grab the composite perspective transform. This matrix is used to convert + // each point to view coordinates. vtkRenderer provides a WorldToView() + // method but it computes the composite perspective transform each time + // WorldToView() is called. This is expensive, so we get the matrix once + // and handle the transformation ourselves. + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + double view[4]; + matrix->DeepCopy(this->Renderer->GetActiveCamera()-> + GetCompositePerspectiveTransformMatrix( + this->Renderer->GetTiledAspectRatio(),0,1)); + + // If we have more than a few query points, we grab the z-buffer for the + // selection region all at once and probe the resulting array. When we + // have just a few points, we perform individual z-buffer queries. + const int SimpleQueryLimit = 25; + float *zPtr = NULL; + if (numPts > SimpleQueryLimit) + { + zPtr = this->Renderer->GetRenderWindow()-> + GetZbufferData(selection[0], selection[2], selection[1], selection[3]); + } + + int abort=0; + vtkIdType progressInterval=numPts/20+1; + x[3] = 1.0; + for (cellId=(-1), ptId=0; ptId < numPts && !abort; ptId++) + { + // perform conversion + input->GetPoint(ptId,x); + matrix->MultiplyPoint(x, view); + if (view[3] == 0.0) + { + continue; + } + this->Renderer->SetViewPoint(view[0]/view[3], view[1]/view[3], + view[2]/view[3]); + this->Renderer->ViewToDisplay(); + this->Renderer->GetDisplayPoint(dx); + visible = 0; + + if ( ! (ptId % progressInterval) ) + { + this->UpdateProgress((double)ptId/numPts); + abort = this->GetAbortExecute(); + } + + // check whether visible and in selection window + if ( dx[0] >= selection[0] && dx[0] <= selection[1] && + dx[1] >= selection[2] && dx[1] <= selection[3] ) + { + if (numPts > SimpleQueryLimit) + { + // Access the value from the captured zbuffer. Note, we only + // captured a portion of the zbuffer, so we need to offset dx by + // the selection window. + z = zPtr[(int)dx[0] - selection[0] + + ((int)dx[1] - selection[2]) + *(selection[1] - selection[0] + 1)]; + } + else + { + z = this->Renderer->GetZ(static_cast(dx[0]), + static_cast(dx[1])); + } + if( dx[2] < (z + this->Tolerance) ) + { + visible = 1; + } + } + + if ( (visible && !this->SelectInvisible) || + (!visible && this->SelectInvisible) ) + { + cellId = outPts->InsertNextPoint(x); + output->InsertNextCell(VTK_VERTEX, 1, &cellId); + outPD->CopyData(inPD,ptId,cellId); + } + }//for all points + + output->SetPoints(outPts); + outPts->Delete(); + output->Squeeze(); + + matrix->Delete(); + + if (zPtr) + { + delete [] zPtr; + } + + vtkDebugMacro(<<"Selected " << cellId + 1 << " out of " + << numPts << " original points"); + + return 1; +} + +unsigned long int vtkSelectVisiblePoints::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long time; + + if ( this->Renderer != NULL ) + { + time = this->Renderer->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +int vtkSelectVisiblePoints::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +void vtkSelectVisiblePoints::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Renderer: " << this->Renderer << "\n"; + os << indent << "Selection Window: " + << (this->SelectionWindow ? "On\n" : "Off\n"); + + os << indent << "Selection: \n"; + os << indent << " Xmin,Xmax: (" << this->Selection[0] << ", " + << this->Selection[1] << ")\n"; + os << indent << " Ymin,Ymax: (" << this->Selection[2] << ", " + << this->Selection[3] << ")\n"; + + os << indent << "Tolerance: " << this->Tolerance << "\n"; + os << indent << "Select Invisible: " + << (this->SelectInvisible ? "On\n" : "Off\n"); +} diff --git a/Rendering/vtkSelectVisiblePoints.h b/Rendering/vtkSelectVisiblePoints.h new file mode 100644 index 0000000..6d6f429 --- /dev/null +++ b/Rendering/vtkSelectVisiblePoints.h @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSelectVisiblePoints.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSelectVisiblePoints - extract points that are visible (based on z-buffer calculation) +// .SECTION Description +// vtkSelectVisiblePoints is a filter that selects points based on +// whether they are visible or not. Visibility is determined by +// accessing the z-buffer of a rendering window. (The position of each +// input point is converted into display coordinates, and then the +// z-value at that point is obtained. If within the user-specified +// tolerance, the point is considered visible.) +// +// Points that are visible (or if the ivar SelectInvisible is on, +// invisible points) are passed to the output. Associated data +// attributes are passed to the output as well. +// +// This filter also allows you to specify a rectangular window in display +// (pixel) coordinates in which the visible points must lie. This can be +// used as a sort of local "brushing" operation to select just data within +// a window. +// + +// .SECTION Caveats +// You must carefully synchronize the execution of this filter. The +// filter refers to a renderer, which is modified every time a render +// occurs. Therefore, the filter is always out of date, and always +// executes. You may have to perform two rendering passes, or if you +// are using this filter in conjunction with vtkLabeledDataMapper, +// things work out because 2D rendering occurs after the 3D rendering. + +#ifndef __vtkSelectVisiblePoints_h +#define __vtkSelectVisiblePoints_h + +#include "vtkPolyDataAlgorithm.h" + +class vtkRenderer; + +class VTK_RENDERING_EXPORT vtkSelectVisiblePoints : public vtkPolyDataAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkSelectVisiblePoints,vtkPolyDataAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with no renderer; window selection turned off; + // tolerance set to 0.01; and select invisible off. + static vtkSelectVisiblePoints *New(); + + // Description: + // Specify the renderer in which the visibility computation is to be + // performed. + void SetRenderer(vtkRenderer* ren) + { + if (this->Renderer != ren) + { + this->Renderer = ren; + this->Modified(); + } + } + vtkRenderer* GetRenderer() { return this->Renderer; } + + // Description: + // Set/Get the flag which enables selection in a rectangular display + // region. + vtkSetMacro(SelectionWindow,int); + vtkGetMacro(SelectionWindow,int); + vtkBooleanMacro(SelectionWindow,int); + + // Description: + // Specify the selection window in display coordinates. You must specify + // a rectangular region using (xmin,xmax,ymin,ymax). + vtkSetVector4Macro(Selection,int); + vtkGetVectorMacro(Selection,int,4); + + // Description: + // Set/Get the flag which enables inverse selection; i.e., invisible points + // are selected. + vtkSetMacro(SelectInvisible,int); + vtkGetMacro(SelectInvisible,int); + vtkBooleanMacro(SelectInvisible,int); + + // Description: + // Set/Get a tolerance to use to determine whether a point is visible. A + // tolerance is usually required because the conversion from world space + // to display space during rendering introduces numerical round-off. + vtkSetClampMacro(Tolerance,double,0.0,VTK_FLOAT_MAX); + vtkGetMacro(Tolerance,double); + + // Description: + // Return MTime also considering the renderer. + unsigned long GetMTime(); + +protected: + vtkSelectVisiblePoints(); + ~vtkSelectVisiblePoints(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); + virtual int FillInputPortInformation(int port, vtkInformation *info); + + vtkRenderer *Renderer; + + int SelectionWindow; + int Selection[4]; + int SelectInvisible; + double Tolerance; + +private: + vtkSelectVisiblePoints(const vtkSelectVisiblePoints&); // Not implemented. + void operator=(const vtkSelectVisiblePoints&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkTesting.cxx b/Rendering/vtkTesting.cxx new file mode 100644 index 0000000..bfa9807 --- /dev/null +++ b/Rendering/vtkTesting.cxx @@ -0,0 +1,676 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTesting.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTesting.h" + +#include "vtkObjectFactory.h" +#include "vtkWindowToImageFilter.h" +#include "vtkPNGWriter.h" +#include "vtkImageShiftScale.h" +#include "vtkJPEGWriter.h" +#include "vtkImageDifference.h" +#include "vtkImageResample.h" +#include "vtkPNGReader.h" +#include "vtkRenderWindow.h" +#include "vtkImageData.h" +#include "vtkTimerLog.h" +#include "vtkSmartPointer.h" +#include "vtkImageClip.h" +#include "vtkToolkits.h" +#include + +vtkStandardNewMacro(vtkTesting); +vtkCxxRevisionMacro(vtkTesting, "$Revision: 1.26 $"); +vtkCxxSetObjectMacro(vtkTesting, RenderWindow, vtkRenderWindow); + + +char* vtkTestingGetArgOrEnvOrDefault(const char* arg, + int argc, char* argv[], + const char* env, + const char *def) +{ + int index = -1; + + for (int i = 0; i < argc; i++) + { + if (strcmp(arg, argv[i]) == 0 && i < argc - 1) + { + index = i + 1; + } + } + + char* value; + + if (index != -1) + { + value = new char[strlen(argv[index]) + 1]; + strcpy(value, argv[index]); + } + else + { + char *foundenv = getenv(env); + if (foundenv) + { + value = new char[strlen(foundenv) + 1]; + strcpy(value, foundenv); + } + else + { + value = new char[strlen(def) + 1]; + strcpy(value, def); + } + } + + return value; +} + +vtkTesting::vtkTesting() +{ + this->FrontBuffer = 0; + this->RenderWindow = 0; + this->ValidImageFileName = 0; + this->ImageDifference = 0; + this->DataRoot = 0; + this->TempDirectory = 0; + this->BorderOffset = 0; + + // on construction we start the timer + this->StartCPUTime = vtkTimerLog::GetCPUTime(); + this->StartWallTime = vtkTimerLog::GetUniversalTime(); +} + +vtkTesting::~vtkTesting() +{ + this->SetRenderWindow(0); + this->SetValidImageFileName(0); + this->SetDataRoot(0); + this->SetTempDirectory(0); +} + +void vtkTesting::AddArgument(const char *arg) +{ + this->Args.push_back(arg); +} + +void vtkTesting::CleanArguments() +{ + this->Args.erase( this->Args.begin(), this->Args.end() ); +} + +const char *vtkTesting::GetDataRoot() +{ + unsigned int i; + char **argv = 0; + if (this->Args.size()) + { + argv = new char * [this->Args.size()]; + for (i = 0; i < this->Args.size(); ++i) + { + argv[i] = strdup(this->Args[i].c_str()); + } + } + +#ifdef VTK_DATA_ROOT + char *dr = vtkTestingGetArgOrEnvOrDefault( + "-D", this->Args.size(), argv, "VTK_DATA_ROOT", + VTK_DATA_ROOT); +#else + char *dr = vtkTestingGetArgOrEnvOrDefault( + "-D", this->Args.size(), argv, "VTK_DATA_ROOT", + "../../../../VTKData"); +#endif + + this->SetDataRoot(dr); + delete [] dr; + + if (argv) + { + for (i = 0; i < this->Args.size(); ++i) + { + free(argv[i]); + } + delete [] argv; + } + return this->DataRoot; +} + +const char *vtkTesting::GetTempDirectory() +{ + unsigned int i; + char **argv = 0; + if (this->Args.size()) + { + argv = new char * [this->Args.size()]; + for (i = 0; i < this->Args.size(); ++i) + { + argv[i] = strdup(this->Args[i].c_str()); + } + } + char *td = vtkTestingGetArgOrEnvOrDefault( + "-T", this->Args.size(), argv, "VTK_TEMP_DIR", + "../../../Testing/Temporary"); + this->SetTempDirectory(td); + delete [] td; + if (argv) + { + for (i = 0; i < this->Args.size(); ++i) + { + free(argv[i]); + } + delete [] argv; + } + return this->TempDirectory; +} + +const char *vtkTesting::GetValidImageFileName() +{ + this->SetValidImageFileName(0); + if (!this->IsValidImageSpecified()) + { + return this->ValidImageFileName; + } + + char **argv = 0; + unsigned int i; + if (this->Args.size()) + { + argv = new char * [this->Args.size()]; + for (i = 0; i < this->Args.size(); ++i) + { + argv[i] = strdup(this->Args[i].c_str()); + } + } + + char * baseline = vtkTestingGetArgOrEnvOrDefault( + "-B", this->Args.size(), argv, + "VTK_BASELINE_ROOT", this->GetDataRoot()); + vtkstd::string viname = baseline; + delete [] baseline; + + for (i = 0; i < (this->Args.size() - 1); ++i) + { + if ( this->Args[i] == "-V") + { + const char *ch = this->Args[i+1].c_str(); + if ( ch[0] == '/' +#ifdef _WIN32 + || (ch[0] >= 'a' && ch[0] <= 'z' && ch[1] == ':' ) + || (ch[0] >= 'A' && ch[0] <= 'Z' && ch[1] == ':' ) +#endif + ) + { + viname = this->Args[i+1]; + } + else + { + viname += "/"; + viname += this->Args[i+1]; + } + break; + } + } + + this->SetValidImageFileName(viname.c_str()); + if (argv) + { + for (i = 0; i < this->Args.size(); ++i) + { + free(argv[i]); + } + delete [] argv; + } + return this->ValidImageFileName; +} + +int vtkTesting::IsInteractiveModeSpecified() +{ + unsigned int i; + for (i = 0; i < this->Args.size(); ++i) + { + if ( this->Args[i] == "-I") + { + return 1; + } + } + return 0; +} + +int vtkTesting::IsValidImageSpecified() +{ + unsigned int i; + for (i = 1; i < this->Args.size(); ++i) + { + if ( this->Args[i-1] == "-V") + { + return 1; + } + } + return 0; +} + +char* vtkTesting::IncrementFileName(const char* fname, int count) +{ + char counts[256]; + sprintf(counts, "%d", count); + + int orgLen = static_cast(strlen(fname)); + if (orgLen < 5) + { + return 0; + } + int extLen = static_cast(strlen(counts)); + char* newFileName = new char[orgLen+extLen+2]; + strcpy(newFileName, fname); + + newFileName[orgLen-4] = '_'; + int i, marker; + for(marker=orgLen-3, i=0; marker < orgLen-3+extLen; marker++, i++) + { + newFileName[marker] = counts[i]; + } + strcpy( newFileName + marker, ".png" ); + + return newFileName; +} + +int vtkTesting::LookForFile(const char* newFileName) +{ + if (!newFileName) + { + return 0; + } + struct stat fs; + if (stat(newFileName, &fs) != 0) + { + return 0; + } + else + { + return 1; + } +} + +int vtkTesting::RegressionTest(vtkImageData* image, double thresh) +{ + int result = this->RegressionTest(image, thresh, cout); + + cout << ""; + cout << vtkTimerLog::GetUniversalTime() - this->StartWallTime; + cout << "\n"; + cout << ""; + cout << vtkTimerLog::GetCPUTime() - this->StartCPUTime; + cout << "\n"; + + return result; +} + +int vtkTesting::RegressionTest(double thresh) +{ + int result = this->RegressionTest(thresh, cout); + + cout << ""; + cout << vtkTimerLog::GetUniversalTime() - this->StartWallTime; + cout << "\n"; + cout << ""; + cout << vtkTimerLog::GetCPUTime() - this->StartCPUTime; + cout << "\n"; + + return result; +} + +int vtkTesting::RegressionTest(double thresh, ostream &os) +{ + vtkWindowToImageFilter *rt_w2if = vtkWindowToImageFilter::New(); + rt_w2if->SetInput(this->RenderWindow); + + unsigned int i; + for (i=0; iArgs.size(); i++) + { + if ( strcmp("-FrontBuffer", this->Args[i].c_str()) == 0 ) + { + this->FrontBufferOn(); + } + else if ( strcmp("-NoRerender", this->Args[i].c_str()) == 0 ) + { + rt_w2if->ShouldRerenderOff(); + } + } + + // perform and extra render to make sure it is displayed + if ( !this->FrontBuffer) + { + this->RenderWindow->Render(); + // tell it to read the back buffer + rt_w2if->ReadFrontBufferOff(); + } + else + { + // read the front buffer + rt_w2if->ReadFrontBufferOn(); + } + + int res = this->RegressionTest(rt_w2if->GetOutput(), thresh, os); + rt_w2if->Delete(); + return res; +} + +int vtkTesting::RegressionTest(vtkImageData* image, double thresh, ostream& os) +{ + // do a get to compute the real value + this->GetValidImageFileName(); + const char * tmpDir = this->GetTempDirectory(); + + // construct the names for the error images + vtkstd::string validName = this->ValidImageFileName; + vtkstd::string::size_type slash_pos = validName.rfind("/"); + if(slash_pos != vtkstd::string::npos) + { + validName = validName.substr(slash_pos + 1); + } + + // check the valid image + FILE *rt_fin = fopen(this->ValidImageFileName,"r"); + if (rt_fin) + { + fclose(rt_fin); + } + else // there was no valid image, so write one to the temp dir + { + char* vImage = new char[strlen(tmpDir) + validName.size() + 30]; + sprintf(vImage, "%s/%s", tmpDir, validName.c_str()); + vtkPNGWriter *rt_pngw = vtkPNGWriter::New(); + rt_pngw->SetFileName(vImage); + rt_pngw->SetInput(image); + rt_pngw->Write(); + rt_pngw->Delete(); + delete [] vImage; + os << "" + << this->ValidImageFileName << "" << endl; + return FAILED; + } + + vtkSmartPointer rt_png = vtkSmartPointer::New(); + rt_png->SetFileName(this->ValidImageFileName); + rt_png->Update(); + image->Update(); + + vtkSmartPointer rt_id = + vtkSmartPointer::New(); + + vtkImageClip* ic1 = vtkImageClip::New(); + ic1->SetClipData(1); + ic1->SetInput(image); + + vtkImageClip* ic2 = vtkImageClip::New(); + ic2->SetClipData(1); + ic2->SetInput(rt_png->GetOutput()); + + int* wExt1 = ic1->GetInput()->GetWholeExtent(); + int* wExt2 = ic2->GetInput()->GetWholeExtent(); + ic1->SetOutputWholeExtent(wExt1[0] + this->BorderOffset, + wExt1[1] - this->BorderOffset, + wExt1[2] + this->BorderOffset, + wExt1[3] - this->BorderOffset, + wExt1[4], + wExt1[5]); + + ic2->SetOutputWholeExtent(wExt2[0] + this->BorderOffset, + wExt2[1] - this->BorderOffset, + wExt2[2] + this->BorderOffset, + wExt2[3] - this->BorderOffset, + wExt2[4], + wExt2[5]); + + rt_id->SetInput(ic1->GetOutput()); + ic1->Delete(); + rt_id->SetImage(ic2->GetOutput()); + ic2->Delete(); + rt_id->Update(); + + double minError = rt_id->GetThresholdedError(); + this->ImageDifference = minError; + int passed = 0; + if (minError <= thresh) + { + // Make sure there was actually a difference image before + // accepting the error measure. + vtkImageData* output = rt_id->GetOutput(); + if(output) + { + int dims[3]; + output->GetDimensions(dims); + if(dims[0]*dims[1]*dims[2] > 0) + { + passed = 1; + } + else + { + vtkErrorMacro("ImageDifference produced output with no data."); + } + } + else + { + vtkErrorMacro("ImageDifference did not produce output."); + } + } + + // If the test failed with the first image (foo.png) check if there are + // images of the form foo_N.png (where N=1,2,3...) and compare against + // them. + double error; + int count=1, errIndex=-1; + char* newFileName; + while (!passed) + { + newFileName = IncrementFileName(this->ValidImageFileName, count); + if (!LookForFile(newFileName)) + { + delete[] newFileName; + break; + } + rt_png->SetFileName(newFileName); + rt_png->Update(); + rt_id->Update(); + error = rt_id->GetThresholdedError(); + if (error <= thresh) + { + // Make sure there was actually a difference image before + // accepting the error measure. + vtkImageData* output = rt_id->GetOutput(); + if(output) + { + int dims[3]; + output->GetDimensions(dims); + if(dims[0]*dims[1]*dims[2] > 0) + { + minError = error; + passed = 1; + } + } + } + else + { + if (error < minError) + { + errIndex = count; + minError = error; + } + } + ++count; + delete[] newFileName; + } + + // output some information + os << ""; + os << minError; + os << ""; + if ( errIndex <= 0) + { + os << "Standard"; + } + else + { + os << ""; + os << errIndex; + os << ""; + } + + if (passed) + { + return PASSED; + } + + os << "Failed Image Test : " << minError << endl; + if (errIndex >= 0) + { + newFileName = IncrementFileName(this->ValidImageFileName, errIndex); + rt_png->SetFileName(newFileName); + delete[] newFileName; + } + else + { + rt_png->SetFileName(this->ValidImageFileName); + } + + rt_png->Update(); + rt_id->Update(); + + // If no image differences produced an image, do not write a + // difference image. + if(minError <= 0) + { + os << "Image differencing failed to produce an image." << endl; + return FAILED; + } + + // test the directory for writing + char* diff_small = new char[strlen(tmpDir) + validName.size() + 30]; + sprintf(diff_small, "%s/%s.diff.small.jpg", tmpDir, validName.c_str()); + FILE *rt_dout = fopen(diff_small,"wb"); + if (rt_dout) + { + fclose(rt_dout); + + // write out the difference image scaled and gamma adjusted + // for the dashboard + int* rt_size = rt_png->GetOutput()->GetDimensions(); + double rt_magfactor=1.0; + if ( rt_size[1] > 250.0) + { + rt_magfactor = 250.0 / rt_size[1]; + } + vtkImageResample* rt_shrink = vtkImageResample::New(); + rt_shrink->SetInput(rt_id->GetOutput()); + rt_shrink->InterpolateOn(); + rt_shrink->SetAxisMagnificationFactor(0, rt_magfactor ); + rt_shrink->SetAxisMagnificationFactor(1, rt_magfactor ); + vtkImageShiftScale* rt_gamma = vtkImageShiftScale::New(); + rt_gamma->SetInput(rt_shrink->GetOutput()); + rt_gamma->SetShift(0); + rt_gamma->SetScale(10); + + vtkJPEGWriter* rt_jpegw_dashboard = vtkJPEGWriter::New(); + rt_jpegw_dashboard->SetFileName( diff_small ); + rt_jpegw_dashboard->SetInput(rt_gamma->GetOutput()); + rt_jpegw_dashboard->SetQuality(85); + rt_jpegw_dashboard->Write(); + + // write out the image that was generated + rt_shrink->SetInput(ic1->GetOutput()); + rt_jpegw_dashboard->SetInput(rt_shrink-> GetOutput()); + char* valid_test_small = new char[strlen(tmpDir) + validName.size() + 30]; + sprintf(valid_test_small, "%s/%s.test.small.jpg", tmpDir, + validName.c_str()); + rt_jpegw_dashboard->SetFileName(valid_test_small); + rt_jpegw_dashboard->Write(); + + // write out the valid image that matched + rt_shrink->SetInput(ic2->GetOutput()); + rt_jpegw_dashboard-> SetInput (rt_shrink->GetOutput()); + char* valid = new char[strlen(tmpDir) + validName.size() + 30]; + sprintf(valid, "%s/%s.small.jpg", tmpDir, validName.c_str()); + rt_jpegw_dashboard-> SetFileName( valid); + rt_jpegw_dashboard->Write(); + rt_jpegw_dashboard->Delete(); + + + os << ""; + os << valid_test_small; + delete [] valid_test_small; + os << ""; + os << ""; + os << diff_small; + os << ""; + os << ""; + os << valid; + os << ""; + + delete [] valid; + + rt_shrink->Delete(); + rt_gamma->Delete(); + } + + delete [] diff_small; + return FAILED; +} + +int vtkTesting::Test(int argc, char *argv[], vtkRenderWindow *rw, + double thresh ) +{ + vtkTesting * testing = vtkTesting::New(); + int i; + for (i = 0; i < argc; ++i) + { + testing->AddArgument(argv[i]); + } + + if (testing->IsInteractiveModeSpecified()) + { + testing->Delete(); + return DO_INTERACTOR; + } + + testing->FrontBufferOff(); + for (i=0; iFrontBufferOn(); + } + } + + if (testing->IsValidImageSpecified()) + { + testing->SetRenderWindow(rw); + int res = testing->RegressionTest(thresh); + testing->Delete(); + return res; + } + + testing->Delete(); + return NOT_RUN; +} + +void vtkTesting::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "RenderWindow: " << this->RenderWindow << endl; + os << indent << "ValidImageFileName: " << (this->ValidImageFileName?this->ValidImageFileName:"(none)") << endl; + os << indent << "FrontBuffer: " << (this->FrontBuffer?"On":"Off") << endl; + os << indent << "ImageDifference: " << this->ImageDifference << endl; + os << indent << "DataRoot: " << this->GetDataRoot() << endl; + os << indent << "Temp Directory: " << this->GetTempDirectory() << endl; + os << indent << "BorderOffset: " << this->GetBorderOffset() << endl; +} diff --git a/Rendering/vtkTesting.h b/Rendering/vtkTesting.h new file mode 100644 index 0000000..1e93e54 --- /dev/null +++ b/Rendering/vtkTesting.h @@ -0,0 +1,182 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTesting.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTesting - a unified VTK regression testing framework +// .SECTION Description +// +// This is a VTK regression testing framework. Looks like this: +// +// vtkTesting* t = vtkTesting::New(); +// +// Two options for setting arguments +// +// Option 1: +// for ( cc = 1; cc < argc; cc ++ ) +// { +// t->AddArgument(argv[cc]); +// } +// +// Option 2: +// t->AddArgument("-D"); +// t->AddArgument(my_data_dir); +// t->AddArgument("-V"); +// t->AddArgument(my_valid_image); +// +// ... +// +// Two options of doing testing: +// +// Option 1: +// t->SetRenderWindow(renWin); +// int res = t->RegressionTest(threshold); +// +// Option 2: +// int res = t->RegressionTest(test_image, threshold); +// +// ... +// +// if ( res == vtkTesting::PASSED ) +// { +// Test passed +// } +// else +// { +// Test failed +// } +// + +#ifndef __vtkTesting_h +#define __vtkTesting_h + +#include "vtkObject.h" +#include // used for argv +#include // used for argv + +class vtkRenderWindow; +class vtkImageData; + +class VTK_RENDERING_EXPORT vtkTesting : public vtkObject +{ +public: + static vtkTesting *New(); + vtkTypeRevisionMacro(vtkTesting,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + +//BTX + enum ReturnValue { + FAILED = 0, + PASSED = 1, + NOT_RUN = 2, + DO_INTERACTOR = 3 + }; + + static int Test(int argc, char *argv[], vtkRenderWindow *rw, double thresh); +//ETX + + // Description: + // Use front buffer for tests. By default use back buffer. + vtkSetClampMacro(FrontBuffer, int, 0, 1); + vtkBooleanMacro(FrontBuffer, int); + vtkGetMacro(FrontBuffer, int); + + // Description: + // Perform the test and return result. At the same time the output will be + // written cout + virtual int RegressionTest(double thresh); + virtual int RegressionTest(double thresh,ostream &os); + + // Description: + // Compare the image with the valid image. + virtual int RegressionTest(vtkImageData* image, double thresh); + virtual int RegressionTest(vtkImageData* image, double thresh, ostream& os); + + // Description: + // Set and get the render window that will be used for regression testing. + virtual void SetRenderWindow(vtkRenderWindow* rw); + vtkGetObjectMacro(RenderWindow, vtkRenderWindow); + + // Description: + // Set/Get the name of the valid image file + vtkSetStringMacro(ValidImageFileName); + const char *GetValidImageFileName(); + + // Description: + // Get the image difference. + vtkGetMacro(ImageDifference, double); + + // Description: + // Pass the command line arguments into this class to be processed. Many of + // the Get methods such as GetValidImage and GetBaselineRoot rely on the + // arguments to be passed in prior to retrieving these values. Just call + // AddArgument for each argument that was passed into the command line + void AddArgument(const char *argv); + + // Description + // This method delete all arguments in vtkTesting, this way you can reuse + // it in a loop where you would have multiple testing. + void CleanArguments(); + + // Description: + // Get some paramters from the command line arguments, env, or defaults + const char *GetDataRoot(); + vtkSetStringMacro(DataRoot); + + // Description: + // Get some paramters from the command line arguments, env, or defaults + const char *GetTempDirectory(); + vtkSetStringMacro(TempDirectory); + + // Description: + // Is a valid image specified on the command line areguments? + int IsValidImageSpecified(); + + // Description: + // Is the interactive mode specified? + int IsInteractiveModeSpecified(); + + // Description: + // Number of pixels added as borders to avoid problems with + // window decorations added by some window managers. + vtkSetMacro(BorderOffset, int); + vtkGetMacro(BorderOffset, int); + +protected: + vtkTesting(); + ~vtkTesting(); + + static char* IncrementFileName(const char* fname, int count); + static int LookForFile(const char* newFileName); + + int FrontBuffer; + vtkRenderWindow* RenderWindow; + char* ValidImageFileName; + double ImageDifference; + char *TempDirectory; + int BorderOffset; + +//BTX + vtkstd::vector Args; +//ETX + char *DataRoot; + double StartWallTime; + double StartCPUTime; + +private: + vtkTesting(const vtkTesting&); // Not implemented. + void operator=(const vtkTesting&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkTextActor.cxx b/Rendering/vtkTextActor.cxx new file mode 100644 index 0000000..3888cb9 --- /dev/null +++ b/Rendering/vtkTextActor.cxx @@ -0,0 +1,377 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextActor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextActor.h" + +#include "vtkObjectFactory.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" +#include "vtkWindow.h" + +vtkCxxRevisionMacro(vtkTextActor, "$Revision: 1.22 $"); +vtkStandardNewMacro(vtkTextActor); + +vtkCxxSetObjectMacro(vtkTextActor,TextProperty,vtkTextProperty); + +// ---------------------------------------------------------------------------- +vtkTextActor::vtkTextActor() +{ + // To remain compatible with code using vtkActor2D, we must set + // position coord to Viewport, not Normalized Viewport + // so...compute equivalent coords for initial position + this->PositionCoordinate->SetCoordinateSystemToViewport(); + + this->AdjustedPositionCoordinate = vtkCoordinate::New(); + this->AdjustedPositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + + // Create default text mapper + vtkTextMapper *mapper = vtkTextMapper::New(); + this->SetMapper(mapper); + mapper->Delete(); + + this->TextProperty = vtkTextProperty::New(); + + this->LastOrigin[0] = 0; + this->LastOrigin[1] = 0; + + this->LastSize[0] = 0; + this->LastSize[1] = 0; + + this->MinimumSize[0] = 10; + this->MinimumSize[1] = 10; + + this->MaximumLineHeight = 1.0; + this->ScaledText = 0; + this->AlignmentPoint = 0; + + this->FontScaleExponent = 1; + this->FontScaleTarget = 10; + + // IMPORTANT: backward compat: the buildtime is updated here so that the + // TextProperty->GetMTime() is lower than BuildTime. In that case, this + // will prevent the TextProperty to override the mapper's TextProperty + // when the actor is created after the mapper. + this->BuildTime.Modified(); +} + +// ---------------------------------------------------------------------------- +vtkTextActor::~vtkTextActor() +{ + this->AdjustedPositionCoordinate->Delete(); + this->SetTextProperty(NULL); +} + +// ---------------------------------------------------------------------------- +void vtkTextActor::SetNonLinearFontScale(double exp, int tgt) +{ + if (this->FontScaleExponent == exp && this->FontScaleTarget == tgt) + { + return; + } + this->FontScaleExponent = exp; + this->FontScaleTarget = tgt; + this->Modified(); +} + +// ---------------------------------------------------------------------------- +void vtkTextActor::SetMapper(vtkTextMapper *mapper) +{ + this->vtkActor2D::SetMapper( mapper ); +} + +// ---------------------------------------------------------------------------- +void vtkTextActor::SetMapper(vtkMapper2D *mapper) +{ + if (mapper->IsA("vtkTextMapper")) + { + this->SetMapper( (vtkTextMapper *)mapper ); + } + else + { + vtkErrorMacro("Must use vtkTextMapper for this class"); + } + } + +// ---------------------------------------------------------------------------- +void vtkTextActor::SetInput(const char* input) +{ + vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper(); + if (!mapper) + { + vtkErrorMacro("Actor has not vtkTextMapper"); + } + mapper->SetInput(input); +} + +// ---------------------------------------------------------------------------- +char* vtkTextActor::GetInput() +{ + vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper(); + if (!mapper) + { + vtkErrorMacro("Actor has not vtkTextMapper"); + } + return mapper->GetInput(); +} + +// ---------------------------------------------------------------------------- +void vtkTextActor::ShallowCopy(vtkProp *prop) +{ + vtkTextActor *a = vtkTextActor::SafeDownCast(prop); + if ( a != NULL ) + { + this->SetPosition2(a->GetPosition2()); + this->SetMinimumSize(a->GetMinimumSize()); + this->SetMaximumLineHeight(a->GetMaximumLineHeight()); + this->SetScaledText(a->GetScaledText()); + this->SetAlignmentPoint(a->GetAlignmentPoint()); + this->SetTextProperty(a->GetTextProperty()); + } + // Now do superclass (mapper is handled by it as well). + this->vtkActor2D::ShallowCopy(prop); +} + +// ---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void vtkTextActor::ReleaseGraphicsResources(vtkWindow *win) +{ + this->vtkActor2D::ReleaseGraphicsResources(win); +} + +// ---------------------------------------------------------------------------- +int vtkTextActor::RenderOverlay(vtkViewport *viewport) +{ + // Everything is built in RenderOpaqueGeometry, just have to render + return this->vtkActor2D::RenderOverlay(viewport); +} + +// ---------------------------------------------------------------------------- +int vtkTextActor::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int size[2]; + + vtkTextMapper *mapper = (vtkTextMapper *)this->GetMapper(); + if (!mapper) + { + vtkErrorMacro(<<"Need mapper to render text actor"); + return 0; + } + + vtkTextProperty *tprop = this->GetTextProperty(); + vtkTextProperty *tpropmapper = mapper->GetTextProperty(); + if (!tprop && !tpropmapper) + { + vtkErrorMacro(<<"Need text property to render text actor"); + return 0; + } + + if (tprop && tprop->GetMTime() > this->BuildTime) + { + // Shallow copy here so that the size of the text prop is not affected + // by the automatic adjustment of its text mapper's size (i.e. its + // mapper's text property is identical except for the font size + // which will be modified later). This allows text actors to + // share the same text property. + if (tpropmapper && tprop->GetMTime() > tpropmapper->GetMTime()) + { + tpropmapper->ShallowCopy(tprop); + } + } + + int *point1, *point2; + double u, v; + + // we don't need to do anything additional, just pass the call + // right through to the actor + if (!this->ScaledText) + { + point1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + point2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + size[0] = point2[0] - point1[0]; + size[1] = point2[1] - point1[1]; + switch (this->AlignmentPoint) + { + case 0: + u = point1[0]; + v = point1[1]; + break; + case 1: + u = point1[0] + size[0]/2; + v = point1[1]; + break; + case 2: + u = point2[0]; + v = point1[1]; + break; + case 3: + u = point1[0]; + v = point1[1] + size[1]/2; + break; + case 4: + u = point1[0] + size[0]/2; + v = point1[1] + size[1]/2; + break; + case 5: + u = point2[0]; + v = point1[1] + size[1]/2; + break; + case 6: + u = point1[0]; + v = point2[1]; + break; + case 7: + u = point1[0] + size[0]/2; + v = point2[1]; + break; + case 8: + u = point2[0]; + v = point2[1]; + break; + } + + viewport->ViewportToNormalizedViewport(u, v); + this->AdjustedPositionCoordinate->SetValue(u,v); + this->BuildTime.Modified(); + } + else + { + point1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + point2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + + size[0] = point2[0] - point1[0]; + size[1] = point2[1] - point1[1]; + + // Check to see whether we have to rebuild everything + int positionsHaveChanged = 0; + if (viewport->GetMTime() > this->BuildTime || + (viewport->GetVTKWindow() && + viewport->GetVTKWindow()->GetMTime() > this->BuildTime)) + { + // if the viewport has changed we may - or may not need + // to rebuild, it depends on if the projected coords change + if (this->LastSize[0] != size[0] || this->LastSize[1] != size[1] || + this->LastOrigin[0] != point1[0] || this->LastOrigin[1] != point1[1]) + { + positionsHaveChanged = 1; + } + } + + // Check to see whether we have to rebuild everything + if (positionsHaveChanged || + this->GetMTime() > this->BuildTime || + mapper->GetMTime() > this->BuildTime || + tpropmapper->GetMTime() > this->BuildTime) + { + vtkDebugMacro(<<"Rebuilding text"); + + this->LastOrigin[0] = point1[0]; + this->LastOrigin[1] = point1[1]; + + // Lets try to minimize the number of times we change the font size. + // If the width of the font box has not changed by more than a pixel + // (numerical issues) do not recompute font size. + if (mapper->GetMTime() > this->BuildTime || + tpropmapper->GetMTime() > this->BuildTime || + this->LastSize[0] < size[0] - 1 || this->LastSize[1] < size[1] - 1 || + this->LastSize[0] > size[0] + 1 || this->LastSize[1] > size[1] + 1) + { + this->LastSize[0] = size[0]; + this->LastSize[1] = size[1]; + + // limit by minimum size + if (this->MinimumSize[0] > size[0]) + { + size[0] = this->MinimumSize[0]; + } + if (this->MinimumSize[1] > size[1]) + { + size[1] = this->MinimumSize[1]; + } + int max_height = (int)(this->MaximumLineHeight * (float)size[1]); + + int fsize = mapper->SetConstrainedFontSize( + viewport, + size[0], + (size[1] < max_height ? size[1] : max_height)); + // apply non-linear scaling + fsize = static_cast(pow(static_cast(fsize),this->FontScaleExponent)* + pow(this->FontScaleTarget, 1.0 - this->FontScaleExponent)); + tpropmapper->SetFontSize(fsize); + } + + // now set the position of the Text + int fpos[2]; + switch (tpropmapper->GetJustification()) + { + case VTK_TEXT_LEFT: + fpos[0] = point1[0]; + break; + case VTK_TEXT_CENTERED: + fpos[0] = point1[0] + size[0]/2; + break; + case VTK_TEXT_RIGHT: + fpos[0] = point1[0]+size[0]; + break; + } + switch (tpropmapper->GetVerticalJustification()) + { + case VTK_TEXT_TOP: + fpos[1] = point1[1] + size[1]; + break; + case VTK_TEXT_CENTERED: + fpos[1] = point1[1] + size[1]/2; + break; + case VTK_TEXT_BOTTOM: + fpos[1] = point1[1]; + break; + } + + u = fpos[0]; + v = fpos[1]; + + viewport->ViewportToNormalizedViewport(u, v); + this->AdjustedPositionCoordinate->SetValue(u,v); + this->BuildTime.Modified(); + } + } + + // Everything is built, just have to render + return this->vtkActor2D::RenderOpaqueGeometry(viewport); +} + +// ---------------------------------------------------------------------------- +void vtkTextActor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->TextProperty) + { + os << indent << "Text Property:\n"; + this->TextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Text Property: (none)\n"; + } + + os << indent << "MaximumLineHeight: " << this->MaximumLineHeight << endl; + os << indent << "MinimumSize: " << this->MinimumSize[0] << " " << this->MinimumSize[1] << endl; + os << indent << "ScaledText: " << this->ScaledText << endl; + os << indent << "AlignmentPoint: " << this->AlignmentPoint << endl; + os << indent << "FontScaleExponent: " << this->FontScaleExponent << endl; + os << indent << "FontScaleTarget: " << this->FontScaleTarget << endl; +} diff --git a/Rendering/vtkTextActor.h b/Rendering/vtkTextActor.h new file mode 100644 index 0000000..33bd3f2 --- /dev/null +++ b/Rendering/vtkTextActor.h @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextActor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextActor - An actor that displays text. Scaled or unscaled +// .SECTION Description +// vtkTextActor can be used to place text annotation into a window. +// When ScaledText is false, the text is fixed font and operation is +// the same as a vtkTextMapper/vtkActor2D pair. +// When ScaledText is true, the font resizes such that the text fits inside the +// box defined by the position 1 & 2 coordinates. This class replaces the +// deprecated vtkScaledTextActor and acts as a convenient wrapper for +// a vtkTextMapper/vtkActor2D pair. +// Set the text property/attributes through the vtkTextProperty associated to +// this actor. +// +// .SECTION See Also +// vtkActor2D vtkTextMapper vtkTextProperty + +#ifndef __vtkTextActor_h +#define __vtkTextActor_h + +#include "vtkActor2D.h" + +// We need to include vtkTextMapper here otherwise we have an ambiguous +// case of vtkMapper2D or vtkTextMapper in SetMapper(vtkTextMapper *mapper); +// - two members with identical prototypes! +class vtkTextProperty; +class vtkTextMapper; + +class VTK_RENDERING_EXPORT vtkTextActor : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(vtkTextActor,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with a rectangle in normaled view coordinates + // of (0.2,0.85, 0.8, 0.95). + static vtkTextActor *New(); + + // Description: + // Shallow copy of this text actor. Overloads the virtual + // vtkProp method. + void ShallowCopy(vtkProp *prop); + + // Description: + // Override the vtkTextMapper that defines the text to be drawn. + // One will be created by default if none is supplied + void SetMapper(vtkTextMapper *mapper); + + // Description: + // Set the text string to be displayed. "\n" is recognized + // as a carriage return/linefeed (line separator). + // Convenience method to the underlying mapper + void SetInput(const char *inputString); + char *GetInput(); + + // Description: + // Set/Get the minimum size in pixels for this actor. + // Defaults to 10,10. + // Not valid when ScaledText = false + vtkSetVector2Macro(MinimumSize,int); + vtkGetVector2Macro(MinimumSize,int); + + // Description: + // Set/Get the maximum height of a line of text as a + // percentage of the vertical area allocated to this + // scaled text actor. Defaults to 1.0. + // Not valid when ScaledText = false + vtkSetMacro(MaximumLineHeight,float); + vtkGetMacro(MaximumLineHeight,float); + + // Description: + // Turn on or off the ScaledText option. + // When text is scaled, the bounding rectangle is used to fit the text + // When ScaledText is off, the text is rendered at a fixed font size + vtkSetMacro(ScaledText,int); + vtkGetMacro(ScaledText,int); + vtkBooleanMacro(ScaledText,int); + + // Description: + // Set/Get the Alignment point for unscaled (fixed fontsize) text + // if zero (default), the text aligns itself to the bottom left corner + // (which is defined by the PositionCoordinate) + // otherwise the text aligns itself to corner/midpoint or centre + // @verbatim + // 6 7 8 Otherwise the text aligns itself to corner/midpoint + // 3 4 5 or centre of the box defined by the position 1 & 2 + // 0 1 2 coordinates according to the diagram on the left. + // @endverbatim + vtkSetClampMacro(AlignmentPoint,int,0,8) + vtkGetMacro(AlignmentPoint,int); + + // Description: + // Return the actual vtkCoordinate reference that the mapper should use + // to position the actor. This is used internally by the mappers and should + // be overridden in specialized subclasses and otherwise ignored. + vtkCoordinate *GetActualPositionCoordinate(void) + { return this->AdjustedPositionCoordinate; } + + // Description: + // Set/Get the text property. + virtual void SetTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TextProperty,vtkTextProperty); + + // Description: + // Enable non-linear scaling of font sizes. This is useful in combination + // with scaled text. With small windows you want to use the entire scaled + // text area. With larger windows you want to reduce the font size some so + // that the entire area is not used. These values modify the computed font + // size as follows: + // newFontSize = pow(FontSize,exponent)*pow(target,1.0 - exponent) + // typically exponent should be around 0.7 and target should be around 10 + virtual void SetNonLinearFontScale(double exponent, int target); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Draw the text actor to the screen. + int RenderOpaqueGeometry(vtkViewport* viewport); + int RenderTranslucentGeometry(vtkViewport* ) {return 0;}; + int RenderOverlay(vtkViewport* viewport); +//ETX + +protected: + // Description: + // Hide access methods which use superclass vtkMapper2D and not vtkTextMapper + void SetMapper(vtkMapper2D *mapper); + + vtkTextActor(); + ~vtkTextActor(); + + int MinimumSize[2]; + float MaximumLineHeight; + double FontScaleExponent; + double FontScaleTarget; + int ScaledText; + int AlignmentPoint; + + vtkCoordinate *AdjustedPositionCoordinate; + vtkTextProperty *TextProperty; + + vtkTimeStamp BuildTime; + int LastSize[2]; + int LastOrigin[2]; + +private: + vtkTextActor(const vtkTextActor&); // Not implemented. + void operator=(const vtkTextActor&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkTextActor3D.cxx b/Rendering/vtkTextActor3D.cxx new file mode 100644 index 0000000..0c78a6a --- /dev/null +++ b/Rendering/vtkTextActor3D.cxx @@ -0,0 +1,339 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextActor3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextActor3D.h" + +#include "vtkObjectFactory.h" +#include "vtkCamera.h" +#include "vtkImageActor.h" +#include "vtkImageData.h" +#include "vtkTransform.h" +#include "vtkTextProperty.h" +#include "vtkRenderer.h" +#include "vtkWindow.h" +#include "vtkFreeTypeUtilities.h" +#include "vtkMatrix4x4.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkTextActor3D, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkTextActor3D); + +vtkCxxSetObjectMacro(vtkTextActor3D, TextProperty, vtkTextProperty); + +// ---------------------------------------------------------------------------- +vtkTextActor3D::vtkTextActor3D() +{ + this->Input = NULL; + this->ImageActor = vtkImageActor::New(); + this->ImageData = NULL; + this->TextProperty = NULL; + + this->BuildTime.Modified(); + + this->SetTextProperty(vtkTextProperty::New()); + this->TextProperty->Delete(); + + this->ImageActor->InterpolateOn(); +} + +// -------------------------------------------------------------------------- +vtkTextActor3D::~vtkTextActor3D() +{ + this->SetTextProperty(NULL); + this->SetInput(NULL); + + if (this->ImageActor) + { + this->ImageActor->Delete(); + this->ImageActor = NULL; + } + + if (this->ImageData) + { + this->ImageData->Delete(); + this->ImageData = NULL; + } +} + +// -------------------------------------------------------------------------- +void vtkTextActor3D::ShallowCopy(vtkProp *prop) +{ + vtkTextActor3D *a = vtkTextActor3D::SafeDownCast(prop); + if (a != NULL) + { + this->SetInput(a->GetInput()); + this->SetTextProperty(a->GetTextProperty()); + } + + this->Superclass::ShallowCopy(prop); +} + +// -------------------------------------------------------------------------- + +double* vtkTextActor3D::GetBounds() +{ + if (this->ImageActor) + { + return this->ImageActor->GetBounds(); + } + + return NULL; +} + +// -------------------------------------------------------------------------- +void vtkTextActor3D::ReleaseGraphicsResources(vtkWindow *win) +{ + if (this->ImageActor) + { + this->ImageActor->ReleaseGraphicsResources(win); + } + + this->Superclass::ReleaseGraphicsResources(win); +} + +// -------------------------------------------------------------------------- +int vtkTextActor3D::RenderOverlay(vtkViewport *viewport) +{ + int rendered_something = 0; + + if (this->UpdateImageActor() && this->ImageActor) + { + rendered_something += this->ImageActor->RenderOverlay(viewport); + } + + return rendered_something; +} + +// -------------------------------------------------------------------------- +int vtkTextActor3D::RenderTranslucentGeometry(vtkViewport *viewport) +{ + int rendered_something = 0; + + if (this->UpdateImageActor() && this->ImageActor) + { + rendered_something += + this->ImageActor->RenderTranslucentGeometry(viewport); + } + + return rendered_something; +} + +// -------------------------------------------------------------------------- +int vtkTextActor3D::RenderOpaqueGeometry(vtkViewport *viewport) +{ + int rendered_something = 0; + + if (this->UpdateImageActor() && this->ImageActor) + { + rendered_something += + this->ImageActor->RenderOpaqueGeometry(viewport); + } + + return rendered_something; +} + +// -------------------------------------------------------------------------- +int vtkTextActor3D::UpdateImageActor() +{ + // Need text prop + + if (!this->TextProperty) + { + vtkErrorMacro(<<"Need a text property to render text actor"); + return 0; + } + + // No input, the assign the image actor a zilch input + + if (!this->Input || !*this->Input) + { + if (this->ImageActor) + { + this->ImageActor->SetInput(NULL); + } + return 1; + } + + // Do we need to (re-)render the text ? + // Yes if: + // - instance has been modified since last build + // - text prop has been modified since last build + // - ImageData ivar has not been allocated yet + + if (this->GetMTime() > this->BuildTime || + this->TextProperty->GetMTime() > this->BuildTime || + !this->ImageData) + { + //cout << "Need to re-render " << this->GetMTime() << ", " << this->TextProperty->GetMTime() << ", " << this->BuildTime << endl; + + this->BuildTime.Modified(); + + // Get the bounding box of the text to render + // If the bounding box is invalid, then there is nothing to render + // assign the image actor a nada input + + vtkFreeTypeUtilities *fu = vtkFreeTypeUtilities::GetInstance(); + if (!fu) + { + vtkErrorMacro(<<"Failed getting the FreeType utilities instance"); + return 0; + } + + int text_bbox[4]; + fu->GetBoundingBox(this->TextProperty, this->Input, text_bbox); + if (!fu->IsBoundingBoxValid(text_bbox)) + { + if (this->ImageActor) + { + this->ImageActor->SetInput(NULL); + } + return 1; + } + + // The bounding box was the area that is going to be filled with pixels + // given a text origin of (0, 0). Now get the real size we need, i.e. + // the full extent from the origin to the bounding box. + + int text_size[2]; + text_size[0] = (text_bbox[1] - text_bbox[0] + 1) + abs(text_bbox[0]); + text_size[1] = (text_bbox[3] - text_bbox[2] + 1) + abs(text_bbox[2]); + + // If the RGBA image data is too small, resize it to the next power of 2 + // WARNING: at this point, since this image is going to be a texture + // we should limit its size or query the hardware + + if (!this->ImageData) + { + this->ImageData = vtkImageData::New(); + this->ImageData->SetScalarTypeToUnsignedChar(); + this->ImageData->SetNumberOfScalarComponents(4); + this->ImageData->SetSpacing(1.0, 1.0, 1.0); + } + + // If the current image data is too small to render the text, + // or more than twice as big (too hungry), then resize + + int img_dims[3], new_img_dims[3]; + this->ImageData->GetDimensions(img_dims); + + if (img_dims[0] < text_size[0] || img_dims[1] < text_size[1] || + text_size[0] * 2 < img_dims[0] || text_size[1] * 2 < img_dims[0]) + { + new_img_dims[0] = 1 << (int)ceil(log((double)text_size[0]) / log(2.0)); + new_img_dims[1] = 1 << (int)ceil(log((double)text_size[1]) / log(2.0)); + new_img_dims[2] = 1; + if (new_img_dims[0] != img_dims[0] || + new_img_dims[1] != img_dims[1] || + new_img_dims[2] != img_dims[2]) + { + //cout << "I need: " << text_size[0] << "x" << text_size[1] << ", I resize to: " << new_img_dims[0] << "x" << new_img_dims[1] << endl; + this->ImageData->SetDimensions(new_img_dims); + this->ImageData->AllocateScalars(); + this->ImageData->UpdateInformation(); + this->ImageData->SetUpdateExtent(this->ImageData->GetWholeExtent()); + this->ImageData->PropagateUpdateExtent(); + if (this->ImageActor) + { + this->ImageActor->SetDisplayExtent( + this->ImageData->GetWholeExtent()); + } + } + } + + // Render inside the image data + + int x = (text_bbox[0] < 0 ? -text_bbox[0] : 0); + int y = (text_bbox[2] < 0 ? -text_bbox[2] : 0); + +#if 0 + char *ptr = (char*)this->ImageData->GetScalarPointer(); + int nb_comp = this->ImageData->GetNumberOfScalarComponents(); + char *ptr_end = ptr + this->ImageData->GetNumberOfPoints() * nb_comp; + memset(ptr, 0, ptr_end - ptr); + ptr += nb_comp - 1; + while (ptr < ptr_end) + { + *ptr = 255.0; + ptr += nb_comp; + } +#else + memset(this->ImageData->GetScalarPointer(), + 0, + (this->ImageData->GetNumberOfPoints() * + this->ImageData->GetNumberOfScalarComponents())); +#endif + + if (!fu->RenderString( + this->TextProperty, this->Input, x, y, this->ImageData)) + { + vtkErrorMacro(<<"Failed rendering text to buffer"); + return 0; + } + + // Set the image data origin so that oriented text is placed properly + // Also take shadow into account, we want the text to be on the baseline + + if (this->TextProperty->GetShadow()) + { + // this is wrong + //x += this->TextProperty->GetShadowOffset()[0]; + //y += this->TextProperty->GetShadowOffset()[1]; + } + this->ImageData->SetOrigin(-x, -y, 0); + + // Associate the image data (should be up to date now) to the image actor + + if (this->ImageActor) + { + this->ImageActor->SetInput(this->ImageData); + } + } + + // Position the actor + + if (this->ImageActor) + { + // Which one is faster ? +#if 1 + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + this->GetMatrix(matrix); + this->ImageActor->SetUserMatrix(matrix); + matrix->Delete(); +#else + this->ImageActor->SetPosition(this->GetPosition()); + this->ImageActor->SetScale(this->GetScale()); + this->ImageActor->SetOrientation(this->GetOrientation()); +#endif + } + + return 1; +} + +// -------------------------------------------------------------------------- +void vtkTextActor3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Input: " << (this->Input ? this->Input : "(none)") << "\n"; + + if (this->TextProperty) + { + os << indent << "Text Property:\n"; + this->TextProperty->PrintSelf(os, indent.GetNextIndent()); + } + else + { + os << indent << "Text Property: (none)\n"; + } +} diff --git a/Rendering/vtkTextActor3D.h b/Rendering/vtkTextActor3D.h new file mode 100644 index 0000000..ff9d96c --- /dev/null +++ b/Rendering/vtkTextActor3D.h @@ -0,0 +1,107 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextActor3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextActor3D - An actor that displays text. +// .SECTION Description +// The input text is rendered into a buffer, which in turn is used as a +// texture applied onto a quad (a vtkImageActor is used under the hood). +// .SECTION Warning +// This class is experimental at the moment. +// - The orientation is not optimized, the quad should be oriented, not +// the text itself when it is rendered in the buffer (we end up with +// excessively big textures for 45 degrees angles). +// This will be fixed first. +// - No checking is done at the moment regarding hardware texture size limits. +// - Alignment is not supported (soon). +// - Multiline is not supported. +// - Need to fix angle out of 0<->360 +// +// .SECTION See Also +// vtkProp3D + +#ifndef __vtkTextActor3D_h +#define __vtkTextActor3D_h + +#include "vtkProp3D.h" + +class vtkImageActor; +class vtkImageData; +class vtkTextProperty; + +class VTK_RENDERING_EXPORT vtkTextActor3D : public vtkProp3D +{ +public: + static vtkTextActor3D *New(); + vtkTypeRevisionMacro(vtkTextActor3D,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set the text string to be displayed. + vtkSetStringMacro(Input); + vtkGetStringMacro(Input); + + // Description: + // Set/Get the text property. + virtual void SetTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TextProperty,vtkTextProperty); + + // Description: + // Shallow copy of this text actor. Overloads the virtual + // vtkProp method. + void ShallowCopy(vtkProp *prop); + + // Description: + // Get the bounds for this Prop3D as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). + virtual double *GetBounds(); + + //BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Draw the text actor to the screen. + int RenderOpaqueGeometry(vtkViewport* viewport); + int RenderTranslucentGeometry(vtkViewport* viewport); + int RenderOverlay(vtkViewport* viewport); + //ETX + +protected: + vtkTextActor3D(); + ~vtkTextActor3D(); + + char *Input; + + vtkImageActor *ImageActor; + vtkImageData *ImageData; + vtkTextProperty *TextProperty; + + vtkTimeStamp BuildTime; + + virtual int UpdateImageActor(); + +private: + vtkTextActor3D(const vtkTextActor3D&); // Not implemented. + void operator=(const vtkTextActor3D&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkTextMapper.cxx b/Rendering/vtkTextMapper.cxx new file mode 100644 index 0000000..29c93b2 --- /dev/null +++ b/Rendering/vtkTextMapper.cxx @@ -0,0 +1,507 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextMapper.h" + +#include "vtkImagingFactory.h" +#include "vtkTextProperty.h" +#include "vtkToolkits.h" + +vtkCxxRevisionMacro(vtkTextMapper, "$Revision: 1.54 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkTextMapper); +//---------------------------------------------------------------------------- + +vtkCxxSetObjectMacro(vtkTextMapper,TextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Creates a new text mapper + +vtkTextMapper::vtkTextMapper() +{ + this->Input = (char*)NULL; + // consistent Register/unregister + this->TextProperty = NULL; + this->SetTextProperty(vtkTextProperty::New()); + this->TextProperty->Delete(); + + this->TextLines = NULL; + this->NumberOfLines = 0; + this->NumberOfLinesAllocated = 0; +} + +//---------------------------------------------------------------------------- +// Shallow copy of an actor. + +void vtkTextMapper::ShallowCopy(vtkTextMapper *tm) +{ + this->SetInput(tm->GetInput()); + this->SetTextProperty(tm->GetTextProperty()); + + this->SetClippingPlanes(tm->GetClippingPlanes()); +} + +//---------------------------------------------------------------------------- +vtkTextMapper *vtkTextMapper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkImagingFactory::CreateInstance("vtkTextMapper"); + return (vtkTextMapper*)ret; +} + +//---------------------------------------------------------------------------- +vtkTextMapper::~vtkTextMapper() +{ + if (this->Input) + { + delete [] this->Input; + this->Input = NULL; + } + + if (this->TextLines != NULL) + { + for (int i=0; i < this->NumberOfLinesAllocated; i++) + { + this->TextLines[i]->Delete(); + } + delete [] this->TextLines; + } + + this->SetTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +void vtkTextMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->TextProperty) + { + os << indent << "Text Property:\n"; + this->TextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Text Property: (none)\n"; + } + + os << indent << "Input: " << (this->Input ? this->Input : "(none)") << "\n"; + os << indent << "NumberOfLines: " << this->NumberOfLines << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkTextMapper::GetWidth(vtkViewport* viewport) +{ + int size[2]; + this->GetSize(viewport, size); + return size[0]; +} + +//---------------------------------------------------------------------------- +int vtkTextMapper::GetHeight(vtkViewport* viewport) +{ + int size[2]; + this->GetSize(viewport, size); + return size[1]; +} + +//---------------------------------------------------------------------------- +#define VTK_TM_DEBUG 0 + +int vtkTextMapper::SetConstrainedFontSize(vtkViewport *viewport, + int targetWidth, + int targetHeight) +{ + // If target "empty" + + if (targetWidth == 0 && targetHeight == 0) + { + return 0; + } + + // Get text property + + vtkTextProperty *tprop = this->GetTextProperty(); + if (!tprop) + { + vtkErrorMacro(<<"Need text property to apply constaint"); + return 0; + } + + int fontSize = tprop->GetFontSize(); +#if VTK_TM_DEBUG + int oldfontSize = fontSize; +#endif + + // Use the last size as a first guess + + int tempi[2]; + this->GetSize(viewport, tempi); + +#if 1 + // Now get an estimate of the target font size using bissection + +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetConstrainedFontSize: init size: (%d, %d) => (%d, %d)\n", tempi[0], tempi[1], targetWidth, targetHeight); +#endif + + // Based on experimentation with big and small font size increments, + // ceil() gives the best result. + // big: floor: 10749, ceil: 10106, cast: 10749, vtkMath::Round: 10311 + // small: floor: 12122, ceil: 11770, cast: 12122, vtkMath::Round: 11768 + // I guess the best optim would be to have a look at the shape of the + // font size growth curve (probably not that linear) + + if (tempi[0] && tempi[1]) + { + float fx = (float)targetWidth / (float)tempi[0]; + float fy = (float)targetHeight / (float)tempi[1] ; + fontSize = (int)ceil((float)fontSize * ((fx <= fy) ? fx : fy)); + tprop->SetFontSize(fontSize); + this->GetSize(viewport, tempi); + } + +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetConstrainedFontSize: estimate size: %2d (was: %2d)\n", + fontSize, oldfontSize); + printf("vtkTextMapper::SetConstrainedFontSize: estimate size: (%d, %d) => (%d, %d)\n", tempi[0], tempi[1], targetWidth, targetHeight); +#endif +#endif + + // While the size is too small increase it + + while (tempi[1] <= targetHeight && + tempi[0] <= targetWidth && + fontSize < 100) + { + fontSize++; +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetConstrainedFontSize: search+ size: %2d\n", + fontSize); +#endif + tprop->SetFontSize(fontSize); + this->GetSize(viewport, tempi); + } + +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetConstrainedFontSize: search+ size: (%d, %d) => (%d, %d)\n", tempi[0], tempi[1], targetWidth, targetHeight); +#endif + + // While the size is too large decrease it + + while ((tempi[1] > targetHeight || tempi[0] > targetWidth) + && fontSize > 0) + { + fontSize--; +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetConstrainedFontSize: search- size: %2d\n", + fontSize); +#endif + tprop->SetFontSize(fontSize); + this->GetSize(viewport, tempi); + } + +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetConstrainedFontSize: search- size: (%d, %d) => (%d, %d)\n", tempi[0], tempi[1], targetWidth, targetHeight); + + printf("vtkTextMapper::SetConstrainedFontSize: new size: %2d (was: %2d)\n", + fontSize, oldfontSize); +#endif + + return fontSize; +} + +//---------------------------------------------------------------------------- +int vtkTextMapper::SetMultipleConstrainedFontSize(vtkViewport *viewport, + int targetWidth, + int targetHeight, + vtkTextMapper **mappers, + int nbOfMappers, + int *maxResultingSize) +{ + maxResultingSize[0] = maxResultingSize[1] = 0; + + if (nbOfMappers == 0) + { + return 0; + } + + int fontSize, aSize; + + // First try to find the constrained font size of the first mapper: it + // will be used minimize the search for the remaining mappers, given the + // fact that all mappers are likely to have the same constrained font size. + + int i, first; + for (first = 0; first < nbOfMappers && !mappers[first]; first++) {} + + if (first >= nbOfMappers) + { + return 0; + } + + fontSize = mappers[first]->SetConstrainedFontSize( + viewport, targetWidth, targetHeight); + +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetMultipleConstrainedFontSize: first size: %2d\n", + fontSize); +#endif + + // Find the constrained font size for the remaining mappers and + // pick the smallest + + for (i = first + 1; i < nbOfMappers; i++) + { + if (mappers[i]) + { + mappers[i]->GetTextProperty()->SetFontSize(fontSize); + aSize = mappers[i]->SetConstrainedFontSize( + viewport, targetWidth, targetHeight); + if (aSize < fontSize) + { + fontSize = aSize; + } + } + } + +#if VTK_TM_DEBUG + printf("vtkTextMapper::SetMultipleConstrainedFontSize: smallest size: %2d\n", + fontSize); +#endif + + // Assign the smallest size to all text mappers and find the largest area + + int tempi[2]; + for (i = first; i < nbOfMappers; i++) + { + if (mappers[i]) + { + mappers[i]->GetTextProperty()->SetFontSize(fontSize); + mappers[i]->GetSize(viewport, tempi); + if (tempi[0] > maxResultingSize[0]) + { + maxResultingSize[0] = tempi[0]; + } + if (tempi[1] > maxResultingSize[1]) + { + maxResultingSize[1] = tempi[1]; + } + } + } + + // The above code could be optimized further since the mappers + // labels are likely to have the same height: in that case, we could + // have searched for the largest label, find the constrained size + // for this one, then applied this size to all others. But who + // knows, maybe one day the text property will support a text + // orientation/rotation, and in that case the height will vary. + + return fontSize; +} + + +//---------------------------------------------------------------------------- +// Parse the input and create multiple text mappers if multiple lines +// (delimited by \n) are specified. + +void vtkTextMapper::SetInput(const char *input) +{ + if ( this->Input && input && (!strcmp(this->Input,input))) + { + return; + } + if (this->Input) + { + delete [] this->Input; + } + if (input) + { + this->Input = new char[strlen(input)+1]; + strcpy(this->Input,input); + } + else + { + this->Input = NULL; + } + this->Modified(); + + int numLines = this->GetNumberOfLines(input); + + if ( numLines <= 1) // a line with no "\n" + { + this->NumberOfLines = numLines; + } + + else //multiple lines + { + char *line; + int i; + + if ( numLines > this->NumberOfLinesAllocated ) + { + // delete old stuff + if ( this->TextLines ) + { + for (i=0; i < this->NumberOfLinesAllocated; i++) + { + this->TextLines[i]->Delete(); + } + delete [] this->TextLines; + } + + // allocate new text mappers + this->NumberOfLinesAllocated = numLines; + this->TextLines = new vtkTextMapper *[numLines]; + for (i=0; i < numLines; i++) + { + this->TextLines[i] = vtkTextMapper::New(); + } + } //if we need to reallocate + + // set the input strings + this->NumberOfLines = numLines; + for (i=0; i < this->NumberOfLines; i++) + { + line = this->NextLine(input, i); + this->TextLines[i]->SetInput( line ); + delete [] line; + } + } +} + +//---------------------------------------------------------------------------- +// Determine the number of lines in the Input string (delimited by "\n"). + +int vtkTextMapper::GetNumberOfLines(const char *input) +{ + if ( input == NULL || input[0] == '\0') + { + return 0; + } + + int numLines=1; + const char *ptr = input; + + while ( ptr != NULL ) + { + if ( (ptr=strstr(ptr,"\n")) != NULL ) + { + numLines++; + ptr++; //skip over \n + } + } + + return numLines; +} + +//---------------------------------------------------------------------------- +// Get the next \n delimited line. Returns a string that +// must be freed by the calling function. + +char *vtkTextMapper::NextLine(const char *input, int lineNum) +{ + const char *ptr, *ptrEnd; + int strLen; + char *line; + + ptr = input; + for (int i=0; i != lineNum; i++) + { + ptr = strstr(ptr,"\n"); + ptr++; + } + ptrEnd = strstr(ptr,"\n"); + if ( ptrEnd == NULL ) + { + ptrEnd = strchr(ptr, '\0'); + } + + strLen = ptrEnd - ptr; + line = new char[strLen+1]; + strncpy(line, ptr, strLen); + line[strLen] = '\0'; + + return line; +} + +//---------------------------------------------------------------------------- +// Get the size of a multi-line text string + +void vtkTextMapper::GetMultiLineSize(vtkViewport* viewport, int size[2]) +{ + int i; + int lineSize[2]; + + vtkTextProperty *tprop = this->GetTextProperty(); + if (!tprop) + { + vtkErrorMacro(<<"Need text property to get multiline size of mapper"); + size[0] = size[1] = 0; + return; + } + + lineSize[0] = lineSize[1] = size[0] = size[1] = 0; + for ( i=0; i < this->NumberOfLines; i++ ) + { + this->TextLines[i]->GetTextProperty()->ShallowCopy(tprop); + this->TextLines[i]->GetSize(viewport, lineSize); + size[0] = (lineSize[0] > size[0] ? lineSize[0] : size[0]); + size[1] = (lineSize[1] > size[1] ? lineSize[1] : size[1]); + } + + // add in the line spacing + this->LineSize = size[1]; + size[1] = (int)((float)size[1] * (1.0 + (this->NumberOfLines - 1) * tprop->GetLineSpacing())); +} + +//---------------------------------------------------------------------------- +void vtkTextMapper::RenderOverlayMultipleLines(vtkViewport *viewport, + vtkActor2D *actor) +{ + float offset = 0.0; + int size[2]; + // make sure LineSize is up to date + this->GetMultiLineSize(viewport,size); + + vtkTextProperty *tprop = this->GetTextProperty(); + if (!tprop) + { + vtkErrorMacro(<<"Need text property to render multiple lines of mapper"); + return; + } + + switch (tprop->GetVerticalJustification()) + { + case VTK_TEXT_TOP: + offset = 0.0; + break; + case VTK_TEXT_CENTERED: + offset = (-this->NumberOfLines + 1.0) / 2.0; + break; + case VTK_TEXT_BOTTOM: + offset = -this->NumberOfLines + 1.0; + break; + } + + for (int lineNum=0; lineNum < this->NumberOfLines; lineNum++) + { + this->TextLines[lineNum]->GetTextProperty()->ShallowCopy(tprop); + this->TextLines[lineNum]->GetTextProperty()->SetLineOffset + (tprop->GetLineOffset() + (int)((float)this->LineSize * (lineNum + offset) * tprop->GetLineSpacing())); + this->TextLines[lineNum]->RenderOverlay(viewport,actor); + } +} diff --git a/Rendering/vtkTextMapper.h b/Rendering/vtkTextMapper.h new file mode 100644 index 0000000..22f1fe1 --- /dev/null +++ b/Rendering/vtkTextMapper.h @@ -0,0 +1,121 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextMapper - 2D text annotation +// .SECTION Description +// vtkTextMapper provides 2D text annotation support for vtk. It is a +// vtkMapper2D that can be associated with a vtkActor2D and placed into a +// vtkRenderer. +// +// To use vtkTextMapper, specify an input text string. + +// .SECTION See Also +// vtkMapper2D vtkActor2D vtkLegendBoxActor vtkCaptionActor2D vtkVectorText vtkTextProperty + +#ifndef __vtkTextMapper_h +#define __vtkTextMapper_h + +#include "vtkMapper2D.h" + +class vtkActor2D; +class vtkTextProperty; +class vtkViewport; + +class VTK_RENDERING_EXPORT vtkTextMapper : public vtkMapper2D +{ +public: + vtkTypeRevisionMacro(vtkTextMapper,vtkMapper2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates a new text mapper. + static vtkTextMapper *New(); + + // Description: + // Return the size[2]/width/height of the rectangle required to draw this + // mapper (in pixels). + virtual void GetSize(vtkViewport*, int size[2]) {size[0]=size[0];}; + virtual int GetWidth(vtkViewport*v); + virtual int GetHeight(vtkViewport*v); + + // Description: + // Set the input text string to the mapper. The mapper recognizes "\n" + // as a carriage return/linefeed (line separator). + virtual void SetInput(const char *inputString); + vtkGetStringMacro(Input); + + // Description: + // Set/Get the text property. + virtual void SetTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TextProperty,vtkTextProperty); + + vtkGetMacro(NumberOfLines,int); + + // Description: + // Shallow copy of an actor. + void ShallowCopy(vtkTextMapper *tm); + + // Description: + // Determine the number of lines in the Input string (delimited by "\n"). + int GetNumberOfLines(const char *input); + + // Description: + // Set and return the font size required to make this mapper fit in a given + // target rectangle (width * height, in pixels). + virtual int SetConstrainedFontSize(vtkViewport*, + int targetWidth, int targetHeight); + + // Description: + // Set and return the font size required to make each element of an array of + // mappers fit in a given rectangle (width * height, in pixels). + // This font size is the smallest size that was required to fit the largest + // mapper in this constraint. + // The resulting maximum area of the mappers is also returned. + static int SetMultipleConstrainedFontSize(vtkViewport*, + int targetWidth, int targetHeight, + vtkTextMapper** mappers, + int nbOfMappers, + int* maxResultingSize); + + // Description: + // Get the available system font size matching a font size. + virtual int GetSystemFontSize(int size) + { return size; }; + +protected: + vtkTextMapper(); + ~vtkTextMapper(); + + char* Input; + vtkTextProperty *TextProperty; + + int LineSize; + int NumberOfLines; + int NumberOfLinesAllocated; + + vtkTextMapper **TextLines; + + // These functions are used to parse, process, and render multiple lines + + char *NextLine(const char *input, int lineNum); + void GetMultiLineSize(vtkViewport* viewport, int size[2]); + void RenderOverlayMultipleLines(vtkViewport *viewport, vtkActor2D *actor); + +private: + vtkTextMapper(const vtkTextMapper&); // Not implemented. + void operator=(const vtkTextMapper&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkTextProperty.cxx b/Rendering/vtkTextProperty.cxx new file mode 100644 index 0000000..cabc2af --- /dev/null +++ b/Rendering/vtkTextProperty.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextProperty.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTextProperty.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkTextProperty, "$Revision: 1.11 $"); +vtkStandardNewMacro(vtkTextProperty); + +//---------------------------------------------------------------------------- +vtkTextProperty::vtkTextProperty() +{ + this->Color[0] = 1.0; + this->Color[1] = 1.0; + this->Color[2] = 1.0; + + this->Opacity = 1.0; + + this->FontFamily = VTK_ARIAL; + this->FontSize = 12; + + this->Bold = 0; + this->Italic = 0; + this->Shadow = 0; + this->ShadowOffset[0] = 1; + this->ShadowOffset[1] = -1; + + this->Justification = VTK_TEXT_LEFT; + this->VerticalJustification = VTK_TEXT_BOTTOM; + + this->LineOffset = 0.0; + this->LineSpacing = 1.1; // why not 1.0 ? + + this->Orientation = 0.0; +} + +//---------------------------------------------------------------------------- +void vtkTextProperty::ShallowCopy(vtkTextProperty *tprop) +{ + if (!tprop) + { + return; + } + + this->SetColor(tprop->GetColor()); + this->SetOpacity(tprop->GetOpacity()); + + this->SetFontFamily(tprop->GetFontFamily()); + this->SetFontSize(tprop->GetFontSize()); + + this->SetBold(tprop->GetBold()); + this->SetItalic(tprop->GetItalic()); + this->SetShadow(tprop->GetShadow()); + + this->SetOrientation(tprop->GetOrientation()); + + this->SetJustification(tprop->GetJustification()); + this->SetVerticalJustification(tprop->GetVerticalJustification()); + + this->SetLineOffset(tprop->GetLineOffset()); + this->SetLineSpacing(tprop->GetLineSpacing()); + +} + +//---------------------------------------------------------------------------- +void vtkTextProperty::GetShadowColor(double color[3]) +{ +#if 1 + double average = (this->Color[0] + this->Color[1] + this->Color[2]) / 3.0; +#else + double average = (0.30 * this->Color[0] + + 0.59 * this->Color[1] + + 0.11 * this->Color[2]); +#endif + double shadow_i = average > 0.5 ? 0.0 : 1.0; + color[0] = color[1] = color[2] = shadow_i; +} + +//---------------------------------------------------------------------------- +void vtkTextProperty::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Color: (" << this->Color[0] << ", " + << this->Color[1] << ", " << this->Color[2] << ")\n"; + + os << indent << "Opacity: " << this->Opacity << "\n"; + + os << indent << "FontFamily: " << this->GetFontFamilyAsString() << "\n"; + os << indent << "FontSize: " << this->FontSize << "\n"; + + os << indent << "Bold: " << (this->Bold ? "On\n" : "Off\n"); + os << indent << "Italic: " << (this->Italic ? "On\n" : "Off\n"); + os << indent << "Shadow: " << (this->Shadow ? "On\n" : "Off\n"); + os << indent << "ShadowOffset: (" << this->ShadowOffset[0] << ", " + << this->ShadowOffset[1] << ")\n"; + + os << indent << "Justification: " + << this->GetJustificationAsString() << "\n"; + + os << indent << "Vertical justification: " + << this->GetVerticalJustificationAsString() << "\n"; + + os << indent << "Orientation: " << this->Orientation << "\n"; + + os << indent << "Line Offset: " << this->LineOffset << "\n"; + os << indent << "Line Spacing: " << this->LineSpacing << "\n"; +} diff --git a/Rendering/vtkTextProperty.h b/Rendering/vtkTextProperty.h new file mode 100644 index 0000000..9a48692 --- /dev/null +++ b/Rendering/vtkTextProperty.h @@ -0,0 +1,220 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTextProperty.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTextProperty - represent text properties. +// .SECTION Description +// vtkTextProperty is an object that represents text properties. +// The primary properties that can be set are color, opacity, font size, +// font family horizontal and vertical justification, bold/italic/shadow +// styles. +// .SECTION See Also +// vtkTextMapper vtkTextActor vtkLegendBoxActor vtkCaptionActor2D + +#ifndef __vtkTextProperty_h +#define __vtkTextProperty_h + +#include "vtkObject.h" + +class VTK_RENDERING_EXPORT vtkTextProperty : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkTextProperty,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates a new text property with font size 12, bold off, italic off, + // and Arial font. + static vtkTextProperty *New(); + + // Description: + // Set the color of the text. + vtkSetVector3Macro(Color,double); + vtkGetVector3Macro(Color,double); + + // Description: + // Set/Get the text's opacity. 1.0 is totally opaque and 0.0 is completely + // transparent. + vtkSetMacro(Opacity,double); + vtkGetMacro(Opacity,double); + + // Description: + // Set/Get the font family. Three font types are allowed: Arial (VTK_ARIAL), + // Courier (VTK_COURIER), and Times (VTK_TIMES). + vtkSetClampMacro(FontFamily,int,VTK_ARIAL,VTK_TIMES); + vtkGetMacro(FontFamily, int); + void SetFontFamilyToArial() { this->SetFontFamily(VTK_ARIAL); }; + void SetFontFamilyToCourier() { this->SetFontFamily(VTK_COURIER);}; + void SetFontFamilyToTimes() { this->SetFontFamily(VTK_TIMES); }; + char *GetFontFamilyAsString(); + static char *GetFontFamilyAsString( int f ); + + // Description: + // Set/Get the font size (in points). + vtkSetClampMacro(FontSize,int,0,VTK_LARGE_INTEGER); + vtkGetMacro(FontSize, int); + + // Description: + // Enable/disable text bolding. + vtkSetMacro(Bold, int); + vtkGetMacro(Bold, int); + vtkBooleanMacro(Bold, int); + + // Description: + // Enable/disable text italic. + vtkSetMacro(Italic, int); + vtkGetMacro(Italic, int); + vtkBooleanMacro(Italic, int); + + // Description: + // Enable/disable text shadow. + vtkSetMacro(Shadow, int); + vtkGetMacro(Shadow, int); + vtkBooleanMacro(Shadow, int); + + // Description: + // Set/Get the shadow offset, i.e. the distance from the text to + // its shadow, in the same unit as FontSize. + vtkSetVector2Macro(ShadowOffset,int); + vtkGetVectorMacro(ShadowOffset,int,2); + + // Description: + // Get the shadow color. It is computed from the Color ivar + void GetShadowColor(double color[3]); + + // Description: + // Set/Get the horizontal justification to left (default), centered, + // or right. + vtkSetClampMacro(Justification,int,VTK_TEXT_LEFT,VTK_TEXT_RIGHT); + vtkGetMacro(Justification,int); + void SetJustificationToLeft() + { this->SetJustification(VTK_TEXT_LEFT);}; + void SetJustificationToCentered() + { this->SetJustification(VTK_TEXT_CENTERED);}; + void SetJustificationToRight() + { this->SetJustification(VTK_TEXT_RIGHT);}; + char *GetJustificationAsString(); + + // Description: + // Set/Get the vertical justification to bottom (default), middle, + // or top. + vtkSetClampMacro(VerticalJustification,int,VTK_TEXT_BOTTOM,VTK_TEXT_TOP); + vtkGetMacro(VerticalJustification,int); + void SetVerticalJustificationToBottom() + {this->SetVerticalJustification(VTK_TEXT_BOTTOM);}; + void SetVerticalJustificationToCentered() + {this->SetVerticalJustification(VTK_TEXT_CENTERED);}; + void SetVerticalJustificationToTop() + {this->SetVerticalJustification(VTK_TEXT_TOP);}; + char *GetVerticalJustificationAsString(); + + // Description: + // Set/Get the text's orientation (in degrees). + vtkSetMacro(Orientation,double); + vtkGetMacro(Orientation,double); + + // Description: + // Set/Get the (extra) spacing between lines, + // expressed as a text height multiplication factor. + vtkSetMacro(LineSpacing, double); + vtkGetMacro(LineSpacing, double); + + // Description: + // Set/Get the vertical offset (measured in pixels). + vtkSetMacro(LineOffset, double); + vtkGetMacro(LineOffset, double); + + // Description: + // Shallow copy of a text property. + void ShallowCopy(vtkTextProperty *tprop); + +protected: + vtkTextProperty(); + ~vtkTextProperty() {}; + + double Color[3]; + double Opacity; + int FontFamily; + int FontSize; + int Bold; + int Italic; + int Shadow; + int ShadowOffset[2]; + int Justification; + int VerticalJustification; + double Orientation; + double LineOffset; + double LineSpacing; + +private: + vtkTextProperty(const vtkTextProperty&); // Not implemented. + void operator=(const vtkTextProperty&); // Not implemented. +}; + +inline char *vtkTextProperty::GetFontFamilyAsString( int f ) +{ + if ( f == VTK_ARIAL ) + { + return (char *)"Arial"; + } + else if ( f == VTK_COURIER ) + { + return (char *)"Courier"; + } + else if ( f == VTK_TIMES ) + { + return (char *)"Times"; + } + return (char *)"Unknown"; +} + +inline char *vtkTextProperty::GetFontFamilyAsString(void) +{ + return vtkTextProperty::GetFontFamilyAsString( this->GetFontFamily() ); +} + +inline char *vtkTextProperty::GetJustificationAsString(void) +{ + if (this->Justification == VTK_TEXT_LEFT) + { + return (char *)"Left"; + } + else if (this->Justification == VTK_TEXT_CENTERED) + { + return (char *)"Centered"; + } + else if (this->Justification == VTK_TEXT_RIGHT) + { + return (char *)"Right"; + } + return (char *)"Unknown"; +} + +inline char *vtkTextProperty::GetVerticalJustificationAsString(void) +{ + if (this->VerticalJustification == VTK_TEXT_BOTTOM) + { + return (char *)"Bottom"; + } + else if (this->VerticalJustification == VTK_TEXT_CENTERED) + { + return (char *)"Centered"; + } + else if (this->VerticalJustification == VTK_TEXT_TOP) + { + return (char *)"Top"; + } + return (char *)"Unknown"; +} + +#endif diff --git a/Rendering/vtkTexture.cxx b/Rendering/vtkTexture.cxx new file mode 100644 index 0000000..78e4585 --- /dev/null +++ b/Rendering/vtkTexture.cxx @@ -0,0 +1,201 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTexture.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTexture.h" + +#include "vtkExecutive.h" +#include "vtkGraphicsFactory.h" +#include "vtkImageData.h" +#include "vtkLookupTable.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkTexture, "$Revision: 1.53 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkTexture); +//---------------------------------------------------------------------------- + +// Construct object and initialize. +vtkTexture::vtkTexture() +{ + this->Repeat = 1; + this->Interpolate = 0; + this->Quality = VTK_TEXTURE_QUALITY_DEFAULT; + + this->LookupTable = NULL; + this->MappedScalars = NULL; + this->MapColorScalarsThroughLookupTable = 0; + + this->SelfAdjustingTableRange = 0; + + this->SetNumberOfOutputPorts(0); +} + +vtkTexture::~vtkTexture() +{ + if (this->MappedScalars) + { + this->MappedScalars->Delete(); + } + + if (this->LookupTable != NULL) + { + this->LookupTable->UnRegister(this); + } +} + +// return the correct type of Texture +vtkTexture *vtkTexture::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkGraphicsFactory::CreateInstance("vtkTexture"); + return (vtkTexture*)ret; +} + +vtkImageData *vtkTexture::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(0, 0)); +} + +void vtkTexture::SetLookupTable(vtkLookupTable *lut) +{ + if ( this->LookupTable != lut ) + { + if ( this->LookupTable != NULL ) {this->LookupTable->UnRegister(this);} + this->LookupTable = lut; + if ( this->LookupTable != NULL ) {this->LookupTable->Register(this);} + this->Modified(); + } +} + +void vtkTexture::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Interpolate: " << (this->Interpolate ? "On\n" : "Off\n"); + os << indent << "Repeat: " << (this->Repeat ? "On\n" : "Off\n"); + os << indent << "Quality: "; + switch (this->Quality) + { + case VTK_TEXTURE_QUALITY_DEFAULT: + os << "Default\n"; + break; + case VTK_TEXTURE_QUALITY_16BIT: + os << "16Bit\n"; + break; + case VTK_TEXTURE_QUALITY_32BIT: + os << "32Bit\n"; + break; + } + os << indent << "MapColorScalarsThroughLookupTable: " << (this->MapColorScalarsThroughLookupTable ? "On\n" : "Off\n"); + + if ( this->GetInput() ) + { + os << indent << "Input: (" << (void *)this->GetInput() << ")\n"; + } + else + { + os << indent << "Input: (none)\n"; + } + if ( this->LookupTable ) + { + os << indent << "LookupTable:\n"; + this->LookupTable->PrintSelf (os, indent.GetNextIndent ()); + } + else + { + os << indent << "LookupTable: (none)\n"; + } + + if ( this->MappedScalars ) + { + os << indent << "Mapped Scalars: " << this->MappedScalars << "\n"; + } + else + { + os << indent << "Mapped Scalars: (none)\n"; + } +} + +unsigned char *vtkTexture::MapScalarsToColors (vtkDataArray *scalars) +{ + int numPts = scalars->GetNumberOfTuples(); + vtkUnsignedCharArray *mappedScalars; + + // if there is no lookup table, create one + if (this->LookupTable == NULL) + { + this->LookupTable = vtkLookupTable::New(); + this->LookupTable->Register(this); + this->LookupTable->Delete(); + this->LookupTable->Build (); + this->SelfAdjustingTableRange = 1; + } + else + { + this->SelfAdjustingTableRange = 0; + } + // if there is no pixmap, create one + if (!this->MappedScalars) + { + this->MappedScalars = vtkUnsignedCharArray::New(); + this->MappedScalars->SetNumberOfComponents(4); + } + + // if the texture created its own lookup table, set the Table Range + // to the range of the scalar data. + if (this->SelfAdjustingTableRange) + { + this->LookupTable->SetTableRange (scalars->GetRange(0)); + } + + // map the scalars to colors + mappedScalars = this->MappedScalars; + mappedScalars->SetNumberOfTuples(numPts); + unsigned char *cptr = (unsigned char *)mappedScalars->GetVoidPointer(0); + + this->LookupTable->MapScalarsThroughTable(scalars,cptr); + + return cptr; +} + +void vtkTexture::Render(vtkRenderer *ren) +{ + vtkImageData *input = this->GetInput(); + + if (input) //load texture map + { + // We do not want more than requested. + input->RequestExactExtentOn(); + + // Updating the whole extent may not be necessary. + input->UpdateInformation(); + input->SetUpdateExtentToWholeExtent(); + input->Update(); + this->Load(ren); + } +} + + + + + + + diff --git a/Rendering/vtkTexture.h b/Rendering/vtkTexture.h new file mode 100644 index 0000000..82c5102 --- /dev/null +++ b/Rendering/vtkTexture.h @@ -0,0 +1,152 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTexture.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTexture - handles properties associated with a texture map +// .SECTION Description +// vtkTexture is an object that handles loading and binding of texture +// maps. It obtains its data from an input image data dataset type. +// Thus you can create visualization pipelines to read, process, and +// construct textures. Note that textures will only work if texture +// coordinates are also defined, and if the rendering system supports +// texture. +// +// Instances of vtkTexture are associated with actors via the actor's +// SetTexture() method. Actors can share texture maps (this is encouraged +// to save memory resources.) + +// .SECTION Caveats +// Currently only 2D texture maps are supported, even though the data pipeline +// supports 1,2, and 3D texture coordinates. +// +// Some renderers such as OpenGL require that the texture map dimensions are +// a power of two in each direction. Other renderers may have similar +// (ridiculous) restrictions, so be careful out there... (Note: a recent change +// to vtk allows use of non-power of two texture maps in OpenGL. The texture is +// automatically resampled to a power of two in one or more directions.) + +// .SECTION See Also +// vtkActor vtkRenderer vtkOpenGLTexture + +#ifndef __vtkTexture_h +#define __vtkTexture_h + +#include "vtkImageAlgorithm.h" + +class vtkImageData; +class vtkLookupTable; +class vtkRenderer; +class vtkUnsignedCharArray; +class vtkWindow; +class vtkDataArray; + +#define VTK_TEXTURE_QUALITY_DEFAULT 0 +#define VTK_TEXTURE_QUALITY_16BIT 16 +#define VTK_TEXTURE_QUALITY_32BIT 32 + +class VTK_RENDERING_EXPORT vtkTexture : public vtkImageAlgorithm +{ +public: + static vtkTexture *New(); + vtkTypeRevisionMacro(vtkTexture,vtkImageAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Renders a texture map. It first checks the object's modified time + // to make sure the texture maps Input is valid, then it invokes the + // Load() method. + virtual void Render(vtkRenderer *ren); + + // Description: + // Release any graphics resources that are being consumed by this texture. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *) {}; + + // Description: + // Abstract interface to renderer. Each concrete subclass of + // vtkTexture will load its data into graphics system in response + // to this method invocation. + virtual void Load(vtkRenderer *) {}; + + // Description: + // Turn on/off the repetition of the texture map when the texture + // coords extend beyond the [0,1] range. + vtkGetMacro(Repeat,int); + vtkSetMacro(Repeat,int); + vtkBooleanMacro(Repeat,int); + + // Description: + // Turn on/off linear interpolation of the texture map when rendering. + vtkGetMacro(Interpolate,int); + vtkSetMacro(Interpolate,int); + vtkBooleanMacro(Interpolate,int); + + // Description: + // Force texture quality to 16-bit or 32-bit. + // This might not be supported on all machines. + vtkSetMacro(Quality,int); + vtkGetMacro(Quality,int); + void SetQualityToDefault() {this->SetQuality(VTK_TEXTURE_QUALITY_DEFAULT);}; + void SetQualityTo16Bit() {this->SetQuality(VTK_TEXTURE_QUALITY_16BIT);}; + void SetQualityTo32Bit() {this->SetQuality(VTK_TEXTURE_QUALITY_32BIT);}; + + // Description: + // Turn on/off the mapping of color scalars through the lookup table. + // The default is Off. If Off, unsigned char scalars will be used + // directly as texture. If On, scalars will be mapped through the + // lookup table to generate 4-component unsigned char scalars. + // This ivar does not affect other scalars like unsigned short, float, + // etc. These scalars are always mapped through lookup tables. + vtkGetMacro(MapColorScalarsThroughLookupTable,int); + vtkSetMacro(MapColorScalarsThroughLookupTable,int); + vtkBooleanMacro(MapColorScalarsThroughLookupTable,int); + +//BTX + // Description: + // This process object accepts image data as input. + vtkImageData *GetInput(); +//ETX + + // Description: + // Specify the lookup table to convert scalars if necessary + void SetLookupTable(vtkLookupTable *); + vtkGetObjectMacro(LookupTable,vtkLookupTable); + + // Description: + // Get Mapped Scalars + vtkGetObjectMacro(MappedScalars,vtkUnsignedCharArray); + + // Description: + // Map scalar values into color scalars. + unsigned char *MapScalarsToColors (vtkDataArray *scalars); + +protected: + vtkTexture(); + ~vtkTexture(); + + int Repeat; + int Interpolate; + int Quality; + int MapColorScalarsThroughLookupTable; + vtkLookupTable *LookupTable; + vtkUnsignedCharArray *MappedScalars; + + // this is to duplicated the previous behavior of SelfCreatedLookUpTable + int SelfAdjustingTableRange; +private: + vtkTexture(const vtkTexture&); // Not implemented. + void operator=(const vtkTexture&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkTkImageViewerWidget.cxx b/Rendering/vtkTkImageViewerWidget.cxx new file mode 100644 index 0000000..5e18fb8 --- /dev/null +++ b/Rendering/vtkTkImageViewerWidget.cxx @@ -0,0 +1,959 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkImageViewerWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include + +#include "vtkTkImageViewerWidget.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkTkInternals.h" + +#ifdef _MSC_VER + #pragma warning ( disable : 4273 ) +#else + #ifdef VTK_USE_CARBON + #include "vtkCarbonRenderWindow.h" + #else + #ifdef VTK_USE_COCOA + #include "vtkCocoaRenderWindow.h" + #else + #include "vtkXOpenGLRenderWindow.h" + #endif + #endif +#endif + +#define VTK_ALL_EVENTS_MASK \ + KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \ + EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \ + VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|ColormapChangeMask + +#define VTK_MAX(a,b) (((a)>(b))?(a):(b)) + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET +#pragma warning ( disable : 4311 ) +#pragma warning ( disable : 4312 ) +# define vtkGetWindowLong GetWindowLongPtr +# define vtkSetWindowLong SetWindowLongPtr +#else // regular Visual studio +# define vtkGetWindowLong GetWindowLong +# define vtkSetWindowLong SetWindowLong +#endif // + +// These are the options that can be set when the widget is created +// or with the command configure. The only new one is "-rw" which allows +// the uses to set their own ImageViewer window. +static Tk_ConfigSpec vtkTkImageViewerWidgetConfigSpecs[] = { + {TK_CONFIG_PIXELS, (char *) "-height", (char *) "height", (char *) "Height", + (char *) "400", Tk_Offset(struct vtkTkImageViewerWidget, Height), 0, NULL}, + + {TK_CONFIG_PIXELS, (char *) "-width", (char *) "width", (char *) "Width", + (char *) "400", Tk_Offset(struct vtkTkImageViewerWidget, Width), 0, NULL}, + + {TK_CONFIG_STRING, (char *) "-iv", (char *) "iv", (char *) "IV", + (char *) "", Tk_Offset(struct vtkTkImageViewerWidget, IV), 0, NULL}, + + {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, + (char *) NULL, 0, 0, NULL} +}; + + +// Forward prototypes +extern "C" +{ + void vtkTkImageViewerWidget_EventProc(ClientData clientData, + XEvent *eventPtr); +} + +static int vtkTkImageViewerWidget_MakeImageViewer(struct vtkTkImageViewerWidget *self); +extern int vtkImageViewerCommand(ClientData cd, Tcl_Interp *interp, + int argc, char *argv[]); + + +//---------------------------------------------------------------------------- +// It's possible to change with this function or in a script some +// options like width, hieght or the ImageViewer widget. +int vtkTkImageViewerWidget_Configure(Tcl_Interp *interp, + struct vtkTkImageViewerWidget *self, + int argc, char *argv[], int flags) +{ + // Let Tk handle generic configure options. + if (Tk_ConfigureWidget(interp, + self->TkWin, + vtkTkImageViewerWidgetConfigSpecs, + argc, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + const_cast(argv), +#else + argv, +#endif + (char *)self, + flags) == TCL_ERROR) + { + return(TCL_ERROR); + } + + // Get the new width and height of the widget + Tk_GeometryRequest(self->TkWin, self->Width, self->Height); + + // Make sure the ImageViewer window has been set. If not, create one. + if (vtkTkImageViewerWidget_MakeImageViewer(self) == TCL_ERROR) + { + return TCL_ERROR; + } + + return TCL_OK; +} + +//---------------------------------------------------------------------------- +// This function is called when the ImageViewer widget name is +// evaluated in a Tcl script. It will compare string parameters +// to choose the appropriate method to invoke. +extern "C" +{ + int vtkTkImageViewerWidget_Widget(ClientData clientData, + Tcl_Interp *interp, + int argc, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + CONST84 +#endif + char *argv[]) + { + struct vtkTkImageViewerWidget *self = + (struct vtkTkImageViewerWidget *)clientData; + int result = TCL_OK; + + // Check to see if the command has enough arguments. + if (argc < 2) + { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " ?options?\"", NULL); + return TCL_ERROR; + } + + // Make sure the widget is not deleted during this function + Tk_Preserve((ClientData)self); + + + // Handle render call to the widget + if (strncmp(argv[1], "render", VTK_MAX(1, strlen(argv[1]))) == 0 || + strncmp(argv[1], "Render", VTK_MAX(1, strlen(argv[1]))) == 0) + { + // make sure we have a window + if (self->ImageViewer == NULL) + { + vtkTkImageViewerWidget_MakeImageViewer(self); + } + self->ImageViewer->Render(); + } + // Handle configure method + else if (!strncmp(argv[1], "configure", VTK_MAX(1, strlen(argv[1])))) + { + if (argc == 2) + { + /* Return list of all configuration parameters */ + result = Tk_ConfigureInfo(interp, self->TkWin, + vtkTkImageViewerWidgetConfigSpecs, + (char *)self, (char *)NULL, 0); + } + else if (argc == 3) + { + /* Return a specific configuration parameter */ + result = Tk_ConfigureInfo(interp, self->TkWin, + vtkTkImageViewerWidgetConfigSpecs, + (char *)self, argv[2], 0); + } + else + { + /* Execute a configuration change */ + result = vtkTkImageViewerWidget_Configure(interp, + self, + argc-2, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + const_cast(argv+2), +#else + argv+2, +#endif + TK_CONFIG_ARGV_ONLY); + } + } + else if (!strcmp(argv[1], "GetImageViewer")) + { // Get ImageViewerWindow is my own method + // Create a ImageViewerWidget if one has not been set yet. + result = vtkTkImageViewerWidget_MakeImageViewer(self); + if (result != TCL_ERROR) + { + // Return the name (Make Tcl copy the string) + Tcl_SetResult(interp, self->IV, TCL_VOLATILE); + } + } + else + { + // Unknown method name. + Tcl_AppendResult(interp, "vtkTkImageViewerWidget: Unknown option: ", argv[1], + "\n", "Try: configure or GetImageViewer\n", NULL); + result = TCL_ERROR; + } + + // Unlock the object so it can be deleted. + Tk_Release((ClientData)self); + return result; + } +} + +//---------------------------------------------------------------------------- +// vtkTkImageViewerWidget_Cmd +// Called when vtkTkImageViewerWidget is executed +// - creation of a vtkTkImageViewerWidget widget. +// * Creates a new window +// * Creates an 'vtkTkImageViewerWidget' data structure +// * Creates an event handler for this window +// * Creates a command that handles this object +// * Configures this vtkTkImageViewerWidget for the given arguments +extern "C" +{ + int vtkTkImageViewerWidget_Cmd(ClientData clientData, + Tcl_Interp *interp, + int argc, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + CONST84 +#endif + char **argv) + { +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + CONST84 +#endif + char *name; + Tk_Window main = (Tk_Window)clientData; + Tk_Window tkwin; + struct vtkTkImageViewerWidget *self; + + // Make sure we have an instance name. + if (argc <= 1) + { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "wrong # args: should be \"pathName read filename\"", + NULL); + return(TCL_ERROR); + } + + // Create the window. + name = argv[1]; + // Possibly X dependent + tkwin = Tk_CreateWindowFromPath(interp, main, name, (char *) NULL); + if (tkwin == NULL) + { + return TCL_ERROR; + } + + // Tcl needs this for setting options and matching event bindings. + Tk_SetClass(tkwin, (char *) "vtkTkImageViewerWidget"); + + // Create vtkTkImageViewerWidget data structure + self = (struct vtkTkImageViewerWidget *) + ckalloc(sizeof(struct vtkTkImageViewerWidget)); + + self->TkWin = tkwin; + self->Interp = interp; + self->Width = 0; + self->Height = 0; + self->ImageViewer = NULL; + self->IV = NULL; + + // ... + // Create command event handler + Tcl_CreateCommand(interp, Tk_PathName(tkwin), vtkTkImageViewerWidget_Widget, + (ClientData)self, (void (*)(ClientData)) NULL); + Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask, + vtkTkImageViewerWidget_EventProc, (ClientData)self); + + // Configure vtkTkImageViewerWidget widget + if (vtkTkImageViewerWidget_Configure(interp, + self, + argc-2, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + const_cast(argv+2), +#else + argv+2, +#endif + 0) + == TCL_ERROR) + { + Tk_DestroyWindow(tkwin); + Tcl_DeleteCommand(interp, (char *) "vtkTkImageViewerWidget"); + // Don't free it, if we do a crash occurs later... + //free(self); + return TCL_ERROR; + } + + Tcl_AppendResult(interp, Tk_PathName(tkwin), NULL); + return TCL_OK; + } +} + + +//---------------------------------------------------------------------------- +char *vtkTkImageViewerWidget_IV(const struct vtkTkImageViewerWidget *self) +{ + return self->IV; +} + + +//---------------------------------------------------------------------------- +int vtkTkImageViewerWidget_Width( const struct vtkTkImageViewerWidget *self) +{ + return self->Width; +} + + +//---------------------------------------------------------------------------- +int vtkTkImageViewerWidget_Height( const struct vtkTkImageViewerWidget *self) +{ + return self->Height; +} + +extern "C" +{ + void vtkTkImageViewerWidget_Destroy(char *memPtr) + { + struct vtkTkImageViewerWidget *self = (struct vtkTkImageViewerWidget *)memPtr; + + if (self->ImageViewer) + { + int netRefCount = self->ImageViewer->GetReferenceCount(); + if (self->ImageViewer->GetRenderWindow()->GetInteractor() && + self->ImageViewer->GetRenderWindow()->GetInteractor()->GetRenderWindow() == self->ImageViewer->GetRenderWindow() && + self->ImageViewer->GetRenderWindow()->GetInteractor()->GetReferenceCount() == 1) + { + netRefCount = netRefCount - 1; + } + if (netRefCount > 1) + { + vtkGenericWarningMacro("A TkImageViewerWidget is being destroyed before it associated vtkImageViewer is destroyed. This is very bad and usually due to the order in which objects are being destroyed. Always destroy the vtkImageViewer before destroying the user interface components."); + return; + } + // Squash the ImageViewer's WindowID + self->ImageViewer->SetWindowId ( (void*)NULL ); + self->ImageViewer->UnRegister(NULL); + self->ImageViewer = NULL; + ckfree (self->IV); + } + ckfree((char *) memPtr); + } +} + +//---------------------------------------------------------------------------- +// This gets called to handle vtkTkImageViewerWidget wind configuration events +// Possibly X dependent +extern "C" +{ + void vtkTkImageViewerWidget_EventProc(ClientData clientData, + XEvent *eventPtr) + { + struct vtkTkImageViewerWidget *self = + (struct vtkTkImageViewerWidget *)clientData; + + switch (eventPtr->type) + { + case Expose: + if ((eventPtr->xexpose.count == 0) + /* && !self->UpdatePending*/) + { + // bid this in tcl now + //self->ImageViewer->Render(); + } + break; + case ConfigureNotify: + if ( 1 /*Tk_IsMapped(self->TkWin)*/ ) + { + self->Width = Tk_Width(self->TkWin); + self->Height = Tk_Height(self->TkWin); + //Tk_GeometryRequest(self->TkWin,self->Width,self->Height); + if (self->ImageViewer) + { +#ifdef VTK_USE_CARBON + TkWindow *winPtr = (TkWindow *)self->TkWin; + self->ImageViewer->SetPosition(winPtr->privatePtr->xOff, + winPtr->privatePtr->yOff); +#else + self->ImageViewer->SetPosition(Tk_X(self->TkWin),Tk_Y(self->TkWin)); +#endif + self->ImageViewer->SetSize(self->Width, self->Height); + } + + //vtkTkImageViewerWidget_PostRedisplay(self); + } + break; + case MapNotify: + break; + case DestroyNotify: +#ifdef _WIN32 + if (self->ImageViewer->GetRenderWindow()->GetGenericWindowId()) + { + SetWindowLong((HWND)self->ImageViewer->GetRenderWindow()->GetGenericWindowId(), + GWL_USERDATA,(LONG)((TkWindow *)self->TkWin)->window); + SetWindowLong((HWND)self->ImageViewer->GetRenderWindow()->GetGenericWindowId(), + GWL_WNDPROC,(LONG)TkWinChildProc); + } +#endif + Tcl_EventuallyFree( (ClientData) self, vtkTkImageViewerWidget_Destroy ); + break; + default: + // nothing + ; + } + } +} + + + +//---------------------------------------------------------------------------- +// vtkTkImageViewerWidget_Init +// Called upon system startup to create vtkTkImageViewerWidget command. +extern "C" {VTK_TK_EXPORT int Vtktkimageviewerwidget_Init(Tcl_Interp *interp);} + +#define VTKTK_TO_STRING(x) VTKTK_TO_STRING0(x) +#define VTKTK_TO_STRING0(x) VTKTK_TO_STRING1(x) +#define VTKTK_TO_STRING1(x) #x +#define VTKTK_VERSION VTKTK_TO_STRING(VTK_MAJOR_VERSION) "." VTKTK_TO_STRING(VTK_MINOR_VERSION) + +int Vtktkimageviewerwidget_Init(Tcl_Interp *interp) +{ + // This widget requires Tk to function. + Tcl_PkgRequire(interp, (char *)"Tk", (char*)TK_VERSION, 0); + if(Tcl_PkgPresent(interp, (char *)"Tk", (char*)TK_VERSION, 0)) + { + // Register the commands for this package. + Tcl_CreateCommand(interp, (char*)"vtkTkImageViewerWidget", + vtkTkImageViewerWidget_Cmd, Tk_MainWindow(interp), NULL); + + // Report that the package is provided. + return Tcl_PkgProvide(interp, (char*)"Vtktkimageviewerwidget", + (char*)VTKTK_VERSION); + } + else + { + // Tk is not available. + return TCL_ERROR; + } +} + + +// Here is the windows specific code for creating the window +// The Xwindows version follows after this +#ifdef _WIN32 + +LRESULT APIENTRY vtkTkImageViewerWidgetProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + LRESULT rval; + struct vtkTkImageViewerWidget *self = + (struct vtkTkImageViewerWidget *)vtkGetWindowLong(hWnd,GWL_USERDATA); + + if (!self) + { + return 0; + } + + // forward message to Tk handler + vtkSetWindowLong(hWnd,GWL_USERDATA,(LONG)((TkWindow *)self->TkWin)->window); + if (((TkWindow *)self->TkWin)->parentPtr) + { + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)TkWinChildProc); + rval = TkWinChildProc(hWnd,message,wParam,lParam); + } + else + { +// +// TkWinTopLevelProc has been deprecated in Tcl/Tk8.0. Not sure how +// well this will actually work in 8.0. +// +#if (TK_MAJOR_VERSION < 8) + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)TkWinTopLevelProc); + rval = TkWinTopLevelProc(hWnd,message,wParam,lParam); +#else + if (message == WM_WINDOWPOSCHANGED) + { + XEvent event; + WINDOWPOS *pos = (WINDOWPOS *) lParam; + TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(pos->hwnd); + + if (winPtr == NULL) { + return 0; + } + + /* + * Update the shape of the contained window. + */ + if (!(pos->flags & SWP_NOSIZE)) { + winPtr->changes.width = pos->cx; + winPtr->changes.height = pos->cy; + } + if (!(pos->flags & SWP_NOMOVE)) { + winPtr->changes.x = pos->x; + winPtr->changes.y = pos->y; + } + + + /* + * Generate a ConfigureNotify event. + */ + event.type = ConfigureNotify; + event.xconfigure.serial = winPtr->display->request; + event.xconfigure.send_event = False; + event.xconfigure.display = winPtr->display; + event.xconfigure.event = winPtr->window; + event.xconfigure.window = winPtr->window; + event.xconfigure.border_width = winPtr->changes.border_width; + event.xconfigure.override_redirect = winPtr->atts.override_redirect; + event.xconfigure.x = winPtr->changes.x; + event.xconfigure.y = winPtr->changes.y; + event.xconfigure.width = winPtr->changes.width; + event.xconfigure.height = winPtr->changes.height; + event.xconfigure.above = None; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + + Tcl_ServiceAll(); + return 0; + } + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)TkWinChildProc); + rval = TkWinChildProc(hWnd,message,wParam,lParam); +#endif + } + + if (message != WM_PAINT) + { + if (self->ImageViewer) + { + vtkSetWindowLong(hWnd,GWL_USERDATA, + (LONG)self->ImageViewer->GetRenderWindow()); + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)self->OldProc); + CallWindowProc(self->OldProc,hWnd,message,wParam,lParam); + } + } + + // now reset to the original config + vtkSetWindowLong(hWnd,GWL_USERDATA,(LONG)self); + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)vtkTkImageViewerWidgetProc); + return rval; +} + +//----------------------------------------------------------------------------- +// Creates a ImageViewer window and forces Tk to use the window. +static int vtkTkImageViewerWidget_MakeImageViewer(struct vtkTkImageViewerWidget *self) +{ + Display *dpy; + TkWindow *winPtr = (TkWindow *) self->TkWin; + Tcl_HashEntry *hPtr; + int new_flag; + vtkImageViewer *imgViewer; + TkWinDrawable *twdPtr; + HWND parentWin; + vtkRenderWindow *imgWindow; + + if (self->ImageViewer) + { + return TCL_OK; + } + + dpy = Tk_Display(self->TkWin); + + if (winPtr->window != None) + { + // XDestroyWindow(dpy, winPtr->window); + } + + if (self->IV[0] == '\0') + { + // Make the ImageViewer window. + self->ImageViewer = imgViewer = vtkImageViewer::New(); +#ifndef VTK_PYTHON_BUILD + vtkTclGetObjectFromPointer(self->Interp, self->ImageViewer, + "vtkImageViewer"); +#endif + ckfree (self->IV); + self->IV = strdup(self->Interp->result); + self->Interp->result[0] = '\0'; + } + else + { + // is IV an address ? big ole python hack here + if (self->IV[0] == 'A' && self->IV[1] == 'd' && + self->IV[2] == 'd' && self->IV[3] == 'r') + { + void *tmp; + sscanf(self->IV+5,"%p",&tmp); + imgViewer = (vtkImageViewer *)tmp; + } + else + { +#ifndef VTK_PYTHON_BUILD + imgViewer = (vtkImageViewer *) + vtkTclGetPointerFromObject(self->IV, "vtkImageViewer", self->Interp, + new_flag); +#else + imgViewer = 0; +#endif + } + if (imgViewer != self->ImageViewer) + { + if (self->ImageViewer != NULL) + { + self->ImageViewer->UnRegister(NULL); + } + self->ImageViewer = (vtkImageViewer *)(imgViewer); + if (self->ImageViewer != NULL) + { + self->ImageViewer->Register(NULL); + } + } + } + + // Set the size + self->ImageViewer->SetSize(self->Width, self->Height); + + // Set the parent correctly + // Possibly X dependent + if ((winPtr->parentPtr != NULL) && !(winPtr->flags & TK_TOP_LEVEL)) + { + if (winPtr->parentPtr->window == None) + { + Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr); + } + + parentWin = ((TkWinDrawable *)winPtr->parentPtr->window)->window.handle; + imgViewer->SetParentId(parentWin); + } + + // Use the same display + self->ImageViewer->SetDisplayId(dpy); + + /* Make sure Tk knows to switch to the new colormap when the cursor + * is over this window when running in color index mode. + */ + //Tk_SetWindowVisual(self->TkWin, imgViewer->GetDesiredVisual(), + //ImageViewer->GetDesiredDepth(), + //ImageViewer->GetDesiredColormap()); + + self->ImageViewer->Render(); + imgWindow = self->ImageViewer->GetRenderWindow(); + +#if(TK_MAJOR_VERSION >= 8) + twdPtr = (TkWinDrawable*)Tk_AttachHWND(self->TkWin, (HWND)imgWindow->GetGenericWindowId()); +#else + twdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable)); + twdPtr->type = TWD_WINDOW; + twdPtr->window.winPtr = winPtr; + twdPtr->window.handle = (HWND)imgWindow->GetGenericWindowId(); +#endif + + self->OldProc = (WNDPROC)vtkGetWindowLong(twdPtr->window.handle,GWL_WNDPROC); + vtkSetWindowLong(twdPtr->window.handle,GWL_USERDATA,(LONG)self); + vtkSetWindowLong(twdPtr->window.handle,GWL_WNDPROC, + (LONG)vtkTkImageViewerWidgetProc); + + winPtr->window = (Window)twdPtr; + + hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable, + (char *) winPtr->window, &new_flag); + Tcl_SetHashValue(hPtr, winPtr); + + winPtr->dirtyAtts = 0; + winPtr->dirtyChanges = 0; +#ifdef TK_USE_INPUT_METHODS + winPtr->inputContext = NULL; +#endif // TK_USE_INPUT_METHODS + + if (!(winPtr->flags & TK_TOP_LEVEL)) + { + /* + * If this window has a different colormap than its parent, add + * the window to the WM_COLORMAP_WINDOWS property for its top-level. + */ + if ((winPtr->parentPtr != NULL) && + (winPtr->atts.colormap != winPtr->parentPtr->atts.colormap)) + { + TkWmAddToColormapWindows(winPtr); + } + } + + /* + * Issue a ConfigureNotify event if there were deferred configuration + * changes (but skip it if the window is being deleted; the + * ConfigureNotify event could cause problems if we're being called + * from Tk_DestroyWindow under some conditions). + */ + if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY) + && !(winPtr->flags & TK_ALREADY_DEAD)) + { + XEvent event; + + winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY; + + event.type = ConfigureNotify; + event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display); + event.xconfigure.send_event = False; + event.xconfigure.display = winPtr->display; + event.xconfigure.event = winPtr->window; + event.xconfigure.window = winPtr->window; + event.xconfigure.x = winPtr->changes.x; + event.xconfigure.y = winPtr->changes.y; + event.xconfigure.width = winPtr->changes.width; + event.xconfigure.height = winPtr->changes.height; + event.xconfigure.border_width = winPtr->changes.border_width; + if (winPtr->changes.stack_mode == Above) + { + event.xconfigure.above = winPtr->changes.sibling; + } + else + { + event.xconfigure.above = None; + } + event.xconfigure.override_redirect = winPtr->atts.override_redirect; + Tk_HandleEvent(&event); + } + + return TCL_OK; +} + +// now the APPLE version - only available using the Carbon APIs +#else +#ifdef VTK_USE_CARBON +//---------------------------------------------------------------------------- +// Creates a ImageViewer window and forces Tk to use the window. +static int +vtkTkImageViewerWidget_MakeImageViewer(struct vtkTkImageViewerWidget *self) +{ + Display *dpy; + TkWindow *winPtr = (TkWindow *)self->TkWin; + vtkImageViewer *imgViewer; + vtkCarbonRenderWindow *imgWindow; + WindowPtr parentWin; + + if (self->ImageViewer) + { + return TCL_OK; + } + + dpy = Tk_Display(self->TkWin); + + if (self->IV[0] == '\0') + { + // Make the ImageViewer window. + self->ImageViewer = imgViewer = vtkImageViewer::New(); +#ifndef VTK_PYTHON_BUILD + vtkTclGetObjectFromPointer(self->Interp, self->ImageViewer, + "vtkImageViewer"); +#endif + ckfree (self->IV); + self->IV = strdup(self->Interp->result); + self->Interp->result[0] = '\0'; + } + else + { + // is IV an address ? big ole python hack here + if (self->IV[0] == 'A' && self->IV[1] == 'd' && + self->IV[2] == 'd' && self->IV[3] == 'r') + { + void *tmp; + sscanf(self->IV+5,"%p",&tmp); + imgViewer = (vtkImageViewer *)tmp; + } + else + { +#ifndef VTK_PYTHON_BUILD + int new_flag; + imgViewer = (vtkImageViewer *) + vtkTclGetPointerFromObject(self->IV, "vtkImageViewer", self->Interp, + new_flag); +#endif + } + if (imgViewer != self->ImageViewer) + { + if (self->ImageViewer != NULL) + { + self->ImageViewer->UnRegister(NULL); + } + self->ImageViewer = (vtkImageViewer *)(imgViewer); + if (self->ImageViewer != NULL) + { + self->ImageViewer->Register(NULL); + } + } + } + + + // get the window + imgWindow = static_cast(imgViewer->GetRenderWindow()); + // If the imageviewer has already created it's window, throw up our hands and quit... + if ( imgWindow->GetRootWindow() != (Window)NULL ) + { + return TCL_ERROR; + } + + // Use the same display + imgWindow->SetDisplayId(dpy); + + // Set the parent correctly and get the actual OSX window on the screen + // Window must be up so that the aglContext can be attached to it + if ((winPtr->parentPtr != NULL) && !(winPtr->flags & TK_TOP_LEVEL)) + { + if (winPtr->parentPtr->window == None) + { + // Look at each parent TK window in order until we run out + // of windows or find the top level. Then the OSX window that will be + // the parent is created so that we have a window to pass to the + // vtkRenderWindow so it can attach its openGL context. + // Ideally the Tk_MakeWindowExist call would do the deed. (I think) + TkWindow *curWin = winPtr->parentPtr; + while ((NULL != curWin->parentPtr) && !(curWin->flags & TK_TOP_LEVEL)) + { + curWin = curWin->parentPtr; + } + Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr); + if (NULL != curWin) + { + TkMacOSXMakeRealWindowExist(curWin); + } + else + { + vtkGenericWarningMacro("Could not find the TK_TOP_LEVEL. This is bad."); + } + } + + parentWin = GetWindowFromPort(TkMacOSXGetDrawablePort( + Tk_WindowId(winPtr->parentPtr))); + // Carbon does not have 'sub-windows', so the ParentId is used more + // as a flag to indicate that the renderwindow is being used as a sub- + // view of its 'parent' window. + imgWindow->SetParentId(parentWin); + imgWindow->SetRootWindow(parentWin); + } + + + // Set the size + self->ImageViewer->SetSize(self->Width, self->Height); + + + self->ImageViewer->Render(); + return TCL_OK; +} + + +// now the Xwindows version +#else + +//---------------------------------------------------------------------------- +// Creates a ImageViewer window and forces Tk to use the window. +static int +vtkTkImageViewerWidget_MakeImageViewer(struct vtkTkImageViewerWidget *self) +{ + Display *dpy; + vtkImageViewer *imgViewer = 0; + vtkXOpenGLRenderWindow *imgWindow; + + if (self->ImageViewer) + { + return TCL_OK; + } + + dpy = Tk_Display(self->TkWin); + + if (Tk_WindowId(self->TkWin) != None) + { + XDestroyWindow(dpy, Tk_WindowId(self->TkWin) ); + } + + if (self->IV[0] == '\0') + { + // Make the ImageViewer window. + self->ImageViewer = imgViewer = vtkImageViewer::New(); +#ifndef VTK_PYTHON_BUILD + vtkTclGetObjectFromPointer(self->Interp, self->ImageViewer, + "vtkImageViewer"); +#endif + self->IV = strdup(self->Interp->result); + self->Interp->result[0] = '\0'; + } + else + { + // is IV an address ? big ole python hack here + if (self->IV[0] == 'A' && self->IV[1] == 'd' && + self->IV[2] == 'd' && self->IV[3] == 'r') + { + void *tmp; + sscanf(self->IV+5,"%p",&tmp); + imgViewer = (vtkImageViewer *)tmp; + } + else + { +#ifndef VTK_PYTHON_BUILD + int new_flag; + imgViewer = (vtkImageViewer *) + vtkTclGetPointerFromObject(self->IV, "vtkImageViewer", self->Interp, + new_flag); +#endif + } + if (imgViewer != self->ImageViewer) + { + if (self->ImageViewer != NULL) + { + self->ImageViewer->UnRegister(NULL); + } + self->ImageViewer = (vtkImageViewer *)(imgViewer); + if (self->ImageViewer != NULL) + { + self->ImageViewer->Register(NULL); + } + } + } + + + // get the window + imgWindow = static_cast(imgViewer->GetRenderWindow()); + // If the imageviewer has already created it's window, throw up our hands and quit... + if ( imgWindow->GetWindowId() != (Window)NULL ) + { + return TCL_ERROR; + } + + // Use the same display + imgWindow->SetDisplayId(dpy); + // The visual MUST BE SET BEFORE the window is created. + Tk_SetWindowVisual(self->TkWin, imgWindow->GetDesiredVisual(), + imgWindow->GetDesiredDepth(), + imgWindow->GetDesiredColormap()); + + // Make this window exist, then use that information to make the vtkImageViewer in sync + Tk_MakeWindowExist ( self->TkWin ); + imgViewer->SetWindowId ( (void*)Tk_WindowId ( self->TkWin ) ); + + // Set the size + self->ImageViewer->SetSize(self->Width, self->Height); + + // Set the parent correctly + // Possibly X dependent + if ((Tk_Parent(self->TkWin) == NULL) || (Tk_IsTopLevel(self->TkWin))) + { + imgWindow->SetParentId(XRootWindow(Tk_Display(self->TkWin), Tk_ScreenNumber(self->TkWin))); + } + else + { + imgWindow->SetParentId(Tk_WindowId(Tk_Parent(self->TkWin) )); + } + + self->ImageViewer->Render(); + return TCL_OK; +} +#endif +#endif diff --git a/Rendering/vtkTkImageViewerWidget.h b/Rendering/vtkTkImageViewerWidget.h new file mode 100644 index 0000000..0b01ce9 --- /dev/null +++ b/Rendering/vtkTkImageViewerWidget.h @@ -0,0 +1,53 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkImageViewerWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTkImageViewerWidget - a Tk Widget for viewing vtk images + +// .SECTION Description +// vtkTkImageViewerWidget is a Tk widget that you can render into. It has a +// GetImageViewer method that returns a vtkImageViewer. You can also +// specify a vtkImageViewer to be used when creating the widget by using +// the -iv option. It also takes -width and -height options. +// Events can be bound on this widget just like any other Tk widget. + +// .SECTION See Also +// vtkImageViewer + + +#ifndef __vtkTkImageViewerWidget_h +#define __vtkTkImageViewerWidget_h + +#include "vtkImageViewer.h" +#include "vtkTcl.h" +#include "vtkTk.h" +#ifndef VTK_PYTHON_BUILD +#include "vtkTclUtil.h" +#endif +#include "vtkWindows.h" + +struct vtkTkImageViewerWidget +{ + Tk_Window TkWin; /* Tk window structure */ + Tcl_Interp *Interp; /* Tcl interpreter */ + int Width; + int Height; + vtkImageViewer *ImageViewer; + char *IV; +#ifdef _WIN32 + WNDPROC OldProc; +#endif +}; + +#endif + diff --git a/Rendering/vtkTkImageViewerWidgetPython.cxx b/Rendering/vtkTkImageViewerWidgetPython.cxx new file mode 100644 index 0000000..59136be --- /dev/null +++ b/Rendering/vtkTkImageViewerWidgetPython.cxx @@ -0,0 +1,18 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkImageViewerWidgetPython.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#define VTK_PYTHON_BUILD +#include "vtkTkImageViewerWidget.cxx" + diff --git a/Rendering/vtkTkInternals.h.in b/Rendering/vtkTkInternals.h.in new file mode 100644 index 0000000..9514b40 --- /dev/null +++ b/Rendering/vtkTkInternals.h.in @@ -0,0 +1,46 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkInternals.h.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __vtkTkInternals_h +#define __vtkTkInternals_h + +#cmakedefine HAVE_LIMITS_H +#cmakedefine HAVE_UNISTD_H + +// This widget requires access to structures that are normally +// not visible to Tcl/Tk applications. For this reason you must +// have access to tkInt.h +// #include "tkInt.h" +#ifdef _WIN32 +extern "C" +{ +#include "tkWinInt.h" +} +#endif + +#ifdef VTK_USE_CARBON +// Tk #defines Status in: +// Tk.framework/Versions/8.4/Headers/X11/Xlib.h, +// which conflicts with a member of the FPUInformationIntel +// struct in Apple's new headers for i386: +// CarbonCore.framework/Versions/A/Headers/MachineExceptions.h +#if defined (i386) +#undef Status +#endif /* defined (i386) */ +#include "tkMacOSXInt.h" +#endif + +#endif /* __vtkTkInternals_h */ + diff --git a/Rendering/vtkTkRenderWidget.cxx b/Rendering/vtkTkRenderWidget.cxx new file mode 100644 index 0000000..c06aaba --- /dev/null +++ b/Rendering/vtkTkRenderWidget.cxx @@ -0,0 +1,1332 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkRenderWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include + +#include "vtkTkRenderWidget.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkImageData.h" +#include "vtkTclUtil.h" +#include "vtkTkInternals.h" +#include "vtkToolkits.h" + +#ifdef _WIN32 +#include "vtkWin32OpenGLRenderWindow.h" +#else +#ifdef VTK_USE_CARBON +#include "vtkCarbonRenderWindow.h" +#include "tkMacOSXInt.h"// Needed for XEvent.type == UnmapNotify +#else +#include "vtkXOpenGLRenderWindow.h" +#endif +#endif + +#define VTK_ALL_EVENTS_MASK \ + KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \ + EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \ + VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|ColormapChangeMask + +#define VTK_MAX(a,b) (((a)>(b))?(a):(b)) + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET +#pragma warning ( disable : 4311 ) +#pragma warning ( disable : 4312 ) +# define vtkGetWindowLong GetWindowLongPtr +# define vtkSetWindowLong SetWindowLongPtr +#else // regular Visual studio +# define vtkGetWindowLong GetWindowLong +# define vtkSetWindowLong SetWindowLong +#endif // + +// These are the options that can be set when the widget is created +// or with the command configure. The only new one is "-rw" which allows +// the uses to set their own render window. +static Tk_ConfigSpec vtkTkRenderWidgetConfigSpecs[] = { + {TK_CONFIG_PIXELS, (char *) "-height", (char *) "height", (char *) "Height", + (char *) "400", Tk_Offset(struct vtkTkRenderWidget, Height), 0, NULL}, + + {TK_CONFIG_PIXELS, (char *) "-width", (char *) "width", (char *) "Width", + (char *) "400", Tk_Offset(struct vtkTkRenderWidget, Width), 0, NULL}, + + {TK_CONFIG_STRING, (char *) "-rw", (char *) "rw", (char *) "RW", + (char *) "", Tk_Offset(struct vtkTkRenderWidget, RW), 0, NULL}, + + {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, + (char *) NULL, 0, 0, NULL} +}; + + +// Foward prototypes +extern "C" +{ + void vtkTkRenderWidget_EventProc(ClientData clientData, + XEvent *eventPtr); +} + +static int vtkTkRenderWidget_MakeRenderWindow(struct vtkTkRenderWidget *self); +extern int vtkRenderWindowCommand(ClientData cd, Tcl_Interp *interp, + int argc, char *argv[]); + +// Start of vtkImageDataToTkPhoto +template +void vtkExtractImageData ( unsigned char* buffer, T *inPtr, double shift, double scale, int width, int height, int pitch, int pixelSize, int components ) +{ + T* ImagePtr; + unsigned char* BufferPtr; + int i, j, c; + float pixel; + + BufferPtr = buffer; + //ImagePtr = inPtr; + + for ( j = 0; j < height; j++ ) + { + ImagePtr = j * pitch + inPtr; + for ( i = 0; i < width; i++ ) + { + for ( c = 0; c < components; c++ ) + { + // Clamp + pixel = (*ImagePtr + shift) * scale; + if ( pixel < 0 ) + { + pixel = 0; + } + else + { + if ( pixel > 255 ) + { + pixel = 255; + } + } + *BufferPtr = (unsigned char) pixel; + ImagePtr++; + BufferPtr++; + } + ImagePtr += pixelSize - components; + } + } + return; +} + + +extern "C" { +#define VTKIMAGEDATATOTKPHOTO_CORONAL 0 +#define VTKIMAGEDATATOTKPHOTO_SAGITTAL 1 +#define VTKIMAGEDATATOTKPHOTO_TRANSVERSE 2 + int vtkImageDataToTkPhoto_Cmd (ClientData vtkNotUsed(clientData), + Tcl_Interp *interp, + int argc, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + CONST84 +#endif + char **argv) + { + int status = 0; + vtkImageData* image; + Tk_PhotoHandle photo; + int slice = 0; + double window = 256.0; + double level = window / 2.0; + int orientation = VTKIMAGEDATATOTKPHOTO_TRANSVERSE; + + // Usage: vtkImageDataToTkPhoto vtkImageData photo slice + if ( argc < 4 || argc > 7 ) + { + const char m[] = + "wrong # args: should be \"vtkImageDataToTkPhoto vtkImageData photo slice [orientation] [window] [level]\""; + + Tcl_SetResult ( interp, const_cast(m), TCL_VOLATILE ); + return TCL_ERROR; + } + + // Start with slice, it's fast, etc... + status = Tcl_GetInt ( interp, argv[3], &slice ); + if ( status != TCL_OK ) + { + return status; + } + + // Find the image +#ifdef VTK_PYTHON_BUILD + void *ptr; + char typeCheck[128]; + sscanf ( argv[1], "_%lx_%s", (long *)&ptr, typeCheck); + if ( strcmp ( "vtkImageData", typeCheck ) != 0 + && strcmp ( "vtkStructuredPoints", typeCheck ) != 0 ) + { + // bad type + ptr = NULL; + } + image = (vtkImageData*) ptr; +#else + image = (vtkImageData*) vtkTclGetPointerFromObject ( argv[1], + "vtkImageData", interp, status ); +#endif + if ( !image ) + { + Tcl_AppendResult ( interp, "could not find vtkImageData: ", argv[1], NULL ); + return TCL_ERROR; + } + + // Find the photo widget + photo = Tk_FindPhoto ( interp, argv[2] ); + if ( !photo ) + { + Tcl_AppendResult ( interp, "could not find photo: ", argv[2], NULL ); + return TCL_ERROR; + } + + int components = image->GetNumberOfScalarComponents(); + if ( components != 1 && components != 3 ) + { + const char* m = "number of scalar components must be 1, 3, 4"; + Tcl_SetResult ( interp, const_cast(m), TCL_VOLATILE ); + return TCL_ERROR; + } + + // Determine the orientation + if ( argc >= 5 ) + { + if ( strcmp ( argv[4], "transverse" ) == 0 ) + { + orientation = VTKIMAGEDATATOTKPHOTO_TRANSVERSE; + } + if ( strcmp ( argv[4], "coronal" ) == 0 ) + { + orientation = VTKIMAGEDATATOTKPHOTO_CORONAL; + } + if ( strcmp ( argv[4], "sagittal" ) == 0 ) + { + orientation = VTKIMAGEDATATOTKPHOTO_SAGITTAL; + } + } + + // Get Window/Level + if ( argc >= 6 ) + { + if ( ( status = Tcl_GetDouble ( interp, argv[5], &window ) ) != TCL_OK ) + { + return status; + } + } + if ( argc >= 7 ) + { + if ( ( status = Tcl_GetDouble ( interp, argv[6], &level ) ) != TCL_OK ) + { + return status; + } + } + + + int extent[6]; + // Pass the check? + int valid = 1; + image->Update(); + image->GetWholeExtent ( extent ); + // Setup the photo data block, this info will be used later to + // handle the vtk data types and window/level + // For reference: + // pitch - address difference between two vertically adjacent pixels + // pixelSize - address difference between two + // horizontally adjacent pixels + Tk_PhotoImageBlock block; + block.width = 0; + block.height = 0; + block.pixelSize = 0; + block.pitch = 0; + void *TempPointer = 0; + switch ( orientation ) + { + case VTKIMAGEDATATOTKPHOTO_TRANSVERSE: + { + valid = ( slice >= extent[4] && slice <= extent[5] ); + if ( valid ) + { + TempPointer = image->GetScalarPointer ( 0, extent[3], slice ); + block.width = extent[1] - extent[0] + 1; + block.height = extent[3] - extent[2] + 1; + block.pixelSize = components; + block.pitch = -components * ( block.width ); + } + break; + } + case VTKIMAGEDATATOTKPHOTO_SAGITTAL: + { + valid = ( slice >= extent[0] && slice <= extent[1] ); + if ( valid ) + { + TempPointer = image->GetScalarPointer ( slice, extent[3], 0 ); + block.width = extent[3] - extent[2] + 1; + block.height = extent[5] - extent[4] + 1; + block.pixelSize = -components * ( extent[1] - extent[0] + 1 ); + block.pitch = components + * ( extent[1] - extent[0] + 1 ) + * ( extent[3] - extent[2] + 1 ); + } + break; + } + case VTKIMAGEDATATOTKPHOTO_CORONAL: + { + valid = ( slice >= extent[2] && slice <= extent[3] ); + if ( valid ) + { + TempPointer = image->GetScalarPointer ( 0, slice, 0 ); + block.width = extent[1] - extent[0] + 1; + block.height = extent[5] - extent[4] + 1; + block.pixelSize = components; + block.pitch = components + * ( extent[1] - extent[0] + 1 ) + * ( extent[3] - extent[2] + 1 ); + } + break; + } + } + + if ( !valid ) + { + const char* m = "slice is outside the image extent"; + Tcl_SetResult ( interp, const_cast(m), TCL_VOLATILE ); + return TCL_ERROR; + } + + // Extract the data, and reset the block + unsigned char* photobuffer = new unsigned char[block.width * block.height * components]; + double shift, scale; + shift = window / 2.0 - level; + scale = 255.0 / window; + switch ( image->GetScalarType() ) + { + vtkTemplateMacro ( + vtkExtractImageData(photobuffer, + static_cast (TempPointer), + shift, + scale, + block.width, + block.height, + block.pitch, + block.pixelSize, + components )); + } + block.pitch = block.width * components; + block.pixelSize = components; + block.pixelPtr = photobuffer; + + block.offset[0] = 0; + block.offset[1] = 1; + block.offset[2] = 2; + block.offset[3] = 0; + switch ( components ) + { + case 1: + block.offset[0] = 0; + block.offset[1] = 0; + block.offset[2] = 0; + block.offset[3] = 0; + break; + case 3: + block.offset[3] = 0; + break; + case 4: + block.offset[3] = 3; + break; + } + Tk_PhotoSetSize ( photo, block.width, block.height ); + Tk_PhotoPutBlock ( photo, &block, 0, 0, block.width, block.height ); + delete[] photobuffer; + return TCL_OK; + } +} + +//---------------------------------------------------------------------------- +// It's possible to change with this function or in a script some +// options like width, height or the render widget. +int vtkTkRenderWidget_Configure(Tcl_Interp *interp, + struct vtkTkRenderWidget *self, + int argc, char *argv[], int flags) +{ + // Let Tk handle generic configure options. + if (Tk_ConfigureWidget(interp, + self->TkWin, + vtkTkRenderWidgetConfigSpecs, + argc, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + const_cast(argv), +#else + argv, +#endif + (char *)self, + flags) == TCL_ERROR) + { + return(TCL_ERROR); + } + + // Get the new width and height of the widget + Tk_GeometryRequest(self->TkWin, self->Width, self->Height); + + // Make sure the render window has been set. If not, create one. + if (vtkTkRenderWidget_MakeRenderWindow(self) == TCL_ERROR) + { + return TCL_ERROR; + } + + return TCL_OK; +} + +//---------------------------------------------------------------------------- +// This function is called when the render widget name is +// evaluated in a Tcl script. It will compare string parameters +// to choose the appropriate method to invoke. +extern "C" +{ + int vtkTkRenderWidget_Widget(ClientData clientData, + Tcl_Interp *interp, + int argc, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + CONST84 +#endif + char *argv[]) + { + struct vtkTkRenderWidget *self = (struct vtkTkRenderWidget *)clientData; + int result = TCL_OK; + + // Check to see if the command has enough arguments. + if (argc < 2) + { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " ?options?\"", NULL); + return TCL_ERROR; + } + + // Make sure the widget is not deleted during this function + Tk_Preserve((ClientData)self); + + // Handle render call to the widget + if (strncmp(argv[1], "render", VTK_MAX(1, strlen(argv[1]))) == 0 || + strncmp(argv[1], "Render", VTK_MAX(1, strlen(argv[1]))) == 0) + { + // make sure we have a window + if (self->RenderWindow == NULL) + { + vtkTkRenderWidget_MakeRenderWindow(self); + } + self->RenderWindow->Render(); + } + // Handle configure method + else if (!strncmp(argv[1], "configure", VTK_MAX(1, strlen(argv[1])))) + { + if (argc == 2) + { + /* Return list of all configuration parameters */ + result = Tk_ConfigureInfo(interp, self->TkWin, + vtkTkRenderWidgetConfigSpecs, + (char *)self, (char *)NULL, 0); + } + else if (argc == 3) + { + /* Return a specific configuration parameter */ + result = Tk_ConfigureInfo(interp, self->TkWin, + vtkTkRenderWidgetConfigSpecs, + (char *)self, argv[2], 0); + } + else + { + /* Execute a configuration change */ + result = vtkTkRenderWidget_Configure(interp, self, argc-2, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + const_cast(argv+2), +#else + argv+2, +#endif + TK_CONFIG_ARGV_ONLY); + } + } + else if (!strcmp(argv[1], "GetRenderWindow")) + { // Get RenderWindow is my own method + // Create a RenderWidget if one has not been set yet. + result = vtkTkRenderWidget_MakeRenderWindow(self); + if (result != TCL_ERROR) + { + // Return the name (Make Tcl copy the string) + Tcl_SetResult(interp, self->RW, TCL_VOLATILE); + } + } + else + { + // Unknown method name. + Tcl_AppendResult(interp, "vtkTkRenderWidget: Unknown option: ", argv[1], + "\n", "Try: configure or GetRenderWindow\n", NULL); + result = TCL_ERROR; + } + + // Unlock the object so it can be deleted. + Tk_Release((ClientData)self); + return result; + } +} + +//---------------------------------------------------------------------------- +// vtkTkRenderWidget_Cmd +// Called when vtkTkRenderWidget is executed +// - creation of a vtkTkRenderWidget widget. +// * Creates a new window +// * Creates an 'vtkTkRenderWidget' data structure +// * Creates an event handler for this window +// * Creates a command that handles this object +// * Configures this vtkTkRenderWidget for the given arguments +extern "C" +{ + int vtkTkRenderWidget_Cmd(ClientData clientData, + Tcl_Interp *interp, + int argc, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + CONST84 +#endif + char **argv) + { +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + CONST84 +#endif + char *name; + Tk_Window main = (Tk_Window)clientData; + Tk_Window tkwin; + struct vtkTkRenderWidget *self; + + // Make sure we have an instance name. + if (argc <= 1) + { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "wrong # args: should be \"pathName read filename\"", + NULL); + return(TCL_ERROR); + } + + // Create the window. + name = argv[1]; + // Possibly X dependent + tkwin = Tk_CreateWindowFromPath(interp, main, name, (char *) NULL); + if (tkwin == NULL) + { + return TCL_ERROR; + } + + // Tcl needs this for setting options and matching event bindings. + Tk_SetClass(tkwin, (char *) "vtkTkRenderWidget"); + + // Create vtkTkRenderWidget data structure + self = (struct vtkTkRenderWidget *)ckalloc(sizeof(struct vtkTkRenderWidget)); + self->TkWin = tkwin; + self->Interp = interp; + self->Width = 0; + self->Height = 0; + self->RenderWindow = NULL; + self->RW = NULL; + + // ... + // Create command event handler + Tcl_CreateCommand(interp, Tk_PathName(tkwin), vtkTkRenderWidget_Widget, + (ClientData)self, (void (*)(ClientData)) NULL); + Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask, + vtkTkRenderWidget_EventProc, (ClientData)self); + + // Configure vtkTkRenderWidget widget + if (vtkTkRenderWidget_Configure(interp, + self, + argc-2, +#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4 && TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE) + const_cast(argv+2), +#else + argv+2, +#endif + 0) + == TCL_ERROR) + { + Tk_DestroyWindow(tkwin); + Tcl_DeleteCommand(interp, (char *) "vtkTkRenderWidget"); + // Don't free it, if we do a crash occurs later... + //free(self); + return TCL_ERROR; + } + + Tcl_AppendResult(interp, Tk_PathName(tkwin), NULL); + return TCL_OK; + } +} + + +//---------------------------------------------------------------------------- +const char *vtkTkRenderWidget_RW(const struct vtkTkRenderWidget *self) +{ + return self->RW; +} + + +//---------------------------------------------------------------------------- +int vtkTkRenderWidget_Width( const struct vtkTkRenderWidget *self) +{ + return self->Width; +} + + +//---------------------------------------------------------------------------- +int vtkTkRenderWidget_Height( const struct vtkTkRenderWidget *self) +{ + return self->Height; +} + + +/* + *---------------------------------------------------------------------- + * + * vtkTkRenderWidget_Destroy --- + * + * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release + * to clean up the internal structure of a canvas at a safe time + * (when no-one is using it anymore). + * + * Results: + * None. + * + * Side effects: + * Everything associated with the canvas is freed up. + * + *---------------------------------------------------------------------- + */ + +extern "C" +{ + void vtkTkRenderWidget_Destroy(char *memPtr) + { + struct vtkTkRenderWidget *self = (struct vtkTkRenderWidget *)memPtr; + + if (self->RenderWindow) + { + int netRefCount = self->RenderWindow->GetReferenceCount(); + if (self->RenderWindow->GetInteractor() && + self->RenderWindow->GetInteractor()->GetRenderWindow() == self->RenderWindow && + self->RenderWindow->GetInteractor()->GetReferenceCount() == 1) + { + netRefCount = netRefCount - 1; + } + if (netRefCount > 1) + { + vtkGenericWarningMacro( + "A TkRenderWidget is being destroyed before it associated vtkRenderWindow is destroyed." + "This is very bad and usually due to the order in which objects are being destroyed." + "Always destroy the vtkRenderWindow before destroying the user interface components."); + } + self->RenderWindow->UnRegister(NULL); + self->RenderWindow = NULL; + } + ckfree (self->RW); + ckfree(memPtr); + } +} + +//---------------------------------------------------------------------------- +// This gets called to handle vtkTkRenderWidget window configuration events +// Possibly X dependent +extern "C" +{ + void vtkTkRenderWidget_EventProc(ClientData clientData, + XEvent *eventPtr) + { + struct vtkTkRenderWidget *self = (struct vtkTkRenderWidget *)clientData; + + switch (eventPtr->type) + { + case Expose: + if ((eventPtr->xexpose.count == 0) + /* && !self->UpdatePending*/) + { + // let the user bind expose events + // self->RenderWindow->Render(); + } + break; + case ConfigureNotify: + //if ( Tk_IsMapped(self->TkWin) ) + { + self->Width = Tk_Width(self->TkWin); + self->Height = Tk_Height(self->TkWin); + //Tk_GeometryRequest(self->TkWin,self->Width,self->Height); + if (self->RenderWindow) + { +// VTK_USE_CARBON: Do not call SetSize or SetPosition until we're +// mapped and if we aren't mapped, clear the AGL_BUFFER_RECT. +#ifdef VTK_USE_CARBON + if (Tk_IsMapped(self->TkWin)) + { + TkWindow *winPtr = (TkWindow *)self->TkWin; + self->RenderWindow->SetPosition(winPtr->privatePtr->xOff, + winPtr->privatePtr->yOff); + self->RenderWindow->SetSize(self->Width, self->Height); + } + else + { + self->RenderWindow->SetSize(0, 0); + } +#else + self->RenderWindow->SetPosition(Tk_X(self->TkWin),Tk_Y(self->TkWin)); + self->RenderWindow->SetSize(self->Width, self->Height); +#endif + } + //vtkTkRenderWidget_PostRedisplay(self); + } + break; + case MapNotify: + { +// VTK_USE_CARBON: we need to update the current AGL_BUFFER_RECT by +// calling vtkCarbonRenderWindow::SetSize and vtkCarbonRenderWindow::SetPosition +#ifdef VTK_USE_CARBON + TkWindow *winPtr = (TkWindow *)self->TkWin; + self->RenderWindow->SetPosition(winPtr->privatePtr->xOff, + winPtr->privatePtr->yOff); + self->RenderWindow->SetSize(self->Width, self->Height); +#endif + break; + } +// VTK_USE_CARBON: we need to clear the current AGL_BUFFER_RECT by +// calling vtkCarbonRenderWindow::SetSize(0,0). +#ifdef VTK_USE_CARBON + case UnmapNotify: + { + self->RenderWindow->SetSize(0, 0); + break; + } +#endif + case DestroyNotify: + Tcl_EventuallyFree((ClientData) self, vtkTkRenderWidget_Destroy ); + break; + default: + // nothing + ; + } + } +} + + + +//---------------------------------------------------------------------------- +// vtkTkRenderWidget_Init +// Called upon system startup to create vtkTkRenderWidget command. +extern "C" {VTK_TK_EXPORT int Vtktkrenderwidget_Init(Tcl_Interp *interp);} + +#define VTKTK_TO_STRING(x) VTKTK_TO_STRING0(x) +#define VTKTK_TO_STRING0(x) VTKTK_TO_STRING1(x) +#define VTKTK_TO_STRING1(x) #x +#define VTKTK_VERSION VTKTK_TO_STRING(VTK_MAJOR_VERSION) "." VTKTK_TO_STRING(VTK_MINOR_VERSION) + +int VTK_TK_EXPORT Vtktkrenderwidget_Init(Tcl_Interp *interp) +{ + // This widget requires Tk to function. + Tcl_PkgRequire(interp, (char *)"Tk", (char*)TK_VERSION, 0); + if(Tcl_PkgPresent(interp, (char *)"Tk", (char*)TK_VERSION, 0)) + { + // Register the commands for this package. + Tcl_CreateCommand(interp, (char*)"vtkTkRenderWidget", + vtkTkRenderWidget_Cmd, Tk_MainWindow(interp), NULL); + Tcl_CreateCommand(interp, (char*)"vtkImageDataToTkPhoto", + vtkImageDataToTkPhoto_Cmd, NULL, NULL); + + // Report that the package is provided. + return Tcl_PkgProvide(interp, (char*)"Vtktkrenderwidget", + (char*)VTKTK_VERSION); + } + else + { + // Tk is not available. + return TCL_ERROR; + } +} + + +// Here is the windows specific code for creating the window +// The Xwindows version follows after this +#ifdef _WIN32 + +LRESULT APIENTRY vtkTkRenderWidgetProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + LRESULT rval; + struct vtkTkRenderWidget *self = + (struct vtkTkRenderWidget *)vtkGetWindowLong(hWnd,4); + + if (!self) + { + return 1; + } + + // watch for WM_USER + 12 this is a special message + // from the vtkRenderWIndowInteractor letting us + // know it wants to get events also + if ((message == WM_USER+12)&&(wParam == 24)) + { + WNDPROC tmp = (WNDPROC)lParam; + // we need to tell it what the original vtk event handler was + vtkSetWindowLong(hWnd,4,(LONG)self->RenderWindow); + tmp(hWnd, WM_USER+13,26,(LONG)self->OldProc); + vtkSetWindowLong(hWnd,4,(LONG)self); + self->OldProc = tmp; + return 1; + } + if ((message == WM_USER+14)&&(wParam == 28)) + { + WNDPROC tmp = (WNDPROC)lParam; + self->OldProc = tmp; + return 1; + } + + if (!self->TkWin) + { + return 1; + } + + // forward message to Tk handler + vtkSetWindowLong(hWnd,4,(LONG)((TkWindow *)self->TkWin)->window); + if (((TkWindow *)self->TkWin)->parentPtr) + { + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)TkWinChildProc); + rval = TkWinChildProc(hWnd,message,wParam,lParam); + } + else + { +#if(TK_MAJOR_VERSION < 8) + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)TkWinTopLevelProc); + rval = TkWinTopLevelProc(hWnd,message,wParam,lParam); +#else + if (message == WM_WINDOWPOSCHANGED) + { + XEvent event; + WINDOWPOS *pos = (WINDOWPOS *) lParam; + TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(pos->hwnd); + + if (winPtr == NULL) { + return 0; + } + + /* + * Update the shape of the contained window. + */ + if (!(pos->flags & SWP_NOSIZE)) { + winPtr->changes.width = pos->cx; + winPtr->changes.height = pos->cy; + } + if (!(pos->flags & SWP_NOMOVE)) { + winPtr->changes.x = pos->x; + winPtr->changes.y = pos->y; + } + + + /* + * Generate a ConfigureNotify event. + */ + event.type = ConfigureNotify; + event.xconfigure.serial = winPtr->display->request; + event.xconfigure.send_event = False; + event.xconfigure.display = winPtr->display; + event.xconfigure.event = winPtr->window; + event.xconfigure.window = winPtr->window; + event.xconfigure.border_width = winPtr->changes.border_width; + event.xconfigure.override_redirect = winPtr->atts.override_redirect; + event.xconfigure.x = winPtr->changes.x; + event.xconfigure.y = winPtr->changes.y; + event.xconfigure.width = winPtr->changes.width; + event.xconfigure.height = winPtr->changes.height; + event.xconfigure.above = None; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + + Tcl_ServiceAll(); + return 0; + } + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)TkWinChildProc); + rval = TkWinChildProc(hWnd,message,wParam,lParam); +#endif + } + + if (message != WM_PAINT) + { + if (self->RenderWindow) + { + vtkSetWindowLong(hWnd,4,(LONG)self->RenderWindow); + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)self->OldProc); + CallWindowProc(self->OldProc,hWnd,message,wParam,lParam); + } + } + + // now reset to the original config + vtkSetWindowLong(hWnd,4,(LONG)self); + vtkSetWindowLong(hWnd,GWL_WNDPROC,(LONG)vtkTkRenderWidgetProc); + return rval; +} + +//----------------------------------------------------------------------------- +// Creates a render window and forces Tk to use the window. +static int vtkTkRenderWidget_MakeRenderWindow(struct vtkTkRenderWidget *self) +{ + Display *dpy; + TkWindow *winPtr = (TkWindow *) self->TkWin; + Tcl_HashEntry *hPtr; + int new_flag; + vtkWin32OpenGLRenderWindow *renderWindow; + TkWinDrawable *twdPtr; + HWND parentWin; + + if (self->RenderWindow) + { + return TCL_OK; + } + + dpy = Tk_Display(self->TkWin); + + if (winPtr->window != None) + { + // XDestroyWindow(dpy, winPtr->window); + } + + if (self->RW[0] == '\0') + { + // Make the Render window. + self->RenderWindow = vtkRenderWindow::New(); + self->RenderWindow->Register(NULL); + self->RenderWindow->Delete(); + renderWindow = (vtkWin32OpenGLRenderWindow *)(self->RenderWindow); +#ifndef VTK_PYTHON_BUILD + vtkTclGetObjectFromPointer(self->Interp, self->RenderWindow, + "vtkRenderWindow"); +#endif + self->RW = ckalloc(strlen(self->Interp->result) + 1); + strcpy(self->RW, self->Interp->result); + self->Interp->result[0] = '\0'; + } + else + { + // is RW an address ? big ole python hack here + if (self->RW[0] == 'A' && self->RW[1] == 'd' && + self->RW[2] == 'd' && self->RW[3] == 'r') + { + void *tmp; + sscanf(self->RW+5,"%p",&tmp); + renderWindow = (vtkWin32OpenGLRenderWindow *)tmp; + } + else + { +#ifndef VTK_PYTHON_BUILD + renderWindow = (vtkWin32OpenGLRenderWindow *) + vtkTclGetPointerFromObject(self->RW, "vtkRenderWindow", self->Interp, + new_flag); +#else + renderWindow = 0; +#endif + } + if (renderWindow != self->RenderWindow) + { + if (self->RenderWindow != NULL) + { + self->RenderWindow->UnRegister(NULL); + } + self->RenderWindow = (vtkRenderWindow *)(renderWindow); + if (self->RenderWindow != NULL) + { + self->RenderWindow->Register(NULL); + } + } + } + + // Set the size + self->RenderWindow->SetSize(self->Width, self->Height); + + // Set the parent correctly + // Possibly X dependent + if ((winPtr->parentPtr != NULL) && !(winPtr->flags & TK_TOP_LEVEL)) + { + if (winPtr->parentPtr->window == None) + { + Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr); + } + + parentWin = ((TkWinDrawable *)winPtr->parentPtr->window)->window.handle; + renderWindow->SetParentId(parentWin); + } + + // Use the same display + self->RenderWindow->SetDisplayId(dpy); + + /* Make sure Tk knows to switch to the new colormap when the cursor + * is over this window when running in color index mode. + */ + //Tk_SetWindowVisual(self->TkWin, renderWindow->GetDesiredVisual(), + //renderWindow->GetDesiredDepth(), + //renderWindow->GetDesiredColormap()); + + self->RenderWindow->Render(); + +#if(TK_MAJOR_VERSION >= 8) + twdPtr = (TkWinDrawable*)Tk_AttachHWND(self->TkWin, renderWindow->GetWindowId()); +#else + twdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable)); + twdPtr->type = TWD_WINDOW; + twdPtr->window.winPtr = winPtr; + twdPtr->window.handle = renderWindow->GetWindowId(); +#endif + + self->OldProc = (WNDPROC)vtkGetWindowLong(twdPtr->window.handle,GWL_WNDPROC); + vtkSetWindowLong(twdPtr->window.handle,4,(LONG)self); + vtkSetWindowLong(twdPtr->window.handle,GWL_WNDPROC, + (LONG)vtkTkRenderWidgetProc); + + winPtr->window = (Window)twdPtr; + + hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable, + (char *) winPtr->window, &new_flag); + Tcl_SetHashValue(hPtr, winPtr); + + + winPtr->dirtyAtts = 0; + winPtr->dirtyChanges = 0; +#ifdef TK_USE_INPUT_METHODS + winPtr->inputContext = NULL; +#endif // TK_USE_INPUT_METHODS + + if (!(winPtr->flags & TK_TOP_LEVEL)) + { + /* + * If this window has a different colormap than its parent, add + * the window to the WM_COLORMAP_WINDOWS property for its top-level. + */ + if ((winPtr->parentPtr != NULL) && + (winPtr->atts.colormap != winPtr->parentPtr->atts.colormap)) + { + TkWmAddToColormapWindows(winPtr); + } + } + + /* + * Issue a ConfigureNotify event if there were deferred configuration + * changes (but skip it if the window is being deleted; the + * ConfigureNotify event could cause problems if we're being called + * from Tk_DestroyWindow under some conditions). + */ + if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY) + && !(winPtr->flags & TK_ALREADY_DEAD)) + { + XEvent event; + + winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY; + + event.type = ConfigureNotify; + event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display); + event.xconfigure.send_event = False; + event.xconfigure.display = winPtr->display; + event.xconfigure.event = winPtr->window; + event.xconfigure.window = winPtr->window; + event.xconfigure.x = winPtr->changes.x; + event.xconfigure.y = winPtr->changes.y; + event.xconfigure.width = winPtr->changes.width; + event.xconfigure.height = winPtr->changes.height; + event.xconfigure.border_width = winPtr->changes.border_width; + if (winPtr->changes.stack_mode == Above) + { + event.xconfigure.above = winPtr->changes.sibling; + } + else + { + event.xconfigure.above = None; + } + event.xconfigure.override_redirect = winPtr->atts.override_redirect; + Tk_HandleEvent(&event); + } + + return TCL_OK; +} +#else + +// the carbon version - tk not available using the cocoa api +#ifdef VTK_USE_CARBON +//---------------------------------------------------------------------------- +// Creates a render window and forces Tk to use the window. +static int +vtkTkRenderWidget_MakeRenderWindow(struct vtkTkRenderWidget *self) +{ + Display *dpy; + TkWindow *winPtr = (TkWindow *)self->TkWin; + vtkCarbonRenderWindow *renderWindow = NULL; + WindowPtr parentWin; + + if (self->RenderWindow) + { + return TCL_OK; + } + + dpy = Tk_Display(self->TkWin); + + if (self->RW[0] == '\0') + { + // Make the Render window. + self->RenderWindow = vtkRenderWindow::New(); + self->RenderWindow->Register(NULL); + self->RenderWindow->Delete(); + renderWindow = (vtkCarbonRenderWindow *)(self->RenderWindow); +#ifndef VTK_PYTHON_BUILD + vtkTclGetObjectFromPointer(self->Interp, self->RenderWindow, + "vtkRenderWindow"); +#endif + self->RW = ckalloc(strlen(self->Interp->result) + 1); + strcpy(self->RW, self->Interp->result); + self->Interp->result[0] = '\0'; + } + else + { + // is RW an address ? big ole python hack here + if (self->RW[0] == 'A' && self->RW[1] == 'd' && + self->RW[2] == 'd' && self->RW[3] == 'r') + { + void *tmp; + sscanf(self->RW+5,"%p",&tmp); + renderWindow = (vtkCarbonRenderWindow *)tmp; + } + else + { +#ifndef VTK_PYTHON_BUILD + int new_flag; + renderWindow = (vtkCarbonRenderWindow *) + vtkTclGetPointerFromObject(self->RW,"vtkRenderWindow",self->Interp, + new_flag); +#endif + } + if (renderWindow != self->RenderWindow) + { + if (self->RenderWindow != NULL) + { + self->RenderWindow->UnRegister(NULL); + } + self->RenderWindow = (vtkRenderWindow *)(renderWindow); + if (self->RenderWindow != NULL) + { + self->RenderWindow->Register(NULL); + } + } + } + + // Position should be set, but only if winPtr properly initialized + // + //self->RenderWindow->SetPosition(winPtr->privatePtr->xOff, + // winPtr->privatePtr->yOff); + self->RenderWindow->SetSize(self->Width, self->Height); + + // Set the parent correctly and get the actual OSX window on the screen + // Window must be up so that the aglContext can be attached to it + if ((winPtr->parentPtr != NULL) && !(winPtr->flags & TK_TOP_LEVEL)) + { + if (winPtr->parentPtr->window == None) + { + // Look at each parent TK window in order until we run out + // of windows or find the top level. Then the OSX window that will be + // the parent is created so that we have a window to pass to the + // vtkRenderWindow so it can attach its openGL context. + // Ideally the Tk_MakeWindowExist call would do the deed. (I think) + TkWindow *curWin = winPtr->parentPtr; + while ((NULL != curWin->parentPtr) && !(curWin->flags & TK_TOP_LEVEL)) + { + curWin = curWin->parentPtr; + } + Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr); + if (NULL != curWin) + { + TkMacOSXMakeRealWindowExist(curWin); + } + else + { + vtkGenericWarningMacro("Could not find the TK_TOP_LEVEL. This is bad."); + } + } + + parentWin = GetWindowFromPort(TkMacOSXGetDrawablePort( + Tk_WindowId(winPtr->parentPtr))); + // Carbon does not have 'sub-windows', so the ParentId is used more + // as a flag to indicate that the renderwindow is being used as a sub- + // view of its 'parent' window. + renderWindow->SetParentId(parentWin); + renderWindow->SetRootWindow(parentWin); + } + + // Use the same display + renderWindow->SetDisplayId(dpy); + + // Don't render yet, the widget isn't necessarily mapped + // self->RenderWindow->Render(); + + XSelectInput(dpy, Tk_WindowId(self->TkWin), VTK_ALL_EVENTS_MASK); + + /* + * Issue a ConfigureNotify event if there were deferred configuration + * changes (but skip it if the window is being deleted; the + * ConfigureNotify event could cause problems if we're being called + * from Tk_DestroyWindow under some conditions). + */ + if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY) + && !(winPtr->flags & TK_ALREADY_DEAD)) + { + XEvent event; + + winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY; + + event.type = ConfigureNotify; + event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display); + event.xconfigure.send_event = False; + event.xconfigure.display = winPtr->display; + event.xconfigure.event = winPtr->window; + event.xconfigure.window = winPtr->window; + event.xconfigure.x = winPtr->changes.x; + event.xconfigure.y = winPtr->changes.y; + event.xconfigure.width = winPtr->changes.width; + event.xconfigure.height = winPtr->changes.height; + event.xconfigure.border_width = winPtr->changes.border_width; + if (winPtr->changes.stack_mode == Above) + { + event.xconfigure.above = winPtr->changes.sibling; + } + else + { + event.xconfigure.above = None; + } + event.xconfigure.override_redirect = winPtr->atts.override_redirect; + Tk_HandleEvent(&event); + } + else + { + // Assume that vtkTkRenderWidget will be packed after this + // method is called. Reset the AGL_BUFFER_RECT to avoid getting the + // initial 'black square'. + + // Cast to a vtkCarbonRenderWindow so we can access the necessary members. + vtkCarbonRenderWindow *carbonRW = (vtkCarbonRenderWindow *)self->RenderWindow; + carbonRW->Initialize(); + carbonRW->UpdateSizeAndPosition(0, 0, 0, 0); + carbonRW->UpdateGLRegion(); + } + + return TCL_OK; +} + +// now the Xwindows version +#else + +//---------------------------------------------------------------------------- +// Creates a render window and forces Tk to use the window. +static int +vtkTkRenderWidget_MakeRenderWindow(struct vtkTkRenderWidget *self) +{ + Display *dpy; + vtkXOpenGLRenderWindow *renderWindow = 0; + + if (self->RenderWindow) + { + return TCL_OK; + } + + dpy = Tk_Display(self->TkWin); + + if (Tk_WindowId(self->TkWin) != None) + { + XDestroyWindow(dpy, Tk_WindowId(self->TkWin)); + } + + if (self->RW[0] == '\0') + { + // Make the Render window. + self->RenderWindow = vtkRenderWindow::New(); + self->RenderWindow->Register(NULL); + self->RenderWindow->Delete(); + renderWindow = (vtkXOpenGLRenderWindow *)(self->RenderWindow); +#ifndef VTK_PYTHON_BUILD + vtkTclGetObjectFromPointer(self->Interp, self->RenderWindow, + "vtkRenderWindow"); +#endif + self->RW = ckalloc(strlen(self->Interp->result) + 1); + strcpy(self->RW, self->Interp->result); + self->Interp->result[0] = '\0'; + } + else + { + // is RW an address ? big ole python hack here + if (self->RW[0] == 'A' && self->RW[1] == 'd' && + self->RW[2] == 'd' && self->RW[3] == 'r') + { + void *tmp; + sscanf(self->RW+5,"%p",&tmp); + renderWindow = (vtkXOpenGLRenderWindow *)tmp; + } + else + { +#ifndef VTK_PYTHON_BUILD + int new_flag; + renderWindow = (vtkXOpenGLRenderWindow *) + vtkTclGetPointerFromObject(self->RW,"vtkRenderWindow",self->Interp, + new_flag); +#endif + } + if (renderWindow != self->RenderWindow) + { + if (self->RenderWindow != NULL) {self->RenderWindow->UnRegister(NULL);} + self->RenderWindow = (vtkRenderWindow *)(renderWindow); + if (self->RenderWindow != NULL) {self->RenderWindow->Register(NULL);} + } + } + + // If window already exists, return an error + if ( renderWindow->GetWindowId() != (Window)NULL ) + { + return TCL_ERROR; + } + + // Use the same display + renderWindow->SetDisplayId(dpy); + + /* Make sure Tk knows to switch to the new colormap when the cursor + * is over this window when running in color index mode. + */ + // The visual MUST BE SET BEFORE the window is created. + Tk_SetWindowVisual(self->TkWin, renderWindow->GetDesiredVisual(), + renderWindow->GetDesiredDepth(), + renderWindow->GetDesiredColormap()); + + // Make this window exist, then use that information to make the vtkImageViewer in sync + Tk_MakeWindowExist ( self->TkWin ); + renderWindow->SetWindowId ( (void*)Tk_WindowId ( self->TkWin ) ); + + // Set the size + self->RenderWindow->SetSize(self->Width, self->Height); + + // Set the parent correctly + // Possibly X dependent + if ((Tk_Parent(self->TkWin) == NULL) || (Tk_IsTopLevel(self->TkWin))) + { + renderWindow->SetParentId(XRootWindow(Tk_Display(self->TkWin), + Tk_ScreenNumber(self->TkWin))); + } + else + { + renderWindow->SetParentId(Tk_WindowId(Tk_Parent(self->TkWin) )); + } + + self->RenderWindow->Render(); + XSelectInput(dpy, Tk_WindowId(self->TkWin), VTK_ALL_EVENTS_MASK); + + return TCL_OK; +} +#endif + + +#endif diff --git a/Rendering/vtkTkRenderWidget.h b/Rendering/vtkTkRenderWidget.h new file mode 100644 index 0000000..bd0779d --- /dev/null +++ b/Rendering/vtkTkRenderWidget.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkRenderWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTkRenderWidget - a Tk Widget for vtk renderering + +// .SECTION Description +// vtkTkRenderWidget is a Tk widget that you can render into. It has a +// GetRenderWindow method that returns a vtkRenderWindow. This can then +// be used to create a vtkRenderer and etc. You can also specify a +// vtkRenderWindow to be used when creating the widget by using +// the -rw option. It also takes -width and -height options. +// Events can be bound on this widget just like any other Tk widget. + +// .SECTION See Also +// vtkRenderWindow vtkRenderer + + +#ifndef __vtkTkRenderWidget_h +#define __vtkTkRenderWidget_h + +#include "vtkRenderWindow.h" +#include "vtkTcl.h" +#include "vtkWindows.h" + +// For the moment, we are not compatible w/Photo compositing +// By defining USE_COMPOSITELESS_PHOTO_PUT_BLOCK, we use the compatible +// call. +#define USE_COMPOSITELESS_PHOTO_PUT_BLOCK +#include "vtkTk.h" + +#ifndef VTK_PYTHON_BUILD +#include "vtkTclUtil.h" +#endif + +struct vtkTkRenderWidget +{ + Tk_Window TkWin; /* Tk window structure */ + Tcl_Interp *Interp; /* Tcl interpreter */ + int Width; + int Height; + vtkRenderWindow *RenderWindow; + char *RW; +#ifdef _WIN32 + WNDPROC OldProc; +#endif +}; + +#endif diff --git a/Rendering/vtkTkRenderWidgetPython.cxx b/Rendering/vtkTkRenderWidgetPython.cxx new file mode 100644 index 0000000..84ea3d8 --- /dev/null +++ b/Rendering/vtkTkRenderWidgetPython.cxx @@ -0,0 +1,17 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkRenderWidgetPython.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#define VTK_PYTHON_BUILD +#include "vtkTkRenderWidget.cxx" diff --git a/Rendering/vtkTkWidgetsInit.cxx b/Rendering/vtkTkWidgetsInit.cxx new file mode 100644 index 0000000..0f25885 --- /dev/null +++ b/Rendering/vtkTkWidgetsInit.cxx @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTkWidgetsInit.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTcl.h" +#include "vtkTk.h" + +#include "vtkTkImageViewerWidget.h" +#include "vtkTkRenderWidget.h" +#include "vtkImageData.h" + + +//---------------------------------------------------------------------------- +// Vtkrenderingpythontkwidgets_Init +// Called upon system startup to create the widget commands. +extern "C" {VTK_TK_EXPORT int Vtkrenderingpythontkwidgets_Init(Tcl_Interp *interp);} + +extern "C" {VTK_TK_EXPORT int Vtktkrenderwidget_Init(Tcl_Interp *interp);} +extern "C" {VTK_TK_EXPORT int Vtktkimageviewerwidget_Init(Tcl_Interp *interp);} + +#define VTKTK_TO_STRING(x) VTKTK_TO_STRING0(x) +#define VTKTK_TO_STRING0(x) VTKTK_TO_STRING1(x) +#define VTKTK_TO_STRING1(x) #x +#define VTKTK_VERSION VTKTK_TO_STRING(VTK_MAJOR_VERSION) "." VTKTK_TO_STRING(VTK_MINOR_VERSION) + +int Vtkrenderingpythontkwidgets_Init(Tcl_Interp *interp) +{ + // Forward the call to the real init functions. + if(Vtktkrenderwidget_Init(interp) == TCL_OK && + Vtktkimageviewerwidget_Init(interp) == TCL_OK) + { + // Report that the package is provided. + return Tcl_PkgProvide(interp, (char*)"Vtkrenderingpythontkwidgets", + (char*)VTKTK_VERSION); + } + else + { + // One of the widgets is not provided. + return TCL_ERROR; + } +} diff --git a/Rendering/vtkTransformInterpolator.cxx b/Rendering/vtkTransformInterpolator.cxx new file mode 100644 index 0000000..179bf46 --- /dev/null +++ b/Rendering/vtkTransformInterpolator.cxx @@ -0,0 +1,447 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformInterpolator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTransformInterpolator.h" +#include "vtkObjectFactory.h" +#include "vtkTransform.h" +#include "vtkMatrix4x4.h" +#include "vtkProp3D.h" +#include "vtkTupleInterpolator.h" +#include "vtkQuaternionInterpolator.h" +#include + +vtkCxxRevisionMacro(vtkTransformInterpolator, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkTransformInterpolator); + +// PIMPL STL encapsulation for list of transforms, and list of +// quaternions. This just keeps track of all the data the user specifies, +// which is later dumped into the interpolators. +struct vtkQTransform +{ + double Time; + double P[3]; + double S[3]; + double Q[4]; + + vtkQTransform() + { + this->Time = 0.0; + this->P[0] = this->P[1] = this->P[2] = 0.0; + this->S[0] = this->S[1] = this->S[2] = 0.0; + this->Q[0] = this->Q[1] = this->Q[2] = this->Q[3] = 0.0; + } + vtkQTransform(double t, vtkTransform *xform) + { + this->Time = t; + if ( xform ) + { + xform->GetPosition(this->P); + xform->GetScale(this->S); + xform->GetOrientationWXYZ(this->Q); //Rotation (in degrees) around unit vector + } + else + { + this->P[0] = this->P[1] = this->P[2] = 0.0; + this->S[0] = this->S[1] = this->S[2] = 0.0; + this->Q[0] = this->Q[1] = this->Q[2] = this->Q[3] = 0.0; + } + } +}; + +// The list is arranged in increasing order in T +class vtkTransformList : public vtkstd::list {}; +typedef vtkTransformList::iterator TransformListIterator; + + +//---------------------------------------------------------------------------- +vtkTransformInterpolator::vtkTransformInterpolator() +{ + // Set up the interpolation + this->InterpolationType = INTERPOLATION_TYPE_SPLINE; + + // Spline interpolation + this->PositionInterpolator = vtkTupleInterpolator::New(); + this->ScaleInterpolator = vtkTupleInterpolator::New(); + this->RotationInterpolator = vtkQuaternionInterpolator::New(); + + // Quaternion interpolation + this->TransformList = new vtkTransformList; + this->Initialized = 0; +} + +//---------------------------------------------------------------------------- +vtkTransformInterpolator::~vtkTransformInterpolator() +{ + delete this->TransformList; + + if ( this->PositionInterpolator ) + { + this->PositionInterpolator->Delete(); + } + if ( this->ScaleInterpolator ) + { + this->ScaleInterpolator->Delete(); + } + if ( this->RotationInterpolator ) + { + this->RotationInterpolator->Delete(); + } +} + +//---------------------------------------------------------------------------- +unsigned long vtkTransformInterpolator::GetMTime() +{ + unsigned long mTime=this->Superclass::GetMTime(); + unsigned long posMTime, scaleMTime, rotMTime; + + if ( this->PositionInterpolator ) + { + posMTime = this->PositionInterpolator->GetMTime(); + mTime = (posMTime > mTime ? posMTime : mTime); + } + if ( this->ScaleInterpolator ) + { + scaleMTime = this->ScaleInterpolator->GetMTime(); + mTime = (scaleMTime > mTime ? scaleMTime : mTime); + } + if ( this->RotationInterpolator ) + { + rotMTime = this->RotationInterpolator->GetMTime(); + mTime = (rotMTime > mTime ? rotMTime : mTime); + } + + return mTime; +} + + +//---------------------------------------------------------------------------- +int vtkTransformInterpolator::GetNumberOfTransforms() +{ + return this->TransformList->size(); +} + + +//---------------------------------------------------------------------------- +double vtkTransformInterpolator::GetMinimumT() +{ + if ( this->TransformList->empty() ) + { + return -VTK_LARGE_FLOAT; + } + else + { + return this->TransformList->front().Time; + } +} + + +//---------------------------------------------------------------------------- +double vtkTransformInterpolator::GetMaximumT() +{ + if ( this->TransformList->empty() ) + { + return VTK_LARGE_FLOAT; + } + else + { + return this->TransformList->back().Time; + } +} + + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::Initialize() +{ + this->TransformList->clear(); +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::AddTransform(double t, vtkTransform *xform) +{ + int size = this->TransformList->size(); + + // Check special cases: t at beginning or end of list + if ( size <= 0 || t < this->TransformList->front().Time ) + { + this->TransformList->push_front(vtkQTransform(t,xform)); + return; + } + else if ( t > this->TransformList->back().Time ) + { + this->TransformList->push_back(vtkQTransform(t,xform)); + return; + } + else if ( size == 1 && t == this->TransformList->back().Time ) + { + this->TransformList->front() = vtkQTransform(t,xform); + return; + } + + // Okay, insert in sorted order + TransformListIterator iter = this->TransformList->begin(); + TransformListIterator nextIter = ++(this->TransformList->begin()); + for (int i=0; i < (size-1); i++, ++iter, ++nextIter) + { + if ( t == iter->Time ) + { + (*iter) = vtkQTransform(t,xform); + } + else if ( t > iter->Time && t < nextIter->Time ) + { + this->TransformList->insert(nextIter, vtkQTransform(t,xform)); + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::AddTransform(double t, vtkMatrix4x4 *matrix) +{ + vtkTransform *xform = vtkTransform::New(); + xform->SetMatrix(matrix); + this->AddTransform(t,xform); + xform->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::AddTransform(double t, vtkProp3D *prop3D) +{ + this->AddTransform(t,prop3D->GetMatrix()); +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::RemoveTransform(double t) +{ + if ( t < this->TransformList->front().Time || + t > this->TransformList->back().Time ) + { + return; + } + + TransformListIterator iter = this->TransformList->begin(); + for ( ; iter->Time != t && iter != this->TransformList->end(); ++iter ) + { + } + if ( iter != this->TransformList->end() ) + { + this->TransformList->erase(iter); + } +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::SetPositionInterpolator(vtkTupleInterpolator *pi) +{ + if ( this->PositionInterpolator != pi ) + { + if ( this->PositionInterpolator != NULL ) + { + this->PositionInterpolator->Delete(); + } + this->PositionInterpolator = pi; + if ( this->PositionInterpolator != NULL ) + { + this->PositionInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::SetScaleInterpolator(vtkTupleInterpolator *si) +{ + if ( this->ScaleInterpolator != si ) + { + if ( this->ScaleInterpolator != NULL ) + { + this->ScaleInterpolator->Delete(); + } + this->ScaleInterpolator = si; + if ( this->ScaleInterpolator != NULL ) + { + this->ScaleInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::SetRotationInterpolator(vtkQuaternionInterpolator *ri) +{ + if ( this->RotationInterpolator != ri ) + { + if ( this->RotationInterpolator != NULL ) + { + this->RotationInterpolator->Delete(); + } + this->RotationInterpolator = ri; + if ( this->RotationInterpolator != NULL ) + { + this->RotationInterpolator->Register(this); + } + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::InitializeInterpolation() +{ + if ( this->TransformList->empty() ) + { + return; + } + + // Set up the interpolators if we need to + if ( !this->Initialized || this->GetMTime() > this->InitializeTime ) + { + if ( !this->PositionInterpolator ) + { + this->PositionInterpolator = vtkTupleInterpolator::New(); + } + if ( !this->ScaleInterpolator ) + { + this->ScaleInterpolator = vtkTupleInterpolator::New(); + } + if ( !this->RotationInterpolator ) + { + this->RotationInterpolator = vtkQuaternionInterpolator::New(); + } + + this->PositionInterpolator->Initialize(); + this->ScaleInterpolator->Initialize(); + this->RotationInterpolator->Initialize(); + + this->PositionInterpolator->SetNumberOfComponents(3); + this->ScaleInterpolator->SetNumberOfComponents(3); + + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + this->PositionInterpolator->SetInterpolationTypeToLinear(); + this->ScaleInterpolator->SetInterpolationTypeToLinear(); + this->RotationInterpolator->SetInterpolationTypeToLinear(); + } + else if ( this->InterpolationType == INTERPOLATION_TYPE_SPLINE ) + { + this->PositionInterpolator->SetInterpolationTypeToSpline(); + this->ScaleInterpolator->SetInterpolationTypeToSpline(); + this->RotationInterpolator->SetInterpolationTypeToSpline(); + } + else + { + ; //manual override, user manipulates interpolators directly + } + + // Okay, now we can load the interpolators with data + TransformListIterator iter = this->TransformList->begin(); + for ( ; iter != this->TransformList->end(); ++iter) + { + this->PositionInterpolator->AddTuple(iter->Time,iter->P); + this->ScaleInterpolator->AddTuple(iter->Time,iter->S); + this->RotationInterpolator->AddQuaternion(iter->Time,iter->Q); + } + + this->Initialized = 1; + this->InitializeTime.Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::InterpolateTransform(double t, + vtkTransform *xform) +{ + if ( this->TransformList->empty() ) + { + return; + } + + // Make sure the xform and this class are initialized properly + xform->Identity(); + this->InitializeInterpolation(); + + // Evaluate the interpolators + if ( t < this->TransformList->front().Time ) + { + t = this->TransformList->front().Time; + } + + else if ( t > this->TransformList->back().Time ) + { + t = this->TransformList->back().Time; + } + + double P[3],S[3],Q[4]; + this->PositionInterpolator->InterpolateTuple(t,P); + this->ScaleInterpolator->InterpolateTuple(t,S); + this->RotationInterpolator->InterpolateQuaternion(t,Q); + + xform->Translate(P); + xform->RotateWXYZ(Q[0],Q+1); + xform->Scale(S); +} + +//---------------------------------------------------------------------------- +void vtkTransformInterpolator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "There are " << this->GetNumberOfTransforms() + << " transforms to be interpolated\n"; + + os << indent << "Interpolation Type: "; + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + os << "Linear\n"; + } + else if ( this->InterpolationType == INTERPOLATION_TYPE_SPLINE ) + { + os << "Spline\n"; + } + else //if ( this->InterpolationType == INTERPOLATION_TYPE_MANUAL ) + { + os << "Manual\n"; + } + + os << indent << "Position Interpolator: "; + if ( this->PositionInterpolator ) + { + os << this->PositionInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } + + os << indent << "Scale Interpolator: "; + if ( this->ScaleInterpolator ) + { + os << this->ScaleInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } + + os << indent << "Rotation Interpolator: "; + if ( this->RotationInterpolator ) + { + os << this->RotationInterpolator << "\n"; + } + else + { + os << "(null)\n"; + } +} + + + diff --git a/Rendering/vtkTransformInterpolator.h b/Rendering/vtkTransformInterpolator.h new file mode 100644 index 0000000..238c33c --- /dev/null +++ b/Rendering/vtkTransformInterpolator.h @@ -0,0 +1,190 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTransformInterpolator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTransformInterpolator - interpolate a series of transformation matrices +// .SECTION Description +// This class is used to interpolate a series of 4x4 transformation +// matrices. Position, scale and orientation (i.e., rotations) are +// interpolated separately, and can be interpolated linearly or with a spline +// function. Note that orientation is interpolated using quaternions via +// SLERP (spherical linear interpolation) or the special vtkQuaternionSpline +// class. +// +// To use this class, specify at least two pairs of (t,transformation matrix) +// with the AddTransform() method. Then interpolated the transforms with the +// InterpolateTransform(t,transform) method, where "t" must be in the range +// of (min,max) times specified by the AddTransform() method. +// +// By default, spline interpolation is used for the interpolation of the +// transformation matrices. The position, scale and orientation of the +// matrices are interpolated with instances of the classes +// vtkTupleInterpolator (position,scale) and vtkQuaternionInterpolator +// (rotation). The user can override the interpolation behavior by gaining +// access to these separate interpolation classes. These interpolator +// classes (vtkTupleInterpolator and vtkQuaternionInterpolator) can be +// modified to perform linear versus spline interpolation, and/or different +// spline basis functions can be specified. +// +// .SECTION Caveats +// The interpolator classes are initialized when the InterpolateTransform() +// is called. Any changes to the interpolators, or additions to the list of +// transforms to be interpolated, causes a reinitialization of the +// interpolators the next time InterpolateTransform() is invoked. Thus the +// best performance is obtained by 1) configuring the interpolators, 2) adding +// all the transforms, and 3) finally performing interpolation. + +#ifndef __vtkTransformInterpolator_h +#define __vtkTransformInterpolator_h + +#include "vtkObject.h" + + +class vtkTransform; +class vtkMatrix4x4; +class vtkProp3D; +class vtkTupleInterpolator; +class vtkQuaternionInterpolator; +class vtkTransformList; + + +class VTK_RENDERING_EXPORT vtkTransformInterpolator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkTransformInterpolator, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the class. + static vtkTransformInterpolator* New(); + + // Description: + // Return the number of transforms in the list of transforms. + int GetNumberOfTransforms(); + + // Description: + // Obtain some information about the interpolation range. The numbers + // returned (corresponding to parameter t, usually thought of as time) + // are undefined if the list of transforms is empty. + double GetMinimumT(); + double GetMaximumT(); + + // Description: + // Clear the list of transforms. + void Initialize(); + + // Description: + // Add another transform to the list of transformations defining + // the transform function. Note that using the same time t value + // more than once replaces the previous transform value at t. + // At least two transforms must be added to define a function. + // There are variants to this method depending on whether you are + // adding a vtkTransform, vtkMaxtirx4x4, and/or vtkProp3D. + void AddTransform(double t, vtkTransform *xform); + void AddTransform(double t, vtkMatrix4x4 *matrix); + void AddTransform(double t, vtkProp3D *prop3D); + + // Description: + // Delete the transform at a particular parameter t. If there is no + // transform defined at location t, then the method does nothing. + void RemoveTransform(double t); + + // Description: + // Interpolate the list of transforms and determine a new transform (i.e., + // fill in the transformation provided). If t is outside the range of + // (min,max) values, then t is clamped. + void InterpolateTransform(double t, vtkTransform *xform); + +//BTX + // Description: + // Enums to control the type of interpolation to use. + enum {INTERPOLATION_TYPE_LINEAR=0, + INTERPOLATION_TYPE_SPLINE, + INTERPOLATION_TYPE_MANUAL + }; +//ETX + + // Description: + // These are convenience methods to switch between linear and spline + // interpolation. The methods simply forward the request for linear or + // spline interpolation to the position, scale and orientation + // interpolators. Note that if the InterpolationType is set to "Manual", + // then the interpolators are expected to be directly manipulated and + // this class does not forward the request for interpolation type to its + // interpolators. + vtkSetClampMacro(InterpolationType,int, INTERPOLATION_TYPE_LINEAR, + INTERPOLATION_TYPE_MANUAL); + vtkGetMacro(InterpolationType,int); + void SetInterpolationTypeToLinear() + {this->SetInterpolationType(INTERPOLATION_TYPE_LINEAR);} + void SetInterpolationTypeToSpline() + {this->SetInterpolationType(INTERPOLATION_TYPE_SPLINE);} + void SetInterpolationTypeToManual() + {this->SetInterpolationType(INTERPOLATION_TYPE_MANUAL);} + + // Description: + // Set/Get the tuple interpolator used to interpolate the position portion + // of the transformation matrix. Note that you can modify the behavior of + // the interpolator (linear vs spline interpolation; change spline basis) + // by manipulating the interpolator instances. + virtual void SetPositionInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(PositionInterpolator,vtkTupleInterpolator); + + // Description: + // Set/Get the tuple interpolator used to interpolate the scale portion + // of the transformation matrix. Note that you can modify the behavior of + // the interpolator (linear vs spline interpolation; change spline basis) + // by manipulating the interpolator instances. + virtual void SetScaleInterpolator(vtkTupleInterpolator*); + vtkGetObjectMacro(ScaleInterpolator,vtkTupleInterpolator); + + // Description: + // Set/Get the tuple interpolator used to interpolate the orientation portion + // of the transformation matrix. Note that you can modify the behavior of + // the interpolator (linear vs spline interpolation; change spline basis) + // by manipulating the interpolator instances. + virtual void SetRotationInterpolator(vtkQuaternionInterpolator*); + vtkGetObjectMacro(RotationInterpolator,vtkQuaternionInterpolator); + + // Description: + // Override GetMTime() because we depend on the interpolators which may be + // modified outside of this class. + unsigned long GetMTime(); + +protected: + vtkTransformInterpolator(); + virtual ~vtkTransformInterpolator(); + + // Control the interpolation type + int InterpolationType; + + // Interpolators + vtkTupleInterpolator *PositionInterpolator; + vtkTupleInterpolator *ScaleInterpolator; + vtkQuaternionInterpolator *RotationInterpolator; + + // Initialize the interpolating splines + int Initialized; + vtkTimeStamp InitializeTime; + void InitializeInterpolation(); + + // Keep track of inserted data + vtkTransformList *TransformList; + +private: + vtkTransformInterpolator(const vtkTransformInterpolator&); // Not implemented. + void operator=(const vtkTransformInterpolator&); // Not implemented. + +}; + +#endif diff --git a/Rendering/vtkTupleInterpolator.cxx b/Rendering/vtkTupleInterpolator.cxx new file mode 100644 index 0000000..ddd7cb2 --- /dev/null +++ b/Rendering/vtkTupleInterpolator.cxx @@ -0,0 +1,317 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTupleInterpolator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkTupleInterpolator.h" +#include "vtkObjectFactory.h" +#include "vtkSpline.h" +#include "vtkKochanekSpline.h" +#include "vtkPiecewiseFunction.h" +#include "vtkMath.h" + +vtkCxxRevisionMacro(vtkTupleInterpolator, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkTupleInterpolator); + +//---------------------------------------------------------------------------- +vtkTupleInterpolator::vtkTupleInterpolator() +{ + // Set up the interpolation + this->NumberOfComponents = 0; + this->InterpolationType = INTERPOLATION_TYPE_SPLINE; + this->InterpolatingSpline = NULL; + + this->Spline = NULL; + this->Linear = NULL; +} + +//---------------------------------------------------------------------------- +vtkTupleInterpolator::~vtkTupleInterpolator() +{ + this->Initialize(); + if ( this->InterpolatingSpline ) + { + this->InterpolatingSpline->Delete(); + } +} + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::SetNumberOfComponents(int numComp) +{ + numComp = (numComp < 1 ? 1 : numComp); + if ( numComp != this->NumberOfComponents ) + { + this->Initialize(); //wipe out data + this->NumberOfComponents = numComp; + this->InitializeInterpolation(); + this->Modified(); + } +} + + +//---------------------------------------------------------------------------- +int vtkTupleInterpolator::GetNumberOfTuples() +{ + if ( this->Spline ) + { + return this->Spline[0]->GetNumberOfPoints(); + } + else if ( this->Linear ) + { + return this->Linear[0]->GetSize(); + } + else + { + return 0; + } +} + + +//---------------------------------------------------------------------------- +double vtkTupleInterpolator::GetMinimumT() +{ + if ( this->Spline ) + { + double range[2]; + this->Spline[0]->GetParametricRange(range); + return range[0]; + } + else if ( this->Linear ) + { + return this->Linear[0]->GetRange()[0]; + } + else + { + return 0.0; + } +} + + +//---------------------------------------------------------------------------- +double vtkTupleInterpolator::GetMaximumT() +{ + if ( this->Spline ) + { + double range[2]; + this->Spline[0]->GetParametricRange(range); + return range[1]; + } + else if ( this->Linear ) + { + return this->Linear[0]->GetRange()[1]; + } + else + { + return 1.0; + } +} + + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::Initialize() +{ + int i; + + // Wipe out old data + if ( this->Spline ) + { + for (i=0; iNumberOfComponents; i++) + { + this->Spline[i]->Delete(); + } + delete [] this->Spline; + this->Spline = NULL; + } + if ( this->Linear ) + { + for (i=0; iNumberOfComponents; i++) + { + this->Linear[i]->Delete(); + } + delete [] this->Linear; + this->Linear = NULL; + } + + this->NumberOfComponents = 0; +} + + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::InitializeInterpolation() +{ + // Prepare for new data + if ( this->NumberOfComponents <= 0 ) + { + return; + } + + int i; + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + this->Linear = new vtkPiecewiseFunction* [this->NumberOfComponents]; + for (i=0; iNumberOfComponents; i++) + { + this->Linear[i] = vtkPiecewiseFunction::New(); + } + } + + else // this->InterpolationType == INTERPOLATION_TYPE_SPLINE + { + this->Spline = new vtkSpline* [this->NumberOfComponents]; + if ( ! this->InterpolatingSpline ) + { + this->InterpolatingSpline = vtkKochanekSpline::New(); + } + for (i=0; iNumberOfComponents; i++) + { + this->Spline[i] = this->InterpolatingSpline->NewInstance(); + this->Spline[i]->DeepCopy(this->InterpolatingSpline); + this->Spline[i]->RemoveAllPoints(); + } + } +} + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::SetInterpolationType(int type) +{ + type = (type < INTERPOLATION_TYPE_LINEAR ? INTERPOLATION_TYPE_LINEAR : + (type > INTERPOLATION_TYPE_SPLINE ? INTERPOLATION_TYPE_SPLINE : type)); + if ( type != this->InterpolationType ) + { + this->Initialize(); //wipe out data + this->InterpolationType = type; + this->InitializeInterpolation(); + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::SetInterpolatingSpline(vtkSpline *spline) +{ + if ( this->InterpolatingSpline == spline ) + { + return; + } + if ( this->InterpolatingSpline ) + { + this->InterpolatingSpline->UnRegister(this); + this->InterpolatingSpline = NULL; + } + if ( spline ) + { + spline->Register(this); + } + this->InterpolatingSpline = spline; + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::AddTuple(double t, double tuple[]) +{ + int i; + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + for (i=0; iNumberOfComponents; i++) + { + this->Linear[i]->AddPoint(t,tuple[i]); + } + } + + else // this->InterpolationType == INTERPOLATION_TYPE_SPLINE + { + for (i=0; iNumberOfComponents; i++) + { + this->Spline[i]->AddPoint(t,tuple[i]); + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::RemoveTuple(double t) +{ + int i; + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + for (i=0; iNumberOfComponents; i++) + { + this->Linear[i]->RemovePoint(t); + } + } + + else // this->InterpolationType == INTERPOLATION_TYPE_SPLINE + { + for (i=0; iNumberOfComponents; i++) + { + this->Spline[i]->RemovePoint(t); + } + } + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::InterpolateTuple(double t, double tuple[]) +{ + if ( this->NumberOfComponents <= 0 ) + { + return; + } + + int i; + if ( this->InterpolationType == INTERPOLATION_TYPE_LINEAR ) + { + double *range=this->Linear[0]->GetRange(); + t = (t < range[0] ? range[0] : (t > range[1] ? range[1] : t)); + for (i=0; iNumberOfComponents; i++) + { + tuple[i] = this->Linear[i]->GetValue(t); + } + } + + else // this->InterpolationType == INTERPOLATION_TYPE_SPLINE + { + for (i=0; iNumberOfComponents; i++) + { + tuple[i] = this->Spline[i]->Evaluate(t); + } + } +} + +//---------------------------------------------------------------------------- +void vtkTupleInterpolator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "There are " << this->GetNumberOfTuples() + << " tuples to be interpolated\n"; + + os << indent << "Number of Components: " << this->NumberOfComponents << "\n"; + + os << indent << "Interpolation Type: " + << (this->InterpolationType == INTERPOLATION_TYPE_LINEAR ? + "Linear\n" : "Spline\n"); + + os << indent << "Interpolating Spline: "; + if ( this->InterpolatingSpline ) + { + os << this->InterpolatingSpline << "\n"; + } + else + { + os << "(null)\n"; + } +} + + + diff --git a/Rendering/vtkTupleInterpolator.h b/Rendering/vtkTupleInterpolator.h new file mode 100644 index 0000000..e712410 --- /dev/null +++ b/Rendering/vtkTupleInterpolator.h @@ -0,0 +1,161 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkTupleInterpolator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkTupleInterpolator - interpolate a tuple of arbitray size +// .SECTION Description +// This class is used to interpolate a tuple which may have an arbitrary +// number of components (but at least one component). The interpolation may +// be linear in form, or via a subclasses of vtkSpline. +// +// To use this class, begin by specifying the number of components of the +// tuple and the interpolation function to use. Then specify at least one +// pair of (t,tuple) with the AddTuple() method. Next interpolate the +// tuples with the InterpolateTuple(t,tuple) method, where "t" must be in the +// range of (t_min,t_max) parameter values specified by the AddTuple() method +// (if not then t is clamped), and tuple[] is filled in by the method (make +// sure that tuple [] is long enough to hold the interpolated data). +// +// You can control the type of interpolation to use. By default, the +// interpolation is based on a Kochanek spline. However, other types of +// splines can be specified. You can also set the interpolation method +// to linear, in which case the specified spline has no effect on the +// interpolation. + +// .SECTION Caveats +// Setting the number of components or changing the type of interpolation +// causes the list of tuples to be reset, so any data inserted up to that +// point is lost. Bisection methods are used to speed up the search for the +// interpolation interval. + +#ifndef __vtkTupleInterpolator_h +#define __vtkTupleInterpolator_h + +#include "vtkObject.h" + +class vtkSpline; +class vtkPiecewiseFunction; + + +class VTK_RENDERING_EXPORT vtkTupleInterpolator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkTupleInterpolator, vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate the class. + static vtkTupleInterpolator* New(); + + // Description: + // Specify the number of tuple components to interpolate. Note that setting + // this value discards any previously inserted data. + void SetNumberOfComponents(int numComp); + vtkGetMacro(NumberOfComponents,int); + + // Description: + // Return the number of tuples in the list of tuples to be + // interpolated. + int GetNumberOfTuples(); + + // Description: + // Obtain some information about the interpolation range. The numbers + // returned (corresponding to parameter t, usually thought of as time) + // are undefined if the list of transforms is empty. This is a convenience + // method for interpolation. + double GetMinimumT(); + double GetMaximumT(); + + // Description: + // Reset the class so that it contains no (t,tuple) information. + void Initialize(); + + // Description: + // Add another tuple to the list of tuples to be interpolated. Note that + // using the same time t value more than once replaces the previous tuple + // value at t. At least two tuples must be added to define an + // interpolation function. + void AddTuple(double t, double tuple[]); + + // Description: + // Delete the tuple at a particular parameter t. If there is no + // tuple defined at t, then the method does nothing. + void RemoveTuple(double t); + + // Description: + // Interpolate the list of tuples and determine a new tuple (i.e., + // fill in the tuple provided). If t is outside the range of + // (min,max) values, then t is clamped. Note that each component + // of tuple[] is interpolated independently. + void InterpolateTuple(double t, double tuple[]); + +//BTX + // Description: + // Enums to control the type of interpolation to use. + enum {INTERPOLATION_TYPE_LINEAR=0, + INTERPOLATION_TYPE_SPLINE + }; +//ETX + + // Description: + // Specify which type of function to use for interpolation. By default + // spline interpolation (SetInterpolationFunctionToSpline()) is used + // (i.e., a Kochanek spline) and the InterpolatingSpline instance variable + // is used to birth the actual interpolation splines via a combination of + // NewInstance() and DeepCopy(). You may also choose to use linear + // interpolation by invoking SetInterpolationFunctionToLinear(). Note that + // changing the type of interpolation causes previously inserted data + // to be discarded. + void SetInterpolationType(int type); + vtkGetMacro(InterpolationType,int); + void SetInterpolationTypeToLinear() + {this->SetInterpolationType(INTERPOLATION_TYPE_LINEAR);} + void SetInterpolationTypeToSpline() + {this->SetInterpolationType(INTERPOLATION_TYPE_SPLINE);} + + // Description: + // If the InterpolationType is set to spline, then this method applies. By + // default Kochanek interpolation is used, but you can specify any instance + // of vtkSpline to use. Note that the actual interpolating splines are + // created by invoking NewInstance() followed by DeepCopy() on the + // interpolating spline specified here, for each tuple component to + // interpolate. + void SetInterpolatingSpline(vtkSpline*); + vtkGetObjectMacro(InterpolatingSpline,vtkSpline); + +protected: + vtkTupleInterpolator(); + virtual ~vtkTupleInterpolator(); + + // The number of components being interpolated + int NumberOfComponents; + + // Specify the type of interpolation to use + int InterpolationType; + + // This is the default 1D spline to use + vtkSpline *InterpolatingSpline; + + // Internal variables for interpolation functions + void InitializeInterpolation(); + vtkPiecewiseFunction **Linear; + vtkSpline **Spline; + + +private: + vtkTupleInterpolator(const vtkTupleInterpolator&); // Not implemented. + void operator=(const vtkTupleInterpolator&); // Not implemented. + +}; + +#endif diff --git a/Rendering/vtkUnstructuredGridVolumeZSweepMapper.cxx b/Rendering/vtkUnstructuredGridVolumeZSweepMapper.cxx new file mode 100644 index 0000000..ef5527b --- /dev/null +++ b/Rendering/vtkUnstructuredGridVolumeZSweepMapper.cxx @@ -0,0 +1,4212 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeZSweepMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridVolumeZSweepMapper.h" + +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" +#include "vtkTimerLog.h" +#include "vtkVolume.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRayCastImageDisplayHelper.h" +#include "vtkTransform.h" +#include "vtkCamera.h" +#include "vtkGenericCell.h" +#include "vtkPriorityQueue.h" +#include "vtkIdList.h" +#include "vtkVolumeProperty.h" +#include "vtkColorTransferFunction.h" +#include "vtkPiecewiseFunction.h" +#include "vtkUnstructuredGridPreIntegration.h" +#include "vtkUnstructuredGridPartialPreIntegration.h" +#include "vtkUnstructuredGridHomogeneousRayIntegrator.h" +#include "vtkDoubleArray.h" +#include "vtkDataArray.h" + +#include "vtkPolyData.h" +#include "vtkCellArray.h" +#include "vtkXMLPolyDataWriter.h" +#include "vtkPointData.h" + +#include +#include // memset() +#include +#include + +// do not remove the following line: +//#define BACK_TO_FRONT + +enum +{ + VTK_VALUES_X_INDEX=0, // world coordinate + VTK_VALUES_Y_INDEX, // world coordinate + VTK_VALUES_Z_INDEX, // world coordinate + VTK_VALUES_SCALAR_INDEX, + VTK_VALUES_SIZE // size of a value array +}; + +// Internal classes +//----------------------------------------------------------------------------- +// Store the result of the scan conversion at some pixel. +class vtkPixelListEntry +{ +public: + vtkPixelListEntry() + { + } + + void Init(double values[VTK_VALUES_SIZE], + double zView) + { + this->Zview=zView; + int i=0; + while(iValues[i]=values[i]; + ++i; + } + } + + + // Return the interpolated values at this pixel. + double *GetValues() { return this->Values; } + // Return the interpolated z coordinate in view space at this pixel. + double GetZview() const { return this->Zview; } + + vtkPixelListEntry *GetPrevious() { return this->Previous; } + vtkPixelListEntry *GetNext() { return this->Next; } + + void SetPrevious(vtkPixelListEntry *e) { this->Previous=e; } + void SetNext(vtkPixelListEntry *e) { this->Next=e; } + +protected: + double Values[VTK_VALUES_SIZE]; + double Zview; + + // List structure: both for the free block list (one-way) and any + // pixel list (two-way) + vtkPixelListEntry *Next; + // List structure: only for the pixel list (two-way) + vtkPixelListEntry *Previous; +private: + vtkPixelListEntry(const vtkPixelListEntry &other); + vtkPixelListEntry &operator=(const vtkPixelListEntry &other); +}; + +//----------------------------------------------------------------------------- +// Cache the projection of a vertex +class vtkVertexEntry +{ +public: + vtkVertexEntry() {} + + vtkVertexEntry(int screenX, + int screenY, + double xWorld, + double yWorld, + double zWorld, + double zView, + double scalar, + double invW) + :ScreenX(screenX),ScreenY(screenY),Zview(zView),InvW(invW) + { + this->Values[VTK_VALUES_X_INDEX]=xWorld; + this->Values[VTK_VALUES_Y_INDEX]=yWorld; + this->Values[VTK_VALUES_Z_INDEX]=zWorld; + this->Values[VTK_VALUES_SCALAR_INDEX]=scalar; + } + + void Set(int screenX, + int screenY, + double xWorld, + double yWorld, + double zWorld, + double zView, + double scalar, + double invW) + { + this->ScreenX=screenX; + this->ScreenY=screenY; + this->Zview=zView; + this->Values[VTK_VALUES_X_INDEX]=xWorld; + this->Values[VTK_VALUES_Y_INDEX]=yWorld; + this->Values[VTK_VALUES_Z_INDEX]=zWorld; + this->Values[VTK_VALUES_SCALAR_INDEX]=scalar; + this->InvW=invW; + } + + int GetScreenX() + { + return this->ScreenX; + } + int GetScreenY() + { + return this->ScreenY; + } + double *GetValues() + { + return this->Values; + } + double GetZview() + { + return this->Zview; + } + double GetInvW() + { + return this->InvW; + } + + vtkVertexEntry(const vtkVertexEntry &vtkNotUsed(other)) {} + +protected: + int ScreenX; + int ScreenY; + double Values[VTK_VALUES_SIZE]; + double Zview; + double InvW; + +private: + vtkVertexEntry &operator=(const vtkVertexEntry &other); +}; + + +//----------------------------------------------------------------------------- +// Abstract interface for an edge of a triangle in the screen space. +// Used during scan-conversion. +class vtkScreenEdge +{ +public: + // If the edge is a composite edge (top+bottom) switch to the bottom edge. + // Otherwise, do nothing. + virtual void OnBottom(int skipped, int y) + { + if(!skipped) + { + this->NextLine(y); + } + } + // Increment edge state to the next line. + virtual void NextLine(int y)=0; + // Increment edge state to the next deltaY line. + virtual void SkipLines(int deltaY, + int y)=0; + // Return the abscissa for the current line. + virtual int GetX()=0; + // Return the projected values for the current line. They are linearly + // incrementally interpolated in view space. The actual values are + // given by projectedValue/InvW. This is the way the values in world space + // are incrementally (not linearly) interpolated in view space. + virtual double *GetPValues()=0; + // Return 1/W, linearly interpolated in view space. + virtual double GetInvW()=0; + // Return Z in view coordinates, linearly interpolated in view space. + virtual double GetZview()=0; +protected: + // Destructor. + virtual ~vtkScreenEdge() {} +}; + +//----------------------------------------------------------------------------- +// Do an incremental traversing of an edge based on an Y increment. +enum +{ + VTK_CASE_VERTICAL=0, + VTK_CASE_MOSTLY_VERTICAL, + VTK_CASE_DIAGONAL, + VTK_CASE_HORIZONTAL_BEGIN, + VTK_CASE_HORIZONTAL_END, + VTK_CASE_HORIZONTAL_MS, // most significant pixel + VTK_CASE_VERTICAL_IN_TO_OUT, // with edge equation + VTK_CASE_VERTICAL_OUT_TO_IN, + VTK_CASE_HORIZONTAL_IN_TO_OUT, + VTK_CASE_HORIZONTAL_OUT_TO_IN +}; + +// We use an edge equation as described in: +// Juan Pineda +// A Parallel Algorithm for Polygon Rasterization +// In Computer Graphics, Volume 22, Number 4, August 1988 +// SIGGRAPH'88, Atlanta, August 1-5, 1988. +// pages 17--20. + +// or in: + +// Marc Olano and Trey Greer +// Triangle Scan Conversion using 2D Homogeneous Coordinates +// In 1997 SIGGRAPH/Eurographics Workshop +// pages 89--95. +// http://www.cs.unc.edu/~olano/papers/2dh-tri/2dh-tri.pdf + +#define MOST_SIGNIFICANT +#define EDGE_EQUATION +#define HORI_EDGE_EQUATION +//#define STRICTLY_INSIDE + +class vtkSimpleScreenEdge + : public vtkScreenEdge +{ +public: + // Initialize the edge by the vertices v0 and v2 (ordered in y) + // `onRight' is true if the edge in on the right side of the triangle. + void Init(vtkVertexEntry *v0, + vtkVertexEntry *v2, + int dx20, + int dy20, + int onRight) + { + double z0=v0->GetZview(); + double z2=v2->GetZview(); + + double invW0=v0->GetInvW(); + double invW2=v2->GetInvW(); + + double pv0[VTK_VALUES_SIZE]; + double pv2[VTK_VALUES_SIZE]; + int i=0; + while(iGetValues()[i]*invW0; + this->PValues[i]=pv0[i]; + pv2[i]=v2->GetValues()[i]*invW2; + ++i; + } + + this->InvW=invW0; + this->Zview=z0; + + int x0=v0->GetScreenX(); + int x2=v2->GetScreenX(); + + this->X0=x0; + this->X2=x2; + + this->V2=v2; + + this->X=x0; + + if(dx20==0) + { + this->Case=VTK_CASE_VERTICAL; + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; + } + else + { + if(dx20>0) + { + this->IncX=1; + if(dx20>dy20) + { + // Mostly horizontal +#ifdef HORI_EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_HORIZONTAL_IN_TO_OUT; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_OUT_TO_IN; + } + this->Error=0; + this->SDy=dy20; + this->XStep=dx20/dy20; // integral division + this->Dx=dx20-this->XStep*this->SDy; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else +#ifdef MOST_SIGNIFICANT + this->Case=VTK_CASE_HORIZONTAL_MS; + this->XStep=dx20/dy20; // integral division + this->Dy=dy20; + this->Dy2=dy20<<1; // *2 + this->Error=0; + this->ErrorStep=(dx20-this->XStep*dy20)<<1; // 2*r, dx=q*dy+r, rDpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=this->DinvW*this->XStep; + this->ZStep=this->Dz*this->XStep; + +#else + if(!onRight) + { + this->Case=VTK_CASE_HORIZONTAL_BEGIN; + this->First=1; + this->Dy2=dy20<<1; // *2 + this->Dx2=dx20<<1; // *2 + this->Error=dx20; + + this->XStep=dx20/dy20; // integral division + + this->ErrorStep=this->XStep*this->Dy2; + + double invDx20=1.0/dx20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=this->DinvW*this->XStep; + this->ZStep=this->Dz*this->XStep; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_END; + + this->InvW2=invW2; + i=0; + while(iPValues2[i]=pv2[i]; + ++i; + } + + this->Zview2=z2; + + this->Dy2=dy20<<1; // *2 + this->Dx2=dx20<<1; // *2 + this->Error=dx20; + this->XStep=dx20/dy20; + this->ErrorStep=this->XStep*this->Dy2; + + double invDx20=1.0/dx20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=this->DinvW*this->XStep; + this->ZStep=this->Dz*this->XStep; + + while(this->ErrorDx2) + { + this->X+=this->IncX; + this->InvW+= this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + this->X-=this->IncX; + this->InvW-= this->DinvW; + i=0; + while(iPValues[i]-=this->Dpv[i]; + ++i; + } + this->Zview-=this->Dz; + } +#endif +#endif // EDGE_EQUATION + } + else + { + if(dx20==dy20) + { + this->Case=VTK_CASE_DIAGONAL; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; + } + else + { +#ifdef EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_VERTICAL_IN_TO_OUT; + } + else + { + this->Case=VTK_CASE_VERTICAL_OUT_TO_IN; + } + this->Error=0; + this->SDy=dy20; + this->Dx=dx20; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else + this->Case=VTK_CASE_MOSTLY_VERTICAL; + this->Dx2=dx20<<1; // *2 + this->Dy2=dy20<<1; // *2 + this->Error=dy20; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#endif + } + } + } + else + { + this->IncX=-1; + if(-dx20>dy20) + { + // Mostly horizontal +#ifdef HORI_EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_HORIZONTAL_OUT_TO_IN; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_IN_TO_OUT; + } + this->Error=0; + this->SDy=-dy20; + this->XStep=dx20/dy20; // integral division + this->Dx=dx20+this->XStep*this->SDy; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else +#ifdef MOST_SIGNIFICANT + this->Case=VTK_CASE_HORIZONTAL_MS; + this->XStep=dx20/dy20; // integral division + this->Dy=dy20; + this->Dy2=dy20<<1; // *2 + this->Error=0; + this->ErrorStep=(dx20+this->XStep*dy20)<<1; // 2*r, dx=q*dy+r, rDpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=-this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=-this->DinvW*this->XStep; + this->ZStep=-this->Dz*this->XStep; + + +#else + if(onRight) + { + this->Case=VTK_CASE_HORIZONTAL_BEGIN; + this->First=1; + this->Dy2=dy20<<1; // *2 + this->Dx2=(-dx20)<<1; // *2 + this->Error=-dx20; + this->XStep=dx20/dy20; + this->ErrorStep=-this->XStep*this->Dy2; + + double invDx20=-1.0/dx20; + + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=-this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=-this->DinvW*this->XStep; + this->ZStep=-this->Dz*this->XStep; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_END; + + this->InvW2=invW2; + i=0; + while(iPValues2[i]=pv2[i]; + ++i; + } + this->Zview2=z2; + + this->Dy2=dy20<<1; // *2 + this->Dx2=(-dx20)<<1; // *2 + this->Error=-dx20; + this->XStep=dx20/dy20; + this->ErrorStep=-this->XStep*this->Dy2; + + double invDx20=-1.0/dx20; + + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=-this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=-this->DinvW*this->XStep; + this->ZStep=-this->Dz*this->XStep; + + while(this->ErrorDx2) + { + this->X+=this->IncX; + this->InvW+= this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + this->X-=this->IncX; + + this->InvW-= this->DinvW; + i=0; + while(iPValues[i]-=this->Dpv[i]; + ++i; + } + this->Zview-=this->Dz; + } +#endif +#endif // EDGE_EQUATION + } + else + { + if(dx20==-dy20) + { + this->Case=VTK_CASE_DIAGONAL; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; + } + else + { +#ifdef EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_VERTICAL_OUT_TO_IN; + } + else + { + this->Case=VTK_CASE_VERTICAL_IN_TO_OUT; + } + this->Error=0; + this->SDy=-dy20; + this->Dx=dx20; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else + this->Case=VTK_CASE_MOSTLY_VERTICAL; + this->Dx2=(-dx20)<<1; // *2 + this->Dy2=dy20<<1; // *2 + this->Error=dy20; + + double invDy20=1.0/dy20; + i=0; + while(iDpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#endif + } + } + } + } + } + + // Check that the current abscissa is in the range given by the vertices. + int ValidXRange() + { + if(this->X0<=this->X2) + { + return (this->X>=this->X0) && (this->X<=this->X2); + } + else + { + return (this->X>=this->X2) && (this->X<=this->X0); + } + } + int GetX() + { + // assert("pre: valid_range" && ValidXRange() ); + return this->X; + } + double GetInvW() { return this->InvW; } + double *GetPValues() { return this->PValues; } + double GetZview() { return this->Zview; } + + void NextLine(int y) + { + int i; + switch(this->Case) + { + case VTK_CASE_VERTICAL: + // nothing to do with X + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_DIAGONAL: + // X + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_MOSTLY_VERTICAL: + // X + this->Error+=this->Dx2; + if(this->Error>=this->Dy2) + { + this->Error-=this->Dy2; + this->X+=this->IncX; + } + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_VERTICAL_OUT_TO_IN: + this->Error-=this->Dx; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) +#else + if(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // we are no more on the left side +#else + if(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE +// assert("check: negative_equation" && this->Error>0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_VERTICAL_IN_TO_OUT: + this->Error+=this->SDy-this->Dx; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) // out: too far on left +#else + if(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // out: too far on right +#else + if(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: negative_equation" && this->Error<0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + + case VTK_CASE_HORIZONTAL_OUT_TO_IN: + this->Error-=this->Dx; + this->X+=this->XStep; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) // we are no more on the right side +#else + if(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // we are no more on the left side +#else + if(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: negative_equation" && this->Error<0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + + case VTK_CASE_HORIZONTAL_IN_TO_OUT: + this->Error+=this->SDy-this->Dx; + this->X+=this->XStep; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) // out: too far on left +#else + if(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE +// assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // out: too far on right +#else + if(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE +// assert("check: negative_equation" && this->Error<0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + + case VTK_CASE_HORIZONTAL_BEGIN: + if(this->First) + { + this->First=0; + } + else + { + this->X+=this->XStep; + + this->InvW+=this->InvWStep; + i=0; + while(iPValues[i]+=this->PValuesStep[i]; + ++i; + } + this->Zview+=this->ZStep; + this->Error+=this->ErrorStep; + } + while(this->ErrorDx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + break; + case VTK_CASE_HORIZONTAL_END: + if(y==this->V2->GetScreenY()) + { + this->X=this->V2->GetScreenX(); + i=0; + while(iPValues[i]=this->PValues2[i]; + ++i; + } + this->Zview=this->Zview2; + this->InvW=this->InvW2; + } + else + { + this->X+=this->XStep; + + this->InvW+=this->InvWStep; + i=0; + while(iPValues[i]+=this->PValuesStep[i]; + ++i; + } + this->Zview+=this->ZStep; + + this->Error+=this->ErrorStep; + + while(this->ErrorDx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + } + break; + case VTK_CASE_HORIZONTAL_MS: + this->Error+=this->ErrorStep; + if(this->Error>=this->Dy) + { + this->Error-=this->Dy2; + this->X+=this->XStep+this->IncX; + this->InvW+=this->InvWStep+this->DinvW; + i=0; + while(iPValues[i]+=this->PValuesStep[i]+this->Dpv[i]; + ++i; + } + this->Zview+=this->ZStep+this->Dz; + } + else + { + this->X+=this->XStep; + this->InvW+=this->InvWStep; + i=0; + while(iPValues[i]+=this->PValuesStep[i]; + ++i; + } + this->Zview+=this->ZStep; + } + break; + } + } + + void SkipLines(int deltaY, + int y) + { + if(deltaY==1) + { + this->NextLine(0); + return; + } + + int firstDeltaY; + int i; + switch(this->Case) + { + case VTK_CASE_VERTICAL: + // nothing to do with X + this->InvW+=this->DinvW*deltaY; + i=0; + while(iPValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_DIAGONAL: + // X + this->X+=this->IncX*deltaY; + this->InvW+=this->DinvW*deltaY; + i=0; + while(iPValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_MOSTLY_VERTICAL: + // X + this->Error+=this->Dx2*deltaY; + while(this->Error>=this->Dy2) + { + this->Error-=this->Dy2; + this->X+=this->IncX; + } + this->InvW+=this->DinvW*deltaY; + i=0; + while(iPValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_VERTICAL_OUT_TO_IN: + this->Error-=this->Dx*deltaY; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // we are no more on the right side +#else + while(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // we are no more on the left side +#else + while(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(iPValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_VERTICAL_IN_TO_OUT: + this->Error+=(this->SDy-this->Dx)*deltaY; + this->X+=this->IncX*deltaY; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // out: too far on left +#else + while(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // out: too far on right +#else + while(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(iPValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + + case VTK_CASE_HORIZONTAL_OUT_TO_IN: + this->Error-=this->Dx*deltaY; + this->X+=this->XStep*deltaY; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // we are no more on the right side +#else + while(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // we are no more on the left side +#else + while(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(iPValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_HORIZONTAL_IN_TO_OUT: + this->Error+=(this->SDy-this->Dx)*deltaY; + this->X+=(this->XStep+this->IncX)*deltaY; +// this->X+=this->IncX*deltaY; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // out: too far on left +#else + while(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // out: too far on right +#else + while(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(iPValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + + case VTK_CASE_HORIZONTAL_BEGIN: + + if(this->First) + { + this->First=0; + firstDeltaY=deltaY-1; + } + else + { + firstDeltaY=deltaY; + } + + this->X+=this->XStep*firstDeltaY; + + this->InvW+=this->InvWStep*firstDeltaY; + i=0; + while(iPValues[i]+=this->PValuesStep[i]*firstDeltaY; + ++i; + } + this->Zview+=this->ZStep*firstDeltaY; + this->Error+=this->ErrorStep*firstDeltaY; + + while(this->ErrorDx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + break; + case VTK_CASE_HORIZONTAL_END: + if(y==this->V2->GetScreenY()) + { + this->X=this->V2->GetScreenX(); + i=0; + while(iPValues[i]=this->PValues2[i]; + ++i; + } + this->Zview=this->Zview2; + this->InvW=this->InvW2; + } + else + { + this->X+=this->XStep*deltaY; + + this->InvW+=this->InvWStep*deltaY; + i=0; + while(iPValues[i]+=this->PValuesStep[i]*deltaY; + ++i; + } + this->Zview+=this->ZStep*deltaY; + + this->Error+=this->ErrorStep*deltaY; + + while(this->ErrorDx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + } + break; + case VTK_CASE_HORIZONTAL_MS: + this->Error+=this->ErrorStep*deltaY; + this->X+=this->XStep*deltaY; + this->InvW+=this->InvWStep*deltaY; + i=0; + while(iPValues[i]+=this->PValuesStep[i]*deltaY; + ++i; + } + this->Zview+=this->ZStep*deltaY; + + while(this->Error>=this->Dy) + { + this->Error-=this->Dy2; + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(iPValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + } + break; + } + } + +protected: + int Case; + int Error; // error to the mid-point + int Dx2; // 2*dx + int Dy2; // 2*dy + int First; // use only with VTK_CASE_HORIZONTAL_BEGIN case + int XStep; // dx/dy + int ErrorStep; // XStep*Dy2 + + vtkVertexEntry *V2; + + int IncX; // -1 or 1 + + int X; // Current abscissa + + int X0; // for debugging + int X2; // for debugging + + // Slope of 1/w + double DinvW; + // Current 1/W + double InvW; + // DinvW*XStep + double InvWStep; + // 1/W at the end vertex + double InvW2; + + // Slope of the z coordinate in view space + double Dz; + // current z in view space + double Zview; + // Dz*XStep + double ZStep; + // z coordinate in view space at the end vertex + double Zview2; + + // Slope of each projected values on the edge + double Dpv[VTK_VALUES_SIZE]; + + + // Current projected values + double PValues[VTK_VALUES_SIZE]; + // Dpv*XStep + double PValuesStep[VTK_VALUES_SIZE]; + // Values at the end vertex. + double PValues2[VTK_VALUES_SIZE]; + + int Dy; // VTK_HORIZONTAL_MS + int SDy; // VTK_VERTICAL_LEFT/RIGHT + int Dx; // VTK_VERTICAL_LEFT/RIGHT +}; + +//----------------------------------------------------------------------------- +// During rasterization of a triangle, there is always one side with two +// edges and the other side with a single edge. +// This class manages the side with the two edges called top and bottom edges. +class vtkDoubleScreenEdge + :public vtkScreenEdge +{ +public: + void Init(vtkVertexEntry *v0, + vtkVertexEntry *v1, + vtkVertexEntry *v2, + int dx10, + int dy10, + int onRight) + { + this->Current=0; + if(dy10!=0) + { + this->Top.Init(v0,v1,dx10,dy10,onRight); + this->Current=&this->Top; + } + + int dx21=v2->GetScreenX()-v1->GetScreenX(); + int dy21=v2->GetScreenY()-v1->GetScreenY(); + + if(dy21!=0) + { + this->Bottom.Init(v1,v2,dx21,dy21,onRight); + if(this->Current==0) + { + this->Current=&this->Bottom; + } + } + } + + int GetX() { return this->Current->GetX(); } + double GetInvW() { return this->Current->GetInvW(); } + double GetZview() { return this->Current->GetZview(); } + double *GetPValues() { return this->Current->GetPValues(); } + + void OnBottom(int skipped, int y) + { + this->Current=&this->Bottom; + this->Current->OnBottom(skipped,y); + } + + void NextLine(int y) + { + this->Current->NextLine(y); + } + void SkipLines(int deltaY, + int y) + { + this->Current->SkipLines(deltaY,y); + } + +protected: + vtkSimpleScreenEdge Top; + vtkSimpleScreenEdge Bottom; + vtkScreenEdge *Current; +}; + +//----------------------------------------------------------------------------- +// Horizontal span between two points of two edges. +// Used during scan-conversion. +// It interpolates the values along the span. + +class vtkSpan +{ +public: + // Initialize the span from the left abcissa x0 and the right absissa x1 and + // from 1/W, the projected values and the z coordinate in view space at + // thoses points. Set the current state to the left point. + void Init(int x0, + double invW0, + double pValues0[VTK_VALUES_SIZE], // projected values + double zView0, + int x1, + double invW1, + double pValues1[VTK_VALUES_SIZE], // projected values + double zView1) + { +// assert("pre: dx>=0" && x1-x0>=0); + // x0=x1: the span is just a point + + int i; + if(x0!=x1) + { + + double invDx10=1.0/(x1-x0); + i=0; + while(iDpv[i]=(pValues1[i]-pValues0[i])*invDx10; + ++i; + } + this->DinvW=(invW1-invW0)*invDx10; + this->Dz=(zView1-zView0)*invDx10; + } + else + { + i=0; + while(iDpv[i]=0; + ++i; + } + this->DinvW=0; + this->Dz=0; + } + + this->Zview=zView0; + this->InvW=invW0; + i=0; + double w=1/this->InvW; + while(iPValues[i]=pValues0[i]; + this->Values[i]=this->PValues[i]*w; + ++i; + } + this->X=x0; + this->X1=x1; + } + + // Is the current state after the right point? + int IsAtEnd() + { + return this->X>this->X1; + } + + // Current abscissa. + int GetX() { return this->X; } + // Current values. + double *GetValues() { return this->Values; } + // Current z coordinate in view space. + double GetZview() { return this->Zview; } + + // Go the next abscissa from left to right. + void NextPixel() + { + ++this->X; + + this->InvW+=this->DinvW; + int i=0; + double w=1/this->InvW; + while(iPValues[i]+=this->Dpv[i]; + this->Values[i]=this->PValues[i]*w; + ++i; + } + this->Zview+=this->Dz; + } + +protected: + int X1; // abscissa at the right point. + + int X; // current abscissa + + // Slope of 1/w + double DinvW; + // current 1/W + double InvW; + + // Slope of the z coordinate in view space + double Dz; + // current z coordinate in view space + double Zview; + + // Slope of each projected values on the span + double Dpv[VTK_VALUES_SIZE]; + // Current projected values + double PValues[VTK_VALUES_SIZE]; + + // Current values: Values=PValues/InvW + double Values[VTK_VALUES_SIZE]; +}; + + +// Pimpl (i.e. private implementation) idiom + +//typedef vtkstd::list vtkPixelList; + +class vtkPixelListEntryBlock +{ +public: + vtkPixelListEntryBlock(vtkIdType size) + { + assert("pre: positive_size" && size>0); + this->Size=size; + this->Next=0; + this->Array=new vtkPixelListEntry[size]; + this->Last=this->Array+size-1; + // link each entry to the next one + vtkPixelListEntry *p; + vtkPixelListEntry *q; + p=this->Array; + q=p+1; + vtkIdType i=1; + while(iSetNext(q); + ++i; + p=q; + ++q; + } + p->SetNext(0); + } + ~vtkPixelListEntryBlock() + { + delete[] this->Array; + } + vtkIdType GetSize() { return this->Size; } + vtkPixelListEntryBlock *GetNext() { return this->Next; } + vtkPixelListEntry *GetFirst() { return this->Array; } + vtkPixelListEntry *GetLast() { return this->Last; } + void SetNext(vtkPixelListEntryBlock *other) { this->Next=other; } + +protected: + vtkIdType Size; + vtkPixelListEntryBlock *Next; + vtkPixelListEntry *Array; + vtkPixelListEntry *Last; +}; + +const vtkIdType VTK_PIXEL_BLOCK_SIZE=64; + +class vtkPixelListEntryMemory +{ +public: + vtkPixelListEntryMemory() + { + this->FirstBlock=new vtkPixelListEntryBlock(VTK_PIXEL_BLOCK_SIZE); + this->FirstFreeElement=this->FirstBlock->GetFirst(); + this->Size=VTK_PIXEL_BLOCK_SIZE; + } + ~vtkPixelListEntryMemory() + { + vtkPixelListEntryBlock *p=this->FirstBlock; + vtkPixelListEntryBlock *q; + while(p!=0) + { + q=p->GetNext(); + delete p; + p=q; + } + } + vtkPixelListEntry *AllocateEntry() + { + if(this->FirstFreeElement==0) + { + this->AllocateBlock(this->Size<<1); +// this->AllocateBlock(BLOCK_SIZE); + } + vtkPixelListEntry *result=this->FirstFreeElement; + this->FirstFreeElement=result->GetNext(); + assert("post: result_exists" && result!=0); + return result; + } + void FreeEntry(vtkPixelListEntry *e) + { + assert("pre: e_exists" && e!=0); + + // the following line works even if this->FirstFreeElement==0 + e->SetNext(this->FirstFreeElement); + this->FirstFreeElement=e; + } + void FreeSubList(vtkPixelListEntry *first, + vtkPixelListEntry *last) + { + assert("pre: first_exists" && first!=0); + assert("pre: last_exists" && last!=0); + // pre: first==last can be true + // the following line works even if this->FirstFreeElement==0 + last->SetNext(this->FirstFreeElement); + this->FirstFreeElement=first; + } +protected: + + void AllocateBlock(vtkIdType size) + { + assert("pre: positive_size" && size>0); + vtkPixelListEntryBlock *b=new vtkPixelListEntryBlock(size); + this->Size+=size; + // Update the block linked list: starts with the new block + b->SetNext(this->FirstBlock); + this->FirstBlock=b; + + // Update the free element linked list. + // It works even if this->FirstFreeElement==0 + b->GetLast()->SetNext(this->FirstFreeElement); + this->FirstFreeElement=b->GetFirst(); + } + + vtkPixelListEntryBlock *FirstBlock; + vtkPixelListEntry *FirstFreeElement; + vtkIdType Size; // overall size, in number of elements, not in bytes +}; + + +class vtkPixelList +{ +public: + vtkPixelList() + { + this->Size=0; + } + vtkPixelListEntry *GetFirst() + { + assert("pre: not_empty" && this->Size>0); + return this->First; + } + vtkIdType GetSize() { return this->Size; } + + void AddAndSort(vtkPixelListEntry *p) + { + assert("pre: p_exists" && p!=0); + if(this->Size==0) + { + p->SetPrevious(0); + p->SetNext(0); + this->First=p; + this->Last=p; + } + else + { + vtkPixelListEntry *it=this->Last; + int sorted=0; + double z=p->GetZview(); + while(!sorted && it!=0) + { +#ifdef BACK_TO_FRONT + sorted=it->GetZview()>=z; +#else + sorted=it->GetZview()<=z; +#endif + if(!sorted) + { + it=it->GetPrevious(); + } + } + if(it==0) // first element + { + p->SetPrevious(0); + p->SetNext(this->First); + // this->First==0 is handled by case size==0 + this->First->SetPrevious(p); + this->First=p; + } + else + { + if(it->GetNext()==0) // last element + { + it->SetNext(p); + p->SetPrevious(it); + p->SetNext(0); + this->Last=p; + } + else // general case + { + vtkPixelListEntry *q=it->GetNext(); + q->SetPrevious(p); + p->SetNext(q); + p->SetPrevious(it); + it->SetNext(p); + } + } + } + ++this->Size; + } + + // the return pointer is used by the memory manager. + void RemoveFirst(vtkPixelListEntryMemory *mm) + { + assert("pre: not_empty" && this->Size>0); + assert("pre: mm_exists" && mm!=0); + + vtkPixelListEntry *p=this->First; + if(this->Size>1) + { + this->First=p->GetNext(); + this->First->SetPrevious(0); + } + --this->Size; + mm->FreeEntry(p); + } + + // the return pointer on the first element is used by the memory manager. + void Clear(vtkPixelListEntryMemory *mm) + { + assert("pre: mm_exists" && mm!=0); + if(this->Size>0) + { + // it works even if first==last + mm->FreeSubList(this->First,this->Last); + this->Size=0; + } + } + +protected: + vtkIdType Size; + vtkPixelListEntry *First; + vtkPixelListEntry *Last; +}; + +//----------------------------------------------------------------------------- +// Store the pixel lists for all the frame. +class vtkPixelListFrame +{ +public: + typedef vtkstd::vector VectorType; + + vtkPixelListFrame(int size) + :Vector(size) + { + } + + // Return width*height + vtkIdType GetSize() { return this->Vector.size(); } + + // Return the size of the list at pixel `i'. + vtkIdType GetListSize(int i) + { + assert("pre: valid_i" && i>=0 && iGetSize()); + return this->Vector[i].GetSize(); + } + + // Add a value the pixel list of pixel `i' and sort it in the list. + void AddAndSort(int i, + vtkPixelListEntry *pixelEntry) + { + assert("pre: valid_i" && i>=0 && iGetSize()); + assert("pre: pixelEntry_exists" && pixelEntry!=0); + + this->Vector[i].AddAndSort(pixelEntry); + } + + // Return the first entry for pixel `i'. + vtkPixelListEntry *GetFront(int i) + { + assert("pre: valid_i" && i>=0 && iGetSize()); + assert("pre: not_empty" && this->GetListSize(i)>0); + return this->Vector[i].GetFirst(); + } + + // Remove the first entry for pixel `i'. + void PopFront(int i, + vtkPixelListEntryMemory *mm) + { + assert("pre: valid_i" && i>=0 && iGetSize()); + assert("pre: not_empty" && this->GetListSize(i)>0); + assert("pre: mm_exists" && mm!=0); + this->Vector[i].RemoveFirst(mm); + } + + // Return the begin iterator for pixel `i'. + vtkPixelListEntry *GetFirst(int i) + { + assert("pre: valid_i" && i>=0 && iGetSize()); + return this->Vector[i].GetFirst(); + } +#if 0 + // Return the end iterator for pixel `i'. + vtkstd::list::iterator GetEndIterator(int i) + { + assert("pre: valid_i" && i>=0 && iGetSize()); + return this->Vector[i].end(); + } +#endif + // Clear the list of each pixel of the frame. + void Clean(vtkPixelListEntryMemory *mm) + { + assert("pre: mm_exists" && mm!=0); + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(iClear(mm); + ++i; + } + } + + // Destructor. + ~vtkPixelListFrame() + { +#if 0 + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(iempty()) + { + delete l->front(); + l->pop_front(); + } + ++i; + } +#endif + } + + vtkPixelList *GetList(int i) + { + assert("pre: valid_i" && i>=0 && iGetSize()); + return &(this->Vector[i]); + } + +protected: + VectorType Vector; + + // the STL specification claims that + // size() on a std: :list is permitted to be O(n)!!!! +// vtkstd::vector Sizes; + +// vtkstd::list::iterator It; +// vtkstd::list::iterator PreviousIt; +// vtkstd::list::iterator ItEnd; +}; + +//----------------------------------------------------------------------------- +// Store a triangle face. Ids are in increasing order. Orientation does not +// matter for the algorithm. +class vtkFace +{ +public: + // Initialization from face ids in increasing order. + vtkFace(vtkIdType faceIds[3]) + { + assert("pre: ordered ids" && faceIds[0]FaceIds[0]=faceIds[0]; + this->FaceIds[1]=faceIds[1]; + this->FaceIds[2]=faceIds[2]; + this->Count=0; + } + + // Return the 3 face ids. + vtkIdType *GetFaceIds() { return this->FaceIds; } + + // Are `this' and faceIds equal? + int IsEqual(vtkIdType faceIds[3]) + { + return (this->FaceIds[0]==faceIds[0])&&(this->FaceIds[1]==faceIds[1]) + &&(this->FaceIds[2]==faceIds[2]); + } + + void Ref() { ++this->Count; } + void Unref() + { + --this->Count; + if(this->Count==0) + { + delete this; + } + } + + int GetRendered() { return this->Rendered; } + void SetRendered(int value) { this->Rendered=value; } + +protected: + vtkIdType FaceIds[3]; + int Count; + int Rendered; + +private: + vtkFace(); // not implemented + vtkFace(const vtkFace &other); // not implemented + vtkFace &operator=(const vtkFace &other); // not implemented +}; + +//----------------------------------------------------------------------------- +// For each vertex, store the list of faces incident on this vertex. +// It is view independent. +class vtkUseSet +{ +public: + typedef vtkstd::vector *> VectorType; + VectorType Vector; + + vtkstd::list AllFaces; // to set up rendering to false. + + // Initialize with the number of vertices. + vtkUseSet(int size) + :Vector(size) + { + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(iVector[i]=0; + ++i; + } + } + + // Destructor. + ~vtkUseSet() + { + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(iVector[i]!=0) + { + while(!this->Vector[i]->empty()) + { + (*this->Vector[i]->begin())->Unref(); + this->Vector[i]->pop_front(); + } + delete this->Vector[i]; + } + ++i; + } + while(!this->AllFaces.empty()) + { + (*this->AllFaces.begin())->Unref(); + this->AllFaces.pop_front(); + } + } + + // For each vertex, clear the list of faces incident to it. + void Clear() + { + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(iVector[i]!=0) + { + while(!this->Vector[i]->empty()) + { + (*this->Vector[i]->begin())->Unref(); + this->Vector[i]->pop_front(); + } + delete this->Vector[i]; + this->Vector[i]=0; + } + ++i; + } + while(!this->AllFaces.empty()) + { + (*this->AllFaces.begin())->Unref(); + this->AllFaces.pop_front(); + } + } + + // Add face to each vertex only if the useset does not have the face yet. + void AddFace(vtkIdType faceIds[3]) + { + assert("pre: ordered ids" && faceIds[0]HasFace(faceIds)) + { + vtkFace *f=new vtkFace(faceIds); + this->AllFaces.push_back(f); + f->Ref(); + // All the vertices of this face need to be fed + int i=0; + while(i<3) + { + vtkstd::list *p=this->Vector[faceIds[i]]; + if(p==0) + { + p=new vtkstd::list; + this->Vector[faceIds[i]]=p; + } + p->push_back(f); + f->Ref(); + ++i; + } + } + } + + void SetNotRendered() + { + vtkstd::list::iterator it; + vtkstd::list::iterator end; + it=this->AllFaces.begin(); + end=this->AllFaces.end(); + while(it!=end) + { + (*it)->SetRendered(0); + ++it; + } + } +protected: + // Does the use set of vertex faceIds[0] have face faceIds? + int HasFace(vtkIdType faceIds[3]) + { + vtkstd::list *useSet=this->Vector[faceIds[0]]; + int result=0; + + if(useSet!=0) + { + this->It=(*useSet).begin(); + this->ItEnd=(*useSet).end(); + while(!result && this->It!=this->ItEnd) + { + result=(*this->It)->IsEqual(faceIds); + ++this->It; + } + } + return result; + } + + + // Used in HasFace() + vtkstd::list::iterator It; + vtkstd::list::iterator ItEnd; +}; + +// For each vertex, store its projection. It is view-dependent. +class vtkVertices +{ +public: + typedef vtkstd::vector VectorType; + VectorType Vector; + + // Initialize with the number of vertices. + vtkVertices(int size) + :Vector(size) + { + } +}; + +//----------------------------------------------------------------------------- +// Implementation of the public class. + +vtkCxxRevisionMacro(vtkUnstructuredGridVolumeZSweepMapper, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkUnstructuredGridVolumeZSweepMapper); + +vtkCxxSetObjectMacro(vtkUnstructuredGridVolumeZSweepMapper, RayIntegrator, + vtkUnstructuredGridVolumeRayIntegrator); + + +//----------------------------------------------------------------------------- +// Description: +// Set MaxPixelListSize to 32. +vtkUnstructuredGridVolumeZSweepMapper::vtkUnstructuredGridVolumeZSweepMapper() +{ + this->MaxPixelListSize=64; // default value. + + this->ImageSampleDistance = 1.0; + this->MinimumImageSampleDistance = 1.0; + this->MaximumImageSampleDistance = 10.0; + this->AutoAdjustSampleDistances = 1; + + this->ImageMemorySize[0] = 0; + this->ImageMemorySize[1] = 0; + + this->Image = NULL; + this->RealRGBAImage=0; + + this->RenderTimeTable = NULL; + this->RenderVolumeTable = NULL; + this->RenderRendererTable = NULL; + this->RenderTableSize = 0; + this->RenderTableEntries = 0; + + this->ZBuffer = NULL; + this->ZBufferSize[0] = 0; + this->ZBufferSize[1] = 0; + this->ZBufferOrigin[0] = 0; + this->ZBufferOrigin[1] = 0; + + this->IntermixIntersectingGeometry = 1; + + this->ImageDisplayHelper = vtkRayCastImageDisplayHelper::New(); + + this->ScalarMode = VTK_SCALAR_MODE_DEFAULT; + this->ArrayName = new char[1]; + this->ArrayName[0] = '\0'; + this->ArrayId = -1; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; + + this->PixelListFrame=0; + + this->Cell=vtkGenericCell::New(); + + this->EventList=vtkPriorityQueue::New(); + + this->UseSet=0; + this->Vertices=0; + + this->PerspectiveTransform = vtkTransform::New(); + this->PerspectiveMatrix = vtkMatrix4x4::New(); + + this->SimpleEdge=new vtkSimpleScreenEdge; + this->DoubleEdge=new vtkDoubleScreenEdge; + + this->Span=new vtkSpan; + + this->RayIntegrator = NULL; + this->RealRayIntegrator = NULL; + + this->IntersectionLengths=vtkDoubleArray::New(); + this->IntersectionLengths->SetNumberOfValues(1); + this->NearIntersections=vtkDoubleArray::New(); + this->NearIntersections->SetNumberOfValues(1); + this->FarIntersections=vtkDoubleArray::New(); + this->FarIntersections->SetNumberOfValues(1); + + this->MemoryManager=0; +} + +//----------------------------------------------------------------------------- +vtkUnstructuredGridVolumeZSweepMapper::~vtkUnstructuredGridVolumeZSweepMapper() +{ + if(this->MemoryManager!=0) + { + delete this->MemoryManager; + } + if(this->PixelListFrame!=0) + { + delete this->PixelListFrame; + } + this->Cell->Delete(); + this->EventList->Delete(); + + this->ImageDisplayHelper->Delete(); + + delete[] this->ArrayName; + + if(this->UseSet!=0) + { + delete this->UseSet; + } + + if(this->Vertices!=0) + { + delete this->Vertices; + } + + this->PerspectiveTransform->Delete(); + this->PerspectiveMatrix->Delete(); + + delete this->SimpleEdge; + delete this->DoubleEdge; + delete this->Span; + + if ( this->Image ) + { + delete [] this->Image; + delete [] this->RealRGBAImage; + } + + if ( this->RenderTableSize ) + { + delete [] this->RenderTimeTable; + delete [] this->RenderVolumeTable; + delete [] this->RenderRendererTable; + } + + this->SetRayIntegrator(NULL); + if (this->RealRayIntegrator) + { + this->RealRayIntegrator->UnRegister(this); + } + + this->IntersectionLengths->Delete(); + this->NearIntersections->Delete(); + this->FarIntersections->Delete(); +} + +//----------------------------------------------------------------------------- +float vtkUnstructuredGridVolumeZSweepMapper::RetrieveRenderTime( + vtkRenderer *ren, + vtkVolume *vol ) +{ + int i; + + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + return this->RenderTimeTable[i]; + } + } + + return 0.0; +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::StoreRenderTime( + vtkRenderer *ren, + vtkVolume *vol, + float time ) +{ + int i; + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + this->RenderTimeTable[i] = time; + return; + } + } + + + // Need to increase size + if ( this->RenderTableEntries >= this->RenderTableSize ) + { + if ( this->RenderTableSize == 0 ) + { + this->RenderTableSize = 10; + } + else + { + this->RenderTableSize *= 2; + } + + float *oldTimePtr = this->RenderTimeTable; + vtkVolume **oldVolumePtr = this->RenderVolumeTable; + vtkRenderer **oldRendererPtr = this->RenderRendererTable; + + this->RenderTimeTable = new float [this->RenderTableSize]; + this->RenderVolumeTable = new vtkVolume *[this->RenderTableSize]; + this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize]; + + for (i = 0; i < this->RenderTableEntries; i++ ) + { + this->RenderTimeTable[i] = oldTimePtr[i]; + this->RenderVolumeTable[i] = oldVolumePtr[i]; + this->RenderRendererTable[i] = oldRendererPtr[i]; + } + + delete [] oldTimePtr; + delete [] oldVolumePtr; + delete [] oldRendererPtr; + } + + this->RenderTimeTable[this->RenderTableEntries] = time; + this->RenderVolumeTable[this->RenderTableEntries] = vol; + this->RenderRendererTable[this->RenderTableEntries] = ren; + + this->RenderTableEntries++; +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::SelectScalarArray(int arrayNum) +{ + if ( (this->ArrayId == arrayNum) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) + { + return; + } + this->Modified(); + + this->ArrayId = arrayNum; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::SelectScalarArray( + const char *arrayName) +{ + if ( !arrayName + || ( (strcmp(this->ArrayName, arrayName) == 0) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) ) + { + return; + } + this->Modified(); + + delete[] this->ArrayName; + this->ArrayName = new char[strlen(arrayName) + 1]; + strcpy(this->ArrayName, arrayName); + this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME; +} + +//----------------------------------------------------------------------------- +// Return the method for obtaining scalar data. +const char *vtkUnstructuredGridVolumeZSweepMapper::GetScalarModeAsString(void) +{ + if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ) + { + return "UseCellData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA ) + { + return "UsePointFieldData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + return "UseCellFieldData"; + } + else + { + return "Default"; + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Max Pixel List Size: " << this->MaxPixelListSize << "\n"; + + os << indent << "ScalarMode: " << this->GetScalarModeAsString() << endl; + + os << indent << "Image Sample Distance: " + << this->ImageSampleDistance << "\n"; + os << indent << "Minimum Image Sample Distance: " + << this->MinimumImageSampleDistance << "\n"; + os << indent << "Maximum Image Sample Distance: " + << this->MaximumImageSampleDistance << "\n"; + os << indent << "Auto Adjust Sample Distances: " + << this->AutoAdjustSampleDistances << "\n"; + os << indent << "Intermix Intersecting Geometry: " + << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n"); + + // The PrintSelf test just search for words in the PrintSelf function + // We add here the internal variable we don't want to display: + // this->ImageViewportSize this->ImageOrigin this->ImageInUseSize + + os << indent << "ImageOrigin="<RayIntegrator) + { + os << indent << "RayIntegrator: " + << this->RayIntegrator->GetClassName() << endl; + } + else + { + os << indent << "RayIntegrator: (automatic)" << endl; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Maximum size allowed for a pixel list. Default is 32. +// During the rendering, if a list of pixel is full, incremental compositing +// is performed. Even if it is a user setting, it is an advanced parameter. +// You have to understand how the algorithm works to change this value. +int vtkUnstructuredGridVolumeZSweepMapper::GetMaxPixelListSize() +{ + return this->MaxPixelListSize; +} + +//----------------------------------------------------------------------------- +// Description: +// Change the maximum size allowed for a pixel list. It is an advanced +// parameter. +void vtkUnstructuredGridVolumeZSweepMapper::SetMaxPixelListSize(int size) +{ + assert("pre: positive_size" && size>0); + this->MaxPixelListSize=size; +} + +//----------------------------------------------------------------------------- +#define ESTABLISH_INTEGRATOR(classname) \ + if ( !this->RealRayIntegrator \ + || (!this->RealRayIntegrator->IsA(#classname)) ) \ + { \ + if (this->RealRayIntegrator) this->RealRayIntegrator->UnRegister(this); \ + this->RealRayIntegrator = classname::New(); \ + this->RealRayIntegrator->Register(this); \ + this->RealRayIntegrator->Delete(); \ + } \ + +//----------------------------------------------------------------------------- +// Description: +// WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE +// DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS +// Render the volume +void vtkUnstructuredGridVolumeZSweepMapper::Render(vtkRenderer *ren, + vtkVolume *vol) +{ + vtkDebugMacro(<<"Render"); + + // Check for input + if(this->GetInput()==0) + { + vtkErrorMacro(<< "No Input!"); + return; + } + + this->Scalars = this->GetScalars(this->GetInput(), this->ScalarMode, + this->ArrayAccessMode, + this->ArrayId, this->ArrayName, + this->CellScalars); + + if(this->Scalars==0) + { + vtkErrorMacro("Can't use the ZSweep mapper without scalars!"); + return; + } + + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + + // Check to make sure we have an appropriate integrator. + if (this->RayIntegrator) + { + if (this->RealRayIntegrator != this->RayIntegrator) + { + if (this->RealRayIntegrator) + { + this->RealRayIntegrator->UnRegister(this); + } + this->RealRayIntegrator = this->RayIntegrator; + this->RealRayIntegrator->Register(this); + } + } + else + { + if (this->CellScalars) + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridHomogeneousRayIntegrator); + } + else + { + if (vol->GetProperty()->GetIndependentComponents()) + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridPreIntegration); + } + else + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridPartialPreIntegration); + } + } + } + // Start timing now. We didn't want to capture the update of the + // input data in the times + this->Timer->StartTimer(); + + int oldImageMemorySize[2]; + oldImageMemorySize[0] = this->ImageMemorySize[0]; + oldImageMemorySize[1] = this->ImageMemorySize[1]; + + // If we are automatically adjusting the size to achieve a desired frame + // rate, then do that adjustment here. Base the new image sample distance + // on the previous one and the previous render time. Don't let + // the adjusted image sample distance be less than the minimum image sample + // distance or more than the maximum image sample distance. + float oldImageSampleDistance = this->ImageSampleDistance; + if ( this->AutoAdjustSampleDistances ) + { + float oldTime = this->RetrieveRenderTime( ren, vol ); + float newTime = vol->GetAllocatedRenderTime(); + this->ImageSampleDistance *= sqrt(oldTime / newTime); + this->ImageSampleDistance = + (this->ImageSampleDistance>this->MaximumImageSampleDistance)? + (this->MaximumImageSampleDistance):(this->ImageSampleDistance); + this->ImageSampleDistance = + (this->ImageSampleDistanceMinimumImageSampleDistance)? + (this->MinimumImageSampleDistance):(this->ImageSampleDistance); + } + + // The full image fills the viewport. First, compute the actual viewport + // size, then divide by the ImageSampleDistance to find the full image + // size in pixels + int width, height; + ren->GetTiledSize(&width, &height); + this->ImageViewportSize[0] = + static_cast(width/this->ImageSampleDistance); + this->ImageViewportSize[1] = + static_cast(height/this->ImageSampleDistance); + + this->ImageInUseSize[0] = this->ImageViewportSize[0]; + this->ImageInUseSize[1] = this->ImageViewportSize[1]; + this->ImageOrigin[0] = 0; + this->ImageOrigin[1] = 0; + + // What is a power of 2 size big enough to fit this image? + this->ImageMemorySize[0] = 32; + this->ImageMemorySize[1] = 32; + while ( this->ImageMemorySize[0] < this->ImageInUseSize[0] ) + { + this->ImageMemorySize[0] *= 2; + } + while ( this->ImageMemorySize[1] < this->ImageInUseSize[1] ) + { + this->ImageMemorySize[1] *= 2; + } + + // If the old image size is much too big (more than twice in + // either direction) then set the old width to 0 which will + // cause the image to be recreated + if ( oldImageMemorySize[0] > 2*this->ImageMemorySize[0] || + oldImageMemorySize[1] > 2*this->ImageMemorySize[1] ) + { + oldImageMemorySize[0] = 0; + } + + // If the old image is big enough (but not too big - we handled + // that above) then we'll bump up our required size to the + // previous one. This will keep us from thrashing. + if ( oldImageMemorySize[0] >= this->ImageMemorySize[0] && + oldImageMemorySize[1] >= this->ImageMemorySize[1] ) + { + this->ImageMemorySize[0] = oldImageMemorySize[0]; + this->ImageMemorySize[1] = oldImageMemorySize[1]; + } + + int bufferSize=this->ImageMemorySize[0] * this->ImageMemorySize[1] * 4; + + // Do we already have a texture big enough? If not, create a new one and + // clear it. + if ( !this->Image || + this->ImageMemorySize[0] > oldImageMemorySize[0] || + this->ImageMemorySize[1] > oldImageMemorySize[1] ) + { + // If there is an image there must be row bounds + if ( this->Image ) + { + delete [] this->Image; + delete [] this->RealRGBAImage; + } + this->Image = new unsigned char[bufferSize]; + this->RealRGBAImage=new float[bufferSize]; + } + + // We have to clear the image, each time: + memset(this->Image,0,bufferSize); + + vtkIdType j=0; + while(jRealRGBAImage[j]=0; + this->RealRGBAImage[j+1]=0; + this->RealRGBAImage[j+2]=0; + this->RealRGBAImage[j+3]=0; + j+=4; + } + + // Capture the zbuffer if necessary + if ( this->IntermixIntersectingGeometry && + ren->GetNumberOfPropsRendered() ) + { + int x1, x2, y1, y2; + double *viewport = ren->GetViewport(); + int *renWinSize = ren->GetRenderWindow()->GetSize(); + + // turn this->ImageOrigin into (x1,y1) in window (not viewport!) + // coordinates. + x1 = static_cast ( + viewport[0] * static_cast(renWinSize[0]) + + static_cast(this->ImageOrigin[0]) * this->ImageSampleDistance ); + y1 = static_cast ( + viewport[1] * static_cast(renWinSize[1]) + + static_cast(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // compute z buffer size + this->ZBufferSize[0] = static_cast( + static_cast(this->ImageInUseSize[0]) * this->ImageSampleDistance); + this->ZBufferSize[1] = static_cast( + static_cast(this->ImageInUseSize[1]) * this->ImageSampleDistance); + + // Use the size to compute (x2,y2) in window coordinates + x2 = x1 + this->ZBufferSize[0] - 1; + y2 = y1 + this->ZBufferSize[1] - 1; + + // This is the z buffer origin (in viewport coordinates) + this->ZBufferOrigin[0] = static_cast( + static_cast(this->ImageOrigin[0]) * this->ImageSampleDistance); + this->ZBufferOrigin[1] = static_cast( + static_cast(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // Capture the z buffer + this->ZBuffer = ren->GetRenderWindow()->GetZbufferData(x1,y1,x2,y2); + } + + this->RealRayIntegrator->Initialize(vol, this->Scalars); + + // Here is the Zsweep algorithm: + + // 1. For each vertex, find the list of incident faces (the "use set") (3.1) + // In the original paper, it deals with incident cells but the chapter about + // the parallel version in the dissertation deals with faces, which makes + // more sense. Hence, there is no need for the sparsification step (3.5.1) + // It is view-independent, so it can be reused for the next call to Render() + // if the dataset did not change. + vtkDebugMacro(<<"BuildUseSets: start"); + this->BuildUseSets(); + vtkDebugMacro(<<"BuildUseSets: done"); + + // 2. Sort the vertices by z-coordinates (view-dependent) in view space. + // For each vertex, compute its camera coordinates and sort it + // by z in an heap. The heap is called the "event list". + // The heap stores the Id of the vertices. + // It is view-dependent. + vtkDebugMacro(<<"ProjectAndSortVertices: start"); + this->ProjectAndSortVertices(ren,vol); + vtkDebugMacro(<<"ProjectAndSortVertices: done"); + + // 3. Create an empty "pixel list" (two way linked list) for each pixel of + // the screen. + vtkDebugMacro(<<"CreateAndCleanPixelList: start"); + this->CreateAndCleanPixelList(); + vtkDebugMacro(<<"CreateAndCleanPixelList: done"); + + // 4. Main loop + // (section 2 paragraph 11) + vtkDebugMacro(<<"MainLoop: start"); + this->MainLoop(ren->GetRenderWindow()); + vtkDebugMacro(<<"MainLoop: done"); + + // The algorithm is done: send to result to the final image. + if ( !ren->GetRenderWindow()->GetAbortRender() ) + { + float depth; + if ( this->IntermixIntersectingGeometry ) + { + depth = this->GetMinimumBoundsDepth( ren, vol ); + } + else + { + depth = -1; + } + + // copy the double image into the unsigned char image: + + j=0; + while(jRealRGBAImage[j+3]; + if(alpha!=0) + { + this->Image[j]=this->ColorComponentRealToByte(this->RealRGBAImage[j]/alpha); + this->Image[j+1]=this->ColorComponentRealToByte(this->RealRGBAImage[j+1]/alpha); + this->Image[j+2]=this->ColorComponentRealToByte(this->RealRGBAImage[j+2]/alpha); + this->Image[j+3]=this->ColorComponentRealToByte(alpha); + } + else + { + this->Image[j]=0; + this->Image[j+1]=0; + this->Image[j+2]=0; + this->Image[j+3]=0; + } + j+=4; + } + this->ImageDisplayHelper-> + RenderTexture( vol, ren, + this->ImageMemorySize, + this->ImageViewportSize, + this->ImageInUseSize, + this->ImageOrigin, + depth, + this->Image ); + + this->Timer->StopTimer(); + this->TimeToDraw = this->Timer->GetElapsedTime(); + this->StoreRenderTime( ren, vol, this->TimeToDraw ); + } + else + { + this->ImageSampleDistance = oldImageSampleDistance; + } + + if ( this->ZBuffer ) + { + delete [] this->ZBuffer; + this->ZBuffer = NULL; + } + + this->UpdateProgress(1.0); +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::AllocateUseSet(vtkIdType size) +{ + if(this->UseSet!=0) + { + if(size>static_cast(this->UseSet->Vector.size())) + { + delete this->UseSet; + this->UseSet=new vtkUseSet(size); + } + else + { + this->UseSet->Clear(); + } + } + else + { + this->UseSet=new vtkUseSet(size); + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::AllocateVertices(vtkIdType size) +{ + if(this->Vertices!=0) + { + if(size>static_cast(this->Vertices->Vector.size())) + { + delete this->Vertices; + this->Vertices=new vtkVertices(size); + } + } + else + { + this->Vertices=new vtkVertices(size); + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::BuildUseSets() +{ + int needsUpdate = 0; + + // If we have never created the list, we need updating + if (this->UseSet==0 ) + { + needsUpdate = 1; + } + + // If the data has changed in some way then we need to update + vtkUnstructuredGrid *input = this->GetInput(); + if ( input->GetMTime() > this->SavedTriangleListMTime.GetMTime() ) + { + needsUpdate = 1; + } + + + // If we don't need updating, return + if ( !needsUpdate ) + { + return; + } + + vtkIdType numberOfCells=input->GetNumberOfCells(); + vtkIdType numberOfPoints=input->GetNumberOfPoints(); + + // init the use set of each vertex + this->AllocateUseSet(numberOfPoints); + + // for each cell + vtkIdType cellIdx=0; + while(cellIdxGetCell(cellIdx,this->Cell); + + vtkIdType faces=this->Cell->GetNumberOfFaces(); + vtkIdType faceidx=0; + vtkCell *face; + vtkIdType faceIds[3]; + vtkIdType orderedFaceIds[3]; + // for each face + while(faceidxCell->GetFace(faceidx); + faceIds[0]=face->GetPointId(0); + faceIds[1]=face->GetPointId(1); + faceIds[2]=face->GetPointId(2); + this->ReorderTriangle(faceIds,orderedFaceIds); + + // Add face only if it is not already in the useset. + this->UseSet->AddFace(orderedFaceIds); + ++faceidx; + } + ++cellIdx; + } + this->SavedTriangleListMTime.Modified(); +} + +//----------------------------------------------------------------------------- +// Description: +// Reorder vertices `v' in increasing order in `w'. Orientation does not +// matter for the algorithm. +void vtkUnstructuredGridVolumeZSweepMapper::ReorderTriangle(vtkIdType v[3], + vtkIdType w[3]) +{ + if(v[0]>v[1]) + { + if(v[1]>v[2]) + { + // v[2] is the min + w[0]=v[2]; + w[1]=v[0]; + w[2]=v[1]; + } + else + { + // v[1] is the min + w[0]=v[1]; + w[1]=v[2]; + w[2]=v[0]; + } + } + else + { + if(v[0]>v[2]) + { + // v[2] is the min + w[0]=v[2]; + w[1]=v[0]; + w[2]=v[1]; + } + else + { + // v[0] is the min + w[0]=v[0]; + w[1]=v[1]; + w[2]=v[2]; + } + } + // At this point the triangle start with the min id and the + // order did not change + // Now, ensure that the two last id are in increasing order + if(w[1]>w[2]) + { + vtkIdType tmp=w[1]; + w[1]=w[2]; + w[2]=tmp; + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::ProjectAndSortVertices( + vtkRenderer *ren, + vtkVolume *vol) +{ + vtkUnstructuredGrid *input = this->GetInput(); + vtkIdType numberOfPoints=input->GetNumberOfPoints(); + + vtkIdType pointId=0; + vtkVertexEntry *vertex=0; + // Pre-computation for the projection. + + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + // Get the view matrix in two steps - there is a one step method in camera + // but it turns off stereo so we do not want to use that one + vtkCamera *cam = ren->GetActiveCamera(); + this->PerspectiveTransform->Identity(); + this->PerspectiveTransform->Concatenate( + cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], 0.0, 1.0 )); + this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + this->PerspectiveTransform->Concatenate(vol->GetMatrix()); + this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix()); + + + assert("check: empty list" && this->EventList->GetNumberOfItems()==0); + + this->AllocateVertices(numberOfPoints); + + while(pointIdVertices->Vector[pointId]); + + // Projection + // + double inPoint[4]; + input->GetPoint(pointId,inPoint); + inPoint[3] = 1.0; + + double outPoint[4]; + this->PerspectiveMatrix->MultiplyPoint( inPoint, outPoint ); + assert("outPoint[3]" && outPoint[3]!=0.0); + + double invW=1/outPoint[3]; + double zView = outPoint[2]*invW; + + int xScreen=static_cast((outPoint[0]*invW+1)*0.5*this->ImageViewportSize[0]-this->ImageOrigin[0]); + int yScreen=static_cast((outPoint[1]*invW+1)*0.5*this->ImageViewportSize[1]-this->ImageOrigin[1]); + + double outWorldPoint[4]; + + vol->GetMatrix()->MultiplyPoint( inPoint, outWorldPoint ); + + assert("check: vol no projection" && outWorldPoint[3]==1); + + double scalar; + if(this->CellScalars) // cell attribute + { + assert(0); + // scalar=this->Scalars->GetComponent(cellIdx,0); + scalar=0; + } + else // point attribute + { + scalar=this->Scalars->GetComponent(pointId,0); + } + + vertex->Set(xScreen,yScreen,outWorldPoint[0]/outWorldPoint[3], + outWorldPoint[1]/outWorldPoint[3], + outWorldPoint[2]/outWorldPoint[3],zView,scalar,invW); + + // Sorting + // + // we store -z because the top of the priority list is the + // smallest value +#ifdef BACK_TO_FRONT + this->EventList->Insert(-zView,pointId); +#else + this->EventList->Insert(zView,pointId); +#endif + ++pointId; + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::CreateAndCleanPixelList() +{ + // paper: a "pixel list" is a double linked list. We put that in a queue. + vtkIdType size=this->ImageInUseSize[0]*this->ImageInUseSize[1]; + if(this->PixelListFrame!=0) + { + if(this->PixelListFrame->GetSize()PixelListFrame; + this->PixelListFrame=0; + } + } + + if(this->PixelListFrame==0) + { + this->PixelListFrame=new vtkPixelListFrame(size); + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::MainLoop(vtkRenderWindow *renWin) +{ + double previousZTarget; + double zTarget; + vtkIdType vertex; + +// used to know if the next vertex is on the same plane + double currentZ; // than the previous one. If so, the z-target has to be + // updated (without calling the compositing function) + if(this->EventList->GetNumberOfItems()==0) + { + return; // we are done. + } + + // initialize the "previous z-target" to the z-coordinate of the first + // vertex. + vertex=this->EventList->Peek(0,previousZTarget); + +#ifdef BACK_TO_FRONT + previousZTarget=-previousZTarget; // because the EventList store -z +#endif + + // (section 2 paragraph 11) + // initialize the "z-target" with the maximum z-coordinate of the adjacent + // vertices to the first vertex. The adjacent vertices can be found + // indirectly by using the "use set" of the first vertex (cells), and + // by taking the vertices of all those cells. + // + zTarget=previousZTarget; + vtkstd::list::iterator it; + vtkstd::list::iterator itEnd; + +// this->MaxRecordedPixelListSize=0; + this->MaxPixelListSizeReached=0; + this->XBounds[0]=this->ImageInUseSize[0]; + this->XBounds[1]=0; + this->YBounds[0]=this->ImageInUseSize[1]; + this->YBounds[1]=0; + + vtkIdType progressCount=0; + vtkIdType sum=this->EventList->GetNumberOfItems(); + + if(this->MemoryManager==0) + { + this->MemoryManager=new vtkPixelListEntryMemory; + } + + this->UseSet->SetNotRendered(); + + int aborded=0; + // for each vertex of the "event list" + while(this->EventList->GetNumberOfItems()>0) + { + this->UpdateProgress(static_cast(progressCount)/sum); + + aborded=renWin->CheckAbortStatus(); + if(aborded) + { + break; + } + ++progressCount; + // the z coordinate of the current vertex defines the "sweep plane". + vertex=this->EventList->Pop(0,currentZ); + + if(this->UseSet->Vector[vertex]!=0) + { // otherwise the vertex is not useful, basically this is the + // end we reached the last ztarget + +#ifdef BACK_TO_FRONT + currentZ=-currentZ; // because the EventList store -z +#endif + + if(previousZTarget==currentZ) + { + // the new vertex is on the same sweep plane than the previous vertex + // that defined a z target + // => the z target has to be updated accordingly + // This is also the case for the first vertex. + it=this->UseSet->Vector[vertex]->begin(); + itEnd=this->UseSet->Vector[vertex]->end(); + + // for each face incident with the vertex + while(it!=itEnd) + { + vtkFace *face=(*it); + // for each point of the face, get the closest z + vtkIdType *vids=face->GetFaceIds(); + vtkIdType i=0; + while(i<3) + { + double z=this->Vertices->Vector[vids[i]].GetZview(); +#ifdef BACK_TO_FRONT + if(zzTarget) +#endif + { + zTarget=z; + } + ++i; + } + ++it; + } + } + + // Time to call the composite function? +#ifdef BACK_TO_FRONT + if(currentZzTarget) +#endif + { + this->CompositeFunction(zTarget); + + // Update the zTarget + previousZTarget=zTarget; + + it=this->UseSet->Vector[vertex]->begin(); + itEnd=this->UseSet->Vector[vertex]->end(); + // for each cell incident with the vertex + while(it!=itEnd) + { + vtkFace *face=(*it); + // for each point of the face, get the closest z + vtkIdType *vids=face->GetFaceIds(); + vtkIdType i=0; + while(i<3) + { + double z=this->Vertices->Vector[vids[i]].GetZview(); +#ifdef BACK_TO_FRONT + if(zzTarget) +#endif + { + zTarget=z; + } + ++i; + } + ++it; + } + } + else + { + if(this->MaxPixelListSizeReached) + { + this->CompositeFunction(currentZ); + // We do not update the zTarget in this case. + } + } + + // use the "use set" (cells) of the vertex to get the cells that are + // incident on the vertex, and that have this vertex as + // minimal z-coordinate, + + it=this->UseSet->Vector[vertex]->begin(); + itEnd=this->UseSet->Vector[vertex]->end(); + + while(it!=itEnd) + { + vtkFace *face=(*it); + if(!face->GetRendered()) + { + vtkIdType *vids=face->GetFaceIds(); + this->RasterizeFace(vids); + face->SetRendered(1); + } +#if 0 // face search + // for each point of the face, get the closest z + vtkIdType *vids=face->GetFaceIds(); + vtkIdType minVertex=vids[0]; + double farestZ=this->Vertices->Vector[vids[0]].GetZview(); + + vtkIdType i=1; + while(i<3) + { + double z=this->Vertices->Vector[vids[i]].GetZview(); +#ifdef BACK_TO_FRONT + if(z>farestZ) +#else + if(zGetRendered()) +// { +// cout<<"FACE ALREADY RENDERED!!!!"<RasterizeFace(vids); +// face->SetRendered(1); + } +#endif // face search + ++it; + } + } // if useset of vertex is not null + } // while(eventList->GetNumberOfItems()>0) + + if(!aborded) + { + // Here a final compositing + vtkDebugMacro(<<"Flush Compositing"); +// this->SavePixelListFrame(); +#ifdef BACK_TO_FRONT + this->CompositeFunction(-2); +#else + this->CompositeFunction(2); +#endif + } + this->PixelListFrame->Clean(this->MemoryManager); +// vtkDebugMacro(<<"MaxRecordedPixelListSize="<MaxRecordedPixelListSize); +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::SavePixelListFrame() +{ + vtkPolyData *dataset=vtkPolyData::New(); + + vtkIdType height=this->ImageInUseSize[1]; + vtkIdType width=this->ImageInUseSize[0]; + vtkPixelListEntry *current; + vtkIdType i; + + vtkPoints *pts=vtkPoints::New(); + pts->SetDataTypeToDouble(); + + vtkDoubleArray *dataArray=vtkDoubleArray::New(); + vtkCellArray *vertices=vtkCellArray::New(); + vtkIdType pointId=0; + +// height=151; +// width=151; + + vtkIdType y=0; //150; + while(yImageInUseSize[0]+x; + current=this->PixelListFrame->GetFirst(i); + while(current!=0) + { + double *values=current->GetValues(); + + double point[3]; + point[0]=x; + point[1]=y; + point[2]=values[2]; // zWorld + + pts->InsertNextPoint(point); + dataArray->InsertNextValue(values[3]); + vertices->InsertNextCell(1,&pointId); + current=current->GetNext(); + ++pointId; + } + ++x; + } + ++y; + } + dataset->SetPoints(pts); + pts->Delete(); + dataset->SetVerts(vertices); + vertices->Delete(); + dataset->GetPointData()->SetScalars(dataArray); + dataArray->Delete(); + + vtkXMLPolyDataWriter *writer=vtkXMLPolyDataWriter::New(); + writer->SetFileName("pixellistframe.vtp"); + writer->SetInput(dataset); + writer->SetIdTypeToInt32(); + dataset->Delete(); + writer->Write(); + writer->Delete(); +} + +//----------------------------------------------------------------------------- +// Description: +// Perform a scan conversion of a triangle, interpolating z and the scalar. +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeFace(vtkIdType faceIds[3]) +{ + // The triangle is splitted by an horizontal line passing through the + // second vertex v1 (y-order) + // Hence, on one side there one edge (v0v2), on the other side there are two + // edges (v0v1 and v1v2). + + vtkVertexEntry *v0=&(this->Vertices->Vector[faceIds[0]]); + vtkVertexEntry *v1=&(this->Vertices->Vector[faceIds[1]]); + vtkVertexEntry *v2=&(this->Vertices->Vector[faceIds[2]]); + + this->RasterizeTriangle(v0,v1,v2); +} + +//----------------------------------------------------------------------------- +// Description: +// Perform a scan conversion of a triangle, interpolating z and the scalar. +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeTriangle( + vtkVertexEntry *ve0, + vtkVertexEntry *ve1, + vtkVertexEntry *ve2 + ) +{ + assert("pre: ve0_exists" && ve0!=0); + assert("pre: ve1_exists" && ve1!=0); + assert("pre: ve2_exists" && ve2!=0); + + vtkVertexEntry *v0=ve0; + vtkVertexEntry *v1=ve1; + vtkVertexEntry *v2=ve2; + + // The triangle is splitted by an horizontal line passing through the + // second vertex v1 (y-order) + // Hence, on one side there one edge (v0v2), on the other side there are two + // edges (v0v1 and v1v2). + + // Order vertices by y screen. + + vtkVertexEntry *tmp; + + if(v0->GetScreenY()>v1->GetScreenY()) + { + tmp=v0; + v0=v1; + v1=tmp; + } + if(v0->GetScreenY()>v2->GetScreenY()) + { + tmp=v1; + v1=v0; + v0=v2; + v2=tmp; + } + else + { + if(v1->GetScreenY()>v2->GetScreenY()) + { + tmp=v1; + v1=v2; + v2=tmp; + } + } + + if(v0->GetScreenY()YBounds[0]) + { + if(v0->GetScreenY()>=0) + { + this->YBounds[0]=v0->GetScreenY(); + } + else + { + this->YBounds[0]=0; + } + } + if(v2->GetScreenY()>this->YBounds[1]) + { + if(v2->GetScreenY()ImageInUseSize[1]) + { + this->YBounds[1]=v2->GetScreenY(); + } + else + { + this->YBounds[1]=this->ImageInUseSize[1]-1; + } + } + + int x=v0->GetScreenX(); + + if(xXBounds[0]) + { + if(x>=0) + { + this->XBounds[0]=x; + } + else + { + this->XBounds[0]=0; + } + } + else + { + if(x>this->XBounds[1]) + { + if(xImageInUseSize[0]) + { + this->XBounds[1]=x; + } + else + { + this->XBounds[1]=this->ImageInUseSize[0]-1; + } + } + } + x=v1->GetScreenX(); + + if(xXBounds[0]) + { + if(x>=0) + { + this->XBounds[0]=x; + } + else + { + this->XBounds[0]=0; + } + } + else + { + if(x>this->XBounds[1]) + { + if(xImageInUseSize[0]) + { + this->XBounds[1]=x; + } + else + { + this->XBounds[1]=this->ImageInUseSize[0]-1; + } + } + } + + x=v2->GetScreenX(); + + if(xXBounds[0]) + { + if(x>=0) + { + this->XBounds[0]=x; + } + else + { + this->XBounds[0]=0; + } + } + else + { + if(x>this->XBounds[1]) + { + if(xImageInUseSize[0]) + { + this->XBounds[1]=x; + } + else + { + this->XBounds[1]=this->ImageInUseSize[0]-1; + } + } + } + + int dy20=v2->GetScreenY()-v0->GetScreenY(); + int dx10=v1->GetScreenX()-v0->GetScreenX(); + int dx20=v2->GetScreenX()-v0->GetScreenX(); + int dy10=v1->GetScreenY()-v0->GetScreenY(); + + int det=dy20*dx10-dx20*dy10; + + vtkScreenEdge *leftEdge=0; + vtkScreenEdge *rightEdge=0; + + if(det==0) //v0v1v2 aligned or v0=v1=v2 + { + // easy case: v0=v1=v2 render the 3 points + if(v0->GetScreenX()==v1->GetScreenX() && v0->GetScreenX()==v2->GetScreenX() + && v0->GetScreenY()==v1->GetScreenY() + && v0->GetScreenY()==v2->GetScreenY()) + { + x=v0->GetScreenX(); + int y=v0->GetScreenY(); + if(x>=0 && xImageInUseSize[0] && y>=0 && + yImageInUseSize[1]) + { + vtkIdType i=y*this->ImageInUseSize[0]+x; + // Write the pixel + vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry(); + p0->Init(v0->GetValues(),v0->GetZview()); + this->PixelListFrame->AddAndSort(i,p0); + + vtkPixelListEntry *p1=this->MemoryManager->AllocateEntry(); + p1->Init(v1->GetValues(),v1->GetZview()); + this->PixelListFrame->AddAndSort(i,p1); + + vtkPixelListEntry *p2=this->MemoryManager->AllocateEntry(); + p2->Init(v2->GetValues(),v2->GetZview()); + this->PixelListFrame->AddAndSort(i,p2); + +// if(this->PixelListFrame->GetListSize(i)>this->MaxRecordedPixelListSize) +// { +// this->MaxRecordedPixelListSize=this->PixelListFrame->GetListSize(i); +// } + + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(i)> + this->MaxPixelListSize; + } + } + } + else // line + { + this->RasterizeLine(v0,v1); + this->RasterizeLine(v1,v2); + this->RasterizeLine(v0,v2); + } + return; + } + else + { + if(det>0) //v0v1 on right + { + this->DoubleEdge->Init(v0,v1,v2,dx10,dy10,1); // true=on right + rightEdge=this->DoubleEdge; + this->SimpleEdge->Init(v0,v2,dx20,dy20,0); + leftEdge=this->SimpleEdge; + } + else + { + // v0v1 on left + this->DoubleEdge->Init(v0,v1,v2,dx10,dy10,0); // true=on right + leftEdge=this->DoubleEdge; + this->SimpleEdge->Init(v0,v2,dx20,dy20,1); + rightEdge=this->SimpleEdge; + } + } + + int y=v0->GetScreenY(); + int y1=v1->GetScreenY(); + int y2=v2->GetScreenY(); + + int skipped=0; + + if(y1>=0) // clipping + { + + if(y1>=this->ImageInUseSize[1]) // clipping + { + y1=this->ImageInUseSize[1]-1; + } + + while(y<=y1) + { + if(y>=0 && yImageInUseSize[1]) // clipping + { + this->RasterizeSpan(y,leftEdge,rightEdge); + } + ++y; + if(y<=y1) + { + leftEdge->NextLine(y); + rightEdge->NextLine(y); + } + } + } + else + { + leftEdge->SkipLines(y1-y,y1); + rightEdge->SkipLines(y1-y,y1); + y=y1; + skipped=1; + } + + if(yImageInUseSize[1]) // clipping + { + leftEdge->OnBottom(skipped,y); + rightEdge->OnBottom(skipped,y); + + if(y2>=this->ImageInUseSize[1]) // clipping + { + y2=this->ImageInUseSize[1]-1; + } + + while(y<=y2) + { + if(y>=0) // clipping, needed in case of no top + { + this->RasterizeSpan(y,leftEdge,rightEdge); + } + ++y; + leftEdge->NextLine(y); + rightEdge->NextLine(y); + } + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeSpan(int y, + vtkScreenEdge *left, + vtkScreenEdge *right) +{ + assert("pre: left_exists" && left!=0); + assert("pre: right_exists" && right!=0); + + vtkIdType i=y*this->ImageInUseSize[0]; + + this->Span->Init(left->GetX(), + left->GetInvW(), + left->GetPValues(), + left->GetZview(), + right->GetX(), + right->GetInvW(), + right->GetPValues(), + right->GetZview()); + + while(!this->Span->IsAtEnd()) + { + int x=this->Span->GetX(); + if(x>=0 && xImageInUseSize[0]) // clipping + { + vtkIdType j=i+x; + // Write the pixel + vtkPixelListEntry *p=this->MemoryManager->AllocateEntry(); + p->Init(this->Span->GetValues(),this->Span->GetZview()); + this->PixelListFrame->AddAndSort(j,p); + + +// if(this->PixelListFrame->GetListSize(j)>this->MaxRecordedPixelListSize) +// { +// this->MaxRecordedPixelListSize=this->PixelListFrame->GetListSize(j); +// } + + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)> + this->MaxPixelListSize; + } + } + this->Span->NextPixel(); + } +} + +enum +{ + VTK_LINE_CONSTANT=0, + VTK_LINE_BRESENHAM, + VTK_LINE_DIAGONAL +}; + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeLine(vtkVertexEntry *v0, + vtkVertexEntry *v1) +{ + assert("pre: v0_exists" && v0!=0); + assert("pre: v1_exists" && v1!=0); + assert("pre: y_ordered" && v0->GetScreenY()<=v1->GetScreenY()); + + int lineCase; + int xIncrement; // if true increment x, if false increment y + int dx; + int dy; + int xSign; + + // initialization is not useful, it is just to remove compiler warnings + int dx2=0; + int dy2=0; + int e=0; + + double values[VTK_VALUES_SIZE]; + double pValues[VTK_VALUES_SIZE]; + + double dPv[VTK_VALUES_SIZE]; + double dInvW; + double dZ; + + double zView; + double invW; + + int i; + + int x=v0->GetScreenX(); + int y=v0->GetScreenY(); + + // 1. Find the case + dx=v1->GetScreenX()-v0->GetScreenX(); + if(dx<0) + { + dx=-dx; + xSign=-1; + } + else + { + xSign=1; + } + dy=v1->GetScreenY()-v0->GetScreenY(); + xIncrement=dx>dy; + if(xIncrement) + { + if(dy==0) + { + lineCase=VTK_LINE_CONSTANT; + } + else + { + lineCase=VTK_LINE_BRESENHAM; + dx2=dx<<1; + dy2=dy<<1; + e=dx; + } + + double invDx=1.0/dx; + i=0; + invW=v0->GetInvW(); + double invW1=v1->GetInvW(); + double *val0=v0->GetValues(); + double *val1=v1->GetValues(); + while(iGetZview(); + dZ=(v1->GetZview()-zView)*invDx; + } + else + { + if(dx==0) + { + if(dy==0) + { + // render both points and return + // write pixel + if(x>=0 && xImageInUseSize[0] && y>=0 && + yImageInUseSize[1]) // clipping + { + vtkIdType j=y*this->ImageInUseSize[0]+x; // mult==bad!! + // Write the pixel + vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry(); + p0->Init(v0->GetValues(),v0->GetZview()); + this->PixelListFrame->AddAndSort(j,p0); + + // Write the pixel + vtkPixelListEntry *p1=this->MemoryManager->AllocateEntry(); + p1->Init(v1->GetValues(),v1->GetZview()); + this->PixelListFrame->AddAndSort(j,p1); + + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)> + this->MaxPixelListSize; + } + } + return; + } + else + { + lineCase=VTK_LINE_CONSTANT; + } + } + else + { + if(dy==dx) + { + lineCase=VTK_LINE_DIAGONAL; + } + else + { + lineCase=VTK_LINE_BRESENHAM; + dx2=dx<<1; + dy2=dy<<1; + e=dy; + } + } + double invDy=1.0/dy; + i=0; + invW=v0->GetInvW(); + double invW1=v1->GetInvW(); + double *val0=v0->GetValues(); + double *val1=v1->GetValues(); + while(iGetZview(); + dZ=(v1->GetZview()-zView)*invDy; + } + + // 2. Iterate over each pixel of the straight line. + int done=0; + while(!done) + { + // write pixel + if(x>=0 && xImageInUseSize[0] && y>=0 && + yImageInUseSize[1]) // clipping + { + vtkIdType j=y*this->ImageInUseSize[0]+x; // mult==bad!! + // Write the pixel + vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry(); + p0->Init(values,zView); + this->PixelListFrame->AddAndSort(j,p0); + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)> + this->MaxPixelListSize; + } + } + + // next pixel + switch(lineCase) + { + case VTK_LINE_CONSTANT: + if(xIncrement) + { + x+=xSign; + if(xSign>0) + { + done=x>v1->GetScreenX(); + } + else + { + done=xGetScreenX(); + } + } + else + { + ++y; + done=y>v1->GetScreenY(); + } + // values, invw, zview + break; + case VTK_LINE_DIAGONAL: + ++y; + x+=xSign; + done=y>v1->GetScreenY(); + // values, invw, zview + break; + case VTK_LINE_BRESENHAM: + if(xIncrement) + { + x+=xSign; + e+=dy2; + if(e>=dx2) + { + e-=dx2; + ++y; + } + if(xSign>0) + { + done=x>v1->GetScreenX(); + } + else + { + done=xGetScreenX(); + } + } + else + { + ++y; + e+=dx2; + if(e>=dy2) + { + e-=dy2; + x+=xSign; + } + done=y>v1->GetScreenY(); + } + // values, invw, zview + break; + } + if(!done) + { + invW+=dInvW; + i=0; + double w=1.0/invW; + while(iYBounds[0]; + vtkIdType i=y*this->ImageInUseSize[0]+this->XBounds[0]; + + vtkIdType index=(y*this->ImageMemorySize[0]+this->XBounds[0])<< 2; // *4 + vtkIdType indexStep=this->ImageMemorySize[0]<<2; // *4 + + vtkPixelListEntry *current; + vtkPixelListEntry *next; + double zBuffer=0; + + int newXBounds[2]; + int newYBounds[2]; + + newXBounds[0]=this->ImageInUseSize[0]; + newXBounds[1]=0; + newYBounds[0]=this->ImageInUseSize[1]; + newYBounds[1]=0; + + int xMin=this->XBounds[0]; + int xMax=this->XBounds[1]; + int yMax=this->YBounds[1]; + + vtkPixelList *pixel; + int x; + vtkIdType j; + vtkIdType index2; + int done; + int doIntegration; + double length; + float *color; + + // for each pixel in the bounding box + while(y<=yMax) + { + x=xMin; + j=i; + index2=index; + while(x<=xMax) + { + pixel=this->PixelListFrame->GetList(j); + // we need at least two entries per pixel to perform compositing + if(pixel->GetSize()>=2) + { + current=pixel->GetFirst(); + next=current->GetNext(); +#ifdef BACK_TO_FRONT + done=current->GetZview()<=zTarget || next->GetZview()<=zTarget; +#else + done=current->GetZview()>=zTarget || next->GetZview()>=zTarget; +#endif + + if(!done && this->ZBuffer!=0) + { + // value of the z buffer at the current pixel. + zBuffer=this->GetZBufferValue(x,y); + } + + while(!done) + { + if(this->ZBuffer!=0) + { + // check that current and next are in front of the z-buffer value + doIntegration=current->GetZview()GetZview()GetZview()!=next->GetZview()) + { + // length in world coordinates + length=sqrt(vtkMath::Distance2BetweenPoints( + current->GetValues(),next->GetValues())); + if(length!=0) +// if(length>=0.4) + { + color=this->RealRGBAImage+index2; + this->IntersectionLengths->SetValue(0,length); + this->NearIntersections->SetValue(0,current->GetValues()[VTK_VALUES_SCALAR_INDEX]); + this->FarIntersections->SetValue(0,next->GetValues()[VTK_VALUES_SCALAR_INDEX]); +#ifdef BACK_TO_FRONT + this->RealRayIntegrator->Integrate(this->IntersectionLengths, + this->FarIntersections, + this->NearIntersections, + color); +#else + this->RealRayIntegrator->Integrate(this->IntersectionLengths, + this->NearIntersections, + this->FarIntersections, + color); +#endif + } // length!=0 + } // current->GetZview()!=next->GetZview() + } // doIntegration + + // Next entry + pixel->RemoveFirst(this->MemoryManager); // remove current + + done=pixel->GetSize()<2; // empty queue? + if(!done) + { + current=next; + next=current->GetNext(); +#ifdef BACK_TO_FRONT + done=next->GetZview()<=zTarget; +#else + done=next->GetZview()>=zTarget; +#endif + } + } // while(!done) + } + if(pixel->GetSize()>=2) + { + if(xnewXBounds[1]) + { + newXBounds[1]=x; + } + } + if(ynewYBounds[1]) + { + newYBounds[1]=y; + } + } + } + + // next abscissa + ++j; + index2+=4; + ++x; + } + // next ordinate + i=i+this->ImageInUseSize[0]; + index+=indexStep; + ++y; + } + + // Update the bounding box. Useful for the delayed compositing + + this->XBounds[0]=newXBounds[0]; + this->XBounds[1]=newXBounds[1]; + this->YBounds[0]=newYBounds[0]; + this->YBounds[1]=newYBounds[1]; + + this->MaxPixelListSizeReached=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Convert and clamp a float color component into a unsigned char. +unsigned char vtkUnstructuredGridVolumeZSweepMapper::ColorComponentRealToByte( + float color) +{ + int val=static_cast(color*255.0); + if(val>255) + { + val=255; + } + else + { + if(val<0) + { + val=0; + } + } + return static_cast(val); +} + +//----------------------------------------------------------------------------- +double vtkUnstructuredGridVolumeZSweepMapper::GetZBufferValue(int x, + int y) +{ + int xPos, yPos; + + xPos = static_cast(static_cast(x) * this->ImageSampleDistance); + yPos = static_cast(static_cast(y) * this->ImageSampleDistance); + + xPos = (xPos >= this->ZBufferSize[0])?(this->ZBufferSize[0]-1):(xPos); + yPos = (yPos >= this->ZBufferSize[1])?(this->ZBufferSize[1]-1):(yPos); + + return *(this->ZBuffer + yPos*this->ZBufferSize[0] + xPos); +} + +//----------------------------------------------------------------------------- +double vtkUnstructuredGridVolumeZSweepMapper::GetMinimumBoundsDepth( + vtkRenderer *ren, + vtkVolume *vol ) +{ + double bounds[6]; + vol->GetBounds( bounds ); + + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + // Get the view matrix in two steps - there is a one step method in camera + // but it turns off stereo so we do not want to use that one + vtkCamera *cam = ren->GetActiveCamera(); + this->PerspectiveTransform->Identity(); + this->PerspectiveTransform->Concatenate( + cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], 0.0, 1.0 )); + this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix()); + + double minZ = 1.0; + + for ( int k = 0; k < 2; k++ ) + { + for ( int j = 0; j < 2; j++ ) + { + for ( int i = 0; i < 2; i++ ) + { + double inPoint[4]; + inPoint[0] = bounds[ i]; + inPoint[1] = bounds[2+j]; + inPoint[2] = bounds[4+k]; + inPoint[3] = 1.0; + + double outPoint[4]; + this->PerspectiveMatrix->MultiplyPoint( inPoint, outPoint ); + double testZ = outPoint[2] / outPoint[3]; + minZ = ( testZ < minZ ) ? (testZ) : (minZ); + } + } + } + + return minZ; +} diff --git a/Rendering/vtkUnstructuredGridVolumeZSweepMapper.h b/Rendering/vtkUnstructuredGridVolumeZSweepMapper.h new file mode 100644 index 0000000..15d4587 --- /dev/null +++ b/Rendering/vtkUnstructuredGridVolumeZSweepMapper.h @@ -0,0 +1,372 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeZSweepMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridVolumeZSweepMapper - Unstructured grid volume mapper based the ZSweep Algorithm + +// .SECTION Description +// This is a volume mapper for unstructured grid implemented with the ZSweep +// algorithm. This is a software projective method. + +// .SECTION see also +// vtkVolumetMapper + +// .SECTION Background +// The algorithm is described in the following paper: +// Ricardo Farias, Joseph S. B. Mitchell and Claudio T. Silva. +// ZSWEEP: An Efficient and Exact Projection Algorithm for Unstructured Volume +// Rendering. In 2000 Volume Visualization Symposium, pages 91--99. +// October 2000. +// http://www.cse.ogi.edu/~csilva/papers/volvis2000.pdf + +#ifndef __vtkUnstructuredGridVolumeZSweepMapper_h +#define __vtkUnstructuredGridVolumeZSweepMapper_h + +#include "vtkUnstructuredGridVolumeMapper.h" + +class vtkRenderer; +class vtkVolume; +class vtkRayCastImageDisplayHelper; +class vtkCell; +class vtkGenericCell; +class vtkIdList; +class vtkPriorityQueue; +class vtkTransform; +class vtkMatrix4x4; +class vtkVolumeProperty; +class vtkDoubleArray; +class vtkUnstructuredGridVolumeRayIntegrator; +class vtkRenderWindow; + +// Internal classes +class vtkScreenEdge; +class vtkSpan; +class vtkPixelListFrame; +class vtkUseSet; +class vtkVertices; +class vtkSimpleScreenEdge; +class vtkDoubleScreenEdge; +class vtkVertexEntry; +class vtkPixelListEntryMemory; + +class VTK_RENDERING_EXPORT vtkUnstructuredGridVolumeZSweepMapper : public vtkUnstructuredGridVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridVolumeZSweepMapper,vtkUnstructuredGridVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set MaxPixelListSize to 32. + static vtkUnstructuredGridVolumeZSweepMapper *New(); + + // Description: + // Control how the filter works with scalar point data and cell attribute + // data. By default (ScalarModeToDefault), the filter will use point data, + // and if no point data is available, then cell data is used. Alternatively + // you can explicitly set the filter to use point data + // (ScalarModeToUsePointData) or cell data (ScalarModeToUseCellData). + // You can also choose to get the scalars from an array in point field + // data (ScalarModeToUsePointFieldData) or cell field data + // (ScalarModeToUseCellFieldData). If scalars are coming from a field + // data array, you must call SelectColorArray before you call + // GetColors. + vtkSetMacro(ScalarMode,int); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToDefault() { + this->SetScalarMode(VTK_SCALAR_MODE_DEFAULT);}; + void SetScalarModeToUsePointData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA);}; + void SetScalarModeToUseCellData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_DATA);}; + void SetScalarModeToUsePointFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA);}; + void SetScalarModeToUseCellFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA);}; + + // Description: + // When ScalarMode is set to UsePointFileData or UseCellFieldData, + // you can specify which array to use for coloring using these methods. + // The transfer function in the vtkVolumeProperty (attached to the calling + // vtkVolume) will decide how to convert vectors to colors. + virtual void SelectScalarArray(int arrayNum); + virtual void SelectScalarArray(const char* arrayName); + + // Description: + // Get the array name or number and component to color by. + virtual char* GetArrayName() { return this->ArrayName; } + virtual int GetArrayId() { return this->ArrayId; } + virtual int GetArrayAccessMode() { return this->ArrayAccessMode; } + + // Description: + // Return the method for obtaining scalar data. + const char *GetScalarModeAsString(); + + // Description: + // Sampling distance in the XY image dimensions. Default value of 1 meaning + // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If + // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. + vtkSetClampMacro( ImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( ImageSampleDistance, float ); + + // Description: + // This is the minimum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MinimumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MinimumImageSampleDistance, float ); + + // Description: + // This is the maximum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MaximumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MaximumImageSampleDistance, float ); + + // Description: + // If AutoAdjustSampleDistances is on, the the ImageSampleDistance + // will be varied to achieve the allocated render time of this + // prop (controlled by the desired update rate and any culling in + // use). + vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 ); + vtkGetMacro( AutoAdjustSampleDistances, int ); + vtkBooleanMacro( AutoAdjustSampleDistances, int ); + + // Description: + // If IntermixIntersectingGeometry is turned on, the zbuffer will be + // captured and used to limit the traversal of the rays. + vtkSetClampMacro( IntermixIntersectingGeometry, int, 0, 1 ); + vtkGetMacro( IntermixIntersectingGeometry, int ); + vtkBooleanMacro( IntermixIntersectingGeometry, int ); + + // Description: + // Maximum size allowed for a pixel list. Default is 32. + // During the rendering, if a list of pixel is full, incremental compositing + // is performed. Even if it is a user setting, it is an advanced parameter. + // You have to understand how the algorithm works to change this value. + int GetMaxPixelListSize(); + + // Description: + // Change the maximum size allowed for a pixel list. It is an advanced + // parameter. + // \pre positive_size: size>0 + void SetMaxPixelListSize(int size); + + // Description: + // Set/Get the helper class for integrating rays. If set to NULL, a + // default integrator will be assigned. + virtual void SetRayIntegrator(vtkUnstructuredGridVolumeRayIntegrator *ri); + vtkGetObjectMacro(RayIntegrator, vtkUnstructuredGridVolumeRayIntegrator); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + void Render(vtkRenderer *ren, + vtkVolume *vol); + + vtkGetVectorMacro( ImageInUseSize, int, 2 ); + vtkGetVectorMacro( ImageOrigin, int, 2 ); + vtkGetVectorMacro( ImageViewportSize, int , 2 ); +//ETX + +protected: + vtkUnstructuredGridVolumeZSweepMapper(); + ~vtkUnstructuredGridVolumeZSweepMapper(); + + // Description: + // For each vertex, find the list of incident faces. + void BuildUseSets(); + + // Description: + // Reorder vertices `v' in increasing order in `w'. Orientation does not + // matter for the algorithm. + void ReorderTriangle(vtkIdType v[3], + vtkIdType w[3]); + + // Description: + // Project and sort the vertices by z-coordinates in view space in the + // "event list" (an heap). + void ProjectAndSortVertices(vtkRenderer *ren, + vtkVolume *vol); + + // Description: + // Create an empty "pixel list" for each pixel of the screen. + void CreateAndCleanPixelList(); + + // Description: + // MainLoop of the Zsweep algorithm. + void MainLoop(vtkRenderWindow *renWin); + + // Description: + // Do delayed compositing from back to front, stopping at zTarget for each + // pixel inside the bounding box. + void CompositeFunction(double zTarget); + + // Description: + // Convert and clamp a float color component into a unsigned char. + unsigned char ColorComponentRealToByte(float color); + + // Description: + // Perform scan conversion of a triangle face. + void RasterizeFace(vtkIdType faceIds[3]); + + // Description: + // Perform scan conversion of a triangle defined by its vertices. + // \pre ve0_exists: ve0!=0 + // \pre ve1_exists: ve1!=0 + // \pre ve2_exists: ve2!=0 + void RasterizeTriangle(vtkVertexEntry *ve0,vtkVertexEntry *ve1, + vtkVertexEntry *ve2); + + // Description: + // Perform scan conversion of an horizontal span from left ro right at line + // y. + // \pre left_exists: left!=0 + // \pre right_exists: right!=0 + void RasterizeSpan(int y, + vtkScreenEdge *left, + vtkScreenEdge *right); + + // Description: + // Scan conversion of a straight line defined by endpoints v0 and v1. + // \pre v0_exists: v0!=0 + // \pre v1_exists: v1!=0 + // \pre y_ordered v0->GetScreenY()<=v1->GetScreenY() + void RasterizeLine(vtkVertexEntry *v0, + vtkVertexEntry *v1); + + void StoreRenderTime(vtkRenderer *ren, + vtkVolume *vol, + float t); + + float RetrieveRenderTime(vtkRenderer *ren, + vtkVolume *vol); + + // Description: + // Return the value of the z-buffer at screen coordinates (x,y). + double GetZBufferValue(int x, + int y); + + double GetMinimumBoundsDepth(vtkRenderer *ren, + vtkVolume *vol); + + // Description: + // Allocate an array of usesets of size `size' only if the current one is not + // large enough. Otherwise clear each use set of each vertex. + void AllocateUseSet(vtkIdType size); + + // Description: + // Allocate a vertex array of size `size' only if the current one is not + // large enough. + void AllocateVertices(vtkIdType size); + + // Description: + // For debugging purpose, save the pixel list frame as a dataset. + void SavePixelListFrame(); + + int MaxPixelListSize; + + float ImageSampleDistance; + float MinimumImageSampleDistance; + float MaximumImageSampleDistance; + int AutoAdjustSampleDistances; + + vtkRayCastImageDisplayHelper *ImageDisplayHelper; + + // This is how big the image would be if it covered the entire viewport + int ImageViewportSize[2]; + + // This is how big the allocated memory for image is. This may be bigger + // or smaller than ImageFullSize - it will be bigger if necessary to + // ensure a power of 2, it will be smaller if the volume only covers a + // small region of the viewport + int ImageMemorySize[2]; + + // This is the size of subregion in ImageSize image that we are using for + // the current image. Since ImageSize is a power of 2, there is likely + // wasted space in it. This number will be used for things such as clearing + // the image if necessary. + int ImageInUseSize[2]; + + // This is the location in ImageFullSize image where our ImageSize image + // is located. + int ImageOrigin[2]; + + // This is the allocated image + unsigned char *Image; + + // This is the accumulating double RGBA image + float *RealRGBAImage; + + float *RenderTimeTable; + vtkVolume **RenderVolumeTable; + vtkRenderer **RenderRendererTable; + int RenderTableSize; + int RenderTableEntries; + + int IntermixIntersectingGeometry; + + float *ZBuffer; + int ZBufferSize[2]; + int ZBufferOrigin[2]; + + int ScalarMode; + char *ArrayName; + int ArrayId; + int ArrayAccessMode; + + vtkDataArray *Scalars; + int CellScalars; + + vtkSpan *Span; + vtkPixelListFrame *PixelListFrame; + + // Used by BuildUseSets(). + vtkGenericCell *Cell; + + vtkUseSet *UseSet; + + vtkPriorityQueue *EventList; + vtkVertices *Vertices; + + vtkTransform *PerspectiveTransform; + vtkMatrix4x4 *PerspectiveMatrix; + + // Used by the main loop + int MaxPixelListSizeReached; + int XBounds[2]; + int YBounds[2]; + + vtkSimpleScreenEdge *SimpleEdge; + vtkDoubleScreenEdge *DoubleEdge; + + vtkUnstructuredGridVolumeRayIntegrator *RayIntegrator; + vtkUnstructuredGridVolumeRayIntegrator *RealRayIntegrator; + + vtkTimeStamp SavedTriangleListMTime; + + // Used during compositing + vtkDoubleArray *IntersectionLengths; + vtkDoubleArray *NearIntersections; + vtkDoubleArray *FarIntersections; + + // Benchmark + vtkIdType MaxRecordedPixelListSize; + + + vtkPixelListEntryMemory *MemoryManager; +private: + vtkUnstructuredGridVolumeZSweepMapper(const vtkUnstructuredGridVolumeZSweepMapper&); // Not implemented. + void operator=(const vtkUnstructuredGridVolumeZSweepMapper&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkVRMLExporter.cxx b/Rendering/vtkVRMLExporter.cxx new file mode 100644 index 0000000..d5e3dfd --- /dev/null +++ b/Rendering/vtkVRMLExporter.cxx @@ -0,0 +1,713 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVRMLExporter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVRMLExporter.h" + +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkGeometryFilter.h" +#include "vtkImageData.h" +#include "vtkLight.h" +#include "vtkLightCollection.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRendererCollection.h" +#include "vtkTexture.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkVRMLExporter, "$Revision: 1.80 $"); +vtkStandardNewMacro(vtkVRMLExporter); + +vtkVRMLExporter::vtkVRMLExporter() +{ + this->Speed = 4.0; + this->FileName = NULL; + this->FilePointer = NULL; +} + +vtkVRMLExporter::~vtkVRMLExporter() +{ + if ( this->FileName ) + { + delete [] this->FileName; + } +} + +void vtkVRMLExporter::SetFilePointer(FILE *fp) +{ + if (fp != this->FilePointer) + { + this->Modified(); + this->FilePointer = fp; + } +} + + +void vtkVRMLExporter::WriteData() +{ + vtkRenderer *ren; + vtkActorCollection *ac; + vtkActor *anActor, *aPart; + vtkLightCollection *lc; + vtkLight *aLight; + vtkCamera *cam; + double *tempd; + FILE *fp; + + // make sure the user specified a FileName or FilePointer + if (!this->FilePointer && (this->FileName == NULL)) + { + vtkErrorMacro(<< "Please specify FileName to use"); + return; + } + + // first make sure there is only one renderer in this rendering window + if (this->RenderWindow->GetRenderers()->GetNumberOfItems() > 1) + { + vtkErrorMacro(<< "VRML files only support one renderer per window."); + return; + } + + // get the renderer + ren = this->RenderWindow->GetRenderers()->GetFirstRenderer(); + + // make sure it has at least one actor + if (ren->GetActors()->GetNumberOfItems() < 1) + { + vtkErrorMacro(<< "no actors found for writing VRML file."); + return; + } + + // try opening the files + if (!this->FilePointer) + { + fp = fopen(this->FileName,"w"); + if (!fp) + { + vtkErrorMacro(<< "unable to open VRML file " << this->FileName); + return; + } + } + else + { + fp = this->FilePointer; + } + + // + // Write header + // + vtkDebugMacro("Writing VRML file"); + fprintf(fp,"#VRML V2.0 utf8\n"); + fprintf(fp,"# VRML file written by the visualization toolkit\n\n"); + + // Start write the Background + double background[3]; + ren->GetBackground(background); + fprintf(fp," Background {\n "); + fprintf(fp," skyColor [%f %f %f, ]\n", background[0], + background[1], background[2]); + fprintf(fp," }\n "); + // End of Background + + // do the camera + cam = ren->GetActiveCamera(); + fprintf(fp," Viewpoint\n {\n fieldOfView %f\n", + cam->GetViewAngle()*3.1415926/180.0); + fprintf(fp," position %f %f %f\n",cam->GetPosition()[0], + cam->GetPosition()[1], cam->GetPosition()[2]); + fprintf(fp," description \"Default View\"\n"); + tempd = cam->GetOrientationWXYZ(); + fprintf(fp," orientation %g %g %g %g\n }\n", tempd[1], tempd[2], + tempd[3], tempd[0]*3.1415926/180.0); + + // do the lights first the ambient then the others + fprintf(fp," NavigationInfo {\n type [\"EXAMINE\",\"FLY\"]\n speed %f\n", this->Speed); + if (ren->GetLights()->GetNumberOfItems() == 0) + { + fprintf(fp," headlight TRUE}\n\n"); + } + else + { + fprintf(fp," headlight FALSE}\n\n"); + } + fprintf(fp," DirectionalLight { ambientIntensity 1 intensity 0 # ambient light\n"); + fprintf(fp," color %f %f %f }\n\n", ren->GetAmbient()[0], + ren->GetAmbient()[1], ren->GetAmbient()[2]); + + // make sure we have a default light + // if we dont then use a headlight + lc = ren->GetLights(); + vtkCollectionSimpleIterator lsit; + for (lc->InitTraversal(lsit); (aLight = lc->GetNextLight(lsit)); ) + { + this->WriteALight(aLight, fp); + } + + // do the actors now + ac = ren->GetActors(); + vtkAssemblyPath *apath; + vtkCollectionSimpleIterator ait; + for (ac->InitTraversal(ait); (anActor = ac->GetNextActor(ait)); ) + { + for (anActor->InitPathTraversal(); (apath=anActor->GetNextPath()); ) + { + aPart=(vtkActor *)apath->GetLastNode()->GetViewProp(); + this->WriteAnActor(aPart, fp); + } + } + + if (!this->FilePointer) + { + fclose(fp); + } +} + +void vtkVRMLExporter::WriteALight(vtkLight *aLight, FILE *fp) +{ + double *pos, *focus, *color; + double dir[3]; + + pos = aLight->GetPosition(); + focus = aLight->GetFocalPoint(); + color = aLight->GetColor(); + + dir[0] = focus[0] - pos[0]; + dir[1] = focus[1] - pos[1]; + dir[2] = focus[2] - pos[2]; + vtkMath::Normalize(dir); + + if (aLight->GetPositional()) + { + double *attn; + + if (aLight->GetConeAngle() >= 180.0) + { + fprintf(fp," PointLight {\n"); + } + else + { + fprintf(fp," SpotLight {\n"); + fprintf(fp," direction %f %f %f\n",dir[0], dir[1], dir[2]); + fprintf(fp," cutOffAngle %f\n", aLight->GetConeAngle()); + } + fprintf(fp," location %f %f %f\n", pos[0], pos[1], pos[2]); + attn = aLight->GetAttenuationValues(); + fprintf(fp," attenuation %f %f %f\n", attn[0], attn[1], attn[2]); + } + else + { + fprintf(fp," DirectionalLight {\n"); + fprintf(fp," direction %f %f %f\n",dir[0], dir[1], dir[2]); + } + + fprintf(fp," color %f %f %f\n", color[0], color[1], color[2]); + fprintf(fp," intensity %f\n", aLight->GetIntensity()); + if (aLight->GetSwitch()) + { + fprintf(fp," on TRUE\n }\n"); + } + else + { + fprintf(fp," on FALSE\n }\n"); + } +} + +void vtkVRMLExporter::WriteAnActor(vtkActor *anActor, FILE *fp) +{ + vtkDataSet *ds; + vtkPolyData *pd; + vtkGeometryFilter *gf = NULL; + vtkPointData *pntData; + vtkPoints *points; + vtkDataArray *normals = NULL; + vtkDataArray *tcoords = NULL; + int i, i1, i2; + vtkProperty *prop; + double *tempd; + vtkCellArray *cells; + vtkIdType npts = 0; + vtkIdType *indx = 0; + double tempf2; + int pointDataWritten = 0; + vtkPolyDataMapper *pm; + vtkUnsignedCharArray *colors; + double *p; + unsigned char *c; + vtkTransform *trans; + int totalValues; + + // see if the actor has a mapper. it could be an assembly + if (anActor->GetMapper() == NULL) + { + return; + } + + // first stuff out the transform + trans = vtkTransform::New(); + trans->SetMatrix(anActor->vtkProp3D::GetMatrix()); + + fprintf(fp," Transform {\n"); + tempd = trans->GetPosition(); + fprintf(fp," translation %g %g %g\n", tempd[0], tempd[1], tempd[2]); + tempd = trans->GetOrientationWXYZ(); + fprintf(fp," rotation %g %g %g %g\n", tempd[1], tempd[2], + tempd[3], tempd[0]*3.1415926/180.0); + tempd = trans->GetScale(); + fprintf(fp," scale %g %g %g\n", tempd[0], tempd[1], tempd[2]); + fprintf(fp," children [\n"); + trans->Delete(); + + // get the mappers input and matrix + ds = anActor->GetMapper()->GetInput(); + + // we really want polydata + if ( ds->GetDataObjectType() != VTK_POLY_DATA ) + { + gf = vtkGeometryFilter::New(); + gf->SetInput(ds); + gf->Update(); + pd = gf->GetOutput(); + } + else + { + pd = (vtkPolyData *)ds; + } + + pm = vtkPolyDataMapper::New(); + pm->SetInput(pd); + pm->SetScalarRange(anActor->GetMapper()->GetScalarRange()); + pm->SetScalarVisibility(anActor->GetMapper()->GetScalarVisibility()); + pm->SetLookupTable(anActor->GetMapper()->GetLookupTable()); + pm->SetScalarMode(anActor->GetMapper()->GetScalarMode()); + + if ( pm->GetScalarMode() == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA || + pm->GetScalarMode() == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + if ( anActor->GetMapper()->GetArrayAccessMode() == VTK_GET_ARRAY_BY_ID ) + { + pm->ColorByArrayComponent(anActor->GetMapper()->GetArrayId(), + anActor->GetMapper()->GetArrayComponent()); + } + else + { + pm->ColorByArrayComponent(anActor->GetMapper()->GetArrayName(), + anActor->GetMapper()->GetArrayComponent()); + } + } + + points = pd->GetPoints(); + pntData = pd->GetPointData(); + normals = pntData->GetNormals(); + tcoords = pntData->GetTCoords(); + colors = pm->MapScalars(1.0); + + fprintf(fp," Shape {\n"); + + // write out the material properties to the mat file + fprintf(fp," appearance Appearance {\n"); + fprintf(fp," material Material {\n"); + prop = anActor->GetProperty(); + fprintf(fp," ambientIntensity %g\n", prop->GetAmbient()); + // if we don't have colors and we have only lines & points + // use emissive to color them + if (!(normals || colors || pd->GetNumberOfPolys() || + pd->GetNumberOfStrips())) + { + tempf2 = prop->GetAmbient(); + tempd = prop->GetAmbientColor(); + fprintf(fp," emissiveColor %g %g %g\n", + tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); + } + tempf2 = prop->GetDiffuse(); + tempd = prop->GetDiffuseColor(); + fprintf(fp," diffuseColor %g %g %g\n", + tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); + tempf2 = prop->GetSpecular(); + tempd = prop->GetSpecularColor(); + fprintf(fp," specularColor %g %g %g\n", + tempd[0]*tempf2, tempd[1]*tempf2, tempd[2]*tempf2); + fprintf(fp," shininess %g\n",prop->GetSpecularPower()/128.0); + fprintf(fp," transparency %g\n",1.0 - prop->GetOpacity()); + fprintf(fp," }\n"); // close matrial + + // is there a texture map + if (anActor->GetTexture()) + { + vtkTexture *aTexture = anActor->GetTexture(); + int *size, xsize, ysize, bpp; + vtkDataArray *scalars; + vtkDataArray *mappedScalars; + unsigned char *txtrData; + + // make sure it is updated and then get some info + if (aTexture->GetInput() == NULL) + { + vtkErrorMacro(<< "texture has no input!\n"); + return; + } + aTexture->GetInput()->Update(); + size = aTexture->GetInput()->GetDimensions(); + scalars = aTexture->GetInput()->GetPointData()->GetScalars(); + + // make sure scalars are non null + if (!scalars) + { + vtkErrorMacro(<< "No scalar values found for texture input!\n"); + return; + } + + // make sure using unsigned char data of color scalars type + if (aTexture->GetMapColorScalarsThroughLookupTable () || + (scalars->GetDataType() != VTK_UNSIGNED_CHAR) ) + { + mappedScalars = aTexture->GetMappedScalars (); + } + else + { + mappedScalars = scalars; + } + + // we only support 2d texture maps right now + // so one of the three sizes must be 1, but it + // could be any of them, so lets find it + if (size[0] == 1) + { + xsize = size[1]; ysize = size[2]; + } + else + { + xsize = size[0]; + if (size[1] == 1) + { + ysize = size[2]; + } + else + { + ysize = size[1]; + if (size[2] != 1) + { + vtkErrorMacro(<< "3D texture maps currently are not supported!\n"); + return; + } + } + } + + fprintf(fp," texture PixelTexture {\n"); + bpp = mappedScalars->GetNumberOfComponents(); + fprintf(fp," image %i %i %i\n", xsize, ysize, bpp); + txtrData = static_cast(mappedScalars)->GetPointer(0); + totalValues = xsize*ysize; + for (i = 0; i < totalValues; i++) + { + fprintf(fp,"0x%.2x",*txtrData); + txtrData++; + if (bpp > 1) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (bpp > 2) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (bpp > 3) + { + fprintf(fp,"%.2x",*txtrData); + txtrData++; + } + if (i%8 == 0) + { + fprintf(fp,"\n"); + } + else + { + fprintf(fp," "); + } + } + if (!(aTexture->GetRepeat())) + { + fprintf(fp," repeatS FALSE\n"); + fprintf(fp," repeatT FALSE\n"); + } + fprintf(fp," }\n"); // close texture + } + fprintf(fp," }\n"); // close appearance + + // write out polys if any + if (pd->GetNumberOfPolys() > 0) + { + fprintf(fp," geometry IndexedFaceSet {\n"); + // two sided lighting ? for now assume it is on + fprintf(fp," solid FALSE\n"); + if (!pointDataWritten) + { + this->WritePointData(points, normals, tcoords, colors, fp); + pointDataWritten = 1; + } + else + { + fprintf(fp," coord USE VTKcoordinates\n"); + if (normals) + { + fprintf(fp," normal USE VTKnormals\n"); + } + if (tcoords) + { + fprintf(fp," texCoord USE VTKtcoords\n"); + } + if (colors) + { + fprintf(fp," color USE VTKcolors\n"); + } + } + + fprintf(fp," coordIndex [\n"); + + cells = pd->GetPolys(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp," "); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + } + fprintf(fp,"-1,\n"); + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + } + + // write out tstrips if any + if (pd->GetNumberOfStrips() > 0) + { + fprintf(fp," geometry IndexedFaceSet {\n"); + if (!pointDataWritten) + { + this->WritePointData(points, normals, tcoords, colors, fp); + pointDataWritten = 1; + } + else + { + fprintf(fp," coord USE VTKcoordinates\n"); + if (normals) + { + fprintf(fp," normal USE VTKnormals\n"); + } + if (tcoords) + { + fprintf(fp," texCoord USE VTKtcoords\n"); + } + if (colors) + { + fprintf(fp," color USE VTKcolors\n"); + } + } + fprintf(fp," coordIndex [\n"); + cells = pd->GetStrips(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + for (i = 2; i < npts; i++) + { + if (i%2) + { + i1 = i - 1; + i2 = i - 2; + } + else + { + i1 = i - 2; + i2 = i - 1; + } + // treating vtkIdType as int + fprintf(fp," %i, %i, %i, -1,\n", (int)indx[i1], + (int)indx[i2], (int)indx[i]); + } + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + } + + // write out lines if any + if (pd->GetNumberOfLines() > 0) + { + fprintf(fp," geometry IndexedLineSet {\n"); + if (!pointDataWritten) + { + this->WritePointData(points, NULL, NULL, colors, fp); + pointDataWritten = 1; + } + else + { + fprintf(fp," coord USE VTKcoordinates\n"); + if (colors) + { + fprintf(fp," color USE VTKcolors\n"); + } + } + + fprintf(fp," coordIndex [\n"); + + cells = pd->GetLines(); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp," "); + for (i = 0; i < npts; i++) + { + // treating vtkIdType as int + fprintf(fp,"%i, ", (int)indx[i]); + } + fprintf(fp,"-1,\n"); + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + } + + // write out verts if any + if (pd->GetNumberOfVerts() > 0) + { + fprintf(fp," geometry PointSet {\n"); + cells = pd->GetVerts(); + fprintf(fp," coord Coordinate {"); + fprintf(fp," point ["); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp," "); + for (i = 0; i < npts; i++) + { + p = points->GetPoint(indx[i]); + fprintf (fp," %g %g %g,\n", p[0], p[1], p[2]); + } + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + if (colors) + { + fprintf(fp," color Color {"); + fprintf(fp," color ["); + for (cells->InitTraversal(); cells->GetNextCell(npts,indx); ) + { + fprintf(fp," "); + for (i = 0; i < npts; i++) + { + c = colors->GetPointer(4*indx[i]); + fprintf (fp," %g %g %g,\n", c[0]/255.0, c[1]/255.0, + c[2]/255.0); + } + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + } + + fprintf(fp," }\n"); + } + + fprintf(fp," }\n"); // close the Shape + fprintf(fp," ]\n"); // close the original transforms children + fprintf(fp," }\n"); // close the original transform + + if (gf) + { + gf->Delete(); + } + pm->Delete(); +} + +void vtkVRMLExporter::WritePointData(vtkPoints *points, vtkDataArray *normals, + vtkDataArray *tcoords, + vtkUnsignedCharArray *colors, FILE *fp) +{ + double *p; + int i; + unsigned char *c; + + // write out the points + fprintf(fp," coord DEF VTKcoordinates Coordinate {\n"); + fprintf(fp," point [\n"); + for (i = 0; i < points->GetNumberOfPoints(); i++) + { + p = points->GetPoint(i); + fprintf (fp," %g %g %g,\n", p[0], p[1], p[2]); + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + + // write out the point data + if (normals) + { + fprintf(fp," normal DEF VTKnormals Normal {\n"); + fprintf(fp," vector [\n"); + for (i = 0; i < normals->GetNumberOfTuples(); i++) + { + p = normals->GetTuple(i); + fprintf (fp," %g %g %g,\n", p[0], p[1], p[2]); + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + } + + // write out the point data + if (tcoords) + { + fprintf(fp," texCoord DEF VTKtcoords TextureCoordinate {\n"); + fprintf(fp," point [\n"); + for (i = 0; i < tcoords->GetNumberOfTuples(); i++) + { + p = tcoords->GetTuple(i); + fprintf (fp," %g %g,\n", p[0], p[1]); + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + } + + // write out the point data + if (colors) + { + fprintf(fp," color DEF VTKcolors Color {\n"); + fprintf(fp," color [\n"); + for (i = 0; i < colors->GetNumberOfTuples(); i++) + { + c = colors->GetPointer(4*i); + fprintf (fp," %g %g %g,\n", c[0]/255.0, c[1]/255.0, + c[2]/255.0); + } + fprintf(fp," ]\n"); + fprintf(fp," }\n"); + } +} + + +void vtkVRMLExporter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if (this->FileName) + { + os << indent << "FileName: " << this->FileName << "\n"; + } + else + { + os << indent << "FileName: (null)\n"; + } + os << indent << "Speed: " << this->Speed << "\n"; +} + diff --git a/Rendering/vtkVRMLExporter.h b/Rendering/vtkVRMLExporter.h new file mode 100644 index 0000000..89b1fdb --- /dev/null +++ b/Rendering/vtkVRMLExporter.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVRMLExporter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVRMLExporter - export a scene into VRML 2.0 format. +// .SECTION Description +// vtkVRMLExporter is a concrete subclass of vtkExporter that writes VRML 2.0 +// files. This is based on the VRML 2.0 draft #3 but it should be pretty +// stable since we aren't using any of the newer features. +// +// .SECTION See Also +// vtkExporter + + +#ifndef __vtkVRMLExporter_h +#define __vtkVRMLExporter_h + +#include "vtkExporter.h" + +class vtkLight; +class vtkActor; +class vtkPoints; +class vtkDataArray; +class vtkUnsignedCharArray; + +class VTK_RENDERING_EXPORT vtkVRMLExporter : public vtkExporter +{ +public: + static vtkVRMLExporter *New(); + vtkTypeRevisionMacro(vtkVRMLExporter,vtkExporter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify the name of the VRML file to write. + vtkSetStringMacro(FileName); + vtkGetStringMacro(FileName); + + // Description: + // Specify the Speed of navigation. Default is 4. + vtkSetMacro(Speed,double); + vtkGetMacro(Speed,double); + + // Description: + // Set the file pointer to write to. This will override + // a FileName if specified. + void SetFilePointer(FILE *); + +protected: + vtkVRMLExporter(); + ~vtkVRMLExporter(); + + void WriteData(); + void WriteALight(vtkLight *aLight, FILE *fp); + void WriteAnActor(vtkActor *anActor, FILE *fp); + void WritePointData(vtkPoints *points, vtkDataArray *normals, + vtkDataArray *tcoords, vtkUnsignedCharArray *colors, + FILE *fp); + char *FileName; + FILE *FilePointer; + double Speed; +private: + vtkVRMLExporter(const vtkVRMLExporter&); // Not implemented. + void operator=(const vtkVRMLExporter&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkVolume.cxx b/Rendering/vtkVolume.cxx new file mode 100644 index 0000000..a66a51a --- /dev/null +++ b/Rendering/vtkVolume.cxx @@ -0,0 +1,827 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolume.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolume.h" + +#include "vtkCamera.h" +#include "vtkColorTransferFunction.h" +#include "vtkImageData.h" +#include "vtkLinearTransform.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" +#include "vtkPointData.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkVolumeCollection.h" +#include "vtkVolumeProperty.h" +#include "vtkAbstractVolumeMapper.h" + +#include + +vtkCxxRevisionMacro(vtkVolume, "$Revision: 1.83 $"); +vtkStandardNewMacro(vtkVolume); + +// Creates a Volume with the following defaults: origin(0,0,0) +// position=(0,0,0) scale=1 visibility=1 pickable=1 dragable=1 +// orientation=(0,0,0). +vtkVolume::vtkVolume() +{ + this->Mapper = NULL; + this->Property = NULL; + + for ( int i = 0; i < VTK_MAX_VRCOMP; i++ ) + { + this->ScalarOpacityArray[i] = NULL; + this->RGBArray[i] = NULL; + this->GrayArray[i] = NULL; + this->CorrectedScalarOpacityArray[i] = NULL; + } + + this->CorrectedStepSize = -1; + this->ArraySize = 0; +} + +// Destruct a volume +vtkVolume::~vtkVolume() +{ + if (this->Property ) + { + this->Property->UnRegister(this); + } + + this->SetMapper(NULL); + + for ( int i = 0; i < VTK_MAX_VRCOMP; i++ ) + { + if ( this->ScalarOpacityArray[i] ) + { + delete [] this->ScalarOpacityArray[i]; + } + + if ( this->RGBArray[i] ) + { + delete [] this->RGBArray[i]; + } + + if ( this->GrayArray[i] ) + { + delete [] this->GrayArray[i]; + } + + if ( this->CorrectedScalarOpacityArray[i] ) + { + delete [] this->CorrectedScalarOpacityArray[i]; + } + } +} + +void vtkVolume::GetVolumes(vtkPropCollection *vc) +{ + vc->AddItem(this); +} + +// Shallow copy of an volume. +void vtkVolume::ShallowCopy(vtkProp *prop) +{ + vtkVolume *v = vtkVolume::SafeDownCast(prop); + + if ( v != NULL ) + { + this->SetMapper(v->GetMapper()); + this->SetProperty(v->GetProperty()); + } + + // Now do superclass + this->vtkProp3D::ShallowCopy(prop); +} + +float *vtkVolume::GetScalarOpacityArray(int index) +{ + if ( index < 0 || index >= VTK_MAX_VRCOMP ) + { + vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << + "]: " << index ); + return NULL; + } + return this->ScalarOpacityArray[index]; +} + +float *vtkVolume::GetCorrectedScalarOpacityArray(int index) +{ + if ( index < 0 || index >= VTK_MAX_VRCOMP ) + { + vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << + "]: " << index ); + return NULL; + } + return this->CorrectedScalarOpacityArray[index]; +} + +float *vtkVolume::GetGradientOpacityArray(int index) +{ + if ( index < 0 || index >= VTK_MAX_VRCOMP ) + { + vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << + "]: " << index ); + return NULL; + } + return this->GradientOpacityArray[index]; +} + +float vtkVolume::GetGradientOpacityConstant(int index) +{ + if ( index < 0 || index >= VTK_MAX_VRCOMP ) + { + vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << + "]: " << index ); + return 0; + } + return this->GradientOpacityConstant[index]; +} + +float *vtkVolume::GetGrayArray(int index) +{ + if ( index < 0 || index >= VTK_MAX_VRCOMP ) + { + vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << + "]: " << index ); + return NULL; + } + return this->GrayArray[index]; +} + +float *vtkVolume::GetRGBArray(int index) +{ + if ( index < 0 || index >= VTK_MAX_VRCOMP ) + { + vtkErrorMacro("Index out of range [0-" << VTK_MAX_VRCOMP << + "]: " << index ); + return NULL; + } + return this->RGBArray[index]; +} + +void vtkVolume::SetMapper(vtkAbstractVolumeMapper *mapper) +{ + if (this->Mapper != mapper) + { + if (this->Mapper != NULL) + { + this->Mapper->UnRegister(this); + } + this->Mapper = mapper; + if (this->Mapper != NULL) + { + this->Mapper->Register(this); + } + this->Modified(); + } +} + +float vtkVolume::ComputeScreenCoverage( vtkViewport *vp ) +{ + float coverage = 1.0; + + vtkRenderer *ren = vtkRenderer::SafeDownCast( vp ); + + if ( ren ) + { + vtkCamera *cam = ren->GetActiveCamera(); + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + vtkMatrix4x4 *mat = cam->GetCompositePerspectiveTransformMatrix( + aspect[0]/aspect[1], 0.0, 1.0 ); + double *bounds = this->GetBounds(); + float minX = 1.0; + float maxX = -1.0; + float minY = 1.0; + float maxY = -1.0; + int i, j, k; + float p[4]; + for ( k = 0; k < 2; k++ ) + { + for ( j = 0; j < 2; j++ ) + { + for ( i = 0; i < 2; i++ ) + { + p[0] = bounds[i]; + p[1] = bounds[2+j]; + p[2] = bounds[4+k]; + p[3] = 1.0; + mat->MultiplyPoint( p, p ); + if ( p[3] ) + { + p[0] /= p[3]; + p[1] /= p[3]; + p[2] /= p[3]; + } + + minX = (p[0] < minX)?(p[0]):(minX); + minY = (p[1] < minY)?(p[1]):(minY); + maxX = (p[0] > maxX)?(p[0]):(maxX); + maxY = (p[1] > maxY)?(p[1]):(maxY); + } + } + } + + coverage = (maxX-minX)*(maxY-minY)*.25; + coverage = (coverage > 1.0 )?(1.0):(coverage); + coverage = (coverage < 0.0 )?(0.0):(coverage); + } + + + return coverage; +} + +// Get the bounds for this Volume as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax). +double *vtkVolume::GetBounds() +{ + int i,n; + double *bounds, bbox[24], *fptr; + + // get the bounds of the Mapper if we have one + if (!this->Mapper) + { + return this->Bounds; + } + + bounds = this->Mapper->GetBounds(); + // Check for the special case when the mapper's bounds are unknown + if (!bounds) + { + return bounds; + } + + // fill out vertices of a bounding box + bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5]; + bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5]; + bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5]; + bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5]; + bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4]; + bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4]; + bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4]; + bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4]; + + // save the old transform + this->Transform->Push(); + this->Transform->SetMatrix(this->GetMatrix()); + + // and transform into actors coordinates + fptr = bbox; + for (n = 0; n < 8; n++) + { + this->Transform->TransformPoint(fptr,fptr); + fptr += 3; + } + + this->Transform->Pop(); + + // now calc the new bounds + this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX; + this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX; + for (i = 0; i < 8; i++) + { + for (n = 0; n < 3; n++) + { + if (bbox[i*3+n] < this->Bounds[n*2]) + { + this->Bounds[n*2] = bbox[i*3+n]; + } + if (bbox[i*3+n] > this->Bounds[n*2+1]) + { + this->Bounds[n*2+1] = bbox[i*3+n]; + } + } + } + + return this->Bounds; +} + +// Get the minimum X bound +double vtkVolume::GetMinXBound( ) +{ + this->GetBounds(); + return this->Bounds[0]; +} + +// Get the maximum X bound +double vtkVolume::GetMaxXBound( ) +{ + this->GetBounds(); + return this->Bounds[1]; +} + +// Get the minimum Y bound +double vtkVolume::GetMinYBound( ) +{ + this->GetBounds(); + return this->Bounds[2]; +} + +// Get the maximum Y bound +double vtkVolume::GetMaxYBound( ) +{ + this->GetBounds(); + return this->Bounds[3]; +} + +// Get the minimum Z bound +double vtkVolume::GetMinZBound( ) +{ + this->GetBounds(); + return this->Bounds[4]; +} + +// Get the maximum Z bound +double vtkVolume::GetMaxZBound( ) +{ + this->GetBounds(); + return this->Bounds[5]; +} + +// If the volume mapper is of type VTK_FRAMEBUFFER_VOLUME_MAPPER, then +// this is its opportunity to render +int vtkVolume::RenderTranslucentGeometry( vtkViewport *vp ) +{ + this->Update(); + + if ( !this->Mapper ) + { + vtkErrorMacro( << "You must specify a mapper!\n" ); + return 0; + } + + // If we don't have any input return silently + if ( !this->Mapper->GetDataSetInput() ) + { + return 0; + } + + // Force the creation of a property + if( !this->Property ) + { + this->GetProperty(); + } + + if( !this->Property ) + { + vtkErrorMacro( << "Error generating a property!\n" ); + return 0; + } + + this->Mapper->Render( (vtkRenderer *)vp, this ); + this->EstimatedRenderTime += this->Mapper->GetTimeToDraw(); + + return 1; +} + + +void vtkVolume::ReleaseGraphicsResources(vtkWindow *win) +{ + // pass this information onto the mapper + if (this->Mapper) + { + this->Mapper->ReleaseGraphicsResources(win); + } +} + +void vtkVolume::Update() +{ + if ( this->Mapper ) + { + this->Mapper->Update(); + } +} + +void vtkVolume::SetProperty(vtkVolumeProperty *property) +{ + if( this->Property != property ) + { + if (this->Property != NULL) {this->Property->UnRegister(this);} + this->Property = property; + if (this->Property != NULL) + { + this->Property->Register(this); + this->Property->UpdateMTimes(); + } + this->Modified(); + } +} + +vtkVolumeProperty *vtkVolume::GetProperty() +{ + if( this->Property == NULL ) + { + this->Property = vtkVolumeProperty::New(); + this->Property->Register(this); + this->Property->Delete(); + } + return this->Property; +} + +unsigned long int vtkVolume::GetMTime() +{ + unsigned long mTime=this->vtkObject::GetMTime(); + unsigned long time; + + if ( this->Property != NULL ) + { + time = this->Property->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->UserMatrix != NULL ) + { + time = this->UserMatrix->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + if ( this->UserTransform != NULL ) + { + time = this->UserTransform->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + return mTime; +} + +unsigned long int vtkVolume::GetRedrawMTime() +{ + unsigned long mTime=this->GetMTime(); + unsigned long time; + + if ( this->Mapper != NULL ) + { + time = this->Mapper->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + if (this->GetMapper()->GetDataSetInput() != NULL) + { + this->GetMapper()->GetDataSetInput()->Update(); + time = this->Mapper->GetDataSetInput()->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + } + + if ( this->Property != NULL ) + { + time = this->Property->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + + int numComponents; + + if ( this->Mapper && this->Mapper->GetDataSetInput() && + this->Mapper->GetDataSetInput()->GetPointData() && + this->Mapper->GetDataSetInput()->GetPointData()->GetScalars() ) + { + numComponents = this->Mapper->GetDataSetInput()->GetPointData()-> + GetScalars()->GetNumberOfComponents(); + } + else + { + numComponents = 0; + } + + for ( int i = 0; i < numComponents; i++ ) + { + // Check the color transfer function (gray or rgb) + if ( this->Property->GetColorChannels(i) == 1 ) + { + time = this->Property->GetGrayTransferFunction(i)->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + else + { + time = this->Property->GetRGBTransferFunction(i)->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + + // check the scalar opacity function + time = this->Property->GetScalarOpacity(i)->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + + // check the gradient opacity function + time = this->Property->GetGradientOpacity(i)->GetMTime(); + mTime = ( time > mTime ? time : mTime ); + } + } + + return mTime; +} + +void vtkVolume::UpdateTransferFunctions( vtkRenderer *vtkNotUsed(ren) ) +{ + int dataType; + vtkPiecewiseFunction *sotf; + vtkPiecewiseFunction *gotf; + vtkPiecewiseFunction *graytf; + vtkColorTransferFunction *rgbtf; + int colorChannels; + + int arraySize; + + // Check that we have scalars + if ( this->Mapper == NULL || + this->Mapper->GetDataSetInput() == NULL || + this->Mapper->GetDataSetInput()->GetPointData() == NULL || + this->Mapper->GetDataSetInput()->GetPointData()->GetScalars() == NULL ) + { + vtkErrorMacro(<<"Need scalar data to volume render"); + return; + } + + // What is the type of the data? + dataType = this->Mapper->GetDataSetInput()-> + GetPointData()->GetScalars()->GetDataType(); + + if (dataType == VTK_UNSIGNED_CHAR) + { + arraySize = 256; + } + else if (dataType == VTK_UNSIGNED_SHORT) + { + arraySize = 65536; + } + else + { + vtkErrorMacro("Unsupported data type"); + return; + } + + int numComponents = this->Mapper->GetDataSetInput()->GetPointData()-> + GetScalars()->GetNumberOfComponents(); + + for ( int c = 0; c < numComponents; c++ ) + { + + // Did our array size change? If so, free up all our previous arrays + // and create new ones for the scalar opacity and corrected scalar + // opacity + if ( arraySize != this->ArraySize ) + { + if ( this->ScalarOpacityArray[c] ) + { + delete [] this->ScalarOpacityArray[c]; + this->ScalarOpacityArray[c] = NULL; + } + if ( this->CorrectedScalarOpacityArray[c] ) + { + delete [] this->CorrectedScalarOpacityArray[c]; + this->CorrectedScalarOpacityArray[c] = NULL; + } + if ( this->GrayArray[c] ) + { + delete [] this->GrayArray[c]; + this->GrayArray[c] = NULL; + } + if ( this->RGBArray[c] ) + { + delete [] this->RGBArray[c]; + this->RGBArray[c] = NULL; + } + + // Allocate these two because we know we need them + this->ScalarOpacityArray[c] = new float[arraySize]; + this->CorrectedScalarOpacityArray[c] = new float[arraySize]; + } + + // How many color channels for this component? + colorChannels = this->Property->GetColorChannels(c); + + // If we have 1 color channel and no gray array, create it. + // Free the rgb array if there is one. + if ( colorChannels == 1 ) + { + if ( this->RGBArray[c] ) + { + delete [] this->RGBArray[c]; + this->RGBArray[c] = NULL; + } + if ( !this->GrayArray[c] ) + { + this->GrayArray[c] = new float[arraySize]; + } + } + + // If we have 3 color channels and no rgb array, create it. + // Free the gray array if there is one. + if ( colorChannels == 3 ) + { + if ( this->GrayArray[c] ) + { + delete [] this->GrayArray[c]; + this->GrayArray[c] = NULL; + } + if ( !this->RGBArray[c] ) + { + this->RGBArray[c] = new float[3*arraySize]; + } + } + + // Get the various functions for this index. There is no chance of + // these being NULL since the property will create them if they were + // not defined + sotf = this->Property->GetScalarOpacity(c); + gotf = this->Property->GetGradientOpacity(c); + + if ( colorChannels == 1 ) + { + rgbtf = NULL; + graytf = this->Property->GetGrayTransferFunction(c); + } + else + { + rgbtf = this->Property->GetRGBTransferFunction(c); + graytf = NULL; + } + + + // Update the scalar opacity array if necessary + if ( sotf->GetMTime() > + this->ScalarOpacityArrayMTime[c] || + this->Property->GetScalarOpacityMTime(c) > + this->ScalarOpacityArrayMTime[c] ) + { + sotf->GetTable( 0.0, static_cast(arraySize-1), + arraySize, this->ScalarOpacityArray[c] ); + this->ScalarOpacityArrayMTime[c].Modified(); + } + + // Update the gradient opacity array if necessary + if ( gotf->GetMTime() > + this->GradientOpacityArrayMTime[c] || + this->Property->GetGradientOpacityMTime(c) > + this->GradientOpacityArrayMTime[c] ) + { + // Get values according to scale/bias from mapper 256 values are + // in the table, the scale / bias values control what those 256 values + // mean. + float scale = this->Mapper->GetGradientMagnitudeScale(c); + float bias = this->Mapper->GetGradientMagnitudeBias(c); + + float low = -bias; + float high = 255 / scale - bias; + + gotf->GetTable( low, high, (int)(0x100), this->GradientOpacityArray[c] ); + + if ( !strcmp(gotf->GetType(), "Constant") ) + { + this->GradientOpacityConstant[c] = this->GradientOpacityArray[c][0]; + } + else + { + this->GradientOpacityConstant[c] = -1.0; + } + + this->GradientOpacityArrayMTime[c].Modified(); + } + + // Update the RGB or Gray transfer function if necessary + if ( colorChannels == 1 ) + { + if ( graytf->GetMTime() > + this->GrayArrayMTime[c] || + this->Property->GetGrayTransferFunctionMTime(c) > + this->GrayArrayMTime[c] ) + { + graytf->GetTable( 0.0, static_cast(arraySize-1), + arraySize, this->GrayArray[c] ); + this->GrayArrayMTime[c].Modified(); + } + } + else + { + if ( rgbtf->GetMTime() > + this->RGBArrayMTime[c] || + this->Property->GetRGBTransferFunctionMTime(c) > + this->RGBArrayMTime[c] ) + { + rgbtf->GetTable( 0.0, static_cast(arraySize-1), + arraySize, this->RGBArray[c] ); + this->RGBArrayMTime[c].Modified(); + } + } + } + + // reset the array size to the current size + this->ArraySize = arraySize; +} + +// This method computes the corrected alpha blending for a given +// step size. The ScalarOpacityArray reflects step size 1. +// The CorrectedScalarOpacityArray reflects step size CorrectedStepSize. +void vtkVolume::UpdateScalarOpacityforSampleSize( vtkRenderer *vtkNotUsed(ren), + float sample_distance ) +{ + int i; + int needsRecomputing; + float originalAlpha,correctedAlpha; + float ray_scale; + + ray_scale = sample_distance; + + // step size changed + needsRecomputing = + this->CorrectedStepSize-ray_scale > 0.0001; + + needsRecomputing = needsRecomputing || + this->CorrectedStepSize-ray_scale < -0.0001; + + // Check that we have scalars + if ( this->Mapper == NULL || + this->Mapper->GetDataSetInput() == NULL || + this->Mapper->GetDataSetInput()->GetPointData() == NULL || + this->Mapper->GetDataSetInput()->GetPointData()->GetScalars() == NULL ) + { + vtkErrorMacro(<<"Need scalar data to volume render"); + return; + } + + int numComponents = this->Mapper->GetDataSetInput()->GetPointData()-> + GetScalars()->GetNumberOfComponents(); + + if ( needsRecomputing ) + { + this->CorrectedStepSize = ray_scale; + } + + for ( int c = 0; c < numComponents; c++ ) + { + if (needsRecomputing || + this->ScalarOpacityArrayMTime[c] > + this->CorrectedScalarOpacityArrayMTime[c]) + { + this->CorrectedScalarOpacityArrayMTime[c].Modified(); + + for (i = 0; i < this->ArraySize; i++) + { + originalAlpha = *(this->ScalarOpacityArray[c]+i); + + // this test is to accelerate the Transfer function correction + if (originalAlpha > 0.0001) + { + correctedAlpha = + 1.0-pow((double)(1.0-originalAlpha), + double(this->CorrectedStepSize)); + } + else + { + correctedAlpha = originalAlpha; + } + *(this->CorrectedScalarOpacityArray[c]+i) = correctedAlpha; + } + } + } +} + + +void vtkVolume::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if( this->Property ) + { + os << indent << "Property:\n"; + this->Property->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Property: (not defined)\n"; + } + + if( this->Mapper ) + { + os << indent << "Mapper:\n"; + this->Mapper->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Mapper: (not defined)\n"; + } + + // make sure our bounds are up to date + if ( this->Mapper ) + { + this->GetBounds(); + os << indent << "Bounds: (" << this->Bounds[0] << ", " + << this->Bounds[1] << ") (" << this->Bounds[2] << ") (" + << this->Bounds[3] << ") (" << this->Bounds[4] << ") (" + << this->Bounds[5] << ")\n"; + } + else + { + os << indent << "Bounds: (not defined)\n"; + } +} + diff --git a/Rendering/vtkVolume.h b/Rendering/vtkVolume.h new file mode 100644 index 0000000..576591f --- /dev/null +++ b/Rendering/vtkVolume.h @@ -0,0 +1,230 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolume.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolume - represents a volume (data & properties) in a rendered scene +// +// .SECTION Description +// vtkVolume is used to represent a volumetric entity in a rendering scene. +// It inherits functions related to the volume's position, orientation and +// origin from vtkProp3D. The volume maintains a reference to the +// volumetric data (i.e., the volume mapper). The volume also contains a +// reference to a volume property which contains all common volume rendering +// parameters. + +// .SECTION see also +// vtkAbstractVolumeMapper vtkVolumeProperty vtkProp3D + +#ifndef __vtkVolume_h +#define __vtkVolume_h + +#include "vtkProp3D.h" + +class vtkRenderer; +class vtkPropCollection; +class vtkVolumeCollection; +class vtkWindow; +class vtkVolumeProperty; +class vtkAbstractVolumeMapper; + +class VTK_RENDERING_EXPORT vtkVolume : public vtkProp3D +{ +public: + vtkTypeRevisionMacro(vtkVolume,vtkProp3D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Creates a Volume with the following defaults: origin(0,0,0) + // position=(0,0,0) scale=1 visibility=1 pickable=1 dragable=1 + // orientation=(0,0,0). + static vtkVolume *New(); + + // Description: + // Set/Get the volume mapper. + void SetMapper(vtkAbstractVolumeMapper *mapper); + vtkGetObjectMacro(Mapper, vtkAbstractVolumeMapper); + + // Description: + // Set/Get the volume property. + void SetProperty(vtkVolumeProperty *property); + vtkVolumeProperty *GetProperty(); + + // Description: + // For some exporters and other other operations we must be + // able to collect all the actors or volumes. This method + // is used in that process. + void GetVolumes(vtkPropCollection *vc); + + // Description: + // Update the volume rendering pipeline by updating the volume mapper + void Update(); + + // Description: + // Get the bounds - either all six at once + // (xmin, xmax, ymin, ymax, zmin, zmax) or one at a time. + double *GetBounds(); + void GetBounds(double bounds[6]) { this->vtkProp3D::GetBounds( bounds ); }; + double GetMinXBound(); + double GetMaxXBound(); + double GetMinYBound(); + double GetMaxYBound(); + double GetMinZBound(); + double GetMaxZBound(); + + // Description: + // Return the MTime also considering the property etc. + unsigned long int GetMTime(); + + // Description: + // Return the mtime of anything that would cause the rendered image to + // appear differently. Usually this involves checking the mtime of the + // prop plus anything else it depends on such as properties, mappers, + // etc. + unsigned long GetRedrawMTime(); + + // Description: + // Shallow copy of this vtkVolume. Overloads the virtual vtkProp method. + void ShallowCopy(vtkProp *prop); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Support the standard render methods. + // Depending on the mapper type, the volume may be rendered using + // this method (FRAMEBUFFER volume such as texture mapping will + // be rendered this way) + int RenderTranslucentGeometry(vtkViewport *viewport); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Release any graphics resources that are being consumed by this volume. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + float *GetCorrectedScalarOpacityArray(int); + float *GetCorrectedScalarOpacityArray() + {return this->GetCorrectedScalarOpacityArray(0);}; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + float *GetScalarOpacityArray(int); + float *GetScalarOpacityArray(){return this->GetScalarOpacityArray(0);}; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + float *GetGradientOpacityArray(int); + float *GetGradientOpacityArray(){return this->GetGradientOpacityArray(0);}; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + float *GetGrayArray(int); + float *GetGrayArray(){return this->GetGrayArray(0);}; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + float *GetRGBArray(int); + float *GetRGBArray(){return this->GetRGBArray(0);}; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + float GetGradientOpacityConstant(int); + float GetGradientOpacityConstant() + {return this->GetGradientOpacityConstant(0);}; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + float GetArraySize () { return static_cast(this->ArraySize); }; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + void UpdateTransferFunctions( vtkRenderer *ren ); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + void UpdateScalarOpacityforSampleSize( vtkRenderer *ren, + float sample_distance ); + +//ETX + +protected: + vtkVolume(); + ~vtkVolume(); + + vtkAbstractVolumeMapper *Mapper; + vtkVolumeProperty *Property; + + // The rgb transfer function array - for unsigned char data this + // is 256 elements, for short or unsigned short it is 65536 elements + // This is a sample at each scalar value of the rgb transfer + // function. A time stamp is kept to know when it needs rebuilding + float *RGBArray[VTK_MAX_VRCOMP]; + vtkTimeStamp RGBArrayMTime[VTK_MAX_VRCOMP]; + + // The gray transfer function array - for unsigned char data this + // is 256 elements, for short or unsigned short it is 65536 elements + // This is a sample at each scalar value of the gray transfer + // function. A time stamp is kept to know when it needs rebuilding + float *GrayArray[VTK_MAX_VRCOMP]; + vtkTimeStamp GrayArrayMTime[VTK_MAX_VRCOMP]; + + // The scalar opacity transfer function array - for unsigned char data this + // is 256 elements, for short or unsigned short it is 65536 elements + // This is a sample at each scalar value of the opacity transfer + // function. A time stamp is kept to know when it needs rebuilding + float *ScalarOpacityArray[VTK_MAX_VRCOMP]; + vtkTimeStamp ScalarOpacityArrayMTime[VTK_MAX_VRCOMP]; + + // The corrected scalar opacity transfer function array - this is identical + // to the opacity transfer function array when the step size is 1. + // In other cases, it is corrected to reflect the new material thickness + // modeled by a step size different than 1. + float *CorrectedScalarOpacityArray[VTK_MAX_VRCOMP]; + vtkTimeStamp CorrectedScalarOpacityArrayMTime[VTK_MAX_VRCOMP]; + + // CorrectedStepSize is the step size currently modeled by + // CorrectedArray. It is used to determine when the + // CorrectedArray needs to be updated to match SampleDistance + // in the volume mapper. + float CorrectedStepSize; + + // Number of elements in the rgb, gray, and opacity transfer function arrays + int ArraySize; + + // The magnitude of gradient opacity transfer function array + float GradientOpacityArray[VTK_MAX_VRCOMP][256]; + float GradientOpacityConstant[VTK_MAX_VRCOMP]; + vtkTimeStamp GradientOpacityArrayMTime[VTK_MAX_VRCOMP]; + + // Function to compute screen coverage of this volume + float ComputeScreenCoverage( vtkViewport *vp ); + +private: + vtkVolume(const vtkVolume&); // Not implemented. + void operator=(const vtkVolume&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkVolumeCollection.cxx b/Rendering/vtkVolumeCollection.cxx new file mode 100644 index 0000000..0defb18 --- /dev/null +++ b/Rendering/vtkVolumeCollection.cxx @@ -0,0 +1,25 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeCollection.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeCollection.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkVolumeCollection, "$Revision: 1.8 $"); +vtkStandardNewMacro(vtkVolumeCollection); + +//---------------------------------------------------------------------------- +void vtkVolumeCollection::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkVolumeCollection.h b/Rendering/vtkVolumeCollection.h new file mode 100644 index 0000000..e1dcef2 --- /dev/null +++ b/Rendering/vtkVolumeCollection.h @@ -0,0 +1,84 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeCollection.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeCollection - a list of volumes +// .SECTION Description +// vtkVolumeCollection represents and provides methods to manipulate a +// list of volumes (i.e., vtkVolume and subclasses). The list is unsorted +// and duplicate entries are not prevented. + +// .SECTION see also +// vtkCollection vtkVolume + +#ifndef __vtkVolumeC_h +#define __vtkVolumeC_h + +#include "vtkPropCollection.h" + +#include "vtkVolume.h" // Needed for static cast + +class VTK_RENDERING_EXPORT vtkVolumeCollection : public vtkPropCollection +{ + public: + static vtkVolumeCollection *New(); + vtkTypeRevisionMacro(vtkVolumeCollection,vtkPropCollection); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Add a Volume to the list. + void AddItem(vtkVolume *a) { + this->vtkCollection::AddItem((vtkObject *)a);}; + + // Description: + // Get the next Volume in the list. Return NULL when at the end of the + // list. + vtkVolume *GetNextVolume() { + return static_cast(this->GetNextItemAsObject());}; + + + // Description: + // Access routine provided for compatibility with previous + // versions of VTK. Please use the GetNextVolume() variant + // where possible. + vtkVolume *GetNextItem() { return this->GetNextVolume(); }; + + //BTX + // Description: + // Reentrant safe way to get an object in a collection. Just pass the + // same cookie back and forth. + vtkVolume *GetNextVolume(vtkCollectionSimpleIterator &cookie) { + return static_cast(this->GetNextItemAsObject(cookie));}; + //ETX + +protected: + vtkVolumeCollection() {}; + ~vtkVolumeCollection() {}; + +private: + // hide the standard AddItem from the user and the compiler. + void AddItem(vtkObject *o) { this->vtkCollection::AddItem(o); }; + void AddItem(vtkProp *o) { this->vtkPropCollection::AddItem(o); }; + +private: + vtkVolumeCollection(const vtkVolumeCollection&); // Not implemented. + void operator=(const vtkVolumeCollection&); // Not implemented. +}; + + +#endif + + + + + diff --git a/Rendering/vtkVolumeProperty.cxx b/Rendering/vtkVolumeProperty.cxx new file mode 100644 index 0000000..388f243 --- /dev/null +++ b/Rendering/vtkVolumeProperty.cxx @@ -0,0 +1,613 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeProperty.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeProperty.h" + +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" +#include "vtkColorTransferFunction.h" + +vtkCxxRevisionMacro(vtkVolumeProperty, "$Revision: 1.41 $"); +vtkStandardNewMacro(vtkVolumeProperty); + +// Construct a new vtkVolumeProperty with default values +vtkVolumeProperty::vtkVolumeProperty() +{ + this->IndependentComponents = 1; + + this->InterpolationType = VTK_NEAREST_INTERPOLATION; + + for ( int i = 0; i < VTK_MAX_VRCOMP; i++ ) + { + this->ColorChannels[i] = 1; + + this->GrayTransferFunction[i] = NULL; + this->RGBTransferFunction[i] = NULL; + this->ScalarOpacity[i] = NULL; + this->ScalarOpacityUnitDistance[i] = 1.0; + this->GradientOpacity[i] = NULL; + this->DefaultGradientOpacity[i] = NULL; + this->DisableGradientOpacity[i] = 0; + + this->ComponentWeight[i] = 1.0; + + this->Shade[i] = 0; + this->Ambient[i] = 0.1; + this->Diffuse[i] = 0.7; + this->Specular[i] = 0.2; + this->SpecularPower[i] = 10.0; + } +} + +// Destruct a vtkVolumeProperty +vtkVolumeProperty::~vtkVolumeProperty() +{ + for ( int i = 0; i < VTK_MAX_VRCOMP; i++ ) + { + if (this->GrayTransferFunction[i] != NULL) + { + this->GrayTransferFunction[i]->UnRegister(this); + } + + if (this->RGBTransferFunction[i] != NULL) + { + this->RGBTransferFunction[i]->UnRegister(this); + } + + if (this->ScalarOpacity[i] != NULL) + { + this->ScalarOpacity[i]->UnRegister(this); + } + + if (this->GradientOpacity[i] != NULL) + { + this->GradientOpacity[i]->UnRegister(this); + } + + if (this->DefaultGradientOpacity[i] != NULL) + { + this->DefaultGradientOpacity[i]->UnRegister(this); + } + } +} + +void vtkVolumeProperty::UpdateMTimes() +{ + this->Modified(); + + for ( int i = 0; i < VTK_MAX_VRCOMP; i++ ) + { + this->GrayTransferFunctionMTime[i].Modified(); + this->RGBTransferFunctionMTime[i].Modified(); + this->ScalarOpacityMTime[i].Modified(); + this->GradientOpacityMTime[i].Modified(); + } +} + +unsigned long int vtkVolumeProperty::GetMTime() +{ + unsigned long mTime=this->vtkObject::GetMTime(); + unsigned long time; + + for ( int i = 0; i < VTK_MAX_VRCOMP; i++ ) + { + // Color MTimes + if (this->ColorChannels[i] == 1) + { + if (this->GrayTransferFunction[i]) + { + // time that Gray transfer function pointer was set + time = this->GrayTransferFunctionMTime[i]; + mTime = (mTime > time ? mTime : time); + + // time that Gray transfer function was last modified + time = this->GrayTransferFunction[i]->GetMTime(); + mTime = (mTime > time ? mTime : time); + } + } + else if (this->ColorChannels[i] == 3) + { + if (this->RGBTransferFunction[i]) + { + // time that RGB transfer function pointer was set + time = this->RGBTransferFunctionMTime[i]; + mTime = (mTime > time ? mTime : time); + + // time that RGB transfer function was last modified + time = this->RGBTransferFunction[i]->GetMTime(); + mTime = (mTime > time ? mTime : time); + } + } + + // Opacity MTimes + if (this->ScalarOpacity[i]) + { + // time that Scalar opacity transfer function pointer was set + time = this->ScalarOpacityMTime[i]; + mTime = (mTime > time ? mTime : time); + + // time that Scalar opacity transfer function was last modified + time = this->ScalarOpacity[i]->GetMTime(); + mTime = (mTime > time ? mTime : time); + } + + if (this->GradientOpacity[i]) + { + // time that Gradient opacity transfer function pointer was set + time = this->GradientOpacityMTime[i]; + mTime = (mTime > time ? mTime : time); + + if (!this->DisableGradientOpacity[i]) + { + // time that Gradient opacity transfer function was last modified + time = this->GradientOpacity[i]->GetMTime(); + mTime = (mTime > time ? mTime : time); + } + } + } + + return mTime; +} + +int vtkVolumeProperty::GetColorChannels( int index ) +{ + if ( index < 0 || index > 3 ) + { + vtkErrorMacro("Bad index - must be between 0 and 3"); + return 0; + } + + return this->ColorChannels[index]; +} + + +// Set the color of a volume to a gray transfer function +void vtkVolumeProperty::SetColor( int index, vtkPiecewiseFunction *function ) +{ + if (this->GrayTransferFunction[index] != function ) + { + if (this->GrayTransferFunction[index] != NULL) + { + this->GrayTransferFunction[index]->UnRegister(this); + } + this->GrayTransferFunction[index] = function; + if (this->GrayTransferFunction[index] != NULL) + { + this->GrayTransferFunction[index]->Register(this); + } + + this->GrayTransferFunctionMTime[index].Modified(); + this->Modified(); + } + + if (this->ColorChannels[index] != 1) + { + this->ColorChannels[index] = 1; + this->Modified(); + } +} + +// Get the currently set gray transfer function. Create one if none set. +vtkPiecewiseFunction *vtkVolumeProperty::GetGrayTransferFunction( int index ) +{ + if (this->GrayTransferFunction[index] == NULL ) + { + this->GrayTransferFunction[index] = vtkPiecewiseFunction::New(); + this->GrayTransferFunction[index]->Register(this); + this->GrayTransferFunction[index]->Delete(); + this->GrayTransferFunction[index]->AddPoint( 0, 0.0 ); + this->GrayTransferFunction[index]->AddPoint( 1024, 1.0 ); + if (this->ColorChannels[index] != 1) + { + this->ColorChannels[index] = 1; + } + this->Modified(); + } + + return this->GrayTransferFunction[index]; +} + +// Set the color of a volume to an RGB transfer function +void vtkVolumeProperty::SetColor( int index, vtkColorTransferFunction *function ) +{ + if (this->RGBTransferFunction[index] != function ) + { + if (this->RGBTransferFunction[index] != NULL) + { + this->RGBTransferFunction[index]->UnRegister(this); + } + this->RGBTransferFunction[index] = function; + if (this->RGBTransferFunction[index] != NULL) + { + this->RGBTransferFunction[index]->Register(this); + } + this->RGBTransferFunctionMTime[index].Modified(); + this->Modified(); + } + + if (this->ColorChannels[index] != 3) + { + this->ColorChannels[index] = 3; + this->Modified(); + } +} + +// Get the currently set RGB transfer function. Create one if none set. +vtkColorTransferFunction *vtkVolumeProperty::GetRGBTransferFunction( int index ) +{ + if (this->RGBTransferFunction[index] == NULL ) + { + this->RGBTransferFunction[index] = vtkColorTransferFunction::New(); + this->RGBTransferFunction[index]->Register(this); + this->RGBTransferFunction[index]->Delete(); + this->RGBTransferFunction[index]->AddRGBPoint( 0, 0.0, 0.0, 0.0 ); + this->RGBTransferFunction[index]->AddRGBPoint( 1024, 1.0, 1.0, 1.0 ); + if (this->ColorChannels[index] != 3) + { + this->ColorChannels[index] = 3; + } + this->Modified(); + } + + return this->RGBTransferFunction[index]; +} + +// Set the scalar opacity of a volume to a transfer function +void vtkVolumeProperty::SetScalarOpacity( int index, vtkPiecewiseFunction *function ) +{ + if ( this->ScalarOpacity[index] != function ) + { + if (this->ScalarOpacity[index] != NULL) + { + this->ScalarOpacity[index]->UnRegister(this); + } + this->ScalarOpacity[index] = function; + if (this->ScalarOpacity[index] != NULL) + { + this->ScalarOpacity[index]->Register(this); + } + + this->ScalarOpacityMTime[index].Modified(); + this->Modified(); + } +} + +// Get the scalar opacity transfer function. Create one if none set. +vtkPiecewiseFunction *vtkVolumeProperty::GetScalarOpacity( int index ) +{ + if( this->ScalarOpacity[index] == NULL ) + { + this->ScalarOpacity[index] = vtkPiecewiseFunction::New(); + this->ScalarOpacity[index]->Register(this); + this->ScalarOpacity[index]->Delete(); + this->ScalarOpacity[index]->AddPoint( 0, 1.0 ); + this->ScalarOpacity[index]->AddPoint( 1024, 1.0 ); + } + + return this->ScalarOpacity[index]; +} + +void vtkVolumeProperty::SetScalarOpacityUnitDistance( int index, double distance ) +{ + if ( index < 0 || index > 3 ) + { + vtkErrorMacro("Bad index - must be between 0 and 3"); + return; + } + + if ( this->ScalarOpacityUnitDistance[index] != distance ) + { + this->ScalarOpacityUnitDistance[index] = distance; + this->Modified(); + } +} + +double vtkVolumeProperty::GetScalarOpacityUnitDistance( int index ) +{ + if ( index < 0 || index > 3 ) + { + vtkErrorMacro("Bad index - must be between 0 and 3"); + return 0; + } + + return this->ScalarOpacityUnitDistance[index]; +} + + +// Set the gradient opacity transfer function +void vtkVolumeProperty::SetGradientOpacity( int index, vtkPiecewiseFunction *function ) +{ + if ( this->GradientOpacity[index] != function ) + { + if (this->GradientOpacity[index] != NULL) + { + this->GradientOpacity[index]->UnRegister(this); + } + this->GradientOpacity[index] = function; + if (this->GradientOpacity[index] != NULL) + { + this->GradientOpacity[index]->Register(this); + } + + this->GradientOpacityMTime[index].Modified(); + this->Modified(); + } +} + +void vtkVolumeProperty::CreateDefaultGradientOpacity( int index ) +{ + if ( this->DefaultGradientOpacity[index] == NULL ) + { + this->DefaultGradientOpacity[index] = vtkPiecewiseFunction::New(); + this->DefaultGradientOpacity[index]->Register(this); + this->DefaultGradientOpacity[index]->Delete(); + } + + this->DefaultGradientOpacity[index]->RemoveAllPoints(); + this->DefaultGradientOpacity[index]->AddPoint( 0, 1.0 ); + this->DefaultGradientOpacity[index]->AddPoint( 255, 1.0 ); +} + +vtkPiecewiseFunction *vtkVolumeProperty::GetGradientOpacity( int index ) +{ + if (this->DisableGradientOpacity[index]) + { + if ( this->DefaultGradientOpacity[index] == NULL ) + { + this->CreateDefaultGradientOpacity(index); + } + return this->DefaultGradientOpacity[index]; + } + + return this->GetStoredGradientOpacity(index); +} + +// Get the gradient opacity transfer function. Create one if none set. +vtkPiecewiseFunction *vtkVolumeProperty::GetStoredGradientOpacity( int index ) +{ + if ( this->GradientOpacity[index] == NULL ) + { + this->GradientOpacity[index] = vtkPiecewiseFunction::New(); + this->GradientOpacity[index]->Register(this); + this->GradientOpacity[index]->Delete(); + this->GradientOpacity[index]->AddPoint( 0, 1.0 ); + this->GradientOpacity[index]->AddPoint( 255, 1.0 ); + } + + return this->GradientOpacity[index]; +} + +void vtkVolumeProperty::SetDisableGradientOpacity( int index, int value ) +{ + if (this->DisableGradientOpacity[index] == value) + { + return; + } + + this->DisableGradientOpacity[index] = value; + + // Make sure the default function is up-to-date (since the user + // could have modified the default function) + + if (value) + { + this->CreateDefaultGradientOpacity(index); + } + + // Since this Ivar basically "sets" the gradient opacity function to be + // either a default one or the user-specified one, update the MTime + // accordingly + + this->GradientOpacityMTime[index].Modified(); + + this->Modified(); +} + +int vtkVolumeProperty::GetDisableGradientOpacity( int index ) +{ + return this->DisableGradientOpacity[index]; +} + +void vtkVolumeProperty::SetComponentWeight(int index, double value) +{ + if (index < 0 || index >= VTK_MAX_VRCOMP) + { + vtkErrorMacro("Invalid index"); + return; + } + + if (this->ComponentWeight[index] == value) + { + return; + } + + this->ComponentWeight[index] = value; + this->Modified(); +} + +double vtkVolumeProperty::GetComponentWeight(int index) +{ + if (index < 0 || index >= VTK_MAX_VRCOMP) + { + vtkErrorMacro("Invalid index"); + return 0.0; + } + + return this->ComponentWeight[index]; +} + +void vtkVolumeProperty::SetShade( int index, int value ) +{ + if ( value != 0 && value != 1 ) + { + vtkErrorMacro("SetShade accepts values 0 or 1"); + return; + } + + if ( this->Shade[index] != value ) + { + this->Shade[index] = value; + this->Modified(); + } +} + +void vtkVolumeProperty::ShadeOn( int index ) +{ + this->SetShade( index, 1 ); +} + + +void vtkVolumeProperty::ShadeOff( int index ) +{ + this->SetShade( index, 0 ); +} + + +int vtkVolumeProperty::GetShade( int index ) +{ + return this->Shade[index]; +} + +void vtkVolumeProperty::SetAmbient( int index, double value ) +{ + if ( this->Ambient[index] != value ) + { + this->Ambient[index] = value; + this->Modified(); + } +} + +double vtkVolumeProperty::GetAmbient( int index ) +{ + return this->Ambient[index]; +} + +void vtkVolumeProperty::SetDiffuse( int index, double value ) +{ + if ( this->Diffuse[index] != value ) + { + this->Diffuse[index] = value; + this->Modified(); + } +} + +double vtkVolumeProperty::GetDiffuse( int index ) +{ + return this->Diffuse[index]; +} + +void vtkVolumeProperty::SetSpecular( int index, double value ) +{ + if ( this->Specular[index] != value ) + { + this->Specular[index] = value; + this->Modified(); + } +} + +double vtkVolumeProperty::GetSpecular( int index ) +{ + return this->Specular[index]; +} + +void vtkVolumeProperty::SetSpecularPower( int index, double value ) +{ + if ( this->SpecularPower[index] != value ) + { + this->SpecularPower[index] = value; + this->Modified(); + } +} + +double vtkVolumeProperty::GetSpecularPower( int index ) +{ + return this->SpecularPower[index]; +} + +vtkTimeStamp vtkVolumeProperty::GetScalarOpacityMTime( int index ) +{ + return this->ScalarOpacityMTime[index]; +} + +vtkTimeStamp vtkVolumeProperty::GetGradientOpacityMTime( int index ) +{ + return this->GradientOpacityMTime[index]; +} + +vtkTimeStamp vtkVolumeProperty::GetRGBTransferFunctionMTime( int index ) +{ + return this->RGBTransferFunctionMTime[index]; +} + +vtkTimeStamp vtkVolumeProperty::GetGrayTransferFunctionMTime( int index ) +{ + return this->GrayTransferFunctionMTime[index]; +} + +// Print the state of the volume property. +void vtkVolumeProperty::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Independent Components: " << + (this->IndependentComponents ? "On\n" : "Off\n"); + + os << indent << "Interpolation Type: " + << this->GetInterpolationTypeAsString() << "\n"; + + for ( int i = 0; i < VTK_MAX_VRCOMP; i++ ) + { + os << indent << "Properties for material " << i << endl; + + os << indent << "Color Channels: " << this->ColorChannels[i] << "\n"; + + if( this->ColorChannels[i] == 1 ) + { + os << indent << "Gray Color Transfer Function: " + << this->GrayTransferFunction[i] << "\n"; + } + else if( this->ColorChannels[i] == 3 ) + { + os << indent << "RGB Color Transfer Function: " + << this->RGBTransferFunction[i] << "\n"; + } + + os << indent << "Scalar Opacity Transfer Function: " + << this->ScalarOpacity[i] << "\n"; + + os << indent << "Gradient Opacity Transfer Function: " + << this->GradientOpacity[i] << "\n"; + + os << indent << "DisableGradientOpacity: " + << (this->DisableGradientOpacity[i] ? "On" : "Off") << "\n"; + + + os << indent << "ComponentWeight: " + << this->ComponentWeight[i] << "\n"; + + os << indent << "Shade: " << this->Shade[i] << "\n"; + os << indent << indent << "Ambient: " << this->Ambient[i] << "\n"; + os << indent << indent << "Diffuse: " << this->Diffuse[i] << "\n"; + os << indent << indent << "Specular: " << this->Specular[i] << "\n"; + os << indent << indent << "SpecularPower: " << this->SpecularPower[i] << "\n"; + } + + // These variables should not be printed to the user: + // this->GradientOpacityMTime + // this->GrayTransferFunctionMTime + // this->RGBTransferFunctionMTime + // this->ScalarOpacityMTime + +} + diff --git a/Rendering/vtkVolumeProperty.h b/Rendering/vtkVolumeProperty.h new file mode 100644 index 0000000..99b27f1 --- /dev/null +++ b/Rendering/vtkVolumeProperty.h @@ -0,0 +1,346 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeProperty.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkVolumeProperty - represents the common properties for rendering a volume. +// +// .SECTION Description +// vtkVolumeProperty is used to represent common properties associated +// with volume rendering. This includes properties for determining the type +// of interpolation to use when sampling a volume, the color of a volume, +// the scalar opacity of a volume, the gradient opacity of a volume, and the +// shading parameters of a volume. +// +// When the scalar opacity or the gradient opacity of a volume is not set, +// then the function is defined to be a constant value of 1.0. When a +// scalar and gradient opacity are both set simultaneously, then the opacity +// is defined to be the product of the scalar opacity and gradient opacity +// transfer functions. +// +// Most properties can be set per "component" for volume mappers that +// support multiple independent components. If you are using 2 component +// data as LV or 4 component data as RGBV (as specified in the mapper) +// only the first scalar opacity and gradient opacity transfer functions +// will be used (and all color functions will be ignored). Omitting the +// index parameter on the Set/Get methods will access index = 0. + +// .SECTION see also +// vtkPiecewiseFunction vtkColorTransferFunction + +#ifndef __vtkVolumeProperty_h +#define __vtkVolumeProperty_h + +#include "vtkObject.h" + +class vtkPiecewiseFunction; +class vtkTimeStamp; +class vtkColorTransferFunction; + +class VTK_RENDERING_EXPORT vtkVolumeProperty : public vtkObject +{ +public: + static vtkVolumeProperty *New(); + vtkTypeRevisionMacro(vtkVolumeProperty,vtkObject); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the modified time for this object (or the properties registered + // with this object). + unsigned long GetMTime(); + + // Description: + // Does the data have independent components, or do some define color + // only? If IndependentComponents is On (the default) then each component + // will be independently passed through a lookup table to determine RGBA, + // shaded. Some volume Mappers can handle 1 to 4 component + // unsigned char or unsigned short data (see each mapper header file to + // determine functionality). If IndependentComponents is Off, then you + // must have either 2 or 4 component data. For 2 component data, the + // first is passed through the first color transfer function and the + // second component is passed through the first opacity transfer function. + // Normals will be generated off of the second component. For 4 component + // data, the first three will directly represent RGB (no lookup table). + // The fourth component will be passed through the first scalar opacity + // transfer function for opacity. Normals will be generated from the fourth + // component. + vtkSetClampMacro( IndependentComponents, int, 0, 1 ); + vtkGetMacro( IndependentComponents, int ); + vtkBooleanMacro( IndependentComponents, int ); + + // Description: + // Set/Get the scalar component weights + virtual void SetComponentWeight(int index, double value); + virtual double GetComponentWeight(int index); + + // Description: + // Set the interpolation type for sampling a volume. + vtkSetClampMacro( InterpolationType, int, + VTK_NEAREST_INTERPOLATION, VTK_LINEAR_INTERPOLATION); + vtkGetMacro(InterpolationType,int); + void SetInterpolationTypeToNearest() + {this->SetInterpolationType(VTK_NEAREST_INTERPOLATION);}; + void SetInterpolationTypeToLinear() + {this->SetInterpolationType(VTK_LINEAR_INTERPOLATION);}; + const char *GetInterpolationTypeAsString(void); + + // Description: + // Set the color of a volume to a gray level transfer function + // for the component indicated by index. This will set the + // color channels for this component to 1. + void SetColor( int index, vtkPiecewiseFunction *function ); + void SetColor( vtkPiecewiseFunction *f ){this->SetColor(0,f);}; + + // Description: + // Set the color of a volume to an RGB transfer function + // for the component indicated by index. This will set the + // color channels for this component to 3. + // This will also recompute the color channels + void SetColor( int index, vtkColorTransferFunction *function ); + void SetColor( vtkColorTransferFunction *f ){this->SetColor(0,f);}; + + // Description: + // Get the number of color channels in the transfer function + // for the given component. + int GetColorChannels( int index ); + int GetColorChannels(){return this->GetColorChannels(0);}; + + // Description: + // Get the gray transfer function. + // If no transfer function has been set for this component, a default one + // is created and returned. + vtkPiecewiseFunction *GetGrayTransferFunction( int index ); + vtkPiecewiseFunction *GetGrayTransferFunction() + {return this->GetGrayTransferFunction(0);}; + + // Description: + // Get the RGB transfer function for the given component. + // If no transfer function has been set for this component, a default one + // is created and returned. + vtkColorTransferFunction *GetRGBTransferFunction( int index ); + vtkColorTransferFunction *GetRGBTransferFunction() + {return this->GetRGBTransferFunction(0);}; + + // Description: + // Set the opacity of a volume to an opacity transfer function based + // on scalar value for the component indicated by index. + void SetScalarOpacity( int index, vtkPiecewiseFunction *function ); + void SetScalarOpacity( vtkPiecewiseFunction *f ) + {this->SetScalarOpacity(0,f);}; + + // Description: + // Get the scalar opacity transfer function for the given component. + // If no transfer function has been set for this component, a default one + // is created and returned. + vtkPiecewiseFunction *GetScalarOpacity( int index ); + vtkPiecewiseFunction *GetScalarOpacity() + {return this->GetScalarOpacity(0);}; + + // Description: + // Set/Get the unit distance on which the scalar opacity transfer function + // is defined. By default this is 1.0, meaning that over a distance of + // 1.0 units, a given opacity (from the transfer function) is accumulated. + // This is adjusted for the actual sampling distance during rendering. + void SetScalarOpacityUnitDistance( int index, double distance ); + void SetScalarOpacityUnitDistance( double distance ) + {this->SetScalarOpacityUnitDistance( 0, distance );} + double GetScalarOpacityUnitDistance( int index ); + double GetScalarOpacityUnitDistance() + {return this->GetScalarOpacityUnitDistance(0);} + + + // Description: + // Set the opacity of a volume to an opacity transfer function based + // on gradient magnitude for the given component. + void SetGradientOpacity( int index, vtkPiecewiseFunction *function ); + void SetGradientOpacity( vtkPiecewiseFunction *function ) + {this->SetGradientOpacity(0,function);} + + // Description: + // Get the gradient magnitude opacity transfer function for + // the given component. + // If no transfer function has been set for this component, a default one + // is created and returned. + // This default function is always returned if DisableGradientOpacity is On + // for that component. + vtkPiecewiseFunction *GetGradientOpacity( int index ); + vtkPiecewiseFunction *GetGradientOpacity() + {return this->GetGradientOpacity( 0 );} + + // Description: + // Enable/Disable the gradient opacity function for the given component. + // If set to true, any call to GetGradientOpacity() will return a default + // function for this component. Note that the gradient opacity function is + // still stored, it is not set or reset and can be retrieved using + // GetStoredGradientOpacity(). + virtual void SetDisableGradientOpacity( int index, int value ); + virtual void SetDisableGradientOpacity( int value ) + { this->SetDisableGradientOpacity(0, value); } + virtual void DisableGradientOpacityOn( int index ) + { this->SetDisableGradientOpacity(index, 1); } + virtual void DisableGradientOpacityOn() + { this->DisableGradientOpacityOn(0); } + virtual void DisableGradientOpacityOff( int index ) + { this->SetDisableGradientOpacity(index, 0); } + virtual void DisableGradientOpacityOff() + { this->DisableGradientOpacityOff(0); } + virtual int GetDisableGradientOpacity( int index ); + virtual int GetDisableGradientOpacity() + { return this->GetDisableGradientOpacity(0); } + vtkPiecewiseFunction *GetStoredGradientOpacity( int index ); + vtkPiecewiseFunction *GetStoredGradientOpacity() + {return this->GetStoredGradientOpacity( 0 );} + + // Description: + // Set/Get the shading of a volume. If shading is turned off, then + // the mapper for the volume will not perform shading calculations. + // If shading is turned on, the mapper may perform shading + // calculations - in some cases shading does not apply (for example, + // in a maximum intensity projection) and therefore shading will + // not be performed even if this flag is on. For a compositing type + // of mapper, turning shading off is generally the same as setting + // ambient=1, diffuse=0, specular=0. Shading can be independently + // turned on/off per component. + void SetShade( int index, int value ); + void SetShade( int value ) {this->SetShade(0,value);} + int GetShade( int index ); + int GetShade() {return this->GetShade(0);} + void ShadeOn( int index ); + void ShadeOn() {this->ShadeOn(0);} + void ShadeOff( int index ); + void ShadeOff() {this->ShadeOff(0);} + + // Description: + // Set/Get the ambient lighting coefficient. + void SetAmbient( int index, double value ); + void SetAmbient( double value ) {this->SetAmbient( 0, value );} + double GetAmbient( int index ); + double GetAmbient() {return this->GetAmbient(0);} + + // Description: + // Set/Get the diffuse lighting coefficient. + void SetDiffuse( int index, double value ); + void SetDiffuse( double value ) {this->SetDiffuse( 0, value );} + double GetDiffuse( int index ); + double GetDiffuse() {return this->GetDiffuse(0);} + + // Description: + // Set/Get the specular lighting coefficient. + void SetSpecular( int index, double value ); + void SetSpecular( double value ) {this->SetSpecular( 0, value );} + double GetSpecular( int index ); + double GetSpecular() {return this->GetSpecular(0);} + + // Description: + // Set/Get the specular power. + void SetSpecularPower( int index, double value ); + void SetSpecularPower( double value ) {this->SetSpecularPower( 0, value );} + double GetSpecularPower( int index ); + double GetSpecularPower() {return this->GetSpecularPower(0);} + + //BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // UpdateMTimes performs a Modified() on all TimeStamps. + // This is used by vtkVolume when the property is set, so + // that any other object that might have been caching + // information for the property will rebuild. + void UpdateMTimes(); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Get the time that the gradient opacity transfer function was set + vtkTimeStamp GetGradientOpacityMTime( int index ); + vtkTimeStamp GetGradientOpacityMTime() + { return this->GetGradientOpacityMTime(0); } + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Get the time that the scalar opacity transfer function was set. + vtkTimeStamp GetScalarOpacityMTime( int index ); + vtkTimeStamp GetScalarOpacityMTime() + { return this->GetScalarOpacityMTime(0); } + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Get the time that the RGBTransferFunction was set + vtkTimeStamp GetRGBTransferFunctionMTime( int index ); + vtkTimeStamp GetRGBTransferFunctionMTime() + { return this->GetRGBTransferFunctionMTime(0); } + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Get the time that the GrayTransferFunction was set + vtkTimeStamp GetGrayTransferFunctionMTime( int index ); + vtkTimeStamp GetGrayTransferFunctionMTime() + { return this->GetGrayTransferFunctionMTime(0); } + //ETX + +protected: + vtkVolumeProperty(); + ~vtkVolumeProperty(); + + int IndependentComponents; + double ComponentWeight[VTK_MAX_VRCOMP]; + + int InterpolationType; + + int ColorChannels[VTK_MAX_VRCOMP]; + + vtkPiecewiseFunction *GrayTransferFunction[VTK_MAX_VRCOMP]; + vtkTimeStamp GrayTransferFunctionMTime[VTK_MAX_VRCOMP]; + + vtkColorTransferFunction *RGBTransferFunction[VTK_MAX_VRCOMP]; + vtkTimeStamp RGBTransferFunctionMTime[VTK_MAX_VRCOMP]; + + vtkPiecewiseFunction *ScalarOpacity[VTK_MAX_VRCOMP]; + vtkTimeStamp ScalarOpacityMTime[VTK_MAX_VRCOMP]; + double ScalarOpacityUnitDistance[VTK_MAX_VRCOMP]; + + vtkPiecewiseFunction *GradientOpacity[VTK_MAX_VRCOMP]; + vtkTimeStamp GradientOpacityMTime[VTK_MAX_VRCOMP]; + vtkPiecewiseFunction *DefaultGradientOpacity[VTK_MAX_VRCOMP]; + int DisableGradientOpacity[VTK_MAX_VRCOMP]; + + int Shade[VTK_MAX_VRCOMP]; + double Ambient[VTK_MAX_VRCOMP]; + double Diffuse[VTK_MAX_VRCOMP]; + double Specular[VTK_MAX_VRCOMP]; + double SpecularPower[VTK_MAX_VRCOMP]; + + virtual void CreateDefaultGradientOpacity(int index); + +private: + vtkVolumeProperty(const vtkVolumeProperty&); // Not implemented. + void operator=(const vtkVolumeProperty&); // Not implemented. +}; + +// Description: +// Return the interpolation type as a descriptive character string. +inline const char *vtkVolumeProperty::GetInterpolationTypeAsString(void) +{ + if( this->InterpolationType == VTK_NEAREST_INTERPOLATION ) + { + return "Nearest Neighbor"; + } + else if( this->InterpolationType == VTK_LINEAR_INTERPOLATION ) + { + return "Linear"; + } + else + { + return "Unknown"; + } +} + +#endif diff --git a/Rendering/vtkWin32OpenGLRenderWindow.cxx b/Rendering/vtkWin32OpenGLRenderWindow.cxx new file mode 100644 index 0000000..29caaa0 --- /dev/null +++ b/Rendering/vtkWin32OpenGLRenderWindow.cxx @@ -0,0 +1,1477 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32OpenGLRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWin32OpenGLRenderWindow.h" + +#include "vtkIdList.h" +#include "vtkCommand.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLActor.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLPolyDataMapper.h" +#include "vtkOpenGLProperty.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLTexture.h" +#include "vtkRendererCollection.h" +#include "vtkWin32RenderWindowInteractor.h" + +#include + +#if defined(_MSC_VER) || defined (__BORLANDC__) +# include "vtkWindows.h" +# include +#else +# include "vtkOpenGL.h" +#endif + +vtkCxxRevisionMacro(vtkWin32OpenGLRenderWindow, "$Revision: 1.130 $"); +vtkStandardNewMacro(vtkWin32OpenGLRenderWindow); + +#define VTK_MAX_LIGHTS 8 + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET +#pragma warning ( disable : 4311 ) +#pragma warning ( disable : 4312 ) +# define vtkGWLP_HINSTANCE GWLP_HINSTANCE +# define vtkGetWindowLong GetWindowLongPtr +# define vtkSetWindowLong SetWindowLongPtr +#else // regular Visual studio +# define vtkGWLP_HINSTANCE GWL_HINSTANCE +# define vtkGetWindowLong GetWindowLong +# define vtkSetWindowLong SetWindowLong +#endif // + +vtkWin32OpenGLRenderWindow::vtkWin32OpenGLRenderWindow() +{ + this->ApplicationInstance = NULL; + this->Palette = NULL; + this->ContextId = 0; + this->MultiSamples = 8; + this->WindowId = 0; + this->ParentId = 0; + this->NextWindowId = 0; + this->DeviceContext = (HDC)0; // hsr + this->MFChandledWindow = FALSE; // hsr + this->StereoType = VTK_STEREO_CRYSTAL_EYES; + this->CursorHidden = 0; + this->Capabilities = 0; + + this->ScreenDeviceContext = (HDC)0; + this->MemoryHdc = (HDC)0; +} + +vtkWin32OpenGLRenderWindow::~vtkWin32OpenGLRenderWindow() +{ + this->Finalize(); + delete[] this->Capabilities; +} + +void vtkWin32OpenGLRenderWindow::Clean() +{ + vtkRenderer *ren; + GLuint id; + + /* finish OpenGL rendering */ + if (this->ContextId) + { + this->MakeCurrent(); + + /* first delete all the old lights */ + for (short cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+VTK_MAX_LIGHTS; cur_light++) + { + glDisable((GLenum)cur_light); + } + + /* now delete all textures */ + glDisable(GL_TEXTURE_2D); + for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++) + { + id = (GLuint) this->TextureResourceIds->GetId(i); +#ifdef GL_VERSION_1_1 + if (glIsTexture(id)) + { + glDeleteTextures(1, &id); + } +#else + if (glIsList(id)) + { + glDeleteLists(id,1); + } +#endif + } + + // tell each of the renderers that this render window/graphics context + // is being removed (the RendererCollection is removed by vtkRenderWindow's + // destructor) + vtkCollectionSimpleIterator rsit; + this->Renderers->InitTraversal(rsit); + for ( ren = (vtkOpenGLRenderer *) this->Renderers->GetNextRenderer(rsit); + ren != NULL; + ren = (vtkOpenGLRenderer *) this->Renderers->GetNextRenderer(rsit) ) + { + ren->SetRenderWindow(NULL); + } + + if (wglMakeCurrent(NULL, NULL) != TRUE) + { + vtkErrorMacro("wglMakeCurrent failed in Clean(), error: " << GetLastError()); + } + if (wglDeleteContext(this->ContextId) != TRUE) + { + vtkErrorMacro("wglDeleteContext failed in Clean(), error: " << GetLastError()); + } + this->ContextId = NULL; + } + if (this->Palette) + { + SelectPalette(this->DeviceContext, this->OldPalette, FALSE); // SVA delete the old palette + DeleteObject(this->Palette); + this->Palette = NULL; + } +} + +LRESULT APIENTRY vtkWin32OpenGLRenderWindow::WndProc(HWND hWnd, UINT message, + WPARAM wParam, + LPARAM lParam) +{ + vtkWin32OpenGLRenderWindow *me = + (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd,4); + + // forward to actual object + if (me) + { + return me->MessageProc(hWnd, message, wParam, lParam); + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +void vtkWin32OpenGLRenderWindow::SetWindowName( const char * _arg ) +{ + vtkWindow::SetWindowName(_arg); + if (this->WindowId) + { +#ifdef UNICODE + wchar_t *wname = new wchar_t [mbstowcs(NULL, this->WindowName, 32000)+1]; + mbstowcs(wname, this->WindowName, 32000); + SetWindowText(this->WindowId, wname); + delete [] wname; +#else + SetWindowText(this->WindowId, this->WindowName); +#endif + } +} + +int vtkWin32OpenGLRenderWindow::GetEventPending() +{ + MSG msg; + if (PeekMessage(&msg,this->WindowId,WM_MOUSEFIRST,WM_MOUSELAST,PM_NOREMOVE)) + { + if (msg.message == WM_MOUSEMOVE) + { + PeekMessage(&msg,this->WindowId,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE); + } + if ((msg.message == WM_LBUTTONDOWN) || + (msg.message == WM_RBUTTONDOWN) || + (msg.message == WM_MBUTTONDOWN)) + { + return 1; + } + } + + return 0; +} + + +void vtkWin32OpenGLRenderWindow::MakeCurrent() +{ + // Try to avoid doing anything (for performance). + HGLRC current = wglGetCurrentContext(); + if (this->ContextId != current) + { + if(this->IsPicking && current) + { + vtkErrorMacro("Attempting to call MakeCurrent for a different window" + " than the one doing the picking, this can causes crashes" + " and/or bad pick results"); + } + else + { + if (wglMakeCurrent(this->DeviceContext, this->ContextId) != TRUE) + { + LPVOID lpMsgBuf; + ::FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + if(lpMsgBuf) + { +#ifdef UNICODE + wchar_t *wmsg = new wchar_t [mbstowcs(NULL, (const char*)lpMsgBuf, 32000)+1]; + wchar_t *wtemp = new wchar_t [mbstowcs(NULL, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000)+1]; + mbstowcs(wmsg, (const char*)lpMsgBuf, 32000); + mbstowcs(wtemp, "wglMakeCurrent failed in MakeCurrent(), error: ", 32000); + vtkErrorMacro(<< wcscat(wtemp, wmsg)); + delete [] wmsg; + delete [] wtemp; +#else + vtkErrorMacro("wglMakeCurrent failed in MakeCurrent(), error: " + << (LPCTSTR)lpMsgBuf); +#endif + ::LocalFree( lpMsgBuf ); + } + } + } + } +} + + +void vtkWin32OpenGLRenderWindow::SetSize(int x, int y) +{ + static int resizing = 0; + if ((this->Size[0] != x) || (this->Size[1] != y)) + { + this->Modified(); + this->Size[0] = x; + this->Size[1] = y; + if (this->OffScreenRendering) + { + if (!resizing) + { + resizing = 1; + this->CleanUpOffScreenRendering(); +#ifdef UNICODE + HDC dc = CreateDC(L"DISPLAY", 0, 0, 0); +#else + HDC dc = CreateDC("DISPLAY", 0, 0, 0); +#endif + this->CreateOffScreenDC(x, y, dc); + DeleteDC(dc); + resizing = 0; + } + } + + else if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + if (this->ParentId) + { + SetWindowExtEx(this->DeviceContext,x,y,NULL); + SetViewportExtEx(this->DeviceContext,x,y,NULL); + SetWindowPos(this->WindowId,HWND_TOP,0,0, + x, y, SWP_NOMOVE | SWP_NOZORDER); + } + else + { + SetWindowPos(this->WindowId,HWND_TOP,0,0, + x+2*GetSystemMetrics(SM_CXFRAME), + y+2*GetSystemMetrics(SM_CYFRAME) +GetSystemMetrics(SM_CYCAPTION), + SWP_NOMOVE | SWP_NOZORDER); + } + resizing = 0; + } + } + } +} + +void vtkWin32OpenGLRenderWindow::SetPosition(int x, int y) +{ + static int resizing = 0; + + if ((this->Position[0] != x) || (this->Position[1] != y)) + { + this->Modified(); + this->Position[0] = x; + this->Position[1] = y; + if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + SetWindowPos(this->WindowId,HWND_TOP,x,y, + 0, 0, SWP_NOSIZE | SWP_NOZORDER); + resizing = 0; + } + } + } +} + + +// End the rendering process and display the image. +void vtkWin32OpenGLRenderWindow::Frame(void) +{ + this->MakeCurrent(); + if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers) + { + // use global scope to get Win32 API SwapBuffers and not be + // confused with this->SwapBuffers + ::SwapBuffers(this->DeviceContext); + vtkDebugMacro(<< " SwapBuffers\n"); + } + else + { + glFlush(); + } +} + +int vtkWin32OpenGLRenderWindow::SupportsOpenGL() +{ + MakeCurrent(); + if (!this->DeviceContext) + { + return 0; + } + + int pixelFormat = GetPixelFormat(this->DeviceContext); + PIXELFORMATDESCRIPTOR pfd; + + DescribePixelFormat(this->DeviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + return (pfd.dwFlags & PFD_SUPPORT_OPENGL) ? 1:0; + +} + + +int vtkWin32OpenGLRenderWindow::IsDirect() +{ + + MakeCurrent(); + if (!this->DeviceContext) + { + return 0; + } + + int pixelFormat = GetPixelFormat(this->DeviceContext); + PIXELFORMATDESCRIPTOR pfd; + + DescribePixelFormat(this->DeviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + return (pfd.dwFlags & PFD_GENERIC_FORMAT) ? 0:1; + +} + + +const char* vtkWin32OpenGLRenderWindow::ReportCapabilities() +{ + MakeCurrent(); + + if (!this->DeviceContext) + { + return "no device context"; + } + + int pixelFormat = GetPixelFormat(this->DeviceContext); + PIXELFORMATDESCRIPTOR pfd; + + DescribePixelFormat(this->DeviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + const char *glVendor = (const char *) glGetString(GL_VENDOR); + const char *glRenderer = (const char *) glGetString(GL_RENDERER); + const char *glVersion = (const char *) glGetString(GL_VERSION); + const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS); + + ostrstream strm; + strm << "OpenGL vendor string: " << glVendor << endl; + strm << "OpenGL renderer string: " << glRenderer << endl; + strm << "OpenGL version string: " << glVersion << endl; + strm << "OpenGL extensions: " << glExtensions << endl; + strm << "PixelFormat Descriptor:" << endl; + strm << "depth: " << static_cast(pfd.cDepthBits) << endl; + if (pfd.cColorBits <= 8) + { + strm << "class: PseudoColor" << endl; + } + else + { + strm << "class: TrueColor" << endl; + } + strm << "buffer size: " << static_cast(pfd.cColorBits) << endl; + strm << "level: " << static_cast(pfd.bReserved) << endl; + if (pfd.iPixelType == PFD_TYPE_RGBA) + { + strm << "renderType: rgba" << endl; + } + else + { + strm <<"renderType: ci" << endl; + } + if (pfd.dwFlags & PFD_DOUBLEBUFFER) { + strm << "double buffer: True" << endl; + } else { + strm << "double buffer: False" << endl; + } + if (pfd.dwFlags & PFD_STEREO) { + strm << "stereo: True" << endl; + } else { + strm << "stereo: False" << endl; + } + if (pfd.dwFlags & PFD_GENERIC_FORMAT) { + strm << "hardware acceleration: False" << endl; + } else { + strm << "hardware acceleration: True" << endl; + } + strm << "rgba: redSize=" << static_cast(pfd.cRedBits) << " greenSize=" << static_cast(pfd.cGreenBits) << "blueSize=" << static_cast(pfd.cBlueBits) << "alphaSize=" << static_cast(pfd.cAlphaBits) << endl; + strm << "aux buffers: " << static_cast(pfd.cAuxBuffers)<< endl; + strm << "depth size: " << static_cast(pfd.cDepthBits) << endl; + strm << "stencil size: " << static_cast(pfd.cStencilBits) << endl; + strm << "accum: redSize=" << static_cast(pfd.cAccumRedBits) << " greenSize=" << static_cast(pfd.cAccumGreenBits) << "blueSize=" << static_cast(pfd.cAccumBlueBits) << "alphaSize=" << static_cast(pfd.cAccumAlphaBits) << endl; + + strm << ends; + delete[] this->Capabilities; + this->Capabilities = strm.str(); + return this->Capabilities; +} + + +void vtkWin32OpenGLRenderWindow::SetupPixelFormat(HDC hDC, DWORD dwFlags, + int debug, int bpp, + int zbpp) +{ + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), /* size */ + 1, /* version */ + dwFlags , /* support double-buffering */ + PFD_TYPE_RGBA, /* color type */ + bpp, /* prefered color depth */ + 0, 0, 0, 0, 0, 0, /* color bits (ignored) */ + this->AlphaBitPlanes ? bpp/4 : 0, /* no alpha buffer */ + 0, /* alpha bits (ignored) */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits (ignored) */ + zbpp, /* depth buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffers */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0, /* no layer, visible, damage masks */ + }; + int pixelFormat; + // Only try to set pixel format if we do not currently have one + int currentPixelFormat = GetPixelFormat(hDC); + // if there is a current pixel format, then make sure it + // supports OpenGL + if (currentPixelFormat != 0) + { + DescribePixelFormat(hDC, currentPixelFormat,sizeof(pfd), &pfd); + if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL)) + { +#ifdef UNICODE + MessageBox(WindowFromDC(hDC), + L"Invalid pixel format, no OpenGL support", + L"Error", + MB_ICONERROR | MB_OK); +#else + MessageBox(WindowFromDC(hDC), + "Invalid pixel format, no OpenGL support", + "Error", + MB_ICONERROR | MB_OK); +#endif + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + exit(1); + } + } + } + else + { + // hDC has no current PixelFormat, so + pixelFormat = ChoosePixelFormat(hDC, &pfd); + if (pixelFormat == 0) + { +#ifdef UNICODE + MessageBox(WindowFromDC(hDC), L"ChoosePixelFormat failed.", L"Error", + MB_ICONERROR | MB_OK); +#else + MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error", + MB_ICONERROR | MB_OK); +#endif + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + exit(1); + } + } + DescribePixelFormat(hDC, pixelFormat,sizeof(pfd), &pfd); + if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) + { + // int err = GetLastError(); +#ifdef UNICODE + MessageBox(WindowFromDC(hDC), L"SetPixelFormat failed.", L"Error", + MB_ICONERROR | MB_OK); +#else + MessageBox(WindowFromDC(hDC), "SetPixelFormat failed.", "Error", + MB_ICONERROR | MB_OK); +#endif + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + exit(1); + } + } + } + if (debug && (dwFlags & PFD_STEREO) && !(pfd.dwFlags & PFD_STEREO)) + { + vtkGenericWarningMacro("No Stereo Available!"); + this->StereoCapableWindow = 0; + } +} + +void vtkWin32OpenGLRenderWindow::SetupPalette(HDC hDC) +{ + int pixelFormat = GetPixelFormat(hDC); + PIXELFORMATDESCRIPTOR pfd; + LOGPALETTE* pPal; + int paletteSize; + + DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + if (pfd.dwFlags & PFD_NEED_PALETTE) { + paletteSize = 1 << pfd.cColorBits; + } else { + return; + } + + pPal = (LOGPALETTE*) + malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); + pPal->palVersion = 0x300; + pPal->palNumEntries = paletteSize; + + /* build a simple RGB color palette */ + { + int redMask = (1 << pfd.cRedBits) - 1; + int greenMask = (1 << pfd.cGreenBits) - 1; + int blueMask = (1 << pfd.cBlueBits) - 1; + int i; + + for (i=0; ipalPalEntry[i].peRed = + (((i >> pfd.cRedShift) & redMask) * 255) / redMask; + pPal->palPalEntry[i].peGreen = + (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; + pPal->palPalEntry[i].peBlue = + (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; + pPal->palPalEntry[i].peFlags = 0; + } + } + + this->Palette = CreatePalette(pPal); + free(pPal); + + if (this->Palette) { + this->OldPalette = SelectPalette(hDC, this->Palette, FALSE); + RealizePalette(hDC); + } +} + + +LRESULT vtkWin32OpenGLRenderWindow::MessageProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CREATE: + { + // nothing to be done here, opengl is initilized after the call to + // create now + return 0; + } + case WM_DESTROY: + this->Clean(); + if (this->DeviceContext) + { + ReleaseDC(this->WindowId, this->DeviceContext); + this->DeviceContext = NULL; + this->WindowId = NULL; + } + return 0; + case WM_SIZE: + /* track window size changes */ + if (this->ContextId) + { + this->SetSize((int) LOWORD(lParam),(int) HIWORD(lParam)); + return 0; + } + case WM_PALETTECHANGED: + /* realize palette if this is *not* the current window */ + if (this->ContextId && this->Palette && (HWND) wParam != hWnd) + { + SelectPalette(this->DeviceContext, this->OldPalette, FALSE); + UnrealizeObject(this->Palette); + this->OldPalette = SelectPalette(this->DeviceContext, + this->Palette, FALSE); + RealizePalette(this->DeviceContext); + this->Render(); + } + break; + case WM_QUERYNEWPALETTE: + /* realize palette if this is the current window */ + if (this->ContextId && this->Palette) + { + SelectPalette(this->DeviceContext, this->OldPalette, FALSE); + UnrealizeObject(this->Palette); + this->OldPalette = SelectPalette(this->DeviceContext, + this->Palette, FALSE); + RealizePalette(this->DeviceContext); + this->Render(); + return TRUE; + } + break; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + if (this->ContextId) + { + this->Render(); + } + EndPaint(hWnd, &ps); + return 0; + } + break; + case WM_ERASEBKGND: + return TRUE; + default: + this->InvokeEvent(vtkCommand::RenderWindowMessageEvent, &message); + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + + +void vtkWin32OpenGLRenderWindow::InitializeApplication() +{ + // get the applicaiton instance if we don't have one already + if (!this->ApplicationInstance) + { + // if we have a parent window get the app instance from it + if (this->ParentId) + { + this->ApplicationInstance = (HINSTANCE)vtkGetWindowLong(this->ParentId,vtkGWLP_HINSTANCE); + } + else + { + this->ApplicationInstance = GetModuleHandle(NULL); /*AfxGetInstanceHandle();*/ + } + } +} + +void vtkWin32OpenGLRenderWindow::CreateAWindow(int x, int y, int width, + int height) +{ + static int count=1; + char *windowName; + + if (!this->WindowId) + { + WNDCLASS wndClass; + this->DeviceContext = 0; + + int len = static_cast(strlen("Visualization Toolkit - Win32OpenGL #")) + + (int)ceil( (double) log10( (double)(count+1) ) ) + + 1; + windowName = new char [ len ]; + sprintf(windowName,"Visualization Toolkit - Win32OpenGL #%i",count++); + this->SetWindowName(windowName); + delete [] windowName; + + // has the class been registered ? +#ifdef UNICODE + if (!GetClassInfo(this->ApplicationInstance,L"vtkOpenGL",&wndClass)) +#else + if (!GetClassInfo(this->ApplicationInstance,"vtkOpenGL",&wndClass)) +#endif + { + wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wndClass.lpfnWndProc = vtkWin32OpenGLRenderWindow::WndProc; + wndClass.cbClsExtra = 0; + wndClass.hInstance = this->ApplicationInstance; + wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndClass.lpszMenuName = NULL; +#ifdef UNICODE + wndClass.lpszClassName = L"vtkOpenGL"; +#else + wndClass.lpszClassName = "vtkOpenGL"; +#endif + // vtk doesn't use the first extra 4 bytes, but app writers + // may want them, so we provide them. VTK does use the second + // four bytes of extra space. + wndClass.cbWndExtra = 8; + RegisterClass(&wndClass); + } + +#ifdef UNICODE + wchar_t *wname = new wchar_t [mbstowcs(NULL, this->WindowName, 32000)+1]; + mbstowcs(wname, this->WindowName, 32000); +#endif + + /* create window */ + if (this->ParentId) + { +#ifdef UNICODE + this->WindowId = CreateWindow( + L"vtkOpenGL", wname, + WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/, + x, y, width, height, + this->ParentId, NULL, this->ApplicationInstance, NULL); +#else + this->WindowId = CreateWindow( + "vtkOpenGL", this->WindowName, + WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/, + x, y, width, height, + this->ParentId, NULL, this->ApplicationInstance, NULL); +#endif + } + else + { + DWORD style; + if (this->Borders) + { + style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/; + } + else + { + style = WS_POPUP | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/; + } +#ifdef UNICODE + this->WindowId = CreateWindow( + L"vtkOpenGL", wname, style, + x,y, width+2*GetSystemMetrics(SM_CXFRAME), + height+2*GetSystemMetrics(SM_CYFRAME) +GetSystemMetrics(SM_CYCAPTION), + NULL, NULL, this->ApplicationInstance, NULL); +#else + this->WindowId = CreateWindow( + "vtkOpenGL", this->WindowName, style, + x,y, width+2*GetSystemMetrics(SM_CXFRAME), + height+2*GetSystemMetrics(SM_CYFRAME) +GetSystemMetrics(SM_CYCAPTION), + NULL, NULL, this->ApplicationInstance, NULL); +#endif + } +#ifdef UNICODE + delete [] wname; +#endif + + if (!this->WindowId) + { + vtkErrorMacro("Could not create window, error: " << GetLastError()); + return; + } + // extract the create info + + /* display window */ + ShowWindow(this->WindowId, SW_SHOW); + //UpdateWindow(this->WindowId); + this->OwnWindow = 1; + vtkSetWindowLong(this->WindowId,4,(LONG)this); + } + if (!this->DeviceContext) + { + this->DeviceContext = GetDC(this->WindowId); + } + if (this->StereoCapableWindow) + { + this->SetupPixelFormat(this->DeviceContext, PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | + PFD_STEREO, this->GetDebug(), 32, 32); + } + else + { + this->SetupPixelFormat(this->DeviceContext, PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER, + this->GetDebug(), 32, 32); + } + this->SetupPalette(this->DeviceContext); + this->ContextId = wglCreateContext(this->DeviceContext); + if (this->ContextId == NULL) + { + vtkErrorMacro("wglCreateContext failed in CreateAWindow(), error: " << GetLastError()); + } + this->MakeCurrent(); + + // wipe out any existing display lists + vtkRenderer* ren; + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(0); + ren->SetRenderWindow(this); + } + this->OpenGLInit(); + this->Mapped = 1; +} + +// Initialize the window for rendering. +void vtkWin32OpenGLRenderWindow::WindowInitialize() +{ + int x, y, width, height; + x = ((this->Position[0] >= 0) ? this->Position[0] : 5); + y = ((this->Position[1] >= 0) ? this->Position[1] : 5); + height = ((this->Size[1] > 0) ? this->Size[1] : 300); + width = ((this->Size[0] > 0) ? this->Size[0] : 300); + + // create our own window if not already set + this->OwnWindow = 0; + if (!this->MFChandledWindow) + { + this->InitializeApplication(); + this->CreateAWindow(x,y,width,height); + } + else + { + this->MakeCurrent(); // hsr + this->OpenGLInit(); + } + + // set the DPI + this->SetDPI(GetDeviceCaps(this->DeviceContext, LOGPIXELSY)); +} + +// Initialize the rendering window. +void vtkWin32OpenGLRenderWindow::Initialize (void) +{ + // make sure we havent already been initialized + if (this->ContextId) + { + return; + } + + // now initialize the window + if (this->OffScreenRendering) + { + this->InitializeApplication(); + } + else + { + this->WindowInitialize(); + } +} + +void vtkWin32OpenGLRenderWindow::Finalize (void) +{ + if (this->CursorHidden) + { + this->ShowCursor(); + } + + if (this->OffScreenRendering) + { + this->CleanUpOffScreenRendering(); + } + + if (this->WindowId) + { + this->Clean(); + ReleaseDC(this->WindowId, this->DeviceContext); + // can't set WindowId=NULL, needed for DestroyWindow + this->DeviceContext = NULL; + + // clear the extra data before calling destroy + vtkSetWindowLong(this->WindowId,4,(LONG)0); + if(this->OwnWindow) + { + DestroyWindow(this->WindowId); + } + } +} + + +// Get the current size of the window. +int *vtkWin32OpenGLRenderWindow::GetSize(void) +{ + // if we aren't mapped then just return the ivar + if (this->Mapped) + { + RECT rect; + + // Find the current window size + if (GetClientRect(this->WindowId, &rect)) + { + this->Size[0] = rect.right; + this->Size[1] = rect.bottom; + } + else + { + this->Size[0] = 0; + this->Size[1] = 0; + } + + } + + return this->vtkOpenGLRenderWindow::GetSize(); +} + +// Get the current size of the window. +int *vtkWin32OpenGLRenderWindow::GetScreenSize(void) +{ + RECT rect; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + + this->Size[0] = rect.right - rect.left; + this->Size[1] = rect.bottom - rect.top; + + return this->Size; +} + +// Get the position in screen coordinates of the window. +int *vtkWin32OpenGLRenderWindow::GetPosition(void) +{ + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Position; + } + + // Find the current window position + // x,y,&this->Position[0],&this->Position[1],&child); + + return this->Position; +} + +// Change the window to fill the entire screen. +void vtkWin32OpenGLRenderWindow::SetFullScreen(int arg) +{ + int *temp; + + if (this->FullScreen == arg) + { + return; + } + + if (!this->Mapped) + { + this->PrefFullScreen(); + return; + } + + // set the mode + this->FullScreen = arg; + if (this->FullScreen <= 0) + { + this->Position[0] = this->OldScreen[0]; + this->Position[1] = this->OldScreen[1]; + this->Size[0] = this->OldScreen[2]; + this->Size[1] = this->OldScreen[3]; + this->Borders = this->OldScreen[4]; + } + else + { + // if window already up get its values + if (this->WindowId) + { + temp = this->GetPosition(); + this->OldScreen[0] = temp[0]; + this->OldScreen[1] = temp[1]; + + this->OldScreen[4] = this->Borders; + this->PrefFullScreen(); + } + } + + // remap the window + this->WindowRemap(); + + this->Modified(); +} + +// +// Set the variable that indicates that we want a stereo capable window +// be created. This method can only be called before a window is realized. +// +void vtkWin32OpenGLRenderWindow::SetStereoCapableWindow(int capable) +{ + if (this->WindowId == 0) + { + vtkRenderWindow::SetStereoCapableWindow(capable); + } + else + { + vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed " + << "before the window is realized, i.e. before a render."); + } +} + + +// Set the preferred window size to full screen. +void vtkWin32OpenGLRenderWindow::PrefFullScreen() +{ + int *size; + + size = this->GetScreenSize(); + + // use full screen + this->Position[0] = 0; + this->Position[1] = 0; + this->Size[0] = size[0] - 2*GetSystemMetrics(SM_CXFRAME); + this->Size[1] = size[1] - + 2*GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYCAPTION); + + // don't show borders + this->Borders = 0; +} + +// Remap the window. +void vtkWin32OpenGLRenderWindow::WindowRemap() +{ + // close everything down + this->Finalize(); + + // set the default windowid + this->WindowId = this->NextWindowId; + this->NextWindowId = 0; + + // and set it up! + this->Initialize(); +} + +void vtkWin32OpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ContextId: " << this->ContextId << "\n"; + os << indent << "Next Window Id: " << this->NextWindowId << "\n"; + os << indent << "Window Id: " << this->WindowId << "\n"; +} + +// Get the window id. +HWND vtkWin32OpenGLRenderWindow::GetWindowId() +{ + vtkDebugMacro(<< "Returning WindowId of " << this->WindowId << "\n"); + + return this->WindowId; +} + +// Set the window id to a pre-existing window. +void vtkWin32OpenGLRenderWindow::SetWindowId(HWND arg) +{ + vtkDebugMacro(<< "Setting WindowId to " << arg << "\n"); + + if (arg != this->WindowId) + { + this->WindowId = arg; + if (this->ContextId) + { + wglDeleteContext(this->ContextId); + } + this->ContextId = 0; + this->DeviceContext = 0; + } +} + +// Set this RenderWindow's X window id to a pre-existing window. +void vtkWin32OpenGLRenderWindow::SetWindowInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->WindowId = (HWND)tmp; + vtkDebugMacro(<< "Setting WindowId to " << this->WindowId << "\n"); +} + +void vtkWin32OpenGLRenderWindow::SetNextWindowInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->SetNextWindowId((HWND)tmp); +} + +void vtkWin32OpenGLRenderWindow::SetDisplayId(void * arg) +{ + this->DeviceContext = (HDC) arg; +} + +void vtkWin32OpenGLRenderWindow::SetContextId(HGLRC arg) +{ + this->ContextId = arg; +} + +void vtkWin32OpenGLRenderWindow::SetDeviceContext(HDC arg) +{ + this->DeviceContext = arg; + this->MFChandledWindow = TRUE; +} + +// Sets the HWND id of the window that WILL BE created. +void vtkWin32OpenGLRenderWindow::SetParentInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->ParentId = (HWND)tmp; + vtkDebugMacro(<< "Setting ParentId to " << this->ParentId << "\n"); +} + +// Set the window id to a pre-existing window. +void vtkWin32OpenGLRenderWindow::SetParentId(HWND arg) +{ + vtkDebugMacro(<< "Setting ParentId to " << arg << "\n"); + + this->ParentId = arg; +} + +// Set the window id of the new window once a WindowRemap is done. +void vtkWin32OpenGLRenderWindow::SetNextWindowId(HWND arg) +{ + vtkDebugMacro(<< "Setting NextWindowId to " << arg << "\n"); + + this->NextWindowId = arg; +} + +void vtkWin32OpenGLRenderWindow::SetNextWindowId(void *arg) +{ + this->SetNextWindowId((HWND)arg); +} + +// Begin the rendering process. +void vtkWin32OpenGLRenderWindow::Start(void) +{ + // if the renderer has not been initialized, do so now + if (!this->ContextId) + { + this->Initialize(); + } + + // set the current window + this->MakeCurrent(); +} + + +void vtkWin32OpenGLRenderWindow::SetOffScreenRendering(int offscreen) +{ + if (offscreen == this->OffScreenRendering) + { + return; + } + + this->vtkRenderWindow::SetOffScreenRendering(offscreen); + + if (offscreen) + { + int size[2]; + size[0] = (this->Size[0] > 0) ? this->Size[0] : 300; + size[1] = (this->Size[1] > 0) ? this->Size[1] : 300; + +#ifdef UNICODE + HDC dc = CreateDC(L"DISPLAY", 0, 0, 0); +#else + HDC dc = CreateDC("DISPLAY", 0, 0, 0); +#endif + this->SetupMemoryRendering(size[0], size[1], dc); + DeleteDC(dc); + } + else + { + if (!this->WindowId) + { + vtkRenderer* ren; + this->CleanUpOffScreenRendering(); + this->WindowInitialize(); + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(this); + } + this->OpenGLInit(); + if (this->Interactor) + { + this->Interactor->ReInitialize(); + } + this->DoubleBuffer = 1; + } + else + { + this->ResumeScreenRendering(); + } + } +} + +void vtkWin32OpenGLRenderWindow::CreateOffScreenDC(int xsize, int ysize, + HDC aHdc) +{ + int dataWidth = ((xsize*3+3)/4)*4; + + this->MemoryDataHeader.bmiHeader.biSize = 40; + this->MemoryDataHeader.bmiHeader.biWidth = xsize; + this->MemoryDataHeader.bmiHeader.biHeight = ysize; + this->MemoryDataHeader.bmiHeader.biPlanes = 1; + this->MemoryDataHeader.bmiHeader.biBitCount = 24; + this->MemoryDataHeader.bmiHeader.biCompression = BI_RGB; + this->MemoryDataHeader.bmiHeader.biClrUsed = 0; + this->MemoryDataHeader.bmiHeader.biClrImportant = 0; + this->MemoryDataHeader.bmiHeader.biSizeImage = dataWidth*ysize; + this->MemoryDataHeader.bmiHeader.biXPelsPerMeter = 10000; + this->MemoryDataHeader.bmiHeader.biYPelsPerMeter = 10000; + + HBITMAP dib = CreateDIBSection(aHdc, + &this->MemoryDataHeader, DIB_RGB_COLORS, + (void **)(&(this->MemoryData)), NULL, 0); + SIZE oldSize; + SetBitmapDimensionEx(dib, xsize, ysize, &oldSize); + // try using a DIBsection + this->CreateOffScreenDC(dib, aHdc); +} + +void vtkWin32OpenGLRenderWindow::CreateOffScreenDC(HBITMAP hbmp, HDC aHdc) +{ + BITMAP bm; + GetObject(hbmp, sizeof(BITMAP), &bm); + + this->MemoryBuffer = hbmp; + + // Create a compatible device context + this->MemoryHdc = (HDC)CreateCompatibleDC(aHdc); + + // Put the bitmap into the device context + SelectObject(this->MemoryHdc, this->MemoryBuffer); + + // Renderers will need to redraw anything cached in display lists + vtkRenderer *ren; + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(NULL); + } + + // adjust settings for renderwindow + this->Mapped =0; + this->Size[0] = bm.bmWidth; + this->Size[1] = bm.bmHeight; + + this->DeviceContext = this->MemoryHdc; + this->DoubleBuffer = 0; + this->SetupPixelFormat(this->DeviceContext, + PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI | + PFD_DRAW_TO_BITMAP, this->GetDebug(), 24, 32); + this->SetupPalette(this->DeviceContext); + this->ContextId = wglCreateContext(this->DeviceContext); + if (this->ContextId == NULL) + { + vtkErrorMacro("wglCreateContext failed in CreateOffScreenDC(), error: " << GetLastError()); + } + this->MakeCurrent(); + + // Renderers will need to redraw anything cached in display lists + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(this); + } + + this->OpenGLInit(); +} + +void vtkWin32OpenGLRenderWindow::SetupMemoryRendering(int xsize, int ysize, + HDC aHdc) +{ + // save the current state + this->ScreenMapped = this->Mapped; + this->ScreenWindowSize[0] = this->Size[0]; + this->ScreenWindowSize[1] = this->Size[1]; + this->ScreenDeviceContext = this->DeviceContext; + this->ScreenDoubleBuffer = this->DoubleBuffer; + this->ScreenContextId = this->ContextId; + + this->CreateOffScreenDC(xsize, ysize, aHdc); +} + +void vtkWin32OpenGLRenderWindow::SetupMemoryRendering(HBITMAP hbmp) +{ +#ifdef UNICODE + HDC dc = CreateDC(L"DISPLAY", 0, 0, 0); +#else + HDC dc = CreateDC("DISPLAY", 0, 0, 0); +#endif + + // save the current state + this->ScreenMapped = this->Mapped; + this->ScreenWindowSize[0] = this->Size[0]; + this->ScreenWindowSize[1] = this->Size[1]; + this->ScreenDeviceContext = this->DeviceContext; + this->ScreenDoubleBuffer = this->DoubleBuffer; + this->ScreenContextId = this->ContextId; + + this->CreateOffScreenDC(hbmp, dc); + DeleteDC(dc); +} + +HDC vtkWin32OpenGLRenderWindow::GetMemoryDC() +{ + return this->MemoryHdc; +} + +void vtkWin32OpenGLRenderWindow::CleanUpOffScreenRendering(void) +{ + if (!this->MemoryHdc) + { + return; + } + + GdiFlush(); + + // we need to release resources + vtkRenderer *ren; + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(NULL); + } + DeleteDC(this->MemoryHdc); + this->MemoryHdc = (HDC)0; + DeleteObject(this->MemoryBuffer); + if (wglDeleteContext(this->ContextId) != TRUE) + { + vtkErrorMacro("wglDeleteContext failed in CleanUpOffScreenRendering(), error: " << GetLastError()); + } +} + +void vtkWin32OpenGLRenderWindow::ResumeScreenRendering(void) +{ + this->CleanUpOffScreenRendering(); + this->Mapped = this->ScreenMapped; + this->Size[0] = this->ScreenWindowSize[0]; + this->Size[1] = this->ScreenWindowSize[1]; + this->DeviceContext = this->ScreenDeviceContext; + this->DoubleBuffer = this->ScreenDoubleBuffer; + this->ContextId = this->ScreenContextId; + this->MakeCurrent(); + + vtkRenderer* ren; + vtkCollectionSimpleIterator rsit; + for (this->Renderers->InitTraversal(rsit); + (ren = this->Renderers->GetNextRenderer(rsit));) + { + ren->SetRenderWindow(this); + } +} + +//---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::HideCursor() +{ + if (this->CursorHidden) + { + return; + } + this->CursorHidden = 1; + + ::ShowCursor(!this->CursorHidden); +} + +//---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::ShowCursor() +{ + if (!this->CursorHidden) + { + return; + } + this->CursorHidden = 0; + + ::ShowCursor(!this->CursorHidden); +} + +//---------------------------------------------------------------------------- +void vtkWin32OpenGLRenderWindow::SetCursorPosition(int x, int y) +{ + int *size = this->GetSize(); + + POINT point; + point.x = x; + point.y = size[1] - y - 1; + + if (ClientToScreen(this->WindowId, &point)) + { + SetCursorPos(point.x, point.y); + } +}; + +void vtkWin32OpenGLRenderWindow::SetCurrentCursor(int shape) +{ + if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) ) + { + return; + } + this->Superclass::SetCurrentCursor(shape); + LPCTSTR cursorName = 0; + switch (shape) + { + case VTK_CURSOR_DEFAULT: + case VTK_CURSOR_ARROW: + cursorName = IDC_ARROW; + break; + case VTK_CURSOR_SIZENE: + case VTK_CURSOR_SIZESW: + cursorName = IDC_SIZENESW; + break; + case VTK_CURSOR_SIZENW: + case VTK_CURSOR_SIZESE: + cursorName = IDC_SIZENWSE; + break; + case VTK_CURSOR_SIZENS: + cursorName = IDC_SIZENS; + break; + case VTK_CURSOR_SIZEWE: + cursorName = IDC_SIZEWE; + break; + case VTK_CURSOR_SIZEALL: + cursorName = IDC_SIZEALL; + break; + case VTK_CURSOR_HAND: +#if(WINVER >= 0x0500) + cursorName = IDC_HAND; +#else + cursorName = IDC_ARROW; +#endif + break; + } + + if (cursorName) + { + HANDLE cursor = + LoadImage(0,cursorName,IMAGE_CURSOR,0,0,LR_SHARED | LR_DEFAULTSIZE); + SetCursor((HCURSOR)cursor); + } +} diff --git a/Rendering/vtkWin32OpenGLRenderWindow.h b/Rendering/vtkWin32OpenGLRenderWindow.h new file mode 100644 index 0000000..81c5cde --- /dev/null +++ b/Rendering/vtkWin32OpenGLRenderWindow.h @@ -0,0 +1,269 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32OpenGLRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWin32OpenGLRenderWindow - OpenGL rendering window +// .SECTION Description +// vtkWin32OpenGLRenderWindow is a concrete implementation of the abstract +// class vtkRenderWindow. vtkWin32OpenGLRenderer interfaces to the standard +// OpenGL graphics library in the Windows/NT environment.. + +#ifndef __vtkWin32OpenGLRenderWindow_h +#define __vtkWin32OpenGLRenderWindow_h + +#include "vtkOpenGLRenderWindow.h" + +class vtkIdList; + +class VTK_RENDERING_EXPORT vtkWin32OpenGLRenderWindow : public vtkOpenGLRenderWindow +{ +public: + static vtkWin32OpenGLRenderWindow *New(); + vtkTypeRevisionMacro(vtkWin32OpenGLRenderWindow,vtkOpenGLRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Begin the rendering process. + virtual void Start(void); + + // Description: + // End the rendering process and display the image. + void Frame(void); + + // Description: + // Create the window + virtual void WindowInitialize(void); + + // Description: + // Initialize the rendering window. This will setup all system-specific + // resources. This method and Finalize() must be symmetric and it + // should be possible to call them multiple times, even changing WindowId + // in-between. This is what WindowRemap does. + virtual void Initialize(void); + + // Description: + // Finalize the rendering window. This will shutdown all system-specific + // resources. After having called this, it should be possible to destroy + // a window that was used for a SetWindowId() call without any ill effects. + virtual void Finalize(void); + + // Description: + // Change the window to fill the entire screen. + virtual void SetFullScreen(int); + + // Description: + // Remap the window. + virtual void WindowRemap(void); + + // Description: + // Set the preferred window size to full screen. + virtual void PrefFullScreen(void); + + // Description: + // Set the size of the window. + virtual void SetSize(int,int); + virtual void SetSize(int a[2]) {vtkOpenGLRenderWindow::SetSize(a);}; + + // Description: + // Get the current size of the window. + virtual int *GetSize(); + + // Description: + // Set the position of the window. + virtual void SetPosition(int,int); + virtual void SetPosition(int a[2]) {vtkOpenGLRenderWindow::SetPosition(a);}; + + // Description: + // Return the screen size. + virtual int *GetScreenSize(); + + // Description: + // Get the position in screen coordinates of the window. + virtual int *GetPosition(); + + // Description: + // Set the name of the window. This appears at the top of the window + // normally. + virtual void SetWindowName(const char *); + + // Description: + // Set this RenderWindow's window id to a pre-existing window. + void SetWindowInfo(char *); + + // Description: + // Sets the WindowInfo that will be used after a WindowRemap. + void SetNextWindowInfo(char *); + + // Description: + // Sets the HWND id of the window that WILL BE created. + void SetParentInfo(char *); + + //BTX + virtual void *GetGenericDisplayId() {return (void *)this->ContextId;}; + virtual void *GetGenericWindowId() {return (void *)this->WindowId;}; + virtual void *GetGenericParentId() {return (void *)this->ParentId;}; + virtual void *GetGenericContext() {return (void *)this->DeviceContext;}; + virtual void *GetGenericDrawable() {return (void *)this->WindowId;}; + virtual void SetDisplayId(void *); + + // Description: + // Get the window id. + virtual HWND GetWindowId(); + void SetWindowId(void *foo) {this->SetWindowId((HWND)foo);}; + + // Description: + // Set the window id to a pre-existing window. + virtual void SetWindowId(HWND); + + // Description: + // Set the window's parent id to a pre-existing window. + virtual void SetParentId(HWND); + void SetParentId(void *foo) {this->SetParentId((HWND)foo);}; + + void SetContextId(HGLRC); // hsr + void SetDeviceContext(HDC); // hsr + + // Description: + // Set the window id of the new window once a WindowRemap is done. + virtual void SetNextWindowId(HWND); + + // Description: + // Set the window id of the new window once a WindowRemap is done. + // This is the generic prototype as required by the vtkRenderWindow + // parent. + virtual void SetNextWindowId(void *arg); + + //ETX + + // Description: + // Prescribe that the window be created in a stereo-capable mode. This + // method must be called before the window is realized. This method + // overrides the superclass method since this class can actually check + // whether the window has been realized yet. + virtual void SetStereoCapableWindow(int capable); + + // Description: + // Make this windows OpenGL context the current context. + void MakeCurrent(); + + // Description: + // Get report of capabilities for the render window + const char *ReportCapabilities(); + + // Description: + // Does this render window support OpenGL? 0-false, 1-true + int SupportsOpenGL(); + + // Description: + // Is this render window using hardware acceleration? 0-false, 1-true + int IsDirect(); + + // Description: + // Check to see if a mouse button has been pressed. + // All other events are ignored by this method. + // This is a useful check to abort a long render. + virtual int GetEventPending(); + + // Description: + // These methods can be used by MFC applications + // to support print preview and printing, or more + // general rendering into memory. + void SetupMemoryRendering(int x, int y, HDC prn); + void SetupMemoryRendering(HBITMAP hbmp); + void ResumeScreenRendering(void); + HDC GetMemoryDC(); + unsigned char *GetMemoryData(){return this->MemoryData;}; + + // Description: + // Initialize OpenGL for this window. + virtual void SetupPalette(HDC hDC); + virtual void SetupPixelFormat(HDC hDC, DWORD dwFlags, int debug, + int bpp=16, int zbpp=16); + + // Description: + // Clean up device contexts, rendering contexts, etc. + void Clean(); + + // Description: + // Hide or Show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + // Set cursor position in window (note that (0,0) is the lower left + // corner). + void HideCursor(); + void ShowCursor(); + void SetCursorPosition(int x, int y); + + // Description: + // Change the shape of the cursor + virtual void SetCurrentCursor(int); + + // Description: + // Override the default implementation so that we can actively switch between + // on and off screen rendering. + virtual void SetOffScreenRendering(int offscreen); + +protected: + vtkWin32OpenGLRenderWindow(); + ~vtkWin32OpenGLRenderWindow(); + + HINSTANCE ApplicationInstance; + HPALETTE Palette; + HPALETTE OldPalette; + HGLRC ContextId; + HDC DeviceContext; + BOOL MFChandledWindow; + HWND WindowId; + HWND ParentId; + HWND NextWindowId; + int OwnWindow; + int ScreenSize[2]; + + // the following is used to support rendering into memory + BITMAPINFO MemoryDataHeader; + HBITMAP MemoryBuffer; + unsigned char *MemoryData; // the data in the DIBSection + HDC MemoryHdc; + + int ScreenMapped; + int ScreenWindowSize[2]; + HDC ScreenDeviceContext; + int ScreenDoubleBuffer; + HGLRC ScreenContextId; + + //BTX + // message handler + virtual LRESULT MessageProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam); + + static LRESULT APIENTRY WndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam); + //ETX + int CursorHidden; + int ForceMakeCurrent; + + char *Capabilities; + + void ResizeWhileOffscreen(int xsize, int ysize); + void CreateAWindow(int x, int y, int width, int height); + void InitializeApplication(); + void CleanUpOffScreenRendering(void); + void CreateOffScreenDC(int xsize, int ysize, HDC aHdc); + void CreateOffScreenDC(HBITMAP hbmp, HDC aHdc); +private: + vtkWin32OpenGLRenderWindow(const vtkWin32OpenGLRenderWindow&); // Not implemented. + void operator=(const vtkWin32OpenGLRenderWindow&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkWin32RenderWindowInteractor.cxx b/Rendering/vtkWin32RenderWindowInteractor.cxx new file mode 100644 index 0000000..2f9002d --- /dev/null +++ b/Rendering/vtkWin32RenderWindowInteractor.cxx @@ -0,0 +1,803 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32RenderWindowInteractor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include +#include +#include +#include + +#define _WIN32_WINNT 0x0400 // for trackmouseevent support requires Win95 with IE 3.0 or greater. + +#include "vtkWin32OpenGLRenderWindow.h" + +// Mouse wheel support +// In an ideal world we would just have to include , but it is not +// always available with all compilers/headers +#ifndef WM_MOUSEWHEEL +# define WM_MOUSEWHEEL 0x020A +#endif //WM_MOUSEWHEEL +#ifndef GET_WHEEL_DELTA_WPARAM +# define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam)) +#endif //GET_WHEEL_DELTA_WPARAM + +// MSVC does the right thing without the forward declaration when it +// sees it in the friend decl in vtkWin32RenderWindowInteractor, but +// GCC needs to see the declaration beforehand. It has to do with the +// CALLBACK attribute. +VTK_RENDERING_EXPORT LRESULT CALLBACK vtkHandleMessage(HWND,UINT,WPARAM,LPARAM); +VTK_RENDERING_EXPORT LRESULT CALLBACK vtkHandleMessage2(HWND,UINT,WPARAM,LPARAM,class vtkWin32RenderWindowInteractor*); + +#include "vtkWin32RenderWindowInteractor.h" +#include "vtkActor.h" +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET +#pragma warning ( disable : 4311 ) +#pragma warning ( disable : 4312 ) +# define vtkGetWindowLong GetWindowLongPtr +# define vtkSetWindowLong SetWindowLongPtr +# define vtkGWL_WNDPROC GWLP_WNDPROC +#else // regular Visual studio +# define vtkGetWindowLong GetWindowLong +# define vtkSetWindowLong SetWindowLong +# define vtkGWL_WNDPROC GWL_WNDPROC +#endif // + + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkWin32RenderWindowInteractor, "$Revision: 1.94.2.1 $"); +vtkStandardNewMacro(vtkWin32RenderWindowInteractor); +#endif + + + +void (*vtkWin32RenderWindowInteractor::ClassExitMethod)(void *) = (void (*)(void *))NULL; +void *vtkWin32RenderWindowInteractor::ClassExitMethodArg = (void *)NULL; +void (*vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)(void *) = (void (*)(void *))NULL; + +// Construct object so that light follows camera motion. +vtkWin32RenderWindowInteractor::vtkWin32RenderWindowInteractor() +{ + static int timerId = 1; + this->WindowId = 0; + this->TimerId = timerId++; + this->InstallMessageProc = 1; + this->MouseInWindow = 0; +} + +vtkWin32RenderWindowInteractor::~vtkWin32RenderWindowInteractor() +{ + vtkWin32OpenGLRenderWindow *tmp; + + // we need to release any hold we have on a windows event loop + if (this->WindowId && this->Enabled && this->InstallMessageProc) + { + vtkWin32OpenGLRenderWindow *ren; + ren = static_cast(this->RenderWindow); + tmp = (vtkWin32OpenGLRenderWindow *)(vtkGetWindowLong(this->WindowId,4)); + // watch for odd conditions + if ((tmp != ren) && (ren != NULL)) + { + // OK someone else has a hold on our event handler + // so lets have them handle this stuff + // well send a USER message to the other + // event handler so that it can properly + // call this event handler if required + CallWindowProc(this->OldProc,this->WindowId,WM_USER+14,28,(LONG)this->OldProc); + } + else + { + vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(LONG)this->OldProc); + } + this->Enabled = 0; + } +} + +void vtkWin32RenderWindowInteractor::Start() +{ + // Let the compositing handle the event loop if it wants to. + if (this->HasObserver(vtkCommand::StartEvent)) + { + this->InvokeEvent(vtkCommand::StartEvent,NULL); + return; + } + + // No need to do anything if this is a 'mapped' interactor + if (!this->Enabled || !this->InstallMessageProc) + { + return; + } + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +// Begin processing keyboard strokes. +void vtkWin32RenderWindowInteractor::Initialize() +{ + vtkWin32OpenGLRenderWindow *ren; + int *size; + + // make sure we have a RenderWindow and camera + if ( ! this->RenderWindow) + { + vtkErrorMacro(<<"No renderer defined!"); + return; + } + if (this->Initialized) + { + return; + } + this->Initialized = 1; + // get the info we need from the RenderingWindow + ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow); + ren->Start(); + size = ren->GetSize(); + ren->GetPosition(); + this->WindowId = ren->GetWindowId(); + this->Enable(); + this->Size[0] = size[0]; + this->Size[1] = size[1]; +} + +void vtkWin32RenderWindowInteractor::Enable() +{ + vtkWin32OpenGLRenderWindow *ren; + vtkWin32OpenGLRenderWindow *tmp; + if (this->Enabled) + { + return; + } + if (this->InstallMessageProc) + { + // add our callback + ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow); + this->OldProc = (WNDPROC)vtkGetWindowLong(this->WindowId,vtkGWL_WNDPROC); + tmp=(vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(this->WindowId,4); + // watch for odd conditions + if (tmp != ren) + { + // OK someone else has a hold on our event handler + // so lets have them handle this stuff + // well send a USER message to the other + // event handler so that it can properly + // call this event handler if required + CallWindowProc(this->OldProc,this->WindowId,WM_USER+12,24,(LONG)vtkHandleMessage); + } + else + { + vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(LONG)vtkHandleMessage); + } + // in case the size of the window has changed while we were away + int *size; + size = ren->GetSize(); + this->Size[0] = size[0]; + this->Size[1] = size[1]; + } + this->Enabled = 1; + this->Modified(); +} + + +void vtkWin32RenderWindowInteractor::Disable() +{ + vtkWin32OpenGLRenderWindow *tmp; + if (!this->Enabled) + { + return; + } + + if (this->InstallMessageProc && this->Enabled && this->WindowId) + { + // we need to release any hold we have on a windows event loop + vtkWin32OpenGLRenderWindow *ren; + ren = (vtkWin32OpenGLRenderWindow *)(this->RenderWindow); + tmp = (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(this->WindowId,4); + // watch for odd conditions + if ((tmp != ren) && (ren != NULL)) + { + // OK someone else has a hold on our event handler + // so lets have them handle this stuff + // well send a USER message to the other + // event handler so that it can properly + // call this event handler if required + CallWindowProc(this->OldProc,this->WindowId,WM_USER+14,28,(LONG)this->OldProc); + } + else + { + vtkSetWindowLong(this->WindowId,vtkGWL_WNDPROC,(LONG)this->OldProc); + } + } + this->Enabled = 0; + this->Modified(); +} + +void vtkWin32RenderWindowInteractor::TerminateApp(void) +{ + PostQuitMessage(0); +} + +int vtkWin32RenderWindowInteractor::CreateTimer(int timertype) +{ + if (timertype==VTKI_TIMER_FIRST) + { + return SetTimer(this->WindowId,this->TimerId,10,NULL); + } + return 1; +} + +int vtkWin32RenderWindowInteractor::DestroyTimer(void) +{ + return KillTimer(this->WindowId,this->TimerId); +} + +//------------------------------------------------------------- +// Virtual Key Code to Unix KeySym Conversion +//------------------------------------------------------------- + +// this ascii code to keysym table is meant to mimic Tk + +static char *AsciiToKeySymTable[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", + "parenleft", "parenright", "asterisk", "plus", + "comma", "minus", "period", "slash", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "colon", "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", "E", "F", "G", + "H", "I", "J", "K", "L", "M", "N", "O", + "P", "Q", "R", "S", "T", "U", "V", "W", + "X", "Y", "Z", "bracketleft", + "backslash", "bracketright", "asciicircum", "underscore", + "quoteleft", "a", "b", "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", "m", "n", "o", + "p", "q", "r", "s", "t", "u", "v", "w", + "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Delete", + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +// this virtual key code to keysym table is meant to mimic Tk + +static char *VKeyCodeToKeySymTable[] = { + 0, 0, 0, "Cancel", 0, 0, 0, 0, + "BackSpace", "Tab", 0, 0, "Clear", "Return", 0, 0, + "Shift_L", "Control_L", "Alt_L", "Pause", "Caps_Lock", 0,0,0, + 0, 0, 0, "Escape", 0, 0, 0, 0, + "space", "Prior", "Next", "End", "Home", "Left", "Up", "Right", + "Down", "Select", 0, "Execute", "Snapshot", "Insert", "Delete", "Help", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", 0, 0, 0, 0, 0, 0, + 0, "a", "b", "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", "m", "n", "o", + "p", "q", "r", "s", "t", "u", "v", "w", + "x", "y", "z", "Win_L", "Win_R", "App", 0, 0, + "KP_0", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7", + "KP_8", "KP_9", "asterisk", "plus", "bar", "minus", "period", "slash", + "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", + "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", + "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", + 0, 0, 0, 0, 0, 0, 0, 0, + "Num_Lock", "Scroll_Lock", 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +//------------------------------------------------------------- +// Event loop handlers +//------------------------------------------------------------- +void vtkWin32RenderWindowInteractor::OnMouseMove(HWND hWnd, UINT nFlags, + int X, int Y) +{ + if (!this->Enabled) + { + return; + } + + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT); + if (!this->MouseInWindow && + (X >= 0 && X < this->Size[0] && Y >= 0 && Y < this->Size[1])) + { + this->InvokeEvent(vtkCommand::EnterEvent, NULL); + this->MouseInWindow = 1; + // request WM_MOUSELEAVE generation + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + TrackMouseEvent(&tme); + } + + this->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); +} + +void vtkWin32RenderWindowInteractor::OnNCMouseMove(HWND, UINT nFlags, + int X, int Y) +{ + if (!this->Enabled) + { + return; + } + + int *pos = this->RenderWindow->GetPosition(); + if (this->MouseInWindow) + { + this->SetEventInformationFlipY(X - pos[0], + Y - pos[1], + nFlags & MK_CONTROL, + nFlags & MK_SHIFT); + this->InvokeEvent(vtkCommand::LeaveEvent, NULL); + this->MouseInWindow = 0; + } +} + +void vtkWin32RenderWindowInteractor::OnMouseWheelForward(HWND,UINT nFlags, + int X, int Y) +{ + if (!this->Enabled) + { + return; + } + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT); + this->InvokeEvent(vtkCommand::MouseWheelForwardEvent,NULL); +} + +void vtkWin32RenderWindowInteractor::OnMouseWheelBackward(HWND,UINT nFlags, + int X, int Y) +{ + if (!this->Enabled) + { + return; + } + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT); + this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent,NULL); +} + +void vtkWin32RenderWindowInteractor::OnLButtonDown(HWND wnd,UINT nFlags, + int X, int Y, int repeat) +{ + if (!this->Enabled) + { + return; + } + SetCapture(wnd); + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT, + 0, repeat); + this->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); +} + +void vtkWin32RenderWindowInteractor::OnLButtonUp(HWND,UINT nFlags, + int X, int Y) +{ + if (!this->Enabled) + { + return; + } + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT); + this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL); + ReleaseCapture( ); +} + +void vtkWin32RenderWindowInteractor::OnMButtonDown(HWND wnd,UINT nFlags, + int X, int Y, int repeat) +{ + if (!this->Enabled) + { + return; + } + SetCapture(wnd); + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT, + 0, repeat); + this->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL); +} + +void vtkWin32RenderWindowInteractor::OnMButtonUp(HWND,UINT nFlags, + int X, int Y) +{ + if (!this->Enabled) + { + return; + } + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT); + this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL); + ReleaseCapture( ); +} + +void vtkWin32RenderWindowInteractor::OnRButtonDown(HWND wnd,UINT nFlags, + int X, int Y, int repeat) +{ + if (!this->Enabled) + { + return; + } + SetCapture(wnd ); + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT, + 0, repeat); + this->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL); +} + +void vtkWin32RenderWindowInteractor::OnRButtonUp(HWND,UINT nFlags, + int X, int Y) +{ + if (!this->Enabled) + { + return; + } + this->SetEventInformationFlipY(X, + Y, + nFlags & MK_CONTROL, + nFlags & MK_SHIFT); + this->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL); + ReleaseCapture( ); +} + +void vtkWin32RenderWindowInteractor::OnSize(HWND,UINT, int X, int Y) { + this->UpdateSize(X,Y); + if (this->Enabled) + { + this->InvokeEvent(vtkCommand::ConfigureEvent,NULL); + } +} + +void vtkWin32RenderWindowInteractor::OnTimer(HWND,UINT) +{ + if (!this->Enabled) + { + return; + } + this->InvokeEvent(vtkCommand::TimerEvent,NULL); +} + +void vtkWin32RenderWindowInteractor::OnKeyDown(HWND, UINT vCode, UINT nRepCnt, UINT nFlags) +{ + if (!this->Enabled) + { + return; + } + int ctrl = GetKeyState(VK_CONTROL) & (~1); + int shift = GetKeyState(VK_SHIFT) & (~1); + WORD nChar = 0; + { +#ifndef _WIN32_WCE + BYTE keyState[256]; + GetKeyboardState(keyState); + if (ToAscii(vCode,nFlags & 0xff,keyState,&nChar,0) == 0) + { + nChar = 0; + } +#endif + } + char *keysym = AsciiToKeySymTable[(unsigned char)nChar]; + if (keysym == 0) + { + keysym = VKeyCodeToKeySymTable[(unsigned char)vCode]; + } + if (keysym == 0) + { + keysym = "None"; + } + this->SetKeyEventInformation(ctrl, + shift, + nChar, + nRepCnt, + keysym); + this->InvokeEvent(vtkCommand::KeyPressEvent, NULL); +} + +void vtkWin32RenderWindowInteractor::OnKeyUp(HWND, UINT vCode, UINT nRepCnt, UINT nFlags) +{ + if (!this->Enabled) + { + return; + } + int ctrl = GetKeyState(VK_CONTROL) & (~1); + int shift = GetKeyState(VK_SHIFT) & (~1); + WORD nChar = 0; + { + BYTE keyState[256]; +#ifndef _WIN32_WCE + GetKeyboardState(keyState); + if (ToAscii(vCode,nFlags & 0xff,keyState,&nChar,0) == 0) + { + nChar = 0; + } +#endif + } + char *keysym = AsciiToKeySymTable[(unsigned char)nChar]; + if (keysym == 0) + { + keysym = VKeyCodeToKeySymTable[(unsigned char)vCode]; + } + if (keysym == 0) + { + keysym = "None"; + } + this->SetKeyEventInformation(ctrl, + shift, + nChar, + nRepCnt, + keysym); + this->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL); +} + +void vtkWin32RenderWindowInteractor::OnChar(HWND,UINT nChar, + UINT nRepCnt, UINT) +{ + if (!this->Enabled) + { + return; + } + int ctrl = GetKeyState(VK_CONTROL) & (~1); + int shift = GetKeyState(VK_SHIFT) & (~1); + this->SetKeyEventInformation(ctrl, + shift, + nChar, + nRepCnt); + this->InvokeEvent(vtkCommand::CharEvent, NULL); +} + +// This is only called when InstallMessageProc is true +LRESULT CALLBACK vtkHandleMessage(HWND hWnd,UINT uMsg, WPARAM wParam, + LPARAM lParam) +{ + vtkWin32OpenGLRenderWindow *ren; + vtkWin32RenderWindowInteractor *me; + + ren = (vtkWin32OpenGLRenderWindow *)vtkGetWindowLong(hWnd,4); + if (ren == NULL) + { + return 0; + } + + me = (vtkWin32RenderWindowInteractor *)ren->GetInteractor(); + + if (me == NULL) + { + return 0; + } + return vtkHandleMessage2(hWnd,uMsg,wParam, lParam, me); +} + +#ifndef MAKEPOINTS +#define MAKEPOINTS(l) (*((POINTS FAR *) & (l))) +#endif + +LRESULT CALLBACK vtkHandleMessage2(HWND hWnd,UINT uMsg, WPARAM wParam, + LPARAM lParam, + vtkWin32RenderWindowInteractor *me) +{ + if ((uMsg == WM_USER+13)&&(wParam == 26)) + { + // someone is telling us to set our OldProc + me->OldProc = (WNDPROC)lParam; + return 1; + } + + switch (uMsg) + { + case WM_PAINT: + me->Render(); + return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam); + break; + + case WM_SIZE: + me->OnSize(hWnd,wParam,LOWORD(lParam),HIWORD(lParam)); + return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam); + break; + + case WM_LBUTTONDBLCLK: + me->OnLButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1); + break; + + case WM_LBUTTONDOWN: + me->OnLButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0); + break; + + case WM_LBUTTONUP: + me->OnLButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); + break; + + case WM_MBUTTONDBLCLK: + me->OnMButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1); + break; + + case WM_MBUTTONDOWN: + me->OnMButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0); + break; + + case WM_MBUTTONUP: + me->OnMButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); + break; + + case WM_RBUTTONDBLCLK: + me->OnRButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 1); + break; + + case WM_RBUTTONDOWN: + me->OnRButtonDown(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y, 0); + break; + + case WM_RBUTTONUP: + me->OnRButtonUp(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); + break; + + case WM_MOUSELEAVE: + me->InvokeEvent(vtkCommand::LeaveEvent, NULL); + me->MouseInWindow = 0; + break; + + case WM_MOUSEMOVE: + me->OnMouseMove(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); + break; + + case WM_MOUSEWHEEL: + if( GET_WHEEL_DELTA_WPARAM(wParam) > 0) + me->OnMouseWheelForward(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); + else + me->OnMouseWheelBackward(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); + break; + +#ifdef WM_MCVMOUSEMOVE + case WM_NCMOUSEMOVE: + me->OnNCMouseMove(hWnd,wParam,MAKEPOINTS(lParam).x,MAKEPOINTS(lParam).y); + break; +#endif + + case WM_CLOSE: + // Don't know what to put here ! Why so many callbacks ? + if (me->HasObserver(vtkCommand::ExitEvent)) + { + me->InvokeEvent(vtkCommand::ExitEvent,NULL); + } + else if (me->ClassExitMethod) + { + (*me->ClassExitMethod)(me->ClassExitMethodArg); + } + else + { + // Add a else condition to override the ExitEvent, and allow for example + // a message box: "Are you sure you want to quit?" + me->TerminateApp(); + } + break; + + case WM_CHAR: + me->OnChar(hWnd,wParam,LOWORD(lParam),HIWORD(lParam)); + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + me->OnKeyDown(hWnd,wParam,LOWORD(lParam),HIWORD(lParam)); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + me->OnKeyUp(hWnd,wParam,LOWORD(lParam),HIWORD(lParam)); + break; + + case WM_TIMER: + me->OnTimer(hWnd,wParam); + + break; + default: + if (me) + { + return CallWindowProc(me->OldProc,hWnd,uMsg,wParam,lParam); + } + }; + return 0; +} + + +//---------------------------------------------------------------------------- +// Specify the default function to be called when an interactor needs to exit. +// This callback is overridden by an instance ExitMethod that is defined. +void +vtkWin32RenderWindowInteractor::SetClassExitMethod(void (*f)(void *),void *arg) +{ + if ( f != vtkWin32RenderWindowInteractor::ClassExitMethod + || arg != vtkWin32RenderWindowInteractor::ClassExitMethodArg) + { + // delete the current arg if there is a delete method + if ((vtkWin32RenderWindowInteractor::ClassExitMethodArg) + && (vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete)) + { + (*vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete) + (vtkWin32RenderWindowInteractor::ClassExitMethodArg); + } + vtkWin32RenderWindowInteractor::ClassExitMethod = f; + vtkWin32RenderWindowInteractor::ClassExitMethodArg = arg; + + // no call to this->Modified() since this is a class member function + } +} + + +//---------------------------------------------------------------------------- +// Set the arg delete method. This is used to free user memory. +void +vtkWin32RenderWindowInteractor::SetClassExitMethodArgDelete(void (*f)(void *)) +{ + if (f != vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete) + { + vtkWin32RenderWindowInteractor::ClassExitMethodArgDelete = f; + + // no call to this->Modified() since this is a class member function + } +} + +//---------------------------------------------------------------------------- +void vtkWin32RenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "InstallMessageProc: " << this->InstallMessageProc << endl; +} + +//---------------------------------------------------------------------------- +void vtkWin32RenderWindowInteractor::ExitCallback() +{ + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent,NULL); + } + else if (this->ClassExitMethod) + { + (*this->ClassExitMethod)(this->ClassExitMethodArg); + } + this->TerminateApp(); +} + + diff --git a/Rendering/vtkWin32RenderWindowInteractor.h b/Rendering/vtkWin32RenderWindowInteractor.h new file mode 100644 index 0000000..2f17596 --- /dev/null +++ b/Rendering/vtkWin32RenderWindowInteractor.h @@ -0,0 +1,147 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32RenderWindowInteractor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWin32RenderWindowInteractor - implements Win32 specific functions +// required by vtkRenderWindowInteractor. +// +// .SECTION Description +// By default the interactor installs a MessageProc callback which +// intercepts windows' messages to the window and controls interactions by +// routing them to the InteractoStyle classes. +// MFC or BCB programs can prevent this and instead directly route any mouse/key +// messages into the event bindings by setting InstallMessageProc to false. +// This provides a minimal "Mapped" mode of interaction +// +#ifndef __vtkWin32RenderWindowInteractor_h +#define __vtkWin32RenderWindowInteractor_h + +#include "vtkRenderWindowInteractor.h" +#include "vtkWindows.h" // For windows API. + +class VTK_RENDERING_EXPORT vtkWin32RenderWindowInteractor : public vtkRenderWindowInteractor +{ +public: + // Description: + // Construct object so that light follows camera motion. + static vtkWin32RenderWindowInteractor *New(); + + vtkTypeRevisionMacro(vtkWin32RenderWindowInteractor,vtkRenderWindowInteractor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initialize the event handler + virtual void Initialize(); + + // Description: + // Enable/Disable interactions. By default interactors are enabled when + // initialized. Initialize() must be called prior to enabling/disabling + // interaction. These methods are used when a window/widget is being + // shared by multiple renderers and interactors. This allows a "modal" + // display where one interactor is active when its data is to be displayed + // and all other interactors associated with the widget are disabled + // when their data is not displayed. + virtual void Enable(); + virtual void Disable(); + + // Description: + // This will start up the event loop and never return. If you + // call this method it will loop processing events until the + // application is exited. + virtual void Start(); + + // Description: + // By default the interactor installs a MessageProc callback which + // intercepts windows messages to the window and controls interactions. + // MFC or BCB programs can prevent this and instead directly route any mouse/key + // messages into the event bindings by setting InstallMessgeProc to false. + vtkSetMacro(InstallMessageProc,int); + vtkGetMacro(InstallMessageProc,int); + vtkBooleanMacro(InstallMessageProc,int); + + // Description: + // Win32 specific application terminate, calls ClassExitMethod then + // calls PostQuitMessage(0) to terminate the application. An application can Specify + // ExitMethod for alternative behavior (i.e. suppression of keyboard exit) + void TerminateApp(void); + + // Description: + // Win32 timer methods + int CreateTimer(int timertype); + int DestroyTimer(void); + + //BTX + friend VTK_RENDERING_EXPORT LRESULT CALLBACK vtkHandleMessage(HWND hwnd,UINT uMsg, WPARAM w, LPARAM l); + friend VTK_RENDERING_EXPORT LRESULT CALLBACK vtkHandleMessage2(HWND hwnd,UINT uMsg, WPARAM w, LPARAM l, vtkWin32RenderWindowInteractor *me); + + // Description: + // Various methods that a Win32 window can redirect to this class to be + // handled. + virtual void OnMouseMove (HWND wnd, UINT nFlags, int X, int Y); + virtual void OnNCMouseMove(HWND wnd, UINT nFlags, int X, int Y); + virtual void OnRButtonDown(HWND wnd, UINT nFlags, int X, int Y, int repeat=0); + virtual void OnRButtonUp (HWND wnd, UINT nFlags, int X, int Y); + virtual void OnMButtonDown(HWND wnd, UINT nFlags, int X, int Y, int repeat=0); + virtual void OnMButtonUp (HWND wnd, UINT nFlags, int X, int Y); + virtual void OnLButtonDown(HWND wnd, UINT nFlags, int X, int Y, int repeat=0); + virtual void OnLButtonUp (HWND wnd, UINT nFlags, int X, int Y); + virtual void OnSize (HWND wnd, UINT nType, int X, int Y); + virtual void OnTimer (HWND wnd, UINT nIDEvent); + virtual void OnKeyDown (HWND wnd, UINT nChar, UINT nRepCnt, UINT nFlags); + virtual void OnKeyUp (HWND wnd, UINT nChar, UINT nRepCnt, UINT nFlags); + virtual void OnChar (HWND wnd, UINT nChar, UINT nRepCnt, UINT nFlags); + virtual void OnMouseWheelForward (HWND wnd, UINT nFlags, int X, int Y); + virtual void OnMouseWheelBackward(HWND wnd, UINT nFlags, int X, int Y); + //ETX + + // Description: + // Methods to set the default exit method for the class. This method is + // only used if no instance level ExitMethod has been defined. It is + // provided as a means to control how an interactor is exited given + // the various language bindings (tcl, Win32, etc.). + static void SetClassExitMethod(void (*f)(void *), void *arg); + static void SetClassExitMethodArgDelete(void (*f)(void *)); + + // Description: + // These methods correspond to the the Exit, User and Pick + // callbacks. They allow for the Style to invoke them. + virtual void ExitCallback(); + +protected: + vtkWin32RenderWindowInteractor(); + ~vtkWin32RenderWindowInteractor(); + + HWND WindowId; + UINT TimerId; + WNDPROC OldProc; + int InstallMessageProc; + + int MouseInWindow; + + //BTX + // Description: + // Class variables so an exit method can be defined for this class + // (used to set different exit methods for various language bindings, + // i.e. tcl, java, Win32) + static void (*ClassExitMethod)(void *); + static void (*ClassExitMethodArgDelete)(void *); + static void *ClassExitMethodArg; + //ETX + +private: + vtkWin32RenderWindowInteractor(const vtkWin32RenderWindowInteractor&); // Not implemented. + void operator=(const vtkWin32RenderWindowInteractor&); // Not implemented. +}; + +#endif + diff --git a/Rendering/vtkWinCEOpenGLRenderWindow.cxx b/Rendering/vtkWinCEOpenGLRenderWindow.cxx new file mode 100644 index 0000000..854d2d8 --- /dev/null +++ b/Rendering/vtkWinCEOpenGLRenderWindow.cxx @@ -0,0 +1,752 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWinCEOpenGLRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include +#include "vtkWinCEOpenGLRenderWindow.h" +#include "vtkWin32RenderWindowInteractor.h" +#include "vtkOpenGL.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLProperty.h" +#include "vtkOpenGLTexture.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLActor.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLPolyDataMapper.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkWinCEOpenGLRenderWindow, "$Revision: 1.12 $"); +vtkStandardNewMacro(vtkWinCEOpenGLRenderWindow); + +#define VTK_MAX_LIGHTS 8 + +// a couple of routines for offscreen rendering +void vtkOSMesaDestroyWindow(void *Window) +{ + free(Window); +} + +void *vtkOSMesaCreateWindow(int width, int height) +{ + return malloc(width*height*4); +} + +vtkWinCEOpenGLRenderWindow::vtkWinCEOpenGLRenderWindow() +{ + this->OffScreenContextId = NULL; + this->OffScreenWindow = NULL; + this->ApplicationInstance = NULL; + this->WindowId = 0; + this->ParentId = 0; + this->NextWindowId = 0; + this->DeviceContext = (HDC)0; // hsr + this->StereoType = VTK_STEREO_CRYSTAL_EYES; + this->CursorHidden = 0; + this->ForceMakeCurrent = 0; +} + +vtkWinCEOpenGLRenderWindow::~vtkWinCEOpenGLRenderWindow() +{ + this->Finalize(); +} + +void vtkWinCEOpenGLRenderWindow::Clean() +{ + vtkRenderer *ren; + GLuint id; + + /* finish OpenGL rendering */ + if (this->OffScreenContextId) + { + this->MakeCurrent(); + + /* first delete all the old lights */ + for (short cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+VTK_MAX_LIGHTS; cur_light++) + { + glDisable((GLenum)cur_light); + } + + /* now delete all textures */ + glDisable(GL_TEXTURE_2D); + for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++) + { + id = (GLuint) this->TextureResourceIds->GetId(i); +#ifdef GL_VERSION_1_1 + if (glIsTexture(id)) + { + glDeleteTextures(1, &id); + } +#else + if (glIsList(id)) + { + glDeleteLists(id,1); + } +#endif + } + + // tell each of the renderers that this render window/graphics context + // is being removed (the RendererCollection is removed by vtkRenderWindow's + // destructor) + this->Renderers->InitTraversal(); + for ( ren = (vtkOpenGLRenderer *) this->Renderers->GetNextItemAsObject(); + ren != NULL; + ren = (vtkOpenGLRenderer *) this->Renderers->GetNextItemAsObject() ) + { + ren->SetRenderWindow(NULL); + } + + OSMesaDestroyContext(this->OffScreenContextId); + this->OffScreenContextId = NULL; + vtkOSMesaDestroyWindow(this->OffScreenWindow); + this->OffScreenWindow = NULL; + } +} + +LRESULT APIENTRY vtkWinCEOpenGLRenderWindow::WndProc(HWND hWnd, UINT message, + WPARAM wParam, + LPARAM lParam) +{ + vtkWinCEOpenGLRenderWindow *me = + (vtkWinCEOpenGLRenderWindow *)GetWindowLong(hWnd,4); + + // forward to actual object + if (me) + { + return me->MessageProc(hWnd, message, wParam, lParam); + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +void vtkWinCEOpenGLRenderWindow::SetWindowName( char * _arg ) +{ + vtkWindow::SetWindowName(_arg); + if (this->WindowId) + { +// SetWindowText(this->WindowId,this->WindowName); + } +} + +int vtkWinCEOpenGLRenderWindow::GetEventPending() +{ + MSG msg; + + return PeekMessage(&msg,this->WindowId,WM_LBUTTONDOWN,WM_MBUTTONDOWN,PM_NOREMOVE); +} + +void vtkWinCEOpenGLRenderWindow::MakeCurrent() +{ + if (this->OffScreenContextId || this->ForceMakeCurrent) + { + if (OSMesaMakeCurrent(this->OffScreenContextId, + this->OffScreenWindow, GL_UNSIGNED_BYTE, + this->Size[0], this->Size[1]) != GL_TRUE) + { + vtkWarningMacro("failed call to OSMesaMakeCurrent"); + } + this->ForceMakeCurrent = 0; + } +} + +void vtkWinCEOpenGLRenderWindow::SetForceMakeCurrent() +{ + this->ForceMakeCurrent = 1; +} + +void vtkWinCEOpenGLRenderWindow::SetSize(int x, int y) +{ + static int resizing = 0; + + if ((this->Size[0] != x) || (this->Size[1] != y)) + { + this->Modified(); + this->Size[0] = x; + this->Size[1] = y; + if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + if (this->ParentId) + { + SetWindowPos(this->WindowId,HWND_TOP,0,0, + x, y, SWP_NOMOVE | SWP_NOZORDER); + } + else + { + SetWindowPos(this->WindowId,HWND_TOP,0,0, + x, y, + SWP_NOMOVE | SWP_NOZORDER); + } + OSMesaDestroyContext(this->OffScreenContextId); + this->OffScreenContextId = NULL; + vtkOSMesaDestroyWindow(this->OffScreenWindow); + this->OffScreenWindow = vtkOSMesaCreateWindow(x,y); + this->OwnWindow = 1; + this->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL); + this->MakeCurrent(); + this->OpenGLInit(); + this->Mapped = 1; + resizing = 0; + } + } + } +} + +void vtkWinCEOpenGLRenderWindow::SetPosition(int x, int y) +{ + static int resizing = 0; + + if ((this->Position[0] != x) || (this->Position[1] != y)) + { + this->Modified(); + this->Position[0] = x; + this->Position[1] = y; + if (this->Mapped) + { + if (!resizing) + { + resizing = 1; + + SetWindowPos(this->WindowId,HWND_TOP,x,y, + 0, 0, SWP_NOSIZE | SWP_NOZORDER); + resizing = 0; + } + } + } +} + + +// End the rendering process and display the image. +void vtkWinCEOpenGLRenderWindow::Frame(void) +{ + this->MakeCurrent(); + if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers) + { + BITMAPINFO MemoryDataHeader; + unsigned char *MemoryData; // the data in the DIBSection + HDC MemoryHdc; + + int dataWidth = ((this->Size[0]*3+3)/4)*4; + + MemoryDataHeader.bmiHeader.biSize = 40; + MemoryDataHeader.bmiHeader.biWidth = this->Size[0]; + MemoryDataHeader.bmiHeader.biHeight = this->Size[1]; + MemoryDataHeader.bmiHeader.biPlanes = 1; + MemoryDataHeader.bmiHeader.biBitCount = 24; + MemoryDataHeader.bmiHeader.biCompression = BI_RGB; + MemoryDataHeader.bmiHeader.biClrUsed = 0; + MemoryDataHeader.bmiHeader.biClrImportant = 0; + MemoryDataHeader.bmiHeader.biSizeImage = dataWidth*this->Size[1]; + + HBITMAP dib = CreateDIBSection(this->DeviceContext, + &MemoryDataHeader, DIB_RGB_COLORS, + (void **)(&(MemoryData)), NULL, 0); + + // copy the data form mesa to dib + int x, y; + for (y = 0; y < this->Size[1]; ++y) + { + int ytot = y*this->Size[0]; + for (x = 0; x < this->Size[0]; ++x) + { + MemoryData[(x+ytot)*3] = ((unsigned char *)this->OffScreenWindow)[(x+ytot)*4+2]; + MemoryData[(x+ytot)*3 + 1] = ((unsigned char *)this->OffScreenWindow)[(x+ytot)*4+1]; + MemoryData[(x+ytot)*3 + 2] = ((unsigned char *)this->OffScreenWindow)[(x+ytot)*4]; + } + } + // Create a compatible device context + MemoryHdc = (HDC)CreateCompatibleDC(this->DeviceContext); + + // Put the bitmap into the device context + SelectObject(MemoryHdc, dib); + BitBlt(this->DeviceContext, 0, 0, this->Size[0], this->Size[1], + MemoryHdc, 0, 0,SRCCOPY); + vtkDebugMacro(<< " SwapBuffers\n"); + } + else + { + glFlush(); + } +} + + +LRESULT vtkWinCEOpenGLRenderWindow::MessageProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CREATE: + { + // nothing to be done here, opengl is initilized after the call to + // create now + return 0; + } + case WM_DESTROY: + this->Clean(); + if (this->DeviceContext) + { + ReleaseDC(this->WindowId, this->DeviceContext); + this->DeviceContext = NULL; + this->WindowId = NULL; + } + return 0; + case WM_SIZE: + /* track window size changes */ + if (this->OffScreenContextId) + { + this->SetSize((int) LOWORD(lParam),(int) HIWORD(lParam)); + return 0; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + if (this->OffScreenContextId) + { + this->Render(); + } + EndPaint(hWnd, &ps); + return 0; + } + break; + case WM_ERASEBKGND: + return TRUE; + default: + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + + +void vtkWinCEOpenGLRenderWindow::InitializeApplication() +{ + // get the applicaiton instance if we don't have one already + if (!this->ApplicationInstance) + { + // if we have a parent window get the app instance from it + this->ApplicationInstance = GetModuleHandle(NULL); /*AfxGetInstanceHandle();*/ + } +} + +void vtkWinCEOpenGLRenderWindow::CreateAWindow(int x, int y, int width, + int height) +{ + static int count=1; + char *windowName; + + if (!this->WindowId) + { + WNDCLASS wndClass; + + int len = strlen( "Visualization Toolkit - WinCEOpenGL #") + + (int)ceil( (double) log10( (double)(count+1) ) ) + + 1; + windowName = new char [ len ]; + sprintf(windowName,"Visualization Toolkit - WinCEOpenGL #%i",count++); + this->SetWindowName(windowName); + delete [] windowName; + + // has the class been registered ? + if (!GetClassInfo(this->ApplicationInstance,L"vtkOpenGL",&wndClass)) + { + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = vtkWinCEOpenGLRenderWindow::WndProc; + wndClass.cbClsExtra = 0; + wndClass.hIcon = NULL; + wndClass.hInstance = this->ApplicationInstance; + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = L"vtkOpenGL"; + // vtk doesn't use the first extra 4 bytes, but app writers + // may want them, so we provide them. VTK does use the second + // four bytes of extra space. + wndClass.cbWndExtra = 8; + ATOM res = RegisterClass(&wndClass); + if (!res) + { + DWORD lerr = GetLastError(); + *(float *)(0x01) = 1.0; + } + } + + /* create window */ + if (this->ParentId) + { + this->WindowId = CreateWindow( + L"vtkOpenGL", L"WinCE", + WS_CHILD | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/, + x, y, width, height, + this->ParentId, NULL, this->ApplicationInstance, NULL); + } + else + { + DWORD style; + if (this->Borders) + { + style = WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/; + } + else + { + style = WS_POPUP | WS_CLIPCHILDREN /*| WS_CLIPSIBLINGS*/; + } + this->WindowId = CreateWindow( + L"vtkOpenGL", L"WinCE", style, + x,y, width, height, + NULL, NULL, this->ApplicationInstance, NULL); + } + if (!this->WindowId) + { + DWORD lerr = GetLastError(); + vtkErrorMacro("Could not create window, error: " << GetLastError()); + + *(float *)(0x01) = 1.0; + return; + } + // extract the create info + + /* display window */ + ShowWindow(this->WindowId, SW_SHOW); + //UpdateWindow(this->WindowId); + this->OwnWindow = 1; + SetWindowLong(this->WindowId,4,(LONG)this); + } + this->DeviceContext = GetDC(this->WindowId); + if (!this->OffScreenWindow) + { + this->OffScreenWindow = vtkOSMesaCreateWindow(width,height); + this->Size[0] = width; + this->Size[1] = height; + this->OwnWindow = 1; + } + this->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL); + + this->MakeCurrent(); + this->OpenGLInit(); + this->Mapped = 1; +} + +// Initialize the window for rendering. +void vtkWinCEOpenGLRenderWindow::WindowInitialize() +{ + int x, y, width, height; + x = ((this->Position[0] >= 0) ? this->Position[0] : 5); + y = ((this->Position[1] >= 0) ? this->Position[1] : 5); + height = ((this->Size[1] > 0) ? this->Size[1] : 300); + width = ((this->Size[0] > 0) ? this->Size[0] : 300); + + + // create our own window if not already set + this->OwnWindow = 0; + this->InitializeApplication(); + this->CreateAWindow(x,y,width,height); + + // set the DPI + this->SetDPI(GetDeviceCaps(this->DeviceContext, LOGPIXELSY)); +} + +// Initialize the rendering window. +void vtkWinCEOpenGLRenderWindow::Initialize (void) +{ + // make sure we havent already been initialized + if (this->OffScreenContextId) + { + return; + } + + // now initialize the window + this->WindowInitialize(); +} + +void vtkWinCEOpenGLRenderWindow::Finalize (void) +{ + if (this->CursorHidden) + { + this->ShowCursor(); + } + + if (this->WindowId && this->OwnWindow) + { + this->Clean(); + ReleaseDC(this->WindowId, this->DeviceContext); + // can't set WindowId=NULL, needed for DestroyWindow + this->DeviceContext = NULL; + + // clear the extra data before calling destroy + SetWindowLong(this->WindowId,4,(LONG)0); + DestroyWindow(this->WindowId); + } +} + + +// Get the current size of the window. +int *vtkWinCEOpenGLRenderWindow::GetSize(void) +{ + RECT rect; + + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Size; + } + + // Find the current window size + GetClientRect(this->WindowId, &rect); + + this->Size[0] = rect.right; + this->Size[1] = rect.bottom; + + return this->Size; +} + +// Get the current size of the window. +int *vtkWinCEOpenGLRenderWindow::GetScreenSize(void) +{ + RECT rect; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0); + + this->Size[0] = rect.right - rect.left; + this->Size[1] = rect.bottom - rect.top; + + return this->Size; +} + +// Get the position in screen coordinates of the window. +int *vtkWinCEOpenGLRenderWindow::GetPosition(void) +{ + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Position; + } + + // Find the current window position +// x,y,&this->Position[0],&this->Position[1],&child); + + return this->Position; +} + +// Change the window to fill the entire screen. +void vtkWinCEOpenGLRenderWindow::SetFullScreen(int arg) +{ + int *temp; + + if (this->FullScreen == arg) + { + return; + } + + if (!this->Mapped) + { + this->PrefFullScreen(); + return; + } + + // set the mode + this->FullScreen = arg; + if (this->FullScreen <= 0) + { + this->Position[0] = this->OldScreen[0]; + this->Position[1] = this->OldScreen[1]; + this->Size[0] = this->OldScreen[2]; + this->Size[1] = this->OldScreen[3]; + this->Borders = this->OldScreen[4]; + } + else + { + // if window already up get its values + if (this->WindowId) + { + temp = this->GetPosition(); + this->OldScreen[0] = temp[0]; + this->OldScreen[1] = temp[1]; + + this->OldScreen[4] = this->Borders; + this->PrefFullScreen(); + } + } + + // remap the window + this->WindowRemap(); + + this->Modified(); +} + +// +// Set the variable that indicates that we want a stereo capable window +// be created. This method can only be called before a window is realized. +// +void vtkWinCEOpenGLRenderWindow::SetStereoCapableWindow(int capable) +{ + if (this->WindowId == 0) + { + vtkRenderWindow::SetStereoCapableWindow(capable); + } + else + { + vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed " + << "before the window is realized, i.e. before a render."); + } +} + + +// Set the preferred window size to full screen. +void vtkWinCEOpenGLRenderWindow::PrefFullScreen() +{ + int *size; + + size = this->GetScreenSize(); + + // use full screen + this->Position[0] = 0; + this->Position[1] = 0; + this->Size[0] = size[0]; + this->Size[1] = size[1]; + // don't show borders + this->Borders = 0; +} + +// Remap the window. +void vtkWinCEOpenGLRenderWindow::WindowRemap() +{ + this->Finalize(); + + // set the default windowid + this->WindowId = this->NextWindowId; + this->NextWindowId = 0; + + // configure the window + this->Initialize(); +} + +void vtkWinCEOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Next Window Id: " << this->NextWindowId << "\n"; + os << indent << "Window Id: " << this->WindowId << "\n"; +} + +// Get the window id. +HWND vtkWinCEOpenGLRenderWindow::GetWindowId() +{ + vtkDebugMacro(<< "Returning WindowId of " << this->WindowId << "\n"); + + return this->WindowId; +} + +// Set the window id to a pre-existing window. +void vtkWinCEOpenGLRenderWindow::SetWindowId(HWND arg) +{ + vtkDebugMacro(<< "Setting WindowId to " << arg << "\n"); + + this->WindowId = arg; +} + +// Set this RenderWindow's X window id to a pre-existing window. +void vtkWinCEOpenGLRenderWindow::SetWindowInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->WindowId = (HWND)tmp; + vtkDebugMacro(<< "Setting WindowId to " << this->WindowId << "\n"); +} + +void vtkWinCEOpenGLRenderWindow::SetNextWindowInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->SetNextWindowId((HWND)tmp); +} + +// Sets the HWND id of the window that WILL BE created. +void vtkWinCEOpenGLRenderWindow::SetParentInfo(char *info) +{ + int tmp; + + sscanf(info,"%i",&tmp); + + this->ParentId = (HWND)tmp; + vtkDebugMacro(<< "Setting ParentId to " << this->ParentId << "\n"); +} + +// Set the window id to a pre-existing window. +void vtkWinCEOpenGLRenderWindow::SetParentId(HWND arg) +{ + vtkDebugMacro(<< "Setting ParentId to " << arg << "\n"); + + this->ParentId = arg; +} + +// Set the window id of the new window once a WindowRemap is done. +void vtkWinCEOpenGLRenderWindow::SetNextWindowId(HWND arg) +{ + vtkDebugMacro(<< "Setting NextWindowId to " << arg << "\n"); + + this->NextWindowId = arg; +} + +void vtkWinCEOpenGLRenderWindow::SetNextWindowId(void *arg) +{ + this->SetNextWindowId((HWND)arg); +} + + +// Begin the rendering process. +void vtkWinCEOpenGLRenderWindow::Start(void) +{ + // if the renderer has not been initialized, do so now + if (!this->OffScreenContextId) + { + this->Initialize(); + } + + // set the current window + this->MakeCurrent(); +} + + +//---------------------------------------------------------------------------- +void vtkWinCEOpenGLRenderWindow::HideCursor() +{ + if (this->CursorHidden) + { + return; + } + this->CursorHidden = 1; + + ::ShowCursor(!this->CursorHidden); +} + +//---------------------------------------------------------------------------- +void vtkWinCEOpenGLRenderWindow::ShowCursor() +{ + if (!this->CursorHidden) + { + return; + } + this->CursorHidden = 0; + + ::ShowCursor(!this->CursorHidden); +} + diff --git a/Rendering/vtkWinCEOpenGLRenderWindow.h b/Rendering/vtkWinCEOpenGLRenderWindow.h new file mode 100644 index 0000000..bdba585 --- /dev/null +++ b/Rendering/vtkWinCEOpenGLRenderWindow.h @@ -0,0 +1,206 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWinCEOpenGLRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWinCEOpenGLRenderWindow - OpenGL rendering window +// .SECTION Description +// vtkWinCEOpenGLRenderWindow is a concrete implementation of the abstract +// class vtkRenderWindow. vtkWinCEOpenGLRenderer interfaces to the standard +// OpenGL graphics library in the Windows/NT environment.. + +#ifndef __vtkWinCEOpenGLRenderWindow_h +#define __vtkWinCEOpenGLRenderWindow_h + +#include "vtkOpenGLRenderWindow.h" + +#include "GL/osmesa.h" // Needed for Mesa types + +class vtkIdList; + +class VTK_RENDERING_EXPORT vtkWinCEOpenGLRenderWindow : public vtkOpenGLRenderWindow +{ +public: + static vtkWinCEOpenGLRenderWindow *New(); + vtkTypeRevisionMacro(vtkWinCEOpenGLRenderWindow,vtkOpenGLRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Begin the rendering process. + virtual void Start(void); + + // Description: + // End the rendering process and display the image. + void Frame(void); + + // Description: + // Create the window + virtual void WindowInitialize(void); + + // Description: + // Initialize the rendering window. This will setup all system-specific + // resources. This method and Finalize() must be symmetric and it + // should be possible to call them multiple times, even changing WindowId + // in-between. This is what WindowRemap does. + virtual void Initialize(void); + + // Description: + // Finalize the rendering window. This will shutdown all system-specific + // resources. After having called this, it should be possible to destroy + // a window that was used for a SetWindowId() call without any ill effects. + virtual void Finalize(void); + + // Description: + // Change the window to fill the entire screen. + virtual void SetFullScreen(int); + + // Description: + // Remap the window. + virtual void WindowRemap(void); + + // Description: + // Set the preferred window size to full screen. + virtual void PrefFullScreen(void); + + // Description: + // Set the size of the window. + virtual void SetSize(int,int); + + // Description: + // Get the current size of the window. + virtual int *GetSize(); + + // Description: + // Set the position of the window. + virtual void SetPosition(int,int); + + // Description: + // Return the screen size. + virtual int *GetScreenSize(); + + // Description: + // Get the position in screen coordinates of the window. + virtual int *GetPosition(); + + // Description: + // Set the name of the window. This appears at the top of the window + // normally. + virtual void SetWindowName(char *); + + // Description: + // Set this RenderWindow's window id to a pre-existing window. + void SetWindowInfo(char *); + + void SetNextWindowInfo(char *); + + // Description: + // Sets the HWND id of the window that WILL BE created. + void SetParentInfo(char *); + + //BTX + virtual void *GetGenericDisplayId() {return (void *)this->OffScreenContextId;}; + virtual void *GetGenericWindowId() {return (void *)this->WindowId;}; + virtual void *GetGenericParentId() {return (void *)this->ParentId;}; + virtual void *GetGenericContext() {return (void *)this->DeviceContext;}; + virtual void SetDisplayId(void *) {}; + + // Description: + // Get the window id. + virtual HWND GetWindowId(); + void SetWindowId(void *foo) {this->SetWindowId((HWND)foo);}; + + // Description: + // Set the window id to a pre-existing window. + virtual void SetWindowId(HWND); + + // Description: + // Set the window's parent id to a pre-existing window. + virtual void SetParentId(HWND); + void SetParentId(void *foo) {this->SetParentId((HWND)foo);}; + + // Description: + // Set the window id of the new window once a WindowRemap is done. + virtual void SetNextWindowId(HWND); + + virtual void SetNextWindowId(void *); + //ETX + + // Description: + // Prescribe that the window be created in a stereo-capable mode. This + // method must be called before the window is realized. This method + // overrides the superclass method since this class can actually check + // whether the window has been realized yet. + virtual void SetStereoCapableWindow(int capable); + + // Description: + // Make this windows OpenGL context the current context. + void MakeCurrent(); + + // Description: + // If called, allow MakeCurrent() to skip cache-check when called. + // MakeCurrent() reverts to original behavior of cache-checking + // on the next render. + void SetForceMakeCurrent(); + + // Description: + // Check to see if an event is pending for this window. + // This is a useful check to abort a long render. + virtual int GetEventPending(); + + // Description: + // Clean up device contexts, rendering contexts, etc. + void Clean(); + + // Description: + // Hide or Show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + void HideCursor(); + void ShowCursor(); + +protected: + vtkWinCEOpenGLRenderWindow(); + ~vtkWinCEOpenGLRenderWindow(); + + HINSTANCE ApplicationInstance; + + OSMesaContext OffScreenContextId; + void *OffScreenWindow; + + HDC DeviceContext; + HWND WindowId; + HWND ParentId; + HWND NextWindowId; + int OwnWindow; + int ScreenSize[2]; + + //BTX + // message handler + virtual LRESULT MessageProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam); + + static LRESULT APIENTRY WndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam); + //ETX + int CursorHidden; + int ForceMakeCurrent; + + void ResizeWhileOffscreen(int xsize, int ysize); + void CreateAWindow(int x, int y, int width, int height); + void InitializeApplication(); +private: + vtkWinCEOpenGLRenderWindow(const vtkWinCEOpenGLRenderWindow&); // Not implemented. + void operator=(const vtkWinCEOpenGLRenderWindow&); // Not implemented. +}; + + +#endif + diff --git a/Rendering/vtkWindowToImageFilter.cxx b/Rendering/vtkWindowToImageFilter.cxx new file mode 100644 index 0000000..2e5ef1b --- /dev/null +++ b/Rendering/vtkWindowToImageFilter.cxx @@ -0,0 +1,417 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindowToImageFilter.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWindowToImageFilter.h" + +#include "vtkCamera.h" +#include "vtkImageData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkRendererCollection.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +vtkCxxRevisionMacro(vtkWindowToImageFilter, "$Revision: 1.39.4.1 $"); +vtkStandardNewMacro(vtkWindowToImageFilter); + +//---------------------------------------------------------------------------- +vtkWindowToImageFilter::vtkWindowToImageFilter() +{ + this->Input = NULL; + this->Magnification = 1; + this->ReadFrontBuffer = 1; + this->ShouldRerender = 1; + this->Viewport[0] = 0; + this->Viewport[1] = 0; + this->Viewport[2] = 1; + this->Viewport[3] = 1; + this->InputBufferType = VTK_RGB; + + this->SetNumberOfInputPorts(0); + this->SetNumberOfOutputPorts(1); +} + +//---------------------------------------------------------------------------- +vtkWindowToImageFilter::~vtkWindowToImageFilter() +{ + if (this->Input) + { + this->Input->UnRegister(this); + this->Input = NULL; + } +} + +//---------------------------------------------------------------------------- +vtkImageData* vtkWindowToImageFilter::GetOutput() +{ + return vtkImageData::SafeDownCast(this->GetOutputDataObject(0)); +} + +//---------------------------------------------------------------------------- +void vtkWindowToImageFilter::SetInput(vtkWindow *input) +{ + if (input != this->Input) + { + if (this->Input) {this->Input->UnRegister(this);} + this->Input = input; + if (this->Input) {this->Input->Register(this);} + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +void vtkWindowToImageFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Input ) + { + os << indent << "Input:\n"; + this->Input->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Input: (none)\n"; + } + os << indent << "ReadFrontBuffer: " << this->ReadFrontBuffer << "\n"; + os << indent << "Magnification: " << this->Magnification << "\n"; + os << indent << "ShouldRerender: " << this->ShouldRerender << "\n"; + os << indent << "Viewport: " << this->Viewport[0] << "," << this->Viewport[1] + << "," << this->Viewport[2] << "," << this->Viewport[3] << "\n"; + os << indent << "InputBufferType: " << this->InputBufferType << "\n"; +} + + +//---------------------------------------------------------------------------- +// This method returns the largest region that can be generated. +void vtkWindowToImageFilter::RequestInformation ( + vtkInformation * vtkNotUsed(request), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector *outputVector) +{ + if (this->Input == NULL ) + { + vtkErrorMacro(<<"Please specify a renderer as input!"); + return; + } + + if(this->Magnification > 1 && + (this->Viewport[0] != 0 || this->Viewport[1] != 0 || + this->Viewport[2] != 1 || this->Viewport[3] != 1)) + { + vtkWarningMacro(<<"Viewport extents are not used when Magnification > 1"); + this->Viewport[0] = 0; + this->Viewport[1] = 0; + this->Viewport[2] = 1; + this->Viewport[3] = 1; + } + + + // set the extent + int *size = this->Input->GetSize(); + int wExtent[6]; + wExtent[0]= 0; + wExtent[1] = int((this->Viewport[2] - this->Viewport[0])*size[0] + 0.5)* + this->Magnification - 1; + wExtent[2] = 0; + wExtent[3] = int((this->Viewport[3] - this->Viewport[1])*size[1] + 0.5)* + this->Magnification - 1; + wExtent[4] = 0; + wExtent[5] = 0; + + // get the info objects + vtkInformation* outInfo = outputVector->GetInformationObject(0); + outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent, 6); + + switch( this->InputBufferType ) + { + case VTK_RGB: + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 3); + break; + case VTK_RGBA: + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 4); + break; + case VTK_ZBUFFER: + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1); + break; + default: + // VTK_RGB configuration by default + vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 3); + break; + } +} + +//---------------------------------------------------------------------------- +int vtkWindowToImageFilter::ProcessRequest(vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector) +{ + // generate the data + if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + this->RequestData(request, inputVector, outputVector); + return 1; + } + + // execute information + if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION())) + { + this->RequestInformation(request, inputVector, outputVector); + return 1; + } + + return this->Superclass::ProcessRequest(request, inputVector, outputVector); +} + + +//---------------------------------------------------------------------------- +// This function reads a region from a file. The regions extent/axes +// are assumed to be the same as the file extent/order. +void vtkWindowToImageFilter::RequestData( + vtkInformation* vtkNotUsed( request ), + vtkInformationVector** vtkNotUsed( inputVector ), + vtkInformationVector* outputVector) +{ + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkImageData *out = + vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + out->SetExtent(out->GetUpdateExtent()); + out->AllocateScalars(); + + if (!this->Input) + { + return; + } + + int outIncrY; + int size[2],winsize[2]; + int idxY, rowSize; + int i; + + if (! ((out->GetScalarType() == VTK_UNSIGNED_CHAR && + (this->InputBufferType == VTK_RGB || this->InputBufferType == VTK_RGBA)) || + (out->GetScalarType() == VTK_FLOAT && this->InputBufferType == VTK_ZBUFFER))) + { + vtkErrorMacro("mismatch in scalar types!"); + return; + } + + // get the size of the render window + winsize[0] = this->Input->GetSize()[0]; + winsize[1] = this->Input->GetSize()[1]; + + size[0] = int(winsize[0]*(this->Viewport[2]-this->Viewport[0]) + 0.5); + size[1] = int(winsize[1]*(this->Viewport[3]-this->Viewport[1]) + 0.5); + + rowSize = size[0]*out->GetNumberOfScalarComponents(); + outIncrY = size[0]*this->Magnification*out->GetNumberOfScalarComponents(); + + float *viewAngles; + double *windowCenters; + vtkRenderWindow *renWin = vtkRenderWindow::SafeDownCast(this->Input); + if (!renWin) + { + vtkWarningMacro("The window passed to window to image should be a RenderWIndow or one of its subclasses"); + return; + } + + vtkRendererCollection *rc = renWin->GetRenderers(); + vtkRenderer *aren; + vtkCamera *cam; + int numRenderers = rc->GetNumberOfItems(); + + // for each renderer + vtkCamera **cams = new vtkCamera *[numRenderers]; + viewAngles = new float [numRenderers]; + windowCenters = new double [numRenderers*2]; + double *parallelScale = new double [numRenderers]; + vtkCollectionSimpleIterator rsit; + rc->InitTraversal(rsit); + for (i = 0; i < numRenderers; ++i) + { + aren = rc->GetNextRenderer(rsit); + cams[i] = aren->GetActiveCamera(); + cams[i]->Register(this); + cams[i]->GetWindowCenter(windowCenters+i*2); + viewAngles[i] = cams[i]->GetViewAngle(); + parallelScale[i] = cams[i]->GetParallelScale(); + cam = cams[i]->NewInstance(); + cam->SetPosition(cams[i]->GetPosition()); + cam->SetFocalPoint(cams[i]->GetFocalPoint()); + cam->SetViewUp(cams[i]->GetViewUp()); + cam->SetClippingRange(cams[i]->GetClippingRange()); + cam->SetParallelProjection(cams[i]->GetParallelProjection()); + cam->SetFocalDisk(cams[i]->GetFocalDisk()); + cam->SetUserTransform(cams[i]->GetUserTransform()); + cam->SetViewShear(cams[i]->GetViewShear()); + aren->SetActiveCamera(cam); + } + + // render each of the tiles required to fill this request + this->Input->SetTileScale(this->Magnification); + this->Input->GetSize(); + + int x, y; + for (y = 0; y < this->Magnification; y++) + { + for (x = 0; x < this->Magnification; x++) + { + // setup the Window ivars + this->Input->SetTileViewport((double)x/this->Magnification, + (double)y/this->Magnification, + (x+1.0)/this->Magnification, + (y+1.0)/this->Magnification); + double *tvp = this->Input->GetTileViewport(); + + // for each renderer, setup camera + rc->InitTraversal(rsit); + for (i = 0; i < numRenderers; ++i) + { + aren = rc->GetNextRenderer(rsit); + cam = aren->GetActiveCamera(); + double *vp = aren->GetViewport(); + double visVP[4]; + visVP[0] = (vp[0] < tvp[0]) ? tvp[0] : vp[0]; + visVP[0] = (visVP[0] > tvp[2]) ? tvp[2] : visVP[0]; + visVP[1] = (vp[1] < tvp[1]) ? tvp[1] : vp[1]; + visVP[1] = (visVP[1] > tvp[3]) ? tvp[3] : visVP[1]; + visVP[2] = (vp[2] > tvp[2]) ? tvp[2] : vp[2]; + visVP[2] = (visVP[2] < tvp[0]) ? tvp[0] : visVP[2]; + visVP[3] = (vp[3] > tvp[3]) ? tvp[3] : vp[3]; + visVP[3] = (visVP[3] < tvp[1]) ? tvp[1] : visVP[3]; + + // compute magnification + double mag = (visVP[3] - visVP[1])/(vp[3] - vp[1]); + // compute the delta + double deltax = (visVP[2] + visVP[0])/2.0 - (vp[2] + vp[0])/2.0; + double deltay = (visVP[3] + visVP[1])/2.0 - (vp[3] + vp[1])/2.0; + // scale by original window size + if (visVP[2] - visVP[0] > 0) + { + deltax = 2.0*deltax/(visVP[2] - visVP[0]); + } + if (visVP[3] - visVP[1] > 0) + { + deltay = 2.0*deltay/(visVP[3] - visVP[1]); + } + cam->SetWindowCenter(windowCenters[i*2]+deltax,windowCenters[i*2+1]+deltay); + cam->SetViewAngle(asin(sin(viewAngles[i]*3.1415926/360.0)*mag) + * 360.0 / 3.1415926); + cam->SetParallelScale(parallelScale[i]*mag); + } + + // now render the tile and get the data + if (this->ShouldRerender || this->Magnification > 1) + { + this->Input->Render(); + } + + int buffer = this->ReadFrontBuffer; + if(!this->Input->GetDoubleBuffer()) + { + buffer = 1; + } + if (this->InputBufferType == VTK_RGB || this->InputBufferType == VTK_RGBA) + { + unsigned char *pixels, *pixels1, *outPtr; + if (this->InputBufferType == VTK_RGB) + { + pixels = this->Input->GetPixelData(int(this->Viewport[0]* winsize[0]), + int(this->Viewport[1]* winsize[1]), + int(this->Viewport[2]* winsize[0] + 0.5) - 1, + int(this->Viewport[3]* winsize[1] + 0.5) - 1, buffer); + } + else + { + pixels = renWin->GetRGBACharPixelData(int(this->Viewport[0]* winsize[0]), + int(this->Viewport[1]* winsize[1]), + int(this->Viewport[2]* winsize[0] + 0.5) - 1, + int(this->Viewport[3]* winsize[1] + 0.5) - 1, buffer); + + } + + pixels1 = pixels; + + // now write the data to the output image + outPtr = + (unsigned char *)out->GetScalarPointer(x*size[0],y*size[1], 0); + for (idxY = 0; idxY < size[1]; idxY++) + { + memcpy(outPtr,pixels1,rowSize); + outPtr += outIncrY; + pixels1 += rowSize; + } + + // free the memory + delete [] pixels; + } + else + { // VTK_ZBUFFER + float *pixels, *pixels1, *outPtr; + pixels = renWin->GetZbufferData(int(this->Viewport[0]* winsize[0]), + int(this->Viewport[1]* winsize[1]), + int(this->Viewport[2]* winsize[0] + 0.5) - 1, + int(this->Viewport[3]* winsize[1] + 0.5) - 1); + + pixels1 = pixels; + + // now write the data to the output image + outPtr = + (float *)out->GetScalarPointer(x*size[0],y*size[1], 0); + for (idxY = 0; idxY < size[1]; idxY++) + { + memcpy(outPtr,pixels1,rowSize*sizeof(float)); + outPtr += outIncrY; + pixels1 += rowSize; + } + + // free the memory + delete [] pixels; + } + } + } + + // restore settings + // for each renderer + rc->InitTraversal(rsit); + for (i = 0; i < numRenderers; ++i) + { + aren = rc->GetNextRenderer(rsit); + // store the old view angle & set the new + cam = aren->GetActiveCamera(); + aren->SetActiveCamera(cams[i]); + cams[i]->UnRegister(this); + cam->Delete(); + } + delete [] viewAngles; + delete [] windowCenters; + delete [] parallelScale; + delete [] cams; + + // render each of the tiles required to fill this request + this->Input->SetTileScale(1); + this->Input->SetTileViewport(0.0,0.0,1.0,1.0); + this->Input->GetSize(); +} + + + +int vtkWindowToImageFilter::FillOutputPortInformation( + int vtkNotUsed(port), vtkInformation* info) +{ + // now add our info + info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData"); + return 1; +} diff --git a/Rendering/vtkWindowToImageFilter.h b/Rendering/vtkWindowToImageFilter.h new file mode 100644 index 0000000..9e89488 --- /dev/null +++ b/Rendering/vtkWindowToImageFilter.h @@ -0,0 +1,152 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWindowToImageFilter.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWindowToImageFilter - Use a vtkWindow as input to image pipeline +// .SECTION Description +// vtkWindowToImageFilter provides methods needed to read the data in +// a vtkWindow and use it as input to the imaging pipeline. This is +// useful for saving an image to a file for example. The window can +// be read as either RGB or RGBA pixels; in addition, the depth buffer +// can also be read. RGB and RGBA pixels are of type unsigned char, +// while Z-Buffer data is returned as floats. Use this filter +// to convert RenderWindows or ImageWindows to an image format. +// +// .SECTION Caveats +// A vtkWindow doesn't behave like other parts of the VTK pipeline: its +// modification time doesn't get updated when an image is rendered. As a +// result, naive use of vtkWindowToImageFilter will produce an image of +// the first image that the window rendered, but which is never updated +// on subsequent window updates. This behavior is unexpected and in +// general undesirable. +// +// To force an update of the output image, call vtkWindowToImageFilter's +// Modified method after rendering to the window. +// +// In VTK versions 4 and later, this filter is part of the canonical +// way to output an image of a window to a file (replacing the +// obsolete SaveImageAsPPM method for vtkRenderWindows that existed in +// 3.2 and earlier). Connect this filter to the output of the window, +// and filter's output to a writer such as vtkPNGWriter. +// +// Reading back alpha planes is dependent on the correct operation of +// the render window's GetRGBACharPixelData method, which in turn is +// dependent on the configuration of the window's alpha planes. As of +// VTK 4.4+, machine-independent behavior is not automatically +// assured because of these dependencies. + +// .SECTION see also +// vtkWindow + +#ifndef __vtkWindowToImageFilter_h +#define __vtkWindowToImageFilter_h + +#include "vtkAlgorithm.h" +#include "vtkImageData.h" // makes things a bit easier + +// VTK_RGB and VTK_RGBA are defined in system includes +#define VTK_ZBUFFER 5 + +class vtkWindow; + +class VTK_RENDERING_EXPORT vtkWindowToImageFilter : public vtkAlgorithm +{ +public: + static vtkWindowToImageFilter *New(); + + vtkTypeRevisionMacro(vtkWindowToImageFilter,vtkAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Indicates what renderer to get the pixel data from. + void SetInput(vtkWindow *input); + + // Description: + // Returns which renderer is being used as the source for the pixel data. + vtkGetObjectMacro(Input,vtkWindow); + + // Description: + // The magnification of the current render window + vtkSetClampMacro(Magnification,int,1,2048); + vtkGetMacro(Magnification,int); + + // Description: + // Set/Get the flag that determines which buffer to read from. + // The default is to read from the front buffer. + vtkBooleanMacro(ReadFrontBuffer, int); + vtkGetMacro(ReadFrontBuffer, int); + vtkSetMacro(ReadFrontBuffer, int); + + // Description: + // Set/get whether to re-render the input window. (This option makes no + // difference if Magnification > 1.) + vtkBooleanMacro(ShouldRerender, int); + vtkSetMacro(ShouldRerender, int); + vtkGetMacro(ShouldRerender, int); + + //Description: + //Set/get the extents to be used to generate the image. (This option + //does not work if Magnification > 1.) + vtkSetVector4Macro(Viewport,double); + vtkGetVectorMacro(Viewport,double,4); + + //Description: + //Set/get the window buffer from which data will be read. Choices + //include VTK_RGB (read the color image from the window), VTK_RGBA + //(same, but include the alpha channel), and VTK_ZBUFFER (depth + //buffer, returned as a float array). + vtkSetMacro(InputBufferType, int); + vtkGetMacro(InputBufferType, int); + void SetInputBufferTypeToRGB() {this->SetInputBufferType(VTK_RGB);}; + void SetInputBufferTypeToRGBA() {this->SetInputBufferType(VTK_RGBA);}; + void SetInputBufferTypeToZBuffer() {this->SetInputBufferType(VTK_ZBUFFER);}; + + + // Description: + // Get the output data object for a port on this algorithm. + vtkImageData* GetOutput(); + + // Description: + // see vtkAlgorithm for details + virtual int ProcessRequest(vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + +protected: + vtkWindowToImageFilter(); + ~vtkWindowToImageFilter(); + + // vtkWindow is not a vtkDataObject, so we need our own ivar. + vtkWindow *Input; + int Magnification; + int ReadFrontBuffer; + int ShouldRerender; + double Viewport[4]; + int InputBufferType; + + void RequestData(vtkInformation *, + vtkInformationVector **, vtkInformationVector *); + + virtual void RequestInformation (vtkInformation*, + vtkInformationVector**, + vtkInformationVector*); + + // see algorithm for more info + virtual int FillOutputPortInformation(int port, vtkInformation* info); + +private: + vtkWindowToImageFilter(const vtkWindowToImageFilter&); // Not implemented. + void operator=(const vtkWindowToImageFilter&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkWorldPointPicker.cxx b/Rendering/vtkWorldPointPicker.cxx new file mode 100644 index 0000000..5282c07 --- /dev/null +++ b/Rendering/vtkWorldPointPicker.cxx @@ -0,0 +1,99 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWorldPointPicker.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWorldPointPicker.h" + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" + +vtkCxxRevisionMacro(vtkWorldPointPicker, "$Revision: 1.21 $"); +vtkStandardNewMacro(vtkWorldPointPicker); + +vtkWorldPointPicker::vtkWorldPointPicker() +{ +} + +// Perform pick operation with selection point provided. The z location +// is recovered from the zBuffer. Always returns 0 since no actors are picked. +int vtkWorldPointPicker::Pick(double selectionX, double selectionY, + double selectionZ, vtkRenderer *renderer) +{ + vtkCamera *camera; + double cameraFP[4]; + double display[3], *world; + double *displayCoord; + double z; + + // Initialize the picking process + this->Initialize(); + this->Renderer = renderer; + this->SelectionPoint[0] = selectionX; + this->SelectionPoint[1] = selectionY; + this->SelectionPoint[2] = selectionZ; + + // Invoke start pick method if defined + this->InvokeEvent(vtkCommand::StartPickEvent,NULL); + + z = renderer->GetZ ((int) selectionX, (int) selectionY); + + // if z is 1.0, we assume the user has picked a point on the + // screen that has not been rendered into. Use the camera's focal + // point for the z value. The test value .999999 has to be used + // instead of 1.0 because for some reason our SGI Infinite Reality + // engine won't return a 1.0 from the zbuffer + if (z < 0.999999) + { + selectionZ = z; + vtkDebugMacro(<< " z from zBuffer: " << selectionZ); + } + else + { + // Get camera focal point and position. Convert to display (screen) + // coordinates. We need a depth value for z-buffer. + camera = renderer->GetActiveCamera(); + camera->GetFocalPoint(cameraFP); cameraFP[3] = 1.0; + + renderer->SetWorldPoint(cameraFP[0],cameraFP[1],cameraFP[2],cameraFP[3]); + renderer->WorldToDisplay(); + displayCoord = renderer->GetDisplayPoint(); + selectionZ = displayCoord[2]; + vtkDebugMacro(<< "computed z from focal point: " << selectionZ); + } + + // now convert the display point to world coordinates + display[0] = selectionX; + display[1] = selectionY; + display[2] = selectionZ; + + renderer->SetDisplayPoint (display); + renderer->DisplayToWorld (); + world = renderer->GetWorldPoint (); + + for (int i=0; i < 3; i++) + { + this->PickPosition[i] = world[i] / world[3]; + } + + // Invoke end pick method if defined + this->InvokeEvent(vtkCommand::EndPickEvent,NULL); + + return 0; +} + +void vtkWorldPointPicker::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Rendering/vtkWorldPointPicker.h b/Rendering/vtkWorldPointPicker.h new file mode 100644 index 0000000..d094705 --- /dev/null +++ b/Rendering/vtkWorldPointPicker.h @@ -0,0 +1,59 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWorldPointPicker.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkWorldPointPicker - find world x,y,z corresponding to display x,y,z +// .SECTION Description +// vtkWorldPointPicker is used to find the x,y,z world coordinate of a +// screen x,y,z. This picker cannot pick actors and/or mappers, it +// simply determines an x-y-z coordinate in world space. (It will always +// return a x-y-z, even if the selection point is not over a prop/actor.) + +// .SECTION Caveats +// The PickMethod() is not invoked, but StartPickMethod() and EndPickMethod() +// are. + +// .SECTION See Also +// vtkPropPicker vtkPicker vtkCellPicker vtkPointPicker + +#ifndef __vtkWorldPointPicker_h +#define __vtkWorldPointPicker_h + +#include "vtkAbstractPicker.h" + +class VTK_RENDERING_EXPORT vtkWorldPointPicker : public vtkAbstractPicker +{ +public: + static vtkWorldPointPicker *New(); + vtkTypeRevisionMacro(vtkWorldPointPicker,vtkAbstractPicker); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Perform the pick. (This method overload's the superclass.) + int Pick(double selectionX, double selectionY, double selectionZ, + vtkRenderer *renderer); + int Pick(double selectionPt[3], vtkRenderer *renderer) + { return this->vtkAbstractPicker::Pick( selectionPt, renderer); }; + +protected: + vtkWorldPointPicker (); + ~vtkWorldPointPicker() {}; + +private: + vtkWorldPointPicker(const vtkWorldPointPicker&); // Not implemented. + void operator=(const vtkWorldPointPicker&); // Not implemented. +}; + +#endif + + diff --git a/Rendering/vtkXMesaRenderWindow.cxx b/Rendering/vtkXMesaRenderWindow.cxx new file mode 100644 index 0000000..a64dd4a --- /dev/null +++ b/Rendering/vtkXMesaRenderWindow.cxx @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMesaRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" +#include "MangleMesaInclude/osmesa.h" +#include "vtkXMesaRenderWindow.h" +#include "vtkMesaRenderer.h" +#include "vtkMesaProperty.h" +#include "vtkMesaTexture.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkMesaActor.h" +#include "vtkMesaPolyDataMapper.h" +#include "MangleMesaInclude/glx_mangle.h" +#include "MangleMesaInclude/glx.h" +#include "MangleMesaInclude/osmesa.h" + + +#define vtkXOpenGLRenderWindow vtkXMesaRenderWindow +#define vtkOpenGLRenderWindow vtkMesaRenderWindow +#define vtkOpenGLRenderer vtkMesaRenderer +#define vtkOpenGLProperty vtkMesaProperty +#define vtkOpenGLTexture vtkMesaTexture +#define vtkOpenGLCamera vtkMesaCamera +#define vtkOpenGLLight vtkMesaLight +#define vtkOpenGLActor vtkMesaActor +#define vtkOpenGLPolyDataMapper vtkMesaPolyDataMapper +#define vtkOSMesaDestroyWindow vtkOSMangleMesaDestroyWindow +#define vtkOSMesaCreateWindow vtkOSMangleMesaCreateWindow +#define vtkXOpenGLRenderWindowPredProc vtkXMesaRenderWindowPredProc +#define vtkXOpenGLRenderWindowFoundMatch vtkXMesaRenderWindowFoundMatch +#define vtkXError vtkMesaXError +#define vtkXOpenGLRenderWindowTryForVisual vtkXMesaRenderWindowTryForVisual +#define vtkXOpenGLRenderWindowInternal vtkXMesaRenderWindowInternal +#define VTK_OPENGL_HAS_OSMESA 1 +// now include the source for vtkXOpenGLRenderWindow +#include "vtkXOpenGLRenderWindow.cxx" + +vtkCxxRevisionMacro(vtkXMesaRenderWindow, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkXMesaRenderWindow); diff --git a/Rendering/vtkXMesaRenderWindow.h b/Rendering/vtkXMesaRenderWindow.h new file mode 100644 index 0000000..a80907f --- /dev/null +++ b/Rendering/vtkXMesaRenderWindow.h @@ -0,0 +1,237 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXMesaRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXMesaRenderWindow - Mesa rendering window +// .SECTION Description +// vtkXMesaRenderWindow is a concrete implementation of the abstract class +// vtkRenderWindow. vtkOpenGLRenderer interfaces to the OpenGL graphics +// library. Application programmers should normally use vtkRenderWindow +// instead of the OpenGL specific version. + +#ifndef __vtkXMesaRenderWindow_h +#define __vtkXMesaRenderWindow_h + +#include "vtkMesaRenderWindow.h" +#include // Needed for X types used in the public interface +#include // Needed for X types used in the public interface + +class vtkIdList; +class vtkXMesaRenderWindowInternal; + +class VTK_RENDERING_EXPORT vtkXMesaRenderWindow : public vtkMesaRenderWindow +{ +public: + static vtkXMesaRenderWindow *New(); + vtkTypeRevisionMacro(vtkXMesaRenderWindow,vtkMesaRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Begin the rendering process. + virtual void Start(void); + + // Description: + // End the rendering process and display the image. + virtual void Frame(void); + + // Description: + // Initialize the window for rendering. + virtual void WindowInitialize(void); + + // Description: + // Initialize the rendering window. + virtual void Initialize(void); + + // Description: + // Shut-down all resources initialized by Initialize() + virtual void Finalize(void); + + // Description: + // Change the window to fill the entire screen. + virtual void SetFullScreen(int); + + // Description: + // Resize the window. + virtual void WindowRemap(void); + + // Description: + // Set the preferred window size to full screen. + virtual void PrefFullScreen(void); + + // Description: + // Specify the size of the rendering window. + virtual void SetSize(int,int); + virtual void SetSize(int a[2]) {this->SetSize(a[0], a[1]);}; + + // Description: + // Get the X properties of an ideal rendering window. + virtual Colormap GetDesiredColormap(); + virtual Visual *GetDesiredVisual(); + virtual XVisualInfo *GetDesiredVisualInfo(); + virtual int GetDesiredDepth(); + + // Description: + // Prescribe that the window be created in a stereo-capable mode. This + // method must be called before the window is realized. This method + // overrides the superclass method since this class can actually check + // whether the window has been realized yet. + virtual void SetStereoCapableWindow(int capable); + + // Description: + // Make this window the current OpenGL context. + void MakeCurrent(); + + // Description: + // If called, allow MakeCurrent() to skip cache-check when called. + // MakeCurrent() reverts to original behavior of cache-checking + // on the next render. + void SetForceMakeCurrent(); + + // Description: + // Get report of capabilities for the render window + const char *ReportCapabilities(); + + // Description: + // Does this render window support OpenGL? 0-false, 1-true + int SupportsOpenGL(); + + // Description: + // Is this render window using hardware acceleration? 0-false, 1-true + int IsDirect(); + + // Description: + // Xwindow get set functions + virtual void *GetGenericDisplayId() {return (void *)this->GetDisplayId();}; + virtual void *GetGenericWindowId(); + virtual void *GetGenericParentId() {return (void *)this->ParentId;}; + virtual void *GetGenericContext(); + virtual void *GetGenericDrawable() {return (void *)this->WindowId;}; + + // Description: + // Get the size of the screen in pixels + virtual int *GetScreenSize(); + + // Description: + // Get the position in screen coordinates (pixels) of the window. + virtual int *GetPosition(); + + // Description: + // Get this RenderWindow's X display id. + Display *GetDisplayId(); + + // Description: + // Set the X display id for this RenderWindow to use to a pre-existing + // X display id. + void SetDisplayId(Display *); + void SetDisplayId(void *); + + // Description: + // Get this RenderWindow's parent X window id. + Window GetParentId(); + + // Description: + // Sets the parent of the window that WILL BE created. + void SetParentId(Window); + void SetParentId(void *); + + // Description: + // Get this RenderWindow's X window id. + Window GetWindowId(); + + // Description: + // Set this RenderWindow's X window id to a pre-existing window. + void SetWindowId(Window); + void SetWindowId(void *); + + // Description: + // Specify the X window id to use if a WindowRemap is done. + void SetNextWindowId(Window); + void SetNextWindowId(void *); + void SetWindowName(const char *); + + // Description: + // Move the window to a new position on the display. + void SetPosition(int,int); + void SetPosition(int a[2]) {this->SetPosition(a[0], a[1]);}; + + // Description: + // Hide or Show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + void HideCursor(); + void ShowCursor(); + + // Description: + // Change the shape of the cursor + virtual void SetCurrentCursor(int); + + // Description: + // Get the properties available at runtime that would result in + // the best Xwindow for 3D rendering. + virtual int GetEventPending(); + + // Description: + // Set this RenderWindow's X window id to a pre-existing window. + void SetWindowInfo(char *info); + + void SetNextWindowInfo(char *); + + // Description: + // Sets the X window id of the window that WILL BE created. + void SetParentInfo(char *info); + + // Description: + // This computes the size of the render window + // before calling the supper classes render + void Render(); + + // Description: + // Render without displaying the window. + void SetOffScreenRendering(int i); + +protected: + vtkXMesaRenderWindow(); + ~vtkXMesaRenderWindow(); + + vtkXMesaRenderWindowInternal *Internal; + + Window ParentId; + Window WindowId; + Window NextWindowId; + Display *DisplayId; + Colormap ColorMap; + int OwnWindow; + int OwnDisplay; + int ScreenSize[2]; + int CursorHidden; + int ForceMakeCurrent; + int UsingHardware; + char *Capabilities; + + // we must keep track of the cursors we are using + Cursor XCArrow; + Cursor XCSizeAll; + Cursor XCSizeNS; + Cursor XCSizeWE; + Cursor XCSizeNE; + Cursor XCSizeNW; + Cursor XCSizeSE; + Cursor XCSizeSW; + +private: + vtkXMesaRenderWindow(const vtkXMesaRenderWindow&); // Not implemented. + void operator=(const vtkXMesaRenderWindow&); // Not implemented. +}; + + + +#endif diff --git a/Rendering/vtkXOpenGLRenderWindow.cxx b/Rendering/vtkXOpenGLRenderWindow.cxx new file mode 100644 index 0000000..a0078a6 --- /dev/null +++ b/Rendering/vtkXOpenGLRenderWindow.cxx @@ -0,0 +1,1536 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXOpenGLRenderWindow.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef VTK_IMPLEMENT_MESA_CXX +#include "vtkXOpenGLRenderWindow.h" +#include "vtkOpenGLRenderer.h" +#include "vtkOpenGLProperty.h" +#include "vtkOpenGLTexture.h" +#include "vtkOpenGLCamera.h" +#include "vtkOpenGLLight.h" +#include "vtkOpenGLActor.h" +#include "vtkOpenGLPolyDataMapper.h" +#include +#include "GL/glx.h" +#else +#include "MangleMesaInclude/osmesa.h" +#endif + +#include "vtkToolkits.h" +#ifndef VTK_IMPLEMENT_MESA_CXX + #ifdef VTK_OPENGL_HAS_OSMESA + #include + #endif +#endif + +#include "vtkCommand.h" +#include "vtkIdList.h" +#include "vtkObjectFactory.h" +#include "vtkRendererCollection.h" + +#include +#include +#include + +class vtkXOpenGLRenderWindow; +class vtkRenderWindow; +class vtkXOpenGLRenderWindowInternal +{ + friend class vtkXOpenGLRenderWindow; +private: + vtkXOpenGLRenderWindowInternal(vtkRenderWindow*); + + GLXContext ContextId; + +#if defined( VTK_OPENGL_HAS_OSMESA ) + // OffScreen stuff + OSMesaContext OffScreenContextId; + void *OffScreenWindow; + int ScreenMapped; + // Looks like this just stores DoubleBuffer. + int ScreenDoubleBuffer; +#endif +}; + +#ifdef VTK_OPENGL_HAS_OSMESA +vtkXOpenGLRenderWindowInternal::vtkXOpenGLRenderWindowInternal( + vtkRenderWindow *rw) +#else +vtkXOpenGLRenderWindowInternal::vtkXOpenGLRenderWindowInternal( + vtkRenderWindow * vtkNotUsed(rw)) +#endif +{ + this->ContextId = NULL; + + // OpenGL specific +#ifdef VTK_OPENGL_HAS_OSMESA + this->OffScreenContextId = NULL; + this->OffScreenWindow = NULL; + this->ScreenMapped = rw->GetMapped(); + this->ScreenDoubleBuffer = rw->GetDoubleBuffer(); +#endif +} + + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkXOpenGLRenderWindow, "$Revision: 1.54 $"); +vtkStandardNewMacro(vtkXOpenGLRenderWindow); +#endif + + + +#define MAX_LIGHTS 8 + +#ifdef VTK_OPENGL_HAS_OSMESA +// a couple of routines for offscreen rendering +void vtkOSMesaDestroyWindow(void *Window) +{ + free(Window); +} + +void *vtkOSMesaCreateWindow(int width, int height) +{ + return malloc(width*height*4); +} +#endif + + +XVisualInfo *vtkXOpenGLRenderWindowTryForVisual(Display *DisplayId, + int doublebuff, int stereo, + int multisamples, + int alphaBitPlanes) +{ + int index; + static int attributes[50]; + + // setup the default stuff we ask for + index = 0; + attributes[index++] = GLX_RGBA; + attributes[index++] = GLX_RED_SIZE; + attributes[index++] = 1; + attributes[index++] = GLX_GREEN_SIZE; + attributes[index++] = 1; + attributes[index++] = GLX_BLUE_SIZE; + attributes[index++] = 1; + attributes[index++] = GLX_DEPTH_SIZE; + attributes[index++] = 1; + if (alphaBitPlanes) + { + attributes[index++] = GLX_ALPHA_SIZE; + attributes[index++] = 1; + } + if (doublebuff) + { + attributes[index++] = GLX_DOUBLEBUFFER; + } + if (stereo) + { + // also try for STEREO + attributes[index++] = GLX_STEREO; + } + if (multisamples) + { +#ifdef GLX_SAMPLE_BUFFERS_SGIS + attributes[index++] = GLX_SAMPLE_BUFFERS_SGIS; + attributes[index++] = 1; + attributes[index++] = GLX_SAMPLES_SGIS; + attributes[index++] = multisamples; +#endif + } + + attributes[index++] = None; + + return glXChooseVisual(DisplayId, DefaultScreen(DisplayId), attributes ); +} + +XVisualInfo *vtkXOpenGLRenderWindow::GetDesiredVisualInfo() +{ + XVisualInfo *v = NULL; + int multi; + int stereo = 0; + + // get the default display connection + if (!this->DisplayId) + { + this->DisplayId = XOpenDisplay((char *)NULL); + if (this->DisplayId == NULL) + { + vtkErrorMacro(<< "bad X server connection.\n"); + } + this->OwnDisplay = 1; + } + + // try every possibility stoping when we find one that works + for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--) + { + for (multi = this->MultiSamples; !v && multi >= 0; multi--) + { + if (v) + { + XFree(v); + } + v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId, + this->DoubleBuffer, + stereo, multi, + this->AlphaBitPlanes); + if (v && this->StereoCapableWindow && !stereo) + { + // requested a stereo capable window but we could not get one + this->StereoCapableWindow = 0; + } + } + } + for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--) + { + for (multi = this->MultiSamples; !v && multi >= 0; multi--) + { + if (v) + { + XFree(v); + } + v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId, + !this->DoubleBuffer, + stereo, multi, + this->AlphaBitPlanes); + if (v) + { + this->DoubleBuffer = !this->DoubleBuffer; + } + if (v && this->StereoCapableWindow && !stereo) + { + // requested a stereo capable window but we could not get one + this->StereoCapableWindow = 0; + } + } + } + if (!v) + { + vtkErrorMacro(<< "Could not find a decent visual\n"); + } + return ( v ); +} + +vtkXOpenGLRenderWindow::vtkXOpenGLRenderWindow() +{ + this->ParentId = (Window)NULL; + this->ScreenSize[0] = 0; + this->ScreenSize[1] = 0; + this->OwnDisplay = 0; + this->CursorHidden = 0; + this->ForceMakeCurrent = 0; + this->UsingHardware = 0; + this->DisplayId = (Display *)NULL; + this->WindowId = (Window)NULL; + this->NextWindowId = (Window)NULL; + this->ColorMap = (Colormap)0; + this->OwnWindow = 0; + + this->Internal = new vtkXOpenGLRenderWindowInternal(this); + + this->XCArrow = 0; + this->XCSizeAll = 0; + this->XCSizeNS = 0; + this->XCSizeWE = 0; + this->XCSizeNE = 0; + this->XCSizeNW = 0; + this->XCSizeSE = 0; + this->XCSizeSW = 0; + + this->Capabilities = 0; + +} + +// free up memory & close the window +vtkXOpenGLRenderWindow::~vtkXOpenGLRenderWindow() +{ + // close-down all system-specific drawing resources + this->Finalize(); + + delete this->Internal; + +} + +// End the rendering process and display the image. +void vtkXOpenGLRenderWindow::Frame(void) +{ + this->MakeCurrent(); + glFlush(); + if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers) + { + glXSwapBuffers(this->DisplayId, this->WindowId); + vtkDebugMacro(<< " glXSwapBuffers\n"); + } +} + +// +// Set the variable that indicates that we want a stereo capable window +// be created. This method can only be called before a window is realized. +// +void vtkXOpenGLRenderWindow::SetStereoCapableWindow(int capable) +{ + if (!this->WindowId) + { + vtkOpenGLRenderWindow::SetStereoCapableWindow(capable); + } + else + { + vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed " + << "before the window is realized, i.e. before a render."); + } +} + +// Initialize the window for rendering. +void vtkXOpenGLRenderWindow::WindowInitialize (void) +{ + XVisualInfo *v, matcher; + XSetWindowAttributes attr; + int x, y, width, height, nItems; + XWindowAttributes winattr; + XSizeHints xsh; + + xsh.flags = USSize; + if ((this->Position[0] >= 0)&&(this->Position[1] >= 0)) + { + xsh.flags |= USPosition; + xsh.x = (int)(this->Position[0]); + xsh.y = (int)(this->Position[1]); + } + + x = ((this->Position[0] >= 0) ? this->Position[0] : 5); + y = ((this->Position[1] >= 0) ? this->Position[1] : 5); + width = ((this->Size[0] > 0) ? this->Size[0] : 300); + height = ((this->Size[1] > 0) ? this->Size[1] : 300); + + xsh.width = width; + xsh.height = height; + + if ( ! this->OffScreenRendering) + { + // get the default display connection + if (!this->DisplayId) + { + this->DisplayId = XOpenDisplay((char *)NULL); + if (this->DisplayId == NULL) + { + vtkErrorMacro(<< "bad X server connection.\n"); + } + this->OwnDisplay = 1; + } + + attr.override_redirect = False; + if (this->Borders == 0.0) + { + attr.override_redirect = True; + } + + // create our own window ? + this->OwnWindow = 0; + if (!this->WindowId) + { + v = this->GetDesiredVisualInfo(); + this->ColorMap = XCreateColormap(this->DisplayId, + RootWindow( this->DisplayId, v->screen), + v->visual, AllocNone ); + + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = this->ColorMap; + attr.event_mask = StructureNotifyMask | ExposureMask; + + // get a default parent if one has not been set. + if (! this->ParentId) + { + this->ParentId = RootWindow(this->DisplayId, v->screen); + } + this->WindowId = + XCreateWindow(this->DisplayId, + this->ParentId, + x, y, width, height, 0, v->depth, InputOutput, v->visual, + CWBackPixel | CWBorderPixel | CWColormap | + CWOverrideRedirect | CWEventMask, + &attr); + XStoreName(this->DisplayId, this->WindowId, this->WindowName); + XSetNormalHints(this->DisplayId,this->WindowId,&xsh); + this->OwnWindow = 1; + } + else + { + XChangeWindowAttributes(this->DisplayId,this->WindowId, + CWOverrideRedirect, &attr); + XGetWindowAttributes(this->DisplayId, + this->WindowId,&winattr); + matcher.visualid = XVisualIDFromVisual(winattr.visual); + matcher.screen = DefaultScreen(DisplayId); + v = XGetVisualInfo(this->DisplayId, VisualIDMask | VisualScreenMask, + &matcher, &nItems); + } + + // RESIZE THE WINDOW TO THE DESIRED SIZE + vtkDebugMacro(<< "Resizing the xwindow\n"); + XResizeWindow(this->DisplayId,this->WindowId, + ((this->Size[0] > 0) ? + (int)(this->Size[0]) : 300), + ((this->Size[1] > 0) ? + (int)(this->Size[1]) : 300)); + XSync(this->DisplayId,False); + + // is GLX extension is supported? + if(!glXQueryExtension(this->DisplayId, NULL, NULL)) + { + vtkErrorMacro("GLX not found. Aborting."); + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + abort(); + } + } + + this->Internal->ContextId = glXCreateContext(this->DisplayId, v, 0, GL_TRUE); + + if(!this->Internal->ContextId) + { + vtkErrorMacro("Cannot create GLX context. Aborting."); + if (this->HasObserver(vtkCommand::ExitEvent)) + { + this->InvokeEvent(vtkCommand::ExitEvent, NULL); + return; + } + else + { + abort(); + } + } + this->MakeCurrent(); + + if(this->OwnWindow) + { + vtkDebugMacro(" Mapping the xwindow\n"); + XMapWindow(this->DisplayId, this->WindowId); + XSync(this->DisplayId,False); + XGetWindowAttributes(this->DisplayId, + this->WindowId,&winattr); + while (winattr.map_state == IsUnmapped) + { + XGetWindowAttributes(this->DisplayId, + this->WindowId,&winattr); + }; + } + // free the visual info + if (v) + { + XFree(v); + } + this->Mapped = 1; + this->Size[0] = width; + this->Size[1] = height; + } + else + { + this->DoubleBuffer = 0; +#ifdef VTK_OPENGL_HAS_OSMESA + if (!this->Internal->OffScreenWindow) + { + this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height); + this->Size[0] = width; + this->Size[1] = height; + this->OwnWindow = 1; + } + this->Internal->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL); +#endif + this->MakeCurrent(); + this->Mapped = 0; + } + + // tell our renderers about us + vtkRenderer* ren; + for (this->Renderers->InitTraversal(); + (ren = this->Renderers->GetNextItem());) + { + ren->SetRenderWindow(0); + ren->SetRenderWindow(this); + } + + this->OpenGLInit(); + glAlphaFunc(GL_GREATER,0); +} + +// Initialize the rendering window. +void vtkXOpenGLRenderWindow::Initialize (void) +{ + // make sure we havent already been initialized + if (this->Internal->ContextId +#ifdef VTK_OPENGL_HAS_OSMESA + || this->Internal->OffScreenContextId +#endif + ) + { + return; + } + + // now initialize the window + this->WindowInitialize(); +} + +void vtkXOpenGLRenderWindow::Finalize (void) +{ + vtkRenderer *ren; + GLuint txId; + short cur_light; + + // free the cursors + if (this->DisplayId) + { + if (this->WindowId) + { + // we will only have a cursor defined if a CurrentCursor has been + // set > 0 or if the cursor has been hidden... if we undefine without + // checking, bad things can happen (BadWindow) + if (this->GetCurrentCursor() || this->CursorHidden) + { + XUndefineCursor(this->DisplayId,this->WindowId); + } + } + if (this->XCArrow) + { + XFreeCursor(this->DisplayId,this->XCArrow); + } + if (this->XCSizeAll) + { + XFreeCursor(this->DisplayId,this->XCSizeAll); + } + if (this->XCSizeNS) + { + XFreeCursor(this->DisplayId,this->XCSizeNS); + } + if (this->XCSizeWE) + { + XFreeCursor(this->DisplayId,this->XCSizeWE); + } + if (this->XCSizeNE) + { + XFreeCursor(this->DisplayId,this->XCSizeNE); + } + if (this->XCSizeNW) + { + XFreeCursor(this->DisplayId,this->XCSizeNW); + } + if (this->XCSizeSE) + { + XFreeCursor(this->DisplayId,this->XCSizeSE); + } + if (this->XCSizeSW) + { + XFreeCursor(this->DisplayId,this->XCSizeSW); + } + } + + this->XCArrow = 0; + this->XCSizeAll = 0; + this->XCSizeNS = 0; + this->XCSizeWE = 0; + this->XCSizeNE = 0; + this->XCSizeNW = 0; + this->XCSizeSE = 0; + this->XCSizeSW = 0; + + // make sure we have been initialized + if (this->Internal->ContextId +#ifdef VTK_OPENGL_HAS_OSMESA + || this->Internal->OffScreenContextId +#endif + ) + { + this->MakeCurrent(); + + // tell each of the renderers that this render window/graphics context + // is being removed (the RendererCollection is removed by vtkRenderWindow's + // destructor) + this->Renderers->InitTraversal(); + for ( ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject()); + ren != NULL; + ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject()) ) + { + ren->SetRenderWindow(NULL); + } + + /* first delete all the old lights */ + for (cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+MAX_LIGHTS; cur_light++) + { + glDisable((GLenum)cur_light); + } + + /* now delete all textures */ + glDisable(GL_TEXTURE_2D); + for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++) + { + txId = (GLuint) this->TextureResourceIds->GetId(i); +#ifdef GL_VERSION_1_1 + if (glIsTexture(txId)) + { + glDeleteTextures(1, &txId); + } +#else + if (glIsList(txId)) + { + glDeleteLists(txId,1); + } +#endif + } + + glFinish(); +#ifdef VTK_OPENGL_HAS_OSMESA + if (this->OffScreenRendering && this->Internal->OffScreenContextId) + { + OSMesaDestroyContext(this->Internal->OffScreenContextId); + this->Internal->OffScreenContextId = NULL; + vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow); + this->Internal->OffScreenWindow = NULL; + } + else +#endif + { + glXDestroyContext( this->DisplayId, this->Internal->ContextId); + this->Internal->ContextId = NULL; + + // then close the old window + if (this->OwnWindow && this->DisplayId && this->WindowId) + { + XDestroyWindow(this->DisplayId,this->WindowId); + this->WindowId = (Window)NULL; + } + } + } + + if (this->DisplayId) + { + XSync(this->DisplayId,0); + } + // if we create the display, we'll delete it + if (this->OwnDisplay && this->DisplayId) + { + XCloseDisplay(this->DisplayId); + this->DisplayId = NULL; + } + + if (this->Capabilities) + { + delete[] this->Capabilities; + this->Capabilities = 0; + } + + // make sure all other code knows we're not mapped anymore + this->Mapped = 0; + +} + +// Change the window to fill the entire screen. +void vtkXOpenGLRenderWindow::SetFullScreen(int arg) +{ + int *temp; + + if (this->OffScreenRendering) + { + return; + } + + if (this->FullScreen == arg) return; + + if (!this->Mapped) + { + this->PrefFullScreen(); + return; + } + + // set the mode + this->FullScreen = arg; + if (this->FullScreen <= 0) + { + this->Position[0] = this->OldScreen[0]; + this->Position[1] = this->OldScreen[1]; + this->Size[0] = this->OldScreen[2]; + this->Size[1] = this->OldScreen[3]; + this->Borders = this->OldScreen[4]; + } + else + { + // if window already up get its values + if (this->WindowId) + { + XWindowAttributes attribs; + + // Find the current window size + XGetWindowAttributes(this->DisplayId, + this->WindowId, &attribs); + + this->OldScreen[2] = attribs.width; + this->OldScreen[3] = attribs.height;; + + temp = this->GetPosition(); + this->OldScreen[0] = temp[0]; + this->OldScreen[1] = temp[1]; + + this->OldScreen[4] = this->Borders; + this->PrefFullScreen(); + } + } + + // remap the window + this->WindowRemap(); + + // if full screen then grab the keyboard + if (this->FullScreen) + { + XGrabKeyboard(this->DisplayId,this->WindowId, + False,GrabModeAsync,GrabModeAsync,CurrentTime); + } + this->Modified(); +} + +// Set the preferred window size to full screen. +void vtkXOpenGLRenderWindow::PrefFullScreen() +{ + // use full screen + this->Position[0] = 0; + this->Position[1] = 0; + + if (this->OffScreenRendering) + { + this->Size[0] = 1280; + this->Size[1] = 1024; + } + else + { + int *size; + size = this->GetScreenSize(); + this->Size[0] = size[0]; + this->Size[1] = size[1]; + } + + // don't show borders + this->Borders = 0; +} + +// Resize the window. +void vtkXOpenGLRenderWindow::WindowRemap() +{ + // shut everything down + this->Finalize(); + + // set the default windowid + this->WindowId = this->NextWindowId; + this->NextWindowId = (Window)NULL; + + // set everything up again + this->Initialize(); +} + +// Begin the rendering process. +void vtkXOpenGLRenderWindow::Start(void) +{ + // if the renderer has not been initialized, do so now + if (!this->Internal->ContextId +#ifdef VTK_OPENGL_HAS_OSMESA + && !this->Internal->OffScreenContextId +#endif + ) + { + this->Initialize(); + } + + // set the current window + this->MakeCurrent(); +} + + +// Specify the size of the rendering window. +void vtkXOpenGLRenderWindow::SetSize(int x,int y) +{ + if ((this->Size[0] != x)||(this->Size[1] != y)) + { + this->Modified(); + this->Size[0] = x; + this->Size[1] = y; + } + + if (this->OffScreenRendering +#ifdef VTK_OPENGL_HAS_OSMESA + && this->Internal->OffScreenWindow +#endif + ) + { + vtkRenderer *ren; + // Disconnect renderers from this render window. + // Done to release graphic resources. + vtkCollectionSimpleIterator rit; + this->Renderers->InitTraversal(rit); + while ( (ren = this->Renderers->GetNextRenderer(rit)) ) + { + ren->SetRenderWindow(NULL); + } + +#ifdef VTK_OPENGL_HAS_OSMESA + OSMesaDestroyContext(this->Internal->OffScreenContextId); + this->Internal->OffScreenContextId = NULL; + vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow); + this->Internal->OffScreenWindow = NULL; +#endif + this->WindowInitialize(); + this->Renderers->InitTraversal(rit); + while ( (ren = this->Renderers->GetNextRenderer(rit)) ) + { + ren->SetRenderWindow(this); + } + } + else + { + // if we arent mappen then just set the ivars + if (!this->Mapped) + { + return; + } + + XResizeWindow(this->DisplayId,this->WindowId,x,y); + XSync(this->DisplayId,False); + } +} + + + +int vtkXOpenGLRenderWindow::GetDesiredDepth() +{ + XVisualInfo *v; + int depth = 0; + + // get the default visual to use + v = this->GetDesiredVisualInfo(); + + if (v) + { + depth = v->depth; + XFree(v); + } + + return depth; +} + +// Get a visual from the windowing system. +Visual *vtkXOpenGLRenderWindow::GetDesiredVisual () +{ + XVisualInfo *v; + Visual *vis=0; + + // get the default visual to use + v = this->GetDesiredVisualInfo(); + + if (v) + { + vis = v->visual; + XFree(v); + } + + return vis; +} + + +// Get a colormap from the windowing system. +Colormap vtkXOpenGLRenderWindow::GetDesiredColormap () +{ + XVisualInfo *v; + + if (this->ColorMap) return this->ColorMap; + + // get the default visual to use + v = this->GetDesiredVisualInfo(); + + if (v) + { + this->ColorMap = XCreateColormap(this->DisplayId, + RootWindow( this->DisplayId, v->screen), + v->visual, AllocNone ); + XFree(v); + } + + return this->ColorMap; +} + +void vtkXOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ContextId: " << this->Internal->ContextId << "\n"; +#ifdef VTK_OPENGL_HAS_OSMESA + os << indent << "OffScreenContextId: " << this->Internal->OffScreenContextId << "\n"; +#endif + os << indent << "Color Map: " << this->ColorMap << "\n"; + os << indent << "Display Id: " << this->GetDisplayId() << "\n"; + os << indent << "Next Window Id: " << this->NextWindowId << "\n"; + os << indent << "Window Id: " << this->GetWindowId() << "\n"; +} + +// the following can be useful for debugging XErrors +// When uncommented (along with the lines in MakeCurrent) +// it will cause a segfault upon an XError instead of +// the normal XError handler +// extern "C" {int vtkXError(Display *display, XErrorEvent *err) +// { +// // cause a segfault +// *(float *)(0x01) = 1.0; +// return 1; +// }} + +void vtkXOpenGLRenderWindow::MakeCurrent() +{ + // when debugging XErrors uncomment the following lines +// if (this->DisplayId) +// { +// XSynchronize(this->DisplayId,1); +// } +// XSetErrorHandler(vtkXError); +#ifdef VTK_OPENGL_HAS_OSMESA + // set the current window + if (this->OffScreenRendering) + { + if (this->Internal->OffScreenContextId) + { + if (OSMesaMakeCurrent(this->Internal->OffScreenContextId, + this->Internal->OffScreenWindow, GL_UNSIGNED_BYTE, + this->Size[0], this->Size[1]) != GL_TRUE) + { + vtkWarningMacro("failed call to OSMesaMakeCurrent"); + } + } + } + else +#endif + { + if (this->Internal->ContextId && ((this->Internal->ContextId != glXGetCurrentContext()) || this->ForceMakeCurrent)) + { + glXMakeCurrent(this->DisplayId,this->WindowId,this->Internal->ContextId); + this->ForceMakeCurrent = 0; + } + } +} + +void vtkXOpenGLRenderWindow::SetForceMakeCurrent() +{ + this->ForceMakeCurrent = 1; +} + +int vtkXOpenGLRenderWindowFoundMatch; + +extern "C" +{ + Bool vtkXOpenGLRenderWindowPredProc(Display *vtkNotUsed(disp), + XEvent *event, + char *arg) + { + Window win = (Window)arg; + + if (((reinterpret_cast(event))->window == win) && + ((event->type == ButtonPress))) + { + vtkXOpenGLRenderWindowFoundMatch = 1; + } + + return 0; + } +} + +void *vtkXOpenGLRenderWindow::GetGenericContext() +{ +#if defined(MESA) && defined(VTK_OPENGL_HAS_OSMESA) + if (this->OffScreenRendering) + { + return (void *)this->Internal->OffScreenContextId; + } + else +#endif + { + static GC gc = (GC) NULL; + if (!gc) gc = XCreateGC(this->DisplayId, this->WindowId, 0, 0); + return (void *) gc; + } + +} + +int vtkXOpenGLRenderWindow::GetEventPending() +{ + XEvent report; + + vtkXOpenGLRenderWindowFoundMatch = 0; +#if defined(VTK_OPENGL_HAS_OSMESA) + if (this->OffScreenRendering) + { + return vtkXOpenGLRenderWindowFoundMatch; + } +#endif + XCheckIfEvent(this->DisplayId, &report, vtkXOpenGLRenderWindowPredProc, + (char *)this->WindowId); + return vtkXOpenGLRenderWindowFoundMatch; +} + +// Get the size of the screen in pixels +int *vtkXOpenGLRenderWindow::GetScreenSize() +{ + // get the default display connection + if (!this->DisplayId) + { + this->DisplayId = XOpenDisplay((char *)NULL); + if (this->DisplayId == NULL) + { + vtkErrorMacro(<< "bad X server connection.\n"); + } + else + { + this->OwnDisplay = 1; + } + } + + this->ScreenSize[0] = + DisplayWidth(this->DisplayId, DefaultScreen(this->DisplayId)); + this->ScreenSize[1] = + DisplayHeight(this->DisplayId, DefaultScreen(this->DisplayId)); + + return this->ScreenSize; +} + +// Get the position in screen coordinates (pixels) of the window. +int *vtkXOpenGLRenderWindow::GetPosition(void) +{ + XWindowAttributes attribs; + int x,y; + Window child; + + // if we aren't mapped then just return the ivar + if (!this->Mapped) + { + return this->Position; + } + + // Find the current window size + XGetWindowAttributes(this->DisplayId, this->WindowId, &attribs); + x = attribs.x; + y = attribs.y; + + XTranslateCoordinates(this->DisplayId,this->WindowId, + RootWindowOfScreen(ScreenOfDisplay(this->DisplayId,0)), + x,y,&this->Position[0],&this->Position[1],&child); + + return this->Position; +} + +// Get this RenderWindow's X display id. +Display *vtkXOpenGLRenderWindow::GetDisplayId() +{ + // get the default display connection + if (!this->DisplayId) + { + this->DisplayId = XOpenDisplay((char *)NULL); + if (this->DisplayId == NULL) + { + vtkErrorMacro(<< "bad X server connection.\n"); + } + this->OwnDisplay = 1; + } + vtkDebugMacro(<< "Returning DisplayId of " << (void *)this->DisplayId << "\n"); + + return this->DisplayId; +} + +// Get this RenderWindow's parent X window id. +Window vtkXOpenGLRenderWindow::GetParentId() +{ + vtkDebugMacro(<< "Returning ParentId of " << (void *)this->ParentId << "\n"); + return this->ParentId; +} + +// Get this RenderWindow's X window id. +Window vtkXOpenGLRenderWindow::GetWindowId() +{ + vtkDebugMacro(<< "Returning WindowId of " << (void *)this->WindowId << "\n"); + return this->WindowId; +} + +// Move the window to a new position on the display. +void vtkXOpenGLRenderWindow::SetPosition(int x, int y) +{ + // if we aren't mapped then just set the ivars + if (!this->Mapped) + { + if ((this->Position[0] != x)||(this->Position[1] != y)) + { + this->Modified(); + } + this->Position[0] = x; + this->Position[1] = y; + return; + } + + XMoveWindow(this->DisplayId,this->WindowId,x,y); + XSync(this->DisplayId,False); +} + +// Sets the parent of the window that WILL BE created. +void vtkXOpenGLRenderWindow::SetParentId(Window arg) +{ +// if (this->ParentId) +// { +// vtkErrorMacro("ParentId is already set."); +// return; +// } + + vtkDebugMacro(<< "Setting ParentId to " << (void *)arg << "\n"); + + this->ParentId = arg; +} + +// Set this RenderWindow's X window id to a pre-existing window. +void vtkXOpenGLRenderWindow::SetWindowId(Window arg) +{ + vtkDebugMacro(<< "Setting WindowId to " << (void *)arg << "\n"); + + this->WindowId = arg; + + if (this->CursorHidden) + { + this->CursorHidden = 0; + this->HideCursor(); + } +} + +// Set this RenderWindow's X window id to a pre-existing window. +void vtkXOpenGLRenderWindow::SetWindowInfo(char *info) +{ + int tmp; + + // get the default display connection + if (!this->DisplayId) + { + this->DisplayId = XOpenDisplay((char *)NULL); + if (this->DisplayId == NULL) + { + vtkErrorMacro(<< "bad X server connection.\n"); + } + else + { + this->OwnDisplay = 1; + } + } + + sscanf(info,"%i",&tmp); + + this->SetWindowId(tmp); +} + +// Set this RenderWindow's X window id to a pre-existing window. +void vtkXOpenGLRenderWindow::SetNextWindowInfo(char *info) +{ + int tmp; + sscanf(info,"%i",&tmp); + + this->SetNextWindowId((Window)tmp); +} + +// Sets the X window id of the window that WILL BE created. +void vtkXOpenGLRenderWindow::SetParentInfo(char *info) +{ + int tmp; + + // get the default display connection + if (!this->DisplayId) + { + this->DisplayId = XOpenDisplay((char *)NULL); + if (this->DisplayId == NULL) + { + vtkErrorMacro(<< "bad X server connection.\n"); + } + else + { + this->OwnDisplay = 1; + } + } + + sscanf(info,"%i",&tmp); + + this->SetParentId(tmp); +} + +void vtkXOpenGLRenderWindow::SetWindowId(void *arg) +{ + this->SetWindowId((Window)arg); +} +void vtkXOpenGLRenderWindow::SetParentId(void *arg) +{ + this->SetParentId((Window)arg); +} + +const char* vtkXOpenGLRenderWindow::ReportCapabilities() +{ + MakeCurrent(); + + if (!this->DisplayId) + { + return "display id not set"; + } + + int scrnum = DefaultScreen(this->DisplayId); + const char *serverVendor = glXQueryServerString(this->DisplayId, scrnum, GLX_VENDOR); + const char *serverVersion = glXQueryServerString(this->DisplayId, scrnum, GLX_VERSION); + const char *serverExtensions = glXQueryServerString(this->DisplayId, scrnum, GLX_EXTENSIONS); + const char *clientVendor = glXGetClientString(this->DisplayId, GLX_VENDOR); + const char *clientVersion = glXGetClientString(this->DisplayId, GLX_VERSION); + const char *clientExtensions = glXGetClientString(this->DisplayId, GLX_EXTENSIONS); + const char *glxExtensions = glXQueryExtensionsString(this->DisplayId, scrnum); + const char *glVendor = (const char *) glGetString(GL_VENDOR); + const char *glRenderer = (const char *) glGetString(GL_RENDERER); + const char *glVersion = (const char *) glGetString(GL_VERSION); + const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS); + + ostrstream strm; + strm << "server glx vendor string: " << serverVendor << endl; + strm << "server glx version string: " << serverVersion << endl; + strm << "server glx extensions: " << serverExtensions << endl; + strm << "client glx vendor string: " << clientVendor << endl; + strm << "client glx version string: " << clientVersion << endl; + strm << "client glx extensions: " << clientExtensions << endl; + strm << "glx extensions: " << glxExtensions << endl; + strm << "OpenGL vendor string: " << glVendor << endl; + strm << "OpenGL renderer string: " << glRenderer << endl; + strm << "OpenGL version string: " << glVersion << endl; + strm << "OpenGL extensions: " << glExtensions << endl; + strm << "X Extensions: "; + + int n = 0; + char **extlist = XListExtensions(this->DisplayId, &n); + + for (int i = 0; i < n; i++) + { + if (i != n-1) { + strm << extlist[i] << ", "; + } else { + strm << extlist[i] << endl; + } + } + strm << ends; + delete[] this->Capabilities; + this->Capabilities = strm.str(); + return this->Capabilities; +} + +int vtkXOpenGLRenderWindow::SupportsOpenGL() +{ + MakeCurrent(); + if (!this->DisplayId) + { + return 0; + } + + int value = 0; + XVisualInfo *v = this->GetDesiredVisualInfo(); + if (v) + { + glXGetConfig(this->DisplayId, v, GLX_USE_GL, &value); + } + + return value; +} + + +int vtkXOpenGLRenderWindow::IsDirect() +{ + MakeCurrent(); + if (!this->DisplayId || !this->Internal->ContextId) + { + return 0; + } + this->UsingHardware = glXIsDirect(this->DisplayId, + this->Internal->ContextId) ? 1:0; + return this->UsingHardware; +} + + +void vtkXOpenGLRenderWindow::SetWindowName(const char * cname) +{ + char *name = new char[ strlen(cname)+1 ]; + strcpy(name, cname); + XTextProperty win_name_text_prop; + + vtkOpenGLRenderWindow::SetWindowName( name ); + + if (this->Mapped) + { + if( XStringListToTextProperty( &name, 1, &win_name_text_prop ) == 0 ) + { + XFree (win_name_text_prop.value); + vtkWarningMacro(<< "Can't rename window"); + delete [] name; + return; + } + + XSetWMName( this->DisplayId, this->WindowId, &win_name_text_prop ); + XSetWMIconName( this->DisplayId, this->WindowId, &win_name_text_prop ); + XFree (win_name_text_prop.value); + } + delete [] name; +} + + +// Specify the X window id to use if a WindowRemap is done. +void vtkXOpenGLRenderWindow::SetNextWindowId(Window arg) +{ + vtkDebugMacro(<< "Setting NextWindowId to " << (void *)arg << "\n"); + + this->NextWindowId = arg; +} + +void vtkXOpenGLRenderWindow::SetNextWindowId(void *arg) +{ + this->SetNextWindowId((Window)arg); +} + + +// Set the X display id for this RenderWindow to use to a pre-existing +// X display id. +void vtkXOpenGLRenderWindow::SetDisplayId(Display *arg) +{ + vtkDebugMacro(<< "Setting DisplayId to " << (void *)arg << "\n"); + + this->DisplayId = arg; + this->OwnDisplay = 0; + +} +void vtkXOpenGLRenderWindow::SetDisplayId(void *arg) +{ + this->SetDisplayId((Display *)arg); + this->OwnDisplay = 0; +} + +void vtkXOpenGLRenderWindow::Render() +{ + XWindowAttributes attribs; + + // To avoid the expensive XGetWindowAttributes call, + // compute size at the start of a render and use + // the ivar other times. + if (this->Mapped) + { + // Find the current window size + XGetWindowAttributes(this->DisplayId, + this->WindowId, &attribs); + + this->Size[0] = attribs.width; + this->Size[1] = attribs.height; + } + + // Now do the superclass stuff + this->vtkOpenGLRenderWindow::Render(); +} + +//---------------------------------------------------------------------------- +void vtkXOpenGLRenderWindow::HideCursor() +{ + static char blankBits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + static XColor black = { 0, 0, 0, 0, 0, 0 }; + + if (!this->DisplayId || !this->WindowId) + { + this->CursorHidden = 1; + } + else if (!this->CursorHidden) + { + Pixmap blankPixmap = XCreateBitmapFromData(this->DisplayId, + this->WindowId, + blankBits, 16, 16); + + Cursor blankCursor = XCreatePixmapCursor(this->DisplayId, blankPixmap, + blankPixmap, &black, &black, + 7, 7); + + XDefineCursor(this->DisplayId, this->WindowId, blankCursor); + + XFreePixmap(this->DisplayId, blankPixmap); + + this->CursorHidden = 1; + } +} + +//---------------------------------------------------------------------------- +void vtkXOpenGLRenderWindow::ShowCursor() +{ + if (!this->DisplayId || !this->WindowId) + { + this->CursorHidden = 0; + } + else if (this->CursorHidden) + { + XUndefineCursor(this->DisplayId, this->WindowId); + this->CursorHidden = 0; + } +} + + +//============================================================================ +// Stuff above this is almost a mirror of vtkXOpenGLRenderWindow. +// The code specific to OpenGL Off-Screen stuff may eventually be +// put in a supper class so this whole file could just be included +// (mangled) from vtkXOpenGLRenderWindow like the other OpenGL classes. +//============================================================================ + +void vtkXOpenGLRenderWindow::SetOffScreenRendering(int i) +{ + if (this->OffScreenRendering == i) + { + return; + } + +#ifdef VTK_OPENGL_HAS_OSMESA + // invoke super + this->vtkRenderWindow::SetOffScreenRendering(i); + + // setup everything + if (i) + { + this->Internal->ScreenDoubleBuffer = this->DoubleBuffer; + this->DoubleBuffer = 0; + this->Internal->ScreenMapped = this->Mapped; + this->Mapped = 0; + if (!this->Internal->OffScreenWindow) + { + this->WindowInitialize(); + } + } + else + { + if (this->Internal->OffScreenWindow) + { + OSMesaDestroyContext(this->Internal->OffScreenContextId); + this->Internal->OffScreenContextId = NULL; + vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow); + this->Internal->OffScreenWindow = NULL; + } + this->DoubleBuffer = this->Internal->ScreenDoubleBuffer; + this->Mapped = this->Internal->ScreenMapped; + this->MakeCurrent(); + // reset the size based on the screen window + this->GetSize(); + this->WindowInitialize(); + } +#endif +} + +// This probably has been moved to superclass. +void *vtkXOpenGLRenderWindow::GetGenericWindowId() +{ +#ifdef VTK_OPENGL_HAS_OSMESA + if (this->OffScreenRendering) + { + return (void *)this->Internal->OffScreenWindow; + } +#endif + return (void *)this->WindowId; +} + +void vtkXOpenGLRenderWindow::SetCurrentCursor(int shape) +{ + if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) ) + { + return; + } + this->Superclass::SetCurrentCursor(shape); + if (!this->DisplayId || !this->WindowId) + { + return; + } + + if (shape == VTK_CURSOR_DEFAULT) + { + XUndefineCursor(this->DisplayId,this->WindowId); + return; + } + + switch (shape) + { + case VTK_CURSOR_ARROW: + if (!this->XCArrow) + { + this->XCArrow = XCreateFontCursor(this->DisplayId, XC_top_left_arrow); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCArrow); + break; + case VTK_CURSOR_SIZEALL: + if (!this->XCSizeAll) + { + this->XCSizeAll = XCreateFontCursor(this->DisplayId, XC_fleur); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeAll); + break; + case VTK_CURSOR_SIZENS: + if (!this->XCSizeNS) + { + this->XCSizeNS = XCreateFontCursor(this->DisplayId, + XC_sb_v_double_arrow); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNS); + break; + case VTK_CURSOR_SIZEWE: + if (!this->XCSizeWE) + { + this->XCSizeWE = XCreateFontCursor(this->DisplayId, + XC_sb_h_double_arrow); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeWE); + break; + case VTK_CURSOR_SIZENE: + if (!this->XCSizeNE) + { + this->XCSizeNE = XCreateFontCursor(this->DisplayId, + XC_top_right_corner); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNE); + break; + case VTK_CURSOR_SIZENW: + if (!this->XCSizeNW) + { + this->XCSizeNW = XCreateFontCursor(this->DisplayId, + XC_top_left_corner); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNW); + break; + case VTK_CURSOR_SIZESE: + if (!this->XCSizeSE) + { + this->XCSizeSE = XCreateFontCursor(this->DisplayId, + XC_bottom_right_corner); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeSE); + break; + case VTK_CURSOR_SIZESW: + if (!this->XCSizeSW) + { + this->XCSizeSW = XCreateFontCursor(this->DisplayId, + XC_bottom_left_corner); + } + XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeSW); + break; + } +} diff --git a/Rendering/vtkXOpenGLRenderWindow.h b/Rendering/vtkXOpenGLRenderWindow.h new file mode 100644 index 0000000..5d80d6e --- /dev/null +++ b/Rendering/vtkXOpenGLRenderWindow.h @@ -0,0 +1,251 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXOpenGLRenderWindow.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXOpenGLRenderWindow - OpenGL rendering window +// .SECTION Description +// vtkXOpenGLRenderWindow is a concrete implementation of the abstract class +// vtkRenderWindow. vtkOpenGLRenderer interfaces to the OpenGL graphics +// library. Application programmers should normally use vtkRenderWindow +// instead of the OpenGL specific version. + +#ifndef __vtkXOpenGLRenderWindow_h +#define __vtkXOpenGLRenderWindow_h + +#include "vtkOpenGLRenderWindow.h" +#include // Needed for X types used in the public interface +#include // Needed for X types used in the public interface + +class vtkIdList; +class vtkXOpenGLRenderWindowInternal; + +class VTK_RENDERING_EXPORT vtkXOpenGLRenderWindow : public vtkOpenGLRenderWindow +{ +public: + static vtkXOpenGLRenderWindow *New(); + vtkTypeRevisionMacro(vtkXOpenGLRenderWindow,vtkOpenGLRenderWindow); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Begin the rendering process. + virtual void Start(void); + + // Description: + // End the rendering process and display the image. + virtual void Frame(void); + + // Description: + // Initialize the window for rendering. + virtual void WindowInitialize(void); + + // Description: + // Initialize the rendering window. This will setup all system-specific + // resources. This method and Finalize() must be symmetric and it + // should be possible to call them multiple times, even changing WindowId + // in-between. This is what WindowRemap does. + virtual void Initialize(void); + + // Description: + // "Deinitialize" the rendering window. This will shutdown all system-specific + // resources. After having called this, it should be possible to destroy + // a window that was used for a SetWindowId() call without any ill effects. + virtual void Finalize(void); + + // Description: + // Change the window to fill the entire screen. + virtual void SetFullScreen(int); + + // Description: + // Resize the window. + virtual void WindowRemap(void); + + // Description: + // Set the preferred window size to full screen. + virtual void PrefFullScreen(void); + + // Description: + // Specify the size of the rendering window. + virtual void SetSize(int,int); + virtual void SetSize(int a[2]) {this->SetSize(a[0], a[1]);}; + + // Description: + // Get the X properties of an ideal rendering window. + virtual Colormap GetDesiredColormap(); + virtual Visual *GetDesiredVisual(); + virtual XVisualInfo *GetDesiredVisualInfo(); + virtual int GetDesiredDepth(); + + // Description: + // Prescribe that the window be created in a stereo-capable mode. This + // method must be called before the window is realized. This method + // overrides the superclass method since this class can actually check + // whether the window has been realized yet. + virtual void SetStereoCapableWindow(int capable); + + // Description: + // Make this window the current OpenGL context. + void MakeCurrent(); + + // Description: + // If called, allow MakeCurrent() to skip cache-check when called. + // MakeCurrent() reverts to original behavior of cache-checking + // on the next render. + void SetForceMakeCurrent(); + + // Description: + // Get report of capabilities for the render window + const char *ReportCapabilities(); + + // Description: + // Does this render window support OpenGL? 0-false, 1-true + int SupportsOpenGL(); + + // Description: + // Is this render window using hardware acceleration? 0-false, 1-true + int IsDirect(); + + // Description: + // Xwindow get set functions + virtual void *GetGenericDisplayId() {return (void *)this->GetDisplayId();}; + virtual void *GetGenericWindowId(); + virtual void *GetGenericParentId() {return (void *)this->ParentId;}; + virtual void *GetGenericContext(); + virtual void *GetGenericDrawable() {return (void *)this->WindowId;}; + + // Description: + // Get the size of the screen in pixels + virtual int *GetScreenSize(); + + // Description: + // Get the position in screen coordinates (pixels) of the window. + virtual int *GetPosition(); + + // Description: + // Get this RenderWindow's X display id. + Display *GetDisplayId(); + + // Description: + // Set the X display id for this RenderWindow to use to a pre-existing + // X display id. + void SetDisplayId(Display *); + void SetDisplayId(void *); + + // Description: + // Get this RenderWindow's parent X window id. + Window GetParentId(); + + // Description: + // Sets the parent of the window that WILL BE created. + void SetParentId(Window); + void SetParentId(void *); + + // Description: + // Get this RenderWindow's X window id. + Window GetWindowId(); + + // Description: + // Set this RenderWindow's X window id to a pre-existing window. + void SetWindowId(Window); + void SetWindowId(void *); + + // Description: + // Specify the X window id to use if a WindowRemap is done. + void SetNextWindowId(Window); + + // Description: + // Set the window id of the new window once a WindowRemap is done. + // This is the generic prototype as required by the vtkRenderWindow + // parent. + void SetNextWindowId(void *); + + void SetWindowName(const char *); + + // Description: + // Move the window to a new position on the display. + void SetPosition(int,int); + void SetPosition(int a[2]) {this->SetPosition(a[0], a[1]);}; + + // Description: + // Hide or Show the mouse cursor, it is nice to be able to hide the + // default cursor if you want VTK to display a 3D cursor instead. + void HideCursor(); + void ShowCursor(); + + // Description: + // Change the shape of the cursor + virtual void SetCurrentCursor(int); + + // Description: + // Check to see if a mouse button has been pressed. + // All other events are ignored by this method. + // This is a useful check to abort a long render. + virtual int GetEventPending(); + + // Description: + // Set this RenderWindow's X window id to a pre-existing window. + void SetWindowInfo(char *info); + + // Description: + // Set the window info that will be used after WindowRemap() + void SetNextWindowInfo(char *info); + + // Description: + // Sets the X window id of the window that WILL BE created. + void SetParentInfo(char *info); + + // Description: + // This computes the size of the render window + // before calling the supper classes render + void Render(); + + // Description: + // Render without displaying the window. + void SetOffScreenRendering(int i); + +protected: + vtkXOpenGLRenderWindow(); + ~vtkXOpenGLRenderWindow(); + + vtkXOpenGLRenderWindowInternal *Internal; + + Window ParentId; + Window WindowId; + Window NextWindowId; + Display *DisplayId; + Colormap ColorMap; + int OwnWindow; + int OwnDisplay; + int ScreenSize[2]; + int CursorHidden; + int ForceMakeCurrent; + int UsingHardware; + char *Capabilities; + + // we must keep track of the cursors we are using + Cursor XCArrow; + Cursor XCSizeAll; + Cursor XCSizeNS; + Cursor XCSizeWE; + Cursor XCSizeNE; + Cursor XCSizeNW; + Cursor XCSizeSE; + Cursor XCSizeSW; + +private: + vtkXOpenGLRenderWindow(const vtkXOpenGLRenderWindow&); // Not implemented. + void operator=(const vtkXOpenGLRenderWindow&); // Not implemented. +}; + + + +#endif diff --git a/Rendering/vtkXRenderWindowInteractor.cxx b/Rendering/vtkXRenderWindowInteractor.cxx new file mode 100644 index 0000000..68bcf3a --- /dev/null +++ b/Rendering/vtkXRenderWindowInteractor.cxx @@ -0,0 +1,752 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXRenderWindowInteractor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include +#include +#include +#include +#include +#include "vtkXRenderWindowInteractor.h" +#include "vtkInteractorStyle.h" +#include "vtkXOpenGLRenderWindow.h" +#include "vtkCallbackCommand.h" +#include "vtkActor.h" +#include +#include +#include "vtkObjectFactory.h" +#include "vtkCommand.h" + +vtkCxxRevisionMacro(vtkXRenderWindowInteractor, "$Revision: 1.122 $"); +vtkStandardNewMacro(vtkXRenderWindowInteractor); + +// Initialize static members: +int vtkXRenderWindowInteractor::NumAppInitialized = 0; +XtAppContext vtkXRenderWindowInteractor::App = 0; + + +typedef struct +{ + Visual *visual; + int depth; +} OptionsRec; +OptionsRec Options; + +XtResource resources[] = +{ + {(char *) "visual", (char *) "Visual", XtRVisual, sizeof (Visual *), + XtOffsetOf (OptionsRec, visual), XtRImmediate, NULL}, + {(char *) "depth", (char *) "Depth", XtRInt, sizeof (int), + XtOffsetOf (OptionsRec, depth), XtRImmediate, NULL}, +}; + +XrmOptionDescRec Desc[] = +{ + {(char *) "-visual", (char *) "*visual", XrmoptionSepArg, NULL}, + {(char *) "-depth", (char *) "*depth", XrmoptionSepArg, NULL} +}; + + +// Construct an instance so that the light follows the camera motion. +vtkXRenderWindowInteractor::vtkXRenderWindowInteractor() +{ + this->Top = 0; + this->OwnTop = 0; + this->OwnApp = 0; + this->TopLevelShell = NULL; + this->BreakLoopFlag = 0; + this->BreakXtLoopCallback = vtkCallbackCommand::New(); + this->BreakXtLoopCallback->SetClientData(this); + this->BreakXtLoopCallback->SetCallback( + &vtkXRenderWindowInteractor::BreakXtLoop); +} + +vtkXRenderWindowInteractor::~vtkXRenderWindowInteractor() +{ + this->Disable(); + if(this->OwnTop) + { + XtDestroyWidget(this->Top); + } + this->BreakXtLoopCallback->Delete(); + if (vtkXRenderWindowInteractor::App) + { + if(vtkXRenderWindowInteractor::NumAppInitialized == 1) + { + if(this->OwnApp) + { + XtDestroyApplicationContext(vtkXRenderWindowInteractor::App); + } + vtkXRenderWindowInteractor::App = 0; + } + vtkXRenderWindowInteractor::NumAppInitialized--; + } +} + +// Specify the Xt widget to use for interaction. This method is +// one of a couple steps that are required for setting up a +// vtkRenderWindowInteractor as a widget inside of another user +// interface. You do not need to use this method if the render window +// will be a stand-alone window. This is only used when you want the +// render window to be a subwindow within a larger user interface. +// In that case, you must tell the render window what X display id +// to use, and then ask the render window what depth, visual and +// colormap it wants. Then, you must create an Xt TopLevelShell with +// those settings. Then you can create the rest of your user interface +// as a child of the TopLevelShell you created. Eventually, you will +// create a drawing area or some other widget to serve as the rendering +// window. You must use the SetWidget method to tell this Interactor +// about that widget. It's X and it's not terribly easy, but it looks cool. +void vtkXRenderWindowInteractor::SetWidget(Widget foo) +{ + this->Top = foo; + this->OwnTop = 0; +} + +// This method will store the top level shell widget for the interactor. +// This method and the method invocation sequence applies for: +// 1 vtkRenderWindow-Interactor pair in a nested widget heirarchy +// multiple vtkRenderWindow-Interactor pairs in the same top level shell +// It is not needed for +// 1 vtkRenderWindow-Interactor pair as the direct child of a top level shell +// multiple vtkRenderWindow-Interactor pairs, each in its own top level shell +// +// The method, along with EnterNotify event, changes the keyboard focus among +// the widgets/vtkRenderWindow(s) so the Interactor(s) can receive the proper +// keyboard events. The following calls need to be made: +// vtkRenderWindow's display ID need to be set to the top level shell's +// display ID. +// vtkXRenderWindowInteractor's Widget has to be set to the vtkRenderWindow's +// container widget +// vtkXRenderWindowInteractor's TopLevel has to be set to the top level +// shell widget +// note that the procedure for setting up render window in a widget needs to +// be followed. See vtkRenderWindowInteractor's SetWidget method. +// +// If multiple vtkRenderWindow-Interactor pairs in SEPARATE windows are desired, +// do not set the display ID (Interactor will create them as needed. Alternatively, +// create and set distinct DisplayID for each vtkRenderWindow. Using the same +// display ID without setting the parent widgets will cause the display to be +// reinitialized every time an interactor is initialized), do not set the +// widgets (so the render windows would be in their own windows), and do +// not set TopLevelShell (each has its own top level shell already) +void vtkXRenderWindowInteractor::SetTopLevelShell(Widget topLevel) +{ + this->TopLevelShell = topLevel; +} + +// This function replaces TerminateApp() if Start() is called. +// This way, when the user hits the exit key, Start() returns +// and the application continues instead of calling exit(). +// With this change, it is possible to have clean-up code after +// the interactor loop. +void vtkXRenderWindowInteractor::BreakXtLoop(vtkObject*, unsigned long, + void* iren, void*) +{ + static_cast(iren)->SetBreakLoopFlag(1); +} + +// This will start up the X event loop and never return. If you +// call this method it will loop processing X events until the +// application is exited. +void vtkXRenderWindowInteractor::Start() +{ + // Let the compositing handle the event loop if it wants to. + if (this->HasObserver(vtkCommand::StartEvent)) + { + this->InvokeEvent(vtkCommand::StartEvent,NULL); + return; + } + + if (!this->Initialized) + { + this->Initialize(); + } + if (! this->Initialized ) + { + return; + } + + this->AddObserver(vtkCommand::ExitEvent, this->BreakXtLoopCallback); + this->BreakLoopFlag = 0; + do + { + XEvent event; + XtAppNextEvent(vtkXRenderWindowInteractor::App, &event); + XtDispatchEvent(&event); + } + while (this->BreakLoopFlag == 0); + this->RemoveObserver(this->BreakXtLoopCallback); +} + +// Initializes the event handlers using an XtAppContext that you have +// provided. This assumes that you want to own the event loop. +void vtkXRenderWindowInteractor::Initialize(XtAppContext app) +{ + vtkXRenderWindowInteractor::App = app; + + this->Initialize(); +} + +// Initializes the event handlers without an XtAppContext. This is +// good for when you don't have a user interface, but you still +// want to have mouse interaction. +void vtkXRenderWindowInteractor::Initialize() +{ + vtkXOpenGLRenderWindow *ren; + int depth; + Colormap cmap; + Visual *vis; + int *size; + int *position; + int argc = 0; + + + // make sure we have a RenderWindow and camera + if ( ! this->RenderWindow) + { + vtkErrorMacro(<<"No renderer defined!"); + return; + } + + this->Initialized = 1; + ren = (vtkXOpenGLRenderWindow *)(this->RenderWindow); + + // do initialization stuff if not initialized yet + if (vtkXRenderWindowInteractor::App) + { + vtkXRenderWindowInteractor::NumAppInitialized++; + } + if (!vtkXRenderWindowInteractor::NumAppInitialized) + { + vtkDebugMacro( << "Toolkit init :" << vtkXRenderWindowInteractor::App ); + XtToolkitInitialize(); + vtkXRenderWindowInteractor::App = XtCreateApplicationContext(); + this->OwnApp = 1; + vtkDebugMacro( << "App context :" << vtkXRenderWindowInteractor::App); + vtkXRenderWindowInteractor::NumAppInitialized = 1; + } + + this->DisplayId = ren->GetDisplayId(); + if (!this->DisplayId) + { + vtkDebugMacro("opening display"); + this->DisplayId = + XtOpenDisplay(vtkXRenderWindowInteractor::App,NULL,"VTK","vtk",NULL,0,&argc,NULL); + vtkDebugMacro("opened display"); + } + else + { + // if there is no parent widget + if (!this->Top) + { + XtDisplayInitialize(vtkXRenderWindowInteractor::App,this->DisplayId, + "VTK","vtk",NULL,0,&argc,NULL); + } + } + + // get the info we need from the RenderingWindow + ren->SetDisplayId(this->DisplayId); + + size = ren->GetSize(); + size[0] = ((size[0] > 0) ? size[0] : 300); + size[1] = ((size[1] > 0) ? size[1] : 300); + if (!this->Top) + { + depth = ren->GetDesiredDepth(); + cmap = ren->GetDesiredColormap(); + vis = ren->GetDesiredVisual(); + position= ren->GetPosition(); + + this->Top = XtVaAppCreateShell(this->RenderWindow->GetWindowName(),"vtk", + applicationShellWidgetClass, + this->DisplayId, + XtNdepth, depth, + XtNcolormap, cmap, + XtNvisual, vis, + XtNx, position[0], + XtNy, position[1], + XtNwidth, size[0], + XtNheight, size[1], + XtNinput, True, + XtNmappedWhenManaged, 0, + NULL); + this->OwnTop = 1; + XtRealizeWidget(this->Top); + XSync(this->DisplayId,False); + ren->SetWindowId(XtWindow(this->Top)); + + XMapWindow(this->DisplayId, XtWindow(this->Top)); + XSync(this->DisplayId,False); + } + else + { + XWindowAttributes attribs; + + XtRealizeWidget(this->Top); + XSync(this->DisplayId,False); + ren->SetWindowId(XtWindow(this->Top)); + + XMapWindow(this->DisplayId, XtWindow(this->Top)); + XSync(this->DisplayId,False); + + // Find the current window size + XGetWindowAttributes(this->DisplayId, + XtWindow(this->Top), &attribs); + size[0] = attribs.width; + size[1] = attribs.height; + ren->SetSize(size[0], size[1]); + } + + this->WindowId = XtWindow(this->Top); + ren->Start(); + this->Enable(); + this->Size[0] = size[0]; + this->Size[1] = size[1]; +} + +void vtkXRenderWindowInteractor::Enable() +{ + // avoid cycles of calling Initialize() and Enable() + if (this->Enabled) + { + return; + } + + // Add the event handler to the system. + // If we change the types of events processed by this handler, then + // we need to change the Disable() routine to match. In order for Disable() + // to work properly, both the callback function AND the client data + // passed to XtAddEventHandler and XtRemoveEventHandler must MATCH + // PERFECTLY + XtAddEventHandler(this->Top, + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + ExposureMask | StructureNotifyMask | + EnterWindowMask | LeaveWindowMask | + PointerMotionHintMask | PointerMotionMask, + True, // True means we also observe ClientMessage + vtkXRenderWindowInteractorCallback,(XtPointer)this); + + // Setup for capturing the window deletion + this->KillAtom = XInternAtom(this->DisplayId,"WM_DELETE_WINDOW",False); + XSetWMProtocols(this->DisplayId,this->WindowId,&this->KillAtom,1); + + this->Enabled = 1; + + this->Modified(); +} + +void vtkXRenderWindowInteractor::Disable() +{ + if (!this->Enabled) + { + return; + } + + // Remove the event handler to the system. + // If we change the types of events processed by this handler, then + // we need to change the Disable() routine to match. In order for Disable() + // to work properly, both the callback function AND the client data + // passed to XtAddEventHandler and XtRemoveEventHandler must MATCH + // PERFECTLY. + // + // NOTE: we do not remove the StructureNotifyMask event since we need to + // keep track of the window size (we will not render if we are disabled, + // we simply track the window size changes for a possible Enable()). + // Expose events are disabled. + XtRemoveEventHandler(this->Top, + KeyPressMask | KeyReleaseMask | ButtonPressMask | + ExposureMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | + PointerMotionHintMask | PointerMotionMask, + True,vtkXRenderWindowInteractorCallback,(XtPointer)this); + + this->Enabled = 0; + this->Modified(); +} + + +void vtkXRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if (vtkXRenderWindowInteractor::App) + { + os << indent << "App: " << this->App << "\n"; + } + else + { + os << indent << "App: (none)\n"; + } + os << indent << "BreakLoopFlag: " + << (this->BreakLoopFlag ? "On\n" : "Off\n"); +} + +//void vtkXRenderWindowInteractor::UpdateSize(int x,int y) +//{ +// // if the size changed send this on to the RenderWindow +// if ((x != this->Size[0])||(y != this->Size[1])) +// { +// this->Size[0] = x; +// this->Size[1] = y; +// this->RenderWindow->SetSize(x,y); +// } +// +//} + +void vtkXRenderWindowInteractorTimer(XtPointer client_data, + XtIntervalId *vtkNotUsed(id)) +{ + vtkXRenderWindowInteractor *me; + me = (vtkXRenderWindowInteractor *)client_data; + + if (me->Enabled) + { + me->InvokeEvent(vtkCommand::TimerEvent,NULL); + } +} + +int vtkXRenderWindowInteractor::CreateTimer(int vtkNotUsed(timertype)) +{ + this->AddTimeOut(vtkXRenderWindowInteractor::App, 10, + vtkXRenderWindowInteractorTimer, + (XtPointer)this); + return 1; +} + +int vtkXRenderWindowInteractor::DestroyTimer(void) +{ + // timers automatically expire in X windows + return 1; +} + +void vtkXRenderWindowInteractorCallback(Widget vtkNotUsed(w), + XtPointer client_data, + XEvent *event, + Boolean *vtkNotUsed(ctd)) +{ + vtkXRenderWindowInteractor *me; + int xp, yp; + + me = (vtkXRenderWindowInteractor *)client_data; + + switch (event->type) + { + case Expose: + { + if (!me->Enabled) + { + return; + } + XEvent result; + while (XCheckTypedWindowEvent(me->DisplayId, + me->WindowId, + Expose, + &result)) + { + // just getting the expose configure event + event = &result; + } + int width = (reinterpret_cast(event))->width; + int height = (reinterpret_cast(event))->height; + me->SetEventSize(width, height); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + yp = me->Size[1] - xp - 1; + me->SetEventPosition(xp, yp); + // only render if we are currently accepting events + if (me->Enabled) + { + me->InvokeEvent(vtkCommand::ExposeEvent,NULL); + me->Render(); + } + } + break; + + case MapNotify: + { + // only render if we are currently accepting events + if (me->Enabled && me->GetRenderWindow()->GetNeverRendered()) + { + me->Render(); + } + } + break; + + case ConfigureNotify: + { + XEvent result; + while (XCheckTypedWindowEvent(me->DisplayId, me->WindowId, + ConfigureNotify, &result)) + { + // just getting the last configure event + event = &result; + } + int width = (reinterpret_cast(event))->width; + int height = (reinterpret_cast(event))->height; + if (width != me->Size[0] || height != me->Size[1]) + { + me->UpdateSize(width, height); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventPosition(xp, me->Size[1] - yp - 1); + // only render if we are currently accepting events + if (me->Enabled) + { + me->InvokeEvent(vtkCommand::ConfigureEvent,NULL); + me->Render(); + } + } + } + break; + + case ButtonPress: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + + // check for double click + static int MousePressTime = 0; + int repeat = 0; + // 400 ms threshold by default is probably good to start + if((reinterpret_cast(event)->time - MousePressTime) < 400) + { + MousePressTime -= 2000; // no double click next time + repeat = 1; + } + else + { + MousePressTime = reinterpret_cast(event)->time; + } + + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift, + 0, + repeat); + switch ((reinterpret_cast(event))->button) + { + case Button1: + me->InvokeEvent(vtkCommand::LeftButtonPressEvent,NULL); + break; + case Button2: + me->InvokeEvent(vtkCommand::MiddleButtonPressEvent,NULL); + break; + case Button3: + me->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL); + break; + case Button4: + me->InvokeEvent(vtkCommand::MouseWheelForwardEvent,NULL); + break; + case Button5: + me->InvokeEvent(vtkCommand::MouseWheelBackwardEvent,NULL); + break; + } + } + break; + + case ButtonRelease: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift); + switch ((reinterpret_cast(event))->button) + { + case Button1: + me->InvokeEvent(vtkCommand::LeftButtonReleaseEvent,NULL); + break; + case Button2: + me->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent,NULL); + break; + case Button3: + me->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL); + break; + } + } + break; + + case EnterNotify: + { + // Force the keyboard focus to be this render window + if (me->TopLevelShell != NULL) + { + XtSetKeyboardFocus(me->TopLevelShell, me->Top); + } + if (me->Enabled) + { + XEnterWindowEvent *e = reinterpret_cast(event); + me->SetEventInformationFlipY(e->x, + e->y, + (e->state & ControlMask) != 0, + (e->state & ShiftMask) != 0); + me->InvokeEvent(vtkCommand::EnterEvent, NULL); + } + } + break; + + case LeaveNotify: + { + if (me->Enabled) + { + XLeaveWindowEvent *e = reinterpret_cast(event); + me->SetEventInformationFlipY(e->x, + e->y, + (e->state & ControlMask) != 0, + (e->state & ShiftMask) != 0); + me->InvokeEvent(vtkCommand::LeaveEvent, NULL); + } + } + break; + + case KeyPress: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + KeySym ks; + static char buffer[20]; + buffer[0] = '\0'; + XLookupString(reinterpret_cast(event),buffer, 20, &ks,NULL); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift, + buffer[0], + 1, + XKeysymToString(ks)); + me->InvokeEvent(vtkCommand::KeyPressEvent, NULL); + me->InvokeEvent(vtkCommand::CharEvent, NULL); + } + break; + + case KeyRelease: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + KeySym ks; + static char buffer[20]; + buffer[0] = '\0'; + XLookupString(reinterpret_cast(event),buffer, 20, &ks,NULL); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift, + buffer[0], + 1, + XKeysymToString(ks)); + me->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL); + } + break; + + case MotionNotify: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + + // Note that even though the (x,y) location of the pointer is event structure, + // we must call XQueryPointer for the hints (motion event compression) to + // work properly. + me->GetMousePosition(&xp, &yp); + me->SetEventInformation(xp, yp, ctrl, shift); + me->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); + } + break; + + case ClientMessage: + { + if( static_cast(event->xclient.data.l[0]) == me->KillAtom ) + { + me->InvokeEvent(vtkCommand::ExitEvent, NULL); + } + } + break; + } +} + + +XtIntervalId vtkXRenderWindowInteractor::AddTimeOut(XtAppContext app_context, + unsigned long interval, + XtTimerCallbackProc proc, + XtPointer client_data) +{ + return XtAppAddTimeOut(app_context, interval, proc, client_data); +} + +void vtkXRenderWindowInteractor::GetMousePosition(int *x, int *y) +{ + Window root,child; + int root_x,root_y; + unsigned int keys; + + XQueryPointer(this->DisplayId,this->WindowId, + &root,&child,&root_x,&root_y,x,y,&keys); + + *y = this->Size[1] - *y - 1; +} + +void vtkXRenderWindowInteractor::Timer(XtPointer client_data, + XtIntervalId *id) +{ + vtkXRenderWindowInteractorTimer(client_data, id); +} + +void vtkXRenderWindowInteractor::Callback(Widget w, + XtPointer client_data, + XEvent *event, + Boolean *ctd) +{ + vtkXRenderWindowInteractorCallback(w, client_data, event, ctd); +} + + diff --git a/Rendering/vtkXRenderWindowInteractor.h b/Rendering/vtkXRenderWindowInteractor.h new file mode 100644 index 0000000..cfac844 --- /dev/null +++ b/Rendering/vtkXRenderWindowInteractor.h @@ -0,0 +1,194 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXRenderWindowInteractor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXRenderWindowInteractor - an X event driven interface for a RenderWindow +// .SECTION Description +// vtkXRenderWindowInteractor is a convenience object that provides event +// bindings to common graphics functions. For example, camera and actor +// functions such as zoom-in/zoom-out, azimuth, roll, and pan. IT is one of +// the window system specific subclasses of vtkRenderWindowInteractor. Please +// see vtkRenderWindowInteractor documentation for event bindings. +// +// .SECTION see also +// vtkRenderWindowInteractor vtkXRenderWindow + +// I've been though this and deleted all I think should go, tried to create +// the basic structure and if you're lucky it might even work! +// but frankly I doubt it + +#ifndef __vtkXRenderWindowInteractor_h +#define __vtkXRenderWindowInteractor_h + +//=========================================================== +// now we define the C++ class + +#include "vtkRenderWindowInteractor.h" +#include // Needed for X types in the public interface +#include // Needed for X types in the public interface + +class vtkCallbackCommand; + +//BTX +// Forward declare internal friend functions. +void vtkXRenderWindowInteractorCallback(Widget,XtPointer, XEvent *,Boolean *); +void vtkXRenderWindowInteractorTimer(XtPointer,XtIntervalId *); +//ETX + +class VTK_RENDERING_EXPORT vtkXRenderWindowInteractor : public vtkRenderWindowInteractor +{ +public: + static vtkXRenderWindowInteractor *New(); + vtkTypeRevisionMacro(vtkXRenderWindowInteractor,vtkRenderWindowInteractor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initializes the event handlers without an XtAppContext. This is + // good for when you don't have a user interface, but you still + // want to have mouse interaction. + virtual void Initialize(); + + // Description: + // Call exit on 'q','e' keypress. Want more ??? + void TerminateApp(void) { exit(0); } + + // Description: + // The BreakLoopFlag is checked in the Start() method. + // Setting it to anything other than zero will cause + // the interactor loop to terminate and return to the + // calling function. + vtkSetMacro(BreakLoopFlag, int); + vtkGetMacro(BreakLoopFlag, int); + vtkBooleanMacro(BreakLoopFlag, int); + + // Description: + // X timer methods + int CreateTimer(int timertype); + int DestroyTimer(void); + + // Description: + // Initializes the event handlers using an XtAppContext that you have + // provided. This assumes that you want to own the event loop. + virtual void Initialize(XtAppContext app); + vtkGetMacro( App, XtAppContext ); + + // Description: + // Enable/Disable interactions. By default interactors are enabled when + // initialized. Initialize() must be called prior to enabling/disabling + // interaction. These methods are used when a window/widget is being + // shared by multiple renderers and interactors. This allows a "modal" + // display where one interactor is active when its data is to be displayed + // and all other interactors associated with the widget are disabled + // when their data is not displayed. + virtual void Enable(); + virtual void Disable(); + + // Description: + // This will start up the X event loop and never return. If you + // call this method it will loop processing X events until the + // application is exited. + virtual void Start(); + + // Description: + // Specify the Xt widget to use for interaction. This method is + // one of a couple steps that are required for setting up a + // vtkRenderWindowInteractor as a widget inside of another user + // interface. You do not need to use this method if the render window + // will be a stand-alone window. This is only used when you want the + // render window to be a subwindow within a larger user interface. + // In that case, you must tell the render window what X display id + // to use, and then ask the render window what depth, visual and + // colormap it wants. Then, you must create an Xt TopLevelShell with + // those settings. Then you can create the rest of your user interface + // as a child of the TopLevelShell you created. Eventually, you will + // create a drawing area or some other widget to serve as the rendering + // window. You must use the SetWidget method to tell this Interactor + // about that widget. It's X and it's not terribly easy, but it looks cool. + virtual void SetWidget(Widget); + Widget GetWidget() {return this->Top;}; + + // Description + // This method will store the top level shell widget for the interactor. + // This method and the method invocation sequence applies for: + // 1 vtkRenderWindow-Interactor pair in a nested widget hierarchy + // multiple vtkRenderWindow-Interactor pairs in the same top level shell + // It is not needed for + // 1 vtkRenderWindow-Interactor pair as the direct child of a top level shell + // multiple vtkRenderWindow-Interactor pairs, each in its own top level shell + // + // The method, along with EnterNotify event, changes the keyboard focus among + // the widgets/vtkRenderWindow(s) so the Interactor(s) can receive the proper + // keyboard events. The following calls need to be made: + // vtkRenderWindow's display ID need to be set to the top level shell's + // display ID. + // vtkXRenderWindowInteractor's Widget has to be set to the vtkRenderWindow's + // container widget + // vtkXRenderWindowInteractor's TopLevel has to be set to the top level + // shell widget + // note that the procedure for setting up render window in a widget needs to + // be followed. See vtkRenderWindowInteractor's SetWidget method. + // + // If multiple vtkRenderWindow-Interactor pairs in SEPARATE windows are desired, + // do not set the display ID (Interactor will create them as needed. Alternatively, + // create and set distinct DisplayID for each vtkRenderWindow. Using the same + // display ID without setting the parent widgets will cause the display to be + // reinitialized every time an interactor is initialized), do not set the + // widgets (so the render windows would be in their own windows), and do + // not set TopLevelShell (each has its own top level shell already) + virtual void SetTopLevelShell(Widget); + Widget GetTopLevelShell() {return this->TopLevelShell;}; + + // Description: + // Re-defines virtual function to get mouse position by querying X-server. + virtual void GetMousePosition(int *x, int *y); + + // Description: + // Functions that are used internally. + friend void vtkXRenderWindowInteractorCallback(Widget,XtPointer, + XEvent *,Boolean *); + friend void vtkXRenderWindowInteractorTimer(XtPointer,XtIntervalId *); + +protected: + vtkXRenderWindowInteractor(); + ~vtkXRenderWindowInteractor(); + + //Using static here to avoid detroying context when many apps are open: + static XtAppContext App; + static int NumAppInitialized; + + Display *DisplayId; + Window WindowId; + Atom KillAtom; + Widget Top; + int OwnTop; + int OwnApp; + int PositionBeforeStereo[2]; + Widget TopLevelShell; + + int BreakLoopFlag; + XtIntervalId AddTimeOut(XtAppContext app_context, unsigned long interval, + XtTimerCallbackProc proc, XtPointer client_data) ; + void Timer(XtPointer client_data, XtIntervalId *id); + void Callback(Widget w, XtPointer client_data, XEvent *event, Boolean *ctd); + + vtkCallbackCommand* BreakXtLoopCallback; + static void BreakXtLoop(vtkObject*, unsigned long, void*, void*); +private: + vtkXRenderWindowInteractor(const vtkXRenderWindowInteractor&); // Not implemented. + void operator=(const vtkXRenderWindowInteractor&); // Not implemented. +}; + +#endif + + + diff --git a/Rendering/vtkXRenderWindowTclInteractor.cxx b/Rendering/vtkXRenderWindowTclInteractor.cxx new file mode 100644 index 0000000..255134a --- /dev/null +++ b/Rendering/vtkXRenderWindowTclInteractor.cxx @@ -0,0 +1,636 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXRenderWindowTclInteractor.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkActorCollection.h" +#include "vtkObjectFactory.h" +#include "vtkOldStyleCallbackCommand.h" +#include "vtkPoints.h" +#include "vtkXOpenGLRenderWindow.h" +#include "vtkXRenderWindowTclInteractor.h" +#include +#include +#include +#include +#include +#include +#include +#include + +vtkCxxRevisionMacro(vtkXRenderWindowTclInteractor, "$Revision: 1.50 $"); +vtkStandardNewMacro(vtkXRenderWindowTclInteractor); + +// steal the first three elements of the TkMainInfo stuct +// we don't care about the rest of the elements. +struct TkMainInfo +{ + int refCount; + struct TkWindow *winPtr; + Tcl_Interp *interp; +}; + +#if ((TK_MAJOR_VERSION <= 4)||((TK_MAJOR_VERSION == 8)&&(TK_MINOR_VERSION == 0))) +extern TkMainInfo *tkMainWindowList; +#else +extern "C" {TkMainInfo *TkGetMainInfoList();} +#endif + +// returns 1 if done +static int vtkTclEventProc(XtPointer clientData,XEvent *event) +{ + Boolean ctd; + vtkXOpenGLRenderWindow *rw; + + rw = (vtkXOpenGLRenderWindow *) + (((vtkXRenderWindowTclInteractor *)clientData)->GetRenderWindow()); + + if (rw->GetWindowId() == (reinterpret_cast(event))->window) + { + vtkXRenderWindowTclInteractorCallback((Widget)NULL,clientData, event, &ctd); + ctd = 0; + } + else + { + ctd = 1; + } + + return !ctd; +} + +extern "C" +{ + void vtkXTclTimerProc(ClientData clientData) + { + XtIntervalId id; + + vtkXRenderWindowTclInteractorTimer((XtPointer)clientData,&id); + } +} + + + +// Construct object so that light follows camera motion. +vtkXRenderWindowTclInteractor::vtkXRenderWindowTclInteractor() +{ + this->App = 0; + this->top = 0; + this->TopLevelShell = NULL; + this->BreakLoopFlag = 0; +} + +vtkXRenderWindowTclInteractor::~vtkXRenderWindowTclInteractor() +{ + if (this->Initialized) + { + Tk_DeleteGenericHandler((Tk_GenericProc *)vtkTclEventProc, + (ClientData)this); + } +} + +void vtkXRenderWindowTclInteractor::SetWidget(Widget foo) +{ + this->top = foo; +} + +// This method will store the top level shell widget for the interactor. +// This method and the method invocation sequence applies for: +// 1 vtkRenderWindow-Interactor pair in a nested widget heirarchy +// multiple vtkRenderWindow-Interactor pairs in the same top level shell +// It is not needed for +// 1 vtkRenderWindow-Interactor pair as the direct child of a top level shell +// multiple vtkRenderWindow-Interactor pairs, each in its own top level shell +// +// The method, along with EnterNotify event, changes the keyboard focus among +// the widgets/vtkRenderWindow(s) so the Interactor(s) can receive the proper +// keyboard events. The following calls need to be made: +// vtkRenderWindow's display ID need to be set to the top level shell's +// display ID. +// vtkXRenderWindowTclInteractor's Widget has to be set to the vtkRenderWindow's +// container widget +// vtkXRenderWindowTclInteractor's TopLevel has to be set to the top level +// shell widget +// note that the procedure for setting up render window in a widget needs to +// be followed. See vtkRenderWindowInteractor's SetWidget method. +// +// If multiple vtkRenderWindow-Interactor pairs in SEPARATE windows are desired, +// do not set the display ID (Interactor will create them as needed. Alternatively, +// create and set distinct DisplayID for each vtkRenderWindow. Using the same +// display ID without setting the parent widgets will cause the display to be +// reinitialized every time an interactor is initialized), do not set the +// widgets (so the render windows would be in their own windows), and do +// not set TopLevelShell (each has its own top level shell already) +void vtkXRenderWindowTclInteractor::SetTopLevelShell(Widget topLevel) +{ + this->TopLevelShell = topLevel; +} + + +static void vtkBreakTclLoop(void *iren) +{ + ((vtkXRenderWindowTclInteractor*)iren)->SetBreakLoopFlag(1); +} + +void vtkXRenderWindowTclInteractor::Start() +{ + // Let the compositing handle the event loop if it wants to. + if (this->HasObserver(vtkCommand::StartEvent)) + { + this->InvokeEvent(vtkCommand::StartEvent,NULL); + return; + } + + vtkOldStyleCallbackCommand *cbc = vtkOldStyleCallbackCommand::New(); + cbc->Callback = vtkBreakTclLoop; + cbc->ClientData = this; + unsigned long ExitTag = this->AddObserver(vtkCommand::ExitEvent,cbc, 0.5); + cbc->Delete(); + + this->BreakLoopFlag = 0; + while(this->BreakLoopFlag == 0) + { + Tk_DoOneEvent(0); + } + this->RemoveObserver(ExitTag); +} + +// Initializes the event handlers +void vtkXRenderWindowTclInteractor::Initialize(XtAppContext app) +{ + this->App = app; + + this->Initialize(); +} + +// Begin processing keyboard strokes. +void vtkXRenderWindowTclInteractor::Initialize() +{ + vtkXOpenGLRenderWindow *ren; + int *size; + + // make sure we have a RenderWindow and camera + if ( ! this->RenderWindow) + { + vtkErrorMacro(<<"No renderer defined!"); + return; + } + + this->Initialized = 1; + ren = (vtkXOpenGLRenderWindow *)(this->RenderWindow); + + // use the same display as tcl/tk +#if ((TK_MAJOR_VERSION <= 4)||((TK_MAJOR_VERSION == 8)&&(TK_MINOR_VERSION == 0))) + ren->SetDisplayId(Tk_Display(tkMainWindowList->winPtr)); +#else + ren->SetDisplayId(Tk_Display(TkGetMainInfoList()->winPtr)); +#endif + this->DisplayId = ren->GetDisplayId(); + + // get the info we need from the RenderingWindow + size = ren->GetSize(); + + size = ren->GetSize(); + ren->Start(); + this->WindowId = ren->GetWindowId(); + size = ren->GetSize(); + + this->Size[0] = size[0]; + this->Size[1] = size[1]; + + this->Enable(); + + // Set the event handler + Tk_CreateGenericHandler((Tk_GenericProc *)vtkTclEventProc,(ClientData)this); +} + + +void vtkXRenderWindowTclInteractor::Enable() +{ + // avoid cycles of calling Initialize() and Enable() + if (this->Enabled) + { + return; + } + + // Select the events that we want to respond to + // (Multiple calls to XSelectInput overrides the previous settings) + XSelectInput(this->DisplayId, this->WindowId, + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + ExposureMask | StructureNotifyMask | + EnterWindowMask | LeaveWindowMask | + PointerMotionMask | PointerMotionMask); + + // Setup for capturing the window deletion + this->KillAtom = XInternAtom(this->DisplayId,"WM_DELETE_WINDOW",False); + XSetWMProtocols(this->DisplayId,this->WindowId,&this->KillAtom,1); + + this->Enabled = 1; + + this->Modified(); +} + +void vtkXRenderWindowTclInteractor::Disable() +{ + if (!this->Enabled) + { + return; + } + + // Remove the all the events that we registered for EXCEPT for + // StructureNotifyMask event since we need to keep track of the window + // size (we will not render if we are disabled, we simply track the window + // size changes for a possible Enable()). Expose events are disabled. + // (Multiple calls to XSelectInput overrides the previous settings) + XSelectInput(this->DisplayId,this->WindowId, + StructureNotifyMask ); + + this->Enabled = 0; + this->Modified(); +} + + +void vtkXRenderWindowTclInteractor::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if (this->App) + { + os << indent << "App: " << this->App << "\n"; + } + else + { + os << indent << "App: (none)\n"; + } + os << indent << "Break Loop Flag: " + << (this->BreakLoopFlag ? "On\n" : "Off\n"); +} + + +void vtkXRenderWindowTclInteractor::UpdateSize(int x,int y) +{ + // if the size changed send this on to the RenderWindow + if ((x != this->Size[0])||(y != this->Size[1])) + { + this->Size[0] = x; + this->Size[1] = y; + this->RenderWindow->SetSize(x,y); + } + +} + + +void vtkXRenderWindowTclInteractorCallback(Widget vtkNotUsed(w), + XtPointer client_data, + XEvent *event, + Boolean *vtkNotUsed(ctd)) +{ + vtkXRenderWindowTclInteractor *me; + + me = (vtkXRenderWindowTclInteractor *)client_data; + int xp, yp; + + switch (event->type) + { + case Expose: + { + if (!me->Enabled) + { + return; + } + XEvent result; + while (XCheckTypedWindowEvent(me->DisplayId, + me->WindowId, + Expose, + &result)) + { + // just getting the expose configure event + event = &result; + } + int width = (reinterpret_cast(event))->width; + int height = (reinterpret_cast(event))->height; + me->SetEventSize(width, height); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + yp = me->Size[1] - xp - 1; + me->SetEventPosition(xp, yp); + // only render if we are currently accepting events + if (me->Enabled) + { + me->InvokeEvent(vtkCommand::ExposeEvent,NULL); + me->Render(); + } + } + break; + + case MapNotify: + { + // only render if we are currently accepting events + if (me->Enabled && me->GetRenderWindow()->GetNeverRendered()) + { + me->Render(); + } + } + break; + + case ConfigureNotify: + { + XEvent result; + while (XCheckTypedWindowEvent(me->DisplayId, + me->WindowId, + ConfigureNotify, + &result)) + { + // just getting the last configure event + event = &result; + } + int width = (reinterpret_cast(event))->width; + int height = (reinterpret_cast(event))->height; + if (width != me->Size[0] || height != me->Size[1]) + { + me->UpdateSize(width, height); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventPosition(xp, me->Size[1] - yp - 1); + // only render if we are currently accepting events + if (me->Enabled) + { + me->InvokeEvent(vtkCommand::ConfigureEvent,NULL); + me->Render(); + } + } + } + break; + + case ButtonPress: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift); + switch ((reinterpret_cast(event))->button) + { + case Button1: + me->InvokeEvent(vtkCommand::LeftButtonPressEvent, NULL); + break; + case Button2: + me->InvokeEvent(vtkCommand::MiddleButtonPressEvent, NULL); + break; + case Button3: + me->InvokeEvent(vtkCommand::RightButtonPressEvent, NULL); + break; + case Button4: + me->InvokeEvent(vtkCommand::MouseWheelForwardEvent, NULL); + break; + case Button5: + me->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, NULL); + break; + } + } + break; + + case ButtonRelease: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + + // check for double click + static int MousePressTime = 0; + int repeat = 0; + // 400 ms threshold by default is probably good to start + if((reinterpret_cast(event)->time - MousePressTime) < 400) + { + MousePressTime -= 2000; // no double click next time + repeat = 1; + } + else + { + MousePressTime = reinterpret_cast(event)->time; + } + + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift, + 0, + repeat); + switch ((reinterpret_cast(event))->button) + { + case Button1: + me->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, NULL); + break; + case Button2: + me->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, NULL); + break; + case Button3: + me->InvokeEvent(vtkCommand::RightButtonReleaseEvent, NULL); + break; + } + } + break; + + case EnterNotify: + { + // Force the keyboard focus to be this render window + if (me->TopLevelShell != NULL) + { + XtSetKeyboardFocus(me->TopLevelShell, me->top); + } + if (me->Enabled) + { + XEnterWindowEvent *e = reinterpret_cast(event); + me->SetEventInformationFlipY(e->x, + e->y, + (e->state & ControlMask) != 0, + (e->state & ShiftMask) != 0); + me->InvokeEvent(vtkCommand::EnterEvent, NULL); + } + } + break; + + case LeaveNotify: + { + if (me->Enabled) + { + XLeaveWindowEvent *e = reinterpret_cast(event); + me->SetEventInformationFlipY(e->x, + e->y, + (e->state & ControlMask) != 0, + (e->state & ShiftMask) != 0); + me->InvokeEvent(vtkCommand::LeaveEvent, NULL); + } + } + break; + + case KeyPress: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + KeySym ks; + static char buffer[20]; + buffer[0] = '\0'; + XLookupString(reinterpret_cast(event),buffer, 20, &ks,NULL); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift, + buffer[0], + 1, + XKeysymToString(ks)); + me->InvokeEvent(vtkCommand::KeyPressEvent, NULL); + me->InvokeEvent(vtkCommand::CharEvent, NULL); + } + break; + + case KeyRelease: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + KeySym ks; + static char buffer[20]; + buffer[0] = '\0'; + XLookupString(reinterpret_cast(event),buffer, 20, &ks,NULL); + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift, + buffer[0], + 1, + XKeysymToString(ks)); + me->InvokeEvent(vtkCommand::KeyReleaseEvent, NULL); + } + break; + + case MotionNotify: + { + if (!me->Enabled) + { + return; + } + int ctrl = + (reinterpret_cast(event))->state & ControlMask ? 1 : 0; + int shift = + (reinterpret_cast(event))->state & ShiftMask ? 1 : 0; + xp = (reinterpret_cast(event))->x; + yp = (reinterpret_cast(event))->y; + me->SetEventInformationFlipY(xp, + yp, + ctrl, + shift); + me->InvokeEvent(vtkCommand::MouseMoveEvent, NULL); + } + break; + + case ClientMessage: + { + if( static_cast(event->xclient.data.l[0]) == me->KillAtom ) + { + me->InvokeEvent(vtkCommand::ExitEvent, NULL); + } + } + break; + } +} + +void vtkXRenderWindowTclInteractorTimer(XtPointer client_data, + XtIntervalId *vtkNotUsed(id)) +{ + vtkXRenderWindowTclInteractor *me; + me = (vtkXRenderWindowTclInteractor *)client_data; + Window root,child; + int root_x,root_y; + int x,y; + unsigned int keys; + + // get the pointer position + XQueryPointer(me->DisplayId, + me->WindowId, + &root, + &child, + &root_x, + &root_y, + &x, + &y, + &keys); + if (!me->Enabled) + { + return; + } + me->SetEventInformationFlipY(x, + y, + 0, + 0); + me->InvokeEvent(vtkCommand::TimerEvent, NULL); +} + +int vtkXRenderWindowTclInteractor::CreateTimer(int vtkNotUsed(timertype)) +{ + Tk_CreateTimerHandler(10,vtkXTclTimerProc,(ClientData)this); + return 1; +} + +int vtkXRenderWindowTclInteractor::DestroyTimer(void) +{ + // timers automatically expire in X windows + return 1; +} + +void vtkXRenderWindowTclInteractor::TerminateApp(void) +{ +#if ((TK_MAJOR_VERSION <= 4)||((TK_MAJOR_VERSION == 8)&&(TK_MINOR_VERSION == 0))) + Tcl_Interp* interp = tkMainWindowList->interp; +#else + Tcl_Interp* interp = TkGetMainInfoList()->interp; +#endif + +#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 2 + char es[12]; + strcpy(es,"exit"); + Tcl_GlobalEval(interp, es); +#else + Tcl_EvalEx(interp, "exit", -1, TCL_EVAL_GLOBAL); +#endif +} diff --git a/Rendering/vtkXRenderWindowTclInteractor.h b/Rendering/vtkXRenderWindowTclInteractor.h new file mode 100644 index 0000000..5905cc9 --- /dev/null +++ b/Rendering/vtkXRenderWindowTclInteractor.h @@ -0,0 +1,175 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXRenderWindowTclInteractor.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXRenderWindowTclInteractor - a TCL event driven interface for a RenderWindow +// .SECTION Description +// vtkXRenderWindowTclInteractor is a convenience object that provides event +// bindings to common graphics functions. For example, camera and actor +// functions such as zoom-in/zoom-out, azimuth, roll, and pan. IT is one of +// the window system specific subclasses of vtkRenderWindowInteractor. Please +// see vtkRenderWindowInteractor documentation for event bindings. +// +// .SECTION see also +// vtkRenderWindowInteractor vtkXRenderWindow + + +#ifndef __vtkXRenderWindowTclInteractor_h +#define __vtkXRenderWindowTclInteractor_h + +//=========================================================== +// now we define the C++ class + +#include "vtkRenderWindowInteractor.h" +#include // Needed for X types in public interface +#include // Needed for X types in public interface + +extern void vtkXRenderWindowTclInteractorCallback(Widget,XtPointer, + XEvent *,Boolean *); +extern void vtkXRenderWindowTclInteractorTimer(XtPointer,XtIntervalId *); + +class VTK_RENDERING_EXPORT vtkXRenderWindowTclInteractor : public vtkRenderWindowInteractor +{ +public: + static vtkXRenderWindowTclInteractor *New(); + vtkTypeRevisionMacro(vtkXRenderWindowTclInteractor,vtkRenderWindowInteractor); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Initializes the event handlers without an XtAppContext. This is + // good for when you don't have a user interface, but you still + // want to have mouse interaction. + virtual void Initialize(); + + // Description: + // Initializes the event handlers using an XtAppContext that you have + // provided. This assumes that you want to own the event loop. + virtual void Initialize(XtAppContext app); + vtkGetMacro( App, XtAppContext ); + + // Description: + // Enable/Disable interactions. By default interactors are enabled when + // initialized. Initialize() must be called prior to enabling/disabling + // interaction. These methods are used when a window/widget is being + // shared by multiple renderers and interactors. This allows a "modal" + // display where one interactor is active when its data is to be displayed + // and all other interactors associated with the widget are disabled + // when their data is not displayed. + virtual void Enable(); + virtual void Disable(); + + // Description: + // This will start up the X event loop and never return. If you + // call this method it will loop processing X events until the + // application is exited. + virtual void Start(); + virtual void UpdateSize(int,int); + + // Description: + // Specify the Xt widget to use for interaction. This method is + // one of a couple steps that are required for setting up a + // vtkRenderWindowInteractor as a widget inside of another user + // interface. You do not need to use this method if the render window + // will be a stand-alone window. This is only used when you want the + // render window to be a subwindow within a larger user interface. + // In that case, you must tell the render window what X display id + // to use, and then ask the render window what depth, visual and + // colormap it wants. Then, you must create an Xt TopLevelShell with + // those settings. Then you can create the rest of your user interface + // as a child of the TopLevelShell you created. Eventually, you will + // create a drawing area or some other widget to serve as the rendering + // window. You must use the SetWidget method to tell this Interactor + // about that widget. It's X and it's not terribly easy, but it looks cool. + virtual void SetWidget(Widget); + Widget GetWidget() + {return this->top;} + + // Description + // This method will store the top level shell widget for the interactor. + // This method and the method invocation sequence applies for: + // * vtkRenderWindow-Interactor pair in a nested widget hierarchy + // * multiple vtkRenderWindow-Interactor pairs in the same top + // level shell + // + // It is not needed for: + // * vtkRenderWindow-Interactor pair as the direct child of a + // top level shell, + // * multiple vtkRenderWindow-Interactor pairs, each in its own + // top level shell. + // + // This method, along with EnterNotify event, changes the keyboard focus + // among the widgets/vtkRenderWindow(s) so the Interactor(s) can receive + // the proper keyboard events. The following calls need to be made: + // * vtkRenderWindow's display ID need to be set to the top level + // shell's display ID. + // * vtkXRenderWindowInteractor's Widget has to be set to the + // vtkRenderWindow's container widget. + // * vtkXRenderWindowInteractor's TopLevel has to be set to the + // top level shell widget. + // + // Note that the procedure for setting up render window in a widget needs + // to be followed. See vtkRenderWindowInteractor's SetWidget() method. + // + // If multiple vtkRenderWindow-Interactor pairs in SEPARATE windows are + // desired, do not set the display ID (Interactor will create them as + // needed. Alternatively, create and set distinct DisplayID for each + // vtkRenderWindow. Using the same display ID without setting the parent + // widgets will cause the display to be reinitialized every time an + // interactor is initialized), do not set the widgets (so the render + // windows would be in their own windows), and do not set TopLevelShell + // (each has its own top level shell already) + virtual void SetTopLevelShell(Widget); + Widget GetTopLevelShell() + {return this->TopLevelShell;} + + // Description: + // X timer methods. + int CreateTimer(int timertype); + int DestroyTimer(void); + + // Description: + // X Tcl specific application terminate. + void TerminateApp(void); + + // Description: + // Set this flag to break the event loop. + vtkGetMacro(BreakLoopFlag, int); + vtkSetMacro(BreakLoopFlag, int); + + // Description: + // Functions that are used internally. + friend void vtkXRenderWindowTclInteractorCallback(Widget,XtPointer, + XEvent *,Boolean *); + friend void vtkXRenderWindowTclInteractorTimer(XtPointer,XtIntervalId *); + +protected: + vtkXRenderWindowTclInteractor(); + ~vtkXRenderWindowTclInteractor(); + + Widget TopLevelShell; + + Display *DisplayId; + Window WindowId; + Atom KillAtom; + Widget top; + Widget oldTop; + XtAppContext App; + int PositionBeforeStereo[2]; + + int BreakLoopFlag; +private: + vtkXRenderWindowTclInteractor(const vtkXRenderWindowTclInteractor&); // Not implemented. + void operator=(const vtkXRenderWindowTclInteractor&); // Not implemented. +}; + +#endif diff --git a/Rendering/vtkgluPickMatrix.h b/Rendering/vtkgluPickMatrix.h new file mode 100644 index 0000000..9cf2242 --- /dev/null +++ b/Rendering/vtkgluPickMatrix.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkgluPickMatrix.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkgluPickMatrix - implement selected glu functionality +// .SECTION Description +// This file implements selected glu functionality to avoid +// system dependencies on glu. + +#ifndef vtkgluPickMatrix_h +#define vtkgluPickMatrix_h + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" // Needed for GLfloat and GLdouble. +#endif + +// This function was copied from Mesa and sets up the pick matrix +inline void vtkgluPickMatrix( GLdouble x, GLdouble y, + GLdouble width, GLdouble height, + int *origin, int *size ) +{ + GLfloat m[16]; + GLfloat sx, sy; + GLfloat tx, ty; + + sx = size[0] / width; + sy = size[1] / height; + tx = (size[0] + 2.0 * (origin[0] - x)) / width; + ty = (size[1] + 2.0 * (origin[1] - y)) / height; + +#define M(row,col) m[col*4+row] + M(0,0) = sx; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = tx; + M(1,0) = 0.0; M(1,1) = sy; M(1,2) = 0.0; M(1,3) = ty; + M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = 1.0; M(2,3) = 0.0; + M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0; +#undef M + + glMultMatrixf( m ); +} + +#endif diff --git a/SETUP b/SETUP new file mode 100644 index 0000000..b7c8db2 --- /dev/null +++ b/SETUP @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +if [ -z "$1" ] +then + printf "Usage: setup.sh install_directory [dependencies].\n" 1>&2 + exit 1 +fi + +cd $(dirname $0) +libname=$(basename $(pwd)) +mkdir -p build +cd build +cmake ../ -Wno-dev -DBUILD_TESTING=0 -DCMAKE_INSTALL_PREFIX="$1" +make -j8 +make install -k + +# Moving directories +mv "$1/include/vtk-5.0" "$1/temp" +rmdir "$1/include" +mv "$1/temp" "$1/include" diff --git a/Testing.txt b/Testing.txt new file mode 100644 index 0000000..bf9fd95 --- /dev/null +++ b/Testing.txt @@ -0,0 +1,135 @@ +How to run and create tests.... + +In creating tests there are a few goals to strive for. + +1) Increase coverage of the code to help detect defects + +2) Don't mess up the tester's directories. If a test wants to write out a + file, first make sure the directory is writable, and if it is, then write + out the files, and then delete them. So that the directory is left in its + original state. + +3) Don't require excessive disk space or CPU time. Most tests that run on a + 512 cubed volume will work just as well on a 64 cubed volume. The 64 cubed + volume will require less disk space for the data, less CPU time to + process, and much less CPU time to purify. The same applies to valid + images. Typically there isn't any need for a 600 by 600 pixel valid + image. A 300 by 300 image will work fine and require less storage and less + CPU time to compute the image difference. + +4) Try to use existing data files. If you can create a test using a data file + that is already present, use that data file. Don't add a new data file + unless it is critical to test the functionality you want tested. If you do + need to add a new data file consider its size. If it is a large data file + can you produce a lower resolution version of it and check that in instead? + +The current status is that the new tree has about 100 tests and is achieving +about 43 percent coverage. These tests require about three minutes to run on +a 1 GHz Pentium and currently require about ten megabytes of disk space for +the data files and valid images. + + +How to run a test +-------------------------- + +The easiest way to run a test is using ctest which is included with +cmake. You must make sure your build of VTK was done with BUILD_TESTS set to +on when running cmake. Once your build is complete you can run tests in a few +different ways. For example; you can cd to the top of your binary tree and +run ctest. This will run every test in VTk and show you the results. If you +only want to run specific tests you can use ctest -R and provide a +regular expression or ctest -I start,end,stride,extra ... Run ctest --help to +see a more complete listing of options. + +How to create a new test +--------------------------- + +The easiest approach is to look at an existing test and use that as a +starting point. The tests are kept in Testing sub-directories under each main +package. (e.g. VTK/Graphics/Testing) In Testing there will be sub-directories +for each type of test (Cxx Tcl Python Java). For C++ tests you need to write +the test and then add it to the CMakeLists.txt file in Testing/Cxx. For +Tclexamples you would write a Tcl script, and then add it to the +CMakeLists.txt file in Testing/Tcl. Just follow the examples already in the +tree. Most tests take a few common arguments: + + -D /path/to/VTKData + -V relative/path/to/valid/image + +Tcl scripts also accept: + + -A /path/to/vtktcl/package + +Typically these arguments are optional and the test will try to run without +them. If the -V option is provided the test will try to perform image +differences between the valid image and the rendered image. If the valid +image specified with -V doesn't exist it will create it. + + +Running a Tcl example +----------------------- + +The most common way to run a Tcl example is to first set TCLLIBPATH to +/path/to/VTK/Wrapping/Tcl so that the examples can find the vtktcl +package. On UNIX you can do: + +setenv TCLLIBPATH /home/you/VTK/Wrapping/Tcl + +or on windows set TCLLIBPATH to c:/your/VTK/Wrapping/Tcl note that UNIX style +slashes are used on windows as well. Once TCLLIBPATH is set you can run the +example as + +cd VTK/Graphics/Testing/Tcl +/path/to/VTK/bin/vtk yourScript.tcl + +It will look for VTKData to be at the same level as VTK on your disk. If it +isn't you will need to provide the -D argument. + +/path/to/VTK/bin/vtk yourScript.tcl -D /path/to/VTKData + +to run the example as a regression test you should make the example the first +argument to VTK/Common/Testing/Tcl/rtImageTest.tcl. For example + +/path/to/VTK/bin/vtk /path/to/VTK/Common/Testing/Tcl/rtImageTest.tcl yourScript.tcl -D /path/to/VTKData -V Baseline/Graphics/yourScript.png + +That is a long command line but normally Dart will take care of it for you. + + +VTK-Python tests +------------------ + +Writing and running VTK-Python tests is documented in +Wrapping/Python/README.txt. There are two types of Python tests, the +old tests and the newer tests that use unit testing approach +(unittest). The newer tests can be run with a -h or --help argument. +This provides information on the available command line options. The +other options for the newer tests are slightly different from the Tcl +test scripts. Please read Wrapping/Python/README.txt for more details +on the newer tests. The older tests should have the same command line +options that the Tcl scripts have. Test writers are encouraged to use +the new approach (unittest) for the tests. + + +Producing a dashboard +------------------------- + +If you want to test your build of VTK you can produce a dashboard. To do this +you will need to have cmake installed on your system (which you need anyhow +to build VTK). Then when you run CMake, make sure BUILD_TESTING is on. Then +you can do + +make Experimental + +on UNIX to perform a build, run the tests, and submit the result to the +dashboard. If you just want to run the tests you can do + +make ExperimentalTest + +on windows there are targets in the workspace for Experiemental and +ExperimentalTest + + + + + + diff --git a/TestingLogo.gif b/TestingLogo.gif new file mode 100644 index 0000000..b57eb7c Binary files /dev/null and b/TestingLogo.gif differ diff --git a/UseVTK.cmake.in b/UseVTK.cmake.in new file mode 100644 index 0000000..313c5fa --- /dev/null +++ b/UseVTK.cmake.in @@ -0,0 +1,38 @@ +# +# This module is provided as VTK_USE_FILE by VTKConfig.cmake. It can +# be INCLUDEd in a project to load the needed compiler and linker +# settings to use VTK. +# + +IF(NOT VTK_USE_FILE_INCLUDED) + SET(VTK_USE_FILE_INCLUDED 1) + + # Load the compiler settings used for VTK. + IF(VTK_BUILD_SETTINGS_FILE) + INCLUDE(${CMAKE_ROOT}/Modules/CMakeImportBuildSettings.cmake) + CMAKE_IMPORT_BUILD_SETTINGS(${VTK_BUILD_SETTINGS_FILE}) + ENDIF(VTK_BUILD_SETTINGS_FILE) + + # Add compiler flags needed to use VTK. + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${VTK_REQUIRED_C_FLAGS}") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VTK_REQUIRED_CXX_FLAGS}") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${VTK_REQUIRED_EXE_LINKER_FLAGS}") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${VTK_REQUIRED_SHARED_LINKER_FLAGS}") + SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${VTK_REQUIRED_MODULE_LINKER_FLAGS}") + + # Add include directories needed to use VTK. + INCLUDE_DIRECTORIES(${VTK_INCLUDE_DIRS}) + + # Add link directories needed to use VTK. + LINK_DIRECTORIES(${VTK_LIBRARY_DIRS}) + + # Import the VTK_LOAD_CMAKE_EXTENSIONS macro. + INCLUDE(${VTK_LOAD_CMAKE_EXTENSIONS_MACRO}) + INCLUDE(${VTK_CMAKE_DIR}/vtkMakeInstantiator.cmake) + + # Load VTK's CMake extension commands. + IF(NOT VTK_NO_LOAD_CMAKE_EXTENSIONS) + VTK_LOAD_CMAKE_EXTENSIONS(${VTK_CMAKE_EXTENSIONS_DIR}) + ENDIF(NOT VTK_NO_LOAD_CMAKE_EXTENSIONS) + +ENDIF(NOT VTK_USE_FILE_INCLUDED) diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt new file mode 100644 index 0000000..9bd891f --- /dev/null +++ b/Utilities/CMakeLists.txt @@ -0,0 +1,72 @@ +# Build kwsys +SUBDIRS(kwsys) + +# Build third-party utilities. + +VTK_THIRD_PARTY_SUBDIR(ZLIB vtkzlib) +VTK_THIRD_PARTY_SUBDIR(JPEG vtkjpeg) +VTK_THIRD_PARTY_SUBDIR(PNG vtkpng) +VTK_THIRD_PARTY_SUBDIR(TIFF vtktiff) +VTK_THIRD_PARTY_SUBDIR(EXPAT vtkexpat) +VTK_THIRD_PARTY_SUBDIR(FREETYPE vtkfreetype) +VTK_THIRD_PARTY_SUBDIR(DICOMParser DICOMParser) + +IF(VTK_HAS_EXODUS) + SUBDIRS(vtknetcdf) + SUBDIRS(vtkexodus2) +ENDIF(VTK_HAS_EXODUS) + +SUBDIRS(Doxygen) +IF(VTK_INCLUDE_NEED_TCL) + SUBDIRS(TclTk) +ENDIF(VTK_INCLUDE_NEED_TCL) + +IF(VTK_USE_RENDERING) + SUBDIRS(ftgl ParseOGLExt) +ENDIF(VTK_USE_RENDERING) + +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} .h + vtk_expat vtk_jpeg vtk_png vtk_zlib vtk_tiff vtk_freetype) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +#----------------------------------------------------------------------------- +# Check for stdarg problem on SGI. +IF(NOT CMAKE_COMPILER_IS_GNUCXX) + IF(CMAKE_SYSTEM MATCHES "IRIX.*") + IF("VTK_COMPILER_NO_SGI_STDARG_WORKAROUND" MATCHES "^VTK_COMPILER_NO_SGI_STDARG_WORKAROUND$") + MESSAGE(STATUS "Checking whether SGI MIPSpro 7.4 stdarg work-around is needed") + TRY_COMPILE(VTK_COMPILER_NO_SGI_STDARG_WORKAROUND + ${VTK_BINARY_DIR}/CMakeTmp + ${VTK_SOURCE_DIR}/CMake/vtkTestSGIstdarg.cxx + OUTPUT_VARIABLE OUTPUT) + IF(VTK_COMPILER_NO_SGI_STDARG_WORKAROUND) + MESSAGE(STATUS "Checking whether SGI MIPSpro 7.4 stdarg work-around is needed -- no") + SET(VTK_COMPILER_NO_SGI_STDARG_WORKAROUND 1 CACHE INTERNAL "Whether SGI MIPSpro 7.4 stdarg work-around is needed") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Determining whether SGI MIPSpro does not have stdarg problems " + "passed with the following output:\n" + "${OUTPUT}\n" APPEND) + ELSE(VTK_COMPILER_NO_SGI_STDARG_WORKAROUND) + MESSAGE(STATUS "Checking whether SGI MIPSpro 7.4 stdarg work-around is needed -- yes") + SET(VTK_COMPILER_NO_SGI_STDARG_WORKAROUND 0 CACHE INTERNAL "Whether SGI MIPSpro 7.4 stdarg work-around is needed") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Determining whether SGI MIPSpro does not have stdarg problems " + "failed with the following output:\n" + "${OUTPUT}\n" APPEND) + ENDIF(VTK_COMPILER_NO_SGI_STDARG_WORKAROUND) + ENDIF("VTK_COMPILER_NO_SGI_STDARG_WORKAROUND" MATCHES "^VTK_COMPILER_NO_SGI_STDARG_WORKAROUND$") + ENDIF(CMAKE_SYSTEM MATCHES "IRIX.*") +ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX) +IF(NOT VTK_COMPILER_NO_SGI_STDARG_WORKAROUND) + # See internal_stdio_core.h.in for explanation. + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/internal_stdio_core.h.in + ${CMAKE_CURRENT_BINARY_DIR}/internal/stdio_core.h + @ONLY IMMEDIATE) + + # Install the work-around header. + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/internal FILES + ${CMAKE_CURRENT_BINARY_DIR}/internal/stdio_core.h) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF(NOT VTK_COMPILER_NO_SGI_STDARG_WORKAROUND) diff --git a/Utilities/DICOMParser/CMakeLists.txt b/Utilities/DICOMParser/CMakeLists.txt new file mode 100644 index 0000000..ec0e3e1 --- /dev/null +++ b/Utilities/DICOMParser/CMakeLists.txt @@ -0,0 +1,42 @@ +PROJECT(DICOMParser) + +INCLUDE_DIRECTORIES(${DICOMParser_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${DICOMParser_BINARY_DIR}) + +IF(WIN32) + IF(BUILD_SHARED_LIBS) + SET(DICOM_DLL 1) + ELSE(BUILD_SHARED_LIBS) + SET(DICOM_STATIC 1) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(WIN32) + +IF(VTK_SOURCE_DIR) + # Inside VTK, use its setting. + SET(DICOM_ANSI_STDLIB ${VTK_USE_ANSI_STDLIB}) +ELSE(VTK_SOURCE_DIR) + # Not inside VTK, use ANSI streams. + SET(DICOM_ANSI_STDLIB 1) +ENDIF(VTK_SOURCE_DIR) + +INCLUDE(${CMAKE_ROOT}/Modules/TestForSTDNamespace.cmake) +SET(DICOM_NO_STD_NAMESPACE ${CMAKE_NO_STD_NAMESPACE}) + + +CONFIGURE_FILE(${DICOMParser_SOURCE_DIR}/DICOMCMakeConfig.h.in + ${DICOMParser_BINARY_DIR}/DICOMCMakeConfig.h) + +ADD_LIBRARY(vtkDICOMParser DICOMFile.cxx DICOMParser.cxx DICOMAppHelper.cxx) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkDICOMParser PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkDICOMParser) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} "(\\.h|\\.txx)$") + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR} FILES ${DICOMParser_BINARY_DIR}/DICOMCMakeConfig.h) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/DICOMParser/Copyright.txt b/Utilities/DICOMParser/Copyright.txt new file mode 100644 index 0000000..d9acc52 --- /dev/null +++ b/Utilities/DICOMParser/Copyright.txt @@ -0,0 +1,41 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: Copyright.txt,v $ + Language: C++ + Date: $Date: 2003/10/22 14:30:34 $ + Version: $Revision: 1.2 $ + + +Copyright (c) 2003 Matt Turek +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * The name of Matt Turek nor the names of any contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + + * Modified source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=========================================================================*/ diff --git a/Utilities/DICOMParser/DICOMAppHelper.cxx b/Utilities/DICOMParser/DICOMAppHelper.cxx new file mode 100644 index 0000000..468e5d0 --- /dev/null +++ b/Utilities/DICOMParser/DICOMAppHelper.cxx @@ -0,0 +1,1388 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMAppHelper.cxx,v $ + Language: C++ + Date: $Date: 2006/08/31 17:30:29 $ + Version: $Revision: 1.21.20.2 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4503 ) +#pragma warning ( disable : 4710 ) +#pragma warning ( disable : 4702 ) +#pragma warning ( push, 3 ) +#endif + +#include "DICOMConfig.h" +#include "DICOMAppHelper.h" +#include "DICOMCallback.h" + +#include +#include +#include +#include +#include +#if defined(__BORLANDC__) +#include // for memcpy +#endif + +//#define DEBUG_DICOM_APP_HELPER + +class DICOMAppHelperImplementation +{ +public: + // map from series UID to vector of files in the series + dicom_stl::map, ltstdstr> SeriesUIDMap; + + // map from filename to intraseries sortable tags + dicom_stl::map SliceOrderingMap; + + typedef dicom_stl::map, DICOMTagInfo> TagMapType; + TagMapType TagMap; + +}; + +struct lt_pair_int_string +{ + bool operator()(const dicom_stl::pair s1, + const dicom_stl::pair s2) const + { + return s1.first < s2.first; + } +}; + + +struct lt_pair_float_string +{ + bool operator()(const dicom_stl::pair s1, + const dicom_stl::pair s2) const + { + return s1.first < s2.first; + } +}; + + +struct gt_pair_int_string +{ + bool operator()(const dicom_stl::pair s1, + const dicom_stl::pair s2) const + { + return s1.first > s2.first; + } +}; + + +struct gt_pair_float_string +{ + bool operator()(const dicom_stl::pair s1, + const dicom_stl::pair s2) const + { + return s1.first > s2.first; + } +}; + + +DICOMAppHelper::DICOMAppHelper() +{ + this->BitsAllocated = 8; + this->ByteSwapData = false; + this->PixelSpacing[0] = this->PixelSpacing[1] = this->PixelSpacing[2] = 1.0; + this->Dimensions[0] = this->Dimensions[1] = 0; + this->PhotometricInterpretation = new dicom_stl::string(); + this->TransferSyntaxUID = new dicom_stl::string(); + this->RescaleOffset = 0.0; + this->RescaleSlope = 1.0; + this->ImageData = NULL; + this->ImageDataLengthInBytes = 0; + this->PatientName = new dicom_stl::string(); + this->StudyUID = new dicom_stl::string(); + this->StudyID = new dicom_stl::string(); + this->GantryAngle = 0.0; + this->Width = 0; + this->Height = 0; + this->PixelRepresentation = 0; + + this->SeriesUIDCB = new DICOMMemberCallback; + this->SliceNumberCB = new DICOMMemberCallback; + this->SliceLocationCB = new DICOMMemberCallback; + this->ImagePositionPatientCB = new DICOMMemberCallback; + this->ImageOrientationPatientCB = new DICOMMemberCallback; + this->TransferSyntaxCB = new DICOMMemberCallback; + this->ToggleSwapBytesCB = new DICOMMemberCallback; + this->BitsAllocatedCB = new DICOMMemberCallback; + this->PixelSpacingCB = new DICOMMemberCallback; + this->HeightCB = new DICOMMemberCallback; + this->WidthCB = new DICOMMemberCallback; + this->PixelRepresentationCB = new DICOMMemberCallback; + this->PhotometricInterpretationCB = new DICOMMemberCallback; + this->RescaleOffsetCB = new DICOMMemberCallback; + this->RescaleSlopeCB = new DICOMMemberCallback; + this->PixelDataCB = new DICOMMemberCallback; + this->PatientNameCB = new DICOMMemberCallback; + this->StudyUIDCB = new DICOMMemberCallback; + this->StudyIDCB = new DICOMMemberCallback; + this->GantryAngleCB = new DICOMMemberCallback; + + this->Implementation = new DICOMAppHelperImplementation; +} + +DICOMAppHelper::~DICOMAppHelper() +{ + this->Clear(); + + this->HeaderFile.close(); + + // + // Fix warning here. + // + if (this->ImageData) + { + delete [] (static_cast (this->ImageData)); + } + if (this->TransferSyntaxUID) + { + delete this->TransferSyntaxUID; + } + if (this->PhotometricInterpretation) + { + delete this->PhotometricInterpretation; + } + + if (this->PatientName) + { + delete this->PatientName; + } + + if (this->StudyUID) + { + delete this->StudyUID; + } + + if (this->StudyID) + { + delete this->StudyID; + } + + delete this->SeriesUIDCB; + delete this->SliceNumberCB; + delete this->SliceLocationCB; + delete this->ImagePositionPatientCB; + delete this->ImageOrientationPatientCB; + delete this->TransferSyntaxCB; + delete this->ToggleSwapBytesCB; + delete this->BitsAllocatedCB; + delete this->PixelSpacingCB; + delete this->HeightCB; + delete this->WidthCB; + delete this->PixelRepresentationCB; + delete this->PhotometricInterpretationCB; + delete this->RescaleOffsetCB; + delete this->RescaleSlopeCB; + delete this->PixelDataCB; + delete this->PatientNameCB; + delete this->StudyUIDCB; + delete this->StudyIDCB; + delete this->GantryAngleCB; + + delete this->Implementation; +} + +void DICOMAppHelper::RegisterCallbacks(DICOMParser* parser) +{ + if (!parser) + { + dicom_stream::cerr << "Null parser!" << dicom_stream::endl; + } + + SeriesUIDCB->SetCallbackFunction(this, &DICOMAppHelper::SeriesUIDCallback); + parser->AddDICOMTagCallback(0x0020, 0x000e, DICOMParser::VR_UI, SeriesUIDCB); + + SliceNumberCB->SetCallbackFunction(this, &DICOMAppHelper::SliceNumberCallback); + parser->AddDICOMTagCallback(0x0020, 0x0013, DICOMParser::VR_IS, SliceNumberCB); + + SliceLocationCB->SetCallbackFunction(this, &DICOMAppHelper::SliceLocationCallback); + parser->AddDICOMTagCallback(0x0020, 0x1041, DICOMParser::VR_CS, SliceLocationCB); + + ImagePositionPatientCB->SetCallbackFunction(this, &DICOMAppHelper::ImagePositionPatientCallback); + parser->AddDICOMTagCallback(0x0020, 0x0032, DICOMParser::VR_SH, ImagePositionPatientCB); + + ImageOrientationPatientCB->SetCallbackFunction(this, &DICOMAppHelper::ImageOrientationPatientCallback); + parser->AddDICOMTagCallback(0x0020, 0x0037, DICOMParser::VR_SH, ImageOrientationPatientCB); + + TransferSyntaxCB->SetCallbackFunction(this, &DICOMAppHelper::TransferSyntaxCallback); + parser->AddDICOMTagCallback(0x0002, 0x0010, DICOMParser::VR_UI, TransferSyntaxCB); + + ToggleSwapBytesCB->SetCallbackFunction(this, &DICOMAppHelper::ToggleSwapBytesCallback); + + BitsAllocatedCB->SetCallbackFunction(this, &DICOMAppHelper::BitsAllocatedCallback); + parser->AddDICOMTagCallback(0x0028, 0x0100, DICOMParser::VR_US, BitsAllocatedCB); + + PixelSpacingCB->SetCallbackFunction(this, &DICOMAppHelper::PixelSpacingCallback); + parser->AddDICOMTagCallback(0x0028, 0x0030, DICOMParser::VR_FL, PixelSpacingCB); + parser->AddDICOMTagCallback(0x0018, 0x0050, DICOMParser::VR_FL, PixelSpacingCB); + + WidthCB->SetCallbackFunction(this, &DICOMAppHelper::WidthCallback); + parser->AddDICOMTagCallback(0x0028, 0x0011, DICOMParser::VR_US, WidthCB); + + HeightCB->SetCallbackFunction(this, &DICOMAppHelper::HeightCallback); + parser->AddDICOMTagCallback(0x0028, 0x0010, DICOMParser::VR_US, HeightCB); + + PixelRepresentationCB->SetCallbackFunction(this, &DICOMAppHelper::PixelRepresentationCallback); + parser->AddDICOMTagCallback(0x0028, 0x0103, DICOMParser::VR_US, PixelRepresentationCB); + + PhotometricInterpretationCB->SetCallbackFunction(this, &DICOMAppHelper::PhotometricInterpretationCallback); + parser->AddDICOMTagCallback(0x0028, 0x0004, DICOMParser::VR_CS, PhotometricInterpretationCB); + + RescaleOffsetCB->SetCallbackFunction(this, &DICOMAppHelper::RescaleOffsetCallback); + parser->AddDICOMTagCallback(0x0028, 0x1052, DICOMParser::VR_CS, RescaleOffsetCB); + + RescaleSlopeCB->SetCallbackFunction(this, &DICOMAppHelper::RescaleSlopeCallback); + parser->AddDICOMTagCallback(0x0028, 0x1053, DICOMParser::VR_FL, RescaleSlopeCB); + + PatientNameCB->SetCallbackFunction(this, &DICOMAppHelper::PatientNameCallback); + parser->AddDICOMTagCallback(0x0010, 0x0010, DICOMParser::VR_PN, PatientNameCB); + + StudyUIDCB->SetCallbackFunction(this, &DICOMAppHelper::StudyUIDCallback); + parser->AddDICOMTagCallback(0x0020, 0x000d, DICOMParser::VR_UI, StudyUIDCB); + + StudyIDCB->SetCallbackFunction(this, &DICOMAppHelper::StudyIDCallback); + parser->AddDICOMTagCallback(0x0020, 0x0010, DICOMParser::VR_SH, StudyIDCB); + + GantryAngleCB->SetCallbackFunction(this, &DICOMAppHelper::GantryAngleCallback); + parser->AddDICOMTagCallback(0x0018, 0x1120, DICOMParser::VR_FL, GantryAngleCB); + + + DICOMTagInfo dicom_tags[] = { + {0x0002, 0x0002, DICOMParser::VR_UI, "Media storage SOP class uid"}, + {0x0002, 0x0003, DICOMParser::VR_UI, "Media storage SOP inst uid"}, + {0x0002, 0x0010, DICOMParser::VR_UI, "Transfer syntax uid"}, + {0x0002, 0x0012, DICOMParser::VR_UI, "Implementation class uid"}, + {0x0008, 0x0018, DICOMParser::VR_UI, "Image UID"}, + {0x0008, 0x0020, DICOMParser::VR_DA, "Series date"}, + {0x0008, 0x0030, DICOMParser::VR_TM, "Series time"}, + {0x0008, 0x0060, DICOMParser::VR_SH, "Modality"}, + {0x0008, 0x0070, DICOMParser::VR_SH, "Manufacturer"}, + {0x0008, 0x1060, DICOMParser::VR_SH, "Physician"}, + {0x0018, 0x0050, DICOMParser::VR_FL, "slice thickness"}, + {0x0018, 0x0060, DICOMParser::VR_FL, "kV"}, + {0x0018, 0x0088, DICOMParser::VR_FL, "slice spacing"}, + {0x0018, 0x1100, DICOMParser::VR_SH, "Recon diameter"}, + {0x0018, 0x1151, DICOMParser::VR_FL, "mA"}, + {0x0018, 0x1210, DICOMParser::VR_SH, "Recon kernel"}, + {0x0020, 0x000d, DICOMParser::VR_UI, "Study UID"}, + {0x0020, 0x000e, DICOMParser::VR_UI, "Series UID"}, + {0x0020, 0x0013, DICOMParser::VR_IS, "Image number"}, + {0x0020, 0x0032, DICOMParser::VR_SH, "Patient position"}, + {0x0020, 0x0037, DICOMParser::VR_SH, "Patient position cosines"}, + {0x0020, 0x1041, DICOMParser::VR_CS, "Slice location"}, + {0x0028, 0x0010, DICOMParser::VR_FL, "Num rows"}, + {0x0028, 0x0011, DICOMParser::VR_FL, "Num cols"}, + {0x0028, 0x0030, DICOMParser::VR_FL, "pixel spacing"}, + {0x0028, 0x0100, DICOMParser::VR_US, "Bits allocated"}, + {0x0028, 0x0120, DICOMParser::VR_UL, "pixel padding"}, + {0x0028, 0x1052, DICOMParser::VR_FL, "pixel offset"} + }; + + int num_tags = sizeof(dicom_tags)/sizeof(DICOMTagInfo); + +#ifdef DEBUG_DICOM_APP_HELPER + DICOMMemberCallback** callbackArray = new DICOMMemberCallback*[num_tags]; +#endif + + for (int j = 0; j < num_tags; j++) + { + // + // Setup internal map. + // + DICOMTagInfo tagStruct = dicom_tags[j]; + doublebyte group = tagStruct.group; + doublebyte element = tagStruct.element; + + dicom_stl::pair gePair(group, element); + dicom_stl::pair, DICOMTagInfo> mapPair(gePair, tagStruct); + this->Implementation->TagMap.insert(mapPair); + +#ifdef DEBUG_DICOM_APP_HELPER + // + // Make callback + // + callbackArray[j] = new DICOMMemberCallback; + callbackArray[j]->SetCallbackFunction(this, &DICOMAppHelper::ArrayCallback); + // + // Set callback on parser. + // + parser->AddDICOMTagCallback(group, element,datatype, callbackArray[j]); +#endif + + } + +} + +void DICOMAppHelper::SeriesUIDCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + char* newString = (char*) val; + dicom_stl::string newStdString(newString); + dicom_stl::map, ltstdstr>::iterator iter = this->Implementation->SeriesUIDMap.find(newStdString); + if ( iter == this->Implementation->SeriesUIDMap.end()) + { + dicom_stl::vector newVector; + + newVector.push_back(parser->GetFileName()); + this->Implementation->SeriesUIDMap.insert(dicom_stl::pair > (newStdString, newVector)); + } + else + { + (*iter).second.push_back(parser->GetFileName()); + } +} + +void DICOMAppHelper::OutputSeries() +{ + dicom_stream::cout << dicom_stream::endl << dicom_stream::endl; + + for (dicom_stl::map, ltstdstr >::iterator iter = this->Implementation->SeriesUIDMap.begin(); + iter != this->Implementation->SeriesUIDMap.end(); + iter++) + { + dicom_stream::cout << "SERIES: " << (*iter).first.c_str() << dicom_stream::endl; + dicom_stl::vector& v_ref = (*iter).second; + + for (dicom_stl::vector::iterator v_iter = v_ref.begin(); + v_iter != v_ref.end(); + v_iter++) + { + dicom_stl::map::iterator sn_iter = Implementation->SliceOrderingMap.find(*v_iter); + + int slice = -1; + if (sn_iter != Implementation->SliceOrderingMap.end()) + { + slice = (*sn_iter).second.SliceNumber; + } + dicom_stream::cout << "\t" << (*v_iter).c_str() << " [" << slice << "]" << dicom_stream::endl; + } + + } +} + + +void DICOMAppHelper::ArrayCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes datatype, + unsigned char* val, + quadbyte len) +{ + const char* desc = "No description"; + + TagMapType::iterator iter = this->Implementation->TagMap.find(dicom_stl::pair (group, element)); + if (iter != this->Implementation->TagMap.end()) + { + desc = (*iter).second.description; + } + + int t2 = int((0x0000FF00 & datatype) >> 8); + int t1 = int((0x000000FF & datatype)); + + char ct2(t2); + char ct1(t1); + + + HeaderFile << "(0x"; + + HeaderFile.width(4); + char prev = HeaderFile.fill('0'); + + HeaderFile << dicom_stream::hex << group; + HeaderFile << ",0x"; + + HeaderFile.width(4); + HeaderFile.fill('0'); + + HeaderFile << dicom_stream::hex << element; + HeaderFile << ") "; + + HeaderFile.fill(prev); + HeaderFile << dicom_stream::dec; + HeaderFile << " " << ct1 << ct2 << " "; + HeaderFile << "[" << len << " bytes] "; + + HeaderFile << desc << " : "; + + unsigned int uival = 0; + float fval = 0; + double dval = 0; + int ival = 0; + + if (val) + { + switch (datatype) + { + case DICOMParser::VR_AE: + case DICOMParser::VR_AS: + case DICOMParser::VR_CS: + case DICOMParser::VR_UI: + case DICOMParser::VR_DA: + case DICOMParser::VR_DS: + case DICOMParser::VR_DT: + case DICOMParser::VR_LO: + case DICOMParser::VR_LT: + case DICOMParser::VR_OB: // ordered bytes + case DICOMParser::VR_OW: // ordered words + case DICOMParser::VR_PN: + case DICOMParser::VR_ST: + case DICOMParser::VR_TM: + case DICOMParser::VR_UN: + case DICOMParser::VR_UT: + case DICOMParser::VR_SQ: // sequence + case DICOMParser::VR_SH: // strings + case DICOMParser::VR_IS: + HeaderFile << val; + break; + case DICOMParser::VR_FL: // float + fval = static_cast (atof((char*) val)); + HeaderFile << fval; + break; + case DICOMParser::VR_FD: // float double + fval = static_cast (atof((char*) val)); + HeaderFile << dval; + break; + case DICOMParser::VR_UL: // unsigned long + case DICOMParser::VR_SL: // signed long + case DICOMParser::VR_AT: + HeaderFile << uival; + break; + //case DICOMParser::VR_IS: + // ival = DICOMFile::ReturnAsSignedLong(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); + // HeaderFile << ival; + // break; + case DICOMParser::VR_SS: + ival = DICOMFile::ReturnAsSignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); + HeaderFile << ival; + break; + case DICOMParser::VR_US: // unsigned short + uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); + HeaderFile << uival; + break; + default: + HeaderFile << val << dicom_stream::endl; + break; + } + } + else + { + HeaderFile << "NULL"; + } + + HeaderFile << dicom_stream::dec << dicom_stream::endl; + HeaderFile.fill(prev); + + delete [] val; +} + +void DICOMAppHelper::SliceNumberCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + // Look for the current file in the map of slice ordering data + dicom_stl::map::iterator it; + it = this->Implementation->SliceOrderingMap.find(parser->GetFileName()); + if (it == Implementation->SliceOrderingMap.end()) + { + // file not found, create a new entry + DICOMOrderingElements ord; + ord.SliceNumber = atoi( (char *) val); + + // insert into the map + this->Implementation->SliceOrderingMap.insert(dicom_stl::pair(parser->GetFileName(), ord)); + } + else + { + // file found, add new values + (*it).second.SliceNumber = atoi( (char *)val ); + } + + // cache the slice number + this->SliceNumber = atoi( (char *) val); +} + + +void DICOMAppHelper::SliceLocationCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + // Look for the current file in the map of slice ordering data + dicom_stl::map::iterator it; + it = this->Implementation->SliceOrderingMap.find(parser->GetFileName()); + if (it == Implementation->SliceOrderingMap.end()) + { + // file not found, create a new entry + DICOMOrderingElements ord; + ord.SliceLocation = (float)atof( (char *) val); + + // insert into the map + this->Implementation->SliceOrderingMap.insert(dicom_stl::pair(parser->GetFileName(), ord)); + } + else + { + // file found, add new values + (*it).second.SliceLocation = (float)atof( (char *)val ); + } +} + +void DICOMAppHelper::ImagePositionPatientCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + // Look for the current file in the map of slice ordering data + dicom_stl::map::iterator it; + it = this->Implementation->SliceOrderingMap.find(parser->GetFileName()); + if (it == Implementation->SliceOrderingMap.end()) + { + // file not found, create a new entry + DICOMOrderingElements ord; + + if (val) + { + sscanf( (char*)(val), "%f\\%f\\%f", + &ord.ImagePositionPatient[0], + &ord.ImagePositionPatient[1], + &ord.ImagePositionPatient[2] ); + } + else + { + // no actual position specified, default to the origin + ord.ImagePositionPatient[0] = 0.0; + ord.ImagePositionPatient[1] = 0.0; + ord.ImagePositionPatient[2] = 0.0; + } + + // insert into the map + this->Implementation->SliceOrderingMap.insert(dicom_stl::pair(parser->GetFileName(), ord)); + + // cache the value + memcpy( this->ImagePositionPatient, ord.ImagePositionPatient, + 3*sizeof(float) ); + } + else + { + if (val) + { + // file found, add new values + sscanf( (char*)(val), "%f\\%f\\%f", + &(*it).second.ImagePositionPatient[0], + &(*it).second.ImagePositionPatient[1], + &(*it).second.ImagePositionPatient[2] ); + } + else + { + // no actual position specified, default to the origin + (*it).second.ImagePositionPatient[0] = 0.0; + (*it).second.ImagePositionPatient[1] = 0.0; + (*it).second.ImagePositionPatient[2] = 0.0; + } + + // cache the value + memcpy( this->ImagePositionPatient, (*it).second.ImagePositionPatient, + 3*sizeof(float) ); + } +} + + +void DICOMAppHelper::ImageOrientationPatientCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + // Look for the current file in the map of slice ordering data + dicom_stl::map::iterator it; + it = this->Implementation->SliceOrderingMap.find(parser->GetFileName()); + if (it == Implementation->SliceOrderingMap.end()) + { + // file not found, create a new entry + DICOMOrderingElements ord; + if (val) + { + sscanf( (char*)(val), "%f\\%f\\%f\\%f\\%f\\%f", + &ord.ImageOrientationPatient[0], + &ord.ImageOrientationPatient[1], + &ord.ImageOrientationPatient[2], + &ord.ImageOrientationPatient[3], + &ord.ImageOrientationPatient[4], + &ord.ImageOrientationPatient[5] ); + } + else + { + // no orientation defined, default to an standard axial orientation + ord.ImageOrientationPatient[0] = 1.0; + ord.ImageOrientationPatient[1] = 0.0; + ord.ImageOrientationPatient[2] = 0.0; + ord.ImageOrientationPatient[3] = 0.0; + ord.ImageOrientationPatient[4] = 1.0; + ord.ImageOrientationPatient[5] = 0.0; + } + + // insert into the map + this->Implementation->SliceOrderingMap.insert(dicom_stl::pair(parser->GetFileName(), ord)); + + // cache the value + memcpy( this->ImageOrientationPatient, ord.ImageOrientationPatient, + 6*sizeof(float) ); + } + else + { + // file found, add new values + if (val) + { + sscanf( (char*)(val), "%f\\%f\\%f\\%f\\%f\\%f", + &(*it).second.ImageOrientationPatient[0], + &(*it).second.ImageOrientationPatient[1], + &(*it).second.ImageOrientationPatient[2], + &(*it).second.ImageOrientationPatient[3], + &(*it).second.ImageOrientationPatient[4], + &(*it).second.ImageOrientationPatient[5] ); + } + else + { + // no orientation defined, default to an standard axial orientation + (*it).second.ImageOrientationPatient[0] = 1.0; + (*it).second.ImageOrientationPatient[1] = 0.0; + (*it).second.ImageOrientationPatient[2] = 0.0; + (*it).second.ImageOrientationPatient[3] = 0.0; + (*it).second.ImageOrientationPatient[4] = 1.0; + (*it).second.ImageOrientationPatient[5] = 0.0; + } + + // cache the value + memcpy( this->ImageOrientationPatient, (*it).second.ImageOrientationPatient, + 6*sizeof(float) ); + } +} + + +void DICOMAppHelper::TransferSyntaxCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + +#ifdef DEBUG_DICOM_APP_HELPER +#ifdef WIN32 + char platformByteOrder = 'L'; +#else + char platformByteOrder = 'B'; +#endif + dicom_stream::cout << "Platform byte order: " << platformByteOrder << dicom_stream::endl; +#endif + + static const char* TRANSFER_UID_EXPLICIT_BIG_ENDIAN = "1.2.840.10008.1.2.2"; + + // Only add the ToggleSwapBytes callback when we need it. + if (strcmp(TRANSFER_UID_EXPLICIT_BIG_ENDIAN, (char*) val) == 0) + { + this->ByteSwapData = true; + parser->AddDICOMTagCallback(0x0800, 0x0000, DICOMParser::VR_UNKNOWN, ToggleSwapBytesCB); +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cerr <<"Registering callback for swapping bytes." << dicom_stream::endl; +#endif + } + + if (this->TransferSyntaxUID) + { + delete this->TransferSyntaxUID; + } + this->TransferSyntaxUID = new dicom_stl::string((char*) val); + +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Transfer Syntax UID: " << *this->TransferSyntaxUID; + dicom_stream::cout << " " << this->TransferSyntaxUIDDescription(this->TransferSyntaxUID->c_str()) << dicom_stream::endl; +#endif +} + +void DICOMAppHelper::BitsAllocatedCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + this->BitsAllocated = parser->GetDICOMFile()->ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Bits allocated: " << this->BitsAllocated << dicom_stream::endl; +#endif +} + + +void DICOMAppHelper::ToggleSwapBytesCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* , + quadbyte len) +{ +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "ToggleSwapBytesCallback" << dicom_stream::endl; +#endif + bool bs = parser->GetDICOMFile()->GetPlatformIsBigEndian(); + parser->GetDICOMFile()->SetPlatformIsBigEndian(!bs); + +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Set byte swap to: " << parser->GetDICOMFile()->GetPlatformIsBigEndian() << dicom_stream::endl; +#endif + + long pos = parser->GetDICOMFile()->Tell(); + + // + // The +4 is probably a hack, but it's a guess at the length of the previous field. + // + parser->GetDICOMFile()->SkipToPos(pos - len + 4); +} + + +void DICOMAppHelper::PixelSpacingCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + float fval = DICOMFile::ReturnAsFloat(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); + + if (group == 0x0028 && element == 0x0030) + { + this->PixelSpacing[0] = this->PixelSpacing[1] = fval; + } + else if (group == 0x0018 && element == 0x0050) + { + this->PixelSpacing[2] = fval; + } +} + +void DICOMAppHelper::WidthCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + unsigned short uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Width: " << uival << dicom_stream::endl; +#endif + + this->Width = uival; + this->Dimensions[0] = this->Width; +} + +void DICOMAppHelper::HeightCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + unsigned short uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Height: " << uival << dicom_stream::endl; +#endif + this->Height = uival; + this->Dimensions[1] = this->Height; +} + + +void DICOMAppHelper::PixelRepresentationCallback( DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + unsigned short uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Pixel Representation: " << (uival ? "Signed" : "Unsigned") << dicom_stream::endl; +#endif + this->PixelRepresentation = uival; +} + +void DICOMAppHelper::PhotometricInterpretationCallback( DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Photometric Interpretation: " << (char*) val << dicom_stream::endl; +#endif + if (this->PhotometricInterpretation) + { + delete this->PhotometricInterpretation; + } + + this->PhotometricInterpretation = new dicom_stl::string((char*) val); +} + +void DICOMAppHelper::PixelDataCallback( DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* data, + quadbyte len) +{ + int numPixels = this->Dimensions[0] * this->Dimensions[1] * this->GetNumberOfComponents(); + if (len < numPixels) + { + numPixels = len; + } + if (numPixels < 0) + { + numPixels = 0; + } + +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "numPixels : " << numPixels << dicom_stream::endl; +#endif + + int ptrIncr = int(this->BitsAllocated/8.0); + + unsigned short* ushortInputData = reinterpret_cast(data); + unsigned char* ucharInputData = data; + short* shortInputData = reinterpret_cast (data); + + float* floatOutputData; // = NULL; + + bool isFloat = this->RescaledImageDataIsFloat(); + + if (isFloat) + { +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Slope and offset are not integer valued : "; + dicom_stream::cout << this->RescaleSlope << ", " << this->RescaleOffset << dicom_stream::endl; +#endif + if (this->ImageData) + { + delete [] (static_cast (this->ImageData)); + } + this->ImageData = new float[numPixels]; + floatOutputData = static_cast (this->ImageData); + + this->ImageDataType = DICOMParser::VR_FL; + this->ImageDataLengthInBytes = numPixels * sizeof(float); + float newFloatPixel; + + if (ptrIncr == 1) + { + for (int i = 0; i < numPixels; i++) + { + newFloatPixel = float(this->RescaleSlope * ucharInputData[i] + this->RescaleOffset); + floatOutputData[i] = newFloatPixel; + } +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Did rescale, offset to float from char." << dicom_stream::endl; + dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl; +#endif + } + else if (ptrIncr == 2) + { + for (int i = 0; i < numPixels; i++) + { + newFloatPixel = float(this->RescaleSlope * ushortInputData[i] + this->RescaleOffset); + floatOutputData[i] = newFloatPixel; + } +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Did rescale, offset to float from short." << dicom_stream::endl; + dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl; +#endif + } + } + else + { +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Slope and offset are integer valued : "; + dicom_stream::cout << this->RescaleSlope << ", " << this->RescaleOffset << dicom_stream::endl; +#endif + + if (ptrIncr == 1) + { + if (this->ImageData) + { + delete [] (static_cast (this->ImageData)); + } + this->ImageData = new char[numPixels]; + + char* charOutputData = static_cast (this->ImageData); + + this->ImageDataType = DICOMParser::VR_OB; + this->ImageDataLengthInBytes = numPixels * sizeof(char); + char newCharPixel; + + for (int i = 0; i < numPixels; i++) + { + newCharPixel = char(this->RescaleSlope * ucharInputData[i] + this->RescaleOffset); + charOutputData[i] = newCharPixel; + } +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Did rescale, offset to char from char." << dicom_stream::endl; + dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl; +#endif + } + else if (ptrIncr == 2) + { + if (this->ImageData) + { + delete [] (static_cast (this->ImageData)); + } + this->ImageData = new short[numPixels]; + short* shortOutputData = static_cast (this->ImageData); + + this->ImageDataType = DICOMParser::VR_OW; + this->ImageDataLengthInBytes = numPixels * sizeof(short); + short newShortPixel; + for (int i = 0; i < numPixels; i++) + { + newShortPixel = short(this->RescaleSlope * shortInputData[i] + this->RescaleOffset); + shortOutputData[i] = newShortPixel; + } +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Did rescale, offset to short from short." << dicom_stream::endl; + dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl; +#endif + } + } +} + +void DICOMAppHelper::RegisterPixelDataCallback(DICOMParser* parser) +{ + this->PixelDataCB->SetCallbackFunction(this, &DICOMAppHelper::PixelDataCallback); + parser->AddDICOMTagCallback(0x7FE0, 0x0010, DICOMParser::VR_OW, this->PixelDataCB); +} + +void DICOMAppHelper::RescaleOffsetCallback( DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + float fval = DICOMFile::ReturnAsFloat(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); + this->RescaleOffset = fval; +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Pixel offset: " << this->RescaleOffset << dicom_stream::endl; +#endif +} + +const char* DICOMAppHelper::TransferSyntaxUIDDescription(const char* uid) +{ + static const char* DICOM_IMPLICIT_VR_LITTLE_ENDIAN = "1.2.840.10008.1.2"; + static const char* DICOM_LOSSLESS_JPEG = "1.2.840.10008.1.2.4.70"; + static const char* DICOM_LOSSY_JPEG_8BIT = "1.2.840.10008.1.2.4.50"; + static const char* DICOM_LOSSY_JPEG_16BIT = "1.2.840.10008.1.2.4.51"; + static const char* DICOM_EXPLICIT_VR_LITTLE_ENDIAN = "1.2.840.10008.1.2.1"; + static const char* DICOM_EXPLICIT_VR_BIG_ENDIAN = "1.2.840.10008.1.2.2"; + static const char* DICOM_GE_PRIVATE_IMPLICIT_BIG_ENDIAN = "1.2.840.113619.5.2"; + + if (!strcmp(DICOM_IMPLICIT_VR_LITTLE_ENDIAN, uid)) + { + return "Implicit VR, Little Endian"; + } + else if (!strcmp(DICOM_LOSSLESS_JPEG, uid)) + { + return "Lossless JPEG"; + } + else if (!strcmp(DICOM_LOSSY_JPEG_8BIT, uid)) + { + return "Lossy JPEG 8 bit"; + } + else if (!strcmp(DICOM_LOSSY_JPEG_16BIT, uid)) + { + return "Lossy JPEG 16 bit."; + } + else if (!strcmp(DICOM_EXPLICIT_VR_LITTLE_ENDIAN, uid)) + { + return "Explicit VR, Little Endian."; + } + else if (!strcmp(DICOM_EXPLICIT_VR_BIG_ENDIAN, uid)) + { + return "Explicit VR, Big Endian."; + } + else if (!strcmp(DICOM_GE_PRIVATE_IMPLICIT_BIG_ENDIAN, uid)) + { + return "GE Private, Implicit VR, Big Endian Image Data."; + } + else + { + return "Unknown."; + } + +} + + +void DICOMAppHelper::RescaleSlopeCallback(DICOMParser *parser, + doublebyte, + doublebyte , + DICOMParser::VRTypes , + unsigned char* val, + quadbyte ) +{ + float fval = DICOMFile::ReturnAsFloat(val, + parser->GetDICOMFile()->GetPlatformIsBigEndian ()); +#ifdef DEBUG_DICOM_APP_HELPER + dicom_stream::cout << "Rescale slope: " << fval << dicom_stream::endl; +#endif + this->RescaleSlope = fval; +} + +bool DICOMAppHelper::RescaledImageDataIsFloat() +{ + int s = int(this->RescaleSlope); + int o = int(this->RescaleOffset); + + float sf = float(s); + float of = float(o); + + double d1 = fabs(sf - this->RescaleSlope); + double d2 = fabs(of - this->RescaleOffset); + + if (d1 > 0.0 || d2 > 0.0) + { + return true; + } + else + { + return false; + } +} + +void DICOMAppHelper::GetImageData(void*& data, DICOMParser::VRTypes& dataType, unsigned long& len) +{ + data = this->ImageData; + dataType = this->ImageDataType; + len = this->ImageDataLengthInBytes; +} + +bool DICOMAppHelper::RescaledImageDataIsSigned() +{ + bool rescaleSigned = (this->RescaleSlope < 0.0); + bool pixelRepSigned = (this->PixelRepresentation == 1); + bool offsetSigned = (this->RescaleOffset < 0.0); + + return (rescaleSigned || pixelRepSigned || offsetSigned); +} + + +void DICOMAppHelper::GetSliceNumberFilenamePairs(const dicom_stl::string &seriesUID, + dicom_stl::vector >& v, bool ascending) +{ + v.clear(); + + dicom_stl::map, ltstdstr >::iterator miter = this->Implementation->SeriesUIDMap.find(seriesUID); + + if (miter == this->Implementation->SeriesUIDMap.end() ) + { + return; + } + + // grab the filenames for the specified series + dicom_stl::vector files = (*miter).second; + + for (dicom_stl::vector::iterator fileIter = files.begin(); + fileIter != files.end(); + fileIter++) + { + dicom_stl::pair p; + p.second = dicom_stl::string(*fileIter); + int slice_number; + dicom_stl::map::iterator sn_iter = Implementation->SliceOrderingMap.find(*fileIter); + // Only store files that have a valid slice number + if (sn_iter != Implementation->SliceOrderingMap.end()) + { + slice_number = (*sn_iter).second.SliceNumber; + p.first = slice_number; + v.push_back(p); + } + } + if (ascending) + { + dicom_stl::sort(v.begin(), v.end(), lt_pair_int_string()); + } + else + { + dicom_stl::sort(v.begin(), v.end(), gt_pair_int_string()); + } +} + +void DICOMAppHelper::GetSliceNumberFilenamePairs(dicom_stl::vector >& v, bool ascending) +{ + // Default to using the first series + if (this->Implementation->SeriesUIDMap.size() > 0) + { + this->GetSliceNumberFilenamePairs( (*this->Implementation->SeriesUIDMap.begin()).first, v, ascending ); + } + else + { + v.clear(); + } +} + +void DICOMAppHelper::GetSliceLocationFilenamePairs(const dicom_stl::string &seriesUID, + dicom_stl::vector >& v, bool ascending) +{ + v.clear(); + + dicom_stl::map, ltstdstr >::iterator miter = this->Implementation->SeriesUIDMap.find(seriesUID); + + if (miter == this->Implementation->SeriesUIDMap.end() ) + { + return; + } + + // grab the filenames for the specified series + dicom_stl::vector files = (*miter).second; + + for (dicom_stl::vector::iterator fileIter = files.begin(); + fileIter != files.end(); + fileIter++) + { + dicom_stl::pair p; + p.second = dicom_stl::string(*fileIter); + float slice_location; + dicom_stl::map::iterator sn_iter = Implementation->SliceOrderingMap.find(*fileIter); + + if (sn_iter != Implementation->SliceOrderingMap.end()) + { + slice_location = (*sn_iter).second.SliceLocation; + p.first = slice_location; + v.push_back(p); + } + } + if (ascending) + { + dicom_stl::sort(v.begin(), v.end(), lt_pair_float_string()); + } + else + { + dicom_stl::sort(v.begin(), v.end(), gt_pair_float_string()); + } +} + +void DICOMAppHelper::GetSliceLocationFilenamePairs(dicom_stl::vector >& v, bool ascending) +{ + // Default to using the first series + if (this->Implementation->SeriesUIDMap.size() > 0) + { + this->GetSliceLocationFilenamePairs( (*this->Implementation->SeriesUIDMap.begin()).first, + v , ascending); + } + else + { + v.clear(); + } +} + +void DICOMAppHelper::GetImagePositionPatientFilenamePairs(const dicom_stl::string &seriesUID, dicom_stl::vector >& v, bool ascending) +{ + v.clear(); + + dicom_stl::map, ltstdstr >::iterator miter = this->Implementation->SeriesUIDMap.find(seriesUID); + + if (miter == this->Implementation->SeriesUIDMap.end() ) + { + return; + } + + // grab the filenames for the specified series + dicom_stl::vector files = (*miter).second; + + for (dicom_stl::vector::iterator fileIter = files.begin(); + fileIter != files.end(); + fileIter++) + { + dicom_stl::pair p; + p.second = dicom_stl::string(*fileIter); + + float image_position; + float normal[3]; + + dicom_stl::map::iterator sn_iter = + Implementation->SliceOrderingMap.find(*fileIter); + + if (sn_iter != Implementation->SliceOrderingMap.end()) + { + // compute the image patient position wrt to the slice image + // plane normal + + normal[0] = ((*sn_iter).second.ImageOrientationPatient[1] + * (*sn_iter).second.ImageOrientationPatient[5]) + - ((*sn_iter).second.ImageOrientationPatient[2] + * (*sn_iter).second.ImageOrientationPatient[4]); + normal[1] = ((*sn_iter).second.ImageOrientationPatient[0] + *(*sn_iter).second.ImageOrientationPatient[5]) + - ((*sn_iter).second.ImageOrientationPatient[2] + * (*sn_iter).second.ImageOrientationPatient[3]); + normal[2] = ((*sn_iter).second.ImageOrientationPatient[0] + * (*sn_iter).second.ImageOrientationPatient[4]) + - ((*sn_iter).second.ImageOrientationPatient[1] + * (*sn_iter).second.ImageOrientationPatient[3]); + + image_position = (normal[0]*(*sn_iter).second.ImagePositionPatient[0]) + + (normal[1]*(*sn_iter).second.ImagePositionPatient[1]) + + (normal[2]*(*sn_iter).second.ImagePositionPatient[2]); + p.first = image_position; + v.push_back(p); + } + } + if (ascending) + { + dicom_stl::sort(v.begin(), v.end(), lt_pair_float_string()); + } + else + { + dicom_stl::sort(v.begin(), v.end(), gt_pair_float_string()); + } +} + + +void DICOMAppHelper::GetImagePositionPatientFilenamePairs(dicom_stl::vector >& v, bool ascending) +{ + // Default to using the first series + if (this->Implementation->SeriesUIDMap.size() > 0) + { + this->GetImagePositionPatientFilenamePairs( + (*this->Implementation->SeriesUIDMap.begin()).first, v, ascending); + } + else + { + v.clear(); + } +} + +void DICOMAppHelper::GetSeriesUIDs(dicom_stl::vector &v) +{ + v.clear(); + + dicom_stl::map, ltstdstr >::iterator miter; + + for (miter = this->Implementation->SeriesUIDMap.begin(); miter != this->Implementation->SeriesUIDMap.end(); + ++miter) + { + v.push_back( (*miter).first ); + } +} + +void DICOMAppHelper::Clear() +{ + this->Implementation->SliceOrderingMap.clear(); + this->Implementation->SeriesUIDMap.clear(); +} + +void DICOMAppHelper::PatientNameCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + if (this->PatientName) + { + delete this->PatientName; + } + + if (val) + { + this->PatientName = new dicom_stl::string((char*) val); + } + else + { + this->PatientName = new dicom_stl::string(); + } +} + +void DICOMAppHelper::StudyUIDCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + if (this->StudyUID) + { + delete this->StudyUID; + } + + this->StudyUID = new dicom_stl::string((char*) val); + +} + +void DICOMAppHelper::StudyIDCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + if (this->StudyID) + { + delete this->StudyID; + } + + if (val) + { + this->StudyID = new dicom_stl::string((char*) val); + } + else + { + this->StudyID = new dicom_stl::string(); + } + +} + +void DICOMAppHelper::GantryAngleCallback(DICOMParser * parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) +{ + float fval = DICOMFile::ReturnAsFloat(val, + parser->GetDICOMFile()->GetPlatformIsBigEndian ()); + + this->GantryAngle = fval; +} + + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif + diff --git a/Utilities/DICOMParser/DICOMAppHelper.h b/Utilities/DICOMParser/DICOMAppHelper.h new file mode 100644 index 0000000..bb26086 --- /dev/null +++ b/Utilities/DICOMParser/DICOMAppHelper.h @@ -0,0 +1,549 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMAppHelper.h,v $ + Language: C++ + Date: $Date: 2006/08/31 17:30:29 $ + Version: $Revision: 1.12.20.1 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __DICOM_APP_HELPER_H_ +#define __DICOM_APP_HELPER_H_ + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( push, 3 ) +#endif + +#include +#include + +#include "DICOMConfig.h" +#include "DICOMTypes.h" +#include "DICOMCallback.h" + +class DICOMParser; + +// Function object for sorting strings +struct ltstdstr +{ + bool operator()(const dicom_stl::string s1, const dicom_stl::string s2) const + { + return s1 < s2; + } +}; + +// Helper structure for DICOM elements +struct DICOMTagInfo +{ + doublebyte group; + doublebyte element; + DICOMParser::VRTypes datatype; + const char* description; +}; + + +// Helper class use for ordering DICOM images based on different +// (group, element) tags. +class DICOM_EXPORT DICOMOrderingElements +{ +public: + DICOMOrderingElements() + { + // Default values to something "valid" + SliceNumber = -1; + SliceLocation = 0.0; + ImagePositionPatient[0] = 0.0; + ImagePositionPatient[1] = 0.0; + ImagePositionPatient[2] = 0.0; + ImageOrientationPatient[0] = 1.0; + ImageOrientationPatient[1] = 0.0; + ImageOrientationPatient[2] = 0.0; + ImageOrientationPatient[3] = 0.0; + ImageOrientationPatient[4] = 1.0; + ImageOrientationPatient[5] = 0.0; + } + + int SliceNumber; + float SliceLocation; + float ImagePositionPatient[3]; + float ImageOrientationPatient[6]; +}; + +class DICOMAppHelperImplementation; + +/** + * \class DICOMAppHelper + * \brief Class to interface an application to a DICOMParser + * + * DICOMAppHelper assists an application in communicating with a + * DICOMParser. DICOMAppHelper registers a series of callbacks to the + * DICOMParser which allows it to cache the information from a DICOM + * file in a format that is appropriate for an application to + * use. Once a DICOM file is read, an application can query the + * DICOMAppHelper for the resolution, pixel size, and pixel data. + * + * If a DICOMParser scans more than one file, the DICOMAppHelper will + * group filesnames by SeriesUID. This allows an application to pass + * a series of DICOM files to the DICOMParser (which via the callback + * mechanism allows the DICOMAppHelper to cache information) and then + * query the DICOMAppHelper for the files that are from the same + * series. The application can request the filenames for a particular + * series to be sorted based on image number, slice location, or + * patient position. This allows the DICOMAppHelper to assist an + * application is collecting all the images from one series into a + * volume. + */ +class DICOM_EXPORT DICOMAppHelper +{ +public: + /** Standard constructor */ + DICOMAppHelper(); + + /** Standard destructor */ + virtual ~DICOMAppHelper(); + + /** Callbacks that are registered with the DICOMParser. The + * DICOMParser will call one of these callbacks whenever it + * encounters a (group, element) that has an associated callback */ + virtual void RescaleSlopeCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len); + + virtual void ArrayCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len); + + virtual void SliceNumberCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void SliceLocationCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void ImagePositionPatientCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void ImageOrientationPatientCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void SeriesUIDCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void TransferSyntaxCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void BitsAllocatedCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void ToggleSwapBytesCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char*, + quadbyte); + + virtual void PixelSpacingCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) ; + + virtual void HeightCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len); + + virtual void WidthCallback( DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len); + + virtual void PixelRepresentationCallback(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len); + + virtual void PhotometricInterpretationCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte len); + + virtual void PixelDataCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte len); + + virtual void RescaleOffsetCallback( DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte); + + /** Register all the standard callbacks with the DICOM Parser. This + * associates a callback with each (group, element) tag pair in the + * header of the file whose data needs to be cached. */ + virtual void RegisterCallbacks(DICOMParser* parser); + + /** Register a callback for retrieving the pixel data from a DICOM + * file */ + virtual void RegisterPixelDataCallback(DICOMParser* parser); + + + /** Output information associated with a DICOM series */ + void OutputSeries(); + + + /** The next set of methods are for accessing information which is + * cached when a DICOM file is processed. This allows access to + * information from the header as well as the pixel data. */ + + + /** Get the pixel spacing of the last image processed by the + * DICOMParser */ + float* GetPixelSpacing() + { + return this->PixelSpacing; + } + + /** Get the image width of the last image processed by the + * DICOMParser */ + int GetWidth() + { + return this->Width; + } + + /** Get the image height of the last image processed by the + * DICOMParser */ + int GetHeight() + { + return this->Height; + } + + /** Get the dimensions (width, height) of the last image processed + * by the DICOMParser */ + int* GetDimensions() + { + return this->Dimensions; + } + + /** Get the (DICOM) x,y,z coordinates of the first pixel in the + * image (upper left hand corner) of the last image processed by the + * DICOMParser */ + float *GetImagePositionPatient() + { + return this->ImagePositionPatient; + } + + /** Get the (DICOM) directions cosines. It consist of the components + * of the first two vectors. The third vector needs to be computed + * to form an orthonormal basis. */ + float *GetImageOrientationPatient() + { + return this->ImageOrientationPatient; + } + + /** Get the number of bits allocated per pixel of the last image + * processed by the DICOMParser */ + int GetBitsAllocated() + { + return this->BitsAllocated; + } + + /** Get the pixel representation of the last image processed by the + * DICOMParser. A zero is a unsigned quantity. A one indicates a + * signed quantity. */ + int GetPixelRepresentation() + { + return this->PixelRepresentation; + } + + /** Get the number of components of the last image processed by the + * DICOMParser. */ + int GetNumberOfComponents() + { + if (!this->PhotometricInterpretation) + { + return 1; + } + + // + // DICOM standard says that spaces (0x20) are to + // be ignored for CS types. We don't handle this + // well yet. + // + dicom_stl::string str1(*this->PhotometricInterpretation); + dicom_stl::string rgb("RGB "); + + if (str1 == rgb) + { + return 3; + } + else + { + return 1; + } + } + + /** Get the transfer syntax UID for the last image processed by the + * DICOMParser. */ + dicom_stl::string GetTransferSyntaxUID() + { + return *(this->TransferSyntaxUID); + } + + /** Get a textual description of the transfer syntax of the last + * image processed by the DICOMParser. */ + const char* TransferSyntaxUIDDescription(const char* uid); + + /** Get the image data from the last image processed by the + * DICOMParser. The data is only valid if the PixelDataCallback was + * registered. + * \sa RegisterPixelDataCallback() + */ + void GetImageData(void* & data, DICOMParser::VRTypes& dataType, unsigned long& len); + + /** Determine whether the image data was rescaled (by the + * RescaleSlope tag) to be floating point. */ + bool RescaledImageDataIsFloat(); + + /** Determine whether the image data was rescaled (by the + * RescaleSlope tag) to be a signed data type. */ + bool RescaledImageDataIsSigned(); + + /** Get the slice number of the last image processed by the + DICOMParser. */ + int GetSliceNumber() + { + return this->SliceNumber; + } + + /** Clear the internal databases. This will reset the internal + * databases that are grouping filenames based on SeriesUID's and + * ordering filenames based on image locations. */ + void Clear(); + + /** Get the series UIDs for the files processed since the last + * clearing of the cache. */ + void GetSeriesUIDs(dicom_stl::vector &v); + + /** Get the filenames for a series ordered by slice number. */ + void GetSliceNumberFilenamePairs(const dicom_stl::string &seriesUID, + dicom_stl::vector > &v, bool ascending = true); + + /** Get the filenames for a series order by slice number. Use the + first series by default. */ + void GetSliceNumberFilenamePairs(dicom_stl::vector > &v, bool ascending = true); + + /* Get the filenames for a series ordered by slice location. */ + void GetSliceLocationFilenamePairs(const dicom_stl::string &seriesUID, + dicom_stl::vector > &v, bool ascending = true); + + /* Get the filenames for a series ordered by slice location. Use the + * first series by default. */ + void GetSliceLocationFilenamePairs(dicom_stl::vector > &v, bool ascending = true); + + /* Get the filenames for a series ordered by image position + patient. This is the most reliable way to order the images in a + series. */ + void GetImagePositionPatientFilenamePairs(const dicom_stl::string &seriesUID, + dicom_stl::vector > &v, bool ascending = true); + + /* Get the filenames for a series ordered by image position + patient. This is the most reliable way to order the images in a + series. Use the first series by default. */ + void GetImagePositionPatientFilenamePairs(dicom_stl::vector > &v, bool ascending = true); + + float GetRescaleSlope() + { + return this->RescaleSlope; + } + + float GetRescaleOffset() + { + return this->RescaleOffset; + } + + dicom_stl::string GetPatientName() + { + return *(this->PatientName); + } + + dicom_stl::string GetStudyUID() + { + return *(this->StudyUID); + } + + dicom_stl::string GetStudyID() + { + return *(this->StudyID); + } + + void PatientNameCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte); + + void StudyUIDCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte); + + void StudyIDCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte); + + void GantryAngleCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte); + + float GetGantryAngle() + { + return this->GantryAngle; + } + + + + protected: + int BitsAllocated; + bool ByteSwapData; + float PixelSpacing[3]; + int Width; + int Height; + int SliceNumber; + int Dimensions[2]; + float ImagePositionPatient[3]; + float ImageOrientationPatient[6]; + + // map from series UID to vector of files in the series + // dicom_stl::map, ltstdstr> SeriesUIDMap; + + // map from filename to intraseries sortable tags + // dicom_stl::map SliceOrderingMap; + + typedef dicom_stl::map, DICOMTagInfo> TagMapType; + // TagMapType TagMap; + + dicom_stream::ofstream HeaderFile; + + // 0 unsigned + // 1 2s complement (signed) + int PixelRepresentation; + dicom_stl::string* PhotometricInterpretation; + dicom_stl::string* TransferSyntaxUID; + float RescaleOffset; + float RescaleSlope; + void* ImageData; + DICOMParser::VRTypes ImageDataType; + unsigned long ImageDataLengthInBytes; + + dicom_stl::string* PatientName; + dicom_stl::string* StudyUID; + dicom_stl::string* StudyID; + float GantryAngle; + + DICOMMemberCallback* SeriesUIDCB; + DICOMMemberCallback* SliceNumberCB; + DICOMMemberCallback* SliceLocationCB; + DICOMMemberCallback* ImagePositionPatientCB; + DICOMMemberCallback* ImageOrientationPatientCB; + DICOMMemberCallback* TransferSyntaxCB; + DICOMMemberCallback* ToggleSwapBytesCB; + DICOMMemberCallback* BitsAllocatedCB; + DICOMMemberCallback* PixelSpacingCB; + DICOMMemberCallback* HeightCB; + DICOMMemberCallback* WidthCB; + DICOMMemberCallback* PixelRepresentationCB; + DICOMMemberCallback* PhotometricInterpretationCB; + DICOMMemberCallback* RescaleOffsetCB; + DICOMMemberCallback* RescaleSlopeCB; + DICOMMemberCallback* PixelDataCB; + DICOMMemberCallback* PatientNameCB; + DICOMMemberCallback* StudyUIDCB; + DICOMMemberCallback* StudyIDCB; + + DICOMMemberCallback* GantryAngleCB; + + // + // Implementation contains stl templated classes that + // can't be exported from a DLL in Windows. We hide + // them in the implementation to get rid of annoying + // compile warnings. + // + DICOMAppHelperImplementation* Implementation; + + private: + DICOMAppHelper(const DICOMAppHelper&); + void operator=(const DICOMAppHelper&); + +}; + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif + +#endif diff --git a/Utilities/DICOMParser/DICOMCMakeConfig.h.in b/Utilities/DICOMParser/DICOMCMakeConfig.h.in new file mode 100644 index 0000000..32e5c3d --- /dev/null +++ b/Utilities/DICOMParser/DICOMCMakeConfig.h.in @@ -0,0 +1,10 @@ + +#ifndef __DICOMCMakeConfig_h_ +#define __DICOMCMakeConfig_h_ + +#cmakedefine DICOM_DLL +#cmakedefine DICOM_STATIC +#cmakedefine DICOM_ANSI_STDLIB +#cmakedefine DICOM_NO_STD_NAMESPACE + +#endif diff --git a/Utilities/DICOMParser/DICOMCallback.h b/Utilities/DICOMParser/DICOMCallback.h new file mode 100644 index 0000000..75ce146 --- /dev/null +++ b/Utilities/DICOMParser/DICOMCallback.h @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMCallback.h,v $ + Language: C++ + Date: $Date: 2005/04/15 22:55:39 $ + Version: $Revision: 1.6 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __DICOM_CALLBACK_H_ +#define __DICOM_CALLBACK_H_ + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4503 ) +#pragma warning ( disable : 4710 ) +#pragma warning ( disable : 4702 ) +#pragma warning ( push, 3 ) +#endif + +#include "DICOMConfig.h" +#include "DICOMParser.h" + +// +// Pure virtual class that specifies the interface +// for a DICOMCallback. +// +// The DICOMParser allows a vector of callbacks to +// be specified for each group element tag. When +// a group, element with a registered callback is +// encountered, the callback is called and passed +// the group, element, type, data, and data length. +// + +class DICOM_EXPORT DICOMCallback +{ + public: + virtual ~DICOMCallback() {}; + virtual void Execute(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) = 0; +}; + +// +// Subclass of DICOMCallback which can be used +// with member functions. +// +template +class DICOMMemberCallback : public DICOMCallback +{ + public: + typedef void (T::*TMemberFunctionPointer)(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len); + + + // + // Method to set the object and member function pointers + // that will be called in the callback. + // + void SetCallbackFunction(T* object, + TMemberFunctionPointer memberFunction) + { + ObjectThis = object; + MemberFunction = memberFunction; + } + + // + // Execute method implementation from DICOMCallback. + // + void Execute(DICOMParser *parser, + doublebyte group, + doublebyte element, + DICOMParser::VRTypes type, + unsigned char* val, + quadbyte len) + { + if (MemberFunction) + { + ((*ObjectThis).*(MemberFunction))(parser, group, element, type, val,len); + } + } + + protected: + T* ObjectThis; + TMemberFunctionPointer MemberFunction; + +}; + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif + +#endif + diff --git a/Utilities/DICOMParser/DICOMConfig.h b/Utilities/DICOMParser/DICOMConfig.h new file mode 100644 index 0000000..8a94c83 --- /dev/null +++ b/Utilities/DICOMParser/DICOMConfig.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMConfig.h,v $ + Language: C++ + Date: $Date: 2003/09/15 22:25:50 $ + Version: $Revision: 1.6 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __DICOM_CONFIG_H_ +#define __DICOM_CONFIG_H_ + +// +// CMake Hook +// +#include "DICOMCMakeConfig.h" + +// +// BEGIN Toolkit (ITK,VTK, etc) specific +// +#ifdef vtkDICOMParser_EXPORTS + #define DICOM_EXPORT_SYMBOLS +#endif +// +// END toolkit (ITK, VTK, etc) specific +// +#ifdef DICOM_NO_STD_NAMESPACE + #define dicom_stl +#else + #define dicom_stl std +#endif + +#ifdef DICOM_ANSI_STDLIB + #define dicom_stream std + + #include + #include + #include +#else + #define dicom_stream + + #include + #include + #include +#endif + +#ifdef DICOM_DLL + #ifdef DICOM_EXPORT_SYMBOLS + #define DICOM_EXPORT __declspec(dllexport) + #define DICOM_EXPIMP_TEMPLATE + #else + #define DICOM_EXPORT __declspec(dllimport) + #define DICOM_EXPIMP_TEMPLATE extern + #endif +#else + #define DICOM_EXPORT +#endif + +#endif // __DICOM_CONFIG_H_ diff --git a/Utilities/DICOMParser/DICOMFile.cxx b/Utilities/DICOMParser/DICOMFile.cxx new file mode 100644 index 0000000..ad5c724 --- /dev/null +++ b/Utilities/DICOMParser/DICOMFile.cxx @@ -0,0 +1,285 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMFile.cxx,v $ + Language: C++ + Date: $Date: 2005/07/26 20:02:22 $ + Version: $Revision: 1.11 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( disable : 4710 ) +#pragma warning ( push, 3 ) +#endif + +#include +#include + +#include "DICOMConfig.h" +#include "DICOMFile.h" + +DICOMFile::DICOMFile() : InputStream() +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + PlatformIsBigEndian = (u.c[sizeof (long) - 1] == 1); + if (PlatformIsBigEndian) + { + PlatformEndian = "BigEndian"; + } + else + { + PlatformEndian = "LittleEndian"; + } +} + +DICOMFile::~DICOMFile() +{ + this->Close(); +} + +DICOMFile::DICOMFile(const DICOMFile& in) +{ + if (strcmp(in.PlatformEndian, "LittleEndian") == 0) + { + PlatformEndian = "LittleEndian"; + } + else + { + PlatformEndian = "BigEndian"; + } + // + // Some compilers can't handle. Comment out for now. + // + // InputStream = in.InputStream; +} + +void DICOMFile::operator=(const DICOMFile& in) +{ + if (strcmp(in.PlatformEndian, "LittleEndian") == 0) + { + PlatformEndian = "LittleEndian"; + } + else + { + PlatformEndian = "BigEndian"; + } + // + // Some compilers can't handle. Comment out for now. + // + // InputStream = in.InputStream; +} + +bool DICOMFile::Open(const dicom_stl::string& filename) +{ +#ifdef _WIN32 + InputStream.open(filename.c_str(), dicom_stream::ios::binary | dicom_stream::ios::in); +#else + InputStream.open(filename.c_str(), dicom_stream::ios::in); +#endif + + //if (InputStream.is_open()) + if (InputStream.rdbuf()->is_open()) + { + return true; + } + else + { + return false; + } +} + +void DICOMFile::Close() +{ + InputStream.close(); +} + +long DICOMFile::Tell() +{ + long loc = InputStream.tellg(); + // dicom_stream::cout << "Tell: " << loc << dicom_stream::endl; + return loc; +} + +void DICOMFile::SkipToPos(long increment) +{ + InputStream.seekg(increment, dicom_stream::ios::beg); +} + +long DICOMFile::GetSize() +{ + long curpos = this->Tell(); + + InputStream.seekg(0,dicom_stream::ios::end); + + long size = this->Tell(); + // dicom_stream::cout << "Tell says size is: " << size << dicom_stream::endl; + this->SkipToPos(curpos); + + return size; +} + +void DICOMFile::Skip(long increment) +{ + InputStream.seekg(increment, dicom_stream::ios::cur); +} + +void DICOMFile::SkipToStart() +{ + InputStream.seekg(0, dicom_stream::ios::beg); +} + +void DICOMFile::Read(void* ptr, long nbytes) +{ + InputStream.read((char*)ptr, nbytes); + // dicom_stream::cout << (char*) ptr << dicom_stream::endl; +} + +doublebyte DICOMFile::ReadDoubleByte() +{ + doublebyte sh = 0; + int sz = sizeof(doublebyte); + this->Read((char*)&(sh),sz); + if (PlatformIsBigEndian) + { + sh = swap2(sh); + } + return(sh); +} + +doublebyte DICOMFile::ReadDoubleByteAsLittleEndian() +{ + doublebyte sh = 0; + int sz = sizeof(doublebyte); + this->Read((char*)&(sh),sz); + if (PlatformIsBigEndian) + { + sh = swap2(sh); + } + return(sh); +} + +quadbyte DICOMFile::ReadQuadByte() +{ + quadbyte sh; + int sz = sizeof(quadbyte); + this->Read((char*)&(sh),sz); + if (PlatformIsBigEndian) + { + sh = swap4(sh); + } + return(sh); +} + +quadbyte DICOMFile::ReadNBytes(int len) +{ + quadbyte ret = -1; + switch (len) + { + case 1: + char ch; + this->Read(&ch,1); //from Image + ret =(quadbyte) ch; + break; + case 2: + ret =(quadbyte) ReadDoubleByte(); + break; + case 4: + ret = ReadQuadByte(); + break; + default: + dicom_stream::cerr << "Unable to read " << len << " bytes" << dicom_stream::endl; + break; + } + return (ret); +} + +float DICOMFile::ReadAsciiFloat(int len) +{ + float ret=0.0; + + + char* val = new char[len+1]; + this->Read(val,len); + val[len] = '\0'; + +#if 0 + // + // istrstream destroys the data during formatted input. + // + int len2 = static_cast (strlen((char*) val)); + char* val2 = new char[len2]; + strncpy(val2, (char*) val, len2); + + dicom_stream::istrstream data(val2); + data >> ret; + delete [] val2; +#else + sscanf(val,"%e",&ret); +#endif + + dicom_stream::cout << "Read ASCII float: " << ret << dicom_stream::endl; + + delete [] val; + return (ret); +} + +int DICOMFile::ReadAsciiInt(int len) +{ + int ret=0; + + char* val = new char[len+1]; + this->Read(val,len); + val[len] = '\0'; + +#if 0 + // + // istrstream destroys the data during formatted input. + // + int len2 = static_cast (strlen((char*) val)); + char* val2 = new char[len2]; + strncpy(val2, (char*) val, len2); + + dicom_stream::istrstream data(val2); + data >> ret; + delete [] val2; +#else + sscanf(val,"%d",&ret); +#endif + + dicom_stream::cout << "Read ASCII int: " << ret << dicom_stream::endl; + + delete [] val; + return (ret); +} + +char* DICOMFile::ReadAsciiCharArray(int len) +{ + if (len <= 0) + { + return NULL; + } + char* val = new char[len + 1]; + this->Read(val, len); + val[len] = 0; // NULL terminate. + return val; +} + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif diff --git a/Utilities/DICOMParser/DICOMFile.h b/Utilities/DICOMParser/DICOMFile.h new file mode 100644 index 0000000..e7a8963 --- /dev/null +++ b/Utilities/DICOMParser/DICOMFile.h @@ -0,0 +1,262 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMFile.h,v $ + Language: C++ + Date: $Date: 2005/07/27 21:01:09 $ + Version: $Revision: 1.14 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __DICOMFILE_H_ +#define __DICOMFILE_H_ + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( push, 3 ) +#endif + +#include +#include +#include + +#include "DICOMTypes.h" +#include "DICOMConfig.h" + +// +// Abstraction of a file used by the DICOMParser. +// This should probably be cleaned up so that it +// can be used to abstract a stream. +// +class DICOM_EXPORT DICOMFile +{ + public: + DICOMFile(); + virtual ~DICOMFile(); + + // + // Open a file with filename. Returns a bool + // that is true if the file is successfully + // opened. + // + bool Open(const dicom_stl::string& filename); + + // + // Close a file. + // + void Close(); + + // + // Return the position in the file. + // + long Tell(); + + // + // Move to a particular position in the file. + // + void SkipToPos(long); + + // + // Return the size of the file. + // + long GetSize(); + + // + // Skip a number of bytes. + // + void Skip(long); + + // + // Skip to the beginning of the file. + // + void SkipToStart(); + + // + // Read data of length len. + // + void Read(void* data, long len); + + // + // Read a double byte of data. + // + doublebyte ReadDoubleByte(); + + + doublebyte ReadDoubleByteAsLittleEndian(); + + // + // Read a quadbyte of data. + // + quadbyte ReadQuadByte(); + + // + // Read nbytes of data up to 4 bytes. + // + quadbyte ReadNBytes(int len); + + // + // Read a float an ascii. + // + float ReadAsciiFloat(int len); + + // + // Read an int as ascii. + // + int ReadAsciiInt(int len); + + // + // Read an array of ascii characters. + // + char* ReadAsciiCharArray(int len); + + // + // Convert the data to signed long. + // + static int ReturnAsSignedLong(unsigned char* data, bool ) + { + unsigned char* data2 = data; + return *((quadbyte*) data2); + } + + + // + // Convert the data to unsigned long. + // + static uint ReturnAsUnsignedLong(unsigned char* data, bool) + { + unsigned char* data2 = data; + return *((ulong*) data2); + } + + // + // Convert data to unsigned short. + // + static ushort ReturnAsUnsignedShort(unsigned char* data, bool) + { + unsigned char* data2 = data; + return *((doublebyte*)data2); + } + + // + // Convert data to signed short. + // + static short int ReturnAsSignedShort(unsigned char* data, bool) + { + unsigned char* data2 = data; + return *((short int*)data2); + } + + // + // Convert data to int. + // + static int ReturnAsInteger(unsigned char* data, bool) + { + return static_cast (atoi((const char*) data)); + } + + static float ReturnAsFloat(unsigned char* data, bool) + { + return static_cast (atof((const char*) data)); + } + + bool GetPlatformIsBigEndian() + { + return PlatformIsBigEndian; + } + + void SetPlatformIsBigEndian(bool v) + { + this->PlatformIsBigEndian = v; + } + + // + // Swap the bytes in an array of unsigned shorts. + // + static void swap2(ushort *ip, ushort *op, int count) + { + while (count) + { + *op++ = swap2(*ip++); + count--; + } + } + + // + // Swap the bytes in an array of unsigned longs. + // + static void swap4(uint *ip, uint *op, int count) + { + while (count) + { + *op++ = swap4(*ip++); + count--; + } + } + + + // + // Swap the bytes in an unsigned short. + // + static ushort swap2(ushort v) + { + return ushort((v << 8) + | (v >> 8)); + } + + // + // Swap the bytes in an unsigned long. + // + static uint swap4(uint v) + { + return uint((v << 24) + | (v << 8) & 0x00ff0000 + | (v >> 8) & 0x0000ff00 + | (v >> 24)); + } + + const char* GetPlatformEndian() {return this->PlatformEndian;} + + protected: + // + // Internal storage for the filename. + // + // char* Filename; + + // + // Internal storage for the file pointer. + // + // FILE* Fptr; + + dicom_stream::ifstream InputStream; + + // + // Flag for swaping bytes. + // + bool PlatformIsBigEndian; + + // + // Platform endianness + // + const char* PlatformEndian; + + private: + DICOMFile(const DICOMFile&); + void operator=(const DICOMFile&); + +}; + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif + +#endif // __DICOMFILE_H_ + + diff --git a/Utilities/DICOMParser/DICOMParser.cxx b/Utilities/DICOMParser/DICOMParser.cxx new file mode 100644 index 0000000..86aefde --- /dev/null +++ b/Utilities/DICOMParser/DICOMParser.cxx @@ -0,0 +1,779 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMParser.cxx,v $ + Language: C++ + Date: $Date: 2006/03/24 15:59:50 $ + Version: $Revision: 1.14.4.1 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4503 ) +#pragma warning ( disable : 4710 ) +#pragma warning ( push, 3 ) +#endif + + +#include +#if !defined(__MWERKS__) +#include +#endif +#include +#include +#if !defined(__MWERKS__) +#include +#endif + +#include + +#include "DICOMConfig.h" +#include "DICOMParser.h" +#include "DICOMCallback.h" + + +// Define DEBUG_DICOM to get debug messages sent to dicom_stream::cerr +// #define DEBUG_DICOM + +#define DICOMPARSER_IGNORE_MAGIC_NUMBER + +#ifdef DEBUG_DICOM +#define DICOM_DBG_MSG(x) {dicom_stream::cout x} +#else +#define DICOM_DBG_MSG(x) +#endif + +static const char* DICOM_MAGIC = "DICM"; +static const int OPTIONAL_SKIP = 128; + +class DICOMParserImplementation +{ +public: + DICOMParserImplementation() : Groups(), Elements(), Datatypes(), Map(), TypeMap() + { + + }; + + dicom_stl::vector Groups; + dicom_stl::vector Elements; + dicom_stl::vector Datatypes; + // + // Stores a map from pair keys to + // values of pair, datatype> + // + DICOMParserMap Map; + + // + // Stores a map from pair keys to + // values of datatype. We use this to store the + // datatypes for implicit keys that we are + // interested in. + // + DICOMImplicitTypeMap TypeMap; + +}; + +DICOMParser::DICOMParser() : ParserOutputFile() +{ + this->Implementation = new DICOMParserImplementation(); + this->DataFile = NULL; + this->ToggleByteSwapImageData = false; + this->TransferSyntaxCB = new DICOMMemberCallback; + this->InitTypeMap(); + this->FileName = ""; +} + +const dicom_stl::string& +DICOMParser::GetFileName() +{ + return this->FileName; +} + +bool DICOMParser::OpenFile(const dicom_stl::string& filename) +{ + if (this->DataFile) + { + // Deleting the DataFile closes the file + delete this->DataFile; + } + this->DataFile = new DICOMFile(); + bool val = this->DataFile->Open(filename); + + if (val) + { + this->FileName = filename; + } + + +#ifdef DEBUG_DICOM + if (this->ParserOutputFile.rdbuf()->is_open()) + { + this->ParserOutputFile.flush(); + this->ParserOutputFile.close(); + } + + dicom_stl::string fn(filename); + dicom_stl::string append(".parser.txt"); + dicom_stl::string parseroutput(fn + append); + // dicom_stl::string parseroutput(dicom_stl::string(dicom_stl::string(filename) + dicom_stl::string(".parser.txt"))); + this->ParserOutputFile.open(parseroutput.c_str()); //, dicom_stream::ios::app); +#endif + + return val; +} + +DICOMParser::~DICOMParser() { + // + // Delete the callbacks. + // + this->ClearAllDICOMTagCallbacks(); + + if (this->DataFile) + { + delete this->DataFile; + } + + delete this->TransferSyntaxCB; + delete this->Implementation; + +#ifdef DEBUG_DICOM + this->ParserOutputFile.flush(); + this->ParserOutputFile.close(); +#endif + +} + +bool DICOMParser::ReadHeader() { + bool dicom = this->IsDICOMFile(this->DataFile); + if (!dicom) + { + return false; + } + + this->TransferSyntaxCB->SetCallbackFunction(this, &DICOMParser::TransferSyntaxCallback); + this->AddDICOMTagCallback(0x0002, 0x0010, DICOMParser::VR_UI, this->TransferSyntaxCB); + + this->ToggleByteSwapImageData = false; + + doublebyte group = 0; + doublebyte element = 0; + DICOMParser::VRTypes datatype = DICOMParser::VR_UNKNOWN; + + this->Implementation->Groups.clear(); + this->Implementation->Elements.clear(); + this->Implementation->Datatypes.clear(); + + long fileSize = DataFile->GetSize(); + do + { + this->ReadNextRecord(group, element, datatype); + + this->Implementation->Groups.push_back(group); + this->Implementation->Elements.push_back(element); + this->Implementation->Datatypes.push_back(datatype); + + } while ((DataFile->Tell() >= 0) && (DataFile->Tell() < fileSize)); + + + return true; +} + +// +// read magic number from file +// return true if this is your image type, false if it is not +// +bool DICOMParser::IsDICOMFile(DICOMFile* file) { + char magic_number[4]; + file->SkipToStart(); + file->Read((void*)magic_number,4); + if (CheckMagic(magic_number)) + { + return(true); + } + // try with optional skip + else + { + file->Skip(OPTIONAL_SKIP-4); + file->Read((void*)magic_number,4); + if (CheckMagic(magic_number)) + { + return true; + } + else + { + +#ifndef DICOMPARSER_IGNORE_MAGIC_NUMBER + return false; +#else + // + // Try it anyways... + // + + file->SkipToStart(); + + doublebyte group = file->ReadDoubleByte(); + bool dicom; + if (group == 0x0002 || group == 0x0008) + { + dicom_stream::cerr << "No DICOM magic number found, but file appears to be DICOM." << dicom_stream::endl; + dicom_stream::cerr << "Proceeding without caution." << dicom_stream::endl; + dicom = true; + } + else + { + dicom = false; + } + file->SkipToStart(); + + return dicom; +#endif // DICOMPARSER_IGNORE_MAGIC_NUMBER + + } + } +} + + +bool DICOMParser::IsValidRepresentation(doublebyte rep, quadbyte& len, VRTypes &mytype) +{ + switch (rep) + { + case DICOMParser::VR_AW: + case DICOMParser::VR_AE: + case DICOMParser::VR_AS: + case DICOMParser::VR_CS: + case DICOMParser::VR_UI: + case DICOMParser::VR_DA: + case DICOMParser::VR_DS: + case DICOMParser::VR_DT: + case DICOMParser::VR_IS: + case DICOMParser::VR_LO: + case DICOMParser::VR_LT: + case DICOMParser::VR_PN: + case DICOMParser::VR_ST: + case DICOMParser::VR_TM: + case DICOMParser::VR_UT: // new + case DICOMParser::VR_SH: + case DICOMParser::VR_FL: + case DICOMParser::VR_SL: + case DICOMParser::VR_AT: + case DICOMParser::VR_UL: + case DICOMParser::VR_US: + case DICOMParser::VR_SS: + case DICOMParser::VR_FD: + len = DataFile->ReadDoubleByte(); + mytype = VRTypes(rep); + return true; + + case DICOMParser::VR_OB: // OB - LE + case DICOMParser::VR_OW: + case DICOMParser::VR_UN: + case DICOMParser::VR_SQ: + DataFile->ReadDoubleByte(); + len = DataFile->ReadQuadByte(); + mytype = VRTypes(rep); + return true; + + default: + // + // + // Need to comment out in new paradigm. + // + DataFile->Skip(-2); + len = DataFile->ReadQuadByte(); + mytype = DICOMParser::VR_UNKNOWN; + return false; + } +} + +void DICOMParser::ReadNextRecord(doublebyte& group, doublebyte& element, DICOMParser::VRTypes& mytype) +{ + // + // WE SHOULD IMPLEMENT THIS ALGORITHM. + // + // FIND A WAY TO STOP IF THERE ARE NO MORE CALLBACKS. + // + // DO WE NEED TO ENSURE THAT WHEN A CALLBACK IS ADDED THAT + // THE IMPLICIT TYPE MAP IS UPDATED? ONLY IF THERE ISN'T + // A VALUE IN THE IMPLICIT TYPE MAP. + // + // New algorithm: + // + // 1. Read group & element + // 2. ParseExplicitRecord + // a. Check to see if the next doublebyte is a valid datatype + // b. If the type is valid, lookup type to find the size of + // the length field. + // 3. If ParseExplicitRecord fails, ParseImplicitRecord + // a. Lookup implicit datatype + // 4. Check to see if there is a registered callback for the group,element. + // 5. If there are callbacks, read the data and call them, otherwise + // skip ahead to the next record. + // + // + + group = DataFile->ReadDoubleByte(); + element = DataFile->ReadDoubleByte(); + + doublebyte representation = DataFile->ReadDoubleByteAsLittleEndian(); + quadbyte length = 0; + mytype = DICOMParser::VR_UNKNOWN; + this->IsValidRepresentation(representation, length, mytype); + + DICOMParserMap::iterator iter = + Implementation->Map.find(DICOMMapKey(group,element)); + + VRTypes callbackType; + + if (iter != Implementation->Map.end()) + { + // + // Only read the data if there's a registered callback. + // + unsigned char* tempdata = (unsigned char*) DataFile->ReadAsciiCharArray(length); + + DICOMMapKey ge = (*iter).first; + callbackType = VRTypes(((*iter).second.first)); + + if (callbackType != mytype && + mytype != VR_UNKNOWN) + { + // + // mytype is not VR_UNKNOWN if the file is in Explicit format. + // + callbackType = mytype; + } + +#ifdef DEBUG_DICOM + this->DumpTag(this->ParserOutputFile, group, element, callbackType, tempdata, length); +#endif + + dicom_stl::pair p = *iter; + DICOMMapValue mv = p.second; + + bool doSwap = (this->ToggleByteSwapImageData ^ this->DataFile->GetPlatformIsBigEndian()) && callbackType == VR_OW; + + if (group == 0x7FE0 && + element == 0x0010 ) + { + if (doSwap) + { +#ifdef DEBUG_DICOM + dicom_stream::cout << "==============================" << dicom_stream::endl; + dicom_stream::cout << "TOGGLE BS FOR IMAGE" << dicom_stream::endl; + dicom_stream::cout << " ToggleByteSwapImageData : " << this->ToggleByteSwapImageData << dicom_stream::endl; + dicom_stream::cout << " DataFile Byte Swap : " << this->DataFile->GetPlatformIsBigEndian() << dicom_stream::endl; + dicom_stream::cout << "==============================" << dicom_stream::endl; +#endif + DICOMFile::swap2((ushort*) tempdata, (ushort*) tempdata, length/sizeof(ushort)); + } + else + { +#ifdef DEBUG_DICOM + dicom_stream::cout << "==============================" << dicom_stream::endl; + dicom_stream::cout << " AT IMAGE DATA " << dicom_stream::endl; + dicom_stream::cout << " ToggleByteSwapImageData : " << this->ToggleByteSwapImageData << dicom_stream::endl; + dicom_stream::cout << " DataFile Byte Swap : " << this->DataFile->GetPlatformIsBigEndian() << dicom_stream::endl; + + int t2 = int((0x0000FF00 & callbackType) >> 8); + int t1 = int((0x000000FF & callbackType)); + + if (t1 == 0 && t2 == 0) + { + t1 = '?'; + t2 = '?'; + } + + char ct2(t2); + char ct1(t1); + dicom_stream::cout << " Callback type : " << ct1 << ct2 << dicom_stream::endl; + + dicom_stream::cout << "==============================" << dicom_stream::endl; +#endif + } + } + else + { + if (this->DataFile->GetPlatformIsBigEndian() == true) + { + switch (callbackType) + { + case DICOMParser::VR_OW: + case DICOMParser::VR_US: + case DICOMParser::VR_SS: + DICOMFile::swap2((ushort*) tempdata, (ushort*) tempdata, length/sizeof(ushort)); + // dicom_stream::cout << "16 bit byte swap needed!" << dicom_stream::endl; + break; + case DICOMParser::VR_FL: + case DICOMParser::VR_FD: + DICOMFile::swap4((uint*) tempdata, (uint*) tempdata, length/sizeof(uint)); + // dicom_stream::cout << "Float byte swap needed!" << dicom_stream::endl; + break; + case DICOMParser::VR_SL: + case DICOMParser::VR_UL: + DICOMFile::swap4((uint*) tempdata, (uint*) tempdata, length/sizeof(uint)); + // dicom_stream::cout << "32 bit byte swap needed!" << dicom_stream::endl; + break; + case DICOMParser::VR_AT: + // dicom_stream::cout << "ATTRIBUTE Byte swap needed!" << dicom_stream::endl; + break; + default: + break; + } + } + } + + dicom_stl::vector * cbVector = mv.second; + for (dicom_stl::vector::iterator cbiter = cbVector->begin(); + cbiter != cbVector->end(); + cbiter++) + { + (*cbiter)->Execute(this, // parser + ge.first, // group + ge.second, // element + callbackType, // type + tempdata, // data + length); // length + } + + delete [] tempdata; + } + else + { + // + // Some lengths are negative, but we don't + // want to back up the file pointer. + // + if (length > 0) + { + DataFile->Skip(length); + } +#ifdef DEBUG_DICOM + this->DumpTag(this->ParserOutputFile, group, element, mytype, (unsigned char*) "Unread.", length); +#endif + } + + +} + +void DICOMParser::InitTypeMap() +{ + DICOMRecord dicom_tags[] = {{0x0002, 0x0002, DICOMParser::VR_UI}, // Media storage SOP class uid + {0x0002, 0x0003, DICOMParser::VR_UI}, // Media storage SOP inst uid + {0x0002, 0x0010, DICOMParser::VR_UI}, // Transfer syntax uid + {0x0002, 0x0012, DICOMParser::VR_UI}, // Implementation class uid + {0x0008, 0x0018, DICOMParser::VR_UI}, // Image UID + {0x0008, 0x0020, DICOMParser::VR_DA}, // Series date + {0x0008, 0x0030, DICOMParser::VR_TM}, // Series time + {0x0008, 0x0060, DICOMParser::VR_SH}, // Modality + {0x0008, 0x0070, DICOMParser::VR_SH}, // Manufacturer + {0x0008, 0x1060, DICOMParser::VR_SH}, // Physician + {0x0018, 0x0050, DICOMParser::VR_FL}, // slice thickness + {0x0018, 0x0060, DICOMParser::VR_FL}, // kV + {0x0018, 0x0088, DICOMParser::VR_FL}, // slice spacing + {0x0018, 0x1100, DICOMParser::VR_SH}, // Recon diameter + {0x0018, 0x1151, DICOMParser::VR_FL}, // mA + {0x0018, 0x1210, DICOMParser::VR_SH}, // Recon kernel + {0x0020, 0x000d, DICOMParser::VR_UI}, // Study UID + {0x0020, 0x000e, DICOMParser::VR_UI}, // Series UID + {0x0020, 0x0013, DICOMParser::VR_IS}, // Image number + {0x0020, 0x0032, DICOMParser::VR_SH}, // Patient position + {0x0020, 0x0037, DICOMParser::VR_SH}, // Patient position cosines + {0x0028, 0x0010, DICOMParser::VR_US}, // Num rows + {0x0028, 0x0011, DICOMParser::VR_US}, // Num cols + {0x0028, 0x0030, DICOMParser::VR_FL}, // pixel spacing + {0x0028, 0x0100, DICOMParser::VR_US}, // Bits allocated + {0x0028, 0x0120, DICOMParser::VR_UL}, // pixel padding + {0x0028, 0x1052, DICOMParser::VR_FL}, // pixel offset + {0x7FE0, 0x0010, DICOMParser::VR_OW} // pixel data + }; + + + int num_tags = sizeof(dicom_tags)/sizeof(DICOMRecord); + + doublebyte group; + doublebyte element; + VRTypes datatype; + + for (int i = 0; i < num_tags; i++) + { + group = dicom_tags[i].group; + element = dicom_tags[i].element; + datatype = (VRTypes) dicom_tags[i].datatype; + Implementation->TypeMap.insert(dicom_stl::pair(DICOMMapKey(group, element), datatype)); + } + +} + +void DICOMParser::SetDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector* cbVector) +{ + Implementation->Map.insert(dicom_stl::pair(DICOMMapKey(group, element), DICOMMapValue((int)datatype, cbVector))); +} + + +bool DICOMParser::CheckMagic(char* magic_number) +{ + return ( + (magic_number[0] == DICOM_MAGIC[0]) && + (magic_number[1] == DICOM_MAGIC[1]) && + (magic_number[2] == DICOM_MAGIC[2]) && + (magic_number[3] == DICOM_MAGIC[3]) + ); +} + +void DICOMParser::DumpTag(dicom_stream::ostream& out, doublebyte group, doublebyte element, VRTypes vrtype, unsigned char* tempdata, quadbyte length) +{ + + int t2 = int((0x0000FF00 & vrtype) >> 8); + int t1 = int((0x000000FF & vrtype)); + + if (t1 == 0 && t2 == 0) + { + t1 = '?'; + t2 = '?'; + } + + char ct2(t2); + char ct1(t1); + + out << "(0x"; + + out.width(4); + char prev = out.fill('0'); + + out << dicom_stream::hex << group; + out << ",0x"; + + out.width(4); + out.fill('0'); + + out << dicom_stream::hex << element; + out << ") "; + + out.fill(prev); + out << dicom_stream::dec; + out << " " << ct1 << ct2 << " "; + out << "[" << length << " bytes] "; + + if (group == 0x7FE0 && element == 0x0010) + { + out << "Image data not printed." ; + } + else + { + out << (tempdata ? (char*) tempdata : "NULL"); + } + + out << dicom_stream::dec << dicom_stream::endl; + out.fill(prev); + out << dicom_stream::dec; + + return; + +} + +void DICOMParser::ModalityTag(doublebyte, doublebyte, VRTypes, unsigned char* tempdata, quadbyte) +{ + if (!strcmp( (char*)tempdata, "MR")) + { + // this->AddMRTags(); + } + else if (!strcmp((char*) tempdata, "CT")) + { + } + else if (!strcmp((char*) tempdata, "US")) + { + } +} + +void DICOMParser::AddDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector* cbVector) +{ + DICOMParserMap::iterator miter = Implementation->Map.find(DICOMMapKey(group,element)); + if (miter != Implementation->Map.end()) + { + for (dicom_stl::vector::iterator iter = cbVector->begin(); + iter != cbVector->end(); + iter++) + { + dicom_stl::vector* callbacks = (*miter).second.second; + callbacks->push_back(*iter); + } + } + else + { + this->SetDICOMTagCallbacks(group, element, datatype, cbVector); + } +} + +void DICOMParser::AddDICOMTagCallback(doublebyte group, doublebyte element, VRTypes datatype, DICOMCallback* cb) +{ + DICOMParserMap::iterator miter = Implementation->Map.find(DICOMMapKey(group,element)); + if (miter != Implementation->Map.end()) + { + dicom_stl::vector* callbacks = (*miter).second.second; + callbacks->push_back(cb); + } + else + { + dicom_stl::vector* callback = new dicom_stl::vector; + callback->push_back(cb); + this->SetDICOMTagCallbacks(group, element, datatype, callback); + } +} + +void DICOMParser::AddDICOMTagCallbackToAllTags(DICOMCallback* cb) +{ + DICOMParserMap::iterator miter; + for (miter = Implementation->Map.begin(); + miter != Implementation->Map.end(); + miter++); + { + dicom_stl::vector* callbacks = (*miter).second.second; + callbacks->push_back(cb); + } +} + +bool DICOMParser::ParseExplicitRecord(doublebyte, doublebyte, + quadbyte& length, + VRTypes& represent) +{ + doublebyte representation = DataFile->ReadDoubleByte(); + + bool valid = this->IsValidRepresentation(representation, length, represent); + + if (valid) + { + return true; + } + else + { + represent = VR_UNKNOWN; + length = 0; + return false; + } +} + +bool DICOMParser::ParseImplicitRecord(doublebyte group, doublebyte element, + quadbyte& length, + VRTypes& represent) +{ + DICOMImplicitTypeMap::iterator iter = + Implementation->TypeMap.find(DICOMMapKey(group,element)); + represent = VRTypes((*iter).second); + // + // length? + // + length = DataFile->ReadQuadByte(); + return false; +} + + + +void DICOMParser::TransferSyntaxCallback(DICOMParser *, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) + +{ +#ifdef DEBUG_DICOM + dicom_stream::cout << "DICOMParser::TransferSyntaxCallback" << dicom_stream::endl; +#endif + + const char* TRANSFER_UID_EXPLICIT_BIG_ENDIAN = "1.2.840.10008.1.2.2"; + const char* TRANSFER_UID_GE_PRIVATE_IMPLICIT_BIG_ENDIAN = "1.2.840.113619.5.2"; + + // char* fileEndian = "LittleEndian"; + // char* dataEndian = "LittleEndian"; + + this->ToggleByteSwapImageData = false; + + if (strcmp(TRANSFER_UID_EXPLICIT_BIG_ENDIAN, (char*) val) == 0) + { +#ifdef DEBUG_DICOM + dicom_stream::cout << "EXPLICIT BIG ENDIAN" << dicom_stream::endl; +#endif + this->ToggleByteSwapImageData = true; + // + // Data byte order is big endian + // + // We're always reading little endian in the beginning, + // so now we need to swap. + } + else if (strcmp(TRANSFER_UID_GE_PRIVATE_IMPLICIT_BIG_ENDIAN, (char*) val) == 0) + { + this->ToggleByteSwapImageData = true; +#ifdef DEBUG_DICOM + dicom_stream::cout << "GE PRIVATE TRANSFER SYNTAX" << dicom_stream::endl; + dicom_stream::cout << "ToggleByteSwapImageData : " << this->ToggleByteSwapImageData << dicom_stream::endl; +#endif + } + else + { + } +} + +void DICOMParser::GetGroupsElementsDatatypes(dicom_stl::vector& groups, + dicom_stl::vector& elements, + dicom_stl::vector& datatypes) +{ + groups.clear(); + elements.clear(); + datatypes.clear(); + + dicom_stl::vector::iterator giter; // = this->Groups.begin(); + dicom_stl::vector::iterator eiter; // = this->Elements.begin(); + dicom_stl::vector::iterator diter; // = this->Datatypes.begin(); + + for (giter = this->Implementation->Groups.begin(), eiter = this->Implementation->Elements.begin(), diter = this->Implementation->Datatypes.begin(); + giter != this->Implementation->Groups.end(), eiter != this->Implementation->Elements.end(), diter != this->Implementation->Datatypes.end(); + giter++, eiter++, diter++) + { + groups.push_back(*giter); + elements.push_back(*eiter); + datatypes.push_back(*diter); + } +} + +void DICOMParser::ClearAllDICOMTagCallbacks() +{ + DICOMParserMap::iterator mapIter; + + for (mapIter = this->Implementation->Map.begin(); + mapIter != this->Implementation->Map.end(); + mapIter++) + { + dicom_stl::pair mapPair = *mapIter; + DICOMMapValue mapVal = mapPair.second; + dicom_stl::vector* cbVector = mapVal.second; + + delete cbVector; + } + + this->Implementation->Map.clear(); +} + +DICOMParser::DICOMParser(const DICOMParser&) +{ + dicom_stream::cerr << "DICOMParser copy constructor should not be called!" << dicom_stream::endl; +} + +void DICOMParser::operator=(const DICOMParser&) +{ + dicom_stream::cerr << "DICOMParser assignment operator should not be called!" << dicom_stream::endl; +} + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif diff --git a/Utilities/DICOMParser/DICOMParser.h b/Utilities/DICOMParser/DICOMParser.h new file mode 100644 index 0000000..0b57b6e --- /dev/null +++ b/Utilities/DICOMParser/DICOMParser.h @@ -0,0 +1,265 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMParser.h,v $ + Language: C++ + Date: $Date: 2003/08/27 18:49:00 $ + Version: $Revision: 1.8 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __DICOMParser_h_ +#define __DICOMParser_h_ + + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4503 ) +#pragma warning ( disable : 4710 ) +#pragma warning ( disable : 4702 ) +#pragma warning ( push, 3 ) +#endif + + +#include +#include +#include + +#include "DICOMConfig.h" +#include "DICOMFile.h" +#include "DICOMTypes.h" +#include "DICOMParserMap.h" + +class DICOMCallback; +template class DICOMMemberCallback; + +//DICOM_EXPIMP_TEMPLATE template class DICOM_EXPORT dicom_stl::vector; + +class DICOMParserImplementation; + +// +// We should keep a map with the implicit types for the groups and elements +// separate from the callbacks. We can use this for the implicit types. +// +// + +class DICOM_EXPORT DICOMParser +{ + public: + + // + // Default constructor + // + DICOMParser(); + + // + // Default destructor. + // + virtual ~DICOMParser(); + + // + // Opens a file and initializes the parser. + // + bool OpenFile(const dicom_stl::string& filename); + + // + // Return the name of the file last processed. + // + const dicom_stl::string& GetFileName(); + + // + // This method kicks off the parser. + // OpenFile needs to be called first. + // + bool ReadHeader(); + + // + // Static method that returns true if DICOMFile is opened + // to a file that contains a DICOM image. + // + static bool IsDICOMFile(DICOMFile* file); + + bool IsDICOMFile() + { + if (!this->DataFile) + { + return false; + } + return DICOMParser::IsDICOMFile(this->DataFile); + } + + // + // Static method that checks the DICOM magic number. + // + static bool CheckMagic(char* magic_number); + + // + // Defined DICOM types. + // + enum VRTypes + { + VR_UNKNOWN = 0x0, + VR_OB=0x424f, // Other byte string (string of bytes, insensitive to byte order) + VR_AW=0x5741, + VR_AE=0x4541, // Application Entity (char string) + VR_AS=0x5341, // Age string (char string) + VR_CS=0x5343, // Code string (char string, leading/trailing spaces insignificant) + VR_UI=0x4955, // UID (character string) + VR_DA=0x4144, // Date (char string) + VR_DS=0x5344, // Decimal string (char string representing a fixed/floating pt number) + VR_DT=0x5444, // Date Time (char string) + VR_IS=0x5349, // Integer string (char string representing an integer) + VR_LO=0x4f4c, // Long string (character string padded with leading/trailing spaces) + VR_LT=0x544c, // Long text (character string with one or more paragraphs.) + VR_OW=0x574f, // Other word string (sensitive to byte order, transfer syntax) + VR_PN=0x4e50, // Person name (character string) + VR_ST=0x5453, // Short text (character string, one or more paragraphs) + VR_TM=0x4d54, // Time (character string) + VR_UN=0x4e55, + VR_UT=0x5455, // Unlimited text (character string) + VR_SQ=0x5153, // Sequence of items + VR_SH=0x4853, // Short string (character string with leading/trailing spaces). + VR_FL=0x4c46, // Floating point single precision + VR_SL=0x4c53, // Signed long, (signed 32bits, 2's complement form.) + VR_AT=0x5441, // Attribute tag (ordered pair 16 bit unsigned) + VR_UL=0x4c55, // Unsigned long (unsigned 32 bits) + VR_US=0x5355, // Unsigned short (unsigned 16 bits) + VR_SS=0x5353, // Signed short, (signed 16bits, 2's complement) + VR_FD=0x4446 // Floating point double precision + }; + + // + // Callback for the modality tag. + // + void ModalityTag(doublebyte group, doublebyte element, VRTypes datatype, unsigned char* tempdata, quadbyte length); + + void SetDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector* cbVector); + void AddDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector* cbVector); + void AddDICOMTagCallback (doublebyte group, doublebyte element, VRTypes datatype, DICOMCallback* cb); + void AddDICOMTagCallbackToAllTags(DICOMCallback* cb); + + DICOMFile* GetDICOMFile() + { + return this->DataFile; + } + + void ClearAllDICOMTagCallbacks(); + + + void TransferSyntaxCallback(DICOMParser *parser, + doublebyte, + doublebyte, + DICOMParser::VRTypes, + unsigned char* val, + quadbyte) ; + + void GetGroupsElementsDatatypes(dicom_stl::vector& groups, + dicom_stl::vector& elements, + dicom_stl::vector& datatypes); + + protected: + + bool ParseExplicitRecord(doublebyte group, doublebyte element, + quadbyte& length, + VRTypes& represent); + + bool ParseImplicitRecord(doublebyte group, doublebyte element, + quadbyte& length, + VRTypes& represent); + // + // Print a tag. + // + // void DumpTag(doublebyte group, doublebyte element, VRTypes datatype, unsigned char* data, quadbyte length); + void DumpTag(dicom_stream::ostream& out, doublebyte group, doublebyte element, VRTypes vrtype, unsigned char* tempdata, quadbyte length); + + struct DICOMRecord + { + doublebyte group; + doublebyte element; + VRTypes datatype; + }; + + // + // Check to see if the type is a valid DICOM type. If not, figure + // out the right thing to do next (i.e. compute the element length). + // + bool IsValidRepresentation(doublebyte rep, quadbyte& len, VRTypes &mytype); + + // + // Reads a record. + // + void ReadNextRecord(doublebyte& group, doublebyte& element, DICOMParser::VRTypes& mytype); + + // + // Sets up the type map. + // + void InitTypeMap(); + + // + // Flags for byte swaping header values and + // image data. + // + bool ByteSwap; + bool ByteSwapData; + + // + // Stores a map from pair keys to + // values of pair, datatype> + // + // DICOMParserMap Map; + + // + // Stores a map from pair keys to + // values of datatype. We use this to store the + // datatypes for implicit keys that we are + // interested in. + // + // DICOMImplicitTypeMap TypeMap; + + // + // Used for outputting debug information. + // + dicom_stream::ofstream ParserOutputFile; + + // + // Pointer to the DICOMFile we're parsing. + // + DICOMFile* DataFile; + dicom_stl::string FileName; + + bool ToggleByteSwapImageData; + + //dicom_stl::vector Groups; + //dicom_stl::vector Elements; + //dicom_stl::vector Datatypes; + + DICOMMemberCallback* TransferSyntaxCB; + + // + // Implementation contains stl templated classes that + // can't be exported from a DLL in Windows. We hide + // them in the implementation to get rid of annoying + // compile warnings. + // + DICOMParserImplementation* Implementation; + + private: + DICOMParser(const DICOMParser&); + void operator=(const DICOMParser&); +}; + + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif + +#endif // __DICOMParser_h_ diff --git a/Utilities/DICOMParser/DICOMParserMap.h b/Utilities/DICOMParser/DICOMParserMap.h new file mode 100644 index 0000000..c45210d --- /dev/null +++ b/Utilities/DICOMParser/DICOMParserMap.h @@ -0,0 +1,141 @@ +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMParserMap.h,v $ + Language: C++ + Date: $Date: 2003/08/27 18:49:00 $ + Version: $Revision: 1.5 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef __DICOM_PARSER_MAP__H_ +#define __DICOM_PARSER_MAP__H_ + +#ifdef _MSC_VER +#pragma warning ( disable : 4514 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4503 ) +#pragma warning ( disable : 4710 ) +#pragma warning ( disable : 4702 ) +#pragma warning ( push, 3 ) +#endif + +#include +#include + +#include "DICOMConfig.h" + +class DICOMCallback; + +// +// Structure that implements a compare operator for +// a pair of doublebytes. This is used when comparing +// group, element pairs. +// +struct group_element_compare +{ + bool operator() (const dicom_stl::pair p1, const dicom_stl::pair p2) const + { + if (p1.first < p2.first) + { + return true; + } + else if (p1.first == p2.first) + { + if (p1.second < p2.second) + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } +}; + +// +// Typedef a pair of doublebytes +// +typedef dicom_stl::pair DICOMMapKeyOverride; + +// DICOM_EXPIMP_TEMPLATE template struct DICOM_MAP_EXPORT dicom_stream::pair; +// +// Subclass of a pair of doublebytes to make +// type names shorter in the code. +// +class DICOMMapKey : public DICOMMapKeyOverride +{ + public: + DICOMMapKey(doublebyte v1, doublebyte v2) : + dicom_stl::pair (v1, v2) + { + + } + +}; + +// +// Typedef of a pair of doublebyte, vector. +// +typedef dicom_stl::pair*> DICOMMapValueOverride; + + +// DICOM_EXPIMP_TEMPLATE template struct DICOM_MAP_EXPORT dicom_stream::pair*>; + +// +// Subclass of pair doublebyte, vector. +// Makes types shorter in the code. +// +class DICOMMapValue : public DICOMMapValueOverride +{ + public: + DICOMMapValue() : dicom_stl::pair*>() {}; + + DICOMMapValue(doublebyte v1, dicom_stl::vector * v2) : + dicom_stl::pair*>(v1, v2) + { + + } +}; + + +// DICOM_EXPIMP_TEMPLATE template class DICOM_MAP_EXPORT dicom_stream::map; + +// +// Subclass of the particular map we're using. Again, +// makes type specifiers shorter in the code. +// +class DICOMParserMap : + public dicom_stl::map +{ + +}; + +typedef doublebyte DICOMTypeValue; + +// DICOM_EXPIMP_TEMPLATE template class dicom_stream::map; + +class DICOMImplicitTypeMap : + public dicom_stl::map +{ + +}; + +#ifdef _MSC_VER +#pragma warning ( pop ) +#endif + +#endif diff --git a/Utilities/DICOMParser/DICOMTypes.h b/Utilities/DICOMParser/DICOMTypes.h new file mode 100644 index 0000000..f53436f --- /dev/null +++ b/Utilities/DICOMParser/DICOMTypes.h @@ -0,0 +1,31 @@ + +/*========================================================================= + + Program: DICOMParser + Module: $RCSfile: DICOMTypes.h,v $ + Language: C++ + Date: $Date: 2005/07/26 20:02:22 $ + Version: $Revision: 1.5 $ + + Copyright (c) 2003 Matt Turek + All rights reserved. + See Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + + +#ifndef __DICOM_TYPES_H_ +#define __DICOM_TYPES_H_ + +typedef unsigned short doublebyte; +typedef int quadbyte; +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned int uint; + + +#endif diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt new file mode 100644 index 0000000..a4b606f --- /dev/null +++ b/Utilities/Doxygen/CMakeLists.txt @@ -0,0 +1,45 @@ +# +# Build the documentation +# +INCLUDE (${CMAKE_ROOT}/Modules/Documentation.cmake OPTIONAL) + +IF (BUILD_DOCUMENTATION) + OPTION(DOXYGEN_SHORT_NAMES "Build Doxygen of VTK using short file names" OFF) + MARK_AS_ADVANCED(DOXYGEN_SHORT_NAMES) + IF(DOXYGEN_SHORT_NAMES) + SET(DOXYGEN_SHORT_NAMES YES) + ELSE(DOXYGEN_SHORT_NAMES) + SET(DOXYGEN_SHORT_NAMES NO) + ENDIF(DOXYGEN_SHORT_NAMES) + + # + # Configure the script and the doxyfile, then add target + # + IF(NOT DOT_PATH) + GET_FILENAME_COMPONENT(DOT_PATH ${DOT} PATH) + ENDIF(NOT DOT_PATH) + + CONFIGURE_FILE( + ${VTK_SOURCE_DIR}/Utilities/Doxygen/doxyfile.in + ${VTK_BINARY_DIR}/Utilities/Doxygen/doxyfile) + + CONFIGURE_FILE( + ${VTK_SOURCE_DIR}/Utilities/Doxygen/doc_makeall.sh.in + ${VTK_BINARY_DIR}/Utilities/Doxygen/doc_makeall.sh) + + ADD_CUSTOM_TARGET(DoxygenDoc + ${BASH} + ${VTK_BINARY_DIR}/Utilities/Doxygen/doc_makeall.sh) + +ENDIF (BUILD_DOCUMENTATION) + +INCLUDE (${VTK_SOURCE_DIR}/Utilities/Doxygen/LocalUserOptions.cmake OPTIONAL) + +IF(NOT VTK_INSTALL_NO_DOCUMENTATION) + INSTALL_FILES(${VTK_INSTALL_DOXYGEN_DIR} "\\.css$") + INSTALL_FILES(${VTK_INSTALL_DOXYGEN_DIR} "\\.gif$") + INSTALL_FILES(${VTK_INSTALL_DOXYGEN_DIR} "\\.html$") + INSTALL_FILES(${VTK_INSTALL_DOXYGEN_DIR} "\\.pl$") + INSTALL_FILES(${VTK_INSTALL_DOXYGEN_DIR} "\\.stop$") + INSTALL_FILES(${VTK_INSTALL_DOXYGEN_DIR} .txt authors doc_readme) +ENDIF(NOT VTK_INSTALL_NO_DOCUMENTATION) diff --git a/Utilities/Doxygen/authors.txt b/Utilities/Doxygen/authors.txt new file mode 100644 index 0000000..9154bad --- /dev/null +++ b/Utilities/Doxygen/authors.txt @@ -0,0 +1,59 @@ +ahrens: Ahrens, Jim (ahrens@lanl.gov) +alyassin: Alyassin, Majeid (alyassin@crd.ge.com) +amaclean: Maclean, Andrew (a.maclean@cas.edu.au) +andy: Cedilnik, Andy (andy.cedilnik@kitware.com) +atwilso: Wilson, Andy (atwilso@sandia.gov) +avila, sobie: Avila, Lisa (lisa.avila@kitware.com) +barre: Barre, Sebastien (sebastien.barre@kitware.com) +berk: Geveci, Berk (berk.geveci@kitware.com) +biddi: Biddiscombe, John (jbiddiscombe@skippingmouse.co.uk) +blezek: Blezek, Dan (blezek@crd.ge.com) +blue: Blue, Rusty (blue@crd.ge.com) +bnwylie: Wylie, Brian (bnwylie@sandia.gov) +bruno: Bruno, Jeannette (bruno@crd.ge.com) +childs: Childs, Hank (childs@forum.llnl.gov) +citrit: Citrini, Tom (citrit@rpi.edu) +clinton: Stimpson, Clinton (clinton@elemtech.com) +cpbotha: Botha, Charl (c.p.botha@its.tudelft.nl) +david.cole: Cole, David (David.Cole@kitware.com) +davisje: Davis, Jon (davisje@crd.ge.com) +dcthomp: Thompson, David (dcthomp@sandia.gov) +dean: Inglis, Dean (dean.inglis@camris.ca) +dgobbi: Gobbi, David (dgobbi@imaging.robarts.ca) +dhroger: Rogers, David (dhroger@sandia.gov) +fbertel: Bertel, Francois (francois.bertel@kitware.com) +gering: Gering, David (gering@ai.mit.edu) +guimond: Guimond, Alexandre (guimond@bwh.harvard.edu) +halazar: Halle, Michael (halazar@media.mit.edu) +hammondr: Hammond, Rich (hammondr@crd.ge.com ) +heiland: Heiland, Randy (heiland@ncsa.uiuc.edu) +henderson: Henderson, Amy (amy.henderson@kitware.com) +hoffman: Hoffman, Bill (bill.hoffman@kitware.com) +ibanez: Ibanez, Luis (luis.ibanez@kitware.com) +jlee: Lee, Jeff (jeff@cdnorthamerica.com) +kellyae: Kelly, Ann (kellyae@crd.ge.com) +king: King, Brad (brad.king@kitware.com) +kmorel: Moreland, Kenneth (kmorel@sandia.gov) +lafisk: Fisk, Lee Ann (lafisk@sandia.gov) +lawcc: Law, Charles (charles.law@kitware.com) +lorensen: Lorensen, Bill (lorensen@crd.ge.com) +malaterre: Malaterre, Mathieu (mathieu.malaterre@kitware.com) +martink, lymbdemo: Martin, Ken (ken.martin@kitware.com) +millerjv: Miller, Jim (millerjv@crd.ge.com) +montanar: Montanaro, Skip (montanaro@crd.ge.com) +mumit: Mumit, Khan (khan@nanotech.wisc.edu) +pppebay: Pébay, Philippe (pppebay@ca.sandia.gov) +prabhu: Ramachandran, Prabhu (prabhu_r@users.sourceforge.net) +paulsen: Paulsen, Rasmus Reinhold (rrp@imm.dtu.dk) +rick: Avila, Rick (rick.avila@kitware.com) +slack: Slack, Christopher (Christopher.Slack@amermsx.med.ge.com) +starreveld: Starreveld, Yves (ystarrev@julian.uwo.ca) +timh: Hutton, Tim (T.Hutton@eastman.ucl.ac.uk) +tpan: Pan, Tony (tpan@crd.ge.com) +turek: Turek, Matt (turek@crd.ge.com) +turner: Turner, Wes (turner@crd.ge.com) +utkarsh: Ayachit, Utkarsh (utkarsh.ayachit@kitware.com) +volpe: Volpe, Christopher (cvolpe@ara.com) +warfield: Warfield, Simon (warfield@bwh.harvard.edu) +will, schroede: Schroeder, Will (will.schroeder@kitware.com) +yamrom: Yamrom, Boris (yamrom@crd.ge.com) diff --git a/Utilities/Doxygen/doc_class2example.pl b/Utilities/Doxygen/doc_class2example.pl new file mode 100644 index 0000000..0c405e2 --- /dev/null +++ b/Utilities/Doxygen/doc_class2example.pl @@ -0,0 +1,846 @@ +#!/usr/bin/env perl +# Time-stamp: <2004-06-09 11:12:38 barre> +# +# Build cross-references between classes and examples +# +# barre : Sebastien Barre +# +# 0.81 (barre) : +# - add --baselinedir d : use 'd' as baseline directory +# - add --baselineicon f: use 'f' as icon file to report that file has +# baseline picture +# - add --baselinelink l: use 'l' as baseline link to picture +# - add --baselinelinksuffix s : suffix string to append +# to --baselinelink + filename +# - add --datamatch s : use string s to match any usage of data files +# +# 0.8 (barre) : +# - more robust code: comments are removed from files before parsing +# and several identifier per lines are now supported (at last). +# - add --datamatch s : use string s to match any usage of data files +# - add --dataicon f : use f as icon file to report that file makes use +# of data files +# +# 0.74 (barre) : +# - use common build_page_doc proc +# +# 0.73 (barre) : +# - add --linksuffix s : suffix string to append to --link + filename +# +# 0.72 (barre) : +# - add --project name : project name, used to uniquify +# - add slightly changed the way --link are created +# +# 0.71 (barre) : +# - add .cpp and .cc extension to the C++ parser regexp +# +# 0.7 (barre) : +# - update to match the new VTK 4.0 tree +# - change default --dirs so that it can be launched from Utilities/Doxygen +# - change default --to so that it can be launched from Utilities/Doxygen +# - add Java support +# - add --label str : use string as label in class page +# - add --title str : use string as title in "Related Pages" +# - add --dirmatch str : use string to match the directory name holding files +# - add --unique str : use string as a unique page identifier (otherwise MD5) +# +# 0.6 (barre) : +# - the "class to example" page is now split in different pages +# - use --weight to increase or decrease the maximum weight of a page +# +# 0.55 (barre) : +# - change default --to to '../vtk-doxygen' to comply with Kitware's doxyfile +# +# 0.54 (barre) : +# - change doxygen command style from \ to @ to match javadoc, autodoc, etc. +# +# 0.53 (barre) : +# - change default --to to '../vtk-dox' +# +# 0.52 (barre) : +# - rename -l option to --link, add a parameter to preprend in front of +# the example location/filename. +# +# 0.51 (barre) : +# - fix O_TEXT flag problem +# - switch to Unix CR/LF format +# +# 0.5 (barre) : +# - removed version extraction feature (moved to another script) +# +# 0.4 (barre) : +# - change (warning) default --to to '../vtk2' because I ruined my own +# VTK distrib too many times :( +# - change (warning) --to is now a path to a destination directory, and +# no more a path to the destination doxygen file. The headers to update +# will logically be searched here, while the examples to process are +# searched in the directory where the script is launched +# +# 0.3 (barre) +# - add '--parser' option to use specific parser only +# +# 0.2 (barre) +# - use vtkVersion.h to fill the main page (@mainpage) with version/revision +# => comment/remove PROJECT_NUMBER from your doxygen config file (doxyfile) +# - add web URL to main page +# - fix small "uninitialized variable" warning +# +# 0.1 (barre) +# - first release (-l does not work for the moment) + +use Carp; +use Data::Dumper; +use Digest::MD5 qw(md5 md5_hex md5_base64); +use Getopt::Long; +use Fcntl; +use File::Basename; +use File::Find; +use strict; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.81, $0, "Sebastien Barre"); +$PROGNAME =~ s/^.*[\\\/]//; +print "$PROGNAME $VERSION, by $AUTHOR\n"; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want : "verbose" => 1 for default verbose mode) + +my %default = + ( + baselineicon => "pic.gif", + baselinelinksuffix => "", + dataicon => "paper-clip.gif", + dirmatch => "^Examples\$", + dirs => ["../.."], + label => "Examples", + limit => 20, + linksuffix => "", + project => "VTK", + store => "doc_VTK_class2examples.dox", + title => "Class To Examples", + to => "../../../VTK-doxygen", + unique => "e", + weight => 90000 + ); + +# ------------------------------------------------------------------------- +# Matchers and parsers : +# +# $eliminate_matcher : regexp matching the names of the 'fake' classes +# that shall be eliminated/ignored, +# %parsers : hash defining each parser by associating +# parser_name => [filename_matcher, func1, func2]. +# $parser_name : language identifier (Tcl, C++, Python, etc.), +# $filename_matcher : regexp matching the filenames belonging to the language, +# @$func1 : function called when a filename is matched, +# - receives the contents of the file as a reference to a +# string, +# - modifies this contents by removing the comments. +# @$func2 : function called when a filename is matched, +# - receives the contents of the file as a reference to a +# string (or the result of func1 if exists), +# - returns an array of unique class names that have been +# recognized/matched in the file contents. + +my $eliminate_matcher = '^vtkCommand$'; + +my %parsers = ( + "Tcl" => ['\.tcl$', \&rm_tcl_comments, \&parse], + "C++" => ['\.c(xx|pp|c)$', \&rm_cpp_comments, \&parse], + "Java" => ['\.java$', \&rm_cpp_comments, \&parse], + "Python" => ['\.py$', \&rm_tcl_comments, \&parse] + ); + +sub rm_tcl_comments { + my $ref = shift; + $$ref =~ s/#.*?$//gms; +} + +sub rm_cpp_comments { + my $ref = shift; + $$ref =~ s/\/\*.*?\*\/|\/\/.*?$|#(include|define|if).*?$//gms; +} + +sub rm_no_comments { + my $ref = shift; +} + +# Parser (seems to work with all languages for the moment) + +sub unique { + my ($ref, %uniques) = (shift, ()); + foreach my $item (@$ref) { + $uniques{$item}++; + } + return keys %uniques; +} + +sub parse { + my $ref = shift; + my @matches = $$ref =~ /\b(vtk[A-Z0-9][A-Za-z0-9]+)[^"]/gms; + return unique(\@matches); +} + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +# Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "verbose|v", "baselinedir=s", "baselineicon=s", "datamatch=s", "baselinelink=s", "baselinelinksuffix=s", "dataicon=s", "dirmatch=s", "label=s", "limit=i", "link=s", "linksuffix=s", "project=s", "store=s", "title=s", "to=s", "unique=s", "weight=i", "parser=s@"); + +my $available_parser = join(", ", keys %parsers); + +if (exists $args{"help"}) { + print <<"EOT"; +by $AUTHOR +Usage : $PROGNAME [--help] [--verbose|-v] [--baselinedir path] [--baselineicon filename] [--baselinelink url] [--baselinelinksuffix url] [--datamatch string] [--dataicon filename] [--dirmatch string] [--label string] [--limit n] [--link url] [--linksuffix string] [--parser name] [--store file] [--title string] [--to path] [--weight n] [directories...] + --help : this message + --verbose|-v : verbose (display filenames/classes while processing) + --baselinedir d : use 'd' as baseline directory + --baselineicon f: use 'f' as icon file to report that file has baseline picture + --baselinelink l: use 'l' as baseline link to picture + --baselinelinksuffix s : suffix string to append to --baselinelink + filename + --datamatch s : use string s to match any usage of data files + --dataicon f : use 'f as icon file to report that file makes use of data files + --dirmatch str : use string to match the directory name holding files (default: $default{dirmatch}) + --label str : use string as label in class page (default: $default{label}) + --limit n : limit the number of examples per parser type (default: $default{limit}) + --link path : link to example files (and prepend path) + --linksuffix s : suffix string to append to --link + filename + --title str : use string as title in "Related Pages" (default: $default{title}) + --parser name : use specific parser only (available : $available_parser) + --project name : project name, used to uniquify (default: $default{project}) + --store file : use 'file' to store xrefs (default: $default{store}) + --to path : use 'path' as destination directory (default : $default{to}) + --unique str : use string as a unique page identifier among "Class To..." pages (otherwise MD5) (default : $default{unique}) + --weight n : use 'n' as an approximation of the maximum page weight (default : $default{weight}) + +Example: + $PROGNAME --verbose + $PROGNAME --dirmatch "^Testing$" --label "Tests" --title "Class To Tests" --store "doc_class2tests.dox" --unique "t" +EOT + exit; +} + +$args{"verbose"} = 1 if exists $default{"verbose"}; +$args{"baselinedir"} =~ s/[\\\/]*$// if exists $args{"baselinedir"}; +$args{"baselineicon"} = $default{"baselineicon"} + if ! exists $args{"baselineicon"}; +$args{"baselinelink"} = $default{"baselinelink"} + if ! exists $args{"baselinelink"} && exists $default{"baselinelink"}; +$args{"baselinelink"} =~ s/[\\\/]*$// if exists $args{"baselinelink"}; +$args{"baselinelinksuffix"} = $default{"baselinelinksuffix"} + if ! exists $args{"baselinelinksuffix"}; +$args{"dataicon"} = $default{"dataicon"} if ! exists $args{"dataicon"}; +$args{"dirmatch"} = $default{"dirmatch"} if ! exists $args{"dirmatch"}; +$args{"label"} = $default{"label"} if ! exists $args{"label"}; +$args{"limit"} = $default{"limit"} if ! exists $args{"limit"}; +$args{"link"} = $default{"link"} if ! exists $args{"link"} && exists $default{"link"}; +$args{"link"} =~ s/[\\\/]*$// if exists $args{"link"}; +$args{"linksuffix"} = $default{"linksuffix"} if ! exists $args{"linksuffix"}; +$args{"project"} = $default{"project"} if ! exists $args{"project"}; +$args{"store"} = $default{"store"} if ! exists $args{"store"}; +$args{"title"} = $default{"title"} if ! exists $args{"title"}; +$args{"to"} = $default{"to"} if ! exists $args{"to"}; +$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"}; +$args{"unique"} = $default{"unique"} if ! exists $args{"unique"}; +$args{"weight"} = $default{"weight"} if ! exists $args{"weight"}; + +# Select parsers + +my @parsers; +if (exists $args{"parser"}) { + foreach my $parser (@{$args{"parser"}}) { + if (exists $parsers{$parser}) { + push @parsers, $parser; + } else { + carp "$PROGNAME: unknown parser : $parser\n"; + } + } +} else { + @parsers = keys %parsers; +} + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Collect unique non-intersecting (top) examples' directories recursively +# Save current path (pwd) to avoid the ::prune bug + +print "Collecting files...\n"; + +push @ARGV, @{$default{"dirs"}} if !@ARGV; +my (%seen, @dirs); + +my $cwd = Cwd::cwd(); + +foreach my $file (@ARGV) { + find sub { + if (-d $_ && + $_ ne "CVS" && + basename($File::Find::name) =~ m/$args{"dirmatch"}/i) { + # my ($dev, $ino) = stat $_; + push @dirs, $File::Find::name; + # if ! $seen{$dev, $ino}++; + # once we are in a "examples directory", don't descend anymore + $File::Find::prune = 1; + } + }, $file; +} + +chdir($cwd); + +# ------------------------------------------------------------------------- +# Collect files within directories recursively + +my @files; +foreach my $dir (@dirs) { + find sub { + push @files, $File::Find::name if -f $_; + }, $dir; +} + +# ------------------------------------------------------------------------- +# Select unique files matching available parsers + +my @parsable; +foreach my $parser (@parsers) { + foreach my $file (@files) { + if ($file =~ m/$parsers{$parser}->[0]/) { + # my ($dev, $ino) = stat $file; + push @parsable, $file; + # if ! $seen{$dev, $ino}++; + } + } +} + +@parsable = sort @parsable; + +print " => ", scalar @parsable, " file(s) collected in ", time() - $start_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Parse files and build xref + +# %xref is a hash : xref{$class}{$parser}{$file} +# Ex: xref{"vtkPoints"}{"Tcl"}{"examplesTcl/foo.tcl"} +# xref{"vtkPoints"}{"Tcl"}{"graphics/examplesTcl/bar.tcl"} +# xref{"vtkNormals"}{"C++"}{"test.cxx"} + +my %xref; + +# %shorter_filename is a hash associating a filename to its shorter +# counterpart where any leading component matching the name of a directory +# being browsed have been removed. + +my %shorter_filename; + +# %use_data is a hash associating a filename to a flag (1) when the +# file makes use of data files (i.e. the contents of the file matches +# $args{"datamatch"}). + +my %use_data; + +# %baseline_picture is a hash associating a filename to the relative path +# to its baseline picture (relative to --baselinedir). + +my %baseline_picture; + +print "Parsing files...\n"; + +my $intermediate_time = time(); + +# slurp mode + +my $oldslurp = $/; +undef $/; + +foreach my $filename (@parsable) { + + # Read entire file into an array of lines + + sysopen(FILE, $filename, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $filename\n"; + my $file = ; + close(FILE); + + # Submit the contents of the file to the corresponding parser + + foreach my $parser (@parsers) { + if ($filename =~ m/$parsers{$parser}->[0]/) { + $parsers{$parser}->[1]->(\$file); + my @classes = $parsers{$parser}->[2]->(\$file); + printf("%7s: %2d | ", $parser, scalar @classes) + if exists $args{"verbose"}; + #print "[", join(", ", @classes), "]" if exists $args{"verbose"}; + if (@classes) { + $shorter_filename{$filename} = $filename; + # print "(", join(", ", sort @classes), ") " if @classes; + foreach my $class (@classes) { + $xref{$class}{$parser}{$filename}++; + } + } + } + } + print "=> ", $filename, "\n" if exists $args{"verbose"}; + + # Shorten filename if it has been added + + if (exists $shorter_filename{$filename}) { + foreach my $dir (@ARGV) { + last if $shorter_filename{$filename} =~ s/$dir//; + } + + # Check for baseline picture + + if (exists $args{"baselinedir"}) { + my ($name, $dir, $ext) = + fileparse($shorter_filename{$filename}, '\..*'); + my @dirs = split('/', $dir); + my $pic = $dirs[1] . "/$name.png"; + $baseline_picture{$filename} = $pic + if -e $args{"baselinedir"} . "/$pic"; + } + } + + # Check for data + + $use_data{$filename} = 1 + if exists $args{"datamatch"} && $file =~ m/$args{"datamatch"}/ms; +} + +$/ = $oldslurp; + +print " => ", scalar @parsable, " file(s) parsed in ", time() - $intermediate_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Eliminate some 'fake' classes + +print "Eliminating some classes...\n"; + +$intermediate_time = time(); +my @eliminated = (); + +foreach my $class (keys %xref) { + if ($class =~ m/$eliminate_matcher/) { + print " $class\n" if exists $args{"verbose"}; + delete($xref{$class}); + push @eliminated, $class; + } +} + +print " => ", scalar @eliminated, " class(es) eliminated (", join(", ", @eliminated), ") in ", time() - $intermediate_time, " s.\n"; + +# ------------------------------------------------------------------------- +# We need to locate the C++ header of each class to add a link from +# that header to the example page. We also remove orphan classes with +# no headers. + +# %headers is a hash associating a class name to the location of its header. +# ex: $headers{"vtkPoints"} = "Common/vtkPoints.h" +# %headers_not_found is a hash associating a class name to a flag that is +# true (1) if the location of its header has not been found. + +print "Locating headers to update...\n"; + +$intermediate_time = time(); +my (%headers, %headers_not_found); + +# Let's state that no headers have been found at the moment + +foreach (keys %xref) { + $headers_not_found{$_} = 1; +} +my $headers_not_found_nb = scalar keys %headers_not_found; + +$cwd = Cwd::cwd(); + +find sub { + if ($headers_not_found_nb == 0) { + # All headers have been found, let's stop descending the tree + $File::Find::prune = 1; + + } elsif (-f $_ && $_ =~ /^(vtk[A-Z0-9][A-Za-z0-9]+)\.h$/) { + # A class header has been found, let's check if it matches one pf + # the class in xref + my $class = $1; + if (exists $headers_not_found{$class}) { + print " $class : $File::Find::name\n" if exists $args{"verbose"}; + $headers{$class} = $File::Find::name; + $headers_not_found_nb--; + delete($headers_not_found{$class}); + } + } +}, $args{"to"}; + +chdir($cwd); + +# Collect these classes that have not been associated to a header and +# remove them from xref. + +my @still_not_found = keys %headers_not_found; +foreach my $not_found (@still_not_found) { + print " $not_found : not found (removed)\n" if exists $args{"verbose"}; + delete($xref{$not_found}); +} + +print " => ", scalar keys %headers, " found, ", scalar @still_not_found, " orphan class(es) removed (", join(", ", @still_not_found), ") in ", time() - $intermediate_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Build the page summary documentation + +# $indent is the indentation string + +my $indent = " "; + +# @words is the array of words to document + +my @words = sort keys %xref; + +# $header is the Doxygen string summarizing what has been documented as well +# as the credits. + +my $header; +my (@summary, @credits, @legend); + +push @summary, + " - " . scalar @words . " class(es) in " . + scalar @parsable . " file(s) from directories matching \@c " . $args{"dirmatch"} . " on " . localtime(); + +push @summary, + " - " . scalar @parsers . " parser(s) : [" . join(", ", @parsers) . "]"; + +push @summary, + " - at most " . $args{"limit"} . " file(s) per parser"; + +push @credits, + "\@version $VERSION", + "\@author \@c $PROGNAME, by $AUTHOR"; + +$header = $indent . join("\n$indent", @summary) . "\n\n" . + $indent . join("\n$indent", @credits) . "\n\n"; + +my $footer; + +if (exists $args{"datamatch"}) { + push @legend, + "- : the corresponding file uses data files."; + # hack so that the image is automatically copied to the doc dir + $footer .= " \@image html " . $args{"dataicon"} . "\n"; +} + +if (exists $args{"baselinedir"}) { + push @legend, + "- : the corresponding file has a baseline picture (click to display)"; + # hack so that the image is automatically copied to the doc dir + $footer .= " \@image html " . $args{"baselineicon"} . "\n"; +} + +if (scalar @legend) { + unshift @legend, "\@par Legend:"; + $header .= $indent . join("\n$indent", @legend) . "\n\n"; +} + +# ------------------------------------------------------------------------- +# Index to class + +print "Building page doc...\n"; + +# $prefix is a unique prefix that is appended to each link + +my $prefix = "c2_" . $args{"project"} . "_"; +if (exists $args{"unique"}) { + $prefix .= $args{"unique"}; +} else { + $prefix .= md5_hex($args{"label"} . $args{"title"}); +} +$prefix = lc($prefix); + +# word_section_name returns the short string describing a word section + +sub word_section_name { + my ($word) = @_; + return "\@anchor ${prefix}_$word\n$indent$word"; +} + +# word_section_doc returns the doxygen doc for a word + +sub word_section_doc { + my ($word) = @_; + my @temp; + foreach my $parser (sort keys %{$xref{$word}}) { + push @temp, " - $parser"; + my $count = 0; + # @files if the set of files found for that class by that parser + my @files = sort keys %{$xref{$word}{$parser}}; + foreach my $file (@files) { + my $has_data; + $has_data = ' @htmlonly @endhtmlonly' if exists $use_data{$file}; + my $has_baseline_picture; + $has_baseline_picture = ' @htmlonly @endhtmlonly' if exists $baseline_picture{$file}; + last if ++$count > $args{"limit"}; + if (exists $args{"link"}) { + push @temp, + ' - @htmlonly @endhtmlonly ' . $shorter_filename{$file} . + '@htmlonly @endhtmlonly ' . + $has_data . $has_baseline_picture; + } else { + push @temp, " - \@c $shorter_filename{$file} $has_data $has_baseline_picture"; + } + } + } + return join("\n$indent", @temp) . "\n"; +} + +# word_section_alpha returns the single alpha char corresponding to that +# word's section. + +sub word_section_alpha { + my ($word) = @_; + $word =~ /^vtk(\w)/; + return $1; +} + +my $page_doc = build_page_doc($indent, + $args{"title"}, + \@words, + $prefix, + \&word_section_name, + \&word_section_doc, + \&word_section_alpha, + $header, + $footer, + $args{"to"} . "/" . $args{"store"}); + +print join("\n", @summary), "\n => in ", time() - $intermediate_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Update class headers (add a link from the class header to the example page). +# Do not update if the section is already there. + +print "Updating headers...\n"; + +$intermediate_time = time(); +my $updated_nb = 0; + +foreach my $class (@words) { + + print " $class => " . $headers{$class} . "\n" if exists $args{"verbose"}; + + sysopen(HEADER, $headers{$class}, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open " . $headers{$class} . "\n"; + + # Search for the documentation block (@class ...) + + my @dest = (); + my $line; + while ($line =

) { + push @dest, $line; + last if $line =~ /\s\@class\s+$class/; + } + + # Search for the end of the block (*/), and check if the xref is not + # already there (@par $args{"label"}) + + if (defined $line) { + while ($line =
) { + last if $line =~ /^\*\// || $line =~ /^\s*\@par\s+$args{"label"}:\s*$/; + push @dest, $line; + } + + # If the example section was not found, insert the xref to the + # example page, read the rest of the file, and overwrite the + # header + + if (defined $line && $line =~ /^\*\//) { + push @dest, "\n \@par " . $args{"label"} . ":\n", + " \@ref ${prefix}_$class \"$class (" . $args{"label"} . ")\"\n", + $line; + while ($line =
) { + push @dest, $line; + } + close(HEADER); + sysopen(HEADER, $headers{$class}, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open " . $headers{$class} . "\n"; + print HEADER @dest; + $updated_nb++; + } + } + close(HEADER); +} + +print " => $updated_nb header(s) updated in ", time() - $intermediate_time, " s.\n"; + +print "Finished in ", time() - $start_time, " s.\n"; + + +# ------------------------------------------------------------------------- + +sub build_page_doc { + + # $indent is the indentation string + # $rwords is a reference to the array of words to document + # $prefix is a unique prefix that is appended to each link + # word_section_name returns the short string describing a word section + # word_section_doc returns the doxygen doc for a word + # word_section_alpha returns the single alpha char corresponding to that + # word's section. + # $header is the Doxygen string summarizing what has been documented as + # well as the credits. + # $footer is a Doxygen string appended to each the resulting page + # $destination_file is the name of the file where this page should be + # written to. + + my ($ident, $title, $rwords, $prefix, $rword_section_name, $rword_section_doc, $rword_section_alpha, $header, $footer, $destination_file) = @_; + + # %words_doc is a hash associating a word to its Doxygen doc (string) + + my %words_doc; + + # %sections_words is a hash associating a section (alphabetical letter) to + # an array of words belonging to that section. + # Ex: $sections_words{"C"} => ("contour", "cut") + # %sections_weight is a hash associating a section to its weight (the sum + # of the weights of each word belonging to that section). + # @sections is the array holding the name of all sections + + my (%sections_words, %sections_weight, @sections); + + # $navbar is the Doxygen string describing the sections' navigation bar + + my $navbar; + + my $intermediate_time = time(); + + # Browse each word + + foreach my $word (@$rwords) { + + my @temp; + push @temp, &$rword_section_name($word), &$rword_section_doc($word); + $words_doc{$word} = $indent . join("\n$indent", @temp) . "\n"; + + # Update section(s) and section(s) weight(s) + + my $section = &$rword_section_alpha($word); + push @{$sections_words{$section}}, $word; + $sections_weight{$section} += length($words_doc{$word}); + + print " => ", $word, "\n" if exists $args{"verbose"}; + } + + print " => ", scalar @$rwords, " words(s) documented in ", time() - $intermediate_time, " s.\n"; + + @sections = sort keys %sections_words; + + # Build the navbar + + my @temp; + foreach my $section (@sections) { + push @temp, "\@ref ${prefix}_section_$section \"$section\""; + } + $navbar = "$indent\@par Navigation: \n$indent\[" . + join(" | ", @temp) . "]\n"; + + # Add the (approximate) weight of the (header + navbar) to each section + + my $total_weight = 0; + my $header_weight = length($indent) + 24 + length($navbar); + + foreach my $section (@sections) { + $sections_weight{$section} += $header_weight; + $total_weight += $sections_weight{$section}; + } + + if (exists $args{"verbose"}) { + foreach my $section (@sections) { + printf("\t- %s : %6d\n", $section, $sections_weight{$section}); + } + } + + print " => total weight is $total_weight in ", scalar @sections, " section(s)\n"; + + print " => mean is ", int($total_weight / scalar @sections), ")\n" + if scalar @sections; + + # Compute the alphabetical groups by joining sections depending on weights + + print "Computing alphabetical group(s)/page(s)...\n"; + + # %groups is a hash associating a group id (int) to an array of sections + # namesbelonging to that group. + # Ex: $groups{"0"} => ("A", "B", "C") + # %groups_weight is a hash associating a group id to its weight (the sum + # of the weights of each section belonging to that group). + + my (%groups, %groups_weight); + + my $groupid = 0; + + # Remove a section one by one, and put it in a group until the group if + # full,then create a next group, etc., until the sections are exhausted. + + my @sections_temp = @sections; + while (@sections_temp) { + $groups_weight{$groupid} = $sections_weight{$sections_temp[0]}; + push @{$groups{$groupid}}, shift @sections_temp; + while (@sections_temp && + ($groups_weight{$groupid} +$sections_weight{$sections_temp[0]}) + <= $args{"weight"}) { + $groups_weight{$groupid} += $sections_weight{$sections_temp[0]}; + push @{$groups{$groupid}}, shift @sections_temp; + } + $groupid++; + } + + if (exists $args{"verbose"}) { + foreach my $groupid (sort {$a <=> $b} keys %groups) { + printf("\t- %02d (weight: %7d) : %s\n", $groupid, + $groups_weight{$groupid}, join(", ", @{$groups{$groupid}})); + } + } + + print " => max weight is ", $args{"weight"}, " per group/page, but a section can not be divided\n"; + print " => ", scalar keys %groups, " group(s) for ", scalar @sections, " section(s)\n"; + + # Build documentation page + # Browse each group, each section in this group, each word in this section + + my $page_doc; + + foreach my $groupid (sort {$a <=> $b} keys %groups) { + + my $fromto = $groups{$groupid}[0]; + $fromto .= ".." . $groups{$groupid}[scalar @{$groups{$groupid}} - 1] + if scalar @{$groups{$groupid}} > 1; + + $page_doc .= + "/*! \@page ${prefix}_$groupid $title ($fromto)\n\n$header"; + + foreach my $section (@{$groups{$groupid}}) { + $page_doc .= + "\n$indent\@section ${prefix}_section_$section $section\n\n$navbar\n"; + foreach my $word (@{$sections_words{$section}}) { + $page_doc .= $words_doc{$word}, "\n"; + } + print "\t- $section\n" if exists $args{"verbose"}; + } + $page_doc .= "$footer\n*/\n\n"; + } + + print "Writing documentation to ", $destination_file, "...\n"; + + $intermediate_time = time(); + + sysopen(DEST_FILE, + $destination_file, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file $destination_file\n"; + print DEST_FILE $page_doc; + close(DEST_FILE); + + print " => written in ", time() - $intermediate_time, " s.\n"; +} + diff --git a/Utilities/Doxygen/doc_cleanhtml.pl b/Utilities/Doxygen/doc_cleanhtml.pl new file mode 100644 index 0000000..1645ec7 --- /dev/null +++ b/Utilities/Doxygen/doc_cleanhtml.pl @@ -0,0 +1,113 @@ +#!/usr/bin/env perl +# Time-stamp: <2002-10-25 20:17:59 barre> +# +# Clean the HTML generated by Doxygen to remove some layout quicks +# +# barre : Sebastien Barre +# +# 0.1 (barre) +# - first release + +use Carp; +use Getopt::Long; +use Fcntl; +use File::Find; +use strict; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.1, $0, "Sebastien Barre"); +$PROGNAME =~ s/^.*[\\\/]//; +print "$PROGNAME $VERSION, by $AUTHOR\n"; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want : "verbose" => 1 for default verbose mode) + +my %default = + ( + html => "../../../doc/html", + ); + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "verbose|v", "html=s"); + +if (exists $args{"help"}) { + print <<"EOT"; +Usage : $PROGNAME [--help] [--verbose|-v] [--html path] + --help : this message + --verbose|-v : verbose (display filenames while processing) + --html path : 'path' the Doxygen generated HTML doc (default : $default{html}) + +Example: + $PROGNAME +EOT + exit; +} + +$args{"html"} = $default{"html"} if ! exists $args{"html"}; +$args{"html"} =~ s/[\\\/]*$// if exists $args{"html"}; + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Collect all HTML files + +print "Collecting HTML files in ", $args{"html"}, "\n"; + +my @files; +find sub { + push @files, $File::Find::name + if -f $_ && $_ =~ /\.html$/; +}, $args{"html"}; + +print " => ", scalar @files, " file(s) collected in ", time() - $start_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Remove path + +my $nb_files = 0; +undef $/; # slurp mode + +print "Cleaning and writing...\n"; +my $intermediate_time = time(); + +foreach my $filename (@files) { + + print " $filename\n" if exists $args{"verbose"}; + + # Open the file, read it entirely + + sysopen(HTMLFILE, + $filename, + O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $filename\n"; + my $html = ; + close(HTMLFILE); + + # Clean + + my $has_been_cleaned = 0; + if ($html =~ s//
/gms) { + $has_been_cleaned = 1; + } + + # Write + + if ($has_been_cleaned) { + ++$nb_files; + sysopen(HTMLFILE, + $filename, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file $filename\n"; + print HTMLFILE $html; + close(HTMLFILE); + } +} + +print " => $nb_files file(s) processed and written in ", time() - $intermediate_time, " s.\n"; +print "Finished in ", time() - $start_time, " s.\n"; + diff --git a/Utilities/Doxygen/doc_codematch.pl b/Utilities/Doxygen/doc_codematch.pl new file mode 100644 index 0000000..681d562 --- /dev/null +++ b/Utilities/Doxygen/doc_codematch.pl @@ -0,0 +1,570 @@ +#!/usr/bin/env perl +# Time-stamp: <2002-01-18 16:17:26 barre> +# +# Summary ? +# +# barre : Sebastien Barre +# +# 0.2 (barre) +# - add --headerext s : expected header file extension +# - add --headernewext s : new header file extension +# - add --headernewsuffix s : new header file suffix +# +# 0.1 (barre) +# - first release + +use Carp; +use Cwd 'abs_path'; +use Getopt::Long; +use Fcntl; +use File::Basename; +use File::Find; +use File::Path; +use strict; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.2, $0, "Sebastien Barre"); +$PROGNAME =~ s/^.*[\\\/]//; +print "$PROGNAME $VERSION, by $AUTHOR\n"; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want : "verbose" => 1 for default verbose mode) + +my %default = + ( + codematch => "\w(?:->|\.)InvokeEvent\s*\(\s*(vtkCommand::\w+)[\s,]", + dirs => ["../../Common", + "../../Filtering", + "../../GenericFiltering", + "../../GenericFiltering/Testing/Cxx", + "../../Graphics", + "../../GUISupport/MFC", + "../../GUISupport/Qt", + "../../Hybrid", + "../../Imaging", + "../../IO", + "../../Parallel", + "../../Patented", + "../../Rendering", + "../../VolumeRendering"], + headerext => "h", + headernewext => "h", + headernewsuffix => "", + label => "Events", + project => "VTK", + relativeto => "", + sectionmatch => "^vtkCommand::(\w)", + sectionmatch2 => "^vtk(\w)", + store => "doc_VTK_events.dox", + store2 => "doc_VTK_events2.dox", + title => "Event To Classes", + title2 => "Class to Events", + to => "../../../VTK-doxygen", + unique => "v", + weight => 90000 + ); + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "verbose|v", "debug", "label=s", "codematch=s", "headerext=s", "headernewext=s", "headernewsuffix=s", "project=s", "relativeto=s", "sectionmatch=s", "sectionmatch2=s", "store=s", "store2=s", "title=s", "title2=s", "to=s", "unique=s", "weight=i"); + +if (exists $args{"help"}) { + print <<"EOT"; +Usage : $PROGNAME [--help] [--verbose|-v] [--limit n] [--stop file] [--sectionmatch str] [--sectionmatch2 file] [--store file] [--store2 file] [--title string] [--title2 string] [--to path] [--relativeto path] [--weight n] [files|directories...] + --help : this message + --verbose|-v : verbose (display filenames while processing) + --codematch str : codematch used to generate matches against code (default: $default{codematch}) + --headerext s : expected header file extension (default: $default{headerext}) + --headernewext s : new header file extension (default: $default{headernewext}) + --headernewsuffix s : new header file suffix (default: $default{headernewsuffix}) + --project name : project name, used to uniquify (default: $default{project}) + --label str : use string as label in class page (default: $default{label}) + --sectionmatch s : use string against match to get unique alpha section (default: $default{sectionmatch}) + --sectionmatch2 s : use string against class to get unique alpha section (default: $default{sectionmatch2}) + --store file : use 'file' to store 'match to classes' (default: $default{store}) + --store2 file : use 'file' to store 'classes to matches' (default: $default{store2}) + --title str : use string as title in 'match to classes' (default: $default{title}) + --title2 str : use string as title in 'class to matches' (default: $default{title2}) + --to path : use 'path' as destination directory (default : $default{to}) + --unique str : use string as a unique page identifier among "Class To..." pages generated by this script (otherwise MD5) (default : $default{unique}) + --relativeto path : each file/directory to document is considered relative to 'path', where --to and --relativeto should be absolute (default: $default{relativeto}) + --weight n : use 'n' as an approximation of the maximum page weight (default : $default{weight}) + +Example: + $PROGNAME +EOT + exit; +} + +$args{"debug"} = $default{"debug"} if exists $default{"debug"}; +$args{"verbose"} = 1 if exists $default{"verbose"}; +$args{"codematch"} = $default{"codematch"} if ! exists $args{"codematch"}; +$args{"headerext"} = $default{"headerext"} if ! exists $args{"headerext"}; +$args{"headernewext"} = $default{"headernewext"} if ! exists $args{"headernewext"}; +$args{"headernewsuffix"} = $default{"headernewsuffix"} +if ! exists $args{"headernewsuffix"}; +$args{"project"} = $default{"project"} if ! exists $args{"project"}; +$args{"label"} = $default{"label"} if ! exists $args{"label"}; +$args{"sectionmatch"} = $default{"sectionmatch"} if ! exists $args{"sectionmatch"}; +$args{"store"} = $default{"store"} if ! exists $args{"store"}; +$args{"title"} = $default{"title"} if ! exists $args{"title"}; +$args{"sectionmatch2"} = $default{"sectionmatch2"} if ! exists $args{"sectionmatch2"}; +$args{"store2"} = $default{"store2"} if ! exists $args{"store2"}; +$args{"title2"} = $default{"title2"} if ! exists $args{"title2"}; +$args{"to"} = $default{"to"} if ! exists $args{"to"}; +$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"}; +$args{"relativeto"} = $default{"relativeto"} if ! exists $args{"relativeto"}; +$args{"relativeto"} =~ s/[\\\/]*$// if exists $args{"relativeto"}; +$args{"unique"} = $default{"unique"} if ! exists $args{"unique"}; +$args{"weight"} = $default{"weight"} if ! exists $args{"weight"}; + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Collect all files and directories + +print "Collecting files...\n"; + +push @ARGV, @{$default{dirs}} if !@ARGV; + +my @files; +foreach my $file (@ARGV) { + if (-f $file) { + push @files, $file; + } elsif (-d $file) { + find sub { push @files, $File::Find::name; }, $file; + } +} + +# ------------------------------------------------------------------------- +# Parse implementation files corresponding to headers + +print "Parsing implementation files and updating headers...\n"; +my $intermediate_time = time(); + +# %allclasses reports all class that have been parsed. +# %allmatches reports all matches that have been found. +# %match2classes associates a match to a class name and reports how many +# times that association was found. +# Example: $match2classes{"vtkCommand::Event"}{"vtkMarchingCubes"} = 2 +# %class2matches associates a class name to a match + +my %allclasses; +my %allmatches; +my %class2matches; +my %match2classes; + +my ($nb_files, $nb_replaced_files, $nb_classes_matching) = (0, 0); +undef $/; # slurp mode + +foreach my $source (@files) { + + # Skip if not a VTK header file or has no implementation file + + next if $source !~ /(\w?vtk[^\\\/]*)\.$args{"headerext"}\Z/; + my ($class, $implem) = ($1, $source); + $implem =~ s/\.$args{"headerext"}\Z/\.cxx/; + next if ! -e $implem; + + ++$nb_files; + + # Open the implementation file, read it entirely + + sysopen(IMPLEMFILE, $implem, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $implem\n"; + my $implemfile = ; + close(IMPLEMFILE); + + # Remove all comments + + $implemfile =~ s/\/\*.*?\*\/|\/\/.*?$//gms; + + # Grab matches, skip to next file if none found + + my @matches = $implemfile =~ m/$args{"codematch"}/gms; + + next if ! @matches; + $allclasses{$class} = 1; + + # Setup match <-> class relationships + + foreach my $match (@matches) { + $allmatches{$match}++; + $class2matches{$class}{$match}++; + $match2classes{$match}{$class}++; + } + + # Figure out the name of the already-converted-to-doxygen header + # file using --to and --relativeto destination file now + + my $header; + + # If source has absolute path, just use the basename (unless a + # relativeto path has been set) otherwise remove the ../ component + # before the source filename, so that it might be appended to the + # "to" directory. + + if ($source =~ m/^(\/|[a-zA-W]\:[\/\\])/) { + if ($args{"relativeto"}) { + my ($dir, $absrel) = (abs_path(dirname($source)), + abs_path($args{"relativeto"})); + $dir =~ s/$absrel//; + $header = $args{"to"} . $dir . '/' . basename($source); + } else { + $header = $args{"to"} . '/' . basename($source); + } + } else { + $source =~ s/^(\.\.[\/\\])*//; + $header = $args{"to"} . '/' . $source; + } + $header =~ s/\.$args{"headerext"}\Z/$args{"headernewsuffix"}\.$args{"headernewext"}/; + + next if ! -e $header; + + # Read that header + + sysopen(HEADERFILE, $header, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $header\n"; + my $headerfile = ; + close(HEADERFILE); + + # Search for the documentation block (@class ...) + + if ($headerfile !~ /(.*\/\*\!\s+)(\@class\s.+?)(\*\/.*)/gms) { + carp "$PROGNAME: no documentation block in $header ! (skipping)\n"; + next; + } + my ($pre, $block, $post) = ($1, $2, $3); + + # Create new doc section, insert it into block + + my $preamble = " \@par " . $args{"label"} . ":\n"; + my $doc = $preamble . + " " . join(" ", keys %{$class2matches{$class}}) . "\n"; + + if ($block !~ s/($preamble.+?)(\s*\@par|\z)/$doc$2/gms) { + $block .= "\n$doc"; + } + + # Write new header + + sysopen(HEADERFILE, $header, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open $header\n"; + print HEADERFILE $pre . $block . $post; + close(HEADERFILE); + + ++$nb_replaced_files; +} + +print " => parsed in ", time() - $intermediate_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Build the page summary documentation + +# $indent is the indentation string + +my $indent = " "; + +# $header is the Doxygen string summarizing what has been documented as well +# as the credits. + +my $header; +my (@summary, @credits); + +push @summary, + " - $nb_files implementation file(s) returning " . scalar (keys %allmatches) . " word(s) for " . scalar (keys %allclasses) . " classe(es) on " . localtime(), + " - $nb_replaced_files file(s) updated"; + +push @credits, + "\@version $VERSION", + "\@author \@c $PROGNAME, by $AUTHOR"; + +$header = $indent . join("\n$indent", @summary) . + "\n\n$indent" . join("\n$indent", @credits) . "\n\n"; + +# ------------------------------------------------------------------------- +# (first part - match 2 classes) + +if ($args{"store"}) { + + print "Building page doc (match 2 classes)...\n"; + + # @words is the array of words to document + + my @words = sort keys %allmatches; + + # $prefix is a unique prefix that is appended to each link + + my $prefix = "mc_" . $args{"project"} . "_"; + if (exists $args{"unique"}) { + $prefix .= $args{"unique"}; + } else { + $prefix .= md5_hex($args{"label"} . $args{"title"}); + } + $prefix = lc($prefix); + + # word_section_name returns the short string describing a word section + + sub word_section_name { + my ($word) = @_; + return $word; + } + + # word_section_doc returns the doxygen doc for a word + + sub word_section_doc { + my ($word) = @_; + return " - " . join(", ", sort keys %{$match2classes{$word}}) . "\n"; + } + + # word_section_alpha returns the single alpha char corresponding to that + # word's section. + + sub word_section_alpha { + my ($word) = @_; + $word =~ /$args{"sectionmatch"}/; + return $1; + } + + my $page_doc = build_page_doc($indent, + $args{"title"}, + \@words, + $prefix, + \&word_section_name, + \&word_section_doc, + \&word_section_alpha, + $header, + "", + $args{"to"} . "/" . $args{"store"}); +} + + +# ------------------------------------------------------------------------- +# (second part - class to matches) + +if ($args{"store2"}) { + + print "Building page doc (classes to matches)...\n"; + + # @words is the array of words to document + + my @words = sort keys %allclasses; + + # $prefix is a unique prefix that is appended to each link + + my $prefix = "mc2_" . $args{"project"} . "_"; + if (exists $args{"unique"}) { + $prefix .= $args{"unique"}; + } else { + $prefix .= md5_hex($args{"label"} . $args{"title"}); + } + $prefix = lc($prefix); + + # word_section_name returns the short string describing a word section + + sub word_section_name2 { + my ($word) = @_; + return $word; + } + + # word_section_doc returns the doxygen doc for a word + + sub word_section_doc2 { + my ($word) = @_; + return " - " . join(", ", sort keys %{$class2matches{$word}}) . "\n"; + } + + # word_section_alpha returns the single alpha char corresponding to that + # word's section. + + sub word_section_alpha2 { + my ($word) = @_; + $word =~ /$args{"sectionmatch2"}/; + return $1; + } + + my $page_doc = build_page_doc($indent, + $args{"title2"}, + \@words, + $prefix, + \&word_section_name2, + \&word_section_doc2, + \&word_section_alpha2, + $header, + "", + $args{"to"} . "/" . $args{"store2"}); +} + +print join("\n", @summary), "\n"; +print "Finished in ", time() - $start_time, " s.\n"; + +# ------------------------------------------------------------------------- + +sub build_page_doc { + + # $indent is the indentation string + # $rwords is a reference to the array of words to document + # $prefix is a unique prefix that is appended to each link + # word_section_name returns the short string describing a word section + # word_section_doc returns the doxygen doc for a word + # word_section_alpha returns the single alpha char corresponding to that + # word's section. + # $header is the Doxygen string summarizing what has been documented as + # well as the credits. + # $footer is a Doxygen string appended to each the resulting page + # $destination_file is the name of the file where this page should be + # written to. + + my ($ident, $title, $rwords, $prefix, $rword_section_name, $rword_section_doc, $rword_section_alpha, $header, $footer, $destination_file) = @_; + + # %words_doc is a hash associating a word to its Doxygen doc (string) + + my %words_doc; + + # %sections_words is a hash associating a section (alphabetical letter) to + # an array of words belonging to that section. + # Ex: $sections_words{"C"} => ("contour", "cut") + # %sections_weight is a hash associating a section to its weight (the sum + # of the weights of each word belonging to that section). + # @sections is the array holding the name of all sections + + my (%sections_words, %sections_weight, @sections); + + # $navbar is the Doxygen string describing the sections' navigation bar + + my $navbar; + + my $intermediate_time = time(); + + # Browse each word + + foreach my $word (@$rwords) { + + my @temp; + push @temp, &$rword_section_name($word), &$rword_section_doc($word); + $words_doc{$word} = $indent . join("\n$indent", @temp) . "\n"; + + # Update section(s) and section(s) weight(s) + + my $section = &$rword_section_alpha($word); + push @{$sections_words{$section}}, $word; + $sections_weight{$section} += length($words_doc{$word}); + + print " => ", $word, "\n" if exists $args{"verbose"}; + } + + print " => ", scalar @$rwords, " words(s) documented in ", time() - $intermediate_time, " s.\n"; + + @sections = sort keys %sections_words; + + # Build the navbar + + my @temp; + foreach my $section (@sections) { + push @temp, "\@ref ${prefix}_section_$section \"$section\""; + } + $navbar = "$indent\@par Navigation: \n$indent\[" . + join(" | ", @temp) . "]\n"; + + # Add the (approximate) weight of the (header + navbar) to each section + + my $total_weight = 0; + my $header_weight = length($indent) + 24 + length($navbar); + + foreach my $section (@sections) { + $sections_weight{$section} += $header_weight; + $total_weight += $sections_weight{$section}; + } + + if (exists $args{"verbose"}) { + foreach my $section (@sections) { + printf("\t- %s : %6d\n", $section, $sections_weight{$section}); + } + } + + print " => total weight is $total_weight in ", scalar @sections, " section(s) (mean is ", int($total_weight / scalar @sections), ")\n"; + + # Compute the alphabetical groups by joining sections depending on weights + + print "Computing alphabetical group(s)/page(s)...\n"; + + # %groups is a hash associating a group id (int) to an array of sections + # namesbelonging to that group. + # Ex: $groups{"0"} => ("A", "B", "C") + # %groups_weight is a hash associating a group id to its weight (the sum + # of the weights of each section belonging to that group). + + my (%groups, %groups_weight); + + my $groupid = 0; + + # Remove a section one by one, and put it in a group until the group if + # full,then create a next group, etc., until the sections are exhausted. + + my @sections_temp = @sections; + while (@sections_temp) { + $groups_weight{$groupid} = $sections_weight{$sections_temp[0]}; + push @{$groups{$groupid}}, shift @sections_temp; + while (@sections_temp && + ($groups_weight{$groupid} +$sections_weight{$sections_temp[0]}) + <= $args{"weight"}) { + $groups_weight{$groupid} += $sections_weight{$sections_temp[0]}; + push @{$groups{$groupid}}, shift @sections_temp; + } + $groupid++; + } + + if (exists $args{"verbose"}) { + foreach my $groupid (sort {$a <=> $b} keys %groups) { + printf("\t- %02d (weight: %7d) : %s\n", $groupid, + $groups_weight{$groupid}, join(", ", @{$groups{$groupid}})); + } + } + + print " => max weight is ", $args{"weight"}, " per group/page, but a section can not be divided\n"; + print " => ", scalar keys %groups, " group(s) for ", scalar @sections, " section(s)\n"; + + # Build documentation page + # Browse each group, each section in this group, each word in this section + + my $page_doc; + + foreach my $groupid (sort {$a <=> $b} keys %groups) { + + my $fromto = $groups{$groupid}[0]; + $fromto .= ".." . $groups{$groupid}[scalar @{$groups{$groupid}} - 1] + if scalar @{$groups{$groupid}} > 1; + + $page_doc .= + "/*! \@page ${prefix}_$groupid $title ($fromto)\n\n$header"; + + foreach my $section (@{$groups{$groupid}}) { + $page_doc .= + "\n$indent\@section ${prefix}_section_$section $section\n\n$navbar\n"; + foreach my $word (@{$sections_words{$section}}) { + $page_doc .= $words_doc{$word}, "\n"; + } + print "\t- $section\n" if exists $args{"verbose"}; + } + $page_doc .= "$footer\n*/\n\n"; + } + + print "Writing documentation to ", $destination_file, "...\n"; + + $intermediate_time = time(); + + sysopen(DEST_FILE, + $destination_file, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file $destination_file\n"; + print DEST_FILE $page_doc; + close(DEST_FILE); + + print " => written in ", time() - $intermediate_time, " s.\n"; +} + diff --git a/Utilities/Doxygen/doc_contributors.pl b/Utilities/Doxygen/doc_contributors.pl new file mode 100644 index 0000000..308b2ba --- /dev/null +++ b/Utilities/Doxygen/doc_contributors.pl @@ -0,0 +1,1052 @@ +#!/usr/bin/env perl +# Time-stamp: <2002-11-01 15:33:04 barre> +# +# Get author and contributors. +# +# barre : Sebastien Barre +# +# 0.8 (barre) : +# - Add --cvsweb and --cvsweb_suffix to report links to CVSweb logs +# +# 0.7 (barre) : +# - Fix empty cached log file pb (regenerated) +# - Add link from name to detailed description of contribution +# +# 0.6 (barre) : +# - Change --history_img in order to create any contribution graph(s) +# +# 0.5 (barre) : +# - Contribution graphs for the whole period (back to 1994). +# +# 0.4 (barre) : +# - D'oh ! Month returned by localtime start with 0 (=january). +# +# 0.3 (barre) : +# - add history feature + gnuplot fig +# +# 0.2 (barre) : +# - now handles most files +# +# 0.1 (barre) : +# - first release + +use Carp; +use Cwd 'abs_path', 'cwd'; +use Getopt::Long; +use Fcntl; +use File::Basename; +use File::Find; +use File::Path; +use POSIX; +use strict; +use FileHandle; +use Time::Local; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.8, $0, "Sebastien Barre"); +$PROGNAME =~ s/^.*[\\\/]//; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want: "verbose" => 1 for default verbose mode) + +my %default = + ( + dirs => ["../.."], + cachedir => $ENV{TMP} . "/cache", + class_group => '^(vtk[A-Z0-9][A-Za-z0-9]+)\.(?:c|cpp|cxx|h|mm)$', + files_in => '(?:^hints|^README|\.(?:c|cmake|cpp|cxx|doc|h|html|in|java|mm|pl|py|tcl|txt))$', + files_out => '(?:^vtkVersion\.\w+|^pkgIndex\.tcl|^vtkParse\.tab\.c|\.yy\.c)$', + gnuplot_file => '../../../VTK-doxygen/contrib/history.plt', + history_dir => '../../../VTK-doxygen/contrib', + history_img => ['|lines|../../../VTK-doxygen/contrib/history.png', + '730|lines|../../../VTK-doxygen/contrib/history2y.png', + '180|linespoints|../../../VTK-doxygen/contrib/history6m.png'], + history_max_nb => 12, + lines_add => 1.0, + lines_rem => 0.5, + massive => 200, + max_class_nb => 10, + max_file_nb => 5, + min_class => 0.02, + min_file => 0.01, + min_contrib => 0.05, + min_gcontrib => 0.0001, + relativeto => "../..", + store => "doc_VTK_contributors.dox", + to => "../../../VTK-doxygen" + ); + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "verbose|v", "authors=s", "cachedir=s", "class_group=s", "cvsweb=s", "cvsweb_suffix=s", "files_in=s", "files_out=s", "gnuplot_file=s", "history_dir=s", "history_img=s@", "history_max_nb=i", "lines_add=f", "lines_rem=f", "massive=i", "max_class_nb=i", "max_file_nb=i", "min_class=f", "min_file=f", "min_contrib=f", "min_gcontrib=f", "relativeto=s", "store=s", "to=s"); + +print "$PROGNAME $VERSION, by $AUTHOR\n"; + +if (exists $args{"help"}) { + print <<"EOT"; +Usage : $PROGNAME [--help] [--verbose|-v] [--authors file] [--cachedir path] [--files_in string] [--files_out string] [--gnuplot_file string] [--history_dir string] [--history_img string] [--history_max_nb number] [--lines_add number] [--lines_rem number] [--massive number] [--max_class_nb number] [--max_file_nb number] [--min_class number] [--min_file number] [--min_contrib number] [--min_gcontrib number] [--store file] [--relativeto path] [--to path] [files|directories...] + --help : this message + --verbose|-v : verbose (display filenames while processing) + --authors file : use 'file' to read authors list + --cachedir path : use 'path' as cache directory for CVS logs (default: $default{cachedir}) + --files_in s : accept only file names (without path) matching 's' (default: $default{files_in}) + --files_out s : (then) reject file names (without path) matching 's' (default: $default{files_out}) + --gnuplot_file s : use 's' to store gnuplot command file (default: $default{gnuplot_file}) + --history_dir s : history dir (default: $default{history_dir}) + --history_img d|s : create history image 's' graphing contribs up to 'd' ago (default: $default{history_img}) + --history_max_nb n : use at most 'n' authors in history pic (default: $default{history_max_nb}) + --lines_add n : use 'n' as weight for added lines (default: $default{lines_add}) + --lines_rem n : use 'n' as weight for removed lines (default: $default{lines_rem}) + --massive n : use 'n' as minimum threshold for massive commits removal (default: $default{massive}) + --max_class_nb n : do not display more than 'n' classes by contributor (default: $default{max_class_nb}) + --max_file_nb n : do not display more than 'n' files by contributor (default: $default{max_file_nb}) + --min_class n : display classes that represent more than 'n' % of author's contribution (default: $default{min_class}) + --min_file n : display files that represent more than 'n' % of author's contribution (default: $default{min_file}) +x --min_contrib n : display authors who represent more than 'n' % of classe's contribution (default: $default{min_contrib}) + --min_gcontrib n : display authors who represent more than 'n' % of total contribution (default: $default{min_gcontrib}) + --cvsweb s : use 's' as a base link to the CVSweb site + --cvsweb_suffix s : use 's' as a suffix to the link to the CVSweb site + --store file : use 'file' to store doc (default: $default{store}) + --relativeto path: each file/directory to document is considered relative to 'path', where --to and --relativeto should be absolute (default: $default{relativeto}) + --to path : use 'path' as destination directory (default: $default{to}) + +Example: + $PROGNAME --to ../vtk-doxygen + $PROGNAME contrib +EOT + exit; +} + +foreach my $option ( + "cachedir", + "class_group", + "files_in", + "files_out", + "gnuplot_file", + "history_dir", + "history_img", + "history_max_nb", + "lines_add", + "lines_rem", + "massive", + "min_contrib", + "min_gcontrib", + "min_class", + "min_file", + "max_class_nb", + "max_file_nb", + "relativeto", + "store", + "to") { + $args{$option} = $default{$option} + if ! exists $args{$option} && exists $default{$option}; +} + +$args{"verbose"} = 1 if exists $default{"verbose"}; + +$args{"cachedir"} =~ s/[\\\/]*$// if exists $args{"cachedir"}; +$args{"history_dir"} =~ s/[\\\/]*$// if exists $args{"history_dir"}; +$args{"relativeto"} =~ s/[\\\/]*$// if exists $args{"relativeto"}; +$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"}; + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; + +STDOUT->autoflush; +STDERR->autoflush; + +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Read the authors list + +# %authors is indexed by login name (i.e. $authors{$name}) +# {'name'}: full name of the user +# {'email'}: email of the user +# +# %authors_aliases is indexed by aliased login name +# $authors_aliases{$name} is the real login name for $name + +my %authors; +my %authors_aliases; + +sub trim_spaces { + my @out = @_; + for (@out) { + s/^\s*//; + s/\s*$//; + } + return wantarray ? @out : $out[0]; +} + +# Grab each author, line by line, setup aliases +# Example: +# will, schroede: Schroeder, Will (will.schroeder@kitware.com) + +my $authors_file_loaded = 0; + +if (exists $args{"authors"}) { + if (!sysopen(AUTHORS_FILE, + $args{"authors"}, + O_RDONLY|$open_file_as_text)) { + carp "$PROGNAME: unable to open authors list ". $args{"authors"}. "\n"; + } else { + print "Reading the authors list from ". $args{"authors"} . "...\n"; + + my @authors_file = ; + close(AUTHORS_FILE); + + $authors_file_loaded = 1; + + foreach my $line (@authors_file) { + if ($line && $line =~ m/^\s*(.+?)\s*:\s*(.+?)\s*\(\s*(.*?)\s*\)/) { + my @aliases = split(',', $1); + my $author = trim_spaces(shift @aliases); + $authors{$author}{'name'} = $2; + $authors{$author}{'email'} = $3; + foreach my $alias (@aliases) { + $authors_aliases{trim_spaces($alias)} = $author; + } + print " >> $author: ", $authors{$author}{'name'}, + " (", $authors{$author}{'email'}, ")\n" + if exists $args{"verbose"}; + } + } + + print " => ", scalar keys %authors, " authors(s) read from ", basename($args{"authors"}), ".\n"; + } +} + +# ------------------------------------------------------------------------- +# Parse a revision +# +# Example: +# 1.2 +# date: 2001/06/05 15:34:17; author: barre; state: Exp; lines: +10 -3 +# fix PrintSelf defects + +sub parse_revision { + my $ref = shift; + + $$ref =~ /([\d\.]*)\n(.*)\n(.*)/; + + my ($revision, $fields_line, $message) = ($1, $2, $3); + my ($author, $date, $time, $lines_add, $lines_rem) = + (undef, undef, undef, undef, undef); + + my @fields = split (';', $fields_line); + + if ($fields[0] =~ m/date:\s+(\d+-\d+-\d+)\s+(\d+:\d+:\d+)\s+\+0000$/) { + ($date, $time) = ($1, $2); + } else { + carp "Unable to find date of revision!\n"; + } + + if ($fields[1] =~ m/author:\s+(.+)$/) { + $author = $1; + } else { + carp "Unable to find author of revision!\n"; + } + + if (exists $fields[3] && $fields[3] =~ m/lines:\s+\+(\d+)\s+\-(\d+)$/) { + ($lines_add, $lines_rem) = ($1, $2); + } + + return ($revision, $date, $time, $author, $lines_add, $lines_rem, $message); +} + +# ------------------------------------------------------------------------- +# Collect all files and directories + +# Avoid all CVS/ directories and third-party libs directories (identified +# by a .NoDartCoverage file) + +push @ARGV, @{$default{dirs}} if !@ARGV; + +print "Collecting...\n"; +my %files; +foreach my $file (@ARGV) { + if (-f $file) { + $files{$file} = 1; + } elsif (-d $file) { + find sub { + if ($File::Find::dir =~ /\bCVS$/ || + -e '.NoDartCoverage') { + $File::Find::prune = 1; + } else { + $files{$File::Find::name} = 1 if -f $_; + } + }, $file; + } +} + +# ------------------------------------------------------------------------- +# Process files and get logs + +print "Processing files and getting logs...\n"; + +my $intermediate_time = time(); +my $nb_revisions = 0; + +# %log_by_file_revision is indexed by file and revision +# (i.e. $log_by_file_revision{$file_name}{$revision_number}) +# {'date'}: revision's date +# {'author'}: revision's author +# {'lines_add'}: number of lines added for that revision +# {'lines_rem'}: number of lines removed for that revision + +my %log_by_file_revision; + +# %log_revision_by_signature_file is indexed by signature and file +# (i.e. $log_revision_by_signature_file{$signature}{$file_name}) +# (hash) all revisions matching this signature and that file. +# The signature is made of the rev date, author and message. + +my %log_revision_by_signature_file; + +my @files_submitted = sort keys %files; +my $nb_file_submitted = scalar @files_submitted; +my $nb_file_fraction = ceil($nb_file_submitted / 10.0); + +my %files_visited; + +sub get_short_relative_name { + my ($file_name, $relative_to) = @_; + $file_name =~ s/^$relative_to//; + return $file_name; +} + +foreach my $file_name (@files_submitted) { + + # print " ? $file_name\n" if exists $args{"verbose"}; + + # Progress meter + + if ($nb_file_submitted % $nb_file_fraction == 0) { + print " - Remaining files: $nb_file_submitted\n"; + } + --$nb_file_submitted; + + # Reject file if not matching pattern or already visited + + my $file_name_basename = basename($file_name); + + next if ($file_name_basename !~ m/$args{"files_in"}/ || + $file_name_basename =~ m/$args{"files_out"}/ || + exists $files_visited{$file_name}); + + print " $file_name\n" if exists $args{"verbose"}; + + # Get the CVS log for that file or grab it from the cache + + my $cache_name = $args{"cachedir"} . + get_short_relative_name($file_name, $args{"relativeto"}) . '.log'; + my $output; + + my $old_slurp = $/; + undef $/; # slurp mode + + # Use the cache if it exists, is not older than file, and not empty + + if (-e $cache_name && + (stat $cache_name)[9] >= (stat $file_name)[9] && + (stat $cache_name)[7]) { + sysopen(CACHE_FILE, + $cache_name, + O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open cache file $cache_name\n"; + $output = ; + close(CACHE_FILE); + } else { + my $file_name_dir = dirname($file_name); + print " >> $file_name_dir: cvs log -b $file_name_basename\n" + if exists $args{"verbose"}; + my $current = cwd; + chdir($file_name_dir); + $output = qx/cvs log -b $file_name_basename/; + chdir($current); + mkpath(dirname($cache_name)); + sysopen(CACHE_FILE, + $cache_name, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open cache file $cache_name\n"; + print CACHE_FILE $output; + close(CACHE_FILE); + } + + $/ = $old_slurp; + + if (! $output) { + carp " >> Empty output from CVS log -b $file_name\n"; + next; + } + + $files_visited{$file_name} = 1; + + # Process revisions + + my @file_revisions = + split('----------------------------\nrevision ', $output); + shift @file_revisions; + + # Store each revision + + my $lines_added = 0; + + foreach my $revision (@file_revisions) { + + my ($revision, $date, $time, $author, + $lines_add, $lines_rem, $message) = parse_revision(\$revision); + + # Resolve author aliases and use full name + + $author = $authors_aliases{$author} + if exists $authors_aliases{$author}; + + $nb_revisions++; + + # Store date/author + + $log_by_file_revision{$file_name}{$revision}{'date'} = $date; + $log_by_file_revision{$file_name}{$revision}{'author'} = $author; + + # Store lines added and removed. Load the file and count the + # lines for rev 1.1 + + if ($revision ne '1.1') { + $log_by_file_revision{$file_name}{$revision}{'lines_add'} + = $lines_add; + $log_by_file_revision{$file_name}{$revision}{'lines_rem'} + = $lines_rem; + + $lines_added += $lines_add - $lines_rem; + + $log_revision_by_signature_file + {"$date: $author: $message"}{$file_name}{$revision} = 1; + } + } + + # Now get the number of lines for 1.1 (not stored in the log) + # Read the current file, add all changes + + sysopen(FILE, + $file_name, + O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open file $file_name\n"; + + my @lines = ; + close(FILE); + + $log_by_file_revision{$file_name}{'1.1'}{'lines_add'} + = (scalar @lines) - $lines_added; + if ($log_by_file_revision{$file_name}{'1.1'}{'lines_add'} < 0) { + print " >> $file_name: ", $log_by_file_revision{$file_name}{'1.1'}{'lines_add'}, " lines !\n"; + } + $log_by_file_revision{$file_name}{'1.1'}{'lines_rem'} = 0; +} + +print " => $nb_revisions revision(s) stored from ", scalar keys %files_visited, " file(s) in ", time() - $intermediate_time, " s. \n"; + +# ------------------------------------------------------------------------- +# Remove massive commits (copyright changes for example) + +print "Removing massive commits (> " . $args{"massive"} . ") ...\n"; + +$intermediate_time = time(); +my $nb_removed = 0; + +# Remove these changes that have been commited to more than 'n' files +# in the same day by the same author with same log message (= signature) + +foreach my $signature (sort { (scalar keys %{$log_revision_by_signature_file{$b}}) <=> (scalar keys %{$log_revision_by_signature_file{$a}}) } + keys %log_revision_by_signature_file) { + my @files = keys %{$log_revision_by_signature_file{$signature}}; + + if (scalar @files > $args{"massive"}) { + print " >> Removed: (" . scalar @files . ")\n " . + substr($signature, 0, 130) . "...\n\n" if exists $args{"verbose"}; + + foreach my $name (@files) { + foreach my $revision + (keys %{$log_revision_by_signature_file{$signature}{$name}}) { + ++$nb_removed; + delete $log_by_file_revision{$name}{$revision}; + } + } + } +} + +print " => ", $nb_revisions - $nb_removed, " revision(s) kept ($nb_removed revision(s) removed) in ", time() - $intermediate_time, " s. \n"; + +# ------------------------------------------------------------------------- +# Compute the contributions + +print "Contributing contributions (sum(added * ", $args{"lines_add"}, " + removed * ", $args{"lines_rem"}, "))...\n"; + +# %contribution_by_author_file is indexed by author and file name +# (i.e $contribution_by_author_file{$author}{$file_name}) +# stores the total contribution of this author for that specific file. + +my %contribution_by_author_file; + +# %contribution_by_author_date is indexed by author and date +# (i.e $contribution_by_author_date{$author}{$date}) +# stores the total *accumulative* contribution of this author up to that date. +# (computed it 2 steps) + +my %contribution_by_author_date; + +# %contribution_by_author_class is indexed by author and class name +# (i.e $contribution_by_author_class{$author}{$class_name}) +# stores the total contribution of this author for that specific class. + +my %contribution_by_author_class; + +# %classes is indexed by class name (i.e. $classes{$class_name}) +# {'files'}: (hash) all files describing that class (header, implem, etc.) +# {'creators'}: (hash) all creators (authors of rev 1.1) for that class +# {'contributors'}: (hash) all contributors for that class + +my %classes; + +# %not_class_file_by_author is indexed by author +# (i.e $not_class_file_by_author{$author}) +# (hash) files contributed by author but not part of a class group. + +my %not_class_file_by_author; + +$intermediate_time = time(); + +# Browse each file, each revision and use contribution + +foreach my $file_name (keys %files_visited) { + + # Check if file is part of a class group + + my $class_name = undef; + if (basename($file_name) =~ m/$args{"class_group"}/) { + $class_name = $1; + print " >> $class_name: $file_name\n" if exists $args{"verbose"}; + $classes{$class_name}{'files'}{$file_name} = 1; + $classes{$class_name}{'creators'}{$log_by_file_revision{$file_name}{'1.1'}{'author'}} = 1; + } + + foreach my $revision (keys %{$log_by_file_revision{$file_name}}) { + + my $author = $log_by_file_revision{$file_name}{$revision}{'author'}; + + # Store contribution + + my $revision_contribution = + $log_by_file_revision{$file_name}{$revision}{'lines_add'} * + $args{"lines_add"} + + $log_by_file_revision{$file_name}{$revision}{'lines_rem'} * + $args{"lines_rem"}; + + $contribution_by_author_file{$author}{$file_name} += + $revision_contribution; + + $contribution_by_author_date{$author}{$log_by_file_revision{$file_name}{$revision}{'date'}} += + $revision_contribution; + + # File is part of a class, store the whole class contributors + # and contributions + + if (defined($class_name)) { + + $classes{$class_name}{'contributors'}{$author} = 1; + + $contribution_by_author_class{$author}{$class_name} += + $revision_contribution; + } else { + $not_class_file_by_author{$author}{$file_name} = 1; + } + } +} + +print " => computed in ", time() - $intermediate_time, " s. \n"; + +# ------------------------------------------------------------------------- +# Find contributors for each class, update header + +print "Finding contributors > ", int($args{"min_contrib"} * 100.0), " and updating class headers...\n"; + +mkpath($args{"to"}); + +$intermediate_time = time(); +my $nb_updated = 0; + +my $class_name; +my @classes_names = sort { $b cmp $a } keys %classes; + +while (@classes_names) { + $class_name = pop @classes_names; + + # Sort the contributors for that class according to their + # respective contributions. + + my @class_contributors_sorted = + sort {$contribution_by_author_class{$b}{$class_name} <=> + $contribution_by_author_class{$a}{$class_name}} + keys %{$classes{$class_name}{'contributors'}}; + + # Compute the total contribution for that class + + my $total_class_contribution; + foreach my $class_contributor (@class_contributors_sorted) { + $total_class_contribution += + $contribution_by_author_class{$class_contributor}{$class_name}; + } + + # Find the class header name + + my $source_header_name = undef; + foreach my $file_name (keys %{$classes{$class_name}{'files'}}) { + if ($file_name =~ m/\.h$/) { + $source_header_name = $file_name; + last; + } + } + next if ! defined $source_header_name; + + # Figure out the name of the already-converted-to-doxygen header + # file using --to and --relativeto destination file now + + my $header; + + # If source has absolute path, just use the basename (unless a + # relativeto path has been set) otherwise remove the ../ component + # before the source filename, so that it might be appended to the + # "to" directory. + + if ($source_header_name =~ m/^(\/|[a-zA-W]\:[\/\\])/) { + if ($args{"relativeto"}) { + my ($dir, $absrel) = (abs_path(dirname($source_header_name)), + abs_path($args{"relativeto"})); + $dir =~ s/$absrel//; + $header = $args{"to"} . $dir . '/' . basename($source_header_name); + } else { + $header = $args{"to"} . '/' . basename($source_header_name); + } + } else { + $source_header_name =~ s/^(\.\.[\/\\])*//; + $header = $args{"to"} . '/' . $source_header_name; + } + + next if ! -e $header; + + # Read that header + + my $old_slurp = $/; + undef $/; # slurp mode + + if (!sysopen(HEADERFILE, + $header, + O_RDONLY|$open_file_as_text)) { + carp "$PROGNAME: unable to open $header\n"; + next; + } + + my $headerfile = ; + close(HEADERFILE); + + $/ = $old_slurp; + + # Search for the documentation block (@class ...) + + if ($headerfile !~ /(.*\/\*\!\s+)(\@class\s.+?)(\*\/.*)/gms) { + carp "$PROGNAME: no documentation block in $header ! (skipping)\n"; + next; + } + my ($pre, $block, $post) = ($1, $2, $3); + + # Create new doc section, insert it into block + + my $preamble = " \@par Created by:\n"; + + my $doc = $preamble . " - " . + join("\n - ", + sort map(exists $authors{$_}{'name'} ? $authors{$_}{'name'} : $_, keys %{$classes{$class_name}{'creators'}})) . "\n"; + + $doc .= "\n \@par CVS contributions (if > " . int(100.0 * $args{"min_contrib"}) . "%):\n"; + + foreach my $class_contributor (@class_contributors_sorted) { + my $ratio = + $contribution_by_author_class{$class_contributor}{$class_name} / + $total_class_contribution; + last if $ratio < $args{"min_contrib"}; + $doc .= " - " . (exists $authors{$class_contributor}{'name'} ? $authors{$class_contributor}{'name'} : $class_contributor) . " (" . int($ratio * 100.0) . "%)\n"; + } + + if (exists $args{"cvsweb"}) { + $doc .= "\n \@par CVS logs (CVSweb):\n"; + foreach my $file (keys %{$classes{$class_name}{'files'}}) { + my $shortname = get_short_relative_name($file, $args{"relativeto"}); + my ($base, $dir, $ext) = fileparse($shortname, '\..*'); + $doc .= ' - @htmlonly@endhtmlonly (@c ' . $shortname . ")\n"; + } + } + + if ($block !~ s/($preamble.+?)(\s*\@par|\z)/$doc$2/gms) { + $block .= "\n$doc"; + } + + # Write new header + + if (!sysopen(HEADERFILE, $header, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)) { + carp "$PROGNAME: unable to open $header\n"; + next; + } + + print HEADERFILE $pre . $block . $post; + close(HEADERFILE); + + print " >> Updating $header\n" if exists $args{"verbose"}; + + $nb_updated++; +} + +print " => $nb_updated header(s) updated in ", time() - $intermediate_time, " s. \n"; + +# ------------------------------------------------------------------------- +# Build the page summary documentation + +# $indent is the indentation string + +my $indent = " "; + +# $header is the Doxygen string summarizing what has been documented as well +# as the credits. + +my $header; +my (@summary, @credits); + +push @summary, + " - " . (scalar keys %contribution_by_author_file) . " authors(s) reported"; + +push @summary, + " - Files matching \@c " . $args{"files_in"} . " and not matching \@c ". $args{"files_out"} . " are taken into account"; + +push @summary, + " - $nb_revisions CVS revision(s) processed from " . (scalar keys %files_visited) . " matching file(s)"; + +push @summary, + " - " . ($nb_revisions - $nb_removed) . " revision(s) kept ($nb_removed revision(s) removed from 'massive commits' > " . $args{"massive"} . " changes per date/author/message)"; + +push @summary, + " - revision's contribution is " . $args{"lines_add"} . " * (number of lines added) + " . $args{"lines_rem"} . " * (number of lines removed)"; + +push @summary, + " - " . (scalar keys %classes) . " class(es) found (matching \@c " . $args{"class_group"} . ")"; + +push @credits, + "\@version $VERSION", + "\@author \@c $PROGNAME, by $AUTHOR"; + +$header = $indent . join("\n$indent", @summary) . "\n\n" . + $indent . join("\n$indent", @credits) . "\n\n"; + +# ------------------------------------------------------------------------- +# Update contributions stats + +# %contribution_by_author is indexed by author +# (i.e $contribution_by_author{$author}) +# stores the total contribution of this author for all files processed so far. + +my %contribution_by_author; + +# %contribution_by_date is indexed by date +# (i.e $contribution_by_date{$date}) +# stores the total *accumulative* contribution up to that date +# for all files processed so far. + +my %contribution_by_date; + +foreach my $contributor (keys %contribution_by_author_file) { + + foreach my $file_name + (keys %{$contribution_by_author_file{$contributor}}) { + $contribution_by_author{$contributor} += + $contribution_by_author_file{$contributor}{$file_name}; + } + + my $accumulate = 0; + + foreach my $date + (sort {$a cmp $b} keys %{$contribution_by_author_date{$contributor}}) { + $contribution_by_date{$date} += + $contribution_by_author_date{$contributor}{$date}; + $accumulate += $contribution_by_author_date{$contributor}{$date}; + $contribution_by_author_date{$contributor}{$date} = $accumulate; + } +} + +my $accumulate = 0; + +foreach my $date + (sort {$a cmp $b} keys %contribution_by_date) { + $accumulate += $contribution_by_date{$date}; + $contribution_by_date{$date} = $accumulate; + } + +my @all_contribution_dates = sort {$a cmp $b} keys %contribution_by_date; + +my $last_contribution_date = $all_contribution_dates[$#all_contribution_dates]; +my $first_contribution_date = $all_contribution_dates[0]; +my $total_contribution = $contribution_by_date{$last_contribution_date}; + +# ------------------------------------------------------------------------- +# Build documentation + +my $destination_file = $args{"to"} . "/" . $args{"store"}; +print "Building documentation to ", $destination_file, "\n"; + +sysopen(DEST_FILE, + $destination_file, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file $destination_file\n"; + +print DEST_FILE + "/*! \@page contributors Contributors\n\n$header"; + +print DEST_FILE + "\n$indent\@section contributors_alphabetical Contributors (by alphabetical order)\n\n"; + +sub compare_by_author_name { + my $a_name = exists $authors{$a}{'name'} ? $authors{$a}{'name'} : $a; + my $b_name = exists $authors{$b}{'name'} ? $authors{$b}{'name'} : $b; + return lc $a_name cmp lc $b_name; +} + +foreach my $contributor (sort compare_by_author_name + keys %contribution_by_author_file) { + + my $c_ratio = $contribution_by_author{$contributor} / $total_contribution; + + my $name = exists $authors{$contributor}{'name'} + ? $authors{$contributor}{'name'} : $contributor; + + if ($c_ratio < $args{"min_gcontrib"}) { + print DEST_FILE "$indent - $name\n"; + } else { + print DEST_FILE "$indent - \@ref $contributor \"$name\"\n"; + } +} + +print DEST_FILE + "\n$indent\@section contributors_decreasing Contributors (by decreasing order of global contribution)\n"; + +print DEST_FILE + "\n$indent\@note Contributions lower than " . int($args{"min_gcontrib"} * 10000.0) / 100.0 . "% are not listed\n\n"; + +my @contributors_sorted = + sort {$contribution_by_author{$b} <=> $contribution_by_author{$a}} + keys %contribution_by_author; + +foreach my $contributor (@contributors_sorted) { + + my $c_ratio = $contribution_by_author{$contributor} / $total_contribution; + last if $c_ratio < $args{"min_gcontrib"}; + + my $name = exists $authors{$contributor}{'name'} + ? $authors{$contributor}{'name'} : $contributor; + + print DEST_FILE "$indent -# \@ref $contributor \"$name\"\n"; +} + +foreach my $history (@{$args{"history_img"}}) { + my ($delta, $style, $filename) = split(/\|/, $history); + print DEST_FILE + "\n$indent\@image html " . basename($filename) . "\n"; +} + +print DEST_FILE + "\n$indent\@section contributors_detailed Detailed contributions (by decreasing order)\n"; + +print DEST_FILE + "\n$indent\@note Contributions lower than " . int($args{"min_gcontrib"} * 10000.0) / 100.0 . "% are not listed\n"; + +print DEST_FILE + "\n$indent\@note Details are:", + "\n$indent - % of global contribution at $last_contribution_date, % at date of last contribution, % at date of first contribution", + "\n$indent - first ", $args{"max_class_nb"}, " contributed classes > ", int($args{"min_class"} * 100.0), "% of author's total contribution", + "\n$indent - first ", $args{"max_file_nb"}, " contributed (non-class) files > ", int($args{"min_file"} * 100.0), "% of author's total contribution", + "\n\n"; + +foreach my $contributor (@contributors_sorted) { + + # Yes, you can have 0 contrib: + # vtkPiecewiseFunction.cxx:date: 1999/11/03 18:11:39; + # author: tpan; state: Exp; lines: +0 -0 + + next if $contribution_by_author{$contributor} == 0; + + my $c_ratio = $contribution_by_author{$contributor} / $total_contribution; + last if $c_ratio < $args{"min_gcontrib"}; + + # Classes + + my @ok_classes; + + my @classes_sorted = + sort {$contribution_by_author_class{$contributor}{$b} <=> + $contribution_by_author_class{$contributor}{$a}} + keys %{$contribution_by_author_class{$contributor}}; + + foreach my $class_name (@classes_sorted) { + last if scalar @ok_classes > $args{"max_class_nb"}; + my $ratio = + $contribution_by_author_class{$contributor}{$class_name} / + $contribution_by_author{$contributor}; + last if $ratio < $args{"min_class"}; + push @ok_classes, "$class_name (" . int($ratio * 100.0) . "%)"; + } + + # Files + + my @ok_files; + + my @files_sorted = + sort {$contribution_by_author_file{$contributor}{$b} <=> + $contribution_by_author_file{$contributor}{$a}} + keys %{$not_class_file_by_author{$contributor}}; + + foreach my $file_name (@files_sorted) { + next if basename($file_name) =~ m/$args{"class_group"}/; + last if scalar @ok_files > $args{"max_file_nb"}; + my $ratio = + $contribution_by_author_file{$contributor}{$file_name} / + $contribution_by_author{$contributor}; + last if $ratio < $args{"min_file"}; + push @ok_files, get_short_relative_name($file_name, $args{"relativeto"}) . " (" . int($ratio * 100.0) . "%)"; + } + + my $name = exists $authors{$contributor}{'name'} + ? $authors{$contributor}{'name'} . " ($contributor)" : $contributor; + + print DEST_FILE "$indent -# \@anchor $contributor \@b $name:\n"; + + my @contribution_dates = sort { $a cmp $b } + keys %{$contribution_by_author_date{$contributor}}; + + my $last_contrib_date = $contribution_dates[$#contribution_dates]; + my $first_contrib_date = $contribution_dates[0]; + + print DEST_FILE + "$indent - \@b ", int(10000.0 * $c_ratio) / 100, "% ($last_contribution_date), ", int(10000.0 * ($contribution_by_author_date{$contributor}{$last_contrib_date} / $contribution_by_date{$last_contrib_date})) / 100, "% ($last_contrib_date), ", int(10000.0 * ($contribution_by_author_date{$contributor}{$first_contrib_date} / $contribution_by_date{$first_contrib_date})) / 100, "% ($first_contrib_date)\n"; + + print DEST_FILE + "$indent - ", (scalar @classes_sorted), " class(es): ", join(", ", @ok_classes), "...\n" if @classes_sorted; + + print DEST_FILE + "$indent - ", (scalar @files_sorted), " file(s): ", join(", ", @ok_files), "...\n" if @files_sorted; +} + +print DEST_FILE "\n*/\n\n"; + +# ------------------------------------------------------------------------- +# Create history files + +print "Creating history files in ", $args{"history_dir"}, "\n"; + +mkpath($args{"history_dir"}); + +foreach my $contributor (@contributors_sorted) { + my $history_name = $args{"history_dir"} . "/$contributor.dat"; + + sysopen(HISTORY_FILE, + $history_name, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open history file $history_name\n"; + + foreach my $date + (sort {$a cmp $b} keys %{$contribution_by_author_date{$contributor}}) { + print HISTORY_FILE $date . ' ' . ($contribution_by_author_date{$contributor}{$date} / $contribution_by_date{$date}) * 100.0 . "\n"; + } + + close(HISTORY_FILE); +} + +# ------------------------------------------------------------------------- +# Create gnuplot file + +print "Creating gnuplot command file\n", $args{"gnuplot_file"}, "\n"; + +my ($year, $month, $mday) = split('-', $last_contribution_date); + +my $last_contribution_sec = timelocal(0, 0, 0, $mday, $month -1 , $year-1900); + +my $history_dir_abs = abs_path($args{"history_dir"}); + +my @plots; +foreach my $contributor (@contributors_sorted) { + last if scalar @plots >= $args{"history_max_nb"}; + my $history_filename = $history_dir_abs . "/$contributor.dat"; + push @plots, "\"$history_filename\" using 1:2 title \"" . (exists $authors{$contributor}{'name'} ? $authors{$contributor}{'name'} : $contributor) . "\"" if -e $history_filename; +} + +my $plot = 'plot ' . join(', ', @plots); + +sysopen(GNUPLOT_FILE, + $args{"gnuplot_file"}, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open gnuplot command file " . $args{"gnuplot_file"} . "\n"; + +print GNUPLOT_FILE < +# +# Convert VTK headers to doxygen format +# +# roeim : Vetle Roeim +# barre : Sebastien Barre +# +# 0.9 (barre) : +# - add --conds : add \cond...\endcond around public:, private:, protected: +# +# 0.83 (barre) : +# - add --stdout : print converted file to standard output +# +# 0.82 (barre) : +# - add --relativeto path : each file/directory to document is considered +# relative to 'path', where --to and --relativeto should be absolute +# +# 0.81 (barre) : +# - fix pb if both --to and path to the file to document were absolute +# - remove warning when date or revision not found +# +# 0.8 (barre) : +# - update to match the new VTK 4.0 tree +# - change default --dirs so that it can be launched from Utilities/Doxygen +# - change default --to so that it can be launched from Utilities/Doxygen +# - handle more .SECTION syntax +# - add group support (at last) +# +# 0.76 (barre) : +# - add 'parallel' to the default set of directories +# +# 0.75 (barre) : +# - change default --to to '../vtk-doxygen' to comply with Kitware's doxyfile +# +# 0.74 (barre) : +# - as doxygen now handles RCS/CVS tags of the form $word:text$, use them +# +# 0.73 (barre) : +# - change doxygen command style from \ to @ to match javadoc, autodoc, etc. +# +# 0.72 (barre) : +# - change default --to to '../vtk-dox' +# +# 0.71 (barre) : +# - fix O_TEXT flag problem +# - switch to Unix CR/LF format +# +# 0.7 (barre) : +# - change name +# - remove -c option +# +# 0.6 (barre) : +# - change (warning) default --to to '../vtk2' because I ruined my own +# VTK distrib too many times :( +# - add automatic creation of missing directory trees +# - add check for current OS (if Windows, do not perform tests based +# on stat()/idev/ino features) +# +# 0.5 (barre) : +# - better .SECTION handling +# - add support for empty lines in documentation block +# - fix problem with headers not corresponding to classes +# - change name to doc_header2doxygen (removed vtk_) +# - change '-s' (silent) to '-v' (verbose) +# - add function description reformatting +# +# 0.4 (barre) : +# - change /*! ... */ position upon request +# - add 'Date:' support as @date +# - add 'Version:' support as @version +# - add 'Thanks:' support as @par Thanks +# +# 0.3 (barre) : +# - fix various " // Description" spelling problems :) +# +# 0.2 (barre) : +# - fix problem with classes with no brief documentation +# +# 0.1 (barre) : +# - add Perl syntactic sugar, options... +# - add standard output (filter) mode (-c) +# - add silent mode (-s) +# - add update mode, convert only if newer (-u) +# - add conversion to another directory (--to) +# - add '.SECTION Caveats' support as @warning +# - add/fix '.SECTION whatever' support as @par +# - add default directories to process +# +# 0.0 (roeim) +# - first release (thanks to V. Roeim !) + + +use Carp; +use Cwd 'abs_path'; +use Getopt::Long; +use Fcntl; +use File::Basename; +use File::Find; +use File::Path; +use Text::Wrap; +use strict; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.9, $0, "Sebastien Barre et al."); +$PROGNAME =~ s/^.*[\\\/]//; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want: "verbose" => 1 for default verbose mode) + +my %default = + ( + dirs => ["../../Common", + "../../Filtering", + "../../GenericFiltering", + "../../GenericFiltering/Testing/Cxx", + "../../Graphics", + "../../GUISupport/MFC", + "../../GUISupport/Qt", + "../../Hybrid", + "../../Imaging", + "../../IO", + "../../Parallel", + "../../Patented", + "../../Rendering", + "../../VolumeRendering"], + relativeto => "", + temp => "doc_header2doxygen.tmp", + to => "../../../VTK-doxygen" + ); + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "verbose|v", "update|u", "conds|c", "force|f", "temp=s", "to=s", "stdout", "relativeto=s"); + +print "$PROGNAME $VERSION, by $AUTHOR\n" if ! exists $args{"stdout"}; + +if (exists $args{"help"}) { + print <<"EOT"; +Usage : $PROGNAME [--help] [--verbose|-v] [--update|-u] [--conds|-c] [--force|-f] [--temp file] [--to path] [--relativeto path] [files|directories...] + --help : this message + --verbose|-v : verbose (display filenames while processing) + --update|-u : update (convert only if newer, requires --to) + --force|-f : force conversion for all files (overrides --update) + --stdout : print converted file to standard output + --temp file : use 'file' as temporary file (default: $default{temp}) + --to path : use 'path' as destination directory (default: $default{to}) + --relativeto path : each file/directory to document is considered relative to 'path', where --to and --relativeto should be absolute (default: $default{relativeto}) + --conds|-c : use \cond sections around public, protected, private + +Example: + $PROGNAME --to ../vtk-doxygen + $PROGNAME contrib +EOT + exit; +} + +$args{"verbose"} = 1 if exists $default{"verbose"}; +$args{"update"} = 1 if exists $default{"update"}; +$args{"conds"} = 1 if exists $default{"conds"}; +$args{"force"} = 1 if exists $default{"force"}; +$args{"temp"} = $default{temp} if ! exists $args{"temp"}; +$args{"to"} = $default{"to"} if ! exists $args{"to"}; +$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"}; +$args{"relativeto"} = $default{"relativeto"} if ! exists $args{"relativeto"}; +$args{"relativeto"} =~ s/[\\\/]*$// if exists $args{"relativeto"}; + +croak "$PROGNAME: --update requires --to\n" + if exists $args{"update"} && ! exists $args{"to"}; + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Collect all files and directories + +push @ARGV, @{$default{dirs}} if !@ARGV; + +print "Collecting...\n" if ! exists $args{"stdout"}; +my @files; +foreach my $file (@ARGV) { + if (-f $file) { + push @files, $file; + } elsif (-d $file) { + find sub { push @files, $File::Find::name; }, $file; + } +} + +# ------------------------------------------------------------------------- +# Process files corresponding to headers + +print "Converting...\n" if ! exists $args{"stdout"}; +my $intermediate_time = time(); +my $nb_file = 0; + +foreach my $source (@files) { + + next if $source !~ /vtk[^\\\/]*\.h\Z/; + + # Figure out destination file now + + my $dest; + if (! exists $args{"to"}) { + $dest = $args{"temp"}; + } else { + # if source has absolute path, just use the basename, unless a + # relativeto path has been set + if ($source =~ m/^(\/|[a-zA-W]\:[\/\\])/) { + if ($args{"relativeto"}) { + my ($dir, $absrel) = (abs_path(dirname($source)), + abs_path($args{"relativeto"})); + $dir =~ s/$absrel//; + $dest = $args{"to"} . $dir . '/' . basename($source); + } else { + $dest = $args{"to"} . '/' . basename($source); + } + } else { + my $source2 = $source; + # let's remove the ../ component before the source filename, so + # that it might be appended to the "to" directory + $source2 =~ s/^(\.\.[\/\\])*//; + $dest = $args{"to"} . '/' . $source2; + } + # Ensure both source and target are different + if (!$os_is_win) { + my ($i_dev, $i_ino) = stat $source; + my ($o_dev, $o_ino) = stat $dest; + croak "$PROGNAME: sorry, $source and $dest are the same file\n" + if ($i_dev == $o_dev && $i_ino == $o_ino); + } + } + + # Update mode : skip the file if it is not newer than the + # previously converted target + + if (exists $args{"update"} && ! exists $args{"force"}) { + next if -e $dest && (stat $source)[9] < (stat $dest)[9]; + } + + ++$nb_file; + print " $source\n" if exists $args{"verbose"}; + + # Open file, feed it entirely to an array + + sysopen(HEADERFILE, $source, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $source\n"; + my @headerfile = ; + close(HEADERFILE); + + my ($date, $revision) = ("", ""); + my @converted = (); + my @thanks = (); + + # Parse the file until the beginning of the documentation block + # is found. The copyright and disclaimer sections are parsed to + # extract the 'Date', 'Version' and 'Thanks' values. + + my $line; + while ($line = shift @headerfile) { + + # Quit if the beginning of the documentation block has been reached. + # It is supposed to start with: + # // .NAME vtkFooBar - foo bar class + + last if $line =~ /\/\/ \.NAME/; + + # Date. Example: + # Date: $Date: 2005/06/23 21:48:34 $ + + if ($line =~ /^\s*Date:\s*(.*)$/) { + $date = $1; + + # Version. Example: + # Version: $Revision: 1.13 $ + + } elsif ($line =~ /^\s*Version:\s*(.*)$/) { + $revision = $1; + + # Thanks (maybe multi-lines). Example: + # Thanks: Thanks to Sebastien Barre who developed this class. + + } elsif ($line =~ /^\s*Thanks:\s*(.*)$/) { + push @thanks, " ", $1, "\n"; + # Handle multi-line thanks + while ($line = shift @headerfile) { + last if $line =~ /^\s*$/; + $line =~ s/^(\s*)//; + push @thanks, " ", $line; + } + push @converted, $line; + + # Everything else goes to the converted file + + } else { + push @converted, $line; + } + } + + # Process the documentation block + # Extract the name of the class and its short description + # // .NAME vtkFooBar - foo bar class + + if (defined($line) && $line =~ /\/\/ \.NAME (\w*)( \- (.*))?/) { + + my ($class_name, $class_short_description) = ($1, $3); + $class_name =~ s/\.h//; + + # Insert class description, date, revision, thanks + + push @converted, "/*! \@class $class_name\n"; + push @converted, " \@brief $class_short_description\n" + if $class_short_description; + + if ($date) { + push @converted, "\n $date\n"; + } + + # WARNING : need a blank line between RCS tags and previous dox tag + + if ($revision) { + push @converted, "\n" if (!$date); + push @converted, " $revision\n"; + } + + # Do not add thanks anymore. Will be done externally. + # push @converted, " \@par Thanks:\n", @thanks if @thanks; + + # Read until the end of the documentation block is reached + # Translate 'See Also', 'Caveats' and whatever .SECTION + # As of 24 sep 2001, there are: + # 137 // .SECTION Caveats + # 1 // .SECTION Credits + # 702 // .SECTION Description + # 3 // .SECTION Note + # 1 // .SECTION note + # 329 // .SECTION See Also + # 4 // .SECTION See also + # 70 // .SECTION see also + # 1 // .SECTION Warning + # find . -name vtk\*.h -exec grep "\.SECTION" {} \; | sort | uniq -c + # Let's provide support for bugs too: + # // .SECTION Bug + # // .SECTION Bugs + # // .SECTION Todo + + my ($tag, $inblock) = ("", 0); + while ($line = shift @headerfile) { + + # Quit if the end of the documentation block has been reached. + # Let'say that it is supposed to end as soon as the usual + # inclusion directives are found, for example: + # #ifndef __vtkAbstractTransform_h + # #define __vtkAbstractTransform_h + + last if $line =~ /^\#/; + + # Process and recognize a .SECTION command and convert it to + # the corresponding doxygen tag ($tag) + + if ($line =~ /^\/\/\s+\.SECTION\s+(.+)\s*$/i) { + + my $type = $1; + + # Bugs (@bugs). Starts with: + # // .SECTION Bug + # // .SECTION Bugs + + if ($type =~ /Bugs?/i) { + $tag = "\@bug"; + } + + # Caveats or Warnings (@warning). Starts with: + # // .SECTION Caveats + # // .SECTION Warning + # // .SECTION Warnings + + elsif ($type =~ /(Caveats|Warnings?)/i) { + $tag = "\@warning"; + } + + # Description. Starts with: + # // .SECTION Description + + elsif ($type =~ /Description/i) { + $tag = ""; + push @converted, "\n"; + } + + # Note (@attention). Starts with: + # // .SECTION Note + + elsif ($type =~ /Note/i) { + $tag = "\@attention"; + } + + # See also (@sa). Starts with: + # // .SECTION See Also + + elsif ($type =~ /See Also/i) { + $tag = "\@sa"; + } + + # Todo (@todo). Starts with: + # // .SECTION Todo + + elsif ($type =~ /Todo/i) { + $tag = "\@todo"; + } + + # Any other .SECTION (@par). Starts with: + # // .SECTION whatever + + else { + $tag = "\@par " . $type . ":"; + } + + $inblock = 0; + } + + # If the line starts with '//', we are still within the tag block. + # Remove '//' for non empty lines, eventually put or duplicate + # the tag name if an empty comment is found (meaning that a new + # 'paragraph' is requested but with the same tag type) + # Example: + # // .SECTION Caveats + # // blabla1q + # // blabla1b + # // + # // blabla2 + # Gets translated into: + # @warning + # blabla1q + # blabla1b + # + # @warning + # blabla2 + + elsif ($line =~ /^\/\/(.*)/) { + my $remaining = $1; + if ($remaining =~ /\S/) { + push @converted, " $tag\n" + if $tag ne "" && ! $inblock; + push @converted, $remaining, "\n"; + $inblock = 1; + } else { + push @converted, "\n"; + $inblock = 0; + } + } else { + # Does not starts with // but still within block or just + # before the end (#). Probably an empty line. + # Hack : let's have a look at the next line... if it begins + # with // then the current line is included (was a space). + + if (my $next_line = shift @headerfile) { + push @converted, $line if $next_line =~ /^\/\//; + unshift @headerfile, $next_line; + } + } + } + + # Close the doxygen documentation block describing the class + + push @converted, "*/\n\n", $line; + } + + # Read until the end of the header and translate the description of + # each function provided that it is located in a C++ comment + # containing the 'Description:' keyword. + # Example: + # // Description: + # // Construct with automatic computation of divisions, averaging + # // 25 points per bucket. + # static vtkPointLocator2D *New(); + + my $in_section = ""; + + while ($line = shift @headerfile) { + + # Track the public:, protected: and private: sections and put them + # between \cond... \endcond so that they can be removed from the + # documentation conditionally. Add them to ENABLED_SECTION + # to show them. + # IMPORTANT: *no* spaces are allowed between the beginning of the + # line and the qualifier. This is mandatory to solve issues + # with nested class definitions, since it is non-trivial to + # track the fact that we are leaving a class definition to + # re-enter the parent class definition, etc. + + if (exists $args{"conds"}) { + if ($line =~ /^(public|protected|private):/) { + if ($in_section ne "") { + push @converted, "// \@endcond\n"; + } + $in_section = $1; + push @converted, "// \@cond section_$in_section\n"; + } + } + + if ($line =~ /^(\s*)\/\/\s*De(s|c)(s|c)?ription/) { + + my $indent = $1; + $Text::Wrap::columns = 76; + + # While there are still lines beginning with '//' append them to + # the function's description and trim spaces. + + my @description = (); + while ($line = shift @headerfile) { + last if $line !~ /^\s*\/\//; + chop $line; + $line =~ s/^\s*\/\/\s*//; + $line =~ s/\s*$//; + push @description, $line; + } + + # While there are non-empty lines add these lines to the + # list of declarations (and/or inline definitions) + # pertaining to the same description. + + my @declarations = (); + while ($line && $line =~ /\s+\S/) { + push @declarations, $line; + $line = shift @headerfile + } + + # If there is more than one declaration or at least a macro, + # enclose in a group (actually a single multiline declaration will + # be enclosed too, but who cares :)... + + my $enclose = + (scalar @declarations > 1 || $declarations[0] =~ /vtk.+Macro/); + + push @converted, "$indent//@\{\n" if $enclose; + push @converted, + wrap("$indent/*! ", "$indent ", @description), " */\n" + if @description; + push @converted, @declarations; + push @converted, "$indent//@\}\n" if $enclose; + } + + push @converted, $line; + } + + if (exists $args{"conds"}) { + if ($in_section ne "") { + push @converted, "// \@endcond"; + } + } + + # Write the converted header to its destination + # or to standard output. + + if (exists $args{"stdout"}) { + + print @converted; + + } else { + + # Open the target and create the missing directory if any + + if (!sysopen(DEST_FILE, + $dest, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)) { + my $dir = dirname($dest); + mkpath($dir); + sysopen(DEST_FILE, + $dest, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file $dest\n"; + } + print DEST_FILE @converted; + close(DEST_FILE); + + # If in-place conversion was requested, remove source and rename target + # (or temp file) to source + + if (! exists $args{"to"}) { + unlink($source) + or carp "$PROGNAME: unable to delete original file $source\n"; + rename($args{"temp"}, $source) + or carp "$PROGNAME: unable to rename ", $args{"temp"}, " to $source\n"; + } + } +} + +if (! exists $args{"stdout"}) { + print " => $nb_file files converted in ", time() - $intermediate_time, " s. \n"; + print "Finished in ", time() - $start_time, " s.\n"; +} diff --git a/Utilities/Doxygen/doc_index.pl b/Utilities/Doxygen/doc_index.pl new file mode 100644 index 0000000..d7b7c29 --- /dev/null +++ b/Utilities/Doxygen/doc_index.pl @@ -0,0 +1,675 @@ +#!/usr/bin/env perl +# Time-stamp: <2001-11-21 17:40:48 barre> +# +# Build full-text index +# +# barre : Sebastien Barre +# +# 0.22 (barre) : +# - use common build_page_doc proc +# +# 0.21 (barre) : +# - add --project name : project name, used to uniquify +# +# 0.2 (barre) : +# - update to match the new VTK 4.0 tree +# - change default --dirs so that it can be launched from Utilities/Doxygen +# - change default --stop so that it can be launched from Utilities/Doxygen +# - change default --to so that it can be launched from Utilities/Doxygen +# - the "class to example" page is now split in different pages +# - use --weight to increase or decrease the maximum weight of a page +# +# 0.16 (barre) : +# - added 'parallel' to the default set of directories +# +# 0.15 (barre) : +# - change default --to to '../vtk-doxygen' to comply with Kitware's doxyfile +# - change default --stop to 'wrap/doc_index.stop' to comply with the source +# tree structure. +# +# 0.14 (barre) : +# - change doxygen command style from \ to @ to match javadoc, autodoc, etc. +# +# 0.13 (barre) : +# - change default --to to '../vtk-dox' +# +# 0.12 (barre) +# - change relevancy sorting : for each word, classes are sorted by presence +# of the word in the class name, *then* by occurence of the word in the +# class documentation, *then* by alphabetical order +# +# 0.11 (barre) +# - fix O_TEXT flag problem +# - switch to Unix CR/LF format +# +# 0.1 (barre) +# - first release + +use Carp; +use Getopt::Long; +use Fcntl; +use File::Find; +use strict; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.22, $0, "Sebastien Barre"); +$PROGNAME =~ s/^.*[\\\/]//; +print "$PROGNAME $VERSION, by $AUTHOR\n"; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want : "verbose" => 1 for default verbose mode) + +my %default = + ( + limit => 10, + dirs => ["../../Common", + "../../Filtering", + "../../GenericFiltering", + "../../GenericFiltering/Testing/Cxx", + "../../Graphics", + "../../GUISupport/MFC", + "../../GUISupport/Qt", + "../../Hybrid", + "../../Imaging", + "../../IO", + "../../Parallel", + "../../Patented", + "../../Rendering", + "../../VolumeRendering"], + project => "VTK", + stop => "doc_index.stop", + store => "doc_VTK_index.dox", + to => "../../../VTK-doxygen", + weight => 90000 + ); + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "verbose|v", "debug", "limit=i", "project=s", "stop=s", "store=s", "to=s", "weight=i"); + +if (exists $args{"help"}) { + print <<"EOT"; +Usage : $PROGNAME [--help] [--verbose|-v] [--limit n] [--stop file] [--store file] [--to path] [--weight n] [files|directories...] + --help : this message + --verbose|-v : verbose (display filenames while processing) + --limit n : limit the number of xrefs per word (default: $default{limit}) + --project name : project name, used to uniquify (default: $default{project}) + --stop file : use 'file' to read stop-words (default: $default{stop}) + --store file : use 'file' to store index (default: $default{store}) + --to path : use 'path' as destination directory (default : $default{to}) + --weight n : use 'n' as an approximation of the maximum page weight (default : $default{weight}) + +Example: + $PROGNAME +EOT + exit; +} + +$args{"debug"} = $default{"debug"} if exists $default{"debug"}; +$args{"verbose"} = 1 if exists $default{"verbose"}; +$args{"limit"} = $default{"limit"} if ! exists $args{"limit"}; +$args{"project"} = $default{"project"} if ! exists $args{"project"}; +$args{"stop"} = $default{"stop"} if ! exists $args{"stop"}; +$args{"store"} = $default{"store"} if ! exists $args{"store"}; +$args{"to"} = $default{"to"} if ! exists $args{"to"}; +$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"}; +$args{"weight"} = $default{"weight"} if ! exists $args{"weight"}; + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Read the stop-words + +print "Reading stop-words from $args{stop}...\n"; + +sysopen(STOPFILE, $args{"stop"}, O_RDONLY|$open_file_as_text) + or die "$PROGNAME: unable to open stop words list $args{stop}\n"; +my @stop_file = ; +close(HEADERFILE); + +my %stop_words; +foreach my $stop_word (@stop_file) { + if ($stop_word && $stop_word !~ m/^\s*#/) { + chop $stop_word; + $stop_words{$stop_word} = 1; + } +} + +print " => ", scalar keys %stop_words, " stop-word(s) read.\n"; + +# ------------------------------------------------------------------------- +# Collect all files and directories + +print "Collecting files...\n"; + +push @ARGV, @{$default{dirs}} if !@ARGV; + +my @files; +foreach my $file (@ARGV) { + if (-f $file) { + push @files, $file; + } elsif (-d $file) { + find sub { push @files, $File::Find::name; }, $file; + } +} + +# ------------------------------------------------------------------------- +# Index files corresponding to headers + +print "Indexing...\n"; +my $intermediate_time = time(); + +# %index associates a word with a class name and reports how many times that +# word was found in that comment. +# Example: $index{"contour"}{"vtkMarchingCubes"} = 2 + +my %index; +keys(%index) = 7000; +my %group; + +my $nb_files = 0; +undef $/; # slurp mode + +foreach my $source (@files) { + + # Skip what is not a vtk header + + next if $source !~ /(vtk[^\\\/]*)\.h\Z/; + my $class = $1; + + ++$nb_files; + print " $source\n" if exists $args{"verbose"}; + + # Open the file, read it entirely + + sysopen(HEADERFILE, $source, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $source\n"; + my $headerfile = ; + close(HEADERFILE); + + # Grab all comments then skip the first one (preamble and copyright stuff) + + my @comments = $headerfile =~ m/(?:\/\*(.+?)\*\/|\/\/(.+?)$)/gms; + shift @comments; + + # Grab (and count) each word in each comment and associate it with + # the class name + + foreach my $comment (@comments) { + next if ! $comment; + my @words = $comment =~ m/\b([A-Za-z][A-Za-z-]*[A-Za-z]+)\b/gms; + foreach my $word (@words) { + $index{$word}{$class}++ if $word; + } + } +} + +my @words = keys %index; +print " => ", scalar @words, " word(s) grabbed in $nb_files file(s) in ", time() - $intermediate_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Remove some words + +print "Removing...\n"; + +my $nb_removed = 0; +foreach my $word (@words) { + my ($len, $lcw, $ucw) = (length($word), lc($word), uc($word)); + if ($len <= 2 || # too small + ($len == 3 && $ucw ne $word) || # small and not an accronym + (ucfirst($word) ne ucfirst($lcw) && $ucw ne $word) || # mixed case + $word =~ m/^vtk/ || # VTK function/class + exists $stop_words{lc($word)}) { # found in stop-words + delete $index{$word}; + ++$nb_removed; + } +} + +print " => $nb_removed word(s) removed.\n"; + +# ------------------------------------------------------------------------- +# Group some words + +print "Grouping...\n"; + +sub transfer_keys { + my ($rfrom, $rto) = @_; + foreach my $key (keys %$rfrom) { + $rto->{$key} += $rfrom->{$key}; + } +} + +@words = sort keys %index; +my $nb_grouped = 0; + +foreach my $word (@words) { + + my ($len, $lcw, $similar) = (length($word), lc($word)); + my (@similars, %verbs, %exts) = ((), (), ()); + + # Now first try to get a list of words similar to the current one + + # Lowercase form ? + + if ($word ne $lcw) { + push @similars, $lcw; + } + + # Singular form ? + + if ($word =~ m/s$/i) { + $similar = substr($word, 0, $len - 1); + push @similars, lc($similar), $similar; + } + + # Singular form ? (dashes -> dash) + + if ($word =~ m/[hsx]es$/i) { + $similar = substr($word, 0, $len - 2); + push @similars, lc($similar), $similar; + + # Singular form ? (leaves -> leaf) + + } elsif ($word =~ m/ves$/i) { + $similar = substr($word, 0, $len - 3) . 'f'; + push @similars, lc($similar), $similar; + } + + # Colour -> color + + if ($word =~ m/our$/i) { + $similar = substr($word, 0, $len - 2) . 'r'; + push @similars, lc($similar), $similar; + } + + # Thick -> thickness + + if ($word =~ m/ness$/i) { + $similar = substr($word, 0, $len - 4); + push @similars, lc($similar), $similar; + } + + # Explicitly -> explicit + + if ($word =~ m/ly$/i) { + $similar = substr($word, 0, $len - 2); + push @similars, lc($similar), $similar; + } + + # Accuracy -> accurate + + if ($word =~ m/acy$/i) { + ($similar = $word) =~ s/cy$/te/i; + push @similars, lc($similar), $similar; + } + + # Rounded, rounding -> round + + if ($word =~ m/.{4,}(ed|ing|ten)$/i) { + $exts{$1} = 1; + ($similar = $word) =~ s/(ed|ing|ten)$//i; + $verbs{$similar} = 1; + } + + # Not try to see if it's not a verb (and keep its "extension") + + # Mapped, mapping -> map + + if ($word =~ m/.{3,}[bglmnpt](ed|ing)$/i) { + $exts{$1} = 1; + ($similar = $word) =~ s/[bglmnpt](ed|ing)$//i; + $verbs{$similar} = 1; + } + + # Applied -> apply + + if ($word =~ m/.{3,}(ied)$/i) { + $exts{$1} = 1; + ($similar = $word) =~ s/ied$/y/i; + $verbs{$similar} = 1; + } + + # Description -> descript + + if ($word =~ m/.{4,}[ts](ion)s?$/i) { + $exts{$1} = 1; + ($similar = $word) =~ s/ions?$//i; + $verbs{$similar} = 1; + } + + # Now we have a list of verb and extension, try to associate each verb + # with these extensions that were not found and build a list of similar + # "words" by concatenating both. + + my @verbs = keys %verbs; + if (@verbs) { + my %try = ("" => 1, + "e" => 1, + "ed" => 1, "ied" => 1, + "es" => 1, + "ing" => 1, + "ion" => 1, + "s" => 1, + "ten" => 1); + foreach my $ext (sort keys %exts) { + delete $try{$ext}; + } + foreach my $verb (@verbs) { + my $lcverb = lc $verb; + print " -> ", $lcverb, "\n" if exists $args{"debug"}; + foreach my $ext (sort keys %try) { + print " +> ", $lcverb . $ext, "\n" if exists $args{"debug"}; + push @similars, $lcverb . $ext, $verb . $ext; + } + } + } + + # Browse each similar word. It it already exists in the index then group + # the current word with it and remove the word from the index. + + foreach $similar (@similars) { + if (exists $index{$similar}) { + print "- grouping $word with $similar\n" if exists $args{"debug"}; + transfer_keys(\%{$index{$word}}, \%{$index{$similar}}); + delete $index{$word}; + $group{$similar}{$word}++; + transfer_keys(\%{$group{$word}}, \%{$group{$similar}}); + delete $group{$word}; + ++$nb_grouped; + last; + } + } +} + +print " => $nb_grouped word(s) grouped.\n"; + +# ------------------------------------------------------------------------- +# Normalize to lowercase except if all uppercase + +print "Normalizing...\n"; + +@words = keys %index; +foreach my $word (@words) { + my $lcw = lc $word; + + # Normalize word to lowercase + + if ($word ne uc($word) && $word ne $lcw) { + transfer_keys(\%{$index{$word}}, \%{$index{$lcw}}); + delete $index{$word}; + transfer_keys(\%{$group{$word}}, \%{$group{$lcw}}); + delete $group{$word}; + } + + # Normalize group to lowercase + + if (exists $group{$word}) { + foreach my $gword (keys %{$group{$word}}) { + my $lcgw = lc $gword; + if ($gword ne uc($gword) && $gword ne $lcgw) { + $group{$word}{$lcgw} = $group{$word}{$gword}; + delete $group{$word}{$gword}; + } + } + delete $group{$word}{$word}; + } +} + +print " => normalized to lowercase.\n"; + +# ------------------------------------------------------------------------- +# Build the page summary documentation + +# $indent is the indentation string + +my $indent = " "; + +# $header is the Doxygen string summarizing what has been documented as well +# as the credits. + +my $header; +my (@summary, @credits); + +push @summary, + " - $nb_files file(s) indexed by " . scalar @words . " word(s) on " . + localtime(), + " - max limit is " . $args{"limit"} . " xref(s) per word"; + +push @credits, + "\@version $VERSION", + "\@author \@c $PROGNAME, by $AUTHOR"; + +$header = $indent . join("\n$indent", @summary) . + "\n\n$indent" . join("\n$indent", @credits) . "\n\n"; + +# ------------------------------------------------------------------------- +# Index to class + +print "Building page doc...\n"; + +# @words is the array of words to document + +my @words = sort keys %index; + +# $prefix is a unique prefix that is appended to each link + +my $prefix = "idx_" . $args{"project"}; +$prefix = lc($prefix); + +# word_section_name returns the short string describing a word section + +sub word_section_name { + my ($word) = @_; + my @group = sort keys %{$group{$word}}; + $word .= " (" . join(", ", @group) . ")" if @group; + return $word; +} + +# word_section_doc returns the doxygen doc for a word + +sub word_section_doc { + my ($word) = @_; + my @xrefs = sort { (($b =~ m/$word/i) <=> ($a =~ m/$word/i)) || ($index{$word}{$b} <=> $index{$word}{$a}) || ($a cmp $b)} (keys %{$index{$word}}); + my @xrefs_lim; + my $count = 0; + foreach my $xref (@xrefs) { + last if ++$count > $args{"limit"}; + push @xrefs_lim, $xref . " (" . $index{$word}{$xref} . ")"; + } + my $string = " - " . join(", ", @xrefs_lim); + $string .= ", [...]" if scalar keys %{$index{$word}} > $args{"limit"}; + return $string . "\n"; +} + +# word_section_alpha returns the single alpha char corresponding to that +# word's section. + +sub word_section_alpha { + my ($word) = @_; + $word =~ /^(\w)/; + return $1; +} + +my $page_doc = build_page_doc($indent, + "Full-text Index", + \@words, + $prefix, + \&word_section_name, + \&word_section_doc, + \&word_section_alpha, + $header, + "", + $args{"to"} . "/" . $args{"store"}); + +print join("\n", @summary), "\n"; +print "Finished in ", time() - $start_time, " s.\n"; + +# ------------------------------------------------------------------------- + +sub build_page_doc { + + # $indent is the indentation string + # $rwords is a reference to the array of words to document + # $prefix is a unique prefix that is appended to each link + # word_section_name returns the short string describing a word section + # word_section_doc returns the doxygen doc for a word + # word_section_alpha returns the single alpha char corresponding to that + # word's section. + # $header is the Doxygen string summarizing what has been documented as + # well as the credits. + # $footer is a Doxygen string appended to each the resulting page + # $destination_file is the name of the file where this page should be + # written to. + + my ($ident, $title, $rwords, $prefix, $rword_section_name, $rword_section_doc, $rword_section_alpha, $header, $footer, $destination_file) = @_; + + # %words_doc is a hash associating a word to its Doxygen doc (string) + + my %words_doc; + + # %sections_words is a hash associating a section (alphabetical letter) to + # an array of words belonging to that section. + # Ex: $sections_words{"C"} => ("contour", "cut") + # %sections_weight is a hash associating a section to its weight (the sum + # of the weights of each word belonging to that section). + # @sections is the array holding the name of all sections + + my (%sections_words, %sections_weight, @sections); + + # $navbar is the Doxygen string describing the sections' navigation bar + + my $navbar; + + my $intermediate_time = time(); + + # Browse each word + + foreach my $word (@$rwords) { + + my @temp; + push @temp, &$rword_section_name($word), &$rword_section_doc($word); + $words_doc{$word} = $indent . join("\n$indent", @temp) . "\n"; + + # Update section(s) and section(s) weight(s) + + my $section = &$rword_section_alpha($word); + push @{$sections_words{$section}}, $word; + $sections_weight{$section} += length($words_doc{$word}); + + print " => ", $word, "\n" if exists $args{"verbose"}; + } + + print " => ", scalar @$rwords, " words(s) documented in ", time() - $intermediate_time, " s.\n"; + + @sections = sort keys %sections_words; + + # Build the navbar + + my @temp; + foreach my $section (@sections) { + push @temp, "\@ref ${prefix}_section_$section \"$section\""; + } + $navbar = "$indent\@par Navigation: \n$indent\[" . + join(" | ", @temp) . "]\n"; + + # Add the (approximate) weight of the (header + navbar) to each section + + my $total_weight = 0; + my $header_weight = length($indent) + 24 + length($navbar); + + foreach my $section (@sections) { + $sections_weight{$section} += $header_weight; + $total_weight += $sections_weight{$section}; + } + + if (exists $args{"verbose"}) { + foreach my $section (@sections) { + printf("\t- %s : %6d\n", $section, $sections_weight{$section}); + } + } + + print " => total weight is $total_weight in ", scalar @sections, " section(s) (mean is ", int($total_weight / scalar @sections), ")\n"; + + # Compute the alphabetical groups by joining sections depending on weights + + print "Computing alphabetical group(s)/page(s)...\n"; + + # %groups is a hash associating a group id (int) to an array of sections + # namesbelonging to that group. + # Ex: $groups{"0"} => ("A", "B", "C") + # %groups_weight is a hash associating a group id to its weight (the sum + # of the weights of each section belonging to that group). + + my (%groups, %groups_weight); + + my $groupid = 0; + + # Remove a section one by one, and put it in a group until the group if + # full,then create a next group, etc., until the sections are exhausted. + + my @sections_temp = @sections; + while (@sections_temp) { + $groups_weight{$groupid} = $sections_weight{$sections_temp[0]}; + push @{$groups{$groupid}}, shift @sections_temp; + while (@sections_temp && + ($groups_weight{$groupid} +$sections_weight{$sections_temp[0]}) + <= $args{"weight"}) { + $groups_weight{$groupid} += $sections_weight{$sections_temp[0]}; + push @{$groups{$groupid}}, shift @sections_temp; + } + $groupid++; + } + + if (exists $args{"verbose"}) { + foreach my $groupid (sort {$a <=> $b} keys %groups) { + printf("\t- %02d (weight: %7d) : %s\n", $groupid, + $groups_weight{$groupid}, join(", ", @{$groups{$groupid}})); + } + } + + print " => max weight is ", $args{"weight"}, " per group/page, but a section can not be divided\n"; + print " => ", scalar keys %groups, " group(s) for ", scalar @sections, " section(s)\n"; + + # Build documentation page + # Browse each group, each section in this group, each word in this section + + my $page_doc; + + foreach my $groupid (sort {$a <=> $b} keys %groups) { + + my $fromto = $groups{$groupid}[0]; + $fromto .= ".." . $groups{$groupid}[scalar @{$groups{$groupid}} - 1] + if scalar @{$groups{$groupid}} > 1; + + $page_doc .= + "/*! \@page ${prefix}_$groupid $title ($fromto)\n\n$header"; + + foreach my $section (@{$groups{$groupid}}) { + $page_doc .= + "\n$indent\@section ${prefix}_section_$section $section\n\n$navbar\n"; + foreach my $word (@{$sections_words{$section}}) { + $page_doc .= $words_doc{$word}, "\n"; + } + print "\t- $section\n" if exists $args{"verbose"}; + } + $page_doc .= "$footer\n*/\n\n"; + } + + print "Writing documentation to ", $destination_file, "...\n"; + + $intermediate_time = time(); + + sysopen(DEST_FILE, + $destination_file, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file $destination_file\n"; + print DEST_FILE $page_doc; + close(DEST_FILE); + + print " => written in ", time() - $intermediate_time, " s.\n"; +} + diff --git a/Utilities/Doxygen/doc_index.stop b/Utilities/Doxygen/doc_index.stop new file mode 100644 index 0000000..3fa4be2 --- /dev/null +++ b/Utilities/Doxygen/doc_index.stop @@ -0,0 +1,731 @@ +# Usual stop list + +a +about +above +across +actual +actually +after +again +against +all +almost +alone +along +already +also +although +always +among +an +and +another +any +anybody +anyone +anything +anywhere +are +around +as +ask +at +away +b +back +backed +backing +backs +be +because +become +becomes +became +been +before +began +behind +being +beings +best +better +between +both +but +by +c +came +can +cannot +case +cases +certain +certainly +clear +clearly +come +could +d +did +differ +different +differently +do +does +done +down +downed +downing +downs +during +e +each +early +either +end +ended +ending +ends +enough +ever +every +everybody +everyone +everything +everywhere +f +fact +facts +felt +few +for +four +from +full +fully +g +gave +general +generally +get +gets +give +given +gives +go +going +good +goods +got +h +had +has +have +having +he +her +herself +here +him +himself +his +how +however +i +if +important +in +into +is +it +its +itself +j +just +k +keep +keeps +kind +knew +know +known +knows +l +last +later +latest +less +let +lets +like +likely +m +made +make +making +man +many +me +men +might +more +most +mostly +mr +mrs +much +must +my +myself +n +necessary +need +needed +needing +needs +never +next +no +non +not +nobody +noone +nothing +now +number +numbers +o +of +off +on +once +one +only +open +opened +opening +opens +or +other +others +our +out +p +per +perhaps +present +presented +presenting +presents +put +puts +q +quite +r +rather +really +right +s +said +same +saw +say +says +second +seconds +see +sees +seem +seemed +seeming +seems +several +shall +she +should +since +so +some +somebody +someone +something +somewhere +something +somewhere +state +states +still +such +sure +t +take +taken +than +that +the +their +them +then +there +therefore +these +they +thing +things +think +thinks +this +those +though +thought +thoughts +three +through +thus +to +today +together +too +took +toward +two +u +under +until +up +upon +us +use +uses +used +v +very +w +want +wanted +wanting +wants +was +way +ways +we +well +wells +went +were +what +when +where +whether +which +while +who +whole +whose +why +will +with +work +worked +working +work +works +would +y +year +years +yet +you +your +yours + +# Specific VTK doc stop list + +able +accepts +acces +accessed +accessible +according +achieved +added +addinput +additem +adds +alternative +alternatively +appear +appends +applied +apply +appropriate +appropriately +argument +arguments +assigned +associated +assumed +assumes +available +avoid +based +basic +basically +beforehand +begin +beginning +begins +below +break +broken +build +building +buildlinks +built +bunch +call +called +calling +calls +cause +causes +change +changed +changes +changing +checking +choose +class +classes +colormode +common +comp +compared +comparison +complete +completely +compose +composed +compute +computed +computenormals +computes +computing +consider +considered +considering +consist +consisting +consists +constructed +constructor +continues +continuous +control +controlled +controls +copied +copies +copyallocate +copying +correct +correctly +corresponding +create +created +creates +creating +creation +current +currently +data +default +defaults +define +defined +defines +defining +definition +dependent +depending +depends +described +description +descriptions +descriptive +designed +desire +desired +determine +determined +determines +determining +direct +directly +disable +disabled +doesn +doing +easier +easy +effective +eight +elements +else +enable +enabled +enables +enabling +encountered +endmethod +entire +entirely +equal +equally +especially +exact +exactly +example +except +execute +executed +executes +execution +explicitly +expressed +extractinside +failrly +fairly +falls +fifth +final +finally +finished +five +fixed +forming +forward +found +function +functions +generate +generated +generates +generating +generic +getcell +getmtime +getnumberofcontours +getoutput +getting +global +guaranteed +hasn +held +helps +hold +i-j-k +ignored +imax +imin +implement +implemented +implements +include +included +includes +including +index +indicate +indicated +indicates +indicating +initial +initially +initpointinsertion +inpts +input +inputs +inputstring +instead +integer +intended +internal +internally +ivar +ivars +jmax +jmin +kept +kmax +kmin +leave +left +local +main +maintain +maintains +makes +managing +maxid +method +methods +mode +modes +mtime +name +named +names +near +necessarily +nice +none +normally +numberofcomponents +numberofcontours +numberofprocesses +numberofthreads +numberoftuples +numcontours +object +obtain +obtained +occur +occurred +occurs +onto +option +optional +optionally +options +organized +originaltransform +otherwise +outer +outpts +output +outputs +overridden +override +parameter +parameters +particular +passed +passing +perform +performed +performing +performs +placed +please +possibly +prevent +prevented +preventseam +printf +prior +probably +proceeds +proper +properly +provide +provided +provides +ptid +ptids +r-s-t +reached +read +receive +receives +refer +referred +remove +requested +require +required +requires +resizecelllist +respect +result +resulting +results +return +returned +returning +returns +section +selects +send +sending +sends +setmultiplemethod +setnumberofcomponents +setnumberoftuples +setnumberofvalues +setvalue +shouldn +simply +single +singlemethod +specific +specified +specifies +specify +specifying +sprintf +start +starting +startmethod +starts +subid +subsequent +suppled +supplied +supply +switch +switching +takes +taking +tell +themselves +third +throughout +treated +treats +true +trying +type +types +typically +underlying +unless +unsigned +unused +useful +user +users +using +usual +usually +value +values +varies +various +vary +verify +void +wholeextent +wish +word +words +x-y-z +xmax +xmin +ymax +ymin +zmax +zmin +ETX +BTX \ No newline at end of file diff --git a/Utilities/Doxygen/doc_makeall.sh.in b/Utilities/Doxygen/doc_makeall.sh.in new file mode 100644 index 0000000..883aee8 --- /dev/null +++ b/Utilities/Doxygen/doc_makeall.sh.in @@ -0,0 +1,413 @@ +# ------------------------------------------------------------------------- +# Doxygen documentation batch +# modified by S. Barre (Time-stamp: <2005-12-05 12:58:52 barre> +# ------------------------------------------------------------------------- + +# Path to several tools (_PROG to avoid the typical GZIP env var pb) +# Example: +# DOXYGEN_PROG=@DOXYGEN@ (INCLUDE(FindDoxygen.cmake)) +# GZIP_PROG=@GZIP@ (INCLUDE(FindCygwin.cmake)) +# HHC_PROG=@HTML_HELP_COMPILER@ (INCLUDE(FindHTMLHelp.cmake)) +# MV_PROG=@MV@ (INCLUDE(FindCygwin.cmake)) +# PERL_PROG=@PERL@ (INCLUDE(FindPerl.cmake)) +# RM_PROG=@RM@ (INCLUDE(FindCygwin.cmake)) +# TAR_PROG=@TAR@ (INCLUDE(FindCygwin.cmake)) +# WGET_PROG=@WGET@ (INCLUDE(FindWget.cmake)) +# +export DOXYGEN_PROG="@DOXYGEN@" # Doxygen +export GZIP_PROG="@GZIP@" # gzip (Unix-like 'gzip compressor') +export GNUPLOT_PROG="@GNUPLOT@" # gnuplot (data plotting program) +export HHC_PROG="@HTML_HELP_COMPILER@" # HTML Help Compiler +export MV_PROG="@MV@" # mv (Unix-like 'move/rename files') +export PERL_PROG="@PERL@" # Perl +export RM_PROG="@RM@" # rm (Unix-like 'remove files') +export TAR_PROG="@TAR@" # tar (Unix-like 'archiver') +export WGET_PROG="@WGET@" # wget (remote file retrieval) + +# PROJECT_NAME: +# Documentation/project name. Used in some of the resulting file names and +# xrefs to uniquify two or more projects linked together through their +# Doxygen's tag files. Mandatory for each documentation set. +# Note: might be the same as the doxyfile's PROJECT_NAME +# Example: +# PROJECT_NAME=VTK +# +export PROJECT_NAME=VTK + +# PATH_TO_VTK_DOX_SCRIPTS: +# Path to the directory holding the Perl scripts used to produce the VTK doc +# in Doxygen format. You need the VTK source files or a local copy of +# these scripts. +# Example: +# PATH_TO_VTK_DOX_SCRIPTS=@VTK_SOURCE_DIR@/Utilities/Doxygen +# +export PATH_TO_VTK_DOX_SCRIPTS="@VTK_SOURCE_DIR@/Utilities/Doxygen" + +# SOURCE_DIR: +# Source directory. The top directory of the source files. +# Example: +# SOURCE_DIR=@VTK_SOURCE_DIR@ +# +export SOURCE_DIR="@VTK_SOURCE_DIR@" + +# REL_PATH_TO_TOP: +# Relative path from the top directory of the source files to the directory +# (or top directory) holding the files to document. Useful if several parts +# of the same source directory should be documented separately. +# Example: +# REL_PATH_TO_TOP=. +# REL_PATH_TO_TOP=framework/src +# +export REL_PATH_TO_TOP=. + +# INTERMEDIATE_DOX_DIR: +# Directory where the intermediate Doxygen files should be stored (mainly +# these headers files converted from the VTK format to the Doxygen format). +# This directory is erased at the end of this script, unless you comment +# the corresponding line. +# DOXTEMP might be used to simplify the syntax. +# Example: +# DOXTEMP=DOXTEMP=@VTK_BINARY_DIR@/Utilities/Doxygen +# INTERMEDIATE_DOX_DIR=$DOXTEMP/dox +# +export DOXTEMP="@VTK_BINARY_DIR@/Utilities/Doxygen" +export INTERMEDIATE_DOX_DIR="$DOXTEMP/dox" + +# DATA_ROOT: +# Data directory. The root directory of the data files. +# Example: +# DATA_ROOT=@VTK_DATA_ROOT@ +# +export DATA_ROOT="@VTK_DATA_ROOT@" + +# CVSWEB, CVSWEB_SUFFIX, CVSWEB__CHECKOUT, +# CVSWEB_DATA, CVSWEB_DATA_SUFFIX, CVSWEB_DATA_CHECKOUT: +# URL to the CVSWeb of the project + same in checkout mode (i.e. appending a +# file name to this URL will retrieve the contents of the file). In the same way +# CVSWEB_SUFFIX will be appended to the result. +# Same applies to CVSWEB_DATA, which is the URL to the CVSWeb +# of the Data's project. +# Example: +# CVSWEB=http://public.kitware.com/cgi-bin/cvsweb.cgi/VTK +# CVSWEB_SUFFIX=?cvsroot=VTK +# CVSWEB_CHECKOUT=http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/VTK +# CVSWEB_DATA=http://public.kitware.com/cgi-bin/cvsweb.cgi/VTKData +# CVSWEB_DATA_SUFFIX=?cvsroot=VTK +# CVSWEB_DATA_CHECKOUT=http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/VTKData +# +export CVSWEB=http://public.kitware.com/cgi-bin/viewcvs.cgi +export CVSWEB_SUFFIX=?root=VTK +export CVSWEB_CHECKOUT=http://public.kitware.com/cgi-bin/viewcvs.cgi/*checkout* +export CVSWEB_DATA=http://public.kitware.com/cgi-bin/viewcvs.cgi +export CVSWEB_DATA_SUFFIX=?root=VTKData +export CVSWEB_DATA_CHECKOUT=http://public.kitware.com/cgi-bin/viewcvs.cgi/*checkout* + +# DOXYFILE: +# Path to the Doxygen configuration file (i.e. doxyfile). +# Example: +# DOXYFILE=$DOXTEMP/doxyfile +# +export DOXYFILE="$DOXTEMP/doxyfile" + +# OUTPUT_DIRECTORY ALLOW_ERASE_OUTPUT_DIRECTORY: +# Path to the Doxygen output directory (where the resulting doc is stored). +# Note: should be the same as your doxyfile's OUTPUT_DIRECTORY +# If ON, allows the output directory to be erased when some advanced output +# file have been produced (HTML Help, or TAR archive for example). +# Example: +# OUTPUT_DIRECTORY=$DOXTEMP/doc +# ALLOW_ERASE_OUTPUT_DIRECTORY=ON +# +export OUTPUT_DIRECTORY="$DOXTEMP/doc" +export ALLOW_ERASE_OUTPUT_DIRECTORY=ON + +# COMPILE_HTML_HELP RESULTING_HTML_HELP_FILE: +# Compile the CHM (Compressed HTML) HTML Help file, name of the resulting +# file. If set to ON and name is non-empty these options will actually +# trigger the HTML-Help compiler to create the CHM. The resulting +# file (usually index.chm) will be renamed to this name. +# Note: if ON, the whole $OUTPUT_DIRECTORY will be erased at the end of +# this script, since this file is considered to be one of the +# advanced final output, unless ALLOW_ERASE_OUTPUT_DIRECTORY is OFF +# Note: your doxyfile should be configured to enable HTML Help creation +# (using GENERATE_HTML = YES, GENERATE_HTMLHELP = YES) +# Example: +# COMPILE_HTML_HELP=ON +# COMPILE_HTML_HELP=@DOCUMENTATION_HTML_HELP@ +# RESULTING_HTML_HELP_FILE=$DOXTEMP/vtk4.chm +# +export COMPILE_HTML_HELP=@DOCUMENTATION_HTML_HELP@ +export RESULTING_HTML_HELP_FILE="$DOXTEMP/vtk4.chm" + +# CREATE_HTML_TARZ_ARCHIVE RESULTING_HTML_TARZ_ARCHIVE_FILE: +# Create a compressed (gzip) tar archive of the html directory (located +# under the OUTPUT_DIRECTORY), and name of the resulting archive file. +# Note: your doxyfile should be configured to enable HTML creation +# (using GENERATE_HTML = YES) +# Example: +# CREATE_HTML_TARZ_ARCHIVE=ON +# CREATE_HTML_TARZ_ARCHIVE=@DOCUMENTATION_HTML_TARZ@ +# RESULTING_HTML_TARZ_ARCHIVE_FILE=$DOXTEMP/vtk4-html.tar.gz +# +export CREATE_HTML_TARZ_ARCHIVE=@DOCUMENTATION_HTML_TARZ@ +export RESULTING_HTML_TARZ_ARCHIVE_FILE="$DOXTEMP/vtk4-html.tar.gz" + +# DOWNLOAD_VTK_TAGFILE VTK_TAGFILE VTK_TAGFILE_REMOTE_DIR VTK_TAGFILE_DEST_DIR: +# Download the VTK tag file, name, remote location and destination dir of this +# tag file. If set to ON, the tag file is retrieved from its remote location +# using wget and stored in the destination dir. It will be automatically +# deleted at the end of this script. +# Note: your doxyfile must be tailored to make use-of or create this tag file. +# (using TAGFILES = vtk4-nightly.tag=http://www.vtk.org/doc/nightly/html +# or GENERATE_TAGFILE = "@VTK_BINARY_DIR@/Utilities/Doxygen/vtk4.tag") +# Example: +# DOWNLOAD_VTK_TAGFILE=OFF +# VTK_TAGFILE=vtk4-nightly.tag +# VTK_TAGFILE_REMOTE_DIR=http://www.vtk.org/doc/nightly/html +# VTK_TAGFILE_DEST_DIR=$DOXTEMP +# +export DOWNLOAD_VTK_TAGFILE=OFF +export VTK_TAGFILE=vtk4-nightly.tag +export VTK_TAGFILE_REMOTE_DIR=http://www.vtk.org/doc/nightly +export VTK_TAGFILE_DEST_DIR="$DOXTEMP" + +# ---------------------------------------------------------------------------- +# Convert the VTK headers to the Doxygen format. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_header2doxygen.pl" \ + --to "$INTERMEDIATE_DOX_DIR" \ + --relativeto "$SOURCE_DIR/$REL_PATH_TO_TOP" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Common" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Filtering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GenericFiltering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GenericFiltering/Testing/Cxx" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Graphics" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GUISupport/MFC" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GUISupport/Qt" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Hybrid" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Imaging" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/IO" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Parallel" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Widgets" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Rendering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/VolumeRendering" +fi + +# ---------------------------------------------------------------------------- +# Build the Events invocation list. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_codematch.pl" \ + --codematch "\w(?:->|\.)InvokeEvent\s*\(\s*(vtkCommand::\w+)[\s,]" \ + --label "Events" \ + --project "$PROJECT_NAME" \ + --sectionmatch "^vtkCommand::(\w)" \ + --store "doc_""$PROJECT_NAME""_events.dox" \ + --title "Event to Classes" \ + --sectionmatch2 "^vtk(\w)" \ + --store2 "doc_""$PROJECT_NAME""_events2.dox" \ + --title2 "Class to Events" \ + --to "$INTERMEDIATE_DOX_DIR" \ + --unique "v" \ + --relativeto "$SOURCE_DIR/$REL_PATH_TO_TOP" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Common" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Filtering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GenericFiltering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GenericFiltering/Testing/Cxx" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Graphics" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GUISupport/MFC" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GUISupport/Qt" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Hybrid" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Imaging" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/IO" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Parallel" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Widgets" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Rendering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/VolumeRendering" +fi + +# ---------------------------------------------------------------------------- +# Build the full-text index. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_index.pl" \ + --project "$PROJECT_NAME" \ + --stop "$PATH_TO_VTK_DOX_SCRIPTS/doc_index.stop" \ + --store "doc_""$PROJECT_NAME""_index.dox" \ + --to "$INTERMEDIATE_DOX_DIR" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Common" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Filtering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GenericFiltering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GenericFiltering/Testing/Cxx" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Graphics" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GUISupport/MFC" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/GUISupport/Qt" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Hybrid" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Imaging" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/IO" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Parallel" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Widgets" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/Rendering" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP/VolumeRendering" +fi + +# ---------------------------------------------------------------------------- +# Extract the VTK version and create the main page. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_version.pl" \ + --version_file "$SOURCE_DIR/$REL_PATH_TO_TOP/CMakeLists.txt" \ + --revision_file "$SOURCE_DIR/$REL_PATH_TO_TOP/Common/vtkVersion.h" \ + --logo "$PATH_TO_VTK_DOX_SCRIPTS/vtk-logo.gif" \ + --store "doc_""$PROJECT_NAME""_version.dox" \ + --to "$INTERMEDIATE_DOX_DIR" +fi + +# ---------------------------------------------------------------------------- +# Generate the 'Class to Examples' page cross-linking each class to these +# examples that use that class. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_class2example.pl" \ + --baselinedir "$DATA_ROOT/Baseline" \ + --baselineicon "pic.gif" \ + --baselinelink "$CVSWEB_DATA_CHECKOUT/Baseline" \ + --baselinelinksuffix "$CVSWEB_DATA_SUFFIX" \ + --datamatch "\W(VTK_DATA_ROOT|VTKData|(vtk)?GetDataRoot|ExpandDataFileName)\W" \ + --dataicon "paper-clip.gif" \ + --dirmatch "^Examples\$" \ + --label "Examples" \ + --link "$CVSWEB_CHECKOUT" \ + --linksuffix "$CVSWEB_SUFFIX" \ + --project "$PROJECT_NAME" \ + --store "doc_""$PROJECT_NAME""_class2examples.dox" \ + --title "Class To Examples" \ + --to "$INTERMEDIATE_DOX_DIR" \ + --unique "e" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP" +fi + +# ---------------------------------------------------------------------------- +# Generate the 'Class to Tests' page cross-linking each class to these +# tests that use that class. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_class2example.pl" \ + --baselinedir "$DATA_ROOT/Baseline" \ + --baselineicon "pic.gif" \ + --baselinelink "$CVSWEB_DATA_CHECKOUT/Baseline" \ + --baselinelinksuffix "$CVSWEB_DATA_SUFFIX" \ + --datamatch "\W(VTK_DATA_ROOT|VTKData|(vtk)?GetDataRoot|ExpandDataFileName)\W" \ + --dataicon "paper-clip.gif" \ + --dirmatch "^Testing$" \ + --label "Tests" \ + --link "$CVSWEB_CHECKOUT" \ + --linksuffix "$CVSWEB_SUFFIX" \ + --project "$PROJECT_NAME" \ + --store "doc_""$PROJECT_NAME""_class2tests.dox" \ + --title "Class To Tests" \ + --to "$INTERMEDIATE_DOX_DIR" \ + --unique "t" \ + "$SOURCE_DIR/$REL_PATH_TO_TOP" +fi + +# ---------------------------------------------------------------------------- +# Retrieve the VTK 4 tag file. + +if test "x$DOWNLOAD_VTK_TAGFILE" == "xON" ; then + if test "x$VTK_TAGFILE" != "x" ; then + if test "x$WGET_PROG" != "xNOTFOUND" ; then + "$WGET_PROG" -nd -nH \ + "$VTK_TAGFILE_REMOTE_DIR/$VTK_TAGFILE" \ + -O "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE" + fi + fi +fi + +# ---------------------------------------------------------------------------- +# Create the Doxygen doc. + +if test "x$DOXYGEN_PROG" != "xNOTFOUND" ; then + + if test "x$RM_PROG" != "xNOTFOUND" ; then + "$RM_PROG" -fr "$OUTPUT_DIRECTORY" + fi + + "$DOXYGEN_PROG" "$DOXYFILE" +fi + +# ---------------------------------------------------------------------------- +# Clean the HTML pages to remove the path to the intermediate Doxygen dir. + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_rmpath.pl" \ + --to "$INTERMEDIATE_DOX_DIR" \ + --html "$OUTPUT_DIRECTORY/html" +fi + +# ---------------------------------------------------------------------------- +# clean the HTML pages to remove layout pbs + +if test "x$PERL_PROG" != "xNOTFOUND" ; then + "$PERL_PROG" "$PATH_TO_VTK_DOX_SCRIPTS/doc_cleanhtml.pl" \ + --html "$OUTPUT_DIRECTORY/html" +fi + +# ---------------------------------------------------------------------------- +# Create the CHM HTML HELP doc. + +if test "x$COMPILE_HTML_HELP" == "xON" ; then + if test "x$RESULTING_HTML_HELP_FILE" != "x" ; then + cd "$OUTPUT_DIRECTORY/html" + if test "x$HHC_PROG" != "xNOTFOUND" ; then + "$HHC_PROG" index.hhp + if test "x$MV_PROG" != "xNOTFOUND" ; then + "$MV_PROG" -f index.chm "$RESULTING_HTML_HELP_FILE" + fi + fi + fi +fi + +# ---------------------------------------------------------------------------- +# Create the compressed tar archive. + +if test "x$CREATE_HTML_TARZ_ARCHIVE" == "xON" ; then + if test "x$RESULTING_HTML_TARZ_ARCHIVE_FILE" != "x" ; then + cd "$OUTPUT_DIRECTORY" + if test "x$TAR_PROG" != "xNOTFOUND" ; then + if test "x$RM_PROG" != "xNOTFOUND" ; then + "$RM_PROG" -f html.tar + fi + "$TAR_PROG" -cf html.tar html + if test "x$GZIP_PROG" != "xNOTFOUND" ; then + if test "x$RM_PROG" != "xNOTFOUND" ; then + "$RM_PROG" -f html.tar.gz + fi + "$GZIP_PROG" html.tar + "$MV_PROG" -f html.tar.gz "$RESULTING_HTML_TARZ_ARCHIVE_FILE" + fi + fi + fi +fi + +# ---------------------------------------------------------------------------- +# Clean-up. + +if test "x$RM_PROG" != "xNOTFOUND" ; then + "$RM_PROG" -fr "$INTERMEDIATE_DOX_DIR" + + if test "x$DOWNLOAD_VTK_TAGFILE" == "xON" ; then + if test "x$VTK_TAGFILE" != "x" ; then + "$RM_PROG" -f "$VTK_TAGFILE_DEST_DIR/$VTK_TAGFILE" + fi + fi + + if test "x$COMPILE_HTML_HELP" == "xON" ; then + if test "x$RESULTING_HTML_HELP_FILE" != "x" ; then + if test "x$ALLOW_ERASE_OUTPUT_DIRECTORY" == "xON" ; then + "$RM_PROG" -fr "$OUTPUT_DIRECTORY" + fi + fi + fi +fi diff --git a/Utilities/Doxygen/doc_readme.txt b/Utilities/Doxygen/doc_readme.txt new file mode 100644 index 0000000..54b3c42 --- /dev/null +++ b/Utilities/Doxygen/doc_readme.txt @@ -0,0 +1,330 @@ +Documenting VTK with doxygen +---------------------------- + +Sebastien BARRE (Time-stamp: <2001-10-24 22:38:42 barre>) + +This file describes how to generate a Doxygen-compliant documentation +featuring cross-references between classes and examples, a full-text index +and an accurate VTK version. + +Note that this file describes how to run the scripts manually, which +can be tedious (to say the least). A batch file doc_makeall.sh is now +used to automate this process. It is part of the CMake/Build process +and is configured both though CMake and through its own parameter. It +should be pretty straightforward to understand and adapt. + +Warning +------- + +These scripts are now part of the VTK source distribution. + +Think twice before letting Doxygen eat your CPU cycles: Kitware is +now using these scripts to build an up-to-date Doxygen-compliant +documentation every night as part of the "nightly build" +process. Thus, you might browse or download a pre-built documentation here: + + http://public.kitware.com/doc/ + +Nevertheless, Doxygen might still be useful to generate additional +PDF, Postscript or plain LaTeX output. + +This package is made of he following Perl scripts: + +- doc_header2doxygen.pl: convert the VTK headers to the Doxygen format +- doc_version.pl: extract the VTK version and add it to the documentation set +- doc_class2example.pl: build cross-references between classes and examples +- doc_index.pl: build the full-text index + +Use the --help option to display the parameters that are allowed for each +script. + +Thanks to Vetle Roeim and Jan Stifter who started the project :) + + +A. Preamble + -------- + +I assume that your VTK distribution is in a 'VTK' directory and that +you do NOT want to modify it in any ways. You would rather create a +modified copy of the VTK files in a different location (here, the +'../VTK-doxygen' directory, assuming that you are in the 'VTK' +directory now). Hence, you might use this main 'VTK' directory for CVS +and development purposes (updating it from time to time) and rerun +the process described below to update your documentation (a +straightforward process once you get used to it). + +The Perl scripts described in that document are stored in the +'VTK/Utilities/Doxygen' directory. You will also find a couple of +additional files like a VTK logo and a batch script automating the +whole conversion process. Thus, the directories that are of some +interest in that README are: + + VTK/ : the VTK repository + VTK/Utilities/Doxygen : the Doxygen scripts and configuration files + VTK-Doxygen/ : the intermediate VTK repository + +The doxygen configuration script, i.e. the script controlling how this +VTK documentation is created, is named 'doxyfile'; it is also stored +in the 'VTK/Utilities/Doxygen' directory. It is read by doxygen and +lists option/value pairs like: + + PARAMETER = VALUE + +Comment lines are allowed and start with '#'. Commenting a directive +is a simple way to hide it to doxygen: + +# PARAMETER = VALUE + +Do not forget to set the OUTPUT_DIRECTORY directive specifying the +location where the whole documentation is to be stored. Example: + + OUTPUT_DIRECTORY = ../../../doc + +The crucial INPUT directive controls which directory or files are +processed by doxygen to produce the documentation. Each directory/file +is separated by a space. Whenever you will be requested to add a +filename to INPUT, just add it to the end of the list. Example: + + INPUT = ../../../VTK-doxygen/Common ../../../VTK-doxygen/Filtering ../../../VTK-doxygen/Graphics ../../../VTK-doxygen/Hybrid ../../../VTK-doxygen/Imaging ../../../VTK-doxygen/IO ../../../VTK-doxygen/Parallel ../../../VTK-doxygen/Patented ../../../VTK-doxygen/Rendering ../../../VTK-doxygen/doc_version.dox ../../../VTK-doxygen/doc_class2examples.dox ../../../VTK-doxygen/doc_class2tests.dox ../../../VTK-doxygen/doc_index.dox + +WARNING: disable the HAVE_DOT directive if you have not installed graphviz +(http://www.research.att.com/~north/graphviz/download.html). + + +B. Download doxygen, make sure it runs + ----------------------------------- + + http://www.doxygen.org + + +C0. Go to the VTK/Utilities/Doxygen directory + ----------------------------------------- + + You are supposed to run all scripts as well as Doxygen from this + directory. + +For example: + + D:\src\kitware\vtk\VTK> cd Utilities\Doxygen + D:\src\kitware\vtk\VTK\Utilities\Doxygen> + + +C1. Convert the VTK headers to Doxygen format + ----------------------------------------- + + Use the conversion script: doc_header2doxygen.pl + +For example: + + D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_header2doxygen.pl --to ../../../VTK-doxygen + doc_header2doxygen.pl 0.8, by Sebastien Barre et al. + Collecting... + Converting... + => 729 files converted in 6 s. + Finished in 7 s. + +Meaning that: + + The optional '--to ../../../VTK-doxygen' parameter specifies that the + script stores the modified C++ *headers* (*.h files) in the + '../../../VTK-doxygen' directory (here: 'D:\src\kitware\vtk\VTK-doxygen', + as I issued the command from 'D:\src\kitware\vtk\VTK\Utilities\Doxygen'). + The files located in 'VTK' remain untouched. The script browses + the directories located two levels up (i.e. ../../) automatically. + + Use --help to display the default value associated to --to. + + Note that you might restrict the conversion to a set of particuliar + directories or files if you want to document a specific VTK part only: + just add these parts as parameters. Example: + + D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_header2doxygen.pl --to ../../../VTK-doxygen ../../Hybrid + +Update the Doxygen configuration file ('doxyfile'): + + Depending on the location from where you are going to run Doxygen + (here: 'D:\src\kitware\vtk\VTK\Utilities\Doxygen') update or add + the paths to the VTK components/directories that you want to + document. Since the headers have been created in + '../../../VTK-doxygen', the following values will be fine: + + INPUT = ../../../VTK-doxygen/Common ../../../VTK-doxygen/Filtering ../../../VTK-doxygen/Graphics ../../../VTK-doxygen/Hybrid ../../../VTK-doxygen/Imaging ../../../VTK-doxygen/IO ../../../VTK-doxygen/Parallel ../../../VTK-doxygen/Patented ../../../VTK-doxygen/Rendering + + +C2. Extract VTK version + ------------------- + + Use the extraction script: doc_version.pl + +For example: + + D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_version.pl --logo "vtk-logo.gif" --to ../../../VTK-doxygen + doc_version.pl 0.22, by Sebastien Barre + => 4.0.0 + => $Revision: 1.4 $ $Date: 2001/10/25 02:48:20 $ + Building version documentation to ../../../VTK-doxygen/doc_version.dox + Finished in 0 s. + +Meaning that: + + The optional '--to ../../../VTK-doxygen' parameter specifies that + the script stores the related documentation part in the + '../../../VTK-doxygen' directory (more precisely in the + '../../../VTK-doxygen/doc_version.dox' file). The VTK logo is + incorporated by using the --logo option. The script searchs for + the VTK version in the '../../Common/vtkVersion.h'. Use --help to + check how to override these default values. + +Update the Doxygen configuration file ('doxyfile'): + + Comment the PROJECT_NUMBER directive: you do not need it anymore + as you have just created a more accurate description based on the + current vtkVersion.h. + + # PROJECT_NUMBER = + + +C3. Generate the 'class to examples' pages + -------------------------------------- + + Use the referencing script: doc_class2example.pl + +For example: + + D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_class2example.pl --link http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/VTK/Utilities/Doxygen --to ../../../VTK-doxygen + doc_class2example.pl 0.7, by Sebastien Barre + Collecting files... + => 17 file(s) collected in 2 s. + Parsing files... + => 17 file(s) parsed in 0 s. + Eliminating some classes... + => 1 class(es) eliminated (vtkCommand) in 0 s. + Locating headers to update... + => 33 found, 8 orphan class(es) removed (vtkIOJava, vtkRenderingJava, vtkCommonJava, vtkImagingJava, vtkGraphicsJava, vtkInteract, vtkTkWidget, vtkFilteringJava) in 0 s. + Building classes doc and alphabetical section(s) weight(s)... + => 33 classes(s) documented in 0 s. + => total weight is 38604 in 13 section(s) (mean is 2969) + Computing alphabetical group(s)/page(s)... + => max weight is 90000 per group/page, but a section can not be divided + => 1 group(s) for 13 section(s) + Building pages header... + Writing documentation to ../../../VTK-doxygen/doc_class2examples.dox... + - 33 class(es) in 17 file(s) from directories matching @c ^Examples$ on Mon Oct 1 10:53:04 2001 + - 4 parser(s) : [Java, Python, C++, Tcl] + - at most 20 file(s) per parser (0% over) + => in 0 s. + Updating headers... + => 32 header(s) updated in 0 s. +Finished in 2 s. + +Meaning that : + + The optional '--to ../../../VTK-doxygen' parameter specifies that + the script searches (and parses) the Python, Tcl, Java or C++ + *examples* (17 here) in the directories two level up (i.e. ../../ + and below) but updates the C++ class *headers* (32 here) stored in + the '../../../VTK-doxygen' directory (which is good because they + have just been created in step C1). These headers are updated to + include cross-links between the class and the examples using + it. The script stores the documentation file listing all examples + in the '../../../VTK-doxygen/doc_class2example.dox' file. Once + again, the files located in 'VTK' remain untouched. The --link + option is a path or a URL that is prepended to each example's name + to provide a physical link to that example (here, the CVSweb). + + Use --help to check how to override these default values. More + specifically you can override the --dirmatch option (a regexp) so + that the parsers will only look into specific directories. The + default value "^Examples\$" constrains the script to any + directory which name is 'Example'; --dirmatch "^Testing$" will + actually make the script parse all examples found in the 'Testing' + directories (the --label, --title and --unique option should be changed + appropriately, check 'doc_makeall.bat' for example). + +Update the Doxygen configuration file ('doxyfile'): + + Add the relative path to 'doc_class2example.dox' (here : + '../../../VTK-doxygen/doc_class2example.dox') to the INPUT + directive, so that Doxygen might process it (see also section D). + + +C4. Build full-text index + --------------------- + + Use the indexing script: doc_index.pl + +For example: + + D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_index.pl --to ../../../VTK-doxygen + doc_index.pl 0.2, by Sebastien Barre + Reading stop-words from doc_index.stop... + => 724 stop-word(s) read. + Collecting files... + Indexing... + => 8174 word(s) grabbed in 729 file(s) in 2 s. + Removing... + => 3126 word(s) removed. + Grouping... + => 2075 word(s) grouped. + Normalizing... + => normalized to lowercase. + Building indexes doc and alphabetical section(s) weight(s)... + => 2973 words(s) documented in 2 s. + => total weight is 400800 in 47 section(s) (mean is 8527) + Computing alphabetical group(s)/page(s)... + => max weight is 90000 per group/page, but a section can not be divided + => 6 group(s) for 47 section(s) + Building pages header... + Writing documentation to ../../../VTK-doxygen/doc_index.dox... + - 729 file(s) indexed by 2973 word(s) on Mon Oct 1 11:13:44 2001 + - max limit is 10 xref(s) per word + Finished in 5 s. + +Meaning that: + + The optional '--to ../../../VTK-doxygen' parameter specifies that + the script stores the full-text index in the + '../../../VTK-doxygen' directory (more precisely in the + '../../../VTK-doxygen/doc_index.dox' file). + + The optional --stop parameter can be used to specify that the + script should read its stop-words from a different file (default + is 'doc_index.stop'). This file is a list of trivial words (one + per line) that won't be indexed. + +Update the Doxygen configuration file ('doxyfile'): + + Add the relative path to 'doc_index.dox' (here : + '../../../VTK-doxygen/doc_index.dox') to the INPUT directive, so that + Doxygen might process it (see also section D) + + +D. Run doxygen + ----------- + + Check that your Doxygen configuration file is OK + ('doxyfile'). The important directives are: + + PROJECT_NAME = VTK + # PROJECT_NUMBER = + OUTPUT_DIRECTORY = ../../../doc + INPUT = ../../../VTK-doxygen/Common ../../../VTK-doxygen/Filtering ../../../VTK-doxygen/Graphics ../../../VTK-doxygen/Hybrid ../../../VTK-doxygen/Imaging ../../../VTK-doxygen/IO ../../../VTK-doxygen/Parallel ../../../VTK-doxygen/Patented ../../../VTK-doxygen/Rendering ../../../VTK-doxygen/doc_version.dox ../../../VTK-doxygen/doc_class2examples.dox ../../../VTK-doxygen/doc_class2tests.dox ../../../VTK-doxygen/doc_index.dox + + Then run doxygen. Be *patient* :) + +For example: + + D:\src\kitware\vtk\VTK\Utilities\Doxygen> doxygen + + The documentation will be located in the '../../../doc' + directory. If that directory does not exist, doxygen will create it, + *unless* the its parent directory does not exist either. + + You are done. + Browse the HTML documentation starting from: + doc/html/index.html + + +Just my 2 cents. + +Sebastien BARRE diff --git a/Utilities/Doxygen/doc_rmpath.pl b/Utilities/Doxygen/doc_rmpath.pl new file mode 100644 index 0000000..4c0294c --- /dev/null +++ b/Utilities/Doxygen/doc_rmpath.pl @@ -0,0 +1,111 @@ +#!/usr/bin/env perl +# Time-stamp: <2001-10-05 11:49:40 barre> +# +# Remove path to intermediate Doxygen dir from html doc +# +# barre : Sebastien Barre +# +# 0.1 (barre) +# - first release + +use Carp; +use Cwd 'abs_path'; +use Getopt::Long; +use Fcntl; +use File::Find; +use strict; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.1, $0, "Sebastien Barre"); +$PROGNAME =~ s/^.*[\\\/]//; +print "$PROGNAME $VERSION, by $AUTHOR\n"; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want : "verbose" => 1 for default verbose mode) + +my %default = + ( + html => "../../../doc/html", + to => "../../../VTK-doxygen" + ); + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "verbose|v", "html=s", "to=s"); + +if (exists $args{"help"}) { + print <<"EOT"; +Usage : $PROGNAME [--help] [--verbose|-v] [--html path] [--to path] + --help : this message + --verbose|-v : verbose (display filenames while processing) + --html path : 'path' the Doxygen generated HTML doc (default : $default{html}) + --to path : 'path' to intermediate Doxygen dir (default : $default{to}) + +Example: + $PROGNAME +EOT + exit; +} + +$args{"to"} = $default{"to"} if ! exists $args{"to"}; +$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"}; +$args{"html"} = $default{"html"} if ! exists $args{"html"}; +$args{"html"} =~ s/[\\\/]*$// if exists $args{"html"}; + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Collect all HTML files + +print "Collecting HTML files in ", $args{"html"}, "\n"; + +my @files; +find sub { + push @files, $File::Find::name + if -f $_ && $_ =~ /\.html$/; +}, $args{"html"}; + +print " => ", scalar @files, " file(s) collected in ", time() - $start_time, " s.\n"; + +# ------------------------------------------------------------------------- +# Remove path + +my ($nb_files, $htmlpath) = (0, abs_path($args{"to"}) . '/'); +undef $/; # slurp mode + +print "Removing $htmlpath and writing...\n"; +my $intermediate_time = time(); + +foreach my $filename (@files) { + + print " $filename\n" if exists $args{"verbose"}; + + # Open the file, read it entirely + + sysopen(HTMLFILE, + $filename, + O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $filename\n"; + my $html = ; + close(HTMLFILE); + + # Remove all paths + + if ($html =~ s/$htmlpath//gms) { + ++$nb_files; + sysopen(HTMLFILE, + $filename, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file $filename\n"; + print HTMLFILE $html; + close(HTMLFILE); + } +} + +print " => $nb_files file(s) processed and written in ", time() - $intermediate_time, " s.\n"; +print "Finished in ", time() - $start_time, " s.\n"; + diff --git a/Utilities/Doxygen/doc_version.pl b/Utilities/Doxygen/doc_version.pl new file mode 100644 index 0000000..0de14b6 --- /dev/null +++ b/Utilities/Doxygen/doc_version.pl @@ -0,0 +1,194 @@ +#!/usr/bin/env perl +# Time-stamp: <2002-11-22 16:23:16 barre> +# +# Extract VTK version and add it to documentation +# +# barre : Sebastien Barre +# +# 0.3 (barre) : +# - update to search for the version infos in a different file +# (i.e. top CMakeLists.txt file instead of vtkVersion.h) +# - --header becomes --revision_file and --version_file +# +# 0.25 (barre) : +# - update useful links for Dart +# +# 0.24 (barre) : +# - update useful links for new public.kitware.com structure +# +# 0.23 (barre) : +# - update useful links +# +# 0.22 (barre) : +# - add more (useful) links to various VTK documentation ressources +# +# 0.21 (barre) : +# - no more --logo defaults +# +# 0.2 (barre) : +# - update to match the new VTK 4.0 tree +# - change default --header so that it can be launched from Utilities/Doxygen +# - change default --to so that it can be launched from Utilities/Doxygen +# - add --logo file : use 'file' as logo +# +# 0.16 (barre) : +# - change default --to to '../vtk-doxygen' to comply with Kitware +# - update VTK home page URL. +# +# 0.15 (barre) : +# - fix RCS/CVS tags problem (regexp replacement when this file is in a CVS) +# +# 0.14 (barre) : +# - as doxygen now handles RCS/CVS tags of the form $word:text$, use them +# +# 0.13 (barre) : +# - change doxygen command style from \ to @ to match javadoc, autodoc, etc. +# +# 0.12 (barre) : +# - change default --to to '../vtk-dox' +# +# 0.11 (barre) +# - fix O_TEXT flag problem +# - switch to Unix CR/LF format +# +# 0.1 (barre) +# - initial release + +use Carp; +use Fcntl; +use File::Basename; +use Getopt::Long; +use strict; + +my ($VERSION, $PROGNAME, $AUTHOR) = (0.3, $0, "Sebastien Barre"); +$PROGNAME =~ s/^.*[\\\/]//; +print "$PROGNAME $VERSION, by $AUTHOR\n"; + +# ------------------------------------------------------------------------- +# Defaults (add options as you want: "verbose" => 1 for default verbose mode) + +my %default = + ( + version_file => "../../CMakeLists.txt", + revison_file => "../../Common/vtkVersion.h", + store => "doc_VTK_version.dox", + to => "../../../VTK-doxygen" + ); + +# ------------------------------------------------------------------------- +# Parse options + +my %args; +Getopt::Long::Configure("bundling"); +GetOptions (\%args, "help", "revision_file=s", "version_file=s", "logo=s", "store=s", "to=s"); + +if (exists $args{"help"}) { + print <<"EOT"; +by $AUTHOR +Usage : $PROGNAME [--help] [--revision_file file] [--store file] [--to path] + --help : this message + --revision_file file : use 'file' to find revision (default: $default{revision_file}) + --version_file file : use 'file' to find version info (default: $default{version_file}) + --logo file : use 'file' as logo (default: $default{logo}) + --store file : use 'file' to store version (default: $default{store}) + --to path : use 'path' as destination directory (default: $default{to}) + +Example: + $PROGNAME +EOT + exit; +} + +$args{"revision_file"} = $default{"revision_file"} if ! exists $args{"revision_file"}; +$args{"version_file"} = $default{"version_file"} if ! exists $args{"version_file"}; +$args{"logo"} = $default{"logo"} if ! exists $args{"logo"}; +$args{"store"} = $default{"store"} if ! exists $args{"store"}; +$args{"to"} = $default{"to"} if ! exists $args{"to"}; +$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"}; + +my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i); +my $open_file_as_text = $os_is_win ? O_TEXT : 0; +my $start_time = time(); + +# ------------------------------------------------------------------------- +# Try to get VTK version and revision + +my ($major_version, $minor_version, $build_version, $revision, $date) = (undef, undef, undef); + +sysopen(FILE, $args{"version_file"}, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $args{version_file}\n"; + +while () { + if ($_ =~ /VTK_MAJOR_VERSION\s+(\d+)/) { + $major_version = $1; + print " major => $major_version\n"; + } elsif ($_ =~ /VTK_MINOR_VERSION\s+(\d+)/) { + $minor_version = $1; + print " minor => $minor_version\n"; + } elsif ($_ =~ /VTK_BUILD_VERSION\s+(\d+)/) { + $build_version = $1; + print " build => $build_version\n"; + } +} + +close(FILE); + +croak "$PROGNAME: unable to find version in " . $args{"version_file"} . "\n" + if (!defined $major_version || !defined $minor_version || !defined $build_version); + +sysopen(FILE, $args{"revision_file"}, O_RDONLY|$open_file_as_text) + or croak "$PROGNAME: unable to open $args{revision_file}\n"; + +while () { + if ($_ =~ /define\s+VTK_SOURCE_VERSION.*(.Revision:.*.?\$).*(.Date:.*?\$).*\"/) { + $revision = $1; + $date = $2; + print " revision => $revision $date\n"; + last; + } +} + +close(FILE); + +croak "$PROGNAME: unable to find revision/date in " . $args{"revision_file"} . "\n" + if (!defined $revision || !defined $date); + +# ------------------------------------------------------------------------- +# Build documentation + +my $destination_file = $args{"to"} . "/" . $args{"store"}; +print "Building version documentation to ", $destination_file, "\n"; + +sysopen(DEST_FILE, + $destination_file, + O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text) + or croak "$PROGNAME: unable to open destination file " . $destination_file . "\n"; + +print DEST_FILE + "/*! \@mainpage VTK $major_version.$minor_version.$build_version Documentation\n\n"; + +print DEST_FILE + " \@image html " . basename($args{"logo"}) . "\n" + if exists $args{"logo"} && -f $args{"logo"}; + +print DEST_FILE + " $revision\n", + " $date\n", + " \@par Useful links:\n", + " \@li VTK Home: http://www.vtk.org\n", + " \@li VTK Users Mailing-list: http://public.kitware.com/mailman/listinfo/vtkusers\n", + " \@li VTK Developer Mailing List: http://www.vtk.org/mailman/listinfo/vtk-developers\n", + " \@li VTK FAQ: http://www.vtk.org/Wiki/VTK_FAQ\n", + " \@li VTK Wiki: http://www.vtk.org/Wiki/\n", + " \@li VTK Search: http://www.kitware.com/search.html\n", + " \@li VTK Dashboard: http://www.vtk.org/Testing/Dashboard/MostRecentResults-Nightly/Dashboard.html\n", + " \@li VTK-Doxygen scripts (Sebastien Barre): http://www.barre.nom.fr/vtk/doc/README\n", + " \@li Kitware Home: http://www.kitware.com\n", + " \@li Sebastien's VTK Links: http://www.barre.nom.fr/vtk/links.html\n", + " \@li Other Links: http://www.vtk.org/links.php\n", + " ", + "*/\n\n"; + +close(DEST_FILE); + +print "Finished in ", time() - $start_time, " s.\n"; diff --git a/Utilities/Doxygen/doxyfile.in b/Utilities/Doxygen/doxyfile.in new file mode 100644 index 0000000..c9e0dc3 --- /dev/null +++ b/Utilities/Doxygen/doxyfile.in @@ -0,0 +1,199 @@ +# ------------------------------------------------------------------------- +# doxyfile for VTK +# modified by S. Barre (Time-stamp: <2005-12-05 12:59:07 barre> +# ------------------------------------------------------------------------- + +PROJECT_NAME = VTK + +FULL_PATH_NAMES = YES +WARN_IF_UNDOCUMENTED = NO + +GENERATE_TREEVIEW = NO +GENERATE_TODOLIST = YES +GENERATE_BUGLIST = YES +GENERATE_HTML = YES +GENERATE_HTMLHELP = YES +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +GENERATE_TAGFILE = "@VTK_BINARY_DIR@/Utilities/Doxygen/vtk4.tag" + +PDF_HYPERLINKS = YES + +HAVE_DOT = YES +#HAVE_DOT = NO +DOT_PATH = "@DOT_PATH@" +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CLASS_DIAGRAMS = YES +GENERATE_LEGEND = YES +GRAPHICAL_HIERARCHY = NO # would be too large for vtkObject + +ALLEXTERNALS = NO + +IMAGE_PATH = "@VTK_SOURCE_DIR@/Utilities/Doxygen" "@VTK_BINARY_DIR@/Utilities/Doxygen/contrib" + +OUTPUT_DIRECTORY = "@VTK_BINARY_DIR@/Utilities/Doxygen/doc" + +INPUT = \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Filtering" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/GenericFiltering" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/GenericFiltering/Testing/Cxx" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Graphics" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/GUISupport" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Hybrid" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Imaging" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/IO" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Parallel" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Widgets" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Rendering" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/VolumeRendering" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/doc_VTK_version.dox" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/doc_VTK_class2examples.dox" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/doc_VTK_class2tests.dox" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/doc_VTK_events2.dox" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/doc_VTK_events.dox" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/doc_VTK_index.dox" + +EXCLUDE_PATTERNS = +EXCLUDE = \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkSetGet.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Filtering/vtkMarchingSquaresCases.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Filtering/vtkMarchingCubesCases.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkWindows.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkWinCE.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkTcl.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkTk.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkTclUtil.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkPython.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkPythonUtil.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkJavaAwt.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkJavaUtil.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkPythonUtil.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/vtkTclUtil.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Parallel/vtkMPI.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Hybrid/vtk3DS.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Hybrid/vtkVRML.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/IO/vtkPLY.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Rendering/vtkOpenGL.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Rendering/vtkFreeTypeFontCache.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Rendering/fonts/vtkEmbeddedFonts.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Rendering/Testing/vtkRegressionTestImage.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/Testing/vtkTestDriver.h" \ + "@VTK_BINARY_DIR@/Utilities/Doxygen/dox/Common/Testing/vtkTestingColors.h" + +# TAGFILES = "@VTK_BINARY_DIR@/Utilities/Doxygen/vtk4-nightly.tag"=http://www.vtk.org/doc/nightly/html + +EXTRACT_ALL = YES +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = YES +ALWAYS_DETAILED_SEC = NO +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +CASE_SENSE_NAMES = YES +VERBATIM_HEADERS = NO +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +SORT_MEMBER_DOCS = NO +DISTRIBUTE_GROUP_DOC = YES +TAB_SIZE = 3 +DETAILS_AT_TOP = YES +SHORT_NAMES = @DOXYGEN_SHORT_NAMES@ +# PAPER_TYPE = letter + +FILE_PATTERNS = *.h +RECURSIVE = NO + +HTML_ALIGN_MEMBERS = YES + +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 3 +IGNORE_PREFIX = vtk + +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +EXPAND_ONLY_PREDEF = YES +PREDEFINED = "vtkSetMacro(name,type)= \ + virtual void Set##name (type);" \ + "vtkGetMacro(name,type)= \ + virtual type Get##name ();" \ + "vtkSetStringMacro(name)= \ + virtual void Set##name (const char*);" \ + "vtkGetStringMacro(name)= \ + virtual char* Get##name ();" \ + "vtkSetClampMacro(name,type,min,max)= \ + virtual void Set##name (type);" \ + "vtkSetObjectMacro(name,type)= \ + virtual void Set##name (type*);" \ + "vtkGetObjectMacro(name,type)= \ + virtual type *Get##name ();" \ + "vtkBooleanMacro(name,type)= \ + virtual void name##On (); \ + virtual void name##Off ();" \ + "vtkSetVector2Macro(name,type)= \ + virtual void Set##name (type, type); \ + void Set##name (type [2]);" \ + "vtkGetVector2Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &); \ + virtual void Get##name (type [2]);" \ + "vtkSetVector3Macro(name,type)= \ + virtual void Set##name (type, type, type); \ + virtual void Set##name (type [3]);" \ + "vtkGetVector3Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &, type &); \ + virtual void Get##name (type [3]);" \ + "vtkSetVector4Macro(name,type)= \ + virtual void Set##name (type, type, type, type); \ + virtual void Set##name (type [4]);" \ + "vtkGetVector4Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &, type &, type &); \ + virtual void Get##name (type [4]);" \ + "vtkSetVector6Macro(name,type)= \ + virtual void Set##name (type, type, type, type, \ + type, type); \ + virtual void Set##name (type [6]);" \ + "vtkGetVector6Macro(name,type)= \ + virtual type *Get##name (); \ + virtual void Get##name (type &, type &, type &, \ + type &, type &, type &); \ + virtual void Get##name (type [6]);" \ + "vtkSetVectorMacro(name,type,count)= \ + virtual void Set##name(type data[]);" \ + "vtkGetVectorMacro(name,type,count)= \ + virtual type *Get##name (); \ + virtual void Get##name(type data[##count]);" \ + "vtkWorldCoordinateMacro(name)= \ + virtual vtkCoordinate *Get##name##Coordinate (); \ + virtual void Set##name(float x[3]); \ + virtual void Set##name(float x, float y, float z); \ + virtual float *Get##name();" \ + "vtkViewportCoordinateMacro(name)= \ + virtual vtkCoordinate *Get##name##Coordinate (); \ + virtual void Set##name(float x[2]); \ + virtual void Set##name(float x, float y); \ + virtual float *Get##name();" \ + "vtkTypeMacro(thisClass,superclass)= \ + typedef superclass Superclass; \ + virtual const char *GetClassName(); \ + static int IsTypeOf(const char *type); \ + virtual int IsA(const char *type); \ + static thisClass* SafeDownCast(vtkObject *o);" \ + "vtkTypeRevisionMacro(thisClass,superclass)= \ + typedef superclass Superclass; \ + virtual const char *GetClassName(); \ + static int IsTypeOf(const char *type); \ + virtual int IsA(const char *type); \ + static thisClass* SafeDownCast(vtkObject *o);" \ + "VTK_LEGACY(x)= x" diff --git a/Utilities/Doxygen/paper-clip.gif b/Utilities/Doxygen/paper-clip.gif new file mode 100644 index 0000000..bf53c12 Binary files /dev/null and b/Utilities/Doxygen/paper-clip.gif differ diff --git a/Utilities/Doxygen/pic.gif b/Utilities/Doxygen/pic.gif new file mode 100644 index 0000000..78fa870 Binary files /dev/null and b/Utilities/Doxygen/pic.gif differ diff --git a/Utilities/Doxygen/vtk-logo.gif b/Utilities/Doxygen/vtk-logo.gif new file mode 100644 index 0000000..50c41c1 Binary files /dev/null and b/Utilities/Doxygen/vtk-logo.gif differ diff --git a/Utilities/LastConfigureStep/CMakeLists.txt b/Utilities/LastConfigureStep/CMakeLists.txt new file mode 100644 index 0000000..51cf297 --- /dev/null +++ b/Utilities/LastConfigureStep/CMakeLists.txt @@ -0,0 +1,14 @@ +# The commands in this directory are intended to be executed as +# the end of the whole configuration process, as a "last step". +# This directory is typically the last SUBDIRS in the main CMakeLists.txt. +# It enable the above commands to use variables that might have been configured +# in previous SUBDIRS. This is especially important when it comes to +# the CONFIGURE_FILE command, since in IMMEDIATE mode that command will +# use the current values of CMake variables instead of waiting until the +# end of CMakeLists processing, i.e. instead of waiting until some variables +# are configured in SUBDIRS. + +#----------------------------------------------------------------------------- +# Create the VTKConfig.cmake file containing the VTK configuration. +# Since it might generate configuration file depending +INCLUDE(${VTK_SOURCE_DIR}/vtkGenerateVTKConfig.cmake) diff --git a/Utilities/OutputWindowProcess/CMakeLists.txt b/Utilities/OutputWindowProcess/CMakeLists.txt new file mode 100644 index 0000000..7100b65 --- /dev/null +++ b/Utilities/OutputWindowProcess/CMakeLists.txt @@ -0,0 +1,48 @@ +# This project is designed to be used as a custom command or be built +# manually. See README.txt for build instructions. +IF(NOT VTK_OWP_BUILD_INNER) + PROJECT(VTK_OWP) + IF(NOT VTK_OWP_OUTPUT) + SET(VTK_OWP_OUTPUT + ${VTK_OWP_BINARY_DIR}/vtkWin32OutputWindowProcessEncoded.c) + ENDIF(NOT VTK_OWP_OUTPUT) + IF(NOT VTK_OWP_NAME) + SET(VTK_OWP_NAME Win32OutputWindowProcess) + ENDIF(NOT VTK_OWP_NAME) + SET(CMAKE_TRY_COMPILE_CONFIGURATION Release) + TRY_COMPILE(COMPILED + ${VTK_OWP_BINARY_DIR}/Inner + ${VTK_OWP_SOURCE_DIR} + VTK_OWP_INNER vtk_owp_encode + CMAKE_FLAGS -DCMAKE_BUILD_TYPE:STRING=${CMAKE_TRY_COMPILE_CONFIGURATION} + -DVTK_OWP_BUILD_INNER:BOOL=1 + -DVTK_OWP_OUTPUT:STRING=${VTK_OWP_OUTPUT} + -DVTK_OWP_NAME:STRING=${VTK_OWP_NAME} + OUTPUT_VARIABLE OUTPUT) + IF(COMPILED) + MESSAGE(STATUS "Creating \"${VTK_OWP_OUTPUT}\" succeeded.") + ELSE(COMPILED) + FILE(WRITE ${VTK_OWP_OUTPUT} "failed_to_generate\n") + MESSAGE(FATAL_ERROR + "Creating \"${VTK_OWP_OUTPUT}\" failed with output [${OUTPUT}].") + ENDIF(COMPILED) +ELSE(NOT VTK_OWP_BUILD_INNER) + PROJECT(VTK_OWP_INNER) + + ADD_EXECUTABLE(vtkWin32OutputWindowProcess WIN32 vtkWin32OutputWindowProcess.c) + GET_TARGET_PROPERTY(VTK_OWP_EXE vtkWin32OutputWindowProcess LOCATION) + IF(NOT BORLAND) + TARGET_LINK_LIBRARIES(vtkWin32OutputWindowProcess gdi32) + ENDIF(NOT BORLAND) + + ADD_EXECUTABLE(vtkEncodeExecutable vtkEncodeExecutable.c) + GET_TARGET_PROPERTY(VTK_ENCODE_EXE vtkEncodeExecutable LOCATION) + ADD_CUSTOM_COMMAND( + OUTPUT ${VTK_OWP_OUTPUT} + COMMAND ${VTK_ENCODE_EXE} + ARGS ${VTK_OWP_EXE} ${VTK_OWP_OUTPUT} ${VTK_OWP_NAME} + DEPENDS ${VTK_OWP_EXE} ${VTK_ENCODE_EXE} + ) + + ADD_CUSTOM_TARGET(vtk_owp_encode DEPENDS ${VTK_OWP_OUTPUT}) +ENDIF(NOT VTK_OWP_BUILD_INNER) diff --git a/Utilities/OutputWindowProcess/README.txt b/Utilities/OutputWindowProcess/README.txt new file mode 100644 index 0000000..02443cf --- /dev/null +++ b/Utilities/OutputWindowProcess/README.txt @@ -0,0 +1,38 @@ +In order to build this project just configure it with CMake as a +separate project. After running the "Configure" step, there will be a +vtkWin32OutputWindowProcessEncoded.c at the top level of the build +tree. There is no need to actually load and build the project with +Visual Studio. + +This project is intended to generate +vtkWin32OutputWindowProcessEncoded.c for inclusion in the build of +vtkCommon. The executable is self-deleting and is used by +vtkWin32ProcessOutputWindow. It is an output window that runs as a +separate process and deletes its own executable on exit. This is +useful so that if the main process crashes, the output window is still +usable, which is good since it probably explains the crash. + +Currently the self-deletion mechanism works on all versions of windows +but only when compiled by a Visual Studio compiler in release mode. + +If vtkWin32OutputWindowProcess.c can be implemented in a way that +works for all windows compilers, then this project can be integrated +into the main VTK build process by adding a custom command to generate +vtkWin32OutputWindowProcessEncoded.c on the fly like this: + +IF(WIN32) + IF (NOT VTK_USE_X) + SET(VTK_OWP_ENCODED_C + ${VTK_BINARY_DIR}/Common/vtkWin32OutputWindowProcessEncoded.c) + ADD_CUSTOM_COMMAND( + OUTPUT ${VTK_OWP_ENCODED_C} + COMMAND ${CMAKE_COMMAND} + ARGS -G\"${CMAKE_GENERATOR}\" + -H${VTK_SOURCE_DIR}/Utilities/OutputWindowProcess + -B${VTK_BINARY_DIR}/Utilities/OutputWindowProcess + -DVTK_OWP_OUTPUT=${VTK_OWP_ENCODED_C} + DEPENDS ${VTK_SOURCE_DIR}/Utilities/OutputWindowProcess/vtkWin32OutputWindowProcess.c + ) + SET_SOURCE_FILES_PROPERTIES(${VTK_OWP_ENCODED_C} PROPERTIES WRAP_EXCLUDE 1) + ENDIF (NOT VTK_USE_X) +ENDIF(WIN32) diff --git a/Utilities/OutputWindowProcess/vtkEncodeExecutable.c b/Utilities/OutputWindowProcess/vtkEncodeExecutable.c new file mode 100644 index 0000000..532a5fe --- /dev/null +++ b/Utilities/OutputWindowProcess/vtkEncodeExecutable.c @@ -0,0 +1,130 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEncodeExecutable.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include + +int main(int argc, char* argv[]) +{ + FILE* ifp; + FILE* ofp; + int i; + int n; + int count = 0; + unsigned char buffer[1024]; + + /* Check arguments. */ + if(argc != 4) + { + fprintf(stderr, "Usage: %s \n", + argv[0]); + return 1; + } + + /* Open the input file. */ + ifp = fopen(argv[1], "rb"); + if(!ifp) + { + fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]); + return 2; + } + ofp = fopen(argv[2], "w"); + if(!ofp) + { + fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]); + return 2; + } + + /* Prepend header comment. */ + fprintf(ofp, "/*=========================================================================\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " Program: Visualization Toolkit\n"); + fprintf(ofp, " Module: $RCSfile: vtkEncodeExecutable.c,v $\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n"); + fprintf(ofp, " All rights reserved.\n"); + fprintf(ofp, " See Copyright.txt or http://www.kitware.com/Copyright.htm for details.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " This software is distributed WITHOUT ANY WARRANTY; without even\n"); + fprintf(ofp, " the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n"); + fprintf(ofp, " PURPOSE. See the above copyright notice for more information.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "=========================================================================*/\n"); + fprintf(ofp, "/*\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "DO NOT EDIT\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "This file is generated by running CMake on\n"); + fprintf(ofp, "VTK/Utilities/OutputWindowProcess as a separate project using a Visual\n"); + fprintf(ofp, "Studio generator. The program built in that project works only when\n"); + fprintf(ofp, "compiled by the Visual Studio compiler because it depends on being\n"); + fprintf(ofp, "able to manipulate the stack frame of another process. See\n"); + fprintf(ofp, "VTK/Utilities/OutputWindowProcess/README.txt for more information.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "This file contains an encoded executable that can be written to disk using\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " int vtkEncodedArrayWin32OutputWindowProcessWrite(const char* fname);\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "It returns 1 for success and 0 for failure. The executable is\n"); + fprintf(ofp, "self-deleting and therefore can be run only once. It is used by\n"); + fprintf(ofp, "vtkWin32ProcessOutputWindow.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "*/\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "#include \n\n"); + + /* Split file up in 1024-byte chunks. */ + while((n = (int)fread(buffer, 1, 1024, ifp)) > 0) + { + fprintf(ofp, "static unsigned char vtkEncodedArray%s_%d[%d] = {\n", + argv[3], count++, n); + for(i=0; i < n-1; ++i) + { + fprintf(ofp, "0x%02X", buffer[i]); + if(i%10 == 9) + { + fprintf(ofp, ",\n"); + } + else + { + fprintf(ofp, ", "); + } + } + fprintf(ofp, "0x%02X};\n\n", buffer[n-1]); + } + fclose(ifp); + + /* Provide a function to write the data to a file. */ + fprintf(ofp, "extern int vtkEncodedArray%sWrite(const char* fname)\n", + argv[3]); + fprintf(ofp, "{\n"); + fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n"); + fprintf(ofp, " if(!ofp) { return 0; }\n"); + for(i=0; i < count; ++i) + { + fprintf(ofp, " if(fwrite(vtkEncodedArray%s_%d, 1,\n" + " sizeof(vtkEncodedArray%s_%d), ofp) !=\n" + " sizeof(vtkEncodedArray%s_%d))\n", + argv[3], i, argv[3], i, argv[3], i); + fprintf(ofp, " {\n"); + fprintf(ofp, " fclose(ofp);\n"); + fprintf(ofp, " _unlink(fname);\n"); + fprintf(ofp, " return 0;\n"); + fprintf(ofp, " }\n"); + } + fprintf(ofp, " fclose(ofp);\n"); + fprintf(ofp, " return 1;\n"); + fprintf(ofp, "}\n"); + fclose(ofp); + return 0; +} diff --git a/Utilities/OutputWindowProcess/vtkWin32OutputWindowProcess.c b/Utilities/OutputWindowProcess/vtkWin32OutputWindowProcess.c new file mode 100644 index 0000000..b06d4d8 --- /dev/null +++ b/Utilities/OutputWindowProcess/vtkWin32OutputWindowProcess.c @@ -0,0 +1,255 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWin32OutputWindowProcess.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifdef _MSC_VER +/* Handle MSVC compiler warning messages, etc. */ +# pragma warning ( disable : 4115 ) +#endif + +/* Function to delete executable calling it. */ +static int SelfDelete(); + +#include + +#undef _T +#ifdef UNICODE +# define _T(x) L x +#else +# define _T(x) x +#endif + +static HWND MainWindow = 0; +static HWND EditWindow = 0; +static LPCTSTR MainWindowClass = _T("vtkOutputWindowProcess"); +static LPCTSTR EditWindowClass = _T("EDIT"); +static LONG MainWindowStyle = (WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW); +static LONG EditWindowStyle = (ES_MULTILINE | ES_READONLY | WS_CHILD | + ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_VISIBLE | + WS_VSCROLL | WS_HSCROLL | WS_MAXIMIZE); + +static LRESULT APIENTRY MainWindowProc(HWND hWnd, UINT m, WPARAM w, LPARAM l) +{ + switch (m) + { + case WM_SIZE: + MoveWindow(EditWindow, 0, 0, LOWORD(l), HIWORD(l), TRUE); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + } + return DefWindowProc(hWnd, m, w, l); +} + +static void RegisterWindowClass() +{ + WNDCLASS wndClass; + if(!GetClassInfo(GetModuleHandle(0), MainWindowClass, &wndClass)) + { + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = MainWindowProc; + wndClass.cbClsExtra = 0; + wndClass.hInstance = GetModuleHandle(0); + wndClass.hIcon = LoadIcon(0, IDI_APPLICATION); + wndClass.hCursor = LoadCursor(0, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndClass.lpszMenuName = 0; + wndClass.lpszClassName = MainWindowClass; + wndClass.cbWndExtra = 0; + RegisterClass(&wndClass); + } +} + +static DWORD WINAPI ReadThreadProc(LPVOID p) +{ + char buffer[1024]; + DWORD nRead = 0; + while(ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, 1024, &nRead, 0)) + { + buffer[nRead] = 0; + SendMessage(EditWindow, EM_SETSEL, (WPARAM)-1, (LPARAM)-1); + SendMessage(EditWindow, EM_REPLACESEL, (WPARAM)0, (LPARAM)buffer); + } + return (DWORD)p; +} + +void MainEventLoop() +{ + BOOL b; + MSG msg; + while((b = GetMessage(&msg, 0, 0, 0)) != 0 && b != -1) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, + PSTR szCmdLine, int iCmdShow) +{ + (void)hInst; (void)hPrev; (void)szCmdLine; (void)iCmdShow; + + /* Setup a child process to delete this executable when it exits. */ + SelfDelete(); + + /* Create a simple GUI. */ + RegisterWindowClass(); + MainWindow = CreateWindow(MainWindowClass, MainWindowClass, MainWindowStyle, + 0,0,512,512, 0, 0, GetModuleHandle(0), 0); + EditWindow = CreateWindow(EditWindowClass, "", EditWindowStyle, + 0,0,512,512, MainWindow, 0, GetModuleHandle(0), 0); + ShowWindow(MainWindow, SW_SHOW); + UpdateWindow(MainWindow); + + /* Create a thread to read from standard input and write to the window. */ + {DWORD threadId; CreateThread(0, 1024, ReadThreadProc, 0, 0, &threadId);} + + /* Run the event loop until the window is closed. */ + MainEventLoop(); + + return 0; +} + +/*--------------------------------------------------------------------------*/ +/* Code to delete executable calling it. Based on code from James + Brown at http://www.catch22.org.uk/tuts/selfdel.asp. */ + +#pragma pack(push, 1) + +#define SELF_DELETE_CODESIZE 0x200 + +/* Data to inject into remote process. */ +typedef struct SelfDeleteRemoteCode_s SelfDeleteRemoteCode; +typedef struct SelfDeleteRemoteCode_s +{ + SelfDeleteRemoteCode *Arg0; + BYTE opCodes[SELF_DELETE_CODESIZE]; + HANDLE hParent; + + DWORD (__stdcall *fnWaitForSingleObject)(HANDLE hHandle, DWORD dwMilliseconds); + BOOL (__stdcall *fnCloseHandle)(HANDLE hObject); + BOOL (__stdcall *fnDeleteFile)(LPCTSTR lpFileName); + void (__stdcall *fnSleep)(DWORD dwMilliseconds); + void (__stdcall *fnExitProcess)(UINT uExitCode); + DWORD (__stdcall *fnGetLastError)(void); + + TCHAR szFileName[MAX_PATH]; +} SelfDeleteRemoteCode; + +#pragma pack(pop) + +#ifdef _DEBUG +# error "vtkWin32OutputWindowProcess must be compiled Release" +#endif + +/* Function to execute in remote process. It may only call windows + kernel functions through pointers in the SelfDeleteRemoteCode + structure. */ +static void SelfDeleteRemoteThread(SelfDeleteRemoteCode* remote) +{ + /* Block until parent process terminates. */ + remote->fnWaitForSingleObject(remote->hParent, INFINITE); + remote->fnCloseHandle(remote->hParent); + + /* Delete the executable file. */ + while(!remote->fnDeleteFile(remote->szFileName)) + { + remote->fnSleep(1000); + } + + /* Exit so that we do not execute garbage code. */ + remote->fnExitProcess(0); +} + +/* Function to setup remote process that waits for this process to + exit and then deletes its executable. */ +static int SelfDelete() +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + /* Create a process using the explorer executable but suspend it + immediately. */ + if(CreateProcess(0, _T("explorer.exe"), 0, 0, 0, + (CREATE_SUSPENDED | IDLE_PRIORITY_CLASS), + 0, 0, &si, &pi)) + { + /* Structure to store code and data to copy to remote process. */ + SelfDeleteRemoteCode code; + + DWORD oldProtect; + CONTEXT context; + DWORD entryPoint; + + /* Setup pointers to kernel functions for the remote code to call. */ + code.fnWaitForSingleObject = WaitForSingleObject; + code.fnCloseHandle = CloseHandle; + code.fnDeleteFile = DeleteFile; + code.fnSleep = Sleep; + code.fnExitProcess = ExitProcess; + code.fnGetLastError = GetLastError; + + /* Give the remote process a copy of our own process handle. */ + DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), + pi.hProcess, &code.hParent, 0, FALSE, 0); + + /* Store the file name of this process's executable. */ + GetModuleFileName(0, code.szFileName, MAX_PATH); + + /* Store the binary code to execute remotely. */ + memcpy(code.opCodes, SelfDeleteRemoteThread, SELF_DELETE_CODESIZE); + + /* Allocate some space on process's stack and place our + SelfDeleteRemoteCode structure there. Then set the instruction + pointer to this location and let the process resume. */ + context.ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL); + GetThreadContext(pi.hThread, &context); + + /* Allocate space on stack that is aligned to cache-line boundary. */ + entryPoint = (context.Esp - sizeof(SelfDeleteRemoteCode)) & ~0x1F; + + /* Place a pointer to the structure at the bottom-of-stack. This + pointer is located in such a way that it becomes the + SelfDeleteRemoteThread's first argument. */ + code.Arg0 = (SelfDeleteRemoteCode*)entryPoint; + + /* Set dummy return address for remote thread. It will never return. */ + context.Esp = entryPoint - 4; + + /* Set remote thread to execute the opCodes we copy to the process. */ + context.Eip = entryPoint + (((char*)&code.opCodes) - ((char*)&code)); + + /* Copy the code and data to the remote process entry point. */ + VirtualProtectEx(pi.hProcess, (PVOID)entryPoint, sizeof(code), + PAGE_EXECUTE_READWRITE, &oldProtect); + WriteProcessMemory(pi.hProcess, (PVOID)entryPoint, &code, sizeof(code), 0); + + /* Make sure the new code will be loaded. */ + FlushInstructionCache(pi.hProcess, (PVOID)entryPoint, sizeof(code)); + + /* Set the remote thread to execute at our entry point. */ + SetThreadContext(pi.hThread, &context); + + /* Let the remote process continue. It will block until this + process exits. */ + ResumeThread(pi.hThread); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return 1; + } + + return 0; +} diff --git a/Utilities/ParseOGLExt/CMakeLists.txt b/Utilities/ParseOGLExt/CMakeLists.txt new file mode 100644 index 0000000..52d2ee4 --- /dev/null +++ b/Utilities/ParseOGLExt/CMakeLists.txt @@ -0,0 +1,43 @@ +# Builds a simple program that will take a text file and generate a C +# header file containing a string holding the contents of that file. This +# provides a simple means of embedding that file into a library or +# executable. +# +# Program: Visualization Toolkit +# Module: $RCSfile: CMakeLists.txt,v $ +# +# Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +# All rights reserved. +# See Copyright.txt or http://www.kitware.com/Copyright.htm for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even +# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the above copyright notice for more information. +# +# Copyright 2003 Sandia Corporation. +# Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive +# license for use of this work by or on behalf of the +# U.S. Government. Redistribution and use in source and binary forms, with +# or without modification, are permitted provided that this Notice and any +# statement of authorship are reproduced on all copies. + +ADD_EXECUTABLE(vtkParseOGLExt Tokenizer.cxx ParseOGLExt.cxx) + +IF (${CMAKE_MAJOR_VERSION} LESS 2) + SET(PARSEOGLEXT_EXE + ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/vtkParseOGLExt + ) +ELSE (${CMAKE_MAJOR_VERSION} LESS 2) + GET_TARGET_PROPERTY(PARSEOGLEXT_EXE vtkParseOGLExt LOCATION) +ENDIF (${CMAKE_MAJOR_VERSION} LESS 2) +SET(VTK_PARSEOGLEXT_EXE ${PARSEOGLEXT_EXE} + CACHE INTERNAL "OpenGL extensions parser." FORCE) + +SET(VTK_GLEXT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/headers/glext.h" CACHE FILEPATH + "Location of the OpenGL extensions header file (glext.h).") +SET(VTK_GLXEXT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/headers/glxext.h" CACHE FILEPATH + "Location of the GLX extensions header file (glxext.h).") +SET(VTK_WGLEXT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/headers/wglext.h" CACHE FILEPATH + "Location of the WGL extensions header file (wglext.h).") +MARK_AS_ADVANCED(VTK_GLEXT_FILE VTK_GLXEXT_FILE VTK_WGLEXT_FILE) + diff --git a/Utilities/ParseOGLExt/ParseOGLExt.cxx b/Utilities/ParseOGLExt/ParseOGLExt.cxx new file mode 100644 index 0000000..c50cc48 --- /dev/null +++ b/Utilities/ParseOGLExt/ParseOGLExt.cxx @@ -0,0 +1,833 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ParseOGLExt.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* A program that will read in OpenGL extension header files and output VTK + * code that handles extensions in a more platform-independent manner. + */ + + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkSystemIncludes.h" + +#include "Tokenizer.h" + +#include +#include +#include +#include + +#include +#include + +// #define this if you want debug output as the parser does its work + +// #define DEBUG_PARSE + +static vtkstd::set< vtkstd::pair< vtkstd::string, vtkstd::string > > ConstantsAlreadyWritten; + +static vtkstd::string ToUpper(vtkstd::string s) +{ + vtkstd::string u; + + for (vtkstd::string::size_type i = 0; i < s.length(); i++) + { + u.append(1, (char)toupper(s[i])); + } + + return u; +} + +class Extension { +public: + vtkstd::string name; + enum {GL, WGL, GLX} type; + + Extension() {} + Extension(char *line); + static bool isExtension(char *line); + + static inline void WriteSupportWrapperBegin(ostream &out, int itype) { + switch (itype) + { + case WGL: + out << "#ifdef WIN32" << endl; + break; + case GLX: + out << "#ifdef VTK_USE_X" << endl; + break; + case GL: + break; + } + } + inline void WriteSupportWrapperBegin(ostream &out) const { + WriteSupportWrapperBegin(out, this->type); + } + static inline void WriteSupportWrapperEnd(ostream &out, int itype) { + if ((itype == WGL) || (itype == GLX)) + { + out << "#endif" << endl; + } + } + inline void WriteSupportWrapperEnd(ostream &out) const { + WriteSupportWrapperEnd(out, this->type); + } + + static inline const char *TypeToCapString(int t) { + switch (t) + { + case GL: return "GL"; + case GLX: return "GLX"; + case WGL: return "WGL"; + } + return NULL; + } + static inline const char *TypeToString(int t) { + switch (t) + { + case GL: return "gl"; + case GLX: return "glX"; + case WGL: return "wgl"; + } + return NULL; + } + + bool operator<(const Extension &obj) const { return this->name < obj.name; } +}; + +Extension::Extension(char *line) +{ + Tokenizer t(line); + + t.GetNextToken(); + + this->name = t.GetNextToken(); + + Tokenizer nameTokens(this->name, "_"); + vtkstd::string header = nameTokens.GetNextToken(); + if (header == "WGL") + { + this->type = WGL; + } + else if (header == "GLX") + { + this->type = GLX; + } + else + { + this->type = GL; + } +} + +bool Extension::isExtension(char *line) +{ + Tokenizer t(line); + + if (t.GetNextToken() != "#ifndef") return false; + + Tokenizer nameTokens(t.GetNextToken(), "_"); + vtkstd::string header = nameTokens.GetNextToken(); + if ((header == "GL") || (header == "WGL") || (header == "GLX")) + { + return true; + } + + return false; +} + +static Extension currentExtension; + +class Constant { +public: + vtkstd::string name; + vtkstd::string value; + + Constant(char *line); + static bool isConstant(char *line); + + bool operator<(const Constant &obj) const { return this->name < obj.name; } +}; + +static vtkstd::map EncounteredConstants; + +Constant::Constant(char *line) +{ + // Assumes isConstant is true. + Tokenizer t(line); + + t.GetNextToken(); + + this->name = t.GetNextToken(); + vtkstd::string fullname = this->name; + if (currentExtension.type == Extension::GL) + { + // Skip the "GL_" + this->name = this->name.substr(3); + } + else + { + // Skip the "GLX_" or "WGL_" + this->name = this->name.substr(4); + } + // Make sure name does not start with a numeric. + if ((this->name[0] >= '0') && (this->name[0] <= '9')) + { + this->name = '_' + this->name; + } + + this->value = t.GetNextToken(); + // Sometimes, one constant points to another. Handle this properly. + vtkstd::map::iterator found + = EncounteredConstants.find(value); + if (found != EncounteredConstants.end()) + { + this->value = found->second; + } + + // Now record this as found. + EncounteredConstants[fullname] = this->value; +} + +bool Constant::isConstant(char *line) +{ + Tokenizer t(line); + + if (t.GetNextToken() != "#define") + { + return false; + } + + vtkstd::string n = t.GetNextToken(); + if ( ( (currentExtension.type == Extension::GL) + && (strncmp(n.c_str(), "GL_", 3) == 0) ) + || ( (currentExtension.type == Extension::WGL) + && (strncmp(n.c_str(), "WGL_", 4) == 0) ) + || ( (currentExtension.type == Extension::GLX) + && (strncmp(n.c_str(), "GLX_", 4) == 0) ) ) + { + return true; + } + return false; +} + +class Typedef { +public: + vtkstd::string definition; + + Typedef(char *line); + static bool isTypedef(char *line); + + bool operator<(const Typedef &obj) const { return this->definition < obj.definition; } +}; + +Typedef::Typedef(char *line) +{ + // Assumes isTypedef is true. + this->definition = line; +} + +bool Typedef::isTypedef(char *line) +{ + Tokenizer t(line); + + // Hack for some SGI stuff that declares a multiline struct. + if ( (t.GetNextToken() == "typedef") + && ((t.GetNextToken() != "struct") || (t.GetNextToken() != "{")) ) + { + return true; + } + + // Hack for how some WIN32 things are declared. + if (strncmp(line, "DECLARE_HANDLE(", 15) == 0) + { + return true; + } + + return false; +} + +class Function { +public: + vtkstd::string returnType; + vtkstd::string entry; + vtkstd::string name; + vtkstd::string arguments; + int extensionType; + + Function(char *line); + static bool isFunction(char *line); + const char *GetProcType(); + + bool operator<(const Function &obj) const { return this->name < obj.name; } +}; + +Function::Function(char *line) : extensionType(currentExtension.type) +{ + // Assumes isFunction returns true. + + Tokenizer t(line, " \n\t("); + + t.GetNextToken(); + vtkstd::string token = t.GetNextToken(); + this->returnType = ""; + while ((token == "const") || (token == "unsigned")) + { + this->returnType += token + " "; + token = t.GetNextToken(); + } + this->returnType += token; + + token = t.GetNextToken(); + if (token == "*") + { + this->returnType += " *"; + token = t.GetNextToken(); + } + else if (token[0] == '*') + { + this->returnType += " *"; + token = token.substr(1); + } + +#ifdef DEBUG_PARSE + cerr << "Function return type: " << this->returnType << endl; +#endif + + if (currentExtension.type == Extension::GL) + { + this->entry = "APIENTRY"; + token = t.GetNextToken(); + } + else if (currentExtension.type == Extension::WGL) + { + this->entry = "WINAPI"; + token = t.GetNextToken(); + } + else + { + this->entry = ""; + } + +#ifdef DEBUG_PARSE + cerr << "Function entry: " << this->entry << endl; +#endif + + if (currentExtension.type == Extension::GL) + { + // Strip off "gl" + this->name = token.substr(2); + } + else + { + // Strip off "glX" or "wgl" + this->name = token.substr(3); + } + +#ifdef DEBUG_PARSE + cerr << "Function name: " << this->name << endl; +#endif + + this->arguments = t.GetRemainingString(); + +#ifdef DEBUG_PARSE + cerr << "Function arguments: " << this->arguments << endl; +#endif +} + +bool Function::isFunction(char *line) +{ + Tokenizer t(line); + + vtkstd::string modifier = t.GetNextToken(); + vtkstd::string sreturnType = t.GetNextToken(); + if (sreturnType == "const") + { + // We don't really need the return type, just to skip over const. + sreturnType += " "; + sreturnType += t.GetNextToken(); + } + + vtkstd::string sentry = t.GetNextToken(); + if (sentry == "*") + { + sreturnType += " *"; + sentry = t.GetNextToken(); + } + else if (sentry.size() && sentry[0] == '*') + { + sreturnType += " *"; + sentry = sentry.substr(1); + } + + return ( ( (currentExtension.type == Extension::GL) + && (modifier == "GLAPI") && (sentry == "APIENTRY") ) + || ( (currentExtension.type == Extension::GL) + && (modifier == "extern") && (sentry == "APIENTRY") ) + || ( (currentExtension.type == Extension::WGL) + && (modifier == "extern") && (sentry == "WINAPI") ) + || ( (currentExtension.type == Extension::GLX) + && (modifier == "extern") ) ); +} + +const char *Function::GetProcType() +{ + static vtkstd::string proctype; + + proctype = "PFN"; + proctype += Extension::TypeToCapString(this->extensionType); + proctype += ToUpper(this->name); + proctype += "PROC"; + + return proctype.c_str(); +} + +static vtkstd::list extensions; +static vtkstd::set extensionset; +static vtkstd::map > consts; +static vtkstd::map > types; +static vtkstd::map > functs; + +static void ParseLine(char *line) +{ + static bool inExtension = false; + static int ifLevel = 0; + + Tokenizer tokens(line); + vtkstd::string firstToken = tokens.GetNextToken(); + + if (Extension::isExtension(line)) + { + currentExtension = Extension(line); +#ifdef DEBUG_PARSE + cerr << "Recognized extension: " << line << endl; +#endif + + // There are some exceptions to the extensions we support. This is + // because someone has placed some funky nonstandard stuff in the + // header files. + if ( (currentExtension.name == "GLX_SGIX_video_source") + || (currentExtension.name == "GLX_SGIX_dmbuffer") + || (currentExtension.name == "GLX_SGIX_hyperpipe") ) + { + inExtension = false; + return; + } + + // Only add extension to list if it is not already in it. + if (extensionset.find(currentExtension) == extensionset.end()) + { + if (currentExtension.name == "GLX_ARB_get_proc_address") + { + // Special case where GLX_VERSION_1_4 depends on a typedef in + // GLX_ARB_get_proc_address, so we have to move the latter up. + extensions.push_front(currentExtension); + } + else + { + extensions.push_back(currentExtension); + } + extensionset.insert(currentExtension); + } + inExtension = true; + ifLevel = 0; + } + else if (inExtension) + { + if (strncmp(firstToken.c_str(), "#if", 3) == 0) + { + ifLevel++; + } + else if (firstToken == "#endif") + { + if (ifLevel == 0) + { + inExtension = false; + } + else + { + ifLevel--; + } + } + else if ( Constant::isConstant(line) + && (strncmp(currentExtension.name.c_str(), (line+8), + currentExtension.name.length()) != 0) ) + { +#ifdef DEBUG_PARSE + cerr << "Recognized constant: " << line << endl; +#endif + consts[currentExtension].push_back(line); + } + else if (Function::isFunction(line)) + { +#ifdef DEBUG_PARSE + cerr << "Recognized function: " << line << endl; +#endif + functs[currentExtension].push_back(line); + } + else if (Typedef::isTypedef(line)) + { +#ifdef DEBUG_PARSE + cerr << "Recognized typedef: " << line << endl; +#endif + types[currentExtension].push_back(line); + } + } + else + { +#ifdef DEBUG_PARSE + cerr << "Unrecognized line: " << line << endl; +#endif + } +} + +static void WriteHeader(ostream &file, const char *generator, + char **srcs, int num_srcs) +{ + file << "// -*- c++ -*-" << endl << endl; + file << "//DO NOT EDIT!" << endl; + file << "//This file was created with " << generator << endl + << "//from"; + for (int i = 0; i < num_srcs; i++) + { + file << " " << srcs[i]; + } + file << endl << endl; + file << "/*" << endl + << " * Copyright 2003 Sandia Corporation." << endl + << " * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive" << endl + << " * license for use of this work by or on behalf of the" << endl + << " * U.S. Government. Redistribution and use in source and binary forms, with" << endl + << " * or without modification, are permitted provided that this Notice and any" << endl + << " * statement of authorship are reproduced on all copies." << endl + << " */" << endl << endl; +} + +static void WriteClassDeclarationGuts(ostream &hfile, int type) +{ + for (vtkstd::list::iterator iextension = extensions.begin(); + iextension != extensions.end(); iextension++) + { + if (iextension->type != type) continue; + hfile << " //Definitions for " << iextension->name.c_str() << endl; + vtkstd::map >::iterator cExts + = consts.find(*iextension); + if (cExts != consts.end()) + { + hfile << " enum " << cExts->first.name.c_str() << "_consts {" << endl; + bool wroteFirst = false; + + for (vtkstd::list::iterator iconst = cExts->second.begin(); + iconst != cExts->second.end(); iconst++) + { + + // New versions of the NVIDIA OpenGL headers for Linux can + // #define the same constant with the same value in multiple + // sections. This utility will happily parse those and write + // out duplicate enums in different enum classes, which + // confuses the C++ preprocessor terribly. Don't write out a + // definition for an enum with a name/value pair that's + // already been used. + if ( ConstantsAlreadyWritten.find( vtkstd::make_pair( iconst->name, + iconst->value ) ) + == ConstantsAlreadyWritten.end() ) + { + if (wroteFirst) + { + hfile << "," << endl; + } + else + { + wroteFirst = true; + } + hfile << " " << iconst->name.c_str() << " = " + << iconst->value.c_str(); + + ConstantsAlreadyWritten.insert( vtkstd::make_pair( iconst->name, + iconst->value ) ); + + } + else + { + hfile << "/* skipping duplicate " << iconst->name.c_str() + << " = " << iconst->value.c_str() << " */" << endl; + } + } + hfile << endl << " };" << endl; + } + vtkstd::map >::iterator tExts + = types.find(*iextension); + if (tExts != types.end()) + { + for (vtkstd::list::iterator itype = tExts->second.begin(); + itype != tExts->second.end(); itype++) + { + hfile << " " << itype->definition.c_str() << endl; + } + } + vtkstd::map >::iterator fExts + = functs.find(*iextension); + if (fExts != functs.end()) + { + for (vtkstd::list::iterator ifunc = fExts->second.begin(); + ifunc != fExts->second.end(); ifunc++) + { + hfile << " extern VTK_RENDERING_EXPORT " << ifunc->GetProcType() + << " " << ifunc->name.c_str() << ";" << endl; + } + } + } +} + +static void WriteFunctionPointerDeclarations(ostream &cxxfile, int type) +{ + Extension::WriteSupportWrapperBegin(cxxfile, type); + for (vtkstd::map >::iterator fExts + = functs.begin(); + fExts != functs.end(); fExts++) + { + if (fExts->first.type != type) continue; + cxxfile << "//Functions for " << fExts->first.name.c_str() << endl; + for (vtkstd::list::iterator ifunc = fExts->second.begin(); + ifunc != fExts->second.end(); ifunc++) + { + cxxfile << "vtk" << Extension::TypeToString(type) << "::" + << ifunc->GetProcType() + << " vtk" << Extension::TypeToString(type) << "::" + << ifunc->name.c_str() << " = NULL;" << endl; + } + } + Extension::WriteSupportWrapperEnd(cxxfile, type); + cxxfile << endl; +} + +static void WriteCode(ostream &hfile, ostream &cxxfile) +{ + // Write data for header file --------------------------------- + hfile << "#ifndef _vtkgl_h" << endl + << "#define _vtkgl_h" << endl << endl; + hfile << "#include \"vtkToolkits.h\"" << endl; + hfile << "#include \"vtkSystemIncludes.h\"" << endl; + hfile << "#include \"vtkWindows.h\"" << endl; + hfile << "#include \"vtkOpenGL.h\"" << endl; + hfile << "#include " << endl << endl; + hfile << "//#ifdef __APPLE__" << endl + << "//#include " << endl + << "//#else" << endl + << "//#include " << endl + << "//#endif" << endl << endl; + hfile << "#ifdef VTK_USE_X" << endl + << "#include " << endl + << "#endif" << endl << endl; + hfile << "class vtkOpenGLExtensionManager;" << endl << endl; + hfile << "#ifndef APIENTRY" << endl + << "#define APIENTRY" << endl + << "#define VTKGL_APIENTRY_DEFINED" << endl + << "#endif" << endl << endl; + hfile << "#ifndef APIENTRYP" << endl + << "#define APIENTRYP APIENTRY *" << endl + << "#define VTKGL_APIENTRYP_DEFINED" << endl + << "#endif" << endl << endl; + + hfile << "/* Undefine all constants to avoid name conflicts. They should be defined */" << endl + << "/* with GL_, GLX_, or WGL_ preprended to them anyway, but sometimes you run */" << endl + << "/* into a header file that gets it wrong. */" << endl; + for (vtkstd::map >::iterator constlist + = consts.begin(); + constlist != consts.end(); constlist++) + { + for (vtkstd::list::iterator c = (*constlist).second.begin(); + c != (*constlist).second.end(); c++) + { + hfile << "#ifdef " << (*c).name.c_str() << endl; + hfile << "#undef " << (*c).name.c_str() << endl; + hfile << "#endif" << endl; + } + } + + Extension::WriteSupportWrapperBegin(hfile, Extension::GL); + hfile << endl << "namespace vtkgl {" << endl; + ConstantsAlreadyWritten.clear(); + WriteClassDeclarationGuts(hfile, Extension::GL); + hfile << endl << " // Method to load functions for a particular extension."; + hfile << endl << " int LoadExtension(const char *name, " + << "vtkOpenGLExtensionManager *manager);" << endl; + hfile << endl << " // Strings containing special version extensions."; + hfile << endl << " const char *GLVersionExtensionsString();" << endl; + hfile << endl << " const char *GLXVersionExtensionsString();" << endl; + hfile << "}" << endl; + Extension::WriteSupportWrapperEnd(hfile, Extension::GL); + + Extension::WriteSupportWrapperBegin(hfile, Extension::GLX); + hfile << "namespace vtkglX {" << endl; + // glxext.h is not written very well. Add some typedefs that may not + // be defined. + hfile << " //Miscellaneous definitions." << endl; + hfile << " typedef XID GLXContextID;" << endl; + hfile << " typedef XID GLXPbuffer;" << endl; + hfile << " typedef XID GLXWindow;" << endl; + hfile << " typedef XID GLXFBConfigID;" << endl; + hfile << " typedef struct __GLXFBConfigRec *GLXFBConfig;" << endl; + hfile << " typedef int int32_t;" << endl; + hfile << " typedef long long int64_t;" << endl; + ConstantsAlreadyWritten.clear(); + WriteClassDeclarationGuts(hfile, Extension::GLX); + hfile << "}" << endl; + Extension::WriteSupportWrapperEnd(hfile, Extension::GLX); + + Extension::WriteSupportWrapperBegin(hfile, Extension::WGL); + hfile << "namespace vtkwgl {" << endl; + ConstantsAlreadyWritten.clear(); + WriteClassDeclarationGuts(hfile, Extension::WGL); + hfile << "}" << endl; + Extension::WriteSupportWrapperEnd(hfile, Extension::WGL); + + hfile << endl + << "#ifdef VTKGL_APIENTRY_DEFINED" << endl + << "#undef APIENTRY" << endl + << "#endif" << endl << endl; + hfile << "#ifdef VTKGL_APIENTRYP_DEFINED" << endl + << "#undef APIENTRYP" << endl + << "#endif" << endl << endl; + hfile << "#endif //_vtkgl_h" << endl; + + // Write data for C++ file -------------------------------------------- + cxxfile << "#include \"vtkgl.h\"" << endl; + cxxfile << "#include \"vtkOpenGLExtensionManager.h\"" << endl << endl; + + // Write function pointer declarations. + WriteFunctionPointerDeclarations(cxxfile, Extension::GL); + WriteFunctionPointerDeclarations(cxxfile, Extension::GLX); + WriteFunctionPointerDeclarations(cxxfile, Extension::WGL); + + vtkstd::list::iterator iextension; + + // Write function to load function pointers. + cxxfile << "int vtkgl::LoadExtension(const char *name, vtkOpenGLExtensionManager *manager)" << endl + << "{" << endl; + for (iextension = extensions.begin(); + iextension != extensions.end(); iextension++) + { + iextension->WriteSupportWrapperBegin(cxxfile); + cxxfile << " if (strcmp(name, \"" << iextension->name.c_str() + << "\") == 0)" << endl + << " {" << endl; + vtkstd::string vtkglclass = "vtk"; + vtkglclass += Extension::TypeToString(iextension->type); + vtkstd::list::iterator ifunct; + for (ifunct = functs[*iextension].begin(); + ifunct != functs[*iextension].end(); ifunct++) + { + cxxfile << " " << vtkglclass.c_str() << "::" + << ifunct->name.c_str() << " = (" << vtkglclass.c_str() << "::" + << ifunct->GetProcType() + << ")manager->GetProcAddress(\"" + << Extension::TypeToString(iextension->type) + << ifunct->name.c_str() << "\");" << endl; + } + cxxfile << " return 1"; + for (ifunct = functs[*iextension].begin(); + ifunct != functs[*iextension].end(); ifunct++) + { + cxxfile << " && (" << vtkglclass.c_str() << "::" << ifunct->name.c_str() + << " != NULL)"; + } + cxxfile << ";" << endl; + cxxfile << " }" << endl; + iextension->WriteSupportWrapperEnd(cxxfile); + } + cxxfile << " vtkGenericWarningMacro(<< \"Nothing known about extension \" << name" << endl + << " << \". vtkgl may need to be updated.\");" << endl; + cxxfile << " return 0;" << endl + << "}" << endl; + + // Write functions to report special version extension strings. + cxxfile << endl << "const char *vtkgl::GLVersionExtensionsString()" << endl + << "{" << endl + << " return \""; + for (iextension = extensions.begin(); + iextension != extensions.end(); iextension++) + { + if (strncmp("GL_VERSION_", iextension->name.c_str(), 11) == 0) + { + cxxfile << iextension->name.c_str() << " "; + } + } + cxxfile << "\";" << endl + << "}" << endl; + + cxxfile << endl << "const char *vtkgl::GLXVersionExtensionsString()" << endl + << "{" << endl + << " return \""; + for (iextension = extensions.begin(); + iextension != extensions.end(); iextension++) + { + if (strncmp("GLX_VERSION_", iextension->name.c_str(), 12) == 0) + { + cxxfile << iextension->name.c_str() << " "; + } + } + cxxfile << "\";" << endl + << "}" << endl; +} + +int main(int argc, char **argv) +{ + if (argc < 3) + { + cerr << "USAGE: " << argv[0] << "
" << endl; + return 1; + } + + vtkstd::string outputDir = argv[1]; + + for (int i = 2; i < argc; i++) + { +#ifdef DEBUG_PARSE + cerr << "*** Parsing declarations from file " << argv[i] << endl; +#endif + ifstream file(argv[i]); + if (!file) + { + cerr << "Could not open " << argv[i] << endl; + return 2; + } + + while (!file.eof()) + { + static char buf[4096]; // What are the odds of needing more? + file.getline(buf, 4096); + ParseLine(buf); + } + file.close(); + } + + ofstream hfile((outputDir + "/vtkgl.h").c_str()); + WriteHeader(hfile, argv[0], argv+1, argc-1); + ofstream cxxfile((outputDir + "/vtkgl.cxx").c_str()); + WriteHeader(cxxfile, argv[0], argv+1, argc-1); + + WriteCode(hfile, cxxfile); + + hfile.close(); + cxxfile.close(); + + return 0; +} diff --git a/Utilities/ParseOGLExt/Tokenizer.cxx b/Utilities/ParseOGLExt/Tokenizer.cxx new file mode 100644 index 0000000..00252d6 --- /dev/null +++ b/Utilities/ParseOGLExt/Tokenizer.cxx @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Tokenizer.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "Tokenizer.h" + +#include "vtkSystemIncludes.h" + +Tokenizer::Tokenizer(const char *s, const char *delim) + : FullString(s), Delim(delim) +{ + this->Reset(); +} + +Tokenizer::Tokenizer(const vtkstd::string &s, const char *delim) + : FullString(s), Delim(delim) +{ + this->Reset(); +} + +vtkstd::string Tokenizer::GetNextToken() +{ + if (this->HasMoreTokens()) + { + vtkstd::string::size_type token_start = this->Position; + vtkstd::string::size_type token_end + = this->FullString.find_first_of(this->Delim, token_start); + this->Position = this->FullString.find_first_not_of(this->Delim, token_end); + + if (token_end != vtkstd::string::npos) + { + return this->FullString.substr(token_start, token_end-token_start); + } + else + { + return this->FullString.substr(token_start); + } + } + else + { + return vtkstd::string(); + } +} + +vtkstd::string Tokenizer::GetRemainingString() const +{ + if (this->HasMoreTokens()) + { + return this->FullString.substr(this->Position); + } + else + { + return vtkstd::string(); + } +} + +bool Tokenizer::HasMoreTokens() const +{ + return (this->Position != vtkstd::string::npos); +} + +void Tokenizer::Reset() +{ + this->Position = this->FullString.find_first_not_of(this->Delim); +} diff --git a/Utilities/ParseOGLExt/Tokenizer.h b/Utilities/ParseOGLExt/Tokenizer.h new file mode 100644 index 0000000..4fe70ae --- /dev/null +++ b/Utilities/ParseOGLExt/Tokenizer.h @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Tokenizer.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include + +class Tokenizer +{ +public: + Tokenizer(const char *s, const char *delim = " \t\n\r"); + Tokenizer(const vtkstd::string &s, const char *delim = " \t\n\r"); + + vtkstd::string GetNextToken(); + vtkstd::string GetRemainingString() const; + bool HasMoreTokens() const; + + void Reset(); + +private: + vtkstd::string FullString; + vtkstd::string Delim; + vtkstd::string::size_type Position; +}; diff --git a/Utilities/ParseOGLExt/headers/glext.h b/Utilities/ParseOGLExt/headers/glext.h new file mode 100644 index 0000000..1c02ec2 --- /dev/null +++ b/Utilities/ParseOGLExt/headers/glext.h @@ -0,0 +1,6389 @@ +#ifndef __glext_h_ +#define __glext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/*************************************************************/ + +/* Header file version number, required by OpenGL ABI for Linux */ +/* glext.h last updated 2005/01/20 */ +/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ +#define GL_GLEXT_VERSION 26 + +#ifndef GL_VERSION_1_2 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#endif + +#ifndef GL_ARB_imaging +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF +#define GL_CONSTANT_BORDER 0x8151 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 +#endif + +#ifndef GL_VERSION_1_3 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_MULTISAMPLE_BIT 0x20000000 +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_SUBTRACT 0x84E7 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#endif + +#ifndef GL_VERSION_1_4 +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E +#endif + +#ifndef GL_VERSION_1_5 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#endif + +#ifndef GL_VERSION_2_0 +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#endif + +#ifndef GL_ARB_multitexture +#define GL_TEXTURE0_ARB 0x84C0 +#define GL_TEXTURE1_ARB 0x84C1 +#define GL_TEXTURE2_ARB 0x84C2 +#define GL_TEXTURE3_ARB 0x84C3 +#define GL_TEXTURE4_ARB 0x84C4 +#define GL_TEXTURE5_ARB 0x84C5 +#define GL_TEXTURE6_ARB 0x84C6 +#define GL_TEXTURE7_ARB 0x84C7 +#define GL_TEXTURE8_ARB 0x84C8 +#define GL_TEXTURE9_ARB 0x84C9 +#define GL_TEXTURE10_ARB 0x84CA +#define GL_TEXTURE11_ARB 0x84CB +#define GL_TEXTURE12_ARB 0x84CC +#define GL_TEXTURE13_ARB 0x84CD +#define GL_TEXTURE14_ARB 0x84CE +#define GL_TEXTURE15_ARB 0x84CF +#define GL_TEXTURE16_ARB 0x84D0 +#define GL_TEXTURE17_ARB 0x84D1 +#define GL_TEXTURE18_ARB 0x84D2 +#define GL_TEXTURE19_ARB 0x84D3 +#define GL_TEXTURE20_ARB 0x84D4 +#define GL_TEXTURE21_ARB 0x84D5 +#define GL_TEXTURE22_ARB 0x84D6 +#define GL_TEXTURE23_ARB 0x84D7 +#define GL_TEXTURE24_ARB 0x84D8 +#define GL_TEXTURE25_ARB 0x84D9 +#define GL_TEXTURE26_ARB 0x84DA +#define GL_TEXTURE27_ARB 0x84DB +#define GL_TEXTURE28_ARB 0x84DC +#define GL_TEXTURE29_ARB 0x84DD +#define GL_TEXTURE30_ARB 0x84DE +#define GL_TEXTURE31_ARB 0x84DF +#define GL_ACTIVE_TEXTURE_ARB 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 +#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 +#endif + +#ifndef GL_ARB_multisample +#define GL_MULTISAMPLE_ARB 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F +#define GL_SAMPLE_COVERAGE_ARB 0x80A0 +#define GL_SAMPLE_BUFFERS_ARB 0x80A8 +#define GL_SAMPLES_ARB 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB +#define GL_MULTISAMPLE_BIT_ARB 0x20000000 +#endif + +#ifndef GL_ARB_texture_env_add +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_NORMAL_MAP_ARB 0x8511 +#define GL_REFLECTION_MAP_ARB 0x8512 +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C +#endif + +#ifndef GL_ARB_texture_compression +#define GL_COMPRESSED_ALPHA_ARB 0x84E9 +#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB +#define GL_COMPRESSED_INTENSITY_ARB 0x84EC +#define GL_COMPRESSED_RGB_ARB 0x84ED +#define GL_COMPRESSED_RGBA_ARB 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 +#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 +#endif + +#ifndef GL_ARB_texture_border_clamp +#define GL_CLAMP_TO_BORDER_ARB 0x812D +#endif + +#ifndef GL_ARB_point_parameters +#define GL_POINT_SIZE_MIN_ARB 0x8126 +#define GL_POINT_SIZE_MAX_ARB 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 +#endif + +#ifndef GL_ARB_vertex_blend +#define GL_MAX_VERTEX_UNITS_ARB 0x86A4 +#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 +#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 +#define GL_VERTEX_BLEND_ARB 0x86A7 +#define GL_CURRENT_WEIGHT_ARB 0x86A8 +#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA +#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB +#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC +#define GL_WEIGHT_ARRAY_ARB 0x86AD +#define GL_MODELVIEW0_ARB 0x1700 +#define GL_MODELVIEW1_ARB 0x850A +#define GL_MODELVIEW2_ARB 0x8722 +#define GL_MODELVIEW3_ARB 0x8723 +#define GL_MODELVIEW4_ARB 0x8724 +#define GL_MODELVIEW5_ARB 0x8725 +#define GL_MODELVIEW6_ARB 0x8726 +#define GL_MODELVIEW7_ARB 0x8727 +#define GL_MODELVIEW8_ARB 0x8728 +#define GL_MODELVIEW9_ARB 0x8729 +#define GL_MODELVIEW10_ARB 0x872A +#define GL_MODELVIEW11_ARB 0x872B +#define GL_MODELVIEW12_ARB 0x872C +#define GL_MODELVIEW13_ARB 0x872D +#define GL_MODELVIEW14_ARB 0x872E +#define GL_MODELVIEW15_ARB 0x872F +#define GL_MODELVIEW16_ARB 0x8730 +#define GL_MODELVIEW17_ARB 0x8731 +#define GL_MODELVIEW18_ARB 0x8732 +#define GL_MODELVIEW19_ARB 0x8733 +#define GL_MODELVIEW20_ARB 0x8734 +#define GL_MODELVIEW21_ARB 0x8735 +#define GL_MODELVIEW22_ARB 0x8736 +#define GL_MODELVIEW23_ARB 0x8737 +#define GL_MODELVIEW24_ARB 0x8738 +#define GL_MODELVIEW25_ARB 0x8739 +#define GL_MODELVIEW26_ARB 0x873A +#define GL_MODELVIEW27_ARB 0x873B +#define GL_MODELVIEW28_ARB 0x873C +#define GL_MODELVIEW29_ARB 0x873D +#define GL_MODELVIEW30_ARB 0x873E +#define GL_MODELVIEW31_ARB 0x873F +#endif + +#ifndef GL_ARB_matrix_palette +#define GL_MATRIX_PALETTE_ARB 0x8840 +#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 +#define GL_MAX_PALETTE_MATRICES_ARB 0x8842 +#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 +#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 +#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 +#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 +#endif + +#ifndef GL_ARB_texture_env_combine +#define GL_COMBINE_ARB 0x8570 +#define GL_COMBINE_RGB_ARB 0x8571 +#define GL_COMBINE_ALPHA_ARB 0x8572 +#define GL_SOURCE0_RGB_ARB 0x8580 +#define GL_SOURCE1_RGB_ARB 0x8581 +#define GL_SOURCE2_RGB_ARB 0x8582 +#define GL_SOURCE0_ALPHA_ARB 0x8588 +#define GL_SOURCE1_ALPHA_ARB 0x8589 +#define GL_SOURCE2_ALPHA_ARB 0x858A +#define GL_OPERAND0_RGB_ARB 0x8590 +#define GL_OPERAND1_RGB_ARB 0x8591 +#define GL_OPERAND2_RGB_ARB 0x8592 +#define GL_OPERAND0_ALPHA_ARB 0x8598 +#define GL_OPERAND1_ALPHA_ARB 0x8599 +#define GL_OPERAND2_ALPHA_ARB 0x859A +#define GL_RGB_SCALE_ARB 0x8573 +#define GL_ADD_SIGNED_ARB 0x8574 +#define GL_INTERPOLATE_ARB 0x8575 +#define GL_SUBTRACT_ARB 0x84E7 +#define GL_CONSTANT_ARB 0x8576 +#define GL_PRIMARY_COLOR_ARB 0x8577 +#define GL_PREVIOUS_ARB 0x8578 +#endif + +#ifndef GL_ARB_texture_env_crossbar +#endif + +#ifndef GL_ARB_texture_env_dot3 +#define GL_DOT3_RGB_ARB 0x86AE +#define GL_DOT3_RGBA_ARB 0x86AF +#endif + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_MIRRORED_REPEAT_ARB 0x8370 +#endif + +#ifndef GL_ARB_depth_texture +#define GL_DEPTH_COMPONENT16_ARB 0x81A5 +#define GL_DEPTH_COMPONENT24_ARB 0x81A6 +#define GL_DEPTH_COMPONENT32_ARB 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A +#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B +#endif + +#ifndef GL_ARB_shadow +#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C +#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D +#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E +#endif + +#ifndef GL_ARB_shadow_ambient +#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF +#endif + +#ifndef GL_ARB_window_pos +#endif + +#ifndef GL_ARB_vertex_program +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF +#endif + +#ifndef GL_ARB_fragment_program +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 +#endif + +#ifndef GL_ARB_vertex_buffer_object +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_READ_WRITE_ARB 0x88BA +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_COPY_ARB 0x88EA +#endif + +#ifndef GL_ARB_occlusion_query +#define GL_QUERY_COUNTER_BITS_ARB 0x8864 +#define GL_CURRENT_QUERY_ARB 0x8865 +#define GL_QUERY_RESULT_ARB 0x8866 +#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 +#define GL_SAMPLES_PASSED_ARB 0x8914 +#endif + +#ifndef GL_ARB_shader_objects +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 +#endif + +#ifndef GL_ARB_vertex_shader +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A +#endif + +#ifndef GL_ARB_fragment_shader +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B +#endif + +#ifndef GL_ARB_shading_language_100 +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C +#endif + +#ifndef GL_ARB_texture_non_power_of_two +#endif + +#ifndef GL_ARB_point_sprite +#define GL_POINT_SPRITE_ARB 0x8861 +#define GL_COORD_REPLACE_ARB 0x8862 +#endif + +#ifndef GL_ARB_fragment_program_shadow +#endif + +#ifndef GL_ARB_draw_buffers +#define GL_MAX_DRAW_BUFFERS_ARB 0x8824 +#define GL_DRAW_BUFFER0_ARB 0x8825 +#define GL_DRAW_BUFFER1_ARB 0x8826 +#define GL_DRAW_BUFFER2_ARB 0x8827 +#define GL_DRAW_BUFFER3_ARB 0x8828 +#define GL_DRAW_BUFFER4_ARB 0x8829 +#define GL_DRAW_BUFFER5_ARB 0x882A +#define GL_DRAW_BUFFER6_ARB 0x882B +#define GL_DRAW_BUFFER7_ARB 0x882C +#define GL_DRAW_BUFFER8_ARB 0x882D +#define GL_DRAW_BUFFER9_ARB 0x882E +#define GL_DRAW_BUFFER10_ARB 0x882F +#define GL_DRAW_BUFFER11_ARB 0x8830 +#define GL_DRAW_BUFFER12_ARB 0x8831 +#define GL_DRAW_BUFFER13_ARB 0x8832 +#define GL_DRAW_BUFFER14_ARB 0x8833 +#define GL_DRAW_BUFFER15_ARB 0x8834 +#endif + +#ifndef GL_ARB_texture_rectangle +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 +#endif + +#ifndef GL_ARB_color_buffer_float +#define GL_RGBA_FLOAT_MODE_ARB 0x8820 +#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A +#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B +#define GL_CLAMP_READ_COLOR_ARB 0x891C +#define GL_FIXED_ONLY_ARB 0x891D +#endif + +#ifndef GL_ARB_half_float_pixel +#define GL_HALF_FLOAT_ARB 0x140B +#endif + +#ifndef GL_ARB_texture_float +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGB32F_ARB 0x8815 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_RGBA16F_ARB 0x881A +#define GL_RGB16F_ARB 0x881B +#define GL_ALPHA16F_ARB 0x881C +#define GL_INTENSITY16F_ARB 0x881D +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#endif + +#ifndef GL_ARB_pixel_buffer_object +#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF +#endif + +#ifndef GL_EXT_abgr +#define GL_ABGR_EXT 0x8000 +#endif + +#ifndef GL_EXT_blend_color +#define GL_CONSTANT_COLOR_EXT 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 +#define GL_CONSTANT_ALPHA_EXT 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 +#define GL_BLEND_COLOR_EXT 0x8005 +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_POLYGON_OFFSET_EXT 0x8037 +#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 +#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 +#endif + +#ifndef GL_EXT_texture +#define GL_ALPHA4_EXT 0x803B +#define GL_ALPHA8_EXT 0x803C +#define GL_ALPHA12_EXT 0x803D +#define GL_ALPHA16_EXT 0x803E +#define GL_LUMINANCE4_EXT 0x803F +#define GL_LUMINANCE8_EXT 0x8040 +#define GL_LUMINANCE12_EXT 0x8041 +#define GL_LUMINANCE16_EXT 0x8042 +#define GL_LUMINANCE4_ALPHA4_EXT 0x8043 +#define GL_LUMINANCE6_ALPHA2_EXT 0x8044 +#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 +#define GL_LUMINANCE12_ALPHA4_EXT 0x8046 +#define GL_LUMINANCE12_ALPHA12_EXT 0x8047 +#define GL_LUMINANCE16_ALPHA16_EXT 0x8048 +#define GL_INTENSITY_EXT 0x8049 +#define GL_INTENSITY4_EXT 0x804A +#define GL_INTENSITY8_EXT 0x804B +#define GL_INTENSITY12_EXT 0x804C +#define GL_INTENSITY16_EXT 0x804D +#define GL_RGB2_EXT 0x804E +#define GL_RGB4_EXT 0x804F +#define GL_RGB5_EXT 0x8050 +#define GL_RGB8_EXT 0x8051 +#define GL_RGB10_EXT 0x8052 +#define GL_RGB12_EXT 0x8053 +#define GL_RGB16_EXT 0x8054 +#define GL_RGBA2_EXT 0x8055 +#define GL_RGBA4_EXT 0x8056 +#define GL_RGB5_A1_EXT 0x8057 +#define GL_RGBA8_EXT 0x8058 +#define GL_RGB10_A2_EXT 0x8059 +#define GL_RGBA12_EXT 0x805A +#define GL_RGBA16_EXT 0x805B +#define GL_TEXTURE_RED_SIZE_EXT 0x805C +#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D +#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E +#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 +#define GL_REPLACE_EXT 0x8062 +#define GL_PROXY_TEXTURE_1D_EXT 0x8063 +#define GL_PROXY_TEXTURE_2D_EXT 0x8064 +#define GL_TEXTURE_TOO_LARGE_EXT 0x8065 +#endif + +#ifndef GL_EXT_texture3D +#define GL_PACK_SKIP_IMAGES_EXT 0x806B +#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C +#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D +#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E +#define GL_TEXTURE_3D_EXT 0x806F +#define GL_PROXY_TEXTURE_3D_EXT 0x8070 +#define GL_TEXTURE_DEPTH_EXT 0x8071 +#define GL_TEXTURE_WRAP_R_EXT 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_FILTER4_SGIS 0x8146 +#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 +#endif + +#ifndef GL_EXT_subtexture +#endif + +#ifndef GL_EXT_copy_texture +#endif + +#ifndef GL_EXT_histogram +#define GL_HISTOGRAM_EXT 0x8024 +#define GL_PROXY_HISTOGRAM_EXT 0x8025 +#define GL_HISTOGRAM_WIDTH_EXT 0x8026 +#define GL_HISTOGRAM_FORMAT_EXT 0x8027 +#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C +#define GL_HISTOGRAM_SINK_EXT 0x802D +#define GL_MINMAX_EXT 0x802E +#define GL_MINMAX_FORMAT_EXT 0x802F +#define GL_MINMAX_SINK_EXT 0x8030 +#define GL_TABLE_TOO_LARGE_EXT 0x8031 +#endif + +#ifndef GL_EXT_convolution +#define GL_CONVOLUTION_1D_EXT 0x8010 +#define GL_CONVOLUTION_2D_EXT 0x8011 +#define GL_SEPARABLE_2D_EXT 0x8012 +#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 +#define GL_REDUCE_EXT 0x8016 +#define GL_CONVOLUTION_FORMAT_EXT 0x8017 +#define GL_CONVOLUTION_WIDTH_EXT 0x8018 +#define GL_CONVOLUTION_HEIGHT_EXT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 +#endif + +#ifndef GL_SGI_color_matrix +#define GL_COLOR_MATRIX_SGI 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB +#endif + +#ifndef GL_SGI_color_table +#define GL_COLOR_TABLE_SGI 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 +#define GL_PROXY_COLOR_TABLE_SGI 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 +#define GL_COLOR_TABLE_SCALE_SGI 0x80D6 +#define GL_COLOR_TABLE_BIAS_SGI 0x80D7 +#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 +#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_PIXEL_TEXTURE_SGIS 0x8353 +#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 +#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 +#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_PIXEL_TEX_GEN_SGIX 0x8139 +#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B +#endif + +#ifndef GL_SGIS_texture4D +#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 +#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 +#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 +#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 +#define GL_TEXTURE_4D_SGIS 0x8134 +#define GL_PROXY_TEXTURE_4D_SGIS 0x8135 +#define GL_TEXTURE_4DSIZE_SGIS 0x8136 +#define GL_TEXTURE_WRAP_Q_SGIS 0x8137 +#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 +#define GL_TEXTURE_4D_BINDING_SGIS 0x814F +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC +#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD +#endif + +#ifndef GL_EXT_cmyka +#define GL_CMYK_EXT 0x800C +#define GL_CMYKA_EXT 0x800D +#define GL_PACK_CMYK_HINT_EXT 0x800E +#define GL_UNPACK_CMYK_HINT_EXT 0x800F +#endif + +#ifndef GL_EXT_texture_object +#define GL_TEXTURE_PRIORITY_EXT 0x8066 +#define GL_TEXTURE_RESIDENT_EXT 0x8067 +#define GL_TEXTURE_1D_BINDING_EXT 0x8068 +#define GL_TEXTURE_2D_BINDING_EXT 0x8069 +#define GL_TEXTURE_3D_BINDING_EXT 0x806A +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 +#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 +#define GL_LINEAR_DETAIL_SGIS 0x8097 +#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 +#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 +#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A +#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B +#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_LINEAR_SHARPEN_SGIS 0x80AD +#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE +#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF +#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_TEXTURE_MIN_LOD_SGIS 0x813A +#define GL_TEXTURE_MAX_LOD_SGIS 0x813B +#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C +#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D +#endif + +#ifndef GL_SGIS_multisample +#define GL_MULTISAMPLE_SGIS 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F +#define GL_SAMPLE_MASK_SGIS 0x80A0 +#define GL_1PASS_SGIS 0x80A1 +#define GL_2PASS_0_SGIS 0x80A2 +#define GL_2PASS_1_SGIS 0x80A3 +#define GL_4PASS_0_SGIS 0x80A4 +#define GL_4PASS_1_SGIS 0x80A5 +#define GL_4PASS_2_SGIS 0x80A6 +#define GL_4PASS_3_SGIS 0x80A7 +#define GL_SAMPLE_BUFFERS_SGIS 0x80A8 +#define GL_SAMPLES_SGIS 0x80A9 +#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA +#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB +#define GL_SAMPLE_PATTERN_SGIS 0x80AC +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_RESCALE_NORMAL_EXT 0x803A +#endif + +#ifndef GL_EXT_vertex_array +#define GL_VERTEX_ARRAY_EXT 0x8074 +#define GL_NORMAL_ARRAY_EXT 0x8075 +#define GL_COLOR_ARRAY_EXT 0x8076 +#define GL_INDEX_ARRAY_EXT 0x8077 +#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 +#define GL_EDGE_FLAG_ARRAY_EXT 0x8079 +#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A +#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B +#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C +#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D +#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E +#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F +#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 +#define GL_COLOR_ARRAY_SIZE_EXT 0x8081 +#define GL_COLOR_ARRAY_TYPE_EXT 0x8082 +#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 +#define GL_COLOR_ARRAY_COUNT_EXT 0x8084 +#define GL_INDEX_ARRAY_TYPE_EXT 0x8085 +#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 +#define GL_INDEX_ARRAY_COUNT_EXT 0x8087 +#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A +#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B +#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C +#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D +#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E +#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F +#define GL_COLOR_ARRAY_POINTER_EXT 0x8090 +#define GL_INDEX_ARRAY_POINTER_EXT 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 +#endif + +#ifndef GL_EXT_misc_attribute +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_GENERATE_MIPMAP_SGIS 0x8191 +#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 +#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 +#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 +#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 +#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 +#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 +#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 +#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 +#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 +#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D +#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E +#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F +#endif + +#ifndef GL_SGIX_shadow +#define GL_TEXTURE_COMPARE_SGIX 0x819A +#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B +#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C +#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_CLAMP_TO_EDGE_SGIS 0x812F +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_CLAMP_TO_BORDER_SGIS 0x812D +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_FUNC_ADD_EXT 0x8006 +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#define GL_BLEND_EQUATION_EXT 0x8009 +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_FUNC_SUBTRACT_EXT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B +#endif + +#ifndef GL_EXT_blend_logic_op +#endif + +#ifndef GL_SGIX_interlace +#define GL_INTERLACE_SGIX 0x8094 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E +#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F +#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 +#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 +#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 +#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 +#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 +#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 +#endif + +#ifndef GL_SGIS_texture_select +#define GL_DUAL_ALPHA4_SGIS 0x8110 +#define GL_DUAL_ALPHA8_SGIS 0x8111 +#define GL_DUAL_ALPHA12_SGIS 0x8112 +#define GL_DUAL_ALPHA16_SGIS 0x8113 +#define GL_DUAL_LUMINANCE4_SGIS 0x8114 +#define GL_DUAL_LUMINANCE8_SGIS 0x8115 +#define GL_DUAL_LUMINANCE12_SGIS 0x8116 +#define GL_DUAL_LUMINANCE16_SGIS 0x8117 +#define GL_DUAL_INTENSITY4_SGIS 0x8118 +#define GL_DUAL_INTENSITY8_SGIS 0x8119 +#define GL_DUAL_INTENSITY12_SGIS 0x811A +#define GL_DUAL_INTENSITY16_SGIS 0x811B +#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C +#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D +#define GL_QUAD_ALPHA4_SGIS 0x811E +#define GL_QUAD_ALPHA8_SGIS 0x811F +#define GL_QUAD_LUMINANCE4_SGIS 0x8120 +#define GL_QUAD_LUMINANCE8_SGIS 0x8121 +#define GL_QUAD_INTENSITY4_SGIS 0x8122 +#define GL_QUAD_INTENSITY8_SGIS 0x8123 +#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 +#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SPRITE_SGIX 0x8148 +#define GL_SPRITE_MODE_SGIX 0x8149 +#define GL_SPRITE_AXIS_SGIX 0x814A +#define GL_SPRITE_TRANSLATION_SGIX 0x814B +#define GL_SPRITE_AXIAL_SGIX 0x814C +#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D +#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E +#endif + +#ifndef GL_EXT_point_parameters +#define GL_POINT_SIZE_MIN_EXT 0x8126 +#define GL_POINT_SIZE_MAX_EXT 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 +#define GL_DISTANCE_ATTENUATION_EXT 0x8129 +#endif + +#ifndef GL_SGIS_point_parameters +#define GL_POINT_SIZE_MIN_SGIS 0x8126 +#define GL_POINT_SIZE_MAX_SGIS 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 +#define GL_DISTANCE_ATTENUATION_SGIS 0x8129 +#endif + +#ifndef GL_SGIX_instruments +#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 +#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 +#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A +#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B +#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C +#endif + +#ifndef GL_SGIX_framezoom +#define GL_FRAMEZOOM_SGIX 0x818B +#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C +#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#endif + +#ifndef GL_FfdMaskSGIX +#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001 +#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002 +#endif + +#ifndef GL_SGIX_polynomial_ffd +#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194 +#define GL_TEXTURE_DEFORMATION_SGIX 0x8195 +#define GL_DEFORMATIONS_MASK_SGIX 0x8196 +#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197 +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_REFERENCE_PLANE_SGIX 0x817D +#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E +#endif + +#ifndef GL_SGIX_flush_raster +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_DEPTH_COMPONENT16_SGIX 0x81A5 +#define GL_DEPTH_COMPONENT24_SGIX 0x81A6 +#define GL_DEPTH_COMPONENT32_SGIX 0x81A7 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_FOG_FUNC_SGIS 0x812A +#define GL_FOG_FUNC_POINTS_SGIS 0x812B +#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_FOG_OFFSET_SGIX 0x8198 +#define GL_FOG_OFFSET_VALUE_SGIX 0x8199 +#endif + +#ifndef GL_HP_image_transform +#define GL_IMAGE_SCALE_X_HP 0x8155 +#define GL_IMAGE_SCALE_Y_HP 0x8156 +#define GL_IMAGE_TRANSLATE_X_HP 0x8157 +#define GL_IMAGE_TRANSLATE_Y_HP 0x8158 +#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 +#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A +#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B +#define GL_IMAGE_MAG_FILTER_HP 0x815C +#define GL_IMAGE_MIN_FILTER_HP 0x815D +#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E +#define GL_CUBIC_HP 0x815F +#define GL_AVERAGE_HP 0x8160 +#define GL_IMAGE_TRANSFORM_2D_HP 0x8161 +#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 +#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_IGNORE_BORDER_HP 0x8150 +#define GL_CONSTANT_BORDER_HP 0x8151 +#define GL_REPLICATE_BORDER_HP 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 +#endif + +#ifndef GL_INGR_palette_buffer +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE +#endif + +#ifndef GL_EXT_color_subtable +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_VERTEX_DATA_HINT_PGI 0x1A22A +#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B +#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C +#define GL_MAX_VERTEX_HINT_PGI 0x1A22D +#define GL_COLOR3_BIT_PGI 0x00010000 +#define GL_COLOR4_BIT_PGI 0x00020000 +#define GL_EDGEFLAG_BIT_PGI 0x00040000 +#define GL_INDEX_BIT_PGI 0x00080000 +#define GL_MAT_AMBIENT_BIT_PGI 0x00100000 +#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 +#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 +#define GL_MAT_EMISSION_BIT_PGI 0x00800000 +#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 +#define GL_MAT_SHININESS_BIT_PGI 0x02000000 +#define GL_MAT_SPECULAR_BIT_PGI 0x04000000 +#define GL_NORMAL_BIT_PGI 0x08000000 +#define GL_TEXCOORD1_BIT_PGI 0x10000000 +#define GL_TEXCOORD2_BIT_PGI 0x20000000 +#define GL_TEXCOORD3_BIT_PGI 0x40000000 +#define GL_TEXCOORD4_BIT_PGI 0x80000000 +#define GL_VERTEX23_BIT_PGI 0x00000004 +#define GL_VERTEX4_BIT_PGI 0x00000008 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 +#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD +#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE +#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 +#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 +#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 +#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C +#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D +#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E +#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F +#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 +#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 +#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 +#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 +#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 +#define GL_FULL_STIPPLE_HINT_PGI 0x1A219 +#define GL_CLIP_NEAR_HINT_PGI 0x1A220 +#define GL_CLIP_FAR_HINT_PGI 0x1A221 +#define GL_WIDE_LINE_HINT_PGI 0x1A222 +#define GL_BACK_NORMALS_HINT_PGI 0x1A223 +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_LIST_PRIORITY_SGIX 0x8182 +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_IR_INSTRUMENT1_SGIX 0x817F +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E +#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F +#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SHADOW_AMBIENT_SGIX 0x80BF +#endif + +#ifndef GL_EXT_index_texture +#endif + +#ifndef GL_EXT_index_material +#define GL_INDEX_MATERIAL_EXT 0x81B8 +#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 +#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA +#endif + +#ifndef GL_EXT_index_func +#define GL_INDEX_TEST_EXT 0x81B5 +#define GL_INDEX_TEST_FUNC_EXT 0x81B6 +#define GL_INDEX_TEST_REF_EXT 0x81B7 +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_IUI_V2F_EXT 0x81AD +#define GL_IUI_V3F_EXT 0x81AE +#define GL_IUI_N3F_V2F_EXT 0x81AF +#define GL_IUI_N3F_V3F_EXT 0x81B0 +#define GL_T2F_IUI_V2F_EXT 0x81B1 +#define GL_T2F_IUI_V3F_EXT 0x81B2 +#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 +#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 +#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_CULL_VERTEX_EXT 0x81AA +#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB +#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_YCRCB_422_SGIX 0x81BB +#define GL_YCRCB_444_SGIX 0x81BC +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_FRAGMENT_LIGHTING_SGIX 0x8400 +#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 +#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 +#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 +#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 +#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 +#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 +#define GL_LIGHT_ENV_MODE_SGIX 0x8407 +#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 +#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 +#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A +#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B +#define GL_FRAGMENT_LIGHT0_SGIX 0x840C +#define GL_FRAGMENT_LIGHT1_SGIX 0x840D +#define GL_FRAGMENT_LIGHT2_SGIX 0x840E +#define GL_FRAGMENT_LIGHT3_SGIX 0x840F +#define GL_FRAGMENT_LIGHT4_SGIX 0x8410 +#define GL_FRAGMENT_LIGHT5_SGIX 0x8411 +#define GL_FRAGMENT_LIGHT6_SGIX 0x8412 +#define GL_FRAGMENT_LIGHT7_SGIX 0x8413 +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 +#define GL_TEXTURE_POST_SPECULAR_HP 0x8168 +#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 +#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 +#endif + +#ifndef GL_WIN_phong_shading +#define GL_PHONG_WIN 0x80EA +#define GL_PHONG_HINT_WIN 0x80EB +#endif + +#ifndef GL_WIN_specular_fog +#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC +#endif + +#ifndef GL_EXT_light_texture +#define GL_FRAGMENT_MATERIAL_EXT 0x8349 +#define GL_FRAGMENT_NORMAL_EXT 0x834A +#define GL_FRAGMENT_COLOR_EXT 0x834C +#define GL_ATTENUATION_EXT 0x834D +#define GL_SHADOW_ATTENUATION_EXT 0x834E +#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F +#define GL_TEXTURE_LIGHT_EXT 0x8350 +#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 +#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 +/* reuse GL_FRAGMENT_DEPTH_EXT */ +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_ALPHA_MIN_SGIX 0x8320 +#define GL_ALPHA_MAX_SGIX 0x8321 +#endif + +#ifndef GL_SGIX_impact_pixel_texture +#define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184 +#define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185 +#define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186 +#define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187 +#define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188 +#define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189 +#define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A +#endif + +#ifndef GL_EXT_bgra +#define GL_BGR_EXT 0x80E0 +#define GL_BGRA_EXT 0x80E1 +#endif + +#ifndef GL_SGIX_async +#define GL_ASYNC_MARKER_SGIX 0x8329 +#endif + +#ifndef GL_SGIX_async_pixel +#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C +#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D +#define GL_ASYNC_READ_PIXELS_SGIX 0x835E +#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F +#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 +#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 +#endif + +#ifndef GL_SGIX_async_histogram +#define GL_ASYNC_HISTOGRAM_SGIX 0x832C +#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D +#endif + +#ifndef GL_INTEL_texture_scissor +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_PARALLEL_ARRAYS_INTEL 0x83F4 +#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 +#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 +#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 +#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 +#endif + +#ifndef GL_HP_occlusion_test +#define GL_OCCLUSION_TEST_HP 0x8165 +#define GL_OCCLUSION_TEST_RESULT_HP 0x8166 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 +#define GL_PIXEL_MAG_FILTER_EXT 0x8331 +#define GL_PIXEL_MIN_FILTER_EXT 0x8332 +#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 +#define GL_CUBIC_EXT 0x8334 +#define GL_AVERAGE_EXT 0x8335 +#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 +#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 +#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 +#define GL_SINGLE_COLOR_EXT 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA +#endif + +#ifndef GL_EXT_secondary_color +#define GL_COLOR_SUM_EXT 0x8458 +#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D +#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_PERTURB_EXT 0x85AE +#define GL_TEXTURE_NORMAL_EXT 0x85AF +#endif + +#ifndef GL_EXT_multi_draw_arrays +#endif + +#ifndef GL_EXT_fog_coord +#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 +#define GL_FOG_COORDINATE_EXT 0x8451 +#define GL_FRAGMENT_DEPTH_EXT 0x8452 +#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 +#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_SCREEN_COORDINATES_REND 0x8490 +#define GL_INVERTED_SCREEN_W_REND 0x8491 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_TANGENT_ARRAY_EXT 0x8439 +#define GL_BINORMAL_ARRAY_EXT 0x843A +#define GL_CURRENT_TANGENT_EXT 0x843B +#define GL_CURRENT_BINORMAL_EXT 0x843C +#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E +#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F +#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 +#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 +#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 +#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 +#define GL_MAP1_TANGENT_EXT 0x8444 +#define GL_MAP2_TANGENT_EXT 0x8445 +#define GL_MAP1_BINORMAL_EXT 0x8446 +#define GL_MAP2_BINORMAL_EXT 0x8447 +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_COMBINE_EXT 0x8570 +#define GL_COMBINE_RGB_EXT 0x8571 +#define GL_COMBINE_ALPHA_EXT 0x8572 +#define GL_RGB_SCALE_EXT 0x8573 +#define GL_ADD_SIGNED_EXT 0x8574 +#define GL_INTERPOLATE_EXT 0x8575 +#define GL_CONSTANT_EXT 0x8576 +#define GL_PRIMARY_COLOR_EXT 0x8577 +#define GL_PREVIOUS_EXT 0x8578 +#define GL_SOURCE0_RGB_EXT 0x8580 +#define GL_SOURCE1_RGB_EXT 0x8581 +#define GL_SOURCE2_RGB_EXT 0x8582 +#define GL_SOURCE0_ALPHA_EXT 0x8588 +#define GL_SOURCE1_ALPHA_EXT 0x8589 +#define GL_SOURCE2_ALPHA_EXT 0x858A +#define GL_OPERAND0_RGB_EXT 0x8590 +#define GL_OPERAND1_RGB_EXT 0x8591 +#define GL_OPERAND2_RGB_EXT 0x8592 +#define GL_OPERAND0_ALPHA_EXT 0x8598 +#define GL_OPERAND1_ALPHA_EXT 0x8599 +#define GL_OPERAND2_ALPHA_EXT 0x859A +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_TRANSFORM_HINT_APPLE 0x85B1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_FOG_SCALE_SGIX 0x81FC +#define GL_FOG_SCALE_VALUE_SGIX 0x81FD +#endif + +#ifndef GL_SUNX_constant_data +#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 +#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 +#endif + +#ifndef GL_SUN_global_alpha +#define GL_GLOBAL_ALPHA_SUN 0x81D9 +#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA +#endif + +#ifndef GL_SUN_triangle_list +#define GL_RESTART_SUN 0x0001 +#define GL_REPLACE_MIDDLE_SUN 0x0002 +#define GL_REPLACE_OLDEST_SUN 0x0003 +#define GL_TRIANGLE_LIST_SUN 0x81D7 +#define GL_REPLACEMENT_CODE_SUN 0x81D8 +#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 +#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 +#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 +#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 +#define GL_R1UI_V3F_SUN 0x85C4 +#define GL_R1UI_C4UB_V3F_SUN 0x85C5 +#define GL_R1UI_C3F_V3F_SUN 0x85C6 +#define GL_R1UI_N3F_V3F_SUN 0x85C7 +#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 +#define GL_R1UI_T2F_V3F_SUN 0x85C9 +#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA +#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB +#endif + +#ifndef GL_SUN_vertex +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_BLEND_DST_RGB_EXT 0x80C8 +#define GL_BLEND_SRC_RGB_EXT 0x80C9 +#define GL_BLEND_DST_ALPHA_EXT 0x80CA +#define GL_BLEND_SRC_ALPHA_EXT 0x80CB +#endif + +#ifndef GL_INGR_color_clamp +#define GL_RED_MIN_CLAMP_INGR 0x8560 +#define GL_GREEN_MIN_CLAMP_INGR 0x8561 +#define GL_BLUE_MIN_CLAMP_INGR 0x8562 +#define GL_ALPHA_MIN_CLAMP_INGR 0x8563 +#define GL_RED_MAX_CLAMP_INGR 0x8564 +#define GL_GREEN_MAX_CLAMP_INGR 0x8565 +#define GL_BLUE_MAX_CLAMP_INGR 0x8566 +#define GL_ALPHA_MAX_CLAMP_INGR 0x8567 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INTERLACE_READ_INGR 0x8568 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_INCR_WRAP_EXT 0x8507 +#define GL_DECR_WRAP_EXT 0x8508 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_422_EXT 0x80CC +#define GL_422_REV_EXT 0x80CD +#define GL_422_AVERAGE_EXT 0x80CE +#define GL_422_REV_AVERAGE_EXT 0x80CF +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NORMAL_MAP_NV 0x8511 +#define GL_REFLECTION_MAP_NV 0x8512 +#endif + +#ifndef GL_EXT_texture_cube_map +#define GL_NORMAL_MAP_EXT 0x8511 +#define GL_REFLECTION_MAP_EXT 0x8512 +#define GL_TEXTURE_CUBE_MAP_EXT 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_WRAP_BORDER_SUN 0x81D4 +#endif + +#ifndef GL_EXT_texture_env_add +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD +#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 +#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH +#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 +#define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX +#define GL_MODELVIEW1_MATRIX_EXT 0x8506 +#define GL_VERTEX_WEIGHTING_EXT 0x8509 +#define GL_MODELVIEW0_EXT GL_MODELVIEW +#define GL_MODELVIEW1_EXT 0x850A +#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B +#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C +#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D +#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E +#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F +#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_MAX_SHININESS_NV 0x8504 +#define GL_MAX_SPOT_EXPONENT_NV 0x8505 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_VERTEX_ARRAY_RANGE_NV 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E +#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F +#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 +#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 +#endif + +#ifndef GL_NV_register_combiners +#define GL_REGISTER_COMBINERS_NV 0x8522 +#define GL_VARIABLE_A_NV 0x8523 +#define GL_VARIABLE_B_NV 0x8524 +#define GL_VARIABLE_C_NV 0x8525 +#define GL_VARIABLE_D_NV 0x8526 +#define GL_VARIABLE_E_NV 0x8527 +#define GL_VARIABLE_F_NV 0x8528 +#define GL_VARIABLE_G_NV 0x8529 +#define GL_CONSTANT_COLOR0_NV 0x852A +#define GL_CONSTANT_COLOR1_NV 0x852B +#define GL_PRIMARY_COLOR_NV 0x852C +#define GL_SECONDARY_COLOR_NV 0x852D +#define GL_SPARE0_NV 0x852E +#define GL_SPARE1_NV 0x852F +#define GL_DISCARD_NV 0x8530 +#define GL_E_TIMES_F_NV 0x8531 +#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 +#define GL_UNSIGNED_IDENTITY_NV 0x8536 +#define GL_UNSIGNED_INVERT_NV 0x8537 +#define GL_EXPAND_NORMAL_NV 0x8538 +#define GL_EXPAND_NEGATE_NV 0x8539 +#define GL_HALF_BIAS_NORMAL_NV 0x853A +#define GL_HALF_BIAS_NEGATE_NV 0x853B +#define GL_SIGNED_IDENTITY_NV 0x853C +#define GL_SIGNED_NEGATE_NV 0x853D +#define GL_SCALE_BY_TWO_NV 0x853E +#define GL_SCALE_BY_FOUR_NV 0x853F +#define GL_SCALE_BY_ONE_HALF_NV 0x8540 +#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 +#define GL_COMBINER_INPUT_NV 0x8542 +#define GL_COMBINER_MAPPING_NV 0x8543 +#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 +#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 +#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 +#define GL_COMBINER_MUX_SUM_NV 0x8547 +#define GL_COMBINER_SCALE_NV 0x8548 +#define GL_COMBINER_BIAS_NV 0x8549 +#define GL_COMBINER_AB_OUTPUT_NV 0x854A +#define GL_COMBINER_CD_OUTPUT_NV 0x854B +#define GL_COMBINER_SUM_OUTPUT_NV 0x854C +#define GL_MAX_GENERAL_COMBINERS_NV 0x854D +#define GL_NUM_GENERAL_COMBINERS_NV 0x854E +#define GL_COLOR_SUM_CLAMP_NV 0x854F +#define GL_COMBINER0_NV 0x8550 +#define GL_COMBINER1_NV 0x8551 +#define GL_COMBINER2_NV 0x8552 +#define GL_COMBINER3_NV 0x8553 +#define GL_COMBINER4_NV 0x8554 +#define GL_COMBINER5_NV 0x8555 +#define GL_COMBINER6_NV 0x8556 +#define GL_COMBINER7_NV 0x8557 +/* reuse GL_TEXTURE0_ARB */ +/* reuse GL_TEXTURE1_ARB */ +/* reuse GL_ZERO */ +/* reuse GL_NONE */ +/* reuse GL_FOG */ +#endif + +#ifndef GL_NV_fog_distance +#define GL_FOG_DISTANCE_MODE_NV 0x855A +#define GL_EYE_RADIAL_NV 0x855B +#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C +/* reuse GL_EYE_PLANE */ +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_EMBOSS_LIGHT_NV 0x855D +#define GL_EMBOSS_CONSTANT_NV 0x855E +#define GL_EMBOSS_MAP_NV 0x855F +#endif + +#ifndef GL_NV_blend_square +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_COMBINE4_NV 0x8503 +#define GL_SOURCE3_RGB_NV 0x8583 +#define GL_SOURCE3_ALPHA_NV 0x858B +#define GL_OPERAND3_RGB_NV 0x8593 +#define GL_OPERAND3_ALPHA_NV 0x859B +#endif + +#ifndef GL_MESA_resize_buffers +#endif + +#ifndef GL_MESA_window_pos +#endif + +#ifndef GL_EXT_texture_compression_s3tc +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_CULL_VERTEX_IBM 103050 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_VERTEX_ARRAY_LIST_IBM 103070 +#define GL_NORMAL_ARRAY_LIST_IBM 103071 +#define GL_COLOR_ARRAY_LIST_IBM 103072 +#define GL_INDEX_ARRAY_LIST_IBM 103073 +#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 +#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 +#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 +#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 +#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 +#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 +#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 +#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 +#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 +#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 +#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 +#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 +#endif + +#ifndef GL_SGIX_subsample +#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 +#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 +#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 +#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 +#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_YCRCB_SGIX 0x8318 +#define GL_YCRCBA_SGIX 0x8319 +#endif + +#ifndef GL_SGI_depth_pass_instrument +#define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 +#define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 +#define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 +#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 +#endif + +#ifndef GL_3DFX_tbuffer +#endif + +#ifndef GL_EXT_multisample +#define GL_MULTISAMPLE_EXT 0x809D +#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F +#define GL_SAMPLE_MASK_EXT 0x80A0 +#define GL_1PASS_EXT 0x80A1 +#define GL_2PASS_0_EXT 0x80A2 +#define GL_2PASS_1_EXT 0x80A3 +#define GL_4PASS_0_EXT 0x80A4 +#define GL_4PASS_1_EXT 0x80A5 +#define GL_4PASS_2_EXT 0x80A6 +#define GL_4PASS_3_EXT 0x80A7 +#define GL_SAMPLE_BUFFERS_EXT 0x80A8 +#define GL_SAMPLES_EXT 0x80A9 +#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA +#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB +#define GL_SAMPLE_PATTERN_EXT 0x80AC +#define GL_MULTISAMPLE_BIT_EXT 0x20000000 +#endif + +#ifndef GL_SGIX_vertex_preclip +#define GL_VERTEX_PRECLIP_SGIX 0x83EE +#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_CONVOLUTION_HINT_SGIX 0x8316 +#endif + +#ifndef GL_SGIX_resample +#define GL_PACK_RESAMPLE_SGIX 0x842C +#define GL_UNPACK_RESAMPLE_SGIX 0x842D +#define GL_RESAMPLE_REPLICATE_SGIX 0x842E +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define GL_RESAMPLE_DECIMATE_SGIX 0x8430 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 +#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 +#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 +#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 +#define GL_EYE_POINT_SGIS 0x81F4 +#define GL_OBJECT_POINT_SGIS 0x81F5 +#define GL_EYE_LINE_SGIS 0x81F6 +#define GL_OBJECT_LINE_SGIS 0x81F7 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF +#endif + +#ifndef GL_EXT_texture_env_dot3 +#define GL_DOT3_RGB_EXT 0x8740 +#define GL_DOT3_RGBA_EXT 0x8741 +#endif + +#ifndef GL_ATI_texture_mirror_once +#define GL_MIRROR_CLAMP_ATI 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 +#endif + +#ifndef GL_NV_fence +#define GL_ALL_COMPLETED_NV 0x84F2 +#define GL_FENCE_STATUS_NV 0x84F3 +#define GL_FENCE_CONDITION_NV 0x84F4 +#endif + +#ifndef GL_IBM_texture_mirrored_repeat +#define GL_MIRRORED_REPEAT_IBM 0x8370 +#endif + +#ifndef GL_NV_evaluators +#define GL_EVAL_2D_NV 0x86C0 +#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 +#define GL_MAP_TESSELLATION_NV 0x86C2 +#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 +#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 +#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 +#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 +#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 +#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 +#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 +#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA +#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB +#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC +#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD +#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE +#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF +#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 +#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 +#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 +#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 +#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 +#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 +#define GL_MAX_MAP_TESSELLATION_NV 0x86D6 +#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 +#endif + +#ifndef GL_NV_packed_depth_stencil +#define GL_DEPTH_STENCIL_NV 0x84F9 +#define GL_UNSIGNED_INT_24_8_NV 0x84FA +#endif + +#ifndef GL_NV_register_combiners2 +#define GL_PER_STAGE_CONSTANTS_NV 0x8535 +#endif + +#ifndef GL_NV_texture_compression_vtc +#endif + +#ifndef GL_NV_texture_rectangle +#define GL_TEXTURE_RECTANGLE_NV 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 +#endif + +#ifndef GL_NV_texture_shader +#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C +#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D +#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E +#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 +#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA +#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB +#define GL_DSDT_MAG_INTENSITY_NV 0x86DC +#define GL_SHADER_CONSISTENT_NV 0x86DD +#define GL_TEXTURE_SHADER_NV 0x86DE +#define GL_SHADER_OPERATION_NV 0x86DF +#define GL_CULL_MODES_NV 0x86E0 +#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 +#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 +#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 +#define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV +#define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV +#define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV +#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 +#define GL_CONST_EYE_NV 0x86E5 +#define GL_PASS_THROUGH_NV 0x86E6 +#define GL_CULL_FRAGMENT_NV 0x86E7 +#define GL_OFFSET_TEXTURE_2D_NV 0x86E8 +#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 +#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA +#define GL_DOT_PRODUCT_NV 0x86EC +#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED +#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE +#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 +#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 +#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 +#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 +#define GL_HILO_NV 0x86F4 +#define GL_DSDT_NV 0x86F5 +#define GL_DSDT_MAG_NV 0x86F6 +#define GL_DSDT_MAG_VIB_NV 0x86F7 +#define GL_HILO16_NV 0x86F8 +#define GL_SIGNED_HILO_NV 0x86F9 +#define GL_SIGNED_HILO16_NV 0x86FA +#define GL_SIGNED_RGBA_NV 0x86FB +#define GL_SIGNED_RGBA8_NV 0x86FC +#define GL_SIGNED_RGB_NV 0x86FE +#define GL_SIGNED_RGB8_NV 0x86FF +#define GL_SIGNED_LUMINANCE_NV 0x8701 +#define GL_SIGNED_LUMINANCE8_NV 0x8702 +#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 +#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 +#define GL_SIGNED_ALPHA_NV 0x8705 +#define GL_SIGNED_ALPHA8_NV 0x8706 +#define GL_SIGNED_INTENSITY_NV 0x8707 +#define GL_SIGNED_INTENSITY8_NV 0x8708 +#define GL_DSDT8_NV 0x8709 +#define GL_DSDT8_MAG8_NV 0x870A +#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B +#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C +#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D +#define GL_HI_SCALE_NV 0x870E +#define GL_LO_SCALE_NV 0x870F +#define GL_DS_SCALE_NV 0x8710 +#define GL_DT_SCALE_NV 0x8711 +#define GL_MAGNITUDE_SCALE_NV 0x8712 +#define GL_VIBRANCE_SCALE_NV 0x8713 +#define GL_HI_BIAS_NV 0x8714 +#define GL_LO_BIAS_NV 0x8715 +#define GL_DS_BIAS_NV 0x8716 +#define GL_DT_BIAS_NV 0x8717 +#define GL_MAGNITUDE_BIAS_NV 0x8718 +#define GL_VIBRANCE_BIAS_NV 0x8719 +#define GL_TEXTURE_BORDER_VALUES_NV 0x871A +#define GL_TEXTURE_HI_SIZE_NV 0x871B +#define GL_TEXTURE_LO_SIZE_NV 0x871C +#define GL_TEXTURE_DS_SIZE_NV 0x871D +#define GL_TEXTURE_DT_SIZE_NV 0x871E +#define GL_TEXTURE_MAG_SIZE_NV 0x871F +#endif + +#ifndef GL_NV_texture_shader2 +#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 +#endif + +#ifndef GL_NV_vertex_program +#define GL_VERTEX_PROGRAM_NV 0x8620 +#define GL_VERTEX_STATE_PROGRAM_NV 0x8621 +#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 +#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 +#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 +#define GL_CURRENT_ATTRIB_NV 0x8626 +#define GL_PROGRAM_LENGTH_NV 0x8627 +#define GL_PROGRAM_STRING_NV 0x8628 +#define GL_MODELVIEW_PROJECTION_NV 0x8629 +#define GL_IDENTITY_NV 0x862A +#define GL_INVERSE_NV 0x862B +#define GL_TRANSPOSE_NV 0x862C +#define GL_INVERSE_TRANSPOSE_NV 0x862D +#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E +#define GL_MAX_TRACK_MATRICES_NV 0x862F +#define GL_MATRIX0_NV 0x8630 +#define GL_MATRIX1_NV 0x8631 +#define GL_MATRIX2_NV 0x8632 +#define GL_MATRIX3_NV 0x8633 +#define GL_MATRIX4_NV 0x8634 +#define GL_MATRIX5_NV 0x8635 +#define GL_MATRIX6_NV 0x8636 +#define GL_MATRIX7_NV 0x8637 +#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 +#define GL_CURRENT_MATRIX_NV 0x8641 +#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 +#define GL_PROGRAM_PARAMETER_NV 0x8644 +#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 +#define GL_PROGRAM_TARGET_NV 0x8646 +#define GL_PROGRAM_RESIDENT_NV 0x8647 +#define GL_TRACK_MATRIX_NV 0x8648 +#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 +#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A +#define GL_PROGRAM_ERROR_POSITION_NV 0x864B +#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 +#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 +#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 +#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 +#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 +#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 +#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 +#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 +#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 +#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 +#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A +#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B +#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C +#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D +#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E +#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F +#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 +#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 +#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 +#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 +#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 +#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 +#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 +#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 +#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 +#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 +#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A +#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B +#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C +#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D +#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E +#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F +#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 +#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 +#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 +#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 +#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 +#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 +#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 +#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 +#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 +#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 +#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A +#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B +#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C +#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D +#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E +#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F +#endif + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 +#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A +#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B +#endif + +#ifndef GL_SGIX_scalebias_hint +#define GL_SCALEBIAS_HINT_SGIX 0x8322 +#endif + +#ifndef GL_OML_interlace +#define GL_INTERLACE_OML 0x8980 +#define GL_INTERLACE_READ_OML 0x8981 +#endif + +#ifndef GL_OML_subsample +#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 +#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 +#endif + +#ifndef GL_OML_resample +#define GL_PACK_RESAMPLE_OML 0x8984 +#define GL_UNPACK_RESAMPLE_OML 0x8985 +#define GL_RESAMPLE_REPLICATE_OML 0x8986 +#define GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define GL_RESAMPLE_AVERAGE_OML 0x8988 +#define GL_RESAMPLE_DECIMATE_OML 0x8989 +#endif + +#ifndef GL_NV_copy_depth_to_color +#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E +#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F +#endif + +#ifndef GL_ATI_envmap_bumpmap +#define GL_BUMP_ROT_MATRIX_ATI 0x8775 +#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 +#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 +#define GL_BUMP_TEX_UNITS_ATI 0x8778 +#define GL_DUDV_ATI 0x8779 +#define GL_DU8DV8_ATI 0x877A +#define GL_BUMP_ENVMAP_ATI 0x877B +#define GL_BUMP_TARGET_ATI 0x877C +#endif + +#ifndef GL_ATI_fragment_shader +#define GL_FRAGMENT_SHADER_ATI 0x8920 +#define GL_REG_0_ATI 0x8921 +#define GL_REG_1_ATI 0x8922 +#define GL_REG_2_ATI 0x8923 +#define GL_REG_3_ATI 0x8924 +#define GL_REG_4_ATI 0x8925 +#define GL_REG_5_ATI 0x8926 +#define GL_REG_6_ATI 0x8927 +#define GL_REG_7_ATI 0x8928 +#define GL_REG_8_ATI 0x8929 +#define GL_REG_9_ATI 0x892A +#define GL_REG_10_ATI 0x892B +#define GL_REG_11_ATI 0x892C +#define GL_REG_12_ATI 0x892D +#define GL_REG_13_ATI 0x892E +#define GL_REG_14_ATI 0x892F +#define GL_REG_15_ATI 0x8930 +#define GL_REG_16_ATI 0x8931 +#define GL_REG_17_ATI 0x8932 +#define GL_REG_18_ATI 0x8933 +#define GL_REG_19_ATI 0x8934 +#define GL_REG_20_ATI 0x8935 +#define GL_REG_21_ATI 0x8936 +#define GL_REG_22_ATI 0x8937 +#define GL_REG_23_ATI 0x8938 +#define GL_REG_24_ATI 0x8939 +#define GL_REG_25_ATI 0x893A +#define GL_REG_26_ATI 0x893B +#define GL_REG_27_ATI 0x893C +#define GL_REG_28_ATI 0x893D +#define GL_REG_29_ATI 0x893E +#define GL_REG_30_ATI 0x893F +#define GL_REG_31_ATI 0x8940 +#define GL_CON_0_ATI 0x8941 +#define GL_CON_1_ATI 0x8942 +#define GL_CON_2_ATI 0x8943 +#define GL_CON_3_ATI 0x8944 +#define GL_CON_4_ATI 0x8945 +#define GL_CON_5_ATI 0x8946 +#define GL_CON_6_ATI 0x8947 +#define GL_CON_7_ATI 0x8948 +#define GL_CON_8_ATI 0x8949 +#define GL_CON_9_ATI 0x894A +#define GL_CON_10_ATI 0x894B +#define GL_CON_11_ATI 0x894C +#define GL_CON_12_ATI 0x894D +#define GL_CON_13_ATI 0x894E +#define GL_CON_14_ATI 0x894F +#define GL_CON_15_ATI 0x8950 +#define GL_CON_16_ATI 0x8951 +#define GL_CON_17_ATI 0x8952 +#define GL_CON_18_ATI 0x8953 +#define GL_CON_19_ATI 0x8954 +#define GL_CON_20_ATI 0x8955 +#define GL_CON_21_ATI 0x8956 +#define GL_CON_22_ATI 0x8957 +#define GL_CON_23_ATI 0x8958 +#define GL_CON_24_ATI 0x8959 +#define GL_CON_25_ATI 0x895A +#define GL_CON_26_ATI 0x895B +#define GL_CON_27_ATI 0x895C +#define GL_CON_28_ATI 0x895D +#define GL_CON_29_ATI 0x895E +#define GL_CON_30_ATI 0x895F +#define GL_CON_31_ATI 0x8960 +#define GL_MOV_ATI 0x8961 +#define GL_ADD_ATI 0x8963 +#define GL_MUL_ATI 0x8964 +#define GL_SUB_ATI 0x8965 +#define GL_DOT3_ATI 0x8966 +#define GL_DOT4_ATI 0x8967 +#define GL_MAD_ATI 0x8968 +#define GL_LERP_ATI 0x8969 +#define GL_CND_ATI 0x896A +#define GL_CND0_ATI 0x896B +#define GL_DOT2_ADD_ATI 0x896C +#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D +#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E +#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F +#define GL_NUM_PASSES_ATI 0x8970 +#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 +#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 +#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 +#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 +#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 +#define GL_SWIZZLE_STR_ATI 0x8976 +#define GL_SWIZZLE_STQ_ATI 0x8977 +#define GL_SWIZZLE_STR_DR_ATI 0x8978 +#define GL_SWIZZLE_STQ_DQ_ATI 0x8979 +#define GL_SWIZZLE_STRQ_ATI 0x897A +#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B +#define GL_RED_BIT_ATI 0x00000001 +#define GL_GREEN_BIT_ATI 0x00000002 +#define GL_BLUE_BIT_ATI 0x00000004 +#define GL_2X_BIT_ATI 0x00000001 +#define GL_4X_BIT_ATI 0x00000002 +#define GL_8X_BIT_ATI 0x00000004 +#define GL_HALF_BIT_ATI 0x00000008 +#define GL_QUARTER_BIT_ATI 0x00000010 +#define GL_EIGHTH_BIT_ATI 0x00000020 +#define GL_SATURATE_BIT_ATI 0x00000040 +#define GL_COMP_BIT_ATI 0x00000002 +#define GL_NEGATE_BIT_ATI 0x00000004 +#define GL_BIAS_BIT_ATI 0x00000008 +#endif + +#ifndef GL_ATI_pn_triangles +#define GL_PN_TRIANGLES_ATI 0x87F0 +#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 +#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 +#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 +#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 +#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 +#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 +#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 +#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 +#endif + +#ifndef GL_ATI_vertex_array_object +#define GL_STATIC_ATI 0x8760 +#define GL_DYNAMIC_ATI 0x8761 +#define GL_PRESERVE_ATI 0x8762 +#define GL_DISCARD_ATI 0x8763 +#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 +#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 +#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 +#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 +#endif + +#ifndef GL_EXT_vertex_shader +#define GL_VERTEX_SHADER_EXT 0x8780 +#define GL_VERTEX_SHADER_BINDING_EXT 0x8781 +#define GL_OP_INDEX_EXT 0x8782 +#define GL_OP_NEGATE_EXT 0x8783 +#define GL_OP_DOT3_EXT 0x8784 +#define GL_OP_DOT4_EXT 0x8785 +#define GL_OP_MUL_EXT 0x8786 +#define GL_OP_ADD_EXT 0x8787 +#define GL_OP_MADD_EXT 0x8788 +#define GL_OP_FRAC_EXT 0x8789 +#define GL_OP_MAX_EXT 0x878A +#define GL_OP_MIN_EXT 0x878B +#define GL_OP_SET_GE_EXT 0x878C +#define GL_OP_SET_LT_EXT 0x878D +#define GL_OP_CLAMP_EXT 0x878E +#define GL_OP_FLOOR_EXT 0x878F +#define GL_OP_ROUND_EXT 0x8790 +#define GL_OP_EXP_BASE_2_EXT 0x8791 +#define GL_OP_LOG_BASE_2_EXT 0x8792 +#define GL_OP_POWER_EXT 0x8793 +#define GL_OP_RECIP_EXT 0x8794 +#define GL_OP_RECIP_SQRT_EXT 0x8795 +#define GL_OP_SUB_EXT 0x8796 +#define GL_OP_CROSS_PRODUCT_EXT 0x8797 +#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 +#define GL_OP_MOV_EXT 0x8799 +#define GL_OUTPUT_VERTEX_EXT 0x879A +#define GL_OUTPUT_COLOR0_EXT 0x879B +#define GL_OUTPUT_COLOR1_EXT 0x879C +#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D +#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E +#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F +#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 +#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 +#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 +#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 +#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 +#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 +#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 +#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 +#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 +#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 +#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA +#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB +#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC +#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD +#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE +#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF +#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 +#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 +#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 +#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 +#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 +#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 +#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 +#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 +#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 +#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 +#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA +#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB +#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC +#define GL_OUTPUT_FOG_EXT 0x87BD +#define GL_SCALAR_EXT 0x87BE +#define GL_VECTOR_EXT 0x87BF +#define GL_MATRIX_EXT 0x87C0 +#define GL_VARIANT_EXT 0x87C1 +#define GL_INVARIANT_EXT 0x87C2 +#define GL_LOCAL_CONSTANT_EXT 0x87C3 +#define GL_LOCAL_EXT 0x87C4 +#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 +#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 +#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 +#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 +#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD +#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE +#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF +#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 +#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 +#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 +#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 +#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 +#define GL_X_EXT 0x87D5 +#define GL_Y_EXT 0x87D6 +#define GL_Z_EXT 0x87D7 +#define GL_W_EXT 0x87D8 +#define GL_NEGATIVE_X_EXT 0x87D9 +#define GL_NEGATIVE_Y_EXT 0x87DA +#define GL_NEGATIVE_Z_EXT 0x87DB +#define GL_NEGATIVE_W_EXT 0x87DC +#define GL_ZERO_EXT 0x87DD +#define GL_ONE_EXT 0x87DE +#define GL_NEGATIVE_ONE_EXT 0x87DF +#define GL_NORMALIZED_RANGE_EXT 0x87E0 +#define GL_FULL_RANGE_EXT 0x87E1 +#define GL_CURRENT_VERTEX_EXT 0x87E2 +#define GL_MVP_MATRIX_EXT 0x87E3 +#define GL_VARIANT_VALUE_EXT 0x87E4 +#define GL_VARIANT_DATATYPE_EXT 0x87E5 +#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 +#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 +#define GL_VARIANT_ARRAY_EXT 0x87E8 +#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 +#define GL_INVARIANT_VALUE_EXT 0x87EA +#define GL_INVARIANT_DATATYPE_EXT 0x87EB +#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC +#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED +#endif + +#ifndef GL_ATI_vertex_streams +#define GL_MAX_VERTEX_STREAMS_ATI 0x876B +#define GL_VERTEX_STREAM0_ATI 0x876C +#define GL_VERTEX_STREAM1_ATI 0x876D +#define GL_VERTEX_STREAM2_ATI 0x876E +#define GL_VERTEX_STREAM3_ATI 0x876F +#define GL_VERTEX_STREAM4_ATI 0x8770 +#define GL_VERTEX_STREAM5_ATI 0x8771 +#define GL_VERTEX_STREAM6_ATI 0x8772 +#define GL_VERTEX_STREAM7_ATI 0x8773 +#define GL_VERTEX_SOURCE_ATI 0x8774 +#endif + +#ifndef GL_ATI_element_array +#define GL_ELEMENT_ARRAY_ATI 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A +#endif + +#ifndef GL_SUN_mesh_array +#define GL_QUAD_MESH_SUN 0x8614 +#define GL_TRIANGLE_MESH_SUN 0x8615 +#endif + +#ifndef GL_SUN_slice_accum +#define GL_SLICE_ACCUM_SUN 0x85CC +#endif + +#ifndef GL_NV_multisample_filter_hint +#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 +#endif + +#ifndef GL_NV_depth_clamp +#define GL_DEPTH_CLAMP_NV 0x864F +#endif + +#ifndef GL_NV_occlusion_query +#define GL_PIXEL_COUNTER_BITS_NV 0x8864 +#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 +#define GL_PIXEL_COUNT_NV 0x8866 +#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 +#endif + +#ifndef GL_NV_point_sprite +#define GL_POINT_SPRITE_NV 0x8861 +#define GL_COORD_REPLACE_NV 0x8862 +#define GL_POINT_SPRITE_R_MODE_NV 0x8863 +#endif + +#ifndef GL_NV_texture_shader3 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 +#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 +#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 +#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 +#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 +#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 +#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 +#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 +#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A +#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B +#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C +#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D +#define GL_HILO8_NV 0x885E +#define GL_SIGNED_HILO8_NV 0x885F +#define GL_FORCE_BLUE_TO_ONE_NV 0x8860 +#endif + +#ifndef GL_NV_vertex_program1_1 +#endif + +#ifndef GL_EXT_shadow_funcs +#endif + +#ifndef GL_EXT_stencil_two_side +#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 +#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 +#endif + +#ifndef GL_ATI_text_fragment_shader +#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 +#endif + +#ifndef GL_APPLE_client_storage +#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 +#endif + +#ifndef GL_APPLE_element_array +#define GL_ELEMENT_ARRAY_APPLE 0x8768 +#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769 +#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A +#endif + +#ifndef GL_APPLE_fence +#define GL_DRAW_PIXELS_APPLE 0x8A0A +#define GL_FENCE_APPLE 0x8A0B +#endif + +#ifndef GL_APPLE_vertex_array_object +#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 +#endif + +#ifndef GL_APPLE_vertex_array_range +#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D +#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E +#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F +#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 +#define GL_STORAGE_CACHED_APPLE 0x85BE +#define GL_STORAGE_SHARED_APPLE 0x85BF +#endif + +#ifndef GL_APPLE_ycbcr_422 +#define GL_YCBCR_422_APPLE 0x85B9 +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#endif + +#ifndef GL_S3_s3tc +#define GL_RGB_S3TC 0x83A0 +#define GL_RGB4_S3TC 0x83A1 +#define GL_RGBA_S3TC 0x83A2 +#define GL_RGBA4_S3TC 0x83A3 +#endif + +#ifndef GL_ATI_draw_buffers +#define GL_MAX_DRAW_BUFFERS_ATI 0x8824 +#define GL_DRAW_BUFFER0_ATI 0x8825 +#define GL_DRAW_BUFFER1_ATI 0x8826 +#define GL_DRAW_BUFFER2_ATI 0x8827 +#define GL_DRAW_BUFFER3_ATI 0x8828 +#define GL_DRAW_BUFFER4_ATI 0x8829 +#define GL_DRAW_BUFFER5_ATI 0x882A +#define GL_DRAW_BUFFER6_ATI 0x882B +#define GL_DRAW_BUFFER7_ATI 0x882C +#define GL_DRAW_BUFFER8_ATI 0x882D +#define GL_DRAW_BUFFER9_ATI 0x882E +#define GL_DRAW_BUFFER10_ATI 0x882F +#define GL_DRAW_BUFFER11_ATI 0x8830 +#define GL_DRAW_BUFFER12_ATI 0x8831 +#define GL_DRAW_BUFFER13_ATI 0x8832 +#define GL_DRAW_BUFFER14_ATI 0x8833 +#define GL_DRAW_BUFFER15_ATI 0x8834 +#endif + +#ifndef GL_ATI_pixel_format_float +#define GL_TYPE_RGBA_FLOAT_ATI 0x8820 +#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835 +#endif + +#ifndef GL_ATI_texture_env_combine3 +#define GL_MODULATE_ADD_ATI 0x8744 +#define GL_MODULATE_SIGNED_ADD_ATI 0x8745 +#define GL_MODULATE_SUBTRACT_ATI 0x8746 +#endif + +#ifndef GL_ATI_texture_float +#define GL_RGBA_FLOAT32_ATI 0x8814 +#define GL_RGB_FLOAT32_ATI 0x8815 +#define GL_ALPHA_FLOAT32_ATI 0x8816 +#define GL_INTENSITY_FLOAT32_ATI 0x8817 +#define GL_LUMINANCE_FLOAT32_ATI 0x8818 +#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 +#define GL_RGBA_FLOAT16_ATI 0x881A +#define GL_RGB_FLOAT16_ATI 0x881B +#define GL_ALPHA_FLOAT16_ATI 0x881C +#define GL_INTENSITY_FLOAT16_ATI 0x881D +#define GL_LUMINANCE_FLOAT16_ATI 0x881E +#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F +#endif + +#ifndef GL_NV_float_buffer +#define GL_FLOAT_R_NV 0x8880 +#define GL_FLOAT_RG_NV 0x8881 +#define GL_FLOAT_RGB_NV 0x8882 +#define GL_FLOAT_RGBA_NV 0x8883 +#define GL_FLOAT_R16_NV 0x8884 +#define GL_FLOAT_R32_NV 0x8885 +#define GL_FLOAT_RG16_NV 0x8886 +#define GL_FLOAT_RG32_NV 0x8887 +#define GL_FLOAT_RGB16_NV 0x8888 +#define GL_FLOAT_RGB32_NV 0x8889 +#define GL_FLOAT_RGBA16_NV 0x888A +#define GL_FLOAT_RGBA32_NV 0x888B +#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C +#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D +#define GL_FLOAT_RGBA_MODE_NV 0x888E +#endif + +#ifndef GL_NV_fragment_program +#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 +#define GL_FRAGMENT_PROGRAM_NV 0x8870 +#define GL_MAX_TEXTURE_COORDS_NV 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 +#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 +#define GL_PROGRAM_ERROR_STRING_NV 0x8874 +#endif + +#ifndef GL_NV_half_float +#define GL_HALF_FLOAT_NV 0x140B +#endif + +#ifndef GL_NV_pixel_data_range +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 +#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A +#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B +#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C +#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D +#endif + +#ifndef GL_NV_primitive_restart +#define GL_PRIMITIVE_RESTART_NV 0x8558 +#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 +#endif + +#ifndef GL_NV_texture_expand_normal +#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F +#endif + +#ifndef GL_NV_vertex_program2 +#endif + +#ifndef GL_ATI_map_object_buffer +#endif + +#ifndef GL_ATI_separate_stencil +#define GL_STENCIL_BACK_FUNC_ATI 0x8800 +#define GL_STENCIL_BACK_FAIL_ATI 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 +#endif + +#ifndef GL_ATI_vertex_attrib_array_object +#endif + +#ifndef GL_OES_read_format +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B +#endif + +#ifndef GL_EXT_depth_bounds_test +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#define GL_DEPTH_BOUNDS_EXT 0x8891 +#endif + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_MIRROR_CLAMP_EXT 0x8742 +#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 +#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 +#endif + +#ifndef GL_EXT_blend_equation_separate +#define GL_BLEND_EQUATION_RGB_EXT GL_BLEND_EQUATION +#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D +#endif + +#ifndef GL_MESA_pack_invert +#define GL_PACK_INVERT_MESA 0x8758 +#endif + +#ifndef GL_MESA_ycbcr_texture +#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB +#define GL_YCBCR_MESA 0x8757 +#endif + +#ifndef GL_EXT_pixel_buffer_object +#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB +#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF +#endif + +#ifndef GL_NV_fragment_program_option +#endif + +#ifndef GL_NV_fragment_program2 +#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 +#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 +#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 +#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 +#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 +#endif + +#ifndef GL_NV_vertex_program2_option +/* reuse GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV */ +/* reuse GL_MAX_PROGRAM_CALL_DEPTH_NV */ +#endif + +#ifndef GL_NV_vertex_program3 +/* reuse GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB */ +#endif + + +/*************************************************************/ + +#include +#ifndef GL_VERSION_2_0 +/* GL type for program/shader text */ +typedef char GLchar; /* native character */ +#endif + +#ifndef GL_VERSION_1_5 +/* GL types for handling large vertex buffer objects */ +typedef ptrdiff_t GLintptr; +typedef ptrdiff_t GLsizeiptr; +#endif + +#ifndef GL_ARB_vertex_buffer_object +/* GL types for handling large vertex buffer objects */ +typedef ptrdiff_t GLintptrARB; +typedef ptrdiff_t GLsizeiptrARB; +#endif + +#ifndef GL_ARB_shader_objects +/* GL types for handling shader object handles and program/shader text */ +typedef char GLcharARB; /* native character */ +typedef unsigned int GLhandleARB; /* shader object handle */ +#endif + +/* GL types for "half" precision (s10e5) float data in host memory */ +#ifndef GL_ARB_half_float_pixel +typedef unsigned short GLhalfARB; +#endif + +#ifndef GL_NV_half_float +typedef unsigned short GLhalfNV; +#endif + +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendColor (GLclampf, GLclampf, GLclampf, GLclampf); +GLAPI void APIENTRY glBlendEquation (GLenum); +GLAPI void APIENTRY glDrawRangeElements (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +GLAPI void APIENTRY glColorTable (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glColorTableParameterfv (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glColorTableParameteriv (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glCopyColorTable (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void APIENTRY glGetColorTable (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetColorTableParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetColorTableParameteriv (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glColorSubTable (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glCopyColorSubTable (GLenum, GLsizei, GLint, GLint, GLsizei); +GLAPI void APIENTRY glConvolutionFilter1D (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glConvolutionFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glConvolutionParameterf (GLenum, GLenum, GLfloat); +GLAPI void APIENTRY glConvolutionParameterfv (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glConvolutionParameteri (GLenum, GLenum, GLint); +GLAPI void APIENTRY glConvolutionParameteriv (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +GLAPI void APIENTRY glGetConvolutionFilter (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetSeparableFilter (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +GLAPI void APIENTRY glSeparableFilter2D (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +GLAPI void APIENTRY glGetHistogram (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetHistogramParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetHistogramParameteriv (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetMinmax (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glHistogram (GLenum, GLsizei, GLenum, GLboolean); +GLAPI void APIENTRY glMinmax (GLenum, GLenum, GLboolean); +GLAPI void APIENTRY glResetHistogram (GLenum); +GLAPI void APIENTRY glResetMinmax (GLenum); +GLAPI void APIENTRY glTexImage3D (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glCopyTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target); +typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target); +typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glActiveTexture (GLenum); +GLAPI void APIENTRY glClientActiveTexture (GLenum); +GLAPI void APIENTRY glMultiTexCoord1d (GLenum, GLdouble); +GLAPI void APIENTRY glMultiTexCoord1dv (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord1f (GLenum, GLfloat); +GLAPI void APIENTRY glMultiTexCoord1fv (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord1i (GLenum, GLint); +GLAPI void APIENTRY glMultiTexCoord1iv (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord1s (GLenum, GLshort); +GLAPI void APIENTRY glMultiTexCoord1sv (GLenum, const GLshort *); +GLAPI void APIENTRY glMultiTexCoord2d (GLenum, GLdouble, GLdouble); +GLAPI void APIENTRY glMultiTexCoord2dv (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord2f (GLenum, GLfloat, GLfloat); +GLAPI void APIENTRY glMultiTexCoord2fv (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord2i (GLenum, GLint, GLint); +GLAPI void APIENTRY glMultiTexCoord2iv (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord2s (GLenum, GLshort, GLshort); +GLAPI void APIENTRY glMultiTexCoord2sv (GLenum, const GLshort *); +GLAPI void APIENTRY glMultiTexCoord3d (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glMultiTexCoord3dv (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord3f (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glMultiTexCoord3fv (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord3i (GLenum, GLint, GLint, GLint); +GLAPI void APIENTRY glMultiTexCoord3iv (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord3s (GLenum, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glMultiTexCoord3sv (GLenum, const GLshort *); +GLAPI void APIENTRY glMultiTexCoord4d (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glMultiTexCoord4dv (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord4f (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glMultiTexCoord4fv (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord4i (GLenum, GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glMultiTexCoord4iv (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord4s (GLenum, GLshort, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glMultiTexCoord4sv (GLenum, const GLshort *); +GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *); +GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *); +GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *); +GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *); +GLAPI void APIENTRY glSampleCoverage (GLclampf, GLboolean); +GLAPI void APIENTRY glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glGetCompressedTexImage (GLenum, GLint, GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m); +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img); +#endif + +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncSeparate (GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glFogCoordf (GLfloat); +GLAPI void APIENTRY glFogCoordfv (const GLfloat *); +GLAPI void APIENTRY glFogCoordd (GLdouble); +GLAPI void APIENTRY glFogCoorddv (const GLdouble *); +GLAPI void APIENTRY glFogCoordPointer (GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glMultiDrawArrays (GLenum, GLint *, GLsizei *, GLsizei); +GLAPI void APIENTRY glMultiDrawElements (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); +GLAPI void APIENTRY glPointParameterf (GLenum, GLfloat); +GLAPI void APIENTRY glPointParameterfv (GLenum, const GLfloat *); +GLAPI void APIENTRY glPointParameteri (GLenum, GLint); +GLAPI void APIENTRY glPointParameteriv (GLenum, const GLint *); +GLAPI void APIENTRY glSecondaryColor3b (GLbyte, GLbyte, GLbyte); +GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *); +GLAPI void APIENTRY glSecondaryColor3d (GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *); +GLAPI void APIENTRY glSecondaryColor3f (GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *); +GLAPI void APIENTRY glSecondaryColor3i (GLint, GLint, GLint); +GLAPI void APIENTRY glSecondaryColor3iv (const GLint *); +GLAPI void APIENTRY glSecondaryColor3s (GLshort, GLshort, GLshort); +GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *); +GLAPI void APIENTRY glSecondaryColor3ub (GLubyte, GLubyte, GLubyte); +GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *); +GLAPI void APIENTRY glSecondaryColor3ui (GLuint, GLuint, GLuint); +GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *); +GLAPI void APIENTRY glSecondaryColor3us (GLushort, GLushort, GLushort); +GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *); +GLAPI void APIENTRY glSecondaryColorPointer (GLint, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glWindowPos2d (GLdouble, GLdouble); +GLAPI void APIENTRY glWindowPos2dv (const GLdouble *); +GLAPI void APIENTRY glWindowPos2f (GLfloat, GLfloat); +GLAPI void APIENTRY glWindowPos2fv (const GLfloat *); +GLAPI void APIENTRY glWindowPos2i (GLint, GLint); +GLAPI void APIENTRY glWindowPos2iv (const GLint *); +GLAPI void APIENTRY glWindowPos2s (GLshort, GLshort); +GLAPI void APIENTRY glWindowPos2sv (const GLshort *); +GLAPI void APIENTRY glWindowPos3d (GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glWindowPos3dv (const GLdouble *); +GLAPI void APIENTRY glWindowPos3f (GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glWindowPos3fv (const GLfloat *); +GLAPI void APIENTRY glWindowPos3i (GLint, GLint, GLint); +GLAPI void APIENTRY glWindowPos3iv (const GLint *); +GLAPI void APIENTRY glWindowPos3s (GLshort, GLshort, GLshort); +GLAPI void APIENTRY glWindowPos3sv (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord); +typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord); +typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord); +typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord); +typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y); +typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v); +#endif + +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenQueries (GLsizei, GLuint *); +GLAPI void APIENTRY glDeleteQueries (GLsizei, const GLuint *); +GLAPI GLboolean APIENTRY glIsQuery (GLuint); +GLAPI void APIENTRY glBeginQuery (GLenum, GLuint); +GLAPI void APIENTRY glEndQuery (GLenum); +GLAPI void APIENTRY glGetQueryiv (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetQueryObjectiv (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetQueryObjectuiv (GLuint, GLenum, GLuint *); +GLAPI void APIENTRY glBindBuffer (GLenum, GLuint); +GLAPI void APIENTRY glDeleteBuffers (GLsizei, const GLuint *); +GLAPI void APIENTRY glGenBuffers (GLsizei, GLuint *); +GLAPI GLboolean APIENTRY glIsBuffer (GLuint); +GLAPI void APIENTRY glBufferData (GLenum, GLsizeiptr, const GLvoid *, GLenum); +GLAPI void APIENTRY glBufferSubData (GLenum, GLintptr, GLsizeiptr, const GLvoid *); +GLAPI void APIENTRY glGetBufferSubData (GLenum, GLintptr, GLsizeiptr, GLvoid *); +GLAPI GLvoid* APIENTRY glMapBuffer (GLenum, GLenum); +GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum); +GLAPI void APIENTRY glGetBufferParameteriv (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetBufferPointerv (GLenum, GLenum, GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); +typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); +typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); +typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); +typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); +typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, GLvoid* *params); +#endif + +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationSeparate (GLenum, GLenum); +GLAPI void APIENTRY glDrawBuffers (GLsizei, const GLenum *); +GLAPI void APIENTRY glStencilOpSeparate (GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glStencilFuncSeparate (GLenum, GLenum, GLint, GLuint); +GLAPI void APIENTRY glStencilMaskSeparate (GLenum, GLuint); +GLAPI void APIENTRY glAttachShader (GLuint, GLuint); +GLAPI void APIENTRY glBindAttribLocation (GLuint, GLuint, const GLchar *); +GLAPI void APIENTRY glCompileShader (GLuint); +GLAPI GLuint APIENTRY glCreateProgram (void); +GLAPI GLuint APIENTRY glCreateShader (GLenum); +GLAPI void APIENTRY glDeleteProgram (GLuint); +GLAPI void APIENTRY glDeleteShader (GLuint); +GLAPI void APIENTRY glDetachShader (GLuint, GLuint); +GLAPI void APIENTRY glDisableVertexAttribArray (GLuint); +GLAPI void APIENTRY glEnableVertexAttribArray (GLuint); +GLAPI void APIENTRY glGetActiveAttrib (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +GLAPI void APIENTRY glGetActiveUniform (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); +GLAPI void APIENTRY glGetAttachedShaders (GLuint, GLsizei, GLsizei *, GLuint *); +GLAPI GLint APIENTRY glGetAttribLocation (GLuint, const GLchar *); +GLAPI void APIENTRY glGetProgramiv (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetProgramInfoLog (GLuint, GLsizei, GLsizei *, GLchar *); +GLAPI void APIENTRY glGetShaderiv (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetShaderInfoLog (GLuint, GLsizei, GLsizei *, GLchar *); +GLAPI void APIENTRY glGetShaderSource (GLuint, GLsizei, GLsizei *, GLchar *); +GLAPI GLint APIENTRY glGetUniformLocation (GLuint, const GLchar *); +GLAPI void APIENTRY glGetUniformfv (GLuint, GLint, GLfloat *); +GLAPI void APIENTRY glGetUniformiv (GLuint, GLint, GLint *); +GLAPI void APIENTRY glGetVertexAttribdv (GLuint, GLenum, GLdouble *); +GLAPI void APIENTRY glGetVertexAttribfv (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetVertexAttribiv (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint, GLenum, GLvoid* *); +GLAPI GLboolean APIENTRY glIsProgram (GLuint); +GLAPI GLboolean APIENTRY glIsShader (GLuint); +GLAPI void APIENTRY glLinkProgram (GLuint); +GLAPI void APIENTRY glShaderSource (GLuint, GLsizei, const GLchar* *, const GLint *); +GLAPI void APIENTRY glUseProgram (GLuint); +GLAPI void APIENTRY glUniform1f (GLint, GLfloat); +GLAPI void APIENTRY glUniform2f (GLint, GLfloat, GLfloat); +GLAPI void APIENTRY glUniform3f (GLint, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glUniform4f (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glUniform1i (GLint, GLint); +GLAPI void APIENTRY glUniform2i (GLint, GLint, GLint); +GLAPI void APIENTRY glUniform3i (GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glUniform4i (GLint, GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glUniform1fv (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform2fv (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform3fv (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform4fv (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform1iv (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniform2iv (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniform3iv (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniform4iv (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniformMatrix2fv (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void APIENTRY glUniformMatrix3fv (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void APIENTRY glUniformMatrix4fv (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void APIENTRY glValidateProgram (GLuint); +GLAPI void APIENTRY glVertexAttrib1d (GLuint, GLdouble); +GLAPI void APIENTRY glVertexAttrib1dv (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib1f (GLuint, GLfloat); +GLAPI void APIENTRY glVertexAttrib1fv (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib1s (GLuint, GLshort); +GLAPI void APIENTRY glVertexAttrib1sv (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib2d (GLuint, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib2dv (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib2f (GLuint, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib2fv (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib2s (GLuint, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib2sv (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib3d (GLuint, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib3dv (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib3f (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib3fv (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib3s (GLuint, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib3sv (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint, const GLbyte *); +GLAPI void APIENTRY glVertexAttrib4Niv (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4Nub (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); +GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint, const GLubyte *); +GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint, const GLushort *); +GLAPI void APIENTRY glVertexAttrib4bv (GLuint, const GLbyte *); +GLAPI void APIENTRY glVertexAttrib4d (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib4dv (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib4f (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib4fv (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib4iv (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttrib4s (GLuint, GLshort, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib4sv (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4ubv (GLuint, const GLubyte *); +GLAPI void APIENTRY glVertexAttrib4uiv (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttrib4usv (GLuint, const GLushort *); +GLAPI void APIENTRY glVertexAttribPointer (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); +typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); +typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); +typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj); +typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); +typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader); +typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); +typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_ARB_multitexture +#define GL_ARB_multitexture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glActiveTextureARB (GLenum); +GLAPI void APIENTRY glClientActiveTextureARB (GLenum); +GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum, GLdouble); +GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum, GLfloat); +GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum, GLint); +GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum, GLshort); +GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum, const GLshort *); +GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum, GLdouble, GLdouble); +GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum, GLfloat, GLfloat); +GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum, GLint, GLint); +GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum, GLshort, GLshort); +GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum, const GLshort *); +GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum, GLint, GLint, GLint); +GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum, const GLshort *); +GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum, const GLdouble *); +GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum, const GLfloat *); +GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum, GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum, const GLint *); +GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum, GLshort, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum, const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v); +#endif + +#ifndef GL_ARB_transpose_matrix +#define GL_ARB_transpose_matrix 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *); +GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *); +GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *); +GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m); +typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m); +#endif + +#ifndef GL_ARB_multisample +#define GL_ARB_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSampleCoverageARB (GLclampf, GLboolean); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLclampf value, GLboolean invert); +#endif + +#ifndef GL_ARB_texture_env_add +#define GL_ARB_texture_env_add 1 +#endif + +#ifndef GL_ARB_texture_cube_map +#define GL_ARB_texture_cube_map 1 +#endif + +#ifndef GL_ARB_texture_compression +#define GL_ARB_texture_compression 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum, GLint, GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, GLvoid *img); +#endif + +#ifndef GL_ARB_texture_border_clamp +#define GL_ARB_texture_border_clamp 1 +#endif + +#ifndef GL_ARB_point_parameters +#define GL_ARB_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameterfARB (GLenum, GLfloat); +GLAPI void APIENTRY glPointParameterfvARB (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_ARB_vertex_blend +#define GL_ARB_vertex_blend 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWeightbvARB (GLint, const GLbyte *); +GLAPI void APIENTRY glWeightsvARB (GLint, const GLshort *); +GLAPI void APIENTRY glWeightivARB (GLint, const GLint *); +GLAPI void APIENTRY glWeightfvARB (GLint, const GLfloat *); +GLAPI void APIENTRY glWeightdvARB (GLint, const GLdouble *); +GLAPI void APIENTRY glWeightubvARB (GLint, const GLubyte *); +GLAPI void APIENTRY glWeightusvARB (GLint, const GLushort *); +GLAPI void APIENTRY glWeightuivARB (GLint, const GLuint *); +GLAPI void APIENTRY glWeightPointerARB (GLint, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glVertexBlendARB (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights); +typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights); +typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights); +typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights); +typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights); +typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights); +typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights); +typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights); +typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count); +#endif + +#ifndef GL_ARB_matrix_palette +#define GL_ARB_matrix_palette 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint); +GLAPI void APIENTRY glMatrixIndexubvARB (GLint, const GLubyte *); +GLAPI void APIENTRY glMatrixIndexusvARB (GLint, const GLushort *); +GLAPI void APIENTRY glMatrixIndexuivARB (GLint, const GLuint *); +GLAPI void APIENTRY glMatrixIndexPointerARB (GLint, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index); +typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices); +typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices); +typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices); +typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_ARB_texture_env_combine +#define GL_ARB_texture_env_combine 1 +#endif + +#ifndef GL_ARB_texture_env_crossbar +#define GL_ARB_texture_env_crossbar 1 +#endif + +#ifndef GL_ARB_texture_env_dot3 +#define GL_ARB_texture_env_dot3 1 +#endif + +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 +#endif + +#ifndef GL_ARB_depth_texture +#define GL_ARB_depth_texture 1 +#endif + +#ifndef GL_ARB_shadow +#define GL_ARB_shadow 1 +#endif + +#ifndef GL_ARB_shadow_ambient +#define GL_ARB_shadow_ambient 1 +#endif + +#ifndef GL_ARB_window_pos +#define GL_ARB_window_pos 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWindowPos2dARB (GLdouble, GLdouble); +GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *); +GLAPI void APIENTRY glWindowPos2fARB (GLfloat, GLfloat); +GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *); +GLAPI void APIENTRY glWindowPos2iARB (GLint, GLint); +GLAPI void APIENTRY glWindowPos2ivARB (const GLint *); +GLAPI void APIENTRY glWindowPos2sARB (GLshort, GLshort); +GLAPI void APIENTRY glWindowPos2svARB (const GLshort *); +GLAPI void APIENTRY glWindowPos3dARB (GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *); +GLAPI void APIENTRY glWindowPos3fARB (GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *); +GLAPI void APIENTRY glWindowPos3iARB (GLint, GLint, GLint); +GLAPI void APIENTRY glWindowPos3ivARB (const GLint *); +GLAPI void APIENTRY glWindowPos3sARB (GLshort, GLshort, GLshort); +GLAPI void APIENTRY glWindowPos3svARB (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y); +typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v); +#endif + +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttrib1dARB (GLuint, GLdouble); +GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib1fARB (GLuint, GLfloat); +GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib1sARB (GLuint, GLshort); +GLAPI void APIENTRY glVertexAttrib1svARB (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib2dARB (GLuint, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib2fARB (GLuint, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib2sARB (GLuint, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib2svARB (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib3dARB (GLuint, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib3fARB (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib3sARB (GLuint, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib3svARB (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint, const GLbyte *); +GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); +GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint, const GLubyte *); +GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint, const GLushort *); +GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint, const GLbyte *); +GLAPI void APIENTRY glVertexAttrib4dARB (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib4fARB (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint, const GLint *); +GLAPI void APIENTRY glVertexAttrib4sARB (GLuint, GLshort, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib4svARB (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint, const GLubyte *); +GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint, const GLuint *); +GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint, const GLushort *); +GLAPI void APIENTRY glVertexAttribPointerARB (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *); +GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint); +GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint); +GLAPI void APIENTRY glProgramStringARB (GLenum, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glBindProgramARB (GLenum, GLuint); +GLAPI void APIENTRY glDeleteProgramsARB (GLsizei, const GLuint *); +GLAPI void APIENTRY glGenProgramsARB (GLsizei, GLuint *); +GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum, GLuint, const GLdouble *); +GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum, GLuint, const GLfloat *); +GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum, GLuint, const GLdouble *); +GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum, GLuint, const GLfloat *); +GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum, GLuint, GLdouble *); +GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum, GLuint, GLfloat *); +GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum, GLuint, GLdouble *); +GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum, GLuint, GLfloat *); +GLAPI void APIENTRY glGetProgramivARB (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetProgramStringARB (GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint, GLenum, GLdouble *); +GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetVertexAttribivARB (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint, GLenum, GLvoid* *); +GLAPI GLboolean APIENTRY glIsProgramARB (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); +typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program); +#endif + +#ifndef GL_ARB_fragment_program +#define GL_ARB_fragment_program 1 +/* All ARB_fragment_program entry points are shared with ARB_vertex_program. */ +#endif + +#ifndef GL_ARB_vertex_buffer_object +#define GL_ARB_vertex_buffer_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindBufferARB (GLenum, GLuint); +GLAPI void APIENTRY glDeleteBuffersARB (GLsizei, const GLuint *); +GLAPI void APIENTRY glGenBuffersARB (GLsizei, GLuint *); +GLAPI GLboolean APIENTRY glIsBufferARB (GLuint); +GLAPI void APIENTRY glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum); +GLAPI void APIENTRY glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *); +GLAPI void APIENTRY glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *); +GLAPI GLvoid* APIENTRY glMapBufferARB (GLenum, GLenum); +GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum); +GLAPI void APIENTRY glGetBufferParameterivARB (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); +typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers); +typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers); +typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); +typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); +typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data); +typedef GLvoid* (APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access); +typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params); +#endif + +#ifndef GL_ARB_occlusion_query +#define GL_ARB_occlusion_query 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenQueriesARB (GLsizei, GLuint *); +GLAPI void APIENTRY glDeleteQueriesARB (GLsizei, const GLuint *); +GLAPI GLboolean APIENTRY glIsQueryARB (GLuint); +GLAPI void APIENTRY glBeginQueryARB (GLenum, GLuint); +GLAPI void APIENTRY glEndQueryARB (GLenum); +GLAPI void APIENTRY glGetQueryivARB (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetQueryObjectivARB (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint, GLenum, GLuint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params); +#endif + +#ifndef GL_ARB_shader_objects +#define GL_ARB_shader_objects 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB); +GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum); +GLAPI void APIENTRY glDetachObjectARB (GLhandleARB, GLhandleARB); +GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum); +GLAPI void APIENTRY glShaderSourceARB (GLhandleARB, GLsizei, const GLcharARB* *, const GLint *); +GLAPI void APIENTRY glCompileShaderARB (GLhandleARB); +GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void); +GLAPI void APIENTRY glAttachObjectARB (GLhandleARB, GLhandleARB); +GLAPI void APIENTRY glLinkProgramARB (GLhandleARB); +GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB); +GLAPI void APIENTRY glValidateProgramARB (GLhandleARB); +GLAPI void APIENTRY glUniform1fARB (GLint, GLfloat); +GLAPI void APIENTRY glUniform2fARB (GLint, GLfloat, GLfloat); +GLAPI void APIENTRY glUniform3fARB (GLint, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glUniform4fARB (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glUniform1iARB (GLint, GLint); +GLAPI void APIENTRY glUniform2iARB (GLint, GLint, GLint); +GLAPI void APIENTRY glUniform3iARB (GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glUniform4iARB (GLint, GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glUniform1fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform2fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform3fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform4fvARB (GLint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glUniform1ivARB (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniform2ivARB (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniform3ivARB (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniform4ivARB (GLint, GLsizei, const GLint *); +GLAPI void APIENTRY glUniformMatrix2fvARB (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void APIENTRY glUniformMatrix3fvARB (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void APIENTRY glUniformMatrix4fvARB (GLint, GLsizei, GLboolean, const GLfloat *); +GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB, GLenum, GLfloat *); +GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB, GLenum, GLint *); +GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); +GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *); +GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB, const GLcharARB *); +GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); +GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB, GLint, GLfloat *); +GLAPI void APIENTRY glGetUniformivARB (GLhandleARB, GLint, GLint *); +GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB, GLsizei, GLsizei *, GLcharARB *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname); +typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj); +typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); +typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0); +typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0); +typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1); +typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); +typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); +typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params); +typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params); +typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); +#endif + +#ifndef GL_ARB_vertex_shader +#define GL_ARB_vertex_shader 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB, GLuint, const GLcharARB *); +GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *); +GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB, const GLcharARB *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name); +typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); +typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name); +#endif + +#ifndef GL_ARB_fragment_shader +#define GL_ARB_fragment_shader 1 +#endif + +#ifndef GL_ARB_shading_language_100 +#define GL_ARB_shading_language_100 1 +#endif + +#ifndef GL_ARB_texture_non_power_of_two +#define GL_ARB_texture_non_power_of_two 1 +#endif + +#ifndef GL_ARB_point_sprite +#define GL_ARB_point_sprite 1 +#endif + +#ifndef GL_ARB_fragment_program_shadow +#define GL_ARB_fragment_program_shadow 1 +#endif + +#ifndef GL_ARB_draw_buffers +#define GL_ARB_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawBuffersARB (GLsizei, const GLenum *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs); +#endif + +#ifndef GL_ARB_texture_rectangle +#define GL_ARB_texture_rectangle 1 +#endif + +#ifndef GL_ARB_color_buffer_float +#define GL_ARB_color_buffer_float 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glClampColorARB (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp); +#endif + +#ifndef GL_ARB_half_float_pixel +#define GL_ARB_half_float_pixel 1 +#endif + +#ifndef GL_ARB_texture_float +#define GL_ARB_texture_float 1 +#endif + +#ifndef GL_ARB_pixel_buffer_object +#define GL_ARB_pixel_buffer_object 1 +#endif + +#ifndef GL_EXT_abgr +#define GL_EXT_abgr 1 +#endif + +#ifndef GL_EXT_blend_color +#define GL_EXT_blend_color 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendColorEXT (GLclampf, GLclampf, GLclampf, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +#endif + +#ifndef GL_EXT_polygon_offset +#define GL_EXT_polygon_offset 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias); +#endif + +#ifndef GL_EXT_texture +#define GL_EXT_texture 1 +#endif + +#ifndef GL_EXT_texture3D +#define GL_EXT_texture3D 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexImage3DEXT (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGIS_texture_filter4 +#define GL_SGIS_texture_filter4 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum, GLenum, GLsizei, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights); +typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights); +#endif + +#ifndef GL_EXT_subtexture +#define GL_EXT_subtexture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexSubImage1DEXT (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_EXT_copy_texture +#define GL_EXT_copy_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); +GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); +GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum, GLint, GLint, GLint, GLint, GLsizei); +GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +#endif + +#ifndef GL_EXT_histogram +#define GL_EXT_histogram 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetHistogramEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetMinmaxEXT (GLenum, GLboolean, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glHistogramEXT (GLenum, GLsizei, GLenum, GLboolean); +GLAPI void APIENTRY glMinmaxEXT (GLenum, GLenum, GLboolean); +GLAPI void APIENTRY glResetHistogramEXT (GLenum); +GLAPI void APIENTRY glResetMinmaxEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target); +typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target); +#endif + +#ifndef GL_EXT_convolution +#define GL_EXT_convolution 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum, GLenum, GLfloat); +GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum, GLenum, GLint); +GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei); +GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *); +GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params); +typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +#endif + +#ifndef GL_EXT_color_matrix +#define GL_EXT_color_matrix 1 +#endif + +#ifndef GL_SGI_color_table +#define GL_SGI_color_table 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorTableSGI (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glColorTableParameterivSGI (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glCopyColorTableSGI (GLenum, GLenum, GLint, GLint, GLsizei); +GLAPI void APIENTRY glGetColorTableSGI (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params); +#endif + +#ifndef GL_SGIX_pixel_texture +#define GL_SGIX_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelTexGenSGIX (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode); +#endif + +#ifndef GL_SGIS_pixel_texture +#define GL_SGIS_pixel_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum, GLint); +GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum, const GLint *); +GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum, GLfloat); +GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum, const GLfloat *); +GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum, GLint *); +GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIS_texture4D +#define GL_SGIS_texture4D 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexImage4DSGIS (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const GLvoid *pixels); +#endif + +#ifndef GL_SGI_texture_color_table +#define GL_SGI_texture_color_table 1 +#endif + +#ifndef GL_EXT_cmyka +#define GL_EXT_cmyka 1 +#endif + +#ifndef GL_EXT_texture_object +#define GL_EXT_texture_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei, const GLuint *, GLboolean *); +GLAPI void APIENTRY glBindTextureEXT (GLenum, GLuint); +GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei, const GLuint *); +GLAPI void APIENTRY glGenTexturesEXT (GLsizei, GLuint *); +GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint); +GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei, const GLuint *, const GLclampf *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures); +typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures); +typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture); +typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities); +#endif + +#ifndef GL_SGIS_detail_texture +#define GL_SGIS_detail_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_SGIS_sharpen_texture +#define GL_SGIS_sharpen_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum, GLsizei, const GLfloat *); +GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points); +typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points); +#endif + +#ifndef GL_EXT_packed_pixels +#define GL_EXT_packed_pixels 1 +#endif + +#ifndef GL_SGIS_texture_lod +#define GL_SGIS_texture_lod 1 +#endif + +#ifndef GL_SGIS_multisample +#define GL_SGIS_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSampleMaskSGIS (GLclampf, GLboolean); +GLAPI void APIENTRY glSamplePatternSGIS (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern); +#endif + +#ifndef GL_EXT_rescale_normal +#define GL_EXT_rescale_normal 1 +#endif + +#ifndef GL_EXT_vertex_array +#define GL_EXT_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glArrayElementEXT (GLint); +GLAPI void APIENTRY glColorPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void APIENTRY glDrawArraysEXT (GLenum, GLint, GLsizei); +GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei, GLsizei, const GLboolean *); +GLAPI void APIENTRY glGetPointervEXT (GLenum, GLvoid* *); +GLAPI void APIENTRY glIndexPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void APIENTRY glNormalPointerEXT (GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void APIENTRY glTexCoordPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +GLAPI void APIENTRY glVertexPointerEXT (GLint, GLenum, GLsizei, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i); +typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer); +typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, GLvoid* *params); +typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_misc_attribute +#define GL_EXT_misc_attribute 1 +#endif + +#ifndef GL_SGIS_generate_mipmap +#define GL_SGIS_generate_mipmap 1 +#endif + +#ifndef GL_SGIX_clipmap +#define GL_SGIX_clipmap 1 +#endif + +#ifndef GL_SGIX_shadow +#define GL_SGIX_shadow 1 +#endif + +#ifndef GL_SGIS_texture_edge_clamp +#define GL_SGIS_texture_edge_clamp 1 +#endif + +#ifndef GL_SGIS_texture_border_clamp +#define GL_SGIS_texture_border_clamp 1 +#endif + +#ifndef GL_EXT_blend_minmax +#define GL_EXT_blend_minmax 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_blend_subtract +#define GL_EXT_blend_subtract 1 +#endif + +#ifndef GL_EXT_blend_logic_op +#define GL_EXT_blend_logic_op 1 +#endif + +#ifndef GL_SGIX_interlace +#define GL_SGIX_interlace 1 +#endif + +#ifndef GL_SGIX_pixel_tiles +#define GL_SGIX_pixel_tiles 1 +#endif + +#ifndef GL_SGIX_texture_select +#define GL_SGIX_texture_select 1 +#endif + +#ifndef GL_SGIX_sprite +#define GL_SGIX_sprite 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum, GLfloat); +GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum, const GLfloat *); +GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum, GLint); +GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_texture_multi_buffer +#define GL_SGIX_texture_multi_buffer 1 +#endif + +#ifndef GL_EXT_point_parameters +#define GL_EXT_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameterfEXT (GLenum, GLfloat); +GLAPI void APIENTRY glPointParameterfvEXT (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_SGIS_point_parameters +#define GL_SGIS_point_parameters 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameterfSGIS (GLenum, GLfloat); +GLAPI void APIENTRY glPointParameterfvSGIS (GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_SGIX_instruments +#define GL_SGIX_instruments 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLint APIENTRY glGetInstrumentsSGIX (void); +GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei, GLint *); +GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *); +GLAPI void APIENTRY glReadInstrumentsSGIX (GLint); +GLAPI void APIENTRY glStartInstrumentsSGIX (void); +GLAPI void APIENTRY glStopInstrumentsSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer); +typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p); +typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker); +typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void); +typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker); +#endif + +#ifndef GL_SGIX_texture_scale_bias +#define GL_SGIX_texture_scale_bias 1 +#endif + +#ifndef GL_SGIX_framezoom +#define GL_SGIX_framezoom 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFrameZoomSGIX (GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor); +#endif + +#ifndef GL_SGIX_tag_sample_buffer +#define GL_SGIX_tag_sample_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTagSampleBufferSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_polynomial_ffd +#define GL_SGIX_polynomial_ffd 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *); +GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *); +GLAPI void APIENTRY glDeformSGIX (GLbitfield); +GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points); +typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points); +typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask); +#endif + +#ifndef GL_SGIX_reference_plane +#define GL_SGIX_reference_plane 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation); +#endif + +#ifndef GL_SGIX_flush_raster +#define GL_SGIX_flush_raster 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFlushRasterSGIX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void); +#endif + +#ifndef GL_SGIX_depth_texture +#define GL_SGIX_depth_texture 1 +#endif + +#ifndef GL_SGIS_fog_function +#define GL_SGIS_fog_function 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFogFuncSGIS (GLsizei, const GLfloat *); +GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points); +typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points); +#endif + +#ifndef GL_SGIX_fog_offset +#define GL_SGIX_fog_offset 1 +#endif + +#ifndef GL_HP_image_transform +#define GL_HP_image_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glImageTransformParameteriHP (GLenum, GLenum, GLint); +GLAPI void APIENTRY glImageTransformParameterfHP (GLenum, GLenum, GLfloat); +GLAPI void APIENTRY glImageTransformParameterivHP (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_HP_convolution_border_modes +#define GL_HP_convolution_border_modes 1 +#endif + +#ifndef GL_SGIX_texture_add_env +#define GL_SGIX_texture_add_env 1 +#endif + +#ifndef GL_EXT_color_subtable +#define GL_EXT_color_subtable 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorSubTableEXT (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum, GLsizei, GLint, GLint, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +#endif + +#ifndef GL_PGI_vertex_hints +#define GL_PGI_vertex_hints 1 +#endif + +#ifndef GL_PGI_misc_hints +#define GL_PGI_misc_hints 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glHintPGI (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode); +#endif + +#ifndef GL_EXT_paletted_texture +#define GL_EXT_paletted_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorTableEXT (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *); +GLAPI void APIENTRY glGetColorTableEXT (GLenum, GLenum, GLenum, GLvoid *); +GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, GLvoid *data); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_EXT_clip_volume_hint +#define GL_EXT_clip_volume_hint 1 +#endif + +#ifndef GL_SGIX_list_priority +#define GL_SGIX_list_priority 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetListParameterivSGIX (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glListParameterfSGIX (GLuint, GLenum, GLfloat); +GLAPI void APIENTRY glListParameterfvSGIX (GLuint, GLenum, const GLfloat *); +GLAPI void APIENTRY glListParameteriSGIX (GLuint, GLenum, GLint); +GLAPI void APIENTRY glListParameterivSGIX (GLuint, GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params); +#endif + +#ifndef GL_SGIX_ir_instrument1 +#define GL_SGIX_ir_instrument1 1 +#endif + +#ifndef GL_SGIX_calligraphic_fragment +#define GL_SGIX_calligraphic_fragment 1 +#endif + +#ifndef GL_SGIX_texture_lod_bias +#define GL_SGIX_texture_lod_bias 1 +#endif + +#ifndef GL_SGIX_shadow_ambient +#define GL_SGIX_shadow_ambient 1 +#endif + +#ifndef GL_EXT_index_texture +#define GL_EXT_index_texture 1 +#endif + +#ifndef GL_EXT_index_material +#define GL_EXT_index_material 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glIndexMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_EXT_index_func +#define GL_EXT_index_func 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glIndexFuncEXT (GLenum, GLclampf); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref); +#endif + +#ifndef GL_EXT_index_array_formats +#define GL_EXT_index_array_formats 1 +#endif + +#ifndef GL_EXT_compiled_vertex_array +#define GL_EXT_compiled_vertex_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glLockArraysEXT (GLint, GLsizei); +GLAPI void APIENTRY glUnlockArraysEXT (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void); +#endif + +#ifndef GL_EXT_cull_vertex +#define GL_EXT_cull_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCullParameterdvEXT (GLenum, GLdouble *); +GLAPI void APIENTRY glCullParameterfvEXT (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params); +#endif + +#ifndef GL_SGIX_ycrcb +#define GL_SGIX_ycrcb 1 +#endif + +#ifndef GL_SGIX_fragment_lighting +#define GL_SGIX_fragment_lighting 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum, GLenum); +GLAPI void APIENTRY glFragmentLightfSGIX (GLenum, GLenum, GLfloat); +GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glFragmentLightiSGIX (GLenum, GLenum, GLint); +GLAPI void APIENTRY glFragmentLightivSGIX (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum, GLfloat); +GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum, const GLfloat *); +GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum, GLint); +GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum, const GLint *); +GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum, GLenum, GLfloat); +GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum, GLenum, GLint); +GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glLightEnviSGIX (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param); +#endif + +#ifndef GL_IBM_rasterpos_clip +#define GL_IBM_rasterpos_clip 1 +#endif + +#ifndef GL_HP_texture_lighting +#define GL_HP_texture_lighting 1 +#endif + +#ifndef GL_EXT_draw_range_elements +#define GL_EXT_draw_range_elements 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +#endif + +#ifndef GL_WIN_phong_shading +#define GL_WIN_phong_shading 1 +#endif + +#ifndef GL_WIN_specular_fog +#define GL_WIN_specular_fog 1 +#endif + +#ifndef GL_EXT_light_texture +#define GL_EXT_light_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glApplyTextureEXT (GLenum); +GLAPI void APIENTRY glTextureLightEXT (GLenum); +GLAPI void APIENTRY glTextureMaterialEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname); +typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode); +#endif + +#ifndef GL_SGIX_blend_alpha_minmax +#define GL_SGIX_blend_alpha_minmax 1 +#endif + +#ifndef GL_EXT_bgra +#define GL_EXT_bgra 1 +#endif + +#ifndef GL_SGIX_async +#define GL_SGIX_async 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint); +GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *); +GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *); +GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei); +GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint, GLsizei); +GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker); +typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp); +typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp); +typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range); +typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range); +typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker); +#endif + +#ifndef GL_SGIX_async_pixel +#define GL_SGIX_async_pixel 1 +#endif + +#ifndef GL_SGIX_async_histogram +#define GL_SGIX_async_histogram 1 +#endif + +#ifndef GL_INTEL_parallel_arrays +#define GL_INTEL_parallel_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexPointervINTEL (GLint, GLenum, const GLvoid* *); +GLAPI void APIENTRY glNormalPointervINTEL (GLenum, const GLvoid* *); +GLAPI void APIENTRY glColorPointervINTEL (GLint, GLenum, const GLvoid* *); +GLAPI void APIENTRY glTexCoordPointervINTEL (GLint, GLenum, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const GLvoid* *pointer); +typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const GLvoid* *pointer); +#endif + +#ifndef GL_HP_occlusion_test +#define GL_HP_occlusion_test 1 +#endif + +#ifndef GL_EXT_pixel_transform +#define GL_EXT_pixel_transform 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum, GLenum, GLint); +GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum, GLenum, GLfloat); +GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum, GLenum, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params); +#endif + +#ifndef GL_EXT_pixel_transform_color_table +#define GL_EXT_pixel_transform_color_table 1 +#endif + +#ifndef GL_EXT_shared_texture_palette +#define GL_EXT_shared_texture_palette 1 +#endif + +#ifndef GL_EXT_separate_specular_color +#define GL_EXT_separate_specular_color 1 +#endif + +#ifndef GL_EXT_secondary_color +#define GL_EXT_secondary_color 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte, GLbyte, GLbyte); +GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *); +GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *); +GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *); +GLAPI void APIENTRY glSecondaryColor3iEXT (GLint, GLint, GLint); +GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *); +GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort, GLshort, GLshort); +GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *); +GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte, GLubyte, GLubyte); +GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *); +GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint, GLuint, GLuint); +GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *); +GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort, GLushort, GLushort); +GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *); +GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v); +typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_perturb_normal +#define GL_EXT_texture_perturb_normal 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureNormalEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode); +#endif + +#ifndef GL_EXT_multi_draw_arrays +#define GL_EXT_multi_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); +GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); +#endif + +#ifndef GL_EXT_fog_coord +#define GL_EXT_fog_coord 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFogCoordfEXT (GLfloat); +GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *); +GLAPI void APIENTRY glFogCoorddEXT (GLdouble); +GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *); +GLAPI void APIENTRY glFogCoordPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord); +typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord); +typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord); +typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord); +typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_REND_screen_coordinates +#define GL_REND_screen_coordinates 1 +#endif + +#ifndef GL_EXT_coordinate_frame +#define GL_EXT_coordinate_frame 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTangent3bEXT (GLbyte, GLbyte, GLbyte); +GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *); +GLAPI void APIENTRY glTangent3dEXT (GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *); +GLAPI void APIENTRY glTangent3fEXT (GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *); +GLAPI void APIENTRY glTangent3iEXT (GLint, GLint, GLint); +GLAPI void APIENTRY glTangent3ivEXT (const GLint *); +GLAPI void APIENTRY glTangent3sEXT (GLshort, GLshort, GLshort); +GLAPI void APIENTRY glTangent3svEXT (const GLshort *); +GLAPI void APIENTRY glBinormal3bEXT (GLbyte, GLbyte, GLbyte); +GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *); +GLAPI void APIENTRY glBinormal3dEXT (GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *); +GLAPI void APIENTRY glBinormal3fEXT (GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *); +GLAPI void APIENTRY glBinormal3iEXT (GLint, GLint, GLint); +GLAPI void APIENTRY glBinormal3ivEXT (const GLint *); +GLAPI void APIENTRY glBinormal3sEXT (GLshort, GLshort, GLshort); +GLAPI void APIENTRY glBinormal3svEXT (const GLshort *); +GLAPI void APIENTRY glTangentPointerEXT (GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glBinormalPointerEXT (GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz); +typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz); +typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz); +typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz); +typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz); +typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz); +typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v); +typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz); +typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz); +typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz); +typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz); +typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_EXT_texture_env_combine +#define GL_EXT_texture_env_combine 1 +#endif + +#ifndef GL_APPLE_specular_vector +#define GL_APPLE_specular_vector 1 +#endif + +#ifndef GL_APPLE_transform_hint +#define GL_APPLE_transform_hint 1 +#endif + +#ifndef GL_SGIX_fog_scale +#define GL_SGIX_fog_scale 1 +#endif + +#ifndef GL_SUNX_constant_data +#define GL_SUNX_constant_data 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFinishTextureSUNX (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void); +#endif + +#ifndef GL_SUN_global_alpha +#define GL_SUN_global_alpha 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte); +GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort); +GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint); +GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat); +GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble); +GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte); +GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort); +GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor); +typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor); +#endif + +#ifndef GL_SUN_triangle_list +#define GL_SUN_triangle_list 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint); +GLAPI void APIENTRY glReplacementCodeusSUN (GLushort); +GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte); +GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *); +GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *); +GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *); +GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum, GLsizei, const GLvoid* *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const GLvoid* *pointer); +#endif + +#ifndef GL_SUN_vertex +#define GL_SUN_vertex 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat); +GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *, const GLfloat *); +GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *, const GLfloat *); +GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *, const GLubyte *, const GLfloat *); +GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *, const GLubyte *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v); +#endif + +#ifndef GL_EXT_blend_func_separate +#define GL_EXT_blend_func_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum, GLenum, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif + +#ifndef GL_INGR_blend_func_separate +#define GL_INGR_blend_func_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum, GLenum, GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +#endif + +#ifndef GL_INGR_color_clamp +#define GL_INGR_color_clamp 1 +#endif + +#ifndef GL_INGR_interlace_read +#define GL_INGR_interlace_read 1 +#endif + +#ifndef GL_EXT_stencil_wrap +#define GL_EXT_stencil_wrap 1 +#endif + +#ifndef GL_EXT_422_pixels +#define GL_EXT_422_pixels 1 +#endif + +#ifndef GL_NV_texgen_reflection +#define GL_NV_texgen_reflection 1 +#endif + +#ifndef GL_SUN_convolution_border_modes +#define GL_SUN_convolution_border_modes 1 +#endif + +#ifndef GL_EXT_texture_env_add +#define GL_EXT_texture_env_add 1 +#endif + +#ifndef GL_EXT_texture_lod_bias +#define GL_EXT_texture_lod_bias 1 +#endif + +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +#ifndef GL_EXT_vertex_weighting +#define GL_EXT_vertex_weighting 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexWeightfEXT (GLfloat); +GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *); +GLAPI void APIENTRY glVertexWeightPointerEXT (GLsizei, GLenum, GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLsizei size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +#ifndef GL_NV_light_max_exponent +#define GL_NV_light_max_exponent 1 +#endif + +#ifndef GL_NV_vertex_array_range +#define GL_NV_vertex_array_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFlushVertexArrayRangeNV (void); +GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void); +typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const GLvoid *pointer); +#endif + +#ifndef GL_NV_register_combiners +#define GL_NV_register_combiners 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCombinerParameterfvNV (GLenum, const GLfloat *); +GLAPI void APIENTRY glCombinerParameterfNV (GLenum, GLfloat); +GLAPI void APIENTRY glCombinerParameterivNV (GLenum, const GLint *); +GLAPI void APIENTRY glCombinerParameteriNV (GLenum, GLint); +GLAPI void APIENTRY glCombinerInputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glCombinerOutputNV (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean); +GLAPI void APIENTRY glFinalCombinerInputNV (GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum, GLenum, GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum, GLenum, GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum, GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum, GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param); +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum); +typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage); +typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params); +#endif + +#ifndef GL_NV_fog_distance +#define GL_NV_fog_distance 1 +#endif + +#ifndef GL_NV_texgen_emboss +#define GL_NV_texgen_emboss 1 +#endif + +#ifndef GL_NV_blend_square +#define GL_NV_blend_square 1 +#endif + +#ifndef GL_NV_texture_env_combine4 +#define GL_NV_texture_env_combine4 1 +#endif + +#ifndef GL_MESA_resize_buffers +#define GL_MESA_resize_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glResizeBuffersMESA (void); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void); +#endif + +#ifndef GL_MESA_window_pos +#define GL_MESA_window_pos 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWindowPos2dMESA (GLdouble, GLdouble); +GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *); +GLAPI void APIENTRY glWindowPos2fMESA (GLfloat, GLfloat); +GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *); +GLAPI void APIENTRY glWindowPos2iMESA (GLint, GLint); +GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *); +GLAPI void APIENTRY glWindowPos2sMESA (GLshort, GLshort); +GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *); +GLAPI void APIENTRY glWindowPos3dMESA (GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *); +GLAPI void APIENTRY glWindowPos3fMESA (GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *); +GLAPI void APIENTRY glWindowPos3iMESA (GLint, GLint, GLint); +GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *); +GLAPI void APIENTRY glWindowPos3sMESA (GLshort, GLshort, GLshort); +GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *); +GLAPI void APIENTRY glWindowPos4dMESA (GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *); +GLAPI void APIENTRY glWindowPos4fMESA (GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *); +GLAPI void APIENTRY glWindowPos4iMESA (GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *); +GLAPI void APIENTRY glWindowPos4sMESA (GLshort, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y); +typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v); +typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v); +#endif + +#ifndef GL_IBM_cull_vertex +#define GL_IBM_cull_vertex 1 +#endif + +#ifndef GL_IBM_multimode_draw_arrays +#define GL_IBM_multimode_draw_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *, const GLint *, const GLsizei *, GLsizei, GLint); +GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *, const GLsizei *, GLenum, const GLvoid* const *, GLsizei, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride); +typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei primcount, GLint modestride); +#endif + +#ifndef GL_IBM_vertex_array_lists +#define GL_IBM_vertex_array_lists 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint, const GLboolean* *, GLint); +GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +GLAPI void APIENTRY glIndexPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +GLAPI void APIENTRY glNormalPointerListIBM (GLenum, GLint, const GLvoid* *, GLint); +GLAPI void APIENTRY glTexCoordPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +GLAPI void APIENTRY glVertexPointerListIBM (GLint, GLenum, GLint, const GLvoid* *, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean* *pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const GLvoid* *pointer, GLint ptrstride); +#endif + +#ifndef GL_SGIX_subsample +#define GL_SGIX_subsample 1 +#endif + +#ifndef GL_SGIX_ycrcba +#define GL_SGIX_ycrcba 1 +#endif + +#ifndef GL_SGIX_ycrcb_subsample +#define GL_SGIX_ycrcb_subsample 1 +#endif + +#ifndef GL_SGIX_depth_pass_instrument +#define GL_SGIX_depth_pass_instrument 1 +#endif + +#ifndef GL_3DFX_texture_compression_FXT1 +#define GL_3DFX_texture_compression_FXT1 1 +#endif + +#ifndef GL_3DFX_multisample +#define GL_3DFX_multisample 1 +#endif + +#ifndef GL_3DFX_tbuffer +#define GL_3DFX_tbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTbufferMask3DFX (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask); +#endif + +#ifndef GL_EXT_multisample +#define GL_EXT_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSampleMaskEXT (GLclampf, GLboolean); +GLAPI void APIENTRY glSamplePatternEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert); +typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern); +#endif + +#ifndef GL_SGIX_vertex_preclip +#define GL_SGIX_vertex_preclip 1 +#endif + +#ifndef GL_SGIX_convolution_accuracy +#define GL_SGIX_convolution_accuracy 1 +#endif + +#ifndef GL_SGIX_resample +#define GL_SGIX_resample 1 +#endif + +#ifndef GL_SGIS_point_line_texgen +#define GL_SGIS_point_line_texgen 1 +#endif + +#ifndef GL_SGIS_texture_color_mask +#define GL_SGIS_texture_color_mask 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean, GLboolean, GLboolean, GLboolean); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +#endif + +#ifndef GL_SGIX_igloo_interface +#define GL_SGIX_igloo_interface 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum, const GLvoid *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const GLvoid *params); +#endif + +#ifndef GL_EXT_texture_env_dot3 +#define GL_EXT_texture_env_dot3 1 +#endif + +#ifndef GL_ATI_texture_mirror_once +#define GL_ATI_texture_mirror_once 1 +#endif + +#ifndef GL_NV_fence +#define GL_NV_fence 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDeleteFencesNV (GLsizei, const GLuint *); +GLAPI void APIENTRY glGenFencesNV (GLsizei, GLuint *); +GLAPI GLboolean APIENTRY glIsFenceNV (GLuint); +GLAPI GLboolean APIENTRY glTestFenceNV (GLuint); +GLAPI void APIENTRY glGetFenceivNV (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glFinishFenceNV (GLuint); +GLAPI void APIENTRY glSetFenceNV (GLuint, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); +typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); +typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); +typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); +typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); +#endif + +#ifndef GL_NV_evaluators +#define GL_NV_evaluators 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *); +GLAPI void APIENTRY glMapParameterivNV (GLenum, GLenum, const GLint *); +GLAPI void APIENTRY glMapParameterfvNV (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glGetMapControlPointsNV (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *); +GLAPI void APIENTRY glGetMapParameterivNV (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glGetMapParameterfvNV (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum, GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum, GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glEvalMapsNV (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const GLvoid *points); +typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, GLvoid *points); +typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode); +#endif + +#ifndef GL_NV_packed_depth_stencil +#define GL_NV_packed_depth_stencil 1 +#endif + +#ifndef GL_NV_register_combiners2 +#define GL_NV_register_combiners2 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum, GLenum, const GLfloat *); +GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params); +typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params); +#endif + +#ifndef GL_NV_texture_compression_vtc +#define GL_NV_texture_compression_vtc 1 +#endif + +#ifndef GL_NV_texture_rectangle +#define GL_NV_texture_rectangle 1 +#endif + +#ifndef GL_NV_texture_shader +#define GL_NV_texture_shader 1 +#endif + +#ifndef GL_NV_texture_shader2 +#define GL_NV_texture_shader2 1 +#endif + +#ifndef GL_NV_vertex_array_range2 +#define GL_NV_vertex_array_range2 1 +#endif + +#ifndef GL_NV_vertex_program +#define GL_NV_vertex_program 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei, const GLuint *, GLboolean *); +GLAPI void APIENTRY glBindProgramNV (GLenum, GLuint); +GLAPI void APIENTRY glDeleteProgramsNV (GLsizei, const GLuint *); +GLAPI void APIENTRY glExecuteProgramNV (GLenum, GLuint, const GLfloat *); +GLAPI void APIENTRY glGenProgramsNV (GLsizei, GLuint *); +GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum, GLuint, GLenum, GLdouble *); +GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum, GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetProgramivNV (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetProgramStringNV (GLuint, GLenum, GLubyte *); +GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum, GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint, GLenum, GLdouble *); +GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetVertexAttribivNV (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint, GLenum, GLvoid* *); +GLAPI GLboolean APIENTRY glIsProgramNV (GLuint); +GLAPI void APIENTRY glLoadProgramNV (GLenum, GLuint, GLsizei, const GLubyte *); +GLAPI void APIENTRY glProgramParameter4dNV (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glProgramParameter4dvNV (GLenum, GLuint, const GLdouble *); +GLAPI void APIENTRY glProgramParameter4fNV (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glProgramParameter4fvNV (GLenum, GLuint, const GLfloat *); +GLAPI void APIENTRY glProgramParameters4dvNV (GLenum, GLuint, GLuint, const GLdouble *); +GLAPI void APIENTRY glProgramParameters4fvNV (GLenum, GLuint, GLuint, const GLfloat *); +GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei, const GLuint *); +GLAPI void APIENTRY glTrackMatrixNV (GLenum, GLuint, GLenum, GLenum); +GLAPI void APIENTRY glVertexAttribPointerNV (GLuint, GLint, GLenum, GLsizei, const GLvoid *); +GLAPI void APIENTRY glVertexAttrib1dNV (GLuint, GLdouble); +GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib1fNV (GLuint, GLfloat); +GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib1sNV (GLuint, GLshort); +GLAPI void APIENTRY glVertexAttrib1svNV (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib2dNV (GLuint, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib2fNV (GLuint, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib2sNV (GLuint, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib2svNV (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib3dNV (GLuint, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib3fNV (GLuint, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib3sNV (GLuint, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib3svNV (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4dNV (GLuint, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint, const GLdouble *); +GLAPI void APIENTRY glVertexAttrib4fNV (GLuint, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint, const GLfloat *); +GLAPI void APIENTRY glVertexAttrib4sNV (GLuint, GLshort, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexAttrib4svNV (GLuint, const GLshort *); +GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint, GLubyte, GLubyte, GLubyte, GLubyte); +GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint, const GLubyte *); +GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glVertexAttribs1svNV (GLuint, GLsizei, const GLshort *); +GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glVertexAttribs2svNV (GLuint, GLsizei, const GLshort *); +GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glVertexAttribs3svNV (GLuint, GLsizei, const GLshort *); +GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint, GLsizei, const GLdouble *); +GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint, GLsizei, const GLfloat *); +GLAPI void APIENTRY glVertexAttribs4svNV (GLuint, GLsizei, const GLshort *); +GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint, GLsizei, const GLubyte *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences); +typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id); +typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params); +typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs); +typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program); +typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id); +typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLuint count, const GLdouble *v); +typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLuint count, const GLfloat *v); +typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform); +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v); +#endif + +#ifndef GL_SGIX_texture_coordinate_clamp +#define GL_SGIX_texture_coordinate_clamp 1 +#endif + +#ifndef GL_SGIX_scalebias_hint +#define GL_SGIX_scalebias_hint 1 +#endif + +#ifndef GL_OML_interlace +#define GL_OML_interlace 1 +#endif + +#ifndef GL_OML_subsample +#define GL_OML_subsample 1 +#endif + +#ifndef GL_OML_resample +#define GL_OML_resample 1 +#endif + +#ifndef GL_NV_copy_depth_to_color +#define GL_NV_copy_depth_to_color 1 +#endif + +#ifndef GL_ATI_envmap_bumpmap +#define GL_ATI_envmap_bumpmap 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexBumpParameterivATI (GLenum, const GLint *); +GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum, const GLfloat *); +GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum, GLint *); +GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param); +typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param); +typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param); +typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param); +#endif + +#ifndef GL_ATI_fragment_shader +#define GL_ATI_fragment_shader 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint); +GLAPI void APIENTRY glBindFragmentShaderATI (GLuint); +GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint); +GLAPI void APIENTRY glBeginFragmentShaderATI (void); +GLAPI void APIENTRY glEndFragmentShaderATI (void); +GLAPI void APIENTRY glPassTexCoordATI (GLuint, GLuint, GLenum); +GLAPI void APIENTRY glSampleMapATI (GLuint, GLuint, GLenum); +GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint, const GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range); +typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void); +typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void); +typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle); +typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle); +typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod); +typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod); +typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod); +typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value); +#endif + +#ifndef GL_ATI_pn_triangles +#define GL_ATI_pn_triangles 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPNTrianglesiATI (GLenum, GLint); +GLAPI void APIENTRY glPNTrianglesfATI (GLenum, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param); +#endif + +#ifndef GL_ATI_vertex_array_object +#define GL_ATI_vertex_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei, const GLvoid *, GLenum); +GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint); +GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint, GLuint, GLsizei, const GLvoid *, GLenum); +GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetObjectBufferivATI (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glFreeObjectBufferATI (GLuint); +GLAPI void APIENTRY glArrayObjectATI (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint); +GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum, GLenum, GLfloat *); +GLAPI void APIENTRY glGetArrayObjectivATI (GLenum, GLenum, GLint *); +GLAPI void APIENTRY glVariantArrayObjectATI (GLuint, GLenum, GLsizei, GLuint, GLuint); +GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const GLvoid *pointer, GLenum usage); +typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const GLvoid *pointer, GLenum preserve); +typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params); +#endif + +#ifndef GL_EXT_vertex_shader +#define GL_EXT_vertex_shader 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBeginVertexShaderEXT (void); +GLAPI void APIENTRY glEndVertexShaderEXT (void); +GLAPI void APIENTRY glBindVertexShaderEXT (GLuint); +GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint); +GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint); +GLAPI void APIENTRY glShaderOp1EXT (GLenum, GLuint, GLuint); +GLAPI void APIENTRY glShaderOp2EXT (GLenum, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glShaderOp3EXT (GLenum, GLuint, GLuint, GLuint, GLuint); +GLAPI void APIENTRY glSwizzleEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glWriteMaskEXT (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glInsertComponentEXT (GLuint, GLuint, GLuint); +GLAPI void APIENTRY glExtractComponentEXT (GLuint, GLuint, GLuint); +GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum, GLenum, GLenum, GLuint); +GLAPI void APIENTRY glSetInvariantEXT (GLuint, GLenum, const GLvoid *); +GLAPI void APIENTRY glSetLocalConstantEXT (GLuint, GLenum, const GLvoid *); +GLAPI void APIENTRY glVariantbvEXT (GLuint, const GLbyte *); +GLAPI void APIENTRY glVariantsvEXT (GLuint, const GLshort *); +GLAPI void APIENTRY glVariantivEXT (GLuint, const GLint *); +GLAPI void APIENTRY glVariantfvEXT (GLuint, const GLfloat *); +GLAPI void APIENTRY glVariantdvEXT (GLuint, const GLdouble *); +GLAPI void APIENTRY glVariantubvEXT (GLuint, const GLubyte *); +GLAPI void APIENTRY glVariantusvEXT (GLuint, const GLushort *); +GLAPI void APIENTRY glVariantuivEXT (GLuint, const GLuint *); +GLAPI void APIENTRY glVariantPointerEXT (GLuint, GLenum, GLuint, const GLvoid *); +GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint); +GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint); +GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum, GLenum); +GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum, GLenum); +GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum, GLenum, GLenum); +GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum, GLenum); +GLAPI GLuint APIENTRY glBindParameterEXT (GLenum); +GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint, GLenum); +GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint, GLenum, GLboolean *); +GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetVariantPointervEXT (GLuint, GLenum, GLvoid* *); +GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint, GLenum, GLboolean *); +GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint, GLenum, GLboolean *); +GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint, GLenum, GLfloat *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void); +typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void); +typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id); +typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range); +typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id); +typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1); +typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2); +typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3); +typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW); +typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num); +typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components); +typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); +typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const GLvoid *addr); +typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr); +typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr); +typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr); +typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr); +typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr); +typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr); +typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr); +typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr); +typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const GLvoid *addr); +typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id); +typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value); +typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value); +typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap); +typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, GLvoid* *data); +typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data); +typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data); +typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data); +#endif + +#ifndef GL_ATI_vertex_streams +#define GL_ATI_vertex_streams 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexStream1sATI (GLenum, GLshort); +GLAPI void APIENTRY glVertexStream1svATI (GLenum, const GLshort *); +GLAPI void APIENTRY glVertexStream1iATI (GLenum, GLint); +GLAPI void APIENTRY glVertexStream1ivATI (GLenum, const GLint *); +GLAPI void APIENTRY glVertexStream1fATI (GLenum, GLfloat); +GLAPI void APIENTRY glVertexStream1fvATI (GLenum, const GLfloat *); +GLAPI void APIENTRY glVertexStream1dATI (GLenum, GLdouble); +GLAPI void APIENTRY glVertexStream1dvATI (GLenum, const GLdouble *); +GLAPI void APIENTRY glVertexStream2sATI (GLenum, GLshort, GLshort); +GLAPI void APIENTRY glVertexStream2svATI (GLenum, const GLshort *); +GLAPI void APIENTRY glVertexStream2iATI (GLenum, GLint, GLint); +GLAPI void APIENTRY glVertexStream2ivATI (GLenum, const GLint *); +GLAPI void APIENTRY glVertexStream2fATI (GLenum, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexStream2fvATI (GLenum, const GLfloat *); +GLAPI void APIENTRY glVertexStream2dATI (GLenum, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexStream2dvATI (GLenum, const GLdouble *); +GLAPI void APIENTRY glVertexStream3sATI (GLenum, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexStream3svATI (GLenum, const GLshort *); +GLAPI void APIENTRY glVertexStream3iATI (GLenum, GLint, GLint, GLint); +GLAPI void APIENTRY glVertexStream3ivATI (GLenum, const GLint *); +GLAPI void APIENTRY glVertexStream3fATI (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexStream3fvATI (GLenum, const GLfloat *); +GLAPI void APIENTRY glVertexStream3dATI (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexStream3dvATI (GLenum, const GLdouble *); +GLAPI void APIENTRY glVertexStream4sATI (GLenum, GLshort, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glVertexStream4svATI (GLenum, const GLshort *); +GLAPI void APIENTRY glVertexStream4iATI (GLenum, GLint, GLint, GLint, GLint); +GLAPI void APIENTRY glVertexStream4ivATI (GLenum, const GLint *); +GLAPI void APIENTRY glVertexStream4fATI (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glVertexStream4fvATI (GLenum, const GLfloat *); +GLAPI void APIENTRY glVertexStream4dATI (GLenum, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glVertexStream4dvATI (GLenum, const GLdouble *); +GLAPI void APIENTRY glNormalStream3bATI (GLenum, GLbyte, GLbyte, GLbyte); +GLAPI void APIENTRY glNormalStream3bvATI (GLenum, const GLbyte *); +GLAPI void APIENTRY glNormalStream3sATI (GLenum, GLshort, GLshort, GLshort); +GLAPI void APIENTRY glNormalStream3svATI (GLenum, const GLshort *); +GLAPI void APIENTRY glNormalStream3iATI (GLenum, GLint, GLint, GLint); +GLAPI void APIENTRY glNormalStream3ivATI (GLenum, const GLint *); +GLAPI void APIENTRY glNormalStream3fATI (GLenum, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glNormalStream3fvATI (GLenum, const GLfloat *); +GLAPI void APIENTRY glNormalStream3dATI (GLenum, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glNormalStream3dvATI (GLenum, const GLdouble *); +GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum); +GLAPI void APIENTRY glVertexBlendEnviATI (GLenum, GLint); +GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum, GLfloat); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x); +typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y); +typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords); +typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz); +typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords); +typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream); +typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param); +#endif + +#ifndef GL_ATI_element_array +#define GL_ATI_element_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glElementPointerATI (GLenum, const GLvoid *); +GLAPI void APIENTRY glDrawElementArrayATI (GLenum, GLsizei); +GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum, GLuint, GLuint, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count); +#endif + +#ifndef GL_SUN_mesh_array +#define GL_SUN_mesh_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum, GLint, GLsizei, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width); +#endif + +#ifndef GL_SUN_slice_accum +#define GL_SUN_slice_accum 1 +#endif + +#ifndef GL_NV_multisample_filter_hint +#define GL_NV_multisample_filter_hint 1 +#endif + +#ifndef GL_NV_depth_clamp +#define GL_NV_depth_clamp 1 +#endif + +#ifndef GL_NV_occlusion_query +#define GL_NV_occlusion_query 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei, GLuint *); +GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei, const GLuint *); +GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint); +GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint); +GLAPI void APIENTRY glEndOcclusionQueryNV (void); +GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint, GLenum, GLint *); +GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint, GLenum, GLuint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids); +typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id); +typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void); +typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params); +#endif + +#ifndef GL_NV_point_sprite +#define GL_NV_point_sprite 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPointParameteriNV (GLenum, GLint); +GLAPI void APIENTRY glPointParameterivNV (GLenum, const GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params); +#endif + +#ifndef GL_NV_texture_shader3 +#define GL_NV_texture_shader3 1 +#endif + +#ifndef GL_NV_vertex_program1_1 +#define GL_NV_vertex_program1_1 1 +#endif + +#ifndef GL_EXT_shadow_funcs +#define GL_EXT_shadow_funcs 1 +#endif + +#ifndef GL_EXT_stencil_two_side +#define GL_EXT_stencil_two_side 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face); +#endif + +#ifndef GL_ATI_text_fragment_shader +#define GL_ATI_text_fragment_shader 1 +#endif + +#ifndef GL_APPLE_client_storage +#define GL_APPLE_client_storage 1 +#endif + +#ifndef GL_APPLE_element_array +#define GL_APPLE_element_array 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glElementPointerAPPLE (GLenum, const GLvoid *); +GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum, GLint, GLsizei); +GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, GLint, GLsizei); +GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum, const GLint *, const GLsizei *, GLsizei); +GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const GLvoid *pointer); +typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount); +#endif + +#ifndef GL_APPLE_fence +#define GL_APPLE_fence 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenFencesAPPLE (GLsizei, GLuint *); +GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei, const GLuint *); +GLAPI void APIENTRY glSetFenceAPPLE (GLuint); +GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint); +GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint); +GLAPI void APIENTRY glFinishFenceAPPLE (GLuint); +GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum, GLuint); +GLAPI void APIENTRY glFinishObjectAPPLE (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences); +typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences); +typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence); +typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence); +typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name); +typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name); +#endif + +#ifndef GL_APPLE_vertex_array_object +#define GL_APPLE_vertex_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint); +GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei, const GLuint *); +GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei, const GLuint *); +GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array); +typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); +typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays); +typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array); +#endif + +#ifndef GL_APPLE_vertex_array_range +#define GL_APPLE_vertex_array_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei, GLvoid *); +GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei, GLvoid *); +GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum, GLint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); +typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, GLvoid *pointer); +typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param); +#endif + +#ifndef GL_APPLE_ycbcr_422 +#define GL_APPLE_ycbcr_422 1 +#endif + +#ifndef GL_S3_s3tc +#define GL_S3_s3tc 1 +#endif + +#ifndef GL_ATI_draw_buffers +#define GL_ATI_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawBuffersATI (GLsizei, const GLenum *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs); +#endif + +#ifndef GL_ATI_pixel_format_float +#define GL_ATI_pixel_format_float 1 +/* This is really a WGL extension, but defines some associated GL enums. + * ATI does not export "GL_ATI_pixel_format_float" in the GL_EXTENSIONS string. + */ +#endif + +#ifndef GL_ATI_texture_env_combine3 +#define GL_ATI_texture_env_combine3 1 +#endif + +#ifndef GL_ATI_texture_float +#define GL_ATI_texture_float 1 +#endif + +#ifndef GL_NV_float_buffer +#define GL_NV_float_buffer 1 +#endif + +#ifndef GL_NV_fragment_program +#define GL_NV_fragment_program 1 +/* Some NV_fragment_program entry points are shared with ARB_vertex_program. */ +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat); +GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble); +GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint, GLsizei, const GLubyte *, const GLfloat *); +GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint, GLsizei, const GLubyte *, const GLdouble *); +GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint, GLsizei, const GLubyte *, GLfloat *); +GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint, GLsizei, const GLubyte *, GLdouble *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v); +typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v); +typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params); +#endif + +#ifndef GL_NV_half_float +#define GL_NV_half_float 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertex2hNV (GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *); +GLAPI void APIENTRY glVertex3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *); +GLAPI void APIENTRY glVertex4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *); +GLAPI void APIENTRY glNormal3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *); +GLAPI void APIENTRY glColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *); +GLAPI void APIENTRY glColor4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *); +GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV); +GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *); +GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *); +GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *); +GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *); +GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum, GLhalfNV); +GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum, const GLhalfNV *); +GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum, const GLhalfNV *); +GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum, const GLhalfNV *); +GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum, const GLhalfNV *); +GLAPI void APIENTRY glFogCoordhNV (GLhalfNV); +GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *); +GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *); +GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV); +GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *); +GLAPI void APIENTRY glVertexAttrib1hNV (GLuint, GLhalfNV); +GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint, const GLhalfNV *); +GLAPI void APIENTRY glVertexAttrib2hNV (GLuint, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint, const GLhalfNV *); +GLAPI void APIENTRY glVertexAttrib3hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint, const GLhalfNV *); +GLAPI void APIENTRY glVertexAttrib4hNV (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV); +GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint, const GLhalfNV *); +GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint, GLsizei, const GLhalfNV *); +GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint, GLsizei, const GLhalfNV *); +GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint, GLsizei, const GLhalfNV *); +GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint, GLsizei, const GLhalfNV *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y); +typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z); +typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz); +typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha); +typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s); +typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t); +typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r); +typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s); +typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t); +typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r); +typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); +typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog); +typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x); +typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y); +typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z); +typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w); +typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +#endif + +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPixelDataRangeNV (GLenum, GLsizei, GLvoid *); +GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); +typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +#endif + +#ifndef GL_NV_primitive_restart +#define GL_NV_primitive_restart 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPrimitiveRestartNV (void); +GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void); +typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index); +#endif + +#ifndef GL_NV_texture_expand_normal +#define GL_NV_texture_expand_normal 1 +#endif + +#ifndef GL_NV_vertex_program2 +#define GL_NV_vertex_program2 1 +#endif + +#ifndef GL_ATI_map_object_buffer +#define GL_ATI_map_object_buffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLvoid* APIENTRY glMapObjectBufferATI (GLuint); +GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef GLvoid* (APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer); +typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer); +#endif + +#ifndef GL_ATI_separate_stencil +#define GL_ATI_separate_stencil 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glStencilOpSeparateATI (GLenum, GLenum, GLenum, GLenum); +GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum, GLenum, GLint, GLuint); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); +#endif + +#ifndef GL_ATI_vertex_attrib_array_object +#define GL_ATI_vertex_attrib_array_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint); +GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint, GLenum, GLfloat *); +GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint, GLenum, GLint *); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params); +#endif + +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 +#endif + +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDepthBoundsEXT (GLclampd, GLclampd); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax); +#endif + +#ifndef GL_EXT_texture_mirror_clamp +#define GL_EXT_texture_mirror_clamp 1 +#endif + +#ifndef GL_EXT_blend_equation_separate +#define GL_EXT_blend_equation_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum, GLenum); +#endif /* GL_GLEXT_PROTOTYPES */ +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha); +#endif + +#ifndef GL_MESA_pack_invert +#define GL_MESA_pack_invert 1 +#endif + +#ifndef GL_MESA_ycbcr_texture +#define GL_MESA_ycbcr_texture 1 +#endif + +#ifndef GL_EXT_pixel_buffer_object +#define GL_EXT_pixel_buffer_object 1 +#endif + +#ifndef GL_NV_fragment_program_option +#define GL_NV_fragment_program_option 1 +#endif + +#ifndef GL_NV_fragment_program2 +#define GL_NV_fragment_program2 1 +#endif + +#ifndef GL_NV_vertex_program2_option +#define GL_NV_vertex_program2_option 1 +#endif + +#ifndef GL_NV_vertex_program3 +#define GL_NV_vertex_program3 1 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Utilities/ParseOGLExt/headers/glxext.h b/Utilities/ParseOGLExt/headers/glxext.h new file mode 100644 index 0000000..74e236c --- /dev/null +++ b/Utilities/ParseOGLExt/headers/glxext.h @@ -0,0 +1,706 @@ +#ifndef __glxext_h_ +#define __glxext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/*************************************************************/ + +/* Header file version number, required by OpenGL ABI for Linux */ +/* glxext.h last updated 2005/01/20 */ +/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ +#define GLX_GLXEXT_VERSION 10 + +#ifndef GLX_VERSION_1_3 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_NONE 0x8000 +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_VISUAL_ID 0x800B +#define GLX_SCREEN 0x800C +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_WIDTH 0x801D +#define GLX_HEIGHT 0x801E +#define GLX_EVENT_MASK 0x801F +#define GLX_DAMAGED 0x8020 +#define GLX_SAVED 0x8021 +#define GLX_WINDOW 0x8022 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#endif + +#ifndef GLX_VERSION_1_4 +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAMPLES 100001 +#endif + +#ifndef GLX_ARB_get_proc_address +#endif + +#ifndef GLX_ARB_multisample +#define GLX_SAMPLE_BUFFERS_ARB 100000 +#define GLX_SAMPLES_ARB 100001 +#endif + +#ifndef GLX_ARB_fbconfig_float +#define GLX_RGBA_FLOAT_TYPE_ARB 0x20B9 +#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004 +#endif + +#ifndef GLX_SGIS_multisample +#define GLX_SAMPLE_BUFFERS_SGIS 100000 +#define GLX_SAMPLES_SGIS 100001 +#endif + +#ifndef GLX_EXT_visual_info +#define GLX_X_VISUAL_TYPE_EXT 0x22 +#define GLX_TRANSPARENT_TYPE_EXT 0x23 +#define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 +#define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 +#define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 +#define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 +#define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 +#define GLX_NONE_EXT 0x8000 +#define GLX_TRUE_COLOR_EXT 0x8002 +#define GLX_DIRECT_COLOR_EXT 0x8003 +#define GLX_PSEUDO_COLOR_EXT 0x8004 +#define GLX_STATIC_COLOR_EXT 0x8005 +#define GLX_GRAY_SCALE_EXT 0x8006 +#define GLX_STATIC_GRAY_EXT 0x8007 +#define GLX_TRANSPARENT_RGB_EXT 0x8008 +#define GLX_TRANSPARENT_INDEX_EXT 0x8009 +#endif + +#ifndef GLX_SGI_swap_control +#endif + +#ifndef GLX_SGI_video_sync +#endif + +#ifndef GLX_SGI_make_current_read +#endif + +#ifndef GLX_SGIX_video_source +#endif + +#ifndef GLX_EXT_visual_rating +#define GLX_VISUAL_CAVEAT_EXT 0x20 +#define GLX_SLOW_VISUAL_EXT 0x8001 +#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D +/* reuse GLX_NONE_EXT */ +#endif + +#ifndef GLX_EXT_import_context +#define GLX_SHARE_CONTEXT_EXT 0x800A +#define GLX_VISUAL_ID_EXT 0x800B +#define GLX_SCREEN_EXT 0x800C +#endif + +#ifndef GLX_SGIX_fbconfig +#define GLX_WINDOW_BIT_SGIX 0x00000001 +#define GLX_PIXMAP_BIT_SGIX 0x00000002 +#define GLX_RGBA_BIT_SGIX 0x00000001 +#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 +#define GLX_DRAWABLE_TYPE_SGIX 0x8010 +#define GLX_RENDER_TYPE_SGIX 0x8011 +#define GLX_X_RENDERABLE_SGIX 0x8012 +#define GLX_FBCONFIG_ID_SGIX 0x8013 +#define GLX_RGBA_TYPE_SGIX 0x8014 +#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 +/* reuse GLX_SCREEN_EXT */ +#endif + +#ifndef GLX_SGIX_pbuffer +#define GLX_PBUFFER_BIT_SGIX 0x00000004 +#define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 +#define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 +#define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 +#define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 +#define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 +#define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 +#define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 +#define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 +#define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 +#define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 +#define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 +#define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 +#define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A +#define GLX_PRESERVED_CONTENTS_SGIX 0x801B +#define GLX_LARGEST_PBUFFER_SGIX 0x801C +#define GLX_WIDTH_SGIX 0x801D +#define GLX_HEIGHT_SGIX 0x801E +#define GLX_EVENT_MASK_SGIX 0x801F +#define GLX_DAMAGED_SGIX 0x8020 +#define GLX_SAVED_SGIX 0x8021 +#define GLX_WINDOW_SGIX 0x8022 +#define GLX_PBUFFER_SGIX 0x8023 +#endif + +#ifndef GLX_SGI_cushion +#endif + +#ifndef GLX_SGIX_video_resize +#define GLX_SYNC_FRAME_SGIX 0x00000000 +#define GLX_SYNC_SWAP_SGIX 0x00000001 +#endif + +#ifndef GLX_SGIX_dmbuffer +#define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024 +#endif + +#ifndef GLX_SGIX_swap_group +#endif + +#ifndef GLX_SGIX_swap_barrier +#endif + +#ifndef GLX_SGIS_blended_overlay +#define GLX_BLENDED_RGBA_SGIS 0x8025 +#endif + +#ifndef GLX_SGIS_shared_multisample +#define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 +#define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 +#endif + +#ifndef GLX_SUN_get_transparent_index +#endif + +#ifndef GLX_3DFX_multisample +#define GLX_SAMPLE_BUFFERS_3DFX 0x8050 +#define GLX_SAMPLES_3DFX 0x8051 +#endif + +#ifndef GLX_MESA_copy_sub_buffer +#endif + +#ifndef GLX_MESA_pixmap_colormap +#endif + +#ifndef GLX_MESA_release_buffers +#endif + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_3DFX_WINDOW_MODE_MESA 0x1 +#define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 +#endif + +#ifndef GLX_SGIX_visual_select_group +#define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 +#endif + +#ifndef GLX_OML_swap_method +#define GLX_SWAP_METHOD_OML 0x8060 +#define GLX_SWAP_EXCHANGE_OML 0x8061 +#define GLX_SWAP_COPY_OML 0x8062 +#define GLX_SWAP_UNDEFINED_OML 0x8063 +#endif + +#ifndef GLX_OML_sync_control +#endif + +#ifndef GLX_NV_float_buffer +#define GLX_FLOAT_COMPONENTS_NV 0x20B0 +#endif + +#ifndef GLX_SGIX_hyperpipe +#define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 +#define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 +#define GLX_BAD_HYPERPIPE_SGIX 92 +#define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 +#define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 +#define GLX_PIPE_RECT_SGIX 0x00000001 +#define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 +#define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 +#define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 +#define GLX_HYPERPIPE_ID_SGIX 0x8030 +#endif + +#ifndef GLX_MESA_agp_offset +#endif + + +/*************************************************************/ + +#ifndef GLX_ARB_get_proc_address +typedef void (*__GLXextFuncPtr)(void); +#endif + +#ifndef GLX_SGIX_video_source +typedef XID GLXVideoSourceSGIX; +#endif + +#ifndef GLX_SGIX_fbconfig +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +#endif + +#ifndef GLX_SGIX_pbuffer +typedef XID GLXPbufferSGIX; +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came for SendEvent request */ + Display *display; /* display the event was read from */ + GLXDrawable drawable; /* i.d. of Drawable */ + int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */ + int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */ + unsigned int mask; /* mask indicating which buffers are affected*/ + int x, y; + int width, height; + int count; /* if nonzero, at least this many more */ +} GLXBufferClobberEventSGIX; +#endif + +/* Define int32_t and int64_t types for UST/MSC */ +/* (as used in the GLX_OML_sync_control extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined( __VMS ) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +#else +#warn "int32_t and int64_t are undefined!" +#endif + +#ifndef GLX_VERSION_1_3 +#define GLX_VERSION_1_3 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXFBConfig * glXGetFBConfigs (Display *, int, int *); +extern GLXFBConfig * glXChooseFBConfig (Display *, int, const int *, int *); +extern int glXGetFBConfigAttrib (Display *, GLXFBConfig, int, int *); +extern XVisualInfo * glXGetVisualFromFBConfig (Display *, GLXFBConfig); +extern GLXWindow glXCreateWindow (Display *, GLXFBConfig, Window, const int *); +extern void glXDestroyWindow (Display *, GLXWindow); +extern GLXPixmap glXCreatePixmap (Display *, GLXFBConfig, Pixmap, const int *); +extern void glXDestroyPixmap (Display *, GLXPixmap); +extern GLXPbuffer glXCreatePbuffer (Display *, GLXFBConfig, const int *); +extern void glXDestroyPbuffer (Display *, GLXPbuffer); +extern void glXQueryDrawable (Display *, GLXDrawable, int, unsigned int *); +extern GLXContext glXCreateNewContext (Display *, GLXFBConfig, int, GLXContext, Bool); +extern Bool glXMakeContextCurrent (Display *, GLXDrawable, GLXDrawable, GLXContext); +extern GLXDrawable glXGetCurrentReadDrawable (void); +extern Display * glXGetCurrentDisplay (void); +extern int glXQueryContext (Display *, GLXContext, int, int *); +extern void glXSelectEvent (Display *, GLXDrawable, unsigned long); +extern void glXGetSelectedEvent (Display *, GLXDrawable, unsigned long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXFBConfig * ( * PFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements); +typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef int ( * PFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value); +typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config); +typedef GLXWindow ( * PFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); +typedef void ( * PFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win); +typedef GLXPixmap ( * PFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap); +typedef GLXPbuffer ( * PFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list); +typedef void ( * PFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf); +typedef void ( * PFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); +typedef GLXContext ( * PFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef Bool ( * PFNGLXMAKECONTEXTCURRENTPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLEPROC) (void); +typedef Display * ( * PFNGLXGETCURRENTDISPLAYPROC) (void); +typedef int ( * PFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value); +typedef void ( * PFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask); +typedef void ( * PFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask); +#endif + +#ifndef GLX_VERSION_1_4 +#define GLX_VERSION_1_4 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern __GLXextFuncPtr glXGetProcAddress (const GLubyte *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName); +#endif + +#ifndef GLX_ARB_get_proc_address +#define GLX_ARB_get_proc_address 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef __GLXextFuncPtr ( * PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); +#endif + +#ifndef GLX_ARB_multisample +#define GLX_ARB_multisample 1 +#endif + +#ifndef GLX_ARB_fbconfig_float +#define GLX_ARB_fbconfig_float 1 +#endif + +#ifndef GLX_SGIS_multisample +#define GLX_SGIS_multisample 1 +#endif + +#ifndef GLX_EXT_visual_info +#define GLX_EXT_visual_info 1 +#endif + +#ifndef GLX_SGI_swap_control +#define GLX_SGI_swap_control 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXSwapIntervalSGI (int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval); +#endif + +#ifndef GLX_SGI_video_sync +#define GLX_SGI_video_sync 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXGetVideoSyncSGI (unsigned int *); +extern int glXWaitVideoSyncSGI (int, int, unsigned int *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXGETVIDEOSYNCSGIPROC) (unsigned int *count); +typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count); +#endif + +#ifndef GLX_SGI_make_current_read +#define GLX_SGI_make_current_read 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXMakeCurrentReadSGI (Display *, GLXDrawable, GLXDrawable, GLXContext); +extern GLXDrawable glXGetCurrentReadDrawableSGI (void); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXMAKECURRENTREADSGIPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef GLXDrawable ( * PFNGLXGETCURRENTREADDRAWABLESGIPROC) (void); +#endif + +#ifndef GLX_SGIX_video_source +#define GLX_SGIX_video_source 1 +#ifdef _VL_H +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX (Display *, int, VLServer, VLPath, int, VLNode); +extern void glXDestroyGLXVideoSourceSGIX (Display *, GLXVideoSourceSGIX); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXVideoSourceSGIX ( * PFNGLXCREATEGLXVIDEOSOURCESGIXPROC) (Display *display, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); +typedef void ( * PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC) (Display *dpy, GLXVideoSourceSGIX glxvideosource); +#endif /* _VL_H */ +#endif + +#ifndef GLX_EXT_visual_rating +#define GLX_EXT_visual_rating 1 +#endif + +#ifndef GLX_EXT_import_context +#define GLX_EXT_import_context 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Display * glXGetCurrentDisplayEXT (void); +extern int glXQueryContextInfoEXT (Display *, GLXContext, int, int *); +extern GLXContextID glXGetContextIDEXT (const GLXContext); +extern GLXContext glXImportContextEXT (Display *, GLXContextID); +extern void glXFreeContextEXT (Display *, GLXContext); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Display * ( * PFNGLXGETCURRENTDISPLAYEXTPROC) (void); +typedef int ( * PFNGLXQUERYCONTEXTINFOEXTPROC) (Display *dpy, GLXContext context, int attribute, int *value); +typedef GLXContextID ( * PFNGLXGETCONTEXTIDEXTPROC) (const GLXContext context); +typedef GLXContext ( * PFNGLXIMPORTCONTEXTEXTPROC) (Display *dpy, GLXContextID contextID); +typedef void ( * PFNGLXFREECONTEXTEXTPROC) (Display *dpy, GLXContext context); +#endif + +#ifndef GLX_SGIX_fbconfig +#define GLX_SGIX_fbconfig 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXGetFBConfigAttribSGIX (Display *, GLXFBConfigSGIX, int, int *); +extern GLXFBConfigSGIX * glXChooseFBConfigSGIX (Display *, int, int *, int *); +extern GLXPixmap glXCreateGLXPixmapWithConfigSGIX (Display *, GLXFBConfigSGIX, Pixmap); +extern GLXContext glXCreateContextWithConfigSGIX (Display *, GLXFBConfigSGIX, int, GLXContext, Bool); +extern XVisualInfo * glXGetVisualFromFBConfigSGIX (Display *, GLXFBConfigSGIX); +extern GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX (Display *, XVisualInfo *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); +typedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements); +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); +typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); +typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config); +typedef GLXFBConfigSGIX ( * PFNGLXGETFBCONFIGFROMVISUALSGIXPROC) (Display *dpy, XVisualInfo *vis); +#endif + +#ifndef GLX_SGIX_pbuffer +#define GLX_SGIX_pbuffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXPbufferSGIX glXCreateGLXPbufferSGIX (Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); +extern void glXDestroyGLXPbufferSGIX (Display *, GLXPbufferSGIX); +extern int glXQueryGLXPbufferSGIX (Display *, GLXPbufferSGIX, int, unsigned int *); +extern void glXSelectEventSGIX (Display *, GLXDrawable, unsigned long); +extern void glXGetSelectedEventSGIX (Display *, GLXDrawable, unsigned long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXPbufferSGIX ( * PFNGLXCREATEGLXPBUFFERSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); +typedef void ( * PFNGLXDESTROYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf); +typedef int ( * PFNGLXQUERYGLXPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); +typedef void ( * PFNGLXSELECTEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long mask); +typedef void ( * PFNGLXGETSELECTEDEVENTSGIXPROC) (Display *dpy, GLXDrawable drawable, unsigned long *mask); +#endif + +#ifndef GLX_SGI_cushion +#define GLX_SGI_cushion 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXCushionSGI (Display *, Window, float); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXCUSHIONSGIPROC) (Display *dpy, Window window, float cushion); +#endif + +#ifndef GLX_SGIX_video_resize +#define GLX_SGIX_video_resize 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern int glXBindChannelToWindowSGIX (Display *, int, int, Window); +extern int glXChannelRectSGIX (Display *, int, int, int, int, int, int); +extern int glXQueryChannelRectSGIX (Display *, int, int, int *, int *, int *, int *); +extern int glXQueryChannelDeltasSGIX (Display *, int, int, int *, int *, int *, int *); +extern int glXChannelRectSyncSGIX (Display *, int, int, GLenum); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef int ( * PFNGLXBINDCHANNELTOWINDOWSGIXPROC) (Display *display, int screen, int channel, Window window); +typedef int ( * PFNGLXCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int x, int y, int w, int h); +typedef int ( * PFNGLXQUERYCHANNELRECTSGIXPROC) (Display *display, int screen, int channel, int *dx, int *dy, int *dw, int *dh); +typedef int ( * PFNGLXQUERYCHANNELDELTASSGIXPROC) (Display *display, int screen, int channel, int *x, int *y, int *w, int *h); +typedef int ( * PFNGLXCHANNELRECTSYNCSGIXPROC) (Display *display, int screen, int channel, GLenum synctype); +#endif + +#ifndef GLX_SGIX_dmbuffer +#define GLX_SGIX_dmbuffer 1 +#ifdef _DM_BUFFER_H_ +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXAssociateDMPbufferSGIX (Display *, GLXPbufferSGIX, DMparams *, DMbuffer); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXASSOCIATEDMPBUFFERSGIXPROC) (Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); +#endif /* _DM_BUFFER_H_ */ +#endif + +#ifndef GLX_SGIX_swap_group +#define GLX_SGIX_swap_group 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXJoinSwapGroupSGIX (Display *, GLXDrawable, GLXDrawable); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXJOINSWAPGROUPSGIXPROC) (Display *dpy, GLXDrawable drawable, GLXDrawable member); +#endif + +#ifndef GLX_SGIX_swap_barrier +#define GLX_SGIX_swap_barrier 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXBindSwapBarrierSGIX (Display *, GLXDrawable, int); +extern Bool glXQueryMaxSwapBarriersSGIX (Display *, int, int *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXBINDSWAPBARRIERSGIXPROC) (Display *dpy, GLXDrawable drawable, int barrier); +typedef Bool ( * PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC) (Display *dpy, int screen, int *max); +#endif + +#ifndef GLX_SUN_get_transparent_index +#define GLX_SUN_get_transparent_index 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Status glXGetTransparentIndexSUN (Display *, Window, Window, long *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Status ( * PFNGLXGETTRANSPARENTINDEXSUNPROC) (Display *dpy, Window overlay, Window underlay, long *pTransparentIndex); +#endif + +#ifndef GLX_MESA_copy_sub_buffer +#define GLX_MESA_copy_sub_buffer 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern void glXCopySubBufferMESA (Display *, GLXDrawable, int, int, int, int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef void ( * PFNGLXCOPYSUBBUFFERMESAPROC) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); +#endif + +#ifndef GLX_MESA_pixmap_colormap +#define GLX_MESA_pixmap_colormap 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXPixmap glXCreateGLXPixmapMESA (Display *, XVisualInfo *, Pixmap, Colormap); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXPixmap ( * PFNGLXCREATEGLXPIXMAPMESAPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap); +#endif + +#ifndef GLX_MESA_release_buffers +#define GLX_MESA_release_buffers 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXReleaseBuffersMESA (Display *, GLXDrawable); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXRELEASEBUFFERSMESAPROC) (Display *dpy, GLXDrawable drawable); +#endif + +#ifndef GLX_MESA_set_3dfx_mode +#define GLX_MESA_set_3dfx_mode 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXSet3DfxModeMESA (int); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXSET3DFXMODEMESAPROC) (int mode); +#endif + +#ifndef GLX_SGIX_visual_select_group +#define GLX_SGIX_visual_select_group 1 +#endif + +#ifndef GLX_OML_swap_method +#define GLX_OML_swap_method 1 +#endif + +#ifndef GLX_OML_sync_control +#define GLX_OML_sync_control 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern Bool glXGetSyncValuesOML (Display *, GLXDrawable, int64_t *, int64_t *, int64_t *); +extern Bool glXGetMscRateOML (Display *, GLXDrawable, int32_t *, int32_t *); +extern int64_t glXSwapBuffersMscOML (Display *, GLXDrawable, int64_t, int64_t, int64_t); +extern Bool glXWaitForMscOML (Display *, GLXDrawable, int64_t, int64_t, int64_t, int64_t *, int64_t *, int64_t *); +extern Bool glXWaitForSbcOML (Display *, GLXDrawable, int64_t, int64_t *, int64_t *, int64_t *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef Bool ( * PFNGLXGETSYNCVALUESOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t *ust, int64_t *msc, int64_t *sbc); +typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); +typedef int64_t ( * PFNGLXSWAPBUFFERSMSCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder); +typedef Bool ( * PFNGLXWAITFORMSCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc); +typedef Bool ( * PFNGLXWAITFORSBCOMLPROC) (Display *dpy, GLXDrawable drawable, int64_t target_sbc, int64_t *ust, int64_t *msc, int64_t *sbc); +#endif + +#ifndef GLX_NV_float_buffer +#define GLX_NV_float_buffer 1 +#endif + +#ifndef GLX_SGIX_hyperpipe +#define GLX_SGIX_hyperpipe 1 + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int networkId; +} GLXHyperpipeNetworkSGIX; + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int channel; + unsigned int + participationType; + int timeSlice; +} GLXHyperpipeConfigSGIX; + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int srcXOrigin, srcYOrigin, srcWidth, srcHeight; + int destXOrigin, destYOrigin, destWidth, destHeight; +} GLXPipeRect; + +typedef struct { + char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; + int XOrigin, YOrigin, maxHeight, maxWidth; +} GLXPipeRectLimits; + +#ifdef GLX_GLXEXT_PROTOTYPES +extern GLXHyperpipeNetworkSGIX * glXQueryHyperpipeNetworkSGIX (Display *, int *); +extern int glXHyperpipeConfigSGIX (Display *, int, int, GLXHyperpipeConfigSGIX *, int *); +extern GLXHyperpipeConfigSGIX * glXQueryHyperpipeConfigSGIX (Display *, int, int *); +extern int glXDestroyHyperpipeConfigSGIX (Display *, int); +extern int glXBindHyperpipeSGIX (Display *, int); +extern int glXQueryHyperpipeBestAttribSGIX (Display *, int, int, int, void *, void *); +extern int glXHyperpipeAttribSGIX (Display *, int, int, int, void *); +extern int glXQueryHyperpipeAttribSGIX (Display *, int, int, int, void *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef GLXHyperpipeNetworkSGIX * ( * PFNGLXQUERYHYPERPIPENETWORKSGIXPROC) (Display *dpy, int *npipes); +typedef int ( * PFNGLXHYPERPIPECONFIGSGIXPROC) (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId); +typedef GLXHyperpipeConfigSGIX * ( * PFNGLXQUERYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId, int *npipes); +typedef int ( * PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXBINDHYPERPIPESGIXPROC) (Display *dpy, int hpId); +typedef int ( * PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList); +typedef int ( * PFNGLXHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *attribList); +typedef int ( * PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC) (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList); +#endif + +#ifndef GLX_MESA_agp_offset +#define GLX_MESA_agp_offset 1 +#ifdef GLX_GLXEXT_PROTOTYPES +extern unsigned int glXGetAGPOffsetMESA (const void *); +#endif /* GLX_GLXEXT_PROTOTYPES */ +typedef unsigned int ( * PFNGLXGETAGPOFFSETMESAPROC) (const void *pointer); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Utilities/ParseOGLExt/headers/wglext.h b/Utilities/ParseOGLExt/headers/wglext.h new file mode 100644 index 0000000..9dcee14 --- /dev/null +++ b/Utilities/ParseOGLExt/headers/wglext.h @@ -0,0 +1,631 @@ +#ifndef __wglext_h_ +#define __wglext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +/*************************************************************/ + +/* Header file version number */ +/* wglext.h last updated 2005/01/07 */ +/* Current version at http://oss.sgi.com/projects/ogl-sample/registry/ */ +#define WGL_WGLEXT_VERSION 6 + +#ifndef WGL_ARB_buffer_region +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#endif + +#ifndef WGL_ARB_multisample +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 +#endif + +#ifndef WGL_ARB_extensions_string +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 +#endif + +#ifndef WGL_ARB_pixel_format_float +#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 +#endif + +#ifndef WGL_EXT_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif + +#ifndef WGL_I3D_digital_video_control +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 +#endif + +#ifndef WGL_I3D_gamma +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F +#endif + +#ifndef WGL_I3D_genlock +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C +#endif + +#ifndef WGL_I3D_image_buffer +#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 +#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 +#endif + +#ifndef WGL_I3D_swap_frame_lock +#endif + +#ifndef WGL_NV_render_depth_texture +#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 +#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 +#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 +#define WGL_DEPTH_COMPONENT_NV 0x20A7 +#endif + +#ifndef WGL_NV_render_texture_rectangle +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 +#define WGL_TEXTURE_RECTANGLE_NV 0x20A2 +#endif + +#ifndef WGL_ATI_pixel_format_float +#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 +#endif + +#ifndef WGL_NV_float_buffer +#define WGL_FLOAT_COMPONENTS_NV 0x20B0 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 +#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 +#define WGL_TEXTURE_FLOAT_R_NV 0x20B5 +#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 +#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 +#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 +#endif + + +/*************************************************************/ + +#ifndef WGL_ARB_pbuffer +DECLARE_HANDLE(HPBUFFERARB); +#endif +#ifndef WGL_EXT_pbuffer +DECLARE_HANDLE(HPBUFFEREXT); +#endif + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); +extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); +extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); +extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +#endif + +#ifndef WGL_ARB_multisample +#define WGL_ARB_multisample 1 +#endif + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringARB (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCARB (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); +extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); +extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); +extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglBindTexImageARB (HPBUFFERARB, int); +extern BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB, int); +extern BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList); +#endif + +#ifndef WGL_ARB_pixel_format_float +#define WGL_ARB_pixel_format_float 1 +#endif + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); +extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); +extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); +extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +#endif + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); +#endif + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); +extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); +extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); +extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglSwapIntervalEXT (int); +extern int WINAPI wglGetSwapIntervalEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_EXT_depth_float 1 +#endif + +#ifndef WGL_NV_vertex_array_range +#define WGL_NV_vertex_array_range 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern void* WINAPI wglAllocateMemoryNV (GLsizei, GLfloat, GLfloat, GLfloat); +extern void WINAPI wglFreeMemoryNV (void *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef void* (WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); +typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_3DFX_multisample 1 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_EXT_multisample 1 +#endif + +#ifndef WGL_OML_sync_control +#define WGL_OML_sync_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetSyncValuesOML (HDC, INT64 *, INT64 *, INT64 *); +extern BOOL WINAPI wglGetMscRateOML (HDC, INT32 *, INT32 *); +extern INT64 WINAPI wglSwapBuffersMscOML (HDC, INT64, INT64, INT64); +extern INT64 WINAPI wglSwapLayerBuffersMscOML (HDC, int, INT64, INT64, INT64); +extern BOOL WINAPI wglWaitForMscOML (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *); +extern BOOL WINAPI wglWaitForSbcOML (HDC, INT64, INT64 *, INT64 *, INT64 *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); +typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); +typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); +typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); +#endif + +#ifndef WGL_I3D_digital_video_control +#define WGL_I3D_digital_video_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC, int, int *); +extern BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC, int, const int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); +typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); +#endif + +#ifndef WGL_I3D_gamma +#define WGL_I3D_gamma 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetGammaTableParametersI3D (HDC, int, int *); +extern BOOL WINAPI wglSetGammaTableParametersI3D (HDC, int, const int *); +extern BOOL WINAPI wglGetGammaTableI3D (HDC, int, USHORT *, USHORT *, USHORT *); +extern BOOL WINAPI wglSetGammaTableI3D (HDC, int, const USHORT *, const USHORT *, const USHORT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); +typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); +typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); +#endif + +#ifndef WGL_I3D_genlock +#define WGL_I3D_genlock 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnableGenlockI3D (HDC); +extern BOOL WINAPI wglDisableGenlockI3D (HDC); +extern BOOL WINAPI wglIsEnabledGenlockI3D (HDC, BOOL *); +extern BOOL WINAPI wglGenlockSourceI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSourceEdgeI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSampleRateI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSampleRateI3D (HDC, UINT *); +extern BOOL WINAPI wglGenlockSourceDelayI3D (HDC, UINT); +extern BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC, UINT *); +extern BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC, UINT *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); +typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge); +typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate); +typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); +typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay); +typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); +#endif + +#ifndef WGL_I3D_image_buffer +#define WGL_I3D_image_buffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern LPVOID WINAPI wglCreateImageBufferI3D (HDC, DWORD, UINT); +extern BOOL WINAPI wglDestroyImageBufferI3D (HDC, LPVOID); +extern BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT); +extern BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC, const LPVOID *, UINT); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); +typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); +typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); +typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count); +#endif + +#ifndef WGL_I3D_swap_frame_lock +#define WGL_I3D_swap_frame_lock 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglEnableFrameLockI3D (void); +extern BOOL WINAPI wglDisableFrameLockI3D (void); +extern BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *); +extern BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag); +#endif + +#ifndef WGL_I3D_swap_frame_usage +#define WGL_I3D_swap_frame_usage 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetFrameUsageI3D (float *); +extern BOOL WINAPI wglBeginFrameTrackingI3D (void); +extern BOOL WINAPI wglEndFrameTrackingI3D (void); +extern BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *, DWORD *, float *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage); +typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); +typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); +#endif + +#ifndef WGL_ATI_pixel_format_float +#define WGL_ATI_pixel_format_float 1 +#endif + +#ifndef WGL_NV_float_buffer +#define WGL_NV_float_buffer 1 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Utilities/Release/VTKInstall.bmp b/Utilities/Release/VTKInstall.bmp new file mode 100644 index 0000000..d476d10 Binary files /dev/null and b/Utilities/Release/VTKInstall.bmp differ diff --git a/Utilities/Rpm/rpm-linux.patch b/Utilities/Rpm/rpm-linux.patch new file mode 100644 index 0000000..e12f5b5 --- /dev/null +++ b/Utilities/Rpm/rpm-linux.patch @@ -0,0 +1,49 @@ +diff -uNr vtk-orig/user.make vtk/user.make +--- vtk-orig/user.make Thu Nov 13 09:25:29 1997 ++++ vtk/user.make Wed Jul 12 12:20:03 2000 +@@ -2,22 +2,22 @@ + # by configure in system.make. At a minimum you should set + # the following Tcl/Tk values if you are planning to use Tcl/Tk + +-TCL_INCLUDE=-I/home/ausable/software/src/tcl7.6/tcl7.6/generic +-TCL_LIB=/common/software/tcl7.6/sun4/5.4/lib/libtcl7.6.a ++TCL_INCLUDE=-I/usr/include ++TCL_LIB=-ltcl + +-TK_INCLUDE=-I/home/ausable/software/src/tcl7.6/tk4.2/generic +-TK_LIB=/common/software/tk4.2/sun4/5.4/lib/libtk4.2.a ++TK_INCLUDE=-I/usr/include ++TK_LIB=-ltk + +-MESA_INCLUDE=-I/home/martink/storage/Mesa-1.2.6/include +-MESA_LIB=/home/martink/storage/Mesa-1.2.6/lib-sun4-solaris/libMesaGL.a ++# MESA_INCLUDE=-I/home/martink/storage/Mesa-1.2.6/include ++MESA_LIB=-lMesaGL + + # for python you must set this +-PYTHON_INCLUDES=-I/home/schroede/montnaro/Python-1.4/Include ++PYTHON_INCLUDES=-I/usr/include/python1.5 + + # Add additional CFLAGS and CXXFLAGS for compilation + # uncomment the following two lines to set your own flags +-#USER_CFLAGS = +-#USER_CXXFLAGS = ++USER_CFLAGS = -O ++USER_CXXFLAGS = -O + + # if you want to try the java support you'll need to set the following + # variables to match your environment and uncomment them +@@ -28,6 +28,13 @@ + #JAVAH=${JDKHOME}/bin/javah + #JAVA_INCLUDES=-I${JDKHOME}/include -I${JDKHOME}/include/solaris + #JAVA_CXX_LIB=/common/software/g++-2.7.1/sun4/5.4/lib/libiberty.a /common/software/g++-2.7.1/sun4/5.4/lib/libstdc++.a /common/software/g++-2.7.1/sun4/5.4/lib/gcc-lib/sparc-sun-solaris2.4/2.7.1/libgcc.a ++ ++JDKHOME=/usr/local/jdk1.2.2/ ++JAVA_CLASS_HOME=../java/ ++JAVAC=${JDKHOME}/bin/javac -classpath ${JAVA_CLASS_HOME} ++JAR=${JDKHOME}/bin/jar ++JAVAH=${JDKHOME}/bin/javah ++JAVA_INCLUDES=-I${JDKHOME}/include -I${JDKHOME}/include/linux + + + diff --git a/Utilities/Rpm/vtk.nightly.spec.in b/Utilities/Rpm/vtk.nightly.spec.in new file mode 100644 index 0000000..43070f7 --- /dev/null +++ b/Utilities/Rpm/vtk.nightly.spec.in @@ -0,0 +1,327 @@ +Summary: The Visualization Toolkit - A high level 3D visualization library +Name: vtk +Version: 3.1 +Release: @BUILD@N +Copyright: Distributable +Group: Development/Libraries +Source: ftp://vtk.scorec.rpi.edu/pub/vtk.tar.gz +URL: http://www.kitware.com/vtk.html +Patch: vtk-linux.patch +#BuildPrereq: jdk, tk, python, python-devel, tcl +BuildPrereq: tk, python, python-devel, tcl + +Buildroot: /usr/src/local/BUILD/vtk-root +Prefix: /usr + +%description + VTK - the Visualization Toolkit is an object oriented, high +level library that allows one to easily write C++ programs, Tcl, +Python and Java scripts that do 3D visualization. This package +provides the shared libraries needed to run C++ programs that use VTK. +The patented and contributed classes are also compiled. To compile +C++ code that uses VTK you have to install vtk-devel. + + VTK enables users to concentrate on their work by providing a +large number of excellent and feature packed high level functions that +do visualization. The library needs OpenGL to render the graphics and +for Linux machines Mesa is necessary. The terms/copyright can be read +in /usr/doc/vtk-%{version}-%{release}/README.html. VTK-Linux-HOWTO has +information about using vtk, getting documentataion or help and +instructions on building VTK. The patented classes (few in number) are +not to be used commercially. Please read the files README.patented-dir +and README.patented-classes. This package is relocatable. + +%changelog +* Thu Dec 1 2000 Daniel Blezek +- Moved from /usr/local to /usr +- Checking into CVS +* Thu Nov 23 2000 David Gobbi +- put vtkpython.pth in /usr/lib/pythonX.X/site-packages +- changed prefix to /usr/local, set INSTALL_ROOT to RPM_BUILD_ROOT +- added /sbin/ldconfig to %post/%postun for each of tcl, python, java +* Wed Jul 12 2000 Daniel Blezek : Removing the need for a patch by changing user.make +* Wed Dec 8 1999 Daniel Blezek : adapted Aleksey's spec file to nightly releases +* Wed Oct 20 1999 Aleksey Nogin +[vtk-2.4-1] +- Upgraded to vtk-2.4 +- Made the SRPM a little more portable by removing Prabhu's "hardwired" paths +- Added tk sources to SRPM so that we do have access to tk header files. + +* Fri Mar 26 1999 Prabhu Ramachandran +- I am the current maintainer + +# vtk-devel + +%package devel +Summary: VTK header files for building C++ code. +Requires: vtk +Group: Development/Libraries +Prefix: /usr + +%description devel + This provides the VTK header files required to compile C++ +programs that use VTK to do 3D visualisation. + +# vtk-tcl + +%package tcl +Summary: Tcl bindings for VTK. +Group: X11/Libraries +Prefix: /usr +# Requires: tk = %{tk_version} + +%description tcl + VTK - the Visualization Toolkit is an object oriented, high level +library that allows one to easily write C++ programs, Tcl, Python and Java +scripts that do 3D visualization. This package provides the shared +libraries that enable one to use VTK via Tcl scripts. This version also +provides the vtkTkRenderWindow class. The patented and contributed classes +are also compiled. This package does not require the vtk package to be +installed. The library needs OpenGL to render the graphics and for Linux +machines Mesa is necessary. + + The terms/copyright can be read in usr/doc/vtk-tcl-%{version}-%{release}/README.html. VTK-Linux-HOWTO has information about using vtk, getting +documentataion or help and instructions on building VTK. The patented +classes (few in number) are not to be used commercially. Please read the +files README.patented-dir and README.patented-classes. This package is +relocatable. + +# vtk-python + +%package python +Summary: Python bindings for VTK. +Requires: vtk +Group: X11/Libraries +Prefix: /usr + +%description python + This provides the shared libraries that enable one to use VTK from +python scripts. You will need python and vtk installed to use this. +Remember to set your PYTHONPATH variable properly before running your +scripts. + +# vtk-java + +%package java +Summary: Java bindings for VTK. +Group: X11/Libraries +Prefix: /usr + +%description java + VTK - the Visualization Toolkit is an object oriented, high level +library that allows one to easily write C++ programs, Tcl, Python and Java +scripts that do 3D visualization. This package provides the shared +libraries that enable one to use VTK with java scripts. The patented and +contributed classes are also compiled. This package does not require the +vtk package to be installed. The library needs OpenGL to render the +graphics and for Linux machines Mesa is necessary. You will need jdk.. +jdk-1.2pre-2 was used to compile this. Remember to set your CLASSPATH to the +directory that has the java classes. + + The terms/copyright can be read in usr/doc/vtk-java-%{version}-%{release}/README and +README.html. VTK-Linux-HOWTO has information about using vtk, getting +documentataion or help and instructions on building VTK. The patented +classes (few in number) are not to be used commercially. Please read the +files README.patented-dir and README.patented-classes. This package is +relocatable. + +# vtk-examples + +%package examples +Summary: C++, Tcl and Python example programs/scripts for VTK. +Group: Development/Libraries +Prefix: /usr + +%description examples + This package contains all the examples from the VTK source. +To compile the C++ examples you will need to install the vtk-devel +package as well. The Python and Tcl examples can be run with the +corresponding packages (vtk-python, vtk-tcl). + + +%prep + +%setup -n vtk -q +%patch -p1 + +%build + +export CLASSPATH=.:/usr/local/jdk1.2.2:`pwd`/java/classes:`pwd`/java:`pwd`/java/vtk +export PATH=/usr/local/jdk1.2.2/bin:$PATH +export LD_LIBRARY_PATH=`pwd`/common:`pwd`/graphics:`pwd`/patented:`pwd`/imaging:`pwd`/contrib:`pwd`/java + +# Can't build with Mesa, Threads and Java, so dropping Java +# ./configure --with-mesa --with-shared --with-tcl --with-tkwidget --with-python --with-java --with-contrib --with-patented --prefix=/usr + +export CC=cc +export CXX=g++ + +./configure --with-java --with-shared --with-tcl --with-tkwidget --with-python --with-contrib --with-patented --prefix=/usr + +# Setup dir for java compiled classes +mkdir -p `pwd`/java/classes + +export VTK_HOMEDIR=`pwd` +# export MAKE='make -j 2' +make -j 2 +# make + +%install + +# chmod 644 README +cp ./patented/README ./README.patented-dir +echo -e "A list of the patented classes.\n\n" > README.patented-classes +ls ./patented/*.h >> README.patented-classes + +rm -rf $RPM_BUILD_ROOT + +#creating all the directories +install -d $RPM_BUILD_ROOT/usr@VTK_INSTALL_BIN_DIR@ +install -d $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/{contrib/examplesTcl,examplesTcl/frog} +install -d $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/graphics/examples{Cxx,Tcl/RenderMan/Shaders,Python} +install -d $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/imaging/examples{,Cxx,Tcl} +install -d $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/patented/examplesTcl +install -d $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/java/vtk +install -d $RPM_BUILD_ROOT/usr@VTK_INSTALL_INCLUDE_DIR@ + +# this installs the libs and the vtk tcl interpretor + +make INSTALL_ROOT=$RPM_BUILD_ROOT install +# make prefix=/usr install + +#stripping all the shared libraries and the vtk interpreter +strip $RPM_BUILD_ROOT/usr@VTK_INSTALL_BIN_DIR@/vtk +strip $RPM_BUILD_ROOT/usr/lib/lib* + +# this installs all the header files. +install -m 644 ./common/*.h $RPM_BUILD_ROOT/usr@VTK_INSTALL_INCLUDE_DIR@ +install -m 644 ./contrib/*.h $RPM_BUILD_ROOT/usr@VTK_INSTALL_INCLUDE_DIR@ +install -m 644 ./wrap/*.h $RPM_BUILD_ROOT/usr@VTK_INSTALL_INCLUDE_DIR@ +install -m 644 ./graphics/*.h $RPM_BUILD_ROOT/usr@VTK_INSTALL_INCLUDE_DIR@ +install -m 644 ./imaging/*.h $RPM_BUILD_ROOT/usr@VTK_INSTALL_INCLUDE_DIR@ +install -m 644 ./patented/*.h $RPM_BUILD_ROOT/usr@VTK_INSTALL_INCLUDE_DIR@ + +#installing all the examples... + +install -m 644 ./contrib/examplesTcl/*.tcl $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/contrib/examplesTcl/ + +install -m 644 ./examplesTcl/*.tcl $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/examplesTcl/ + +install -m 644 ./examplesTcl/frog/*.tcl $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/examplesTcl/frog + +install -m 644 ./graphics/examplesCxx/*.cxx $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/graphics/examplesCxx/ +install -m 644 ./graphics/examplesCxx/Makefile* $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/graphics/examplesCxx/ +install -m 644 ./graphics/examplesPython/*.py $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/graphics/examplesPython/ +install -m 644 ./graphics/examplesTcl/{*.tcl,*.ppm} $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/graphics/examplesTcl/ +install -m 644 ./graphics/examplesTcl/RenderMan/{*.so,*.tcl} $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/graphics/examplesTcl/RenderMan/ +install -m 644 ./graphics/examplesTcl/RenderMan/Shaders/*.sl $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/graphics/examplesTcl/RenderMan/Shaders + +# install -m 644 ./imaging/examples/* $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/imaging/examples/ +install -m 644 ./imaging/examplesTcl/*.tcl $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/imaging/examplesTcl/ +install -m 644 ./imaging/examplesCxx/*.cxx $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/imaging/examplesCxx/ + +install -m 644 ./patented/examplesTcl/*.tcl $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/patented/examplesTcl/ + +# installing java classes + +install -m 644 ./java/vtk.jar $RPM_BUILD_ROOT/usr@VTK_INSTALL_LIB_DIR@/ + +%post +# Check for /usr/lib in /etc/ld.so.conf... +if grep "/usr/lib" /etc/ld.so.conf > /dev/null +then + true +else + echo "/usr/lib" >> /etc/ld.so.conf +fi +/sbin/ldconfig + +%post tcl +/sbin/ldconfig + +%post python +/sbin/ldconfig + +%post java +/sbin/ldconfig + + +%postun +/sbin/ldconfig + +%postun tcl +/sbin/ldconfig + +%postun python +/sbin/ldconfig + +%postun java +/sbin/ldconfig + + + +%files +%attr(755, root, root) /usr/lib/libVTKCommon.so +%attr(755, root, root) /usr/lib/libVTKContrib.so +%attr(755, root, root) /usr/lib/libVTKGraphics.so +%attr(755, root, root) /usr/lib/libVTKImaging.so +%attr(755, root, root) /usr/lib/libVTKPatented.so + +%attr(-, root, root) %doc README.html VTK-Linux-HOWTO README.patented-dir +# %attr(644, root, root) %doc README.patented-classes README vtkLogo.jpg +%attr(644, root, root) %doc README.patented-classes vtkLogo.jpg + +%files devel +%attr(644, root, root) /usr@VTK_INSTALL_INCLUDE_DIR@/ + +%files tcl +%attr(755, root, root) /usr/lib/libVTKCommonTcl.so +%attr(755, root, root) /usr/lib/libVTKContribTcl.so +%attr(755, root, root) /usr/lib/libVTKGraphicsTcl.so +%attr(755, root, root) /usr/lib/libVTKImagingTcl.so +%attr(755, root, root) /usr/lib/libVTKPatentedTcl.so +%attr(755, root, root) /usr@VTK_INSTALL_BIN_DIR@/vtk + +%attr(-, root, root) %doc README.html VTK-Linux-HOWTO README.patented-dir +# %attr(644, root, root) %doc README.patented-classes README vtkLogo.jpg +%attr(644, root, root) %doc README.patented-classes vtkLogo.jpg + + +%files python +%attr(755, root, root) /usr/lib/libVTKCommonPython.so +%attr(755, root, root) /usr/lib/libVTKContribPython.so +%attr(755, root, root) /usr/lib/libVTKGraphicsPython.so +%attr(755, root, root) /usr/lib/libVTKImagingPython.so +%attr(755, root, root) /usr/lib/libVTKPatentedPython.so +%attr(755, root, root) /usr@VTK_INSTALL_LIB_DIR@TkRenderWidget +%attr(755, root, root) /usr@VTK_INSTALL_LIB_DIR@TkImageWindowWidget +%attr(755, root, root) /usr@VTK_INSTALL_LIB_DIR@TkImageViewerWidget +%attr(-, root, root) /usr@VTK_INSTALL_LIB_DIR@/python/ +%attr(644, root, root) %(python -c "import sys, os; print os.path.join(sys.prefix,'lib','python'+sys.version[0:3],'site-packages','vtkpython.pth')") + + +%files java +%attr(755, root, root) /usr/lib/libVTKCommonJava.so +%attr(755, root, root) /usr/lib/libVTKContribJava.so +%attr(755, root, root) /usr/lib/libVTKGraphicsJava.so +%attr(755, root, root) /usr/lib/libVTKImagingJava.so +%attr(755, root, root) /usr/lib/libVTKPatentedJava.so +%attr(755, root, root) /usr/lib/libvtkJava.so +%attr(-, root, root) /usr@VTK_INSTALL_LIB_DIR@.jar + +# +# %attr(-, root, root) %doc README.html VTK-Linux-HOWTO README.patented-dir +# %attr(644, root, root) %doc README.patented-classes README vtkLogo.jpg + + +%files examples +%attr(-, root, root) /usr@VTK_INSTALL_LIB_DIR@/contrib +%attr(-, root, root) /usr@VTK_INSTALL_LIB_DIR@/examplesTcl +%attr(-, root, root) /usr@VTK_INSTALL_LIB_DIR@/graphics +%attr(-, root, root) /usr@VTK_INSTALL_LIB_DIR@/imaging +%attr(-, root, root) /usr@VTK_INSTALL_LIB_DIR@/patented + + +%clean +rm -rf $RPM_BUILD_ROOT + diff --git a/Utilities/TclTk/.NoDartCoverage b/Utilities/TclTk/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/TclTk/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/TclTk/CMakeLists.txt b/Utilities/TclTk/CMakeLists.txt new file mode 100644 index 0000000..18c70df --- /dev/null +++ b/Utilities/TclTk/CMakeLists.txt @@ -0,0 +1,6 @@ +SUBDIRS(internals lib resources) + +CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/.NoDartCoverage + ${CMAKE_CURRENT_BINARY_DIR}/.NoDartCoverage + COPY_ONLY) diff --git a/Utilities/TclTk/internals/CMakeLists.txt b/Utilities/TclTk/internals/CMakeLists.txt new file mode 100644 index 0000000..3f9a03c --- /dev/null +++ b/Utilities/TclTk/internals/CMakeLists.txt @@ -0,0 +1,9 @@ +IF(TK_INTERNAL_PATH) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + IF("${TK_INTERNAL_PATH}" MATCHES + "${CMAKE_CURRENT_SOURCE_DIR}/tk${TCL_TK_VERSION}") + SUBDIRS(tk${TCL_TK_VERSION}) + ENDIF("${TK_INTERNAL_PATH}" MATCHES + "${CMAKE_CURRENT_SOURCE_DIR}/tk${TCL_TK_VERSION}") +ENDIF(TK_INTERNAL_PATH) diff --git a/Utilities/TclTk/internals/tk8.2/CMakeLists.txt b/Utilities/TclTk/internals/tk8.2/CMakeLists.txt new file mode 100644 index 0000000..5695ea3 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/CMakeLists.txt @@ -0,0 +1,5 @@ +IF(TK_INTERNAL_PATH) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/TclTk/internals/tk8.2 "\\.h$") + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF(TK_INTERNAL_PATH) diff --git a/Utilities/TclTk/internals/tk8.2/tclInt.h b/Utilities/TclTk/internals/tk8.2/tclInt.h new file mode 100644 index 0000000..c4a635d --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tclInt.h @@ -0,0 +1,2163 @@ +/* + * tclInt.h -- + * + * Declarations of things used internally by the Tcl interpreter. + * + * Copyright (c) 1987-1993 The Regents of the University of California. + * Copyright (c) 1993-1997 Lucent Technologies. + * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclInt.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TCLINT +#define _TCLINT + +/* + * Common include files needed by most of the Tcl source files are + * included here, so that system-dependent personalizations for the + * include files only have to be made in once place. This results + * in a few extra includes, but greater modularity. The order of + * the three groups of #includes is important. For example, stdio.h + * is needed by tcl.h, and the _ANSI_ARGS_ declaration in tcl.h is + * needed by stdlib.h in some configurations. + */ + +#include + +#ifndef _TCL +#include "tcl.h" +#endif + +#include +#ifdef NO_LIMITS_H +# include "../compat/limits.h" +#else +# include +#endif +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include +#endif +#ifdef NO_STRING_H +#include "../compat/string.h" +#else +#include +#endif + +#undef TCL_STORAGE_CLASS +#ifdef BUILD_tcl +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# ifdef USE_TCL_STUBS +# define TCL_STORAGE_CLASS +# else +# define TCL_STORAGE_CLASS DLLIMPORT +# endif +#endif + +/* + * The following procedures allow namespaces to be customized to + * support special name resolution rules for commands/variables. + * + */ + +struct Tcl_ResolvedVarInfo; + +typedef Tcl_Var (Tcl_ResolveRuntimeVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, struct Tcl_ResolvedVarInfo *vinfoPtr)); + +typedef void (Tcl_ResolveVarDeleteProc) _ANSI_ARGS_(( + struct Tcl_ResolvedVarInfo *vinfoPtr)); + +/* + * The following structure encapsulates the routines needed to resolve a + * variable reference at runtime. Any variable specific state will typically + * be appended to this structure. + */ + + +typedef struct Tcl_ResolvedVarInfo { + Tcl_ResolveRuntimeVarProc *fetchProc; + Tcl_ResolveVarDeleteProc *deleteProc; +} Tcl_ResolvedVarInfo; + + + +typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, char* name, int length, + Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr)); + +typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, char* name, Tcl_Namespace *context, + int flags, Tcl_Var *rPtr)); + +typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((Tcl_Interp* interp, + char* name, Tcl_Namespace *context, int flags, + Tcl_Command *rPtr)); + +typedef struct Tcl_ResolverInfo { + Tcl_ResolveCmdProc *cmdResProc; /* Procedure handling command name + * resolution. */ + Tcl_ResolveVarProc *varResProc; /* Procedure handling variable name + * resolution for variables that + * can only be handled at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* Procedure handling variable name + * resolution at compile time. */ +} Tcl_ResolverInfo; + +/* + *---------------------------------------------------------------- + * Data structures related to namespaces. + *---------------------------------------------------------------- + */ + +/* + * The structure below defines a namespace. + * Note: the first five fields must match exactly the fields in a + * Tcl_Namespace structure (see tcl.h). If you change one, be sure to + * change the other. + */ + +typedef struct Namespace { + char *name; /* The namespace's simple (unqualified) + * name. This contains no ::'s. The name of + * the global namespace is "" although "::" + * is an synonym. */ + char *fullName; /* The namespace's fully qualified name. + * This starts with ::. */ + ClientData clientData; /* An arbitrary value associated with this + * namespace. */ + Tcl_NamespaceDeleteProc *deleteProc; + /* Procedure invoked when deleting the + * namespace to, e.g., free clientData. */ + struct Namespace *parentPtr; /* Points to the namespace that contains + * this one. NULL if this is the global + * namespace. */ + Tcl_HashTable childTable; /* Contains any child namespaces. Indexed + * by strings; values have type + * (Namespace *). */ + long nsId; /* Unique id for the namespace. */ + Tcl_Interp *interp; /* The interpreter containing this + * namespace. */ + int flags; /* OR-ed combination of the namespace + * status flags NS_DYING and NS_DEAD + * listed below. */ + int activationCount; /* Number of "activations" or active call + * frames for this namespace that are on + * the Tcl call stack. The namespace won't + * be freed until activationCount becomes + * zero. */ + int refCount; /* Count of references by namespaceName * + * objects. The namespace can't be freed + * until refCount becomes zero. */ + Tcl_HashTable cmdTable; /* Contains all the commands currently + * registered in the namespace. Indexed by + * strings; values have type (Command *). + * Commands imported by Tcl_Import have + * Command structures that point (via an + * ImportedCmdRef structure) to the + * Command structure in the source + * namespace's command table. */ + Tcl_HashTable varTable; /* Contains all the (global) variables + * currently in this namespace. Indexed + * by strings; values have type (Var *). */ + char **exportArrayPtr; /* Points to an array of string patterns + * specifying which commands are exported. + * A pattern may include "string match" + * style wildcard characters to specify + * multiple commands; however, no namespace + * qualifiers are allowed. NULL if no + * export patterns are registered. */ + int numExportPatterns; /* Number of export patterns currently + * registered using "namespace export". */ + int maxExportPatterns; /* Mumber of export patterns for which + * space is currently allocated. */ + int cmdRefEpoch; /* Incremented if a newly added command + * shadows a command for which this + * namespace has already cached a Command * + * pointer; this causes all its cached + * Command* pointers to be invalidated. */ + int resolverEpoch; /* Incremented whenever the name resolution + * rules change for this namespace; this + * invalidates all byte codes compiled in + * the namespace, causing the code to be + * recompiled under the new rules. */ + Tcl_ResolveCmdProc *cmdResProc; + /* If non-null, this procedure overrides + * the usual command resolution mechanism + * in Tcl. This procedure is invoked + * within Tcl_FindCommand to resolve all + * command references within the namespace. */ + Tcl_ResolveVarProc *varResProc; + /* If non-null, this procedure overrides + * the usual variable resolution mechanism + * in Tcl. This procedure is invoked + * within Tcl_FindNamespaceVar to resolve all + * variable references within the namespace + * at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* If non-null, this procedure overrides + * the usual variable resolution mechanism + * in Tcl. This procedure is invoked + * within LookupCompiledLocal to resolve + * variable references within the namespace + * at compile time. */ +} Namespace; + +/* + * Flags used to represent the status of a namespace: + * + * NS_DYING - 1 means Tcl_DeleteNamespace has been called to delete the + * namespace but there are still active call frames on the Tcl + * stack that refer to the namespace. When the last call frame + * referring to it has been popped, it's variables and command + * will be destroyed and it will be marked "dead" (NS_DEAD). + * The namespace can no longer be looked up by name. + * NS_DEAD - 1 means Tcl_DeleteNamespace has been called to delete the + * namespace and no call frames still refer to it. Its + * variables and command have already been destroyed. This bit + * allows the namespace resolution code to recognize that the + * namespace is "deleted". When the last namespaceName object + * in any byte code code unit that refers to the namespace has + * been freed (i.e., when the namespace's refCount is 0), the + * namespace's storage will be freed. + */ + +#define NS_DYING 0x01 +#define NS_DEAD 0x02 + +/* + * Flag passed to TclGetNamespaceForQualName to have it create all namespace + * components of a namespace-qualified name that cannot be found. The new + * namespaces are created within their specified parent. Note that this + * flag's value must not conflict with the values of the flags + * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, and FIND_ONLY_NS (defined in + * tclNamesp.c). + */ + +#define CREATE_NS_IF_UNKNOWN 0x800 + +/* + *---------------------------------------------------------------- + * Data structures related to variables. These are used primarily + * in tclVar.c + *---------------------------------------------------------------- + */ + +/* + * The following structure defines a variable trace, which is used to + * invoke a specific C procedure whenever certain operations are performed + * on a variable. + */ + +typedef struct VarTrace { + Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given + * by flags are performed on variable. */ + ClientData clientData; /* Argument to pass to proc. */ + int flags; /* What events the trace procedure is + * interested in: OR-ed combination of + * TCL_TRACE_READS, TCL_TRACE_WRITES, + * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */ + struct VarTrace *nextPtr; /* Next in list of traces associated with + * a particular variable. */ +} VarTrace; + +/* + * When a variable trace is active (i.e. its associated procedure is + * executing), one of the following structures is linked into a list + * associated with the variable's interpreter. The information in + * the structure is needed in order for Tcl to behave reasonably + * if traces are deleted while traces are active. + */ + +typedef struct ActiveVarTrace { + struct Var *varPtr; /* Variable that's being traced. */ + struct ActiveVarTrace *nextPtr; + /* Next in list of all active variable + * traces for the interpreter, or NULL + * if no more. */ + VarTrace *nextTracePtr; /* Next trace to check after current + * trace procedure returns; if this + * trace gets deleted, must update pointer + * to avoid using free'd memory. */ +} ActiveVarTrace; + +/* + * The following structure describes an enumerative search in progress on + * an array variable; this are invoked with options to the "array" + * command. + */ + +typedef struct ArraySearch { + int id; /* Integer id used to distinguish among + * multiple concurrent searches for the + * same array. */ + struct Var *varPtr; /* Pointer to array variable that's being + * searched. */ + Tcl_HashSearch search; /* Info kept by the hash module about + * progress through the array. */ + Tcl_HashEntry *nextEntry; /* Non-null means this is the next element + * to be enumerated (it's leftover from + * the Tcl_FirstHashEntry call or from + * an "array anymore" command). NULL + * means must call Tcl_NextHashEntry + * to get value to return. */ + struct ArraySearch *nextPtr;/* Next in list of all active searches + * for this variable, or NULL if this is + * the last one. */ +} ArraySearch; + +/* + * The structure below defines a variable, which associates a string name + * with a Tcl_Obj value. These structures are kept in procedure call frames + * (for local variables recognized by the compiler) or in the heap (for + * global variables and any variable not known to the compiler). For each + * Var structure in the heap, a hash table entry holds the variable name and + * a pointer to the Var structure. + */ + +typedef struct Var { + union { + Tcl_Obj *objPtr; /* The variable's object value. Used for + * scalar variables and array elements. */ + Tcl_HashTable *tablePtr;/* For array variables, this points to + * information about the hash table used + * to implement the associative array. + * Points to malloc-ed data. */ + struct Var *linkPtr; /* If this is a global variable being + * referred to in a procedure, or a variable + * created by "upvar", this field points to + * the referenced variable's Var struct. */ + } value; + char *name; /* NULL if the variable is in a hashtable, + * otherwise points to the variable's + * name. It is used, e.g., by TclLookupVar + * and "info locals". The storage for the + * characters of the name is not owned by + * the Var and must not be freed when + * freeing the Var. */ + Namespace *nsPtr; /* Points to the namespace that contains + * this variable or NULL if the variable is + * a local variable in a Tcl procedure. */ + Tcl_HashEntry *hPtr; /* If variable is in a hashtable, either the + * hash table entry that refers to this + * variable or NULL if the variable has been + * detached from its hash table (e.g. an + * array is deleted, but some of its + * elements are still referred to in + * upvars). NULL if the variable is not in a + * hashtable. This is used to delete an + * variable from its hashtable if it is no + * longer needed. */ + int refCount; /* Counts number of active uses of this + * variable, not including its entry in the + * call frame or the hash table: 1 for each + * additional variable whose linkPtr points + * here, 1 for each nested trace active on + * variable, and 1 if the variable is a + * namespace variable. This record can't be + * deleted until refCount becomes 0. */ + VarTrace *tracePtr; /* First in list of all traces set for this + * variable. */ + ArraySearch *searchPtr; /* First in list of all searches active + * for this variable, or NULL if none. */ + int flags; /* Miscellaneous bits of information about + * variable. See below for definitions. */ +} Var; + +/* + * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and + * VAR_LINK) are mutually exclusive and give the "type" of the variable. + * VAR_UNDEFINED is independent of the variable's type. + * + * VAR_SCALAR - 1 means this is a scalar variable and not + * an array or link. The "objPtr" field points + * to the variable's value, a Tcl object. + * VAR_ARRAY - 1 means this is an array variable rather + * than a scalar variable or link. The + * "tablePtr" field points to the array's + * hashtable for its elements. + * VAR_LINK - 1 means this Var structure contains a + * pointer to another Var structure that + * either has the real value or is itself + * another VAR_LINK pointer. Variables like + * this come about through "upvar" and "global" + * commands, or through references to variables + * in enclosing namespaces. + * VAR_UNDEFINED - 1 means that the variable is in the process + * of being deleted. An undefined variable + * logically does not exist and survives only + * while it has a trace, or if it is a global + * variable currently being used by some + * procedure. + * VAR_IN_HASHTABLE - 1 means this variable is in a hashtable and + * the Var structure is malloced. 0 if it is + * a local variable that was assigned a slot + * in a procedure frame by the compiler so the + * Var storage is part of the call frame. + * VAR_TRACE_ACTIVE - 1 means that trace processing is currently + * underway for a read or write access, so + * new read or write accesses should not cause + * trace procedures to be called and the + * variable can't be deleted. + * VAR_ARRAY_ELEMENT - 1 means that this variable is an array + * element, so it is not legal for it to be + * an array itself (the VAR_ARRAY flag had + * better not be set). + * VAR_NAMESPACE_VAR - 1 means that this variable was declared + * as a namespace variable. This flag ensures + * it persists until its namespace is + * destroyed or until the variable is unset; + * it will persist even if it has not been + * initialized and is marked undefined. + * The variable's refCount is incremented to + * reflect the "reference" from its namespace. + * + * The following additional flags are used with the CompiledLocal type + * defined below: + * + * VAR_ARGUMENT - 1 means that this variable holds a procedure + * argument. + * VAR_TEMPORARY - 1 if the local variable is an anonymous + * temporary variable. Temporaries have a NULL + * name. + * VAR_RESOLVED - 1 if name resolution has been done for this + * variable. + */ + +#define VAR_SCALAR 0x1 +#define VAR_ARRAY 0x2 +#define VAR_LINK 0x4 +#define VAR_UNDEFINED 0x8 +#define VAR_IN_HASHTABLE 0x10 +#define VAR_TRACE_ACTIVE 0x20 +#define VAR_ARRAY_ELEMENT 0x40 +#define VAR_NAMESPACE_VAR 0x80 + +#define VAR_ARGUMENT 0x100 +#define VAR_TEMPORARY 0x200 +#define VAR_RESOLVED 0x400 + +/* + * Macros to ensure that various flag bits are set properly for variables. + * The ANSI C "prototypes" for these macros are: + * + * EXTERN void TclSetVarScalar _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarArray _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarLink _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarArrayElement _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarUndefined _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclClearVarUndefined _ANSI_ARGS_((Var *varPtr)); + */ + +#define TclSetVarScalar(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR + +#define TclSetVarArray(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY + +#define TclSetVarLink(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_ARRAY)) | VAR_LINK + +#define TclSetVarArrayElement(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT + +#define TclSetVarUndefined(varPtr) \ + (varPtr)->flags |= VAR_UNDEFINED + +#define TclClearVarUndefined(varPtr) \ + (varPtr)->flags &= ~VAR_UNDEFINED + +/* + * Macros to read various flag bits of variables. + * The ANSI C "prototypes" for these macros are: + * + * EXTERN int TclIsVarScalar _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarLink _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArray _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarUndefined _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarTemporary _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArgument _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarResolved _ANSI_ARGS_((Var *varPtr)); + */ + +#define TclIsVarScalar(varPtr) \ + ((varPtr)->flags & VAR_SCALAR) + +#define TclIsVarLink(varPtr) \ + ((varPtr)->flags & VAR_LINK) + +#define TclIsVarArray(varPtr) \ + ((varPtr)->flags & VAR_ARRAY) + +#define TclIsVarUndefined(varPtr) \ + ((varPtr)->flags & VAR_UNDEFINED) + +#define TclIsVarArrayElement(varPtr) \ + ((varPtr)->flags & VAR_ARRAY_ELEMENT) + +#define TclIsVarTemporary(varPtr) \ + ((varPtr)->flags & VAR_TEMPORARY) + +#define TclIsVarArgument(varPtr) \ + ((varPtr)->flags & VAR_ARGUMENT) + +#define TclIsVarResolved(varPtr) \ + ((varPtr)->flags & VAR_RESOLVED) + +/* + *---------------------------------------------------------------- + * Data structures related to procedures. These are used primarily + * in tclProc.c, tclCompile.c, and tclExecute.c. + *---------------------------------------------------------------- + */ + +/* + * Forward declaration to prevent an error when the forward reference to + * Command is encountered in the Proc and ImportRef types declared below. + */ + +struct Command; + +/* + * The variable-length structure below describes a local variable of a + * procedure that was recognized by the compiler. These variables have a + * name, an element in the array of compiler-assigned local variables in the + * procedure's call frame, and various other items of information. If the + * local variable is a formal argument, it may also have a default value. + * The compiler can't recognize local variables whose names are + * expressions (these names are only known at runtime when the expressions + * are evaluated) or local variables that are created as a result of an + * "upvar" or "uplevel" command. These other local variables are kept + * separately in a hash table in the call frame. + */ + +typedef struct CompiledLocal { + struct CompiledLocal *nextPtr; + /* Next compiler-recognized local variable + * for this procedure, or NULL if this is + * the last local. */ + int nameLength; /* The number of characters in local + * variable's name. Used to speed up + * variable lookups. */ + int frameIndex; /* Index in the array of compiler-assigned + * variables in the procedure call frame. */ + int flags; /* Flag bits for the local variable. Same as + * the flags for the Var structure above, + * although only VAR_SCALAR, VAR_ARRAY, + * VAR_LINK, VAR_ARGUMENT, VAR_TEMPORARY, and + * VAR_RESOLVED make sense. */ + Tcl_Obj *defValuePtr; /* Pointer to the default value of an + * argument, if any. NULL if not an argument + * or, if an argument, no default value. */ + Tcl_ResolvedVarInfo *resolveInfo; + /* Customized variable resolution info + * supplied by the Tcl_ResolveCompiledVarProc + * associated with a namespace. Each variable + * is marked by a unique ClientData tag + * during compilation, and that same tag + * is used to find the variable at runtime. */ + char name[4]; /* Name of the local variable starts here. + * If the name is NULL, this will just be + * '\0'. The actual size of this field will + * be large enough to hold the name. MUST + * BE THE LAST FIELD IN THE STRUCTURE! */ +} CompiledLocal; + +/* + * The structure below defines a command procedure, which consists of a + * collection of Tcl commands plus information about arguments and other + * local variables recognized at compile time. + */ + +typedef struct Proc { + struct Interp *iPtr; /* Interpreter for which this command + * is defined. */ + int refCount; /* Reference count: 1 if still present + * in command table plus 1 for each call + * to the procedure that is currently + * active. This structure can be freed + * when refCount becomes zero. */ + struct Command *cmdPtr; /* Points to the Command structure for + * this procedure. This is used to get + * the namespace in which to execute + * the procedure. */ + Tcl_Obj *bodyPtr; /* Points to the ByteCode object for + * procedure's body command. */ + int numArgs; /* Number of formal parameters. */ + int numCompiledLocals; /* Count of local variables recognized by + * the compiler including arguments and + * temporaries. */ + CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's + * compiler-allocated local variables, or + * NULL if none. The first numArgs entries + * in this list describe the procedure's + * formal arguments. */ + CompiledLocal *lastLocalPtr; /* Pointer to the last allocated local + * variable or NULL if none. This has + * frame index (numCompiledLocals-1). */ +} Proc; + +/* + * The structure below defines a command trace. This is used to allow Tcl + * clients to find out whenever a command is about to be executed. + */ + +typedef struct Trace { + int level; /* Only trace commands at nesting level + * less than or equal to this. */ + Tcl_CmdTraceProc *proc; /* Procedure to call to trace command. */ + ClientData clientData; /* Arbitrary value to pass to proc. */ + struct Trace *nextPtr; /* Next in list of traces for this interp. */ +} Trace; + +/* + * The structure below defines an entry in the assocData hash table which + * is associated with an interpreter. The entry contains a pointer to a + * function to call when the interpreter is deleted, and a pointer to + * a user-defined piece of data. + */ + +typedef struct AssocData { + Tcl_InterpDeleteProc *proc; /* Proc to call when deleting. */ + ClientData clientData; /* Value to pass to proc. */ +} AssocData; + +/* + * The structure below defines a call frame. A call frame defines a naming + * context for a procedure call: its local naming scope (for local + * variables) and its global naming scope (a namespace, perhaps the global + * :: namespace). A call frame can also define the naming context for a + * namespace eval or namespace inscope command: the namespace in which the + * command's code should execute. The Tcl_CallFrame structures exist only + * while procedures or namespace eval/inscope's are being executed, and + * provide a kind of Tcl call stack. + * + * WARNING!! The structure definition must be kept consistent with the + * Tcl_CallFrame structure in tcl.h. If you change one, change the other. + */ + +typedef struct CallFrame { + Namespace *nsPtr; /* Points to the namespace used to resolve + * commands and global variables. */ + int isProcCallFrame; /* If nonzero, the frame was pushed to + * execute a Tcl procedure and may have + * local vars. If 0, the frame was pushed + * to execute a namespace command and var + * references are treated as references to + * namespace vars; varTablePtr and + * compiledLocals are ignored. */ + int objc; /* This and objv below describe the + * arguments for this procedure call. */ + Tcl_Obj *CONST *objv; /* Array of argument objects. */ + struct CallFrame *callerPtr; + /* Value of interp->framePtr when this + * procedure was invoked (i.e. next higher + * in stack of all active procedures). */ + struct CallFrame *callerVarPtr; + /* Value of interp->varFramePtr when this + * procedure was invoked (i.e. determines + * variable scoping within caller). Same + * as callerPtr unless an "uplevel" command + * or something equivalent was active in + * the caller). */ + int level; /* Level of this procedure, for "uplevel" + * purposes (i.e. corresponds to nesting of + * callerVarPtr's, not callerPtr's). 1 for + * outermost procedure, 0 for top-level. */ + Proc *procPtr; /* Points to the structure defining the + * called procedure. Used to get information + * such as the number of compiled local + * variables (local variables assigned + * entries ["slots"] in the compiledLocals + * array below). */ + Tcl_HashTable *varTablePtr; /* Hash table containing local variables not + * recognized by the compiler, or created at + * execution time through, e.g., upvar. + * Initially NULL and created if needed. */ + int numCompiledLocals; /* Count of local variables recognized by + * the compiler including arguments. */ + Var* compiledLocals; /* Points to the array of local variables + * recognized by the compiler. The compiler + * emits code that refers to these variables + * using an index into this array. */ +} CallFrame; + +/* + *---------------------------------------------------------------- + * Data structures and procedures related to TclHandles, which + * are a very lightweight method of preserving enough information + * to determine if an arbitrary malloc'd block has been deleted. + *---------------------------------------------------------------- + */ + +typedef VOID **TclHandle; + +EXTERN TclHandle TclHandleCreate _ANSI_ARGS_((VOID *ptr)); +EXTERN void TclHandleFree _ANSI_ARGS_((TclHandle handle)); +EXTERN TclHandle TclHandlePreserve _ANSI_ARGS_((TclHandle handle)); +EXTERN void TclHandleRelease _ANSI_ARGS_((TclHandle handle)); + +/* + *---------------------------------------------------------------- + * Data structures related to history. These are used primarily + * in tclHistory.c + *---------------------------------------------------------------- + */ + +/* + * The structure below defines one history event (a previously-executed + * command that can be re-executed in whole or in part). + */ + +typedef struct { + char *command; /* String containing previously-executed + * command. */ + int bytesAvl; /* Total # of bytes available at *event (not + * all are necessarily in use now). */ +} HistoryEvent; + +/* + * The structure below defines a pending revision to the most recent + * history event. Changes are linked together into a list and applied + * during the next call to Tcl_RecordHistory. See the comments at the + * beginning of tclHistory.c for information on revisions. + */ + +typedef struct HistoryRev { + int firstIndex; /* Index of the first byte to replace in + * current history event. */ + int lastIndex; /* Index of last byte to replace in + * current history event. */ + int newSize; /* Number of bytes in newBytes. */ + char *newBytes; /* Replacement for the range given by + * firstIndex and lastIndex (malloced). */ + struct HistoryRev *nextPtr; /* Next in chain of revisions to apply, or + * NULL for end of list. */ +} HistoryRev; + +/* + *---------------------------------------------------------------- + * Data structures related to expressions. These are used only in + * tclExpr.c. + *---------------------------------------------------------------- + */ + +/* + * The data structure below defines a math function (e.g. sin or hypot) + * for use in Tcl expressions. + */ + +#define MAX_MATH_ARGS 5 +typedef struct MathFunc { + int builtinFuncIndex; /* If this is a builtin math function, its + * index in the array of builtin functions. + * (tclCompilation.h lists these indices.) + * The value is -1 if this is a new function + * defined by Tcl_CreateMathFunc. The value + * is also -1 if a builtin function is + * replaced by a Tcl_CreateMathFunc call. */ + int numArgs; /* Number of arguments for function. */ + Tcl_ValueType argTypes[MAX_MATH_ARGS]; + /* Acceptable types for each argument. */ + Tcl_MathProc *proc; /* Procedure that implements this function. + * NULL if isBuiltinFunc is 1. */ + ClientData clientData; /* Additional argument to pass to the + * function when invoking it. NULL if + * isBuiltinFunc is 1. */ +} MathFunc; + +/* + * These are a thin layer over TclpThreadKeyDataGet and TclpThreadKeyDataSet + * when threads are used, or an emulation if there are no threads. These + * are really internal and Tcl clients should use Tcl_GetThreadData. + */ + +EXTERN VOID *TclThreadDataKeyGet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclThreadDataKeySet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr, VOID *data)); + +/* + * This is a convenience macro used to initialize a thread local storage ptr. + */ +#define TCL_TSD_INIT(keyPtr) (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) + + +#ifdef MAC_TCL +typedef pascal void *(Tcl_ThreadCreateProc) _ANSI_ARGS_((ClientData clientData)); +#else +typedef void (Tcl_ThreadCreateProc) _ANSI_ARGS_((ClientData clientData)); +#endif + +/* + *---------------------------------------------------------------- + * Data structures related to bytecode compilation and execution. + * These are used primarily in tclCompile.c, tclExecute.c, and + * tclBasic.c. + *---------------------------------------------------------------- + */ + +/* + * Forward declaration to prevent errors when the forward references to + * Tcl_Parse and CompileEnv are encountered in the procedure type + * CompileProc declared below. + */ + +struct CompileEnv; + +/* + * The type of procedures called by the Tcl bytecode compiler to compile + * commands. Pointers to these procedures are kept in the Command structure + * describing each command. When a CompileProc returns, the interpreter's + * result is set to error information, if any. In addition, the CompileProc + * returns an integer value, which is one of the following: + * + * TCL_OK Compilation completed normally. + * TCL_ERROR Compilation failed because of an error; + * the interpreter's result describes what went wrong. + * TCL_OUT_LINE_COMPILE Compilation failed because, e.g., the command is + * too complex for effective inline compilation. The + * CompileProc believes the command is legal but + * should be compiled "out of line" by emitting code + * to invoke its command procedure at runtime. + */ + +#define TCL_OUT_LINE_COMPILE (TCL_CONTINUE + 1) + +typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *compEnvPtr)); + +/* + * The type of procedure called from the compilation hook point in + * SetByteCodeFromAny. + */ + +typedef int (CompileHookProc) _ANSI_ARGS_((Tcl_Interp *interp, + struct CompileEnv *compEnvPtr, ClientData clientData)); + +/* + * The data structure defining the execution environment for ByteCode's. + * There is one ExecEnv structure per Tcl interpreter. It holds the + * evaluation stack that holds command operands and results. The stack grows + * towards increasing addresses. The "stackTop" member is cached by + * TclExecuteByteCode in a local variable: it must be set before calling + * TclExecuteByteCode and will be restored by TclExecuteByteCode before it + * returns. + */ + +typedef struct ExecEnv { + Tcl_Obj **stackPtr; /* Points to the first item in the + * evaluation stack on the heap. */ + int stackTop; /* Index of current top of stack; -1 when + * the stack is empty. */ + int stackEnd; /* Index of last usable item in stack. */ +} ExecEnv; + +/* + * The definitions for the LiteralTable and LiteralEntry structures. Each + * interpreter contains a LiteralTable. It is used to reduce the storage + * needed for all the Tcl objects that hold the literals of scripts compiled + * by the interpreter. A literal's object is shared by all the ByteCodes + * that refer to the literal. Each distinct literal has one LiteralEntry + * entry in the LiteralTable. A literal table is a specialized hash table + * that is indexed by the literal's string representation, which may contain + * null characters. + * + * Note that we reduce the space needed for literals by sharing literal + * objects both within a ByteCode (each ByteCode contains a local + * LiteralTable) and across all an interpreter's ByteCodes (with the + * interpreter's global LiteralTable). + */ + +typedef struct LiteralEntry { + struct LiteralEntry *nextPtr; /* Points to next entry in this + * hash bucket or NULL if end of + * chain. */ + Tcl_Obj *objPtr; /* Points to Tcl object that + * holds the literal's bytes and + * length. */ + int refCount; /* If in an interpreter's global + * literal table, the number of + * ByteCode structures that share + * the literal object; the literal + * entry can be freed when refCount + * drops to 0. If in a local literal + * table, -1. */ +} LiteralEntry; + +typedef struct LiteralTable { + LiteralEntry **buckets; /* Pointer to bucket array. Each + * element points to first entry in + * bucket's hash chain, or NULL. */ + LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; + /* Bucket array used for small + * tables to avoid mallocs and + * frees. */ + int numBuckets; /* Total number of buckets allocated + * at **buckets. */ + int numEntries; /* Total number of entries present + * in table. */ + int rebuildSize; /* Enlarge table when numEntries + * gets to be this large. */ + int mask; /* Mask value used in hashing + * function. */ +} LiteralTable; + +/* + * The following structure defines for each Tcl interpreter various + * statistics-related information about the bytecode compiler and + * interpreter's operation in that interpreter. + */ + +#ifdef TCL_COMPILE_STATS +typedef struct ByteCodeStats { + long numExecutions; /* Number of ByteCodes executed. */ + long numCompilations; /* Number of ByteCodes created. */ + long numByteCodesFreed; /* Number of ByteCodes destroyed. */ + long instructionCount[256]; /* Number of times each instruction was + * executed. */ + + double totalSrcBytes; /* Total source bytes ever compiled. */ + double totalByteCodeBytes; /* Total bytes for all ByteCodes. */ + double currentSrcBytes; /* Src bytes for all current ByteCodes. */ + double currentByteCodeBytes; /* Code bytes in all current ByteCodes. */ + + long srcCount[32]; /* Source size distribution: # of srcs of + * size [2**(n-1)..2**n), n in [0..32). */ + long byteCodeCount[32]; /* ByteCode size distribution. */ + long lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */ + + double currentInstBytes; /* Instruction bytes-current ByteCodes. */ + double currentLitBytes; /* Current literal bytes. */ + double currentExceptBytes; /* Current exception table bytes. */ + double currentAuxBytes; /* Current auxiliary information bytes. */ + double currentCmdMapBytes; /* Current src<->code map bytes. */ + + long numLiteralsCreated; /* Total literal objects ever compiled. */ + double totalLitStringBytes; /* Total string bytes in all literals. */ + double currentLitStringBytes; /* String bytes in current literals. */ + long literalCount[32]; /* Distribution of literal string sizes. */ +} ByteCodeStats; +#endif /* TCL_COMPILE_STATS */ + +/* + *---------------------------------------------------------------- + * Data structures related to commands. + *---------------------------------------------------------------- + */ + +/* + * An imported command is created in an namespace when it imports a "real" + * command from another namespace. An imported command has a Command + * structure that points (via its ClientData value) to the "real" Command + * structure in the source namespace's command table. The real command + * records all the imported commands that refer to it in a list of ImportRef + * structures so that they can be deleted when the real command is deleted. */ + +typedef struct ImportRef { + struct Command *importedCmdPtr; + /* Points to the imported command created in + * an importing namespace; this command + * redirects its invocations to the "real" + * command. */ + struct ImportRef *nextPtr; /* Next element on the linked list of + * imported commands that refer to the + * "real" command. The real command deletes + * these imported commands on this list when + * it is deleted. */ +} ImportRef; + +/* + * Data structure used as the ClientData of imported commands: commands + * created in an namespace when it imports a "real" command from another + * namespace. + */ + +typedef struct ImportedCmdData { + struct Command *realCmdPtr; /* "Real" command that this imported command + * refers to. */ + struct Command *selfPtr; /* Pointer to this imported command. Needed + * only when deleting it in order to remove + * it from the real command's linked list of + * imported commands that refer to it. */ +} ImportedCmdData; + +/* + * A Command structure exists for each command in a namespace. The + * Tcl_Command opaque type actually refers to these structures. + */ + +typedef struct Command { + Tcl_HashEntry *hPtr; /* Pointer to the hash table entry that + * refers to this command. The hash table is + * either a namespace's command table or an + * interpreter's hidden command table. This + * pointer is used to get a command's name + * from its Tcl_Command handle. NULL means + * that the hash table entry has been + * removed already (this can happen if + * deleteProc causes the command to be + * deleted or recreated). */ + Namespace *nsPtr; /* Points to the namespace containing this + * command. */ + int refCount; /* 1 if in command hashtable plus 1 for each + * reference from a CmdName Tcl object + * representing a command's name in a + * ByteCode instruction sequence. This + * structure can be freed when refCount + * becomes zero. */ + int cmdEpoch; /* Incremented to invalidate any references + * that point to this command when it is + * renamed, deleted, hidden, or exposed. */ + CompileProc *compileProc; /* Procedure called to compile command. NULL + * if no compile proc exists for command. */ + Tcl_ObjCmdProc *objProc; /* Object-based command procedure. */ + ClientData objClientData; /* Arbitrary value passed to object proc. */ + Tcl_CmdProc *proc; /* String-based command procedure. */ + ClientData clientData; /* Arbitrary value passed to string proc. */ + Tcl_CmdDeleteProc *deleteProc; + /* Procedure invoked when deleting command + * to, e.g., free all client data. */ + ClientData deleteData; /* Arbitrary value passed to deleteProc. */ + int deleted; /* Means that the command is in the process + * of being deleted (its deleteProc is + * currently executing). Other attempts to + * delete the command should be ignored. */ + ImportRef *importRefPtr; /* List of each imported Command created in + * another namespace when this command is + * imported. These imported commands + * redirect invocations back to this + * command. The list is used to remove all + * those imported commands when deleting + * this "real" command. */ +} Command; + +/* + *---------------------------------------------------------------- + * Data structures related to name resolution procedures. + *---------------------------------------------------------------- + */ + +/* + * The interpreter keeps a linked list of name resolution schemes. + * The scheme for a namespace is consulted first, followed by the + * list of schemes in an interpreter, followed by the default + * name resolution in Tcl. Schemes are added/removed from the + * interpreter's list by calling Tcl_AddInterpResolver and + * Tcl_RemoveInterpResolver. + */ + +typedef struct ResolverScheme { + char *name; /* Name identifying this scheme. */ + Tcl_ResolveCmdProc *cmdResProc; + /* Procedure handling command name + * resolution. */ + Tcl_ResolveVarProc *varResProc; + /* Procedure handling variable name + * resolution for variables that + * can only be handled at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* Procedure handling variable name + * resolution at compile time. */ + + struct ResolverScheme *nextPtr; + /* Pointer to next record in linked list. */ +} ResolverScheme; + +/* + *---------------------------------------------------------------- + * This structure defines an interpreter, which is a collection of + * commands plus other state information related to interpreting + * commands, such as variable storage. Primary responsibility for + * this data structure is in tclBasic.c, but almost every Tcl + * source file uses something in here. + *---------------------------------------------------------------- + */ + +typedef struct Interp { + + /* + * Note: the first three fields must match exactly the fields in + * a Tcl_Interp struct (see tcl.h). If you change one, be sure to + * change the other. + * + * The interpreter's result is held in both the string and the + * objResultPtr fields. These fields hold, respectively, the result's + * string or object value. The interpreter's result is always in the + * result field if that is non-empty, otherwise it is in objResultPtr. + * The two fields are kept consistent unless some C code sets + * interp->result directly. Programs should not access result and + * objResultPtr directly; instead, they should always get and set the + * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult, + * and Tcl_GetStringResult. See the SetResult man page for details. + */ + + char *result; /* If the last command returned a string + * result, this points to it. Should not be + * accessed directly; see comment above. */ + Tcl_FreeProc *freeProc; /* Zero means a string result is statically + * allocated. TCL_DYNAMIC means string + * result was allocated with ckalloc and + * should be freed with ckfree. Other values + * give address of procedure to invoke to + * free the string result. Tcl_Eval must + * free it before executing next command. */ + int errorLine; /* When TCL_ERROR is returned, this gives + * the line number in the command where the + * error occurred (1 means first line). */ + struct TclStubs *stubTable; + /* Pointer to the exported Tcl stub table. + * On previous versions of Tcl this is a + * pointer to the objResultPtr or a pointer + * to a buckets array in a hash table. We + * therefore have to do some careful checking + * before we can use this. */ + + TclHandle handle; /* Handle used to keep track of when this + * interp is deleted. */ + + Namespace *globalNsPtr; /* The interpreter's global namespace. */ + Tcl_HashTable *hiddenCmdTablePtr; + /* Hash table used by tclBasic.c to keep + * track of hidden commands on a per-interp + * basis. */ + ClientData interpInfo; /* Information used by tclInterp.c to keep + * track of master/slave interps on + * a per-interp basis. */ + Tcl_HashTable mathFuncTable;/* Contains all the math functions currently + * defined for the interpreter. Indexed by + * strings (function names); values have + * type (MathFunc *). */ + + + + /* + * Information related to procedures and variables. See tclProc.c + * and tclvar.c for usage. + */ + + int numLevels; /* Keeps track of how many nested calls to + * Tcl_Eval are in progress for this + * interpreter. It's used to delay deletion + * of the table until all Tcl_Eval + * invocations are completed. */ + int maxNestingDepth; /* If numLevels exceeds this value then Tcl + * assumes that infinite recursion has + * occurred and it generates an error. */ + CallFrame *framePtr; /* Points to top-most in stack of all nested + * procedure invocations. NULL means there + * are no active procedures. */ + CallFrame *varFramePtr; /* Points to the call frame whose variables + * are currently in use (same as framePtr + * unless an "uplevel" command is + * executing). NULL means no procedure is + * active or "uplevel 0" is executing. */ + ActiveVarTrace *activeTracePtr; + /* First in list of active traces for + * interp, or NULL if no active traces. */ + int returnCode; /* Completion code to return if current + * procedure exits with TCL_RETURN code. */ + char *errorInfo; /* Value to store in errorInfo if returnCode + * is TCL_ERROR. Malloc'ed, may be NULL */ + char *errorCode; /* Value to store in errorCode if returnCode + * is TCL_ERROR. Malloc'ed, may be NULL */ + + /* + * Information used by Tcl_AppendResult to keep track of partial + * results. See Tcl_AppendResult code for details. + */ + + char *appendResult; /* Storage space for results generated + * by Tcl_AppendResult. Malloc-ed. NULL + * means not yet allocated. */ + int appendAvl; /* Total amount of space available at + * partialResult. */ + int appendUsed; /* Number of non-null bytes currently + * stored at partialResult. */ + + /* + * Information about packages. Used only in tclPkg.c. + */ + + Tcl_HashTable packageTable; /* Describes all of the packages loaded + * in or available to this interpreter. + * Keys are package names, values are + * (Package *) pointers. */ + char *packageUnknown; /* Command to invoke during "package + * require" commands for packages that + * aren't described in packageTable. + * Malloc'ed, may be NULL. */ + + /* + * Miscellaneous information: + */ + + int cmdCount; /* Total number of times a command procedure + * has been called for this interpreter. */ + int evalFlags; /* Flags to control next call to Tcl_Eval. + * Normally zero, but may be set before + * calling Tcl_Eval. See below for valid + * values. */ + int termOffset; /* Offset of character just after last one + * compiled or executed by Tcl_EvalObj. */ + LiteralTable literalTable; /* Contains LiteralEntry's describing all + * Tcl objects holding literals of scripts + * compiled by the interpreter. Indexed by + * the string representations of literals. + * Used to avoid creating duplicate + * objects. */ + int compileEpoch; /* Holds the current "compilation epoch" + * for this interpreter. This is + * incremented to invalidate existing + * ByteCodes when, e.g., a command with a + * compile procedure is redefined. */ + Proc *compiledProcPtr; /* If a procedure is being compiled, a + * pointer to its Proc structure; otherwise, + * this is NULL. Set by ObjInterpProc in + * tclProc.c and used by tclCompile.c to + * process local variables appropriately. */ + ResolverScheme *resolverPtr; + /* Linked list of name resolution schemes + * added to this interpreter. Schemes + * are added/removed by calling + * Tcl_AddInterpResolvers and + * Tcl_RemoveInterpResolver. */ + char *scriptFile; /* NULL means there is no nested source + * command active; otherwise this points to + * the name of the file being sourced (it's + * not malloc-ed: it points to an argument + * to Tcl_EvalFile. */ + int flags; /* Various flag bits. See below. */ + long randSeed; /* Seed used for rand() function. */ + Trace *tracePtr; /* List of traces for this interpreter. */ + Tcl_HashTable *assocData; /* Hash table for associating data with + * this interpreter. Cleaned up when + * this interpreter is deleted. */ + struct ExecEnv *execEnvPtr; /* Execution environment for Tcl bytecode + * execution. Contains a pointer to the + * Tcl evaluation stack. */ + Tcl_Obj *emptyObjPtr; /* Points to an object holding an empty + * string. Returned by Tcl_ObjSetVar2 when + * variable traces change a variable in a + * gross way. */ + char resultSpace[TCL_RESULT_SIZE+1]; + /* Static space holding small results. */ + Tcl_Obj *objResultPtr; /* If the last command returned an object + * result, this points to it. Should not be + * accessed directly; see comment above. */ + Tcl_ThreadId threadId; /* ID of thread that owns the interpreter */ + + /* + * Statistical information about the bytecode compiler and interpreter's + * operation. + */ + +#ifdef TCL_COMPILE_STATS + ByteCodeStats stats; /* Holds compilation and execution + * statistics for this interpreter. */ +#endif /* TCL_COMPILE_STATS */ +} Interp; + +/* + * EvalFlag bits for Interp structures: + * + * TCL_BRACKET_TERM 1 means that the current script is terminated by + * a close bracket rather than the end of the string. + * TCL_ALLOW_EXCEPTIONS 1 means it's OK for the script to terminate with + * a code other than TCL_OK or TCL_ERROR; 0 means + * codes other than these should be turned into errors. + */ + +#define TCL_BRACKET_TERM 1 +#define TCL_ALLOW_EXCEPTIONS 4 + +/* + * Flag bits for Interp structures: + * + * DELETED: Non-zero means the interpreter has been deleted: + * don't process any more commands for it, and destroy + * the structure as soon as all nested invocations of + * Tcl_Eval are done. + * ERR_IN_PROGRESS: Non-zero means an error unwind is already in + * progress. Zero means a command proc has been + * invoked since last error occured. + * ERR_ALREADY_LOGGED: Non-zero means information has already been logged + * in $errorInfo for the current Tcl_Eval instance, + * so Tcl_Eval needn't log it (used to implement the + * "error message log" command). + * ERROR_CODE_SET: Non-zero means that Tcl_SetErrorCode has been + * called to record information for the current + * error. Zero means Tcl_Eval must clear the + * errorCode variable if an error is returned. + * EXPR_INITIALIZED: Non-zero means initialization specific to + * expressions has been carried out. + * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler + * should not compile any commands into an inline + * sequence of instructions. This is set 1, for + * example, when command traces are requested. + * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the + * interp has not be initialized. This is set 1 + * when we first use the rand() or srand() functions. + * SAFE_INTERP: Non zero means that the current interp is a + * safe interp (ie it has only the safe commands + * installed, less priviledge than a regular interp). + * USE_EVAL_DIRECT: Non-zero means don't use the compiler or byte-code + * interpreter; instead, have Tcl_EvalObj call + * Tcl_EvalEx. Used primarily for testing the + * new parser. + */ + +#define DELETED 1 +#define ERR_IN_PROGRESS 2 +#define ERR_ALREADY_LOGGED 4 +#define ERROR_CODE_SET 8 +#define EXPR_INITIALIZED 0x10 +#define DONT_COMPILE_CMDS_INLINE 0x20 +#define RAND_SEED_INITIALIZED 0x40 +#define SAFE_INTERP 0x80 +#define USE_EVAL_DIRECT 0x100 + +/* + *---------------------------------------------------------------- + * Data structures related to command parsing. These are used in + * tclParse.c and its clients. + *---------------------------------------------------------------- + */ + +/* + * The following data structure is used by various parsing procedures + * to hold information about where to store the results of parsing + * (e.g. the substituted contents of a quoted argument, or the result + * of a nested command). At any given time, the space available + * for output is fixed, but a procedure may be called to expand the + * space available if the current space runs out. + */ + +typedef struct ParseValue { + char *buffer; /* Address of first character in + * output buffer. */ + char *next; /* Place to store next character in + * output buffer. */ + char *end; /* Address of the last usable character + * in the buffer. */ + void (*expandProc) _ANSI_ARGS_((struct ParseValue *pvPtr, int needed)); + /* Procedure to call when space runs out; + * it will make more space. */ + ClientData clientData; /* Arbitrary information for use of + * expandProc. */ +} ParseValue; + + +/* + * Maximum number of levels of nesting permitted in Tcl commands (used + * to catch infinite recursion). + */ + +#define MAX_NESTING_DEPTH 1000 + +/* + * The macro below is used to modify a "char" value (e.g. by casting + * it to an unsigned character) so that it can be used safely with + * macros such as isspace. + */ + +#define UCHAR(c) ((unsigned char) (c)) + +/* + * This macro is used to determine the offset needed to safely allocate any + * data structure in memory. Given a starting offset or size, it "rounds up" + * or "aligns" the offset to the next 8-byte boundary so that any data + * structure can be placed at the resulting offset without fear of an + * alignment error. + * + * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce + * the wrong result on platforms that allocate addresses that are divisible + * by 4 or 2. Only use it for offsets or sizes. + */ + +#define TCL_ALIGN(x) (((int)(x) + 7) & ~7) + +/* + * The following macros are used to specify the runtime platform + * setting of the tclPlatform variable. + */ + +typedef enum { + TCL_PLATFORM_UNIX, /* Any Unix-like OS. */ + TCL_PLATFORM_MAC, /* MacOS. */ + TCL_PLATFORM_WINDOWS /* Any Microsoft Windows OS. */ +} TclPlatformType; + +/* + * Flags for TclInvoke: + * + * TCL_INVOKE_HIDDEN Invoke a hidden command; if not set, + * invokes an exposed command. + * TCL_INVOKE_NO_UNKNOWN If set, "unknown" is not invoked if + * the command to be invoked is not found. + * Only has an effect if invoking an exposed + * command, i.e. if TCL_INVOKE_HIDDEN is not + * also set. + * TCL_INVOKE_NO_TRACEBACK Does not record traceback information if + * the invoked command returns an error. Used + * if the caller plans on recording its own + * traceback information. + */ + +#define TCL_INVOKE_HIDDEN (1<<0) +#define TCL_INVOKE_NO_UNKNOWN (1<<1) +#define TCL_INVOKE_NO_TRACEBACK (1<<2) + +/* + * The structure used as the internal representation of Tcl list + * objects. This is an array of pointers to the element objects. This array + * is grown (reallocated and copied) as necessary to hold all the list's + * element pointers. The array might contain more slots than currently used + * to hold all element pointers. This is done to make append operations + * faster. + */ + +typedef struct List { + int maxElemCount; /* Total number of element array slots. */ + int elemCount; /* Current number of list elements. */ + Tcl_Obj **elements; /* Array of pointers to element objects. */ +} List; + + +/* + * The following types are used for getting and storing platform-specific + * file attributes in tclFCmd.c and the various platform-versions of + * that file. This is done to have as much common code as possible + * in the file attributes code. For more information about the callbacks, + * see TclFileAttrsCmd in tclFCmd.c. + */ + +typedef int (TclGetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, + int objIndex, CONST char *fileName, Tcl_Obj **attrObjPtrPtr)); +typedef int (TclSetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, + int objIndex, CONST char *fileName, Tcl_Obj *attrObjPtr)); + +typedef struct TclFileAttrProcs { + TclGetFileAttrProc *getProc; /* The procedure for getting attrs. */ + TclSetFileAttrProc *setProc; /* The procedure for setting attrs. */ +} TclFileAttrProcs; + +/* + * Opaque handle used in pipeline routines to encapsulate platform-dependent + * state. + */ + +typedef struct TclFile_ *TclFile; + +/* + *---------------------------------------------------------------- + * Data structures related to hooking 'TclStat(...)' and + * 'TclAccess(...)'. + *---------------------------------------------------------------- + */ + +typedef int (TclStatProc_) _ANSI_ARGS_((CONST char *path, struct stat *buf)); +typedef int (TclAccessProc_) _ANSI_ARGS_((CONST char *path, int mode)); +typedef Tcl_Channel (TclOpenFileChannelProc_) _ANSI_ARGS_((Tcl_Interp *interp, + char *fileName, char *modeString, + int permissions)); + +typedef int (*TclCmdProcType) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[])); +typedef int (*TclObjCmdProcType) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, struct Tcl_Obj * CONST objv[])); + +/* + * Opaque names for platform specific types. + */ + +typedef struct TclpTime_t_ *TclpTime_t; + +/* + *---------------------------------------------------------------- + * Variables shared among Tcl modules but not used by the outside world. + *---------------------------------------------------------------- + */ + +extern Tcl_Time tclBlockTime; +extern int tclBlockTimeSet; +extern char * tclExecutableName; +extern char * tclNativeExecutableName; +extern char * tclDefaultEncodingDir; +extern Tcl_ChannelType tclFileChannelType; +extern char * tclMemDumpFileName; +extern TclPlatformType tclPlatform; +extern char * tclpFileAttrStrings[]; +extern CONST TclFileAttrProcs tclpFileAttrProcs[]; + +/* + * Variables denoting the Tcl object types defined in the core. + */ + +extern Tcl_ObjType tclBooleanType; +extern Tcl_ObjType tclByteArrayType; +extern Tcl_ObjType tclByteCodeType; +extern Tcl_ObjType tclDoubleType; +extern Tcl_ObjType tclIntType; +extern Tcl_ObjType tclListType; +extern Tcl_ObjType tclProcBodyType; +extern Tcl_ObjType tclStringType; + +/* + * The head of the list of free Tcl objects, and the total number of Tcl + * objects ever allocated and freed. + */ + +extern Tcl_Obj * tclFreeObjList; + +#ifdef TCL_COMPILE_STATS +extern long tclObjsAlloced; +extern long tclObjsFreed; +#endif /* TCL_COMPILE_STATS */ + +/* + * Pointer to a heap-allocated string of length zero that the Tcl core uses + * as the value of an empty string representation for an object. This value + * is shared by all new objects allocated by Tcl_NewObj. + */ + +extern char * tclEmptyStringRep; + +/* + *---------------------------------------------------------------- + * Procedures shared among Tcl modules but not used by the outside + * world: + *---------------------------------------------------------------- + */ + +EXTERN int TclAccess _ANSI_ARGS_((CONST char *path, + int mode)); +EXTERN int TclAccessDeleteProc _ANSI_ARGS_((TclAccessProc_ *proc)); +EXTERN int TclAccessInsertProc _ANSI_ARGS_((TclAccessProc_ *proc)); +EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); +EXTERN int TclArraySet _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj)); +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp *interp, + int numPids, Tcl_Pid *pidPtr, + Tcl_Channel errorChan)); +EXTERN void TclCleanupCommand _ANSI_ARGS_((Command *cmdPtr)); +EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Channel inChan, Tcl_Channel outChan, + int toRead, Tcl_Obj *cmdPtr)); +/* + * TclCreatePipeline unofficially exported for use by BLT. + */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv, Tcl_Pid **pidArrayPtr, + TclFile *inPipePtr, TclFile *outPipePtr, + TclFile *errFilePtr)); +EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp *interp, + Namespace *nsPtr, char *procName, + Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, + Proc **procPtrPtr)); +EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_(( + Interp *iPtr, CallFrame *framePtr)); +EXTERN void TclDeleteVars _ANSI_ARGS_((Interp *iPtr, + Tcl_HashTable *tablePtr)); +EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp *interp, + char *separators, Tcl_DString *headPtr, + char *tail)); +EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE *outFile)); +EXTERN void TclExpandTokenArray _ANSI_ARGS_(( + Tcl_Parse *parsePtr)); +EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp *interp, + double value)); +EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)) ; +EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)); +EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)) ; +EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)) ; +EXTERN void TclFinalizeAllocSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeCompExecEnv _ANSI_ARGS_((void)); +EXTERN void TclFinalizeCondition _ANSI_ARGS_(( + Tcl_Condition *condPtr)); +EXTERN void TclFinalizeCompilation _ANSI_ARGS_((void)); +EXTERN void TclFinalizeEncodingSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeEnvironment _ANSI_ARGS_((void)); +EXTERN void TclFinalizeExecution _ANSI_ARGS_((void)); +EXTERN void TclFinalizeIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeLoad _ANSI_ARGS_((void)); +EXTERN void TclFinalizeMemorySubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutex)); +EXTERN void TclFinalizeNotifier _ANSI_ARGS_((void)); +EXTERN void TclFinalizeSynchronization _ANSI_ARGS_((void)); +EXTERN void TclFinalizeThreadData _ANSI_ARGS_((void)); +EXTERN void TclFindEncodings _ANSI_ARGS_((CONST char *argv0)); +EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp *iPtr, + char *procName)); +EXTERN int TclFormatInt _ANSI_ARGS_((char *buffer, long n)); +EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp *iPtr)); +EXTERN int TclGetDate _ANSI_ARGS_((char *p, + unsigned long now, long zone, + unsigned long *timePtr)); +EXTERN Tcl_Obj * TclGetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + Tcl_Obj *elemPtr, int leaveErrorMsg)); +EXTERN char * TclGetExtension _ANSI_ARGS_((char *name)); +EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp *interp, + char *string, CallFrame **framePtrPtr)); +EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void)); +EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr, int endValue, int *indexPtr)); +EXTERN Tcl_Obj * TclGetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp, + int localIndex, int leaveErrorMsg)); +EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp *interp, + char *string, long *longPtr)); +EXTERN int TclGetLoadedPackages _ANSI_ARGS_(( + Tcl_Interp *interp, char *targetName)); +EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_(( + Tcl_Interp *interp, char *qualName, + Namespace *cxtNsPtr, int flags, + Namespace **nsPtrPtr, Namespace **altNsPtrPtr, + Namespace **actualCxtPtrPtr, + char **simpleNamePtr)); +EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void)); +EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp *interp, + char *string, int *seekFlagPtr)); +EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_(( + Tcl_Command command)); +EXTERN int TclGlob _ANSI_ARGS_((Tcl_Interp *interp, + char *pattern, int noComplain)); +EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv, int flags)); +EXTERN int TclGuessPackageName _ANSI_ARGS_((char *fileName, + Tcl_DString *bufPtr)); +EXTERN int TclHideUnsafeCommands _ANSI_ARGS_(( + Tcl_Interp *interp)); +EXTERN int TclInExit _ANSI_ARGS_((void)); +EXTERN Tcl_Obj * TclIncrElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + Tcl_Obj *elemPtr, long incrAmount)); +EXTERN Tcl_Obj * TclIncrIndexedScalar _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + long incrAmount)); +EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, + long incrAmount, int flags)); +EXTERN void TclInitAlloc _ANSI_ARGS_((void)); +EXTERN void TclInitCompiledLocals _ANSI_ARGS_(( + Tcl_Interp *interp, CallFrame *framePtr, + Namespace *nsPtr)); +EXTERN void TclInitDbCkalloc _ANSI_ARGS_((void)); +EXTERN void TclInitEncodingSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNamespaceSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNotifier _ANSI_ARGS_((void)); +EXTERN void TclInitObjSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitSubsystems _ANSI_ARGS_((CONST char *argv0)); +EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv, int flags)); +EXTERN int TclInvokeObjectCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int argc, char **argv)); +EXTERN int TclInvokeStringCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int TclIsLocalScalar _ANSI_ARGS_((CONST char *src, + int len)); +EXTERN Proc * TclIsProc _ANSI_ARGS_((Command *cmdPtr)); +EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp *interp, + char *part1, char *part2, int flags, char *msg, + int createPart1, int createPart2, + Var **arrayPtrPtr)); +EXTERN int TclMathInProgress _ANSI_ARGS_((void)); +EXTERN int TclNeedSpace _ANSI_ARGS_((char *start, char *end)); +EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc *procPtr)); +EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj *cmdPtr)); +EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ *proc)); +EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ *proc)); +EXTERN int TclpAccess _ANSI_ARGS_((CONST char *filename, + int mode)); +EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size)); +EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); +EXTERN int TclpCopyFile _ANSI_ARGS_((CONST char *source, + CONST char *dest)); +EXTERN int TclpCopyDirectory _ANSI_ARGS_((CONST char *source, + CONST char *dest, Tcl_DString *errorPtr)); +EXTERN int TclpCreateDirectory _ANSI_ARGS_((CONST char *path)); +EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char *path)); +EXTERN void TclpExit _ANSI_ARGS_((int status)); +EXTERN void TclpFinalizeCondition _ANSI_ARGS_(( + Tcl_Condition *condPtr)); +EXTERN void TclpFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutexPtr)); +EXTERN void TclpFinalizeThreadData _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpFinalizeThreadDataKey _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN char * TclpFindExecutable _ANSI_ARGS_(( + CONST char *argv0)); +EXTERN int TclpFindVariable _ANSI_ARGS_((CONST char *name, + int *lengthPtr)); +EXTERN void TclpFree _ANSI_ARGS_((char *ptr)); +EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void)); +EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); +EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void)); +EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time *time)); +EXTERN int TclpGetTimeZone _ANSI_ARGS_((unsigned long time)); +EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char *name, + Tcl_DString *bufferPtr)); +EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TclpInitLibraryPath _ANSI_ARGS_((CONST char *argv0)); +EXTERN void TclpInitLock _ANSI_ARGS_((void)); +EXTERN void TclpInitPlatform _ANSI_ARGS_((void)); +EXTERN void TclpInitUnlock _ANSI_ARGS_((void)); +EXTERN int TclpListVolumes _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TclpMasterLock _ANSI_ARGS_((void)); +EXTERN void TclpMasterUnlock _ANSI_ARGS_((void)); +EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp *interp, + char *separators, Tcl_DString *dirPtr, + char *pattern, char *tail)); +EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp, + char *fileName, char *modeString, + int permissions)); +EXTERN char * TclpReadlink _ANSI_ARGS_((CONST char *fileName, + Tcl_DString *linkPtr)); +EXTERN char * TclpRealloc _ANSI_ARGS_((char *ptr, + unsigned int size)); +EXTERN void TclpReleaseFile _ANSI_ARGS_((TclFile file)); +EXTERN int TclpRemoveDirectory _ANSI_ARGS_((CONST char *path, + int recursive, Tcl_DString *errorPtr)); +EXTERN int TclpRenameFile _ANSI_ARGS_((CONST char *source, + CONST char *dest)); +EXTERN void TclpSetInitialEncodings _ANSI_ARGS_((void)); +EXTERN void TclpSetVariables _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN VOID * TclpSysAlloc _ANSI_ARGS_((long size, int isBin)); +EXTERN void TclpSysFree _ANSI_ARGS_((VOID *ptr)); +EXTERN VOID * TclpSysRealloc _ANSI_ARGS_((VOID *cp, + unsigned int size)); +EXTERN void TclpUnloadFile _ANSI_ARGS_((ClientData clientData)); +EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, char *name1, char *name2, + int flags)); +EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *cmdInterp, Tcl_Command cmd)); +EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc *procPtr)); +EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp *interp, + Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, + CONST char *description, CONST char *procName)); +EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int TclpThreadCreate _ANSI_ARGS_((Tcl_ThreadId *idPtr, + Tcl_ThreadCreateProc proc, ClientData clientData)); +EXTERN VOID * TclpThreadDataKeyGet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeyInit _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeySet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr, VOID *data)); +EXTERN void TclpThreadExit _ANSI_ARGS_((int status)); +EXTERN void TclRememberCondition _ANSI_ARGS_((Tcl_Condition *mutex)); +EXTERN void TclRememberDataKey _ANSI_ARGS_((Tcl_ThreadDataKey *mutex)); +EXTERN void TclRememberMutex _ANSI_ARGS_((Tcl_Mutex *mutex)); +EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp *interp, + char *oldName, char *newName)) ; +EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_(( + Tcl_Interp *interp, Command *newCmdPtr)); +EXTERN int TclServiceIdle _ANSI_ARGS_((void)); +EXTERN Tcl_Obj * TclSetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + Tcl_Obj *elemPtr, Tcl_Obj *objPtr, + int leaveErrorMsg)); +EXTERN Tcl_Obj * TclSetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp, + int localIndex, Tcl_Obj *objPtr, + int leaveErrorMsg)); +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char *string)); +EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp *interp, + char *string, char *proto, int *portPtr)); +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +EXTERN int TclStat _ANSI_ARGS_((CONST char *path, + struct stat *buf)); +EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ *proc)); +EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ *proc)); +EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace *nsPtr)); +EXTERN void TclTransferResult _ANSI_ARGS_((Tcl_Interp *sourceInterp, + int result, Tcl_Interp *targetInterp)); +EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp *iPtr)); + +/* + *---------------------------------------------------------------- + * Command procedures in the generic core: + *---------------------------------------------------------------- + */ + +EXTERN int Tcl_AfterObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_AppendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ArrayObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BinaryObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BreakObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CaseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ClockObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CloseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ConcatObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ContinueObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EncodingObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EofObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExecObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExprObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FblockedObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FconfigureObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FcopyObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FileObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FileEventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FlushObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ForObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ForeachObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FormatObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GetsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GlobalObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GlobObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IfObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IncrObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_InfoObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_InterpObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_JoinObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LappendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LindexObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LinsertObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LlengthObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ListObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LoadObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LrangeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LreplaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LsearchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LsortObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_NamespaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_OpenObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PackageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PidObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ProcObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PutsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PwdObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ReadObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RegexpObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RegsubObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RenameObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ReturnObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ScanObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SeekObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SplitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SocketObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_StringObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SubstObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SwitchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TellObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TimeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TraceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UnsetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UplevelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UpvarObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_VariableObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_VwaitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_WhileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); + +/* + *---------------------------------------------------------------- + * Command procedures found only in the Mac version of the core: + *---------------------------------------------------------------- + */ + +#ifdef MAC_TCL +EXTERN int Tcl_EchoCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_LsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BeepObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_MacSourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ResourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +#endif + +/* + *---------------------------------------------------------------- + * Compilation procedures for commands in the generic core: + *---------------------------------------------------------------- + */ + +EXTERN int TclCompileBreakCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileCatchCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileContinueCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileExprCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileForCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileForeachCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileIfCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileIncrCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileSetCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileWhileCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); + +/* + *---------------------------------------------------------------- + * Macros used by the Tcl core to create and release Tcl objects. + * TclNewObj(objPtr) creates a new object denoting an empty string. + * TclDecrRefCount(objPtr) decrements the object's reference count, + * and frees the object if its reference count is zero. + * These macros are inline versions of Tcl_NewObj() and + * Tcl_DecrRefCount(). Notice that the names differ in not having + * a "_" after the "Tcl". Notice also that these macros reference + * their argument more than once, so you should avoid calling them + * with an expression that is expensive to compute or has + * side effects. The ANSI C "prototypes" for these macros are: + * + * EXTERN void TclNewObj _ANSI_ARGS_((Tcl_Obj *objPtr)); + * EXTERN void TclDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr)); + *---------------------------------------------------------------- + */ + +#ifdef TCL_COMPILE_STATS +# define TclIncrObjsAllocated() \ + tclObjsAlloced++ +# define TclIncrObjsFreed() \ + tclObjsFreed++ +#else +# define TclIncrObjsAllocated() +# define TclIncrObjsFreed() +#endif /* TCL_COMPILE_STATS */ + +#ifdef TCL_MEM_DEBUG +# define TclNewObj(objPtr) \ + (objPtr) = (Tcl_Obj *) \ + Tcl_DbCkalloc(sizeof(Tcl_Obj), __FILE__, __LINE__); \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL; \ + TclIncrObjsAllocated() + +# define TclDbNewObj(objPtr, file, line) \ + (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL; \ + TclIncrObjsAllocated() + +# define TclDecrRefCount(objPtr) \ + if (--(objPtr)->refCount <= 0) { \ + if ((objPtr)->refCount < -1) \ + panic("Reference count for %lx was negative: %s line %d", \ + (objPtr), __FILE__, __LINE__); \ + if (((objPtr)->bytes != NULL) \ + && ((objPtr)->bytes != tclEmptyStringRep)) { \ + ckfree((char *) (objPtr)->bytes); \ + } \ + if (((objPtr)->typePtr != NULL) \ + && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ + (objPtr)->typePtr->freeIntRepProc(objPtr); \ + } \ + ckfree((char *) (objPtr)); \ + TclIncrObjsFreed(); \ + } + +#else /* not TCL_MEM_DEBUG */ + +#ifdef TCL_THREADS +extern Tcl_Mutex tclObjMutex; +#endif + +# define TclNewObj(objPtr) \ + Tcl_MutexLock(&tclObjMutex); \ + if (tclFreeObjList == NULL) { \ + TclAllocateFreeObjects(); \ + } \ + (objPtr) = tclFreeObjList; \ + tclFreeObjList = (Tcl_Obj *) \ + tclFreeObjList->internalRep.otherValuePtr; \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL; \ + TclIncrObjsAllocated(); \ + Tcl_MutexUnlock(&tclObjMutex) + +# define TclDecrRefCount(objPtr) \ + if (--(objPtr)->refCount <= 0) { \ + if (((objPtr)->bytes != NULL) \ + && ((objPtr)->bytes != tclEmptyStringRep)) { \ + ckfree((char *) (objPtr)->bytes); \ + } \ + if (((objPtr)->typePtr != NULL) \ + && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ + (objPtr)->typePtr->freeIntRepProc(objPtr); \ + } \ + Tcl_MutexLock(&tclObjMutex); \ + (objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \ + tclFreeObjList = (objPtr); \ + TclIncrObjsFreed(); \ + Tcl_MutexUnlock(&tclObjMutex); \ + } +#endif /* TCL_MEM_DEBUG */ + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to set a Tcl_Obj's string representation + * to a copy of the "len" bytes starting at "bytePtr". This code + * works even if the byte array contains NULLs as long as the length + * is correct. Because "len" is referenced multiple times, it should + * be as simple an expression as possible. The ANSI C "prototype" for + * this macro is: + * + * EXTERN void TclInitStringRep _ANSI_ARGS_((Tcl_Obj *objPtr, + * char *bytePtr, int len)); + *---------------------------------------------------------------- + */ + +#define TclInitStringRep(objPtr, bytePtr, len) \ + if ((len) == 0) { \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + } else { \ + (objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \ + memcpy((VOID *) (objPtr)->bytes, (VOID *) (bytePtr), \ + (unsigned) (len)); \ + (objPtr)->bytes[len] = '\0'; \ + (objPtr)->length = (len); \ + } + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to get the string representation's + * byte array pointer from a Tcl_Obj. This is an inline version + * of Tcl_GetString(). The macro's expression result is the string + * rep's byte pointer which might be NULL. The bytes referenced by + * this pointer must not be modified by the caller. + * The ANSI C "prototype" for this macro is: + * + * EXTERN char * TclGetString _ANSI_ARGS_((Tcl_Obj *objPtr)); + *---------------------------------------------------------------- + */ + +#define TclGetString(objPtr) \ + ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr))) + +#include "tclIntDecls.h" + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TCLINT */ + diff --git a/Utilities/TclTk/internals/tk8.2/tclIntDecls.h b/Utilities/TclTk/internals/tk8.2/tclIntDecls.h new file mode 100644 index 0000000..0f337c4 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tclIntDecls.h @@ -0,0 +1,1363 @@ +/* + * tclIntDecls.h -- + * + * This file contains the declarations for all unsupported + * functions that are exported by the Tcl library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclIntDecls.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TCLINTDECLS +#define _TCLINTDECLS + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tclInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +/* 0 */ +EXTERN int TclAccess _ANSI_ARGS_((CONST char * path, int mode)); +/* 1 */ +EXTERN int TclAccessDeleteProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 2 */ +EXTERN int TclAccessInsertProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 3 */ +EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); +/* Slot 4 is reserved */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 5 */ +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp, + int numPids, Tcl_Pid * pidPtr, + Tcl_Channel errorChan)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 5 */ +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp, + int numPids, Tcl_Pid * pidPtr, + Tcl_Channel errorChan)); +#endif /* __WIN32__ */ +/* 6 */ +EXTERN void TclCleanupCommand _ANSI_ARGS_((Command * cmdPtr)); +/* 7 */ +EXTERN int TclCopyAndCollapse _ANSI_ARGS_((int count, + CONST char * src, char * dst)); +/* 8 */ +EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel inChan, Tcl_Channel outChan, + int toRead, Tcl_Obj * cmdPtr)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 9 */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, + Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, + TclFile * outPipePtr, TclFile * errFilePtr)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 9 */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, + Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, + TclFile * outPipePtr, TclFile * errFilePtr)); +#endif /* __WIN32__ */ +/* 10 */ +EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp * interp, + Namespace * nsPtr, char * procName, + Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, + Proc ** procPtrPtr)); +/* 11 */ +EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_(( + Interp * iPtr, CallFrame * framePtr)); +/* 12 */ +EXTERN void TclDeleteVars _ANSI_ARGS_((Interp * iPtr, + Tcl_HashTable * tablePtr)); +/* 13 */ +EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * headPtr, + char * tail)); +/* 14 */ +EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE * outFile)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp * interp, + double value)); +/* 17 */ +EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[])); +/* 18 */ +EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 19 */ +EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 20 */ +EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 21 */ +EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 22 */ +EXTERN int TclFindElement _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * listStr, int listLength, + CONST char ** elementPtr, + CONST char ** nextPtr, int * sizePtr, + int * bracePtr)); +/* 23 */ +EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp * iPtr, + char * procName)); +/* 24 */ +EXTERN int TclFormatInt _ANSI_ARGS_((char * buffer, long n)); +/* 25 */ +EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 26 is reserved */ +/* 27 */ +EXTERN int TclGetDate _ANSI_ARGS_((char * p, unsigned long now, + long zone, unsigned long * timePtr)); +/* 28 */ +EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); +/* 29 */ +EXTERN Tcl_Obj * TclGetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, int leaveErrorMsg)); +/* Slot 30 is reserved */ +/* 31 */ +EXTERN char * TclGetExtension _ANSI_ARGS_((char * name)); +/* 32 */ +EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp * interp, + char * str, CallFrame ** framePtrPtr)); +/* 33 */ +EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void)); +/* 34 */ +EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, int endValue, + int * indexPtr)); +/* 35 */ +EXTERN Tcl_Obj * TclGetIndexedScalar _ANSI_ARGS_((Tcl_Interp * interp, + int localIndex, int leaveErrorMsg)); +/* 36 */ +EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp * interp, + char * str, long * longPtr)); +/* 37 */ +EXTERN int TclGetLoadedPackages _ANSI_ARGS_(( + Tcl_Interp * interp, char * targetName)); +/* 38 */ +EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_(( + Tcl_Interp * interp, char * qualName, + Namespace * cxtNsPtr, int flags, + Namespace ** nsPtrPtr, + Namespace ** altNsPtrPtr, + Namespace ** actualCxtPtrPtr, + char ** simpleNamePtr)); +/* 39 */ +EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void)); +/* 40 */ +EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp * interp, + char * str, int * seekFlagPtr)); +/* 41 */ +EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_(( + Tcl_Command command)); +/* 42 */ +EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char * name, + Tcl_DString * bufferPtr)); +/* 43 */ +EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, int flags)); +/* 44 */ +EXTERN int TclGuessPackageName _ANSI_ARGS_((char * fileName, + Tcl_DString * bufPtr)); +/* 45 */ +EXTERN int TclHideUnsafeCommands _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 46 */ +EXTERN int TclInExit _ANSI_ARGS_((void)); +/* 47 */ +EXTERN Tcl_Obj * TclIncrElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, long incrAmount)); +/* 48 */ +EXTERN Tcl_Obj * TclIncrIndexedScalar _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + long incrAmount)); +/* 49 */ +EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, + long incrAmount, int part1NotParsed)); +/* 50 */ +EXTERN void TclInitCompiledLocals _ANSI_ARGS_(( + Tcl_Interp * interp, CallFrame * framePtr, + Namespace * nsPtr)); +/* 51 */ +EXTERN int TclInterpInit _ANSI_ARGS_((Tcl_Interp * interp)); +/* 52 */ +EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp * interp, int argc, + char ** argv, int flags)); +/* 53 */ +EXTERN int TclInvokeObjectCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int argc, char ** argv)); +/* 54 */ +EXTERN int TclInvokeStringCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[])); +/* 55 */ +EXTERN Proc * TclIsProc _ANSI_ARGS_((Command * cmdPtr)); +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +/* 58 */ +EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags, + char * msg, int createPart1, int createPart2, + Var ** arrayPtrPtr)); +/* 59 */ +EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * dirPtr, + char * pattern, char * tail)); +/* 60 */ +EXTERN int TclNeedSpace _ANSI_ARGS_((char * start, char * end)); +/* 61 */ +EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc * procPtr)); +/* 62 */ +EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj * cmdPtr)); +/* 63 */ +EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int objc, + Tcl_Obj *CONST objv[])); +/* 64 */ +EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 65 */ +EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 66 */ +EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* 67 */ +EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* 68 */ +EXTERN int TclpAccess _ANSI_ARGS_((CONST char * path, int mode)); +/* 69 */ +EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size)); +/* 70 */ +EXTERN int TclpCopyFile _ANSI_ARGS_((CONST char * source, + CONST char * dest)); +/* 71 */ +EXTERN int TclpCopyDirectory _ANSI_ARGS_((CONST char * source, + CONST char * dest, Tcl_DString * errorPtr)); +/* 72 */ +EXTERN int TclpCreateDirectory _ANSI_ARGS_((CONST char * path)); +/* 73 */ +EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char * path)); +/* 74 */ +EXTERN void TclpFree _ANSI_ARGS_((char * ptr)); +/* 75 */ +EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void)); +/* 76 */ +EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void)); +/* 77 */ +EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time * time)); +/* 78 */ +EXTERN int TclpGetTimeZone _ANSI_ARGS_((unsigned long time)); +/* 79 */ +EXTERN int TclpListVolumes _ANSI_ARGS_((Tcl_Interp * interp)); +/* 80 */ +EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName, char * modeString, + int permissions)); +/* 81 */ +EXTERN char * TclpRealloc _ANSI_ARGS_((char * ptr, + unsigned int size)); +/* 82 */ +EXTERN int TclpRemoveDirectory _ANSI_ARGS_((CONST char * path, + int recursive, Tcl_DString * errorPtr)); +/* 83 */ +EXTERN int TclpRenameFile _ANSI_ARGS_((CONST char * source, + CONST char * dest)); +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +/* 88 */ +EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, char * name1, + char * name2, int flags)); +/* 89 */ +EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Interp * cmdInterp, Tcl_Command cmd)); +/* Slot 90 is reserved */ +/* 91 */ +EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc * procPtr)); +/* 92 */ +EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp * interp, + Proc * procPtr, Tcl_Obj * bodyPtr, + Namespace * nsPtr, CONST char * description, + CONST char * procName)); +/* 93 */ +EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +/* 94 */ +EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, char ** argv)); +/* 95 */ +EXTERN int TclpStat _ANSI_ARGS_((CONST char * path, + struct stat * buf)); +/* 96 */ +EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * oldName, char * newName)); +/* 97 */ +EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_(( + Tcl_Interp * interp, Command * newCmdPtr)); +/* 98 */ +EXTERN int TclServiceIdle _ANSI_ARGS_((void)); +/* 99 */ +EXTERN Tcl_Obj * TclSetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, Tcl_Obj * objPtr, + int leaveErrorMsg)); +/* 100 */ +EXTERN Tcl_Obj * TclSetIndexedScalar _ANSI_ARGS_((Tcl_Interp * interp, + int localIndex, Tcl_Obj * objPtr, + int leaveErrorMsg)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 101 */ +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char * string)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 101 */ +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char * string)); +#endif /* __WIN32__ */ +/* 102 */ +EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp * interp)); +/* 103 */ +EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp * interp, + char * str, char * proto, int * portPtr)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 104 */ +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 104 */ +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +#endif /* __WIN32__ */ +/* 105 */ +EXTERN int TclStat _ANSI_ARGS_((CONST char * path, + struct stat * buf)); +/* 106 */ +EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 107 */ +EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 108 */ +EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace * nsPtr)); +/* 109 */ +EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 110 is reserved */ +/* 111 */ +EXTERN void Tcl_AddInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 112 */ +EXTERN int Tcl_AppendExportList _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Namespace * nsPtr, + Tcl_Obj * objPtr)); +/* 113 */ +EXTERN Tcl_Namespace * Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp * interp, + char * name, ClientData clientData, + Tcl_NamespaceDeleteProc * deleteProc)); +/* 114 */ +EXTERN void Tcl_DeleteNamespace _ANSI_ARGS_(( + Tcl_Namespace * nsPtr)); +/* 115 */ +EXTERN int Tcl_Export _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern, + int resetListFirst)); +/* 116 */ +EXTERN Tcl_Command Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_Namespace * contextNsPtr, + int flags)); +/* 117 */ +EXTERN Tcl_Namespace * Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_Namespace * contextNsPtr, + int flags)); +/* 118 */ +EXTERN int Tcl_GetInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_ResolverInfo * resInfo)); +/* 119 */ +EXTERN int Tcl_GetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolverInfo * resInfo)); +/* 120 */ +EXTERN Tcl_Var Tcl_FindNamespaceVar _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_Namespace * contextNsPtr, int flags)); +/* 121 */ +EXTERN int Tcl_ForgetImport _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern)); +/* 122 */ +EXTERN Tcl_Command Tcl_GetCommandFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr)); +/* 123 */ +EXTERN void Tcl_GetCommandFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Command command, + Tcl_Obj * objPtr)); +/* 124 */ +EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 125 */ +EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 126 */ +EXTERN void Tcl_GetVariableFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Var variable, + Tcl_Obj * objPtr)); +/* 127 */ +EXTERN int Tcl_Import _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern, + int allowOverwrite)); +/* 128 */ +EXTERN void Tcl_PopCallFrame _ANSI_ARGS_((Tcl_Interp* interp)); +/* 129 */ +EXTERN int Tcl_PushCallFrame _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_CallFrame * framePtr, + Tcl_Namespace * nsPtr, int isProcCallFrame)); +/* 130 */ +EXTERN int Tcl_RemoveInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name)); +/* 131 */ +EXTERN void Tcl_SetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 132 */ +EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp * interp)); +/* 133 */ +EXTERN struct tm * TclpGetDate _ANSI_ARGS_((TclpTime_t time, int useGMT)); +/* 134 */ +EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize, + CONST char * format, CONST struct tm * t)); +/* 135 */ +EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); +/* Slot 136 is reserved */ +/* 137 */ +EXTERN int TclpChdir _ANSI_ARGS_((CONST char * dirName)); +/* 138 */ +EXTERN char * TclGetEnv _ANSI_ARGS_((CONST char * name, + Tcl_DString * valuePtr)); +/* 139 */ +EXTERN int TclpLoadFile _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName, char * sym1, char * sym2, + Tcl_PackageInitProc ** proc1Ptr, + Tcl_PackageInitProc ** proc2Ptr, + ClientData * clientDataPtr)); +/* 140 */ +EXTERN int TclLooksLikeInt _ANSI_ARGS_((char * bytes, + int length)); +/* 141 */ +EXTERN char * TclpGetCwd _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * cwdPtr)); +/* 142 */ +EXTERN int TclSetByteCodeFromAny _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr, + CompileHookProc * hookProc, + ClientData clientData)); +/* 143 */ +EXTERN int TclAddLiteralObj _ANSI_ARGS_(( + struct CompileEnv * envPtr, Tcl_Obj * objPtr, + LiteralEntry ** litPtrPtr)); +/* 144 */ +EXTERN void TclHideLiteral _ANSI_ARGS_((Tcl_Interp * interp, + struct CompileEnv * envPtr, int index)); +/* 145 */ +EXTERN struct AuxDataType * TclGetAuxDataType _ANSI_ARGS_((char * typeName)); +/* 146 */ +EXTERN TclHandle TclHandleCreate _ANSI_ARGS_((VOID * ptr)); +/* 147 */ +EXTERN void TclHandleFree _ANSI_ARGS_((TclHandle handle)); +/* 148 */ +EXTERN TclHandle TclHandlePreserve _ANSI_ARGS_((TclHandle handle)); +/* 149 */ +EXTERN void TclHandleRelease _ANSI_ARGS_((TclHandle handle)); +/* 150 */ +EXTERN int TclRegAbout _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_RegExp re)); +/* 151 */ +EXTERN void TclRegExpRangeUniChar _ANSI_ARGS_((Tcl_RegExp re, + int index, int * startPtr, int * endPtr)); +/* 152 */ +EXTERN void TclSetLibraryPath _ANSI_ARGS_((Tcl_Obj * pathPtr)); +/* 153 */ +EXTERN Tcl_Obj * TclGetLibraryPath _ANSI_ARGS_((void)); +/* 154 */ +EXTERN int TclTestChannelCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, char ** argv)); +/* 155 */ +EXTERN int TclTestChannelEventCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int argc, char ** argv)); +/* 156 */ +EXTERN void TclRegError _ANSI_ARGS_((Tcl_Interp * interp, + char * msg, int status)); +/* 157 */ +EXTERN Var * TclVarTraceExists _ANSI_ARGS_((Tcl_Interp * interp, + char * varName)); + +typedef struct TclIntStubs { + int magic; + struct TclIntStubHooks *hooks; + + int (*tclAccess) _ANSI_ARGS_((CONST char * path, int mode)); /* 0 */ + int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */ + int (*tclAccessInsertProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 2 */ + void (*tclAllocateFreeObjects) _ANSI_ARGS_((void)); /* 3 */ + void *reserved4; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved5; +#endif /* MAC_TCL */ + void (*tclCleanupCommand) _ANSI_ARGS_((Command * cmdPtr)); /* 6 */ + int (*tclCopyAndCollapse) _ANSI_ARGS_((int count, CONST char * src, char * dst)); /* 7 */ + int (*tclCopyChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj * cmdPtr)); /* 8 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved9; +#endif /* MAC_TCL */ + int (*tclCreateProc) _ANSI_ARGS_((Tcl_Interp * interp, Namespace * nsPtr, char * procName, Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, Proc ** procPtrPtr)); /* 10 */ + void (*tclDeleteCompiledLocalVars) _ANSI_ARGS_((Interp * iPtr, CallFrame * framePtr)); /* 11 */ + void (*tclDeleteVars) _ANSI_ARGS_((Interp * iPtr, Tcl_HashTable * tablePtr)); /* 12 */ + int (*tclDoGlob) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * headPtr, char * tail)); /* 13 */ + void (*tclDumpMemoryInfo) _ANSI_ARGS_((FILE * outFile)); /* 14 */ + void *reserved15; + void (*tclExprFloatError) _ANSI_ARGS_((Tcl_Interp * interp, double value)); /* 16 */ + int (*tclFileAttrsCmd) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 17 */ + int (*tclFileCopyCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 18 */ + int (*tclFileDeleteCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 19 */ + int (*tclFileMakeDirsCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 20 */ + int (*tclFileRenameCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 21 */ + int (*tclFindElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * listStr, int listLength, CONST char ** elementPtr, CONST char ** nextPtr, int * sizePtr, int * bracePtr)); /* 22 */ + Proc * (*tclFindProc) _ANSI_ARGS_((Interp * iPtr, char * procName)); /* 23 */ + int (*tclFormatInt) _ANSI_ARGS_((char * buffer, long n)); /* 24 */ + void (*tclFreePackageInfo) _ANSI_ARGS_((Interp * iPtr)); /* 25 */ + void *reserved26; + int (*tclGetDate) _ANSI_ARGS_((char * p, unsigned long now, long zone, unsigned long * timePtr)); /* 27 */ + Tcl_Channel (*tclpGetDefaultStdChannel) _ANSI_ARGS_((int type)); /* 28 */ + Tcl_Obj * (*tclGetElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, int leaveErrorMsg)); /* 29 */ + void *reserved30; + char * (*tclGetExtension) _ANSI_ARGS_((char * name)); /* 31 */ + int (*tclGetFrame) _ANSI_ARGS_((Tcl_Interp * interp, char * str, CallFrame ** framePtrPtr)); /* 32 */ + TclCmdProcType (*tclGetInterpProc) _ANSI_ARGS_((void)); /* 33 */ + int (*tclGetIntForIndex) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int endValue, int * indexPtr)); /* 34 */ + Tcl_Obj * (*tclGetIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, int leaveErrorMsg)); /* 35 */ + int (*tclGetLong) _ANSI_ARGS_((Tcl_Interp * interp, char * str, long * longPtr)); /* 36 */ + int (*tclGetLoadedPackages) _ANSI_ARGS_((Tcl_Interp * interp, char * targetName)); /* 37 */ + int (*tclGetNamespaceForQualName) _ANSI_ARGS_((Tcl_Interp * interp, char * qualName, Namespace * cxtNsPtr, int flags, Namespace ** nsPtrPtr, Namespace ** altNsPtrPtr, Namespace ** actualCxtPtrPtr, char ** simpleNamePtr)); /* 38 */ + TclObjCmdProcType (*tclGetObjInterpProc) _ANSI_ARGS_((void)); /* 39 */ + int (*tclGetOpenMode) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * seekFlagPtr)); /* 40 */ + Tcl_Command (*tclGetOriginalCommand) _ANSI_ARGS_((Tcl_Command command)); /* 41 */ + char * (*tclpGetUserHome) _ANSI_ARGS_((CONST char * name, Tcl_DString * bufferPtr)); /* 42 */ + int (*tclGlobalInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, int flags)); /* 43 */ + int (*tclGuessPackageName) _ANSI_ARGS_((char * fileName, Tcl_DString * bufPtr)); /* 44 */ + int (*tclHideUnsafeCommands) _ANSI_ARGS_((Tcl_Interp * interp)); /* 45 */ + int (*tclInExit) _ANSI_ARGS_((void)); /* 46 */ + Tcl_Obj * (*tclIncrElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, long incrAmount)); /* 47 */ + Tcl_Obj * (*tclIncrIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, long incrAmount)); /* 48 */ + Tcl_Obj * (*tclIncrVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, long incrAmount, int part1NotParsed)); /* 49 */ + void (*tclInitCompiledLocals) _ANSI_ARGS_((Tcl_Interp * interp, CallFrame * framePtr, Namespace * nsPtr)); /* 50 */ + int (*tclInterpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 51 */ + int (*tclInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, int flags)); /* 52 */ + int (*tclInvokeObjectCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 53 */ + int (*tclInvokeStringCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 54 */ + Proc * (*tclIsProc) _ANSI_ARGS_((Command * cmdPtr)); /* 55 */ + void *reserved56; + void *reserved57; + Var * (*tclLookupVar) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags, char * msg, int createPart1, int createPart2, Var ** arrayPtrPtr)); /* 58 */ + int (*tclpMatchFiles) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * dirPtr, char * pattern, char * tail)); /* 59 */ + int (*tclNeedSpace) _ANSI_ARGS_((char * start, char * end)); /* 60 */ + Tcl_Obj * (*tclNewProcBodyObj) _ANSI_ARGS_((Proc * procPtr)); /* 61 */ + int (*tclObjCommandComplete) _ANSI_ARGS_((Tcl_Obj * cmdPtr)); /* 62 */ + int (*tclObjInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 63 */ + int (*tclObjInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 64 */ + int (*tclObjInvokeGlobal) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 65 */ + int (*tclOpenFileChannelDeleteProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 66 */ + int (*tclOpenFileChannelInsertProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 67 */ + int (*tclpAccess) _ANSI_ARGS_((CONST char * path, int mode)); /* 68 */ + char * (*tclpAlloc) _ANSI_ARGS_((unsigned int size)); /* 69 */ + int (*tclpCopyFile) _ANSI_ARGS_((CONST char * source, CONST char * dest)); /* 70 */ + int (*tclpCopyDirectory) _ANSI_ARGS_((CONST char * source, CONST char * dest, Tcl_DString * errorPtr)); /* 71 */ + int (*tclpCreateDirectory) _ANSI_ARGS_((CONST char * path)); /* 72 */ + int (*tclpDeleteFile) _ANSI_ARGS_((CONST char * path)); /* 73 */ + void (*tclpFree) _ANSI_ARGS_((char * ptr)); /* 74 */ + unsigned long (*tclpGetClicks) _ANSI_ARGS_((void)); /* 75 */ + unsigned long (*tclpGetSeconds) _ANSI_ARGS_((void)); /* 76 */ + void (*tclpGetTime) _ANSI_ARGS_((Tcl_Time * time)); /* 77 */ + int (*tclpGetTimeZone) _ANSI_ARGS_((unsigned long time)); /* 78 */ + int (*tclpListVolumes) _ANSI_ARGS_((Tcl_Interp * interp)); /* 79 */ + Tcl_Channel (*tclpOpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName, char * modeString, int permissions)); /* 80 */ + char * (*tclpRealloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 81 */ + int (*tclpRemoveDirectory) _ANSI_ARGS_((CONST char * path, int recursive, Tcl_DString * errorPtr)); /* 82 */ + int (*tclpRenameFile) _ANSI_ARGS_((CONST char * source, CONST char * dest)); /* 83 */ + void *reserved84; + void *reserved85; + void *reserved86; + void *reserved87; + char * (*tclPrecTraceProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, char * name1, char * name2, int flags)); /* 88 */ + int (*tclPreventAliasLoop) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Interp * cmdInterp, Tcl_Command cmd)); /* 89 */ + void *reserved90; + void (*tclProcCleanupProc) _ANSI_ARGS_((Proc * procPtr)); /* 91 */ + int (*tclProcCompileProc) _ANSI_ARGS_((Tcl_Interp * interp, Proc * procPtr, Tcl_Obj * bodyPtr, Namespace * nsPtr, CONST char * description, CONST char * procName)); /* 92 */ + void (*tclProcDeleteProc) _ANSI_ARGS_((ClientData clientData)); /* 93 */ + int (*tclProcInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 94 */ + int (*tclpStat) _ANSI_ARGS_((CONST char * path, struct stat * buf)); /* 95 */ + int (*tclRenameCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * oldName, char * newName)); /* 96 */ + void (*tclResetShadowedCmdRefs) _ANSI_ARGS_((Tcl_Interp * interp, Command * newCmdPtr)); /* 97 */ + int (*tclServiceIdle) _ANSI_ARGS_((void)); /* 98 */ + Tcl_Obj * (*tclSetElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, Tcl_Obj * objPtr, int leaveErrorMsg)); /* 99 */ + Tcl_Obj * (*tclSetIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * objPtr, int leaveErrorMsg)); /* 100 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + char * (*tclSetPreInitScript) _ANSI_ARGS_((char * string)); /* 101 */ +#endif /* UNIX */ +#ifdef __WIN32__ + char * (*tclSetPreInitScript) _ANSI_ARGS_((char * string)); /* 101 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved101; +#endif /* MAC_TCL */ + void (*tclSetupEnv) _ANSI_ARGS_((Tcl_Interp * interp)); /* 102 */ + int (*tclSockGetPort) _ANSI_ARGS_((Tcl_Interp * interp, char * str, char * proto, int * portPtr)); /* 103 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved104; +#endif /* MAC_TCL */ + int (*tclStat) _ANSI_ARGS_((CONST char * path, struct stat * buf)); /* 105 */ + int (*tclStatDeleteProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 106 */ + int (*tclStatInsertProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 107 */ + void (*tclTeardownNamespace) _ANSI_ARGS_((Namespace * nsPtr)); /* 108 */ + int (*tclUpdateReturnInfo) _ANSI_ARGS_((Interp * iPtr)); /* 109 */ + void *reserved110; + void (*tcl_AddInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 111 */ + int (*tcl_AppendExportList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, Tcl_Obj * objPtr)); /* 112 */ + Tcl_Namespace * (*tcl_CreateNamespace) _ANSI_ARGS_((Tcl_Interp * interp, char * name, ClientData clientData, Tcl_NamespaceDeleteProc * deleteProc)); /* 113 */ + void (*tcl_DeleteNamespace) _ANSI_ARGS_((Tcl_Namespace * nsPtr)); /* 114 */ + int (*tcl_Export) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern, int resetListFirst)); /* 115 */ + Tcl_Command (*tcl_FindCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 116 */ + Tcl_Namespace * (*tcl_FindNamespace) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 117 */ + int (*tcl_GetInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_ResolverInfo * resInfo)); /* 118 */ + int (*tcl_GetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolverInfo * resInfo)); /* 119 */ + Tcl_Var (*tcl_FindNamespaceVar) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 120 */ + int (*tcl_ForgetImport) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern)); /* 121 */ + Tcl_Command (*tcl_GetCommandFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 122 */ + void (*tcl_GetCommandFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command, Tcl_Obj * objPtr)); /* 123 */ + Tcl_Namespace * (*tcl_GetCurrentNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 124 */ + Tcl_Namespace * (*tcl_GetGlobalNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 125 */ + void (*tcl_GetVariableFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Var variable, Tcl_Obj * objPtr)); /* 126 */ + int (*tcl_Import) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern, int allowOverwrite)); /* 127 */ + void (*tcl_PopCallFrame) _ANSI_ARGS_((Tcl_Interp* interp)); /* 128 */ + int (*tcl_PushCallFrame) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_CallFrame * framePtr, Tcl_Namespace * nsPtr, int isProcCallFrame)); /* 129 */ + int (*tcl_RemoveInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name)); /* 130 */ + void (*tcl_SetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 131 */ + int (*tclpHasSockets) _ANSI_ARGS_((Tcl_Interp * interp)); /* 132 */ + struct tm * (*tclpGetDate) _ANSI_ARGS_((TclpTime_t time, int useGMT)); /* 133 */ + size_t (*tclpStrftime) _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t)); /* 134 */ + int (*tclpCheckStackSpace) _ANSI_ARGS_((void)); /* 135 */ + void *reserved136; + int (*tclpChdir) _ANSI_ARGS_((CONST char * dirName)); /* 137 */ + char * (*tclGetEnv) _ANSI_ARGS_((CONST char * name, Tcl_DString * valuePtr)); /* 138 */ + int (*tclpLoadFile) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName, char * sym1, char * sym2, Tcl_PackageInitProc ** proc1Ptr, Tcl_PackageInitProc ** proc2Ptr, ClientData * clientDataPtr)); /* 139 */ + int (*tclLooksLikeInt) _ANSI_ARGS_((char * bytes, int length)); /* 140 */ + char * (*tclpGetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 141 */ + int (*tclSetByteCodeFromAny) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CompileHookProc * hookProc, ClientData clientData)); /* 142 */ + int (*tclAddLiteralObj) _ANSI_ARGS_((struct CompileEnv * envPtr, Tcl_Obj * objPtr, LiteralEntry ** litPtrPtr)); /* 143 */ + void (*tclHideLiteral) _ANSI_ARGS_((Tcl_Interp * interp, struct CompileEnv * envPtr, int index)); /* 144 */ + struct AuxDataType * (*tclGetAuxDataType) _ANSI_ARGS_((char * typeName)); /* 145 */ + TclHandle (*tclHandleCreate) _ANSI_ARGS_((VOID * ptr)); /* 146 */ + void (*tclHandleFree) _ANSI_ARGS_((TclHandle handle)); /* 147 */ + TclHandle (*tclHandlePreserve) _ANSI_ARGS_((TclHandle handle)); /* 148 */ + void (*tclHandleRelease) _ANSI_ARGS_((TclHandle handle)); /* 149 */ + int (*tclRegAbout) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp re)); /* 150 */ + void (*tclRegExpRangeUniChar) _ANSI_ARGS_((Tcl_RegExp re, int index, int * startPtr, int * endPtr)); /* 151 */ + void (*tclSetLibraryPath) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 152 */ + Tcl_Obj * (*tclGetLibraryPath) _ANSI_ARGS_((void)); /* 153 */ + int (*tclTestChannelCmd) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 154 */ + int (*tclTestChannelEventCmd) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 155 */ + void (*tclRegError) _ANSI_ARGS_((Tcl_Interp * interp, char * msg, int status)); /* 156 */ + Var * (*tclVarTraceExists) _ANSI_ARGS_((Tcl_Interp * interp, char * varName)); /* 157 */ +} TclIntStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TclIntStubs *tclIntStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifndef TclAccess +#define TclAccess \ + (tclIntStubsPtr->tclAccess) /* 0 */ +#endif +#ifndef TclAccessDeleteProc +#define TclAccessDeleteProc \ + (tclIntStubsPtr->tclAccessDeleteProc) /* 1 */ +#endif +#ifndef TclAccessInsertProc +#define TclAccessInsertProc \ + (tclIntStubsPtr->tclAccessInsertProc) /* 2 */ +#endif +#ifndef TclAllocateFreeObjects +#define TclAllocateFreeObjects \ + (tclIntStubsPtr->tclAllocateFreeObjects) /* 3 */ +#endif +/* Slot 4 is reserved */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclCleanupChildren +#define TclCleanupChildren \ + (tclIntStubsPtr->tclCleanupChildren) /* 5 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclCleanupChildren +#define TclCleanupChildren \ + (tclIntStubsPtr->tclCleanupChildren) /* 5 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclCleanupCommand +#define TclCleanupCommand \ + (tclIntStubsPtr->tclCleanupCommand) /* 6 */ +#endif +#ifndef TclCopyAndCollapse +#define TclCopyAndCollapse \ + (tclIntStubsPtr->tclCopyAndCollapse) /* 7 */ +#endif +#ifndef TclCopyChannel +#define TclCopyChannel \ + (tclIntStubsPtr->tclCopyChannel) /* 8 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclCreatePipeline +#define TclCreatePipeline \ + (tclIntStubsPtr->tclCreatePipeline) /* 9 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclCreatePipeline +#define TclCreatePipeline \ + (tclIntStubsPtr->tclCreatePipeline) /* 9 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclCreateProc +#define TclCreateProc \ + (tclIntStubsPtr->tclCreateProc) /* 10 */ +#endif +#ifndef TclDeleteCompiledLocalVars +#define TclDeleteCompiledLocalVars \ + (tclIntStubsPtr->tclDeleteCompiledLocalVars) /* 11 */ +#endif +#ifndef TclDeleteVars +#define TclDeleteVars \ + (tclIntStubsPtr->tclDeleteVars) /* 12 */ +#endif +#ifndef TclDoGlob +#define TclDoGlob \ + (tclIntStubsPtr->tclDoGlob) /* 13 */ +#endif +#ifndef TclDumpMemoryInfo +#define TclDumpMemoryInfo \ + (tclIntStubsPtr->tclDumpMemoryInfo) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TclExprFloatError +#define TclExprFloatError \ + (tclIntStubsPtr->tclExprFloatError) /* 16 */ +#endif +#ifndef TclFileAttrsCmd +#define TclFileAttrsCmd \ + (tclIntStubsPtr->tclFileAttrsCmd) /* 17 */ +#endif +#ifndef TclFileCopyCmd +#define TclFileCopyCmd \ + (tclIntStubsPtr->tclFileCopyCmd) /* 18 */ +#endif +#ifndef TclFileDeleteCmd +#define TclFileDeleteCmd \ + (tclIntStubsPtr->tclFileDeleteCmd) /* 19 */ +#endif +#ifndef TclFileMakeDirsCmd +#define TclFileMakeDirsCmd \ + (tclIntStubsPtr->tclFileMakeDirsCmd) /* 20 */ +#endif +#ifndef TclFileRenameCmd +#define TclFileRenameCmd \ + (tclIntStubsPtr->tclFileRenameCmd) /* 21 */ +#endif +#ifndef TclFindElement +#define TclFindElement \ + (tclIntStubsPtr->tclFindElement) /* 22 */ +#endif +#ifndef TclFindProc +#define TclFindProc \ + (tclIntStubsPtr->tclFindProc) /* 23 */ +#endif +#ifndef TclFormatInt +#define TclFormatInt \ + (tclIntStubsPtr->tclFormatInt) /* 24 */ +#endif +#ifndef TclFreePackageInfo +#define TclFreePackageInfo \ + (tclIntStubsPtr->tclFreePackageInfo) /* 25 */ +#endif +/* Slot 26 is reserved */ +#ifndef TclGetDate +#define TclGetDate \ + (tclIntStubsPtr->tclGetDate) /* 27 */ +#endif +#ifndef TclpGetDefaultStdChannel +#define TclpGetDefaultStdChannel \ + (tclIntStubsPtr->tclpGetDefaultStdChannel) /* 28 */ +#endif +#ifndef TclGetElementOfIndexedArray +#define TclGetElementOfIndexedArray \ + (tclIntStubsPtr->tclGetElementOfIndexedArray) /* 29 */ +#endif +/* Slot 30 is reserved */ +#ifndef TclGetExtension +#define TclGetExtension \ + (tclIntStubsPtr->tclGetExtension) /* 31 */ +#endif +#ifndef TclGetFrame +#define TclGetFrame \ + (tclIntStubsPtr->tclGetFrame) /* 32 */ +#endif +#ifndef TclGetInterpProc +#define TclGetInterpProc \ + (tclIntStubsPtr->tclGetInterpProc) /* 33 */ +#endif +#ifndef TclGetIntForIndex +#define TclGetIntForIndex \ + (tclIntStubsPtr->tclGetIntForIndex) /* 34 */ +#endif +#ifndef TclGetIndexedScalar +#define TclGetIndexedScalar \ + (tclIntStubsPtr->tclGetIndexedScalar) /* 35 */ +#endif +#ifndef TclGetLong +#define TclGetLong \ + (tclIntStubsPtr->tclGetLong) /* 36 */ +#endif +#ifndef TclGetLoadedPackages +#define TclGetLoadedPackages \ + (tclIntStubsPtr->tclGetLoadedPackages) /* 37 */ +#endif +#ifndef TclGetNamespaceForQualName +#define TclGetNamespaceForQualName \ + (tclIntStubsPtr->tclGetNamespaceForQualName) /* 38 */ +#endif +#ifndef TclGetObjInterpProc +#define TclGetObjInterpProc \ + (tclIntStubsPtr->tclGetObjInterpProc) /* 39 */ +#endif +#ifndef TclGetOpenMode +#define TclGetOpenMode \ + (tclIntStubsPtr->tclGetOpenMode) /* 40 */ +#endif +#ifndef TclGetOriginalCommand +#define TclGetOriginalCommand \ + (tclIntStubsPtr->tclGetOriginalCommand) /* 41 */ +#endif +#ifndef TclpGetUserHome +#define TclpGetUserHome \ + (tclIntStubsPtr->tclpGetUserHome) /* 42 */ +#endif +#ifndef TclGlobalInvoke +#define TclGlobalInvoke \ + (tclIntStubsPtr->tclGlobalInvoke) /* 43 */ +#endif +#ifndef TclGuessPackageName +#define TclGuessPackageName \ + (tclIntStubsPtr->tclGuessPackageName) /* 44 */ +#endif +#ifndef TclHideUnsafeCommands +#define TclHideUnsafeCommands \ + (tclIntStubsPtr->tclHideUnsafeCommands) /* 45 */ +#endif +#ifndef TclInExit +#define TclInExit \ + (tclIntStubsPtr->tclInExit) /* 46 */ +#endif +#ifndef TclIncrElementOfIndexedArray +#define TclIncrElementOfIndexedArray \ + (tclIntStubsPtr->tclIncrElementOfIndexedArray) /* 47 */ +#endif +#ifndef TclIncrIndexedScalar +#define TclIncrIndexedScalar \ + (tclIntStubsPtr->tclIncrIndexedScalar) /* 48 */ +#endif +#ifndef TclIncrVar2 +#define TclIncrVar2 \ + (tclIntStubsPtr->tclIncrVar2) /* 49 */ +#endif +#ifndef TclInitCompiledLocals +#define TclInitCompiledLocals \ + (tclIntStubsPtr->tclInitCompiledLocals) /* 50 */ +#endif +#ifndef TclInterpInit +#define TclInterpInit \ + (tclIntStubsPtr->tclInterpInit) /* 51 */ +#endif +#ifndef TclInvoke +#define TclInvoke \ + (tclIntStubsPtr->tclInvoke) /* 52 */ +#endif +#ifndef TclInvokeObjectCommand +#define TclInvokeObjectCommand \ + (tclIntStubsPtr->tclInvokeObjectCommand) /* 53 */ +#endif +#ifndef TclInvokeStringCommand +#define TclInvokeStringCommand \ + (tclIntStubsPtr->tclInvokeStringCommand) /* 54 */ +#endif +#ifndef TclIsProc +#define TclIsProc \ + (tclIntStubsPtr->tclIsProc) /* 55 */ +#endif +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +#ifndef TclLookupVar +#define TclLookupVar \ + (tclIntStubsPtr->tclLookupVar) /* 58 */ +#endif +#ifndef TclpMatchFiles +#define TclpMatchFiles \ + (tclIntStubsPtr->tclpMatchFiles) /* 59 */ +#endif +#ifndef TclNeedSpace +#define TclNeedSpace \ + (tclIntStubsPtr->tclNeedSpace) /* 60 */ +#endif +#ifndef TclNewProcBodyObj +#define TclNewProcBodyObj \ + (tclIntStubsPtr->tclNewProcBodyObj) /* 61 */ +#endif +#ifndef TclObjCommandComplete +#define TclObjCommandComplete \ + (tclIntStubsPtr->tclObjCommandComplete) /* 62 */ +#endif +#ifndef TclObjInterpProc +#define TclObjInterpProc \ + (tclIntStubsPtr->tclObjInterpProc) /* 63 */ +#endif +#ifndef TclObjInvoke +#define TclObjInvoke \ + (tclIntStubsPtr->tclObjInvoke) /* 64 */ +#endif +#ifndef TclObjInvokeGlobal +#define TclObjInvokeGlobal \ + (tclIntStubsPtr->tclObjInvokeGlobal) /* 65 */ +#endif +#ifndef TclOpenFileChannelDeleteProc +#define TclOpenFileChannelDeleteProc \ + (tclIntStubsPtr->tclOpenFileChannelDeleteProc) /* 66 */ +#endif +#ifndef TclOpenFileChannelInsertProc +#define TclOpenFileChannelInsertProc \ + (tclIntStubsPtr->tclOpenFileChannelInsertProc) /* 67 */ +#endif +#ifndef TclpAccess +#define TclpAccess \ + (tclIntStubsPtr->tclpAccess) /* 68 */ +#endif +#ifndef TclpAlloc +#define TclpAlloc \ + (tclIntStubsPtr->tclpAlloc) /* 69 */ +#endif +#ifndef TclpCopyFile +#define TclpCopyFile \ + (tclIntStubsPtr->tclpCopyFile) /* 70 */ +#endif +#ifndef TclpCopyDirectory +#define TclpCopyDirectory \ + (tclIntStubsPtr->tclpCopyDirectory) /* 71 */ +#endif +#ifndef TclpCreateDirectory +#define TclpCreateDirectory \ + (tclIntStubsPtr->tclpCreateDirectory) /* 72 */ +#endif +#ifndef TclpDeleteFile +#define TclpDeleteFile \ + (tclIntStubsPtr->tclpDeleteFile) /* 73 */ +#endif +#ifndef TclpFree +#define TclpFree \ + (tclIntStubsPtr->tclpFree) /* 74 */ +#endif +#ifndef TclpGetClicks +#define TclpGetClicks \ + (tclIntStubsPtr->tclpGetClicks) /* 75 */ +#endif +#ifndef TclpGetSeconds +#define TclpGetSeconds \ + (tclIntStubsPtr->tclpGetSeconds) /* 76 */ +#endif +#ifndef TclpGetTime +#define TclpGetTime \ + (tclIntStubsPtr->tclpGetTime) /* 77 */ +#endif +#ifndef TclpGetTimeZone +#define TclpGetTimeZone \ + (tclIntStubsPtr->tclpGetTimeZone) /* 78 */ +#endif +#ifndef TclpListVolumes +#define TclpListVolumes \ + (tclIntStubsPtr->tclpListVolumes) /* 79 */ +#endif +#ifndef TclpOpenFileChannel +#define TclpOpenFileChannel \ + (tclIntStubsPtr->tclpOpenFileChannel) /* 80 */ +#endif +#ifndef TclpRealloc +#define TclpRealloc \ + (tclIntStubsPtr->tclpRealloc) /* 81 */ +#endif +#ifndef TclpRemoveDirectory +#define TclpRemoveDirectory \ + (tclIntStubsPtr->tclpRemoveDirectory) /* 82 */ +#endif +#ifndef TclpRenameFile +#define TclpRenameFile \ + (tclIntStubsPtr->tclpRenameFile) /* 83 */ +#endif +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +#ifndef TclPrecTraceProc +#define TclPrecTraceProc \ + (tclIntStubsPtr->tclPrecTraceProc) /* 88 */ +#endif +#ifndef TclPreventAliasLoop +#define TclPreventAliasLoop \ + (tclIntStubsPtr->tclPreventAliasLoop) /* 89 */ +#endif +/* Slot 90 is reserved */ +#ifndef TclProcCleanupProc +#define TclProcCleanupProc \ + (tclIntStubsPtr->tclProcCleanupProc) /* 91 */ +#endif +#ifndef TclProcCompileProc +#define TclProcCompileProc \ + (tclIntStubsPtr->tclProcCompileProc) /* 92 */ +#endif +#ifndef TclProcDeleteProc +#define TclProcDeleteProc \ + (tclIntStubsPtr->tclProcDeleteProc) /* 93 */ +#endif +#ifndef TclProcInterpProc +#define TclProcInterpProc \ + (tclIntStubsPtr->tclProcInterpProc) /* 94 */ +#endif +#ifndef TclpStat +#define TclpStat \ + (tclIntStubsPtr->tclpStat) /* 95 */ +#endif +#ifndef TclRenameCommand +#define TclRenameCommand \ + (tclIntStubsPtr->tclRenameCommand) /* 96 */ +#endif +#ifndef TclResetShadowedCmdRefs +#define TclResetShadowedCmdRefs \ + (tclIntStubsPtr->tclResetShadowedCmdRefs) /* 97 */ +#endif +#ifndef TclServiceIdle +#define TclServiceIdle \ + (tclIntStubsPtr->tclServiceIdle) /* 98 */ +#endif +#ifndef TclSetElementOfIndexedArray +#define TclSetElementOfIndexedArray \ + (tclIntStubsPtr->tclSetElementOfIndexedArray) /* 99 */ +#endif +#ifndef TclSetIndexedScalar +#define TclSetIndexedScalar \ + (tclIntStubsPtr->tclSetIndexedScalar) /* 100 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclSetPreInitScript +#define TclSetPreInitScript \ + (tclIntStubsPtr->tclSetPreInitScript) /* 101 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclSetPreInitScript +#define TclSetPreInitScript \ + (tclIntStubsPtr->tclSetPreInitScript) /* 101 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclSetupEnv +#define TclSetupEnv \ + (tclIntStubsPtr->tclSetupEnv) /* 102 */ +#endif +#ifndef TclSockGetPort +#define TclSockGetPort \ + (tclIntStubsPtr->tclSockGetPort) /* 103 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclSockMinimumBuffers +#define TclSockMinimumBuffers \ + (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclSockMinimumBuffers +#define TclSockMinimumBuffers \ + (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclStat +#define TclStat \ + (tclIntStubsPtr->tclStat) /* 105 */ +#endif +#ifndef TclStatDeleteProc +#define TclStatDeleteProc \ + (tclIntStubsPtr->tclStatDeleteProc) /* 106 */ +#endif +#ifndef TclStatInsertProc +#define TclStatInsertProc \ + (tclIntStubsPtr->tclStatInsertProc) /* 107 */ +#endif +#ifndef TclTeardownNamespace +#define TclTeardownNamespace \ + (tclIntStubsPtr->tclTeardownNamespace) /* 108 */ +#endif +#ifndef TclUpdateReturnInfo +#define TclUpdateReturnInfo \ + (tclIntStubsPtr->tclUpdateReturnInfo) /* 109 */ +#endif +/* Slot 110 is reserved */ +#ifndef Tcl_AddInterpResolvers +#define Tcl_AddInterpResolvers \ + (tclIntStubsPtr->tcl_AddInterpResolvers) /* 111 */ +#endif +#ifndef Tcl_AppendExportList +#define Tcl_AppendExportList \ + (tclIntStubsPtr->tcl_AppendExportList) /* 112 */ +#endif +#ifndef Tcl_CreateNamespace +#define Tcl_CreateNamespace \ + (tclIntStubsPtr->tcl_CreateNamespace) /* 113 */ +#endif +#ifndef Tcl_DeleteNamespace +#define Tcl_DeleteNamespace \ + (tclIntStubsPtr->tcl_DeleteNamespace) /* 114 */ +#endif +#ifndef Tcl_Export +#define Tcl_Export \ + (tclIntStubsPtr->tcl_Export) /* 115 */ +#endif +#ifndef Tcl_FindCommand +#define Tcl_FindCommand \ + (tclIntStubsPtr->tcl_FindCommand) /* 116 */ +#endif +#ifndef Tcl_FindNamespace +#define Tcl_FindNamespace \ + (tclIntStubsPtr->tcl_FindNamespace) /* 117 */ +#endif +#ifndef Tcl_GetInterpResolvers +#define Tcl_GetInterpResolvers \ + (tclIntStubsPtr->tcl_GetInterpResolvers) /* 118 */ +#endif +#ifndef Tcl_GetNamespaceResolvers +#define Tcl_GetNamespaceResolvers \ + (tclIntStubsPtr->tcl_GetNamespaceResolvers) /* 119 */ +#endif +#ifndef Tcl_FindNamespaceVar +#define Tcl_FindNamespaceVar \ + (tclIntStubsPtr->tcl_FindNamespaceVar) /* 120 */ +#endif +#ifndef Tcl_ForgetImport +#define Tcl_ForgetImport \ + (tclIntStubsPtr->tcl_ForgetImport) /* 121 */ +#endif +#ifndef Tcl_GetCommandFromObj +#define Tcl_GetCommandFromObj \ + (tclIntStubsPtr->tcl_GetCommandFromObj) /* 122 */ +#endif +#ifndef Tcl_GetCommandFullName +#define Tcl_GetCommandFullName \ + (tclIntStubsPtr->tcl_GetCommandFullName) /* 123 */ +#endif +#ifndef Tcl_GetCurrentNamespace +#define Tcl_GetCurrentNamespace \ + (tclIntStubsPtr->tcl_GetCurrentNamespace) /* 124 */ +#endif +#ifndef Tcl_GetGlobalNamespace +#define Tcl_GetGlobalNamespace \ + (tclIntStubsPtr->tcl_GetGlobalNamespace) /* 125 */ +#endif +#ifndef Tcl_GetVariableFullName +#define Tcl_GetVariableFullName \ + (tclIntStubsPtr->tcl_GetVariableFullName) /* 126 */ +#endif +#ifndef Tcl_Import +#define Tcl_Import \ + (tclIntStubsPtr->tcl_Import) /* 127 */ +#endif +#ifndef Tcl_PopCallFrame +#define Tcl_PopCallFrame \ + (tclIntStubsPtr->tcl_PopCallFrame) /* 128 */ +#endif +#ifndef Tcl_PushCallFrame +#define Tcl_PushCallFrame \ + (tclIntStubsPtr->tcl_PushCallFrame) /* 129 */ +#endif +#ifndef Tcl_RemoveInterpResolvers +#define Tcl_RemoveInterpResolvers \ + (tclIntStubsPtr->tcl_RemoveInterpResolvers) /* 130 */ +#endif +#ifndef Tcl_SetNamespaceResolvers +#define Tcl_SetNamespaceResolvers \ + (tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */ +#endif +#ifndef TclpHasSockets +#define TclpHasSockets \ + (tclIntStubsPtr->tclpHasSockets) /* 132 */ +#endif +#ifndef TclpGetDate +#define TclpGetDate \ + (tclIntStubsPtr->tclpGetDate) /* 133 */ +#endif +#ifndef TclpStrftime +#define TclpStrftime \ + (tclIntStubsPtr->tclpStrftime) /* 134 */ +#endif +#ifndef TclpCheckStackSpace +#define TclpCheckStackSpace \ + (tclIntStubsPtr->tclpCheckStackSpace) /* 135 */ +#endif +/* Slot 136 is reserved */ +#ifndef TclpChdir +#define TclpChdir \ + (tclIntStubsPtr->tclpChdir) /* 137 */ +#endif +#ifndef TclGetEnv +#define TclGetEnv \ + (tclIntStubsPtr->tclGetEnv) /* 138 */ +#endif +#ifndef TclpLoadFile +#define TclpLoadFile \ + (tclIntStubsPtr->tclpLoadFile) /* 139 */ +#endif +#ifndef TclLooksLikeInt +#define TclLooksLikeInt \ + (tclIntStubsPtr->tclLooksLikeInt) /* 140 */ +#endif +#ifndef TclpGetCwd +#define TclpGetCwd \ + (tclIntStubsPtr->tclpGetCwd) /* 141 */ +#endif +#ifndef TclSetByteCodeFromAny +#define TclSetByteCodeFromAny \ + (tclIntStubsPtr->tclSetByteCodeFromAny) /* 142 */ +#endif +#ifndef TclAddLiteralObj +#define TclAddLiteralObj \ + (tclIntStubsPtr->tclAddLiteralObj) /* 143 */ +#endif +#ifndef TclHideLiteral +#define TclHideLiteral \ + (tclIntStubsPtr->tclHideLiteral) /* 144 */ +#endif +#ifndef TclGetAuxDataType +#define TclGetAuxDataType \ + (tclIntStubsPtr->tclGetAuxDataType) /* 145 */ +#endif +#ifndef TclHandleCreate +#define TclHandleCreate \ + (tclIntStubsPtr->tclHandleCreate) /* 146 */ +#endif +#ifndef TclHandleFree +#define TclHandleFree \ + (tclIntStubsPtr->tclHandleFree) /* 147 */ +#endif +#ifndef TclHandlePreserve +#define TclHandlePreserve \ + (tclIntStubsPtr->tclHandlePreserve) /* 148 */ +#endif +#ifndef TclHandleRelease +#define TclHandleRelease \ + (tclIntStubsPtr->tclHandleRelease) /* 149 */ +#endif +#ifndef TclRegAbout +#define TclRegAbout \ + (tclIntStubsPtr->tclRegAbout) /* 150 */ +#endif +#ifndef TclRegExpRangeUniChar +#define TclRegExpRangeUniChar \ + (tclIntStubsPtr->tclRegExpRangeUniChar) /* 151 */ +#endif +#ifndef TclSetLibraryPath +#define TclSetLibraryPath \ + (tclIntStubsPtr->tclSetLibraryPath) /* 152 */ +#endif +#ifndef TclGetLibraryPath +#define TclGetLibraryPath \ + (tclIntStubsPtr->tclGetLibraryPath) /* 153 */ +#endif +#ifndef TclTestChannelCmd +#define TclTestChannelCmd \ + (tclIntStubsPtr->tclTestChannelCmd) /* 154 */ +#endif +#ifndef TclTestChannelEventCmd +#define TclTestChannelEventCmd \ + (tclIntStubsPtr->tclTestChannelEventCmd) /* 155 */ +#endif +#ifndef TclRegError +#define TclRegError \ + (tclIntStubsPtr->tclRegError) /* 156 */ +#endif +#ifndef TclVarTraceExists +#define TclVarTraceExists \ + (tclIntStubsPtr->tclVarTraceExists) /* 157 */ +#endif + +#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TCLINTDECLS */ diff --git a/Utilities/TclTk/internals/tk8.2/tkInt.h b/Utilities/TclTk/internals/tk8.2/tkInt.h new file mode 100644 index 0000000..6c53fae --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkInt.h @@ -0,0 +1,1009 @@ +/* + * tkInt.h -- + * + * Declarations for things used internally by the Tk + * procedures but not exported outside the module. + * + * Copyright (c) 1990-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1998 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: $Id: tkInt.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKINT +#define _TKINT + +#ifndef _TK +#include "tk.h" +#endif +#ifndef _TCL +#include "tcl.h" +#endif +#ifndef _TKPORT +#include +#endif + +/* + * Opaque type declarations: + */ + +typedef struct TkColormap TkColormap; +typedef struct TkGrabEvent TkGrabEvent; +typedef struct Tk_PostscriptInfo Tk_PostscriptInfo; +typedef struct TkpCursor_ *TkpCursor; +typedef struct TkRegion_ *TkRegion; +typedef struct TkStressedCmap TkStressedCmap; +typedef struct TkBindInfo_ *TkBindInfo; + +/* + * Procedure types. + */ + +typedef int (TkBindEvalProc) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, XEvent *eventPtr, Tk_Window tkwin, + KeySym keySym)); +typedef void (TkBindFreeProc) _ANSI_ARGS_((ClientData clientData)); +typedef Window (TkClassCreateProc) _ANSI_ARGS_((Tk_Window tkwin, + Window parent, ClientData instanceData)); +typedef void (TkClassGeometryProc) _ANSI_ARGS_((ClientData instanceData)); +typedef void (TkClassModalProc) _ANSI_ARGS_((Tk_Window tkwin, + XEvent *eventPtr)); + + +/* + * Widget class procedures used to implement platform specific widget + * behavior. + */ + +typedef struct TkClassProcs { + TkClassCreateProc *createProc; + /* Procedure to invoke when the + platform-dependent window needs to be + created. */ + TkClassGeometryProc *geometryProc; + /* Procedure to invoke when the geometry of a + window needs to be recalculated as a result + of some change in the system. */ + TkClassModalProc *modalProc; + /* Procedure to invoke after all bindings on a + widget have been triggered in order to + handle a modal loop. */ +} TkClassProcs; + +/* + * One of the following structures is maintained for each cursor in + * use in the system. This structure is used by tkCursor.c and the + * various system specific cursor files. + */ + +typedef struct TkCursor { + Tk_Cursor cursor; /* System specific identifier for cursor. */ + Display *display; /* Display containing cursor. Needed for + * disposal and retrieval of cursors. */ + int resourceRefCount; /* Number of active uses of this cursor (each + * active use corresponds to a call to + * Tk_AllocPreserveFromObj or Tk_Preserve). + * If this count is 0, then this structure + * is no longer valid and it isn't present + * in a hash table: it is being kept around + * only because there are objects referring + * to it. The structure is freed when + * resourceRefCount and objRefCount are + * both 0. */ + int objRefCount; /* Number of Tcl objects that reference + * this structure.. */ + Tcl_HashTable *otherTable; /* Second table (other than idTable) used + * to index this entry. */ + Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure + * (needed when deleting). */ + Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure + * (needed when deleting). */ + struct TkCursor *nextPtr; /* Points to the next TkCursor structure with + * the same name. Cursors with the same + * name but different displays are chained + * together off a single hash table entry. */ +} TkCursor; + +/* + * One of the following structures is maintained for each display + * containing a window managed by Tk. In part, the structure is + * used to store thread-specific data, since each thread will have + * its own TkDisplay structure. + */ + +typedef struct TkDisplay { + Display *display; /* Xlib's info about display. */ + struct TkDisplay *nextPtr; /* Next in list of all displays. */ + char *name; /* Name of display (with any screen + * identifier removed). Malloc-ed. */ + Time lastEventTime; /* Time of last event received for this + * display. */ + + /* + * Information used primarily by tk3d.c: + */ + + int borderInit; /* 0 means borderTable needs initializing. */ + Tcl_HashTable borderTable; /* Maps from color name to TkBorder + * structure. */ + + /* + * Information used by tkAtom.c only: + */ + + int atomInit; /* 0 means stuff below hasn't been + * initialized yet. */ + Tcl_HashTable nameTable; /* Maps from names to Atom's. */ + Tcl_HashTable atomTable; /* Maps from Atom's back to names. */ + + /* + * Information used primarily by tkBind.c: + */ + + int bindInfoStale; /* Non-zero means the variables in this + * part of the structure are potentially + * incorrect and should be recomputed. */ + unsigned int modeModMask; /* Has one bit set to indicate the modifier + * corresponding to "mode shift". If no + * such modifier, than this is zero. */ + unsigned int metaModMask; /* Has one bit set to indicate the modifier + * corresponding to the "Meta" key. If no + * such modifier, then this is zero. */ + unsigned int altModMask; /* Has one bit set to indicate the modifier + * corresponding to the "Meta" key. If no + * such modifier, then this is zero. */ + enum {LU_IGNORE, LU_CAPS, LU_SHIFT} lockUsage; + /* Indicates how to interpret lock modifier. */ + int numModKeyCodes; /* Number of entries in modKeyCodes array + * below. */ + KeyCode *modKeyCodes; /* Pointer to an array giving keycodes for + * all of the keys that have modifiers + * associated with them. Malloc'ed, but + * may be NULL. */ + + /* + * Information used by tkBitmap.c only: + */ + + int bitmapInit; /* 0 means tables above need initializing. */ + int bitmapAutoNumber; /* Used to number bitmaps. */ + Tcl_HashTable bitmapNameTable; + /* Maps from name of bitmap to the first + * TkBitmap record for that name. */ + Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap + * structure for the bitmap. */ + Tcl_HashTable bitmapDataTable; + /* Used by Tk_GetBitmapFromData to map from + * a collection of in-core data about a + * bitmap to a reference giving an auto- + * matically-generated name for the bitmap. */ + + /* + * Information used by tkCanvas.c only: + */ + + int numIdSearches; + int numSlowSearches; + + /* + * Used by tkColor.c only: + */ + + int colorInit; /* 0 means color module needs initializing. */ + TkStressedCmap *stressPtr; /* First in list of colormaps that have + * filled up, so we have to pick an + * approximate color. */ + Tcl_HashTable colorNameTable; + /* Maps from color name to TkColor structure + * for that color. */ + Tcl_HashTable colorValueTable; + /* Maps from integer RGB values to TkColor + * structures. */ + + /* + * Used by tkCursor.c only: + */ + + int cursorInit; /* 0 means cursor module need initializing. */ + Tcl_HashTable cursorNameTable; + /* Maps from a string name to a cursor to the + * TkCursor record for the cursor. */ + Tcl_HashTable cursorDataTable; + /* Maps from a collection of in-core data + * about a cursor to a TkCursor structure. */ + Tcl_HashTable cursorIdTable; + /* Maps from a cursor id to the TkCursor + * structure for the cursor. */ + char cursorString[20]; /* Used to store a cursor id string. */ + Font cursorFont; /* Font to use for standard cursors. + * None means font not loaded yet. */ + + /* + * Information used by tkError.c only: + */ + + struct TkErrorHandler *errorPtr; + /* First in list of error handlers + * for this display. NULL means + * no handlers exist at present. */ + int deleteCount; /* Counts # of handlers deleted since + * last time inactive handlers were + * garbage-collected. When this number + * gets big, handlers get cleaned up. */ + + /* + * Used by tkEvent.c only: + */ + + struct TkWindowEvent *delayedMotionPtr; + /* Points to a malloc-ed motion event + * whose processing has been delayed in + * the hopes that another motion event + * will come along right away and we can + * merge the two of them together. NULL + * means that there is no delayed motion + * event. */ + + /* + * Information used by tkFocus.c only: + */ + + int focusDebug; /* 1 means collect focus debugging + * statistics. */ + struct TkWindow *implicitWinPtr; + /* If the focus arrived at a toplevel window + * implicitly via an Enter event (rather + * than via a FocusIn event), this points + * to the toplevel window. Otherwise it is + * NULL. */ + struct TkWindow *focusPtr; /* Points to the window on this display that + * should be receiving keyboard events. When + * multiple applications on the display have + * the focus, this will refer to the + * innermost window in the innermost + * application. This information isn't used + * under Unix or Windows, but it's needed on + * the Macintosh. */ + + /* + * Information used by tkGC.c only: + */ + + Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure + * describing a GC with those values. */ + Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */ + int gcInit; /* 0 means the tables below need + * initializing. */ + + /* + * Information used by tkGeometry.c only: + */ + + Tcl_HashTable maintainHashTable; + /* Hash table that maps from a master's + * Tk_Window token to a list of slaves + * managed by that master. */ + int geomInit; + + /* + * Information used by tkGet.c only: + */ + + Tcl_HashTable uidTable; /* Stores all Tk_Uid used in a thread. */ + int uidInit; /* 0 means uidTable needs initializing. */ + + /* + * Information used by tkGrab.c only: + */ + + struct TkWindow *grabWinPtr; + /* Window in which the pointer is currently + * grabbed, or NULL if none. */ + struct TkWindow *eventualGrabWinPtr; + /* Value that grabWinPtr will have once the + * grab event queue (below) has been + * completely emptied. */ + struct TkWindow *buttonWinPtr; + /* Window in which first mouse button was + * pressed while grab was in effect, or NULL + * if no such press in effect. */ + struct TkWindow *serverWinPtr; + /* If no application contains the pointer then + * this is NULL. Otherwise it contains the + * last window for which we've gotten an + * Enter or Leave event from the server (i.e. + * the last window known to have contained + * the pointer). Doesn't reflect events + * that were synthesized in tkGrab.c. */ + TkGrabEvent *firstGrabEventPtr; + /* First in list of enter/leave events + * synthesized by grab code. These events + * must be processed in order before any other + * events are processed. NULL means no such + * events. */ + TkGrabEvent *lastGrabEventPtr; + /* Last in list of synthesized events, or NULL + * if list is empty. */ + int grabFlags; /* Miscellaneous flag values. See definitions + * in tkGrab.c. */ + + /* + * Information used by tkGrid.c only: + */ + + int gridInit; /* 0 means table below needs initializing. */ + Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to + * corresponding Grid structures. */ + + /* + * Information used by tkImage.c only: + */ + + int imageId; /* Value used to number image ids. */ + + /* + * Information used by tkMacWinMenu.c only: + */ + + int postCommandGeneration; + + /* + * Information used by tkOption.c only. + */ + + + + /* + * Information used by tkPack.c only. + */ + + int packInit; /* 0 means table below needs initializing. */ + Tcl_HashTable packerHashTable; + /* Maps from Tk_Window tokens to + * corresponding Packer structures. */ + + + /* + * Information used by tkPlace.c only. + */ + + int placeInit; /* 0 means tables below need initializing. */ + Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master + * structure for the window, if it exists. */ + Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave + * structure for the window, if it exists. */ + + /* + * Information used by tkSelect.c and tkClipboard.c only: + */ + + struct TkSelectionInfo *selectionInfoPtr; + /* First in list of selection information + * records. Each entry contains information + * about the current owner of a particular + * selection on this display. */ + Atom multipleAtom; /* Atom for MULTIPLE. None means + * selection stuff isn't initialized. */ + Atom incrAtom; /* Atom for INCR. */ + Atom targetsAtom; /* Atom for TARGETS. */ + Atom timestampAtom; /* Atom for TIMESTAMP. */ + Atom textAtom; /* Atom for TEXT. */ + Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */ + Atom applicationAtom; /* Atom for TK_APPLICATION. */ + Atom windowAtom; /* Atom for TK_WINDOW. */ + Atom clipboardAtom; /* Atom for CLIPBOARD. */ + + Tk_Window clipWindow; /* Window used for clipboard ownership and to + * retrieve selections between processes. NULL + * means clipboard info hasn't been + * initialized. */ + int clipboardActive; /* 1 means we currently own the clipboard + * selection, 0 means we don't. */ + struct TkMainInfo *clipboardAppPtr; + /* Last application that owned clipboard. */ + struct TkClipboardTarget *clipTargetPtr; + /* First in list of clipboard type information + * records. Each entry contains information + * about the buffers for a given selection + * target. */ + + /* + * Information used by tkSend.c only: + */ + + Tk_Window commTkwin; /* Window used for communication + * between interpreters during "send" + * commands. NULL means send info hasn't + * been initialized yet. */ + Atom commProperty; /* X's name for comm property. */ + Atom registryProperty; /* X's name for property containing + * registry of interpreter names. */ + Atom appNameProperty; /* X's name for property used to hold the + * application name on each comm window. */ + + /* + * Information used by tkXId.c only: + */ + + struct TkIdStack *idStackPtr; + /* First in list of chunks of free resource + * identifiers, or NULL if there are no free + * resources. */ + XID (*defaultAllocProc) _ANSI_ARGS_((Display *display)); + /* Default resource allocator for display. */ + struct TkIdStack *windowStackPtr; + /* First in list of chunks of window + * identifers that can't be reused right + * now. */ + int idCleanupScheduled; /* 1 means a call to WindowIdCleanup has + * already been scheduled, 0 means it + * hasn't. */ + + /* + * Information used by tkUnixWm.c and tkWinWm.c only: + */ + + int wmTracing; /* Used to enable or disable tracing in + * this module. If tracing is enabled, + * then information is printed on + * standard output about interesting + * interactions with the window manager. */ + struct TkWmInfo *firstWmPtr; /* Points to first top-level window. */ + struct TkWmInfo *foregroundWmPtr; + /* Points to the foreground window. */ + + /* + * Information maintained by tkWindow.c for use later on by tkXId.c: + */ + + + int destroyCount; /* Number of Tk_DestroyWindow operations + * in progress. */ + unsigned long lastDestroyRequest; + /* Id of most recent XDestroyWindow request; + * can re-use ids in windowStackPtr when + * server has seen this request and event + * queue is empty. */ + + /* + * Information used by tkVisual.c only: + */ + + TkColormap *cmapPtr; /* First in list of all non-default colormaps + * allocated for this display. */ + + /* + * Miscellaneous information: + */ + +#ifdef TK_USE_INPUT_METHODS + XIM inputMethod; /* Input method for this display */ +#endif /* TK_USE_INPUT_METHODS */ + Tcl_HashTable winTable; /* Maps from X window ids to TkWindow ptrs. */ + + int refCount; /* Reference count of how many Tk applications + * are using this display. Used to clean up + * the display when we no longer have any + * Tk applications using it. + */ +} TkDisplay; + +/* + * One of the following structures exists for each error handler + * created by a call to Tk_CreateErrorHandler. The structure + * is managed by tkError.c. + */ + +typedef struct TkErrorHandler { + TkDisplay *dispPtr; /* Display to which handler applies. */ + unsigned long firstRequest; /* Only errors with serial numbers + * >= to this are considered. */ + unsigned long lastRequest; /* Only errors with serial numbers + * <= to this are considered. This + * field is filled in when XUnhandle + * is called. -1 means XUnhandle + * hasn't been called yet. */ + int error; /* Consider only errors with this + * error_code (-1 means consider + * all errors). */ + int request; /* Consider only errors with this + * major request code (-1 means + * consider all major codes). */ + int minorCode; /* Consider only errors with this + * minor request code (-1 means + * consider all minor codes). */ + Tk_ErrorProc *errorProc; /* Procedure to invoke when a matching + * error occurs. NULL means just ignore + * errors. */ + ClientData clientData; /* Arbitrary value to pass to + * errorProc. */ + struct TkErrorHandler *nextPtr; + /* Pointer to next older handler for + * this display, or NULL for end of + * list. */ +} TkErrorHandler; + + + + +/* + * One of the following structures exists for each event handler + * created by calling Tk_CreateEventHandler. This information + * is used by tkEvent.c only. + */ + +typedef struct TkEventHandler { + unsigned long mask; /* Events for which to invoke + * proc. */ + Tk_EventProc *proc; /* Procedure to invoke when an event + * in mask occurs. */ + ClientData clientData; /* Argument to pass to proc. */ + struct TkEventHandler *nextPtr; + /* Next in list of handlers + * associated with window (NULL means + * end of list). */ +} TkEventHandler; + +/* + * Tk keeps one of the following data structures for each main + * window (created by a call to TkCreateMainWindow). It stores + * information that is shared by all of the windows associated + * with a particular main window. + */ + +typedef struct TkMainInfo { + int refCount; /* Number of windows whose "mainPtr" fields + * point here. When this becomes zero, can + * free up the structure (the reference + * count is zero because windows can get + * deleted in almost any order; the main + * window isn't necessarily the last one + * deleted). */ + struct TkWindow *winPtr; /* Pointer to main window. */ + Tcl_Interp *interp; /* Interpreter associated with application. */ + Tcl_HashTable nameTable; /* Hash table mapping path names to TkWindow + * structs for all windows related to this + * main window. Managed by tkWindow.c. */ + Tk_BindingTable bindingTable; + /* Used in conjunction with "bind" command + * to bind events to Tcl commands. */ + TkBindInfo bindInfo; /* Information used by tkBind.c on a per + * application basis. */ + struct TkFontInfo *fontInfoPtr; + /* Information used by tkFont.c on a per + * application basis. */ + + /* + * Information used only by tkFocus.c and tk*Embed.c: + */ + + struct TkToplevelFocusInfo *tlFocusPtr; + /* First in list of records containing focus + * information for each top-level in the + * application. Used only by tkFocus.c. */ + struct TkDisplayFocusInfo *displayFocusPtr; + /* First in list of records containing focus + * information for each display that this + * application has ever used. Used only + * by tkFocus.c. */ + + struct ElArray *optionRootPtr; + /* Top level of option hierarchy for this + * main window. NULL means uninitialized. + * Managed by tkOption.c. */ + Tcl_HashTable imageTable; /* Maps from image names to Tk_ImageMaster + * structures. Managed by tkImage.c. */ + int strictMotif; /* This is linked to the tk_strictMotif + * global variable. */ + struct TkMainInfo *nextPtr; /* Next in list of all main windows managed by + * this process. */ +} TkMainInfo; + +/* + * Tk keeps the following data structure for each of it's builtin + * bitmaps. This structure is only used by tkBitmap.c and other + * platform specific bitmap files. + */ + +typedef struct { + char *source; /* Bits for bitmap. */ + int width, height; /* Dimensions of bitmap. */ + int native; /* 0 means generic (X style) bitmap, + * 1 means native style bitmap. */ +} TkPredefBitmap; + +/* + * Tk keeps one of the following structures for each window. + * Some of the information (like size and location) is a shadow + * of information managed by the X server, and some is special + * information used here, such as event and geometry management + * information. This information is (mostly) managed by tkWindow.c. + * WARNING: the declaration below must be kept consistent with the + * Tk_FakeWin structure in tk.h. If you change one, be sure to + * change the other!! + */ + +typedef struct TkWindow { + + /* + * Structural information: + */ + + Display *display; /* Display containing window. */ + TkDisplay *dispPtr; /* Tk's information about display + * for window. */ + int screenNum; /* Index of screen for window, among all + * those for dispPtr. */ + Visual *visual; /* Visual to use for window. If not default, + * MUST be set before X window is created. */ + int depth; /* Number of bits/pixel. */ + Window window; /* X's id for window. NULL means window + * hasn't actually been created yet, or it's + * been deleted. */ + struct TkWindow *childList; /* First in list of child windows, + * or NULL if no children. List is in + * stacking order, lowest window first.*/ + struct TkWindow *lastChildPtr; + /* Last in list of child windows (highest + * in stacking order), or NULL if no + * children. */ + struct TkWindow *parentPtr; /* Pointer to parent window (logical + * parent, not necessarily X parent). NULL + * means either this is the main window, or + * the window's parent has already been + * deleted. */ + struct TkWindow *nextPtr; /* Next higher sibling (in stacking order) + * in list of children with same parent. NULL + * means end of list. */ + TkMainInfo *mainPtr; /* Information shared by all windows + * associated with a particular main + * window. NULL means this window is + * a rogue that isn't associated with + * any application (at present, this + * only happens for the dummy windows + * used for "send" communication). */ + + /* + * Name and type information for the window: + */ + + char *pathName; /* Path name of window (concatenation + * of all names between this window and + * its top-level ancestor). This is a + * pointer into an entry in + * mainPtr->nameTable. NULL means that + * the window hasn't been completely + * created yet. */ + Tk_Uid nameUid; /* Name of the window within its parent + * (unique within the parent). */ + Tk_Uid classUid; /* Class of the window. NULL means window + * hasn't been given a class yet. */ + + /* + * Geometry and other attributes of window. This information + * may not be updated on the server immediately; stuff that + * hasn't been reflected in the server yet is called "dirty". + * At present, information can be dirty only if the window + * hasn't yet been created. + */ + + XWindowChanges changes; /* Geometry and other info about + * window. */ + unsigned int dirtyChanges; /* Bits indicate fields of "changes" + * that are dirty. */ + XSetWindowAttributes atts; /* Current attributes of window. */ + unsigned long dirtyAtts; /* Bits indicate fields of "atts" + * that are dirty. */ + + unsigned int flags; /* Various flag values: these are all + * defined in tk.h (confusing, but they're + * needed there for some query macros). */ + + /* + * Information kept by the event manager (tkEvent.c): + */ + + TkEventHandler *handlerList;/* First in list of event handlers + * declared for this window, or + * NULL if none. */ +#ifdef TK_USE_INPUT_METHODS + XIC inputContext; /* Input context (for input methods). */ +#endif /* TK_USE_INPUT_METHODS */ + + /* + * Information used for event bindings (see "bind" and "bindtags" + * commands in tkCmds.c): + */ + + ClientData *tagPtr; /* Points to array of tags used for bindings + * on this window. Each tag is a Tk_Uid. + * Malloc'ed. NULL means no tags. */ + int numTags; /* Number of tags at *tagPtr. */ + + /* + * Information used by tkOption.c to manage options for the + * window. + */ + + int optionLevel; /* -1 means no option information is + * currently cached for this window. + * Otherwise this gives the level in + * the option stack at which info is + * cached. */ + /* + * Information used by tkSelect.c to manage the selection. + */ + + struct TkSelHandler *selHandlerList; + /* First in list of handlers for + * returning the selection in various + * forms. */ + + /* + * Information used by tkGeometry.c for geometry management. + */ + + Tk_GeomMgr *geomMgrPtr; /* Information about geometry manager for + * this window. */ + ClientData geomData; /* Argument for geometry manager procedures. */ + int reqWidth, reqHeight; /* Arguments from last call to + * Tk_GeometryRequest, or 0's if + * Tk_GeometryRequest hasn't been + * called. */ + int internalBorderWidth; /* Width of internal border of window + * (0 means no internal border). Geometry + * managers should not normally place children + * on top of the border. */ + + /* + * Information maintained by tkWm.c for window manager communication. + */ + + struct TkWmInfo *wmInfoPtr; /* For top-level windows (and also + * for special Unix menubar and wrapper + * windows), points to structure with + * wm-related info (see tkWm.c). For + * other windows, this is NULL. */ + + /* + * Information used by widget classes. + */ + + TkClassProcs *classProcsPtr; + ClientData instanceData; + + /* + * Platform specific information private to each port. + */ + + struct TkWindowPrivate *privatePtr; +} TkWindow; + +/* + * The following structure is used as a two way map between integers + * and strings, usually to map between an internal C representation + * and the strings used in Tcl. + */ + +typedef struct TkStateMap { + int numKey; /* Integer representation of a value. */ + char *strKey; /* String representation of a value. */ +} TkStateMap; + +/* + * This structure is used by the Mac and Window porting layers as + * the internal representation of a clip_mask in a GC. + */ + +typedef struct TkpClipMask { + int type; /* One of TKP_CLIP_PIXMAP or TKP_CLIP_REGION */ + union { + Pixmap pixmap; + TkRegion region; + } value; +} TkpClipMask; + +#define TKP_CLIP_PIXMAP 0 +#define TKP_CLIP_REGION 1 + +/* + * Pointer to first entry in list of all displays currently known. + */ + +extern TkDisplay *tkDisplayList; + +/* + * Return values from TkGrabState: + */ + +#define TK_GRAB_NONE 0 +#define TK_GRAB_IN_TREE 1 +#define TK_GRAB_ANCESTOR 2 +#define TK_GRAB_EXCLUDED 3 + +/* + * The macro below is used to modify a "char" value (e.g. by casting + * it to an unsigned character) so that it can be used safely with + * macros such as isspace. + */ + +#define UCHAR(c) ((unsigned char) (c)) + +/* + * The following symbol is used in the mode field of FocusIn events + * generated by an embedded application to request the input focus from + * its container. + */ + +#define EMBEDDED_APP_WANTS_FOCUS (NotifyNormal + 20) + +/* + * Miscellaneous variables shared among Tk modules but not exported + * to the outside world: + */ + +extern Tk_Uid tkActiveUid; +extern Tk_ImageType tkBitmapImageType; +extern Tk_Uid tkDisabledUid; +extern Tk_PhotoImageFormat tkImgFmtGIF; +extern void (*tkHandleEventProc) _ANSI_ARGS_(( + XEvent* eventPtr)); +extern Tk_PhotoImageFormat tkImgFmtPPM; +extern TkMainInfo *tkMainWindowList; +extern Tk_Uid tkNormalUid; +extern Tk_ImageType tkPhotoImageType; +extern Tcl_HashTable tkPredefBitmapTable; +extern int tkSendSerial; + +#include "tkIntDecls.h" + +#ifdef BUILD_tk +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * Internal procedures shared among Tk modules but not exported + * to the outside world: + */ + +EXTERN int Tk_AfterCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_BellObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_BindCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_BindtagsCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ButtonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_CanvasCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_CheckbuttonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ClipboardCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ChooseColorObjCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_ChooseDirectoryObjCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_ChooseFontObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_DestroyCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_EntryObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_EventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FileeventCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_FrameCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_FocusObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FontObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GetOpenFileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GetSaveFileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GrabCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_GridCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ImageCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_LabelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ListboxCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_LowerCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_MenubuttonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MessageBoxObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MessageCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_OptionCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_PackCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_PlaceCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_RadiobuttonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_RaiseCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ScaleObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ScrollbarCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_SelectionCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_SendCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_SendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_TextCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_TkObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_TkwaitCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ToplevelCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_WinfoObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_WmCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); + +void TkConsolePrint _ANSI_ARGS_((Tcl_Interp *interp, + int devId, char *buffer, long size)); + +EXTERN void TkEventInit _ANSI_ARGS_((void)); + +EXTERN int TkCreateMenuCmd _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); + +EXTERN int TkpTestembedCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); + +/* + * Unsupported commands. + */ +EXTERN int TkUnsupported1Cmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINT */ diff --git a/Utilities/TclTk/internals/tk8.2/tkIntDecls.h b/Utilities/TclTk/internals/tk8.2/tkIntDecls.h new file mode 100644 index 0000000..82bcc52 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkIntDecls.h @@ -0,0 +1,1460 @@ +/* + * tkIntDecls.h -- + * + * This file contains the declarations for all unsupported + * functions that are exported by the Tk library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkIntDecls.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKINTDECLS +#define _TKINTDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tkInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +/* 0 */ +EXTERN TkWindow * TkAllocWindow _ANSI_ARGS_((TkDisplay * dispPtr, + int screenNum, TkWindow * parentPtr)); +/* 1 */ +EXTERN void TkBezierPoints _ANSI_ARGS_((double control[], + int numSteps, double * coordPtr)); +/* 2 */ +EXTERN void TkBezierScreenPoints _ANSI_ARGS_((Tk_Canvas canvas, + double control[], int numSteps, + XPoint * xPointPtr)); +/* 3 */ +EXTERN void TkBindDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 4 */ +EXTERN void TkBindEventProc _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 5 */ +EXTERN void TkBindFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 6 */ +EXTERN void TkBindInit _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 7 */ +EXTERN void TkChangeEventWindow _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * winPtr)); +/* 8 */ +EXTERN int TkClipInit _ANSI_ARGS_((Tcl_Interp * interp, + TkDisplay * dispPtr)); +/* 9 */ +EXTERN void TkComputeAnchor _ANSI_ARGS_((Tk_Anchor anchor, + Tk_Window tkwin, int padX, int padY, + int innerWidth, int innerHeight, int * xPtr, + int * yPtr)); +/* 10 */ +EXTERN int TkCopyAndGlobalEval _ANSI_ARGS_((Tcl_Interp * interp, + char * script)); +/* 11 */ +EXTERN unsigned long TkCreateBindingProcedure _ANSI_ARGS_(( + Tcl_Interp * interp, + Tk_BindingTable bindingTable, + ClientData object, char * eventString, + TkBindEvalProc * evalProc, + TkBindFreeProc * freeProc, + ClientData clientData)); +/* 12 */ +EXTERN TkCursor * TkCreateCursorFromData _ANSI_ARGS_((Tk_Window tkwin, + char * source, char * mask, int width, + int height, int xHot, int yHot, XColor fg, + XColor bg)); +/* 13 */ +EXTERN int TkCreateFrame _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, char ** argv, + int toplevel, char * appName)); +/* 14 */ +EXTERN Tk_Window TkCreateMainWindow _ANSI_ARGS_((Tcl_Interp * interp, + char * screenName, char * baseName)); +/* 15 */ +EXTERN Time TkCurrentTime _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 16 */ +EXTERN void TkDeleteAllImages _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 17 */ +EXTERN void TkDoConfigureNotify _ANSI_ARGS_((TkWindow * winPtr)); +/* 18 */ +EXTERN void TkDrawInsetFocusHighlight _ANSI_ARGS_(( + Tk_Window tkwin, GC gc, int width, + Drawable drawable, int padding)); +/* 19 */ +EXTERN void TkEventDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 20 */ +EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas, + double * coordPtr, int numPoints, + Display * display, Drawable drawable, GC gc, + GC outlineGC)); +/* 21 */ +EXTERN int TkFindStateNum _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * option, + CONST TkStateMap * mapPtr, + CONST char * strKey)); +/* 22 */ +EXTERN char * TkFindStateString _ANSI_ARGS_(( + CONST TkStateMap * mapPtr, int numKey)); +/* 23 */ +EXTERN void TkFocusDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 24 */ +EXTERN int TkFocusFilterEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 25 */ +EXTERN TkWindow * TkFocusKeyEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 26 */ +EXTERN void TkFontPkgInit _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 27 */ +EXTERN void TkFontPkgFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 28 */ +EXTERN void TkFreeBindingTags _ANSI_ARGS_((TkWindow * winPtr)); +/* 29 */ +EXTERN void TkpFreeCursor _ANSI_ARGS_((TkCursor * cursorPtr)); +/* 30 */ +EXTERN char * TkGetBitmapData _ANSI_ARGS_((Tcl_Interp * interp, + char * string, char * fileName, + int * widthPtr, int * heightPtr, + int * hotXPtr, int * hotYPtr)); +/* 31 */ +EXTERN void TkGetButtPoints _ANSI_ARGS_((double p1[], + double p2[], double width, int project, + double m1[], double m2[])); +/* 32 */ +EXTERN TkCursor * TkGetCursorByName _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, Tk_Uid string)); +/* 33 */ +EXTERN char * TkGetDefaultScreenName _ANSI_ARGS_(( + Tcl_Interp * interp, char * screenName)); +/* 34 */ +EXTERN TkDisplay * TkGetDisplay _ANSI_ARGS_((Display * display)); +/* 35 */ +EXTERN int TkGetDisplayOf _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], + Tk_Window * tkwinPtr)); +/* 36 */ +EXTERN TkWindow * TkGetFocusWin _ANSI_ARGS_((TkWindow * winPtr)); +/* 37 */ +EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin)); +/* 38 */ +EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[], + double p2[], double p3[], double width, + double m1[], double m2[])); +/* 39 */ +EXTERN void TkGetPointerCoords _ANSI_ARGS_((Tk_Window tkwin, + int * xPtr, int * yPtr)); +/* 40 */ +EXTERN void TkGetServerInfo _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin)); +/* 41 */ +EXTERN void TkGrabDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 42 */ +EXTERN int TkGrabState _ANSI_ARGS_((TkWindow * winPtr)); +/* 43 */ +EXTERN void TkIncludePoint _ANSI_ARGS_((Tk_Item * itemPtr, + double * pointPtr)); +/* 44 */ +EXTERN void TkInOutEvents _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * sourcePtr, TkWindow * destPtr, + int leaveType, int enterType, + Tcl_QueuePosition position)); +/* 45 */ +EXTERN void TkInstallFrameMenu _ANSI_ARGS_((Tk_Window tkwin)); +/* 46 */ +EXTERN char * TkKeysymToString _ANSI_ARGS_((KeySym keysym)); +/* 47 */ +EXTERN int TkLineToArea _ANSI_ARGS_((double end1Ptr[], + double end2Ptr[], double rectPtr[])); +/* 48 */ +EXTERN double TkLineToPoint _ANSI_ARGS_((double end1Ptr[], + double end2Ptr[], double pointPtr[])); +/* 49 */ +EXTERN int TkMakeBezierCurve _ANSI_ARGS_((Tk_Canvas canvas, + double * pointPtr, int numPoints, + int numSteps, XPoint xPoints[], + double dblPoints[])); +/* 50 */ +EXTERN void TkMakeBezierPostscript _ANSI_ARGS_(( + Tcl_Interp * interp, Tk_Canvas canvas, + double * pointPtr, int numPoints)); +/* 51 */ +EXTERN void TkOptionClassChanged _ANSI_ARGS_((TkWindow * winPtr)); +/* 52 */ +EXTERN void TkOptionDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 53 */ +EXTERN int TkOvalToArea _ANSI_ARGS_((double * ovalPtr, + double * rectPtr)); +/* 54 */ +EXTERN double TkOvalToPoint _ANSI_ARGS_((double ovalPtr[], + double width, int filled, double pointPtr[])); +/* 55 */ +EXTERN int TkpChangeFocus _ANSI_ARGS_((TkWindow * winPtr, + int force)); +/* 56 */ +EXTERN void TkpCloseDisplay _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 57 */ +EXTERN void TkpClaimFocus _ANSI_ARGS_((TkWindow * topLevelPtr, + int force)); +/* 58 */ +EXTERN void TkpDisplayWarning _ANSI_ARGS_((char * msg, + char * title)); +/* 59 */ +EXTERN void TkpGetAppName _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * name)); +/* 60 */ +EXTERN TkWindow * TkpGetOtherWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 61 */ +EXTERN TkWindow * TkpGetWrapperWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 62 */ +EXTERN int TkpInit _ANSI_ARGS_((Tcl_Interp * interp)); +/* 63 */ +EXTERN void TkpInitializeMenuBindings _ANSI_ARGS_(( + Tcl_Interp * interp, + Tk_BindingTable bindingTable)); +/* 64 */ +EXTERN void TkpMakeContainer _ANSI_ARGS_((Tk_Window tkwin)); +/* 65 */ +EXTERN void TkpMakeMenuWindow _ANSI_ARGS_((Tk_Window tkwin, + int transient)); +/* 66 */ +EXTERN Window TkpMakeWindow _ANSI_ARGS_((TkWindow * winPtr, + Window parent)); +/* 67 */ +EXTERN void TkpMenuNotifyToplevelCreate _ANSI_ARGS_(( + Tcl_Interp * interp1, char * menuName)); +/* 68 */ +EXTERN TkDisplay * TkpOpenDisplay _ANSI_ARGS_((char * display_name)); +/* 69 */ +EXTERN int TkPointerEvent _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * winPtr)); +/* 70 */ +EXTERN int TkPolygonToArea _ANSI_ARGS_((double * polyPtr, + int numPoints, double * rectPtr)); +/* 71 */ +EXTERN double TkPolygonToPoint _ANSI_ARGS_((double * polyPtr, + int numPoints, double * pointPtr)); +/* 72 */ +EXTERN int TkPositionInTree _ANSI_ARGS_((TkWindow * winPtr, + TkWindow * treePtr)); +/* 73 */ +EXTERN void TkpRedirectKeyEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 74 */ +EXTERN void TkpSetMainMenubar _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * menuName)); +/* 75 */ +EXTERN int TkpUseWindow _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * string)); +/* 76 */ +EXTERN int TkpWindowWasRecentlyDeleted _ANSI_ARGS_((Window win, + TkDisplay * dispPtr)); +/* 77 */ +EXTERN void TkQueueEventForAllChildren _ANSI_ARGS_(( + TkWindow * winPtr, XEvent * eventPtr)); +/* 78 */ +EXTERN int TkReadBitmapFile _ANSI_ARGS_((Display* display, + Drawable d, CONST char* filename, + unsigned int* width_return, + unsigned int* height_return, + Pixmap* bitmap_return, int* x_hot_return, + int* y_hot_return)); +/* 79 */ +EXTERN int TkScrollWindow _ANSI_ARGS_((Tk_Window tkwin, GC gc, + int x, int y, int width, int height, int dx, + int dy, TkRegion damageRgn)); +/* 80 */ +EXTERN void TkSelDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 81 */ +EXTERN void TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin, + XEvent * eventPtr)); +/* 82 */ +EXTERN void TkSelInit _ANSI_ARGS_((Tk_Window tkwin)); +/* 83 */ +EXTERN void TkSelPropProc _ANSI_ARGS_((XEvent * eventPtr)); +/* 84 */ +EXTERN void TkSetClassProcs _ANSI_ARGS_((Tk_Window tkwin, + TkClassProcs * procs, + ClientData instanceData)); +/* 85 */ +EXTERN void TkSetWindowMenuBar _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * oldMenuName, + char * menuName)); +/* 86 */ +EXTERN KeySym TkStringToKeysym _ANSI_ARGS_((char * name)); +/* 87 */ +EXTERN int TkThickPolyLineToArea _ANSI_ARGS_((double * coordPtr, + int numPoints, double width, int capStyle, + int joinStyle, double * rectPtr)); +/* 88 */ +EXTERN void TkWmAddToColormapWindows _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 89 */ +EXTERN void TkWmDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 90 */ +EXTERN TkWindow * TkWmFocusToplevel _ANSI_ARGS_((TkWindow * winPtr)); +/* 91 */ +EXTERN void TkWmMapWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 92 */ +EXTERN void TkWmNewWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 93 */ +EXTERN void TkWmProtocolEventProc _ANSI_ARGS_((TkWindow * winPtr, + XEvent * evenvPtr)); +/* 94 */ +EXTERN void TkWmRemoveFromColormapWindows _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 95 */ +EXTERN void TkWmRestackToplevel _ANSI_ARGS_((TkWindow * winPtr, + int aboveBelow, TkWindow * otherPtr)); +/* 96 */ +EXTERN void TkWmSetClass _ANSI_ARGS_((TkWindow * winPtr)); +/* 97 */ +EXTERN void TkWmUnmapWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 98 */ +EXTERN Tcl_Obj * TkDebugBitmap _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 99 */ +EXTERN Tcl_Obj * TkDebugBorder _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 100 */ +EXTERN Tcl_Obj * TkDebugCursor _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 101 */ +EXTERN Tcl_Obj * TkDebugColor _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 102 */ +EXTERN Tcl_Obj * TkDebugConfig _ANSI_ARGS_((Tcl_Interp * interp, + Tk_OptionTable table)); +/* 103 */ +EXTERN Tcl_Obj * TkDebugFont _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 104 */ +EXTERN int TkFindStateNumObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * optionPtr, + CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr)); +/* 105 */ +EXTERN Tcl_HashTable * TkGetBitmapPredefTable _ANSI_ARGS_((void)); +/* 106 */ +EXTERN TkDisplay * TkGetDisplayList _ANSI_ARGS_((void)); +/* 107 */ +EXTERN TkMainInfo * TkGetMainInfoList _ANSI_ARGS_((void)); +/* 108 */ +EXTERN int TkGetWindowFromObj _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, Tcl_Obj * objPtr, + Tk_Window * windowPtr)); +/* 109 */ +EXTERN char * TkpGetString _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr, Tcl_DString * dsPtr)); +/* 110 */ +EXTERN void TkpGetSubFonts _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Font tkfont)); +/* 111 */ +EXTERN Tcl_Obj * TkpGetSystemDefault _ANSI_ARGS_((Tk_Window tkwin, + char * dbName, char * className)); +/* 112 */ +EXTERN void TkpMenuThreadInit _ANSI_ARGS_((void)); +#ifdef __WIN32__ +/* 113 */ +EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, + XRectangle* rect_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 113 */ +EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, + XRectangle* rect_return)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 114 */ +EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 114 */ +EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 115 */ +EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 115 */ +EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 116 */ +EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 116 */ +EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 117 */ +EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, + int y, unsigned int width, + unsigned int height)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 117 */ +EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, + int y, unsigned int width, + unsigned int height)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 118 */ +EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc, + TkRegion rgn)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 118 */ +EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc, + TkRegion rgn)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 119 */ +EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect, + TkRegion src, TkRegion dr_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 119 */ +EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect, + TkRegion src, TkRegion dr_return)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 120 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 121 */ +EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display, + char * source)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 122 */ +EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 123 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 124 */ +EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display * display, + CONST char * name, int * width, int * height)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 125 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 126 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 127 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 128 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +#endif /* MAC_TCL */ +/* Slot 129 is reserved */ +#ifdef MAC_TCL +/* 130 */ +EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 131 */ +EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, + Window window, unsigned int state)); +#endif /* MAC_TCL */ +/* Slot 132 is reserved */ +#ifdef MAC_TCL +/* 133 */ +EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 134 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +#endif /* MAC_TCL */ +/* 135 */ +EXTERN void TkpDrawHighlightBorder _ANSI_ARGS_((Tk_Window tkwin, + GC fgGC, GC bgGC, int highlightWidth, + Drawable drawable)); +/* 136 */ +EXTERN void TkSetFocusWin _ANSI_ARGS_((TkWindow * winPtr, + int force)); + +typedef struct TkIntStubs { + int magic; + struct TkIntStubHooks *hooks; + + TkWindow * (*tkAllocWindow) _ANSI_ARGS_((TkDisplay * dispPtr, int screenNum, TkWindow * parentPtr)); /* 0 */ + void (*tkBezierPoints) _ANSI_ARGS_((double control[], int numSteps, double * coordPtr)); /* 1 */ + void (*tkBezierScreenPoints) _ANSI_ARGS_((Tk_Canvas canvas, double control[], int numSteps, XPoint * xPointPtr)); /* 2 */ + void (*tkBindDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 3 */ + void (*tkBindEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 4 */ + void (*tkBindFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 5 */ + void (*tkBindInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 6 */ + void (*tkChangeEventWindow) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 7 */ + int (*tkClipInit) _ANSI_ARGS_((Tcl_Interp * interp, TkDisplay * dispPtr)); /* 8 */ + void (*tkComputeAnchor) _ANSI_ARGS_((Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int * xPtr, int * yPtr)); /* 9 */ + int (*tkCopyAndGlobalEval) _ANSI_ARGS_((Tcl_Interp * interp, char * script)); /* 10 */ + unsigned long (*tkCreateBindingProcedure) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object, char * eventString, TkBindEvalProc * evalProc, TkBindFreeProc * freeProc, ClientData clientData)); /* 11 */ + TkCursor * (*tkCreateCursorFromData) _ANSI_ARGS_((Tk_Window tkwin, char * source, char * mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg)); /* 12 */ + int (*tkCreateFrame) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv, int toplevel, char * appName)); /* 13 */ + Tk_Window (*tkCreateMainWindow) _ANSI_ARGS_((Tcl_Interp * interp, char * screenName, char * baseName)); /* 14 */ + Time (*tkCurrentTime) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 15 */ + void (*tkDeleteAllImages) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 16 */ + void (*tkDoConfigureNotify) _ANSI_ARGS_((TkWindow * winPtr)); /* 17 */ + void (*tkDrawInsetFocusHighlight) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding)); /* 18 */ + void (*tkEventDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 19 */ + void (*tkFillPolygon) _ANSI_ARGS_((Tk_Canvas canvas, double * coordPtr, int numPoints, Display * display, Drawable drawable, GC gc, GC outlineGC)); /* 20 */ + int (*tkFindStateNum) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * option, CONST TkStateMap * mapPtr, CONST char * strKey)); /* 21 */ + char * (*tkFindStateString) _ANSI_ARGS_((CONST TkStateMap * mapPtr, int numKey)); /* 22 */ + void (*tkFocusDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 23 */ + int (*tkFocusFilterEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 24 */ + TkWindow * (*tkFocusKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 25 */ + void (*tkFontPkgInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 26 */ + void (*tkFontPkgFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 27 */ + void (*tkFreeBindingTags) _ANSI_ARGS_((TkWindow * winPtr)); /* 28 */ + void (*tkpFreeCursor) _ANSI_ARGS_((TkCursor * cursorPtr)); /* 29 */ + char * (*tkGetBitmapData) _ANSI_ARGS_((Tcl_Interp * interp, char * string, char * fileName, int * widthPtr, int * heightPtr, int * hotXPtr, int * hotYPtr)); /* 30 */ + void (*tkGetButtPoints) _ANSI_ARGS_((double p1[], double p2[], double width, int project, double m1[], double m2[])); /* 31 */ + TkCursor * (*tkGetCursorByName) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_Uid string)); /* 32 */ + char * (*tkGetDefaultScreenName) _ANSI_ARGS_((Tcl_Interp * interp, char * screenName)); /* 33 */ + TkDisplay * (*tkGetDisplay) _ANSI_ARGS_((Display * display)); /* 34 */ + int (*tkGetDisplayOf) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], Tk_Window * tkwinPtr)); /* 35 */ + TkWindow * (*tkGetFocusWin) _ANSI_ARGS_((TkWindow * winPtr)); /* 36 */ + int (*tkGetInterpNames) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 37 */ + int (*tkGetMiterPoints) _ANSI_ARGS_((double p1[], double p2[], double p3[], double width, double m1[], double m2[])); /* 38 */ + void (*tkGetPointerCoords) _ANSI_ARGS_((Tk_Window tkwin, int * xPtr, int * yPtr)); /* 39 */ + void (*tkGetServerInfo) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 40 */ + void (*tkGrabDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 41 */ + int (*tkGrabState) _ANSI_ARGS_((TkWindow * winPtr)); /* 42 */ + void (*tkIncludePoint) _ANSI_ARGS_((Tk_Item * itemPtr, double * pointPtr)); /* 43 */ + void (*tkInOutEvents) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * sourcePtr, TkWindow * destPtr, int leaveType, int enterType, Tcl_QueuePosition position)); /* 44 */ + void (*tkInstallFrameMenu) _ANSI_ARGS_((Tk_Window tkwin)); /* 45 */ + char * (*tkKeysymToString) _ANSI_ARGS_((KeySym keysym)); /* 46 */ + int (*tkLineToArea) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double rectPtr[])); /* 47 */ + double (*tkLineToPoint) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double pointPtr[])); /* 48 */ + int (*tkMakeBezierCurve) _ANSI_ARGS_((Tk_Canvas canvas, double * pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[])); /* 49 */ + void (*tkMakeBezierPostscript) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, double * pointPtr, int numPoints)); /* 50 */ + void (*tkOptionClassChanged) _ANSI_ARGS_((TkWindow * winPtr)); /* 51 */ + void (*tkOptionDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 52 */ + int (*tkOvalToArea) _ANSI_ARGS_((double * ovalPtr, double * rectPtr)); /* 53 */ + double (*tkOvalToPoint) _ANSI_ARGS_((double ovalPtr[], double width, int filled, double pointPtr[])); /* 54 */ + int (*tkpChangeFocus) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 55 */ + void (*tkpCloseDisplay) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 56 */ + void (*tkpClaimFocus) _ANSI_ARGS_((TkWindow * topLevelPtr, int force)); /* 57 */ + void (*tkpDisplayWarning) _ANSI_ARGS_((char * msg, char * title)); /* 58 */ + void (*tkpGetAppName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * name)); /* 59 */ + TkWindow * (*tkpGetOtherWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 60 */ + TkWindow * (*tkpGetWrapperWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 61 */ + int (*tkpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 62 */ + void (*tkpInitializeMenuBindings) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable)); /* 63 */ + void (*tkpMakeContainer) _ANSI_ARGS_((Tk_Window tkwin)); /* 64 */ + void (*tkpMakeMenuWindow) _ANSI_ARGS_((Tk_Window tkwin, int transient)); /* 65 */ + Window (*tkpMakeWindow) _ANSI_ARGS_((TkWindow * winPtr, Window parent)); /* 66 */ + void (*tkpMenuNotifyToplevelCreate) _ANSI_ARGS_((Tcl_Interp * interp1, char * menuName)); /* 67 */ + TkDisplay * (*tkpOpenDisplay) _ANSI_ARGS_((char * display_name)); /* 68 */ + int (*tkPointerEvent) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 69 */ + int (*tkPolygonToArea) _ANSI_ARGS_((double * polyPtr, int numPoints, double * rectPtr)); /* 70 */ + double (*tkPolygonToPoint) _ANSI_ARGS_((double * polyPtr, int numPoints, double * pointPtr)); /* 71 */ + int (*tkPositionInTree) _ANSI_ARGS_((TkWindow * winPtr, TkWindow * treePtr)); /* 72 */ + void (*tkpRedirectKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 73 */ + void (*tkpSetMainMenubar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * menuName)); /* 74 */ + int (*tkpUseWindow) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * string)); /* 75 */ + int (*tkpWindowWasRecentlyDeleted) _ANSI_ARGS_((Window win, TkDisplay * dispPtr)); /* 76 */ + void (*tkQueueEventForAllChildren) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 77 */ + int (*tkReadBitmapFile) _ANSI_ARGS_((Display* display, Drawable d, CONST char* filename, unsigned int* width_return, unsigned int* height_return, Pixmap* bitmap_return, int* x_hot_return, int* y_hot_return)); /* 78 */ + int (*tkScrollWindow) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn)); /* 79 */ + void (*tkSelDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 80 */ + void (*tkSelEventProc) _ANSI_ARGS_((Tk_Window tkwin, XEvent * eventPtr)); /* 81 */ + void (*tkSelInit) _ANSI_ARGS_((Tk_Window tkwin)); /* 82 */ + void (*tkSelPropProc) _ANSI_ARGS_((XEvent * eventPtr)); /* 83 */ + void (*tkSetClassProcs) _ANSI_ARGS_((Tk_Window tkwin, TkClassProcs * procs, ClientData instanceData)); /* 84 */ + void (*tkSetWindowMenuBar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * oldMenuName, char * menuName)); /* 85 */ + KeySym (*tkStringToKeysym) _ANSI_ARGS_((char * name)); /* 86 */ + int (*tkThickPolyLineToArea) _ANSI_ARGS_((double * coordPtr, int numPoints, double width, int capStyle, int joinStyle, double * rectPtr)); /* 87 */ + void (*tkWmAddToColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 88 */ + void (*tkWmDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 89 */ + TkWindow * (*tkWmFocusToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 90 */ + void (*tkWmMapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 91 */ + void (*tkWmNewWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 92 */ + void (*tkWmProtocolEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * evenvPtr)); /* 93 */ + void (*tkWmRemoveFromColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 94 */ + void (*tkWmRestackToplevel) _ANSI_ARGS_((TkWindow * winPtr, int aboveBelow, TkWindow * otherPtr)); /* 95 */ + void (*tkWmSetClass) _ANSI_ARGS_((TkWindow * winPtr)); /* 96 */ + void (*tkWmUnmapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 97 */ + Tcl_Obj * (*tkDebugBitmap) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 98 */ + Tcl_Obj * (*tkDebugBorder) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 99 */ + Tcl_Obj * (*tkDebugCursor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 100 */ + Tcl_Obj * (*tkDebugColor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 101 */ + Tcl_Obj * (*tkDebugConfig) _ANSI_ARGS_((Tcl_Interp * interp, Tk_OptionTable table)); /* 102 */ + Tcl_Obj * (*tkDebugFont) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 103 */ + int (*tkFindStateNumObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * optionPtr, CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr)); /* 104 */ + Tcl_HashTable * (*tkGetBitmapPredefTable) _ANSI_ARGS_((void)); /* 105 */ + TkDisplay * (*tkGetDisplayList) _ANSI_ARGS_((void)); /* 106 */ + TkMainInfo * (*tkGetMainInfoList) _ANSI_ARGS_((void)); /* 107 */ + int (*tkGetWindowFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr, Tk_Window * windowPtr)); /* 108 */ + char * (*tkpGetString) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr, Tcl_DString * dsPtr)); /* 109 */ + void (*tkpGetSubFonts) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Font tkfont)); /* 110 */ + Tcl_Obj * (*tkpGetSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, char * dbName, char * className)); /* 111 */ + void (*tkpMenuThreadInit) _ANSI_ARGS_((void)); /* 112 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved113; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved114; +#endif /* UNIX */ +#ifdef __WIN32__ + TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved115; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved116; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved117; +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved118; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved119; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved120; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved120; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 120 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved121; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved121; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, char * source)); /* 121 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved122; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved122; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 122 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved123; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved123; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 123 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved124; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved124; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display * display, CONST char * name, int * width, int * height)); /* 124 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved125; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved125; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 125 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved126; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved126; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 126 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved127; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved127; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 127 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved128; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved128; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 128 */ +#endif /* MAC_TCL */ + void *reserved129; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved130; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved130; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 130 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved131; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved131; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 131 */ +#endif /* MAC_TCL */ + void *reserved132; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved133; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved133; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 133 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved134; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved134; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 134 */ +#endif /* MAC_TCL */ + void (*tkpDrawHighlightBorder) _ANSI_ARGS_((Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable)); /* 135 */ + void (*tkSetFocusWin) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 136 */ +} TkIntStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkIntStubs *tkIntStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifndef TkAllocWindow +#define TkAllocWindow \ + (tkIntStubsPtr->tkAllocWindow) /* 0 */ +#endif +#ifndef TkBezierPoints +#define TkBezierPoints \ + (tkIntStubsPtr->tkBezierPoints) /* 1 */ +#endif +#ifndef TkBezierScreenPoints +#define TkBezierScreenPoints \ + (tkIntStubsPtr->tkBezierScreenPoints) /* 2 */ +#endif +#ifndef TkBindDeadWindow +#define TkBindDeadWindow \ + (tkIntStubsPtr->tkBindDeadWindow) /* 3 */ +#endif +#ifndef TkBindEventProc +#define TkBindEventProc \ + (tkIntStubsPtr->tkBindEventProc) /* 4 */ +#endif +#ifndef TkBindFree +#define TkBindFree \ + (tkIntStubsPtr->tkBindFree) /* 5 */ +#endif +#ifndef TkBindInit +#define TkBindInit \ + (tkIntStubsPtr->tkBindInit) /* 6 */ +#endif +#ifndef TkChangeEventWindow +#define TkChangeEventWindow \ + (tkIntStubsPtr->tkChangeEventWindow) /* 7 */ +#endif +#ifndef TkClipInit +#define TkClipInit \ + (tkIntStubsPtr->tkClipInit) /* 8 */ +#endif +#ifndef TkComputeAnchor +#define TkComputeAnchor \ + (tkIntStubsPtr->tkComputeAnchor) /* 9 */ +#endif +#ifndef TkCopyAndGlobalEval +#define TkCopyAndGlobalEval \ + (tkIntStubsPtr->tkCopyAndGlobalEval) /* 10 */ +#endif +#ifndef TkCreateBindingProcedure +#define TkCreateBindingProcedure \ + (tkIntStubsPtr->tkCreateBindingProcedure) /* 11 */ +#endif +#ifndef TkCreateCursorFromData +#define TkCreateCursorFromData \ + (tkIntStubsPtr->tkCreateCursorFromData) /* 12 */ +#endif +#ifndef TkCreateFrame +#define TkCreateFrame \ + (tkIntStubsPtr->tkCreateFrame) /* 13 */ +#endif +#ifndef TkCreateMainWindow +#define TkCreateMainWindow \ + (tkIntStubsPtr->tkCreateMainWindow) /* 14 */ +#endif +#ifndef TkCurrentTime +#define TkCurrentTime \ + (tkIntStubsPtr->tkCurrentTime) /* 15 */ +#endif +#ifndef TkDeleteAllImages +#define TkDeleteAllImages \ + (tkIntStubsPtr->tkDeleteAllImages) /* 16 */ +#endif +#ifndef TkDoConfigureNotify +#define TkDoConfigureNotify \ + (tkIntStubsPtr->tkDoConfigureNotify) /* 17 */ +#endif +#ifndef TkDrawInsetFocusHighlight +#define TkDrawInsetFocusHighlight \ + (tkIntStubsPtr->tkDrawInsetFocusHighlight) /* 18 */ +#endif +#ifndef TkEventDeadWindow +#define TkEventDeadWindow \ + (tkIntStubsPtr->tkEventDeadWindow) /* 19 */ +#endif +#ifndef TkFillPolygon +#define TkFillPolygon \ + (tkIntStubsPtr->tkFillPolygon) /* 20 */ +#endif +#ifndef TkFindStateNum +#define TkFindStateNum \ + (tkIntStubsPtr->tkFindStateNum) /* 21 */ +#endif +#ifndef TkFindStateString +#define TkFindStateString \ + (tkIntStubsPtr->tkFindStateString) /* 22 */ +#endif +#ifndef TkFocusDeadWindow +#define TkFocusDeadWindow \ + (tkIntStubsPtr->tkFocusDeadWindow) /* 23 */ +#endif +#ifndef TkFocusFilterEvent +#define TkFocusFilterEvent \ + (tkIntStubsPtr->tkFocusFilterEvent) /* 24 */ +#endif +#ifndef TkFocusKeyEvent +#define TkFocusKeyEvent \ + (tkIntStubsPtr->tkFocusKeyEvent) /* 25 */ +#endif +#ifndef TkFontPkgInit +#define TkFontPkgInit \ + (tkIntStubsPtr->tkFontPkgInit) /* 26 */ +#endif +#ifndef TkFontPkgFree +#define TkFontPkgFree \ + (tkIntStubsPtr->tkFontPkgFree) /* 27 */ +#endif +#ifndef TkFreeBindingTags +#define TkFreeBindingTags \ + (tkIntStubsPtr->tkFreeBindingTags) /* 28 */ +#endif +#ifndef TkpFreeCursor +#define TkpFreeCursor \ + (tkIntStubsPtr->tkpFreeCursor) /* 29 */ +#endif +#ifndef TkGetBitmapData +#define TkGetBitmapData \ + (tkIntStubsPtr->tkGetBitmapData) /* 30 */ +#endif +#ifndef TkGetButtPoints +#define TkGetButtPoints \ + (tkIntStubsPtr->tkGetButtPoints) /* 31 */ +#endif +#ifndef TkGetCursorByName +#define TkGetCursorByName \ + (tkIntStubsPtr->tkGetCursorByName) /* 32 */ +#endif +#ifndef TkGetDefaultScreenName +#define TkGetDefaultScreenName \ + (tkIntStubsPtr->tkGetDefaultScreenName) /* 33 */ +#endif +#ifndef TkGetDisplay +#define TkGetDisplay \ + (tkIntStubsPtr->tkGetDisplay) /* 34 */ +#endif +#ifndef TkGetDisplayOf +#define TkGetDisplayOf \ + (tkIntStubsPtr->tkGetDisplayOf) /* 35 */ +#endif +#ifndef TkGetFocusWin +#define TkGetFocusWin \ + (tkIntStubsPtr->tkGetFocusWin) /* 36 */ +#endif +#ifndef TkGetInterpNames +#define TkGetInterpNames \ + (tkIntStubsPtr->tkGetInterpNames) /* 37 */ +#endif +#ifndef TkGetMiterPoints +#define TkGetMiterPoints \ + (tkIntStubsPtr->tkGetMiterPoints) /* 38 */ +#endif +#ifndef TkGetPointerCoords +#define TkGetPointerCoords \ + (tkIntStubsPtr->tkGetPointerCoords) /* 39 */ +#endif +#ifndef TkGetServerInfo +#define TkGetServerInfo \ + (tkIntStubsPtr->tkGetServerInfo) /* 40 */ +#endif +#ifndef TkGrabDeadWindow +#define TkGrabDeadWindow \ + (tkIntStubsPtr->tkGrabDeadWindow) /* 41 */ +#endif +#ifndef TkGrabState +#define TkGrabState \ + (tkIntStubsPtr->tkGrabState) /* 42 */ +#endif +#ifndef TkIncludePoint +#define TkIncludePoint \ + (tkIntStubsPtr->tkIncludePoint) /* 43 */ +#endif +#ifndef TkInOutEvents +#define TkInOutEvents \ + (tkIntStubsPtr->tkInOutEvents) /* 44 */ +#endif +#ifndef TkInstallFrameMenu +#define TkInstallFrameMenu \ + (tkIntStubsPtr->tkInstallFrameMenu) /* 45 */ +#endif +#ifndef TkKeysymToString +#define TkKeysymToString \ + (tkIntStubsPtr->tkKeysymToString) /* 46 */ +#endif +#ifndef TkLineToArea +#define TkLineToArea \ + (tkIntStubsPtr->tkLineToArea) /* 47 */ +#endif +#ifndef TkLineToPoint +#define TkLineToPoint \ + (tkIntStubsPtr->tkLineToPoint) /* 48 */ +#endif +#ifndef TkMakeBezierCurve +#define TkMakeBezierCurve \ + (tkIntStubsPtr->tkMakeBezierCurve) /* 49 */ +#endif +#ifndef TkMakeBezierPostscript +#define TkMakeBezierPostscript \ + (tkIntStubsPtr->tkMakeBezierPostscript) /* 50 */ +#endif +#ifndef TkOptionClassChanged +#define TkOptionClassChanged \ + (tkIntStubsPtr->tkOptionClassChanged) /* 51 */ +#endif +#ifndef TkOptionDeadWindow +#define TkOptionDeadWindow \ + (tkIntStubsPtr->tkOptionDeadWindow) /* 52 */ +#endif +#ifndef TkOvalToArea +#define TkOvalToArea \ + (tkIntStubsPtr->tkOvalToArea) /* 53 */ +#endif +#ifndef TkOvalToPoint +#define TkOvalToPoint \ + (tkIntStubsPtr->tkOvalToPoint) /* 54 */ +#endif +#ifndef TkpChangeFocus +#define TkpChangeFocus \ + (tkIntStubsPtr->tkpChangeFocus) /* 55 */ +#endif +#ifndef TkpCloseDisplay +#define TkpCloseDisplay \ + (tkIntStubsPtr->tkpCloseDisplay) /* 56 */ +#endif +#ifndef TkpClaimFocus +#define TkpClaimFocus \ + (tkIntStubsPtr->tkpClaimFocus) /* 57 */ +#endif +#ifndef TkpDisplayWarning +#define TkpDisplayWarning \ + (tkIntStubsPtr->tkpDisplayWarning) /* 58 */ +#endif +#ifndef TkpGetAppName +#define TkpGetAppName \ + (tkIntStubsPtr->tkpGetAppName) /* 59 */ +#endif +#ifndef TkpGetOtherWindow +#define TkpGetOtherWindow \ + (tkIntStubsPtr->tkpGetOtherWindow) /* 60 */ +#endif +#ifndef TkpGetWrapperWindow +#define TkpGetWrapperWindow \ + (tkIntStubsPtr->tkpGetWrapperWindow) /* 61 */ +#endif +#ifndef TkpInit +#define TkpInit \ + (tkIntStubsPtr->tkpInit) /* 62 */ +#endif +#ifndef TkpInitializeMenuBindings +#define TkpInitializeMenuBindings \ + (tkIntStubsPtr->tkpInitializeMenuBindings) /* 63 */ +#endif +#ifndef TkpMakeContainer +#define TkpMakeContainer \ + (tkIntStubsPtr->tkpMakeContainer) /* 64 */ +#endif +#ifndef TkpMakeMenuWindow +#define TkpMakeMenuWindow \ + (tkIntStubsPtr->tkpMakeMenuWindow) /* 65 */ +#endif +#ifndef TkpMakeWindow +#define TkpMakeWindow \ + (tkIntStubsPtr->tkpMakeWindow) /* 66 */ +#endif +#ifndef TkpMenuNotifyToplevelCreate +#define TkpMenuNotifyToplevelCreate \ + (tkIntStubsPtr->tkpMenuNotifyToplevelCreate) /* 67 */ +#endif +#ifndef TkpOpenDisplay +#define TkpOpenDisplay \ + (tkIntStubsPtr->tkpOpenDisplay) /* 68 */ +#endif +#ifndef TkPointerEvent +#define TkPointerEvent \ + (tkIntStubsPtr->tkPointerEvent) /* 69 */ +#endif +#ifndef TkPolygonToArea +#define TkPolygonToArea \ + (tkIntStubsPtr->tkPolygonToArea) /* 70 */ +#endif +#ifndef TkPolygonToPoint +#define TkPolygonToPoint \ + (tkIntStubsPtr->tkPolygonToPoint) /* 71 */ +#endif +#ifndef TkPositionInTree +#define TkPositionInTree \ + (tkIntStubsPtr->tkPositionInTree) /* 72 */ +#endif +#ifndef TkpRedirectKeyEvent +#define TkpRedirectKeyEvent \ + (tkIntStubsPtr->tkpRedirectKeyEvent) /* 73 */ +#endif +#ifndef TkpSetMainMenubar +#define TkpSetMainMenubar \ + (tkIntStubsPtr->tkpSetMainMenubar) /* 74 */ +#endif +#ifndef TkpUseWindow +#define TkpUseWindow \ + (tkIntStubsPtr->tkpUseWindow) /* 75 */ +#endif +#ifndef TkpWindowWasRecentlyDeleted +#define TkpWindowWasRecentlyDeleted \ + (tkIntStubsPtr->tkpWindowWasRecentlyDeleted) /* 76 */ +#endif +#ifndef TkQueueEventForAllChildren +#define TkQueueEventForAllChildren \ + (tkIntStubsPtr->tkQueueEventForAllChildren) /* 77 */ +#endif +#ifndef TkReadBitmapFile +#define TkReadBitmapFile \ + (tkIntStubsPtr->tkReadBitmapFile) /* 78 */ +#endif +#ifndef TkScrollWindow +#define TkScrollWindow \ + (tkIntStubsPtr->tkScrollWindow) /* 79 */ +#endif +#ifndef TkSelDeadWindow +#define TkSelDeadWindow \ + (tkIntStubsPtr->tkSelDeadWindow) /* 80 */ +#endif +#ifndef TkSelEventProc +#define TkSelEventProc \ + (tkIntStubsPtr->tkSelEventProc) /* 81 */ +#endif +#ifndef TkSelInit +#define TkSelInit \ + (tkIntStubsPtr->tkSelInit) /* 82 */ +#endif +#ifndef TkSelPropProc +#define TkSelPropProc \ + (tkIntStubsPtr->tkSelPropProc) /* 83 */ +#endif +#ifndef TkSetClassProcs +#define TkSetClassProcs \ + (tkIntStubsPtr->tkSetClassProcs) /* 84 */ +#endif +#ifndef TkSetWindowMenuBar +#define TkSetWindowMenuBar \ + (tkIntStubsPtr->tkSetWindowMenuBar) /* 85 */ +#endif +#ifndef TkStringToKeysym +#define TkStringToKeysym \ + (tkIntStubsPtr->tkStringToKeysym) /* 86 */ +#endif +#ifndef TkThickPolyLineToArea +#define TkThickPolyLineToArea \ + (tkIntStubsPtr->tkThickPolyLineToArea) /* 87 */ +#endif +#ifndef TkWmAddToColormapWindows +#define TkWmAddToColormapWindows \ + (tkIntStubsPtr->tkWmAddToColormapWindows) /* 88 */ +#endif +#ifndef TkWmDeadWindow +#define TkWmDeadWindow \ + (tkIntStubsPtr->tkWmDeadWindow) /* 89 */ +#endif +#ifndef TkWmFocusToplevel +#define TkWmFocusToplevel \ + (tkIntStubsPtr->tkWmFocusToplevel) /* 90 */ +#endif +#ifndef TkWmMapWindow +#define TkWmMapWindow \ + (tkIntStubsPtr->tkWmMapWindow) /* 91 */ +#endif +#ifndef TkWmNewWindow +#define TkWmNewWindow \ + (tkIntStubsPtr->tkWmNewWindow) /* 92 */ +#endif +#ifndef TkWmProtocolEventProc +#define TkWmProtocolEventProc \ + (tkIntStubsPtr->tkWmProtocolEventProc) /* 93 */ +#endif +#ifndef TkWmRemoveFromColormapWindows +#define TkWmRemoveFromColormapWindows \ + (tkIntStubsPtr->tkWmRemoveFromColormapWindows) /* 94 */ +#endif +#ifndef TkWmRestackToplevel +#define TkWmRestackToplevel \ + (tkIntStubsPtr->tkWmRestackToplevel) /* 95 */ +#endif +#ifndef TkWmSetClass +#define TkWmSetClass \ + (tkIntStubsPtr->tkWmSetClass) /* 96 */ +#endif +#ifndef TkWmUnmapWindow +#define TkWmUnmapWindow \ + (tkIntStubsPtr->tkWmUnmapWindow) /* 97 */ +#endif +#ifndef TkDebugBitmap +#define TkDebugBitmap \ + (tkIntStubsPtr->tkDebugBitmap) /* 98 */ +#endif +#ifndef TkDebugBorder +#define TkDebugBorder \ + (tkIntStubsPtr->tkDebugBorder) /* 99 */ +#endif +#ifndef TkDebugCursor +#define TkDebugCursor \ + (tkIntStubsPtr->tkDebugCursor) /* 100 */ +#endif +#ifndef TkDebugColor +#define TkDebugColor \ + (tkIntStubsPtr->tkDebugColor) /* 101 */ +#endif +#ifndef TkDebugConfig +#define TkDebugConfig \ + (tkIntStubsPtr->tkDebugConfig) /* 102 */ +#endif +#ifndef TkDebugFont +#define TkDebugFont \ + (tkIntStubsPtr->tkDebugFont) /* 103 */ +#endif +#ifndef TkFindStateNumObj +#define TkFindStateNumObj \ + (tkIntStubsPtr->tkFindStateNumObj) /* 104 */ +#endif +#ifndef TkGetBitmapPredefTable +#define TkGetBitmapPredefTable \ + (tkIntStubsPtr->tkGetBitmapPredefTable) /* 105 */ +#endif +#ifndef TkGetDisplayList +#define TkGetDisplayList \ + (tkIntStubsPtr->tkGetDisplayList) /* 106 */ +#endif +#ifndef TkGetMainInfoList +#define TkGetMainInfoList \ + (tkIntStubsPtr->tkGetMainInfoList) /* 107 */ +#endif +#ifndef TkGetWindowFromObj +#define TkGetWindowFromObj \ + (tkIntStubsPtr->tkGetWindowFromObj) /* 108 */ +#endif +#ifndef TkpGetString +#define TkpGetString \ + (tkIntStubsPtr->tkpGetString) /* 109 */ +#endif +#ifndef TkpGetSubFonts +#define TkpGetSubFonts \ + (tkIntStubsPtr->tkpGetSubFonts) /* 110 */ +#endif +#ifndef TkpGetSystemDefault +#define TkpGetSystemDefault \ + (tkIntStubsPtr->tkpGetSystemDefault) /* 111 */ +#endif +#ifndef TkpMenuThreadInit +#define TkpMenuThreadInit \ + (tkIntStubsPtr->tkpMenuThreadInit) /* 112 */ +#endif +#ifdef __WIN32__ +#ifndef TkClipBox +#define TkClipBox \ + (tkIntStubsPtr->tkClipBox) /* 113 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkClipBox +#define TkClipBox \ + (tkIntStubsPtr->tkClipBox) /* 113 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkCreateRegion +#define TkCreateRegion \ + (tkIntStubsPtr->tkCreateRegion) /* 114 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkCreateRegion +#define TkCreateRegion \ + (tkIntStubsPtr->tkCreateRegion) /* 114 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkDestroyRegion +#define TkDestroyRegion \ + (tkIntStubsPtr->tkDestroyRegion) /* 115 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkDestroyRegion +#define TkDestroyRegion \ + (tkIntStubsPtr->tkDestroyRegion) /* 115 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkIntersectRegion +#define TkIntersectRegion \ + (tkIntStubsPtr->tkIntersectRegion) /* 116 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkIntersectRegion +#define TkIntersectRegion \ + (tkIntStubsPtr->tkIntersectRegion) /* 116 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkRectInRegion +#define TkRectInRegion \ + (tkIntStubsPtr->tkRectInRegion) /* 117 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkRectInRegion +#define TkRectInRegion \ + (tkIntStubsPtr->tkRectInRegion) /* 117 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkSetRegion +#define TkSetRegion \ + (tkIntStubsPtr->tkSetRegion) /* 118 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkSetRegion +#define TkSetRegion \ + (tkIntStubsPtr->tkSetRegion) /* 118 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkUnionRectWithRegion +#define TkUnionRectWithRegion \ + (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkUnionRectWithRegion +#define TkUnionRectWithRegion \ + (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntStubsPtr->tkGenerateActivateEvents) /* 120 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpCreateNativeBitmap +#define TkpCreateNativeBitmap \ + (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpDefineNativeBitmaps +#define TkpDefineNativeBitmaps \ + (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntStubsPtr->tkpGetMS) /* 123 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpGetNativeAppBitmap +#define TkpGetNativeAppBitmap \ + (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntStubsPtr->tkPointerDeadWindow) /* 125 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntStubsPtr->tkpSetCapture) /* 126 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntStubsPtr->tkpSetCursor) /* 127 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntStubsPtr->tkpWmSetState) /* 128 */ +#endif +#endif /* MAC_TCL */ +/* Slot 129 is reserved */ +#ifdef MAC_TCL +#ifndef TkGetTransientMaster +#define TkGetTransientMaster \ + (tkIntStubsPtr->tkGetTransientMaster) /* 130 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkGenerateButtonEvent +#define TkGenerateButtonEvent \ + (tkIntStubsPtr->tkGenerateButtonEvent) /* 131 */ +#endif +#endif /* MAC_TCL */ +/* Slot 132 is reserved */ +#ifdef MAC_TCL +#ifndef TkGenWMDestroyEvent +#define TkGenWMDestroyEvent \ + (tkIntStubsPtr->tkGenWMDestroyEvent) /* 133 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkIntStubsPtr->tkGenWMConfigureEvent) /* 134 */ +#endif +#endif /* MAC_TCL */ +#ifndef TkpDrawHighlightBorder +#define TkpDrawHighlightBorder \ + (tkIntStubsPtr->tkpDrawHighlightBorder) /* 135 */ +#endif +#ifndef TkSetFocusWin +#define TkSetFocusWin \ + (tkIntStubsPtr->tkSetFocusWin) /* 136 */ +#endif + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINTDECLS */ + diff --git a/Utilities/TclTk/internals/tk8.2/tkIntPlatDecls.h b/Utilities/TclTk/internals/tk8.2/tkIntPlatDecls.h new file mode 100644 index 0000000..cd0de97 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkIntPlatDecls.h @@ -0,0 +1,837 @@ +/* + * tkIntPlatDecls.h -- + * + * This file contains the declarations for all platform dependent + * unsupported functions that are exported by the Tk library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * All rights reserved. + * + * RCS: @(#) $Id: tkIntPlatDecls.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKINTPLATDECLS +#define _TKINTPLATDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tkInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 0 */ +EXTERN void TkCreateXEventSource _ANSI_ARGS_((void)); +/* 1 */ +EXTERN void TkFreeWindowId _ANSI_ARGS_((TkDisplay * dispPtr, + Window w)); +/* 2 */ +EXTERN void TkInitXId _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 3 */ +EXTERN int TkpCmapStressed _ANSI_ARGS_((Tk_Window tkwin, + Colormap colormap)); +/* 4 */ +EXTERN void TkpSync _ANSI_ARGS_((Display * display)); +/* 5 */ +EXTERN Window TkUnixContainerId _ANSI_ARGS_((TkWindow * winPtr)); +/* 6 */ +EXTERN int TkUnixDoOneXEvent _ANSI_ARGS_((Tcl_Time * timePtr)); +/* 7 */ +EXTERN void TkUnixSetMenubar _ANSI_ARGS_((Tk_Window tkwin, + Tk_Window menubar)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 0 */ +EXTERN char * TkAlignImageData _ANSI_ARGS_((XImage * image, + int alignment, int bitOrder)); +/* Slot 1 is reserved */ +/* 2 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +/* 3 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +/* 4 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 5 */ +EXTERN void TkpPrintWindowId _ANSI_ARGS_((char * buf, + Window window)); +/* 6 */ +EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp * interp, + char * string, int * idPtr)); +/* 7 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +/* 8 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +/* 9 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +/* 10 */ +EXTERN void TkSetPixmapColormap _ANSI_ARGS_((Pixmap pixmap, + Colormap colormap)); +/* 11 */ +EXTERN void TkWinCancelMouseTimer _ANSI_ARGS_((void)); +/* 12 */ +EXTERN void TkWinClipboardRender _ANSI_ARGS_(( + TkDisplay * dispPtr, UINT format)); +/* 13 */ +EXTERN LRESULT TkWinEmbeddedEventProc _ANSI_ARGS_((HWND hwnd, + UINT message, WPARAM wParam, LPARAM lParam)); +/* 14 */ +EXTERN void TkWinFillRect _ANSI_ARGS_((HDC dc, int x, int y, + int width, int height, int pixel)); +/* 15 */ +EXTERN COLORREF TkWinGetBorderPixels _ANSI_ARGS_((Tk_Window tkwin, + Tk_3DBorder border, int which)); +/* 16 */ +EXTERN HDC TkWinGetDrawableDC _ANSI_ARGS_((Display * display, + Drawable d, TkWinDCState* state)); +/* 17 */ +EXTERN int TkWinGetModifierState _ANSI_ARGS_((void)); +/* 18 */ +EXTERN HPALETTE TkWinGetSystemPalette _ANSI_ARGS_((void)); +/* 19 */ +EXTERN HWND TkWinGetWrapperWindow _ANSI_ARGS_((Tk_Window tkwin)); +/* 20 */ +EXTERN int TkWinHandleMenuEvent _ANSI_ARGS_((HWND * phwnd, + UINT * pMessage, WPARAM * pwParam, + LPARAM * plParam, LRESULT * plResult)); +/* 21 */ +EXTERN int TkWinIndexOfColor _ANSI_ARGS_((XColor * colorPtr)); +/* 22 */ +EXTERN void TkWinReleaseDrawableDC _ANSI_ARGS_((Drawable d, + HDC hdc, TkWinDCState* state)); +/* 23 */ +EXTERN LRESULT TkWinResendEvent _ANSI_ARGS_((WNDPROC wndproc, + HWND hwnd, XEvent * eventPtr)); +/* 24 */ +EXTERN HPALETTE TkWinSelectPalette _ANSI_ARGS_((HDC dc, + Colormap colormap)); +/* 25 */ +EXTERN void TkWinSetMenu _ANSI_ARGS_((Tk_Window tkwin, + HMENU hMenu)); +/* 26 */ +EXTERN void TkWinSetWindowPos _ANSI_ARGS_((HWND hwnd, + HWND siblingHwnd, int pos)); +/* 27 */ +EXTERN void TkWinWmCleanup _ANSI_ARGS_((HINSTANCE hInstance)); +/* 28 */ +EXTERN void TkWinXCleanup _ANSI_ARGS_((HINSTANCE hInstance)); +/* 29 */ +EXTERN void TkWinXInit _ANSI_ARGS_((HINSTANCE hInstance)); +/* 30 */ +EXTERN void TkWinSetForegroundWindow _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 31 */ +EXTERN void TkWinDialogDebug _ANSI_ARGS_((int debug)); +/* 32 */ +EXTERN Tcl_Obj * TkWinGetMenuSystemDefault _ANSI_ARGS_(( + Tk_Window tkwin, char * dbName, + char * className)); +/* 33 */ +EXTERN int TkWinGetPlatformId _ANSI_ARGS_((void)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +/* 1 */ +EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display, + char * source)); +/* 2 */ +EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); +/* 3 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +/* Slot 4 is reserved */ +/* 5 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 6 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +/* 7 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +/* 8 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +/* Slot 9 is reserved */ +/* 10 */ +EXTERN void TkAboutDlg _ANSI_ARGS_((void)); +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ +/* 13 */ +EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr)); +/* 14 */ +EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, + Window window, unsigned int state)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); +/* 17 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +/* 18 */ +EXTERN unsigned int TkMacButtonKeyState _ANSI_ARGS_((void)); +/* 19 */ +EXTERN void TkMacClearMenubarActive _ANSI_ARGS_((void)); +/* 20 */ +EXTERN int TkMacConvertEvent _ANSI_ARGS_(( + EventRecord * eventPtr)); +/* 21 */ +EXTERN int TkMacDispatchMenuEvent _ANSI_ARGS_((int menuID, + int index)); +/* 22 */ +EXTERN void TkMacInstallCursor _ANSI_ARGS_((int resizeOverride)); +/* 23 */ +EXTERN int TkMacConvertTkEvent _ANSI_ARGS_(( + EventRecord * eventPtr, Window window)); +/* 24 */ +EXTERN void TkMacHandleTearoffMenu _ANSI_ARGS_((void)); +/* Slot 25 is reserved */ +/* 26 */ +EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr)); +/* 27 */ +EXTERN void TkMacDoHLEvent _ANSI_ARGS_((EventRecord * theEvent)); +/* Slot 28 is reserved */ +/* 29 */ +EXTERN Time TkMacGenerateTime _ANSI_ARGS_((void)); +/* 30 */ +EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable)); +/* 31 */ +EXTERN TkWindow * TkMacGetScrollbarGrowWindow _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 32 */ +EXTERN Window TkMacGetXWindow _ANSI_ARGS_((WindowRef macWinPtr)); +/* 33 */ +EXTERN int TkMacGrowToplevel _ANSI_ARGS_((WindowRef whichWindow, + Point start)); +/* 34 */ +EXTERN void TkMacHandleMenuSelect _ANSI_ARGS_((long mResult, + int optionKeyPressed)); +/* 35 */ +EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void)); +/* 36 */ +EXTERN void TkMacInitAppleEvents _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 37 */ +EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp * interp)); +/* 38 */ +EXTERN void TkMacInvalidateWindow _ANSI_ARGS_(( + MacDrawable * macWin, int flag)); +/* 39 */ +EXTERN int TkMacIsCharacterMissing _ANSI_ARGS_((Tk_Font tkfont, + unsigned int searchChar)); +/* 40 */ +EXTERN void TkMacMakeRealWindowExist _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 41 */ +EXTERN BitMapPtr TkMacMakeStippleMap _ANSI_ARGS_((Drawable d1, + Drawable d2)); +/* 42 */ +EXTERN void TkMacMenuClick _ANSI_ARGS_((void)); +/* 43 */ +EXTERN void TkMacRegisterOffScreenWindow _ANSI_ARGS_(( + Window window, GWorldPtr portPtr)); +/* 44 */ +EXTERN int TkMacResizable _ANSI_ARGS_((TkWindow * winPtr)); +/* Slot 45 is reserved */ +/* 46 */ +EXTERN void TkMacSetHelpMenuItemCount _ANSI_ARGS_((void)); +/* 47 */ +EXTERN void TkMacSetScrollbarGrow _ANSI_ARGS_((TkWindow * winPtr, + int flag)); +/* 48 */ +EXTERN void TkMacSetUpClippingRgn _ANSI_ARGS_((Drawable drawable)); +/* 49 */ +EXTERN void TkMacSetUpGraphicsPort _ANSI_ARGS_((GC gc)); +/* 50 */ +EXTERN void TkMacUpdateClipRgn _ANSI_ARGS_((TkWindow * winPtr)); +/* 51 */ +EXTERN void TkMacUnregisterMacWindow _ANSI_ARGS_(( + GWorldPtr portPtr)); +/* 52 */ +EXTERN int TkMacUseMenuID _ANSI_ARGS_((short macID)); +/* 53 */ +EXTERN RgnHandle TkMacVisableClipRgn _ANSI_ARGS_((TkWindow * winPtr)); +/* 54 */ +EXTERN void TkMacWinBounds _ANSI_ARGS_((TkWindow * winPtr, + Rect * geometry)); +/* 55 */ +EXTERN void TkMacWindowOffset _ANSI_ARGS_((WindowRef wRef, + int * xOffset, int * yOffset)); +/* Slot 56 is reserved */ +/* 57 */ +EXTERN int TkSetMacColor _ANSI_ARGS_((unsigned long pixel, + RGBColor * macColor)); +/* 58 */ +EXTERN void TkSetWMName _ANSI_ARGS_((TkWindow * winPtr, + Tk_Uid titleUid)); +/* 59 */ +EXTERN void TkSuspendClipboard _ANSI_ARGS_((void)); +/* Slot 60 is reserved */ +/* 61 */ +EXTERN int TkMacZoomToplevel _ANSI_ARGS_((WindowPtr whichWindow, + Point where, short zoomPart)); +/* 62 */ +EXTERN Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin, + int rootX, int rootY, int * newX, int * newY)); +/* 63 */ +EXTERN MacDrawable * TkMacContainerId _ANSI_ARGS_((TkWindow * winPtr)); +/* 64 */ +EXTERN MacDrawable * TkMacGetHostToplevel _ANSI_ARGS_((TkWindow * winPtr)); +#endif /* MAC_TCL */ + +typedef struct TkIntPlatStubs { + int magic; + struct TkIntPlatStubHooks *hooks; + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void (*tkCreateXEventSource) _ANSI_ARGS_((void)); /* 0 */ + void (*tkFreeWindowId) _ANSI_ARGS_((TkDisplay * dispPtr, Window w)); /* 1 */ + void (*tkInitXId) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 2 */ + int (*tkpCmapStressed) _ANSI_ARGS_((Tk_Window tkwin, Colormap colormap)); /* 3 */ + void (*tkpSync) _ANSI_ARGS_((Display * display)); /* 4 */ + Window (*tkUnixContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */ + int (*tkUnixDoOneXEvent) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 6 */ + void (*tkUnixSetMenubar) _ANSI_ARGS_((Tk_Window tkwin, Tk_Window menubar)); /* 7 */ +#endif /* UNIX */ +#ifdef __WIN32__ + char * (*tkAlignImageData) _ANSI_ARGS_((XImage * image, int alignment, int bitOrder)); /* 0 */ + void *reserved1; + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 2 */ + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 4 */ + void (*tkpPrintWindowId) _ANSI_ARGS_((char * buf, Window window)); /* 5 */ + int (*tkpScanWindowId) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int * idPtr)); /* 6 */ + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 7 */ + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 8 */ + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 9 */ + void (*tkSetPixmapColormap) _ANSI_ARGS_((Pixmap pixmap, Colormap colormap)); /* 10 */ + void (*tkWinCancelMouseTimer) _ANSI_ARGS_((void)); /* 11 */ + void (*tkWinClipboardRender) _ANSI_ARGS_((TkDisplay * dispPtr, UINT format)); /* 12 */ + LRESULT (*tkWinEmbeddedEventProc) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); /* 13 */ + void (*tkWinFillRect) _ANSI_ARGS_((HDC dc, int x, int y, int width, int height, int pixel)); /* 14 */ + COLORREF (*tkWinGetBorderPixels) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int which)); /* 15 */ + HDC (*tkWinGetDrawableDC) _ANSI_ARGS_((Display * display, Drawable d, TkWinDCState* state)); /* 16 */ + int (*tkWinGetModifierState) _ANSI_ARGS_((void)); /* 17 */ + HPALETTE (*tkWinGetSystemPalette) _ANSI_ARGS_((void)); /* 18 */ + HWND (*tkWinGetWrapperWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 19 */ + int (*tkWinHandleMenuEvent) _ANSI_ARGS_((HWND * phwnd, UINT * pMessage, WPARAM * pwParam, LPARAM * plParam, LRESULT * plResult)); /* 20 */ + int (*tkWinIndexOfColor) _ANSI_ARGS_((XColor * colorPtr)); /* 21 */ + void (*tkWinReleaseDrawableDC) _ANSI_ARGS_((Drawable d, HDC hdc, TkWinDCState* state)); /* 22 */ + LRESULT (*tkWinResendEvent) _ANSI_ARGS_((WNDPROC wndproc, HWND hwnd, XEvent * eventPtr)); /* 23 */ + HPALETTE (*tkWinSelectPalette) _ANSI_ARGS_((HDC dc, Colormap colormap)); /* 24 */ + void (*tkWinSetMenu) _ANSI_ARGS_((Tk_Window tkwin, HMENU hMenu)); /* 25 */ + void (*tkWinSetWindowPos) _ANSI_ARGS_((HWND hwnd, HWND siblingHwnd, int pos)); /* 26 */ + void (*tkWinWmCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 27 */ + void (*tkWinXCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 28 */ + void (*tkWinXInit) _ANSI_ARGS_((HINSTANCE hInstance)); /* 29 */ + void (*tkWinSetForegroundWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 30 */ + void (*tkWinDialogDebug) _ANSI_ARGS_((int debug)); /* 31 */ + Tcl_Obj * (*tkWinGetMenuSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, char * dbName, char * className)); /* 32 */ + int (*tkWinGetPlatformId) _ANSI_ARGS_((void)); /* 33 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 0 */ + Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, char * source)); /* 1 */ + void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 2 */ + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ + void *reserved4; + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */ + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 6 */ + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 7 */ + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 8 */ + void *reserved9; + void (*tkAboutDlg) _ANSI_ARGS_((void)); /* 10 */ + void *reserved11; + void *reserved12; + Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 13 */ + int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 14 */ + void *reserved15; + void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 16 */ + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 17 */ + unsigned int (*tkMacButtonKeyState) _ANSI_ARGS_((void)); /* 18 */ + void (*tkMacClearMenubarActive) _ANSI_ARGS_((void)); /* 19 */ + int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord * eventPtr)); /* 20 */ + int (*tkMacDispatchMenuEvent) _ANSI_ARGS_((int menuID, int index)); /* 21 */ + void (*tkMacInstallCursor) _ANSI_ARGS_((int resizeOverride)); /* 22 */ + int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord * eventPtr, Window window)); /* 23 */ + void (*tkMacHandleTearoffMenu) _ANSI_ARGS_((void)); /* 24 */ + void *reserved25; + void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 26 */ + void (*tkMacDoHLEvent) _ANSI_ARGS_((EventRecord * theEvent)); /* 27 */ + void *reserved28; + Time (*tkMacGenerateTime) _ANSI_ARGS_((void)); /* 29 */ + GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 30 */ + TkWindow * (*tkMacGetScrollbarGrowWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 31 */ + Window (*tkMacGetXWindow) _ANSI_ARGS_((WindowRef macWinPtr)); /* 32 */ + int (*tkMacGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 33 */ + void (*tkMacHandleMenuSelect) _ANSI_ARGS_((long mResult, int optionKeyPressed)); /* 34 */ + int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 35 */ + void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 36 */ + void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 37 */ + void (*tkMacInvalidateWindow) _ANSI_ARGS_((MacDrawable * macWin, int flag)); /* 38 */ + int (*tkMacIsCharacterMissing) _ANSI_ARGS_((Tk_Font tkfont, unsigned int searchChar)); /* 39 */ + void (*tkMacMakeRealWindowExist) _ANSI_ARGS_((TkWindow * winPtr)); /* 40 */ + BitMapPtr (*tkMacMakeStippleMap) _ANSI_ARGS_((Drawable d1, Drawable d2)); /* 41 */ + void (*tkMacMenuClick) _ANSI_ARGS_((void)); /* 42 */ + void (*tkMacRegisterOffScreenWindow) _ANSI_ARGS_((Window window, GWorldPtr portPtr)); /* 43 */ + int (*tkMacResizable) _ANSI_ARGS_((TkWindow * winPtr)); /* 44 */ + void *reserved45; + void (*tkMacSetHelpMenuItemCount) _ANSI_ARGS_((void)); /* 46 */ + void (*tkMacSetScrollbarGrow) _ANSI_ARGS_((TkWindow * winPtr, int flag)); /* 47 */ + void (*tkMacSetUpClippingRgn) _ANSI_ARGS_((Drawable drawable)); /* 48 */ + void (*tkMacSetUpGraphicsPort) _ANSI_ARGS_((GC gc)); /* 49 */ + void (*tkMacUpdateClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 50 */ + void (*tkMacUnregisterMacWindow) _ANSI_ARGS_((GWorldPtr portPtr)); /* 51 */ + int (*tkMacUseMenuID) _ANSI_ARGS_((short macID)); /* 52 */ + RgnHandle (*tkMacVisableClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 53 */ + void (*tkMacWinBounds) _ANSI_ARGS_((TkWindow * winPtr, Rect * geometry)); /* 54 */ + void (*tkMacWindowOffset) _ANSI_ARGS_((WindowRef wRef, int * xOffset, int * yOffset)); /* 55 */ + void *reserved56; + int (*tkSetMacColor) _ANSI_ARGS_((unsigned long pixel, RGBColor * macColor)); /* 57 */ + void (*tkSetWMName) _ANSI_ARGS_((TkWindow * winPtr, Tk_Uid titleUid)); /* 58 */ + void (*tkSuspendClipboard) _ANSI_ARGS_((void)); /* 59 */ + void *reserved60; + int (*tkMacZoomToplevel) _ANSI_ARGS_((WindowPtr whichWindow, Point where, short zoomPart)); /* 61 */ + Tk_Window (*tk_TopCoordsToWindow) _ANSI_ARGS_((Tk_Window tkwin, int rootX, int rootY, int * newX, int * newY)); /* 62 */ + MacDrawable * (*tkMacContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 63 */ + MacDrawable * (*tkMacGetHostToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 64 */ +#endif /* MAC_TCL */ +} TkIntPlatStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkIntPlatStubs *tkIntPlatStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TkCreateXEventSource +#define TkCreateXEventSource \ + (tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */ +#endif +#ifndef TkFreeWindowId +#define TkFreeWindowId \ + (tkIntPlatStubsPtr->tkFreeWindowId) /* 1 */ +#endif +#ifndef TkInitXId +#define TkInitXId \ + (tkIntPlatStubsPtr->tkInitXId) /* 2 */ +#endif +#ifndef TkpCmapStressed +#define TkpCmapStressed \ + (tkIntPlatStubsPtr->tkpCmapStressed) /* 3 */ +#endif +#ifndef TkpSync +#define TkpSync \ + (tkIntPlatStubsPtr->tkpSync) /* 4 */ +#endif +#ifndef TkUnixContainerId +#define TkUnixContainerId \ + (tkIntPlatStubsPtr->tkUnixContainerId) /* 5 */ +#endif +#ifndef TkUnixDoOneXEvent +#define TkUnixDoOneXEvent \ + (tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 6 */ +#endif +#ifndef TkUnixSetMenubar +#define TkUnixSetMenubar \ + (tkIntPlatStubsPtr->tkUnixSetMenubar) /* 7 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TkAlignImageData +#define TkAlignImageData \ + (tkIntPlatStubsPtr->tkAlignImageData) /* 0 */ +#endif +/* Slot 1 is reserved */ +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */ +#endif +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntPlatStubsPtr->tkpGetMS) /* 3 */ +#endif +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 4 */ +#endif +#ifndef TkpPrintWindowId +#define TkpPrintWindowId \ + (tkIntPlatStubsPtr->tkpPrintWindowId) /* 5 */ +#endif +#ifndef TkpScanWindowId +#define TkpScanWindowId \ + (tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */ +#endif +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntPlatStubsPtr->tkpSetCapture) /* 7 */ +#endif +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntPlatStubsPtr->tkpSetCursor) /* 8 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 9 */ +#endif +#ifndef TkSetPixmapColormap +#define TkSetPixmapColormap \ + (tkIntPlatStubsPtr->tkSetPixmapColormap) /* 10 */ +#endif +#ifndef TkWinCancelMouseTimer +#define TkWinCancelMouseTimer \ + (tkIntPlatStubsPtr->tkWinCancelMouseTimer) /* 11 */ +#endif +#ifndef TkWinClipboardRender +#define TkWinClipboardRender \ + (tkIntPlatStubsPtr->tkWinClipboardRender) /* 12 */ +#endif +#ifndef TkWinEmbeddedEventProc +#define TkWinEmbeddedEventProc \ + (tkIntPlatStubsPtr->tkWinEmbeddedEventProc) /* 13 */ +#endif +#ifndef TkWinFillRect +#define TkWinFillRect \ + (tkIntPlatStubsPtr->tkWinFillRect) /* 14 */ +#endif +#ifndef TkWinGetBorderPixels +#define TkWinGetBorderPixels \ + (tkIntPlatStubsPtr->tkWinGetBorderPixels) /* 15 */ +#endif +#ifndef TkWinGetDrawableDC +#define TkWinGetDrawableDC \ + (tkIntPlatStubsPtr->tkWinGetDrawableDC) /* 16 */ +#endif +#ifndef TkWinGetModifierState +#define TkWinGetModifierState \ + (tkIntPlatStubsPtr->tkWinGetModifierState) /* 17 */ +#endif +#ifndef TkWinGetSystemPalette +#define TkWinGetSystemPalette \ + (tkIntPlatStubsPtr->tkWinGetSystemPalette) /* 18 */ +#endif +#ifndef TkWinGetWrapperWindow +#define TkWinGetWrapperWindow \ + (tkIntPlatStubsPtr->tkWinGetWrapperWindow) /* 19 */ +#endif +#ifndef TkWinHandleMenuEvent +#define TkWinHandleMenuEvent \ + (tkIntPlatStubsPtr->tkWinHandleMenuEvent) /* 20 */ +#endif +#ifndef TkWinIndexOfColor +#define TkWinIndexOfColor \ + (tkIntPlatStubsPtr->tkWinIndexOfColor) /* 21 */ +#endif +#ifndef TkWinReleaseDrawableDC +#define TkWinReleaseDrawableDC \ + (tkIntPlatStubsPtr->tkWinReleaseDrawableDC) /* 22 */ +#endif +#ifndef TkWinResendEvent +#define TkWinResendEvent \ + (tkIntPlatStubsPtr->tkWinResendEvent) /* 23 */ +#endif +#ifndef TkWinSelectPalette +#define TkWinSelectPalette \ + (tkIntPlatStubsPtr->tkWinSelectPalette) /* 24 */ +#endif +#ifndef TkWinSetMenu +#define TkWinSetMenu \ + (tkIntPlatStubsPtr->tkWinSetMenu) /* 25 */ +#endif +#ifndef TkWinSetWindowPos +#define TkWinSetWindowPos \ + (tkIntPlatStubsPtr->tkWinSetWindowPos) /* 26 */ +#endif +#ifndef TkWinWmCleanup +#define TkWinWmCleanup \ + (tkIntPlatStubsPtr->tkWinWmCleanup) /* 27 */ +#endif +#ifndef TkWinXCleanup +#define TkWinXCleanup \ + (tkIntPlatStubsPtr->tkWinXCleanup) /* 28 */ +#endif +#ifndef TkWinXInit +#define TkWinXInit \ + (tkIntPlatStubsPtr->tkWinXInit) /* 29 */ +#endif +#ifndef TkWinSetForegroundWindow +#define TkWinSetForegroundWindow \ + (tkIntPlatStubsPtr->tkWinSetForegroundWindow) /* 30 */ +#endif +#ifndef TkWinDialogDebug +#define TkWinDialogDebug \ + (tkIntPlatStubsPtr->tkWinDialogDebug) /* 31 */ +#endif +#ifndef TkWinGetMenuSystemDefault +#define TkWinGetMenuSystemDefault \ + (tkIntPlatStubsPtr->tkWinGetMenuSystemDefault) /* 32 */ +#endif +#ifndef TkWinGetPlatformId +#define TkWinGetPlatformId \ + (tkIntPlatStubsPtr->tkWinGetPlatformId) /* 33 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */ +#endif +#ifndef TkpCreateNativeBitmap +#define TkpCreateNativeBitmap \ + (tkIntPlatStubsPtr->tkpCreateNativeBitmap) /* 1 */ +#endif +#ifndef TkpDefineNativeBitmaps +#define TkpDefineNativeBitmaps \ + (tkIntPlatStubsPtr->tkpDefineNativeBitmaps) /* 2 */ +#endif +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntPlatStubsPtr->tkpGetMS) /* 3 */ +#endif +/* Slot 4 is reserved */ +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 5 */ +#endif +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntPlatStubsPtr->tkpSetCapture) /* 6 */ +#endif +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntPlatStubsPtr->tkpSetCursor) /* 7 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 8 */ +#endif +/* Slot 9 is reserved */ +#ifndef TkAboutDlg +#define TkAboutDlg \ + (tkIntPlatStubsPtr->tkAboutDlg) /* 10 */ +#endif +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ +#ifndef TkGetTransientMaster +#define TkGetTransientMaster \ + (tkIntPlatStubsPtr->tkGetTransientMaster) /* 13 */ +#endif +#ifndef TkGenerateButtonEvent +#define TkGenerateButtonEvent \ + (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TkGenWMDestroyEvent +#define TkGenWMDestroyEvent \ + (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 16 */ +#endif +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkIntPlatStubsPtr->tkGenWMConfigureEvent) /* 17 */ +#endif +#ifndef TkMacButtonKeyState +#define TkMacButtonKeyState \ + (tkIntPlatStubsPtr->tkMacButtonKeyState) /* 18 */ +#endif +#ifndef TkMacClearMenubarActive +#define TkMacClearMenubarActive \ + (tkIntPlatStubsPtr->tkMacClearMenubarActive) /* 19 */ +#endif +#ifndef TkMacConvertEvent +#define TkMacConvertEvent \ + (tkIntPlatStubsPtr->tkMacConvertEvent) /* 20 */ +#endif +#ifndef TkMacDispatchMenuEvent +#define TkMacDispatchMenuEvent \ + (tkIntPlatStubsPtr->tkMacDispatchMenuEvent) /* 21 */ +#endif +#ifndef TkMacInstallCursor +#define TkMacInstallCursor \ + (tkIntPlatStubsPtr->tkMacInstallCursor) /* 22 */ +#endif +#ifndef TkMacConvertTkEvent +#define TkMacConvertTkEvent \ + (tkIntPlatStubsPtr->tkMacConvertTkEvent) /* 23 */ +#endif +#ifndef TkMacHandleTearoffMenu +#define TkMacHandleTearoffMenu \ + (tkIntPlatStubsPtr->tkMacHandleTearoffMenu) /* 24 */ +#endif +/* Slot 25 is reserved */ +#ifndef TkMacInvalClipRgns +#define TkMacInvalClipRgns \ + (tkIntPlatStubsPtr->tkMacInvalClipRgns) /* 26 */ +#endif +#ifndef TkMacDoHLEvent +#define TkMacDoHLEvent \ + (tkIntPlatStubsPtr->tkMacDoHLEvent) /* 27 */ +#endif +/* Slot 28 is reserved */ +#ifndef TkMacGenerateTime +#define TkMacGenerateTime \ + (tkIntPlatStubsPtr->tkMacGenerateTime) /* 29 */ +#endif +#ifndef TkMacGetDrawablePort +#define TkMacGetDrawablePort \ + (tkIntPlatStubsPtr->tkMacGetDrawablePort) /* 30 */ +#endif +#ifndef TkMacGetScrollbarGrowWindow +#define TkMacGetScrollbarGrowWindow \ + (tkIntPlatStubsPtr->tkMacGetScrollbarGrowWindow) /* 31 */ +#endif +#ifndef TkMacGetXWindow +#define TkMacGetXWindow \ + (tkIntPlatStubsPtr->tkMacGetXWindow) /* 32 */ +#endif +#ifndef TkMacGrowToplevel +#define TkMacGrowToplevel \ + (tkIntPlatStubsPtr->tkMacGrowToplevel) /* 33 */ +#endif +#ifndef TkMacHandleMenuSelect +#define TkMacHandleMenuSelect \ + (tkIntPlatStubsPtr->tkMacHandleMenuSelect) /* 34 */ +#endif +#ifndef TkMacHaveAppearance +#define TkMacHaveAppearance \ + (tkIntPlatStubsPtr->tkMacHaveAppearance) /* 35 */ +#endif +#ifndef TkMacInitAppleEvents +#define TkMacInitAppleEvents \ + (tkIntPlatStubsPtr->tkMacInitAppleEvents) /* 36 */ +#endif +#ifndef TkMacInitMenus +#define TkMacInitMenus \ + (tkIntPlatStubsPtr->tkMacInitMenus) /* 37 */ +#endif +#ifndef TkMacInvalidateWindow +#define TkMacInvalidateWindow \ + (tkIntPlatStubsPtr->tkMacInvalidateWindow) /* 38 */ +#endif +#ifndef TkMacIsCharacterMissing +#define TkMacIsCharacterMissing \ + (tkIntPlatStubsPtr->tkMacIsCharacterMissing) /* 39 */ +#endif +#ifndef TkMacMakeRealWindowExist +#define TkMacMakeRealWindowExist \ + (tkIntPlatStubsPtr->tkMacMakeRealWindowExist) /* 40 */ +#endif +#ifndef TkMacMakeStippleMap +#define TkMacMakeStippleMap \ + (tkIntPlatStubsPtr->tkMacMakeStippleMap) /* 41 */ +#endif +#ifndef TkMacMenuClick +#define TkMacMenuClick \ + (tkIntPlatStubsPtr->tkMacMenuClick) /* 42 */ +#endif +#ifndef TkMacRegisterOffScreenWindow +#define TkMacRegisterOffScreenWindow \ + (tkIntPlatStubsPtr->tkMacRegisterOffScreenWindow) /* 43 */ +#endif +#ifndef TkMacResizable +#define TkMacResizable \ + (tkIntPlatStubsPtr->tkMacResizable) /* 44 */ +#endif +/* Slot 45 is reserved */ +#ifndef TkMacSetHelpMenuItemCount +#define TkMacSetHelpMenuItemCount \ + (tkIntPlatStubsPtr->tkMacSetHelpMenuItemCount) /* 46 */ +#endif +#ifndef TkMacSetScrollbarGrow +#define TkMacSetScrollbarGrow \ + (tkIntPlatStubsPtr->tkMacSetScrollbarGrow) /* 47 */ +#endif +#ifndef TkMacSetUpClippingRgn +#define TkMacSetUpClippingRgn \ + (tkIntPlatStubsPtr->tkMacSetUpClippingRgn) /* 48 */ +#endif +#ifndef TkMacSetUpGraphicsPort +#define TkMacSetUpGraphicsPort \ + (tkIntPlatStubsPtr->tkMacSetUpGraphicsPort) /* 49 */ +#endif +#ifndef TkMacUpdateClipRgn +#define TkMacUpdateClipRgn \ + (tkIntPlatStubsPtr->tkMacUpdateClipRgn) /* 50 */ +#endif +#ifndef TkMacUnregisterMacWindow +#define TkMacUnregisterMacWindow \ + (tkIntPlatStubsPtr->tkMacUnregisterMacWindow) /* 51 */ +#endif +#ifndef TkMacUseMenuID +#define TkMacUseMenuID \ + (tkIntPlatStubsPtr->tkMacUseMenuID) /* 52 */ +#endif +#ifndef TkMacVisableClipRgn +#define TkMacVisableClipRgn \ + (tkIntPlatStubsPtr->tkMacVisableClipRgn) /* 53 */ +#endif +#ifndef TkMacWinBounds +#define TkMacWinBounds \ + (tkIntPlatStubsPtr->tkMacWinBounds) /* 54 */ +#endif +#ifndef TkMacWindowOffset +#define TkMacWindowOffset \ + (tkIntPlatStubsPtr->tkMacWindowOffset) /* 55 */ +#endif +/* Slot 56 is reserved */ +#ifndef TkSetMacColor +#define TkSetMacColor \ + (tkIntPlatStubsPtr->tkSetMacColor) /* 57 */ +#endif +#ifndef TkSetWMName +#define TkSetWMName \ + (tkIntPlatStubsPtr->tkSetWMName) /* 58 */ +#endif +#ifndef TkSuspendClipboard +#define TkSuspendClipboard \ + (tkIntPlatStubsPtr->tkSuspendClipboard) /* 59 */ +#endif +/* Slot 60 is reserved */ +#ifndef TkMacZoomToplevel +#define TkMacZoomToplevel \ + (tkIntPlatStubsPtr->tkMacZoomToplevel) /* 61 */ +#endif +#ifndef Tk_TopCoordsToWindow +#define Tk_TopCoordsToWindow \ + (tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 62 */ +#endif +#ifndef TkMacContainerId +#define TkMacContainerId \ + (tkIntPlatStubsPtr->tkMacContainerId) /* 63 */ +#endif +#ifndef TkMacGetHostToplevel +#define TkMacGetHostToplevel \ + (tkIntPlatStubsPtr->tkMacGetHostToplevel) /* 64 */ +#endif +#endif /* MAC_TCL */ + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINTPLATDECLS */ diff --git a/Utilities/TclTk/internals/tk8.2/tkPlatDecls.h b/Utilities/TclTk/internals/tk8.2/tkPlatDecls.h new file mode 100644 index 0000000..0e5167a --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkPlatDecls.h @@ -0,0 +1,208 @@ +/* + * tkPlatDecls.h -- + * + * Declarations of functions in the platform-specific public Tcl API. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkPlatDecls.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKPLATDECLS +#define _TKPLATDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tk.decls script. + */ + + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +#ifdef __WIN32__ +/* 0 */ +EXTERN Window Tk_AttachHWND _ANSI_ARGS_((Tk_Window tkwin, + HWND hwnd)); +/* 1 */ +EXTERN HINSTANCE Tk_GetHINSTANCE _ANSI_ARGS_((void)); +/* 2 */ +EXTERN HWND Tk_GetHWND _ANSI_ARGS_((Window window)); +/* 3 */ +EXTERN Tk_Window Tk_HWNDToWindow _ANSI_ARGS_((HWND hwnd)); +/* 4 */ +EXTERN void Tk_PointerEvent _ANSI_ARGS_((HWND hwnd, int x, int y)); +/* 5 */ +EXTERN int Tk_TranslateWinEvent _ANSI_ARGS_((HWND hwnd, + UINT message, WPARAM wParam, LPARAM lParam, + LRESULT * result)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN void Tk_MacSetEmbedHandler _ANSI_ARGS_(( + Tk_MacEmbedRegisterWinProc * registerWinProcPtr, + Tk_MacEmbedGetGrafPortProc * getPortProcPtr, + Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, + Tk_MacEmbedGetClipProc * getClipProc, + Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); +/* 1 */ +EXTERN void Tk_MacTurnOffMenus _ANSI_ARGS_((void)); +/* 2 */ +EXTERN void Tk_MacTkOwnsCursor _ANSI_ARGS_((int tkOwnsIt)); +/* 3 */ +EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp * interp)); +/* 4 */ +EXTERN void TkMacInitAppleEvents _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 5 */ +EXTERN int TkMacConvertEvent _ANSI_ARGS_(( + EventRecord * eventPtr)); +/* 6 */ +EXTERN int TkMacConvertTkEvent _ANSI_ARGS_(( + EventRecord * eventPtr, Window window)); +/* 7 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +/* 8 */ +EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr)); +/* 9 */ +EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void)); +/* 10 */ +EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable)); +#endif /* MAC_TCL */ + +typedef struct TkPlatStubs { + int magic; + struct TkPlatStubHooks *hooks; + +#ifdef __WIN32__ + Window (*tk_AttachHWND) _ANSI_ARGS_((Tk_Window tkwin, HWND hwnd)); /* 0 */ + HINSTANCE (*tk_GetHINSTANCE) _ANSI_ARGS_((void)); /* 1 */ + HWND (*tk_GetHWND) _ANSI_ARGS_((Window window)); /* 2 */ + Tk_Window (*tk_HWNDToWindow) _ANSI_ARGS_((HWND hwnd)); /* 3 */ + void (*tk_PointerEvent) _ANSI_ARGS_((HWND hwnd, int x, int y)); /* 4 */ + int (*tk_TranslateWinEvent) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT * result)); /* 5 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tk_MacSetEmbedHandler) _ANSI_ARGS_((Tk_MacEmbedRegisterWinProc * registerWinProcPtr, Tk_MacEmbedGetGrafPortProc * getPortProcPtr, Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, Tk_MacEmbedGetClipProc * getClipProc, Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); /* 0 */ + void (*tk_MacTurnOffMenus) _ANSI_ARGS_((void)); /* 1 */ + void (*tk_MacTkOwnsCursor) _ANSI_ARGS_((int tkOwnsIt)); /* 2 */ + void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 3 */ + void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 4 */ + int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord * eventPtr)); /* 5 */ + int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord * eventPtr, Window window)); /* 6 */ + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 7 */ + void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 8 */ + int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 9 */ + GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 10 */ +#endif /* MAC_TCL */ +} TkPlatStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkPlatStubs *tkPlatStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifdef __WIN32__ +#ifndef Tk_AttachHWND +#define Tk_AttachHWND \ + (tkPlatStubsPtr->tk_AttachHWND) /* 0 */ +#endif +#ifndef Tk_GetHINSTANCE +#define Tk_GetHINSTANCE \ + (tkPlatStubsPtr->tk_GetHINSTANCE) /* 1 */ +#endif +#ifndef Tk_GetHWND +#define Tk_GetHWND \ + (tkPlatStubsPtr->tk_GetHWND) /* 2 */ +#endif +#ifndef Tk_HWNDToWindow +#define Tk_HWNDToWindow \ + (tkPlatStubsPtr->tk_HWNDToWindow) /* 3 */ +#endif +#ifndef Tk_PointerEvent +#define Tk_PointerEvent \ + (tkPlatStubsPtr->tk_PointerEvent) /* 4 */ +#endif +#ifndef Tk_TranslateWinEvent +#define Tk_TranslateWinEvent \ + (tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef Tk_MacSetEmbedHandler +#define Tk_MacSetEmbedHandler \ + (tkPlatStubsPtr->tk_MacSetEmbedHandler) /* 0 */ +#endif +#ifndef Tk_MacTurnOffMenus +#define Tk_MacTurnOffMenus \ + (tkPlatStubsPtr->tk_MacTurnOffMenus) /* 1 */ +#endif +#ifndef Tk_MacTkOwnsCursor +#define Tk_MacTkOwnsCursor \ + (tkPlatStubsPtr->tk_MacTkOwnsCursor) /* 2 */ +#endif +#ifndef TkMacInitMenus +#define TkMacInitMenus \ + (tkPlatStubsPtr->tkMacInitMenus) /* 3 */ +#endif +#ifndef TkMacInitAppleEvents +#define TkMacInitAppleEvents \ + (tkPlatStubsPtr->tkMacInitAppleEvents) /* 4 */ +#endif +#ifndef TkMacConvertEvent +#define TkMacConvertEvent \ + (tkPlatStubsPtr->tkMacConvertEvent) /* 5 */ +#endif +#ifndef TkMacConvertTkEvent +#define TkMacConvertTkEvent \ + (tkPlatStubsPtr->tkMacConvertTkEvent) /* 6 */ +#endif +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkPlatStubsPtr->tkGenWMConfigureEvent) /* 7 */ +#endif +#ifndef TkMacInvalClipRgns +#define TkMacInvalClipRgns \ + (tkPlatStubsPtr->tkMacInvalClipRgns) /* 8 */ +#endif +#ifndef TkMacHaveAppearance +#define TkMacHaveAppearance \ + (tkPlatStubsPtr->tkMacHaveAppearance) /* 9 */ +#endif +#ifndef TkMacGetDrawablePort +#define TkMacGetDrawablePort \ + (tkPlatStubsPtr->tkMacGetDrawablePort) /* 10 */ +#endif +#endif /* MAC_TCL */ + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKPLATDECLS */ diff --git a/Utilities/TclTk/internals/tk8.2/tkPort.h b/Utilities/TclTk/internals/tk8.2/tkPort.h new file mode 100644 index 0000000..21509a8 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkPort.h @@ -0,0 +1,36 @@ +/* + * tkPort.h -- + * + * This header file handles porting issues that occur because of + * differences between systems. It reads in platform specific + * portability files. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkPort.h,v 1.1.22.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKPORT +#define _TKPORT + +#ifndef _TK +#include "tk.h" +#endif +#ifndef _TCL +#include "tcl.h" +#endif + +#if defined(__WIN32__) || defined(_WIN32) +# include "tkWinPort.h" +#else +# if defined(MAC_TCL) +# include "tkMacPort.h" +# else +# include "tkUnixPort.h" +# endif +#endif + +#endif /* _TKPORT */ diff --git a/Utilities/TclTk/internals/tk8.2/tkWin.h b/Utilities/TclTk/internals/tk8.2/tkWin.h new file mode 100644 index 0000000..34e56e8 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkWin.h @@ -0,0 +1,55 @@ +/* + * tkWin.h -- + * + * Declarations of public types and interfaces that are only + * available under Windows. + * + * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWin.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKWIN +#define _TKWIN + +#ifndef _TK +#include +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#ifdef BUILD_tk +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * The following messages are use to communicate between a Tk toplevel + * and its container window. + */ + +#define TK_CLAIMFOCUS (WM_USER) +#define TK_GEOMETRYREQ (WM_USER+1) +#define TK_ATTACHWINDOW (WM_USER+2) +#define TK_DETACHWINDOW (WM_USER+3) + + +/* + *-------------------------------------------------------------- + * + * Exported procedures defined for the Windows platform only. + * + *-------------------------------------------------------------- + */ + +#include "tkPlatDecls.h" + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKWIN */ diff --git a/Utilities/TclTk/internals/tk8.2/tkWinInt.h b/Utilities/TclTk/internals/tk8.2/tkWinInt.h new file mode 100644 index 0000000..d970942 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkWinInt.h @@ -0,0 +1,160 @@ +/* + * tkWinInt.h -- + * + * This file contains declarations that are shared among the + * Windows-specific parts of Tk, but aren't used by the rest of + * Tk. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinInt.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKWININT +#define _TKWININT + +#ifndef _TKINT +#include "tkInt.h" +#endif + +/* + * Include platform specific public interfaces. + */ + +#ifndef _TKWIN +#include "tkWin.h" +#endif + +#ifndef _TKPORT +#include "tkPort.h" +#endif + + +/* + * Define constants missing from older Win32 SDK header files. + */ + +#ifndef WS_EX_TOOLWINDOW +#define WS_EX_TOOLWINDOW 0x00000080L +#endif + +typedef struct TkFontAttributes TkFontAttributes; + +/* + * The TkWinDCState is used to save the state of a device context + * so that it can be restored later. + */ + +typedef struct TkWinDCState { + HPALETTE palette; +} TkWinDCState; + +/* + * The TkWinDrawable is the internal implementation of an X Drawable (either + * a Window or a Pixmap). The following constants define the valid Drawable + * types. + */ + +#define TWD_BITMAP 1 +#define TWD_WINDOW 2 +#define TWD_WINDC 3 + +typedef struct { + int type; + HWND handle; + TkWindow *winPtr; +} TkWinWindow; + +typedef struct { + int type; + HBITMAP handle; + Colormap colormap; + int depth; +} TkWinBitmap; + +typedef struct { + int type; + HDC hdc; +}TkWinDC; + +typedef union { + int type; + TkWinWindow window; + TkWinBitmap bitmap; + TkWinDC winDC; +} TkWinDrawable; + +/* + * The following macros are used to retrieve internal values from a Drawable. + */ + +#define TkWinGetHWND(w) (((TkWinDrawable *) w)->window.handle) +#define TkWinGetWinPtr(w) (((TkWinDrawable*)w)->window.winPtr) +#define TkWinGetHBITMAP(w) (((TkWinDrawable*)w)->bitmap.handle) +#define TkWinGetColormap(w) (((TkWinDrawable*)w)->bitmap.colormap) +#define TkWinGetHDC(w) (((TkWinDrawable *) w)->winDC.hdc) + +/* + * The following structure is used to encapsulate palette information. + */ + +typedef struct { + HPALETTE palette; /* Palette handle used when drawing. */ + UINT size; /* Number of entries in the palette. */ + int stale; /* 1 if palette needs to be realized, + * otherwise 0. If the palette is stale, + * then an idle handler is scheduled to + * realize the palette. */ + Tcl_HashTable refCounts; /* Hash table of palette entry reference counts + * indexed by pixel value. */ +} TkWinColormap; + +/* + * The following macro retrieves the Win32 palette from a colormap. + */ + +#define TkWinGetPalette(colormap) (((TkWinColormap *) colormap)->palette) + +/* + * The following macros define the class names for Tk Window types. + */ + +#define TK_WIN_TOPLEVEL_CLASS_NAME "TkTopLevel" +#define TK_WIN_CHILD_CLASS_NAME "TkChild" + +/* + * The following variable indicates whether we are restricted to Win32s + * GDI calls. + */ + +extern int tkpIsWin32s; + +/* + * The following variable is a translation table between X gc functions and + * Win32 raster op modes. + */ + +extern int tkpWinRopModes[]; + +/* + * The following defines are used with TkWinGetBorderPixels to get the + * extra 2 border colors from a Tk_3DBorder. + */ + +#define TK_3D_LIGHT2 TK_3D_DARK_GC+1 +#define TK_3D_DARK2 TK_3D_DARK_GC+2 + +/* + * Internal procedures used by more than one source file. + */ + +#include "tkIntPlatDecls.h" + +extern LRESULT CALLBACK TkWinChildProc _ANSI_ARGS_((HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam)); + +#endif /* _TKWININT */ + diff --git a/Utilities/TclTk/internals/tk8.2/tkWinPort.h b/Utilities/TclTk/internals/tk8.2/tkWinPort.h new file mode 100644 index 0000000..c9114cf --- /dev/null +++ b/Utilities/TclTk/internals/tk8.2/tkWinPort.h @@ -0,0 +1,127 @@ +/* + * tkWinPort.h -- + * + * This header file handles porting issues that occur because of + * differences between Windows and Unix. It should be the only + * file that contains #ifdefs to handle different flavors of OS. + * + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinPort.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _WINPORT +#define _WINPORT + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Need to block out this include for building extensions with MetroWerks + * compiler for Win32. + */ + +#ifndef __MWERKS__ +#include +#endif + +#include +#include + +#ifdef _MSC_VER +# define hypot _hypot +#endif /* _MSC_VER */ + +#define strncasecmp strnicmp +#define strcasecmp stricmp + +#define NBBY 8 + +#define OPEN_MAX 32 + +/* + * The following define causes Tk to use its internal keysym hash table + */ + +#define REDO_KEYSYM_LOOKUP + +/* + * The following macro checks to see whether there is buffered + * input data available for a stdio FILE. + */ + +#ifdef _MSC_VER +# define TK_READ_DATA_PENDING(f) ((f)->_cnt > 0) +#else /* _MSC_VER */ +# define TK_READ_DATA_PENDING(f) ((f)->level > 0) +#endif /* _MSC_VER */ + +/* + * The following stubs implement various calls that don't do anything + * under Windows. + */ + +#define TkFreeWindowId(dispPtr,w) +#define TkInitXId(dispPtr) +#define TkpCmapStressed(tkwin,colormap) (0) +#define XFlush(display) +#define XGrabServer(display) +#define XUngrabServer(display) +#define TkpSync(display) + +/* + * The following functions are implemented as macros under Windows. + */ + +#define XFree(data) {if ((data) != NULL) ckfree((char *) (data));} +#define XNoOp(display) {display->request++;} +#define XSynchronize(display, bool) {display->request++;} +#define XSync(display, bool) {display->request++;} +#define XVisualIDFromVisual(visual) (visual->visualid) + +/* + * The following Tk functions are implemented as macros under Windows. + */ + +#define TkpGetPixel(p) (((((p)->red >> 8) & 0xff) \ + | ((p)->green & 0xff00) | (((p)->blue << 8) & 0xff0000)) | 0x20000000) + +/* + * These calls implement native bitmaps which are not currently + * supported under Windows. The macros eliminate the calls. + */ + +#define TkpDefineNativeBitmaps() +#define TkpCreateNativeBitmap(display, source) None +#define TkpGetNativeAppBitmap(display, name, w, h) None + +/* + * Define timezone for gettimeofday. + */ + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +#ifndef _TCLINT +#include +#endif + +#endif /* _WINPORT */ diff --git a/Utilities/TclTk/internals/tk8.3/CMakeLists.txt b/Utilities/TclTk/internals/tk8.3/CMakeLists.txt new file mode 100644 index 0000000..b30926f --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/CMakeLists.txt @@ -0,0 +1,5 @@ +IF(TK_INTERNAL_PATH) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/TclTk/internals/tk8.3 "\\.h$") + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF(TK_INTERNAL_PATH) diff --git a/Utilities/TclTk/internals/tk8.3/default.h b/Utilities/TclTk/internals/tk8.3/default.h new file mode 100644 index 0000000..115a371 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/default.h @@ -0,0 +1,29 @@ +/* + * default.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: default.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _DEFAULT +#define _DEFAULT + +#if defined(__WIN32__) || defined(_WIN32) +# include "tkWinDefault.h" +#else +# if defined(MAC_TCL) +# include "tkMacDefault.h" +# else +# include "tkUnixDefault.h" +# endif +#endif + +#endif /* _DEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.3/tclInt.h b/Utilities/TclTk/internals/tk8.3/tclInt.h new file mode 100644 index 0000000..fb52126 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tclInt.h @@ -0,0 +1,2188 @@ +/* + * tclInt.h -- + * + * Declarations of things used internally by the Tcl interpreter. + * + * Copyright (c) 1987-1993 The Regents of the University of California. + * Copyright (c) 1993-1997 Lucent Technologies. + * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclInt.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TCLINT +#define _TCLINT + +/* + * Common include files needed by most of the Tcl source files are + * included here, so that system-dependent personalizations for the + * include files only have to be made in once place. This results + * in a few extra includes, but greater modularity. The order of + * the three groups of #includes is important. For example, stdio.h + * is needed by tcl.h, and the _ANSI_ARGS_ declaration in tcl.h is + * needed by stdlib.h in some configurations. + */ + +#include + +#ifndef _TCL +#include "tcl.h" +#endif + +#include +#ifdef NO_LIMITS_H +# include "../compat/limits.h" +#else +# include +#endif +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include +#endif +#ifdef NO_STRING_H +#include "../compat/string.h" +#else +#include +#endif + +#undef TCL_STORAGE_CLASS +#ifdef BUILD_tcl +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# ifdef USE_TCL_STUBS +# define TCL_STORAGE_CLASS +# else +# define TCL_STORAGE_CLASS DLLIMPORT +# endif +#endif + +/* + * The following procedures allow namespaces to be customized to + * support special name resolution rules for commands/variables. + * + */ + +struct Tcl_ResolvedVarInfo; + +typedef Tcl_Var (Tcl_ResolveRuntimeVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, struct Tcl_ResolvedVarInfo *vinfoPtr)); + +typedef void (Tcl_ResolveVarDeleteProc) _ANSI_ARGS_(( + struct Tcl_ResolvedVarInfo *vinfoPtr)); + +/* + * The following structure encapsulates the routines needed to resolve a + * variable reference at runtime. Any variable specific state will typically + * be appended to this structure. + */ + + +typedef struct Tcl_ResolvedVarInfo { + Tcl_ResolveRuntimeVarProc *fetchProc; + Tcl_ResolveVarDeleteProc *deleteProc; +} Tcl_ResolvedVarInfo; + + + +typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, char* name, int length, + Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr)); + +typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, char* name, Tcl_Namespace *context, + int flags, Tcl_Var *rPtr)); + +typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((Tcl_Interp* interp, + char* name, Tcl_Namespace *context, int flags, + Tcl_Command *rPtr)); + +typedef struct Tcl_ResolverInfo { + Tcl_ResolveCmdProc *cmdResProc; /* Procedure handling command name + * resolution. */ + Tcl_ResolveVarProc *varResProc; /* Procedure handling variable name + * resolution for variables that + * can only be handled at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* Procedure handling variable name + * resolution at compile time. */ +} Tcl_ResolverInfo; + +/* + *---------------------------------------------------------------- + * Data structures related to namespaces. + *---------------------------------------------------------------- + */ + +/* + * The structure below defines a namespace. + * Note: the first five fields must match exactly the fields in a + * Tcl_Namespace structure (see tcl.h). If you change one, be sure to + * change the other. + */ + +typedef struct Namespace { + char *name; /* The namespace's simple (unqualified) + * name. This contains no ::'s. The name of + * the global namespace is "" although "::" + * is an synonym. */ + char *fullName; /* The namespace's fully qualified name. + * This starts with ::. */ + ClientData clientData; /* An arbitrary value associated with this + * namespace. */ + Tcl_NamespaceDeleteProc *deleteProc; + /* Procedure invoked when deleting the + * namespace to, e.g., free clientData. */ + struct Namespace *parentPtr; /* Points to the namespace that contains + * this one. NULL if this is the global + * namespace. */ + Tcl_HashTable childTable; /* Contains any child namespaces. Indexed + * by strings; values have type + * (Namespace *). */ + long nsId; /* Unique id for the namespace. */ + Tcl_Interp *interp; /* The interpreter containing this + * namespace. */ + int flags; /* OR-ed combination of the namespace + * status flags NS_DYING and NS_DEAD + * listed below. */ + int activationCount; /* Number of "activations" or active call + * frames for this namespace that are on + * the Tcl call stack. The namespace won't + * be freed until activationCount becomes + * zero. */ + int refCount; /* Count of references by namespaceName * + * objects. The namespace can't be freed + * until refCount becomes zero. */ + Tcl_HashTable cmdTable; /* Contains all the commands currently + * registered in the namespace. Indexed by + * strings; values have type (Command *). + * Commands imported by Tcl_Import have + * Command structures that point (via an + * ImportedCmdRef structure) to the + * Command structure in the source + * namespace's command table. */ + Tcl_HashTable varTable; /* Contains all the (global) variables + * currently in this namespace. Indexed + * by strings; values have type (Var *). */ + char **exportArrayPtr; /* Points to an array of string patterns + * specifying which commands are exported. + * A pattern may include "string match" + * style wildcard characters to specify + * multiple commands; however, no namespace + * qualifiers are allowed. NULL if no + * export patterns are registered. */ + int numExportPatterns; /* Number of export patterns currently + * registered using "namespace export". */ + int maxExportPatterns; /* Mumber of export patterns for which + * space is currently allocated. */ + int cmdRefEpoch; /* Incremented if a newly added command + * shadows a command for which this + * namespace has already cached a Command * + * pointer; this causes all its cached + * Command* pointers to be invalidated. */ + int resolverEpoch; /* Incremented whenever the name resolution + * rules change for this namespace; this + * invalidates all byte codes compiled in + * the namespace, causing the code to be + * recompiled under the new rules. */ + Tcl_ResolveCmdProc *cmdResProc; + /* If non-null, this procedure overrides + * the usual command resolution mechanism + * in Tcl. This procedure is invoked + * within Tcl_FindCommand to resolve all + * command references within the namespace. */ + Tcl_ResolveVarProc *varResProc; + /* If non-null, this procedure overrides + * the usual variable resolution mechanism + * in Tcl. This procedure is invoked + * within Tcl_FindNamespaceVar to resolve all + * variable references within the namespace + * at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* If non-null, this procedure overrides + * the usual variable resolution mechanism + * in Tcl. This procedure is invoked + * within LookupCompiledLocal to resolve + * variable references within the namespace + * at compile time. */ +} Namespace; + +/* + * Flags used to represent the status of a namespace: + * + * NS_DYING - 1 means Tcl_DeleteNamespace has been called to delete the + * namespace but there are still active call frames on the Tcl + * stack that refer to the namespace. When the last call frame + * referring to it has been popped, it's variables and command + * will be destroyed and it will be marked "dead" (NS_DEAD). + * The namespace can no longer be looked up by name. + * NS_DEAD - 1 means Tcl_DeleteNamespace has been called to delete the + * namespace and no call frames still refer to it. Its + * variables and command have already been destroyed. This bit + * allows the namespace resolution code to recognize that the + * namespace is "deleted". When the last namespaceName object + * in any byte code code unit that refers to the namespace has + * been freed (i.e., when the namespace's refCount is 0), the + * namespace's storage will be freed. + */ + +#define NS_DYING 0x01 +#define NS_DEAD 0x02 + +/* + * Flag passed to TclGetNamespaceForQualName to have it create all namespace + * components of a namespace-qualified name that cannot be found. The new + * namespaces are created within their specified parent. Note that this + * flag's value must not conflict with the values of the flags + * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, and FIND_ONLY_NS (defined in + * tclNamesp.c). + */ + +#define CREATE_NS_IF_UNKNOWN 0x800 + +/* + *---------------------------------------------------------------- + * Data structures related to variables. These are used primarily + * in tclVar.c + *---------------------------------------------------------------- + */ + +/* + * The following structure defines a variable trace, which is used to + * invoke a specific C procedure whenever certain operations are performed + * on a variable. + */ + +typedef struct VarTrace { + Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given + * by flags are performed on variable. */ + ClientData clientData; /* Argument to pass to proc. */ + int flags; /* What events the trace procedure is + * interested in: OR-ed combination of + * TCL_TRACE_READS, TCL_TRACE_WRITES, + * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */ + struct VarTrace *nextPtr; /* Next in list of traces associated with + * a particular variable. */ +} VarTrace; + +/* + * When a variable trace is active (i.e. its associated procedure is + * executing), one of the following structures is linked into a list + * associated with the variable's interpreter. The information in + * the structure is needed in order for Tcl to behave reasonably + * if traces are deleted while traces are active. + */ + +typedef struct ActiveVarTrace { + struct Var *varPtr; /* Variable that's being traced. */ + struct ActiveVarTrace *nextPtr; + /* Next in list of all active variable + * traces for the interpreter, or NULL + * if no more. */ + VarTrace *nextTracePtr; /* Next trace to check after current + * trace procedure returns; if this + * trace gets deleted, must update pointer + * to avoid using free'd memory. */ +} ActiveVarTrace; + +/* + * The following structure describes an enumerative search in progress on + * an array variable; this are invoked with options to the "array" + * command. + */ + +typedef struct ArraySearch { + int id; /* Integer id used to distinguish among + * multiple concurrent searches for the + * same array. */ + struct Var *varPtr; /* Pointer to array variable that's being + * searched. */ + Tcl_HashSearch search; /* Info kept by the hash module about + * progress through the array. */ + Tcl_HashEntry *nextEntry; /* Non-null means this is the next element + * to be enumerated (it's leftover from + * the Tcl_FirstHashEntry call or from + * an "array anymore" command). NULL + * means must call Tcl_NextHashEntry + * to get value to return. */ + struct ArraySearch *nextPtr;/* Next in list of all active searches + * for this variable, or NULL if this is + * the last one. */ +} ArraySearch; + +/* + * The structure below defines a variable, which associates a string name + * with a Tcl_Obj value. These structures are kept in procedure call frames + * (for local variables recognized by the compiler) or in the heap (for + * global variables and any variable not known to the compiler). For each + * Var structure in the heap, a hash table entry holds the variable name and + * a pointer to the Var structure. + */ + +typedef struct Var { + union { + Tcl_Obj *objPtr; /* The variable's object value. Used for + * scalar variables and array elements. */ + Tcl_HashTable *tablePtr;/* For array variables, this points to + * information about the hash table used + * to implement the associative array. + * Points to malloc-ed data. */ + struct Var *linkPtr; /* If this is a global variable being + * referred to in a procedure, or a variable + * created by "upvar", this field points to + * the referenced variable's Var struct. */ + } value; + char *name; /* NULL if the variable is in a hashtable, + * otherwise points to the variable's + * name. It is used, e.g., by TclLookupVar + * and "info locals". The storage for the + * characters of the name is not owned by + * the Var and must not be freed when + * freeing the Var. */ + Namespace *nsPtr; /* Points to the namespace that contains + * this variable or NULL if the variable is + * a local variable in a Tcl procedure. */ + Tcl_HashEntry *hPtr; /* If variable is in a hashtable, either the + * hash table entry that refers to this + * variable or NULL if the variable has been + * detached from its hash table (e.g. an + * array is deleted, but some of its + * elements are still referred to in + * upvars). NULL if the variable is not in a + * hashtable. This is used to delete an + * variable from its hashtable if it is no + * longer needed. */ + int refCount; /* Counts number of active uses of this + * variable, not including its entry in the + * call frame or the hash table: 1 for each + * additional variable whose linkPtr points + * here, 1 for each nested trace active on + * variable, and 1 if the variable is a + * namespace variable. This record can't be + * deleted until refCount becomes 0. */ + VarTrace *tracePtr; /* First in list of all traces set for this + * variable. */ + ArraySearch *searchPtr; /* First in list of all searches active + * for this variable, or NULL if none. */ + int flags; /* Miscellaneous bits of information about + * variable. See below for definitions. */ +} Var; + +/* + * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and + * VAR_LINK) are mutually exclusive and give the "type" of the variable. + * VAR_UNDEFINED is independent of the variable's type. + * + * VAR_SCALAR - 1 means this is a scalar variable and not + * an array or link. The "objPtr" field points + * to the variable's value, a Tcl object. + * VAR_ARRAY - 1 means this is an array variable rather + * than a scalar variable or link. The + * "tablePtr" field points to the array's + * hashtable for its elements. + * VAR_LINK - 1 means this Var structure contains a + * pointer to another Var structure that + * either has the real value or is itself + * another VAR_LINK pointer. Variables like + * this come about through "upvar" and "global" + * commands, or through references to variables + * in enclosing namespaces. + * VAR_UNDEFINED - 1 means that the variable is in the process + * of being deleted. An undefined variable + * logically does not exist and survives only + * while it has a trace, or if it is a global + * variable currently being used by some + * procedure. + * VAR_IN_HASHTABLE - 1 means this variable is in a hashtable and + * the Var structure is malloced. 0 if it is + * a local variable that was assigned a slot + * in a procedure frame by the compiler so the + * Var storage is part of the call frame. + * VAR_TRACE_ACTIVE - 1 means that trace processing is currently + * underway for a read or write access, so + * new read or write accesses should not cause + * trace procedures to be called and the + * variable can't be deleted. + * VAR_ARRAY_ELEMENT - 1 means that this variable is an array + * element, so it is not legal for it to be + * an array itself (the VAR_ARRAY flag had + * better not be set). + * VAR_NAMESPACE_VAR - 1 means that this variable was declared + * as a namespace variable. This flag ensures + * it persists until its namespace is + * destroyed or until the variable is unset; + * it will persist even if it has not been + * initialized and is marked undefined. + * The variable's refCount is incremented to + * reflect the "reference" from its namespace. + * + * The following additional flags are used with the CompiledLocal type + * defined below: + * + * VAR_ARGUMENT - 1 means that this variable holds a procedure + * argument. + * VAR_TEMPORARY - 1 if the local variable is an anonymous + * temporary variable. Temporaries have a NULL + * name. + * VAR_RESOLVED - 1 if name resolution has been done for this + * variable. + */ + +#define VAR_SCALAR 0x1 +#define VAR_ARRAY 0x2 +#define VAR_LINK 0x4 +#define VAR_UNDEFINED 0x8 +#define VAR_IN_HASHTABLE 0x10 +#define VAR_TRACE_ACTIVE 0x20 +#define VAR_ARRAY_ELEMENT 0x40 +#define VAR_NAMESPACE_VAR 0x80 + +#define VAR_ARGUMENT 0x100 +#define VAR_TEMPORARY 0x200 +#define VAR_RESOLVED 0x400 + +/* + * Macros to ensure that various flag bits are set properly for variables. + * The ANSI C "prototypes" for these macros are: + * + * EXTERN void TclSetVarScalar _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarArray _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarLink _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarArrayElement _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarUndefined _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclClearVarUndefined _ANSI_ARGS_((Var *varPtr)); + */ + +#define TclSetVarScalar(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR + +#define TclSetVarArray(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY + +#define TclSetVarLink(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_ARRAY)) | VAR_LINK + +#define TclSetVarArrayElement(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT + +#define TclSetVarUndefined(varPtr) \ + (varPtr)->flags |= VAR_UNDEFINED + +#define TclClearVarUndefined(varPtr) \ + (varPtr)->flags &= ~VAR_UNDEFINED + +/* + * Macros to read various flag bits of variables. + * The ANSI C "prototypes" for these macros are: + * + * EXTERN int TclIsVarScalar _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarLink _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArray _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarUndefined _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarTemporary _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArgument _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarResolved _ANSI_ARGS_((Var *varPtr)); + */ + +#define TclIsVarScalar(varPtr) \ + ((varPtr)->flags & VAR_SCALAR) + +#define TclIsVarLink(varPtr) \ + ((varPtr)->flags & VAR_LINK) + +#define TclIsVarArray(varPtr) \ + ((varPtr)->flags & VAR_ARRAY) + +#define TclIsVarUndefined(varPtr) \ + ((varPtr)->flags & VAR_UNDEFINED) + +#define TclIsVarArrayElement(varPtr) \ + ((varPtr)->flags & VAR_ARRAY_ELEMENT) + +#define TclIsVarTemporary(varPtr) \ + ((varPtr)->flags & VAR_TEMPORARY) + +#define TclIsVarArgument(varPtr) \ + ((varPtr)->flags & VAR_ARGUMENT) + +#define TclIsVarResolved(varPtr) \ + ((varPtr)->flags & VAR_RESOLVED) + +/* + *---------------------------------------------------------------- + * Data structures related to procedures. These are used primarily + * in tclProc.c, tclCompile.c, and tclExecute.c. + *---------------------------------------------------------------- + */ + +/* + * Forward declaration to prevent an error when the forward reference to + * Command is encountered in the Proc and ImportRef types declared below. + */ + +struct Command; + +/* + * The variable-length structure below describes a local variable of a + * procedure that was recognized by the compiler. These variables have a + * name, an element in the array of compiler-assigned local variables in the + * procedure's call frame, and various other items of information. If the + * local variable is a formal argument, it may also have a default value. + * The compiler can't recognize local variables whose names are + * expressions (these names are only known at runtime when the expressions + * are evaluated) or local variables that are created as a result of an + * "upvar" or "uplevel" command. These other local variables are kept + * separately in a hash table in the call frame. + */ + +typedef struct CompiledLocal { + struct CompiledLocal *nextPtr; + /* Next compiler-recognized local variable + * for this procedure, or NULL if this is + * the last local. */ + int nameLength; /* The number of characters in local + * variable's name. Used to speed up + * variable lookups. */ + int frameIndex; /* Index in the array of compiler-assigned + * variables in the procedure call frame. */ + int flags; /* Flag bits for the local variable. Same as + * the flags for the Var structure above, + * although only VAR_SCALAR, VAR_ARRAY, + * VAR_LINK, VAR_ARGUMENT, VAR_TEMPORARY, and + * VAR_RESOLVED make sense. */ + Tcl_Obj *defValuePtr; /* Pointer to the default value of an + * argument, if any. NULL if not an argument + * or, if an argument, no default value. */ + Tcl_ResolvedVarInfo *resolveInfo; + /* Customized variable resolution info + * supplied by the Tcl_ResolveCompiledVarProc + * associated with a namespace. Each variable + * is marked by a unique ClientData tag + * during compilation, and that same tag + * is used to find the variable at runtime. */ + char name[4]; /* Name of the local variable starts here. + * If the name is NULL, this will just be + * '\0'. The actual size of this field will + * be large enough to hold the name. MUST + * BE THE LAST FIELD IN THE STRUCTURE! */ +} CompiledLocal; + +/* + * The structure below defines a command procedure, which consists of a + * collection of Tcl commands plus information about arguments and other + * local variables recognized at compile time. + */ + +typedef struct Proc { + struct Interp *iPtr; /* Interpreter for which this command + * is defined. */ + int refCount; /* Reference count: 1 if still present + * in command table plus 1 for each call + * to the procedure that is currently + * active. This structure can be freed + * when refCount becomes zero. */ + struct Command *cmdPtr; /* Points to the Command structure for + * this procedure. This is used to get + * the namespace in which to execute + * the procedure. */ + Tcl_Obj *bodyPtr; /* Points to the ByteCode object for + * procedure's body command. */ + int numArgs; /* Number of formal parameters. */ + int numCompiledLocals; /* Count of local variables recognized by + * the compiler including arguments and + * temporaries. */ + CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's + * compiler-allocated local variables, or + * NULL if none. The first numArgs entries + * in this list describe the procedure's + * formal arguments. */ + CompiledLocal *lastLocalPtr; /* Pointer to the last allocated local + * variable or NULL if none. This has + * frame index (numCompiledLocals-1). */ +} Proc; + +/* + * The structure below defines a command trace. This is used to allow Tcl + * clients to find out whenever a command is about to be executed. + */ + +typedef struct Trace { + int level; /* Only trace commands at nesting level + * less than or equal to this. */ + Tcl_CmdTraceProc *proc; /* Procedure to call to trace command. */ + ClientData clientData; /* Arbitrary value to pass to proc. */ + struct Trace *nextPtr; /* Next in list of traces for this interp. */ +} Trace; + +/* + * The structure below defines an entry in the assocData hash table which + * is associated with an interpreter. The entry contains a pointer to a + * function to call when the interpreter is deleted, and a pointer to + * a user-defined piece of data. + */ + +typedef struct AssocData { + Tcl_InterpDeleteProc *proc; /* Proc to call when deleting. */ + ClientData clientData; /* Value to pass to proc. */ +} AssocData; + +/* + * The structure below defines a call frame. A call frame defines a naming + * context for a procedure call: its local naming scope (for local + * variables) and its global naming scope (a namespace, perhaps the global + * :: namespace). A call frame can also define the naming context for a + * namespace eval or namespace inscope command: the namespace in which the + * command's code should execute. The Tcl_CallFrame structures exist only + * while procedures or namespace eval/inscope's are being executed, and + * provide a kind of Tcl call stack. + * + * WARNING!! The structure definition must be kept consistent with the + * Tcl_CallFrame structure in tcl.h. If you change one, change the other. + */ + +typedef struct CallFrame { + Namespace *nsPtr; /* Points to the namespace used to resolve + * commands and global variables. */ + int isProcCallFrame; /* If nonzero, the frame was pushed to + * execute a Tcl procedure and may have + * local vars. If 0, the frame was pushed + * to execute a namespace command and var + * references are treated as references to + * namespace vars; varTablePtr and + * compiledLocals are ignored. */ + int objc; /* This and objv below describe the + * arguments for this procedure call. */ + Tcl_Obj *CONST *objv; /* Array of argument objects. */ + struct CallFrame *callerPtr; + /* Value of interp->framePtr when this + * procedure was invoked (i.e. next higher + * in stack of all active procedures). */ + struct CallFrame *callerVarPtr; + /* Value of interp->varFramePtr when this + * procedure was invoked (i.e. determines + * variable scoping within caller). Same + * as callerPtr unless an "uplevel" command + * or something equivalent was active in + * the caller). */ + int level; /* Level of this procedure, for "uplevel" + * purposes (i.e. corresponds to nesting of + * callerVarPtr's, not callerPtr's). 1 for + * outermost procedure, 0 for top-level. */ + Proc *procPtr; /* Points to the structure defining the + * called procedure. Used to get information + * such as the number of compiled local + * variables (local variables assigned + * entries ["slots"] in the compiledLocals + * array below). */ + Tcl_HashTable *varTablePtr; /* Hash table containing local variables not + * recognized by the compiler, or created at + * execution time through, e.g., upvar. + * Initially NULL and created if needed. */ + int numCompiledLocals; /* Count of local variables recognized by + * the compiler including arguments. */ + Var* compiledLocals; /* Points to the array of local variables + * recognized by the compiler. The compiler + * emits code that refers to these variables + * using an index into this array. */ +} CallFrame; + +/* + *---------------------------------------------------------------- + * Data structures and procedures related to TclHandles, which + * are a very lightweight method of preserving enough information + * to determine if an arbitrary malloc'd block has been deleted. + *---------------------------------------------------------------- + */ + +typedef VOID **TclHandle; + +EXTERN TclHandle TclHandleCreate _ANSI_ARGS_((VOID *ptr)); +EXTERN void TclHandleFree _ANSI_ARGS_((TclHandle handle)); +EXTERN TclHandle TclHandlePreserve _ANSI_ARGS_((TclHandle handle)); +EXTERN void TclHandleRelease _ANSI_ARGS_((TclHandle handle)); + +/* + *---------------------------------------------------------------- + * Data structures related to history. These are used primarily + * in tclHistory.c + *---------------------------------------------------------------- + */ + +/* + * The structure below defines one history event (a previously-executed + * command that can be re-executed in whole or in part). + */ + +typedef struct { + char *command; /* String containing previously-executed + * command. */ + int bytesAvl; /* Total # of bytes available at *event (not + * all are necessarily in use now). */ +} HistoryEvent; + +/* + * The structure below defines a pending revision to the most recent + * history event. Changes are linked together into a list and applied + * during the next call to Tcl_RecordHistory. See the comments at the + * beginning of tclHistory.c for information on revisions. + */ + +typedef struct HistoryRev { + int firstIndex; /* Index of the first byte to replace in + * current history event. */ + int lastIndex; /* Index of last byte to replace in + * current history event. */ + int newSize; /* Number of bytes in newBytes. */ + char *newBytes; /* Replacement for the range given by + * firstIndex and lastIndex (malloced). */ + struct HistoryRev *nextPtr; /* Next in chain of revisions to apply, or + * NULL for end of list. */ +} HistoryRev; + +/* + *---------------------------------------------------------------- + * Data structures related to expressions. These are used only in + * tclExpr.c. + *---------------------------------------------------------------- + */ + +/* + * The data structure below defines a math function (e.g. sin or hypot) + * for use in Tcl expressions. + */ + +#define MAX_MATH_ARGS 5 +typedef struct MathFunc { + int builtinFuncIndex; /* If this is a builtin math function, its + * index in the array of builtin functions. + * (tclCompilation.h lists these indices.) + * The value is -1 if this is a new function + * defined by Tcl_CreateMathFunc. The value + * is also -1 if a builtin function is + * replaced by a Tcl_CreateMathFunc call. */ + int numArgs; /* Number of arguments for function. */ + Tcl_ValueType argTypes[MAX_MATH_ARGS]; + /* Acceptable types for each argument. */ + Tcl_MathProc *proc; /* Procedure that implements this function. + * NULL if isBuiltinFunc is 1. */ + ClientData clientData; /* Additional argument to pass to the + * function when invoking it. NULL if + * isBuiltinFunc is 1. */ +} MathFunc; + +/* + * These are a thin layer over TclpThreadKeyDataGet and TclpThreadKeyDataSet + * when threads are used, or an emulation if there are no threads. These + * are really internal and Tcl clients should use Tcl_GetThreadData. + */ + +EXTERN VOID *TclThreadDataKeyGet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclThreadDataKeySet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr, VOID *data)); + +/* + * This is a convenience macro used to initialize a thread local storage ptr. + */ +#define TCL_TSD_INIT(keyPtr) (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) + + +/* + *---------------------------------------------------------------- + * Data structures related to bytecode compilation and execution. + * These are used primarily in tclCompile.c, tclExecute.c, and + * tclBasic.c. + *---------------------------------------------------------------- + */ + +/* + * Forward declaration to prevent errors when the forward references to + * Tcl_Parse and CompileEnv are encountered in the procedure type + * CompileProc declared below. + */ + +struct CompileEnv; + +/* + * The type of procedures called by the Tcl bytecode compiler to compile + * commands. Pointers to these procedures are kept in the Command structure + * describing each command. When a CompileProc returns, the interpreter's + * result is set to error information, if any. In addition, the CompileProc + * returns an integer value, which is one of the following: + * + * TCL_OK Compilation completed normally. + * TCL_ERROR Compilation failed because of an error; + * the interpreter's result describes what went wrong. + * TCL_OUT_LINE_COMPILE Compilation failed because, e.g., the command is + * too complex for effective inline compilation. The + * CompileProc believes the command is legal but + * should be compiled "out of line" by emitting code + * to invoke its command procedure at runtime. + */ + +#define TCL_OUT_LINE_COMPILE (TCL_CONTINUE + 1) + +typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *compEnvPtr)); + +/* + * The type of procedure called from the compilation hook point in + * SetByteCodeFromAny. + */ + +typedef int (CompileHookProc) _ANSI_ARGS_((Tcl_Interp *interp, + struct CompileEnv *compEnvPtr, ClientData clientData)); + +/* + * The data structure defining the execution environment for ByteCode's. + * There is one ExecEnv structure per Tcl interpreter. It holds the + * evaluation stack that holds command operands and results. The stack grows + * towards increasing addresses. The "stackTop" member is cached by + * TclExecuteByteCode in a local variable: it must be set before calling + * TclExecuteByteCode and will be restored by TclExecuteByteCode before it + * returns. + */ + +typedef struct ExecEnv { + Tcl_Obj **stackPtr; /* Points to the first item in the + * evaluation stack on the heap. */ + int stackTop; /* Index of current top of stack; -1 when + * the stack is empty. */ + int stackEnd; /* Index of last usable item in stack. */ +} ExecEnv; + +/* + * The definitions for the LiteralTable and LiteralEntry structures. Each + * interpreter contains a LiteralTable. It is used to reduce the storage + * needed for all the Tcl objects that hold the literals of scripts compiled + * by the interpreter. A literal's object is shared by all the ByteCodes + * that refer to the literal. Each distinct literal has one LiteralEntry + * entry in the LiteralTable. A literal table is a specialized hash table + * that is indexed by the literal's string representation, which may contain + * null characters. + * + * Note that we reduce the space needed for literals by sharing literal + * objects both within a ByteCode (each ByteCode contains a local + * LiteralTable) and across all an interpreter's ByteCodes (with the + * interpreter's global LiteralTable). + */ + +typedef struct LiteralEntry { + struct LiteralEntry *nextPtr; /* Points to next entry in this + * hash bucket or NULL if end of + * chain. */ + Tcl_Obj *objPtr; /* Points to Tcl object that + * holds the literal's bytes and + * length. */ + int refCount; /* If in an interpreter's global + * literal table, the number of + * ByteCode structures that share + * the literal object; the literal + * entry can be freed when refCount + * drops to 0. If in a local literal + * table, -1. */ +} LiteralEntry; + +typedef struct LiteralTable { + LiteralEntry **buckets; /* Pointer to bucket array. Each + * element points to first entry in + * bucket's hash chain, or NULL. */ + LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; + /* Bucket array used for small + * tables to avoid mallocs and + * frees. */ + int numBuckets; /* Total number of buckets allocated + * at **buckets. */ + int numEntries; /* Total number of entries present + * in table. */ + int rebuildSize; /* Enlarge table when numEntries + * gets to be this large. */ + int mask; /* Mask value used in hashing + * function. */ +} LiteralTable; + +/* + * The following structure defines for each Tcl interpreter various + * statistics-related information about the bytecode compiler and + * interpreter's operation in that interpreter. + */ + +#ifdef TCL_COMPILE_STATS +typedef struct ByteCodeStats { + long numExecutions; /* Number of ByteCodes executed. */ + long numCompilations; /* Number of ByteCodes created. */ + long numByteCodesFreed; /* Number of ByteCodes destroyed. */ + long instructionCount[256]; /* Number of times each instruction was + * executed. */ + + double totalSrcBytes; /* Total source bytes ever compiled. */ + double totalByteCodeBytes; /* Total bytes for all ByteCodes. */ + double currentSrcBytes; /* Src bytes for all current ByteCodes. */ + double currentByteCodeBytes; /* Code bytes in all current ByteCodes. */ + + long srcCount[32]; /* Source size distribution: # of srcs of + * size [2**(n-1)..2**n), n in [0..32). */ + long byteCodeCount[32]; /* ByteCode size distribution. */ + long lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */ + + double currentInstBytes; /* Instruction bytes-current ByteCodes. */ + double currentLitBytes; /* Current literal bytes. */ + double currentExceptBytes; /* Current exception table bytes. */ + double currentAuxBytes; /* Current auxiliary information bytes. */ + double currentCmdMapBytes; /* Current src<->code map bytes. */ + + long numLiteralsCreated; /* Total literal objects ever compiled. */ + double totalLitStringBytes; /* Total string bytes in all literals. */ + double currentLitStringBytes; /* String bytes in current literals. */ + long literalCount[32]; /* Distribution of literal string sizes. */ +} ByteCodeStats; +#endif /* TCL_COMPILE_STATS */ + +/* + *---------------------------------------------------------------- + * Data structures related to commands. + *---------------------------------------------------------------- + */ + +/* + * An imported command is created in an namespace when it imports a "real" + * command from another namespace. An imported command has a Command + * structure that points (via its ClientData value) to the "real" Command + * structure in the source namespace's command table. The real command + * records all the imported commands that refer to it in a list of ImportRef + * structures so that they can be deleted when the real command is deleted. */ + +typedef struct ImportRef { + struct Command *importedCmdPtr; + /* Points to the imported command created in + * an importing namespace; this command + * redirects its invocations to the "real" + * command. */ + struct ImportRef *nextPtr; /* Next element on the linked list of + * imported commands that refer to the + * "real" command. The real command deletes + * these imported commands on this list when + * it is deleted. */ +} ImportRef; + +/* + * Data structure used as the ClientData of imported commands: commands + * created in an namespace when it imports a "real" command from another + * namespace. + */ + +typedef struct ImportedCmdData { + struct Command *realCmdPtr; /* "Real" command that this imported command + * refers to. */ + struct Command *selfPtr; /* Pointer to this imported command. Needed + * only when deleting it in order to remove + * it from the real command's linked list of + * imported commands that refer to it. */ +} ImportedCmdData; + +/* + * A Command structure exists for each command in a namespace. The + * Tcl_Command opaque type actually refers to these structures. + */ + +typedef struct Command { + Tcl_HashEntry *hPtr; /* Pointer to the hash table entry that + * refers to this command. The hash table is + * either a namespace's command table or an + * interpreter's hidden command table. This + * pointer is used to get a command's name + * from its Tcl_Command handle. NULL means + * that the hash table entry has been + * removed already (this can happen if + * deleteProc causes the command to be + * deleted or recreated). */ + Namespace *nsPtr; /* Points to the namespace containing this + * command. */ + int refCount; /* 1 if in command hashtable plus 1 for each + * reference from a CmdName Tcl object + * representing a command's name in a + * ByteCode instruction sequence. This + * structure can be freed when refCount + * becomes zero. */ + int cmdEpoch; /* Incremented to invalidate any references + * that point to this command when it is + * renamed, deleted, hidden, or exposed. */ + CompileProc *compileProc; /* Procedure called to compile command. NULL + * if no compile proc exists for command. */ + Tcl_ObjCmdProc *objProc; /* Object-based command procedure. */ + ClientData objClientData; /* Arbitrary value passed to object proc. */ + Tcl_CmdProc *proc; /* String-based command procedure. */ + ClientData clientData; /* Arbitrary value passed to string proc. */ + Tcl_CmdDeleteProc *deleteProc; + /* Procedure invoked when deleting command + * to, e.g., free all client data. */ + ClientData deleteData; /* Arbitrary value passed to deleteProc. */ + int deleted; /* Means that the command is in the process + * of being deleted (its deleteProc is + * currently executing). Other attempts to + * delete the command should be ignored. */ + ImportRef *importRefPtr; /* List of each imported Command created in + * another namespace when this command is + * imported. These imported commands + * redirect invocations back to this + * command. The list is used to remove all + * those imported commands when deleting + * this "real" command. */ +} Command; + +/* + *---------------------------------------------------------------- + * Data structures related to name resolution procedures. + *---------------------------------------------------------------- + */ + +/* + * The interpreter keeps a linked list of name resolution schemes. + * The scheme for a namespace is consulted first, followed by the + * list of schemes in an interpreter, followed by the default + * name resolution in Tcl. Schemes are added/removed from the + * interpreter's list by calling Tcl_AddInterpResolver and + * Tcl_RemoveInterpResolver. + */ + +typedef struct ResolverScheme { + char *name; /* Name identifying this scheme. */ + Tcl_ResolveCmdProc *cmdResProc; + /* Procedure handling command name + * resolution. */ + Tcl_ResolveVarProc *varResProc; + /* Procedure handling variable name + * resolution for variables that + * can only be handled at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* Procedure handling variable name + * resolution at compile time. */ + + struct ResolverScheme *nextPtr; + /* Pointer to next record in linked list. */ +} ResolverScheme; + +/* + *---------------------------------------------------------------- + * This structure defines an interpreter, which is a collection of + * commands plus other state information related to interpreting + * commands, such as variable storage. Primary responsibility for + * this data structure is in tclBasic.c, but almost every Tcl + * source file uses something in here. + *---------------------------------------------------------------- + */ + +typedef struct Interp { + + /* + * Note: the first three fields must match exactly the fields in + * a Tcl_Interp struct (see tcl.h). If you change one, be sure to + * change the other. + * + * The interpreter's result is held in both the string and the + * objResultPtr fields. These fields hold, respectively, the result's + * string or object value. The interpreter's result is always in the + * result field if that is non-empty, otherwise it is in objResultPtr. + * The two fields are kept consistent unless some C code sets + * interp->result directly. Programs should not access result and + * objResultPtr directly; instead, they should always get and set the + * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult, + * and Tcl_GetStringResult. See the SetResult man page for details. + */ + + char *result; /* If the last command returned a string + * result, this points to it. Should not be + * accessed directly; see comment above. */ + Tcl_FreeProc *freeProc; /* Zero means a string result is statically + * allocated. TCL_DYNAMIC means string + * result was allocated with ckalloc and + * should be freed with ckfree. Other values + * give address of procedure to invoke to + * free the string result. Tcl_Eval must + * free it before executing next command. */ + int errorLine; /* When TCL_ERROR is returned, this gives + * the line number in the command where the + * error occurred (1 means first line). */ + struct TclStubs *stubTable; + /* Pointer to the exported Tcl stub table. + * On previous versions of Tcl this is a + * pointer to the objResultPtr or a pointer + * to a buckets array in a hash table. We + * therefore have to do some careful checking + * before we can use this. */ + + TclHandle handle; /* Handle used to keep track of when this + * interp is deleted. */ + + Namespace *globalNsPtr; /* The interpreter's global namespace. */ + Tcl_HashTable *hiddenCmdTablePtr; + /* Hash table used by tclBasic.c to keep + * track of hidden commands on a per-interp + * basis. */ + ClientData interpInfo; /* Information used by tclInterp.c to keep + * track of master/slave interps on + * a per-interp basis. */ + Tcl_HashTable mathFuncTable;/* Contains all the math functions currently + * defined for the interpreter. Indexed by + * strings (function names); values have + * type (MathFunc *). */ + + + + /* + * Information related to procedures and variables. See tclProc.c + * and tclvar.c for usage. + */ + + int numLevels; /* Keeps track of how many nested calls to + * Tcl_Eval are in progress for this + * interpreter. It's used to delay deletion + * of the table until all Tcl_Eval + * invocations are completed. */ + int maxNestingDepth; /* If numLevels exceeds this value then Tcl + * assumes that infinite recursion has + * occurred and it generates an error. */ + CallFrame *framePtr; /* Points to top-most in stack of all nested + * procedure invocations. NULL means there + * are no active procedures. */ + CallFrame *varFramePtr; /* Points to the call frame whose variables + * are currently in use (same as framePtr + * unless an "uplevel" command is + * executing). NULL means no procedure is + * active or "uplevel 0" is executing. */ + ActiveVarTrace *activeTracePtr; + /* First in list of active traces for + * interp, or NULL if no active traces. */ + int returnCode; /* Completion code to return if current + * procedure exits with TCL_RETURN code. */ + char *errorInfo; /* Value to store in errorInfo if returnCode + * is TCL_ERROR. Malloc'ed, may be NULL */ + char *errorCode; /* Value to store in errorCode if returnCode + * is TCL_ERROR. Malloc'ed, may be NULL */ + + /* + * Information used by Tcl_AppendResult to keep track of partial + * results. See Tcl_AppendResult code for details. + */ + + char *appendResult; /* Storage space for results generated + * by Tcl_AppendResult. Malloc-ed. NULL + * means not yet allocated. */ + int appendAvl; /* Total amount of space available at + * partialResult. */ + int appendUsed; /* Number of non-null bytes currently + * stored at partialResult. */ + + /* + * Information about packages. Used only in tclPkg.c. + */ + + Tcl_HashTable packageTable; /* Describes all of the packages loaded + * in or available to this interpreter. + * Keys are package names, values are + * (Package *) pointers. */ + char *packageUnknown; /* Command to invoke during "package + * require" commands for packages that + * aren't described in packageTable. + * Malloc'ed, may be NULL. */ + + /* + * Miscellaneous information: + */ + + int cmdCount; /* Total number of times a command procedure + * has been called for this interpreter. */ + int evalFlags; /* Flags to control next call to Tcl_Eval. + * Normally zero, but may be set before + * calling Tcl_Eval. See below for valid + * values. */ + int termOffset; /* Offset of character just after last one + * compiled or executed by Tcl_EvalObj. */ + LiteralTable literalTable; /* Contains LiteralEntry's describing all + * Tcl objects holding literals of scripts + * compiled by the interpreter. Indexed by + * the string representations of literals. + * Used to avoid creating duplicate + * objects. */ + int compileEpoch; /* Holds the current "compilation epoch" + * for this interpreter. This is + * incremented to invalidate existing + * ByteCodes when, e.g., a command with a + * compile procedure is redefined. */ + Proc *compiledProcPtr; /* If a procedure is being compiled, a + * pointer to its Proc structure; otherwise, + * this is NULL. Set by ObjInterpProc in + * tclProc.c and used by tclCompile.c to + * process local variables appropriately. */ + ResolverScheme *resolverPtr; + /* Linked list of name resolution schemes + * added to this interpreter. Schemes + * are added/removed by calling + * Tcl_AddInterpResolvers and + * Tcl_RemoveInterpResolver. */ + char *scriptFile; /* NULL means there is no nested source + * command active; otherwise this points to + * the name of the file being sourced (it's + * not malloc-ed: it points to an argument + * to Tcl_EvalFile. */ + int flags; /* Various flag bits. See below. */ + long randSeed; /* Seed used for rand() function. */ + Trace *tracePtr; /* List of traces for this interpreter. */ + Tcl_HashTable *assocData; /* Hash table for associating data with + * this interpreter. Cleaned up when + * this interpreter is deleted. */ + struct ExecEnv *execEnvPtr; /* Execution environment for Tcl bytecode + * execution. Contains a pointer to the + * Tcl evaluation stack. */ + Tcl_Obj *emptyObjPtr; /* Points to an object holding an empty + * string. Returned by Tcl_ObjSetVar2 when + * variable traces change a variable in a + * gross way. */ + char resultSpace[TCL_RESULT_SIZE+1]; + /* Static space holding small results. */ + Tcl_Obj *objResultPtr; /* If the last command returned an object + * result, this points to it. Should not be + * accessed directly; see comment above. */ + Tcl_ThreadId threadId; /* ID of thread that owns the interpreter */ + + /* + * Statistical information about the bytecode compiler and interpreter's + * operation. + */ + +#ifdef TCL_COMPILE_STATS + ByteCodeStats stats; /* Holds compilation and execution + * statistics for this interpreter. */ +#endif /* TCL_COMPILE_STATS */ +} Interp; + +/* + * EvalFlag bits for Interp structures: + * + * TCL_BRACKET_TERM 1 means that the current script is terminated by + * a close bracket rather than the end of the string. + * TCL_ALLOW_EXCEPTIONS 1 means it's OK for the script to terminate with + * a code other than TCL_OK or TCL_ERROR; 0 means + * codes other than these should be turned into errors. + */ + +#define TCL_BRACKET_TERM 1 +#define TCL_ALLOW_EXCEPTIONS 4 + +/* + * Flag bits for Interp structures: + * + * DELETED: Non-zero means the interpreter has been deleted: + * don't process any more commands for it, and destroy + * the structure as soon as all nested invocations of + * Tcl_Eval are done. + * ERR_IN_PROGRESS: Non-zero means an error unwind is already in + * progress. Zero means a command proc has been + * invoked since last error occured. + * ERR_ALREADY_LOGGED: Non-zero means information has already been logged + * in $errorInfo for the current Tcl_Eval instance, + * so Tcl_Eval needn't log it (used to implement the + * "error message log" command). + * ERROR_CODE_SET: Non-zero means that Tcl_SetErrorCode has been + * called to record information for the current + * error. Zero means Tcl_Eval must clear the + * errorCode variable if an error is returned. + * EXPR_INITIALIZED: Non-zero means initialization specific to + * expressions has been carried out. + * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler + * should not compile any commands into an inline + * sequence of instructions. This is set 1, for + * example, when command traces are requested. + * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the + * interp has not be initialized. This is set 1 + * when we first use the rand() or srand() functions. + * SAFE_INTERP: Non zero means that the current interp is a + * safe interp (ie it has only the safe commands + * installed, less priviledge than a regular interp). + * USE_EVAL_DIRECT: Non-zero means don't use the compiler or byte-code + * interpreter; instead, have Tcl_EvalObj call + * Tcl_EvalEx. Used primarily for testing the + * new parser. + */ + +#define DELETED 1 +#define ERR_IN_PROGRESS 2 +#define ERR_ALREADY_LOGGED 4 +#define ERROR_CODE_SET 8 +#define EXPR_INITIALIZED 0x10 +#define DONT_COMPILE_CMDS_INLINE 0x20 +#define RAND_SEED_INITIALIZED 0x40 +#define SAFE_INTERP 0x80 +#define USE_EVAL_DIRECT 0x100 + +/* + *---------------------------------------------------------------- + * Data structures related to command parsing. These are used in + * tclParse.c and its clients. + *---------------------------------------------------------------- + */ + +/* + * The following data structure is used by various parsing procedures + * to hold information about where to store the results of parsing + * (e.g. the substituted contents of a quoted argument, or the result + * of a nested command). At any given time, the space available + * for output is fixed, but a procedure may be called to expand the + * space available if the current space runs out. + */ + +typedef struct ParseValue { + char *buffer; /* Address of first character in + * output buffer. */ + char *next; /* Place to store next character in + * output buffer. */ + char *end; /* Address of the last usable character + * in the buffer. */ + void (*expandProc) _ANSI_ARGS_((struct ParseValue *pvPtr, int needed)); + /* Procedure to call when space runs out; + * it will make more space. */ + ClientData clientData; /* Arbitrary information for use of + * expandProc. */ +} ParseValue; + + +/* + * Maximum number of levels of nesting permitted in Tcl commands (used + * to catch infinite recursion). + */ + +#define MAX_NESTING_DEPTH 1000 + +/* + * The macro below is used to modify a "char" value (e.g. by casting + * it to an unsigned character) so that it can be used safely with + * macros such as isspace. + */ + +#define UCHAR(c) ((unsigned char) (c)) + +/* + * This macro is used to determine the offset needed to safely allocate any + * data structure in memory. Given a starting offset or size, it "rounds up" + * or "aligns" the offset to the next 8-byte boundary so that any data + * structure can be placed at the resulting offset without fear of an + * alignment error. + * + * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce + * the wrong result on platforms that allocate addresses that are divisible + * by 4 or 2. Only use it for offsets or sizes. + */ + +#define TCL_ALIGN(x) (((int)(x) + 7) & ~7) + +/* + * The following macros are used to specify the runtime platform + * setting of the tclPlatform variable. + */ + +typedef enum { + TCL_PLATFORM_UNIX, /* Any Unix-like OS. */ + TCL_PLATFORM_MAC, /* MacOS. */ + TCL_PLATFORM_WINDOWS /* Any Microsoft Windows OS. */ +} TclPlatformType; + +/* + * Flags for TclInvoke: + * + * TCL_INVOKE_HIDDEN Invoke a hidden command; if not set, + * invokes an exposed command. + * TCL_INVOKE_NO_UNKNOWN If set, "unknown" is not invoked if + * the command to be invoked is not found. + * Only has an effect if invoking an exposed + * command, i.e. if TCL_INVOKE_HIDDEN is not + * also set. + * TCL_INVOKE_NO_TRACEBACK Does not record traceback information if + * the invoked command returns an error. Used + * if the caller plans on recording its own + * traceback information. + */ + +#define TCL_INVOKE_HIDDEN (1<<0) +#define TCL_INVOKE_NO_UNKNOWN (1<<1) +#define TCL_INVOKE_NO_TRACEBACK (1<<2) + +/* + * The structure used as the internal representation of Tcl list + * objects. This is an array of pointers to the element objects. This array + * is grown (reallocated and copied) as necessary to hold all the list's + * element pointers. The array might contain more slots than currently used + * to hold all element pointers. This is done to make append operations + * faster. + */ + +typedef struct List { + int maxElemCount; /* Total number of element array slots. */ + int elemCount; /* Current number of list elements. */ + Tcl_Obj **elements; /* Array of pointers to element objects. */ +} List; + + +/* + * The following types are used for getting and storing platform-specific + * file attributes in tclFCmd.c and the various platform-versions of + * that file. This is done to have as much common code as possible + * in the file attributes code. For more information about the callbacks, + * see TclFileAttrsCmd in tclFCmd.c. + */ + +typedef int (TclGetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, + int objIndex, CONST char *fileName, Tcl_Obj **attrObjPtrPtr)); +typedef int (TclSetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, + int objIndex, CONST char *fileName, Tcl_Obj *attrObjPtr)); + +typedef struct TclFileAttrProcs { + TclGetFileAttrProc *getProc; /* The procedure for getting attrs. */ + TclSetFileAttrProc *setProc; /* The procedure for setting attrs. */ +} TclFileAttrProcs; + +/* + * Opaque handle used in pipeline routines to encapsulate platform-dependent + * state. + */ + +typedef struct TclFile_ *TclFile; + +/* + *---------------------------------------------------------------- + * Data structures related to hooking 'TclStat(...)' and + * 'TclAccess(...)'. + *---------------------------------------------------------------- + */ + +typedef int (TclStatProc_) _ANSI_ARGS_((CONST char *path, struct stat *buf)); +typedef int (TclAccessProc_) _ANSI_ARGS_((CONST char *path, int mode)); +typedef Tcl_Channel (TclOpenFileChannelProc_) _ANSI_ARGS_((Tcl_Interp *interp, + char *fileName, char *modeString, + int permissions)); + +typedef int (*TclCmdProcType) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char *argv[])); +typedef int (*TclObjCmdProcType) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, struct Tcl_Obj * CONST objv[])); + +/* + * Opaque names for platform specific types. + */ + +typedef struct TclpTime_t_ *TclpTime_t; + +/* + * The following structure is used to pass glob type data amongst + * the various glob routines and TclpMatchFilesTypes. Currently + * most of the fields are ignored. However they will be used in + * a future release to implement glob's ability to find files + * of particular types/permissions/etc only. + */ +typedef struct GlobTypeData { + /* Corresponds to bcdpfls as in 'find -t' */ + int type; + /* Corresponds to file permissions */ + int perm; + /* Acceptable mac type */ + Tcl_Obj* macType; + /* Acceptable mac creator */ + Tcl_Obj* macCreator; +} GlobTypeData; + +/* + * type and permission definitions for glob command + */ +#define TCL_GLOB_TYPE_BLOCK (1<<0) +#define TCL_GLOB_TYPE_CHAR (1<<1) +#define TCL_GLOB_TYPE_DIR (1<<2) +#define TCL_GLOB_TYPE_PIPE (1<<3) +#define TCL_GLOB_TYPE_FILE (1<<4) +#define TCL_GLOB_TYPE_LINK (1<<5) +#define TCL_GLOB_TYPE_SOCK (1<<6) + +#define TCL_GLOB_PERM_RONLY (1<<0) +#define TCL_GLOB_PERM_HIDDEN (1<<1) +#define TCL_GLOB_PERM_R (1<<2) +#define TCL_GLOB_PERM_W (1<<3) +#define TCL_GLOB_PERM_X (1<<4) + +/* + *---------------------------------------------------------------- + * Variables shared among Tcl modules but not used by the outside world. + *---------------------------------------------------------------- + */ + +extern Tcl_Time tclBlockTime; +extern int tclBlockTimeSet; +extern char * tclExecutableName; +extern char * tclNativeExecutableName; +extern char * tclDefaultEncodingDir; +extern Tcl_ChannelType tclFileChannelType; +extern char * tclMemDumpFileName; +extern TclPlatformType tclPlatform; +extern char * tclpFileAttrStrings[]; +extern CONST TclFileAttrProcs tclpFileAttrProcs[]; + +/* + * Variables denoting the Tcl object types defined in the core. + */ + +extern Tcl_ObjType tclBooleanType; +extern Tcl_ObjType tclByteArrayType; +extern Tcl_ObjType tclByteCodeType; +extern Tcl_ObjType tclDoubleType; +extern Tcl_ObjType tclIntType; +extern Tcl_ObjType tclListType; +extern Tcl_ObjType tclProcBodyType; +extern Tcl_ObjType tclStringType; + +/* + * The head of the list of free Tcl objects, and the total number of Tcl + * objects ever allocated and freed. + */ + +extern Tcl_Obj * tclFreeObjList; + +#ifdef TCL_COMPILE_STATS +extern long tclObjsAlloced; +extern long tclObjsFreed; +#endif /* TCL_COMPILE_STATS */ + +/* + * Pointer to a heap-allocated string of length zero that the Tcl core uses + * as the value of an empty string representation for an object. This value + * is shared by all new objects allocated by Tcl_NewObj. + */ + +extern char * tclEmptyStringRep; + +/* + *---------------------------------------------------------------- + * Procedures shared among Tcl modules but not used by the outside + * world: + *---------------------------------------------------------------- + */ + +EXTERN int TclAccess _ANSI_ARGS_((CONST char *path, + int mode)); +EXTERN int TclAccessDeleteProc _ANSI_ARGS_((TclAccessProc_ *proc)); +EXTERN int TclAccessInsertProc _ANSI_ARGS_((TclAccessProc_ *proc)); +EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); +EXTERN int TclArraySet _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj)); +EXTERN int TclCheckBadOctal _ANSI_ARGS_((Tcl_Interp *interp, + char *value)); +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp *interp, + int numPids, Tcl_Pid *pidPtr, + Tcl_Channel errorChan)); +EXTERN void TclCleanupCommand _ANSI_ARGS_((Command *cmdPtr)); +EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Channel inChan, Tcl_Channel outChan, + int toRead, Tcl_Obj *cmdPtr)); +/* + * TclCreatePipeline unofficially exported for use by BLT. + */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv, Tcl_Pid **pidArrayPtr, + TclFile *inPipePtr, TclFile *outPipePtr, + TclFile *errFilePtr)); +EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp *interp, + Namespace *nsPtr, char *procName, + Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, + Proc **procPtrPtr)); +EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_(( + Interp *iPtr, CallFrame *framePtr)); +EXTERN void TclDeleteVars _ANSI_ARGS_((Interp *iPtr, + Tcl_HashTable *tablePtr)); +EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp *interp, + char *separators, Tcl_DString *headPtr, + char *tail, GlobTypeData *types)); +EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE *outFile)); +EXTERN void TclExpandTokenArray _ANSI_ARGS_(( + Tcl_Parse *parsePtr)); +EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp *interp, + double value)); +EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)) ; +EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)); +EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)) ; +EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv)) ; +EXTERN void TclFinalizeAllocSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeCompExecEnv _ANSI_ARGS_((void)); +EXTERN void TclFinalizeCompilation _ANSI_ARGS_((void)); +EXTERN void TclFinalizeEncodingSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeEnvironment _ANSI_ARGS_((void)); +EXTERN void TclFinalizeExecution _ANSI_ARGS_((void)); +EXTERN void TclFinalizeIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeLoad _ANSI_ARGS_((void)); +EXTERN void TclFinalizeMemorySubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeNotifier _ANSI_ARGS_((void)); +EXTERN void TclFinalizeSynchronization _ANSI_ARGS_((void)); +EXTERN void TclFinalizeThreadData _ANSI_ARGS_((void)); +EXTERN void TclFindEncodings _ANSI_ARGS_((CONST char *argv0)); +EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp *iPtr, + char *procName)); +EXTERN int TclFormatInt _ANSI_ARGS_((char *buffer, long n)); +EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp *iPtr)); +EXTERN int TclGetDate _ANSI_ARGS_((char *p, + unsigned long now, long zone, + unsigned long *timePtr)); +EXTERN Tcl_Obj * TclGetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + Tcl_Obj *elemPtr, int leaveErrorMsg)); +EXTERN char * TclGetExtension _ANSI_ARGS_((char *name)); +EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp *interp, + char *string, CallFrame **framePtrPtr)); +EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void)); +EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *objPtr, int endValue, int *indexPtr)); +EXTERN Tcl_Obj * TclGetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp, + int localIndex, int leaveErrorMsg)); +EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp *interp, + char *string, long *longPtr)); +EXTERN int TclGetLoadedPackages _ANSI_ARGS_(( + Tcl_Interp *interp, char *targetName)); +EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_(( + Tcl_Interp *interp, char *qualName, + Namespace *cxtNsPtr, int flags, + Namespace **nsPtrPtr, Namespace **altNsPtrPtr, + Namespace **actualCxtPtrPtr, + char **simpleNamePtr)); +EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void)); +EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp *interp, + char *string, int *seekFlagPtr)); +EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_(( + Tcl_Command command)); +EXTERN int TclGlob _ANSI_ARGS_((Tcl_Interp *interp, + char *pattern, char *unquotedPrefix, + int globFlags, GlobTypeData* types)); +EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv, int flags)); +EXTERN int TclGuessPackageName _ANSI_ARGS_((char *fileName, + Tcl_DString *bufPtr)); +EXTERN int TclHideUnsafeCommands _ANSI_ARGS_(( + Tcl_Interp *interp)); +EXTERN int TclInExit _ANSI_ARGS_((void)); +EXTERN Tcl_Obj * TclIncrElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + Tcl_Obj *elemPtr, long incrAmount)); +EXTERN Tcl_Obj * TclIncrIndexedScalar _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + long incrAmount)); +EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, + long incrAmount, int flags)); +EXTERN void TclInitAlloc _ANSI_ARGS_((void)); +EXTERN void TclInitCompiledLocals _ANSI_ARGS_(( + Tcl_Interp *interp, CallFrame *framePtr, + Namespace *nsPtr)); +EXTERN void TclInitDbCkalloc _ANSI_ARGS_((void)); +EXTERN void TclInitEncodingSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNamespaceSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNotifier _ANSI_ARGS_((void)); +EXTERN void TclInitObjSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitSubsystems _ANSI_ARGS_((CONST char *argv0)); +EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp *interp, + int argc, char **argv, int flags)); +EXTERN int TclInvokeObjectCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int argc, char **argv)); +EXTERN int TclInvokeStringCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int TclIsLocalScalar _ANSI_ARGS_((CONST char *src, + int len)); +EXTERN Proc * TclIsProc _ANSI_ARGS_((Command *cmdPtr)); +EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp *interp, + char *part1, char *part2, int flags, char *msg, + int createPart1, int createPart2, + Var **arrayPtrPtr)); +EXTERN int TclMathInProgress _ANSI_ARGS_((void)); +EXTERN int TclNeedSpace _ANSI_ARGS_((char *start, char *end)); +EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc *procPtr)); +EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj *cmdPtr)); +EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ *proc)); +EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ *proc)); +EXTERN int TclpAccess _ANSI_ARGS_((CONST char *filename, + int mode)); +EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size)); +EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); +EXTERN int TclpCopyFile _ANSI_ARGS_((CONST char *source, + CONST char *dest)); +EXTERN int TclpCopyDirectory _ANSI_ARGS_((CONST char *source, + CONST char *dest, Tcl_DString *errorPtr)); +EXTERN int TclpCreateDirectory _ANSI_ARGS_((CONST char *path)); +EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char *path)); +EXTERN void TclpExit _ANSI_ARGS_((int status)); +EXTERN void TclpFinalizeCondition _ANSI_ARGS_(( + Tcl_Condition *condPtr)); +EXTERN void TclpFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutexPtr)); +EXTERN void TclpFinalizeThreadData _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpFinalizeThreadDataKey _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN char * TclpFindExecutable _ANSI_ARGS_(( + CONST char *argv0)); +EXTERN int TclpFindVariable _ANSI_ARGS_((CONST char *name, + int *lengthPtr)); +EXTERN void TclpFree _ANSI_ARGS_((char *ptr)); +EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void)); +EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); +EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void)); +EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time *time)); +EXTERN int TclpGetTimeZone _ANSI_ARGS_((unsigned long time)); +EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char *name, + Tcl_DString *bufferPtr)); +EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TclpInitLibraryPath _ANSI_ARGS_((CONST char *argv0)); +EXTERN void TclpInitLock _ANSI_ARGS_((void)); +EXTERN void TclpInitPlatform _ANSI_ARGS_((void)); +EXTERN void TclpInitUnlock _ANSI_ARGS_((void)); +EXTERN int TclpListVolumes _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TclpMasterLock _ANSI_ARGS_((void)); +EXTERN void TclpMasterUnlock _ANSI_ARGS_((void)); +EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp *interp, + char *separators, Tcl_DString *dirPtr, + char *pattern, char *tail)); +EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp, + char *fileName, char *modeString, + int permissions)); +EXTERN char * TclpReadlink _ANSI_ARGS_((CONST char *fileName, + Tcl_DString *linkPtr)); +EXTERN char * TclpRealloc _ANSI_ARGS_((char *ptr, + unsigned int size)); +EXTERN void TclpReleaseFile _ANSI_ARGS_((TclFile file)); +EXTERN int TclpRemoveDirectory _ANSI_ARGS_((CONST char *path, + int recursive, Tcl_DString *errorPtr)); +EXTERN int TclpRenameFile _ANSI_ARGS_((CONST char *source, + CONST char *dest)); +EXTERN void TclpSetInitialEncodings _ANSI_ARGS_((void)); +EXTERN void TclpSetVariables _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN VOID * TclpSysAlloc _ANSI_ARGS_((long size, int isBin)); +EXTERN void TclpSysFree _ANSI_ARGS_((VOID *ptr)); +EXTERN VOID * TclpSysRealloc _ANSI_ARGS_((VOID *cp, + unsigned int size)); +EXTERN void TclpUnloadFile _ANSI_ARGS_((ClientData clientData)); +EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, char *name1, char *name2, + int flags)); +EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Interp *cmdInterp, Tcl_Command cmd)); +EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc *procPtr)); +EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp *interp, + Proc *procPtr, Tcl_Obj *bodyPtr, Namespace *nsPtr, + CONST char *description, CONST char *procName)); +EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN VOID * TclpThreadDataKeyGet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeyInit _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeySet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr, VOID *data)); +EXTERN void TclpThreadExit _ANSI_ARGS_((int status)); +EXTERN void TclRememberCondition _ANSI_ARGS_((Tcl_Condition *mutex)); +EXTERN void TclRememberDataKey _ANSI_ARGS_((Tcl_ThreadDataKey *mutex)); +EXTERN void TclRememberMutex _ANSI_ARGS_((Tcl_Mutex *mutex)); +EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp *interp, + char *oldName, char *newName)) ; +EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_(( + Tcl_Interp *interp, Command *newCmdPtr)); +EXTERN int TclServiceIdle _ANSI_ARGS_((void)); +EXTERN Tcl_Obj * TclSetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp *interp, int localIndex, + Tcl_Obj *elemPtr, Tcl_Obj *objPtr, + int leaveErrorMsg)); +EXTERN Tcl_Obj * TclSetIndexedScalar _ANSI_ARGS_((Tcl_Interp *interp, + int localIndex, Tcl_Obj *objPtr, + int leaveErrorMsg)); +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char *string)); +EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp *interp, + char *string, char *proto, int *portPtr)); +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +EXTERN int TclStat _ANSI_ARGS_((CONST char *path, + struct stat *buf)); +EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ *proc)); +EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ *proc)); +EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace *nsPtr)); +EXTERN void TclTransferResult _ANSI_ARGS_((Tcl_Interp *sourceInterp, + int result, Tcl_Interp *targetInterp)); +EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp *iPtr)); + +/* + *---------------------------------------------------------------- + * Command procedures in the generic core: + *---------------------------------------------------------------- + */ + +EXTERN int Tcl_AfterObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_AppendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ArrayObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BinaryObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BreakObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CaseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ClockObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CloseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ConcatObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ContinueObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EncodingObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EofObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExecObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExprObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FblockedObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FconfigureObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FcopyObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FileObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FileEventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FlushObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ForObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ForeachObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FormatObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GetsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GlobalObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GlobObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IfObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IncrObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_InfoObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_InterpObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_JoinObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LappendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LindexObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LinsertObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LlengthObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ListObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LoadObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LrangeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LreplaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LsearchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LsortObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_NamespaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_OpenObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PackageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PidObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PutsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PwdObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ReadObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RegexpObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RegsubObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RenameObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ReturnObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ScanObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SeekObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SplitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SocketObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_StringObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SubstObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SwitchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TellObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TimeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TraceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UnsetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UplevelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UpvarObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_VariableObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_VwaitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_WhileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); + +/* + *---------------------------------------------------------------- + * Command procedures found only in the Mac version of the core: + *---------------------------------------------------------------- + */ + +#ifdef MAC_TCL +EXTERN int Tcl_EchoCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tcl_LsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BeepObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_MacSourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ResourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +#endif + +/* + *---------------------------------------------------------------- + * Compilation procedures for commands in the generic core: + *---------------------------------------------------------------- + */ + +EXTERN int TclCompileBreakCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileCatchCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileContinueCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileExprCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileForCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileForeachCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileIfCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileIncrCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileSetCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileWhileCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); + +/* + *---------------------------------------------------------------- + * Macros used by the Tcl core to create and release Tcl objects. + * TclNewObj(objPtr) creates a new object denoting an empty string. + * TclDecrRefCount(objPtr) decrements the object's reference count, + * and frees the object if its reference count is zero. + * These macros are inline versions of Tcl_NewObj() and + * Tcl_DecrRefCount(). Notice that the names differ in not having + * a "_" after the "Tcl". Notice also that these macros reference + * their argument more than once, so you should avoid calling them + * with an expression that is expensive to compute or has + * side effects. The ANSI C "prototypes" for these macros are: + * + * EXTERN void TclNewObj _ANSI_ARGS_((Tcl_Obj *objPtr)); + * EXTERN void TclDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr)); + *---------------------------------------------------------------- + */ + +#ifdef TCL_COMPILE_STATS +# define TclIncrObjsAllocated() \ + tclObjsAlloced++ +# define TclIncrObjsFreed() \ + tclObjsFreed++ +#else +# define TclIncrObjsAllocated() +# define TclIncrObjsFreed() +#endif /* TCL_COMPILE_STATS */ + +#ifdef TCL_MEM_DEBUG +# define TclNewObj(objPtr) \ + (objPtr) = (Tcl_Obj *) \ + Tcl_DbCkalloc(sizeof(Tcl_Obj), __FILE__, __LINE__); \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL; \ + TclIncrObjsAllocated() + +# define TclDbNewObj(objPtr, file, line) \ + (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL; \ + TclIncrObjsAllocated() + +# define TclDecrRefCount(objPtr) \ + if (--(objPtr)->refCount <= 0) { \ + if ((objPtr)->refCount < -1) \ + panic("Reference count for %lx was negative: %s line %d", \ + (objPtr), __FILE__, __LINE__); \ + if (((objPtr)->bytes != NULL) \ + && ((objPtr)->bytes != tclEmptyStringRep)) { \ + ckfree((char *) (objPtr)->bytes); \ + } \ + if (((objPtr)->typePtr != NULL) \ + && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ + (objPtr)->typePtr->freeIntRepProc(objPtr); \ + } \ + ckfree((char *) (objPtr)); \ + TclIncrObjsFreed(); \ + } + +#else /* not TCL_MEM_DEBUG */ + +#ifdef TCL_THREADS +extern Tcl_Mutex tclObjMutex; +#endif + +# define TclNewObj(objPtr) \ + Tcl_MutexLock(&tclObjMutex); \ + if (tclFreeObjList == NULL) { \ + TclAllocateFreeObjects(); \ + } \ + (objPtr) = tclFreeObjList; \ + tclFreeObjList = (Tcl_Obj *) \ + tclFreeObjList->internalRep.otherValuePtr; \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL; \ + TclIncrObjsAllocated(); \ + Tcl_MutexUnlock(&tclObjMutex) + +# define TclDecrRefCount(objPtr) \ + if (--(objPtr)->refCount <= 0) { \ + if (((objPtr)->bytes != NULL) \ + && ((objPtr)->bytes != tclEmptyStringRep)) { \ + ckfree((char *) (objPtr)->bytes); \ + } \ + if (((objPtr)->typePtr != NULL) \ + && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ + (objPtr)->typePtr->freeIntRepProc(objPtr); \ + } \ + Tcl_MutexLock(&tclObjMutex); \ + (objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \ + tclFreeObjList = (objPtr); \ + TclIncrObjsFreed(); \ + Tcl_MutexUnlock(&tclObjMutex); \ + } +#endif /* TCL_MEM_DEBUG */ + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to set a Tcl_Obj's string representation + * to a copy of the "len" bytes starting at "bytePtr". This code + * works even if the byte array contains NULLs as long as the length + * is correct. Because "len" is referenced multiple times, it should + * be as simple an expression as possible. The ANSI C "prototype" for + * this macro is: + * + * EXTERN void TclInitStringRep _ANSI_ARGS_((Tcl_Obj *objPtr, + * char *bytePtr, int len)); + *---------------------------------------------------------------- + */ + +#define TclInitStringRep(objPtr, bytePtr, len) \ + if ((len) == 0) { \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + } else { \ + (objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \ + memcpy((VOID *) (objPtr)->bytes, (VOID *) (bytePtr), \ + (unsigned) (len)); \ + (objPtr)->bytes[len] = '\0'; \ + (objPtr)->length = (len); \ + } + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to get the string representation's + * byte array pointer from a Tcl_Obj. This is an inline version + * of Tcl_GetString(). The macro's expression result is the string + * rep's byte pointer which might be NULL. The bytes referenced by + * this pointer must not be modified by the caller. + * The ANSI C "prototype" for this macro is: + * + * EXTERN char * TclGetString _ANSI_ARGS_((Tcl_Obj *objPtr)); + *---------------------------------------------------------------- + */ + +#define TclGetString(objPtr) \ + ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr))) + +#include "tclIntDecls.h" + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TCLINT */ + diff --git a/Utilities/TclTk/internals/tk8.3/tclIntDecls.h b/Utilities/TclTk/internals/tk8.3/tclIntDecls.h new file mode 100644 index 0000000..b5bbe84 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tclIntDecls.h @@ -0,0 +1,1393 @@ +/* + * tclIntDecls.h -- + * + * This file contains the declarations for all unsupported + * functions that are exported by the Tcl library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclIntDecls.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TCLINTDECLS +#define _TCLINTDECLS + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tclInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +/* 0 */ +EXTERN int TclAccess _ANSI_ARGS_((CONST char * path, int mode)); +/* 1 */ +EXTERN int TclAccessDeleteProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 2 */ +EXTERN int TclAccessInsertProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 3 */ +EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); +/* Slot 4 is reserved */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 5 */ +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp, + int numPids, Tcl_Pid * pidPtr, + Tcl_Channel errorChan)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 5 */ +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp, + int numPids, Tcl_Pid * pidPtr, + Tcl_Channel errorChan)); +#endif /* __WIN32__ */ +/* 6 */ +EXTERN void TclCleanupCommand _ANSI_ARGS_((Command * cmdPtr)); +/* 7 */ +EXTERN int TclCopyAndCollapse _ANSI_ARGS_((int count, + CONST char * src, char * dst)); +/* 8 */ +EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel inChan, Tcl_Channel outChan, + int toRead, Tcl_Obj * cmdPtr)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 9 */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, + Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, + TclFile * outPipePtr, TclFile * errFilePtr)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 9 */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, + Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, + TclFile * outPipePtr, TclFile * errFilePtr)); +#endif /* __WIN32__ */ +/* 10 */ +EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp * interp, + Namespace * nsPtr, char * procName, + Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, + Proc ** procPtrPtr)); +/* 11 */ +EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_(( + Interp * iPtr, CallFrame * framePtr)); +/* 12 */ +EXTERN void TclDeleteVars _ANSI_ARGS_((Interp * iPtr, + Tcl_HashTable * tablePtr)); +/* 13 */ +EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * headPtr, + char * tail, GlobTypeData * types)); +/* 14 */ +EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE * outFile)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp * interp, + double value)); +/* 17 */ +EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[])); +/* 18 */ +EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 19 */ +EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 20 */ +EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 21 */ +EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv)); +/* 22 */ +EXTERN int TclFindElement _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * listStr, int listLength, + CONST char ** elementPtr, + CONST char ** nextPtr, int * sizePtr, + int * bracePtr)); +/* 23 */ +EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp * iPtr, + char * procName)); +/* 24 */ +EXTERN int TclFormatInt _ANSI_ARGS_((char * buffer, long n)); +/* 25 */ +EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 26 is reserved */ +/* 27 */ +EXTERN int TclGetDate _ANSI_ARGS_((char * p, unsigned long now, + long zone, unsigned long * timePtr)); +/* 28 */ +EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); +/* 29 */ +EXTERN Tcl_Obj * TclGetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, int leaveErrorMsg)); +/* Slot 30 is reserved */ +/* 31 */ +EXTERN char * TclGetExtension _ANSI_ARGS_((char * name)); +/* 32 */ +EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp * interp, + char * str, CallFrame ** framePtrPtr)); +/* 33 */ +EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void)); +/* 34 */ +EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, int endValue, + int * indexPtr)); +/* 35 */ +EXTERN Tcl_Obj * TclGetIndexedScalar _ANSI_ARGS_((Tcl_Interp * interp, + int localIndex, int leaveErrorMsg)); +/* 36 */ +EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp * interp, + char * str, long * longPtr)); +/* 37 */ +EXTERN int TclGetLoadedPackages _ANSI_ARGS_(( + Tcl_Interp * interp, char * targetName)); +/* 38 */ +EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_(( + Tcl_Interp * interp, char * qualName, + Namespace * cxtNsPtr, int flags, + Namespace ** nsPtrPtr, + Namespace ** altNsPtrPtr, + Namespace ** actualCxtPtrPtr, + char ** simpleNamePtr)); +/* 39 */ +EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void)); +/* 40 */ +EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp * interp, + char * str, int * seekFlagPtr)); +/* 41 */ +EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_(( + Tcl_Command command)); +/* 42 */ +EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char * name, + Tcl_DString * bufferPtr)); +/* 43 */ +EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int argc, char ** argv, int flags)); +/* 44 */ +EXTERN int TclGuessPackageName _ANSI_ARGS_((char * fileName, + Tcl_DString * bufPtr)); +/* 45 */ +EXTERN int TclHideUnsafeCommands _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 46 */ +EXTERN int TclInExit _ANSI_ARGS_((void)); +/* 47 */ +EXTERN Tcl_Obj * TclIncrElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, long incrAmount)); +/* 48 */ +EXTERN Tcl_Obj * TclIncrIndexedScalar _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + long incrAmount)); +/* 49 */ +EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, + long incrAmount, int part1NotParsed)); +/* 50 */ +EXTERN void TclInitCompiledLocals _ANSI_ARGS_(( + Tcl_Interp * interp, CallFrame * framePtr, + Namespace * nsPtr)); +/* 51 */ +EXTERN int TclInterpInit _ANSI_ARGS_((Tcl_Interp * interp)); +/* 52 */ +EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp * interp, int argc, + char ** argv, int flags)); +/* 53 */ +EXTERN int TclInvokeObjectCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int argc, char ** argv)); +/* 54 */ +EXTERN int TclInvokeStringCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[])); +/* 55 */ +EXTERN Proc * TclIsProc _ANSI_ARGS_((Command * cmdPtr)); +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +/* 58 */ +EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp * interp, + char * part1, char * part2, int flags, + char * msg, int createPart1, int createPart2, + Var ** arrayPtrPtr)); +/* 59 */ +EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * dirPtr, + char * pattern, char * tail)); +/* 60 */ +EXTERN int TclNeedSpace _ANSI_ARGS_((char * start, char * end)); +/* 61 */ +EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc * procPtr)); +/* 62 */ +EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj * cmdPtr)); +/* 63 */ +EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int objc, + Tcl_Obj *CONST objv[])); +/* 64 */ +EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 65 */ +EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 66 */ +EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* 67 */ +EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* 68 */ +EXTERN int TclpAccess _ANSI_ARGS_((CONST char * path, int mode)); +/* 69 */ +EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size)); +/* 70 */ +EXTERN int TclpCopyFile _ANSI_ARGS_((CONST char * source, + CONST char * dest)); +/* 71 */ +EXTERN int TclpCopyDirectory _ANSI_ARGS_((CONST char * source, + CONST char * dest, Tcl_DString * errorPtr)); +/* 72 */ +EXTERN int TclpCreateDirectory _ANSI_ARGS_((CONST char * path)); +/* 73 */ +EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char * path)); +/* 74 */ +EXTERN void TclpFree _ANSI_ARGS_((char * ptr)); +/* 75 */ +EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void)); +/* 76 */ +EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void)); +/* 77 */ +EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time * time)); +/* 78 */ +EXTERN int TclpGetTimeZone _ANSI_ARGS_((unsigned long time)); +/* 79 */ +EXTERN int TclpListVolumes _ANSI_ARGS_((Tcl_Interp * interp)); +/* 80 */ +EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName, char * modeString, + int permissions)); +/* 81 */ +EXTERN char * TclpRealloc _ANSI_ARGS_((char * ptr, + unsigned int size)); +/* 82 */ +EXTERN int TclpRemoveDirectory _ANSI_ARGS_((CONST char * path, + int recursive, Tcl_DString * errorPtr)); +/* 83 */ +EXTERN int TclpRenameFile _ANSI_ARGS_((CONST char * source, + CONST char * dest)); +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +/* 88 */ +EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, char * name1, + char * name2, int flags)); +/* 89 */ +EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Interp * cmdInterp, Tcl_Command cmd)); +/* Slot 90 is reserved */ +/* 91 */ +EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc * procPtr)); +/* 92 */ +EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp * interp, + Proc * procPtr, Tcl_Obj * bodyPtr, + Namespace * nsPtr, CONST char * description, + CONST char * procName)); +/* 93 */ +EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +/* 94 */ +EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, char ** argv)); +/* 95 */ +EXTERN int TclpStat _ANSI_ARGS_((CONST char * path, + struct stat * buf)); +/* 96 */ +EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * oldName, char * newName)); +/* 97 */ +EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_(( + Tcl_Interp * interp, Command * newCmdPtr)); +/* 98 */ +EXTERN int TclServiceIdle _ANSI_ARGS_((void)); +/* 99 */ +EXTERN Tcl_Obj * TclSetElementOfIndexedArray _ANSI_ARGS_(( + Tcl_Interp * interp, int localIndex, + Tcl_Obj * elemPtr, Tcl_Obj * objPtr, + int leaveErrorMsg)); +/* 100 */ +EXTERN Tcl_Obj * TclSetIndexedScalar _ANSI_ARGS_((Tcl_Interp * interp, + int localIndex, Tcl_Obj * objPtr, + int leaveErrorMsg)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 101 */ +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char * string)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 101 */ +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char * string)); +#endif /* __WIN32__ */ +/* 102 */ +EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp * interp)); +/* 103 */ +EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp * interp, + char * str, char * proto, int * portPtr)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 104 */ +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 104 */ +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +#endif /* __WIN32__ */ +/* 105 */ +EXTERN int TclStat _ANSI_ARGS_((CONST char * path, + struct stat * buf)); +/* 106 */ +EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 107 */ +EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 108 */ +EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace * nsPtr)); +/* 109 */ +EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 110 is reserved */ +/* 111 */ +EXTERN void Tcl_AddInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 112 */ +EXTERN int Tcl_AppendExportList _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Namespace * nsPtr, + Tcl_Obj * objPtr)); +/* 113 */ +EXTERN Tcl_Namespace * Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp * interp, + char * name, ClientData clientData, + Tcl_NamespaceDeleteProc * deleteProc)); +/* 114 */ +EXTERN void Tcl_DeleteNamespace _ANSI_ARGS_(( + Tcl_Namespace * nsPtr)); +/* 115 */ +EXTERN int Tcl_Export _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern, + int resetListFirst)); +/* 116 */ +EXTERN Tcl_Command Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_Namespace * contextNsPtr, + int flags)); +/* 117 */ +EXTERN Tcl_Namespace * Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp * interp, + char * name, Tcl_Namespace * contextNsPtr, + int flags)); +/* 118 */ +EXTERN int Tcl_GetInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_ResolverInfo * resInfo)); +/* 119 */ +EXTERN int Tcl_GetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolverInfo * resInfo)); +/* 120 */ +EXTERN Tcl_Var Tcl_FindNamespaceVar _ANSI_ARGS_(( + Tcl_Interp * interp, char * name, + Tcl_Namespace * contextNsPtr, int flags)); +/* 121 */ +EXTERN int Tcl_ForgetImport _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern)); +/* 122 */ +EXTERN Tcl_Command Tcl_GetCommandFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr)); +/* 123 */ +EXTERN void Tcl_GetCommandFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Command command, + Tcl_Obj * objPtr)); +/* 124 */ +EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 125 */ +EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 126 */ +EXTERN void Tcl_GetVariableFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Var variable, + Tcl_Obj * objPtr)); +/* 127 */ +EXTERN int Tcl_Import _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, char * pattern, + int allowOverwrite)); +/* 128 */ +EXTERN void Tcl_PopCallFrame _ANSI_ARGS_((Tcl_Interp* interp)); +/* 129 */ +EXTERN int Tcl_PushCallFrame _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_CallFrame * framePtr, + Tcl_Namespace * nsPtr, int isProcCallFrame)); +/* 130 */ +EXTERN int Tcl_RemoveInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, char * name)); +/* 131 */ +EXTERN void Tcl_SetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 132 */ +EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp * interp)); +/* 133 */ +EXTERN struct tm * TclpGetDate _ANSI_ARGS_((TclpTime_t time, int useGMT)); +/* 134 */ +EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize, + CONST char * format, CONST struct tm * t)); +/* 135 */ +EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); +/* Slot 136 is reserved */ +/* 137 */ +EXTERN int TclpChdir _ANSI_ARGS_((CONST char * dirName)); +/* 138 */ +EXTERN char * TclGetEnv _ANSI_ARGS_((CONST char * name, + Tcl_DString * valuePtr)); +/* 139 */ +EXTERN int TclpLoadFile _ANSI_ARGS_((Tcl_Interp * interp, + char * fileName, char * sym1, char * sym2, + Tcl_PackageInitProc ** proc1Ptr, + Tcl_PackageInitProc ** proc2Ptr, + ClientData * clientDataPtr)); +/* 140 */ +EXTERN int TclLooksLikeInt _ANSI_ARGS_((char * bytes, + int length)); +/* 141 */ +EXTERN char * TclpGetCwd _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * cwdPtr)); +/* 142 */ +EXTERN int TclSetByteCodeFromAny _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr, + CompileHookProc * hookProc, + ClientData clientData)); +/* 143 */ +EXTERN int TclAddLiteralObj _ANSI_ARGS_(( + struct CompileEnv * envPtr, Tcl_Obj * objPtr, + LiteralEntry ** litPtrPtr)); +/* 144 */ +EXTERN void TclHideLiteral _ANSI_ARGS_((Tcl_Interp * interp, + struct CompileEnv * envPtr, int index)); +/* 145 */ +EXTERN struct AuxDataType * TclGetAuxDataType _ANSI_ARGS_((char * typeName)); +/* 146 */ +EXTERN TclHandle TclHandleCreate _ANSI_ARGS_((VOID * ptr)); +/* 147 */ +EXTERN void TclHandleFree _ANSI_ARGS_((TclHandle handle)); +/* 148 */ +EXTERN TclHandle TclHandlePreserve _ANSI_ARGS_((TclHandle handle)); +/* 149 */ +EXTERN void TclHandleRelease _ANSI_ARGS_((TclHandle handle)); +/* 150 */ +EXTERN int TclRegAbout _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_RegExp re)); +/* 151 */ +EXTERN void TclRegExpRangeUniChar _ANSI_ARGS_((Tcl_RegExp re, + int index, int * startPtr, int * endPtr)); +/* 152 */ +EXTERN void TclSetLibraryPath _ANSI_ARGS_((Tcl_Obj * pathPtr)); +/* 153 */ +EXTERN Tcl_Obj * TclGetLibraryPath _ANSI_ARGS_((void)); +/* Slot 154 is reserved */ +/* Slot 155 is reserved */ +/* 156 */ +EXTERN void TclRegError _ANSI_ARGS_((Tcl_Interp * interp, + char * msg, int status)); +/* 157 */ +EXTERN Var * TclVarTraceExists _ANSI_ARGS_((Tcl_Interp * interp, + char * varName)); +/* 158 */ +EXTERN void TclSetStartupScriptFileName _ANSI_ARGS_(( + char * filename)); +/* 159 */ +EXTERN char * TclGetStartupScriptFileName _ANSI_ARGS_((void)); +/* 160 */ +EXTERN int TclpMatchFilesTypes _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * dirPtr, + char * pattern, char * tail, + GlobTypeData * types)); +/* 161 */ +EXTERN int TclChannelTransform _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel chan, Tcl_Obj * cmdObjPtr)); +/* 162 */ +EXTERN void TclChannelEventScriptInvoker _ANSI_ARGS_(( + ClientData clientData, int flags)); + +typedef struct TclIntStubs { + int magic; + struct TclIntStubHooks *hooks; + + int (*tclAccess) _ANSI_ARGS_((CONST char * path, int mode)); /* 0 */ + int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */ + int (*tclAccessInsertProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 2 */ + void (*tclAllocateFreeObjects) _ANSI_ARGS_((void)); /* 3 */ + void *reserved4; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved5; +#endif /* MAC_TCL */ + void (*tclCleanupCommand) _ANSI_ARGS_((Command * cmdPtr)); /* 6 */ + int (*tclCopyAndCollapse) _ANSI_ARGS_((int count, CONST char * src, char * dst)); /* 7 */ + int (*tclCopyChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj * cmdPtr)); /* 8 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved9; +#endif /* MAC_TCL */ + int (*tclCreateProc) _ANSI_ARGS_((Tcl_Interp * interp, Namespace * nsPtr, char * procName, Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, Proc ** procPtrPtr)); /* 10 */ + void (*tclDeleteCompiledLocalVars) _ANSI_ARGS_((Interp * iPtr, CallFrame * framePtr)); /* 11 */ + void (*tclDeleteVars) _ANSI_ARGS_((Interp * iPtr, Tcl_HashTable * tablePtr)); /* 12 */ + int (*tclDoGlob) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * headPtr, char * tail, GlobTypeData * types)); /* 13 */ + void (*tclDumpMemoryInfo) _ANSI_ARGS_((FILE * outFile)); /* 14 */ + void *reserved15; + void (*tclExprFloatError) _ANSI_ARGS_((Tcl_Interp * interp, double value)); /* 16 */ + int (*tclFileAttrsCmd) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 17 */ + int (*tclFileCopyCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 18 */ + int (*tclFileDeleteCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 19 */ + int (*tclFileMakeDirsCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 20 */ + int (*tclFileRenameCmd) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv)); /* 21 */ + int (*tclFindElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * listStr, int listLength, CONST char ** elementPtr, CONST char ** nextPtr, int * sizePtr, int * bracePtr)); /* 22 */ + Proc * (*tclFindProc) _ANSI_ARGS_((Interp * iPtr, char * procName)); /* 23 */ + int (*tclFormatInt) _ANSI_ARGS_((char * buffer, long n)); /* 24 */ + void (*tclFreePackageInfo) _ANSI_ARGS_((Interp * iPtr)); /* 25 */ + void *reserved26; + int (*tclGetDate) _ANSI_ARGS_((char * p, unsigned long now, long zone, unsigned long * timePtr)); /* 27 */ + Tcl_Channel (*tclpGetDefaultStdChannel) _ANSI_ARGS_((int type)); /* 28 */ + Tcl_Obj * (*tclGetElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, int leaveErrorMsg)); /* 29 */ + void *reserved30; + char * (*tclGetExtension) _ANSI_ARGS_((char * name)); /* 31 */ + int (*tclGetFrame) _ANSI_ARGS_((Tcl_Interp * interp, char * str, CallFrame ** framePtrPtr)); /* 32 */ + TclCmdProcType (*tclGetInterpProc) _ANSI_ARGS_((void)); /* 33 */ + int (*tclGetIntForIndex) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int endValue, int * indexPtr)); /* 34 */ + Tcl_Obj * (*tclGetIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, int leaveErrorMsg)); /* 35 */ + int (*tclGetLong) _ANSI_ARGS_((Tcl_Interp * interp, char * str, long * longPtr)); /* 36 */ + int (*tclGetLoadedPackages) _ANSI_ARGS_((Tcl_Interp * interp, char * targetName)); /* 37 */ + int (*tclGetNamespaceForQualName) _ANSI_ARGS_((Tcl_Interp * interp, char * qualName, Namespace * cxtNsPtr, int flags, Namespace ** nsPtrPtr, Namespace ** altNsPtrPtr, Namespace ** actualCxtPtrPtr, char ** simpleNamePtr)); /* 38 */ + TclObjCmdProcType (*tclGetObjInterpProc) _ANSI_ARGS_((void)); /* 39 */ + int (*tclGetOpenMode) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * seekFlagPtr)); /* 40 */ + Tcl_Command (*tclGetOriginalCommand) _ANSI_ARGS_((Tcl_Command command)); /* 41 */ + char * (*tclpGetUserHome) _ANSI_ARGS_((CONST char * name, Tcl_DString * bufferPtr)); /* 42 */ + int (*tclGlobalInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, int flags)); /* 43 */ + int (*tclGuessPackageName) _ANSI_ARGS_((char * fileName, Tcl_DString * bufPtr)); /* 44 */ + int (*tclHideUnsafeCommands) _ANSI_ARGS_((Tcl_Interp * interp)); /* 45 */ + int (*tclInExit) _ANSI_ARGS_((void)); /* 46 */ + Tcl_Obj * (*tclIncrElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, long incrAmount)); /* 47 */ + Tcl_Obj * (*tclIncrIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, long incrAmount)); /* 48 */ + Tcl_Obj * (*tclIncrVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, long incrAmount, int part1NotParsed)); /* 49 */ + void (*tclInitCompiledLocals) _ANSI_ARGS_((Tcl_Interp * interp, CallFrame * framePtr, Namespace * nsPtr)); /* 50 */ + int (*tclInterpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 51 */ + int (*tclInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, int flags)); /* 52 */ + int (*tclInvokeObjectCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 53 */ + int (*tclInvokeStringCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 54 */ + Proc * (*tclIsProc) _ANSI_ARGS_((Command * cmdPtr)); /* 55 */ + void *reserved56; + void *reserved57; + Var * (*tclLookupVar) _ANSI_ARGS_((Tcl_Interp * interp, char * part1, char * part2, int flags, char * msg, int createPart1, int createPart2, Var ** arrayPtrPtr)); /* 58 */ + int (*tclpMatchFiles) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * dirPtr, char * pattern, char * tail)); /* 59 */ + int (*tclNeedSpace) _ANSI_ARGS_((char * start, char * end)); /* 60 */ + Tcl_Obj * (*tclNewProcBodyObj) _ANSI_ARGS_((Proc * procPtr)); /* 61 */ + int (*tclObjCommandComplete) _ANSI_ARGS_((Tcl_Obj * cmdPtr)); /* 62 */ + int (*tclObjInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 63 */ + int (*tclObjInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 64 */ + int (*tclObjInvokeGlobal) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 65 */ + int (*tclOpenFileChannelDeleteProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 66 */ + int (*tclOpenFileChannelInsertProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 67 */ + int (*tclpAccess) _ANSI_ARGS_((CONST char * path, int mode)); /* 68 */ + char * (*tclpAlloc) _ANSI_ARGS_((unsigned int size)); /* 69 */ + int (*tclpCopyFile) _ANSI_ARGS_((CONST char * source, CONST char * dest)); /* 70 */ + int (*tclpCopyDirectory) _ANSI_ARGS_((CONST char * source, CONST char * dest, Tcl_DString * errorPtr)); /* 71 */ + int (*tclpCreateDirectory) _ANSI_ARGS_((CONST char * path)); /* 72 */ + int (*tclpDeleteFile) _ANSI_ARGS_((CONST char * path)); /* 73 */ + void (*tclpFree) _ANSI_ARGS_((char * ptr)); /* 74 */ + unsigned long (*tclpGetClicks) _ANSI_ARGS_((void)); /* 75 */ + unsigned long (*tclpGetSeconds) _ANSI_ARGS_((void)); /* 76 */ + void (*tclpGetTime) _ANSI_ARGS_((Tcl_Time * time)); /* 77 */ + int (*tclpGetTimeZone) _ANSI_ARGS_((unsigned long time)); /* 78 */ + int (*tclpListVolumes) _ANSI_ARGS_((Tcl_Interp * interp)); /* 79 */ + Tcl_Channel (*tclpOpenFileChannel) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName, char * modeString, int permissions)); /* 80 */ + char * (*tclpRealloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 81 */ + int (*tclpRemoveDirectory) _ANSI_ARGS_((CONST char * path, int recursive, Tcl_DString * errorPtr)); /* 82 */ + int (*tclpRenameFile) _ANSI_ARGS_((CONST char * source, CONST char * dest)); /* 83 */ + void *reserved84; + void *reserved85; + void *reserved86; + void *reserved87; + char * (*tclPrecTraceProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, char * name1, char * name2, int flags)); /* 88 */ + int (*tclPreventAliasLoop) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Interp * cmdInterp, Tcl_Command cmd)); /* 89 */ + void *reserved90; + void (*tclProcCleanupProc) _ANSI_ARGS_((Proc * procPtr)); /* 91 */ + int (*tclProcCompileProc) _ANSI_ARGS_((Tcl_Interp * interp, Proc * procPtr, Tcl_Obj * bodyPtr, Namespace * nsPtr, CONST char * description, CONST char * procName)); /* 92 */ + void (*tclProcDeleteProc) _ANSI_ARGS_((ClientData clientData)); /* 93 */ + int (*tclProcInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv)); /* 94 */ + int (*tclpStat) _ANSI_ARGS_((CONST char * path, struct stat * buf)); /* 95 */ + int (*tclRenameCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * oldName, char * newName)); /* 96 */ + void (*tclResetShadowedCmdRefs) _ANSI_ARGS_((Tcl_Interp * interp, Command * newCmdPtr)); /* 97 */ + int (*tclServiceIdle) _ANSI_ARGS_((void)); /* 98 */ + Tcl_Obj * (*tclSetElementOfIndexedArray) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * elemPtr, Tcl_Obj * objPtr, int leaveErrorMsg)); /* 99 */ + Tcl_Obj * (*tclSetIndexedScalar) _ANSI_ARGS_((Tcl_Interp * interp, int localIndex, Tcl_Obj * objPtr, int leaveErrorMsg)); /* 100 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + char * (*tclSetPreInitScript) _ANSI_ARGS_((char * string)); /* 101 */ +#endif /* UNIX */ +#ifdef __WIN32__ + char * (*tclSetPreInitScript) _ANSI_ARGS_((char * string)); /* 101 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved101; +#endif /* MAC_TCL */ + void (*tclSetupEnv) _ANSI_ARGS_((Tcl_Interp * interp)); /* 102 */ + int (*tclSockGetPort) _ANSI_ARGS_((Tcl_Interp * interp, char * str, char * proto, int * portPtr)); /* 103 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved104; +#endif /* MAC_TCL */ + int (*tclStat) _ANSI_ARGS_((CONST char * path, struct stat * buf)); /* 105 */ + int (*tclStatDeleteProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 106 */ + int (*tclStatInsertProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 107 */ + void (*tclTeardownNamespace) _ANSI_ARGS_((Namespace * nsPtr)); /* 108 */ + int (*tclUpdateReturnInfo) _ANSI_ARGS_((Interp * iPtr)); /* 109 */ + void *reserved110; + void (*tcl_AddInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 111 */ + int (*tcl_AppendExportList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, Tcl_Obj * objPtr)); /* 112 */ + Tcl_Namespace * (*tcl_CreateNamespace) _ANSI_ARGS_((Tcl_Interp * interp, char * name, ClientData clientData, Tcl_NamespaceDeleteProc * deleteProc)); /* 113 */ + void (*tcl_DeleteNamespace) _ANSI_ARGS_((Tcl_Namespace * nsPtr)); /* 114 */ + int (*tcl_Export) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern, int resetListFirst)); /* 115 */ + Tcl_Command (*tcl_FindCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 116 */ + Tcl_Namespace * (*tcl_FindNamespace) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 117 */ + int (*tcl_GetInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_ResolverInfo * resInfo)); /* 118 */ + int (*tcl_GetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolverInfo * resInfo)); /* 119 */ + Tcl_Var (*tcl_FindNamespaceVar) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 120 */ + int (*tcl_ForgetImport) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern)); /* 121 */ + Tcl_Command (*tcl_GetCommandFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 122 */ + void (*tcl_GetCommandFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command, Tcl_Obj * objPtr)); /* 123 */ + Tcl_Namespace * (*tcl_GetCurrentNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 124 */ + Tcl_Namespace * (*tcl_GetGlobalNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 125 */ + void (*tcl_GetVariableFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Var variable, Tcl_Obj * objPtr)); /* 126 */ + int (*tcl_Import) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, char * pattern, int allowOverwrite)); /* 127 */ + void (*tcl_PopCallFrame) _ANSI_ARGS_((Tcl_Interp* interp)); /* 128 */ + int (*tcl_PushCallFrame) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_CallFrame * framePtr, Tcl_Namespace * nsPtr, int isProcCallFrame)); /* 129 */ + int (*tcl_RemoveInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, char * name)); /* 130 */ + void (*tcl_SetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 131 */ + int (*tclpHasSockets) _ANSI_ARGS_((Tcl_Interp * interp)); /* 132 */ + struct tm * (*tclpGetDate) _ANSI_ARGS_((TclpTime_t time, int useGMT)); /* 133 */ + size_t (*tclpStrftime) _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t)); /* 134 */ + int (*tclpCheckStackSpace) _ANSI_ARGS_((void)); /* 135 */ + void *reserved136; + int (*tclpChdir) _ANSI_ARGS_((CONST char * dirName)); /* 137 */ + char * (*tclGetEnv) _ANSI_ARGS_((CONST char * name, Tcl_DString * valuePtr)); /* 138 */ + int (*tclpLoadFile) _ANSI_ARGS_((Tcl_Interp * interp, char * fileName, char * sym1, char * sym2, Tcl_PackageInitProc ** proc1Ptr, Tcl_PackageInitProc ** proc2Ptr, ClientData * clientDataPtr)); /* 139 */ + int (*tclLooksLikeInt) _ANSI_ARGS_((char * bytes, int length)); /* 140 */ + char * (*tclpGetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 141 */ + int (*tclSetByteCodeFromAny) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CompileHookProc * hookProc, ClientData clientData)); /* 142 */ + int (*tclAddLiteralObj) _ANSI_ARGS_((struct CompileEnv * envPtr, Tcl_Obj * objPtr, LiteralEntry ** litPtrPtr)); /* 143 */ + void (*tclHideLiteral) _ANSI_ARGS_((Tcl_Interp * interp, struct CompileEnv * envPtr, int index)); /* 144 */ + struct AuxDataType * (*tclGetAuxDataType) _ANSI_ARGS_((char * typeName)); /* 145 */ + TclHandle (*tclHandleCreate) _ANSI_ARGS_((VOID * ptr)); /* 146 */ + void (*tclHandleFree) _ANSI_ARGS_((TclHandle handle)); /* 147 */ + TclHandle (*tclHandlePreserve) _ANSI_ARGS_((TclHandle handle)); /* 148 */ + void (*tclHandleRelease) _ANSI_ARGS_((TclHandle handle)); /* 149 */ + int (*tclRegAbout) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp re)); /* 150 */ + void (*tclRegExpRangeUniChar) _ANSI_ARGS_((Tcl_RegExp re, int index, int * startPtr, int * endPtr)); /* 151 */ + void (*tclSetLibraryPath) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 152 */ + Tcl_Obj * (*tclGetLibraryPath) _ANSI_ARGS_((void)); /* 153 */ + void *reserved154; + void *reserved155; + void (*tclRegError) _ANSI_ARGS_((Tcl_Interp * interp, char * msg, int status)); /* 156 */ + Var * (*tclVarTraceExists) _ANSI_ARGS_((Tcl_Interp * interp, char * varName)); /* 157 */ + void (*tclSetStartupScriptFileName) _ANSI_ARGS_((char * filename)); /* 158 */ + char * (*tclGetStartupScriptFileName) _ANSI_ARGS_((void)); /* 159 */ + int (*tclpMatchFilesTypes) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * dirPtr, char * pattern, char * tail, GlobTypeData * types)); /* 160 */ + int (*tclChannelTransform) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, Tcl_Obj * cmdObjPtr)); /* 161 */ + void (*tclChannelEventScriptInvoker) _ANSI_ARGS_((ClientData clientData, int flags)); /* 162 */ +} TclIntStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TclIntStubs *tclIntStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifndef TclAccess +#define TclAccess \ + (tclIntStubsPtr->tclAccess) /* 0 */ +#endif +#ifndef TclAccessDeleteProc +#define TclAccessDeleteProc \ + (tclIntStubsPtr->tclAccessDeleteProc) /* 1 */ +#endif +#ifndef TclAccessInsertProc +#define TclAccessInsertProc \ + (tclIntStubsPtr->tclAccessInsertProc) /* 2 */ +#endif +#ifndef TclAllocateFreeObjects +#define TclAllocateFreeObjects \ + (tclIntStubsPtr->tclAllocateFreeObjects) /* 3 */ +#endif +/* Slot 4 is reserved */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclCleanupChildren +#define TclCleanupChildren \ + (tclIntStubsPtr->tclCleanupChildren) /* 5 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclCleanupChildren +#define TclCleanupChildren \ + (tclIntStubsPtr->tclCleanupChildren) /* 5 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclCleanupCommand +#define TclCleanupCommand \ + (tclIntStubsPtr->tclCleanupCommand) /* 6 */ +#endif +#ifndef TclCopyAndCollapse +#define TclCopyAndCollapse \ + (tclIntStubsPtr->tclCopyAndCollapse) /* 7 */ +#endif +#ifndef TclCopyChannel +#define TclCopyChannel \ + (tclIntStubsPtr->tclCopyChannel) /* 8 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclCreatePipeline +#define TclCreatePipeline \ + (tclIntStubsPtr->tclCreatePipeline) /* 9 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclCreatePipeline +#define TclCreatePipeline \ + (tclIntStubsPtr->tclCreatePipeline) /* 9 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclCreateProc +#define TclCreateProc \ + (tclIntStubsPtr->tclCreateProc) /* 10 */ +#endif +#ifndef TclDeleteCompiledLocalVars +#define TclDeleteCompiledLocalVars \ + (tclIntStubsPtr->tclDeleteCompiledLocalVars) /* 11 */ +#endif +#ifndef TclDeleteVars +#define TclDeleteVars \ + (tclIntStubsPtr->tclDeleteVars) /* 12 */ +#endif +#ifndef TclDoGlob +#define TclDoGlob \ + (tclIntStubsPtr->tclDoGlob) /* 13 */ +#endif +#ifndef TclDumpMemoryInfo +#define TclDumpMemoryInfo \ + (tclIntStubsPtr->tclDumpMemoryInfo) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TclExprFloatError +#define TclExprFloatError \ + (tclIntStubsPtr->tclExprFloatError) /* 16 */ +#endif +#ifndef TclFileAttrsCmd +#define TclFileAttrsCmd \ + (tclIntStubsPtr->tclFileAttrsCmd) /* 17 */ +#endif +#ifndef TclFileCopyCmd +#define TclFileCopyCmd \ + (tclIntStubsPtr->tclFileCopyCmd) /* 18 */ +#endif +#ifndef TclFileDeleteCmd +#define TclFileDeleteCmd \ + (tclIntStubsPtr->tclFileDeleteCmd) /* 19 */ +#endif +#ifndef TclFileMakeDirsCmd +#define TclFileMakeDirsCmd \ + (tclIntStubsPtr->tclFileMakeDirsCmd) /* 20 */ +#endif +#ifndef TclFileRenameCmd +#define TclFileRenameCmd \ + (tclIntStubsPtr->tclFileRenameCmd) /* 21 */ +#endif +#ifndef TclFindElement +#define TclFindElement \ + (tclIntStubsPtr->tclFindElement) /* 22 */ +#endif +#ifndef TclFindProc +#define TclFindProc \ + (tclIntStubsPtr->tclFindProc) /* 23 */ +#endif +#ifndef TclFormatInt +#define TclFormatInt \ + (tclIntStubsPtr->tclFormatInt) /* 24 */ +#endif +#ifndef TclFreePackageInfo +#define TclFreePackageInfo \ + (tclIntStubsPtr->tclFreePackageInfo) /* 25 */ +#endif +/* Slot 26 is reserved */ +#ifndef TclGetDate +#define TclGetDate \ + (tclIntStubsPtr->tclGetDate) /* 27 */ +#endif +#ifndef TclpGetDefaultStdChannel +#define TclpGetDefaultStdChannel \ + (tclIntStubsPtr->tclpGetDefaultStdChannel) /* 28 */ +#endif +#ifndef TclGetElementOfIndexedArray +#define TclGetElementOfIndexedArray \ + (tclIntStubsPtr->tclGetElementOfIndexedArray) /* 29 */ +#endif +/* Slot 30 is reserved */ +#ifndef TclGetExtension +#define TclGetExtension \ + (tclIntStubsPtr->tclGetExtension) /* 31 */ +#endif +#ifndef TclGetFrame +#define TclGetFrame \ + (tclIntStubsPtr->tclGetFrame) /* 32 */ +#endif +#ifndef TclGetInterpProc +#define TclGetInterpProc \ + (tclIntStubsPtr->tclGetInterpProc) /* 33 */ +#endif +#ifndef TclGetIntForIndex +#define TclGetIntForIndex \ + (tclIntStubsPtr->tclGetIntForIndex) /* 34 */ +#endif +#ifndef TclGetIndexedScalar +#define TclGetIndexedScalar \ + (tclIntStubsPtr->tclGetIndexedScalar) /* 35 */ +#endif +#ifndef TclGetLong +#define TclGetLong \ + (tclIntStubsPtr->tclGetLong) /* 36 */ +#endif +#ifndef TclGetLoadedPackages +#define TclGetLoadedPackages \ + (tclIntStubsPtr->tclGetLoadedPackages) /* 37 */ +#endif +#ifndef TclGetNamespaceForQualName +#define TclGetNamespaceForQualName \ + (tclIntStubsPtr->tclGetNamespaceForQualName) /* 38 */ +#endif +#ifndef TclGetObjInterpProc +#define TclGetObjInterpProc \ + (tclIntStubsPtr->tclGetObjInterpProc) /* 39 */ +#endif +#ifndef TclGetOpenMode +#define TclGetOpenMode \ + (tclIntStubsPtr->tclGetOpenMode) /* 40 */ +#endif +#ifndef TclGetOriginalCommand +#define TclGetOriginalCommand \ + (tclIntStubsPtr->tclGetOriginalCommand) /* 41 */ +#endif +#ifndef TclpGetUserHome +#define TclpGetUserHome \ + (tclIntStubsPtr->tclpGetUserHome) /* 42 */ +#endif +#ifndef TclGlobalInvoke +#define TclGlobalInvoke \ + (tclIntStubsPtr->tclGlobalInvoke) /* 43 */ +#endif +#ifndef TclGuessPackageName +#define TclGuessPackageName \ + (tclIntStubsPtr->tclGuessPackageName) /* 44 */ +#endif +#ifndef TclHideUnsafeCommands +#define TclHideUnsafeCommands \ + (tclIntStubsPtr->tclHideUnsafeCommands) /* 45 */ +#endif +#ifndef TclInExit +#define TclInExit \ + (tclIntStubsPtr->tclInExit) /* 46 */ +#endif +#ifndef TclIncrElementOfIndexedArray +#define TclIncrElementOfIndexedArray \ + (tclIntStubsPtr->tclIncrElementOfIndexedArray) /* 47 */ +#endif +#ifndef TclIncrIndexedScalar +#define TclIncrIndexedScalar \ + (tclIntStubsPtr->tclIncrIndexedScalar) /* 48 */ +#endif +#ifndef TclIncrVar2 +#define TclIncrVar2 \ + (tclIntStubsPtr->tclIncrVar2) /* 49 */ +#endif +#ifndef TclInitCompiledLocals +#define TclInitCompiledLocals \ + (tclIntStubsPtr->tclInitCompiledLocals) /* 50 */ +#endif +#ifndef TclInterpInit +#define TclInterpInit \ + (tclIntStubsPtr->tclInterpInit) /* 51 */ +#endif +#ifndef TclInvoke +#define TclInvoke \ + (tclIntStubsPtr->tclInvoke) /* 52 */ +#endif +#ifndef TclInvokeObjectCommand +#define TclInvokeObjectCommand \ + (tclIntStubsPtr->tclInvokeObjectCommand) /* 53 */ +#endif +#ifndef TclInvokeStringCommand +#define TclInvokeStringCommand \ + (tclIntStubsPtr->tclInvokeStringCommand) /* 54 */ +#endif +#ifndef TclIsProc +#define TclIsProc \ + (tclIntStubsPtr->tclIsProc) /* 55 */ +#endif +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +#ifndef TclLookupVar +#define TclLookupVar \ + (tclIntStubsPtr->tclLookupVar) /* 58 */ +#endif +#ifndef TclpMatchFiles +#define TclpMatchFiles \ + (tclIntStubsPtr->tclpMatchFiles) /* 59 */ +#endif +#ifndef TclNeedSpace +#define TclNeedSpace \ + (tclIntStubsPtr->tclNeedSpace) /* 60 */ +#endif +#ifndef TclNewProcBodyObj +#define TclNewProcBodyObj \ + (tclIntStubsPtr->tclNewProcBodyObj) /* 61 */ +#endif +#ifndef TclObjCommandComplete +#define TclObjCommandComplete \ + (tclIntStubsPtr->tclObjCommandComplete) /* 62 */ +#endif +#ifndef TclObjInterpProc +#define TclObjInterpProc \ + (tclIntStubsPtr->tclObjInterpProc) /* 63 */ +#endif +#ifndef TclObjInvoke +#define TclObjInvoke \ + (tclIntStubsPtr->tclObjInvoke) /* 64 */ +#endif +#ifndef TclObjInvokeGlobal +#define TclObjInvokeGlobal \ + (tclIntStubsPtr->tclObjInvokeGlobal) /* 65 */ +#endif +#ifndef TclOpenFileChannelDeleteProc +#define TclOpenFileChannelDeleteProc \ + (tclIntStubsPtr->tclOpenFileChannelDeleteProc) /* 66 */ +#endif +#ifndef TclOpenFileChannelInsertProc +#define TclOpenFileChannelInsertProc \ + (tclIntStubsPtr->tclOpenFileChannelInsertProc) /* 67 */ +#endif +#ifndef TclpAccess +#define TclpAccess \ + (tclIntStubsPtr->tclpAccess) /* 68 */ +#endif +#ifndef TclpAlloc +#define TclpAlloc \ + (tclIntStubsPtr->tclpAlloc) /* 69 */ +#endif +#ifndef TclpCopyFile +#define TclpCopyFile \ + (tclIntStubsPtr->tclpCopyFile) /* 70 */ +#endif +#ifndef TclpCopyDirectory +#define TclpCopyDirectory \ + (tclIntStubsPtr->tclpCopyDirectory) /* 71 */ +#endif +#ifndef TclpCreateDirectory +#define TclpCreateDirectory \ + (tclIntStubsPtr->tclpCreateDirectory) /* 72 */ +#endif +#ifndef TclpDeleteFile +#define TclpDeleteFile \ + (tclIntStubsPtr->tclpDeleteFile) /* 73 */ +#endif +#ifndef TclpFree +#define TclpFree \ + (tclIntStubsPtr->tclpFree) /* 74 */ +#endif +#ifndef TclpGetClicks +#define TclpGetClicks \ + (tclIntStubsPtr->tclpGetClicks) /* 75 */ +#endif +#ifndef TclpGetSeconds +#define TclpGetSeconds \ + (tclIntStubsPtr->tclpGetSeconds) /* 76 */ +#endif +#ifndef TclpGetTime +#define TclpGetTime \ + (tclIntStubsPtr->tclpGetTime) /* 77 */ +#endif +#ifndef TclpGetTimeZone +#define TclpGetTimeZone \ + (tclIntStubsPtr->tclpGetTimeZone) /* 78 */ +#endif +#ifndef TclpListVolumes +#define TclpListVolumes \ + (tclIntStubsPtr->tclpListVolumes) /* 79 */ +#endif +#ifndef TclpOpenFileChannel +#define TclpOpenFileChannel \ + (tclIntStubsPtr->tclpOpenFileChannel) /* 80 */ +#endif +#ifndef TclpRealloc +#define TclpRealloc \ + (tclIntStubsPtr->tclpRealloc) /* 81 */ +#endif +#ifndef TclpRemoveDirectory +#define TclpRemoveDirectory \ + (tclIntStubsPtr->tclpRemoveDirectory) /* 82 */ +#endif +#ifndef TclpRenameFile +#define TclpRenameFile \ + (tclIntStubsPtr->tclpRenameFile) /* 83 */ +#endif +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +#ifndef TclPrecTraceProc +#define TclPrecTraceProc \ + (tclIntStubsPtr->tclPrecTraceProc) /* 88 */ +#endif +#ifndef TclPreventAliasLoop +#define TclPreventAliasLoop \ + (tclIntStubsPtr->tclPreventAliasLoop) /* 89 */ +#endif +/* Slot 90 is reserved */ +#ifndef TclProcCleanupProc +#define TclProcCleanupProc \ + (tclIntStubsPtr->tclProcCleanupProc) /* 91 */ +#endif +#ifndef TclProcCompileProc +#define TclProcCompileProc \ + (tclIntStubsPtr->tclProcCompileProc) /* 92 */ +#endif +#ifndef TclProcDeleteProc +#define TclProcDeleteProc \ + (tclIntStubsPtr->tclProcDeleteProc) /* 93 */ +#endif +#ifndef TclProcInterpProc +#define TclProcInterpProc \ + (tclIntStubsPtr->tclProcInterpProc) /* 94 */ +#endif +#ifndef TclpStat +#define TclpStat \ + (tclIntStubsPtr->tclpStat) /* 95 */ +#endif +#ifndef TclRenameCommand +#define TclRenameCommand \ + (tclIntStubsPtr->tclRenameCommand) /* 96 */ +#endif +#ifndef TclResetShadowedCmdRefs +#define TclResetShadowedCmdRefs \ + (tclIntStubsPtr->tclResetShadowedCmdRefs) /* 97 */ +#endif +#ifndef TclServiceIdle +#define TclServiceIdle \ + (tclIntStubsPtr->tclServiceIdle) /* 98 */ +#endif +#ifndef TclSetElementOfIndexedArray +#define TclSetElementOfIndexedArray \ + (tclIntStubsPtr->tclSetElementOfIndexedArray) /* 99 */ +#endif +#ifndef TclSetIndexedScalar +#define TclSetIndexedScalar \ + (tclIntStubsPtr->tclSetIndexedScalar) /* 100 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclSetPreInitScript +#define TclSetPreInitScript \ + (tclIntStubsPtr->tclSetPreInitScript) /* 101 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclSetPreInitScript +#define TclSetPreInitScript \ + (tclIntStubsPtr->tclSetPreInitScript) /* 101 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclSetupEnv +#define TclSetupEnv \ + (tclIntStubsPtr->tclSetupEnv) /* 102 */ +#endif +#ifndef TclSockGetPort +#define TclSockGetPort \ + (tclIntStubsPtr->tclSockGetPort) /* 103 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclSockMinimumBuffers +#define TclSockMinimumBuffers \ + (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclSockMinimumBuffers +#define TclSockMinimumBuffers \ + (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclStat +#define TclStat \ + (tclIntStubsPtr->tclStat) /* 105 */ +#endif +#ifndef TclStatDeleteProc +#define TclStatDeleteProc \ + (tclIntStubsPtr->tclStatDeleteProc) /* 106 */ +#endif +#ifndef TclStatInsertProc +#define TclStatInsertProc \ + (tclIntStubsPtr->tclStatInsertProc) /* 107 */ +#endif +#ifndef TclTeardownNamespace +#define TclTeardownNamespace \ + (tclIntStubsPtr->tclTeardownNamespace) /* 108 */ +#endif +#ifndef TclUpdateReturnInfo +#define TclUpdateReturnInfo \ + (tclIntStubsPtr->tclUpdateReturnInfo) /* 109 */ +#endif +/* Slot 110 is reserved */ +#ifndef Tcl_AddInterpResolvers +#define Tcl_AddInterpResolvers \ + (tclIntStubsPtr->tcl_AddInterpResolvers) /* 111 */ +#endif +#ifndef Tcl_AppendExportList +#define Tcl_AppendExportList \ + (tclIntStubsPtr->tcl_AppendExportList) /* 112 */ +#endif +#ifndef Tcl_CreateNamespace +#define Tcl_CreateNamespace \ + (tclIntStubsPtr->tcl_CreateNamespace) /* 113 */ +#endif +#ifndef Tcl_DeleteNamespace +#define Tcl_DeleteNamespace \ + (tclIntStubsPtr->tcl_DeleteNamespace) /* 114 */ +#endif +#ifndef Tcl_Export +#define Tcl_Export \ + (tclIntStubsPtr->tcl_Export) /* 115 */ +#endif +#ifndef Tcl_FindCommand +#define Tcl_FindCommand \ + (tclIntStubsPtr->tcl_FindCommand) /* 116 */ +#endif +#ifndef Tcl_FindNamespace +#define Tcl_FindNamespace \ + (tclIntStubsPtr->tcl_FindNamespace) /* 117 */ +#endif +#ifndef Tcl_GetInterpResolvers +#define Tcl_GetInterpResolvers \ + (tclIntStubsPtr->tcl_GetInterpResolvers) /* 118 */ +#endif +#ifndef Tcl_GetNamespaceResolvers +#define Tcl_GetNamespaceResolvers \ + (tclIntStubsPtr->tcl_GetNamespaceResolvers) /* 119 */ +#endif +#ifndef Tcl_FindNamespaceVar +#define Tcl_FindNamespaceVar \ + (tclIntStubsPtr->tcl_FindNamespaceVar) /* 120 */ +#endif +#ifndef Tcl_ForgetImport +#define Tcl_ForgetImport \ + (tclIntStubsPtr->tcl_ForgetImport) /* 121 */ +#endif +#ifndef Tcl_GetCommandFromObj +#define Tcl_GetCommandFromObj \ + (tclIntStubsPtr->tcl_GetCommandFromObj) /* 122 */ +#endif +#ifndef Tcl_GetCommandFullName +#define Tcl_GetCommandFullName \ + (tclIntStubsPtr->tcl_GetCommandFullName) /* 123 */ +#endif +#ifndef Tcl_GetCurrentNamespace +#define Tcl_GetCurrentNamespace \ + (tclIntStubsPtr->tcl_GetCurrentNamespace) /* 124 */ +#endif +#ifndef Tcl_GetGlobalNamespace +#define Tcl_GetGlobalNamespace \ + (tclIntStubsPtr->tcl_GetGlobalNamespace) /* 125 */ +#endif +#ifndef Tcl_GetVariableFullName +#define Tcl_GetVariableFullName \ + (tclIntStubsPtr->tcl_GetVariableFullName) /* 126 */ +#endif +#ifndef Tcl_Import +#define Tcl_Import \ + (tclIntStubsPtr->tcl_Import) /* 127 */ +#endif +#ifndef Tcl_PopCallFrame +#define Tcl_PopCallFrame \ + (tclIntStubsPtr->tcl_PopCallFrame) /* 128 */ +#endif +#ifndef Tcl_PushCallFrame +#define Tcl_PushCallFrame \ + (tclIntStubsPtr->tcl_PushCallFrame) /* 129 */ +#endif +#ifndef Tcl_RemoveInterpResolvers +#define Tcl_RemoveInterpResolvers \ + (tclIntStubsPtr->tcl_RemoveInterpResolvers) /* 130 */ +#endif +#ifndef Tcl_SetNamespaceResolvers +#define Tcl_SetNamespaceResolvers \ + (tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */ +#endif +#ifndef TclpHasSockets +#define TclpHasSockets \ + (tclIntStubsPtr->tclpHasSockets) /* 132 */ +#endif +#ifndef TclpGetDate +#define TclpGetDate \ + (tclIntStubsPtr->tclpGetDate) /* 133 */ +#endif +#ifndef TclpStrftime +#define TclpStrftime \ + (tclIntStubsPtr->tclpStrftime) /* 134 */ +#endif +#ifndef TclpCheckStackSpace +#define TclpCheckStackSpace \ + (tclIntStubsPtr->tclpCheckStackSpace) /* 135 */ +#endif +/* Slot 136 is reserved */ +#ifndef TclpChdir +#define TclpChdir \ + (tclIntStubsPtr->tclpChdir) /* 137 */ +#endif +#ifndef TclGetEnv +#define TclGetEnv \ + (tclIntStubsPtr->tclGetEnv) /* 138 */ +#endif +#ifndef TclpLoadFile +#define TclpLoadFile \ + (tclIntStubsPtr->tclpLoadFile) /* 139 */ +#endif +#ifndef TclLooksLikeInt +#define TclLooksLikeInt \ + (tclIntStubsPtr->tclLooksLikeInt) /* 140 */ +#endif +#ifndef TclpGetCwd +#define TclpGetCwd \ + (tclIntStubsPtr->tclpGetCwd) /* 141 */ +#endif +#ifndef TclSetByteCodeFromAny +#define TclSetByteCodeFromAny \ + (tclIntStubsPtr->tclSetByteCodeFromAny) /* 142 */ +#endif +#ifndef TclAddLiteralObj +#define TclAddLiteralObj \ + (tclIntStubsPtr->tclAddLiteralObj) /* 143 */ +#endif +#ifndef TclHideLiteral +#define TclHideLiteral \ + (tclIntStubsPtr->tclHideLiteral) /* 144 */ +#endif +#ifndef TclGetAuxDataType +#define TclGetAuxDataType \ + (tclIntStubsPtr->tclGetAuxDataType) /* 145 */ +#endif +#ifndef TclHandleCreate +#define TclHandleCreate \ + (tclIntStubsPtr->tclHandleCreate) /* 146 */ +#endif +#ifndef TclHandleFree +#define TclHandleFree \ + (tclIntStubsPtr->tclHandleFree) /* 147 */ +#endif +#ifndef TclHandlePreserve +#define TclHandlePreserve \ + (tclIntStubsPtr->tclHandlePreserve) /* 148 */ +#endif +#ifndef TclHandleRelease +#define TclHandleRelease \ + (tclIntStubsPtr->tclHandleRelease) /* 149 */ +#endif +#ifndef TclRegAbout +#define TclRegAbout \ + (tclIntStubsPtr->tclRegAbout) /* 150 */ +#endif +#ifndef TclRegExpRangeUniChar +#define TclRegExpRangeUniChar \ + (tclIntStubsPtr->tclRegExpRangeUniChar) /* 151 */ +#endif +#ifndef TclSetLibraryPath +#define TclSetLibraryPath \ + (tclIntStubsPtr->tclSetLibraryPath) /* 152 */ +#endif +#ifndef TclGetLibraryPath +#define TclGetLibraryPath \ + (tclIntStubsPtr->tclGetLibraryPath) /* 153 */ +#endif +/* Slot 154 is reserved */ +/* Slot 155 is reserved */ +#ifndef TclRegError +#define TclRegError \ + (tclIntStubsPtr->tclRegError) /* 156 */ +#endif +#ifndef TclVarTraceExists +#define TclVarTraceExists \ + (tclIntStubsPtr->tclVarTraceExists) /* 157 */ +#endif +#ifndef TclSetStartupScriptFileName +#define TclSetStartupScriptFileName \ + (tclIntStubsPtr->tclSetStartupScriptFileName) /* 158 */ +#endif +#ifndef TclGetStartupScriptFileName +#define TclGetStartupScriptFileName \ + (tclIntStubsPtr->tclGetStartupScriptFileName) /* 159 */ +#endif +#ifndef TclpMatchFilesTypes +#define TclpMatchFilesTypes \ + (tclIntStubsPtr->tclpMatchFilesTypes) /* 160 */ +#endif +#ifndef TclChannelTransform +#define TclChannelTransform \ + (tclIntStubsPtr->tclChannelTransform) /* 161 */ +#endif +#ifndef TclChannelEventScriptInvoker +#define TclChannelEventScriptInvoker \ + (tclIntStubsPtr->tclChannelEventScriptInvoker) /* 162 */ +#endif + +#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TCLINTDECLS */ diff --git a/Utilities/TclTk/internals/tk8.3/tkInt.h b/Utilities/TclTk/internals/tk8.3/tkInt.h new file mode 100644 index 0000000..cb1557e --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkInt.h @@ -0,0 +1,1097 @@ +/* + * tkInt.h -- + * + * Declarations for things used internally by the Tk + * procedures but not exported outside the module. + * + * Copyright (c) 1990-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1998 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: $Id: tkInt.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKINT +#define _TKINT + +#ifndef _TK +#include "tk.h" +#endif +#ifndef _TCL +#include "tcl.h" +#endif +#ifndef _TKPORT +#include +#endif + +/* + * Opaque type declarations: + */ + +typedef struct TkColormap TkColormap; +typedef struct TkGrabEvent TkGrabEvent; +typedef struct TkpCursor_ *TkpCursor; +typedef struct TkRegion_ *TkRegion; +typedef struct TkStressedCmap TkStressedCmap; +typedef struct TkBindInfo_ *TkBindInfo; + +/* + * Procedure types. + */ + +typedef int (TkBindEvalProc) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, XEvent *eventPtr, Tk_Window tkwin, + KeySym keySym)); +typedef void (TkBindFreeProc) _ANSI_ARGS_((ClientData clientData)); +typedef Window (TkClassCreateProc) _ANSI_ARGS_((Tk_Window tkwin, + Window parent, ClientData instanceData)); +typedef void (TkClassGeometryProc) _ANSI_ARGS_((ClientData instanceData)); +typedef void (TkClassModalProc) _ANSI_ARGS_((Tk_Window tkwin, + XEvent *eventPtr)); + + +/* + * Widget class procedures used to implement platform specific widget + * behavior. + */ + +typedef struct TkClassProcs { + TkClassCreateProc *createProc; + /* Procedure to invoke when the + platform-dependent window needs to be + created. */ + TkClassGeometryProc *geometryProc; + /* Procedure to invoke when the geometry of a + window needs to be recalculated as a result + of some change in the system. */ + TkClassModalProc *modalProc; + /* Procedure to invoke after all bindings on a + widget have been triggered in order to + handle a modal loop. */ +} TkClassProcs; + +/* + * One of the following structures is maintained for each cursor in + * use in the system. This structure is used by tkCursor.c and the + * various system specific cursor files. + */ + +typedef struct TkCursor { + Tk_Cursor cursor; /* System specific identifier for cursor. */ + Display *display; /* Display containing cursor. Needed for + * disposal and retrieval of cursors. */ + int resourceRefCount; /* Number of active uses of this cursor (each + * active use corresponds to a call to + * Tk_AllocPreserveFromObj or Tk_Preserve). + * If this count is 0, then this structure + * is no longer valid and it isn't present + * in a hash table: it is being kept around + * only because there are objects referring + * to it. The structure is freed when + * resourceRefCount and objRefCount are + * both 0. */ + int objRefCount; /* Number of Tcl objects that reference + * this structure.. */ + Tcl_HashTable *otherTable; /* Second table (other than idTable) used + * to index this entry. */ + Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure + * (needed when deleting). */ + Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure + * (needed when deleting). */ + struct TkCursor *nextPtr; /* Points to the next TkCursor structure with + * the same name. Cursors with the same + * name but different displays are chained + * together off a single hash table entry. */ +} TkCursor; + +/* + * One of the following structures is maintained for each display + * containing a window managed by Tk. In part, the structure is + * used to store thread-specific data, since each thread will have + * its own TkDisplay structure. + */ + +typedef struct TkDisplay { + Display *display; /* Xlib's info about display. */ + struct TkDisplay *nextPtr; /* Next in list of all displays. */ + char *name; /* Name of display (with any screen + * identifier removed). Malloc-ed. */ + Time lastEventTime; /* Time of last event received for this + * display. */ + + /* + * Information used primarily by tk3d.c: + */ + + int borderInit; /* 0 means borderTable needs initializing. */ + Tcl_HashTable borderTable; /* Maps from color name to TkBorder + * structure. */ + + /* + * Information used by tkAtom.c only: + */ + + int atomInit; /* 0 means stuff below hasn't been + * initialized yet. */ + Tcl_HashTable nameTable; /* Maps from names to Atom's. */ + Tcl_HashTable atomTable; /* Maps from Atom's back to names. */ + + /* + * Information used primarily by tkBind.c: + */ + + int bindInfoStale; /* Non-zero means the variables in this + * part of the structure are potentially + * incorrect and should be recomputed. */ + unsigned int modeModMask; /* Has one bit set to indicate the modifier + * corresponding to "mode shift". If no + * such modifier, than this is zero. */ + unsigned int metaModMask; /* Has one bit set to indicate the modifier + * corresponding to the "Meta" key. If no + * such modifier, then this is zero. */ + unsigned int altModMask; /* Has one bit set to indicate the modifier + * corresponding to the "Meta" key. If no + * such modifier, then this is zero. */ + enum {LU_IGNORE, LU_CAPS, LU_SHIFT} lockUsage; + /* Indicates how to interpret lock modifier. */ + int numModKeyCodes; /* Number of entries in modKeyCodes array + * below. */ + KeyCode *modKeyCodes; /* Pointer to an array giving keycodes for + * all of the keys that have modifiers + * associated with them. Malloc'ed, but + * may be NULL. */ + + /* + * Information used by tkBitmap.c only: + */ + + int bitmapInit; /* 0 means tables above need initializing. */ + int bitmapAutoNumber; /* Used to number bitmaps. */ + Tcl_HashTable bitmapNameTable; + /* Maps from name of bitmap to the first + * TkBitmap record for that name. */ + Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap + * structure for the bitmap. */ + Tcl_HashTable bitmapDataTable; + /* Used by Tk_GetBitmapFromData to map from + * a collection of in-core data about a + * bitmap to a reference giving an auto- + * matically-generated name for the bitmap. */ + + /* + * Information used by tkCanvas.c only: + */ + + int numIdSearches; + int numSlowSearches; + + /* + * Used by tkColor.c only: + */ + + int colorInit; /* 0 means color module needs initializing. */ + TkStressedCmap *stressPtr; /* First in list of colormaps that have + * filled up, so we have to pick an + * approximate color. */ + Tcl_HashTable colorNameTable; + /* Maps from color name to TkColor structure + * for that color. */ + Tcl_HashTable colorValueTable; + /* Maps from integer RGB values to TkColor + * structures. */ + + /* + * Used by tkCursor.c only: + */ + + int cursorInit; /* 0 means cursor module need initializing. */ + Tcl_HashTable cursorNameTable; + /* Maps from a string name to a cursor to the + * TkCursor record for the cursor. */ + Tcl_HashTable cursorDataTable; + /* Maps from a collection of in-core data + * about a cursor to a TkCursor structure. */ + Tcl_HashTable cursorIdTable; + /* Maps from a cursor id to the TkCursor + * structure for the cursor. */ + char cursorString[20]; /* Used to store a cursor id string. */ + Font cursorFont; /* Font to use for standard cursors. + * None means font not loaded yet. */ + + /* + * Information used by tkError.c only: + */ + + struct TkErrorHandler *errorPtr; + /* First in list of error handlers + * for this display. NULL means + * no handlers exist at present. */ + int deleteCount; /* Counts # of handlers deleted since + * last time inactive handlers were + * garbage-collected. When this number + * gets big, handlers get cleaned up. */ + + /* + * Used by tkEvent.c only: + */ + + struct TkWindowEvent *delayedMotionPtr; + /* Points to a malloc-ed motion event + * whose processing has been delayed in + * the hopes that another motion event + * will come along right away and we can + * merge the two of them together. NULL + * means that there is no delayed motion + * event. */ + + /* + * Information used by tkFocus.c only: + */ + + int focusDebug; /* 1 means collect focus debugging + * statistics. */ + struct TkWindow *implicitWinPtr; + /* If the focus arrived at a toplevel window + * implicitly via an Enter event (rather + * than via a FocusIn event), this points + * to the toplevel window. Otherwise it is + * NULL. */ + struct TkWindow *focusPtr; /* Points to the window on this display that + * should be receiving keyboard events. When + * multiple applications on the display have + * the focus, this will refer to the + * innermost window in the innermost + * application. This information isn't used + * under Unix or Windows, but it's needed on + * the Macintosh. */ + + /* + * Information used by tkGC.c only: + */ + + Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure + * describing a GC with those values. */ + Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */ + int gcInit; /* 0 means the tables below need + * initializing. */ + + /* + * Information used by tkGeometry.c only: + */ + + Tcl_HashTable maintainHashTable; + /* Hash table that maps from a master's + * Tk_Window token to a list of slaves + * managed by that master. */ + int geomInit; + + /* + * Information used by tkGet.c only: + */ + + Tcl_HashTable uidTable; /* Stores all Tk_Uid used in a thread. */ + int uidInit; /* 0 means uidTable needs initializing. */ + + /* + * Information used by tkGrab.c only: + */ + + struct TkWindow *grabWinPtr; + /* Window in which the pointer is currently + * grabbed, or NULL if none. */ + struct TkWindow *eventualGrabWinPtr; + /* Value that grabWinPtr will have once the + * grab event queue (below) has been + * completely emptied. */ + struct TkWindow *buttonWinPtr; + /* Window in which first mouse button was + * pressed while grab was in effect, or NULL + * if no such press in effect. */ + struct TkWindow *serverWinPtr; + /* If no application contains the pointer then + * this is NULL. Otherwise it contains the + * last window for which we've gotten an + * Enter or Leave event from the server (i.e. + * the last window known to have contained + * the pointer). Doesn't reflect events + * that were synthesized in tkGrab.c. */ + TkGrabEvent *firstGrabEventPtr; + /* First in list of enter/leave events + * synthesized by grab code. These events + * must be processed in order before any other + * events are processed. NULL means no such + * events. */ + TkGrabEvent *lastGrabEventPtr; + /* Last in list of synthesized events, or NULL + * if list is empty. */ + int grabFlags; /* Miscellaneous flag values. See definitions + * in tkGrab.c. */ + + /* + * Information used by tkGrid.c only: + */ + + int gridInit; /* 0 means table below needs initializing. */ + Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to + * corresponding Grid structures. */ + + /* + * Information used by tkImage.c only: + */ + + int imageId; /* Value used to number image ids. */ + + /* + * Information used by tkMacWinMenu.c only: + */ + + int postCommandGeneration; + + /* + * Information used by tkOption.c only. + */ + + + + /* + * Information used by tkPack.c only. + */ + + int packInit; /* 0 means table below needs initializing. */ + Tcl_HashTable packerHashTable; + /* Maps from Tk_Window tokens to + * corresponding Packer structures. */ + + + /* + * Information used by tkPlace.c only. + */ + + int placeInit; /* 0 means tables below need initializing. */ + Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master + * structure for the window, if it exists. */ + Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave + * structure for the window, if it exists. */ + + /* + * Information used by tkSelect.c and tkClipboard.c only: + */ + + struct TkSelectionInfo *selectionInfoPtr; + /* First in list of selection information + * records. Each entry contains information + * about the current owner of a particular + * selection on this display. */ + Atom multipleAtom; /* Atom for MULTIPLE. None means + * selection stuff isn't initialized. */ + Atom incrAtom; /* Atom for INCR. */ + Atom targetsAtom; /* Atom for TARGETS. */ + Atom timestampAtom; /* Atom for TIMESTAMP. */ + Atom textAtom; /* Atom for TEXT. */ + Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */ + Atom applicationAtom; /* Atom for TK_APPLICATION. */ + Atom windowAtom; /* Atom for TK_WINDOW. */ + Atom clipboardAtom; /* Atom for CLIPBOARD. */ + + Tk_Window clipWindow; /* Window used for clipboard ownership and to + * retrieve selections between processes. NULL + * means clipboard info hasn't been + * initialized. */ + int clipboardActive; /* 1 means we currently own the clipboard + * selection, 0 means we don't. */ + struct TkMainInfo *clipboardAppPtr; + /* Last application that owned clipboard. */ + struct TkClipboardTarget *clipTargetPtr; + /* First in list of clipboard type information + * records. Each entry contains information + * about the buffers for a given selection + * target. */ + + /* + * Information used by tkSend.c only: + */ + + Tk_Window commTkwin; /* Window used for communication + * between interpreters during "send" + * commands. NULL means send info hasn't + * been initialized yet. */ + Atom commProperty; /* X's name for comm property. */ + Atom registryProperty; /* X's name for property containing + * registry of interpreter names. */ + Atom appNameProperty; /* X's name for property used to hold the + * application name on each comm window. */ + + /* + * Information used by tkXId.c only: + */ + + struct TkIdStack *idStackPtr; + /* First in list of chunks of free resource + * identifiers, or NULL if there are no free + * resources. */ + XID (*defaultAllocProc) _ANSI_ARGS_((Display *display)); + /* Default resource allocator for display. */ + struct TkIdStack *windowStackPtr; + /* First in list of chunks of window + * identifers that can't be reused right + * now. */ + int idCleanupScheduled; /* 1 means a call to WindowIdCleanup has + * already been scheduled, 0 means it + * hasn't. */ + + /* + * Information used by tkUnixWm.c and tkWinWm.c only: + */ + + int wmTracing; /* Used to enable or disable tracing in + * this module. If tracing is enabled, + * then information is printed on + * standard output about interesting + * interactions with the window manager. */ + struct TkWmInfo *firstWmPtr; /* Points to first top-level window. */ + struct TkWmInfo *foregroundWmPtr; + /* Points to the foreground window. */ + + /* + * Information maintained by tkWindow.c for use later on by tkXId.c: + */ + + + int destroyCount; /* Number of Tk_DestroyWindow operations + * in progress. */ + unsigned long lastDestroyRequest; + /* Id of most recent XDestroyWindow request; + * can re-use ids in windowStackPtr when + * server has seen this request and event + * queue is empty. */ + + /* + * Information used by tkVisual.c only: + */ + + TkColormap *cmapPtr; /* First in list of all non-default colormaps + * allocated for this display. */ + + /* + * Miscellaneous information: + */ + +#ifdef TK_USE_INPUT_METHODS + XIM inputMethod; /* Input method for this display */ +#endif /* TK_USE_INPUT_METHODS */ + Tcl_HashTable winTable; /* Maps from X window ids to TkWindow ptrs. */ + + int refCount; /* Reference count of how many Tk applications + * are using this display. Used to clean up + * the display when we no longer have any + * Tk applications using it. + */ + /* + * The following field were all added for Tk8.3 + */ + int mouseButtonState; /* current mouse button state for this + * display */ + int warpInProgress; + Window warpWindow; + int warpX; + int warpY; + int useInputMethods; /* Whether to use input methods */ +} TkDisplay; + +/* + * One of the following structures exists for each error handler + * created by a call to Tk_CreateErrorHandler. The structure + * is managed by tkError.c. + */ + +typedef struct TkErrorHandler { + TkDisplay *dispPtr; /* Display to which handler applies. */ + unsigned long firstRequest; /* Only errors with serial numbers + * >= to this are considered. */ + unsigned long lastRequest; /* Only errors with serial numbers + * <= to this are considered. This + * field is filled in when XUnhandle + * is called. -1 means XUnhandle + * hasn't been called yet. */ + int error; /* Consider only errors with this + * error_code (-1 means consider + * all errors). */ + int request; /* Consider only errors with this + * major request code (-1 means + * consider all major codes). */ + int minorCode; /* Consider only errors with this + * minor request code (-1 means + * consider all minor codes). */ + Tk_ErrorProc *errorProc; /* Procedure to invoke when a matching + * error occurs. NULL means just ignore + * errors. */ + ClientData clientData; /* Arbitrary value to pass to + * errorProc. */ + struct TkErrorHandler *nextPtr; + /* Pointer to next older handler for + * this display, or NULL for end of + * list. */ +} TkErrorHandler; + + + + +/* + * One of the following structures exists for each event handler + * created by calling Tk_CreateEventHandler. This information + * is used by tkEvent.c only. + */ + +typedef struct TkEventHandler { + unsigned long mask; /* Events for which to invoke + * proc. */ + Tk_EventProc *proc; /* Procedure to invoke when an event + * in mask occurs. */ + ClientData clientData; /* Argument to pass to proc. */ + struct TkEventHandler *nextPtr; + /* Next in list of handlers + * associated with window (NULL means + * end of list). */ +} TkEventHandler; + +/* + * Tk keeps one of the following data structures for each main + * window (created by a call to TkCreateMainWindow). It stores + * information that is shared by all of the windows associated + * with a particular main window. + */ + +typedef struct TkMainInfo { + int refCount; /* Number of windows whose "mainPtr" fields + * point here. When this becomes zero, can + * free up the structure (the reference + * count is zero because windows can get + * deleted in almost any order; the main + * window isn't necessarily the last one + * deleted). */ + struct TkWindow *winPtr; /* Pointer to main window. */ + Tcl_Interp *interp; /* Interpreter associated with application. */ + Tcl_HashTable nameTable; /* Hash table mapping path names to TkWindow + * structs for all windows related to this + * main window. Managed by tkWindow.c. */ + Tk_BindingTable bindingTable; + /* Used in conjunction with "bind" command + * to bind events to Tcl commands. */ + TkBindInfo bindInfo; /* Information used by tkBind.c on a per + * application basis. */ + struct TkFontInfo *fontInfoPtr; + /* Information used by tkFont.c on a per + * application basis. */ + + /* + * Information used only by tkFocus.c and tk*Embed.c: + */ + + struct TkToplevelFocusInfo *tlFocusPtr; + /* First in list of records containing focus + * information for each top-level in the + * application. Used only by tkFocus.c. */ + struct TkDisplayFocusInfo *displayFocusPtr; + /* First in list of records containing focus + * information for each display that this + * application has ever used. Used only + * by tkFocus.c. */ + + struct ElArray *optionRootPtr; + /* Top level of option hierarchy for this + * main window. NULL means uninitialized. + * Managed by tkOption.c. */ + Tcl_HashTable imageTable; /* Maps from image names to Tk_ImageMaster + * structures. Managed by tkImage.c. */ + int strictMotif; /* This is linked to the tk_strictMotif + * global variable. */ + struct TkMainInfo *nextPtr; /* Next in list of all main windows managed by + * this process. */ +} TkMainInfo; + +/* + * Tk keeps the following data structure for each of it's builtin + * bitmaps. This structure is only used by tkBitmap.c and other + * platform specific bitmap files. + */ + +typedef struct { + char *source; /* Bits for bitmap. */ + int width, height; /* Dimensions of bitmap. */ + int native; /* 0 means generic (X style) bitmap, + * 1 means native style bitmap. */ +} TkPredefBitmap; + +/* + * Tk keeps one of the following structures for each window. + * Some of the information (like size and location) is a shadow + * of information managed by the X server, and some is special + * information used here, such as event and geometry management + * information. This information is (mostly) managed by tkWindow.c. + * WARNING: the declaration below must be kept consistent with the + * Tk_FakeWin structure in tk.h. If you change one, be sure to + * change the other!! + */ + +typedef struct TkWindow { + + /* + * Structural information: + */ + + Display *display; /* Display containing window. */ + TkDisplay *dispPtr; /* Tk's information about display + * for window. */ + int screenNum; /* Index of screen for window, among all + * those for dispPtr. */ + Visual *visual; /* Visual to use for window. If not default, + * MUST be set before X window is created. */ + int depth; /* Number of bits/pixel. */ + Window window; /* X's id for window. NULL means window + * hasn't actually been created yet, or it's + * been deleted. */ + struct TkWindow *childList; /* First in list of child windows, + * or NULL if no children. List is in + * stacking order, lowest window first.*/ + struct TkWindow *lastChildPtr; + /* Last in list of child windows (highest + * in stacking order), or NULL if no + * children. */ + struct TkWindow *parentPtr; /* Pointer to parent window (logical + * parent, not necessarily X parent). NULL + * means either this is the main window, or + * the window's parent has already been + * deleted. */ + struct TkWindow *nextPtr; /* Next higher sibling (in stacking order) + * in list of children with same parent. NULL + * means end of list. */ + TkMainInfo *mainPtr; /* Information shared by all windows + * associated with a particular main + * window. NULL means this window is + * a rogue that isn't associated with + * any application (at present, this + * only happens for the dummy windows + * used for "send" communication). */ + + /* + * Name and type information for the window: + */ + + char *pathName; /* Path name of window (concatenation + * of all names between this window and + * its top-level ancestor). This is a + * pointer into an entry in + * mainPtr->nameTable. NULL means that + * the window hasn't been completely + * created yet. */ + Tk_Uid nameUid; /* Name of the window within its parent + * (unique within the parent). */ + Tk_Uid classUid; /* Class of the window. NULL means window + * hasn't been given a class yet. */ + + /* + * Geometry and other attributes of window. This information + * may not be updated on the server immediately; stuff that + * hasn't been reflected in the server yet is called "dirty". + * At present, information can be dirty only if the window + * hasn't yet been created. + */ + + XWindowChanges changes; /* Geometry and other info about + * window. */ + unsigned int dirtyChanges; /* Bits indicate fields of "changes" + * that are dirty. */ + XSetWindowAttributes atts; /* Current attributes of window. */ + unsigned long dirtyAtts; /* Bits indicate fields of "atts" + * that are dirty. */ + + unsigned int flags; /* Various flag values: these are all + * defined in tk.h (confusing, but they're + * needed there for some query macros). */ + + /* + * Information kept by the event manager (tkEvent.c): + */ + + TkEventHandler *handlerList;/* First in list of event handlers + * declared for this window, or + * NULL if none. */ +#ifdef TK_USE_INPUT_METHODS + XIC inputContext; /* Input context (for input methods). */ +#endif /* TK_USE_INPUT_METHODS */ + + /* + * Information used for event bindings (see "bind" and "bindtags" + * commands in tkCmds.c): + */ + + ClientData *tagPtr; /* Points to array of tags used for bindings + * on this window. Each tag is a Tk_Uid. + * Malloc'ed. NULL means no tags. */ + int numTags; /* Number of tags at *tagPtr. */ + + /* + * Information used by tkOption.c to manage options for the + * window. + */ + + int optionLevel; /* -1 means no option information is + * currently cached for this window. + * Otherwise this gives the level in + * the option stack at which info is + * cached. */ + /* + * Information used by tkSelect.c to manage the selection. + */ + + struct TkSelHandler *selHandlerList; + /* First in list of handlers for + * returning the selection in various + * forms. */ + + /* + * Information used by tkGeometry.c for geometry management. + */ + + Tk_GeomMgr *geomMgrPtr; /* Information about geometry manager for + * this window. */ + ClientData geomData; /* Argument for geometry manager procedures. */ + int reqWidth, reqHeight; /* Arguments from last call to + * Tk_GeometryRequest, or 0's if + * Tk_GeometryRequest hasn't been + * called. */ + int internalBorderWidth; /* Width of internal border of window + * (0 means no internal border). Geometry + * managers should not normally place children + * on top of the border. */ + + /* + * Information maintained by tkWm.c for window manager communication. + */ + + struct TkWmInfo *wmInfoPtr; /* For top-level windows (and also + * for special Unix menubar and wrapper + * windows), points to structure with + * wm-related info (see tkWm.c). For + * other windows, this is NULL. */ + + /* + * Information used by widget classes. + */ + + TkClassProcs *classProcsPtr; + ClientData instanceData; + + /* + * Platform specific information private to each port. + */ + + struct TkWindowPrivate *privatePtr; +} TkWindow; + +/* + * The following structure is used as a two way map between integers + * and strings, usually to map between an internal C representation + * and the strings used in Tcl. + */ + +typedef struct TkStateMap { + int numKey; /* Integer representation of a value. */ + char *strKey; /* String representation of a value. */ +} TkStateMap; + +/* + * This structure is used by the Mac and Window porting layers as + * the internal representation of a clip_mask in a GC. + */ + +typedef struct TkpClipMask { + int type; /* One of TKP_CLIP_PIXMAP or TKP_CLIP_REGION */ + union { + Pixmap pixmap; + TkRegion region; + } value; +} TkpClipMask; + +#define TKP_CLIP_PIXMAP 0 +#define TKP_CLIP_REGION 1 + +/* + * Pointer to first entry in list of all displays currently known. + */ + +extern TkDisplay *tkDisplayList; + +/* + * Return values from TkGrabState: + */ + +#define TK_GRAB_NONE 0 +#define TK_GRAB_IN_TREE 1 +#define TK_GRAB_ANCESTOR 2 +#define TK_GRAB_EXCLUDED 3 + +/* + * The macro below is used to modify a "char" value (e.g. by casting + * it to an unsigned character) so that it can be used safely with + * macros such as isspace. + */ + +#define UCHAR(c) ((unsigned char) (c)) + +/* + * The following symbol is used in the mode field of FocusIn events + * generated by an embedded application to request the input focus from + * its container. + */ + +#define EMBEDDED_APP_WANTS_FOCUS (NotifyNormal + 20) + +/* + * The following special modifier mask bits are defined, to indicate + * logical modifiers such as Meta and Alt that may float among the + * actual modifier bits. + */ + +#define META_MASK (AnyModifier<<1) +#define ALT_MASK (AnyModifier<<2) + +/* + * Miscellaneous variables shared among Tk modules but not exported + * to the outside world: + */ + +extern Tk_SmoothMethod tkBezierSmoothMethod; +extern Tk_ImageType tkBitmapImageType; +extern Tk_PhotoImageFormat tkImgFmtGIF; +extern void (*tkHandleEventProc) _ANSI_ARGS_(( + XEvent* eventPtr)); +extern Tk_PhotoImageFormat tkImgFmtPPM; +extern TkMainInfo *tkMainWindowList; +extern Tk_ImageType tkPhotoImageType; +extern Tcl_HashTable tkPredefBitmapTable; +extern int tkSendSerial; + +#include "tkIntDecls.h" + +#ifdef BUILD_tk +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * Internal procedures shared among Tk modules but not exported + * to the outside world: + */ + +EXTERN int Tk_AfterCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_BellObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_BindCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_BindtagsCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ButtonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_CanvasObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_CheckbuttonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ClipboardCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ChooseColorObjCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_ChooseDirectoryObjCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_ChooseFontObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_DestroyObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_EntryObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_EventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FileeventCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_FrameObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FocusObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FontObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GetOpenFileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GetSaveFileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GrabCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_GridCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ImageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_LabelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ListboxObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_LowerObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MenubuttonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MessageBoxObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MessageCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_OptionObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_PackCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_PlaceCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_RadiobuttonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_RaiseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ScaleObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ScrollbarCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_SelectionCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_SendCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_SendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_TextCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_TkObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_TkwaitCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_ToplevelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_WinfoObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_WmCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); + +void TkConsolePrint _ANSI_ARGS_((Tcl_Interp *interp, + int devId, char *buffer, long size)); + +EXTERN void TkEventInit _ANSI_ARGS_((void)); + +EXTERN int TkCreateMenuCmd _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); + +EXTERN int TkpTestembedCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int TkCanvasGetCoordObj _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Canvas canvas, Tcl_Obj *obj, + double *doublePtr)); +EXTERN int TkCanvasDashParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkCanvasDashPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkGetDoublePixels _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Window tkwin, CONST char *string, + double *doublePtr)); +EXTERN int TkOffsetParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkOffsetPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkOrientParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, + char *widgRec, int offset)); +EXTERN char * TkOrientPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkPixelParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkPixelPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkPostscriptImage _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Window tkwin, Tk_PostscriptInfo psInfo, + XImage *ximage, int x, int y, int width, + int height)); +EXTERN int TkSmoothParseProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *recordPtr, int offset)); +EXTERN char * TkSmoothPrintProc _ANSI_ARGS_((ClientData clientData, + Tk_Window tkwin, char *recordPtr, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkStateParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, + char *widgRec, int offset)); +EXTERN char * TkStatePrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkTileParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkTilePrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); + +/* + * Unsupported commands. + */ +EXTERN int TkUnsupported1Cmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINT */ diff --git a/Utilities/TclTk/internals/tk8.3/tkIntDecls.h b/Utilities/TclTk/internals/tk8.3/tkIntDecls.h new file mode 100644 index 0000000..2e38468 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkIntDecls.h @@ -0,0 +1,1483 @@ +/* + * tkIntDecls.h -- + * + * This file contains the declarations for all unsupported + * functions that are exported by the Tk library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkIntDecls.h,v 1.1 2004/01/07 22:32:38 barre Exp $ + */ + +#ifndef _TKINTDECLS +#define _TKINTDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tkInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +/* 0 */ +EXTERN TkWindow * TkAllocWindow _ANSI_ARGS_((TkDisplay * dispPtr, + int screenNum, TkWindow * parentPtr)); +/* 1 */ +EXTERN void TkBezierPoints _ANSI_ARGS_((double control[], + int numSteps, double * coordPtr)); +/* 2 */ +EXTERN void TkBezierScreenPoints _ANSI_ARGS_((Tk_Canvas canvas, + double control[], int numSteps, + XPoint * xPointPtr)); +/* 3 */ +EXTERN void TkBindDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 4 */ +EXTERN void TkBindEventProc _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 5 */ +EXTERN void TkBindFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 6 */ +EXTERN void TkBindInit _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 7 */ +EXTERN void TkChangeEventWindow _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * winPtr)); +/* 8 */ +EXTERN int TkClipInit _ANSI_ARGS_((Tcl_Interp * interp, + TkDisplay * dispPtr)); +/* 9 */ +EXTERN void TkComputeAnchor _ANSI_ARGS_((Tk_Anchor anchor, + Tk_Window tkwin, int padX, int padY, + int innerWidth, int innerHeight, int * xPtr, + int * yPtr)); +/* 10 */ +EXTERN int TkCopyAndGlobalEval _ANSI_ARGS_((Tcl_Interp * interp, + char * script)); +/* 11 */ +EXTERN unsigned long TkCreateBindingProcedure _ANSI_ARGS_(( + Tcl_Interp * interp, + Tk_BindingTable bindingTable, + ClientData object, char * eventString, + TkBindEvalProc * evalProc, + TkBindFreeProc * freeProc, + ClientData clientData)); +/* 12 */ +EXTERN TkCursor * TkCreateCursorFromData _ANSI_ARGS_((Tk_Window tkwin, + char * source, char * mask, int width, + int height, int xHot, int yHot, XColor fg, + XColor bg)); +/* 13 */ +EXTERN int TkCreateFrame _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, char ** argv, + int toplevel, char * appName)); +/* 14 */ +EXTERN Tk_Window TkCreateMainWindow _ANSI_ARGS_((Tcl_Interp * interp, + char * screenName, char * baseName)); +/* 15 */ +EXTERN Time TkCurrentTime _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 16 */ +EXTERN void TkDeleteAllImages _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 17 */ +EXTERN void TkDoConfigureNotify _ANSI_ARGS_((TkWindow * winPtr)); +/* 18 */ +EXTERN void TkDrawInsetFocusHighlight _ANSI_ARGS_(( + Tk_Window tkwin, GC gc, int width, + Drawable drawable, int padding)); +/* 19 */ +EXTERN void TkEventDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 20 */ +EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas, + double * coordPtr, int numPoints, + Display * display, Drawable drawable, GC gc, + GC outlineGC)); +/* 21 */ +EXTERN int TkFindStateNum _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * option, + CONST TkStateMap * mapPtr, + CONST char * strKey)); +/* 22 */ +EXTERN char * TkFindStateString _ANSI_ARGS_(( + CONST TkStateMap * mapPtr, int numKey)); +/* 23 */ +EXTERN void TkFocusDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 24 */ +EXTERN int TkFocusFilterEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 25 */ +EXTERN TkWindow * TkFocusKeyEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 26 */ +EXTERN void TkFontPkgInit _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 27 */ +EXTERN void TkFontPkgFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 28 */ +EXTERN void TkFreeBindingTags _ANSI_ARGS_((TkWindow * winPtr)); +/* 29 */ +EXTERN void TkpFreeCursor _ANSI_ARGS_((TkCursor * cursorPtr)); +/* 30 */ +EXTERN char * TkGetBitmapData _ANSI_ARGS_((Tcl_Interp * interp, + char * string, char * fileName, + int * widthPtr, int * heightPtr, + int * hotXPtr, int * hotYPtr)); +/* 31 */ +EXTERN void TkGetButtPoints _ANSI_ARGS_((double p1[], + double p2[], double width, int project, + double m1[], double m2[])); +/* 32 */ +EXTERN TkCursor * TkGetCursorByName _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, Tk_Uid string)); +/* 33 */ +EXTERN char * TkGetDefaultScreenName _ANSI_ARGS_(( + Tcl_Interp * interp, char * screenName)); +/* 34 */ +EXTERN TkDisplay * TkGetDisplay _ANSI_ARGS_((Display * display)); +/* 35 */ +EXTERN int TkGetDisplayOf _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], + Tk_Window * tkwinPtr)); +/* 36 */ +EXTERN TkWindow * TkGetFocusWin _ANSI_ARGS_((TkWindow * winPtr)); +/* 37 */ +EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin)); +/* 38 */ +EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[], + double p2[], double p3[], double width, + double m1[], double m2[])); +/* 39 */ +EXTERN void TkGetPointerCoords _ANSI_ARGS_((Tk_Window tkwin, + int * xPtr, int * yPtr)); +/* 40 */ +EXTERN void TkGetServerInfo _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin)); +/* 41 */ +EXTERN void TkGrabDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 42 */ +EXTERN int TkGrabState _ANSI_ARGS_((TkWindow * winPtr)); +/* 43 */ +EXTERN void TkIncludePoint _ANSI_ARGS_((Tk_Item * itemPtr, + double * pointPtr)); +/* 44 */ +EXTERN void TkInOutEvents _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * sourcePtr, TkWindow * destPtr, + int leaveType, int enterType, + Tcl_QueuePosition position)); +/* 45 */ +EXTERN void TkInstallFrameMenu _ANSI_ARGS_((Tk_Window tkwin)); +/* 46 */ +EXTERN char * TkKeysymToString _ANSI_ARGS_((KeySym keysym)); +/* 47 */ +EXTERN int TkLineToArea _ANSI_ARGS_((double end1Ptr[], + double end2Ptr[], double rectPtr[])); +/* 48 */ +EXTERN double TkLineToPoint _ANSI_ARGS_((double end1Ptr[], + double end2Ptr[], double pointPtr[])); +/* 49 */ +EXTERN int TkMakeBezierCurve _ANSI_ARGS_((Tk_Canvas canvas, + double * pointPtr, int numPoints, + int numSteps, XPoint xPoints[], + double dblPoints[])); +/* 50 */ +EXTERN void TkMakeBezierPostscript _ANSI_ARGS_(( + Tcl_Interp * interp, Tk_Canvas canvas, + double * pointPtr, int numPoints)); +/* 51 */ +EXTERN void TkOptionClassChanged _ANSI_ARGS_((TkWindow * winPtr)); +/* 52 */ +EXTERN void TkOptionDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 53 */ +EXTERN int TkOvalToArea _ANSI_ARGS_((double * ovalPtr, + double * rectPtr)); +/* 54 */ +EXTERN double TkOvalToPoint _ANSI_ARGS_((double ovalPtr[], + double width, int filled, double pointPtr[])); +/* 55 */ +EXTERN int TkpChangeFocus _ANSI_ARGS_((TkWindow * winPtr, + int force)); +/* 56 */ +EXTERN void TkpCloseDisplay _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 57 */ +EXTERN void TkpClaimFocus _ANSI_ARGS_((TkWindow * topLevelPtr, + int force)); +/* 58 */ +EXTERN void TkpDisplayWarning _ANSI_ARGS_((char * msg, + char * title)); +/* 59 */ +EXTERN void TkpGetAppName _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * name)); +/* 60 */ +EXTERN TkWindow * TkpGetOtherWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 61 */ +EXTERN TkWindow * TkpGetWrapperWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 62 */ +EXTERN int TkpInit _ANSI_ARGS_((Tcl_Interp * interp)); +/* 63 */ +EXTERN void TkpInitializeMenuBindings _ANSI_ARGS_(( + Tcl_Interp * interp, + Tk_BindingTable bindingTable)); +/* 64 */ +EXTERN void TkpMakeContainer _ANSI_ARGS_((Tk_Window tkwin)); +/* 65 */ +EXTERN void TkpMakeMenuWindow _ANSI_ARGS_((Tk_Window tkwin, + int transient)); +/* 66 */ +EXTERN Window TkpMakeWindow _ANSI_ARGS_((TkWindow * winPtr, + Window parent)); +/* 67 */ +EXTERN void TkpMenuNotifyToplevelCreate _ANSI_ARGS_(( + Tcl_Interp * interp1, char * menuName)); +/* 68 */ +EXTERN TkDisplay * TkpOpenDisplay _ANSI_ARGS_((char * display_name)); +/* 69 */ +EXTERN int TkPointerEvent _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * winPtr)); +/* 70 */ +EXTERN int TkPolygonToArea _ANSI_ARGS_((double * polyPtr, + int numPoints, double * rectPtr)); +/* 71 */ +EXTERN double TkPolygonToPoint _ANSI_ARGS_((double * polyPtr, + int numPoints, double * pointPtr)); +/* 72 */ +EXTERN int TkPositionInTree _ANSI_ARGS_((TkWindow * winPtr, + TkWindow * treePtr)); +/* 73 */ +EXTERN void TkpRedirectKeyEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 74 */ +EXTERN void TkpSetMainMenubar _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * menuName)); +/* 75 */ +EXTERN int TkpUseWindow _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * string)); +/* 76 */ +EXTERN int TkpWindowWasRecentlyDeleted _ANSI_ARGS_((Window win, + TkDisplay * dispPtr)); +/* 77 */ +EXTERN void TkQueueEventForAllChildren _ANSI_ARGS_(( + TkWindow * winPtr, XEvent * eventPtr)); +/* 78 */ +EXTERN int TkReadBitmapFile _ANSI_ARGS_((Display* display, + Drawable d, CONST char* filename, + unsigned int* width_return, + unsigned int* height_return, + Pixmap* bitmap_return, int* x_hot_return, + int* y_hot_return)); +/* 79 */ +EXTERN int TkScrollWindow _ANSI_ARGS_((Tk_Window tkwin, GC gc, + int x, int y, int width, int height, int dx, + int dy, TkRegion damageRgn)); +/* 80 */ +EXTERN void TkSelDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 81 */ +EXTERN void TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin, + XEvent * eventPtr)); +/* 82 */ +EXTERN void TkSelInit _ANSI_ARGS_((Tk_Window tkwin)); +/* 83 */ +EXTERN void TkSelPropProc _ANSI_ARGS_((XEvent * eventPtr)); +/* 84 */ +EXTERN void TkSetClassProcs _ANSI_ARGS_((Tk_Window tkwin, + TkClassProcs * procs, + ClientData instanceData)); +/* 85 */ +EXTERN void TkSetWindowMenuBar _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * oldMenuName, + char * menuName)); +/* 86 */ +EXTERN KeySym TkStringToKeysym _ANSI_ARGS_((char * name)); +/* 87 */ +EXTERN int TkThickPolyLineToArea _ANSI_ARGS_((double * coordPtr, + int numPoints, double width, int capStyle, + int joinStyle, double * rectPtr)); +/* 88 */ +EXTERN void TkWmAddToColormapWindows _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 89 */ +EXTERN void TkWmDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 90 */ +EXTERN TkWindow * TkWmFocusToplevel _ANSI_ARGS_((TkWindow * winPtr)); +/* 91 */ +EXTERN void TkWmMapWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 92 */ +EXTERN void TkWmNewWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 93 */ +EXTERN void TkWmProtocolEventProc _ANSI_ARGS_((TkWindow * winPtr, + XEvent * evenvPtr)); +/* 94 */ +EXTERN void TkWmRemoveFromColormapWindows _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 95 */ +EXTERN void TkWmRestackToplevel _ANSI_ARGS_((TkWindow * winPtr, + int aboveBelow, TkWindow * otherPtr)); +/* 96 */ +EXTERN void TkWmSetClass _ANSI_ARGS_((TkWindow * winPtr)); +/* 97 */ +EXTERN void TkWmUnmapWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 98 */ +EXTERN Tcl_Obj * TkDebugBitmap _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 99 */ +EXTERN Tcl_Obj * TkDebugBorder _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 100 */ +EXTERN Tcl_Obj * TkDebugCursor _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 101 */ +EXTERN Tcl_Obj * TkDebugColor _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 102 */ +EXTERN Tcl_Obj * TkDebugConfig _ANSI_ARGS_((Tcl_Interp * interp, + Tk_OptionTable table)); +/* 103 */ +EXTERN Tcl_Obj * TkDebugFont _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 104 */ +EXTERN int TkFindStateNumObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * optionPtr, + CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr)); +/* 105 */ +EXTERN Tcl_HashTable * TkGetBitmapPredefTable _ANSI_ARGS_((void)); +/* 106 */ +EXTERN TkDisplay * TkGetDisplayList _ANSI_ARGS_((void)); +/* 107 */ +EXTERN TkMainInfo * TkGetMainInfoList _ANSI_ARGS_((void)); +/* 108 */ +EXTERN int TkGetWindowFromObj _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, Tcl_Obj * objPtr, + Tk_Window * windowPtr)); +/* 109 */ +EXTERN char * TkpGetString _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr, Tcl_DString * dsPtr)); +/* 110 */ +EXTERN void TkpGetSubFonts _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Font tkfont)); +/* 111 */ +EXTERN Tcl_Obj * TkpGetSystemDefault _ANSI_ARGS_((Tk_Window tkwin, + char * dbName, char * className)); +/* 112 */ +EXTERN void TkpMenuThreadInit _ANSI_ARGS_((void)); +#ifdef __WIN32__ +/* 113 */ +EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, + XRectangle* rect_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 113 */ +EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, + XRectangle* rect_return)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 114 */ +EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 114 */ +EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 115 */ +EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 115 */ +EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 116 */ +EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 116 */ +EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 117 */ +EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, + int y, unsigned int width, + unsigned int height)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 117 */ +EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, + int y, unsigned int width, + unsigned int height)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 118 */ +EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc, + TkRegion rgn)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 118 */ +EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc, + TkRegion rgn)); +#endif /* MAC_TCL */ +#ifdef __WIN32__ +/* 119 */ +EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect, + TkRegion src, TkRegion dr_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 119 */ +EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect, + TkRegion src, TkRegion dr_return)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 120 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 121 */ +EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display, + char * source)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 122 */ +EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 123 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 124 */ +EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display * display, + CONST char * name, int * width, int * height)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 125 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 126 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 127 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 128 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +#endif /* MAC_TCL */ +/* Slot 129 is reserved */ +#ifdef MAC_TCL +/* 130 */ +EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 131 */ +EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, + Window window, unsigned int state)); +#endif /* MAC_TCL */ +/* Slot 132 is reserved */ +#ifdef MAC_TCL +/* 133 */ +EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); +#endif /* MAC_TCL */ +#ifdef MAC_TCL +/* 134 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +#endif /* MAC_TCL */ +/* 135 */ +EXTERN void TkpDrawHighlightBorder _ANSI_ARGS_((Tk_Window tkwin, + GC fgGC, GC bgGC, int highlightWidth, + Drawable drawable)); +/* 136 */ +EXTERN void TkSetFocusWin _ANSI_ARGS_((TkWindow * winPtr, + int force)); +/* 137 */ +EXTERN void TkpSetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin, + KeySym keySym, XEvent * eventPtr)); +/* 138 */ +EXTERN KeySym TkpGetKeySym _ANSI_ARGS_((TkDisplay * dispPtr, + XEvent * eventPtr)); +/* 139 */ +EXTERN void TkpInitKeymapInfo _ANSI_ARGS_((TkDisplay * dispPtr)); + +typedef struct TkIntStubs { + int magic; + struct TkIntStubHooks *hooks; + + TkWindow * (*tkAllocWindow) _ANSI_ARGS_((TkDisplay * dispPtr, int screenNum, TkWindow * parentPtr)); /* 0 */ + void (*tkBezierPoints) _ANSI_ARGS_((double control[], int numSteps, double * coordPtr)); /* 1 */ + void (*tkBezierScreenPoints) _ANSI_ARGS_((Tk_Canvas canvas, double control[], int numSteps, XPoint * xPointPtr)); /* 2 */ + void (*tkBindDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 3 */ + void (*tkBindEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 4 */ + void (*tkBindFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 5 */ + void (*tkBindInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 6 */ + void (*tkChangeEventWindow) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 7 */ + int (*tkClipInit) _ANSI_ARGS_((Tcl_Interp * interp, TkDisplay * dispPtr)); /* 8 */ + void (*tkComputeAnchor) _ANSI_ARGS_((Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int * xPtr, int * yPtr)); /* 9 */ + int (*tkCopyAndGlobalEval) _ANSI_ARGS_((Tcl_Interp * interp, char * script)); /* 10 */ + unsigned long (*tkCreateBindingProcedure) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object, char * eventString, TkBindEvalProc * evalProc, TkBindFreeProc * freeProc, ClientData clientData)); /* 11 */ + TkCursor * (*tkCreateCursorFromData) _ANSI_ARGS_((Tk_Window tkwin, char * source, char * mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg)); /* 12 */ + int (*tkCreateFrame) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv, int toplevel, char * appName)); /* 13 */ + Tk_Window (*tkCreateMainWindow) _ANSI_ARGS_((Tcl_Interp * interp, char * screenName, char * baseName)); /* 14 */ + Time (*tkCurrentTime) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 15 */ + void (*tkDeleteAllImages) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 16 */ + void (*tkDoConfigureNotify) _ANSI_ARGS_((TkWindow * winPtr)); /* 17 */ + void (*tkDrawInsetFocusHighlight) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding)); /* 18 */ + void (*tkEventDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 19 */ + void (*tkFillPolygon) _ANSI_ARGS_((Tk_Canvas canvas, double * coordPtr, int numPoints, Display * display, Drawable drawable, GC gc, GC outlineGC)); /* 20 */ + int (*tkFindStateNum) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * option, CONST TkStateMap * mapPtr, CONST char * strKey)); /* 21 */ + char * (*tkFindStateString) _ANSI_ARGS_((CONST TkStateMap * mapPtr, int numKey)); /* 22 */ + void (*tkFocusDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 23 */ + int (*tkFocusFilterEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 24 */ + TkWindow * (*tkFocusKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 25 */ + void (*tkFontPkgInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 26 */ + void (*tkFontPkgFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 27 */ + void (*tkFreeBindingTags) _ANSI_ARGS_((TkWindow * winPtr)); /* 28 */ + void (*tkpFreeCursor) _ANSI_ARGS_((TkCursor * cursorPtr)); /* 29 */ + char * (*tkGetBitmapData) _ANSI_ARGS_((Tcl_Interp * interp, char * string, char * fileName, int * widthPtr, int * heightPtr, int * hotXPtr, int * hotYPtr)); /* 30 */ + void (*tkGetButtPoints) _ANSI_ARGS_((double p1[], double p2[], double width, int project, double m1[], double m2[])); /* 31 */ + TkCursor * (*tkGetCursorByName) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_Uid string)); /* 32 */ + char * (*tkGetDefaultScreenName) _ANSI_ARGS_((Tcl_Interp * interp, char * screenName)); /* 33 */ + TkDisplay * (*tkGetDisplay) _ANSI_ARGS_((Display * display)); /* 34 */ + int (*tkGetDisplayOf) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], Tk_Window * tkwinPtr)); /* 35 */ + TkWindow * (*tkGetFocusWin) _ANSI_ARGS_((TkWindow * winPtr)); /* 36 */ + int (*tkGetInterpNames) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 37 */ + int (*tkGetMiterPoints) _ANSI_ARGS_((double p1[], double p2[], double p3[], double width, double m1[], double m2[])); /* 38 */ + void (*tkGetPointerCoords) _ANSI_ARGS_((Tk_Window tkwin, int * xPtr, int * yPtr)); /* 39 */ + void (*tkGetServerInfo) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 40 */ + void (*tkGrabDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 41 */ + int (*tkGrabState) _ANSI_ARGS_((TkWindow * winPtr)); /* 42 */ + void (*tkIncludePoint) _ANSI_ARGS_((Tk_Item * itemPtr, double * pointPtr)); /* 43 */ + void (*tkInOutEvents) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * sourcePtr, TkWindow * destPtr, int leaveType, int enterType, Tcl_QueuePosition position)); /* 44 */ + void (*tkInstallFrameMenu) _ANSI_ARGS_((Tk_Window tkwin)); /* 45 */ + char * (*tkKeysymToString) _ANSI_ARGS_((KeySym keysym)); /* 46 */ + int (*tkLineToArea) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double rectPtr[])); /* 47 */ + double (*tkLineToPoint) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double pointPtr[])); /* 48 */ + int (*tkMakeBezierCurve) _ANSI_ARGS_((Tk_Canvas canvas, double * pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[])); /* 49 */ + void (*tkMakeBezierPostscript) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, double * pointPtr, int numPoints)); /* 50 */ + void (*tkOptionClassChanged) _ANSI_ARGS_((TkWindow * winPtr)); /* 51 */ + void (*tkOptionDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 52 */ + int (*tkOvalToArea) _ANSI_ARGS_((double * ovalPtr, double * rectPtr)); /* 53 */ + double (*tkOvalToPoint) _ANSI_ARGS_((double ovalPtr[], double width, int filled, double pointPtr[])); /* 54 */ + int (*tkpChangeFocus) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 55 */ + void (*tkpCloseDisplay) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 56 */ + void (*tkpClaimFocus) _ANSI_ARGS_((TkWindow * topLevelPtr, int force)); /* 57 */ + void (*tkpDisplayWarning) _ANSI_ARGS_((char * msg, char * title)); /* 58 */ + void (*tkpGetAppName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * name)); /* 59 */ + TkWindow * (*tkpGetOtherWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 60 */ + TkWindow * (*tkpGetWrapperWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 61 */ + int (*tkpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 62 */ + void (*tkpInitializeMenuBindings) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable)); /* 63 */ + void (*tkpMakeContainer) _ANSI_ARGS_((Tk_Window tkwin)); /* 64 */ + void (*tkpMakeMenuWindow) _ANSI_ARGS_((Tk_Window tkwin, int transient)); /* 65 */ + Window (*tkpMakeWindow) _ANSI_ARGS_((TkWindow * winPtr, Window parent)); /* 66 */ + void (*tkpMenuNotifyToplevelCreate) _ANSI_ARGS_((Tcl_Interp * interp1, char * menuName)); /* 67 */ + TkDisplay * (*tkpOpenDisplay) _ANSI_ARGS_((char * display_name)); /* 68 */ + int (*tkPointerEvent) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 69 */ + int (*tkPolygonToArea) _ANSI_ARGS_((double * polyPtr, int numPoints, double * rectPtr)); /* 70 */ + double (*tkPolygonToPoint) _ANSI_ARGS_((double * polyPtr, int numPoints, double * pointPtr)); /* 71 */ + int (*tkPositionInTree) _ANSI_ARGS_((TkWindow * winPtr, TkWindow * treePtr)); /* 72 */ + void (*tkpRedirectKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 73 */ + void (*tkpSetMainMenubar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * menuName)); /* 74 */ + int (*tkpUseWindow) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * string)); /* 75 */ + int (*tkpWindowWasRecentlyDeleted) _ANSI_ARGS_((Window win, TkDisplay * dispPtr)); /* 76 */ + void (*tkQueueEventForAllChildren) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 77 */ + int (*tkReadBitmapFile) _ANSI_ARGS_((Display* display, Drawable d, CONST char* filename, unsigned int* width_return, unsigned int* height_return, Pixmap* bitmap_return, int* x_hot_return, int* y_hot_return)); /* 78 */ + int (*tkScrollWindow) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn)); /* 79 */ + void (*tkSelDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 80 */ + void (*tkSelEventProc) _ANSI_ARGS_((Tk_Window tkwin, XEvent * eventPtr)); /* 81 */ + void (*tkSelInit) _ANSI_ARGS_((Tk_Window tkwin)); /* 82 */ + void (*tkSelPropProc) _ANSI_ARGS_((XEvent * eventPtr)); /* 83 */ + void (*tkSetClassProcs) _ANSI_ARGS_((Tk_Window tkwin, TkClassProcs * procs, ClientData instanceData)); /* 84 */ + void (*tkSetWindowMenuBar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * oldMenuName, char * menuName)); /* 85 */ + KeySym (*tkStringToKeysym) _ANSI_ARGS_((char * name)); /* 86 */ + int (*tkThickPolyLineToArea) _ANSI_ARGS_((double * coordPtr, int numPoints, double width, int capStyle, int joinStyle, double * rectPtr)); /* 87 */ + void (*tkWmAddToColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 88 */ + void (*tkWmDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 89 */ + TkWindow * (*tkWmFocusToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 90 */ + void (*tkWmMapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 91 */ + void (*tkWmNewWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 92 */ + void (*tkWmProtocolEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * evenvPtr)); /* 93 */ + void (*tkWmRemoveFromColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 94 */ + void (*tkWmRestackToplevel) _ANSI_ARGS_((TkWindow * winPtr, int aboveBelow, TkWindow * otherPtr)); /* 95 */ + void (*tkWmSetClass) _ANSI_ARGS_((TkWindow * winPtr)); /* 96 */ + void (*tkWmUnmapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 97 */ + Tcl_Obj * (*tkDebugBitmap) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 98 */ + Tcl_Obj * (*tkDebugBorder) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 99 */ + Tcl_Obj * (*tkDebugCursor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 100 */ + Tcl_Obj * (*tkDebugColor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 101 */ + Tcl_Obj * (*tkDebugConfig) _ANSI_ARGS_((Tcl_Interp * interp, Tk_OptionTable table)); /* 102 */ + Tcl_Obj * (*tkDebugFont) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 103 */ + int (*tkFindStateNumObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * optionPtr, CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr)); /* 104 */ + Tcl_HashTable * (*tkGetBitmapPredefTable) _ANSI_ARGS_((void)); /* 105 */ + TkDisplay * (*tkGetDisplayList) _ANSI_ARGS_((void)); /* 106 */ + TkMainInfo * (*tkGetMainInfoList) _ANSI_ARGS_((void)); /* 107 */ + int (*tkGetWindowFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr, Tk_Window * windowPtr)); /* 108 */ + char * (*tkpGetString) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr, Tcl_DString * dsPtr)); /* 109 */ + void (*tkpGetSubFonts) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Font tkfont)); /* 110 */ + Tcl_Obj * (*tkpGetSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, char * dbName, char * className)); /* 111 */ + void (*tkpMenuThreadInit) _ANSI_ARGS_((void)); /* 112 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved113; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved114; +#endif /* UNIX */ +#ifdef __WIN32__ + TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved115; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved116; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved117; +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved118; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved119; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved120; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved120; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 120 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved121; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved121; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, char * source)); /* 121 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved122; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved122; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 122 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved123; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved123; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 123 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved124; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved124; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display * display, CONST char * name, int * width, int * height)); /* 124 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved125; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved125; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 125 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved126; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved126; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 126 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved127; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved127; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 127 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved128; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved128; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 128 */ +#endif /* MAC_TCL */ + void *reserved129; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved130; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved130; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 130 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved131; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved131; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 131 */ +#endif /* MAC_TCL */ + void *reserved132; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved133; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved133; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 133 */ +#endif /* MAC_TCL */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved134; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved134; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 134 */ +#endif /* MAC_TCL */ + void (*tkpDrawHighlightBorder) _ANSI_ARGS_((Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable)); /* 135 */ + void (*tkSetFocusWin) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 136 */ + void (*tkpSetKeycodeAndState) _ANSI_ARGS_((Tk_Window tkwin, KeySym keySym, XEvent * eventPtr)); /* 137 */ + KeySym (*tkpGetKeySym) _ANSI_ARGS_((TkDisplay * dispPtr, XEvent * eventPtr)); /* 138 */ + void (*tkpInitKeymapInfo) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 139 */ +} TkIntStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkIntStubs *tkIntStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifndef TkAllocWindow +#define TkAllocWindow \ + (tkIntStubsPtr->tkAllocWindow) /* 0 */ +#endif +#ifndef TkBezierPoints +#define TkBezierPoints \ + (tkIntStubsPtr->tkBezierPoints) /* 1 */ +#endif +#ifndef TkBezierScreenPoints +#define TkBezierScreenPoints \ + (tkIntStubsPtr->tkBezierScreenPoints) /* 2 */ +#endif +#ifndef TkBindDeadWindow +#define TkBindDeadWindow \ + (tkIntStubsPtr->tkBindDeadWindow) /* 3 */ +#endif +#ifndef TkBindEventProc +#define TkBindEventProc \ + (tkIntStubsPtr->tkBindEventProc) /* 4 */ +#endif +#ifndef TkBindFree +#define TkBindFree \ + (tkIntStubsPtr->tkBindFree) /* 5 */ +#endif +#ifndef TkBindInit +#define TkBindInit \ + (tkIntStubsPtr->tkBindInit) /* 6 */ +#endif +#ifndef TkChangeEventWindow +#define TkChangeEventWindow \ + (tkIntStubsPtr->tkChangeEventWindow) /* 7 */ +#endif +#ifndef TkClipInit +#define TkClipInit \ + (tkIntStubsPtr->tkClipInit) /* 8 */ +#endif +#ifndef TkComputeAnchor +#define TkComputeAnchor \ + (tkIntStubsPtr->tkComputeAnchor) /* 9 */ +#endif +#ifndef TkCopyAndGlobalEval +#define TkCopyAndGlobalEval \ + (tkIntStubsPtr->tkCopyAndGlobalEval) /* 10 */ +#endif +#ifndef TkCreateBindingProcedure +#define TkCreateBindingProcedure \ + (tkIntStubsPtr->tkCreateBindingProcedure) /* 11 */ +#endif +#ifndef TkCreateCursorFromData +#define TkCreateCursorFromData \ + (tkIntStubsPtr->tkCreateCursorFromData) /* 12 */ +#endif +#ifndef TkCreateFrame +#define TkCreateFrame \ + (tkIntStubsPtr->tkCreateFrame) /* 13 */ +#endif +#ifndef TkCreateMainWindow +#define TkCreateMainWindow \ + (tkIntStubsPtr->tkCreateMainWindow) /* 14 */ +#endif +#ifndef TkCurrentTime +#define TkCurrentTime \ + (tkIntStubsPtr->tkCurrentTime) /* 15 */ +#endif +#ifndef TkDeleteAllImages +#define TkDeleteAllImages \ + (tkIntStubsPtr->tkDeleteAllImages) /* 16 */ +#endif +#ifndef TkDoConfigureNotify +#define TkDoConfigureNotify \ + (tkIntStubsPtr->tkDoConfigureNotify) /* 17 */ +#endif +#ifndef TkDrawInsetFocusHighlight +#define TkDrawInsetFocusHighlight \ + (tkIntStubsPtr->tkDrawInsetFocusHighlight) /* 18 */ +#endif +#ifndef TkEventDeadWindow +#define TkEventDeadWindow \ + (tkIntStubsPtr->tkEventDeadWindow) /* 19 */ +#endif +#ifndef TkFillPolygon +#define TkFillPolygon \ + (tkIntStubsPtr->tkFillPolygon) /* 20 */ +#endif +#ifndef TkFindStateNum +#define TkFindStateNum \ + (tkIntStubsPtr->tkFindStateNum) /* 21 */ +#endif +#ifndef TkFindStateString +#define TkFindStateString \ + (tkIntStubsPtr->tkFindStateString) /* 22 */ +#endif +#ifndef TkFocusDeadWindow +#define TkFocusDeadWindow \ + (tkIntStubsPtr->tkFocusDeadWindow) /* 23 */ +#endif +#ifndef TkFocusFilterEvent +#define TkFocusFilterEvent \ + (tkIntStubsPtr->tkFocusFilterEvent) /* 24 */ +#endif +#ifndef TkFocusKeyEvent +#define TkFocusKeyEvent \ + (tkIntStubsPtr->tkFocusKeyEvent) /* 25 */ +#endif +#ifndef TkFontPkgInit +#define TkFontPkgInit \ + (tkIntStubsPtr->tkFontPkgInit) /* 26 */ +#endif +#ifndef TkFontPkgFree +#define TkFontPkgFree \ + (tkIntStubsPtr->tkFontPkgFree) /* 27 */ +#endif +#ifndef TkFreeBindingTags +#define TkFreeBindingTags \ + (tkIntStubsPtr->tkFreeBindingTags) /* 28 */ +#endif +#ifndef TkpFreeCursor +#define TkpFreeCursor \ + (tkIntStubsPtr->tkpFreeCursor) /* 29 */ +#endif +#ifndef TkGetBitmapData +#define TkGetBitmapData \ + (tkIntStubsPtr->tkGetBitmapData) /* 30 */ +#endif +#ifndef TkGetButtPoints +#define TkGetButtPoints \ + (tkIntStubsPtr->tkGetButtPoints) /* 31 */ +#endif +#ifndef TkGetCursorByName +#define TkGetCursorByName \ + (tkIntStubsPtr->tkGetCursorByName) /* 32 */ +#endif +#ifndef TkGetDefaultScreenName +#define TkGetDefaultScreenName \ + (tkIntStubsPtr->tkGetDefaultScreenName) /* 33 */ +#endif +#ifndef TkGetDisplay +#define TkGetDisplay \ + (tkIntStubsPtr->tkGetDisplay) /* 34 */ +#endif +#ifndef TkGetDisplayOf +#define TkGetDisplayOf \ + (tkIntStubsPtr->tkGetDisplayOf) /* 35 */ +#endif +#ifndef TkGetFocusWin +#define TkGetFocusWin \ + (tkIntStubsPtr->tkGetFocusWin) /* 36 */ +#endif +#ifndef TkGetInterpNames +#define TkGetInterpNames \ + (tkIntStubsPtr->tkGetInterpNames) /* 37 */ +#endif +#ifndef TkGetMiterPoints +#define TkGetMiterPoints \ + (tkIntStubsPtr->tkGetMiterPoints) /* 38 */ +#endif +#ifndef TkGetPointerCoords +#define TkGetPointerCoords \ + (tkIntStubsPtr->tkGetPointerCoords) /* 39 */ +#endif +#ifndef TkGetServerInfo +#define TkGetServerInfo \ + (tkIntStubsPtr->tkGetServerInfo) /* 40 */ +#endif +#ifndef TkGrabDeadWindow +#define TkGrabDeadWindow \ + (tkIntStubsPtr->tkGrabDeadWindow) /* 41 */ +#endif +#ifndef TkGrabState +#define TkGrabState \ + (tkIntStubsPtr->tkGrabState) /* 42 */ +#endif +#ifndef TkIncludePoint +#define TkIncludePoint \ + (tkIntStubsPtr->tkIncludePoint) /* 43 */ +#endif +#ifndef TkInOutEvents +#define TkInOutEvents \ + (tkIntStubsPtr->tkInOutEvents) /* 44 */ +#endif +#ifndef TkInstallFrameMenu +#define TkInstallFrameMenu \ + (tkIntStubsPtr->tkInstallFrameMenu) /* 45 */ +#endif +#ifndef TkKeysymToString +#define TkKeysymToString \ + (tkIntStubsPtr->tkKeysymToString) /* 46 */ +#endif +#ifndef TkLineToArea +#define TkLineToArea \ + (tkIntStubsPtr->tkLineToArea) /* 47 */ +#endif +#ifndef TkLineToPoint +#define TkLineToPoint \ + (tkIntStubsPtr->tkLineToPoint) /* 48 */ +#endif +#ifndef TkMakeBezierCurve +#define TkMakeBezierCurve \ + (tkIntStubsPtr->tkMakeBezierCurve) /* 49 */ +#endif +#ifndef TkMakeBezierPostscript +#define TkMakeBezierPostscript \ + (tkIntStubsPtr->tkMakeBezierPostscript) /* 50 */ +#endif +#ifndef TkOptionClassChanged +#define TkOptionClassChanged \ + (tkIntStubsPtr->tkOptionClassChanged) /* 51 */ +#endif +#ifndef TkOptionDeadWindow +#define TkOptionDeadWindow \ + (tkIntStubsPtr->tkOptionDeadWindow) /* 52 */ +#endif +#ifndef TkOvalToArea +#define TkOvalToArea \ + (tkIntStubsPtr->tkOvalToArea) /* 53 */ +#endif +#ifndef TkOvalToPoint +#define TkOvalToPoint \ + (tkIntStubsPtr->tkOvalToPoint) /* 54 */ +#endif +#ifndef TkpChangeFocus +#define TkpChangeFocus \ + (tkIntStubsPtr->tkpChangeFocus) /* 55 */ +#endif +#ifndef TkpCloseDisplay +#define TkpCloseDisplay \ + (tkIntStubsPtr->tkpCloseDisplay) /* 56 */ +#endif +#ifndef TkpClaimFocus +#define TkpClaimFocus \ + (tkIntStubsPtr->tkpClaimFocus) /* 57 */ +#endif +#ifndef TkpDisplayWarning +#define TkpDisplayWarning \ + (tkIntStubsPtr->tkpDisplayWarning) /* 58 */ +#endif +#ifndef TkpGetAppName +#define TkpGetAppName \ + (tkIntStubsPtr->tkpGetAppName) /* 59 */ +#endif +#ifndef TkpGetOtherWindow +#define TkpGetOtherWindow \ + (tkIntStubsPtr->tkpGetOtherWindow) /* 60 */ +#endif +#ifndef TkpGetWrapperWindow +#define TkpGetWrapperWindow \ + (tkIntStubsPtr->tkpGetWrapperWindow) /* 61 */ +#endif +#ifndef TkpInit +#define TkpInit \ + (tkIntStubsPtr->tkpInit) /* 62 */ +#endif +#ifndef TkpInitializeMenuBindings +#define TkpInitializeMenuBindings \ + (tkIntStubsPtr->tkpInitializeMenuBindings) /* 63 */ +#endif +#ifndef TkpMakeContainer +#define TkpMakeContainer \ + (tkIntStubsPtr->tkpMakeContainer) /* 64 */ +#endif +#ifndef TkpMakeMenuWindow +#define TkpMakeMenuWindow \ + (tkIntStubsPtr->tkpMakeMenuWindow) /* 65 */ +#endif +#ifndef TkpMakeWindow +#define TkpMakeWindow \ + (tkIntStubsPtr->tkpMakeWindow) /* 66 */ +#endif +#ifndef TkpMenuNotifyToplevelCreate +#define TkpMenuNotifyToplevelCreate \ + (tkIntStubsPtr->tkpMenuNotifyToplevelCreate) /* 67 */ +#endif +#ifndef TkpOpenDisplay +#define TkpOpenDisplay \ + (tkIntStubsPtr->tkpOpenDisplay) /* 68 */ +#endif +#ifndef TkPointerEvent +#define TkPointerEvent \ + (tkIntStubsPtr->tkPointerEvent) /* 69 */ +#endif +#ifndef TkPolygonToArea +#define TkPolygonToArea \ + (tkIntStubsPtr->tkPolygonToArea) /* 70 */ +#endif +#ifndef TkPolygonToPoint +#define TkPolygonToPoint \ + (tkIntStubsPtr->tkPolygonToPoint) /* 71 */ +#endif +#ifndef TkPositionInTree +#define TkPositionInTree \ + (tkIntStubsPtr->tkPositionInTree) /* 72 */ +#endif +#ifndef TkpRedirectKeyEvent +#define TkpRedirectKeyEvent \ + (tkIntStubsPtr->tkpRedirectKeyEvent) /* 73 */ +#endif +#ifndef TkpSetMainMenubar +#define TkpSetMainMenubar \ + (tkIntStubsPtr->tkpSetMainMenubar) /* 74 */ +#endif +#ifndef TkpUseWindow +#define TkpUseWindow \ + (tkIntStubsPtr->tkpUseWindow) /* 75 */ +#endif +#ifndef TkpWindowWasRecentlyDeleted +#define TkpWindowWasRecentlyDeleted \ + (tkIntStubsPtr->tkpWindowWasRecentlyDeleted) /* 76 */ +#endif +#ifndef TkQueueEventForAllChildren +#define TkQueueEventForAllChildren \ + (tkIntStubsPtr->tkQueueEventForAllChildren) /* 77 */ +#endif +#ifndef TkReadBitmapFile +#define TkReadBitmapFile \ + (tkIntStubsPtr->tkReadBitmapFile) /* 78 */ +#endif +#ifndef TkScrollWindow +#define TkScrollWindow \ + (tkIntStubsPtr->tkScrollWindow) /* 79 */ +#endif +#ifndef TkSelDeadWindow +#define TkSelDeadWindow \ + (tkIntStubsPtr->tkSelDeadWindow) /* 80 */ +#endif +#ifndef TkSelEventProc +#define TkSelEventProc \ + (tkIntStubsPtr->tkSelEventProc) /* 81 */ +#endif +#ifndef TkSelInit +#define TkSelInit \ + (tkIntStubsPtr->tkSelInit) /* 82 */ +#endif +#ifndef TkSelPropProc +#define TkSelPropProc \ + (tkIntStubsPtr->tkSelPropProc) /* 83 */ +#endif +#ifndef TkSetClassProcs +#define TkSetClassProcs \ + (tkIntStubsPtr->tkSetClassProcs) /* 84 */ +#endif +#ifndef TkSetWindowMenuBar +#define TkSetWindowMenuBar \ + (tkIntStubsPtr->tkSetWindowMenuBar) /* 85 */ +#endif +#ifndef TkStringToKeysym +#define TkStringToKeysym \ + (tkIntStubsPtr->tkStringToKeysym) /* 86 */ +#endif +#ifndef TkThickPolyLineToArea +#define TkThickPolyLineToArea \ + (tkIntStubsPtr->tkThickPolyLineToArea) /* 87 */ +#endif +#ifndef TkWmAddToColormapWindows +#define TkWmAddToColormapWindows \ + (tkIntStubsPtr->tkWmAddToColormapWindows) /* 88 */ +#endif +#ifndef TkWmDeadWindow +#define TkWmDeadWindow \ + (tkIntStubsPtr->tkWmDeadWindow) /* 89 */ +#endif +#ifndef TkWmFocusToplevel +#define TkWmFocusToplevel \ + (tkIntStubsPtr->tkWmFocusToplevel) /* 90 */ +#endif +#ifndef TkWmMapWindow +#define TkWmMapWindow \ + (tkIntStubsPtr->tkWmMapWindow) /* 91 */ +#endif +#ifndef TkWmNewWindow +#define TkWmNewWindow \ + (tkIntStubsPtr->tkWmNewWindow) /* 92 */ +#endif +#ifndef TkWmProtocolEventProc +#define TkWmProtocolEventProc \ + (tkIntStubsPtr->tkWmProtocolEventProc) /* 93 */ +#endif +#ifndef TkWmRemoveFromColormapWindows +#define TkWmRemoveFromColormapWindows \ + (tkIntStubsPtr->tkWmRemoveFromColormapWindows) /* 94 */ +#endif +#ifndef TkWmRestackToplevel +#define TkWmRestackToplevel \ + (tkIntStubsPtr->tkWmRestackToplevel) /* 95 */ +#endif +#ifndef TkWmSetClass +#define TkWmSetClass \ + (tkIntStubsPtr->tkWmSetClass) /* 96 */ +#endif +#ifndef TkWmUnmapWindow +#define TkWmUnmapWindow \ + (tkIntStubsPtr->tkWmUnmapWindow) /* 97 */ +#endif +#ifndef TkDebugBitmap +#define TkDebugBitmap \ + (tkIntStubsPtr->tkDebugBitmap) /* 98 */ +#endif +#ifndef TkDebugBorder +#define TkDebugBorder \ + (tkIntStubsPtr->tkDebugBorder) /* 99 */ +#endif +#ifndef TkDebugCursor +#define TkDebugCursor \ + (tkIntStubsPtr->tkDebugCursor) /* 100 */ +#endif +#ifndef TkDebugColor +#define TkDebugColor \ + (tkIntStubsPtr->tkDebugColor) /* 101 */ +#endif +#ifndef TkDebugConfig +#define TkDebugConfig \ + (tkIntStubsPtr->tkDebugConfig) /* 102 */ +#endif +#ifndef TkDebugFont +#define TkDebugFont \ + (tkIntStubsPtr->tkDebugFont) /* 103 */ +#endif +#ifndef TkFindStateNumObj +#define TkFindStateNumObj \ + (tkIntStubsPtr->tkFindStateNumObj) /* 104 */ +#endif +#ifndef TkGetBitmapPredefTable +#define TkGetBitmapPredefTable \ + (tkIntStubsPtr->tkGetBitmapPredefTable) /* 105 */ +#endif +#ifndef TkGetDisplayList +#define TkGetDisplayList \ + (tkIntStubsPtr->tkGetDisplayList) /* 106 */ +#endif +#ifndef TkGetMainInfoList +#define TkGetMainInfoList \ + (tkIntStubsPtr->tkGetMainInfoList) /* 107 */ +#endif +#ifndef TkGetWindowFromObj +#define TkGetWindowFromObj \ + (tkIntStubsPtr->tkGetWindowFromObj) /* 108 */ +#endif +#ifndef TkpGetString +#define TkpGetString \ + (tkIntStubsPtr->tkpGetString) /* 109 */ +#endif +#ifndef TkpGetSubFonts +#define TkpGetSubFonts \ + (tkIntStubsPtr->tkpGetSubFonts) /* 110 */ +#endif +#ifndef TkpGetSystemDefault +#define TkpGetSystemDefault \ + (tkIntStubsPtr->tkpGetSystemDefault) /* 111 */ +#endif +#ifndef TkpMenuThreadInit +#define TkpMenuThreadInit \ + (tkIntStubsPtr->tkpMenuThreadInit) /* 112 */ +#endif +#ifdef __WIN32__ +#ifndef TkClipBox +#define TkClipBox \ + (tkIntStubsPtr->tkClipBox) /* 113 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkClipBox +#define TkClipBox \ + (tkIntStubsPtr->tkClipBox) /* 113 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkCreateRegion +#define TkCreateRegion \ + (tkIntStubsPtr->tkCreateRegion) /* 114 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkCreateRegion +#define TkCreateRegion \ + (tkIntStubsPtr->tkCreateRegion) /* 114 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkDestroyRegion +#define TkDestroyRegion \ + (tkIntStubsPtr->tkDestroyRegion) /* 115 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkDestroyRegion +#define TkDestroyRegion \ + (tkIntStubsPtr->tkDestroyRegion) /* 115 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkIntersectRegion +#define TkIntersectRegion \ + (tkIntStubsPtr->tkIntersectRegion) /* 116 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkIntersectRegion +#define TkIntersectRegion \ + (tkIntStubsPtr->tkIntersectRegion) /* 116 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkRectInRegion +#define TkRectInRegion \ + (tkIntStubsPtr->tkRectInRegion) /* 117 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkRectInRegion +#define TkRectInRegion \ + (tkIntStubsPtr->tkRectInRegion) /* 117 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkSetRegion +#define TkSetRegion \ + (tkIntStubsPtr->tkSetRegion) /* 118 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkSetRegion +#define TkSetRegion \ + (tkIntStubsPtr->tkSetRegion) /* 118 */ +#endif +#endif /* MAC_TCL */ +#ifdef __WIN32__ +#ifndef TkUnionRectWithRegion +#define TkUnionRectWithRegion \ + (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkUnionRectWithRegion +#define TkUnionRectWithRegion \ + (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntStubsPtr->tkGenerateActivateEvents) /* 120 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpCreateNativeBitmap +#define TkpCreateNativeBitmap \ + (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpDefineNativeBitmaps +#define TkpDefineNativeBitmaps \ + (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntStubsPtr->tkpGetMS) /* 123 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpGetNativeAppBitmap +#define TkpGetNativeAppBitmap \ + (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntStubsPtr->tkPointerDeadWindow) /* 125 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntStubsPtr->tkpSetCapture) /* 126 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntStubsPtr->tkpSetCursor) /* 127 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntStubsPtr->tkpWmSetState) /* 128 */ +#endif +#endif /* MAC_TCL */ +/* Slot 129 is reserved */ +#ifdef MAC_TCL +#ifndef TkGetTransientMaster +#define TkGetTransientMaster \ + (tkIntStubsPtr->tkGetTransientMaster) /* 130 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkGenerateButtonEvent +#define TkGenerateButtonEvent \ + (tkIntStubsPtr->tkGenerateButtonEvent) /* 131 */ +#endif +#endif /* MAC_TCL */ +/* Slot 132 is reserved */ +#ifdef MAC_TCL +#ifndef TkGenWMDestroyEvent +#define TkGenWMDestroyEvent \ + (tkIntStubsPtr->tkGenWMDestroyEvent) /* 133 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_TCL +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkIntStubsPtr->tkGenWMConfigureEvent) /* 134 */ +#endif +#endif /* MAC_TCL */ +#ifndef TkpDrawHighlightBorder +#define TkpDrawHighlightBorder \ + (tkIntStubsPtr->tkpDrawHighlightBorder) /* 135 */ +#endif +#ifndef TkSetFocusWin +#define TkSetFocusWin \ + (tkIntStubsPtr->tkSetFocusWin) /* 136 */ +#endif +#ifndef TkpSetKeycodeAndState +#define TkpSetKeycodeAndState \ + (tkIntStubsPtr->tkpSetKeycodeAndState) /* 137 */ +#endif +#ifndef TkpGetKeySym +#define TkpGetKeySym \ + (tkIntStubsPtr->tkpGetKeySym) /* 138 */ +#endif +#ifndef TkpInitKeymapInfo +#define TkpInitKeymapInfo \ + (tkIntStubsPtr->tkpInitKeymapInfo) /* 139 */ +#endif + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINTDECLS */ + diff --git a/Utilities/TclTk/internals/tk8.3/tkIntPlatDecls.h b/Utilities/TclTk/internals/tk8.3/tkIntPlatDecls.h new file mode 100644 index 0000000..db1a8b9 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkIntPlatDecls.h @@ -0,0 +1,844 @@ +/* + * tkIntPlatDecls.h -- + * + * This file contains the declarations for all platform dependent + * unsupported functions that are exported by the Tk library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * All rights reserved. + * + * RCS: @(#) $Id: tkIntPlatDecls.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKINTPLATDECLS +#define _TKINTPLATDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tkInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 0 */ +EXTERN void TkCreateXEventSource _ANSI_ARGS_((void)); +/* 1 */ +EXTERN void TkFreeWindowId _ANSI_ARGS_((TkDisplay * dispPtr, + Window w)); +/* 2 */ +EXTERN void TkInitXId _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 3 */ +EXTERN int TkpCmapStressed _ANSI_ARGS_((Tk_Window tkwin, + Colormap colormap)); +/* 4 */ +EXTERN void TkpSync _ANSI_ARGS_((Display * display)); +/* 5 */ +EXTERN Window TkUnixContainerId _ANSI_ARGS_((TkWindow * winPtr)); +/* 6 */ +EXTERN int TkUnixDoOneXEvent _ANSI_ARGS_((Tcl_Time * timePtr)); +/* 7 */ +EXTERN void TkUnixSetMenubar _ANSI_ARGS_((Tk_Window tkwin, + Tk_Window menubar)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 0 */ +EXTERN char * TkAlignImageData _ANSI_ARGS_((XImage * image, + int alignment, int bitOrder)); +/* Slot 1 is reserved */ +/* 2 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +/* 3 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +/* 4 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 5 */ +EXTERN void TkpPrintWindowId _ANSI_ARGS_((char * buf, + Window window)); +/* 6 */ +EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp * interp, + char * string, int * idPtr)); +/* 7 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +/* 8 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +/* 9 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +/* 10 */ +EXTERN void TkSetPixmapColormap _ANSI_ARGS_((Pixmap pixmap, + Colormap colormap)); +/* 11 */ +EXTERN void TkWinCancelMouseTimer _ANSI_ARGS_((void)); +/* 12 */ +EXTERN void TkWinClipboardRender _ANSI_ARGS_(( + TkDisplay * dispPtr, UINT format)); +/* 13 */ +EXTERN LRESULT TkWinEmbeddedEventProc _ANSI_ARGS_((HWND hwnd, + UINT message, WPARAM wParam, LPARAM lParam)); +/* 14 */ +EXTERN void TkWinFillRect _ANSI_ARGS_((HDC dc, int x, int y, + int width, int height, int pixel)); +/* 15 */ +EXTERN COLORREF TkWinGetBorderPixels _ANSI_ARGS_((Tk_Window tkwin, + Tk_3DBorder border, int which)); +/* 16 */ +EXTERN HDC TkWinGetDrawableDC _ANSI_ARGS_((Display * display, + Drawable d, TkWinDCState* state)); +/* 17 */ +EXTERN int TkWinGetModifierState _ANSI_ARGS_((void)); +/* 18 */ +EXTERN HPALETTE TkWinGetSystemPalette _ANSI_ARGS_((void)); +/* 19 */ +EXTERN HWND TkWinGetWrapperWindow _ANSI_ARGS_((Tk_Window tkwin)); +/* 20 */ +EXTERN int TkWinHandleMenuEvent _ANSI_ARGS_((HWND * phwnd, + UINT * pMessage, WPARAM * pwParam, + LPARAM * plParam, LRESULT * plResult)); +/* 21 */ +EXTERN int TkWinIndexOfColor _ANSI_ARGS_((XColor * colorPtr)); +/* 22 */ +EXTERN void TkWinReleaseDrawableDC _ANSI_ARGS_((Drawable d, + HDC hdc, TkWinDCState* state)); +/* 23 */ +EXTERN LRESULT TkWinResendEvent _ANSI_ARGS_((WNDPROC wndproc, + HWND hwnd, XEvent * eventPtr)); +/* 24 */ +EXTERN HPALETTE TkWinSelectPalette _ANSI_ARGS_((HDC dc, + Colormap colormap)); +/* 25 */ +EXTERN void TkWinSetMenu _ANSI_ARGS_((Tk_Window tkwin, + HMENU hMenu)); +/* 26 */ +EXTERN void TkWinSetWindowPos _ANSI_ARGS_((HWND hwnd, + HWND siblingHwnd, int pos)); +/* 27 */ +EXTERN void TkWinWmCleanup _ANSI_ARGS_((HINSTANCE hInstance)); +/* 28 */ +EXTERN void TkWinXCleanup _ANSI_ARGS_((HINSTANCE hInstance)); +/* 29 */ +EXTERN void TkWinXInit _ANSI_ARGS_((HINSTANCE hInstance)); +/* 30 */ +EXTERN void TkWinSetForegroundWindow _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 31 */ +EXTERN void TkWinDialogDebug _ANSI_ARGS_((int debug)); +/* 32 */ +EXTERN Tcl_Obj * TkWinGetMenuSystemDefault _ANSI_ARGS_(( + Tk_Window tkwin, char * dbName, + char * className)); +/* 33 */ +EXTERN int TkWinGetPlatformId _ANSI_ARGS_((void)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +/* 1 */ +EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display, + char * source)); +/* 2 */ +EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); +/* 3 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +/* Slot 4 is reserved */ +/* 5 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 6 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +/* 7 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +/* 8 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +/* Slot 9 is reserved */ +/* 10 */ +EXTERN void TkAboutDlg _ANSI_ARGS_((void)); +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ +/* 13 */ +EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr)); +/* 14 */ +EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, + Window window, unsigned int state)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); +/* 17 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +/* 18 */ +EXTERN unsigned int TkMacButtonKeyState _ANSI_ARGS_((void)); +/* 19 */ +EXTERN void TkMacClearMenubarActive _ANSI_ARGS_((void)); +/* 20 */ +EXTERN int TkMacConvertEvent _ANSI_ARGS_(( + EventRecord * eventPtr)); +/* 21 */ +EXTERN int TkMacDispatchMenuEvent _ANSI_ARGS_((int menuID, + int index)); +/* 22 */ +EXTERN void TkMacInstallCursor _ANSI_ARGS_((int resizeOverride)); +/* 23 */ +EXTERN int TkMacConvertTkEvent _ANSI_ARGS_(( + EventRecord * eventPtr, Window window)); +/* 24 */ +EXTERN void TkMacHandleTearoffMenu _ANSI_ARGS_((void)); +/* Slot 25 is reserved */ +/* 26 */ +EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr)); +/* 27 */ +EXTERN void TkMacDoHLEvent _ANSI_ARGS_((EventRecord * theEvent)); +/* Slot 28 is reserved */ +/* 29 */ +EXTERN Time TkMacGenerateTime _ANSI_ARGS_((void)); +/* 30 */ +EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable)); +/* 31 */ +EXTERN TkWindow * TkMacGetScrollbarGrowWindow _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 32 */ +EXTERN Window TkMacGetXWindow _ANSI_ARGS_((WindowRef macWinPtr)); +/* 33 */ +EXTERN int TkMacGrowToplevel _ANSI_ARGS_((WindowRef whichWindow, + Point start)); +/* 34 */ +EXTERN void TkMacHandleMenuSelect _ANSI_ARGS_((long mResult, + int optionKeyPressed)); +/* 35 */ +EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void)); +/* 36 */ +EXTERN void TkMacInitAppleEvents _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 37 */ +EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp * interp)); +/* 38 */ +EXTERN void TkMacInvalidateWindow _ANSI_ARGS_(( + MacDrawable * macWin, int flag)); +/* 39 */ +EXTERN int TkMacIsCharacterMissing _ANSI_ARGS_((Tk_Font tkfont, + unsigned int searchChar)); +/* 40 */ +EXTERN void TkMacMakeRealWindowExist _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 41 */ +EXTERN BitMapPtr TkMacMakeStippleMap _ANSI_ARGS_((Drawable d1, + Drawable d2)); +/* 42 */ +EXTERN void TkMacMenuClick _ANSI_ARGS_((void)); +/* 43 */ +EXTERN void TkMacRegisterOffScreenWindow _ANSI_ARGS_(( + Window window, GWorldPtr portPtr)); +/* 44 */ +EXTERN int TkMacResizable _ANSI_ARGS_((TkWindow * winPtr)); +/* Slot 45 is reserved */ +/* 46 */ +EXTERN void TkMacSetHelpMenuItemCount _ANSI_ARGS_((void)); +/* 47 */ +EXTERN void TkMacSetScrollbarGrow _ANSI_ARGS_((TkWindow * winPtr, + int flag)); +/* 48 */ +EXTERN void TkMacSetUpClippingRgn _ANSI_ARGS_((Drawable drawable)); +/* 49 */ +EXTERN void TkMacSetUpGraphicsPort _ANSI_ARGS_((GC gc)); +/* 50 */ +EXTERN void TkMacUpdateClipRgn _ANSI_ARGS_((TkWindow * winPtr)); +/* 51 */ +EXTERN void TkMacUnregisterMacWindow _ANSI_ARGS_(( + GWorldPtr portPtr)); +/* 52 */ +EXTERN int TkMacUseMenuID _ANSI_ARGS_((short macID)); +/* 53 */ +EXTERN RgnHandle TkMacVisableClipRgn _ANSI_ARGS_((TkWindow * winPtr)); +/* 54 */ +EXTERN void TkMacWinBounds _ANSI_ARGS_((TkWindow * winPtr, + Rect * geometry)); +/* 55 */ +EXTERN void TkMacWindowOffset _ANSI_ARGS_((WindowRef wRef, + int * xOffset, int * yOffset)); +/* Slot 56 is reserved */ +/* 57 */ +EXTERN int TkSetMacColor _ANSI_ARGS_((unsigned long pixel, + RGBColor * macColor)); +/* 58 */ +EXTERN void TkSetWMName _ANSI_ARGS_((TkWindow * winPtr, + Tk_Uid titleUid)); +/* 59 */ +EXTERN void TkSuspendClipboard _ANSI_ARGS_((void)); +/* Slot 60 is reserved */ +/* 61 */ +EXTERN int TkMacZoomToplevel _ANSI_ARGS_((WindowPtr whichWindow, + Point where, short zoomPart)); +/* 62 */ +EXTERN Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin, + int rootX, int rootY, int * newX, int * newY)); +/* 63 */ +EXTERN MacDrawable * TkMacContainerId _ANSI_ARGS_((TkWindow * winPtr)); +/* 64 */ +EXTERN MacDrawable * TkMacGetHostToplevel _ANSI_ARGS_((TkWindow * winPtr)); +/* 65 */ +EXTERN void TkMacPreprocessMenu _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ + +typedef struct TkIntPlatStubs { + int magic; + struct TkIntPlatStubHooks *hooks; + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void (*tkCreateXEventSource) _ANSI_ARGS_((void)); /* 0 */ + void (*tkFreeWindowId) _ANSI_ARGS_((TkDisplay * dispPtr, Window w)); /* 1 */ + void (*tkInitXId) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 2 */ + int (*tkpCmapStressed) _ANSI_ARGS_((Tk_Window tkwin, Colormap colormap)); /* 3 */ + void (*tkpSync) _ANSI_ARGS_((Display * display)); /* 4 */ + Window (*tkUnixContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */ + int (*tkUnixDoOneXEvent) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 6 */ + void (*tkUnixSetMenubar) _ANSI_ARGS_((Tk_Window tkwin, Tk_Window menubar)); /* 7 */ +#endif /* UNIX */ +#ifdef __WIN32__ + char * (*tkAlignImageData) _ANSI_ARGS_((XImage * image, int alignment, int bitOrder)); /* 0 */ + void *reserved1; + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 2 */ + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 4 */ + void (*tkpPrintWindowId) _ANSI_ARGS_((char * buf, Window window)); /* 5 */ + int (*tkpScanWindowId) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int * idPtr)); /* 6 */ + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 7 */ + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 8 */ + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 9 */ + void (*tkSetPixmapColormap) _ANSI_ARGS_((Pixmap pixmap, Colormap colormap)); /* 10 */ + void (*tkWinCancelMouseTimer) _ANSI_ARGS_((void)); /* 11 */ + void (*tkWinClipboardRender) _ANSI_ARGS_((TkDisplay * dispPtr, UINT format)); /* 12 */ + LRESULT (*tkWinEmbeddedEventProc) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); /* 13 */ + void (*tkWinFillRect) _ANSI_ARGS_((HDC dc, int x, int y, int width, int height, int pixel)); /* 14 */ + COLORREF (*tkWinGetBorderPixels) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int which)); /* 15 */ + HDC (*tkWinGetDrawableDC) _ANSI_ARGS_((Display * display, Drawable d, TkWinDCState* state)); /* 16 */ + int (*tkWinGetModifierState) _ANSI_ARGS_((void)); /* 17 */ + HPALETTE (*tkWinGetSystemPalette) _ANSI_ARGS_((void)); /* 18 */ + HWND (*tkWinGetWrapperWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 19 */ + int (*tkWinHandleMenuEvent) _ANSI_ARGS_((HWND * phwnd, UINT * pMessage, WPARAM * pwParam, LPARAM * plParam, LRESULT * plResult)); /* 20 */ + int (*tkWinIndexOfColor) _ANSI_ARGS_((XColor * colorPtr)); /* 21 */ + void (*tkWinReleaseDrawableDC) _ANSI_ARGS_((Drawable d, HDC hdc, TkWinDCState* state)); /* 22 */ + LRESULT (*tkWinResendEvent) _ANSI_ARGS_((WNDPROC wndproc, HWND hwnd, XEvent * eventPtr)); /* 23 */ + HPALETTE (*tkWinSelectPalette) _ANSI_ARGS_((HDC dc, Colormap colormap)); /* 24 */ + void (*tkWinSetMenu) _ANSI_ARGS_((Tk_Window tkwin, HMENU hMenu)); /* 25 */ + void (*tkWinSetWindowPos) _ANSI_ARGS_((HWND hwnd, HWND siblingHwnd, int pos)); /* 26 */ + void (*tkWinWmCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 27 */ + void (*tkWinXCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 28 */ + void (*tkWinXInit) _ANSI_ARGS_((HINSTANCE hInstance)); /* 29 */ + void (*tkWinSetForegroundWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 30 */ + void (*tkWinDialogDebug) _ANSI_ARGS_((int debug)); /* 31 */ + Tcl_Obj * (*tkWinGetMenuSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, char * dbName, char * className)); /* 32 */ + int (*tkWinGetPlatformId) _ANSI_ARGS_((void)); /* 33 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 0 */ + Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, char * source)); /* 1 */ + void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 2 */ + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ + void *reserved4; + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */ + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 6 */ + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 7 */ + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 8 */ + void *reserved9; + void (*tkAboutDlg) _ANSI_ARGS_((void)); /* 10 */ + void *reserved11; + void *reserved12; + Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 13 */ + int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 14 */ + void *reserved15; + void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 16 */ + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 17 */ + unsigned int (*tkMacButtonKeyState) _ANSI_ARGS_((void)); /* 18 */ + void (*tkMacClearMenubarActive) _ANSI_ARGS_((void)); /* 19 */ + int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord * eventPtr)); /* 20 */ + int (*tkMacDispatchMenuEvent) _ANSI_ARGS_((int menuID, int index)); /* 21 */ + void (*tkMacInstallCursor) _ANSI_ARGS_((int resizeOverride)); /* 22 */ + int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord * eventPtr, Window window)); /* 23 */ + void (*tkMacHandleTearoffMenu) _ANSI_ARGS_((void)); /* 24 */ + void *reserved25; + void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 26 */ + void (*tkMacDoHLEvent) _ANSI_ARGS_((EventRecord * theEvent)); /* 27 */ + void *reserved28; + Time (*tkMacGenerateTime) _ANSI_ARGS_((void)); /* 29 */ + GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 30 */ + TkWindow * (*tkMacGetScrollbarGrowWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 31 */ + Window (*tkMacGetXWindow) _ANSI_ARGS_((WindowRef macWinPtr)); /* 32 */ + int (*tkMacGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 33 */ + void (*tkMacHandleMenuSelect) _ANSI_ARGS_((long mResult, int optionKeyPressed)); /* 34 */ + int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 35 */ + void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 36 */ + void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 37 */ + void (*tkMacInvalidateWindow) _ANSI_ARGS_((MacDrawable * macWin, int flag)); /* 38 */ + int (*tkMacIsCharacterMissing) _ANSI_ARGS_((Tk_Font tkfont, unsigned int searchChar)); /* 39 */ + void (*tkMacMakeRealWindowExist) _ANSI_ARGS_((TkWindow * winPtr)); /* 40 */ + BitMapPtr (*tkMacMakeStippleMap) _ANSI_ARGS_((Drawable d1, Drawable d2)); /* 41 */ + void (*tkMacMenuClick) _ANSI_ARGS_((void)); /* 42 */ + void (*tkMacRegisterOffScreenWindow) _ANSI_ARGS_((Window window, GWorldPtr portPtr)); /* 43 */ + int (*tkMacResizable) _ANSI_ARGS_((TkWindow * winPtr)); /* 44 */ + void *reserved45; + void (*tkMacSetHelpMenuItemCount) _ANSI_ARGS_((void)); /* 46 */ + void (*tkMacSetScrollbarGrow) _ANSI_ARGS_((TkWindow * winPtr, int flag)); /* 47 */ + void (*tkMacSetUpClippingRgn) _ANSI_ARGS_((Drawable drawable)); /* 48 */ + void (*tkMacSetUpGraphicsPort) _ANSI_ARGS_((GC gc)); /* 49 */ + void (*tkMacUpdateClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 50 */ + void (*tkMacUnregisterMacWindow) _ANSI_ARGS_((GWorldPtr portPtr)); /* 51 */ + int (*tkMacUseMenuID) _ANSI_ARGS_((short macID)); /* 52 */ + RgnHandle (*tkMacVisableClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 53 */ + void (*tkMacWinBounds) _ANSI_ARGS_((TkWindow * winPtr, Rect * geometry)); /* 54 */ + void (*tkMacWindowOffset) _ANSI_ARGS_((WindowRef wRef, int * xOffset, int * yOffset)); /* 55 */ + void *reserved56; + int (*tkSetMacColor) _ANSI_ARGS_((unsigned long pixel, RGBColor * macColor)); /* 57 */ + void (*tkSetWMName) _ANSI_ARGS_((TkWindow * winPtr, Tk_Uid titleUid)); /* 58 */ + void (*tkSuspendClipboard) _ANSI_ARGS_((void)); /* 59 */ + void *reserved60; + int (*tkMacZoomToplevel) _ANSI_ARGS_((WindowPtr whichWindow, Point where, short zoomPart)); /* 61 */ + Tk_Window (*tk_TopCoordsToWindow) _ANSI_ARGS_((Tk_Window tkwin, int rootX, int rootY, int * newX, int * newY)); /* 62 */ + MacDrawable * (*tkMacContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 63 */ + MacDrawable * (*tkMacGetHostToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 64 */ + void (*tkMacPreprocessMenu) _ANSI_ARGS_((void)); /* 65 */ +#endif /* MAC_TCL */ +} TkIntPlatStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkIntPlatStubs *tkIntPlatStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TkCreateXEventSource +#define TkCreateXEventSource \ + (tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */ +#endif +#ifndef TkFreeWindowId +#define TkFreeWindowId \ + (tkIntPlatStubsPtr->tkFreeWindowId) /* 1 */ +#endif +#ifndef TkInitXId +#define TkInitXId \ + (tkIntPlatStubsPtr->tkInitXId) /* 2 */ +#endif +#ifndef TkpCmapStressed +#define TkpCmapStressed \ + (tkIntPlatStubsPtr->tkpCmapStressed) /* 3 */ +#endif +#ifndef TkpSync +#define TkpSync \ + (tkIntPlatStubsPtr->tkpSync) /* 4 */ +#endif +#ifndef TkUnixContainerId +#define TkUnixContainerId \ + (tkIntPlatStubsPtr->tkUnixContainerId) /* 5 */ +#endif +#ifndef TkUnixDoOneXEvent +#define TkUnixDoOneXEvent \ + (tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 6 */ +#endif +#ifndef TkUnixSetMenubar +#define TkUnixSetMenubar \ + (tkIntPlatStubsPtr->tkUnixSetMenubar) /* 7 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TkAlignImageData +#define TkAlignImageData \ + (tkIntPlatStubsPtr->tkAlignImageData) /* 0 */ +#endif +/* Slot 1 is reserved */ +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */ +#endif +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntPlatStubsPtr->tkpGetMS) /* 3 */ +#endif +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 4 */ +#endif +#ifndef TkpPrintWindowId +#define TkpPrintWindowId \ + (tkIntPlatStubsPtr->tkpPrintWindowId) /* 5 */ +#endif +#ifndef TkpScanWindowId +#define TkpScanWindowId \ + (tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */ +#endif +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntPlatStubsPtr->tkpSetCapture) /* 7 */ +#endif +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntPlatStubsPtr->tkpSetCursor) /* 8 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 9 */ +#endif +#ifndef TkSetPixmapColormap +#define TkSetPixmapColormap \ + (tkIntPlatStubsPtr->tkSetPixmapColormap) /* 10 */ +#endif +#ifndef TkWinCancelMouseTimer +#define TkWinCancelMouseTimer \ + (tkIntPlatStubsPtr->tkWinCancelMouseTimer) /* 11 */ +#endif +#ifndef TkWinClipboardRender +#define TkWinClipboardRender \ + (tkIntPlatStubsPtr->tkWinClipboardRender) /* 12 */ +#endif +#ifndef TkWinEmbeddedEventProc +#define TkWinEmbeddedEventProc \ + (tkIntPlatStubsPtr->tkWinEmbeddedEventProc) /* 13 */ +#endif +#ifndef TkWinFillRect +#define TkWinFillRect \ + (tkIntPlatStubsPtr->tkWinFillRect) /* 14 */ +#endif +#ifndef TkWinGetBorderPixels +#define TkWinGetBorderPixels \ + (tkIntPlatStubsPtr->tkWinGetBorderPixels) /* 15 */ +#endif +#ifndef TkWinGetDrawableDC +#define TkWinGetDrawableDC \ + (tkIntPlatStubsPtr->tkWinGetDrawableDC) /* 16 */ +#endif +#ifndef TkWinGetModifierState +#define TkWinGetModifierState \ + (tkIntPlatStubsPtr->tkWinGetModifierState) /* 17 */ +#endif +#ifndef TkWinGetSystemPalette +#define TkWinGetSystemPalette \ + (tkIntPlatStubsPtr->tkWinGetSystemPalette) /* 18 */ +#endif +#ifndef TkWinGetWrapperWindow +#define TkWinGetWrapperWindow \ + (tkIntPlatStubsPtr->tkWinGetWrapperWindow) /* 19 */ +#endif +#ifndef TkWinHandleMenuEvent +#define TkWinHandleMenuEvent \ + (tkIntPlatStubsPtr->tkWinHandleMenuEvent) /* 20 */ +#endif +#ifndef TkWinIndexOfColor +#define TkWinIndexOfColor \ + (tkIntPlatStubsPtr->tkWinIndexOfColor) /* 21 */ +#endif +#ifndef TkWinReleaseDrawableDC +#define TkWinReleaseDrawableDC \ + (tkIntPlatStubsPtr->tkWinReleaseDrawableDC) /* 22 */ +#endif +#ifndef TkWinResendEvent +#define TkWinResendEvent \ + (tkIntPlatStubsPtr->tkWinResendEvent) /* 23 */ +#endif +#ifndef TkWinSelectPalette +#define TkWinSelectPalette \ + (tkIntPlatStubsPtr->tkWinSelectPalette) /* 24 */ +#endif +#ifndef TkWinSetMenu +#define TkWinSetMenu \ + (tkIntPlatStubsPtr->tkWinSetMenu) /* 25 */ +#endif +#ifndef TkWinSetWindowPos +#define TkWinSetWindowPos \ + (tkIntPlatStubsPtr->tkWinSetWindowPos) /* 26 */ +#endif +#ifndef TkWinWmCleanup +#define TkWinWmCleanup \ + (tkIntPlatStubsPtr->tkWinWmCleanup) /* 27 */ +#endif +#ifndef TkWinXCleanup +#define TkWinXCleanup \ + (tkIntPlatStubsPtr->tkWinXCleanup) /* 28 */ +#endif +#ifndef TkWinXInit +#define TkWinXInit \ + (tkIntPlatStubsPtr->tkWinXInit) /* 29 */ +#endif +#ifndef TkWinSetForegroundWindow +#define TkWinSetForegroundWindow \ + (tkIntPlatStubsPtr->tkWinSetForegroundWindow) /* 30 */ +#endif +#ifndef TkWinDialogDebug +#define TkWinDialogDebug \ + (tkIntPlatStubsPtr->tkWinDialogDebug) /* 31 */ +#endif +#ifndef TkWinGetMenuSystemDefault +#define TkWinGetMenuSystemDefault \ + (tkIntPlatStubsPtr->tkWinGetMenuSystemDefault) /* 32 */ +#endif +#ifndef TkWinGetPlatformId +#define TkWinGetPlatformId \ + (tkIntPlatStubsPtr->tkWinGetPlatformId) /* 33 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */ +#endif +#ifndef TkpCreateNativeBitmap +#define TkpCreateNativeBitmap \ + (tkIntPlatStubsPtr->tkpCreateNativeBitmap) /* 1 */ +#endif +#ifndef TkpDefineNativeBitmaps +#define TkpDefineNativeBitmaps \ + (tkIntPlatStubsPtr->tkpDefineNativeBitmaps) /* 2 */ +#endif +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntPlatStubsPtr->tkpGetMS) /* 3 */ +#endif +/* Slot 4 is reserved */ +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 5 */ +#endif +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntPlatStubsPtr->tkpSetCapture) /* 6 */ +#endif +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntPlatStubsPtr->tkpSetCursor) /* 7 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 8 */ +#endif +/* Slot 9 is reserved */ +#ifndef TkAboutDlg +#define TkAboutDlg \ + (tkIntPlatStubsPtr->tkAboutDlg) /* 10 */ +#endif +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ +#ifndef TkGetTransientMaster +#define TkGetTransientMaster \ + (tkIntPlatStubsPtr->tkGetTransientMaster) /* 13 */ +#endif +#ifndef TkGenerateButtonEvent +#define TkGenerateButtonEvent \ + (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TkGenWMDestroyEvent +#define TkGenWMDestroyEvent \ + (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 16 */ +#endif +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkIntPlatStubsPtr->tkGenWMConfigureEvent) /* 17 */ +#endif +#ifndef TkMacButtonKeyState +#define TkMacButtonKeyState \ + (tkIntPlatStubsPtr->tkMacButtonKeyState) /* 18 */ +#endif +#ifndef TkMacClearMenubarActive +#define TkMacClearMenubarActive \ + (tkIntPlatStubsPtr->tkMacClearMenubarActive) /* 19 */ +#endif +#ifndef TkMacConvertEvent +#define TkMacConvertEvent \ + (tkIntPlatStubsPtr->tkMacConvertEvent) /* 20 */ +#endif +#ifndef TkMacDispatchMenuEvent +#define TkMacDispatchMenuEvent \ + (tkIntPlatStubsPtr->tkMacDispatchMenuEvent) /* 21 */ +#endif +#ifndef TkMacInstallCursor +#define TkMacInstallCursor \ + (tkIntPlatStubsPtr->tkMacInstallCursor) /* 22 */ +#endif +#ifndef TkMacConvertTkEvent +#define TkMacConvertTkEvent \ + (tkIntPlatStubsPtr->tkMacConvertTkEvent) /* 23 */ +#endif +#ifndef TkMacHandleTearoffMenu +#define TkMacHandleTearoffMenu \ + (tkIntPlatStubsPtr->tkMacHandleTearoffMenu) /* 24 */ +#endif +/* Slot 25 is reserved */ +#ifndef TkMacInvalClipRgns +#define TkMacInvalClipRgns \ + (tkIntPlatStubsPtr->tkMacInvalClipRgns) /* 26 */ +#endif +#ifndef TkMacDoHLEvent +#define TkMacDoHLEvent \ + (tkIntPlatStubsPtr->tkMacDoHLEvent) /* 27 */ +#endif +/* Slot 28 is reserved */ +#ifndef TkMacGenerateTime +#define TkMacGenerateTime \ + (tkIntPlatStubsPtr->tkMacGenerateTime) /* 29 */ +#endif +#ifndef TkMacGetDrawablePort +#define TkMacGetDrawablePort \ + (tkIntPlatStubsPtr->tkMacGetDrawablePort) /* 30 */ +#endif +#ifndef TkMacGetScrollbarGrowWindow +#define TkMacGetScrollbarGrowWindow \ + (tkIntPlatStubsPtr->tkMacGetScrollbarGrowWindow) /* 31 */ +#endif +#ifndef TkMacGetXWindow +#define TkMacGetXWindow \ + (tkIntPlatStubsPtr->tkMacGetXWindow) /* 32 */ +#endif +#ifndef TkMacGrowToplevel +#define TkMacGrowToplevel \ + (tkIntPlatStubsPtr->tkMacGrowToplevel) /* 33 */ +#endif +#ifndef TkMacHandleMenuSelect +#define TkMacHandleMenuSelect \ + (tkIntPlatStubsPtr->tkMacHandleMenuSelect) /* 34 */ +#endif +#ifndef TkMacHaveAppearance +#define TkMacHaveAppearance \ + (tkIntPlatStubsPtr->tkMacHaveAppearance) /* 35 */ +#endif +#ifndef TkMacInitAppleEvents +#define TkMacInitAppleEvents \ + (tkIntPlatStubsPtr->tkMacInitAppleEvents) /* 36 */ +#endif +#ifndef TkMacInitMenus +#define TkMacInitMenus \ + (tkIntPlatStubsPtr->tkMacInitMenus) /* 37 */ +#endif +#ifndef TkMacInvalidateWindow +#define TkMacInvalidateWindow \ + (tkIntPlatStubsPtr->tkMacInvalidateWindow) /* 38 */ +#endif +#ifndef TkMacIsCharacterMissing +#define TkMacIsCharacterMissing \ + (tkIntPlatStubsPtr->tkMacIsCharacterMissing) /* 39 */ +#endif +#ifndef TkMacMakeRealWindowExist +#define TkMacMakeRealWindowExist \ + (tkIntPlatStubsPtr->tkMacMakeRealWindowExist) /* 40 */ +#endif +#ifndef TkMacMakeStippleMap +#define TkMacMakeStippleMap \ + (tkIntPlatStubsPtr->tkMacMakeStippleMap) /* 41 */ +#endif +#ifndef TkMacMenuClick +#define TkMacMenuClick \ + (tkIntPlatStubsPtr->tkMacMenuClick) /* 42 */ +#endif +#ifndef TkMacRegisterOffScreenWindow +#define TkMacRegisterOffScreenWindow \ + (tkIntPlatStubsPtr->tkMacRegisterOffScreenWindow) /* 43 */ +#endif +#ifndef TkMacResizable +#define TkMacResizable \ + (tkIntPlatStubsPtr->tkMacResizable) /* 44 */ +#endif +/* Slot 45 is reserved */ +#ifndef TkMacSetHelpMenuItemCount +#define TkMacSetHelpMenuItemCount \ + (tkIntPlatStubsPtr->tkMacSetHelpMenuItemCount) /* 46 */ +#endif +#ifndef TkMacSetScrollbarGrow +#define TkMacSetScrollbarGrow \ + (tkIntPlatStubsPtr->tkMacSetScrollbarGrow) /* 47 */ +#endif +#ifndef TkMacSetUpClippingRgn +#define TkMacSetUpClippingRgn \ + (tkIntPlatStubsPtr->tkMacSetUpClippingRgn) /* 48 */ +#endif +#ifndef TkMacSetUpGraphicsPort +#define TkMacSetUpGraphicsPort \ + (tkIntPlatStubsPtr->tkMacSetUpGraphicsPort) /* 49 */ +#endif +#ifndef TkMacUpdateClipRgn +#define TkMacUpdateClipRgn \ + (tkIntPlatStubsPtr->tkMacUpdateClipRgn) /* 50 */ +#endif +#ifndef TkMacUnregisterMacWindow +#define TkMacUnregisterMacWindow \ + (tkIntPlatStubsPtr->tkMacUnregisterMacWindow) /* 51 */ +#endif +#ifndef TkMacUseMenuID +#define TkMacUseMenuID \ + (tkIntPlatStubsPtr->tkMacUseMenuID) /* 52 */ +#endif +#ifndef TkMacVisableClipRgn +#define TkMacVisableClipRgn \ + (tkIntPlatStubsPtr->tkMacVisableClipRgn) /* 53 */ +#endif +#ifndef TkMacWinBounds +#define TkMacWinBounds \ + (tkIntPlatStubsPtr->tkMacWinBounds) /* 54 */ +#endif +#ifndef TkMacWindowOffset +#define TkMacWindowOffset \ + (tkIntPlatStubsPtr->tkMacWindowOffset) /* 55 */ +#endif +/* Slot 56 is reserved */ +#ifndef TkSetMacColor +#define TkSetMacColor \ + (tkIntPlatStubsPtr->tkSetMacColor) /* 57 */ +#endif +#ifndef TkSetWMName +#define TkSetWMName \ + (tkIntPlatStubsPtr->tkSetWMName) /* 58 */ +#endif +#ifndef TkSuspendClipboard +#define TkSuspendClipboard \ + (tkIntPlatStubsPtr->tkSuspendClipboard) /* 59 */ +#endif +/* Slot 60 is reserved */ +#ifndef TkMacZoomToplevel +#define TkMacZoomToplevel \ + (tkIntPlatStubsPtr->tkMacZoomToplevel) /* 61 */ +#endif +#ifndef Tk_TopCoordsToWindow +#define Tk_TopCoordsToWindow \ + (tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 62 */ +#endif +#ifndef TkMacContainerId +#define TkMacContainerId \ + (tkIntPlatStubsPtr->tkMacContainerId) /* 63 */ +#endif +#ifndef TkMacGetHostToplevel +#define TkMacGetHostToplevel \ + (tkIntPlatStubsPtr->tkMacGetHostToplevel) /* 64 */ +#endif +#ifndef TkMacPreprocessMenu +#define TkMacPreprocessMenu \ + (tkIntPlatStubsPtr->tkMacPreprocessMenu) /* 65 */ +#endif +#endif /* MAC_TCL */ + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINTPLATDECLS */ diff --git a/Utilities/TclTk/internals/tk8.3/tkMacDefault.h b/Utilities/TclTk/internals/tk8.3/tkMacDefault.h new file mode 100644 index 0000000..0cf937d --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkMacDefault.h @@ -0,0 +1,465 @@ +/* + * tkMacDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacDefault.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKMACDEFAULT +#define _TKMACDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * SELECT_FG - Foreground color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "Black" +#define WHITE "White" + +#define NORMAL_BG "systemWindowBody" +#define ACTIVE_BG "#ececec" +#define SELECT_BG "systemHighlight" +#define SELECT_FG "systemHighlightText" +#define TROUGH "#c3c3c3" +#define INDICATOR "#b03060" +#define DISABLED "#a3a3a3" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR "systemButtonText" +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR "systemButtonFace" +#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +#define DEF_BUTTON_BG_COLOR "systemButtonFace" +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +#define DEF_BUTTON_FG "systemButtonText" +#define DEF_CHKRAD_FG DEF_BUTTON_FG +#define DEF_BUTTON_FONT "system" +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT "systemButtonFrame" +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "4" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_PADX "7" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "3" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "flat" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT_WIDTH "3" +#define DEF_CANVAS_INSERT_BG BLACK +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR BLACK +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_BG_MONO WHITE +/* #define DEF_ENTRY_BORDER_WIDTH "2" */ +#define DEF_ENTRY_BORDER_WIDTH "1" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT "Helvetica 12" +#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT BLACK +/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */ +#define DEF_ENTRY_HIGHLIGHT_WIDTH "0" +#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +/* #define DEF_ENTRY_INSERT_WIDTH "2" */ +#define DEF_ENTRY_INSERT_WIDTH "1" +#define DEF_ENTRY_JUSTIFY "left" +/* #define DEF_ENTRY_RELIEF "sunken" */ +#define DEF_ENTRY_RELIEF "solid" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "1" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_USE "" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_BG_COLOR NORMAL_BG +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "1" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT "application" +#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "0" +#define DEF_LISTBOX_RELIEF "solid" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "0" +#define DEF_LISTBOX_SELECT_FG_COLOR SELECT_FG +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR "SystemMenuActive" +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "0" +#define DEF_MENU_ACTIVE_FG_COLOR "SystemMenuActiveText" +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR "SystemMenu" +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "0" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR "SystemMenuDisabled" +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT "system" +#define DEF_MENU_FG "SystemMenuText" +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "flat" +#define DEF_MENU_SELECT_COLOR "SystemMenuActive" +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT "system" +#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT BLACK +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +/* #define DEF_MENUBUTTON_JUSTIFY "center" */ +#define DEF_MENUBUTTON_JUSTIFY "left" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FONT "system" +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT "system" +#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT_WIDTH "0" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +/* #define DEF_SCROLLBAR_BORDER_WIDTH "2" */ +#define DEF_SCROLLBAR_BORDER_WIDTH "0" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT BLACK +/* #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "2" */ +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +/*#define DEF_SCROLLBAR_RELIEF "sunken" */ +#define DEF_SCROLLBAR_RELIEF "flat" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +/*#define DEF_SCROLLBAR_WIDTH "15" */ +#define DEF_SCROLLBAR_WIDTH "16" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_BG_COLOR NORMAL_BG +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "0" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG BLACK +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT "Courier 12" +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT_WIDTH "3" +#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_WIDTH "1" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "flat" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "1" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR SELECT_FG +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "solid" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT "Helvetica 12" + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" + +#endif /* _TKMACDEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.3/tkPlatDecls.h b/Utilities/TclTk/internals/tk8.3/tkPlatDecls.h new file mode 100644 index 0000000..434ddba --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkPlatDecls.h @@ -0,0 +1,208 @@ +/* + * tkPlatDecls.h -- + * + * Declarations of functions in the platform-specific public Tcl API. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkPlatDecls.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKPLATDECLS +#define _TKPLATDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tk.decls script. + */ + + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +#ifdef __WIN32__ +/* 0 */ +EXTERN Window Tk_AttachHWND _ANSI_ARGS_((Tk_Window tkwin, + HWND hwnd)); +/* 1 */ +EXTERN HINSTANCE Tk_GetHINSTANCE _ANSI_ARGS_((void)); +/* 2 */ +EXTERN HWND Tk_GetHWND _ANSI_ARGS_((Window window)); +/* 3 */ +EXTERN Tk_Window Tk_HWNDToWindow _ANSI_ARGS_((HWND hwnd)); +/* 4 */ +EXTERN void Tk_PointerEvent _ANSI_ARGS_((HWND hwnd, int x, int y)); +/* 5 */ +EXTERN int Tk_TranslateWinEvent _ANSI_ARGS_((HWND hwnd, + UINT message, WPARAM wParam, LPARAM lParam, + LRESULT * result)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN void Tk_MacSetEmbedHandler _ANSI_ARGS_(( + Tk_MacEmbedRegisterWinProc * registerWinProcPtr, + Tk_MacEmbedGetGrafPortProc * getPortProcPtr, + Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, + Tk_MacEmbedGetClipProc * getClipProc, + Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); +/* 1 */ +EXTERN void Tk_MacTurnOffMenus _ANSI_ARGS_((void)); +/* 2 */ +EXTERN void Tk_MacTkOwnsCursor _ANSI_ARGS_((int tkOwnsIt)); +/* 3 */ +EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp * interp)); +/* 4 */ +EXTERN void TkMacInitAppleEvents _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 5 */ +EXTERN int TkMacConvertEvent _ANSI_ARGS_(( + EventRecord * eventPtr)); +/* 6 */ +EXTERN int TkMacConvertTkEvent _ANSI_ARGS_(( + EventRecord * eventPtr, Window window)); +/* 7 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +/* 8 */ +EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr)); +/* 9 */ +EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void)); +/* 10 */ +EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable)); +#endif /* MAC_TCL */ + +typedef struct TkPlatStubs { + int magic; + struct TkPlatStubHooks *hooks; + +#ifdef __WIN32__ + Window (*tk_AttachHWND) _ANSI_ARGS_((Tk_Window tkwin, HWND hwnd)); /* 0 */ + HINSTANCE (*tk_GetHINSTANCE) _ANSI_ARGS_((void)); /* 1 */ + HWND (*tk_GetHWND) _ANSI_ARGS_((Window window)); /* 2 */ + Tk_Window (*tk_HWNDToWindow) _ANSI_ARGS_((HWND hwnd)); /* 3 */ + void (*tk_PointerEvent) _ANSI_ARGS_((HWND hwnd, int x, int y)); /* 4 */ + int (*tk_TranslateWinEvent) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT * result)); /* 5 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tk_MacSetEmbedHandler) _ANSI_ARGS_((Tk_MacEmbedRegisterWinProc * registerWinProcPtr, Tk_MacEmbedGetGrafPortProc * getPortProcPtr, Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, Tk_MacEmbedGetClipProc * getClipProc, Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); /* 0 */ + void (*tk_MacTurnOffMenus) _ANSI_ARGS_((void)); /* 1 */ + void (*tk_MacTkOwnsCursor) _ANSI_ARGS_((int tkOwnsIt)); /* 2 */ + void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 3 */ + void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 4 */ + int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord * eventPtr)); /* 5 */ + int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord * eventPtr, Window window)); /* 6 */ + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 7 */ + void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 8 */ + int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 9 */ + GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 10 */ +#endif /* MAC_TCL */ +} TkPlatStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkPlatStubs *tkPlatStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifdef __WIN32__ +#ifndef Tk_AttachHWND +#define Tk_AttachHWND \ + (tkPlatStubsPtr->tk_AttachHWND) /* 0 */ +#endif +#ifndef Tk_GetHINSTANCE +#define Tk_GetHINSTANCE \ + (tkPlatStubsPtr->tk_GetHINSTANCE) /* 1 */ +#endif +#ifndef Tk_GetHWND +#define Tk_GetHWND \ + (tkPlatStubsPtr->tk_GetHWND) /* 2 */ +#endif +#ifndef Tk_HWNDToWindow +#define Tk_HWNDToWindow \ + (tkPlatStubsPtr->tk_HWNDToWindow) /* 3 */ +#endif +#ifndef Tk_PointerEvent +#define Tk_PointerEvent \ + (tkPlatStubsPtr->tk_PointerEvent) /* 4 */ +#endif +#ifndef Tk_TranslateWinEvent +#define Tk_TranslateWinEvent \ + (tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef Tk_MacSetEmbedHandler +#define Tk_MacSetEmbedHandler \ + (tkPlatStubsPtr->tk_MacSetEmbedHandler) /* 0 */ +#endif +#ifndef Tk_MacTurnOffMenus +#define Tk_MacTurnOffMenus \ + (tkPlatStubsPtr->tk_MacTurnOffMenus) /* 1 */ +#endif +#ifndef Tk_MacTkOwnsCursor +#define Tk_MacTkOwnsCursor \ + (tkPlatStubsPtr->tk_MacTkOwnsCursor) /* 2 */ +#endif +#ifndef TkMacInitMenus +#define TkMacInitMenus \ + (tkPlatStubsPtr->tkMacInitMenus) /* 3 */ +#endif +#ifndef TkMacInitAppleEvents +#define TkMacInitAppleEvents \ + (tkPlatStubsPtr->tkMacInitAppleEvents) /* 4 */ +#endif +#ifndef TkMacConvertEvent +#define TkMacConvertEvent \ + (tkPlatStubsPtr->tkMacConvertEvent) /* 5 */ +#endif +#ifndef TkMacConvertTkEvent +#define TkMacConvertTkEvent \ + (tkPlatStubsPtr->tkMacConvertTkEvent) /* 6 */ +#endif +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkPlatStubsPtr->tkGenWMConfigureEvent) /* 7 */ +#endif +#ifndef TkMacInvalClipRgns +#define TkMacInvalClipRgns \ + (tkPlatStubsPtr->tkMacInvalClipRgns) /* 8 */ +#endif +#ifndef TkMacHaveAppearance +#define TkMacHaveAppearance \ + (tkPlatStubsPtr->tkMacHaveAppearance) /* 9 */ +#endif +#ifndef TkMacGetDrawablePort +#define TkMacGetDrawablePort \ + (tkPlatStubsPtr->tkMacGetDrawablePort) /* 10 */ +#endif +#endif /* MAC_TCL */ + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKPLATDECLS */ diff --git a/Utilities/TclTk/internals/tk8.3/tkPort.h b/Utilities/TclTk/internals/tk8.3/tkPort.h new file mode 100644 index 0000000..21509a8 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkPort.h @@ -0,0 +1,36 @@ +/* + * tkPort.h -- + * + * This header file handles porting issues that occur because of + * differences between systems. It reads in platform specific + * portability files. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkPort.h,v 1.1.22.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKPORT +#define _TKPORT + +#ifndef _TK +#include "tk.h" +#endif +#ifndef _TCL +#include "tcl.h" +#endif + +#if defined(__WIN32__) || defined(_WIN32) +# include "tkWinPort.h" +#else +# if defined(MAC_TCL) +# include "tkMacPort.h" +# else +# include "tkUnixPort.h" +# endif +#endif + +#endif /* _TKPORT */ diff --git a/Utilities/TclTk/internals/tk8.3/tkUnixDefault.h b/Utilities/TclTk/internals/tk8.3/tkUnixDefault.h new file mode 100644 index 0000000..a4a9b34 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkUnixDefault.h @@ -0,0 +1,454 @@ +/* + * tkUnixDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkUnixDefault.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKUNIXDEFAULT +#define _TKUNIXDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "Black" +#define WHITE "White" + +#define NORMAL_BG "#d9d9d9" +#define ACTIVE_BG "#ececec" +#define SELECT_BG "#c3c3c3" +#define TROUGH "#c3c3c3" +#define INDICATOR "#b03060" +#define DISABLED "#a3a3a3" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +#define DEF_BUTTON_BG_COLOR NORMAL_BG +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +#define DEF_BUTTON_FG BLACK +#define DEF_CHKRAD_FG DEF_BUTTON_FG +#define DEF_BUTTON_FONT "Helvetica -12 bold" +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT BLACK +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "1" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_PADX "3m" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "1m" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "raised" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT_WIDTH "1" +#define DEF_CANVAS_INSERT_BG BLACK +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR BLACK +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_BG_MONO WHITE +#define DEF_ENTRY_BORDER_WIDTH "2" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT "Helvetica -12" +#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT BLACK +#define DEF_ENTRY_HIGHLIGHT_WIDTH "1" +#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +#define DEF_ENTRY_INSERT_WIDTH "2" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_RELIEF "sunken" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "1" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR BLACK +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_USE "" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_BG_COLOR NORMAL_BG +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "2" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT "Helvetica -12 bold" +#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1" +#define DEF_LISTBOX_RELIEF "sunken" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "1" +#define DEF_LISTBOX_SELECT_FG_COLOR BLACK +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "2" +#define DEF_MENU_ACTIVE_FG_COLOR BLACK +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR NORMAL_BG +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "2" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR DISABLED +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT "Helvetica -12 bold" +#define DEF_MENU_FG BLACK +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "raised" +#define DEF_MENU_SELECT_COLOR INDICATOR +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT "Helvetica -12 bold" +#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT BLACK +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +#define DEF_MENUBUTTON_JUSTIFY "center" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FONT "Helvetica -12 bold" +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT "Helvetica -12 bold" +#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT_WIDTH "1" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +#define DEF_SCROLLBAR_BORDER_WIDTH "2" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT BLACK +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "1" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +#define DEF_SCROLLBAR_RELIEF "sunken" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +#define DEF_SCROLLBAR_WIDTH "15" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_BG_COLOR NORMAL_BG +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "2" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG BLACK +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT "Courier -12" +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT_WIDTH "1" +#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_WIDTH "2" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "sunken" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "1" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR BLACK +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "raised" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT "Helvetica -12" + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" + +#endif /* _TKUNIXDEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.3/tkUnixPort.h b/Utilities/TclTk/internals/tk8.3/tkUnixPort.h new file mode 100644 index 0000000..a2e12ff --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkUnixPort.h @@ -0,0 +1,225 @@ +/* + * tkUnixPort.h -- + * + * This file is included by all of the Tk C files. It contains + * information that may be configuration-dependent, such as + * #includes for system include files and a few other things. + * + * Copyright (c) 1991-1993 The Regents of the University of California. + * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkUnixPort.h,v 1.1.2.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _UNIXPORT +#define _UNIXPORT + +#define __UNIX__ 1 + +/* + * Macro to use instead of "void" for arguments that must have + * type "void *" in ANSI C; maps them to type "char *" in + * non-ANSI systems. This macro may be used in some of the include + * files below, which is why it is defined here. + */ + +#ifndef VOID +# ifdef __STDC__ +# define VOID void +# else +# define VOID char +# endif +#endif + +#include +#include +#include +#ifdef HAVE_LIMITS_H +# include +#else +# include "../compat/limits.h" +#endif +#include +#include +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include +#endif +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#include +#ifndef _TCL +# include +#endif +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifdef HAVE_UNISTD_H +# include +#else +# include "../compat/unistd.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +/* + * The following macro defines the type of the mask arguments to + * select: + */ + +#ifndef NO_FD_SET +# define SELECT_MASK fd_set +#else +# ifndef _AIX + typedef long fd_mask; +# endif +# if defined(_IBMR2) +# define SELECT_MASK void +# else +# define SELECT_MASK int +# endif +#endif + +/* + * The following macro defines the number of fd_masks in an fd_set: + */ + +#ifndef FD_SETSIZE +# ifdef OPEN_MAX +# define FD_SETSIZE OPEN_MAX +# else +# define FD_SETSIZE 256 +# endif +#endif +#if !defined(howmany) +# define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef NFDBITS +# define NFDBITS NBBY*sizeof(fd_mask) +#endif +#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS) + +/* + * Not all systems declare the errno variable in errno.h. so this + * file does it explicitly. + */ + +extern int errno; + +/* + * Define "NBBY" (number of bits per byte) if it's not already defined. + */ + +#ifndef NBBY +# define NBBY 8 +#endif + +/* + * These macros are just wrappers for the equivalent X Region calls. + */ + +#define TkClipBox(rgn, rect) XClipBox((Region) rgn, rect) +#define TkCreateRegion() (TkRegion) XCreateRegion() +#define TkDestroyRegion(rgn) XDestroyRegion((Region) rgn) +#define TkIntersectRegion(a, b, r) XIntersectRegion((Region) a, \ + (Region) b, (Region) r) +#define TkRectInRegion(r, x, y, w, h) XRectInRegion((Region) r, x, y, w, h) +#define TkSetRegion(d, gc, rgn) XSetRegion(d, gc, (Region) rgn) +#define TkUnionRectWithRegion(rect, src, ret) XUnionRectWithRegion(rect, \ + (Region) src, (Region) ret) + +/* + * The TkPutImage macro strips off the color table information, which isn't + * needed for X. + */ + +#define TkPutImage(colors, ncolors, display, pixels, gc, image, destx, desty, srcx, srcy, width, height) \ + XPutImage(display, pixels, gc, image, destx, desty, srcx, \ + srcy, width, height); + +/* + * Supply macros for seek offsets, if they're not already provided by + * an include file. + */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +#ifndef SEEK_CUR +# define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +# define SEEK_END 2 +#endif + +/* + * Declarations for various library procedures that may not be declared + * in any other header file. + */ + + +/* + * These functions do nothing under Unix, so we just eliminate calls to them. + */ + +#define TkpButtonSetDefaults(specPtr) {} +#define TkpDestroyButton(butPtr) {} +#define TkSelUpdateClipboard(a,b) {} +#define TkSetPixmapColormap(p,c) {} + +/* + * These calls implement native bitmaps which are not supported under + * UNIX. The macros eliminate the calls. + */ + +#define TkpDefineNativeBitmaps() +#define TkpCreateNativeBitmap(display, source) None +#define TkpGetNativeAppBitmap(display, name, w, h) None + +/* + * This macro stores a representation of the window handle in a string. + * This should perhaps use the real size of an XID. + */ + +#define TkpPrintWindowId(buf,w) \ + sprintf((buf), "%#08lx", (unsigned long) (w)) + +/* + * This macro indicates that entry and text widgets should display + * the selection highlight regardless of which window has the focus. + */ + +#define ALWAYS_SHOW_SELECTION + +/* + * The following declaration is used to get access to a private Tcl interface + * that is needed for portability reasons. + */ + +#ifndef _TCLINT +#include +#endif + +#endif /* _UNIXPORT */ diff --git a/Utilities/TclTk/internals/tk8.3/tkWin.h b/Utilities/TclTk/internals/tk8.3/tkWin.h new file mode 100644 index 0000000..32e137e --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkWin.h @@ -0,0 +1,55 @@ +/* + * tkWin.h -- + * + * Declarations of public types and interfaces that are only + * available under Windows. + * + * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWin.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKWIN +#define _TKWIN + +#ifndef _TK +#include +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#ifdef BUILD_tk +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * The following messages are use to communicate between a Tk toplevel + * and its container window. + */ + +#define TK_CLAIMFOCUS (WM_USER) +#define TK_GEOMETRYREQ (WM_USER+1) +#define TK_ATTACHWINDOW (WM_USER+2) +#define TK_DETACHWINDOW (WM_USER+3) + + +/* + *-------------------------------------------------------------- + * + * Exported procedures defined for the Windows platform only. + * + *-------------------------------------------------------------- + */ + +#include "tkPlatDecls.h" + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKWIN */ diff --git a/Utilities/TclTk/internals/tk8.3/tkWinDefault.h b/Utilities/TclTk/internals/tk8.3/tkWinDefault.h new file mode 100644 index 0000000..dfc23d3 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkWinDefault.h @@ -0,0 +1,460 @@ +/* + * tkWinDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinDefault.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKWINDEFAULT +#define _TKWINDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "Black" +#define WHITE "White" + +#define CTL_FONT "{MS Sans Serif} 8" +#define NORMAL_BG "SystemButtonFace" +#define NORMAL_FG "SystemButtonText" +#define ACTIVE_BG NORMAL_BG +#define TEXT_FG "SystemWindowText" +#define SELECT_BG "SystemHighlight" +#define SELECT_FG "SystemHighlightText" +#define TROUGH "SystemScrollbar" +#define INDICATOR "SystemWindow" +#define DISABLED "SystemDisabledText" +#define MENU_BG "SystemMenu" +#define MENU_FG "SystemMenuText" +#define HIGHLIGHT "SystemWindowFrame" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR NORMAL_BG +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR NORMAL_FG +#define DEF_CHKRAD_ACTIVE_FG_COLOR TEXT_FG +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +#define DEF_BUTTON_BG_COLOR NORMAL_BG +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +#define DEF_BUTTON_FG NORMAL_FG +#define DEF_CHKRAD_FG TEXT_FG +#define DEF_BUTTON_FONT CTL_FONT +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT HIGHLIGHT +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "1" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_PADX "1" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "1" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "raised" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT HIGHLIGHT +#define DEF_CANVAS_HIGHLIGHT_WIDTH "2" +#define DEF_CANVAS_INSERT_BG NORMAL_FG +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR SELECT_FG +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR "SystemWindow" +#define DEF_ENTRY_BG_MONO WHITE +#define DEF_ENTRY_BORDER_WIDTH "2" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT CTL_FONT +#define DEF_ENTRY_FG TEXT_FG +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT HIGHLIGHT +#define DEF_ENTRY_HIGHLIGHT_WIDTH "0" +#define DEF_ENTRY_INSERT_BG TEXT_FG +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +#define DEF_ENTRY_INSERT_WIDTH "2" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_RELIEF "sunken" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "0" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT HIGHLIGHT +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_USE "" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_BG_COLOR NORMAL_BG +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "2" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT CTL_FONT +#define DEF_LISTBOX_FG NORMAL_FG +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT HIGHLIGHT +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1" +#define DEF_LISTBOX_RELIEF "sunken" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "1" +#define DEF_LISTBOX_SELECT_FG_COLOR SELECT_FG +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR SELECT_BG +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "0" +#define DEF_MENU_ACTIVE_FG_COLOR SELECT_FG +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR MENU_BG +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "0" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR DISABLED +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT CTL_FONT +#define DEF_MENU_FG MENU_FG +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "flat" +#define DEF_MENU_SELECT_COLOR MENU_FG +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR NORMAL_FG +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT CTL_FONT +#define DEF_MENUBUTTON_FG NORMAL_FG +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT HIGHLIGHT +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +#define DEF_MENUBUTTON_JUSTIFY "center" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG NORMAL_FG +#define DEF_MESSAGE_FONT CTL_FONT +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT HIGHLIGHT +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT CTL_FONT +#define DEF_SCALE_FG_COLOR NORMAL_FG +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT HIGHLIGHT +#define DEF_SCALE_HIGHLIGHT_WIDTH "2" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +#define DEF_SCROLLBAR_BORDER_WIDTH "0" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT HIGHLIGHT +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +#define DEF_SCROLLBAR_RELIEF "sunken" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +#define DEF_SCROLLBAR_WIDTH "10" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_BG_COLOR "SystemWindow" +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "2" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG TEXT_FG +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT CTL_FONT +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT HIGHLIGHT +#define DEF_TEXT_HIGHLIGHT_WIDTH "0" +#define DEF_TEXT_INSERT_BG TEXT_FG +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_WIDTH "2" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "sunken" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "0" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR SELECT_FG +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "flat" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT CTL_FONT + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" + +#endif /* _TKWINDEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.3/tkWinInt.h b/Utilities/TclTk/internals/tk8.3/tkWinInt.h new file mode 100644 index 0000000..4a30bd9 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkWinInt.h @@ -0,0 +1,171 @@ +/* + * tkWinInt.h -- + * + * This file contains declarations that are shared among the + * Windows-specific parts of Tk, but aren't used by the rest of + * Tk. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1998-2000 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinInt.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKWININT +#define _TKWININT + +#ifndef _TKINT +#include "tkInt.h" +#endif + +/* + * Include platform specific public interfaces. + */ + +#ifndef _TKWIN +#include "tkWin.h" +#endif + +#ifndef _TKPORT +#include "tkPort.h" +#endif + + +/* + * Define constants missing from older Win32 SDK header files. + */ + +#ifndef WS_EX_TOOLWINDOW +#define WS_EX_TOOLWINDOW 0x00000080L +#endif + +/* + * The TkWinDCState is used to save the state of a device context + * so that it can be restored later. + */ + +typedef struct TkWinDCState { + HPALETTE palette; + int bkmode; +} TkWinDCState; + +/* + * The TkWinDrawable is the internal implementation of an X Drawable (either + * a Window or a Pixmap). The following constants define the valid Drawable + * types. + */ + +#define TWD_BITMAP 1 +#define TWD_WINDOW 2 +#define TWD_WINDC 3 + +typedef struct { + int type; + HWND handle; + TkWindow *winPtr; +} TkWinWindow; + +typedef struct { + int type; + HBITMAP handle; + Colormap colormap; + int depth; +} TkWinBitmap; + +typedef struct { + int type; + HDC hdc; +}TkWinDC; + +typedef union { + int type; + TkWinWindow window; + TkWinBitmap bitmap; + TkWinDC winDC; +} TkWinDrawable; + +/* + * The following macros are used to retrieve internal values from a Drawable. + */ + +#define TkWinGetHWND(w) (((TkWinDrawable *) w)->window.handle) +#define TkWinGetWinPtr(w) (((TkWinDrawable *) w)->window.winPtr) +#define TkWinGetHBITMAP(w) (((TkWinDrawable *) w)->bitmap.handle) +#define TkWinGetColormap(w) (((TkWinDrawable *) w)->bitmap.colormap) +#define TkWinGetHDC(w) (((TkWinDrawable *) w)->winDC.hdc) + +/* + * The following structure is used to encapsulate palette information. + */ + +typedef struct { + HPALETTE palette; /* Palette handle used when drawing. */ + UINT size; /* Number of entries in the palette. */ + int stale; /* 1 if palette needs to be realized, + * otherwise 0. If the palette is stale, + * then an idle handler is scheduled to + * realize the palette. */ + Tcl_HashTable refCounts; /* Hash table of palette entry reference counts + * indexed by pixel value. */ +} TkWinColormap; + +/* + * The following macro retrieves the Win32 palette from a colormap. + */ + +#define TkWinGetPalette(colormap) (((TkWinColormap *) colormap)->palette) + +/* + * The following macros define the class names for Tk Window types. + */ + +#define TK_WIN_TOPLEVEL_CLASS_NAME "TkTopLevel" +#define TK_WIN_CHILD_CLASS_NAME "TkChild" + +/* + * The following variable is a translation table between X gc functions and + * Win32 raster op modes. + */ + +extern int tkpWinRopModes[]; + +/* + * The following defines are used with TkWinGetBorderPixels to get the + * extra 2 border colors from a Tk_3DBorder. + */ + +#define TK_3D_LIGHT2 TK_3D_DARK_GC+1 +#define TK_3D_DARK2 TK_3D_DARK_GC+2 + +/* + * Internal procedures used by more than one source file. + */ + +#include "tkIntPlatDecls.h" + +/* + * We need to specially add the TkWinChildProc because of the special + * prototype it has (doesn't fit into stubs schema) + */ +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +EXTERN LRESULT CALLBACK TkWinChildProc _ANSI_ARGS_((HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam)); + +/* + * Special proc needed as tsd accessor function between + * tkWinX.c:GenerateXEvent and tkWinClipboard.c:UpdateClipboard + */ +EXTERN void TkWinUpdatingClipboard(int mode); + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKWININT */ + diff --git a/Utilities/TclTk/internals/tk8.3/tkWinPort.h b/Utilities/TclTk/internals/tk8.3/tkWinPort.h new file mode 100644 index 0000000..97234cb --- /dev/null +++ b/Utilities/TclTk/internals/tk8.3/tkWinPort.h @@ -0,0 +1,129 @@ +/* + * tkWinPort.h -- + * + * This header file handles porting issues that occur because of + * differences between Windows and Unix. It should be the only + * file that contains #ifdefs to handle different flavors of OS. + * + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinPort.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _WINPORT +#define _WINPORT + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Need to block out this include for building extensions with MetroWerks + * compiler for Win32. + */ + +#ifndef __MWERKS__ +#include +#endif + +#include +#include + +#ifdef _MSC_VER +# define hypot _hypot +#endif /* _MSC_VER */ + +#ifndef __GNUC__ +# define strncasecmp strnicmp +# define strcasecmp stricmp +#endif + +#define NBBY 8 + +#define OPEN_MAX 32 + +/* + * The following define causes Tk to use its internal keysym hash table + */ + +#define REDO_KEYSYM_LOOKUP + +/* + * The following macro checks to see whether there is buffered + * input data available for a stdio FILE. + */ + +#ifdef _MSC_VER +# define TK_READ_DATA_PENDING(f) ((f)->_cnt > 0) +#else /* _MSC_VER */ +# define TK_READ_DATA_PENDING(f) ((f)->level > 0) +#endif /* _MSC_VER */ + +/* + * The following stubs implement various calls that don't do anything + * under Windows. + */ + +#define TkFreeWindowId(dispPtr,w) +#define TkInitXId(dispPtr) +#define TkpCmapStressed(tkwin,colormap) (0) +#define XFlush(display) +#define XGrabServer(display) +#define XUngrabServer(display) +#define TkpSync(display) + +/* + * The following functions are implemented as macros under Windows. + */ + +#define XFree(data) {if ((data) != NULL) ckfree((char *) (data));} +#define XNoOp(display) {display->request++;} +#define XSynchronize(display, bool) {display->request++;} +#define XSync(display, bool) {display->request++;} +#define XVisualIDFromVisual(visual) (visual->visualid) + +/* + * The following Tk functions are implemented as macros under Windows. + */ + +#define TkpGetPixel(p) (((((p)->red >> 8) & 0xff) \ + | ((p)->green & 0xff00) | (((p)->blue << 8) & 0xff0000)) | 0x20000000) + +/* + * These calls implement native bitmaps which are not currently + * supported under Windows. The macros eliminate the calls. + */ + +#define TkpDefineNativeBitmaps() +#define TkpCreateNativeBitmap(display, source) None +#define TkpGetNativeAppBitmap(display, name, w, h) None + +/* + * Define timezone for gettimeofday. + */ + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +#ifndef _TCLINT +#include +#endif + +#endif /* _WINPORT */ diff --git a/Utilities/TclTk/internals/tk8.4/CMakeLists.txt b/Utilities/TclTk/internals/tk8.4/CMakeLists.txt new file mode 100644 index 0000000..d5991df --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/CMakeLists.txt @@ -0,0 +1,5 @@ +IF(TK_INTERNAL_PATH) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/TclTk/internals/tk8.4 "\\.h$") + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF(TK_INTERNAL_PATH) diff --git a/Utilities/TclTk/internals/tk8.4/default.h b/Utilities/TclTk/internals/tk8.4/default.h new file mode 100644 index 0000000..0ef8985 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/default.h @@ -0,0 +1,32 @@ +/* + * default.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: default.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _DEFAULT +#define _DEFAULT + +#if defined(__WIN32__) || defined(_WIN32) || \ + defined(__CYGWIN__) || defined(__MINGW32__) +# include "tkWinDefault.h" +#else +# if defined(MAC_OSX_TK) +# include "tkMacOSXDefault.h" +# elif defined(MAC_TCL) +# include "tkMacDefault.h" +# else +# include "tkUnixDefault.h" +# endif +#endif + +#endif /* _DEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.4/tclInt.h b/Utilities/TclTk/internals/tk8.4/tclInt.h new file mode 100644 index 0000000..92af825 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tclInt.h @@ -0,0 +1,2272 @@ +/* + * tclInt.h -- + * + * Declarations of things used internally by the Tcl interpreter. + * + * Copyright (c) 1987-1993 The Regents of the University of California. + * Copyright (c) 1993-1997 Lucent Technologies. + * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclInt.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TCLINT +#define _TCLINT + +/* + * Common include files needed by most of the Tcl source files are + * included here, so that system-dependent personalizations for the + * include files only have to be made in once place. This results + * in a few extra includes, but greater modularity. The order of + * the three groups of #includes is important. For example, stdio.h + * is needed by tcl.h, and the _ANSI_ARGS_ declaration in tcl.h is + * needed by stdlib.h in some configurations. + */ + +#ifndef _TCL +#include "tcl.h" +#endif + +#include + +#include +#ifdef NO_LIMITS_H +# include "../compat/limits.h" +#else +# include +#endif +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include +#endif +#ifdef NO_STRING_H +#include "../compat/string.h" +#else +#include +#endif + +#undef TCL_STORAGE_CLASS +#ifdef BUILD_tcl +# define TCL_STORAGE_CLASS DLLEXPORT +#else +# ifdef USE_TCL_STUBS +# define TCL_STORAGE_CLASS +# else +# define TCL_STORAGE_CLASS DLLIMPORT +# endif +#endif + +/* + * The following procedures allow namespaces to be customized to + * support special name resolution rules for commands/variables. + * + */ + +struct Tcl_ResolvedVarInfo; + +typedef Tcl_Var (Tcl_ResolveRuntimeVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, struct Tcl_ResolvedVarInfo *vinfoPtr)); + +typedef void (Tcl_ResolveVarDeleteProc) _ANSI_ARGS_(( + struct Tcl_ResolvedVarInfo *vinfoPtr)); + +/* + * The following structure encapsulates the routines needed to resolve a + * variable reference at runtime. Any variable specific state will typically + * be appended to this structure. + */ + + +typedef struct Tcl_ResolvedVarInfo { + Tcl_ResolveRuntimeVarProc *fetchProc; + Tcl_ResolveVarDeleteProc *deleteProc; +} Tcl_ResolvedVarInfo; + + + +typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, CONST84 char* name, int length, + Tcl_Namespace *context, Tcl_ResolvedVarInfo **rPtr)); + +typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_(( + Tcl_Interp* interp, CONST84 char* name, Tcl_Namespace *context, + int flags, Tcl_Var *rPtr)); + +typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((Tcl_Interp* interp, + CONST84 char* name, Tcl_Namespace *context, int flags, + Tcl_Command *rPtr)); + +typedef struct Tcl_ResolverInfo { + Tcl_ResolveCmdProc *cmdResProc; /* Procedure handling command name + * resolution. */ + Tcl_ResolveVarProc *varResProc; /* Procedure handling variable name + * resolution for variables that + * can only be handled at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* Procedure handling variable name + * resolution at compile time. */ +} Tcl_ResolverInfo; + +/* + *---------------------------------------------------------------- + * Data structures related to namespaces. + *---------------------------------------------------------------- + */ + +/* + * The structure below defines a namespace. + * Note: the first five fields must match exactly the fields in a + * Tcl_Namespace structure (see tcl.h). If you change one, be sure to + * change the other. + */ + +typedef struct Namespace { + char *name; /* The namespace's simple (unqualified) + * name. This contains no ::'s. The name of + * the global namespace is "" although "::" + * is an synonym. */ + char *fullName; /* The namespace's fully qualified name. + * This starts with ::. */ + ClientData clientData; /* An arbitrary value associated with this + * namespace. */ + Tcl_NamespaceDeleteProc *deleteProc; + /* Procedure invoked when deleting the + * namespace to, e.g., free clientData. */ + struct Namespace *parentPtr; /* Points to the namespace that contains + * this one. NULL if this is the global + * namespace. */ + Tcl_HashTable childTable; /* Contains any child namespaces. Indexed + * by strings; values have type + * (Namespace *). */ + long nsId; /* Unique id for the namespace. */ + Tcl_Interp *interp; /* The interpreter containing this + * namespace. */ + int flags; /* OR-ed combination of the namespace + * status flags NS_DYING and NS_DEAD + * listed below. */ + int activationCount; /* Number of "activations" or active call + * frames for this namespace that are on + * the Tcl call stack. The namespace won't + * be freed until activationCount becomes + * zero. */ + int refCount; /* Count of references by namespaceName * + * objects. The namespace can't be freed + * until refCount becomes zero. */ + Tcl_HashTable cmdTable; /* Contains all the commands currently + * registered in the namespace. Indexed by + * strings; values have type (Command *). + * Commands imported by Tcl_Import have + * Command structures that point (via an + * ImportedCmdRef structure) to the + * Command structure in the source + * namespace's command table. */ + Tcl_HashTable varTable; /* Contains all the (global) variables + * currently in this namespace. Indexed + * by strings; values have type (Var *). */ + char **exportArrayPtr; /* Points to an array of string patterns + * specifying which commands are exported. + * A pattern may include "string match" + * style wildcard characters to specify + * multiple commands; however, no namespace + * qualifiers are allowed. NULL if no + * export patterns are registered. */ + int numExportPatterns; /* Number of export patterns currently + * registered using "namespace export". */ + int maxExportPatterns; /* Mumber of export patterns for which + * space is currently allocated. */ + int cmdRefEpoch; /* Incremented if a newly added command + * shadows a command for which this + * namespace has already cached a Command * + * pointer; this causes all its cached + * Command* pointers to be invalidated. */ + int resolverEpoch; /* Incremented whenever (a) the name resolution + * rules change for this namespace or (b) a + * newly added command shadows a command that + * is compiled to bytecodes. + * This invalidates all byte codes compiled + * in the namespace, causing the code to be + * recompiled under the new rules.*/ + Tcl_ResolveCmdProc *cmdResProc; + /* If non-null, this procedure overrides + * the usual command resolution mechanism + * in Tcl. This procedure is invoked + * within Tcl_FindCommand to resolve all + * command references within the namespace. */ + Tcl_ResolveVarProc *varResProc; + /* If non-null, this procedure overrides + * the usual variable resolution mechanism + * in Tcl. This procedure is invoked + * within Tcl_FindNamespaceVar to resolve all + * variable references within the namespace + * at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* If non-null, this procedure overrides + * the usual variable resolution mechanism + * in Tcl. This procedure is invoked + * within LookupCompiledLocal to resolve + * variable references within the namespace + * at compile time. */ +} Namespace; + +/* + * Flags used to represent the status of a namespace: + * + * NS_DYING - 1 means Tcl_DeleteNamespace has been called to delete the + * namespace but there are still active call frames on the Tcl + * stack that refer to the namespace. When the last call frame + * referring to it has been popped, it's variables and command + * will be destroyed and it will be marked "dead" (NS_DEAD). + * The namespace can no longer be looked up by name. + * NS_DEAD - 1 means Tcl_DeleteNamespace has been called to delete the + * namespace and no call frames still refer to it. Its + * variables and command have already been destroyed. This bit + * allows the namespace resolution code to recognize that the + * namespace is "deleted". When the last namespaceName object + * in any byte code code unit that refers to the namespace has + * been freed (i.e., when the namespace's refCount is 0), the + * namespace's storage will be freed. + */ + +#define NS_DYING 0x01 +#define NS_DEAD 0x02 + +/* + * Flag passed to TclGetNamespaceForQualName to have it create all namespace + * components of a namespace-qualified name that cannot be found. The new + * namespaces are created within their specified parent. Note that this + * flag's value must not conflict with the values of the flags + * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, and FIND_ONLY_NS (defined in + * tclNamesp.c). + */ + +#define CREATE_NS_IF_UNKNOWN 0x800 + +/* + *---------------------------------------------------------------- + * Data structures related to variables. These are used primarily + * in tclVar.c + *---------------------------------------------------------------- + */ + +/* + * The following structure defines a variable trace, which is used to + * invoke a specific C procedure whenever certain operations are performed + * on a variable. + */ + +typedef struct VarTrace { + Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given + * by flags are performed on variable. */ + ClientData clientData; /* Argument to pass to proc. */ + int flags; /* What events the trace procedure is + * interested in: OR-ed combination of + * TCL_TRACE_READS, TCL_TRACE_WRITES, + * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */ + struct VarTrace *nextPtr; /* Next in list of traces associated with + * a particular variable. */ +} VarTrace; + +/* + * The following structure defines a command trace, which is used to + * invoke a specific C procedure whenever certain operations are performed + * on a command. + */ + +typedef struct CommandTrace { + Tcl_CommandTraceProc *traceProc;/* Procedure to call when operations given + * by flags are performed on command. */ + ClientData clientData; /* Argument to pass to proc. */ + int flags; /* What events the trace procedure is + * interested in: OR-ed combination of + * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */ + struct CommandTrace *nextPtr; /* Next in list of traces associated with + * a particular command. */ + int refCount; /* Used to ensure this structure is + * not deleted too early. Keeps track + * of how many pieces of code have + * a pointer to this structure. */ +} CommandTrace; + +/* + * When a command trace is active (i.e. its associated procedure is + * executing), one of the following structures is linked into a list + * associated with the command's interpreter. The information in + * the structure is needed in order for Tcl to behave reasonably + * if traces are deleted while traces are active. + */ + +typedef struct ActiveCommandTrace { + struct Command *cmdPtr; /* Command that's being traced. */ + struct ActiveCommandTrace *nextPtr; + /* Next in list of all active command + * traces for the interpreter, or NULL + * if no more. */ + CommandTrace *nextTracePtr; /* Next trace to check after current + * trace procedure returns; if this + * trace gets deleted, must update pointer + * to avoid using free'd memory. */ +} ActiveCommandTrace; + +/* + * When a variable trace is active (i.e. its associated procedure is + * executing), one of the following structures is linked into a list + * associated with the variable's interpreter. The information in + * the structure is needed in order for Tcl to behave reasonably + * if traces are deleted while traces are active. + */ + +typedef struct ActiveVarTrace { + struct Var *varPtr; /* Variable that's being traced. */ + struct ActiveVarTrace *nextPtr; + /* Next in list of all active variable + * traces for the interpreter, or NULL + * if no more. */ + VarTrace *nextTracePtr; /* Next trace to check after current + * trace procedure returns; if this + * trace gets deleted, must update pointer + * to avoid using free'd memory. */ +} ActiveVarTrace; + +/* + * The following structure describes an enumerative search in progress on + * an array variable; this are invoked with options to the "array" + * command. + */ + +typedef struct ArraySearch { + int id; /* Integer id used to distinguish among + * multiple concurrent searches for the + * same array. */ + struct Var *varPtr; /* Pointer to array variable that's being + * searched. */ + Tcl_HashSearch search; /* Info kept by the hash module about + * progress through the array. */ + Tcl_HashEntry *nextEntry; /* Non-null means this is the next element + * to be enumerated (it's leftover from + * the Tcl_FirstHashEntry call or from + * an "array anymore" command). NULL + * means must call Tcl_NextHashEntry + * to get value to return. */ + struct ArraySearch *nextPtr;/* Next in list of all active searches + * for this variable, or NULL if this is + * the last one. */ +} ArraySearch; + +/* + * The structure below defines a variable, which associates a string name + * with a Tcl_Obj value. These structures are kept in procedure call frames + * (for local variables recognized by the compiler) or in the heap (for + * global variables and any variable not known to the compiler). For each + * Var structure in the heap, a hash table entry holds the variable name and + * a pointer to the Var structure. + */ + +typedef struct Var { + union { + Tcl_Obj *objPtr; /* The variable's object value. Used for + * scalar variables and array elements. */ + Tcl_HashTable *tablePtr;/* For array variables, this points to + * information about the hash table used + * to implement the associative array. + * Points to malloc-ed data. */ + struct Var *linkPtr; /* If this is a global variable being + * referred to in a procedure, or a variable + * created by "upvar", this field points to + * the referenced variable's Var struct. */ + } value; + char *name; /* NULL if the variable is in a hashtable, + * otherwise points to the variable's + * name. It is used, e.g., by TclLookupVar + * and "info locals". The storage for the + * characters of the name is not owned by + * the Var and must not be freed when + * freeing the Var. */ + Namespace *nsPtr; /* Points to the namespace that contains + * this variable or NULL if the variable is + * a local variable in a Tcl procedure. */ + Tcl_HashEntry *hPtr; /* If variable is in a hashtable, either the + * hash table entry that refers to this + * variable or NULL if the variable has been + * detached from its hash table (e.g. an + * array is deleted, but some of its + * elements are still referred to in + * upvars). NULL if the variable is not in a + * hashtable. This is used to delete an + * variable from its hashtable if it is no + * longer needed. */ + int refCount; /* Counts number of active uses of this + * variable, not including its entry in the + * call frame or the hash table: 1 for each + * additional variable whose linkPtr points + * here, 1 for each nested trace active on + * variable, and 1 if the variable is a + * namespace variable. This record can't be + * deleted until refCount becomes 0. */ + VarTrace *tracePtr; /* First in list of all traces set for this + * variable. */ + ArraySearch *searchPtr; /* First in list of all searches active + * for this variable, or NULL if none. */ + int flags; /* Miscellaneous bits of information about + * variable. See below for definitions. */ +} Var; + +/* + * Flag bits for variables. The first three (VAR_SCALAR, VAR_ARRAY, and + * VAR_LINK) are mutually exclusive and give the "type" of the variable. + * VAR_UNDEFINED is independent of the variable's type. + * + * VAR_SCALAR - 1 means this is a scalar variable and not + * an array or link. The "objPtr" field points + * to the variable's value, a Tcl object. + * VAR_ARRAY - 1 means this is an array variable rather + * than a scalar variable or link. The + * "tablePtr" field points to the array's + * hashtable for its elements. + * VAR_LINK - 1 means this Var structure contains a + * pointer to another Var structure that + * either has the real value or is itself + * another VAR_LINK pointer. Variables like + * this come about through "upvar" and "global" + * commands, or through references to variables + * in enclosing namespaces. + * VAR_UNDEFINED - 1 means that the variable is in the process + * of being deleted. An undefined variable + * logically does not exist and survives only + * while it has a trace, or if it is a global + * variable currently being used by some + * procedure. + * VAR_IN_HASHTABLE - 1 means this variable is in a hashtable and + * the Var structure is malloced. 0 if it is + * a local variable that was assigned a slot + * in a procedure frame by the compiler so the + * Var storage is part of the call frame. + * VAR_TRACE_ACTIVE - 1 means that trace processing is currently + * underway for a read or write access, so + * new read or write accesses should not cause + * trace procedures to be called and the + * variable can't be deleted. + * VAR_ARRAY_ELEMENT - 1 means that this variable is an array + * element, so it is not legal for it to be + * an array itself (the VAR_ARRAY flag had + * better not be set). + * VAR_NAMESPACE_VAR - 1 means that this variable was declared + * as a namespace variable. This flag ensures + * it persists until its namespace is + * destroyed or until the variable is unset; + * it will persist even if it has not been + * initialized and is marked undefined. + * The variable's refCount is incremented to + * reflect the "reference" from its namespace. + * + * The following additional flags are used with the CompiledLocal type + * defined below: + * + * VAR_ARGUMENT - 1 means that this variable holds a procedure + * argument. + * VAR_TEMPORARY - 1 if the local variable is an anonymous + * temporary variable. Temporaries have a NULL + * name. + * VAR_RESOLVED - 1 if name resolution has been done for this + * variable. + */ + +#define VAR_SCALAR 0x1 +#define VAR_ARRAY 0x2 +#define VAR_LINK 0x4 +#define VAR_UNDEFINED 0x8 +#define VAR_IN_HASHTABLE 0x10 +#define VAR_TRACE_ACTIVE 0x20 +#define VAR_ARRAY_ELEMENT 0x40 +#define VAR_NAMESPACE_VAR 0x80 + +#define VAR_ARGUMENT 0x100 +#define VAR_TEMPORARY 0x200 +#define VAR_RESOLVED 0x400 + +/* + * Macros to ensure that various flag bits are set properly for variables. + * The ANSI C "prototypes" for these macros are: + * + * EXTERN void TclSetVarScalar _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarArray _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarLink _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarArrayElement _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclSetVarUndefined _ANSI_ARGS_((Var *varPtr)); + * EXTERN void TclClearVarUndefined _ANSI_ARGS_((Var *varPtr)); + */ + +#define TclSetVarScalar(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_SCALAR + +#define TclSetVarArray(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_LINK)) | VAR_ARRAY + +#define TclSetVarLink(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~(VAR_SCALAR|VAR_ARRAY)) | VAR_LINK + +#define TclSetVarArrayElement(varPtr) \ + (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT + +#define TclSetVarUndefined(varPtr) \ + (varPtr)->flags |= VAR_UNDEFINED + +#define TclClearVarUndefined(varPtr) \ + (varPtr)->flags &= ~VAR_UNDEFINED + +/* + * Macros to read various flag bits of variables. + * The ANSI C "prototypes" for these macros are: + * + * EXTERN int TclIsVarScalar _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarLink _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArray _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarUndefined _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArrayElement _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarTemporary _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarArgument _ANSI_ARGS_((Var *varPtr)); + * EXTERN int TclIsVarResolved _ANSI_ARGS_((Var *varPtr)); + */ + +#define TclIsVarScalar(varPtr) \ + ((varPtr)->flags & VAR_SCALAR) + +#define TclIsVarLink(varPtr) \ + ((varPtr)->flags & VAR_LINK) + +#define TclIsVarArray(varPtr) \ + ((varPtr)->flags & VAR_ARRAY) + +#define TclIsVarUndefined(varPtr) \ + ((varPtr)->flags & VAR_UNDEFINED) + +#define TclIsVarArrayElement(varPtr) \ + ((varPtr)->flags & VAR_ARRAY_ELEMENT) + +#define TclIsVarTemporary(varPtr) \ + ((varPtr)->flags & VAR_TEMPORARY) + +#define TclIsVarArgument(varPtr) \ + ((varPtr)->flags & VAR_ARGUMENT) + +#define TclIsVarResolved(varPtr) \ + ((varPtr)->flags & VAR_RESOLVED) + +/* + *---------------------------------------------------------------- + * Data structures related to procedures. These are used primarily + * in tclProc.c, tclCompile.c, and tclExecute.c. + *---------------------------------------------------------------- + */ + +/* + * Forward declaration to prevent an error when the forward reference to + * Command is encountered in the Proc and ImportRef types declared below. + */ + +struct Command; + +/* + * The variable-length structure below describes a local variable of a + * procedure that was recognized by the compiler. These variables have a + * name, an element in the array of compiler-assigned local variables in the + * procedure's call frame, and various other items of information. If the + * local variable is a formal argument, it may also have a default value. + * The compiler can't recognize local variables whose names are + * expressions (these names are only known at runtime when the expressions + * are evaluated) or local variables that are created as a result of an + * "upvar" or "uplevel" command. These other local variables are kept + * separately in a hash table in the call frame. + */ + +typedef struct CompiledLocal { + struct CompiledLocal *nextPtr; + /* Next compiler-recognized local variable + * for this procedure, or NULL if this is + * the last local. */ + int nameLength; /* The number of characters in local + * variable's name. Used to speed up + * variable lookups. */ + int frameIndex; /* Index in the array of compiler-assigned + * variables in the procedure call frame. */ + int flags; /* Flag bits for the local variable. Same as + * the flags for the Var structure above, + * although only VAR_SCALAR, VAR_ARRAY, + * VAR_LINK, VAR_ARGUMENT, VAR_TEMPORARY, and + * VAR_RESOLVED make sense. */ + Tcl_Obj *defValuePtr; /* Pointer to the default value of an + * argument, if any. NULL if not an argument + * or, if an argument, no default value. */ + Tcl_ResolvedVarInfo *resolveInfo; + /* Customized variable resolution info + * supplied by the Tcl_ResolveCompiledVarProc + * associated with a namespace. Each variable + * is marked by a unique ClientData tag + * during compilation, and that same tag + * is used to find the variable at runtime. */ + char name[4]; /* Name of the local variable starts here. + * If the name is NULL, this will just be + * '\0'. The actual size of this field will + * be large enough to hold the name. MUST + * BE THE LAST FIELD IN THE STRUCTURE! */ +} CompiledLocal; + +/* + * The structure below defines a command procedure, which consists of a + * collection of Tcl commands plus information about arguments and other + * local variables recognized at compile time. + */ + +typedef struct Proc { + struct Interp *iPtr; /* Interpreter for which this command + * is defined. */ + int refCount; /* Reference count: 1 if still present + * in command table plus 1 for each call + * to the procedure that is currently + * active. This structure can be freed + * when refCount becomes zero. */ + struct Command *cmdPtr; /* Points to the Command structure for + * this procedure. This is used to get + * the namespace in which to execute + * the procedure. */ + Tcl_Obj *bodyPtr; /* Points to the ByteCode object for + * procedure's body command. */ + int numArgs; /* Number of formal parameters. */ + int numCompiledLocals; /* Count of local variables recognized by + * the compiler including arguments and + * temporaries. */ + CompiledLocal *firstLocalPtr; /* Pointer to first of the procedure's + * compiler-allocated local variables, or + * NULL if none. The first numArgs entries + * in this list describe the procedure's + * formal arguments. */ + CompiledLocal *lastLocalPtr; /* Pointer to the last allocated local + * variable or NULL if none. This has + * frame index (numCompiledLocals-1). */ +} Proc; + +/* + * The structure below defines a command trace. This is used to allow Tcl + * clients to find out whenever a command is about to be executed. + */ + +typedef struct Trace { + int level; /* Only trace commands at nesting level + * less than or equal to this. */ + Tcl_CmdObjTraceProc *proc; /* Procedure to call to trace command. */ + ClientData clientData; /* Arbitrary value to pass to proc. */ + struct Trace *nextPtr; /* Next in list of traces for this interp. */ + int flags; /* Flags governing the trace - see + * Tcl_CreateObjTrace for details */ + Tcl_CmdObjTraceDeleteProc* delProc; + /* Procedure to call when trace is deleted */ +} Trace; + +/* + * When an interpreter trace is active (i.e. its associated procedure + * is executing), one of the following structures is linked into a list + * associated with the interpreter. The information in the structure + * is needed in order for Tcl to behave reasonably if traces are + * deleted while traces are active. + */ + +typedef struct ActiveInterpTrace { + struct ActiveInterpTrace *nextPtr; + /* Next in list of all active command + * traces for the interpreter, or NULL + * if no more. */ + Trace *nextTracePtr; /* Next trace to check after current + * trace procedure returns; if this + * trace gets deleted, must update pointer + * to avoid using free'd memory. */ +} ActiveInterpTrace; + +/* + * The structure below defines an entry in the assocData hash table which + * is associated with an interpreter. The entry contains a pointer to a + * function to call when the interpreter is deleted, and a pointer to + * a user-defined piece of data. + */ + +typedef struct AssocData { + Tcl_InterpDeleteProc *proc; /* Proc to call when deleting. */ + ClientData clientData; /* Value to pass to proc. */ +} AssocData; + +/* + * The structure below defines a call frame. A call frame defines a naming + * context for a procedure call: its local naming scope (for local + * variables) and its global naming scope (a namespace, perhaps the global + * :: namespace). A call frame can also define the naming context for a + * namespace eval or namespace inscope command: the namespace in which the + * command's code should execute. The Tcl_CallFrame structures exist only + * while procedures or namespace eval/inscope's are being executed, and + * provide a kind of Tcl call stack. + * + * WARNING!! The structure definition must be kept consistent with the + * Tcl_CallFrame structure in tcl.h. If you change one, change the other. + */ + +typedef struct CallFrame { + Namespace *nsPtr; /* Points to the namespace used to resolve + * commands and global variables. */ + int isProcCallFrame; /* If nonzero, the frame was pushed to + * execute a Tcl procedure and may have + * local vars. If 0, the frame was pushed + * to execute a namespace command and var + * references are treated as references to + * namespace vars; varTablePtr and + * compiledLocals are ignored. */ + int objc; /* This and objv below describe the + * arguments for this procedure call. */ + Tcl_Obj *CONST *objv; /* Array of argument objects. */ + struct CallFrame *callerPtr; + /* Value of interp->framePtr when this + * procedure was invoked (i.e. next higher + * in stack of all active procedures). */ + struct CallFrame *callerVarPtr; + /* Value of interp->varFramePtr when this + * procedure was invoked (i.e. determines + * variable scoping within caller). Same + * as callerPtr unless an "uplevel" command + * or something equivalent was active in + * the caller). */ + int level; /* Level of this procedure, for "uplevel" + * purposes (i.e. corresponds to nesting of + * callerVarPtr's, not callerPtr's). 1 for + * outermost procedure, 0 for top-level. */ + Proc *procPtr; /* Points to the structure defining the + * called procedure. Used to get information + * such as the number of compiled local + * variables (local variables assigned + * entries ["slots"] in the compiledLocals + * array below). */ + Tcl_HashTable *varTablePtr; /* Hash table containing local variables not + * recognized by the compiler, or created at + * execution time through, e.g., upvar. + * Initially NULL and created if needed. */ + int numCompiledLocals; /* Count of local variables recognized by + * the compiler including arguments. */ + Var* compiledLocals; /* Points to the array of local variables + * recognized by the compiler. The compiler + * emits code that refers to these variables + * using an index into this array. */ +} CallFrame; + +/* + *---------------------------------------------------------------- + * Data structures and procedures related to TclHandles, which + * are a very lightweight method of preserving enough information + * to determine if an arbitrary malloc'd block has been deleted. + *---------------------------------------------------------------- + */ + +typedef VOID **TclHandle; + +/* + *---------------------------------------------------------------- + * Data structures related to expressions. These are used only in + * tclExpr.c. + *---------------------------------------------------------------- + */ + +/* + * The data structure below defines a math function (e.g. sin or hypot) + * for use in Tcl expressions. + */ + +#define MAX_MATH_ARGS 5 +typedef struct MathFunc { + int builtinFuncIndex; /* If this is a builtin math function, its + * index in the array of builtin functions. + * (tclCompilation.h lists these indices.) + * The value is -1 if this is a new function + * defined by Tcl_CreateMathFunc. The value + * is also -1 if a builtin function is + * replaced by a Tcl_CreateMathFunc call. */ + int numArgs; /* Number of arguments for function. */ + Tcl_ValueType argTypes[MAX_MATH_ARGS]; + /* Acceptable types for each argument. */ + Tcl_MathProc *proc; /* Procedure that implements this function. + * NULL if isBuiltinFunc is 1. */ + ClientData clientData; /* Additional argument to pass to the + * function when invoking it. NULL if + * isBuiltinFunc is 1. */ +} MathFunc; + +/* + * These are a thin layer over TclpThreadKeyDataGet and TclpThreadKeyDataSet + * when threads are used, or an emulation if there are no threads. These + * are really internal and Tcl clients should use Tcl_GetThreadData. + */ + +EXTERN VOID *TclThreadDataKeyGet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclThreadDataKeySet _ANSI_ARGS_((Tcl_ThreadDataKey *keyPtr, VOID *data)); + +/* + * This is a convenience macro used to initialize a thread local storage ptr. + */ +#define TCL_TSD_INIT(keyPtr) (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) + + +/* + *---------------------------------------------------------------- + * Data structures related to bytecode compilation and execution. + * These are used primarily in tclCompile.c, tclExecute.c, and + * tclBasic.c. + *---------------------------------------------------------------- + */ + +/* + * Forward declaration to prevent errors when the forward references to + * Tcl_Parse and CompileEnv are encountered in the procedure type + * CompileProc declared below. + */ + +struct CompileEnv; + +/* + * The type of procedures called by the Tcl bytecode compiler to compile + * commands. Pointers to these procedures are kept in the Command structure + * describing each command. When a CompileProc returns, the interpreter's + * result is set to error information, if any. In addition, the CompileProc + * returns an integer value, which is one of the following: + * + * TCL_OK Compilation completed normally. + * TCL_ERROR Compilation failed because of an error; + * the interpreter's result describes what went wrong. + * TCL_OUT_LINE_COMPILE Compilation failed because, e.g., the command is + * too complex for effective inline compilation. The + * CompileProc believes the command is legal but + * should be compiled "out of line" by emitting code + * to invoke its command procedure at runtime. + */ + +#define TCL_OUT_LINE_COMPILE (TCL_CONTINUE + 1) + +typedef int (CompileProc) _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *compEnvPtr)); + +/* + * The type of procedure called from the compilation hook point in + * SetByteCodeFromAny. + */ + +typedef int (CompileHookProc) _ANSI_ARGS_((Tcl_Interp *interp, + struct CompileEnv *compEnvPtr, ClientData clientData)); + +/* + * The data structure defining the execution environment for ByteCode's. + * There is one ExecEnv structure per Tcl interpreter. It holds the + * evaluation stack that holds command operands and results. The stack grows + * towards increasing addresses. The "stackTop" member is cached by + * TclExecuteByteCode in a local variable: it must be set before calling + * TclExecuteByteCode and will be restored by TclExecuteByteCode before it + * returns. + */ + +typedef struct ExecEnv { + Tcl_Obj **stackPtr; /* Points to the first item in the + * evaluation stack on the heap. */ + int stackTop; /* Index of current top of stack; -1 when + * the stack is empty. */ + int stackEnd; /* Index of last usable item in stack. */ + Tcl_Obj *errorInfo; + Tcl_Obj *errorCode; +} ExecEnv; + +/* + * The definitions for the LiteralTable and LiteralEntry structures. Each + * interpreter contains a LiteralTable. It is used to reduce the storage + * needed for all the Tcl objects that hold the literals of scripts compiled + * by the interpreter. A literal's object is shared by all the ByteCodes + * that refer to the literal. Each distinct literal has one LiteralEntry + * entry in the LiteralTable. A literal table is a specialized hash table + * that is indexed by the literal's string representation, which may contain + * null characters. + * + * Note that we reduce the space needed for literals by sharing literal + * objects both within a ByteCode (each ByteCode contains a local + * LiteralTable) and across all an interpreter's ByteCodes (with the + * interpreter's global LiteralTable). + */ + +typedef struct LiteralEntry { + struct LiteralEntry *nextPtr; /* Points to next entry in this + * hash bucket or NULL if end of + * chain. */ + Tcl_Obj *objPtr; /* Points to Tcl object that + * holds the literal's bytes and + * length. */ + int refCount; /* If in an interpreter's global + * literal table, the number of + * ByteCode structures that share + * the literal object; the literal + * entry can be freed when refCount + * drops to 0. If in a local literal + * table, -1. */ +} LiteralEntry; + +typedef struct LiteralTable { + LiteralEntry **buckets; /* Pointer to bucket array. Each + * element points to first entry in + * bucket's hash chain, or NULL. */ + LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; + /* Bucket array used for small + * tables to avoid mallocs and + * frees. */ + int numBuckets; /* Total number of buckets allocated + * at **buckets. */ + int numEntries; /* Total number of entries present + * in table. */ + int rebuildSize; /* Enlarge table when numEntries + * gets to be this large. */ + int mask; /* Mask value used in hashing + * function. */ +} LiteralTable; + +/* + * The following structure defines for each Tcl interpreter various + * statistics-related information about the bytecode compiler and + * interpreter's operation in that interpreter. + */ + +#ifdef TCL_COMPILE_STATS +typedef struct ByteCodeStats { + long numExecutions; /* Number of ByteCodes executed. */ + long numCompilations; /* Number of ByteCodes created. */ + long numByteCodesFreed; /* Number of ByteCodes destroyed. */ + long instructionCount[256]; /* Number of times each instruction was + * executed. */ + + double totalSrcBytes; /* Total source bytes ever compiled. */ + double totalByteCodeBytes; /* Total bytes for all ByteCodes. */ + double currentSrcBytes; /* Src bytes for all current ByteCodes. */ + double currentByteCodeBytes; /* Code bytes in all current ByteCodes. */ + + long srcCount[32]; /* Source size distribution: # of srcs of + * size [2**(n-1)..2**n), n in [0..32). */ + long byteCodeCount[32]; /* ByteCode size distribution. */ + long lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */ + + double currentInstBytes; /* Instruction bytes-current ByteCodes. */ + double currentLitBytes; /* Current literal bytes. */ + double currentExceptBytes; /* Current exception table bytes. */ + double currentAuxBytes; /* Current auxiliary information bytes. */ + double currentCmdMapBytes; /* Current src<->code map bytes. */ + + long numLiteralsCreated; /* Total literal objects ever compiled. */ + double totalLitStringBytes; /* Total string bytes in all literals. */ + double currentLitStringBytes; /* String bytes in current literals. */ + long literalCount[32]; /* Distribution of literal string sizes. */ +} ByteCodeStats; +#endif /* TCL_COMPILE_STATS */ + +/* + *---------------------------------------------------------------- + * Data structures related to commands. + *---------------------------------------------------------------- + */ + +/* + * An imported command is created in an namespace when it imports a "real" + * command from another namespace. An imported command has a Command + * structure that points (via its ClientData value) to the "real" Command + * structure in the source namespace's command table. The real command + * records all the imported commands that refer to it in a list of ImportRef + * structures so that they can be deleted when the real command is deleted. */ + +typedef struct ImportRef { + struct Command *importedCmdPtr; + /* Points to the imported command created in + * an importing namespace; this command + * redirects its invocations to the "real" + * command. */ + struct ImportRef *nextPtr; /* Next element on the linked list of + * imported commands that refer to the + * "real" command. The real command deletes + * these imported commands on this list when + * it is deleted. */ +} ImportRef; + +/* + * Data structure used as the ClientData of imported commands: commands + * created in an namespace when it imports a "real" command from another + * namespace. + */ + +typedef struct ImportedCmdData { + struct Command *realCmdPtr; /* "Real" command that this imported command + * refers to. */ + struct Command *selfPtr; /* Pointer to this imported command. Needed + * only when deleting it in order to remove + * it from the real command's linked list of + * imported commands that refer to it. */ +} ImportedCmdData; + +/* + * A Command structure exists for each command in a namespace. The + * Tcl_Command opaque type actually refers to these structures. + */ + +typedef struct Command { + Tcl_HashEntry *hPtr; /* Pointer to the hash table entry that + * refers to this command. The hash table is + * either a namespace's command table or an + * interpreter's hidden command table. This + * pointer is used to get a command's name + * from its Tcl_Command handle. NULL means + * that the hash table entry has been + * removed already (this can happen if + * deleteProc causes the command to be + * deleted or recreated). */ + Namespace *nsPtr; /* Points to the namespace containing this + * command. */ + int refCount; /* 1 if in command hashtable plus 1 for each + * reference from a CmdName Tcl object + * representing a command's name in a + * ByteCode instruction sequence. This + * structure can be freed when refCount + * becomes zero. */ + int cmdEpoch; /* Incremented to invalidate any references + * that point to this command when it is + * renamed, deleted, hidden, or exposed. */ + CompileProc *compileProc; /* Procedure called to compile command. NULL + * if no compile proc exists for command. */ + Tcl_ObjCmdProc *objProc; /* Object-based command procedure. */ + ClientData objClientData; /* Arbitrary value passed to object proc. */ + Tcl_CmdProc *proc; /* String-based command procedure. */ + ClientData clientData; /* Arbitrary value passed to string proc. */ + Tcl_CmdDeleteProc *deleteProc; + /* Procedure invoked when deleting command + * to, e.g., free all client data. */ + ClientData deleteData; /* Arbitrary value passed to deleteProc. */ + int flags; /* Miscellaneous bits of information about + * command. See below for definitions. */ + ImportRef *importRefPtr; /* List of each imported Command created in + * another namespace when this command is + * imported. These imported commands + * redirect invocations back to this + * command. The list is used to remove all + * those imported commands when deleting + * this "real" command. */ + CommandTrace *tracePtr; /* First in list of all traces set for this + * command. */ +} Command; + +/* + * Flag bits for commands. + * + * CMD_IS_DELETED - Means that the command is in the process + * of being deleted (its deleteProc is + * currently executing). Other attempts to + * delete the command should be ignored. + * CMD_TRACE_ACTIVE - 1 means that trace processing is currently + * underway for a rename/delete change. + * See the two flags below for which is + * currently being processed. + * CMD_HAS_EXEC_TRACES - 1 means that this command has at least + * one execution trace (as opposed to simple + * delete/rename traces) in its tracePtr list. + * TCL_TRACE_RENAME - A rename trace is in progress. Further + * recursive renames will not be traced. + * TCL_TRACE_DELETE - A delete trace is in progress. Further + * recursive deletes will not be traced. + * (these last two flags are defined in tcl.h) + */ +#define CMD_IS_DELETED 0x1 +#define CMD_TRACE_ACTIVE 0x2 +#define CMD_HAS_EXEC_TRACES 0x4 + +/* + *---------------------------------------------------------------- + * Data structures related to name resolution procedures. + *---------------------------------------------------------------- + */ + +/* + * The interpreter keeps a linked list of name resolution schemes. + * The scheme for a namespace is consulted first, followed by the + * list of schemes in an interpreter, followed by the default + * name resolution in Tcl. Schemes are added/removed from the + * interpreter's list by calling Tcl_AddInterpResolver and + * Tcl_RemoveInterpResolver. + */ + +typedef struct ResolverScheme { + char *name; /* Name identifying this scheme. */ + Tcl_ResolveCmdProc *cmdResProc; + /* Procedure handling command name + * resolution. */ + Tcl_ResolveVarProc *varResProc; + /* Procedure handling variable name + * resolution for variables that + * can only be handled at runtime. */ + Tcl_ResolveCompiledVarProc *compiledVarResProc; + /* Procedure handling variable name + * resolution at compile time. */ + + struct ResolverScheme *nextPtr; + /* Pointer to next record in linked list. */ +} ResolverScheme; + +/* + *---------------------------------------------------------------- + * This structure defines an interpreter, which is a collection of + * commands plus other state information related to interpreting + * commands, such as variable storage. Primary responsibility for + * this data structure is in tclBasic.c, but almost every Tcl + * source file uses something in here. + *---------------------------------------------------------------- + */ + +typedef struct Interp { + + /* + * Note: the first three fields must match exactly the fields in + * a Tcl_Interp struct (see tcl.h). If you change one, be sure to + * change the other. + * + * The interpreter's result is held in both the string and the + * objResultPtr fields. These fields hold, respectively, the result's + * string or object value. The interpreter's result is always in the + * result field if that is non-empty, otherwise it is in objResultPtr. + * The two fields are kept consistent unless some C code sets + * interp->result directly. Programs should not access result and + * objResultPtr directly; instead, they should always get and set the + * result using procedures such as Tcl_SetObjResult, Tcl_GetObjResult, + * and Tcl_GetStringResult. See the SetResult man page for details. + */ + + char *result; /* If the last command returned a string + * result, this points to it. Should not be + * accessed directly; see comment above. */ + Tcl_FreeProc *freeProc; /* Zero means a string result is statically + * allocated. TCL_DYNAMIC means string + * result was allocated with ckalloc and + * should be freed with ckfree. Other values + * give address of procedure to invoke to + * free the string result. Tcl_Eval must + * free it before executing next command. */ + int errorLine; /* When TCL_ERROR is returned, this gives + * the line number in the command where the + * error occurred (1 means first line). */ + struct TclStubs *stubTable; + /* Pointer to the exported Tcl stub table. + * On previous versions of Tcl this is a + * pointer to the objResultPtr or a pointer + * to a buckets array in a hash table. We + * therefore have to do some careful checking + * before we can use this. */ + + TclHandle handle; /* Handle used to keep track of when this + * interp is deleted. */ + + Namespace *globalNsPtr; /* The interpreter's global namespace. */ + Tcl_HashTable *hiddenCmdTablePtr; + /* Hash table used by tclBasic.c to keep + * track of hidden commands on a per-interp + * basis. */ + ClientData interpInfo; /* Information used by tclInterp.c to keep + * track of master/slave interps on + * a per-interp basis. */ + Tcl_HashTable mathFuncTable;/* Contains all the math functions currently + * defined for the interpreter. Indexed by + * strings (function names); values have + * type (MathFunc *). */ + + + + /* + * Information related to procedures and variables. See tclProc.c + * and tclVar.c for usage. + */ + + int numLevels; /* Keeps track of how many nested calls to + * Tcl_Eval are in progress for this + * interpreter. It's used to delay deletion + * of the table until all Tcl_Eval + * invocations are completed. */ + int maxNestingDepth; /* If numLevels exceeds this value then Tcl + * assumes that infinite recursion has + * occurred and it generates an error. */ + CallFrame *framePtr; /* Points to top-most in stack of all nested + * procedure invocations. NULL means there + * are no active procedures. */ + CallFrame *varFramePtr; /* Points to the call frame whose variables + * are currently in use (same as framePtr + * unless an "uplevel" command is + * executing). NULL means no procedure is + * active or "uplevel 0" is executing. */ + ActiveVarTrace *activeVarTracePtr; + /* First in list of active traces for + * interp, or NULL if no active traces. */ + int returnCode; /* Completion code to return if current + * procedure exits with TCL_RETURN code. */ + char *errorInfo; /* Value to store in errorInfo if returnCode + * is TCL_ERROR. Malloc'ed, may be NULL */ + char *errorCode; /* Value to store in errorCode if returnCode + * is TCL_ERROR. Malloc'ed, may be NULL */ + + /* + * Information used by Tcl_AppendResult to keep track of partial + * results. See Tcl_AppendResult code for details. + */ + + char *appendResult; /* Storage space for results generated + * by Tcl_AppendResult. Malloc-ed. NULL + * means not yet allocated. */ + int appendAvl; /* Total amount of space available at + * partialResult. */ + int appendUsed; /* Number of non-null bytes currently + * stored at partialResult. */ + + /* + * Information about packages. Used only in tclPkg.c. + */ + + Tcl_HashTable packageTable; /* Describes all of the packages loaded + * in or available to this interpreter. + * Keys are package names, values are + * (Package *) pointers. */ + char *packageUnknown; /* Command to invoke during "package + * require" commands for packages that + * aren't described in packageTable. + * Malloc'ed, may be NULL. */ + + /* + * Miscellaneous information: + */ + + int cmdCount; /* Total number of times a command procedure + * has been called for this interpreter. */ + int evalFlags; /* Flags to control next call to Tcl_Eval. + * Normally zero, but may be set before + * calling Tcl_Eval. See below for valid + * values. */ + int termOffset; /* Offset of character just after last one + * compiled or executed by Tcl_EvalObj. */ + LiteralTable literalTable; /* Contains LiteralEntry's describing all + * Tcl objects holding literals of scripts + * compiled by the interpreter. Indexed by + * the string representations of literals. + * Used to avoid creating duplicate + * objects. */ + int compileEpoch; /* Holds the current "compilation epoch" + * for this interpreter. This is + * incremented to invalidate existing + * ByteCodes when, e.g., a command with a + * compile procedure is redefined. */ + Proc *compiledProcPtr; /* If a procedure is being compiled, a + * pointer to its Proc structure; otherwise, + * this is NULL. Set by ObjInterpProc in + * tclProc.c and used by tclCompile.c to + * process local variables appropriately. */ + ResolverScheme *resolverPtr; + /* Linked list of name resolution schemes + * added to this interpreter. Schemes + * are added/removed by calling + * Tcl_AddInterpResolvers and + * Tcl_RemoveInterpResolver. */ + Tcl_Obj *scriptFile; /* NULL means there is no nested source + * command active; otherwise this points to + * pathPtr of the file being sourced. */ + int flags; /* Various flag bits. See below. */ + long randSeed; /* Seed used for rand() function. */ + Trace *tracePtr; /* List of traces for this interpreter. */ + Tcl_HashTable *assocData; /* Hash table for associating data with + * this interpreter. Cleaned up when + * this interpreter is deleted. */ + struct ExecEnv *execEnvPtr; /* Execution environment for Tcl bytecode + * execution. Contains a pointer to the + * Tcl evaluation stack. */ + Tcl_Obj *emptyObjPtr; /* Points to an object holding an empty + * string. Returned by Tcl_ObjSetVar2 when + * variable traces change a variable in a + * gross way. */ + char resultSpace[TCL_RESULT_SIZE+1]; + /* Static space holding small results. */ + Tcl_Obj *objResultPtr; /* If the last command returned an object + * result, this points to it. Should not be + * accessed directly; see comment above. */ + Tcl_ThreadId threadId; /* ID of thread that owns the interpreter */ + + ActiveCommandTrace *activeCmdTracePtr; + /* First in list of active command traces for + * interp, or NULL if no active traces. */ + ActiveInterpTrace *activeInterpTracePtr; + /* First in list of active traces for + * interp, or NULL if no active traces. */ + + int tracesForbiddingInline; /* Count of traces (in the list headed by + * tracePtr) that forbid inline bytecode + * compilation */ + /* + * Statistical information about the bytecode compiler and interpreter's + * operation. + */ + +#ifdef TCL_COMPILE_STATS + ByteCodeStats stats; /* Holds compilation and execution + * statistics for this interpreter. */ +#endif /* TCL_COMPILE_STATS */ +} Interp; + +/* + * EvalFlag bits for Interp structures: + * + * TCL_BRACKET_TERM 1 means that the current script is terminated by + * a close bracket rather than the end of the string. + * TCL_ALLOW_EXCEPTIONS 1 means it's OK for the script to terminate with + * a code other than TCL_OK or TCL_ERROR; 0 means + * codes other than these should be turned into errors. + */ + +#define TCL_BRACKET_TERM 1 +#define TCL_ALLOW_EXCEPTIONS 4 + +/* + * Flag bits for Interp structures: + * + * DELETED: Non-zero means the interpreter has been deleted: + * don't process any more commands for it, and destroy + * the structure as soon as all nested invocations of + * Tcl_Eval are done. + * ERR_IN_PROGRESS: Non-zero means an error unwind is already in + * progress. Zero means a command proc has been + * invoked since last error occured. + * ERR_ALREADY_LOGGED: Non-zero means information has already been logged + * in $errorInfo for the current Tcl_Eval instance, + * so Tcl_Eval needn't log it (used to implement the + * "error message log" command). + * ERROR_CODE_SET: Non-zero means that Tcl_SetErrorCode has been + * called to record information for the current + * error. Zero means Tcl_Eval must clear the + * errorCode variable if an error is returned. + * EXPR_INITIALIZED: Non-zero means initialization specific to + * expressions has been carried out. + * DONT_COMPILE_CMDS_INLINE: Non-zero means that the bytecode compiler + * should not compile any commands into an inline + * sequence of instructions. This is set 1, for + * example, when command traces are requested. + * RAND_SEED_INITIALIZED: Non-zero means that the randSeed value of the + * interp has not be initialized. This is set 1 + * when we first use the rand() or srand() functions. + * SAFE_INTERP: Non zero means that the current interp is a + * safe interp (ie it has only the safe commands + * installed, less priviledge than a regular interp). + * USE_EVAL_DIRECT: Non-zero means don't use the compiler or byte-code + * interpreter; instead, have Tcl_EvalObj call + * Tcl_EvalEx. Used primarily for testing the + * new parser. + * INTERP_TRACE_IN_PROGRESS: Non-zero means that an interp trace is currently + * active; so no further trace callbacks should be + * invoked. + */ + +#define DELETED 1 +#define ERR_IN_PROGRESS 2 +#define ERR_ALREADY_LOGGED 4 +#define ERROR_CODE_SET 8 +#define EXPR_INITIALIZED 0x10 +#define DONT_COMPILE_CMDS_INLINE 0x20 +#define RAND_SEED_INITIALIZED 0x40 +#define SAFE_INTERP 0x80 +#define USE_EVAL_DIRECT 0x100 +#define INTERP_TRACE_IN_PROGRESS 0x200 + +/* + * Maximum number of levels of nesting permitted in Tcl commands (used + * to catch infinite recursion). + */ + +#define MAX_NESTING_DEPTH 1000 + +/* + * The macro below is used to modify a "char" value (e.g. by casting + * it to an unsigned character) so that it can be used safely with + * macros such as isspace. + */ + +#define UCHAR(c) ((unsigned char) (c)) + +/* + * This macro is used to determine the offset needed to safely allocate any + * data structure in memory. Given a starting offset or size, it "rounds up" + * or "aligns" the offset to the next 8-byte boundary so that any data + * structure can be placed at the resulting offset without fear of an + * alignment error. + * + * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce + * the wrong result on platforms that allocate addresses that are divisible + * by 4 or 2. Only use it for offsets or sizes. + */ + +#define TCL_ALIGN(x) (((int)(x) + 7) & ~7) + +/* + * The following enum values are used to specify the runtime platform + * setting of the tclPlatform variable. + */ + +typedef enum { + TCL_PLATFORM_UNIX, /* Any Unix-like OS. */ + TCL_PLATFORM_MAC, /* MacOS. */ + TCL_PLATFORM_WINDOWS /* Any Microsoft Windows OS. */ +} TclPlatformType; + +/* + * The following enum values are used to indicate the translation + * of a Tcl channel. Declared here so that each platform can define + * TCL_PLATFORM_TRANSLATION to the native translation on that platform + */ + +typedef enum TclEolTranslation { + TCL_TRANSLATE_AUTO, /* Eol == \r, \n and \r\n. */ + TCL_TRANSLATE_CR, /* Eol == \r. */ + TCL_TRANSLATE_LF, /* Eol == \n. */ + TCL_TRANSLATE_CRLF /* Eol == \r\n. */ +} TclEolTranslation; + +/* + * Flags for TclInvoke: + * + * TCL_INVOKE_HIDDEN Invoke a hidden command; if not set, + * invokes an exposed command. + * TCL_INVOKE_NO_UNKNOWN If set, "unknown" is not invoked if + * the command to be invoked is not found. + * Only has an effect if invoking an exposed + * command, i.e. if TCL_INVOKE_HIDDEN is not + * also set. + * TCL_INVOKE_NO_TRACEBACK Does not record traceback information if + * the invoked command returns an error. Used + * if the caller plans on recording its own + * traceback information. + */ + +#define TCL_INVOKE_HIDDEN (1<<0) +#define TCL_INVOKE_NO_UNKNOWN (1<<1) +#define TCL_INVOKE_NO_TRACEBACK (1<<2) + +/* + * The structure used as the internal representation of Tcl list + * objects. This is an array of pointers to the element objects. This array + * is grown (reallocated and copied) as necessary to hold all the list's + * element pointers. The array might contain more slots than currently used + * to hold all element pointers. This is done to make append operations + * faster. + */ + +typedef struct List { + int maxElemCount; /* Total number of element array slots. */ + int elemCount; /* Current number of list elements. */ + Tcl_Obj **elements; /* Array of pointers to element objects. */ +} List; + + +/* + * The following types are used for getting and storing platform-specific + * file attributes in tclFCmd.c and the various platform-versions of + * that file. This is done to have as much common code as possible + * in the file attributes code. For more information about the callbacks, + * see TclFileAttrsCmd in tclFCmd.c. + */ + +typedef int (TclGetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, + int objIndex, Tcl_Obj *fileName, Tcl_Obj **attrObjPtrPtr)); +typedef int (TclSetFileAttrProc) _ANSI_ARGS_((Tcl_Interp *interp, + int objIndex, Tcl_Obj *fileName, Tcl_Obj *attrObjPtr)); + +typedef struct TclFileAttrProcs { + TclGetFileAttrProc *getProc; /* The procedure for getting attrs. */ + TclSetFileAttrProc *setProc; /* The procedure for setting attrs. */ +} TclFileAttrProcs; + +/* + * Opaque handle used in pipeline routines to encapsulate platform-dependent + * state. + */ + +typedef struct TclFile_ *TclFile; + +/* + * Opaque names for platform specific types. + */ + +typedef struct TclpTime_t_ *TclpTime_t; + +/* + * The "globParameters" argument of the function TclGlob is an + * or'ed combination of the following values: + */ + +#define TCL_GLOBMODE_NO_COMPLAIN 1 +#define TCL_GLOBMODE_JOIN 2 +#define TCL_GLOBMODE_DIR 4 +#define TCL_GLOBMODE_TAILS 8 + +/* + *---------------------------------------------------------------- + * Data structures related to obsolete filesystem hooks + *---------------------------------------------------------------- + */ + +typedef int (TclStatProc_) _ANSI_ARGS_((CONST char *path, struct stat *buf)); +typedef int (TclAccessProc_) _ANSI_ARGS_((CONST char *path, int mode)); +typedef Tcl_Channel (TclOpenFileChannelProc_) _ANSI_ARGS_((Tcl_Interp *interp, + CONST char *fileName, CONST char *modeString, + int permissions)); + + +/* + *---------------------------------------------------------------- + * Data structures related to procedures + *---------------------------------------------------------------- + */ + +typedef Tcl_CmdProc *TclCmdProcType; +typedef Tcl_ObjCmdProc *TclObjCmdProcType; + +/* + *---------------------------------------------------------------- + * Variables shared among Tcl modules but not used by the outside world. + *---------------------------------------------------------------- + */ + +extern Tcl_Time tclBlockTime; +extern int tclBlockTimeSet; +extern char * tclExecutableName; +extern char * tclNativeExecutableName; +extern char * tclDefaultEncodingDir; +extern Tcl_ChannelType tclFileChannelType; +extern char * tclMemDumpFileName; +extern TclPlatformType tclPlatform; +extern Tcl_NotifierProcs tclOriginalNotifier; + +/* + * Variables denoting the Tcl object types defined in the core. + */ + +extern Tcl_ObjType tclBooleanType; +extern Tcl_ObjType tclByteArrayType; +extern Tcl_ObjType tclByteCodeType; +extern Tcl_ObjType tclDoubleType; +extern Tcl_ObjType tclEndOffsetType; +extern Tcl_ObjType tclIntType; +extern Tcl_ObjType tclListType; +extern Tcl_ObjType tclProcBodyType; +extern Tcl_ObjType tclStringType; +extern Tcl_ObjType tclArraySearchType; +extern Tcl_ObjType tclIndexType; +extern Tcl_ObjType tclNsNameType; +extern Tcl_ObjType tclWideIntType; + +/* + * Variables denoting the hash key types defined in the core. + */ + +extern Tcl_HashKeyType tclArrayHashKeyType; +extern Tcl_HashKeyType tclOneWordHashKeyType; +extern Tcl_HashKeyType tclStringHashKeyType; +extern Tcl_HashKeyType tclObjHashKeyType; + +/* + * The head of the list of free Tcl objects, and the total number of Tcl + * objects ever allocated and freed. + */ + +extern Tcl_Obj * tclFreeObjList; + +#ifdef TCL_COMPILE_STATS +extern long tclObjsAlloced; +extern long tclObjsFreed; +#define TCL_MAX_SHARED_OBJ_STATS 5 +extern long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS]; +#endif /* TCL_COMPILE_STATS */ + +/* + * Pointer to a heap-allocated string of length zero that the Tcl core uses + * as the value of an empty string representation for an object. This value + * is shared by all new objects allocated by Tcl_NewObj. + */ + +extern char * tclEmptyStringRep; +extern char tclEmptyString; + +/* + *---------------------------------------------------------------- + * Procedures shared among Tcl modules but not used by the outside + * world: + *---------------------------------------------------------------- + */ + +EXTERN int TclArraySet _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj)); +EXTERN int TclCheckBadOctal _ANSI_ARGS_((Tcl_Interp *interp, + CONST char *value)); +EXTERN void TclExpandTokenArray _ANSI_ARGS_(( + Tcl_Parse *parsePtr)); +EXTERN int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int TclFileCopyCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])) ; +EXTERN int TclFileDeleteCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int TclFileMakeDirsCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])) ; +EXTERN int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])) ; +EXTERN void TclFinalizeAllocSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeCompExecEnv _ANSI_ARGS_((void)); +EXTERN void TclFinalizeCompilation _ANSI_ARGS_((void)); +EXTERN void TclFinalizeEncodingSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeEnvironment _ANSI_ARGS_((void)); +EXTERN void TclFinalizeExecution _ANSI_ARGS_((void)); +EXTERN void TclFinalizeIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeFilesystem _ANSI_ARGS_((void)); +EXTERN void TclResetFilesystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeLoad _ANSI_ARGS_((void)); +EXTERN void TclFinalizeMemorySubsystem _ANSI_ARGS_((void)); +EXTERN void TclFinalizeNotifier _ANSI_ARGS_((void)); +EXTERN void TclFinalizeAsync _ANSI_ARGS_((void)); +EXTERN void TclFinalizeSynchronization _ANSI_ARGS_((void)); +EXTERN void TclFinalizeThreadData _ANSI_ARGS_((void)); +EXTERN void TclFindEncodings _ANSI_ARGS_((CONST char *argv0)); +EXTERN int TclGlob _ANSI_ARGS_((Tcl_Interp *interp, + char *pattern, Tcl_Obj *unquotedPrefix, + int globFlags, Tcl_GlobTypeData* types)); +EXTERN void TclInitAlloc _ANSI_ARGS_((void)); +EXTERN void TclInitDbCkalloc _ANSI_ARGS_((void)); +EXTERN void TclInitEncodingSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitIOSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNamespaceSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitNotifier _ANSI_ARGS_((void)); +EXTERN void TclInitObjSubsystem _ANSI_ARGS_((void)); +EXTERN void TclInitSubsystems _ANSI_ARGS_((CONST char *argv0)); +EXTERN int TclIsLocalScalar _ANSI_ARGS_((CONST char *src, + int len)); +EXTERN int TclJoinThread _ANSI_ARGS_((Tcl_ThreadId id, + int* result)); +EXTERN Tcl_Obj * TclLindexList _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_Obj* listPtr, + Tcl_Obj* argPtr )); +EXTERN Tcl_Obj * TclLindexFlat _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_Obj* listPtr, + int indexCount, + Tcl_Obj *CONST indexArray[] + )); +EXTERN Tcl_Obj * TclLsetList _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_Obj* listPtr, + Tcl_Obj* indexPtr, + Tcl_Obj* valuePtr + )); +EXTERN Tcl_Obj * TclLsetFlat _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_Obj* listPtr, + int indexCount, + Tcl_Obj *CONST indexArray[], + Tcl_Obj* valuePtr + )); +EXTERN int TclParseBackslash _ANSI_ARGS_((CONST char *src, + int numBytes, int *readPtr, char *dst)); +EXTERN int TclParseHex _ANSI_ARGS_((CONST char *src, int numBytes, + Tcl_UniChar *resultPtr)); +EXTERN int TclParseInteger _ANSI_ARGS_((CONST char *string, + int numBytes)); +EXTERN int TclParseWhiteSpace _ANSI_ARGS_((CONST char *src, + int numBytes, Tcl_Parse *parsePtr, char *typePtr)); +EXTERN int TclpObjAccess _ANSI_ARGS_((Tcl_Obj *filename, + int mode)); +EXTERN int TclpObjLstat _ANSI_ARGS_((Tcl_Obj *pathPtr, + Tcl_StatBuf *buf)); +EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); +EXTERN Tcl_Obj* TclpTempFileName _ANSI_ARGS_((void)); +EXTERN Tcl_Obj* TclNewFSPathObj _ANSI_ARGS_((Tcl_Obj *dirPtr, + CONST char *addStrRep, int len)); +EXTERN int TclpDeleteFile _ANSI_ARGS_((CONST char *path)); +EXTERN void TclpFinalizeCondition _ANSI_ARGS_(( + Tcl_Condition *condPtr)); +EXTERN void TclpFinalizeMutex _ANSI_ARGS_((Tcl_Mutex *mutexPtr)); +EXTERN void TclpFinalizeThreadData _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpFinalizeThreadDataKey _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN char * TclpFindExecutable _ANSI_ARGS_(( + CONST char *argv0)); +EXTERN int TclpFindVariable _ANSI_ARGS_((CONST char *name, + int *lengthPtr)); +EXTERN void TclpInitLibraryPath _ANSI_ARGS_((CONST char *argv0)); +EXTERN void TclpInitLock _ANSI_ARGS_((void)); +EXTERN void TclpInitPlatform _ANSI_ARGS_((void)); +EXTERN void TclpInitUnlock _ANSI_ARGS_((void)); +EXTERN int TclpLoadFile _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *pathPtr, + CONST char *sym1, CONST char *sym2, + Tcl_PackageInitProc **proc1Ptr, + Tcl_PackageInitProc **proc2Ptr, + ClientData *clientDataPtr, + Tcl_FSUnloadFileProc **unloadProcPtr)); +EXTERN Tcl_Obj* TclpObjListVolumes _ANSI_ARGS_((void)); +EXTERN void TclpMasterLock _ANSI_ARGS_((void)); +EXTERN void TclpMasterUnlock _ANSI_ARGS_((void)); +EXTERN int TclpMatchFiles _ANSI_ARGS_((Tcl_Interp *interp, + char *separators, Tcl_DString *dirPtr, + char *pattern, char *tail)); +EXTERN int TclpObjNormalizePath _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *pathPtr, int nextCheckpoint)); +EXTERN int TclpObjCreateDirectory _ANSI_ARGS_((Tcl_Obj *pathPtr)); +EXTERN void TclpNativeJoinPath _ANSI_ARGS_((Tcl_Obj *prefix, + char *joining)); +EXTERN Tcl_Obj* TclpNativeSplitPath _ANSI_ARGS_((Tcl_Obj *pathPtr, + int *lenPtr)); +EXTERN Tcl_PathType TclpGetNativePathType _ANSI_ARGS_((Tcl_Obj *pathObjPtr, + int *driveNameLengthPtr, Tcl_Obj **driveNameRef)); +EXTERN int TclCrossFilesystemCopy _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *source, Tcl_Obj *target)); +EXTERN int TclpObjDeleteFile _ANSI_ARGS_((Tcl_Obj *pathPtr)); +EXTERN int TclpObjCopyDirectory _ANSI_ARGS_((Tcl_Obj *srcPathPtr, + Tcl_Obj *destPathPtr, Tcl_Obj **errorPtr)); +EXTERN int TclpObjCopyFile _ANSI_ARGS_((Tcl_Obj *srcPathPtr, + Tcl_Obj *destPathPtr)); +EXTERN int TclpObjRemoveDirectory _ANSI_ARGS_((Tcl_Obj *pathPtr, + int recursive, Tcl_Obj **errorPtr)); +EXTERN int TclpObjRenameFile _ANSI_ARGS_((Tcl_Obj *srcPathPtr, + Tcl_Obj *destPathPtr)); +EXTERN int TclpMatchInDirectory _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *resultPtr, Tcl_Obj *pathPtr, + CONST char *pattern, Tcl_GlobTypeData *types)); +EXTERN Tcl_Obj* TclpObjGetCwd _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN Tcl_Obj* TclpObjLink _ANSI_ARGS_((Tcl_Obj *pathPtr, + Tcl_Obj *toPtr, int linkType)); +EXTERN int TclpObjChdir _ANSI_ARGS_((Tcl_Obj *pathPtr)); +EXTERN Tcl_Obj* TclFileDirname _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj*pathPtr)); +EXTERN int TclpObjStat _ANSI_ARGS_((Tcl_Obj *pathPtr, Tcl_StatBuf *buf)); +EXTERN Tcl_Channel TclpOpenFileChannel _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *pathPtr, int mode, + int permissions)); +EXTERN void TclpCutFileChannel _ANSI_ARGS_((Tcl_Channel chan)); +EXTERN void TclpSpliceFileChannel _ANSI_ARGS_((Tcl_Channel chan)); +EXTERN void TclpPanic _ANSI_ARGS_(TCL_VARARGS(CONST char *, + format)); +EXTERN char * TclpReadlink _ANSI_ARGS_((CONST char *fileName, + Tcl_DString *linkPtr)); +EXTERN void TclpReleaseFile _ANSI_ARGS_((TclFile file)); +EXTERN void TclpSetVariables _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TclpUnloadFile _ANSI_ARGS_((Tcl_LoadHandle loadHandle)); +EXTERN VOID * TclpThreadDataKeyGet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeyInit _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr)); +EXTERN void TclpThreadDataKeySet _ANSI_ARGS_(( + Tcl_ThreadDataKey *keyPtr, VOID *data)); +EXTERN void TclpThreadExit _ANSI_ARGS_((int status)); +EXTERN void TclRememberCondition _ANSI_ARGS_((Tcl_Condition *mutex)); +EXTERN void TclRememberDataKey _ANSI_ARGS_((Tcl_ThreadDataKey *mutex)); +EXTERN VOID TclRememberJoinableThread _ANSI_ARGS_((Tcl_ThreadId id)); +EXTERN void TclRememberMutex _ANSI_ARGS_((Tcl_Mutex *mutex)); +EXTERN VOID TclSignalExitThread _ANSI_ARGS_((Tcl_ThreadId id, + int result)); +EXTERN void TclTransferResult _ANSI_ARGS_((Tcl_Interp *sourceInterp, + int result, Tcl_Interp *targetInterp)); +EXTERN Tcl_Obj* TclpNativeToNormalized + _ANSI_ARGS_((ClientData clientData)); +EXTERN Tcl_Obj* TclpFilesystemPathType + _ANSI_ARGS_((Tcl_Obj* pathObjPtr)); +EXTERN Tcl_PackageInitProc* TclpFindSymbol _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_LoadHandle loadHandle, CONST char *symbol)); +EXTERN int TclpDlopen _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *pathPtr, + Tcl_LoadHandle *loadHandle, + Tcl_FSUnloadFileProc **unloadProcPtr)); +EXTERN int TclpUtime _ANSI_ARGS_((Tcl_Obj *pathPtr, + struct utimbuf *tval)); + +/* + *---------------------------------------------------------------- + * Command procedures in the generic core: + *---------------------------------------------------------------- + */ + +EXTERN int Tcl_AfterObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_AppendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ArrayObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BinaryObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BreakObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CaseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CatchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CdObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ClockObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_CloseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ConcatObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ContinueObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EncodingObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EofObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ErrorObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_EvalObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExecObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ExprObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FblockedObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FconfigureObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FcopyObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FileObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FileEventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FlushObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ForObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ForeachObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_FormatObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GetsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GlobalObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_GlobObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IfObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_IncrObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_InfoObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_InterpObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_JoinObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LappendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LindexObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LinsertObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LlengthObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ListObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LoadObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LrangeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LreplaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LsearchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LsetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp* interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_LsortObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_NamespaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_OpenObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PackageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PidObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PutsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_PwdObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ReadObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RegexpObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RegsubObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_RenameObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ReturnObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ScanObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SeekObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SplitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SocketObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_StringObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SubstObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_SwitchObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TellObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TimeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_TraceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UnsetObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UplevelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_UpvarObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_VariableObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_VwaitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_WhileObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); + +/* + *---------------------------------------------------------------- + * Command procedures found only in the Mac version of the core: + *---------------------------------------------------------------- + */ + +#ifdef MAC_TCL +EXTERN int Tcl_EchoCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, CONST84 char **argv)); +EXTERN int Tcl_LsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_BeepObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_MacSourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tcl_ResourceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +#endif + +/* + *---------------------------------------------------------------- + * Compilation procedures for commands in the generic core: + *---------------------------------------------------------------- + */ + +EXTERN int TclCompileAppendCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileBreakCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileCatchCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileContinueCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileExprCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileForCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileForeachCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileIfCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileIncrCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileLappendCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileLindexCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileListCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileLlengthCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileLsetCmd _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_Parse* parsePtr, struct CompileEnv* envPtr)); +EXTERN int TclCompileRegexpCmd _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_Parse* parsePtr, struct CompileEnv* envPtr)); +EXTERN int TclCompileReturnCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileSetCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileStringCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); +EXTERN int TclCompileWhileCmd _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Parse *parsePtr, struct CompileEnv *envPtr)); + +/* + * Functions defined in generic/tclVar.c and currenttly exported only + * for use by the bytecode compiler and engine. Some of these could later + * be placed in the public interface. + */ + +EXTERN Var * TclLookupArrayElement _ANSI_ARGS_((Tcl_Interp *interp, + CONST char *arrayName, CONST char *elName, CONST int flags, + CONST char *msg, CONST int createPart1, + CONST int createPart2, Var *arrayPtr)); +EXTERN Var * TclObjLookupVar _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *part1Ptr, CONST char *part2, int flags, + CONST char *msg, CONST int createPart1, + CONST int createPart2, Var **arrayPtrPtr)); +EXTERN Tcl_Obj *TclPtrGetVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr, + Var *arrayPtr, CONST char *part1, CONST char *part2, + CONST int flags)); +EXTERN Tcl_Obj *TclPtrSetVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr, + Var *arrayPtr, CONST char *part1, CONST char *part2, + Tcl_Obj *newValuePtr, CONST int flags)); +EXTERN Tcl_Obj *TclPtrIncrVar _ANSI_ARGS_((Tcl_Interp *interp, Var *varPtr, + Var *arrayPtr, CONST char *part1, CONST char *part2, + CONST long i, CONST int flags)); + +/* + *---------------------------------------------------------------- + * Macros used by the Tcl core to create and release Tcl objects. + * TclNewObj(objPtr) creates a new object denoting an empty string. + * TclDecrRefCount(objPtr) decrements the object's reference count, + * and frees the object if its reference count is zero. + * These macros are inline versions of Tcl_NewObj() and + * Tcl_DecrRefCount(). Notice that the names differ in not having + * a "_" after the "Tcl". Notice also that these macros reference + * their argument more than once, so you should avoid calling them + * with an expression that is expensive to compute or has + * side effects. The ANSI C "prototypes" for these macros are: + * + * EXTERN void TclNewObj _ANSI_ARGS_((Tcl_Obj *objPtr)); + * EXTERN void TclDecrRefCount _ANSI_ARGS_((Tcl_Obj *objPtr)); + * + * These macros are defined in terms of two macros that depend on + * memory allocator in use: TclAllocObjStorage, TclFreeObjStorage. + * They are defined below. + *---------------------------------------------------------------- + */ + +#ifdef TCL_COMPILE_STATS +# define TclIncrObjsAllocated() \ + tclObjsAlloced++ +# define TclIncrObjsFreed() \ + tclObjsFreed++ +#else +# define TclIncrObjsAllocated() +# define TclIncrObjsFreed() +#endif /* TCL_COMPILE_STATS */ + +#define TclNewObj(objPtr) \ + TclAllocObjStorage(objPtr); \ + TclIncrObjsAllocated(); \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL + +#define TclDecrRefCount(objPtr) \ + if (--(objPtr)->refCount <= 0) { \ + if (((objPtr)->typePtr != NULL) \ + && ((objPtr)->typePtr->freeIntRepProc != NULL)) { \ + (objPtr)->typePtr->freeIntRepProc(objPtr); \ + } \ + if (((objPtr)->bytes != NULL) \ + && ((objPtr)->bytes != tclEmptyStringRep)) { \ + ckfree((char *) (objPtr)->bytes); \ + } \ + TclFreeObjStorage(objPtr); \ + TclIncrObjsFreed(); \ + } + +#ifdef TCL_MEM_DEBUG +# define TclAllocObjStorage(objPtr) \ + (objPtr) = (Tcl_Obj *) \ + Tcl_DbCkalloc(sizeof(Tcl_Obj), __FILE__, __LINE__) + +# define TclFreeObjStorage(objPtr) \ + if ((objPtr)->refCount < -1) { \ + panic("Reference count for %lx was negative: %s line %d", \ + (objPtr), __FILE__, __LINE__); \ + } \ + ckfree((char *) (objPtr)) + +# define TclDbNewObj(objPtr, file, line) \ + (objPtr) = (Tcl_Obj *) Tcl_DbCkalloc(sizeof(Tcl_Obj), (file), (line)); \ + (objPtr)->refCount = 0; \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + (objPtr)->typePtr = NULL; \ + TclIncrObjsAllocated() + +#elif defined(PURIFY) + +/* + * The PURIFY mode is like the regular mode, but instead of doing block + * Tcl_Obj allocation and keeping a freed list for efficiency, it always + * allocates and frees a single Tcl_Obj so that tools like Purify can + * better track memory leaks + */ + +# define TclAllocObjStorage(objPtr) \ + (objPtr) = (Tcl_Obj *) Tcl_Ckalloc(sizeof(Tcl_Obj)) + +# define TclFreeObjStorage(objPtr) \ + ckfree((char *) (objPtr)) + +#elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) + +/* + * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's + * from per-thread caches. + */ + +EXTERN Tcl_Obj *TclThreadAllocObj _ANSI_ARGS_((void)); +EXTERN void TclThreadFreeObj _ANSI_ARGS_((Tcl_Obj *)); + +# define TclAllocObjStorage(objPtr) \ + (objPtr) = TclThreadAllocObj() + +# define TclFreeObjStorage(objPtr) \ + TclThreadFreeObj((objPtr)) + +#else /* not TCL_MEM_DEBUG */ + +#ifdef TCL_THREADS +/* declared in tclObj.c */ +extern Tcl_Mutex tclObjMutex; +#endif + +# define TclAllocObjStorage(objPtr) \ + Tcl_MutexLock(&tclObjMutex); \ + if (tclFreeObjList == NULL) { \ + TclAllocateFreeObjects(); \ + } \ + (objPtr) = tclFreeObjList; \ + tclFreeObjList = (Tcl_Obj *) \ + tclFreeObjList->internalRep.otherValuePtr; \ + Tcl_MutexUnlock(&tclObjMutex) + +# define TclFreeObjStorage(objPtr) \ + Tcl_MutexLock(&tclObjMutex); \ + (objPtr)->internalRep.otherValuePtr = (VOID *) tclFreeObjList; \ + tclFreeObjList = (objPtr); \ + Tcl_MutexUnlock(&tclObjMutex) + +#endif /* TCL_MEM_DEBUG */ + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to set a Tcl_Obj's string representation + * to a copy of the "len" bytes starting at "bytePtr". This code + * works even if the byte array contains NULLs as long as the length + * is correct. Because "len" is referenced multiple times, it should + * be as simple an expression as possible. The ANSI C "prototype" for + * this macro is: + * + * EXTERN void TclInitStringRep _ANSI_ARGS_((Tcl_Obj *objPtr, + * char *bytePtr, int len)); + *---------------------------------------------------------------- + */ + +#define TclInitStringRep(objPtr, bytePtr, len) \ + if ((len) == 0) { \ + (objPtr)->bytes = tclEmptyStringRep; \ + (objPtr)->length = 0; \ + } else { \ + (objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \ + memcpy((VOID *) (objPtr)->bytes, (VOID *) (bytePtr), \ + (unsigned) (len)); \ + (objPtr)->bytes[len] = '\0'; \ + (objPtr)->length = (len); \ + } + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to get the string representation's + * byte array pointer from a Tcl_Obj. This is an inline version + * of Tcl_GetString(). The macro's expression result is the string + * rep's byte pointer which might be NULL. The bytes referenced by + * this pointer must not be modified by the caller. + * The ANSI C "prototype" for this macro is: + * + * EXTERN char * TclGetString _ANSI_ARGS_((Tcl_Obj *objPtr)); + *---------------------------------------------------------------- + */ + +#define TclGetString(objPtr) \ + ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString((objPtr))) + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to get a Tcl_WideInt value out of + * a Tcl_Obj of the "wideInt" type. Different implementation on + * different platforms depending whether TCL_WIDE_INT_IS_LONG. + *---------------------------------------------------------------- + */ + +#ifdef TCL_WIDE_INT_IS_LONG +# define TclGetWide(resultVar, objPtr) \ + (resultVar) = (objPtr)->internalRep.longValue +# define TclGetLongFromWide(resultVar, objPtr) \ + (resultVar) = (objPtr)->internalRep.longValue +#else +# define TclGetWide(resultVar, objPtr) \ + (resultVar) = (objPtr)->internalRep.wideValue +# define TclGetLongFromWide(resultVar, objPtr) \ + (resultVar) = Tcl_WideAsLong((objPtr)->internalRep.wideValue) +#endif + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core get a unicode char from a utf string. + * It checks to see if we have a one-byte utf char before calling + * the real Tcl_UtfToUniChar, as this will save a lot of time for + * primarily ascii string handling. The macro's expression result + * is 1 for the 1-byte case or the result of Tcl_UtfToUniChar. + * The ANSI C "prototype" for this macro is: + * + * EXTERN int TclUtfToUniChar _ANSI_ARGS_((CONST char *string, + * Tcl_UniChar *ch)); + *---------------------------------------------------------------- + */ + +#define TclUtfToUniChar(str, chPtr) \ + ((((unsigned char) *(str)) < 0xC0) ? \ + ((*(chPtr) = (Tcl_UniChar) *(str)), 1) \ + : Tcl_UtfToUniChar(str, chPtr)) + +/* + *---------------------------------------------------------------- + * Macro used by the Tcl core to compare Unicode strings. On + * big-endian systems we can use the more efficient memcmp, but + * this would not be lexically correct on little-endian systems. + * The ANSI C "prototype" for this macro is: + * + * EXTERN int TclUniCharNcmp _ANSI_ARGS_((CONST Tcl_UniChar *cs, + * CONST Tcl_UniChar *ct, unsigned long n)); + *---------------------------------------------------------------- + */ +#ifdef WORDS_BIGENDIAN +# define TclUniCharNcmp(cs,ct,n) memcmp((cs),(ct),(n)*sizeof(Tcl_UniChar)) +#else /* !WORDS_BIGENDIAN */ +# define TclUniCharNcmp Tcl_UniCharNcmp +#endif /* WORDS_BIGENDIAN */ + +#include "tclIntDecls.h" + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TCLINT */ + diff --git a/Utilities/TclTk/internals/tk8.4/tclIntDecls.h b/Utilities/TclTk/internals/tk8.4/tclIntDecls.h new file mode 100644 index 0000000..798805a --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tclIntDecls.h @@ -0,0 +1,1324 @@ +/* + * tclIntDecls.h -- + * + * This file contains the declarations for all unsupported + * functions that are exported by the Tcl library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tclIntDecls.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TCLINTDECLS +#define _TCLINTDECLS + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tclInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +/* Slot 0 is reserved */ +/* 1 */ +EXTERN int TclAccessDeleteProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 2 */ +EXTERN int TclAccessInsertProc _ANSI_ARGS_(( + TclAccessProc_ * proc)); +/* 3 */ +EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); +/* Slot 4 is reserved */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 5 */ +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp, + int numPids, Tcl_Pid * pidPtr, + Tcl_Channel errorChan)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 5 */ +EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp * interp, + int numPids, Tcl_Pid * pidPtr, + Tcl_Channel errorChan)); +#endif /* __WIN32__ */ +/* 6 */ +EXTERN void TclCleanupCommand _ANSI_ARGS_((Command * cmdPtr)); +/* 7 */ +EXTERN int TclCopyAndCollapse _ANSI_ARGS_((int count, + CONST char * src, char * dst)); +/* 8 */ +EXTERN int TclCopyChannel _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel inChan, Tcl_Channel outChan, + int toRead, Tcl_Obj * cmdPtr)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 9 */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, + int argc, CONST char ** argv, + Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, + TclFile * outPipePtr, TclFile * errFilePtr)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 9 */ +EXTERN int TclCreatePipeline _ANSI_ARGS_((Tcl_Interp * interp, + int argc, CONST char ** argv, + Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, + TclFile * outPipePtr, TclFile * errFilePtr)); +#endif /* __WIN32__ */ +/* 10 */ +EXTERN int TclCreateProc _ANSI_ARGS_((Tcl_Interp * interp, + Namespace * nsPtr, CONST char * procName, + Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, + Proc ** procPtrPtr)); +/* 11 */ +EXTERN void TclDeleteCompiledLocalVars _ANSI_ARGS_(( + Interp * iPtr, CallFrame * framePtr)); +/* 12 */ +EXTERN void TclDeleteVars _ANSI_ARGS_((Interp * iPtr, + Tcl_HashTable * tablePtr)); +/* 13 */ +EXTERN int TclDoGlob _ANSI_ARGS_((Tcl_Interp * interp, + char * separators, Tcl_DString * headPtr, + char * tail, Tcl_GlobTypeData * types)); +/* 14 */ +EXTERN void TclDumpMemoryInfo _ANSI_ARGS_((FILE * outFile)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN void TclExprFloatError _ANSI_ARGS_((Tcl_Interp * interp, + double value)); +/* Slot 17 is reserved */ +/* Slot 18 is reserved */ +/* Slot 19 is reserved */ +/* Slot 20 is reserved */ +/* Slot 21 is reserved */ +/* 22 */ +EXTERN int TclFindElement _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * listStr, int listLength, + CONST char ** elementPtr, + CONST char ** nextPtr, int * sizePtr, + int * bracePtr)); +/* 23 */ +EXTERN Proc * TclFindProc _ANSI_ARGS_((Interp * iPtr, + CONST char * procName)); +/* 24 */ +EXTERN int TclFormatInt _ANSI_ARGS_((char * buffer, long n)); +/* 25 */ +EXTERN void TclFreePackageInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 26 is reserved */ +/* 27 */ +EXTERN int TclGetDate _ANSI_ARGS_((char * p, unsigned long now, + long zone, unsigned long * timePtr)); +/* 28 */ +EXTERN Tcl_Channel TclpGetDefaultStdChannel _ANSI_ARGS_((int type)); +/* Slot 29 is reserved */ +/* Slot 30 is reserved */ +/* 31 */ +EXTERN char * TclGetExtension _ANSI_ARGS_((char * name)); +/* 32 */ +EXTERN int TclGetFrame _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * str, CallFrame ** framePtrPtr)); +/* 33 */ +EXTERN TclCmdProcType TclGetInterpProc _ANSI_ARGS_((void)); +/* 34 */ +EXTERN int TclGetIntForIndex _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * objPtr, int endValue, + int * indexPtr)); +/* Slot 35 is reserved */ +/* 36 */ +EXTERN int TclGetLong _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * str, long * longPtr)); +/* 37 */ +EXTERN int TclGetLoadedPackages _ANSI_ARGS_(( + Tcl_Interp * interp, char * targetName)); +/* 38 */ +EXTERN int TclGetNamespaceForQualName _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * qualName, + Namespace * cxtNsPtr, int flags, + Namespace ** nsPtrPtr, + Namespace ** altNsPtrPtr, + Namespace ** actualCxtPtrPtr, + CONST char ** simpleNamePtr)); +/* 39 */ +EXTERN TclObjCmdProcType TclGetObjInterpProc _ANSI_ARGS_((void)); +/* 40 */ +EXTERN int TclGetOpenMode _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * str, int * seekFlagPtr)); +/* 41 */ +EXTERN Tcl_Command TclGetOriginalCommand _ANSI_ARGS_(( + Tcl_Command command)); +/* 42 */ +EXTERN char * TclpGetUserHome _ANSI_ARGS_((CONST char * name, + Tcl_DString * bufferPtr)); +/* 43 */ +EXTERN int TclGlobalInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int argc, CONST84 char ** argv, int flags)); +/* 44 */ +EXTERN int TclGuessPackageName _ANSI_ARGS_(( + CONST char * fileName, Tcl_DString * bufPtr)); +/* 45 */ +EXTERN int TclHideUnsafeCommands _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 46 */ +EXTERN int TclInExit _ANSI_ARGS_((void)); +/* Slot 47 is reserved */ +/* Slot 48 is reserved */ +/* 49 */ +EXTERN Tcl_Obj * TclIncrVar2 _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, + long incrAmount, int part1NotParsed)); +/* 50 */ +EXTERN void TclInitCompiledLocals _ANSI_ARGS_(( + Tcl_Interp * interp, CallFrame * framePtr, + Namespace * nsPtr)); +/* 51 */ +EXTERN int TclInterpInit _ANSI_ARGS_((Tcl_Interp * interp)); +/* 52 */ +EXTERN int TclInvoke _ANSI_ARGS_((Tcl_Interp * interp, int argc, + CONST84 char ** argv, int flags)); +/* 53 */ +EXTERN int TclInvokeObjectCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int argc, CONST84 char ** argv)); +/* 54 */ +EXTERN int TclInvokeStringCommand _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[])); +/* 55 */ +EXTERN Proc * TclIsProc _ANSI_ARGS_((Command * cmdPtr)); +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +/* 58 */ +EXTERN Var * TclLookupVar _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * part1, CONST char * part2, + int flags, CONST char * msg, int createPart1, + int createPart2, Var ** arrayPtrPtr)); +/* Slot 59 is reserved */ +/* 60 */ +EXTERN int TclNeedSpace _ANSI_ARGS_((CONST char * start, + CONST char * end)); +/* 61 */ +EXTERN Tcl_Obj * TclNewProcBodyObj _ANSI_ARGS_((Proc * procPtr)); +/* 62 */ +EXTERN int TclObjCommandComplete _ANSI_ARGS_((Tcl_Obj * cmdPtr)); +/* 63 */ +EXTERN int TclObjInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int objc, + Tcl_Obj *CONST objv[])); +/* 64 */ +EXTERN int TclObjInvoke _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 65 */ +EXTERN int TclObjInvokeGlobal _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], int flags)); +/* 66 */ +EXTERN int TclOpenFileChannelDeleteProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* 67 */ +EXTERN int TclOpenFileChannelInsertProc _ANSI_ARGS_(( + TclOpenFileChannelProc_ * proc)); +/* Slot 68 is reserved */ +/* 69 */ +EXTERN char * TclpAlloc _ANSI_ARGS_((unsigned int size)); +/* Slot 70 is reserved */ +/* Slot 71 is reserved */ +/* Slot 72 is reserved */ +/* Slot 73 is reserved */ +/* 74 */ +EXTERN void TclpFree _ANSI_ARGS_((char * ptr)); +/* 75 */ +EXTERN unsigned long TclpGetClicks _ANSI_ARGS_((void)); +/* 76 */ +EXTERN unsigned long TclpGetSeconds _ANSI_ARGS_((void)); +/* 77 */ +EXTERN void TclpGetTime _ANSI_ARGS_((Tcl_Time * time)); +/* 78 */ +EXTERN int TclpGetTimeZone _ANSI_ARGS_((unsigned long time)); +/* Slot 79 is reserved */ +/* Slot 80 is reserved */ +/* 81 */ +EXTERN char * TclpRealloc _ANSI_ARGS_((char * ptr, + unsigned int size)); +/* Slot 82 is reserved */ +/* Slot 83 is reserved */ +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +/* 88 */ +EXTERN char * TclPrecTraceProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, CONST char * name1, + CONST char * name2, int flags)); +/* 89 */ +EXTERN int TclPreventAliasLoop _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Interp * cmdInterp, Tcl_Command cmd)); +/* Slot 90 is reserved */ +/* 91 */ +EXTERN void TclProcCleanupProc _ANSI_ARGS_((Proc * procPtr)); +/* 92 */ +EXTERN int TclProcCompileProc _ANSI_ARGS_((Tcl_Interp * interp, + Proc * procPtr, Tcl_Obj * bodyPtr, + Namespace * nsPtr, CONST char * description, + CONST char * procName)); +/* 93 */ +EXTERN void TclProcDeleteProc _ANSI_ARGS_((ClientData clientData)); +/* 94 */ +EXTERN int TclProcInterpProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, + CONST84 char ** argv)); +/* Slot 95 is reserved */ +/* 96 */ +EXTERN int TclRenameCommand _ANSI_ARGS_((Tcl_Interp * interp, + char * oldName, char * newName)); +/* 97 */ +EXTERN void TclResetShadowedCmdRefs _ANSI_ARGS_(( + Tcl_Interp * interp, Command * newCmdPtr)); +/* 98 */ +EXTERN int TclServiceIdle _ANSI_ARGS_((void)); +/* Slot 99 is reserved */ +/* Slot 100 is reserved */ +/* 101 */ +EXTERN char * TclSetPreInitScript _ANSI_ARGS_((char * string)); +/* 102 */ +EXTERN void TclSetupEnv _ANSI_ARGS_((Tcl_Interp * interp)); +/* 103 */ +EXTERN int TclSockGetPort _ANSI_ARGS_((Tcl_Interp * interp, + char * str, char * proto, int * portPtr)); +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +/* 104 */ +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +#endif /* UNIX */ +#ifdef __WIN32__ +/* 104 */ +EXTERN int TclSockMinimumBuffers _ANSI_ARGS_((int sock, + int size)); +#endif /* __WIN32__ */ +/* Slot 105 is reserved */ +/* 106 */ +EXTERN int TclStatDeleteProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 107 */ +EXTERN int TclStatInsertProc _ANSI_ARGS_((TclStatProc_ * proc)); +/* 108 */ +EXTERN void TclTeardownNamespace _ANSI_ARGS_((Namespace * nsPtr)); +/* 109 */ +EXTERN int TclUpdateReturnInfo _ANSI_ARGS_((Interp * iPtr)); +/* Slot 110 is reserved */ +/* 111 */ +EXTERN void Tcl_AddInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * name, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 112 */ +EXTERN int Tcl_AppendExportList _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Namespace * nsPtr, + Tcl_Obj * objPtr)); +/* 113 */ +EXTERN Tcl_Namespace * Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * name, ClientData clientData, + Tcl_NamespaceDeleteProc * deleteProc)); +/* 114 */ +EXTERN void Tcl_DeleteNamespace _ANSI_ARGS_(( + Tcl_Namespace * nsPtr)); +/* 115 */ +EXTERN int Tcl_Export _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, CONST char * pattern, + int resetListFirst)); +/* 116 */ +EXTERN Tcl_Command Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * name, + Tcl_Namespace * contextNsPtr, int flags)); +/* 117 */ +EXTERN Tcl_Namespace * Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * name, + Tcl_Namespace * contextNsPtr, int flags)); +/* 118 */ +EXTERN int Tcl_GetInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * name, + Tcl_ResolverInfo * resInfo)); +/* 119 */ +EXTERN int Tcl_GetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolverInfo * resInfo)); +/* 120 */ +EXTERN Tcl_Var Tcl_FindNamespaceVar _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * name, + Tcl_Namespace * contextNsPtr, int flags)); +/* 121 */ +EXTERN int Tcl_ForgetImport _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, CONST char * pattern)); +/* 122 */ +EXTERN Tcl_Command Tcl_GetCommandFromObj _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr)); +/* 123 */ +EXTERN void Tcl_GetCommandFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Command command, + Tcl_Obj * objPtr)); +/* 124 */ +EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 125 */ +EXTERN Tcl_Namespace * Tcl_GetGlobalNamespace _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 126 */ +EXTERN void Tcl_GetVariableFullName _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Var variable, + Tcl_Obj * objPtr)); +/* 127 */ +EXTERN int Tcl_Import _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Namespace * nsPtr, CONST char * pattern, + int allowOverwrite)); +/* 128 */ +EXTERN void Tcl_PopCallFrame _ANSI_ARGS_((Tcl_Interp* interp)); +/* 129 */ +EXTERN int Tcl_PushCallFrame _ANSI_ARGS_((Tcl_Interp* interp, + Tcl_CallFrame * framePtr, + Tcl_Namespace * nsPtr, int isProcCallFrame)); +/* 130 */ +EXTERN int Tcl_RemoveInterpResolvers _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * name)); +/* 131 */ +EXTERN void Tcl_SetNamespaceResolvers _ANSI_ARGS_(( + Tcl_Namespace * namespacePtr, + Tcl_ResolveCmdProc * cmdProc, + Tcl_ResolveVarProc * varProc, + Tcl_ResolveCompiledVarProc * compiledVarProc)); +/* 132 */ +EXTERN int TclpHasSockets _ANSI_ARGS_((Tcl_Interp * interp)); +/* 133 */ +EXTERN struct tm * TclpGetDate _ANSI_ARGS_((TclpTime_t time, int useGMT)); +/* 134 */ +EXTERN size_t TclpStrftime _ANSI_ARGS_((char * s, size_t maxsize, + CONST char * format, CONST struct tm * t, + int useGMT)); +/* 135 */ +EXTERN int TclpCheckStackSpace _ANSI_ARGS_((void)); +/* Slot 136 is reserved */ +/* Slot 137 is reserved */ +/* 138 */ +EXTERN CONST84_RETURN char * TclGetEnv _ANSI_ARGS_((CONST char * name, + Tcl_DString * valuePtr)); +/* Slot 139 is reserved */ +/* 140 */ +EXTERN int TclLooksLikeInt _ANSI_ARGS_((CONST char * bytes, + int length)); +/* 141 */ +EXTERN CONST84_RETURN char * TclpGetCwd _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * cwdPtr)); +/* 142 */ +EXTERN int TclSetByteCodeFromAny _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * objPtr, + CompileHookProc * hookProc, + ClientData clientData)); +/* 143 */ +EXTERN int TclAddLiteralObj _ANSI_ARGS_(( + struct CompileEnv * envPtr, Tcl_Obj * objPtr, + LiteralEntry ** litPtrPtr)); +/* 144 */ +EXTERN void TclHideLiteral _ANSI_ARGS_((Tcl_Interp * interp, + struct CompileEnv * envPtr, int index)); +/* 145 */ +EXTERN struct AuxDataType * TclGetAuxDataType _ANSI_ARGS_((char * typeName)); +/* 146 */ +EXTERN TclHandle TclHandleCreate _ANSI_ARGS_((VOID * ptr)); +/* 147 */ +EXTERN void TclHandleFree _ANSI_ARGS_((TclHandle handle)); +/* 148 */ +EXTERN TclHandle TclHandlePreserve _ANSI_ARGS_((TclHandle handle)); +/* 149 */ +EXTERN void TclHandleRelease _ANSI_ARGS_((TclHandle handle)); +/* 150 */ +EXTERN int TclRegAbout _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_RegExp re)); +/* 151 */ +EXTERN void TclRegExpRangeUniChar _ANSI_ARGS_((Tcl_RegExp re, + int index, int * startPtr, int * endPtr)); +/* 152 */ +EXTERN void TclSetLibraryPath _ANSI_ARGS_((Tcl_Obj * pathPtr)); +/* 153 */ +EXTERN Tcl_Obj * TclGetLibraryPath _ANSI_ARGS_((void)); +/* Slot 154 is reserved */ +/* Slot 155 is reserved */ +/* 156 */ +EXTERN void TclRegError _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * msg, int status)); +/* 157 */ +EXTERN Var * TclVarTraceExists _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * varName)); +/* 158 */ +EXTERN void TclSetStartupScriptFileName _ANSI_ARGS_(( + CONST char * filename)); +/* 159 */ +EXTERN CONST84_RETURN char * TclGetStartupScriptFileName _ANSI_ARGS_((void)); +/* Slot 160 is reserved */ +/* 161 */ +EXTERN int TclChannelTransform _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Channel chan, Tcl_Obj * cmdObjPtr)); +/* 162 */ +EXTERN void TclChannelEventScriptInvoker _ANSI_ARGS_(( + ClientData clientData, int flags)); +/* 163 */ +EXTERN void * TclGetInstructionTable _ANSI_ARGS_((void)); +/* 164 */ +EXTERN void TclExpandCodeArray _ANSI_ARGS_((void * envPtr)); +/* 165 */ +EXTERN void TclpSetInitialEncodings _ANSI_ARGS_((void)); +/* 166 */ +EXTERN int TclListObjSetElement _ANSI_ARGS_(( + Tcl_Interp * interp, Tcl_Obj * listPtr, + int index, Tcl_Obj * valuePtr)); +/* 167 */ +EXTERN void TclSetStartupScriptPath _ANSI_ARGS_(( + Tcl_Obj * pathPtr)); +/* 168 */ +EXTERN Tcl_Obj * TclGetStartupScriptPath _ANSI_ARGS_((void)); +/* 169 */ +EXTERN int TclpUtfNcmp2 _ANSI_ARGS_((CONST char * s1, + CONST char * s2, unsigned long n)); +/* 170 */ +EXTERN int TclCheckInterpTraces _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * command, + int numChars, Command * cmdPtr, int result, + int traceFlags, int objc, + Tcl_Obj *CONST objv[])); +/* 171 */ +EXTERN int TclCheckExecutionTraces _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * command, + int numChars, Command * cmdPtr, int result, + int traceFlags, int objc, + Tcl_Obj *CONST objv[])); +/* 172 */ +EXTERN int TclInThreadExit _ANSI_ARGS_((void)); +/* 173 */ +EXTERN int TclUniCharMatch _ANSI_ARGS_(( + CONST Tcl_UniChar * string, int strLen, + CONST Tcl_UniChar * pattern, int ptnLen, + int nocase)); + +typedef struct TclIntStubs { + int magic; + struct TclIntStubHooks *hooks; + + void *reserved0; + int (*tclAccessDeleteProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 1 */ + int (*tclAccessInsertProc) _ANSI_ARGS_((TclAccessProc_ * proc)); /* 2 */ + void (*tclAllocateFreeObjects) _ANSI_ARGS_((void)); /* 3 */ + void *reserved4; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclCleanupChildren) _ANSI_ARGS_((Tcl_Interp * interp, int numPids, Tcl_Pid * pidPtr, Tcl_Channel errorChan)); /* 5 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved5; +#endif /* MAC_TCL */ + void (*tclCleanupCommand) _ANSI_ARGS_((Command * cmdPtr)); /* 6 */ + int (*tclCopyAndCollapse) _ANSI_ARGS_((int count, CONST char * src, char * dst)); /* 7 */ + int (*tclCopyChannel) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj * cmdPtr)); /* 8 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclCreatePipeline) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST char ** argv, Tcl_Pid ** pidArrayPtr, TclFile * inPipePtr, TclFile * outPipePtr, TclFile * errFilePtr)); /* 9 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved9; +#endif /* MAC_TCL */ + int (*tclCreateProc) _ANSI_ARGS_((Tcl_Interp * interp, Namespace * nsPtr, CONST char * procName, Tcl_Obj * argsPtr, Tcl_Obj * bodyPtr, Proc ** procPtrPtr)); /* 10 */ + void (*tclDeleteCompiledLocalVars) _ANSI_ARGS_((Interp * iPtr, CallFrame * framePtr)); /* 11 */ + void (*tclDeleteVars) _ANSI_ARGS_((Interp * iPtr, Tcl_HashTable * tablePtr)); /* 12 */ + int (*tclDoGlob) _ANSI_ARGS_((Tcl_Interp * interp, char * separators, Tcl_DString * headPtr, char * tail, Tcl_GlobTypeData * types)); /* 13 */ + void (*tclDumpMemoryInfo) _ANSI_ARGS_((FILE * outFile)); /* 14 */ + void *reserved15; + void (*tclExprFloatError) _ANSI_ARGS_((Tcl_Interp * interp, double value)); /* 16 */ + void *reserved17; + void *reserved18; + void *reserved19; + void *reserved20; + void *reserved21; + int (*tclFindElement) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * listStr, int listLength, CONST char ** elementPtr, CONST char ** nextPtr, int * sizePtr, int * bracePtr)); /* 22 */ + Proc * (*tclFindProc) _ANSI_ARGS_((Interp * iPtr, CONST char * procName)); /* 23 */ + int (*tclFormatInt) _ANSI_ARGS_((char * buffer, long n)); /* 24 */ + void (*tclFreePackageInfo) _ANSI_ARGS_((Interp * iPtr)); /* 25 */ + void *reserved26; + int (*tclGetDate) _ANSI_ARGS_((char * p, unsigned long now, long zone, unsigned long * timePtr)); /* 27 */ + Tcl_Channel (*tclpGetDefaultStdChannel) _ANSI_ARGS_((int type)); /* 28 */ + void *reserved29; + void *reserved30; + char * (*tclGetExtension) _ANSI_ARGS_((char * name)); /* 31 */ + int (*tclGetFrame) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, CallFrame ** framePtrPtr)); /* 32 */ + TclCmdProcType (*tclGetInterpProc) _ANSI_ARGS_((void)); /* 33 */ + int (*tclGetIntForIndex) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int endValue, int * indexPtr)); /* 34 */ + void *reserved35; + int (*tclGetLong) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, long * longPtr)); /* 36 */ + int (*tclGetLoadedPackages) _ANSI_ARGS_((Tcl_Interp * interp, char * targetName)); /* 37 */ + int (*tclGetNamespaceForQualName) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * qualName, Namespace * cxtNsPtr, int flags, Namespace ** nsPtrPtr, Namespace ** altNsPtrPtr, Namespace ** actualCxtPtrPtr, CONST char ** simpleNamePtr)); /* 38 */ + TclObjCmdProcType (*tclGetObjInterpProc) _ANSI_ARGS_((void)); /* 39 */ + int (*tclGetOpenMode) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * str, int * seekFlagPtr)); /* 40 */ + Tcl_Command (*tclGetOriginalCommand) _ANSI_ARGS_((Tcl_Command command)); /* 41 */ + char * (*tclpGetUserHome) _ANSI_ARGS_((CONST char * name, Tcl_DString * bufferPtr)); /* 42 */ + int (*tclGlobalInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST84 char ** argv, int flags)); /* 43 */ + int (*tclGuessPackageName) _ANSI_ARGS_((CONST char * fileName, Tcl_DString * bufPtr)); /* 44 */ + int (*tclHideUnsafeCommands) _ANSI_ARGS_((Tcl_Interp * interp)); /* 45 */ + int (*tclInExit) _ANSI_ARGS_((void)); /* 46 */ + void *reserved47; + void *reserved48; + Tcl_Obj * (*tclIncrVar2) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * part1Ptr, Tcl_Obj * part2Ptr, long incrAmount, int part1NotParsed)); /* 49 */ + void (*tclInitCompiledLocals) _ANSI_ARGS_((Tcl_Interp * interp, CallFrame * framePtr, Namespace * nsPtr)); /* 50 */ + int (*tclInterpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 51 */ + int (*tclInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int argc, CONST84 char ** argv, int flags)); /* 52 */ + int (*tclInvokeObjectCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, CONST84 char ** argv)); /* 53 */ + int (*tclInvokeStringCommand) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 54 */ + Proc * (*tclIsProc) _ANSI_ARGS_((Command * cmdPtr)); /* 55 */ + void *reserved56; + void *reserved57; + Var * (*tclLookupVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * part1, CONST char * part2, int flags, CONST char * msg, int createPart1, int createPart2, Var ** arrayPtrPtr)); /* 58 */ + void *reserved59; + int (*tclNeedSpace) _ANSI_ARGS_((CONST char * start, CONST char * end)); /* 60 */ + Tcl_Obj * (*tclNewProcBodyObj) _ANSI_ARGS_((Proc * procPtr)); /* 61 */ + int (*tclObjCommandComplete) _ANSI_ARGS_((Tcl_Obj * cmdPtr)); /* 62 */ + int (*tclObjInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])); /* 63 */ + int (*tclObjInvoke) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 64 */ + int (*tclObjInvokeGlobal) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], int flags)); /* 65 */ + int (*tclOpenFileChannelDeleteProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 66 */ + int (*tclOpenFileChannelInsertProc) _ANSI_ARGS_((TclOpenFileChannelProc_ * proc)); /* 67 */ + void *reserved68; + char * (*tclpAlloc) _ANSI_ARGS_((unsigned int size)); /* 69 */ + void *reserved70; + void *reserved71; + void *reserved72; + void *reserved73; + void (*tclpFree) _ANSI_ARGS_((char * ptr)); /* 74 */ + unsigned long (*tclpGetClicks) _ANSI_ARGS_((void)); /* 75 */ + unsigned long (*tclpGetSeconds) _ANSI_ARGS_((void)); /* 76 */ + void (*tclpGetTime) _ANSI_ARGS_((Tcl_Time * time)); /* 77 */ + int (*tclpGetTimeZone) _ANSI_ARGS_((unsigned long time)); /* 78 */ + void *reserved79; + void *reserved80; + char * (*tclpRealloc) _ANSI_ARGS_((char * ptr, unsigned int size)); /* 81 */ + void *reserved82; + void *reserved83; + void *reserved84; + void *reserved85; + void *reserved86; + void *reserved87; + char * (*tclPrecTraceProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, CONST char * name1, CONST char * name2, int flags)); /* 88 */ + int (*tclPreventAliasLoop) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Interp * cmdInterp, Tcl_Command cmd)); /* 89 */ + void *reserved90; + void (*tclProcCleanupProc) _ANSI_ARGS_((Proc * procPtr)); /* 91 */ + int (*tclProcCompileProc) _ANSI_ARGS_((Tcl_Interp * interp, Proc * procPtr, Tcl_Obj * bodyPtr, Namespace * nsPtr, CONST char * description, CONST char * procName)); /* 92 */ + void (*tclProcDeleteProc) _ANSI_ARGS_((ClientData clientData)); /* 93 */ + int (*tclProcInterpProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, CONST84 char ** argv)); /* 94 */ + void *reserved95; + int (*tclRenameCommand) _ANSI_ARGS_((Tcl_Interp * interp, char * oldName, char * newName)); /* 96 */ + void (*tclResetShadowedCmdRefs) _ANSI_ARGS_((Tcl_Interp * interp, Command * newCmdPtr)); /* 97 */ + int (*tclServiceIdle) _ANSI_ARGS_((void)); /* 98 */ + void *reserved99; + void *reserved100; + char * (*tclSetPreInitScript) _ANSI_ARGS_((char * string)); /* 101 */ + void (*tclSetupEnv) _ANSI_ARGS_((Tcl_Interp * interp)); /* 102 */ + int (*tclSockGetPort) _ANSI_ARGS_((Tcl_Interp * interp, char * str, char * proto, int * portPtr)); /* 103 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */ +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tclSockMinimumBuffers) _ANSI_ARGS_((int sock, int size)); /* 104 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void *reserved104; +#endif /* MAC_TCL */ + void *reserved105; + int (*tclStatDeleteProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 106 */ + int (*tclStatInsertProc) _ANSI_ARGS_((TclStatProc_ * proc)); /* 107 */ + void (*tclTeardownNamespace) _ANSI_ARGS_((Namespace * nsPtr)); /* 108 */ + int (*tclUpdateReturnInfo) _ANSI_ARGS_((Interp * iPtr)); /* 109 */ + void *reserved110; + void (*tcl_AddInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 111 */ + int (*tcl_AppendExportList) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, Tcl_Obj * objPtr)); /* 112 */ + Tcl_Namespace * (*tcl_CreateNamespace) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, ClientData clientData, Tcl_NamespaceDeleteProc * deleteProc)); /* 113 */ + void (*tcl_DeleteNamespace) _ANSI_ARGS_((Tcl_Namespace * nsPtr)); /* 114 */ + int (*tcl_Export) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, CONST char * pattern, int resetListFirst)); /* 115 */ + Tcl_Command (*tcl_FindCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 116 */ + Tcl_Namespace * (*tcl_FindNamespace) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 117 */ + int (*tcl_GetInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_ResolverInfo * resInfo)); /* 118 */ + int (*tcl_GetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolverInfo * resInfo)); /* 119 */ + Tcl_Var (*tcl_FindNamespaceVar) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, Tcl_Namespace * contextNsPtr, int flags)); /* 120 */ + int (*tcl_ForgetImport) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, CONST char * pattern)); /* 121 */ + Tcl_Command (*tcl_GetCommandFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr)); /* 122 */ + void (*tcl_GetCommandFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Command command, Tcl_Obj * objPtr)); /* 123 */ + Tcl_Namespace * (*tcl_GetCurrentNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 124 */ + Tcl_Namespace * (*tcl_GetGlobalNamespace) _ANSI_ARGS_((Tcl_Interp * interp)); /* 125 */ + void (*tcl_GetVariableFullName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Var variable, Tcl_Obj * objPtr)); /* 126 */ + int (*tcl_Import) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Namespace * nsPtr, CONST char * pattern, int allowOverwrite)); /* 127 */ + void (*tcl_PopCallFrame) _ANSI_ARGS_((Tcl_Interp* interp)); /* 128 */ + int (*tcl_PushCallFrame) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_CallFrame * framePtr, Tcl_Namespace * nsPtr, int isProcCallFrame)); /* 129 */ + int (*tcl_RemoveInterpResolvers) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 130 */ + void (*tcl_SetNamespaceResolvers) _ANSI_ARGS_((Tcl_Namespace * namespacePtr, Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc, Tcl_ResolveCompiledVarProc * compiledVarProc)); /* 131 */ + int (*tclpHasSockets) _ANSI_ARGS_((Tcl_Interp * interp)); /* 132 */ + struct tm * (*tclpGetDate) _ANSI_ARGS_((TclpTime_t time, int useGMT)); /* 133 */ + size_t (*tclpStrftime) _ANSI_ARGS_((char * s, size_t maxsize, CONST char * format, CONST struct tm * t, int useGMT)); /* 134 */ + int (*tclpCheckStackSpace) _ANSI_ARGS_((void)); /* 135 */ + void *reserved136; + void *reserved137; + CONST84_RETURN char * (*tclGetEnv) _ANSI_ARGS_((CONST char * name, Tcl_DString * valuePtr)); /* 138 */ + void *reserved139; + int (*tclLooksLikeInt) _ANSI_ARGS_((CONST char * bytes, int length)); /* 140 */ + CONST84_RETURN char * (*tclpGetCwd) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * cwdPtr)); /* 141 */ + int (*tclSetByteCodeFromAny) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, CompileHookProc * hookProc, ClientData clientData)); /* 142 */ + int (*tclAddLiteralObj) _ANSI_ARGS_((struct CompileEnv * envPtr, Tcl_Obj * objPtr, LiteralEntry ** litPtrPtr)); /* 143 */ + void (*tclHideLiteral) _ANSI_ARGS_((Tcl_Interp * interp, struct CompileEnv * envPtr, int index)); /* 144 */ + struct AuxDataType * (*tclGetAuxDataType) _ANSI_ARGS_((char * typeName)); /* 145 */ + TclHandle (*tclHandleCreate) _ANSI_ARGS_((VOID * ptr)); /* 146 */ + void (*tclHandleFree) _ANSI_ARGS_((TclHandle handle)); /* 147 */ + TclHandle (*tclHandlePreserve) _ANSI_ARGS_((TclHandle handle)); /* 148 */ + void (*tclHandleRelease) _ANSI_ARGS_((TclHandle handle)); /* 149 */ + int (*tclRegAbout) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_RegExp re)); /* 150 */ + void (*tclRegExpRangeUniChar) _ANSI_ARGS_((Tcl_RegExp re, int index, int * startPtr, int * endPtr)); /* 151 */ + void (*tclSetLibraryPath) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 152 */ + Tcl_Obj * (*tclGetLibraryPath) _ANSI_ARGS_((void)); /* 153 */ + void *reserved154; + void *reserved155; + void (*tclRegError) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * msg, int status)); /* 156 */ + Var * (*tclVarTraceExists) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * varName)); /* 157 */ + void (*tclSetStartupScriptFileName) _ANSI_ARGS_((CONST char * filename)); /* 158 */ + CONST84_RETURN char * (*tclGetStartupScriptFileName) _ANSI_ARGS_((void)); /* 159 */ + void *reserved160; + int (*tclChannelTransform) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Channel chan, Tcl_Obj * cmdObjPtr)); /* 161 */ + void (*tclChannelEventScriptInvoker) _ANSI_ARGS_((ClientData clientData, int flags)); /* 162 */ + void * (*tclGetInstructionTable) _ANSI_ARGS_((void)); /* 163 */ + void (*tclExpandCodeArray) _ANSI_ARGS_((void * envPtr)); /* 164 */ + void (*tclpSetInitialEncodings) _ANSI_ARGS_((void)); /* 165 */ + int (*tclListObjSetElement) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * listPtr, int index, Tcl_Obj * valuePtr)); /* 166 */ + void (*tclSetStartupScriptPath) _ANSI_ARGS_((Tcl_Obj * pathPtr)); /* 167 */ + Tcl_Obj * (*tclGetStartupScriptPath) _ANSI_ARGS_((void)); /* 168 */ + int (*tclpUtfNcmp2) _ANSI_ARGS_((CONST char * s1, CONST char * s2, unsigned long n)); /* 169 */ + int (*tclCheckInterpTraces) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * command, int numChars, Command * cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *CONST objv[])); /* 170 */ + int (*tclCheckExecutionTraces) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * command, int numChars, Command * cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *CONST objv[])); /* 171 */ + int (*tclInThreadExit) _ANSI_ARGS_((void)); /* 172 */ + int (*tclUniCharMatch) _ANSI_ARGS_((CONST Tcl_UniChar * string, int strLen, CONST Tcl_UniChar * pattern, int ptnLen, int nocase)); /* 173 */ +} TclIntStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TclIntStubs *tclIntStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) + +/* + * Inline function declarations: + */ + +/* Slot 0 is reserved */ +#ifndef TclAccessDeleteProc +#define TclAccessDeleteProc \ + (tclIntStubsPtr->tclAccessDeleteProc) /* 1 */ +#endif +#ifndef TclAccessInsertProc +#define TclAccessInsertProc \ + (tclIntStubsPtr->tclAccessInsertProc) /* 2 */ +#endif +#ifndef TclAllocateFreeObjects +#define TclAllocateFreeObjects \ + (tclIntStubsPtr->tclAllocateFreeObjects) /* 3 */ +#endif +/* Slot 4 is reserved */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclCleanupChildren +#define TclCleanupChildren \ + (tclIntStubsPtr->tclCleanupChildren) /* 5 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclCleanupChildren +#define TclCleanupChildren \ + (tclIntStubsPtr->tclCleanupChildren) /* 5 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclCleanupCommand +#define TclCleanupCommand \ + (tclIntStubsPtr->tclCleanupCommand) /* 6 */ +#endif +#ifndef TclCopyAndCollapse +#define TclCopyAndCollapse \ + (tclIntStubsPtr->tclCopyAndCollapse) /* 7 */ +#endif +#ifndef TclCopyChannel +#define TclCopyChannel \ + (tclIntStubsPtr->tclCopyChannel) /* 8 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclCreatePipeline +#define TclCreatePipeline \ + (tclIntStubsPtr->tclCreatePipeline) /* 9 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclCreatePipeline +#define TclCreatePipeline \ + (tclIntStubsPtr->tclCreatePipeline) /* 9 */ +#endif +#endif /* __WIN32__ */ +#ifndef TclCreateProc +#define TclCreateProc \ + (tclIntStubsPtr->tclCreateProc) /* 10 */ +#endif +#ifndef TclDeleteCompiledLocalVars +#define TclDeleteCompiledLocalVars \ + (tclIntStubsPtr->tclDeleteCompiledLocalVars) /* 11 */ +#endif +#ifndef TclDeleteVars +#define TclDeleteVars \ + (tclIntStubsPtr->tclDeleteVars) /* 12 */ +#endif +#ifndef TclDoGlob +#define TclDoGlob \ + (tclIntStubsPtr->tclDoGlob) /* 13 */ +#endif +#ifndef TclDumpMemoryInfo +#define TclDumpMemoryInfo \ + (tclIntStubsPtr->tclDumpMemoryInfo) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TclExprFloatError +#define TclExprFloatError \ + (tclIntStubsPtr->tclExprFloatError) /* 16 */ +#endif +/* Slot 17 is reserved */ +/* Slot 18 is reserved */ +/* Slot 19 is reserved */ +/* Slot 20 is reserved */ +/* Slot 21 is reserved */ +#ifndef TclFindElement +#define TclFindElement \ + (tclIntStubsPtr->tclFindElement) /* 22 */ +#endif +#ifndef TclFindProc +#define TclFindProc \ + (tclIntStubsPtr->tclFindProc) /* 23 */ +#endif +#ifndef TclFormatInt +#define TclFormatInt \ + (tclIntStubsPtr->tclFormatInt) /* 24 */ +#endif +#ifndef TclFreePackageInfo +#define TclFreePackageInfo \ + (tclIntStubsPtr->tclFreePackageInfo) /* 25 */ +#endif +/* Slot 26 is reserved */ +#ifndef TclGetDate +#define TclGetDate \ + (tclIntStubsPtr->tclGetDate) /* 27 */ +#endif +#ifndef TclpGetDefaultStdChannel +#define TclpGetDefaultStdChannel \ + (tclIntStubsPtr->tclpGetDefaultStdChannel) /* 28 */ +#endif +/* Slot 29 is reserved */ +/* Slot 30 is reserved */ +#ifndef TclGetExtension +#define TclGetExtension \ + (tclIntStubsPtr->tclGetExtension) /* 31 */ +#endif +#ifndef TclGetFrame +#define TclGetFrame \ + (tclIntStubsPtr->tclGetFrame) /* 32 */ +#endif +#ifndef TclGetInterpProc +#define TclGetInterpProc \ + (tclIntStubsPtr->tclGetInterpProc) /* 33 */ +#endif +#ifndef TclGetIntForIndex +#define TclGetIntForIndex \ + (tclIntStubsPtr->tclGetIntForIndex) /* 34 */ +#endif +/* Slot 35 is reserved */ +#ifndef TclGetLong +#define TclGetLong \ + (tclIntStubsPtr->tclGetLong) /* 36 */ +#endif +#ifndef TclGetLoadedPackages +#define TclGetLoadedPackages \ + (tclIntStubsPtr->tclGetLoadedPackages) /* 37 */ +#endif +#ifndef TclGetNamespaceForQualName +#define TclGetNamespaceForQualName \ + (tclIntStubsPtr->tclGetNamespaceForQualName) /* 38 */ +#endif +#ifndef TclGetObjInterpProc +#define TclGetObjInterpProc \ + (tclIntStubsPtr->tclGetObjInterpProc) /* 39 */ +#endif +#ifndef TclGetOpenMode +#define TclGetOpenMode \ + (tclIntStubsPtr->tclGetOpenMode) /* 40 */ +#endif +#ifndef TclGetOriginalCommand +#define TclGetOriginalCommand \ + (tclIntStubsPtr->tclGetOriginalCommand) /* 41 */ +#endif +#ifndef TclpGetUserHome +#define TclpGetUserHome \ + (tclIntStubsPtr->tclpGetUserHome) /* 42 */ +#endif +#ifndef TclGlobalInvoke +#define TclGlobalInvoke \ + (tclIntStubsPtr->tclGlobalInvoke) /* 43 */ +#endif +#ifndef TclGuessPackageName +#define TclGuessPackageName \ + (tclIntStubsPtr->tclGuessPackageName) /* 44 */ +#endif +#ifndef TclHideUnsafeCommands +#define TclHideUnsafeCommands \ + (tclIntStubsPtr->tclHideUnsafeCommands) /* 45 */ +#endif +#ifndef TclInExit +#define TclInExit \ + (tclIntStubsPtr->tclInExit) /* 46 */ +#endif +/* Slot 47 is reserved */ +/* Slot 48 is reserved */ +#ifndef TclIncrVar2 +#define TclIncrVar2 \ + (tclIntStubsPtr->tclIncrVar2) /* 49 */ +#endif +#ifndef TclInitCompiledLocals +#define TclInitCompiledLocals \ + (tclIntStubsPtr->tclInitCompiledLocals) /* 50 */ +#endif +#ifndef TclInterpInit +#define TclInterpInit \ + (tclIntStubsPtr->tclInterpInit) /* 51 */ +#endif +#ifndef TclInvoke +#define TclInvoke \ + (tclIntStubsPtr->tclInvoke) /* 52 */ +#endif +#ifndef TclInvokeObjectCommand +#define TclInvokeObjectCommand \ + (tclIntStubsPtr->tclInvokeObjectCommand) /* 53 */ +#endif +#ifndef TclInvokeStringCommand +#define TclInvokeStringCommand \ + (tclIntStubsPtr->tclInvokeStringCommand) /* 54 */ +#endif +#ifndef TclIsProc +#define TclIsProc \ + (tclIntStubsPtr->tclIsProc) /* 55 */ +#endif +/* Slot 56 is reserved */ +/* Slot 57 is reserved */ +#ifndef TclLookupVar +#define TclLookupVar \ + (tclIntStubsPtr->tclLookupVar) /* 58 */ +#endif +/* Slot 59 is reserved */ +#ifndef TclNeedSpace +#define TclNeedSpace \ + (tclIntStubsPtr->tclNeedSpace) /* 60 */ +#endif +#ifndef TclNewProcBodyObj +#define TclNewProcBodyObj \ + (tclIntStubsPtr->tclNewProcBodyObj) /* 61 */ +#endif +#ifndef TclObjCommandComplete +#define TclObjCommandComplete \ + (tclIntStubsPtr->tclObjCommandComplete) /* 62 */ +#endif +#ifndef TclObjInterpProc +#define TclObjInterpProc \ + (tclIntStubsPtr->tclObjInterpProc) /* 63 */ +#endif +#ifndef TclObjInvoke +#define TclObjInvoke \ + (tclIntStubsPtr->tclObjInvoke) /* 64 */ +#endif +#ifndef TclObjInvokeGlobal +#define TclObjInvokeGlobal \ + (tclIntStubsPtr->tclObjInvokeGlobal) /* 65 */ +#endif +#ifndef TclOpenFileChannelDeleteProc +#define TclOpenFileChannelDeleteProc \ + (tclIntStubsPtr->tclOpenFileChannelDeleteProc) /* 66 */ +#endif +#ifndef TclOpenFileChannelInsertProc +#define TclOpenFileChannelInsertProc \ + (tclIntStubsPtr->tclOpenFileChannelInsertProc) /* 67 */ +#endif +/* Slot 68 is reserved */ +#ifndef TclpAlloc +#define TclpAlloc \ + (tclIntStubsPtr->tclpAlloc) /* 69 */ +#endif +/* Slot 70 is reserved */ +/* Slot 71 is reserved */ +/* Slot 72 is reserved */ +/* Slot 73 is reserved */ +#ifndef TclpFree +#define TclpFree \ + (tclIntStubsPtr->tclpFree) /* 74 */ +#endif +#ifndef TclpGetClicks +#define TclpGetClicks \ + (tclIntStubsPtr->tclpGetClicks) /* 75 */ +#endif +#ifndef TclpGetSeconds +#define TclpGetSeconds \ + (tclIntStubsPtr->tclpGetSeconds) /* 76 */ +#endif +#ifndef TclpGetTime +#define TclpGetTime \ + (tclIntStubsPtr->tclpGetTime) /* 77 */ +#endif +#ifndef TclpGetTimeZone +#define TclpGetTimeZone \ + (tclIntStubsPtr->tclpGetTimeZone) /* 78 */ +#endif +/* Slot 79 is reserved */ +/* Slot 80 is reserved */ +#ifndef TclpRealloc +#define TclpRealloc \ + (tclIntStubsPtr->tclpRealloc) /* 81 */ +#endif +/* Slot 82 is reserved */ +/* Slot 83 is reserved */ +/* Slot 84 is reserved */ +/* Slot 85 is reserved */ +/* Slot 86 is reserved */ +/* Slot 87 is reserved */ +#ifndef TclPrecTraceProc +#define TclPrecTraceProc \ + (tclIntStubsPtr->tclPrecTraceProc) /* 88 */ +#endif +#ifndef TclPreventAliasLoop +#define TclPreventAliasLoop \ + (tclIntStubsPtr->tclPreventAliasLoop) /* 89 */ +#endif +/* Slot 90 is reserved */ +#ifndef TclProcCleanupProc +#define TclProcCleanupProc \ + (tclIntStubsPtr->tclProcCleanupProc) /* 91 */ +#endif +#ifndef TclProcCompileProc +#define TclProcCompileProc \ + (tclIntStubsPtr->tclProcCompileProc) /* 92 */ +#endif +#ifndef TclProcDeleteProc +#define TclProcDeleteProc \ + (tclIntStubsPtr->tclProcDeleteProc) /* 93 */ +#endif +#ifndef TclProcInterpProc +#define TclProcInterpProc \ + (tclIntStubsPtr->tclProcInterpProc) /* 94 */ +#endif +/* Slot 95 is reserved */ +#ifndef TclRenameCommand +#define TclRenameCommand \ + (tclIntStubsPtr->tclRenameCommand) /* 96 */ +#endif +#ifndef TclResetShadowedCmdRefs +#define TclResetShadowedCmdRefs \ + (tclIntStubsPtr->tclResetShadowedCmdRefs) /* 97 */ +#endif +#ifndef TclServiceIdle +#define TclServiceIdle \ + (tclIntStubsPtr->tclServiceIdle) /* 98 */ +#endif +/* Slot 99 is reserved */ +/* Slot 100 is reserved */ +#ifndef TclSetPreInitScript +#define TclSetPreInitScript \ + (tclIntStubsPtr->tclSetPreInitScript) /* 101 */ +#endif +#ifndef TclSetupEnv +#define TclSetupEnv \ + (tclIntStubsPtr->tclSetupEnv) /* 102 */ +#endif +#ifndef TclSockGetPort +#define TclSockGetPort \ + (tclIntStubsPtr->tclSockGetPort) /* 103 */ +#endif +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#ifndef TclSockMinimumBuffers +#define TclSockMinimumBuffers \ + (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */ +#endif +#endif /* UNIX */ +#ifdef __WIN32__ +#ifndef TclSockMinimumBuffers +#define TclSockMinimumBuffers \ + (tclIntStubsPtr->tclSockMinimumBuffers) /* 104 */ +#endif +#endif /* __WIN32__ */ +/* Slot 105 is reserved */ +#ifndef TclStatDeleteProc +#define TclStatDeleteProc \ + (tclIntStubsPtr->tclStatDeleteProc) /* 106 */ +#endif +#ifndef TclStatInsertProc +#define TclStatInsertProc \ + (tclIntStubsPtr->tclStatInsertProc) /* 107 */ +#endif +#ifndef TclTeardownNamespace +#define TclTeardownNamespace \ + (tclIntStubsPtr->tclTeardownNamespace) /* 108 */ +#endif +#ifndef TclUpdateReturnInfo +#define TclUpdateReturnInfo \ + (tclIntStubsPtr->tclUpdateReturnInfo) /* 109 */ +#endif +/* Slot 110 is reserved */ +#ifndef Tcl_AddInterpResolvers +#define Tcl_AddInterpResolvers \ + (tclIntStubsPtr->tcl_AddInterpResolvers) /* 111 */ +#endif +#ifndef Tcl_AppendExportList +#define Tcl_AppendExportList \ + (tclIntStubsPtr->tcl_AppendExportList) /* 112 */ +#endif +#ifndef Tcl_CreateNamespace +#define Tcl_CreateNamespace \ + (tclIntStubsPtr->tcl_CreateNamespace) /* 113 */ +#endif +#ifndef Tcl_DeleteNamespace +#define Tcl_DeleteNamespace \ + (tclIntStubsPtr->tcl_DeleteNamespace) /* 114 */ +#endif +#ifndef Tcl_Export +#define Tcl_Export \ + (tclIntStubsPtr->tcl_Export) /* 115 */ +#endif +#ifndef Tcl_FindCommand +#define Tcl_FindCommand \ + (tclIntStubsPtr->tcl_FindCommand) /* 116 */ +#endif +#ifndef Tcl_FindNamespace +#define Tcl_FindNamespace \ + (tclIntStubsPtr->tcl_FindNamespace) /* 117 */ +#endif +#ifndef Tcl_GetInterpResolvers +#define Tcl_GetInterpResolvers \ + (tclIntStubsPtr->tcl_GetInterpResolvers) /* 118 */ +#endif +#ifndef Tcl_GetNamespaceResolvers +#define Tcl_GetNamespaceResolvers \ + (tclIntStubsPtr->tcl_GetNamespaceResolvers) /* 119 */ +#endif +#ifndef Tcl_FindNamespaceVar +#define Tcl_FindNamespaceVar \ + (tclIntStubsPtr->tcl_FindNamespaceVar) /* 120 */ +#endif +#ifndef Tcl_ForgetImport +#define Tcl_ForgetImport \ + (tclIntStubsPtr->tcl_ForgetImport) /* 121 */ +#endif +#ifndef Tcl_GetCommandFromObj +#define Tcl_GetCommandFromObj \ + (tclIntStubsPtr->tcl_GetCommandFromObj) /* 122 */ +#endif +#ifndef Tcl_GetCommandFullName +#define Tcl_GetCommandFullName \ + (tclIntStubsPtr->tcl_GetCommandFullName) /* 123 */ +#endif +#ifndef Tcl_GetCurrentNamespace +#define Tcl_GetCurrentNamespace \ + (tclIntStubsPtr->tcl_GetCurrentNamespace) /* 124 */ +#endif +#ifndef Tcl_GetGlobalNamespace +#define Tcl_GetGlobalNamespace \ + (tclIntStubsPtr->tcl_GetGlobalNamespace) /* 125 */ +#endif +#ifndef Tcl_GetVariableFullName +#define Tcl_GetVariableFullName \ + (tclIntStubsPtr->tcl_GetVariableFullName) /* 126 */ +#endif +#ifndef Tcl_Import +#define Tcl_Import \ + (tclIntStubsPtr->tcl_Import) /* 127 */ +#endif +#ifndef Tcl_PopCallFrame +#define Tcl_PopCallFrame \ + (tclIntStubsPtr->tcl_PopCallFrame) /* 128 */ +#endif +#ifndef Tcl_PushCallFrame +#define Tcl_PushCallFrame \ + (tclIntStubsPtr->tcl_PushCallFrame) /* 129 */ +#endif +#ifndef Tcl_RemoveInterpResolvers +#define Tcl_RemoveInterpResolvers \ + (tclIntStubsPtr->tcl_RemoveInterpResolvers) /* 130 */ +#endif +#ifndef Tcl_SetNamespaceResolvers +#define Tcl_SetNamespaceResolvers \ + (tclIntStubsPtr->tcl_SetNamespaceResolvers) /* 131 */ +#endif +#ifndef TclpHasSockets +#define TclpHasSockets \ + (tclIntStubsPtr->tclpHasSockets) /* 132 */ +#endif +#ifndef TclpGetDate +#define TclpGetDate \ + (tclIntStubsPtr->tclpGetDate) /* 133 */ +#endif +#ifndef TclpStrftime +#define TclpStrftime \ + (tclIntStubsPtr->tclpStrftime) /* 134 */ +#endif +#ifndef TclpCheckStackSpace +#define TclpCheckStackSpace \ + (tclIntStubsPtr->tclpCheckStackSpace) /* 135 */ +#endif +/* Slot 136 is reserved */ +/* Slot 137 is reserved */ +#ifndef TclGetEnv +#define TclGetEnv \ + (tclIntStubsPtr->tclGetEnv) /* 138 */ +#endif +/* Slot 139 is reserved */ +#ifndef TclLooksLikeInt +#define TclLooksLikeInt \ + (tclIntStubsPtr->tclLooksLikeInt) /* 140 */ +#endif +#ifndef TclpGetCwd +#define TclpGetCwd \ + (tclIntStubsPtr->tclpGetCwd) /* 141 */ +#endif +#ifndef TclSetByteCodeFromAny +#define TclSetByteCodeFromAny \ + (tclIntStubsPtr->tclSetByteCodeFromAny) /* 142 */ +#endif +#ifndef TclAddLiteralObj +#define TclAddLiteralObj \ + (tclIntStubsPtr->tclAddLiteralObj) /* 143 */ +#endif +#ifndef TclHideLiteral +#define TclHideLiteral \ + (tclIntStubsPtr->tclHideLiteral) /* 144 */ +#endif +#ifndef TclGetAuxDataType +#define TclGetAuxDataType \ + (tclIntStubsPtr->tclGetAuxDataType) /* 145 */ +#endif +#ifndef TclHandleCreate +#define TclHandleCreate \ + (tclIntStubsPtr->tclHandleCreate) /* 146 */ +#endif +#ifndef TclHandleFree +#define TclHandleFree \ + (tclIntStubsPtr->tclHandleFree) /* 147 */ +#endif +#ifndef TclHandlePreserve +#define TclHandlePreserve \ + (tclIntStubsPtr->tclHandlePreserve) /* 148 */ +#endif +#ifndef TclHandleRelease +#define TclHandleRelease \ + (tclIntStubsPtr->tclHandleRelease) /* 149 */ +#endif +#ifndef TclRegAbout +#define TclRegAbout \ + (tclIntStubsPtr->tclRegAbout) /* 150 */ +#endif +#ifndef TclRegExpRangeUniChar +#define TclRegExpRangeUniChar \ + (tclIntStubsPtr->tclRegExpRangeUniChar) /* 151 */ +#endif +#ifndef TclSetLibraryPath +#define TclSetLibraryPath \ + (tclIntStubsPtr->tclSetLibraryPath) /* 152 */ +#endif +#ifndef TclGetLibraryPath +#define TclGetLibraryPath \ + (tclIntStubsPtr->tclGetLibraryPath) /* 153 */ +#endif +/* Slot 154 is reserved */ +/* Slot 155 is reserved */ +#ifndef TclRegError +#define TclRegError \ + (tclIntStubsPtr->tclRegError) /* 156 */ +#endif +#ifndef TclVarTraceExists +#define TclVarTraceExists \ + (tclIntStubsPtr->tclVarTraceExists) /* 157 */ +#endif +#ifndef TclSetStartupScriptFileName +#define TclSetStartupScriptFileName \ + (tclIntStubsPtr->tclSetStartupScriptFileName) /* 158 */ +#endif +#ifndef TclGetStartupScriptFileName +#define TclGetStartupScriptFileName \ + (tclIntStubsPtr->tclGetStartupScriptFileName) /* 159 */ +#endif +/* Slot 160 is reserved */ +#ifndef TclChannelTransform +#define TclChannelTransform \ + (tclIntStubsPtr->tclChannelTransform) /* 161 */ +#endif +#ifndef TclChannelEventScriptInvoker +#define TclChannelEventScriptInvoker \ + (tclIntStubsPtr->tclChannelEventScriptInvoker) /* 162 */ +#endif +#ifndef TclGetInstructionTable +#define TclGetInstructionTable \ + (tclIntStubsPtr->tclGetInstructionTable) /* 163 */ +#endif +#ifndef TclExpandCodeArray +#define TclExpandCodeArray \ + (tclIntStubsPtr->tclExpandCodeArray) /* 164 */ +#endif +#ifndef TclpSetInitialEncodings +#define TclpSetInitialEncodings \ + (tclIntStubsPtr->tclpSetInitialEncodings) /* 165 */ +#endif +#ifndef TclListObjSetElement +#define TclListObjSetElement \ + (tclIntStubsPtr->tclListObjSetElement) /* 166 */ +#endif +#ifndef TclSetStartupScriptPath +#define TclSetStartupScriptPath \ + (tclIntStubsPtr->tclSetStartupScriptPath) /* 167 */ +#endif +#ifndef TclGetStartupScriptPath +#define TclGetStartupScriptPath \ + (tclIntStubsPtr->tclGetStartupScriptPath) /* 168 */ +#endif +#ifndef TclpUtfNcmp2 +#define TclpUtfNcmp2 \ + (tclIntStubsPtr->tclpUtfNcmp2) /* 169 */ +#endif +#ifndef TclCheckInterpTraces +#define TclCheckInterpTraces \ + (tclIntStubsPtr->tclCheckInterpTraces) /* 170 */ +#endif +#ifndef TclCheckExecutionTraces +#define TclCheckExecutionTraces \ + (tclIntStubsPtr->tclCheckExecutionTraces) /* 171 */ +#endif +#ifndef TclInThreadExit +#define TclInThreadExit \ + (tclIntStubsPtr->tclInThreadExit) /* 172 */ +#endif +#ifndef TclUniCharMatch +#define TclUniCharMatch \ + (tclIntStubsPtr->tclUniCharMatch) /* 173 */ +#endif + +#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TCLINTDECLS */ diff --git a/Utilities/TclTk/internals/tk8.4/tkInt.h b/Utilities/TclTk/internals/tk8.4/tkInt.h new file mode 100644 index 0000000..c6b6970 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkInt.h @@ -0,0 +1,1176 @@ +/* + * tkInt.h -- + * + * Declarations for things used internally by the Tk + * procedures but not exported outside the module. + * + * Copyright (c) 1990-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1998 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: $Id: tkInt.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKINT +#define _TKINT + +#ifndef _TK +#include "tk.h" +#endif +#ifndef _TCL +#include "tcl.h" +#endif +#ifndef _TKPORT +#include +#endif + +/* + * Opaque type declarations: + */ + +typedef struct TkColormap TkColormap; +typedef struct TkGrabEvent TkGrabEvent; +typedef struct TkpCursor_ *TkpCursor; +typedef struct TkRegion_ *TkRegion; +typedef struct TkStressedCmap TkStressedCmap; +typedef struct TkBindInfo_ *TkBindInfo; + +/* + * Procedure types. + */ + +typedef int (TkBindEvalProc) _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, XEvent *eventPtr, Tk_Window tkwin, + KeySym keySym)); +typedef void (TkBindFreeProc) _ANSI_ARGS_((ClientData clientData)); + +/* + * One of the following structures is maintained for each cursor in + * use in the system. This structure is used by tkCursor.c and the + * various system specific cursor files. + */ + +typedef struct TkCursor { + Tk_Cursor cursor; /* System specific identifier for cursor. */ + Display *display; /* Display containing cursor. Needed for + * disposal and retrieval of cursors. */ + int resourceRefCount; /* Number of active uses of this cursor (each + * active use corresponds to a call to + * Tk_AllocPreserveFromObj or Tk_Preserve). + * If this count is 0, then this structure + * is no longer valid and it isn't present + * in a hash table: it is being kept around + * only because there are objects referring + * to it. The structure is freed when + * resourceRefCount and objRefCount are + * both 0. */ + int objRefCount; /* Number of Tcl objects that reference + * this structure.. */ + Tcl_HashTable *otherTable; /* Second table (other than idTable) used + * to index this entry. */ + Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure + * (needed when deleting). */ + Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure + * (needed when deleting). */ + struct TkCursor *nextPtr; /* Points to the next TkCursor structure with + * the same name. Cursors with the same + * name but different displays are chained + * together off a single hash table entry. */ +} TkCursor; + +/* + * This defines whether we should try to use XIM over-the-spot style + * input. Allow users to override it. It is a much more elegant use + * of XIM, but uses a bit more memory. + */ + +#ifndef TK_XIM_SPOT +# define TK_XIM_SPOT 1 +#endif + +/* + * The following structure is kept one-per-TkDisplay to maintain information + * about the caret (cursor location) on this display. This is used to + * dictate global focus location (Windows Accessibility guidelines) and to + * position the IME or XIM over-the-spot window. + */ + +typedef struct TkCaret { + struct TkWindow *winPtr; /* the window on which we requested caret + * placement */ + int x; /* relative x coord of the caret */ + int y; /* relative y coord of the caret */ + int height; /* specified height of the window */ +} TkCaret; + +/* + * One of the following structures is maintained for each display + * containing a window managed by Tk. In part, the structure is + * used to store thread-specific data, since each thread will have + * its own TkDisplay structure. + */ + +typedef struct TkDisplay { + Display *display; /* Xlib's info about display. */ + struct TkDisplay *nextPtr; /* Next in list of all displays. */ + char *name; /* Name of display (with any screen + * identifier removed). Malloc-ed. */ + Time lastEventTime; /* Time of last event received for this + * display. */ + + /* + * Information used primarily by tk3d.c: + */ + + int borderInit; /* 0 means borderTable needs initializing. */ + Tcl_HashTable borderTable; /* Maps from color name to TkBorder + * structure. */ + + /* + * Information used by tkAtom.c only: + */ + + int atomInit; /* 0 means stuff below hasn't been + * initialized yet. */ + Tcl_HashTable nameTable; /* Maps from names to Atom's. */ + Tcl_HashTable atomTable; /* Maps from Atom's back to names. */ + + /* + * Information used primarily by tkBind.c: + */ + + int bindInfoStale; /* Non-zero means the variables in this + * part of the structure are potentially + * incorrect and should be recomputed. */ + unsigned int modeModMask; /* Has one bit set to indicate the modifier + * corresponding to "mode shift". If no + * such modifier, than this is zero. */ + unsigned int metaModMask; /* Has one bit set to indicate the modifier + * corresponding to the "Meta" key. If no + * such modifier, then this is zero. */ + unsigned int altModMask; /* Has one bit set to indicate the modifier + * corresponding to the "Meta" key. If no + * such modifier, then this is zero. */ + enum {LU_IGNORE, LU_CAPS, LU_SHIFT} lockUsage; + /* Indicates how to interpret lock modifier. */ + int numModKeyCodes; /* Number of entries in modKeyCodes array + * below. */ + KeyCode *modKeyCodes; /* Pointer to an array giving keycodes for + * all of the keys that have modifiers + * associated with them. Malloc'ed, but + * may be NULL. */ + + /* + * Information used by tkBitmap.c only: + */ + + int bitmapInit; /* 0 means tables above need initializing. */ + int bitmapAutoNumber; /* Used to number bitmaps. */ + Tcl_HashTable bitmapNameTable; + /* Maps from name of bitmap to the first + * TkBitmap record for that name. */ + Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap + * structure for the bitmap. */ + Tcl_HashTable bitmapDataTable; + /* Used by Tk_GetBitmapFromData to map from + * a collection of in-core data about a + * bitmap to a reference giving an auto- + * matically-generated name for the bitmap. */ + + /* + * Information used by tkCanvas.c only: + */ + + int numIdSearches; + int numSlowSearches; + + /* + * Used by tkColor.c only: + */ + + int colorInit; /* 0 means color module needs initializing. */ + TkStressedCmap *stressPtr; /* First in list of colormaps that have + * filled up, so we have to pick an + * approximate color. */ + Tcl_HashTable colorNameTable; + /* Maps from color name to TkColor structure + * for that color. */ + Tcl_HashTable colorValueTable; + /* Maps from integer RGB values to TkColor + * structures. */ + + /* + * Used by tkCursor.c only: + */ + + int cursorInit; /* 0 means cursor module need initializing. */ + Tcl_HashTable cursorNameTable; + /* Maps from a string name to a cursor to the + * TkCursor record for the cursor. */ + Tcl_HashTable cursorDataTable; + /* Maps from a collection of in-core data + * about a cursor to a TkCursor structure. */ + Tcl_HashTable cursorIdTable; + /* Maps from a cursor id to the TkCursor + * structure for the cursor. */ + char cursorString[20]; /* Used to store a cursor id string. */ + Font cursorFont; /* Font to use for standard cursors. + * None means font not loaded yet. */ + + /* + * Information used by tkError.c only: + */ + + struct TkErrorHandler *errorPtr; + /* First in list of error handlers + * for this display. NULL means + * no handlers exist at present. */ + int deleteCount; /* Counts # of handlers deleted since + * last time inactive handlers were + * garbage-collected. When this number + * gets big, handlers get cleaned up. */ + + /* + * Used by tkEvent.c only: + */ + + struct TkWindowEvent *delayedMotionPtr; + /* Points to a malloc-ed motion event + * whose processing has been delayed in + * the hopes that another motion event + * will come along right away and we can + * merge the two of them together. NULL + * means that there is no delayed motion + * event. */ + + /* + * Information used by tkFocus.c only: + */ + + int focusDebug; /* 1 means collect focus debugging + * statistics. */ + struct TkWindow *implicitWinPtr; + /* If the focus arrived at a toplevel window + * implicitly via an Enter event (rather + * than via a FocusIn event), this points + * to the toplevel window. Otherwise it is + * NULL. */ + struct TkWindow *focusPtr; /* Points to the window on this display that + * should be receiving keyboard events. When + * multiple applications on the display have + * the focus, this will refer to the + * innermost window in the innermost + * application. This information isn't used + * under Unix or Windows, but it's needed on + * the Macintosh. */ + + /* + * Information used by tkGC.c only: + */ + + Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure + * describing a GC with those values. */ + Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */ + int gcInit; /* 0 means the tables below need + * initializing. */ + + /* + * Information used by tkGeometry.c only: + */ + + Tcl_HashTable maintainHashTable; + /* Hash table that maps from a master's + * Tk_Window token to a list of slaves + * managed by that master. */ + int geomInit; + + /* + * Information used by tkGet.c only: + */ + + Tcl_HashTable uidTable; /* Stores all Tk_Uid used in a thread. */ + int uidInit; /* 0 means uidTable needs initializing. */ + + /* + * Information used by tkGrab.c only: + */ + + struct TkWindow *grabWinPtr; + /* Window in which the pointer is currently + * grabbed, or NULL if none. */ + struct TkWindow *eventualGrabWinPtr; + /* Value that grabWinPtr will have once the + * grab event queue (below) has been + * completely emptied. */ + struct TkWindow *buttonWinPtr; + /* Window in which first mouse button was + * pressed while grab was in effect, or NULL + * if no such press in effect. */ + struct TkWindow *serverWinPtr; + /* If no application contains the pointer then + * this is NULL. Otherwise it contains the + * last window for which we've gotten an + * Enter or Leave event from the server (i.e. + * the last window known to have contained + * the pointer). Doesn't reflect events + * that were synthesized in tkGrab.c. */ + TkGrabEvent *firstGrabEventPtr; + /* First in list of enter/leave events + * synthesized by grab code. These events + * must be processed in order before any other + * events are processed. NULL means no such + * events. */ + TkGrabEvent *lastGrabEventPtr; + /* Last in list of synthesized events, or NULL + * if list is empty. */ + int grabFlags; /* Miscellaneous flag values. See definitions + * in tkGrab.c. */ + + /* + * Information used by tkGrid.c only: + */ + + int gridInit; /* 0 means table below needs initializing. */ + Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to + * corresponding Grid structures. */ + + /* + * Information used by tkImage.c only: + */ + + int imageId; /* Value used to number image ids. */ + + /* + * Information used by tkMacWinMenu.c only: + */ + + int postCommandGeneration; + + /* + * Information used by tkOption.c only. + */ + + + + /* + * Information used by tkPack.c only. + */ + + int packInit; /* 0 means table below needs initializing. */ + Tcl_HashTable packerHashTable; + /* Maps from Tk_Window tokens to + * corresponding Packer structures. */ + + + /* + * Information used by tkPlace.c only. + */ + + int placeInit; /* 0 means tables below need initializing. */ + Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master + * structure for the window, if it exists. */ + Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave + * structure for the window, if it exists. */ + + /* + * Information used by tkSelect.c and tkClipboard.c only: + */ + + struct TkSelectionInfo *selectionInfoPtr; + /* First in list of selection information + * records. Each entry contains information + * about the current owner of a particular + * selection on this display. */ + Atom multipleAtom; /* Atom for MULTIPLE. None means + * selection stuff isn't initialized. */ + Atom incrAtom; /* Atom for INCR. */ + Atom targetsAtom; /* Atom for TARGETS. */ + Atom timestampAtom; /* Atom for TIMESTAMP. */ + Atom textAtom; /* Atom for TEXT. */ + Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */ + Atom applicationAtom; /* Atom for TK_APPLICATION. */ + Atom windowAtom; /* Atom for TK_WINDOW. */ + Atom clipboardAtom; /* Atom for CLIPBOARD. */ + Atom utf8Atom; /* Atom for UTF8_STRING. */ + + Tk_Window clipWindow; /* Window used for clipboard ownership and to + * retrieve selections between processes. NULL + * means clipboard info hasn't been + * initialized. */ + int clipboardActive; /* 1 means we currently own the clipboard + * selection, 0 means we don't. */ + struct TkMainInfo *clipboardAppPtr; + /* Last application that owned clipboard. */ + struct TkClipboardTarget *clipTargetPtr; + /* First in list of clipboard type information + * records. Each entry contains information + * about the buffers for a given selection + * target. */ + + /* + * Information used by tkSend.c only: + */ + + Tk_Window commTkwin; /* Window used for communication + * between interpreters during "send" + * commands. NULL means send info hasn't + * been initialized yet. */ + Atom commProperty; /* X's name for comm property. */ + Atom registryProperty; /* X's name for property containing + * registry of interpreter names. */ + Atom appNameProperty; /* X's name for property used to hold the + * application name on each comm window. */ + + /* + * Information used by tkXId.c only: + */ + + struct TkIdStack *idStackPtr; + /* First in list of chunks of free resource + * identifiers, or NULL if there are no free + * resources. */ + XID (*defaultAllocProc) _ANSI_ARGS_((Display *display)); + /* Default resource allocator for display. */ + struct TkIdStack *windowStackPtr; + /* First in list of chunks of window + * identifers that can't be reused right + * now. */ + Tcl_TimerToken idCleanupScheduled; + /* If set, it means a call to WindowIdCleanup + * has already been scheduled, 0 means it + * hasn't. */ + + /* + * Information used by tkUnixWm.c and tkWinWm.c only: + */ + + struct TkWmInfo *firstWmPtr; /* Points to first top-level window. */ + struct TkWmInfo *foregroundWmPtr; + /* Points to the foreground window. */ + + /* + * Information maintained by tkWindow.c for use later on by tkXId.c: + */ + + + int destroyCount; /* Number of Tk_DestroyWindow operations + * in progress. */ + unsigned long lastDestroyRequest; + /* Id of most recent XDestroyWindow request; + * can re-use ids in windowStackPtr when + * server has seen this request and event + * queue is empty. */ + + /* + * Information used by tkVisual.c only: + */ + + TkColormap *cmapPtr; /* First in list of all non-default colormaps + * allocated for this display. */ + + /* + * Miscellaneous information: + */ + +#ifdef TK_USE_INPUT_METHODS + XIM inputMethod; /* Input method for this display */ +#if TK_XIM_SPOT + XFontSet inputXfs; /* XFontSet cached for over-the-spot XIM. */ +#endif +#endif /* TK_USE_INPUT_METHODS */ + Tcl_HashTable winTable; /* Maps from X window ids to TkWindow ptrs. */ + + int refCount; /* Reference count of how many Tk applications + * are using this display. Used to clean up + * the display when we no longer have any + * Tk applications using it. + */ + /* + * The following field were all added for Tk8.3 + */ + int mouseButtonState; /* current mouse button state for this + * display */ + Window mouseButtonWindow; /* Window the button state was set in, + * added in Tk 8.4. */ + Window warpWindow; + int warpX; + int warpY; + + /* + * The following field(s) were all added for Tk8.4 + */ + unsigned int flags; /* Various flag values: these are all + * defined in below. */ + TkCaret caret; /* information about the caret for this + * display. This is not a pointer. */ +} TkDisplay; + +/* + * Flag values for TkDisplay flags. + * TK_DISPLAY_COLLAPSE_MOTION_EVENTS: (default on) + * Indicates that we should collapse motion events on this display + * TK_DISPLAY_USE_IM: (default on, set via tk.tcl) + * Whether to use input methods for this display + * TK_DISPLAY_XIM_SPOT: (default off) + * Indicates that we should use over-the-spot XIM on this display + * TK_DISPLAY_WM_TRACING: (default off) + * Whether we should do wm tracing on this display. + * TK_DISPLAY_IN_WARP: (default off) + * Indicates that we are in a pointer warp + */ + +#define TK_DISPLAY_COLLAPSE_MOTION_EVENTS (1 << 0) +#define TK_DISPLAY_USE_IM (1 << 1) +#define TK_DISPLAY_XIM_SPOT (1 << 2) +#define TK_DISPLAY_WM_TRACING (1 << 3) +#define TK_DISPLAY_IN_WARP (1 << 4) + +/* + * One of the following structures exists for each error handler + * created by a call to Tk_CreateErrorHandler. The structure + * is managed by tkError.c. + */ + +typedef struct TkErrorHandler { + TkDisplay *dispPtr; /* Display to which handler applies. */ + unsigned long firstRequest; /* Only errors with serial numbers + * >= to this are considered. */ + unsigned long lastRequest; /* Only errors with serial numbers + * <= to this are considered. This + * field is filled in when XUnhandle + * is called. -1 means XUnhandle + * hasn't been called yet. */ + int error; /* Consider only errors with this + * error_code (-1 means consider + * all errors). */ + int request; /* Consider only errors with this + * major request code (-1 means + * consider all major codes). */ + int minorCode; /* Consider only errors with this + * minor request code (-1 means + * consider all minor codes). */ + Tk_ErrorProc *errorProc; /* Procedure to invoke when a matching + * error occurs. NULL means just ignore + * errors. */ + ClientData clientData; /* Arbitrary value to pass to + * errorProc. */ + struct TkErrorHandler *nextPtr; + /* Pointer to next older handler for + * this display, or NULL for end of + * list. */ +} TkErrorHandler; + + +/* + * One of the following structures exists for each event handler + * created by calling Tk_CreateEventHandler. This information + * is used by tkEvent.c only. + */ + +typedef struct TkEventHandler { + unsigned long mask; /* Events for which to invoke + * proc. */ + Tk_EventProc *proc; /* Procedure to invoke when an event + * in mask occurs. */ + ClientData clientData; /* Argument to pass to proc. */ + struct TkEventHandler *nextPtr; + /* Next in list of handlers + * associated with window (NULL means + * end of list). */ +} TkEventHandler; + +/* + * Tk keeps one of the following data structures for each main + * window (created by a call to TkCreateMainWindow). It stores + * information that is shared by all of the windows associated + * with a particular main window. + */ + +typedef struct TkMainInfo { + int refCount; /* Number of windows whose "mainPtr" fields + * point here. When this becomes zero, can + * free up the structure (the reference + * count is zero because windows can get + * deleted in almost any order; the main + * window isn't necessarily the last one + * deleted). */ + struct TkWindow *winPtr; /* Pointer to main window. */ + Tcl_Interp *interp; /* Interpreter associated with application. */ + Tcl_HashTable nameTable; /* Hash table mapping path names to TkWindow + * structs for all windows related to this + * main window. Managed by tkWindow.c. */ + long deletionEpoch; /* Incremented by window deletions */ + Tk_BindingTable bindingTable; + /* Used in conjunction with "bind" command + * to bind events to Tcl commands. */ + TkBindInfo bindInfo; /* Information used by tkBind.c on a per + * application basis. */ + struct TkFontInfo *fontInfoPtr; + /* Information used by tkFont.c on a per + * application basis. */ + + /* + * Information used only by tkFocus.c and tk*Embed.c: + */ + + struct TkToplevelFocusInfo *tlFocusPtr; + /* First in list of records containing focus + * information for each top-level in the + * application. Used only by tkFocus.c. */ + struct TkDisplayFocusInfo *displayFocusPtr; + /* First in list of records containing focus + * information for each display that this + * application has ever used. Used only + * by tkFocus.c. */ + + struct ElArray *optionRootPtr; + /* Top level of option hierarchy for this + * main window. NULL means uninitialized. + * Managed by tkOption.c. */ + Tcl_HashTable imageTable; /* Maps from image names to Tk_ImageMaster + * structures. Managed by tkImage.c. */ + int strictMotif; /* This is linked to the tk_strictMotif + * global variable. */ + struct TkMainInfo *nextPtr; /* Next in list of all main windows managed by + * this process. */ +} TkMainInfo; + +/* + * Tk keeps the following data structure for each of it's builtin + * bitmaps. This structure is only used by tkBitmap.c and other + * platform specific bitmap files. + */ + +typedef struct { + CONST char *source; /* Bits for bitmap. */ + int width, height; /* Dimensions of bitmap. */ + int native; /* 0 means generic (X style) bitmap, + * 1 means native style bitmap. */ +} TkPredefBitmap; + +/* + * Tk keeps one of the following structures for each window. + * Some of the information (like size and location) is a shadow + * of information managed by the X server, and some is special + * information used here, such as event and geometry management + * information. This information is (mostly) managed by tkWindow.c. + * WARNING: the declaration below must be kept consistent with the + * Tk_FakeWin structure in tk.h. If you change one, be sure to + * change the other!! + */ + +typedef struct TkWindow { + + /* + * Structural information: + */ + + Display *display; /* Display containing window. */ + TkDisplay *dispPtr; /* Tk's information about display + * for window. */ + int screenNum; /* Index of screen for window, among all + * those for dispPtr. */ + Visual *visual; /* Visual to use for window. If not default, + * MUST be set before X window is created. */ + int depth; /* Number of bits/pixel. */ + Window window; /* X's id for window. NULL means window + * hasn't actually been created yet, or it's + * been deleted. */ + struct TkWindow *childList; /* First in list of child windows, + * or NULL if no children. List is in + * stacking order, lowest window first.*/ + struct TkWindow *lastChildPtr; + /* Last in list of child windows (highest + * in stacking order), or NULL if no + * children. */ + struct TkWindow *parentPtr; /* Pointer to parent window (logical + * parent, not necessarily X parent). NULL + * means either this is the main window, or + * the window's parent has already been + * deleted. */ + struct TkWindow *nextPtr; /* Next higher sibling (in stacking order) + * in list of children with same parent. NULL + * means end of list. */ + TkMainInfo *mainPtr; /* Information shared by all windows + * associated with a particular main + * window. NULL means this window is + * a rogue that isn't associated with + * any application (at present, this + * only happens for the dummy windows + * used for "send" communication). */ + + /* + * Name and type information for the window: + */ + + char *pathName; /* Path name of window (concatenation + * of all names between this window and + * its top-level ancestor). This is a + * pointer into an entry in + * mainPtr->nameTable. NULL means that + * the window hasn't been completely + * created yet. */ + Tk_Uid nameUid; /* Name of the window within its parent + * (unique within the parent). */ + Tk_Uid classUid; /* Class of the window. NULL means window + * hasn't been given a class yet. */ + + /* + * Geometry and other attributes of window. This information + * may not be updated on the server immediately; stuff that + * hasn't been reflected in the server yet is called "dirty". + * At present, information can be dirty only if the window + * hasn't yet been created. + */ + + XWindowChanges changes; /* Geometry and other info about + * window. */ + unsigned int dirtyChanges; /* Bits indicate fields of "changes" + * that are dirty. */ + XSetWindowAttributes atts; /* Current attributes of window. */ + unsigned long dirtyAtts; /* Bits indicate fields of "atts" + * that are dirty. */ + + unsigned int flags; /* Various flag values: these are all + * defined in tk.h (confusing, but they're + * needed there for some query macros). */ + + /* + * Information kept by the event manager (tkEvent.c): + */ + + TkEventHandler *handlerList;/* First in list of event handlers + * declared for this window, or + * NULL if none. */ +#ifdef TK_USE_INPUT_METHODS + XIC inputContext; /* XIM input context. */ +#endif /* TK_USE_INPUT_METHODS */ + + /* + * Information used for event bindings (see "bind" and "bindtags" + * commands in tkCmds.c): + */ + + ClientData *tagPtr; /* Points to array of tags used for bindings + * on this window. Each tag is a Tk_Uid. + * Malloc'ed. NULL means no tags. */ + int numTags; /* Number of tags at *tagPtr. */ + + /* + * Information used by tkOption.c to manage options for the + * window. + */ + + int optionLevel; /* -1 means no option information is + * currently cached for this window. + * Otherwise this gives the level in + * the option stack at which info is + * cached. */ + /* + * Information used by tkSelect.c to manage the selection. + */ + + struct TkSelHandler *selHandlerList; + /* First in list of handlers for + * returning the selection in various + * forms. */ + + /* + * Information used by tkGeometry.c for geometry management. + */ + + Tk_GeomMgr *geomMgrPtr; /* Information about geometry manager for + * this window. */ + ClientData geomData; /* Argument for geometry manager procedures. */ + int reqWidth, reqHeight; /* Arguments from last call to + * Tk_GeometryRequest, or 0's if + * Tk_GeometryRequest hasn't been + * called. */ + int internalBorderLeft; /* Width of internal border of window + * (0 means no internal border). Geometry + * managers should not normally place children + * on top of the border. + * Fields for the other three sides are found + * below. */ + + /* + * Information maintained by tkWm.c for window manager communication. + */ + + struct TkWmInfo *wmInfoPtr; /* For top-level windows (and also + * for special Unix menubar and wrapper + * windows), points to structure with + * wm-related info (see tkWm.c). For + * other windows, this is NULL. */ + + /* + * Information used by widget classes. + */ + + Tk_ClassProcs *classProcsPtr; + ClientData instanceData; + + /* + * Platform specific information private to each port. + */ + + struct TkWindowPrivate *privatePtr; + + /* + * More information used by tkGeometry.c for geometry management. + */ + + /* The remaining fields of internal border. */ + int internalBorderRight; + int internalBorderTop; + int internalBorderBottom; + + int minReqWidth; /* Minimum requested width. */ + int minReqHeight; /* Minimum requested height. */ +} TkWindow; + +/* + * The following structure is used as a two way map between integers + * and strings, usually to map between an internal C representation + * and the strings used in Tcl. + */ + +typedef struct TkStateMap { + int numKey; /* Integer representation of a value. */ + char *strKey; /* String representation of a value. */ +} TkStateMap; + +/* + * This structure is used by the Mac and Window porting layers as + * the internal representation of a clip_mask in a GC. + */ + +typedef struct TkpClipMask { + int type; /* One of TKP_CLIP_PIXMAP or TKP_CLIP_REGION */ + union { + Pixmap pixmap; + TkRegion region; + } value; +} TkpClipMask; + +#define TKP_CLIP_PIXMAP 0 +#define TKP_CLIP_REGION 1 + +/* + * Pointer to first entry in list of all displays currently known. + */ + +extern TkDisplay *tkDisplayList; + +/* + * Return values from TkGrabState: + */ + +#define TK_GRAB_NONE 0 +#define TK_GRAB_IN_TREE 1 +#define TK_GRAB_ANCESTOR 2 +#define TK_GRAB_EXCLUDED 3 + +/* + * The macro below is used to modify a "char" value (e.g. by casting + * it to an unsigned character) so that it can be used safely with + * macros such as isspace. + */ + +#define UCHAR(c) ((unsigned char) (c)) + +/* + * The following symbol is used in the mode field of FocusIn events + * generated by an embedded application to request the input focus from + * its container. + */ + +#define EMBEDDED_APP_WANTS_FOCUS (NotifyNormal + 20) + +/* + * The following special modifier mask bits are defined, to indicate + * logical modifiers such as Meta and Alt that may float among the + * actual modifier bits. + */ + +#define META_MASK (AnyModifier<<1) +#define ALT_MASK (AnyModifier<<2) + +/* + * Object types not declared in tkObj.c need to be mentioned here so + * they can be properly registered with Tcl: + */ + +extern Tcl_ObjType tkBorderObjType; +extern Tcl_ObjType tkBitmapObjType; +extern Tcl_ObjType tkColorObjType; +extern Tcl_ObjType tkCursorObjType; +extern Tcl_ObjType tkFontObjType; +extern Tcl_ObjType tkOptionObjType; +extern Tcl_ObjType tkStateKeyObjType; + +/* + * Miscellaneous variables shared among Tk modules but not exported + * to the outside world: + */ + +extern Tk_SmoothMethod tkBezierSmoothMethod; +extern Tk_ImageType tkBitmapImageType; +extern Tk_PhotoImageFormat tkImgFmtGIF; +extern void (*tkHandleEventProc) _ANSI_ARGS_(( + XEvent* eventPtr)); +extern Tk_PhotoImageFormat tkImgFmtPPM; +extern TkMainInfo *tkMainWindowList; +extern Tk_ImageType tkPhotoImageType; +extern Tcl_HashTable tkPredefBitmapTable; +extern int tkSendSerial; + +#include "tkIntDecls.h" + +#ifdef BUILD_tk +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * Internal procedures shared among Tk modules but not exported + * to the outside world: + */ + +EXTERN int Tk_BellObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_BindObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_BindtagsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ButtonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_CanvasObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_CheckbuttonObjCmd _ANSI_ARGS_(( + ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ClipboardObjCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_ChooseColorObjCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_ChooseDirectoryObjCmd _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[])); +EXTERN int Tk_ChooseFontObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_DestroyObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_EntryObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_EventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FileeventCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, char **argv)); +EXTERN int Tk_FrameObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FocusObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_FontObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GetOpenFileObjCmd _ANSI_ARGS_(( + ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GetSaveFileObjCmd _ANSI_ARGS_(( + ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GrabObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_GridObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ImageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_LabelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_LabelframeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ListboxObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_LowerObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MenubuttonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MessageBoxObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_MessageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_PanedWindowObjCmd _ANSI_ARGS_(( + ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_OptionObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_PackObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_PlaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_RadiobuttonObjCmd _ANSI_ARGS_(( + ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_RaiseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ScaleObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ScrollbarCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, CONST char **argv)); +EXTERN int Tk_SelectionObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_SendCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, CONST char **argv)); +EXTERN int Tk_SendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_SpinboxObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_TextCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, CONST char **argv)); +EXTERN int Tk_TkObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_TkwaitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_ToplevelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_WinfoObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +EXTERN int Tk_WmObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); + +EXTERN void TkConsolePrint _ANSI_ARGS_((Tcl_Interp *interp, + int devId, CONST char *buffer, long size)); + +EXTERN void TkEventInit _ANSI_ARGS_((void)); + +EXTERN void TkRegisterObjTypes _ANSI_ARGS_((void)); + +EXTERN int TkCreateMenuCmd _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, CONST char **argv)); + +EXTERN int TkpTestembedCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, CONST char **argv)); +EXTERN int TkCanvasGetCoordObj _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Canvas canvas, Tcl_Obj *obj, + double *doublePtr)); +EXTERN int TkCanvasDashParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkCanvasDashPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkGetDoublePixels _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Window tkwin, CONST char *string, + double *doublePtr)); +EXTERN int TkOffsetParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkOffsetPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkOrientParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, + char *widgRec, int offset)); +EXTERN char * TkOrientPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkPixelParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkPixelPrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkPostscriptImage _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Window tkwin, Tk_PostscriptInfo psInfo, + XImage *ximage, int x, int y, int width, + int height)); +EXTERN int TkSmoothParseProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *recordPtr, int offset)); +EXTERN char * TkSmoothPrintProc _ANSI_ARGS_((ClientData clientData, + Tk_Window tkwin, char *recordPtr, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkStateParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, + char *widgRec, int offset)); +EXTERN char * TkStatePrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); +EXTERN int TkTileParseProc _ANSI_ARGS_(( + ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, CONST char *value, char *widgRec, + int offset)); +EXTERN char * TkTilePrintProc _ANSI_ARGS_(( + ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr)); + +/* + * Unsupported commands. + */ +EXTERN int TkUnsupported1Cmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int argc, CONST char **argv)); + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkIntDecls.h b/Utilities/TclTk/internals/tk8.4/tkIntDecls.h new file mode 100644 index 0000000..adcd26d --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkIntDecls.h @@ -0,0 +1,1563 @@ +/* + * tkIntDecls.h -- + * + * This file contains the declarations for all unsupported + * functions that are exported by the Tk library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkIntDecls.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKINTDECLS +#define _TKINTDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tkInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +/* 0 */ +EXTERN TkWindow * TkAllocWindow _ANSI_ARGS_((TkDisplay * dispPtr, + int screenNum, TkWindow * parentPtr)); +/* 1 */ +EXTERN void TkBezierPoints _ANSI_ARGS_((double control[], + int numSteps, double * coordPtr)); +/* 2 */ +EXTERN void TkBezierScreenPoints _ANSI_ARGS_((Tk_Canvas canvas, + double control[], int numSteps, + XPoint * xPointPtr)); +/* 3 */ +EXTERN void TkBindDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 4 */ +EXTERN void TkBindEventProc _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 5 */ +EXTERN void TkBindFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 6 */ +EXTERN void TkBindInit _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 7 */ +EXTERN void TkChangeEventWindow _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * winPtr)); +/* 8 */ +EXTERN int TkClipInit _ANSI_ARGS_((Tcl_Interp * interp, + TkDisplay * dispPtr)); +/* 9 */ +EXTERN void TkComputeAnchor _ANSI_ARGS_((Tk_Anchor anchor, + Tk_Window tkwin, int padX, int padY, + int innerWidth, int innerHeight, int * xPtr, + int * yPtr)); +/* 10 */ +EXTERN int TkCopyAndGlobalEval _ANSI_ARGS_((Tcl_Interp * interp, + char * script)); +/* 11 */ +EXTERN unsigned long TkCreateBindingProcedure _ANSI_ARGS_(( + Tcl_Interp * interp, + Tk_BindingTable bindingTable, + ClientData object, CONST char * eventString, + TkBindEvalProc * evalProc, + TkBindFreeProc * freeProc, + ClientData clientData)); +/* 12 */ +EXTERN TkCursor * TkCreateCursorFromData _ANSI_ARGS_((Tk_Window tkwin, + CONST char * source, CONST char * mask, + int width, int height, int xHot, int yHot, + XColor fg, XColor bg)); +/* 13 */ +EXTERN int TkCreateFrame _ANSI_ARGS_((ClientData clientData, + Tcl_Interp * interp, int argc, char ** argv, + int toplevel, char * appName)); +/* 14 */ +EXTERN Tk_Window TkCreateMainWindow _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * screenName, char * baseName)); +/* 15 */ +EXTERN Time TkCurrentTime _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 16 */ +EXTERN void TkDeleteAllImages _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 17 */ +EXTERN void TkDoConfigureNotify _ANSI_ARGS_((TkWindow * winPtr)); +/* 18 */ +EXTERN void TkDrawInsetFocusHighlight _ANSI_ARGS_(( + Tk_Window tkwin, GC gc, int width, + Drawable drawable, int padding)); +/* 19 */ +EXTERN void TkEventDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 20 */ +EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas, + double * coordPtr, int numPoints, + Display * display, Drawable drawable, GC gc, + GC outlineGC)); +/* 21 */ +EXTERN int TkFindStateNum _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * option, + CONST TkStateMap * mapPtr, + CONST char * strKey)); +/* 22 */ +EXTERN char * TkFindStateString _ANSI_ARGS_(( + CONST TkStateMap * mapPtr, int numKey)); +/* 23 */ +EXTERN void TkFocusDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 24 */ +EXTERN int TkFocusFilterEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 25 */ +EXTERN TkWindow * TkFocusKeyEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 26 */ +EXTERN void TkFontPkgInit _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 27 */ +EXTERN void TkFontPkgFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 28 */ +EXTERN void TkFreeBindingTags _ANSI_ARGS_((TkWindow * winPtr)); +/* 29 */ +EXTERN void TkpFreeCursor _ANSI_ARGS_((TkCursor * cursorPtr)); +/* 30 */ +EXTERN char * TkGetBitmapData _ANSI_ARGS_((Tcl_Interp * interp, + char * string, char * fileName, + int * widthPtr, int * heightPtr, + int * hotXPtr, int * hotYPtr)); +/* 31 */ +EXTERN void TkGetButtPoints _ANSI_ARGS_((double p1[], + double p2[], double width, int project, + double m1[], double m2[])); +/* 32 */ +EXTERN TkCursor * TkGetCursorByName _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, Tk_Uid string)); +/* 33 */ +EXTERN CONST84_RETURN char * TkGetDefaultScreenName _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * screenName)); +/* 34 */ +EXTERN TkDisplay * TkGetDisplay _ANSI_ARGS_((Display * display)); +/* 35 */ +EXTERN int TkGetDisplayOf _ANSI_ARGS_((Tcl_Interp * interp, + int objc, Tcl_Obj *CONST objv[], + Tk_Window * tkwinPtr)); +/* 36 */ +EXTERN TkWindow * TkGetFocusWin _ANSI_ARGS_((TkWindow * winPtr)); +/* 37 */ +EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin)); +/* 38 */ +EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[], + double p2[], double p3[], double width, + double m1[], double m2[])); +/* 39 */ +EXTERN void TkGetPointerCoords _ANSI_ARGS_((Tk_Window tkwin, + int * xPtr, int * yPtr)); +/* 40 */ +EXTERN void TkGetServerInfo _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin)); +/* 41 */ +EXTERN void TkGrabDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 42 */ +EXTERN int TkGrabState _ANSI_ARGS_((TkWindow * winPtr)); +/* 43 */ +EXTERN void TkIncludePoint _ANSI_ARGS_((Tk_Item * itemPtr, + double * pointPtr)); +/* 44 */ +EXTERN void TkInOutEvents _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * sourcePtr, TkWindow * destPtr, + int leaveType, int enterType, + Tcl_QueuePosition position)); +/* 45 */ +EXTERN void TkInstallFrameMenu _ANSI_ARGS_((Tk_Window tkwin)); +/* 46 */ +EXTERN char * TkKeysymToString _ANSI_ARGS_((KeySym keysym)); +/* 47 */ +EXTERN int TkLineToArea _ANSI_ARGS_((double end1Ptr[], + double end2Ptr[], double rectPtr[])); +/* 48 */ +EXTERN double TkLineToPoint _ANSI_ARGS_((double end1Ptr[], + double end2Ptr[], double pointPtr[])); +/* 49 */ +EXTERN int TkMakeBezierCurve _ANSI_ARGS_((Tk_Canvas canvas, + double * pointPtr, int numPoints, + int numSteps, XPoint xPoints[], + double dblPoints[])); +/* 50 */ +EXTERN void TkMakeBezierPostscript _ANSI_ARGS_(( + Tcl_Interp * interp, Tk_Canvas canvas, + double * pointPtr, int numPoints)); +/* 51 */ +EXTERN void TkOptionClassChanged _ANSI_ARGS_((TkWindow * winPtr)); +/* 52 */ +EXTERN void TkOptionDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 53 */ +EXTERN int TkOvalToArea _ANSI_ARGS_((double * ovalPtr, + double * rectPtr)); +/* 54 */ +EXTERN double TkOvalToPoint _ANSI_ARGS_((double ovalPtr[], + double width, int filled, double pointPtr[])); +/* 55 */ +EXTERN int TkpChangeFocus _ANSI_ARGS_((TkWindow * winPtr, + int force)); +/* 56 */ +EXTERN void TkpCloseDisplay _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 57 */ +EXTERN void TkpClaimFocus _ANSI_ARGS_((TkWindow * topLevelPtr, + int force)); +/* 58 */ +EXTERN void TkpDisplayWarning _ANSI_ARGS_((CONST char * msg, + CONST char * title)); +/* 59 */ +EXTERN void TkpGetAppName _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_DString * name)); +/* 60 */ +EXTERN TkWindow * TkpGetOtherWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 61 */ +EXTERN TkWindow * TkpGetWrapperWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 62 */ +EXTERN int TkpInit _ANSI_ARGS_((Tcl_Interp * interp)); +/* 63 */ +EXTERN void TkpInitializeMenuBindings _ANSI_ARGS_(( + Tcl_Interp * interp, + Tk_BindingTable bindingTable)); +/* 64 */ +EXTERN void TkpMakeContainer _ANSI_ARGS_((Tk_Window tkwin)); +/* 65 */ +EXTERN void TkpMakeMenuWindow _ANSI_ARGS_((Tk_Window tkwin, + int transient)); +/* 66 */ +EXTERN Window TkpMakeWindow _ANSI_ARGS_((TkWindow * winPtr, + Window parent)); +/* 67 */ +EXTERN void TkpMenuNotifyToplevelCreate _ANSI_ARGS_(( + Tcl_Interp * interp1, char * menuName)); +/* 68 */ +EXTERN TkDisplay * TkpOpenDisplay _ANSI_ARGS_(( + CONST char * display_name)); +/* 69 */ +EXTERN int TkPointerEvent _ANSI_ARGS_((XEvent * eventPtr, + TkWindow * winPtr)); +/* 70 */ +EXTERN int TkPolygonToArea _ANSI_ARGS_((double * polyPtr, + int numPoints, double * rectPtr)); +/* 71 */ +EXTERN double TkPolygonToPoint _ANSI_ARGS_((double * polyPtr, + int numPoints, double * pointPtr)); +/* 72 */ +EXTERN int TkPositionInTree _ANSI_ARGS_((TkWindow * winPtr, + TkWindow * treePtr)); +/* 73 */ +EXTERN void TkpRedirectKeyEvent _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr)); +/* 74 */ +EXTERN void TkpSetMainMenubar _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * menuName)); +/* 75 */ +EXTERN int TkpUseWindow _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, CONST char * string)); +/* 76 */ +EXTERN int TkpWindowWasRecentlyDeleted _ANSI_ARGS_((Window win, + TkDisplay * dispPtr)); +/* 77 */ +EXTERN void TkQueueEventForAllChildren _ANSI_ARGS_(( + TkWindow * winPtr, XEvent * eventPtr)); +/* 78 */ +EXTERN int TkReadBitmapFile _ANSI_ARGS_((Display* display, + Drawable d, CONST char* filename, + unsigned int* width_return, + unsigned int* height_return, + Pixmap* bitmap_return, int* x_hot_return, + int* y_hot_return)); +/* 79 */ +EXTERN int TkScrollWindow _ANSI_ARGS_((Tk_Window tkwin, GC gc, + int x, int y, int width, int height, int dx, + int dy, TkRegion damageRgn)); +/* 80 */ +EXTERN void TkSelDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 81 */ +EXTERN void TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin, + XEvent * eventPtr)); +/* 82 */ +EXTERN void TkSelInit _ANSI_ARGS_((Tk_Window tkwin)); +/* 83 */ +EXTERN void TkSelPropProc _ANSI_ARGS_((XEvent * eventPtr)); +/* Slot 84 is reserved */ +/* 85 */ +EXTERN void TkSetWindowMenuBar _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, char * oldMenuName, + char * menuName)); +/* 86 */ +EXTERN KeySym TkStringToKeysym _ANSI_ARGS_((char * name)); +/* 87 */ +EXTERN int TkThickPolyLineToArea _ANSI_ARGS_((double * coordPtr, + int numPoints, double width, int capStyle, + int joinStyle, double * rectPtr)); +/* 88 */ +EXTERN void TkWmAddToColormapWindows _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 89 */ +EXTERN void TkWmDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 90 */ +EXTERN TkWindow * TkWmFocusToplevel _ANSI_ARGS_((TkWindow * winPtr)); +/* 91 */ +EXTERN void TkWmMapWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 92 */ +EXTERN void TkWmNewWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 93 */ +EXTERN void TkWmProtocolEventProc _ANSI_ARGS_((TkWindow * winPtr, + XEvent * evenvPtr)); +/* 94 */ +EXTERN void TkWmRemoveFromColormapWindows _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 95 */ +EXTERN void TkWmRestackToplevel _ANSI_ARGS_((TkWindow * winPtr, + int aboveBelow, TkWindow * otherPtr)); +/* 96 */ +EXTERN void TkWmSetClass _ANSI_ARGS_((TkWindow * winPtr)); +/* 97 */ +EXTERN void TkWmUnmapWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 98 */ +EXTERN Tcl_Obj * TkDebugBitmap _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 99 */ +EXTERN Tcl_Obj * TkDebugBorder _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 100 */ +EXTERN Tcl_Obj * TkDebugCursor _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 101 */ +EXTERN Tcl_Obj * TkDebugColor _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 102 */ +EXTERN Tcl_Obj * TkDebugConfig _ANSI_ARGS_((Tcl_Interp * interp, + Tk_OptionTable table)); +/* 103 */ +EXTERN Tcl_Obj * TkDebugFont _ANSI_ARGS_((Tk_Window tkwin, + char * name)); +/* 104 */ +EXTERN int TkFindStateNumObj _ANSI_ARGS_((Tcl_Interp * interp, + Tcl_Obj * optionPtr, + CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr)); +/* 105 */ +EXTERN Tcl_HashTable * TkGetBitmapPredefTable _ANSI_ARGS_((void)); +/* 106 */ +EXTERN TkDisplay * TkGetDisplayList _ANSI_ARGS_((void)); +/* 107 */ +EXTERN TkMainInfo * TkGetMainInfoList _ANSI_ARGS_((void)); +/* 108 */ +EXTERN int TkGetWindowFromObj _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Window tkwin, Tcl_Obj * objPtr, + Tk_Window * windowPtr)); +/* 109 */ +EXTERN char * TkpGetString _ANSI_ARGS_((TkWindow * winPtr, + XEvent * eventPtr, Tcl_DString * dsPtr)); +/* 110 */ +EXTERN void TkpGetSubFonts _ANSI_ARGS_((Tcl_Interp * interp, + Tk_Font tkfont)); +/* 111 */ +EXTERN Tcl_Obj * TkpGetSystemDefault _ANSI_ARGS_((Tk_Window tkwin, + CONST char * dbName, CONST char * className)); +/* 112 */ +EXTERN void TkpMenuThreadInit _ANSI_ARGS_((void)); +#ifdef __WIN32__ +/* 113 */ +EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, + XRectangle* rect_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 113 */ +EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, + XRectangle* rect_return)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 113 */ +EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, + XRectangle* rect_return)); +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +/* 114 */ +EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 114 */ +EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 114 */ +EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +/* 115 */ +EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 115 */ +EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 115 */ +EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +/* 116 */ +EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 116 */ +EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 116 */ +EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +/* 117 */ +EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, + int y, unsigned int width, + unsigned int height)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 117 */ +EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, + int y, unsigned int width, + unsigned int height)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 117 */ +EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, + int y, unsigned int width, + unsigned int height)); +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +/* 118 */ +EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc, + TkRegion rgn)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 118 */ +EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc, + TkRegion rgn)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 118 */ +EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc, + TkRegion rgn)); +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +/* 119 */ +EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect, + TkRegion src, TkRegion dr_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 119 */ +EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect, + TkRegion src, TkRegion dr_return)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 119 */ +EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect, + TkRegion src, TkRegion dr_return)); +#endif /* MAC_OSX_TK */ +/* Slot 120 is reserved */ +#ifdef MAC_TCL +/* 121 */ +EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display, + CONST char * source)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 121 */ +EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display, + CONST char * source)); +#endif /* MAC_OSX_TK */ +#ifdef MAC_TCL +/* 122 */ +EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 122 */ +EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); +#endif /* MAC_OSX_TK */ +/* Slot 123 is reserved */ +#ifdef MAC_TCL +/* 124 */ +EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display * display, + CONST char * name, int * width, int * height)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 124 */ +EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display * display, + CONST char * name, int * width, int * height)); +#endif /* MAC_OSX_TK */ +/* Slot 125 is reserved */ +/* Slot 126 is reserved */ +/* Slot 127 is reserved */ +/* Slot 128 is reserved */ +/* Slot 129 is reserved */ +/* Slot 130 is reserved */ +/* Slot 131 is reserved */ +/* Slot 132 is reserved */ +/* Slot 133 is reserved */ +/* Slot 134 is reserved */ +/* 135 */ +EXTERN void TkpDrawHighlightBorder _ANSI_ARGS_((Tk_Window tkwin, + GC fgGC, GC bgGC, int highlightWidth, + Drawable drawable)); +/* 136 */ +EXTERN void TkSetFocusWin _ANSI_ARGS_((TkWindow * winPtr, + int force)); +/* 137 */ +EXTERN void TkpSetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin, + KeySym keySym, XEvent * eventPtr)); +/* 138 */ +EXTERN KeySym TkpGetKeySym _ANSI_ARGS_((TkDisplay * dispPtr, + XEvent * eventPtr)); +/* 139 */ +EXTERN void TkpInitKeymapInfo _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 140 */ +EXTERN TkRegion TkPhotoGetValidRegion _ANSI_ARGS_(( + Tk_PhotoHandle handle)); +/* 141 */ +EXTERN TkWindow ** TkWmStackorderToplevel _ANSI_ARGS_(( + TkWindow * parentPtr)); +/* 142 */ +EXTERN void TkFocusFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 143 */ +EXTERN void TkClipCleanup _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 144 */ +EXTERN void TkGCCleanup _ANSI_ARGS_((TkDisplay * dispPtr)); +#ifdef __WIN32__ +/* 145 */ +EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 145 */ +EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 145 */ +EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra, + TkRegion srcb, TkRegion dr_return)); +#endif /* MAC_OSX_TK */ +/* 146 */ +EXTERN void TkStylePkgInit _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 147 */ +EXTERN void TkStylePkgFree _ANSI_ARGS_((TkMainInfo * mainPtr)); +/* 148 */ +EXTERN Tk_Window TkToplevelWindowForCommand _ANSI_ARGS_(( + Tcl_Interp * interp, CONST char * cmdName)); +/* 149 */ +EXTERN CONST Tk_OptionSpec * TkGetOptionSpec _ANSI_ARGS_((CONST char * name, + Tk_OptionTable optionTable)); + +typedef struct TkIntStubs { + int magic; + struct TkIntStubHooks *hooks; + + TkWindow * (*tkAllocWindow) _ANSI_ARGS_((TkDisplay * dispPtr, int screenNum, TkWindow * parentPtr)); /* 0 */ + void (*tkBezierPoints) _ANSI_ARGS_((double control[], int numSteps, double * coordPtr)); /* 1 */ + void (*tkBezierScreenPoints) _ANSI_ARGS_((Tk_Canvas canvas, double control[], int numSteps, XPoint * xPointPtr)); /* 2 */ + void (*tkBindDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 3 */ + void (*tkBindEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 4 */ + void (*tkBindFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 5 */ + void (*tkBindInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 6 */ + void (*tkChangeEventWindow) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 7 */ + int (*tkClipInit) _ANSI_ARGS_((Tcl_Interp * interp, TkDisplay * dispPtr)); /* 8 */ + void (*tkComputeAnchor) _ANSI_ARGS_((Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int * xPtr, int * yPtr)); /* 9 */ + int (*tkCopyAndGlobalEval) _ANSI_ARGS_((Tcl_Interp * interp, char * script)); /* 10 */ + unsigned long (*tkCreateBindingProcedure) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object, CONST char * eventString, TkBindEvalProc * evalProc, TkBindFreeProc * freeProc, ClientData clientData)); /* 11 */ + TkCursor * (*tkCreateCursorFromData) _ANSI_ARGS_((Tk_Window tkwin, CONST char * source, CONST char * mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg)); /* 12 */ + int (*tkCreateFrame) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv, int toplevel, char * appName)); /* 13 */ + Tk_Window (*tkCreateMainWindow) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * screenName, char * baseName)); /* 14 */ + Time (*tkCurrentTime) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 15 */ + void (*tkDeleteAllImages) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 16 */ + void (*tkDoConfigureNotify) _ANSI_ARGS_((TkWindow * winPtr)); /* 17 */ + void (*tkDrawInsetFocusHighlight) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding)); /* 18 */ + void (*tkEventDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 19 */ + void (*tkFillPolygon) _ANSI_ARGS_((Tk_Canvas canvas, double * coordPtr, int numPoints, Display * display, Drawable drawable, GC gc, GC outlineGC)); /* 20 */ + int (*tkFindStateNum) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * option, CONST TkStateMap * mapPtr, CONST char * strKey)); /* 21 */ + char * (*tkFindStateString) _ANSI_ARGS_((CONST TkStateMap * mapPtr, int numKey)); /* 22 */ + void (*tkFocusDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 23 */ + int (*tkFocusFilterEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 24 */ + TkWindow * (*tkFocusKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 25 */ + void (*tkFontPkgInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 26 */ + void (*tkFontPkgFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 27 */ + void (*tkFreeBindingTags) _ANSI_ARGS_((TkWindow * winPtr)); /* 28 */ + void (*tkpFreeCursor) _ANSI_ARGS_((TkCursor * cursorPtr)); /* 29 */ + char * (*tkGetBitmapData) _ANSI_ARGS_((Tcl_Interp * interp, char * string, char * fileName, int * widthPtr, int * heightPtr, int * hotXPtr, int * hotYPtr)); /* 30 */ + void (*tkGetButtPoints) _ANSI_ARGS_((double p1[], double p2[], double width, int project, double m1[], double m2[])); /* 31 */ + TkCursor * (*tkGetCursorByName) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_Uid string)); /* 32 */ + CONST84_RETURN char * (*tkGetDefaultScreenName) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * screenName)); /* 33 */ + TkDisplay * (*tkGetDisplay) _ANSI_ARGS_((Display * display)); /* 34 */ + int (*tkGetDisplayOf) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], Tk_Window * tkwinPtr)); /* 35 */ + TkWindow * (*tkGetFocusWin) _ANSI_ARGS_((TkWindow * winPtr)); /* 36 */ + int (*tkGetInterpNames) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 37 */ + int (*tkGetMiterPoints) _ANSI_ARGS_((double p1[], double p2[], double p3[], double width, double m1[], double m2[])); /* 38 */ + void (*tkGetPointerCoords) _ANSI_ARGS_((Tk_Window tkwin, int * xPtr, int * yPtr)); /* 39 */ + void (*tkGetServerInfo) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 40 */ + void (*tkGrabDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 41 */ + int (*tkGrabState) _ANSI_ARGS_((TkWindow * winPtr)); /* 42 */ + void (*tkIncludePoint) _ANSI_ARGS_((Tk_Item * itemPtr, double * pointPtr)); /* 43 */ + void (*tkInOutEvents) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * sourcePtr, TkWindow * destPtr, int leaveType, int enterType, Tcl_QueuePosition position)); /* 44 */ + void (*tkInstallFrameMenu) _ANSI_ARGS_((Tk_Window tkwin)); /* 45 */ + char * (*tkKeysymToString) _ANSI_ARGS_((KeySym keysym)); /* 46 */ + int (*tkLineToArea) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double rectPtr[])); /* 47 */ + double (*tkLineToPoint) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double pointPtr[])); /* 48 */ + int (*tkMakeBezierCurve) _ANSI_ARGS_((Tk_Canvas canvas, double * pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[])); /* 49 */ + void (*tkMakeBezierPostscript) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, double * pointPtr, int numPoints)); /* 50 */ + void (*tkOptionClassChanged) _ANSI_ARGS_((TkWindow * winPtr)); /* 51 */ + void (*tkOptionDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 52 */ + int (*tkOvalToArea) _ANSI_ARGS_((double * ovalPtr, double * rectPtr)); /* 53 */ + double (*tkOvalToPoint) _ANSI_ARGS_((double ovalPtr[], double width, int filled, double pointPtr[])); /* 54 */ + int (*tkpChangeFocus) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 55 */ + void (*tkpCloseDisplay) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 56 */ + void (*tkpClaimFocus) _ANSI_ARGS_((TkWindow * topLevelPtr, int force)); /* 57 */ + void (*tkpDisplayWarning) _ANSI_ARGS_((CONST char * msg, CONST char * title)); /* 58 */ + void (*tkpGetAppName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * name)); /* 59 */ + TkWindow * (*tkpGetOtherWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 60 */ + TkWindow * (*tkpGetWrapperWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 61 */ + int (*tkpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 62 */ + void (*tkpInitializeMenuBindings) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable)); /* 63 */ + void (*tkpMakeContainer) _ANSI_ARGS_((Tk_Window tkwin)); /* 64 */ + void (*tkpMakeMenuWindow) _ANSI_ARGS_((Tk_Window tkwin, int transient)); /* 65 */ + Window (*tkpMakeWindow) _ANSI_ARGS_((TkWindow * winPtr, Window parent)); /* 66 */ + void (*tkpMenuNotifyToplevelCreate) _ANSI_ARGS_((Tcl_Interp * interp1, char * menuName)); /* 67 */ + TkDisplay * (*tkpOpenDisplay) _ANSI_ARGS_((CONST char * display_name)); /* 68 */ + int (*tkPointerEvent) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 69 */ + int (*tkPolygonToArea) _ANSI_ARGS_((double * polyPtr, int numPoints, double * rectPtr)); /* 70 */ + double (*tkPolygonToPoint) _ANSI_ARGS_((double * polyPtr, int numPoints, double * pointPtr)); /* 71 */ + int (*tkPositionInTree) _ANSI_ARGS_((TkWindow * winPtr, TkWindow * treePtr)); /* 72 */ + void (*tkpRedirectKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 73 */ + void (*tkpSetMainMenubar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * menuName)); /* 74 */ + int (*tkpUseWindow) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, CONST char * string)); /* 75 */ + int (*tkpWindowWasRecentlyDeleted) _ANSI_ARGS_((Window win, TkDisplay * dispPtr)); /* 76 */ + void (*tkQueueEventForAllChildren) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 77 */ + int (*tkReadBitmapFile) _ANSI_ARGS_((Display* display, Drawable d, CONST char* filename, unsigned int* width_return, unsigned int* height_return, Pixmap* bitmap_return, int* x_hot_return, int* y_hot_return)); /* 78 */ + int (*tkScrollWindow) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn)); /* 79 */ + void (*tkSelDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 80 */ + void (*tkSelEventProc) _ANSI_ARGS_((Tk_Window tkwin, XEvent * eventPtr)); /* 81 */ + void (*tkSelInit) _ANSI_ARGS_((Tk_Window tkwin)); /* 82 */ + void (*tkSelPropProc) _ANSI_ARGS_((XEvent * eventPtr)); /* 83 */ + void *reserved84; + void (*tkSetWindowMenuBar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * oldMenuName, char * menuName)); /* 85 */ + KeySym (*tkStringToKeysym) _ANSI_ARGS_((char * name)); /* 86 */ + int (*tkThickPolyLineToArea) _ANSI_ARGS_((double * coordPtr, int numPoints, double width, int capStyle, int joinStyle, double * rectPtr)); /* 87 */ + void (*tkWmAddToColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 88 */ + void (*tkWmDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 89 */ + TkWindow * (*tkWmFocusToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 90 */ + void (*tkWmMapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 91 */ + void (*tkWmNewWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 92 */ + void (*tkWmProtocolEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * evenvPtr)); /* 93 */ + void (*tkWmRemoveFromColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 94 */ + void (*tkWmRestackToplevel) _ANSI_ARGS_((TkWindow * winPtr, int aboveBelow, TkWindow * otherPtr)); /* 95 */ + void (*tkWmSetClass) _ANSI_ARGS_((TkWindow * winPtr)); /* 96 */ + void (*tkWmUnmapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 97 */ + Tcl_Obj * (*tkDebugBitmap) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 98 */ + Tcl_Obj * (*tkDebugBorder) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 99 */ + Tcl_Obj * (*tkDebugCursor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 100 */ + Tcl_Obj * (*tkDebugColor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 101 */ + Tcl_Obj * (*tkDebugConfig) _ANSI_ARGS_((Tcl_Interp * interp, Tk_OptionTable table)); /* 102 */ + Tcl_Obj * (*tkDebugFont) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 103 */ + int (*tkFindStateNumObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * optionPtr, CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr)); /* 104 */ + Tcl_HashTable * (*tkGetBitmapPredefTable) _ANSI_ARGS_((void)); /* 105 */ + TkDisplay * (*tkGetDisplayList) _ANSI_ARGS_((void)); /* 106 */ + TkMainInfo * (*tkGetMainInfoList) _ANSI_ARGS_((void)); /* 107 */ + int (*tkGetWindowFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr, Tk_Window * windowPtr)); /* 108 */ + char * (*tkpGetString) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr, Tcl_DString * dsPtr)); /* 109 */ + void (*tkpGetSubFonts) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Font tkfont)); /* 110 */ + Tcl_Obj * (*tkpGetSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, CONST char * dbName, CONST char * className)); /* 111 */ + void (*tkpMenuThreadInit) _ANSI_ARGS_((void)); /* 112 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved113; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */ +#endif /* MAC_OSX_TK */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved114; +#endif /* UNIX */ +#ifdef __WIN32__ + TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ +#endif /* MAC_OSX_TK */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved115; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ +#endif /* MAC_OSX_TK */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved116; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ +#endif /* MAC_OSX_TK */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved117; +#endif /* UNIX */ +#ifdef __WIN32__ + int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ +#endif /* MAC_OSX_TK */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved118; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */ +#endif /* MAC_OSX_TK */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved119; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */ +#endif /* MAC_OSX_TK */ + void *reserved120; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved121; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved121; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, CONST char * source)); /* 121 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, CONST char * source)); /* 121 */ +#endif /* MAC_OSX_TK */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved122; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved122; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 122 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 122 */ +#endif /* MAC_OSX_TK */ + void *reserved123; +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved124; +#endif /* UNIX */ +#ifdef __WIN32__ + void *reserved124; +#endif /* __WIN32__ */ +#ifdef MAC_TCL + Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display * display, CONST char * name, int * width, int * height)); /* 124 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display * display, CONST char * name, int * width, int * height)); /* 124 */ +#endif /* MAC_OSX_TK */ + void *reserved125; + void *reserved126; + void *reserved127; + void *reserved128; + void *reserved129; + void *reserved130; + void *reserved131; + void *reserved132; + void *reserved133; + void *reserved134; + void (*tkpDrawHighlightBorder) _ANSI_ARGS_((Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable)); /* 135 */ + void (*tkSetFocusWin) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 136 */ + void (*tkpSetKeycodeAndState) _ANSI_ARGS_((Tk_Window tkwin, KeySym keySym, XEvent * eventPtr)); /* 137 */ + KeySym (*tkpGetKeySym) _ANSI_ARGS_((TkDisplay * dispPtr, XEvent * eventPtr)); /* 138 */ + void (*tkpInitKeymapInfo) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 139 */ + TkRegion (*tkPhotoGetValidRegion) _ANSI_ARGS_((Tk_PhotoHandle handle)); /* 140 */ + TkWindow ** (*tkWmStackorderToplevel) _ANSI_ARGS_((TkWindow * parentPtr)); /* 141 */ + void (*tkFocusFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 142 */ + void (*tkClipCleanup) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 143 */ + void (*tkGCCleanup) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 144 */ +#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void *reserved145; +#endif /* UNIX */ +#ifdef __WIN32__ + void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */ +#endif /* MAC_OSX_TK */ + void (*tkStylePkgInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 146 */ + void (*tkStylePkgFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 147 */ + Tk_Window (*tkToplevelWindowForCommand) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * cmdName)); /* 148 */ + CONST Tk_OptionSpec * (*tkGetOptionSpec) _ANSI_ARGS_((CONST char * name, Tk_OptionTable optionTable)); /* 149 */ +} TkIntStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkIntStubs *tkIntStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifndef TkAllocWindow +#define TkAllocWindow \ + (tkIntStubsPtr->tkAllocWindow) /* 0 */ +#endif +#ifndef TkBezierPoints +#define TkBezierPoints \ + (tkIntStubsPtr->tkBezierPoints) /* 1 */ +#endif +#ifndef TkBezierScreenPoints +#define TkBezierScreenPoints \ + (tkIntStubsPtr->tkBezierScreenPoints) /* 2 */ +#endif +#ifndef TkBindDeadWindow +#define TkBindDeadWindow \ + (tkIntStubsPtr->tkBindDeadWindow) /* 3 */ +#endif +#ifndef TkBindEventProc +#define TkBindEventProc \ + (tkIntStubsPtr->tkBindEventProc) /* 4 */ +#endif +#ifndef TkBindFree +#define TkBindFree \ + (tkIntStubsPtr->tkBindFree) /* 5 */ +#endif +#ifndef TkBindInit +#define TkBindInit \ + (tkIntStubsPtr->tkBindInit) /* 6 */ +#endif +#ifndef TkChangeEventWindow +#define TkChangeEventWindow \ + (tkIntStubsPtr->tkChangeEventWindow) /* 7 */ +#endif +#ifndef TkClipInit +#define TkClipInit \ + (tkIntStubsPtr->tkClipInit) /* 8 */ +#endif +#ifndef TkComputeAnchor +#define TkComputeAnchor \ + (tkIntStubsPtr->tkComputeAnchor) /* 9 */ +#endif +#ifndef TkCopyAndGlobalEval +#define TkCopyAndGlobalEval \ + (tkIntStubsPtr->tkCopyAndGlobalEval) /* 10 */ +#endif +#ifndef TkCreateBindingProcedure +#define TkCreateBindingProcedure \ + (tkIntStubsPtr->tkCreateBindingProcedure) /* 11 */ +#endif +#ifndef TkCreateCursorFromData +#define TkCreateCursorFromData \ + (tkIntStubsPtr->tkCreateCursorFromData) /* 12 */ +#endif +#ifndef TkCreateFrame +#define TkCreateFrame \ + (tkIntStubsPtr->tkCreateFrame) /* 13 */ +#endif +#ifndef TkCreateMainWindow +#define TkCreateMainWindow \ + (tkIntStubsPtr->tkCreateMainWindow) /* 14 */ +#endif +#ifndef TkCurrentTime +#define TkCurrentTime \ + (tkIntStubsPtr->tkCurrentTime) /* 15 */ +#endif +#ifndef TkDeleteAllImages +#define TkDeleteAllImages \ + (tkIntStubsPtr->tkDeleteAllImages) /* 16 */ +#endif +#ifndef TkDoConfigureNotify +#define TkDoConfigureNotify \ + (tkIntStubsPtr->tkDoConfigureNotify) /* 17 */ +#endif +#ifndef TkDrawInsetFocusHighlight +#define TkDrawInsetFocusHighlight \ + (tkIntStubsPtr->tkDrawInsetFocusHighlight) /* 18 */ +#endif +#ifndef TkEventDeadWindow +#define TkEventDeadWindow \ + (tkIntStubsPtr->tkEventDeadWindow) /* 19 */ +#endif +#ifndef TkFillPolygon +#define TkFillPolygon \ + (tkIntStubsPtr->tkFillPolygon) /* 20 */ +#endif +#ifndef TkFindStateNum +#define TkFindStateNum \ + (tkIntStubsPtr->tkFindStateNum) /* 21 */ +#endif +#ifndef TkFindStateString +#define TkFindStateString \ + (tkIntStubsPtr->tkFindStateString) /* 22 */ +#endif +#ifndef TkFocusDeadWindow +#define TkFocusDeadWindow \ + (tkIntStubsPtr->tkFocusDeadWindow) /* 23 */ +#endif +#ifndef TkFocusFilterEvent +#define TkFocusFilterEvent \ + (tkIntStubsPtr->tkFocusFilterEvent) /* 24 */ +#endif +#ifndef TkFocusKeyEvent +#define TkFocusKeyEvent \ + (tkIntStubsPtr->tkFocusKeyEvent) /* 25 */ +#endif +#ifndef TkFontPkgInit +#define TkFontPkgInit \ + (tkIntStubsPtr->tkFontPkgInit) /* 26 */ +#endif +#ifndef TkFontPkgFree +#define TkFontPkgFree \ + (tkIntStubsPtr->tkFontPkgFree) /* 27 */ +#endif +#ifndef TkFreeBindingTags +#define TkFreeBindingTags \ + (tkIntStubsPtr->tkFreeBindingTags) /* 28 */ +#endif +#ifndef TkpFreeCursor +#define TkpFreeCursor \ + (tkIntStubsPtr->tkpFreeCursor) /* 29 */ +#endif +#ifndef TkGetBitmapData +#define TkGetBitmapData \ + (tkIntStubsPtr->tkGetBitmapData) /* 30 */ +#endif +#ifndef TkGetButtPoints +#define TkGetButtPoints \ + (tkIntStubsPtr->tkGetButtPoints) /* 31 */ +#endif +#ifndef TkGetCursorByName +#define TkGetCursorByName \ + (tkIntStubsPtr->tkGetCursorByName) /* 32 */ +#endif +#ifndef TkGetDefaultScreenName +#define TkGetDefaultScreenName \ + (tkIntStubsPtr->tkGetDefaultScreenName) /* 33 */ +#endif +#ifndef TkGetDisplay +#define TkGetDisplay \ + (tkIntStubsPtr->tkGetDisplay) /* 34 */ +#endif +#ifndef TkGetDisplayOf +#define TkGetDisplayOf \ + (tkIntStubsPtr->tkGetDisplayOf) /* 35 */ +#endif +#ifndef TkGetFocusWin +#define TkGetFocusWin \ + (tkIntStubsPtr->tkGetFocusWin) /* 36 */ +#endif +#ifndef TkGetInterpNames +#define TkGetInterpNames \ + (tkIntStubsPtr->tkGetInterpNames) /* 37 */ +#endif +#ifndef TkGetMiterPoints +#define TkGetMiterPoints \ + (tkIntStubsPtr->tkGetMiterPoints) /* 38 */ +#endif +#ifndef TkGetPointerCoords +#define TkGetPointerCoords \ + (tkIntStubsPtr->tkGetPointerCoords) /* 39 */ +#endif +#ifndef TkGetServerInfo +#define TkGetServerInfo \ + (tkIntStubsPtr->tkGetServerInfo) /* 40 */ +#endif +#ifndef TkGrabDeadWindow +#define TkGrabDeadWindow \ + (tkIntStubsPtr->tkGrabDeadWindow) /* 41 */ +#endif +#ifndef TkGrabState +#define TkGrabState \ + (tkIntStubsPtr->tkGrabState) /* 42 */ +#endif +#ifndef TkIncludePoint +#define TkIncludePoint \ + (tkIntStubsPtr->tkIncludePoint) /* 43 */ +#endif +#ifndef TkInOutEvents +#define TkInOutEvents \ + (tkIntStubsPtr->tkInOutEvents) /* 44 */ +#endif +#ifndef TkInstallFrameMenu +#define TkInstallFrameMenu \ + (tkIntStubsPtr->tkInstallFrameMenu) /* 45 */ +#endif +#ifndef TkKeysymToString +#define TkKeysymToString \ + (tkIntStubsPtr->tkKeysymToString) /* 46 */ +#endif +#ifndef TkLineToArea +#define TkLineToArea \ + (tkIntStubsPtr->tkLineToArea) /* 47 */ +#endif +#ifndef TkLineToPoint +#define TkLineToPoint \ + (tkIntStubsPtr->tkLineToPoint) /* 48 */ +#endif +#ifndef TkMakeBezierCurve +#define TkMakeBezierCurve \ + (tkIntStubsPtr->tkMakeBezierCurve) /* 49 */ +#endif +#ifndef TkMakeBezierPostscript +#define TkMakeBezierPostscript \ + (tkIntStubsPtr->tkMakeBezierPostscript) /* 50 */ +#endif +#ifndef TkOptionClassChanged +#define TkOptionClassChanged \ + (tkIntStubsPtr->tkOptionClassChanged) /* 51 */ +#endif +#ifndef TkOptionDeadWindow +#define TkOptionDeadWindow \ + (tkIntStubsPtr->tkOptionDeadWindow) /* 52 */ +#endif +#ifndef TkOvalToArea +#define TkOvalToArea \ + (tkIntStubsPtr->tkOvalToArea) /* 53 */ +#endif +#ifndef TkOvalToPoint +#define TkOvalToPoint \ + (tkIntStubsPtr->tkOvalToPoint) /* 54 */ +#endif +#ifndef TkpChangeFocus +#define TkpChangeFocus \ + (tkIntStubsPtr->tkpChangeFocus) /* 55 */ +#endif +#ifndef TkpCloseDisplay +#define TkpCloseDisplay \ + (tkIntStubsPtr->tkpCloseDisplay) /* 56 */ +#endif +#ifndef TkpClaimFocus +#define TkpClaimFocus \ + (tkIntStubsPtr->tkpClaimFocus) /* 57 */ +#endif +#ifndef TkpDisplayWarning +#define TkpDisplayWarning \ + (tkIntStubsPtr->tkpDisplayWarning) /* 58 */ +#endif +#ifndef TkpGetAppName +#define TkpGetAppName \ + (tkIntStubsPtr->tkpGetAppName) /* 59 */ +#endif +#ifndef TkpGetOtherWindow +#define TkpGetOtherWindow \ + (tkIntStubsPtr->tkpGetOtherWindow) /* 60 */ +#endif +#ifndef TkpGetWrapperWindow +#define TkpGetWrapperWindow \ + (tkIntStubsPtr->tkpGetWrapperWindow) /* 61 */ +#endif +#ifndef TkpInit +#define TkpInit \ + (tkIntStubsPtr->tkpInit) /* 62 */ +#endif +#ifndef TkpInitializeMenuBindings +#define TkpInitializeMenuBindings \ + (tkIntStubsPtr->tkpInitializeMenuBindings) /* 63 */ +#endif +#ifndef TkpMakeContainer +#define TkpMakeContainer \ + (tkIntStubsPtr->tkpMakeContainer) /* 64 */ +#endif +#ifndef TkpMakeMenuWindow +#define TkpMakeMenuWindow \ + (tkIntStubsPtr->tkpMakeMenuWindow) /* 65 */ +#endif +#ifndef TkpMakeWindow +#define TkpMakeWindow \ + (tkIntStubsPtr->tkpMakeWindow) /* 66 */ +#endif +#ifndef TkpMenuNotifyToplevelCreate +#define TkpMenuNotifyToplevelCreate \ + (tkIntStubsPtr->tkpMenuNotifyToplevelCreate) /* 67 */ +#endif +#ifndef TkpOpenDisplay +#define TkpOpenDisplay \ + (tkIntStubsPtr->tkpOpenDisplay) /* 68 */ +#endif +#ifndef TkPointerEvent +#define TkPointerEvent \ + (tkIntStubsPtr->tkPointerEvent) /* 69 */ +#endif +#ifndef TkPolygonToArea +#define TkPolygonToArea \ + (tkIntStubsPtr->tkPolygonToArea) /* 70 */ +#endif +#ifndef TkPolygonToPoint +#define TkPolygonToPoint \ + (tkIntStubsPtr->tkPolygonToPoint) /* 71 */ +#endif +#ifndef TkPositionInTree +#define TkPositionInTree \ + (tkIntStubsPtr->tkPositionInTree) /* 72 */ +#endif +#ifndef TkpRedirectKeyEvent +#define TkpRedirectKeyEvent \ + (tkIntStubsPtr->tkpRedirectKeyEvent) /* 73 */ +#endif +#ifndef TkpSetMainMenubar +#define TkpSetMainMenubar \ + (tkIntStubsPtr->tkpSetMainMenubar) /* 74 */ +#endif +#ifndef TkpUseWindow +#define TkpUseWindow \ + (tkIntStubsPtr->tkpUseWindow) /* 75 */ +#endif +#ifndef TkpWindowWasRecentlyDeleted +#define TkpWindowWasRecentlyDeleted \ + (tkIntStubsPtr->tkpWindowWasRecentlyDeleted) /* 76 */ +#endif +#ifndef TkQueueEventForAllChildren +#define TkQueueEventForAllChildren \ + (tkIntStubsPtr->tkQueueEventForAllChildren) /* 77 */ +#endif +#ifndef TkReadBitmapFile +#define TkReadBitmapFile \ + (tkIntStubsPtr->tkReadBitmapFile) /* 78 */ +#endif +#ifndef TkScrollWindow +#define TkScrollWindow \ + (tkIntStubsPtr->tkScrollWindow) /* 79 */ +#endif +#ifndef TkSelDeadWindow +#define TkSelDeadWindow \ + (tkIntStubsPtr->tkSelDeadWindow) /* 80 */ +#endif +#ifndef TkSelEventProc +#define TkSelEventProc \ + (tkIntStubsPtr->tkSelEventProc) /* 81 */ +#endif +#ifndef TkSelInit +#define TkSelInit \ + (tkIntStubsPtr->tkSelInit) /* 82 */ +#endif +#ifndef TkSelPropProc +#define TkSelPropProc \ + (tkIntStubsPtr->tkSelPropProc) /* 83 */ +#endif +/* Slot 84 is reserved */ +#ifndef TkSetWindowMenuBar +#define TkSetWindowMenuBar \ + (tkIntStubsPtr->tkSetWindowMenuBar) /* 85 */ +#endif +#ifndef TkStringToKeysym +#define TkStringToKeysym \ + (tkIntStubsPtr->tkStringToKeysym) /* 86 */ +#endif +#ifndef TkThickPolyLineToArea +#define TkThickPolyLineToArea \ + (tkIntStubsPtr->tkThickPolyLineToArea) /* 87 */ +#endif +#ifndef TkWmAddToColormapWindows +#define TkWmAddToColormapWindows \ + (tkIntStubsPtr->tkWmAddToColormapWindows) /* 88 */ +#endif +#ifndef TkWmDeadWindow +#define TkWmDeadWindow \ + (tkIntStubsPtr->tkWmDeadWindow) /* 89 */ +#endif +#ifndef TkWmFocusToplevel +#define TkWmFocusToplevel \ + (tkIntStubsPtr->tkWmFocusToplevel) /* 90 */ +#endif +#ifndef TkWmMapWindow +#define TkWmMapWindow \ + (tkIntStubsPtr->tkWmMapWindow) /* 91 */ +#endif +#ifndef TkWmNewWindow +#define TkWmNewWindow \ + (tkIntStubsPtr->tkWmNewWindow) /* 92 */ +#endif +#ifndef TkWmProtocolEventProc +#define TkWmProtocolEventProc \ + (tkIntStubsPtr->tkWmProtocolEventProc) /* 93 */ +#endif +#ifndef TkWmRemoveFromColormapWindows +#define TkWmRemoveFromColormapWindows \ + (tkIntStubsPtr->tkWmRemoveFromColormapWindows) /* 94 */ +#endif +#ifndef TkWmRestackToplevel +#define TkWmRestackToplevel \ + (tkIntStubsPtr->tkWmRestackToplevel) /* 95 */ +#endif +#ifndef TkWmSetClass +#define TkWmSetClass \ + (tkIntStubsPtr->tkWmSetClass) /* 96 */ +#endif +#ifndef TkWmUnmapWindow +#define TkWmUnmapWindow \ + (tkIntStubsPtr->tkWmUnmapWindow) /* 97 */ +#endif +#ifndef TkDebugBitmap +#define TkDebugBitmap \ + (tkIntStubsPtr->tkDebugBitmap) /* 98 */ +#endif +#ifndef TkDebugBorder +#define TkDebugBorder \ + (tkIntStubsPtr->tkDebugBorder) /* 99 */ +#endif +#ifndef TkDebugCursor +#define TkDebugCursor \ + (tkIntStubsPtr->tkDebugCursor) /* 100 */ +#endif +#ifndef TkDebugColor +#define TkDebugColor \ + (tkIntStubsPtr->tkDebugColor) /* 101 */ +#endif +#ifndef TkDebugConfig +#define TkDebugConfig \ + (tkIntStubsPtr->tkDebugConfig) /* 102 */ +#endif +#ifndef TkDebugFont +#define TkDebugFont \ + (tkIntStubsPtr->tkDebugFont) /* 103 */ +#endif +#ifndef TkFindStateNumObj +#define TkFindStateNumObj \ + (tkIntStubsPtr->tkFindStateNumObj) /* 104 */ +#endif +#ifndef TkGetBitmapPredefTable +#define TkGetBitmapPredefTable \ + (tkIntStubsPtr->tkGetBitmapPredefTable) /* 105 */ +#endif +#ifndef TkGetDisplayList +#define TkGetDisplayList \ + (tkIntStubsPtr->tkGetDisplayList) /* 106 */ +#endif +#ifndef TkGetMainInfoList +#define TkGetMainInfoList \ + (tkIntStubsPtr->tkGetMainInfoList) /* 107 */ +#endif +#ifndef TkGetWindowFromObj +#define TkGetWindowFromObj \ + (tkIntStubsPtr->tkGetWindowFromObj) /* 108 */ +#endif +#ifndef TkpGetString +#define TkpGetString \ + (tkIntStubsPtr->tkpGetString) /* 109 */ +#endif +#ifndef TkpGetSubFonts +#define TkpGetSubFonts \ + (tkIntStubsPtr->tkpGetSubFonts) /* 110 */ +#endif +#ifndef TkpGetSystemDefault +#define TkpGetSystemDefault \ + (tkIntStubsPtr->tkpGetSystemDefault) /* 111 */ +#endif +#ifndef TkpMenuThreadInit +#define TkpMenuThreadInit \ + (tkIntStubsPtr->tkpMenuThreadInit) /* 112 */ +#endif +#ifdef __WIN32__ +#ifndef TkClipBox +#define TkClipBox \ + (tkIntStubsPtr->tkClipBox) /* 113 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkClipBox +#define TkClipBox \ + (tkIntStubsPtr->tkClipBox) /* 113 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkClipBox +#define TkClipBox \ + (tkIntStubsPtr->tkClipBox) /* 113 */ +#endif +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +#ifndef TkCreateRegion +#define TkCreateRegion \ + (tkIntStubsPtr->tkCreateRegion) /* 114 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkCreateRegion +#define TkCreateRegion \ + (tkIntStubsPtr->tkCreateRegion) /* 114 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkCreateRegion +#define TkCreateRegion \ + (tkIntStubsPtr->tkCreateRegion) /* 114 */ +#endif +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +#ifndef TkDestroyRegion +#define TkDestroyRegion \ + (tkIntStubsPtr->tkDestroyRegion) /* 115 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkDestroyRegion +#define TkDestroyRegion \ + (tkIntStubsPtr->tkDestroyRegion) /* 115 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkDestroyRegion +#define TkDestroyRegion \ + (tkIntStubsPtr->tkDestroyRegion) /* 115 */ +#endif +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +#ifndef TkIntersectRegion +#define TkIntersectRegion \ + (tkIntStubsPtr->tkIntersectRegion) /* 116 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkIntersectRegion +#define TkIntersectRegion \ + (tkIntStubsPtr->tkIntersectRegion) /* 116 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkIntersectRegion +#define TkIntersectRegion \ + (tkIntStubsPtr->tkIntersectRegion) /* 116 */ +#endif +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +#ifndef TkRectInRegion +#define TkRectInRegion \ + (tkIntStubsPtr->tkRectInRegion) /* 117 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkRectInRegion +#define TkRectInRegion \ + (tkIntStubsPtr->tkRectInRegion) /* 117 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkRectInRegion +#define TkRectInRegion \ + (tkIntStubsPtr->tkRectInRegion) /* 117 */ +#endif +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +#ifndef TkSetRegion +#define TkSetRegion \ + (tkIntStubsPtr->tkSetRegion) /* 118 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkSetRegion +#define TkSetRegion \ + (tkIntStubsPtr->tkSetRegion) /* 118 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkSetRegion +#define TkSetRegion \ + (tkIntStubsPtr->tkSetRegion) /* 118 */ +#endif +#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ +#ifndef TkUnionRectWithRegion +#define TkUnionRectWithRegion \ + (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkUnionRectWithRegion +#define TkUnionRectWithRegion \ + (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkUnionRectWithRegion +#define TkUnionRectWithRegion \ + (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ +#endif +#endif /* MAC_OSX_TK */ +/* Slot 120 is reserved */ +#ifdef MAC_TCL +#ifndef TkpCreateNativeBitmap +#define TkpCreateNativeBitmap \ + (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkpCreateNativeBitmap +#define TkpCreateNativeBitmap \ + (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */ +#endif +#endif /* MAC_OSX_TK */ +#ifdef MAC_TCL +#ifndef TkpDefineNativeBitmaps +#define TkpDefineNativeBitmaps \ + (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkpDefineNativeBitmaps +#define TkpDefineNativeBitmaps \ + (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */ +#endif +#endif /* MAC_OSX_TK */ +/* Slot 123 is reserved */ +#ifdef MAC_TCL +#ifndef TkpGetNativeAppBitmap +#define TkpGetNativeAppBitmap \ + (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkpGetNativeAppBitmap +#define TkpGetNativeAppBitmap \ + (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */ +#endif +#endif /* MAC_OSX_TK */ +/* Slot 125 is reserved */ +/* Slot 126 is reserved */ +/* Slot 127 is reserved */ +/* Slot 128 is reserved */ +/* Slot 129 is reserved */ +/* Slot 130 is reserved */ +/* Slot 131 is reserved */ +/* Slot 132 is reserved */ +/* Slot 133 is reserved */ +/* Slot 134 is reserved */ +#ifndef TkpDrawHighlightBorder +#define TkpDrawHighlightBorder \ + (tkIntStubsPtr->tkpDrawHighlightBorder) /* 135 */ +#endif +#ifndef TkSetFocusWin +#define TkSetFocusWin \ + (tkIntStubsPtr->tkSetFocusWin) /* 136 */ +#endif +#ifndef TkpSetKeycodeAndState +#define TkpSetKeycodeAndState \ + (tkIntStubsPtr->tkpSetKeycodeAndState) /* 137 */ +#endif +#ifndef TkpGetKeySym +#define TkpGetKeySym \ + (tkIntStubsPtr->tkpGetKeySym) /* 138 */ +#endif +#ifndef TkpInitKeymapInfo +#define TkpInitKeymapInfo \ + (tkIntStubsPtr->tkpInitKeymapInfo) /* 139 */ +#endif +#ifndef TkPhotoGetValidRegion +#define TkPhotoGetValidRegion \ + (tkIntStubsPtr->tkPhotoGetValidRegion) /* 140 */ +#endif +#ifndef TkWmStackorderToplevel +#define TkWmStackorderToplevel \ + (tkIntStubsPtr->tkWmStackorderToplevel) /* 141 */ +#endif +#ifndef TkFocusFree +#define TkFocusFree \ + (tkIntStubsPtr->tkFocusFree) /* 142 */ +#endif +#ifndef TkClipCleanup +#define TkClipCleanup \ + (tkIntStubsPtr->tkClipCleanup) /* 143 */ +#endif +#ifndef TkGCCleanup +#define TkGCCleanup \ + (tkIntStubsPtr->tkGCCleanup) /* 144 */ +#endif +#ifdef __WIN32__ +#ifndef TkSubtractRegion +#define TkSubtractRegion \ + (tkIntStubsPtr->tkSubtractRegion) /* 145 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkSubtractRegion +#define TkSubtractRegion \ + (tkIntStubsPtr->tkSubtractRegion) /* 145 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkSubtractRegion +#define TkSubtractRegion \ + (tkIntStubsPtr->tkSubtractRegion) /* 145 */ +#endif +#endif /* MAC_OSX_TK */ +#ifndef TkStylePkgInit +#define TkStylePkgInit \ + (tkIntStubsPtr->tkStylePkgInit) /* 146 */ +#endif +#ifndef TkStylePkgFree +#define TkStylePkgFree \ + (tkIntStubsPtr->tkStylePkgFree) /* 147 */ +#endif +#ifndef TkToplevelWindowForCommand +#define TkToplevelWindowForCommand \ + (tkIntStubsPtr->tkToplevelWindowForCommand) /* 148 */ +#endif +#ifndef TkGetOptionSpec +#define TkGetOptionSpec \ + (tkIntStubsPtr->tkGetOptionSpec) /* 149 */ +#endif + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINTDECLS */ + diff --git a/Utilities/TclTk/internals/tk8.4/tkIntPlatDecls.h b/Utilities/TclTk/internals/tk8.4/tkIntPlatDecls.h new file mode 100644 index 0000000..7438091 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkIntPlatDecls.h @@ -0,0 +1,1227 @@ +/* + * tkIntPlatDecls.h -- + * + * This file contains the declarations for all platform dependent + * unsupported functions that are exported by the Tk library. These + * interfaces are not guaranteed to remain the same between + * versions. Use at your own risk. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * All rights reserved. + * + * RCS: @(#) $Id: tkIntPlatDecls.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKINTPLATDECLS +#define _TKINTPLATDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tkInt.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +#ifdef __WIN32__ +/* 0 */ +EXTERN char * TkAlignImageData _ANSI_ARGS_((XImage * image, + int alignment, int bitOrder)); +/* Slot 1 is reserved */ +/* 2 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +/* 3 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +/* 4 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 5 */ +EXTERN void TkpPrintWindowId _ANSI_ARGS_((char * buf, + Window window)); +/* 6 */ +EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * string, Window * idPtr)); +/* 7 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +/* 8 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +/* 9 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +/* 10 */ +EXTERN void TkSetPixmapColormap _ANSI_ARGS_((Pixmap pixmap, + Colormap colormap)); +/* 11 */ +EXTERN void TkWinCancelMouseTimer _ANSI_ARGS_((void)); +/* 12 */ +EXTERN void TkWinClipboardRender _ANSI_ARGS_(( + TkDisplay * dispPtr, UINT format)); +/* 13 */ +EXTERN LRESULT TkWinEmbeddedEventProc _ANSI_ARGS_((HWND hwnd, + UINT message, WPARAM wParam, LPARAM lParam)); +/* 14 */ +EXTERN void TkWinFillRect _ANSI_ARGS_((HDC dc, int x, int y, + int width, int height, int pixel)); +/* 15 */ +EXTERN COLORREF TkWinGetBorderPixels _ANSI_ARGS_((Tk_Window tkwin, + Tk_3DBorder border, int which)); +/* 16 */ +EXTERN HDC TkWinGetDrawableDC _ANSI_ARGS_((Display * display, + Drawable d, TkWinDCState* state)); +/* 17 */ +EXTERN int TkWinGetModifierState _ANSI_ARGS_((void)); +/* 18 */ +EXTERN HPALETTE TkWinGetSystemPalette _ANSI_ARGS_((void)); +/* 19 */ +EXTERN HWND TkWinGetWrapperWindow _ANSI_ARGS_((Tk_Window tkwin)); +/* 20 */ +EXTERN int TkWinHandleMenuEvent _ANSI_ARGS_((HWND * phwnd, + UINT * pMessage, WPARAM * pwParam, + LPARAM * plParam, LRESULT * plResult)); +/* 21 */ +EXTERN int TkWinIndexOfColor _ANSI_ARGS_((XColor * colorPtr)); +/* 22 */ +EXTERN void TkWinReleaseDrawableDC _ANSI_ARGS_((Drawable d, + HDC hdc, TkWinDCState* state)); +/* 23 */ +EXTERN LRESULT TkWinResendEvent _ANSI_ARGS_((WNDPROC wndproc, + HWND hwnd, XEvent * eventPtr)); +/* 24 */ +EXTERN HPALETTE TkWinSelectPalette _ANSI_ARGS_((HDC dc, + Colormap colormap)); +/* 25 */ +EXTERN void TkWinSetMenu _ANSI_ARGS_((Tk_Window tkwin, + HMENU hMenu)); +/* 26 */ +EXTERN void TkWinSetWindowPos _ANSI_ARGS_((HWND hwnd, + HWND siblingHwnd, int pos)); +/* 27 */ +EXTERN void TkWinWmCleanup _ANSI_ARGS_((HINSTANCE hInstance)); +/* 28 */ +EXTERN void TkWinXCleanup _ANSI_ARGS_((HINSTANCE hInstance)); +/* 29 */ +EXTERN void TkWinXInit _ANSI_ARGS_((HINSTANCE hInstance)); +/* 30 */ +EXTERN void TkWinSetForegroundWindow _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 31 */ +EXTERN void TkWinDialogDebug _ANSI_ARGS_((int debug)); +/* 32 */ +EXTERN Tcl_Obj * TkWinGetMenuSystemDefault _ANSI_ARGS_(( + Tk_Window tkwin, CONST char * dbName, + CONST char * className)); +/* 33 */ +EXTERN int TkWinGetPlatformId _ANSI_ARGS_((void)); +/* 34 */ +EXTERN void TkWinSetHINSTANCE _ANSI_ARGS_((HINSTANCE hInstance)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +/* Slot 1 is reserved */ +/* Slot 2 is reserved */ +/* 3 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +/* Slot 4 is reserved */ +/* 5 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 6 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +/* 7 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +/* 8 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +/* Slot 9 is reserved */ +/* 10 */ +EXTERN void TkAboutDlg _ANSI_ARGS_((void)); +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ +/* 13 */ +EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr)); +/* 14 */ +EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, + Window window, unsigned int state)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); +/* Slot 17 is reserved */ +/* 18 */ +EXTERN unsigned int TkMacButtonKeyState _ANSI_ARGS_((void)); +/* 19 */ +EXTERN void TkMacClearMenubarActive _ANSI_ARGS_((void)); +/* Slot 20 is reserved */ +/* 21 */ +EXTERN int TkMacDispatchMenuEvent _ANSI_ARGS_((int menuID, + int index)); +/* 22 */ +EXTERN void TkMacInstallCursor _ANSI_ARGS_((int resizeOverride)); +/* Slot 23 is reserved */ +/* 24 */ +EXTERN void TkMacHandleTearoffMenu _ANSI_ARGS_((void)); +/* Slot 25 is reserved */ +/* Slot 26 is reserved */ +/* 27 */ +EXTERN void TkMacDoHLEvent _ANSI_ARGS_((EventRecord * theEvent)); +/* Slot 28 is reserved */ +/* 29 */ +EXTERN Time TkMacGenerateTime _ANSI_ARGS_((void)); +/* Slot 30 is reserved */ +/* 31 */ +EXTERN TkWindow * TkMacGetScrollbarGrowWindow _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 32 */ +EXTERN Window TkMacGetXWindow _ANSI_ARGS_((WindowRef macWinPtr)); +/* 33 */ +EXTERN int TkMacGrowToplevel _ANSI_ARGS_((WindowRef whichWindow, + Point start)); +/* 34 */ +EXTERN void TkMacHandleMenuSelect _ANSI_ARGS_((long mResult, + int optionKeyPressed)); +/* Slot 35 is reserved */ +/* Slot 36 is reserved */ +/* Slot 37 is reserved */ +/* 38 */ +EXTERN void TkMacInvalidateWindow _ANSI_ARGS_(( + MacDrawable * macWin, int flag)); +/* 39 */ +EXTERN int TkMacIsCharacterMissing _ANSI_ARGS_((Tk_Font tkfont, + unsigned int searchChar)); +/* 40 */ +EXTERN void TkMacMakeRealWindowExist _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 41 */ +EXTERN BitMapPtr TkMacMakeStippleMap _ANSI_ARGS_((Drawable d1, + Drawable d2)); +/* 42 */ +EXTERN void TkMacMenuClick _ANSI_ARGS_((void)); +/* 43 */ +EXTERN void TkMacRegisterOffScreenWindow _ANSI_ARGS_(( + Window window, GWorldPtr portPtr)); +/* 44 */ +EXTERN int TkMacResizable _ANSI_ARGS_((TkWindow * winPtr)); +/* Slot 45 is reserved */ +/* 46 */ +EXTERN void TkMacSetHelpMenuItemCount _ANSI_ARGS_((void)); +/* 47 */ +EXTERN void TkMacSetScrollbarGrow _ANSI_ARGS_((TkWindow * winPtr, + int flag)); +/* 48 */ +EXTERN void TkMacSetUpClippingRgn _ANSI_ARGS_((Drawable drawable)); +/* 49 */ +EXTERN void TkMacSetUpGraphicsPort _ANSI_ARGS_((GC gc)); +/* 50 */ +EXTERN void TkMacUpdateClipRgn _ANSI_ARGS_((TkWindow * winPtr)); +/* 51 */ +EXTERN void TkMacUnregisterMacWindow _ANSI_ARGS_(( + GWorldPtr portPtr)); +/* 52 */ +EXTERN int TkMacUseMenuID _ANSI_ARGS_((short macID)); +/* 53 */ +EXTERN RgnHandle TkMacVisableClipRgn _ANSI_ARGS_((TkWindow * winPtr)); +/* 54 */ +EXTERN void TkMacWinBounds _ANSI_ARGS_((TkWindow * winPtr, + Rect * geometry)); +/* 55 */ +EXTERN void TkMacWindowOffset _ANSI_ARGS_((WindowRef wRef, + int * xOffset, int * yOffset)); +/* Slot 56 is reserved */ +/* 57 */ +EXTERN int TkSetMacColor _ANSI_ARGS_((unsigned long pixel, + RGBColor * macColor)); +/* 58 */ +EXTERN void TkSetWMName _ANSI_ARGS_((TkWindow * winPtr, + Tk_Uid titleUid)); +/* 59 */ +EXTERN void TkSuspendClipboard _ANSI_ARGS_((void)); +/* Slot 60 is reserved */ +/* 61 */ +EXTERN int TkMacZoomToplevel _ANSI_ARGS_((WindowPtr whichWindow, + Point where, short zoomPart)); +/* 62 */ +EXTERN Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin, + int rootX, int rootY, int * newX, int * newY)); +/* 63 */ +EXTERN MacDrawable * TkMacContainerId _ANSI_ARGS_((TkWindow * winPtr)); +/* 64 */ +EXTERN MacDrawable * TkMacGetHostToplevel _ANSI_ARGS_((TkWindow * winPtr)); +/* 65 */ +EXTERN void TkMacPreprocessMenu _ANSI_ARGS_((void)); +/* 66 */ +EXTERN int TkpIsWindowFloating _ANSI_ARGS_((WindowRef window)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 0 */ +EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( + TkWindow * winPtr, int active)); +/* Slot 1 is reserved */ +/* Slot 2 is reserved */ +/* 3 */ +EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr)); +/* 4 */ +EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr)); +/* 5 */ +EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +/* 6 */ +EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +/* 7 */ +EXTERN void TkAboutDlg _ANSI_ARGS_((void)); +/* 8 */ +EXTERN unsigned int TkMacOSXButtonKeyState _ANSI_ARGS_((void)); +/* 9 */ +EXTERN void TkMacOSXClearMenubarActive _ANSI_ARGS_((void)); +/* 10 */ +EXTERN int TkMacOSXDispatchMenuEvent _ANSI_ARGS_((int menuID, + int index)); +/* 11 */ +EXTERN void TkMacOSXInstallCursor _ANSI_ARGS_(( + int resizeOverride)); +/* 12 */ +EXTERN void TkMacOSXHandleTearoffMenu _ANSI_ARGS_((void)); +/* Slot 13 is reserved */ +/* 14 */ +EXTERN int TkMacOSXDoHLEvent _ANSI_ARGS_(( + EventRecord * theEvent)); +/* Slot 15 is reserved */ +/* 16 */ +EXTERN Window TkMacOSXGetXWindow _ANSI_ARGS_((WindowRef macWinPtr)); +/* 17 */ +EXTERN int TkMacOSXGrowToplevel _ANSI_ARGS_(( + WindowRef whichWindow, Point start)); +/* 18 */ +EXTERN void TkMacOSXHandleMenuSelect _ANSI_ARGS_((long mResult, + int optionKeyPressed)); +/* Slot 19 is reserved */ +/* Slot 20 is reserved */ +/* 21 */ +EXTERN void TkMacOSXInvalidateWindow _ANSI_ARGS_(( + MacDrawable * macWin, int flag)); +/* 22 */ +EXTERN int TkMacOSXIsCharacterMissing _ANSI_ARGS_(( + Tk_Font tkfont, unsigned int searchChar)); +/* 23 */ +EXTERN void TkMacOSXMakeRealWindowExist _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 24 */ +EXTERN BitMapPtr TkMacOSXMakeStippleMap _ANSI_ARGS_((Drawable d1, + Drawable d2)); +/* 25 */ +EXTERN void TkMacOSXMenuClick _ANSI_ARGS_((void)); +/* 26 */ +EXTERN void TkMacOSXRegisterOffScreenWindow _ANSI_ARGS_(( + Window window, GWorldPtr portPtr)); +/* 27 */ +EXTERN int TkMacOSXResizable _ANSI_ARGS_((TkWindow * winPtr)); +/* 28 */ +EXTERN void TkMacOSXSetHelpMenuItemCount _ANSI_ARGS_((void)); +/* 29 */ +EXTERN void TkMacOSXSetScrollbarGrow _ANSI_ARGS_(( + TkWindow * winPtr, int flag)); +/* 30 */ +EXTERN void TkMacOSXSetUpClippingRgn _ANSI_ARGS_(( + Drawable drawable)); +/* 31 */ +EXTERN void TkMacOSXSetUpGraphicsPort _ANSI_ARGS_((GC gc, + GWorldPtr destPort)); +/* 32 */ +EXTERN void TkMacOSXUpdateClipRgn _ANSI_ARGS_((TkWindow * winPtr)); +/* 33 */ +EXTERN void TkMacOSXUnregisterMacWindow _ANSI_ARGS_(( + WindowRef portPtr)); +/* 34 */ +EXTERN int TkMacOSXUseMenuID _ANSI_ARGS_((short macID)); +/* 35 */ +EXTERN RgnHandle TkMacOSXVisableClipRgn _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 36 */ +EXTERN void TkMacOSXWinBounds _ANSI_ARGS_((TkWindow * winPtr, + Rect * geometry)); +/* 37 */ +EXTERN void TkMacOSXWindowOffset _ANSI_ARGS_((WindowRef wRef, + int * xOffset, int * yOffset)); +/* 38 */ +EXTERN int TkSetMacColor _ANSI_ARGS_((unsigned long pixel, + RGBColor * macColor)); +/* 39 */ +EXTERN void TkSetWMName _ANSI_ARGS_((TkWindow * winPtr, + Tk_Uid titleUid)); +/* 40 */ +EXTERN void TkSuspendClipboard _ANSI_ARGS_((void)); +/* 41 */ +EXTERN int TkMacOSXZoomToplevel _ANSI_ARGS_(( + WindowPtr whichWindow, Point where, + short zoomPart)); +/* 42 */ +EXTERN Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin, + int rootX, int rootY, int * newX, int * newY)); +/* 43 */ +EXTERN MacDrawable * TkMacOSXContainerId _ANSI_ARGS_((TkWindow * winPtr)); +/* 44 */ +EXTERN MacDrawable * TkMacOSXGetHostToplevel _ANSI_ARGS_(( + TkWindow * winPtr)); +/* 45 */ +EXTERN void TkMacOSXPreprocessMenu _ANSI_ARGS_((void)); +/* 46 */ +EXTERN int TkpIsWindowFloating _ANSI_ARGS_((WindowRef window)); +/* 47 */ +EXTERN Tk_Window TkMacOSXGetCapture _ANSI_ARGS_((void)); +/* Slot 48 is reserved */ +/* 49 */ +EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr)); +/* 50 */ +EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, + Window window, unsigned int state)); +/* 51 */ +EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); +/* Slot 52 is reserved */ +/* 53 */ +EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +#endif /* MAC_OSX_TK */ +#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */ +/* 0 */ +EXTERN void TkCreateXEventSource _ANSI_ARGS_((void)); +/* 1 */ +EXTERN void TkFreeWindowId _ANSI_ARGS_((TkDisplay * dispPtr, + Window w)); +/* 2 */ +EXTERN void TkInitXId _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 3 */ +EXTERN int TkpCmapStressed _ANSI_ARGS_((Tk_Window tkwin, + Colormap colormap)); +/* 4 */ +EXTERN void TkpSync _ANSI_ARGS_((Display * display)); +/* 5 */ +EXTERN Window TkUnixContainerId _ANSI_ARGS_((TkWindow * winPtr)); +/* 6 */ +EXTERN int TkUnixDoOneXEvent _ANSI_ARGS_((Tcl_Time * timePtr)); +/* 7 */ +EXTERN void TkUnixSetMenubar _ANSI_ARGS_((Tk_Window tkwin, + Tk_Window menubar)); +/* 8 */ +EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp * interp, + CONST char * string, Window * idPtr)); +/* 9 */ +EXTERN void TkWmCleanup _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 10 */ +EXTERN void TkSendCleanup _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 11 */ +EXTERN void TkFreeXId _ANSI_ARGS_((TkDisplay * dispPtr)); +/* 12 */ +EXTERN int TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr, + int state)); +#endif /* X11 */ + +typedef struct TkIntPlatStubs { + int magic; + struct TkIntPlatStubHooks *hooks; + +#ifdef __WIN32__ + char * (*tkAlignImageData) _ANSI_ARGS_((XImage * image, int alignment, int bitOrder)); /* 0 */ + void *reserved1; + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 2 */ + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 4 */ + void (*tkpPrintWindowId) _ANSI_ARGS_((char * buf, Window window)); /* 5 */ + int (*tkpScanWindowId) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, Window * idPtr)); /* 6 */ + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 7 */ + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 8 */ + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 9 */ + void (*tkSetPixmapColormap) _ANSI_ARGS_((Pixmap pixmap, Colormap colormap)); /* 10 */ + void (*tkWinCancelMouseTimer) _ANSI_ARGS_((void)); /* 11 */ + void (*tkWinClipboardRender) _ANSI_ARGS_((TkDisplay * dispPtr, UINT format)); /* 12 */ + LRESULT (*tkWinEmbeddedEventProc) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); /* 13 */ + void (*tkWinFillRect) _ANSI_ARGS_((HDC dc, int x, int y, int width, int height, int pixel)); /* 14 */ + COLORREF (*tkWinGetBorderPixels) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int which)); /* 15 */ + HDC (*tkWinGetDrawableDC) _ANSI_ARGS_((Display * display, Drawable d, TkWinDCState* state)); /* 16 */ + int (*tkWinGetModifierState) _ANSI_ARGS_((void)); /* 17 */ + HPALETTE (*tkWinGetSystemPalette) _ANSI_ARGS_((void)); /* 18 */ + HWND (*tkWinGetWrapperWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 19 */ + int (*tkWinHandleMenuEvent) _ANSI_ARGS_((HWND * phwnd, UINT * pMessage, WPARAM * pwParam, LPARAM * plParam, LRESULT * plResult)); /* 20 */ + int (*tkWinIndexOfColor) _ANSI_ARGS_((XColor * colorPtr)); /* 21 */ + void (*tkWinReleaseDrawableDC) _ANSI_ARGS_((Drawable d, HDC hdc, TkWinDCState* state)); /* 22 */ + LRESULT (*tkWinResendEvent) _ANSI_ARGS_((WNDPROC wndproc, HWND hwnd, XEvent * eventPtr)); /* 23 */ + HPALETTE (*tkWinSelectPalette) _ANSI_ARGS_((HDC dc, Colormap colormap)); /* 24 */ + void (*tkWinSetMenu) _ANSI_ARGS_((Tk_Window tkwin, HMENU hMenu)); /* 25 */ + void (*tkWinSetWindowPos) _ANSI_ARGS_((HWND hwnd, HWND siblingHwnd, int pos)); /* 26 */ + void (*tkWinWmCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 27 */ + void (*tkWinXCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 28 */ + void (*tkWinXInit) _ANSI_ARGS_((HINSTANCE hInstance)); /* 29 */ + void (*tkWinSetForegroundWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 30 */ + void (*tkWinDialogDebug) _ANSI_ARGS_((int debug)); /* 31 */ + Tcl_Obj * (*tkWinGetMenuSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, CONST char * dbName, CONST char * className)); /* 32 */ + int (*tkWinGetPlatformId) _ANSI_ARGS_((void)); /* 33 */ + void (*tkWinSetHINSTANCE) _ANSI_ARGS_((HINSTANCE hInstance)); /* 34 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 0 */ + void *reserved1; + void *reserved2; + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ + void *reserved4; + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */ + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 6 */ + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 7 */ + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 8 */ + void *reserved9; + void (*tkAboutDlg) _ANSI_ARGS_((void)); /* 10 */ + void *reserved11; + void *reserved12; + Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 13 */ + int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 14 */ + void *reserved15; + void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 16 */ + void *reserved17; + unsigned int (*tkMacButtonKeyState) _ANSI_ARGS_((void)); /* 18 */ + void (*tkMacClearMenubarActive) _ANSI_ARGS_((void)); /* 19 */ + void *reserved20; + int (*tkMacDispatchMenuEvent) _ANSI_ARGS_((int menuID, int index)); /* 21 */ + void (*tkMacInstallCursor) _ANSI_ARGS_((int resizeOverride)); /* 22 */ + void *reserved23; + void (*tkMacHandleTearoffMenu) _ANSI_ARGS_((void)); /* 24 */ + void *reserved25; + void *reserved26; + void (*tkMacDoHLEvent) _ANSI_ARGS_((EventRecord * theEvent)); /* 27 */ + void *reserved28; + Time (*tkMacGenerateTime) _ANSI_ARGS_((void)); /* 29 */ + void *reserved30; + TkWindow * (*tkMacGetScrollbarGrowWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 31 */ + Window (*tkMacGetXWindow) _ANSI_ARGS_((WindowRef macWinPtr)); /* 32 */ + int (*tkMacGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 33 */ + void (*tkMacHandleMenuSelect) _ANSI_ARGS_((long mResult, int optionKeyPressed)); /* 34 */ + void *reserved35; + void *reserved36; + void *reserved37; + void (*tkMacInvalidateWindow) _ANSI_ARGS_((MacDrawable * macWin, int flag)); /* 38 */ + int (*tkMacIsCharacterMissing) _ANSI_ARGS_((Tk_Font tkfont, unsigned int searchChar)); /* 39 */ + void (*tkMacMakeRealWindowExist) _ANSI_ARGS_((TkWindow * winPtr)); /* 40 */ + BitMapPtr (*tkMacMakeStippleMap) _ANSI_ARGS_((Drawable d1, Drawable d2)); /* 41 */ + void (*tkMacMenuClick) _ANSI_ARGS_((void)); /* 42 */ + void (*tkMacRegisterOffScreenWindow) _ANSI_ARGS_((Window window, GWorldPtr portPtr)); /* 43 */ + int (*tkMacResizable) _ANSI_ARGS_((TkWindow * winPtr)); /* 44 */ + void *reserved45; + void (*tkMacSetHelpMenuItemCount) _ANSI_ARGS_((void)); /* 46 */ + void (*tkMacSetScrollbarGrow) _ANSI_ARGS_((TkWindow * winPtr, int flag)); /* 47 */ + void (*tkMacSetUpClippingRgn) _ANSI_ARGS_((Drawable drawable)); /* 48 */ + void (*tkMacSetUpGraphicsPort) _ANSI_ARGS_((GC gc)); /* 49 */ + void (*tkMacUpdateClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 50 */ + void (*tkMacUnregisterMacWindow) _ANSI_ARGS_((GWorldPtr portPtr)); /* 51 */ + int (*tkMacUseMenuID) _ANSI_ARGS_((short macID)); /* 52 */ + RgnHandle (*tkMacVisableClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 53 */ + void (*tkMacWinBounds) _ANSI_ARGS_((TkWindow * winPtr, Rect * geometry)); /* 54 */ + void (*tkMacWindowOffset) _ANSI_ARGS_((WindowRef wRef, int * xOffset, int * yOffset)); /* 55 */ + void *reserved56; + int (*tkSetMacColor) _ANSI_ARGS_((unsigned long pixel, RGBColor * macColor)); /* 57 */ + void (*tkSetWMName) _ANSI_ARGS_((TkWindow * winPtr, Tk_Uid titleUid)); /* 58 */ + void (*tkSuspendClipboard) _ANSI_ARGS_((void)); /* 59 */ + void *reserved60; + int (*tkMacZoomToplevel) _ANSI_ARGS_((WindowPtr whichWindow, Point where, short zoomPart)); /* 61 */ + Tk_Window (*tk_TopCoordsToWindow) _ANSI_ARGS_((Tk_Window tkwin, int rootX, int rootY, int * newX, int * newY)); /* 62 */ + MacDrawable * (*tkMacContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 63 */ + MacDrawable * (*tkMacGetHostToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 64 */ + void (*tkMacPreprocessMenu) _ANSI_ARGS_((void)); /* 65 */ + int (*tkpIsWindowFloating) _ANSI_ARGS_((WindowRef window)); /* 66 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 0 */ + void *reserved1; + void *reserved2; + void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 3 */ + void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 4 */ + void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 5 */ + void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 6 */ + void (*tkAboutDlg) _ANSI_ARGS_((void)); /* 7 */ + unsigned int (*tkMacOSXButtonKeyState) _ANSI_ARGS_((void)); /* 8 */ + void (*tkMacOSXClearMenubarActive) _ANSI_ARGS_((void)); /* 9 */ + int (*tkMacOSXDispatchMenuEvent) _ANSI_ARGS_((int menuID, int index)); /* 10 */ + void (*tkMacOSXInstallCursor) _ANSI_ARGS_((int resizeOverride)); /* 11 */ + void (*tkMacOSXHandleTearoffMenu) _ANSI_ARGS_((void)); /* 12 */ + void *reserved13; + int (*tkMacOSXDoHLEvent) _ANSI_ARGS_((EventRecord * theEvent)); /* 14 */ + void *reserved15; + Window (*tkMacOSXGetXWindow) _ANSI_ARGS_((WindowRef macWinPtr)); /* 16 */ + int (*tkMacOSXGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 17 */ + void (*tkMacOSXHandleMenuSelect) _ANSI_ARGS_((long mResult, int optionKeyPressed)); /* 18 */ + void *reserved19; + void *reserved20; + void (*tkMacOSXInvalidateWindow) _ANSI_ARGS_((MacDrawable * macWin, int flag)); /* 21 */ + int (*tkMacOSXIsCharacterMissing) _ANSI_ARGS_((Tk_Font tkfont, unsigned int searchChar)); /* 22 */ + void (*tkMacOSXMakeRealWindowExist) _ANSI_ARGS_((TkWindow * winPtr)); /* 23 */ + BitMapPtr (*tkMacOSXMakeStippleMap) _ANSI_ARGS_((Drawable d1, Drawable d2)); /* 24 */ + void (*tkMacOSXMenuClick) _ANSI_ARGS_((void)); /* 25 */ + void (*tkMacOSXRegisterOffScreenWindow) _ANSI_ARGS_((Window window, GWorldPtr portPtr)); /* 26 */ + int (*tkMacOSXResizable) _ANSI_ARGS_((TkWindow * winPtr)); /* 27 */ + void (*tkMacOSXSetHelpMenuItemCount) _ANSI_ARGS_((void)); /* 28 */ + void (*tkMacOSXSetScrollbarGrow) _ANSI_ARGS_((TkWindow * winPtr, int flag)); /* 29 */ + void (*tkMacOSXSetUpClippingRgn) _ANSI_ARGS_((Drawable drawable)); /* 30 */ + void (*tkMacOSXSetUpGraphicsPort) _ANSI_ARGS_((GC gc, GWorldPtr destPort)); /* 31 */ + void (*tkMacOSXUpdateClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 32 */ + void (*tkMacOSXUnregisterMacWindow) _ANSI_ARGS_((WindowRef portPtr)); /* 33 */ + int (*tkMacOSXUseMenuID) _ANSI_ARGS_((short macID)); /* 34 */ + RgnHandle (*tkMacOSXVisableClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 35 */ + void (*tkMacOSXWinBounds) _ANSI_ARGS_((TkWindow * winPtr, Rect * geometry)); /* 36 */ + void (*tkMacOSXWindowOffset) _ANSI_ARGS_((WindowRef wRef, int * xOffset, int * yOffset)); /* 37 */ + int (*tkSetMacColor) _ANSI_ARGS_((unsigned long pixel, RGBColor * macColor)); /* 38 */ + void (*tkSetWMName) _ANSI_ARGS_((TkWindow * winPtr, Tk_Uid titleUid)); /* 39 */ + void (*tkSuspendClipboard) _ANSI_ARGS_((void)); /* 40 */ + int (*tkMacOSXZoomToplevel) _ANSI_ARGS_((WindowPtr whichWindow, Point where, short zoomPart)); /* 41 */ + Tk_Window (*tk_TopCoordsToWindow) _ANSI_ARGS_((Tk_Window tkwin, int rootX, int rootY, int * newX, int * newY)); /* 42 */ + MacDrawable * (*tkMacOSXContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 43 */ + MacDrawable * (*tkMacOSXGetHostToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 44 */ + void (*tkMacOSXPreprocessMenu) _ANSI_ARGS_((void)); /* 45 */ + int (*tkpIsWindowFloating) _ANSI_ARGS_((WindowRef window)); /* 46 */ + Tk_Window (*tkMacOSXGetCapture) _ANSI_ARGS_((void)); /* 47 */ + void *reserved48; + Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 49 */ + int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 50 */ + void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 51 */ + void *reserved52; + unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 53 */ +#endif /* MAC_OSX_TK */ +#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */ + void (*tkCreateXEventSource) _ANSI_ARGS_((void)); /* 0 */ + void (*tkFreeWindowId) _ANSI_ARGS_((TkDisplay * dispPtr, Window w)); /* 1 */ + void (*tkInitXId) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 2 */ + int (*tkpCmapStressed) _ANSI_ARGS_((Tk_Window tkwin, Colormap colormap)); /* 3 */ + void (*tkpSync) _ANSI_ARGS_((Display * display)); /* 4 */ + Window (*tkUnixContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */ + int (*tkUnixDoOneXEvent) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 6 */ + void (*tkUnixSetMenubar) _ANSI_ARGS_((Tk_Window tkwin, Tk_Window menubar)); /* 7 */ + int (*tkpScanWindowId) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * string, Window * idPtr)); /* 8 */ + void (*tkWmCleanup) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 9 */ + void (*tkSendCleanup) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 10 */ + void (*tkFreeXId) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 11 */ + int (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 12 */ +#endif /* X11 */ +} TkIntPlatStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkIntPlatStubs *tkIntPlatStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifdef __WIN32__ +#ifndef TkAlignImageData +#define TkAlignImageData \ + (tkIntPlatStubsPtr->tkAlignImageData) /* 0 */ +#endif +/* Slot 1 is reserved */ +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */ +#endif +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntPlatStubsPtr->tkpGetMS) /* 3 */ +#endif +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 4 */ +#endif +#ifndef TkpPrintWindowId +#define TkpPrintWindowId \ + (tkIntPlatStubsPtr->tkpPrintWindowId) /* 5 */ +#endif +#ifndef TkpScanWindowId +#define TkpScanWindowId \ + (tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */ +#endif +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntPlatStubsPtr->tkpSetCapture) /* 7 */ +#endif +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntPlatStubsPtr->tkpSetCursor) /* 8 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 9 */ +#endif +#ifndef TkSetPixmapColormap +#define TkSetPixmapColormap \ + (tkIntPlatStubsPtr->tkSetPixmapColormap) /* 10 */ +#endif +#ifndef TkWinCancelMouseTimer +#define TkWinCancelMouseTimer \ + (tkIntPlatStubsPtr->tkWinCancelMouseTimer) /* 11 */ +#endif +#ifndef TkWinClipboardRender +#define TkWinClipboardRender \ + (tkIntPlatStubsPtr->tkWinClipboardRender) /* 12 */ +#endif +#ifndef TkWinEmbeddedEventProc +#define TkWinEmbeddedEventProc \ + (tkIntPlatStubsPtr->tkWinEmbeddedEventProc) /* 13 */ +#endif +#ifndef TkWinFillRect +#define TkWinFillRect \ + (tkIntPlatStubsPtr->tkWinFillRect) /* 14 */ +#endif +#ifndef TkWinGetBorderPixels +#define TkWinGetBorderPixels \ + (tkIntPlatStubsPtr->tkWinGetBorderPixels) /* 15 */ +#endif +#ifndef TkWinGetDrawableDC +#define TkWinGetDrawableDC \ + (tkIntPlatStubsPtr->tkWinGetDrawableDC) /* 16 */ +#endif +#ifndef TkWinGetModifierState +#define TkWinGetModifierState \ + (tkIntPlatStubsPtr->tkWinGetModifierState) /* 17 */ +#endif +#ifndef TkWinGetSystemPalette +#define TkWinGetSystemPalette \ + (tkIntPlatStubsPtr->tkWinGetSystemPalette) /* 18 */ +#endif +#ifndef TkWinGetWrapperWindow +#define TkWinGetWrapperWindow \ + (tkIntPlatStubsPtr->tkWinGetWrapperWindow) /* 19 */ +#endif +#ifndef TkWinHandleMenuEvent +#define TkWinHandleMenuEvent \ + (tkIntPlatStubsPtr->tkWinHandleMenuEvent) /* 20 */ +#endif +#ifndef TkWinIndexOfColor +#define TkWinIndexOfColor \ + (tkIntPlatStubsPtr->tkWinIndexOfColor) /* 21 */ +#endif +#ifndef TkWinReleaseDrawableDC +#define TkWinReleaseDrawableDC \ + (tkIntPlatStubsPtr->tkWinReleaseDrawableDC) /* 22 */ +#endif +#ifndef TkWinResendEvent +#define TkWinResendEvent \ + (tkIntPlatStubsPtr->tkWinResendEvent) /* 23 */ +#endif +#ifndef TkWinSelectPalette +#define TkWinSelectPalette \ + (tkIntPlatStubsPtr->tkWinSelectPalette) /* 24 */ +#endif +#ifndef TkWinSetMenu +#define TkWinSetMenu \ + (tkIntPlatStubsPtr->tkWinSetMenu) /* 25 */ +#endif +#ifndef TkWinSetWindowPos +#define TkWinSetWindowPos \ + (tkIntPlatStubsPtr->tkWinSetWindowPos) /* 26 */ +#endif +#ifndef TkWinWmCleanup +#define TkWinWmCleanup \ + (tkIntPlatStubsPtr->tkWinWmCleanup) /* 27 */ +#endif +#ifndef TkWinXCleanup +#define TkWinXCleanup \ + (tkIntPlatStubsPtr->tkWinXCleanup) /* 28 */ +#endif +#ifndef TkWinXInit +#define TkWinXInit \ + (tkIntPlatStubsPtr->tkWinXInit) /* 29 */ +#endif +#ifndef TkWinSetForegroundWindow +#define TkWinSetForegroundWindow \ + (tkIntPlatStubsPtr->tkWinSetForegroundWindow) /* 30 */ +#endif +#ifndef TkWinDialogDebug +#define TkWinDialogDebug \ + (tkIntPlatStubsPtr->tkWinDialogDebug) /* 31 */ +#endif +#ifndef TkWinGetMenuSystemDefault +#define TkWinGetMenuSystemDefault \ + (tkIntPlatStubsPtr->tkWinGetMenuSystemDefault) /* 32 */ +#endif +#ifndef TkWinGetPlatformId +#define TkWinGetPlatformId \ + (tkIntPlatStubsPtr->tkWinGetPlatformId) /* 33 */ +#endif +#ifndef TkWinSetHINSTANCE +#define TkWinSetHINSTANCE \ + (tkIntPlatStubsPtr->tkWinSetHINSTANCE) /* 34 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */ +#endif +/* Slot 1 is reserved */ +/* Slot 2 is reserved */ +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntPlatStubsPtr->tkpGetMS) /* 3 */ +#endif +/* Slot 4 is reserved */ +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 5 */ +#endif +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntPlatStubsPtr->tkpSetCapture) /* 6 */ +#endif +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntPlatStubsPtr->tkpSetCursor) /* 7 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 8 */ +#endif +/* Slot 9 is reserved */ +#ifndef TkAboutDlg +#define TkAboutDlg \ + (tkIntPlatStubsPtr->tkAboutDlg) /* 10 */ +#endif +/* Slot 11 is reserved */ +/* Slot 12 is reserved */ +#ifndef TkGetTransientMaster +#define TkGetTransientMaster \ + (tkIntPlatStubsPtr->tkGetTransientMaster) /* 13 */ +#endif +#ifndef TkGenerateButtonEvent +#define TkGenerateButtonEvent \ + (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TkGenWMDestroyEvent +#define TkGenWMDestroyEvent \ + (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 16 */ +#endif +/* Slot 17 is reserved */ +#ifndef TkMacButtonKeyState +#define TkMacButtonKeyState \ + (tkIntPlatStubsPtr->tkMacButtonKeyState) /* 18 */ +#endif +#ifndef TkMacClearMenubarActive +#define TkMacClearMenubarActive \ + (tkIntPlatStubsPtr->tkMacClearMenubarActive) /* 19 */ +#endif +/* Slot 20 is reserved */ +#ifndef TkMacDispatchMenuEvent +#define TkMacDispatchMenuEvent \ + (tkIntPlatStubsPtr->tkMacDispatchMenuEvent) /* 21 */ +#endif +#ifndef TkMacInstallCursor +#define TkMacInstallCursor \ + (tkIntPlatStubsPtr->tkMacInstallCursor) /* 22 */ +#endif +/* Slot 23 is reserved */ +#ifndef TkMacHandleTearoffMenu +#define TkMacHandleTearoffMenu \ + (tkIntPlatStubsPtr->tkMacHandleTearoffMenu) /* 24 */ +#endif +/* Slot 25 is reserved */ +/* Slot 26 is reserved */ +#ifndef TkMacDoHLEvent +#define TkMacDoHLEvent \ + (tkIntPlatStubsPtr->tkMacDoHLEvent) /* 27 */ +#endif +/* Slot 28 is reserved */ +#ifndef TkMacGenerateTime +#define TkMacGenerateTime \ + (tkIntPlatStubsPtr->tkMacGenerateTime) /* 29 */ +#endif +/* Slot 30 is reserved */ +#ifndef TkMacGetScrollbarGrowWindow +#define TkMacGetScrollbarGrowWindow \ + (tkIntPlatStubsPtr->tkMacGetScrollbarGrowWindow) /* 31 */ +#endif +#ifndef TkMacGetXWindow +#define TkMacGetXWindow \ + (tkIntPlatStubsPtr->tkMacGetXWindow) /* 32 */ +#endif +#ifndef TkMacGrowToplevel +#define TkMacGrowToplevel \ + (tkIntPlatStubsPtr->tkMacGrowToplevel) /* 33 */ +#endif +#ifndef TkMacHandleMenuSelect +#define TkMacHandleMenuSelect \ + (tkIntPlatStubsPtr->tkMacHandleMenuSelect) /* 34 */ +#endif +/* Slot 35 is reserved */ +/* Slot 36 is reserved */ +/* Slot 37 is reserved */ +#ifndef TkMacInvalidateWindow +#define TkMacInvalidateWindow \ + (tkIntPlatStubsPtr->tkMacInvalidateWindow) /* 38 */ +#endif +#ifndef TkMacIsCharacterMissing +#define TkMacIsCharacterMissing \ + (tkIntPlatStubsPtr->tkMacIsCharacterMissing) /* 39 */ +#endif +#ifndef TkMacMakeRealWindowExist +#define TkMacMakeRealWindowExist \ + (tkIntPlatStubsPtr->tkMacMakeRealWindowExist) /* 40 */ +#endif +#ifndef TkMacMakeStippleMap +#define TkMacMakeStippleMap \ + (tkIntPlatStubsPtr->tkMacMakeStippleMap) /* 41 */ +#endif +#ifndef TkMacMenuClick +#define TkMacMenuClick \ + (tkIntPlatStubsPtr->tkMacMenuClick) /* 42 */ +#endif +#ifndef TkMacRegisterOffScreenWindow +#define TkMacRegisterOffScreenWindow \ + (tkIntPlatStubsPtr->tkMacRegisterOffScreenWindow) /* 43 */ +#endif +#ifndef TkMacResizable +#define TkMacResizable \ + (tkIntPlatStubsPtr->tkMacResizable) /* 44 */ +#endif +/* Slot 45 is reserved */ +#ifndef TkMacSetHelpMenuItemCount +#define TkMacSetHelpMenuItemCount \ + (tkIntPlatStubsPtr->tkMacSetHelpMenuItemCount) /* 46 */ +#endif +#ifndef TkMacSetScrollbarGrow +#define TkMacSetScrollbarGrow \ + (tkIntPlatStubsPtr->tkMacSetScrollbarGrow) /* 47 */ +#endif +#ifndef TkMacSetUpClippingRgn +#define TkMacSetUpClippingRgn \ + (tkIntPlatStubsPtr->tkMacSetUpClippingRgn) /* 48 */ +#endif +#ifndef TkMacSetUpGraphicsPort +#define TkMacSetUpGraphicsPort \ + (tkIntPlatStubsPtr->tkMacSetUpGraphicsPort) /* 49 */ +#endif +#ifndef TkMacUpdateClipRgn +#define TkMacUpdateClipRgn \ + (tkIntPlatStubsPtr->tkMacUpdateClipRgn) /* 50 */ +#endif +#ifndef TkMacUnregisterMacWindow +#define TkMacUnregisterMacWindow \ + (tkIntPlatStubsPtr->tkMacUnregisterMacWindow) /* 51 */ +#endif +#ifndef TkMacUseMenuID +#define TkMacUseMenuID \ + (tkIntPlatStubsPtr->tkMacUseMenuID) /* 52 */ +#endif +#ifndef TkMacVisableClipRgn +#define TkMacVisableClipRgn \ + (tkIntPlatStubsPtr->tkMacVisableClipRgn) /* 53 */ +#endif +#ifndef TkMacWinBounds +#define TkMacWinBounds \ + (tkIntPlatStubsPtr->tkMacWinBounds) /* 54 */ +#endif +#ifndef TkMacWindowOffset +#define TkMacWindowOffset \ + (tkIntPlatStubsPtr->tkMacWindowOffset) /* 55 */ +#endif +/* Slot 56 is reserved */ +#ifndef TkSetMacColor +#define TkSetMacColor \ + (tkIntPlatStubsPtr->tkSetMacColor) /* 57 */ +#endif +#ifndef TkSetWMName +#define TkSetWMName \ + (tkIntPlatStubsPtr->tkSetWMName) /* 58 */ +#endif +#ifndef TkSuspendClipboard +#define TkSuspendClipboard \ + (tkIntPlatStubsPtr->tkSuspendClipboard) /* 59 */ +#endif +/* Slot 60 is reserved */ +#ifndef TkMacZoomToplevel +#define TkMacZoomToplevel \ + (tkIntPlatStubsPtr->tkMacZoomToplevel) /* 61 */ +#endif +#ifndef Tk_TopCoordsToWindow +#define Tk_TopCoordsToWindow \ + (tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 62 */ +#endif +#ifndef TkMacContainerId +#define TkMacContainerId \ + (tkIntPlatStubsPtr->tkMacContainerId) /* 63 */ +#endif +#ifndef TkMacGetHostToplevel +#define TkMacGetHostToplevel \ + (tkIntPlatStubsPtr->tkMacGetHostToplevel) /* 64 */ +#endif +#ifndef TkMacPreprocessMenu +#define TkMacPreprocessMenu \ + (tkIntPlatStubsPtr->tkMacPreprocessMenu) /* 65 */ +#endif +#ifndef TkpIsWindowFloating +#define TkpIsWindowFloating \ + (tkIntPlatStubsPtr->tkpIsWindowFloating) /* 66 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef TkGenerateActivateEvents +#define TkGenerateActivateEvents \ + (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */ +#endif +/* Slot 1 is reserved */ +/* Slot 2 is reserved */ +#ifndef TkPointerDeadWindow +#define TkPointerDeadWindow \ + (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 3 */ +#endif +#ifndef TkpSetCapture +#define TkpSetCapture \ + (tkIntPlatStubsPtr->tkpSetCapture) /* 4 */ +#endif +#ifndef TkpSetCursor +#define TkpSetCursor \ + (tkIntPlatStubsPtr->tkpSetCursor) /* 5 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 6 */ +#endif +#ifndef TkAboutDlg +#define TkAboutDlg \ + (tkIntPlatStubsPtr->tkAboutDlg) /* 7 */ +#endif +#ifndef TkMacOSXButtonKeyState +#define TkMacOSXButtonKeyState \ + (tkIntPlatStubsPtr->tkMacOSXButtonKeyState) /* 8 */ +#endif +#ifndef TkMacOSXClearMenubarActive +#define TkMacOSXClearMenubarActive \ + (tkIntPlatStubsPtr->tkMacOSXClearMenubarActive) /* 9 */ +#endif +#ifndef TkMacOSXDispatchMenuEvent +#define TkMacOSXDispatchMenuEvent \ + (tkIntPlatStubsPtr->tkMacOSXDispatchMenuEvent) /* 10 */ +#endif +#ifndef TkMacOSXInstallCursor +#define TkMacOSXInstallCursor \ + (tkIntPlatStubsPtr->tkMacOSXInstallCursor) /* 11 */ +#endif +#ifndef TkMacOSXHandleTearoffMenu +#define TkMacOSXHandleTearoffMenu \ + (tkIntPlatStubsPtr->tkMacOSXHandleTearoffMenu) /* 12 */ +#endif +/* Slot 13 is reserved */ +#ifndef TkMacOSXDoHLEvent +#define TkMacOSXDoHLEvent \ + (tkIntPlatStubsPtr->tkMacOSXDoHLEvent) /* 14 */ +#endif +/* Slot 15 is reserved */ +#ifndef TkMacOSXGetXWindow +#define TkMacOSXGetXWindow \ + (tkIntPlatStubsPtr->tkMacOSXGetXWindow) /* 16 */ +#endif +#ifndef TkMacOSXGrowToplevel +#define TkMacOSXGrowToplevel \ + (tkIntPlatStubsPtr->tkMacOSXGrowToplevel) /* 17 */ +#endif +#ifndef TkMacOSXHandleMenuSelect +#define TkMacOSXHandleMenuSelect \ + (tkIntPlatStubsPtr->tkMacOSXHandleMenuSelect) /* 18 */ +#endif +/* Slot 19 is reserved */ +/* Slot 20 is reserved */ +#ifndef TkMacOSXInvalidateWindow +#define TkMacOSXInvalidateWindow \ + (tkIntPlatStubsPtr->tkMacOSXInvalidateWindow) /* 21 */ +#endif +#ifndef TkMacOSXIsCharacterMissing +#define TkMacOSXIsCharacterMissing \ + (tkIntPlatStubsPtr->tkMacOSXIsCharacterMissing) /* 22 */ +#endif +#ifndef TkMacOSXMakeRealWindowExist +#define TkMacOSXMakeRealWindowExist \ + (tkIntPlatStubsPtr->tkMacOSXMakeRealWindowExist) /* 23 */ +#endif +#ifndef TkMacOSXMakeStippleMap +#define TkMacOSXMakeStippleMap \ + (tkIntPlatStubsPtr->tkMacOSXMakeStippleMap) /* 24 */ +#endif +#ifndef TkMacOSXMenuClick +#define TkMacOSXMenuClick \ + (tkIntPlatStubsPtr->tkMacOSXMenuClick) /* 25 */ +#endif +#ifndef TkMacOSXRegisterOffScreenWindow +#define TkMacOSXRegisterOffScreenWindow \ + (tkIntPlatStubsPtr->tkMacOSXRegisterOffScreenWindow) /* 26 */ +#endif +#ifndef TkMacOSXResizable +#define TkMacOSXResizable \ + (tkIntPlatStubsPtr->tkMacOSXResizable) /* 27 */ +#endif +#ifndef TkMacOSXSetHelpMenuItemCount +#define TkMacOSXSetHelpMenuItemCount \ + (tkIntPlatStubsPtr->tkMacOSXSetHelpMenuItemCount) /* 28 */ +#endif +#ifndef TkMacOSXSetScrollbarGrow +#define TkMacOSXSetScrollbarGrow \ + (tkIntPlatStubsPtr->tkMacOSXSetScrollbarGrow) /* 29 */ +#endif +#ifndef TkMacOSXSetUpClippingRgn +#define TkMacOSXSetUpClippingRgn \ + (tkIntPlatStubsPtr->tkMacOSXSetUpClippingRgn) /* 30 */ +#endif +#ifndef TkMacOSXSetUpGraphicsPort +#define TkMacOSXSetUpGraphicsPort \ + (tkIntPlatStubsPtr->tkMacOSXSetUpGraphicsPort) /* 31 */ +#endif +#ifndef TkMacOSXUpdateClipRgn +#define TkMacOSXUpdateClipRgn \ + (tkIntPlatStubsPtr->tkMacOSXUpdateClipRgn) /* 32 */ +#endif +#ifndef TkMacOSXUnregisterMacWindow +#define TkMacOSXUnregisterMacWindow \ + (tkIntPlatStubsPtr->tkMacOSXUnregisterMacWindow) /* 33 */ +#endif +#ifndef TkMacOSXUseMenuID +#define TkMacOSXUseMenuID \ + (tkIntPlatStubsPtr->tkMacOSXUseMenuID) /* 34 */ +#endif +#ifndef TkMacOSXVisableClipRgn +#define TkMacOSXVisableClipRgn \ + (tkIntPlatStubsPtr->tkMacOSXVisableClipRgn) /* 35 */ +#endif +#ifndef TkMacOSXWinBounds +#define TkMacOSXWinBounds \ + (tkIntPlatStubsPtr->tkMacOSXWinBounds) /* 36 */ +#endif +#ifndef TkMacOSXWindowOffset +#define TkMacOSXWindowOffset \ + (tkIntPlatStubsPtr->tkMacOSXWindowOffset) /* 37 */ +#endif +#ifndef TkSetMacColor +#define TkSetMacColor \ + (tkIntPlatStubsPtr->tkSetMacColor) /* 38 */ +#endif +#ifndef TkSetWMName +#define TkSetWMName \ + (tkIntPlatStubsPtr->tkSetWMName) /* 39 */ +#endif +#ifndef TkSuspendClipboard +#define TkSuspendClipboard \ + (tkIntPlatStubsPtr->tkSuspendClipboard) /* 40 */ +#endif +#ifndef TkMacOSXZoomToplevel +#define TkMacOSXZoomToplevel \ + (tkIntPlatStubsPtr->tkMacOSXZoomToplevel) /* 41 */ +#endif +#ifndef Tk_TopCoordsToWindow +#define Tk_TopCoordsToWindow \ + (tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 42 */ +#endif +#ifndef TkMacOSXContainerId +#define TkMacOSXContainerId \ + (tkIntPlatStubsPtr->tkMacOSXContainerId) /* 43 */ +#endif +#ifndef TkMacOSXGetHostToplevel +#define TkMacOSXGetHostToplevel \ + (tkIntPlatStubsPtr->tkMacOSXGetHostToplevel) /* 44 */ +#endif +#ifndef TkMacOSXPreprocessMenu +#define TkMacOSXPreprocessMenu \ + (tkIntPlatStubsPtr->tkMacOSXPreprocessMenu) /* 45 */ +#endif +#ifndef TkpIsWindowFloating +#define TkpIsWindowFloating \ + (tkIntPlatStubsPtr->tkpIsWindowFloating) /* 46 */ +#endif +#ifndef TkMacOSXGetCapture +#define TkMacOSXGetCapture \ + (tkIntPlatStubsPtr->tkMacOSXGetCapture) /* 47 */ +#endif +/* Slot 48 is reserved */ +#ifndef TkGetTransientMaster +#define TkGetTransientMaster \ + (tkIntPlatStubsPtr->tkGetTransientMaster) /* 49 */ +#endif +#ifndef TkGenerateButtonEvent +#define TkGenerateButtonEvent \ + (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 50 */ +#endif +#ifndef TkGenWMDestroyEvent +#define TkGenWMDestroyEvent \ + (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 51 */ +#endif +/* Slot 52 is reserved */ +#ifndef TkpGetMS +#define TkpGetMS \ + (tkIntPlatStubsPtr->tkpGetMS) /* 53 */ +#endif +#endif /* MAC_OSX_TK */ +#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */ +#ifndef TkCreateXEventSource +#define TkCreateXEventSource \ + (tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */ +#endif +#ifndef TkFreeWindowId +#define TkFreeWindowId \ + (tkIntPlatStubsPtr->tkFreeWindowId) /* 1 */ +#endif +#ifndef TkInitXId +#define TkInitXId \ + (tkIntPlatStubsPtr->tkInitXId) /* 2 */ +#endif +#ifndef TkpCmapStressed +#define TkpCmapStressed \ + (tkIntPlatStubsPtr->tkpCmapStressed) /* 3 */ +#endif +#ifndef TkpSync +#define TkpSync \ + (tkIntPlatStubsPtr->tkpSync) /* 4 */ +#endif +#ifndef TkUnixContainerId +#define TkUnixContainerId \ + (tkIntPlatStubsPtr->tkUnixContainerId) /* 5 */ +#endif +#ifndef TkUnixDoOneXEvent +#define TkUnixDoOneXEvent \ + (tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 6 */ +#endif +#ifndef TkUnixSetMenubar +#define TkUnixSetMenubar \ + (tkIntPlatStubsPtr->tkUnixSetMenubar) /* 7 */ +#endif +#ifndef TkpScanWindowId +#define TkpScanWindowId \ + (tkIntPlatStubsPtr->tkpScanWindowId) /* 8 */ +#endif +#ifndef TkWmCleanup +#define TkWmCleanup \ + (tkIntPlatStubsPtr->tkWmCleanup) /* 9 */ +#endif +#ifndef TkSendCleanup +#define TkSendCleanup \ + (tkIntPlatStubsPtr->tkSendCleanup) /* 10 */ +#endif +#ifndef TkFreeXId +#define TkFreeXId \ + (tkIntPlatStubsPtr->tkFreeXId) /* 11 */ +#endif +#ifndef TkpWmSetState +#define TkpWmSetState \ + (tkIntPlatStubsPtr->tkpWmSetState) /* 12 */ +#endif +#endif /* X11 */ + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINTPLATDECLS */ diff --git a/Utilities/TclTk/internals/tk8.4/tkMacDefault.h b/Utilities/TclTk/internals/tk8.4/tkMacDefault.h new file mode 100644 index 0000000..469afaa --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkMacDefault.h @@ -0,0 +1,529 @@ +/* + * tkMacDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacDefault.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKMACDEFAULT +#define _TKMACDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * SELECT_FG - Foreground color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "Black" +#define WHITE "White" + +#define NORMAL_BG "systemWindowBody" +#define ACTIVE_BG "#ececec" +#define SELECT_BG "systemHighlight" +#define SELECT_FG "systemHighlightText" +#define TROUGH "#c3c3c3" +#define INDICATOR "#b03060" +#define DISABLED "#a3a3a3" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR "systemButtonText" +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR "systemButtonFace" +#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +#define DEF_BUTTON_BG_COLOR "systemButtonFace" +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_COMPOUND "none" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +#define DEF_BUTTON_FG "systemButtonText" +#define DEF_CHKRAD_FG DEF_BUTTON_FG +#define DEF_BUTTON_FONT "system" +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT "systemButtonFrame" +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "4" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_OVER_RELIEF "" +#define DEF_BUTTON_PADX "7" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "3" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "flat" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_REPEAT_DELAY "0" +#define DEF_BUTTON_REPEAT_INTERVAL "0" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT_WIDTH "3" +#define DEF_CANVAS_INSERT_BG BLACK +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR BLACK +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_BG_MONO WHITE +/* #define DEF_ENTRY_BORDER_WIDTH "2" */ +#define DEF_ENTRY_BORDER_WIDTH "1" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_DISABLED_BG_COLOR NORMAL_BG +#define DEF_ENTRY_DISABLED_BG_MONO WHITE +#define DEF_ENTRY_DISABLED_FG DISABLED +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT "Helvetica 12" +#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT BLACK +/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */ +#define DEF_ENTRY_HIGHLIGHT_WIDTH "0" +#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +/* #define DEF_ENTRY_INSERT_WIDTH "2" */ +#define DEF_ENTRY_INSERT_WIDTH "1" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_READONLY_BG_MONO WHITE +/* #define DEF_ENTRY_RELIEF "sunken" */ +#define DEF_ENTRY_RELIEF "solid" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "1" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_PADX "0" +#define DEF_FRAME_PADY "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for labelframes: + */ + +#define DEF_LABELFRAME_BORDER_WIDTH "2" +#define DEF_LABELFRAME_CLASS "Labelframe" +#define DEF_LABELFRAME_RELIEF "groove" +#define DEF_LABELFRAME_FG "systemButtonText" +#define DEF_LABELFRAME_FONT "system" +#define DEF_LABELFRAME_TEXT "" +#define DEF_LABELFRAME_LABELANCHOR "nw" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_ACTIVE_STYLE "underline" +#define DEF_LISTBOX_BG_COLOR NORMAL_BG +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "1" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_DISABLED_FG DISABLED +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT "application" +#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "0" +#define DEF_LISTBOX_RELIEF "solid" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "0" +#define DEF_LISTBOX_SELECT_FG_COLOR SELECT_FG +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_STATE "normal" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_COMPOUND "none" +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR "SystemMenuActive" +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "0" +#define DEF_MENU_ACTIVE_FG_COLOR "SystemMenuActiveText" +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR "SystemMenu" +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "0" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR "SystemMenuDisabled" +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT "system" +#define DEF_MENU_FG "SystemMenuText" +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "flat" +#define DEF_MENU_SELECT_COLOR "SystemMenuActive" +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT "system" +#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT BLACK +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +/* #define DEF_MENUBUTTON_JUSTIFY "center" */ +#define DEF_MENUBUTTON_JUSTIFY "left" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FONT "system" +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" + +/* + * Defaults for panedwindows + */ + +#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG +#define DEF_PANEDWINDOW_BG_MONO WHITE +#define DEF_PANEDWINDOW_BORDERWIDTH "2" +#define DEF_PANEDWINDOW_CURSOR "" +#define DEF_PANEDWINDOW_HANDLEPAD "8" +#define DEF_PANEDWINDOW_HANDLESIZE "8" +#define DEF_PANEDWINDOW_HEIGHT "" +#define DEF_PANEDWINDOW_OPAQUERESIZE "0" +#define DEF_PANEDWINDOW_ORIENT "horizontal" +#define DEF_PANEDWINDOW_RELIEF "flat" +#define DEF_PANEDWINDOW_SASHCURSOR "" +#define DEF_PANEDWINDOW_SASHPAD "2" +#define DEF_PANEDWINDOW_SASHRELIEF "raised" +#define DEF_PANEDWINDOW_SASHWIDTH "2" +#define DEF_PANEDWINDOW_SHOWHANDLE "0" +#define DEF_PANEDWINDOW_WIDTH "" + +/* + * Defaults for panedwindow panes + */ + +#define DEF_PANEDWINDOW_PANE_AFTER "" +#define DEF_PANEDWINDOW_PANE_BEFORE "" +#define DEF_PANEDWINDOW_PANE_HEIGHT "" +#define DEF_PANEDWINDOW_PANE_MINSIZE "0" +#define DEF_PANEDWINDOW_PANE_PADX "0" +#define DEF_PANEDWINDOW_PANE_PADY "0" +#define DEF_PANEDWINDOW_PANE_STICKY "nsew" +#define DEF_PANEDWINDOW_PANE_WIDTH "" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT "system" +#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT_WIDTH "0" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +/* #define DEF_SCROLLBAR_BORDER_WIDTH "2" */ +#define DEF_SCROLLBAR_BORDER_WIDTH "0" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT BLACK +/* #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "2" */ +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +/*#define DEF_SCROLLBAR_RELIEF "sunken" */ +#define DEF_SCROLLBAR_RELIEF "flat" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +/*#define DEF_SCROLLBAR_WIDTH "15" */ +#define DEF_SCROLLBAR_WIDTH "16" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_AUTO_SEPARATORS "1" +#define DEF_TEXT_BG_COLOR NORMAL_BG +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "0" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG BLACK +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT "Courier 12" +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT_WIDTH "3" +#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_WIDTH "1" +#define DEF_TEXT_MAX_UNDO "0" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "flat" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "1" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR SELECT_FG +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "solid" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_UNDO "0" +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT "Helvetica 12" + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" +#define DEF_TOPLEVEL_USE "" + +#endif /* _TKMACDEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkMacOSXDefault.h b/Utilities/TclTk/internals/tk8.4/tkMacOSXDefault.h new file mode 100644 index 0000000..58f9cf0 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkMacOSXDefault.h @@ -0,0 +1,546 @@ +/* + * tkMacOSXDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXDefault.h,v 1.1.4.1 2007/02/06 18:52:24 barre Exp $ + */ + +#ifndef _TKMACDEFAULT +#define _TKMACDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * SELECT_FG - Foreground color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "Black" +#define WHITE "White" + +#define NORMAL_BG "systemWindowBody" +#define ACTIVE_BG "#ececec" +#define SELECT_BG "systemHighlight" +#define SELECT_FG "systemHighlightText" +#define TROUGH "#c3c3c3" +#define INDICATOR "#b03060" +#define DISABLED "#a3a3a3" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR "systemButtonText" +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR "systemButtonFace" +#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +//IGR#define DEF_BUTTON_BG_COLOR "systemButtonFace" +#define DEF_BUTTON_BG_COLOR WHITE +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_COMPOUND "none" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +//IGR#define DEF_BUTTON_FG "systemButtonText" +#define DEF_BUTTON_FG BLACK +#define DEF_CHKRAD_FG DEF_BUTTON_FG +#define DEF_BUTTON_FONT "system" +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT "systemButtonFrame" +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "4" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_OVER_RELIEF "" +#define DEF_BUTTON_PADX "12" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "3" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "flat" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_REPEAT_DELAY "0" +#define DEF_BUTTON_REPEAT_INTERVAL "0" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT_WIDTH "3" +#define DEF_CANVAS_INSERT_BG BLACK +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR BLACK +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +/* + * I test the following three values in TkpDrawEntryBorderAndFocus + * to determine whether to use the native entry widget. So if + * you change the defaults to be different from these, then you + * won't get the native widget by default. + */ + +#define MAC_OSX_FOCUS_WIDTH 3 +#define MAC_OSX_ENTRY_BORDER 2 +#define MAC_OSX_ENTRY_RELEIF TK_RELIEF_SUNKEN + +#define DEF_ENTRY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_BG_MONO WHITE +#define DEF_ENTRY_BORDER_WIDTH "2" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_DISABLED_BG_COLOR NORMAL_BG +#define DEF_ENTRY_DISABLED_BG_MONO WHITE +#define DEF_ENTRY_DISABLED_FG DISABLED +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT "Helvetica 12" +#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT BLACK +/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */ +#define DEF_ENTRY_HIGHLIGHT_WIDTH "3" +#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +/* #define DEF_ENTRY_INSERT_WIDTH "2" */ +#define DEF_ENTRY_INSERT_WIDTH "1" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_READONLY_BG_MONO WHITE +#define DEF_ENTRY_RELIEF "sunken" +/* #define DEF_ENTRY_RELIEF "solid" */ +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "1" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_PADX "0" +#define DEF_FRAME_PADY "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for labelframes: + */ + +#define DEF_LABELFRAME_BORDER_WIDTH "2" +#define DEF_LABELFRAME_CLASS "Labelframe" +#define DEF_LABELFRAME_RELIEF "groove" +#define DEF_LABELFRAME_FG "systemButtonText" +#define DEF_LABELFRAME_FONT "system" +#define DEF_LABELFRAME_TEXT "" +#define DEF_LABELFRAME_LABELANCHOR "nw" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_ACTIVE_STYLE "underline" +#define DEF_LISTBOX_BG_COLOR NORMAL_BG +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "1" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_DISABLED_FG DISABLED +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT "application" +#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "0" +#define DEF_LISTBOX_RELIEF "solid" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "0" +#define DEF_LISTBOX_SELECT_FG_COLOR SELECT_FG +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_STATE "normal" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_COMPOUND "none" +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR "SystemMenuActive" +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "0" +#define DEF_MENU_ACTIVE_FG_COLOR "SystemMenuActiveText" +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR "SystemMenu" +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "0" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR "SystemMenuDisabled" +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT "system" +#define DEF_MENU_FG "SystemMenuText" +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "flat" +#define DEF_MENU_SELECT_COLOR "SystemMenuActive" +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" + +/* + * FIXME: Turn the default back to 1 when we make tearoff menus work again. + */ + +#define DEF_MENU_TEAROFF "0" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT "system" +#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT BLACK +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +/* #define DEF_MENUBUTTON_JUSTIFY "center" */ +#define DEF_MENUBUTTON_JUSTIFY "left" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FONT "system" +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" +/* + * Defaults for panedwindows + */ + +#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG +#define DEF_PANEDWINDOW_BG_MONO WHITE +#define DEF_PANEDWINDOW_BORDERWIDTH "2" +#define DEF_PANEDWINDOW_CURSOR "" +#define DEF_PANEDWINDOW_HANDLEPAD "8" +#define DEF_PANEDWINDOW_HANDLESIZE "8" +#define DEF_PANEDWINDOW_HEIGHT "" +#define DEF_PANEDWINDOW_OPAQUERESIZE "0" +#define DEF_PANEDWINDOW_ORIENT "horizontal" +#define DEF_PANEDWINDOW_RELIEF "flat" +#define DEF_PANEDWINDOW_SASHCURSOR "" +#define DEF_PANEDWINDOW_SASHPAD "2" +#define DEF_PANEDWINDOW_SASHRELIEF "raised" +#define DEF_PANEDWINDOW_SASHWIDTH "2" +#define DEF_PANEDWINDOW_SHOWHANDLE "1" +#define DEF_PANEDWINDOW_WIDTH "" + +/* + * Defaults for panedwindow panes + */ + +#define DEF_PANEDWINDOW_PANE_AFTER "" +#define DEF_PANEDWINDOW_PANE_BEFORE "" +#define DEF_PANEDWINDOW_PANE_HEIGHT "" +#define DEF_PANEDWINDOW_PANE_MINSIZE "0" +#define DEF_PANEDWINDOW_PANE_PADX "0" +#define DEF_PANEDWINDOW_PANE_PADY "0" +#define DEF_PANEDWINDOW_PANE_STICKY "nsew" +#define DEF_PANEDWINDOW_PANE_WIDTH "" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT "system" +#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT_WIDTH "0" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +/* #define DEF_SCROLLBAR_BORDER_WIDTH "2" */ +#define DEF_SCROLLBAR_BORDER_WIDTH "0" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT BLACK +/* #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "2" */ +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +/*#define DEF_SCROLLBAR_RELIEF "sunken" */ +#define DEF_SCROLLBAR_RELIEF "flat" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +/*#define DEF_SCROLLBAR_WIDTH "15" */ +#define DEF_SCROLLBAR_WIDTH "16" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_AUTO_SEPARATORS "1" +#define DEF_TEXT_BG_COLOR NORMAL_BG +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "0" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG BLACK +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT "Courier 12" +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT_WIDTH "3" +#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_WIDTH "1" +#define DEF_TEXT_MAX_UNDO "0" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "flat" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "1" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR SELECT_FG +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "solid" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_UNDO "0" +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT "Helvetica 12" + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" +#define DEF_TOPLEVEL_USE "" + +#endif /* _TKMACDEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkMacOSXInt.h b/Utilities/TclTk/internals/tk8.4/tkMacOSXInt.h new file mode 100644 index 0000000..aa6b27c --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkMacOSXInt.h @@ -0,0 +1,157 @@ +/* + * tkMacOSXInt.h -- + * + * Declarations of Macintosh specific shared variables and procedures. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXInt.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKMACINT +#define _TKMACINT + +#ifndef _TKINT +#include "tkInt.h" +#endif + +/* + * Include platform specific public interfaces. + */ + +#ifndef _TKMAC +#include "tkMacOSX.h" +#endif + +#ifndef _TKPORT +#include "tkPort.h" +#endif + +#include + +struct TkWindowPrivate { + TkWindow *winPtr; /* Ptr to tk window or NULL if Pixmap */ + CGrafPtr grafPtr; + ControlRef rootControl; + int xOff; /* X offset from toplevel window */ + int yOff; /* Y offset from toplevel window */ + RgnHandle clipRgn; /* Visable region of window */ + RgnHandle aboveClipRgn; /* Visable region of window & it's children */ + int referenceCount; /* Don't delete toplevel until children are + * gone. */ + struct TkWindowPrivate *toplevel; /* Pointer to the toplevel + * datastruct. */ + int flags; /* Various state see defines below. */ +}; +typedef struct TkWindowPrivate MacDrawable; + +/* + * This list is used to keep track of toplevel windows that have a Mac + * window attached. This is useful for several things, not the least + * of which is maintaining floating windows. + */ + +typedef struct TkMacOSXWindowList { + struct TkMacOSXWindowList *nextPtr; /* The next window in the list. */ + TkWindow *winPtr; /* This window */ +} TkMacOSXWindowList; + +/* + * Defines use for the flags field of the MacDrawable data structure. + */ + +#define TK_SCROLLBAR_GROW 1 +#define TK_CLIP_INVALID 2 +#define TK_HOST_EXISTS 4 +#define TK_DRAWN_UNDER_MENU 8 + +/* + * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags + * This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the + * TkWindow structure for the window, but in the MacWin. This way we can still tell + * what the correct port is after the TKWindow structure has been freed. This + * actually happens when you bind destroy of a toplevel to Destroy of a child. + */ + +/* + * This structure is for handling Netscape-type in process + * embedding where Tk does not control the top-level. It contains + * various functions that are needed by Mac specific routines, like + * TkMacOSXGetDrawablePort. The definitions of the function types + * are in tclMac.h. + */ + +typedef struct { + Tk_MacOSXEmbedRegisterWinProc *registerWinProc; + Tk_MacOSXEmbedGetGrafPortProc *getPortProc; + Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc; + Tk_MacOSXEmbedGetClipProc *getClipProc; + Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc; +} TkMacOSXEmbedHandler; + +extern TkMacOSXEmbedHandler *gMacEmbedHandler; + +/* + * Defines used for TkMacOSXInvalidateWindow + */ + +#define TK_WINDOW_ONLY 0 +#define TK_PARENT_WINDOW 1 + +/* + * Accessor for the privatePtr flags field for the TK_HOST_EXISTS field + */ + +#define TkMacOSXHostToplevelExists(tkwin) \ + (((TkWindow *) (tkwin))->privatePtr->toplevel->flags & TK_HOST_EXISTS) + +/* + * Defines use for the flags argument to TkGenWMConfigureEvent. + */ + +#define TK_LOCATION_CHANGED 1 +#define TK_SIZE_CHANGED 2 +#define TK_BOTH_CHANGED 3 + +/* + * Variables shared among various Mac Tk modules but are not + * exported to the outside world. + */ + +/* + * Globals shared among Macintosh Tk + */ + +extern MenuHandle tkAppleMenu; /* Handle to the Apple Menu */ +extern MenuHandle tkFileMenu; /* Handles to menus */ +extern MenuHandle tkEditMenu; /* Handles to menus */ +extern RgnHandle tkMenuCascadeRgn; /* A region to clip with. */ +extern int tkUseMenuCascadeRgn; /* If this is 1, clipping code + * should intersect tkMenuCascadeRgn + * before drawing occurs. + * tkMenuCascadeRgn will only + * be valid when the value of this + * variable is 1. */ +extern int tkPictureIsOpen; /* If this is 1, we are drawing to a picture + * The clipping should then be done relative + * to the bounds of the picture rather than the window + * As of OS X.0.4, something is seriously wrong: + * The clipping bounds only seem to work if the + * top,left values are 0,0 + * The destination rectangle for CopyBits + * should also have top,left values of 0,0 + */ +extern TkMacOSXWindowList *tkMacOSXWindowListPtr; + /* The list of toplevels */ + +extern Tcl_Encoding TkMacOSXCarbonEncoding; + +extern int TkMacOSXUseAntialiasedText(Tcl_Interp *interp, int enable); + +#include "tkIntPlatDecls.h" + +#endif /* _TKMACINT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkMacOSXPort.h b/Utilities/TclTk/internals/tk8.4/tkMacOSXPort.h new file mode 100644 index 0000000..76399fe --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkMacOSXPort.h @@ -0,0 +1,220 @@ +/* + * tkMacOSXPort.h -- + * + * This file is included by all of the Tk C files. It contains + * information that may be configuration-dependent, such as + * #includes for system include files and a few other things. + * + * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXPort.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKMACPORT +#define _TKMACPORT + +/* + * Macro to use instead of "void" for arguments that must have + * type "void *" in ANSI C; maps them to type "char *" in + * non-ANSI systems. This macro may be used in some of the include + * files below, which is why it is defined here. + */ + +#ifndef VOID +# ifdef __STDC__ +# define VOID void +# else +# define VOID char +# endif +#endif + +#include +#include +#include +#ifdef HAVE_LIMITS_H +# include +#else +# include "../compat/limits.h" +#endif +#include +#include +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include +#endif +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#include +#ifndef _TCL +# include +#endif +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifdef HAVE_UNISTD_H +# include +#else +# include "../compat/unistd.h" +#endif +#include +#include +#include +#include +#include +#include +#include "tkIntXlibDecls.h" + +/* + * The following macro defines the type of the mask arguments to + * select: + */ + +#ifndef NO_FD_SET +# define SELECT_MASK fd_set +#else +# ifndef _AIX + typedef long fd_mask; +# endif +# if defined(_IBMR2) +# define SELECT_MASK void +# else +# define SELECT_MASK int +# endif +#endif + +/* + * The following macro defines the number of fd_masks in an fd_set: + */ + +#ifndef FD_SETSIZE +# ifdef OPEN_MAX +# define FD_SETSIZE OPEN_MAX +# else +# define FD_SETSIZE 256 +# endif +#endif +#if !defined(howmany) +# define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef NFDBITS +# define NFDBITS NBBY*sizeof(fd_mask) +#endif +#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS) + +/* + * Not all systems declare the errno variable in errno.h. so this + * file does it explicitly. + */ + +extern int errno; + +/* + * Define "NBBY" (number of bits per byte) if it's not already defined. + */ + +#ifndef NBBY +# define NBBY 8 +#endif + +/* + * Declarations for various library procedures that may not be declared + * in any other header file. + */ + +#ifndef panic /* In a stubs-aware setting, this could confuse the #define */ +extern void panic _ANSI_ARGS_(TCL_VARARGS(char *, string)); +#endif +#ifndef strcasecmp +extern int strcasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2)); +#endif +#ifndef strncasecmp +extern int strncasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2, size_t n)); +#endif +/* + * Defines for X functions that are used by Tk but are treated as + * no-op functions on the Macintosh. + */ + +#define XFlush(display) +#define XFree(data) {if ((data) != NULL) ckfree((char *) (data));} +#define XGrabServer(display) +#define XNoOp(display) {display->request++;} +#define XUngrabServer(display) +#define XSynchronize(display, bool) {display->request++;} +#define XSync(display, bool) {display->request++;} +#define XVisualIDFromVisual(visual) (visual->visualid) + +/* + * The following functions are not used on the Mac, so we stub them out. + */ + +#define TkFreeWindowId(dispPtr,w) +#define TkInitXId(dispPtr) +#define TkpButtonSetDefaults(specPtr) {} +#define TkpCmapStressed(tkwin,colormap) (0) +#define TkpFreeColor(tkColPtr) +#define TkSetPixmapColormap(p,c) {} +#define TkpSync(display) + +/* + * The following macro returns the pixel value that corresponds to the + * RGB values in the given XColor structure. + */ + +#define PIXEL_MAGIC ((unsigned char) 0x69) +#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \ + | (((p)->red >> 8) & 0xff)) << 8) \ + | (((p)->green >> 8) & 0xff)) << 8) \ + | (((p)->blue >> 8) & 0xff)) + +/* + * This macro stores a representation of the window handle in a string. + * This should perhaps use the real size of an XID. + */ + +#define TkpPrintWindowId(buf,w) \ + sprintf((buf), "0x%x", (unsigned int) (w)) + +/* + * TkpScanWindowId is just an alias for Tcl_GetInt on Unix. + */ + +#define TkpScanWindowId(i,s,wp) \ + Tcl_GetInt((i),(s),(int *) (wp)) + +/* + * Magic pixel values for dynamic (or active) colors. + */ + +#define HIGHLIGHT_PIXEL 31 +#define HIGHLIGHT_TEXT_PIXEL 33 +#define CONTROL_TEXT_PIXEL 35 +#define CONTROL_BODY_PIXEL 37 +#define CONTROL_FRAME_PIXEL 39 +#define WINDOW_BODY_PIXEL 41 +#define MENU_ACTIVE_PIXEL 43 +#define MENU_ACTIVE_TEXT_PIXEL 45 +#define MENU_BACKGROUND_PIXEL 47 +#define MENU_DISABLED_PIXEL 49 +#define MENU_TEXT_PIXEL 51 +#define APPEARANCE_PIXEL 52 + +#endif /* _TKMACPORT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkPlatDecls.h b/Utilities/TclTk/internals/tk8.4/tkPlatDecls.h new file mode 100644 index 0000000..fafb188 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkPlatDecls.h @@ -0,0 +1,300 @@ +/* + * tkPlatDecls.h -- + * + * Declarations of functions in the platform-specific public Tcl API. + * + * Copyright (c) 1998-1999 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkPlatDecls.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKPLATDECLS +#define _TKPLATDECLS + +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * WARNING: This file is automatically generated by the tools/genStubs.tcl + * script. Any modifications to the function declarations below should be made + * in the generic/tk.decls script. + */ + +/* !BEGIN!: Do not edit below this line. */ + +/* + * Exported function declarations: + */ + +#ifdef __WIN32__ +/* 0 */ +EXTERN Window Tk_AttachHWND _ANSI_ARGS_((Tk_Window tkwin, + HWND hwnd)); +/* 1 */ +EXTERN HINSTANCE Tk_GetHINSTANCE _ANSI_ARGS_((void)); +/* 2 */ +EXTERN HWND Tk_GetHWND _ANSI_ARGS_((Window window)); +/* 3 */ +EXTERN Tk_Window Tk_HWNDToWindow _ANSI_ARGS_((HWND hwnd)); +/* 4 */ +EXTERN void Tk_PointerEvent _ANSI_ARGS_((HWND hwnd, int x, int y)); +/* 5 */ +EXTERN int Tk_TranslateWinEvent _ANSI_ARGS_((HWND hwnd, + UINT message, WPARAM wParam, LPARAM lParam, + LRESULT * result)); +#endif /* __WIN32__ */ +#ifdef MAC_TCL +/* 0 */ +EXTERN void Tk_MacSetEmbedHandler _ANSI_ARGS_(( + Tk_MacEmbedRegisterWinProc * registerWinProcPtr, + Tk_MacEmbedGetGrafPortProc * getPortProcPtr, + Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, + Tk_MacEmbedGetClipProc * getClipProc, + Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); +/* 1 */ +EXTERN void Tk_MacTurnOffMenus _ANSI_ARGS_((void)); +/* 2 */ +EXTERN void Tk_MacTkOwnsCursor _ANSI_ARGS_((int tkOwnsIt)); +/* 3 */ +EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp * interp)); +/* 4 */ +EXTERN void TkMacInitAppleEvents _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 5 */ +EXTERN int TkMacConvertEvent _ANSI_ARGS_(( + EventRecord * eventPtr)); +/* 6 */ +EXTERN int TkMacConvertTkEvent _ANSI_ARGS_(( + EventRecord * eventPtr, Window window)); +/* 7 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +/* 8 */ +EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr)); +/* 9 */ +EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void)); +/* 10 */ +EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable)); +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +/* 0 */ +EXTERN void Tk_MacOSXSetEmbedHandler _ANSI_ARGS_(( + Tk_MacOSXEmbedRegisterWinProc * registerWinProcPtr, + Tk_MacOSXEmbedGetGrafPortProc * getPortProcPtr, + Tk_MacOSXEmbedMakeContainerExistProc * containerExistProcPtr, + Tk_MacOSXEmbedGetClipProc * getClipProc, + Tk_MacOSXEmbedGetOffsetInParentProc * getOffsetProc)); +/* 1 */ +EXTERN void Tk_MacOSXTurnOffMenus _ANSI_ARGS_((void)); +/* 2 */ +EXTERN void Tk_MacOSXTkOwnsCursor _ANSI_ARGS_((int tkOwnsIt)); +/* 3 */ +EXTERN void TkMacOSXInitMenus _ANSI_ARGS_((Tcl_Interp * interp)); +/* 4 */ +EXTERN void TkMacOSXInitAppleEvents _ANSI_ARGS_(( + Tcl_Interp * interp)); +/* 5 */ +EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, + int x, int y, int width, int height, + int flags)); +/* 6 */ +EXTERN void TkMacOSXInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr)); +/* 7 */ +EXTERN GWorldPtr TkMacOSXGetDrawablePort _ANSI_ARGS_(( + Drawable drawable)); +/* 8 */ +EXTERN ControlRef TkMacOSXGetRootControl _ANSI_ARGS_(( + Drawable drawable)); +/* 9 */ +EXTERN void Tk_MacOSXSetupTkNotifier _ANSI_ARGS_((void)); +/* 10 */ +EXTERN int Tk_MacOSXIsAppInFront _ANSI_ARGS_((void)); +#endif /* MAC_OSX_TK */ + +typedef struct TkPlatStubs { + int magic; + struct TkPlatStubHooks *hooks; + +#ifdef __WIN32__ + Window (*tk_AttachHWND) _ANSI_ARGS_((Tk_Window tkwin, HWND hwnd)); /* 0 */ + HINSTANCE (*tk_GetHINSTANCE) _ANSI_ARGS_((void)); /* 1 */ + HWND (*tk_GetHWND) _ANSI_ARGS_((Window window)); /* 2 */ + Tk_Window (*tk_HWNDToWindow) _ANSI_ARGS_((HWND hwnd)); /* 3 */ + void (*tk_PointerEvent) _ANSI_ARGS_((HWND hwnd, int x, int y)); /* 4 */ + int (*tk_TranslateWinEvent) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT * result)); /* 5 */ +#endif /* __WIN32__ */ +#ifdef MAC_TCL + void (*tk_MacSetEmbedHandler) _ANSI_ARGS_((Tk_MacEmbedRegisterWinProc * registerWinProcPtr, Tk_MacEmbedGetGrafPortProc * getPortProcPtr, Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, Tk_MacEmbedGetClipProc * getClipProc, Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); /* 0 */ + void (*tk_MacTurnOffMenus) _ANSI_ARGS_((void)); /* 1 */ + void (*tk_MacTkOwnsCursor) _ANSI_ARGS_((int tkOwnsIt)); /* 2 */ + void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 3 */ + void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 4 */ + int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord * eventPtr)); /* 5 */ + int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord * eventPtr, Window window)); /* 6 */ + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 7 */ + void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 8 */ + int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 9 */ + GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 10 */ +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK + void (*tk_MacOSXSetEmbedHandler) _ANSI_ARGS_((Tk_MacOSXEmbedRegisterWinProc * registerWinProcPtr, Tk_MacOSXEmbedGetGrafPortProc * getPortProcPtr, Tk_MacOSXEmbedMakeContainerExistProc * containerExistProcPtr, Tk_MacOSXEmbedGetClipProc * getClipProc, Tk_MacOSXEmbedGetOffsetInParentProc * getOffsetProc)); /* 0 */ + void (*tk_MacOSXTurnOffMenus) _ANSI_ARGS_((void)); /* 1 */ + void (*tk_MacOSXTkOwnsCursor) _ANSI_ARGS_((int tkOwnsIt)); /* 2 */ + void (*tkMacOSXInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 3 */ + void (*tkMacOSXInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 4 */ + void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 5 */ + void (*tkMacOSXInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 6 */ + GWorldPtr (*tkMacOSXGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 7 */ + ControlRef (*tkMacOSXGetRootControl) _ANSI_ARGS_((Drawable drawable)); /* 8 */ + void (*tk_MacOSXSetupTkNotifier) _ANSI_ARGS_((void)); /* 9 */ + int (*tk_MacOSXIsAppInFront) _ANSI_ARGS_((void)); /* 10 */ +#endif /* MAC_OSX_TK */ +} TkPlatStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern TkPlatStubs *tkPlatStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) + +/* + * Inline function declarations: + */ + +#ifdef __WIN32__ +#ifndef Tk_AttachHWND +#define Tk_AttachHWND \ + (tkPlatStubsPtr->tk_AttachHWND) /* 0 */ +#endif +#ifndef Tk_GetHINSTANCE +#define Tk_GetHINSTANCE \ + (tkPlatStubsPtr->tk_GetHINSTANCE) /* 1 */ +#endif +#ifndef Tk_GetHWND +#define Tk_GetHWND \ + (tkPlatStubsPtr->tk_GetHWND) /* 2 */ +#endif +#ifndef Tk_HWNDToWindow +#define Tk_HWNDToWindow \ + (tkPlatStubsPtr->tk_HWNDToWindow) /* 3 */ +#endif +#ifndef Tk_PointerEvent +#define Tk_PointerEvent \ + (tkPlatStubsPtr->tk_PointerEvent) /* 4 */ +#endif +#ifndef Tk_TranslateWinEvent +#define Tk_TranslateWinEvent \ + (tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */ +#endif +#endif /* __WIN32__ */ +#ifdef MAC_TCL +#ifndef Tk_MacSetEmbedHandler +#define Tk_MacSetEmbedHandler \ + (tkPlatStubsPtr->tk_MacSetEmbedHandler) /* 0 */ +#endif +#ifndef Tk_MacTurnOffMenus +#define Tk_MacTurnOffMenus \ + (tkPlatStubsPtr->tk_MacTurnOffMenus) /* 1 */ +#endif +#ifndef Tk_MacTkOwnsCursor +#define Tk_MacTkOwnsCursor \ + (tkPlatStubsPtr->tk_MacTkOwnsCursor) /* 2 */ +#endif +#ifndef TkMacInitMenus +#define TkMacInitMenus \ + (tkPlatStubsPtr->tkMacInitMenus) /* 3 */ +#endif +#ifndef TkMacInitAppleEvents +#define TkMacInitAppleEvents \ + (tkPlatStubsPtr->tkMacInitAppleEvents) /* 4 */ +#endif +#ifndef TkMacConvertEvent +#define TkMacConvertEvent \ + (tkPlatStubsPtr->tkMacConvertEvent) /* 5 */ +#endif +#ifndef TkMacConvertTkEvent +#define TkMacConvertTkEvent \ + (tkPlatStubsPtr->tkMacConvertTkEvent) /* 6 */ +#endif +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkPlatStubsPtr->tkGenWMConfigureEvent) /* 7 */ +#endif +#ifndef TkMacInvalClipRgns +#define TkMacInvalClipRgns \ + (tkPlatStubsPtr->tkMacInvalClipRgns) /* 8 */ +#endif +#ifndef TkMacHaveAppearance +#define TkMacHaveAppearance \ + (tkPlatStubsPtr->tkMacHaveAppearance) /* 9 */ +#endif +#ifndef TkMacGetDrawablePort +#define TkMacGetDrawablePort \ + (tkPlatStubsPtr->tkMacGetDrawablePort) /* 10 */ +#endif +#endif /* MAC_TCL */ +#ifdef MAC_OSX_TK +#ifndef Tk_MacOSXSetEmbedHandler +#define Tk_MacOSXSetEmbedHandler \ + (tkPlatStubsPtr->tk_MacOSXSetEmbedHandler) /* 0 */ +#endif +#ifndef Tk_MacOSXTurnOffMenus +#define Tk_MacOSXTurnOffMenus \ + (tkPlatStubsPtr->tk_MacOSXTurnOffMenus) /* 1 */ +#endif +#ifndef Tk_MacOSXTkOwnsCursor +#define Tk_MacOSXTkOwnsCursor \ + (tkPlatStubsPtr->tk_MacOSXTkOwnsCursor) /* 2 */ +#endif +#ifndef TkMacOSXInitMenus +#define TkMacOSXInitMenus \ + (tkPlatStubsPtr->tkMacOSXInitMenus) /* 3 */ +#endif +#ifndef TkMacOSXInitAppleEvents +#define TkMacOSXInitAppleEvents \ + (tkPlatStubsPtr->tkMacOSXInitAppleEvents) /* 4 */ +#endif +#ifndef TkGenWMConfigureEvent +#define TkGenWMConfigureEvent \ + (tkPlatStubsPtr->tkGenWMConfigureEvent) /* 5 */ +#endif +#ifndef TkMacOSXInvalClipRgns +#define TkMacOSXInvalClipRgns \ + (tkPlatStubsPtr->tkMacOSXInvalClipRgns) /* 6 */ +#endif +#ifndef TkMacOSXGetDrawablePort +#define TkMacOSXGetDrawablePort \ + (tkPlatStubsPtr->tkMacOSXGetDrawablePort) /* 7 */ +#endif +#ifndef TkMacOSXGetRootControl +#define TkMacOSXGetRootControl \ + (tkPlatStubsPtr->tkMacOSXGetRootControl) /* 8 */ +#endif +#ifndef Tk_MacOSXSetupTkNotifier +#define Tk_MacOSXSetupTkNotifier \ + (tkPlatStubsPtr->tk_MacOSXSetupTkNotifier) /* 9 */ +#endif +#ifndef Tk_MacOSXIsAppInFront +#define Tk_MacOSXIsAppInFront \ + (tkPlatStubsPtr->tk_MacOSXIsAppInFront) /* 10 */ +#endif +#endif /* MAC_OSX_TK */ + +#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ + +/* !END!: Do not edit above this line. */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKPLATDECLS */ diff --git a/Utilities/TclTk/internals/tk8.4/tkPort.h b/Utilities/TclTk/internals/tk8.4/tkPort.h new file mode 100644 index 0000000..b6526cc --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkPort.h @@ -0,0 +1,38 @@ +/* + * tkPort.h -- + * + * This header file handles porting issues that occur because of + * differences between systems. It reads in platform specific + * portability files. + * + * Copyright (c) 1995 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkPort.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKPORT +#define _TKPORT + +#ifndef _TK +#include "tk.h" +#endif +#ifndef _TCL +#include "tcl.h" +#endif + +#if defined(__WIN32__) || defined(_WIN32) +# include "tkWinPort.h" +#else +# if defined(MAC_TCL) +# include "tkMacPort.h" +# elif defined(MAC_OSX_TK) +# include "tkMacOSXPort.h" +# else +# include "tkUnixPort.h" +# endif +#endif + +#endif /* _TKPORT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkUnixDefault.h b/Utilities/TclTk/internals/tk8.4/tkUnixDefault.h new file mode 100644 index 0000000..58d4d7f --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkUnixDefault.h @@ -0,0 +1,519 @@ +/* + * tkUnixDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkUnixDefault.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKUNIXDEFAULT +#define _TKUNIXDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "Black" +#define WHITE "White" + +#define NORMAL_BG "#d9d9d9" +#define ACTIVE_BG "#ececec" +#define SELECT_BG "#c3c3c3" +#define TROUGH "#c3c3c3" +#define INDICATOR "#b03060" +#define DISABLED "#a3a3a3" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +#define DEF_BUTTON_BG_COLOR NORMAL_BG +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMPOUND "none" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +#define DEF_BUTTON_FG BLACK +#define DEF_CHKRAD_FG DEF_BUTTON_FG +#define DEF_BUTTON_FONT "Helvetica -12 bold" +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT BLACK +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "1" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_OVER_RELIEF "" +#define DEF_BUTTON_PADX "3m" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "1m" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "raised" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_REPEAT_DELAY "0" +#define DEF_BUTTON_REPEAT_INTERVAL "0" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT_WIDTH "1" +#define DEF_CANVAS_INSERT_BG BLACK +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR BLACK +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_BG_MONO WHITE +#define DEF_ENTRY_BORDER_WIDTH "2" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_DISABLED_BG_COLOR NORMAL_BG +#define DEF_ENTRY_DISABLED_BG_MONO WHITE +#define DEF_ENTRY_DISABLED_FG DISABLED +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT "Helvetica -12" +#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT BLACK +#define DEF_ENTRY_HIGHLIGHT_WIDTH "1" +#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +#define DEF_ENTRY_INSERT_WIDTH "2" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_READONLY_BG_MONO WHITE +#define DEF_ENTRY_RELIEF "sunken" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "1" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR BLACK +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_LABEL "" +#define DEF_FRAME_PADX "0" +#define DEF_FRAME_PADY "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for labelframes: + */ + +#define DEF_LABELFRAME_BORDER_WIDTH "2" +#define DEF_LABELFRAME_CLASS "Labelframe" +#define DEF_LABELFRAME_RELIEF "groove" +#define DEF_LABELFRAME_FG BLACK +#define DEF_LABELFRAME_FONT "Helvetica -12 bold" +#define DEF_LABELFRAME_TEXT "" +#define DEF_LABELFRAME_LABELANCHOR "nw" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_ACTIVE_STYLE "underline" +#define DEF_LISTBOX_BG_COLOR NORMAL_BG +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "2" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_DISABLED_FG DISABLED +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT "Helvetica -12 bold" +#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1" +#define DEF_LISTBOX_RELIEF "sunken" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "1" +#define DEF_LISTBOX_SELECT_FG_COLOR BLACK +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_STATE "normal" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_COMPOUND "none" +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "2" +#define DEF_MENU_ACTIVE_FG_COLOR BLACK +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR NORMAL_BG +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "2" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR DISABLED +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT "Helvetica -12 bold" +#define DEF_MENU_FG BLACK +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "raised" +#define DEF_MENU_SELECT_COLOR INDICATOR +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT "Helvetica -12 bold" +#define DEF_MENUBUTTON_FG BLACK +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT BLACK +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +#define DEF_MENUBUTTON_JUSTIFY "center" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FONT "Helvetica -12 bold" +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" + +/* + * Defaults for panedwindows + */ + +#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG +#define DEF_PANEDWINDOW_BG_MONO WHITE +#define DEF_PANEDWINDOW_BORDERWIDTH "2" +#define DEF_PANEDWINDOW_CURSOR "" +#define DEF_PANEDWINDOW_HANDLEPAD "8" +#define DEF_PANEDWINDOW_HANDLESIZE "8" +#define DEF_PANEDWINDOW_HEIGHT "" +#define DEF_PANEDWINDOW_OPAQUERESIZE "0" +#define DEF_PANEDWINDOW_ORIENT "horizontal" +#define DEF_PANEDWINDOW_RELIEF "flat" +#define DEF_PANEDWINDOW_SASHCURSOR "" +#define DEF_PANEDWINDOW_SASHPAD "2" +#define DEF_PANEDWINDOW_SASHRELIEF "raised" +#define DEF_PANEDWINDOW_SASHWIDTH "2" +#define DEF_PANEDWINDOW_SHOWHANDLE "1" +#define DEF_PANEDWINDOW_WIDTH "" + +/* + * Defaults for panedwindow panes + */ + +#define DEF_PANEDWINDOW_PANE_AFTER "" +#define DEF_PANEDWINDOW_PANE_BEFORE "" +#define DEF_PANEDWINDOW_PANE_HEIGHT "" +#define DEF_PANEDWINDOW_PANE_MINSIZE "0" +#define DEF_PANEDWINDOW_PANE_PADX "0" +#define DEF_PANEDWINDOW_PANE_PADY "0" +#define DEF_PANEDWINDOW_PANE_STICKY "nsew" +#define DEF_PANEDWINDOW_PANE_WIDTH "" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT "Helvetica -12 bold" +#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT_WIDTH "1" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +#define DEF_SCROLLBAR_BORDER_WIDTH "2" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT BLACK +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "1" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +#define DEF_SCROLLBAR_RELIEF "sunken" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +#define DEF_SCROLLBAR_WIDTH "15" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_AUTO_SEPARATORS "1" +#define DEF_TEXT_BG_COLOR NORMAL_BG +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "2" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG BLACK +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT "Courier -12" +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT_WIDTH "1" +#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_WIDTH "2" +#define DEF_TEXT_MAX_UNDO "0" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "sunken" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "1" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR BLACK +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "raised" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_UNDO "0" +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT "Helvetica -12" + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" +#define DEF_TOPLEVEL_USE "" + +#endif /* _TKUNIXDEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkUnixPort.h b/Utilities/TclTk/internals/tk8.4/tkUnixPort.h new file mode 100644 index 0000000..4431570 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkUnixPort.h @@ -0,0 +1,220 @@ +/* + * tkUnixPort.h -- + * + * This file is included by all of the Tk C files. It contains + * information that may be configuration-dependent, such as + * #includes for system include files and a few other things. + * + * Copyright (c) 1991-1993 The Regents of the University of California. + * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkUnixPort.h,v 1.1.2.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _UNIXPORT +#define _UNIXPORT + +#define __UNIX__ 1 + +/* + * Macro to use instead of "void" for arguments that must have + * type "void *" in ANSI C; maps them to type "char *" in + * non-ANSI systems. This macro may be used in some of the include + * files below, which is why it is defined here. + */ + +#ifndef VOID +# ifdef __STDC__ +# define VOID void +# else +# define VOID char +# endif +#endif + +#include +#include +#include +#ifndef NO_LIMITS_H +# include +#else +# include "../compat/limits.h" +#endif +#include +#include +#ifdef NO_STDLIB_H +# include "../compat/stdlib.h" +#else +# include +#endif +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#include +#ifndef _TCL +# include +#endif +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#ifndef NO_UNISTD_H +# include +#else +# include "../compat/unistd.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +/* + * The following macro defines the type of the mask arguments to + * select: + */ + +#ifndef NO_FD_SET +# define SELECT_MASK fd_set +#else +# ifndef _AIX + typedef long fd_mask; +# endif +# if defined(_IBMR2) +# define SELECT_MASK void +# else +# define SELECT_MASK int +# endif +#endif + +/* + * The following macro defines the number of fd_masks in an fd_set: + */ + +#ifndef FD_SETSIZE +# ifdef OPEN_MAX +# define FD_SETSIZE OPEN_MAX +# else +# define FD_SETSIZE 256 +# endif +#endif +#if !defined(howmany) +# define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#ifndef NFDBITS +# define NFDBITS NBBY*sizeof(fd_mask) +#endif +#define MASK_SIZE howmany(FD_SETSIZE, NFDBITS) + +/* + * Define "NBBY" (number of bits per byte) if it's not already defined. + */ + +#ifndef NBBY +# define NBBY 8 +#endif + +/* + * These macros are just wrappers for the equivalent X Region calls. + */ + +#define TkClipBox(rgn, rect) XClipBox((Region) rgn, rect) +#define TkCreateRegion() (TkRegion) XCreateRegion() +#define TkDestroyRegion(rgn) XDestroyRegion((Region) rgn) +#define TkIntersectRegion(a, b, r) XIntersectRegion((Region) a, \ + (Region) b, (Region) r) +#define TkRectInRegion(r, x, y, w, h) XRectInRegion((Region) r, x, y, w, h) +#define TkSetRegion(d, gc, rgn) XSetRegion(d, gc, (Region) rgn) +#define TkSubtractRegion(a, b, r) XSubtractRegion((Region) a, \ + (Region) b, (Region) r) +#define TkUnionRectWithRegion(rect, src, ret) XUnionRectWithRegion(rect, \ + (Region) src, (Region) ret) + +/* + * The TkPutImage macro strips off the color table information, which isn't + * needed for X. + */ + +#define TkPutImage(colors, ncolors, display, pixels, gc, image, destx, desty, srcx, srcy, width, height) \ + XPutImage(display, pixels, gc, image, destx, desty, srcx, \ + srcy, width, height); + +/* + * Supply macros for seek offsets, if they're not already provided by + * an include file. + */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +#ifndef SEEK_CUR +# define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +# define SEEK_END 2 +#endif + +/* + * Declarations for various library procedures that may not be declared + * in any other header file. + */ + + +/* + * These functions do nothing under Unix, so we just eliminate calls to them. + */ + +#define TkpButtonSetDefaults(specPtr) {} +#define TkpDestroyButton(butPtr) {} +#define TkSelUpdateClipboard(a,b) {} +#define TkSetPixmapColormap(p,c) {} + +/* + * These calls implement native bitmaps which are not supported under + * UNIX. The macros eliminate the calls. + */ + +#define TkpDefineNativeBitmaps() +#define TkpCreateNativeBitmap(display, source) None +#define TkpGetNativeAppBitmap(display, name, w, h) None + +/* + * This macro stores a representation of the window handle in a string. + * This should perhaps use the real size of an XID. + */ + +#define TkpPrintWindowId(buf,w) \ + sprintf((buf), "%#08lx", (unsigned long) (w)) + +/* + * This macro indicates that entry and text widgets should display + * the selection highlight regardless of which window has the focus. + */ + +#define ALWAYS_SHOW_SELECTION + +/* + * The following declaration is used to get access to a private Tcl interface + * that is needed for portability reasons. + */ + +#ifndef _TCLINT +#include +#endif + +#endif /* _UNIXPORT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkWin.h b/Utilities/TclTk/internals/tk8.4/tkWin.h new file mode 100644 index 0000000..292acaa --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkWin.h @@ -0,0 +1,55 @@ +/* + * tkWin.h -- + * + * Declarations of public types and interfaces that are only + * available under Windows. + * + * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWin.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKWIN +#define _TKWIN + +#ifndef _TK +#include +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#ifdef BUILD_tk +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLEXPORT +#endif + +/* + * The following messages are use to communicate between a Tk toplevel + * and its container window. + */ + +#define TK_CLAIMFOCUS (WM_USER) +#define TK_GEOMETRYREQ (WM_USER+1) +#define TK_ATTACHWINDOW (WM_USER+2) +#define TK_DETACHWINDOW (WM_USER+3) + + +/* + *-------------------------------------------------------------- + * + * Exported procedures defined for the Windows platform only. + * + *-------------------------------------------------------------- + */ + +#include "tkPlatDecls.h" + +# undef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKWIN */ diff --git a/Utilities/TclTk/internals/tk8.4/tkWinDefault.h b/Utilities/TclTk/internals/tk8.4/tkWinDefault.h new file mode 100644 index 0000000..b0bacae --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkWinDefault.h @@ -0,0 +1,524 @@ +/* + * tkWinDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinDefault.h,v 1.1.4.1 2007/02/06 18:51:59 barre Exp $ + */ + +#ifndef _TKWINDEFAULT +#define _TKWINDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * DISABLED - Foreground color when widget is disabled. + */ + +#define BLACK "Black" +#define WHITE "White" + +#define CTL_FONT "{MS Sans Serif} 8" +#define NORMAL_BG "SystemButtonFace" +#define NORMAL_FG "SystemButtonText" +#define ACTIVE_BG NORMAL_BG +#define TEXT_FG "SystemWindowText" +#define SELECT_BG "SystemHighlight" +#define SELECT_FG "SystemHighlightText" +#define TROUGH "SystemScrollbar" +#define INDICATOR "SystemWindow" +#define DISABLED "SystemDisabledText" +#define MENU_BG "SystemMenu" +#define MENU_FG "SystemMenuText" +#define HIGHLIGHT "SystemWindowFrame" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR NORMAL_BG +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#define DEF_BUTTON_ACTIVE_FG_COLOR NORMAL_FG +#define DEF_CHKRAD_ACTIVE_FG_COLOR TEXT_FG +#define DEF_BUTTON_ACTIVE_FG_MONO WHITE +#define DEF_BUTTON_BG_COLOR NORMAL_BG +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_COMPOUND "none" +#define DEF_BUTTON_DEFAULT "disabled" +#define DEF_BUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_BUTTON_DISABLED_FG_MONO "" +#define DEF_BUTTON_FG NORMAL_FG +#define DEF_CHKRAD_FG TEXT_FG +#define DEF_BUTTON_FONT CTL_FONT +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT HIGHLIGHT +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "1" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_OVER_RELIEF "" +#define DEF_BUTTON_PADX "1" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "1" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "raised" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_REPEAT_DELAY "0" +#define DEF_BUTTON_REPEAT_INTERVAL "0" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT HIGHLIGHT +#define DEF_CANVAS_HIGHLIGHT_WIDTH "2" +#define DEF_CANVAS_INSERT_BG NORMAL_FG +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#define DEF_CANVAS_SELECT_MONO BLACK +#define DEF_CANVAS_SELECT_BD_COLOR "1" +#define DEF_CANVAS_SELECT_BD_MONO "0" +#define DEF_CANVAS_SELECT_FG_COLOR SELECT_FG +#define DEF_CANVAS_SELECT_FG_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR "SystemWindow" +#define DEF_ENTRY_BG_MONO WHITE +#define DEF_ENTRY_BORDER_WIDTH "2" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_DISABLED_BG_COLOR "SystemButtonFace" +#define DEF_ENTRY_DISABLED_BG_MONO WHITE +#define DEF_ENTRY_DISABLED_FG DISABLED +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT CTL_FONT +#define DEF_ENTRY_FG TEXT_FG +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT HIGHLIGHT +#define DEF_ENTRY_HIGHLIGHT_WIDTH "0" +#define DEF_ENTRY_INSERT_BG TEXT_FG +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +#define DEF_ENTRY_INSERT_WIDTH "2" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_READONLY_BG_COLOR "SystemButtonFace" +#define DEF_ENTRY_READONLY_BG_MONO WHITE +#define DEF_ENTRY_RELIEF "sunken" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "0" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT HIGHLIGHT +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_PADX "0" +#define DEF_FRAME_PADY "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for labelframes: + */ + +#define DEF_LABELFRAME_BORDER_WIDTH "2" +#define DEF_LABELFRAME_CLASS "Labelframe" +#define DEF_LABELFRAME_RELIEF "groove" +#define DEF_LABELFRAME_FG NORMAL_FG +#define DEF_LABELFRAME_FONT CTL_FONT +#define DEF_LABELFRAME_TEXT "" +#define DEF_LABELFRAME_LABELANCHOR "nw" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_ACTIVE_STYLE "underline" +#define DEF_LISTBOX_BG_COLOR "SystemWindow" +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "2" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_DISABLED_FG DISABLED +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT CTL_FONT +#define DEF_LISTBOX_FG NORMAL_FG +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT HIGHLIGHT +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "1" +#define DEF_LISTBOX_RELIEF "sunken" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "0" +#define DEF_LISTBOX_SELECT_FG_COLOR SELECT_FG +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_STATE "normal" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_COMPOUND "none" +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#define DEF_MENU_ACTIVE_BG_COLOR SELECT_BG +#define DEF_MENU_ACTIVE_BG_MONO BLACK +#define DEF_MENU_ACTIVE_BORDER_WIDTH "0" +#define DEF_MENU_ACTIVE_FG_COLOR SELECT_FG +#define DEF_MENU_ACTIVE_FG_MONO WHITE +#define DEF_MENU_BG_COLOR MENU_BG +#define DEF_MENU_BG_MONO WHITE +#define DEF_MENU_BORDER_WIDTH "0" +#define DEF_MENU_CURSOR "arrow" +#define DEF_MENU_DISABLED_FG_COLOR DISABLED +#define DEF_MENU_DISABLED_FG_MONO "" +#define DEF_MENU_FONT CTL_FONT +#define DEF_MENU_FG MENU_FG +#define DEF_MENU_POST_COMMAND "" +#define DEF_MENU_RELIEF "flat" +#define DEF_MENU_SELECT_COLOR MENU_FG +#define DEF_MENU_SELECT_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR NORMAL_FG +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#define DEF_MENUBUTTON_DIRECTION "below" +#define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED +#define DEF_MENUBUTTON_DISABLED_FG_MONO "" +#define DEF_MENUBUTTON_FONT CTL_FONT +#define DEF_MENUBUTTON_FG NORMAL_FG +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT HIGHLIGHT +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +#define DEF_MENUBUTTON_JUSTIFY "center" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG NORMAL_FG +#define DEF_MESSAGE_FONT CTL_FONT +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT HIGHLIGHT +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" + +/* + * Defaults for panedwindows + */ + +#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG +#define DEF_PANEDWINDOW_BG_MONO WHITE +#define DEF_PANEDWINDOW_BORDERWIDTH "2" +#define DEF_PANEDWINDOW_CURSOR "" +#define DEF_PANEDWINDOW_HANDLEPAD "8" +#define DEF_PANEDWINDOW_HANDLESIZE "8" +#define DEF_PANEDWINDOW_HEIGHT "" +#define DEF_PANEDWINDOW_OPAQUERESIZE "0" +#define DEF_PANEDWINDOW_ORIENT "horizontal" +#define DEF_PANEDWINDOW_RELIEF "flat" +#define DEF_PANEDWINDOW_SASHCURSOR "" +#define DEF_PANEDWINDOW_SASHPAD "2" +#define DEF_PANEDWINDOW_SASHRELIEF "raised" +#define DEF_PANEDWINDOW_SASHWIDTH "2" +#define DEF_PANEDWINDOW_SHOWHANDLE "0" +#define DEF_PANEDWINDOW_WIDTH "" + +/* + * Defaults for panedwindow panes + */ + +#define DEF_PANEDWINDOW_PANE_AFTER "" +#define DEF_PANEDWINDOW_PANE_BEFORE "" +#define DEF_PANEDWINDOW_PANE_HEIGHT "" +#define DEF_PANEDWINDOW_PANE_MINSIZE "0" +#define DEF_PANEDWINDOW_PANE_PADX "0" +#define DEF_PANEDWINDOW_PANE_PADY "0" +#define DEF_PANEDWINDOW_PANE_STICKY "nsew" +#define DEF_PANEDWINDOW_PANE_WIDTH "" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT CTL_FONT +#define DEF_SCALE_FG_COLOR NORMAL_FG +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT HIGHLIGHT +#define DEF_SCALE_HIGHLIGHT_WIDTH "2" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +#define DEF_SCROLLBAR_BORDER_WIDTH "0" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT HIGHLIGHT +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +#define DEF_SCROLLBAR_RELIEF "sunken" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL +#define DEF_SCROLLBAR_TROUGH_COLOR TROUGH +#define DEF_SCROLLBAR_TROUGH_MONO WHITE +#define DEF_SCROLLBAR_WIDTH "10" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_AUTO_SEPARATORS "1" +#define DEF_TEXT_BG_COLOR "SystemWindow" +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "2" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG TEXT_FG +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT CTL_FONT +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT HIGHLIGHT +#define DEF_TEXT_HIGHLIGHT_WIDTH "0" +#define DEF_TEXT_INSERT_BG TEXT_FG +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#define DEF_TEXT_INSERT_OFF_TIME "300" +#define DEF_TEXT_INSERT_ON_TIME "600" +#define DEF_TEXT_INSERT_WIDTH "2" +#define DEF_TEXT_MAX_UNDO "0" +#define DEF_TEXT_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "sunken" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "0" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR SELECT_FG +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "flat" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_UNDO "0" +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT CTL_FONT + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" +#define DEF_TOPLEVEL_USE "" + +#endif /* _TKWINDEFAULT */ diff --git a/Utilities/TclTk/internals/tk8.4/tkWinInt.h b/Utilities/TclTk/internals/tk8.4/tkWinInt.h new file mode 100644 index 0000000..182435c --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkWinInt.h @@ -0,0 +1,206 @@ +/* + * tkWinInt.h -- + * + * This file contains declarations that are shared among the + * Windows-specific parts of Tk, but aren't used by the rest of + * Tk. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1998-2000 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinInt.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _TKWININT +#define _TKWININT + +#ifndef _TKINT +#include "tkInt.h" +#endif + +/* + * Include platform specific public interfaces. + */ + +#ifndef _TKWIN +#include "tkWin.h" +#endif + +#ifndef _TKPORT +#include "tkPort.h" +#endif + + +/* + * Define constants missing from older Win32 SDK header files. + */ + +#ifndef WS_EX_TOOLWINDOW +#define WS_EX_TOOLWINDOW 0x00000080L +#endif + +/* + * The TkWinDCState is used to save the state of a device context + * so that it can be restored later. + */ + +typedef struct TkWinDCState { + HPALETTE palette; + int bkmode; +} TkWinDCState; + +/* + * The TkWinDrawable is the internal implementation of an X Drawable (either + * a Window or a Pixmap). The following constants define the valid Drawable + * types. + */ + +#define TWD_BITMAP 1 +#define TWD_WINDOW 2 +#define TWD_WINDC 3 + +typedef struct { + int type; + HWND handle; + TkWindow *winPtr; +} TkWinWindow; + +typedef struct { + int type; + HBITMAP handle; + Colormap colormap; + int depth; +} TkWinBitmap; + +typedef struct { + int type; + HDC hdc; +}TkWinDC; + +typedef union { + int type; + TkWinWindow window; + TkWinBitmap bitmap; + TkWinDC winDC; +} TkWinDrawable; + +/* + * The following macros are used to retrieve internal values from a Drawable. + */ + +#define TkWinGetHWND(w) (((TkWinDrawable *) w)->window.handle) +#define TkWinGetWinPtr(w) (((TkWinDrawable *) w)->window.winPtr) +#define TkWinGetHBITMAP(w) (((TkWinDrawable *) w)->bitmap.handle) +#define TkWinGetColormap(w) (((TkWinDrawable *) w)->bitmap.colormap) +#define TkWinGetHDC(w) (((TkWinDrawable *) w)->winDC.hdc) + +/* + * The following structure is used to encapsulate palette information. + */ + +typedef struct { + HPALETTE palette; /* Palette handle used when drawing. */ + UINT size; /* Number of entries in the palette. */ + int stale; /* 1 if palette needs to be realized, + * otherwise 0. If the palette is stale, + * then an idle handler is scheduled to + * realize the palette. */ + Tcl_HashTable refCounts; /* Hash table of palette entry reference counts + * indexed by pixel value. */ +} TkWinColormap; + +/* + * The following macro retrieves the Win32 palette from a colormap. + */ + +#define TkWinGetPalette(colormap) (((TkWinColormap *) colormap)->palette) + +/* + * The following macros define the class names for Tk Window types. + */ + +#define TK_WIN_TOPLEVEL_CLASS_NAME "TkTopLevel" +#define TK_WIN_CHILD_CLASS_NAME "TkChild" + +/* + * The following variable is a translation table between X gc functions and + * Win32 raster and BitBlt op modes. + */ + +extern int tkpWinRopModes[]; +extern int tkpWinBltModes[]; + +/* + * The following defines are used with TkWinGetBorderPixels to get the + * extra 2 border colors from a Tk_3DBorder. + */ + +#define TK_3D_LIGHT2 TK_3D_DARK_GC+1 +#define TK_3D_DARK2 TK_3D_DARK_GC+2 + +/* + * Internal procedures used by more than one source file. + */ + +#include "tkIntPlatDecls.h" + +/* + * We need to specially add the TkWinChildProc because of the special + * prototype it has (doesn't fit into stubs schema) + */ +#ifdef BUILD_tk +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT +#endif + +EXTERN LRESULT CALLBACK TkWinChildProc _ANSI_ARGS_((HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam)); + +/* + * Special proc needed as tsd accessor function between + * tkWinX.c:GenerateXEvent and tkWinClipboard.c:UpdateClipboard + */ +EXTERN void TkWinUpdatingClipboard(int mode); + +/* + * The following structure keeps track of whether we are using the + * multi-byte or the wide-character interfaces to the operating system. + * System calls should be made through the following function table. + * + * While some system calls need to use this A/W jump-table, it is not + * necessary for all calls to do it, which is why you won't see this + * used throughout the Tk code, but only in key areas. -- hobbs + */ + +typedef struct TkWinProcs { + int useWide; + LRESULT (WINAPI *callWindowProc)(WNDPROC lpPrevWndFunc, HWND hWnd, + UINT Msg, WPARAM wParam, LPARAM lParam); + LRESULT (WINAPI *defWindowProc)(HWND hWnd, UINT Msg, WPARAM wParam, + LPARAM lParam); + ATOM (WINAPI *registerClass)(CONST WNDCLASS *lpWndClass); + BOOL (WINAPI *setWindowText)(HWND hWnd, LPCTSTR lpString); + HWND (WINAPI *createWindowEx)(DWORD dwExStyle, LPCTSTR lpClassName, + LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, + int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, + HINSTANCE hInstance, LPVOID lpParam); +} TkWinProcs; + +EXTERN TkWinProcs *tkWinProcs; + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +/* + * The following allows us to cache these encoding for multiple functions. + */ + + +extern Tcl_Encoding TkWinGetKeyInputEncoding _ANSI_ARGS_((void)); +extern Tcl_Encoding TkWinGetUnicodeEncoding _ANSI_ARGS_((void)); + +#endif /* _TKWININT */ + diff --git a/Utilities/TclTk/internals/tk8.4/tkWinPort.h b/Utilities/TclTk/internals/tk8.4/tkWinPort.h new file mode 100644 index 0000000..945c419 --- /dev/null +++ b/Utilities/TclTk/internals/tk8.4/tkWinPort.h @@ -0,0 +1,135 @@ +/* + * tkWinPort.h -- + * + * This header file handles porting issues that occur because of + * differences between Windows and Unix. It should be the only + * file that contains #ifdefs to handle different flavors of OS. + * + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkWinPort.h,v 1.1 2004/01/07 22:32:39 barre Exp $ + */ + +#ifndef _WINPORT +#define _WINPORT + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Need to block out this include for building extensions with MetroWerks + * compiler for Win32. + */ + +#ifndef __MWERKS__ +#include +#endif + +#include +#ifdef __CYGWIN__ +# define _T(x) L##x +#else +# include +#endif + +#ifdef _MSC_VER +# define hypot _hypot +#endif /* _MSC_VER */ + +#ifndef __GNUC__ +# define strncasecmp strnicmp +# define strcasecmp stricmp +#endif + +#define NBBY 8 + +#ifndef OPEN_MAX +#define OPEN_MAX 32 +#endif + +/* + * The following define causes Tk to use its internal keysym hash table + */ + +#define REDO_KEYSYM_LOOKUP + +/* + * The following macro checks to see whether there is buffered + * input data available for a stdio FILE. + */ + +#ifdef _MSC_VER +# define TK_READ_DATA_PENDING(f) ((f)->_cnt > 0) +#else /* _MSC_VER */ +# define TK_READ_DATA_PENDING(f) ((f)->level > 0) +#endif /* _MSC_VER */ + +/* + * The following stubs implement various calls that don't do anything + * under Windows. + */ + +#define TkFreeWindowId(dispPtr,w) +#define TkInitXId(dispPtr) +#define TkpCmapStressed(tkwin,colormap) (0) +#define XFlush(display) +#define XGrabServer(display) +#define XUngrabServer(display) +#define TkpSync(display) + +/* + * The following functions are implemented as macros under Windows. + */ + +#define XFree(data) {if ((data) != NULL) ckfree((char *) (data));} +#define XNoOp(display) {display->request++;} +#define XSynchronize(display, bool) {display->request++;} +#define XSync(display, bool) {display->request++;} +#define XVisualIDFromVisual(visual) (visual->visualid) + +/* + * The following Tk functions are implemented as macros under Windows. + */ + +#define TkpGetPixel(p) (((((p)->red >> 8) & 0xff) \ + | ((p)->green & 0xff00) | (((p)->blue << 8) & 0xff0000)) | 0x20000000) + +/* + * These calls implement native bitmaps which are not currently + * supported under Windows. The macros eliminate the calls. + */ + +#define TkpDefineNativeBitmaps() +#define TkpCreateNativeBitmap(display, source) None +#define TkpGetNativeAppBitmap(display, name, w, h) None + +/* + * Define timezone for gettimeofday. + */ + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +#ifndef _TCLINT +#include +#endif + +#endif /* _WINPORT */ diff --git a/Utilities/TclTk/lib/CMakeLists.txt b/Utilities/TclTk/lib/CMakeLists.txt new file mode 100644 index 0000000..9b7e873 --- /dev/null +++ b/Utilities/TclTk/lib/CMakeLists.txt @@ -0,0 +1,86 @@ +IF (TCL_LIBRARY AND TK_LIBRARY) + + # Do we need to copy the Tcl/Tk support files to the build directory ? + # Yes if we are building against static Tcl/Tk, and also yes if we + # are building against a shared Tcl/Tk which was provided with no + # support files (turn-key apps like ParaViewComplete for example). + # In the latter case, it's up to the user or the top CMakeLists.txt + # file to set VTK_TCL_TK_COPY_SUPPORT_LIBRARY to ON, since there is no + # reliable way to know that the Tcl/Tk shared lib was provided with + # no support files. + + SET (VTK_TCL_TK_COPY_SUPPORT_LIBRARY ${VTK_TCL_TK_STATIC} CACHE INTERNAL "Very few users should worry about this option. If VTK is built against a static Tcl/Tk lib (see VTK_TCL_TK_STATIC) or a shared Tcl/Tk bundled inside a project with no library support files (ex: ParaViewComplete), this variable should be set to ON and both VTK_TCL_SUPPORT_LIBRARY_PATH and VTK_TK_SUPPORT_LIBRARY_PATH should point to the directories that hold those files (typically, lib/tcl8.4 and lib/tk8.4 for a typical Tcl/Tk installation, or tcl8.4.5/library and tk8.4.5/library for a Tcl/Tk source repository). Once this variable is set to ON, support files will automatically be copied to the build directory and the executables will try to use that location to initialize Tcl/Tk.") + + IF (VTK_TCL_TK_COPY_SUPPORT_LIBRARY) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + + GET_FILENAME_COMPONENT(TCL_LIBRARY_PATH ${TCL_LIBRARY} PATH) + SET (TRY_DIRS + "${TCL_LIBRARY_PATH}/tcl${TCL_TK_VERSION}" + "${TCL_INCLUDE_PATH}/../lib/tcl${TCL_TK_VERSION}" + "${TCL_LIBRARY_PATH}/../library" + "${TCL_INCLUDE_PATH}/../library") + FOREACH (dir ${TRY_DIRS}) + IF (EXISTS "${dir}/ldAout.tcl") + SET (VTK_TCL_SUPPORT_LIBRARY_PATH ${dir} CACHE INTERNAL + "Path to the Tcl support library files.") + ENDIF (EXISTS "${dir}/ldAout.tcl") + ENDFOREACH (dir) + + GET_FILENAME_COMPONENT(TK_LIBRARY_PATH ${TK_LIBRARY} PATH) + SET (TRY_DIRS + "${TK_LIBRARY_PATH}/tk${TCL_TK_VERSION}" + "${TK_INCLUDE_PATH}/../lib/tk${TCL_TK_VERSION}" + "${TK_LIBRARY_PATH}/../library" + "${TK_INCLUDE_PATH}/../library") + FOREACH (dir ${TRY_DIRS}) + IF (EXISTS "${dir}/clrpick.tcl") + SET (VTK_TK_SUPPORT_LIBRARY_PATH ${dir} CACHE INTERNAL + "Path to the Tk support library files.") + ENDIF (EXISTS "${dir}/clrpick.tcl") + ENDFOREACH (dir) + + IF(VTK_TCL_SUPPORT_LIBRARY_PATH AND VTK_TK_SUPPORT_LIBRARY_PATH) + + IF (CXX_TEST_PATH) + IF(NOT DEFINED TclTk_LIB_DIR) + SET(TclTk_LIB_DIR "${PROJECT_BINARY_DIR}/lib") + ENDIF(NOT DEFINED TclTk_LIB_DIR) + VTK_COPY_TCL_TK_SUPPORT_FILES_TO_DIR ( + ${VTK_TCL_SUPPORT_LIBRARY_PATH} + ${VTK_TK_SUPPORT_LIBRARY_PATH} + "${TclTk_LIB_DIR}") + ENDIF (CXX_TEST_PATH) + + IF(NOT VTK_INSTALL_NO_RUNTIME) + VTK_COPY_TCL_TK_SUPPORT_FILES( + "${VTK_TCL_SUPPORT_LIBRARY_PATH}" + "${VTK_INSTALL_TCL_DIR}/tcl${TCL_TK_VERSION}" + "${VTK_TK_SUPPORT_LIBRARY_PATH}" + "${VTK_INSTALL_TCL_DIR}/tk${TCL_TK_VERSION}" + INSTALL) + ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + + IF(NOT VTK_INSTALL_NO_RUNTIME) + VTK_GET_TCL_SUPPORT_FILES( + ${VTK_TCL_SUPPORT_LIBRARY_PATH} "TCL_SUPPORT_FILES") + FOREACH (file ${TCL_SUPPORT_FILES}) + STRING (REGEX REPLACE "${VTK_TCL_SUPPORT_LIBRARY_PATH}/" "" base ${file}) + GET_FILENAME_COMPONENT(dest ${base} PATH) + INSTALL_FILES(${VTK_INSTALL_TCL_DIR}/tcl${TCL_TK_VERSION}/${dest} FILES ${file}) + ENDFOREACH (file) + + VTK_GET_TK_SUPPORT_FILES(${VTK_TK_SUPPORT_LIBRARY_PATH} "TK_SUPPORT_FILES") + FOREACH (file ${TK_SUPPORT_FILES}) + STRING (REGEX REPLACE "${VTK_TK_SUPPORT_LIBRARY_PATH}/" "" base ${file}) + GET_FILENAME_COMPONENT(dest ${base} PATH) + INSTALL_FILES(${VTK_INSTALL_TCL_DIR}/tk${TCL_TK_VERSION}/${dest} FILES ${file}) + ENDFOREACH (file) + ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + + ENDIF(VTK_TCL_SUPPORT_LIBRARY_PATH AND VTK_TK_SUPPORT_LIBRARY_PATH) + + ENDIF (VTK_TCL_TK_COPY_SUPPORT_LIBRARY) + +ENDIF (TCL_LIBRARY AND TK_LIBRARY) diff --git a/Utilities/TclTk/resources/CMakeLists.txt b/Utilities/TclTk/resources/CMakeLists.txt new file mode 100644 index 0000000..2bae221 --- /dev/null +++ b/Utilities/TclTk/resources/CMakeLists.txt @@ -0,0 +1,9 @@ +IF(VTK_USE_TK) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + IF("${VTK_TK_RESOURCES_DIR}" MATCHES + "${CMAKE_CURRENT_SOURCE_DIR}/tk${TCL_TK_VERSION}") + SUBDIRS(tk${TCL_TK_VERSION}) + ENDIF("${VTK_TK_RESOURCES_DIR}" MATCHES + "${CMAKE_CURRENT_SOURCE_DIR}/tk${TCL_TK_VERSION}") +ENDIF(VTK_USE_TK) diff --git a/Utilities/TclTk/resources/tk8.3/CMakeLists.txt b/Utilities/TclTk/resources/tk8.3/CMakeLists.txt new file mode 100644 index 0000000..f92a134 --- /dev/null +++ b/Utilities/TclTk/resources/tk8.3/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(WIN32) + SUBDIRS(win) +ENDIF(WIN32) diff --git a/Utilities/TclTk/resources/tk8.3/win/CMakeLists.txt b/Utilities/TclTk/resources/tk8.3/win/CMakeLists.txt new file mode 100644 index 0000000..a31ef8b --- /dev/null +++ b/Utilities/TclTk/resources/tk8.3/win/CMakeLists.txt @@ -0,0 +1 @@ +SUBDIRS(rc) diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/CMakeLists.txt b/Utilities/TclTk/resources/tk8.3/win/rc/CMakeLists.txt new file mode 100644 index 0000000..45e21ba --- /dev/null +++ b/Utilities/TclTk/resources/tk8.3/win/rc/CMakeLists.txt @@ -0,0 +1,10 @@ +# The resources dir is only worth exporting if we are building with +# Tcl/Tk static +IF(VTK_USE_TK AND VTK_TCL_TK_STATIC) + IF(VTK_TK_RESOURCES_DIR) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/TclTk/resources/tk8.3/win/rc + "\\.(bmp|cur|ico|manifest|rc)$") + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + ENDIF(VTK_TK_RESOURCES_DIR) +ENDIF(VTK_USE_TK AND VTK_TCL_TK_STATIC) diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/buttons.bmp b/Utilities/TclTk/resources/tk8.3/win/rc/buttons.bmp new file mode 100644 index 0000000..f37a4c9 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/buttons.bmp differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor00.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor00.cur new file mode 100644 index 0000000..337e6d4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor00.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor02.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor02.cur new file mode 100644 index 0000000..fbc4774 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor02.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor04.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor04.cur new file mode 100644 index 0000000..9634c42 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor04.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor06.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor06.cur new file mode 100644 index 0000000..f7188b2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor06.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor08.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor08.cur new file mode 100644 index 0000000..d9f15f7 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor08.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor0a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor0a.cur new file mode 100644 index 0000000..3f8ef45 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor0a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor0c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor0c.cur new file mode 100644 index 0000000..1014edd Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor0c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor0e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor0e.cur new file mode 100644 index 0000000..964058d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor0e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor10.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor10.cur new file mode 100644 index 0000000..c4f7809 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor10.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor12.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor12.cur new file mode 100644 index 0000000..920c936 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor12.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor14.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor14.cur new file mode 100644 index 0000000..c7de122 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor14.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor16.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor16.cur new file mode 100644 index 0000000..cfc08f2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor16.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor18.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor18.cur new file mode 100644 index 0000000..95ed2ee Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor18.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor1a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor1a.cur new file mode 100644 index 0000000..ea51361 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor1a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor1c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor1c.cur new file mode 100644 index 0000000..6f10bfb Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor1c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor1e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor1e.cur new file mode 100644 index 0000000..49fa7f7 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor1e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor20.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor20.cur new file mode 100644 index 0000000..cf177a1 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor20.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor22.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor22.cur new file mode 100644 index 0000000..2f8e912 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor22.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor24.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor24.cur new file mode 100644 index 0000000..87ba5b4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor24.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor26.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor26.cur new file mode 100644 index 0000000..0b2dbd2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor26.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor28.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor28.cur new file mode 100644 index 0000000..30550f9 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor28.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor2a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor2a.cur new file mode 100644 index 0000000..8dca432 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor2a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor2c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor2c.cur new file mode 100644 index 0000000..7be3494 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor2c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor2e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor2e.cur new file mode 100644 index 0000000..7a0bc69 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor2e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor30.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor30.cur new file mode 100644 index 0000000..70ef4fd Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor30.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor32.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor32.cur new file mode 100644 index 0000000..93b5c47 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor32.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor34.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor34.cur new file mode 100644 index 0000000..0fad3f1 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor34.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor36.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor36.cur new file mode 100644 index 0000000..fc8d4f6 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor36.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor38.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor38.cur new file mode 100644 index 0000000..4447d7d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor38.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor3a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor3a.cur new file mode 100644 index 0000000..8176d1d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor3a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor3c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor3c.cur new file mode 100644 index 0000000..6a3111d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor3c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor3e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor3e.cur new file mode 100644 index 0000000..fa6fe5b Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor3e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor40.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor40.cur new file mode 100644 index 0000000..f07bf4f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor40.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor42.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor42.cur new file mode 100644 index 0000000..387d5f0 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor42.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor44.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor44.cur new file mode 100644 index 0000000..190320c Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor44.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor46.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor46.cur new file mode 100644 index 0000000..3e97094 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor46.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor48.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor48.cur new file mode 100644 index 0000000..2a56897 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor48.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor4a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor4a.cur new file mode 100644 index 0000000..30febfa Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor4a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor4c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor4c.cur new file mode 100644 index 0000000..0407d77 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor4c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor4e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor4e.cur new file mode 100644 index 0000000..a58e3db Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor4e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor50.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor50.cur new file mode 100644 index 0000000..7352420 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor50.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor52.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor52.cur new file mode 100644 index 0000000..435f99f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor52.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor54.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor54.cur new file mode 100644 index 0000000..54eb4f2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor54.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor56.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor56.cur new file mode 100644 index 0000000..c808bd4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor56.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor58.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor58.cur new file mode 100644 index 0000000..98b6a2f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor58.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor5a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor5a.cur new file mode 100644 index 0000000..b00070e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor5a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor5c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor5c.cur new file mode 100644 index 0000000..a407b55 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor5c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor5e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor5e.cur new file mode 100644 index 0000000..ab3449f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor5e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor60.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor60.cur new file mode 100644 index 0000000..847969d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor60.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor62.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor62.cur new file mode 100644 index 0000000..36404a5 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor62.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor64.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor64.cur new file mode 100644 index 0000000..a6bdd0e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor64.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor66.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor66.cur new file mode 100644 index 0000000..81d53b4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor66.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor68.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor68.cur new file mode 100644 index 0000000..27cfaf0 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor68.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor6a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor6a.cur new file mode 100644 index 0000000..20f138e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor6a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor6c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor6c.cur new file mode 100644 index 0000000..1e8d6d8 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor6c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor6e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor6e.cur new file mode 100644 index 0000000..3a9b6b0 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor6e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor70.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor70.cur new file mode 100644 index 0000000..e2d7673 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor70.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor72.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor72.cur new file mode 100644 index 0000000..4994c6e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor72.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor74.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor74.cur new file mode 100644 index 0000000..d5e4361 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor74.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor76.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor76.cur new file mode 100644 index 0000000..34f402a Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor76.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor78.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor78.cur new file mode 100644 index 0000000..70e25dd Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor78.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor7a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor7a.cur new file mode 100644 index 0000000..5ea95c4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor7a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor7c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor7c.cur new file mode 100644 index 0000000..38036ab Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor7c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor7e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor7e.cur new file mode 100644 index 0000000..4b24e50 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor7e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor80.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor80.cur new file mode 100644 index 0000000..a3955a5 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor80.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor82.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor82.cur new file mode 100644 index 0000000..984cfba Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor82.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor84.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor84.cur new file mode 100644 index 0000000..cd6807e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor84.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor86.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor86.cur new file mode 100644 index 0000000..2d38c03 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor86.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor88.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor88.cur new file mode 100644 index 0000000..62b8061 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor88.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor8a.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor8a.cur new file mode 100644 index 0000000..6c5358d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor8a.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor8c.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor8c.cur new file mode 100644 index 0000000..103010b Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor8c.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor8e.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor8e.cur new file mode 100644 index 0000000..a500a38 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor8e.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor90.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor90.cur new file mode 100644 index 0000000..08731f8 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor90.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor92.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor92.cur new file mode 100644 index 0000000..4364b5d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor92.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor94.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor94.cur new file mode 100644 index 0000000..7777d53 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor94.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor96.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor96.cur new file mode 100644 index 0000000..cecaea3 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor96.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/cursor98.cur b/Utilities/TclTk/resources/tk8.3/win/rc/cursor98.cur new file mode 100644 index 0000000..5cab68e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/cursor98.cur differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/tk.ico b/Utilities/TclTk/resources/tk8.3/win/rc/tk.ico new file mode 100644 index 0000000..5fdb9a7 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/tk.ico differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/tk.rc b/Utilities/TclTk/resources/tk8.3/win/rc/tk.rc new file mode 100644 index 0000000..c708212 --- /dev/null +++ b/Utilities/TclTk/resources/tk8.3/win/rc/tk.rc @@ -0,0 +1,69 @@ +// RCS: @(#) $Id: tk.rc,v 1.1.2.1 2006/06/13 17:39:29 david.cole Exp $ +// +// Version Resource Script +// + +#include + +#define RESOURCE_INCLUDED +#include + +#define STRINGIFY1(x) #x +#define STRINGIFY(x) STRINGIFY1(x) + + +// +// build-up the name suffix that defines the type of build this is. +// +#ifdef TCL_THREADS +#define SUFFIX_THREADS "t" +#else +#define SUFFIX_THREADS "" +#endif + +#ifdef DEBUG +#define SUFFIX_DEBUG "d" +#else +#define SUFFIX_DEBUG "" +#endif + +#define SUFFIX SUFFIX_THREADS SUFFIX_DEBUG + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Tk DLL\0" + VALUE "OriginalFilename", "tk" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) SUFFIX ".dll\0" + VALUE "CompanyName", "ActiveState Corporation\0" + VALUE "FileVersion", TK_PATCH_LEVEL + VALUE "LegalCopyright", "Copyright \251 2000 by ActiveState Corporation, et al\0" + VALUE "ProductName", "Tk " TK_VERSION " for Windows\0" + VALUE "ProductVersion", TK_PATCH_LEVEL + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +// +// Include the base resources. +// + +#include "tk_base.rc" diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/tk_base.rc b/Utilities/TclTk/resources/tk8.3/win/rc/tk_base.rc new file mode 100644 index 0000000..cb6b1da --- /dev/null +++ b/Utilities/TclTk/resources/tk8.3/win/rc/tk_base.rc @@ -0,0 +1,130 @@ +// RCS: @(#) $Id: tk_base.rc,v 1.1.2.1 2006/06/13 17:39:29 david.cole Exp $ +// +// Base resources needed by Tk whether it's a DLL or a static library. +// + +// +// Tk Icon +// + +tk ICON DISCARDABLE "tk.ico" + +#include + +FILEOPENORD DIALOG DISCARDABLE 36, 24, 218, 138 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Choose Directory" +FONT 8, "Helv" +BEGIN + LTEXT "Directory &name:",-1,8,6,118,9 + EDITTEXT edt10,8,26,144,12, WS_TABSTOP | ES_AUTOHSCROLL + LISTBOX lst2,8,40,144,64,LBS_SORT | LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | + LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Dri&ves:",stc4,8,106,92,9 + COMBOBOX cmb2,8,115,144,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | + CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",1,160,6,50,14,WS_GROUP + PUSHBUTTON "Cancel",2,160,24,50,14,WS_GROUP + PUSHBUTTON "&Help",psh15,160,42,50,14,WS_GROUP + CHECKBOX "&Read only",chx1,160,66,50,12,WS_GROUP + PUSHBUTTON "Net&work...",psh14,160,115,50,14,WS_GROUP + + LTEXT "a",stc3,9,143,114,15 + EDITTEXT edt1,7,158,135,20,NOT WS_TABSTOP + LISTBOX lst1,8,205,134,42,LBS_NOINTEGRALHEIGHT + COMBOBOX cmb1,8,253,135,21,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | + CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | + WS_VSCROLL + +END + + +// +// Bitmaps +// + +buttons BITMAP DISCARDABLE "buttons.bmp" + +// +// Cursors +// + +X_cursor CURSOR DISCARDABLE "cursor00.cur" +arrow CURSOR DISCARDABLE "cursor02.cur" +based_arrow_down CURSOR DISCARDABLE "cursor04.cur" +based_arrow_up CURSOR DISCARDABLE "cursor06.cur" +boat CURSOR DISCARDABLE "cursor08.cur" +bogosity CURSOR DISCARDABLE "cursor0a.cur" +bottom_left_corner CURSOR DISCARDABLE "cursor0c.cur" +bottom_right_corner CURSOR DISCARDABLE "cursor0e.cur" +bottom_side CURSOR DISCARDABLE "cursor10.cur" +bottom_tee CURSOR DISCARDABLE "cursor12.cur" +box_spiral CURSOR DISCARDABLE "cursor14.cur" +center_ptr CURSOR DISCARDABLE "cursor16.cur" +circle CURSOR DISCARDABLE "cursor18.cur" +clock CURSOR DISCARDABLE "cursor1a.cur" +coffee_mug CURSOR DISCARDABLE "cursor1c.cur" +cross CURSOR DISCARDABLE "cursor1e.cur" +cross_reverse CURSOR DISCARDABLE "cursor20.cur" +crosshair CURSOR DISCARDABLE "cursor22.cur" +diamond_cross CURSOR DISCARDABLE "cursor24.cur" +dot CURSOR DISCARDABLE "cursor26.cur" +dotbox CURSOR DISCARDABLE "cursor28.cur" +double_arrow CURSOR DISCARDABLE "cursor2a.cur" +draft_large CURSOR DISCARDABLE "cursor2c.cur" +draft_small CURSOR DISCARDABLE "cursor2e.cur" +draped_box CURSOR DISCARDABLE "cursor30.cur" +exchange CURSOR DISCARDABLE "cursor32.cur" +fleur CURSOR DISCARDABLE "cursor34.cur" +gobbler CURSOR DISCARDABLE "cursor36.cur" +gumby CURSOR DISCARDABLE "cursor38.cur" +hand1 CURSOR DISCARDABLE "cursor3a.cur" +hand2 CURSOR DISCARDABLE "cursor3c.cur" +heart CURSOR DISCARDABLE "cursor3e.cur" +icon CURSOR DISCARDABLE "cursor40.cur" +iron_cross CURSOR DISCARDABLE "cursor42.cur" +left_ptr CURSOR DISCARDABLE "cursor44.cur" +left_side CURSOR DISCARDABLE "cursor46.cur" +left_tee CURSOR DISCARDABLE "cursor48.cur" +leftbutton CURSOR DISCARDABLE "cursor4a.cur" +ll_angle CURSOR DISCARDABLE "cursor4c.cur" +lr_angle CURSOR DISCARDABLE "cursor4e.cur" +man CURSOR DISCARDABLE "cursor50.cur" +middlebutton CURSOR DISCARDABLE "cursor52.cur" +mouse CURSOR DISCARDABLE "cursor54.cur" +pencil CURSOR DISCARDABLE "cursor56.cur" +pirate CURSOR DISCARDABLE "cursor58.cur" +plus CURSOR DISCARDABLE "cursor5a.cur" +question_arrow CURSOR DISCARDABLE "cursor5c.cur" +right_ptr CURSOR DISCARDABLE "cursor5e.cur" +right_side CURSOR DISCARDABLE "cursor60.cur" +right_tee CURSOR DISCARDABLE "cursor62.cur" +rightbutton CURSOR DISCARDABLE "cursor64.cur" +rtl_logo CURSOR DISCARDABLE "cursor66.cur" +sailboat CURSOR DISCARDABLE "cursor68.cur" +sb_down_arrow CURSOR DISCARDABLE "cursor6a.cur" +sb_h_double_arrow CURSOR DISCARDABLE "cursor6c.cur" +sb_left_arrow CURSOR DISCARDABLE "cursor6e.cur" +sb_right_arrow CURSOR DISCARDABLE "cursor70.cur" +sb_up_arrow CURSOR DISCARDABLE "cursor72.cur" +sb_v_double_arrow CURSOR DISCARDABLE "cursor74.cur" +shuttle CURSOR DISCARDABLE "cursor76.cur" +sizing CURSOR DISCARDABLE "cursor78.cur" +spider CURSOR DISCARDABLE "cursor7a.cur" +spraycan CURSOR DISCARDABLE "cursor7c.cur" +star CURSOR DISCARDABLE "cursor7e.cur" +target CURSOR DISCARDABLE "cursor80.cur" +tcross CURSOR DISCARDABLE "cursor82.cur" +top_left_arrow CURSOR DISCARDABLE "cursor84.cur" +top_left_corner CURSOR DISCARDABLE "cursor86.cur" +top_right_corner CURSOR DISCARDABLE "cursor88.cur" +top_side CURSOR DISCARDABLE "cursor8a.cur" +top_tee CURSOR DISCARDABLE "cursor8c.cur" +trek CURSOR DISCARDABLE "cursor8e.cur" +ul_angle CURSOR DISCARDABLE "cursor90.cur" +umbrella CURSOR DISCARDABLE "cursor92.cur" +ur_angle CURSOR DISCARDABLE "cursor94.cur" +watch CURSOR DISCARDABLE "cursor96.cur" +xterm CURSOR DISCARDABLE "cursor98.cur" diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/wish.exe.manifest b/Utilities/TclTk/resources/tk8.3/win/rc/wish.exe.manifest new file mode 100644 index 0000000..84cb269 --- /dev/null +++ b/Utilities/TclTk/resources/tk8.3/win/rc/wish.exe.manifest @@ -0,0 +1,23 @@ + + + +Tcl/Tk windowing shell (wish) + + + + + + + diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/wish.ico b/Utilities/TclTk/resources/tk8.3/win/rc/wish.ico new file mode 100644 index 0000000..1825751 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.3/win/rc/wish.ico differ diff --git a/Utilities/TclTk/resources/tk8.3/win/rc/wish.rc b/Utilities/TclTk/resources/tk8.3/win/rc/wish.rc new file mode 100644 index 0000000..4b5ff08 --- /dev/null +++ b/Utilities/TclTk/resources/tk8.3/win/rc/wish.rc @@ -0,0 +1,81 @@ +// RCS: @(#) $Id: wish.rc,v 1.1.2.1 2006/06/13 17:39:29 david.cole Exp $ +// +// Version Resource Script +// + +#include + +#define RESOURCE_INCLUDED +#include + +#define STRINGIFY1(x) #x +#define STRINGIFY(x) STRINGIFY1(x) + +// +// build-up the name suffix that defines the type of build this is. +// +#ifdef TCL_THREADS +#define SUFFIX_THREADS "t" +#else +#define SUFFIX_THREADS "" +#endif + +#ifdef STATIC_BUILD +#define SUFFIX_STATIC "s" +#else +#define SUFFIX_STATIC "" +#endif + +#ifdef DEBUG +#define SUFFIX_DEBUG "d" +#else +#define SUFFIX_DEBUG "" +#endif + +#define SUFFIX SUFFIX_THREADS SUFFIX_STATIC SUFFIX_DEBUG + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Wish Application\0" + VALUE "OriginalFilename", "wish" STRINGIFY(TK_MAJOR_VERSION) STRINGIFY(TK_MINOR_VERSION) SUFFIX ".exe\0" + VALUE "CompanyName", "ActiveState Corporation\0" + VALUE "FileVersion", TK_PATCH_LEVEL + VALUE "LegalCopyright", "Copyright \251 2000 by ActiveState Corporation, et al\0" + VALUE "ProductName", "Tk " TK_VERSION " for Windows\0" + VALUE "ProductVersion", TK_PATCH_LEVEL + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +// +// Icon +// +// The icon whose name or resource ID is lexigraphically first, is used +// as the application's icon. +// + +app ICON DISCARDABLE "wish.ico" + +#ifdef STATIC_BUILD +#include "tk_base.rc" +#endif diff --git a/Utilities/TclTk/resources/tk8.4/CMakeLists.txt b/Utilities/TclTk/resources/tk8.4/CMakeLists.txt new file mode 100644 index 0000000..f92a134 --- /dev/null +++ b/Utilities/TclTk/resources/tk8.4/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(WIN32) + SUBDIRS(win) +ENDIF(WIN32) diff --git a/Utilities/TclTk/resources/tk8.4/win/CMakeLists.txt b/Utilities/TclTk/resources/tk8.4/win/CMakeLists.txt new file mode 100644 index 0000000..a31ef8b --- /dev/null +++ b/Utilities/TclTk/resources/tk8.4/win/CMakeLists.txt @@ -0,0 +1 @@ +SUBDIRS(rc) diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/CMakeLists.txt b/Utilities/TclTk/resources/tk8.4/win/rc/CMakeLists.txt new file mode 100644 index 0000000..be4305b --- /dev/null +++ b/Utilities/TclTk/resources/tk8.4/win/rc/CMakeLists.txt @@ -0,0 +1,10 @@ +# The resources dir is only worth exporting if we are building with +# Tcl/Tk static +IF(VTK_USE_TK AND VTK_TCL_TK_STATIC) + IF(VTK_TK_RESOURCES_DIR) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/TclTk/resources/tk8.4/win/rc + "\\.(bmp|cur|ico|manifest|rc)$") + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + ENDIF(VTK_TK_RESOURCES_DIR) +ENDIF(VTK_USE_TK AND VTK_TCL_TK_STATIC) diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/buttons.bmp b/Utilities/TclTk/resources/tk8.4/win/rc/buttons.bmp new file mode 100644 index 0000000..f37a4c9 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/buttons.bmp differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor00.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor00.cur new file mode 100644 index 0000000..337e6d4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor00.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor02.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor02.cur new file mode 100644 index 0000000..fbc4774 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor02.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor04.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor04.cur new file mode 100644 index 0000000..9634c42 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor04.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor06.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor06.cur new file mode 100644 index 0000000..f7188b2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor06.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor08.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor08.cur new file mode 100644 index 0000000..d9f15f7 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor08.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor0a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor0a.cur new file mode 100644 index 0000000..3f8ef45 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor0a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor0c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor0c.cur new file mode 100644 index 0000000..1014edd Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor0c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor0e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor0e.cur new file mode 100644 index 0000000..964058d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor0e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor10.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor10.cur new file mode 100644 index 0000000..c4f7809 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor10.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor12.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor12.cur new file mode 100644 index 0000000..920c936 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor12.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor14.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor14.cur new file mode 100644 index 0000000..c7de122 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor14.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor16.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor16.cur new file mode 100644 index 0000000..cfc08f2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor16.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor18.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor18.cur new file mode 100644 index 0000000..95ed2ee Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor18.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor1a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor1a.cur new file mode 100644 index 0000000..ea51361 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor1a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor1c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor1c.cur new file mode 100644 index 0000000..6f10bfb Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor1c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor1e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor1e.cur new file mode 100644 index 0000000..49fa7f7 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor1e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor20.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor20.cur new file mode 100644 index 0000000..cf177a1 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor20.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor22.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor22.cur new file mode 100644 index 0000000..2f8e912 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor22.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor24.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor24.cur new file mode 100644 index 0000000..87ba5b4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor24.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor26.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor26.cur new file mode 100644 index 0000000..0b2dbd2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor26.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor28.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor28.cur new file mode 100644 index 0000000..30550f9 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor28.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor2a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor2a.cur new file mode 100644 index 0000000..8dca432 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor2a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor2c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor2c.cur new file mode 100644 index 0000000..7be3494 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor2c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor2e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor2e.cur new file mode 100644 index 0000000..7a0bc69 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor2e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor30.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor30.cur new file mode 100644 index 0000000..70ef4fd Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor30.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor32.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor32.cur new file mode 100644 index 0000000..93b5c47 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor32.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor34.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor34.cur new file mode 100644 index 0000000..0fad3f1 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor34.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor36.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor36.cur new file mode 100644 index 0000000..fc8d4f6 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor36.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor38.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor38.cur new file mode 100644 index 0000000..4447d7d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor38.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor3a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor3a.cur new file mode 100644 index 0000000..8176d1d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor3a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor3c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor3c.cur new file mode 100644 index 0000000..6a3111d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor3c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor3e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor3e.cur new file mode 100644 index 0000000..fa6fe5b Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor3e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor40.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor40.cur new file mode 100644 index 0000000..f07bf4f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor40.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor42.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor42.cur new file mode 100644 index 0000000..387d5f0 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor42.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor44.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor44.cur new file mode 100644 index 0000000..190320c Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor44.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor46.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor46.cur new file mode 100644 index 0000000..3e97094 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor46.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor48.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor48.cur new file mode 100644 index 0000000..2a56897 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor48.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor4a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor4a.cur new file mode 100644 index 0000000..30febfa Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor4a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor4c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor4c.cur new file mode 100644 index 0000000..0407d77 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor4c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor4e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor4e.cur new file mode 100644 index 0000000..a58e3db Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor4e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor50.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor50.cur new file mode 100644 index 0000000..7352420 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor50.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor52.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor52.cur new file mode 100644 index 0000000..435f99f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor52.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor54.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor54.cur new file mode 100644 index 0000000..54eb4f2 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor54.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor56.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor56.cur new file mode 100644 index 0000000..c808bd4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor56.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor58.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor58.cur new file mode 100644 index 0000000..98b6a2f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor58.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor5a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor5a.cur new file mode 100644 index 0000000..b00070e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor5a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor5c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor5c.cur new file mode 100644 index 0000000..a407b55 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor5c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor5e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor5e.cur new file mode 100644 index 0000000..ab3449f Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor5e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor60.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor60.cur new file mode 100644 index 0000000..847969d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor60.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor62.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor62.cur new file mode 100644 index 0000000..36404a5 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor62.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor64.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor64.cur new file mode 100644 index 0000000..a6bdd0e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor64.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor66.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor66.cur new file mode 100644 index 0000000..81d53b4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor66.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor68.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor68.cur new file mode 100644 index 0000000..27cfaf0 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor68.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor6a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor6a.cur new file mode 100644 index 0000000..20f138e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor6a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor6c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor6c.cur new file mode 100644 index 0000000..1e8d6d8 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor6c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor6e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor6e.cur new file mode 100644 index 0000000..3a9b6b0 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor6e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor70.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor70.cur new file mode 100644 index 0000000..e2d7673 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor70.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor72.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor72.cur new file mode 100644 index 0000000..4994c6e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor72.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor74.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor74.cur new file mode 100644 index 0000000..d5e4361 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor74.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor76.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor76.cur new file mode 100644 index 0000000..34f402a Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor76.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor78.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor78.cur new file mode 100644 index 0000000..70e25dd Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor78.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor7a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor7a.cur new file mode 100644 index 0000000..5ea95c4 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor7a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor7c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor7c.cur new file mode 100644 index 0000000..38036ab Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor7c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor7e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor7e.cur new file mode 100644 index 0000000..4b24e50 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor7e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor80.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor80.cur new file mode 100644 index 0000000..a3955a5 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor80.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor82.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor82.cur new file mode 100644 index 0000000..984cfba Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor82.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor84.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor84.cur new file mode 100644 index 0000000..cd6807e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor84.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor86.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor86.cur new file mode 100644 index 0000000..2d38c03 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor86.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor88.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor88.cur new file mode 100644 index 0000000..62b8061 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor88.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor8a.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor8a.cur new file mode 100644 index 0000000..6c5358d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor8a.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor8c.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor8c.cur new file mode 100644 index 0000000..103010b Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor8c.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor8e.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor8e.cur new file mode 100644 index 0000000..a500a38 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor8e.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor90.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor90.cur new file mode 100644 index 0000000..08731f8 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor90.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor92.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor92.cur new file mode 100644 index 0000000..4364b5d Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor92.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor94.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor94.cur new file mode 100644 index 0000000..7777d53 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor94.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor96.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor96.cur new file mode 100644 index 0000000..cecaea3 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor96.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/cursor98.cur b/Utilities/TclTk/resources/tk8.4/win/rc/cursor98.cur new file mode 100644 index 0000000..5cab68e Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/cursor98.cur differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/tk.ico b/Utilities/TclTk/resources/tk8.4/win/rc/tk.ico new file mode 100644 index 0000000..5fdb9a7 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/tk.ico differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/tk.rc b/Utilities/TclTk/resources/tk8.4/win/rc/tk.rc new file mode 100644 index 0000000..0a72f41 --- /dev/null +++ b/Utilities/TclTk/resources/tk8.4/win/rc/tk.rc @@ -0,0 +1,76 @@ +// RCS: @(#) $Id: tk.rc,v 1.1 2004/01/06 23:06:38 barre Exp $ +// +// Version Resource Script +// + +#include +#include + +// +// build-up the name suffix that defines the type of build this is. +// +#ifdef TCL_THREADS +#define SUFFIX_THREADS "t" +#else +#define SUFFIX_THREADS "" +#endif + +#ifdef DEBUG +#define SUFFIX_DEBUG "d" +#else +#define SUFFIX_DEBUG "" +#endif + +#define SUFFIX SUFFIX_THREADS SUFFIX_DEBUG + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Tk DLL\0" + VALUE "OriginalFilename", "tk" STRINGIFY(JOIN(TK_MAJOR_VERSION,TK_MINOR_VERSION)) SUFFIX ".dll\0" + VALUE "CompanyName", "ActiveState Corporation\0" + VALUE "FileVersion", TK_PATCH_LEVEL + VALUE "LegalCopyright", "Copyright \251 2001 by ActiveState Corporation, et al\0" + VALUE "ProductName", "Tk " TK_VERSION " for Windows\0" + VALUE "ProductVersion", TK_PATCH_LEVEL + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +// +// Include the base resources. +// + +#include "tk_base.rc" + +// +// This enables themed scrollbars in XP by trying to use comctl32 v6. +// + +#ifndef RT_MANIFEST +#define RT_MANIFEST 24 +#endif +#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID +#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 +#endif +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "wish.exe.manifest" + diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/tk_base.rc b/Utilities/TclTk/resources/tk8.4/win/rc/tk_base.rc new file mode 100644 index 0000000..36bb79f --- /dev/null +++ b/Utilities/TclTk/resources/tk8.4/win/rc/tk_base.rc @@ -0,0 +1,131 @@ +// RCS: @(#) $Id: tk_base.rc,v 1.1 2004/01/06 23:06:38 barre Exp $ +// +// Base resources needed by Tk whether it's a DLL or a static library. +// + +// +// Tk Icon +// + +tk ICON DISCARDABLE "tk.ico" + +#include + +FILEOPENORD DIALOG DISCARDABLE 36, 24, 218, 138 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Choose Directory" +FONT 8, "Helv" +BEGIN + LTEXT "Directory &name:",-1,8,6,118,9 + EDITTEXT edt10,8,26,144,12, WS_TABSTOP | ES_AUTOHSCROLL + LISTBOX lst2,8,40,144,64,LBS_SORT | LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | + LBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Dri&ves:",stc4,8,106,92,9 + COMBOBOX cmb2,8,115,144,68,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | + CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",1,160,6,50,14,WS_GROUP + PUSHBUTTON "Cancel",2,160,24,50,14,WS_GROUP + PUSHBUTTON "&Help",psh15,160,42,50,14,WS_GROUP + CHECKBOX "&Read only",chx1,160,66,50,12,WS_GROUP + PUSHBUTTON "Net&work...",psh14,160,115,50,14,WS_GROUP + + LTEXT "a",stc3,9,143,114,15 + EDITTEXT edt1,7,158,135,20,NOT WS_TABSTOP + LISTBOX lst1,8,205,134,42,LBS_NOINTEGRALHEIGHT + COMBOBOX cmb1,8,253,135,21,CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | + CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | + WS_VSCROLL + +END + + +// +// Bitmaps +// + +buttons BITMAP DISCARDABLE "buttons.bmp" + +// +// Cursors +// + +X_cursor CURSOR DISCARDABLE "cursor00.cur" +arrow CURSOR DISCARDABLE "cursor02.cur" +based_arrow_down CURSOR DISCARDABLE "cursor04.cur" +based_arrow_up CURSOR DISCARDABLE "cursor06.cur" +boat CURSOR DISCARDABLE "cursor08.cur" +bogosity CURSOR DISCARDABLE "cursor0a.cur" +bottom_left_corner CURSOR DISCARDABLE "cursor0c.cur" +bottom_right_corner CURSOR DISCARDABLE "cursor0e.cur" +bottom_side CURSOR DISCARDABLE "cursor10.cur" +bottom_tee CURSOR DISCARDABLE "cursor12.cur" +box_spiral CURSOR DISCARDABLE "cursor14.cur" +center_ptr CURSOR DISCARDABLE "cursor16.cur" +circle CURSOR DISCARDABLE "cursor18.cur" +clock CURSOR DISCARDABLE "cursor1a.cur" +coffee_mug CURSOR DISCARDABLE "cursor1c.cur" +cross CURSOR DISCARDABLE "cursor1e.cur" +cross_reverse CURSOR DISCARDABLE "cursor20.cur" +crosshair CURSOR DISCARDABLE "cursor22.cur" +diamond_cross CURSOR DISCARDABLE "cursor24.cur" +dot CURSOR DISCARDABLE "cursor26.cur" +dotbox CURSOR DISCARDABLE "cursor28.cur" +double_arrow CURSOR DISCARDABLE "cursor2a.cur" +draft_large CURSOR DISCARDABLE "cursor2c.cur" +draft_small CURSOR DISCARDABLE "cursor2e.cur" +draped_box CURSOR DISCARDABLE "cursor30.cur" +exchange CURSOR DISCARDABLE "cursor32.cur" +fleur CURSOR DISCARDABLE "cursor34.cur" +gobbler CURSOR DISCARDABLE "cursor36.cur" +gumby CURSOR DISCARDABLE "cursor38.cur" +hand1 CURSOR DISCARDABLE "cursor3a.cur" +hand2 CURSOR DISCARDABLE "cursor3c.cur" +heart CURSOR DISCARDABLE "cursor3e.cur" +icon CURSOR DISCARDABLE "cursor40.cur" +iron_cross CURSOR DISCARDABLE "cursor42.cur" +left_ptr CURSOR DISCARDABLE "cursor44.cur" +left_side CURSOR DISCARDABLE "cursor46.cur" +left_tee CURSOR DISCARDABLE "cursor48.cur" +leftbutton CURSOR DISCARDABLE "cursor4a.cur" +ll_angle CURSOR DISCARDABLE "cursor4c.cur" +lr_angle CURSOR DISCARDABLE "cursor4e.cur" +man CURSOR DISCARDABLE "cursor50.cur" +middlebutton CURSOR DISCARDABLE "cursor52.cur" +mouse CURSOR DISCARDABLE "cursor54.cur" +pencil CURSOR DISCARDABLE "cursor56.cur" +pirate CURSOR DISCARDABLE "cursor58.cur" +plus CURSOR DISCARDABLE "cursor5a.cur" +question_arrow CURSOR DISCARDABLE "cursor5c.cur" +right_ptr CURSOR DISCARDABLE "cursor5e.cur" +right_side CURSOR DISCARDABLE "cursor60.cur" +right_tee CURSOR DISCARDABLE "cursor62.cur" +rightbutton CURSOR DISCARDABLE "cursor64.cur" +rtl_logo CURSOR DISCARDABLE "cursor66.cur" +sailboat CURSOR DISCARDABLE "cursor68.cur" +sb_down_arrow CURSOR DISCARDABLE "cursor6a.cur" +sb_h_double_arrow CURSOR DISCARDABLE "cursor6c.cur" +sb_left_arrow CURSOR DISCARDABLE "cursor6e.cur" +sb_right_arrow CURSOR DISCARDABLE "cursor70.cur" +sb_up_arrow CURSOR DISCARDABLE "cursor72.cur" +sb_v_double_arrow CURSOR DISCARDABLE "cursor74.cur" +shuttle CURSOR DISCARDABLE "cursor76.cur" +sizing CURSOR DISCARDABLE "cursor78.cur" +spider CURSOR DISCARDABLE "cursor7a.cur" +spraycan CURSOR DISCARDABLE "cursor7c.cur" +star CURSOR DISCARDABLE "cursor7e.cur" +target CURSOR DISCARDABLE "cursor80.cur" +tcross CURSOR DISCARDABLE "cursor82.cur" +top_left_arrow CURSOR DISCARDABLE "cursor84.cur" +top_left_corner CURSOR DISCARDABLE "cursor86.cur" +top_right_corner CURSOR DISCARDABLE "cursor88.cur" +top_side CURSOR DISCARDABLE "cursor8a.cur" +top_tee CURSOR DISCARDABLE "cursor8c.cur" +trek CURSOR DISCARDABLE "cursor8e.cur" +ul_angle CURSOR DISCARDABLE "cursor90.cur" +umbrella CURSOR DISCARDABLE "cursor92.cur" +ur_angle CURSOR DISCARDABLE "cursor94.cur" +watch CURSOR DISCARDABLE "cursor96.cur" +xterm CURSOR DISCARDABLE "cursor98.cur" + diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/wish.exe.manifest b/Utilities/TclTk/resources/tk8.4/win/rc/wish.exe.manifest new file mode 100644 index 0000000..84cb269 --- /dev/null +++ b/Utilities/TclTk/resources/tk8.4/win/rc/wish.exe.manifest @@ -0,0 +1,23 @@ + + + +Tcl/Tk windowing shell (wish) + + + + + + + diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/wish.ico b/Utilities/TclTk/resources/tk8.4/win/rc/wish.ico new file mode 100644 index 0000000..1825751 Binary files /dev/null and b/Utilities/TclTk/resources/tk8.4/win/rc/wish.ico differ diff --git a/Utilities/TclTk/resources/tk8.4/win/rc/wish.rc b/Utilities/TclTk/resources/tk8.4/win/rc/wish.rc new file mode 100644 index 0000000..e34e72e --- /dev/null +++ b/Utilities/TclTk/resources/tk8.4/win/rc/wish.rc @@ -0,0 +1,89 @@ +// RCS: @(#) $Id: wish.rc,v 1.1 2004/01/06 23:06:38 barre Exp $ +// +// Version Resource Script +// + +#include +#include + +// +// build-up the name suffix that defines the type of build this is. +// +#ifdef TCL_THREADS +#define SUFFIX_THREADS "t" +#else +#define SUFFIX_THREADS "" +#endif + +#ifdef STATIC_BUILD +#define SUFFIX_STATIC "s" +#else +#define SUFFIX_STATIC "" +#endif + +#ifdef DEBUG +#define SUFFIX_DEBUG "d" +#else +#define SUFFIX_DEBUG "" +#endif + +#define SUFFIX SUFFIX_THREADS SUFFIX_STATIC SUFFIX_DEBUG + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + PRODUCTVERSION TK_MAJOR_VERSION,TK_MINOR_VERSION,TK_RELEASE_LEVEL,TK_RELEASE_SERIAL + FILEFLAGSMASK 0x3fL +#ifdef DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Wish Application\0" + VALUE "OriginalFilename", "wish" STRINGIFY(JOIN(TK_MAJOR_VERSION,TK_MINOR_VERSION)) SUFFIX ".exe\0" + VALUE "CompanyName", "ActiveState Corporation\0" + VALUE "FileVersion", TK_PATCH_LEVEL + VALUE "LegalCopyright", "Copyright \251 2000 by ActiveState Corporation, et al\0" + VALUE "ProductName", "Tk " TK_VERSION " for Windows\0" + VALUE "ProductVersion", TK_PATCH_LEVEL + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +// +// Icon +// +// The icon whose name or resource ID is lexigraphically first, is used +// as the application's icon. +// + +app ICON DISCARDABLE "wish.ico" + +#ifdef STATIC_BUILD +#include "tk_base.rc" +#endif + +// +// This enables themed scrollbars in XP by trying to use comctl32 v6. +// + +#ifndef RT_MANIFEST +#define RT_MANIFEST 24 +#endif +#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID +#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 +#endif +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "wish.exe.manifest" + diff --git a/Utilities/Upgrading/AttributeChanges.pdf b/Utilities/Upgrading/AttributeChanges.pdf new file mode 100644 index 0000000..e8a8efd Binary files /dev/null and b/Utilities/Upgrading/AttributeChanges.pdf differ diff --git a/Utilities/Upgrading/DiagAttribute.pl b/Utilities/Upgrading/DiagAttribute.pl new file mode 100644 index 0000000..147d24c --- /dev/null +++ b/Utilities/Upgrading/DiagAttribute.pl @@ -0,0 +1,482 @@ +#!/usr/bin/env perl + +# This script tries to find deprecated attribute data classes and +# methods and warns the user whenever it finds them. It also suggests +# possible modification to bring code up to date. + +use Getopt::Long; + +if (!GetOptions("language:s" => \$language, + "verbose" => \$verbose, + "help" => \$help, + "print-messages" => \$print)) +{ + die; +} + +if (!$language) +{ + $language = "c++"; +} + +if ( !$print && ($#ARGV < 0 || $help) ) +{ + print "Usage: $0 [--language {c++ | tcl | python | java}] ", + "[--verbose] [--help] [--print-messages] file1 [file2 ...]\n"; + exit; +} + + +%cxxmessageids = ( + 'vtkScalars\*' => 0, + 'vtkVectors\*' => 1, + 'vtkNormals\*' => 2, + 'vtkTCoords\*' => 3, + 'vtkTensors\*' => 4, + 'vtkScalars::New[ \t]*\(' => 5, + 'vtkVectors::New[ \t]*\(' => 6, + 'vtkNormals::New[ \t]*\(' => 7, + 'vtkTCoords::New[ \t]*\(' => 8, + 'vtkTensors::New[ \t]*\(' => 9, + '->GetScalar[ \t]*\(' => 10, + '->GetVector[ \t]*\(' => 11, + '->GetNormal[ \t]*\(' => 12, + '->GetTCoord[ \t]*\(' => 13, + '->GetTensor[ \t]*\(' => 14, + '->SetScalar[ \t]*\(' => 15, + '->SetVector[ \t]*\(' => 16, + '->SetNormal[ \t]*\(' => 17, + '->SetTCoord[ \t]*\(' => 18, + '->SetTensor[ \t]*\(' => 19, + '->GetScalars[ \t]*\([a-zA-Z]+.*\)' => 20, + '->GetVectors[ \t]*\([a-zA-Z]+.*\)' => 21, + '->GetNormals[ \t]*\([a-zA-Z]+.*\)' => 22, + '->GetTCoords[ \t]*\([a-zA-Z]+.*\)' => 23, + '->GetTensors[ \t]*\([a-zA-Z]+.*\)' => 24, + '->InsertScalar[ \t]*\(' => 25, + '->InsertVector[ \t]*\(' => 26, + '->InsertNormal[ \t]*\(' => 27, + '->InsertTCoord[ \t]*\(' => 28, + '->InsertTensor[ \t]*\(' => 29, + '->InsertNextScalar[ \t]*\(' => 30, + '->InsertNextVector[ \t]*\(' => 31, + '->InsertNextNormal[ \t]*\(' => 32, + '->InsertNextTCoord[ \t]*\(' => 33, + '->InsertNextTensor[ \t]*\(' => 34, + '->GetActiveScalars' => 35, + '->GetActiveVectors' => 36, + '->GetActiveNormals' => 37, + '->GetActiveTCoords' => 38, + '->GetActiveTensors' => 39, + '->GetNumberOfScalars' => 40, + '->GetNumberOfVectors' => 41, + '->GetNumberOfNormals' => 42, + '->GetNumberOfTCoords' => 43, + '->GetNumberOfTensors' => 44, + '->SetNumberOfScalars' => 40, + '->SetNumberOfVectors' => 41, + '->SetNumberOfNormals' => 42, + '->SetNumberOfTCoords' => 43, + '->SetNumberOfTensors' => 44, + ); + +%tclmessageids = ( + 'vtkScalars ' => 5, + 'vtkVectors ' => 6, + 'vtkNormals ' => 7, + 'vtkTCoords ' => 8, + 'vtkTensors ' => 9, + '[ \t]+GetScalar([ \t]*$|[^a-zA-Z0-9])' => 10, + '[ \t]+GetVector([ \t]*$|[^a-zA-Z0-9])' => 11, + '[ \t]+GetNormal([ \t]*$|[^a-zA-Z0-9])' => 12, + '[ \t]+GetTCoord([ \t]*$|[^a-zA-Z0-9])' => 13, + '[ \t]+GetTensor([ \t]*$|[^a-zA-Z0-9])' => 14, + '[ \t]+SetScalar([ \t]*$|[^a-zA-Z0-9])' => 15, + '[ \t]+SetVector([ \t]*$|[^a-zA-Z0-9])' => 16, + '[ \t]+SetNormal([ \t]*$|[^a-zA-Z0-9])' => 17, + '[ \t]+SetTCoord([ \t]*$|[^a-zA-Z0-9])' => 18, + '[ \t]+SetTensor([ \t]*$|[^a-zA-Z0-9])' => 19, + '[ \t]GetScalars[ \t]*[a-zA-Z]+.*' => 20, + '[ \t]GetVectors[ \t]*[a-zA-Z]+.*' => 21, + '[ \t]GetNormals[ \t]*[a-zA-Z]+.*' => 22, + '[ \t]GetTCoords[ \t]*[a-zA-Z]+.*' => 23, + '[ \t]GetTensors[ \t]*[a-zA-Z]+.*' => 24, + '[ \t]InsertScalar[ \t]+' => 25, + '[ \t]InsertVector[ \t]+' => 26, + '[ \t]InsertNormal[ \t]+' => 27, + '[ \t]InsertTCoord[ \t]+' => 28, + '[ \t]InsertTensor[ \t]+' => 29, + '[ \t]InsertNextScalar[ \t]+' => 30, + '[ \t]InsertNextVector[ \t]+' => 31, + '[ \t]InsertNextNormal[ \t]+' => 32, + '[ \t]InsertNextTCoord[ \t]+' => 33, + '[ \t]InsertNextTensor[ \t]+' => 34, + '[ \t]GetActiveScalars' => 35, + '[ \t]GetActiveVectors' => 36, + '[ \t]GetActiveNormals' => 37, + '[ \t]GetActiveTCoords' => 38, + '[ \t]GetActiveTensors' => 39, + '[ \t]GetNumberOfScalars' => 40, + '[ \t]GetNumberOfVectors' => 41, + '[ \t]GetNumberOfNormals' => 42, + '[ \t]GetNumberOfTCoords' => 43, + '[ \t]GetNumberOfTensors' => 44, + '[ \t]SetNumberOfScalars' => 40, + '[ \t]SetNumberOfVectors' => 41, + '[ \t]SetNumberOfNormals' => 42, + '[ \t]SetNumberOfTCoords' => 43, + '[ \t]SetNumberOfTensors' => 44, + ); + +%pythonmessageids = ( + 'vtkScalars[ \t]*\(\)' => 5, + 'vtkVectors[ \t]*\(\)' => 6, + 'vtkNormals[ \t]*\(\)' => 7, + 'vtkTCoords[ \t]*\(\)' => 8, + 'vtkTensors[ \t]*\(\)' => 9, + '\.GetScalar[ \t]*\(' => 10, + '\.GetVector[ \t]*\(' => 11, + '\.GetNormal[ \t]*\(' => 12, + '\.GetTCoord[ \t]*\(' => 13, + '\.GetTensor[ \t]*\(' => 14, + '\.SetScalar[ \t]*\(' => 15, + '\.SetVector[ \t]*\(' => 16, + '\.SetNormal[ \t]*\(' => 17, + '\.SetTCoord[ \t]*\(' => 18, + '\.SetTensor[ \t]*\(' => 19, + '.GetScalars[ \t]*\([a-zA-Z]+.*\)' => 20, + '.GetVectors[ \t]*\([a-zA-Z]+.*\)' => 21, + '.GetNormals[ \t]*\([a-zA-Z]+.*\)' => 22, + '.GetTCoords[ \t]*\([a-zA-Z]+.*\)' => 23, + '.GetTensors[ \t]*\([a-zA-Z]+.*\)' => 24, + '.InsertScalar[ \t]*\(' => 25, + '.InsertVector[ \t]*\(' => 26, + '.InsertNormal[ \t]*\(' => 27, + '.InsertTCoord[ \t]*\(' => 28, + '.InsertTensor[ \t]*\(' => 29, + '.InsertNextScalar[ \t]*\(' => 30, + '.InsertNextVector[ \t]*\(' => 31, + '.InsertNextNormal[ \t]*\(' => 32, + '.InsertNextTCoord[ \t]*\(' => 33, + '.InsertNextTensor[ \t]*\(' => 34, + '.GetActiveScalars' => 35, + '.GetActiveVectors' => 36, + '.GetActiveNormals' => 37, + '.GetActiveTCoords' => 38, + '.GetActiveTensors' => 39, + '.GetNumberOfScalars' => 40, + '.GetNumberOfVectors' => 41, + '.GetNumberOfNormals' => 42, + '.GetNumberOfTCoords' => 43, + '.GetNumberOfTensors' => 44, + '.SetNumberOfScalars' => 40, + '.SetNumberOfVectors' => 41, + '.SetNumberOfNormals' => 42, + '.SetNumberOfTCoords' => 43, + '.SetNumberOfTensors' => 44, + ); + +%javamessageids = ( + 'new[ \t]+vtkScalars[ \t]*\(\)' => 5, + 'new[ \t]+vtkVectors[ \t]*\(\)' => 6, + 'new[ \t]+vtkNormals[ \t]*\(\)' => 7, + 'new[ \t]+vtkTCoords[ \t]*\(\)' => 8, + 'new[ \t]+vtkTensors[ \t]*\(\)' => 9, + '\.GetScalar[ \t]*\(' => 10, + '\.GetVector[ \t]*\(' => 11, + '\.GetNormal[ \t]*\(' => 12, + '\.GetTCoord[ \t]*\(' => 13, + '\.GetTensor[ \t]*\(' => 14, + '\.SetScalar[ \t]*\(' => 15, + '\.SetVector[ \t]*\(' => 16, + '\.SetNormal[ \t]*\(' => 17, + '\.SetTCoord[ \t]*\(' => 18, + '\.SetTensor[ \t]*\(' => 19, + '.GetScalars[ \t]*\([a-zA-Z]+.*\)' => 20, + '.GetVectors[ \t]*\([a-zA-Z]+.*\)' => 21, + '.GetNormals[ \t]*\([a-zA-Z]+.*\)' => 22, + '.GetTCoords[ \t]*\([a-zA-Z]+.*\)' => 23, + '.GetTensors[ \t]*\([a-zA-Z]+.*\)' => 24, + '.InsertScalar[ \t]*\(' => 25, + '.InsertVector[ \t]*\(' => 26, + '.InsertNormal[ \t]*\(' => 27, + '.InsertTCoord[ \t]*\(' => 28, + '.InsertTensor[ \t]*\(' => 29, + '.InsertNextScalar[ \t]*\(' => 30, + '.InsertNextVector[ \t]*\(' => 31, + '.InsertNextNormal[ \t]*\(' => 32, + '.InsertNextTCoord[ \t]*\(' => 33, + '.InsertNextTensor[ \t]*\(' => 34, + '.GetActiveScalars' => 35, + '.GetActiveVectors' => 36, + '.GetActiveNormals' => 37, + '.GetActiveTCoords' => 38, + '.GetActiveTensors' => 39, + '.GetNumberOfScalars' => 40, + '.GetNumberOfVectors' => 41, + '.GetNumberOfNormals' => 42, + '.GetNumberOfTCoords' => 43, + '.GetNumberOfTensors' => 44, + '.SetNumberOfScalars' => 40, + '.SetNumberOfVectors' => 41, + '.SetNumberOfNormals' => 42, + '.SetNumberOfTCoords' => 43, + '.SetNumberOfTensors' => 44, + ); + +if ($language eq "c++") +{ + %messageids = %cxxmessageids; +} +elsif($language eq "tcl") +{ + %messageids = %tclmessageids; +} +elsif($language eq "python") +{ + %messageids = %pythonmessageids; +} +elsif($language eq "java") +{ + %messageids = %javamessageids; +} +else +{ + die "Unsupported language: $language.\n"; +} +@messages = ( + "> Encountered vtkScalars* : vtkScalars has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.\n", + "> Encountered vtkVectors* : vtkVectors has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.\n", + "> Encountered vtkNormals* : vtkNormals has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.\n", + "> Encountered vtkTCoords* : vtkTCoords has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.\n", + "> Encountered vtkTensors* : vtkTensors has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.\n", + "> Encountered vtkScalars constructor: vtkScalars has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.\n", + "> Encountered vtkVectors constructor: vtkVectors has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses. Note that you have to explicitly set the\n". + "> number of components. For example (in Tcl):\n". + "> vtkFloatArray vectors\n". + "> vectors SetNumberOfComponents 3\n", + "> Encountered vtkNormals constructor: vtkNormals has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.Note that you have to explicitly set the\n". + "> number of components. For example (in Tcl):\n". + "> vtkFloatArray normals\n". + "> normals SetNumberOfComponents 3\n", + "> Encountered vtkTCoords constructor: vtkTCoords has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.Note that you have to explicitly set the\n". + "> number of components. For example (in Tcl):\n". + "> vtkFloatArray tc\n". + "> tc SetNumberOfComponents 2\n", + "> Encountered vtkTensors constructor: vtkTensors has been\n". + "> deprecated. You should use vtkDataArray or one\n". + "> of it's subclasses.Note that you have to explicitly set the\n". + "> number of components. For example (in Tcl):\n". + "> vtkFloatArray tensors\n". + "> tensors SetNumberOfComponents 9\n", + "> Encountered vtkScalars::GetScalar() : vtkScalars has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetComponent(id, component)\n". + "> instead of GetScalar(id)\n" , + "> Encountered vtkVectors::GetVector(): vtkVectors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuple(id)\n". + "> instead of GetVector(id)\n" , + "> Encountered vtkNormals::GetNormal(): vtkNormals has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuple(id)\n". + "> instead of GetNormal(id)\n" , + "> Encountered vtkTCoords::GetTCoord(): vtkTCoords has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuple(id)\n". + "> instead of GetTCoord(id)\n" , + "> Encountered vtkTensors::GetTensors(): vtkTensors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuple(id)\n". + "> instead of GetTensor(id)\n" , + "> Encountered vtkScalars::SetScalar() : vtkScalars has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use SetComponent(id, component, value)\n". + "> instead of GetScalar(id)\n" , + "> Encountered vtkVectors::SetVector(): vtkVectors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use SetTuple(id, v)\n". + "> instead of SetVector(id, v)\n" , + "> Encountered vtkNormals::SetNormal(): vtkNormals has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use SetTuple(id,v)\n". + "> instead of SetNormal(id,v)\n" , + "> Encountered vtkTCoords::SetTCoord(): vtkTCoords has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use SetTuple(id,v)\n". + "> instead of SetTCoord(id,v)\n" , + "> Encountered vtkTensors::SetTensors(): vtkTensors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use SetTuple(id,v)\n". + "> instead of GetTensor(id,v)\n" , + "> Encountered vtkScalars::GetScalars() : vtkScalars has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuples()\n". + "> instead of GetScalars(id). Note that, unlike GetScalars(),\n". + "> GetTuples() requires that enough memory is allocated in the\n". + "> target array. See the documentation of vtkDataArray for more\n". + "> information.\n", + "> Encountered vtkVectors::GetVectors() : vtkVectors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuples()\n". + "> instead of GetVectors(id). Note that, unlike GetVectors(),\n". + "> GetTuples() requires that enough memory is allocated in the\n". + "> target array. See the documentation of vtkDataArray for more\n". + "> information.\n", + "> Encountered vtkNormals::GetNormals() : vtkNormals has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuples()\n". + "> instead of GetNormals(id). Note that, unlike GetNormals(),\n". + "> GetTuples() requires that enough memory is allocated in the\n". + "> target array. See the documentation of vtkDataArray for more\n". + "> information.\n", + "> Encountered vtkTCoords::GetTCoords() : vtkTCoords has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuples()\n". + "> instead of GetTCoords(id). Note that, unlike GetTCoords(),\n". + "> GetTuples() requires that enough memory is allocated in the\n". + "> target array. See the documentation of vtkDataArray for more\n". + "> information.\n", + "> Encountered vtkTensors::GetTensors() : vtkTensors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use GetTuples()\n". + "> instead of GetTensors(id). Note that, unlike GetTensors(),\n". + "> GetTuples() requires that enough memory is allocated in the\n". + "> target array. See the documentation of vtkDataArray for more\n". + "> information.\n", + "> Encountered vtkScalars::InsertScalar() : vtkScalars has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertComponent(),\n ". + "> InsertValue() or InsertTuple1() instead of InsertScalar()\n", + "> Encountered vtkVectors::InsertVector() : vtkVectors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertTuple(),\n ". + "> or InsertTuple3() instead of InsertVector()\n", + "> Encountered vtkNormals::InsertNormal() : vtkNormals has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertTuple(),\n ". + "> or InsertTuple3() instead of InsertNormal()\n", + "> Encountered vtkTCoords::InsertTCoord() : vtkTCoords has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertTuple(),\n ". + "> or InsertTuple2() instead of InsertTCoord()\n", + "> Encountered vtkTensors::InsertTensor() : vtkTensors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertTuple(),\n ". + "> or InsertTuple9() instead of InsertTensor()\n", + "> Encountered vtkScalars::InsertNextScalar() : vtkScalars has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertNextComponent(),\n ". + "> InsertNextValue() or InsertNextTuple1() instead of InsertNextScalar()\n", + "> Encountered vtkVectors::InsertNextVector() : vtkVectors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertNextTuple(),\n ". + "> or InsertNextTuple3() instead of InsertNextVector()\n", + "> Encountered vtkNormals::InsertNextNormal() : vtkNormals has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertNextTuple(),\n ". + "> or InsertNextTuple3() instead of InsertNextNormal()\n", + "> Encountered vtkTCoords::InsertNextTCoord() : vtkTCoords has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertNextTuple(),\n ". + "> or InsertNextTuple2() instead of InsertNextTCoord()\n", + "> Encountered vtkTensors::InsertNextTensor() : vtkTensors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use InsertNextTuple(),\n ". + "> or InsertNextTuple9() instead of InsertNextTensor()\n", + "> Replace vtkDataSetAttributes::GetActiveScalars() with \n". + "> vtkDataSetAttributes::GetScalars()\n", + "> Replace vtkDataSetAttributes::GetActiveVectors() with \n". + "> vtkDataSetAttributes::GetVectors()\n", + "> Replace vtkDataSetAttributes::GetActiveNormals() with \n". + "> vtkDataSetAttributes::GetNormals()\n", + "> Replace vtkDataSetAttributes::GetActiveTCoords() with \n". + "> vtkDataSetAttributes::GetTCoords()\n", + "> Replace vtkDataSetAttributes::GetActiveTensors() with \n". + "> vtkDataSetAttributes::GetTensors()\n", + "> Encountered vtkScalars::Set/GetNumberOfScalars() : vtkScalars has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use Set/GetNumberOfTuples()\n". + "> instead of Set/GetNumberOfScalars().\n", + "> Encountered vtkVectors::Set/GetNumberOfVectors() : vtkVectors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use Set/GetNumberOfTuples()\n". + "> instead of Set/GetNumberOfVectors().\n", + "> Encountered vtkNormals::Set/GetNumberOfNormals() : vtkNormals has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use Set/GetNumberOfTuples()\n". + "> instead of Set/GetNumberOfNormals().\n", + "> Encountered vtkTCoords::Set/GetNumberOfTCoords() : vtkTCoords has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use Set/GetNumberOfTuples()\n". + "> instead of Set/GetNumberOfTCoords().\n", + "> Encountered vtkTensors::Set/GetNumberOfTensors() : vtkTensors has been\n". + "> deprecated. You should replace this object with a\n". + "> vtkDataArray or one of it's subclasses and use Set/GetNumberOfTuples()\n". + "> instead of Set/GetNumberOfTensors().\n", + ); + + +if ( $print ) +{ + $i = 0; + foreach $key (@messages) + { + print "Message id $i:\n"; + print $key, "\n"; + $i++; + } + exit 0; +} + +foreach $filename (@ARGV) +{ + open(FPTR, "<$filename") or die "Could not open file $filename"; + if ($verbose) + { + print "Processing file: $filename\n"; + } + $i = 1; + while () + { + $line = $_; + foreach $key (keys %messageids) + { + if ( $line =~ m($key) ) + { + chomp $line; + if ($verbose) + { + print ">> File $filename line $i: ", + "\n$messages[$messageids{$key}]\n"; + } + else + { + print ">> File $filename line $i: ", + "Message $messageids{$key}\n"; + } + last; + } + } + $i++; + } +} + diff --git a/Utilities/Upgrading/FieldDataChanges.pdf b/Utilities/Upgrading/FieldDataChanges.pdf new file mode 100644 index 0000000..89e0299 Binary files /dev/null and b/Utilities/Upgrading/FieldDataChanges.pdf differ diff --git a/Utilities/Upgrading/FindWindowsMangledMethods.cmake b/Utilities/Upgrading/FindWindowsMangledMethods.cmake new file mode 100644 index 0000000..ace6e39 --- /dev/null +++ b/Utilities/Upgrading/FindWindowsMangledMethods.cmake @@ -0,0 +1,899 @@ +#=========================================================================== +# +# Program: Visualization Toolkit +# Module: $RCSfile: FindWindowsMangledMethods.cmake,v $ +# +# Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +# All rights reserved. +# See Copyright.txt or http://www.kitware.com/Copyright.htm for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even +# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the above copyright notice for more information. +# +#=========================================================================== + +# See README.WindowsMangling.txt for the purpose of this script. + +#----------------------------------------------------------------------------- +# Instructions to use this script: +# +# CMake version 2.0.x is required, but 2.0.5 or better is preferred. +# +# Set the current working directory to the top of a source tree and +# run this script with this command: +# +# cmake -P /path/to/FindWindowsMangledMethods.cmake +# +# A list of potentially mangled methods will be displayed as output. +# Each line will consist of a file name and a partial method +# signature. Note that Set/Get macros are capable of producing +# methods that might be mangled. These are also listed. + +IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.0) + MESSAGE(FATAL_ERROR "CMake 2.0 or higher is required for this script.") +ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.0) + +# List of symbols that might be mangled. +SET(SYMBOLS +AbnormalTermination +AbortSystemShutdown +AccessCheckAndAuditAlarm +AddAtom +AddFontResource +AddForm +AddJob +AddMonitor +AddPort +AddPrintProcessor +AddPrintProvidor +AddPrinter +AddPrinterConnection +AddPrinterDriver +AddPrinterDriverEx +AdvancedDocumentProperties +AnsiLower +AnsiLowerBuff +AnsiNext +AnsiPrev +AnsiToOem +AnsiToOemBuff +AnsiUpper +AnsiUpperBuff +AppendMenu +BackupEventLog +BeginUpdateResource +BuildCommDCB +BuildCommDCBAndTimeouts +CallMsgFilter +CallNamedPipe +CallWindowProc +CdChangerClassGuid +CdRomClassGuid +CertAddEncodedCertificateToSystemStore +CertGetNameString +CertNameToStr +CertOpenSystemStore +CertRDNValueToStr +CertStrToName +ChangeDisplaySettings +ChangeDisplaySettingsEx +ChangeMenu +ChangeServiceConfig +ChangeServiceConfig2 +CharLower +CharLowerBuff +CharNext +CharPrev +CharToOem +CharToOemBuff +CharUpper +CharUpperBuff +ChooseColor +ChooseFont +ClearEventLog +CommConfigDialog +CommDlg_OpenSave_GetFilePath +CommDlg_OpenSave_GetFilePathA +CommDlg_OpenSave_GetFilePathW +CommDlg_OpenSave_GetFolderIDList +CommDlg_OpenSave_GetFolderPath +CommDlg_OpenSave_GetFolderPathA +CommDlg_OpenSave_GetFolderPathW +CommDlg_OpenSave_GetSpec +CommDlg_OpenSave_GetSpecA +CommDlg_OpenSave_GetSpecW +CommDlg_OpenSave_HideControl +CommDlg_OpenSave_SetControlText +CommDlg_OpenSave_SetDefExt +CompareString +ConfigurePort +CopyAcceleratorTable +CopyCursor +CopyEnhMetaFile +CopyFile +CopyMemory +CopyMetaFile +CreateAcceleratorTable +CreateColorSpace +CreateDC +CreateDesktop +CreateDialog +CreateDialogA +CreateDialogIndirect +CreateDialogIndirectA +CreateDialogIndirectParam +CreateDialogIndirectW +CreateDialogParam +CreateDialogW +CreateDirectory +CreateDirectoryEx +CreateEnhMetaFile +CreateEvent +CreateFile +CreateFileMapping +CreateFont +CreateFontIndirect +CreateIC +CreateMDIWindow +CreateMailslot +CreateMetaFile +CreateMutex +CreateNamedPipe +CreateProcess +CreateProcessAsUser +CreatePropertySheetPage +CreateScalableFontResource +CreateSemaphore +CreateService +CreateWindow +CreateWindowA +CreateWindowEx +CreateWindowStation +CreateWindowW +CryptAcquireContext +CryptBinaryToString +CryptEnumProviderTypes +CryptEnumProviders +CryptGetDefaultProvider +CryptRetrieveObjectByUrl +CryptSetProvider +CryptSetProviderEx +CryptSignHash +CryptStringToBinary +CryptVerifySignature +DceErrorInqText +DdeCreateStringHandle +DdeInitialize +DdeQueryString +DecryptFile +DefDlgProc +DefFrameProc +DefHookProc +DefMDIChildProc +DefWindowProc +DefineDosDevice +DefineHandleTable +DeleteFile +DeleteForm +DeleteMonitor +DeletePort +DeletePrintProcessor +DeletePrintProvidor +DeletePrinterConnection +DeletePrinterData +DeletePrinterDataEx +DeletePrinterDriver +DeletePrinterDriverEx +DeletePrinterKey +DeviceCapabilities +DialogBox +DialogBoxA +DialogBoxIndirect +DialogBoxIndirectA +DialogBoxIndirectParam +DialogBoxIndirectW +DialogBoxParam +DialogBoxW +DiskClassGuid +DispatchMessage +DlgDirList +DlgDirListComboBox +DlgDirSelectComboBoxEx +DlgDirSelectEx +DoEnvironmentSubst +DocumentProperties +DragQueryFile +DrawState +DrawText +DrawTextEx +EncryptFile +EndUpdateResource +EnumCalendarInfo +EnumCalendarInfoEx +EnumDateFormats +EnumDateFormatsEx +EnumDependentServices +EnumDesktops +EnumDisplayDevices +EnumDisplaySettings +EnumDisplaySettingsEx +EnumFontFamilies +EnumFontFamiliesEx +EnumFonts +EnumForms +EnumICMProfiles +EnumJobs +EnumLanguageGroupLocales +EnumMonitors +EnumPorts +EnumPrintProcessorDatatypes +EnumPrintProcessors +EnumPrinterData +EnumPrinterDataEx +EnumPrinterDrivers +EnumPrinterKey +EnumPrinters +EnumProps +EnumPropsEx +EnumResourceLanguages +EnumResourceNames +EnumResourceTypes +EnumServicesStatus +EnumServicesStatusEx +EnumSystemCodePages +EnumSystemLanguageGroups +EnumSystemLocales +EnumTaskWindows +EnumTimeFormats +EnumUILanguages +EnumWindowStations +ExitWindows +ExpandEnvironmentStrings +ExtTextOut +ExtractAssociatedIcon +ExtractAssociatedIconEx +ExtractIcon +ExtractIconEx +FatalAppExit +FileEncryptionStatus +FillConsoleOutputCharacter +FillMemory +FindAtom +FindExecutable +FindFirstChangeNotification +FindFirstFile +FindNextFile +FindResource +FindResourceEx +FindText +FindWindow +FindWindowEx +FloppyClassGuid +FoldString +FormatMessage +FreeEnvironmentStrings +FreeModule +FreeProcInstance +GetAltTabInfo +GetAtomName +GetBValue +GetBinaryType +GetCPInfoEx +GetCValue +GetCalendarInfo +GetCharABCWidths +GetCharABCWidthsFloat +GetCharWidth +GetCharWidth32 +GetCharWidthFloat +GetCharacterPlacement +GetClassInfo +GetClassInfoEx +GetClassLong +GetClassLongPtr +GetClassLongPtrA +GetClassLongPtrW +GetClassName +GetClipboardFormatName +GetCommandLine +GetCompressedFileSize +GetComputerName +GetConsoleTitle +GetCurrencyFormat +GetCurrentDirectory +GetCurrentTime +GetDateFormat +GetDefaultCommConfig +GetDefaultPrinter +GetDiskFreeSpace +GetDiskFreeSpaceEx +GetDlgItemText +GetDriveType +GetEnhMetaFile +GetEnhMetaFileDescription +GetEnvironmentStringsA +GetEnvironmentVariable +GetExceptionCode +GetExceptionInformation +GetExpandedName +GetFileAttributes +GetFileAttributesEx +GetFileSecurity +GetFileTitle +GetFileVersionInfo +GetFileVersionInfoSize +GetFirmwareEnvironmentVariable +GetForm +GetFreeSpace +GetFullPathName +GetGValue +GetGeoInfo +GetGlyphOutline +GetICMProfile +GetJob +GetKValue +GetKerningPairs +GetKeyNameText +GetKeyboardLayoutName +GetLocaleInfo +GetLogColorSpace +GetLogicalDriveStrings +GetLongPathName +GetMValue +GetMenuItemInfo +GetMenuString +GetMessage +GetMetaFile +GetModuleFileName +GetModuleHandle +GetMonitorInfo +GetNamedPipeHandleState +GetNextWindow +GetNumberFormat +GetObject +GetOpenCardName +GetOpenFileName +GetOutlineTextMetrics +GetPrintProcessorDirectory +GetPrinter +GetPrinterData +GetPrinterDataEx +GetPrinterDriver +GetPrinterDriverDirectory +GetPrivateProfileInt +GetPrivateProfileSection +GetPrivateProfileSectionNames +GetPrivateProfileString +GetPrivateProfileStruct +GetProfileInt +GetProfileSection +GetProfileString +GetProp +GetRValue +GetSaveFileName +GetScode +GetServiceDisplayName +GetServiceKeyName +GetShortPathName +GetStartupInfo +GetStringTypeEx +GetSysModalWindow +GetSystemDirectory +GetSystemWindowsDirectory +GetTabbedTextExtent +GetTempFileName +GetTempPath +GetTextExtentExPoint +GetTextExtentPoint +GetTextExtentPoint32 +GetTextFace +GetTextMetrics +GetTimeFormat +GetUrlPolicyPermissions +GetUserName +GetUserObjectInformation +GetVersionEx +GetVolumeInformation +GetWindowLong +GetWindowLongPtr +GetWindowLongPtrA +GetWindowLongPtrW +GetWindowModuleFileName +GetWindowTask +GetWindowText +GetWindowTextLength +GetWindowsDirectory +GetYValue +GlobalAddAtom +GlobalDiscard +GlobalFindAtom +GlobalGetAtomName +GlobalLRUNewest +GlobalLRUOldest +GrayString +HandleToLong +HandleToULong +HandleToUlong +HasOverlappedIoCompleted +ImmConfigureIME +ImmEnumRegisterWord +ImmEscape +ImmGetCandidateList +ImmGetCandidateListCount +ImmGetCompositionFont +ImmGetCompositionString +ImmGetConversionList +ImmGetDescription +ImmGetGuideLine +ImmGetIMEFileName +ImmGetImeMenuItems +ImmGetRegisterWordStyle +ImmInstallIME +ImmIsUIMessage +ImmRegisterWord +ImmSetCompositionFont +ImmSetCompositionString +ImmUnregisterWord +InitiateSystemShutdown +InitiateSystemShutdownEx +InsertMenu +InsertMenuItem +Int32x32To64 +IntToPtr +InterlockedCompareExchangePointer +InterlockedExchangePointer +IsBadStringPtr +IsCharAlpha +IsCharAlphaNumeric +IsCharLower +IsCharUpper +IsContainerPartition +IsDialogMessage +IsEqualCLSID +IsEqualFMTID +IsEqualIID +IsFTPartition +IsHashValCompatible +IsLFNDrive +IsLoggingEnabled +IsRecognizedPartition +IsReparseTagMicrosoft +IsReparseTagNameSurrogate +IsValidDevmode +LimitEmsPages +LoadAccelerators +LoadBitmap +LoadCursor +LoadCursorFromFile +LoadIcon +LoadImage +LoadKeyboardLayout +LoadLibrary +LoadLibraryEx +LoadMenu +LoadMenuIndirect +LoadString +LocalDiscard +LockSegment +LogonUser +LogonUserEx +LongToHandle +LongToPtr +LookupAccountName +LookupAccountSid +LookupPrivilegeDisplayName +LookupPrivilegeName +LookupPrivilegeValue +MakeProcInstance +MapVirtualKey +MapVirtualKeyEx +MaxNumberOfEEInfoParams +MediumChangerClassGuid +MessageBox +MessageBoxEx +MessageBoxIndirect +ModifyMenu +MoveFile +MoveFileEx +MoveMemory +MultinetGetConnectionPerformance +NdrFcLong +NdrFcShort +NdrFieldOffset +NdrFieldPad +NdrMarshCCtxtHdl +NdrMarshConfStringHdr +NdrMarshSCtxtHdl +NdrUnMarshCCtxtHdl +NdrUnMarshConfStringHdr +NdrUnMarshSCtxtHdl +ObjectCloseAuditAlarm +ObjectDeleteAuditAlarm +ObjectOpenAuditAlarm +ObjectPrivilegeAuditAlarm +OemToAnsi +OemToAnsiBuff +OemToChar +OemToCharBuff +OpenBackupEventLog +OpenDesktop +OpenEncryptedFileRaw +OpenEvent +OpenEventLog +OpenFileMapping +OpenMutex +OpenPrinter +OpenSCManager +OpenSemaphore +OpenService +OpenWindowStation +OutputDebugStr +OutputDebugString +PageSetupDlg +PartitionClassGuid +PeekConsoleInput +PeekMessage +PlaySound +PolyTextOut +PostAppMessage +PostAppMessageA +PostAppMessageW +PostMessage +PostThreadMessage +PrintDlg +PrintDlgEx +PrinterMessageBox +PrivateExtractIcons +PrivilegedServiceAuditAlarm +PropSheet_AddPage +PropSheet_Apply +PropSheet_CancelToClose +PropSheet_Changed +PropSheet_GetCurrentPageHwnd +PropSheet_GetResult +PropSheet_GetTabControl +PropSheet_HwndToIndex +PropSheet_IdToIndex +PropSheet_IndexToHwnd +PropSheet_IndexToId +PropSheet_IndexToPage +PropSheet_InsertPage +PropSheet_IsDialogMessage +PropSheet_PageToIndex +PropSheet_PressButton +PropSheet_QuerySiblings +PropSheet_RebootSystem +PropSheet_RecalcPageSizes +PropSheet_RemovePage +PropSheet_RestartWindows +PropSheet_SetCurSel +PropSheet_SetCurSelByID +PropSheet_SetFinishText +PropSheet_SetHeaderSubTitle +PropSheet_SetHeaderTitle +PropSheet_SetTitle +PropSheet_SetWizButtons +PropSheet_UnChanged +PropagateResult +PropertySheet +PtrToInt +PtrToLong +PtrToShort +PtrToUint +PtrToUlong +PtrToUshort +QueryDosDevice +QueryServiceConfig +QueryServiceConfig2 +QueryServiceLockStatus +ReadConsole +ReadConsoleInput +ReadConsoleOutput +ReadConsoleOutputCharacter +ReadEventLog +RealGetWindowClass +RegConnectRegistry +RegCreateKey +RegCreateKeyEx +RegDeleteKey +RegDeleteValue +RegEnumKey +RegEnumKeyEx +RegEnumValue +RegLoadKey +RegOpenKey +RegOpenKeyEx +RegQueryInfoKey +RegQueryMultipleValues +RegQueryValue +RegQueryValueEx +RegReplaceKey +RegRestoreKey +RegSaveKey +RegSaveKeyEx +RegSetValue +RegSetValueEx +RegUnLoadKey +RegisterClass +RegisterClassEx +RegisterClipboardFormat +RegisterDeviceNotification +RegisterEventSource +RegisterServiceCtrlHandler +RegisterServiceCtrlHandlerEx +RegisterWindowMessage +RemoveDirectory +RemoveFontResource +RemoveProp +ReplaceText +ReportEvent +ResetDC +ResetPrinter +ResultFromScode +RpcAbnormalTermination +RpcAsyncGetCallHandle +RpcBindingFromStringBinding +RpcBindingInqAuthClient +RpcBindingInqAuthClientEx +RpcBindingInqAuthInfo +RpcBindingInqAuthInfoEx +RpcBindingSetAuthInfo +RpcBindingSetAuthInfoEx +RpcBindingToStringBinding +RpcEndExcept +RpcEndFinally +RpcEpRegister +RpcEpRegisterNoReplace +RpcExcept +RpcExceptionCode +RpcFinally +RpcMgmtEpEltInqNext +RpcMgmtInqServerPrincName +RpcNetworkInqProtseqs +RpcNetworkIsProtseqValid +RpcNsBindingExport +RpcNsBindingExportPnP +RpcNsBindingImportBegin +RpcNsBindingInqEntryName +RpcNsBindingLookupBegin +RpcNsBindingUnexport +RpcNsBindingUnexportPnP +RpcNsEntryExpandName +RpcNsEntryObjectInqBegin +RpcNsGroupDelete +RpcNsGroupMbrAdd +RpcNsGroupMbrInqBegin +RpcNsGroupMbrInqNext +RpcNsGroupMbrRemove +RpcNsMgmtBindingUnexport +RpcNsMgmtEntryCreate +RpcNsMgmtEntryDelete +RpcNsMgmtEntryInqIfIds +RpcNsProfileDelete +RpcNsProfileEltAdd +RpcNsProfileEltInqBegin +RpcNsProfileEltInqNext +RpcNsProfileEltRemove +RpcProtseqVectorFree +RpcServerInqCallAttributes +RpcServerInqDefaultPrincName +RpcServerRegisterAuthInfo +RpcServerUseProtseq +RpcServerUseProtseqEp +RpcServerUseProtseqEpEx +RpcServerUseProtseqEx +RpcServerUseProtseqIf +RpcServerUseProtseqIfEx +RpcStringBindingCompose +RpcStringBindingParse +RpcStringFree +RpcTryExcept +RpcTryFinally +RtlCopyMemory +RtlEqualMemory +RtlFillMemory +RtlMoveMemory +RtlZeroMemory +ScrollConsoleScreenBuffer +SearchPath +SecureZeroMemory +SendDlgItemMessage +SendMessage +SendMessageCallback +SendMessageTimeout +SendNotifyMessage +SetCalendarInfo +SetClassLong +SetClassLongPtr +SetClassLongPtrA +SetClassLongPtrW +SetComputerName +SetConsoleTitle +SetCurrentDirectory +SetDefaultCommConfig +SetDefaultPrinter +SetDlgItemText +SetEnvironmentStrings +SetEnvironmentVariable +SetFileAttributes +SetFileSecurity +SetFileShortName +SetFirmwareEnvironmentVariable +SetForm +SetICMProfile +SetJob +SetLocaleInfo +SetMenuItemInfo +SetPort +SetPrinter +SetPrinterData +SetPrinterDataEx +SetProp +SetSwapAreaSize +SetSysModalWindow +SetUrlPolicyPermissions +SetUserObjectInformation +SetVolumeLabel +SetWindowLong +SetWindowLongPtr +SetWindowLongPtrA +SetWindowLongPtrW +SetWindowText +SetWindowsHook +SetWindowsHookEx +ShellAbout +ShellExecute +ShellExecuteEx +ShellMessageBox +Shell_NotifyIcon +StartDoc +StartDocPrinter +StartService +StartServiceCtrlDispatcher +StoragePortClassGuid +SystemParametersInfo +TabbedTextOut +TapeClassGuid +TextOut +TranslateAccelerator +UintToPtr +UlongToHandle +UlongToPtr +UnlockResource +UnlockSegment +UnregisterClass +UpdateICMRegKey +UpdateResource +UuidFromString +UuidToString +VarBoolFromInt +VarBoolFromUint +VarBstrFromInt +VarBstrFromUint +VarCyFromInt +VarCyFromUint +VarDateFromInt +VarDateFromUint +VarDecFromInt +VarDecFromUint +VarI1FromInt +VarI1FromUint +VarI2FromInt +VarI2FromUint +VarI4FromI4 +VarI4FromInt +VarI4FromUint +VarI8FromI8 +VarI8FromInt +VarI8FromUint +VarIntFromBool +VarIntFromCy +VarIntFromDate +VarIntFromDec +VarIntFromDisp +VarIntFromI1 +VarIntFromI2 +VarIntFromI4 +VarIntFromI8 +VarIntFromR4 +VarIntFromR8 +VarIntFromStr +VarIntFromUI1 +VarIntFromUI2 +VarIntFromUI4 +VarIntFromUI8 +VarIntFromUint +VarR4FromInt +VarR4FromUint +VarR8FromInt +VarR8FromUint +VarUI1FromInt +VarUI1FromUint +VarUI2FromInt +VarUI2FromUint +VarUI4FromInt +VarUI4FromUI4 +VarUI4FromUint +VarUI8FromUI8 +VarUintFromBool +VarUintFromCy +VarUintFromDate +VarUintFromDec +VarUintFromDisp +VarUintFromI1 +VarUintFromI2 +VarUintFromI4 +VarUintFromI8 +VarUintFromInt +VarUintFromR4 +VarUintFromR8 +VarUintFromStr +VarUintFromUI1 +VarUintFromUI2 +VarUintFromUI4 +VarUintFromUI8 +VerFindFile +VerInstallFile +VerLanguageName +VerQueryValue +VerifyVersionInfo +VkKeyScan +VkKeyScanEx +VolumeClassGuid +WaitNamedPipe +WinExecError +WinHelp +WriteConsole +WriteConsoleInput +WriteConsoleOutput +WriteConsoleOutputCharacter +WriteOnceDiskClassGuid +WritePrivateProfileSection +WritePrivateProfileString +WritePrivateProfileStruct +WriteProfileSection +WriteProfileString +XcvDataZeroMemory +) + +# Construct regular expressions to look for methods or Set/Get macros +# that define names that might be mangled. +SET(DIRECT_REGEX "[^>A-Za-z0-9](") +SET(MACRO_REGEX "vtk[A-Za-z0-9]*Macro *\\((") +SET(SEP1 "") +SET(SEP2 "") +FOREACH(s ${SYMBOLS}) + SET(DIRECT_REGEX "${DIRECT_REGEX}${SEP1}${s}") + SET(SEP1 "|") + IF("${s}" MATCHES "^(Get|Set)") + STRING(REGEX REPLACE "^(Set|Get)(.+)$" "\\2" IVAR "${s}") + IF(IVAR) + SET(MACRO_REGEX "${MACRO_REGEX}${SEP2}${IVAR}") + SET(SEP2 "|") + ENDIF(IVAR) + ENDIF("${s}" MATCHES "^(Get|Set)") +ENDFOREACH(s) +SET(DIRECT_REGEX "${DIRECT_REGEX})\\([^)]*\\)") +SET(MACRO_REGEX "${MACRO_REGEX})[^A-Za-z0-9_][^)]*\\)") + +# Find all VTK class header files in the current directory and below. +FILE(GLOB_RECURSE VTK_CLASS_HEADERS "vtk*.h") + +# Look for potentially mangled names. +FOREACH(h ${VTK_CLASS_HEADERS}) + # Read this class header. + FILE(READ "${h}" CONTENTS) + + # Look for Set/Get macros defining methods with potentially mangled names. + STRING(REGEX MATCH "${MACRO_REGEX}" OUTPUT "${CONTENTS}") + IF(OUTPUT) + MESSAGE("${h}: ${OUTPUT}") + ENDIF(OUTPUT) + + # Look for methods with potentially mangled names. + STRING(REGEX MATCH "${DIRECT_REGEX}" OUTPUT "${CONTENTS}") + IF(OUTPUT) + MESSAGE("${h}: ${OUTPUT}") + ENDIF(OUTPUT) +ENDFOREACH(h) diff --git a/Utilities/Upgrading/NewPipeConvert.cmake b/Utilities/Upgrading/NewPipeConvert.cmake new file mode 100644 index 0000000..38729d8 --- /dev/null +++ b/Utilities/Upgrading/NewPipeConvert.cmake @@ -0,0 +1,190 @@ +# This file attempts to convert an old pipeline filter to a new pipeline +# filter. Run it with a -DCLASS=classname it will use that class name +# for processing + +IF (NOT DEFINED CLASS) + MESSAGE ("You did not specify the class to process. Usage: cmake -DCLASS=vtkMyClass -P NewPipeConvert" FATAL_ERROR) +ENDIF (NOT DEFINED CLASS) + +FILE (GLOB H_FILE ${CLASS}.h) +FILE (GLOB CXX_FILE ${CLASS}.cxx) + +# read in both files +FILE (READ ${H_FILE} H_CONTENTS) +FILE (READ ${CXX_FILE} CXX_CONTENTS) + +#================================================================ +# First do the H file +#================================================================ + +# convert vtkImageToImageFilter subclasses to subclass off of +# vtkImageAlgorithm, if it is threaded use threaded one +IF ("${CXX_CONTENTS}" MATCHES ".*ThreadedExecute.*") + STRING (REGEX REPLACE + "vtkImageToImageFilter" + "vtkThreadedImageAlgorithm" + H_CONTENTS "${H_CONTENTS}") + STRING (REGEX REPLACE + "vtkImageTwoInputFilter" + "vtkThreadedImageAlgorithm" + H_CONTENTS "${H_CONTENTS}") +ELSE ("${CXX_CONTENTS}" MATCHES ".*ThreadedExecute.*") + STRING (REGEX REPLACE + "vtkImageToImageFilter" + "vtkImageAlgorithm" + H_CONTENTS "${H_CONTENTS}") + STRING (REGEX REPLACE + "vtkImageSource" + "vtkImageAlgorithm" + H_CONTENTS "${H_CONTENTS}") + STRING (REGEX REPLACE + "vtkImageTwoInputFilter" + "vtkImageAlgorithm" + H_CONTENTS "${H_CONTENTS}") + STRING (REGEX REPLACE + "vtkDataSetToImageFilter" + "vtkImageAlgorithm" + H_CONTENTS "${H_CONTENTS}") +ENDIF ("${CXX_CONTENTS}" MATCHES ".*ThreadedExecute.*") + + +# polyDataAlgorithm +STRING (REGEX REPLACE + "vtkPolyDataToPolyDataFilter" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "ExecuteInformation[ \t]*\\([^,\)]*,[^\)]*\\)" + "ExecuteInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void ExecuteInformation[ \t]*\\([ \t]*\\)[ \t\n]*{[^}]*};" + "" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "ExecuteInformation[ \t]*\\([ \t]*\\)" + "ExecuteInformation (vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "ComputeInputUpdateExtent[ \t]*\\([^,]*,[^,\)]*\\)" + "RequestUpdateExtent (vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +FILE (WRITE ${H_FILE} "${H_CONTENTS}") + + +#================================================================ +# Now do the CXX files +#================================================================ + +STRING (REGEX REPLACE + "::ExecuteInformation[ \t]*\\([^{]*{" + "::ExecuteInformation (\n vtkInformation * vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add outInfo only once +IF (NOT "${CXX_CONTENTS}" MATCHES ".*::ExecuteInformation[^{]*{\n // get the info objects.*") + STRING (REGEX REPLACE + "::ExecuteInformation[ \t]*\\([^{]*{" + "::ExecuteInformation (\n vtkInformation * vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation* outInfo = outputVector->GetInformationObject(0);\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") +ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*::ExecuteInformation[^{]*{\n // get the info objects.*") + + +STRING (REGEX REPLACE + "::ComputeInputUpdateExtent[ \t]*\\([^,\)]*,[^,\)]*\\)" + "::RequestUpdateExtent (\n vtkInformation * vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add outInfo only once +IF (NOT "${CXX_CONTENTS}" MATCHES ".*::RequestUpdateExtent[^{]*{\n // get the info objects.*") + STRING (REGEX REPLACE + "::RequestUpdateExtent[ \t]*\\([^{]*{" + "::RequestUpdateExtent (\n vtkInformation * vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation* outInfo = outputVector->GetInformationObject(0);\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") +ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*::RequestUpdateExtent[^{]*{\n // get the info objects.*") + +STRING (REGEX REPLACE + "this->GetInput\\(\\)->GetWholeExtent\\(" + "inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()," + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "input->GetWholeExtent\\(" + "inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()," + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "inData->GetWholeExtent\\(" + "inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()," + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "this->GetOutput\\(\\)->SetWholeExtent[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),\\1,6" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "output->SetWholeExtent[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),\\1,6" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "outData->SetWholeExtent[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),\\1,6" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "this->GetOutput\\(\\)->SetOrigin[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::ORIGIN(),\\1,3" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "output->SetOrigin[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::ORIGIN(),\\1,3" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "outData->SetOrigin[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::ORIGIN(),\\1,3" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "this->GetOutput\\(\\)->SetSpacing[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::SPACING(),\\1,3" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "output->SetSpacing[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::SPACING(),\\1,3" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "outData->SetSpacing[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::SPACING(),\\1,3" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "output->SetScalarType[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::SCALAR_TYPE(),\\1" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "outData->SetScalarType[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::SCALAR_TYPE(),\\1" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "output->SetNumberOfScalarComponents[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::SCALAR_NUMBER_OF_COMPONENTS(),\\1" + CXX_CONTENTS "${CXX_CONTENTS}") +STRING (REGEX REPLACE + "outData->SetNumberOfScalarComponents[ \t\n]*\\(([^)]*)" + "outInfo->Set(vtkDataObject::SCALAR_NUMBER_OF_COMPONENTS(),\\1" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add some useful include files if needed +IF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + # do not do these replacements multiple times + IF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") + STRING (REGEX REPLACE + "vtkObjectFactory.h" + "vtkInformation.h\"\n#include \"vtkInformationVector.h\"\n#include \"vtkObjectFactory.h\"\n#include \"vtkStreamingDemandDrivenPipeline.h" + CXX_CONTENTS "${CXX_CONTENTS}") + ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") +ENDIF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + +FILE (WRITE ${CXX_FILE} "${CXX_CONTENTS}") diff --git a/Utilities/Upgrading/NewPipeConvertDataSet.cmake b/Utilities/Upgrading/NewPipeConvertDataSet.cmake new file mode 100644 index 0000000..ed0a794 --- /dev/null +++ b/Utilities/Upgrading/NewPipeConvertDataSet.cmake @@ -0,0 +1,77 @@ +# This file attempts to convert an old pipeline filter to a new pipeline +# filter. Run it with a -DCLASS=classname it will use that class name +# for processing + +IF (NOT DEFINED CLASS) + MESSAGE ("You did not specify the class to process. Usage: cmake -DCLASS=vtkMyClass -P NewPipeConvertDataSet" FATAL_ERROR) +ENDIF (NOT DEFINED CLASS) + +FILE (GLOB H_FILE ${CLASS}.h) +FILE (GLOB CXX_FILE ${CLASS}.cxx) + +# read in both files +FILE (READ ${H_FILE} H_CONTENTS) +FILE (READ ${CXX_FILE} CXX_CONTENTS) + +#================================================================ +# First do the H file +#================================================================ + +STRING (REGEX REPLACE + "vtkDataSetToDataSetFilter" + "vtkDataSetAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkSource" + "vtkDataSetAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+Execute[ \t]*\\([ \t]*\\)" + "int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ExecuteInformation[ \t]*\\([ \t]*\\)" + "int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ComputeInputUpdateExtents[ \t]*\\([ \t]*[^)]*\\)" + "int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +FILE (WRITE ${H_FILE} "${H_CONTENTS}") + +#================================================================ +# Now do the CXX files +#================================================================ + +STRING (REGEX REPLACE + "::Execute[ \t]*\\([^{]*{" + "::RequestData(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n\n // get the input and output\n vtkDataSet *input = vtkDataSet::SafeDownCast(\n inInfo->Get(vtkDataObject::DATA_OBJECT()));\n vtkDataSet *output = vtkDataSet::SafeDownCast(\n outInfo->Get(vtkDataObject::DATA_OBJECT()));\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ExecuteInformation[ \t]*\\([^{]*{" + "::RequestInformation(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ComputeInputUpdateExtents[ \t]*\\([^{]*{" + "::RequestUpdateExtent(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add some useful include files if needed +IF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + # do not do these replacements multiple times + IF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") + STRING (REGEX REPLACE + "vtkObjectFactory.h" + "vtkInformation.h\"\n#include \"vtkInformationVector.h\"\n#include \"vtkObjectFactory.h" + CXX_CONTENTS "${CXX_CONTENTS}") + ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") +ENDIF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + +FILE (WRITE ${CXX_FILE} "${CXX_CONTENTS}") diff --git a/Utilities/Upgrading/NewPipeConvertPointSet.cmake b/Utilities/Upgrading/NewPipeConvertPointSet.cmake new file mode 100644 index 0000000..19fc01c --- /dev/null +++ b/Utilities/Upgrading/NewPipeConvertPointSet.cmake @@ -0,0 +1,72 @@ +# This file attempts to convert an old pipeline filter to a new pipeline +# filter. Run it with a -DCLASS=classname it will use that class name +# for processing + +IF (NOT DEFINED CLASS) + MESSAGE ("You did not specify the class to process. Usage: cmake -DCLASS=vtkMyClass -P NewPipeConvertPointSet" FATAL_ERROR) +ENDIF (NOT DEFINED CLASS) + +FILE (GLOB H_FILE ${CLASS}.h) +FILE (GLOB CXX_FILE ${CLASS}.cxx) + +# read in both files +FILE (READ ${H_FILE} H_CONTENTS) +FILE (READ ${CXX_FILE} CXX_CONTENTS) + +#================================================================ +# First do the H file +#================================================================ + +STRING (REGEX REPLACE + "vtkPointSetToPointSetFilter" + "vtkPointSetAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+Execute[ \t]*\\([ \t]*\\)" + "int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ExecuteInformation[ \t]*\\([ \t]*\\)" + "int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ComputeInputUpdateExtents[ \t]*\\([ \t]*[^)]*\\)" + "int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +FILE (WRITE ${H_FILE} "${H_CONTENTS}") + +#================================================================ +# Now do the CXX files +#================================================================ + +STRING (REGEX REPLACE + "::Execute[ \t]*\\([^{]*{" + "::RequestData(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n\n // get the input and output\n vtkPointSet *input = vtkPointSet::SafeDownCast(\n inInfo->Get(vtkDataObject::DATA_OBJECT()));\n vtkPointSet *output = vtkPointSet::SafeDownCast(\n outInfo->Get(vtkDataObject::DATA_OBJECT()));\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ExecuteInformation[ \t]*\\([^{]*{" + "::RequestInformation(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ComputeInputUpdateExtents[ \t]*\\([^{]*{" + "::RequestUpdateExtent(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add some useful include files if needed +IF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + # do not do these replacements multiple times + IF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") + STRING (REGEX REPLACE + "vtkObjectFactory.h" + "vtkInformation.h\"\n#include \"vtkInformationVector.h\"\n#include \"vtkObjectFactory.h" + CXX_CONTENTS "${CXX_CONTENTS}") + ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") +ENDIF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + +FILE (WRITE ${CXX_FILE} "${CXX_CONTENTS}") diff --git a/Utilities/Upgrading/NewPipeConvertPolyData.cmake b/Utilities/Upgrading/NewPipeConvertPolyData.cmake new file mode 100644 index 0000000..c46f421 --- /dev/null +++ b/Utilities/Upgrading/NewPipeConvertPolyData.cmake @@ -0,0 +1,102 @@ +# This file attempts to convert an old pipeline filter to a new pipeline +# filter. Run it with a -DCLASS=classname it will use that class name +# for processing + +IF (NOT DEFINED CLASS) + MESSAGE ("You did not specify the class to process. Usage: cmake -DCLASS=vtkMyClass -P NewPipeConvertPolyData" FATAL_ERROR) +ENDIF (NOT DEFINED CLASS) + +FILE (GLOB H_FILE ${CLASS}.h) +FILE (GLOB CXX_FILE ${CLASS}.cxx) + +# read in both files +FILE (READ ${H_FILE} H_CONTENTS) +FILE (READ ${CXX_FILE} CXX_CONTENTS) + +#================================================================ +# First do the H file +#================================================================ + +STRING (REGEX REPLACE + "vtkPolyDataToPolyDataFilter" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkPolyDataSource" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkDataSetToPolyDataFilter" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkStructuredPointsToPolyDataFilter" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkRectilinearGridToPolyDataFilter" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkStructuredGridToPolyDataFilter" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkGenericDataSetToPolyDataFilter" + "vtkPolyDataAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+Execute[ \t]*\\([ \t]*\\)" + "int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ExecuteInformation[ \t]*\\([ \t]*\\)" + "int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ComputeInputUpdateExtents[ \t]*\\([ \t]*[^)]*\\)" + "int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +FILE (WRITE ${H_FILE} "${H_CONTENTS}") + +#================================================================ +# Now do the CXX files +#================================================================ + +STRING (REGEX REPLACE + "::Execute[ \t]*\\([^{]*{" + "::RequestData(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n\n // get the input and output\n vtkPolyData *input = vtkPolyData::SafeDownCast(\n inInfo->Get(vtkDataObject::DATA_OBJECT()));\n vtkPolyData *output = vtkPolyData::SafeDownCast(\n outInfo->Get(vtkDataObject::DATA_OBJECT()));\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ExecuteInformation[ \t]*\\([^{]*{" + "::RequestInformation(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ComputeInputUpdateExtents[ \t]*\\([^{]*{" + "::RequestUpdateExtent(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add some useful include files if needed +IF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + # do not do these replacements multiple times + IF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") + STRING (REGEX REPLACE + "vtkObjectFactory.h" + "vtkInformation.h\"\n#include \"vtkInformationVector.h\"\n#include \"vtkObjectFactory.h" + CXX_CONTENTS "${CXX_CONTENTS}") + ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") +ENDIF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + +FILE (WRITE ${CXX_FILE} "${CXX_CONTENTS}") diff --git a/Utilities/Upgrading/NewPipeConvertStructuredGrid.cmake b/Utilities/Upgrading/NewPipeConvertStructuredGrid.cmake new file mode 100644 index 0000000..56e91ed --- /dev/null +++ b/Utilities/Upgrading/NewPipeConvertStructuredGrid.cmake @@ -0,0 +1,77 @@ +# This file attempts to convert an old pipeline filter to a new pipeline +# filter. Run it with a -DCLASS=classname it will use that class name +# for processing + +IF (NOT DEFINED CLASS) + MESSAGE ("You did not specify the class to process. Usage: cmake -DCLASS=vtkMyClass -P NewPipeConvertStructuredGrid" FATAL_ERROR) +ENDIF (NOT DEFINED CLASS) + +FILE (GLOB H_FILE ${CLASS}.h) +FILE (GLOB CXX_FILE ${CLASS}.cxx) + +# read in both files +FILE (READ ${H_FILE} H_CONTENTS) +FILE (READ ${CXX_FILE} CXX_CONTENTS) + +#================================================================ +# First do the H file +#================================================================ + +STRING (REGEX REPLACE + "vtkStructuredGridSource" + "vtkStructuredGridAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkStructuredGridToStructuredGridFilter" + "vtkStructuredGridAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+Execute[ \t]*\\([ \t]*\\)" + "int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ExecuteInformation[ \t]*\\([ \t]*\\)" + "int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ComputeInputUpdateExtents[ \t]*\\([ \t]*[^)]*\\)" + "int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +FILE (WRITE ${H_FILE} "${H_CONTENTS}") + +#================================================================ +# Now do the CXX files +#================================================================ + +STRING (REGEX REPLACE + "::Execute[ \t]*\\([^{]*{" + "::RequestData(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n\n // get the input and output\n vtkStructuredGrid *input = vtkStructuredGrid::SafeDownCast(\n inInfo->Get(vtkDataObject::DATA_OBJECT()));\n vtkStructuredGrid *output = vtkStructuredGrid::SafeDownCast(\n outInfo->Get(vtkDataObject::DATA_OBJECT()));\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ExecuteInformation[ \t]*\\([^{]*{" + "::RequestInformation(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ComputeInputUpdateExtents[ \t]*\\([^{]*{" + "::RequestUpdateExtent(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add some useful include files if needed +IF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + # do not do these replacements multiple times + IF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") + STRING (REGEX REPLACE + "vtkObjectFactory.h" + "vtkInformation.h\"\n#include \"vtkInformationVector.h\"\n#include \"vtkObjectFactory.h" + CXX_CONTENTS "${CXX_CONTENTS}") + ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") +ENDIF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + +FILE (WRITE ${CXX_FILE} "${CXX_CONTENTS}") diff --git a/Utilities/Upgrading/NewPipeConvertUnstructuredGrid.cmake b/Utilities/Upgrading/NewPipeConvertUnstructuredGrid.cmake new file mode 100644 index 0000000..a183a33 --- /dev/null +++ b/Utilities/Upgrading/NewPipeConvertUnstructuredGrid.cmake @@ -0,0 +1,92 @@ +# This file attempts to convert an old pipeline filter to a new pipeline +# filter. Run it with a -DCLASS=classname it will use that class name +# for processing + +IF (NOT DEFINED CLASS) + MESSAGE ("You did not specify the class to process. Usage: cmake -DCLASS=vtkMyClass -P NewPipeConvertUnstructuredGrid" FATAL_ERROR) +ENDIF (NOT DEFINED CLASS) + +FILE (GLOB H_FILE ${CLASS}.h) +FILE (GLOB CXX_FILE ${CLASS}.cxx) + +# read in both files +FILE (READ ${H_FILE} H_CONTENTS) +FILE (READ ${CXX_FILE} CXX_CONTENTS) + +#================================================================ +# First do the H file +#================================================================ + +STRING (REGEX REPLACE + "vtkUnstructuredGridSource" + "vtkUnstructuredGridAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkUnstructuredGridToUnstructuredGridFilter" + "vtkUnstructuredGridAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkDataSetToUnstructuredGridFilter" + "vtkUnstructuredGridAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkStructuredPointsToUnstructuredGridFilter" + "vtkUnstructuredGridAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "vtkGenericDataSetToUnstructuredGridFilter" + "vtkUnstructuredGridAlgorithm" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+Execute[ \t]*\\([ \t]*\\)" + "int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ExecuteInformation[ \t]*\\([ \t]*\\)" + "int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +STRING (REGEX REPLACE + "void[ \t]+ComputeInputUpdateExtents[ \t]*\\([ \t]*[^)]*\\)" + "int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *)" + H_CONTENTS "${H_CONTENTS}") + +FILE (WRITE ${H_FILE} "${H_CONTENTS}") + +#================================================================ +# Now do the CXX files +#================================================================ + +STRING (REGEX REPLACE + "::Execute[ \t]*\\([^{]*{" + "::RequestData(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n\n // get the input and output\n vtkUnstructuredGrid *input = vtkUnstructuredGrid::SafeDownCast(\n inInfo->Get(vtkDataObject::DATA_OBJECT()));\n vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(\n outInfo->Get(vtkDataObject::DATA_OBJECT()));\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ExecuteInformation[ \t]*\\([^{]*{" + "::RequestInformation(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +STRING (REGEX REPLACE + "::ComputeInputUpdateExtents[ \t]*\\([^{]*{" + "::RequestUpdateExtent(\n vtkInformation *vtkNotUsed(request),\n vtkInformationVector **inputVector,\n vtkInformationVector *outputVector)\n{\n // get the info objects\n vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);\n vtkInformation *outInfo = outputVector->GetInformationObject(0);\n" + CXX_CONTENTS "${CXX_CONTENTS}") + +# add some useful include files if needed +IF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + # do not do these replacements multiple times + IF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") + STRING (REGEX REPLACE + "vtkObjectFactory.h" + "vtkInformation.h\"\n#include \"vtkInformationVector.h\"\n#include \"vtkObjectFactory.h" + CXX_CONTENTS "${CXX_CONTENTS}") + ENDIF (NOT "${CXX_CONTENTS}" MATCHES ".*vtkInformation.h.*") +ENDIF ("${CXX_CONTENTS}" MATCHES ".*vtkInformation.*") + +FILE (WRITE ${CXX_FILE} "${CXX_CONTENTS}") diff --git a/Utilities/Upgrading/README.WindowsMangling.txt b/Utilities/Upgrading/README.WindowsMangling.txt new file mode 100644 index 0000000..a3c67c4 --- /dev/null +++ b/Utilities/Upgrading/README.WindowsMangling.txt @@ -0,0 +1,214 @@ +As of December 15, 2004 VTK no longer includes windows.h by default in +most of its header files. This change results in a 70% compile time +reduction on Windows compilers because the compiler does not have to +parse the 280K lines of source the preprocessor produces from +windows.h. All VTK code that still includes windows.h does so through +vtkWindows.h which includes a minimal part of the real windows.h +header. This also avoids contaminating user code with the windows.h +API just because it included a VTK header. + +The main problem with windows.h is what we call the "windows mangling" +problem. In order to support UNICODE and ASCII characters APIs, +windows.h defines most of its API as macros. This code appears in the +windows header: + +WINUSERAPI int WINAPI GetClassNameA(HWND hWnd, LPSTR lpClassName, + int nMaxCount); +WINUSERAPI int WINAPI GetClassNameW(HWND hWnd, LPWSTR lpClassName, + int nMaxCount); +#ifdef UNICODE +#define GetClassName GetClassNameW +#else +#define GetClassName GetClassNameA +#endif // !UNICODE + +The idea for windows.h is that user code can simply call GetClassName +and automatically support both UNICODE and ASCII character sets based +on a preprocessor switch. The problem for everyone else is that the +windows API does not have any prefix on its functions, and the +preprocessor has no notion of namespaces or classes. Therefore when +windows.h is included it invisibly renames methods in VTK like +GetClassName to another name. Examples of other mangled names include +GetObject, SetProp, GetProp, RemoveProp, and CreateDirectory. In fact +there are over 500 such names in the windows API. + +Now consider what happens in each of these cases: + +1.) VTK includes windows.h everywhere (as it did previously). In this + case the methods are always renamed for all VTK code and all user + code that includes a VTK header. The method GetClassNameA is + actually visible as an export from the DLL. Since the renaming is + consistent then user code links correctly to VTK libraries. + + However, applications and other libraries do not necessarily + include VTK or windows.h in all of their sources. When this + outside code uses methods that are mangled by windows.h then they + get mangled in some translation units but not others. This + results in linking errors within the outside application for no + other reason than that it included a VTK header! + + Also, when VTK is built without UNICODE defined then all the + methods are renamed to have "A" at the end. If the user + application defines UNICODE and includes a VTK header then the + methods get renamed to have "W" at the end, which results in + unresolved symbols like "GetClassNameW". Then the user complains + and is told he/she has to rebuild VTK from scratch with UNICODE + defined. Basically VTK must be built separately for ASCII and + UNICODE applications. + +2.) VTK does not include windows.h everywhere. In this case the + methods are not renamed when VTK is built. The method + GetClassName is visible as an export from the DLL. User code that + includes windows.h before a VTK header will cause the method to be + renamed in the user's translation units. This will cause + unresolved symbols with names like "GetClassNameA" or + "GetClassNameW". + +The solution to this problem is to start by NOT including windows.h +everywhere. This avoids all the problems listed in case 1 above. In +order to avoid the problems listed in case 2, we rename all affected +methods to have names that do not get mangled. For example, +GetClassName becomes GetNameOfClass. In order to maintain +compatibility with application code, the old names of the methods must +still be provided. We now export all three possible names of the +original method from the library. In the case of GetClassName, the +names "GetClassName", "GetClassNameA", and "GetClassNameW" are all +provided as methods in the class and exported from the library. This +way when user code calls the method it does not matter which name it +gets because all three names are available. + +Here is how all three names can be provided in a VTK header regardless +of whether windows.h has been included before it: + +// See vtkWin32Header.h for definition of VTK_WORKAROUND_WINDOWS_MANGLE. +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define GetClassNameA GetClassName +# define GetClassNameW GetClassName +#endif + const char* GetClassName() const; +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef GetClassNameW +# undef GetClassNameA + //BTX + const char* GetClassNameA() const; + const char* GetClassNameW() const; + //ETX +#endif + +The method GetClassName has three cases. If windows.h is not included +then it is not mangled and the name is provided. If windows.h is +included and UNICODE is not defined then GetClassName gets mangled to +GetClassNameA, but then gets replaced by GetClassName again. The +preprocessor will not recursively expand a macro, so replacement stops +there and the GetClassName method is declared. When UNICODE is +defined the same process occurs but through GetClassNameW instead. +The methods GetClassNameA and GetClassNameW are not mangled so they +can be provided directly. They are surrounded by a BTX/ETX pair +because they should not be wrapped since scripting language code will +not be mangled by windows.h. + +Now that all three names are provided we can address the fact that +GetClassName is supposed to be a virtual function. When a subclass +wants to override a method with a mangled name it has to use this same +trick to override all three names. Existing user code that tries to +override the function will only replace one of the three names, and it +will not implement the new unmangled name at all. It is not possible +to get this code to work out-of-the-box, but we can at least produce a +compiler error to get the user's attention. We change the signature +of the three possible mangled names to: + + virtual const char* const GetClassName() const; + virtual const char* const GetClassNameA() const; + virtual const char* const GetClassNameW() const; + +and provide the new name with the original signature: + + virtual const char* GetNameOfClass() const; + +When existing code tries to override the original method it will get a +compiler error that the return type does not match due to the extra +"const" qualifier. This qualifier is otherwise meaningless and does +not affect calls to the method. When the user encounters the error +and reads the source with the new signature, it will be clear that the +method is deprecated and that the replacement is called +GetNameOfClass. The user code can then be modified to override the +new method name. + +Users can detect places in their own code that may need modification +by using this cmake script: + + VTK/Utilities/Upgrading/FindWindowsMangledMethods.cmake + +There are three backward-compatibility issues: + +1.) User code that used the windows API without including windows.h + that worked before because VTK included it will now break until + the explicit inclusion is added. This is considered acceptable + because the code was technically wrong in the first place. As a + quick-fix, users can define VTK_INCLUDE_WINDOWS_H in their + application and VTK will include windows.h as it did before. + +2.) The virtual methods that have been renamed and replaced as + described above must be renamed in user code. + +3.) All functions that fall victim to mangling have been deprecated. + User code will work (with warnings) but should be modified to call + the new non-mangled versions of the methods. VTK 5.0 includes + support for the original names but it will be removed in a future + version. Use the VTK_LEGACY_REMOVE setting when building VTK to + help make sure your application can build without using deprecated + code. + +Frequently Proposed Alternatives: + +Several people have proposed alternatives that they think solve the +problem with less of a backward compatibility problem. Here are some +of the common proposals and the reasons they were rejected: + +1.) Use #undef to avoid the name mangling altogether. + + If VTK includes windows.h and then does the #undef then user code + will not be able to access the windows API through the standard + means. If VTK does not include windows.h and uses #undef just in + case the user included windows.h first then user code can still + include windows.h after the VTK header and then their calls to VTK + methods will be mangled and will not compile. + +2.) Do not include windows.h but instead provide the same mangled + names by defining the macros in VTK the same way windows.h does. + + The idea behind this solution is that the compile time improvement + is achieved without breaking the previous mangling behavior. This + solution does not address the problems when users build VTK + without UNICODE and then build their application with UNICODE. It + defines macros in VTK that are supposed to be defined in a system + header. This is always dangerous. The solution used above does + not every actually change or redefine any macros defined by + windows.h. It just temporarily defines extra macros. + +3.) Use the above solution but change VTK_INCLUDE_WINDOWS_H to a + VTK_DO_NOT_INCLUDE_WINDOWS_H so that the previous default behavior + of including windows.h is preserved for user applications. VTK + can define VTK_DO_NOT_INCLUDE_WINDOWS_H when it is building + itself. + + This helps existing applications but will also allow new + applications to be written that do not include windows.h properly. + It will also prevent the compile-time improvements from + propagating to application code by default. The policy we are + trying to achieve is that including a VTK header should not do + anything but define VTK... and vtk... symbols to avoid namespacing + violations. We are willing to let users break this policy by + defining macros but we do not want to require users to define + macros to get this policy. + +NOTE: Since GetClassName is so widely used it was decided that it +would not be renamed or deprecated at this time. The documentation +above uses GetClassName as an example but not all of these changes +were actually applied to it in VTK. All changes were applied to other +offending methods, but only enough changes were applied to +GetClassName to get it to work whether or not windows.h is included or +UNICODE is defined. The method is no longer virtual so user code must +define a GetClassNameInternal protected method instead of GetClassName +in order to override it. Since most user code defines the method with +vtkTypeRevisionMacro anyway this should not require many changes. diff --git a/Utilities/Upgrading/README.txt b/Utilities/Upgrading/README.txt new file mode 100644 index 0000000..5af95d1 --- /dev/null +++ b/Utilities/Upgrading/README.txt @@ -0,0 +1,47 @@ +This package includes information about changes in VTK since last release +and utilities for upgrading to VTK 4.0. + +Two pdf files and two perl scripts are included: + +FieldDataChanges.pdf: + This document discusses changes to vtkDataSetAttributes, vtkPointData, + vtkCellData and vtkFieldData. + +AttributeChanges.pdf: + This document discusses changes to the way VTK handles attributes. + It focuses on the removal of vtkAttributeData and it's subclasses + (vtkScalars, vtkVectors, vtkNormals, vtkTCoords, vtkTensors). + +DiagAttribute.pl : + This script tries to find deprecated attribute data classes and + methods and warns the user whenever it finds them. It also suggests + possible modification to bring code up to date. + +UpgradeFrom32.pl: + This script tries to find deprecated classes and methods and replace + them with new classes/methods. Please note that it can not fix all + possible problems. However, it should be relatively easy to trace + those problems from compilation errors. + + +Here is the related entry from VTK FAQ at +http://public.kitware.com/cgi-bin/vtkfaq : + +6.7. Changes in VTK since 3.2 + +* Changes to vtkDataSetAttributes, vtkFieldData and vtkDataArray: All attributes (scalars, vectors...) are now stored in the field data as vtkDataArray's. vtkDataSetAttributes became a sub-class of vtkFieldData. For backwards compatibility, the interface which allows setting/getting the attributes the old way (by passing in a sub-class of vtkAttributeData such as vtkScalars) is still supported but it will be removed in the future. Therefore, the developers should use the new interface which requires passing in a vtkDataArray to set an attribute. vtkAttributeData and it's sub-classes (vtkScalars, vtkVectors...) will be deprectated in the near future; developers should use vtkDataArray and it's sub-classes instead. We are in the process of removing the use of these classes from vtk filters. + +* Subclasses of vtkAttributeData (vtkScalars, vtkVectors, vtkNormals, vtkTCoords, vtkTensors) were removed. As of VTK 4.0, vtkDataArray and it's sub-classes should be used to represent attributes and fields. Detailed description of the changes and utilities for upgrading from 3.2 to 4.0 can be found in the package http://public.kitware.com/VTK/files/Upgrading.zip. + +* Improved support for parallel visualization: vtkMultiProcessController and it's sub-classes have been re-structured and mostly re-written. The functionality of vtkMultiProcessController have been re-distributed between vtkMultiProcessController and vtkCommunicator. vtkCommunicator is responsible of sending/receiving messages whereas vtkMultiProcessController (and it's subclasses) is responsible of program flow/control (for example processing rmi's). New classes have been added to the Parallel directory. These include vtkCommunicator, vtkMPIGroup, vtkMPICommunicator, vtkSharedMemoryCommunicator, vtkMPIEventLog... There is now a tcl interpreter which supports parallel scripts. It is called pvtk and can be build on Windows and Unix. Examples for both Tcl and C++ can be found in the examples directories. + +* vtkSocketCommunicator and vtkSocketController have been added. These support message passing via BSD sockets. Best used together with input-output ports. + +* vtkIterativeClosestPointTransform has been added. This class is an implementation of the ICP algorithm. It matches two surfaces using the iterative closest point (ICP) algorithm. The core of the algorithm is to match each vertex in one surface with the closest surface point on the other, then apply the transformation that modify one surface to best match the other (in a least square sense). + +* The SetFileName, SaveImageAsPPM and related methods in vtkRenderWindow have been removed. vtkWindowToImageFilter combined with any of the image writers provides greater functionality. + +* Support for reading and writing PGM and JPEG images has been included. + + + diff --git a/Utilities/Upgrading/TheNewVTKPipeline.pdf b/Utilities/Upgrading/TheNewVTKPipeline.pdf new file mode 100644 index 0000000..5a18fa4 Binary files /dev/null and b/Utilities/Upgrading/TheNewVTKPipeline.pdf differ diff --git a/Utilities/Upgrading/UpgradeFrom32.pl b/Utilities/Upgrading/UpgradeFrom32.pl new file mode 100644 index 0000000..ed8a4f1 --- /dev/null +++ b/Utilities/Upgrading/UpgradeFrom32.pl @@ -0,0 +1,318 @@ +#!/usr/bin/env perl + +# This script tries to find deprecated classes and methods and replace +# them with new classes/methods. Please note that it can not fix all +# possible problems. However, it should be relatively easy to trace +# those problems from compilation errors. + +use Getopt::Long; + +if (!GetOptions("language:s" => \$language, + "help" => \$help, + "update" => \$update, + "print-messages" => \$print)) +{ + die; +} + +if (!$language) +{ + $language = "c++"; +} + +if ( !$print && ($#ARGV < 0 || $help) ) +{ + print "Usage: $0 [--language {c++ | tcl | python | java}] ", + "[--help] [--print-messages] file1 [file2 ...]\n"; + exit; +} + + +@cxxmessageids = + ( + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\([ ]*\)', 0, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_CHAR\s*,\s*([1-4])\s*\);', 4, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_SHORT\s*,\s*([1-4])\s*\);', 5, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_SHORT\s*,\s*([1-4])\s*\);', 25, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_INT\s*,\s*([1-4])\s*\);', 17, + 'vtkScalars\.h', 1, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*\)', 2, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_CHAR\s*,\s*([1-4])\s*\);', 6, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_SHORT\s*,\s*([1-4])\s*\);', 7, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_SHORT\s*,\s*([1-4])\s*\);', 26, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_INT\s*,\s*([1-4])\s*\);', 18, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_INT\s*\);', 19, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_CHAR\s*\);', 20, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_SHORT\s*\);', 21, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_SHORT\s*\);', 27, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_CHAR\s*\);', 22, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_UNSIGNED_SHORT\s*\);', 23, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_SHORT\s*\);', 28, + '([a-zA-Z0-9_-]*)\s*=\s*vtkScalars::New\(\s*VTK_INT\s*\);', 24, + 'vtkScalars\s*\*\s*([a-zA-Z0-9_-]*)', 3, + 'GetScalar\s*\(', 8, + 'SetScalar\s*\(', 9, + 'InsertScalar\s*\(', 10, + 'InsertNextScalar\s*\(', 11, + '(GetScalars\s*\(\s*[-a-zA-Z0-9_\*]+\s*\))', 12, + 'SetNumberOfScalars\s*\(', 13, + 'GetNumberOfScalars\s*\(', 16, + 'GetActiveScalars', 14, + 'vtkScalars([^a-zA-Z0-9])', 15, + + + 'vtkVectors\s*\*\s*([a-zA-Z0-9_-]*)\s*=[ \t]vtkVectors::New\([ ]*\)\s*;', 100, + 'vtkVectors\.h', 1, + '([a-zA-Z0-9_-]*)\s*=\s*vtkVectors::New\(\s*\)', 102, + 'vtkVectors\s*\*\s*([a-zA-Z0-9_-]*)\s', 3, + 'GetVector\s*\(', 108, + 'SetVector\s*\(([^,]*),([^\),]*)\)', 109, + 'SetVector\s*\(([^,]*),([^,]*),([^,]*),([^\),]*)\)', 115, + 'InsertVector\s*\(', 110, + 'InsertNextVector\s*\(', 111, + '(GetVectors\s*\(\s*[-a-zA-Z0-9_\*]+\s*\))', 12, + 'SetNumberOfVectors\s*\(', 113, + 'GetNumberOfVectors\s*\(', 16, + 'GetActiveVectors', 114, + 'vtkVectors([^a-zA-Z0-9])', 15, + + 'vtkNormals\s*\*\s*([a-zA-Z0-9_-]*)\s*=[ \t]vtkNormals::New\([ ]*\)\s*;', 100, + 'vtkNormals\.h', 1, + '([a-zA-Z0-9_-]*)\s*=\s*vtkNormals::New\(\s*\)', 102, + 'vtkNormals\s*\*\s*([a-zA-Z0-9_-]*)\s', 3, + 'GetNormal\s*\(', 108, + 'SetNormal\s*\(([^,]*),([^\),]*)\)', 109, + 'SetNormal\s*\(([^,]*),([^,]*),([^,]*),([^\),]*)\)', 115, + 'InsertNormal\s*\(', 110, + 'InsertNextNormal\s*\(', 111, + '(GetNormals\s*\(\s*[-a-zA-Z0-9_\*]+\s*\))', 12, + 'SetNumberOfNormals\s*\(', 113, + 'GetNumberOfNormals\s*\(', 16, + 'GetActiveNormals', 214, + 'vtkNormals([^a-zA-Z0-9])', 15, + + 'vtkTCoords\s*\*\s*([a-zA-Z0-9_-]*)\s*=[ \t]vtkTCoords::New\([ ]*\)\s*;', 300, + 'vtkTCoords\.h', 1, + '([a-zA-Z0-9_-]*)\s*=\s*vtkTCoords::New\(\s*\)', 302, + 'vtkTCoords\s*\*\s*([a-zA-Z0-9_-]*)\s', 3, + 'GetTCoord\s*\(', 108, + 'SetTCoord\s*\(([^,]*),([^\),]*)\)', 109, + 'InsertTCoord\s*\(', 110, + 'InsertNextTCoord\s*\(', 111, + '(GetTCoords\s*\(\s*[-a-zA-Z0-9_\*]+\s*\))', 12, + 'SetNumberOfTCoords\s*\(', 113, + 'GetNumberOfTCoords\s*\(', 16, + 'GetActiveTCoords', 314, + 'vtkTCoords([^a-zA-Z0-9])', 15, + + 'vtkTensors\s*\*\s*([a-zA-Z0-9_-]*)\s*=[ \t]vtkTensors::New\([ ]*\)\s*;', 400, + 'vtkTensors\.h', 1, + '([a-zA-Z0-9_-]*)\s*=\s*vtkTensors::New\(\s*\)', 402, + 'vtkTensors\s*\*\s*([a-zA-Z0-9_-]*)\s', 3, + 'GetTensor\s*\(', 108, + 'SetTensor\s*\(([^,]*),([^\),]*)\)', 109, + 'InsertTensor\s*\(', 110, + 'InsertNextTensor\s*\(', 111, + '(GetTensors\s*\(\s*[-a-zA-Z0-9_\*]+\s*\))', 12, + 'SetNumberOfTensors\s*\(', 113, + 'GetNumberOfTensors\s*\(', 16, + 'GetActiveTensors', 414, + 'vtkTensors([^a-zA-Z0-9])', 15, + + 'GetPointData\(\)->GetFieldData\(', 1000, + 'GetCellData\(\)->GetFieldData\(', 1001, + 'SaveImageAsPPM\s*\(', 1002, + ); + + +%cxxreps = + ( + 0 => 'vtkFloatArray \*$1 = vtkFloatArray::New\(\)', + 1 => 'vtkFloatArray\.h', + 2 => '$1 = vtkFloatArray::New\(\)', + 3 => 'vtkDataArray \*$1', + 4 => 'vtkUnsignedCharArray \*$1 = vtkUnsignedCharArray::New\(\); $1->SetNumberOfComponents\($2\);', + 5 => 'vtkUnsignedShortArray \*$1 = vtkUnsignedShortArray::New\(\); $1->SetNumberOfComponents\($2\);', + 6 => '$1 = vtkUnsignedCharArray::New\(\); $1->SetNumberOfComponents\($2\);', + 7 => '$1 = vtkUnsignedShortArray::New\(\); $1->SetNumberOfComponents\($2\);', + 8 => 'GetTuple1\(', + 9 => 'SetTuple1\(', + 10 => 'InsertTuple1\(', + 11 => 'InsertNextTuple1\(', + 12 => '$1 \/\/ Use GetTuples here instead ', + 13 => 'SetNumberOfTuples\(', + 14 => 'GetScalars', + 15 => 'vtkDataArray$1', + 16 => 'GetNumberOfTuples\(', + 17 => 'vtkIntArray \*$1 = vtkIntArray::New\(\); $1->SetNumberOfComponents\($2\);', + 18 => '$1 = vtkIntArray::New\(\); $1->SetNumberOfComponents\($2\);', + 19 => 'vtkIntArray \*$1 = vtkIntArray::New\(\);', + 20 => 'vtkUnsignedCharArray \*$1 = vtkUnsignedCharArray::New\(\);', + 21 => 'vtkUnsignedShortArray \*$1 = vtkUnsignedShortArray::New\(\);', + 22 => '$1 = vtkUnsignedCharArray::New\(\);', + 23 => '$1 = vtkUnsignedShortArray::New\(\);', + 24 => '$1 = vtkIntArray::New\(\);', + 25 => 'vtkShortArray \*$1 = vtkShortArray::New\(\); $1->SetNumberOfComponents\($2\);', + 26 => '$1 = vtkShortArray::New\(\); $1->SetNumberOfComponents\($2\);', + 27 => 'vtkShortArray \*$1 = vtkShortArray::New\(\);', + 28 => '$1 = vtkShortArray::New\(\);', + + + 100 => 'vtkFloatArray \*$1 = vtkFloatArray::New\(\); $1->SetNumberOfComponents\(3\);', + 102 => '$1 = vtkFloatArray::New\(\); $1->SetNumberOfComponents\(3\)', + 108 => 'GetTuple\(', + 109 => 'SetTuple\($1,$2\)', + 110 => 'InsertTuple\(', + 111 => 'InsertNextTuple\(', + 113 => 'SetNumberOfTuples\(', + 114 => 'GetVectors', + 115 => 'SetTuple3\($1,$2,$3,$4\)', + + 214 => 'GetNormals', + + 300 => 'vtkFloatArray \*$1 = vtkFloatArray::New\(\); $1->SetNumberOfComponents\(2\);', + 302 => '$1 = vtkFloatArray::New\(\); $1->SetNumberOfComponents\(2\)', + 314 => 'GetTCoords', + + 400 => 'vtkFloatArray \*$1 = vtkFloatArray::New\(\); $1->SetNumberOfComponents\(9\);', + 402 => '$1 = vtkFloatArray::New\(\); $1->SetNumberOfComponents\(9\)', + 414 => 'GetTensors', + + 1000 => 'GetPointData\(', + 1001 => 'GetCellData\(', + 1002 => 'SaveImageAsPPM\( \/\/ Use a vtkWindowToImageFilter instead of SaveImageAsPPM', + ); + + +@tclmessageids = + ( + 'vtkScalars\s+([a-zA-Z0-9\$_-]*)', 0, + 'SetScalar\s+(\S+)\s*(\S+)', 1, + 'InsertScalar\s+', 2, + 'InsertNextScalar\s+', 3, + 'SetNumberOfScalars\s+', 4, + 'GetNumberOfScalars\s+', 5, + 'GetActiveScalars\s+', 6, + + 'vtkVectors\s+([a-zA-Z0-9\$_-]*)', 100, + 'SetVector\s+(\S+)\s*(\S+)\s*(\S+)\s*(\S+)', 101, + 'InsertVector\s+', 102, + 'InsertNextVector\s+', 103, + 'SetNumberOfVectors\s+', 4, + 'GetNumberOfVectors\s+', 5, + 'GetActiveVectors\+', 106, + + 'vtkNormals\s+([a-zA-Z0-9\$_-]*)', 100, + 'SetNormal\s+(\S+)\s*(\S+)\s*(\S+)\s*(\S+)', 101, + 'InsertNormal\s+', 102, + 'InsertNextNormal\s+', 103, + 'SetNumberOfNormals\s+', 4, + 'GetNumberOfNormals\s+', 5, + 'GetActiveNormals\+', 206, + + 'vtkTCoords\s+([a-zA-Z0-9\$_-]*)', 300, + 'SetTCoord\s+(\S+)\s*(\S+)\s*(\S+)\s*(\S+)', 101, + 'InsertTCoord\s+', 102, + 'InsertNextTCoord\s+', 103, + 'SetNumberOfTCoords\s+', 4, + 'GetNumberOfTCoords\s+', 5, + 'GetActiveTCoords\s+', 306, + + 'GetPointData\s*\]\s+GetFieldData\s*\]', 1000, + 'GetCellData\s*\]\s+GetFieldData\s*\]', 1001, + 'SaveImageAsPPM\s*', 1002, + 'GetImageWindow', 1003, + 'catch\s*\{\s*load\s*vtktcl\s*\}', 1004, + 'source\s*\$VTK_TCL\/vtkInt\.tcl', 1005, + 'source\s*\$VTK_TCL\/colors\.tcl', 1006, + ); + +%tclreps = + ( + 0 => 'vtkFloatArray $1', + 1 => 'SetTuple1 $1 $2', + 2 => 'InsertTuple1 ', + 3 => 'InsertNextTuple1 ', + 4 => 'SetNumberOfTuples ', + 5 => 'GetNumberOfTuples ', + 6 => 'GetScalars ', + + 100 => 'vtkFloatArray $1; $1 SetNumberOfComponents 3', + 101 => 'SetTuple3 $1 $2 $3 $4', + 102 => 'InsertTuple3 ', + 103 => 'InsertNextTuple3 ', + 106 => 'GetVectors ', + + 206 => 'GetNormals ', + + 300 => 'vtkFloatArray $1; $1 SetNumberOfComponents 2', + 306 => 'GetTCoords ', + + 1000 => 'GetPointData\]', + 1001 => 'GetCellData\]', + 1002 => 'SaveImageAsPPM \# Use a vtkWindowToImageFilter instead of SaveImageAsPPM', + 1003 => 'GetRenderWindow', + 1004 => 'package require vtk', + 1005 => 'package require vtkinteraction', + 1006 => 'package require vtktesting', + ); + +if ($language eq "c++") +{ + @messageids = @cxxmessageids; + %reps = %cxxreps; +} +elsif($language eq "tcl") +{ + @messageids = @tclmessageids; + %reps = %tclreps; +} + +else +{ + die "Unsupported language: $language.\n"; +} + +if ( $print ) +{ + $i = 0; + foreach $key (@messages) + { + print "Message id $i:\n"; + print $key, "\n"; + $i++; + } + exit 0; +} + +foreach $filename (@ARGV) +{ + + open(FPTR, "<$filename") or die "Could not open file $filename"; + open(OPTR, ">$filename.update") or die "Could not open file $filename.update"; + + $i = 1; + while () + { + $line = $_; + $j = 0; + while ($j < $#messageids) + { + if ( $line =~ m($messageids[$j]) ) + { + eval "\$line =~ s/$messageids[$j]/$reps{$messageids[$j+1]}/g"; + } + $j = $j + 2; + } + print OPTR $line; + $i++; + } + close OPTR; + close FPTR; + if ( $update ) + { + print $filename,"\n"; + rename("$filename.update","$filename"); + } +} + diff --git a/Utilities/ftgl/.NoDartCoverage b/Utilities/ftgl/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/ftgl/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/ftgl/CMakeLists.txt b/Utilities/ftgl/CMakeLists.txt new file mode 100644 index 0000000..202476b --- /dev/null +++ b/Utilities/ftgl/CMakeLists.txt @@ -0,0 +1,262 @@ +PROJECT (VTKFTGL) + +# +# Dependency mask +# +INCLUDE_REGULAR_EXPRESSION(".*") + +# +# Include path +# +INCLUDE_DIRECTORIES ( + ${VTKFTGL_SOURCE_DIR}/src + ${VTKFTGL_BINARY_DIR} +) + +# +# Collect the required libs +# +SET (VTKFTGL_LIBS "") + +# +# Do not use the STL (portability issue) +# +SET (VTKFTGL_DO_NOT_USE_STL 1) + +# +# Source files +# +SET (FTGL_SRCS + src/FTBitmapGlyph.cpp + src/FTBitmapGlyphRenderOpenGL.cpp + src/FTCharmap.cpp + src/FTFace.cpp + src/FTFont.cpp + src/FTGLBitmapFont.cpp + src/FTGLBitmapFontRenderOpenGL.cpp + src/FTGLPixmapFont.cpp + src/FTGLPixmapFontRenderOpenGL.cpp + src/FTGlyph.cpp + src/FTGlyphContainer.cpp + src/FTLibrary.cpp + src/FTPixmapGlyph.cpp + src/FTPixmapGlyphRenderOpenGL.cpp + src/FTSize.cpp +) + +# +# Do not use texture fonts (crash on Type1 fonts) +# +SET (VTKFTGL_DO_NOT_USE_TEXTURE_FONT 1) +IF (NOT VTKFTGL_DO_NOT_USE_TEXTURE_FONT) + SET (FTGL_SRCS ${FTGL_SRCS} + src/FTGLTextureFont.cpp + src/FTTextureGlyph.cpp + ) +ENDIF (NOT VTKFTGL_DO_NOT_USE_TEXTURE_FONT) + +# +# Do not use vector fonts (we only need pixmap and bitmaps and vector fonts +# needs glu). Might be an option at some point, but set it to 'true' for now. +# +SET (VTKFTGL_DO_NOT_USE_VECTORISER 1) +IF (NOT VTKFTGL_DO_NOT_USE_VECTORISER) + SET (FTGL_SRCS ${FTGL_SRCS} + src/FTExtrdGlyph.cpp + src/FTGLExtrdFont.cpp + src/FTGLOutlineFont.cpp + src/FTGLPolygonFont.cpp + src/FTOutlineGlyph.cpp + src/FTPolyGlyph.cpp + ) +ENDIF (NOT VTKFTGL_DO_NOT_USE_VECTORISER) + +# +# Support Mangle Mesa +# +IF (VTK_USE_MANGLED_MESA) + SET (FTGL_SUPPORT_MANGLE_MESA 1) + IF (FTGL_SUPPORT_MANGLE_MESA) + SET (FTGL_SRCS ${FTGL_SRCS} + src/FTBitmapGlyphRenderMesa.cpp + src/FTGLBitmapFontRenderMesa.cpp + src/FTGLPixmapFontRenderMesa.cpp + src/FTPixmapGlyphRenderMesa.cpp + ) + ENDIF (FTGL_SUPPORT_MANGLE_MESA) +ENDIF (VTK_USE_MANGLED_MESA) + +# +# Shared/static lib settings) +# +IF (BUILD_SHARED_LIBS) + SET (VTKFTGL_DLL 1) +ELSE (BUILD_SHARED_LIBS) + SET (VTKFTGL_STATIC 1) +ENDIF (BUILD_SHARED_LIBS) + +# +# Win32 flags (and shared/static lib settings) +# +IF (WIN32) + # This will add -DUSE_STD_NAMESPACE and -DWIN32 + SET (VTKFTGL_WIN32_FLAGS 1) +ENDIF (WIN32) + +# +# Unix flags +# +IF (UNIX) + IF(CMAKE_SYSTEM MATCHES "HP-UX.*") + SET (VTKFTGL_HPUX_SOURCE 1) + ENDIF(CMAKE_SYSTEM MATCHES "HP-UX.*") +ENDIF (UNIX) + +# +# Apple flags +# +IF (APPLE) + IF(CMAKE_COMPILER_IS_GNUCXX) + SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -fpascal-strings") + ENDIF(CMAKE_COMPILER_IS_GNUCXX) +ENDIF (APPLE) + +# +# We need OpenGL +# +# Use GL library provided by parent VTK if possible. +# +IF(NOT OPENGL_FOUND) + FIND_PACKAGE(OpenGL) + IF (OPENGL_INCLUDE_PATH) + INCLUDE_DIRECTORIES (${OPENGL_INCLUDE_PATH}) + ENDIF (OPENGL_INCLUDE_PATH) +ENDIF(NOT OPENGL_FOUND) +SET (VTKFTGL_LIBS "${VTKFTGL_LIBS};${OPENGL_gl_LIBRARY}") + +# +# We obviously need FreeType +# +SET (VTKFTGL_LIBS "${VTKFTGL_LIBS};${VTK_FREETYPE_LIBRARIES}") + +# +# Define the library (and install it) +# +ADD_LIBRARY (vtkftgl ${FTGL_SRCS}) +TARGET_LINK_LIBRARIES(vtkftgl ${VTKFTGL_LIBS}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkftgl PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS (${VTK_INSTALL_LIB_DIR} vtkftgl) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) + +# +# Do not cover this lib +# +CONFIGURE_FILE (${VTKFTGL_SOURCE_DIR}/.NoDartCoverage + ${VTKFTGL_BINARY_DIR}/.NoDartCoverage) + +# +# Create the configuration file +# +ADD_DEFINITIONS (-DVTKFTGL) +CONFIGURE_FILE(${VTKFTGL_SOURCE_DIR}/vtkftglConfig.h.in + ${VTKFTGL_BINARY_DIR}/vtkftglConfig.h) + +# +# Build examples (testing purposes) +# (Warning, they use Glut) +# +#OPTION (FTGL_BUILD_EXAMPLES "Build FTGL examples (warning: you need Glut)" OFF) +#MARK_AS_ADVANCED (FTGL_BUILD_EXAMPLES) +SET(FTGL_BUILD_EXAMPLES 0) + +IF (FTGL_BUILD_EXAMPLES) + + # + # Need GLU and GLUT + # + FIND_PACKAGE(GLU) + FIND_PACKAGE(GLUT) + + IF (GLU_LIBRARY AND GLUT_LIBRARY) + + SET (VTKFTGL_EXAMPLES_LIBS "${VTKFTGL_LIBS}") + + IF (GLUT_INCLUDE_PATH) + INCLUDE_DIRECTORIES (${GLUT_INCLUDE_PATH}) + ENDIF (GLUT_INCLUDE_PATH) + SET (VTKFTGL_EXAMPLES_LIBS "${VTKFTGL_EXAMPLES_LIBS};${GLUT_LIBRARY}") + + IF (GLU_INCLUDE_PATH) + INCLUDE_DIRECTORIES (${GLU_INCLUDE_PATH}) + ENDIF (GLU_INCLUDE_PATH) + SET (VTKFTGL_EXAMPLES_LIBS "${VTKFTGL_EXAMPLES_LIBS};${GLU_LIBRARY}") + + # + # Do we need X ? + # + IF (VTK_USE_X) + SET (VTKFTGL_EXAMPLES_LIBS "${VTKFTGL_EXAMPLES_LIBS};-lXt") + FIND_LIBRARY (XMU_LIBRARY Xmu + /usr/lib + /usr/local/lib + /opt/graphics/OpenGL/lib + /usr/openwin/lib + /usr/X11R6/lib + /usr/contrib/X11R6/lib + ) + MARK_AS_ADVANCED (XMU_LIBRARY) + IF (XMU_LIBRARY) + SET (VTKFTGL_EXAMPLES_LIBS "${VTKFTGL_EXAMPLES_LIBS};${XMU_LIBRARY}") + ENDIF (XMU_LIBRARY) + SET (VTKFTGL_EXAMPLES_LIBS "${VTKFTGL_EXAMPLES_LIBS};${CMAKE_X_LIBS}") + ENDIF (VTK_USE_X) + + # + # Win32 flags + # + IF (WIN32) + # - Avoid the glutCreateMenu_ATEXIT_HACK pb. + # - Sort-of a hack to avoid the bug in glut.h to avoid + # ambiguity between 'std::exit(int)' and 'std::exit(int)' in function + ADD_DEFINITIONS (-DGLUT_DISABLE_ATEXIT_HACK) + ADD_DEFINITIONS (-DGLUT_BUILDING_LIB) + ENDIF (WIN32) + + # + # Apple libraries. + # + IF (APPLE) + SET (VTKFTGL_EXAMPLES_LIBS "-framework Cocoa" ${VTKFTGL_EXAMPLES_LIBS}) + ENDIF (APPLE) + + # + # Link examples to FTGL and Freetype + # + SET (VTKFTGL_EXAMPLES_LIBS "${VTKFTGL_EXAMPLES_LIBS};vtkftgl;${VTK_FREETYPE_LIBRARIES}") + + # + # Example 1 + # + SET(FTGL_DEMO_SRCS + demo/tb.c + demo/trackball.c + demo/FTGLDemo.cpp + ) + ADD_EXECUTABLE (ftgl_demo ${FTGL_DEMO_SRCS}) + TARGET_LINK_LIBRARIES(ftgl_demo ${VTKFTGL_EXAMPLES_LIBS}) + + # + # Example 2 + # + ADD_EXECUTABLE (ftgl_demo2 demo/demo.cpp) + TARGET_LINK_LIBRARIES(ftgl_demo2 ${VTKFTGL_EXAMPLES_LIBS}) + + ENDIF (GLU_LIBRARY AND GLUT_LIBRARY) + +ENDIF (FTGL_BUILD_EXAMPLES) diff --git a/Utilities/ftgl/README.VTK.txt b/Utilities/ftgl/README.VTK.txt new file mode 100644 index 0000000..865e4bc --- /dev/null +++ b/Utilities/ftgl/README.VTK.txt @@ -0,0 +1,10 @@ +This directory contains a subset of the FTGL library (1.32). +We only include enough of distribution to build it. + +We'd like to thank Henry Maddocks for distributing this library. +henryj@paradise.net.nz +http://homepages.paradise.net.nz/henryj/code/index.html#FTGL + +Modifications +------------- +A lot (including new code in src/NoSTL, speedups, portability issues). diff --git a/Utilities/ftgl/README.txt b/Utilities/ftgl/README.txt new file mode 100644 index 0000000..7bda6e4 --- /dev/null +++ b/Utilities/ftgl/README.txt @@ -0,0 +1,133 @@ +FTGL 1.32 +April 23 2002 + +DESCRIPTION: + +FTGL is a free open source library to enable developers to use arbitrary +fonts in their OpenGL (www.opengl.org) applications. +Unlike other OpenGL font libraries FTGL uses standard font file formats +so doesn't need a preprocessing step to convert the high quality font data +into a lesser quality, proprietary format. +FTGL uses the Freetype (www.freetype.org) font library to open and 'decode' +the fonts. It then takes that output and stores it in a format most efficient +for OpenGL rendering. + +Rendering modes supported are +- Bit maps +- Antialiased Pix maps +- Texture maps +- Outlines +- Polygon meshes +- Extruded polygon meshes + +FTGL is designed to be used in commercial quality software. It has been +written with performance, robustness and simplicity in mind. + +USAGE: + + FTGLPixmapFont font; + + font.Open( "Fonts:Arial"); + font.FaceSize( 72); + + font.render( "Hello World!"); + +This library was inspired by gltt, Copyright (C) 1998-1999 Stephane Rehel +(http://gltt.sourceforge.net) +Bezier curve code contributed by Jed Soane. +Demo, Linux port, extrusion code and gltt maintainance by Gerard Lanois +Linux port by Matthias Kretz +Windows port by Max Rheiner & Ellers +Bug fixes by Robert Osfield, Marcelo E. Magallon, Markku Rontu + +Please contact me if you have any suggestions, feature requests, or problems. + +Henry Maddocks +henryj@paradise.net.nz +http://homepages.paradise.net.nz/henryj/ + + + +//============================================================================== + +Version 2?????? +My initial design of FTGL was in 2 distinct parts...the freetype stuff and +the FTGL stuff. The freetype side contained wrappers for the freetype stuff +(surprise) and the ftgl side handled all the opengl stuff. All communication +was done via FTFace <-> FTFont. This felt right from a design point of view +because conceptually it made sense, it was clean, simple and it insulated +FTGL from changes in freetype. Up to version 1.3 I have rigidly stuck to +this 'rule'. Unfortunately this has been at the expense of the code. This +became most evident when dealing with char maps. Common sense would argue +that charmaps and the glyph container are intimately related, but because +of the 'rule' the communication path between them is... +FTGlyphContainer <-> FTFont <-> FTFace <-> FTCharMap +This is bollocks and has lead to some ugly code. +I am not about abandon the design completely, just the rule that says all +communication should be via FTFace <-> FTFont. I will still maintain +wrappers for freetype objects, but they will interface with ftgl in places +that make the most sense from a code efficiency point of view. + +move glyph creation out of constructor, but load the freetype glyph and get +the metrics. +Change all dim stuff to float. Make my own floating point version of +FT_Vector. +Move Charmap to be owned by glyph container. See above +Try out cbloom sorted vector in charmap. faster than std::map? +Enable access to raw glyph data +State handling... +inline base class methods + +Extreme Programming... + + +Things to think about... + +The whole char size thing is major headache. +At the moment if you call font.CharSize( x) the glyph list is destroyed and +rebuilt, which will be really, really, really inefficient if you change sizes +often. Will the freetype cache stuff help? What about the new (FT 2.0.5) +FTSize public api. + +When is the best time to construct the glyphList? After the call to Size(x) +is the earliest but what happens if the client doesn't set the char size? +Define a default size, check if glyphlist is valid in render function, if +not call size with default size. + +good sites... +http://cgm.cs.mcgill.ca/~luc/ +http://www.blackpawn.com/texts/lightmaps/default.html + +glGetIntegerv( GL_TEXTURE_2D_BINDING_EXT, &activeTextureID); +should really check at run time. + + + +Check that I do this properly.. +============================ + +Dave Williss a ecrit : + +Question: + +If I do this... + + TT_New_Glyph(face, &glyph); + for (i = 0 ; i < n ; ++i) { + TT_Load_Glyph(instance, glyph, index[i], flags); + ... use glyph... + } + + TT_Done_Glyph(glyph) + +Will I be leaking memory on each call to Load Glyph or +should I create and destroy the glyph handle for each call? +Seems terribily inefficient but to do that, but doing it as +above I seem to be leaking memory. + + +No, this is the correct behavior. Each call to TT_Load_Glyph +overwrites the previous content.. and this was designed on +purpose because the real content of a TT_Glyph object is +_really_ complex with TrueType, and you don't want to create +them on each glyph load.. diff --git a/Utilities/ftgl/demo/FTGLDemo.cpp b/Utilities/ftgl/demo/FTGLDemo.cpp new file mode 100644 index 0000000..e74e5a1 --- /dev/null +++ b/Utilities/ftgl/demo/FTGLDemo.cpp @@ -0,0 +1,557 @@ +#include +#include + +#include "FTGL.h" + +#ifdef __APPLE_CC__ + #include +#else + #include +#endif + +#include "tb.h" + +#ifndef FTGL_DO_NOT_USE_VECTORISER +#include "FTGLExtrdFont.h" +#include "FTGLOutlineFont.h" +#include "FTGLPolygonFont.h" +#endif + +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT +#include "FTGLTextureFont.h" +#endif + +#include "FTGLPixmapFont.h" +#include "FTGLBitmapFont.h" + +// YOU'LL PROBABLY WANT TO CHANGE THESE + +#ifdef __linux__ +const char* FONT_FILE = "/usr/share/fonts/truetype/arial.ttf"; +const char* FONT_INFO = "/usr/share/fonts/truetype/arial.ttf"; +#else +#ifdef __APPLE_CC__ +const char* FONT_FILE = "/Users/henry/Development/PROJECTS/FTGL/ftglcvs/FTGL/demo/arial.ttf"; +const char* FONT_INFO = "/Users/henry/Development/PROJECTS/FTGL/ftglcvs/FTGL/demo/arial.ttf"; +#else +#ifdef WIN32 +const char* FONT_FILE = "C:\\WINNT\\Fonts\\arial.ttf"; +const char* FONT_INFO = "C:\\WINNT\\Fonts\\arial.ttf"; +#else +const char* FONT_FILE = "arial.ttf"; +const char* FONT_INFO = "arial.ttf"; +#endif +#endif +#endif + +#define EDITING 1 +#define INTERACTIVE 2 + +#define FTGL_BITMAP 0 +#define FTGL_PIXMAP 1 +#define FTGL_OUTLINE 2 +#define FTGL_POLYGON 3 +#define FTGL_EXTRUDE 4 +#define FTGL_TEXTURE 5 + +#ifndef FTGL_DO_NOT_USE_VECTORISER +int current_font = FTGL_EXTRUDE; +#else +int current_font = FTGL_PIXMAP; +#endif + +GLint w_win = 640, h_win = 480; +float posX, posY, posZ; +int mode = INTERACTIVE; +int carat = 0; + +const char* fontfile; +const char* fontinfo; + +//wchar_t myString[16] = { 0x6FB3, 0x9580}; +wchar_t myString[16]; + +static FTFont* fonts[6]; +static FTGLPixmapFont* infoFont; + +void SetCamera(void); + +void my_lighting() +{ + // Set up lighting. + float light1_ambient[4] = { 1.0, 1.0, 1.0, 1.0 }; + float light1_diffuse[4] = { 1.0, 0.9, 0.9, 1.0 }; + float light1_specular[4] = { 1.0, 0.7, 0.7, 1.0 }; + float light1_position[4] = { -1.0, 1.0, 1.0, 0.0 }; + glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular); + glLightfv(GL_LIGHT1, GL_POSITION, light1_position); + glEnable(GL_LIGHT1); + + float light2_ambient[4] = { 0.2, 0.2, 0.2, 1.0 }; + float light2_diffuse[4] = { 0.9, 0.9, 0.9, 1.0 }; + float light2_specular[4] = { 0.7, 0.7, 0.7, 1.0 }; + float light2_position[4] = { 1.0, -1.0, -1.0, 0.0 }; + glLightfv(GL_LIGHT2, GL_AMBIENT, light2_ambient); + glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse); + glLightfv(GL_LIGHT2, GL_SPECULAR, light2_specular); + glLightfv(GL_LIGHT2, GL_POSITION, light2_position); +// glEnable(GL_LIGHT2); + + float front_emission[4] = { 0.3, 0.2, 0.1, 0.0 }; + float front_ambient[4] = { 0.2, 0.2, 0.2, 0.0 }; + float front_diffuse[4] = { 0.95, 0.95, 0.8, 0.0 }; + float front_specular[4] = { 0.6, 0.6, 0.6, 0.0 }; + glMaterialfv(GL_FRONT, GL_EMISSION, front_emission); + glMaterialfv(GL_FRONT, GL_AMBIENT, front_ambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, front_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, front_specular); + glMaterialf(GL_FRONT, GL_SHININESS, 16.0); + glColor4fv(front_diffuse); + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + glEnable(GL_CULL_FACE); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); +} + + +void do_display () +{ + switch( current_font) + { + case FTGL_BITMAP: +// glDisable( GL_BLEND); + break; + case FTGL_PIXMAP: +// glDisable( GL_TEXTURE_2D); +// glEnable(GL_BLEND); +// glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE + break; +#ifndef FTGL_DO_NOT_USE_VECTORISER + case FTGL_OUTLINE: +// glDisable( GL_TEXTURE_2D); +// glEnable( GL_LINE_SMOOTH); +// glEnable(GL_BLEND); +// glBlendFunc( GL_SRC_ALPHA, GL_ONE); // GL_ONE_MINUS_SRC_ALPHA + break; + case FTGL_POLYGON: + glDisable( GL_BLEND); + my_lighting(); + break; + case FTGL_EXTRUDE: + glEnable( GL_DEPTH_TEST); + glDisable( GL_BLEND); + my_lighting(); + break; +#endif +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT + case FTGL_TEXTURE: + glEnable( GL_TEXTURE_2D); + glDisable( GL_DEPTH_TEST); + my_lighting(); + glNormal3f( 0.0, 0.0, 1.0); +// glDisable( GL_BLEND); + break; +#endif + } + + glColor3f( 1.0, 1.0, 1.0); +// If you do want to switch the color of bitmaps rendered with glBitmap, +// you will need to explicitly call glRasterPos3f (or its ilk) to lock +// in a changed current color. + + fonts[current_font]->render( myString); + + float x1, y1, z1, x2, y2, z2; + fonts[current_font]->BBox( myString, x1, y1, z1, x2, y2, z2); + + // Draw the bounding box + glDisable( GL_LIGHTING); + glDisable( GL_TEXTURE_2D); + glEnable( GL_LINE_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc( GL_SRC_ALPHA, GL_ONE); // GL_ONE_MINUS_SRC_ALPHA + + glColor3f( 0.0, 1.0, 0.0); + // Draw the front face + glBegin( GL_LINE_LOOP); + glVertex3f( x1, y1, z1); + glVertex3f( x1, y2, z1); + glVertex3f( x2, y2, z1); + glVertex3f( x2, y1, z1); + glEnd(); +#ifndef FTGL_DO_NOT_USE_VECTORISER + // Draw the back face + if( current_font == FTGL_EXTRUDE && z1 != z2) + { + glBegin( GL_LINE_LOOP); + glVertex3f( x1, y1, z2); + glVertex3f( x1, y2, z2); + glVertex3f( x2, y2, z2); + glVertex3f( x2, y1, z2); + glEnd(); + // Join the faces + glBegin( GL_LINES); + glVertex3f( x1, y1, z1); + glVertex3f( x1, y1, z2); + + glVertex3f( x1, y2, z1); + glVertex3f( x1, y2, z2); + + glVertex3f( x2, y2, z1); + glVertex3f( x2, y2, z2); + + glVertex3f( x2, y1, z1); + glVertex3f( x2, y1, z2); + glEnd(); + } +#endif + + // Draw the baseline, Ascender and Descender + glBegin( GL_LINES); + glColor3f( 0.0, 0.0, 1.0); + glVertex3f( 0.0, 0.0, 0.0); + glVertex3f( fonts[current_font]->Advance( myString), 0.0, 0.0); + + glVertex3f( 0.0, fonts[current_font]->Ascender(), 0.0); + glVertex3f( 0.0, fonts[current_font]->Descender(), 0.0); + + glEnd(); + + // Draw the origin + glColor3f( 1.0, 0.0, 0.0); + glPointSize( 5.0); + glBegin( GL_POINTS); + glVertex3f( 0.0, 0.0, 0.0); + glEnd(); + + // draw the info + int save_font = current_font; + current_font = FTGL_PIXMAP; + SetCamera(); + + // draw mode + glColor3f( 1.0, 1.0, 1.0); + glRasterPos2i( 20 , h_win - ( 20 + infoFont->Ascender())); + + switch( mode) + { + case EDITING: + infoFont->render("Edit Mode"); + break; + case INTERACTIVE: + break; + } + + // draw font type + glRasterPos2i( 20 , 20); + switch( save_font) + { + case FTGL_BITMAP: + infoFont->render("Bitmap Font"); + break; + case FTGL_PIXMAP: + infoFont->render("Pixmap Font"); + break; +#ifndef FTGL_DO_NOT_USE_VECTORISER + case FTGL_OUTLINE: + infoFont->render("Outline Font"); + break; + case FTGL_POLYGON: + infoFont->render("Polygon Font"); + break; + case FTGL_EXTRUDE: + infoFont->render("Extruded Font"); + break; +#endif +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT + case FTGL_TEXTURE: + infoFont->render("Texture Font"); + break; +#endif + } + + glRasterPos2i( 20 , 20 + infoFont->Ascender() - infoFont->Descender()); + infoFont->render(fontfile); + + current_font = save_font; + + glutSwapBuffers(); +} + +void myinit () +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearColor( 0.13, 0.17, 0.32, 0.0); + glColor3f( 1.0, 1.0, 1.0); + + glEnable( GL_CULL_FACE); + glFrontFace( GL_CCW); + + glEnable( GL_DEPTH_TEST); + + glEnable( GL_POLYGON_OFFSET_LINE); + glPolygonOffset( 1.0, 1.0); // ???? + + SetCamera(); + + fonts[FTGL_BITMAP] = new FTGLBitmapFont; + fonts[FTGL_PIXMAP] = new FTGLPixmapFont; + +#ifndef FTGL_DO_NOT_USE_VECTORISER + fonts[FTGL_OUTLINE] = new FTGLOutlineFont; + fonts[FTGL_POLYGON] = new FTGLPolygonFont; + fonts[FTGL_EXTRUDE] = new FTGLExtrdFont; +#else + fonts[FTGL_OUTLINE] = + fonts[FTGL_POLYGON] = + fonts[FTGL_EXTRUDE] = 0; +#endif + +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT + fonts[FTGL_TEXTURE] = new FTGLTextureFont; +#else + fonts[FTGL_TEXTURE] = 0; +#endif + + for( int x = 0; x < 6; ++x) + { + if(!fonts[x]) + { + continue; + } + + if( !fonts[x]->Open( fontfile, false)) + { + fprintf( stderr, "Failed to open font %s", fontfile); + exit(1); + } + + if( !fonts[x]->FaceSize( 144)) + { + fprintf( stderr, "Failed to set size"); + exit(1); + } + + fonts[x]->Depth(20); + + fonts[x]->CharMap(ft_encoding_unicode); + } + + infoFont = new FTGLPixmapFont; + + if( !infoFont->Open( fontinfo, false)) + { + fprintf( stderr, "Failed to open font %s", fontinfo); + exit(1); + } + + infoFont->FaceSize( 18); + + myString[0] = 65; + myString[1] = 0; + + + tbInit(GLUT_LEFT_BUTTON); + tbAnimate( GL_FALSE); + +} + +#ifndef GLUTCALLBACK +#define GLUTCALLBACK +#endif + +extern "C" { + +void GLUTCALLBACK display() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SetCamera(); + + glPushMatrix(); + + switch( current_font) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + glRasterPos2i( w_win / 2, h_win / 2); + glTranslatef( w_win / 2, h_win / 2, 0.0); + break; +#ifndef FTGL_DO_NOT_USE_VECTORISER + case FTGL_OUTLINE: + case FTGL_POLYGON: + case FTGL_EXTRUDE: +#endif +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT + case FTGL_TEXTURE: +#endif +#if !defined(FTGL_DO_NOT_USE_VECTORISER) || !defined(FTGL_DO_NOT_USE_TEXTURE_FONT) + tbMatrix(); + break; +#endif + } + + do_display(); + + glPopMatrix(); + +} + +void GLUTCALLBACK parsekey(unsigned char key, int, int) +{ + switch (key) + { + case 27: exit(0); break; + case 13: + if( mode == EDITING) + { + mode = INTERACTIVE; + } + else + { + mode = EDITING; + carat = 0; + } + break; + case ' ': + do + { + current_font++; + if(current_font > 5) + current_font = 0; + } while (!fonts[current_font]); + break; + default: + if( mode == INTERACTIVE) + { + myString[0] = key; + myString[1] = 0; + break; + } + else + { + myString[carat] = key; + myString[carat + 1] = 0; + carat = carat > 14 ? 15 : ++carat; + } + } + + glutPostRedisplay(); + +} + + +void GLUTCALLBACK parsekey_special(int key, int, int) +{ + switch (key) + { + case GLUT_KEY_UP: + posY += 10; + break; + case GLUT_KEY_DOWN: + posY -= 10; + break; + case GLUT_KEY_RIGHT: + posX += 10; + break; + case GLUT_KEY_LEFT: + posX -= 10; + break; + } +} + +void GLUTCALLBACK motion(int x, int y) +{ + tbMotion( x, y); +} + +void GLUTCALLBACK mouse(int button, int state, int x, int y) +{ + tbMouse( button, state, x, y); +} + +void GLUTCALLBACK myReshape(int w, int h) +{ + glMatrixMode (GL_MODELVIEW); + glViewport (0, 0, w, h); + glLoadIdentity(); + + w_win = w; + h_win = h; + SetCamera(); + + tbReshape(w_win, h_win); +} + +} // End of extern C + +void SetCamera(void) +{ + switch( current_font) + { + case FTGL_BITMAP: + case FTGL_PIXMAP: + glMatrixMode( GL_PROJECTION); + glLoadIdentity(); +#ifndef FTGL_DO_NOT_USE_VECTORISER + gluOrtho2D(0, w_win, 0, h_win); +#else + glOrtho(0, w_win, 0, h_win, -1.0, 1.0); +#endif + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + break; +#ifndef FTGL_DO_NOT_USE_VECTORISER + case FTGL_OUTLINE: + case FTGL_POLYGON: + case FTGL_EXTRUDE: +#endif +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT + case FTGL_TEXTURE: +#endif +#if !defined(FTGL_DO_NOT_USE_VECTORISER) || !defined(FTGL_DO_NOT_USE_TEXTURE_FONT) + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective( 90, (float)w_win / (float)h_win, 1, 1000); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt( 0.0, 0.0, (float)h_win / 2.0f, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + break; +#endif + } +} + + +int main(int argc, char *argv[]) +{ + fontfile = FONT_FILE; + fontinfo = FONT_INFO; + + if (argc == 2) + fontfile = fontinfo = argv[1]; + + glutInit( &argc, argv); + glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); + glutInitWindowPosition(50, 50); + glutInitWindowSize( w_win, h_win); + glutCreateWindow("FTGL TEST"); + glutDisplayFunc(&display); + glutKeyboardFunc(parsekey); + glutMouseFunc(mouse); + glutMotionFunc(motion); + glutSpecialFunc(parsekey_special); + glutReshapeFunc(myReshape); + glutIdleFunc(display); + + myinit(); + + glutMainLoop(); + + return 0; +} diff --git a/Utilities/ftgl/demo/README.txt b/Utilities/ftgl/demo/README.txt new file mode 100644 index 0000000..306a487 --- /dev/null +++ b/Utilities/ftgl/demo/README.txt @@ -0,0 +1,15 @@ +FTGL Version 1.3 Demo + +This demo demonstrates the different rendering styles available with FTGL. +Press to change the font rendering style. +Press to enable edit mode. + +When compiling you will need to check the paths to the font files as they are +hard coded. See #define FONT_FILE and #define FONT_INFO in FTGLDemo.c + + +Please contact me if you have any suggestions, feature requests, or problems. + +Henry Maddocks +henryj@paradise.net.nz +http://homepages.paradise.net.nz/henryj/ diff --git a/Utilities/ftgl/demo/demo.cpp b/Utilities/ftgl/demo/demo.cpp new file mode 100644 index 0000000..c1efbe8 --- /dev/null +++ b/Utilities/ftgl/demo/demo.cpp @@ -0,0 +1,372 @@ +// source changed by mrn@paus.ch/ max rheiner +// original source: henryj@paradise.net.nz + +#include +#include // exit() + +#include "FTGL.h" + +#ifdef __APPLE_CC__ + #include +#else + #include +#endif + +#ifndef FTGL_DO_NOT_USE_VECTORISER +#include "FTGLOutlineFont.h" +#include "FTGLPolygonFont.h" +#endif + +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT +#include "FTGLTextureFont.h" +#endif + +#include "FTGLBitmapFont.h" +#include "FTGLPixmapFont.h" + +static FTFont* fonts[5]; +static int width; +static int height; + +static int point_size = 24; + +#ifdef __linux__ +const char* DEFAULT_FONT = "/usr/share/fonts/truetype/arial.ttf"; +#else +#ifdef __APPLE_CC__ +const char* DEFAULT_FONT = "/Users/henry/Development/PROJECTS/FTGL/ftglcvs/FTGL/demo/arial.ttf"; +#else +#ifdef WIN32 +const char* DEFAULT_FONT = "C:\\WINNT\\Fonts\\arial.ttf"; +#else +const char* DEFAULT_FONT = "arial.ttf"; +#endif +#endif +#endif + +int file_exists( const char * filename ); + +void draw_scene(); + +void +my_init( const char* font_filename ) +{ + glClearColor(0.0, 0.0, 0.0, 0.0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + +#ifndef FTGL_DO_NOT_USE_VECTORISER + fonts[0] = new FTGLOutlineFont; + fonts[1] = new FTGLPolygonFont; +#else + fonts[0] = + fonts[1] = 0; +#endif + +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT + fonts[2] = new FTGLTextureFont; +#else + fonts[2] = 0; +#endif + + fonts[3] = new FTGLBitmapFont; + fonts[4] = new FTGLPixmapFont; + + for (int i=0; i< 5; i++) { + + if(!fonts[i]) + { + continue; + } + + if (!fonts[i]->Open(font_filename)) { + printf("Reading font %d from %s\n", i, font_filename); + fprintf(stderr, "ERROR: Unable to open file %s\n", font_filename); + } + else { + printf("Reading font %d from %s\n", i, font_filename); + + if (!fonts[i]->FaceSize(point_size)) { + fprintf(stderr, "ERROR: Unable to set font face size %d\n", point_size); + } + + // Try to load AFM font metrics + const char* ext = strrchr(font_filename, '.'); + if (ext && !strcmp(ext, ".pfb")) + { + char *metrics = new char[strlen(font_filename)]; + strncpy(metrics, font_filename, ext - font_filename); + strcpy(metrics + (ext - font_filename), ".afm"); + if (file_exists(metrics)) + { + printf("Attaching font metrics from %s\n", metrics);; + fonts[i]->Attach(metrics); + } + } + } + } +} + +static void +do_ortho() +{ + int w; + int h; + GLdouble size; + GLdouble aspect; + + w = width; + h = height; + aspect = (GLdouble)w / (GLdouble)h; + + // Use the whole window. + glViewport(0, 0, w, h); + + // We are going to do some 2-D orthographic drawing. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + size = (GLdouble)((w >= h) ? w : h) / 2.0; + if (w <= h) { + aspect = (GLdouble)h/(GLdouble)w; + glOrtho(-size, size, -size*aspect, size*aspect, + -100000.0, 100000.0); + } + else { + aspect = (GLdouble)w/(GLdouble)h; + glOrtho(-size*aspect, size*aspect, -size, size, + -100000.0, 100000.0); + } + + // Make the world and window coordinates coincide so that 1.0 in + // model space equals one pixel in window space. + glScaled(aspect, aspect, 1.0); + + // Now determine where to draw things. + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + +#ifndef GLUTCALLBACK +#define GLUTCALLBACK +#endif + +extern "C" { + +void +GLUTCALLBACK my_display(void) +{ + glClear(GL_COLOR_BUFFER_BIT); + + draw_scene(); + + glutSwapBuffers(); +} + +void +GLUTCALLBACK my_reshape(int w, int h) +{ + width = w; + height = h; + + do_ortho( ); +} + +void +GLUTCALLBACK my_handle_key(unsigned char key, int, int) +{ + switch (key) { + + //!!ELLERS + case 'q': // Esc or 'q' Quits the program. + case 27: + { + for (int i=0; i<5; i++) { + if (fonts[i]) { + delete fonts[i]; + fonts[i] = 0; + } + } + exit(1); + } + break; + + default: + break; + } +} + +} // End of extern C + +void +draw_scene() +{ + /* Set up some strings with the characters to draw. */ + unsigned int count = 0; + char string[8][256]; + int i; + for (i=1; i < 32; i++) { /* Skip zero - it's the null terminator! */ + string[0][count] = i; + count++; + } + string[0][count] = '\0'; + + count = 0; + for (i=32; i < 64; i++) { + string[1][count] = i; + count++; + } + string[1][count] = '\0'; + + count = 0; + for (i=64; i < 96; i++) { + string[2][count] = i; + count++; + } + string[2][count] = '\0'; + + count = 0; + for (i=96; i < 128; i++) { + string[3][count] = i; + count++; + } + string[3][count] = '\0'; + + count = 0; + for (i=128; i < 160; i++) { + string[4][count] = i; + count++; + } + string[4][count] = '\0'; + + count = 0; + for (i=160; i < 192; i++) { + string[5][count] = i; + count++; + } + string[5][count] = '\0'; + + count = 0; + for (i=192; i < 224; i++) { + string[6][count] = i; + count++; + } + string[6][count] = '\0'; + + count = 0; + for (i=224; i < 256; i++) { + string[7][count] = i; + count++; + } + string[7][count] = '\0'; + + + glColor3f(1.0, 1.0, 1.0); + + for (int font = 0; font < 5; font++) { + + if(!fonts[font]) + { + continue; + } + + GLfloat x = -250.0; + GLfloat y; + GLfloat yild = 20.0; + for (int j=0; j<4; j++) { + y = 275.0-font*120.0-j*yild; + if (font >= 3) { + glRasterPos2f(x, y); + fonts[font]->render(string[j]); + } + else { +#ifndef FTGL_DO_NOT_USE_TEXTURE_FONT + if (font == 2) { + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +#endif + glPushMatrix(); { + glTranslatef(x, y, 0.0); + fonts[font]->render(string[j]); + } glPopMatrix(); + if (font == 2) { + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + } + } + } + } +} + + +int +file_exists( const char * filename ) +{ + FILE * fp = fopen( filename, "r" ); + + if ( fp == NULL ) + { + // That fopen failed does _not_ definitely mean the file isn't there + // but for now this is ok + return 0; + } + fclose( fp ); + return 1; +} + +void +usage( const char * program ) +{ + fprintf(stderr, "Usage %s \n", program); +} + +int +main(int argc, char **argv) +{ + //!!ELLERS -- cleaned up + const char * filename; + + glutInitWindowSize(600, 600); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE); + + glutCreateWindow("FTGL demo"); + + if ( argc >= 2 ) + { + if ( !file_exists( argv[ 1 ] )) + { + usage( argv[ 0 ]); + fprintf(stderr, "Couldn't open file '%s'\n", argv[1]); + exit( -1 ); + } + filename = argv[ 1 ]; + + if ( argc >= 3 ) + { + point_size = atoi(argv[2]); + } + } + else + { + // try a default font + filename = DEFAULT_FONT; + + if ( !file_exists( filename )) + { + usage( argv[ 0 ]); + fprintf(stderr, "Couldn't open default file '%s'\n", filename); + exit( -1 ); + } + } + + my_init( filename ); + + glutDisplayFunc(my_display); + glutReshapeFunc(my_reshape); + glutKeyboardFunc(my_handle_key); + + glutMainLoop(); + return 0; +} + diff --git a/Utilities/ftgl/demo/tb.c b/Utilities/ftgl/demo/tb.c new file mode 100644 index 0000000..ef2b1f3 --- /dev/null +++ b/Utilities/ftgl/demo/tb.c @@ -0,0 +1,127 @@ +/* + * Simple trackball-like motion adapted (ripped off) from projtex.c + * (written by David Yu and David Blythe). See the SIGGRAPH '96 + * Advanced OpenGL course notes. + */ + + +/* includes */ +#include +#include +#ifdef __APPLE_CC__ + #include +#else + #include +#endif +#include "tb.h" +#include "trackball.h" + +/* globals */ +static GLuint tb_lasttime; + +float curquat[4]; +float lastquat[4]; +int beginx, beginy; + +static GLuint tb_width; +static GLuint tb_height; + +static GLint tb_button = -1; +static GLboolean tb_tracking = GL_FALSE; +static GLboolean tb_animate = GL_TRUE; + +static void +_tbAnimate(void) +{ + add_quats(lastquat, curquat, curquat); + glutPostRedisplay(); +} + +void +_tbStartMotion(int x, int y, int time) +{ + assert(tb_button != -1); + + glutIdleFunc(0); + tb_tracking = GL_TRUE; + tb_lasttime = time; + beginx = x; + beginy = y; +} + +void +_tbStopMotion(unsigned time) +{ + assert(tb_button != -1); + + tb_tracking = GL_FALSE; + + if (time == tb_lasttime && tb_animate) { + glutIdleFunc(_tbAnimate); + } else { + if (tb_animate) { + glutIdleFunc(0); + } + } +} + +void +tbAnimate(GLboolean animate) +{ + tb_animate = animate; +} + +void +tbInit(GLuint button) +{ + tb_button = button; + trackball(curquat, 0.0, 0.0, 0.0, 0.0); +} + +void +tbMatrix(void) +{ + GLfloat m[4][4]; + + assert(tb_button != -1); + build_rotmatrix(m, curquat); + glMultMatrixf(&m[0][0]); +} + +void +tbReshape(int width, int height) +{ + assert(tb_button != -1); + + tb_width = width; + tb_height = height; +} + +void +tbMouse(int button, int state, int x, int y) +{ + assert(tb_button != -1); + + if (state == GLUT_DOWN && button == tb_button) + _tbStartMotion(x, y, glutGet(GLUT_ELAPSED_TIME)); + else if (state == GLUT_UP && button == tb_button) + _tbStopMotion(glutGet(GLUT_ELAPSED_TIME)); +} + +void +tbMotion(int x, int y) +{ + if (tb_tracking) { + trackball(lastquat, + (2.0 * beginx - tb_width) / tb_width, + (tb_height - 2.0 * beginy) / tb_height, + (2.0 * x - tb_width) / tb_width, + (tb_height - 2.0 * y) / tb_height + ); + beginx = x; + beginy = y; + tb_animate = 1; + tb_lasttime = glutGet(GLUT_ELAPSED_TIME); + _tbAnimate(); + } +} diff --git a/Utilities/ftgl/demo/tb.h b/Utilities/ftgl/demo/tb.h new file mode 100644 index 0000000..3ac0ea8 --- /dev/null +++ b/Utilities/ftgl/demo/tb.h @@ -0,0 +1,103 @@ +/* + * Simple trackball-like motion adapted (ripped off) from projtex.c + * (written by David Yu and David Blythe). See the SIGGRAPH '96 + * Advanced OpenGL course notes. + * + * + * Usage: + * + * o call tbInit() in before any other tb call + * o call tbReshape() from the reshape callback + * o call tbMatrix() to get the trackball matrix rotation + * o call tbStartMotion() to begin trackball movememt + * o call tbStopMotion() to stop trackball movememt + * o call tbMotion() from the motion callback + * o call tbAnimate(GL_TRUE) if you want the trackball to continue + * spinning after the mouse button has been released + * o call tbAnimate(GL_FALSE) if you want the trackball to stop + * spinning after the mouse button has been released + * + * Typical setup: + * + * + void + init(void) + { + tbInit(GLUT_MIDDLE_BUTTON); + tbAnimate(GL_TRUE); + . . . + } + + void + reshape(int width, int height) + { + tbReshape(width, height); + . . . + } + + void + display(void) + { + glPushMatrix(); + + tbMatrix(); + . . . draw the scene . . . + + glPopMatrix(); + } + + void + mouse(int button, int state, int x, int y) + { + tbMouse(button, state, x, y); + . . . + } + + void + motion(int x, int y) + { + tbMotion(x, y); + . . . + } + + int + main(int argc, char** argv) + { + . . . + init(); + glutReshapeFunc(reshape); + glutDisplayFunc(display); + glutMouseFunc(mouse); + glutMotionFunc(motion); + . . . + } + * + * */ + + +/* functions */ +#ifdef __cplusplus +extern "C" { +#endif + +void +tbInit(GLuint button); + +void +tbMatrix(void); + +void +tbReshape(int width, int height); + +void +tbMouse(int button, int state, int x, int y); + +void +tbMotion(int x, int y); + +void +tbAnimate(GLboolean animate); + +#ifdef __cplusplus +} +#endif diff --git a/Utilities/ftgl/demo/trackball.c b/Utilities/ftgl/demo/trackball.c new file mode 100644 index 0000000..cc018c8 --- /dev/null +++ b/Utilities/ftgl/demo/trackball.c @@ -0,0 +1,324 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ +#include +#include "trackball.h" + +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (0.4f) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static float tb_project_to_sphere(float, float, float); +static void normalize_quat(float [4]); + +void +vzero(float *v) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +void +vset(float *v, float x, float y, float z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +void +vsub(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +void +vcopy(const float *v1, float *v2) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +void +vcross(const float *v1, const float *v2, float *cross) +{ + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +float +vlength(const float *v) +{ + return (float)sqrt((double)v[0] * (double)v[0] + (double)v[1] * (double)v[1] + (double)v[2] * (double)v[2]); +} + +void +vscale(float *v, float div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +void +vnormal(float *v) +{ + vscale(v, 1.0f/vlength(v)); +} + +float +vdot(const float *v1, const float *v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void +vadd(const float *src1, const float *src2, float *dst) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y) +{ + float a[3]; /* Axis of rotation */ + float phi; /* how much to rotate about axis */ + float p1[3], p2[3], d[3]; + float t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + t = vlength(d) / (2.0f*TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = (float)(2.0 * asin(t)); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void +axis_to_quat(float a[3], float phi, float q[4]) +{ + vnormal(a); + vcopy(a,q); + vscale(q, (float)sin(phi/2.0)); + q[3] = (float)cos(phi/2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static float +tb_project_to_sphere(float r, float x, float y) +{ + float d, t, z; + + d = (float)sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440) { /* Inside sphere */ + z = (float)sqrt(r*r - d*d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880f; + z = t*t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(float q1[4], float q2[4], float dest[4]) +{ + static int count=0; + float t1[4], t2[4], t3[4]; + float tf[4]; + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void +normalize_quat(float q[4]) +{ + int i; + float mag; + + mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void +build_rotmatrix(float m[4][4], float q[4]) +{ + m[0][0] = 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0f * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0f * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0f; + + m[1][0] = 2.0f * (q[0] * q[1] + q[2] * q[3]); + m[1][1]= 1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0f * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0f; + + m[2][0] = 2.0f * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0f * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0f; + + m[3][0] = 0.0f; + m[3][1] = 0.0f; + m[3][2] = 0.0f; + m[3][3] = 1.0f; +} + diff --git a/Utilities/ftgl/demo/trackball.h b/Utilities/ftgl/demo/trackball.h new file mode 100644 index 0000000..3aea4ee --- /dev/null +++ b/Utilities/ftgl/demo/trackball.h @@ -0,0 +1,85 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +#ifdef __cpluscplus +extern "C" { +#endif + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void +trackball(float q[4], float p1x, float p1y, float p2x, float p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void +add_quats(float *q1, float *q2, float *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void +build_rotmatrix(float m[4][4], float q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void +axis_to_quat(float a[3], float phi, float q[4]); + +#ifdef __cpluscplus +} +#endif diff --git a/Utilities/ftgl/license.txt b/Utilities/ftgl/license.txt new file mode 100644 index 0000000..fbb6e65 --- /dev/null +++ b/Utilities/ftgl/license.txt @@ -0,0 +1,27 @@ +FTGL + +Herewith is a license. I've also chucked in a gnu (see COPYING.txt) license +for those that are that way inclined. Basically I want you to use this +software and if you think this license is preventing you from doing so +let me know. + +Copyright (C) 2001-2 Henry Maddocks + +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. diff --git a/Utilities/ftgl/src/FTBitmapGlyph.cpp b/Utilities/ftgl/src/FTBitmapGlyph.cpp new file mode 100644 index 0000000..1c1ef84 --- /dev/null +++ b/Utilities/ftgl/src/FTBitmapGlyph.cpp @@ -0,0 +1,112 @@ +#include "FTBitmapGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTBitmapGlyph::FTBitmapGlyph( FT_Glyph _glyph) +: FTGlyph(), + destWidth(0), + destHeight(0), + data(0) +{ + this->glyph = _glyph; + bBox = FTBBox(this->glyph); + advance = (float)(this->glyph->advance.x >> 16); +} + +void FTBitmapGlyph::ConvertGlyph() +{ + // This function will always fail if the glyph's format isn't scalable???? + err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_mono, 0, 1); + if( err || ft_glyph_format_bitmap != this->glyph->format) + {return;} + + FT_BitmapGlyph bitmap = reinterpret_cast(this->glyph); + FT_Bitmap* source = &bitmap->bitmap; + + //check the pixel mode + //ft_pixel_mode_grays + + int srcWidth = source->width; + int srcHeight = source->rows; + int srcPitch = source->pitch; + + // FIXME What about dest alignment? + destWidth = srcWidth; + destHeight = srcHeight; + + if( destWidth && destHeight) + { + data = new unsigned char[srcPitch * destHeight]; + +#if 1 + unsigned char *src = source->buffer; + unsigned char *src_row; + + unsigned char *dest = data + ((destHeight - 1) * srcPitch); + size_t dest_step = srcPitch * 2; + + for(int y = 0; y < srcHeight; ++y) + { + src_row = src; + for(int x = 0; x < srcPitch; ++x) + { + *dest++ = *src_row++; + } + src += srcPitch; + dest -= dest_step; + } + +#else + + for(int y = 0; y < srcHeight; ++y) + { + --destHeight; + for(int x = 0; x < srcPitch; ++x) + { + *( data + ( destHeight * srcPitch + x)) = *( source->buffer + ( y * srcPitch) + x); + } + } + +#endif + destHeight = srcHeight; + } + + pos.x = bitmap->left; + pos.y = srcHeight - bitmap->top; + this->glyphHasBeenConverted = 1; +} + + +FTBitmapGlyph::~FTBitmapGlyph() +{ + if( data) + delete [] data; +} + + +float FTBitmapGlyph::Render( const FT_Vector& pen, + const FTGLRenderContext *context) +{ + if (!this->glyphHasBeenConverted) + { + this->ConvertGlyph(); + } + + if( data) + { +#ifdef FTGL_SUPPORT_MANGLE_MESA + if (context && context->UseMangleMesa) + { + this->RenderMesa(pen, context); + } + else +#endif + { + this->RenderOpenGL(pen, context); + } + } + + return advance; +} diff --git a/Utilities/ftgl/src/FTBitmapGlyph.h b/Utilities/ftgl/src/FTBitmapGlyph.h new file mode 100644 index 0000000..6a9687a --- /dev/null +++ b/Utilities/ftgl/src/FTBitmapGlyph.h @@ -0,0 +1,77 @@ +#ifndef __FTBitmapGlyph__ +#define __FTBitmapGlyph__ + + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGlyph.h" + + +/** + * FTBitmapGlyph is a specialisation of FTGlyph for creating bitmaps. + * + * It provides the interface between Freetype glyphs and their openGL + * renderable counterparts. This is an abstract class and derived classes + * must implement the render function. + * + * @see FTGlyphContainer + * + */ +class FTGL_EXPORT FTBitmapGlyph : public FTGlyph +{ + public: + /** + * Constructor + * + * @param glyph The Freetype glyph to be processed + */ + FTBitmapGlyph( FT_Glyph glyph); + + /** + * Destructor + */ + virtual ~FTBitmapGlyph(); + + /** + * Renders this glyph at the current pen position. + * + * @param pen The current pen position. + * @return The advance distance for this glyph. + */ + virtual float Render( const FT_Vector& pen, + const FTGLRenderContext *context = 0); + + virtual void ConvertGlyph(); + + private: + /** + * The width of the glyph 'image' + */ + int destWidth; + + /** + * The height of the glyph 'image' + */ + int destHeight; + + /** + * Pointer to the 'image' data + */ + unsigned char* data; + + void RenderOpenGL(const FT_Vector& pen, + const FTGLRenderContext *context = 0); + +#ifdef FTGL_SUPPORT_MANGLE_MESA + void RenderMesa(const FT_Vector& pen, + const FTGLRenderContext *context = 0); +#endif + +}; + + +#endif // __FTBitmapGlyph__ + diff --git a/Utilities/ftgl/src/FTBitmapGlyphRenderMesa.cpp b/Utilities/ftgl/src/FTBitmapGlyphRenderMesa.cpp new file mode 100644 index 0000000..455d6f3 --- /dev/null +++ b/Utilities/ftgl/src/FTBitmapGlyphRenderMesa.cpp @@ -0,0 +1,6 @@ +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#define RenderFunctionName RenderMesa + +#include "FTBitmapGlyphRenderOpenGL.cpp" diff --git a/Utilities/ftgl/src/FTBitmapGlyphRenderOpenGL.cpp b/Utilities/ftgl/src/FTBitmapGlyphRenderOpenGL.cpp new file mode 100644 index 0000000..185fc94 --- /dev/null +++ b/Utilities/ftgl/src/FTBitmapGlyphRenderOpenGL.cpp @@ -0,0 +1,21 @@ +#include "FTBitmapGlyph.h" +#include "FTGLgl.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + +#ifndef RenderFunctionName +#define RenderFunctionName RenderOpenGL +#endif + +void FTBitmapGlyph::RenderFunctionName(const FT_Vector& pen, + const FTGLRenderContext *) +{ + // Move the glyph origin + glBitmap( 0, 0, 0.0, 0.0, (float)(pen.x + pos.x), (float)(pen.y - pos.y), (const GLubyte *)0 ); + + glBitmap( destWidth, destHeight, 0.0f, 0.0, 0.0, 0.0, (const GLubyte *)data); + + // Restore the glyph origin + glBitmap( 0, 0, 0.0, 0.0, (float)(-pen.x - pos.x), (float)(-pen.y + pos.y), (const GLubyte *)0 ); +} diff --git a/Utilities/ftgl/src/FTCharmap.cpp b/Utilities/ftgl/src/FTCharmap.cpp new file mode 100644 index 0000000..92f0bec --- /dev/null +++ b/Utilities/ftgl/src/FTCharmap.cpp @@ -0,0 +1,114 @@ +#include "FTCharmap.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTCharmap::FTCharmap( FT_Face face) +: ftFace( face), + err(0) +{ + // Check that the default is valid + if( !face->charmap) + { + FT_Set_Charmap( ftFace, ftFace->charmaps[0]); + } + + ftEncoding = face->charmap->encoding; +} + + +FTCharmap::~FTCharmap() +{ + charMap.clear(); +} + + +bool FTCharmap::CharMap( FT_Encoding encoding) +{ + if( ftEncoding == encoding) + { + return true; + } + + err = FT_Select_Charmap( ftFace, encoding ); + + if( !err) + { + ftEncoding = encoding; + charMap.clear(); + } + + return !err; +} + + +bool FTCharmap::CharMap( FT_UShort platform, FT_UShort encoding) +{ + FT_CharMap found = 0; + FT_CharMap charmap; + + for( int n = 0; n < ftFace->num_charmaps; n++ ) + { + charmap = ftFace->charmaps[n]; + + if( charmap->platform_id == platform && charmap->encoding_id == encoding) + { + found = charmap; + break; + } + } + + if( !found ) + { + return false; + } + + if( ftEncoding == found->encoding) + { + return true; + } + + /* now, select the charmap for the face object */ + err = FT_Set_Charmap( ftFace, found ); + + if( !err) + { + ftEncoding = found->encoding; + charMap.clear(); + } + + return !err; +} + + +unsigned int FTCharmap::CharIndex( unsigned int index ) +{ +#ifdef FTGL_DO_NOT_USE_STL + const CharacterMap::GlyphIndex *result = charMap.find(index); + + if (!result) + { + unsigned int glyph = FT_Get_Char_Index(ftFace, index); + charMap.insert(index, glyph); + return glyph; + } + else + { + return *result; + } +#else + CharacterMap::const_iterator result = charMap.find( index); + + if( result == charMap.end()) + { + unsigned int glyph = FT_Get_Char_Index( ftFace, index); + charMap.insert( CharacterMap::value_type( index, glyph)); + return glyph; + } + else + { + return result->second; + } +#endif +} diff --git a/Utilities/ftgl/src/FTCharmap.h b/Utilities/ftgl/src/FTCharmap.h new file mode 100644 index 0000000..42ac4a0 --- /dev/null +++ b/Utilities/ftgl/src/FTCharmap.h @@ -0,0 +1,138 @@ +#ifndef __FTCharmap__ +#define __FTCharmap__ + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" + +#ifdef FTGL_DO_NOT_USE_STL +#include +#else +#ifdef _MSC_VER +#pragma warning (push, 2) +#endif + +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#ifdef USE_STD_NAMESPACE +using namespace std; +#endif +#endif + +/** + * FTCharmap takes care of specifying the encoding for a font and mapping + * character codes to glyph indices. + * + * It doesn't preprocess all indices, only on an as needed basis. This may + * seem like a performance penalty but it is quicker than using the 'raw' + * freetype calls and will save significant amounts of memory when dealing + * with uncode encoding + * + */ +class FTGL_EXPORT FTCharmap +{ + public: + /** + * Constructor + */ + FTCharmap( FT_Face ftFace); + + /** + * Destructor + */ + virtual ~FTCharmap(); + + /** + * Queries for the current character map code. + * + * @return The current character map code. + */ + FT_Encoding Encoding() const { return ftEncoding;} + + /** + * Sets the character map for the face. + * Valid encodings as at Freetype 2.0.4 + * ft_encoding_none + * ft_encoding_symbol + * ft_encoding_unicode + * ft_encoding_latin_2 + * ft_encoding_sjis + * ft_encoding_gb2312 + * ft_encoding_big5 + * ft_encoding_wansung + * ft_encoding_johab + * ft_encoding_adobe_standard + * ft_encoding_adobe_expert + * ft_encoding_adobe_custom + * ft_encoding_apple_roman + * + * @param encoding the Freetype encoding symbol. See above. + * @return true if charmap was valid + * and set correctly + */ + bool CharMap( FT_Encoding encoding); + + /** + * Sets the character map for the face. + * + * @param encoding the Freetype encoding symbol. See above. + * @return true if charmap was valid + * and set correctly + */ + bool CharMap( FT_UShort platform, FT_UShort encoding); + + /** + * Get the glyph index of the input character. + * + * @param index The character code of the requested glyph in the + * current encoding eg apple roman. + * @return The glyph index for the character. + */ + unsigned int CharIndex( unsigned int index ); + + /** + * Queries for errors. + * + * @return The current error code. + */ + FT_Error Error() const { return err;} + + protected: + /** + * Current character map code. + */ + FT_Encoding ftEncoding; + + /** + * The current Freetype face. + */ + FT_Face ftFace; + + /** + * A structure that maps glyph indices to character codes + * + * < character code, face glyph index> + */ +#ifdef FTGL_DO_NOT_USE_STL + typedef FTCharToGlyphIndexMap CharacterMap; +#else + typedef map< unsigned long, unsigned long> CharacterMap; +#endif + CharacterMap charMap; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; + + private: + +}; + + +#endif // __FTCharmap__ diff --git a/Utilities/ftgl/src/FTExtrdGlyph.cpp b/Utilities/ftgl/src/FTExtrdGlyph.cpp new file mode 100644 index 0000000..c2e9c57 --- /dev/null +++ b/Utilities/ftgl/src/FTExtrdGlyph.cpp @@ -0,0 +1,236 @@ +#include + +#include "FTExtrdGlyph.h" +#include "FTVectoriser.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTExtrdGlyph::FTExtrdGlyph( FT_Glyph glyph, float d) +: FTGlyph(), + vectoriser(0), + glList(0), + depth(d) +{ + if( ft_glyph_format_outline != glyph->format) + { + return; + } + + vectoriser = new FTVectoriser( glyph); + + vectoriser->Process(); + + // Make the front polygons + vectoriser->MakeMesh( 1.0); + + bBox = FTBBox( glyph); + bBox.z2 = -depth; + advance = (float)(glyph->advance.x >> 16); + + int numPoints = vectoriser->MeshPoints(); + if ( numPoints < 3) + { + delete vectoriser; + return; + } + + FTGL_DOUBLE* frontMesh = new FTGL_DOUBLE[ numPoints * 3]; + vectoriser->GetMesh( frontMesh); + + // Make the back polygons + vectoriser->MakeMesh( -1.0); + + numPoints = vectoriser->MeshPoints(); + if ( numPoints < 3) + { + delete vectoriser; + delete [] frontMesh; + return; + } + + FTGL_DOUBLE* backMesh = new FTGL_DOUBLE[ numPoints * 3]; + vectoriser->GetMesh( backMesh); + + numPoints = vectoriser->points(); + int numContours = vectoriser->contours(); // FIXME + + if ( ( numContours < 1) || ( numPoints < 3)) + { + delete vectoriser; + delete [] frontMesh; + delete [] backMesh; + return; + } + + // Build the edge polygons + int* contourLength = new int[ numContours]; + for( int cn = 0; cn < numContours; ++cn) + { + contourLength[cn] = vectoriser->contourSize( cn); + } + + FTGL_DOUBLE* sidemesh = new FTGL_DOUBLE[ numPoints * 3]; + vectoriser->GetOutline( sidemesh); + + delete vectoriser; + + // Draw the glyph + int offset = 0; + glList = glGenLists(1); + glNewList( glList, GL_COMPILE); + // Render Front Mesh + int i; + int BEPairs = static_cast(frontMesh[0]); + for( i = 0; i < BEPairs; ++i) + { + int polyType = (int)frontMesh[offset + 1]; + glBegin( polyType); + glNormal3d(0.0, 0.0, 1.0); + + int verts = (int)frontMesh[offset+2]; + offset += 3; + for( int x = 0; x < verts; ++x) + { + glVertex3dv( frontMesh + offset); + offset += 3; + } + glEnd(); + } + + // Render Back Mesh + offset = 0; + BEPairs = static_cast(backMesh[0]); + for( i = 0; i < BEPairs; ++i) + { + int polyType = (int)backMesh[offset + 1]; + glBegin( polyType); + + glNormal3d(0.0, 0.0, -1.0); + int verts = (int)backMesh[offset+2]; + offset += 3; + for( int x = 0; x < verts; ++x) + { + glVertex3d( backMesh[offset], backMesh[offset + 1], -depth); // FIXME + offset += 3; + } + glEnd(); + } + + FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; + FT_Outline ftOutline = outline->outline; + int contourFlag = ftOutline.flags; // this is broken for winding direction in freetype... + // BUT THIS DOESN'T WORK EITHER!!!!! +// bool winding = Winding( contourLength[0], sidemesh); + + // Join them together. + // Extrude each contour to make the sides. + FTGL_DOUBLE* contour = sidemesh; + for (int c=0; c= 0 ); +} + + +float FTExtrdGlyph::Render( const FT_Vector& pen, + const FTGLRenderContext *context) +{ + if( glList) + { + glTranslatef( (float)pen.x, (float)pen.y, 0); + glCallList( glList); + glTranslatef( (float)-pen.x, (float)-pen.y, 0); + } + + return advance; +} diff --git a/Utilities/ftgl/src/FTExtrdGlyph.h b/Utilities/ftgl/src/FTExtrdGlyph.h new file mode 100644 index 0000000..f996753 --- /dev/null +++ b/Utilities/ftgl/src/FTExtrdGlyph.h @@ -0,0 +1,75 @@ +#ifndef __FTExtrdGlyph__ +#define __FTExtrdGlyph__ + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGLgl.h" +#include "FTGlyph.h" + +class FTVectoriser; + +/** + * FTExtrdGlyph is a specialisation of FTGlyph for creating tessellated + * extruded polygon glyphs. + * + * @see FTGlyphContainer + * @see FTVectoriser + * + */ +class FTGL_EXPORT FTExtrdGlyph : public FTGlyph +{ + public: + /** + * Constructor + * + * @param glyph The Freetype glyph to be processed + */ + FTExtrdGlyph( FT_Glyph glyph, float depth); + + /** + * Destructor + */ + virtual ~FTExtrdGlyph(); + + /** + * Renders this glyph at the current pen position. + * + * @param pen The current pen position. + * @return The advance distance for this glyph. + */ + virtual float Render( const FT_Vector& pen, + const FTGLRenderContext *context = 0); + + private: + /** + * Calculate the winding direction of a contour. + * + * This uses the signed area of the contour. It is required because + * freetype doesn't do this despite the docs saying it does:( + */ + bool Winding( int numPoints, FTGL_DOUBLE *points); + + /** + * An object that helps convert freetype outlines into point + * data + */ + FTVectoriser* vectoriser; + + /** + * OpenGL display list + */ + GLuint glList; + + /** + * Distance to extrude the glyph + */ + float depth; + +}; + + +#endif // __FTExtrdGlyph__ + diff --git a/Utilities/ftgl/src/FTFace.cpp b/Utilities/ftgl/src/FTFace.cpp new file mode 100644 index 0000000..2349b86 --- /dev/null +++ b/Utilities/ftgl/src/FTFace.cpp @@ -0,0 +1,144 @@ +#include "FTFace.h" +#include "FTLibrary.h" +#include "FTCharmap.h" + +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTFace::FTFace() +: charMap(0), + ftFace(0), + numCharMaps(0), + numGlyphs(0), + err(0) +{} + + +FTFace::~FTFace() +{ + if (charMap) + { + delete charMap; + } + charMap = 0; + Close(); +} + + +bool FTFace::Open( const char* filename) +{ + // FIXME check library for errors + err = FT_New_Face( *FTLibrary::GetInstance()->GetLibrary(), + filename, + 0, + &ftFace); + + if( err) + { + return false; + } + else + { + charMap = new FTCharmap( ftFace); + return true; + } +} + + +bool FTFace::Open( const unsigned char *pBufferBytes, size_t bufferSizeInBytes ) +{ + // FIXME check library for errors + err = FT_New_Memory_Face( *FTLibrary::GetInstance()->GetLibrary(), + pBufferBytes, + bufferSizeInBytes, + 0, + &ftFace); + + if( err) + { + return false; + } + else + { + charMap = new FTCharmap( ftFace); + return true; + } +} + + +bool FTFace::Attach( const char* filename) +{ + err = FT_Attach_File( ftFace, filename); + return !err; +} + + +void FTFace::Close() +{ + if( ftFace) + { + FT_Done_Face( ftFace); + ftFace = 0; + } +} + + +FTSize& FTFace::Size( const unsigned int size, const unsigned int res) +{ + if( !charSize.CharSize( &ftFace, size, res, res)) + { + err = charSize.Error(); + } + + return charSize; +} + + +bool FTFace::CharMap( FT_Encoding encoding) +{ + return charMap->CharMap( encoding); +} + + +unsigned int FTFace::CharIndex( unsigned int index) const +{ + return charMap->CharIndex( index); +} + + +FT_Vector& FTFace::KernAdvance( unsigned int index1, unsigned int index2) +{ + kernAdvance.x = 0; kernAdvance.y = 0; + + if( FT_HAS_KERNING((ftFace)) && index1 && index2) + { + err = FT_Get_Kerning( ftFace, index1, index2, ft_kerning_unfitted, &kernAdvance); + if( !err) + { + kernAdvance.x /= 64; kernAdvance.y /= 64; + } + } + + return kernAdvance; +} + + +FT_Glyph* FTFace::Glyph( unsigned int index, FT_Int load_flags) +{ + err = FT_Load_Glyph( ftFace, index, load_flags); + err = FT_Get_Glyph( ftFace->glyph, &ftGlyph); + + if( !err) + { + return &ftGlyph; + } + else + { + return NULL; + } +} + + + diff --git a/Utilities/ftgl/src/FTFace.h b/Utilities/ftgl/src/FTFace.h new file mode 100644 index 0000000..06dad5b --- /dev/null +++ b/Utilities/ftgl/src/FTFace.h @@ -0,0 +1,162 @@ +#ifndef __FTFace__ +#define __FTFace__ + +#include "FTGL.h" + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTSize.h" + +class FTCharmap; + +/** + * FTFace class provides an abstraction layer for the Freetype Face. + * + * @see "Freetype 2 Documentation - 2.0.4" + * + */ +class FTGL_EXPORT FTFace +{ + public: + /** + * Default Constructor + */ + FTFace(); + + /** + * Destructor + * + * Disposes of the current Freetype Face. + */ + virtual ~FTFace(); + + /** + * Opens and reads a face file. + * + * @param fontname font file name. + * @return true if file has opened + * successfully. + */ + bool Open( const char* filename); + + /** + * Read face data from an in-memory buffer. + * + * @param pBufferBytes the in-memory buffer + * @param bufferSizeInBytes the length of the buffer in bytes + * @return true if file has opened + * successfully. + */ + bool Open( const unsigned char *pBufferBytes, size_t bufferSizeInBytes ); + + /** + * Attach auxilliary file to face (e.g., font metrics). + */ + bool Attach( const char* filename); + + /** + * Disposes of the face + */ + void Close(); + + /** + * Sets the char size for the current face. + * + * This doesn't guarantee that the size was set correctly. Clients + * should check errors. + * + * @param size the face size in points (1/72 inch) + * @param res the resolution of the target device. + * @return FTSize object + */ + FTSize& Size( const unsigned int size, const unsigned int res); + + /** + * Sets the character map for the face. + * + * This doesn't guarantee that the size was set correctly. Clients + * should check errors. + * + * @param encoding the Freetype encoding symbol. See above. + * @return true if charmap was valid + * and set correctly + */ + bool CharMap( FT_Encoding encoding); + + /** + * Get the glyph index of the input character. + * + * @param index The character code of the requested glyph in the + * current encoding eg apple roman. + * @return The glyph index for the character. + */ + unsigned int CharIndex( unsigned int index ) const; + + /** + * Gets the kerning vector between two glyphs + */ + FT_Vector& KernAdvance( unsigned int index1, unsigned int index2); + + /** + * Loads and creates a Freetype glyph. + */ + FT_Glyph* Glyph( unsigned int index, FT_Int load_flags); + + /** + * Gets the current Freetype face. + */ + FT_Face* Face() { return &ftFace;} + + /** + * Queries for errors. + * + * @return The current error code. + */ + FT_Error Error() const { return err; } + + private: + /** + * The size object associated with this face + */ + FTSize charSize; + + /** + * The Character Map object associated with this face + */ + FTCharmap* charMap; + + /** + * The Freetype face + */ + FT_Face ftFace; + + /** + * Temporary variable to hold a glyph + */ + FT_Glyph ftGlyph; + + /** + * The number of character maps in this face. + */ + int numCharMaps; + + /** + * The number of glyphs in this face + */ + int numGlyphs; + + /** + * Temporary variable to holding a kerning vector. + */ + FT_Vector kernAdvance; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; +}; + + +#endif // __FTFace__ diff --git a/Utilities/ftgl/src/FTFont.cpp b/Utilities/ftgl/src/FTFont.cpp new file mode 100644 index 0000000..330efff --- /dev/null +++ b/Utilities/ftgl/src/FTFont.cpp @@ -0,0 +1,289 @@ +#include "FTFace.h" +#include "FTFont.h" +#include "FTGlyphContainer.h" +#include "FTGlyph.h" // for FTBbox +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTFont::FTFont() +: numFaces(0), + glyphList(0), + numGlyphs(0), + preCache(true), + err(0) +{ + pen.x = 0; + pen.y = 0; +} + + +FTFont::~FTFont() +{ + Close(); +} + + +bool FTFont::Open( const char* fontname, bool p) +{ + preCache = p; + + if( face.Open( fontname)) + { + FT_Face* ftFace = face.Face(); + numGlyphs = (*ftFace)->num_glyphs; + + return true; + } + else + { + err = face.Error(); + return false; + } +} + + +bool FTFont::Open( const unsigned char *pBufferBytes, size_t bufferSizeInBytes, bool p ) +{ + preCache = p; + + if( face.Open( pBufferBytes, bufferSizeInBytes )) + { + FT_Face* ftFace = face.Face(); + numGlyphs = (*ftFace)->num_glyphs; + + return true; + } + else + { + err = face.Error(); + return false; + } +} + +bool FTFont::Attach( const char* filename) +{ + return face.Attach( filename); +} + +void FTFont::Close() +{ + delete glyphList; +} + + +bool FTFont::FaceSize( const unsigned int size, const unsigned int res ) +{ + charSize = face.Size( size, res); + + if( glyphList) + delete glyphList; + + glyphList = new FTGlyphContainer( &face, numGlyphs, preCache); + + if( preCache) + { + return MakeGlyphList() ? true : false; + } + + return true; +} + + +bool FTFont::MakeGlyphList() +{ + if( preCache) + { + for( unsigned int c = 0; c < numGlyphs; ++c) + { + glyphList->Add( MakeGlyph( c), c); + } + } + else + { + for( unsigned int c = 0; c < numGlyphs; ++c) + { + glyphList->Add( NULL, c); + } + } + + return !err; // FIXME what err? +} + + +bool FTFont::CharMap( FT_Encoding encoding) +{ + err = face.CharMap( encoding); + return !err; +} + + +int FTFont::Ascender() const +{ + return charSize.Ascender(); +} + + +int FTFont::Descender() const +{ + return charSize.Descender(); +} + +void FTFont::BBox( const char* string, + float& llx, float& lly, float& llz, float& urx, float& ury, float& urz) +{ + const unsigned char* c = (unsigned char*)string; + llx = lly = llz = urx = ury = urz = 0; + FTBBox bbox; + + while( *c) + { + if( !glyphList->Glyph( static_cast(*c))) + { + unsigned int g = face.CharIndex( static_cast(*c)); + glyphList->Add( MakeGlyph( g), g); + } + + bbox = glyphList->BBox( *c); + + // Lower extent + lly = lly < bbox.y1 ? lly: bbox.y1; + // Upper extent + ury = ury > bbox.y2 ? ury: bbox.y2; + // Depth + urz = urz < bbox.z2 ? urz: bbox.z2; + + // Width + urx += glyphList->Advance( *c, *(c + 1)); + ++c; + } + + //Final adjustments + llx = glyphList->BBox( *string).x1; + urx -= glyphList->Advance( *(c - 1), 0); + urx += bbox.x2; +} + +void FTFont::BBox( const wchar_t* string, + float& llx, float& lly, float& llz, float& urx, float& ury, float& urz) +{ + const wchar_t* c = string; + llx = lly = llz = urx = ury = urz = 0; + FTBBox bbox; + + while( *c) + { + if( !glyphList->Glyph( static_cast(*c))) + { + unsigned int g = face.CharIndex( static_cast(*c)); + glyphList->Add( MakeGlyph( g), g); + } + + bbox = glyphList->BBox( *c); + + // Lower extent + lly = lly < bbox.y1 ? lly: bbox.y1; + // Upper extent + ury = ury > bbox.y2 ? ury: bbox.y2; + // Depth + urz = urz < bbox.z2 ? urz: bbox.z2; + + // Width + urx += glyphList->Advance( *c, *(c + 1)); + ++c; + } + + //Final adjustments + llx = glyphList->BBox( *string).x1; + urx -= glyphList->Advance( *(c - 1), 0); + urx += bbox.x2; +} + + +float FTFont::Advance( const wchar_t* string) +{ + const wchar_t* c = string; + float width = 0; + + while( *c) + { + width += doAdvance( *c, *(c + 1)); + ++c; + } + + return width; +} + + +float FTFont::Advance( const char* string) +{ + const unsigned char* c = (unsigned char*)string; + float width = 0; + + while( *c) + { + width += doAdvance( *c, *(c + 1)); + ++c; + } + + return width; +} + + +float FTFont::doAdvance( const unsigned int chr, const unsigned int nextChr) +{ + if( !glyphList->Glyph( chr)) + { + unsigned int g = face.CharIndex( chr); + glyphList->Add( MakeGlyph( g), g); + } + + return glyphList->Advance( chr, nextChr); +} + + +void FTFont::render( const char* string, + const FTGLRenderContext *context) +{ + const unsigned char* c = (unsigned char*)string; + pen.x = 0; pen.y = 0; + + while( *c) + { + doRender( *c, *(c + 1), context); + ++c; + } +} + + +void FTFont::render( const wchar_t* string, + const FTGLRenderContext *context) +{ + const wchar_t* c = string; + pen.x = 0; pen.y = 0; + + while( *c) + { + doRender( *c, *(c + 1), context); + ++c; + } +} + + +void FTFont::doRender( const unsigned int chr, + const unsigned int nextChr, + const FTGLRenderContext *context) +{ + if( !glyphList->Glyph( chr)) + { + unsigned int g = face.CharIndex( chr); + glyphList->Add( MakeGlyph( g), g); + } + + FT_Vector kernAdvance = glyphList->render( chr, nextChr, pen, context); + + pen.x += kernAdvance.x; + pen.y += kernAdvance.y; +} + diff --git a/Utilities/ftgl/src/FTFont.h b/Utilities/ftgl/src/FTFont.h new file mode 100644 index 0000000..1c8aca5 --- /dev/null +++ b/Utilities/ftgl/src/FTFont.h @@ -0,0 +1,278 @@ +#ifndef __FTFont__ +#define __FTFont__ + +#include +#include FT_FREETYPE_H + +#include "FTGL.h" +#include "FTFace.h" + +class FTGlyphContainer; +class FTGlyph; + +/** + * FTFont is the public interface for the FTGL library. + * + * Specific font classes are derived from this class. It uses the helper + * classes FTFace and FTSize to access the Freetype library. This class + * is abstract and deriving classes must implement the protected + * MakeGlyph function to create glyphs of the + * appropriate type. + * + * @see FTFace + * @see FTSize + * @see FTGlyphContainer + * @see FTGlyph + */ +class FTGL_EXPORT FTFont +{ + public: + /** + * Default Constructor + */ + FTFont(); + + /** + * Destructor + */ + virtual ~FTFont(); + + /** + * Open and read a font file. + * + * @param fontname font file name. + * @param preCache A flag to indicate whether or not to build + * a complete set of glyphs at startup + * (true) or as required + * (false). Defaults to true. + * @return true if file has opened + * successfully. + */ + bool Open( const char* fontname, bool preCache = true); + + /** + * Open and read a font from a buffer in memory. + * + * @param pBufferBytes the in-memory buffer + * @param bufferSizeInBytes the length of the buffer in bytes + * @param preCache A flag to indicate whether or not to build + * a complete set of glyphs at startup + * (true) or as prequired + * (false). Defaults to true. + * @return true if file has opened + * successfully. + */ + virtual bool Open( const unsigned char *pBufferBytes, size_t bufferSizeInBytes, bool preCache = true); + + /** + * Attach auxilliary file to font (e.g., font metrics). + */ + bool Attach( const char* filename); + + /** + * Disposes of the font + */ + void Close(); + + /** + * Set the char size for the current face. + * + * @param size the face size in points (1/72 inch) + * @param res the resolution of the target device. + * @return true if size was set correctly + */ + bool FaceSize( const unsigned int size, const unsigned int res = 72); + + FTSize& GetSize() { return this->charSize; }; + + /** + * Gets the current face. + */ + FTFace* Face() { return &face;} + + /** + * Set the extrusion distance for the font. Only availbale for + * Extruded fonts + * + * @param d The extrusion distance. + */ + virtual void Depth( float ){} + + + /** + * Set the character map for the face. + * + * @param encoding Freetype enumerate for char map code. + * @return true if charmap was valid and + * set correctly + */ + bool CharMap( FT_Encoding encoding ); + + /** + * Get the global ascender height for the face. + * + * @return Ascender height + */ + int Ascender() const; + + /** + * Gets the global descender height for the face. + * + * @return Descender height + */ + int Descender() const; + + /** + * Get the bounding box for a string. + * + * @param string a char string + * @param llx lower left near x coord + * @param lly lower left near y coord + * @param llz lower left near z coord + * @param urx upper right far x coord + * @param ury upper right far y coord + * @param urz upper right far z coord + */ + void BBox( const char* text, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz); + + /** + * Get the bounding box for a string. + * + * @param string a wchar_t string + * @param llx lower left near x coord + * @param lly lower left near y coord + * @param llz lower left near z coord + * @param urx upper right far x coord + * @param ury upper right far y coord + * @param urz upper right far z coord + */ + void BBox( const wchar_t* string, float& llx, float& lly, float& llz, float& urx, float& ury, float& urz); + + /** + * Get the advance width for a string. + * + * @param string a wchar_t string + * @return advance width + */ + float Advance( const wchar_t* string); + + /** + * Get the advance width for a string. + * + * @param string a char string + * @return advance width + */ + float Advance( const char* string); + + /** + * Render a string of characters + * + * @param string 'C' style string to be output. + */ + virtual void render(const char* string, + const FTGLRenderContext *context = 0); + + /** + * Render a string of characters + * + * @param string wchar_t string to be output. + */ + virtual void render(const wchar_t* string, + const FTGLRenderContext *context = 0); + + /** + * Queries the Font for errors. + * + * @return The current error code. + */ + FT_Error Error() const { return err;} + + + protected: + /** + * Construct a glyph of the correct type. + * + * Clients must overide the function and return their specialised + * FTGlyph. + * + * @param g The glyph index NOT the char code. + * @return An FT****Glyph or null on failure. + */ + virtual FTGlyph* MakeGlyph( unsigned int g) = 0; + + /** + * Construct the internal glyph cache. + * + * This a list of glyphs processed for openGL rendering NOT + * freetype glyphs. + * + * @return true on success. + */ + virtual bool MakeGlyphList(); + + /** + * Get the advance width for a character. + * + * @param chr current character + * @param nextChr next character + * @return advance width + */ + float doAdvance( const unsigned int chr, const unsigned int nextChr); + + /** + * Render a character + * + * @param chr current character + * @param nextChr next character + */ + void doRender( const unsigned int chr, + const unsigned int nextChr, + const FTGLRenderContext *context = 0); + + /** + * Current face object + */ + FTFace face; + + /** + * Number of faces in this font + */ + unsigned int numFaces; + + /** + * Current size object + */ + FTSize charSize; + + /** + * An object that holds a list of glyphs + */ + FTGlyphContainer* glyphList; + + /** + * The number of glyphs in this font + */ + unsigned int numGlyphs; + + /** + * Have glyphs been pre-cached + */ + bool preCache; + + /** + * Current pen or cursor position; + */ + FT_Vector pen; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; + + private: + +}; + + +#endif // __FTFont__ + diff --git a/Utilities/ftgl/src/FTGL.h b/Utilities/ftgl/src/FTGL.h new file mode 100644 index 0000000..1e19d7b --- /dev/null +++ b/Utilities/ftgl/src/FTGL.h @@ -0,0 +1,92 @@ +#ifndef __FTGL__ +#define __FTGL__ + +#if defined(VTKFTGL) +#include "vtkftglConfig.h" +#endif + +// To include debug memory manager by Paul Nettle (midnight@FluidStudios.com) +// http://www.FluidStudios.com/publications.html +// Get this code and use it. It will open your eyes:) +// #define FTGL_DEBUG + +typedef double FTGL_DOUBLE; +typedef float FTGL_FLOAT; + +typedef void (*FTCallback)(); + +struct FTGLRenderContext +{ +#ifdef FTGL_SUPPORT_MANGLE_MESA + int UseMangleMesa; +#endif +}; + +#ifdef WIN32 + + // Under windows avoid including is overrated. + // Sure, it can be avoided and "name space pollution" can be + // avoided, but why? It really doesn't make that much difference + // these days. + #define WIN32_LEAN_AND_MEAN + #include + +#else + +// Some sgi compilers do not define true, false and bool +#ifndef false +#define false 0 +#define true 1 +#define bool char +#endif + +#endif + +// Compiler-specific conditional compilation +#ifdef _MSC_VER // MS Visual C++ + + // Disable various warning. + // 4786: template name too long + #pragma warning( disable : 4251 ) + #pragma warning( disable : 4275 ) + #pragma warning( disable : 4786 ) + + // Disable the usual'function ... not inlined' triggered by /W4 + #pragma warning( disable : 4710 ) + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET + +#pragma warning( disable : 4244 ) // conversion [...] possible loss of data +#pragma warning( disable : 4267 ) // same +#pragma warning( disable : 4311 ) // same for pointer +#pragma warning( disable : 4312 ) // same for pointer + +#endif /* _MSC_VER */ + +#endif + +#ifdef WIN32 + + // The following definitions control how symbols are exported. + // If the target is a static library ensure that FTGL_LIBRARY_STATIC + // is defined. If building a dynamic library (ie DLL) ensure the + // FTGL_LIBRARY macro is defined, as it will mark symbols for + // export. If compiling a project to _use_ the _dynamic_ library + // version of the library, no definition is required. + #ifdef FTGL_LIBRARY_STATIC // static lib - no special export required + # define FTGL_EXPORT + #else + #ifdef FTGL_LIBRARY // dynamic lib - must export/import symbols appropriately. + # define FTGL_EXPORT __declspec(dllexport) + #else + # define FTGL_EXPORT __declspec(dllimport) + #endif + #endif + +#else + // Compiler that is not MS Visual C++. + // Ensure that the export symbol is defined (and blank) + #define FTGL_EXPORT +#endif + +#endif // __FTGL__ diff --git a/Utilities/ftgl/src/FTGLBitmapFont.cpp b/Utilities/ftgl/src/FTGLBitmapFont.cpp new file mode 100644 index 0000000..6cd65f4 --- /dev/null +++ b/Utilities/ftgl/src/FTGLBitmapFont.cpp @@ -0,0 +1,64 @@ +#include "FTGLBitmapFont.h" +#include "FTBitmapGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTGLBitmapFont::FTGLBitmapFont() +{} + + +FTGLBitmapFont::~FTGLBitmapFont() +{} + + +FTGlyph* FTGLBitmapFont::MakeGlyph( unsigned int g) +{ + FT_Glyph* ftGlyph = face.Glyph( g, FT_LOAD_DEFAULT); + + if( ftGlyph) + { + FTBitmapGlyph* tempGlyph = new FTBitmapGlyph( *ftGlyph); +// FT_Done_Glyph( *ftGlyph ); + + return tempGlyph; + } + + err = face.Error(); + return NULL; +} + + +void FTGLBitmapFont::render(const char* string, + const FTGLRenderContext *context) + +{ +#ifdef FTGL_SUPPORT_MANGLE_MESA + if (context && context->UseMangleMesa) + { + this->RenderMesa(string, context); + } + else +#endif + { + this->RenderOpenGL(string, context); + } +} + + +void FTGLBitmapFont::render(const wchar_t* string, + const FTGLRenderContext *context) + +{ +#ifdef FTGL_SUPPORT_MANGLE_MESA + if (context && context->UseMangleMesa) + { + this->RenderMesa(string, context); + } + else +#endif + { + this->RenderOpenGL(string, context); + } +} diff --git a/Utilities/ftgl/src/FTGLBitmapFont.h b/Utilities/ftgl/src/FTGLBitmapFont.h new file mode 100644 index 0000000..96e5752 --- /dev/null +++ b/Utilities/ftgl/src/FTGLBitmapFont.h @@ -0,0 +1,70 @@ +#ifndef __FTGLBitmapFont__ +#define __FTGLBitmapFont__ + +#include "FTGL.h" + +#include "FTFont.h" + +class FTGlyph; + +/** + * FTGLBitmapFont is a specialisation of the FTFont class for handling + * Bitmap fonts + * + * @see FTFont + */ +class FTGL_EXPORT FTGLBitmapFont : public FTFont +{ + public: + /** + * Constructor + */ + FTGLBitmapFont(); + + /** + * Destructor + */ + ~FTGLBitmapFont(); + + /** + * Renders a string of characters + * + * @param string 'C' style string to be output. + */ + void render( const char* string, + const FTGLRenderContext *context = 0); + + /** + * Renders a string of characters + * + * @param string 'C' style wide string to be output. + */ + void render( const wchar_t* string, + const FTGLRenderContext *context = 0); + + // attributes + + private: + /** + * Construct a FTBitmapGlyph. + * + * @param g The glyph index NOT the char code. + * @return An FTBitmapGlyph or null on failure. + */ + virtual FTGlyph* MakeGlyph( unsigned int g); + + void RenderOpenGL(const char* string, + const FTGLRenderContext *context = 0); + void RenderOpenGL(const wchar_t* string, + const FTGLRenderContext *context = 0); + +#ifdef FTGL_SUPPORT_MANGLE_MESA + void RenderMesa(const char* string, + const FTGLRenderContext *context = 0); + void RenderMesa(const wchar_t* string, + const FTGLRenderContext *context = 0); +#endif + +}; + +#endif // __FTGLBitmapFont__ diff --git a/Utilities/ftgl/src/FTGLBitmapFontRenderMesa.cpp b/Utilities/ftgl/src/FTGLBitmapFontRenderMesa.cpp new file mode 100644 index 0000000..75eaeab --- /dev/null +++ b/Utilities/ftgl/src/FTGLBitmapFontRenderMesa.cpp @@ -0,0 +1,6 @@ +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#define RenderFunctionName RenderMesa + +#include "FTGLBitmapFontRenderOpenGL.cpp" diff --git a/Utilities/ftgl/src/FTGLBitmapFontRenderOpenGL.cpp b/Utilities/ftgl/src/FTGLBitmapFontRenderOpenGL.cpp new file mode 100644 index 0000000..90adf25 --- /dev/null +++ b/Utilities/ftgl/src/FTGLBitmapFontRenderOpenGL.cpp @@ -0,0 +1,46 @@ +#include "FTGLBitmapFont.h" +#include "FTBitmapGlyph.h" +#include "FTGLgl.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + +#ifndef RenderFunctionName +#define RenderFunctionName RenderOpenGL +#endif + +void FTGLBitmapFont::RenderFunctionName(const char* string, + const FTGLRenderContext *context) +{ + glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT); + glPushAttrib( GL_ENABLE_BIT); + + glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + + glDisable( GL_BLEND); + + FTFont::render(string, context); + + glPopAttrib(); + glPopClientAttrib(); +} + +void FTGLBitmapFont::RenderFunctionName(const wchar_t* string, + const FTGLRenderContext *context) +{ + glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT); + glPushAttrib( GL_ENABLE_BIT); + + glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); + + glDisable( GL_BLEND); + + FTFont::render(string, context); + + glPopAttrib(); + glPopClientAttrib(); +} diff --git a/Utilities/ftgl/src/FTGLExtrdFont.cpp b/Utilities/ftgl/src/FTGLExtrdFont.cpp new file mode 100644 index 0000000..738ad2a --- /dev/null +++ b/Utilities/ftgl/src/FTGLExtrdFont.cpp @@ -0,0 +1,31 @@ +#include "FTGLExtrdFont.h" +#include "FTExtrdGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTGLExtrdFont::FTGLExtrdFont() +: depth(0) +{} + + +FTGLExtrdFont::~FTGLExtrdFont() +{} + + +FTGlyph* FTGLExtrdFont::MakeGlyph( unsigned int g) +{ + FT_Glyph* ftGlyph = face.Glyph( g, FT_LOAD_DEFAULT); + + if( ftGlyph) + { + FTExtrdGlyph* tempGlyph = new FTExtrdGlyph( *ftGlyph, depth); + return tempGlyph; + } + + err = face.Error(); + return NULL; +} + + diff --git a/Utilities/ftgl/src/FTGLExtrdFont.h b/Utilities/ftgl/src/FTGLExtrdFont.h new file mode 100644 index 0000000..d979f67 --- /dev/null +++ b/Utilities/ftgl/src/FTGLExtrdFont.h @@ -0,0 +1,47 @@ +#ifndef __FTGLExtrdFont__ +#define __FTGLExtrdFont__ + +#include "FTGL.h" + +#include "FTFont.h" + +class FTGlyph; + + +/** + * FTGLPolygonFont is a specialisation of the FTFont class for handling + * tesselated Polygon Mesh fonts + * + * @see FTFont + */ +class FTGL_EXPORT FTGLExtrdFont : public FTFont +{ + public: + /** + * Default Constructor + */ + FTGLExtrdFont(); + + /** + * Destructor + */ + ~FTGLExtrdFont(); + + void Depth( float d) { depth = d;} + + private: + /** + * Construct a FTPolyGlyph. + * + * @param g The glyph index NOT the char code. + * @return An FTPolyGlyph or null on failure. + */ + virtual FTGlyph* MakeGlyph( unsigned int g); + + float depth; + +}; + + +#endif // __FTGLExtrdFont__ + diff --git a/Utilities/ftgl/src/FTGLOutlineFont.cpp b/Utilities/ftgl/src/FTGLOutlineFont.cpp new file mode 100644 index 0000000..3e7e470 --- /dev/null +++ b/Utilities/ftgl/src/FTGLOutlineFont.cpp @@ -0,0 +1,65 @@ +#include "FTGLOutlineFont.h" +#include "FTOutlineGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTGLOutlineFont::FTGLOutlineFont() +{} + + +FTGLOutlineFont::~FTGLOutlineFont() +{} + + +FTGlyph* FTGLOutlineFont::MakeGlyph( unsigned int g) +{ + FT_Glyph* ftGlyph = face.Glyph( g, FT_LOAD_DEFAULT); + + if( ftGlyph) + { + FTOutlineGlyph* tempGlyph = new FTOutlineGlyph( *ftGlyph); + return tempGlyph; + } + + err = face.Error(); + return NULL; +} + + +void FTGLOutlineFont::render( const char* string) +{ + glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT); + + glDisable( GL_TEXTURE_2D); + + glEnable( GL_LINE_SMOOTH); + glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE); + glEnable(GL_BLEND); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE + + FTFont::render( string); + + glPopAttrib(); + +} + + +void FTGLOutlineFont::render( const wchar_t* string) +{ + glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT); + + glDisable( GL_TEXTURE_2D); + + glEnable( GL_LINE_SMOOTH); + glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE); + glEnable(GL_BLEND); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE + + FTFont::render( string); + + glPopAttrib(); + +} + diff --git a/Utilities/ftgl/src/FTGLOutlineFont.h b/Utilities/ftgl/src/FTGLOutlineFont.h new file mode 100644 index 0000000..03bc495 --- /dev/null +++ b/Utilities/ftgl/src/FTGLOutlineFont.h @@ -0,0 +1,56 @@ +#ifndef __FTGLOutlineFont__ +#define __FTGLOutlineFont__ + +#include "FTGL.h" + +#include "FTFont.h" + +class FTGlyph; + + +/** + * FTGLOutlineFont is a specialisation of the FTFont class for handling + * Vector Outline fonts + * + * @see FTFont + */ +class FTGL_EXPORT FTGLOutlineFont : public FTFont +{ + public: + /** + * Default Constructor + */ + FTGLOutlineFont(); + + /** + * Destructor + */ + ~FTGLOutlineFont(); + + /** + * Renders a string of characters + * + * @param string 'C' style string to be output. + */ + void render( const char* string); + + /** + * Renders a string of characters + * + * @param string wchar_t string to be output. + */ + void render( const wchar_t* string); + + // attributes + + private: + /** + * Construct a FTOutlineGlyph. + * + * @param g The glyph index NOT the char code. + * @return An FTOutlineGlyph or null on failure. + */ + virtual FTGlyph* MakeGlyph( unsigned int g); + +}; +#endif // __FTGLOutlineFont__ diff --git a/Utilities/ftgl/src/FTGLPixmapFont.cpp b/Utilities/ftgl/src/FTGLPixmapFont.cpp new file mode 100644 index 0000000..cd78c9f --- /dev/null +++ b/Utilities/ftgl/src/FTGLPixmapFont.cpp @@ -0,0 +1,62 @@ +#include "FTGLPixmapFont.h" +#include "FTPixmapGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTGLPixmapFont::FTGLPixmapFont() +{} + + +FTGLPixmapFont::~FTGLPixmapFont() +{} + + +FTGlyph* FTGLPixmapFont::MakeGlyph( unsigned int g) +{ + FT_Glyph* ftGlyph = face.Glyph( g, FT_LOAD_DEFAULT); + + if( ftGlyph) + { + FTPixmapGlyph* tempGlyph = new FTPixmapGlyph( *ftGlyph); + return tempGlyph; + } + + err = face.Error(); + return NULL; +} + + +void FTGLPixmapFont::render(const char* string, + const FTGLRenderContext *context) + +{ +#ifdef FTGL_SUPPORT_MANGLE_MESA + if (context && context->UseMangleMesa) + { + this->RenderMesa(string, context); + } + else +#endif + { + this->RenderOpenGL(string, context); + } +} + + +void FTGLPixmapFont::render(const wchar_t* string, + const FTGLRenderContext *context) + +{ +#ifdef FTGL_SUPPORT_MANGLE_MESA + if (context && context->UseMangleMesa) + { + this->RenderMesa(string, context); + } + else +#endif + { + this->RenderOpenGL(string, context); + } +} diff --git a/Utilities/ftgl/src/FTGLPixmapFont.h b/Utilities/ftgl/src/FTGLPixmapFont.h new file mode 100644 index 0000000..82408b7 --- /dev/null +++ b/Utilities/ftgl/src/FTGLPixmapFont.h @@ -0,0 +1,72 @@ +#ifndef __FTGLPixmapFont__ +#define __FTGLPixmapFont__ + + +#include "FTGL.h" + +#include "FTFont.h" + +class FTGlyph; + + +/** + * FTGLPixmapFont is a specialisation of the FTFont class for handling + * Pixmap (Grey Scale) fonts + * + * @see FTFont + */ +class FTGL_EXPORT FTGLPixmapFont : public FTFont +{ + public: + /** + * Default Constructor + */ + FTGLPixmapFont(); + + /** + * Destructor + */ + ~FTGLPixmapFont(); + + /** + * Renders a string of characters + * + * @param string 'C' style string to be output. + */ + void render(const char* string, + const FTGLRenderContext *context = 0); + + /** + * Renders a string of characters + * + * @param string wchar_t string to be output. + */ + void render(const wchar_t* string, + const FTGLRenderContext *context = 0); + + + private: + /** + * Construct a FTPixmapGlyph. + * + * @param g The glyph index NOT the char code. + * @return An FTPixmapGlyph or null on failure. + */ + virtual FTGlyph* MakeGlyph( unsigned int g); + + void RenderOpenGL(const char* string, + const FTGLRenderContext *context = 0); + void RenderOpenGL(const wchar_t* string, + const FTGLRenderContext *context = 0); + +#ifdef FTGL_SUPPORT_MANGLE_MESA + void RenderMesa(const char* string, + const FTGLRenderContext *context = 0); + void RenderMesa(const wchar_t* string, + const FTGLRenderContext *context = 0); +#endif + +}; + +#endif // __FTGLPixmapFont__ + diff --git a/Utilities/ftgl/src/FTGLPixmapFontRenderMesa.cpp b/Utilities/ftgl/src/FTGLPixmapFontRenderMesa.cpp new file mode 100644 index 0000000..79eb008 --- /dev/null +++ b/Utilities/ftgl/src/FTGLPixmapFontRenderMesa.cpp @@ -0,0 +1,6 @@ +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#define RenderFunctionName RenderMesa + +#include "FTGLPixmapFontRenderOpenGL.cpp" diff --git a/Utilities/ftgl/src/FTGLPixmapFontRenderOpenGL.cpp b/Utilities/ftgl/src/FTGLPixmapFontRenderOpenGL.cpp new file mode 100644 index 0000000..caeb40a --- /dev/null +++ b/Utilities/ftgl/src/FTGLPixmapFontRenderOpenGL.cpp @@ -0,0 +1,46 @@ +#include "FTGLPixmapFont.h" +#include "FTPixmapGlyph.h" +#include "FTGLgl.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + +#ifndef RenderFunctionName +#define RenderFunctionName RenderOpenGL +#endif + +void FTGLPixmapFont::RenderFunctionName(const char* string, + const FTGLRenderContext *context) +{ + glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT); + glPushAttrib( GL_ENABLE_BIT | GL_PIXEL_MODE_BIT); + + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0); + + glEnable(GL_BLEND); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable( GL_TEXTURE_2D); + + FTFont::render(string, context); + + glPopAttrib(); + glPopClientAttrib(); +} + +void FTGLPixmapFont::RenderFunctionName(const wchar_t* string, + const FTGLRenderContext *context) +{ + glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT); + glPushAttrib( GL_ENABLE_BIT | GL_PIXEL_MODE_BIT); + + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0); + + glEnable(GL_BLEND); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable( GL_TEXTURE_2D); + + FTFont::render(string, context); + + glPopAttrib(); + glPopClientAttrib(); +} diff --git a/Utilities/ftgl/src/FTGLPolygonFont.cpp b/Utilities/ftgl/src/FTGLPolygonFont.cpp new file mode 100644 index 0000000..9c80c10 --- /dev/null +++ b/Utilities/ftgl/src/FTGLPolygonFont.cpp @@ -0,0 +1,30 @@ +#include "FTGLPolygonFont.h" +#include "FTPolyGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTGLPolygonFont::FTGLPolygonFont() +{} + + +FTGLPolygonFont::~FTGLPolygonFont() +{} + + +FTGlyph* FTGLPolygonFont::MakeGlyph( unsigned int g) +{ + FT_Glyph* ftGlyph = face.Glyph( g, FT_LOAD_DEFAULT); + + if( ftGlyph) + { + FTPolyGlyph* tempGlyph = new FTPolyGlyph( *ftGlyph); + return tempGlyph; + } + + err = face.Error(); + return NULL; +} + + diff --git a/Utilities/ftgl/src/FTGLPolygonFont.h b/Utilities/ftgl/src/FTGLPolygonFont.h new file mode 100644 index 0000000..52fa572 --- /dev/null +++ b/Utilities/ftgl/src/FTGLPolygonFont.h @@ -0,0 +1,43 @@ +#ifndef __FTGLPolygonFont__ +#define __FTGLPolygonFont__ + +#include "FTGL.h" + +#include "FTFont.h" + +class FTGlyph; + + +/** + * FTGLPolygonFont is a specialisation of the FTFont class for handling + * tesselated Polygon Mesh fonts + * + * @see FTFont + */ +class FTGL_EXPORT FTGLPolygonFont : public FTFont +{ + public: + /** + * Default Constructor + */ + FTGLPolygonFont(); + + /** + * Destructor + */ + ~FTGLPolygonFont(); + + private: + /** + * Construct a FTPolyGlyph. + * + * @param g The glyph index NOT the char code. + * @return An FTPolyGlyph or null on failure. + */ + virtual FTGlyph* MakeGlyph( unsigned int g); + +}; + + +#endif // __FTGLPolygonFont__ + diff --git a/Utilities/ftgl/src/FTGLTextureFont.cpp b/Utilities/ftgl/src/FTGLTextureFont.cpp new file mode 100644 index 0000000..32c1a91 --- /dev/null +++ b/Utilities/ftgl/src/FTGLTextureFont.cpp @@ -0,0 +1,175 @@ +#include "FTGLTextureFont.h" +#include "FTTextureGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +inline GLuint NextPowerOf2( GLuint in) +{ + in -= 1; + + in |= in >> 16; + in |= in >> 8; + in |= in >> 4; + in |= in >> 2; + in |= in >> 1; + + return in + 1; +} + + +FTGLTextureFont::FTGLTextureFont() +: maxTextSize(0), + textureWidth(0), + textureHeight(0), + numTextures(0), + textMem(0), + glyphHeight(0), + glyphWidth(0), + padding(1), + remGlyphs(0), + xOffset(0), + yOffset(0) +{} + + +FTGLTextureFont::~FTGLTextureFont() +{ + glDeleteTextures( numTextures, (const GLuint*)glTextureID); +} + + +FTGlyph* FTGLTextureFont::MakeGlyph( unsigned int g) +{ + FT_Glyph* ftGlyph = face.Glyph( g, FT_LOAD_NO_HINTING); + + if( ftGlyph) + { + // Estimate the glyph size size - global bbox + glyphHeight = ( charSize.Height()); + glyphWidth = ( charSize.Width()); + + // Is there a current texture + if( numTextures == 0) + { + glTextureID[0] = CreateTexture(); + xOffset = yOffset = padding; + ++numTextures; + } + + // will it fit in the current texture + if( xOffset > ( textureWidth - glyphWidth)) + { + xOffset = padding; + yOffset += glyphHeight; + + if( yOffset > ( textureHeight - glyphHeight)) + { + // no - make a new texture + glTextureID[numTextures] = CreateTexture(); + yOffset = padding; + ++numTextures; + } + } + + // yes - load the glyph + FTTextureGlyph* tempGlyph = new FTTextureGlyph( *ftGlyph, glTextureID[numTextures - 1], + xOffset, yOffset, textureWidth, textureHeight); + + // FIXME ceiling + xOffset += (int)(tempGlyph->BBox().x2 - tempGlyph->BBox().x1 + padding); + + --remGlyphs; + return tempGlyph; + } + + err = face.Error(); + return NULL; + +} + + +bool FTGLTextureFont::MakeGlyphList() +{ + if( !maxTextSize) + glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize); + + remGlyphs = numGlyphs; + + FTFont::MakeGlyphList(); + + return !err; // FIXME what err? +} + + +void FTGLTextureFont::GetSize() +{ + //work out the max width. Most likely maxTextSize + textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + padding * 2); + if( textureWidth > maxTextSize) + { + textureWidth = maxTextSize; + } + + int h = static_cast( (textureWidth - padding * 2) / glyphWidth); + + textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight); + textureHeight = textureHeight > maxTextSize ? maxTextSize : textureHeight; +} + + +int FTGLTextureFont::CreateTexture() +{ + // calc the size + GetSize(); + + // allocate some mem and clear it to black + int totalMem = textureWidth * textureHeight; + textMem = new unsigned char[totalMem]; // GL_ALPHA texture; + memset( textMem, 0, totalMem); + + // Create the blank texture + int textID; + glGenTextures( 1, (GLuint*)&textID); + + glPixelStorei( GL_UNPACK_ALIGNMENT, 1); //What does this do exactly? + glBindTexture( GL_TEXTURE_2D, textID); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textMem); + + delete [] textMem; + + return textID; +} + + +void FTGLTextureFont::render( const char* string) +{ + glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT); + + glEnable(GL_BLEND); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE + + FTFont::render( string); + + glPopAttrib(); +} + + +void FTGLTextureFont::render( const wchar_t* string) +{ + glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT); + + glEnable(GL_BLEND); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE + + FTFont::render( string); + + glPopAttrib(); +} + diff --git a/Utilities/ftgl/src/FTGLTextureFont.h b/Utilities/ftgl/src/FTGLTextureFont.h new file mode 100644 index 0000000..50251ec --- /dev/null +++ b/Utilities/ftgl/src/FTGLTextureFont.h @@ -0,0 +1,147 @@ +#ifndef __FTGLTextureFont__ +#define __FTGLTextureFont__ + +#include "FTGL.h" +#include "FTGLgl.h" +#include "FTFont.h" + +class FTTextureGlyph; + + +/** + * FTGLTextureFont is a specialisation of the FTFont class for handling + * Texture mapped fonts + * + * @see FTFont + */ +class FTGL_EXPORT FTGLTextureFont : public FTFont +{ + public: + /** + * Default Constructor + */ + FTGLTextureFont(); + + /** + * Destructor + */ + virtual ~FTGLTextureFont(); + + /** + * Get the total width of the texture that holds this font + */ + GLsizei TextureWidth() const { return textureWidth;} + + /** + * Get the total height of the texture that holds this font + */ + GLsizei TextureHeight() const { return textureHeight;} + + /** + * Renders a string of characters + * + * @param string 'C' style string to be output. + */ + virtual void render( const char* string); + + /** + * Renders a string of characters + * + * @param string wchar_t string to be output. + */ + virtual void render( const wchar_t* string); + + + private: + virtual FTGlyph* MakeGlyph( unsigned int g); + + /** + * Constructs the internal glyph cache. + * + * This a list of glyphs processed for openGL rendering NOT + * freetype glyphs + */ + virtual bool MakeGlyphList(); + + /** + * Get the size of a block of memory required to layout the glyphs + * + * Calculates a width and height based on the glyph sizes and the + * number of glyphs. It over estimates. + */ + void GetSize(); + + /** + * Creates a 'blank' OpenGL texture object. + * + * The format is GL_ALPHA and the params are + * GL_TEXTURE_WRAP_S = GL_CLAMP + * GL_TEXTURE_WRAP_T = GL_CLAMP + * GL_TEXTURE_MAG_FILTER = GL_LINEAR + * GL_TEXTURE_MIN_FILTER = GL_LINEAR + * Note that mipmapping is NOT used + * @param id The index into an array of glTextureIDs. + * @param width The width of the texture in bytes + * @param height The number of rows of bytes. + * @param data A pointer to the texture data + */ + int CreateTexture(); + + /** + * The maximum texture dimension on this OpenGL implemetation + */ + GLsizei maxTextSize; + + /** + * The minimum texture width required to hold the glyphs + */ + GLsizei textureWidth; + + /** + * The minimum texture height required to hold the glyphs + */ + GLsizei textureHeight; + + /** + *An array of texture ids + */ + unsigned long glTextureID[1024]; + + /** + * The number of textures required to hold the glyphs + */ + int numTextures; + + /** + * The memeory where the textures are built before beiing transferred + * to OpenGL + */ + unsigned char* textMem; + + /** + * The max height for glyphs in the current font + */ + int glyphHeight; + + /** + * The max width for glyphs in the current font + */ + int glyphWidth; + + /** + * A value to be added to the height and width to ensure that + * glyphs don't overlap in the texture + */ + int padding; + + int remGlyphs; + int xOffset; + int yOffset; + + +}; + + +#endif // __FTGLTextureFont__ + + diff --git a/Utilities/ftgl/src/FTGLgl.h b/Utilities/ftgl/src/FTGLgl.h new file mode 100644 index 0000000..1033439 --- /dev/null +++ b/Utilities/ftgl/src/FTGLgl.h @@ -0,0 +1,49 @@ +#ifndef __FTGLgl__ +#define __FTGLgl__ + +#include "FTGL.h" + +#ifdef WIN32 + + #ifndef __gl_h_ + #include + #ifndef FTGL_DO_NOT_USE_VECTORISER + #include + #endif + #endif + +#else + + // Non windows platforms - don't require nonsense as seen above :-) + #ifndef __gl_h_ + #ifdef __APPLE__ + #include + #ifndef FTGL_DO_NOT_USE_VECTORISER + #include + #endif + #else + #include + #ifndef FTGL_DO_NOT_USE_VECTORISER + #include + #endif + #endif + + #endif + + // Required for compatibility with glext.h style function definitions of + // OpenGL extensions, such as in src/osg/Point.cpp. + #ifndef APIENTRY + #define APIENTRY + #endif +#endif + +// lifted from glext.h, to remove dependancy on glext.h +#ifndef GL_EXT_texture_object + #define GL_TEXTURE_PRIORITY_EXT 0x8066 + #define GL_TEXTURE_RESIDENT_EXT 0x8067 + #define GL_TEXTURE_1D_BINDING_EXT 0x8068 + #define GL_TEXTURE_2D_BINDING_EXT 0x8069 + #define GL_TEXTURE_3D_BINDING_EXT 0x806A +#endif + +#endif // __FTGLgl__ diff --git a/Utilities/ftgl/src/FTGlyph.cpp b/Utilities/ftgl/src/FTGlyph.cpp new file mode 100644 index 0000000..b0bdd61 --- /dev/null +++ b/Utilities/ftgl/src/FTGlyph.cpp @@ -0,0 +1,24 @@ +#include "FTGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTGlyph::FTGlyph() +: advance(0), + err(0) +{ + pos.x = 0; + pos.y = 0; + this->glyphHasBeenConverted = 0; + this->glyph = 0; +} + + +FTGlyph::~FTGlyph() +{ + if(this->glyph) + { + FT_Done_Glyph( glyph ); + } +} diff --git a/Utilities/ftgl/src/FTGlyph.h b/Utilities/ftgl/src/FTGlyph.h new file mode 100644 index 0000000..4a23f86 --- /dev/null +++ b/Utilities/ftgl/src/FTGlyph.h @@ -0,0 +1,147 @@ +#ifndef __FTGlyph__ +#define __FTGlyph__ + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" + + +/** + * FTBBox + * + * + */ +class FTGL_EXPORT FTBBox +{ + public: + FTBBox() + : x1(0), + y1(0), + z1(0), + x2(0), + y2(0), + z2(0) + {} + + FTBBox( FT_Glyph glyph) + { + FT_BBox bbox; + FT_Glyph_Get_CBox( glyph, ft_glyph_bbox_subpixels, &bbox ); + + x1 = (float)(bbox.xMin >> 6); + y1 = (float)(bbox.yMin >> 6); + z1 = 0; + x2 = (float)(bbox.xMax >> 6); + y2 = (float)(bbox.yMax >> 6); + z2 = 0; + } + + FTBBox( int a, int b, int c, int d, int e, int f) + : x1((float)a), + y1((float)b), + z1((float)c), + x2((float)d), + y2((float)e), + z2((float)f) + {} + + ~FTBBox() + {} + + // Make these ftPoints + float x1, y1, z1, x2, y2, z2; + + protected: + + + private: +}; + + +/** + * FTGlyph is the base class for FTGL glyphs. + * + * It provides the interface between Freetype glyphs and their openGL + * renderable counterparts. This is an abstract class and derived classes + * must implement the render function. + * + * @see FTGlyphContainer + * + */ +class FTGL_EXPORT FTGlyph +{ + public: + /** + * Constructor + */ + FTGlyph(); + + /** + * Destructor + */ + virtual ~FTGlyph(); + + /** + * Renders this glyph at the current pen position. + * + * @param pen The current pen position. + * @return The advance distance for this glyph. + */ + virtual float Render( const FT_Vector& pen, + const FTGLRenderContext *context = 0) = 0; + + /** + * Return the advance width for this glyph. + * + * @return advance width. + */ + float Advance() const { return advance;} + + /** + * Return the bounding box for this glyph. + * + * @return bounding box. + */ + FTBBox BBox() const { return bBox;} + + /** + * Queries for errors. + * + * @return The current error code. + */ + FT_Error Error() const { return err;} + + protected: + /** + * The advance distance for this glyph + */ + float advance; + + /** + * Vector from the pen position to the topleft corner of the glyph + */ + FT_Vector pos; + + + /** + * A freetype bounding box + */ + FTBBox bBox; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; + + int glyphHasBeenConverted; + FT_Glyph glyph; + + private: + +}; + + +#endif // __FTGlyph__ + diff --git a/Utilities/ftgl/src/FTGlyphContainer.cpp b/Utilities/ftgl/src/FTGlyphContainer.cpp new file mode 100644 index 0000000..156c649 --- /dev/null +++ b/Utilities/ftgl/src/FTGlyphContainer.cpp @@ -0,0 +1,67 @@ +#include "FTGlyphContainer.h" +#include "FTGlyph.h" +#include "FTFace.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTGlyphContainer::FTGlyphContainer( FTFace* f, unsigned int g, bool p) +: preCache( p), + numGlyphs( g), + face( f), + err( 0) +{ + // Fill the glyphlist with null glyphs + glyphs.resize( g, NULL); +} + + +FTGlyphContainer::~FTGlyphContainer() +{ + GlyphVector::iterator iter; + for( iter = glyphs.begin(); iter != glyphs.end(); ++iter) + { + if( *iter) + { + delete *iter; + } + } + + glyphs.clear(); +} + + +float FTGlyphContainer::Advance( unsigned int index, unsigned int next) +{ + unsigned int left = face->CharIndex( index); + unsigned int right = face->CharIndex( next); + + float width = (float)face->KernAdvance( left, right).x; + width += glyphs[left]->Advance(); + + return width; +} + + +FT_Vector& FTGlyphContainer::render( unsigned int index, + unsigned int next, + FT_Vector pen, + const FTGLRenderContext *context) +{ + kernAdvance.x = 0; kernAdvance.y = 0; + + unsigned int left = face->CharIndex( index); + unsigned int right = face->CharIndex( next); + + kernAdvance = face->KernAdvance( left, right); + + if( !face->Error()) + { + advance = glyphs[left]->Render(pen, context); + } + + kernAdvance.x = (FT_Pos)(advance + kernAdvance.x); +// kernAdvance.y = advance.y + kernAdvance.y; + return kernAdvance; +} diff --git a/Utilities/ftgl/src/FTGlyphContainer.h b/Utilities/ftgl/src/FTGlyphContainer.h new file mode 100644 index 0000000..429d2fe --- /dev/null +++ b/Utilities/ftgl/src/FTGlyphContainer.h @@ -0,0 +1,146 @@ +#ifndef __FTGlyphContainer__ +#define __FTGlyphContainer__ + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGlyph.h" // for FTBBox + +#include "FTFace.h" + +#ifdef FTGL_DO_NOT_USE_STL +#include +#else +#include +#ifdef USE_STD_NAMESPACE +using namespace std; +#endif +#endif + +/** + * FTGlyphContainer holds the post processed FTGlyph objects. + * + * @see FTGlyph + */ +class FTGL_EXPORT FTGlyphContainer +{ + public: + /** + * Constructor + * + * @param face The Freetype face + * @param numGlyphs the number of glyphs in this face + * @param p A flag to indicate preprocessing of glyphs. + * Not used. + */ + FTGlyphContainer( FTFace* face, unsigned int numGlyphs, bool p = false); + + /** + * Destructor + */ + virtual ~FTGlyphContainer(); + + /** + * Adds a glyph to this glyph list. + * + * @param glyph + * @return true + */ + bool Add( FTGlyph* tempGlyph, unsigned int g) + { + glyphs[g] = tempGlyph; + return true; + } + + /** + * Get a glyph from the glyph list + * + * @param c The char code of the glyph NOT the glyph index + * @return An FTGlyph or null is it hasn't been + * loaded. + */ + FTGlyph* Glyph( const unsigned int c) const + { + return glyphs[face->CharIndex( c)]; + } + + FTBBox BBox( const unsigned int index) const + { + return glyphs[face->CharIndex( index)]->BBox(); + } + + /** + * Returns the kerned advance width for a glyph. + * + * @param index glyph index of the character + * @param next the next glyph in a string + * @return advance width + */ + float Advance( unsigned int index, unsigned int next); + + /** + * renders a character + * @param index the glyph to be rendered + * @param next the next glyph in the string. Used for kerning. + * @param pen the position to render the glyph + * @return The distance to advance the pen position after rendering + */ + FT_Vector& render( unsigned int index, + unsigned int next, + FT_Vector pen, + const FTGLRenderContext *context = 0); + + /** + * Queries the Font for errors. + * + * @return The current error code. + */ + virtual FT_Error Error() const { return err;} + + private: + /** + * A flag to indicate preprocessing of glyphs. Not used. + */ + bool preCache; + + /** + * How meny glyphs are stored in this container + */ + int numGlyphs; + + /** + * The current Freetype face + */ + FTFace* face; + + /** + * The kerning vector for the current pair of glyphs + */ + FT_Vector kernAdvance; + + /** + * The advance for the glyph being rendered + */ + float advance; + + /** + * A structure to hold the glyphs + */ +#ifdef FTGL_DO_NOT_USE_STL + typedef FTGlyphVector GlyphVector; +#else + typedef vector GlyphVector; +#endif + GlyphVector glyphs; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; + +}; + + +#endif // __FTGlyphContainer__ diff --git a/Utilities/ftgl/src/FTLibrary.cpp b/Utilities/ftgl/src/FTLibrary.cpp new file mode 100644 index 0000000..68f216c --- /dev/null +++ b/Utilities/ftgl/src/FTLibrary.cpp @@ -0,0 +1,154 @@ +#include "FTLibrary.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + +#include + +FTLibrary *FTLibrary::Instance = 0; +FTLibraryCleanup FTLibrary::Cleanup; +FTCallbackVector *FTLibraryCleanup::Dependencies = 0; + +// (static) Call and remove dependencies + +void FTLibraryCleanup::CallAndRemoveDependencies() +{ + if (!FTLibraryCleanup::Dependencies) + { + return; + } + + FTCallbackVector::iterator iter; + for(iter = FTLibraryCleanup::Dependencies->begin(); + iter != FTLibraryCleanup::Dependencies->end(); + ++iter) + { + if(*iter) + { + (*iter)(); + } + } + + delete FTLibraryCleanup::Dependencies; + FTLibraryCleanup::Dependencies = 0; +} + +// (static) Add dependency +// This gives a chance to dependent singleton (i.e. a font cache for ex.) +// to get cleaned up before the FTLibrary singleton is destroyed +// WARNING: this method auto-allocate the FTCallbackVector, which is +// freed by a call to CallAndRemoveDependencies in the destructor, so +// there better be at least one instance of that object, which is the +// case anyway otherwise this would make no sense. +// Why is Dependencies a static member ? Because a regular member would +// have to be initialized by the FTLibraryCleanup singleton, which can +// occurs after any other dependent singleton :( +// Why dynamic (allocated) ? Because (again) a static one would indeed +// be a singleton itself, that can be initialized *after* the other +// singletons, etc. + +void FTLibraryCleanup::AddDependency(FTCallback callback) +{ + if (!FTLibraryCleanup::Dependencies) + { + FTLibraryCleanup::Dependencies = new FTCallbackVector; + } + FTLibraryCleanup::Dependencies->push_back(callback); +} + +// Create the singleton cleanup + +FTLibraryCleanup::FTLibraryCleanup() +{ +} + +// Delete the singleton cleanup +// Thiswill delete the FTLibrary singleton itself, and call all dependencies +// before, so that external dependent singletons can be deleted first. + +FTLibraryCleanup::~FTLibraryCleanup() +{ + FTLibraryCleanup::CallAndRemoveDependencies(); + FTLibrary::SetInstance(0); +} + +// (static) Return the single instance + +FTLibrary* FTLibrary::GetInstance() +{ + if (!FTLibrary::Instance) + { + FTLibrary::Instance = new FTLibrary; + } + return FTLibrary::Instance; +} + +// (static) Set the singleton instance + +void FTLibrary::SetInstance(FTLibrary* instance) +{ + if (FTLibrary::Instance == instance) + { + return; + } + + if (FTLibrary::Instance) + { + delete FTLibrary::Instance; + } + + FTLibrary::Instance = instance; +} + +FTLibrary::FTLibrary() +: lib(0), + err(0) +{ + Init(); +} + +FTLibrary::~FTLibrary() +{ + if( lib != 0) + { + FT_Done_FreeType( *lib); + + delete lib; + lib= 0; + } + +// if( manager != 0) +// { +// FTC_Manager_Done( manager ); +// +// delete manager; +// manager= 0; +// } +} + +bool FTLibrary::Init() +{ + if( lib != 0 ) + return true; + + lib = new FT_Library; + + err = FT_Init_FreeType( lib); + if( err) + { + delete lib; + lib = 0; + return false; + } + +// FTC_Manager* manager; +// +// if( FTC_Manager_New( lib, 0, 0, 0, my_face_requester, 0, manager ) +// { +// delete manager; +// manager= 0; +// return false; +// } + + return true; +} diff --git a/Utilities/ftgl/src/FTLibrary.h b/Utilities/ftgl/src/FTLibrary.h new file mode 100644 index 0000000..13b7325 --- /dev/null +++ b/Utilities/ftgl/src/FTLibrary.h @@ -0,0 +1,117 @@ +#ifndef __FTLibrary__ +#define __FTLibrary__ + +#include "FTGL.h" + +#include +#include FT_FREETYPE_H +//#include FT_CACHE_H + + +/** + * FTLibrary class is the global accessor for the Freetype library. + * + * This class encapsulates the Freetype Library. This is a singleton class + * and ensures that only one FT_Library is in existence at any one time. + * All constructors are private therefore clients cannot create or + * instantiate this class themselves and must access it's methods via the + * static FTLibrary::Instance() function. + * + * Just because this class returns a valid FTLibrary object + * doesn't mean that the Freetype Library has been successfully initialised. + * Clients should check for errors. You can initialse the library AND check + * for errors using the following code... + * err = FTLibrary::Instance().Error(); + * + * @see "Freetype 2 Documentation - 2.0.4" + * + */ +class FTCallbackVector; + +class FTGL_EXPORT FTLibraryCleanup +{ +public: + FTLibraryCleanup(); + ~FTLibraryCleanup(); + + static void AddDependency(FTCallback); + static void CallAndRemoveDependencies(); + +private: + static FTCallbackVector *Dependencies; +}; + +class FTGL_EXPORT FTLibrary +{ + public: + /** + * Global acces point to the single FTLibrary object. + * + * @return The global FTLibrary object. + */ + static FTLibrary* GetInstance(); + + /** + * Manually sets the library/singleton + */ + static void SetInstance (FTLibrary*); + + /** + * Gets a pointer to the native Freetype library. + * + * @return A handle to a FreeType library instance. + */ + FT_Library* GetLibrary() const { return lib;} + + /** + * Queries the library for errors. + * + * @return The current error code. + */ + virtual FT_Error Error() const { return err;} + + /** + * Destructor + * + * Disposes of the Freetype library + */ + virtual ~FTLibrary(); + + private: + + /** + * Default constructors. + */ + FTLibrary(); + FTLibrary( const FT_Library&) {} + FTLibrary& operator=( const FT_Library&) { return *this; } + + /** + * Initialises the Freetype library + * + * Even though this function indicates success via the return value, + * clients can't see this so must check the error codes. This function + * is only ever called by the default c_stor + * + * @return true if the Freetype library was + * successfully initialised, false + * otherwise. + */ + bool Init(); + + /** + * Freetype library handle. + */ + FT_Library* lib; +// FTC_Manager* manager; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; + + static FTLibraryCleanup Cleanup; + static FTLibrary* Instance; +}; + +#endif // __FTLibrary__ diff --git a/Utilities/ftgl/src/FTOutlineGlyph.cpp b/Utilities/ftgl/src/FTOutlineGlyph.cpp new file mode 100644 index 0000000..7c8b409 --- /dev/null +++ b/Utilities/ftgl/src/FTOutlineGlyph.cpp @@ -0,0 +1,91 @@ +#include "FTOutlineGlyph.h" +#include "FTVectoriser.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTOutlineGlyph::FTOutlineGlyph( FT_Glyph glyph) +: FTGlyph(), + vectoriser(0), + numPoints(0), + numContours(0), + contourLength(0), + data(0), + glList(0) +{ + if( ft_glyph_format_outline != glyph->format) + { + return; + } + + vectoriser = new FTVectoriser( glyph); + + vectoriser->Process(); + + numPoints = vectoriser->points(); + numContours = vectoriser->contours(); + + bBox = FTBBox( glyph); + advance = (float)(glyph->advance.x >> 16); + + if ( ( numContours < 1) || ( numPoints < 3)) + { + delete vectoriser; + return; + } + + contourLength = new int[ numContours]; + for( int cn = 0; cn < numContours; ++cn) + { + contourLength[cn] = vectoriser->contourSize( cn); + } + + data = new FTGL_DOUBLE[ numPoints * 3]; + vectoriser->GetOutline( data); + + delete vectoriser; + + int d = 0; + glList = glGenLists(1); + glNewList( glList, GL_COMPILE); + for( int c = 0; c < numContours; ++c) + { + glBegin( GL_LINE_LOOP); + for( int p = 0; p < contourLength[c]; ++p) + { + glVertex2dv( data + d); + d += 3; + } + glEnd(); + } + glEndList(); + + delete [] data; // FIXME + delete [] contourLength; // FIXME + + // discard glyph image (bitmap or not) + FT_Done_Glyph( glyph); // Why does this have to be HERE +} + + +FTOutlineGlyph::~FTOutlineGlyph() +{ +// delete [] data; +// delete [] contourLength; +} + + +float FTOutlineGlyph::Render( const FT_Vector& pen, + const FTGLRenderContext *context) +{ + if( glList) + { + glTranslatef( (float)pen.x, (float)pen.y, 0); + glCallList( glList); + glTranslatef( (float)-pen.x, (float)-pen.y, 0); + } + + return advance; +} + diff --git a/Utilities/ftgl/src/FTOutlineGlyph.h b/Utilities/ftgl/src/FTOutlineGlyph.h new file mode 100644 index 0000000..f7020c6 --- /dev/null +++ b/Utilities/ftgl/src/FTOutlineGlyph.h @@ -0,0 +1,82 @@ +#ifndef __FTOutlineGlyph__ +#define __FTOutlineGlyph__ + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGLgl.h" +#include "FTGlyph.h" + +class FTVectoriser; + + +/** + * FTOutlineGlyph is a specialisation of FTGlyph for creating outlines. + * + * @see FTGlyphContainer + * @see FTVectoriser + * + */ +class FTGL_EXPORT FTOutlineGlyph : public FTGlyph +{ + public: + /** + * Constructor + * + * @param glyph The Freetype glyph to be processed + */ + FTOutlineGlyph( FT_Glyph glyph); + + /** + * Destructor + */ + virtual ~FTOutlineGlyph(); + + /** + * Renders this glyph at the current pen position. + * + * @param pen The current pen position. + * @return The advance distance for this glyph. + */ + virtual float Render( const FT_Vector& pen, + const FTGLRenderContext *context = 0); + + private: + /** + * An object that helps convert freetype outlines into point + * data + */ + FTVectoriser* vectoriser; + + /** + * The total number of points in the Freetype outline + */ + int numPoints; + + /** + * The totals number of contours in the Freetype outline + */ + int numContours; + + /** + * An array containing the number of points in each outline + */ + int* contourLength; + + /** + * Pointer to the point data + */ + FTGL_DOUBLE* data; + + /** + * OpenGL display list + */ + GLuint glList; + +}; + + +#endif // __FTOutlineGlyph__ + diff --git a/Utilities/ftgl/src/FTPixmapGlyph.cpp b/Utilities/ftgl/src/FTPixmapGlyph.cpp new file mode 100644 index 0000000..f3e7a95 --- /dev/null +++ b/Utilities/ftgl/src/FTPixmapGlyph.cpp @@ -0,0 +1,159 @@ +#include "FTPixmapGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTPixmapGlyph::FTPixmapGlyph( FT_Glyph _glyph) +: FTGlyph(), + destWidth(0), + destHeight(0), + numGreys(0), + data(0) +{ + this->glyph = _glyph; + bBox = FTBBox(this->glyph); + advance = (float)(this->glyph->advance.x >> 16); +} + +void FTPixmapGlyph::ConvertGlyph(const FTGLRenderContext *context) +{ + // This function will always fail if the glyph's format isn't scalable???? + err = FT_Glyph_To_Bitmap( &this->glyph, ft_render_mode_normal, 0, 1); + if( err || ft_glyph_format_bitmap != this->glyph->format) + { + return; + } + + FT_BitmapGlyph bitmap = reinterpret_cast(this->glyph); + FT_Bitmap* source = &bitmap->bitmap; + + //check the pixel mode + //ft_pixel_mode_grays + + int srcWidth = source->width; + int srcHeight = source->rows; + int srcPitch = source->pitch; + + // FIXME What about dest alignment? + destWidth = srcWidth; + destHeight = srcHeight; + + if( destWidth && destHeight) + { + data = new unsigned char[destWidth * destHeight * 4]; + + // Get the current glColor. + float ftglColour[4]; +#ifdef FTGL_SUPPORT_MANGLE_MESA + if (context && context->UseMangleMesa) + { + this->GetCurrentColorMesa(ftglColour, context); + } + else +#endif + { + this->GetCurrentColorOpenGL(ftglColour, context); + } + +#if 1 + unsigned char red = static_cast(ftglColour[0]*255.0f); + unsigned char green = static_cast(ftglColour[1]*255.0f); + unsigned char blue = static_cast(ftglColour[2]*255.0f); + + unsigned char *src = source->buffer; + unsigned char *src_row; + + unsigned char *dest = data + ((destHeight - 1) * destWidth) * 4; + size_t dest_step = destWidth * 4 * 2; + + if (ftglColour[3] == 1.0f) + { + for(int y = 0; y < srcHeight; ++y) + { + src_row = src; + for(int x = 0; x < srcWidth; ++x) + { + *dest++ = red; + *dest++ = green; + *dest++ = blue; + *dest++ = *src_row++; + } + src += srcPitch; + dest -= dest_step; + } + } + else + { + for(int y = 0; y < srcHeight; ++y) + { + src_row = src; + for(int x = 0; x < srcWidth; ++x) + { + *dest++ = red; + *dest++ = green; + *dest++ = blue; + *dest++ = static_cast(ftglColour[3] * *src_row++); + } + src += srcPitch; + dest -= dest_step; + } + } +#else + + for(int y = 0; y < srcHeight; ++y) + { + --destHeight; + for(int x = 0; x < srcWidth; ++x) + { + *( data + ( destHeight * destWidth + x) * 4 + 0) = static_cast( ftglColour[0] * 255.0f); + *( data + ( destHeight * destWidth + x) * 4 + 1) = static_cast( ftglColour[1] * 255.0f); + *( data + ( destHeight * destWidth + x) * 4 + 2) = static_cast( ftglColour[2] * 255.0f); + *( data + ( destHeight * destWidth + x) * 4 + 3) = static_cast( ftglColour[3] * (*( source->buffer + ( y * srcPitch) + x))); + } + } + +#endif + + destHeight = srcHeight; + } + + numGreys = source->num_grays; + pos.x = bitmap->left; + pos.y = srcHeight - bitmap->top; + + this->glyphHasBeenConverted = 1; +} + + +FTPixmapGlyph::~FTPixmapGlyph() +{ + if( data) + delete [] data; +} + + +float FTPixmapGlyph::Render( const FT_Vector& pen, + const FTGLRenderContext *context) +{ + if (!this->glyphHasBeenConverted) + { + this->ConvertGlyph(context); + } + + if( data) + { +#ifdef FTGL_SUPPORT_MANGLE_MESA + if (context && context->UseMangleMesa) + { + this->RenderMesa(pen, context); + } + else +#endif + { + this->RenderOpenGL(pen, context); + } + } + + return advance; +} diff --git a/Utilities/ftgl/src/FTPixmapGlyph.h b/Utilities/ftgl/src/FTPixmapGlyph.h new file mode 100644 index 0000000..c7c0df8 --- /dev/null +++ b/Utilities/ftgl/src/FTPixmapGlyph.h @@ -0,0 +1,80 @@ +#ifndef __FTPixmapGlyph__ +#define __FTPixmapGlyph__ + + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGlyph.h" + + +/** + * FTPixmapGlyph is a specialisation of FTGlyph for creating pixmaps. + * + * @see FTGlyphContainer + * + */ +class FTGL_EXPORT FTPixmapGlyph : public FTGlyph +{ + public: + /** + * Constructor + * + * @param glyph The Freetype glyph to be processed + */ + FTPixmapGlyph( FT_Glyph glyph); + + /** + * Destructor + */ + virtual ~FTPixmapGlyph(); + + /** + * Renders this glyph at the current pen position. + * + * @param pen The current pen position. + * @return The advance distance for this glyph. + */ + virtual float Render( const FT_Vector& pen, + const FTGLRenderContext *context = 0); + + virtual void ConvertGlyph(const FTGLRenderContext *context = 0); + + private: + /** + * The width of the glyph 'image' + */ + int destWidth; + + /** + * The height of the glyph 'image' + */ + int destHeight; + + /** + * The number of greys or bit depth of the image + */ + int numGreys; + + /** + * Pointer to the 'image' data + */ + unsigned char* data; + + void RenderOpenGL(const FT_Vector& pen, + const FTGLRenderContext *context = 0); + void GetCurrentColorOpenGL(float colour[4], + const FTGLRenderContext *context = 0); + +#ifdef FTGL_SUPPORT_MANGLE_MESA + void RenderMesa(const FT_Vector& pen, + const FTGLRenderContext *context = 0); + void GetCurrentColorMesa(float colour[4], + const FTGLRenderContext *context = 0); +#endif + +}; + +#endif // __FTPixmapGlyph__ diff --git a/Utilities/ftgl/src/FTPixmapGlyphRenderMesa.cpp b/Utilities/ftgl/src/FTPixmapGlyphRenderMesa.cpp new file mode 100644 index 0000000..2d67bcf --- /dev/null +++ b/Utilities/ftgl/src/FTPixmapGlyphRenderMesa.cpp @@ -0,0 +1,7 @@ +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#define RenderFunctionName RenderMesa +#define GetCurrentColorFunctionName GetCurrentColorMesa + +#include "FTPixmapGlyphRenderOpenGL.cpp" diff --git a/Utilities/ftgl/src/FTPixmapGlyphRenderOpenGL.cpp b/Utilities/ftgl/src/FTPixmapGlyphRenderOpenGL.cpp new file mode 100644 index 0000000..545cf49 --- /dev/null +++ b/Utilities/ftgl/src/FTPixmapGlyphRenderOpenGL.cpp @@ -0,0 +1,31 @@ +#include "FTPixmapGlyph.h" +#include "FTGLgl.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + +#ifndef GetCurrentColorFunctionName +#define GetCurrentColorFunctionName GetCurrentColorOpenGL +#endif + +void FTPixmapGlyph::GetCurrentColorFunctionName(float colour[4], + const FTGLRenderContext *) +{ + glGetFloatv( GL_CURRENT_COLOR, colour); +} + +#ifndef RenderFunctionName +#define RenderFunctionName RenderOpenGL +#endif + +void FTPixmapGlyph::RenderFunctionName(const FT_Vector& pen, + const FTGLRenderContext *) +{ + // Move the glyph origin + glBitmap( 0, 0, 0.0, 0.0, (float)(pen.x + pos.x), (float)(pen.y - pos.y), (const GLubyte *)0); + + glDrawPixels( destWidth, destHeight, GL_RGBA, GL_UNSIGNED_BYTE, (const GLvoid*)data); + + // Restore the glyph origin + glBitmap( 0, 0, 0.0, 0.0, (float)(-pen.x - pos.x), (float)(-pen.y + pos.y), (const GLubyte *)0); +} diff --git a/Utilities/ftgl/src/FTPolyGlyph.cpp b/Utilities/ftgl/src/FTPolyGlyph.cpp new file mode 100644 index 0000000..049f6dc --- /dev/null +++ b/Utilities/ftgl/src/FTPolyGlyph.cpp @@ -0,0 +1,86 @@ +#include "FTPolyGlyph.h" +#include "FTVectoriser.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTPolyGlyph::FTPolyGlyph( FT_Glyph glyph) +: FTGlyph(), + vectoriser(0), + numPoints(0), + data(0), + glList(0) +{ + if( ft_glyph_format_outline != glyph->format) + { + return; + } + + vectoriser = new FTVectoriser( glyph); + + vectoriser->Process(); + + vectoriser->MakeMesh(1.0); + numPoints = vectoriser->MeshPoints(); + + bBox = FTBBox( glyph); + advance = (float)(glyph->advance.x >> 16); + + if ( numPoints < 3) + { + delete vectoriser; + return; + } + + data = new FTGL_DOUBLE[ numPoints * 3]; + vectoriser->GetMesh( data); + delete vectoriser; + + int d = 0; + glList = glGenLists(1); + glNewList( glList, GL_COMPILE); + int BEPairs = static_cast(data[0]); + for( int i = 0; i < BEPairs; ++i) + { + int polyType = (int)data[d + 1]; + glBegin( polyType); + + int verts = (int)data[d+2]; + d += 3; + for( int x = 0; x < verts; ++x) + { + glVertex3dv( data + d); + d += 3; + } + glEnd(); + } + glEndList(); + + delete [] data; // FIXME + data = 0; + + // discard glyph image (bitmap or not) + FT_Done_Glyph( glyph); // Why does this have to be HERE +} + + +FTPolyGlyph::~FTPolyGlyph() +{ +// if( data) +// delete [] data; // FIXME +} + + +float FTPolyGlyph::Render( const FT_Vector& pen, + const FTGLRenderContext *context) +{ + if( glList) + { + glTranslatef( (float)pen.x, (float)pen.y, 0); + glCallList( glList); + glTranslatef( (float)-pen.x, (float)-pen.y, 0); + } + + return advance; +} diff --git a/Utilities/ftgl/src/FTPolyGlyph.h b/Utilities/ftgl/src/FTPolyGlyph.h new file mode 100644 index 0000000..1eb2215 --- /dev/null +++ b/Utilities/ftgl/src/FTPolyGlyph.h @@ -0,0 +1,80 @@ +#ifndef __FTPolyGlyph__ +#define __FTPolyGlyph__ + + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGLgl.h" +#include "FTGlyph.h" + +class FTVectoriser; + +/** + * FTPolyGlyph is a specialisation of FTGlyph for creating tessellated + * polygon glyphs. + * + * @see FTGlyphContainer + * @see FTVectoriser + * + */ +class FTGL_EXPORT FTPolyGlyph : public FTGlyph +{ + public: + /** + * Constructor + * + * @param glyph The Freetype glyph to be processed + */ + FTPolyGlyph( FT_Glyph glyph); + + /** + * Destructor + */ + virtual ~FTPolyGlyph(); + + /** + * Renders this glyph at the current pen position. + * + * @param pen The current pen position. + * @return The advance distance for this glyph. + */ + virtual float Render( const FT_Vector& pen, + const FTGLRenderContext *context = 0); + + private: + /** + * Convert the point data into a mesh. + * + * Uses GLUtesselator to create a mesh + */ + void Tesselate(); + + /** + * An object that helps convert freetype outlines into point + * data + */ + FTVectoriser* vectoriser; + + /** + * The total number of points in the Freetype outline + */ + int numPoints; + + /** + * Pointer to the point data + */ + FTGL_DOUBLE* data; + + /** + * OpenGL display list + */ + GLuint glList; + +}; + + +#endif // __FTPolyGlyph__ + diff --git a/Utilities/ftgl/src/FTSize.cpp b/Utilities/ftgl/src/FTSize.cpp new file mode 100644 index 0000000..ad5b828 --- /dev/null +++ b/Utilities/ftgl/src/FTSize.cpp @@ -0,0 +1,93 @@ +#include "FTSize.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTSize::FTSize() +: ftFace(0), + size(0), + err(0) +{} + + +FTSize::~FTSize() +{} + + +bool FTSize::CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution ) +{ + ftFace = face; + size = point_size; + err = FT_Set_Char_Size( *ftFace, 0L, point_size * 64, x_resolution, y_resolution); + + ftSize = (*ftFace)->size; + + return !err; +} + + +int FTSize::Ascender() const +{ + return ftSize->metrics.ascender >> 6; +} + + +int FTSize::Descender() const +{ + return ftSize->metrics.descender >> 6; +} + + +int FTSize::Height() const +{ + if( FT_IS_SCALABLE((*ftFace))) + { + float height; + if( FT_IS_SFNT((*ftFace))) // Don't think this is correct + { + height = (float)((*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin); // bbox.yMax-bbox.yMin + } + else + { + height = (float)(((*ftFace)->bbox.yMax - (*ftFace)->bbox.yMin) >> 16); // bbox.yMax-bbox.yMin + } + + height = height * ( (float)ftSize->metrics.y_ppem / (float)(*ftFace)->units_per_EM); + return static_cast(height); + } + else + { + return ftSize->metrics.height >> 6; + } +} + + +int FTSize::Width() const +{ + if( FT_IS_SCALABLE((*ftFace))) + { + float width; + if( FT_IS_SFNT((*ftFace))) // Don't think this is correct + { + width = (float)((*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin); // bbox.xMax-bbox.xMin + } + else + { + width = (float)(((*ftFace)->bbox.xMax - (*ftFace)->bbox.xMin) >> 16); // bbox.xMax-bbox.xMin + } + + width = width * ( (float)ftSize->metrics.x_ppem / (float)(*ftFace)->units_per_EM); + return static_cast(width); + } + else + { + return ftSize->metrics.max_advance >> 6; + } +} + + +int FTSize::Underline() const +{ + return 0; +} diff --git a/Utilities/ftgl/src/FTSize.h b/Utilities/ftgl/src/FTSize.h new file mode 100644 index 0000000..2aaa7e5 --- /dev/null +++ b/Utilities/ftgl/src/FTSize.h @@ -0,0 +1,123 @@ +#ifndef __FTSize__ +#define __FTSize__ + + +#include +#include FT_FREETYPE_H + +#include "FTGL.h" + + + +/** + * FTSize class provides an abstraction layer for the Freetype Size. + * + * @see "Freetype 2 Documentation - 2.0.4" + * + */ +class FTGL_EXPORT FTSize +{ + public: + /** + * Default Constructor + */ + FTSize(); + + /** + * Destructor + */ + virtual ~FTSize(); + + /** + * Sets the char size for the current face. + * + * This doesn't guarantee that the size was set correctly. Clients + * should check errors. + * + * @param point_size the face size in points (1/72 inch) + * @param x_resolution the horizontal resolution of the target device. + * @param y_resolution the vertical resolution of the target device. + * @return true if the size has been set. Clients should check Error() for more information if this function returns false() + */ + bool CharSize( FT_Face* face, unsigned int point_size, unsigned int x_resolution, unsigned int y_resolution ); + + /** + * Gets the global ascender height for the face in pixels. + * + * @return Ascender height + */ + int Ascender() const; + + /** + * Gets the global descender height for the face in pixels. + * + * @return Ascender height + */ + int Descender() const; + + /** + * Gets the global face height for the face. + * + * If the face is scalable this returns the height of the global + * bounding box which ensures that any glyph will be less than or + * equal to this height. If the font isn't scalable there is no + * guarantee that glyphs will not be taller than this value. + * + * @return height in pixels. + */ + int Height() const; + + /** + * Gets the global face width for the face. + * + * If the face is scalable this returns the width of the global + * bounding box which ensures that any glyph will be less than or + * equal to this width. If the font isn't scalable this value is + * the max_advance for the face. + * + * @return width in pixels. + */ + int Width() const; + + /** + * Gets the underline position for the face. + * + * @return underline position in pixels + */ + int Underline() const; + + + /** + * Queries for errors. + * + * @return The current error code. + */ + FT_Error Error() const { return err; } + + int GetSizeInPoints() const { return this->size; }; + + private: + /** + * The current Freetype face that this FTSize object relates to. + */ + FT_Face* ftFace; + + /** + * The Freetype size. + */ + FT_Size ftSize; + + /** + * The size in points. + */ + unsigned int size; + + /** + * Current error code. Zero means no error. + */ + FT_Error err; + +}; + +#endif // __FTSize__ + diff --git a/Utilities/ftgl/src/FTTextureGlyph.cpp b/Utilities/ftgl/src/FTTextureGlyph.cpp new file mode 100644 index 0000000..e0d7f28 --- /dev/null +++ b/Utilities/ftgl/src/FTTextureGlyph.cpp @@ -0,0 +1,111 @@ +#include "FTTextureGlyph.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +FTTextureGlyph::FTTextureGlyph( FT_Glyph glyph, int id, int xOffset, int yOffset, GLsizei width, GLsizei height) +: FTGlyph(), + data(0), + destWidth(0), + destHeight(0), + numGreys(0), + glTextureID(id), + activeTextureID(0) +{ + // FIXME This function will always fail if the glyph's format isn't scalable???? + err = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1); + if( err || glyph->format != ft_glyph_format_bitmap) + { + return; + } + + FT_BitmapGlyph bitmap = ( FT_BitmapGlyph)glyph; + FT_Bitmap* source = &bitmap->bitmap; + + // FIXME check the pixel mode + //ft_pixel_mode_grays + + int srcPitch = source->pitch; + destWidth = source->width; + destHeight = source->rows; + + // Not sure what the standard behavior should be here? + if( destWidth && destHeight) + { + data = new unsigned char[destWidth * destHeight]; + + for(int y = 0; y < destHeight; ++y) + { + for(int x = 0; x < destWidth; ++x) + { + *( data + ( y * destWidth + x)) = *( source->buffer + ( y * srcPitch) + x); + } + } + + glBindTexture( GL_TEXTURE_2D, glTextureID); + glTexSubImage2D( GL_TEXTURE_2D, 0, xOffset, yOffset, destWidth, destHeight, GL_ALPHA, GL_UNSIGNED_BYTE, data); + } + + +// 0 +// +----+ +// | | +// | | +// | | +// +----+ +// 1 + + // Texture co-ords + uv[0].x = static_cast(xOffset) / static_cast(width); + uv[0].y = static_cast(yOffset) / static_cast(height); + uv[1].x = static_cast( xOffset + destWidth) / static_cast(width); + uv[1].y = static_cast( yOffset + destHeight) / static_cast(height); + + numGreys = source->num_grays; + advance = (float)(glyph->advance.x >> 16); + bBox = FTBBox( glyph); + + pos.x = bitmap->left; + pos.y = bitmap->top; + + if( data) + delete [] data; + +// discard glyph image (bitmap or not) + // Is this the right place to do this? + FT_Done_Glyph( glyph); +} + + +FTTextureGlyph::~FTTextureGlyph() +{} + + +float FTTextureGlyph::Render( const FT_Vector& pen, + const FTGLRenderContext *context) +{ + glGetIntegerv( GL_TEXTURE_2D_BINDING_EXT, &activeTextureID); + if( activeTextureID != glTextureID) + { + glBindTexture( GL_TEXTURE_2D, (GLuint)glTextureID); + } + + glBegin( GL_QUADS); + glTexCoord2f( uv[0].x, uv[0].y); + glVertex2f( (float)(pen.x + pos.x), (float)(pen.y + pos.y)); + + glTexCoord2f( uv[0].x, uv[1].y); + glVertex2f( (float)(pen.x + pos.x), (float)(pen.y + pos.y - destHeight)); + + glTexCoord2f( uv[1].x, uv[1].y); + glVertex2f((float)(pen.x + destWidth + pos.x), (float)(pen.y + pos.y - destHeight)); + + glTexCoord2f( uv[1].x, uv[0].y); + glVertex2f((float)(pen.x + destWidth + pos.x), (float)(pen.y + pos.y)); + glEnd(); + + return advance; + +} + diff --git a/Utilities/ftgl/src/FTTextureGlyph.h b/Utilities/ftgl/src/FTTextureGlyph.h new file mode 100644 index 0000000..1fee832 --- /dev/null +++ b/Utilities/ftgl/src/FTTextureGlyph.h @@ -0,0 +1,105 @@ +#ifndef __FTTextureGlyph__ +#define __FTTextureGlyph__ + + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGLgl.h" +#include "FTGlyph.h" + + +/** + * FTTextureGlyph is a specialisation of FTGlyph for creating texture + * glyphs. + * + * @see FTGlyphContainer + * + */ +class FTGL_EXPORT FTTextureGlyph : public FTGlyph +{ + public: + /** + * Constructor + * + * @param glyph The Freetype glyph to be processed + * @param id The id the texture that this glyph will be + * drawn in + * @param xOffset The x offset into the parent texture to draw + * this glyph + * @param yOffset The y offset into the parent texture to draw + * this glyph + * @param width The width of the parent texture + * @param height The height (number of rows) of the parent texture + */ + FTTextureGlyph( FT_Glyph glyph, int id, int xOffset, int yOffset, GLsizei width, GLsizei height); + + /** + * Destructor + */ + virtual ~FTTextureGlyph(); + + /** + * Renders this glyph at the current pen position. + * + * @param pen The current pen position. + * @return The advance distance for this glyph. + */ + virtual float Render( const FT_Vector& pen, + const FTGLRenderContext *context = 0); + + private: + /** + * Pointer to the 'image' data + */ + unsigned char* data; + + /** + * The width of the glyph 'image' + */ + int destWidth; + + /** + * The height of the glyph 'image' + */ + int destHeight; + + /** + * The number of greys or bit depth of the image + */ + int numGreys; + + /** + * A structure to hold the uv co-ords. + */ + struct FTPoint + { + float x; + float y; + }; + + /** + * The texture co-ords of this glyph within the texture. + */ + FTPoint uv[2]; + + /** + * The texture index that this glyph is contained in. + */ + int glTextureID; + + /** + * The texture index of the currently active texture + * + * We call glGetIntegerv( GL_TEXTURE_2D_BINDING, activeTextureID); + * to get the currently active texture to try to reduce the number + * of texture bind operations + */ + GLint activeTextureID; + +}; + + +#endif // __FTTextureGlyph__ diff --git a/Utilities/ftgl/src/FTVectoriser.cpp b/Utilities/ftgl/src/FTVectoriser.cpp new file mode 100644 index 0000000..6343334 --- /dev/null +++ b/Utilities/ftgl/src/FTVectoriser.cpp @@ -0,0 +1,421 @@ +#include "FTVectoriser.h" +#include "FTGL.h" +#ifdef FTGL_DEBUG + #include "mmgr.h" +#endif + + +#ifndef CALLBACK +#define CALLBACK +#endif + +extern "C" { + +typedef void (CALLBACK*ftglCallback)(); + +void CALLBACK ftglError( GLenum errCode, FTMesh* mesh) +{ + mesh->Error( errCode); +} + +void CALLBACK ftglVertex( void* data, FTMesh* mesh) +{ + FTGL_DOUBLE* vertex = (FTGL_DOUBLE*)data; + mesh->AddPoint( vertex[0], vertex[1], vertex[2]); +} + + +void CALLBACK ftglBegin( GLenum type, FTMesh* mesh) +{ + mesh->Begin( type); +} + + +void CALLBACK ftglEnd( FTMesh* mesh) +{ + mesh->End(); +} + + +void CALLBACK ftglCombine( FTGL_DOUBLE coords[3], void* , GLfloat*, void** outData, FTMesh* mesh) +{ + FTGL_DOUBLE* vertex = (FTGL_DOUBLE*)coords; + mesh->tempPool.push_back( ftPoint( vertex[0], vertex[1], vertex[2])); + + *outData = &mesh->tempPool[ mesh->tempPool.size() - 1].x; +} + +} // End of extern C + +//============================================================================= + +bool operator == ( const ftPoint &a, const ftPoint &b) +{ + return((a.x == b.x) && (a.y == b.y) && (a.z == b.z)); +} + +bool operator != ( const ftPoint &a, const ftPoint &b) +{ + return((a.x != b.x) || (a.y != b.y) || (a.z != b.z)); +} + + +FTMesh::FTMesh() +: err(0) +{ + tess.reserve( 16); + tempPool.reserve( 128); +} + + +FTMesh::~FTMesh() +{ + for( size_t t = 0; t < tess.size(); ++t) + { + delete tess[t]; + } + tess.clear(); + + tempPool.clear(); +} + + +void FTMesh::AddPoint( const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z) +{ + tempTess->AddPoint( x, y, z); +} + +void FTMesh::Begin( GLenum m) +{ + tempTess = new FTTesselation; + tempTess->meshType = m; +} + + +void FTMesh::End() +{ + tess.push_back( tempTess); +} + + +FTGL_DOUBLE* FTMesh::Point() +{ + return &tempTess->pointList[ tempTess->size() - 1].x; + +} + + +int FTMesh::size() const +{ + int s = 0; + for( size_t t = 0; t < tess.size(); ++t) + { + s += tess[t]->size(); + ++s; + } + return s; +} + + +//============================================================================= + + +FTVectoriser::FTVectoriser( const FT_Glyph glyph) +: contour(0), + mesh(0), + contourFlag(0), + kBSTEPSIZE( 0.2f) +{ + FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph; + ftOutline = outline->outline; + + contourList.reserve( ftOutline.n_contours); +} + + +FTVectoriser::~FTVectoriser() +{ + for( size_t c = 0; c < contours(); ++c) + { + delete contourList[c]; + } + + contourList.clear(); + + if( mesh) + delete mesh; +} + + +int FTVectoriser::points() +{ + int s = 0; + for( size_t c = 0; c < contours(); ++c) + { + s += contourList[c]->size(); + } + + return s; +} + + +bool FTVectoriser::Process() +{ + short first = 0; + short last; + const short cont = ftOutline.n_contours; + + for( short c = 0; c < cont; ++c) + { + contour = new FTContour; + contourFlag = ftOutline.flags; + last = ftOutline.contours[c]; + + for( int p = first; p <= last; ++p) + { + switch( ftOutline.tags[p]) + { + case FT_Curve_Tag_Conic: + p += Conic( p, first, last); + break; + case FT_Curve_Tag_Cubic: + p += Cubic( p, first, last); + break; + case FT_Curve_Tag_On: + default: + contour->AddPoint( ftOutline.points[p].x, ftOutline.points[p].y); + } + } + + contourList.push_back( contour); + first = (short)(last + 1); + } + + return true; +} + + +int FTVectoriser::Conic( const int index, const int first, const int last) +{ + int next = index + 1; + int prev = index - 1; + + if( index == last) + next = first; + + if( index == first) + prev = last; + + if( ftOutline.tags[next] != FT_Curve_Tag_Conic) + { + ctrlPtArray[0][0] = (float)ftOutline.points[prev].x; + ctrlPtArray[0][1] = (float)ftOutline.points[prev].y; + ctrlPtArray[1][0] = (float)ftOutline.points[index].x; + ctrlPtArray[1][1] = (float)ftOutline.points[index].y; + ctrlPtArray[2][0] = (float)ftOutline.points[next].x; + ctrlPtArray[2][1] = (float)ftOutline.points[next].y; + + evaluateCurve( 2); + return 1; + } + else + { + int next2 = next + 1; + if( next == last) + next2 = first; + + //create a phantom point + float x = (float)(ftOutline.points[index].x + ftOutline.points[next].x)/ 2; + float y = (float)(ftOutline.points[index].y + ftOutline.points[next].y)/ 2; + + // process first curve + ctrlPtArray[0][0] = (float)ftOutline.points[prev].x; + ctrlPtArray[0][1] = (float)ftOutline.points[prev].y; + ctrlPtArray[1][0] = (float)ftOutline.points[index].x; + ctrlPtArray[1][1] = (float)ftOutline.points[index].y; + ctrlPtArray[2][0] = (float)x; + ctrlPtArray[2][1] = (float)y; + + evaluateCurve( 2); + + // process second curve + ctrlPtArray[0][0] = (float)x; + ctrlPtArray[0][1] = (float)y; + ctrlPtArray[1][0] = (float)ftOutline.points[next].x; + ctrlPtArray[1][1] = (float)ftOutline.points[next].y; + ctrlPtArray[2][0] = (float)ftOutline.points[next2].x; + ctrlPtArray[2][1] = (float)ftOutline.points[next2].y; + evaluateCurve( 2); + + return 2; + } +} + + +int FTVectoriser::Cubic( const int index, const int first, const int last) +{ + int next = index + 1; + int prev = index - 1; + + if( index == last) + next = first; + + int next2 = next + 1; + + if( next == last) + next2 = first; + + if( index == first) + prev = last; + + ctrlPtArray[0][0] = (float)ftOutline.points[prev].x; + ctrlPtArray[0][1] = (float)ftOutline.points[prev].y; + ctrlPtArray[1][0] = (float)ftOutline.points[index].x; + ctrlPtArray[1][1] = (float)ftOutline.points[index].y; + ctrlPtArray[2][0] = (float)ftOutline.points[next].x; + ctrlPtArray[2][1] = (float)ftOutline.points[next].y; + ctrlPtArray[3][0] = (float)ftOutline.points[next2].x; + ctrlPtArray[3][1] = (float)ftOutline.points[next2].y; + + evaluateCurve( 3); + return 2; +} + + +// De Casteljau algorithm contributed by Jed Soane +void FTVectoriser::deCasteljau( const float t, const int n) +{ + //Calculating successive b(i)'s using de Casteljau algorithm. + for( int i = 1; i <= n; i++) + for( int k = 0; k <= (n - i); k++) + { + bValues[i][k][0] = (1 - t) * bValues[i - 1][k][0] + t * bValues[i - 1][k + 1][0]; + bValues[i][k][1] = (1 - t) * bValues[i - 1][k][1] + t * bValues[i - 1][k + 1][1]; + } + + //Specify next vertex to be included on curve + contour->AddPoint( bValues[n][0][0], bValues[n][0][1]); +} + + +// De Casteljau algorithm contributed by Jed Soane +void FTVectoriser::evaluateCurve( const int n) +{ + // setting the b(0) equal to the control points + for( int i = 0; i <= n; i++) + { + bValues[0][i][0] = ctrlPtArray[i][0]; + bValues[0][i][1] = ctrlPtArray[i][1]; + } + + float t; //parameter for curve point calc. [0.0, 1.0] + + for( int m = 0; m <= ( 1 / kBSTEPSIZE); m++) + { + t = m * kBSTEPSIZE; + deCasteljau( t, n); //calls to evaluate point on curve att. + } +} + + +void FTVectoriser::GetOutline( FTGL_DOUBLE* data) +{ + int i = 0; + + for( size_t c= 0; c < contours(); ++c) + { + const FTContour* acontour = contourList[c]; + + for( size_t p = 0; p < acontour->size(); ++p) + { + data[i] = static_cast(acontour->pointList[p].x / 64.0f); // is 64 correct? + data[i + 1] = static_cast(acontour->pointList[p].y / 64.0f); + data[i + 2] = 0.0; // static_cast(acontour->pointList[p].z / 64.0f); + i += 3; + } + } +} + + +void FTVectoriser::MakeMesh( FTGL_DOUBLE zNormal) +{ + if( mesh) + { + delete mesh; + } + + mesh = new FTMesh; + + GLUtesselator* tobj = gluNewTess(); + + gluTessCallback( tobj, GLU_TESS_BEGIN_DATA, (ftglCallback)ftglBegin); + gluTessCallback( tobj, GLU_TESS_VERTEX_DATA, (ftglCallback)ftglVertex); + gluTessCallback( tobj, GLU_TESS_COMBINE_DATA, (ftglCallback)ftglCombine); + gluTessCallback( tobj, GLU_TESS_END_DATA, (ftglCallback)ftglEnd); + gluTessCallback( tobj, GLU_TESS_ERROR_DATA, (ftglCallback)ftglError); + + + if( contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill + { + gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); + } + else + { + gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); + } + + + gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0); + gluTessNormal( tobj, 0.0, 0.0, zNormal); + gluTessBeginPolygon( tobj, mesh); + + for( size_t c = 0; c < contours(); ++c) + { + const FTContour* acontour = contourList[c]; + gluTessBeginContour( tobj); + + for( size_t p = 0; p < acontour->size(); ++p) + { + FTGL_DOUBLE* d = const_cast(&acontour->pointList[p].x); + gluTessVertex( tobj, d, d); + } + gluTessEndContour( tobj); + } + + gluTessEndPolygon( tobj); + + gluDeleteTess( tobj); + +} + + +void FTVectoriser::GetMesh( FTGL_DOUBLE* data) +{ + // Now write it out + int i = 0; + + // fill out the header + size_t msize = mesh->tess.size(); + data[0] = msize; + + for( int p = 0; p < data[0]; ++p) + { + FTTesselation* tess = mesh->tess[p]; + size_t tSize = tess->pointList.size(); + int tType = tess->meshType; + + data[i+1] = tType; + data[i+2] = tSize; + i += 3; + for( size_t q = 0; q < ( tess->pointList.size()); ++q) + { + data[i] = tess->pointList[q].x / 64.0f; // is 64 correct? + data[i + 1] = tess->pointList[q].y / 64.0f; + data[i + 2] = 0.0; // static_cast(mesh->pointList[p].z / 64.0f); + i += 3; + + } + + } + +} diff --git a/Utilities/ftgl/src/FTVectoriser.h b/Utilities/ftgl/src/FTVectoriser.h new file mode 100644 index 0000000..442fb6a --- /dev/null +++ b/Utilities/ftgl/src/FTVectoriser.h @@ -0,0 +1,427 @@ +#ifndef __FTVectoriser__ +#define __FTVectoriser__ + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "FTGL.h" +#include "FTGLgl.h" +#include "FTGlyph.h" + +#ifndef CALLBACK +#define CALLBACK +#endif + +/** + * ftPoint class is a basic 3 dimensional point for holding outline font + * point data. + * + * @see FTOutlineGlyph + * @see FTPolyGlyph + * + */ +class FTGL_EXPORT ftPoint +{ + public: + /** + * Default constructor. Point is set to zero. + */ + ftPoint() + : x(0), y(0), z(0) + {} + + /** + * Constructor. + * + * @param X + * @param Y + * @param Z + */ + ftPoint( const FTGL_DOUBLE X, const FTGL_DOUBLE Y, const FTGL_DOUBLE Z) + : x(X), y(Y), z(Z) + {} + + /** + * Operator == Tests for eqaulity + * + * @param a + * @param b + * @return + */ + friend bool operator == ( const ftPoint &a, const ftPoint &b); + + /** + * Operator != Tests for non equality + * + * @param a + * @param b + * @return + */ + friend bool operator != ( const ftPoint &a, const ftPoint &b); + + /** + * The point data + */ + FTGL_DOUBLE x, y, z; // FIXME make private + + private: +}; + +#ifdef FTGL_DO_NOT_USE_STL +#include +#else +#include +#ifdef USE_STD_NAMESPACE +using namespace std; +#endif +#endif + +/** + * FTContour class is a container of points that describe an outline + * point data. + * + * @see FTOutlineGlyph + * @see FTPolyGlyph + * @see ftPoint + * + */ +class FTGL_EXPORT FTContour +{ + public: + /** + * Default constructor + */ + FTContour() + : kMAXPOINTS( 1000) + { + pointList.reserve( kMAXPOINTS); + } + + /** + * Destructor + */ + ~FTContour() + { + pointList.clear(); + } + + /** + * Assignment + */ + FTContour& operator =(const FTContour& v) + { + this->pointList = v.pointList; + return *this; + } + + /** + * Add a point to the end of this contour. + * + * Doesn't add the point if it's already on the end or the start + * of the contour. The Z component is always 0 + * + * @param x The X component of the point + * @param y The Y component of the point + */ + void AddPoint( const FTGL_DOUBLE x, const FTGL_DOUBLE y) + { + ftPoint point( x, y, 0.0); + + // Eliminate duplicate points. + if( pointList.empty() || ( pointList[pointList.size() - 1] != point && pointList[0] != point)) + { + pointList.push_back( point); + } + } + + /** + * How many points define this contour + * + * @return the number of points in this contour + */ + size_t size() const { return pointList.size();} + + /** + * The list of points in this contour + */ +#ifdef FTGL_DO_NOT_USE_STL + typedef FTPointVector PointVector; +#else + typedef vector< ftPoint> PointVector; +#endif + PointVector pointList; + + private: + /** + * A 'max' number of points that this contour holds. Note however it + * can hold more than this number. It is just used to reserve space + * in the + */ + const unsigned int kMAXPOINTS; +}; + + +class FTGL_EXPORT FTTesselation +{ + public: + FTTesselation() + { + pointList.reserve( 128); + } + + ~FTTesselation() + { + pointList.clear(); + } + + + void AddPoint( const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z) + { + pointList.push_back( ftPoint( x, y, z)); + } + + + size_t size() const { return pointList.size();} + + GLenum meshType; +#ifdef FTGL_DO_NOT_USE_STL + typedef FTPointVector PointVector; +#else + typedef vector< ftPoint> PointVector; +#endif + PointVector pointList; + private: + +}; + +#ifdef FTGL_DO_NOT_USE_STL +#include +#include +#else +#include +#ifdef USE_STD_NAMESPACE +using namespace std; +#endif +#endif + + +class FTGL_EXPORT FTMesh +{ + public: + FTMesh(); + ~FTMesh(); + + void AddPoint( const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z); + void Begin( GLenum m); + void End(); + + FTGL_DOUBLE* Point(); + int size() const; + + void Error( GLenum e) { err = e;} + GLenum Error() const { return err;} + +#ifdef FTGL_DO_NOT_USE_STL + typedef FTPointVector PointVector; +#else + typedef vector< ftPoint> PointVector; +#endif + PointVector tempPool; + +#ifdef FTGL_DO_NOT_USE_STL + typedef FTTesselationVector TesselationVector; +#else + typedef vector< FTTesselation*> TesselationVector; +#endif + TesselationVector tess; + protected: + + private: + /** + * The list of points in this mesh + */ + FTTesselation* tempTess; + GLenum err; + +}; + + +/** + * FTVectoriser class is a helper class that converts font outlines into + * point data. It includes a bezier curve evaluator + * + * @see FTOutlineGlyph + * @see FTPolyGlyph + * @see FTContour + * @see ftPoint + * + */ +class FTGL_EXPORT FTVectoriser +{ + public: + /** + * Constructor + * + * @param glyph The freetype glyph to be processed + */ + FTVectoriser( const FT_Glyph glyph); + + /** + * Destructor + */ + virtual ~FTVectoriser(); + + /** + * Assignment (just to remove warnings, ideally it should never use it) + */ + FTVectoriser& operator =(const FTVectoriser&) + { + return *this; + } + + /** + * Process the freetype outline data into contours of points + * + * @return true on success + */ + bool Process(); + + /** + * Copy the outline data into a block of FTGL_DOUBLEs + * + * @param d a pointer to the memory to copy the data into. + */ + void GetOutline( FTGL_DOUBLE* d); + + /** + * Build a mesh from the outline and copy the vertex data into a + * block of FTGL_DOUBLEs + * + * @param zNormal The direction of the z axis of the normal + * for this mesh + */ + void MakeMesh( FTGL_DOUBLE zNormal = 1.0); + + /** + * Copy the tesselation data into a block of FTGL_DOUBLEs + * + * @param d a pointer to the memory to copy the data into. + */ + void GetMesh( FTGL_DOUBLE* d); + + /** Get the number of points in the tesselation + * + * @return the number of points. + */ + size_t MeshPoints() const { return mesh->size();} + + /** + * Get the total count of points in this outline + * + * @return the number of points + */ + int points(); + + /** + * Get the count of contours in this outline + * + * @return the number of contours + */ + size_t contours() const { return contourList.size();} + + /** + * Get the nuber of points in a contour in this outline + * + * @param c The contour index + * @return the number of points in contour[c] + */ + size_t contourSize( int c) const { return contourList[c]->size();} + + /** + * Get the flag for the tesselation rule for this outline + * + * @return The contour flag + */ + int ContourFlag() const { return contourFlag;} + + private: + /** + * Process a conic ( second order bezier curve) + * + * @param index The index of the current point in the point list. + * @param first The index into the pointlist of the first point in + * the contour that the current point is part of. + * @param last The index into the pointlist of the last point in + * the contour that the current point is part of. + * @return the number of control points processed + */ + int Conic( const int index, const int first, const int last); + + /** + * Process a cubic ( third order) bezier curve + * + * @param index The index of the current point in the point list. + * @param first The index into the pointlist of the first point in + * the contour that the current point is part of. + * @param last The index into the pointlist of the last point in + * the contour that the current point is part of. + * @return the number of control points processed + */ + int Cubic( const int index, const int first, const int last); + + /** + * @param a + * @param b + */ + void deCasteljau( const float t, const int n); + + /** + * @param a + */ + void evaluateCurve( const int n); + + /** + * The list of contours in this outline + */ +#ifdef FTGL_DO_NOT_USE_STL + typedef FTContourVector ContourVector; +#else + typedef vector< FTContour*> ContourVector; +#endif + ContourVector contourList; + + /** + * A Mesh for tesselations + */ + FTContour* contour; + + /** + * A Mesh for tesselations + */ + FTMesh* mesh; + + /** + * A flag indicating the tesselation rule for this outline + */ + int contourFlag; + + /** + * A Freetype outline + */ + FT_Outline ftOutline; + + /** + */ + // Magic numbers -- #define MAX_DEG 4 + float bValues[4][4][2]; //3D array storing values of de Casteljau algorithm. + float ctrlPtArray[4][2]; // Magic numbers + + /** + */ + const float kBSTEPSIZE; + +}; + + +#endif // __FTVectoriser__ diff --git a/Utilities/ftgl/src/NoSTL/FTCallbackVector.h b/Utilities/ftgl/src/NoSTL/FTCallbackVector.h new file mode 100644 index 0000000..bb88d7f --- /dev/null +++ b/Utilities/ftgl/src/NoSTL/FTCallbackVector.h @@ -0,0 +1,21 @@ +#ifndef __FTCallbackVector__ +#define __FTCallbackVector__ + +/* + Provides a non-STL alternative to the STL vector<...> + used inside FTLibrary. +*/ + +#ifdef FT_VECTOR_CLASS_NAME +#undef FT_VECTOR_CLASS_NAME +#endif +#define FT_VECTOR_CLASS_NAME FTCallbackVector + +#ifdef FT_VECTOR_ITEM_TYPE +#undef FT_VECTOR_ITEM_TYPE +#endif +#define FT_VECTOR_ITEM_TYPE FTCallback + +#include "FTVector.h" + +#endif // __FTCallbackVector__ diff --git a/Utilities/ftgl/src/NoSTL/FTCharToGlyphIndexMap.h b/Utilities/ftgl/src/NoSTL/FTCharToGlyphIndexMap.h new file mode 100644 index 0000000..b39c4b2 --- /dev/null +++ b/Utilities/ftgl/src/NoSTL/FTCharToGlyphIndexMap.h @@ -0,0 +1,153 @@ +#ifndef __FTCharToGlyphIndexMap__ +#define __FTCharToGlyphIndexMap__ + +/* + Provides a non-STL alternative to the STL map + which maps character codes to glyph indices inside FTCharmap. + + Implementation: + - NumberOfBuckets buckets are considered. + - Each bucket has BucketSize entries. + - When the glyph index for the character code C has to be stored, the + bucket this character belongs to is found using 'C div BucketSize'. + If this bucket has not been allocated yet, do it now. + The entry in the bucked is found using 'C mod BucketSize'. + If it is set to IndexNotFound, then the glyph entry has not been set. + - Try to mimic the calls made to the STL map API. + + Caveats: + - The glyph index is now a signed long instead of unsigned long, so + the special value IndexNotFound (= -1) can be used to specify that the + glyph index has not been stored yet. +*/ + +#include "FTGL.h" + +class FTGL_EXPORT FTCharToGlyphIndexMap +{ +public: + + typedef unsigned long CharacterCode; + typedef signed long GlyphIndex; + + enum + { + NumberOfBuckets = 256, + BucketSize = 256, + IndexNotFound = -1 + }; + + FTCharToGlyphIndexMap(); + + virtual ~FTCharToGlyphIndexMap(); + + void clear(); + + const GlyphIndex* find(CharacterCode c); + + void insert(CharacterCode c, GlyphIndex g); + +private: + + GlyphIndex** Indices; +}; + + +inline FTCharToGlyphIndexMap::FTCharToGlyphIndexMap() +{ + this->Indices = 0; +} + + +// Free all buckets + +inline void FTCharToGlyphIndexMap::clear() +{ + if (this->Indices) + { + for (int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++) + { + if (this->Indices[i]) + { + delete [] this->Indices[i]; + this->Indices[i] = 0; + } + } + } +} + +inline FTCharToGlyphIndexMap::~FTCharToGlyphIndexMap() +{ + if (this->Indices) + { + // Free all buckets + + this->clear(); + + // Free main structure + + delete [] this->Indices; + this->Indices = 0; + } +} + +// Find index corresponding to char code + +inline const FTCharToGlyphIndexMap::GlyphIndex* FTCharToGlyphIndexMap::find(FTCharToGlyphIndexMap::CharacterCode c) +{ + if (!this->Indices) + { + return 0; + } + + // Find position of char code in buckets + + div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize); + + if (!this->Indices[pos.quot]) + { + return 0; + } + + const FTCharToGlyphIndexMap::GlyphIndex *ptr = &this->Indices[pos.quot][pos.rem]; + if (*ptr == FTCharToGlyphIndexMap::IndexNotFound) + { + return 0; + } + + return ptr; +} + +// Insert index corresponding to char code + +inline void FTCharToGlyphIndexMap::insert(FTCharToGlyphIndexMap::CharacterCode c, + FTCharToGlyphIndexMap::GlyphIndex g) +{ + if (!this->Indices) + { + this->Indices = new GlyphIndex* [FTCharToGlyphIndexMap::NumberOfBuckets]; + for (int i = 0; i < FTCharToGlyphIndexMap::NumberOfBuckets; i++) + { + this->Indices[i] = 0; + } + } + + // Find position of char code in buckets + + div_t pos = div(c, FTCharToGlyphIndexMap::BucketSize); + + // Allocate bucket if does not exist yet + + if (!this->Indices[pos.quot]) + { + this->Indices[pos.quot] = new GlyphIndex [FTCharToGlyphIndexMap::BucketSize]; + for (int i = 0; i < FTCharToGlyphIndexMap::BucketSize; i++) + { + this->Indices[pos.quot][i] = FTCharToGlyphIndexMap::IndexNotFound; + } + } + + this->Indices[pos.quot][pos.rem] = g; +} + +#endif // __FTCharToGlyphIndexMap__ diff --git a/Utilities/ftgl/src/NoSTL/FTContourVector.h b/Utilities/ftgl/src/NoSTL/FTContourVector.h new file mode 100644 index 0000000..7365ae5 --- /dev/null +++ b/Utilities/ftgl/src/NoSTL/FTContourVector.h @@ -0,0 +1,21 @@ +#ifndef __FTContourVector__ +#define __FTContourVector__ + +/* + Provides a non-STL alternative to the STL vector<...> + used inside FTVectoriser. +*/ + +#ifdef FT_VECTOR_CLASS_NAME +#undef FT_VECTOR_CLASS_NAME +#endif +#define FT_VECTOR_CLASS_NAME FTContourVector + +#ifdef FT_VECTOR_ITEM_TYPE +#undef FT_VECTOR_ITEM_TYPE +#endif +#define FT_VECTOR_ITEM_TYPE FTContour* + +#include "FTVector.h" + +#endif // __FTContourVector__ diff --git a/Utilities/ftgl/src/NoSTL/FTGlyphVector.h b/Utilities/ftgl/src/NoSTL/FTGlyphVector.h new file mode 100644 index 0000000..53818a5 --- /dev/null +++ b/Utilities/ftgl/src/NoSTL/FTGlyphVector.h @@ -0,0 +1,21 @@ +#ifndef __FTGlyphVector__ +#define __FTGlyphVector__ + +/* + Provides a non-STL alternative to the STL vector<...> + used inside FTGlyphContainer. +*/ + +#ifdef FT_VECTOR_CLASS_NAME +#undef FT_VECTOR_CLASS_NAME +#endif +#define FT_VECTOR_CLASS_NAME FTGlyphVector + +#ifdef FT_VECTOR_ITEM_TYPE +#undef FT_VECTOR_ITEM_TYPE +#endif +#define FT_VECTOR_ITEM_TYPE FTGlyph* + +#include "FTVector.h" + +#endif // __FTGlyphVector__ diff --git a/Utilities/ftgl/src/NoSTL/FTPointVector.h b/Utilities/ftgl/src/NoSTL/FTPointVector.h new file mode 100644 index 0000000..e8e4244 --- /dev/null +++ b/Utilities/ftgl/src/NoSTL/FTPointVector.h @@ -0,0 +1,21 @@ +#ifndef __FTPointVector__ +#define __FTPointVector__ + +/* + Provides a non-STL alternative to the STL vector<...> + used inside FTVectoriser. +*/ + +#ifdef FT_VECTOR_CLASS_NAME +#undef FT_VECTOR_CLASS_NAME +#endif +#define FT_VECTOR_CLASS_NAME FTPointVector + +#ifdef FT_VECTOR_ITEM_TYPE +#undef FT_VECTOR_ITEM_TYPE +#endif +#define FT_VECTOR_ITEM_TYPE ftPoint + +#include "FTVector.h" + +#endif // __FTPointVector__ diff --git a/Utilities/ftgl/src/NoSTL/FTTesselationVector.h b/Utilities/ftgl/src/NoSTL/FTTesselationVector.h new file mode 100644 index 0000000..165975d --- /dev/null +++ b/Utilities/ftgl/src/NoSTL/FTTesselationVector.h @@ -0,0 +1,21 @@ +#ifndef __FTTesselationVector__ +#define __FTTesselationVector__ + +/* + Provides a non-STL alternative to the STL vector<...> + used inside FTVectoriser. +*/ + +#ifdef FT_VECTOR_CLASS_NAME +#undef FT_VECTOR_CLASS_NAME +#endif +#define FT_VECTOR_CLASS_NAME FTTesselationVector + +#ifdef FT_VECTOR_ITEM_TYPE +#undef FT_VECTOR_ITEM_TYPE +#endif +#define FT_VECTOR_ITEM_TYPE FTTesselation* + +#include "FTVector.h" + +#endif // __FTTesselationVector__ diff --git a/Utilities/ftgl/src/NoSTL/FTVector.h b/Utilities/ftgl/src/NoSTL/FTVector.h new file mode 100644 index 0000000..39e8bab --- /dev/null +++ b/Utilities/ftgl/src/NoSTL/FTVector.h @@ -0,0 +1,287 @@ +/* + Provides a non-STL alternative to the STL vector<...> + used inside FTvectorizer and FTGlyphContainer. + + Implementation: + - Dynamically resizable container. + - Try to mimic the calls made to the STL vector API. + + Caveats: + - No templates, use poor macro substition where : + FT_VECTOR_CLASS_NAME: is the name of the class + FT_VECTOR_ITEM_TYPE: is the type of the object to store +*/ + +#define FT_VECTOR_CLASS_DEBUG 0 + +#include "FTGL.h" + +class FTGL_EXPORT FT_VECTOR_CLASS_NAME +{ +public: + + typedef FT_VECTOR_ITEM_TYPE value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef size_t size_type; + + FT_VECTOR_CLASS_NAME(); + + virtual ~FT_VECTOR_CLASS_NAME(); + + FT_VECTOR_CLASS_NAME& operator =(const FT_VECTOR_CLASS_NAME& v); + + size_type size() const; + size_type capacity() const; + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + bool empty() const; + + reference operator [](size_type pos); + const_reference operator [](size_type pos) const; + + void clear(); + void reserve(size_type); + void push_back(const value_type&); + void resize(size_type, value_type); + +protected: + + void expand(size_type = 0); + +private: + + size_type Capacity; + size_type Size; + value_type* Items; +}; + + +inline +FT_VECTOR_CLASS_NAME::FT_VECTOR_CLASS_NAME() +{ + this->Capacity = this->Size = 0; + this->Items = 0; +} + + +inline +FT_VECTOR_CLASS_NAME::size_type FT_VECTOR_CLASS_NAME::size() const +{ + return this->Size; +} + + +inline +FT_VECTOR_CLASS_NAME::size_type FT_VECTOR_CLASS_NAME::capacity() const +{ + return this->Capacity; +} + + +inline +FT_VECTOR_CLASS_NAME::iterator FT_VECTOR_CLASS_NAME::begin() +{ + return this->Items; +} + + +inline +FT_VECTOR_CLASS_NAME::const_iterator FT_VECTOR_CLASS_NAME::begin() const +{ + return this->Items; +} + + +inline +FT_VECTOR_CLASS_NAME::iterator FT_VECTOR_CLASS_NAME::end() +{ + return this->begin() + this->size(); +} + + +inline +FT_VECTOR_CLASS_NAME::const_iterator FT_VECTOR_CLASS_NAME::end() const +{ + return this->begin() + this->size(); +} + + +inline +void FT_VECTOR_CLASS_NAME::clear() +{ + if (this->Capacity) + { +#if FT_VECTOR_CLASS_DEBUG + printf("FT_VECTOR_CLASS_NAME: clear() (%d / %d)\n", + this->size(), this->capacity()); +#endif + delete [] this->Items; + this->Capacity = this->Size = 0; + this->Items = 0; + } +} + + +inline +FT_VECTOR_CLASS_NAME::~FT_VECTOR_CLASS_NAME() +{ + this->clear(); +} + + +inline +void FT_VECTOR_CLASS_NAME::expand(size_type capacity_hint) +{ +#if FT_VECTOR_CLASS_DEBUG + printf("FT_VECTOR_CLASS_NAME: expand() (%d / %d) hint: %d\n", + this->size(), this->capacity(), capacity_hint); +#endif + + // Allocate new vector (capacity doubles) + + size_type new_capacity = (this->capacity() == 0) ? 256 : this->capacity()* 2; + if (capacity_hint) + { + while (new_capacity < capacity_hint) + { + new_capacity *= 2; + } + } + + value_type *new_items = new value_type[new_capacity]; + + // Copy values to new vector + + iterator ibegin = this->begin(); + iterator iend = this->end(); + value_type *ptr = new_items; + while (ibegin != iend) + { + *ptr++ = *ibegin++; + } + + // Deallocate old vector and use new vector + + if (this->Capacity) + { + delete [] this->Items; + } + this->Items = new_items; + this->Capacity = new_capacity; +} + + +inline +void FT_VECTOR_CLASS_NAME::reserve(size_type n) +{ +#if FT_VECTOR_CLASS_DEBUG + printf("FT_VECTOR_CLASS_NAME: reserve() (%d / %d) n: %d\n", + this->size(), this->capacity(), n); +#endif + if (this->capacity() < n) + { + this->expand(n); + } +} + + +inline +FT_VECTOR_CLASS_NAME& FT_VECTOR_CLASS_NAME::operator =(const FT_VECTOR_CLASS_NAME& v) +{ + // Warning: the vector is not cleared and resized to v capacity for + // efficiency reasons. + // this->clear(); + this->reserve(v.capacity()); + + iterator ptr = this->begin(); + const_iterator vbegin = v.begin(); + const_iterator vend = v.end(); + + while (vbegin != vend) + { + *ptr++ = *vbegin++; + } + this->Size = v.size(); + return *this; +} + + +inline +bool FT_VECTOR_CLASS_NAME::empty() const +{ + return this->size() == 0; +} + + +inline +FT_VECTOR_CLASS_NAME::reference FT_VECTOR_CLASS_NAME::operator [](FT_VECTOR_CLASS_NAME::size_type pos) +{ +#if FT_VECTOR_CLASS_DEBUG + printf("FT_VECTOR_CLASS_NAME: []() (%d / %d) pos: %d\n", + this->size(), this->capacity(), pos); +#endif + return (*(begin() + pos)); +} + + +inline +FT_VECTOR_CLASS_NAME::const_reference FT_VECTOR_CLASS_NAME::operator [](FT_VECTOR_CLASS_NAME::size_type pos) const +{ +#if FT_VECTOR_CLASS_DEBUG + printf("FT_VECTOR_CLASS_NAME: []() (%d / %d) pos: %d\n", + this->size(), this->capacity(), pos); +#endif + return (*(begin() + pos)); +} + + +inline +void FT_VECTOR_CLASS_NAME::push_back(const value_type& x) +{ +#if FT_VECTOR_CLASS_DEBUG + printf("FT_VECTOR_CLASS_NAME: push_back() (%d / %d)\n", + this->size(), this->capacity()); +#endif + if (this->size() == this->capacity()) + { + this->expand(); + } + (*this)[this->size()] = x; + this->Size++; +} + + +inline +void FT_VECTOR_CLASS_NAME::resize(size_type n, value_type x) +{ +#if FT_VECTOR_CLASS_DEBUG + printf("FT_VECTOR_CLASS_NAME: resize() (%d / %d) n: %d\n", + this->size(), this->capacity(), n); +#endif + if (n == this->size()) + { + return; + } + this->reserve(n); + iterator ibegin, iend; + if (n >= this->Size) + { + ibegin = this->end(); + iend = this->begin() + n; + } + else + { + ibegin = this->begin() + n; + iend = this->end(); + } + while (ibegin != iend) + { + *ibegin++ = x; + } + this->Size = n; +} diff --git a/Utilities/ftgl/vtkftglConfig.h.in b/Utilities/ftgl/vtkftglConfig.h.in new file mode 100644 index 0000000..c79fe4a --- /dev/null +++ b/Utilities/ftgl/vtkftglConfig.h.in @@ -0,0 +1,66 @@ +#ifndef _ftglConfig_h +#define _ftglConfig_h + +/* + Do not use the STL (portability issue) +*/ +#cmakedefine VTKFTGL_DO_NOT_USE_STL +#if defined(VTKFTGL_DO_NOT_USE_STL) && !defined(FTGL_DO_NOT_USE_STL) +#define FTGL_DO_NOT_USE_STL +#endif + +/* + Support Mangle Mesa +*/ +#cmakedefine FTGL_SUPPORT_MANGLE_MESA + +/* + Do not use texture fonts (crash on Type1 fonts) +*/ +#cmakedefine VTKFTGL_DO_NOT_USE_TEXTURE_FONT +#if defined(VTKFTGL_DO_NOT_USE_TEXTURE_FONT) && !defined(FTGL_DO_NOT_USE_TEXTURE_FONT) +#define FTGL_DO_NOT_USE_TEXTURE_FONT +#endif + +/* + Do not use vector fonts +*/ +#cmakedefine VTKFTGL_DO_NOT_USE_VECTORISER +#if defined(VTKFTGL_DO_NOT_USE_VECTORISER) && !defined(FTGL_DO_NOT_USE_VECTORISER) +#define FTGL_DO_NOT_USE_VECTORISER +#endif + +/* + Static or shared lib flags +*/ +#cmakedefine VTKFTGL_DLL +#if defined(VTKFTGL_DLL) && !defined(FTGL_LIBRARY) +#define FTGL_LIBRARY +#endif +#cmakedefine VTKFTGL_STATIC +#if defined(VTKFTGL_STATIC) && !defined(FTGL_LIBRARY_STATIC) +#define FTGL_LIBRARY_STATIC +#endif + +/* + Win32 flags +*/ +#cmakedefine VTKFTGL_WIN32_FLAGS +#if defined(VTKFTGL_WIN32_FLAGS) +#if !defined(USE_STD_NAMESPACE) +#define USE_STD_NAMESPACE +#endif +#if !defined(WIN32) +#define WIN32 +#endif +#endif + +/* + HPUX workaround +*/ +#cmakedefine VTKFTGL_HPUX_SOURCE +#if defined(VTKFTGL_HPUX_SOURCE) && !defined(_HPUX_SOURCE) +#define _HPUX_SOURCE +#endif + +#endif diff --git a/Utilities/gl2ps/.NoDartCoverage b/Utilities/gl2ps/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/gl2ps/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/gl2ps/COPYING.GL2PS b/Utilities/gl2ps/COPYING.GL2PS new file mode 100644 index 0000000..363ef7d --- /dev/null +++ b/Utilities/gl2ps/COPYING.GL2PS @@ -0,0 +1,25 @@ + + GL2PS LICENSE + Version 2, November 2003 + + Copyright (C) 2003, Christophe Geuzaine + +Permission to use, copy, and distribute this software and its +documentation for any purpose with or without fee is hereby granted, +provided that the copyright notice appear in all copies and that both +that copyright notice and this permission notice appear in supporting +documentation. + +Permission to modify and distribute modified versions of this software +is granted, provided that: + +1) the modifications are licensed under the same terms as this +software; + +2) you make available the source code of any modifications that you +distribute, either on the same media as you distribute any executable +or other form of this software, or via a mechanism generally accepted +in the software development community for the electronic transfer of +data. + +This software is provided "as is" without express or implied warranty. diff --git a/Utilities/gl2ps/COPYING.LGPL b/Utilities/gl2ps/COPYING.LGPL new file mode 100644 index 0000000..1796e28 --- /dev/null +++ b/Utilities/gl2ps/COPYING.LGPL @@ -0,0 +1,482 @@ + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Utilities/gl2ps/README.VTK.txt b/Utilities/gl2ps/README.VTK.txt new file mode 100644 index 0000000..9095b29 --- /dev/null +++ b/Utilities/gl2ps/README.VTK.txt @@ -0,0 +1,23 @@ +This directory contains the sources for the GL2PS library. The +complete GL2PS library with documentation is available from here: + + http://www.geuz.org/gl2ps/ + +We thank Christophe Geuzaine for +distributing this library under a license compatible with VTK. + +Please read the COPYING.GL2PS license before you make any +modifications to this copy of the GL2PS sources. + + +Notes on how GL2PS is built in VTK +---------------------------------- + +CMakeLists.txt is conspicuous by its absence in this directory. +Currently, the GL2PS sources are in two files, one header and the +other the library. The GL2PS code is only used in Rendering so we +simply compile gl2ps.c in the Rendering directory and build the +Rendering library along with the resulting gl2ps object file. Since +VTK ships with its own ZLIB library, GL2PS compressed output is +enabled and GL2PS_HAVE_ZLIB is defined inside +Rendering/CMakeLists.txt. diff --git a/Utilities/gl2ps/gl2ps.c b/Utilities/gl2ps/gl2ps.c new file mode 100644 index 0000000..119e4f7 --- /dev/null +++ b/Utilities/gl2ps/gl2ps.c @@ -0,0 +1,3509 @@ +/* $Id: gl2ps.c,v 1.2 2003/11/15 19:02:53 prabhu Exp $ */ +/* + * GL2PS, an OpenGL to PostScript Printing Library + * Copyright (C) 1999-2003 Christophe Geuzaine + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of either: + * + * a) 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; or + * + * b) the GL2PS License as published by Christophe Geuzaine, either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either + * the GNU Library General Public License or the GL2PS License for + * more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library in the file named "COPYING.LGPL"; + * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + * + * You should have received a copy of the GL2PS License with this + * library in the file named "COPYING.GL2PS"; if not, I will be glad + * to provide one. + * + * Contributors: + * Michael Sweet + * Marc Ume + * Jean-Francois Remacle + * Bart Kaptein + * Quy Nguyen-Dai + * Sam Buss + * Shane Hill + * Romain Boman + * Rouben Rostamian + * Diego Santa Cruz + * Shahzad Muzaffar + * Lassi Tuura + * Guy Barrand + * Prabhu Ramachandran + * Micha Bieber + * + * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/. + * Please report all bugs and problems to . + */ + +#include +#include +#include +#include +#include +#include "gl2ps.h" + +/* The gl2ps context. gl2ps is not thread safe (we should create a + local GL2PScontext during gl2psBeginPage) */ + +GL2PScontext *gl2ps = NULL; + +/********************************************************************* + * + * Utility routines + * + *********************************************************************/ + +void gl2psMsg(GLint level, char *fmt, ...){ + va_list args; + + if(!(gl2ps->options & GL2PS_SILENT)){ + switch(level){ + case GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break; + case GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break; + case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break; + } + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + } + /* if(level == GL2PS_ERROR) exit(1); */ +} + +void *gl2psMalloc(size_t size){ + void *ptr; + + if(!size) return(NULL); + ptr = malloc(size); + if(!ptr){ + gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory"); + exit(1); + } + return(ptr); +} + +void *gl2psRealloc(void *ptr, size_t size){ + if(!size) return(NULL); + ptr = realloc(ptr, size); + if(!ptr){ + gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory"); + exit(1); + } + return(ptr); +} + +void gl2psFree(void *ptr){ + if(!ptr) return; + free(ptr); +} + +/* zlib compression helper routines */ + +#ifdef GL2PS_HAVE_ZLIB + +void gl2psSetupCompress(){ + gl2ps->compress = (GL2PScompress*)gl2psMalloc(sizeof(GL2PScompress)); + gl2ps->compress->src = NULL; + gl2ps->compress->start = NULL; + gl2ps->compress->dest = NULL; + gl2ps->compress->srcLen = 0; + gl2ps->compress->destLen = 0; +} + +void gl2psFreeCompress(){ + if(!gl2ps->compress) + return; + gl2psFree(gl2ps->compress->start); + gl2psFree(gl2ps->compress->dest); + gl2ps->compress->src = NULL; + gl2ps->compress->start = NULL; + gl2ps->compress->dest = NULL; + gl2ps->compress->srcLen = 0; + gl2ps->compress->destLen = 0; +} + +int gl2psAllocCompress(unsigned int srcsize){ + gl2psFreeCompress(); + + if(!gl2ps->compress || !srcsize) + return GL2PS_ERROR; + + gl2ps->compress->srcLen = srcsize; + gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12); + gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen); + gl2ps->compress->start = gl2ps->compress->src; + gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen); + + return GL2PS_SUCCESS; +} + +void* gl2psReallocCompress(unsigned int srcsize){ + if(!gl2ps->compress || !srcsize) + return NULL; + + if(srcsize < gl2ps->compress->srcLen) + return gl2ps->compress->start; + + gl2ps->compress->srcLen = srcsize; + gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12); + gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src, gl2ps->compress->srcLen); + gl2ps->compress->start = gl2ps->compress->src; + gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest, gl2ps->compress->destLen); + + return gl2ps->compress->start; +} + +size_t gl2psWriteBigEndianCompress(unsigned long data, size_t bytes){ + size_t i; + size_t size = sizeof(unsigned long); + for(i = 1; i <= bytes; ++i){ + *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8)); + ++gl2ps->compress->src; + } + return bytes; +} + +int gl2psDeflate(){ + /* For compatibility with older zlib versions, we use compress(...) + instead of compress2(..., Z_BEST_COMPRESSION) */ + return compress(gl2ps->compress->dest, &gl2ps->compress->destLen, + gl2ps->compress->start, gl2ps->compress->srcLen); +} + +#endif + +int gl2psPrintf(const char* fmt, ...){ + int ret = 0; + va_list args; + +#ifdef GL2PS_HAVE_ZLIB + unsigned int bufsize = 0; + unsigned int oldsize = 0; + static char buf[1000]; + if(gl2ps->options & GL2PS_COMPRESS){ + va_start(args, fmt); + bufsize = vsprintf(buf, fmt, args); + va_end(args); + oldsize = gl2ps->compress->srcLen; + gl2ps->compress->start = (Bytef*)gl2psReallocCompress(oldsize + bufsize); + memcpy(gl2ps->compress->start+oldsize, buf, bufsize); + } + else{ +#endif + va_start(args, fmt); + ret = vfprintf(gl2ps->stream, fmt, args); + va_end(args); +#ifdef GL2PS_HAVE_ZLIB + } +#endif + return ret; +} + +size_t gl2psWriteBigEndian(unsigned long data, size_t bytes){ + size_t i; + size_t size = sizeof(unsigned long); + for(i = 1; i <= bytes; ++i){ + fputc(0xff & (data >> (size-i) * 8), gl2ps->stream); + } + return bytes; +} + +/* The list handling routines */ + +void gl2psListRealloc(GL2PSlist *list, GLint n){ + if(n <= 0) return; + if(!list->array){ + list->nmax = ((n - 1) / list->incr + 1) * list->incr; + list->array = (char *)gl2psMalloc(list->nmax * list->size); + } + else{ + if(n > list->nmax){ + list->nmax = ((n - 1) / list->incr + 1) * list->incr; + list->array = (char *)gl2psRealloc(list->array, + list->nmax * list->size); + } + } +} + +GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size){ + GL2PSlist *list; + + if(n < 0) n = 0; + if(incr <= 0) incr = 1; + list = (GL2PSlist *)gl2psMalloc(sizeof(GL2PSlist)); + list->nmax = 0; + list->incr = incr; + list->size = size; + list->n = 0; + list->array = NULL; + gl2psListRealloc(list, n); + return(list); +} + +void gl2psListReset(GL2PSlist *list){ + list->n = 0; +} + +void gl2psListDelete(GL2PSlist *list){ + gl2psFree(list->array); + gl2psFree(list); +} + +void gl2psListAdd(GL2PSlist *list, void *data){ + list->n++; + gl2psListRealloc(list, list->n); + memcpy(&list->array[(list->n - 1) * list->size], data, list->size); +} + +int gl2psListNbr(GL2PSlist *list){ + return(list->n); +} + +void *gl2psListPointer(GL2PSlist *list, GLint index){ + if((index < 0) || (index >= list->n)){ + gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer"); + return(&list->array[0]); + } + return(&list->array[index * list->size]); +} + +void gl2psListRead(GL2PSlist *list, GLint index, void *data){ + if((index < 0) || (index >= list->n)){ + gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListRead"); + data = 0; + } + else{ + memcpy(data, &list->array[index * list->size], list->size); + } +} + +void gl2psListSort(GL2PSlist *list, + int (*fcmp)(const void *a, const void *b)){ + qsort(list->array, list->n, list->size, fcmp); +} + +void gl2psListAction(GL2PSlist *list, void (*action)(void *data)){ + GLint i; + + for(i = 0; i < gl2psListNbr(list); i++){ + (*action)(gl2psListPointer(list, i)); + } +} + +void gl2psListActionInverse(GL2PSlist *list, void (*action)(void *data)){ + GLint i; + + for(i = gl2psListNbr(list); i > 0; i--){ + (*action)(gl2psListPointer(list, i-1)); + } +} + +/* Helper for pixmaps and strings */ + +GL2PSimage* gl2psCopyPixmap(GL2PSimage* im){ + int size; + GL2PSimage* image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); + + image->width = im->width; + image->height = im->height; + image->format = im->format; + image->type = im->type; + + /* FIXME: handle other types/formats */ + size = image->height*image->width*3*sizeof(GLfloat); + + image->pixels = (GLfloat*)gl2psMalloc(size); + memcpy(image->pixels, im->pixels, size); + + return image; +} + +void gl2psFreePixmap(GL2PSimage* im){ + if(!im) + return; + if(im->pixels) + gl2psFree(im->pixels); + gl2psFree(im); +} + +GL2PSstring* gl2psCopyText(GL2PSstring* t){ + GL2PSstring* text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); + text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char)); + strcpy(text->str, t->str); + text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char)); + strcpy(text->fontname, t->fontname); + text->fontsize = t->fontsize; + text->alignment = t->alignment; + + return text; +} + +void gl2psFreeText(GL2PSstring* text){ + if(!text) + return; + if(text->str) + gl2psFree(text->str); + if(text->fontname) + gl2psFree(text->fontname); + gl2psFree(text); +} + +/* Helpers for rgba colors */ + +GLfloat gl2psColorDiff(GL2PSrgba rgba1, GL2PSrgba rgba2){ + int i; + GLfloat res = 0; + for(i = 0; i < 3; ++i){ + res += (rgba1[i] - rgba2[i]) * (rgba1[i] - rgba2[i]); + } + return res; +} + +GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2){ + return !(rgba1[0] != rgba2[0] || + rgba1[1] != rgba2[1] || + rgba1[2] != rgba2[2]); +} + +GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim){ + int i; + + for(i = 1; i < prim->numverts; i++){ + if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){ + return 0; + } + } + return 1; +} + +void gl2psSetLastColor(GL2PSrgba rgba){ + int i; + for(i = 0; i < 3; ++i){ + gl2ps->lastrgba[i] = rgba[i]; + } +} + +/********************************************************************* + * + * 3D sorting routines + * + *********************************************************************/ + +GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane){ + return(plane[0] * point[0] + + plane[1] * point[1] + + plane[2] * point[2] + + plane[3]); +} + +GLfloat gl2psPsca(GLfloat *a, GLfloat *b){ + return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]); +} + +void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *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]; +} + +GLfloat gl2psNorm(GLfloat *a){ + return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); +} + +void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c){ + GLfloat norm; + + gl2psPvec(a, b, c); + if(!GL2PS_ZERO(norm = gl2psNorm(c))){ + c[0] = c[0] / norm; + c[1] = c[1] / norm; + c[2] = c[2] / norm; + } + else{ + /* FIXME: the plane is still wrong, despite our tests in + gl2psGetPlane... Let's return a dummy value for now (this is a + hack: we should do more tests in GetPlane) */ + c[0] = c[1] = 0.0F; + c[2] = 1.0F; + } +} + +void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane){ + GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F}; + + switch(prim->type){ + case GL2PS_TRIANGLE : + case GL2PS_QUADRANGLE : + v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; + v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; + v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; + w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0]; + w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1]; + w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2]; + if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) || + (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){ + plane[0] = plane[1] = 0.0F; + plane[2] = 1.0F; + plane[3] = -prim->verts[0].xyz[2]; + } + else{ + gl2psGetNormal(v, w, plane); + plane[3] = + - plane[0] * prim->verts[0].xyz[0] + - plane[1] * prim->verts[0].xyz[1] + - plane[2] * prim->verts[0].xyz[2]; + } + break; + case GL2PS_LINE : + v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; + v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; + v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; + if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){ + plane[0] = plane[1] = 0.0F; + plane[2] = 1.0F; + plane[3] = -prim->verts[0].xyz[2]; + } + else{ + if(GL2PS_ZERO(v[0])) w[0] = 1.0F; + else if(GL2PS_ZERO(v[1])) w[1] = 1.0F; + else w[2] = 1.0F; + gl2psGetNormal(v, w, plane); + plane[3] = + - plane[0] * prim->verts[0].xyz[0] + - plane[1] * prim->verts[0].xyz[1] + - plane[2] * prim->verts[0].xyz[2]; + } + break; + case GL2PS_POINT : + case GL2PS_PIXMAP : + case GL2PS_TEXT : + plane[0] = plane[1] = 0.0F; + plane[2] = 1.0F; + plane[3] = -prim->verts[0].xyz[2]; + break; + default : + gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree"); + plane[0] = plane[1] = plane[3] = 0.0F; + plane[2] = 1.0F; + break; + } +} + +void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane, + GL2PSvertex *c){ + GL2PSxyz v; + GLfloat sect; + + v[0] = b->xyz[0] - a->xyz[0]; + v[1] = b->xyz[1] - a->xyz[1]; + v[2] = b->xyz[2] - a->xyz[2]; + sect = - gl2psComparePointPlane(a->xyz, plane) / gl2psPsca(plane, v); + + c->xyz[0] = a->xyz[0] + v[0] * sect; + c->xyz[1] = a->xyz[1] + v[1] * sect; + c->xyz[2] = a->xyz[2] + v[2] * sect; + + c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0]; + c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1]; + c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2]; + c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3]; +} + +void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane, + GL2PSprimitive *child, GLshort numverts, + GLshort *index0, GLshort *index1){ + GLshort i; + + if(numverts > 4){ + gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts); + numverts = 4; + } + + switch(numverts){ + case 1 : child->type = GL2PS_POINT; break; + case 2 : child->type = GL2PS_LINE; break; + case 3 : child->type = GL2PS_TRIANGLE; break; + case 4 : child->type = GL2PS_QUADRANGLE; break; + } + child->boundary = 0; /* not done! */ + child->depth = parent->depth; /* should not be used in this case */ + child->culled = parent->culled; + child->dash = parent->dash; + child->width = parent->width; + child->numverts = numverts; + child->verts = (GL2PSvertex *)gl2psMalloc(numverts * sizeof(GL2PSvertex)); + + for(i = 0; i < numverts; i++){ + if(index1[i] < 0){ + child->verts[i] = parent->verts[index0[i]]; + } + else{ + gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]], + plane, &child->verts[i]); + } + } +} + +void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb, + GLshort i, GLshort j){ + GLint k; + + for(k = 0; k < *nb; k++){ + if((index0[k] == i && index1[k] == j) || + (index1[k] == i && index0[k] == j)) return; + } + index0[*nb] = i; + index1[*nb] = j; + (*nb)++; +} + +GLshort gl2psGetIndex(GLshort i, GLshort num){ + return(i < num-1) ? i+1 : 0; +} + +GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane){ + GLint type = GL2PS_COINCIDENT; + GLshort i, j; + GLfloat d[5]; + + for(i = 0; i < prim->numverts; i++){ + d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane); + } + + if(prim->numverts < 2){ + return 0; + } + else{ + for(i = 0; i < prim->numverts; i++){ + j = gl2psGetIndex(i, prim->numverts); + if(d[j] > GL2PS_EPSILON){ + if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF; + else if(type != GL2PS_IN_BACK_OF) return 1; + if(d[i] < -GL2PS_EPSILON) return 1; + } + else if(d[j] < -GL2PS_EPSILON){ + if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF; + else if(type != GL2PS_IN_FRONT_OF) return 1; + if(d[i] > GL2PS_EPSILON) return 1; + } + } + } + return 0; +} + +GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane, + GL2PSprimitive **front, GL2PSprimitive **back){ + GLshort i, j, in=0, out=0, in0[5], in1[5], out0[5], out1[5]; + GLint type; + GLfloat d[5]; + + type = GL2PS_COINCIDENT; + + for(i = 0; i < prim->numverts; i++){ + d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane); + } + + switch(prim->type){ + case GL2PS_POINT : + if(d[0] > GL2PS_EPSILON) type = GL2PS_IN_BACK_OF; + else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF; + else type = GL2PS_COINCIDENT; + break; + default : + for(i = 0; i < prim->numverts; i++){ + j = gl2psGetIndex(i, prim->numverts); + if(d[j] > GL2PS_EPSILON){ + if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF; + else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING; + if(d[i] < -GL2PS_EPSILON){ + gl2psAddIndex(in0, in1, &in, i, j); + gl2psAddIndex(out0, out1, &out, i, j); + type = GL2PS_SPANNING; + } + gl2psAddIndex(out0, out1, &out, j, -1); + } + else if(d[j] < -GL2PS_EPSILON){ + if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF; + else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING; + if(d[i] > GL2PS_EPSILON){ + gl2psAddIndex(in0, in1, &in, i, j); + gl2psAddIndex(out0, out1, &out, i, j); + type = GL2PS_SPANNING; + } + gl2psAddIndex(in0, in1, &in, j, -1); + } + else{ + gl2psAddIndex(in0, in1, &in, j, -1); + gl2psAddIndex(out0, out1, &out, j, -1); + } + } + break; + } + + if(type == GL2PS_SPANNING){ + *back = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); + *front = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); + gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1); + gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1); + } + + return type; +} + +void gl2psDivideQuad(GL2PSprimitive *quad, + GL2PSprimitive **t1, GL2PSprimitive **t2){ + *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); + *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); + (*t1)->type = (*t2)->type = GL2PS_TRIANGLE; + (*t1)->numverts = (*t2)->numverts = 3; + (*t1)->depth = (*t2)->depth = quad->depth; + (*t1)->culled = (*t2)->culled = quad->culled; + (*t1)->dash = (*t2)->dash = quad->dash; + (*t1)->width = (*t2)->width = quad->width; + (*t1)->verts = (GL2PSvertex *)gl2psMalloc(3 * sizeof(GL2PSvertex)); + (*t2)->verts = (GL2PSvertex *)gl2psMalloc(3 * sizeof(GL2PSvertex)); + (*t1)->verts[0] = quad->verts[0]; + (*t1)->verts[1] = quad->verts[1]; + (*t1)->verts[2] = quad->verts[2]; + (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0); + (*t2)->verts[0] = quad->verts[0]; + (*t2)->verts[1] = quad->verts[2]; + (*t2)->verts[2] = quad->verts[3]; + (*t1)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 4) ? 2 : 0); +} + +int gl2psCompareDepth(const void *a, const void *b){ + GL2PSprimitive *q, *w; + GLfloat diff; + + q = *(GL2PSprimitive**)a; + w = *(GL2PSprimitive**)b; + diff = q->depth - w->depth; + if(diff > 0.){ + return 1; + } + else if(diff < 0.){ + return -1; + } + else{ + return 0; + } +} + +int gl2psTrianglesFirst(const void *a, const void *b){ + GL2PSprimitive *q, *w; + + q = *(GL2PSprimitive**)a; + w = *(GL2PSprimitive**)b; + return(q->type < w->type ? 1 : -1); +} + +GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root){ + GLint i, j, count, best = 1000000, index = 0; + GL2PSprimitive *prim1, *prim2; + GL2PSplane plane; + GLint maxp; + + if(gl2ps->options & GL2PS_BEST_ROOT){ + *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0); + maxp = gl2psListNbr(primitives); + if(maxp > gl2ps->maxbestroot){ + maxp = gl2ps->maxbestroot; + } + for(i = 0; i < maxp; i++){ + prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i); + gl2psGetPlane(prim1, plane); + count = 0; + for(j = 0; j < gl2psListNbr(primitives); j++){ + if(j != i){ + prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j); + count += gl2psTestSplitPrimitive(prim2, plane); + } + if(count > best) break; + } + if(count < best){ + best = count; + index = i; + *root = prim1; + if(!count) return index; + } + } + /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */ + return index; + } + else{ + *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0); + return 0; + } +} + +void gl2psFreePrimitive(void *data){ + GL2PSprimitive *q; + + q = *(GL2PSprimitive**)data; + gl2psFree(q->verts); + if(q->type == GL2PS_TEXT){ + gl2psFree(q->data.text->str); + gl2psFree(q->data.text->fontname); + gl2psFree(q->data.text); + } + if(q->type == GL2PS_PIXMAP){ + gl2psFree(q->data.image->pixels); + gl2psFree(q->data.image); + } + gl2psFree(q); +} + +void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list){ + GL2PSprimitive *t1, *t2; + + if(prim->type != GL2PS_QUADRANGLE){ + gl2psListAdd(list, &prim); + } + else{ + gl2psDivideQuad(prim, &t1, &t2); + gl2psListAdd(list, &t1); + gl2psListAdd(list, &t2); + gl2psFreePrimitive(&prim); + } + +} + +void gl2psFreeBspTree(GL2PSbsptree **tree){ + if(*tree){ + if((*tree)->back) gl2psFreeBspTree(&(*tree)->back); + if((*tree)->primitives){ + gl2psListAction((*tree)->primitives, gl2psFreePrimitive); + gl2psListDelete((*tree)->primitives); + } + if((*tree)->front) gl2psFreeBspTree(&(*tree)->front); + gl2psFree(*tree); + *tree = NULL; + } +} + +GLboolean gl2psGreater(GLfloat f1, GLfloat f2){ + if(f1 > f2) return 1; + else return 0; +} + +GLboolean gl2psLess(GLfloat f1, GLfloat f2){ + if(f1 < f2) return 1; + else return 0; +} + +void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives){ + GL2PSprimitive *prim, *frontprim, *backprim; + GL2PSlist *frontlist, *backlist; + GLint i, index; + + tree->front = NULL; + tree->back = NULL; + tree->primitives = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); + index = gl2psFindRoot(primitives, &prim); + gl2psGetPlane(prim, tree->plane); + gl2psAddPrimitiveInList(prim, tree->primitives); + + frontlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); + backlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); + + for(i = 0; i < gl2psListNbr(primitives); i++){ + if(i != index){ + prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i); + switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){ + case GL2PS_COINCIDENT: + gl2psAddPrimitiveInList(prim, tree->primitives); + break; + case GL2PS_IN_BACK_OF: + gl2psAddPrimitiveInList(prim, backlist); + break; + case GL2PS_IN_FRONT_OF: + gl2psAddPrimitiveInList(prim, frontlist); + break; + case GL2PS_SPANNING: + gl2psAddPrimitiveInList(backprim, backlist); + gl2psAddPrimitiveInList(frontprim, frontlist); + gl2psFreePrimitive(&prim); + break; + } + } + } + + if(gl2psListNbr(tree->primitives)){ + gl2psListSort(tree->primitives, gl2psTrianglesFirst); + } + + if(gl2psListNbr(frontlist)){ + gl2psListSort(frontlist, gl2psTrianglesFirst); + tree->front = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree)); + gl2psBuildBspTree(tree->front, frontlist); + } + else{ + gl2psListDelete(frontlist); + } + + if(gl2psListNbr(backlist)){ + gl2psListSort(backlist, gl2psTrianglesFirst); + tree->back = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree)); + gl2psBuildBspTree(tree->back, backlist); + } + else{ + gl2psListDelete(backlist); + } + + gl2psListDelete(primitives); +} + +void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon, + GLboolean (*compare)(GLfloat f1, GLfloat f2), + void (*action)(void *data), int inverse){ + GLfloat result; + + if(!tree) return; + + result = gl2psComparePointPlane(eye, tree->plane); + + if(compare(result, epsilon)){ + gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse); + if(inverse){ + gl2psListActionInverse(tree->primitives, action); + } + else{ + gl2psListAction(tree->primitives, action); + } + gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse); + } + else if(compare(-epsilon, result)){ + gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse); + if(inverse){ + gl2psListActionInverse(tree->primitives, action); + } + else{ + gl2psListAction(tree->primitives, action); + } + gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse); + } + else{ + gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse); + gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse); + } +} + +/********************************************************************* + * + * 2D sorting routines (for occlusion culling) + * + *********************************************************************/ + +GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane){ + GLfloat n; + + plane[0] = b[1] - a[1]; + plane[1] = a[0] - b[0]; + n = (GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]); + plane[2] = 0.0F; + if(n != 0.0){ + plane[0] /= n; + plane[1] /= n; + plane[3] = -plane[0]*a[0]-plane[1]*a[1]; + return 1; + } + else{ + plane[0] = -1.0F; + plane[1] = 0.0F; + plane[3] = a[0]; + return 0; + } +} + +void gl2psFreeBspImageTree(GL2PSbsptree2d **tree){ + if(*tree){ + if((*tree)->back) gl2psFreeBspImageTree(&(*tree)->back); + if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front); + gl2psFree(*tree); + *tree = NULL; + } +} + +GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane){ + GLfloat pt_dis; + + pt_dis = gl2psComparePointPlane(point, plane); + if(pt_dis > GL2PS_EPSILON) return GL2PS_POINT_INFRONT; + else if(pt_dis < -GL2PS_EPSILON) return GL2PS_POINT_BACK; + else return GL2PS_POINT_COINCIDENT; +} + +void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim, + GL2PSbsptree2d **tree){ + GLint ret = 0; + GLint i; + GLint offset = 0; + GL2PSbsptree2d *head = NULL, *cur = NULL; + + if((*tree == NULL) && (prim->numverts > 2)){ + head = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); + for(i = 0; i < prim->numverts-1; i++){ + if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz, + prim->verts[i+1].xyz, + head->plane)){ + if(prim->numverts-i > 3){ + offset++; + } + else{ + gl2psFree(head); + return; + } + } + else{ + break; + } + } + head->back = NULL; + head->front = NULL; + for(i = 2+offset; i < prim->numverts; i++){ + ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane); + if(ret != GL2PS_POINT_COINCIDENT) break; + } + switch(ret){ + case GL2PS_POINT_INFRONT : + cur = head; + for(i = 1+offset; i < prim->numverts-1; i++){ + if(cur->front == NULL){ + cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); + } + if(gl2psGetPlaneFromPoints(prim->verts[i].xyz, + prim->verts[i+1].xyz, + cur->front->plane)){ + cur = cur->front; + cur->front = NULL; + cur->back = NULL; + } + } + if(cur->front == NULL){ + cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); + } + if(gl2psGetPlaneFromPoints(prim->verts[i].xyz, + prim->verts[offset].xyz, + cur->front->plane)){ + cur->front->front = NULL; + cur->front->back = NULL; + } + else{ + gl2psFree(cur->front); + cur->front = NULL; + } + break; + case GL2PS_POINT_BACK : + for(i = 0; i < 4; i++){ + head->plane[i] = -head->plane[i]; + } + cur = head; + for(i = 1+offset; i < prim->numverts-1; i++){ + if(cur->front == NULL){ + cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); + } + if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz, + prim->verts[i].xyz, + cur->front->plane)){ + cur = cur->front; + cur->front = NULL; + cur->back = NULL; + } + } + if(cur->front == NULL){ + cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); + } + if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz, + prim->verts[i].xyz, + cur->front->plane)){ + cur->front->front = NULL; + cur->front->back = NULL; + } + else{ + gl2psFree(cur->front); + cur->front = NULL; + } + break; + default: + gl2psFree(head); + return; + } + (*tree) = head; + } +} + +GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane){ + GLint i; + GLint pos; + + pos = gl2psCheckPoint(prim->verts[0].xyz, plane); + for(i = 1; i < prim->numverts; i++){ + pos |= gl2psCheckPoint(prim->verts[i].xyz, plane); + if(pos == (GL2PS_POINT_INFRONT | GL2PS_POINT_BACK)) return GL2PS_SPANNING; + } + if(pos & GL2PS_POINT_INFRONT) return GL2PS_IN_FRONT_OF; + else if(pos & GL2PS_POINT_BACK) return GL2PS_IN_BACK_OF; + else return GL2PS_COINCIDENT; +} + +GL2PSprimitive* gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent, + GLshort numverts, + GL2PSvertex *vertx){ + GLint i; + GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); + + switch(numverts){ + case 1 : child->type = GL2PS_POINT; break; + case 2 : child->type = GL2PS_LINE; break; + case 3 : child->type = GL2PS_TRIANGLE; break; + case 4 : child->type = GL2PS_QUADRANGLE; break; + } + child->boundary = 0; /* not done! */ + child->depth = parent->depth; + child->culled = parent->culled; + child->dash = parent->dash; + child->width = parent->width; + child->numverts = numverts; + child->verts = (GL2PSvertex *)gl2psMalloc(numverts * sizeof(GL2PSvertex)); + for(i = 0; i < numverts; i++){ + child->verts[i] = vertx[i]; + } + return child; +} + +void gl2psSplitPrimitive2D(GL2PSprimitive *prim, + GL2PSplane plane, + GL2PSprimitive **front, + GL2PSprimitive **back){ + + /* cur will hold the position of the current vertex + prev will hold the position of the previous vertex + prev0 will hold the position of the vertex number 0 + v1 and v2 represent the current and previous vertices, respectively + flag is set if the current vertex should be checked against the plane */ + GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1; + + /* list of vertices that will go in front and back primitive */ + GL2PSvertex *front_list = NULL, *back_list = NULL; + + /* number of vertices in front and back list */ + GLshort front_count = 0, back_count = 0; + + for(i = 0; i <= prim->numverts; i++){ + v1 = i; + if(v1 == prim->numverts){ + if(prim->numverts < 3) break; + v1 = 0; + v2 = prim->numverts-1; + cur = prev0; + } + else if(flag){ + cur = gl2psCheckPoint(prim->verts[v1].xyz, plane); + if(i == 0){ + prev0 = cur; + } + } + if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) && + (i < prim->numverts)){ + if(cur == GL2PS_POINT_INFRONT){ + front_count++; + front_list = (GL2PSvertex*)gl2psRealloc(front_list, + sizeof(GL2PSvertex)*front_count); + front_list[front_count-1] = prim->verts[v1]; + } + else if(cur == GL2PS_POINT_BACK){ + back_count++; + back_list = (GL2PSvertex*)gl2psRealloc(back_list, + sizeof(GL2PSvertex)*back_count); + back_list[back_count-1] = prim->verts[v1]; + } + else{ + front_count++; + front_list = (GL2PSvertex*)gl2psRealloc(front_list, + sizeof(GL2PSvertex)*front_count); + front_list[front_count-1] = prim->verts[v1]; + back_count++; + back_list = (GL2PSvertex*)gl2psRealloc(back_list, + sizeof(GL2PSvertex)*back_count); + back_list[back_count-1] = prim->verts[v1]; + } + flag = 1; + } + else if((prev != cur) && (cur != 0) && (prev != 0)){ + if(v1 != 0){ + v2 = v1-1; + i--; + } + front_count++; + front_list = (GL2PSvertex*)gl2psRealloc(front_list, + sizeof(GL2PSvertex)*front_count); + gl2psCutEdge(&prim->verts[v2], + &prim->verts[v1], + plane, + &front_list[front_count-1]); + back_count++; + back_list = (GL2PSvertex*)gl2psRealloc(back_list, + sizeof(GL2PSvertex)*back_count); + back_list[back_count-1] = front_list[front_count-1]; + flag = 0; + } + prev = cur; + } + *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list); + *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list); + gl2psFree(front_list); + gl2psFree(back_list); +} + +GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree){ + GLint ret = 0; + GL2PSprimitive *frontprim = NULL, *backprim = NULL; + + /* FIXME: until we consider the actual extent of text strings and + pixmaps, never cull them. Otherwise the whole string/pixmap gets + culled as soon as the reference point is hidden */ + if(prim->type == GL2PS_PIXMAP || prim->type == GL2PS_TEXT){ + return 1; + } + + if(*tree == NULL){ + if(!gl2ps->zerosurfacearea){ + gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree); + } + return 1; + } + else{ + switch(gl2psCheckPrimitive(prim, (*tree)->plane)){ + case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back); + case GL2PS_IN_FRONT_OF: + if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front); + else return 0; + case GL2PS_SPANNING: + gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim); + ret = gl2psAddInBspImageTree(backprim, &(*tree)->back); + if((*tree)->front != NULL){ + if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){ + ret = 1; + } + } + gl2psFree(frontprim->verts); + gl2psFree(frontprim); + gl2psFree(backprim->verts); + gl2psFree(backprim); + return ret; + case GL2PS_COINCIDENT: + if((*tree)->back != NULL){ + gl2ps->zerosurfacearea = 1; + ret = gl2psAddInBspImageTree(prim, &(*tree)->back); + gl2ps->zerosurfacearea = 0; + if(ret) return ret; + } + if((*tree)->front != NULL){ + gl2ps->zerosurfacearea = 1; + ret = gl2psAddInBspImageTree(prim, &(*tree)->front); + gl2ps->zerosurfacearea = 0; + if(ret) return ret; + } + if(prim->type == GL2PS_LINE) return 1; + else return 0; + } + } + return 0; +} + +void gl2psAddInImageTree(void *data){ + GL2PSprimitive *prim = *(GL2PSprimitive **)data; + gl2ps->primitivetoadd = prim; + if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){ + prim->culled = 1; + } +} + +/* Boundary contruction */ + +void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list){ + GL2PSprimitive *b; + GLshort i; + GL2PSxyz c; + + c[0] = c[1] = c[2] = 0.0F; + for(i = 0; i < prim->numverts; i++){ + c[0] += prim->verts[i].xyz[0]; + c[1] += prim->verts[i].xyz[1]; + } + c[0] /= prim->numverts; + c[1] /= prim->numverts; + + for(i = 0; i < prim->numverts; i++){ + if(prim->boundary & (GLint)pow(2., i)){ + b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); + b->type = GL2PS_LINE; + b->dash = prim->dash; + b->depth = prim->depth; /* FIXME: this is wrong */ + b->culled = prim->culled; + b->width = prim->width; + b->boundary = 0; + b->numverts = 2; + b->verts = (GL2PSvertex *)gl2psMalloc(2 * sizeof(GL2PSvertex)); + +#if 0 /* FIXME: need to work on boundary offset... */ + v[0] = c[0] - prim->verts[i].xyz[0]; + v[1] = c[1] - prim->verts[i].xyz[1]; + v[2] = 0.0F; + norm = gl2psNorm(v); + v[0] /= norm; + v[1] /= norm; + b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0]; + b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1]; + b->verts[0].xyz[2] = prim->verts[i].xyz[2]; + v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0]; + v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1]; + norm = gl2psNorm(v); + v[0] /= norm; + v[1] /= norm; + b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0]; + b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1]; + b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2]; +#else + b->verts[0].xyz[0] = prim->verts[i].xyz[0]; + b->verts[0].xyz[1] = prim->verts[i].xyz[1]; + b->verts[0].xyz[2] = prim->verts[i].xyz[2]; + b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0]; + b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1]; + b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2]; +#endif + + b->verts[0].rgba[0] = 0.0F; + b->verts[0].rgba[1] = 0.0F; + b->verts[0].rgba[2] = 0.0F; + b->verts[0].rgba[3] = 0.0F; + b->verts[1].rgba[0] = 0.0F; + b->verts[1].rgba[1] = 0.0F; + b->verts[1].rgba[2] = 0.0F; + b->verts[1].rgba[3] = 0.0F; + gl2psListAdd(list, &b); + } + } + +} + +void gl2psBuildPolygonBoundary(GL2PSbsptree *tree){ + GLint i, n; + GL2PSprimitive *prim; + + if(!tree) return; + gl2psBuildPolygonBoundary(tree->back); + n = gl2psListNbr(tree->primitives); + for(i = 0; i < n; i++){ + prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i); + if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives); + } + gl2psBuildPolygonBoundary(tree->front); +} + +/********************************************************************* + * + * Feedback buffer parser + * + *********************************************************************/ + +void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, + GL2PSvertex *verts, GLint offset, + char dash, GLfloat width, + char boundary){ + GLshort i; + GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ; + GL2PSprimitive *prim; + + prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive)); + prim->type = type; + prim->numverts = numverts; + prim->verts = (GL2PSvertex *)gl2psMalloc(numverts * sizeof(GL2PSvertex)); + memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex)); + prim->boundary = boundary; + prim->dash = dash; + prim->width = width; + prim->culled = 0; + + if(gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET){ + + if(type == GL2PS_LINE){ + if(gl2ps->sort == GL2PS_SIMPLE_SORT){ + prim->verts[0].xyz[2] -= GL2PS_SIMPLE_OFFSET_LARGE; + prim->verts[1].xyz[2] -= GL2PS_SIMPLE_OFFSET_LARGE; + } + else{ + prim->verts[0].xyz[2] -= GL2PS_SIMPLE_OFFSET; + prim->verts[1].xyz[2] -= GL2PS_SIMPLE_OFFSET; + } + } + + } + else if(offset && type == GL2PS_TRIANGLE){ + + /* FIXME: this needs some more work... */ + + if(gl2ps->sort == GL2PS_SIMPLE_SORT){ + factor = gl2ps->offset[0]; + units = gl2ps->offset[1]; + } + else{ + factor = gl2ps->offset[0] / 800.0F; + units = gl2ps->offset[1] / 800.0F; + } + + area = + (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * + (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - + (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * + (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]); + dZdX = + (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) * + (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) - + (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) * + (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) / area; + dZdY = + (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * + (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) - + (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * + (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) / area; + + maxdZ = (GLfloat)sqrt(dZdX*dZdX + dZdY*dZdY); + + dZ = factor * maxdZ + units; + + prim->verts[0].xyz[2] += dZ; + prim->verts[1].xyz[2] += dZ; + prim->verts[2].xyz[2] += dZ; + } + + prim->depth = 0.; + if(gl2ps->sort == GL2PS_SIMPLE_SORT){ + for(i = 0; i < numverts; i++){ + prim->depth += prim->verts[i].xyz[2]; + } + prim->depth /= (GLfloat)numverts; + } + + gl2psListAdd(gl2ps->primitives, &prim); +} + +GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p){ + GLint i; + + v->xyz[0] = p[0]; + v->xyz[1] = p[1]; + v->xyz[2] = GL2PS_DEPTH_FACT * p[2]; + + if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){ + i = (GLint)(p[3] + 0.5); + v->rgba[0] = gl2ps->colormap[i][0]; + v->rgba[1] = gl2ps->colormap[i][1]; + v->rgba[2] = gl2ps->colormap[i][2]; + v->rgba[3] = gl2ps->colormap[i][3]; + return 4; + } + else{ + v->rgba[0] = p[3]; + v->rgba[1] = p[4]; + v->rgba[2] = p[5]; + v->rgba[3] = p[6]; + return 7; + } +} + +void gl2psParseFeedbackBuffer(GLint used){ + char flag, dash = 0; + GLshort boundary; + GLint i, count, v, vtot, offset = 0; + GLfloat lwidth = 1.0F, psize = 1.0F; + GLfloat *current; + GL2PSvertex vertices[3]; + + current = gl2ps->feedback; + boundary = gl2ps->boundary = 0; + + while(used > 0){ + + if(boundary) gl2ps->boundary = 1; + + switch((GLint)*current){ + case GL_POINT_TOKEN : + current ++; + used --; + i = gl2psGetVertex(&vertices[0], current); + current += i; + used -= i; + gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, dash, psize, 0); + break; + case GL_LINE_TOKEN : + case GL_LINE_RESET_TOKEN : + current ++; + used --; + i = gl2psGetVertex(&vertices[0], current); + current += i; + used -= i; + i = gl2psGetVertex(&vertices[1], current); + current += i; + used -= i; + gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, dash, lwidth, 0); + break; + case GL_POLYGON_TOKEN : + count = (GLint)current[1]; + current += 2; + used -= 2; + v = vtot = 0; + while(count > 0 && used > 0){ + i = gl2psGetVertex(&vertices[v], current); + current += i; + used -= i; + count --; + vtot++; + if(v == 2){ + if(boundary){ + if(!count && vtot == 2) flag = 1|2|4; + else if(!count) flag = 2|4; + else if(vtot == 2) flag = 1|2; + else flag = 2; + } + else + flag = 0; + gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, + offset, dash, 1, flag); + vertices[1] = vertices[2]; + } + else + v ++; + } + break; + case GL_BITMAP_TOKEN : + case GL_DRAW_PIXEL_TOKEN : + case GL_COPY_PIXEL_TOKEN : + current ++; + used --; + i = gl2psGetVertex(&vertices[0], current); + current += i; + used -= i; + break; + case GL_PASS_THROUGH_TOKEN : + switch((GLint)current[1]){ + case GL2PS_BEGIN_POLYGON_OFFSET_FILL : offset = 1; break; + case GL2PS_END_POLYGON_OFFSET_FILL : offset = 0; break; + case GL2PS_BEGIN_POLYGON_BOUNDARY : boundary = 1; break; + case GL2PS_END_POLYGON_BOUNDARY : boundary = 0; break; + case GL2PS_BEGIN_LINE_STIPPLE : dash = 4; break; + case GL2PS_END_LINE_STIPPLE : dash = 0; break; + case GL2PS_SET_POINT_SIZE : + current += 2; + used -= 2; + psize = current[1]; + break; + case GL2PS_SET_LINE_WIDTH : + current += 2; + used -= 2; + lwidth = current[1]; + break; + } + current += 2; + used -= 2; + break; + default : + gl2psMsg(GL2PS_WARNING, "Unknown token in buffer"); + current ++; + used --; + break; + } + } +} + +/********************************************************************* + * + * PostScript routines + * + *********************************************************************/ + +void gl2psGetRGB(GLfloat *pixels, GLsizei width, GLsizei height, GLuint x, GLuint y, + GLfloat *red, GLfloat *green, GLfloat *blue){ + /* OpenGL image is from down to up, PS image is up to down */ + GLfloat *pimag; + pimag = pixels + 3 * (width * (height - 1 - y) + x); + *red = *pimag; pimag++; + *green = *pimag; pimag++; + *blue = *pimag; pimag++; +} + +void gl2psWriteByte(unsigned char byte){ + unsigned char h = byte / 16; + unsigned char l = byte % 16; + gl2psPrintf("%x%x", h, l); +} + +void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GLsizei width, GLsizei height, + GLfloat *pixels){ + int nbhex, nbyte2, nbyte4, nbyte8; + GLsizei row, col, col_max; + GLfloat dr, dg, db; + unsigned char red, green, blue, b, grey; + + /* FIXME: define an option for these? */ + int greyscale = 0; /* set to 1 to output greyscale image */ + int nbits = 8; /* number of bits per color compoment (2, 4 or 8) */ + + if((width <= 0) || (height <= 0)) return; + + gl2psPrintf("gsave\n"); + gl2psPrintf("%.2f %.2f translate\n", x, y); + gl2psPrintf("%d %d scale\n", (int)width, (int)height); + + if(greyscale){ /* greyscale, 8 bits per pixel */ + gl2psPrintf("/picstr %d string def\n", (int)width); + gl2psPrintf("%d %d %d\n", (int)width, (int)height, 8); + gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)width, (int)height, (int)height); + gl2psPrintf("{ currentfile picstr readhexstring pop }\n"); + gl2psPrintf("image\n"); + for(row = 0; row < height; row++){ + for(col = 0; col < width; col++){ + gl2psGetRGB(pixels, width, height, col, row, &dr, &dg, &db); + grey = (unsigned char)(255.0 * (0.30 * dr + 0.59 * dg + 0.11 * db)); + gl2psWriteByte(grey); + } + gl2psPrintf("\n"); + } + nbhex = width * height * 2; + gl2psPrintf("%%%% nbhex digit :%d\n", nbhex); + } + else if(nbits == 2){ /* color, 2 bits for r and g and b; rgbs following each other */ + nbyte2 = (width * 3)/4; + nbyte2 /=3; + nbyte2 *=3; + col_max = (nbyte2 * 4)/3; + gl2psPrintf("/rgbstr %d string def\n", nbyte2); + gl2psPrintf("%d %d %d\n", (int)col_max, (int)height, 2); + gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)col_max, (int)height, (int)height); + gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n" ); + gl2psPrintf("false 3\n" ); + gl2psPrintf("colorimage\n" ); + for(row = 0; row < height; row++){ + for(col = 0; col < col_max; col+=4){ + gl2psGetRGB(pixels, width, height, col, row, &dr, &dg, &db); + red = (unsigned char)(3.0 * dr); + green = (unsigned char)(3.0 * dg); + blue = (unsigned char)(3.0 * db); + b = red; + b = (b<<2)+green; + b = (b<<2)+blue; + gl2psGetRGB(pixels, width, height, col+1, row, &dr, &dg, &db); + red = (unsigned char)(3.0 * dr); + green = (unsigned char)(3.0 * dg); + blue = (unsigned char)(3.0 * db); + b = (b<<2)+red; + gl2psWriteByte(b); + b = green; + b = (b<<2)+blue; + gl2psGetRGB(pixels, width, height, col+2, row, &dr, &dg, &db); + red = (unsigned char)(3.0 * dr); + green = (unsigned char)(3.0 * dg); + blue = (unsigned char)(3.0 * db); + b = (b<<2)+red; + b = (b<<2)+green; + gl2psWriteByte(b); + b = blue; + gl2psGetRGB(pixels, width, height, col+3, row, &dr, &dg, &db); + red = (unsigned char)(3.0 * dr); + green = (unsigned char)(3.0 * dg); + blue = (unsigned char)(3.0 * db); + b = (b<<2)+red; + b = (b<<2)+green; + b = (b<<2)+blue; + gl2psWriteByte(b); + } + gl2psPrintf("\n"); + } + } + else if(nbits == 4){ /* color, 4 bits for r and g and b; rgbs following each other */ + nbyte4 = (width * 3)/2; + nbyte4 /=3; + nbyte4 *=3; + col_max = (nbyte4 * 2)/3; + gl2psPrintf("/rgbstr %d string def\n", nbyte4); + gl2psPrintf("%d %d %d\n", (int)col_max, (int)height, 4); + gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)col_max, (int)height, (int)height); + gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n"); + gl2psPrintf("false 3\n"); + gl2psPrintf("colorimage\n"); + for(row = 0; row < height; row++){ + for(col = 0; col < col_max; col+=2){ + gl2psGetRGB(pixels, width, height, col, row, &dr, &dg, &db); + red = (unsigned char)(15. * dr); + green = (unsigned char)(15. * dg); + gl2psPrintf("%x%x", red, green); + blue = (unsigned char)(15. * db); + gl2psGetRGB(pixels, width, height, col+1, row, &dr, &dg, &db); + red = (unsigned char)(15. * dr); + gl2psPrintf("%x%x",blue,red); + green = (unsigned char)(15. * dg); + blue = (unsigned char)(15. * db); + gl2psPrintf("%x%x", green, blue); + } + gl2psPrintf("\n"); + } + } + else{ /* color, 8 bits for r and g and b; rgbs following each other */ + nbyte8 = width * 3; + gl2psPrintf("/rgbstr %d string def\n", nbyte8); + gl2psPrintf("%d %d %d\n", (int)width, (int)height, 8); + gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)width, (int)height, (int)height); + gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n"); + gl2psPrintf("false 3\n"); + gl2psPrintf("colorimage\n"); + for(row = 0; row < height; row++){ + for(col = 0; col < width; col++){ + gl2psGetRGB(pixels, width, height, col, row, &dr, &dg, &db); + red = (unsigned char)(255.0 * dr); + gl2psWriteByte(red); + green = (unsigned char)(255.0 * dg); + gl2psWriteByte(green); + blue = (unsigned char)(255.0 * db); + gl2psWriteByte(blue); + } + gl2psPrintf("\n"); + } + } + + gl2psPrintf("grestore\n"); +} + +void gl2psPrintPostScriptHeader(void){ + GLint index; + GLfloat rgba[4]; + time_t now; + +#ifdef GL2PS_HAVE_ZLIB + char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */ + 8, /* compression method: Z_DEFLATED */ + 0, /* flags */ + 0, 0, 0, 0, /* time */ + 2, /* extra flags: max compression */ + '\x03'}; /* OS code: 0x03 (Unix) */ + + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psSetupCompress(); + + /* add the gzip file header */ + fwrite(tmp, 10, 1, gl2ps->stream); + } +#endif + + time(&now); + + if(gl2ps->format == GL2PS_PS){ + gl2psPrintf("%%!PS-Adobe-3.0\n"); + } + else{ + gl2psPrintf("%%!PS-Adobe-3.0 EPSF-3.0\n"); + } + + gl2psPrintf("%%%%Title: %s\n" + "%%%%Creator: GL2PS %d.%d.%d, (C) 1999-2003 Christophe Geuzaine \n" + "%%%%For: %s\n" + "%%%%CreationDate: %s" + "%%%%LanguageLevel: 3\n" + "%%%%DocumentData: Clean7Bit\n" + "%%%%Pages: 1\n", + gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION, + gl2ps->producer, ctime(&now)); + + if(gl2ps->format == GL2PS_PS){ + gl2psPrintf("%%%%Orientation: %s\n" + "%%%%DocumentMedia: Default %d %d 0 () ()\n", + (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait", + (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : + (int)gl2ps->viewport[2], + (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : + (int)gl2ps->viewport[3]); + } + + gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n" + "%%%%EndComments\n", + (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] : + (int)gl2ps->viewport[0], + (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] : + (int)gl2ps->viewport[1], + (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : + (int)gl2ps->viewport[2], + (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : + (int)gl2ps->viewport[3]); + + /* RGB color: r g b C (replace C by G in output to change from rgb to gray) + Grayscale: r g b G + Font choose: size fontname FC + String primitive: (string) x y size fontname S + Point primitive: x y size P + Line width: width W + Flat-shaded line: x2 y2 x1 y1 L + Smooth-shaded line: x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 SL + Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T + Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */ + + gl2psPrintf("%%%%BeginProlog\n" + "/gl2psdict 64 dict def gl2psdict begin\n" + "0 setlinecap 0 setlinejoin\n" + "/tryPS3shading %s def %% set to false to force subdivision\n" + "/rThreshold %g def %% red component subdivision threshold\n" + "/gThreshold %g def %% green component subdivision threshold\n" + "/bThreshold %g def %% blue component subdivision threshold\n" + "/BD { bind def } bind def\n" + "/C { setrgbcolor } BD\n" + "/G { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n" + "/W { setlinewidth } BD\n" + "/FC { findfont exch scalefont setfont } BD\n" + "/S { FC moveto show } BD\n" + "/P { newpath 0.0 360.0 arc closepath fill } BD\n" + "/L { newpath moveto lineto stroke } BD\n" + "/SL { C moveto C lineto stroke } BD\n" + "/T { newpath moveto lineto lineto closepath fill } BD\n", + (gl2ps->options & GL2PS_NO_PS3_SHADING) ? "false" : "true", + gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]); + + /* Smooth-shaded triangle with PostScript level 3 shfill operator: + x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */ + + gl2psPrintf("/STshfill {\n" + " /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n" + " /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n" + " /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n" + " gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n" + " /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n" + " shfill grestore } BD\n"); + + /* Flat-shaded triangle with middle color: + x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */ + + gl2psPrintf(/* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */ + "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */ + /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */ + " 3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */ + /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */ + " 3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */ + /* stack : x3 y3 x2 y2 x1 y1 r g b */ + " C T } BD\n"); + + /* Split triangle in four sub-triangles (at sides middle points) and call the + STnoshfill procedure on each, interpolating the colors in RGB space: + x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit + (in procedure comments key: (Vi) = xi yi ri gi bi) */ + + gl2psPrintf("/STsplit {\n" + " 4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */ + " 4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */ + " 4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */ + " 4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */ + " 4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */ + " 5 copy 5 copy 25 15 roll\n" + /* stack : (V3) (V13) (V13) (V13) (V2) (V1) */ + " 9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */ + " 9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */ + " 9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */ + " 9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */ + " 9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */ + " 5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n" + /* stack : (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */ + " 4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */ + " 4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */ + " 4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */ + " 4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */ + " 4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */ + " 5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n" + /* stack : (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */ + " STnoshfill STnoshfill STnoshfill STnoshfill } BD\n"); + + /* Gouraud shaded triangle using recursive subdivision until the difference + between corner colors does not exceed the thresholds: + x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill */ + + gl2psPrintf("/STnoshfill {\n" + " 2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */ + " { STsplit }\n" + " { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */ + " { STsplit }\n" + " { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */ + " { STsplit }\n" + " { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */ + " { STsplit }\n" + " { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */ + " { STsplit }\n" + " { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */ + " { STsplit }\n" + " { 7 index 13 index sub abs rThreshold gt\n" /* |r2-r3|>rht */ + " { STsplit }\n" + " { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */ + " { STsplit }\n" + " { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */ + " { STsplit }\n" + " { Tm }\n" /* all colors sufficiently similar */ + " ifelse }\n" + " ifelse }\n" + " ifelse }\n" + " ifelse }\n" + " ifelse }\n" + " ifelse }\n" + " ifelse }\n" + " ifelse }\n" + " ifelse } BD\n"); + + gl2psPrintf("tryPS3shading\n" + "{ /shfill where\n" + " { /ST { STshfill } BD }\n" + " { /ST { STnoshfill } BD }\n" + " ifelse }\n" + "{ /ST { STnoshfill } BD }\n" + "ifelse\n"); + + gl2psPrintf("end\n" + "%%%%EndProlog\n" + "%%%%BeginSetup\n" + "/DeviceRGB setcolorspace\n" + "gl2psdict begin\n" + "%%%%EndSetup\n" + "%%%%Page: 1 1\n" + "%%%%BeginPageSetup\n"); + + if(gl2ps->options & GL2PS_LANDSCAPE){ + gl2psPrintf("%d 0 translate 90 rotate\n", + (int)gl2ps->viewport[3]); + } + + gl2psPrintf("%%%%EndPageSetup\n" + "mark\n" + "gsave\n" + "1.0 1.0 scale\n"); + + if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ + if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ + glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); + } + else{ + glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); + rgba[0] = gl2ps->colormap[index][0]; + rgba[1] = gl2ps->colormap[index][1]; + rgba[2] = gl2ps->colormap[index][2]; + rgba[3] = 0.0F; + } + gl2psPrintf("%g %g %g C\n" + "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" + "closepath fill\n", + rgba[0], rgba[1], rgba[2], + (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], + (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], + (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]); + } +} + +void gl2psPrintPostScriptColor(GL2PSrgba rgba){ + if(!gl2psSameColor(gl2ps->lastrgba, rgba)){ + gl2psSetLastColor(rgba); + gl2psPrintf("%g %g %g C\n", rgba[0], rgba[1], rgba[2]); + } +} + +void gl2psResetPostScriptColor(void){ + gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.; +} + +void gl2psPrintPostScriptPrimitive(void *data){ + GL2PSprimitive *prim; + + prim = *(GL2PSprimitive**)data; + + if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return; + + switch(prim->type){ + case GL2PS_PIXMAP : + gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1], + prim->data.image->width, prim->data.image->height, + prim->data.image->pixels); + break; + case GL2PS_TEXT : + gl2psPrintPostScriptColor(prim->verts[0].rgba); + gl2psPrintf("(%s) %g %g %d /%s S\n", + prim->data.text->str, prim->verts[0].xyz[0], prim->verts[0].xyz[1], + prim->data.text->fontsize, prim->data.text->fontname); + break; + case GL2PS_POINT : + gl2psPrintPostScriptColor(prim->verts[0].rgba); + gl2psPrintf("%g %g %g P\n", + prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5*prim->width); + break; + case GL2PS_LINE : + if(gl2ps->lastlinewidth != prim->width){ + gl2ps->lastlinewidth = prim->width; + gl2psPrintf("%g W\n", gl2ps->lastlinewidth); + } + if(prim->dash){ + gl2psPrintf("[%d] 0 setdash\n", prim->dash); + } + if(!gl2psVertsSameColor(prim)){ + gl2psResetPostScriptColor(); + gl2psPrintf("%g %g %g %g %g %g %g %g %g %g SL\n", + prim->verts[1].xyz[0], prim->verts[1].xyz[1], + prim->verts[1].rgba[0], prim->verts[1].rgba[1], + prim->verts[1].rgba[2], prim->verts[0].xyz[0], + prim->verts[0].xyz[1], prim->verts[0].rgba[0], + prim->verts[0].rgba[1], prim->verts[0].rgba[2]); + } + else{ + gl2psPrintPostScriptColor(prim->verts[0].rgba); + gl2psPrintf("%g %g %g %g L\n", + prim->verts[1].xyz[0], prim->verts[1].xyz[1], + prim->verts[0].xyz[0], prim->verts[0].xyz[1]); + } + if(prim->dash){ + gl2psPrintf("[] 0 setdash\n"); + } + break; + case GL2PS_TRIANGLE : + if(!gl2psVertsSameColor(prim)){ + gl2psResetPostScriptColor(); + gl2psPrintf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n", + prim->verts[2].xyz[0], prim->verts[2].xyz[1], + prim->verts[2].rgba[0], prim->verts[2].rgba[1], + prim->verts[2].rgba[2], prim->verts[1].xyz[0], + prim->verts[1].xyz[1], prim->verts[1].rgba[0], + prim->verts[1].rgba[1], prim->verts[1].rgba[2], + prim->verts[0].xyz[0], prim->verts[0].xyz[1], + prim->verts[0].rgba[0], prim->verts[0].rgba[1], + prim->verts[0].rgba[2]); + } + else{ + gl2psPrintPostScriptColor(prim->verts[0].rgba); + gl2psPrintf("%g %g %g %g %g %g T\n", + prim->verts[2].xyz[0], prim->verts[2].xyz[1], + prim->verts[1].xyz[0], prim->verts[1].xyz[1], + prim->verts[0].xyz[0], prim->verts[0].xyz[1]); + } + break; + case GL2PS_QUADRANGLE : + gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print"); + break; + default : + gl2psMsg(GL2PS_ERROR, "Unknown type of primitive to print"); + break; + } +} + +void gl2psPrintPostScriptFooter(void){ +#ifdef GL2PS_HAVE_ZLIB + int n; + uLong crc, len; + char tmp[8]; +#endif + + gl2psPrintf("grestore\n" + "showpage\n" + "cleartomark\n" + "%%%%PageTrailer\n" + "%%%%Trailer\n" + "end\n" + "%%%%EOF\n"); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + if(Z_OK != gl2psDeflate()){ + gl2psMsg(GL2PS_ERROR, "Zlib deflate error"); + } + else{ + /* determine the length of the header in the zlib stream */ + n = 2; /* CMF+FLG */ + if(gl2ps->compress->dest[1] & (1<<5)){ + n += 4; /* DICTID */ + } + /* write the data, without the zlib header and footer */ + fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4), + 1, gl2ps->stream); + /* add the gzip file footer */ + crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen); + for(n = 0; n < 4; ++n) { + tmp[n] = (char)(crc & 0xff); + crc >>= 8; + } + len = gl2ps->compress->srcLen; + for(n = 4; n < 8; ++n) { + tmp[n] = (char)(len & 0xff); + len >>= 8; + } + fwrite(tmp, 8, 1, gl2ps->stream); + } + gl2psFreeCompress(); + gl2psFree(gl2ps->compress); + gl2ps->compress = NULL; + } +#endif +} + +void gl2psPrintPostScriptBeginViewport(GLint viewport[4]){ + GLint index; + GLfloat rgba[4]; + int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; + + glRenderMode(GL_FEEDBACK); + + gl2psPrintf("gsave\n" + "1.0 1.0 scale\n"); + + if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ + if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ + glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); + } + else{ + glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); + rgba[0] = gl2ps->colormap[index][0]; + rgba[1] = gl2ps->colormap[index][1]; + rgba[2] = gl2ps->colormap[index][2]; + rgba[3] = 0.0F; + } + gl2psPrintf("%g %g %g C\n" + "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" + "closepath fill\n", + rgba[0], rgba[1], rgba[2], + x, y, x+w, y, x+w, y+h, x, y+h); + gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" + "closepath clip\n", + x, y, x+w, y, x+w, y+h, x, y+h); + } + +} + +GLint gl2psPrintPostScriptEndViewport(void){ + GLint res; + + res = gl2psPrintPrimitives(); + gl2psPrintf("grestore\n"); + return res; +} + +/********************************************************************* + * + * LaTeX routines + * + *********************************************************************/ + +void gl2psPrintTeXHeader(void){ + char name[256]; + int i; + + if(gl2ps->filename && strlen(gl2ps->filename) < 256){ + for(i = strlen(gl2ps->filename)-1; i >= 0; i--){ + if(gl2ps->filename[i] == '.'){ + strncpy(name, gl2ps->filename, i); + name[i] = '\0'; + break; + } + } + if(i <= 0) strcpy(name, gl2ps->filename); + } + else{ + strcpy(name, "untitled"); + } + + fprintf(gl2ps->stream, + "\\setlength{\\unitlength}{1pt}\n" + "\\begin{picture}(0,0)\n" + "\\includegraphics{%s}\n" + "\\end{picture}%%\n" + "%s\\begin{picture}(%d,%d)(0,0)\n", + name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "", + (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); +} + +void gl2psPrintTeXPrimitive(void *data){ + GL2PSprimitive *prim; + + prim = *(GL2PSprimitive**)data; + + switch(prim->type){ + case GL2PS_TEXT : + fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont", + prim->data.text->fontsize); + fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)", + prim->verts[0].xyz[0], prim->verts[0].xyz[1]); + switch (prim->data.text->alignment) { + case GL2PS_TEXT_CL: + fprintf(gl2ps->stream, "[l]"); + break; + case GL2PS_TEXT_CR: + fprintf(gl2ps->stream, "[r]"); + break; + case GL2PS_TEXT_B: + fprintf(gl2ps->stream, "[b]"); + break; + case GL2PS_TEXT_BL: + fprintf(gl2ps->stream, "[bl]"); + break; + case GL2PS_TEXT_BR: + fprintf(gl2ps->stream, "[br]"); + break; + case GL2PS_TEXT_T: + fprintf(gl2ps->stream, "[t]"); + break; + case GL2PS_TEXT_TL: + fprintf(gl2ps->stream, "[tl]"); + break; + case GL2PS_TEXT_TR: + fprintf(gl2ps->stream, "[tr]"); + break; + default: + break; + } + fprintf(gl2ps->stream, "{\\textcolor[rgb]{%f,%f,%f}{", + prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2]); + fprintf(gl2ps->stream, "{%s}}}}\n", prim->data.text->str); + break; + default : + break; + } +} + +void gl2psPrintTeXFooter(void){ + fprintf(gl2ps->stream, "\\end{picture}%s\n", + (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : ""); +} + +/********************************************************************* + * + * PDF routines + * + *********************************************************************/ + +int gl2psPrintPDFCompressorType(){ +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n"); + } +#endif + return 0; +} + +int gl2psPrintPDFStrokeColor(GL2PSrgba rgba){ + int offs = 0; + int i; + + gl2psSetLastColor(rgba); + for(i = 0; i < 3; ++i){ + if(GL2PS_ZERO(rgba[i])) + offs += gl2psPrintf("%.0f ", 0.); + else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ + offs += gl2psPrintf("%f ", rgba[i]); + else + offs += gl2psPrintf("%g ", rgba[i]); + } + offs += gl2psPrintf("RG\n"); + return offs; +} + +int gl2psPrintPDFFillColor(GL2PSrgba rgba){ + int offs = 0; + int i; + + for(i = 0; i < 3; ++i){ + if(GL2PS_ZERO(rgba[i])) + offs += gl2psPrintf("%.0f ", 0.); + else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ + offs += gl2psPrintf("%f ", rgba[i]); + else + offs += gl2psPrintf("%g ", rgba[i]); + } + offs += gl2psPrintf("rg\n"); + return offs; +} + +int gl2psPrintPDFLineWidth(GLfloat lw){ + if(GL2PS_ZERO(lw)) + return gl2psPrintf("%.0f w\n", 0.); + else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */ + return gl2psPrintf("%f w\n", lw); + else + return gl2psPrintf("%g w\n", lw); +} + +/* Print 1st PDF object - file info */ + +int gl2psPrintPDFInfo(){ + int offs; + time_t now; + struct tm *newtime; + + time(&now); + newtime = gmtime(&now); + + offs = fprintf(gl2ps->stream, + "1 0 obj\n" + "<<\n" + "/Title (%s)\n" + "/Creator (%s)\n" + "/Producer (GL2PS %d.%d.%d, (C) 1999-2003 Christophe Geuzaine )\n", + gl2ps->title, gl2ps->producer, + GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION); + + if(!newtime){ + offs += fprintf(gl2ps->stream, + ">>\n" + "endobj\n"); + return offs; + } + + offs += fprintf(gl2ps->stream, + "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n" + ">>\n" + "endobj\n", + newtime->tm_year+1900, + newtime->tm_mon+1, + newtime->tm_mday, + newtime->tm_hour, + newtime->tm_min, + newtime->tm_sec); + return offs; +} + +/* Create catalog and page structure - 2nd and 3th PDF object */ + +int gl2psPrintPDFCatalog(){ + return fprintf(gl2ps->stream, + "2 0 obj\n" + "<<\n" + "/Type /Catalog\n" + "/Pages 3 0 R\n" + ">>\n" + "endobj\n"); +} + +int gl2psPrintPDFPages(){ + return fprintf(gl2ps->stream, + "3 0 obj\n" + "<<\n" + "/Type /Pages\n" + "/Kids [6 0 R]\n" + "/Count 1\n" + ">>\n" + "endobj\n"); +} + +/* Open stream for data - graphical objects, fonts etc. PDF object 4*/ + +int gl2psOpenPDFDataStream(){ + int offs = 0; + + offs += fprintf(gl2ps->stream, + "4 0 obj\n" + "<<\n" + "/Length 5 0 R\n" ); + offs += gl2psPrintPDFCompressorType(); + offs += fprintf(gl2ps->stream, + ">>\n" + "stream\n"); + return offs; +} + +/* Stream setup - Graphics state, fill background if allowed */ + +int gl2psOpenPDFDataStreamWritePreface(){ + int offs; + GLint index; + GLfloat rgba[4]; + + offs = gl2psPrintf("/GS1 gs\n"); + + if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ + if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ + glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); + } + else{ + glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); + rgba[0] = gl2ps->colormap[index][0]; + rgba[1] = gl2ps->colormap[index][1]; + rgba[2] = gl2ps->colormap[index][2]; + rgba[3] = 0.0F; + } + offs += gl2psPrintPDFFillColor(rgba); + offs += gl2psPrintf("%d %d %d %d re\n", + (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], + (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); + offs += gl2psPrintf("f\n"); + } + return offs; +} + +/* Use the functions above to create the first part of the PDF*/ + +void gl2psPrintPDFHeader(){ + int offs; + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psSetupCompress(); + } +#endif + + /* tlist, tidxlist, ilist and slist contain triangles, indexes for + consecutive triangles, images and strings */ + gl2ps->tlist = gl2psListCreate(100, 100, sizeof(GL2PStriangle)); + gl2ps->tidxlist = gl2psListCreate(100, 100, sizeof(int)); + gl2ps->ilist = gl2psListCreate(100, 100, sizeof(GL2PSimage*)); + gl2ps->slist = gl2psListCreate(100, 100, sizeof(GL2PSstring*)); + + gl2ps->lasttype = GL2PS_NOTYPE; + gl2ps->consec_cnt = 0; + gl2ps->consec_inner_cnt = 0; + + offs = fprintf(gl2ps->stream, "%%PDF-1.3\n"); + gl2ps->cref[0] = offs; + + offs += gl2psPrintPDFInfo(); + gl2ps->cref[1] = offs; + + offs += gl2psPrintPDFCatalog(); + gl2ps->cref[2] = offs; + + offs += gl2psPrintPDFPages(); + gl2ps->cref[3] = offs; + + offs += gl2psOpenPDFDataStream(); + gl2ps->cref[4] = offs; /* finished in gl2psPrintPDFFooter */ + gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface(); +} + +int gl2psFlushPDFTriangles(){ + int offs = 0; + + if(gl2ps->lasttype == GL2PS_TRIANGLE && !gl2ps->last_triangle_finished){ + gl2psListAdd(gl2ps->tidxlist, &gl2ps->consec_inner_cnt); + offs = gl2psPrintf("/Sh%d sh\n", gl2ps->consec_cnt++); + gl2ps->consec_inner_cnt = 0; + gl2ps->streamlength += offs; + gl2ps->last_triangle_finished = 1; + } + return offs; +} + +int gl2psFlushPDFLines(){ + int offs = 0; + + if(gl2ps->lasttype == GL2PS_LINE && !gl2ps->last_line_finished){ + offs = gl2psPrintf("S\n"); + gl2ps->streamlength += offs; + gl2ps->last_line_finished = 1; + } + return offs; +} + +/* The central primitive drawing */ + +void gl2psPrintPDFPrimitive(void *data){ + GL2PSprimitive *prim; + GL2PStriangle t; + GL2PSimage* image; + GL2PSstring* str; + + prim = *(GL2PSprimitive**)data; + + if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return; + + if(prim->type != GL2PS_TRIANGLE) + gl2psFlushPDFTriangles(); + if(prim->type != GL2PS_LINE) + gl2psFlushPDFLines(); + + switch(prim->type){ + case GL2PS_PIXMAP : + image = gl2psCopyPixmap(prim->data.image); + gl2psListAdd(gl2ps->ilist, &image); + gl2ps->streamlength += gl2psPrintf("q\n" + "%d 0 0 %d %f %f cm\n" + "/Im%d Do\n" + "Q\n", + (int)prim->data.image->width, (int)prim->data.image->height, + prim->verts[0].xyz[0], prim->verts[0].xyz[1], + gl2psListNbr(gl2ps->ilist)-1); + break; + case GL2PS_TEXT : + str = gl2psCopyText(prim->data.text); + gl2psListAdd(gl2ps->slist, &str); + gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba); + gl2ps->streamlength += gl2psPrintf("BT\n" + "/F%d %d Tf\n" + "%f %f Td\n" + "(%s) Tj\n" + "ET\n", + gl2psListNbr(gl2ps->slist)-1, + prim->data.text->fontsize, prim->verts[0].xyz[0], + prim->verts[0].xyz[1], prim->data.text->str); + break; + case GL2PS_POINT : + if(gl2ps->lastlinewidth != prim->width){ + gl2ps->lastlinewidth = prim->width; + gl2ps->streamlength += gl2psPrintPDFLineWidth(gl2ps->lastlinewidth); + } + gl2ps->streamlength += gl2psPrintf("1 J\n"); + gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); + gl2ps->streamlength += gl2psPrintf("%f %f m %f %f l S\n", + prim->verts[0].xyz[0], prim->verts[0].xyz[1], + prim->verts[0].xyz[0], prim->verts[0].xyz[1]); + gl2ps->streamlength += gl2psPrintf("0 J\n"); + break; + case GL2PS_LINE : + gl2ps->line_width_diff = gl2ps->lastlinewidth != prim->width; + gl2ps->line_rgb_diff = !GL2PS_ZERO(gl2psColorDiff(prim->verts[0].rgba, gl2ps->lastrgba)); + + if(gl2ps->line_width_diff || gl2ps->line_rgb_diff || prim->dash){ + gl2psFlushPDFLines(); + } + if(gl2ps->line_width_diff){ + gl2ps->lastlinewidth = prim->width; + gl2ps->streamlength += gl2psPrintPDFLineWidth(gl2ps->lastlinewidth); + } + if(gl2ps->line_rgb_diff){ + gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); + } + if(prim->dash){ + gl2ps->streamlength += gl2psPrintf("[%d] 0 d\n", prim->dash); + } + gl2ps->streamlength += gl2psPrintf("%f %f m %f %f l \n", + prim->verts[0].xyz[0], prim->verts[0].xyz[1], + prim->verts[1].xyz[0], prim->verts[1].xyz[1]); + gl2ps->last_line_finished = 0; + + if(prim->dash){ + gl2ps->streamlength += gl2psPrintf("S\n[] 0 d\n"); + gl2ps->last_line_finished = 1; + } + break; + case GL2PS_TRIANGLE : + t[0] = prim->verts[0]; + t[1] = prim->verts[1]; + t[2] = prim->verts[2]; + + gl2psListAdd(gl2ps->tlist, t); + ++gl2ps->consec_inner_cnt; + gl2ps->last_triangle_finished = 0; + break; + case GL2PS_QUADRANGLE : + gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print"); + break; + default : + gl2psMsg(GL2PS_ERROR, "Unknown type of primitive to print"); + break; + } + gl2ps->lasttype = prim->type; +} + +/* close stream and ... */ + +int gl2psClosePDFDataStream(){ + int offs = 0; + + offs += gl2psFlushPDFTriangles(); + offs += gl2psFlushPDFLines(); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + if(Z_OK != gl2psDeflate()) + gl2psMsg(GL2PS_ERROR, "Zlib deflate error"); + else + fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream); + gl2ps->streamlength += gl2ps->compress->destLen; + + offs += gl2ps->streamlength; + gl2psFreeCompress(); + } +#endif + + offs += fprintf(gl2ps->stream, + "endstream\n" + "endobj\n"); + return offs; +} + +/* ... write the now known length object */ + +int gl2psPrintPDFDataStreamLength(int val){ + return fprintf(gl2ps->stream, + "5 0 obj\n" + "%d\n" + "endobj\n", val); +} + +/* Create named shader objects */ + +int gl2psPrintPDFShaderResources(int firstObject, int size){ + int offs = 0; + int i; + + offs += fprintf(gl2ps->stream, + "/Shading\n" + "<<\n"); + for(i = 0; i < size; ++i){ + offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", i, firstObject+i); + } + offs += fprintf(gl2ps->stream, ">>\n"); + return offs; +} + +/* Create named pixmap objects */ + +int gl2psPrintPDFPixmapResources(int firstObject, int size){ + int offs = 0; + int i; + + offs += fprintf(gl2ps->stream, + "/XObject\n" + "<<\n"); + for(i = 0; i < size; ++i){ + offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", i, firstObject + i); + } + offs += fprintf(gl2ps->stream, ">>\n"); + return offs; +} + +/* Create named font objects */ + +int gl2psPrintPDFTextResources(int firstObject, int size){ + int offs = 0; + int i; + + offs += fprintf(gl2ps->stream, + "/Font\n" + "<<\n"); + for(i = 0; i < size; ++i){ + offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", i, firstObject + i); + } + offs += fprintf(gl2ps->stream, ">>\n"); + return offs; +} + +/* Put the info created before in PDF objects */ + +int gl2psPrintPDFSinglePage(){ + int offs; + + offs = fprintf(gl2ps->stream, + "6 0 obj\n" + "<<\n" + "/Type /Page\n" + "/Parent 3 0 R\n" + "/MediaBox [%d %d %d %d]\n", + (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], + (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); + + if(gl2ps->options & GL2PS_LANDSCAPE) + offs += fprintf(gl2ps->stream, "/Rotate -90\n"); + + offs += fprintf(gl2ps->stream, + "/Contents 4 0 R\n" + "/Resources\n" + "<<\n" + "/ProcSet [/PDF /Text /ImageB /ImageC] %%/ImageI\n" + "/ExtGState\n" + "<<\n" + "/GS1 7 0 R\n" + ">>\n"); + + offs += gl2psPrintPDFShaderResources(GL2PS_FIXED_XREF_ENTRIES + 1, + gl2psListNbr(gl2ps->tidxlist)); + offs += gl2psPrintPDFPixmapResources(GL2PS_FIXED_XREF_ENTRIES + 1 + + gl2psListNbr(gl2ps->tidxlist), + gl2psListNbr(gl2ps->ilist)); + offs += gl2psPrintPDFTextResources(GL2PS_FIXED_XREF_ENTRIES + 1 + + gl2psListNbr(gl2ps->tidxlist) + + gl2psListNbr(gl2ps->ilist), + gl2psListNbr(gl2ps->slist)); + offs += fprintf(gl2ps->stream, + ">>\n" + ">>\n" + "endobj\n"); + return offs; +} + +/* Extended graphics state for shading */ + +int gl2psPrintPDFExtGState(){ + return fprintf(gl2ps->stream, + "7 0 obj\n" + "<<\n" + "/Type /ExtGState\n" + "/SA false\n" + "/SM 0.02\n" + "/OP false\n" + "/op false\n" + "/OPM 0\n" + "/BG2 /Default\n" + "/UCR2 /Default\n" + "/TR2 /Default\n" + ">>\n" + "endobj\n"); +} + +/* Put a triangles raw data in shader stream */ + +int gl2psPrintPDFShaderStreamData(GL2PStriangle triangle, + size_t (*action)(unsigned long data, size_t size)){ + int offs = 0; + int i; + unsigned long imap; + GLfloat diff, dx, dy; + char edgeflag = 0; + double dmax = ~1UL; + + dx = (GLfloat)(gl2ps->viewport[2] - gl2ps->viewport[0]); + dy = (GLfloat)(gl2ps->viewport[3] - gl2ps->viewport[1]); + + for(i = 0; i < 3; ++i){ + offs += (*action)(edgeflag, 1); + + /* The Shader stream in PDF requires to be in a 'big-endian' + order */ + + if(fabs(dx*dy) < FLT_MIN){ + offs += (*action)(0, 4); + offs += (*action)(0, 4); + } + else{ + diff = (triangle[i].xyz[0] - gl2ps->viewport[0]) / dx; + if(diff > 1) + diff = 1; + else if(diff < 0) + diff = 0; + imap = (unsigned long)(diff * dmax); + offs += (*action)(imap, 4); + + diff = (triangle[i].xyz[1] - gl2ps->viewport[1]) / dy; + if(diff > 1) + diff = 1; + else if(diff < 0) + diff = 0; + imap = (unsigned long)(diff * dmax); + offs += (*action)(imap, 4); + } + + imap = (unsigned long)(triangle[i].rgba[0] * dmax); + offs += (*action)(imap, 1); + + imap = (unsigned long)(triangle[i].rgba[1] * dmax); + offs += (*action)(imap, 1); + + imap = (unsigned long)(triangle[i].rgba[2] * dmax); + offs += (*action)(imap, 1); + } + return offs; +} + + +/* Writes shaded triangle */ + +int gl2psPrintPDFShader(int obj, GL2PSlist* triangles, int idx, int cnt ){ + int offs = 0; + int vertexbytes = 1+4+4+1+1+1; + int i, done = 0; + + offs += fprintf(gl2ps->stream, + "%d 0 obj\n" + "<< " + "/ShadingType 4 " + "/ColorSpace /DeviceRGB " + "/BitsPerCoordinate 32 " + "/BitsPerComponent 8 " + "/BitsPerFlag 8 " + "/Decode [%d %d %d %d 0 1 0 1 0 1] ", + obj, + (int)gl2ps->viewport[0], (int)gl2ps->viewport[2], + (int)gl2ps->viewport[1], (int)gl2ps->viewport[3]); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psAllocCompress(vertexbytes * cnt * 3); + + for(i = 0; i < cnt; ++i) + gl2psPrintPDFShaderStreamData((GL2PSvertex*)gl2psListPointer(triangles, idx+i), + gl2psWriteBigEndianCompress); + + if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){ + offs += gl2psPrintPDFCompressorType(); + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + (int)gl2ps->compress->destLen); + offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, + 1, gl2ps->stream); + done = 1; + } + gl2psFreeCompress(); + } +#endif + + if(!done){ + /* no compression, or too long after compression, or compress error + -> write non-compressed entry */ + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + vertexbytes * 3 * cnt); + for(i = 0; i < cnt; ++i) + offs += gl2psPrintPDFShaderStreamData((GL2PSvertex*)gl2psListPointer(triangles, idx+i), + gl2psWriteBigEndian); + } + + offs += fprintf(gl2ps->stream, + "\nendstream\n" + "endobj\n"); + + return offs; +} + +/* Writes all triangles and returns field of offsets for the PDF cross + reference table */ + +int* gl2psPrintPDFShaderObjects(int firstObjnumber, int firstOffs){ + int size; + int* offs; + int i; + int idx = 0; + int tmp; + + size = gl2psListNbr(gl2ps->tidxlist); + offs = (int*)gl2psMalloc(sizeof(int) * (size+1)); + + offs[0] = firstOffs; + + for(i = 0; i < size; ++i){ + gl2psListRead(gl2ps->tidxlist, i, &tmp); + firstOffs += gl2psPrintPDFShader(i+firstObjnumber, gl2ps->tlist, idx, tmp); + offs[i+1] = firstOffs; + idx += tmp; + } + return offs; +} + +/* Similar groups of functions for pixmaps and text */ + +int gl2psPrintPDFPixmapStreamData(GL2PSimage* im, + size_t (*action)(unsigned long data, size_t size)){ + int x, y; + GLfloat r, g, b; + + for(y = 0; y < im->height; ++y) + for(x = 0; x < im->width; ++x){ + gl2psGetRGB(im->pixels, im->width, im->height, x, y, &r, &g, &b); + (*action)((unsigned long)(r*255) << 24,1); + (*action)((unsigned long)(g*255) << 24,1); + (*action)((unsigned long)(b*255) << 24,1); + } + return 3 * im->width * im->height; +} + +int gl2psPrintPDFPixmap(int obj, GL2PSimage* im){ + int offs = 0, done = 0; + + offs += fprintf(gl2ps->stream, + "%d 0 obj\n" + "<<\n" + "/Type /XObject\n" + "/Subtype /Image\n" + "/Width %d\n" + "/Height %d\n" + "/ColorSpace /DeviceRGB\n" + "/BitsPerComponent 8\n", + obj, (int)im->width, (int)im->height); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psAllocCompress((int)(im->width * im->height * 3)); + + gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress); + + if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){ + offs += gl2psPrintPDFCompressorType(); + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + (int)gl2ps->compress->destLen); + offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, + 1, gl2ps->stream); + done = 1; + } + gl2psFreeCompress(); + } +#endif + + if(!done){ + /* no compression, or too long after compression, or compress error + -> write non-compressed entry */ + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + (int)(im->width * im->height * 3)); + offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian); + } + + offs += fprintf(gl2ps->stream, + "\nendstream\n" + "endobj\n"); + + return offs; +} + +int* gl2psPrintPDFPixmapObjects(int firstObjnumber, int firstOffs){ + int size; + int* offs; + int i; + + size = gl2psListNbr(gl2ps->ilist); + offs = (int*)gl2psMalloc(sizeof(int) * (size+1)); + + offs[0] = firstOffs; + + for(i = 0; i < size; ++i){ + firstOffs += gl2psPrintPDFPixmap(i+firstObjnumber, + *(GL2PSimage**)gl2psListPointer(gl2ps->ilist, i)); + offs[i+1] = firstOffs; + } + return offs; +} + +int gl2psPrintPDFText(int obj, GL2PSstring* s, int fontnumber){ + int offs = 0; + + offs += fprintf(gl2ps->stream, + "%d 0 obj\n" + "<<\n" + "/Type /Font\n" + "/Subtype /Type1\n" + "/Name /F%d\n" + "/BaseFont /%s\n" + "/Encoding /MacRomanEncoding\n" + ">>\n" + "endobj\n", + obj, fontnumber, s->fontname); + return offs; +} + +int* gl2psPrintPDFTextObjects(int firstObjnumber, int firstOffs){ + int size; + int* offs; + int i; + + size = gl2psListNbr(gl2ps->slist); + offs = (int*)gl2psMalloc(sizeof(int) * (size+1)); + + offs[0] = firstOffs; + + for(i = 0; i < size; ++i){ + firstOffs += gl2psPrintPDFText(i+firstObjnumber, + *(GL2PSstring**)gl2psListPointer(gl2ps->slist, i), i); + offs[i+1] = firstOffs; + } + return offs; +} + +/* All variable data is written at this point and all required + functioninality has been gathered: Writes file footer with cross + reference table and trailer */ + +void gl2psPrintPDFFooter(){ + int offs; + int i; + int *shader_offs, *image_offs, *text_offs; + int shader_size, image_size, text_size, objnumber, lastoffset; + + offs = gl2ps->cref[4] + gl2ps->streamlength; + offs += gl2psClosePDFDataStream(); + gl2ps->cref[4] = offs; + + offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength); + gl2ps->cref[5] = offs; + gl2ps->streamlength = 0; + + offs += gl2psPrintPDFSinglePage(); + gl2ps->cref[6] = offs; + + offs += gl2psPrintPDFExtGState(); + + shader_size = gl2psListNbr(gl2ps->tidxlist); + image_size = gl2psListNbr(gl2ps->ilist); + text_size = gl2psListNbr(gl2ps->slist); + + shader_offs = gl2psPrintPDFShaderObjects(GL2PS_FIXED_XREF_ENTRIES + 1, offs); + image_offs = gl2psPrintPDFPixmapObjects(GL2PS_FIXED_XREF_ENTRIES + 1 + shader_size, + shader_offs[shader_size]); + text_offs = gl2psPrintPDFTextObjects(GL2PS_FIXED_XREF_ENTRIES + 1 + shader_size + image_size, + image_offs[image_size]); + + lastoffset = text_offs[text_size]; + objnumber = GL2PS_FIXED_XREF_ENTRIES + shader_size + image_size + text_size + 1; + + /* Start cross reference table. The file has to been opened in + binary mode to preserve the 20 digit string length! */ + fprintf(gl2ps->stream, + "xref\n" + "0 %d\n" + "%010d 65535 f \n", objnumber, 0); + + for(i = 0; i < GL2PS_FIXED_XREF_ENTRIES; ++i){ + fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->cref[i]); + } + for(i = 0; i < shader_size; ++i){ + fprintf(gl2ps->stream, "%010d 00000 n \n", shader_offs[i]); + } + for(i = 0; i < image_size; ++i){ + fprintf(gl2ps->stream, "%010d 00000 n \n", image_offs[i]); + } + for(i = 0; i < text_size; ++i){ + fprintf(gl2ps->stream, "%010d 00000 n \n", text_offs[i]); + } + + fprintf(gl2ps->stream, + "trailer\n" + "<<\n" + "/Size %d\n" + "/Info 1 0 R\n" + "/Root 2 0 R\n" + ">>\n" + "startxref\n%d\n" + "%%%%EOF\n", + objnumber, lastoffset); + + /* Free auxiliary lists and arrays */ + gl2psFree(shader_offs); + gl2psFree(image_offs); + gl2psFree(text_offs); + gl2psListDelete(gl2ps->tlist); + gl2psListDelete(gl2ps->tidxlist); + for(i = 0; i < gl2psListNbr(gl2ps->ilist); ++i) + gl2psFreePixmap(*(GL2PSimage**)gl2psListPointer(gl2ps->ilist, i)); + gl2psListDelete(gl2ps->ilist); + for(i = 0; i < gl2psListNbr(gl2ps->slist); ++i) + gl2psFreeText(*(GL2PSstring**)gl2psListPointer(gl2ps->slist, i)); + gl2psListDelete(gl2ps->slist); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psFreeCompress(); + gl2psFree(gl2ps->compress); + gl2ps->compress = NULL; + } +#endif +} + +/* PDF begin viewport */ + +void gl2psPrintPDFBeginViewport(GLint viewport[4]){ + int offs; + GLint index; + GLfloat rgba[4]; + int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; + + offs = 0; + + glRenderMode(GL_FEEDBACK); + + offs += gl2psPrintf("q\n"); + + if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ + if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ + glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); + } + else{ + glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); + rgba[0] = gl2ps->colormap[index][0]; + rgba[1] = gl2ps->colormap[index][1]; + rgba[2] = gl2ps->colormap[index][2]; + rgba[3] = 0.; + } + offs += gl2psPrintf("%f %f %f rg\n" + "%d %d %d %d re\n" + "W\n" + "f\n", + rgba[0], rgba[1], rgba[2], x, y, w, h); + } + else{ + offs += gl2psPrintf("%d %d %d %d re\n" + "W\n" + "n\n", + x, y, w, h); + } + + gl2ps->streamlength += offs; +} + +GLint gl2psPrintPDFEndViewport(){ + GLint res; + + res = gl2psPrintPrimitives(); + res += gl2psFlushPDFTriangles(); + res += gl2psFlushPDFLines(); + + gl2ps->streamlength += gl2psPrintf("Q\n"); + + return res; +} + +/********************************************************************* + * + * General primitive printing routine + * + *********************************************************************/ + +GLint gl2psPrintPrimitives(void){ + GL2PSbsptree *root; + GL2PSxyz eye = {0.0F, 0.0F, 100000.0F}; + GLint used; + void (*pprim)(void *data) = 0; + + used = glRenderMode(GL_RENDER); + + if(used < 0){ + gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow"); + return GL2PS_OVERFLOW; + } + + if(used == 0){ + return GL2PS_NO_FEEDBACK; /* Empty feedback buffer */ + } + + if(gl2ps->format == GL2PS_PS || + gl2ps->format == GL2PS_EPS || + gl2ps->format == GL2PS_PDF){ + gl2psParseFeedbackBuffer(used); + } + + if(!gl2psListNbr(gl2ps->primitives)){ + return GL2PS_SUCCESS; /* Nothing to print */ + } + + switch(gl2ps->format){ + case GL2PS_TEX : + pprim = gl2psPrintTeXPrimitive; + break; + case GL2PS_PS : + case GL2PS_EPS : + pprim = gl2psPrintPostScriptPrimitive; + break; + case GL2PS_PDF : + pprim = gl2psPrintPDFPrimitive; + break; + } + + switch(gl2ps->sort){ + case GL2PS_NO_SORT : + gl2psListAction(gl2ps->primitives, pprim); + gl2psListAction(gl2ps->primitives, gl2psFreePrimitive); + /* reset the primitive list, waiting for the next viewport */ + gl2psListReset(gl2ps->primitives); + break; + case GL2PS_SIMPLE_SORT : + gl2psListSort(gl2ps->primitives, gl2psCompareDepth); + if(gl2ps->options & GL2PS_OCCLUSION_CULL){ + gl2psListAction(gl2ps->primitives, gl2psAddInImageTree); + gl2psFreeBspImageTree(&gl2ps->imagetree); + } + gl2psListActionInverse(gl2ps->primitives, pprim); + gl2psListAction(gl2ps->primitives, gl2psFreePrimitive); + /* reset the primitive list, waiting for the next viewport */ + gl2psListReset(gl2ps->primitives); + break; + case GL2PS_BSP_SORT : + root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree)); + gl2psBuildBspTree(root, gl2ps->primitives); + if(gl2ps->boundary) gl2psBuildPolygonBoundary(root); + if(gl2ps->options & GL2PS_OCCLUSION_CULL){ + gl2psTraverseBspTree(root, eye, -(float)GL2PS_EPSILON, gl2psLess, + gl2psAddInImageTree, 1); + gl2psFreeBspImageTree(&gl2ps->imagetree); + } + gl2psTraverseBspTree(root, eye, (float)GL2PS_EPSILON, gl2psGreater, + pprim, 0); + gl2psFreeBspTree(&root); + /* reallocate the primitive list (it's been deleted by + gl2psBuildBspTree) in case there is another viewport */ + gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); + break; + default : + gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", gl2ps->sort); + return GL2PS_ERROR; + } + + fflush(gl2ps->stream); + + return GL2PS_SUCCESS; +} + +/********************************************************************* + * + * Public routines + * + *********************************************************************/ + +GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, + GLint viewport[4], GLint format, GLint sort, + GLint options, GLint colormode, + GLint colorsize, GL2PSrgba *colormap, + GLint nr, GLint ng, GLint nb, GLint buffersize, + FILE *stream, const char *filename){ + int i; + + gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext)); + gl2ps->maxbestroot = 10; + gl2ps->format = format; + gl2ps->title = title; + gl2ps->producer = producer; + gl2ps->filename = filename; + gl2ps->sort = sort; + gl2ps->options = options; + gl2ps->compress = NULL; + + if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){ + glGetIntegerv(GL_VIEWPORT, gl2ps->viewport); + } + else{ + for(i = 0; i < 4; i++){ + gl2ps->viewport[i] = viewport[i]; + } + } + gl2ps->threshold[0] = nr ? 1.0F/(GLfloat)nr : 0.032F; + gl2ps->threshold[1] = ng ? 1.0F/(GLfloat)ng : 0.017F; + gl2ps->threshold[2] = nb ? 1.0F/(GLfloat)nb : 0.050F; + gl2ps->colormode = colormode; + gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048; + for(i = 0; i < 4; i++){ + gl2ps->lastrgba[i] = -1.0F; + } + gl2ps->lastlinewidth = -1.0F; + gl2ps->imagetree = NULL; + gl2ps->primitivetoadd = NULL; + gl2ps->zerosurfacearea = 0; + + if(gl2ps->colormode == GL_RGBA){ + gl2ps->colorsize = 0; + gl2ps->colormap = NULL; + } + else if(gl2ps->colormode == GL_COLOR_INDEX){ + if(!colorsize || !colormap){ + gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering"); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + gl2ps->colorsize = colorsize; + gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba)); + memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba)); + } + else{ + gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage"); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + + if(!stream){ + gl2psMsg(GL2PS_ERROR, "Bad file pointer"); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + else{ + gl2ps->stream = stream; + /* In case gl2psEndPage failed (e.g. due to a GL2PS_OVERFLOW) and + we didn't reopen the stream before calling gl2psBeginPage + again, we need to rewind the stream */ + rewind(gl2ps->stream); + } + + /* only used for PDF output... */ + gl2ps->lasttype = -1; + gl2ps->consec_cnt = 0; + gl2ps->consec_inner_cnt = 1; + gl2ps->line_width_diff = 1; + gl2ps->line_rgb_diff = 1; + gl2ps->last_line_finished = 0; + gl2ps->last_triangle_finished = 0; + + switch(gl2ps->format){ + case GL2PS_TEX : + gl2psPrintTeXHeader(); + break; + case GL2PS_PS : + case GL2PS_EPS : + gl2psPrintPostScriptHeader(); + break; + case GL2PS_PDF : + gl2psPrintPDFHeader(); + break; + default : + gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", gl2ps->format); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + + gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); + gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat)); + glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback); + glRenderMode(GL_FEEDBACK); + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psEndPage(void){ + GLint res; + + if(!gl2ps) return GL2PS_UNINITIALIZED; + + res = gl2psPrintPrimitives(); + + /* print the footer even if gl2psPrintPrimitives didn't succeed, so + that we end up with a valid file */ + switch(gl2ps->format){ + case GL2PS_TEX : + gl2psPrintTeXFooter(); + break; + case GL2PS_PS : + case GL2PS_EPS : + gl2psPrintPostScriptFooter(); + break; + case GL2PS_PDF : + gl2psPrintPDFFooter(); + break; + } + + fflush(gl2ps->stream); + + gl2psListDelete(gl2ps->primitives); + gl2psFree(gl2ps->colormap); + gl2psFree(gl2ps->feedback); + gl2psFree(gl2ps); + gl2ps = NULL; + + return res; +} + +GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]){ + if(!gl2ps) return GL2PS_UNINITIALIZED; + + switch(gl2ps->format){ + case GL2PS_PS : + case GL2PS_EPS : + gl2psPrintPostScriptBeginViewport(viewport); + break; + case GL2PS_PDF : + gl2psPrintPDFBeginViewport(viewport); + break; + default : + break; + } + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psEndViewport(void){ + GLint res; + + if(!gl2ps) return GL2PS_UNINITIALIZED; + + switch(gl2ps->format){ + case GL2PS_PS : + case GL2PS_EPS : + res = gl2psPrintPostScriptEndViewport(); + break; + case GL2PS_PDF : + res = gl2psPrintPDFEndViewport(); + break; + default : + res = GL2PS_SUCCESS; + break; + } + + return res; +} + +GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, GLshort fontsize, + GLint alignment, GL2PSrgba rgba){ + GLfloat pos[4]; + GL2PSprimitive *prim; + GLboolean valid; + + if(!gl2ps || !str) return GL2PS_UNINITIALIZED; + + if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS; + + glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid); + if(!valid) return GL2PS_SUCCESS; /* the primitive is culled */ + + glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); + + prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive)); + prim->type = GL2PS_TEXT; + prim->boundary = 0; + prim->numverts = 1; + prim->verts = (GL2PSvertex *)gl2psMalloc(sizeof(GL2PSvertex)); + prim->verts[0].xyz[0] = pos[0]; + prim->verts[0].xyz[1] = pos[1]; + prim->verts[0].xyz[2] = GL2PS_DEPTH_FACT * pos[2]; + prim->depth = pos[2]; + prim->culled = 0; + prim->dash = 0; + prim->width = 1; + if(rgba){ + prim->verts[0].rgba[0] = rgba[0]; + prim->verts[0].rgba[1] = rgba[1]; + prim->verts[0].rgba[2] = rgba[2]; + prim->verts[0].rgba[3] = rgba[3]; + } + else{ + glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); + } + prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); + prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char)); + strcpy(prim->data.text->str, str); + prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char)); + strcpy(prim->data.text->fontname, fontname); + prim->data.text->fontsize = fontsize; + prim->data.text->alignment = alignment; + + gl2psListAdd(gl2ps->primitives, &prim); + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize){ + return gl2psTextOpt(str, fontname, fontsize, GL2PS_TEXT_BL, NULL); +} + +GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, + GLint xorig, GLint yorig, + GLenum format, GLenum type, + const void *pixels){ + int size; + GLfloat pos[4]; + GL2PSprimitive *prim; + GLboolean valid; + + if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED; + + if((width <= 0) || (height <= 0)) return GL2PS_ERROR; + + if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS; + + if(format != GL_RGB || type != GL_FLOAT){ + gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for GL_RGB, GL_FLOAT pixels"); + return GL2PS_ERROR; + } + + glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid); + if(!valid) return GL2PS_SUCCESS; /* the primitive is culled */ + + glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); + + prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive)); + prim->type = GL2PS_PIXMAP; + prim->boundary = 0; + prim->numverts = 1; + prim->verts = (GL2PSvertex *)gl2psMalloc(sizeof(GL2PSvertex)); + prim->verts[0].xyz[0] = pos[0] + xorig; + prim->verts[0].xyz[1] = pos[1] + yorig; + prim->verts[0].xyz[2] = GL2PS_DEPTH_FACT * pos[2]; + prim->depth = pos[2]; + prim->culled = 0; + prim->dash = 0; + prim->width = 1; + glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); + prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); + prim->data.image->width = width; + prim->data.image->height = height; + prim->data.image->format = format; + prim->data.image->type = type; + size = height*width*3*sizeof(GLfloat); /* FIXME: handle other types/formats */ + prim->data.image->pixels = (GLfloat*)gl2psMalloc(size); + memcpy(prim->data.image->pixels, pixels, size); + + gl2psListAdd(gl2ps->primitives, &prim); + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psEnable(GLint mode){ + if(!gl2ps) return GL2PS_UNINITIALIZED; + + switch(mode){ + case GL2PS_POLYGON_OFFSET_FILL : + glPassThrough(GL2PS_BEGIN_POLYGON_OFFSET_FILL); + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]); + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]); + break; + case GL2PS_POLYGON_BOUNDARY : + glPassThrough(GL2PS_BEGIN_POLYGON_BOUNDARY); + break; + case GL2PS_LINE_STIPPLE : + glPassThrough(GL2PS_BEGIN_LINE_STIPPLE); + break; + default : + gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode); + return GL2PS_WARNING; + } + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psDisable(GLint mode){ + if(!gl2ps) return GL2PS_UNINITIALIZED; + + switch(mode){ + case GL2PS_POLYGON_OFFSET_FILL : + glPassThrough(GL2PS_END_POLYGON_OFFSET_FILL); + break; + case GL2PS_POLYGON_BOUNDARY : + glPassThrough(GL2PS_END_POLYGON_BOUNDARY); + break; + case GL2PS_LINE_STIPPLE : + glPassThrough(GL2PS_END_LINE_STIPPLE); + break; + default : + gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode); + return GL2PS_WARNING; + } + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psPointSize(GLfloat value){ + if(!gl2ps) return GL2PS_UNINITIALIZED; + + glPassThrough(GL2PS_SET_POINT_SIZE); + glPassThrough(value); + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psLineWidth(GLfloat value){ + if(!gl2ps) return GL2PS_UNINITIALIZED; + + glPassThrough(GL2PS_SET_LINE_WIDTH); + glPassThrough(value); + + return GL2PS_SUCCESS; +} diff --git a/Utilities/gl2ps/gl2ps.h b/Utilities/gl2ps/gl2ps.h new file mode 100644 index 0000000..c3d5f8f --- /dev/null +++ b/Utilities/gl2ps/gl2ps.h @@ -0,0 +1,315 @@ +/* $Id: gl2ps.h,v 1.4 2004/04/30 17:18:30 king Exp $ */ +/* + * GL2PS, an OpenGL to PostScript Printing Library + * Copyright (C) 1999-2003 Christophe Geuzaine + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of either: + * + * a) 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; or + * + * b) the GL2PS License as published by Christophe Geuzaine, either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either + * the GNU Library General Public License or the GL2PS License for + * more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library in the file named "COPYING.LGPL"; + * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + * + * You should have received a copy of the GL2PS License with this + * library in the file named "COPYING.GL2PS"; if not, I will be glad + * to provide one. + * + * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/. + * Please report all bugs and problems to . + */ + +#ifndef __GL2PS_H__ +#define __GL2PS_H__ + +#include +#include +#include + +/* To generate a Windows dll, define GL2PSDLL at compile time */ + + +#ifdef WIN32 +# if defined(_MSC_VER) +/* shut up warning due to bad windows header file */ +# pragma warning ( disable : 4115 ) +# endif +# include +# ifdef GL2PSDLL +# ifdef GL2PSDLL_EXPORTS +# define GL2PSDLL_API __declspec(dllexport) +# else +# define GL2PSDLL_API __declspec(dllimport) +# endif +# else +# define GL2PSDLL_API +# endif +#else +# define GL2PSDLL_API +#endif + +#ifdef __APPLE__ +# include +#else +# include +#endif + +/* Support for compressed PDF */ + +#if defined(HAVE_ZLIB) || defined(HAVE_LIBZ) || defined(GL2PS_HAVE_ZLIB) +# include "vtk_zlib.h" +# ifndef GL2PS_HAVE_ZLIB +# define GL2PS_HAVE_ZLIB +# endif +#endif + +/* Version number */ + +#define GL2PS_MAJOR_VERSION 1 +#define GL2PS_MINOR_VERSION 1 +#define GL2PS_PATCH_VERSION 2 + +#define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \ + 0.01 * GL2PS_MINOR_VERSION + \ + 0.0001 * GL2PS_PATCH_VERSION) + +/* Output file format */ + +#define GL2PS_PS 1 +#define GL2PS_EPS 2 +#define GL2PS_TEX 3 +#define GL2PS_PDF 4 + +/* Sorting algorithms */ + +#define GL2PS_NO_SORT 1 +#define GL2PS_SIMPLE_SORT 2 +#define GL2PS_BSP_SORT 3 + +/* Options for gl2psBeginPage */ + +#define GL2PS_NONE 0 +#define GL2PS_DRAW_BACKGROUND (1<<0) +#define GL2PS_SIMPLE_LINE_OFFSET (1<<1) +#define GL2PS_SILENT (1<<2) +#define GL2PS_BEST_ROOT (1<<3) +#define GL2PS_OCCLUSION_CULL (1<<4) +#define GL2PS_NO_TEXT (1<<5) +#define GL2PS_LANDSCAPE (1<<6) +#define GL2PS_NO_PS3_SHADING (1<<7) +#define GL2PS_NO_PIXMAP (1<<8) +#define GL2PS_USE_CURRENT_VIEWPORT (1<<9) +#define GL2PS_COMPRESS (1<<10) + +/* Arguments for gl2psEnable/gl2psDisable */ + +#define GL2PS_POLYGON_OFFSET_FILL 1 +#define GL2PS_POLYGON_BOUNDARY 2 +#define GL2PS_LINE_STIPPLE 3 + +/* Magic numbers */ + +#define GL2PS_EPSILON 5.0e-3F +#define GL2PS_DEPTH_FACT 1000.0F +#define GL2PS_SIMPLE_OFFSET 0.05F +#define GL2PS_SIMPLE_OFFSET_LARGE 1.0F +#define GL2PS_ZERO(arg) (fabs(arg)<1.e-20) +#define GL2PS_FIXED_XREF_ENTRIES 7 + +/* Message levels and error codes */ + +#define GL2PS_SUCCESS 0 +#define GL2PS_INFO 1 +#define GL2PS_WARNING 2 +#define GL2PS_ERROR 3 +#define GL2PS_NO_FEEDBACK 4 +#define GL2PS_OVERFLOW 5 +#define GL2PS_UNINITIALIZED 6 + +/* Primitive types */ + +#define GL2PS_NOTYPE -1 +#define GL2PS_TEXT 1 +#define GL2PS_POINT 2 +#define GL2PS_LINE 3 +#define GL2PS_QUADRANGLE 4 +#define GL2PS_TRIANGLE 5 +#define GL2PS_PIXMAP 6 + +/* Text alignment */ + +#define GL2PS_TEXT_C 1 +#define GL2PS_TEXT_CL 2 +#define GL2PS_TEXT_CR 3 +#define GL2PS_TEXT_B 4 +#define GL2PS_TEXT_BL 5 +#define GL2PS_TEXT_BR 6 +#define GL2PS_TEXT_T 7 +#define GL2PS_TEXT_TL 8 +#define GL2PS_TEXT_TR 9 + +/* BSP tree primitive comparison */ + +#define GL2PS_COINCIDENT 1 +#define GL2PS_IN_FRONT_OF 2 +#define GL2PS_IN_BACK_OF 3 +#define GL2PS_SPANNING 4 + +/* 2D BSP tree primitive comparison */ + +#define GL2PS_POINT_COINCIDENT 0 +#define GL2PS_POINT_INFRONT 1 +#define GL2PS_POINT_BACK 2 + +/* Pass through options */ + +#define GL2PS_BEGIN_POLYGON_OFFSET_FILL 1 +#define GL2PS_END_POLYGON_OFFSET_FILL 2 +#define GL2PS_BEGIN_POLYGON_BOUNDARY 3 +#define GL2PS_END_POLYGON_BOUNDARY 4 +#define GL2PS_BEGIN_LINE_STIPPLE 5 +#define GL2PS_END_LINE_STIPPLE 6 +#define GL2PS_SET_POINT_SIZE 7 +#define GL2PS_SET_LINE_WIDTH 8 + +typedef GLfloat GL2PSrgba[4]; +typedef GLfloat GL2PSxyz[3]; +typedef GLfloat GL2PSplane[4]; + +typedef struct _GL2PSbsptree2d GL2PSbsptree2d; + +struct _GL2PSbsptree2d { + GL2PSplane plane; + GL2PSbsptree2d *front, *back; +}; + +typedef struct { + GLint nmax, size, incr, n; + char *array; +} GL2PSlist; + +typedef struct _GL2PSbsptree GL2PSbsptree; + +struct _GL2PSbsptree { + GL2PSplane plane; + GL2PSlist *primitives; + GL2PSbsptree *front, *back; +}; + +typedef struct { + GL2PSxyz xyz; + GL2PSrgba rgba; +} GL2PSvertex; + +typedef GL2PSvertex GL2PStriangle[3]; + +typedef struct { + GLshort fontsize; + char *str, *fontname; + GLint alignment; +} GL2PSstring; + +typedef struct { + GLsizei width, height; + GLenum format, type; + GLfloat *pixels; +} GL2PSimage; + +typedef struct { + GLshort type, numverts; + char boundary, dash, culled; + GLfloat width, depth; + GL2PSvertex *verts; + union { + GL2PSstring *text; + GL2PSimage *image; + } data; +} GL2PSprimitive; + +typedef struct { +#ifdef GL2PS_HAVE_ZLIB + Bytef *dest, *src, *start; + uLongf destLen, srcLen; +#else + int dummy; +#endif +} GL2PScompress; + +typedef struct { + /* general */ + GLint format, sort, options, colorsize, colormode, buffersize; + const char *title, *producer, *filename; + GLboolean boundary; + GLfloat *feedback, offset[2], lastlinewidth; + GLint viewport[4]; + GL2PSrgba *colormap, lastrgba, threshold; + GL2PSlist *primitives; + FILE *stream; + GL2PScompress *compress; + + /* BSP-specific */ + GLint maxbestroot; + + /* occlusion culling-specific */ + GLboolean zerosurfacearea; + GL2PSbsptree2d *imagetree; + GL2PSprimitive *primitivetoadd; + + /* PDF-specific */ + int cref[GL2PS_FIXED_XREF_ENTRIES]; + int streamlength; + GL2PSlist *tlist, *tidxlist, *ilist, *slist; + int lasttype, consec_cnt, consec_inner_cnt; + int line_width_diff, line_rgb_diff, last_line_finished, last_triangle_finished; +} GL2PScontext; + +/* private prototypes */ + +GLint gl2psPrintPrimitives(void); + +/* public functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, + GLint viewport[4], GLint format, GLint sort, + GLint options, GLint colormode, + GLint colorsize, GL2PSrgba *colormap, + GLint nr, GLint ng, GLint nb, GLint buffersize, + FILE *stream, const char *filename); +GL2PSDLL_API GLint gl2psEndPage(void); +GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]); +GL2PSDLL_API GLint gl2psEndViewport(void); +GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize); +GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, + GLint xorig, GLint yorig, + GLenum format, GLenum type, const void *pixels); +GL2PSDLL_API GLint gl2psEnable(GLint mode); +GL2PSDLL_API GLint gl2psDisable(GLint mode); +GL2PSDLL_API GLint gl2psPointSize(GLfloat value); +GL2PSDLL_API GLint gl2psLineWidth(GLfloat value); + +/* Undocumented */ +GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, GLshort fontsize, + GLint align, GL2PSrgba color); + +#ifdef __cplusplus +}; +#endif + +#endif /* __GL2PS_H__ */ diff --git a/Utilities/internal_stdio_core.h.in b/Utilities/internal_stdio_core.h.in new file mode 100644 index 0000000..ae5910c --- /dev/null +++ b/Utilities/internal_stdio_core.h.in @@ -0,0 +1,5 @@ +/* This is a hack to work around a bug in MIPSpro 7.4 on some SGIs. + We need to include stdarg.h before the stdio core to avoid putting + va_list in the std namespace and never in the global namespace. */ +#include +#include_next diff --git a/Utilities/kwsys/Base64.c b/Utilities/kwsys/Base64.c new file mode 100644 index 0000000..7af6d8c --- /dev/null +++ b/Utilities/kwsys/Base64.c @@ -0,0 +1,281 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Base64.c,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Base64.h) + +/* Work-around CMake dependency scanning limitation. This must + duplicate the above list of headers. */ +#if 0 +# include "Base64.h.in" +#endif + +/*--------------------------------------------------------------------------*/ +static const unsigned char kwsysBase64EncodeTable[65] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"abcdefghijklmnopqrstuvwxyz" +"0123456789+/"; + +/*--------------------------------------------------------------------------*/ +static const unsigned char kwsysBase64DecodeTable[256] = +{ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0x3E,0xFF,0xFF,0xFF,0x3F, + 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, + 0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF, + 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, + 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, + 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20, + 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, + 0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30, + 0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF, + /*------------------------------------*/ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF +}; + +/*--------------------------------------------------------------------------*/ +static unsigned char kwsysBase64EncodeChar(int c) +{ + return kwsysBase64EncodeTable[(unsigned char)c]; +} + +/*--------------------------------------------------------------------------*/ +static unsigned char kwsysBase64DecodeChar(unsigned char c) +{ + return kwsysBase64DecodeTable[c]; +} + +/*--------------------------------------------------------------------------*/ +/* Encode 3 bytes into a 4 byte string. */ +void kwsysBase64_Encode3(const unsigned char *src, unsigned char *dest) +{ + dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F); + dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30)|((src[1] >> 4) & 0x0F)); + dest[2] = kwsysBase64EncodeChar(((src[1] << 2) & 0x3C)|((src[2] >> 6) & 0x03)); + dest[3] = kwsysBase64EncodeChar(src[2] & 0x3F); +} + +/*--------------------------------------------------------------------------*/ +/* Encode 2 bytes into a 4 byte string. */ +void kwsysBase64_Encode2(const unsigned char *src, unsigned char *dest) +{ + dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F); + dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30)|((src[1] >> 4) & 0x0F)); + dest[2] = kwsysBase64EncodeChar(((src[1] << 2) & 0x3C)); + dest[3] = '='; +} + +/*--------------------------------------------------------------------------*/ +/* Encode 1 bytes into a 4 byte string. */ +void kwsysBase64_Encode1(const unsigned char *src, unsigned char *dest) +{ + dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F); + dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30)); + dest[2] = '='; + dest[3] = '='; +} + +/*--------------------------------------------------------------------------*/ +/* Encode 'length' bytes from the input buffer and store the + encoded stream into the output buffer. Return the length of the encoded + buffer (output). Note that the output buffer must be allocated by the caller + (length * 1.5 should be a safe estimate). If 'mark_end' is true than an + extra set of 4 bytes is added to the end of the stream if the input is a + multiple of 3 bytes. These bytes are invalid chars and therefore they will + stop the decoder thus enabling the caller to decode a stream without + actually knowing how much data to expect (if the input is not a multiple of + 3 bytes then the extra padding needed to complete the encode 4 bytes will + stop the decoding anyway). */ +unsigned long kwsysBase64_Encode(const unsigned char *input, + unsigned long length, + unsigned char *output, + int mark_end) +{ + const unsigned char *ptr = input; + const unsigned char *end = input + length; + unsigned char *optr = output; + + /* Encode complete triplet */ + + while ((end - ptr) >= 3) + { + kwsysBase64_Encode3(ptr, optr); + ptr += 3; + optr += 4; + } + + /* Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes. */ + + if (end - ptr == 2) + { + kwsysBase64_Encode2(ptr, optr); + optr += 4; + } + + /* Encodes a 1-byte ending into 2 bytes and 2 pad bytes */ + + else if (end - ptr == 1) + { + kwsysBase64_Encode1(ptr, optr); + optr += 4; + } + + /* Do we need to mark the end */ + + else if (mark_end) + { + optr[0] = optr[1] = optr[2] = optr[3] = '='; + optr += 4; + } + + return (unsigned long)(optr - output); +} + +/*--------------------------------------------------------------------------*/ +/* Decode 4 bytes into a 3 byte string. */ +int kwsysBase64_Decode3(const unsigned char *src, unsigned char *dest) +{ + unsigned char d0, d1, d2, d3; + + d0 = kwsysBase64DecodeChar(src[0]); + d1 = kwsysBase64DecodeChar(src[1]); + d2 = kwsysBase64DecodeChar(src[2]); + d3 = kwsysBase64DecodeChar(src[3]); + + /* Make sure all characters were valid */ + + if (d0 == 0xFF || d1 == 0xFF || d2 == 0xFF || d3 == 0xFF) + { + return 0; + } + + /* Decode the 3 bytes */ + + dest[0] = (unsigned char)(((d0 << 2) & 0xFC) | ((d1 >> 4) & 0x03)); + dest[1] = (unsigned char)(((d1 << 4) & 0xF0) | ((d2 >> 2) & 0x0F)); + dest[2] = (unsigned char)(((d2 << 6) & 0xC0) | ((d3 >> 0) & 0x3F)); + + /* Return the number of bytes actually decoded */ + + if (src[2] == '=') + { + return 1; + } + if (src[3] == '=') + { + return 2; + } + return 3; +} + +/*--------------------------------------------------------------------------*/ +/* Decode bytes from the input buffer and store the decoded stream + into the output buffer until 'length' bytes have been decoded. Return the + real length of the decoded stream (which should be equal to 'length'). Note + that the output buffer must be allocated by the caller. If + 'max_input_length' is not null, then it specifies the number of encoded + bytes that should be at most read from the input buffer. In that case the + 'length' parameter is ignored. This enables the caller to decode a stream + without actually knowing how much decoded data to expect (of course, the + buffer must be large enough). */ +unsigned long kwsysBase64_Decode(const unsigned char *input, + unsigned long length, + unsigned char *output, + unsigned long max_input_length) +{ + const unsigned char *ptr = input; + unsigned char *optr = output; + + /* Decode complete triplet */ + + if (max_input_length) + { + const unsigned char *end = input + max_input_length; + while (ptr < end) + { + int len = kwsysBase64_Decode3(ptr, optr); + optr += len; + if(len < 3) + { + return (unsigned long)(optr - output); + } + ptr += 4; + } + } + else + { + unsigned char *oend = output + length; + while ((oend - optr) >= 3) + { + int len = kwsysBase64_Decode3(ptr, optr); + optr += len; + if(len < 3) + { + return (unsigned long)(optr - output); + } + ptr += 4; + } + + /* Decode the last triplet */ + + if (oend - optr == 2) + { + unsigned char temp[3]; + int len = kwsysBase64_Decode3(ptr, temp); + if(len >= 2) + { + optr[0] = temp[0]; + optr[1] = temp[1]; + optr += 2; + } + else if(len > 0) + { + optr[0] = temp[0]; + optr += 1; + } + } + else if (oend - optr == 1) + { + unsigned char temp[3]; + int len = kwsysBase64_Decode3(ptr, temp); + if(len > 0) + { + optr[0] = temp[0]; + optr += 1; + } + } + } + + return (unsigned long)(optr - output); +} diff --git a/Utilities/kwsys/Base64.h.in b/Utilities/kwsys/Base64.h.in new file mode 100644 index 0000000..66329a2 --- /dev/null +++ b/Utilities/kwsys/Base64.h.in @@ -0,0 +1,118 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Base64.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_Base64_h +#define @KWSYS_NAMESPACE@_Base64_h + +#include <@KWSYS_NAMESPACE@/Configure.h> + +/* Redefine all public interface symbol names to be in the proper + namespace. These macros are used internally to kwsys only, and are + not visible to user code. Use kwsysHeaderDump.pl to reproduce + these macros after making changes to the interface. */ +#if !defined(KWSYS_NAMESPACE) +# define kwsys_ns(x) @KWSYS_NAMESPACE@##x +# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT +#endif +#define kwsysBase64 kwsys_ns(Base64) +#define kwsysBase64_Decode kwsys_ns(Base64_Decode) +#define kwsysBase64_Decode3 kwsys_ns(Base64_Decode3) +#define kwsysBase64_Encode kwsys_ns(Base64_Encode) +#define kwsysBase64_Encode1 kwsys_ns(Base64_Encode1) +#define kwsysBase64_Encode2 kwsys_ns(Base64_Encode2) +#define kwsysBase64_Encode3 kwsys_ns(Base64_Encode3) + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/** + * Encode 3 bytes into a 4 byte string. + */ +kwsysEXPORT void kwsysBase64_Encode3(const unsigned char *src, + unsigned char *dest); + +/** + * Encode 2 bytes into a 4 byte string. + */ +kwsysEXPORT void kwsysBase64_Encode2(const unsigned char *src, + unsigned char *dest); + +/** + * Encode 1 bytes into a 4 byte string. + */ +kwsysEXPORT void kwsysBase64_Encode1(const unsigned char *src, + unsigned char *dest); + +/** + * Encode 'length' bytes from the input buffer and store the encoded + * stream into the output buffer. Return the length of the encoded + * buffer (output). Note that the output buffer must be allocated by + * the caller (length * 1.5 should be a safe estimate). If 'mark_end' + * is true than an extra set of 4 bytes is added to the end of the + * stream if the input is a multiple of 3 bytes. These bytes are + * invalid chars and therefore they will stop the decoder thus + * enabling the caller to decode a stream without actually knowing how + * much data to expect (if the input is not a multiple of 3 bytes then + * the extra padding needed to complete the encode 4 bytes will stop + * the decoding anyway). + */ +kwsysEXPORT unsigned long kwsysBase64_Encode(const unsigned char *input, + unsigned long length, + unsigned char *output, + int mark_end); + +/** + * Decode 4 bytes into a 3 byte string. Returns the number of bytes + * actually decoded. + */ +kwsysEXPORT int kwsysBase64_Decode3(const unsigned char *src, + unsigned char *dest); + +/** + * Decode bytes from the input buffer and store the decoded stream + * into the output buffer until 'length' bytes have been decoded. + * Return the real length of the decoded stream (which should be equal + * to 'length'). Note that the output buffer must be allocated by the + * caller. If 'max_input_length' is not null, then it specifies the + * number of encoded bytes that should be at most read from the input + * buffer. In that case the 'length' parameter is ignored. This + * enables the caller to decode a stream without actually knowing how + * much decoded data to expect (of course, the buffer must be large + * enough). + */ +kwsysEXPORT unsigned long kwsysBase64_Decode(const unsigned char *input, + unsigned long length, + unsigned char *output, + unsigned long max_input_length); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +/* If we are building a kwsys .c or .cxx file, let it use these macros. + Otherwise, undefine them to keep the namespace clean. */ +#if !defined(KWSYS_NAMESPACE) +# undef kwsys_ns +# undef kwsysEXPORT +# undef kwsysBase64 +# undef kwsysBase64_Decode +# undef kwsysBase64_Decode3 +# undef kwsysBase64_Encode +# undef kwsysBase64_Encode1 +# undef kwsysBase64_Encode2 +# undef kwsysBase64_Encode3 +#endif + +#endif diff --git a/Utilities/kwsys/CMakeLists.txt b/Utilities/kwsys/CMakeLists.txt new file mode 100644 index 0000000..54ce137 --- /dev/null +++ b/Utilities/kwsys/CMakeLists.txt @@ -0,0 +1,631 @@ +#============================================================================= +# +# Program: KWSys - Kitware System Library +# Module: $RCSfile: CMakeLists.txt,v $ +# +# Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. +# See Copyright.txt or http://www.kitware.com/Copyright.htm for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even +# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the above copyright notices for more information. +# +#============================================================================= + +# The Kitware System Library is intended to be included in other +# projects. It is completely configurable in that the library's +# namespace can be configured and the components that are included can +# be selected invididually. + +# Typical usage is to import the kwsys directory tree into a +# subdirectory under a parent project and enable the classes that will +# be used. All classes are disabled by default. The CMake listfile +# above this one configures the library as follows: +# +# SET(KWSYS_NAMESPACE foosys) +# SET(KWSYS_USE_Directory 1) # Enable Directory class. +# SUBDIRS(kwsys) +# +# Optional settings are as follows: +# +# KWSYS_HEADER_ROOT = The directory into which to generate the kwsys headers. +# A directory called "${KWSYS_NAMESPACE}" will be +# created under this root directory to hold the files. +# +# Example: +# +# SET(KWSYS_HEADER_ROOT ${PROJECT_BINARY_DIR}) +# INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}) +# +# KWSYS_LIBRARY_INSTALL_DIR = The installation target directories into +# KWSYS_HEADER_INSTALL_DIR which the libraries and headers from +# kwsys should be installed by a "make install". +# The values should be specified relative to +# the installation prefix and start with a '/'. +# Example: +# +# SET(KWSYS_LIBRARY_INSTALL_DIR /lib) +# SET(KWSYS_HEADER_INSTALL_DIR /include) +# +# KWSYS_IOS_FORCE_OLD = Force use of old non-ANSI C++ streams even if +# new streams are available. This may be used +# by projects that cannot configure their +# streams library. +# Example: +# +# SET(KWSYS_IOS_FORCE_OLD 1) +# + +# Once configured, kwsys should be used as follows from C or C++ code: +# +# #include +# ... +# foosys::Directory directory; +# + +#----------------------------------------------------------------------------- +# If a namespace is not specified, use "kwsys" and enable testing. +# This should be the case only when kwsys is not included inside +# another project and is being tested. +IF(NOT KWSYS_NAMESPACE) + SET(KWSYS_NAMESPACE "kwsys") + SET(KWSYS_STANDALONE 1) +ENDIF(NOT KWSYS_NAMESPACE) + +IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) + SET(KWSYS_ENABLE_C 1) + + # Enable all components. + SET(KWSYS_USE_Base64 1) + SET(KWSYS_USE_Directory 1) + SET(KWSYS_USE_Glob 1) + SET(KWSYS_USE_Process 1) + SET(KWSYS_USE_RegularExpression 1) + SET(KWSYS_USE_SystemTools 1) + SET(KWSYS_USE_CommandLineArguments 1) + SET(KWSYS_USE_FundamentalType 1) +ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) + +#----------------------------------------------------------------------------- +# The project name is that of the specified namespace. +PROJECT(${KWSYS_NAMESPACE}) + +# Enable testing if building standalone. +IF(KWSYS_STANDALONE) + INCLUDE(Dart) + MARK_AS_ADVANCED(BUILD_TESTING DART_ROOT TCL_TCLSH) + IF(BUILD_TESTING) + ENABLE_TESTING() + ENDIF(BUILD_TESTING) +ENDIF(KWSYS_STANDALONE) + +# Do full dependency headers. +INCLUDE_REGULAR_EXPRESSION("^.*$") + +# Work-around for CMake 1.6.7 bug in custom command dependencies when +# there is no executable output path. +IF(NOT EXECUTABLE_OUTPUT_PATH) + SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}" CACHE PATH + "Output directory for executables.") +ENDIF(NOT EXECUTABLE_OUTPUT_PATH) + +# Generated source files will need this header. +STRING(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" + KWSYS_IN_SOURCE_BUILD) +IF(NOT KWSYS_IN_SOURCE_BUILD) + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsysPrivate.h + ${PROJECT_BINARY_DIR}/kwsysPrivate.h COPY_ONLY IMMEDIATE) +ENDIF(NOT KWSYS_IN_SOURCE_BUILD) + +#----------------------------------------------------------------------------- +# We require ANSI support from the C compiler. Add any needed flags. +IF(CMAKE_ANSI_CFLAGS) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") +ENDIF(CMAKE_ANSI_CFLAGS) + +#----------------------------------------------------------------------------- +# Adjust compiler flags for some platforms. +IF(NOT CMAKE_COMPILER_IS_GNUCXX) + IF(CMAKE_SYSTEM MATCHES "OSF1-V.*") + STRING(REGEX MATCH "-timplicit_local" + KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL "${CMAKE_CXX_FLAGS}") + STRING(REGEX MATCH "-no_implicit_include" + KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE "${CMAKE_CXX_FLAGS}") + IF(NOT KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -timplicit_local") + ENDIF(NOT KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL) + IF(NOT KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no_implicit_include") + ENDIF(NOT KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE) + ENDIF(CMAKE_SYSTEM MATCHES "OSF1-V.*") +ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX) + +#----------------------------------------------------------------------------- +# Configure the standard library header wrappers based on compiler's +# capabilities and parent project's request. Enforce 0/1 as only +# possible values for configuration into Configure.hxx. +INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformCxxTests.cmake) + +KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAVE_STD + "Checking whether STL classes are in std namespace" DIRECT) + +IF(KWSYS_IOS_FORCE_OLD) + SET(KWSYS_IOS_USE_ANSI 0) +ELSE(KWSYS_IOS_FORCE_OLD) + KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_ANSI + "Checking whether ANSI stream headers are available" DIRECT) +ENDIF(KWSYS_IOS_FORCE_OLD) + +IF(KWSYS_IOS_USE_ANSI) + KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAVE_STD + "Checking whether ANSI streams are in std namespace" DIRECT) + KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_SSTREAM + "Checking whether ANSI string stream is available" DIRECT) +ELSE(KWSYS_IOS_USE_ANSI) + SET(KWSYS_IOS_HAVE_STD 0) + SET(KWSYS_IOS_USE_SSTREAM 0) +ENDIF(KWSYS_IOS_USE_ANSI) + +IF(KWSYS_IOS_USE_SSTREAM) + SET(KWSYS_IOS_USE_STRSTREAM_H 0) + SET(KWSYS_IOS_USE_STRSTREA_H 0) +ELSE(KWSYS_IOS_USE_SSTREAM) + KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_STRSTREAM_H + "Checking whether strstream.h is available" DIRECT) + IF(KWSYS_IOS_USE_STRSTREAM_H) + SET(KWSYS_IOS_USE_STRSTREA_H 0) + ELSE(KWSYS_IOS_USE_STRSTREAM_H) + KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_STRSTREA_H + "Checking whether strstrea.h is available" DIRECT) + ENDIF(KWSYS_IOS_USE_STRSTREAM_H) +ENDIF(KWSYS_IOS_USE_SSTREAM) + +KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CSTDDEF + "Checking whether header cstddef is available" DIRECT) + +SET(KWSYS_PLATFORM_CXX_TEST_DEFINES + -DKWSYS_STL_HAVE_STD=${KWSYS_STL_HAVE_STD}) +KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_NEQ_CHAR + "Checking whether stl string has operator!= for char*" DIRECT) +KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ITERATOR_TRAITS + "Checking whether stl has iterator_traits" DIRECT) +IF(KWSYS_STL_HAS_ITERATOR_TRAITS) + SET(KWSYS_STL_HAS_ITERATOR_CATEGORY 0) + SET(KWSYS_STL_HAS___ITERATOR_CATEGORY 0) +ELSE(KWSYS_STL_HAS_ITERATOR_TRAITS) + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ITERATOR_CATEGORY + "Checking whether stl has old iterator_category" DIRECT) + IF(KWSYS_STL_HAS_ITERATOR_CATEGORY) + SET(KWSYS_STL_HAS___ITERATOR_CATEGORY 0) + ELSE(KWSYS_STL_HAS_ITERATOR_CATEGORY) + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS___ITERATOR_CATEGORY + "Checking whether stl has internal __iterator_category" DIRECT) + ENDIF(KWSYS_STL_HAS_ITERATOR_CATEGORY) +ENDIF(KWSYS_STL_HAS_ITERATOR_TRAITS) +KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE + "Checking whether stl has standard template allocator" DIRECT) +IF(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE) + SET(KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE 0) + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_REBIND + "Checking for rebind member of stl allocator" DIRECT) + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT + "Checking for non-standard argument to stl allocator<>::max_size" DIRECT) +ELSE(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE) + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE + "Checking whether stl has old non-template allocator" DIRECT) + SET(KWSYS_STL_HAS_ALLOCATOR_REBIND 0) + SET(KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT 0) +ENDIF(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE) +KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_OBJECTS + "Checking whether stl containers support allocator objects." DIRECT) +IF(KWSYS_IOS_USE_ANSI) + # ANSI streams always have string operators. + SET(KWSYS_STL_STRING_HAVE_OSTREAM 1) + SET(KWSYS_STL_STRING_HAVE_ISTREAM 1) +ELSE(KWSYS_IOS_USE_ANSI) + # There may not be string operators for old streams. + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_OSTREAM + "Checking whether stl string has ostream operator<<" DIRECT) + KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_ISTREAM + "Checking whether stl string has istream operator>>" DIRECT) +ENDIF(KWSYS_IOS_USE_ANSI) +SET(KWSYS_PLATFORM_CXX_TEST_DEFINES) + +KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS + "Checking whether \"<>\" is needed for template friends" INVERT) +KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_MEMBER_TEMPLATES + "Checking for member template support" DIRECT) +KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_FULL_SPECIALIZATION + "Checking for standard template specialization syntax" DIRECT) +KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP + "Checking whether argument dependent lookup is supported" DIRECT) + +IF(UNIX) + KWSYS_PLATFORM_CXX_TEST(KWSYS_STAT_HAS_ST_MTIM + "Checking whether struct stat has st_mtim member" DIRECT) +ENDIF(UNIX) + +IF(KWSYS_USE_FundamentalType) + # Determine type sizes. + INCLUDE(CheckTypeSize) + CHECK_TYPE_SIZE("char" KWSYS_SIZEOF_CHAR) + CHECK_TYPE_SIZE("short" KWSYS_SIZEOF_SHORT) + CHECK_TYPE_SIZE("int" KWSYS_SIZEOF_INT) + CHECK_TYPE_SIZE("long" KWSYS_SIZEOF_LONG) + CHECK_TYPE_SIZE("long long" KWSYS_SIZEOF_LONG_LONG) + CHECK_TYPE_SIZE("__int64" KWSYS_SIZEOF___INT64) + IF(NOT KWSYS_SIZEOF_LONG_LONG) + SET(KWSYS_SIZEOF_LONG_LONG 0) + ENDIF(NOT KWSYS_SIZEOF_LONG_LONG) + IF(NOT KWSYS_SIZEOF___INT64) + SET(KWSYS_SIZEOF___INT64 0) + ENDIF(NOT KWSYS_SIZEOF___INT64) + + # Check uniqueness of types. + IF(KWSYS_SIZEOF___INT64) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_SAME_LONG_AND___INT64 + "Checking whether long and __int64 are the same type" DIRECT) + IF(KWSYS_SIZEOF_LONG_LONG) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_SAME_LONG_LONG_AND___INT64 + "Checking whether long long and __int64 are the same type" DIRECT) + ENDIF(KWSYS_SIZEOF_LONG_LONG) + ENDIF(KWSYS_SIZEOF___INT64) + + # Enable the "long long" type if it is available. It is standard in + # C99 and C++03 but not in earlier standards. + IF(KWSYS_SIZEOF_LONG_LONG) + SET(KWSYS_USE_LONG_LONG 1) + ELSE(KWSYS_SIZEOF_LONG_LONG) + SET(KWSYS_USE_LONG_LONG 0) + ENDIF(KWSYS_SIZEOF_LONG_LONG) + + # Enable the "__int64" type if it is available and unique. It is not + # standard. + SET(KWSYS_USE___INT64 0) + IF(KWSYS_SIZEOF___INT64) + IF(NOT KWSYS_CXX_SAME_LONG_AND___INT64) + IF(NOT KWSYS_CXX_SAME_LONG_LONG_AND___INT64) + SET(KWSYS_USE___INT64 1) + ENDIF(NOT KWSYS_CXX_SAME_LONG_LONG_AND___INT64) + ENDIF(NOT KWSYS_CXX_SAME_LONG_AND___INT64) + ENDIF(KWSYS_SIZEOF___INT64) + IF(KWSYS_USE___INT64) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CAN_CONVERT_UI64_TO_DOUBLE + "Checking whether unsigned __int64 can convert to double" DIRECT) + ELSE(KWSYS_USE___INT64) + SET(KWSYS_CAN_CONVERT_UI64_TO_DOUBLE 1) + ENDIF(KWSYS_USE___INT64) + + # Check signedness of "char" type. + IF("KWSYS_CHAR_IS_SIGNED" MATCHES "^KWSYS_CHAR_IS_SIGNED$") + MESSAGE(STATUS "Checking signedness of char") + TRY_RUN(KWSYS_CHAR_IS_SIGNED KWSYS_CHAR_IS_SIGNED_COMPILED + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformCxxTests.cxx + COMPILE_DEFINITIONS -DTEST_KWSYS_CHAR_IS_SIGNED) + IF(KWSYS_CHAR_IS_SIGNED_COMPILED) + IF(KWSYS_CHAR_IS_SIGNED) + MESSAGE(STATUS "Checking signedness of char -- signed") + SET(KWSYS_CHAR_IS_SIGNED 1 CACHE INTERNAL "Whether char is signed.") + ELSE(KWSYS_CHAR_IS_SIGNED) + MESSAGE(STATUS "Checking signedness of char -- unsigned") + SET(KWSYS_CHAR_IS_SIGNED 0 CACHE INTERNAL "Whether char is signed.") + ENDIF(KWSYS_CHAR_IS_SIGNED) + ELSE(KWSYS_CHAR_IS_SIGNED_COMPILED) + MESSAGE(FATAL_ERROR "Checking signedness of char -- failed") + ENDIF(KWSYS_CHAR_IS_SIGNED_COMPILED) + ENDIF("KWSYS_CHAR_IS_SIGNED" MATCHES "^KWSYS_CHAR_IS_SIGNED$") +ENDIF(KWSYS_USE_FundamentalType) + +IF(KWSYS_NAMESPACE MATCHES "^kwsys$") + SET(KWSYS_NAME_IS_KWSYS 1) +ELSE(KWSYS_NAMESPACE MATCHES "^kwsys$") + SET(KWSYS_NAME_IS_KWSYS 0) +ENDIF(KWSYS_NAMESPACE MATCHES "^kwsys$") + +# Choose default shared/static build if not specified. +IF(KWSYS_BUILD_SHARED MATCHES "^KWSYS_BUILD_SHARED$") + SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS}) +ENDIF(KWSYS_BUILD_SHARED MATCHES "^KWSYS_BUILD_SHARED$") + +IF(KWSYS_BUILD_SHARED) + SET(KWSYS_BUILD_SHARED 1) + SET(KWSYS_LIBRARY_TYPE SHARED) +ELSE(KWSYS_BUILD_SHARED) + SET(KWSYS_BUILD_SHARED 0) + SET(KWSYS_LIBRARY_TYPE STATIC) +ENDIF(KWSYS_BUILD_SHARED) + +#----------------------------------------------------------------------------- +# Choose a directory for the generated headers. +IF(NOT KWSYS_HEADER_ROOT) + SET(KWSYS_HEADER_ROOT "${PROJECT_BINARY_DIR}") +ENDIF(NOT KWSYS_HEADER_ROOT) +SET(KWSYS_HEADER_DIR "${KWSYS_HEADER_ROOT}/${KWSYS_NAMESPACE}") +INCLUDE_DIRECTORIES(${KWSYS_HEADER_ROOT}) + +#----------------------------------------------------------------------------- +# Create STL header wrappers to block warnings in the STL headers and +# give standard names by which they may be included. +SET(KWSYS_STL_HEADER_EXTRA_string 1) +FOREACH(header algorithm deque iterator list map numeric queue set stack string + utility vector memory functional) + # Configure the header wrapper. + SET(KWSYS_STL_HEADER "${header}") + IF(KWSYS_STL_HEADER_EXTRA_${header}) + SET(KWSYS_STL_HEADER_EXTRA + "#define ${KWSYS_NAMESPACE}_stl_${header}_including_hxx\n# include <${KWSYS_NAMESPACE}/stl/${header}.hxx>\n#undef ${KWSYS_NAMESPACE}_stl_${header}_including_hxx\n") + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_stl_${header}.hxx.in + ${KWSYS_HEADER_DIR}/stl/${header}.hxx + @ONLY IMMEDIATE) + IF(KWSYS_HEADER_INSTALL_DIR) + INSTALL_FILES(${KWSYS_HEADER_INSTALL_DIR}/${KWSYS_NAMESPACE}/stl + FILES ${KWSYS_HEADER_DIR}/stl/${header}.hxx) + ENDIF(KWSYS_HEADER_INSTALL_DIR) + ELSE(KWSYS_STL_HEADER_EXTRA_${header}) + SET(KWSYS_STL_HEADER_EXTRA "") + ENDIF(KWSYS_STL_HEADER_EXTRA_${header}) + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_stl.hxx.in + ${KWSYS_HEADER_DIR}/stl/${header} + @ONLY IMMEDIATE) + + # Create an install target for the header wrapper. + IF(KWSYS_HEADER_INSTALL_DIR) + INSTALL_FILES(${KWSYS_HEADER_INSTALL_DIR}/${KWSYS_NAMESPACE}/stl + FILES ${KWSYS_HEADER_DIR}/stl/${header}) + ENDIF(KWSYS_HEADER_INSTALL_DIR) +ENDFOREACH(header) + +# Provide cstddef header. +CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_cstddef.hxx.in + ${KWSYS_HEADER_DIR}/cstddef + @ONLY IMMEDIATE) + +#----------------------------------------------------------------------------- +# Create streams header wrappers to give standard names by which they +# may be included. +FOREACH(header iostream fstream sstream iosfwd) + # Configure the header wrapper. + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_ios_${header}.h.in + ${KWSYS_HEADER_DIR}/ios/${header} + @ONLY IMMEDIATE) + + # Create an install target for the header wrapper. + IF(KWSYS_HEADER_INSTALL_DIR) + INSTALL_FILES(${KWSYS_HEADER_INSTALL_DIR}/${KWSYS_NAMESPACE}/ios + FILES ${KWSYS_HEADER_DIR}/ios/${header}) + ENDIF(KWSYS_HEADER_INSTALL_DIR) +ENDFOREACH(header) + +#----------------------------------------------------------------------------- +# Build a list of classes and headers we need to implement the +# selected components. Initialize with required components. +SET(KWSYS_CLASSES) +SET(KWSYS_H_FILES Configure SharedForward) +SET(KWSYS_HXX_FILES Configure hashtable hash_fun hash_map hash_set) + +# Enforce component dependencies. +IF(KWSYS_USE_SystemTools) + SET(KWSYS_USE_Directory 1) +ENDIF(KWSYS_USE_SystemTools) +IF(KWSYS_USE_Glob) + SET(KWSYS_USE_Directory 1) + SET(KWSYS_USE_SystemTools 1) + SET(KWSYS_USE_RegularExpression 1) +ENDIF(KWSYS_USE_Glob) + +# Add selected C++ classes. +FOREACH(c Directory Glob RegularExpression SystemTools CommandLineArguments) + IF(KWSYS_USE_${c}) + SET(KWSYS_CLASSES ${KWSYS_CLASSES} ${c}) + ENDIF(KWSYS_USE_${c}) +ENDFOREACH(c) + +# Add selected C components. +FOREACH(c Process Base64 FundamentalType) + IF(KWSYS_USE_${c}) + SET(KWSYS_H_FILES ${KWSYS_H_FILES} ${c}) + ENDIF(KWSYS_USE_${c}) +ENDFOREACH(c) + +#----------------------------------------------------------------------------- +# Build a list of sources for the library based on components that are +# included. +SET(KWSYS_C_SRCS) +SET(KWSYS_CXX_SRCS) + +# Add the proper sources for this platform's Process implementation. +IF(KWSYS_USE_Process) + IF(NOT UNIX) + # Use the Windows implementation. We need the encoded forwarding executable. + SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c + ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c) + SET_SOURCE_FILES_PROPERTIES( + ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c + PROPERTIES GENERATED 1) + ELSE(NOT UNIX) + # Use the UNIX implementation. + SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c) + ENDIF(NOT UNIX) +ENDIF(KWSYS_USE_Process) + +# Add sources for Base64 encoding. +IF(KWSYS_USE_Base64) + SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} Base64.c) +ENDIF(KWSYS_USE_Base64) + +# Configure headers of C++ classes and construct the list of sources. +FOREACH(c ${KWSYS_CLASSES}) + # Add this source to the list of source files for the library. + SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${c}.cxx) + + # Configure the header for this class. + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${c}.hxx.in ${KWSYS_HEADER_DIR}/${c}.hxx + @ONLY IMMEDIATE) + + # Create an install target for the header. + IF(KWSYS_HEADER_INSTALL_DIR) + INSTALL_FILES(${KWSYS_HEADER_INSTALL_DIR}/${KWSYS_NAMESPACE} + FILES ${KWSYS_HEADER_DIR}/${c}.hxx) + ENDIF(KWSYS_HEADER_INSTALL_DIR) +ENDFOREACH(c) + +# Configure C headers. +FOREACH(h ${KWSYS_H_FILES}) + # Configure the header into the given directory. + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.h.in ${KWSYS_HEADER_DIR}/${h}.h + @ONLY IMMEDIATE) + + # Create an install target for the header. + IF(KWSYS_HEADER_INSTALL_DIR) + INSTALL_FILES(${KWSYS_HEADER_INSTALL_DIR}/${KWSYS_NAMESPACE} + FILES ${KWSYS_HEADER_DIR}/${h}.h) + ENDIF(KWSYS_HEADER_INSTALL_DIR) +ENDFOREACH(h) + +# Configure other C++ headers. +FOREACH(h ${KWSYS_HXX_FILES}) + # Configure the header into the given directory. + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.hxx.in ${KWSYS_HEADER_DIR}/${h}.hxx + @ONLY IMMEDIATE) + + # Create an install target for the header. + IF(KWSYS_HEADER_INSTALL_DIR) + INSTALL_FILES(${KWSYS_HEADER_INSTALL_DIR}/${KWSYS_NAMESPACE} + FILES ${KWSYS_HEADER_DIR}/${h}.hxx) + ENDIF(KWSYS_HEADER_INSTALL_DIR) +ENDFOREACH(h) + +#----------------------------------------------------------------------------- +# Add the library with the configured name and list of sources. +IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) + ADD_LIBRARY(${KWSYS_NAMESPACE} ${KWSYS_LIBRARY_TYPE} + ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) + + # Apply user-defined target properties to the library. + IF(KWSYS_PROPERTIES_CXX) + SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE} PROPERTIES + ${KWSYS_PROPERTIES_CXX} + ) + ENDIF(KWSYS_PROPERTIES_CXX) + + # Create an install target for the library. + IF(KWSYS_LIBRARY_INSTALL_DIR) + INSTALL_TARGETS(${KWSYS_LIBRARY_INSTALL_DIR} ${KWSYS_NAMESPACE}) + ENDIF(KWSYS_LIBRARY_INSTALL_DIR) +ENDIF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) + +# Add a C-only library if requested. +IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS) + ADD_LIBRARY(${KWSYS_NAMESPACE}_c ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS}) + + # Apply user-defined target properties to the library. + IF(KWSYS_PROPERTIES_C) + SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE} PROPERTIES + ${KWSYS_PROPERTIES_C} + ) + ENDIF(KWSYS_PROPERTIES_C) + + # Create an install target for the library. + IF(KWSYS_LIBRARY_INSTALL_DIR) + INSTALL_TARGETS(${KWSYS_LIBRARY_INSTALL_DIR} ${KWSYS_NAMESPACE}_c) + ENDIF(KWSYS_LIBRARY_INSTALL_DIR) +ENDIF(KWSYS_ENABLE_C AND KWSYS_C_SRCS) + +# For building kwsys itself, we use a macro defined on the command +# line to configure the namespace in the C and C++ source files. +ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}") + +#----------------------------------------------------------------------------- +# Process execution on windows needs to build a forwarding executable +# that works around a Win9x bug. We encode the executable into a C +# file and build it into the library. Win9x platforms reproduce the +# executable into a temporary directory when it is needed. +IF(KWSYS_USE_Process) + IF(NOT UNIX) + # Build the forwarding executable itself and a program that will + # encode it into a C file. + ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c) + ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c) + + # Construct the location of the executable to be encoded. + SET(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}) + IF(EXECUTABLE_OUTPUT_PATH) + SET(BIN_DIR ${EXECUTABLE_OUTPUT_PATH}) + ENDIF(EXECUTABLE_OUTPUT_PATH) + + SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}") + IF(CMAKE_BUILD_TOOL MATCHES "make") + SET(CFG_INTDIR "") + ENDIF(CMAKE_BUILD_TOOL MATCHES "make") + + # Take advantage of a better custom command syntax if possible. + SET(CMD ${BIN_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe) + SET(FWD ${BIN_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe) + IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c + COMMAND ${CMD} + ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c + ${KWSYS_NAMESPACE} ProcessFwd9x + DEPENDS ${CMD} ${FWD}) + ELSE("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + ADD_CUSTOM_COMMAND( + TARGET ${KWSYS_NAMESPACE} + SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ProcessFwd9x.c + COMMAND ${CMD} + ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c + ${KWSYS_NAMESPACE} ProcessFwd9x + OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c + DEPENDS ${CMD} ${FWD}) + ENDIF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 1.6) + + # Make sure build occurs in proper order. + ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x + ${KWSYS_NAMESPACE}EncodeExecutable) + ENDIF(NOT UNIX) +ENDIF(KWSYS_USE_Process) + +#----------------------------------------------------------------------------- +# Setup testing if not being built as part of another project. +IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) + # C++ tests + FOREACH(test + testSystemTools + testIOS + testHashSTL + testCommandLineArguments + ) + ADD_EXECUTABLE(${test} ${test}.cxx) + TARGET_LINK_LIBRARIES(${test} ${KWSYS_NAMESPACE}) + ENDFOREACH(test) + # C tests + FOREACH(test + testProcess + ) + ADD_EXECUTABLE(${test} ${test}.c) + TARGET_LINK_LIBRARIES(${test} ${KWSYS_NAMESPACE}_c) + ENDFOREACH(test) + + SET(EXEC_DIR "${CMAKE_CURRENT_BINARY_DIR}") + IF(EXECUTABLE_OUTPUT_PATH) + SET(EXEC_DIR "${EXECUTABLE_OUTPUT_PATH}") + ENDIF(EXECUTABLE_OUTPUT_PATH) + + IF(BUILD_TESTING) + IF(CTEST_TEST_KWSYS) + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/ExtraTest.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake") + SET_DIRECTORY_PROPERTIES(PROPERTIES TEST_INCLUDE_FILE "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake") + ENDIF(CTEST_TEST_KWSYS) + ADD_TEST(kwsys-testSystemTools ${EXEC_DIR}/testSystemTools) + ADD_TEST(kwsys-testProcess-1 ${EXEC_DIR}/testProcess 1) + ADD_TEST(kwsys-testProcess-2 ${EXEC_DIR}/testProcess 2) + ADD_TEST(kwsys-testProcess-3 ${EXEC_DIR}/testProcess 3) + ADD_TEST(kwsys-testProcess-4 ${EXEC_DIR}/testProcess 4) + ADD_TEST(kwsys-testProcess-5 ${EXEC_DIR}/testProcess 5) + ADD_TEST(kwsys-testProcess-6 ${EXEC_DIR}/testProcess 6) + ADD_TEST(kwsys-testProcess-7 ${EXEC_DIR}/testProcess 7) + ADD_TEST(kwsys-testHashSTL ${EXEC_DIR}/testHashSTL) + ENDIF(BUILD_TESTING) +ENDIF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) diff --git a/Utilities/kwsys/CTestConfig.cmake b/Utilities/kwsys/CTestConfig.cmake new file mode 100644 index 0000000..23a5bd1 --- /dev/null +++ b/Utilities/kwsys/CTestConfig.cmake @@ -0,0 +1,3 @@ +SET (CTEST_PROJECT_NAME "kwsys") +SET (CTEST_NIGHTLY_START_TIME "21:00:00 EDT") +SET (CTEST_DART_SERVER_VERSION "2") diff --git a/Utilities/kwsys/CommandLineArguments.cxx b/Utilities/kwsys/CommandLineArguments.cxx new file mode 100644 index 0000000..5923270 --- /dev/null +++ b/Utilities/kwsys/CommandLineArguments.cxx @@ -0,0 +1,670 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: CommandLineArguments.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(CommandLineArguments.hxx) + +#include KWSYS_HEADER(Configure.hxx) + +#include KWSYS_HEADER(stl/vector) +#include KWSYS_HEADER(stl/map) +#include KWSYS_HEADER(stl/set) +#include KWSYS_HEADER(ios/sstream) +#include KWSYS_HEADER(ios/iostream) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "CommandLineArguments.hxx.in" +# include "Configure.hxx.in" +# include "kwsys_stl.hxx.in" +# include "kwsys_ios_sstream.h.in" +# include "kwsys_ios_iostream.h.in" +#endif + +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning (disable: 4786) +#endif + +#if defined(__sgi) && !defined(__GNUC__) +# pragma set woff 1375 /* base class destructor not virtual */ +#endif + +namespace KWSYS_NAMESPACE +{ + +//---------------------------------------------------------------------------- +//============================================================================ +class CommandLineArgumentsString : public kwsys_stl::string +{ +public: + typedef kwsys_stl::string StdString; + CommandLineArgumentsString(): StdString() {} + CommandLineArgumentsString(const value_type* s): StdString(s) {} + CommandLineArgumentsString(const value_type* s, size_type n): StdString(s, n) {} + CommandLineArgumentsString(const StdString& s, size_type pos=0, size_type n=npos): + StdString(s, pos, n) {} +}; + +struct CommandLineArgumentsCallbackStructure +{ + const char* Argument; + int ArgumentType; + CommandLineArguments::CallbackType Callback; + void* CallData; + void* Variable; + int VariableType; + const char* Help; +}; + +class CommandLineArgumentsVectorOfStrings : + public kwsys_stl::vector {}; +class CommandLineArgumentsSetOfStrings : + public kwsys_stl::set {}; +class CommandLineArgumentsMapOfStrucs : + public kwsys_stl::map {}; + +class CommandLineArgumentsInternal +{ +public: + CommandLineArgumentsInternal() + { + this->UnknownArgumentCallback = 0; + this->ClientData = 0; + this->LastArgument = 0; + } + + typedef CommandLineArgumentsVectorOfStrings VectorOfStrings; + typedef CommandLineArgumentsMapOfStrucs CallbacksMap; + typedef CommandLineArgumentsString String; + typedef CommandLineArgumentsSetOfStrings SetOfStrings; + + VectorOfStrings Argv; + String Argv0; + CallbacksMap Callbacks; + + CommandLineArguments::ErrorCallbackType UnknownArgumentCallback; + void* ClientData; + + VectorOfStrings::size_type LastArgument; +}; +//============================================================================ +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +CommandLineArguments::CommandLineArguments() +{ + this->Internals = new CommandLineArguments::Internal; + this->Help = ""; + this->LineLength = 80; +} + +//---------------------------------------------------------------------------- +CommandLineArguments::~CommandLineArguments() +{ + delete this->Internals; +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::Initialize(int argc, const char* const argv[]) +{ + int cc; + + this->Initialize(); + this->Internals->Argv0 = argv[0]; + for ( cc = 1; cc < argc; cc ++ ) + { + this->ProcessArgument(argv[cc]); + } +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::Initialize(int argc, char* argv[]) +{ + this->Initialize(argc, static_cast(argv)); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::Initialize() +{ + this->Internals->Argv.clear(); + this->Internals->LastArgument = 0; +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::ProcessArgument(const char* arg) +{ + this->Internals->Argv.push_back(arg); +} + +//---------------------------------------------------------------------------- +int CommandLineArguments::Parse() +{ + CommandLineArguments::Internal::VectorOfStrings::size_type cc; + CommandLineArguments::Internal::VectorOfStrings matches; + for ( cc = 0; cc < this->Internals->Argv.size(); cc ++ ) + { + this->Internals->LastArgument = cc; + matches.clear(); + CommandLineArguments::Internal::String& arg = this->Internals->Argv[cc]; + CommandLineArguments::Internal::CallbacksMap::iterator it; + + // Does the argument match to any we know about? + for ( it = this->Internals->Callbacks.begin(); + it != this->Internals->Callbacks.end(); + it ++ ) + { + const CommandLineArguments::Internal::String& parg = it->first; + CommandLineArgumentsCallbackStructure *cs = &it->second; + if (cs->ArgumentType == CommandLineArguments::NO_ARGUMENT || + cs->ArgumentType == CommandLineArguments::SPACE_ARGUMENT) + { + if ( arg == parg ) + { + matches.push_back(parg); + } + } + else if ( arg.find( parg ) == 0 ) + { + matches.push_back(parg); + } + } + if ( matches.size() > 0 ) + { + // Ok, we found one or more arguments that match what user specified. + // Let's find the longest one. + CommandLineArguments::Internal::VectorOfStrings::size_type kk; + CommandLineArguments::Internal::VectorOfStrings::size_type maxidx = 0; + CommandLineArguments::Internal::String::size_type maxlen = 0; + for ( kk = 0; kk < matches.size(); kk ++ ) + { + if ( matches[kk].size() > maxlen ) + { + maxlen = matches[kk].size(); + maxidx = kk; + } + } + // So, the longest one is probably the right one. Now see if it has any + // additional value + const char* value = 0; + CommandLineArgumentsCallbackStructure *cs + = &this->Internals->Callbacks[matches[maxidx]]; + const CommandLineArguments::Internal::String& sarg = matches[maxidx]; + if ( cs->ArgumentType == NO_ARGUMENT ) + { + // No value + } + else if ( cs->ArgumentType == SPACE_ARGUMENT ) + { + if ( cc == this->Internals->Argv.size()-1 ) + { + this->Internals->LastArgument --; + return 0; + } + // Value is the next argument + value = this->Internals->Argv[cc+1].c_str(); + cc ++; + } + else if ( cs->ArgumentType == EQUAL_ARGUMENT ) + { + if ( arg.size() == sarg.size() || *(arg.c_str() + sarg.size()) != '=' ) + { + this->Internals->LastArgument --; + return 0; + } + // Value is everythng followed the '=' sign + value = arg.c_str() + sarg.size()+1; + } + else if ( cs->ArgumentType == CONCAT_ARGUMENT ) + { + // Value is whatever follows the argument + value = arg.c_str() + sarg.size(); + } + + // Call the callback + if ( cs->Callback ) + { + if ( !cs->Callback(sarg.c_str(), value, cs->CallData) ) + { + this->Internals->LastArgument --; + return 0; + } + } + if ( cs->Variable ) + { + kwsys_stl::string var = "1"; + if ( value ) + { + var = value; + } + if ( cs->VariableType == CommandLineArguments::INT_TYPE ) + { + int* variable = static_cast(cs->Variable); + char* res = 0; + *variable = strtol(var.c_str(), &res, 10); + //if ( res && *res ) + // { + // Can handle non-int + // } + } + else if ( cs->VariableType == CommandLineArguments::DOUBLE_TYPE ) + { + double* variable = static_cast(cs->Variable); + char* res = 0; + *variable = strtod(var.c_str(), &res); + //if ( res && *res ) + // { + // Can handle non-int + // } + } + else if ( cs->VariableType == CommandLineArguments::STRING_TYPE ) + { + char** variable = static_cast(cs->Variable); + if ( *variable ) + { + delete [] *variable; + *variable = 0; + } + *variable = new char[ strlen(var.c_str()) + 1 ]; + strcpy(*variable, var.c_str()); + } + else if ( cs->VariableType == CommandLineArguments::STL_STRING_TYPE ) + { + kwsys_stl::string* variable = static_cast(cs->Variable); + *variable = var; + } + else if ( cs->VariableType == CommandLineArguments::BOOL_TYPE ) + { + bool* variable = static_cast(cs->Variable); + if ( var == "1" || var == "ON" || var == "TRUE" || var == "true" || var == "on" || + var == "True" || var == "yes" || var == "Yes" || var == "YES" ) + { + *variable = true; + } + else + { + *variable = false; + } + } + else + { + kwsys_ios::cerr << "Got unknown argument type: \"" << cs->VariableType << "\"" << kwsys_ios::endl; + this->Internals->LastArgument --; + return 0; + } + } + } + else + { + // Handle unknown arguments + if ( this->Internals->UnknownArgumentCallback ) + { + if ( !this->Internals->UnknownArgumentCallback(arg.c_str(), + this->Internals->ClientData) ) + { + this->Internals->LastArgument --; + return 0; + } + return 1; + } + else + { + kwsys_ios::cerr << "Got unknown argument: \"" << arg.c_str() << "\"" << kwsys_ios::endl; + this->Internals->LastArgument --; + return 0; + } + } + } + return 1; +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::GetRemainingArguments(int* argc, char*** argv) +{ + CommandLineArguments::Internal::VectorOfStrings::size_type size + = this->Internals->Argv.size() - this->Internals->LastArgument + 1; + CommandLineArguments::Internal::VectorOfStrings::size_type cc; + + // Copy Argv0 as the first argument + char** args = new char*[ size ]; + args[0] = new char[ this->Internals->Argv0.size() + 1 ]; + strcpy(args[0], this->Internals->Argv0.c_str()); + int cnt = 1; + + // Copy everything after the LastArgument, since that was not parsed. + for ( cc = this->Internals->LastArgument+1; + cc < this->Internals->Argv.size(); cc ++ ) + { + args[cnt] = new char[ this->Internals->Argv[cc].size() + 1]; + strcpy(args[cnt], this->Internals->Argv[cc].c_str()); + cnt ++; + } + *argc = cnt; + *argv = args; +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddCallback(const char* argument, ArgumentTypeEnum type, + CallbackType callback, void* call_data, const char* help) +{ + CommandLineArgumentsCallbackStructure s; + s.Argument = argument; + s.ArgumentType = type; + s.Callback = callback; + s.CallData = call_data; + s.VariableType = CommandLineArguments::NO_VARIABLE_TYPE; + s.Variable = 0; + s.Help = help; + + this->Internals->Callbacks[argument] = s; + this->GenerateHelp(); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, + VariableTypeEnum vtype, void* variable, const char* help) +{ + CommandLineArgumentsCallbackStructure s; + s.Argument = argument; + s.ArgumentType = type; + s.Callback = 0; + s.CallData = 0; + s.VariableType = vtype; + s.Variable = variable; + s.Help = help; + + this->Internals->Callbacks[argument] = s; + this->GenerateHelp(); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, + int* variable, const char* help) +{ + this->AddArgument(argument, type, CommandLineArguments::INT_TYPE, variable, help); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, + double* variable, const char* help) +{ + this->AddArgument(argument, type, CommandLineArguments::DOUBLE_TYPE, variable, help); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, + char** variable, const char* help) +{ + this->AddArgument(argument, type, CommandLineArguments::STRING_TYPE, variable, help); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, + kwsys_stl::string* variable, const char* help) +{ + this->AddArgument(argument, type, CommandLineArguments::STL_STRING_TYPE, variable, help); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddArgument(const char* argument, ArgumentTypeEnum type, + bool* variable, const char* help) +{ + this->AddArgument(argument, type, CommandLineArguments::BOOL_TYPE, variable, help); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddBooleanArgument(const char* argument, bool* + variable, const char* help) +{ + this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT, + CommandLineArguments::BOOL_TYPE, variable, help); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::AddBooleanArgument(const char* argument, int* + variable, const char* help) +{ + this->AddArgument(argument, CommandLineArguments::NO_ARGUMENT, + CommandLineArguments::INT_TYPE, variable, help); +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::SetClientData(void* client_data) +{ + this->Internals->ClientData = client_data; +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::SetUnknownArgumentCallback( + CommandLineArguments::ErrorCallbackType callback) +{ + this->Internals->UnknownArgumentCallback = callback; +} + +//---------------------------------------------------------------------------- +const char* CommandLineArguments::GetHelp(const char* arg) +{ + CommandLineArguments::Internal::CallbacksMap::iterator it + = this->Internals->Callbacks.find(arg); + if ( it == this->Internals->Callbacks.end() ) + { + return 0; + } + + // Since several arguments may point to the same argument, find the one this + // one point to if this one is pointing to another argument. + CommandLineArgumentsCallbackStructure *cs = &(it->second); + for(;;) + { + CommandLineArguments::Internal::CallbacksMap::iterator hit + = this->Internals->Callbacks.find(cs->Help); + if ( hit == this->Internals->Callbacks.end() ) + { + break; + } + cs = &(hit->second); + } + return cs->Help; +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::SetLineLength(unsigned int ll) +{ + if ( ll < 9 || ll > 1000 ) + { + return; + } + this->LineLength = ll; + this->GenerateHelp(); +} + +//---------------------------------------------------------------------------- +const char* CommandLineArguments::GetArgv0() +{ + return this->Internals->Argv0.c_str(); +} + +//---------------------------------------------------------------------------- +unsigned int CommandLineArguments::GetLastArgument() +{ + return this->Internals->LastArgument + 1; +} + +//---------------------------------------------------------------------------- +void CommandLineArguments::GenerateHelp() +{ + kwsys_ios::ostringstream str; + + // Collapse all arguments into the map of vectors of all arguments that do + // the same thing. + CommandLineArguments::Internal::CallbacksMap::iterator it; + typedef kwsys_stl::map MapArgs; + MapArgs mp; + MapArgs::iterator mpit, smpit; + for ( it = this->Internals->Callbacks.begin(); + it != this->Internals->Callbacks.end(); + it ++ ) + { + CommandLineArgumentsCallbackStructure *cs = &(it->second); + mpit = mp.find(cs->Help); + if ( mpit != mp.end() ) + { + mpit->second.insert(it->first); + mp[it->first].insert(it->first); + } + else + { + mp[it->first].insert(it->first); + } + } + for ( it = this->Internals->Callbacks.begin(); + it != this->Internals->Callbacks.end(); + it ++ ) + { + CommandLineArgumentsCallbackStructure *cs = &(it->second); + mpit = mp.find(cs->Help); + if ( mpit != mp.end() ) + { + mpit->second.insert(it->first); + smpit = mp.find(it->first); + CommandLineArguments::Internal::SetOfStrings::iterator sit; + for ( sit = smpit->second.begin(); sit != smpit->second.end(); sit++ ) + { + mpit->second.insert(*sit); + } + mp.erase(smpit); + } + else + { + mp[it->first].insert(it->first); + } + } + + // Find the length of the longest string + CommandLineArguments::Internal::String::size_type maxlen = 0; + for ( mpit = mp.begin(); + mpit != mp.end(); + mpit ++ ) + { + CommandLineArguments::Internal::SetOfStrings::iterator sit; + for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ ) + { + CommandLineArguments::Internal::String::size_type clen = sit->size(); + switch ( this->Internals->Callbacks[*sit].ArgumentType ) + { + case CommandLineArguments::NO_ARGUMENT: clen += 0; break; + case CommandLineArguments::CONCAT_ARGUMENT: clen += 3; break; + case CommandLineArguments::SPACE_ARGUMENT: clen += 4; break; + case CommandLineArguments::EQUAL_ARGUMENT: clen += 4; break; + } + if ( clen > maxlen ) + { + maxlen = clen; + } + } + } + + // Create format for that string + char format[80]; + sprintf(format, " %%-%ds ", static_cast(maxlen)); + + maxlen += 4; // For the space before and after the option + + // Print help for each option + for ( mpit = mp.begin(); + mpit != mp.end(); + mpit ++ ) + { + CommandLineArguments::Internal::SetOfStrings::iterator sit; + for ( sit = mpit->second.begin(); sit != mpit->second.end(); sit++ ) + { + str << kwsys_ios::endl; + char argument[100]; + sprintf(argument, sit->c_str()); + switch ( this->Internals->Callbacks[*sit].ArgumentType ) + { + case CommandLineArguments::NO_ARGUMENT: break; + case CommandLineArguments::CONCAT_ARGUMENT: strcat(argument, "opt"); break; + case CommandLineArguments::SPACE_ARGUMENT: strcat(argument, " opt"); break; + case CommandLineArguments::EQUAL_ARGUMENT: strcat(argument, "=opt"); break; + } + char buffer[80]; + sprintf(buffer, format, argument); + str << buffer; + } + const char* ptr = this->Internals->Callbacks[mpit->first].Help; + int len = strlen(ptr); + int cnt = 0; + while ( len > 0) + { + // If argument with help is longer than line length, split it on previous + // space (or tab) and continue on the next line + CommandLineArguments::Internal::String::size_type cc; + for ( cc = 0; ptr[cc]; cc ++ ) + { + if ( *ptr == ' ' || *ptr == '\t' ) + { + ptr ++; + len --; + } + } + if ( cnt > 0 ) + { + for ( cc = 0; cc < maxlen; cc ++ ) + { + str << " "; + } + } + CommandLineArguments::Internal::String::size_type skip = len; + if ( skip > this->LineLength - maxlen ) + { + skip = this->LineLength - maxlen; + for ( cc = skip-1; cc > 0; cc -- ) + { + if ( ptr[cc] == ' ' || ptr[cc] == '\t' ) + { + break; + } + } + if ( cc != 0 ) + { + skip = cc; + } + } + str.write(ptr, skip); + str << kwsys_ios::endl; + ptr += skip; + len -= skip; + cnt ++; + } + } + /* + // This can help debugging help string + str << endl; + unsigned int cc; + for ( cc = 0; cc < this->LineLength; cc ++ ) + { + str << cc % 10; + } + str << endl; + */ + this->Help = str.str(); +} + +} // namespace KWSYS_NAMESPACE diff --git a/Utilities/kwsys/CommandLineArguments.hxx.in b/Utilities/kwsys/CommandLineArguments.hxx.in new file mode 100644 index 0000000..878a01b --- /dev/null +++ b/Utilities/kwsys/CommandLineArguments.hxx.in @@ -0,0 +1,226 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: CommandLineArguments.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_CommandLineArguments_hxx +#define @KWSYS_NAMESPACE@_CommandLineArguments_hxx + +#include <@KWSYS_NAMESPACE@/Configure.h> +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#include <@KWSYS_NAMESPACE@/stl/string> + +/* Define this macro temporarily to keep the code readable. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsys_stl @KWSYS_NAMESPACE@_stl +#endif + +namespace @KWSYS_NAMESPACE@ +{ + +class CommandLineArgumentsInternal; + +/** \class CommandLineArguments + * \brief Command line arguments processing code. + * + * Find specified arguments with optional options and execute specified methods + * or set given variables. + * + * The two interfaces it knows are callback based and variable based. For + * callback based, you have to register callback for particular argument using + * AddCallback method. When that argument is passed, the callback will be + * called with argument, value, and call data. For boolean (NO_ARGUMENT) + * arguments, the value is "1". If the callback returns 0 the argument parsing + * will stop with an error. + * + * For the variable interface you associate variable with each argument. When + * the argument is specified, the variable is set to the specified value casted + * to the apropriate type. For boolean (NO_ARGUMENT), the value is "1". + * + * Both interfaces can be used at the same time. + * + * Possible argument types are: + * NO_ARGUMENT - The argument takes no value : --A + * CONCAT_ARGUMENT - The argument takes value after no space : --Aval + * SPACE_ARGUMENT - The argument takes value after space : --A val + * EQUAL_ARGUMENT - The argument takes value after equal : --A=val + * + * Example use: + * + * kwsys::CommandLineArguments arg; + * arg.Initialize(argc, argv); + * typedef kwsys::CommandLineArguments argT; + * arg.AddArgument("--something", argT::EQUAL_ARGUMENT, &some_variable, + * "This is help string for --something"); + * if ( !arg.Parse() ) + * { + * kwsys_ios::cerr << "Problem parsing arguments" << kwsys_ios::endl; + * res = 1; + * } + * + */ + +class @KWSYS_NAMESPACE@_EXPORT CommandLineArguments +{ +public: + CommandLineArguments(); + ~CommandLineArguments(); + + /** + * Various argument types. + */ + enum ArgumentTypeEnum { + NO_ARGUMENT, + CONCAT_ARGUMENT, + SPACE_ARGUMENT, + EQUAL_ARGUMENT + }; + + /** + * Various variable types. When using the variable interface, this specifies + * what type the variable is. + */ + enum VariableTypeEnum { + NO_VARIABLE_TYPE = 0, // The variable is not specified + INT_TYPE, // The variable is integer (int) + BOOL_TYPE, // The vairable is boolean (bool) + DOUBLE_TYPE, // The variable is float (double) + STRING_TYPE, // The variable is string (char*) + STL_STRING_TYPE // The variable is string (char*) + }; + + /** + * Prototypes for callbacks for callback interface. + */ + typedef int(*CallbackType)(const char* argument, const char* value, + void* call_data); + typedef int(*ErrorCallbackType)(const char* argument, void* client_data); + + /** + * Initialize internal data structures. This should be called before parsing. + */ + void Initialize(int argc, const char* const argv[]); + void Initialize(int argc, char* argv[]); + + /** + * Initialize internal data structure and pass arguments one by one. This is + * convenience method for use from scripting languages where argc and argv + * are not available. + */ + void Initialize(); + void ProcessArgument(const char* arg); + + /** + * This method will parse arguments and call apropriate methods. + */ + int Parse(); + + /** + * This method will add a callback for a specific argument. The arguments to + * it are argument, argument type, callback method, and call data. The + * argument help specifies the help string used with this option. The + * callback and call_data can be skipped. + */ + void AddCallback(const char* argument, ArgumentTypeEnum type, + CallbackType callback, void* call_data, const char* help); + + /** + * Add handler for argument which is going to set the variable to the + * specified value. If the argument is specified, the option is casted to the + * apropriate type. + */ + void AddArgument(const char* argument, ArgumentTypeEnum type, bool* variable, + const char* help); + void AddArgument(const char* argument, ArgumentTypeEnum type, int* variable, + const char* help); + void AddArgument(const char* argument, ArgumentTypeEnum type, + double* variable, const char* help); + void AddArgument(const char* argument, ArgumentTypeEnum type, + char** variable, const char* help); + void AddArgument(const char* argument, ArgumentTypeEnum type, + kwsys_stl::string* variable, const char* help); + + /** + * Add handler for boolean argument. The argument does not take any option + * and if it is specified, the value of the variable is true/1, otherwise it + * is false/0. + */ + void AddBooleanArgument(const char* argument, bool* variable, const char* + help); + void AddBooleanArgument(const char* argument, int* variable, const char* + help); + + /** + * Set the callbacks for error handling. + */ + void SetClientData(void* client_data); + void SetUnknownArgumentCallback(ErrorCallbackType callback); + + /** + * Get remaining arguments. It allocates space for argv, so you have to call + * delete[] on it. + */ + void GetRemainingArguments(int* argc, char*** argv); + + /** + * Return string containing help. If the argument is specified, only return + * help for that argument. + */ + const char* GetHelp() { return this->Help.c_str(); } + const char* GetHelp(const char* arg); + + /** + * Get / Set the help line length. This length is used when generating the + * help page. Default length is 80. + */ + void SetLineLength(unsigned int); + unsigned int GetLineLength(); + + /** + * Get the executable name (argv0). This is only available when using + * Initialize with argc/argv. + */ + const char* GetArgv0(); + + /** + * Get index of the last argument parsed. This is the last argument that was + * parsed ok in the original argc/argv list. + */ + unsigned int GetLastArgument(); + +protected: + void GenerateHelp(); + + //! This is internal method that registers variable with argument + void AddArgument(const char* argument, ArgumentTypeEnum type, + VariableTypeEnum vtype, void* variable, const char* help); + + typedef CommandLineArgumentsInternal Internal; + Internal* Internals; + kwsys_stl::string Help; + + unsigned int LineLength; +}; + +} // namespace @KWSYS_NAMESPACE@ + +/* Undefine temporary macro. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsys_stl +#endif + +#endif + + + + + diff --git a/Utilities/kwsys/Configure.h.in b/Utilities/kwsys/Configure.h.in new file mode 100644 index 0000000..1dace1b --- /dev/null +++ b/Utilities/kwsys/Configure.h.in @@ -0,0 +1,70 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Configure.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_Configure_h +#define @KWSYS_NAMESPACE@_Configure_h + +/* If we are building a kwsys .c or .cxx file, let it use the kwsys + namespace. When not building a kwsys source file these macros are + temporarily defined inside the headers that use them. */ +#if defined(KWSYS_NAMESPACE) +# define kwsys_ns(x) @KWSYS_NAMESPACE@##x +# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT +#endif + +/* Setup the export macro. */ +#if defined(_WIN32) && @KWSYS_BUILD_SHARED@ +# if defined(@KWSYS_NAMESPACE@_EXPORTS) +# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllexport) +# else +# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllimport) +# endif +#else +# define @KWSYS_NAMESPACE@_EXPORT +#endif + +/* Enable warnings that are off by default but are useful. */ +#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_ENABLE) +# if defined(_MSC_VER) +# pragma warning ( default : 4263 ) /* no override, call convention differs */ +# endif +#endif + +/* Disable warnings that are on by default but occur in valid code. */ +#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE) +# if defined(_MSC_VER) +# pragma warning (disable: 4097) /* typedef is synonym for class */ +# pragma warning (disable: 4127) /* conditional expression is constant */ +# pragma warning (disable: 4244) /* possible loss in conversion */ +# pragma warning (disable: 4251) /* missing DLL-interface */ +# pragma warning (disable: 4305) /* truncation from type1 to type2 */ +# pragma warning (disable: 4309) /* truncation of constant value */ +# pragma warning (disable: 4514) /* unreferenced inline function */ +# pragma warning (disable: 4706) /* assignment in conditional expression */ +# pragma warning (disable: 4710) /* function not inlined */ +# pragma warning (disable: 4786) /* identifier truncated in debug info */ +# endif +#endif + +/* MSVC 6.0 in release mode will warn about code it produces with its + optimizer. Disable the warnings specifically for this + configuration. Real warnings will be revealed by a debug build or + by other compilers. */ +#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE_BOGUS) +# if defined(_MSC_VER) && (_MSC_VER < 1300) && defined(NDEBUG) +# pragma warning ( disable : 4701 ) /* Variable may be used uninitialized. */ +# pragma warning ( disable : 4702 ) /* Unreachable code. */ +# endif +#endif + +#endif diff --git a/Utilities/kwsys/Configure.hxx.in b/Utilities/kwsys/Configure.hxx.in new file mode 100644 index 0000000..cb7817f --- /dev/null +++ b/Utilities/kwsys/Configure.hxx.in @@ -0,0 +1,168 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Configure.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_Configure_hxx +#define @KWSYS_NAMESPACE@_Configure_hxx + +/* Include C configuration. */ +#include <@KWSYS_NAMESPACE@/Configure.h> + +/* Whether kwsys namespace is "kwsys". */ +#define @KWSYS_NAMESPACE@_NAME_IS_KWSYS @KWSYS_NAME_IS_KWSYS@ + +/* Whether ANSI C++ stream headers are to be used. */ +#define @KWSYS_NAMESPACE@_IOS_USE_ANSI @KWSYS_IOS_USE_ANSI@ + +/* Whether ANSI C++ streams are in std namespace. */ +#define @KWSYS_NAMESPACE@_IOS_HAVE_STD @KWSYS_IOS_HAVE_STD@ + +/* Whether ANSI C++ header is to be used. */ +#define @KWSYS_NAMESPACE@_IOS_USE_SSTREAM @KWSYS_IOS_USE_SSTREAM@ + +/* Whether old C++ header is to be used. */ +#define @KWSYS_NAMESPACE@_IOS_USE_STRSTREAM_H @KWSYS_IOS_USE_STRSTREAM_H@ + +/* Whether old C++ header is to be used. */ +#define @KWSYS_NAMESPACE@_IOS_USE_STRSTREA_H @KWSYS_IOS_USE_STRSTREA_H@ + +/* Whether STL is in std namespace. */ +#define @KWSYS_NAMESPACE@_STL_HAVE_STD @KWSYS_STL_HAVE_STD@ + +/* Whether the STL string has operator<< for ostream. */ +#define @KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM @KWSYS_STL_STRING_HAVE_OSTREAM@ + +/* Whether the STL string has operator>> for istream. */ +#define @KWSYS_NAMESPACE@_STL_STRING_HAVE_ISTREAM @KWSYS_STL_STRING_HAVE_ISTREAM@ + +/* Whether the STL string has operator!= for char*. */ +#define @KWSYS_NAMESPACE@_STL_STRING_HAVE_NEQ_CHAR @KWSYS_STL_STRING_HAVE_NEQ_CHAR@ + +/* Define the stl namespace macro. */ +#if @KWSYS_NAMESPACE@_STL_HAVE_STD +# define @KWSYS_NAMESPACE@_stl std +#else +# define @KWSYS_NAMESPACE@_stl +#endif + +/* Define the ios namespace macro. */ +#if @KWSYS_NAMESPACE@_IOS_HAVE_STD +# define @KWSYS_NAMESPACE@_ios_namespace std +#else +# define @KWSYS_NAMESPACE@_ios_namespace +#endif +#if @KWSYS_NAMESPACE@_IOS_USE_SSTREAM +# define @KWSYS_NAMESPACE@_ios @KWSYS_NAMESPACE@_ios_namespace +#else +# define @KWSYS_NAMESPACE@_ios @KWSYS_NAMESPACE@_ios +#endif + +/* Whether the cstddef header is available. */ +#define @KWSYS_NAMESPACE@_CXX_HAS_CSTDDEF @KWSYS_CXX_HAS_CSTDDEF@ + +/* Whether the compiler supports null template arguments. */ +#define @KWSYS_NAMESPACE@_CXX_HAS_NULL_TEMPLATE_ARGS @KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS@ + +/* Define the null template arguments macro. */ +#if @KWSYS_NAMESPACE@_CXX_HAS_NULL_TEMPLATE_ARGS +# define @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS <> +#else +# define @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS +#endif + +/* Whether the compiler supports member templates. */ +#define @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES @KWSYS_CXX_HAS_MEMBER_TEMPLATES@ + +/* Whether the compiler supports argument dependent lookup. */ +#define @KWSYS_NAMESPACE@_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP @KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP@ + +/* Whether the compiler supports standard full specialization syntax. */ +#define @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION @KWSYS_CXX_HAS_FULL_SPECIALIZATION@ + +/* Define the specialization definition macro. */ +#if @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION +# define @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION template <> +#else +# define @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +#endif + +/* Define typename keyword macro for use in declarations. */ +#if defined(_MSC_VER) && _MSC_VER < 1300 +# define @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME +#else +# define @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME typename +#endif + +/* Whether the stl has iterator_traits. */ +#define @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_TRAITS @KWSYS_STL_HAS_ITERATOR_TRAITS@ + +/* Whether the stl has iterator_category. */ +#define @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_CATEGORY @KWSYS_STL_HAS_ITERATOR_CATEGORY@ + +/* Whether the stl has __iterator_category. */ +#define @KWSYS_NAMESPACE@_STL_HAS___ITERATOR_CATEGORY @KWSYS_STL_HAS___ITERATOR_CATEGORY@ + +/* Whether the stl allocator is the standard template. */ +#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE @KWSYS_STL_HAS_ALLOCATOR_TEMPLATE@ + +/* Whether the stl allocator is not a template. */ +#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE @KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE@ + +/* Whether the stl allocator has rebind. */ +#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND @KWSYS_STL_HAS_ALLOCATOR_REBIND@ + +/* Whether the stl allocator has a size argument for max_size. */ +#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT @KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT@ + +/* Whether the stl containers support allocator objects. */ +#define @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS @KWSYS_STL_HAS_ALLOCATOR_OBJECTS@ + +/* Whether struct stat has the st_mtim member for high resolution times. */ +#define @KWSYS_NAMESPACE@_STAT_HAS_ST_MTIM @KWSYS_STAT_HAS_ST_MTIM@ + +/* If building a C++ file in kwsys itself, give the source file + access to the macros without a configured namespace. */ +#if defined(KWSYS_NAMESPACE) +# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsys_stl @KWSYS_NAMESPACE@_stl +# define kwsys_ios @KWSYS_NAMESPACE@_ios +# define kwsys @KWSYS_NAMESPACE@ +# endif +# define KWSYS_NAME_IS_KWSYS @KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define KWSYS_STL_HAVE_STD @KWSYS_NAMESPACE@_STL_HAVE_STD +# define KWSYS_IOS_HAVE_STD @KWSYS_NAMESPACE@_IOS_HAVE_STD +# define KWSYS_IOS_USE_ANSI @KWSYS_NAMESPACE@_IOS_USE_ANSI +# define KWSYS_IOS_USE_SSTREAM @KWSYS_NAMESPACE@_IOS_USE_SSTREAM +# define KWSYS_IOS_USE_STRSTREAM_H @KWSYS_NAMESPACE@_IOS_USE_STRSTREAM_H +# define KWSYS_IOS_USE_STRSTREA_H @KWSYS_NAMESPACE@_IOS_USE_STRSTREA_H +# define KWSYS_STAT_HAS_ST_MTIM @KWSYS_NAMESPACE@_STAT_HAS_ST_MTIM +# define KWSYS_CXX_HAS_CSTDDEF @KWSYS_NAMESPACE@_CXX_HAS_CSTDDEF +# define KWSYS_STL_STRING_HAVE_OSTREAM @KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM +# define KWSYS_STL_STRING_HAVE_ISTREAM @KWSYS_NAMESPACE@_STL_STRING_HAVE_ISTREAM +# define KWSYS_STL_STRING_HAVE_NEQ_CHAR @KWSYS_NAMESPACE@_STL_STRING_HAVE_NEQ_CHAR +# define KWSYS_CXX_NULL_TEMPLATE_ARGS @KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS +# define KWSYS_CXX_HAS_MEMBER_TEMPLATES @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES +# define KWSYS_CXX_HAS_FULL_SPECIALIZATION @KWSYS_NAMESPACE@_CXX_HAS_FULL_SPECIALIZATION +# define KWSYS_CXX_DEFINE_SPECIALIZATION @KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +# define KWSYS_CXX_DECL_TYPENAME @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME +# define KWSYS_STL_HAS_ALLOCATOR_REBIND @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND +# define KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT +# define KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP @KWSYS_NAMESPACE@_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP +# define KWSYS_STL_HAS_ITERATOR_TRAITS @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_TRAITS +# define KWSYS_STL_HAS_ITERATOR_CATEGORY @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_CATEGORY +# define KWSYS_STL_HAS___ITERATOR_CATEGORY @KWSYS_NAMESPACE@_STL_HAS___ITERATOR_CATEGORY +# define KWSYS_STL_HAS_ALLOCATOR_TEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE +# define KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE +# define KWSYS_STL_HAS_ALLOCATOR_OBJECTS @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS +#endif + +#endif diff --git a/Utilities/kwsys/Copyright.txt b/Utilities/kwsys/Copyright.txt new file mode 100644 index 0000000..86e0e73 --- /dev/null +++ b/Utilities/kwsys/Copyright.txt @@ -0,0 +1,33 @@ +Copyright (c) 2000-2003 Kitware, Inc., Insight Consortium. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + + * Neither the name of Kitware nor the names of any contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + + * Modified source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Utilities/kwsys/Directory.cxx b/Utilities/kwsys/Directory.cxx new file mode 100644 index 0000000..46a30cc --- /dev/null +++ b/Utilities/kwsys/Directory.cxx @@ -0,0 +1,163 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Directory.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Directory.hxx) + +#include KWSYS_HEADER(Configure.hxx) + +#include KWSYS_HEADER(stl/string) +#include KWSYS_HEADER(stl/vector) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Directory.hxx.in" +# include "Configure.hxx.in" +# include "kwsys_stl.hxx.in" +# include "kwsys_stl_string.hxx.in" +#endif + +namespace KWSYS_NAMESPACE +{ + +//---------------------------------------------------------------------------- +class DirectoryInternals +{ +public: + // Array of Files + kwsys_stl::vector Files; + + // Path to Open'ed directory + kwsys_stl::string Path; +}; + +//---------------------------------------------------------------------------- +Directory::Directory() +{ + this->Internal = new DirectoryInternals; +} + +//---------------------------------------------------------------------------- +Directory::~Directory() +{ + delete this->Internal; +} + +//---------------------------------------------------------------------------- +unsigned long Directory::GetNumberOfFiles() +{ + return static_cast(this->Internal->Files.size()); +} + +//---------------------------------------------------------------------------- +const char* Directory::GetFile(unsigned long dindex) +{ + if ( dindex >= this->Internal->Files.size() ) + { + return 0; + } + return this->Internal->Files[dindex].c_str(); +} + +} // namespace KWSYS_NAMESPACE + +// First microsoft compilers + +#ifdef _MSC_VER +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace KWSYS_NAMESPACE +{ + +bool Directory::Load(const char* name) +{ +#if _MSC_VER < 1300 + long srchHandle; +#else + intptr_t srchHandle; +#endif + char* buf; + size_t n = strlen(name); + if ( name[n - 1] == '/' ) + { + buf = new char[n + 1 + 1]; + sprintf(buf, "%s*", name); + } + else + { + buf = new char[n + 2 + 1]; + sprintf(buf, "%s/*", name); + } + struct _finddata_t data; // data of current file + + // Now put them into the file array + srchHandle = _findfirst(buf, &data); + delete [] buf; + + if ( srchHandle == -1 ) + { + return 0; + } + + // Loop through names + do + { + this->Internal->Files.push_back(data.name); + } + while ( _findnext(srchHandle, &data) != -1 ); + this->Internal->Path = name; + return _findclose(srchHandle) != -1; +} + +} // namespace KWSYS_NAMESPACE + +#else + +// Now the POSIX style directory access + +#include +#include + +namespace KWSYS_NAMESPACE +{ + +bool Directory::Load(const char* name) +{ + DIR* dir = opendir(name); + + if (!dir) + { + return 0; + } + + for (dirent* d = readdir(dir); d; d = readdir(dir) ) + { + this->Internal->Files.push_back(d->d_name); + } + this->Internal->Path = name; + closedir(dir); + return 1; +} + +} // namespace KWSYS_NAMESPACE + +#endif diff --git a/Utilities/kwsys/Directory.hxx.in b/Utilities/kwsys/Directory.hxx.in new file mode 100644 index 0000000..cce03d1 --- /dev/null +++ b/Utilities/kwsys/Directory.hxx.in @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Directory.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_Directory_hxx +#define @KWSYS_NAMESPACE@_Directory_hxx + +#include <@KWSYS_NAMESPACE@/Configure.h> + +namespace @KWSYS_NAMESPACE@ +{ + +class DirectoryInternals; + +/** \class Directory + * \brief Portable directory/filename traversal. + * + * Directory provides a portable way of finding the names of the files + * in a system directory. + * + * Directory currently works with Windows and Unix operating systems. + */ +class @KWSYS_NAMESPACE@_EXPORT Directory +{ +public: + Directory(); + ~Directory(); + + /** + * Load the specified directory and load the names of the files + * in that directory. 0 is returned if the directory can not be + * opened, 1 if it is opened. + */ + bool Load(const char*); + + /** + * Return the number of files in the current directory. + */ + unsigned long GetNumberOfFiles(); + + /** + * Return the file at the given index, the indexing is 0 based + */ + const char* GetFile(unsigned long); + +private: + // Private implementation details. + DirectoryInternals* Internal; +}; // End Class: Directory + +} // namespace @KWSYS_NAMESPACE@ + +#endif diff --git a/Utilities/kwsys/EncodeExecutable.c b/Utilities/kwsys/EncodeExecutable.c new file mode 100644 index 0000000..5e822d0 --- /dev/null +++ b/Utilities/kwsys/EncodeExecutable.c @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: EncodeExecutable.c,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include + +int main(int argc, char* argv[]) +{ + FILE* ifp; + FILE* ofp; + int i; + int n; + int count = 0; + unsigned char buffer[1024]; + + /* Check arguments. */ + if(argc != 5) + { + fprintf(stderr, "Usage: %s \n", + argv[0]); + return 1; + } + + /* Open the input file. */ + ifp = fopen(argv[1], "rb"); + if(!ifp) + { + fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]); + return 2; + } + ofp = fopen(argv[2], "w"); + if(!ofp) + { + fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]); + return 2; + } + + /* Prepend header comment. */ + fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n"); + fprintf(ofp, " * %s\n */\n\n", argv[0]); + fprintf(ofp, "#include \"kwsysPrivate.h\"\n"); + fprintf(ofp, "#include KWSYS_HEADER(Configure.h)\n\n"); + fprintf(ofp, "#include \n\n"); + + /* Split file up in 1024-byte chunks. */ + while((n = (int)fread(buffer, 1, 1024, ifp)) > 0) + { + fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n", + argv[4], count++, n); + for(i=0; i < n-1; ++i) + { + fprintf(ofp, "0x%02X", buffer[i]); + if(i%10 == 9) + { + fprintf(ofp, ",\n"); + } + else + { + fprintf(ofp, ", "); + } + } + fprintf(ofp, "0x%02X};\n\n", buffer[n-1]); + } + fclose(ifp); + + /* Provide a function to write the data to a file. */ + fprintf(ofp, "extern %s_EXPORT int %sEncodedWriteArray%s(const char* fname)\n", + argv[3], argv[3], argv[4]); + fprintf(ofp, "{\n"); + fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n"); + fprintf(ofp, " if(!ofp) { return 0; }\n"); + for(i=0; i < count; ++i) + { + fprintf(ofp, " if(fwrite(kwsysEncodedArray%s_%d, 1,\n" + " sizeof(kwsysEncodedArray%s_%d), ofp) !=\n" + " sizeof(kwsysEncodedArray%s_%d))\n", + argv[4], i, argv[4], i, argv[4], i); + fprintf(ofp, " {\n"); + fprintf(ofp, " fclose(ofp);\n"); + fprintf(ofp, " _unlink(fname);\n"); + fprintf(ofp, " return 0;\n"); + fprintf(ofp, " }\n"); + } + fprintf(ofp, " fclose(ofp);\n"); + fprintf(ofp, " return 1;\n"); + fprintf(ofp, "}\n"); + fclose(ofp); + return 0; +} diff --git a/Utilities/kwsys/ExtraTest.cmake.in b/Utilities/kwsys/ExtraTest.cmake.in new file mode 100644 index 0000000..e8c0a1c --- /dev/null +++ b/Utilities/kwsys/ExtraTest.cmake.in @@ -0,0 +1 @@ +MESSAGE("*** This message is generated by message inside a file that is included in DartTestfile.txt ***") diff --git a/Utilities/kwsys/FundamentalType.h.in b/Utilities/kwsys/FundamentalType.h.in new file mode 100644 index 0000000..648270f --- /dev/null +++ b/Utilities/kwsys/FundamentalType.h.in @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: FundamentalType.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_FundamentalType_h +#define @KWSYS_NAMESPACE@_FundamentalType_h + +#include <@KWSYS_NAMESPACE@/Configure.h> + +/* Redefine all public interface symbol names to be in the proper + namespace. These macros are used internally to kwsys only, and are + not visible to user code. Use kwsysHeaderDump.pl to reproduce + these macros after making changes to the interface. */ +#if !defined(KWSYS_NAMESPACE) +# define kwsys_ns(x) @KWSYS_NAMESPACE@##x +# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT +#endif +#define kwsysFundamentalType kwsys_ns(FundamentalType) +#define kwsysFundamentalType_Int8 kwsys_ns(FundamentalType_Int8) +#define kwsysFundamentalType_UInt8 kwsys_ns(FundamentalType_UInt8) +#define kwsysFundamentalType_Int16 kwsys_ns(FundamentalType_Int16) +#define kwsysFundamentalType_UInt16 kwsys_ns(FundamentalType_UInt16) +#define kwsysFundamentalType_Int32 kwsys_ns(FundamentalType_Int32) +#define kwsysFundamentalType_UInt32 kwsys_ns(FundamentalType_UInt32) +#define kwsysFundamentalType_Int64 kwsys_ns(FundamentalType_Int64) +#define kwsysFundamentalType_UInt64 kwsys_ns(FundamentalType_UInt64) + +/* The size of fundamental types. Types that do not exist have size 0. */ +#define @KWSYS_NAMESPACE@_SIZEOF_CHAR @KWSYS_SIZEOF_CHAR@ +#define @KWSYS_NAMESPACE@_SIZEOF_SHORT @KWSYS_SIZEOF_SHORT@ +#define @KWSYS_NAMESPACE@_SIZEOF_INT @KWSYS_SIZEOF_INT@ +#define @KWSYS_NAMESPACE@_SIZEOF_LONG @KWSYS_SIZEOF_LONG@ +#define @KWSYS_NAMESPACE@_SIZEOF_LONG_LONG @KWSYS_SIZEOF_LONG_LONG@ +#define @KWSYS_NAMESPACE@_SIZEOF___INT64 @KWSYS_SIZEOF___INT64@ + +/* Whether types "long long" and "__int64" are enabled. If a type is + enabled then it is a unique fundamental type. */ +#define @KWSYS_NAMESPACE@_USE_LONG_LONG @KWSYS_USE_LONG_LONG@ +#define @KWSYS_NAMESPACE@_USE___INT64 @KWSYS_USE___INT64@ + +/* Whether type "char" is signed (it may be signed or unsigned). */ +#define @KWSYS_NAMESPACE@_CHAR_IS_SIGNED @KWSYS_CHAR_IS_SIGNED@ + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Select an 8-bit integer type. */ +#if @KWSYS_NAMESPACE@_SIZEOF_CHAR == 1 +typedef signed char kwsysFundamentalType_Int8; +typedef unsigned char kwsysFundamentalType_UInt8; +#else +# error "No native data type can represent an 8-bit integer." +#endif + +/* Select a 16-bit integer type. */ +#if @KWSYS_NAMESPACE@_SIZEOF_SHORT == 2 +typedef short kwsysFundamentalType_Int16; +typedef unsigned short kwsysFundamentalType_UInt16; +#elif @KWSYS_NAMESPACE@_SIZEOF_INT == 2 +typedef int kwsysFundamentalType_Int16; +typedef unsigned int kwsysFundamentalType_UInt16; +#else +# error "No native data type can represent a 16-bit integer." +#endif + +/* Select a 32-bit integer type. */ +#if @KWSYS_NAMESPACE@_SIZEOF_INT == 4 +typedef int kwsysFundamentalType_Int32; +typedef unsigned int kwsysFundamentalType_UInt32; +#elif @KWSYS_NAMESPACE@_SIZEOF_LONG == 4 +typedef long kwsysFundamentalType_Int32; +typedef unsigned long kwsysFundamentalType_UInt32; +#else +# error "No native data type can represent a 32-bit integer." +#endif + +/* Select a 64-bit integer type. */ +#if @KWSYS_NAMESPACE@_SIZEOF_LONG == 8 +typedef signed long kwsysFundamentalType_Int64; +typedef unsigned long kwsysFundamentalType_UInt64; +/* Whether UInt64 can be converted to double. */ +# define @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE 1 +#elif @KWSYS_NAMESPACE@_USE_LONG_LONG && @KWSYS_NAMESPACE@_SIZEOF_LONG_LONG == 8 +typedef signed long long kwsysFundamentalType_Int64; +typedef unsigned long long kwsysFundamentalType_UInt64; +/* Whether UInt64 can be converted to double. */ +# define @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE 1 +#elif @KWSYS_NAMESPACE@_USE___INT64 && @KWSYS_NAMESPACE@_SIZEOF___INT64 == 8 +typedef signed __int64 kwsysFundamentalType_Int64; +typedef unsigned __int64 kwsysFundamentalType_UInt64; +/* Whether UInt64 can be converted to double. */ +# define @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE @KWSYS_CAN_CONVERT_UI64_TO_DOUBLE@ +#else +# error "No native data type can represent a 64-bit integer." +#endif + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +/* If we are building a kwsys .c or .cxx file, let it use these macros. + Otherwise, undefine them to keep the namespace clean. */ +#if !defined(KWSYS_NAMESPACE) +# undef kwsys_ns +# undef kwsysEXPORT +# undef kwsysFundamentalType +# undef kwsysFundamentalType_Int8 +# undef kwsysFundamentalType_UInt8 +# undef kwsysFundamentalType_Int16 +# undef kwsysFundamentalType_UInt16 +# undef kwsysFundamentalType_Int32 +# undef kwsysFundamentalType_UInt32 +# undef kwsysFundamentalType_Int64 +# undef kwsysFundamentalType_UInt64 +#endif + +/* If building a C or C++ file in kwsys itself, give the source file + access to the configured macros without a configured namespace. */ +#if defined(KWSYS_NAMESPACE) +# define KWSYS_SIZEOF_CHAR @KWSYS_NAMESPACE@_SIZEOF_CHAR +# define KWSYS_SIZEOF_SHORT @KWSYS_NAMESPACE@_SIZEOF_SHORT +# define KWSYS_SIZEOF_INT @KWSYS_NAMESPACE@_SIZEOF_INT +# define KWSYS_SIZEOF_LONG @KWSYS_NAMESPACE@_SIZEOF_LONG +# define KWSYS_SIZEOF_LONG_LONG @KWSYS_NAMESPACE@_SIZEOF_LONG_LONG +# define KWSYS_SIZEOF___INT64 @KWSYS_NAMESPACE@_SIZEOF___INT64 +# define KWSYS_USE_LONG_LONG @KWSYS_NAMESPACE@_USE_LONG_LONG +# define KWSYS_USE___INT64 @KWSYS_NAMESPACE@_USE___INT64 +# define KWSYS_CHAR_IS_SIGNED @KWSYS_NAMESPACE@_CHAR_IS_SIGNED +# define KWSYS_CAN_CONVERT_UI64_TO_DOUBLE @KWSYS_NAMESPACE@_CAN_CONVERT_UI64_TO_DOUBLE +#endif + +#endif diff --git a/Utilities/kwsys/Glob.cxx b/Utilities/kwsys/Glob.cxx new file mode 100644 index 0000000..72cfdb9 --- /dev/null +++ b/Utilities/kwsys/Glob.cxx @@ -0,0 +1,496 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Glob.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Glob.hxx) + +#include KWSYS_HEADER(Configure.hxx) + +#include KWSYS_HEADER(RegularExpression.hxx) +#include KWSYS_HEADER(SystemTools.hxx) +#include KWSYS_HEADER(Directory.hxx) +#include KWSYS_HEADER(stl/string) +#include KWSYS_HEADER(stl/vector) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Glob.hxx.in" +# include "Directory.hxx.in" +# include "Configure.hxx.in" +# include "RegularExpression.hxx.in" +# include "SystemTools.hxx.in" +# include "kwsys_stl.hxx.in" +# include "kwsys_stl_string.hxx.in" +#endif + +#include +#include +#include +namespace KWSYS_NAMESPACE +{ +#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__) +// On Windows and apple, no difference between lower and upper case +# define KWSYS_GLOB_CASE_INDEPENDENT +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) +// Handle network paths +# define KWSYS_GLOB_SUPPORT_NETWORK_PATHS +#endif + +//---------------------------------------------------------------------------- +class GlobInternals +{ +public: + kwsys_stl::vector Files; + kwsys_stl::vector Expressions; +}; + +//---------------------------------------------------------------------------- +Glob::Glob() +{ + this->Internals = new GlobInternals; + this->Recurse = false; + this->Relative = ""; +} + +//---------------------------------------------------------------------------- +Glob::~Glob() +{ + delete this->Internals; +} + +//---------------------------------------------------------------------------- +kwsys_stl::vector& Glob::GetFiles() +{ + return this->Internals->Files; +} + +//---------------------------------------------------------------------------- +kwsys_stl::string Glob::PatternToRegex(const kwsys_stl::string& pattern, + bool require_whole_string) +{ + // Incrementally build the regular expression from the pattern. + kwsys_stl::string regex = require_whole_string? "^" : ""; + kwsys_stl::string::const_iterator pattern_first = pattern.begin(); + kwsys_stl::string::const_iterator pattern_last = pattern.end(); + for(kwsys_stl::string::const_iterator i = pattern_first; + i != pattern_last; ++i) + { + int c = *i; + if(c == '*') + { + // A '*' (not between brackets) matches any string. + // We modify this to not match slashes since the orignal glob + // pattern documentation was meant for matching file name + // components separated by slashes. + regex += "[^/]*"; + } + else if(c == '?') + { + // A '?' (not between brackets) matches any single character. + // We modify this to not match slashes since the orignal glob + // pattern documentation was meant for matching file name + // components separated by slashes. + regex += "[^/]"; + } + else if(c == '[') + { + // Parse out the bracket expression. It begins just after the + // opening character. + kwsys_stl::string::const_iterator bracket_first = i+1; + kwsys_stl::string::const_iterator bracket_last = bracket_first; + + // The first character may be complementation '!' or '^'. + if(bracket_last != pattern_last && + (*bracket_last == '!' || *bracket_last == '^')) + { + ++bracket_last; + } + + // If the next character is a ']' it is included in the brackets + // because the bracket string may not be empty. + if(bracket_last != pattern_last && *bracket_last == ']') + { + ++bracket_last; + } + + // Search for the closing ']'. + while(bracket_last != pattern_last && *bracket_last != ']') + { + ++bracket_last; + } + + // Check whether we have a complete bracket string. + if(bracket_last == pattern_last) + { + // The bracket string did not end, so it was opened simply by + // a '[' that is supposed to be matched literally. + regex += "\\["; + } + else + { + // Convert the bracket string to its regex equivalent. + kwsys_stl::string::const_iterator k = bracket_first; + + // Open the regex block. + regex += "["; + + // A regex range complement uses '^' instead of '!'. + if(k != bracket_last && *k == '!') + { + regex += "^"; + ++k; + } + + // Convert the remaining characters. + for(; k != bracket_last; ++k) + { + // Backslashes must be escaped. + if(*k == '\\') + { + regex += "\\"; + } + + // Store this character. + regex += *k; + } + + // Close the regex block. + regex += "]"; + + // Jump to the end of the bracket string. + i = bracket_last; + } + } + else + { + // A single character matches itself. + int ch = c; + if(!(('a' <= ch && ch <= 'z') || + ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9'))) + { + // Escape the non-alphanumeric character. + regex += "\\"; + } +#if defined(KWSYS_GLOB_CASE_INDEPENDENT) + else + { + // On case-insensitive systems file names are converted to lower + // case before matching. + ch = tolower(ch); + } +#endif + + // Store the character. + regex.append(1, static_cast(ch)); + } + } + + if(require_whole_string) + { + regex += "$"; + } + return regex; +} + +//---------------------------------------------------------------------------- +void Glob::RecurseDirectory(kwsys_stl::string::size_type start, + const kwsys_stl::string& dir, bool dir_only) +{ + kwsys::Directory d; + if ( !d.Load(dir.c_str()) ) + { + return; + } + unsigned long cc; + kwsys_stl::string fullname; + kwsys_stl::string realname; + kwsys_stl::string fname; + for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ ) + { + fname = d.GetFile(cc); + if ( strcmp(fname.c_str(), ".") == 0 || + strcmp(fname.c_str(), "..") == 0 ) + { + continue; + } + + if ( start == 0 ) + { + realname = dir + fname; + } + else + { + realname = dir + "/" + fname; + } + +#if defined( KWSYS_GLOB_CASE_INDEPENDENT ) + // On Windows and apple, no difference between lower and upper case + fname = kwsys::SystemTools::LowerCase(fname); +#endif + + if ( start == 0 ) + { + fullname = dir + fname; + } + else + { + fullname = dir + "/" + fname; + } + + if ( !dir_only || !kwsys::SystemTools::FileIsDirectory(realname.c_str()) ) + { + if ( this->Internals->Expressions[ + this->Internals->Expressions.size()-1].find(fname.c_str()) ) + { + this->AddFile(this->Internals->Files, realname.c_str()); + } + } + if ( kwsys::SystemTools::FileIsDirectory(realname.c_str()) ) + { + this->RecurseDirectory(start+1, realname, dir_only); + } + } +} + +//---------------------------------------------------------------------------- +void Glob::ProcessDirectory(kwsys_stl::string::size_type start, + const kwsys_stl::string& dir, bool dir_only) +{ + //kwsys_ios::cout << "ProcessDirectory: " << dir << kwsys_ios::endl; + bool last = ( start == this->Internals->Expressions.size()-1 ); + if ( last && this->Recurse ) + { + this->RecurseDirectory(start, dir, dir_only); + return; + } + kwsys::Directory d; + if ( !d.Load(dir.c_str()) ) + { + return; + } + unsigned long cc; + kwsys_stl::string fullname; + kwsys_stl::string realname; + kwsys_stl::string fname; + for ( cc = 0; cc < d.GetNumberOfFiles(); cc ++ ) + { + fname = d.GetFile(cc); + if ( strcmp(fname.c_str(), ".") == 0 || + strcmp(fname.c_str(), "..") == 0 ) + { + continue; + } + + if ( start == 0 ) + { + realname = dir + fname; + } + else + { + realname = dir + "/" + fname; + } + +#if defined(KWSYS_GLOB_CASE_INDEPENDENT) + // On case-insensitive file systems convert to lower case for matching. + fname = kwsys::SystemTools::LowerCase(fname); +#endif + + if ( start == 0 ) + { + fullname = dir + fname; + } + else + { + fullname = dir + "/" + fname; + } + + //kwsys_ios::cout << "Look at file: " << fname << kwsys_ios::endl; + //kwsys_ios::cout << "Match: " + // << this->Internals->TextExpressions[start].c_str() << kwsys_ios::endl; + //kwsys_ios::cout << "Full name: " << fullname << kwsys_ios::endl; + + if ( (!dir_only || !last) && + !kwsys::SystemTools::FileIsDirectory(realname.c_str()) ) + { + continue; + } + + if ( this->Internals->Expressions[start].find(fname.c_str()) ) + { + if ( last ) + { + this->AddFile(this->Internals->Files, realname.c_str()); + } + else + { + this->ProcessDirectory(start+1, realname + "/", dir_only); + } + } + } +} + +//---------------------------------------------------------------------------- +bool Glob::FindFiles(const kwsys_stl::string& inexpr) +{ + kwsys_stl::string cexpr; + kwsys_stl::string::size_type cc; + kwsys_stl::string expr = inexpr; + + this->Internals->Expressions.clear(); + this->Internals->Files.clear(); + + if ( !kwsys::SystemTools::FileIsFullPath(expr.c_str()) ) + { + expr = kwsys::SystemTools::GetCurrentWorkingDirectory(); + expr += "/" + inexpr; + } + kwsys_stl::string fexpr = expr; + + int skip = 0; + int last_slash = 0; + for ( cc = 0; cc < expr.size(); cc ++ ) + { + if ( cc > 0 && expr[cc] == '/' && expr[cc-1] != '\\' ) + { + last_slash = static_cast(cc); + } + if ( cc > 0 && + (expr[cc] == '[' || expr[cc] == '?' || expr[cc] == '*') && + expr[cc-1] != '\\' ) + { + break; + } + } + if ( last_slash > 0 ) + { + //kwsys_ios::cout << "I can skip: " << fexpr.substr(0, last_slash) + //<< kwsys_ios::endl; + skip = last_slash; + } + if ( skip == 0 ) + { +#if defined( KWSYS_GLOB_SUPPORT_NETWORK_PATHS ) + // Handle network paths + if ( expr[0] == '/' && expr[1] == '/' ) + { + int cnt = 0; + for ( cc = 2; cc < expr.size(); cc ++ ) + { + if ( expr[cc] == '/' ) + { + cnt ++; + if ( cnt == 2 ) + { + break; + } + } + } + skip = int(cc + 1); + } + else +#endif + // Handle drive letters on Windows + if ( expr[1] == ':' && expr[0] != '/' ) + { + skip = 2; + } + } + + if ( skip > 0 ) + { + expr = expr.substr(skip); + } + + cexpr = ""; + for ( cc = 0; cc < expr.size(); cc ++ ) + { + int ch = expr[cc]; + if ( ch == '/' ) + { + if ( cexpr.size() > 0 ) + { + this->AddExpression(cexpr.c_str()); + } + cexpr = ""; + } + else + { + cexpr.append(1, static_cast(ch)); + } + } + if ( cexpr.size() > 0 ) + { + this->AddExpression(cexpr.c_str()); + } + + // Handle network paths + if ( skip > 0 ) + { + this->ProcessDirectory(0, fexpr.substr(0, skip) + "/", + true); + } + else + { + this->ProcessDirectory(0, "/", true); + } + return true; +} + +//---------------------------------------------------------------------------- +void Glob::AddExpression(const char* expr) +{ + this->Internals->Expressions.push_back( + kwsys::RegularExpression( + this->PatternToRegex(expr).c_str())); +} + +//---------------------------------------------------------------------------- +void Glob::SetRelative(const char* dir) +{ + if ( !dir ) + { + this->Relative = ""; + return; + } + this->Relative = dir; +} + +//---------------------------------------------------------------------------- +const char* Glob::GetRelative() +{ + if ( this->Relative.empty() ) + { + return 0; + } + return this->Relative.c_str(); +} + +//---------------------------------------------------------------------------- +void Glob::AddFile(kwsys_stl::vector& files, const char* file) +{ + if ( !this->Relative.empty() ) + { + files.push_back(kwsys::SystemTools::RelativePath(this->Relative.c_str(), file)); + } + else + { + files.push_back(file); + } +} + +} // namespace KWSYS_NAMESPACE + diff --git a/Utilities/kwsys/Glob.hxx.in b/Utilities/kwsys/Glob.hxx.in new file mode 100644 index 0000000..e656819 --- /dev/null +++ b/Utilities/kwsys/Glob.hxx.in @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Glob.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_Glob_hxx +#define @KWSYS_NAMESPACE@_Glob_hxx + +#include <@KWSYS_NAMESPACE@/Configure.h> +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#include <@KWSYS_NAMESPACE@/stl/string> +#include <@KWSYS_NAMESPACE@/stl/vector> + +/* Define this macro temporarily to keep the code readable. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsys_stl @KWSYS_NAMESPACE@_stl +#endif + +namespace @KWSYS_NAMESPACE@ +{ + +class GlobInternals; + +/** \class Glob + * \brief Portable globbing searches. + * + * Globbing expressions are much simpler than regular + * expressions. This class will search for files using + * globbing expressions. + * + * Finds all files that match a given globbing expression. + */ +class @KWSYS_NAMESPACE@_EXPORT Glob +{ +public: + Glob(); + ~Glob(); + + //! Find all files that match the pattern. + bool FindFiles(const kwsys_stl::string& inexpr); + + //! Return the list of files that matched. + kwsys_stl::vector& GetFiles(); + + //! Set recurse to true to match subdirectories. + void RecurseOn() { this->SetRecurse(true); } + void RecurseOff() { this->SetRecurse(false); } + void SetRecurse(bool i) { this->Recurse = i; } + bool GetRecurse() { return this->Recurse; } + + //! Set relative to true to only show relative path to files. + void SetRelative(const char* dir); + const char* GetRelative(); + + /** Convert the given globbing pattern to a regular expression. + There is no way to quote meta-characters. The + require_whole_string argument specifies whether the regex is + automatically surrounded by "^" and "$" to match the whole + string. This is on by default because patterns always match + whole strings, but may be disabled to support concatenating + expressions more easily (regex1|regex2|etc). */ + static kwsys_stl::string PatternToRegex(const kwsys_stl::string& pattern, + bool require_whole_string = true); + +protected: + //! Process directory + void ProcessDirectory(kwsys_stl::string::size_type start, + const kwsys_stl::string& dir, bool dir_only); + + //! Process last directory, but only when recurse flags is on. That is + // effectively like saying: /path/to/file/**/file + void RecurseDirectory(kwsys_stl::string::size_type start, + const kwsys_stl::string& dir, bool dir_only); + + //! Add regular expression + void AddExpression(const char* expr); + + //! Add a file to the list + void AddFile(kwsys_stl::vector& files, const char* file); + + GlobInternals* Internals; + bool Recurse; + kwsys_stl::string Relative; +}; + +} // namespace @KWSYS_NAMESPACE@ + +/* Undefine temporary macro. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsys_stl +#endif + +#endif diff --git a/Utilities/kwsys/Process.h.in b/Utilities/kwsys/Process.h.in new file mode 100644 index 0000000..b5ccefa --- /dev/null +++ b/Utilities/kwsys/Process.h.in @@ -0,0 +1,384 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: Process.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_Process_h +#define @KWSYS_NAMESPACE@_Process_h + +#include <@KWSYS_NAMESPACE@/Configure.h> + +/* Redefine all public interface symbol names to be in the proper + namespace. These macros are used internally to kwsys only, and are + not visible to user code. Use kwsysHeaderDump.pl to reproduce + these macros after making changes to the interface. */ +#if !defined(KWSYS_NAMESPACE) +# define kwsys_ns(x) @KWSYS_NAMESPACE@##x +# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT +#endif +#define kwsysProcess kwsys_ns(Process) +#define kwsysProcess_s kwsys_ns(Process_s) +#define kwsysProcess_New kwsys_ns(Process_New) +#define kwsysProcess_Delete kwsys_ns(Process_Delete) +#define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand) +#define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand) +#define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout) +#define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory) +#define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile) +#define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared) +#define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach) +#define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow) +#define kwsysProcess_GetOption kwsys_ns(Process_GetOption) +#define kwsysProcess_SetOption kwsys_ns(Process_SetOption) +#define kwsysProcess_Option_e kwsys_ns(Process_Option_e) +#define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting) +#define kwsysProcess_State_Error kwsys_ns(Process_State_Error) +#define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception) +#define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing) +#define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited) +#define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired) +#define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed) +#define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned) +#define kwsysProcess_GetState kwsys_ns(Process_GetState) +#define kwsysProcess_State_e kwsys_ns(Process_State_e) +#define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None) +#define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault) +#define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal) +#define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt) +#define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical) +#define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other) +#define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException) +#define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e) +#define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode) +#define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue) +#define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString) +#define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString) +#define kwsysProcess_Execute kwsys_ns(Process_Execute) +#define kwsysProcess_Disown kwsys_ns(Process_Disown) +#define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData) +#define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e) +#define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None) +#define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN) +#define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT) +#define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR) +#define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout) +#define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit) +#define kwsysProcess_Kill kwsys_ns(Process_Kill) + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/** + * Process control data structure. + */ +typedef struct kwsysProcess_s kwsysProcess; + +/** + * Create a new Process instance. + */ +kwsysEXPORT kwsysProcess* kwsysProcess_New(void); + +/** + * Delete an existing Process instance. If the instance is currently + * executing a process, this blocks until the process terminates. + */ +kwsysEXPORT void kwsysProcess_Delete(kwsysProcess* cp); + +/** + * Set the command line to be executed. Argument is an array of + * pointers to the command and each argument. Ths array must end with + * a NULL pointer. Any previous command lines are removed. Returns + * 1 for success and 0 otherwise. + */ +kwsysEXPORT int kwsysProcess_SetCommand(kwsysProcess* cp, + char const* const* command); + +/** + * Add a command line to be executed. Argument is an array of + * pointers to the command and each argument. Ths array must end with + * a NULL pointer. If this is not the first command added, its + * standard input will be connected to the standard output of the + * previous command. Returns 1 for success and 0 otherwise. + */ +kwsysEXPORT int kwsysProcess_AddCommand(kwsysProcess* cp, + char const* const* command); + +/** + * Set the timeout in seconds for the child process. The timeout + * period begins when the child is executed. If the child has not + * terminated when the timeout expires, it will be killed. A + * non-positive (<= 0) value will disable the timeout. + */ +kwsysEXPORT void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout); + +/** + * Set the working directory for the child process. The working + * directory can be absolute or relative to the current directory. + * Returns 1 for success and 0 for failure. + */ +kwsysEXPORT int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, + const char* dir); + +/** + * Set the name of a file to be attached to the given pipe. Returns 1 + * for success and 0 for failure. + */ +kwsysEXPORT int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, + const char* file); + +/** + * Set whether the given pipe in the child is shared with the parent + * process. The default is no for Pipe_STDOUT and Pipe_STDERR and yes + * for Pipe_STDIN. + */ +kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, + int shared); + +/** + * Get/Set a possibly platform-specific option. Possible options are: + * + * kwsysProcess_Option_Detach = Whether to detach the process. + * 0 = No (default) + * 1 = Yes + * + * kwsysProcess_Option_HideWindow = Whether to hide window on Windows. + * 0 = No (default) + * 1 = Yes + */ +kwsysEXPORT int kwsysProcess_GetOption(kwsysProcess* cp, int optionId); +kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, + int value); +enum kwsysProcess_Option_e +{ + kwsysProcess_Option_HideWindow, + kwsysProcess_Option_Detach +}; + +/** + * Get the current state of the Process instance. Possible states are: + * + * kwsysProcess_State_Starting = Execute has not yet been called. + * kwsysProcess_State_Error = Error administrating the child process. + * kwsysProcess_State_Exception = Child process exited abnormally. + * kwsysProcess_State_Executing = Child process is currently running. + * kwsysProcess_State_Exited = Child process exited normally. + * kwsysProcess_State_Expired = Child process's timeout expired. + * kwsysProcess_State_Killed = Child process terminated by Kill method. + * kwsysProcess_State_Disowned = Child is no longer managed by this object. + */ +kwsysEXPORT int kwsysProcess_GetState(kwsysProcess* cp); +enum kwsysProcess_State_e +{ + kwsysProcess_State_Starting, + kwsysProcess_State_Error, + kwsysProcess_State_Exception, + kwsysProcess_State_Executing, + kwsysProcess_State_Exited, + kwsysProcess_State_Expired, + kwsysProcess_State_Killed, + kwsysProcess_State_Disowned +}; + +/** + * When GetState returns "Exception", this method returns a + * platform-independent description of the exceptional behavior that + * caused the child to terminate abnormally. Possible exceptions are: + * + * kwsysProcess_Exception_None = No exceptional behavior occurred. + * kwsysProcess_Exception_Fault = Child crashed with a memory fault. + * kwsysProcess_Exception_Illegal = Child crashed with an illegal instruction. + * kwsysProcess_Exception_Interrupt = Child was interrupted by user (Cntl-C/Break). + * kwsysProcess_Exception_Numerical = Child crashed with a numerical exception. + * kwsysProcess_Exception_Other = Child terminated for another reason. + */ +kwsysEXPORT int kwsysProcess_GetExitException(kwsysProcess* cp); +enum kwsysProcess_Exception_e +{ + kwsysProcess_Exception_None, + kwsysProcess_Exception_Fault, + kwsysProcess_Exception_Illegal, + kwsysProcess_Exception_Interrupt, + kwsysProcess_Exception_Numerical, + kwsysProcess_Exception_Other +}; + +/** + * When GetState returns "Exited" or "Exception", this method returns + * the platform-specific raw exit code of the process. UNIX platforms + * should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access + * this value. Windows users should compare the value to the various + * EXCEPTION_* values. + * + * If GetState returns "Exited", use GetExitValue to get the + * platform-independent child return value. + */ +kwsysEXPORT int kwsysProcess_GetExitCode(kwsysProcess* cp); + +/** + * When GetState returns "Exited", this method returns the child's + * platform-independent exit code (such as the value returned by the + * child's main). + */ +kwsysEXPORT int kwsysProcess_GetExitValue(kwsysProcess* cp); + +/** + * When GetState returns "Error", this method returns a string + * describing the problem. Otherwise, it returns NULL. + */ +kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp); + +/** + * When GetState returns "Exception", this method returns a string + * describing the problem. Otherwise, it returns NULL. + */ +kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp); + +/** + * Start executing the child process. + */ +kwsysEXPORT void kwsysProcess_Execute(kwsysProcess* cp); + +/** + * Stop management of a detached child process. This closes any pipes + * being read. If the child was not created with the + * kwsysProcess_Option_Detach option, this method does nothing. This + * is because disowning a non-detached process will cause the child + * exit signal to be left unhandled until this process exits. + */ +kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp); + +/** + * Block until data are available on a pipe, a timeout expires, or the + * child process terminates. Arguments are as follows: + * + * data = If data are read, the pointer to which this points is + * set to point to the data. + * length = If data are read, the integer to which this points is + * set to the length of the data read. + * timeout = Specifies the maximum time this call may block. Upon + * return after reading data, the time elapsed is subtracted + * from the timeout value. If this timeout expires, the + * value is set to 0. A NULL pointer passed for this argument + * indicates no timeout for the call. A negative or zero + * value passed for this argument may be used for polling + * and will always return immediately. + * + * Return value will be one of: + * + * Pipe_None = No more data will be available from the child process, + * ( == 0) or no process has been executed. WaitForExit should + * be called to wait for the process to terminate. + * Pipe_STDOUT = Data have been read from the child's stdout pipe. + * Pipe_STDERR = Data have been read from the child's stderr pipe. + * Pipe_Timeout = No data available within timeout specified for the + * call. Time elapsed has been subtracted from timeout + * argument. + */ +kwsysEXPORT int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, + int* length, double* timeout); +enum kwsysProcess_Pipes_e +{ + kwsysProcess_Pipe_None, + kwsysProcess_Pipe_STDIN, + kwsysProcess_Pipe_STDOUT, + kwsysProcess_Pipe_STDERR, + kwsysProcess_Pipe_Timeout=255 +}; + +/** + * Block until the child process terminates or the given timeout + * expires. If no process is running, returns immediatly. The + * argument is: + * + * timeout = Specifies the maximum time this call may block. Upon + * returning due to child termination, the elapsed time + * is subtracted from the given value. A NULL pointer + * passed for this argument indicates no timeout for the + * call. + * + * Return value will be one of: + * + * 0 = Child did not terminate within timeout specified for + * the call. Time elapsed has been subtracted from timeout + * argument. + * 1 = Child has terminated or was not running. + */ +kwsysEXPORT int kwsysProcess_WaitForExit(kwsysProcess* cp, double* timeout); + +/** + * Forcefully terminate the child process that is currently running. + * The caller should call WaitForExit after this returns to wait for + * the child to terminate. + */ +kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +/* If we are building a kwsys .c or .cxx file, let it use these macros. + Otherwise, undefine them to keep the namespace clean. */ +#if !defined(KWSYS_NAMESPACE) +# undef kwsys_ns +# undef kwsysEXPORT +# undef kwsysProcess +# undef kwsysProcess_s +# undef kwsysProcess_New +# undef kwsysProcess_Delete +# undef kwsysProcess_SetCommand +# undef kwsysProcess_AddCommand +# undef kwsysProcess_SetTimeout +# undef kwsysProcess_SetWorkingDirectory +# undef kwsysProcess_SetPipeFile +# undef kwsysProcess_SetPipeShared +# undef kwsysProcess_Option_Detach +# undef kwsysProcess_Option_HideWindow +# undef kwsysProcess_GetOption +# undef kwsysProcess_SetOption +# undef kwsysProcess_Option_e +# undef kwsysProcess_State_Starting +# undef kwsysProcess_State_Error +# undef kwsysProcess_State_Exception +# undef kwsysProcess_State_Executing +# undef kwsysProcess_State_Exited +# undef kwsysProcess_State_Expired +# undef kwsysProcess_State_Killed +# undef kwsysProcess_State_Disowned +# undef kwsysProcess_GetState +# undef kwsysProcess_State_e +# undef kwsysProcess_Exception_None +# undef kwsysProcess_Exception_Fault +# undef kwsysProcess_Exception_Illegal +# undef kwsysProcess_Exception_Interrupt +# undef kwsysProcess_Exception_Numerical +# undef kwsysProcess_Exception_Other +# undef kwsysProcess_GetExitException +# undef kwsysProcess_Exception_e +# undef kwsysProcess_GetExitCode +# undef kwsysProcess_GetExitValue +# undef kwsysProcess_GetErrorString +# undef kwsysProcess_GetExceptionString +# undef kwsysProcess_Execute +# undef kwsysProcess_Disown +# undef kwsysProcess_WaitForData +# undef kwsysProcess_Pipes_e +# undef kwsysProcess_Pipe_None +# undef kwsysProcess_Pipe_STDIN +# undef kwsysProcess_Pipe_STDOUT +# undef kwsysProcess_Pipe_STDERR +# undef kwsysProcess_Pipe_Timeout +# undef kwsysProcess_WaitForExit +# undef kwsysProcess_Kill +#endif + +#endif diff --git a/Utilities/kwsys/ProcessFwd9x.c b/Utilities/kwsys/ProcessFwd9x.c new file mode 100644 index 0000000..1749424 --- /dev/null +++ b/Utilities/kwsys/ProcessFwd9x.c @@ -0,0 +1,213 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: ProcessFwd9x.c,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +/* + On Windows9x platforms, this executable is spawned between a parent + process and the child it is invoking to work around a bug. See the + Win32 implementation file for details. + + Future Work: This executable must be linked statically against the C + runtime library before being encoded into the library. Building it + in this way may be hard because CMake has limited abilities to build + different targets with different configurations in the same + directory. We may just have to create and encode the executable + once instead of generating it during the build. This would be an + acceptable solution because the forwarding executable should not + change very often and is pretty simple. +*/ + +#ifdef _MSC_VER +#pragma warning (push, 1) +#endif +#include +#include + +void ReportLastError(HANDLE errorPipe); + +int main() +{ + /* Process startup information for the real child. */ + STARTUPINFO si; + PROCESS_INFORMATION pi; + + /* The result of waiting for the child to exit. */ + DWORD waitResult; + + /* The child's process return code. */ + DWORD retVal; + + /* The command line used to invoke this process. */ + LPSTR commandLine = GetCommandLine(); + + /* Pointer that will be advanced to the beginning of the command + line of the real child process. */ + LPSTR cmdLine = commandLine; + + /* Handle to the error reporting pipe provided by the parent. This + is parsed off the command line. */ + HANDLE errorPipe = 0; + HANDLE errorPipeOrig = 0; + + /* Handle to the event the parent uses to tell us to resume the child. + This is parsed off the command line. */ + HANDLE resumeEvent = 0; + + /* Handle to the event the parent uses to tell us to kill the child. + This is parsed off the command line. */ + HANDLE killEvent = 0; + + /* Flag for whether to hide window of child process. */ + int hideWindow = 0; + + /* An array of the handles on which we wait when the child is + running. */ + HANDLE waitHandles[2] = {0, 0}; + + /* Move the pointer past the name of this executable. */ + if(*cmdLine == '"') + { + ++cmdLine; + while(*cmdLine && *cmdLine != '"') { ++cmdLine; } + if(*cmdLine) { ++cmdLine; } + } + else + { + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + } + + /* Parse the error pipe handle. */ + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + sscanf(cmdLine, "%p", &errorPipeOrig); + + /* Parse the resume event handle. */ + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + sscanf(cmdLine, "%p", &resumeEvent); + + /* Parse the kill event handle. */ + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + sscanf(cmdLine, "%p", &killEvent); + + /* Parse the hide window flag. */ + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + sscanf(cmdLine, "%d", &hideWindow); + + /* Skip to the beginning of the command line of the real child. */ + while(*cmdLine && *cmdLine != ' ') { ++cmdLine; } + while(*cmdLine && *cmdLine == ' ') { ++cmdLine; } + + /* Create a non-inherited copy of the error pipe. We do not want + the child to get it. */ + if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig, + GetCurrentProcess(), &errorPipe, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + /* Have a non-inherited duplicate. Close the inherited one. */ + CloseHandle(errorPipeOrig); + } + else + { + /* Could not duplicate handle. Report the error. */ + ReportLastError(errorPipeOrig); + return 1; + } + + /* Create the subprocess. */ + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi)) + { + /* Process created successfully. Close the error reporting pipe + to notify the parent of success. */ + CloseHandle(errorPipe); + } + else + { + /* Error creating the process. Report the error to the parent + process through the special error reporting pipe. */ + ReportLastError(errorPipe); + return 1; + } + + /* Wait for resume or kill event from parent. */ + waitHandles[0] = killEvent; + waitHandles[1] = resumeEvent; + waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE); + + /* Check what happened. */ + if(waitResult == WAIT_OBJECT_0) + { + /* We were asked to kill the child. */ + TerminateProcess(pi.hProcess, 255); + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return 1; + } + else + { + /* We were asked to resume the child. */ + ResumeThread(pi.hThread); + CloseHandle(pi.hThread); + } + + /* Wait for subprocess to exit or for kill event from parent. */ + waitHandles[0] = killEvent; + waitHandles[1] = pi.hProcess; + waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE); + + /* Check what happened. */ + if(waitResult == WAIT_OBJECT_0) + { + /* We were asked to kill the child. */ + TerminateProcess(pi.hProcess, 255); + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + return 1; + } + else + { + /* The child exited. Get the return code. */ + GetExitCodeProcess(pi.hProcess, &retVal); + CloseHandle(pi.hProcess); + return retVal; + } +} + +void ReportLastError(HANDLE errorPipe) +{ + LPVOID lpMsgBuf; + DWORD n; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0); + LocalFree( lpMsgBuf ); +} diff --git a/Utilities/kwsys/ProcessUNIX.c b/Utilities/kwsys/ProcessUNIX.c new file mode 100644 index 0000000..6afaaeb --- /dev/null +++ b/Utilities/kwsys/ProcessUNIX.c @@ -0,0 +1,1960 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: ProcessUNIX.c,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Process.h) + +/* Work-around CMake dependency scanning limitation. This must + duplicate the above list of headers. */ +#if 0 +# include "Process.h.in" +#endif + +/* + +Implementation for UNIX + +On UNIX, a child process is forked to exec the program. Three +output pipes from the child are read by the parent process using a +select call to block until data are ready. Two of the pipes are +stdout and stderr for the child. The third is a special error pipe +that has two purposes. First, if the child cannot exec the program, +the error is reported through the error pipe. Second, the error +pipe is left open until the child exits. This is used in +conjunction with the timeout on the select call to implement a +timeout for program even when it closes stdout and stderr. +*/ + +/* + +TODO: + +We cannot create the pipeline of processes in suspended states. How +do we cleanup processes already started when one fails to load? Right +now we are just killing them, which is probably not the right thing to +do. + +*/ + +#include /* snprintf */ +#include /* malloc, free */ +#include /* strdup, strerror, memset */ +#include /* struct timeval */ +#include /* pid_t, fd_set */ +#include /* waitpid */ +#include /* open mode */ +#include /* pipe, close, fork, execvp, select, _exit */ +#include /* fcntl */ +#include /* errno */ +#include /* gettimeofday */ +#include /* sigaction */ +#include /* DIR, dirent */ + +/* The number of pipes for the child's output. The standard stdout + and stderr pipes are the first two. One more pipe is used to + detect when the child process has terminated. The third pipe is + not given to the child process, so it cannot close it until it + terminates. */ +#define KWSYSPE_PIPE_COUNT 3 +#define KWSYSPE_PIPE_STDOUT 0 +#define KWSYSPE_PIPE_STDERR 1 +#define KWSYSPE_PIPE_TERM 2 + +/* The maximum amount to read from a pipe at a time. */ +#define KWSYSPE_PIPE_BUFFER_SIZE 1024 + +/* Keep track of times using a signed representation. Switch to the + native (possibly unsigned) representation only when calling native + functions. */ +typedef struct timeval kwsysProcessTimeNative; +typedef struct kwsysProcessTime_s kwsysProcessTime; +struct kwsysProcessTime_s +{ + long tv_sec; + long tv_usec; +}; + +typedef struct kwsysProcessCreateInformation_s +{ + int StdIn; + int StdOut; + int StdErr; + int TermPipe; + int ErrorPipe[2]; +} kwsysProcessCreateInformation; + +/*--------------------------------------------------------------------------*/ +static int kwsysProcessInitialize(kwsysProcess* cp); +static void kwsysProcessCleanup(kwsysProcess* cp, int error); +static void kwsysProcessCleanupDescriptor(int* pfd); +static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, + kwsysProcessCreateInformation* si, int* readEnd); +static int kwsysProcessSetupOutputPipeFile(int* p, const char* name); +static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, + kwsysProcessTime* timeoutTime); +static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, + double* userTimeout, + kwsysProcessTimeNative* timeoutLength); +static kwsysProcessTime kwsysProcessTimeGetCurrent(void); +static double kwsysProcessTimeToDouble(kwsysProcessTime t); +static kwsysProcessTime kwsysProcessTimeFromDouble(double d); +static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); +static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); +static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2); +static void kwsysProcessSetExitException(kwsysProcess* cp, int sig); +static void kwsysProcessChildErrorExit(int errorPipe); +static void kwsysProcessRestoreDefaultSignalHandlers(void); +static pid_t kwsysProcessFork(kwsysProcess* cp, + kwsysProcessCreateInformation* si); +static void kwsysProcessKill(pid_t process_id); + +/*--------------------------------------------------------------------------*/ +/* Structure containing data used to implement the child's execution. */ +struct kwsysProcess_s +{ + /* The command lines to execute. */ + char*** Commands; + int NumberOfCommands; + + /* Descriptors for the read ends of the child's output pipes. */ + int PipeReadEnds[KWSYSPE_PIPE_COUNT]; + + /* Buffer for pipe data. */ + char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE]; + + /* Process IDs returned by the calls to fork. */ + pid_t* ForkPIDs; + + /* Flag for whether the children were terminated by a faild select. */ + int SelectError; + + /* The timeout length. */ + double Timeout; + + /* The working directory for the process. */ + char* WorkingDirectory; + + /* Whether to create the child as a detached process. */ + int OptionDetach; + + /* Whether the child was created as a detached process. */ + int Detached; + + /* Time at which the child started. Negative for no timeout. */ + kwsysProcessTime StartTime; + + /* Time at which the child will timeout. Negative for no timeout. */ + kwsysProcessTime TimeoutTime; + + /* Flag for whether the timeout expired. */ + int TimeoutExpired; + + /* The old SIGCHLD handler. */ + struct sigaction OldSigChldAction; + + /* The number of pipes left open during execution. */ + int PipesLeft; + + /* File descriptor set for call to select. */ + fd_set PipeSet; + + /* The current status of the child process. */ + int State; + + /* The exceptional behavior that terminated the child process, if + * any. */ + int ExitException; + + /* The exit code of the child process. */ + int ExitCode; + + /* The exit value of the child process, if any. */ + int ExitValue; + + /* Whether the process was killed. */ + int Killed; + + /* Buffer for error message in case of failure. */ + char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; + + /* Description for the ExitException. */ + char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1]; + + /* The exit codes of each child process in the pipeline. */ + int* CommandExitCodes; + + /* Name of files to which stdin and stdout pipes are attached. */ + char* PipeFileSTDIN; + char* PipeFileSTDOUT; + char* PipeFileSTDERR; + + /* Whether each pipe is shared with the parent process. */ + int PipeSharedSTDIN; + int PipeSharedSTDOUT; + int PipeSharedSTDERR; + + /* The real working directory of this process. */ + int RealWorkingDirectoryLength; + char* RealWorkingDirectory; +}; + +/*--------------------------------------------------------------------------*/ +kwsysProcess* kwsysProcess_New(void) +{ + /* Allocate a process control structure. */ + kwsysProcess* cp = (kwsysProcess*)malloc(sizeof(kwsysProcess)); + if(!cp) + { + return 0; + } + memset(cp, 0, sizeof(kwsysProcess)); + + /* Share stdin with the parent process by default. */ + cp->PipeSharedSTDIN = 1; + + /* Set initial status. */ + cp->State = kwsysProcess_State_Starting; + + return cp; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_Delete(kwsysProcess* cp) +{ + /* Make sure we have an instance. */ + if(!cp) + { + return; + } + + /* If the process is executing, wait for it to finish. */ + if(cp->State == kwsysProcess_State_Executing) + { + if(cp->Detached) + { + kwsysProcess_Disown(cp); + } + else + { + kwsysProcess_WaitForExit(cp, 0); + } + } + + /* Free memory. */ + kwsysProcess_SetCommand(cp, 0); + kwsysProcess_SetWorkingDirectory(cp, 0); + kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0); + kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0); + kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0); + if(cp->CommandExitCodes) + { + free(cp->CommandExitCodes); + } + free(cp); +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) +{ + int i; + if(!cp) + { + return 0; + } + for(i=0; i < cp->NumberOfCommands; ++i) + { + char** c = cp->Commands[i]; + while(*c) + { + free(*c++); + } + free(cp->Commands[i]); + } + cp->NumberOfCommands = 0; + if(cp->Commands) + { + free(cp->Commands); + cp->Commands = 0; + } + if(command) + { + return kwsysProcess_AddCommand(cp, command); + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) +{ + int newNumberOfCommands; + char*** newCommands; + + /* Make sure we have a command to add. */ + if(!cp || !command) + { + return 0; + } + + /* Allocate a new array for command pointers. */ + newNumberOfCommands = cp->NumberOfCommands + 1; + if(!(newCommands = (char***)malloc(sizeof(char**) * newNumberOfCommands))) + { + /* Out of memory. */ + return 0; + } + + /* Copy any existing commands into the new array. */ + { + int i; + for(i=0; i < cp->NumberOfCommands; ++i) + { + newCommands[i] = cp->Commands[i]; + } + } + + /* Add the new command. */ + { + char const* const* c = command; + int n = 0; + int i = 0; + while(*c++); + n = c - command - 1; + newCommands[cp->NumberOfCommands] = (char**)malloc((n+1)*sizeof(char*)); + if(!newCommands[cp->NumberOfCommands]) + { + /* Out of memory. */ + free(newCommands); + return 0; + } + for(i=0; i < n; ++i) + { + newCommands[cp->NumberOfCommands][i] = strdup(command[i]); + if(!newCommands[cp->NumberOfCommands][i]) + { + break; + } + } + if(i < n) + { + /* Out of memory. */ + for(;i > 0; --i) + { + free(newCommands[cp->NumberOfCommands][i-1]); + } + free(newCommands); + return 0; + } + newCommands[cp->NumberOfCommands][n] = 0; + } + + /* Successfully allocated new command array. Free the old array. */ + free(cp->Commands); + cp->Commands = newCommands; + cp->NumberOfCommands = newNumberOfCommands; + + return 1; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) +{ + if(!cp) + { + return; + } + cp->Timeout = timeout; + if(cp->Timeout < 0) + { + cp->Timeout = 0; + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) +{ + if(!cp) + { + return 0; + } + if(cp->WorkingDirectory == dir) + { + return 1; + } + if(cp->WorkingDirectory && dir && strcmp(cp->WorkingDirectory, dir) == 0) + { + return 1; + } + if(cp->WorkingDirectory) + { + free(cp->WorkingDirectory); + cp->WorkingDirectory = 0; + } + if(dir) + { + cp->WorkingDirectory = (char*)malloc(strlen(dir) + 1); + if(!cp->WorkingDirectory) + { + return 0; + } + strcpy(cp->WorkingDirectory, dir); + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file) +{ + char** pfile; + if(!cp) + { + return 0; + } + switch(prPipe) + { + case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break; + case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break; + case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break; + default: return 0; + } + if(*pfile) + { + free(*pfile); + *pfile = 0; + } + if(file) + { + *pfile = malloc(strlen(file)+1); + if(!*pfile) + { + return 0; + } + strcpy(*pfile, file); + } + + /* If we are redirecting the pipe, do not share it. */ + if(*pfile) + { + kwsysProcess_SetPipeShared(cp, prPipe, 0); + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared) +{ + if(!cp) + { + return; + } + + switch(prPipe) + { + case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break; + case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break; + case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break; + default: return; + } + + /* If we are sharing the pipe, do not redirect it to a file. */ + if(shared) + { + kwsysProcess_SetPipeFile(cp, prPipe, 0); + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) +{ + if(!cp) + { + return 0; + } + + switch(optionId) + { + case kwsysProcess_Option_Detach: return cp->OptionDetach; + default: return 0; + } +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) +{ + if(!cp) + { + return; + } + + switch(optionId) + { + case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; + default: break; + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetState(kwsysProcess* cp) +{ + return cp? cp->State : kwsysProcess_State_Error; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetExitException(kwsysProcess* cp) +{ + return cp? cp->ExitException : kwsysProcess_Exception_Other; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetExitCode(kwsysProcess* cp) +{ + return cp? cp->ExitCode : 0; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetExitValue(kwsysProcess* cp) +{ + return cp? cp->ExitValue : -1; +} + +/*--------------------------------------------------------------------------*/ +const char* kwsysProcess_GetErrorString(kwsysProcess* cp) +{ + if(!cp) + { + return "Process management structure could not be allocated"; + } + else if(cp->State == kwsysProcess_State_Error) + { + return cp->ErrorMessage; + } + return "Success"; +} + +/*--------------------------------------------------------------------------*/ +const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) +{ + if(!cp) + { + return "GetExceptionString called with NULL process management structure"; + } + else if(cp->State == kwsysProcess_State_Exception) + { + return cp->ExitExceptionString; + } + return "No exception"; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_Execute(kwsysProcess* cp) +{ + int i; + struct sigaction newSigChldAction; + kwsysProcessCreateInformation si = {-1, -1, -1, -1, {-1, -1}}; + + /* Do not execute a second copy simultaneously. */ + if(!cp || cp->State == kwsysProcess_State_Executing) + { + return; + } + + /* Initialize the control structure for a new process. */ + if(!kwsysProcessInitialize(cp)) + { + strcpy(cp->ErrorMessage, "Out of memory"); + cp->State = kwsysProcess_State_Error; + return; + } + + /* Save the real working directory of this process and change to + the working directory for the child processes. This is needed + to make pipe file paths evaluate correctly. */ + if(cp->WorkingDirectory) + { + int r; + if(!getcwd(cp->RealWorkingDirectory, cp->RealWorkingDirectoryLength)) + { + kwsysProcessCleanup(cp, 1); + return; + } + + /* Some platforms specify that the chdir call may be + interrupted. Repeat the call until it finishes. */ + while(((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR)); + if(r < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + + /* We want no special handling of SIGCHLD. Repeat call until it is + not interrupted. */ + memset(&newSigChldAction, 0, sizeof(struct sigaction)); + newSigChldAction.sa_handler = SIG_DFL; + while((sigaction(SIGCHLD, &newSigChldAction, &cp->OldSigChldAction) < 0) && + (errno == EINTR)); + + /* Setup the stderr and termination pipes to be shared by all processes. */ + for(i=KWSYSPE_PIPE_STDERR; i < KWSYSPE_PIPE_COUNT; ++i) + { + /* Create the pipe. */ + int p[2]; + if(pipe(p) < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + + /* Store the pipe. */ + cp->PipeReadEnds[i] = p[0]; + if(i == KWSYSPE_PIPE_STDERR) + { + si.StdErr = p[1]; + } + else + { + si.TermPipe = p[1]; + } + + /* Set close-on-exec flag on the pipe's ends. */ + if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) + { + kwsysProcessCleanup(cp, 1); + kwsysProcessCleanupDescriptor(&si.StdErr); + kwsysProcessCleanupDescriptor(&si.TermPipe); + return; + } + } + + /* Replace the stderr pipe with a file if requested. In this case + the select call will report that stderr is closed immediately. */ + if(cp->PipeFileSTDERR) + { + if(!kwsysProcessSetupOutputPipeFile(&si.StdErr, cp->PipeFileSTDERR)) + { + kwsysProcessCleanup(cp, 1); + kwsysProcessCleanupDescriptor(&si.StdErr); + kwsysProcessCleanupDescriptor(&si.TermPipe); + return; + } + } + + /* Replace the stderr pipe with the parent's if requested. In this + case the select call will report that stderr is closed + immediately. */ + if(cp->PipeSharedSTDERR) + { + kwsysProcessCleanupDescriptor(&si.StdErr); + si.StdErr = 2; + } + + /* The timeout period starts now. */ + cp->StartTime = kwsysProcessTimeGetCurrent(); + cp->TimeoutTime.tv_sec = -1; + cp->TimeoutTime.tv_usec = -1; + + /* Create the pipeline of processes. */ + { + int readEnd = -1; + for(i=0; i < cp->NumberOfCommands; ++i) + { + if(!kwsysProcessCreate(cp, i, &si, &readEnd)) + { + kwsysProcessCleanup(cp, 1); + + /* Release resources that may have been allocated for this + process before an error occurred. */ + kwsysProcessCleanupDescriptor(&readEnd); + if(si.StdIn != 0) + { + kwsysProcessCleanupDescriptor(&si.StdIn); + } + if(si.StdOut != 1) + { + kwsysProcessCleanupDescriptor(&si.StdOut); + } + if(si.StdErr != 2) + { + kwsysProcessCleanupDescriptor(&si.StdErr); + } + kwsysProcessCleanupDescriptor(&si.TermPipe); + kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]); + kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]); + return; + } + } + /* Save a handle to the output pipe for the last process. */ + cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = readEnd; + } + + /* The parent process does not need the output pipe write ends. */ + if(si.StdErr != 2) + { + kwsysProcessCleanupDescriptor(&si.StdErr); + } + kwsysProcessCleanupDescriptor(&si.TermPipe); + + /* Restore the working directory. */ + if(cp->RealWorkingDirectory) + { + /* Some platforms specify that the chdir call may be + interrupted. Repeat the call until it finishes. */ + while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR)); + free(cp->RealWorkingDirectory); + cp->RealWorkingDirectory = 0; + } + + /* All the pipes are now open. */ + cp->PipesLeft = KWSYSPE_PIPE_COUNT; + + /* The process has now started. */ + cp->State = kwsysProcess_State_Executing; + cp->Detached = cp->OptionDetach; +} + +/*--------------------------------------------------------------------------*/ +kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp) +{ + int i; + + /* Make sure a detached child process is running. */ + if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing || + cp->TimeoutExpired || cp->Killed) + { + return; + } + + /* Close any pipes that are still open. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + if(cp->PipeReadEnds[i] >= 0) + { + /* If the pipe was reported by the last call to select, we must + read from it. Ignore the data. */ + if(FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) + { + /* We are handling this pipe now. Remove it from the set. */ + FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); + + /* The pipe is ready to read without blocking. Keep trying to + read until the operation is not interrupted. */ + while((read(cp->PipeReadEnds[i], cp->PipeBuffer, + KWSYSPE_PIPE_BUFFER_SIZE) < 0) && (errno == EINTR)); + } + + /* We are done reading from this pipe. */ + kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); + --cp->PipesLeft; + } + } + + /* We will not wait for exit, so cleanup now. */ + kwsysProcessCleanup(cp, 0); + + /* The process has been disowned. */ + cp->State = kwsysProcess_State_Disowned; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, + double* userTimeout) +{ + int i; + int max = -1; + kwsysProcessTimeNative* timeout = 0; + kwsysProcessTimeNative timeoutLength; + kwsysProcessTime timeoutTime; + kwsysProcessTime userStartTime = {0, 0}; + int user = 0; + int expired = 0; + int pipeId = kwsysProcess_Pipe_None; + int numReady = 0; + + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed || + cp->TimeoutExpired) + { + return kwsysProcess_Pipe_None; + } + + /* Record the time at which user timeout period starts. */ + if(userTimeout) + { + userStartTime = kwsysProcessTimeGetCurrent(); + } + + /* Calculate the time at which a timeout will expire, and whether it + is the user or process timeout. */ + user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime); + + /* Data can only be available when pipes are open. If the process + is not running, cp->PipesLeft will be 0. */ + while(cp->PipesLeft > 0) + { + /* Check for any open pipes with data reported ready by the last + call to select. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + if(cp->PipeReadEnds[i] >= 0 && + FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) + { + int n; + + /* We are handling this pipe now. Remove it from the set. */ + FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); + + /* The pipe is ready to read without blocking. Keep trying to + read until the operation is not interrupted. */ + while(((n = read(cp->PipeReadEnds[i], cp->PipeBuffer, + KWSYSPE_PIPE_BUFFER_SIZE)) < 0) && (errno == EINTR)); + if(n > 0) + { + /* We have data on this pipe. */ + if(i == KWSYSPE_PIPE_TERM) + { + /* This is data on the special termination pipe. Ignore it. */ + } + else if(data && length) + { + /* Report this data. */ + *data = cp->PipeBuffer; + *length = n; + switch(i) + { + case KWSYSPE_PIPE_STDOUT: + pipeId = kwsysProcess_Pipe_STDOUT; break; + case KWSYSPE_PIPE_STDERR: + pipeId = kwsysProcess_Pipe_STDERR; break; + }; + break; + } + } + else + { + /* We are done reading from this pipe. */ + kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); + --cp->PipesLeft; + } + } + } + + /* If we have data, break early. */ + if(pipeId) + { + break; + } + + /* Make sure the set is empty (it should always be empty here + anyway). */ + FD_ZERO(&cp->PipeSet); + + /* Setup a timeout if required. */ + if(timeoutTime.tv_sec < 0) + { + timeout = 0; + } + else + { + timeout = &timeoutLength; + } + if(kwsysProcessGetTimeoutLeft(&timeoutTime, user?userTimeout:0, &timeoutLength)) + { + /* Timeout has already expired. */ + expired = 1; + break; + } + + /* Add the pipe reading ends that are still open. */ + max = -1; + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + if(cp->PipeReadEnds[i] >= 0) + { + FD_SET(cp->PipeReadEnds[i], &cp->PipeSet); + if(cp->PipeReadEnds[i] > max) + { + max = cp->PipeReadEnds[i]; + } + } + } + + /* Make sure we have a non-empty set. */ + if(max < 0) + { + /* All pipes have closed. Child has terminated. */ + break; + } + + /* Run select to block until data are available. Repeat call + until it is not interrupted. */ + while(((numReady = select(max+1, &cp->PipeSet, 0, 0, timeout)) < 0) && + (errno == EINTR)); + + /* Check result of select. */ + if(numReady == 0) + { + /* Select's timeout expired. */ + expired = 1; + break; + } + else if(numReady < 0) + { + /* Select returned an error. Leave the error description in the + pipe buffer. */ + strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); + + /* Kill the children now. */ + kwsysProcess_Kill(cp); + cp->Killed = 0; + cp->SelectError = 1; + } + } + + /* Update the user timeout. */ + if(userTimeout) + { + kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent(); + kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime, + userStartTime); + double d = kwsysProcessTimeToDouble(difference); + *userTimeout -= d; + if(*userTimeout < 0) + { + *userTimeout = 0; + } + } + + /* Check what happened. */ + if(pipeId) + { + /* Data are ready on a pipe. */ + return pipeId; + } + else if(expired) + { + /* A timeout has expired. */ + if(user) + { + /* The user timeout has expired. It has no time left. */ + return kwsysProcess_Pipe_Timeout; + } + else + { + /* The process timeout has expired. Kill the children now. */ + kwsysProcess_Kill(cp); + cp->Killed = 0; + cp->TimeoutExpired = 1; + return kwsysProcess_Pipe_None; + } + } + else + { + /* No pipes are left open. */ + return kwsysProcess_Pipe_None; + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) +{ + int result = 0; + int status = 0; + int prPipe = 0; + + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing) + { + return 1; + } + + /* Wait for all the pipes to close. Ignore all data. */ + while((prPipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) + { + if(prPipe == kwsysProcess_Pipe_Timeout) + { + return 0; + } + } + + /* Wait for each child to terminate. The process should have + already exited because KWSYSPE_PIPE_TERM has been closed by this + point. Repeat the call until it is not interrupted. */ + if(!cp->Detached) + { + int i; + for(i=0; i < cp->NumberOfCommands; ++i) + { + while(((result = waitpid(cp->ForkPIDs[i], + &cp->CommandExitCodes[i], 0)) < 0) && + (errno == EINTR)); + if(result <= 0 && cp->State != kwsysProcess_State_Error) + { + /* Unexpected error. Report the first time this happens. */ + strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); + cp->State = kwsysProcess_State_Error; + } + } + } + + /* Check if there was an error in one of the waitpid calls. */ + if(cp->State == kwsysProcess_State_Error) + { + /* The error message is already in its buffer. Tell + kwsysProcessCleanup to not create it. */ + kwsysProcessCleanup(cp, 0); + return 1; + } + + /* Check whether the child reported an error invoking the process. */ + if(cp->SelectError) + { + /* The error message is already in its buffer. Tell + kwsysProcessCleanup to not create it. */ + kwsysProcessCleanup(cp, 0); + cp->State = kwsysProcess_State_Error; + return 1; + } + + /* Use the status of the last process in the pipeline. */ + status = cp->CommandExitCodes[cp->NumberOfCommands-1]; + + /* Determine the outcome. */ + if(cp->Killed) + { + /* We killed the child. */ + cp->State = kwsysProcess_State_Killed; + } + else if(cp->TimeoutExpired) + { + /* The timeout expired. */ + cp->State = kwsysProcess_State_Expired; + } + else if(WIFEXITED(status)) + { + /* The child exited normally. */ + cp->State = kwsysProcess_State_Exited; + cp->ExitException = kwsysProcess_Exception_None; + cp->ExitCode = status; + cp->ExitValue = (int)WEXITSTATUS(status); + } + else if(WIFSIGNALED(status)) + { + /* The child received an unhandled signal. */ + cp->State = kwsysProcess_State_Exception; + cp->ExitCode = status; + kwsysProcessSetExitException(cp, (int)WTERMSIG(status)); + } + else + { + /* Error getting the child return code. */ + strcpy(cp->ErrorMessage, "Error getting child return code."); + cp->State = kwsysProcess_State_Error; + } + + /* Normal cleanup. */ + kwsysProcessCleanup(cp, 0); + return 1; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_Kill(kwsysProcess* cp) +{ + int i; + + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing) + { + return; + } + + /* Kill the children. */ + cp->Killed = 1; + for(i=0; i < cp->NumberOfCommands; ++i) + { + if(cp->ForkPIDs[i]) + { + kwsysProcessKill(cp->ForkPIDs[i]); + } + } + + /* Close all the pipe read ends. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); + } + cp->PipesLeft = 0; +} + +/*--------------------------------------------------------------------------*/ +/* Initialize a process control structure for kwsysProcess_Execute. */ +static int kwsysProcessInitialize(kwsysProcess* cp) +{ + int i; + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + cp->PipeReadEnds[i] = -1; + } + cp->SelectError = 0; + cp->StartTime.tv_sec = -1; + cp->StartTime.tv_usec = -1; + cp->TimeoutTime.tv_sec = -1; + cp->TimeoutTime.tv_usec = -1; + cp->TimeoutExpired = 0; + cp->PipesLeft = 0; + FD_ZERO(&cp->PipeSet); + cp->State = kwsysProcess_State_Starting; + cp->Killed = 0; + cp->ExitException = kwsysProcess_Exception_None; + cp->ExitCode = 1; + cp->ExitValue = 1; + cp->ErrorMessage[0] = 0; + strcpy(cp->ExitExceptionString, "No exception"); + + if(cp->ForkPIDs) + { + free(cp->ForkPIDs); + } + cp->ForkPIDs = (pid_t*)malloc(sizeof(pid_t)*cp->NumberOfCommands); + if(!cp->ForkPIDs) + { + return 0; + } + memset(cp->ForkPIDs, 0, sizeof(pid_t)*cp->NumberOfCommands); + + if(cp->CommandExitCodes) + { + free(cp->CommandExitCodes); + } + cp->CommandExitCodes = (int*)malloc(sizeof(int)*cp->NumberOfCommands); + if(!cp->CommandExitCodes) + { + return 0; + } + memset(cp->CommandExitCodes, 0, sizeof(int)*cp->NumberOfCommands); + + /* Allocate memory to save the real working directory. */ + if ( cp->WorkingDirectory ) + { +#if defined(MAXPATHLEN) + cp->RealWorkingDirectoryLength = MAXPATHLEN; +#elif defined(PATH_MAX) + cp->RealWorkingDirectoryLength = PATH_MAX; +#else + cp->RealWorkingDirectoryLength = 4096; +#endif + cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength); + if(!cp->RealWorkingDirectory) + { + return 0; + } + } + + return 1; +} + +/*--------------------------------------------------------------------------*/ +/* Free all resources used by the given kwsysProcess instance that were + allocated by kwsysProcess_Execute. */ +static void kwsysProcessCleanup(kwsysProcess* cp, int error) +{ + int i; + + if(error) + { + /* We are cleaning up due to an error. Report the error message + if one has not been provided already. */ + if(cp->ErrorMessage[0] == 0) + { + strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); + } + + /* Set the error state. */ + cp->State = kwsysProcess_State_Error; + + /* Kill any children already started. */ + if(cp->ForkPIDs) + { + for(i=0; i < cp->NumberOfCommands; ++i) + { + if(cp->ForkPIDs[i]) + { + kwsysProcessKill(cp->ForkPIDs[i]); + } + } + } + + /* Restore the working directory. */ + if(cp->RealWorkingDirectory) + { + while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR)); + } + } + + /* Restore the SIGCHLD handler. */ + while((sigaction(SIGCHLD, &cp->OldSigChldAction, 0) < 0) && + (errno == EINTR)); + + /* Free memory. */ + if(cp->ForkPIDs) + { + free(cp->ForkPIDs); + cp->ForkPIDs = 0; + } + if(cp->RealWorkingDirectory) + { + free(cp->RealWorkingDirectory); + cp->RealWorkingDirectory = 0; + } + + /* Close pipe handles. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); + } +} + +/*--------------------------------------------------------------------------*/ +/* Close the given file descriptor if it is open. Reset its value to -1. */ +static void kwsysProcessCleanupDescriptor(int* pfd) +{ + if(pfd && *pfd >= 0) + { + /* Keep trying to close until it is not interrupted by a + * signal. */ + while((close(*pfd) < 0) && (errno == EINTR)); + *pfd = -1; + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, + kwsysProcessCreateInformation* si, int* readEnd) +{ + /* Setup the process's stdin. */ + if(prIndex > 0) + { + si->StdIn = *readEnd; + *readEnd = 0; + } + else if(cp->PipeFileSTDIN) + { + /* Open a file for the child's stdin to read. */ + si->StdIn = open(cp->PipeFileSTDIN, O_RDONLY); + if(si->StdIn < 0) + { + return 0; + } + + /* Set close-on-exec flag on the pipe's end. */ + if(fcntl(si->StdIn, F_SETFD, FD_CLOEXEC) < 0) + { + return 0; + } + } + else if(cp->PipeSharedSTDIN) + { + si->StdIn = 0; + } + else + { + si->StdIn = -1; + } + + /* Setup the process's stdout. */ + { + /* Create the pipe. */ + int p[2]; + if(pipe(p) < 0) + { + return 0; + } + *readEnd = p[0]; + si->StdOut = p[1]; + + /* Set close-on-exec flag on the pipe's ends. */ + if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) + { + return 0; + } + } + + /* Replace the stdout pipe with a file if requested. In this case + the select call will report that stdout is closed immediately. */ + if(prIndex == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT) + { + if(!kwsysProcessSetupOutputPipeFile(&si->StdOut, cp->PipeFileSTDOUT)) + { + return 0; + } + } + + /* Replace the stdout pipe with the parent's if requested. In this + case the select call will report that stderr is closed + immediately. */ + if(prIndex == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT) + { + kwsysProcessCleanupDescriptor(&si->StdOut); + si->StdOut = 1; + } + + /* Create the error reporting pipe. */ + if(pipe(si->ErrorPipe) < 0) + { + return 0; + } + + /* Set close-on-exec flag on the error pipe's write end. */ + if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0) + { + return 0; + } + + /* Fork off a child process. */ + cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si); + if(cp->ForkPIDs[prIndex] < 0) + { + return 0; + } + + if(cp->ForkPIDs[prIndex] == 0) + { + /* Close the read end of the error reporting pipe. */ + close(si->ErrorPipe[0]); + + /* Setup the stdin, stdout, and stderr pipes. */ + if(si->StdIn > 0) + { + dup2(si->StdIn, 0); + } + else if(si->StdIn < 0) + { + close(0); + } + if(si->StdOut != 1) + { + dup2(si->StdOut, 1); + } + if(si->StdErr != 2) + { + dup2(si->StdErr, 2); + } + + /* Clear the close-on-exec flag for stdin, stdout, and stderr. + Also clear it for the termination pipe. All other pipe handles + will be closed when exec succeeds. */ + fcntl(0, F_SETFD, 0); + fcntl(1, F_SETFD, 0); + fcntl(2, F_SETFD, 0); + fcntl(si->TermPipe, F_SETFD, 0); + + /* Restore all default signal handlers. */ + kwsysProcessRestoreDefaultSignalHandlers(); + + /* Execute the real process. If successful, this does not return. */ + execvp(cp->Commands[prIndex][0], cp->Commands[prIndex]); + + /* Failure. Report error to parent and terminate. */ + kwsysProcessChildErrorExit(si->ErrorPipe[1]); + } + + /* We are done with the error reporting pipe write end. */ + kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); + + /* Block until the child's exec call succeeds and closes the error + pipe or writes data to the pipe to report an error. */ + { + int total = 0; + int n = 1; + /* Read the entire error message up to the length of our buffer. */ + while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0) + { + /* Keep trying to read until the operation is not interrupted. */ + while(((n = read(si->ErrorPipe[0], cp->ErrorMessage+total, + KWSYSPE_PIPE_BUFFER_SIZE-total)) < 0) && + (errno == EINTR)); + if(n > 0) + { + total += n; + } + } + + /* We are done with the error reporting pipe read end. */ + kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); + + if(total > 0) + { + /* The child failed to execute the process. */ + return 0; + } + } + + /* Successfully created this child process. */ + if(prIndex > 0 || si->StdIn > 0) + { + /* The parent process does not need the input pipe read end. */ + kwsysProcessCleanupDescriptor(&si->StdIn); + } + + /* The parent process does not need the output pipe write ends. */ + if(si->StdOut != 1) + { + kwsysProcessCleanupDescriptor(&si->StdOut); + } + + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcessSetupOutputPipeFile(int* p, const char* name) +{ + int fout; + if(!name) + { + return 1; + } + + /* Close the existing descriptor. */ + kwsysProcessCleanupDescriptor(p); + + /* Open a file for the pipe to write (permissions 644). */ + if((fout = open(name, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) + { + return 0; + } + + /* Set close-on-exec flag on the pipe's end. */ + if(fcntl(fout, F_SETFD, FD_CLOEXEC) < 0) + { + return 0; + } + + /* Assign the replacement descriptor. */ + *p = fout; + return 1; +} + +/*--------------------------------------------------------------------------*/ +/* Get the time at which either the process or user timeout will + expire. Returns 1 if the user timeout is first, and 0 otherwise. */ +static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, + kwsysProcessTime* timeoutTime) +{ + /* The first time this is called, we need to calculate the time at + which the child will timeout. */ + if(cp->Timeout && cp->TimeoutTime.tv_sec < 0) + { + kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout); + cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length); + } + + /* Start with process timeout. */ + *timeoutTime = cp->TimeoutTime; + + /* Check if the user timeout is earlier. */ + if(userTimeout) + { + kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); + kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout); + kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime, + userTimeoutLength); + if(timeoutTime->tv_sec < 0 || + kwsysProcessTimeLess(userTimeoutTime, *timeoutTime)) + { + *timeoutTime = userTimeoutTime; + return 1; + } + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +/* Get the length of time before the given timeout time arrives. + Returns 1 if the time has already arrived, and 0 otherwise. */ +static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, + double* userTimeout, + kwsysProcessTimeNative* timeoutLength) +{ + if(timeoutTime->tv_sec < 0) + { + /* No timeout time has been requested. */ + return 0; + } + else + { + /* Calculate the remaining time. */ + kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); + kwsysProcessTime timeLeft = kwsysProcessTimeSubtract(*timeoutTime, + currentTime); + if(timeLeft.tv_sec < 0 && userTimeout && *userTimeout <= 0) + { + /* Caller has explicitly requested a zero timeout. */ + timeLeft.tv_sec = 0; + timeLeft.tv_usec = 0; + } + + if(timeLeft.tv_sec < 0) + { + /* Timeout has already expired. */ + return 1; + } + else + { + /* There is some time left. */ + timeoutLength->tv_sec = timeLeft.tv_sec; + timeoutLength->tv_usec = timeLeft.tv_usec; + return 0; + } + } +} + +/*--------------------------------------------------------------------------*/ +static kwsysProcessTime kwsysProcessTimeGetCurrent(void) +{ + kwsysProcessTime current; + kwsysProcessTimeNative current_native; + gettimeofday(¤t_native, 0); + current.tv_sec = (long)current_native.tv_sec; + current.tv_usec = (long)current_native.tv_usec; + return current; +} + +/*--------------------------------------------------------------------------*/ +static double kwsysProcessTimeToDouble(kwsysProcessTime t) +{ + return (double)t.tv_sec + t.tv_usec*0.000001; +} + +/*--------------------------------------------------------------------------*/ +static kwsysProcessTime kwsysProcessTimeFromDouble(double d) +{ + kwsysProcessTime t; + t.tv_sec = (long)d; + t.tv_usec = (long)((d-t.tv_sec)*1000000); + return t; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2) +{ + return ((in1.tv_sec < in2.tv_sec) || + ((in1.tv_sec == in2.tv_sec) && (in1.tv_usec < in2.tv_usec))); +} + +/*--------------------------------------------------------------------------*/ +static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2) +{ + kwsysProcessTime out; + out.tv_sec = in1.tv_sec + in2.tv_sec; + out.tv_usec = in1.tv_usec + in2.tv_usec; + if(out.tv_usec > 1000000) + { + out.tv_usec -= 1000000; + out.tv_sec += 1; + } + return out; +} + +/*--------------------------------------------------------------------------*/ +static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2) +{ + kwsysProcessTime out; + out.tv_sec = in1.tv_sec - in2.tv_sec; + out.tv_usec = in1.tv_usec - in2.tv_usec; + if(out.tv_usec < 0) + { + out.tv_usec += 1000000; + out.tv_sec -= 1; + } + return out; +} + +/*--------------------------------------------------------------------------*/ +#define KWSYSPE_CASE(type, str) \ + cp->ExitException = kwsysProcess_Exception_##type; \ + strcpy(cp->ExitExceptionString, str) +static void kwsysProcessSetExitException(kwsysProcess* cp, int sig) +{ + switch (sig) + { +#ifdef SIGSEGV + case SIGSEGV: KWSYSPE_CASE(Fault, "Segmentation fault"); break; +#endif +#ifdef SIGBUS +# if !defined(SIGSEGV) || SIGBUS != SIGSEGV + case SIGBUS: KWSYSPE_CASE(Fault, "Bus error"); break; +# endif +#endif +#ifdef SIGFPE + case SIGFPE: KWSYSPE_CASE(Numerical, "Floating-point exception"); break; +#endif +#ifdef SIGILL + case SIGILL: KWSYSPE_CASE(Illegal, "Illegal instruction"); break; +#endif +#ifdef SIGINT + case SIGINT: KWSYSPE_CASE(Interrupt, "User interrupt"); break; +#endif +#ifdef SIGABRT + case SIGABRT: KWSYSPE_CASE(Other, "Child aborted"); break; +#endif +#ifdef SIGKILL + case SIGKILL: KWSYSPE_CASE(Other, "Child killed"); break; +#endif +#ifdef SIGTERM + case SIGTERM: KWSYSPE_CASE(Other, "Child terminated"); break; +#endif +#ifdef SIGHUP + case SIGHUP: KWSYSPE_CASE(Other, "SIGHUP"); break; +#endif +#ifdef SIGQUIT + case SIGQUIT: KWSYSPE_CASE(Other, "SIGQUIT"); break; +#endif +#ifdef SIGTRAP + case SIGTRAP: KWSYSPE_CASE(Other, "SIGTRAP"); break; +#endif +#ifdef SIGIOT +# if !defined(SIGABRT) || SIGIOT != SIGABRT + case SIGIOT: KWSYSPE_CASE(Other, "SIGIOT"); break; +# endif +#endif +#ifdef SIGUSR1 + case SIGUSR1: KWSYSPE_CASE(Other, "SIGUSR1"); break; +#endif +#ifdef SIGUSR2 + case SIGUSR2: KWSYSPE_CASE(Other, "SIGUSR2"); break; +#endif +#ifdef SIGPIPE + case SIGPIPE: KWSYSPE_CASE(Other, "SIGPIPE"); break; +#endif +#ifdef SIGALRM + case SIGALRM: KWSYSPE_CASE(Other, "SIGALRM"); break; +#endif +#ifdef SIGSTKFLT + case SIGSTKFLT: KWSYSPE_CASE(Other, "SIGSTKFLT"); break; +#endif +#ifdef SIGCHLD + case SIGCHLD: KWSYSPE_CASE(Other, "SIGCHLD"); break; +#elif defined(SIGCLD) + case SIGCLD: KWSYSPE_CASE(Other, "SIGCLD"); break; +#endif +#ifdef SIGCONT + case SIGCONT: KWSYSPE_CASE(Other, "SIGCONT"); break; +#endif +#ifdef SIGSTOP + case SIGSTOP: KWSYSPE_CASE(Other, "SIGSTOP"); break; +#endif +#ifdef SIGTSTP + case SIGTSTP: KWSYSPE_CASE(Other, "SIGTSTP"); break; +#endif +#ifdef SIGTTIN + case SIGTTIN: KWSYSPE_CASE(Other, "SIGTTIN"); break; +#endif +#ifdef SIGTTOU + case SIGTTOU: KWSYSPE_CASE(Other, "SIGTTOU"); break; +#endif +#ifdef SIGURG + case SIGURG: KWSYSPE_CASE(Other, "SIGURG"); break; +#endif +#ifdef SIGXCPU + case SIGXCPU: KWSYSPE_CASE(Other, "SIGXCPU"); break; +#endif +#ifdef SIGXFSZ + case SIGXFSZ: KWSYSPE_CASE(Other, "SIGXFSZ"); break; +#endif +#ifdef SIGVTALRM + case SIGVTALRM: KWSYSPE_CASE(Other, "SIGVTALRM"); break; +#endif +#ifdef SIGPROF + case SIGPROF: KWSYSPE_CASE(Other, "SIGPROF"); break; +#endif +#ifdef SIGWINCH + case SIGWINCH: KWSYSPE_CASE(Other, "SIGWINCH"); break; +#endif +#ifdef SIGPOLL + case SIGPOLL: KWSYSPE_CASE(Other, "SIGPOLL"); break; +#endif +#ifdef SIGIO +# if !defined(SIGPOLL) || SIGIO != SIGPOLL + case SIGIO: KWSYSPE_CASE(Other, "SIGIO"); break; +# endif +#endif +#ifdef SIGPWR + case SIGPWR: KWSYSPE_CASE(Other, "SIGPWR"); break; +#endif +#ifdef SIGSYS + case SIGSYS: KWSYSPE_CASE(Other, "SIGSYS"); break; +#endif +#ifdef SIGUNUSED +# if !defined(SIGSYS) || SIGUNUSED != SIGSYS + case SIGUNUSED: KWSYSPE_CASE(Other, "SIGUNUSED"); break; +# endif +#endif + default: + cp->ExitException = kwsysProcess_Exception_Other; + sprintf(cp->ExitExceptionString, "Signal %d", sig); + break; + } +} +#undef KWSYSPE_CASE + +/*--------------------------------------------------------------------------*/ +/* When the child process encounters an error before its program is + invoked, this is called to report the error to the parent and + exit. */ +static void kwsysProcessChildErrorExit(int errorPipe) +{ + /* Construct the error message. */ + char buffer[KWSYSPE_PIPE_BUFFER_SIZE]; + strncpy(buffer, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); + + /* Report the error to the parent through the special pipe. */ + write(errorPipe, buffer, strlen(buffer)); + + /* Terminate without cleanup. */ + _exit(1); +} + +/*--------------------------------------------------------------------------*/ +/* Restores all signal handlers to their default values. */ +static void kwsysProcessRestoreDefaultSignalHandlers(void) +{ + struct sigaction act; + memset(&act, 0, sizeof(struct sigaction)); + act.sa_handler = SIG_DFL; +#ifdef SIGHUP + sigaction(SIGHUP, &act, 0); +#endif +#ifdef SIGINT + sigaction(SIGINT, &act, 0); +#endif +#ifdef SIGQUIT + sigaction(SIGQUIT, &act, 0); +#endif +#ifdef SIGILL + sigaction(SIGILL, &act, 0); +#endif +#ifdef SIGTRAP + sigaction(SIGTRAP, &act, 0); +#endif +#ifdef SIGABRT + sigaction(SIGABRT, &act, 0); +#endif +#ifdef SIGIOT + sigaction(SIGIOT, &act, 0); +#endif +#ifdef SIGBUS + sigaction(SIGBUS, &act, 0); +#endif +#ifdef SIGFPE + sigaction(SIGFPE, &act, 0); +#endif +#ifdef SIGUSR1 + sigaction(SIGUSR1, &act, 0); +#endif +#ifdef SIGSEGV + sigaction(SIGSEGV, &act, 0); +#endif +#ifdef SIGUSR2 + sigaction(SIGUSR2, &act, 0); +#endif +#ifdef SIGPIPE + sigaction(SIGPIPE, &act, 0); +#endif +#ifdef SIGALRM + sigaction(SIGALRM, &act, 0); +#endif +#ifdef SIGTERM + sigaction(SIGTERM, &act, 0); +#endif +#ifdef SIGSTKFLT + sigaction(SIGSTKFLT, &act, 0); +#endif +#ifdef SIGCLD + sigaction(SIGCLD, &act, 0); +#endif +#ifdef SIGCHLD + sigaction(SIGCHLD, &act, 0); +#endif +#ifdef SIGCONT + sigaction(SIGCONT, &act, 0); +#endif +#ifdef SIGTSTP + sigaction(SIGTSTP, &act, 0); +#endif +#ifdef SIGTTIN + sigaction(SIGTTIN, &act, 0); +#endif +#ifdef SIGTTOU + sigaction(SIGTTOU, &act, 0); +#endif +#ifdef SIGURG + sigaction(SIGURG, &act, 0); +#endif +#ifdef SIGXCPU + sigaction(SIGXCPU, &act, 0); +#endif +#ifdef SIGXFSZ + sigaction(SIGXFSZ, &act, 0); +#endif +#ifdef SIGVTALRM + sigaction(SIGVTALRM, &act, 0); +#endif +#ifdef SIGPROF + sigaction(SIGPROF, &act, 0); +#endif +#ifdef SIGWINCH + sigaction(SIGWINCH, &act, 0); +#endif +#ifdef SIGPOLL + sigaction(SIGPOLL, &act, 0); +#endif +#ifdef SIGIO + sigaction(SIGIO, &act, 0); +#endif +#ifdef SIGPWR + sigaction(SIGPWR, &act, 0); +#endif +#ifdef SIGSYS + sigaction(SIGSYS, &act, 0); +#endif +#ifdef SIGUNUSED + sigaction(SIGUNUSED, &act, 0); +#endif +} + +/*--------------------------------------------------------------------------*/ +static pid_t kwsysProcessFork(kwsysProcess* cp, + kwsysProcessCreateInformation* si) +{ + /* Create a detached process if requested. */ + if(cp->OptionDetach) + { + /* Create an intermediate process. */ + pid_t middle_pid = fork(); + if(middle_pid < 0) + { + /* Fork failed. Return as if we were not detaching. */ + return middle_pid; + } + else if(middle_pid == 0) + { + /* This is the intermediate process. Create the real child. */ + pid_t child_pid = fork(); + if(child_pid == 0) + { + /* This is the real child process. There is nothing to do here. */ + return 0; + } + else + { + /* Use the error pipe to report the pid to the real parent. */ + while((write(si->ErrorPipe[1], &child_pid, sizeof(child_pid)) < 0) && + (errno == EINTR)); + + /* Exit without cleanup. The parent holds all resources. */ + _exit(0); + return 0; /* Never reached, but avoids SunCC warning. */ + } + } + else + { + /* This is the original parent process. The intermediate + process will use the error pipe to report the pid of the + detached child. */ + pid_t child_pid; + int status; + while((read(si->ErrorPipe[0], &child_pid, sizeof(child_pid)) < 0) && + (errno == EINTR)); + + /* Wait for the intermediate process to exit and clean it up. */ + while((waitpid(middle_pid, &status, 0) < 0) && (errno == EINTR)); + return child_pid; + } + } + else + { + /* Not creating a detached process. Use normal fork. */ + return fork(); + } +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcessKill(pid_t process_id) +{ + DIR* procdir; + + /* Suspend the process to be sure it will not create more children. */ + kill(process_id, SIGSTOP); + + /* Kill all children if we can find them. Currently this works only + on systems that support the proc filesystem. */ + if((procdir = opendir("/proc")) != NULL) + { +#if defined(MAXPATHLEN) + char fname[MAXPATHLEN]; +#elif defined(PATH_MAX) + char fname[PATH_MAX]; +#else + char fname[4096]; +#endif + char buffer[KWSYSPE_PIPE_BUFFER_SIZE+1]; + struct dirent* d; + + /* Each process has a directory in /proc whose name is the pid. + Within this directory is a file called stat that has the + following format: + + pid (command line) status ppid ... + + We want to get the ppid for all processes. Those that have + process_id as their parent should be recursively killed. */ + for(d = readdir(procdir); d; d = readdir(procdir)) + { + int pid; + if(sscanf(d->d_name, "%d", &pid) == 1 && pid != 0) + { + struct stat finfo; + sprintf(fname, "/proc/%d/stat", pid); + if(stat(fname, &finfo) == 0) + { + FILE* f = fopen(fname, "r"); + if(f) + { + int nread = fread(buffer, 1, KWSYSPE_PIPE_BUFFER_SIZE, f); + buffer[nread] = '\0'; + if(nread > 0) + { + const char* rparen = strrchr(buffer, ')'); + int ppid; + if(rparen && (sscanf(rparen+1, "%*s %d", &ppid) == 1)) + { + if(ppid == process_id) + { + /* Recursively kill this child and its children. */ + kwsysProcessKill(pid); + } + } + } + fclose(f); + } + } + } + } + closedir(procdir); + } + + /* Kill the process. */ + kill(process_id, SIGKILL); +} diff --git a/Utilities/kwsys/ProcessWin32.c b/Utilities/kwsys/ProcessWin32.c new file mode 100644 index 0000000..010ed40 --- /dev/null +++ b/Utilities/kwsys/ProcessWin32.c @@ -0,0 +1,2749 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: ProcessWin32.c,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Process.h) + +/* Work-around CMake dependency scanning limitation. This must + duplicate the above list of headers. */ +#if 0 +# include "Process.h.in" +#endif + +/* + +Implementation for Windows + +On windows, a thread is created to wait for data on each pipe. The +threads are synchronized with the main thread to simulate the use of +a UNIX-style select system call. + +On Windows9x platforms, a small WIN32 console application is spawned +in-between the calling process and the actual child to be executed. +This is to work-around a problem with connecting pipes from WIN16 +console applications to WIN32 applications. + +For more information, please check Microsoft Knowledge Base Articles +Q190351 and Q150956. + +*/ + +#ifdef _MSC_VER +#pragma warning (push, 1) +#endif +#include /* Windows API */ +#include /* strlen, strdup */ +#include /* sprintf */ +#include /* _unlink */ + +#ifndef _MAX_FNAME +#define _MAX_FNAME 4096 +#endif +#ifndef _MAX_PATH +#define _MAX_PATH 4096 +#endif + +#ifdef _MSC_VER +#pragma warning (pop) +#pragma warning (disable: 4514) +#pragma warning (disable: 4706) +#endif + +/* There are pipes for the process pipeline's stdout and stderr. */ +#define KWSYSPE_PIPE_COUNT 2 +#define KWSYSPE_PIPE_STDOUT 0 +#define KWSYSPE_PIPE_STDERR 1 + +/* The maximum amount to read from a pipe at a time. */ +#define KWSYSPE_PIPE_BUFFER_SIZE 1024 + +#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x) + +typedef LARGE_INTEGER kwsysProcessTime; + +typedef struct kwsysProcessCreateInformation_s +{ + /* Windows child startup control data. */ + STARTUPINFO StartupInfo; + + /* Special error reporting pipe for Win9x forwarding executable. */ + HANDLE ErrorPipeRead; + HANDLE ErrorPipeWrite; +} kwsysProcessCreateInformation; + +/*--------------------------------------------------------------------------*/ +typedef struct kwsysProcessPipeData_s kwsysProcessPipeData; +static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd); +static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, + kwsysProcessPipeData* td); +static DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd); +static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, + kwsysProcessPipeData* td); +static int kwsysProcessInitialize(kwsysProcess* cp); +static int kwsysProcessCreate(kwsysProcess* cp, int index, + kwsysProcessCreateInformation* si, + PHANDLE readEnd); +static void kwsysProcessDestroy(kwsysProcess* cp, int event); +static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name); +static void kwsysProcessCleanupHandle(PHANDLE h); +static void kwsysProcessCleanup(kwsysProcess* cp, int error); +static void kwsysProcessCleanErrorMessage(kwsysProcess* cp); +static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, + kwsysProcessTime* timeoutTime); +static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, + double* userTimeout, + kwsysProcessTime* timeoutLength); +static kwsysProcessTime kwsysProcessTimeGetCurrent(); +static DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t); +static double kwsysProcessTimeToDouble(kwsysProcessTime t); +static kwsysProcessTime kwsysProcessTimeFromDouble(double d); +static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); +static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); +static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2); +static void kwsysProcessSetExitException(kwsysProcess* cp, int code); +static void kwsysProcessKillTree(int pid); +static void kwsysProcessDisablePipeThreads(kwsysProcess* cp); +extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname); + +/*--------------------------------------------------------------------------*/ +/* A structure containing synchronization data for each thread. */ +typedef struct kwsysProcessPipeSync_s kwsysProcessPipeSync; +struct kwsysProcessPipeSync_s +{ + /* Handle to the thread. */ + HANDLE Thread; + + /* Semaphore indicating to the thread that a process has started. */ + HANDLE Ready; + + /* Semaphore indicating to the thread that it should begin work. */ + HANDLE Go; + + /* Semaphore indicating thread has reset for another process. */ + HANDLE Reset; +}; + +/*--------------------------------------------------------------------------*/ +/* A structure containing data for each pipe's threads. */ +struct kwsysProcessPipeData_s +{ + /* ------------- Data managed per instance of kwsysProcess ------------- */ + + /* Synchronization data for reading thread. */ + kwsysProcessPipeSync Reader; + + /* Synchronization data for waking thread. */ + kwsysProcessPipeSync Waker; + + /* Index of this pipe. */ + int Index; + + /* The kwsysProcess instance owning this pipe. */ + kwsysProcess* Process; + + /* ------------- Data managed per call to Execute ------------- */ + + /* Buffer for data read in this pipe's thread. */ + char DataBuffer[KWSYSPE_PIPE_BUFFER_SIZE]; + + /* The length of the data stored in the buffer. */ + DWORD DataLength; + + /* Whether the pipe has been closed. */ + int Closed; + + /* Handle for the read end of this pipe. */ + HANDLE Read; + + /* Handle for the write end of this pipe. */ + HANDLE Write; +}; + +/*--------------------------------------------------------------------------*/ +/* Structure containing data used to implement the child's execution. */ +struct kwsysProcess_s +{ + /* ------------- Data managed per instance of kwsysProcess ------------- */ + + /* The status of the process structure. */ + int State; + + /* The command lines to execute. */ + char** Commands; + int NumberOfCommands; + + /* The exit code of each command. */ + DWORD* CommandExitCodes; + + /* The working directory for the child process. */ + char* WorkingDirectory; + + /* Whether to create the child as a detached process. */ + int OptionDetach; + + /* Whether the child was created as a detached process. */ + int Detached; + + /* Whether to hide the child process's window. */ + int HideWindow; + + /* On Win9x platforms, the path to the forwarding executable. */ + char* Win9x; + + /* On Win9x platforms, the resume event for the forwarding executable. */ + HANDLE Win9xResumeEvent; + + /* On Win9x platforms, the kill event for the forwarding executable. */ + HANDLE Win9xKillEvent; + + /* Mutex to protect the shared index used by threads to report data. */ + HANDLE SharedIndexMutex; + + /* Semaphore used by threads to signal data ready. */ + HANDLE Full; + + /* Whether we are currently deleting this kwsysProcess instance. */ + int Deleting; + + /* Data specific to each pipe and its thread. */ + kwsysProcessPipeData Pipe[KWSYSPE_PIPE_COUNT]; + + /* Name of files to which stdin and stdout pipes are attached. */ + char* PipeFileSTDIN; + char* PipeFileSTDOUT; + char* PipeFileSTDERR; + + /* Whether each pipe is shared with the parent process. */ + int PipeSharedSTDIN; + int PipeSharedSTDOUT; + int PipeSharedSTDERR; + + /* Handle to automatically delete the Win9x forwarding executable. */ + HANDLE Win9xHandle; + + /* ------------- Data managed per call to Execute ------------- */ + + /* The exceptional behavior that terminated the process, if any. */ + int ExitException; + + /* The process exit code. */ + DWORD ExitCode; + + /* The process return code, if any. */ + int ExitValue; + + /* Index of last pipe to report data, if any. */ + int CurrentIndex; + + /* Index shared by threads to report data. */ + int SharedIndex; + + /* The timeout length. */ + double Timeout; + + /* Time at which the child started. */ + kwsysProcessTime StartTime; + + /* Time at which the child will timeout. Negative for no timeout. */ + kwsysProcessTime TimeoutTime; + + /* Flag for whether the process was killed. */ + int Killed; + + /* Flag for whether the timeout expired. */ + int TimeoutExpired; + + /* Flag for whether the process has terminated. */ + int Terminated; + + /* The number of pipes still open during execution and while waiting + for pipes to close after process termination. */ + int PipesLeft; + + /* Buffer for error messages (possibly from Win9x child). */ + char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; + + /* Description for the ExitException. */ + char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1]; + + /* Windows process information data. */ + PROCESS_INFORMATION* ProcessInformation; + + /* Data and process termination events for which to wait. */ + PHANDLE ProcessEvents; + int ProcessEventsLength; + + /* Real working directory of our own process. */ + DWORD RealWorkingDirectoryLength; + char* RealWorkingDirectory; +}; + +/*--------------------------------------------------------------------------*/ +kwsysProcess* kwsysProcess_New() +{ + int i; + + /* Process control structure. */ + kwsysProcess* cp; + + /* Path to Win9x forwarding executable. */ + char* win9x = 0; + + /* Windows version number data. */ + OSVERSIONINFO osv; + + /* Allocate a process control structure. */ + cp = (kwsysProcess*)malloc(sizeof(kwsysProcess)); + if(!cp) + { + /* Could not allocate memory for the control structure. */ + return 0; + } + ZeroMemory(cp, sizeof(*cp)); + + /* Share stdin with the parent process by default. */ + cp->PipeSharedSTDIN = 1; + + /* Set initial status. */ + cp->State = kwsysProcess_State_Starting; + + /* Choose a method of running the child based on version of + windows. */ + ZeroMemory(&osv, sizeof(osv)); + osv.dwOSVersionInfoSize = sizeof(osv); + GetVersionEx(&osv); + if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + /* This is Win9x. We need the console forwarding executable to + work-around a Windows 9x bug. */ + char fwdName[_MAX_FNAME+1] = ""; + char tempDir[_MAX_PATH+1] = ""; + + /* We will try putting the executable in the system temp + directory. Note that the returned path already has a trailing + slash. */ + DWORD length = GetTempPath(_MAX_PATH+1, tempDir); + + /* Construct the executable name from the process id and kwsysProcess + instance. This should be unique. */ + sprintf(fwdName, KWSYS_NAMESPACE_STRING "pew9xfwd_%u_%p.exe", + GetCurrentProcessId(), cp); + + /* If we have a temp directory, use it. */ + if(length > 0 && length <= _MAX_PATH) + { + /* Allocate a buffer to hold the forwarding executable path. */ + size_t tdlen = strlen(tempDir); + win9x = (char*)malloc(tdlen + strlen(fwdName) + 2); + if(!win9x) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* Construct the full path to the forwarding executable. */ + sprintf(win9x, "%s%s", tempDir, fwdName); + } + + /* If we found a place to put the forwarding executable, try to + write it. */ + if(win9x) + { + if(!kwsysEncodedWriteArrayProcessFwd9x(win9x)) + { + /* Failed to create forwarding executable. Give up. */ + free(win9x); + kwsysProcess_Delete(cp); + return 0; + } + + /* Get a handle to the file that will delete it when closed. */ + cp->Win9xHandle = CreateFile(win9x, GENERIC_READ, FILE_SHARE_READ, 0, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); + if(cp->Win9xHandle == INVALID_HANDLE_VALUE) + { + /* We were not able to get a read handle for the forwarding + executable. It will not be deleted properly. Give up. */ + _unlink(win9x); + free(win9x); + kwsysProcess_Delete(cp); + return 0; + } + } + else + { + /* Failed to find a place to put forwarding executable. */ + kwsysProcess_Delete(cp); + return 0; + } + } + + /* Save the path to the forwarding executable. */ + cp->Win9x = win9x; + + /* Initially no thread owns the mutex. Initialize semaphore to 1. */ + if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* Initially no data are available. Initialize semaphore to 0. */ + if(!(cp->Full = CreateSemaphore(0, 0, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + if(cp->Win9x) + { + SECURITY_ATTRIBUTES sa; + ZeroMemory(&sa, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + + /* Create an event to tell the forwarding executable to resume the + child. */ + if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* Create an event to tell the forwarding executable to kill the + child. */ + if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + } + + /* Create the thread to read each pipe. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + DWORD dummy=0; + + /* Assign the thread its index. */ + cp->Pipe[i].Index = i; + + /* Give the thread a pointer back to the kwsysProcess instance. */ + cp->Pipe[i].Process = cp; + + /* No process is yet running. Initialize semaphore to 0. */ + if(!(cp->Pipe[i].Reader.Ready = CreateSemaphore(0, 0, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* The pipe is not yet reset. Initialize semaphore to 0. */ + if(!(cp->Pipe[i].Reader.Reset = CreateSemaphore(0, 0, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* The thread's buffer is initially empty. Initialize semaphore to 1. */ + if(!(cp->Pipe[i].Reader.Go = CreateSemaphore(0, 1, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* Create the reading thread. It will block immediately. The + thread will not make deeply nested calls, so we need only a + small stack. */ + if(!(cp->Pipe[i].Reader.Thread = CreateThread(0, 1024, + kwsysProcessPipeThreadRead, + &cp->Pipe[i], 0, &dummy))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* No process is yet running. Initialize semaphore to 0. */ + if(!(cp->Pipe[i].Waker.Ready = CreateSemaphore(0, 0, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* The pipe is not yet reset. Initialize semaphore to 0. */ + if(!(cp->Pipe[i].Waker.Reset = CreateSemaphore(0, 0, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* The waker should not wake immediately. Initialize semaphore to 0. */ + if(!(cp->Pipe[i].Waker.Go = CreateSemaphore(0, 0, 1, 0))) + { + kwsysProcess_Delete(cp); + return 0; + } + + /* Create the waking thread. It will block immediately. The + thread will not make deeply nested calls, so we need only a + small stack. */ + if(!(cp->Pipe[i].Waker.Thread = CreateThread(0, 1024, + kwsysProcessPipeThreadWake, + &cp->Pipe[i], 0, &dummy))) + { + kwsysProcess_Delete(cp); + return 0; + } + } + + return cp; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_Delete(kwsysProcess* cp) +{ + int i; + + /* Make sure we have an instance. */ + if(!cp) + { + return; + } + + /* If the process is executing, wait for it to finish. */ + if(cp->State == kwsysProcess_State_Executing) + { + if(cp->Detached) + { + kwsysProcess_Disown(cp); + } + else + { + kwsysProcess_WaitForExit(cp, 0); + } + } + + /* We are deleting the kwsysProcess instance. */ + cp->Deleting = 1; + + /* Terminate each of the threads. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + /* Terminate this reading thread. */ + if(cp->Pipe[i].Reader.Thread) + { + /* Signal the thread we are ready for it. It will terminate + immediately since Deleting is set. */ + ReleaseSemaphore(cp->Pipe[i].Reader.Ready, 1, 0); + + /* Wait for the thread to exit. */ + WaitForSingleObject(cp->Pipe[i].Reader.Thread, INFINITE); + + /* Close the handle to the thread. */ + kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Thread); + } + + /* Terminate this waking thread. */ + if(cp->Pipe[i].Waker.Thread) + { + /* Signal the thread we are ready for it. It will terminate + immediately since Deleting is set. */ + ReleaseSemaphore(cp->Pipe[i].Waker.Ready, 1, 0); + + /* Wait for the thread to exit. */ + WaitForSingleObject(cp->Pipe[i].Waker.Thread, INFINITE); + + /* Close the handle to the thread. */ + kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Thread); + } + + /* Cleanup the pipe's semaphores. */ + kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Ready); + kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Go); + kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Reset); + kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Ready); + kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Go); + kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Reset); + } + + /* Close the shared semaphores. */ + kwsysProcessCleanupHandle(&cp->SharedIndexMutex); + kwsysProcessCleanupHandle(&cp->Full); + + /* Close the Win9x resume and kill event handles. */ + if(cp->Win9x) + { + kwsysProcessCleanupHandle(&cp->Win9xResumeEvent); + kwsysProcessCleanupHandle(&cp->Win9xKillEvent); + } + + /* Free memory. */ + kwsysProcess_SetCommand(cp, 0); + kwsysProcess_SetWorkingDirectory(cp, 0); + kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0); + kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0); + kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0); + if(cp->CommandExitCodes) + { + free(cp->CommandExitCodes); + } + if(cp->Win9x) + { + /* Close our handle to the forwarding executable file. This will + cause it to be deleted. */ + kwsysProcessCleanupHandle(&cp->Win9xHandle); + } + free(cp); +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) +{ + int i; + if(!cp) + { + return 0; + } + for(i=0; i < cp->NumberOfCommands; ++i) + { + free(cp->Commands[i]); + } + cp->NumberOfCommands = 0; + if(cp->Commands) + { + free(cp->Commands); + cp->Commands = 0; + } + if(command) + { + return kwsysProcess_AddCommand(cp, command); + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) +{ + int newNumberOfCommands; + char** newCommands; + + /* Make sure we have a command to add. */ + if(!cp || !command) + { + return 0; + } + + /* Allocate a new array for command pointers. */ + newNumberOfCommands = cp->NumberOfCommands + 1; + if(!(newCommands = (char**)malloc(sizeof(char*) * newNumberOfCommands))) + { + /* Out of memory. */ + return 0; + } + + /* Copy any existing commands into the new array. */ + { + int i; + for(i=0; i < cp->NumberOfCommands; ++i) + { + newCommands[i] = cp->Commands[i]; + } + } + + /* We need to construct a single string representing the command + and its arguments. We will surround each argument containing + spaces with double-quotes. Inside a double-quoted argument, we + need to escape double-quotes and all backslashes before them. + We also need to escape backslashes at the end of an argument + because they come before the closing double-quote for the + argument. */ + { + char* cmd; + char const* const* arg; + int length = 0; + /* First determine the length of the final string. */ + for(arg = command; *arg; ++arg) + { + /* Keep track of how many backslashes have been encountered in a + row in this argument. */ + int backslashes = 0; + int spaces = 0; + const char* c; + + /* Scan the string for spaces. If there are no spaces, we can + pass the argument verbatim. */ + for(c=*arg; *c; ++c) + { + if(*c == ' ' || *c == '\t') + { + spaces = 1; + break; + } + } + + /* Add the length of the argument, plus 1 for the space + separating the arguments. */ + length += (int)strlen(*arg) + 1; + + if(spaces) + { + /* Add 2 for double quotes since spaces are present. */ + length += 2; + + /* Scan the string to find characters that need escaping. */ + for(c=*arg; *c; ++c) + { + if(*c == '\\') + { + /* Found a backslash. It may need to be escaped later. */ + ++backslashes; + } + else if(*c == '"') + { + /* Found a double-quote. We need to escape it and all + immediately preceding backslashes. */ + length += backslashes + 1; + backslashes = 0; + } + else + { + /* Found another character. This eliminates the possibility + that any immediately preceding backslashes will be + escaped. */ + backslashes = 0; + } + } + + /* We need to escape all ending backslashes. */ + length += backslashes; + } + } + + /* Allocate enough space for the command. We do not need an extra + byte for the terminating null because we allocated a space for + the first argument that we will not use. */ + newCommands[cp->NumberOfCommands] = (char*)malloc(length); + if(!newCommands[cp->NumberOfCommands]) + { + /* Out of memory. */ + free(newCommands); + return 0; + } + + /* Construct the command line in the allocated buffer. */ + cmd = newCommands[cp->NumberOfCommands]; + for(arg = command; *arg; ++arg) + { + /* Keep track of how many backslashes have been encountered in a + row in an argument. */ + int backslashes = 0; + int spaces = 0; + const char* c; + + /* Scan the string for spaces. If there are no spaces, we can + pass the argument verbatim. */ + for(c=*arg; *c; ++c) + { + if(*c == ' ' || *c == '\t') + { + spaces = 1; + break; + } + } + + /* Add the separating space if this is not the first argument. */ + if(arg != command) + { + *cmd++ = ' '; + } + + if(spaces) + { + /* Add the opening double-quote for this argument. */ + *cmd++ = '"'; + + /* Add the characters of the argument, possibly escaping them. */ + for(c=*arg; *c; ++c) + { + if(*c == '\\') + { + /* Found a backslash. It may need to be escaped later. */ + ++backslashes; + *cmd++ = '\\'; + } + else if(*c == '"') + { + /* Add enough backslashes to escape any that preceded the + double-quote. */ + while(backslashes > 0) + { + --backslashes; + *cmd++ = '\\'; + } + + /* Add the backslash to escape the double-quote. */ + *cmd++ = '\\'; + + /* Add the double-quote itself. */ + *cmd++ = '"'; + } + else + { + /* We encountered a normal character. This eliminates any + escaping needed for preceding backslashes. Add the + character. */ + backslashes = 0; + *cmd++ = *c; + } + } + + /* Add enough backslashes to escape any trailing ones. */ + while(backslashes > 0) + { + --backslashes; + *cmd++ = '\\'; + } + + /* Add the closing double-quote for this argument. */ + *cmd++ = '"'; + } + else + { + /* No spaces. Add the argument verbatim. */ + for(c=*arg; *c; ++c) + { + *cmd++ = *c; + } + } + } + + /* Add the terminating null character to the command line. */ + *cmd = 0; + } + + /* Save the new array of commands. */ + free(cp->Commands); + cp->Commands = newCommands; + cp->NumberOfCommands = newNumberOfCommands; + return 1; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) +{ + if(!cp) + { + return; + } + cp->Timeout = timeout; + if(cp->Timeout < 0) + { + cp->Timeout = 0; + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) +{ + if(!cp) + { + return 0; + } + if(cp->WorkingDirectory) + { + free(cp->WorkingDirectory); + cp->WorkingDirectory = 0; + } + if(dir && dir[0]) + { + /* We must convert the working directory to a full path. */ + DWORD length = GetFullPathName(dir, 0, 0, 0); + if(length > 0) + { + cp->WorkingDirectory = (char*)malloc(length); + if(!cp->WorkingDirectory) + { + return 0; + } + if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0)) + { + free(cp->WorkingDirectory); + cp->WorkingDirectory = 0; + return 0; + } + } + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file) +{ + char** pfile; + if(!cp) + { + return 0; + } + switch(pipe) + { + case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break; + case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break; + case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break; + default: return 0; + } + if(*pfile) + { + free(*pfile); + *pfile = 0; + } + if(file) + { + *pfile = malloc(strlen(file)+1); + if(!*pfile) + { + return 0; + } + strcpy(*pfile, file); + } + + /* If we are redirecting the pipe, do not share it. */ + if(*pfile) + { + kwsysProcess_SetPipeShared(cp, pipe, 0); + } + + return 1; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared) +{ + if(!cp) + { + return; + } + + switch(pipe) + { + case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break; + case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break; + case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break; + default: return; + } + + /* If we are sharing the pipe, do not redirect it to a file. */ + if(shared) + { + kwsysProcess_SetPipeFile(cp, pipe, 0); + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) +{ + if(!cp) + { + return 0; + } + + switch(optionId) + { + case kwsysProcess_Option_Detach: return cp->OptionDetach; + case kwsysProcess_Option_HideWindow: return cp->HideWindow; + default: return 0; + } +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) +{ + if(!cp) + { + return; + } + + switch(optionId) + { + case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; + case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break; + default: break; + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetState(kwsysProcess* cp) +{ + return cp? cp->State : kwsysProcess_State_Error; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetExitException(kwsysProcess* cp) +{ + return cp? cp->ExitException : kwsysProcess_Exception_Other; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetExitValue(kwsysProcess* cp) +{ + return cp? cp->ExitValue : -1; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_GetExitCode(kwsysProcess* cp) +{ + return cp? cp->ExitCode : 0; +} + +/*--------------------------------------------------------------------------*/ +const char* kwsysProcess_GetErrorString(kwsysProcess* cp) +{ + if(!cp) + { + return "Process management structure could not be allocated"; + } + else if(cp->State == kwsysProcess_State_Error) + { + return cp->ErrorMessage; + } + return "Success"; +} + +/*--------------------------------------------------------------------------*/ +const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) +{ + if(!cp) + { + return "GetExceptionString called with NULL process management structure"; + } + else if(cp->State == kwsysProcess_State_Exception) + { + return cp->ExitExceptionString; + } + return "No exception"; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_Execute(kwsysProcess* cp) +{ + int i; + + /* Child startup control data. */ + kwsysProcessCreateInformation si; + + /* Do not execute a second time. */ + if(!cp || cp->State == kwsysProcess_State_Executing) + { + return; + } + + /* Initialize the control structure for a new process. */ + if(!kwsysProcessInitialize(cp)) + { + strcpy(cp->ErrorMessage, "Out of memory"); + cp->State = kwsysProcess_State_Error; + return; + } + + /* Save the real working directory of this process and change to + the working directory for the child processes. This is needed + to make pipe file paths evaluate correctly. */ + if(cp->WorkingDirectory) + { + if(!GetCurrentDirectory(cp->RealWorkingDirectoryLength, + cp->RealWorkingDirectory)) + { + kwsysProcessCleanup(cp, 1); + return; + } + SetCurrentDirectory(cp->WorkingDirectory); + } + + /* Reset the Win9x resume and kill events. */ + if(cp->Win9x) + { + if(!ResetEvent(cp->Win9xResumeEvent)) + { + kwsysProcessCleanup(cp, 1); + return; + } + if(!ResetEvent(cp->Win9xKillEvent)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + + /* Initialize startup info data. */ + ZeroMemory(&si, sizeof(si)); + si.StartupInfo.cb = sizeof(si.StartupInfo); + + /* Decide whether a child window should be shown. */ + si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; + si.StartupInfo.wShowWindow = + (unsigned short)(cp->HideWindow?SW_HIDE:SW_SHOWDEFAULT); + + /* Connect the child's output pipes to the threads. */ + si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + + /* Create stderr pipe to be shared by all processes in the pipeline. + Neither end is directly inherited. */ + if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read, + &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) + { + kwsysProcessCleanup(cp, 1); + return; + } + + /* Create an inherited duplicate of the write end, but do not + close the non-inherited version. We need to keep it open + to use in waking up the pipe threads. */ + if(!DuplicateHandle(GetCurrentProcess(), cp->Pipe[KWSYSPE_PIPE_STDERR].Write, + GetCurrentProcess(), &si.StartupInfo.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS)) + { + kwsysProcessCleanup(cp, 1); + kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); + return; + } + + /* Replace the stderr pipe with a file if requested. In this case + the pipe thread will still run but never report data. */ + if(cp->PipeFileSTDERR) + { + if(!kwsysProcessSetupOutputPipeFile(&si.StartupInfo.hStdError, + cp->PipeFileSTDERR)) + { + kwsysProcessCleanup(cp, 1); + kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); + return; + } + } + + /* Replace the stderr pipe with the parent process's if requested. + In this case the pipe thread will still run but never report + data. */ + if(cp->PipeSharedSTDERR) + { + kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); + si.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); + } + + /* Create the pipeline of processes. */ + { + HANDLE readEnd = 0; + for(i=0; i < cp->NumberOfCommands; ++i) + { + if(kwsysProcessCreate(cp, i, &si, &readEnd)) + { + cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess; + } + else + { + kwsysProcessCleanup(cp, 1); + + /* Release resources that may have been allocated for this + process before an error occurred. */ + kwsysProcessCleanupHandle(&readEnd); + if(si.StartupInfo.hStdInput != GetStdHandle(STD_INPUT_HANDLE)) + { + kwsysProcessCleanupHandle(&si.StartupInfo.hStdInput); + } + if(si.StartupInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE)) + { + kwsysProcessCleanupHandle(&si.StartupInfo.hStdOutput); + } + if(si.StartupInfo.hStdError != GetStdHandle(STD_ERROR_HANDLE)) + { + kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); + } + kwsysProcessCleanupHandle(&si.ErrorPipeRead); + kwsysProcessCleanupHandle(&si.ErrorPipeWrite); + return; + } + } + + /* Save a handle to the output pipe for the last process. */ + cp->Pipe[KWSYSPE_PIPE_STDOUT].Read = readEnd; + } + + /* Close the inherited handles to the stderr pipe shared by all + processes in the pipeline. */ + if(si.StartupInfo.hStdError != GetStdHandle(STD_ERROR_HANDLE)) + { + kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); + } + + /* Restore the working directory. */ + if(cp->RealWorkingDirectory) + { + SetCurrentDirectory(cp->RealWorkingDirectory); + free(cp->RealWorkingDirectory); + cp->RealWorkingDirectory = 0; + } + + /* The timeout period starts now. */ + cp->StartTime = kwsysProcessTimeGetCurrent(); + cp->TimeoutTime = kwsysProcessTimeFromDouble(-1); + + /* All processes in the pipeline have been started in suspended + mode. Resume them all now. */ + if(cp->Win9x) + { + SetEvent(cp->Win9xResumeEvent); + } + else + { + for(i=0; i < cp->NumberOfCommands; ++i) + { + ResumeThread(cp->ProcessInformation[i].hThread); + } + } + + /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */ + /* Tell the pipe threads that a process has started. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + ReleaseSemaphore(cp->Pipe[i].Reader.Ready, 1, 0); + ReleaseSemaphore(cp->Pipe[i].Waker.Ready, 1, 0); + } + + /* We don't care about the children's main threads. */ + for(i=0; i < cp->NumberOfCommands; ++i) + { + kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); + } + + /* No pipe has reported data. */ + cp->CurrentIndex = KWSYSPE_PIPE_COUNT; + cp->PipesLeft = KWSYSPE_PIPE_COUNT; + + /* The process has now started. */ + cp->State = kwsysProcess_State_Executing; + cp->Detached = cp->OptionDetach; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_Disown(kwsysProcess* cp) +{ + int i; + + /* Make sure we are executing a detached process. */ + if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing || + cp->TimeoutExpired || cp->Killed || cp->Terminated) + { + return; + } + + /* Disable the reading threads. */ + kwsysProcessDisablePipeThreads(cp); + + /* Wait for all pipe threads to reset. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + WaitForSingleObject(cp->Pipe[i].Reader.Reset, INFINITE); + WaitForSingleObject(cp->Pipe[i].Waker.Reset, INFINITE); + } + + /* We will not wait for exit, so cleanup now. */ + kwsysProcessCleanup(cp, 0); + + /* The process has been disowned. */ + cp->State = kwsysProcess_State_Disowned; +} + +/*--------------------------------------------------------------------------*/ + +int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, + double* userTimeout) +{ + kwsysProcessTime userStartTime; + kwsysProcessTime timeoutLength; + kwsysProcessTime timeoutTime; + DWORD timeout; + int user; + int done = 0; + int expired = 0; + int pipeId = kwsysProcess_Pipe_None; + DWORD w; + + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed || + cp->TimeoutExpired) + { + return kwsysProcess_Pipe_None; + } + + /* Record the time at which user timeout period starts. */ + userStartTime = kwsysProcessTimeGetCurrent(); + + /* Calculate the time at which a timeout will expire, and whether it + is the user or process timeout. */ + user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime); + + /* Loop until we have a reason to return. */ + while(!done && cp->PipesLeft > 0) + { + /* If we previously got data from a thread, let it know we are + done with the data. */ + if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT) + { + ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); + cp->CurrentIndex = KWSYSPE_PIPE_COUNT; + } + + /* Setup a timeout if required. */ + if(kwsysProcessGetTimeoutLeft(&timeoutTime, user?userTimeout:0, + &timeoutLength)) + { + /* Timeout has already expired. */ + expired = 1; + break; + } + if(timeoutTime.QuadPart < 0) + { + timeout = INFINITE; + } + else + { + timeout = kwsysProcessTimeToDWORD(timeoutLength); + } + + /* Wait for a pipe's thread to signal or a process to terminate. */ + w = WaitForMultipleObjects(cp->ProcessEventsLength, cp->ProcessEvents, + 0, timeout); + if(w == WAIT_TIMEOUT) + { + /* Timeout has expired. */ + expired = 1; + done = 1; + } + else if(w == WAIT_OBJECT_0) + { + /* Save the index of the reporting thread and release the mutex. + The thread will block until we signal its Empty mutex. */ + cp->CurrentIndex = cp->SharedIndex; + ReleaseSemaphore(cp->SharedIndexMutex, 1, 0); + + /* Data are available or a pipe closed. */ + if(cp->Pipe[cp->CurrentIndex].Closed) + { + /* The pipe closed at the write end. Close the read end and + inform the wakeup thread it is done with this process. */ + kwsysProcessCleanupHandle(&cp->Pipe[cp->CurrentIndex].Read); + ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Waker.Go, 1, 0); + --cp->PipesLeft; + } + else if(data && length) + { + /* Report this data. */ + *data = cp->Pipe[cp->CurrentIndex].DataBuffer; + *length = cp->Pipe[cp->CurrentIndex].DataLength; + switch(cp->CurrentIndex) + { + case KWSYSPE_PIPE_STDOUT: + pipeId = kwsysProcess_Pipe_STDOUT; break; + case KWSYSPE_PIPE_STDERR: + pipeId = kwsysProcess_Pipe_STDERR; break; + } + done = 1; + } + } + else + { + /* A process has terminated. */ + kwsysProcessDestroy(cp, w-WAIT_OBJECT_0); + } + } + + /* Update the user timeout. */ + if(userTimeout) + { + kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent(); + kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime, + userStartTime); + double d = kwsysProcessTimeToDouble(difference); + *userTimeout -= d; + if(*userTimeout < 0) + { + *userTimeout = 0; + } + } + + /* Check what happened. */ + if(pipeId) + { + /* Data are ready on a pipe. */ + return pipeId; + } + else if(expired) + { + /* A timeout has expired. */ + if(user) + { + /* The user timeout has expired. It has no time left. */ + return kwsysProcess_Pipe_Timeout; + } + else + { + /* The process timeout has expired. Kill the child now. */ + kwsysProcess_Kill(cp); + cp->TimeoutExpired = 1; + cp->Killed = 0; + return kwsysProcess_Pipe_None; + } + } + else + { + /* The children have terminated and no more data are available. */ + return kwsysProcess_Pipe_None; + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) +{ + int i; + int pipe; + + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing) + { + return 1; + } + + /* Wait for the process to terminate. Ignore all data. */ + while((pipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) + { + if(pipe == kwsysProcess_Pipe_Timeout) + { + /* The user timeout has expired. */ + return 0; + } + } + + /* When the last pipe closes in WaitForData, the loop terminates + without releasing the pipe's thread. Release it now. */ + if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT) + { + ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); + cp->CurrentIndex = KWSYSPE_PIPE_COUNT; + } + + /* Wait for all pipe threads to reset. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + WaitForSingleObject(cp->Pipe[i].Reader.Reset, INFINITE); + WaitForSingleObject(cp->Pipe[i].Waker.Reset, INFINITE); + } + + /* ---- It is now safe again to call kwsysProcessCleanup. ----- */ + /* Close all the pipes. */ + kwsysProcessCleanup(cp, 0); + + /* Determine the outcome. */ + if(cp->Killed) + { + /* We killed the child. */ + cp->State = kwsysProcess_State_Killed; + } + else if(cp->TimeoutExpired) + { + /* The timeout expired. */ + cp->State = kwsysProcess_State_Expired; + } + else + { + /* The children exited. Report the outcome of the last process. */ + cp->ExitCode = cp->CommandExitCodes[cp->NumberOfCommands-1]; + if((cp->ExitCode & 0xF0000000) == 0xC0000000) + { + /* Child terminated due to exceptional behavior. */ + cp->State = kwsysProcess_State_Exception; + cp->ExitValue = 1; + kwsysProcessSetExitException(cp, cp->ExitCode); + } + else + { + /* Child exited without exception. */ + cp->State = kwsysProcess_State_Exited; + cp->ExitException = kwsysProcess_Exception_None; + cp->ExitValue = cp->ExitCode; + } + } + + return 1; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcess_Kill(kwsysProcess* cp) +{ + int i; + + /* Make sure we are executing a process. */ + if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || + cp->Killed || cp->Terminated) + { + return; + } + + /* Disable the reading threads. */ + kwsysProcessDisablePipeThreads(cp); + + /* Kill the children. */ + cp->Killed = 1; + if(cp->Win9x) + { + /* Windows 9x. Tell the forwarding executable to kill the child. */ + SetEvent(cp->Win9xKillEvent); + } + else + { + /* Not Windows 9x. Just terminate the children. */ + for(i=0; i < cp->NumberOfCommands; ++i) + { + kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); + } + } + + /* We are killing the children and ignoring all data. Do not wait + for them to exit. */ +} + +/*--------------------------------------------------------------------------*/ + +/* + Function executed for each pipe's thread. Argument is a pointer to + the kwsysProcessPipeData instance for this thread. +*/ +DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd) +{ + kwsysProcessPipeData* td = (kwsysProcessPipeData*)ptd; + kwsysProcess* cp = td->Process; + + /* Wait for a process to be ready. */ + while((WaitForSingleObject(td->Reader.Ready, INFINITE), !cp->Deleting)) + { + /* Read output from the process for this thread's pipe. */ + kwsysProcessPipeThreadReadPipe(cp, td); + + /* Signal the main thread we have reset for a new process. */ + ReleaseSemaphore(td->Reader.Reset, 1, 0); + } + return 0; +} + +/*--------------------------------------------------------------------------*/ + +/* + Function called in each pipe's thread to handle data for one + execution of a subprocess. +*/ +void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td) +{ + /* Wait for space in the thread's buffer. */ + while((WaitForSingleObject(td->Reader.Go, INFINITE), !td->Closed)) + { + /* Read data from the pipe. This may block until data are available. */ + if(!ReadFile(td->Read, td->DataBuffer, KWSYSPE_PIPE_BUFFER_SIZE, + &td->DataLength, 0)) + { + if(GetLastError() != ERROR_BROKEN_PIPE) + { + /* UNEXPECTED failure to read the pipe. */ + } + + /* The pipe closed. There are no more data to read. */ + td->Closed = 1; + } + + /* Wait for our turn to be handled by the main thread. */ + WaitForSingleObject(cp->SharedIndexMutex, INFINITE); + + /* Tell the main thread we have something to report. */ + cp->SharedIndex = td->Index; + ReleaseSemaphore(cp->Full, 1, 0); + } + + /* We were signalled to exit with our buffer empty. Reset the + mutex for a new process. */ + ReleaseSemaphore(td->Reader.Go, 1, 0); +} + +/*--------------------------------------------------------------------------*/ + +/* + Function executed for each pipe's thread. Argument is a pointer to + the kwsysProcessPipeData instance for this thread. +*/ +DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd) +{ + kwsysProcessPipeData* td = (kwsysProcessPipeData*)ptd; + kwsysProcess* cp = td->Process; + + /* Wait for a process to be ready. */ + while((WaitForSingleObject(td->Waker.Ready, INFINITE), !cp->Deleting)) + { + /* Wait for a possible wakeup. */ + kwsysProcessPipeThreadWakePipe(cp, td); + + /* Signal the main thread we have reset for a new process. */ + ReleaseSemaphore(td->Waker.Reset, 1, 0); + } + return 0; +} + +/*--------------------------------------------------------------------------*/ + +/* + Function called in each pipe's thread to handle reading thread + wakeup for one execution of a subprocess. +*/ +void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td) +{ + (void)cp; + + /* Wait for a possible wake command. */ + WaitForSingleObject(td->Waker.Go, INFINITE); + + /* If the pipe is not closed, we need to wake up the reading thread. */ + if(!td->Closed) + { + DWORD dummy; + WriteFile(td->Write, "", 1, &dummy, 0); + } +} + +/*--------------------------------------------------------------------------*/ +/* Initialize a process control structure for kwsysProcess_Execute. */ +int kwsysProcessInitialize(kwsysProcess* cp) +{ + /* Reset internal status flags. */ + cp->TimeoutExpired = 0; + cp->Terminated = 0; + cp->Killed = 0; + cp->ExitException = kwsysProcess_Exception_None; + cp->ExitCode = 1; + cp->ExitValue = 1; + + /* Reset error data. */ + cp->ErrorMessage[0] = 0; + strcpy(cp->ExitExceptionString, "No exception"); + + /* Allocate process information for each process. */ + cp->ProcessInformation = + (PROCESS_INFORMATION*)malloc(sizeof(PROCESS_INFORMATION) * + cp->NumberOfCommands); + if(!cp->ProcessInformation) + { + return 0; + } + ZeroMemory(cp->ProcessInformation, + sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands); + if(cp->CommandExitCodes) + { + free(cp->CommandExitCodes); + } + cp->CommandExitCodes = (DWORD*)malloc(sizeof(DWORD)*cp->NumberOfCommands); + if(!cp->CommandExitCodes) + { + return 0; + } + ZeroMemory(cp->CommandExitCodes, sizeof(DWORD)*cp->NumberOfCommands); + + /* Allocate event wait array. The first event is cp->Full, the rest + are the process termination events. */ + cp->ProcessEvents = (PHANDLE)malloc(sizeof(HANDLE)*(cp->NumberOfCommands+1)); + if(!cp->ProcessEvents) + { + return 0; + } + ZeroMemory(cp->ProcessEvents, sizeof(HANDLE) * (cp->NumberOfCommands+1)); + cp->ProcessEvents[0] = cp->Full; + cp->ProcessEventsLength = cp->NumberOfCommands+1; + + /* Allocate space to save the real working directory of this process. */ + if(cp->WorkingDirectory) + { + cp->RealWorkingDirectoryLength = GetCurrentDirectory(0, 0); + if(cp->RealWorkingDirectoryLength > 0) + { + cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength); + if(!cp->RealWorkingDirectory) + { + return 0; + } + } + } + + return 1; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcessCreate(kwsysProcess* cp, int index, + kwsysProcessCreateInformation* si, + PHANDLE readEnd) +{ + /* Setup the process's stdin. */ + if(*readEnd) + { + /* Create an inherited duplicate of the read end from the output + pipe of the previous process. This also closes the + non-inherited version. */ + if(!DuplicateHandle(GetCurrentProcess(), *readEnd, + GetCurrentProcess(), readEnd, + 0, TRUE, (DUPLICATE_CLOSE_SOURCE | + DUPLICATE_SAME_ACCESS))) + { + return 0; + } + si->StartupInfo.hStdInput = *readEnd; + + /* This function is done with this handle. */ + *readEnd = 0; + } + else if(cp->PipeFileSTDIN) + { + /* Create a handle to read a file for stdin. */ + HANDLE fin = CreateFile(cp->PipeFileSTDIN, GENERIC_READ, + FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if(fin == INVALID_HANDLE_VALUE) + { + return 0; + } + /* Create an inherited duplicate of the handle. This also closes + the non-inherited version. */ + if(!DuplicateHandle(GetCurrentProcess(), fin, + GetCurrentProcess(), &fin, + 0, TRUE, (DUPLICATE_CLOSE_SOURCE | + DUPLICATE_SAME_ACCESS))) + { + return 0; + } + si->StartupInfo.hStdInput = fin; + } + else if(cp->PipeSharedSTDIN) + { + si->StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + } + else + { + si->StartupInfo.hStdInput = INVALID_HANDLE_VALUE; + } + + /* Setup the process's stdout. */ + { + DWORD maybeClose = DUPLICATE_CLOSE_SOURCE; + HANDLE writeEnd; + + /* Create the output pipe for this process. Neither end is directly + inherited. */ + if(!CreatePipe(readEnd, &writeEnd, 0, 0)) + { + return 0; + } + + /* Create an inherited duplicate of the write end. Close the + non-inherited version unless this is the last process. Save the + non-inherited write end of the last process. */ + if(index == cp->NumberOfCommands-1) + { + cp->Pipe[KWSYSPE_PIPE_STDOUT].Write = writeEnd; + maybeClose = 0; + } + if(!DuplicateHandle(GetCurrentProcess(), writeEnd, + GetCurrentProcess(), &writeEnd, + 0, TRUE, (maybeClose | DUPLICATE_SAME_ACCESS))) + { + return 0; + } + si->StartupInfo.hStdOutput = writeEnd; + } + + /* Replace the stdout pipe with a file if requested. In this case + the pipe thread will still run but never report data. */ + if(index == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT) + { + if(!kwsysProcessSetupOutputPipeFile(&si->StartupInfo.hStdOutput, + cp->PipeFileSTDOUT)) + { + return 0; + } + } + + /* Replace the stdout pipe with the parent process's if requested. + In this case the pipe thread will still run but never report + data. */ + if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT) + { + kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput); + si->StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + } + + /* Create the child process. */ + { + BOOL r; + char* realCommand; + if(cp->Win9x) + { + /* Create an error reporting pipe for the forwarding executable. + Neither end is directly inherited. */ + if(!CreatePipe(&si->ErrorPipeRead, &si->ErrorPipeWrite, 0, 0)) + { + return 0; + } + + /* Create an inherited duplicate of the write end. This also closes + the non-inherited version. */ + if(!DuplicateHandle(GetCurrentProcess(), si->ErrorPipeWrite, + GetCurrentProcess(), &si->ErrorPipeWrite, + 0, TRUE, (DUPLICATE_CLOSE_SOURCE | + DUPLICATE_SAME_ACCESS))) + { + return 0; + } + + /* The forwarding executable is given a handle to the error pipe + and resume and kill events. */ + realCommand = malloc(strlen(cp->Win9x)+strlen(cp->Commands[index])+100); + if(!realCommand) + { + return 0; + } + sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x, + si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent, + cp->HideWindow, cp->Commands[index]); + } + else + { + realCommand = cp->Commands[index]; + } + + /* Create the child in a suspended state so we can wait until all + children have been created before running any one. */ + r = CreateProcess(0, realCommand, 0, 0, TRUE, + cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0, + &si->StartupInfo, &cp->ProcessInformation[index]); + + if(cp->Win9x) + { + /* Free memory. */ + free(realCommand); + + /* Close the error pipe write end so we can detect when the + forwarding executable closes it. */ + kwsysProcessCleanupHandle(&si->ErrorPipeWrite); + if(r) + { + /* Wait for the forwarding executable to report an error or + close the error pipe to report success. */ + DWORD total = 0; + DWORD n = 1; + while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0) + { + if(ReadFile(si->ErrorPipeRead, cp->ErrorMessage+total, + KWSYSPE_PIPE_BUFFER_SIZE-total, &n, 0)) + { + total += n; + } + else + { + n = 0; + } + } + if(total > 0 || GetLastError() != ERROR_BROKEN_PIPE) + { + /* The forwarding executable could not run the process, or + there was an error reading from its error pipe. Preserve + the last error while cleaning up the forwarding executable + so the cleanup our caller does reports the proper error. */ + DWORD error = GetLastError(); + kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread); + kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); + SetLastError(error); + return 0; + } + } + kwsysProcessCleanupHandle(&si->ErrorPipeRead); + } + + if(!r) + { + return 0; + } + } + + /* Successfully created this child process. */ + if(index > 0) + { + /* Close our handle to the input pipe for the current process. */ + kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput); + } + + if(si->StartupInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE)) + { + /* The parent process does not need the inhertied pipe write end. */ + kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput); + } + + return 1; +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcessDestroy(kwsysProcess* cp, int event) +{ + int i; + int index; + + /* Find the process index for the termination event. */ + for(index=0; index < cp->NumberOfCommands; ++index) + { + if(cp->ProcessInformation[index].hProcess == cp->ProcessEvents[event]) + { + break; + } + } + + /* Check the exit code of the process. */ + GetExitCodeProcess(cp->ProcessInformation[index].hProcess, + &cp->CommandExitCodes[index]); + + /* Close the process handle for the terminated process. */ + kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); + + /* Remove the process from the available events. */ + cp->ProcessEventsLength -= 1; + for(i=event; i < cp->ProcessEventsLength; ++i) + { + cp->ProcessEvents[i] = cp->ProcessEvents[i+1]; + } + + /* Check if all processes have terminated. */ + if(cp->ProcessEventsLength == 1) + { + cp->Terminated = 1; + + /* Close our copies of the pipe write handles so the pipe threads + can detect end-of-data. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + kwsysProcessCleanupHandle(&cp->Pipe[i].Write); + } + } +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) +{ + HANDLE fout; + if(!name) + { + return 1; + } + + /* Close the existing inherited handle. */ + kwsysProcessCleanupHandle(phandle); + + /* Create a handle to write a file for the pipe. */ + fout = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, 0, + CREATE_ALWAYS, 0, 0); + if(fout == INVALID_HANDLE_VALUE) + { + return 0; + } + + /* Create an inherited duplicate of the handle. This also closes + the non-inherited version. */ + if(!DuplicateHandle(GetCurrentProcess(), fout, + GetCurrentProcess(), &fout, + 0, TRUE, (DUPLICATE_CLOSE_SOURCE | + DUPLICATE_SAME_ACCESS))) + { + return 0; + } + + /* Assign the replacement handle. */ + *phandle = fout; + return 1; +} + +/*--------------------------------------------------------------------------*/ + +/* Close the given handle if it is open. Reset its value to 0. */ +void kwsysProcessCleanupHandle(PHANDLE h) +{ + if(h && *h) + { + CloseHandle(*h); + *h = 0; + } +} + +/*--------------------------------------------------------------------------*/ + +/* Close all handles created by kwsysProcess_Execute. */ +void kwsysProcessCleanup(kwsysProcess* cp, int error) +{ + int i; + + /* If this is an error case, report the error. */ + if(error) + { + /* Construct an error message if one has not been provided already. */ + if(cp->ErrorMessage[0] == 0) + { + /* Format the error message. */ + DWORD original = GetLastError(); + DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, 0, original, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, 0); + if(length < 1) + { + /* FormatMessage failed. Use a default message. */ + _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, + "Process execution failed with error 0x%X. " + "FormatMessage failed with error 0x%X", + original, GetLastError()); + } + } + + /* Remove trailing period and newline, if any. */ + kwsysProcessCleanErrorMessage(cp); + + /* Set the error state. */ + cp->State = kwsysProcess_State_Error; + + /* Cleanup any processes already started in a suspended state. */ + if(cp->ProcessInformation) + { + if(cp->Win9x) + { + SetEvent(cp->Win9xKillEvent); + } + else + { + for(i=0; i < cp->NumberOfCommands; ++i) + { + if(cp->ProcessInformation[i].hProcess) + { + TerminateProcess(cp->ProcessInformation[i].hProcess, 255); + WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE); + } + } + } + for(i=0; i < cp->NumberOfCommands; ++i) + { + kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); + kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); + } + } + + /* Restore the working directory. */ + if(cp->RealWorkingDirectory) + { + SetCurrentDirectory(cp->RealWorkingDirectory); + } + } + + /* Free memory. */ + if(cp->ProcessInformation) + { + free(cp->ProcessInformation); + cp->ProcessInformation = 0; + } + if(cp->ProcessEvents) + { + free(cp->ProcessEvents); + cp->ProcessEvents = 0; + } + if(cp->RealWorkingDirectory) + { + free(cp->RealWorkingDirectory); + cp->RealWorkingDirectory = 0; + } + + /* Close each pipe. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + kwsysProcessCleanupHandle(&cp->Pipe[i].Write); + kwsysProcessCleanupHandle(&cp->Pipe[i].Read); + cp->Pipe[i].Closed = 0; + } +} + +/*--------------------------------------------------------------------------*/ +void kwsysProcessCleanErrorMessage(kwsysProcess* cp) +{ + /* Remove trailing period and newline, if any. */ + int length = strlen(cp->ErrorMessage); + if(cp->ErrorMessage[length-1] == '\n') + { + cp->ErrorMessage[length-1] = 0; + --length; + if(length > 0 && cp->ErrorMessage[length-1] == '\r') + { + cp->ErrorMessage[length-1] = 0; + --length; + } + } + if(length > 0 && cp->ErrorMessage[length-1] == '.') + { + cp->ErrorMessage[length-1] = 0; + } +} + +/*--------------------------------------------------------------------------*/ +/* Get the time at which either the process or user timeout will + expire. Returns 1 if the user timeout is first, and 0 otherwise. */ +int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, + kwsysProcessTime* timeoutTime) +{ + /* The first time this is called, we need to calculate the time at + which the child will timeout. */ + if(cp->Timeout && cp->TimeoutTime.QuadPart < 0) + { + kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout); + cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length); + } + + /* Start with process timeout. */ + *timeoutTime = cp->TimeoutTime; + + /* Check if the user timeout is earlier. */ + if(userTimeout) + { + kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); + kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout); + kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime, + userTimeoutLength); + if(timeoutTime->QuadPart < 0 || + kwsysProcessTimeLess(userTimeoutTime, *timeoutTime)) + { + *timeoutTime = userTimeoutTime; + return 1; + } + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +/* Get the length of time before the given timeout time arrives. + Returns 1 if the time has already arrived, and 0 otherwise. */ +int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, + double* userTimeout, + kwsysProcessTime* timeoutLength) +{ + if(timeoutTime->QuadPart < 0) + { + /* No timeout time has been requested. */ + return 0; + } + else + { + /* Calculate the remaining time. */ + kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); + *timeoutLength = kwsysProcessTimeSubtract(*timeoutTime, currentTime); + + if(timeoutLength->QuadPart < 0 && userTimeout && *userTimeout <= 0) + { + /* Caller has explicitly requested a zero timeout. */ + timeoutLength->QuadPart = 0; + } + + if(timeoutLength->QuadPart < 0) + { + /* Timeout has already expired. */ + return 1; + } + else + { + /* There is some time left. */ + return 0; + } + } +} + +/*--------------------------------------------------------------------------*/ +kwsysProcessTime kwsysProcessTimeGetCurrent() +{ + kwsysProcessTime current; + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + current.LowPart = ft.dwLowDateTime; + current.HighPart = ft.dwHighDateTime; + return current; +} + +/*--------------------------------------------------------------------------*/ +DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t) +{ + return (DWORD)(t.QuadPart * 0.0001); +} + +/*--------------------------------------------------------------------------*/ +double kwsysProcessTimeToDouble(kwsysProcessTime t) +{ + return t.QuadPart * 0.0000001; +} + +/*--------------------------------------------------------------------------*/ +kwsysProcessTime kwsysProcessTimeFromDouble(double d) +{ + kwsysProcessTime t; + t.QuadPart = (LONGLONG)(d*10000000); + return t; +} + +/*--------------------------------------------------------------------------*/ +int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2) +{ + return in1.QuadPart < in2.QuadPart; +} + +/*--------------------------------------------------------------------------*/ +kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2) +{ + kwsysProcessTime out; + out.QuadPart = in1.QuadPart + in2.QuadPart; + return out; +} + +/*--------------------------------------------------------------------------*/ +kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2) +{ + kwsysProcessTime out; + out.QuadPart = in1.QuadPart - in2.QuadPart; + return out; +} + +/*--------------------------------------------------------------------------*/ +#define KWSYSPE_CASE(type, str) \ + cp->ExitException = kwsysProcess_Exception_##type; \ + strcpy(cp->ExitExceptionString, str) +static void kwsysProcessSetExitException(kwsysProcess* cp, int code) +{ + switch (code) + { + case STATUS_CONTROL_C_EXIT: + KWSYSPE_CASE(Interrupt, "User interrupt"); break; + + case STATUS_FLOAT_DENORMAL_OPERAND: + KWSYSPE_CASE(Numerical, "Floating-point exception (denormal operand)"); break; + case STATUS_FLOAT_DIVIDE_BY_ZERO: + KWSYSPE_CASE(Numerical, "Divide-by-zero"); break; + case STATUS_FLOAT_INEXACT_RESULT: + KWSYSPE_CASE(Numerical, "Floating-point exception (inexact result)"); break; + case STATUS_FLOAT_INVALID_OPERATION: + KWSYSPE_CASE(Numerical, "Invalid floating-point operation"); break; + case STATUS_FLOAT_OVERFLOW: + KWSYSPE_CASE(Numerical, "Floating-point overflow"); break; + case STATUS_FLOAT_STACK_CHECK: + KWSYSPE_CASE(Numerical, "Floating-point stack check failed"); break; + case STATUS_FLOAT_UNDERFLOW: + KWSYSPE_CASE(Numerical, "Floating-point underflow"); break; +#ifdef STATUS_FLOAT_MULTIPLE_FAULTS + case STATUS_FLOAT_MULTIPLE_FAULTS: + KWSYSPE_CASE(Numerical, "Floating-point exception (multiple faults)"); break; +#endif +#ifdef STATUS_FLOAT_MULTIPLE_TRAPS + case STATUS_FLOAT_MULTIPLE_TRAPS: + KWSYSPE_CASE(Numerical, "Floating-point exception (multiple traps)"); break; +#endif + case STATUS_INTEGER_DIVIDE_BY_ZERO: + KWSYSPE_CASE(Numerical, "Integer divide-by-zero"); break; + case STATUS_INTEGER_OVERFLOW: + KWSYSPE_CASE(Numerical, "Integer overflow"); break; + + case STATUS_DATATYPE_MISALIGNMENT: + KWSYSPE_CASE(Fault, "Datatype misalignment"); break; + case STATUS_ACCESS_VIOLATION: + KWSYSPE_CASE(Fault, "Access violation"); break; + case STATUS_IN_PAGE_ERROR: + KWSYSPE_CASE(Fault, "In-page error"); break; + case STATUS_INVALID_HANDLE: + KWSYSPE_CASE(Fault, "Invalid hanlde"); break; + case STATUS_NONCONTINUABLE_EXCEPTION: + KWSYSPE_CASE(Fault, "Noncontinuable exception"); break; + case STATUS_INVALID_DISPOSITION: + KWSYSPE_CASE(Fault, "Invalid disposition"); break; + case STATUS_ARRAY_BOUNDS_EXCEEDED: + KWSYSPE_CASE(Fault, "Array bounds exceeded"); break; + case STATUS_STACK_OVERFLOW: + KWSYSPE_CASE(Fault, "Stack overflow"); break; + + case STATUS_ILLEGAL_INSTRUCTION: + KWSYSPE_CASE(Illegal, "Illegal instruction"); break; + case STATUS_PRIVILEGED_INSTRUCTION: + KWSYSPE_CASE(Illegal, "Privileged instruction"); break; + + case STATUS_NO_MEMORY: + default: + cp->ExitException = kwsysProcess_Exception_Other; + sprintf(cp->ExitExceptionString, "Exit code 0x%x\n", code); + break; + } +} +#undef KWSYSPE_CASE + +typedef struct kwsysProcess_List_s kwsysProcess_List; +static kwsysProcess_List* kwsysProcess_List_New(); +static void kwsysProcess_List_Delete(kwsysProcess_List* self); +static int kwsysProcess_List_Update(kwsysProcess_List* self); +static int kwsysProcess_List_NextProcess(kwsysProcess_List* self); +static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self); +static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self); + +/*--------------------------------------------------------------------------*/ +/* Windows NT 4 API definitions. */ +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +typedef LONG NTSTATUS; +typedef LONG KPRIORITY; +typedef struct _UNICODE_STRING UNICODE_STRING; +struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +}; + +/* The process information structure. Declare only enough to get + process identifiers. The rest may be ignored because we use the + NextEntryDelta to move through an array of instances. */ +typedef struct _SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION; +typedef SYSTEM_PROCESS_INFORMATION* PSYSTEM_PROCESS_INFORMATION; +struct _SYSTEM_PROCESS_INFORMATION +{ + ULONG NextEntryDelta; + ULONG ThreadCount; + ULONG Reserved1[6]; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ProcessName; + KPRIORITY BasePriority; + ULONG ProcessId; + ULONG InheritedFromProcessId; +}; + +/*--------------------------------------------------------------------------*/ +/* Toolhelp32 API definitions. */ +#define TH32CS_SNAPPROCESS 0x00000002 +typedef struct tagPROCESSENTRY32 PROCESSENTRY32; +typedef PROCESSENTRY32* LPPROCESSENTRY32; +struct tagPROCESSENTRY32 +{ + DWORD dwSize; + DWORD cntUsage; + DWORD th32ProcessID; + DWORD th32DefaultHeapID; + DWORD th32ModuleID; + DWORD cntThreads; + DWORD th32ParentProcessID; + LONG pcPriClassBase; + DWORD dwFlags; + char szExeFile[MAX_PATH]; +}; + +/*--------------------------------------------------------------------------*/ +/* Windows API function types. */ +typedef HANDLE (WINAPI* CreateToolhelp32SnapshotType)(DWORD, DWORD); +typedef BOOL (WINAPI* Process32FirstType)(HANDLE, LPPROCESSENTRY32); +typedef BOOL (WINAPI* Process32NextType)(HANDLE, LPPROCESSENTRY32); +typedef NTSTATUS (WINAPI* ZwQuerySystemInformationType)(ULONG, PVOID, + ULONG, PULONG); + + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__New_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self); +static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self); +static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self); +static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self); +static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self); + +struct kwsysProcess_List_s +{ + /* Implementation switches at runtime based on version of Windows. */ + int NT4; + + /* Implementation functions and data for NT 4. */ + ZwQuerySystemInformationType P_ZwQuerySystemInformation; + char* Buffer; + int BufferSize; + PSYSTEM_PROCESS_INFORMATION CurrentInfo; + + /* Implementation functions and data for other Windows versions. */ + CreateToolhelp32SnapshotType P_CreateToolhelp32Snapshot; + Process32FirstType P_Process32First; + Process32NextType P_Process32Next; + HANDLE Snapshot; + PROCESSENTRY32 CurrentEntry; +}; + +/*--------------------------------------------------------------------------*/ +static kwsysProcess_List* kwsysProcess_List_New() +{ + OSVERSIONINFO osv; + kwsysProcess_List* self; + + /* Allocate and initialize the list object. */ + if(!(self = (kwsysProcess_List*)malloc(sizeof(kwsysProcess_List)))) + { + return 0; + } + memset(self, 0, sizeof(*self)); + + /* Select an implementation. */ + ZeroMemory(&osv, sizeof(osv)); + osv.dwOSVersionInfoSize = sizeof(osv); + GetVersionEx(&osv); + self->NT4 = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT && + osv.dwMajorVersion < 5)? 1:0; + + /* Initialize the selected implementation. */ + if(!(self->NT4? + kwsysProcess_List__New_NT4(self) : + kwsysProcess_List__New_Snapshot(self))) + { + kwsysProcess_List_Delete(self); + return 0; + } + + /* Update to the current set of processes. */ + if(!kwsysProcess_List_Update(self)) + { + kwsysProcess_List_Delete(self); + return 0; + } + return self; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcess_List_Delete(kwsysProcess_List* self) +{ + if(self) + { + if(self->NT4) + { + kwsysProcess_List__Delete_NT4(self); + } + else + { + kwsysProcess_List__Delete_Snapshot(self); + } + free(self); + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_Update(kwsysProcess_List* self) +{ + return self? (self->NT4? + kwsysProcess_List__Update_NT4(self) : + kwsysProcess_List__Update_Snapshot(self)) : 0; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self) +{ + return self? (self->NT4? + kwsysProcess_List__GetProcessId_NT4(self) : + kwsysProcess_List__GetProcessId_Snapshot(self)) : -1; + +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self) +{ + return self? (self->NT4? + kwsysProcess_List__GetParentId_NT4(self) : + kwsysProcess_List__GetParentId_Snapshot(self)) : -1; + +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List_NextProcess(kwsysProcess_List* self) +{ + return (self? (self->NT4? + kwsysProcess_List__Next_NT4(self) : + kwsysProcess_List__Next_Snapshot(self)) : 0); +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__New_NT4(kwsysProcess_List* self) +{ + HANDLE hNT = GetModuleHandle("ntdll.dll"); + if(hNT) + { + /* Get pointers to the needed API functions. */ + self->P_ZwQuerySystemInformation = + ((ZwQuerySystemInformationType) + GetProcAddress(hNT, "ZwQuerySystemInformation")); + CloseHandle(hNT); + } + if(!self->P_ZwQuerySystemInformation) + { + return 0; + } + + /* Allocate an initial process information buffer. */ + self->BufferSize = 32768; + self->Buffer = (char*)malloc(self->BufferSize); + return self->Buffer? 1:0; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self) +{ + /* Free the process information buffer. */ + if(self->Buffer) + { + free(self->Buffer); + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self) +{ + self->CurrentInfo = 0; + for(;;) + { + /* Query number 5 is for system process list. */ + NTSTATUS status = + self->P_ZwQuerySystemInformation(5, self->Buffer, self->BufferSize, 0); + if(status == STATUS_INFO_LENGTH_MISMATCH) + { + /* The query requires a bigger buffer. */ + int newBufferSize = self->BufferSize * 2; + char* newBuffer = (char*)malloc(newBufferSize); + if(newBuffer) + { + free(self->Buffer); + self->Buffer = newBuffer; + self->BufferSize = newBufferSize; + } + else + { + return 0; + } + } + else if(status >= 0) + { + /* The query succeeded. Initialize traversal of the process list. */ + self->CurrentInfo = (PSYSTEM_PROCESS_INFORMATION)self->Buffer; + return 1; + } + else + { + /* The query failed. */ + return 0; + } + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self) +{ + if(self->CurrentInfo) + { + if(self->CurrentInfo->NextEntryDelta > 0) + { + self->CurrentInfo = ((PSYSTEM_PROCESS_INFORMATION) + ((char*)self->CurrentInfo + + self->CurrentInfo->NextEntryDelta)); + return 1; + } + self->CurrentInfo = 0; + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self) +{ + return self->CurrentInfo? self->CurrentInfo->ProcessId : -1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self) +{ + return self->CurrentInfo? self->CurrentInfo->InheritedFromProcessId : -1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self) +{ + HANDLE hKernel = GetModuleHandle("kernel32.dll"); + if(hKernel) + { + self->P_CreateToolhelp32Snapshot = + ((CreateToolhelp32SnapshotType) + GetProcAddress(hKernel, "CreateToolhelp32Snapshot")); + self->P_Process32First = + ((Process32FirstType) + GetProcAddress(hKernel, "Process32First")); + self->P_Process32Next = + ((Process32NextType) + GetProcAddress(hKernel, "Process32Next")); + CloseHandle(hKernel); + } + return (self->P_CreateToolhelp32Snapshot && + self->P_Process32First && + self->P_Process32Next)? 1:0; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self) +{ + if(self->Snapshot) + { + CloseHandle(self->Snapshot); + } +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self) +{ + if(self->Snapshot) + { + CloseHandle(self->Snapshot); + } + if(!(self->Snapshot = + self->P_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))) + { + return 0; + } + ZeroMemory(&self->CurrentEntry, sizeof(self->CurrentEntry)); + self->CurrentEntry.dwSize = sizeof(self->CurrentEntry); + if(!self->P_Process32First(self->Snapshot, &self->CurrentEntry)) + { + CloseHandle(self->Snapshot); + self->Snapshot = 0; + return 0; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self) +{ + if(self->Snapshot) + { + if(self->P_Process32Next(self->Snapshot, &self->CurrentEntry)) + { + return 1; + } + CloseHandle(self->Snapshot); + self->Snapshot = 0; + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self) +{ + return self->Snapshot? self->CurrentEntry.th32ProcessID : -1; +} + +/*--------------------------------------------------------------------------*/ +static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self) +{ + return self->Snapshot? self->CurrentEntry.th32ParentProcessID : -1; +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcessKill(DWORD pid) +{ + HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid); + if(h) + { + TerminateProcess(h, 255); + WaitForSingleObject(h, INFINITE); + } +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcessKillTree(int pid) +{ + kwsysProcess_List* plist = kwsysProcess_List_New(); + kwsysProcessKill(pid); + if(plist) + { + do + { + if(kwsysProcess_List_GetCurrentParentId(plist) == pid) + { + int ppid = kwsysProcess_List_GetCurrentProcessId(plist); + kwsysProcessKillTree(ppid); + } + } while(kwsysProcess_List_NextProcess(plist)); + kwsysProcess_List_Delete(plist); + } +} + +/*--------------------------------------------------------------------------*/ +static void kwsysProcessDisablePipeThreads(kwsysProcess* cp) +{ + int i; + + /* If data were just reported data, release the pipe's thread. */ + if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT) + { + ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); + cp->CurrentIndex = KWSYSPE_PIPE_COUNT; + } + + /* Wakeup all reading threads that are not on closed pipes. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + /* The wakeup threads will write one byte to the pipe write ends. + If there are no data in the pipe then this is enough to wakeup + the reading threads. If there are already data in the pipe + this may block. We cannot use PeekNamedPipe to check whether + there are data because an outside process might still be + writing data if we are disowning it. Also, PeekNamedPipe will + block if checking a pipe on which the reading thread is + currently calling ReadPipe. Therefore we need a separate + thread to call WriteFile. If it blocks, that is okay because + it will unblock when we close the read end and break the pipe + below. */ + if(cp->Pipe[i].Read) + { + ReleaseSemaphore(cp->Pipe[i].Waker.Go, 1, 0); + } + } + + /* Tell pipe threads to reset until we run another process. */ + while(cp->PipesLeft > 0) + { + /* The waking threads will cause all reading threads to report. + Wait for the next one and save its index. */ + WaitForSingleObject(cp->Full, INFINITE); + cp->CurrentIndex = cp->SharedIndex; + ReleaseSemaphore(cp->SharedIndexMutex, 1, 0); + + /* We are done reading this pipe. Close its read handle. */ + cp->Pipe[cp->CurrentIndex].Closed = 1; + kwsysProcessCleanupHandle(&cp->Pipe[cp->CurrentIndex].Read); + --cp->PipesLeft; + + /* Tell the reading thread we are done with the data. It will + reset immediately because the pipe is closed. */ + ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); + } +} diff --git a/Utilities/kwsys/README.txt b/Utilities/kwsys/README.txt new file mode 100644 index 0000000..4f439d1 --- /dev/null +++ b/Utilities/kwsys/README.txt @@ -0,0 +1,7 @@ +KWSys provides a platform-independent API to many common system +features that are implemented differently on every platform. This +library is intended to be shared among many projects. + +You are probably reading this file in the source tree of a surrounding +project. In that case, see "../README.kwsys" for details of using +KWSys in your project. diff --git a/Utilities/kwsys/RegularExpression.cxx b/Utilities/kwsys/RegularExpression.cxx new file mode 100644 index 0000000..7d988e5 --- /dev/null +++ b/Utilities/kwsys/RegularExpression.cxx @@ -0,0 +1,1217 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: RegularExpression.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +// +// 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 +// + +#include "kwsysPrivate.h" +#include KWSYS_HEADER(RegularExpression.hxx) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "RegularExpression.hxx.in" +#endif + +#include +#include + +namespace KWSYS_NAMESPACE +{ + +// RegularExpression -- Copies the given regular expression. +RegularExpression::RegularExpression (const RegularExpression& rxp) { + if ( !rxp.program ) + { + this->program = 0; + return; + } + 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 != 0) { + 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 RegularExpression::operator== (const RegularExpression& rxp) const { + if (this != &rxp) { // Same address? + int 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 RegularExpression::deep_equal (const RegularExpression& rxp) const { + int 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(0); } +#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. + +bool RegularExpression::compile (const char* exp) { + register const char* scan; + register const char* longest; + register unsigned long len; + int flags; + + if (exp == 0) { + //RAISE Error, SYM(RegularExpression), SYM(No_Expr), + printf ("RegularExpression::compile(): No expression supplied.\n"); + return false; + } + + // First pass: determine size, legality. + regparse = exp; + regnpar = 1; + regsize = 0L; + regcode = ®dummy; + regc(MAGIC); + if(!reg(0, &flags)) + { + printf ("RegularExpression::compile(): Error in compile.\n"); + return false; + } + this->startp[0] = this->endp[0] = this->searchstring = 0; + + // Small enough for pointer-storage convention? + if (regsize >= 32767L) { // Probably could be 65535L. + //RAISE Error, SYM(RegularExpression), SYM(Expr_Too_Big), + printf ("RegularExpression::compile(): Expression too big.\n"); + return false; + } + + // Allocate space. +//#ifndef WIN32 + if (this->program != 0) delete [] this->program; +//#endif + this->program = new char[regsize]; + this->progsize = (int) regsize; + + if (this->program == 0) { + //RAISE Error, SYM(RegularExpression), SYM(Out_Of_Memory), + printf ("RegularExpression::compile(): Out of memory.\n"); + return false; + } + + // 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 = 0; + 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 = 0; + len = 0; + for (; scan != 0; scan = regnext(scan)) + if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { + longest = OPERAND(scan); + len = int(strlen(OPERAND(scan))); + } + this->regmust = longest; + this->regmlen = len; + } + } + return true; +} + + +/* + - 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. + */ +static char* 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 >= RegularExpression::NSUBEXP) { + //RAISE Error, SYM(RegularExpression), SYM(Too_Many_Parens), + printf ("RegularExpression::compile(): Too many parentheses.\n"); + return 0; + } + parno = regnpar; + regnpar++; + ret = regnode(static_cast(OPEN + parno)); + } + else + ret = 0; + + // Pick up the branches, linking them together. + br = regbranch(&flags); + if (br == 0) + return (0); + if (ret != 0) + regtail(ret, br); // OPEN -> first. + else + ret = br; + if (!(flags & HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags & SPSTART; + while (*regparse == '|') { + regparse++; + br = regbranch(&flags); + if (br == 0) + return (0); + 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(static_cast((paren) ? CLOSE + parno : END)); + regtail(ret, ender); + + // Hook the tails of the branches to the closing node. + for (br = ret; br != 0; br = regnext(br)) + regoptail(br, ender); + + // Check for proper termination. + if (paren && *regparse++ != ')') { + //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens), + printf ("RegularExpression::compile(): Unmatched parentheses.\n"); + return 0; + } + else if (!paren && *regparse != '\0') { + if (*regparse == ')') { + //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens), + printf ("RegularExpression::compile(): Unmatched parentheses.\n"); + return 0; + } + else { + //RAISE Error, SYM(RegularExpression), SYM(Internal_Error), + printf ("RegularExpression::compile(): Internal error.\n"); + return 0; + } + // NOTREACHED + } + return (ret); +} + + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static char* regbranch (int *flagp) { + register char* ret; + register char* chain; + register char* latest; + int flags; + + *flagp = WORST; // Tentatively. + + ret = regnode(BRANCH); + chain = 0; + while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { + latest = regpiece(&flags); + if (latest == 0) + return (0); + *flagp |= flags & HASWIDTH; + if (chain == 0) // First piece. + *flagp |= flags & SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == 0) // 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. + */ +static char* regpiece (int *flagp) { + register char* ret; + register char op; + register char* next; + int flags; + + ret = regatom(&flags); + if (ret == 0) + return (0); + + op = *regparse; + if (!ISMULT(op)) { + *flagp = flags; + return (ret); + } + + if (!(flags & HASWIDTH) && op != '?') { + //RAISE Error, SYM(RegularExpression), SYM(Empty_Operand), + printf ("RegularExpression::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(RegularExpression), SYM(Nested_Operand), + printf ("RegularExpression::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. + */ +static char* 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(RegularExpression), SYM(Invalid_Range), + printf ("RegularExpression::compile(): Invalid range in [].\n"); + return 0; + } + for (; rxpclass <= rxpclassend; rxpclass++) + regc(static_cast(rxpclass)); + regparse++; + } + } + else + regc(*regparse++); + } + regc('\0'); + if (*regparse != ']') { + //RAISE Error, SYM(RegularExpression), SYM(Unmatched_Bracket), + printf ("RegularExpression::compile(): Unmatched [].\n"); + return 0; + } + regparse++; + *flagp |= HASWIDTH | SIMPLE; + } + break; + case '(': + ret = reg(1, &flags); + if (ret == 0) + return (0); + *flagp |= flags & (HASWIDTH | SPSTART); + break; + case '\0': + case '|': + case ')': + //RAISE Error, SYM(RegularExpression), SYM(Internal_Error), + printf ("RegularExpression::compile(): Internal error.\n"); // Never here + return 0; + case '?': + case '+': + case '*': + //RAISE Error, SYM(RegularExpression), SYM(No_Operand), + printf ("RegularExpression::compile(): ?+* follows nothing.\n"); + return 0; + case '\\': + if (*regparse == '\0') { + //RAISE Error, SYM(RegularExpression), SYM(Trailing_Backslash), + printf ("RegularExpression::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 = int(strcspn(regparse, META)); + if (len <= 0) { + //RAISE Error, SYM(RegularExpression), SYM(Internal_Error), + printf ("RegularExpression::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. + */ +static char* 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 + */ +static void 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. + */ +static void 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 + */ +static void 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 == 0) + break; + scan = temp; + } + + if (OP(scan) == BACK) + offset = int(scan - val); + else + offset = int(val - scan); + *(scan + 1) = static_cast((offset >> 8) & 0377); + *(scan + 2) = static_cast(offset & 0377); +} + + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ +static void regoptail (char* p, const char* val) { + // "Operandless" and "op != BRANCH" are synonymous in practice. + if (p == 0 || 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 + +bool RegularExpression::find (kwsys_stl::string const& s) +{ + return find(s.c_str()); +} + + + +// find -- Matches the regular expression to the given string. +// Returns true if found, and sets start and end indexes accordingly. + +bool RegularExpression::find (const char* string) { + register const char* s; + + this->searchstring = string; + + if (!this->program) + { + return false; + } + + // Check validity of program. + if (UCHARAT(this->program) != MAGIC) { + //RAISE Error, SYM(RegularExpression), SYM(Internal_Error), + printf ("RegularExpression::find(): Compiled regular expression corrupted.\n"); + return 0; + } + + // If there is a "must appear" string, look for it. + if (this->regmust != 0) { + s = string; + while ((s = strchr(s, this->regmust[0])) != 0) { + if (strncmp(s, this->regmust, this->regmlen) == 0) + break; // Found it. + s++; + } + if (s == 0) // 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) != 0); + + // Messy cases: unanchored match. + s = string; + if (this->regstart != '\0') + // We know what char it must start with. + while ((s = strchr(s, this->regstart)) != 0) { + 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 + */ +static int 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 = RegularExpression::NSUBEXP; i > 0; i--) { + *sp1++ = 0; + *ep++ = 0; + } + 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 + */ +static int regmatch (const char* prog) { + register const char* scan; // Current node. + const char* next; // Next node. + + scan = prog; + + while (scan != 0) { + + 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 = int(strlen(opnd)); + if (len > 1 && strncmp(opnd, reginput, len) != 0) + return (0); + reginput += len; + } + break; + case ANYOF: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == 0) + return (0); + reginput++; + break; + case ANYBUT: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != 0) + 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] == 0) + 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] == 0) + 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 != 0 && 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(RegularExpression), SYM(Internal_Error), + printf ("RegularExpression::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(RegularExpression), SYM(Internal_Error), + printf ("RegularExpression::find(): Internal error -- corrupted pointers.\n"); + return (0); +} + + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int 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 = int(strlen(scan)); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && strchr(opnd, *scan) != 0) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && strchr(opnd, *scan) == 0) { + count++; + scan++; + } + break; + default: // Oh dear. Called inappropriately. + //RAISE Error, SYM(RegularExpression), SYM(Internal_Error), + printf ("cm RegularExpression::find(): Internal error.\n"); + return 0; + } + reginput = scan; + return (count); +} + + +/* + - regnext - dig the "next" pointer out of a node + */ +static const char* regnext (register const char* p) { + register int offset; + + if (p == ®dummy) + return (0); + + offset = NEXT(p); + if (offset == 0) + return (0); + + if (OP(p) == BACK) + return (p - offset); + else + return (p + offset); +} + + +static char* regnext (register char* p) { + register int offset; + + if (p == ®dummy) + return (0); + + offset = NEXT(p); + if (offset == 0) + return (0); + + if (OP(p) == BACK) + return (p - offset); + else + return (p + offset); +} + +} // namespace KWSYS_NAMESPACE diff --git a/Utilities/kwsys/RegularExpression.hxx.in b/Utilities/kwsys/RegularExpression.hxx.in new file mode 100644 index 0000000..d88f6bc --- /dev/null +++ b/Utilities/kwsys/RegularExpression.hxx.in @@ -0,0 +1,392 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: RegularExpression.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +// Original Copyright notice: +// 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 +// + +#ifndef @KWSYS_NAMESPACE@_RegularExpression_hxx +#define @KWSYS_NAMESPACE@_RegularExpression_hxx + +#include <@KWSYS_NAMESPACE@/Configure.h> +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#include <@KWSYS_NAMESPACE@/stl/string> + +/* Define this macro temporarily to keep the code readable. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsys_stl @KWSYS_NAMESPACE@_stl +#endif + +namespace @KWSYS_NAMESPACE@ +{ + +/** \class RegularExpression + * \brief Implements pattern matching with regular expressions. + * + * 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 RegularExpression 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. + * + * This class implements pattern matching via regular expressions. + * 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 RegularExpression regu- + * lar expression class implements regular expression pattern + * matching as is found and implemented in many UNIX commands + * and utilities. + * + * Example: The perl code + * + * $filename =~ m"([a-z]+)\.cc"; + * print $1; + * + * Is written as follows in C++ + * + * RegularExpression re("([a-z]+)\\.cc"); + * re.find(filename); + * cerr << re.match(1); + * + * + * 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. + * + * There are three constructors for RegularExpression. One just creates an + * empty RegularExpression object. Another creates a RegularExpression + * object and initializes it with a regular expression that is given in the + * form of a char*. The third takes a reference to a RegularExpression + * object as an argument and creates an object initialized with the + * information from the given RegularExpression 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". + * + */ +class @KWSYS_NAMESPACE@_EXPORT RegularExpression +{ +public: + /** + * Instantiate RegularExpression with program=NULL. + */ + inline RegularExpression (); + + /** + * Instantiate RegularExpression with compiled char*. + */ + inline RegularExpression (char const*); + + /** + * Instantiate RegularExpression as a copy of another regular expression. + */ + RegularExpression (RegularExpression const&); + + /** + * Destructor. + */ + inline ~RegularExpression(); + + /** + * Compile a regular expression into internal code + * for later pattern matching. + */ + bool compile (char const*); + + /** + * Matches the regular expression to the given string. + * Returns true if found, and sets start and end indexes accordingly. + */ + bool find (char const*); + + /** + * Matches the regular expression to the given std string. + * Returns true if found, and sets start and end indexes accordingly. + */ + bool find (kwsys_stl::string const&); + + /** + * Index to start of first find. + */ + inline kwsys_stl::string::size_type start() const; + + /** + * Index to end of first find. + */ + inline kwsys_stl::string::size_type end() const; + + /** + * Returns true if two regular expressions have the same + * compiled program for pattern matching. + */ + bool operator== (RegularExpression const&) const; + + /** + * Returns true if two regular expressions have different + * compiled program for pattern matching. + */ + inline bool operator!= (RegularExpression const&) const; + + /** + * Returns true if have the same compiled regular expressions + * and the same start and end pointers. + */ + bool deep_equal (RegularExpression const&) const; + + /** + * True if the compiled regexp is valid. + */ + inline bool is_valid() const; + + /** + * Marks the regular expression as invalid. + */ + inline void set_invalid(); + + /** + * Destructor. + */ + // awf added + kwsys_stl::string::size_type start(int n) const; + kwsys_stl::string::size_type end(int n) const; + kwsys_stl::string match(int n) const; + + enum { NSUBEXP = 10 }; +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 + unsigned long regmlen; // Internal use only + char* program; + int progsize; + const char* searchstring; +}; + +/** + * Create an empty regular expression. + */ +inline RegularExpression::RegularExpression () +{ + this->program = 0; +} + +/** + * Creates a regular expression from string s, and + * compiles s. + */ +inline RegularExpression::RegularExpression (const char* s) +{ + this->program = 0; + if ( s ) + { + this->compile(s); + } +} + +/** + * Destroys and frees space allocated for the regular expression. + */ +inline RegularExpression::~RegularExpression () +{ +//#ifndef WIN32 + delete [] this->program; +//#endif +} + +/** + * Set the start position for the regular expression. + */ +inline kwsys_stl::string::size_type RegularExpression::start () const +{ + return(this->startp[0] - searchstring); +} + + +/** + * Returns the start/end index of the last item found. + */ +inline kwsys_stl::string::size_type RegularExpression::end () const +{ + return(this->endp[0] - searchstring); +} + +/** + * Returns true if two regular expressions have different + * compiled program for pattern matching. + */ +inline bool RegularExpression::operator!= (const RegularExpression& r) const +{ + return(!(*this == r)); +} + +/** + * Returns true if a valid regular expression is compiled + * and ready for pattern matching. + */ +inline bool RegularExpression::is_valid () const +{ + return (this->program != 0); +} + + +inline void RegularExpression::set_invalid () +{ +//#ifndef WIN32 + delete [] this->program; +//#endif + this->program = 0; +} + +/** + * Return start index of nth submatch. start(0) is the start of the full match. + */ +inline kwsys_stl::string::size_type RegularExpression::start(int n) const +{ + return this->startp[n] - searchstring; +} + + +/** + * Return end index of nth submatch. end(0) is the end of the full match. + */ +inline kwsys_stl::string::size_type RegularExpression::end(int n) const +{ + return this->endp[n] - searchstring; +} + +/** + * Return nth submatch as a string. + */ +inline kwsys_stl::string RegularExpression::match(int n) const +{ + return kwsys_stl::string(this->startp[n], this->endp[n] - this->startp[n]); +} + +} // namespace @KWSYS_NAMESPACE@ + +/* Undefine temporary macro. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsys_stl +#endif + +#endif diff --git a/Utilities/kwsys/SharedForward.h.in b/Utilities/kwsys/SharedForward.h.in new file mode 100644 index 0000000..110d2b0 --- /dev/null +++ b/Utilities/kwsys/SharedForward.h.in @@ -0,0 +1,672 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: SharedForward.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_SharedForward_h +#define @KWSYS_NAMESPACE@_SharedForward_h + +/* + This header is used to create a forwarding executable sets up the + shared library search path and replaces itself with a real + executable. This is useful when creating installations on UNIX with + shared libraries that will run from any install directory. Typical + usage: + + #define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD "/path/to/foo-build/bin" + #define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD "." + #define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL "../lib/foo-1.2" + #define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD "foo-real" + #define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL "../lib/foo-1.2/foo-real" + #define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT "--print" + #define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD "--ldd" + #if defined(CMAKE_INTDIR) + # define @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME CMAKE_INTDIR + #endif + #include <@KWSYS_NAMESPACE@/SharedForward.h> + int main(int argc, char** argv) + { + return @KWSYS_NAMESPACE@_shared_forward_to_real(argc, argv); + } + */ + +/*--------------------------------------------------------------------------*/ +/* Configuration for this executable. Specify search and executable + paths relative to the forwarding executable location or as full + paths. Include no trailing slash. */ + +/* Full path to the directory in which this executable is built. Do + not include a trailing slash. */ +#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD) +# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD" +#endif +#if !defined(KWSYS_SHARED_FORWARD_DIR_BUILD) +# define KWSYS_SHARED_FORWARD_DIR_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD +#endif + +/* Library search path for build tree. */ +#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD) +# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD" +#endif +#if !defined(KWSYS_SHARED_FORWARD_PATH_BUILD) +# define KWSYS_SHARED_FORWARD_PATH_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD +#endif + +/* Library search path for install tree. */ +#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL) +# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL" +#endif +#if !defined(KWSYS_SHARED_FORWARD_PATH_INSTALL) +# define KWSYS_SHARED_FORWARD_PATH_INSTALL @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL +#endif + +/* The real executable to which to forward in the build tree. */ +#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD) +# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD" +#endif +#if !defined(KWSYS_SHARED_FORWARD_EXE_BUILD) +# define KWSYS_SHARED_FORWARD_EXE_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD +#endif + +/* The real executable to which to forward in the install tree. */ +#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL) +# error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL" +#endif +#if !defined(KWSYS_SHARED_FORWARD_EXE_INSTALL) +# define KWSYS_SHARED_FORWARD_EXE_INSTALL @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL +#endif + +/* The configuration name with which this executable was built (Debug/Release). */ +#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME) +# define KWSYS_SHARED_FORWARD_CONFIG_NAME @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME +#else +# undef KWSYS_SHARED_FORWARD_CONFIG_NAME +#endif + +/* Create command line option to print environment setting and exit. */ +#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT) +# if !defined(KWSYS_SHARED_FORWARD_OPTION_PRINT) +# define KWSYS_SHARED_FORWARD_OPTION_PRINT @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT +# endif +#else +# undef KWSYS_SHARED_FORWARD_OPTION_PRINT +#endif + +/* Create command line option to run ldd or equivalent. */ +#if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD) +# if !defined(KWSYS_SHARED_FORWARD_OPTION_LDD) +# define KWSYS_SHARED_FORWARD_OPTION_LDD @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD +# endif +#else +# undef KWSYS_SHARED_FORWARD_OPTION_LDD +#endif + +/*--------------------------------------------------------------------------*/ +/* Include needed system headers. */ + +#include +#include +#include +#include +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +# include +# include +# include +#else +# include +#endif + +/*--------------------------------------------------------------------------*/ +/* Configuration for this platform. */ + +/* The path separator for this platform. */ +#if defined(_WIN32) && !defined(__CYGWIN__) +# define KWSYS_SHARED_FORWARD_PATH_SEP ';' +# define KWSYS_SHARED_FORWARD_PATH_SLASH '\\' +#else +# define KWSYS_SHARED_FORWARD_PATH_SEP ':' +# define KWSYS_SHARED_FORWARD_PATH_SLASH '/' +#endif +static const char kwsys_shared_forward_path_sep[2] = {KWSYS_SHARED_FORWARD_PATH_SEP, 0}; +static const char kwsys_shared_forward_path_slash[2] = {KWSYS_SHARED_FORWARD_PATH_SLASH, 0}; + +/* The maximum length of a file name. */ +#if defined(PATH_MAX) +# define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX +#elif defined(MAXPATHLEN) +# define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN +#else +# define KWSYS_SHARED_FORWARD_MAXPATH 16384 +#endif + +/* Select the environment variable holding the shared library runtime + search path for this platform and build configuration. Also select + ldd command equivalent. */ + +/* Linux */ +#if defined(__linux) +# define KWSYS_SHARED_FORWARD_LDD "ldd" +# define KWSYS_SHARED_FORWARD_LDD_N 1 +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH" +#endif + +/* FreeBSD */ +#if defined(__FreeBSD__) +# define KWSYS_SHARED_FORWARD_LDD "ldd" +# define KWSYS_SHARED_FORWARD_LDD_N 1 +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH" +#endif + +/* OSX */ +#if defined(__APPLE__) +# define KWSYS_SHARED_FORWARD_LDD "otool", "-L" +# define KWSYS_SHARED_FORWARD_LDD_N 2 +# define KWSYS_SHARED_FORWARD_LDPATH "DYLD_LIBRARY_PATH" +#endif + +/* AIX */ +#if defined(_AIX) +# define KWSYS_SHARED_FORWARD_LDD "dump", "-H" +# define KWSYS_SHARED_FORWARD_LDD_N 2 +# define KWSYS_SHARED_FORWARD_LDPATH "LIBPATH" +#endif + +/* SUN */ +#if defined(__sparc) +# define KWSYS_SHARED_FORWARD_LDD "ldd" +# define KWSYS_SHARED_FORWARD_LDD_N 1 +# include +# if defined(_ILP32) +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH" +# elif defined(_LP64) +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH_64" +# endif +#endif + +/* HP-UX */ +#if defined(__hpux) +# define KWSYS_SHARED_FORWARD_LDD "chatr" +# define KWSYS_SHARED_FORWARD_LDD_N 1 +# if defined(__LP64__) +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH" +# else +# define KWSYS_SHARED_FORWARD_LDPATH "SHLIB_PATH" +# endif +#endif + +/* SGI MIPS */ +#if defined(__sgi) && defined(_MIPS_SIM) +# define KWSYS_SHARED_FORWARD_LDD "ldd" +# define KWSYS_SHARED_FORWARD_LDD_N 1 +# if _MIPS_SIM == _ABIO32 +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH" +# elif _MIPS_SIM == _ABIN32 +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARYN32_PATH" +# elif _MIPS_SIM == _ABI64 +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY64_PATH" +# endif +#endif + +/* Windows */ +#if defined(_WIN32) +# if defined(__CYGWIN__) +# define KWSYS_SHARED_FORWARD_LDD "cygcheck" +# define KWSYS_SHARED_FORWARD_LDD_N 1 +# endif +# define KWSYS_SHARED_FORWARD_LDPATH "PATH" +#endif + +/* Guess on this unknown system. */ +#if !defined(KWSYS_SHARED_FORWARD_LDPATH) +# define KWSYS_SHARED_FORWARD_LDD "ldd" +# define KWSYS_SHARED_FORWARD_LDD_N 1 +# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH" +#endif + +/*--------------------------------------------------------------------------*/ +/* Function to convert a logical or relative path to a physical full path. */ +static int kwsys_shared_forward_realpath(const char* in_path, char* out_path) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Implementation for Windows. */ + DWORD n = GetFullPathName(in_path, KWSYS_SHARED_FORWARD_MAXPATH, + out_path, 0); + return n > 0 && n <= KWSYS_SHARED_FORWARD_MAXPATH; +#else + /* Implementation for UNIX. */ + return realpath(in_path, out_path) != 0; +#endif +} + +/*--------------------------------------------------------------------------*/ +/* Function to report a system error message. */ +static void kwsys_shared_forward_strerror(char* message) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Implementation for Windows. */ + DWORD original = GetLastError(); + DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, 0, original, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + message, KWSYS_SHARED_FORWARD_MAXPATH, 0); + if(length < 1 || length > KWSYS_SHARED_FORWARD_MAXPATH) + { + /* FormatMessage failed. Use a default message. */ + _snprintf(message, KWSYS_SHARED_FORWARD_MAXPATH, + "Error 0x%X (FormatMessage failed with error 0x%X)", + original, GetLastError()); + } +#else + /* Implementation for UNIX. */ + strcpy(message, strerror(errno)); +#endif +} + +/*--------------------------------------------------------------------------*/ +/* Functions to execute a child process. */ +static void kwsys_shared_forward_execv(const char* cmd, char* const argv[]) +{ +#if defined(_MSC_VER) + _execv(cmd, argv); +#else + execv(cmd, argv); +#endif +} +static void kwsys_shared_forward_execvp(const char* cmd, char* const argv[]) +{ +#if defined(_MSC_VER) + _execvp(cmd, argv); +#else + execvp(cmd, argv); +#endif +} + +/*--------------------------------------------------------------------------*/ +/* Function to get the directory containing the given file or directory. */ +static void kwsys_shared_forward_dirname(const char* begin, char* result) +{ + /* Find the location of the last slash. */ + int last_slash_index = -1; + const char* end = begin + strlen(begin); + for(;begin <= end && last_slash_index < 0; --end) + { + if(*end == '/' || *end == '\\') + { + last_slash_index = end-begin; + } + } + + /* Handle each case of the index of the last slash. */ + if(last_slash_index < 0) + { + /* No slashes. */ + strcpy(result, "."); + } + else if(last_slash_index == 0) + { + /* Only one leading slash. */ + strcpy(result, kwsys_shared_forward_path_slash); + } +#if defined(_WIN32) + else if(last_slash_index == 2 && begin[1] == ':') + { + /* Only one leading drive letter and slash. */ + strncpy(result, begin, last_slash_index); + result[last_slash_index] = KWSYS_SHARED_FORWARD_PATH_SLASH; + result[last_slash_index+1] = 0; + } +#endif + else + { + /* A non-leading slash. */ + strncpy(result, begin, last_slash_index); + result[last_slash_index] = 0; + } +} + +/*--------------------------------------------------------------------------*/ +/* Function to check if a file exists and is executable. */ +static int kwsys_shared_forward_is_executable(const char* f) +{ +#if defined(_MSC_VER) +# define KWSYS_SHARED_FORWARD_ACCESS _access +#else +# define KWSYS_SHARED_FORWARD_ACCESS access +#endif +#if defined(X_OK) +# define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK +#else +# define KWSYS_SHARED_FORWARD_ACCESS_OK 04 +#endif + if(KWSYS_SHARED_FORWARD_ACCESS(f, KWSYS_SHARED_FORWARD_ACCESS_OK) == 0) + { + return 1; + } + else + { + return 0; + } +} + +/*--------------------------------------------------------------------------*/ +/* Function to locate the executable currently running. */ +static int kwsys_shared_forward_self_path(const char* argv0, char* result) +{ + /* Check whether argv0 has a slash. */ + int has_slash = 0; + const char* p = argv0; + for(;*p && !has_slash; ++p) + { + if(*p == '/' || *p == '\\') + { + has_slash = 1; + } + } + + if(has_slash) + { + /* There is a slash. Use the dirname of the given location. */ + kwsys_shared_forward_dirname(argv0, result); + return 1; + } + else + { + /* There is no slash. Search the PATH for the executable. */ + const char* path = getenv("PATH"); + const char* begin = path; + const char* end = begin + (begin?strlen(begin):0); + const char* first = begin; + while(first != end) + { + /* Store the end of this path entry. */ + const char* last; + + /* Skip all path separators. */ + for(;*first && *first == KWSYS_SHARED_FORWARD_PATH_SEP; ++first); + + /* Find the next separator. */ + for(last = first;*last && *last != KWSYS_SHARED_FORWARD_PATH_SEP; ++last); + + /* If we got a non-empty directory, look for the executable there. */ + if(first < last) + { + /* Determine the length without trailing slash. */ + int length = last-first; + if(*(last-1) == '/' || *(last-1) == '\\') + { + --length; + } + + /* Construct the name of the executable in this location. */ + strncpy(result, first, length); + result[length] = KWSYS_SHARED_FORWARD_PATH_SLASH; + strcpy(result+(length)+1, argv0); + + /* Check if it exists and is executable. */ + if(kwsys_shared_forward_is_executable(result)) + { + /* Found it. */ + result[length] = 0; + return 1; + } + } + + /* Move to the next directory in the path. */ + first = last; + } + } + + /* We could not find the executable. */ + return 0; +} + +/*--------------------------------------------------------------------------*/ +/* Function to convert a specified path to a full path. If it is not + already full, it is taken relative to the self path. */ +static int kwsys_shared_forward_fullpath(const char* self_path, + const char* in_path, + char* result, + const char* desc) +{ + /* Check the specified path type. */ + if(in_path[0] == '/') + { + /* Already a full path. */ + strcpy(result, in_path); + } +#if defined(_WIN32) + else if(in_path[0] && in_path[1] == ':') + { + /* Already a full path. */ + strcpy(result, in_path); + } +#endif + else + { + /* Relative to self path. */ + char temp_path[KWSYS_SHARED_FORWARD_MAXPATH]; + strcpy(temp_path, self_path); + strcat(temp_path, kwsys_shared_forward_path_slash); + strcat(temp_path, in_path); + if(!kwsys_shared_forward_realpath(temp_path, result)) + { + if(desc) + { + char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH]; + kwsys_shared_forward_strerror(msgbuf); + fprintf(stderr, "Error converting %s \"%s\" to real path: %s\n", + desc, temp_path, msgbuf); + } + return 0; + } + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +/* Function to compute the library search path and executable name + based on the self path. */ +static int kwsys_shared_forward_get_settings(const char* self_path, + char* ldpath, char* exe) +{ + /* Possible search paths. */ + static const char* search_path_build[] = {KWSYS_SHARED_FORWARD_PATH_BUILD, 0}; + static const char* search_path_install[] = {KWSYS_SHARED_FORWARD_PATH_INSTALL, 0}; + + /* Chosen paths. */ + const char** search_path; + const char* exe_path; + + /* Get the real name of the build and self paths. */ +#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME) + char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD "/" KWSYS_SHARED_FORWARD_CONFIG_NAME; + char self_path_logical[KWSYS_SHARED_FORWARD_MAXPATH]; +#else + char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD; + const char* self_path_logical = self_path; +#endif + char build_path_real[KWSYS_SHARED_FORWARD_MAXPATH]; + char self_path_real[KWSYS_SHARED_FORWARD_MAXPATH]; + if(!kwsys_shared_forward_realpath(self_path, self_path_real)) + { + char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH]; + kwsys_shared_forward_strerror(msgbuf); + fprintf(stderr, "Error converting self path \"%s\" to real path: %s\n", + self_path, msgbuf); + return 0; + } + + /* Check whether we are running in the build tree or an install tree. */ + if(kwsys_shared_forward_realpath(build_path, build_path_real) && + strcmp(self_path_real, build_path_real) == 0) + { + /* Running in build tree. Use the build path and exe. */ + search_path = search_path_build; +#if defined(_WIN32) + exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD ".exe"; +#else + exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD; +#endif + +#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME) + /* Remove the configuration directory from self_path. */ + kwsys_shared_forward_dirname(self_path, self_path_logical); +#endif + } + else + { + /* Running in install tree. Use the install path and exe. */ + search_path = search_path_install; +#if defined(_WIN32) + exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL ".exe"; +#else + exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL; +#endif + +#if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME) + /* Use the original self path directory. */ + strcpy(self_path_logical, self_path); +#endif + } + + /* Construct the runtime search path. */ + { + const char** dir; + for(dir = search_path; *dir; ++dir) + { + /* Add seperator between path components. */ + if(dir != search_path) + { + strcat(ldpath, kwsys_shared_forward_path_sep); + } + + /* Add this path component. */ + if(!kwsys_shared_forward_fullpath(self_path_logical, *dir, + ldpath+strlen(ldpath), + "runtime path entry")) + { + return 0; + } + } + } + + /* Construct the executable location. */ + if(!kwsys_shared_forward_fullpath(self_path_logical, exe_path, exe, + "executable file")) + { + return 0; + } + return 1; +} + +/*--------------------------------------------------------------------------*/ +/* Function to print why execution of a command line failed. */ +static void kwsys_shared_forward_print_failure(char** argv) +{ + char msg[KWSYS_SHARED_FORWARD_MAXPATH]; + char** arg = argv; + kwsys_shared_forward_strerror(msg); + fprintf(stderr, "Error running"); + for(; *arg; ++arg) + { + fprintf(stderr, " \"%s\"", *arg); + } + fprintf(stderr, ": %s\n", msg); +} + +/* Static storage space to store the updated environment variable. */ +static char kwsys_shared_forward_ldpath[KWSYS_SHARED_FORWARD_MAXPATH*16] = KWSYS_SHARED_FORWARD_LDPATH "="; + +/*--------------------------------------------------------------------------*/ +/* Main driver function to be called from main. */ +static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv) +{ + /* Get the directory containing this executable. */ + char self_path[KWSYS_SHARED_FORWARD_MAXPATH]; + if(kwsys_shared_forward_self_path(argv[0], self_path)) + { + /* Found this executable. Use it to get the library directory. */ + char exe[KWSYS_SHARED_FORWARD_MAXPATH]; + if(kwsys_shared_forward_get_settings(self_path, + kwsys_shared_forward_ldpath, exe)) + { + /* Append the old runtime search path. */ + const char* old_ldpath = getenv(KWSYS_SHARED_FORWARD_LDPATH); + if(old_ldpath) + { + strcat(kwsys_shared_forward_ldpath, kwsys_shared_forward_path_sep); + strcat(kwsys_shared_forward_ldpath, old_ldpath); + } + + /* Store the environment variable. */ + putenv(kwsys_shared_forward_ldpath); + +#if defined(KWSYS_SHARED_FORWARD_OPTION_PRINT) + /* Look for the print command line option. */ + if(argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_PRINT) == 0) + { + fprintf(stdout, "%s\n", kwsys_shared_forward_ldpath); + fprintf(stdout, "%s\n", exe); + return 0; + } +#endif + +#if defined(KWSYS_SHARED_FORWARD_OPTION_LDD) + /* Look for the ldd command line option. */ + if(argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_LDD) == 0) + { +# if defined(KWSYS_SHARED_FORWARD_LDD) + /* Use the named ldd-like executable and arguments. */ + char* ldd_argv[] = {KWSYS_SHARED_FORWARD_LDD, 0, 0}; + ldd_argv[KWSYS_SHARED_FORWARD_LDD_N] = exe; + kwsys_shared_forward_execvp(ldd_argv[0], ldd_argv); + + /* Report why execution failed. */ + kwsys_shared_forward_print_failure(ldd_argv); + return 1; +# else + /* We have no ldd-like executable available on this platform. */ + fprintf(stderr, "No ldd-like tool is known to this executable.\n"); + return 1; +# endif + } +#endif + + /* Replace this process with the real executable. */ + argv[0] = exe; + kwsys_shared_forward_execv(argv[0], argv); + + /* Report why execution failed. */ + kwsys_shared_forward_print_failure(argv); + } + else + { + /* Could not convert self path to the library directory. */ + } + } + else + { + /* Could not find this executable. */ + fprintf(stderr, "Error locating executable \"%s\".\n", argv[0]); + } + + /* Avoid unused argument warning. */ + (void)argc; + + /* Exit with failure. */ + return 1; +} + +#else +# error "@KWSYS_NAMESPACE@/SharedForward.h should be included only once." +#endif diff --git a/Utilities/kwsys/SystemTools.cxx b/Utilities/kwsys/SystemTools.cxx new file mode 100644 index 0000000..19d5e7c --- /dev/null +++ b/Utilities/kwsys/SystemTools.cxx @@ -0,0 +1,3858 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: SystemTools.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(SystemTools.hxx) +#include KWSYS_HEADER(Directory.hxx) + +#include KWSYS_HEADER(ios/iostream) +#include KWSYS_HEADER(ios/fstream) +#include KWSYS_HEADER(ios/sstream) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "SystemTools.hxx.in" +# include "Directory.hxx.in" +# include "kwsys_ios_iostream.h.in" +# include "kwsys_ios_fstream.h.in" +# include "kwsys_ios_sstream.h.in" +#endif + +#ifdef _MSC_VER +# pragma warning (disable: 4786) +#endif + +#if defined(__sgi) && !defined(__GNUC__) +# pragma set woff 1375 /* base class destructor not virtual */ +#endif + +#include +#include +#ifdef __QNX__ +# include /* for malloc/free on QNX */ +#endif +#include +#include +#include +#include +#include + +// support for realpath call +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#endif + +// Windows API. Some parts used even on cygwin. +#if defined(_WIN32) +# include +#endif + +// This is a hack to prevent warnings about these functions being +// declared but not referenced. +#if defined(__sgi) && !defined(__GNUC__) +# include +namespace KWSYS_NAMESPACE +{ +class SystemToolsHack +{ +public: + enum + { + Ref1 = sizeof(cfgetospeed(0)), + Ref2 = sizeof(cfgetispeed(0)), + Ref3 = sizeof(tcgetattr(0, 0)), + Ref4 = sizeof(tcsetattr(0, 0, 0)), + Ref5 = sizeof(cfsetospeed(0,0)), + Ref6 = sizeof(cfsetispeed(0,0)) + }; +}; +} +#endif + +#if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)) +#include +#include +#define _unlink unlink +inline int Mkdir(const char* dir) +{ + return _mkdir(dir); +} +inline int Rmdir(const char* dir) +{ + return _rmdir(dir); +} +inline const char* Getcwd(char* buf, unsigned int len) +{ + return _getcwd(buf, len); +} +inline int Chdir(const char* dir) +{ + #if defined(__BORLANDC__) + return chdir(dir); + #else + return _chdir(dir); + #endif +} +inline void Realpath(const char *path, kwsys_stl::string & resolved_path) +{ + char *ptemp; + char fullpath[MAX_PATH]; + if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) ) + { + resolved_path = fullpath; + KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path); + } +} +#else +#include +#include +#include +inline int Mkdir(const char* dir) +{ + return mkdir(dir, 00777); +} +inline int Rmdir(const char* dir) +{ + return rmdir(dir); +} +inline const char* Getcwd(char* buf, unsigned int len) +{ + return getcwd(buf, len); +} +inline int Chdir(const char* dir) +{ + return chdir(dir); +} +inline void Realpath(const char *path, kwsys_stl::string & resolved_path) +{ +# ifdef MAXPATHLEN + char resolved_name[MAXPATHLEN]; +# else +# ifdef PATH_MAX + char resolved_name[PATH_MAX]; +# else + char resolved_name[5024]; +# endif //PATH_MAX +# endif //MAXPATHLEN + + realpath(path, resolved_name); + resolved_path = resolved_name; +} +#endif + +#if !defined(_WIN32) && defined(__COMO__) +// Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE. +extern "C" +{ +extern FILE *popen (__const char *__command, __const char *__modes) __THROW; +extern int pclose (FILE *__stream) __THROW; +extern char *realpath (__const char *__restrict __name, + char *__restrict __resolved) __THROW; +extern char *strdup (__const char *__s) __THROW; +extern int putenv (char *__string) __THROW; +} +#endif + +/* Implement floattime() for various platforms */ +// Taken from Python 2.1.3 + +#if defined( _WIN32 ) && !defined( __CYGWIN__ ) +# include +# define HAVE_FTIME +# if defined( __BORLANDC__) +# define FTIME ftime +# define TIMEB timeb +# else // Visual studio? +# define FTIME _ftime +# define TIMEB _timeb +# endif +#elif defined( __CYGWIN__ ) || defined( __linux__ ) +# include +# include +# define HAVE_GETTIMEOFDAY +#endif + +namespace KWSYS_NAMESPACE +{ + +class SystemToolsTranslationMap : + public kwsys_stl::map +{ +}; + +double +SystemTools::GetTime(void) +{ + /* There are three ways to get the time: + (1) gettimeofday() -- resolution in microseconds + (2) ftime() -- resolution in milliseconds + (3) time() -- resolution in seconds + In all cases the return value is a float in seconds. + Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may + fail, so we fall back on ftime() or time(). + Note: clock resolution does not imply clock accuracy! */ +#ifdef HAVE_GETTIMEOFDAY + { + struct timeval t; +#ifdef GETTIMEOFDAY_NO_TZ + if (gettimeofday(&t) == 0) + return (double)t.tv_sec + t.tv_usec*0.000001; +#else /* !GETTIMEOFDAY_NO_TZ */ + if (gettimeofday(&t, (struct timezone *)NULL) == 0) + return (double)t.tv_sec + t.tv_usec*0.000001; +#endif /* !GETTIMEOFDAY_NO_TZ */ + } +#endif /* !HAVE_GETTIMEOFDAY */ + { +#if defined(HAVE_FTIME) + struct TIMEB t; + ::FTIME(&t); + return (double)t.time + (double)t.millitm * (double)0.001; +#else /* !HAVE_FTIME */ + time_t secs; + time(&secs); + return (double)secs; +#endif /* !HAVE_FTIME */ + } +} + +// adds the elements of the env variable path to the arg passed in +void SystemTools::GetPath(kwsys_stl::vector& path, const char* env) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + const char* pathSep = ";"; +#else + const char* pathSep = ":"; +#endif + if(!env) + { + env = "PATH"; + } + const char* cpathEnv = SystemTools::GetEnv(env); + if ( !cpathEnv ) + { + return; + } + + kwsys_stl::string pathEnv = cpathEnv; + + // A hack to make the below algorithm work. + if(pathEnv[pathEnv.length()-1] != ':') + { + pathEnv += pathSep; + } + kwsys_stl::string::size_type start =0; + bool done = false; + while(!done) + { + kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start); + if(endpos != kwsys_stl::string::npos) + { + path.push_back(pathEnv.substr(start, endpos-start)); + start = endpos+1; + } + else + { + done = true; + } + } + for(kwsys_stl::vector::iterator i = path.begin(); + i != path.end(); ++i) + { + SystemTools::ConvertToUnixSlashes(*i); + } +} + +const char* SystemTools::GetEnv(const char* key) +{ + return getenv(key); +} + +bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result) +{ + const char* v = getenv(key); + if(v) + { + result = v; + return true; + } + else + { + return false; + } +} + +const char* SystemTools::GetExecutableExtension() +{ +#if defined(_WIN32) || defined(__CYGWIN__) + return ".exe"; +#else + return ""; +#endif +} + + +bool SystemTools::MakeDirectory(const char* path) +{ + if(SystemTools::FileExists(path)) + { + return true; + } + kwsys_stl::string dir = path; + if(dir.size() == 0) + { + return false; + } + SystemTools::ConvertToUnixSlashes(dir); + + kwsys_stl::string::size_type pos = dir.find(':'); + if(pos == kwsys_stl::string::npos) + { + pos = 0; + } + kwsys_stl::string topdir; + while((pos = dir.find('/', pos)) != kwsys_stl::string::npos) + { + topdir = dir.substr(0, pos); + Mkdir(topdir.c_str()); + pos++; + } + if(dir[dir.size()-1] == '/') + { + topdir = dir.substr(0, dir.size()); + } + else + { + topdir = dir; + } + if(Mkdir(topdir.c_str()) != 0) + { + // There is a bug in the Borland Run time library which makes MKDIR + // return EACCES when it should return EEXISTS + // if it is some other error besides directory exists + // then return false + if( (errno != EEXIST) +#ifdef __BORLANDC__ + && (errno != EACCES) +#endif + ) + { + return false; + } + } + return true; +} + + +// replace replace with with as many times as it shows up in source. +// write the result into source. +void SystemTools::ReplaceString(kwsys_stl::string& source, + const char* replace, + const char* with) +{ + const char *src = source.c_str(); + char *searchPos = const_cast(strstr(src,replace)); + + // get out quick if string is not found + if (!searchPos) + { + return; + } + + // perform replacements until done + size_t replaceSize = strlen(replace); + char *orig = strdup(src); + char *currentPos = orig; + searchPos = searchPos - src + orig; + + // initialize the result + source.erase(source.begin(),source.end()); + do + { + *searchPos = '\0'; + source += currentPos; + currentPos = searchPos + replaceSize; + // replace + source += with; + searchPos = strstr(currentPos,replace); + } + while (searchPos); + + // copy any trailing text + source += currentPos; + free(orig); +} + +// Read a registry value. +// Example : +// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath +// => will return the data of the "default" value of the key +// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root +// => will return the data of the "Root" value of the key + +#if defined(_WIN32) && !defined(__CYGWIN__) +bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value) +{ + + kwsys_stl::string primary = key; + kwsys_stl::string second; + kwsys_stl::string valuename; + + size_t start = primary.find("\\"); + if (start == kwsys_stl::string::npos) + { + return false; + } + + size_t valuenamepos = primary.find(";"); + if (valuenamepos != kwsys_stl::string::npos) + { + valuename = primary.substr(valuenamepos+1); + } + + second = primary.substr(start+1, valuenamepos-start-1); + primary = primary.substr(0, start); + + HKEY primaryKey = HKEY_CURRENT_USER; + if (primary == "HKEY_CURRENT_USER") + { + primaryKey = HKEY_CURRENT_USER; + } + if (primary == "HKEY_CURRENT_CONFIG") + { + primaryKey = HKEY_CURRENT_CONFIG; + } + if (primary == "HKEY_CLASSES_ROOT") + { + primaryKey = HKEY_CLASSES_ROOT; + } + if (primary == "HKEY_LOCAL_MACHINE") + { + primaryKey = HKEY_LOCAL_MACHINE; + } + if (primary == "HKEY_USERS") + { + primaryKey = HKEY_USERS; + } + + HKEY hKey; + if(RegOpenKeyEx(primaryKey, + second.c_str(), + 0, + KEY_READ, + &hKey) != ERROR_SUCCESS) + { + return false; + } + else + { + DWORD dwType, dwSize; + dwSize = 1023; + char data[1024]; + if(RegQueryValueEx(hKey, + (LPTSTR)valuename.c_str(), + NULL, + &dwType, + (BYTE *)data, + &dwSize) == ERROR_SUCCESS) + { + if (dwType == REG_SZ) + { + value = data; + RegCloseKey(hKey); + return true; + } + } + } + return false; +} +#else +bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &) +{ + return false; +} +#endif + + +// Write a registry value. +// Example : +// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath +// => will set the data of the "default" value of the key +// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root +// => will set the data of the "Root" value of the key + +#if defined(_WIN32) && !defined(__CYGWIN__) +bool SystemTools::WriteRegistryValue(const char *key, const char *value) +{ + kwsys_stl::string primary = key; + kwsys_stl::string second; + kwsys_stl::string valuename; + + size_t start = primary.find("\\"); + if (start == kwsys_stl::string::npos) + { + return false; + } + + size_t valuenamepos = primary.find(";"); + if (valuenamepos != kwsys_stl::string::npos) + { + valuename = primary.substr(valuenamepos+1); + } + + second = primary.substr(start+1, valuenamepos-start-1); + primary = primary.substr(0, start); + + HKEY primaryKey = HKEY_CURRENT_USER; + if (primary == "HKEY_CURRENT_USER") + { + primaryKey = HKEY_CURRENT_USER; + } + if (primary == "HKEY_CURRENT_CONFIG") + { + primaryKey = HKEY_CURRENT_CONFIG; + } + if (primary == "HKEY_CLASSES_ROOT") + { + primaryKey = HKEY_CLASSES_ROOT; + } + if (primary == "HKEY_LOCAL_MACHINE") + { + primaryKey = HKEY_LOCAL_MACHINE; + } + if (primary == "HKEY_USERS") + { + primaryKey = HKEY_USERS; + } + + HKEY hKey; + DWORD dwDummy; + if(RegCreateKeyEx(primaryKey, + second.c_str(), + 0, + "", + REG_OPTION_NON_VOLATILE, + KEY_WRITE, + NULL, + &hKey, + &dwDummy) != ERROR_SUCCESS) + { + return false; + } + + if(RegSetValueEx(hKey, + (LPTSTR)valuename.c_str(), + 0, + REG_SZ, + (CONST BYTE *)value, + (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS) + { + return true; + } + return false; +} +#else +bool SystemTools::WriteRegistryValue(const char *, const char *) +{ + return false; +} +#endif + +// Delete a registry value. +// Example : +// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath +// => will delete the data of the "default" value of the key +// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root +// => will delete the data of the "Root" value of the key + +#if defined(_WIN32) && !defined(__CYGWIN__) +bool SystemTools::DeleteRegistryValue(const char *key) +{ + kwsys_stl::string primary = key; + kwsys_stl::string second; + kwsys_stl::string valuename; + + size_t start = primary.find("\\"); + if (start == kwsys_stl::string::npos) + { + return false; + } + + size_t valuenamepos = primary.find(";"); + if (valuenamepos != kwsys_stl::string::npos) + { + valuename = primary.substr(valuenamepos+1); + } + + second = primary.substr(start+1, valuenamepos-start-1); + primary = primary.substr(0, start); + + HKEY primaryKey = HKEY_CURRENT_USER; + if (primary == "HKEY_CURRENT_USER") + { + primaryKey = HKEY_CURRENT_USER; + } + if (primary == "HKEY_CURRENT_CONFIG") + { + primaryKey = HKEY_CURRENT_CONFIG; + } + if (primary == "HKEY_CLASSES_ROOT") + { + primaryKey = HKEY_CLASSES_ROOT; + } + if (primary == "HKEY_LOCAL_MACHINE") + { + primaryKey = HKEY_LOCAL_MACHINE; + } + if (primary == "HKEY_USERS") + { + primaryKey = HKEY_USERS; + } + + HKEY hKey; + if(RegOpenKeyEx(primaryKey, + second.c_str(), + 0, + KEY_WRITE, + &hKey) != ERROR_SUCCESS) + { + return false; + } + else + { + if(RegDeleteValue(hKey, + (LPTSTR)valuename.c_str()) == ERROR_SUCCESS) + { + RegCloseKey(hKey); + return true; + } + } + return false; +} +#else +bool SystemTools::DeleteRegistryValue(const char *) +{ + return false; +} +#endif + +bool SystemTools::SameFile(const char* file1, const char* file2) +{ +#ifdef _WIN32 + HANDLE hFile1, hFile2; + + hFile1 = CreateFile( file1, + GENERIC_READ, + FILE_SHARE_READ , + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + hFile2 = CreateFile( file2, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE) + { + if(hFile1 != INVALID_HANDLE_VALUE) + { + CloseHandle(hFile1); + } + if(hFile2 != INVALID_HANDLE_VALUE) + { + CloseHandle(hFile2); + } + return false; + } + + BY_HANDLE_FILE_INFORMATION fiBuf1; + BY_HANDLE_FILE_INFORMATION fiBuf2; + GetFileInformationByHandle( hFile1, &fiBuf1 ); + GetFileInformationByHandle( hFile2, &fiBuf2 ); + CloseHandle(hFile1); + CloseHandle(hFile2); + return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber && + fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh && + fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow); +#else + struct stat fileStat1, fileStat2; + if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0) + { + // see if the files are the same file + // check the device inode and size + if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 && + memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 && + fileStat2.st_size == fileStat1.st_size + ) + { + return true; + } + } + return false; +#endif +} + + +// return true if the file exists +bool SystemTools::FileExists(const char* filename) +{ +#ifdef _MSC_VER +# define access _access +#endif +#ifndef R_OK +# define R_OK 04 +#endif + if ( access(filename, R_OK) != 0 ) + { + return false; + } + else + { + return true; + } +} + + +bool SystemTools::FileTimeCompare(const char* f1, const char* f2, + int* result) +{ + // Default to same time. + *result = 0; +#if !defined(_WIN32) || defined(__CYGWIN__) + // POSIX version. Use stat function to get file modification time. + struct stat s1; + if(stat(f1, &s1) != 0) + { + return false; + } + struct stat s2; + if(stat(f2, &s2) != 0) + { + return false; + } +# if KWSYS_STAT_HAS_ST_MTIM + // Compare using nanosecond resolution. + if(s1.st_mtim.tv_sec < s2.st_mtim.tv_sec) + { + *result = -1; + } + else if(s1.st_mtim.tv_sec > s2.st_mtim.tv_sec) + { + *result = 1; + } + else if(s1.st_mtim.tv_nsec < s2.st_mtim.tv_nsec) + { + *result = -1; + } + else if(s1.st_mtim.tv_nsec > s2.st_mtim.tv_nsec) + { + *result = 1; + } +# else + // Compare using 1 second resolution. + if(s1.st_mtime < s2.st_mtime) + { + *result = -1; + } + else if(s1.st_mtime > s2.st_mtime) + { + *result = 1; + } +# endif +#else + // Windows version. Create file handles and get the modification times. + HANDLE hf1 = CreateFile(f1, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if(hf1 == INVALID_HANDLE_VALUE) + { + return false; + } + FILETIME tf1; + if(!GetFileTime(hf1, 0, 0, &tf1)) + { + CloseHandle(hf1); + return false; + } + CloseHandle(hf1); + HANDLE hf2 = CreateFile(f2, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, + NULL); + if(hf2 == INVALID_HANDLE_VALUE) + { + return false; + } + FILETIME tf2; + if(!GetFileTime(hf2, 0, 0, &tf2)) + { + CloseHandle(hf2); + return false; + } + CloseHandle(hf2); + + // Compare the file times using resolution provided by system call. + *result = (int)CompareFileTime(&tf1, &tf2); +#endif + return true; +} + + +// Return a capitalized string (i.e the first letter is uppercased, all other +// are lowercased) +kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s) +{ + kwsys_stl::string n; + if(s.size() == 0) + { + return n; + } + n.resize(s.size()); + n[0] = static_cast(toupper(s[0])); + for (size_t i = 1; i < s.size(); i++) + { + n[i] = static_cast(tolower(s[i])); + } + return n; +} + +// Return capitalized words +kwsys_stl::string SystemTools::CapitalizedWords(const kwsys_stl::string& s) +{ + kwsys_stl::string n(s); + for (size_t i = 0; i < s.size(); i++) + { + if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1]))) + { + n[i] = static_cast(toupper(s[i])); + } + } + return n; +} + +// Return uncapitalized words +kwsys_stl::string SystemTools::UnCapitalizedWords(const kwsys_stl::string& s) +{ + kwsys_stl::string n(s); + for (size_t i = 0; i < s.size(); i++) + { + if (isalpha(s[i]) && (i == 0 || isspace(s[i - 1]))) + { + n[i] = static_cast(tolower(s[i])); + } + } + return n; +} + +kwsys_stl::string SystemTools::AddSpaceBetweenCapitalizedWords( + const kwsys_stl::string& s) +{ + kwsys_stl::string n; + if (s.size()) + { + n.reserve(s.size()); + n += s[0]; + for (size_t i = 1; i < s.size(); i++) + { + if (isupper(s[i]) && !isspace(s[i - 1]) && !isupper(s[i - 1])) + { + n += ' '; + } + n += s[i]; + } + } + return n; +} + +char* SystemTools::AppendStrings(const char* str1, const char* str2) +{ + if (!str1) + { + return SystemTools::DuplicateString(str2); + } + if (!str2) + { + return SystemTools::DuplicateString(str1); + } + size_t len1 = strlen(str1); + char *newstr = new char[len1 + strlen(str2) + 1]; + if (!newstr) + { + return 0; + } + strcpy(newstr, str1); + strcat(newstr + len1, str2); + return newstr; +} + +char* SystemTools::AppendStrings( + const char* str1, const char* str2, const char* str3) +{ + if (!str1) + { + return SystemTools::AppendStrings(str2, str3); + } + if (!str2) + { + return SystemTools::AppendStrings(str1, str3); + } + if (!str3) + { + return SystemTools::AppendStrings(str1, str2); + } + + size_t len1 = strlen(str1), len2 = strlen(str2); + char *newstr = new char[len1 + len2 + strlen(str3) + 1]; + if (!newstr) + { + return 0; + } + strcpy(newstr, str1); + strcat(newstr + len1, str2); + strcat(newstr + len1 + len2, str3); + return newstr; +} + +// Return a lower case string +kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s) +{ + kwsys_stl::string n; + n.resize(s.size()); + for (size_t i = 0; i < s.size(); i++) + { + n[i] = static_cast(tolower(s[i])); + } + return n; +} + +// Return a lower case string +kwsys_stl::string SystemTools::UpperCase(const kwsys_stl::string& s) +{ + kwsys_stl::string n; + n.resize(s.size()); + for (size_t i = 0; i < s.size(); i++) + { + n[i] = static_cast(toupper(s[i])); + } + return n; +} + +// Count char in string +size_t SystemTools::CountChar(const char* str, char c) +{ + size_t count = 0; + + if (str) + { + while (*str) + { + if (*str == c) + { + ++count; + } + ++str; + } + } + return count; +} + +// Remove chars in string +char* SystemTools::RemoveChars(const char* str, const char *toremove) +{ + if (!str) + { + return NULL; + } + char *clean_str = new char [strlen(str) + 1]; + char *ptr = clean_str; + while (*str) + { + const char *str2 = toremove; + while (*str2 && *str != *str2) + { + ++str2; + } + if (!*str2) + { + *ptr++ = *str; + } + ++str; + } + *ptr = '\0'; + return clean_str; +} + +// Remove chars in string +char* SystemTools::RemoveCharsButUpperHex(const char* str) +{ + if (!str) + { + return 0; + } + char *clean_str = new char [strlen(str) + 1]; + char *ptr = clean_str; + while (*str) + { + if ((*str >= '0' && *str <= '9') || (*str >= 'A' && *str <= 'H')) + { + *ptr++ = *str; + } + ++str; + } + *ptr = '\0'; + return clean_str; +} + +// Replace chars in string +char* SystemTools::ReplaceChars(char* str, const char *toreplace, char replacement) +{ + if (str) + { + char *ptr = str; + while (*ptr) + { + const char *ptr2 = toreplace; + while (*ptr2) + { + if (*ptr == *ptr2) + { + *ptr = replacement; + } + ++ptr2; + } + ++ptr; + } + } + return str; +} + +// Returns if string starts with another string +bool SystemTools::StringStartsWith(const char* str1, const char* str2) +{ + if (!str1 || !str2) + { + return false; + } + size_t len1 = strlen(str1), len2 = strlen(str2); + return len1 >= len2 && !strncmp(str1, str2, len2) ? true : false; +} + +// Returns if string ends with another string +bool SystemTools::StringEndsWith(const char* str1, const char* str2) +{ + if (!str1 || !str2) + { + return false; + } + size_t len1 = strlen(str1), len2 = strlen(str2); + return len1 >= len2 && !strncmp(str1 + (len1 - len2), str2, len2) ? true : false; +} + +// Returns a pointer to the last occurence of str2 in str1 +const char* SystemTools::FindLastString(const char* str1, const char* str2) +{ + if (!str1 || !str2) + { + return NULL; + } + + size_t len1 = strlen(str1), len2 = strlen(str2); + if (len1 >= len2) + { + const char *ptr = str1 + len1 - len2; + do + { + if (!strncmp(ptr, str2, len2)) + { + return ptr; + } + } while (ptr-- != str1); + } + + return NULL; +} + +// Duplicate string +char* SystemTools::DuplicateString(const char* str) +{ + if (str) + { + char *newstr = new char [strlen(str) + 1]; + return strcpy(newstr, str); + } + return NULL; +} + +// Return a cropped string +kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s, + size_t max_len) +{ + if (!s.size() || max_len == 0 || max_len >= s.size()) + { + return s; + } + + kwsys_stl::string n; + n.reserve(max_len); + + size_t middle = max_len / 2; + + n += s.substr(0, middle); + n += s.substr(s.size() - (max_len - middle), kwsys_stl::string::npos); + + if (max_len > 2) + { + n[middle] = '.'; + if (max_len > 3) + { + n[middle - 1] = '.'; + if (max_len > 4) + { + n[middle + 1] = '.'; + } + } + } + + return n; +} + +//---------------------------------------------------------------------------- +kwsys_stl::vector SystemTools::SplitString(const char* p, char sep, bool isPath) +{ + kwsys_stl::string path = p; + kwsys_stl::vector paths; + if(isPath && path[0] == '/') + { + path.erase(path.begin()); + paths.push_back("/"); + } + kwsys_stl::string::size_type pos1 = 0; + kwsys_stl::string::size_type pos2 = path.find(sep, pos1+1); + while(pos2 != kwsys_stl::string::npos) + { + paths.push_back(path.substr(pos1, pos2-pos1)); + pos1 = pos2+1; + pos2 = path.find(sep, pos1+1); + } + paths.push_back(path.substr(pos1, pos2-pos1)); + + return paths; +} + +//---------------------------------------------------------------------------- +int SystemTools::EstimateFormatLength(const char *format, va_list ap) +{ + if (!format) + { + return 0; + } + + // Quick-hack attempt at estimating the length of the string. + // Should never under-estimate. + + // Start with the length of the format string itself. + + int length = strlen(format); + + // Increase the length for every argument in the format. + + const char* cur = format; + while(*cur) + { + if(*cur++ == '%') + { + // Skip "%%" since it doesn't correspond to a va_arg. + if(*cur != '%') + { + while(!int(isalpha(*cur))) + { + ++cur; + } + switch (*cur) + { + case 's': + { + // Check the length of the string. + char* s = va_arg(ap, char*); + if(s) + { + length += strlen(s); + } + } break; + case 'e': + case 'f': + case 'g': + { + // Assume the argument contributes no more than 64 characters. + length += 64; + + // Eat the argument. + static_cast(va_arg(ap, double)); + } break; + default: + { + // Assume the argument contributes no more than 64 characters. + length += 64; + + // Eat the argument. + static_cast(va_arg(ap, int)); + } break; + } + } + + // Move past the characters just tested. + ++cur; + } + } + + return length; +} + +kwsys_stl::string SystemTools::EscapeChars( + const char *str, + const char *chars_to_escape, + char escape_char) +{ + kwsys_stl::string n; + if (str) + { + if (!chars_to_escape | !*chars_to_escape) + { + n.append(str); + } + else + { + n.reserve(strlen(str)); + while (*str) + { + const char *ptr = chars_to_escape; + while (*ptr) + { + if (*str == *ptr) + { + n += escape_char; + break; + } + ++ptr; + } + n += *str; + ++str; + } + } + } + return n; +} + +// convert windows slashes to unix slashes +void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path) +{ + const char* pathCString = path.c_str(); + bool hasDoubleSlash = false; + + const char* pos0 = pathCString; + const char* pos1 = pathCString+1; + for (kwsys_stl::string::size_type pos = 0; *pos0; ++ pos ) + { + // make sure we don't convert an escaped space to a unix slash + if ( *pos0 == '\\' && *pos1 != ' ' ) + { + path[pos] = '/'; + } + + // Also, reuse the loop to check for slash followed by another slash + if ( !hasDoubleSlash && *pos1 && + *pos1 == '/' && *(pos1+1) == '/' ) + { +#ifdef _WIN32 + // However, on windows if the first characters are both slashes, + // then keep them that way, so that network paths can be handled. + if ( pos > 0) + { + hasDoubleSlash = true; + } +#else + hasDoubleSlash = true; +#endif + } + + pos0 ++; + pos1 ++; + } + + if ( hasDoubleSlash ) + { + SystemTools::ReplaceString(path, "//", "/"); + } + + // remove any trailing slash + if(!path.empty()) + { + // if there is a tilda ~ then replace it with HOME + pathCString = path.c_str(); + if(*pathCString == '~') + { + const char* homeEnv = SystemTools::GetEnv("HOME"); + if (homeEnv) + { + path.replace(0,1,homeEnv); + } + } + + pathCString = path.c_str(); + if (*(pathCString+(path.size()-1)) == '/') + { + path = path.substr(0, path.size()-1); + } + + } +} + +// change // to /, and escape any spaces in the path +kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path) +{ + kwsys_stl::string ret = path; + + // remove // except at the beginning might be a cygwin drive + kwsys_stl::string::size_type pos=0; + while((pos = ret.find("//", pos)) != kwsys_stl::string::npos) + { + ret.erase(pos, 1); + } + // now escape spaces if there is a space in the path + if(ret.find(" ") != kwsys_stl::string::npos) + { + kwsys_stl::string result = ""; + char lastch = 1; + for(const char* ch = ret.c_str(); *ch != '\0'; ++ch) + { + // if it is already escaped then don't try to escape it again + if(*ch == ' ' && lastch != '\\') + { + result += '\\'; + } + result += *ch; + lastch = *ch; + } + ret = result; + } + return ret; +} + +kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + return SystemTools::ConvertToWindowsOutputPath(path); +#else + return SystemTools::ConvertToUnixOutputPath(path); +#endif +} + +// remove double slashes not at the start +kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path) +{ + kwsys_stl::string ret; + // make it big enough for all of path and double quotes + ret.reserve(strlen(path)+3); + // put path into the string + ret.insert(0,path); + kwsys_stl::string::size_type pos = 0; + // first convert all of the slashes + while((pos = ret.find('/', pos)) != kwsys_stl::string::npos) + { + ret[pos] = '\\'; + pos++; + } + // check for really small paths + if(ret.size() < 2) + { + return ret; + } + // now clean up a bit and remove double slashes + // Only if it is not the first position in the path which is a network + // path on windows + pos = 1; // start at position 1 + if(ret[0] == '\"') + { + pos = 2; // if the string is already quoted then start at 2 + if(ret.size() < 3) + { + return ret; + } + } + while((pos = ret.find("\\\\", pos)) != kwsys_stl::string::npos) + { + ret.erase(pos, 1); + } + // now double quote the path if it has spaces in it + // and is not already double quoted + if(ret.find(' ') != kwsys_stl::string::npos + && ret[0] != '\"') + { + ret.insert(static_cast(0), + static_cast(1), '\"'); + ret.append(1, '\"'); + } + return ret; +} + +bool SystemTools::CopyFileIfDifferent(const char* source, + const char* destination) +{ + if(SystemTools::FilesDiffer(source, destination)) + { + return SystemTools::CopyFileAlways(source, destination); + } + return true; +} + + +bool SystemTools::FilesDiffer(const char* source, + const char* destination) +{ + struct stat statSource; + if (stat(source, &statSource) != 0) + { + return true; + } + + struct stat statDestination; + if (stat(destination, &statDestination) != 0) + { + return true; + } + + if(statSource.st_size != statDestination.st_size) + { + return true; + } + + if(statSource.st_size == 0) + { + return false; + } + +#if defined(_WIN32) || defined(__CYGWIN__) + kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary | + kwsys_ios::ios::in)); + kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary | + kwsys_ios::ios::in)); +#else + kwsys_ios::ifstream finSource(source); + kwsys_ios::ifstream finDestination(destination); +#endif + if(!finSource || !finDestination) + { + return true; + } + + char* source_buf = new char[statSource.st_size]; + char* dest_buf = new char[statSource.st_size]; + + finSource.read(source_buf, statSource.st_size); + finDestination.read(dest_buf, statSource.st_size); + + if(statSource.st_size != static_cast(finSource.gcount()) || + statSource.st_size != static_cast(finDestination.gcount())) + { + // Failed to read files. + delete [] source_buf; + delete [] dest_buf; + return true; + } + int ret = memcmp((const void*)source_buf, + (const void*)dest_buf, + statSource.st_size); + + delete [] dest_buf; + delete [] source_buf; + + return ret != 0; +} + + +/** + * Copy a file named by "source" to the file named by "destination". + */ +bool SystemTools::CopyFileAlways(const char* source, const char* destination) +{ + // If files are the same do not copy + if ( SystemTools::SameFile(source, destination) ) + { + return true; + } + + mode_t perm = 0; + bool perms = SystemTools::GetPermissions(source, perm); + + const int bufferSize = 4096; + char buffer[bufferSize]; + + // If destination is a directory, try to create a file with the same + // name as the source in that directory. + + kwsys_stl::string new_destination; + if(SystemTools::FileExists(destination) && + SystemTools::FileIsDirectory(destination)) + { + new_destination = destination; + SystemTools::ConvertToUnixSlashes(new_destination); + new_destination += '/'; + kwsys_stl::string source_name = source; + new_destination += SystemTools::GetFilenameName(source_name); + destination = new_destination.c_str(); + } + + // Create destination directory + + kwsys_stl::string destination_dir = destination; + destination_dir = SystemTools::GetFilenamePath(destination_dir); + SystemTools::MakeDirectory(destination_dir.c_str()); + + // Open files + +#if defined(_WIN32) || defined(__CYGWIN__) + kwsys_ios::ifstream fin(source, + kwsys_ios::ios::binary | kwsys_ios::ios::in); +#else + kwsys_ios::ifstream fin(source); +#endif + if(!fin) + { + return false; + } + + // try and remove the destination file so that read only destination files + // can be written to. + // If the remove fails continue so that files in read only directories + // that do not allow file removal can be modified. + SystemTools::RemoveFile(destination); + +#if defined(_WIN32) || defined(__CYGWIN__) + kwsys_ios::ofstream fout(destination, + kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc); +#else + kwsys_ios::ofstream fout(destination, + kwsys_ios::ios::out | kwsys_ios::ios::trunc); +#endif + if(!fout) + { + return false; + } + + // This copy loop is very sensitive on certain platforms with + // slightly broken stream libraries (like HPUX). Normally, it is + // incorrect to not check the error condition on the fin.read() + // before using the data, but the fin.gcount() will be zero if an + // error occurred. Therefore, the loop should be safe everywhere. + while(fin) + { + fin.read(buffer, bufferSize); + if(fin.gcount()) + { + fout.write(buffer, fin.gcount()); + } + } + + // Make sure the operating system has finished writing the file + // before closing it. This will ensure the file is finished before + // the check below. + fout.flush(); + + fin.close(); + fout.close(); + + // More checks. + struct stat statSource, statDestination; + statSource.st_size = 12345; + statDestination.st_size = 12345; + if(stat(source, &statSource) != 0) + { + return false; + } + else if(stat(destination, &statDestination) != 0) + { + return false; + } + else if(statSource.st_size != statDestination.st_size) + { + return false; + } + if ( perms ) + { + if ( !SystemTools::SetPermissions(destination, perm) ) + { + return false; + } + } + return true; +} + +/** + * Copy a directory content from "source" directory to the directory named by + * "destination". + */ +bool SystemTools::CopyADirectory(const char* source, const char* destination) +{ + Directory dir; + dir.Load(source); + size_t fileNum; + if ( !SystemTools::MakeDirectory(destination) ) + { + return false; + } + for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) + { + if (strcmp(dir.GetFile(static_cast(fileNum)),".") && + strcmp(dir.GetFile(static_cast(fileNum)),"..")) + { + kwsys_stl::string fullPath = source; + fullPath += "/"; + fullPath += dir.GetFile(static_cast(fileNum)); + if(SystemTools::FileIsDirectory(fullPath.c_str())) + { + kwsys_stl::string fullDestPath = destination; + fullDestPath += "/"; + fullDestPath += dir.GetFile(static_cast(fileNum)); + if (!SystemTools::CopyADirectory(fullPath.c_str(), fullDestPath.c_str())) + { + return false; + } + } + else + { + if(!SystemTools::CopyFileAlways(fullPath.c_str(), destination)) + { + return false; + } + } + } + } + + return true; +} + + +// return size of file; also returns zero if no file exists +unsigned long SystemTools::FileLength(const char* filename) +{ + struct stat fs; + if (stat(filename, &fs) != 0) + { + return 0; + } + else + { + return static_cast(fs.st_size); + } +} + +int SystemTools::Strucmp(const char *s1, const char *s2) +{ +// lifted from Graphvis http://www.graphviz.org + while ((*s1 != '\0') + && (tolower(*s1) == tolower(*s2))) + { + s1++; + s2++; + } + + return tolower(*s1) - tolower(*s2); + +} + +// return file's modified time +long int SystemTools::ModifiedTime(const char* filename) +{ + struct stat fs; + if (stat(filename, &fs) != 0) + { + return 0; + } + else + { + return (long int)fs.st_mtime; + } +} + +// return file's creation time +long int SystemTools::CreationTime(const char* filename) +{ + struct stat fs; + if (stat(filename, &fs) != 0) + { + return 0; + } + else + { + return fs.st_ctime >= 0 ? (long int)fs.st_ctime : 0; + } +} + +bool SystemTools::ConvertDateMacroString(const char *str, time_t *tmt) +{ + if (!str || !tmt || strlen(str) < 12) + { + return false; + } + + struct tm tmt2; + + // __DATE__ + // The compilation date of the current source file. The date is a string + // literal of the form Mmm dd yyyy. The month name Mmm is the same as for + // dates generated by the library function asctime declared in TIME.H. + + // index: 012345678901 + // format: Mmm dd yyyy + // example: Dec 19 2003 + + static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + char buffer[12]; + strcpy(buffer, str); + + buffer[3] = 0; + char *ptr = strstr(month_names, buffer); + if (!ptr) + { + return false; + } + + int month = (ptr - month_names) / 3; + int day = atoi(buffer + 4); + int year = atoi(buffer + 7); + + tmt2.tm_isdst = -1; + tmt2.tm_hour = 0; + tmt2.tm_min = 0; + tmt2.tm_sec = 0; + tmt2.tm_wday = 0; + tmt2.tm_yday = 0; + tmt2.tm_mday = day; + tmt2.tm_mon = month; + tmt2.tm_year = year - 1900; + + *tmt = mktime(&tmt2); + return true; +} + +bool SystemTools::ConvertTimeStampMacroString(const char *str, time_t *tmt) +{ + if (!str || !tmt || strlen(str) < 27) + { + return false; + } + + struct tm tmt2; + + // __TIMESTAMP__ + // The date and time of the last modification of the current source file, + // expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy, + /// where Ddd is the abbreviated day of the week and Date is an integer + // from 1 to 31. + + // index: 0123456789 + // 0123456789 + // 0123456789 + // format: Ddd Mmm Date hh:mm:ss yyyy + // example: Fri Dec 19 14:34:58 2003 + + static char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + char buffer[27]; + strcpy(buffer, str); + + buffer[7] = 0; + char *ptr = strstr(month_names, buffer + 4); + if (!ptr) + { + return false; + } + + int month = (ptr - month_names) / 3; + int day = atoi(buffer + 8); + int hour = atoi(buffer + 11); + int min = atoi(buffer + 14); + int sec = atoi(buffer + 17); + int year = atoi(buffer + 20); + + tmt2.tm_isdst = -1; + tmt2.tm_hour = hour; + tmt2.tm_min = min; + tmt2.tm_sec = sec; + tmt2.tm_wday = 0; + tmt2.tm_yday = 0; + tmt2.tm_mday = day; + tmt2.tm_mon = month; + tmt2.tm_year = year - 1900; + + *tmt = mktime(&tmt2); + return true; +} + +kwsys_stl::string SystemTools::GetLastSystemError() +{ + int e = errno; + return strerror(e); +} + +bool SystemTools::RemoveFile(const char* source) +{ +#ifdef _WIN32 + mode_t mode; + if ( !SystemTools::GetPermissions(source, mode) ) + { + return false; + } + /* Win32 unlink is stupid --- it fails if the file is read-only */ + SystemTools::SetPermissions(source, S_IWRITE); +#endif + bool res = unlink(source) != 0 ? false : true; +#ifdef _WIN32 + if ( !res ) + { + SystemTools::SetPermissions(source, mode); + } +#endif + return res; +} + +bool SystemTools::RemoveADirectory(const char* source) +{ + Directory dir; + dir.Load(source); + size_t fileNum; + for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) + { + if (strcmp(dir.GetFile(static_cast(fileNum)),".") && + strcmp(dir.GetFile(static_cast(fileNum)),"..")) + { + kwsys_stl::string fullPath = source; + fullPath += "/"; + fullPath += dir.GetFile(static_cast(fileNum)); + if(SystemTools::FileIsDirectory(fullPath.c_str()) && + !SystemTools::FileIsSymlink(fullPath.c_str())) + { + if (!SystemTools::RemoveADirectory(fullPath.c_str())) + { + return false; + } + } + else + { + if(!SystemTools::RemoveFile(fullPath.c_str())) + { + return false; + } + } + } + } + + return (Rmdir(source) == 0); +} + +/** + * Find the file the given name. Searches the given path and then + * the system search path. Returns the full path to the file if it is + * found. Otherwise, the empty string is returned. + */ +kwsys_stl::string SystemTools +::FindFile(const char* name, + const kwsys_stl::vector& userPaths) +{ + // Add the system search path to our path first + kwsys_stl::vector path; + SystemTools::GetPath(path, "CMAKE_FILE_PATH"); + SystemTools::GetPath(path); + // now add the additional paths + path.insert(path.end(), userPaths.begin(), userPaths.end()); + // now look for the file + kwsys_stl::string tryPath; + for(kwsys_stl::vector::const_iterator p = path.begin(); + p != path.end(); ++p) + { + tryPath = *p; + tryPath += "/"; + tryPath += name; + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + } + // Couldn't find the file. + return ""; +} + +/** + * Find the executable with the given name. Searches the given path and then + * the system search path. Returns the full path to the executable if it is + * found. Otherwise, the empty string is returned. + */ +kwsys_stl::string SystemTools::FindProgram( + const char* name, + const kwsys_stl::vector& userPaths, + bool no_system_path) +{ + if(!name) + { + return ""; + } + // See if the executable exists as written. + if(SystemTools::FileExists(name) && + !SystemTools::FileIsDirectory(name)) + { + return SystemTools::CollapseFullPath(name); + } + kwsys_stl::string tryPath = name; + tryPath += SystemTools::GetExecutableExtension(); + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + kwsys_stl::vector path; + SystemTools::GetPath(path, "CMAKE_PROGRAM_PATH"); + // Add the system search path to our path. + if (!no_system_path) + { + SystemTools::GetPath(path); + } + + // now add the additional paths + path.insert(path.end(), userPaths.begin(), userPaths.end()); + + for(kwsys_stl::vector::const_iterator p = path.begin(); + p != path.end(); ++p) + { + tryPath = *p; + tryPath += "/"; + tryPath += name; + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } +#ifdef _WIN32 + tryPath += ".com"; + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/"; + tryPath += name; +#endif + tryPath += SystemTools::GetExecutableExtension(); + if(SystemTools::FileExists(tryPath.c_str()) && + !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + } + + // Couldn't find the program. + return ""; +} + + +/** + * Find the library with the given name. Searches the given path and then + * the system search path. Returns the full path to the library if it is + * found. Otherwise, the empty string is returned. + */ +kwsys_stl::string SystemTools +::FindLibrary(const char* name, + const kwsys_stl::vector& userPaths) +{ + // See if the executable exists as written. + if(SystemTools::FileExists(name) && + !SystemTools::FileIsDirectory(name)) + { + return SystemTools::CollapseFullPath(name); + } + + // Add the system search path to our path. + kwsys_stl::vector path; + SystemTools::GetPath(path); + // now add the additional paths + path.insert(path.end(), userPaths.begin(), userPaths.end()); + kwsys_stl::string tryPath; + for(kwsys_stl::vector::const_iterator p = path.begin(); + p != path.end(); ++p) + { +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) + tryPath = *p; + tryPath += "/"; + tryPath += name; + tryPath += ".lib"; + if(SystemTools::FileExists(tryPath.c_str()) + && !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } +#else + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".so"; + if(SystemTools::FileExists(tryPath.c_str()) + && !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".a"; + if(SystemTools::FileExists(tryPath.c_str()) + && !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".sl"; + if(SystemTools::FileExists(tryPath.c_str()) + && !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".dylib"; + if(SystemTools::FileExists(tryPath.c_str()) + && !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath = *p; + tryPath += "/lib"; + tryPath += name; + tryPath += ".dll"; + if(SystemTools::FileExists(tryPath.c_str()) + && !SystemTools::FileIsDirectory(tryPath.c_str())) + { + return SystemTools::CollapseFullPath(tryPath.c_str()); + } +#endif + } + + // Couldn't find the library. + return ""; +} + +bool SystemTools::FileIsDirectory(const char* name) +{ + struct stat fs; + if(stat(name, &fs) == 0) + { +#if _WIN32 + return ((fs.st_mode & _S_IFDIR) != 0); +#else + return S_ISDIR(fs.st_mode); +#endif + } + else + { + return false; + } +} + +bool SystemTools::FileIsSymlink(const char* name) +{ +#if _WIN32 + (void)name; + return false; +#else + struct stat fs; + if(lstat(name, &fs) == 0) + { + return S_ISLNK(fs.st_mode); + } + else + { + return false; + } +#endif +} + +int SystemTools::ChangeDirectory(const char *dir) +{ + return Chdir(dir); +} + +kwsys_stl::string SystemTools::GetCurrentWorkingDirectory(bool collapse) +{ + char buf[2048]; + const char* cwd = Getcwd(buf, 2048); + kwsys_stl::string path; + if ( cwd ) + { + path = cwd; + } + if(collapse) + { + return SystemTools::CollapseFullPath(path.c_str()); + } + return path; +} + +kwsys_stl::string SystemTools::GetProgramPath(const char* in_name) +{ + kwsys_stl::string dir, file; + SystemTools::SplitProgramPath(in_name, dir, file); + return dir; +} + +bool SystemTools::SplitProgramPath(const char* in_name, + kwsys_stl::string& dir, + kwsys_stl::string& file, + bool) +{ + dir = in_name; + file = ""; + SystemTools::ConvertToUnixSlashes(dir); + + if(!SystemTools::FileIsDirectory(dir.c_str())) + { + kwsys_stl::string::size_type slashPos = dir.rfind("/"); + if(slashPos != kwsys_stl::string::npos) + { + file = dir.substr(slashPos+1); + dir = dir.substr(0, slashPos); + } + else + { + file = dir; + dir = ""; + } + } + if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str())) + { + kwsys_stl::string oldDir = in_name; + SystemTools::ConvertToUnixSlashes(oldDir); + dir = in_name; + return false; + } + return true; +} + +bool SystemTools::FindProgramPath(const char* argv0, + kwsys_stl::string& pathOut, + kwsys_stl::string& errorMsg, + const char* exeName, + const char* buildDir, + const char* installPrefix ) +{ + kwsys_stl::vector failures; + kwsys_stl::string self = argv0; + SystemTools::ConvertToUnixSlashes(self); + failures.push_back(argv0); + self = SystemTools::FindProgram(self.c_str()); + if(!SystemTools::FileExists(self.c_str())) + { + if(buildDir) + { + kwsys_stl::string intdir = "."; +#ifdef CMAKE_INTDIR + intdir = CMAKE_INTDIR; +#endif + self = buildDir; + self += "/bin/"; + self += intdir; + self += "/"; + self += exeName; + self += SystemTools::GetExecutableExtension(); + } + } + if(installPrefix) + { + if(!SystemTools::FileExists(self.c_str())) + { + failures.push_back(self); + self = installPrefix; + self += "/bin/"; + self += exeName; + } + } + if(!SystemTools::FileExists(self.c_str())) + { + failures.push_back(self); + kwsys_ios::ostringstream msg; + msg << "Can not find the command line program " << exeName << "\n"; + msg << " argv[0] = \"" << argv0 << "\"\n"; + msg << " Attempted paths:\n"; + kwsys_stl::vector::iterator i; + for(i=failures.begin(); i != failures.end(); ++i) + { + msg << " \"" << i->c_str() << "\"\n"; + } + errorMsg = msg.str(); + return false; + } + pathOut = self; + return true; +} + + +kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative) +{ + return SystemTools::CollapseFullPath(in_relative, 0); +} + +void SystemTools::AddTranslationPath(const char * a, const char * b) +{ + kwsys_stl::string path_a = a; + kwsys_stl::string path_b = b; + SystemTools::ConvertToUnixSlashes(path_a); + SystemTools::ConvertToUnixSlashes(path_b); + // First check this is a directory path, since we don't want the table to + // grow too fat + if( SystemTools::FileIsDirectory( path_a.c_str() ) ) + { + // Make sure the path is a full path and does not contain no '..' + if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..") + == kwsys_stl::string::npos ) + { + // Before inserting make sure path ends with '/' + if(path_a.size() && path_a[path_a.size() -1] != '/') + { + path_a += '/'; + } + if(path_b.size() && path_b[path_b.size() -1] != '/') + { + path_b += '/'; + } + if( !(path_a == path_b) ) + { + SystemTools::TranslationMap->insert( + SystemToolsTranslationMap::value_type(path_a, path_b)); + } + } + } +} + +void SystemTools::AddKeepPath(const char* dir) +{ + kwsys_stl::string cdir = SystemTools::CollapseFullPath(dir); + SystemTools::AddTranslationPath(cdir.c_str(), dir); +} + +void SystemTools::CheckTranslationPath(kwsys_stl::string & path) +{ + // Do not translate paths that are too short to have meaningful + // translations. + if(path.size() < 2) + { + return; + } + + // Always add a trailing slash before translation. It does not + // matter if this adds an extra slash, but we do not want to + // translate part of a directory (like the foo part of foo-dir). + path += "/"; + + // In case a file was specified we still have to go through this: + // Now convert any path found in the table back to the one desired: + kwsys_stl::map::const_iterator it; + for(it = SystemTools::TranslationMap->begin(); + it != SystemTools::TranslationMap->end(); + ++it ) + { + // We need to check of the path is a substring of the other path + if(path.find( it->first ) == 0) + { + path = path.replace( 0, it->first.size(), it->second); + } + } + + // Remove the trailing slash we added before. + path.erase(path.end()-1, path.end()); +} + +void +SystemToolsAppendComponents( + kwsys_stl::vector& out_components, + kwsys_stl::vector::const_iterator first, + kwsys_stl::vector::const_iterator last) +{ + for(kwsys_stl::vector::const_iterator i = first; + i != last; ++i) + { + if(*i == "..") + { + if(out_components.begin() != out_components.end()) + { + out_components.erase(out_components.end()-1, out_components.end()); + } + } + else if(!(*i == ".") && !(*i == "")) + { + out_components.push_back(*i); + } + } +} + +kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path, + const char* in_base) +{ + // Collect the output path components. + kwsys_stl::vector out_components; + + // Split the input path components. + kwsys_stl::vector path_components; + SystemTools::SplitPath(in_path, path_components); + + // If the input path is relative, start with a base path. + if(path_components[0].length() == 0) + { + kwsys_stl::vector base_components; + if(in_base) + { + // Use the given base path. + SystemTools::SplitPath(in_base, base_components); + } + else + { + // Use the current working directory as a base path. + char buf[2048]; + if(const char* cwd = Getcwd(buf, 2048)) + { + SystemTools::SplitPath(cwd, base_components); + } + else + { + // ?? + } + } + + // Append base path components to the output path. + out_components.push_back(base_components[0]); + SystemToolsAppendComponents(out_components, + base_components.begin()+1, + base_components.end()); + } + + // Append input path components to the output path. + SystemToolsAppendComponents(out_components, + path_components.begin(), + path_components.end()); + + // Transform the path back to a string. + kwsys_stl::string newPath = SystemTools::JoinPath(out_components); + + // Update the translation table with this potentially new path. + SystemTools::AddTranslationPath(newPath.c_str(), in_path); + SystemTools::CheckTranslationPath(newPath); +#ifdef _WIN32 + newPath = SystemTools::GetActualCaseForPath(newPath.c_str()); +#endif + // Return the reconstructed path. + return newPath; +} + +// compute the relative path from here to there +kwsys_stl::string SystemTools::RelativePath(const char* local, const char* remote) +{ + if(!SystemTools::FileIsFullPath(local)) + { + return ""; + } + if(!SystemTools::FileIsFullPath(remote)) + { + return ""; + } + + // split up both paths into arrays of strings using / as a separator + kwsys_stl::vector localSplit = SystemTools::SplitString(local, '/', true); + kwsys_stl::vector remoteSplit = SystemTools::SplitString(remote, '/', true); + kwsys_stl::vector commonPath; // store shared parts of path in this array + kwsys_stl::vector finalPath; // store the final relative path here + // count up how many matching directory names there are from the start + unsigned int sameCount = 0; + while( + ((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1))) + && +// for windows and apple do a case insensitive string compare +#if defined(_WIN32) || defined(__APPLE__) + SystemTools::Strucmp(localSplit[sameCount].c_str(), + remoteSplit[sameCount].c_str()) == 0 +#else + localSplit[sameCount] == remoteSplit[sameCount] +#endif + ) + { + // put the common parts of the path into the commonPath array + commonPath.push_back(localSplit[sameCount]); + // erase the common parts of the path from the original path arrays + localSplit[sameCount] = ""; + remoteSplit[sameCount] = ""; + sameCount++; + } + +#if 0 + // NOTE: We did this at one time to prevent relative paths to the + // compiler from looking like "../../../../../../../usr/bin/gcc". + // Now however relative paths are only computed for destinations + // inside the build tree so this is not a problem. This is now a + // general-purpose method and should not have this hack. I'm + // leaving it in place in case removing it causes a problem so it is + // easy to restore: + // + // If there is nothing in common but the root directory, then just + // return the full path. + if(sameCount <= 1) + { + return remote; + } +#endif + + // for each entry that is not common in the local path + // add a ../ to the finalpath array, this gets us out of the local + // path into the remote dir + for(unsigned int i = 0; i < localSplit.size(); ++i) + { + if(localSplit[i].size()) + { + finalPath.push_back("../"); + } + } + // for each entry that is not common in the remote path add it + // to the final path. + for(kwsys_stl::vector::iterator vit = remoteSplit.begin(); + vit != remoteSplit.end(); ++vit) + { + if(vit->size()) + { + finalPath.push_back(*vit); + } + } + kwsys_stl::string relativePath; // result string + // now turn the array of directories into a unix path by puttint / + // between each entry that does not already have one + for(kwsys_stl::vector::iterator vit1 = finalPath.begin(); + vit1 != finalPath.end(); ++vit1) + { + if(relativePath.size() && relativePath[relativePath.size()-1] != '/') + { + relativePath += "/"; + } + relativePath += *vit1; + } + return relativePath; +} + +// OK, some fun stuff to get the actual case of a given path. +// Basically, you just need to call ShortPath, then GetLongPathName, +// However, GetLongPathName is not implemented on windows NT and 95, +// so we have to simulate it on those versions +#ifdef _WIN32 +int OldWindowsGetLongPath(kwsys_stl::string const& shortPath, + kwsys_stl::string& longPath ) +{ + kwsys_stl::string::size_type iFound = shortPath.rfind('/'); + if (iFound > 1 && iFound != shortPath.npos) + { + // recurse to peel off components + // + if (OldWindowsGetLongPath(shortPath.substr(0, iFound), longPath) > 0) + { + longPath += '/'; + if (shortPath[1] != '/') + { + WIN32_FIND_DATA findData; + + // append the long component name to the path + // + if (INVALID_HANDLE_VALUE != ::FindFirstFile + (shortPath.c_str(), &findData)) + { + longPath += findData.cFileName; + } + else + { + // if FindFirstFile fails, return the error code + // + longPath = ""; + return 0; + } + } + } + } + else + { + longPath = shortPath; + } + return longPath.size(); +} + + +int PortableGetLongPathName(const char* pathIn, + kwsys_stl::string & longPath) +{ + kwsys_stl::string shortPath; + if(!SystemTools::GetShortPath(pathIn, shortPath)) + { + return 0; + } + HMODULE lh = LoadLibrary("Kernel32.dll"); + if(lh) + { + FARPROC proc = GetProcAddress(lh, "GetLongPathNameA"); + if(proc) + { + typedef DWORD (WINAPI * GetLongFunctionPtr) (LPCSTR,LPSTR,DWORD); + GetLongFunctionPtr func = (GetLongFunctionPtr)proc; + char buffer[MAX_PATH+1]; + int len = (*func)(shortPath.c_str(), buffer, MAX_PATH+1); + if(len == 0 || len > MAX_PATH+1) + { + FreeLibrary(lh); + return 0; + } + longPath = buffer; + FreeLibrary(lh); + return len; + } + FreeLibrary(lh); + } + return OldWindowsGetLongPath(shortPath.c_str(), longPath); +} +#endif + + +//---------------------------------------------------------------------------- +kwsys_stl::string SystemTools::GetActualCaseForPath(const char* p) +{ +#ifndef _WIN32 + return p; +#else + kwsys_stl::string shortPath; + if(!SystemTools::GetShortPath(p, shortPath)) + { + return p; + } + kwsys_stl::string longPath; + int len = PortableGetLongPathName(shortPath.c_str(), longPath); + if(len == 0 || len > MAX_PATH+1) + { + return p; + } + return longPath; +#endif +} + +//---------------------------------------------------------------------------- +void SystemTools::SplitPath(const char* p, + kwsys_stl::vector& components) +{ + components.clear(); + // Identify the root component. + const char* c = p; + if((c[0] == '/' && c[1] == '/') || (c[0] == '\\' && c[1] == '\\')) + { + // Network path. + components.push_back("//"); + c += 2; + } + else if(c[0] == '/') + { + // Unix path. + components.push_back("/"); + c += 1; + } + else if(c[0] && c[1] == ':' && (c[2] == '/' || c[2] == '\\')) + { + // Windows path. + kwsys_stl::string root = "_:/"; + root[0] = c[0]; + components.push_back(root); + c += 3; + } + else if(c[0] && c[1] == ':') + { + // Path relative to a windows drive working directory. + kwsys_stl::string root = "_:"; + root[0] = c[0]; + components.push_back(root); + c += 2; + } + else + { + // Relative path. + components.push_back(""); + } + + // Parse the remaining components. + const char* first = c; + const char* last = first; + for(;*last; ++last) + { + if(*last == '/' || *last == '\\') + { + // End of a component. Save it. + components.push_back(kwsys_stl::string(first, last-first)); + first = last+1; + } + } + + // Save the last component unless there were no components. + if(last != c) + { + components.push_back(kwsys_stl::string(first, last-first)); + } +} + +//---------------------------------------------------------------------------- +kwsys_stl::string +SystemTools::JoinPath(const kwsys_stl::vector& components) +{ + kwsys_stl::string result; + if(components.size() > 0) + { + result += components[0]; + } + if(components.size() > 1) + { + result += components[1]; + } + for(unsigned int i=2; i < components.size(); ++i) + { + result += "/"; + result += components[i]; + } + return result; +} + +//---------------------------------------------------------------------------- +bool SystemTools::ComparePath(const char* c1, const char* c2) +{ +#if defined(_WIN32) || defined(__APPLE__) + return SystemTools::Strucmp(c1, c2) == 0; +#else + return strcmp(c1, c2) == 0; +#endif +} + +//---------------------------------------------------------------------------- +bool SystemTools::Split(const char* str, kwsys_stl::vector& lines, char separator) +{ + kwsys_stl::string data(str); + kwsys_stl::string::size_type lpos = 0; + while(lpos < data.length()) + { + kwsys_stl::string::size_type rpos = data.find_first_of(separator, lpos); + if(rpos == kwsys_stl::string::npos) + { + // Line ends at end of string without a newline. + lines.push_back(data.substr(lpos)); + return false; + } + else + { + // Line ends in a "\n", remove the character. + lines.push_back(data.substr(lpos, rpos-lpos)); + } + lpos = rpos+1; + } + return true; +} + +//---------------------------------------------------------------------------- +bool SystemTools::Split(const char* str, kwsys_stl::vector& lines) +{ + kwsys_stl::string data(str); + kwsys_stl::string::size_type lpos = 0; + while(lpos < data.length()) + { + kwsys_stl::string::size_type rpos = data.find_first_of("\n", lpos); + if(rpos == kwsys_stl::string::npos) + { + // Line ends at end of string without a newline. + lines.push_back(data.substr(lpos)); + return false; + } + if((rpos > lpos) && (data[rpos-1] == '\r')) + { + // Line ends in a "\r\n" pair, remove both characters. + lines.push_back(data.substr(lpos, (rpos-1)-lpos)); + } + else + { + // Line ends in a "\n", remove the character. + lines.push_back(data.substr(lpos, rpos-lpos)); + } + lpos = rpos+1; + } + return true; +} + +/** + * Return path of a full filename (no trailing slashes). + * Warning: returned path is converted to Unix slashes format. + */ +kwsys_stl::string SystemTools::GetFilenamePath(const kwsys_stl::string& filename) +{ + kwsys_stl::string fn = filename; + SystemTools::ConvertToUnixSlashes(fn); + + kwsys_stl::string::size_type slash_pos = fn.rfind("/"); + if(slash_pos != kwsys_stl::string::npos) + { + return fn.substr(0, slash_pos); + } + else + { + return ""; + } +} + + +/** + * Return file name of a full filename (i.e. file name without path). + */ +kwsys_stl::string SystemTools::GetFilenameName(const kwsys_stl::string& filename) +{ +#if defined(_WIN32) + kwsys_stl::string::size_type slash_pos = filename.find_last_of("/\\"); +#else + kwsys_stl::string::size_type slash_pos = filename.find_last_of("/"); +#endif + if(slash_pos != kwsys_stl::string::npos) + { + return filename.substr(slash_pos + 1); + } + else + { + return filename; + } +} + + +/** + * Return file extension of a full filename (dot included). + * Warning: this is the longest extension (for example: .tar.gz) + */ +kwsys_stl::string SystemTools::GetFilenameExtension(const kwsys_stl::string& filename) +{ + kwsys_stl::string name = SystemTools::GetFilenameName(filename); + kwsys_stl::string::size_type dot_pos = name.find("."); + if(dot_pos != kwsys_stl::string::npos) + { + return name.substr(dot_pos); + } + else + { + return ""; + } +} + +/** + * Return file extension of a full filename (dot included). + * Warning: this is the shortest extension (for example: .tar.gz) + */ +kwsys_stl::string SystemTools::GetFilenameLastExtension(const kwsys_stl::string& filename) +{ + kwsys_stl::string name = SystemTools::GetFilenameName(filename); + kwsys_stl::string::size_type dot_pos = name.rfind("."); + if(dot_pos != kwsys_stl::string::npos) + { + return name.substr(dot_pos); + } + else + { + return ""; + } +} + +/** + * Return file name without extension of a full filename (i.e. without path). + * Warning: it considers the longest extension (for example: .tar.gz) + */ +kwsys_stl::string SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string& filename) +{ + kwsys_stl::string name = SystemTools::GetFilenameName(filename); + kwsys_stl::string::size_type dot_pos = name.find("."); + if(dot_pos != kwsys_stl::string::npos) + { + return name.substr(0, dot_pos); + } + else + { + return name; + } +} + + +/** + * Return file name without extension of a full filename (i.e. without path). + * Warning: it considers the last extension (for example: removes .gz + * from .tar.gz) + */ +kwsys_stl::string +SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string& filename) +{ + kwsys_stl::string name = SystemTools::GetFilenameName(filename); + kwsys_stl::string::size_type dot_pos = name.rfind("."); + if(dot_pos != kwsys_stl::string::npos) + { + return name.substr(0, dot_pos); + } + else + { + return name; + } +} + +bool SystemTools::FileHasSignature(const char *filename, + const char *signature, + long offset) +{ + if (!filename || !signature) + { + return false; + } + + FILE *fp; + fp = fopen(filename, "rb"); + if (!fp) + { + return false; + } + + fseek(fp, offset, SEEK_SET); + + bool res = false; + size_t signature_len = strlen(signature); + char *buffer = new char [signature_len]; + + if (fread(buffer, 1, signature_len, fp) == signature_len) + { + res = (!strncmp(buffer, signature, signature_len) ? true : false); + } + + delete [] buffer; + + fclose(fp); + return res; +} + +SystemTools::FileTypeEnum +SystemTools::DetectFileType(const char *filename, + unsigned long length, + double percent_bin) +{ + if (!filename || percent_bin < 0) + { + return SystemTools::FileTypeUnknown; + } + + FILE *fp; + fp = fopen(filename, "rb"); + if (!fp) + { + return SystemTools::FileTypeUnknown; + } + + // Allocate buffer and read bytes + + unsigned char *buffer = new unsigned char [length]; + size_t read_length = fread(buffer, 1, length, fp); + fclose(fp); + if (read_length == 0) + { + return SystemTools::FileTypeUnknown; + } + + // Loop over contents and count + + size_t text_count = 0; + + const unsigned char *ptr = buffer; + const unsigned char *buffer_end = buffer + read_length; + + while (ptr != buffer_end) + { + if ((*ptr >= 0x20 && *ptr <= 0x7F) || + *ptr == '\n' || + *ptr == '\r' || + *ptr == '\t') + { + text_count++; + } + ptr++; + } + + delete [] buffer; + + double current_percent_bin = + ((double)(read_length - text_count) / (double)read_length); + + if (current_percent_bin >= percent_bin) + { + return SystemTools::FileTypeBinary; + } + + return SystemTools::FileTypeText; +} + +bool SystemTools::LocateFileInDir(const char *filename, + const char *dir, + kwsys_stl::string& filename_found, + int try_filename_dirs) +{ + if (!filename || !dir) + { + return false; + } + + // Get the basename of 'filename' + + kwsys_stl::string filename_base = SystemTools::GetFilenameName(filename); + + // Check if 'dir' is really a directory + // If win32 and matches something like C:, accept it as a dir + + kwsys_stl::string real_dir; + if (!SystemTools::FileIsDirectory(dir)) + { +#if _WIN32 + size_t dir_len = strlen(dir); + if (dir_len < 2 || dir[dir_len - 1] != ':') + { +#endif + real_dir = SystemTools::GetFilenamePath(dir); + dir = real_dir.c_str(); +#if _WIN32 + } +#endif + } + + // Try to find the file in 'dir' + + bool res = false; + if (filename_base.size() && dir) + { + size_t dir_len = strlen(dir); + int need_slash = + (dir_len && dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\'); + + kwsys_stl::string temp = dir; + if (need_slash) + { + temp += "/"; + } + temp += filename_base; + + if (SystemTools::FileExists(filename_found.c_str())) + { + res = true; + filename_found = temp; + } + + // If not found, we can try harder by appending part of the file to + // to the directory to look inside. + // Example: if we were looking for /foo/bar/yo.txt in /d1/d2, then + // try to find yo.txt in /d1/d2/bar, then /d1/d2/foo/bar, etc. + + else if (try_filename_dirs) + { + kwsys_stl::string filename_dir(filename); + kwsys_stl::string filename_dir_base; + kwsys_stl::string filename_dir_bases; + do + { + filename_dir = SystemTools::GetFilenamePath(filename_dir); + filename_dir_base = SystemTools::GetFilenameName(filename_dir); +#if _WIN32 + if (!filename_dir_base.size() || + filename_dir_base[filename_dir_base.size() - 1] == ':') +#else + if (!filename_dir_base.size()) +#endif + { + break; + } + + filename_dir_bases = filename_dir_base + "/" + filename_dir_bases; + + temp = dir; + if (need_slash) + { + temp += "/"; + } + temp += filename_dir_bases; + + res = SystemTools::LocateFileInDir( + filename_base.c_str(), temp.c_str(), filename_found, 0); + + } while (!res && filename_dir_base.size()); + } + } + + return res; +} + +bool SystemTools::FileIsFullPath(const char* in_name) +{ + kwsys_stl::string name = in_name; +#if defined(_WIN32) || defined(__CYGWIN__) + // On Windows, the name must be at least two characters long. + if(name.length() < 2) + { + return false; + } + if(name[1] == ':') + { + return true; + } + if(name[0] == '\\') + { + return true; + } +#else + // On UNIX, the name must be at least one character long. + if(name.length() < 1) + { + return false; + } +#endif + // On UNIX, the name must begin in a '/'. + // On Windows, if the name begins in a '/', then it is a full + // network path. + if(name[0] == '/') + { + return true; + } + return false; +} + +bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath) +{ +#if defined(WIN32) && !defined(__CYGWIN__) + const int size = int(strlen(path)) +1; // size of return + char *buffer = new char[size]; // create a buffer + char *tempPath = new char[size]; // create a buffer + int ret; + + // if the path passed in has quotes around it, first remove the quotes + if (path[0] == '"' && path[strlen(path)-1] == '"') + { + strcpy(tempPath,path+1); + tempPath[strlen(tempPath)-1] = '\0'; + } + else + { + strcpy(tempPath,path); + } + + buffer[0] = 0; + ret = GetShortPathName(tempPath, buffer, size); + + if(buffer[0] == 0 || ret > size) + { + delete [] buffer; + delete [] tempPath; + return false; + } + else + { + shortPath = buffer; + delete [] buffer; + delete [] tempPath; + return true; + } +#else + shortPath = path; + return true; +#endif +} + +void SystemTools::SplitProgramFromArgs(const char* path, + kwsys_stl::string& program, kwsys_stl::string& args) +{ + // see if this is a full path to a program + // if so then set program to path and args to nothing + if(SystemTools::FileExists(path)) + { + program = path; + args = ""; + return; + } + // Try to find the program in the path, note the program + // may have spaces in its name so we have to look for it + kwsys_stl::vector e; + kwsys_stl::string findProg = SystemTools::FindProgram(path, e); + if(findProg.size()) + { + program = findProg; + args = ""; + return; + } + + // Now try and peel off space separated chunks from the end of the string + // so the largest path possible is found allowing for spaces in the path + kwsys_stl::string dir = path; + kwsys_stl::string::size_type spacePos = dir.rfind(' '); + while(spacePos != kwsys_stl::string::npos) + { + kwsys_stl::string tryProg = dir.substr(0, spacePos); + // See if the file exists + if(SystemTools::FileExists(tryProg.c_str())) + { + program = tryProg; + // remove trailing spaces from program + kwsys_stl::string::size_type pos = program.size()-1; + while(program[pos] == ' ') + { + program.erase(pos); + pos--; + } + args = dir.substr(spacePos, dir.size()-spacePos); + return; + } + // Now try and find the the program in the path + findProg = SystemTools::FindProgram(tryProg.c_str(), e); + if(findProg.size()) + { + program = findProg; + // remove trailing spaces from program + kwsys_stl::string::size_type pos = program.size()-1; + while(program[pos] == ' ') + { + program.erase(pos); + pos--; + } + args = dir.substr(spacePos, dir.size()-spacePos); + return; + } + // move past the space for the next search + spacePos--; + spacePos = dir.rfind(' ', spacePos); + } + + program = ""; + args = ""; +} + +kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format) +{ + char buf[1024]; + time_t t; + time(&t); + strftime(buf, sizeof(buf), format, localtime(&t)); + return buf; +} + +kwsys_stl::string SystemTools::MakeCindentifier(const char* s) +{ + kwsys_stl::string str(s); + if (str.find_first_of("0123456789") == 0) + { + str = "_" + str; + } + + kwsys_stl::string permited_chars("_" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"); + kwsys_stl::string::size_type pos = 0; + while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_stl::string::npos) + { + str[pos] = '_'; + } + return str; +} + +// Due to a buggy stream library on the HP and another on Mac OSX, we +// need this very carefully written version of getline. Returns true +// if any data were read before the end-of-file was reached. +bool SystemTools::GetLineFromStream(kwsys_ios::istream& is, kwsys_stl::string& line, + bool *has_newline /* = 0 */) +{ + const int bufferSize = 1024; + char buffer[bufferSize]; + line = ""; + bool haveData = false; + if ( has_newline ) + { + *has_newline = false; + } + + // If no characters are read from the stream, the end of file has + // been reached. + while((is.getline(buffer, bufferSize), is.gcount() > 0)) + { + haveData = true; + line.append(buffer); + + // If newline character was read, the gcount includes the + // character, but the buffer does not. The end of line has been + // reached. + if(strlen(buffer) < static_cast(is.gcount())) + { + if ( has_newline ) + { + *has_newline = true; + } + break; + } + + // The fail bit may be set. Clear it. + is.clear(is.rdstate() & ~kwsys_ios::ios::failbit); + } + return haveData; +} + +int SystemTools::GetTerminalWidth() +{ + int width = -1; +#ifndef _WIN32 + struct winsize ws; + char *columns; /* Unix98 environment variable */ + if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0) + { + width = ws.ws_col; + } + if(!isatty(STDOUT_FILENO)) + { + width = -1; + } + columns = getenv("COLUMNS"); + if(columns && *columns) + { + long t; + char *endptr; + t = strtol(columns, &endptr, 0); + if(endptr && !*endptr && (t>0) && (t<1000)) + { + width = (int)t; + } + } + if ( width < 9 ) + { + width = -1; + } +#endif + return width; +} + +bool SystemTools::GetPermissions(const char* file, mode_t& mode) +{ + if ( !file ) + { + return false; + } + + struct stat st; + if ( stat(file, &st) < 0 ) + { + return false; + } + mode = st.st_mode; + return true; +} + +bool SystemTools::SetPermissions(const char* file, mode_t mode) +{ + if ( !file ) + { + return false; + } + if ( !SystemTools::FileExists(file) ) + { + return false; + } + if ( chmod(file, mode) < 0 ) + { + return false; + } + + return true; +} + +kwsys_stl::string SystemTools::GetParentDirectory(const char* fileOrDir) +{ + if ( !fileOrDir || !*fileOrDir ) + { + return ""; + } + kwsys_stl::string res = fileOrDir; + SystemTools::ConvertToUnixSlashes(res); + kwsys_stl::string::size_type cc = res.size()-1; + if ( res[cc] == '/' ) + { + cc --; + } + for ( ; cc > 0; cc -- ) + { + if ( res[cc] == '/' ) + { + break; + } + } + return res.substr(0, cc); +} + +bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir) +{ + kwsys_stl::string subdir = cSubdir; + kwsys_stl::string dir = cDir; + SystemTools::ConvertToUnixSlashes(dir); + kwsys_stl::string path = subdir; + do + { + path = SystemTools::GetParentDirectory(path.c_str()); + if ( dir == path ) + { + return true; + } + } + while ( path.size() > dir.size() ); + return false; +} + +kwsys_stl::string SystemTools::FileExistsInParentDirectories(const char* fname, + const char* directory, const char* toplevel) +{ + kwsys_stl::string file = fname; + SystemTools::ConvertToUnixSlashes(file); + kwsys_stl::string dir = directory; + SystemTools::ConvertToUnixSlashes(dir); + while ( !dir.empty() ) + { + kwsys_stl::string path = dir + "/" + file; + if ( SystemTools::FileExists(path.c_str()) ) + { + return path; + } + if ( dir.size() < strlen(toplevel) ) + { + break; + } + dir = SystemTools::GetParentDirectory(dir.c_str()); + } + return ""; +} + +void SystemTools::Delay(unsigned int msec) +{ +#ifdef _WIN32 + Sleep(msec); +#else + usleep(msec * 1000); +#endif +} + +void SystemTools::ConvertWindowsCommandLineToUnixArguments( + const char *cmd_line, int *argc, char ***argv) +{ + if (!cmd_line || !argc || !argv) + { + return; + } + + // A space delimites an argument except when it is inside a quote + + (*argc) = 1; + + size_t cmd_line_len = strlen(cmd_line); + + size_t i; + for (i = 0; i < cmd_line_len; i++) + { + while (isspace(cmd_line[i]) && i < cmd_line_len) + { + i++; + } + if (i < cmd_line_len) + { + if (cmd_line[i] == '\"') + { + i++; + while (cmd_line[i] != '\"' && i < cmd_line_len) + { + i++; + } + (*argc)++; + } + else + { + while (!isspace(cmd_line[i]) && i < cmd_line_len) + { + i++; + } + (*argc)++; + } + } + } + + (*argv) = new char* [(*argc) + 1]; + (*argv)[(*argc)] = NULL; + + // Set the first arg to be the exec name + + (*argv)[0] = new char [1024]; +#ifdef _WIN32 + ::GetModuleFileName(0, (*argv)[0], 1024); +#else + (*argv)[0][0] = '\0'; +#endif + + // Allocate the others + + int j; + for (j = 1; j < (*argc); j++) + { + (*argv)[j] = new char [cmd_line_len + 10]; + } + + // Grab the args + + size_t pos; + int argc_idx = 1; + + for (i = 0; i < cmd_line_len; i++) + { + while (isspace(cmd_line[i]) && i < cmd_line_len) + { + i++; + } + if (i < cmd_line_len) + { + if (cmd_line[i] == '\"') + { + i++; + pos = i; + while (cmd_line[i] != '\"' && i < cmd_line_len) + { + i++; + } + memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos); + (*argv)[argc_idx][i - pos] = '\0'; + argc_idx++; + } + else + { + pos = i; + while (!isspace(cmd_line[i]) && i < cmd_line_len) + { + i++; + } + memcpy((*argv)[argc_idx], &cmd_line[pos], i - pos); + (*argv)[argc_idx][i - pos] = '\0'; + argc_idx++; + } + } + } + } + +kwsys_stl::string SystemTools::GetOperatingSystemNameAndVersion() +{ + kwsys_stl::string res; + +#ifdef _WIN32 + char buffer[256]; + + OSVERSIONINFOEX osvi; + BOOL bOsVersionInfoEx; + + // Try calling GetVersionEx using the OSVERSIONINFOEX structure. + // If that fails, try using the OSVERSIONINFO structure. + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *)&osvi); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx((OSVERSIONINFO *)&osvi)) + { + return 0; + } + } + + switch (osvi.dwPlatformId) + { + // Test for the Windows NT product family. + + case VER_PLATFORM_WIN32_NT: + + // Test for the specific product family. + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + res += "Microsoft Windows Server 2003 family"; + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + { + res += "Microsoft Windows XP"; + } + + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + res += "Microsoft Windows 2000"; + } + + if (osvi.dwMajorVersion <= 4) + { + res += "Microsoft Windows NT"; + } + + // Test for specific product on Windows NT 4.0 SP6 and later. + + if (bOsVersionInfoEx) + { + // Test for the workstation type. + +#if (_MSC_VER >= 1300) + if (osvi.wProductType == VER_NT_WORKSTATION) + { + if (osvi.dwMajorVersion == 4) + { + res += " Workstation 4.0"; + } + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + { + res += " Home Edition"; + } + else + { + res += " Professional"; + } + } + + // Test for the server type. + + else if (osvi.wProductType == VER_NT_SERVER) + { + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + { + res += " Datacenter Edition"; + } + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + res += " Enterprise Edition"; + } + else if (osvi.wSuiteMask == VER_SUITE_BLADE) + { + res += " Web Edition"; + } + else + { + res += " Standard Edition"; + } + } + + else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + { + res += " Datacenter Server"; + } + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + res += " Advanced Server"; + } + else + { + res += " Server"; + } + } + + else // Windows NT 4.0 + { + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + { + res += " Server 4.0, Enterprise Edition"; + } + else + { + res += " Server 4.0"; + } + } + } +#endif // Visual Studio 7 and up + } + + // Test for specific product on Windows NT 4.0 SP5 and earlier + + else + { + HKEY hKey; + #define BUFSIZE 80 + char szProductType[BUFSIZE]; + DWORD dwBufLen=BUFSIZE; + LONG lRet; + + lRet = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + 0, KEY_QUERY_VALUE, &hKey); + if (lRet != ERROR_SUCCESS) + { + return 0; + } + + lRet = RegQueryValueEx(hKey, "ProductType", NULL, NULL, + (LPBYTE) szProductType, &dwBufLen); + + if ((lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE)) + { + return 0; + } + + RegCloseKey(hKey); + + if (lstrcmpi("WINNT", szProductType) == 0) + { + res += " Workstation"; + } + if (lstrcmpi("LANMANNT", szProductType) == 0) + { + res += " Server"; + } + if (lstrcmpi("SERVERNT", szProductType) == 0) + { + res += " Advanced Server"; + } + + res += " "; + sprintf(buffer, "%d", osvi.dwMajorVersion); + res += buffer; + res += "."; + sprintf(buffer, "%d", osvi.dwMinorVersion); + res += buffer; + } + + // Display service pack (if any) and build number. + + if (osvi.dwMajorVersion == 4 && + lstrcmpi(osvi.szCSDVersion, "Service Pack 6") == 0) + { + HKEY hKey; + LONG lRet; + + // Test for SP6 versus SP6a. + + lRet = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009", + 0, KEY_QUERY_VALUE, &hKey); + + if (lRet == ERROR_SUCCESS) + { + res += " Service Pack 6a (Build "; + sprintf(buffer, "%d", osvi.dwBuildNumber & 0xFFFF); + res += buffer; + res += ")"; + } + else // Windows NT 4.0 prior to SP6a + { + res += " "; + res += osvi.szCSDVersion; + res += " (Build "; + sprintf(buffer, "%d", osvi.dwBuildNumber & 0xFFFF); + res += buffer; + res += ")"; + } + + RegCloseKey(hKey); + } + else // Windows NT 3.51 and earlier or Windows 2000 and later + { + res += " "; + res += osvi.szCSDVersion; + res += " (Build "; + sprintf(buffer, "%d", osvi.dwBuildNumber & 0xFFFF); + res += buffer; + res += ")"; + } + + break; + + // Test for the Windows 95 product family. + + case VER_PLATFORM_WIN32_WINDOWS: + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + { + res += "Microsoft Windows 95"; + if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') + { + res += " OSR2"; + } + } + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + res += "Microsoft Windows 98"; + if (osvi.szCSDVersion[1] == 'A') + { + res += " SE"; + } + } + + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + { + res += "Microsoft Windows Millennium Edition"; + } + break; + + case VER_PLATFORM_WIN32s: + + res += "Microsoft Win32s"; + break; + } +#endif + + return res; +} + +// These must NOT be initialized. Default initialization to zero is +// necessary. +unsigned int SystemToolsManagerCount; +SystemToolsTranslationMap *SystemTools::TranslationMap; + +// SystemToolsManager manages the SystemTools singleton. +// SystemToolsManager should be included in any translation unit +// that will use SystemTools or that implements the singleton +// pattern. It makes sure that the SystemTools singleton is created +// before and destroyed after all other singletons in CMake. + +SystemToolsManager::SystemToolsManager() +{ + if(++SystemToolsManagerCount == 1) + { + SystemTools::ClassInitialize(); + } +} + +SystemToolsManager::~SystemToolsManager() +{ + if(--SystemToolsManagerCount == 0) + { + SystemTools::ClassFinalize(); + } +} + +void SystemTools::ClassInitialize() +{ + // Allocate the translation map first. + SystemTools::TranslationMap = new SystemToolsTranslationMap; + + // Add some special translation paths for unix. These are not added + // for windows because drive letters need to be maintained. Also, + // there are not sym-links and mount points on windows anyway. +#if !defined(_WIN32) || defined(__CYGWIN__) + // Work-around an SGI problem by always adding this mapping: + SystemTools::AddTranslationPath("/tmp_mnt/", "/"); + // The tmp path is frequently a logical path so always keep it: + SystemTools::AddKeepPath("/tmp/"); + + // If the current working directory is a logical path then keep the + // logical name. + if(const char* pwd = getenv("PWD")) + { + char buf[2048]; + if(const char* cwd = Getcwd(buf, 2048)) + { + // The current working directory may be a logical path. Find + // the shortest logical path that still produces the correct + // physical path. + kwsys_stl::string cwd_changed; + kwsys_stl::string pwd_changed; + + // Test progressively shorter logical-to-physical mappings. + kwsys_stl::string pwd_str = pwd; + kwsys_stl::string cwd_str = cwd; + kwsys_stl::string pwd_path; + Realpath(pwd, pwd_path); + while(cwd_str == pwd_path && cwd_str != pwd_str) + { + // The current pair of paths is a working logical mapping. + cwd_changed = cwd_str; + pwd_changed = pwd_str; + + // Strip off one directory level and see if the logical + // mapping still works. + pwd_str = SystemTools::GetFilenamePath(pwd_str.c_str()); + cwd_str = SystemTools::GetFilenamePath(cwd_str.c_str()); + Realpath(pwd_str.c_str(), pwd_path); + } + + // Add the translation to keep the logical path name. + if(!cwd_changed.empty() && !pwd_changed.empty()) + { + SystemTools::AddTranslationPath(cwd_changed.c_str(), + pwd_changed.c_str()); + } + } + } +#endif +} + +void SystemTools::ClassFinalize() +{ + delete SystemTools::TranslationMap; +} + + +} // namespace KWSYS_NAMESPACE + +#if defined(_MSC_VER) && defined(_DEBUG) +# include +# include +# include +namespace KWSYS_NAMESPACE +{ + +static int SystemToolsDebugReport(int, char* message, int*) +{ + fprintf(stderr, message); + exit(1); +} +void SystemTools::EnableMSVCDebugHook() +{ + if(getenv("DART_TEST_FROM_DART")) + { + _CrtSetReportHook(SystemToolsDebugReport); + } +} + +} // namespace KWSYS_NAMESPACE +#else +namespace KWSYS_NAMESPACE +{ +void SystemTools::EnableMSVCDebugHook() {} +} // namespace KWSYS_NAMESPACE +#endif + diff --git a/Utilities/kwsys/SystemTools.hxx.in b/Utilities/kwsys/SystemTools.hxx.in new file mode 100644 index 0000000..00302cf --- /dev/null +++ b/Utilities/kwsys/SystemTools.hxx.in @@ -0,0 +1,766 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: SystemTools.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_SystemTools_hxx +#define @KWSYS_NAMESPACE@_SystemTools_hxx + +#include <@KWSYS_NAMESPACE@/ios/iosfwd> +#include <@KWSYS_NAMESPACE@/stl/string> +#include <@KWSYS_NAMESPACE@/stl/vector> +#include <@KWSYS_NAMESPACE@/stl/map> + +#include <@KWSYS_NAMESPACE@/Configure.h> + +#include + +// Required for va_list +#include +#if @KWSYS_NAMESPACE@_STL_HAVE_STD && !defined(va_list) +// Some compilers move va_list into the std:: namespace and there is no way to +// tell that this has been done. Playing with things being included before or +// after stdarg.h does not solve things because we do not have control over +// what the user does. This hack solves this problem by moving va_list to our +// own namespace that is local for kwsys. +namespace std {} // Required for platforms that do not have std:: +namespace @KWSYS_NAMESPACE@_VA_LIST +{ + using namespace std; + typedef va_list hack_va_list; +} +namespace @KWSYS_NAMESPACE@ +{ + typedef @KWSYS_NAMESPACE@_VA_LIST::hack_va_list va_list; +} +#endif // va_list + +#if defined( _MSC_VER ) +typedef unsigned short mode_t; +#endif + +/* Define these macros temporarily to keep the code readable. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsys_stl @KWSYS_NAMESPACE@_stl +# define kwsys_ios @KWSYS_NAMESPACE@_ios +#endif + +namespace @KWSYS_NAMESPACE@ +{ + +class SystemToolsTranslationMap; +class @KWSYS_NAMESPACE@_EXPORT SystemToolsManager +{ +public: + SystemToolsManager(); + ~SystemToolsManager(); +}; + +// This instance will show up in any translation unit that uses +// SystemTools. It will make sure SystemTools is initialized +// before it is used and is the last static object destroyed. +static SystemToolsManager SystemToolsManagerInstance; + +/** \class SystemTools + * \brief A collection of useful platform-independent system functions. + */ +class @KWSYS_NAMESPACE@_EXPORT SystemTools +{ +public: + + /** ----------------------------------------------------------------- + * String Manipulation Routines + * ----------------------------------------------------------------- + */ + + /** + * Replace symbols in str that are not valid in C identifiers as + * defined by the 1999 standard, ie. anything except [A-Za-z0-9_]. + * They are replaced with `_' and if the first character is a digit + * then an underscore is prepended. Note that this can produce + * identifiers that the standard reserves (_[A-Z].* and __.*). + */ + static kwsys_stl::string MakeCindentifier(const char* s); + + /** + * Replace replace all occurences of the string in the source string. + */ + static void ReplaceString(kwsys_stl::string& source, + const char* replace, + const char* with); + + /** + * Return a capitalized string (i.e the first letter is uppercased, + * all other are lowercased). + */ + static kwsys_stl::string Capitalized(const kwsys_stl::string&); + + /** + * Return a 'capitalized words' string (i.e the first letter of each word + * is uppercased all other are left untouched though). + */ + static kwsys_stl::string CapitalizedWords(const kwsys_stl::string&); + + /** + * Return a 'uncapitalized words' string (i.e the first letter of each word + * is lowercased all other are left untouched though). + */ + static kwsys_stl::string UnCapitalizedWords(const kwsys_stl::string&); + + /** + * Return a lower case string + */ + static kwsys_stl::string LowerCase(const kwsys_stl::string&); + + /** + * Return a lower case string + */ + static kwsys_stl::string UpperCase(const kwsys_stl::string&); + + /** + * Count char in string + */ + static size_t CountChar(const char* str, char c); + + /** + * Remove some characters from a string. + * Return a pointer to the new resulting string (allocated with 'new') + */ + static char* RemoveChars(const char* str, const char *toremove); + + /** + * Remove remove all but 0->9, A->F characters from a string. + * Return a pointer to the new resulting string (allocated with 'new') + */ + static char* RemoveCharsButUpperHex(const char* str); + + /** + * Replace some characters by another character in a string (in-place) + * Return a pointer to string + */ + static char* ReplaceChars(char* str, const char *toreplace,char replacement); + + /** + * Returns true if str1 starts (respectively ends) with str2 + */ + static bool StringStartsWith(const char* str1, const char* str2); + static bool StringEndsWith(const char* str1, const char* str2); + + /** + * Returns a pointer to the last occurence of str2 in str1 + */ + static const char* FindLastString(const char* str1, const char* str2); + + /** + * Make a duplicate of the string similar to the strdup C function + * but use new to create the 'new' string, so one can use + * 'delete' to remove it. Returns 0 if the input is empty. + */ + static char* DuplicateString(const char* str); + + /** + * Return the string cropped to a given length by removing chars in the + * center of the string and replacing them with an ellipsis (...) + */ + static kwsys_stl::string CropString(const kwsys_stl::string&,size_t max_len); + + /** split a path by separator into an array of strings, default is /. + If isPath is true then the string is treated like a path and if + s starts with a / then the first element of the returned array will + be /, so /foo/bar will be [/, foo, bar] + */ + static kwsys_stl::vector SplitString(const char* s, char separator = '/', + bool isPath = false); + /** + * Perform a case-independent string comparison + */ + static int Strucmp(const char *s1, const char *s2); + + /** + * Convert a string in __DATE__ or __TIMESTAMP__ format into a time_t. + * Return false on error, true on success + */ + static bool ConvertDateMacroString(const char *str, time_t *tmt); + static bool ConvertTimeStampMacroString(const char *str, time_t *tmt); + + /** + * Split a string on its newlines into multiple lines + * Return false only if the last line stored had no newline + */ + static bool Split(const char* s, kwsys_stl::vector& l); + static bool Split(const char* s, kwsys_stl::vector& l, char separator); + + /** + * Return string with space added between capitalized words + * (i.e. EatMyShorts becomes Eat My Shorts + */ + static kwsys_stl::string AddSpaceBetweenCapitalizedWords( + const kwsys_stl::string&); + + /** + * Append two or more strings and produce new one. + * Programmer must 'delete []' the resulting string, which was allocated + * with 'new'. + * Return 0 if inputs are empty or there was an error + */ + static char* AppendStrings( + const char* str1, const char* str2); + static char* AppendStrings( + const char* str1, const char* str2, const char* str3); + + /** + * Estimate the length of the string that will be produced + * from printing the given format string and arguments. The + * returned length will always be at least as large as the string + * that will result from printing. + * WARNING: since va_arg is called to iterate of the argument list, + * you will not be able to use this 'ap' anymore from the beginning. + * It's up to you to call va_end though. + */ + static int EstimateFormatLength(const char *format, va_list ap); + + /** + * Escape specific characters in 'str'. + */ + static kwsys_stl::string EscapeChars( + const char *str, const char *chars_to_escape, char escape_char = '\\'); + + /** ----------------------------------------------------------------- + * Filename Manipulation Routines + * ----------------------------------------------------------------- + */ + + /** + * Replace Windows file system slashes with Unix-style slashes. + */ + static void ConvertToUnixSlashes(kwsys_stl::string& path); + + /** + * For windows this calls ConvertToWindowsOutputPath and for unix + * it calls ConvertToUnixOutputPath + */ + static kwsys_stl::string ConvertToOutputPath(const char*); + + /** + * Return true if a file exists in the current directory + */ + static bool FileExists(const char* filename); + + /** + * Return file length + */ + static unsigned long FileLength(const char *filename); + + /** + * Compare file modification times. + * Return true for successful comparison and false for error. + * When true is returned, result has -1, 0, +1 for + * f1 older, same, or newer than f2. + */ + static bool FileTimeCompare(const char* f1, const char* f2, + int* result); + + /** + * Get the file extension (including ".") needed for an executable + * on the current platform ("" for unix, ".exe" for Windows). + */ + static const char* GetExecutableExtension(); + + /** + * Given a path that exists on a windows machine, return the + * actuall case of the path as it was created. If the file + * does not exist path is returned unchanged. This does nothing + * on unix but return path. + */ + static kwsys_stl::string GetActualCaseForPath(const char* path); + + /** + * Given the path to a program executable, get the directory part of + * the path with the file stripped off. If there is no directory + * part, the empty string is returned. + */ + static kwsys_stl::string GetProgramPath(const char*); + static bool SplitProgramPath(const char* in_name, + kwsys_stl::string& dir, + kwsys_stl::string& file, + bool errorReport = true); + + /** + * Given argv[0] for a unix program find the full path to a running + * executable. argv0 can be null for windows WinMain programs + * in this case GetModuleFileName will be used to find the path + * to the running executable. If argv0 is not a full path, + * then this will try to find the full path. If the path is not + * found false is returned, if found true is returned. An error + * message of the attempted paths is stored in errorMsg. + * exeName is the name of the executable. + * buildDir is a possibly null path to the build directory. + * installPrefix is a possibly null pointer to the install directory. + */ + static bool FindProgramPath(const char* argv0, + kwsys_stl::string& pathOut, + kwsys_stl::string& errorMsg, + const char* exeName = 0, + const char* buildDir = 0, + const char* installPrefix = 0); + + /** + * Given a path to a file or directory, convert it to a full path. + * This collapses away relative paths relative to the cwd argument + * (which defaults to the current working directory). The full path + * is returned. + */ + static kwsys_stl::string CollapseFullPath(const char* in_relative); + static kwsys_stl::string CollapseFullPath(const char* in_relative, + const char* in_base); + + /** + * Split a path name into its basic components. The first component + * is one of the following roots: + * "/" = UNIX + * "c:/" = Windows full path (can be any drive letter) + * "c:" = Windows drive-letter relative path (can be any drive letter) + * "//" = Network path + * "" = Relative path + * The remaining components form the path. If there is a trailing + * slash then the last component is the empty string. The + * components can be recombined as "c[0]c[1]/c[2]/.../c[n]" to + * produce the original path. + */ + static void SplitPath(const char* p, + kwsys_stl::vector& components); + + /** + * Join components of a path name into a single string. See + * SplitPath for the format of the components. + */ + static kwsys_stl::string JoinPath( + const kwsys_stl::vector& components); + + /** + * Compare a path or components of a path. + */ + static bool ComparePath(const char* c1, const char* c2); + + + /** + * Return path of a full filename (no trailing slashes) + */ + static kwsys_stl::string GetFilenamePath(const kwsys_stl::string&); + + /** + * Return file name of a full filename (i.e. file name without path) + */ + static kwsys_stl::string GetFilenameName(const kwsys_stl::string&); + + /** + * Split a program from its arguments and handle spaces in the paths + */ + static void SplitProgramFromArgs( + const char* path, + kwsys_stl::string& program, kwsys_stl::string& args); + + /** + * Return longest file extension of a full filename (dot included) + */ + static kwsys_stl::string GetFilenameExtension(const kwsys_stl::string&); + + /** + * Return shortest file extension of a full filename (dot included) + */ + static kwsys_stl::string GetFilenameLastExtension( + const kwsys_stl::string& filename); + + /** + * Return file name without extension of a full filename + */ + static kwsys_stl::string GetFilenameWithoutExtension( + const kwsys_stl::string&); + + /** + * Return file name without its last (shortest) extension + */ + static kwsys_stl::string GetFilenameWithoutLastExtension( + const kwsys_stl::string&); + + /** + * Return whether the path represents a full path (not relative) + */ + static bool FileIsFullPath(const char*); + + /** + * For windows return the short path for the given path, + * Unix just a pass through + */ + static bool GetShortPath(const char* path, kwsys_stl::string& result); + + /** + * Read line from file. Make sure to get everything. Due to a buggy stream + * library on the HP and another on Mac OSX, we need this very carefully + * written version of getline. Returns true if any data were read before the + * end-of-file was reached. If the has_newline argument is specified, it will + * be true when the line read had a newline character. + */ + static bool GetLineFromStream(kwsys_ios::istream& istr, + kwsys_stl::string& line, + bool* has_newline=0); + + /** + * Get the parent directory of the directory or file + */ + static kwsys_stl::string GetParentDirectory(const char* fileOrDir); + + /** + * Check if the given file or directory is in subdirectory of dir + */ + static bool IsSubDirectory(const char* fileOrDir, const char* dir); + + /** + * Convert the path to a string that can be used in a unix makefile. + * double slashes are removed, and spaces are escaped. + */ + static kwsys_stl::string ConvertToUnixOutputPath(const char*); + + /** ----------------------------------------------------------------- + * File Manipulation Routines + * ----------------------------------------------------------------- + */ + + /** + * Make a new directory if it is not there. This function + * can make a full path even if none of the directories existed + * prior to calling this function. + */ + static bool MakeDirectory(const char* path); + + /** + * Copy the source file to the destination file only + * if the two files differ. + */ + static bool CopyFileIfDifferent(const char* source, + const char* destination); + + /** + * Compare the contents of two files. Return true if different + */ + static bool FilesDiffer(const char* source, const char* destination); + + /** + * Return true if the two files are the same file + */ + static bool SameFile(const char* file1, const char* file2); + + /** + * Copy a file + */ + static bool CopyFileAlways(const char* source, const char* destination); + + /** + * Copy content directory to another directory with all files and + * subdirectories + */ + static bool CopyADirectory(const char* source, const char* destination); + + /** + * Remove a file + */ + static bool RemoveFile(const char* source); + + /** + * Remove a directory + */ + static bool RemoveADirectory(const char* source); + + /** + * Find a file in the system PATH, with optional extra paths + */ + static kwsys_stl::string FindFile( + const char* name, + const kwsys_stl::vector& path = + kwsys_stl::vector()); + + /** + * Find an executable in the system PATH, with optional extra paths + */ + static kwsys_stl::string FindProgram( + const char* name, + const kwsys_stl::vector& path = + kwsys_stl::vector(), + bool no_system_path = false); + + /** + * Find a library in the system PATH, with optional extra paths + */ + static kwsys_stl::string FindLibrary( + const char* name, + const kwsys_stl::vector& path); + + /** + * Return true if the file is a directory + */ + static bool FileIsDirectory(const char* name); + + /** + * Return true if the file is a symlink + */ + static bool FileIsSymlink(const char* name); + + /** + * Return true if the file has a given signature (first set of bytes) + */ + static bool FileHasSignature( + const char* filename, const char *signature, long offset = 0); + + /** + * Attempt to detect and return the type of a file. + * Up to 'length' bytes are read from the file, if more than 'percent_bin' % + * of the bytes are non-textual elements, the file is considered binary, + * otherwise textual. Textual elements are bytes in the ASCII [0x20, 0x7E] + * range, but also \n, \r, \t. + * The algorithm is simplistic, and should probably check for usual file + * extensions, 'magic' signature, unicode, etc. + */ + enum FileTypeEnum + { + FileTypeUnknown, + FileTypeBinary, + FileTypeText + }; + static SystemTools::FileTypeEnum DetectFileType( + const char* filename, + unsigned long length = 256, + double percent_bin = 0.05); + + /** + * Try to locate the file 'filename' in the directory 'dir'. + * If 'filename' is a fully qualified filename, the basename of the file is + * used to check for its existence in 'dir'. + * If 'dir' is not a directory, GetFilenamePath() is called on 'dir' to + * get its directory first (thus, you can pass a filename as 'dir', as + * a convenience). + * 'filename_found' is assigned the fully qualified name/path of the file + * if it is found (not touched otherwise). + * If 'try_filename_dirs' is true, try to find the file using the + * components of its path, i.e. if we are looking for c:/foo/bar/bill.txt, + * first look for bill.txt in 'dir', then in 'dir'/bar, then in 'dir'/foo/bar + * etc. + * Return true if the file was found, false otherwise. + */ + static bool LocateFileInDir(const char *filename, + const char *dir, + kwsys_stl::string& filename_found, + int try_filename_dirs = 0); + + /** + * Check if the given file exists in one of the parent directory of the + * given file or directory and if it does, return the name of the file. + * Toplevel specifies the top-most directory to where it will look. + */ + static kwsys_stl::string FileExistsInParentDirectories(const char* fname, + const char* directory, const char* toplevel); + + /** compute the relative path from local to remote. local must + be a directory. remote can be a file or a directory. + Both remote and local must be full paths. Basically, if + you are in directory local and you want to access the file in remote + what is the relative path to do that. For example: + /a/b/c/d to /a/b/c1/d1 -> ../../c1/d1 + from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp + */ + static kwsys_stl::string RelativePath(const char* local, const char* remote); + + /** + * Return file's modified time + */ + static long int ModifiedTime(const char* filename); + + /** + * Return file's creation time (Win32: works only for NTFS, not FAT) + */ + static long int CreationTime(const char* filename); + + /** + * Get and set permissions of the file. + */ + static bool GetPermissions(const char* file, mode_t& mode); + static bool SetPermissions(const char* file, mode_t mode); + + /** ----------------------------------------------------------------- + * Time Manipulation Routines + * ----------------------------------------------------------------- + */ + + /** + * Get current time as a double. On certain platforms this will + * return higher resolution than seconds: + * (1) gettimeofday() -- resolution in microseconds + * (2) ftime() -- resolution in milliseconds + * (3) time() -- resolution in seconds + */ + static double GetTime(); + + /** + * Get current date/time + */ + static kwsys_stl::string GetCurrentDateTime(const char* format); + + /** ----------------------------------------------------------------- + * Registry Manipulation Routines + * ----------------------------------------------------------------- + */ + + /** + * Read a registry value + */ + static bool ReadRegistryValue(const char *key, kwsys_stl::string &value); + + /** + * Write a registry value + */ + static bool WriteRegistryValue(const char *key, const char *value); + + /** + * Delete a registry value + */ + static bool DeleteRegistryValue(const char *key); + + /** ----------------------------------------------------------------- + * Environment Manipulation Routines + * ----------------------------------------------------------------- + */ + + /** + * Add the paths from the environment variable PATH to the + * string vector passed in. If env is set then the value + * of env will be used instead of PATH. + */ + static void GetPath(kwsys_stl::vector& path, + const char* env=0); + + /** + * Read an environment variable + */ + static const char* GetEnv(const char* key); + static bool GetEnv(const char* key, kwsys_stl::string& result); + + /** + * Get current working directory CWD + */ + static kwsys_stl::string GetCurrentWorkingDirectory(bool collapse =true); + + /** + * Change directory the the directory specified + */ + static int ChangeDirectory(const char* dir); + + /** + * Get the result of strerror(errno) + */ + static kwsys_stl::string GetLastSystemError(); + + /** + * When building DEBUG with MSVC, this enables a hook that prevents + * error dialogs from popping up if the program is being run from + * DART. + */ + static void EnableMSVCDebugHook(); + + /** + * Get the width of the terminal window. The code may or may not work, so + * make sure you have some resonable defaults prepared if the code returns + * some bogus size. + */ + static int GetTerminalWidth(); + + /** + * Add an entry in the path translation table. + */ + static void AddTranslationPath(const char * dir, const char * refdir); + + /** + * If dir is different after CollapseFullPath is called, + * Then insert it into the path translation table + */ + static void AddKeepPath(const char* dir); + + /** + * Update path by going through the Path Translation table; + */ + static void CheckTranslationPath(kwsys_stl::string & path); + + /** + * Delay the execution for a specified amount of time specified + * in miliseconds + */ + static void Delay(unsigned int msec); + + /** + * Get the operating system name and version + * This is implemented for Win32 only for the moment + */ + static kwsys_stl::string GetOperatingSystemNameAndVersion(); + + /** + * Convert windows-style arguments given as a command-line string + * into more traditional argc/argv arguments. + * Note that argv[0] will be assigned the executable name using + * the ::GetModuleFileName function. + */ + static void ConvertWindowsCommandLineToUnixArguments( + const char *cmd_line, int *argc, char ***argv); + +protected: + // these two functions can be called from ConvertToOutputPath + + /** + * Convert the path to string that can be used in a windows project or + * makefile. Double slashes are removed if they are not at the start of + * the string, the slashes are converted to windows style backslashes, and + * if there are spaces in the string it is double quoted. + */ + static kwsys_stl::string ConvertToWindowsOutputPath(const char*); + +private: + /** + * Allocate the std::map that serve as the Path Translation table. + */ + static void ClassInitialize(); + + /** + * Deallocate the std::map that serve as the Path Translation table. + */ + static void ClassFinalize(); + + /** + * This method prevents warning on SGI + */ + SystemToolsManager* GetSystemToolsManager() + { + return &SystemToolsManagerInstance; + } + + /** + * Path translation table from dir to refdir + * Each time 'dir' will be found it will be replace by 'refdir' + */ + static SystemToolsTranslationMap *TranslationMap; + friend class SystemToolsManager; +}; + +} // namespace @KWSYS_NAMESPACE@ + +/* Undefine temporary macros. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsys_stl +# undef kwsys_ios +#endif + +#endif diff --git a/Utilities/kwsys/hash_fun.hxx.in b/Utilities/kwsys/hash_fun.hxx.in new file mode 100644 index 0000000..36044b6 --- /dev/null +++ b/Utilities/kwsys/hash_fun.hxx.in @@ -0,0 +1,117 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: hash_fun.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +#ifndef @KWSYS_NAMESPACE@_hash_fun_hxx +#define @KWSYS_NAMESPACE@_hash_fun_hxx + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#include <@KWSYS_NAMESPACE@/cstddef> // size_t + +namespace @KWSYS_NAMESPACE@ +{ + +template struct hash { }; + +inline size_t _stl_hash_string(const char* __s) +{ + unsigned long __h = 0; + for ( ; *__s; ++__s) + __h = 5*__h + *__s; + + return size_t(__h); +} + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(const char* __s) const { return _stl_hash_string(__s); } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(const char* __s) const { return _stl_hash_string(__s); } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(char __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(unsigned char __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(unsigned char __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(short __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(unsigned short __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(int __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(unsigned int __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(long __x) const { return __x; } +}; + +@KWSYS_NAMESPACE@_CXX_DEFINE_SPECIALIZATION +struct hash { + size_t operator()(unsigned long __x) const { return __x; } +}; + +} // namespace @KWSYS_NAMESPACE@ + +#endif diff --git a/Utilities/kwsys/hash_map.hxx.in b/Utilities/kwsys/hash_map.hxx.in new file mode 100644 index 0000000..088960c --- /dev/null +++ b/Utilities/kwsys/hash_map.hxx.in @@ -0,0 +1,463 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: hash_map.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +#ifndef @KWSYS_NAMESPACE@_hash_map_hxx +#define @KWSYS_NAMESPACE@_hash_map_hxx + +#include <@KWSYS_NAMESPACE@/hashtable.hxx> +#include <@KWSYS_NAMESPACE@/hash_fun.hxx> +#include <@KWSYS_NAMESPACE@/stl/functional> // equal_to + +#if defined(_MSC_VER) +# pragma warning (push) +# pragma warning (disable:4284) +# pragma warning (disable:4786) +#endif + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +# pragma set woff 1174 +# pragma set woff 1375 +#endif + +namespace @KWSYS_NAMESPACE@ +{ + +// select1st is an extension: it is not part of the standard. +template +struct hash_select1st: + public @KWSYS_NAMESPACE@_stl::unary_function<@KWSYS_NAMESPACE@_stl::pair, T1> +{ + const T1& operator()(const @KWSYS_NAMESPACE@_stl::pair& __x) const + { return __x.first; } +}; + +// Forward declaration of equality operator; needed for friend declaration. + +template , + class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Key>, + class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) > +class hash_map; + +template +inline bool operator==(const hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc>&, + const hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc>&); + +template +class hash_map +{ +private: + typedef hashtable<@KWSYS_NAMESPACE@_stl::pair,_Key,_HashFcn, + hash_select1st,_EqualKey,_Alloc> _Ht; + _Ht _M_ht; + +public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher hash_funct() const { return _M_ht.hash_funct(); } + key_equal key_eq() const { return _M_ht.key_eq(); } + allocator_type get_allocator() const { return _M_ht.get_allocator(); } + +public: + hash_map() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + explicit hash_map(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + hash_map(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + hash_map(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + +#else + hash_map(const value_type* __f, const value_type* __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_map(const value_type* __f, const value_type* __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_map(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_map(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + hash_map(const_iterator __f, const_iterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_map(const_iterator __f, const_iterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_map(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_map(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } +#endif + +public: + size_type size() const { return _M_ht.size(); } + size_type max_size() const { return _M_ht.max_size(); } + bool empty() const { return _M_ht.empty(); } + void swap(hash_map& __hs) { _M_ht.swap(__hs._M_ht); } + + friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_map&, + const hash_map&); + + iterator begin() { return _M_ht.begin(); } + iterator end() { return _M_ht.end(); } + const_iterator begin() const { return _M_ht.begin(); } + const_iterator end() const { return _M_ht.end(); } + +public: + @KWSYS_NAMESPACE@_stl::pair insert(const value_type& __obj) + { return _M_ht.insert_unique(__obj); } +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + void insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f,__l); } +#else + void insert(const value_type* __f, const value_type* __l) { + _M_ht.insert_unique(__f,__l); + } + void insert(const_iterator __f, const_iterator __l) + { _M_ht.insert_unique(__f, __l); } +#endif + @KWSYS_NAMESPACE@_stl::pair insert_noresize(const value_type& __obj) + { return _M_ht.insert_unique_noresize(__obj); } + + iterator find(const key_type& __key) { return _M_ht.find(__key); } + const_iterator find(const key_type& __key) const + { return _M_ht.find(__key); } + + _Tp& operator[](const key_type& __key) { + return _M_ht.find_or_insert(value_type(__key, _Tp())).second; + } + + size_type count(const key_type& __key) const { return _M_ht.count(__key); } + + @KWSYS_NAMESPACE@_stl::pair equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + @KWSYS_NAMESPACE@_stl::pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type erase(const key_type& __key) {return _M_ht.erase(__key); } + void erase(iterator __it) { _M_ht.erase(__it); } + void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); } + void clear() { _M_ht.clear(); } + + void resize(size_type __hint) { _M_ht.resize(__hint); } + size_type bucket_count() const { return _M_ht.bucket_count(); } + size_type max_bucket_count() const { return _M_ht.max_bucket_count(); } + size_type elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } +}; + +template +inline bool +operator==(const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1, + const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2) +{ + return __hm1._M_ht == __hm2._M_ht; +} + +template +inline bool +operator!=(const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1, + const hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2) { + return !(__hm1 == __hm2); +} + +template +inline void +swap(hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1, + hash_map<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2) +{ + __hm1.swap(__hm2); +} + +// Forward declaration of equality operator; needed for friend declaration. + +template , + class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Key>, + class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) > +class hash_multimap; + +template +inline bool +operator==(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1, + const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2); + +template +class hash_multimap +{ +private: + typedef hashtable<@KWSYS_NAMESPACE@_stl::pair, _Key, _HashFcn, + hash_select1st, _EqualKey, _Alloc> + _Ht; + _Ht _M_ht; + +public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher hash_funct() const { return _M_ht.hash_funct(); } + key_equal key_eq() const { return _M_ht.key_eq(); } + allocator_type get_allocator() const { return _M_ht.get_allocator(); } + +public: + hash_multimap() : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + explicit hash_multimap(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + hash_multimap(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + hash_multimap(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + +#else + hash_multimap(const value_type* __f, const value_type* __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multimap(const value_type* __f, const value_type* __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multimap(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multimap(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + hash_multimap(const_iterator __f, const_iterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multimap(const_iterator __f, const_iterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multimap(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multimap(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } +#endif + +public: + size_type size() const { return _M_ht.size(); } + size_type max_size() const { return _M_ht.max_size(); } + bool empty() const { return _M_ht.empty(); } + void swap(hash_multimap& __hs) { _M_ht.swap(__hs._M_ht); } + + friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_multimap&, + const hash_multimap&); + + iterator begin() { return _M_ht.begin(); } + iterator end() { return _M_ht.end(); } + const_iterator begin() const { return _M_ht.begin(); } + const_iterator end() const { return _M_ht.end(); } + +public: + iterator insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + void insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } +#else + void insert(const value_type* __f, const value_type* __l) { + _M_ht.insert_equal(__f,__l); + } + void insert(const_iterator __f, const_iterator __l) + { _M_ht.insert_equal(__f, __l); } +#endif + iterator insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator find(const key_type& __key) { return _M_ht.find(__key); } + const_iterator find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type count(const key_type& __key) const { return _M_ht.count(__key); } + + @KWSYS_NAMESPACE@_stl::pair equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + @KWSYS_NAMESPACE@_stl::pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type erase(const key_type& __key) {return _M_ht.erase(__key); } + void erase(iterator __it) { _M_ht.erase(__it); } + void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); } + void clear() { _M_ht.clear(); } + +public: + void resize(size_type __hint) { _M_ht.resize(__hint); } + size_type bucket_count() const { return _M_ht.bucket_count(); } + size_type max_bucket_count() const { return _M_ht.max_bucket_count(); } + size_type elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } +}; + +template +inline bool +operator==(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1, + const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2) +{ + return __hm1._M_ht == __hm2._M_ht; +} + +template +inline bool +operator!=(const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm1, + const hash_multimap<_Key,_Tp,_HF,_EqKey,_Alloc>& __hm2) { + return !(__hm1 == __hm2); +} + +template +inline void +swap(hash_multimap<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm1, + hash_multimap<_Key,_Tp,_HashFcn,_EqlKey,_Alloc>& __hm2) +{ + __hm1.swap(__hm2); +} + +} // namespace @KWSYS_NAMESPACE@ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +# pragma reset woff 1174 +# pragma reset woff 1375 +#endif + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif diff --git a/Utilities/kwsys/hash_set.hxx.in b/Utilities/kwsys/hash_set.hxx.in new file mode 100644 index 0000000..10111d3 --- /dev/null +++ b/Utilities/kwsys/hash_set.hxx.in @@ -0,0 +1,447 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: hash_set.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +#ifndef @KWSYS_NAMESPACE@_hash_set_hxx +#define @KWSYS_NAMESPACE@_hash_set_hxx + +#include <@KWSYS_NAMESPACE@/hashtable.hxx> +#include <@KWSYS_NAMESPACE@/hash_fun.hxx> +#include <@KWSYS_NAMESPACE@/stl/functional> // equal_to + +#if defined(_MSC_VER) +# pragma warning (push) +# pragma warning (disable:4284) +# pragma warning (disable:4786) +#endif + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +# pragma set woff 1174 +# pragma set woff 1375 +#endif + +namespace @KWSYS_NAMESPACE@ +{ + +// identity is an extension: it is not part of the standard. +template +struct _Identity : public @KWSYS_NAMESPACE@_stl::unary_function<_Tp,_Tp> +{ + const _Tp& operator()(const _Tp& __x) const { return __x; } +}; + +// Forward declaration of equality operator; needed for friend declaration. + +template , + class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Value>, + class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) > +class hash_set; + +template +inline bool +operator==(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1, + const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2); + +template +class hash_set +{ +private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + +public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::const_pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::const_reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher hash_funct() const { return _M_ht.hash_funct(); } + key_equal key_eq() const { return _M_ht.key_eq(); } + allocator_type get_allocator() const { return _M_ht.get_allocator(); } + +public: + hash_set() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + explicit hash_set(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + hash_set(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + hash_set(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } +#else + + hash_set(const value_type* __f, const value_type* __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_set(const value_type* __f, const value_type* __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_set(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_set(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + hash_set(const_iterator __f, const_iterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_set(const_iterator __f, const_iterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_set(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + hash_set(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } +#endif + +public: + size_type size() const { return _M_ht.size(); } + size_type max_size() const { return _M_ht.max_size(); } + bool empty() const { return _M_ht.empty(); } + void swap(hash_set& __hs) { _M_ht.swap(__hs._M_ht); } + + friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_set&, + const hash_set&); + + iterator begin() const { return _M_ht.begin(); } + iterator end() const { return _M_ht.end(); } + +public: + @KWSYS_NAMESPACE@_stl::pair insert(const value_type& __obj) + { + typedef typename _Ht::iterator _Ht_iterator; + @KWSYS_NAMESPACE@_stl::pair<_Ht_iterator, bool> __p = _M_ht.insert_unique(__obj); + return @KWSYS_NAMESPACE@_stl::pair(__p.first, __p.second); + } +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + void insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f,__l); } +#else + void insert(const value_type* __f, const value_type* __l) { + _M_ht.insert_unique(__f,__l); + } + void insert(const_iterator __f, const_iterator __l) + {_M_ht.insert_unique(__f, __l); } +#endif + @KWSYS_NAMESPACE@_stl::pair insert_noresize(const value_type& __obj) + { + typedef typename _Ht::iterator _Ht_iterator; + @KWSYS_NAMESPACE@_stl::pair<_Ht_iterator, bool> __p = + _M_ht.insert_unique_noresize(__obj); + return @KWSYS_NAMESPACE@_stl::pair(__p.first, __p.second); + } + + iterator find(const key_type& __key) const { return _M_ht.find(__key); } + + size_type count(const key_type& __key) const { return _M_ht.count(__key); } + + @KWSYS_NAMESPACE@_stl::pair equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type erase(const key_type& __key) {return _M_ht.erase(__key); } + void erase(iterator __it) { _M_ht.erase(__it); } + void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); } + void clear() { _M_ht.clear(); } + +public: + void resize(size_type __hint) { _M_ht.resize(__hint); } + size_type bucket_count() const { return _M_ht.bucket_count(); } + size_type max_bucket_count() const { return _M_ht.max_bucket_count(); } + size_type elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } +}; + +template +inline bool +operator==(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1, + const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2) +{ + return __hs1._M_ht == __hs2._M_ht; +} + +template +inline bool +operator!=(const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs1, + const hash_set<_Value,_HashFcn,_EqualKey,_Alloc>& __hs2) { + return !(__hs1 == __hs2); +} + +template +inline void +swap(hash_set<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1, + hash_set<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) +{ + __hs1.swap(__hs2); +} + +template , + class _EqualKey = @KWSYS_NAMESPACE@_stl::equal_to<_Value>, + class _Alloc = @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(char) > +class hash_multiset; + +template +inline bool +operator==(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1, + const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2); + + +template +class hash_multiset +{ +private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + +public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::const_pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::const_reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher hash_funct() const { return _M_ht.hash_funct(); } + key_equal key_eq() const { return _M_ht.key_eq(); } + allocator_type get_allocator() const { return _M_ht.get_allocator(); } + +public: + hash_multiset() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + explicit hash_multiset(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + hash_multiset(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + hash_multiset(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } +#else + + hash_multiset(const value_type* __f, const value_type* __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multiset(const value_type* __f, const value_type* __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multiset(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multiset(const value_type* __f, const value_type* __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + hash_multiset(const_iterator __f, const_iterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multiset(const_iterator __f, const_iterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multiset(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + hash_multiset(const_iterator __f, const_iterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } +#endif + +public: + size_type size() const { return _M_ht.size(); } + size_type max_size() const { return _M_ht.max_size(); } + bool empty() const { return _M_ht.empty(); } + void swap(hash_multiset& hs) { _M_ht.swap(hs._M_ht); } + + friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hash_multiset&, + const hash_multiset&); + + iterator begin() const { return _M_ht.begin(); } + iterator end() const { return _M_ht.end(); } + +public: + iterator insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + void insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } +#else + void insert(const value_type* __f, const value_type* __l) { + _M_ht.insert_equal(__f,__l); + } + void insert(const_iterator __f, const_iterator __l) + { _M_ht.insert_equal(__f, __l); } +#endif + iterator insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator find(const key_type& __key) const { return _M_ht.find(__key); } + + size_type count(const key_type& __key) const { return _M_ht.count(__key); } + + @KWSYS_NAMESPACE@_stl::pair equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type erase(const key_type& __key) {return _M_ht.erase(__key); } + void erase(iterator __it) { _M_ht.erase(__it); } + void erase(iterator __f, iterator __l) { _M_ht.erase(__f, __l); } + void clear() { _M_ht.clear(); } + +public: + void resize(size_type __hint) { _M_ht.resize(__hint); } + size_type bucket_count() const { return _M_ht.bucket_count(); } + size_type max_bucket_count() const { return _M_ht.max_bucket_count(); } + size_type elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } +}; + +template +inline bool +operator==(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1, + const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) +{ + return __hs1._M_ht == __hs2._M_ht; +} + +template +inline bool +operator!=(const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1, + const hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) { + return !(__hs1 == __hs2); +} + +template +inline void +swap(hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs1, + hash_multiset<_Val,_HashFcn,_EqualKey,_Alloc>& __hs2) { + __hs1.swap(__hs2); +} + +} // namespace @KWSYS_NAMESPACE@ + +#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32) +# pragma reset woff 1174 +# pragma reset woff 1375 +#endif + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif diff --git a/Utilities/kwsys/hashtable.hxx.in b/Utilities/kwsys/hashtable.hxx.in new file mode 100644 index 0000000..64022ac --- /dev/null +++ b/Utilities/kwsys/hashtable.hxx.in @@ -0,0 +1,1258 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: hashtable.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +#ifndef @KWSYS_NAMESPACE@_hashtable_hxx +#define @KWSYS_NAMESPACE@_hashtable_hxx + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#include <@KWSYS_NAMESPACE@/cstddef> // size_t +#include <@KWSYS_NAMESPACE@/stl/algorithm> // lower_bound +#include <@KWSYS_NAMESPACE@/stl/functional> // unary_function +#include <@KWSYS_NAMESPACE@/stl/iterator> // iterator_traits +#include <@KWSYS_NAMESPACE@/stl/memory> // allocator +#include <@KWSYS_NAMESPACE@/stl/utility> // pair +#include <@KWSYS_NAMESPACE@/stl/vector> // vector + +#if defined(_MSC_VER) +# pragma warning (push) +# pragma warning (disable:4284) +# pragma warning (disable:4786) +#endif + +#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE +# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator< T > +#elif @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE +# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator +#else +# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::alloc +#endif + +#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS +# define @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a) _M_buckets(__a) +# define @KWSYS_NAMESPACE@_HASH_BUCKETS_GET_ALLOCATOR(__b) , __b.get_allocator() +#else +# define @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a) _M_buckets() +# define @KWSYS_NAMESPACE@_HASH_BUCKETS_GET_ALLOCATOR(__b) +#endif + +namespace @KWSYS_NAMESPACE@ +{ + +//---------------------------------------------------------------------------- +// Define an allocator adaptor for platforms that do not provide an +// allocator with the rebind member. +#if !@KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND + +// Utility functions to convert item counts. +inline size_t hash_sizeof(void*) { return sizeof(char); } +inline size_t hash_sizeof(const void*) { return sizeof(char); } +template inline size_t hash_sizeof(TPtr p) { return sizeof(*p); } +template +inline TSize hash_allocator_n(POut out, PIn in, TSize n) +{ + return n*(hash_sizeof(out)/hash_sizeof(in) + + (hash_sizeof(out)%hash_sizeof(in)>0)); +} + +// Define an allocation method to use the native allocator with +// the proper signature. The following signatures of the allocate +// method are used on various STL implementations: +// pointer allocate(size_type, const void* hint) +// pointer allocate(size_type) +// static pointer allocate(size_type, const void* hint) +// static pointer allocate(size_type) +// Where pointer might be a real type or void*. +// This set of overloads decodes the signature for a particular STL. +// The extra three int/long arguments will favor certain signatures +// over others in the case that multiple are present to avoid +// ambiguity errors. +template +inline void hash_allocate(TAlloc* a, PIn (TAlloc::*allocate)(TSize, THint), + TSize n_out, const void* hint, POut& out, + int, int, int) +{ + TSize n_in = hash_allocator_n(POut(), PIn(), n_out); + void* vout = (a->*allocate)(n_in, const_cast(hint)); + out = static_cast(vout); +} + +template +inline void hash_allocate(TAlloc* a, PIn (TAlloc::*allocate)(TSize), + TSize n_out, const void*, POut& out, + int, int, long) +{ + TSize n_in = hash_allocator_n(POut(), PIn(), n_out); + void* vout = (a->*allocate)(n_in); + out = static_cast(vout); +} + +template +inline void hash_allocate(void*, PIn (*allocate)(TSize, THint), + TSize n_out, const void* hint, POut& out, + int, long, long) +{ + TSize n_in = hash_allocator_n(POut(), PIn(), n_out); + void* vout = allocate(n_in, const_cast(hint)); + out = static_cast(vout); +} + +template +inline void hash_allocate(void*, PIn (*allocate)(TSize), + TSize n_out, const void*, POut& out, + long, long, long) +{ + TSize n_in = hash_allocator_n(POut(), PIn(), n_out); + void* vout = allocate(n_in); + out = static_cast(vout); +} + +// Define a deallocation method to use the native allocator with +// the proper signature. The following signatures of the deallocate +// method are used on various STL implementations: +// void deallocate(pointer, size_type) +// void deallocate(pointer) +// static void deallocate(pointer, size_type) +// static void deallocate(pointer) +// Where pointer might be a real type or void*. +// This set of overloads decodes the signature for a particular STL. +// The extra three int/long arguments will favor certain signatures +// over others in the case that multiple are present to avoid +// ambiguity errors. +template +inline void hash_deallocate(TAlloc* a, void (TAlloc::*deallocate)(PIn, TSize), + PInReal, POut p, TSize n_out, int, int, int) +{ + TSize n_in = hash_allocator_n(POut(), PInReal(), n_out); + void* vout = p; + (a->*deallocate)(static_cast(vout), n_in); +} + +template +inline void hash_deallocate(TAlloc* a, void (TAlloc::*deallocate)(PIn), + PInReal, POut p, TSize, int, int, long) +{ + void* vout = p; + (a->*deallocate)(static_cast(vout)); +} + +template +inline void hash_deallocate(void*, void (*deallocate)(PIn, TSize), + PInReal, POut p, TSize n_out, int, long, long) +{ + TSize n_in = hash_allocator_n(POut(), PInReal(), n_out); + void* vout = p; + deallocate(static_cast(vout), n_in); +} + +template +inline void hash_deallocate(void*, void (*deallocate)(PIn), + PInReal, POut p, TSize, long, long, long) +{ + void* vout = p; + deallocate(static_cast(vout)); +} + +// Use the same four overloads as hash_allocate to decode the type +// really used for allocation. This is passed as PInReal to the +// deallocate functions so that hash_allocator_n has the proper size. +template +inline PIn hash_allocate_type(PIn (TAlloc::*)(TSize, THint), + int, int, int) { return 0; } +template +inline PIn hash_allocate_type(PIn (TAlloc::*)(TSize), + int, int, long) { return 0; } +template +inline PIn hash_allocate_type(PIn (*)(TSize, THint), + int, long, long) { return 0; } +template +inline PIn hash_allocate_type(PIn (*)(TSize), + long, long, long) { return 0; } + +// Define the comparison operators in terms of a base type to avoid +// needing templated versions. +class hash_allocator_base {}; +bool operator==(const hash_allocator_base&, + const hash_allocator_base&) throw() { return true; } +bool operator!=(const hash_allocator_base&, + const hash_allocator_base&) throw() { return false; } + +// Define the allocator template. +template +class hash_allocator: public hash_allocator_base +{ +private: + // Store the real allocator privately. + typedef Alloc alloc_type; + alloc_type alloc_; + +public: + // Standard allocator interface. + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + hash_allocator() throw(): alloc_() {} + hash_allocator(const hash_allocator_base&) throw() : alloc_() {} + hash_allocator(const hash_allocator& a) throw() : alloc_(a.alloc_) {} + hash_allocator(const alloc_type& a) throw() : alloc_(a) {} + ~hash_allocator() throw() {} +# if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES + template + struct rebind { typedef hash_allocator other; }; +# endif + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + typedef void* void_pointer; + typedef const void* const_void_pointer; + pointer allocate(size_type n=1, const_void_pointer hint = 0) + { + if(n) + { + pointer p; + hash_allocate(&alloc_, &alloc_type::allocate, n, hint, p, 1, 1, 1); + return p; + } + else + { + return 0; + } + } + void deallocate(pointer p, size_type n=1) + { + if(n) + { + hash_deallocate(&alloc_, &alloc_type::deallocate, + hash_allocate_type(&alloc_type::allocate, 1, 1, 1), + p, n, 1, 1, 1); + } + } +#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT + size_type max_size(size_type s) const throw() + { + return alloc_.max_size(s); + } +#else + size_type max_size() const throw() + { + size_type n = alloc_.max_size() / sizeof(value_type); + return n>0? n:1; + } +#endif + void construct(pointer p, const value_type& val) { new (p) value_type(val); } + void destroy(pointer p) { (void)p; p->~value_type(); } +}; +#endif + +template +struct _Hashtable_node +{ + _Hashtable_node* _M_next; + _Val _M_val; +}; + +template +class hashtable; + +template +struct _Hashtable_iterator; + +template +struct _Hashtable_const_iterator; + +template +struct _Hashtable_iterator { + typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc> + _Hashtable; + typedef _Hashtable_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + const_iterator; + typedef _Hashtable_node<_Val> _Node; + + typedef @KWSYS_NAMESPACE@_stl::forward_iterator_tag iterator_category; + typedef _Val value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef _Val& reference; + typedef _Val* pointer; + + _Node* _M_cur; + _Hashtable* _M_ht; + + _Hashtable_iterator(_Node* __n, _Hashtable* __tab) + : _M_cur(__n), _M_ht(__tab) {} + _Hashtable_iterator() {} + reference operator*() const { return _M_cur->_M_val; } + pointer operator->() const { return &(operator*()); } + iterator& operator++(); + iterator operator++(int); + bool operator==(const iterator& __it) const + { return _M_cur == __it._M_cur; } + bool operator!=(const iterator& __it) const + { return _M_cur != __it._M_cur; } +}; + + +template +struct _Hashtable_const_iterator { + typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc> + _Hashtable; + typedef _Hashtable_iterator<_Val,_Key,_HashFcn, + _ExtractKey,_EqualKey,_Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + const_iterator; + typedef _Hashtable_node<_Val> _Node; + + typedef @KWSYS_NAMESPACE@_stl::forward_iterator_tag iterator_category; + typedef _Val value_type; + typedef ptrdiff_t difference_type; + typedef size_t size_type; + typedef const _Val& reference; + typedef const _Val* pointer; + + const _Node* _M_cur; + const _Hashtable* _M_ht; + + _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab) + : _M_cur(__n), _M_ht(__tab) {} + _Hashtable_const_iterator() {} + _Hashtable_const_iterator(const iterator& __it) + : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {} + reference operator*() const { return _M_cur->_M_val; } + pointer operator->() const { return &(operator*()); } + const_iterator& operator++(); + const_iterator operator++(int); + bool operator==(const const_iterator& __it) const + { return _M_cur == __it._M_cur; } + bool operator!=(const const_iterator& __it) const + { return _M_cur != __it._M_cur; } +}; + +// Note: assumes long is at least 32 bits. +enum { _stl_num_primes = 31 }; + +static const unsigned long _stl_prime_list[_stl_num_primes] = +{ + 5ul, 11ul, 23ul, + 53ul, 97ul, 193ul, 389ul, 769ul, + 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, + 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, + 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, + 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, + 1610612741ul, 3221225473ul, 4294967291ul +}; + +inline unsigned long _stl_next_prime(unsigned long __n) +{ + const unsigned long* __first = _stl_prime_list; + const unsigned long* __last = _stl_prime_list + (int)_stl_num_primes; + const unsigned long* pos = @KWSYS_NAMESPACE@_stl::lower_bound(__first, __last, __n); + return pos == __last ? *(__last - 1) : *pos; +} + +// Forward declaration of operator==. + +template +class hashtable; + +template +bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1, + const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2); + +// Hashtables handle allocators a bit differently than other containers +// do. If we're using standard-conforming allocators, then a hashtable +// unconditionally has a member variable to hold its allocator, even if +// it so happens that all instances of the allocator type are identical. +// This is because, for hashtables, this extra storage is negligible. +// Additionally, a base class wouldn't serve any other purposes; it +// wouldn't, for example, simplify the exception-handling code. + +template +class hashtable { +public: + typedef _Key key_type; + typedef _Val value_type; + typedef _HashFcn hasher; + typedef _EqualKey key_equal; + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + hasher hash_funct() const { return _M_hash; } + key_equal key_eq() const { return _M_equals; } + +private: + typedef _Hashtable_node<_Val> _Node; + +#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_REBIND +public: + typedef typename _Alloc::template rebind<_Val>::other allocator_type; + allocator_type get_allocator() const { return _M_node_allocator; } +private: + typedef typename _Alloc::template rebind<_Node>::other _M_node_allocator_type; + typedef typename _Alloc::template rebind<_Node*>::other _M_node_ptr_allocator_type; + typedef @KWSYS_NAMESPACE@_stl::vector<_Node*,_M_node_ptr_allocator_type> _M_buckets_type; +#else +public: + typedef hash_allocator<_Val, _Alloc> allocator_type; + allocator_type get_allocator() const { return allocator_type(); } +private: + typedef hash_allocator<_Node, _Alloc> _M_node_allocator_type; +# if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_OBJECTS + typedef hash_allocator<_Node*, _Alloc> _M_node_ptr_allocator_type; +# else + typedef _Alloc _M_node_ptr_allocator_type; +# endif + typedef @KWSYS_NAMESPACE@_stl::vector<_Node*,_M_node_ptr_allocator_type> _M_buckets_type; +#endif + +private: + _M_node_allocator_type _M_node_allocator; + hasher _M_hash; + key_equal _M_equals; + _ExtractKey _M_get_key; + _M_buckets_type _M_buckets; + size_type _M_num_elements; + + _Node* _M_get_node() { return _M_node_allocator.allocate(1); } + void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); } + +public: + typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey, + _Alloc> + const_iterator; + + friend struct + _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>; + friend struct + _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>; + +public: + hashtable(size_type __n, + const _HashFcn& __hf, + const _EqualKey& __eql, + const _ExtractKey& __ext, + const allocator_type& __a = allocator_type()) + : _M_node_allocator(__a), + _M_hash(__hf), + _M_equals(__eql), + _M_get_key(__ext), + @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a), + _M_num_elements(0) + { + _M_initialize_buckets(__n); + } + + hashtable(size_type __n, + const _HashFcn& __hf, + const _EqualKey& __eql, + const allocator_type& __a = allocator_type()) + : _M_node_allocator(__a), + _M_hash(__hf), + _M_equals(__eql), + _M_get_key(_ExtractKey()), + @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__a), + _M_num_elements(0) + { + _M_initialize_buckets(__n); + } + + hashtable(const hashtable& __ht) + : _M_node_allocator(__ht.get_allocator()), + _M_hash(__ht._M_hash), + _M_equals(__ht._M_equals), + _M_get_key(__ht._M_get_key), + @KWSYS_NAMESPACE@_HASH_BUCKETS_INIT(__ht.get_allocator()), + _M_num_elements(0) + { + _M_copy_from(__ht); + } + + hashtable& operator= (const hashtable& __ht) + { + if (&__ht != this) { + clear(); + _M_hash = __ht._M_hash; + _M_equals = __ht._M_equals; + _M_get_key = __ht._M_get_key; + _M_copy_from(__ht); + } + return *this; + } + + ~hashtable() { clear(); } + + size_type size() const { return _M_num_elements; } + size_type max_size() const { return size_type(-1); } + bool empty() const { return size() == 0; } + + void swap(hashtable& __ht) + { + @KWSYS_NAMESPACE@_stl::swap(_M_hash, __ht._M_hash); + @KWSYS_NAMESPACE@_stl::swap(_M_equals, __ht._M_equals); + @KWSYS_NAMESPACE@_stl::swap(_M_get_key, __ht._M_get_key); + _M_buckets.swap(__ht._M_buckets); + @KWSYS_NAMESPACE@_stl::swap(_M_num_elements, __ht._M_num_elements); + } + + iterator begin() + { + for (size_type __n = 0; __n < _M_buckets.size(); ++__n) + if (_M_buckets[__n]) + return iterator(_M_buckets[__n], this); + return end(); + } + + iterator end() { return iterator(0, this); } + + const_iterator begin() const + { + for (size_type __n = 0; __n < _M_buckets.size(); ++__n) + if (_M_buckets[__n]) + return const_iterator(_M_buckets[__n], this); + return end(); + } + + const_iterator end() const { return const_iterator(0, this); } + + friend bool operator==@KWSYS_NAMESPACE@_CXX_NULL_TEMPLATE_ARGS(const hashtable&, + const hashtable&); + +public: + + size_type bucket_count() const { return _M_buckets.size(); } + + size_type max_bucket_count() const + { return _stl_prime_list[(int)_stl_num_primes - 1]; } + + size_type elems_in_bucket(size_type __bucket) const + { + size_type __result = 0; + for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next) + __result += 1; + return __result; + } + + @KWSYS_NAMESPACE@_stl::pair insert_unique(const value_type& __obj) + { + resize(_M_num_elements + 1); + return insert_unique_noresize(__obj); + } + + iterator insert_equal(const value_type& __obj) + { + resize(_M_num_elements + 1); + return insert_equal_noresize(__obj); + } + + @KWSYS_NAMESPACE@_stl::pair insert_unique_noresize(const value_type& __obj); + iterator insert_equal_noresize(const value_type& __obj); + +#if @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_TRAITS +# define @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(T,I) \ + typename @KWSYS_NAMESPACE@_stl::iterator_traits< T >::iterator_category() +#elif @KWSYS_NAMESPACE@_STL_HAS_ITERATOR_CATEGORY +# define @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(T,I) \ + @KWSYS_NAMESPACE@_stl::iterator_category( I ) +#elif @KWSYS_NAMESPACE@_STL_HAS___ITERATOR_CATEGORY +# define @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(T,I) \ + @KWSYS_NAMESPACE@_stl::__iterator_category( I ) +#endif + +#if @KWSYS_NAMESPACE@_CXX_HAS_MEMBER_TEMPLATES && defined(@KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY) + template + void insert_unique(_InputIterator __f, _InputIterator __l) + { + insert_unique(__f, __l, + @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(_InputIterator, __f)); + } + + template + void insert_equal(_InputIterator __f, _InputIterator __l) + { + insert_equal(__f, __l, + @KWSYS_NAMESPACE@_HASH_ITERATOR_CATEGORY(_InputIterator, __f)); + } + + template + void insert_unique(_InputIterator __f, _InputIterator __l, + @KWSYS_NAMESPACE@_stl::input_iterator_tag) + { + for ( ; __f != __l; ++__f) + insert_unique(*__f); + } + + template + void insert_equal(_InputIterator __f, _InputIterator __l, + @KWSYS_NAMESPACE@_stl::input_iterator_tag) + { + for ( ; __f != __l; ++__f) + insert_equal(*__f); + } + + template + void insert_unique(_ForwardIterator __f, _ForwardIterator __l, + @KWSYS_NAMESPACE@_stl::forward_iterator_tag) + { + size_type __n = 0; + @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_unique_noresize(*__f); + } + + template + void insert_equal(_ForwardIterator __f, _ForwardIterator __l, + @KWSYS_NAMESPACE@_stl::forward_iterator_tag) + { + size_type __n = 0; + @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_equal_noresize(*__f); + } + +#else + void insert_unique(const value_type* __f, const value_type* __l) + { + size_type __n = __l - __f; + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_unique_noresize(*__f); + } + + void insert_equal(const value_type* __f, const value_type* __l) + { + size_type __n = __l - __f; + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_equal_noresize(*__f); + } + + void insert_unique(const_iterator __f, const_iterator __l) + { + size_type __n = 0; + @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_unique_noresize(*__f); + } + + void insert_equal(const_iterator __f, const_iterator __l) + { + size_type __n = 0; + @KWSYS_NAMESPACE@_stl::distance(__f, __l, __n); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_equal_noresize(*__f); + } +#endif + + reference find_or_insert(const value_type& __obj); + + iterator find(const key_type& __key) + { + size_type __n = _M_bkt_num_key(__key); + _Node* __first; + for ( __first = _M_buckets[__n]; + __first && !_M_equals(_M_get_key(__first->_M_val), __key); + __first = __first->_M_next) + {} + return iterator(__first, this); + } + + const_iterator find(const key_type& __key) const + { + size_type __n = _M_bkt_num_key(__key); + const _Node* __first; + for ( __first = _M_buckets[__n]; + __first && !_M_equals(_M_get_key(__first->_M_val), __key); + __first = __first->_M_next) + {} + return const_iterator(__first, this); + } + + size_type count(const key_type& __key) const + { + const size_type __n = _M_bkt_num_key(__key); + size_type __result = 0; + + for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), __key)) + ++__result; + return __result; + } + + @KWSYS_NAMESPACE@_stl::pair + equal_range(const key_type& __key); + + @KWSYS_NAMESPACE@_stl::pair + equal_range(const key_type& __key) const; + + size_type erase(const key_type& __key); + void erase(const iterator& __it); + void erase(iterator __first, iterator __last); + + void erase(const const_iterator& __it); + void erase(const_iterator __first, const_iterator __last); + + void resize(size_type __num_elements_hint); + void clear(); + +private: + size_type _M_next_size(size_type __n) const + { return _stl_next_prime(__n); } + + void _M_initialize_buckets(size_type __n) + { + const size_type __n_buckets = _M_next_size(__n); + _M_buckets.reserve(__n_buckets); + _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0); + _M_num_elements = 0; + } + + size_type _M_bkt_num_key(const key_type& __key) const + { + return _M_bkt_num_key(__key, _M_buckets.size()); + } + + size_type _M_bkt_num(const value_type& __obj) const + { + return _M_bkt_num_key(_M_get_key(__obj)); + } + + size_type _M_bkt_num_key(const key_type& __key, size_t __n) const + { + return _M_hash(__key) % __n; + } + + size_type _M_bkt_num(const value_type& __obj, size_t __n) const + { + return _M_bkt_num_key(_M_get_key(__obj), __n); + } + + void construct(_Val* p, const _Val& v) + { + new (p) _Val(v); + } + void destroy(_Val* p) + { + (void)p; + p->~_Val(); + } + + _Node* _M_new_node(const value_type& __obj) + { + _Node* __n = _M_get_node(); + __n->_M_next = 0; + try { + construct(&__n->_M_val, __obj); + return __n; + } + catch(...) {_M_put_node(__n); throw;} + } + + void _M_delete_node(_Node* __n) + { + destroy(&__n->_M_val); + _M_put_node(__n); + } + + void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last); + void _M_erase_bucket(const size_type __n, _Node* __last); + + void _M_copy_from(const hashtable& __ht); + +}; + +template +_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>& +_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++() +{ + const _Node* __old = _M_cur; + _M_cur = _M_cur->_M_next; + if (!_M_cur) { + size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); + while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) + _M_cur = _M_ht->_M_buckets[__bucket]; + } + return *this; +} + +template +inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All> +_Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int) +{ + iterator __tmp = *this; + ++*this; + return __tmp; +} + +template +_Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>& +_Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++() +{ + const _Node* __old = _M_cur; + _M_cur = _M_cur->_M_next; + if (!_M_cur) { + size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); + while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) + _M_cur = _M_ht->_M_buckets[__bucket]; + } + return *this; +} + +template +inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All> +_Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int) +{ + const_iterator __tmp = *this; + ++*this; + return __tmp; +} + +template +bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1, + const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) +{ + typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node; + if (__ht1._M_buckets.size() != __ht2._M_buckets.size()) + return false; + for (int __n = 0; __n < __ht1._M_buckets.size(); ++__n) { + _Node* __cur1 = __ht1._M_buckets[__n]; + _Node* __cur2 = __ht2._M_buckets[__n]; + for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val; + __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next) + {} + if (__cur1 || __cur2) + return false; + } + return true; +} + +template +inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1, + const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) { + return !(__ht1 == __ht2); +} + +template +inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1, + hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) { + __ht1.swap(__ht2); +} + +template +@KWSYS_NAMESPACE@_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool> +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::insert_unique_noresize(const value_type& __obj) +{ + const size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + return @KWSYS_NAMESPACE@_stl::pair(iterator(__cur, this), false); + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return @KWSYS_NAMESPACE@_stl::pair(iterator(__tmp, this), true); +} + +template +typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::insert_equal_noresize(const value_type& __obj) +{ + const size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) { + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __cur->_M_next; + __cur->_M_next = __tmp; + ++_M_num_elements; + return iterator(__tmp, this); + } + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return iterator(__tmp, this); +} + +template +typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj) +{ + resize(_M_num_elements + 1); + + size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + return __cur->_M_val; + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return __tmp->_M_val; +} + +template +@KWSYS_NAMESPACE@_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, + @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator> +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key) +{ + typedef @KWSYS_NAMESPACE@_stl::pair _Pii; + const size_type __n = _M_bkt_num_key(__key); + + for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next) + if (_M_equals(_M_get_key(__first->_M_val), __key)) { + for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next) + if (!_M_equals(_M_get_key(__cur->_M_val), __key)) + return _Pii(iterator(__first, this), iterator(__cur, this)); + for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) + if (_M_buckets[__m]) + return _Pii(iterator(__first, this), + iterator(_M_buckets[__m], this)); + return _Pii(iterator(__first, this), end()); + } + return _Pii(end(), end()); +} + +template +@KWSYS_NAMESPACE@_stl::pair<@KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator, + @KWSYS_NAMESPACE@_CXX_DECL_TYPENAME hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator> +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::equal_range(const key_type& __key) const +{ + typedef @KWSYS_NAMESPACE@_stl::pair _Pii; + const size_type __n = _M_bkt_num_key(__key); + + for (const _Node* __first = _M_buckets[__n] ; + __first; + __first = __first->_M_next) { + if (_M_equals(_M_get_key(__first->_M_val), __key)) { + for (const _Node* __cur = __first->_M_next; + __cur; + __cur = __cur->_M_next) + if (!_M_equals(_M_get_key(__cur->_M_val), __key)) + return _Pii(const_iterator(__first, this), + const_iterator(__cur, this)); + for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) + if (_M_buckets[__m]) + return _Pii(const_iterator(__first, this), + const_iterator(_M_buckets[__m], this)); + return _Pii(const_iterator(__first, this), end()); + } + } + return _Pii(end(), end()); +} + +template +typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key) +{ + const size_type __n = _M_bkt_num_key(__key); + _Node* __first = _M_buckets[__n]; + size_type __erased = 0; + + if (__first) { + _Node* __cur = __first; + _Node* __next = __cur->_M_next; + while (__next) { + if (_M_equals(_M_get_key(__next->_M_val), __key)) { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + __next = __cur->_M_next; + ++__erased; + --_M_num_elements; + } + else { + __cur = __next; + __next = __cur->_M_next; + } + } + if (_M_equals(_M_get_key(__first->_M_val), __key)) { + _M_buckets[__n] = __first->_M_next; + _M_delete_node(__first); + ++__erased; + --_M_num_elements; + } + } + return __erased; +} + +template +void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it) +{ + _Node* __p = __it._M_cur; + if (__p) { + const size_type __n = _M_bkt_num(__p->_M_val); + _Node* __cur = _M_buckets[__n]; + + if (__cur == __p) { + _M_buckets[__n] = __cur->_M_next; + _M_delete_node(__cur); + --_M_num_elements; + } + else { + _Node* __next = __cur->_M_next; + while (__next) { + if (__next == __p) { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + --_M_num_elements; + break; + } + else { + __cur = __next; + __next = __cur->_M_next; + } + } + } + } +} + +template +void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::erase(iterator __first, iterator __last) +{ + size_type __f_bucket = __first._M_cur ? + _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size(); + size_type __l_bucket = __last._M_cur ? + _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size(); + + if (__first._M_cur == __last._M_cur) + return; + else if (__f_bucket == __l_bucket) + _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur); + else { + _M_erase_bucket(__f_bucket, __first._M_cur, 0); + for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n) + _M_erase_bucket(__n, 0); + if (__l_bucket != _M_buckets.size()) + _M_erase_bucket(__l_bucket, __last._M_cur); + } +} + +template +inline void +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first, + const_iterator __last) +{ + erase(iterator(const_cast<_Node*>(__first._M_cur), + const_cast(__first._M_ht)), + iterator(const_cast<_Node*>(__last._M_cur), + const_cast(__last._M_ht))); +} + +template +inline void +hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it) +{ + erase(iterator(const_cast<_Node*>(__it._M_cur), + const_cast(__it._M_ht))); +} + +template +void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::resize(size_type __num_elements_hint) +{ + const size_type __old_n = _M_buckets.size(); + if (__num_elements_hint > __old_n) { + const size_type __n = _M_next_size(__num_elements_hint); + if (__n > __old_n) { + _M_buckets_type __tmp( + __n, (_Node*)(0) + @KWSYS_NAMESPACE@_HASH_BUCKETS_GET_ALLOCATOR(_M_buckets)); + try { + for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) { + _Node* __first = _M_buckets[__bucket]; + while (__first) { + size_type __new_bucket = _M_bkt_num(__first->_M_val, __n); + _M_buckets[__bucket] = __first->_M_next; + __first->_M_next = __tmp[__new_bucket]; + __tmp[__new_bucket] = __first; + __first = _M_buckets[__bucket]; + } + } + _M_buckets.swap(__tmp); + } + catch(...) { + for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) { + while (__tmp[__bucket]) { + _Node* __next = __tmp[__bucket]->_M_next; + _M_delete_node(__tmp[__bucket]); + __tmp[__bucket] = __next; + } + } + throw; + } + } + } +} + +template +void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last) +{ + _Node* __cur = _M_buckets[__n]; + if (__cur == __first) + _M_erase_bucket(__n, __last); + else { + _Node* __next; + for (__next = __cur->_M_next; + __next != __first; + __cur = __next, __next = __cur->_M_next) + ; + while (__next != __last) { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + __next = __cur->_M_next; + --_M_num_elements; + } + } +} + +template +void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::_M_erase_bucket(const size_type __n, _Node* __last) +{ + _Node* __cur = _M_buckets[__n]; + while (__cur != __last) { + _Node* __next = __cur->_M_next; + _M_delete_node(__cur); + __cur = __next; + _M_buckets[__n] = __cur; + --_M_num_elements; + } +} + +template +void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear() +{ + for (size_type __i = 0; __i < _M_buckets.size(); ++__i) { + _Node* __cur = _M_buckets[__i]; + while (__cur != 0) { + _Node* __next = __cur->_M_next; + _M_delete_node(__cur); + __cur = __next; + } + _M_buckets[__i] = 0; + } + _M_num_elements = 0; +} + + +template +void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> + ::_M_copy_from(const hashtable& __ht) +{ + _M_buckets.clear(); + _M_buckets.reserve(__ht._M_buckets.size()); + _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0); + try { + for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) { + const _Node* __cur = __ht._M_buckets[__i]; + if (__cur) { + _Node* __copy = _M_new_node(__cur->_M_val); + _M_buckets[__i] = __copy; + + for (_Node* __next = __cur->_M_next; + __next; + __cur = __next, __next = __cur->_M_next) { + __copy->_M_next = _M_new_node(__next->_M_val); + __copy = __copy->_M_next; + } + } + } + _M_num_elements = __ht._M_num_elements; + } + catch(...) {clear(); throw;} +} + +} // namespace @KWSYS_NAMESPACE@ + +// Normally the comparison operators should be found in the @KWSYS_NAMESPACE@ +// namespace by argument dependent lookup. For compilers that do not +// support it we must bring them into the global namespace now. +#if !@KWSYS_NAMESPACE@_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP +using @KWSYS_NAMESPACE@::operator==; +using @KWSYS_NAMESPACE@::operator!=; +#endif + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +#endif diff --git a/Utilities/kwsys/kwsysHeaderDump.pl b/Utilities/kwsys/kwsysHeaderDump.pl new file mode 100644 index 0000000..4631b91 --- /dev/null +++ b/Utilities/kwsys/kwsysHeaderDump.pl @@ -0,0 +1,50 @@ +#!/usr/bin/perl +# +# Program: KWSys - Kitware System Library +# Module: $RCSfile: kwsysHeaderDump.pl,v $ +# +# Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. +# See Copyright.txt or http://www.kitware.com/Copyright.htm for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even +# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the above copyright notices for more information. +# + +if ( $#ARGV+1 < 2 ) +{ + print "Usage: ./kwsysHeaderDump.pl
\n"; + exit(1); +} + +$name = $ARGV[0]; +$max = 0; +open(INFILE, $ARGV[1]); +while (chomp ($line = )) +{ + if (($line !~ /^\#/) && + ($line =~ s/.*kwsys${name}_([A-Za-z0-9_]*).*/\1/) && + ($i{$line}++ < 1)) + { + push(@lines, "$line"); + if (length($line) > $max) + { + $max = length($line); + } + } +} +close(INFILE); + +$width = $max + 13; +print sprintf("#define %-${width}s kwsys_ns(${name})\n", "kwsys${name}"); +foreach $l (@lines) +{ + print sprintf("#define %-${width}s kwsys_ns(${name}_$l)\n", + "kwsys${name}_$l"); +} +print "\n"; +print sprintf("# undef kwsys${name}\n"); +foreach $l (@lines) +{ + print sprintf("# undef kwsys${name}_$l\n"); +} diff --git a/Utilities/kwsys/kwsysPlatformCxxTests.cmake b/Utilities/kwsys/kwsysPlatformCxxTests.cmake new file mode 100644 index 0000000..0bd8b62 --- /dev/null +++ b/Utilities/kwsys/kwsysPlatformCxxTests.cmake @@ -0,0 +1,43 @@ +MACRO(KWSYS_PLATFORM_CXX_TEST var description invert) + IF("${var}_COMPILED" MATCHES "^${var}_COMPILED$") + MESSAGE(STATUS "${description}") + TRY_COMPILE(${var}_COMPILED + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformCxxTests.cxx + COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_CXX_TEST_DEFINES} + OUTPUT_VARIABLE OUTPUT) + IF(${var}_COMPILED) + WRITE_FILE(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "${description} compiled with the following output:\n${OUTPUT}\n\n" APPEND) + ELSE(${var}_COMPILED) + WRITE_FILE(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeError.log + "${description} failed to compile with the following output:\n${OUTPUT}\n\n" APPEND) + ENDIF(${var}_COMPILED) + IF(${invert} MATCHES INVERT) + IF(${var}_COMPILED) + MESSAGE(STATUS "${description} - no") + ELSE(${var}_COMPILED) + MESSAGE(STATUS "${description} - yes") + ENDIF(${var}_COMPILED) + ELSE(${invert} MATCHES INVERT) + IF(${var}_COMPILED) + MESSAGE(STATUS "${description} - yes") + ELSE(${var}_COMPILED) + MESSAGE(STATUS "${description} - no") + ENDIF(${var}_COMPILED) + ENDIF(${invert} MATCHES INVERT) + ENDIF("${var}_COMPILED" MATCHES "^${var}_COMPILED$") + IF(${invert} MATCHES INVERT) + IF(${var}_COMPILED) + SET(${var} 0) + ELSE(${var}_COMPILED) + SET(${var} 1) + ENDIF(${var}_COMPILED) + ELSE(${invert} MATCHES INVERT) + IF(${var}_COMPILED) + SET(${var} 1) + ELSE(${var}_COMPILED) + SET(${var} 0) + ENDIF(${var}_COMPILED) + ENDIF(${invert} MATCHES INVERT) +ENDMACRO(KWSYS_PLATFORM_CXX_TEST) diff --git a/Utilities/kwsys/kwsysPlatformCxxTests.cxx b/Utilities/kwsys/kwsysPlatformCxxTests.cxx new file mode 100644 index 0000000..4187bcc --- /dev/null +++ b/Utilities/kwsys/kwsysPlatformCxxTests.cxx @@ -0,0 +1,267 @@ +// Setup for tests that use result of stl namespace test. +#if defined(KWSYS_STL_HAVE_STD) +# if KWSYS_STL_HAVE_STD +# define kwsys_stl std +# else +# define kwsys_stl +# endif +#endif + +#ifdef TEST_KWSYS_STL_HAVE_STD +#include +void f(std::list*) {} +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_IOS_USE_ANSI +#include +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_IOS_HAVE_STD +#include +void f(std::ostream*) {} +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_IOS_USE_SSTREAM +#include +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_IOS_USE_STRSTREAM_H +#include +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_IOS_USE_STRSTREA_H +#include +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_STL_STRING_HAVE_OSTREAM +# include +# include +void f(ostream& os, const kwsys_stl::string& s) { os << s; } +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_STL_STRING_HAVE_ISTREAM +# include +# include +void f(istream& is, kwsys_stl::string& s) { is >> s; } +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_STL_STRING_HAVE_NEQ_CHAR +# include +bool f(const kwsys_stl::string& s) { return s != ""; } +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_CXX_HAS_CSTDDEF +#include +void f(size_t) {} +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS +template class A; +template int f(A&); +template class A +{ +public: + // "friend int f<>(A&)" would conform + friend int f(A&); +private: + int x; +}; + +template int f(A& a) { return a.x = 0; } +template int f(A&); + +int main() +{ + A a; + return f(a); +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_MEMBER_TEMPLATES +template +class A +{ +public: + U u; + A(): u(0) {} + template V m(V* p) { return *p = u; } +}; + +int main() +{ + A a; + int s = 1; + return a.m(&s); +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_FULL_SPECIALIZATION +template struct A {}; +template <> struct A +{ + static int f() { return 0; } +}; +int main() { return A::f(); } +#endif + +#ifdef TEST_KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP +namespace N +{ + class A {}; + int f(A*) { return 0; } +} +void f(void*); +int main() +{ + N::A* a = 0; + return f(a); +} +#endif + +#ifdef TEST_KWSYS_STL_HAS_ITERATOR_TRAITS +#include +#include +void f(kwsys_stl::iterator_traits::iterator>::iterator_category const&) {} +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_STL_HAS_ITERATOR_CATEGORY +#include +#include +void f(kwsys_stl::list::iterator x) { kwsys_stl::iterator_category(x); } +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_STL_HAS___ITERATOR_CATEGORY +#include +#include +void f(kwsys_stl::list::iterator x) { kwsys_stl::__iterator_category(x); } +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_TEMPLATE +#include +template +void f(const Alloc&) +{ + typedef typename Alloc::size_type alloc_size_type; +} +int main() +{ + f(kwsys_stl::allocator()); + return 0; +} +#endif + +#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE +#include +void f(kwsys_stl::allocator::size_type const&) {} +int main() { return 0; } +#endif + +#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_REBIND +#include +template +void f(const T&, const Alloc&) +{ + typedef typename Alloc::template rebind::other alloc_type; +} +int main() +{ + f(0, kwsys_stl::allocator()); + return 0; +} +#endif + +#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT +#include +void f(kwsys_stl::allocator const& a) +{ + a.max_size(sizeof(int)); +} +int main() +{ + f(kwsys_stl::allocator()); + return 0; +} +#endif + +#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_OBJECTS +#include +void f(kwsys_stl::vector const& v1) +{ + kwsys_stl::vector(1, 1, v1.get_allocator()); +} +int main() +{ + f(kwsys_stl::vector()); + return 0; +} +#endif + +#ifdef TEST_KWSYS_STAT_HAS_ST_MTIM +#include +#include +#include +int main() +{ + struct stat stat1; + (void)stat1.st_mtim.tv_sec; + (void)stat1.st_mtim.tv_nsec; + return 0; +} +#endif + +#ifdef TEST_KWSYS_CXX_SAME_LONG_AND___INT64 +void function(long**) {} +int main() +{ + __int64** p = 0; + function(p); + return 0; +} +#endif + +#ifdef TEST_KWSYS_CXX_SAME_LONG_LONG_AND___INT64 +void function(long long**) {} +int main() +{ + __int64** p = 0; + function(p); + return 0; +} +#endif + +#ifdef TEST_KWSYS_CAN_CONVERT_UI64_TO_DOUBLE +void function(double& l, unsigned __int64 const& r) +{ + l = static_cast(r); +} + +int main() +{ + double tTo = 0.0; + unsigned __int64 tFrom = 0; + function(tTo, tFrom); + return 0; +} +#endif + +#ifdef TEST_KWSYS_CHAR_IS_SIGNED +/* Return 1 for char signed and 0 for char unsigned. */ +int main() +{ + unsigned char uc = 255; + return (*reinterpret_cast(&uc) < 0)?1:0; +} +#endif diff --git a/Utilities/kwsys/kwsysPrivate.h b/Utilities/kwsys/kwsysPrivate.h new file mode 100644 index 0000000..1b614c9 --- /dev/null +++ b/Utilities/kwsys/kwsysPrivate.h @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsysPrivate.h,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef KWSYS_NAMESPACE +# error "Do not include kwsysPrivate.h outside of kwsys c and cxx files." +#endif + +#ifndef _kwsysPrivate_h +#define _kwsysPrivate_h + +/* + Define KWSYS_HEADER macro to help the c and cxx files include kwsys + headers from the configured namespace directory. The macro can be + used like this: + + #include KWSYS_HEADER(Directory.hxx) + #include KWSYS_HEADER(std/vector) +*/ +#define KWSYS_HEADER(x) KWSYS_HEADER0(KWSYS_NAMESPACE/x) +#define KWSYS_HEADER0(x) KWSYS_HEADER1(x) +#define KWSYS_HEADER1(x) + +/* + Define KWSYS_NAMESPACE_STRING to be a string constant containing the + name configured for this instance of the kwsys library. +*/ +#define KWSYS_NAMESPACE_STRING KWSYS_NAMESPACE_STRING0(KWSYS_NAMESPACE) +#define KWSYS_NAMESPACE_STRING0(x) KWSYS_NAMESPACE_STRING1(x) +#define KWSYS_NAMESPACE_STRING1(x) #x + +#else +# error "kwsysPrivate.h included multiple times." +#endif diff --git a/Utilities/kwsys/kwsys_cstddef.hxx.in b/Utilities/kwsys/kwsys_cstddef.hxx.in new file mode 100644 index 0000000..2c95759 --- /dev/null +++ b/Utilities/kwsys/kwsys_cstddef.hxx.in @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsys_cstddef.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_cstddef +#define @KWSYS_NAMESPACE@_cstddef + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +/* Avoid warnings in MSVC standard headers. */ +#ifdef _MSC_VER +# pragma warning (push, 1) +# pragma warning (disable: 4702) +# pragma warning (disable: 4786) +#endif + +/* Include the real header. */ +#if @KWSYS_NAMESPACE@_CXX_HAS_CSTDDEF +# include +#else +# include +#endif + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/Utilities/kwsys/kwsys_ios_fstream.h.in b/Utilities/kwsys/kwsys_ios_fstream.h.in new file mode 100644 index 0000000..b20ac0e --- /dev/null +++ b/Utilities/kwsys/kwsys_ios_fstream.h.in @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsys_ios_fstream.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_ios_fstream +#define @KWSYS_NAMESPACE@_ios_fstream + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#ifdef _MSC_VER +# pragma warning (push, 1) +# pragma warning (disable: 4702) +# pragma warning (disable: 4995) /* Old streams are deprecated. */ +#endif + +#if @KWSYS_NAMESPACE@_IOS_USE_ANSI +# include +#else +# include +#endif + +#if !@KWSYS_NAMESPACE@_IOS_USE_SSTREAM +namespace @KWSYS_NAMESPACE@_ios +{ + using @KWSYS_NAMESPACE@_ios_namespace::ostream; + using @KWSYS_NAMESPACE@_ios_namespace::istream; + using @KWSYS_NAMESPACE@_ios_namespace::ofstream; + using @KWSYS_NAMESPACE@_ios_namespace::ifstream; + using @KWSYS_NAMESPACE@_ios_namespace::ios; + using @KWSYS_NAMESPACE@_ios_namespace::endl; + using @KWSYS_NAMESPACE@_ios_namespace::flush; +} +#endif + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/Utilities/kwsys/kwsys_ios_iosfwd.h.in b/Utilities/kwsys/kwsys_ios_iosfwd.h.in new file mode 100644 index 0000000..484fdda --- /dev/null +++ b/Utilities/kwsys/kwsys_ios_iosfwd.h.in @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsys_ios_iosfwd.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_ios_iosfwd +#define @KWSYS_NAMESPACE@_ios_iosfwd + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#ifdef _MSC_VER +#pragma warning (push, 1) +#pragma warning (disable: 4702) +#endif + +#if @KWSYS_NAMESPACE@_IOS_USE_ANSI +# include +#else +class fstream; +class ifstream; +class ios; +class istream; +class ofstream; +class ostream; +#endif + +#if !@KWSYS_NAMESPACE@_IOS_USE_SSTREAM +namespace @KWSYS_NAMESPACE@_ios +{ + using @KWSYS_NAMESPACE@_ios_namespace::fstream; + using @KWSYS_NAMESPACE@_ios_namespace::ifstream; + using @KWSYS_NAMESPACE@_ios_namespace::ios; + using @KWSYS_NAMESPACE@_ios_namespace::istream; + using @KWSYS_NAMESPACE@_ios_namespace::ofstream; + using @KWSYS_NAMESPACE@_ios_namespace::ostream; +} +#endif + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/Utilities/kwsys/kwsys_ios_iostream.h.in b/Utilities/kwsys/kwsys_ios_iostream.h.in new file mode 100644 index 0000000..c8303ac --- /dev/null +++ b/Utilities/kwsys/kwsys_ios_iostream.h.in @@ -0,0 +1,49 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsys_ios_iostream.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_ios_iostream +#define @KWSYS_NAMESPACE@_ios_iostream + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +#ifdef _MSC_VER +# pragma warning (push, 1) +# pragma warning (disable: 4702) +# pragma warning (disable: 4995) /* Old streams are deprecated. */ +#endif + +#if @KWSYS_NAMESPACE@_IOS_USE_ANSI +# include +#else +# include +#endif + +#if !@KWSYS_NAMESPACE@_IOS_USE_SSTREAM +namespace @KWSYS_NAMESPACE@_ios +{ + using @KWSYS_NAMESPACE@_ios_namespace::ostream; + using @KWSYS_NAMESPACE@_ios_namespace::istream; + using @KWSYS_NAMESPACE@_ios_namespace::ios; + using @KWSYS_NAMESPACE@_ios_namespace::cout; + using @KWSYS_NAMESPACE@_ios_namespace::cerr; + using @KWSYS_NAMESPACE@_ios_namespace::cin; + using @KWSYS_NAMESPACE@_ios_namespace::endl; + using @KWSYS_NAMESPACE@_ios_namespace::flush; +} +#endif + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/Utilities/kwsys/kwsys_ios_sstream.h.in b/Utilities/kwsys/kwsys_ios_sstream.h.in new file mode 100644 index 0000000..1f9d43d --- /dev/null +++ b/Utilities/kwsys/kwsys_ios_sstream.h.in @@ -0,0 +1,145 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsys_ios_sstream.h.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_ios_sstream +#define @KWSYS_NAMESPACE@_ios_sstream + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +/* Define this macro temporarily to keep the code readable. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# define kwsys_stl @KWSYS_NAMESPACE@_stl +#endif + +#if @KWSYS_NAMESPACE@_IOS_USE_SSTREAM +# ifdef _MSC_VER +# pragma warning (push, 1) +# pragma warning (disable: 4702) +# endif +# include +# ifdef _MSC_VER +# pragma warning(pop) +# endif +#else +# ifdef _MSC_VER +# pragma warning (push, 1) +# pragma warning (disable: 4702) +# pragma warning (disable: 4995) /* Old streams are deprecated. */ +# endif +# if @KWSYS_NAMESPACE@_IOS_USE_ANSI +# include +# elif @KWSYS_NAMESPACE@_IOS_USE_STRSTREAM_H +# include +# elif @KWSYS_NAMESPACE@_IOS_USE_STRSTREA_H +# include +# endif +# if @KWSYS_NAMESPACE@_IOS_USE_ANSI +# include // Need placement operator new. +# else +# include // Need placement operator new. +# endif +# ifdef _MSC_VER +# pragma warning(pop) +# endif + +// Only have old std::strstream classes. Wrap them to look like new +// ostringstream and istringstream classes. + +# include <@KWSYS_NAMESPACE@/stl/string> + +namespace @KWSYS_NAMESPACE@_ios +{ +using @KWSYS_NAMESPACE@_ios_namespace::ostream; +using @KWSYS_NAMESPACE@_ios_namespace::istream; +using @KWSYS_NAMESPACE@_ios_namespace::istrstream; +using @KWSYS_NAMESPACE@_ios_namespace::ostrstream; +using @KWSYS_NAMESPACE@_ios_namespace::ios; +using @KWSYS_NAMESPACE@_ios_namespace::endl; +using @KWSYS_NAMESPACE@_ios_namespace::ends; +using @KWSYS_NAMESPACE@_ios_namespace::flush; + +class ostringstream_cleanup +{ +public: + ostringstream_cleanup(ostrstream& ostr): m_OStrStream(ostr) {} + ~ostringstream_cleanup() { m_OStrStream.rdbuf()->freeze(0); } + static void IgnoreUnusedVariable(const ostringstream_cleanup&) {} +protected: + ostrstream& m_OStrStream; +private: + void operator=(ostringstream_cleanup const&); +}; + +class ostringstream: public ostrstream +{ +public: + typedef ostrstream Superclass; + ostringstream() {} + ostringstream(const kwsys_stl::string& s) { *this << s.c_str(); } + kwsys_stl::string str() + { + ostringstream_cleanup cleanup(*this); + ostringstream_cleanup::IgnoreUnusedVariable(cleanup); + int pcount = this->pcount(); + const char* ptr = this->Superclass::str(); + return kwsys_stl::string(ptr?ptr:"", pcount); + } + void str(const kwsys_stl::string& s) + { + this->~ostringstream(); + new (this) ostringstream(s); + } +private: + ostringstream(const ostringstream&); + void operator=(const ostringstream&); +}; + +#if defined(_MSC_VER) +# pragma warning (push) +# pragma warning (disable: 4097) /* typedef-name used as synonym for class */ +#endif + +class istringstream: private kwsys_stl::string, public istrstream +{ +public: + typedef kwsys_stl::string StdString; + typedef istrstream IStrStream; + istringstream(): StdString(), + IStrStream(const_cast(StdString::c_str())) {} + istringstream(const kwsys_stl::string& s): + StdString(s), IStrStream(const_cast(StdString::c_str())) {} + kwsys_stl::string str() const { return *this; } + void str(const kwsys_stl::string& s) + { + this->~istringstream(); + new (this) istringstream(s); + } +private: + istringstream(const istringstream&); + void operator=(const istringstream&); +}; + +#if defined(_MSC_VER) +# pragma warning (pop) +#endif + +} // namespace @KWSYS_NAMESPACE@_ios + +#endif + +/* Undefine temporary macro. */ +#if !defined (KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS +# undef kwsys_stl +#endif + +#endif diff --git a/Utilities/kwsys/kwsys_stl.hxx.in b/Utilities/kwsys/kwsys_stl.hxx.in new file mode 100644 index 0000000..8c2d9ea --- /dev/null +++ b/Utilities/kwsys/kwsys_stl.hxx.in @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsys_stl.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef @KWSYS_NAMESPACE@_stl_@KWSYS_STL_HEADER@ +#define @KWSYS_NAMESPACE@_stl_@KWSYS_STL_HEADER@ + +#include <@KWSYS_NAMESPACE@/Configure.hxx> + +/* Avoid warnings in MSVC standard headers. */ +#ifdef _MSC_VER +# pragma warning (push, 1) +# pragma warning (disable: 4702) +# pragma warning (disable: 4786) +#endif + +/* The HP standard library defines the functor "times" instead of + "multiplies" as specified by C++98 20.3.2 for backward + compatibility with earlier specifications. Defining this macro + fixes this behavior. The name "times" also conflicts with the + function declared in sys/times.h on that platform, so we must do + this as a work-around anyway. */ +#if defined(__HP_aCC) && !defined(__HPACC_USING_MULTIPLIES_IN_FUNCTIONAL) +# define __HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +# define @KWSYS_NAMESPACE@_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +#endif + +/* Include the real header. */ +#include <@KWSYS_STL_HEADER@> + +/* Cleanup. */ +#if defined(@KWSYS_NAMESPACE@_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL) +# undef @KWSYS_NAMESPACE@_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +# undef __HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +#endif + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +@KWSYS_STL_HEADER_EXTRA@ +#endif diff --git a/Utilities/kwsys/kwsys_stl_string.hxx.in b/Utilities/kwsys/kwsys_stl_string.hxx.in new file mode 100644 index 0000000..2c9b316 --- /dev/null +++ b/Utilities/kwsys/kwsys_stl_string.hxx.in @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: kwsys_stl_string.hxx.in,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +// This header is extra code for <@KWSYS_NAMESPACE@/stl/string>. +#if !defined(@KWSYS_NAMESPACE@_stl_string_including_hxx) +# error "The header <@KWSYS_NAMESPACE@/stl/string.hxx> may be included only by <@KWSYS_NAMESPACE@/stl/string>." +#endif + +// Provide the istream operator for the stl string if it is not +// provided by the system or another copy of kwsys. Allow user code +// to block this definition by defining the macro +// @KWSYS_NAMESPACE@_STL_STRING_NO_ISTREAM +// to avoid conflicts with other libraries. User code can test for +// this definition by checking the macro +// @KWSYS_NAMESPACE@_STL_STRING_ISTREAM_DEFINED +#if !@KWSYS_NAMESPACE@_STL_STRING_HAVE_ISTREAM && !defined(@KWSYS_NAMESPACE@_STL_STRING_NO_ISTREAM) && !defined(KWSYS_STL_STRING_ISTREAM_DEFINED) +# define KWSYS_STL_STRING_ISTREAM_DEFINED +# define @KWSYS_NAMESPACE@_STL_STRING_ISTREAM_DEFINED +# include // isspace +# include <@KWSYS_NAMESPACE@/ios/iostream> +inline @KWSYS_NAMESPACE@_ios::istream& +operator>>(@KWSYS_NAMESPACE@_ios::istream& is, + @KWSYS_NAMESPACE@_stl::string& s) +{ + // Keep track of the resulting state. + int state = @KWSYS_NAMESPACE@_ios::ios::goodbit; + + // Save the width setting and set it back to zero. + size_t n = static_cast(is.width(0)); + + // Clear any old contents of the output string. + s.erase(); + + // Skip leading whitespace. + is.eatwhite(); + istream& okay = is; + + if(okay) + { + // Select a maximum possible length. + if(n == 0 || n >= s.max_size()) + { + n = s.max_size(); + } + + // Read until a space is found or the maximum length is reached. + bool success = false; + for(int c = is.peek(); (--n > 0 && c != EOF && !isspace(c)); c = is.peek()) + { + s += static_cast(c); + success = true; + is.ignore(); + } + + // Set flags for resulting state. + if(is.peek() == EOF) { state |= @KWSYS_NAMESPACE@_ios::ios::eofbit; } + if(success) { state |= @KWSYS_NAMESPACE@_ios::ios::failbit; } + } + + // Set the final result state. + is.clear(state); + return is; +} +#endif + +// Provide the ostream operator for the stl string if it is not +// provided by the system or another copy of kwsys. Allow user code +// to block this definition by defining the macro +// @KWSYS_NAMESPACE@_STL_STRING_NO_OSTREAM +// to avoid conflicts with other libraries. User code can test for +// this definition by checking the macro +// @KWSYS_NAMESPACE@_STL_STRING_OSTREAM_DEFINED +#if !@KWSYS_NAMESPACE@_STL_STRING_HAVE_OSTREAM && !defined(@KWSYS_NAMESPACE@_STL_STRING_NO_OSTREAM) && !defined(KWSYS_STL_STRING_OSTREAM_DEFINED) +# define KWSYS_STL_STRING_OSTREAM_DEFINED +# define @KWSYS_NAMESPACE@_STL_STRING_OSTREAM_DEFINED +# include <@KWSYS_NAMESPACE@/ios/iostream> +inline @KWSYS_NAMESPACE@_ios::ostream& +operator<<(@KWSYS_NAMESPACE@_ios::ostream& os, + @KWSYS_NAMESPACE@_stl::string const& s) +{ + return os << s.c_str(); +} +#endif + +// Provide the operator!= for the stl string and char* if it is not +// provided by the system or another copy of kwsys. Allow user code +// to block this definition by defining the macro +// @KWSYS_NAMESPACE@_STL_STRING_NO_NEQ_CHAR +// to avoid conflicts with other libraries. User code can test for +// this definition by checking the macro +// @KWSYS_NAMESPACE@_STL_STRING_NEQ_CHAR_DEFINED +#if !@KWSYS_NAMESPACE@_STL_STRING_HAVE_NEQ_CHAR && !defined(@KWSYS_NAMESPACE@_STL_STRING_NO_NEQ_CHAR) && !defined(KWSYS_STL_STRING_NEQ_CHAR_DEFINED) +# define KWSYS_STL_STRING_NEQ_CHAR_DEFINED +# define @KWSYS_NAMESPACE@_STL_STRING_NEQ_CHAR_DEFINED +inline bool operator!=(@KWSYS_NAMESPACE@_stl::string const& s, const char* c) +{ + return !(s == c); +} +inline bool operator!=(const char* c, @KWSYS_NAMESPACE@_stl::string const& s) +{ + return !(s == c); +} +#endif diff --git a/Utilities/kwsys/testCommandLineArguments.cxx b/Utilities/kwsys/testCommandLineArguments.cxx new file mode 100644 index 0000000..67a3c0a --- /dev/null +++ b/Utilities/kwsys/testCommandLineArguments.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: testCommandLineArguments.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(CommandLineArguments.hxx) +#include KWSYS_HEADER(ios/iostream) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "CommandLineArguments.hxx.in" +# include "kwsys_ios_iostream.h.in" +#endif + +void* random_ptr = (void*)0x123; + +int argument(const char* arg, const char* value, void* call_data) +{ + kwsys_ios::cout << "Got argument: \"" << arg << "\" value: \"" << (value?value:"(null)") << "\"" << kwsys_ios::endl; + if ( call_data != random_ptr ) + { + kwsys_ios::cerr << "Problem processing call_data" << kwsys_ios::endl; + return 0; + } + return 1; +} + +int unknown_argument(const char* argument, void* call_data) +{ + kwsys_ios::cout << "Got unknown argument: \"" << argument << "\"" << kwsys_ios::endl; + if ( call_data != random_ptr ) + { + kwsys_ios::cerr << "Problem processing call_data" << kwsys_ios::endl; + return 0; + } + return 1; +} + +int main(int argc, char* argv[]) +{ + // Example run: ./testCommandLineArguments --some-int-variable 4 + // --another-bool-variable --some-bool-variable=yes + // --some-stl-string-variable=foobar --set-bool-arg1 --set-bool-arg2 + // --some-string-variable=hello + + int res = 0; + kwsys::CommandLineArguments arg; + arg.Initialize(argc, argv); + + // For error handling + arg.SetClientData(random_ptr); + arg.SetUnknownArgumentCallback(unknown_argument); + + int some_int_variable = 10; + double some_double_variable = 10.10; + char* some_string_variable = 0; + kwsys_stl::string some_stl_string_variable = ""; + bool some_bool_variable = false; + bool some_bool_variable1 = false; + bool bool_arg1 = false; + int bool_arg2 = 0; + + typedef kwsys::CommandLineArguments argT; + + arg.AddArgument("--some-int-variable", argT::SPACE_ARGUMENT, &some_int_variable, "Set some random int variable"); + arg.AddArgument("--some-double-variable", argT::CONCAT_ARGUMENT, &some_double_variable, "Set some random double variable"); + arg.AddArgument("--some-string-variable", argT::EQUAL_ARGUMENT, &some_string_variable, "Set some random string variable"); + arg.AddArgument("--some-stl-string-variable", argT::EQUAL_ARGUMENT, &some_stl_string_variable, "Set some random stl string variable"); + arg.AddArgument("--some-bool-variable", argT::EQUAL_ARGUMENT, &some_bool_variable, "Set some random bool variable"); + arg.AddArgument("--another-bool-variable", argT::NO_ARGUMENT, &some_bool_variable1, "Set some random bool variable 1"); + arg.AddBooleanArgument("--set-bool-arg1", &bool_arg1, "Test AddBooleanArgument 1"); + arg.AddBooleanArgument("--set-bool-arg2", &bool_arg2, "Test AddBooleanArgument 2"); + + arg.AddCallback("-A", argT::NO_ARGUMENT, argument, random_ptr, "Some option -A. This option has a multiline comment. It should demonstrate how the code splits lines."); + arg.AddCallback("-B", argT::SPACE_ARGUMENT, argument, random_ptr, "Option -B takes argument with space"); + arg.AddCallback("-C", argT::EQUAL_ARGUMENT, argument, random_ptr, "Option -C takes argument after ="); + arg.AddCallback("-D", argT::CONCAT_ARGUMENT, argument, random_ptr, "This option takes concatinated argument"); + arg.AddCallback("--long1", argT::NO_ARGUMENT, argument, random_ptr, "-A"); + arg.AddCallback("--long2", argT::SPACE_ARGUMENT, argument, random_ptr, "-B"); + arg.AddCallback("--long3", argT::EQUAL_ARGUMENT, argument, random_ptr, "Same as -C but a bit different"); + arg.AddCallback("--long4", argT::CONCAT_ARGUMENT, argument, random_ptr, "-C"); + + if ( !arg.Parse() ) + { + kwsys_ios::cerr << "Problem parsing arguments" << kwsys_ios::endl; + res = 1; + } + kwsys_ios::cout << "Help: " << arg.GetHelp() << kwsys_ios::endl; + + kwsys_ios::cout << "Some int variable was set to: " << some_int_variable << kwsys_ios::endl; + kwsys_ios::cout << "Some double variable was set to: " << some_double_variable << kwsys_ios::endl; + if ( some_string_variable ) + { + kwsys_ios::cout << "Some string variable was set to: " << some_string_variable << kwsys_ios::endl; + delete [] some_string_variable; + } + else + { + kwsys_ios::cerr << "Problem setting string variable" << kwsys_ios::endl; + res = 1; + } + kwsys_ios::cout << "Some STL String variable was set to: " << some_stl_string_variable.c_str() << kwsys_ios::endl; + kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable << kwsys_ios::endl; + kwsys_ios::cout << "Some bool variable was set to: " << some_bool_variable1 << kwsys_ios::endl; + kwsys_ios::cout << "bool_arg1 variable was set to: " << bool_arg1 << kwsys_ios::endl; + kwsys_ios::cout << "bool_arg2 variable was set to: " << bool_arg2 << kwsys_ios::endl; + kwsys_ios::cout << kwsys_ios::endl; + return res; +} diff --git a/Utilities/kwsys/testHashSTL.cxx b/Utilities/kwsys/testHashSTL.cxx new file mode 100644 index 0000000..f8e98be --- /dev/null +++ b/Utilities/kwsys/testHashSTL.cxx @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: testHashSTL.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(hash_map.hxx) +#include KWSYS_HEADER(hash_set.hxx) +#include KWSYS_HEADER(ios/iostream) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "hash_map.hxx.in" +# include "hash_set.hxx.in" +# include "hashtable.hxx.in" +# include "kwsys_ios_iostream.h.in" +#endif + +#if defined(_MSC_VER) +# pragma warning (disable:4786) +#endif + +#if defined(__sgi) && !defined(__GNUC__) +# pragma set woff 1468 /* inline function cannot be explicitly instantiated */ +#endif + +template class kwsys::hash_map; +template class kwsys::hash_set; + +bool test_hash_map() +{ + typedef kwsys::hash_map mtype; + mtype m; + const char* keys[] = {"hello", "world"}; + m[keys[0]] = 1; + m.insert(mtype::value_type(keys[1], 2)); + int sum = 0; + for(mtype::iterator mi = m.begin(); mi != m.end(); ++mi) + { + kwsys_ios::cout << "Found entry [" << mi->first << "," << mi->second << "]" + << kwsys_ios::endl; + sum += mi->second; + } + return sum == 3; +} + +bool test_hash_set() +{ + typedef kwsys::hash_set stype; + stype s; + s.insert(1); + s.insert(2); + int sum = 0; + for(stype::iterator si = s.begin(); si != s.end(); ++si) + { + kwsys_ios::cout << "Found entry [" << *si << "]" << kwsys_ios::endl; + sum += *si; + } + return sum == 3; +} + +int main() +{ + bool result = true; + result = test_hash_map() && result; + result = test_hash_set() && result; + return result? 0:1; +} diff --git a/Utilities/kwsys/testIOS.cxx b/Utilities/kwsys/testIOS.cxx new file mode 100644 index 0000000..d699ae5 --- /dev/null +++ b/Utilities/kwsys/testIOS.cxx @@ -0,0 +1,20 @@ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(stl/vector) +#include KWSYS_HEADER(ios/sstream) +#include KWSYS_HEADER(ios/iostream) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "kwsys_stl_vector.h.in" +# include "kwsys_ios_sstream.h.in" +# include "kwsys_ios_iostream.h.in" +#endif + +int main() +{ + kwsys_ios::ostringstream ostr; + ostr << "Hello, World!"; + kwsys_ios::cout << ostr.str() << kwsys_ios::endl; + return 0; +} diff --git a/Utilities/kwsys/testProcess.c b/Utilities/kwsys/testProcess.c new file mode 100644 index 0000000..b0ea8de --- /dev/null +++ b/Utilities/kwsys/testProcess.c @@ -0,0 +1,435 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: testProcess.c,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" +#include KWSYS_HEADER(Process.h) + +/* Work-around CMake dependency scanning limitation. This must + duplicate the above list of headers. */ +#if 0 +# include "Process.h.in" +#endif + +#include +#include +#include + +#if defined(_WIN32) +# include +#else +# include +#endif + +int runChild(const char* cmd[], int state, int exception, int value, + int share, int output, int delay, double timeout, int poll, + int repeat); + +int test1(int argc, const char* argv[]) +{ + (void)argc; (void)argv; + fprintf(stdout, "Output on stdout from test returning 0.\n"); + fprintf(stderr, "Output on stderr from test returning 0.\n"); + return 0; +} + +int test2(int argc, const char* argv[]) +{ + (void)argc; (void)argv; + fprintf(stdout, "Output on stdout from test returning 123.\n"); + fprintf(stderr, "Output on stderr from test returning 123.\n"); + return 123; +} + +int test3(int argc, const char* argv[]) +{ + (void)argc; (void)argv; + fprintf(stdout, "Output before sleep on stdout from timeout test.\n"); + fprintf(stderr, "Output before sleep on stderr from timeout test.\n"); + fflush(stdout); + fflush(stderr); +#if defined(_WIN32) + Sleep(15000); +#else + sleep(15); +#endif + fprintf(stdout, "Output after sleep on stdout from timeout test.\n"); + fprintf(stderr, "Output after sleep on stderr from timeout test.\n"); + return 0; +} + +int test4(int argc, const char* argv[]) +{ +#if defined(_WIN32) + /* Avoid error diagnostic popups since we are crashing on purpose. */ + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); +#endif + (void)argc; (void)argv; + fprintf(stdout, "Output before crash on stdout from crash test.\n"); + fprintf(stderr, "Output before crash on stderr from crash test.\n"); + fflush(stdout); + fflush(stderr); + *(int*)0 = 0; + fprintf(stdout, "Output after crash on stdout from crash test.\n"); + fprintf(stderr, "Output after crash on stderr from crash test.\n"); + return 0; +} + +int test5(int argc, const char* argv[]) +{ + int r; + const char* cmd[4]; + (void)argc; + cmd[0] = argv[0]; + cmd[1] = "run"; + cmd[2] = "4"; + cmd[3] = 0; + fprintf(stdout, "Output on stdout before recursive test.\n"); + fprintf(stderr, "Output on stderr before recursive test.\n"); + fflush(stdout); + fflush(stderr); + r = runChild(cmd, kwsysProcess_State_Exception, + kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15, 0, 1); + fprintf(stdout, "Output on stdout after recursive test.\n"); + fprintf(stderr, "Output on stderr after recursive test.\n"); + fflush(stdout); + fflush(stderr); + return r; +} + +#define TEST6_SIZE (4096*2) +void test6(int argc, const char* argv[]) +{ + int i; + char runaway[TEST6_SIZE+1]; + (void)argc; (void)argv; + for(i=0;i < TEST6_SIZE;++i) + { + runaway[i] = '.'; + } + runaway[TEST6_SIZE] = '\n'; + + /* Generate huge amounts of output to test killing. */ + for(;;) + { + fwrite(runaway, 1, TEST6_SIZE+1, stdout); + fflush(stdout); + } +} + +/* Define MINPOLL to be one more than the number of times output is + written. Define MAXPOLL to be the largest number of times a loop + delaying 1/10th of a second should ever have to poll. */ +#define MINPOLL 5 +#define MAXPOLL 20 +int test7(int argc, const char* argv[]) +{ + (void)argc; (void)argv; + fprintf(stdout, "Output on stdout before sleep.\n"); + fprintf(stderr, "Output on stderr before sleep.\n"); + fflush(stdout); + fflush(stderr); + /* Sleep for 1 second. */ +#if defined(_WIN32) + Sleep(1000); +#else + sleep(1); +#endif + fprintf(stdout, "Output on stdout after sleep.\n"); + fprintf(stderr, "Output on stderr after sleep.\n"); + fflush(stdout); + fflush(stderr); + return 0; +} + +int runChild2(kwsysProcess* kp, + const char* cmd[], int state, int exception, int value, + int share, int output, int delay, double timeout, + int poll) +{ + int result = 0; + char* data = 0; + int length = 0; + double userTimeout = 0; + double* pUserTimeout = 0; + kwsysProcess_SetCommand(kp, cmd); + if(timeout >= 0) + { + kwsysProcess_SetTimeout(kp, timeout); + } + if(share) + { + kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDOUT, 1); + kwsysProcess_SetPipeShared(kp, kwsysProcess_Pipe_STDERR, 1); + } + kwsysProcess_Execute(kp); + + if(poll) + { + pUserTimeout = &userTimeout; + } + + if(!share) + { + int p; + while((p = kwsysProcess_WaitForData(kp, &data, &length, pUserTimeout))) + { + if(output) + { + if(poll && p == kwsysProcess_Pipe_Timeout) + { + fprintf(stdout, "WaitForData timeout reached.\n"); + fflush(stdout); + + /* Count the number of times we polled without getting data. + If it is excessive then kill the child and fail. */ + if(++poll >= MAXPOLL) + { + fprintf(stdout, "Poll count reached limit %d.\n", + MAXPOLL); + kwsysProcess_Kill(kp); + } + } + else + { + fwrite(data, 1, length, stdout); + fflush(stdout); + } + } + if(poll) + { + /* Delay to avoid busy loop during polling. */ +#if defined(_WIN32) + Sleep(100); +#else + usleep(100000); +#endif + } + if(delay) + { + /* Purposely sleeping only on Win32 to let pipe fill up. */ +#if defined(_WIN32) + Sleep(100); +#endif + } + } + } + + kwsysProcess_WaitForExit(kp, 0); + + switch (kwsysProcess_GetState(kp)) + { + case kwsysProcess_State_Starting: + printf("No process has been executed.\n"); break; + case kwsysProcess_State_Executing: + printf("The process is still executing.\n"); break; + case kwsysProcess_State_Expired: + printf("Child was killed when timeout expired.\n"); break; + case kwsysProcess_State_Exited: + printf("Child exited with value = %d\n", + kwsysProcess_GetExitValue(kp)); + result = ((exception != kwsysProcess_GetExitException(kp)) || + (value != kwsysProcess_GetExitValue(kp))); break; + case kwsysProcess_State_Killed: + printf("Child was killed by parent.\n"); break; + case kwsysProcess_State_Exception: + printf("Child terminated abnormally: %s\n", + kwsysProcess_GetExceptionString(kp)); + result = ((exception != kwsysProcess_GetExitException(kp)) || + (value != kwsysProcess_GetExitValue(kp))); break; + case kwsysProcess_State_Error: + printf("Error in administrating child process: [%s]\n", + kwsysProcess_GetErrorString(kp)); break; + }; + + if(result) + { + if(exception != kwsysProcess_GetExitException(kp)) + { + fprintf(stderr, "Mismatch in exit exception. " + "Should have been %d, was %d.\n", + exception, kwsysProcess_GetExitException(kp)); + } + if(value != kwsysProcess_GetExitValue(kp)) + { + fprintf(stderr, "Mismatch in exit value. " + "Should have been %d, was %d.\n", + value, kwsysProcess_GetExitValue(kp)); + } + } + + if(kwsysProcess_GetState(kp) != state) + { + fprintf(stderr, "Mismatch in state. " + "Should have been %d, was %d.\n", + state, kwsysProcess_GetState(kp)); + result = 1; + } + + /* We should have polled more times than there were data if polling + was enabled. */ + if(poll && poll < MINPOLL) + { + fprintf(stderr, "Poll count is %d, which is less than %d.\n", + poll, MINPOLL); + result = 1; + } + + return result; +} + +int runChild(const char* cmd[], int state, int exception, int value, + int share, int output, int delay, double timeout, + int poll, int repeat) +{ + int result = 1; + kwsysProcess* kp = kwsysProcess_New(); + if(!kp) + { + fprintf(stderr, "kwsysProcess_New returned NULL!\n"); + return 1; + } + while(repeat-- > 0) + { + result = runChild2(kp, cmd, state, exception, value, share, + output, delay, timeout, poll); + } + kwsysProcess_Delete(kp); + return result; +} + +int main(int argc, const char* argv[]) +{ + int n = 0; +#if 0 + { + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + DuplicateHandle(GetCurrentProcess(), out, + GetCurrentProcess(), &out, 0, FALSE, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); + SetStdHandle(STD_OUTPUT_HANDLE, out); + } + { + HANDLE out = GetStdHandle(STD_ERROR_HANDLE); + DuplicateHandle(GetCurrentProcess(), out, + GetCurrentProcess(), &out, 0, FALSE, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); + SetStdHandle(STD_ERROR_HANDLE, out); + } +#endif + if(argc == 2) + { + n = atoi(argv[1]); + } + else if(argc == 3) + { + n = atoi(argv[2]); + } + /* Check arguments. */ + if(n < 1 || n > 7 || (argc == 3 && strcmp(argv[1], "run") != 0)) + { + fprintf(stdout, "Usage: %s \n", argv[0]); + return 1; + } + if(argc == 3) + { + switch (n) + { + case 1: return test1(argc, argv); + case 2: return test2(argc, argv); + case 3: return test3(argc, argv); + case 4: return test4(argc, argv); + case 5: return test5(argc, argv); + case 6: test6(argc, argv); return 0; + case 7: return test7(argc, argv); + } + fprintf(stderr, "Invalid test number %d.\n", n); + return 1; + } + + if(n >= 0 && n <= 7) + { + int states[7] = + { + kwsysProcess_State_Exited, + kwsysProcess_State_Exited, + kwsysProcess_State_Expired, + kwsysProcess_State_Exception, + kwsysProcess_State_Exited, + kwsysProcess_State_Expired, + kwsysProcess_State_Exited + }; + int exceptions[7] = + { + kwsysProcess_Exception_None, + kwsysProcess_Exception_None, + kwsysProcess_Exception_None, + kwsysProcess_Exception_Fault, + kwsysProcess_Exception_None, + kwsysProcess_Exception_None, + kwsysProcess_Exception_None + }; + int values[7] = {0, 123, 1, 1, 0, 0, 0}; + int outputs[7] = {1, 1, 1, 1, 1, 0, 1}; + int delays[7] = {0, 0, 0, 0, 0, 1, 0}; + double timeouts[7] = {10, 10, 10, 10, 30, 10, -1}; + int polls[7] = {0, 0, 0, 0, 0, 0, 1}; + int repeat[7] = {2, 1, 1, 1, 1, 1, 1}; + int r; + const char* cmd[4]; +#ifdef _WIN32 + char* argv0 = 0; + if(n == 0 && (argv0 = strdup(argv[0]))) + { + /* Try converting to forward slashes to see if it works. */ + char* c; + for(c=argv0; *c; ++c) + { + if(*c == '\\') + { + *c = '/'; + } + } + cmd[0] = argv0; + } + else + { + cmd[0] = argv[0]; + } +#else + cmd[0] = argv[0]; +#endif + cmd[1] = "run"; + cmd[2] = argv[1]; + cmd[3] = 0; + fprintf(stdout, "Output on stdout before test %d.\n", n); + fprintf(stderr, "Output on stderr before test %d.\n", n); + fflush(stdout); + fflush(stderr); + r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0, + outputs[n-1], delays[n-1], timeouts[n-1], + polls[n-1], repeat[n-1]); + fprintf(stdout, "Output on stdout after test %d.\n", n); + fprintf(stderr, "Output on stderr after test %d.\n", n); + fflush(stdout); + fflush(stderr); +#if _WIN32 + if(argv0) { free(argv0); } +#endif + return r; + } + else + { + fprintf(stderr, "Test number out of range\n"); + return 1; + } +} diff --git a/Utilities/kwsys/testSystemTools.cxx b/Utilities/kwsys/testSystemTools.cxx new file mode 100644 index 0000000..47ad761 --- /dev/null +++ b/Utilities/kwsys/testSystemTools.cxx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: KWSys - Kitware System Library + Module: $RCSfile: testSystemTools.cxx,v $ + + Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "kwsysPrivate.h" + +#if defined(_MSC_VER) +# pragma warning (disable:4786) +#endif + +#include KWSYS_HEADER(SystemTools.hxx) +#include KWSYS_HEADER(ios/iostream) + +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "SystemTools.hxx.in" +# include "kwsys_ios_iostream.h.in" +#endif + +//---------------------------------------------------------------------------- +const char* toUnixPaths[][2] = +{ + { "/usr/local/bin/passwd", "/usr/local/bin/passwd" }, + { "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" }, + { "/usr/lo\\ cal/bin/pa\\ sswd", "/usr/lo\\ cal/bin/pa\\ sswd" }, + { "c:/usr/local/bin/passwd", "c:/usr/local/bin/passwd" }, + { "c:/usr/lo cal/bin/pa sswd", "c:/usr/lo cal/bin/pa sswd" }, + { "c:/usr/lo\\ cal/bin/pa\\ sswd", "c:/usr/lo\\ cal/bin/pa\\ sswd" }, + { "\\usr\\local\\bin\\passwd", "/usr/local/bin/passwd" }, + { "\\usr\\lo cal\\bin\\pa sswd", "/usr/lo cal/bin/pa sswd" }, + { "\\usr\\lo\\ cal\\bin\\pa\\ sswd", "/usr/lo\\ cal/bin/pa\\ sswd" }, + { "c:\\usr\\local\\bin\\passwd", "c:/usr/local/bin/passwd" }, + { "c:\\usr\\lo cal\\bin\\pa sswd", "c:/usr/lo cal/bin/pa sswd" }, + { "c:\\usr\\lo\\ cal\\bin\\pa\\ sswd", "c:/usr/lo\\ cal/bin/pa\\ sswd" }, + { "\\\\usr\\local\\bin\\passwd", "//usr/local/bin/passwd" }, + { "\\\\usr\\lo cal\\bin\\pa sswd", "//usr/lo cal/bin/pa sswd" }, + { "\\\\usr\\lo\\ cal\\bin\\pa\\ sswd", "//usr/lo\\ cal/bin/pa\\ sswd" }, + {0, 0} +}; + +bool CheckConvertToUnixSlashes(kwsys_stl::string input, + kwsys_stl::string output) +{ + kwsys_stl::string result = input; + kwsys::SystemTools::ConvertToUnixSlashes(result); + if ( result != output ) + { + kwsys_ios::cerr + << "Problem with ConvertToUnixSlashes - input: " << input.c_str() + << " output: " << result.c_str() << " expected: " << output.c_str() + << kwsys_ios::endl; + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +const char* checkEscapeChars[][4] = +{ + { "1 foo 2 bar 2", "12", "\\", "\\1 foo \\2 bar \\2"}, + { " {} ", "{}", "#", " #{#} "}, + {0, 0, 0, 0} +}; + +bool CheckEscapeChars(kwsys_stl::string input, + const char *chars_to_escape, + char escape_char, + kwsys_stl::string output) +{ + kwsys_stl::string result = kwsys::SystemTools::EscapeChars( + input.c_str(), chars_to_escape, escape_char); + if (result != output) + { + kwsys_ios::cerr + << "Problem with CheckEscapeChars - input: " << input.c_str() + << " output: " << result.c_str() << " expected: " << output.c_str() + << kwsys_ios::endl; + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +int main(/*int argc, char* argv*/) +{ + bool res = true; + + int cc; + for ( cc = 0; toUnixPaths[cc][0]; cc ++ ) + { + res &= CheckConvertToUnixSlashes(toUnixPaths[cc][0], toUnixPaths[cc][1]); + } + + // Special check for ~ + kwsys_stl::string output; + if(kwsys::SystemTools::GetEnv("HOME", output)) + { + output += "/foo bar/lala"; + res &= CheckConvertToUnixSlashes("~/foo bar/lala", output); + } + + for (cc = 0; checkEscapeChars[cc][0]; cc ++ ) + { + res &= CheckEscapeChars(checkEscapeChars[cc][0], checkEscapeChars[cc][1], + *checkEscapeChars[cc][2], checkEscapeChars[cc][3]); + } + + return res ? 0 : 1; +} diff --git a/Utilities/tcl2py.py b/Utilities/tcl2py.py new file mode 100644 index 0000000..9e6ba26 --- /dev/null +++ b/Utilities/tcl2py.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python +# +# tcl2py.py - try to Pythonize a vtk tcl script +# +# This code is based on tcl2py.py from VTK 3.2 which was written by +# Randy Heiland. +# +# Changes: +# +# (21/12/2002) -- Prabhu Ramachandran +# Made to work with re instead of regex. Superficial cleanup of the +# code, fixed a few issues, using new VTK package structure, added +# support for VTK_DATA_ROOT and set keyword, primitive support for +# expr, made code easier to run with usage message etc. Seems to +# generate decent output now. Simple Tcl scripts work out of the +# box! Complex ones need work. For a truly general solution the +# code has to be rewritten. +# + +import sys +import string +import re + + +def scanner(name,function): + file = open(name,'r') + while 1: + line = file.readline() + if not line: break + function(line) + file.close() + + +def processLine(line, output, keepTcl=1): + line = string.strip(line) + "\n" + if line[0] == '#': + output.write(line) + elif line[:15] == 'package require': + if keepTcl == 1: + output.write('# ' + line) + elif string.find(line, "deiconify") > -1: + output.write('# ' + line) + else: + if keepTcl == 1: + output.write('#' + line) + + if string.find(line, 'expr') > -1: + match = re.search("\[\s*expr ([^\]]+)\]", line).groups()[0] + match = re.sub('\s+', '', match) + line = re.sub("\[\s*expr ([^\]]+)\]", match, line) + line = re.sub('\[','',line) + line = re.sub('\]','',line) + line = re.sub('ren1','ren',line) + line = re.sub(';','\n',line) + line = re.sub('\$','',line) + line = re.sub('{',' ',line) + line = re.sub('}',' ',line) + + n = len(line) + + keys = string.split(line) + + # handle set keyword. + inSet = 0 + if len(keys) and keys[0] == 'set': + output.write(keys[1] + ' = ') + keys = keys[2:] + inSet = 1 + + keysLength = len(keys) + + inaModule = 0 + inaForLoop = 0 + if keysLength == 0: + output.write(line) + # Catch some tcl-specific keywords and comment out + elif keys[0] == 'proc': + inaModule = 0 + output.write( 'def ' + keys[1] + '(') + if len(keys) > 2: + output.write(keys[2]) + for i in range(3,len(keys)): + output.write(', ' + keys[i]) + output.write('):\n') + elif keys[0] == 'catch': + output.write( '#' + line) + elif keys[0] == 'source': + output.write( '#' + line) + if re.search("colors.tcl",line) > -1: + output.write("from colors import *") + elif keys[0] == 'wm': + output.write( '#' + line) + elif keysLength > 1 and keys[1] == 'SetUserMethod': + if keepTcl == 1: + output.write( '#' + line) + elif keys[0] == 'for' and keys[1]=='set': + inaForLoop = 1 + #print '...Handling for loop' + output.write( "for " + keys[2] + " in range(" + keys[3] +", ") + upper = keys[6] + if keys[5] == "<=": + output.write( upper + "+1):\n" ) + else: + output.write( upper + "):\n" ) + + # Detect vtk class instance; Pythonize it. + elif line[:3] == 'vtk': + output.write( keys[1] + ' = vtk.' + keys[0] + '()\n' ) + else: + lparen = 0 + finishedFlag = 0 + # for i in range(len(keys)-1): + for i in range(len(keys)): + ls = len(keys[i]) + if keys[i] == 'eval': + continue + # continuation mark + elif keys[i] == '\\': + output.write( " \\\n") + elif keys[i][-8:] == 'FileName': + if keys[i+1][0:1] == '"': + f_name = re.sub('"VTK_DATA_ROOT/', \ + 'VTK_DATA_ROOT + "/', keys[i+1]) + output.write( keys[i] + "(" + f_name + ")") + else: + f_name = re.sub('VTK_DATA_ROOT/', \ + 'VTK_DATA_ROOT + "/', keys[i+1]) + if f_name[:13] == 'VTK_DATA_ROOT': + output.write(keys[i] + "(" + f_name + "\")") + else: + output.write( keys[i] + "(\"" + keys[i+1] + "\")") + finishedFlag = 1 + break + elif keys[i] == 'SetColor': + #print '...doing SetColor' + #print keys + if not re.search('[-\d.]', keys[i+1][0:1]): + #print '...got a named color' + color = keys[i+1][0:] + #print 'color = ' + color + output.write( "SetColor(" + color+"[0]," + \ + color+"[1]," + color+"[2])" ) + else: + output.write( "SetColor("+keys[i+1]+", "+keys[i+2]+", "+keys[i+3]+")") + finishedFlag = 1 + break + elif keys[i][:3]=='Set' or keys[i][:3]=='Add' or keys[i][:6]=='Insert': + output.write( keys[i] + '(' ) + lparen = 1 + elif i < len(keys)-1 and \ + re.search('[-\d.]', keys[i+1][0:1]) and \ + not re.search('[-\d.]', keys[i][ls-1:ls]): + output.write( keys[i] + '(' ) + lparen = 1 + elif keys[i][:3] == 'Get': + output.write( keys[i] + '()' ) + if i < len(keys)-1: + output.write( '.' ) + else: + if i < len(keys)-1: + npos = re.search("[-\d.]", keys[i][0:1]) + if npos > -1 or keys[i][0:3] == 'VTK': + output.write( keys[i] + ', ' ) + else: + output.write( keys[i] + '.' ) + else: + if inaModule == 1: + output.write( '\t' ) + output.write( keys[i] ) + + if finishedFlag == 0: + if keys[-1][:3] != 'Get' and \ + (not re.search("[-+\d.]", keys[-1])): + if lparen == 0: + output.write( '(' ) + lparen = 1 + else: + output.write( '\n' ) + + # Terminating right paren. + #output.write( ')\n' ) + + if lparen == 1: + output.write( ')\n' ) + if inSet == 1: + output.write( '\n' ) + + +def usage(): + msg = """Usage:\n tcl2py.py script.tcl [keep_tcl_code]\n +This script attempts to convert a VTK-Tcl script to Python. +The converted code is printed on the standard output. + +Options: + + keep_tcl_code -- If 1 it keeps the original tcl code + in a commented line. If zero it does not print + the translated Tcl line. Defaults to 1. + +Example: + + $ ./tcl2py.py example.tcl 0 > example.py +""" + print msg + + +def main(): + global keepTcl + if len(sys.argv) < 2: + usage() + sys.exit(1) + + keepTcl = 1 + if len(sys.argv) > 2: + try: + keepTcl = int(sys.argv[2]) + except ValueError: + usage() + print "Second argument must be 0 or 1." + sys.exit(1) + + name = sys.argv[1] + output = sys.stdout + if name[-4:] == '.tcl': + input = open(name, 'r') + #output = open(name[:-4] + '.py', 'w') + else: + input = open(name + '.tcl', 'r') + #output = open(name + '.py', 'w') + + # Standard stuff; import useful things and handle VTK_DATA_ROOT. + output.write('#!/usr/bin/env python\n') + output.write('\nimport vtk\n') + output.write('from vtk.util.misc import vtkGetDataRoot\n') + output.write('VTK_DATA_ROOT = vtkGetDataRoot()\n\n') + + for line in input.readlines(): + processLine(line, output, keepTcl) + input.close() + + output.write('iren.Initialize()\nrenWin.Render()\niren.Start()\n') + output.close() + + +if __name__ == "__main__": + main() + diff --git a/Utilities/vtk2xml.py b/Utilities/vtk2xml.py new file mode 100644 index 0000000..e2b0bce --- /dev/null +++ b/Utilities/vtk2xml.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python + +"""Utility script to convert an old VTK file format to the new VTK XML +file format (serial format). The output XML file will contain *all* +the existing scalars, vectors and tensors in the input file. + +This requires VTK 4.x or above. + +Created May 2003, Prabhu Ramachandran + +Licence: VTK License. + +""" + +import sys +import vtk +import os.path +import getopt + + +def getReaderWriter(file_name, out_dir=None): + r = vtk.vtkDataReader() + r.SetFileName(file_name) + f_base = os.path.splitext(file_name)[0] + r.Update() + reader = None + writer = None + xmlsuffix = '.xml' + map = {'StructuredPoints': '.vti', 'StructuredGrid': '.vts', + 'RectilinearGrid': '.vtr', 'UnstructuredGrid': '.vtu', + 'PolyData': '.vtp'} + for i in ['StructuredPoints', 'StructuredGrid', 'RectilinearGrid', + 'UnstructuredGrid', 'PolyData']: + if eval('r.IsFile%s()'%i): + reader = eval('vtk.vtk%sReader()'%i) + if i == 'StructuredPoints': + writer = eval('vtk.vtkXMLImageDataWriter()') + else: + writer = eval('vtk.vtkXML%sWriter()'%i) + xmlsuffix = map[i] + break + if not reader: + return None, None + + reader.SetFileName(file_name) + reader.Update() + + out_file = f_base + xmlsuffix + if out_dir: + out_file = os.path.join(out_dir, + os.path.basename(f_base) + xmlsuffix) + writer.SetFileName(out_file) + return reader, writer + + +def _getAttr(reader, lst, attr='Scalars'): + p_a = [] + c_a = [] + + for i in lst: + eval('reader.Set%sName(i)'%attr) + reader.Update() + o = reader.GetOutput() + pd = o.GetPointData() + cd = o.GetCellData() + s = eval('pd.Get%s()'%attr) + if s and (s not in p_a): + p_a.append(s) + s = eval('cd.Get%s()'%attr) + if s and (s not in c_a): + c_a.append(s) + return p_a, c_a + + +def setAllAttributes(reader): + s_name = [] + v_name = [] + t_name = [] + for i in range(reader.GetNumberOfScalarsInFile()): + s_name.append(reader.GetScalarsNameInFile(i)) + for i in range(reader.GetNumberOfVectorsInFile()): + v_name.append(reader.GetVectorsNameInFile(i)) + for i in range(reader.GetNumberOfTensorsInFile()): + t_name.append(reader.GetTensorsNameInFile(i)) + + p_s, c_s = _getAttr(reader, s_name, 'Scalars') + p_v, c_v = _getAttr(reader, v_name, 'Vectors') + p_t, c_t = _getAttr(reader, t_name, 'Tensors') + + o = reader.GetOutput() + pd = o.GetPointData() + for i in p_s + p_v + p_t: + pd.AddArray(i) + + cd = o.GetCellData() + for i in c_s + c_v + c_t: + cd.AddArray(i) + + return o + + +def usage(): + msg = """usage: vtk2xml.py [options] vtk_file1 vtk_file2 ...\n +This program converts VTK's old file format to the new XML format. + +The default mode is to store the data as appended (compressed and +base64 encoded). Change this behaviour with the provided options. +This code requires VTK 4.x or above to run. + +options: + -h, --help Show this help message and exit. + + -b, --binary Store data as binary (compressed and base64 encoded). + + -a, --ascii Store data as ascii. + + -n, --no-encode Do not base64 encode the data. This violates the + XML specification but makes reading and writing fast + and files smaller. + + -d, --output-dir + Output directory where the files should be generated. + Defaults to the same directory as the input file. +""" + return msg + + +def main(): + options = "bahnd:" + long_opts = ['binary', 'ascii', 'help', 'no-encode', 'output-dir='] + + try: + opts, args = getopt.getopt(sys.argv[1:], options, long_opts) + except getopt.error, msg: + print msg + print usage() + print '-'*70 + print msg + sys.exit(1) + + mode = 'p' + encode = 1 + out_dir = None + for o, a in opts: + if o in ('-h', '--help'): + print usage() + sys.exit(0) + if o in ('-b', '--binary'): + mode = 'b' + if o in ('-a', '--ascii'): + mode = 'a' + if o in ('-n', '--no-encode'): + encode = 0 + if o in ('-d', '--output-dir'): + out_dir = a + if not os.path.exists(out_dir): + print "Error: Directory %s does not exist!"%out_dir + sys.exit(1) + + if len(args) < 1: + print "\nError: Incorrect number of arguments\n" + print usage() + sys.exit(1) + + for i in args: + r, w = getReaderWriter(i, out_dir) + if not r: + print "\nError: Could not convert file: %s"%i + print "Unsupported data format!\n" + else: + o = setAllAttributes(r) + w.SetInput(o) + # set output modes + if mode == 'a': + w.SetDataModeToAscii() + elif mode == 'b': + w.SetDataModeToBinary() + else: + w.SetDataModeToAppended() + + w.SetEncodeAppendedData(encode) + w.Write() + + +if __name__ == "__main__": + main() diff --git a/Utilities/vtkTclTest2Py/CMakeLists.txt b/Utilities/vtkTclTest2Py/CMakeLists.txt new file mode 100644 index 0000000..7d24ef2 --- /dev/null +++ b/Utilities/vtkTclTest2Py/CMakeLists.txt @@ -0,0 +1,121 @@ +# Handle out-of-source builds correctly. +# +# 1. Create a list of Python files to be installed/copied. +# 2. Copy them to VTK_BINARY_DIR if it is different from VTK_SOURCE_DIR. +# 3. Use Python's compileall to compile the copied files. +# +# *** Step 1 has to be done carefully to avoid missing out files *** + +IF(PYTHON_EXECUTABLE AND VTK_WRAP_PYTHON) + SET(CMD ${PYTHON_EXECUTABLE}) + + # Make the necessary directories. + FOREACH(dir + ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py + ) + MAKE_DIRECTORY(${dir}) + ENDFOREACH(dir) + + # Now create a list of Python files. + # tcl2py testing related files. These are for testing tcl-translated scripts. + SET(VTK_PYTHON_FILES + __init__ + vtkTclParser + vtkTclToPyConvertor + backdrop + catch + expr + file + info + mccases + rtImageTest + ) + # Done listing of files. + + # Now copy these files if necessary. + SET(VTK_PYTHON_SOURCE_FILES) + SET(VTK_PYTHON_OUTPUT_FILES) + FOREACH(file ${VTK_PYTHON_FILES}) + SET(src "${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/${file}.py") + SET(VTK_PYTHON_SOURCE_FILES ${VTK_PYTHON_SOURCE_FILES} ${src}) + ENDFOREACH(file) + + IF ("${VTK_BINARY_DIR}" MATCHES "^${VTK_SOURCE_DIR}$") + #MESSAGE("In source build -- no need to copy Python files.") + ELSE ("${VTK_BINARY_DIR}" MATCHES "^${VTK_SOURCE_DIR}$") + FOREACH(file ${VTK_PYTHON_FILES}) + SET(src "${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/${file}.py") + SET(tgt "${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/${file}.py") + ADD_CUSTOM_COMMAND(DEPENDS ${src} + COMMAND ${CMAKE_COMMAND} + ARGS -E copy ${src} ${tgt} + OUTPUT ${tgt} + COMMENT "source copy") + ENDFOREACH(file) + ENDIF ("${VTK_BINARY_DIR}" MATCHES "^${VTK_SOURCE_DIR}$") + + # Byte compile the Python files. + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/compile_all_vtk.py.in + ${CMAKE_CURRENT_BINARY_DIR}/compile_all_vtk.py + @ONLY IMMEDIATE) + + ADD_CUSTOM_COMMAND( + COMMAND ${CMD} + ARGS -- ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/compile_all_vtk.py + -A "${VTK_BINARY_DIR}/Wrapping/Python" + DEPENDS ${VTK_PYTHON_SOURCE_FILES} ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/compile_all_vtk.py vtkpython + OUTPUT "${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/vtk_compile_complete" + ) + + #ADD_DEPENDENCIES(vtktcltest2py_pyc vtkpython_pyc) + + # Create a python module having the list of all VTK Classes. + SET(kits + Common + Filtering + Imaging + Graphics + GenericFiltering + IO) + + IF(VTK_USE_RENDERING) + SET(kits ${kits} + Rendering + VolumeRendering + Hybrid + Widgets) + ENDIF(VTK_USE_RENDERING) + IF(VTK_USE_PARALLEL) + SET(kits ${kits} + Parallel) + ENDIF(VTK_USE_PARALLEL) + + SET(VTK_CLASSES "\"___list_begins___\"") + + MACRO(APPEND_CLASSES varname) + #SET(VTK_CLASSES ${VTK_CLASSES} ${${varname}}) + FOREACH (class ${${varname}}) + SET(VTK_CLASSES "${VTK_CLASSES},\n\"${class}\"") + ENDFOREACH (class) + ENDMACRO(APPEND_CLASSES) + + FOREACH(kit ${kits}) + STRING(TOUPPER ${kit} ukit) + INCLUDE(${VTK_BINARY_DIR}/Utilities/vtk${kit}Kit.cmake) + SET(var VTK_${ukit}_CLASSES) + APPEND_CLASSES(${var}) + ENDFOREACH(kit) + + CONFIGURE_FILE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkClassList.py.in + ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/vtkClassList.py + @ONLY) + + ADD_CUSTOM_TARGET(vtktcltest2py_pyc ALL echo "..." + DEPENDS + ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/vtk_compile_complete + ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/vtkClassList.py + ) + +ENDIF(PYTHON_EXECUTABLE AND VTK_WRAP_PYTHON) + + diff --git a/Utilities/vtkTclTest2Py/__init__.py b/Utilities/vtkTclTest2Py/__init__.py new file mode 100644 index 0000000..bf1fc05 --- /dev/null +++ b/Utilities/vtkTclTest2Py/__init__.py @@ -0,0 +1 @@ +"""Modules used for testing and generating python tests translated from tcl""" diff --git a/Utilities/vtkTclTest2Py/backdrop.py b/Utilities/vtkTclTest2Py/backdrop.py new file mode 100644 index 0000000..5647591 --- /dev/null +++ b/Utilities/vtkTclTest2Py/backdrop.py @@ -0,0 +1,75 @@ +"""this is python equivalent of ./Wrapping/Tcl/vtktesting/backdrop.tcl +This script is used while running python tests translated from Tcl.""" + +import vtk + +basePlane = None +baseMapper = None +base = None + +backPlane = None +backMapper = None +back = None + +leftPlane = None +leftMapper = None +left = None + +def BuildBackdrop (minX, maxX, minY, maxY, minZ, maxZ, thickness): + global basePlane + global baseMapper + global base + global backPlane + global backMapper + global back + global left + global leftPlane + global leftMapper + + if not basePlane: + basePlane = vtk.vtkCubeSource() + basePlane.SetCenter( (maxX + minX)/2.0, minY, (maxZ + minZ)/2.0) + basePlane.SetXLength(maxX-minX) + basePlane.SetYLength(thickness) + basePlane.SetZLength(maxZ - minZ) + + if not baseMapper: + baseMapper = vtk.vtkPolyDataMapper() + baseMapper.SetInput(basePlane.GetOutput()) + + if not base: + base = vtk.vtkActor() + base.SetMapper(baseMapper) + + if not backPlane: + backPlane = vtk.vtkCubeSource() + backPlane.SetCenter( (maxX + minX)/2.0, (maxY + minY)/2.0, minZ) + backPlane.SetXLength(maxX-minX) + backPlane.SetYLength(maxY - minY) + backPlane.SetZLength(thickness) + + if not backMapper: + backMapper = vtk.vtkPolyDataMapper() + backMapper.SetInput(backPlane.GetOutput()) + + if not back: + back = vtk.vtkActor() + back.SetMapper(backMapper) + + if not leftPlane: + leftPlane = vtk.vtkCubeSource() + leftPlane.SetCenter( minX, (maxY+minY)/2.0, (maxZ+minZ)/2.0) + leftPlane.SetXLength(thickness) + leftPlane.SetYLength(maxY-minY) + leftPlane.SetZLength(maxZ-minZ) + + if not leftMapper: + leftMapper = vtk.vtkPolyDataMapper() + leftMapper.SetInput(leftPlane.GetOutput()) + + if not left: + left = vtk.vtkActor() + left.SetMapper(leftMapper) + + return [base, back, left] + diff --git a/Utilities/vtkTclTest2Py/catch.py b/Utilities/vtkTclTest2Py/catch.py new file mode 100644 index 0000000..7c3b08d --- /dev/null +++ b/Utilities/vtkTclTest2Py/catch.py @@ -0,0 +1,13 @@ +""" implementation for tcl catch. +since this call may need to create new vars in the caller scope +we have to use globals(), since locals are readonly. +This script is used while running python tests translated from Tcl.""" + +import sys +def catch(caller_globalvars_dict, code_to_catch): + try: + exec(code_to_catch, caller_globalvars_dict) + except: + print "caught exception: %s" % sys.exc_info()[1] + return 1 #returns non-zero on exception + return 0 #return zero when no exception is raised diff --git a/Utilities/vtkTclTest2Py/compile_all_vtk.py.in b/Utilities/vtkTclTest2Py/compile_all_vtk.py.in new file mode 100644 index 0000000..4bffcbf --- /dev/null +++ b/Utilities/vtkTclTest2Py/compile_all_vtk.py.in @@ -0,0 +1,4 @@ +import compileall +compileall.compile_dir('@VTK_BINARY_DIR@/Utilities/vtkTclTest2Py') +file = open('@VTK_BINARY_DIR@/Utilities/vtkTclTest2Py/vtk_compile_complete', 'w') +file.write('Done') diff --git a/Utilities/vtkTclTest2Py/expr.py b/Utilities/vtkTclTest2Py/expr.py new file mode 100644 index 0000000..574f770 --- /dev/null +++ b/Utilities/vtkTclTest2Py/expr.py @@ -0,0 +1,29 @@ +"""Evalues a tcl expr expression.""" +import math + +def expr(caller_globals_dict, caller_localvars_dict, arguments): + """the arguments to expr in tcl are passed as individual arguments to this + method. + eg [expr sin(20)*$a] becomes expr.expr("sin","(","20",")","*", a)""" + eval_str = "eval(\"\"\"" + for arg in arguments: + if arg in caller_localvars_dict.keys(): + #arg is a local variable. First, get its value + arg = caller_localvars_dict[arg] + if type(arg) == type("string"): + #this will obtain value in the variable. + if arg in dir(math): + eval_str += "math.%s" % arg + else: + if arg == "(": + eval_str += arg + else: + if arg.strip() == "double": + arg = "float" #tcl double is python float + eval_str += " " + arg + continue + eval_str += " " + `arg` + eval_str += "\"\"\")" + #print "eval_str : %s" % eval_str + return eval(eval_str, caller_globals_dict, caller_localvars_dict) + diff --git a/Utilities/vtkTclTest2Py/file.py b/Utilities/vtkTclTest2Py/file.py new file mode 100644 index 0000000..b00aa01 --- /dev/null +++ b/Utilities/vtkTclTest2Py/file.py @@ -0,0 +1,33 @@ +"""selective implementation of tcl file command. +This script is used while running python tests translated from Tcl.""" + +import os +import stat + +def is_dir(filename): + if stat.S_ISDIR(os.stat(filename)[stat.ST_MODE]): + return True + return False + +def delete( *arguments ): + end_of_switch = False + force_switch = False + pathnames = [] + for arg in arguments: + if arg.strip() == "-force" and not end_of_switch: + force_switch = True + elif arg.strip() == "--" and not end_of_switch: + end_of_switch = True + else: + pathnames.append(arg) + for filename in pathnames: + #dir is deleted only if force is specified. + try: + if is_dir(filename): + if force_switch: + os.rmdirs(filename) + else: + os.remove(filename) + except: + pass + diff --git a/Utilities/vtkTclTest2Py/info.py b/Utilities/vtkTclTest2Py/info.py new file mode 100644 index 0000000..e63b012 --- /dev/null +++ b/Utilities/vtkTclTest2Py/info.py @@ -0,0 +1,20 @@ +"""Selective implementation of tcl info command. +This script is used while running python tests translated from Tcl.""" + +import re + +def command (caller_globals, caller_locals, pattern): + return commands(caller_globals, caller_locals, pattern) + +def commands (caller_globals, caller_locals, pattern): + print "pattern %s" % pattern + rex = re.compile(pattern) + + str = "" + for c in caller_globals.keys(): + if rex.match(c): + str += c + " " + for c in caller_locals.keys(): + if rex.match(c): + str += c + " " + return str.strip() diff --git a/Utilities/vtkTclTest2Py/mccases.py b/Utilities/vtkTclTest2Py/mccases.py new file mode 100644 index 0000000..568093f --- /dev/null +++ b/Utilities/vtkTclTest2Py/mccases.py @@ -0,0 +1,35 @@ +"""This is python equivalent of Wrapping/Tcl/vtktesting/mccases.tcl. +Used for setting vertex values for clipping, cutting, and contouring tests. +This script is used while running python tests translated from Tcl.""" + +def case1 ( scalars, IN, OUT, caseLabel ): + scalars.InsertValue(0,IN ) + scalars.InsertValue(1,OUT) + scalars.InsertValue(2,OUT) + scalars.InsertValue(3,OUT) + scalars.InsertValue(4,OUT) + scalars.InsertValue(5,OUT) + scalars.InsertValue(6,OUT) + scalars.InsertValue(7,OUT) + if IN == 1: + caseLabel.SetText("Case 1 - 00000001") + else : + caseLabel.SetText("Case 1c - 11111110") + pass + +def case2 ( scalars, IN, OUT, caseLabel ): + scalars.InsertValue(0,IN) + scalars.InsertValue(1,IN) + scalars.InsertValue(2,OUT) + scalars.InsertValue(3,OUT) + scalars.InsertValue(4,OUT) + scalars.InsertValue(5,OUT) + scalars.InsertValue(6,OUT) + scalars.InsertValue(7,OUT) + if IN == 1: + caseLabel.SetText("Case 2 - 00000011") + else: + caseLabel.SetText("Case 2c - 11111100") + pass + + diff --git a/Utilities/vtkTclTest2Py/rtImageTest.py b/Utilities/vtkTclTest2Py/rtImageTest.py new file mode 100644 index 0000000..403feef --- /dev/null +++ b/Utilities/vtkTclTest2Py/rtImageTest.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# This is the script that runs a testing python script. +# The script to be run must be the first argument. +import sys +if len(sys.argv) < 2: + print "Usage %s []" % sys.argv[0] + sys.exit(1) +for i in range(2, len(sys.argv)): + if sys.argv[i] == '-A' and i < len(sys.argv)-1: + sys.path = sys.path + [sys.argv[i+1]] + +import vtk +import math + +#these are the modules that define methods/variables +#used by many scripts. We just include them always +from backdrop import * +from mccases import * +import expr +import catch +import info +import file +from vtk.util.colors import * + +#implementation for lindex. +def lindex(list, index): + if type(list) == type("string"): + return list.split()[index] + return list[index] + +#gets with no varName (returns the read string) +def gets(file): + line = file.readline() + if line[-1] == "\n": + line = line[:-1] + return line + +def gets(file, varName, global_vars): + line = gets(file) + ret = len(line) + global_vars[varName] = line + return ret + +def tcl_platform(what): + if what != "platform": + raise "Only platform supported as yet!" + plat = sys.platform + if plat[:5] == "linux": + return "unix" + return plat + +def get_variable_name(*args): + var_name = "" + for arg in args: + if arg == "": + continue + # it is essential to qualify the scope of type since + # some test define type variable which messes up the + # bultin call. + if __builtins__.type(arg) == __builtins__.type("string"): + var_name += arg + else: + var_name += `arg` + return var_name + +#init Tk +try: + import Tkinter + pythonTk = Tkinter.Tk() +except: + pythonTk = None + pass #no hassles is Tk is not present. + +# setup some common things for testing +rtTempObject = vtk.vtkObject() + +rtExMath = vtk.vtkMath() +rtExMath.RandomSeed(6) + +# create the testing class to do the work +rtTester = vtk.vtkTesting() +for arg in sys.argv[2:]: + rtTester.AddArgument(arg) + +VTK_DATA_ROOT = rtTester.GetDataRoot() + +# load in the script +test_script = sys.argv[1] + +# set the default threshold, the Tcl script may change this +threshold = -1 + + +# we pass the locals over so that the test script has access to +# all the locals we have defined here. +execfile(test_script, globals(), locals()) + +local_variables_dict = locals() + + +if "iren" in local_variables_dict.keys(): + renWin.Render() + +# run the event loop quickly to map any tkwidget windows +if pythonTk: + pythonTk.withdraw() +# update + +rtResult = 0 + +if rtTester.IsValidImageSpecified() != 0: + # look for a renderWindow ImageWindow or ImageViewer + # first check for some common names + if "renWin" in local_variables_dict.keys(): + rtTester.SetRenderWindow(renWin) + if threshold == -1: + threshold = 10 + else: + if threshold == -1: + threshold = 5 + + if "viewer" in local_variables_dict.keys(): + rtTester.SetRenderWindow(viewer.GetRenderWindow()) + viewer.Render() + elif "imgWin" in local_variables_dict.keys(): + rtTester.SetRenderWindow(imgWin) + imgWin.Render() + rtResult = rtTester.RegressionTest(threshold) + +if rtResult == 0: + sys.exit(1) +sys.exit(0) diff --git a/Utilities/vtkTclTest2Py/vtkClassList.py.in b/Utilities/vtkTclTest2Py/vtkClassList.py.in new file mode 100644 index 0000000..24be9b9 --- /dev/null +++ b/Utilities/vtkTclTest2Py/vtkClassList.py.in @@ -0,0 +1,10 @@ +# List of wrapped classes in VTK. + + +VTKClassList = [ + @VTK_CLASSES@ + ] + + +def get_vtk_classes(): + return VTKClassList diff --git a/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake b/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake new file mode 100644 index 0000000..06c3500 --- /dev/null +++ b/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake @@ -0,0 +1,72 @@ +# Macro to convert tcl tests to python and add those tests. +# Assumes VTK_WRAP_PYTHON is on and PYTHON_EXECUTABLE is defined. +MACRO (CONVERT_TCL_TEST_TO_PY tcl_tests kit_name) + SET (input_dir ${VTK_SOURCE_DIR}/${kit_name}/Testing/Tcl) + SET (output_dir ${VTK_BINARY_DIR}/${kit_name}/Testing/Python) + SET (target_name ${kit_name}PythonTests) + + SET(CMD ${PYTHON_EXECUTABLE}) + SET (CONVERTED_TESTS) + SET (CONVERTER_SCRIPT "${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/vtkTclToPyConvertor.py") + SET (TESTS_TO_CONVERT) + SET (CONVERSIONLIST) + + FOREACH(test ${${tcl_tests}}) + SET(input "${input_dir}/${test}.tcl") + SET(output "${output_dir}/${test}.py") + + SET (CONVERTED_TESTS ${CONVERTED_TESTS} "${output}") + SET (CONVERSIONLIST ${CONVERSIONLIST} "${input};${output}") + SET (TESTS_TO_CONVERT ${TESTS_TO_CONVERT} "${input}") + + #Add the py test. + IF (${VTK_DATA_ROOT}) + ADD_TEST(${test}Python ${VTK_PYTHON_EXE} + ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/rtImageTest.py + ${output} + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/${kit_name}/${test}.png + -A "${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py" + -A "${VTK_LIBRARY_DIR}" + ) + ELSE (${VTK_DATA_ROOT}) + ADD_TEST(${test}Python ${VTK_PYTHON_EXE} + ${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py/rtImageTest.py + ${output} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/${kit_name}/${test}.png + -A "${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py" + -A "${VTK_LIBRARY_DIR}" + ) + ENDIF (${VTK_DATA_ROOT}) + ENDFOREACH(test) + + CONFIGURE_FILE( + ${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkTestsToConvert.in + ${output_dir}/vtkTestsToConvert + @ONLY + ) + + ADD_CUSTOM_COMMAND( + OUTPUT "${output_dir}/conversion_complete" + COMMAND ${CMD} + ARGS ${CONVERTER_SCRIPT} + -l "${output_dir}/vtkTestsToConvert" + -t "${output_dir}/conversion_complete" + -A "${VTK_BINARY_DIR}/Utilities/vtkTclTest2Py" + -A "${VTK_BINARY_DIR}/Wrapping/Python" + -A "${VTK_LIBRARY_DIR}" + DEPENDS ${TESTS_TO_CONVERT} + ${output_dir}/vtkTestsToConvert + ${CONVERTER_SCRIPT} + COMMENT "Converting Tcl test" + ) + ADD_CUSTOM_TARGET(${target_name} ALL DEPENDS + "${output_dir}/conversion_complete") + + ADD_DEPENDENCIES(${target_name} vtktcltest2py_pyc) + + # TODO: add explicit dependency between the vtk{Name}Kit.cmake files and the + # the test conversion. +ENDMACRO (CONVERT_TCL_TEST_TO_PY) diff --git a/Utilities/vtkTclTest2Py/vtkTclParser.py b/Utilities/vtkTclTest2Py/vtkTclParser.py new file mode 100644 index 0000000..e534027 --- /dev/null +++ b/Utilities/vtkTclTest2Py/vtkTclParser.py @@ -0,0 +1,245 @@ +"""This parses the tcl script and calls virtual methods to translate the code +to target language.""" + + +import re + +# Some module variables used internally. +token = "[+\-]?[\$0-9A-Za-z_\.{}]+" +hexnumber = "0x[0-9abcdefABCDEF]+" +number = "[+-]?[0-9]+(?:(?:\.[0-9]+)?(?:e[+-][0-9]+)?)?" +number2 = "[+-]?\.[0-9]+(?:e[+-][0-9]+)?" +word_separator = "[ \t]" +command_separator = "[\n;]" +word = "%s*(%s|%s|%s|%s)"% (word_separator, hexnumber, number2, number, token) +reWord = re.compile("^%s" % word ) +reNewWord = re.compile("^(?:%s|%s)*%s" % (command_separator, word_separator, + word)) +reCondition = re.compile("%s*([!<>=]+)" % word_separator) +reOperation = re.compile("%s*([|&<>=!+\-/%%*()]+)" % word_separator) +reStackBegin = re.compile("%s*(? 0 and command[0] == "#": + translated_cmd = command + elif len(command) > 0 and command[0] == "\"": + translated_cmd = command + elif command == "global" and len(arguments) >= 1: + translated_cmd = "global %s" % arguments[0] + for arg in arguments[1:]: + translated_cmd += ", %s" % arg + elif command == "eval" and len(arguments) > 0: + translated_cmd = self.translate_command(arguments[0], arguments[1:]) + pass + elif command == "catch" and len(arguments) == 1: + translated_cmd = "catch.catch(globals(),\"\"\"%s\"\"\")" % \ + self.translate_block(arguments[0]).strip() + elif command == "expr": + translated_cmd = "expr.expr(globals(), locals(),[" + i = False + for arg in arguments: + if i: + translated_cmd += "," + translated_cmd += "\"%s\"" % arg + i = True + translated_cmd += "])" + elif command == "lindex" and len(arguments) == 2: + translated_cmd = "lindex(%s,%s)" % (arguments[0], arguments[1]) + elif command == "append" and len(arguments) >= 2: + translated_cmd = "%s += %s" % (arguments[0], arguments[1]) + for arg in arguments[2:]: + translated_cmd += " + %s" % arg + elif command == "proc" and len(arguments) == 3: + translated_cmd = "def %s (" % arguments[0] + proc_args = arguments[1].split() + i = False + pair = 0 + for pa in proc_args: + if pa.strip() == "{": + pair = 1 + continue + elif pa.strip() == "}": + pair = 0 + continue + if i and pair != 2: + translated_cmd += "," + if pair == 2: + translated_cmd += "=" + if pair == 1: + pair = 2 + i = True + translated_cmd += pa + translated_cmd +="):\n" + p = self._get_block_parser() + p.feed(arguments[2]) + translated_cmd += p.output + self._procedure_list.append(arguments[0]) + elif command == "set" and len(arguments) == 2: + #translate a set command. + translated_cmd = "%s = %s" % (arguments[0], arguments[1]) + elif command == "foreach" and len(arguments) == 3: + p = self._get_block_parser() + p.feed(arguments[0]) + arguments[0] = p.output.strip() + p = self._get_block_parser() + p.feed(arguments[1]) + arguments[1] = p.output.strip() + p = self._get_block_parser() + p.indent = self.indent + " " + p.feed(arguments[2]) + translated_cmd = "for %s in %s.split():\n" % (arguments[0], arguments[1]) + translated_cmd += p.output + translated_cmd += "\n" + self.indent + " pass" + elif command == "for" and len(arguments) == 4: + p = self._get_block_parser() + p.feed(arguments[0]) + translated_cmd = p.output.strip() + "\n" + p = self._get_block_parser() + p.feed(arguments[1]) + translated_cmd += self.indent + "while " + p.output.strip() + ":\n" + p = self._get_block_parser() + p.indent = self.indent + " " + p.feed(arguments[3]) + translated_cmd += p.output + p = self._get_block_parser() + p.indent = self.indent + " " + p.feed(arguments[2]) + translated_cmd += p.output + elif command == "while" and len(arguments) == 2: + p = self._get_block_parser() + p.feed(arguments[0]) + translated_cmd = "while %s:\n" % p.output.strip() + p = self._get_block_parser() + p.indent = self.indent + " " + p.feed(arguments[1]) + translated_cmd += p.output + translated_cmd += "\n" + self.indent + " pass" + elif command in ["if", "elseif"] and len(arguments) >= 2: + p = self._get_block_parser() + p.indent = self.indent + p.feed(arguments[0]) + if command == "if": + translated_cmd = "if (%s):\n" % p.output.strip() + else: + translated_cmd = "elif (%s):\n" % p.output.strip() + p = self._get_block_parser() + p.indent = self.indent + " " + p.feed(arguments[1]) + translated_cmd += p.output + if len(arguments) > 2: + translated_cmd += self.indent + \ + self.translate_command(arguments[2], arguments[3:]) + translated_cmd += self.indent + " pass" + elif command=="else" and len(arguments)==1: + translated_cmd = " pass\n" + translated_cmd += self.indent + "else:\n" + p = self._get_block_parser() + p.indent = self.indent + " " + p.feed(arguments[0]) + translated_cmd += p.output + elif command == "return" and len(arguments) == 0: + translated_cmd = "return" + elif command == "return" and len(arguments) == 1: + translated_cmd = "return %s" % arguments[0] + elif command == "open" and len(arguments) >= 1: + translated_cmd = "open(%s" % arguments[0] + for arg in arguments[1:]: + translated_cmd += ", %s" % arg + translated_cmd +=")" + elif command == "close" and len(arguments) == 1: + translated_cmd = "%s.close()" % arguments[0] + elif command == "gets" and len(arguments) == 1: + translated_cmd = "gets(%s)" % arguments[0] + elif command == "gets" and len(arguments) == 2: + translated_cmd = "gets(%s," % arguments[0] + if len(arguments[1]) == 0 or arguments[1][0] not in ["\"","'"]: + translated_cmd += "\"%s\"" % arguments[1] + else: + translated_cmd += "%s" % arguments[1] + translated_cmd +=", globals())" + elif command == "incr" and len(arguments) == 1: + translated_cmd = "%s = %s + 1" % (arguments[0], arguments[0]) + elif command == "incr" and len(arguments) == 2: + translated_cmd = "%s = %s + %s" % (arguments[0], arguments[0], arguments[1]) + elif command == "info" and len(arguments) > 0: + translated_cmd = "info.%s(globals(), locals(), "% arguments[0] + i = False + for arg in arguments[1:]: + if i: + translated_cmd +="," + i = True + translated_cmd += " %s" % arg + translated_cmd +=")" + elif command == "tcl_platform" and len(arguments) >= 3: + new_cmd = "tcl_platform(\"" + arguments[1] + "\")" + if len(arguments) > 3: + return self.translate_command(new_cmd, arguments[3:]) + return translated_cmd + elif command in self.class_list: + #translate a VTK object create command. + if len(arguments) == 1: + translated_cmd = "%s = %s.%s()" % (arguments[0], self.name_space, command) + else: + self._error("Invalid command: %s %s" % (command, `arguments`)) + elif command == "BuildBackdrop" and len(arguments) == 7: + translated_cmd = "[base, back, left] = BuildBackdrop(%s" % arguments[0] + for arg in arguments[1:]: + translated_cmd += ", %s" % arg + translated_cmd += ")" + elif command in ["case1", "case2", "case3", "case4", "case5", "case6", "case7", + "case8", "case9", "case10", "case11", "case12", "case13", "case14"] and \ + len(arguments) == 3: + translated_cmd = "%s(%s, %s, %s, caseLabel)" % (command, arguments[0], arguments[1], arguments[2]) + elif len(arguments) >= 2 and arguments[0][0] in ["<",">","=","!"]: + translated_cmd = command + for arg in arguments: + translated_cmd+= " " + arg + elif command == "file" and len(arguments) > 0: + translated_cmd = "file.%s(" % arguments[0] + i = False + for arg in arguments[1:]: + if i: + translated_cmd +=", " + i = True + if arg.strip() == "-force": + translated_cmd += "\"%s\"" % arg + else: + translated_cmd += "%s" % arg + translated_cmd += ")" + elif len(arguments) > 0 and arguments[0] == "UnRegister": + translated_cmd = "%s.UnRegister(" % command + if len(arguments) < 2 or len(arguments[1].strip()) == 0: + translated_cmd += "None" + else: + translated_cmd += "%s" % arguments[1] + translated_cmd += ")" + pass + elif command in self._procedure_list: + translated_cmd = "%s(" % command + i = False + for arg in arguments: + if i: + translated_cmd +="," + i = True + translated_cmd += arg + translated_cmd +=")" + elif command == "source": + translated_cmd = "#skipping source" + pass + elif len(arguments) == 1 and arguments[0].strip() == "Delete": + translated_cmd = "del %s" % command + elif len(arguments) > 0: + translated_cmd = "" + if arguments[0].strip() == "Print" : + translated_cmd = "#" + #translate a VTK object command invocation. + translated_cmd += "%s.%s(" % (command, arguments[0]) + if len(arguments) > 9: #typically, methods taking more than 9 args in VTK take them as lists. + translated_cmd += "[" + for i in range(1,len(arguments)): + if i > 1: + translated_cmd += "," + if arguments[i] != "" : + translated_cmd += arguments[i] + else: + translated_cmd += "None" + + if len(arguments) > 9: + translated_cmd += "]" + translated_cmd += ")" + elif command and len(arguments) == 0: + return command + return translated_cmd + pass + + def handle_command(self, translated_cmd): + translated_cmd = self.indent + translated_cmd + "\n" + self.output += translated_cmd + pass + +if __name__ == "__main__": + input_file = None + output_file = None + class_file = None + prefix_file = None + convert_file_list_file = None + namespace = "vtk" + touch_file = None + kit_files_dir = "" + for i in range(0, len(sys.argv)): + if sys.argv[i] == "-i" and i < len(sys.argv)-1: + input_file = sys.argv[i+1] + if sys.argv[i] == "-o" and i < len(sys.argv)-1: + output_file = sys.argv[i+1] + if sys.argv[i] == "-f" and i < len(sys.argv)-1: + class_file = sys.argv[i+1] + if sys.argv[i] == "-n" and i < len(sys.argv)-1: + namespace = sys.argv[i+1] + if sys.argv[i] == "-p" and i < len(sys.argv)-1: + prefix_file = sys.argv[i+1] + if sys.argv[i] == "-l" and i < len(sys.argv)-1: + convert_file_list_file = sys.argv[i+1] + if sys.argv[i] == "-t" and i < len(sys.argv)-1: + touch_file = sys.argv[i+1] + if sys.argv[i] == "-k" and i < len(sys.argv)-1: + kit_files_dir = sys.argv[i+1] + + + if (not input_file or not output_file) and not convert_file_list_file: + print "Usage: %s [-o -i ]"\ + "[-f ] [-n ] [-p ]"\ + "[-l ]"\ + "[-t ]"\ + "[-k ] [-k ...] ..." % sys.argv[0] + print "Got Args: %s" % `sys.argv` + sys.exit(1) + class_list = [] + if class_file: + try: + fp = file(class_file, "r") + new_class_list = fp.readlines() + for a in new_class_list: + class_list.append(string.strip(a)) + fp.close() + except: + print "Failed to read class list file %s" % class_file + sys.exit(1) + else: + try: + import vtkClassList + class_list = vtkClassList.get_vtk_classes() + pass + except: + print "ERROR: Failed to load module vtkClassList." + sys.exit(1) + + if not class_list: + print "Cannot find list of classes. Please provide -f option" + sys.exit(1) + + prefix_content = "" + try: + fp = file(prefix_file, "r") + prefix_content = fp.read() + fp.close() + except: + pass + convert_file_list = [] + output_file_list = [] + if convert_file_list_file: + try: + fp = file(convert_file_list_file, "r") + filename_list = fp.read().split(";") + fp.close() + for i in range(0, len(filename_list), 2): + convert_file_list.append(filename_list[i]) + output_file_list.append(filename_list[i+1]) + except: + print "Failed to read list of file to translate %s" % convert_file_list_file + print "%s" % sys.exc_info()[1] + sys.exit(1) + + + if input_file: + convert_file_list.append(input_file) + if output_file: + output_file_list.append(output_file) + + for i in range(0,len(convert_file_list)): + data = "" + ip_filename = convert_file_list[i].strip() + op_filename = output_file_list[i].strip() + try: + print "Converting %s" % ip_filename + fp = file(ip_filename, "r") + data = fp.read() + fp.close() + except: + print "Failed to read input file %s" % ip_filename + sys.exit(1) + + p = vtkTclToPyConvertor() + p.class_list = class_list + p.name_space = namespace + p.print_header(prefix_content) + p.feed(data) + p.print_footer() + if p.success(): + try: + ofp = file(op_filename, "w") + ofp.write(p.output) + ofp.close() + except: + print "Failed to write output file %s" % op_filename + sys.exit(1) + else: + print "Conversion failed!" + sys.exit(1) + if touch_file: + try: + ofp = file(touch_file, "w") + ofp.write("Done\n") + ofp.close() + except: + print "Failed to touch file %s" % touch_file + sys.exit(1) + + sys.exit(0) diff --git a/Utilities/vtkTclTest2Py/vtkTestsToConvert.in b/Utilities/vtkTclTest2Py/vtkTestsToConvert.in new file mode 100644 index 0000000..7223153 --- /dev/null +++ b/Utilities/vtkTclTest2Py/vtkTestsToConvert.in @@ -0,0 +1 @@ +@CONVERSIONLIST@ diff --git a/Utilities/vtk_expat.h b/Utilities/vtk_expat.h new file mode 100644 index 0000000..3f65c17 --- /dev/null +++ b/Utilities/vtk_expat.h @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk_expat.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtk_expat_h +#define __vtk_expat_h + +/* Use the expat library configured for VTK. */ +#include "vtkToolkits.h" +#ifdef VTK_USE_SYSTEM_EXPAT +# include +#else +# include +#endif + +#endif diff --git a/Utilities/vtk_freetype.h b/Utilities/vtk_freetype.h new file mode 100644 index 0000000..d4e1e46 --- /dev/null +++ b/Utilities/vtk_freetype.h @@ -0,0 +1,35 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk_freetype.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtk_freetype_h +#define __vtk_freetype_h + +/* Use the freetype library configured for VTK. */ +//#include "vtkToolkits.h" +#ifdef VTK_USE_SYSTEM_FREETYPE +#ifndef FTC_Manager_LookupFace +#define FTC_Manager_LookupFace FTC_Manager_Lookup_Face +#endif //FTC_Manager_LookupFace +#ifndef FTC_Manager_LookupSize +#define FTC_Manager_LookupSize FTC_Manager_Lookup_Size +#endif //FTC_Manager_LookupSize +# include +#else +# include +# if defined(VTKFREETYPE) +# include "vtkFreeTypeConfig.h" +# endif +#endif + +#endif diff --git a/Utilities/vtk_jpeg.h b/Utilities/vtk_jpeg.h new file mode 100644 index 0000000..d53f09f --- /dev/null +++ b/Utilities/vtk_jpeg.h @@ -0,0 +1,48 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk_jpeg.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtk_jpeg_h +#define __vtk_jpeg_h + +/* Use the jpeg library configured for VTK. */ +#include "vtkToolkits.h" +#ifdef VTK_USE_SYSTEM_JPEG + /* Work-around for a conflict between windows.h and jpeglib.h in cygwin. + If ADDRESS_TAG_BIT is defined then BaseTsd.h has been included and + INT32 has been defined with a typedef, so we must define XMD_H to + prevent the jpeg header from defining it again. */ +# if defined(__CYGWIN__) && defined(ADDRESS_TAG_BIT) && !defined(XMD_H) +# define XMD_H +# define VTK_JPEG_XMD_H +# endif +# include +# if defined(VTK_JPEG_XMD_H) +# undef VTK_JPEG_XMD_H +# undef XMD_H +# endif +#else +# include +#endif + +#endif + +/* Include the jerror header if VTK_JPEG_INCLUDE_JERROR is defined. */ +#if defined(VTK_JPEG_INCLUDE_JERROR) && !defined(VTK_JPEG_JERROR_INCLUDED) +# define VTK_JPEG_JERROR_INCLUDED +# ifdef VTK_USE_SYSTEM_JPEG +# include +# else +# include +# endif +#endif diff --git a/Utilities/vtk_netcdf.h b/Utilities/vtk_netcdf.h new file mode 100644 index 0000000..e2fbbe5 --- /dev/null +++ b/Utilities/vtk_netcdf.h @@ -0,0 +1,21 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk_netcdf.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtk_netcdf_h +#define __vtk_netcdf_h + +/* Use the netcdf library configured for VTK. */ +#include + +#endif diff --git a/Utilities/vtk_png.h b/Utilities/vtk_png.h new file mode 100644 index 0000000..bac07f9 --- /dev/null +++ b/Utilities/vtk_png.h @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk_png.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtk_png_h +#define __vtk_png_h + +/* Use the png library configured for VTK. */ +#include "vtkToolkits.h" +#ifdef VTK_USE_SYSTEM_PNG +# include +#else +# include +#endif + +#endif diff --git a/Utilities/vtk_tiff.h b/Utilities/vtk_tiff.h new file mode 100644 index 0000000..0b3628e --- /dev/null +++ b/Utilities/vtk_tiff.h @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk_tiff.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtk_tiff_h +#define __vtk_tiff_h + +/* Use the tiff library configured for VTK. */ +#include "vtkToolkits.h" +#ifdef VTK_USE_SYSTEM_TIFF +# include +#else +# include +#endif + +#endif diff --git a/Utilities/vtk_zlib.h b/Utilities/vtk_zlib.h new file mode 100644 index 0000000..002c1d8 --- /dev/null +++ b/Utilities/vtk_zlib.h @@ -0,0 +1,26 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk_zlib.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtk_zlib_h +#define __vtk_zlib_h + +/* Use the zlib library configured for VTK. */ +#include "vtkToolkits.h" +#ifdef VTK_USE_SYSTEM_ZLIB +# include +#else +# include +#endif + +#endif diff --git a/Utilities/vtkexodus2/CMakeLists.txt b/Utilities/vtkexodus2/CMakeLists.txt new file mode 100644 index 0000000..1dffb78 --- /dev/null +++ b/Utilities/vtkexodus2/CMakeLists.txt @@ -0,0 +1,64 @@ +PROJECT(vtkExodus2) + +INCLUDE_REGULAR_EXPRESSION(".*") + +SET(EXODUSII_VERSION_MAJOR "2") +SET(EXODUSII_VERSION_MINOR "0") +SET(EXODUSII_VERSION_PATCH "0") +SET(EXODUSII_VERSION "${EXODUSII_VERSION_MAJOR}.${EXODUSII_VERSION_MINOR}") +SET(EXODUSII_VERSION_FULL "${EXODUSII_VERSION}.${EXODUSII_VERSION_PATCH}") + +SET(EXODUSII_BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}") + +CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/include/exodusII_cfg.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/exodusII_cfg.h + @ONLY IMMEDIATE) + +INCLUDE_DIRECTORIES( +"${CMAKE_CURRENT_SOURCE_DIR}/include" +"${CMAKE_CURRENT_BINARY_DIR}/include" +) + +SET(cbind_SRCS + exerr.c exopts.c expini.c exgini.c excre.c + exgcor.c expcor.c expcon.c exgcon.c expmap.c exgmap.c + expelb.c exgelb.c expelc.c exgelc.c expeat.c + exgeat.c expnp.c exgnp.c expns.c expnsd.c exgns.c exgnsd.c + expcns.c exgcns.c expsp.c exgsp.c expss.c exgss.c + expssd.c exgssd.c expcss.c exgcss.c expvpc.c + expqa.c exgqa.c expinf.c exginf.c expvp.c exgvp.c + expvan.c exgvan.c expvnm.c exgvnm.c expvtt.c exgvtt.c + expgv.c exggv.c exggvt.c expnv.c exgnv.c exgnvt.c + expev.c exgev.c exgevt.c expclb.c exgssc.c expfrm.c exgfrm.c + exptim.c exgtim.c exgatm.c exinq.c + exopen.c exupda.c exclos.c exgebi.c exgssi.c exgnsi.c + ex_utils.c ex_conv.c excn2s.c exgsnl.c exgssn.c + exgp.c exgpa.c exgpn.c expp.c exppa.c exppn.c + exgenm.c exgnnm.c expnnm.c expenm.c excopy.c + expmp.c exgmp.c expem.c exgem.c expnm.c exgnm.c + exgvv.c expvv.c expnvv.c exgnvv.c exgnvid.c exgevid.c + ) + +IF(APPLE) + SET_SOURCE_FILES_PROPERTIES( + ex_utils.c + PROPERTIES + COMPILE_FLAGS -fno-common) +ENDIF(APPLE) + + +ADD_LIBRARY(vtkexoIIc ${cbind_SRCS}) +TARGET_LINK_LIBRARIES(vtkexoIIc vtkNetCDF) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkexoIIc PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkexoIIc) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) +# INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtkexodus2 .h +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/vtkexodus2/COPYRIGHT b/Utilities/vtkexodus2/COPYRIGHT new file mode 100644 index 0000000..2976485 --- /dev/null +++ b/Utilities/vtkexodus2/COPYRIGHT @@ -0,0 +1,32 @@ +Copyright (c) 1994 Sandia Corporation. Under the terms of Contract +DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement +retains certain rights in this software. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/Utilities/vtkexodus2/ex_conv.c b/Utilities/vtkexodus2/ex_conv.c new file mode 100644 index 0000000..9eb3fb8 --- /dev/null +++ b/Utilities/vtkexodus2/ex_conv.c @@ -0,0 +1,584 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exutils - exodus utilities +* +* author - James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* environment - UNIX +* +* entry conditions - +* +* exit conditions - +* +* revision history - +* +* $Id: ex_conv.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +typedef int convert_task; + +/* this file contains code needed to support the various floating point word + * size combinations for computation and i/o that applications might want to + * use. the following discussion uses the C type names "float" and "double". + * + * netCDF supports two floating point word sizes for its files: + * NC_FLOAT - 32 bit IEEE (in XDR parlance, XDR_FLOAT) + * NC_DOUBLE - 64 bit IEEE (in XDR parlance, XDR_DOUBLE) + * now, if you want to write an array of NC_FLOATs, netCDF expects as input + * an array of native floats; NC_DOUBLEs require an input array of native + * doubles. + * + * so, suppose you're computing using variables declared double, but you want + * to write a netCDF file using NC_FLOATs. you need to copy your array into + * a buffer array declared as float, which truncates your data from double to + * float (type conversion). then you can pass the buffer array to netCDF + * routines for output as NC_FLOATs, and everything will work OK. similarly, + * if you are computing in floats but want to write NC_DOUBLEs, you need to + * copy your data into a buffer array declared as double, which promotes it + * from float to double, and then call the netCDF routine with the buffer array. + * + * these routines are designed to do this type conversion, based on information + * given in the ex_open or ex_create calls. thus, except for when the file is + * opened, the user is relieved of the burden of caring about compute word size + * (the size of floating point variables used in the application program, and + * passed into the EXODUS II calls) and i/o word size (the size of floating + * point data as written in the netCDF file). + * + * this code is supposed to be general enough to handle weird cases like the + * cray, where in C (and C++) both floats and doubles are 8 byte quantities. + * thus the same array can be passed into a netCDF routine to write either + * NC_FLOATs or NC_DOUBLEs. + * + * note: 16 byte floating point values, such as might be obtained from an ANSI C + * "long double", are specifically not handled. Also, I don't know how + * the vanilla netCDF interface handles double precision on a CRAY, which + * gives 16 byte values, but these routines as written won't be able to + * handle it. + * + * author: j. a. schutt, sandia national laboratories, department 1425 + */ + +#define NC_FLOAT_WORDSIZE 4 +#define NC_DOUBLE_WORDSIZE 8 + +enum conv_action { NO_CONVERSION, CONVERT_UP, CONVERT_DOWN }; +typedef int conv_action; + +struct file_item { + int file_id; + conv_action rd_conv_action; + conv_action wr_conv_action; + nc_type netcdf_type_code; + int user_compute_wordsize; + struct file_item* next; +}; + +struct file_item* file_list = NULL; + +/* + * Now recognized at more locations worldwide in this file... + */ + +static int cur_len = 0; /* in bytes! */ +static void* buffer_array = NULL; +static int do_conversion = 0; /* Do any files do a conversion? */ + +#define FIND_FILE(ptr,id) { ptr = file_list; \ + while(ptr) { \ + if( ptr->file_id == id ) break; \ + ptr = ptr->next; \ + } \ + } + +/*............................................................................*/ +/*............................................................................*/ + +int ex_conv_ini( int exoid, + int* comp_wordsize, + int* io_wordsize, + int file_wordsize ) +{ + char errmsg[MAX_ERR_LENGTH]; + struct file_item* new_file; + +/* ex_conv_ini() initializes the floating point conversion process. + * + * exoid an integer uniquely identifying the file of interest. + * + * word size parameters are specified in bytes. valid values are 0, 4, and 8: + * + * comp_wordsize compute floating point word size in the user's code. + * a zero value indicates that the user is requesting the + * default float size for the machine. The appropriate + * value is chosen and returned in comp_wordsize, and used + * in subsequent conversions. a valid but inappropriate + * for this parameter cannot be detected. + * + * io_wordsize the desired floating point word size for a netCDF file. + * for an existing file, if this parameter doesn't match + * the word size of data already stored in the file, a + * fatal error is generated. a value of 0 for an existing + * file indicates that the word size of the file was not + * known a priori, so use whatever is in the file. a value + * of 0 for a new file means to use the default size, an + * NC_FLOAT (4 bytes). when a value of 0 is specified the + * actual value used is returned in io_wordsize. + * + * file_wordsize floating point word size in an existing netCDF file. + * a value of 0 should be passed in for a new netCDF file. + */ + +/* check to make sure machine word sizes aren't weird (I'm paranoid) */ + + if ((sizeof(float) != 4 && sizeof(float) != 8) || + (sizeof(double) != 4 && sizeof(double) != 8 ) ) + { + sprintf(errmsg,"Error: unsupported compute word size for file id: %d", + exoid); + ex_err("ex_conv_ini",errmsg,EX_FATAL); + return(EX_FATAL); + } + +/* check to see if requested word sizes are valid */ + + if (!*io_wordsize ) + { + if (!file_wordsize ) + *io_wordsize = NC_FLOAT_WORDSIZE; + else + *io_wordsize = file_wordsize; + } + else if (*io_wordsize != 4 && *io_wordsize != 8 ) + { + sprintf(errmsg,"Error: unsupported I/O word size for file id: %d",exoid); + ex_err("ex_conv_ini",errmsg,EX_FATAL); + return(EX_FATAL); + } + else if (file_wordsize && *io_wordsize != file_wordsize ) + { + *io_wordsize = file_wordsize; + sprintf(errmsg, + "Error: invalid I/O word size specified for existing file id: %d", + exoid); + ex_err("ex_conv_ini",errmsg,EX_MSG); + ex_err("ex_conv_ini", + " Requested I/O word size overridden.", + EX_MSG); + } + + if (!*comp_wordsize ) + { + *comp_wordsize = sizeof(float); + } + else if (*comp_wordsize != 4 && *comp_wordsize != 8 ) + { + ex_err("ex_conv_ini","Error: invalid compute wordsize specified",EX_FATAL); + return(EX_FATAL); + } + +/* finally, set up conversion action */ + + new_file = malloc(sizeof(struct file_item)); + + new_file->file_id = exoid; + new_file->user_compute_wordsize = *comp_wordsize; + new_file->next = file_list; + file_list = new_file; + +/* crays writing NC_FLOATs always hit this case first since on a cray + * sizeof(float) = sizeof(double) + */ + if( *comp_wordsize == sizeof(float) && + *io_wordsize == NC_FLOAT_WORDSIZE ) { + + new_file->rd_conv_action = NO_CONVERSION; + new_file->wr_conv_action = NO_CONVERSION; + new_file->netcdf_type_code = NC_FLOAT; + } +/* crays writing NC_DOUBLEs always hit this case first since on a cray + * sizeof(float) = sizeof(double) + */ + else if( *comp_wordsize == sizeof(double) && + *io_wordsize == NC_DOUBLE_WORDSIZE ) { + + new_file->rd_conv_action = NO_CONVERSION; + new_file->wr_conv_action = NO_CONVERSION; + new_file->netcdf_type_code = NC_DOUBLE; + } + else if( *comp_wordsize == sizeof(double) && + *io_wordsize == NC_FLOAT_WORDSIZE ) { + + new_file->rd_conv_action = CONVERT_UP; + new_file->wr_conv_action = CONVERT_DOWN; + new_file->netcdf_type_code = NC_FLOAT; + do_conversion = 1; + } + else if( *comp_wordsize == sizeof(float) && + *io_wordsize == NC_DOUBLE_WORDSIZE ) { + + new_file->rd_conv_action = CONVERT_DOWN; + new_file->wr_conv_action = CONVERT_UP; + new_file->netcdf_type_code = NC_DOUBLE; + do_conversion = 1; + } + else + { + /* Invalid compute or io wordsize: i.e. 4 byte compute word on Cray */ + sprintf(errmsg,"Error: invalid compute (%d) or io (%d) wordsize specified", + *comp_wordsize, *io_wordsize); + ex_err("ex_conv_ini", errmsg, EX_FATAL); + return(EX_FATAL); + } + + return(EX_NOERR); + +} + +/*............................................................................*/ +/*............................................................................*/ + +void ex_conv_exit( int exoid ) +{ +/* ex_conv_exit() takes the structure identified by "exoid" out of the linked + * list which describes the files that ex_conv_array() knows how to convert. + * + * NOTE: it is absolutely necessary for ex_conv_array() to be called after + * ncclose(), if the parameter used as "exoid" is the id returned from + * an ncopen() or nccreate() call, as netCDF reuses file ids! + * the best place to do this is ex_close(), which is where I did it. + * + * "exoid" is some integer which uniquely identifies the file of interest. + */ + + char errmsg[MAX_ERR_LENGTH]; + struct file_item* file = file_list; + struct file_item* prev = NULL; + + exerrval = 0; /* clear error code */ + while( file ) + { + if (file->file_id == exoid ) break; + + prev = file; + file = file->next; + } + + if (!file ) + { + sprintf(errmsg,"Warning: failure to clear file id %d - not in list.",exoid); + ex_err("ex_conv_exit",errmsg,EX_MSG); + exerrval = EX_BADFILEID; + return; + } + + if (prev ) + prev->next = file->next; + else + file_list = file->next; + + free( file ); + + /* + * If no other files are opened, any buffer arrays for float/double + * conversion ought to be cleaned up. + */ + if ( !file_list ) + { + if ( cur_len > 0 ) + { + free(buffer_array); /* Better not be null if condition true! */ + buffer_array = NULL; + cur_len = 0; + } + do_conversion = 0; + } +} + +/*............................................................................*/ +/*............................................................................*/ + +nc_type nc_flt_code( int exoid ) +{ +/* nc_flt_code() returns either NC_FLOAT or NC_DOUBLE, based on the parameters + * with which ex_conv_ini() was called. nc_flt_code() is used as the nc_type + * parameter on ncvardef() calls that define floating point variables. + * + * "exoid" is some integer which uniquely identifies the file of interest. + */ + + char errmsg[MAX_ERR_LENGTH]; + struct file_item* file; + + exerrval = 0; /* clear error code */ + FIND_FILE( file, exoid ); + + if (!file ) + { + exerrval = EX_BADFILEID; + sprintf(errmsg,"Error: unknown file id %d for nc_flt_code().",exoid); + ex_err("nc_flt_code",errmsg,exerrval); + return (nc_type) -1; + } + + return file->netcdf_type_code; +} + +/*............................................................................*/ +/*............................................................................*/ + +int ex_comp_ws( int exoid ) +{ +/* "exoid" is some integer which uniquely identifies the file of interest. + * + * ex_comp_ws() returns 4 (i.e. sizeof(float)) or 8 (i.e. sizeof(double)), + * depending on the value of floating point word size used to initialize + * the conversion facility for this file id (exoid). + */ + + char errmsg[MAX_ERR_LENGTH]; + struct file_item* file; + + exerrval = 0; /* clear error code */ + FIND_FILE( file, exoid ); + + if (!file ) + { + exerrval = EX_BADFILEID; + sprintf(errmsg,"Error: unknown file id %d",exoid); + ex_err("ex_comp_ws",errmsg,exerrval); + return(EX_FATAL); + } + + return file->user_compute_wordsize; +} + +/*............................................................................*/ +/*............................................................................*/ + +/* some utility routines for use only by ex_conv_array() */ + +#define BUFFER_SIZE_UNIT 8192 /* should be even multiple of sizeof(double) */ + +void* resize_buffer( void* buffer, + int new_len ) /* in bytes! */ +{ + /* + * Broaden the scope of this puppy to aid cleanup in ex_conv_exit(). + */ + + /* static int cur_len = 0; in bytes! */ + + exerrval = 0; /* clear error code */ + if( new_len > cur_len ) + { + + cur_len = BUFFER_SIZE_UNIT * ( new_len/BUFFER_SIZE_UNIT + 1 ); + + if( buffer ) free( buffer ); + buffer = malloc( cur_len ); + + if (!buffer ) + { + exerrval = EX_MEMFAIL; + ex_err("ex_conv_array","couldn't allocate buffer space",exerrval); + return (NULL); + } + } + return buffer; +} + +void flt_to_dbl( float* in_vec, + int len, + double* out_vec ) +{ + int i; + + for( i=0; ird_conv_action ) { + case NO_CONVERSION: + return (void*)usr_array; + case CONVERT_UP: /* file ws: 4 byte, CPU ws: 8 byte */ + len_bytes = usr_length * sizeof(float); + buffer_array = resize_buffer( buffer_array, len_bytes ); + return buffer_array; + case CONVERT_DOWN: /* file ws: 8 byte, CPU ws: 4 byte */ + len_bytes = usr_length * sizeof(double); + buffer_array = resize_buffer( buffer_array, len_bytes ); + return buffer_array; + } + break; + + case READ_CONVERT: + + switch( file->rd_conv_action ) { + case NO_CONVERSION: + break; + case CONVERT_UP: + flt_to_dbl( buffer_array, usr_length, (void*)usr_array ); + break; + case CONVERT_DOWN: + dbl_to_flt( buffer_array, usr_length, (void*)usr_array ); + break; + } + return NULL; + + case WRITE_CONVERT: + + switch( file->wr_conv_action ) { + case NO_CONVERSION: + return (void*)usr_array; + case CONVERT_UP: + len_bytes = usr_length * sizeof(double); + buffer_array = resize_buffer( buffer_array, len_bytes ); + flt_to_dbl( (void*)usr_array, usr_length, buffer_array ); + return buffer_array; + case CONVERT_DOWN: + len_bytes = usr_length * sizeof(float); + buffer_array = resize_buffer( buffer_array, len_bytes ); + dbl_to_flt( (void*)usr_array, usr_length, buffer_array ); + return buffer_array; + } + break; + + case WRITE_CONVERT_DOWN: + + len_bytes = usr_length * sizeof(float); + buffer_array = resize_buffer( buffer_array, len_bytes ); + dbl_to_flt( (void*)usr_array, usr_length, buffer_array ); + return buffer_array; + + case WRITE_CONVERT_UP: + + len_bytes = usr_length * sizeof(double); + buffer_array = resize_buffer( buffer_array, len_bytes ); + flt_to_dbl( (void*)usr_array, usr_length, buffer_array ); + return buffer_array; + + } + + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: unknown task code %d specified for converting float array",task); + ex_err("ex_conv_array",errmsg,exerrval); + return NULL; +} diff --git a/Utilities/vtkexodus2/ex_utils.c b/Utilities/vtkexodus2/ex_utils.c new file mode 100644 index 0000000..1ad7995 --- /dev/null +++ b/Utilities/vtkexodus2/ex_utils.c @@ -0,0 +1,928 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exutils - utility routines +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* environment - UNIX +* +* entry conditions - +* +* exit conditions - +* +* revision history - +* +* $Id: ex_utils.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +*****************************************************************************/ + +#if defined(DEBUG_QSORT) +#include +#endif + +#include +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +struct obj_stats* eb = 0; +struct obj_stats* ns = 0; +struct obj_stats* ss = 0; +struct obj_stats* em = 0; +struct obj_stats* nm = 0; + +/***************************************************************************** +* +* utility routines for string conversions +* ex_catstr - concatenate string/number (where number is converted to ASCII) +* ex_catstr2 - concatenate string1/number1/string2/number2 " +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* environment - UNIX +* +* entry conditions - +* +* exit conditions - +* +* revision history - +* +* NOTE: these routines reuse the same storage over and over to build +* concatenated strings, because the strings are just passed to netCDF +* routines as names used to look up variables. if the strings returned +* by these routines are needed for any other purpose, they should +* immediately be copied into other storage. +*****************************************************************************/ + +char ret_string[MAX_VAR_NAME_LENGTH+1]; + +char *ex_catstr (const char *string, + int num) +{ + sprintf (ret_string, "%s%d", string, num); + return (ret_string); + +} + + +char *ex_catstr2 (const char *string1, + int num1, + const char *string2, + int num2) +{ + sprintf (ret_string, "%s%d%s%d", string1, num1, string2, num2); + return (ret_string); + +} + +/***************************************************************************** +* +* ex_id_lkup - look up id +* +* author - Sandia National Laboratories +* Vic Yarberry - Original +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* char* id_type id type name: +* elem_ss +* node_ns +* side_ss +* int num id value +* +* exit conditions - +* int return index into table (1-based) +* +* revision history - +* +* +*****************************************************************************/ + +int ex_id_lkup( int exoid, + char *id_type, + int num) +{ + + char id_table[MAX_VAR_NAME_LENGTH+1]; + char id_dim[MAX_VAR_NAME_LENGTH+1]; + char stat_table[MAX_VAR_NAME_LENGTH+1]; + char idtyp[MAX_VAR_NAME_LENGTH+1]; + int varid, dimid, i; + long dim_len, start[2], count[2]; + nclong *id_vals=NULL, *stat_vals=NULL; + + static int filled=FALSE; + struct obj_stats *tmp_stats; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + strcpy(idtyp,id_type); + + if (strcmp(idtyp,VAR_ID_EL_BLK) == 0) + { + strcpy(id_table, VAR_ID_EL_BLK); /* id array name */ + strcpy(id_dim, DIM_NUM_EL_BLK); /* id array dimension name*/ + strcpy(stat_table, VAR_STAT_EL_BLK); /* id status array name */ + tmp_stats = get_stat_ptr (exoid, &eb); + } + else if (strcmp(idtyp,VAR_NS_IDS) == 0) + { + strcpy(id_table, VAR_NS_IDS); + strcpy(id_dim, DIM_NUM_NS); + strcpy(stat_table, VAR_NS_STAT); + tmp_stats = get_stat_ptr (exoid, &ns); + } + else if (strcmp(idtyp,VAR_SS_IDS) == 0) + { + strcpy(id_table, VAR_SS_IDS); + strcpy(id_dim, DIM_NUM_SS); + strcpy(stat_table, VAR_SS_STAT); + tmp_stats = get_stat_ptr (exoid, &ss); + } + else if (strcmp(idtyp,VAR_EM_PROP(1)) == 0) + { + strcpy(id_table, VAR_EM_PROP(1)); + strcpy(id_dim, DIM_NUM_EM); + strcpy(stat_table, ""); + tmp_stats = get_stat_ptr (exoid, &em); + } + else if (strcmp(idtyp,VAR_NM_PROP(1)) == 0) + { + strcpy(id_table, VAR_NM_PROP(1)); + strcpy(id_dim, DIM_NUM_NM); + strcpy(stat_table, ""); + tmp_stats = get_stat_ptr (exoid, &nm); + } + else + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: unsupported id array type %s for file id %d", + idtyp, exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + return (EX_FATAL); + } + + if ( (tmp_stats->id_vals == NULL) || (!(tmp_stats->valid_ids)) ) { + + /* first time thru or id arrays haven't been completely filled yet */ + + /* get size of id array */ + + /* First get dimension id of id array */ + if ((dimid = ncdimid(exoid,id_dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate id array dimension in file id %d", + exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + return (EX_FATAL); + } + + + /* Next get value of dimension */ + if (ncdiminq (exoid,dimid,(char *) 0,&dim_len) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate %s array length in file id %d", + id_table,exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + return (EX_FATAL); + } + + /* get variable id of id array */ + if ((varid = ncvarid (exoid, id_table)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate %s array in file id %d", + id_table, exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + return (EX_FATAL); + } + + /* allocate space for id array */ + if (!(id_vals = malloc((int)dim_len*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for %s array for file id %d", + id_table,exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + return (EX_FATAL); + } + + start[0] = 0; + start[1] = 0; + count[0] = dim_len; + count[1] = 0; + + + if (ncvarget (exoid, varid, start, count, (void *)id_vals) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get %s array from file id %d", + id_table,exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + free(id_vals); + return (EX_FATAL); + } + + /* check if values in stored arrays are filled with non-zeroes */ + filled = TRUE; + for (i=0;ivalid_ids = TRUE; + tmp_stats->num = dim_len; + tmp_stats->id_vals = id_vals; + } + + } else { + id_vals = tmp_stats->id_vals; + dim_len = tmp_stats->num; + } + + /* Do a linear search through the id array to find the array value + corresponding to the passed index number */ + + for (i=0;i= dim_len) /* failed to find id number */ + { + if ( !(tmp_stats->valid_ids) ) { + free (id_vals); + } + exerrval = EX_LOOKUPFAIL; + return(EX_LOOKUPFAIL); /*if we got here, the id array value doesn't exist */ + } + + /* Now check status array to see if object is null */ + + /* get variable id of status array */ + if ((varid = ncvarid (exoid, stat_table)) != -1) + { + /* if status array exists, use it, otherwise assume object exists + to be backward compatible */ + + if ( (tmp_stats->stat_vals == NULL) || (!(tmp_stats->valid_stat)) ) { + /* first time thru or status arrays haven't been filled yet */ + + /* allocate space for new status array */ + + if (!(stat_vals = malloc((int)dim_len*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for %s array for file id %d", + id_table,exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + return (EX_FATAL); + } + + start[0] = 0; + start[1] = 0; + count[0] = dim_len; + count[1] = 0; + + if (ncvarget (exoid, varid, start, count, (void *)stat_vals) == -1) + { + exerrval = ncerr; + free(stat_vals); + sprintf(errmsg, + "Error: failed to get %s array from file id %d", + stat_table,exoid); + ex_err("ex_id_lkup",errmsg,exerrval); + return (EX_FATAL); + } + + if (tmp_stats->valid_ids) { + /* status array is valid only if ids are valid */ + tmp_stats->valid_stat = TRUE; + tmp_stats->stat_vals = stat_vals; + } + + } else { + stat_vals = tmp_stats->stat_vals; + } + + if (stat_vals[i] == 0) /* is this object null? */ + { + exerrval = EX_NULLENTITY; + if ( !(tmp_stats->valid_stat) ) { + free (stat_vals); + } + return(-(i+1)); /* return index into id array (1-based) */ + } + } + if ( !(tmp_stats->valid_ids) ) { + if (id_vals) free (id_vals); + if (stat_vals) free (stat_vals); + } + return(i+1); /* return index into id array (1-based) */ +} + +/****************************************************************************** +* +* get_stat_ptr - returns a pointer to a structure of object ids +* +* author - Sandia National Laboratories +* Larry Schoof +* +* +* environment - UNIX +* +* revision history - +* +* +*****************************************************************************/ + +/* this routine returns a pointer to a structure containing the ids of + * element blocks, node sets, or side sets according to exoid; if there + * is not a structure that matches the exoid, one is created + */ + +struct obj_stats *get_stat_ptr (int exoid, struct obj_stats **obj_ptr) + +{ + struct obj_stats *tmp_ptr; + + tmp_ptr = *obj_ptr; + + while (tmp_ptr) { + if ( (tmp_ptr)->exoid == exoid) { + break; + } + tmp_ptr = (tmp_ptr)->next; + } + + if (!tmp_ptr) { /* exoid not found */ + tmp_ptr = (struct obj_stats *) calloc (1, sizeof(struct obj_stats)); + tmp_ptr->exoid = exoid; + tmp_ptr->next = *obj_ptr; + *obj_ptr = tmp_ptr; + } + + return (tmp_ptr); +} + +/****************************************************************************** +* +* rm_stat_ptr - removes a pointer to a structure of object ids +* +* author - Sandia National Laboratories +* Larry Schoof +* +* +* environment - UNIX +* +* revision history - +* +* +*****************************************************************************/ + +/* this routine removes a pointer to a structure containing the ids of + * element blocks, node sets, or side sets according to exoid; this + * is necessary to clean up because netCDF reuses file ids; should be + * called from ex_close + */ + +void rm_stat_ptr (int exoid, struct obj_stats **obj_ptr) + +{ + struct obj_stats *last_head_list_ptr, *tmp_ptr; + + tmp_ptr = *obj_ptr; + last_head_list_ptr = *obj_ptr; /* save last head pointer */ + + while (tmp_ptr ) /* Walk linked list of file ids/vals */ + { + if (exoid == tmp_ptr->exoid ) /* linear search for exodus file id */ + { + if (tmp_ptr == *obj_ptr) /* Are we at the head of the list? */ + *obj_ptr = (*obj_ptr)->next; /* yes, reset ptr to head of list */ + else /* no, remove this record from chain*/ + last_head_list_ptr->next=tmp_ptr->next; + if (tmp_ptr->id_vals != NULL) + free(tmp_ptr->id_vals); /* free up memory */ + if (tmp_ptr->stat_vals != NULL) + free(tmp_ptr->stat_vals); + free(tmp_ptr); + break; /* Quit if found */ + } + last_head_list_ptr = tmp_ptr; /* save last head pointer */ + tmp_ptr = tmp_ptr->next; /* Loop back if not */ + } +} +/****************************************************************************** +* +* ex_inc_file_item - increment file item +* +* author - Sandia National Laboratories +* Vic Yarberry +* +* +* environment - UNIX +* +* revision history - +* +* +*****************************************************************************/ + + +/* this routine sets up a structure to track and increment a counter for + * each open exodus file. it is designed to be used by the routines + * ex_put_elem_block(), ex_put_node_set_param(), and ex_put_side_set_param(), + * to keep track of the number of element blocks, node sets, or side sets, + * respectively, for each open exodus II file. + * + * The list structure is used as follows: + * + * ptr -----------> list item structure + * ------------------- + * exodus file id + * item value (int) + * ptr to next (NULL if last) + * + * + * NOTE: since netCDF reuses its file ids, and a user may open and close any + * number of files in one application, items must be taken out of the + * linked lists in each of the above routines. these should be called + * after ncclose(). + */ + +int ex_inc_file_item( int exoid, /* file id */ + struct list_item **list_ptr)/* ptr to ptr to list_item */ + +{ + struct list_item* tlist_ptr; + + + /* printf("[f] list: %ld, *list: %ld \n", list_ptr, *list_ptr); */ + tlist_ptr = *list_ptr; /* use temp list ptr to walk linked list */ + + while (tlist_ptr ) /* Walk linked list of file ids/vals */ + { + if (exoid == tlist_ptr->exo_id ) /* linear search for exodus file id */ + break; /* Quit if found */ + tlist_ptr = tlist_ptr->next; /* Loop back if not */ + } + + if (!tlist_ptr ) /* ptr NULL? */ + { /* yes, new file id */ + /* allocate space for new structure record */ + tlist_ptr = (struct list_item*) calloc(1,sizeof(struct list_item)); + tlist_ptr->exo_id = exoid; /* insert file id */ + tlist_ptr->next = *list_ptr; /* insert into head of list */ + *list_ptr = tlist_ptr; /* fix up new head of list */ + } + +/* printf("[f] tlist: %ld *tlist: %ld **tlist: %ld\n", + tlist_ptr,*tlist_ptr,(*tlist_ptr)->value, (*tlist_ptr)->next); */ + + + return(tlist_ptr->value++); + +} + +/***************************************************************************** +* +* ex_get_file_item - increment file item +* +* author - Sandia National Laboratories +* Vic Yarberry +* +* +* environment - UNIX +* +* revision history - +* +* +*****************************************************************************/ + + +/* this routine accesses a structure to track and increment a counter for + * each open exodus file. it is designed to be used by the routines + * ex_put_elem_block(), ex_put_node_set_param(), and ex_put_side_set_param(), + * to get the number of element blocks, node sets, or side sets, + * respectively, for an open exodus II file. + * + * The list structure is used as follows: + * + * ptr -----------> list item structure + * ------------------- + * exodus file id + * item value (int) + * ptr to next (NULL if last) + * + * + * NOTE: since netCDF reuses its file ids, and a user may open and close any + * number of files in one application, items must be taken out of the + * linked lists in each of the above routines. these should be called + * after ncclose(). + */ + +int ex_get_file_item( int exoid, /* file id */ + struct list_item **list_ptr)/* ptr to ptr to list_item */ + +{ + struct list_item* tlist_ptr; + + /* printf("[f] list: %ld, *list: %ld \n", list_ptr, *list_ptr); */ + tlist_ptr = *list_ptr; /* use temp list ptr to walk linked list */ + + + while (tlist_ptr ) /* Walk linked list of file ids/vals */ + { + if (exoid == tlist_ptr->exo_id ) /* linear search for exodus file id */ + break; /* Quit if found */ + tlist_ptr = tlist_ptr->next; /* Loop back if not */ + } + + if (!tlist_ptr ) /* ptr NULL? */ + { /* yes, Error: file id not found*/ + return(-1); + } + +/* printf("[f] list: %ld *list: %ld **list: %ld\n", + list_ptr,*list_ptr,(*list_ptr)->value, (*list_ptr)->next); */ + + return(tlist_ptr->value); +} + +/***************************************************************************** +* +* ex_rm_file_item - remove file item +* +* author - Sandia National Laboratories +* Vic Yarberry +* +* +* environment - UNIX +* +* revision history - +* +* +*****************************************************************************/ + + +/* this routine removes a structure to track and increment a counter for + * each open exodus file. + * + * The list structure is used as follows: + * + * ptr -----------> list item structure + * ------------------- + * exodus file id + * item value (int) + * ptr to next (NULL if last) + * + * + * NOTE: since netCDF reuses its file ids, and a user may open and close any + * number of files in one application, items must be taken out of the + * linked lists in each of the above routines. these should be called + * after ncclose(). + */ + +void ex_rm_file_item( int exoid, /* file id */ + struct list_item **list_ptr)/* ptr to ptr to list_item */ + +{ + struct list_item *last_head_list_ptr, *tlist_ptr; + + /* printf("[f] list: %ld, *list: %ld \n", list_ptr, *list_ptr); */ + tlist_ptr = *list_ptr; + last_head_list_ptr = *list_ptr; /* save last head pointer */ + /* printf("[f] last head list: %ld\n",last_head_list_ptr); */ + + while (tlist_ptr ) /* Walk linked list of file ids/vals */ + { + if (exoid == tlist_ptr->exo_id ) /* linear search for exodus file id */ + { + if (tlist_ptr == *list_ptr) /* Are we at the head of the list? */ + *list_ptr = (*list_ptr)->next; /* yes, reset ptr to head of list */ + else /* no, remove this record from chain*/ + last_head_list_ptr->next=tlist_ptr->next; + free(tlist_ptr); /* free up memory */ + break; /* Quit if found */ + } + last_head_list_ptr = tlist_ptr; /* save last head pointer */ + tlist_ptr = tlist_ptr->next; /* Loop back if not */ + } + +/* printf("[f] list: %ld *list: %ld **list: %ld\n", + list_ptr,*list_ptr,(*list_ptr)->value, (*list_ptr)->next); */ + +} + +/***************************************************************************** +* +* ex_get_num_props - get number of properties +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* +* environment - UNIX +* +* entry conditions - +* +* exit conditions - +* +* revision history - +* +* +*****************************************************************************/ +int ex_get_num_props (int exoid, int obj_type) +{ + int cntr; + char var_name[MAX_VAR_NAME_LENGTH+1]; + char errmsg[MAX_ERR_LENGTH]; + + cntr = 0; + +/* loop until there is not a property variable defined; the name of */ +/* the variables begin with an increment of 1 ("xx_prop1") so use cntr+1 */ + + while (TRUE) + { + switch (obj_type) + { + case EX_ELEM_BLOCK: + strcpy (var_name, VAR_EB_PROP(cntr+1)); + break; + case EX_NODE_SET: + strcpy (var_name, VAR_NS_PROP(cntr+1)); + break; + case EX_SIDE_SET: + strcpy (var_name, VAR_SS_PROP(cntr+1)); + break; + case EX_ELEM_MAP: + strcpy (var_name, VAR_EM_PROP(cntr+1)); + break; + case EX_NODE_MAP: + strcpy (var_name, VAR_NM_PROP(cntr+1)); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_get_prop_names",errmsg,exerrval); + return(EX_FATAL); + } + + if ((ncvarid (exoid, var_name)) == -1) + { + +/* no variable with this name; return cntr which is now the number of */ +/* properties for this type of entity */ + + return (cntr); + } + cntr++; + } +} +int ex_get_cpu_ws() +{ + return(sizeof(float)); +} + + +/* swap - interchange v[i] and v[j] */ +void ex_swap (int v[], int i, int j) +{ + int temp; + + temp = v[i]; + v[i] = v[j]; + v[j] = temp; +} + +/* + * The following 'indexed qsort' routine is modified from Sedgewicks + * algorithm It selects the pivot based on the median of the left, + * right, and center values to try to avoid degenerate cases ocurring + * when a single value is chosen. It performs a quicksort on + * intervals down to the EX_QSORT_CUTOFF size and then performs a final + * insertion sort on the almost sorted final array. Based on data in + * Sedgewick, the EX_QSORT_CUTOFF value should be between 5 and 20. + * + * See Sedgewick for further details + * Define DEBUG_QSORT at the top of this file and recompile to compile + * in code that verifies that the array is sorted. + */ + +#define EX_QSORT_CUTOFF 12 + +int ex_int_median3(int v[], int iv[], int left, int right) +{ + int center; + center = (left + right) / 2; + + if (v[iv[left]] > v[iv[center]]) + ex_swap(iv, left, center); + if (v[iv[left]] > v[iv[right]]) + ex_swap(iv, left, right); + if (v[iv[center]] > v[iv[right]]) + ex_swap(iv, center, right); + + ex_swap(iv, center, right-1); + return iv[right-1]; +} + +void ex_int_iqsort(int v[], int iv[], int left, int right) +{ + int pivot; + int i, j; + + if (left + EX_QSORT_CUTOFF <= right) { + pivot = ex_int_median3(v, iv, left, right); + i = left; + j = right - 1; + + for ( ; ; ) { + while (v[iv[++i]] < v[pivot]); + while (v[iv[--j]] > v[pivot]); + if (i < j) { + ex_swap(iv, i, j); + } else { + break; + } + } + + ex_swap(iv, i, right-1); + ex_int_iqsort(v, iv, left, i-1); + ex_int_iqsort(v, iv, i+1, right); + } +} + +void ex_int_iisort(int v[], int iv[], int N) +{ + int i,j; + int ndx = 0; + int small; + int tmp; + + small = v[iv[0]]; + for (i = 1; i < N; i++) { + if (v[iv[i]] < small) { + small = v[iv[i]]; + ndx = i; + } + } + /* Put smallest value in slot 0 */ + ex_swap(iv, 0, ndx); + + for (i=1; i 0; len--) { + *lp++ = (nclong) *ip++; + } + } else { + char errmsg[MAX_ERR_LENGTH]; + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for integer to long conversion"); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + } + return longs; +} + +/* + * Convert array of "nclongs" to array of ints + */ +int ltoi (const nclong *longs, /* array of longs */ + int *ints, /* array of ints */ + int len) /* length of array */ +{ + int *ip; + const nclong *lp; + + for (ip = ints, lp = longs; len > 0; len--) + *ip++ = *lp++; + + return (0); +} + +/* + * Determine whether the new large model storage is being used in this + * file, or old method. Basically, the difference is whether the + * coordinates and nodal variables are stored in a blob (xyz + * components together) or as a variable per component per + * nodal_variable. + */ +int ex_large_model(int exoid) +{ + if (exoid < 0) { + /* If exoid not specified, then query is to see if user specified + * the large model via an environment variable + */ + char *option = getenv("EXODUS_LARGE_MODEL"); + if (option != NULL) { + fprintf(stderr, "EXODUSII: Large model size selected via EXODUS_LARGE_MODEL environment variable\n"); + return 1; + } else { + return 0; + } + + } else { + /* See if the ATT_FILESIZE attribute is defined in the file */ + int file_size = 0; + if (nc_get_att_int(exoid, NC_GLOBAL, ATT_FILESIZE, &file_size) != NC_NOERR) { + /* Variable not found; default is 0 */ + file_size = 0; + } + return file_size; + } +} + diff --git a/Utilities/vtkexodus2/exclos.c b/Utilities/vtkexodus2/exclos.c new file mode 100644 index 0000000..9877481 --- /dev/null +++ b/Utilities/vtkexodus2/exclos.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exclos - ex_close +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* +* revision history - +* +* $Id: exclos.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +struct list_item* eb_ctr_list = 0; +extern char *ret_string; /* cf ex_utils.c */ + +/* + * updates and then closes an open EXODUS II file + */ + +int ex_close (int exoid) +{ + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + if (ncsync (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to update file id %d",exoid); + ex_err("ex_close",errmsg,exerrval); + return(EX_FATAL); + } + if (ncclose (exoid) >= 0 ) + { + ex_conv_exit(exoid); + ex_rm_file_item(exoid, &eb_ctr_list); + ex_rm_file_item(exoid, &ns_ctr_list); + ex_rm_file_item(exoid, &ss_ctr_list); + ex_rm_file_item(exoid, &em_ctr_list); + ex_rm_file_item(exoid, &nm_ctr_list); + + rm_stat_ptr (exoid, &eb); + rm_stat_ptr (exoid, &ns); + rm_stat_ptr (exoid, &ss); + rm_stat_ptr (exoid, &em); + rm_stat_ptr (exoid, &nm); + } + else + { + exerrval = ncerr; + sprintf(errmsg, "Error: failed to close file id %d",exoid); + ex_err("ex_close",errmsg,ncerr); + return(EX_FATAL); + } + + return(EX_NOERR); +} diff --git a/Utilities/vtkexodus2/excn2s.c b/Utilities/vtkexodus2/excn2s.c new file mode 100644 index 0000000..975c46e --- /dev/null +++ b/Utilities/vtkexodus2/excn2s.c @@ -0,0 +1,1006 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* excn2s - ex_cvt_nodes_to_sides: convert nodes to sides +* +* author - Sandia National Laboratories +* Vic Yarberry - Original +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int *num_elem_per_set number of element per set +* int *num_nodes_per_set number of nodes per set +* int *side_sets_elem_index index array of elements into elem list +* int *side_sets_node_index index array of nodes +* int *side_sets_elem_list array of elements +* int *side_sets_node_list array of nodes +* +* exit conditions - +* int *side_sets_side_list array of sides/faces +* +* revision history - +* +* $Id: excn2s.c,v 1.4 2005/07/19 23:40:10 andy Exp $ +* +*****************************************************************************/ + +#include +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * This routine is designed to take the results from retrieving the ExodusI + * style concatenated side sets to the Exodus II V 2.0 definition + * uses the element id to get the coordinate node list, element block + * connectivity, element type to + * convert the side set node list to a side/face list. + + Algorithm: + + Read elem_block_ids --> elem_blk_id[array] + + Read element block parameters --> elem_blk_parms[array] + + Determine total number of elements in side set by summing num_elem_per_set + + Build side set element to side set node list index --> ss_elem_node_ndx[array] + + For each element in the side_set_elem_list + { + If Jth element is not in current element block (e.g. J>elem_ctr) + { + get element block parameters (num_elem_in_blk, ...) + + elem_ctr += num_elem_in_blk + + + free old connectity array space + + allocate connectivity array: size=num_elem_in_blk*num_nodes_per_elem + + get connectivity array + } + + If Jth element is in current element block (e.g. J<=elem_ctr) + { + For each node in element (linear search of up to num_nodes_per_elem) + { + If side set element node[1] == element node[i] + { + Case element type = Hex + { + If side set element node[2] == element node[Hex_table[i,1]] + + Jth side = Hex_table[i,2] + + break + } + Case element type = Wedge + { + If side set element node[2] == element node[Wedge_table[i,1]] + + Jth side = Wedge_table[i,2] + + break + } + } + } + } + } + + + + + + + + */ + +int ex_cvt_nodes_to_sides(int exoid, + int *num_elem_per_set, + int *num_nodes_per_set, + int *side_sets_elem_index, + int *side_sets_node_index, + int *side_sets_elem_list, + int *side_sets_node_list, + int *side_sets_side_list) +{ + int i, j, k, m, n; + int num_side_sets, num_elem_blks; + int tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0, ndim; + int *elem_blk_ids, *connect; + int *ss_elem_ndx, *ss_elem_node_ndx, *ss_parm_ndx; + int elem_ctr, node_ctr, elem_num_pos; + int num_elem_in_blk, num_nodes_per_elem, num_node_per_side, num_attr; + int *same_elem_type, el_type; + float fdum; + char *cdum, elem_type[MAX_STR_LENGTH+1]; + + struct elem_blk_parm + { + char elem_type[MAX_STR_LENGTH+1]; + int elem_blk_id; + int num_elem_in_blk; + int num_nodes_per_elem; + int num_nodes_per_side; + int num_attr; + int elem_ctr; + int elem_type_val; + } *elem_blk_parms; + +/* node to side translation tables - + These tables are used to look up the side number based on the + first and second node in the side/face list. The side node order + is found in the original Exodus document, SAND87-2997. The element + node order is found in the ExodusII document, SAND92-2137. These + tables were generated by following the right-hand rule for determining + the outward normal. Note: Only the more complex 3-D shapes require + these tables, the simple shapes are trivial - the first node found + is also the side number. +*/ + + /* 1 2 3 4 node 1 */ + static int shell_table[2][8] = { + {2,4, 3,1, 4,2, 1,3}, /* node 2 */ + {1,2, 1,2, 1,2, 1,2} /* side # */ + }; + + /* 1 2 3 4 node 1 */ + static int shell_edge_table[2][8] = { + {2,4, 3,1, 4,2, 1,3}, /* node 2 */ + {3,6, 4,3, 5,4, 6,5} /* side # */ + }; + + /* 1 2 3 node 1 */ + static int trishell_table[2][6] = { + {2,3, 3,1, 1,2}, /* node 2 */ + {1,2, 1,2, 1,2} /* side # */ + }; + + /* 1 2 3 4 node 1 */ + static int tetra_table[2][12] = { + {2,3,4, 1,3,4, 4,1,2, 1,2,3}, /* node 2 */ + {1,4,3, 4,2,1, 2,3,4, 1,2,3} /* side # */ + }; + +#if 0 + static int wedge_table[2][18] = { + /* 1 2 3 4 5 6 node 1 */ + {2,4,3, 5,1,3, 6,1,2, 1,6,5, 6,2,4, 4,3,5}, /* node 2 */ + {1,3,4, 1,4,2, 2,3,4, 1,3,5, 5,2,1, 5,3,2} /* side # */ + }; +#endif + + static int hex_table[2][24] = { + /* 1 2 3 4 5 6 7 8 node 1 */ + {4,2,5, 1,3,6, 7,4,2, 3,1,8, 6,8,1, 5,2,7, 8,6,3, 7,5,4},/* node 2 */ + {5,1,4, 5,2,1, 2,3,5, 5,4,3, 6,4,1, 1,2,6, 6,2,3, 3,6,4} /* side # */ + }; + + char errmsg[MAX_ERR_LENGTH]; + + (void)side_sets_node_index; + (void)side_sets_elem_index; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + +/* first check if any side sets are specified */ +/* inquire how many side sets have been stored */ + + if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of side sets in file id %d",exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + return(EX_FATAL); + } + + if (num_side_sets == 0) + { + sprintf(errmsg, + "Warning: no side sets defined in file id %d",exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,EX_WARN); + return(EX_WARN); + } + + if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d",exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + return(EX_FATAL); + } + + if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get total number of elements in file id %d",exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + return(EX_FATAL); + } + +/* get the dimensionality of the coordinates; this is necessary to + distinguish between 2d TRIs and 3d TRIs */ + + if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get dimensionality in file id %d",exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + return(EX_FATAL); + } + + /* First count up # of elements in the side sets*/ + for (i=0;i= elem_ctr) { + elem_ctr += num_elem_per_set[++k]; + el_type = elem_blk_parms[j].elem_type_val; + same_elem_type[k] = TRUE; + } + + if (el_type != elem_blk_parms[j].elem_type_val) same_elem_type[k] = FALSE; + + } + +/* Build side set element to node list index and side set element + parameter index. +*/ + node_ctr = 0; + elem_ctr = num_elem_per_set[0]; + for (i=0,k=0;i= elem_ctr) { + /* skip over NULL side sets */ + while (num_elem_per_set[++k] == 0); + elem_ctr += num_elem_per_set[k]; + } + + /* determine number of nodes per side */ + if (((num_nodes_per_set[k] % num_elem_per_set[k]) == 0) && + (same_elem_type[k])) { /* all side set elements are same type */ + node_ctr += num_nodes_per_set[k] /num_elem_per_set[k]; + } else { + node_ctr += elem_blk_parms[j].num_nodes_per_side; + } + } + + ss_elem_node_ndx[i] = node_ctr; /* assign node list index */ + + /* All setup, ready to go ... */ + + elem_ctr=0; + + for (j=0; j < tot_num_ss_elem; j++) + { + + if (side_sets_elem_list[ss_elem_ndx[j]] > elem_ctr) + { + /* release connectivity array space and get next one */ + if (elem_ctr > 0) + free(connect); + + /* Allocate space for the connectivity array for new element block */ + if (!(connect= + malloc(elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk* + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem* + sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for connectivity array for file id %d", + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + + /* get connectivity array */ + if (ex_get_elem_conn( + exoid, + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + connect) == -1) + { + sprintf(errmsg, + "Error: failed to get connectivity array for elem blk %d for file id %d", + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + elem_ctr = elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr; + } +/* For the first node of each side in side set, using a linear search + (of up to num_nodes_per_elem) of the connectivity array, + locate the node position in the element. The first node position + and the second node position are used with a element type specific + table to determine the side. */ + + elem_num = side_sets_elem_list[ss_elem_ndx[j]]-1;/* element number 0-based*/ + /* calculate the relative element number position in it's block*/ + elem_num_pos = elem_num - + (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr - + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk); + /* calculate the beginning of the node list for this element by + using the ss_elem_node_ndx index into the side_sets_node_index + and adding the element number position * number of nodes per elem */ + + num_nodes_per_elem = + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem; + for (n=0; n= 4) + /* 4- or 8-node side (front or back face) */ + side_sets_side_list[ss_elem_ndx[j]] = shell_table[1][2*n]; + else + /* 2- or 3-node side (edge of shell) */ + side_sets_side_list[ss_elem_ndx[j]] = shell_edge_table[1][2*n]; + } + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (shell_table[0][2*n+1]-1)]) + { + if (num_node_per_side >= 4) + /* 4- or 8-node side (front or back face) */ + side_sets_side_list[ss_elem_ndx[j]] = shell_table[1][2*n+1]; + else + /* 2- or 3-node side (edge of shell) */ + side_sets_side_list[ss_elem_ndx[j]]=shell_edge_table[1][2*n+1]; + } + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (shell_table[0][2*n+2]-1)]) + { + if (num_node_per_side >= 4) + /* 4- or 8-node side (front or back face) */ + side_sets_side_list[ss_elem_ndx[j]] = shell_table[1][2*n+2]; + else + /* 2- or 3-node side (edge of shell) */ + side_sets_side_list[ss_elem_ndx[j]]=shell_edge_table[1][2*n+2]; + } + else + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: failed to find SHELL element %d, node %d in connectivity array %d for file id %d", + side_sets_elem_list[ss_elem_ndx[j]], + side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1], + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + break; + + } + case HEX: + { + /* use table to find which node to compare to next */ + + if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (hex_table[0][3*n]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = hex_table[1][3*n]; + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (hex_table[0][3*n+1]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = hex_table[1][3*n+1]; + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (hex_table[0][3*n+2]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = hex_table[1][3*n+2]; + else + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: failed to find HEX element %d, node %d in connectivity array %d for file id %d", + side_sets_elem_list[ss_elem_ndx[j]], + side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1], + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + break; + } + case TETRA: + { + /* use table to find which node to compare to next */ + + if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (tetra_table[0][3*n]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = tetra_table[1][3*n]; + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (tetra_table[0][3*n+1]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = tetra_table[1][3*n+1]; + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (tetra_table[0][3*n+2]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = tetra_table[1][3*n+2]; + else + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: failed to find TETRA element %d, node %d in connectivity array %d for file id %d", + side_sets_elem_list[ss_elem_ndx[j]], + side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1], + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + break; + } + case PYRAMID: + { + /* NOTE: PYRAMID elements in side set node lists are currently not supported */ + exerrval = EX_BADPARAM; + sprintf(errmsg, + "ERROR: unsupported PYRAMID element found in side set node list in file id %d", + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + case WEDGE: + { +#if 1 + /* NOTE: WEDGE elements in side set node lists are currently not supported */ + exerrval = EX_BADPARAM; + sprintf(errmsg, + "ERROR: unsupported WEDGE element found in side set node list in file id %d", + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + +#else + /* use wedge_table to find which node to compare to next */ + +/* This section is commented out because Wedges are no longer supported !!!*/ + + if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (wedge_table[0][3*n]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = wedge_table[1][3*n]; + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (wedge_table[0][3*n+1]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = wedge_table[1][3*n+1]; + else if (side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1] == + connect[num_nodes_per_elem*(elem_num_pos)+ + (wedge_table[0][3*n+2]-1)]) + side_sets_side_list[ss_elem_ndx[j]] = wedge_table[1][3*n+2]; + else + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: failed to find WEDGE element %d, node %d in connectivity array %d for file id %d", + side_sets_elem_list[ss_elem_ndx[j]], + side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]+1], + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + break; +#endif + } + default: + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: %s is an unsupported element type", + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + return(EX_FATAL); + } + } + break; /* done with this element */ + } + } + if (n >= num_nodes_per_elem) /* did we find the node? */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: failed to find element %d, node %d in element block %d for file id %d", + side_sets_elem_list[ss_elem_ndx[j]], + side_sets_node_list[ss_elem_node_ndx[ss_elem_ndx[j]]], + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + return (EX_FATAL); + } + + } + + /* All done: release connectivity array space, element block ids array, + element block parameters array, and side set element index array */ + free(connect); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + + return (EX_NOERR); +} + diff --git a/Utilities/vtkexodus2/excopy.c b/Utilities/vtkexodus2/excopy.c new file mode 100644 index 0000000..c36ab95 --- /dev/null +++ b/Utilities/vtkexodus2/excopy.c @@ -0,0 +1,581 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* excopy - ex_copy +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int in_exoid input exodus file id +* +* exit conditions - +* int out_exoid output exodus file id +* +* revision history - +* +* +*****************************************************************************/ + +#include +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +struct ncdim { /* dimension */ + char name[MAX_STR_LENGTH]; + long size; +}; + +struct ncvar { /* variable */ + char name[MAX_STR_LENGTH]; + nc_type type; + int ndims; + int dims[MAX_VAR_DIMS]; + int natts; +}; + +struct ncatt { /* attribute */ + int var; + char name[MAX_STR_LENGTH]; + nc_type type; + int len; + void *val; +}; + +/* + * copies all information (attributes, dimensions, and variables from + * an opened EXODUS file to another opened EXODUS file + */ + +int ex_copy (int in_exoid, int out_exoid) +{ + int ndims; /* number of dimensions */ + int nvars; /* number of variables */ + int ngatts; /* number of global attributes */ + int recdimid; /* id of unlimited dimension */ + int dimid; /* dimension id */ + int dim_out_id; /* dimension id */ + int varid; /* variable id */ + int var_out_id; /* variable id */ + struct ncvar var; /* variable */ + struct ncatt att; /* attribute */ + int i, number, temp; + long numrec; + long dim_sz; + float fdum; + char *cdum=0; + char dim_nm[MAX_NC_NAME]; + + extern int ncopts; + + exerrval = 0; /* clear error code */ + + /* + * get number of dimensions, number of variables, number of global + * atts, and dimension id of unlimited dimension, if any + */ + + ncinquire(in_exoid, &ndims, &nvars, &ngatts, &recdimid); + ncdiminq (in_exoid, recdimid, (char *) 0, &numrec); + + /* put output file into define mode */ + + ncredef(out_exoid); + + /* copy global attributes */ + + for (i = 0; i < ngatts; i++) { + + ncattname(in_exoid, NC_GLOBAL, i, att.name); + + ncattinq(in_exoid, NC_GLOBAL, att.name, &att.type, &att.len); + + /* if attribute exists in output file, don't overwrite it; compute + * word size, I/O word size etc. are global attributes stored when + * file is created with ex_create; we don't want to overwrite those + */ + + if (ncattinq (out_exoid, NC_GLOBAL, att.name, &att.type, &att.len) == -1){ + + /* attribute doesn't exist in new file so OK to create it */ + ncattcopy (in_exoid,NC_GLOBAL,att.name,out_exoid,NC_GLOBAL); + } + } + + /* copy dimensions */ + + /* Get the dimension sizes and names */ + + for(dimid = 0; dimid < ndims; dimid++){ + + ncdiminq(in_exoid,dimid,dim_nm,&dim_sz); + + /* See if the dimension has already been defined */ + + temp = ncopts; + ncopts = 0; + dim_out_id = ncdimid(out_exoid,dim_nm); + ncopts = temp; + + /* If the dimension isn't one we specifically don't want + * to copy (ie, number of QA or INFO records) and it + * hasn't been defined, copy it */ + + if ( ( strcmp(dim_nm,DIM_NUM_QA) != 0) && + ( strcmp(dim_nm,DIM_NUM_INFO) != 0) && + ( strcmp(dim_nm,DIM_NUM_NOD_VAR) != 0) && + ( strcmp(dim_nm,DIM_NUM_ELE_VAR) != 0) && + ( strcmp(dim_nm,DIM_NUM_GLO_VAR) != 0) ) { + + if(dim_out_id == -1){ + if(dimid != recdimid){ + dim_out_id=ncdimdef(out_exoid,dim_nm,dim_sz); + }else{ + dim_out_id=ncdimdef(out_exoid,dim_nm,NC_UNLIMITED); + } /* end else */ + } /* end if */ + } /* end if */ + } /* end loop over dim */ + + /* copy variable definitions and variable attributes */ + + for (varid = 0; varid < nvars; varid++) { + + ncvarinq(in_exoid, varid, var.name, &var.type, &var.ndims, + var.dims, &var.natts); + + /* we don't want to copy some variables because there is not a + * simple way to add to them; + * QA records, info records and all results variables (nodal + * element, and global results) are examples + */ + + if ( ( strcmp(var.name,VAR_QA_TITLE) != 0) && + ( strcmp(var.name,VAR_INFO) != 0) && + ( strcmp(var.name,VAR_ELEM_TAB) != 0) && + ( strcmp(var.name,VAR_NAME_GLO_VAR) != 0) && + ( strcmp(var.name,VAR_GLO_VAR) != 0) && + ( strcmp(var.name,VAR_NAME_NOD_VAR) != 0) && + ( strcmp(var.name,VAR_NOD_VAR) != 0) && + ( strcmp(var.name,VAR_NAME_ELE_VAR) != 0) && + ( strncmp(var.name,"vals_nod_var", 12) != 0) && + ( strncmp(var.name,"vals_elem_var",13) != 0) ) { + + var_out_id = cpy_var_def (in_exoid, out_exoid, recdimid, var.name); + + /* copy the variable's attributes */ + (void) cpy_att (in_exoid, out_exoid, varid, var_out_id); + + } + } + + /* take the output file out of define mode */ + ncendef (out_exoid); + + /* output variable data */ + + for (varid = 0; varid < nvars; varid++) { + ncvarinq(in_exoid, varid, var.name, &var.type, &var.ndims, + var.dims, &var.natts); + + /* we don't want to copy some variable values; + * QA records and info records shouldn't be copied because there + * isn't an easy way to add to them; + * the time value array ("time_whole") and any results variables + * (nodal, elemental, or global) shouldn't be copied + */ + + if ( ( strcmp(var.name,VAR_QA_TITLE) != 0) && + ( strcmp(var.name,VAR_INFO) != 0) && + ( strcmp(var.name,VAR_ELEM_TAB) != 0) && + ( strcmp(var.name,VAR_NAME_GLO_VAR) != 0) && + ( strcmp(var.name,VAR_GLO_VAR) != 0) && + ( strcmp(var.name,VAR_NAME_NOD_VAR) != 0) && + ( strcmp(var.name,VAR_NOD_VAR) != 0) && + ( strcmp(var.name,VAR_NAME_ELE_VAR) != 0) && + ( strncmp(var.name,"vals_nod_var", 12) != 0) && + ( strncmp(var.name,"vals_elem_var",13) != 0) && + ( strcmp(var.name,VAR_WHOLE_TIME) != 0) ) { + + (void) cpy_var_val (in_exoid, out_exoid, var.name); + } + } + + /* ensure internal data structures are updated */ + + /* if number of element blocks > 0 */ + + ex_inquire (out_exoid, EX_INQ_ELEM_BLK, &number, &fdum, cdum); + + if (number > 0) { + + for (i=0; i 0 */ + + ex_inquire (out_exoid, EX_INQ_NODE_SETS, &number, &fdum, cdum); + + if (number > 0) { + + for (i=0; i 0 */ + + ex_inquire (out_exoid, EX_INQ_SIDE_SETS, &number, &fdum, cdum); + + if (number > 0) { + + for (i=0; i 0 */ + + ex_inquire (out_exoid, EX_INQ_ELEM_MAP, &number, &fdum, cdum); + + if (number > 0) { + + for (i=0; i 0 */ + + ex_inquire (out_exoid, EX_INQ_NODE_MAP, &number, &fdum, cdum); + + if (number > 0) { + + for (i=0; i +#include +#include +#include "netcdf.h" +#include "exodusII.h" + +int exerrval = 0; /* clear initial global error code value */ + +static char last_pname[MAX_ERR_LENGTH]; +static char last_errmsg[MAX_ERR_LENGTH]; +static int last_errcode; + +void ex_err( const char *pname, /* procedure name */ + const char *err_string, /* error message string */ + int errcode) /* error code */ +{ + if (errcode == 0) /* zero is no error, ignore and return */ + return; + + else if (errcode == EX_PRTLASTMSG) + { + fprintf(stderr, "[%s] %s\n",last_pname,last_errmsg); + fprintf(stderr, " exerrval = %d\n",last_errcode); + return; + } + + else if (exoptval & EX_VERBOSE) /* check see if we really want to hear this */ + { + fprintf(stderr, "[%s] %s\n",pname,err_string); + if (exoptval & EX_VERBOSE) + fprintf(stderr, " exerrval = %d\n",errcode); + switch (errcode) + { + case NC_ESTS: + fprintf (stderr," In FORTRAN interface, string too small\n"); + break; + case NC_ENTOOL: + fprintf (stderr," length of name exceeds MAX_NC_NAME\n"); + break; + case EX_MSG: + break; + } + } + /* save the error message for replays */ + strcpy(last_errmsg, err_string); + strcpy(last_pname, pname); + last_errcode = errcode; + + fflush(stderr); + + /* with netCDF 3.4, (fatal) system error codes are > 0; + so all EXODUS fatal error codes are > 0 */ + if ((errcode > 0) && (exoptval & EX_ABORT)) + exit (errcode); +} diff --git a/Utilities/vtkexodus2/exgatm.c b/Utilities/vtkexodus2/exgatm.c new file mode 100644 index 0000000..17930b0 --- /dev/null +++ b/Utilities/vtkexodus2/exgatm.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgatm - get all time values +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* float* time_values array of simulation time values +* +* revision history - +* +* $Id: exgatm.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads all the time values for history or whole time steps + */ + +int ex_get_all_times (int exoid, + void *time_values) + +{ + int dimid, varid; + long start[1], count[1]; + char var_name[MAX_VAR_NAME_LENGTH+1]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; + +/* inquire previously defined dimensions */ + + strcpy (var_name, VAR_WHOLE_TIME); + if (((dimid = ncdimid (exoid, DIM_TIME))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate whole time step dimension in file id %d", + exoid); + ex_err("ex_get_all_times",errmsg,exerrval); + return(EX_FATAL); + } + +/* inquire previously defined variable */ + + if ((varid = ncvarid (exoid, var_name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to locate time variable %s in file id %d", + var_name,exoid); + ex_err("ex_get_all_times",errmsg,exerrval); + return(EX_FATAL); + } + + +/*read time values */ + + start[0] = 0; + + if (ncdiminq (exoid, dimid, (char *) 0, count) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of %s time values in file id %d", + var_name,exoid); + ex_err("ex_get_all_times",errmsg,exerrval); + return(EX_FATAL); + } + + if (ncvarget (exoid, varid, start, count, + ex_conv_array(exoid,RTN_ADDRESS,time_values,(int)count[0])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get %s time values from file id %d", + var_name,exoid); + ex_err("ex_get_all_times",errmsg,exerrval); + return(EX_FATAL); + } + + ex_conv_array( exoid, READ_CONVERT, time_values, count[0] ); + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgcns.c b/Utilities/vtkexodus2/exgcns.c new file mode 100644 index 0000000..ecd4446 --- /dev/null +++ b/Utilities/vtkexodus2/exgcns.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgcns - read concatenated side sets +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* int* node_set_ids array of node set IDs +* int* num_nodes_per_set number of nodes for each set +* int* num_df_per_set number of dist factors for each set +* int* node_sets_index array of indices into node_set_node_list +* int* df_sets_index array of indices into node_set_dist_fact +* int* node_sets_node_list array of nodes for all sets +* float* node_sets_dist_fact array of distribution factors for sets +* +* revision history - +* +* $Id: exgcns.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the node set ID's, node set count array, node set pointers array, + * node set node list, and node set distribution factors for all of the + * node sets + */ + +int ex_get_concat_node_sets (int exoid, + int *node_set_ids, + int *num_nodes_per_set, + int *num_df_per_set, + int *node_sets_node_index, + int *node_sets_df_index, + int *node_sets_node_list, + void *node_sets_dist_fact) +{ + int i, num_node_sets, node_index_ctr, df_index_ctr; + float fdum; + char *cdum; + float *flt_dist_fact; + double *dbl_dist_fact; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + +/* first check if any node sets are specified */ + + if (ncdimid (exoid, DIM_NUM_NS) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: failed to locate number of node sets in file id %d", + exoid); + ex_err("ex_get_concat_node_sets",errmsg,exerrval); + return (EX_WARN); /* no node sets were defined */ + } + +/* inquire how many node sets have been stored */ + + if ((ex_inquire(exoid, EX_INQ_NODE_SETS, &num_node_sets, &fdum, cdum)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of node sets in file id %d", + exoid); + ex_err("ex_get_concat_node_sets",errmsg,exerrval); + return(EX_FATAL); + } + + if ((ex_get_node_set_ids (exoid, node_set_ids)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node sets ids in file id %d",exoid); + ex_err("ex_get_concat_node_sets",errmsg,exerrval); + return(EX_FATAL); + } + + node_index_ctr = 0; + df_index_ctr = 0; + + for (i=0; i 0) + { + if (ex_get_node_set(exoid, node_set_ids[i], + &(node_sets_node_list[node_index_ctr])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node set %d in file id %d", + node_set_ids[i], exoid); + ex_err("ex_get_concat_node_sets",errmsg,exerrval); + return(EX_FATAL); + } + + if (ex_comp_ws(exoid) == sizeof(float) ) /* 4-byte float word */ + { + + /* get distribution factors for this set */ + flt_dist_fact = node_sets_dist_fact; + if (num_df_per_set[i] > 0) /* only get df if they exist */ + { + if (ex_get_node_set_dist_fact(exoid, node_set_ids[i], + &(flt_dist_fact[df_index_ctr])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node set %d dist factors in file id %d", + node_set_ids[i], exoid); + ex_err("ex_get_concat_node_sets",errmsg,exerrval); + return(EX_FATAL); + } + } + } + else if (ex_comp_ws(exoid) == sizeof(double) ) /* 8-byte float word */ + { + + /* get distribution factors for this set */ + dbl_dist_fact = node_sets_dist_fact; + if (num_df_per_set[i] > 0) /* only get df if they exist */ + { + if (ex_get_node_set_dist_fact(exoid, node_set_ids[i], + &(dbl_dist_fact[df_index_ctr])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node set %d dist factors in file id %d", + node_set_ids[i], exoid); + ex_err("ex_get_concat_node_sets",errmsg,exerrval); + return(EX_FATAL); + } + } + } + else + { + /* unknown floating point word size */ + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: unsupported floating point word size %d for file id %d", + ex_comp_ws(exoid), exoid); + ex_err("ex_get_concat_node_sets", errmsg, exerrval); + return (EX_FATAL); + } + } + + /* update index arrays */ + + if (i < num_node_sets) + { + node_sets_node_index[i] = node_index_ctr; + node_index_ctr += num_nodes_per_set[i]; /* keep running count */ + + if (num_df_per_set[i] > 0) /* only get df if they exist */ + { + node_sets_df_index[i] = df_index_ctr; + df_index_ctr += num_df_per_set[i]; /* keep running count */ + } + else + { + node_sets_df_index[i] = -1; /* signal non-existence of df */ + } + } + } + + return(EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgcon.c b/Utilities/vtkexodus2/exgcon.c new file mode 100644 index 0000000..a9f2d72 --- /dev/null +++ b/Utilities/vtkexodus2/exgcon.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgcon - ex_get_coord_names +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* char* coord_names[] ptr array of coord names +* +* revision history - +* +* $Id: exgcon.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the names of the coordinate arrays from the database + */ + +int ex_get_coord_names (int exoid, + char **coord_names) +{ + int i, j, ndimdim, varid; + long num_dim, start[2]; + char *ptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; + +/* inquire previously defined dimensions and variables */ + + if ((ndimdim = ncdimid (exoid, DIM_NUM_DIM)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of dimensions in file id %d", + exoid); + ex_err("ex_get_coord_names",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, ndimdim, (char *) 0, &num_dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of dimensions in file id %d", + exoid); + ex_err("ex_get_coord_names",errmsg,exerrval); + return (EX_FATAL); + } + + if ((varid = ncvarid (exoid, VAR_NAME_COOR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: failed to locate coordinate names in file id %d", + exoid); + ex_err("ex_get_coord_names",errmsg,exerrval); + return (EX_WARN); + } + + +/* read the coordinate names */ + + for (i=0; i coord_names[i]) { + /* get rid of trailing blanks */ + while (*(--ptr) == ' '); + } + *(++ptr) = '\0'; + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgcor.c b/Utilities/vtkexodus2/exgcor.c new file mode 100644 index 0000000..63c0c58 --- /dev/null +++ b/Utilities/vtkexodus2/exgcor.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgcor - ex_get_coord +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* float* x_coord X coord array +* float* y_coord y coord array +* float* z_coord z coord array +* +* revision history - +* +* $Id: exgcor.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the coordinates of the nodes + * Only fills in the 'non-null' arrays. + */ + +int ex_get_coord (int exoid, + void *x_coor, + void *y_coor, + void *z_coor) +{ + int coordid; + int coordidx, coordidy, coordidz; + + int numnoddim, ndimdim, i; + long num_nod, num_dim, start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; + + /* inquire id's of previously defined dimensions */ + + if ((numnoddim = ncdimid (exoid, DIM_NUM_NODES)) == -1) + { + /* If not found, then this file is storing 0 nodes. + Return immediately */ + return (EX_NOERR); + } + + if (ncdiminq (exoid, numnoddim, (char *) 0, &num_nod) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in file id %d", + exoid); + ex_err("ex_get_coord",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((ndimdim = ncdimid (exoid, DIM_NUM_DIM)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of dimensions in file id %d", + exoid); + ex_err("ex_get_coord",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, ndimdim, (char *) 0, &num_dim) == -1) + { + sprintf(errmsg, + "Error: failed to get number of dimensions in file id %d", + exoid); + ex_err("ex_get_coord",errmsg,exerrval); + return (EX_FATAL); + } + + /* read in the coordinates */ + if (ex_large_model(exoid) == 0) { + if ((coordid = ncvarid (exoid, VAR_COORD)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate nodal coordinates in file id %d", exoid); + ex_err("ex_get_coord",errmsg,exerrval); + return (EX_FATAL); + } + + for (i=0; i 1) { + if ((coordidy = ncvarid (exoid, VAR_COORD_Y)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate y nodal coordinates in file id %d", exoid); + ex_err("ex_get_coord",errmsg,exerrval); + return (EX_FATAL); + } + } else { + coordidy = 0; + } + + if (num_dim > 2) { + if ((coordidz = ncvarid (exoid, VAR_COORD_Z)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate z nodal coordinates in file id %d", exoid); + ex_err("ex_get_coord",errmsg,exerrval); + return (EX_FATAL); + } + } else { + coordidz = 0; + } + + /* write out the coordinates */ + for (i=0; i 0) /* only get df if they exist */ + { + if (ex_get_side_set_dist_fact(exoid, side_set_ids[i], + &(flt_dist_fact[side_sets_dist_index[i]])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node set %d dist factors in file id %d", + side_set_ids[i], exoid); + ex_err("ex_get_concat_side_sets",errmsg,exerrval); + return(EX_FATAL); + } + } else { /* fill distribution factor array with 1's */ + } + } + else if (ex_comp_ws(exoid) == sizeof(double)) + { + if (ex_get_side_set(exoid, side_set_ids[i], + &(side_sets_elem_list[side_sets_elem_index[i]]), + &(side_sets_side_list[side_sets_elem_index[i]])) == -1) + return(EX_FATAL); /* error will be reported by subroutine */ + + /* get distribution factors for this set */ + dbl_dist_fact = side_sets_dist_fact; + if (num_dist_per_set[i] > 0) /* only get df if they exist */ + { + if (ex_get_side_set_dist_fact(exoid, side_set_ids[i], + &(dbl_dist_fact[side_sets_dist_index[i]])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node set %d dist factors in file id %d", + side_set_ids[i], exoid); + ex_err("ex_get_concat_side_sets",errmsg,exerrval); + return(EX_FATAL); + } + } else { /* fill distribution factor array with 1's */ + } + } + } + + return(EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgeat.c b/Utilities/vtkexodus2/exgeat.c new file mode 100644 index 0000000..125e89d --- /dev/null +++ b/Utilities/vtkexodus2/exgeat.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgeat - ex_get_elem_attr +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int elem_blk_id element block id +* +* exit conditions - +* float* attrib array of attributes +* +* revision history - +* +* $Id: exgeat.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the attributes for an element block + */ + +int ex_get_elem_attr (int exoid, + int elem_blk_id, + void *attrib) + +{ + int numelbdim, numattrdim, attrid, elem_blk_id_ndx; + long num_elem_this_blk, num_attr, start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* Determine index of elem_blk_id in VAR_ID_EL_BLK array */ + elem_blk_id_ndx = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no attributes found for NULL block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_attr",errmsg,EX_MSG); + return (EX_WARN); /* no attributes for this element block */ + } + else + { + sprintf(errmsg, + "Warning: failed to locate element block id %d in %s array in file id %d", + elem_blk_id,VAR_ID_EL_BLK, exoid); + ex_err("ex_get_elem_attr",errmsg,exerrval); + return (EX_WARN); + } + } + + +/* inquire id's of previously defined dimensions */ + + if ((numelbdim = ncdimid (exoid, DIM_NUM_EL_IN_BLK(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of elements for block %d in file id %d", + elem_blk_id, exoid); + ex_err("ex_get_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, numelbdim, (char *) 0, &num_elem_this_blk) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((numattrdim = ncdimid(exoid, DIM_NUM_ATT_IN_BLK(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no attributes found for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_attr",errmsg,EX_MSG); + return (EX_WARN); /* no attributes for this element block */ + } + + if (ncdiminq (exoid, numattrdim, (char *) 0, &num_attr) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of attributes for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + if ((attrid = ncvarid (exoid, VAR_ATTRIB(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate attributes for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the attributes */ + + start[0] = 0; + start[1] = 0; + + count[0] = num_elem_this_blk; + count[1] = num_attr; + + if (ncvarget (exoid, attrid, start, count, + ex_conv_array(exoid,RTN_ADDRESS,attrib, + (int)num_attr*num_elem_this_blk)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get attributes for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + + ex_conv_array( exoid, READ_CONVERT, attrib, num_attr*num_elem_this_blk ); + + return(EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgebi.c b/Utilities/vtkexodus2/exgebi.c new file mode 100644 index 0000000..c03f22e --- /dev/null +++ b/Utilities/vtkexodus2/exgebi.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgebi - ex_get_elem_blk_ids +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* int* elem_blk_ids array of element block ids +* +* revision history - +* +* $Id: exgebi.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the element block ids from the database + */ + +int ex_get_elem_blk_ids (int exoid, + int *ids) +{ + int dimid, varid, iresult; + long num_elem_blocks, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions and variables */ + + if ((dimid = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate dimension DIM_NUM_EL_BLK in file id %d", + exoid); + ex_err("ex_get_elem_blk_ids",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem_blocks) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to return number of element blocks in file id %d", + exoid); + ex_err("ex_get_get_elem_blk_ids",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((varid = ncvarid (exoid, VAR_ID_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element block ids variable in file id %d", + exoid); + ex_err("ex_get_get_elem_blk_ids",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the element block ids */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_elem_blocks; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, varid, start, count, ids); + } else { + if (!(longs = malloc(num_elem_blocks * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element block ids for file id %d", + exoid); + ex_err("ex_get_elem_blk_ids",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, varid, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to return element block ids in file id %d", + exoid); + ex_err("ex_get_get_elem_blk_ids",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, ids, num_elem_blocks); + free (longs); + } + + return(EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgelb.c b/Utilities/vtkexodus2/exgelb.c new file mode 100644 index 0000000..9227d7a --- /dev/null +++ b/Utilities/vtkexodus2/exgelb.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgelb - read element block parameters +* +* author - Victor R. Yarberry, Sandia National Laboratories +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int idexo exodus file id +* int elem_blk_id element block id +* +* exit conditions - +* char* elem_type element type name +* int* num_elem_this_blk number of elements in this element block +* int* num_nodes_per_elem number of nodes per element block +* int* num_attr number of attributes +* +* revision history - +* +* $Id: exgelb.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*/ + +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the parameters used to describe an element block + */ + +int ex_get_elem_block (int exoid, + int elem_blk_id, + char *elem_type, + int *num_elem_this_blk, + int *num_nodes_per_elem, + int *num_attr) + +{ + int dimid, connid, len, elem_blk_id_ndx; + long lnum_elem_this_blk, lnum_nodes_per_elem, lnum_attr; + char *ptr; + char errmsg[MAX_ERR_LENGTH]; + nc_type dummy; + + exerrval = 0; + +/* First, locate index of element block id in VAR_ID_EL_BLK array */ + + elem_blk_id_ndx = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) /* NULL element block? */ + { + strcpy(elem_type, "NULL"); /* NULL element type name */ + *num_elem_this_blk = 0; /* no elements */ + *num_nodes_per_elem = 0; /* no nodes */ + *num_attr = 0; /* no attributes */ + return (EX_NOERR); + } + else + { + sprintf(errmsg, + "Error: failed to locate element block id %d in %s array in file id %d", + elem_blk_id,VAR_ID_EL_BLK,exoid); + ex_err("ex_get_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire values of some dimensions */ + + if ((dimid = ncdimid (exoid, DIM_NUM_EL_IN_BLK(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of elements in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_elem_this_blk) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in block %d in file id %d", + elem_blk_id, exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + *num_elem_this_blk = lnum_elem_this_blk; + if ((dimid = ncdimid (exoid, DIM_NUM_NOD_PER_EL(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes/element in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_nodes_per_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes/element in block %d in file id %d", + elem_blk_id, exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + *num_nodes_per_elem = lnum_nodes_per_elem; + + if ((dimid = ncdimid (exoid, DIM_NUM_ATT_IN_BLK(elem_blk_id_ndx))) == -1) + *num_attr = 0; /* dimension is undefined */ + else + { + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_attr) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of attributes in block %d in file id %d", + elem_blk_id, exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + *num_attr = lnum_attr; + } + + /* look up connectivity array for this element block id */ + + if ((connid = ncvarid (exoid, VAR_CONN(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, +"Error: failed to locate connectivity array for element block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + + if (ncattinq (exoid, connid, ATT_NAME_ELB, &dummy, &len) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get element block %d type in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + + if (len > (MAX_STR_LENGTH+1)) + { + len = MAX_STR_LENGTH; + sprintf (errmsg, + "Warning: element block %d type will be truncated to %d chars", + elem_blk_id,len); + ex_err("ex_get_elem_block",errmsg,EX_MSG); + } +/* get the element type name */ + + if (ncattget (exoid, connid, ATT_NAME_ELB, elem_type) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to get element block %d type in file id %d", + elem_blk_id, exoid); + ex_err("ex_get_elem_block",errmsg, exerrval); + return(EX_FATAL); + } + +/* get rid of trailing blanks */ + ptr = elem_type; + /* fprintf(stderr,"[exgelb] %s, len: %d\n",ptr,len); */ + while (ptr < elem_type + len && *ptr != ' ') + { + ptr++; + } + *(ptr) = '\0'; + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgelc.c b/Utilities/vtkexodus2/exgelc.c new file mode 100644 index 0000000..5c77469 --- /dev/null +++ b/Utilities/vtkexodus2/exgelc.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgelc - exodusII read element block connectivity +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* environment - UNIX +* +* entry conditions - +* expelb must be called first to establish element block parameters. +* input parameters: +* int exoid exodus file id +* int elem_blk_id element block id +* +* exit conditions - +* int* connect connectivity array +* +* revision history - +* +* $Id: exgelc.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +*/ +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the connectivity array for an element block + */ + +int ex_get_elem_conn (int exoid, + int elem_blk_id, + int *connect) +{ + int numelbdim, nelnoddim, connid, elem_blk_id_ndx, iresult; + long num_elem_this_blk, num_nod_per_elem, start[2], count[2]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* Locate index of element block id in VAR_ID_EL_BLK array */ + + elem_blk_id_ndx = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no connectivity array for NULL block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_conn",errmsg,EX_MSG); + return (EX_WARN); /* no connectivity array for this element block */ + } + else + { + sprintf(errmsg, + "Error: failed to locate element block id %d in %s array in file id %d", + elem_blk_id,VAR_ID_EL_BLK,exoid); + ex_err("ex_get_elem_conn",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions */ + + if ((numelbdim = ncdimid (exoid, DIM_NUM_EL_IN_BLK(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of elements in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_conn",errmsg, exerrval); + return(EX_FATAL); + } + + if (ncdiminq (exoid, numelbdim, (char *) 0, &num_elem_this_blk) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_conn",errmsg,exerrval); + return(EX_FATAL); + } + + + if ((nelnoddim = ncdimid (exoid, DIM_NUM_NOD_PER_EL(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes/elem for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_conn",errmsg,exerrval); + return(EX_FATAL); + } + + if (ncdiminq (exoid, nelnoddim, (char *) 0, &num_nod_per_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes/elem for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_conn",errmsg, exerrval); + return(EX_FATAL); + } + + + if ((connid = ncvarid (exoid, VAR_CONN(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate connectivity array for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_conn",errmsg, exerrval); + return(EX_FATAL); + } + + +/* read in the connectivity array */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + start[1] = 0; + + count[0] = num_elem_this_blk; + count[1] = num_nod_per_elem; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, connid, start, count, connect); + } else { + if (!(longs = malloc (num_elem_this_blk*num_nod_per_elem * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element connectivity array for file id %d", + exoid); + ex_err("ex_get_elem_conn",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, connid, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get connectivity array for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_get_elem_conn",errmsg, exerrval); + return(EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, connect, num_elem_this_blk*num_nod_per_elem); + free (longs); + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgem.c b/Utilities/vtkexodus2/exgem.c new file mode 100644 index 0000000..6695348 --- /dev/null +++ b/Utilities/vtkexodus2/exgem.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgem - ex_get_elem_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int map_id element map id +* +* exit conditions - +* int* elem_map element map +* +* revision history - +* +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the element map with specified ID + */ + +int ex_get_elem_map (int exoid, + int map_id, + int *elem_map) +{ + int dimid, var_id, id_ndx, iresult; + long num_elem, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* See if file contains any elements...*/ + if ((dimid = ncdimid (exoid, DIM_NUM_ELEM)) == -1) + { + return (EX_NOERR); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in file id %d", exoid); + ex_err("ex_get_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* first check if any element maps have been defined */ + + if ((dimid = ncdimid (exoid, DIM_NUM_EM)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no element maps defined in file id %d", + exoid); + ex_err("ex_get_elem_map",errmsg,exerrval); + return (EX_WARN); + } + +/* Lookup index of element map id property array */ + + id_ndx = ex_id_lkup(exoid,VAR_EM_PROP(1),map_id); + if (exerrval != 0) + { + + sprintf(errmsg, + "Error: failed to locate element map id %d in %s in file id %d", + map_id,VAR_EM_PROP(1),exoid); + ex_err("ex_get_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* inquire id's of previously defined dimensions and variables */ + + if ((var_id = ncvarid (exoid, VAR_ELEM_MAP(id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element map %d in file id %d", + map_id,exoid); + ex_err("ex_get_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the element map */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_elem; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, var_id, start, count, elem_map); + } else { + if (!(longs = malloc(num_elem * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element map for file id %d", + exoid); + ex_err("ex_get_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, var_id, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get element map in file id %d", + exoid); + ex_err("ex_get_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, elem_map, num_elem); + free (longs); + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgenm.c b/Utilities/vtkexodus2/exgenm.c new file mode 100644 index 0000000..f310d2b --- /dev/null +++ b/Utilities/vtkexodus2/exgenm.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgenm - ex_get_elem_num_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* int* elem_map element number map array +* +* revision history - +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the element numbering map from the database; allows element numbers + * to be noncontiguous + */ + +int ex_get_elem_num_map (int exoid, + int *elem_map) +{ + int numelemdim, mapid, i, iresult; + long num_elem, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions and variables */ + + /* See if file contains any elements...*/ + if ((numelemdim = ncdimid (exoid, DIM_NUM_ELEM)) == -1) + { + return(EX_NOERR); + } + + if (ncdiminq (exoid, numelemdim, (char *) 0, &num_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in file id %d", + exoid); + ex_err("ex_get_elem_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((mapid = ncvarid (exoid, VAR_ELEM_NUM_MAP)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, +"Warning: elem numbering map not stored in file id %d; returning default map", + exoid); + ex_err("ex_get_elem_num_map",errmsg,exerrval); + +/* generate default map of 1..n, where n is num_elem */ + for (i=0; i +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the EXODUS II element variable truth table from the database + */ + +int ex_get_elem_varid (int exoid, + int *varid) +{ + int dimid, evarid, i, j; + long num_elem_blk, num_elem_var; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* inquire id's of previously defined dimensions */ + if ((dimid = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element blocks in file id %d", + exoid); + ex_err("ex_get_elem_varid",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem_blk) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_get_elem_varid",errmsg,exerrval); + return (EX_FATAL); + } + + if ((dimid = ncdimid (exoid, DIM_NUM_ELE_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no element variables stored in file id %d", + exoid); + ex_err("ex_get_elem_varid",errmsg,exerrval); + return (EX_WARN); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem_var) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element variables in file id %d", + exoid); + ex_err("ex_get_elem_varid",errmsg,exerrval); + return (EX_FATAL); + } + + + /* since truth table isn't stored in the data file, derive it dynamically */ + for (j=0; j +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the values of an element variable for a single element through a + * specified number of time steps in the database; assume the first element + * variable index, element number, and time step are 1 + */ + +int ex_get_elem_var_time (int exoid, + int elem_var_index, + int elem_number, + int beg_time_step, + int end_time_step, + void *elem_var_vals) +{ + int i, dimid, varid, numel = 0, offset; + nclong *elem_blk_ids, *stat_vals; + long num_elem_blocks, num_el_this_blk = 0, start[2], count[2]; + float fdum; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + + /* assume element number is 1-based (the first element number is 1); + * adjust so it is 0-based + */ + elem_number--; + + /* find what element block the element is in */ + + /* first, find out how many element blocks there are */ + + if ((dimid = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element blocks in file id %d", + exoid); + ex_err("ex_get_elem_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem_blocks) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_get_elem_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + /* get the array of element block ids */ + /* don't think we need this anymore since the netcdf variable names + associated with element blocks don't contain the element block ids */ + + if (!(elem_blk_ids = malloc(num_elem_blocks*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element block ids for file id %d", + exoid); + ex_err("ex_get_elem_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((varid = ncvarid (exoid, VAR_ID_EL_BLK)) == -1) + { + exerrval = ncerr; + free(elem_blk_ids); + sprintf(errmsg, + "Error: failed to locate element block ids in file id %d", exoid); + ex_err("ex_get_elem_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + + start[0] = 0; + count[0] = num_elem_blocks; + if (ncvarget (exoid, varid, start, count, elem_blk_ids) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get element block ids from file id %d", exoid); + ex_err("ex_get_elem_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + /* allocate space for stat array */ + if (!(stat_vals = malloc((int)num_elem_blocks*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + free (elem_blk_ids); + sprintf(errmsg, + "Error: failed to allocate memory for element block status array for file id %d", + exoid); + ex_err("ex_get_elem_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + /* get variable id of status array */ + if ((varid = ncvarid (exoid, VAR_STAT_EL_BLK)) != -1) + { + /* if status array exists, use it, otherwise assume, object exists + to be backward compatible */ + + start[0] = 0; + start[1] = 0; + count[0] = num_elem_blocks; + count[1] = 0; + + if (ncvarget (exoid, varid, start, count, (void *)stat_vals) == -1) + { + exerrval = ncerr; + free (elem_blk_ids); + free(stat_vals); + sprintf(errmsg, + "Error: failed to get element block status array from file id %d", + exoid); + ex_err("ex_get_elem_var_time",errmsg,exerrval); + return (EX_FATAL); + } + } + else /* default: status is true */ + for(i=0;i +#include "exodusII.h" +#include "exodusII_int.h" + +/* -------------------- local defines --------------------------- */ +#define PROCNAME "ex_get_coordinate_frames" +/* -------------------- end of local defines -------------------- */ +int ex_get_coordinate_frames( int exoid, int *nframes, int *cf_ids, + void* pt_coordinates, char* tags) +{ + int dimid; /* ID of the dimension of # frames */ + char errmsg[MAX_ERR_LENGTH]; + int exerrval; /* returned error value */ + int varids; /* variable id for the frame ids */ + long int start=0; /* start value for varputs */ + long int count; /* number vars to put in varput */ + long int count9; /* ditto, but for coordinates */ + void* pt_c=0; /* pointer to converted array */ + + /* get the dimensions */ + assert( nframes !=NULL ); + dimid = ncdimid(exoid,NUM_CFRAMES); + if ( dimid<0 ){ + *nframes=0; + return EX_NOERR; + } + ncdiminq(exoid,dimid,(char*)0,&count); + *nframes=(int)count; + count9=count*9; + + if ( count==0 ) + return (EX_NOERR); + + if ( cf_ids ) + if ( (varids=ncvarid(exoid,FRAME_IDS))==-1 || + ncvarget(exoid,varids,&start,&count,cf_ids)== -1 ) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to read number coordinate ids from file id %d", + exoid); + ex_err((char*)PROCNAME,errmsg,exerrval); + return (EX_FATAL); + } + + if ( tags ) + if ( (varids=ncvarid(exoid,FRAME_TAGS))==-1 || + ncvarget(exoid,varids,&start,&count,tags)== -1 ) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to read number coordinate tags from file id %d", + exoid); + ex_err((char*)PROCNAME,errmsg,exerrval); + return (EX_FATAL); + } + + if (pt_coordinates ){ + pt_c=ex_conv_array(exoid,RTN_ADDRESS,pt_coordinates,count9); + assert(pt_c!=0); + if ( (varids=ncvarid(exoid,FRAME_COORDS))==-1 || + ncvarget(exoid,varids,&start,&count9,pt_c)== -1 ) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to read number coordinate tags from file id %d", + exoid); + ex_err((char*)PROCNAME,errmsg,exerrval); + return (EX_FATAL); + } + else { + pt_c=ex_conv_array( exoid, READ_CONVERT,pt_coordinates,count9); + assert(pt_c==0); + } + } + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exggv.c b/Utilities/vtkexodus2/exggv.c new file mode 100644 index 0000000..4e58349 --- /dev/null +++ b/Utilities/vtkexodus2/exggv.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exggv - ex_get_glob_vars +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step time step number +* int num_glob_vars number of global vars in file +* +* exit conditions - +* float* glob_var_vals array of global variable values +* +* revision history - +* +* $Id: exggv.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the values of all the global variables for a single time step from + * the database; time step numbers are assumed to start at 1 + */ + +int ex_get_glob_vars (int exoid, + int time_step, + int num_glob_vars, + void *glob_var_vals) +{ + int varid; + long start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire previously defined variable */ + + if ((varid = ncvarid (exoid, VAR_GLO_VAR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: failed to locate global variables in file id %d", + exoid); + ex_err("ex_get_glob_vars",errmsg,exerrval); + return (EX_WARN); + } + + +/* read values of global variables */ + + start[0] = --time_step; + start[1] = 0; + + count[0] = 1; + count[1] = num_glob_vars; + + if (ncvarget (exoid, varid, start, count, + ex_conv_array(exoid,RTN_ADDRESS,glob_var_vals,num_glob_vars)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get global variable values from file id %d", + exoid); + ex_err("ex_get_glob_vars",errmsg,exerrval); + return (EX_FATAL); + } + + + ex_conv_array( exoid, READ_CONVERT, glob_var_vals, num_glob_vars ); + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exggvt.c b/Utilities/vtkexodus2/exggvt.c new file mode 100644 index 0000000..5087cc3 --- /dev/null +++ b/Utilities/vtkexodus2/exggvt.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exggvt - get_glob_var_time +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int glob_var_index global variable index +* int beg_time_step starting time step +* int end_time_step ending time step +* +* exit conditions - +* float* glob_var_vals global variable values +* +* revision history - +* +* $Id: exggvt.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the values of a single global variable through a specified number + * of time steps in the database; time step numbers and variable indices + * are assumed to start at 1 + */ + +int ex_get_glob_var_time (int exoid, + int glob_var_index, + int beg_time_step, + int end_time_step, + void *glob_var_vals) +{ + int varid; + long start[2], count[2]; + float fdum; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + + +/* inquire previously defined variable */ + + if ((varid = ncvarid (exoid, VAR_GLO_VAR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate global variables in file id %d", + exoid); + ex_err("ex_get_glob_var_time",errmsg,exerrval); + return (EX_WARN); + } + +/* read values of global variables */ + + start[0] = --beg_time_step; + start[1] = --glob_var_index; + + if (end_time_step < 0) + { + +/* user is requesting the maximum time step; we find this out using the + * database inquire function to get the number of time steps + */ + if (ex_inquire (exoid, EX_INQ_TIME, &end_time_step, &fdum, cdum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of time steps in file id %d", + exoid); + ex_err("ex_get_glob_var_time",errmsg,exerrval); + return (EX_FATAL); + } + } + + end_time_step--; + + count[0] = end_time_step - beg_time_step + 1; + count[1] = 1; + + if (ncvarget (exoid, varid, start, count, + ex_conv_array(exoid,RTN_ADDRESS,glob_var_vals,count[0])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get global variable %d values from file id %d", + glob_var_index, exoid); + ex_err("ex_get_glob_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + ex_conv_array( exoid, READ_CONVERT, glob_var_vals, count[0] ); + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exginf.c b/Utilities/vtkexodus2/exginf.c new file mode 100644 index 0000000..fee9e7c --- /dev/null +++ b/Utilities/vtkexodus2/exginf.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exginf - ex_get_info +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* char* info[] ptr array of info records +* +* revision history - +* +* $Id: exginf.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads information records from the database + */ + +int ex_get_info (int exoid, + char **info) +{ + int i, j, dimid, varid; + long num_info, start[2]; + char *ptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire previously defined dimensions and variables */ + + if ((dimid = ncdimid (exoid, DIM_NUM_INFO)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: failed to locate number of info records in file id %d", + exoid); + ex_err("ex_get_info",errmsg,exerrval); + return (EX_WARN); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_info) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of info records in file id %d", + exoid); + ex_err("ex_get_info",errmsg,exerrval); + return (EX_FATAL); + } + + +/* do this only if there are any information records */ + + if (num_info > 0) + { + if ((varid = ncvarid (exoid, VAR_INFO)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate info record data in file id %d", exoid); + ex_err("ex_get_info",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read the information records */ + + for (i=0; i= info[i] && *ptr == ' ' ); + *(++ptr) = '\0'; + } + + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgini.c b/Utilities/vtkexodus2/exgini.c new file mode 100644 index 0000000..2e64d44 --- /dev/null +++ b/Utilities/vtkexodus2/exgini.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgini - ex_get_init +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* char* title title of file +* int* num_dim number of dimensions (per node) +* int* num_nodes number of nodes +* int* num_elem number of elements +* int* num_elem_blk number of element blocks +* int* num_node_sets number of node sets +* int* num_side_sets numver of side sets +* +* revision history - +* +* $Id: exgini.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the initialization parameters from an opened EXODUS II file + */ + +int ex_get_init (int exoid, + char *title, + int *num_dim, + int *num_nodes, + int *num_elem, + int *num_elem_blk, + int *num_node_sets, + int *num_side_sets) +{ + int dimid; + long lnum_dim, lnum_nodes, lnum_elem, lnum_elem_blk, lnum_node_sets; + long lnum_side_sets; + char errmsg[MAX_ERR_LENGTH]; + int title_len; + nc_type title_type; + + exerrval = 0; /* clear error code */ + + if (ncattinq (exoid, NC_GLOBAL, ATT_TITLE, &title_type, &title_len) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to inquire title in file id %d", exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + + /* Check title length to avoid overrunning clients memory space; + include trailing null */ + if (title_len > MAX_LINE_LENGTH+1) { + sprintf(errmsg, + "Error: Title is too long (%d characters) in file id %d", + title_len-1, exoid); + exerrval = -1; + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + /* printf("[ex_get_init] title length: %d\n",title_len); */ + + if (ncattget (exoid, NC_GLOBAL, ATT_TITLE, title) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get title in file id %d", exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + + + /* printf("[ex_get_init] title: %s\n",title); */ + + + if ((dimid = ncdimid (exoid, DIM_NUM_DIM)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of dimensions in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of dimensions in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + *num_dim = lnum_dim; + + + /* Handle case with zero-nodes */ + if ((dimid = ncdimid (exoid, DIM_NUM_NODES)) == -1) { + *num_nodes = 0; + } else { + + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_nodes) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + *num_nodes = lnum_nodes; + } + + if ((dimid = ncdimid (exoid, DIM_NUM_ELEM)) == -1) { + *num_elem = 0; + } else { + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + *num_elem = lnum_elem; + } + + + if (*num_elem > 0) { + if ((dimid = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element blocks in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_elem_blk) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + *num_elem_blk = lnum_elem_blk; + } else { + *num_elem_blk = 0; + } + + + /* node sets are optional */ + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) == -1) + *num_node_sets = 0; + else + { + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_node_sets) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of node sets in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + *num_node_sets = lnum_node_sets; + } + + /* side sets are optional */ + if ((dimid = ncdimid (exoid, DIM_NUM_SS)) == -1) + *num_side_sets = 0; + else + { + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_side_sets) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of side sets in file id %d", + exoid); + ex_err("ex_get_init",errmsg,exerrval); + return (EX_FATAL); + } + *num_side_sets = lnum_side_sets; + } + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgmap.c b/Utilities/vtkexodus2/exgmap.c new file mode 100644 index 0000000..87afef5 --- /dev/null +++ b/Utilities/vtkexodus2/exgmap.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgmap - ex_get_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* int* elem_map element order map array +* +* revision history - +* +* $Id: exgmap.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the element order map from the database + */ + +int ex_get_map (int exoid, + int *elem_map) +{ + int numelemdim, mapid, i, iresult; + long num_elem, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions and variables */ + + /* See if file contains any elements...*/ + if ((numelemdim = ncdimid (exoid, DIM_NUM_ELEM)) == -1) + { + return (EX_NOERR); + } + + if (ncdiminq (exoid, numelemdim, (char *) 0, &num_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in file id %d", + exoid); + ex_err("ex_get_map",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((mapid = ncvarid (exoid, VAR_MAP)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: element order map not stored in file id %d; returning default map", + exoid); + ex_err("ex_get_map",errmsg,exerrval); + +/* generate default map of 1..n, where n is num_elem */ + for (i=0; i +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the node map with specified ID + */ + +int ex_get_node_map (int exoid, + int map_id, + int *node_map) +{ + int dimid, var_id, id_ndx, iresult; + long num_node, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* See if any nodes are stored in this file */ + if ((dimid = ncdimid (exoid, DIM_NUM_NODES)) == -1) + { + return (EX_NOERR); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_node) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in file id %d", exoid); + ex_err("ex_get_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* first check if any node maps have been defined */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NM)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no node maps defined in file id %d", + exoid); + ex_err("ex_get_node_map",errmsg,exerrval); + return (EX_WARN); + } + +/* Lookup index of node map id property array */ + + id_ndx = ex_id_lkup(exoid,VAR_NM_PROP(1),map_id); + if (exerrval != 0) + { + + sprintf(errmsg, + "Error: failed to locate node map id %d in %s in file id %d", + map_id,VAR_NM_PROP(1),exoid); + ex_err("ex_get_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* inquire id's of previously defined dimensions and variables */ + + if ((var_id = ncvarid (exoid, VAR_NODE_MAP(id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node map %d in file id %d", + map_id,exoid); + ex_err("ex_get_node_map",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the node map */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_node; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, var_id, start, count, node_map); + } else { + if (!(longs = malloc(num_node * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for node map for file id %d", + exoid); + ex_err("ex_get_node_map",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, var_id, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node map in file id %d", + exoid); + ex_err("ex_get_node_map",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, node_map, num_node); + free (longs); + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgnnm.c b/Utilities/vtkexodus2/exgnnm.c new file mode 100644 index 0000000..2d9a919 --- /dev/null +++ b/Utilities/vtkexodus2/exgnnm.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgnnm - ex_get_node_num_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* int* node_map node numbering map array +* +* revision history - +* +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the node numbering map from the database + */ + +int ex_get_node_num_map (int exoid, + int *node_map) +{ + int numnodedim, mapid, i, iresult; + long num_nodes, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions and variables */ + if ((numnodedim = ncdimid (exoid, DIM_NUM_NODES)) == -1) + { + return (EX_NOERR); + } + + if (ncdiminq (exoid, numnodedim, (char *) 0, &num_nodes) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in file id %d", + exoid); + ex_err("ex_get_node_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((mapid = ncvarid (exoid, VAR_NODE_NUM_MAP)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: node numbering map not stored in file id %d; returning default map", + exoid); + ex_err("ex_get_node_num_map",errmsg,exerrval); + +/* generate default map of 1..n, where n is num_nodes */ + for (i=0; i +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the node list for a single node set + */ + +int ex_get_node_set (int exoid, + int node_set_id, + int *node_set_node_list) +{ + int dimid, node_list_id, node_set_id_ndx, iresult; + long num_nodes_in_set, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any node sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no node sets defined in file id %d", + exoid); + ex_err("ex_get_node_set",errmsg,exerrval); + return (EX_WARN); + } + +/* Lookup index of node set id in VAR_NS_IDS array */ + + node_set_id_ndx = ex_id_lkup(exoid,VAR_NS_IDS,node_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: node set %d is NULL in file id %d", + node_set_id,exoid); + ex_err("ex_get_node_set",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + + sprintf(errmsg, + "Error: failed to locate node set id %d in %s in file id %d", + node_set_id,VAR_NS_IDS,exoid); + ex_err("ex_get_node_set",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions and variables */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NOD_NS(node_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes in node set %d in file id %d", + node_set_id,exoid); + ex_err("ex_get_node_set",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_nodes_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in set %d in file id %d", + node_set_id, exoid); + ex_err("ex_get_node_set",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((node_list_id = ncvarid (exoid, VAR_NODE_NS(node_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node set %d node list in file id %d", + node_set_id,exoid); + ex_err("ex_get_node_set",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the node list array */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_nodes_in_set; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, node_list_id, start, count, node_set_node_list); + } else { + if (!(longs = malloc(num_nodes_in_set * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for node set node list for file id %d", + exoid); + ex_err("ex_get_node_set",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, node_list_id, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node set node list in file id %d", + exoid); + ex_err("ex_get_node_set",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, node_set_node_list, num_nodes_in_set); + free (longs); + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgnsd.c b/Utilities/vtkexodus2/exgnsd.c new file mode 100644 index 0000000..2cbc5ac --- /dev/null +++ b/Utilities/vtkexodus2/exgnsd.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgnsd - ex_get_node_set_dist_fact +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int node_set_id node set id +* +* exit conditions - +* int* node_set_dist_fact node distribution factors for node set +* +* revision history - +* +* $Id: exgnsd.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the distribution factors for a single node set + */ + +int ex_get_node_set_dist_fact (int exoid, + int node_set_id, + void *node_set_dist_fact) +{ + int dimid, dist_id, node_set_id_ndx; + long num_nodes_in_set, start[1], count[1]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any node sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no node sets defined in file id %d", + exoid); + ex_err("ex_get_node_set_dist_fact",errmsg,exerrval); + return (EX_WARN); + } + +/* Lookup index of node set id in VAR_NS_IDS array */ + + node_set_id_ndx = ex_id_lkup(exoid,VAR_NS_IDS,node_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: node set %d is NULL in file id %d", + node_set_id,exoid); + ex_err("ex_get_node_set_dist_fact",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + + sprintf(errmsg, + "Error: failed to locate node set id %d in %s in file id %d", + node_set_id,VAR_NS_IDS,exoid); + ex_err("ex_get_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions and variables */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NOD_NS(node_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes in node set %d in file id %d", + node_set_id,exoid); + ex_err("ex_get_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_nodes_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in node set %d in file id %d", + node_set_id, exoid); + ex_err("ex_get_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + if ((dist_id = ncvarid (exoid, VAR_FACT_NS(node_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: dist factors not stored for node set %d in file id %d", + node_set_id,exoid); + ex_err("ex_get_node_set_dist_fact",errmsg,exerrval); + return (EX_WARN); /* complain - but not too loud */ + } + + +/* read in the distribution factors array */ + + start[0] = 0; + + count[0] = num_nodes_in_set; + + if (ncvarget (exoid, dist_id, start, count, + ex_conv_array(exoid,RTN_ADDRESS,node_set_dist_fact, + num_nodes_in_set)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get distribution factors in file id %d", + exoid); + ex_err("ex_get_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + + ex_conv_array( exoid, READ_CONVERT, node_set_dist_fact, num_nodes_in_set ); + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgnsi.c b/Utilities/vtkexodus2/exgnsi.c new file mode 100644 index 0000000..2b40631 --- /dev/null +++ b/Utilities/vtkexodus2/exgnsi.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgnsi - ex_get_node_set_ids +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* int node_set_ids array of node set ids +* +* revision history - +* +* $Id: exgnsi.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the node set ids from the database + */ + +int ex_get_node_set_ids (int exoid, + int *ids) +{ + int dimid, varid, iresult; + long num_node_sets, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions and variables */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no node sets defined in file id %d", + exoid); + ex_err("ex_get_node_set_ids",errmsg,exerrval); + return (EX_WARN); + } + + + if (ncdiminq (exoid, dimid, (char *) 0, &num_node_sets) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of node sets in file id %d", + exoid); + ex_err("ex_get_node_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((varid = ncvarid (exoid, VAR_NS_IDS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node set ids in file id %d", + exoid); + ex_err("ex_get_node_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the node set ids */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_node_sets; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, varid, start, count, ids); + } else { + if (!(longs = malloc(num_node_sets * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for node set ids for file id %d", + exoid); + ex_err("ex_get_node_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, varid, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get node set ids in file id %d", + exoid); + ex_err("ex_get_node_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, ids, num_node_sets); + free (longs); + } + + return(EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgnv.c b/Utilities/vtkexodus2/exgnv.c new file mode 100644 index 0000000..ca15170 --- /dev/null +++ b/Utilities/vtkexodus2/exgnv.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgnv - ex_get_nodal_var +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step whole time step number +* int nodeal_var_index index of desired nodal variable +* int num_nodes number of nodal points +* +* exit conditions - +* float* nodal_var_vals array of nodal variable values +* +* revision history - +* +* $Id: exgnv.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the values of a single nodal variable for a single time step from + * the database; assume the first time step and nodal variable index is 1 + */ + +int ex_get_nodal_var (int exoid, + int time_step, + int nodal_var_index, + int num_nodes, + void *nodal_var_vals) +{ + int varid; + long start[3], count[3]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* inquire previously defined variable */ + + if (ex_large_model(exoid) == 0) { + /* read values of the nodal variable */ + if ((varid = ncvarid (exoid, VAR_NOD_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variables in file id %d", + exoid); + ex_err("ex_get_nodal_var",errmsg,exerrval); + return (EX_WARN); + } + + start[0] = --time_step; + start[1] = --nodal_var_index; + start[2] = 0; + + count[0] = 1; + count[1] = 1; + count[2] = num_nodes; + + } else { + /* read values of the nodal variable -- stored as separate variables... */ + /* Get the varid.... */ + if ((varid = ncvarid (exoid, VAR_NOD_VAR_NEW(nodal_var_index))) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variable %d in file id %d", + nodal_var_index, exoid); + ex_err("ex_get_nodal_var",errmsg,exerrval); + return (EX_WARN); + } + + start[0] = --time_step; + start[1] = 0; + + count[0] = 1; + count[1] = num_nodes; + + } + if (ncvarget (exoid, varid, start, count, + ex_conv_array(exoid,RTN_ADDRESS,nodal_var_vals,num_nodes)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get nodal variables in file id %d", + exoid); + ex_err("ex_get_nodal_var",errmsg,exerrval); + return (EX_FATAL); + } + + ex_conv_array( exoid, READ_CONVERT,nodal_var_vals, num_nodes ); + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgnvid.c b/Utilities/vtkexodus2/exgnvid.c new file mode 100644 index 0000000..a2bdca8 --- /dev/null +++ b/Utilities/vtkexodus2/exgnvid.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgnvid - ex_get_nodal_varid +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* +* exit conditions - +* int* varid array of nodal variable varids +* +* revision history - +* +* $Id: exgnvid.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * returns the varids for the nodal variables. + */ + +int ex_get_nodal_varid(int exoid, int *varid) +{ + int i, dimid, nvarid; + long num_vars; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NOD_VAR)) == -1) { + num_vars = 0; + if (ncerr == NC_EBADDIM) + return(EX_NOERR); /* no nodal variables defined */ + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate nodal variable names in file id %d", + exoid); + ex_err("ex_get_nodal_varid",errmsg,exerrval); + return (EX_FATAL); + } + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_vars) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodal variables in file id %d", + exoid); + ex_err("ex_get_nodal_varid",errmsg,exerrval); + return (EX_FATAL); + } + + if (ex_large_model(exoid) == 0) { + /* All varids are the same; */ + if ((nvarid = ncvarid (exoid, VAR_NOD_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variables in file id %d", + exoid); + ex_err("ex_get_nodal_varid",errmsg,exerrval); + return (EX_WARN); + } + for (i=0; i < num_vars; i++) { + varid[i] = nvarid; + } + } else { + /* Variables stored separately; each has a unique varid */ + for (i=0; i < num_vars; i++) { + if ((nvarid = ncvarid (exoid, VAR_NOD_VAR_NEW(i+1))) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variable %d in file id %d", + i+1, exoid); + ex_err("ex_get_nodal_varid",errmsg,exerrval); + return (EX_WARN); + } + varid[i] = nvarid; + } + } + return(EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgnvt.c b/Utilities/vtkexodus2/exgnvt.c new file mode 100644 index 0000000..74b09ad --- /dev/null +++ b/Utilities/vtkexodus2/exgnvt.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgnvt - ex_get_nodal_var_time +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int nodal_var_index index of desired nodal variable +* int node_number number of desired node +* int beg_time_step starting time step +* int end_time_step finishing time step +* +* exit conditions - +* float* nodal_var_vals array of nodal variable values +* +* revision history - +* +* $Id: exgnvt.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the values of a nodal variable for a single node through a + * specified number of time steps in the database; assume the first time + * step, nodal variable index, and node are numbered 1 + */ + +int ex_get_nodal_var_time (int exoid, + int nodal_var_index, + int node_number, + int beg_time_step, + int end_time_step, + void *nodal_var_vals) +{ + int varid; + long start[3], count[3]; + float fdum; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + /* inquire previously defined variable */ + + cdum = 0; /* initialize even though it is not used */ + + if (end_time_step < 0) + { + + /* user is requesting the maximum time step; we find this out using the + * database inquire function to get the number of time steps; the ending + * time step number is 1 less due to 0 based array indexing in C + */ + if (ex_inquire (exoid, EX_INQ_TIME, &end_time_step, &fdum, cdum) == -1) + { + + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of time steps in file id %d", + exoid); + ex_err("ex_get_nodal_var_time",errmsg,exerrval); + return (EX_FATAL); + } + } + + end_time_step--; + + if (ex_large_model(exoid) == 0) { + /* read values of the nodal variable; + * assume node number is 1-based (first node is numbered 1); adjust + * so it is 0-based + */ + if ((varid = ncvarid (exoid, VAR_NOD_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variable %d in file id %d", + nodal_var_index, exoid); + ex_err("ex_get_nodal_var",errmsg,exerrval); + return (EX_WARN); + } + start[0] = --beg_time_step; + start[1] = --nodal_var_index; + start[2] = --node_number; + + count[0] = end_time_step - beg_time_step + 1; + count[1] = 1; + count[2] = 1; + + } else { + if ((varid = ncvarid (exoid, VAR_NOD_VAR_NEW(nodal_var_index))) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variable %d in file id %d", + nodal_var_index, exoid); + ex_err("ex_get_nodal_var",errmsg,exerrval); + return (EX_WARN); + } + + /* read values of the nodal variable; + * assume node number is 1-based (first node is numbered 1); adjust + * so it is 0-based + */ + + start[0] = --beg_time_step; + start[1] = --node_number; + + count[0] = end_time_step - beg_time_step + 1; + count[1] = 1; + + } + if (ncvarget (exoid, varid, start, count, + ex_conv_array(exoid,RTN_ADDRESS,nodal_var_vals,count[0])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get nodal variables in file id %d", + exoid); + ex_err("ex_get_nodal_var_time",errmsg,exerrval); + return (EX_FATAL); + } + + ex_conv_array( exoid, READ_CONVERT, nodal_var_vals, count[0] ); + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgnvv.c b/Utilities/vtkexodus2/exgnvv.c new file mode 100644 index 0000000..ebea0e4 --- /dev/null +++ b/Utilities/vtkexodus2/exgnvv.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgnv - ex_get_nodal_varid_var +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step whole time step number +* int nodal_var_index index of desired nodal variable +* int num_nodes number of nodal points +* int varid id of variable on exodus database +* +* exit conditions - +* float* nodal_var_vals array of nodal variable values +* +* revision history - +* +* $Id: exgnvv.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the values of a single nodal variable for a single time step from + * the database; assume the first time step and nodal variable index is 1 + */ + +int ex_get_nodal_varid_var(int exoid, + int time_step, + int nodal_var_index, + int num_nodes, + int varid, + void *nodal_var_vals) +{ + long start[3], count[3]; + char errmsg[MAX_ERR_LENGTH]; + void *array; + + exerrval = 0; /* clear error code */ + + /* inquire previously defined variable */ + + if (ex_large_model(exoid) == 0) { + start[0] = --time_step; + start[1] = --nodal_var_index; + start[2] = 0; + + count[0] = 1; + count[1] = 1; + count[2] = num_nodes; + } else { + + start[0] = --time_step; + start[1] = 0; + + count[0] = 1; + count[1] = num_nodes; + } + array = ex_conv_array(exoid,RTN_ADDRESS,nodal_var_vals,num_nodes); + if (ncvarget (exoid, varid, start, count, array) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get nodal variables in file id %d", + exoid); + ex_err("ex_get_nodal_varid_var",errmsg,exerrval); + return (EX_FATAL); + } + + if (array != nodal_var_vals) + ex_conv_array( exoid, READ_CONVERT,nodal_var_vals, num_nodes ); + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgp.c b/Utilities/vtkexodus2/exgp.c new file mode 100644 index 0000000..104e9f2 --- /dev/null +++ b/Utilities/vtkexodus2/exgp.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expp - ex_get_prop: read object property +* +* author - Larry A. Schoof, Sandia National Laboratories +* Victor R. Yarberry, Sandia National Laboratories +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int obj_type type of object (element block, node +* set or side set) +* int obj_id id of object for which value +* is desired +* char* prop_name name of the property for which +* value is desired +* +* exit conditions - +* int* value returned value of the property +* +* revision history - +* +* $Id: exgp.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads an object property + */ + +int ex_get_prop (int exoid, + int obj_type, + int obj_id, + const char *prop_name, + int *value) +{ + int num_props, i, propid; + int found = FALSE; + long start[1]; + nclong l_val; + char name[MAX_VAR_NAME_LENGTH+1]; + char tmpstr[MAX_VAR_NAME_LENGTH+1]; + char obj_stype[MAX_VAR_NAME_LENGTH+1]; + char obj_vtype[MAX_VAR_NAME_LENGTH+1]; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* open appropriate variable, depending on obj_type and prop_name */ + + num_props = ex_get_num_props(exoid,obj_type); + + switch (obj_type) + { + case EX_ELEM_BLOCK: + strcpy (obj_stype, "element block"); + strcpy (obj_vtype, VAR_ID_EL_BLK); + break; + case EX_NODE_SET: + strcpy (obj_stype, "node set"); + strcpy (obj_vtype, VAR_NS_IDS); + break; + case EX_SIDE_SET: + strcpy (obj_stype, "side set"); + strcpy (obj_vtype, VAR_SS_IDS); + break; + case EX_ELEM_MAP: + strcpy (obj_stype, "element map"); + strcpy (obj_vtype, VAR_EM_PROP(1)); + break; + case EX_NODE_MAP: + strcpy (obj_stype, "node map"); + strcpy (obj_vtype, VAR_NM_PROP(1)); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_get_prop",errmsg,exerrval); + return(EX_FATAL); + } + + for (i=1; i<=num_props; i++) + { + switch (obj_type){ + case EX_ELEM_BLOCK: + strcpy (name, VAR_EB_PROP(i)); + break; + case EX_NODE_SET: + strcpy (name, VAR_NS_PROP(i)); + break; + case EX_SIDE_SET: + strcpy (name, VAR_SS_PROP(i)); + break; + case EX_ELEM_MAP: + strcpy (name, VAR_EM_PROP(i)); + break; + case EX_NODE_MAP: + strcpy (name, VAR_NM_PROP(i)); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_get_prop",errmsg,exerrval); + return(EX_FATAL); + } + + if ((propid = ncvarid (exoid, name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate property array %s in file id %d", + name, exoid); + ex_err("ex_get_prop",errmsg,exerrval); + return (EX_FATAL); + } + +/* compare stored attribute name with passed property name */ + + if ((ncattget (exoid, propid, ATT_PROP_NAME, tmpstr)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get property name in file id %d", exoid); + ex_err("ex_get_prop",errmsg,exerrval); + return (EX_FATAL); + } + + if (strcmp(tmpstr, prop_name) == 0) + { + found = TRUE; + break; + } + } + +/* if property is not found, return warning */ + + if (!found) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Warning: %s property %s not defined in file id %d", + obj_stype, prop_name, exoid); + ex_err("ex_get_prop",errmsg,exerrval); + return (EX_WARN); + } + +/* find index into property array using obj_id; read value from property */ +/* array at proper index; ex_id_lkup returns an index that is 1-based, */ +/* but netcdf expects 0-based arrays so subtract 1 */ + + start[0] = ex_id_lkup (exoid, obj_vtype, obj_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: %s id %d is NULL in file id %d", + obj_stype, obj_id, exoid); + ex_err("ex_get_prop",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate id %d in %s property array in file id %d", + obj_id, obj_stype, exoid); + ex_err("ex_get_prop",errmsg,exerrval); + return (EX_FATAL); + } + } + start[0] = start[0] - 1; + + if (ncvarget1 (exoid, propid, start, &l_val) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to read value in %s property array in file id %d", + obj_stype, exoid); + ex_err("ex_get_prop",errmsg,exerrval); + return (EX_FATAL); + } + + *value = l_val; + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgpa.c b/Utilities/vtkexodus2/exgpa.c new file mode 100644 index 0000000..fc8ee5a --- /dev/null +++ b/Utilities/vtkexodus2/exgpa.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgpa - ex_get_prop_array: read object property array +* +* author - Larry A. Schoof, Sandia National Laboratories +* Victor R. Yarberry, Sandia National Laboratories +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int obj_type type of object (element block, node +* set or side set) +* char* prop_name name of the property for which the +* values will be read +* +* exit conditions - +* int* values returned array of property values +* +* revision history - +* +* $Id: exgpa.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads an array of object properties + */ + +int ex_get_prop_array (int exoid, + int obj_type, + const char *prop_name, + int *values) +{ + int num_props, i, propid, dimid, iresult; + int found = FALSE; + long start[1], count[1], num_obj; + nclong *longs; + char name[MAX_VAR_NAME_LENGTH+1]; + char tmpstr[MAX_VAR_NAME_LENGTH+1]; + char obj_stype[MAX_VAR_NAME_LENGTH+1]; + char dim_name[MAX_VAR_NAME_LENGTH+1]; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* open appropriate variable, depending on obj_type and prop_name */ + + num_props = ex_get_num_props(exoid, obj_type); + + switch (obj_type) + { + case EX_ELEM_BLOCK: + strcpy (obj_stype, VAR_ID_EL_BLK); + strcpy (dim_name, DIM_NUM_EL_BLK); + break; + case EX_NODE_SET: + strcpy (obj_stype, VAR_NS_IDS); + strcpy (dim_name, DIM_NUM_NS); + break; + case EX_SIDE_SET: + strcpy (obj_stype, VAR_SS_IDS); + strcpy (dim_name, DIM_NUM_SS); + break; + case EX_ELEM_MAP: + strcpy (obj_stype, VAR_EM_PROP(1)); + strcpy (dim_name, DIM_NUM_EM); + break; + case EX_NODE_MAP: + strcpy (obj_stype, VAR_NM_PROP(1)); + strcpy (dim_name, DIM_NUM_NM); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_get_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + + + for (i=1; i<=num_props; i++) + { + switch (obj_type){ + case EX_ELEM_BLOCK: + strcpy (name, VAR_EB_PROP(i)); + break; + case EX_NODE_SET: + strcpy (name, VAR_NS_PROP(i)); + break; + case EX_SIDE_SET: + strcpy (name, VAR_SS_PROP(i)); + break; + case EX_ELEM_MAP: + strcpy (name, VAR_EM_PROP(i)); + break; + case EX_NODE_MAP: + strcpy (name, VAR_NM_PROP(i)); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_get_prop_array",errmsg,exerrval); + return(EX_FATAL); + } + + if ((propid = ncvarid (exoid, name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate property array %s in file id %d", + name, exoid); + ex_err("ex_get_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + +/* compare stored attribute name with passed property name */ + + tmpstr[0] = '\0'; + if ((ncattget (exoid, propid, ATT_PROP_NAME, tmpstr)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get property name in file id %d", exoid); + ex_err("ex_get_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + + if (strcmp(tmpstr, prop_name) == 0) + { + found = TRUE; + break; + } + } + +/* if property is not found, return warning */ + + if (!found) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Warning: object type %d, property %s not defined in file id %d", + obj_type, prop_name, exoid); + ex_err("ex_get_prop_array",errmsg,exerrval); + return (EX_WARN); + } + + if ((dimid = ncdimid (exoid, dim_name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of objects in file id %d", + exoid); + ex_err("ex_get_prop_array",errmsg, exerrval); + return(EX_FATAL); + } + +/* get number of objects */ + + if (ncdiminq (exoid, dimid, dim_name, &num_obj) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of %s objects in file id %d", + obj_stype, exoid); + ex_err("ex_get_prop_array",errmsg, exerrval); + return (EX_FATAL); + } + +/* read num_obj values from property variable */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_obj; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, propid, start, count, values); + } else { + if (!(longs = malloc(num_obj * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for %s property array for file id %d", + obj_stype, exoid); + ex_err("ex_get_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, propid, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to read values in %s property array in file id %d", + obj_stype, exoid); + ex_err("ex_get_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, values, num_obj); + free (longs); + } + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgpn.c b/Utilities/vtkexodus2/exgpn.c new file mode 100644 index 0000000..8bdbd03 --- /dev/null +++ b/Utilities/vtkexodus2/exgpn.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgpn - ex_get_prop_names +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int obj_type type of object; element block, node +* set, or side set +* +* exit conditions - +* char* prop_names[] ptr array of property names +* +* revision history - +* +* $Id: exgpn.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the names of the property arrays from the database + */ + +int ex_get_prop_names (int exoid, + int obj_type, + char **prop_names) +{ + int i, num_props, propid; + char var_name[12]; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; + +/* determine which type of object property names are desired for */ + + num_props = ex_get_num_props (exoid, obj_type); + + for (i=0; i 0) + { + if ((varid = ncvarid (exoid, VAR_QA_TITLE)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate qa record data in file id %d", exoid); + ex_err("ex_get_qa",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read the QA records */ + + for (i=0; i= qa_record[i][j] && *ptr == ' ' ); + *(++ptr) = '\0'; + } + } + } + + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgsnl.c b/Utilities/vtkexodus2/exgsnl.c new file mode 100644 index 0000000..8994c1f --- /dev/null +++ b/Utilities/vtkexodus2/exgsnl.c @@ -0,0 +1,522 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgsnl - ex_get_side_set_node_list_len +* +* author - Sandia National Laboratories +* Vic Yarberry - Original +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int side_set_id side set id +* +* exit conditions - +* int *side_set_node_list_len length of node list +* +* revision history - +* +* $Id: exgsnl.c,v 1.3 2005/07/19 23:40:10 andy Exp $ +* +*****************************************************************************/ + +#include +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * This routine is designed to read the Exodus II V 2.0 side set side + * definition and return the length of a ExodusI style side set node list. + + + + */ + +int ex_get_side_set_node_list_len(int exoid, + int side_set_id, + int *side_set_node_list_len) +{ + int i, j, m; + int num_side_sets, num_elem_blks, num_df, ndim; + int tot_num_elem = 0, tot_num_ss_elem = 0; + int *elem_blk_ids; + int *ss_elem_ndx; + int *side_set_elem_list, *side_set_side_list; + int elem_ctr; + int num_elem_in_blk, num_nodes_per_elem, num_attr; + float fdum; + char *cdum, elem_type[MAX_STR_LENGTH+1]; + + struct elem_blk_parm + { + char elem_type[MAX_STR_LENGTH+1]; + int elem_blk_id; + int num_elem_in_blk; + int num_nodes_per_elem; + int num_nodes_per_side; + int num_attr; + int elem_ctr; + int elem_type_val; + } *elem_blk_parms; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + + *side_set_node_list_len = 0; /* default value */ +/* first check if any side sets are specified */ +/* inquire how many side sets have been stored */ + + if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of side sets in file id %d",exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return(EX_FATAL); + } + + if (num_side_sets == 0) + { + sprintf(errmsg, + "Warning: no side sets defined in file id %d",exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,EX_WARN); + return(EX_WARN); + } + + if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d",exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return(EX_FATAL); + } + + if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get total number of elements in file id %d",exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return(EX_FATAL); + } + +/* get the dimensionality of the coordinates; this is necessary to + distinguish between 2d TRIs and 3d TRIs */ + + if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get dimensionality in file id %d",exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return(EX_FATAL); + } + + /* First determine the # of elements in the side set*/ + if ((ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of elements in side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return(EX_FATAL); + } + + if (tot_num_ss_elem == 0) /* NULL side set? */ + return (EX_NOERR); /* return zero */ + + /* Allocate space for the side set element list */ + if (!(side_set_elem_list=malloc(tot_num_ss_elem*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set element list for file id %d", + exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return (EX_FATAL); + } + + /* Allocate space for the side set side list */ + if (!(side_set_side_list=malloc(tot_num_ss_elem*sizeof(int)))) + { + free(side_set_elem_list); + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set side list for file id %d", + exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return (EX_FATAL); + } + + if (ex_get_side_set(exoid, side_set_id, + side_set_elem_list, side_set_side_list) == -1) + { + free(side_set_elem_list); + free(side_set_side_list); + sprintf(errmsg, + "Error: failed to get side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return (EX_FATAL); + } + + /* Allocate space for the ss element index array */ + if (!(ss_elem_ndx=malloc(tot_num_ss_elem*sizeof(int)))) + { + free(side_set_elem_list); + free(side_set_side_list); + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set elem sort array for file id %d", + exoid); + ex_err("ex_get_side_set_node_list_len",errmsg,exerrval); + return (EX_FATAL); + } + + /* Sort side set element list into index array - non-destructive */ + for (i=0;i= num_elem_blks) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid element number %d found in side set %d in file %d", + side_set_elem_list[i], side_set_id, exoid); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(side_set_side_list); + free(side_set_elem_list); + ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG); + return (EX_FATAL); + } + + /* Update *side_set_node_list_len (which points to next node in chain */ + + /* WEDGEs with 3 node sides (side 4 or 5) are special cases */ + if (elem_blk_parms[j].elem_type_val == WEDGE && + (side_set_side_list[i] == 4 || side_set_side_list[i] == 5)) + { + if (elem_blk_parms[j].num_nodes_per_elem == 6) + *side_set_node_list_len += 3; /* 3 node side */ + else + *side_set_node_list_len += 6; /* 6 node side */ + } + /* PYRAMIDSs with 3 node sides (sides 1,2,3,4) are also special */ + else if (elem_blk_parms[j].elem_type_val == PYRAMID && + (side_set_side_list[i] < 5)) + { + if (elem_blk_parms[j].num_nodes_per_elem == 5) + *side_set_node_list_len += 3; /* 3 node side */ + else + *side_set_node_list_len += 6; /* 6 node side */ + } + /* side numbers 3,4,5,6 for SHELLs are also special */ + else if (elem_blk_parms[j].elem_type_val == SHELL && + (side_set_side_list[i] > 2 )) + { + if (elem_blk_parms[j].num_nodes_per_elem == 4) + *side_set_node_list_len += 2; /* 2 node side */ + else + *side_set_node_list_len += 3; /* 3 node side */ + } + /* sides 3, 4, and 5 of 3d TRIs are special cases */ + else if (elem_blk_parms[j].elem_type_val == TRIANGLE && + ndim == 3 && + side_set_side_list[i] > 2 ) + { + if (elem_blk_parms[j].num_nodes_per_elem == 3) /* 3-node TRI */ + *side_set_node_list_len += 2; /* 2 node side */ + else /* 6-node TRI */ + *side_set_node_list_len += 3; /* 3 node side */ + } + else if (elem_blk_parms[j].elem_type_val == UNK) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: %s in elem block %d is an unsupported element type", + elem_blk_parms[i].elem_type, elem_blk_parms[i].elem_blk_id); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(side_set_side_list); + free(side_set_elem_list); + ex_err("ex_get_side_set_node_list_len",errmsg,EX_MSG); + return (EX_FATAL); + } + else /* all other element types */ + *side_set_node_list_len += elem_blk_parms[j].num_nodes_per_side; + } + + /* All done: release element block ids array, + element block parameters array, and side set element index array */ + free(elem_blk_ids); + free(elem_blk_parms); + free(ss_elem_ndx); + free(side_set_side_list); + free(side_set_elem_list); + + return(EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgsp.c b/Utilities/vtkexodus2/exgsp.c new file mode 100644 index 0000000..a4f7fd8 --- /dev/null +++ b/Utilities/vtkexodus2/exgsp.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgsp - ex_get_side_set_param +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int side_set_id side set id +* +* exit conditions - +* int* num_side_in_set number of sides in the side set +* int* num_dist_fact_in_set number of distribution factors in the +* side set +* +* revision history - +* +* $Id: exgsp.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the number of sides and the number of distribution factors which + * describe a single side set + */ + +int ex_get_side_set_param (int exoid, + int side_set_id, + int *num_side_in_set, + int *num_dist_fact_in_set) +{ + int dimid, side_set_id_ndx; + long lnum_side_in_set, lnum_dist_fact_in_set; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any side sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no side sets stored in file id %d", + exoid); + ex_err("ex_get_side_set_param",errmsg,exerrval); + return (EX_WARN); + } + +/* Lookup index of side set id in VAR_SS_IDS array */ + + side_set_id_ndx = ex_id_lkup(exoid,VAR_SS_IDS,side_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) /* NULL side set? */ + { + *num_side_in_set = 0; + *num_dist_fact_in_set = 0; + sprintf(errmsg, + "Warning: side set %d is NULL in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_param",errmsg,exerrval); + return (EX_WARN); + } + else + { + + sprintf(errmsg, + "Error: failed to locate side set id %d in %s in file id %d", + side_set_id,VAR_SS_IDS,exoid); + ex_err("ex_get_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + } + + +/* inquire values of dimensions */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SIDE_SS(side_set_id_ndx))) == -1) + { + *num_side_in_set = 0; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of sides in side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + else + { + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_side_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of side sets in file id %d", + exoid); + ex_err("ex_get_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + *num_side_in_set = lnum_side_in_set; + } + + + if ((dimid = ncdimid (exoid, DIM_NUM_DF_SS(side_set_id_ndx))) == -1) + { + *num_dist_fact_in_set = 0; /* no distribution factors for this side set*/ + if (ncerr == NC_EBADDIM) + return (EX_NOERR); + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of dist factors in side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + } + else + { + if (ncdiminq (exoid, dimid, (char *) 0, &lnum_dist_fact_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of dist factors in side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + *num_dist_fact_in_set = lnum_dist_fact_in_set; + } + + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgss.c b/Utilities/vtkexodus2/exgss.c new file mode 100644 index 0000000..b103f29 --- /dev/null +++ b/Utilities/vtkexodus2/exgss.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgss - ex_get_side_set +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int side_set_id side set id +* +* exit conditions - +* int* side_set_elem_list array of elements in side set +* int* side_set_side_list array of sides in side set +* +* revision history - +* +* $Id: exgss.c,v 1.1 2005/07/17 15:43:59 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the side set element list and side set side list for a single side set + */ + +int ex_get_side_set (int exoid, + int side_set_id, + int *side_set_elem_list, + int *side_set_side_list) +{ + + int dimid, elem_list_id, side_list_id, iresult; + int side_set_id_ndx; + long num_side_in_set, count[1], start[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any side sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no side sets stored in file id %d", + exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_WARN); + } + +/* Lookup index of side set id in VAR_SS_IDS array */ + + side_set_id_ndx = ex_id_lkup(exoid,VAR_SS_IDS,side_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: side set %d is NULL in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + + sprintf(errmsg, + "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions and variables */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SIDE_SS(side_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of sides in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_side_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of sides in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + if ((elem_list_id = ncvarid (exoid, VAR_ELEM_SS(side_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + if ((side_list_id = ncvarid (exoid, VAR_SIDE_SS(side_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate side list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the element list and side list arrays */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_side_in_set; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget(exoid, elem_list_id, start, count, side_set_elem_list); + } else { + if (!(longs = malloc(num_side_in_set * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element list for side set %d for file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, elem_list_id, start, count, longs); + } + + if (iresult) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get element list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, side_set_elem_list, num_side_in_set); + } + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget(exoid, side_list_id, start, count, side_set_side_list); + } else { + iresult = ncvarget (exoid, side_list_id, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get side list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, side_set_side_list, num_side_in_set); + free (longs); + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exgssc.c b/Utilities/vtkexodus2/exgssc.c new file mode 100644 index 0000000..634a275 --- /dev/null +++ b/Utilities/vtkexodus2/exgssc.c @@ -0,0 +1,620 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgssc - ex_get_side_set_node_count +* +* author - Sandia National Laboratories +* Greg Sjaardema; modified from exgssn.c +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int side_set_id side set id +* +* exit conditions - +* int *side_set_node_cnt_list returned array of number of nodes for +* side or face +* revision history - +* +* $Id: exgssc.c,v 1.3 2005/07/19 23:40:10 andy Exp $ +*****************************************************************************/ + +#include +#include +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* Generic error message for element type/node count mapping...*/ +#define EL_NODE_COUNT_ERROR sprintf(errmsg, \ + "Error: An element of type '%s' with %d nodes is not valid.",\ + elem_blk_parms[i].elem_type,\ + elem_blk_parms[i].num_nodes_per_elem);\ + ex_err("ex_get_side_set_node_count",errmsg,EX_MSG);\ + return(EX_FATAL);\ + +int ex_get_side_set_node_count(int exoid, + int side_set_id, + int *side_set_node_cnt_list) +{ + int ii, i, j, m; + int num_side_sets, num_elem_blks, num_df, ndim; + int tot_num_elem = 0, tot_num_ss_elem = 0, side, elem; + int *elem_blk_ids; + int *ss_elem_ndx; + int *side_set_elem_list, *side_set_side_list; + int elem_ctr; + int num_elem_in_blk, num_nodes_per_elem, num_attr; + float fdum; + char *cdum, elem_type[MAX_STR_LENGTH+1]; + + struct elem_blk_parm + { + char elem_type[MAX_STR_LENGTH+1]; + int elem_blk_id; + int num_elem_in_blk; + int num_nodes_per_elem; + int num_sides; + int num_nodes_per_side[6]; + int num_attr; + int elem_ctr; + int elem_type_val; + } *elem_blk_parms; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + + /* first check if any side sets are specified */ + /* inquire how many side sets have been stored */ + if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of side sets in file id %d",exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return(EX_FATAL); + } + + if (num_side_sets == 0) + { + sprintf(errmsg, + "Warning: no side sets defined in file id %d",exoid); + ex_err("ex_get_side_set_node_count",errmsg,EX_WARN); + return(EX_WARN); + } + + /* Lookup index of side set id in VAR_SS_IDS array */ + ex_id_lkup(exoid,VAR_SS_IDS,side_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: side set %d is NULL in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set_node_count",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + + sprintf(errmsg, + "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return (EX_FATAL); + } + } + + if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d",exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return(EX_FATAL); + } + + if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get total number of elements in file id %d",exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return(EX_FATAL); + } + + /* get the dimensionality of the coordinates; this is necessary to + distinguish between 2d TRIs and 3d TRIs */ + if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get dimensionality in file id %d",exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + return(EX_FATAL); + } + + /* First determine the # of elements in the side set*/ + if ((ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of elements in side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return(EX_FATAL); + } + + /* Allocate space for the side set element list */ + if (!(side_set_elem_list=malloc(tot_num_ss_elem*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set element list for file id %d", + exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return (EX_FATAL); + } + + /* Allocate space for the side set side list */ + if (!(side_set_side_list=malloc(tot_num_ss_elem*sizeof(int)))) + { + free(side_set_elem_list); + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set side list for file id %d", + exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return (EX_FATAL); + } + + if (ex_get_side_set(exoid, side_set_id, + side_set_elem_list, side_set_side_list) == -1) + { + free(side_set_elem_list); + free(side_set_side_list); + sprintf(errmsg, + "Error: failed to get side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return (EX_FATAL); + } + + /* Allocate space for the ss element index array */ + if (!(ss_elem_ndx=malloc(tot_num_ss_elem*sizeof(int)))) + { + free(side_set_elem_list); + free(side_set_side_list); + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set elem sort array for file id %d", + exoid); + ex_err("ex_get_side_set_node_count",errmsg,exerrval); + return (EX_FATAL); + } + + /* Sort side set element list into index array - non-destructive */ + for (i=0;i +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the side set ids from the database + */ + +int ex_get_side_set_ids (int exoid, + int *ids) +{ + int dimid, varid, iresult; + long num_side_sets, start[1], count[1]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions and variables */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SS)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no side sets stored in file id %d", exoid); + ex_err("ex_get_side_set_ids",errmsg,exerrval); + return (EX_WARN); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_side_sets) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of side sets in file id %d", exoid); + ex_err("ex_get_side_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((varid = ncvarid (exoid, VAR_SS_IDS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate side set ids in file id %d", exoid); + ex_err("ex_get_side_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + + +/* read in the side set ids */ + +/* application code has allocated an array of ints but netcdf is expecting + a pointer to nclongs; if ints are different sizes than nclongs, + we must allocate an array of nclongs then convert them to ints with ltoi */ + + start[0] = 0; + count[0] = num_side_sets; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarget (exoid, varid, start, count, ids); + } else { + if (!(longs = malloc(num_side_sets * sizeof(nclong)))) { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for side set ids for file id %d", + exoid); + ex_err("ex_get_side_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + iresult = ncvarget (exoid, varid, start, count, longs); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get side set ids in file id %d", exoid); + ex_err("ex_get_side_set_ids",errmsg,exerrval); + return (EX_FATAL); + } + + if (sizeof(int) != sizeof(nclong)) { + ltoi (longs, ids, num_side_sets); + free (longs); + } + + return(EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgssn.c b/Utilities/vtkexodus2/exgssn.c new file mode 100644 index 0000000..919dc02 --- /dev/null +++ b/Utilities/vtkexodus2/exgssn.c @@ -0,0 +1,1138 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgssn - ex_get_side_set_node_list +* +* author - Sandia National Laboratories +* Vic Yarberry - Original +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int side_set_id side set id +* +* exit conditions - +* int *side_set_node_cnt_list returned array of number of nodes for +* side or face +* int *side_set_node_list array of nodes +* +* revision history - +* +* $Id: exgssn.c,v 1.3 2005/07/19 23:40:10 andy Exp $ +* +*****************************************************************************/ + +#include +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" +/* + * This routine is designed to read the Exodus II V 2.0 side set side + * definition and return a ExodusI style side set node definition. + + + + */ + +int ex_get_side_set_node_list(int exoid, + int side_set_id, + int *side_set_node_cnt_list, + int *side_set_node_list) +{ + int i, j, m; + int num_side_sets, num_elem_blks, num_df, ndim; + int tot_num_elem = 0, tot_num_ss_elem = 0, elem_num = 0; + int connect_offset, side_num, node_pos; + int *elem_blk_ids, *connect; + int *ss_elem_ndx, *ss_elem_node_ndx, *ss_parm_ndx; + int *side_set_elem_list, *side_set_side_list; + int elem_ctr, node_ctr, elem_num_pos; + int num_elem_in_blk, num_nodes_per_elem, num_attr; + float fdum; + char *cdum, elem_type[MAX_STR_LENGTH+1]; + + struct elem_blk_parm + { + char elem_type[MAX_STR_LENGTH+1]; + int elem_blk_id; + int num_elem_in_blk; + int num_nodes_per_elem; + int num_nodes_per_side; + int num_attr; + int elem_ctr; + int elem_type_val; + } *elem_blk_parms; + +/* side to node translation tables - + These tables are used to look up the side number based on the + first and second node in the side/face list. The side node order + is found in the original Exodus document, SAND87-2997. The element + node order is found in the ExodusII document, SAND92-2137. These + tables were generated by following the right-hand rule for determining + the outward normal. +*/ + /* triangle */ + static int tri_table[3][3] = { + /* 1 2 3 side */ + {1,2,4}, {2,3,5}, {3,1,6} /* nodes */ + }; + + /* triangle 3d */ + static int tri3_table[5][7] = { + /* 1 2 side */ + {1,2,3,4,5,6,7}, {3,2,1,6,5,4,7}, /* nodes */ + /* 3 4 5 side */ + {1,2,4,0,0,0,0}, {2,3,5,0,0,0,0}, {3,1,6,0,0,0,0} /* nodes */ + }; + + /* quad */ + static int quad_table[4][3] = { + /* 1 2 3 4 side */ + {1,2,5}, {2,3,6}, {3,4,7}, {4,1,8} /* nodes */ + }; + + /* shell */ + static int shell_table[6][8] = { + /* 1 2 side */ + {1,2,3,4,5,6,7,8}, {1,4,3,2,8,7,6,5} , /* nodes */ + /* 3 4 side */ + {1,2,5,0,0,0,0,0}, {2,3,6,0,0,0,0,0} , /* nodes */ + /* 5 6 side */ + {3,4,7,0,0,0,0,0}, {4,1,8,0,0,0,0,0} /* nodes */ + }; + + /* tetra */ + static int tetra_table[4][6] = { + /* 1 2 3 4 side */ + {1,2,4,5,9,8}, {2,3,4,6,10,9}, {1,4,3,8,10,7}, {1,3,2,7,6,5} /* nodes */ + }; + + /* wedge */ + static int wedge_table[5][8] = { + /* 1 2 3 side */ + {1,2,5,4,7,11,13,10}, {2,3,6,5,8,12,14,11}, {1,4,6,3,10,15,12,9}, + /* 4 5 side */ + {1,3,2,0,9,8,7,0}, {4,5,6,0,13,14,15,0} /* nodes */ + }; + + /* hex */ + static int hex_table[6][9] = { + /* 1 2 side */ + {1,2,6,5,9,14,17,13,26}, {2,3,7,6,10,15,18,14,25}, /* nodes */ + /* 3 4 side */ + {3,4,8,7,11,16,19,15,27}, {1,5,8,4,13,20,16,12,24}, /* nodes */ + /* 5 6 side */ + {1,4,3,2,12,11,10,9,22}, {5,6,7,8,17,18,19,20,23} /* nodes */ + }; + + /* pyramid */ + static int pyramid_table[5][8] = { + /* 1 2 3 side */ + {1,2,5,0,6,11,10,0}, {2,3,5,0,7,12,11,0}, {3,4,5,0,8,13,12,0}, /* nodes */ + /* 4 5 side */ + {1,5,4,0,10,13,9,0}, {1,4,3,2,9,8,7,6} /* nodes */ + }; + + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + +/* first check if any side sets are specified */ +/* inquire how many side sets have been stored */ + + if ((ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of side sets in file id %d",exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return(EX_FATAL); + } + + if (num_side_sets == 0) + { + sprintf(errmsg, + "Warning: no side sets defined in file id %d",exoid); + ex_err("ex_get_side_set_node_list",errmsg,EX_WARN); + return(EX_WARN); + } + +/* Lookup index of side set id in VAR_SS_IDS array */ + + ex_id_lkup(exoid,VAR_SS_IDS,side_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: side set %d is NULL in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set_node_list",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + + sprintf(errmsg, + "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d", + side_set_id,exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return (EX_FATAL); + } + } + + if ((ex_inquire(exoid, EX_INQ_ELEM_BLK, &num_elem_blks, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d",exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return(EX_FATAL); + } + + if ((ex_inquire(exoid, EX_INQ_ELEM, &tot_num_elem, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get total number of elements in file id %d",exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return(EX_FATAL); + } + +/* get the dimensionality of the coordinates; this is necessary to + distinguish between 2d TRIs and 3d TRIs */ + + if ((ex_inquire(exoid, EX_INQ_DIM, &ndim, &fdum, cdum)) == -1) + { + sprintf(errmsg, + "Error: failed to get dimensionality in file id %d",exoid); + ex_err("ex_cvt_nodes_to_sides",errmsg,exerrval); + return(EX_FATAL); + } + + /* First determine the # of elements in the side set*/ + if ((ex_get_side_set_param(exoid,side_set_id,&tot_num_ss_elem,&num_df)) == -1) + { + sprintf(errmsg, + "Error: failed to get number of elements in side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return(EX_FATAL); + } + + /* Allocate space for the side set element list */ + if (!(side_set_elem_list=malloc(tot_num_ss_elem*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set element list for file id %d", + exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return (EX_FATAL); + } + + /* Allocate space for the side set side list */ + if (!(side_set_side_list=malloc(tot_num_ss_elem*sizeof(int)))) + { + free(side_set_elem_list); + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set side list for file id %d", + exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return (EX_FATAL); + } + + if (ex_get_side_set(exoid, side_set_id, + side_set_elem_list, side_set_side_list) == -1) + { + free(side_set_elem_list); + free(side_set_side_list); + sprintf(errmsg, + "Error: failed to get side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return (EX_FATAL); + } + + /* Allocate space for the ss element index array */ + if (!(ss_elem_ndx= malloc(tot_num_ss_elem*sizeof(int)))) + { + free(side_set_elem_list); + free(side_set_side_list); + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set elem sort array for file id %d", + exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return (EX_FATAL); + } + + /* Sort side set element list into index array - non-destructive */ + for (i=0;i= num_elem_blks) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid element number %d found in side set %d in file %d", + side_set_elem_list[i], side_set_id, exoid); + free(ss_parm_ndx); + free(ss_elem_node_ndx); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(side_set_side_list); + free(side_set_elem_list); + ex_err("ex_get_side_set_node_list",errmsg,EX_MSG); + return (EX_FATAL); + } + + ss_parm_ndx[i] = j; /* assign parameter block index */ + ss_elem_node_ndx[i] = node_ctr; /* assign node list index */ + + /* Update node_ctr (which points to next node in chain */ + + /* WEDGEs with 3 node sides (side 4 or 5) are special cases */ + if (elem_blk_parms[j].elem_type_val == WEDGE && + (side_set_side_list[i] == 4 || side_set_side_list[i] == 5)) + { + if (elem_blk_parms[j].num_nodes_per_elem == 6) + node_ctr += 3; /* 3 node side */ + else + node_ctr += 6; /* 6 node side */ + } + /* PYRAMIDSs with 3 node sides (sides 1,2,3,4) are also special */ + else if (elem_blk_parms[j].elem_type_val == PYRAMID && + (side_set_side_list[i] < 5)) + { + if (elem_blk_parms[j].num_nodes_per_elem == 5) + node_ctr += 3; /* 3 node side */ + else + node_ctr += 6; /* 6 node side */ + } + /* side numbers 3,4,5,6 for SHELLs are also special */ + else if (elem_blk_parms[j].elem_type_val == SHELL && + (side_set_side_list[i] > 2 )) + { + if (elem_blk_parms[j].num_nodes_per_elem == 4) + node_ctr += 2; /* 2 node side */ + else + node_ctr += 3; /* 3 node side */ + } + /* side numbers 3,4,5 for 3d TRIs are also special */ + else if (elem_blk_parms[j].elem_type_val == TRIANGLE && + ndim == 3 && + side_set_side_list[i] > 2 ) + { + if (elem_blk_parms[j].num_nodes_per_elem == 3) /* 3-node TRI */ + node_ctr += 2; /* 2 node side */ + else /* 6-node TRI */ + node_ctr += 3; /* 3 node side */ + } + else /* all other element types */ + node_ctr += elem_blk_parms[j].num_nodes_per_side; + } + + /* All setup, ready to go ... */ + + elem_ctr=0; + + for (j=0; j < tot_num_ss_elem; j++) + { + + if (side_set_elem_list[ss_elem_ndx[j]] > elem_ctr) + { + /* release connectivity array space and get next one */ + if (elem_ctr > 0) + { + free(connect); + } + + /* Allocate space for the connectivity array for new element block */ + if (!(connect=malloc(elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk* + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem* + (int)sizeof(int)))) + { + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for connectivity array for file id %d", + exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return (EX_FATAL); + } + + /* get connectivity array */ + if (ex_get_elem_conn( + exoid, + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_blk_id, + connect) == -1) + { + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + sprintf(errmsg, + "Error: failed to allocate space for connectivity array for file id %d", + exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return (EX_FATAL); + } + elem_ctr = elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr; + } +/* For each side in side set, use the appropriate lookup table to + determine the nodes from the connect array. */ + + elem_num = side_set_elem_list[ss_elem_ndx[j]]-1;/* element number 0-based*/ + /* calculate the relative element number position in it's block*/ + + elem_num_pos = elem_num - + (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_ctr - + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_elem_in_blk); + + /* calculate the beginning of the node list for this element by + using the ss_elem_node_ndx index into the side_sets_node_index + and adding the element number position * number of nodes per elem */ + + num_nodes_per_elem = + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].num_nodes_per_elem; + node_pos = ss_elem_node_ndx[ss_elem_ndx[j]]; + connect_offset = num_nodes_per_elem*elem_num_pos; + side_num = side_set_side_list[ss_elem_ndx[j]]-1; + + switch (elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type_val) + { + case CIRCLE: + case SPHERE: + { /* Note: no side-node lookup table is used for this simple case */ + side_set_node_list[node_pos] = connect[connect_offset]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 1; /* 1 node object */ + break; + } + case TRUSS: + case BEAM: + { /* Note: no side-node lookup table is used for this simple case */ + side_set_node_list[node_pos] = connect[connect_offset]; + side_set_node_list[node_pos+1] = connect[connect_offset+1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 2; /* 2 node object */ + if (num_nodes_per_elem > 2) + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */ + side_set_node_list[node_pos+2] = connect[connect_offset+2]; + } + break; + } + case TRIANGLE: + { + if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid triangle edge number %d in file id %d", + side_num+1, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + return(EX_FATAL); + } + + if (ndim == 2) /* 2d TRIs */ + { + side_set_node_list[node_pos] = + connect[connect_offset+tri_table[side_num][0]-1]; + side_set_node_list[node_pos+1] = + connect[connect_offset+tri_table[side_num][1]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 2; /* 2 node object */ + if (num_nodes_per_elem > 3) /* 6-node TRI */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */ + side_set_node_list[node_pos+2] = + connect[connect_offset+tri_table[side_num][2]-1]; + } + } + else if (ndim == 3) /* 3d TRIs */ + { + side_set_node_list[node_pos] = + connect[connect_offset+tri3_table[side_num][0]-1]; + side_set_node_list[node_pos+1] = + connect[connect_offset+tri3_table[side_num][1]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 2; /* 2 node object */ + if (side_num+1 <= 2) /* 3- or 6-node face */ + { + if (num_nodes_per_elem == 3) /* 3-node face */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */ + side_set_node_list[node_pos+2] = + connect[connect_offset+tri3_table[side_num][2]-1]; + } + else /* 6-node face */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node object */ + side_set_node_list[node_pos+2] = + connect[connect_offset+tri3_table[side_num][2]-1]; + side_set_node_list[node_pos+3] = + connect[connect_offset+tri3_table[side_num][3]-1]; + side_set_node_list[node_pos+4] = + connect[connect_offset+tri3_table[side_num][4]-1]; + side_set_node_list[node_pos+5] = + connect[connect_offset+tri3_table[side_num][5]-1]; + } + } + else /* 2- or 3-node edge */ + { + if (num_nodes_per_elem > 3) /* 3-node edge */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */ + side_set_node_list[node_pos+2] = + connect[connect_offset+tri3_table[side_num][2]-1]; + } + } + } + break; + } + case QUAD: + { + if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid quad edge number %d in file id %d", + side_num+1, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + return(EX_FATAL); + } + + side_set_node_list[node_pos] = + connect[connect_offset+quad_table[side_num][0]-1]; + side_set_node_list[node_pos+1] = + connect[connect_offset+quad_table[side_num][1]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 2; /* 2 node object */ + if (num_nodes_per_elem > 5) + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */ + side_set_node_list[node_pos+2] = + connect[connect_offset+quad_table[side_num][2]-1]; + } + break; + } + case SHELL: + { + if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid shell face number %d in file id %d", + side_num+1, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + return(EX_FATAL); + } + + side_set_node_list[node_pos] = + connect[connect_offset+shell_table[side_num][0]-1]; + side_set_node_list[node_pos+1] = + connect[connect_offset+shell_table[side_num][1]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 2; /* 2 node object */ + if (num_nodes_per_elem > 2) /*** KLUDGE for 2D shells ***/ + { + if (side_num+1 <= 2) /* 4-node face */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 4; /* 4 node object */ + side_set_node_list[node_pos+2] = + connect[connect_offset+shell_table[side_num][2]-1]; + side_set_node_list[node_pos+3] = + connect[connect_offset+shell_table[side_num][3]-1]; + } + } + if (num_nodes_per_elem == 8) + { + if (side_num+1 <= 2) /* 8-node face */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */ + side_set_node_list[node_pos+4] = + connect[connect_offset+shell_table[side_num][4]-1]; + side_set_node_list[node_pos+5] = + connect[connect_offset+shell_table[side_num][5]-1]; + side_set_node_list[node_pos+6] = + connect[connect_offset+shell_table[side_num][6]-1]; + side_set_node_list[node_pos+7] = + connect[connect_offset+shell_table[side_num][7]-1]; + } + else + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node edge */ + side_set_node_list[node_pos+2] = + connect[connect_offset+shell_table[side_num][2]-1]; + } + } + break; + } + case TETRA: + { + if (side_num+1 < 1 || side_num+1 > 4) /* side number range check */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid tetra face number %d in file id %d", + side_num+1, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + return(EX_FATAL); + } + + side_set_node_list[node_pos] = + connect[connect_offset+tetra_table[side_num][0]-1]; + side_set_node_list[node_pos+1] = + connect[connect_offset+tetra_table[side_num][1]-1]; + side_set_node_list[node_pos+2] = + connect[connect_offset+tetra_table[side_num][2]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node object */ + if (num_nodes_per_elem == 8) + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 4; /* 4 node object */ + side_set_node_list[node_pos+3] = + connect[connect_offset+tetra_table[side_num][3]-1]; + } + else if (num_nodes_per_elem > 8) + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node object */ + side_set_node_list[node_pos+3] = + connect[connect_offset+tetra_table[side_num][3]-1]; + side_set_node_list[node_pos+4] = + connect[connect_offset+tetra_table[side_num][4]-1]; + side_set_node_list[node_pos+5] = + connect[connect_offset+tetra_table[side_num][5]-1]; + } + break; + } + case WEDGE: + { + if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid wedge face number %d in file id %d", + side_num+1, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + return(EX_FATAL); + } + + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][0]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][1]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][2]-1]; + + if (wedge_table[side_num][3] == 0) { /* degenerate side? */ + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node side */ + } + else + { + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][3]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 4; /* 4 node side */ + } + + + if (num_nodes_per_elem > 6) + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */ + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][4]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][5]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][6]-1]; + + if (wedge_table[side_num][7] == 0) /* degenerate side? */ + side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node side */ + else + { + side_set_node_list[node_pos++] = + connect[connect_offset+wedge_table[side_num][7]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node side */ + } + } + break; + } + case PYRAMID: + { + if (side_num+1 < 1 || side_num+1 > 5) /* side number range check */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid pyramid face number %d in file id %d", + side_num+1, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + return(EX_FATAL); + } + + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][0]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][1]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][2]-1]; + + if (pyramid_table[side_num][3] == 0) { /* degenerate side? */ + side_set_node_cnt_list[ss_elem_ndx[j]] = 3; /* 3 node side */ + } + else + { + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][3]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 4; /* 4 node side */ + } + + + if (num_nodes_per_elem > 5) + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */ + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][4]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][5]-1]; + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][6]-1]; + + if (pyramid_table[side_num][7] == 0) /* degenerate side? */ + side_set_node_cnt_list[ss_elem_ndx[j]] = 6; /* 6 node side */ + else + { + side_set_node_list[node_pos++] = + connect[connect_offset+pyramid_table[side_num][7]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node side */ + } + } + break; + } + case HEX: + { + if (side_num+1 < 1 || side_num+1 > 6) /* side number range check */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid hex face number %d in file id %d", + side_num+1, exoid); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + free(connect); + free(elem_blk_parms); + free(elem_blk_ids); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(ss_parm_ndx); + free(side_set_side_list); + free(side_set_elem_list); + return(EX_FATAL); + } + + side_set_node_list[node_pos] = + connect[connect_offset+hex_table[side_num][0]-1]; + side_set_node_list[node_pos+1] = + connect[connect_offset+hex_table[side_num][1]-1]; + side_set_node_list[node_pos+2] = + connect[connect_offset+hex_table[side_num][2]-1]; + side_set_node_list[node_pos+3] = + connect[connect_offset+hex_table[side_num][3]-1]; + side_set_node_cnt_list[ss_elem_ndx[j]] = 4; /* 4 node object */ + if (num_nodes_per_elem > 12) /* more nodes than HEXSHELL */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 8; /* 8 node object */ + side_set_node_list[node_pos+4] = + connect[connect_offset+hex_table[side_num][4]-1]; + side_set_node_list[node_pos+5] = + connect[connect_offset+hex_table[side_num][5]-1]; + side_set_node_list[node_pos+6] = + connect[connect_offset+hex_table[side_num][6]-1]; + side_set_node_list[node_pos+7] = + connect[connect_offset+hex_table[side_num][7]-1]; + } + if (num_nodes_per_elem == 27) /* 27-node brick */ + { + side_set_node_cnt_list[ss_elem_ndx[j]] = 9; /* 9 node object */ + side_set_node_list[node_pos+8] = + connect[connect_offset+hex_table[side_num][8]-1]; + } + break; + } + default: + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: %s is an unsupported element type", + elem_blk_parms[ss_parm_ndx[ss_elem_ndx[j]]].elem_type); + ex_err("ex_get_side_set_node_list",errmsg,exerrval); + return(EX_FATAL); + } + } + } + + + /* All done: release connectivity array space, element block ids array, + element block parameters array, and side set element index array */ + free(connect); + free(ss_parm_ndx); + free(elem_blk_ids); + free(elem_blk_parms); + free(ss_elem_ndx); + free(ss_elem_node_ndx); + free(side_set_side_list); + free(side_set_elem_list); + + return(EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgtim.c b/Utilities/vtkexodus2/exgtim.c new file mode 100644 index 0000000..775d558 --- /dev/null +++ b/Utilities/vtkexodus2/exgtim.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgtim - ex_get_time +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step time step number +* +* exit conditions - +* float time_value simulation time at specified step +* +* revision history - +* +* $Id: exgtim.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the time value for a specified time step; + * assume the first time step is 1 + */ + +int ex_get_time (int exoid, + int time_step, + void *time_value) +{ + int varid; + long start[1]; + char var_name[MAX_VAR_NAME_LENGTH+1]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire previously defined dimensions */ + + strcpy (var_name, VAR_WHOLE_TIME); + +/* inquire previously defined variable */ + + if ((varid = ncvarid (exoid, var_name)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate time variable in file id %d", exoid); + ex_err("ex_get_time",errmsg,exerrval); + return (EX_FATAL); + } + +/* read time value */ + + start[0] = --time_step; + + if (ncvarget1 (exoid, varid, start, + ex_conv_array(exoid,RTN_ADDRESS,time_value,1)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get time value in file id %d", exoid); + ex_err("ex_get_time",errmsg,exerrval); + return (EX_FATAL); + } + + + ex_conv_array( exoid, READ_CONVERT, time_value, 1 ); + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/exgvan.c b/Utilities/vtkexodus2/exgvan.c new file mode 100644 index 0000000..4ef4815 --- /dev/null +++ b/Utilities/vtkexodus2/exgvan.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exgvan - ex_get_var_names +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* char* var_type variable type: G,N, or E +* int num_vars # of variables to read +* +* exit conditions - +* char* var_names ptr array of variable names +* +* revision history - +* +* $Id: exgvan.c,v 1.2 2005/07/19 22:11:53 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the names of the results variables from the database + */ + +int ex_get_var_names (int exoid, + const char *var_type, + int num_vars, + char *var_names[]) +{ + int i, varid, status; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* inquire previously defined variables */ + if (*var_type == 'g' || *var_type == 'G') { + if ((varid = ncvarid (exoid, VAR_NAME_GLO_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no global variables names stored in file id %d", exoid); + ex_err("ex_get_var_names",errmsg,exerrval); + return (EX_WARN); + } + } + + else if (*var_type == 'n' || *var_type == 'N') { + if ((varid = ncvarid (exoid, VAR_NAME_NOD_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no nodal variable names stored in file id %d", + exoid); + ex_err("ex_get_var_names",errmsg,exerrval); + return (EX_WARN); + } + + } + + else if (*var_type == 'e' || *var_type == 'E') { + + if ((varid = ncvarid (exoid, VAR_NAME_ELE_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no element variable names stored in file id %d", + exoid); + ex_err("ex_get_var_names",errmsg,exerrval); + return (EX_WARN); + } + } + + else /* invalid variable type */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid variable type %c specified in file id %d", + *var_type, exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + return (EX_WARN); + } + + + /* read the variable names */ + + /* + * See if reading into contiguous memory in which case we can load + * all values in one call. If not, we must load each name individually. + */ + if ((size_t)(&var_names[num_vars-1][0] - &var_names[0][0]) == + sizeof(char)*(MAX_STR_LENGTH+1)*(num_vars-1)) { + status = nc_get_var_text(exoid, varid, &var_names[0][0]); + if (status == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get results variable names from file id %d", exoid); + ex_err("ex_get_var_names",errmsg,exerrval); + return (EX_FATAL); + } + } else { + for (i=0; i +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * reads the EXODUS II element variable truth table from the database + */ + +int ex_get_elem_var_tab (int exoid, + int num_elem_blk, + int num_elem_var, + int *elem_var_tab) +{ + int dimid, varid, i, j, iresult; + long idum, start[2], count[2]; + nclong *longs; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions */ + + if ((dimid = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element blocks in file id %d", + exoid); + ex_err("ex_get_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &idum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_get_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + + if (idum != num_elem_blk) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: # of element blocks doesn't match those defined in file id %d", + exoid); + ex_err("ex_get_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((dimid = ncdimid (exoid, DIM_NUM_ELE_VAR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no element variables stored in file id %d", + exoid); + ex_err("ex_get_elem_var_tab",errmsg,exerrval); + return (EX_WARN); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &idum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element variables in file id %d", + exoid); + ex_err("ex_get_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + + if (idum != num_elem_var) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: # of element variables doesn't match those defined in file id %d", + exoid); + ex_err("ex_get_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + if ((varid = ncvarid (exoid, VAR_ELEM_TAB)) == -1) + { + + /* since truth table isn't stored in the data file, derive it dynamically */ + /* printf("[exgvtt] building truth table on the fly ...\n"); */ + + for (j=0; j +#include "exodusII.h" +#include "exodusII_int.h" + +static void flt_cvt(float *xptr,double x) +{ + *xptr = (float)x; +} + +/* + * returns information about the database + */ + +int ex_inquire (int exoid, + int req_info, + int *ret_int, + void *ret_float, + char *ret_char) +{ + int dimid, varid, i, tmp_num, *ids; + long ldum, num_sets, start[2], count[2]; + nclong *stat_vals; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + switch (req_info) + { + case EX_INQ_FILE_TYPE: + + /* obsolete call */ + /*returns "r" for regular EXODUS II file or "h" for history EXODUS file*/ + + *ret_char = '\0'; + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Warning: file type inquire is obsolete"); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_WARN); + + case EX_INQ_API_VERS: + +/* returns the EXODUS II API version number */ + + if (ncattget (exoid, NC_GLOBAL, ATT_API_VERSION, ret_float) == -1) + { /* try old (prior to db version 2.02) attribute name */ + if (ncattget (exoid, NC_GLOBAL, ATT_API_VERSION_BLANK,ret_float) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get EXODUS API version for file id %d", exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + } + + break; + + case EX_INQ_DB_VERS: + +/* returns the EXODUS II database version number */ + + if (ncattget (exoid, NC_GLOBAL, ATT_VERSION, ret_float) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get EXODUS database version for file id %d", exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + + break; + + case EX_INQ_LIB_VERS: + +/* returns the EXODUS II Library version number */ + + flt_cvt((float *)ret_float, EX_API_VERS); + + break; + + case EX_INQ_TITLE: + +/* returns the title of the database */ + + if (ncattget (exoid, NC_GLOBAL, ATT_TITLE, ret_char) == -1) + { + *ret_char = '\0'; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get database title for file id %d", exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + + break; + + case EX_INQ_DIM: + +/* returns the dimensionality (2 or 3, for 2-d or 3-d) of the database */ + + if ((dimid = ncdimid (exoid, DIM_NUM_DIM)) == -1) + { + *ret_int = 0; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate database dimensionality in file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &ldum) == -1) + { + *ret_int = 0; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get database dimensionality for file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + *ret_int = ldum; + + break; + + case EX_INQ_NODES: + +/* returns the number of nodes */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NODES)) == -1) + { + *ret_int = 0; + } else { + + if (ncdiminq (exoid, dimid, (char *) 0, &ldum) == -1) + { + *ret_int = 0; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes for file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + *ret_int = ldum; + } + break; + + case EX_INQ_ELEM: + +/* returns the number of elements */ + + if ((dimid = ncdimid (exoid, DIM_NUM_ELEM)) == -1) + { + *ret_int = 0; + } else { + + if (ncdiminq (exoid, dimid, (char *) 0, &ldum) == -1) + { + *ret_int = 0; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements for file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + *ret_int = ldum; + } + break; + + case EX_INQ_ELEM_BLK: + +/* returns the number of element blocks */ + + if ((dimid = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + *ret_int = 0; + } else { + + if (ncdiminq (exoid, dimid, (char *) 0, &ldum) == -1) + { + *ret_int = 0; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks for file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + *ret_int = ldum; + } + + break; + + case EX_INQ_NODE_SETS: + +/* returns the number of node sets */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) < 0) + *ret_int = 0; /* no node sets defined */ + else + { + if (ncdiminq (exoid, dimid, (char *) 0, &ldum) == -1) + { + *ret_int = 0; + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of node sets in file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + *ret_int = ldum; + } + + break; + + case EX_INQ_NS_NODE_LEN: + +/* returns the length of the concatenated node sets node list */ + + *ret_int = 0; /* default value if no node sets are defined */ + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) != -1 ) + { + if (ncdiminq (exoid, dimid, (char *) 0, &num_sets) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of node sets in file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + + + if (!(ids = malloc(num_sets*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for node set ids for file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + + if (ex_get_node_set_ids (exoid, ids) == EX_FATAL) + { + sprintf(errmsg, + "Error: failed to get node sets in file id %d", + exoid); + /* pass back error code from ex_get_node_set_ids (in exerrval) */ + ex_err("ex_inquire",errmsg,exerrval); + free (ids); + return (EX_FATAL); + } + /* allocate space for stat array */ + if (!(stat_vals = malloc((int)num_sets*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + free (ids); + sprintf(errmsg, + "Error: failed to allocate memory for node set status array for file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + + /* get variable id of status array */ + if ((varid = ncvarid (exoid, VAR_NS_STAT)) != -1) + { + /* if status array exists, use it, otherwise assume, object exists + to be backward compatible */ + + start[0] = 0; + start[1] = 0; + count[0] = num_sets; + count[1] = 0; + + if (ncvarget (exoid, varid, start, count, (void *)stat_vals) == -1) + { + exerrval = ncerr; + free (ids); + free(stat_vals); + sprintf(errmsg, + "Error: failed to get node set status array from file id %d", + exoid); + ex_err("ex_inquire",errmsg,exerrval); + return (EX_FATAL); + } + } + else /* default: status is true */ + for(i=0;i +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * opens an existing EXODUS II file (or EXODUS II history file) and returns + * an id that can subsequently be used to refer to the file. Multiple files + * may be open simultaneously + */ + +int ex_open (const char *path, + int mode, + int *comp_ws, + int *io_ws, + float *version) +{ + int exoid; + nclong file_wordsize; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* set error handling mode to no messages, non-fatal errors */ + ex_opts(exoptval); /* call required to set ncopts first time through */ + + + if (mode == EX_READ) /* READ ONLY */ + { +#ifdef TFLOP + if ((exoid = ncopen (path, NC_NOWRITE)) < 0) +#else + if ((exoid = ncopen (path, NC_NOWRITE|NC_SHARE)) < 0) +#endif + { + /* NOTE: netCDF returns an id of -1 on an error - but no error code! */ + if (ncerr == 0) + exerrval = EX_FATAL; + else + exerrval = ncerr; + sprintf(errmsg,"Error: failed to open %s read only",path); + ex_err("ex_open",errmsg,exerrval); + return(EX_FATAL); + } + } + + else if (mode == EX_WRITE) /* READ/WRITE */ + { +#ifdef TFLOP + if ((exoid = ncopen (path, NC_WRITE)) < 0) +#else + if ((exoid = ncopen (path, NC_WRITE|NC_SHARE)) < 0) +#endif + { + /* NOTE: netCDF returns an id of -1 on an error - but no error code! */ + if (ncerr == 0) + exerrval = EX_FATAL; + else + exerrval = ncerr; + sprintf(errmsg,"Error: failed to open %s write only",path); + ex_err("ex_open",errmsg,exerrval); + return(EX_FATAL); + } + + /* turn off automatic filling of netCDF variables */ + + if (ncsetfill (exoid, NC_NOFILL) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to set nofill mode in file id %d", + exoid); + ex_err("ex_open", errmsg, exerrval); + return (EX_FATAL); + } + } + else + { + exerrval = EX_BADFILEMODE; + sprintf(errmsg,"Error: invalid file open mode: %d",mode); + ex_err("ex_open",errmsg,exerrval); + return (EX_FATAL); + } + +/* determine version of EXODUS II file, and the word size of + * floating point values stored in the file + */ + + if (ncattget (exoid, NC_GLOBAL, ATT_VERSION, version) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to get database version for file id: %d", + exoid); + ex_err("ex_open",errmsg,exerrval); + return(EX_FATAL); + } + +/* check ExodusII file version - old version 1.x files are not supported */ + if (*version < 2.0) + { + exerrval = EX_FATAL; + sprintf(errmsg,"Error: Unsupported file version %.2f in file id: %d", + *version, exoid); + ex_err("ex_open",errmsg,exerrval); + return(EX_FATAL); + } + + if (ncattget (exoid, NC_GLOBAL, ATT_FLT_WORDSIZE, &file_wordsize) == -1) + { /* try old (prior to db version 2.02) attribute name */ + if (ncattget (exoid,NC_GLOBAL,ATT_FLT_WORDSIZE_BLANK,&file_wordsize) == -1) + { + exerrval = EX_FATAL; + sprintf(errmsg,"Error: failed to get file wordsize from file id: %d", + exoid); + ex_err("ex_open",errmsg,exerrval); + return(exerrval); + } + } + +/* initialize floating point size conversion. + */ + + if (ex_conv_ini( exoid, comp_ws, io_ws, file_wordsize ) != EX_NOERR ) { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: failed to init conversion routines in file id %d", + exoid); + ex_err("ex_open", errmsg, exerrval); + return (EX_FATAL); + } + + return (exoid); +} diff --git a/Utilities/vtkexodus2/exopts.c b/Utilities/vtkexodus2/exopts.c new file mode 100644 index 0000000..3db37a5 --- /dev/null +++ b/Utilities/vtkexodus2/exopts.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exopts - ex_opts +* +* author - Sandia National Laboratories +* Vic Yarberry - Original +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int options error reporting options mask +* +* exit conditions - +* The internal error reporting options mask, exoptval, is set to the passed +* value - no error checking is done. +* +* revision history - +* +* $Id: exopts.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ +#include "exodusII.h" +#include "exodusII_int.h" + +/* init exoptval */ +#if defined(VERBOSE) +int exoptval = EX_VERBOSE; /* loud mode: set EX_VERBOSE */ +#else +#if defined (DEBUG) +int exoptval = EX_VERBOSE | EX_DEBUG;/* debug mode: set EX_VERBOSE & EX_DEBUG */ +#else +int exoptval = 0; /* set default global options value to NOT print error msgs*/ +#endif +#endif + +void ex_opts (int options) /* error reporting options mask */ +{ + static int first_time = TRUE; + exerrval = 0; /* clear error code */ + exoptval = options; + + if (first_time) /* set ncopts to quiet & no abort first time through */ + { + ncopts = 0; + first_time = FALSE; + } + + if (exoptval & EX_DEBUG) + ncopts = ncopts | NC_VERBOSE; /* debug mode: turn on netCDF verbose */ + else + ncopts = ncopts & !NC_VERBOSE; +} diff --git a/Utilities/vtkexodus2/expclb.c b/Utilities/vtkexodus2/expclb.c new file mode 100644 index 0000000..a311fc0 --- /dev/null +++ b/Utilities/vtkexodus2/expclb.c @@ -0,0 +1,458 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expclb - ex_put_concat_elem_block: write element block parameters +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* Greg Sjaardema - created this function to avoid ncredef calls. +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int idexo exodus file id +* char** elem_type element type string +* int* num_elem_this_blk number of elements in the element blk +* int* num_nodes_per_elem number of nodes per element block +* int* num_attr number of attributes +* int define_maps if != 0, write maps, else don't +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" +#include + +/* + * writes the parameters used to describe an element block + */ + +int ex_put_concat_elem_block (int exoid, + const int* elem_blk_id, + char *elem_type[], + const int* num_elem_this_blk, + const int* num_nodes_per_elem, + const int* num_attr, + int define_maps) +{ + int mapid, varid, dimid, dims[2], *elem_blk_id_ndx, elem_blk_stat; + int iblk; + int iresult; + long start[2], count[2], num_elem_blk; + nclong ldum, *lptr; + int cur_num_elem_blk, nelnoddim, numelbdim, numattrdim, connid, numelemdim, numnodedim; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; + + /* first check if any element blocks are specified + * OK if zero... + */ + + if ((dimid = (ncdimid (exoid, DIM_NUM_EL_BLK))) == -1 ) + { + return (EX_NOERR); + } + + /* Get number of element blocks defined for this file */ + if ((ncdiminq (exoid,dimid,cdum,&num_elem_blk)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + /* Next: Make sure that this is not a duplicate element block id by + searching the VAR_ID_EL_BLK array. + WARNING: This must be done outside of define mode because id_lkup accesses + the database to determine the position + */ + + if ((varid = ncvarid (exoid, VAR_ID_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element block ids in file id %d", exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + if (!(elem_blk_id_ndx= malloc(num_elem_blk*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for element block id index array in file id %d", + exoid); + ex_err("ex_put_concat_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + for (iblk = 0; iblk < num_elem_blk; iblk++) { + elem_blk_id_ndx[iblk] = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id[iblk]); + if (exerrval != EX_LOOKUPFAIL) /* found the element block id */ + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: element block id %d already exists in file id %d", + elem_blk_id[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + free(elem_blk_id_ndx); + return (EX_FATAL); + } + + /* Keep track of the total number of element blocks defined using a counter + stored in a linked list keyed by exoid. + NOTE: ex_get_file_item is a function that finds the number of element + blocks for a specific file and returns that value incremented. + */ + cur_num_elem_blk=ex_get_file_item(exoid, &eb_ctr_list); + if (cur_num_elem_blk >= num_elem_blk) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of element blocks (%ld) defined in file id %d", + num_elem_blk,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + free(elem_blk_id_ndx); + return (EX_FATAL); + } + + + /* NOTE: ex_get_file_item is a function that finds the number of element + blocks for a specific file and returns that value incremented. */ + + cur_num_elem_blk=ex_inc_file_item(exoid, &eb_ctr_list); + start[0] = (long)cur_num_elem_blk; + + /* write out element block id to previously defined id array variable*/ + + ldum = (nclong)elem_blk_id[iblk]; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element block id to file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + free(elem_blk_id_ndx); + return (EX_FATAL); + } + + elem_blk_id_ndx[iblk] = start[0]+1; /* element id index into VAR_ID_EL_BLK array*/ + + if (num_elem_this_blk[iblk] == 0) /* Is this a NULL element block? */ + elem_blk_stat = 0; /* change element block status to NULL */ + else + elem_blk_stat = 1; /* change element block status to TRUE */ + + if ((varid = ncvarid (exoid, VAR_STAT_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element block status in file id %d", exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + free(elem_blk_id_ndx); + return (EX_FATAL); + } + + ldum = (nclong)elem_blk_stat; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element id %d status to file id %d", + elem_blk_id[iblk], exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + free(elem_blk_id_ndx); + return (EX_FATAL); + } + } + + /* put netcdf file into define mode */ + + /* + ncsync(exoid); + */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + /* Iterate over element blocks ... */ + for (iblk = 0; iblk < num_elem_blk; iblk++) { + + if (num_elem_this_blk[iblk] == 0) /* Is this a NULL element block? */ + continue; + + /* define some dimensions and variables*/ + if ((numelbdim = ncdimdef (exoid, + DIM_NUM_EL_IN_BLK(elem_blk_id_ndx[iblk]), + (long)num_elem_this_blk[iblk])) == -1) + { + if (ncerr == NC_ENAMEINUSE) /* duplicate entry */ + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element block %d already defined in file id %d", + elem_blk_id[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of elements/block for block %d file id %d", + elem_blk_id[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + if ((nelnoddim = ncdimdef (exoid, + DIM_NUM_NOD_PER_EL(elem_blk_id_ndx[iblk]), + (long)num_nodes_per_elem[iblk])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of nodes/element for block %d in file id %d", + elem_blk_id[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* element attribute array */ + + if (num_attr[iblk] > 0) + { + + if ((numattrdim = ncdimdef (exoid, + DIM_NUM_ATT_IN_BLK(elem_blk_id_ndx[iblk]), + (long)num_attr[iblk])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of attributes in block %d in file id %d", + elem_blk_id[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + dims[0] = numelbdim; + dims[1] = numattrdim; + + if ((ncvardef (exoid, + VAR_ATTRIB(elem_blk_id_ndx[iblk]), nc_flt_code(exoid), 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define attributes for element block %d in file id %d", + elem_blk_id[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + + /* element connectivity array */ + + dims[0] = numelbdim; + dims[1] = nelnoddim; + + if ((connid = ncvardef (exoid, + VAR_CONN(elem_blk_id_ndx[iblk]), NC_LONG, 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create connectivity array for block %d in file id %d", + elem_blk_id[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* store element type as attribute of connectivity variable */ + + if ((ncattput (exoid, connid, ATT_NAME_ELB, NC_CHAR, strlen(elem_type[iblk])+1, + (void*)elem_type[iblk])) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element type name %s in file id %d", + elem_type[iblk],exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + } + free(elem_blk_id_ndx); + + /* Define the element map here to avoid a later redefine call */ + if (define_maps != 0) { + if (ncvarid(exoid, VAR_ELEM_NUM_MAP) == -1) { /* Map does not exist */ + /* Possible to have zero elements but >0 element blocks. + * Only define map if there are nonzero elements + */ + if ((numelemdim = ncdimid (exoid, DIM_NUM_ELEM)) != -1) + { + dims[0] = numelemdim; + + if ((mapid = ncvardef (exoid, VAR_ELEM_NUM_MAP, NC_LONG, 1, dims)) == -1) { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element numbering map already exists in file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create element numbering map in file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + } + } + /* Do the same for the node numbering map */ + if (ncvarid(exoid, VAR_NODE_NUM_MAP) == -1) { /* Map does not exist */ + if ((numnodedim = ncdimid (exoid, DIM_NUM_NODES)) != -1) + { + dims[0] = numnodedim; + if ((mapid = ncvardef (exoid, VAR_NODE_NUM_MAP, NC_LONG, 1, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node numbering map already exists in file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node numbering map array in file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + } + } + } + /* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete element block definition in file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + /* first get id of element block ids array variable */ + + if ((varid = ncvarid (exoid, VAR_ID_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element block ids array in file id %d", + exoid); + ex_err("ex_put_concat_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + /* then, write out element block id list */ + + /* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_elem_blk; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, varid, start, count, elem_blk_id); + } else { + lptr = itol (elem_blk_id, num_elem_blk); + iresult = ncvarput (exoid, varid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to element block id array in file id %d", + exoid); + ex_err("ex_put_concat_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + + /* Fatal error: exit definition mode and return */ + error_ret: + free(elem_blk_id_ndx); + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + } + (void)mapid; + return (EX_FATAL); +} + diff --git a/Utilities/vtkexodus2/expcns.c b/Utilities/vtkexodus2/expcns.c new file mode 100644 index 0000000..b945764 --- /dev/null +++ b/Utilities/vtkexodus2/expcns.c @@ -0,0 +1,469 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expcns - ex_put_concat_node_sets +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int* node_set_ids array of node set ids +* int* num_nodes_per_set array of number of nodes per set +* int* num_dist_per_set array of number of dist fact per set +* ----------pass in NULL for remaining args if just want to set params ------------- +* int* node_sets_node_index array of set indices into node list +* int* node_sets_df_index array of set indices into dist fact list +* int* node_set_node_list array of node list #'s for node set +* void* node_set_dist_fact array of dist factors for node set +* +* exit conditions - +* +* revision history - +* +* $Id: expcns.c,v 1.2 2005/07/19 22:11:53 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the node set ID's, node set count array, node set pointers array, + * and node set node list for all of the node sets + */ + +int ex_put_concat_node_sets (int exoid, + int *node_set_ids, + int *num_nodes_per_set, + int *num_dist_per_set, + int *node_sets_node_index, + int *node_sets_df_index, + int *node_sets_node_list, + void *node_sets_dist_fact) +{ + int i, num_node_sets, cur_num_node_sets, dimid, varid, dims[1], *ns_stat; + int iresult; + long start[1], count[1]; + nclong *lptr; + float fdum; + char *cdum; + float *flt_dist_fact; + double *dbl_dist_fact; + char errmsg[MAX_ERR_LENGTH]; + + (void)node_sets_df_index; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + +/* first check if any node sets are specified */ + + if (ncdimid (exoid, DIM_NUM_NS) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no node sets defined for file id %d", exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node sets defined in file id %d", exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + return (EX_FATAL); + } + +/* inquire how many node sets are to be stored */ + + if (ex_inquire(exoid, EX_INQ_NODE_SETS, &num_node_sets, &fdum, cdum) == -1) + { + sprintf(errmsg, + "Error: failed to get number of node sets defined for file id %d", + exoid); + /* use error val from inquire */ + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + + /* Fill out node set status array */ + + /* First, allocate space for the node set status list */ + if (!(ns_stat= malloc(num_node_sets*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for node set status array in file id %d", + exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + + for (i=0;i= num_node_sets) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of node sets (%d) defined in file id %d", + num_node_sets,exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + goto error_ret; + } + +/* NOTE: ex_inc_file_item is used to find the number of node sets + for a specific file and returns that value incremented. */ + + cur_num_node_sets=ex_inc_file_item(exoid, &ns_ctr_list ); + +/* define dimension for number of nodes in node set */ + + if (num_nodes_per_set[i] == 0) /* Is this a NULL node set? */ + continue; /* Do not create anything for NULL node sets! */ + + + if ((dimid = ncdimdef (exoid, DIM_NUM_NOD_NS(cur_num_node_sets+1), + (long)num_nodes_per_set[i])) == -1) + { + exerrval = ncerr; + if (ncerr == NC_ENAMEINUSE) + { + sprintf(errmsg, + "Error: node set %d already defined in file id %d", + node_set_ids[i],exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + else + { + sprintf(errmsg, + "Error: failed to define number of nodes for set %d in file id %d", + node_set_ids[i],exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + goto error_ret; + } + + +/* define variable to store node set node list here instead of in expns */ + + dims[0] = dimid; + if (ncvardef(exoid,VAR_NODE_NS(cur_num_node_sets+1),NC_LONG,1,dims) == -1) + { + exerrval = ncerr; + if (ncerr == NC_ENAMEINUSE) + { + sprintf(errmsg, + "Error: node set %d node list already defined in file id %d", + node_set_ids[i],exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + else + { + sprintf(errmsg, + "Error: failed to create node set %d node list in file id %d", + node_set_ids[i],exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + +/* Create variable for distribution factors if required */ + + if (num_dist_per_set[i] > 0) /* only define it if needed */ + { + /* num_dist_per_set should equal num_nodes_per_set */ + if (num_dist_per_set[i] != num_nodes_per_set[i]) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: # dist fact (%d) not equal to # nodes (%d) in node set %d file id %d", + num_dist_per_set[i], num_nodes_per_set[i], node_set_ids[i],exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + else + { + /* create variable for distribution factors */ + + if (ncvardef (exoid, VAR_FACT_NS(cur_num_node_sets+1), + nc_flt_code(exoid), 1, dims) == -1) + { + exerrval = ncerr; + if (ncerr == NC_ENAMEINUSE) + { + sprintf(errmsg, + "Error: node set %d dist factors already exist in file id %d", + node_set_ids[i],exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + else + { + sprintf(errmsg, + "Error: failed to create node set %d dist factors in file id %d", + node_set_ids[i],exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + } + } + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + +/* Next, fill out node set ids array */ + + /* first get id of node set ids array variable */ + + if ((varid = ncvarid (exoid, VAR_NS_IDS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node set ids array in file id %d", + exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + /* then, write out node set ids */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_node_sets; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, varid, start, count, node_set_ids); + } else { + lptr = itol (node_set_ids, num_node_sets); + iresult = ncvarput (exoid, varid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node set id array in file id %d", + exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + + /* If the node_sets_node_index is passed in as a NULL pointer, then + * the user only wants us to define the nodesets and not populate + * the data structures. + */ + if (node_sets_node_index == 0) + return(EX_NOERR); + + /* Now, use ExodusII call to store node lists */ + + for (i=0; i 0) /* only store if they exist */ + { + if (ex_put_node_set_dist_fact(exoid, node_set_ids[i], + &( flt_dist_fact[node_sets_node_index[i]])) == -1) + { + sprintf(errmsg, + "Error: failed to store node set %d dist factors for file id %d", + node_set_ids[i],exoid); + /* use error val from exodusII routine */ + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + } + } + else if( ex_comp_ws(exoid) == sizeof(double)) /* 8-byte float word */ + { + dbl_dist_fact = node_sets_dist_fact; + if (ex_put_node_set(exoid, node_set_ids[i], + &(node_sets_node_list[node_sets_node_index[i]])) == -1) + { + sprintf(errmsg, + "Error: failed to store node set %d for file id %d", + node_set_ids[i],exoid); + /* use error val from exodusII routine */ + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + if (num_dist_per_set[i] > 0) /* only store if they exist */ + { + if (ex_put_node_set_dist_fact(exoid, node_set_ids[i], + &( dbl_dist_fact[node_sets_node_index[i]])) == -1) + { + sprintf(errmsg, + "Error: failed to store node set %d dist factors for file id %d", + node_set_ids[i],exoid); + /* use error val from exodusII routine */ + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + return (EX_FATAL); + } + } + } + else + { + /* unknown floating point word size */ + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: unsupported floating point word size %d for file id %d", + ex_comp_ws(exoid), exoid); + ex_err("ex_put_concat_node_sets", errmsg, exerrval); + return (EX_FATAL); + } + } + + return (EX_NOERR); + + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_concat_node_sets",errmsg,exerrval); + } + return (EX_FATAL); + +} diff --git a/Utilities/vtkexodus2/expcon.c b/Utilities/vtkexodus2/expcon.c new file mode 100644 index 0000000..e16a3ef --- /dev/null +++ b/Utilities/vtkexodus2/expcon.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expcon - ex_put_coord_names +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* char* coord_names ptr array of coordinate names +* +* exit conditions - +* +* revision history - +* +* $Id: expcon.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" +#include +/* + * writes the names of the coordinate arrays to the database + */ + +int ex_put_coord_names (int exoid, + char *coord_names[]) +{ + int i, ndimdim, varid; + long num_dim, start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire previously defined dimensions */ + + if ((ndimdim = ncdimid (exoid, DIM_NUM_DIM)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of dimensions in file id %d", + exoid); + ex_err("ex_put_coord_names",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, ndimdim, (char *) 0, &num_dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: inquire failed to get number of dimensions in file id %d", + exoid); + ex_err("ex_put_coord_names",errmsg,exerrval); + return (EX_FATAL); + } + + if ((varid = ncvarid (exoid, VAR_NAME_COOR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate coordinate names in file id %d", + exoid); + ex_err("ex_put_coord_names",errmsg,exerrval); + return (EX_FATAL); + } + + +/* write out coordinate names */ + + for (i=0; i 1) { + if ((coordidy = ncvarid (exoid, VAR_COORD_Y)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate y nodal coordinates in file id %d", exoid); + ex_err("ex_put_coord",errmsg,exerrval); + return (EX_FATAL); + } + } else { + coordidy = 0; + } + if (num_dim > 2) { + if ((coordidz = ncvarid (exoid, VAR_COORD_Z)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate z nodal coordinates in file id %d", exoid); + ex_err("ex_put_coord",errmsg,exerrval); + return (EX_FATAL); + } + } else { + coordidz = 0; + } + /* write out the coordinates */ + for (i=0; i +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the side set ID's, side set element count array, + * side set element pointers array, side set element list, + * side set side list, and distribution factors list. + */ + +int ex_put_concat_side_sets (int exoid, + const int *side_set_ids, + const int *num_elem_per_set, + const int *num_dist_per_set, + const int *side_sets_elem_index, + const int *side_sets_dist_index, + const int *side_sets_elem_list, + const int *side_sets_side_list, + const void *side_sets_dist_fact) +{ + char *cdum; + int i, num_side_sets, cur_num_side_sets, dimid, varid, dims[1], *ss_stat; + int iresult; + long start[1], count[1]; + nclong *lptr; + float fdum; + const float *flt_dist_fact; + const double *dbl_dist_fact; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; /* initialize even though it is not used */ + +/* first check if any side sets are specified */ + + if (ncdimid (exoid, DIM_NUM_SS) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no side sets defined for file id %d", exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate side sets defined in file id %d", exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + return (EX_FATAL); + } + +/* inquire how many side sets are to be stored */ + + if (ex_inquire(exoid, EX_INQ_SIDE_SETS, &num_side_sets, &fdum, cdum) == -1) + { + sprintf(errmsg, + "Error: failed to get number of side sets defined for file id %d", + exoid); + /* use error val from inquire */ + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + return (EX_FATAL); + } +/* fill out side set status array */ + + /* First, allocate space for the side set status list */ + if (!(ss_stat= malloc(num_side_sets*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate space for side set status array in file id %d", + exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + return (EX_FATAL); + } + + for (i=0;i= num_side_sets) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of side sets (%d) defined in file id %d", + num_side_sets,exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + goto error_ret; + } + +/* NOTE: ex_inc_file_item is used to find the number of side sets + for a specific file and returns that value incremented. */ + + cur_num_side_sets=ex_inc_file_item(exoid, &ss_ctr_list ); + +/* define dimension for number of sides/elements per side set */ + + if (num_elem_per_set[i] == 0) /* Is this a NULL side set? */ + continue; /* Do not create anything for NULL side sets! */ + + + if ((dimid = ncdimdef (exoid, DIM_NUM_SIDE_SS(cur_num_side_sets+1), + (long)num_elem_per_set[i])) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: side set side count %d already defined in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of sides for set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + goto error_ret; + } + + /* create element list variable for side set */ + + dims[0] = dimid; + if (ncvardef (exoid,VAR_ELEM_SS(cur_num_side_sets+1),NC_LONG,1,dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element list already exists for side set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create element list for side set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + /* create side list variable for side set */ + + if (ncvardef (exoid,VAR_SIDE_SS(cur_num_side_sets+1),NC_LONG,1,dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: side list already exists for side set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create side list for side set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + + } + +/* define dimension for number of dist factors/nodes per side set */ + +/* NOTE: only define df count if the dist factors exist! */ + + if (num_dist_per_set[i] > 0) + { + + if ((dimid = ncdimdef (exoid, DIM_NUM_DF_SS(cur_num_side_sets+1), + (long)num_dist_per_set[i])) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: side set df count %d already defined in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define side set df count for set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + goto error_ret; + } + + /* create distribution factor list variable for side set */ + + dims[0] = dimid; + if (ncvardef (exoid, VAR_FACT_SS(cur_num_side_sets+1), + nc_flt_code(exoid), 1, dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: dist factor list already exists for side set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create dist factor list for side set %d in file id %d", + side_set_ids[i],exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + } /* end define dist factors */ + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + return (EX_FATAL); + } + +/* Next, fill out side set ids array */ + + /* first get id of side set ids array variable */ + + if ((varid = ncvarid (exoid, VAR_SS_IDS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate side set ids array in file id %d", + exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + return (EX_FATAL); + } + + /* then, write out side set id list */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_side_sets; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, varid, start, count, side_set_ids); + } else { + lptr = itol (side_set_ids, num_side_sets); + iresult = ncvarput (exoid, varid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store side set id array in file id %d", + exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + return (EX_FATAL); + } + + /* If the side_sets_elem_index is passed in as a NULL pointer, then + * the user only wants us to define the sidesets and not populate + * the data structures. + */ + if (side_sets_elem_index == 0) + return(EX_NOERR); + + /* Now, use ExodusII call to store side sets */ + for (i=0; i 0) /* store dist factors if required */ + { + if (ex_put_side_set_dist_fact(exoid, side_set_ids[i], + &(flt_dist_fact[side_sets_dist_index[i]])) == -1) + { + sprintf(errmsg, + "Error: failed to store side set %d dist factors for file id %d", + side_set_ids[i],exoid); + /* use error val from exodusII routine */ + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + return (EX_FATAL); + } + } + } + else if (ex_comp_ws(exoid) == sizeof(double)) + { + dbl_dist_fact = side_sets_dist_fact; + if (ex_put_side_set(exoid, side_set_ids[i], + &(side_sets_elem_list[side_sets_elem_index[i]]), + &(side_sets_side_list[side_sets_elem_index[i]])) == -1) + return(EX_FATAL); /* error will be reported by subroutine */ + if (num_dist_per_set[i] > 0) /* only store if they exist */ + { + if (ex_put_side_set_dist_fact(exoid, side_set_ids[i], + &(dbl_dist_fact[side_sets_dist_index[i]])) == -1) + { + sprintf(errmsg, + "Error: failed to store side set %d dist factors for file id %d", + side_set_ids[i],exoid); + /* use error val from exodusII routine */ + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + return (EX_FATAL); + } + } + } + else + { + /* unknown floating point word size */ + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: unsupported floating point word size %d for file id %d", + ex_comp_ws(exoid), exoid); + ex_err("ex_put_concat_side_sets", errmsg, exerrval); + return (EX_FATAL); + } + } + + return(EX_NOERR); + + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_concat_side_sets",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expeat.c b/Utilities/vtkexodus2/expeat.c new file mode 100644 index 0000000..78aa803 --- /dev/null +++ b/Utilities/vtkexodus2/expeat.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expeat - ex_put_elem_attr +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int elem_blk_id element block id +* float* attrib array of attributes +* +* exit conditions - +* +* revision history - +* +* $Id: expeat.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the attributes for an element block + */ + +int ex_put_elem_attr (int exoid, + int elem_blk_id, + const void *attrib) +{ + int numelbdim, numattrdim, attrid, elem_blk_id_ndx; + long num_elem_this_blk, num_attr, start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* Determine index of elem_blk_id in VAR_ID_EL_BLK array */ + elem_blk_id_ndx = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no attributes allowed for NULL block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_attr",errmsg,EX_MSG); + return (EX_WARN); /* no attributes for this element block */ + } + else + { + sprintf(errmsg, + "Error: no element block id %d in %s array in file id %d", + elem_blk_id, VAR_ID_EL_BLK, exoid); + ex_err("ex_put_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions */ + + if ((numelbdim = ncdimid (exoid, DIM_NUM_EL_IN_BLK(elem_blk_id_ndx))) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element block with id %d in file id %d", + elem_blk_id, exoid); + ex_err("ex_put_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of elements for block %d in file id %d", + elem_blk_id, exoid); + ex_err("ex_put_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + } + + + if (ncdiminq (exoid, numelbdim, (char *) 0, &num_elem_this_blk) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((numattrdim = ncdimid(exoid, DIM_NUM_ATT_IN_BLK(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: number of attributes not defined for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_attr",errmsg,EX_MSG); + return (EX_FATAL); /* number of attributes not defined */ + } + + if (ncdiminq (exoid, numattrdim, (char *) 0, &num_attr) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of attributes for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + if ((attrid = ncvarid (exoid, VAR_ATTRIB(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate attribute variable for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + +/* write out the attributes */ + + start[0] = 0; + start[1] = 0; + + count[0] = num_elem_this_blk; + count[1] = num_attr; + + if (ncvarput (exoid, attrid, start, count, + ex_conv_array(exoid,WRITE_CONVERT,attrib, + (int)num_attr*num_elem_this_blk)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put attributes for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_attr",errmsg,exerrval); + return (EX_FATAL); + } + + + return(EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/expelb.c b/Utilities/vtkexodus2/expelb.c new file mode 100644 index 0000000..1d57b66 --- /dev/null +++ b/Utilities/vtkexodus2/expelb.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expelb - ex_put_elem_block: write element block parameters +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int idexo exodus file id +* char* elem_type element type string +* int num_elem_this_blk number of elements in the element blk +* int num_nodes_per_elem number of nodes per element block +* int num_attr number of attributes +* +* exit conditions - +* +* revision history - +* +* $Id: expelb.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" +#include + +/* + * writes the parameters used to describe an element block + */ + +int ex_put_elem_block (int exoid, + int elem_blk_id, + const char *elem_type, + int num_elem_this_blk, + int num_nodes_per_elem, + int num_attr) +{ + int varid, dimid, dims[2], elem_blk_id_ndx, elem_blk_stat; + long start[2], num_elem_blk; + nclong ldum; + int cur_num_elem_blk, nelnoddim, numelbdim, numattrdim, connid; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; + +/* first check if any element blocks are specified */ + + if ((dimid = (ncdimid (exoid, DIM_NUM_EL_BLK))) == -1 ) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element blocks defined in file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + +/* Get number of element blocks defined for this file */ + if ((ncdiminq (exoid,dimid,cdum,&num_elem_blk)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + +/* Next: Make sure that this is not a duplicate element block id by + searching the VAR_ID_EL_BLK array. + WARNING: This must be done outside of define mode because id_lkup accesses + the database to determine the position +*/ + + if ((varid = ncvarid (exoid, VAR_ID_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element block ids in file id %d", exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + elem_blk_id_ndx = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id); + if (exerrval != EX_LOOKUPFAIL) /* found the element block id */ + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: element block id %d already exists in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + +/* Keep track of the total number of element blocks defined using a counter + stored in a linked list keyed by exoid. + NOTE: ex_get_file_item is a function that finds the number of element + blocks for a specific file and returns that value incremented. +*/ + cur_num_elem_blk=ex_get_file_item(exoid, &eb_ctr_list); + if (cur_num_elem_blk >= num_elem_blk) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of element blocks (%ld) defined in file id %d", + num_elem_blk,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + +/* NOTE: ex_get_file_item is a function that finds the number of element + blocks for a specific file and returns that value incremented. */ + + cur_num_elem_blk=ex_inc_file_item(exoid, &eb_ctr_list); + start[0] = (long)cur_num_elem_blk; + +/* write out element block id to previously defined id array variable*/ + + ldum = (nclong)elem_blk_id; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element block id to file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + elem_blk_id_ndx = start[0]+1; /* element id index into VAR_ID_EL_BLK array*/ + + if (num_elem_this_blk == 0) /* Is this a NULL element block? */ + elem_blk_stat = 0; /* change element block status to NULL */ + else + elem_blk_stat = 1; /* change element block status to TRUE */ + + if ((varid = ncvarid (exoid, VAR_STAT_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element block status in file id %d", exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + ldum = (nclong)elem_blk_stat; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element id %d status to file id %d", + elem_blk_id, exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + if (num_elem_this_blk == 0) /* Is this a NULL element block? */ + { + return(EX_NOERR); + } + + + /* + * Check that storage required for connectivity array is less + * than 2GB which is maximum size permitted by netcdf + * (in large file mode). 1<<29 == max number of integer items. + */ + if (num_elem_this_blk * num_nodes_per_elem > (1<<29)) { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Size to store connectivity for element block %d exceeds 2GB in file id %d", + elem_blk_id, exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + /* put netcdf file into define mode */ + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + +/* define some dimensions and variables*/ + + if ((numelbdim = ncdimdef (exoid, + DIM_NUM_EL_IN_BLK(elem_blk_id_ndx), (long)num_elem_this_blk)) == -1) + { + if (ncerr == NC_ENAMEINUSE) /* duplicate entry */ + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element block %d already defined in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of elements/block for block %d file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + if ((nelnoddim = ncdimdef (exoid, + DIM_NUM_NOD_PER_EL(elem_blk_id_ndx), (long)num_nodes_per_elem)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of nodes/element for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + +/* element attribute array */ + + if (num_attr > 0) + { + + if ((numattrdim = ncdimdef (exoid, + DIM_NUM_ATT_IN_BLK(elem_blk_id_ndx), (long)num_attr)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of attributes in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + dims[0] = numelbdim; + dims[1] = numattrdim; + + if ((ncvardef (exoid, + VAR_ATTRIB(elem_blk_id_ndx), nc_flt_code(exoid), 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define attributes for element block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + +/* element connectivity array */ + + dims[0] = numelbdim; + dims[1] = nelnoddim; + + if ((connid = ncvardef (exoid, + VAR_CONN(elem_blk_id_ndx), NC_LONG, 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create connectivity array for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + +/* store element type as attribute of connectivity variable */ + + if ((ncattput (exoid, connid, ATT_NAME_ELB, NC_CHAR, strlen(elem_type)+1, + (void*) elem_type)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element type name %s in file id %d", + elem_type,exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete element block definition in file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_elem_block",errmsg,exerrval); + } + return (EX_FATAL); +} + diff --git a/Utilities/vtkexodus2/expelc.c b/Utilities/vtkexodus2/expelc.c new file mode 100644 index 0000000..f25b857 --- /dev/null +++ b/Utilities/vtkexodus2/expelc.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expelc - ex_put_elem_conn +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int elem_blk_id ID value +* int connect connectivity array +* +* exit conditions - +* +* revision history - +* +* $Id: expelc.c,v 1.2 2005/07/19 12:31:28 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* + * writes the connectivity array for an element block + */ + +int ex_put_elem_conn (int exoid, + int elem_blk_id, + const int *connect) +{ + int numelbdim, nelnoddim, connid, elem_blk_id_ndx, iresult; + long num_elem_this_blk, num_nod_per_elem, start[2], count[2]; + nclong *lptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* Determine index of elem_blk_id in VAR_ID_EL_BLK array */ + elem_blk_id_ndx = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, +"Warning: connectivity array not allowed for NULL element block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_conn",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + + sprintf(errmsg, + "Error: failed to locate element block id %d in %s array in file id %d", + elem_blk_id,VAR_ID_EL_BLK, exoid); + ex_err("ex_put_elem_conn",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions */ + + if ((numelbdim = ncdimid (exoid, DIM_NUM_EL_IN_BLK(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of elements in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_conn",errmsg, exerrval); + return(EX_FATAL); + } + + if (ncdiminq(exoid, numelbdim, NULL, &num_elem_this_blk) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_conn",errmsg,exerrval); + return(EX_FATAL); + } + + + if ((nelnoddim = ncdimid (exoid, DIM_NUM_NOD_PER_EL(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes/elem in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_conn",errmsg,exerrval); + return(EX_FATAL); + } + + if (ncdiminq (exoid, nelnoddim, NULL, &num_nod_per_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes/elem in block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_conn",errmsg,exerrval); + return(EX_FATAL); + } + + + if ((connid = ncvarid (exoid, VAR_CONN(elem_blk_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, +"Error: failed to locate connectivity array for element block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_conn",errmsg, exerrval); + return(EX_FATAL); + } + + +/* write out the connectivity array */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + start[1] = 0; + + count[0] = num_elem_this_blk; + count[1] = num_nod_per_elem; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, connid, start, count, connect); + } else { + lptr = itol (connect, (int)(num_elem_this_blk*num_nod_per_elem)); + iresult = ncvarput (exoid, connid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to write connectivity array for block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_conn",errmsg, exerrval); + return(EX_FATAL); + } + + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/expem.c b/Utilities/vtkexodus2/expem.c new file mode 100644 index 0000000..5cc62fb --- /dev/null +++ b/Utilities/vtkexodus2/expem.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expem - ex_put_elem_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int map_id element map id +* int *elem_map element map +* +* exit conditions - +* +* revision history - +* +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* initialize this once */ + +struct list_item* em_ctr_list = 0; + +/* + * writes an element map; this is a vector of integers of length number + * of elements + */ + +int ex_put_elem_map (int exoid, + int map_id, + const int *elem_map) +{ + int dimid, varid, dims[1], iresult; + long start[1]; + nclong ldum, *lptr; + long num_elem_maps, num_elem, count[1]; + int cur_num_elem_maps; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; + + + /* Make sure the file contains elements */ + if ((dimid = (ncdimid (exoid, DIM_NUM_ELEM))) == -1 ) + { + return (EX_NOERR); + } + +/* first check if any element maps are specified */ + + if ((dimid = (ncdimid (exoid, DIM_NUM_EM))) == -1 ) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element maps specified in file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* Check for duplicate element map id entry */ + ex_id_lkup(exoid,VAR_EM_PROP(1),map_id); + if (exerrval != EX_LOOKUPFAIL) /* found the element map id */ + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element map %d already defined in file id %d", + map_id,exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return(EX_FATAL); + } + +/* Get number of element maps initialized for this file */ + if ((ncdiminq (exoid,dimid,cdum,&num_elem_maps)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element maps in file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* Keep track of the total number of element maps defined using a counter stored + in a linked list keyed by exoid. + NOTE: ex_get_file_item is used to find the number of element maps + for a specific file and returns that value. +*/ + cur_num_elem_maps = ex_get_file_item(exoid, &em_ctr_list ); + if (cur_num_elem_maps >= num_elem_maps) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of element maps (%ld) specified in file id %d", + num_elem_maps,exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* NOTE: ex_inc_file_item is used to find the number of element maps + for a specific file and returns that value incremented. */ + + cur_num_elem_maps = ex_inc_file_item(exoid, &em_ctr_list ); + +/* write out information to previously defined variable */ + + /* first get id of variable */ + + if ((varid = ncvarid (exoid, VAR_EM_PROP(1))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element map ids in file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + + /* then, write out element map id */ + + start[0] = cur_num_elem_maps; + + ldum = (nclong)map_id; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element map id %d in file id %d", + map_id,exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* determine number of elements */ + + if ((dimid = (ncdimid (exoid, DIM_NUM_ELEM))) == -1 ) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: couldn't determine number of elements in file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* create variable array in which to store the element map */ + + dims[0] = dimid; + + if ((varid = + ncvardef(exoid,VAR_ELEM_MAP(cur_num_elem_maps+1),NC_LONG,1,dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element map %d already defined in file id %d", + map_id,exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create element map %d in file id %d", + map_id,exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* write out the element map */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_elem; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, varid, start, count, elem_map); + } else { + lptr = itol (elem_map, (int)num_elem); + iresult = ncvarput (exoid, varid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element map in file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expenm.c b/Utilities/vtkexodus2/expenm.c new file mode 100644 index 0000000..332eb3c --- /dev/null +++ b/Utilities/vtkexodus2/expenm.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expenm - ex_put_elem_num_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int* elem_map element numbering map array +* +* exit conditions - +* +* revision history - +* +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* + * writes out the element numbering map to the database; this allows + * element numbers to be non-contiguous + */ + +int ex_put_elem_num_map (int exoid, + const int *elem_map) +{ + int numelemdim, dims[1], mapid, iresult; + long num_elem, start[1], count[1]; + nclong *lptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* inquire id's of previously defined dimensions */ + + /* determine number of elements. Return if zero... */ + if ((numelemdim = ncdimid (exoid, DIM_NUM_ELEM)) == -1) + { + return (EX_NOERR); + } + + if (ncdiminq (exoid, numelemdim, (char *) 0, &num_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + /* put netcdf file into define mode */ + + if ((mapid = ncvarid (exoid, VAR_ELEM_NUM_MAP)) == -1) { + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + /* create a variable array in which to store the element numbering map */ + + dims[0] = numelemdim; + + if ((mapid = ncvardef (exoid, VAR_ELEM_NUM_MAP, NC_LONG, 1, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element numbering map already exists in file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create element numbering map in file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + + /* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + return (EX_FATAL); + } + } + + /* write out the element numbering map */ + + /* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_elem; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, mapid, start, count, elem_map); + } else { + lptr = itol (elem_map, (int)num_elem); + iresult = ncvarput (exoid, mapid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element numbering map in file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); + + /* Fatal error: exit definition mode and return */ + error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_elem_num_map",errmsg,exerrval); + } + return (EX_FATAL); +} + diff --git a/Utilities/vtkexodus2/expev.c b/Utilities/vtkexodus2/expev.c new file mode 100644 index 0000000..7cee23c --- /dev/null +++ b/Utilities/vtkexodus2/expev.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expev - ex_put_elem_var +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step time step number +* int elem_var_index element variable index +* int elem_blk_id element block id +* int num_elem_this_blk number of elements in this block +* +* exit conditions - +* +* +* exit conditions - +* +* revision history - +* +* $Id: expev.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the values of a single element variable for one element block at + * one time step to the database; assume the first time step and + * element variable index are 1 + */ + +int ex_put_elem_var (int exoid, + int time_step, + int elem_var_index, + int elem_blk_id, + int num_elem_this_blk, + const void *elem_var_vals) +{ + int varid, dimid,time_dim, numelbdim, dims[2], elem_blk_id_ndx; + long num_elem_blk, num_elem_var, start[2], count[2]; + nclong *elem_var_tab; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* Determine index of elem_blk_id in VAR_ID_EL_BLK array */ + elem_blk_id_ndx = ex_id_lkup(exoid,VAR_ID_EL_BLK,elem_blk_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no variables allowed for NULL block %d in file id %d", + elem_blk_id,exoid); + ex_err("ex_put_elem_var",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + sprintf(errmsg, + "Error: failed to locate element block id %d in %s array in file id %d", + elem_blk_id, VAR_ID_EL_BLK, exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + } + + if ((varid = ncvarid (exoid, + VAR_ELEM_VAR(elem_var_index,elem_blk_id_ndx))) == -1) + { + if (ncerr == NC_ENOTVAR) /* variable doesn't exist, create it! */ + { + +/* inquire previously defined dimensions */ + + /* check for the existance of an element variable truth table */ + if ((varid = ncvarid (exoid, VAR_ELEM_TAB)) != -1) + { + /* find out number of element blocks and element variables */ + if ((dimid = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element blocks in file id %d", + exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem_blk) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + if ((dimid = ncdimid (exoid, DIM_NUM_ELE_VAR)) == -1) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: no element variables stored in file id %d", + exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_elem_var) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element variables in file id %d", + exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + if (!(elem_var_tab = malloc(num_elem_blk*num_elem_var*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element variable truth table in file id %d", + exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + /* read in the element variable truth table */ + + start[0] = 0; + start[1] = 0; + + count[0] = num_elem_blk; + count[1] = num_elem_var; + + if (ncvarget (exoid, varid, start, count, elem_var_tab) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get truth table from file id %d", exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + if(elem_var_tab[num_elem_var*(elem_blk_id_ndx-1)+elem_var_index-1] + == 0L) + { + free(elem_var_tab); + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid element variable %d, block %d in file id %d", + elem_var_index, elem_blk_id, exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + free(elem_var_tab); + } + + if ((time_dim = ncdimid (exoid, DIM_TIME)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate time dimension in file id %d", exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + if ((numelbdim=ncdimid(exoid, DIM_NUM_EL_IN_BLK(elem_blk_id_ndx))) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: number of elements in element block %d not defined in file id %d", + elem_blk_id, exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of elements in element block %d in file id %d", + elem_blk_id, exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + } + goto error_ret; + } + +/* variable doesn't exist so put file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + +/* define netCDF variable to store element variable values */ + + dims[0] = time_dim; + dims[1] = numelbdim; + if ((varid = ncvardef(exoid,VAR_ELEM_VAR(elem_var_index,elem_blk_id_ndx), + nc_flt_code(exoid), 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define element variable %d in file id %d", + elem_var_index,exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + goto error_ret; + } + + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete element variable %s definition to file id %d", + VAR_ELEM_VAR(elem_var_index,elem_blk_id_ndx), exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element variable %s in file id %d", + VAR_ELEM_VAR(elem_var_index,elem_blk_id_ndx),exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* store element variable values */ + + start[0] = --time_step; + start[1] = 0; + + count[0] = 1; + count[1] = num_elem_this_blk; + + if (ncvarput (exoid, varid, start, count, + ex_conv_array(exoid,WRITE_CONVERT,elem_var_vals, + num_elem_this_blk)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element variable %d in file id %d", + elem_var_index,exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_elem_var",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expfrm.c b/Utilities/vtkexodus2/expfrm.c new file mode 100644 index 0000000..b0ad0e6 --- /dev/null +++ b/Utilities/vtkexodus2/expfrm.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expfrm - ex_put_coordinate_frames: write coordinate frames +* +* author - Sandia National Laboratories +* Garth Reese - created this function. Nov 2002. +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int nframes number of coordinate frames in model +* const int* cf_ids coordinate ids +* void* pt_coordinates pointer to coordinates. 9 values per +* coordinate frame +* const char* tags character tag for each frame. +* 'r' - rectangular +* 'c' - cylindrical +* 's' - spherical +* +* returns - +* EX_NOERR for no error +* EX_FATAL for fatal errors +* 1 number frames < 0 +* +*****************************************************************************/ + +#include +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* -------------------- local defines --------------------------- */ +#define PROCNAME "ex_put_coordinate_frames" +/* -------------------- end of local defines -------------------- */ +int ex_put_coordinate_frames( int exoid, int nframes, const int cf_ids[], + void* pt_coordinates, const char* tags) +{ + int dim, dim9; /* dimension id for nframes, nframes*9 */ + char errmsg[MAX_ERR_LENGTH]; /* buffer for error messages */ + int exerrval; /* returned error value */ + int varcoords; /* variable id for the coordinates */ + int varids; /* variable id for the frame ids */ + int vartags; /* variable id for the frame tags */ + long int start=0; /* start value for varputs */ + long int count=nframes; /* number vars to put in varput */ + long int count9=nframes*9; /* ditto, but for coordinates */ + int i; /* general indices */ + void* pt_c=0; /* pointer to size converted array */ + + + + if ( exoid < 0 ) + return exoid; + if ( nframes == 0 ) /* write nothing */ + return (EX_NOERR); + if ( nframes<0 ) + return 1; + assert( cf_ids!=0 ); + assert( pt_coordinates !=0 ); + assert( tags != 0 ); + + /* make the definitions */ + /* go into define mode. define num_frames, num_frames9 */ + if (ncredef (exoid) == -1){ + exerrval = ncerr; + sprintf(errmsg,"Error: failed to place file id %d into define mode", + exoid); + ex_err(PROCNAME,errmsg,exerrval); + return (EX_FATAL); + } + + if ( (dim=ncdimdef (exoid, NUM_CFRAMES, nframes)) == -1 || + (dim9=ncdimdef (exoid, NUM_CFRAME9, nframes*9))== -1 ){ + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of coordinate frames in file id %d", + exoid); + ex_err(PROCNAME,errmsg,exerrval); + goto error_ret; + } + + + /* define the variables. coordinates, tags and ids */ + if ((varcoords=ncvardef (exoid, FRAME_COORDS, + nc_flt_code(exoid), 1, &dim9)) == -1 || + (varids=ncvardef (exoid, FRAME_IDS,NC_INT, 1, &dim)) == -1 || + (vartags=ncvardef(exoid, FRAME_TAGS,NC_CHAR,1,&dim)) == -1 ) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define coordinate frames in file id %d", + exoid); + ex_err(PROCNAME,errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* leave define mode */ + if (ncendef (exoid) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete coordinate frame definition in file id %d", + exoid); + ex_err(PROCNAME,errmsg,exerrval); + return (EX_FATAL); + } + + /* check variables consistency */ + exerrval = EX_NOERR; + for (i=0;i + +/* + * writes information records to the database + */ + +int ex_put_info (int exoid, + int num_info, + char *info[]) +{ + int i, lindim, num_info_dim, dims[2], varid; + long start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* only do this if there are records */ + + if (num_info > 0) + { +/* inquire previously defined dimensions */ + + if ((lindim = ncdimid (exoid, DIM_LIN)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get line string length in file id %d", exoid); + ex_err("ex_put_info",errmsg,exerrval); + return (EX_FATAL); + } + + +/* put file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed put file id %d into define mode", exoid); + ex_err("ex_put_info",errmsg,exerrval); + return (EX_FATAL); + } + + +/* define dimensions */ + + if ((num_info_dim = ncdimdef (exoid, DIM_NUM_INFO, (long)num_info)) == -1) + { + if (ncerr == NC_ENAMEINUSE) /* duplicate entry? */ + { + exerrval = ncerr; + sprintf(errmsg, + "Error: info records already exist in file id %d", + exoid); + ex_err("ex_put_info",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of info records in file id %d", + exoid); + ex_err("ex_put_info",errmsg,exerrval); + } + + goto error_ret; /* exit define mode and return */ + } + + +/* define variable */ + + dims[0] = num_info_dim; + dims[1] = lindim; + + if ((varid = ncvardef (exoid, VAR_INFO, NC_CHAR, 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define info record in file id %d", + exoid); + ex_err("ex_put_info",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete info record definition in file id %d", + exoid); + ex_err("ex_put_info",errmsg,exerrval); + return (EX_FATAL); + } + + +/* write out information records */ + + for (i=0; i + +/* + * writes the initialization parameters to the EXODUS II file + */ + +int ex_put_init (int exoid, + const char *title, + int num_dim, + int num_nodes, + int num_elem, + int num_elem_blk, + int num_node_sets, + int num_side_sets) +{ + int numdimdim, numnoddim, elblkdim, strdim, dim[2], dimid, varid; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + if ((ncdimid (exoid, DIM_NUM_DIM)) != -1) + { + exerrval = EX_MSG; + sprintf(errmsg, + "Error: initialization already done for file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } + + + /* put file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } + + + /* define some attributes... */ + + if (ncattput (exoid, NC_GLOBAL, (const char*) ATT_TITLE, + NC_CHAR, strlen(title)+1, (void *)title) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define title attribute to file id %d", exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* ...and some dimensions... */ + + if ((numdimdim = ncdimdef (exoid, DIM_NUM_DIM, (long)num_dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of dimensions in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* + * Need to handle "empty file" that may be the result of a strange + * load balance or some other strange run. Note that if num_node + * == 0, then num_elem must be zero since you cannot have elements + * with no nodes. It *is* permissible to have zero elements with + * non-zero node count. + */ + + if (num_nodes > 0) { + if ((numnoddim = ncdimdef (exoid, DIM_NUM_NODES, (long)num_nodes)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of nodes in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + + if (num_elem > 0) { + if (num_nodes <= 0) { + exerrval = EX_MSG; + sprintf(errmsg, + "Error: Cannot have non-zero element count if node count is zero.in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + if ((ncdimdef (exoid, DIM_NUM_ELEM, (long)num_elem)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of elements in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + + /* Can have nonzero num_elem_blk even if num_elem == 0 */ + if (num_elem_blk > 0) { + if ((elblkdim = ncdimdef (exoid, DIM_NUM_EL_BLK, (long)num_elem_blk)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of element blocks in file id %d", + exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* ...and some variables */ + + /* element block id status array */ + + dim[0] = elblkdim; + if ((varid = ncvardef (exoid, VAR_STAT_EL_BLK, NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define element block status array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + +#if 0 + /* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 7, "STATUS")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element block property name %s in file id %d", + "STATUS",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } +#endif + + /* element block id array */ + + if ((varid = ncvardef (exoid, VAR_ID_EL_BLK, NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define element block id array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 3, "ID")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element block property name %s in file id %d", + "ID",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } + } + + /* node set id array: */ + + if (num_node_sets > 0) { + + if ((dimid = ncdimdef (exoid, DIM_NUM_NS, (long)num_node_sets)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of node sets in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* node set id status array: */ + + dim[0] = dimid; + if ((varid = ncvardef (exoid, VAR_NS_STAT, NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node sets status array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + +#if 0 + /* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 7, "STATUS")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node set property name %s in file id %d", + "ID",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } +#endif + + /* node set id array: */ + + dim[0] = dimid; + if ((varid = ncvardef (exoid, VAR_NS_IDS, NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node sets property array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + + /* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 3, "ID")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node set property name %s in file id %d", + "ID",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } + + + } + + /* side set id array: */ + + if (num_side_sets > 0) { + + if ((dimid = ncdimdef (exoid, DIM_NUM_SS, (long)num_side_sets)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of side sets in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* side set id status array: */ + + dim[0] = dimid; + if ((varid = ncvardef (exoid, VAR_SS_STAT, NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define side set status in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + +#if 0 + /* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 7, "STATUS")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store side set property name %s in file id %d", + "ID",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } +#endif + + /* side set id array: */ + + if ((varid = ncvardef (exoid, VAR_SS_IDS, NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define side set property in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 3, "ID")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store side set property name %s in file id %d", + "ID",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } + + } + + /* + * To reduce the maximum dataset sizes, the storage of the nodal + * coordinates and the nodal variables was changed from a single + * dataset to a dataset per component or variable. However, we + * want to maintain some form of compatability with the old + * exodusII version. It is easy to do this on read; however, we + * also want to be able to store in the old format using the new + * library. + * + * The mode is set in the ex_create call. The setting can be checked + * via the ATT_FILESIZE attribute in the file (1=large, + * 0=normal). Also handle old files that do not contain this + * attribute. + */ + + if (num_nodes > 0) { + if (ex_large_model(exoid) == 1) { + /* node coordinate arrays -- separate storage... */ + + /* + * Check that storage required for coordinates is less + * than 2GB which is maximum size permitted by netcdf + * (in large file mode). 1<<29 == max number of integer items. + */ + int shift = nc_flt_code(exoid) == NC_DOUBLE ? 28 : 29; + if (num_nodes > (1< 0) { + if (ncvardef (exoid, VAR_COORD_X, nc_flt_code(exoid), 1, dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define node x coordinate array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + + if (num_dim > 1) { + if (ncvardef (exoid, VAR_COORD_Y, nc_flt_code(exoid), 1, dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define node y coordinate array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + + if (num_dim > 2) { + if (ncvardef (exoid, VAR_COORD_Z, nc_flt_code(exoid), 1, dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define node z coordinate array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + } else { + /* node coordinate arrays: -- all stored together (old method) */ + + dim[0] = numdimdim; + dim[1] = numnoddim; + if (ncvardef (exoid, VAR_COORD, nc_flt_code(exoid), 2, dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define node coordinate array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + } + + /* inquire previously defined dimensions */ + if ((strdim = ncdimid (exoid, DIM_STR)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get string length in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* coordinate names array */ + + dim[0] = numdimdim; + dim[1] = strdim; + + if (ncvardef (exoid, VAR_NAME_COOR, NC_CHAR, 2, dim) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define coordinate name array in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + + /* leave define mode */ +#if 1 + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete variable definitions in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } + +#else + /* estimate (guess) size of header of netCDF file */ + header_size = 1200 + + num_elem_blk * 800 + + num_node_sets * 220 + + num_side_sets * 300; + + if (header_size > MAX_HEADER_SIZE) header_size = MAX_HEADER_SIZE; + + /* estimate (guess) size of fixed size variable section of netCDF file */ + + if (nc_flt_code(exoid) == NC_DOUBLE) + iows = 8; + else + iows = 4; + + fixed_var_size = num_dim * num_nodes * iows + + num_nodes * sizeof(int) + + num_elem * 16 * sizeof(int) + + num_elem_blk * sizeof(int) + + num_node_sets * num_nodes/100 * sizeof(int) + + num_node_sets * num_nodes/100 * iows + + num_node_sets * sizeof(int) + + num_side_sets * num_elem/100 * 2 * sizeof(int) + + num_side_sets * num_elem/100 * iows + + num_side_sets * sizeof(int); + + + + /* With netcdf-3.4, this produces very large files on the + * SGI. Also with netcdf-3.5beta3 + */ + /* + * This is also causing other problems on other systems .. disable for now + */ + if (nc__enddef (exoid, + header_size, NC_ALIGN_CHUNK, + fixed_var_size, NC_ALIGN_CHUNK) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete variable definitions in file id %d",exoid); + ex_err("ex_put_init",errmsg,exerrval); + return (EX_FATAL); + } + +#endif + return (EX_NOERR); + + /* Fatal error: exit definition mode and return */ + error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_init",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expmap.c b/Utilities/vtkexodus2/expmap.c new file mode 100644 index 0000000..be10c7f --- /dev/null +++ b/Utilities/vtkexodus2/expmap.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expmap - ex_put_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int* elem_map element order map array +* +* exit conditions - +* +* revision history - +* +* $Id: expmap.c,v 1.2 2005/07/19 12:31:28 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* + * writes out the element order map to the database + */ + +int ex_put_map (int exoid, + const int *elem_map) +{ + int numelemdim, dims[1], mapid, iresult; + long num_elem, start[1], count[1]; + nclong *lptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions */ + + /* determine number of elements. Return if zero... */ + if ((numelemdim = ncdimid (exoid, DIM_NUM_ELEM)) == -1) + { + return (EX_NOERR); + } + + if (ncdiminq (exoid, numelemdim, (char *) 0, &num_elem) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of elements in file id %d", + exoid); + ex_err("ex_put_map",errmsg,exerrval); + return (EX_FATAL); + } + + +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", + exoid); + ex_err("ex_put_map",errmsg,exerrval); + return (EX_FATAL); + } + + +/* create a variable array in which to store the element map */ + + dims[0] = numelemdim; + + if ((mapid = ncvardef (exoid, VAR_MAP, NC_LONG, 1, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element map already exists in file id %d", + exoid); + ex_err("ex_put_map",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create element map array in file id %d", + exoid); + ex_err("ex_put_map",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_map",errmsg,exerrval); + return (EX_FATAL); + } + + +/* write out the element order map */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_elem; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, mapid, start, count, elem_map); + } else { + lptr = itol (elem_map, (int)num_elem); + iresult = ncvarput (exoid, mapid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element map in file id %d", + exoid); + ex_err("ex_put_map",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_map",errmsg,exerrval); + } + return (EX_FATAL); +} + diff --git a/Utilities/vtkexodus2/expmp.c b/Utilities/vtkexodus2/expmp.c new file mode 100644 index 0000000..edc34cc --- /dev/null +++ b/Utilities/vtkexodus2/expmp.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expmp - ex_put_map_param +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int num_node_maps number of node maps +* int num_elem_maps number of element maps +* +* exit conditions - +* +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * defines the number of node and element maps + */ + +int ex_put_map_param (int exoid, + int num_node_maps, + int num_elem_maps) +{ + int dim[2], dimid, varid; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* return if these have been defined before */ + + if ( ((ncdimid (exoid, DIM_NUM_NM)) != -1) || + ((ncdimid (exoid, DIM_NUM_EM)) != -1) ) + { + exerrval = EX_MSG; + sprintf(errmsg, + "Error: number of maps already defined for file id %d",exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + return (EX_FATAL); + } + + if ( (num_node_maps > 0) || (num_elem_maps > 0) ) + { + +/* put file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + return (EX_FATAL); + } + + +/* node maps: */ + + if (num_node_maps > 0) + { + + if ((dimid = ncdimdef (exoid, DIM_NUM_NM, (long)num_node_maps)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of node maps in file id %d",exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* node maps id array: */ + + dim[0] = dimid; + if ((varid = ncvardef (exoid, VAR_NM_PROP(1), NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node maps property array in file id %d", + exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + +/* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 3, "ID")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node map property name %s in file id %d", + "ID",exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* element maps: */ + + if (num_elem_maps > 0) + { + + if ((dimid = ncdimdef (exoid, DIM_NUM_EM, (long)num_elem_maps)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of element maps in file id %d", + exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* element maps id array: */ + + dim[0] = dimid; + if ((varid = ncvardef (exoid, VAR_EM_PROP(1), NC_LONG, 1, dim)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create element maps property array in file id %d", + exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + +/* store property name as attribute of property array variable */ + if ((ncattput (exoid, varid, ATT_PROP_NAME, NC_CHAR, 3, "ID")) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element map property name %s in file id %d", + "ID",exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete variable definitions in file id %d",exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + return (EX_FATAL); + } + + } + + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_map_param",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expnm.c b/Utilities/vtkexodus2/expnm.c new file mode 100644 index 0000000..a17ca41 --- /dev/null +++ b/Utilities/vtkexodus2/expnm.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expnm - ex_put_node_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int map_id node map id +* int *node_map node map +* +* exit conditions - +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* initialize this once */ + +struct list_item* nm_ctr_list = 0; + +/* + * writes an node map; this is a vector of integers of length number + * of nodes + */ + +int ex_put_node_map (int exoid, + int map_id, + const int *node_map) +{ + int dimid, varid, dims[1], iresult; + long start[1]; + nclong ldum, *lptr; + long num_node_maps, num_nodes, count[1]; + int cur_num_node_maps; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; + + + /* Return if node nodes stored in this file */ + if ((dimid = (ncdimid (exoid, DIM_NUM_NODES))) == -1 ) { + return (EX_NOERR); + } + +/* first check if any node maps are specified */ + + if ((dimid = (ncdimid (exoid, DIM_NUM_NM))) == -1 ) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no node maps specified in file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* Check for duplicate node map id entry */ + ex_id_lkup(exoid,VAR_NM_PROP(1),map_id); + if (exerrval != EX_LOOKUPFAIL) /* found the node map id */ + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node map %d already defined in file id %d", + map_id,exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return(EX_FATAL); + } + +/* Get number of node maps initialized for this file */ + if ((ncdiminq (exoid,dimid,cdum,&num_node_maps)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of node maps in file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* Keep track of the total number of node maps defined using a counter stored + in a linked list keyed by exoid. + NOTE: ex_get_file_item is used to find the number of node maps + for a specific file and returns that value. +*/ + cur_num_node_maps = ex_get_file_item(exoid, &nm_ctr_list ); + if (cur_num_node_maps >= num_node_maps) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of node maps (%ld) specified in file id %d", + num_node_maps,exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* NOTE: ex_inc_file_item is used to find the number of node maps + for a specific file and returns that value incremented. */ + + cur_num_node_maps = ex_inc_file_item(exoid, &nm_ctr_list ); + +/* write out information to previously defined variable */ + + /* first get id of variable */ + + if ((varid = ncvarid (exoid, VAR_NM_PROP(1))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node map ids in file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + + /* then, write out node map id */ + + start[0] = cur_num_node_maps; + + ldum = (nclong)map_id; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node map id %d in file id %d", + map_id,exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* determine number of nodes */ + + if ((dimid = (ncdimid (exoid, DIM_NUM_NODES))) == -1 ) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: couldn't determine number of nodes in file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_nodes) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", + exoid); + ex_err("ex_put_elem_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* create variable array in which to store the node map */ + + dims[0] = dimid; + + if ((varid = + ncvardef(exoid,VAR_NODE_MAP(cur_num_node_maps+1),NC_LONG,1,dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node map %d already defined in file id %d", + map_id,exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node map %d in file id %d", + map_id,exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + +/* write out the node map */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_nodes; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, varid, start, count, node_map); + } else { + lptr = itol (node_map, (int)num_nodes); + iresult = ncvarput (exoid, varid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node map in file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_node_map",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expnnm.c b/Utilities/vtkexodus2/expnnm.c new file mode 100644 index 0000000..ad41f11 --- /dev/null +++ b/Utilities/vtkexodus2/expnnm.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expnnm - ex_put_node_num_map +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int* node_map node numbering map +* +* exit conditions - +* +* revision history - +* +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* + * writes out the node numbering map to the database; allows node numbers + * to be non-contiguous + */ + +int ex_put_node_num_map (int exoid, + const int *node_map) +{ + int numnodedim, dims[1], mapid, iresult; + long num_nodes, start[1], count[1]; + nclong *lptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* inquire id's of previously defined dimensions */ + + /* determine number of nodes, return immediately if 0 */ + if ((numnodedim = ncdimid (exoid, DIM_NUM_NODES)) == -1) + { + return (EX_NOERR); + } + + if (ncdiminq (exoid, numnodedim, (char *) 0, &num_nodes) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + /* put netcdf file into define mode */ + + if ((mapid = ncvarid (exoid, VAR_NODE_NUM_MAP)) == -1) { + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + /* create a variable array in which to store the node numbering map */ + + dims[0] = numnodedim; + + if ((mapid = ncvardef (exoid, VAR_NODE_NUM_MAP, NC_LONG, 1, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node numbering map already exists in file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node numbering map array in file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + + /* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + return (EX_FATAL); + } + } + + /* write out the node numbering map */ + + /* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_nodes; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, mapid, start, count, node_map); + } else { + lptr = itol (node_map, (int)num_nodes); + iresult = ncvarput (exoid, mapid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node numbering map in file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); + + /* Fatal error: exit definition mode and return */ + error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_node_num_map",errmsg,exerrval); + } + return (EX_FATAL); +} + diff --git a/Utilities/vtkexodus2/expnp.c b/Utilities/vtkexodus2/expnp.c new file mode 100644 index 0000000..d71e1a7 --- /dev/null +++ b/Utilities/vtkexodus2/expnp.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expnp - ex_put_node_set_parameters +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int node_set_id node set id +* int num_nodes_in_set number of nodes in set +* int num_dist_in_set number of distribution factors in set +* +* exit conditions - +* +* revision history - +* +* $Id: expnp.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +struct list_item* ns_ctr_list = 0; + +/* + * writes the information which describes a single node set + */ + +int ex_put_node_set_param (int exoid, + int node_set_id, + int num_nodes_in_set, + int num_dist_in_set) +{ + int dimid, varid, dims[1]; + long start[1]; + nclong ldum; + long num_node_sets; + int cur_num_node_sets, node_set_stat; + char *cdum; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + cdum = 0; + +/* first check if any node sets are specified */ + + if ((dimid = (ncdimid (exoid, DIM_NUM_NS))) == -1 ) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no node sets specified in file id %d", + exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + +/* Check for duplicate node set id entry */ + ex_id_lkup(exoid,VAR_NS_IDS,node_set_id); + if (exerrval != EX_LOOKUPFAIL) /* found the node set id */ + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node set %d already defined in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return(EX_FATAL); + } + +/* Get number of node sets initialized for this file */ + if ((ncdiminq (exoid,dimid,cdum,&num_node_sets)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of node sets in file id %d", + exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + +/* Keep track of the total number of node sets defined using a counter stored + in a linked list keyed by exoid. + NOTE: ex_get_file_item is used to find the number of node sets + for a specific file and returns that value. +*/ + cur_num_node_sets=ex_get_file_item(exoid, &ns_ctr_list ); + if (cur_num_node_sets >= num_node_sets) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of node sets (%ld) specified in file id %d", + num_node_sets,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + +/* NOTE: ex_inc_file_item is used to find the number of node sets + for a specific file and returns that value incremented. */ + + cur_num_node_sets=ex_inc_file_item(exoid, &ns_ctr_list ); + +/* write out information to previously defined variable */ + + /* first get id of variable */ + + if ((varid = ncvarid (exoid, VAR_NS_IDS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node set ids in file id %d", + exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + /* then, write out node set id */ + + start[0] = cur_num_node_sets; + + ldum = (nclong)node_set_id; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node set id %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + if (num_nodes_in_set == 0) /* Is this a NULL side set? */ + node_set_stat = 0; /* change node set status to NULL */ + else + node_set_stat = 1; /* change node set status to TRUE */ + + if ((varid = ncvarid (exoid, VAR_NS_STAT)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node set status in file id %d", exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + ldum = (nclong)node_set_stat; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node set %d status to file id %d", + node_set_id, exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + if (num_nodes_in_set == 0) /* Is this a NULL side set? */ + { + return(EX_NOERR); + } + + +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", + exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((dimid = ncdimdef (exoid, DIM_NUM_NOD_NS(cur_num_node_sets+1), + (long)num_nodes_in_set)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node set %d size already defined in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of nodes for set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + } + goto error_ret; + } + + +/* create variable array in which to store the node set node list */ + + dims[0] = dimid; + + if (ncvardef(exoid, VAR_NODE_NS(cur_num_node_sets+1), NC_LONG,1,dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node set %d node list already defined in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node set %d node list in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + +/* Create distribution factors variable if required */ + + if (num_dist_in_set > 0) + { + + /* num_dist_in_set should equal num_nodes_in_set */ + if (num_dist_in_set != num_nodes_in_set) + { + exerrval = EX_FATAL; + sprintf(errmsg, +"Error: # dist fact (%d) not equal to # nodes (%d) in node set %d file id %d", + num_dist_in_set, num_nodes_in_set, node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + else + { +/* create variable for distribution factors */ + + if (ncvardef (exoid, VAR_FACT_NS(cur_num_node_sets+1), + nc_flt_code(exoid), 1, dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: node set %d dist factors already exist in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create node set %d dist factors in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + } + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); + + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_node_set_param",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expns.c b/Utilities/vtkexodus2/expns.c new file mode 100644 index 0000000..b93a394 --- /dev/null +++ b/Utilities/vtkexodus2/expns.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expns - ex_put_node_set +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int node_set_id node set id +* int* node_set_node_list node list array for the node set +* +* exit conditions - +* +* revision history - +* +* $Id: expns.c,v 1.2 2005/07/19 12:31:28 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* + * writes the node list for a single node set + */ + +int ex_put_node_set (int exoid, + int node_set_id, + const int *node_set_node_list) +{ + int dimid, node_list_id, node_set_id_ndx, iresult; + long num_nodes_in_set, start[1], count[1]; + nclong *lptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any node sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no node sets specified in file id %d", + exoid); + ex_err("ex_put_node_set",errmsg,exerrval); + return (EX_FATAL); + } + +/* Lookup index of node set id in VAR_NS_IDS array */ + + node_set_id_ndx = ex_id_lkup(exoid,VAR_NS_IDS,node_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no data allowed for NULL node set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + sprintf(errmsg, + "Error: failed to locate node set id %d in VAR_NS_IDS array in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NOD_NS(node_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes in set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_nodes_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set",errmsg,exerrval); + return (EX_FATAL); + } + +/* inquire if variable for node set node list has been defined */ + + if ((node_list_id = ncvarid (exoid, VAR_NODE_NS(node_set_id_ndx))) == -1) + { + +/* variable doesn't exist */ + + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node set %d node list in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set",errmsg,exerrval); + return (EX_FATAL); + + } + +/* write out the node list array */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_nodes_in_set; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput(exoid, node_list_id, start, count, node_set_node_list); + } else { + lptr = itol (node_set_node_list, (int)num_nodes_in_set); + iresult = ncvarput (exoid, node_list_id, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node set %d node list in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/expnsd.c b/Utilities/vtkexodus2/expnsd.c new file mode 100644 index 0000000..a5747a9 --- /dev/null +++ b/Utilities/vtkexodus2/expnsd.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expnsd - ex_put_node_set_dist_fact +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int node_set_id node set id +* void* node_set _dist_fact node distribution factors for node set +* +* exit conditions - +* +* revision history - +* +* $Id: expnsd.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the node set distribution factors for a single node set + */ + +int ex_put_node_set_dist_fact (int exoid, + int node_set_id, + const void *node_set_dist_fact) +{ + int dimid, dist_id, node_set_id_ndx; + long num_nodes_in_set, start[1], count[1]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any node sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NS)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no node sets specified in file id %d", + exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + +/* Lookup index of node set id in VAR_NS_IDS array */ + + node_set_id_ndx = ex_id_lkup(exoid,VAR_NS_IDS,node_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no data allowed for NULL node set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + sprintf(errmsg, + "Error: failed to locate node set id %d in VAR_NS_IDS array in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions */ + + if ((dimid = ncdimid (exoid, DIM_NUM_NOD_NS(node_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes in node set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_nodes_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of nodes in set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + +/* find id of distribution factors variable + */ + + if ((dist_id = ncvarid (exoid, VAR_FACT_NS(node_set_id_ndx))) == -1) + { + if (ncerr == NC_ENOTVAR) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Warning: no dist factors defined for node set %d in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,exerrval); + return (EX_WARN); + + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate node set %d dist factors in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + } + + +/* write out the distribution factors array */ + + start[0] = 0; + + count[0] = num_nodes_in_set; + + + if (ncvarput (exoid, dist_id, start, count, + ex_conv_array(exoid,WRITE_CONVERT,node_set_dist_fact, + (int)num_nodes_in_set)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store node set %d dist factors in file id %d", + node_set_id,exoid); + ex_err("ex_put_node_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/expnv.c b/Utilities/vtkexodus2/expnv.c new file mode 100644 index 0000000..1d8efcb --- /dev/null +++ b/Utilities/vtkexodus2/expnv.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expnv - ex_put_nodal_var +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step whole time step number +* int nodeal_var_index index of desired nodal variable +* int num_nodes number of nodal points +* float* nodal_var_vals array of nodal variable values +* +* exit conditions - +* +* revision history - +* +* $Id: expnv.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the values of a single nodal variable for a single time step to + * the database; assume the first time step and nodal variable index + * is 1 + */ + +int ex_put_nodal_var (int exoid, + int time_step, + int nodal_var_index, + int num_nodes, + const void *nodal_var_vals) + +{ + int varid; + long start[3], count[3]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + if (ex_large_model(exoid) == 0) { + /* write values of the nodal variable */ + if ((varid = ncvarid (exoid, VAR_NOD_VAR)) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variables in file id %d", + exoid); + ex_err("ex_put_nodal_var",errmsg,exerrval); + return (EX_WARN); + } + start[0] = --time_step; + start[1] = --nodal_var_index; + start[2] = 0; + + count[0] = 1; + count[1] = 1; + count[2] = num_nodes; + } else { + /* nodal variables stored separately, find variable for this variable + index */ + if ((varid = ncvarid (exoid, VAR_NOD_VAR_NEW(nodal_var_index))) == -1) { + exerrval = ncerr; + sprintf(errmsg, + "Warning: could not find nodal variable %d in file id %d", + nodal_var_index, exoid); + ex_err("ex_put_nodal_var",errmsg,exerrval); + return (EX_WARN); + } + + start[0] = --time_step; + start[1] = 0; + + count[0] = 1; + count[1] = num_nodes; + } + + if (ncvarput (exoid, varid, start, count, + ex_conv_array(exoid,WRITE_CONVERT,nodal_var_vals,num_nodes)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store nodal variables in file id %d", + exoid); + ex_err("ex_put_nodal_var",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/expnvv.c b/Utilities/vtkexodus2/expnvv.c new file mode 100644 index 0000000..9e5c2d2 --- /dev/null +++ b/Utilities/vtkexodus2/expnvv.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expnv - ex_put_nodal_varid_var +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step whole time step number +* int nodeal_var_index index of desired nodal variable +* int num_nodes number of nodal points +* int varid id of variable on exodus database +* float* nodal_var_vals array of nodal variable values +* +* exit conditions - +* +* revision history - +* +* $Id: expnvv.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the values of a single nodal variable for a single time step to + * the database; assume the first time step and nodal variable index + * is 1 + */ + +int ex_put_nodal_varid_var(int exoid, + int time_step, + int nodal_var_index, + int num_nodes, + int varid, + const void *nodal_var_vals) +{ + long start[3], count[3]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + if (ex_large_model(exoid) == 0) { + start[0] = --time_step; + start[1] = --nodal_var_index; + start[2] = 0; + + count[0] = 1; + count[1] = 1; + count[2] = num_nodes; + } else { + start[0] = --time_step; + start[1] = 0; + + count[0] = 1; + count[1] = num_nodes; + } + + if (ncvarput (exoid, varid, start, count, + ex_conv_array(exoid,WRITE_CONVERT,nodal_var_vals,num_nodes)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store nodal variables in file id %d", + exoid); + ex_err("ex_put_nodal_varid_var",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/expp.c b/Utilities/vtkexodus2/expp.c new file mode 100644 index 0000000..5c0b9a8 --- /dev/null +++ b/Utilities/vtkexodus2/expp.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expp - ex_put_prop: write object property +* +* author - Larry A. Schoof, Sandia National Laboratories +* Victor R. Yarberry, Sandia National Laboratories +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int obj_type type of object (element block, node +* set or side set) +* int obj_id id of object to which property will +* be assigned +* char* prop_name name of the property for which the +* value will be stored +* int value value of the property +* +* exit conditions - +* +* revision history - +* +* $Id: expp.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" +#include + +/* + * writes an object property + */ + +int ex_put_prop (int exoid, + int obj_type, + int obj_id, + const char *prop_name, + int value) +{ + int found = FALSE; + int num_props, i, dimid, propid, dims[1]; + long start[1]; + nclong ldum; + char name[MAX_VAR_NAME_LENGTH+1]; + char obj_stype[MAX_VAR_NAME_LENGTH+1]; + char obj_vtype[MAX_VAR_NAME_LENGTH+1]; + char tmpstr[MAX_VAR_NAME_LENGTH+1]; + char dim_name[MAX_VAR_NAME_LENGTH+1]; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* check if property has already been created */ + + num_props = ex_get_num_props(exoid, obj_type); + + switch (obj_type) + { + case EX_ELEM_BLOCK: + strcpy (obj_vtype, VAR_ID_EL_BLK); + strcpy (obj_stype, "element block"); + break; + case EX_NODE_SET: + strcpy (obj_vtype, VAR_NS_IDS); + strcpy (obj_stype, "node set"); + break; + case EX_SIDE_SET: + strcpy (obj_vtype, VAR_SS_IDS); + strcpy (obj_stype, "side set"); + break; + case EX_ELEM_MAP: + strcpy (obj_vtype, VAR_EM_PROP(1)); + strcpy (obj_stype, "element map"); + break; + case EX_NODE_MAP: + strcpy (obj_vtype, VAR_NM_PROP(1)); + strcpy (obj_stype, "node map"); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return(EX_FATAL); + } + + if (num_props > 1) /* any properties other than the default 1? */ + { + + for (i=1; i<=num_props; i++) + { + switch (obj_type) + { + case EX_ELEM_BLOCK: + strcpy (name, VAR_EB_PROP(i)); + break; + case EX_NODE_SET: + strcpy (name, VAR_NS_PROP(i)); + break; + case EX_SIDE_SET: + strcpy (name, VAR_SS_PROP(i)); + break; + case EX_ELEM_MAP: + strcpy (name, VAR_EM_PROP(i)); + break; + case EX_NODE_MAP: + strcpy (name, VAR_NM_PROP(i)); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return(EX_FATAL); + } + + if ((propid = ncvarid (exoid, name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get property array id in file id %d", + exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return (EX_FATAL); + } + +/* compare stored attribute name with passed property name */ + + if ((ncattget (exoid, propid, ATT_PROP_NAME, tmpstr)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get property name in file id %d", exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return (EX_FATAL); + } + + if (strcmp(tmpstr, prop_name) == 0) + { + found = TRUE; + break; + } + } + } + +/* if property array has not been created, create it */ + + if (!found) + { +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return (EX_FATAL); + } + +/* create a variable with a name xx_prop#, where # is the new number */ +/* of the property */ + + switch (obj_type){ + case EX_ELEM_BLOCK: + strcpy (name, VAR_EB_PROP(num_props+1)); + strcpy (dim_name, DIM_NUM_EL_BLK); + break; + case EX_NODE_SET: + strcpy (name, VAR_NS_PROP(num_props+1)); + strcpy (dim_name, DIM_NUM_NS); + break; + case EX_SIDE_SET: + strcpy (name, VAR_SS_PROP(num_props+1)); + strcpy (dim_name, DIM_NUM_SS); + break; + case EX_ELEM_MAP: + strcpy (name, VAR_EM_PROP(num_props+1)); + strcpy (dim_name, DIM_NUM_EM); + break; + case EX_NODE_MAP: + strcpy (name, VAR_NM_PROP(num_props+1)); + strcpy (dim_name, DIM_NUM_NM); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_put_prop",errmsg,exerrval); + goto error_ret; /* Exit define mode and return */ + } + +/* inquire id of previously defined dimension (number of objects) */ + + if ((dimid = ncdimid (exoid, dim_name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of objects in file id %d", + exoid); + ex_err("ex_put_prop",errmsg, exerrval); + goto error_ret; /* Exit define mode and return */ + } + + dims[0] = dimid; + ncsetfill(exoid, NC_FILL); /* fill with zeros per routine spec */ + + if ((propid = ncvardef (exoid, name, NC_LONG, 1, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create property array variable in file id %d", + exoid); + ex_err("ex_put_prop",errmsg,exerrval); + goto error_ret; /* Exit define mode and return */ + } + ncsetfill(exoid, NC_NOFILL); /* default: nofill */ + +/* store property name as attribute of property array variable */ + + if ((ncattput (exoid, propid, ATT_PROP_NAME, NC_CHAR, + strlen(prop_name)+1, prop_name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store property name %s in file id %d", + prop_name,exoid); + ex_err("ex_put_prop",errmsg,exerrval); + goto error_ret; /* Exit define mode and return */ + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to leave define mode in file id %d", + exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return (EX_FATAL); + } + + } + +/* find index into property array using obj_id; put value in property */ +/* array at proper index; ex_id_lkup returns an index that is 1-based,*/ +/* but netcdf expects 0-based arrays so subtract 1 */ + + /* special case: property name ID - check for duplicate ID assignment */ + if (strcmp("ID",prop_name) == 0) + { + start[0] = ex_id_lkup (exoid, obj_vtype, value); + if (exerrval != EX_LOOKUPFAIL) /* found the id */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Warning: attempt to assign duplicate %s ID %d in file id %d", + obj_stype, value, exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return (EX_WARN); + } + } + + start[0] = ex_id_lkup (exoid, obj_vtype, obj_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no properties allowed for NULL %s id %d in file id %d", + obj_stype, obj_id,exoid); + ex_err("ex_put_prop",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to find value %d in %s property array in file id %d", + obj_id, obj_stype, exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return (EX_FATAL); + } + } + + start[0] = start[0] - 1; + + ldum = (nclong)value; + if (ncvarput1 (exoid, propid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store property value in file id %d", + exoid); + ex_err("ex_put_prop",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + ncsetfill(exoid, NC_NOFILL); /* default: nofill */ + + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_prop",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/exppa.c b/Utilities/vtkexodus2/exppa.c new file mode 100644 index 0000000..e5a6f35 --- /dev/null +++ b/Utilities/vtkexodus2/exppa.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exppa - ex_put_prop_array: write object property array +* +* author - Larry A. Schoof, Sandia National Laboratories +* Victor R. Yarberry, Sandia National Laboratories +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int obj_type type of object (element block, node +* set or side set) +* char* prop_name name of the property for which the +* values will be stored +* int* values array of property values +* +* exit conditions - +* +* revision history - +* +* $Id: exppa.c,v 1.2 2005/07/19 12:31:28 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include +#include + +/* + * writes an array of object properties + */ + +int ex_put_prop_array (int exoid, + int obj_type, + const char *prop_name, + const int *values) +{ + int num_props, i, propid, dimid, dims[1], iresult; + int found = FALSE; + long start[1], count[1], num_obj; + nclong *lptr; + char name[MAX_VAR_NAME_LENGTH+1]; + char tmpstr[MAX_VAR_NAME_LENGTH+1]; + char obj_stype[MAX_VAR_NAME_LENGTH+1]; + char dim_name[MAX_VAR_NAME_LENGTH+1]; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* check if property has already been created */ + + num_props = ex_get_num_props(exoid, obj_type); + + switch (obj_type) + { + case EX_ELEM_BLOCK: + strcpy (obj_stype, VAR_ID_EL_BLK); + strcpy (dim_name, DIM_NUM_EL_BLK); + break; + case EX_NODE_SET: + strcpy (obj_stype, VAR_NS_IDS); + strcpy (dim_name, DIM_NUM_NS); + break; + case EX_SIDE_SET: + strcpy (obj_stype, VAR_SS_IDS); + strcpy (dim_name, DIM_NUM_SS); + break; + case EX_ELEM_MAP: + strcpy (obj_stype, VAR_EM_PROP(1)); + strcpy (dim_name, DIM_NUM_EM); + break; + case EX_NODE_MAP: + strcpy (obj_stype, VAR_NM_PROP(1)); + strcpy (dim_name, DIM_NUM_NM); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + return (EX_FATAL); + } +/* inquire id of previously defined dimension (number of objects) */ + + if ((dimid = ncdimid (exoid, dim_name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of %s objects in file id %d", + obj_stype, exoid); + ex_err("ex_put_prop_array",errmsg, exerrval); + return (EX_FATAL); + } + +/* get number of objects */ + + if (ncdiminq (exoid, dimid, dim_name, &num_obj) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of %s objects in file id %d", + obj_stype, exoid); + ex_err("ex_put_prop_array",errmsg, exerrval); + return (EX_FATAL); + } + + + + for (i=1; i<=num_props; i++) + { + switch (obj_type){ + case EX_ELEM_BLOCK: + strcpy (name, VAR_EB_PROP(i)); + break; + case EX_NODE_SET: + strcpy (name, VAR_NS_PROP(i)); + break; + case EX_SIDE_SET: + strcpy (name, VAR_SS_PROP(i)); + break; + case EX_ELEM_MAP: + strcpy (name, VAR_EM_PROP(i)); + break; + case EX_NODE_MAP: + strcpy (name, VAR_NM_PROP(i)); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + return(EX_FATAL); + } + + if ((propid = ncvarid (exoid, name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get property array id in file id %d", + exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + +/* compare stored attribute name with passed property name */ + + if ((ncattget (exoid, propid, ATT_PROP_NAME, tmpstr)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get property name in file id %d", exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + + if (strcmp(tmpstr, prop_name) == 0) + { + found = TRUE; + break; + } + } + +/* if property array has not been created, create it */ + + if (!found) + { +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + +/* create a variable with a name xx_prop#, where # is the new number */ +/* of properties */ + + switch (obj_type){ + case EX_ELEM_BLOCK: + strcpy (name, VAR_EB_PROP(num_props+1)); + break; + case EX_NODE_SET: + strcpy (name, VAR_NS_PROP(num_props+1)); + break; + case EX_SIDE_SET: + strcpy (name, VAR_SS_PROP(num_props+1)); + break; + case EX_ELEM_MAP: + strcpy (name, VAR_EM_PROP(num_props+1)); + break; + case EX_NODE_MAP: + strcpy (name, VAR_NM_PROP(num_props+1)); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + goto error_ret; /* Exit define mode and return */ + } + + dims[0] = dimid; + ncsetfill(exoid, NC_FILL); /* fill with zeros per routine spec */ + + if ((propid = ncvardef (exoid, name, NC_LONG, 1, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create property array variable in file id %d", + exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + goto error_ret; /* Exit define mode and return */ + } + ncsetfill(exoid, NC_NOFILL); /* default: nofill */ + + +/* store property name as attribute of property array variable */ + + if ((ncattput (exoid, propid, ATT_PROP_NAME, NC_CHAR, + strlen(prop_name)+1, prop_name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store property name %s in file id %d", + prop_name,exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + goto error_ret; /* Exit define mode and return */ + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to leave define mode in file id %d", + exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + + } + +/* put num_obj values in property array */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_obj; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, propid, start, count, values); + } else { + lptr = itol (values, (int)num_obj); + iresult = ncvarput (exoid, propid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store property values in file id %d", + exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + ncsetfill(exoid, NC_NOFILL); /* default: nofill */ + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_prop_array",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/exppn.c b/Utilities/vtkexodus2/exppn.c new file mode 100644 index 0000000..6dbbf6c --- /dev/null +++ b/Utilities/vtkexodus2/exppn.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exppn - ex_put_prop_names: write property arrays names +* +* author - Larry A. Schoof, Sandia National Laboratories +* Victor R. Yarberry, Sandia National Laboratories +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int obj_type type of object (element block, node +* set or side set) +* int num_props number of properties to be assigned +* char** prop_names array of num_props names +* +* exit conditions - +* +* revision history - +* +* $Id: exppn.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" +#include + +/* + * writes the parameters to set up property name arrays + */ + +int ex_put_prop_names (int exoid, + int obj_type, + int num_props, + char **prop_names) +{ + int i, propid, dimid, dims[1]; + char name[MAX_VAR_NAME_LENGTH+1]; + long vals[1]; + + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* determine what type of object (element block, node set, or side set) */ + + switch (obj_type){ + case EX_ELEM_BLOCK: + strcpy (name, DIM_NUM_EL_BLK); + break; + case EX_NODE_SET: + strcpy (name, DIM_NUM_NS); + break; + case EX_SIDE_SET: + strcpy (name, DIM_NUM_SS); + break; + case EX_ELEM_MAP: + strcpy (name, DIM_NUM_EM); + break; + case EX_NODE_MAP: + strcpy (name, DIM_NUM_NM); + break; + default: + exerrval = EX_BADPARAM; + sprintf(errmsg, "Error: object type %d not supported; file id %d", + obj_type, exoid); + ex_err("ex_put_prop_names",errmsg,exerrval); + return(EX_FATAL); + } + +/* inquire id of previously defined dimension (number of objects) */ + + if ((dimid = ncdimid (exoid, name)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of objects in file id %d", + exoid); + ex_err("ex_put_prop_names",errmsg, exerrval); + return(EX_FATAL); + } + + ncsetfill(exoid, NC_FILL); /* fill with zeros per routine spec */ +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg,"Error: failed to place file id %d into define mode",exoid); + ex_err("ex_put_prop_names",errmsg,exerrval); + return (EX_FATAL); + } + +/* define num_props variables; we postpend the netcdf variable name with */ +/* a counter starting at 2 because "xx_prop1" is reserved for the id array*/ + + dims[0] = dimid; + + for (i=0; i + +/* + * writes the QA records to the database + */ + +int ex_put_qa (int exoid, + int num_qa_records, + char* qa_record[][4]) +{ + int i, j, strdim, num_qa_dim, varid, n4dim; + int dims[3]; + long start[3], count[3]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* only do this if there are records */ + + if (num_qa_records > 0) + { +/* inquire previously defined dimensions */ + + if ((strdim = ncdimid (exoid, DIM_STR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate string length in file id %d", exoid); + ex_err("ex_put_qa",errmsg,exerrval); + return (EX_FATAL); + } + + if ((n4dim = ncdimid (exoid, DIM_N4)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate record length in file id %d", exoid); + ex_err("ex_put_qa",errmsg,exerrval); + return (EX_FATAL); + } + + +/* put file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", exoid); + ex_err("ex_put_qa",errmsg,exerrval); + return (EX_FATAL); + } + + +/* define dimensions */ + + if ((num_qa_dim = ncdimdef (exoid,DIM_NUM_QA,(long)num_qa_records)) == -1) + { + if (ncerr == NC_ENAMEINUSE) /* duplicate entry? */ + { + exerrval = ncerr; + sprintf(errmsg, + "Error: qa records already exist in file id %d", exoid); + ex_err("ex_put_qa",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define qa record array size in file id %d", exoid); + ex_err("ex_put_qa",errmsg,exerrval); + } + + goto error_ret; /* exit define mode and return */ + } + + + +/* define variable */ + + dims[0] = num_qa_dim; + dims[1] = n4dim; + dims[2] = strdim; + + if ((varid = ncvardef (exoid, VAR_QA_TITLE, NC_CHAR, 3, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define qa record array in file id %d", exoid); + ex_err("ex_put_qa",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", exoid); + ex_err("ex_put_qa",errmsg,exerrval); + return (EX_FATAL); + } + + +/* write out QA records */ + + for (i=0; i= num_side_sets) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: exceeded number of side sets (%ld) defined in file id %d", + num_side_sets,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + +/* NOTE: ex_inc_file_item finds the current number of side sets defined + for a specific file and returns that value incremented. */ + + cur_num_side_sets=ex_inc_file_item(exoid,&ss_ctr_list); + side_set_id_ndx = cur_num_side_sets + 1; + +/* write out information to previously defined variable */ + + /* first: get id of side set id variable */ + + if ((varid = ncvarid (exoid, VAR_SS_IDS)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate side set %d in file id %d", + side_set_id, exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + /* write out side set id */ + + start[0] = cur_num_side_sets; + + ldum = (nclong)side_set_id; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store side set id %d in file id %d", + side_set_id, exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + if (num_side_in_set == 0) /* Is this a NULL side set? */ + side_set_stat = 0; /* change side set status to NULL */ + else + side_set_stat = 1; /* change side set status to TRUE */ + + if ((varid = ncvarid (exoid, VAR_SS_STAT)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate side set status in file id %d", exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + ldum = (nclong)side_set_stat; + if (ncvarput1 (exoid, varid, start, &ldum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store side set %d status to file id %d", + side_set_id, exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + if (num_side_in_set == 0) /* Is this a NULL side set? */ + { + return(EX_NOERR); + } + +/* put netcdf file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", + exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + +/* define dimensions and variables */ + + if (num_side_in_set > 0) + { + if ((dimid = ncdimdef(exoid,DIM_NUM_SIDE_SS(side_set_id_ndx), + (long)num_side_in_set)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of sides in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + goto error_ret; + } + + dims[0] = dimid; + + if (ncvardef (exoid, VAR_ELEM_SS(side_set_id_ndx), NC_LONG, 1, dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element list already exists for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create element list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + if (ncvardef (exoid, VAR_SIDE_SS(side_set_id_ndx), NC_LONG, 1, dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: side list already exists for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create side list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + + } + + } + + if (num_dist_fact_in_set > 0) + { + if ((dimid = ncdimdef (exoid, DIM_NUM_DF_SS(side_set_id_ndx), + (long)num_dist_fact_in_set)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of dist factors in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + +/* create variable array in which to store the side set distribution factors + */ + + dims[0] = dimid; + + if (ncvardef (exoid, VAR_FACT_SS(side_set_id_ndx), + nc_flt_code(exoid), 1, dims) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: dist factors list already exists for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to create dist factors list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + } + +/* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + +/* Fatal error: exit definition mode and return */ +error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_side_set_param",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expss.c b/Utilities/vtkexodus2/expss.c new file mode 100644 index 0000000..74c96eb --- /dev/null +++ b/Utilities/vtkexodus2/expss.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expss - ex_put_side_set +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int side_set_id side set id +* int* side_set_elem_list array of elements in side set +* int* side_set_side_list array of sides in side set + +* exit conditions - +* +* revision history - +* +* $Id: expss.c,v 1.2 2005/07/19 12:31:28 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include + +/* + * writes the side set element list and side set side list for a single side set + */ + +int ex_put_side_set (int exoid, + int side_set_id, + const int *side_set_elem_list, + const int *side_set_side_list) +{ + int dimid, iresult; + int elem_list_id, side_list_id, side_set_id_ndx; + long num_side_in_set, start[1], count[1]; + nclong *lptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any side sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SS)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no side sets defined in file id %d", + exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + +/* Lookup index of side set id in VAR_SS_IDS array */ + + side_set_id_ndx = ex_id_lkup(exoid,VAR_SS_IDS,side_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no data allowed for NULL side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + sprintf(errmsg, + "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimensions */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SIDE_SS(side_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of sides in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_side_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of sides in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + +/* inquire id's of previously defined variables */ + + if ((elem_list_id = ncvarid (exoid, VAR_ELEM_SS(side_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + if ((side_list_id = ncvarid (exoid, VAR_SIDE_SS(side_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate side list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + +/* write out the element list and side list arrays */ + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + count[0] = num_side_in_set; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput(exoid, elem_list_id, start, count, side_set_elem_list); + } else { + lptr = itol (side_set_elem_list, (int)num_side_in_set); + iresult = ncvarput (exoid, elem_list_id, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + +/* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput(exoid, side_list_id, start, count, side_set_side_list); + } else { + lptr = itol (side_set_side_list, (int)num_side_in_set); + iresult = ncvarput (exoid, side_list_id, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store side list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/expssd.c b/Utilities/vtkexodus2/expssd.c new file mode 100644 index 0000000..dc05dc9 --- /dev/null +++ b/Utilities/vtkexodus2/expssd.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expssd - ex_put_side_set_dist_fact +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int side_set_id side set id +* void* side_set_dist_fact array of dist factors for side set + +* exit conditions - +* +* revision history - +* +* $Id: expssd.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the distribution factors for a single side set + */ + +int ex_put_side_set_dist_fact (int exoid, + int side_set_id, + const void *side_set_dist_fact) +{ + int dimid, side_set_id_ndx; + int dist_id; + long num_df_in_set, start[1], count[1]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* first check if any side sets are specified */ + + if ((dimid = ncdimid (exoid, DIM_NUM_SS)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no side sets specified in file id %d", + exoid); + ex_err("ex_put_side_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + +/* Lookup index of side set id in VAR_SS_IDS array */ + + side_set_id_ndx = ex_id_lkup(exoid,VAR_SS_IDS,side_set_id); + if (exerrval != 0) + { + if (exerrval == EX_NULLENTITY) + { + sprintf(errmsg, + "Warning: no data allowed for NULL side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_fact",errmsg,EX_MSG); + return (EX_WARN); + } + else + { + sprintf(errmsg, + "Error: failed to locate side set id %d in VAR_SS_IDS array in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + } + +/* inquire id's of previously defined dimension and variable */ + + if ((dimid = ncdimid (exoid, DIM_NUM_DF_SS(side_set_id_ndx))) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Warning: no dist factors defined for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_dist_fact",errmsg,exerrval); + return (EX_WARN); + + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of dist factors in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + } + + if (ncdiminq (exoid, dimid, (char *) 0, &num_df_in_set) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of dist factors in side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + + if ((dist_id = ncvarid (exoid, VAR_FACT_SS(side_set_id_ndx))) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate dist factors list for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + +/* write out the distribution factors array */ + + start[0] = 0; + + count[0] = num_df_in_set; + + if (ncvarput (exoid, dist_id, start, count, + ex_conv_array(exoid,WRITE_CONVERT,side_set_dist_fact, + (int)num_df_in_set)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store dist factors for side set %d in file id %d", + side_set_id,exoid); + ex_err("ex_put_side_set_dist_fact",errmsg,exerrval); + return (EX_FATAL); + } + + return (EX_NOERR); + +} diff --git a/Utilities/vtkexodus2/exptim.c b/Utilities/vtkexodus2/exptim.c new file mode 100644 index 0000000..70a5879 --- /dev/null +++ b/Utilities/vtkexodus2/exptim.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* exptim - ex_put_time +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int time_step time step number +* float time_value simulation time at specified step +* +* exit conditions - +* +* revision history - +* +* $Id: exptim.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the time value for a whole time step; + * assume the first time step is 1 + */ + +int ex_put_time (int exoid, + int time_step, + const void *time_value) +{ + int varid; + long start[1]; + char var_name[MAX_VAR_NAME_LENGTH+1]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire previously defined dimensions */ + + strcpy (var_name, VAR_WHOLE_TIME); + +/* inquire previously defined variable */ + + if ((varid = ncvarid (exoid, var_name)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate time variable in file id %d", exoid); + ex_err("ex_put_time",errmsg,exerrval); + return (EX_FATAL); + } + +/* store time value */ + + start[0] = --time_step; + + if (ncvarput1 (exoid, varid, start, + ex_conv_array(exoid,WRITE_CONVERT,time_value,1)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store time value in file id %d", exoid); + ex_err("ex_put_time",errmsg,exerrval); + return (EX_FATAL); + } + + + return (EX_NOERR); +} diff --git a/Utilities/vtkexodus2/expvan.c b/Utilities/vtkexodus2/expvan.c new file mode 100644 index 0000000..56b906a --- /dev/null +++ b/Utilities/vtkexodus2/expvan.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expvan - ex_put_var_names +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* char* var_type variable type: G,N, or E +* int num_vars # of variables to read +* char* var_names ptr array of variable names +* +* exit conditions - +* +* revision history - +* +* $Id: expvan.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" +#include + +/* + * writes the names of the results variables to the database + */ + +int ex_put_var_names (int exoid, + const char *var_type, + int num_vars, + char *var_names[]) +{ + int i, varid; + long start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + if (*var_type == 'g' || *var_type == 'G') + { + if ((ncdimid (exoid, DIM_NUM_GLO_VAR)) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no global variables defined in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of global variables in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + return(EX_FATAL); + } + + if ((varid = ncvarid (exoid, VAR_NAME_GLO_VAR)) == -1) + { + if (ncerr == NC_ENOTVAR) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no global variable names defined in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: global name variable names not found in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + return(EX_FATAL); + } + + } + + else if (*var_type == 'n' || *var_type == 'N') + { + if ((ncdimid (exoid, DIM_NUM_NOD_VAR)) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no nodal variables defined in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodal variables in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + return(EX_FATAL); + } + + if ((varid = ncvarid (exoid, VAR_NAME_NOD_VAR)) == -1) + { + if (ncerr == NC_ENOTVAR) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no nodal variable names defined in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: nodal name variable names not found in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + return(EX_FATAL); + } + } + + else if (*var_type == 'e' || *var_type == 'E') + { + if ((ncdimid (exoid, DIM_NUM_ELE_VAR)) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element variables defined in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element variables in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + return(EX_FATAL); + } + if ((varid = ncvarid (exoid, VAR_NAME_ELE_VAR)) == -1) + { + if (ncerr == NC_ENOTVAR) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element variable names defined in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element name variable names not found in file id %d", + exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + } + return(EX_FATAL); + + } + } + + else /* invalid variable type */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid variable type %c specified in file id %d", + *var_type, exoid); + ex_err("ex_put_var_names",errmsg,exerrval); + return(EX_FATAL); + } + + +/* write EXODUS variable names */ + + for (i=0; i + +/* + * writes the name of a particular results variable to the database + */ + +int ex_put_var_name (int exoid, + const char *var_type, + int var_num, + const char *var_name) +{ + int varid; + long start[2], count[2]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire previously defined dimensions */ + + if ((ncdimid (exoid, DIM_STR)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get string length in file id %d",exoid); + ex_err("ex_put_var_name",errmsg,exerrval); + return (EX_FATAL); + } + +/* inquire previously defined variables */ + + if (*var_type == 'g' || *var_type == 'G') + { + if ((varid = ncvarid (exoid, VAR_NAME_GLO_VAR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no global variables names stored in file id %d", exoid); + ex_err("ex_put_var_name",errmsg,exerrval); + return (EX_WARN); + } + } + + else if (*var_type == 'n' || *var_type == 'N') + { + if ((varid = ncvarid (exoid, VAR_NAME_NOD_VAR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no nodal variable names stored in file id %d", + exoid); + ex_err("ex_put_var_name",errmsg,exerrval); + return (EX_WARN); + } + + } + + else if (*var_type == 'e' || *var_type == 'E') + { + + if ((varid = ncvarid (exoid, VAR_NAME_ELE_VAR)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Warning: no element variable names stored in file id %d", + exoid); + ex_err("ex_put_var_name",errmsg,exerrval); + return (EX_WARN); + } + } + + else /* invalid variable type */ + { + exerrval = EX_BADPARAM; + sprintf(errmsg, + "Error: Invalid variable type %c specified in file id %d", + *var_type, exoid); + ex_err("ex_put_var_name",errmsg,exerrval); + return (EX_WARN); + } + +/* write EXODUS variable name */ + + start[0] = var_num; + start[1] = 0; + + count[0] = 1; + count[1] = strlen(var_name) + 1; + + if (ncvarput (exoid, varid, start, count, (void*)var_name) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store %c variable name %d in file id %d", + *var_type, var_num, exoid); + ex_err("ex_put_var_name",errmsg,exerrval); + return (EX_FATAL); + } + + return(EX_NOERR); +} diff --git a/Utilities/vtkexodus2/expvp.c b/Utilities/vtkexodus2/expvp.c new file mode 100644 index 0000000..52b276c --- /dev/null +++ b/Utilities/vtkexodus2/expvp.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expvp - ex_put_var_param +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* char* var_type variable type G,N, or E +* int* num_vars number of variables in database +* +* exit conditions - +* +* revision history - +* +* $Id: expvp.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include "exodusII.h" +#include "exodusII_int.h" + +#include +/* + * writes the number and names of global, nodal, or element variables + * that will be written to the database + */ + +int ex_put_var_param (int exoid, + const char *var_type, + int num_vars) +{ + int time_dim, num_nod_dim, dimid, strdim; + int dims[3]; + char *vptr; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* if no variables are to be stored, return with warning */ + if (num_vars == 0) + { + exerrval = EX_MSG; + if (tolower(*var_type) == 'e') + vptr="element"; + else if (tolower(*var_type) == 'g') + vptr="global"; + else if (tolower(*var_type) == 'n') + vptr="nodal"; + else + vptr="invalid type"; + + sprintf(errmsg, + "Warning: zero %s variables specified for file id %d", + vptr,exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + + return (EX_WARN); + } + + /* inquire previously defined dimensions */ + + if ((time_dim = ncdimid (exoid, DIM_TIME)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate time dimension in file id %d", exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + if ((num_nod_dim = ncdimid (exoid, DIM_NUM_NODES)) == -1) { + if (tolower(*var_type) == 'n') { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes in file id %d", exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + return (EX_FATAL); + } + } + + + if ((strdim = ncdimid (exoid, DIM_STR)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get string length in file id %d",exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + /* put file into define mode */ + + if (ncredef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to put file id %d into define mode", exoid); + ex_err("ex_get_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + + /* define dimensions and variables */ + + if (tolower(*var_type) == 'g') + { + if ((dimid = ncdimdef (exoid, DIM_NUM_GLO_VAR, (long)num_vars)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: global variable name parameters are already defined in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of global variables in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + + dims[0] = time_dim; + dims[1] = dimid; + if ((ncvardef (exoid, VAR_GLO_VAR, + nc_flt_code(exoid), 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define global variables in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* Now define global variable name variable */ + dims[0] = dimid; + dims[1] = strdim; + if ((ncvardef (exoid, VAR_NAME_GLO_VAR, NC_CHAR, 2, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: global variable names are already defined in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define global variable names in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + } + + else if (tolower(*var_type) == 'n') + { + /* + * There are two ways to store the nodal variables. The old way * + * was a blob (#times,#vars,#nodes), but that was exceeding the + * netcdf maximum dataset size for large models. The new way is + * to store #vars separate datasets each of size (#times,#nodes) + * + * We want this routine to be capable of storing both formats + * based on some external flag. Since the storage format of the + * coordinates have also been changed, we key off of their + * storage type to decide which method to use for nodal + * variables. If the variable 'coord' is defined, then store old + * way; otherwise store new. + */ + if ((dimid = ncdimdef (exoid, DIM_NUM_NOD_VAR, (long)num_vars)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: nodal variable name parameters are already defined in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of nodal variables in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + if (ex_large_model(exoid) == 0) { /* Old way */ + dims[0] = time_dim; + dims[1] = dimid; + dims[2] = num_nod_dim; + if ((ncvardef (exoid, VAR_NOD_VAR, + nc_flt_code(exoid), 3, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define nodal variables in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } else { /* New way */ + int i; + for (i = 1; i <= num_vars; i++) { + dims[0] = time_dim; + dims[1] = num_nod_dim; + if ((ncvardef (exoid, VAR_NOD_VAR_NEW(i), + nc_flt_code(exoid), 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define nodal variable %d in file id %d", + i, exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + } + + /* Now define nodal variable name variable */ + dims[0] = dimid; + dims[1] = strdim; + if ((ncvardef (exoid, VAR_NAME_NOD_VAR, NC_CHAR, 2, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: nodal variable names are already defined in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define nodal variable names in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + } + + else if (tolower(*var_type) == 'e') + { + if ((dimid = ncdimdef (exoid, DIM_NUM_ELE_VAR, (long)num_vars)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element variable name parameters are already defined in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of element variables in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + /* Now define element variable name variable */ + dims[0] = dimid; + dims[1] = strdim; + if ((ncvardef (exoid, VAR_NAME_ELE_VAR, NC_CHAR, 2, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element variable names are already defined in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define element variable names in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + + /* netCDF variables in which to store the EXODUS element variable values will + * be defined in ex_put_elem_var_tab or ex_put_elem_var; at this point, we + * don't know what element variables are valid for which element blocks + * (the info that is stored in the element variable truth table) + */ + } + + /* leave define mode */ + + if (ncendef (exoid) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to complete definition in file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + return(EX_NOERR); + + /* Fatal error: exit definition mode and return */ + error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expvpc.c b/Utilities/vtkexodus2/expvpc.c new file mode 100644 index 0000000..5340c22 --- /dev/null +++ b/Utilities/vtkexodus2/expvpc.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expvp - ex_put_concat_var_param +* +* author - Sandia National Laboratories +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int num_g global variable count +* int num_n nodal variable count +* int num_e element variable count +* int num_elem_blk number of element blocks +* int* elem_var_tab element variable truth table array +* +* exit conditions - +* +* revision history - +* +* $Id: expvpc.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +#include +/* + * writes the number of global, nodal, and element variables + * that will be written to the database + */ + +int ex_put_concat_var_param (int exoid, + int num_g, + int num_n, + int num_e, + int num_elem_blk, + int *elem_var_tab) +{ + int time_dim, num_nod_dim, dimid, strdim, varid, iresult; + long idum, start[2], count[2]; + int numelblkdim, numelvardim; + nclong *stat_vals, *lptr; + int i, j, k, id, *ids; + int dims[3]; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + + /* inquire previously defined dimensions */ + + if ((time_dim = ncdimid (exoid, DIM_TIME)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate time dimension in file id %d", exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + if ((num_nod_dim = ncdimid (exoid, DIM_NUM_NODES)) == -1) + { + if (num_n > 0) { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of nodes in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + } + + if ((strdim = ncdimid (exoid, DIM_STR)) < 0) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get string length in file id %d",exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + /* put file into define mode */ + + if (num_e > 0) { + if ((numelblkdim = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element blocks defined in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element blocks in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + return (EX_FATAL); + } + + if (ncdiminq (exoid, numelblkdim, (char *) 0, &idum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + + if (idum != num_elem_blk) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: # of element blocks doesn't match those specified in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + /* get element block IDs */ + if (!(ids = malloc(num_elem_blk*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element block id array for file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + ex_get_elem_blk_ids (exoid, ids); + + /* Get element block status array for later use */ + + if (!(stat_vals = malloc(num_elem_blk*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + free(ids); + sprintf(errmsg, + "Error: failed to allocate memory for element block status array for file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + + /* get variable id of status array */ + if ((varid = ncvarid (exoid, VAR_STAT_EL_BLK)) != -1) + { + /* if status array exists (V 2.01+), use it, otherwise assume + object exists to be backward compatible */ + + start[0] = 0; + start[1] = 0; + count[0] = num_elem_blk; + count[1] = 0; + + if (ncvarget (exoid, varid, start, count, (void *)stat_vals) == -1) + { + exerrval = ncerr; + free(stat_vals); + sprintf(errmsg, + "Error: failed to get element block status array from file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + } + else + { + /* status array doesn't exist (V2.00), dummy one up for later checking */ + for(i=0;i 0) + { + if ((dimid = ncdimdef (exoid, DIM_NUM_GLO_VAR, (long)num_g)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: global variable name parameters are already defined in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of global variables in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + + dims[0] = time_dim; + dims[1] = dimid; + if ((ncvardef (exoid, VAR_GLO_VAR, + nc_flt_code(exoid), 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define global variables in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + + /* Now define global variable name variable */ + dims[0] = dimid; + dims[1] = strdim; + if ((ncvardef (exoid, VAR_NAME_GLO_VAR, NC_CHAR, 2, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: global variable names are already defined in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define global variable names in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + } + + if (num_n > 0) + { + /* + * There are two ways to store the nodal variables. The old way * + * was a blob (#times,#vars,#nodes), but that was exceeding the + * netcdf maximum dataset size for large models. The new way is + * to store #vars separate datasets each of size (#times,#nodes) + * + * We want this routine to be capable of storing both formats + * based on some external flag. Since the storage format of the + * coordinates have also been changed, we key off of their + * storage type to decide which method to use for nodal + * variables. If the variable 'coord' is defined, then store old + * way; otherwise store new. + */ + if ((dimid = ncdimdef (exoid, DIM_NUM_NOD_VAR, (long)num_n)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: nodal variable name parameters are already defined in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of nodal variables in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + if (ex_large_model(exoid) == 0) { /* Old way */ + dims[0] = time_dim; + dims[1] = dimid; + dims[2] = num_nod_dim; + if ((ncvardef (exoid, VAR_NOD_VAR, + nc_flt_code(exoid), 3, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define nodal variables in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } else { /* Store new way */ + for (i = 1; i <= num_n; i++) { + dims[0] = time_dim; + dims[1] = num_nod_dim; + if ((ncvardef (exoid, VAR_NOD_VAR_NEW(i), + nc_flt_code(exoid), 2, dims)) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define nodal variable %d in file id %d", + i, exoid); + ex_err("ex_put_var_param",errmsg,exerrval); + goto error_ret; /* exit define mode and return */ + } + } + } + /* Now define nodal variable name variable */ + dims[0] = dimid; + dims[1] = strdim; + if ((ncvardef (exoid, VAR_NAME_NOD_VAR, NC_CHAR, 2, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: nodal variable names are already defined in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define nodal variable names in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + } + + if (num_e > 0) + { + if ((numelvardim = ncdimdef (exoid, DIM_NUM_ELE_VAR, (long)num_e)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element variable name parameters are already defined in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define number of element variables in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + /* Now define element variable name variable */ + dims[0] = numelvardim; + dims[1] = strdim; + if ((ncvardef (exoid, VAR_NAME_ELE_VAR, NC_CHAR, 2, dims)) == -1) + { + if (ncerr == NC_ENAMEINUSE) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: element variable names are already defined in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to define element variable names in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + goto error_ret; /* exit define mode and return */ + } + + k = 0; + for (i=0; i 0) { + /* this contortion is necessary because netCDF is expecting nclongs; fortunately + it's necessary only when ints and nclongs aren't the same size */ + + start[0] = 0; + start[1] = 0; + + count[0] = num_elem_blk; + count[1] = num_e; + + if (sizeof(int) == sizeof(nclong)) { + iresult = ncvarput (exoid, varid, start, count, elem_var_tab); + } else { + lptr = itol (elem_var_tab, (int)(num_elem_blk*num_e)); + iresult = ncvarput (exoid, varid, start, count, lptr); + free(lptr); + } + + if (iresult == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to store element variable truth table in file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + return (EX_FATAL); + } + } + return(EX_NOERR); + + /* Fatal error: exit definition mode and return */ + error_ret: + if (ncendef (exoid) == -1) /* exit define mode */ + { + sprintf(errmsg, + "Error: failed to complete definition for file id %d", + exoid); + ex_err("ex_put_concat_var_param",errmsg,exerrval); + } + return (EX_FATAL); +} diff --git a/Utilities/vtkexodus2/expvtt.c b/Utilities/vtkexodus2/expvtt.c new file mode 100644 index 0000000..054a247 --- /dev/null +++ b/Utilities/vtkexodus2/expvtt.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 1994 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement + * retains certain rights in this software. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Sandia Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/***************************************************************************** +* +* expvtt - ex_put_elem_var_tab +* +* author - Sandia National Laboratories +* Larry A. Schoof - Original +* James A. Schutt - 8 byte float and standard C definitions +* Vic Yarberry - Added headers and error logging +* +* +* environment - UNIX +* +* entry conditions - +* input parameters: +* int exoid exodus file id +* int num_elem_blk number of element blocks +* int num_elem_var number of element variables +* int* elem_var_tab element variable truth table array +* +* exit conditions - +* +* revision history - +* +* $Id: expvtt.c,v 1.1 2005/07/17 15:44:00 andy Exp $ +* +*****************************************************************************/ + +#include +#include "exodusII.h" +#include "exodusII_int.h" + +/* + * writes the EXODUS II element variable truth table to the database; + * also, creates netCDF variables in which to store EXODUS II element + * variable values; although this table isn't required (because the + * netCDF variables can also be created in ex_put_elem_var), this call + * will save tremendous time because all of the variables are defined + * at once while the file is in define mode, rather than going in and out + * of define mode (causing the entire file to be copied over and over) + * which is what occurs when the element variable values variables are + * defined in ex_put_elem_var + */ + +int ex_put_elem_var_tab (int exoid, + int num_elem_blk, + int num_elem_var, + int *elem_var_tab) +{ + int numelblkdim, numelvardim, dims[2], varid, iresult; + long idum, start[2], count[2]; + nclong *stat_vals, *lptr; + int i, j, k, id, *ids; + char errmsg[MAX_ERR_LENGTH]; + + exerrval = 0; /* clear error code */ + +/* inquire id's of previously defined dimensions */ + + if ((numelblkdim = ncdimid (exoid, DIM_NUM_EL_BLK)) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element blocks defined in file id %d", + exoid); + ex_err("ex_put_var_tab",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate number of element blocks in file id %d", + exoid); + ex_err("ex_put_var_tab",errmsg,exerrval); + } + return (EX_FATAL); + } + + if (ncdiminq (exoid, numelblkdim, (char *) 0, &idum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element blocks in file id %d", + exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + + if (idum != num_elem_blk) + { + exerrval = EX_FATAL; + sprintf(errmsg, + "Error: # of element blocks doesn't match those specified in file id %d", + exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + if ((numelvardim = ncdimid (exoid, DIM_NUM_ELE_VAR)) == -1) + { + if (ncerr == NC_EBADDIM) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: no element variables defined in file id %d", + exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + } + else + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to locate element variable parameters in file id %d", exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + } + return (EX_FATAL); + } + + if (ncdiminq (exoid, numelvardim, (char *) 0, &idum) == -1) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: failed to get number of element variables in file id %d", + exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + + if (idum != num_elem_var) + { + exerrval = ncerr; + sprintf(errmsg, + "Error: # of element variables doesn't match those defined in file id %d", + exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + +/* get element block IDs */ + if (!(ids = malloc(num_elem_blk*sizeof(int)))) + { + exerrval = EX_MEMFAIL; + sprintf(errmsg, + "Error: failed to allocate memory for element block id array for file id %d", + exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + ex_get_elem_blk_ids (exoid, ids); + + /* Get element block status array for later use */ + + if (!(stat_vals = malloc(num_elem_blk*sizeof(nclong)))) + { + exerrval = EX_MEMFAIL; + free(ids); + sprintf(errmsg, +"Error: failed to allocate memory for element block status array for file id %d", + exoid); + ex_err("ex_put_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + + /* get variable id of status array */ + if ((varid = ncvarid (exoid, VAR_STAT_EL_BLK)) != -1) + { + /* if status array exists (V 2.01+), use it, otherwise assume + object exists to be backward compatible */ + + start[0] = 0; + start[1] = 0; + count[0] = num_elem_blk; + count[1] = 0; + + if (ncvarget (exoid, varid, start, count, (void *)stat_vals) == -1) + { + exerrval = ncerr; + free(stat_vals); + sprintf(errmsg, + "Error: failed to get element block status array from file id %d", + exoid); + ex_err("put_elem_var_tab",errmsg,exerrval); + return (EX_FATAL); + } + } + else + { + /* status array doesn't exist (V2.00), dummy one up for later checking */ + for(i=0;i +#endif +#endif + +#ifdef _MSC_VER +# pragma warning ( disable : 4127 ) +# pragma warning ( disable : 4706 ) +# pragma warning ( disable : 4701 ) +#endif + + +#include + +/* these should be defined in ANSI C, and probably C++, but just in case ... */ + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +#ifndef NULL +#define NULL 0 +#endif + +/* EXODUS II version number */ + +/* ExodusII file version */ +#define EX_VERS 3.01 +/* ExodusII access library version */ +#define EX_API_VERS 4.17 + +/* Exodus error return codes - function return values: */ +#define EX_FATAL -1 /* fatal error flag def */ +#define EX_NOERR 0 /* no error flag def */ +#define EX_WARN 1 /* warning flag def */ + +/* + * This file contains defined constants that are used internally in the + * EXODUS II API. + * + * The first group of constants refer to netCDF variables, attributes, or + * dimensions in which the EXODUS II data are stored. Using the defined + * constants will allow the names of the netCDF entities to be changed easily + * in the future if needed. The first three letters of the constant identify + * the netCDF entity as a variable (VAR), dimension (DIM), or attribute (ATT). + * + * NOTE: The entity name should not have any blanks in it. Blanks are + * technically legal but some netcdf utilities (ncgen in particular) + * fail when they encounter a blank in a name. + * + * DEFINED CONSTANT ENTITY NAME DATA STORED IN ENTITY + */ +#define ATT_FILE_TYPE "type" /* obsolete */ +#define ATT_TITLE "title" /* the database title */ +#define ATT_API_VERSION "api_version" /* the EXODUS II api vers # */ +#define ATT_API_VERSION_BLANK "api version" /* the EXODUS II api vers # */ + /* used for db version 2.01 */ + /* and earlier */ +#define ATT_VERSION "version" /* the EXODUS II file vers # */ +#define ATT_FILESIZE "file_size" /* 1=large, 0=normal */ +#define ATT_FLT_WORDSIZE "floating_point_word_size" + /* word size of floating */ + /* point numbers in file */ +#define ATT_FLT_WORDSIZE_BLANK "floating point word size" + /* word size of floating */ + /* point numbers in file */ + /* used for db version 2.01 */ + /* and earlier */ +#define DIM_NUM_NODES "num_nodes" /* # of nodes */ +#define DIM_NUM_DIM "num_dim" /* # of dimensions; 2- or 3-d*/ +#define DIM_NUM_ELEM "num_elem" /* # of elements */ +#define DIM_NUM_EL_BLK "num_el_blk" /* # of element blocks */ +#define VAR_COORD "coord" /* nodal coordinates */ +#define VAR_COORD_X "coordx" /* X-dimension coordinate */ +#define VAR_COORD_Y "coordy" /* Y-dimension coordinate */ +#define VAR_COORD_Z "coordz" /* Z-dimension coordinate */ +#define VAR_NAME_COOR "coor_names" /* names of coordinates */ +#define VAR_STAT_EL_BLK "eb_status" /* element block status */ +#define VAR_ID_EL_BLK "eb_prop1" /* element block ids props */ +#define ATT_NAME_ELB "elem_type" /* element type names for */ + /* each element block */ +#define DIM_NUM_EL_IN_BLK(num) ex_catstr("num_el_in_blk",num) + /* # of elements in element */ + /* block num */ +#define DIM_NUM_NOD_PER_EL(num) ex_catstr("num_nod_per_el",num) + /* # of nodes per element in */ + /* element block num */ +#define DIM_NUM_ATT_IN_BLK(num) ex_catstr("num_att_in_blk",num) + /* # of attributes in element*/ + /* block num */ +#define VAR_CONN(num) ex_catstr("connect",num) + /* element connectivity for */ + /* element block num */ +#define VAR_ATTRIB(num) ex_catstr("attrib",num) + /* list of attributes for */ + /* element block num */ +#define VAR_EB_PROP(num) ex_catstr("eb_prop",num) + /* list of the numth property*/ + /* for all element blocks */ +#define ATT_PROP_NAME "name" /* name attached to element */ + /* block, node set, side */ + /* set, element map, or */ + /* map properties */ +#define VAR_MAP "elem_map" /* element order map */ + /* obsolete, replaced by */ + /* VAR_ELEM_MAP(num) */ +#define DIM_NUM_SS "num_side_sets" /* # of side sets */ +#define VAR_SS_STAT "ss_status" /* side set status */ +#define VAR_SS_IDS "ss_prop1" /* side set id properties */ +#define DIM_NUM_SIDE_SS(num) ex_catstr("num_side_ss",num) + /* # of sides in side set num*/ +#define DIM_NUM_DF_SS(num) ex_catstr("num_df_ss",num) + /* # of distribution factors */ + /* in side set num */ +/*#define DIM_NUM_NOD_SS(num) ex_catstr("num_nod_ss",num) *** obsolete *** */ + /* # of nodes in side set num*/ +#define VAR_FACT_SS(num) ex_catstr("dist_fact_ss",num) + /* the distribution factors */ + /* for each node in side */ + /* set num */ +#define VAR_ELEM_SS(num) ex_catstr("elem_ss",num) + /* list of elements in side */ + /* set num */ +#define VAR_SIDE_SS(num) ex_catstr("side_ss",num) + /* list of sides in side set */ +#define VAR_SS_PROP(num) ex_catstr("ss_prop",num) + /* list of the numth property*/ + /* for all side sets */ +#define DIM_NUM_NS "num_node_sets" /* # of node sets */ +#define DIM_NUM_NOD_NS(num) ex_catstr("num_nod_ns",num) + /* # of nodes in node set */ + /* num */ +#define DIM_NUM_DF_NS(num) ex_catstr("num_df_ns",num) + /* # of distribution factors */ + /* in node set num */ +#define VAR_NS_STAT "ns_status" /* node set status */ +#define VAR_NS_IDS "ns_prop1" /* node set id properties */ +#define VAR_NODE_NS(num) ex_catstr("node_ns",num) + /* list of nodes in node set */ + /* num */ +#define VAR_FACT_NS(num) ex_catstr("dist_fact_ns",num) + /* list of distribution */ + /* factors in node set num */ +#define VAR_NS_PROP(num) ex_catstr("ns_prop",num) + /* list of the numth property*/ + /* for all node sets */ +#define DIM_NUM_QA "num_qa_rec" /* # of QA records */ +#define VAR_QA_TITLE "qa_records" /* QA records */ +#define DIM_NUM_INFO "num_info" /* # of information records */ +#define VAR_INFO "info_records" /* information records */ +#define VAR_HIS_TIME "time_hist" /* obsolete */ +#define VAR_WHOLE_TIME "time_whole" /* simulation times for whole*/ + /* time steps */ +#define VAR_ELEM_TAB "elem_var_tab" /* element variable truth */ + /* table */ +#define DIM_NUM_GLO_VAR "num_glo_var" /* # of global variables */ +#define VAR_NAME_GLO_VAR "name_glo_var" /* names of global variables */ +#define VAR_GLO_VAR "vals_glo_var" /* values of global variables*/ +#define DIM_NUM_NOD_VAR "num_nod_var" /* # of nodal variables */ +#define VAR_NAME_NOD_VAR "name_nod_var" /* names of nodal variables */ +#define VAR_NOD_VAR "vals_nod_var" /* values of nodal variables */ +#define VAR_NOD_VAR_NEW(num) ex_catstr("vals_nod_var",num) + /* values of nodal variables */ +#define DIM_NUM_ELE_VAR "num_elem_var" /* # of element variables */ +#define VAR_NAME_ELE_VAR "name_elem_var" /* names of element variables*/ +#define VAR_ELEM_VAR(num1,num2) ex_catstr2("vals_elem_var",num1,"eb",num2) + /* values of element variable*/ + /* num1 in element block */ + /* num2 */ +#define DIM_NUM_HIS_VAR "num_his_var" /* obsolete */ +#define VAR_NAME_HIS_VAR "name_his_var" /* obsolete */ +#define VAR_HIS_VAR "vals_his_var" /* obsolete */ +#define DIM_STR "len_string" /* general dimension of */ + /* length MAX_STR_LENGTH */ + /* used for name lengths */ +#define DIM_LIN "len_line" /* general dimension of */ + /* length MAX_LINE_LENGTH */ + /* used for long strings */ +#define DIM_N4 "four" /* general dimension of */ + /* length 4 */ +#define DIM_TIME "time_step" /* unlimited (expandable) */ + /* dimension for time steps*/ +#define DIM_HTIME "hist_time_step"/* obsolete */ +#define VAR_ELEM_NUM_MAP "elem_num_map" /* element numbering map */ + /* obsolete, replaced by */ + /* VAR_ELEM_MAP(num) */ +#define VAR_NODE_NUM_MAP "node_num_map" /* node numbering map */ + /* obsolete, replaced by */ + /* VAR_NODE_MAP(num) */ +#define DIM_NUM_EM "num_elem_maps" /* # of element maps */ +#define VAR_ELEM_MAP(num) ex_catstr("elem_map",num) + /* the numth element map */ +#define VAR_EM_PROP(num) ex_catstr("em_prop",num) + /* list of the numth property*/ + /* for all element maps */ +#define DIM_NUM_NM "num_node_maps" /* # of node maps */ +#define VAR_NODE_MAP(num) ex_catstr("node_map",num) + /* the numth node map */ +#define VAR_NM_PROP(num) ex_catstr("nm_prop",num) + /* list of the numth property*/ + /* for all node maps */ + +#define NUM_CFRAMES "num_cframes" +#define NUM_CFRAME9 "num_cframes_9" +#define FRAME_COORDS "frame_coordinates" +#define FRAME_IDS "frame_ids" +#define FRAME_TAGS "frame_tags" + + +#define UNK -1 /* unknown entity */ +#define TRIANGLE 1 /* Triangle entity */ +#define QUAD 2 /* Quad entity */ +#define HEX 3 /* Hex entity */ +#define WEDGE 4 /* Wedge entity */ +#define TETRA 5 /* Tetra entity */ +#define TRUSS 6 /* Truss entity */ +#define BEAM 7 /* Beam entity */ +#define SHELL 8 /* Shell entity */ +#define SPHERE 9 /* Sphere entity */ +#define CIRCLE 10 /* Circle entity */ +#define TRISHELL 11 /* Triangular Shell */ +#define PYRAMID 12 /* Pyramid */ +/* Internal structure declarations */ + +struct list_item { /* for use with ex_get_file_item */ + + int exo_id; + int value; + struct list_item* next; +}; + +struct obj_stats { + int *id_vals; + int *stat_vals; + long num; + int exoid; + int valid_ids; + int valid_stat; + struct obj_stats *next; +}; + + +void ex_iqsort (int v[], int iv[], int count ); +char *ex_catstr (const char*, int); +char *ex_catstr2 (const char*, int, const char*, int); + +enum convert_task { RTN_ADDRESS, + READ_CONVERT, + WRITE_CONVERT, + WRITE_CONVERT_DOWN, + WRITE_CONVERT_UP }; + +int ex_conv_ini ( int, int*, int*, int); +void ex_conv_exit (int); +nc_type nc_flt_code (int); +int ex_comp_ws (int); +void* ex_conv_array (int, int, const void*, int); +int ex_get_cpu_ws(); + +void ex_rm_file_item_eb (int); +void ex_rm_file_item_ns (int); +void ex_rm_file_item_ss (int); + +extern struct list_item* eb_ctr_list; +extern struct list_item* ns_ctr_list; +extern struct list_item* ss_ctr_list; +extern struct list_item* em_ctr_list; +extern struct list_item* nm_ctr_list; + +int ex_get_file_item ( int, struct list_item**); +int ex_inc_file_item ( int, struct list_item**); +void ex_rm_file_item (int, struct list_item**); + +extern struct obj_stats* eb; +extern struct obj_stats* ns; +extern struct obj_stats* ss; +extern struct obj_stats* em; +extern struct obj_stats* nm; + +int ex_get_side_set_node_list_len (int, int, int*); +struct obj_stats *get_stat_ptr ( int, struct obj_stats**); +void rm_stat_ptr (int, struct obj_stats**); + +int ex_id_lkup ( int exoid, char *id_type, int num); +int ex_large_model(int exoid); +#endif diff --git a/Utilities/vtkexpat/.NoDartCoverage b/Utilities/vtkexpat/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/vtkexpat/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/vtkexpat/CMakeLists.txt b/Utilities/vtkexpat/CMakeLists.txt new file mode 100644 index 0000000..a1b4abb --- /dev/null +++ b/Utilities/vtkexpat/CMakeLists.txt @@ -0,0 +1,38 @@ +PROJECT(VTKEXPAT) +INCLUDE_REGULAR_EXPRESSION("^(expat|xml|ascii|utf|name|iascii|latin|vtk).*$") + +SET(expat_SRCS + xmlparse.c + xmltok.c + xmlrole.c +) + +INCLUDE_DIRECTORIES(${VTKEXPAT_SOURCE_DIR}) + +IF(WIN32) + IF(NOT BUILD_SHARED_LIBS) + SET (VTK_EXPAT_STATIC 1) + ENDIF(NOT BUILD_SHARED_LIBS) +ENDIF(WIN32) + +CONFIGURE_FILE(${VTKEXPAT_SOURCE_DIR}/expatConfig.h.in + ${VTKEXPAT_BINARY_DIR}/expatConfig.h) +CONFIGURE_FILE(${VTKEXPAT_SOURCE_DIR}/expatDllConfig.h.in + ${VTKEXPAT_BINARY_DIR}/expatDllConfig.h) +CONFIGURE_FILE(${VTKEXPAT_SOURCE_DIR}/.NoDartCoverage + ${VTKEXPAT_BINARY_DIR}/.NoDartCoverage) + +ADD_LIBRARY(vtkexpat ${expat_SRCS}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkexpat PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkexpat) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtkexpat .h + expat expatDllConfig vtk_expat_mangle) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/vtkexpat/COPYING b/Utilities/vtkexpat/COPYING new file mode 100644 index 0000000..fc97b02 --- /dev/null +++ b/Utilities/vtkexpat/COPYING @@ -0,0 +1,21 @@ +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd + and Clark Cooper + +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. diff --git a/Utilities/vtkexpat/ascii.h b/Utilities/vtkexpat/ascii.h new file mode 100644 index 0000000..6376b1f --- /dev/null +++ b/Utilities/vtkexpat/ascii.h @@ -0,0 +1,86 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +#define ASCII_A 0x41 +#define ASCII_B 0x42 +#define ASCII_C 0x43 +#define ASCII_D 0x44 +#define ASCII_E 0x45 +#define ASCII_F 0x46 +#define ASCII_G 0x47 +#define ASCII_H 0x48 +#define ASCII_I 0x49 +#define ASCII_J 0x4A +#define ASCII_K 0x4B +#define ASCII_L 0x4C +#define ASCII_M 0x4D +#define ASCII_N 0x4E +#define ASCII_O 0x4F +#define ASCII_P 0x50 +#define ASCII_Q 0x51 +#define ASCII_R 0x52 +#define ASCII_S 0x53 +#define ASCII_T 0x54 +#define ASCII_U 0x55 +#define ASCII_V 0x56 +#define ASCII_W 0x57 +#define ASCII_X 0x58 +#define ASCII_Y 0x59 +#define ASCII_Z 0x5A + +#define ASCII_a 0x61 +#define ASCII_b 0x62 +#define ASCII_c 0x63 +#define ASCII_d 0x64 +#define ASCII_e 0x65 +#define ASCII_f 0x66 +#define ASCII_g 0x67 +#define ASCII_h 0x68 +#define ASCII_i 0x69 +#define ASCII_j 0x6A +#define ASCII_k 0x6B +#define ASCII_l 0x6C +#define ASCII_m 0x6D +#define ASCII_n 0x6E +#define ASCII_o 0x6F +#define ASCII_p 0x70 +#define ASCII_q 0x71 +#define ASCII_r 0x72 +#define ASCII_s 0x73 +#define ASCII_t 0x74 +#define ASCII_u 0x75 +#define ASCII_v 0x76 +#define ASCII_w 0x77 +#define ASCII_x 0x78 +#define ASCII_y 0x79 +#define ASCII_z 0x7A + +#define ASCII_0 0x30 +#define ASCII_1 0x31 +#define ASCII_2 0x32 +#define ASCII_3 0x33 +#define ASCII_4 0x34 +#define ASCII_5 0x35 +#define ASCII_6 0x36 +#define ASCII_7 0x37 +#define ASCII_8 0x38 +#define ASCII_9 0x39 + +#define ASCII_TAB 0x09 +#define ASCII_SPACE 0x20 +#define ASCII_EXCL 0x21 +#define ASCII_QUOT 0x22 +#define ASCII_AMP 0x26 +#define ASCII_APOS 0x27 +#define ASCII_MINUS 0x2D +#define ASCII_PERIOD 0x2E +#define ASCII_COLON 0x3A +#define ASCII_SEMI 0x3B +#define ASCII_LT 0x3C +#define ASCII_EQUALS 0x3D +#define ASCII_GT 0x3E +#define ASCII_LSQB 0x5B +#define ASCII_RSQB 0x5D +#define ASCII_UNDERSCORE 0x5F diff --git a/Utilities/vtkexpat/asciitab.h b/Utilities/vtkexpat/asciitab.h new file mode 100644 index 0000000..eb445cc --- /dev/null +++ b/Utilities/vtkexpat/asciitab.h @@ -0,0 +1,37 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, +/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, +/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, +/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, +/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, +/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, +/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, +/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, +/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, +/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, +/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/Utilities/vtkexpat/expat.h b/Utilities/vtkexpat/expat.h new file mode 100644 index 0000000..718b2b7 --- /dev/null +++ b/Utilities/vtkexpat/expat.h @@ -0,0 +1,740 @@ +#include "vtk_expat_mangle.h" +/* +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +#ifndef XmlParse_INCLUDED +#define XmlParse_INCLUDED 1 + +#include + +#include + +#if defined(_WIN32) && !defined(VTK_EXPAT_STATIC) +# if defined(vtkexpat_EXPORTS) +# define XMLPARSEAPI(type) __declspec( dllexport ) type __cdecl +# else +# define XMLPARSEAPI(type) __declspec( dllimport ) type __cdecl +# endif +#else +# define XMLPARSEAPI(type) type +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *XML_Parser; + +/* Information is UTF-8 encoded. */ +typedef char XML_Char; +typedef char XML_LChar; + +enum XML_Content_Type { + XML_CTYPE_EMPTY = 1, + XML_CTYPE_ANY, + XML_CTYPE_MIXED, + XML_CTYPE_NAME, + XML_CTYPE_CHOICE, + XML_CTYPE_SEQ +}; + +enum XML_Content_Quant { + XML_CQUANT_NONE, + XML_CQUANT_OPT, + XML_CQUANT_REP, + XML_CQUANT_PLUS +}; + +/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be + XML_CQUANT_NONE, and the other fields will be zero or NULL. + If type == XML_CTYPE_MIXED, then quant will be NONE or REP and + numchildren will contain number of elements that may be mixed in + and children point to an array of XML_Content cells that will be + all of XML_CTYPE_NAME type with no quantification. + + If type == XML_CTYPE_NAME, then the name points to the name, and + the numchildren field will be zero and children will be NULL. The + quant fields indicates any quantifiers placed on the name. + + CHOICE and SEQ will have name NULL, the number of children in + numchildren and children will point, recursively, to an array + of XML_Content cells. + + The EMPTY, ANY, and MIXED types will only occur at top level. +*/ + +typedef struct XML_cp XML_Content; + +struct XML_cp { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + XML_Char * name; + unsigned int numchildren; + XML_Content * children; +}; + + +/* This is called for an element declaration. See above for + description of the model argument. It's the caller's responsibility + to free model when finished with it. +*/ + +typedef void (*XML_ElementDeclHandler) (void *userData, + const XML_Char *name, + XML_Content *model); + +XMLPARSEAPI(void) +XML_SetElementDeclHandler(XML_Parser parser, + XML_ElementDeclHandler eldecl); + +/* + The Attlist declaration handler is called for *each* attribute. So + a single Attlist declaration with multiple attributes declared will + generate multiple calls to this handler. The "default" parameter + may be NULL in the case of the "#IMPLIED" or "#REQUIRED" keyword. + The "isrequired" parameter will be true and the default value will + be NULL in the case of "#REQUIRED". If "isrequired" is true and + default is non-NULL, then this is a "#FIXED" default. + */ + +typedef void (*XML_AttlistDeclHandler) (void *userData, + const XML_Char *elname, + const XML_Char *attname, + const XML_Char *att_type, + const XML_Char *dflt, + int isrequired); + +XMLPARSEAPI(void) +XML_SetAttlistDeclHandler(XML_Parser parser, + XML_AttlistDeclHandler attdecl); + + + /* The XML declaration handler is called for *both* XML declarations and + text declarations. The way to distinguish is that the version parameter + will be null for text declarations. The encoding parameter may be null + for XML declarations. The standalone parameter will be -1, 0, or 1 + indicating respectively that there was no standalone parameter in + the declaration, that it was given as no, or that it was given as yes. + */ + +typedef void (*XML_XmlDeclHandler) (void *userData, + const XML_Char *version, + const XML_Char *encoding, + int standalone); + +XMLPARSEAPI(void) +XML_SetXmlDeclHandler(XML_Parser parser, + XML_XmlDeclHandler xmldecl); + + +typedef struct { + void *(*malloc_fcn)(size_t size); + void *(*realloc_fcn)(void *ptr, size_t size); + void (*free_fcn)(void *ptr); +} XML_Memory_Handling_Suite; + +/* Constructs a new parser; encoding is the encoding specified by the +external protocol or null if there is none specified. */ + +XMLPARSEAPI(XML_Parser) +XML_ParserCreate(const XML_Char *encoding); + +/* Constructs a new parser and namespace processor. Element type +names and attribute names that belong to a namespace will be expanded; +unprefixed attribute names are never expanded; unprefixed element type +names are expanded only if there is a default namespace. The expanded +name is the concatenation of the namespace URI, the namespace +separator character, and the local part of the name. If the namespace +separator is '\0' then the namespace URI and the local part will be +concatenated without any separator. When a namespace is not declared, +the name and prefix will be passed through without expansion. */ + +XMLPARSEAPI(XML_Parser) +XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); + + +/* Constructs a new parser using the memory management suit referred to + by memsuite. If memsuite is NULL, then use the standard library memory + suite. If namespaceSeparator is non-NULL it creates a parser with + namespace processing as described above. The character pointed at + will serve as the namespace separator. + + All further memory operations used for the created parser will come from + the given suite. +*/ + +XMLPARSEAPI(XML_Parser) +XML_ParserCreate_MM(const XML_Char *encoding, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *namespaceSeparator); + +/* atts is array of name/value pairs, terminated by 0; + names and values are 0 terminated. */ + +typedef void (*XML_StartElementHandler)(void *userData, + const XML_Char *name, + const XML_Char **atts); + +typedef void (*XML_EndElementHandler)(void *userData, + const XML_Char *name); + + +/* s is not 0 terminated. */ +typedef void (*XML_CharacterDataHandler)(void *userData, + const XML_Char *s, + int len); + +/* target and data are 0 terminated */ +typedef void (*XML_ProcessingInstructionHandler)(void *userData, + const XML_Char *target, + const XML_Char *data); + +/* data is 0 terminated */ +typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data); + +typedef void (*XML_StartCdataSectionHandler)(void *userData); +typedef void (*XML_EndCdataSectionHandler)(void *userData); + +/* This is called for any characters in the XML document for +which there is no applicable handler. This includes both +characters that are part of markup which is of a kind that is +not reported (comments, markup declarations), or characters +that are part of a construct which could be reported but +for which no handler has been supplied. The characters are passed +exactly as they were in the XML document except that +they will be encoded in UTF-8. Line boundaries are not normalized. +Note that a byte order mark character is not passed to the default handler. +There are no guarantees about how characters are divided between calls +to the default handler: for example, a comment might be split between +multiple calls. */ + +typedef void (*XML_DefaultHandler)(void *userData, + const XML_Char *s, + int len); + +/* This is called for the start of the DOCTYPE declaration, before + any DTD or internal subset is parsed. */ + +typedef void (*XML_StartDoctypeDeclHandler)(void *userData, + const XML_Char *doctypeName, + const XML_Char *sysid, + const XML_Char *pubid, + int has_internal_subset); + +/* This is called for the start of the DOCTYPE declaration when the +closing > is encountered, but after processing any external subset. */ +typedef void (*XML_EndDoctypeDeclHandler)(void *userData); + +/* This is called for entity declarations. The is_parameter_entity + argument will be non-zero if the entity is a parameter entity, zero + otherwise. + + For internal entities (), value will + be non-null and systemId, publicID, and notationName will be null. + The value string is NOT null terminated; the length is provided in + the value_length argument. Since it is legal to have zero-length + values, do not use this argument to test for internal entities. + + For external entities, value will be null and systemId will be non-null. + The publicId argument will be null unless a public identifier was + provided. The notationName argument will have a non-null value only + for unparsed entity declarations. +*/ + +typedef void (*XML_EntityDeclHandler) (void *userData, + const XML_Char *entityName, + int is_parameter_entity, + const XML_Char *value, + int value_length, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +XMLPARSEAPI(void) +XML_SetEntityDeclHandler(XML_Parser parser, + XML_EntityDeclHandler handler); + +/* OBSOLETE -- OBSOLETE -- OBSOLETE + This handler has been superceded by the EntityDeclHandler above. + It is provided here for backward compatibility. +This is called for a declaration of an unparsed (NDATA) +entity. The base argument is whatever was set by XML_SetBase. +The entityName, systemId and notationName arguments will never be null. +The other arguments may be. */ + +typedef void (*XML_UnparsedEntityDeclHandler)(void *userData, + const XML_Char *entityName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName); + +/* This is called for a declaration of notation. +The base argument is whatever was set by XML_SetBase. +The notationName will never be null. The other arguments can be. */ + +typedef void (*XML_NotationDeclHandler)(void *userData, + const XML_Char *notationName, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* When namespace processing is enabled, these are called once for +each namespace declaration. The call to the start and end element +handlers occur between the calls to the start and end namespace +declaration handlers. For an xmlns attribute, prefix will be null. +For an xmlns="" attribute, uri will be null. */ + +typedef void (*XML_StartNamespaceDeclHandler)(void *userData, + const XML_Char *prefix, + const XML_Char *uri); + +typedef void (*XML_EndNamespaceDeclHandler)(void *userData, + const XML_Char *prefix); + +/* This is called if the document is not standalone (it has an +external subset or a reference to a parameter entity, but does not +have standalone="yes"). If this handler returns 0, then processing +will not continue, and the parser will return a +XML_ERROR_NOT_STANDALONE error. */ + +typedef int (*XML_NotStandaloneHandler)(void *userData); + +/* This is called for a reference to an external parsed general entity. +The referenced entity is not automatically parsed. +The application can parse it immediately or later using +XML_ExternalEntityParserCreate. +The parser argument is the parser parsing the entity containing the reference; +it can be passed as the parser argument to XML_ExternalEntityParserCreate. +The systemId argument is the system identifier as specified in the entity +declaration; it will not be null. +The base argument is the system identifier that should be used as the base for +resolving systemId if systemId was relative; this is set by XML_SetBase; +it may be null. +The publicId argument is the public identifier as specified in the entity +declaration, or null if none was specified; the whitespace in the public +identifier will have been normalized as required by the XML spec. +The context argument specifies the parsing context in the format +expected by the context argument to +XML_ExternalEntityParserCreate; context is valid only until the handler +returns, so if the referenced entity is to be parsed later, it must be copied. +The handler should return 0 if processing should not continue because of +a fatal error in the handling of the external entity. +In this case the calling parser will return an +XML_ERROR_EXTERNAL_ENTITY_HANDLING error. +Note that unlike other handlers the first argument is the parser, not +userData. */ + +typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser, + const XML_Char *context, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId); + +/* This structure is filled in by the XML_UnknownEncodingHandler +to provide information to the parser about encodings that are unknown +to the parser. +The map[b] member gives information about byte sequences +whose first byte is b. +If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar +value c. +If map[b] is -1, then the byte sequence is malformed. +If map[b] is -n, where n >= 2, then b is the first byte of an n-byte +sequence that encodes a single Unicode scalar value. +The data member will be passed as the first argument to the convert function. +The convert function is used to convert multibyte sequences; +s will point to a n-byte sequence where map[(unsigned char)*s] == -n. +The convert function must return the Unicode scalar value +represented by this byte sequence or -1 if the byte sequence is malformed. +The convert function may be null if the encoding is a single-byte encoding, +that is if map[b] >= -1 for all bytes b. +When the parser is finished with the encoding, then if release is not null, +it will call release passing it the data member; +once release has been called, the convert function will not be called again. + +Expat places certain restrictions on the encodings that are supported +using this mechanism. + +1. Every ASCII character that can appear in a well-formed XML document, +other than the characters + + $@\^`{}~ + +must be represented by a single byte, and that byte must be the +same byte that represents that character in ASCII. + +2. No character may require more than 4 bytes to encode. + +3. All characters encoded must have Unicode scalar values <= 0xFFFF, (i.e., +characters that would be encoded by surrogates in UTF-16 are not +allowed). Note that this restriction doesn't apply to the built-in +support for UTF-8 and UTF-16. + +4. No Unicode character may be encoded by more than one distinct sequence +of bytes. */ + +typedef struct { + int map[256]; + void *data; + int (*convert)(void *data, const char *s); + void (*release)(void *data); +} XML_Encoding; + +/* This is called for an encoding that is unknown to the parser. +The encodingHandlerData argument is that which was passed as the +second argument to XML_SetUnknownEncodingHandler. +The name argument gives the name of the encoding as specified in +the encoding declaration. +If the callback can provide information about the encoding, +it must fill in the XML_Encoding structure, and return 1. +Otherwise it must return 0. +If info does not describe a suitable encoding, +then the parser will return an XML_UNKNOWN_ENCODING error. */ + +typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData, + const XML_Char *name, + XML_Encoding *info); + +XMLPARSEAPI(void) +XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end); + +XMLPARSEAPI(void) +XML_SetStartElementHandler(XML_Parser, XML_StartElementHandler); + +XMLPARSEAPI(void) +XML_SetEndElementHandler(XML_Parser, XML_EndElementHandler); + +XMLPARSEAPI(void) +XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler); + +XMLPARSEAPI(void) +XML_SetProcessingInstructionHandler(XML_Parser parser, + XML_ProcessingInstructionHandler handler); +XMLPARSEAPI(void) +XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler); + +XMLPARSEAPI(void) +XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end); + +XMLPARSEAPI(void) +XML_SetStartCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start); + +XMLPARSEAPI(void) +XML_SetEndCdataSectionHandler(XML_Parser parser, + XML_EndCdataSectionHandler end); + +/* This sets the default handler and also inhibits expansion of +internal entities. The entity reference will be passed to the default +handler. */ + +XMLPARSEAPI(void) +XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler); + +/* This sets the default handler but does not inhibit expansion of +internal entities. The entity reference will not be passed to the +default handler. */ + +XMLPARSEAPI(void) +XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler); + +XMLPARSEAPI(void) +XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndDoctypeDeclHandler(XML_Parser parser, + XML_EndDoctypeDeclHandler end); + +XMLPARSEAPI(void) +XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler); + +XMLPARSEAPI(void) +XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetStartNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start); + +XMLPARSEAPI(void) +XML_SetEndNamespaceDeclHandler(XML_Parser parser, + XML_EndNamespaceDeclHandler end); + +XMLPARSEAPI(void) +XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler); + +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler); + +/* If a non-null value for arg is specified here, then it will be passed +as the first argument to the external entity ref handler instead +of the parser object. */ +XMLPARSEAPI(void) +XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg); + +XMLPARSEAPI(void) +XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *encodingHandlerData); + +/* This can be called within a handler for a start element, end element, +processing instruction or character data. It causes the corresponding +markup to be passed to the default handler. */ +XMLPARSEAPI(void) +XML_DefaultCurrent(XML_Parser parser); + +/* If do_nst is non-zero, and namespace processing is in effect, and + a name has a prefix (i.e. an explicit namespace qualifier) then + that name is returned as a triplet in a single + string separated by the separator character specified when the parser + was created: URI + sep + local_name + sep + prefix. + + If do_nst is zero, then namespace information is returned in the + default manner (URI + sep + local_name) whether or not the names + has a prefix. +*/ + +XMLPARSEAPI(void) +XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); + +/* This value is passed as the userData argument to callbacks. */ +XMLPARSEAPI(void) +XML_SetUserData(XML_Parser parser, void *userData); + +/* Returns the last value set by XML_SetUserData or null. */ +#define XML_GetUserData(parser) (*(void **)(parser)) + +/* This is equivalent to supplying an encoding argument +to XML_ParserCreate. It must not be called after XML_Parse +or XML_ParseBuffer. */ + +XMLPARSEAPI(int) +XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); + +/* If this function is called, then the parser will be passed +as the first argument to callbacks instead of userData. +The userData will still be accessible using XML_GetUserData. */ + +XMLPARSEAPI(void) +XML_UseParserAsHandlerArg(XML_Parser parser); + +/* Sets the base to be used for resolving relative URIs in system +identifiers in declarations. Resolving relative identifiers is left +to the application: this value will be passed through as the base +argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler +and XML_UnparsedEntityDeclHandler. The base argument will be copied. +Returns zero if out of memory, non-zero otherwise. */ + +XMLPARSEAPI(int) +XML_SetBase(XML_Parser parser, const XML_Char *base); + +XMLPARSEAPI(const XML_Char *) +XML_GetBase(XML_Parser parser); + +/* Returns the number of the attribute/value pairs passed in last call +to the XML_StartElementHandler that were specified in the start-tag +rather than defaulted. Each attribute/value pair counts as 2; thus +this correspondds to an index into the atts array passed to the +XML_StartElementHandler. */ + +XMLPARSEAPI(int) +XML_GetSpecifiedAttributeCount(XML_Parser parser); + +/* Returns the index of the ID attribute passed in the last call to +XML_StartElementHandler, or -1 if there is no ID attribute. Each +attribute/value pair counts as 2; thus this correspondds to an index +into the atts array passed to the XML_StartElementHandler. */ + +XMLPARSEAPI(int) +XML_GetIdAttributeIndex(XML_Parser parser); + +/* Parses some input. Returns 0 if a fatal error is detected. +The last call to XML_Parse must have isFinal true; +len may be zero for this call (or any other). */ +XMLPARSEAPI(int) +XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); + +XMLPARSEAPI(void *) +XML_GetBuffer(XML_Parser parser, int len); + +XMLPARSEAPI(int) +XML_ParseBuffer(XML_Parser parser, int len, int isFinal); + +/* Creates an XML_Parser object that can parse an external general +entity; context is a '\0'-terminated string specifying the parse +context; encoding is a '\0'-terminated string giving the name of the +externally specified encoding, or null if there is no externally +specified encoding. The context string consists of a sequence of +tokens separated by formfeeds (\f); a token consisting of a name +specifies that the general entity of the name is open; a token of the +form prefix=uri specifies the namespace for a particular prefix; a +token of the form =uri specifies the default namespace. This can be +called at any point after the first call to an +ExternalEntityRefHandler so longer as the parser has not yet been +freed. The new parser is completely independent and may safely be +used in a separate thread. The handlers and userData are initialized +from the parser argument. Returns 0 if out of memory. Otherwise +returns a new XML_Parser object. */ +XMLPARSEAPI(XML_Parser) +XML_ExternalEntityParserCreate(XML_Parser parser, + const XML_Char *context, + const XML_Char *encoding); + +enum XML_ParamEntityParsing { + XML_PARAM_ENTITY_PARSING_NEVER, + XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, + XML_PARAM_ENTITY_PARSING_ALWAYS +}; + +/* Controls parsing of parameter entities (including the external DTD +subset). If parsing of parameter entities is enabled, then references +to external parameter entities (including the external DTD subset) +will be passed to the handler set with +XML_SetExternalEntityRefHandler. The context passed will be 0. +Unlike external general entities, external parameter entities can only +be parsed synchronously. If the external parameter entity is to be +parsed, it must be parsed during the call to the external entity ref +handler: the complete sequence of XML_ExternalEntityParserCreate, +XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during +this call. After XML_ExternalEntityParserCreate has been called to +create the parser for the external parameter entity (context must be 0 +for this call), it is illegal to make any calls on the old parser +until XML_ParserFree has been called on the newly created parser. If +the library has been compiled without support for parameter entity +parsing (ie without XML_DTD being defined), then +XML_SetParamEntityParsing will return 0 if parsing of parameter +entities is requested; otherwise it will return non-zero. */ + +XMLPARSEAPI(int) +XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing parsing); + +enum XML_Error { + XML_ERROR_NONE, + XML_ERROR_NO_MEMORY, + XML_ERROR_SYNTAX, + XML_ERROR_NO_ELEMENTS, + XML_ERROR_INVALID_TOKEN, + XML_ERROR_UNCLOSED_TOKEN, + XML_ERROR_PARTIAL_CHAR, + XML_ERROR_TAG_MISMATCH, + XML_ERROR_DUPLICATE_ATTRIBUTE, + XML_ERROR_JUNK_AFTER_DOC_ELEMENT, + XML_ERROR_PARAM_ENTITY_REF, + XML_ERROR_UNDEFINED_ENTITY, + XML_ERROR_RECURSIVE_ENTITY_REF, + XML_ERROR_ASYNC_ENTITY, + XML_ERROR_BAD_CHAR_REF, + XML_ERROR_BINARY_ENTITY_REF, + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, + XML_ERROR_MISPLACED_XML_PI, + XML_ERROR_UNKNOWN_ENCODING, + XML_ERROR_INCORRECT_ENCODING, + XML_ERROR_UNCLOSED_CDATA_SECTION, + XML_ERROR_EXTERNAL_ENTITY_HANDLING, + XML_ERROR_NOT_STANDALONE, + XML_ERROR_UNEXPECTED_STATE +}; + +/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode +returns information about the error. */ + +XMLPARSEAPI(enum XML_Error) +XML_GetErrorCode(XML_Parser parser); + +/* These functions return information about the current parse location. +They may be called when XML_Parse or XML_ParseBuffer return 0; +in this case the location is the location of the character at which +the error was detected. +They may also be called from any other callback called to report +some parse event; in this the location is the location of the first +of the sequence of characters that generated the event. */ + +XMLPARSEAPI(int) XML_GetCurrentLineNumber(XML_Parser parser); +XMLPARSEAPI(int) XML_GetCurrentColumnNumber(XML_Parser parser); +XMLPARSEAPI(long) XML_GetCurrentByteIndex(XML_Parser parser); + +/* Return the number of bytes in the current event. +Returns 0 if the event is in an internal entity. */ + +XMLPARSEAPI(int) +XML_GetCurrentByteCount(XML_Parser parser); + +/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets + the integer pointed to by offset to the offset within this buffer + of the current parse position, and sets the integer pointed to by size + to the size of this buffer (the number of input bytes). Otherwise + returns a null pointer. Also returns a null pointer if a parse isn't + active. + + NOTE: The character pointer returned should not be used outside + the handler that makes the call. */ + +XMLPARSEAPI(const char *) +XML_GetInputContext(XML_Parser parser, + int *offset, + int *size); + +/* For backwards compatibility with previous versions. */ +#define XML_GetErrorLineNumber XML_GetCurrentLineNumber +#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber +#define XML_GetErrorByteIndex XML_GetCurrentByteIndex + +/* Frees memory used by the parser. */ +XMLPARSEAPI(void) +XML_ParserFree(XML_Parser parser); + +/* Returns a string describing the error. */ +XMLPARSEAPI(const XML_LChar *) +XML_ErrorString(int code); + +/* Return a string containing the version number of this expat */ +XMLPARSEAPI(const XML_LChar *) +XML_ExpatVersion(void); + +typedef struct { + int major; + int minor; + int micro; +} XML_Expat_Version; + +/* Return an XML_Expat_Version structure containing numeric version + number information for this version of expat */ + +XMLPARSEAPI(XML_Expat_Version) +XML_ExpatVersionInfo(void); + +#define XML_MAJOR_VERSION 1 +#define XML_MINOR_VERSION 95 +#define XML_MICRO_VERSION 2 + +#ifdef __cplusplus +} +#endif + +#endif /* not XmlParse_INCLUDED */ diff --git a/Utilities/vtkexpat/expatConfig.h.in b/Utilities/vtkexpat/expatConfig.h.in new file mode 100644 index 0000000..4128f9d --- /dev/null +++ b/Utilities/vtkexpat/expatConfig.h.in @@ -0,0 +1,43 @@ +#include "vtk_expat_mangle.h" +#if defined(_WIN32) || defined(WIN32) + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#include +#include +#define XML_BYTE_ORDER 12 + +#else + +#cmakedefine CMAKE_WORDS_BIGENDIAN +#ifdef CMAKE_WORDS_BIGENDIAN +# define XML_BYTE_ORDER 21 +#else +# define XML_BYTE_ORDER 12 +#endif + +#endif + +#define XML_NS +#define XML_DTD +#define XML_CONTEXT_BYTES 1024 + +#if defined ( _MSC_VER ) +#pragma warning ( disable : 4100 ) +#pragma warning ( disable : 4127 ) +#pragma warning ( disable : 4244 ) +#pragma warning ( disable : 4251 ) +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4309 ) +#pragma warning ( disable : 4702 ) +#pragma warning ( disable : 4706 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4057 ) +#pragma warning ( disable : 4189 ) +#pragma warning ( disable : 4505 ) +#endif + +#define VERSION "1.95.2" + +#define vtkExpatUnused(x) (void)x diff --git a/Utilities/vtkexpat/expatDllConfig.h.in b/Utilities/vtkexpat/expatDllConfig.h.in new file mode 100644 index 0000000..05c3c50 --- /dev/null +++ b/Utilities/vtkexpat/expatDllConfig.h.in @@ -0,0 +1,6 @@ +#ifndef _expatDllConfig_h +#define _expatDllConfig_h + +#cmakedefine VTK_EXPAT_STATIC + +#endif diff --git a/Utilities/vtkexpat/iasciitab.h b/Utilities/vtkexpat/iasciitab.h new file mode 100644 index 0000000..55dbc39 --- /dev/null +++ b/Utilities/vtkexpat/iasciitab.h @@ -0,0 +1,38 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ +/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, +/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, +/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, +/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, +/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, +/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, +/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, +/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, +/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, +/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, +/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, +/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, +/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, +/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, diff --git a/Utilities/vtkexpat/latin1tab.h b/Utilities/vtkexpat/latin1tab.h new file mode 100644 index 0000000..178b1d1 --- /dev/null +++ b/Utilities/vtkexpat/latin1tab.h @@ -0,0 +1,37 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, +/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, +/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, +/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, +/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, +/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, +/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, diff --git a/Utilities/vtkexpat/nametab.h b/Utilities/vtkexpat/nametab.h new file mode 100644 index 0000000..b05e62c --- /dev/null +++ b/Utilities/vtkexpat/nametab.h @@ -0,0 +1,150 @@ +static const unsigned namingBitmap[] = { +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, +0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, +0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, +0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, +0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, +0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, +0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, +0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, +0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, +0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, +0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, +0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, +0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, +0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, +0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, +0x40000000, 0xF580C900, 0x00000007, 0x02010800, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, +0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, +0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, +0x00000000, 0x00004C40, 0x00000000, 0x00000000, +0x00000007, 0x00000000, 0x00000000, 0x00000000, +0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, +0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, +0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, +0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, +0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, +0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, +0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, +0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, +0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, +0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, +0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, +0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, +0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, +0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, +0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, +0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, +0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, +0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, +0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, +0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, +0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, +0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, +0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, +0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, +0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, +0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, +0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, +0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, +}; +static const unsigned char nmstrtPages[] = { +0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, +0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const unsigned char namePages[] = { +0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, +0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, +0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, +0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/Utilities/vtkexpat/utf8tab.h b/Utilities/vtkexpat/utf8tab.h new file mode 100644 index 0000000..9e3b6b8 --- /dev/null +++ b/Utilities/vtkexpat/utf8tab.h @@ -0,0 +1,38 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + + +/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, +/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, +/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, +/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, +/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, +/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, diff --git a/Utilities/vtkexpat/vtk_expat_mangle.h b/Utilities/vtkexpat/vtk_expat_mangle.h new file mode 100644 index 0000000..f89727d --- /dev/null +++ b/Utilities/vtkexpat/vtk_expat_mangle.h @@ -0,0 +1,87 @@ +#ifndef vtk_expat_mangle_h +#define vtk_expat_mangle_h + +/* + +This header file mangles all symbols exported from the expat library. +It is included in all files while building the expat library. Due to +namespace pollution, no expat headers should be included in .h files in +VTK. + +The following command was used to obtain the symbol list: + +nm libvtkexpat.a |grep " [TR] " + +*/ + +#define XML_DefaultCurrent vtk_expat_XML_DefaultCurrent +#define XML_ErrorString vtk_expat_XML_ErrorString +#define XML_ExpatVersion vtk_expat_XML_ExpatVersion +#define XML_ExpatVersionInfo vtk_expat_XML_ExpatVersionInfo +#define XML_ExternalEntityParserCreate vtk_expat_XML_ExternalEntityParserCreate +#define XML_GetBase vtk_expat_XML_GetBase +#define XML_GetBuffer vtk_expat_XML_GetBuffer +#define XML_GetCurrentByteCount vtk_expat_XML_GetCurrentByteCount +#define XML_GetCurrentByteIndex vtk_expat_XML_GetCurrentByteIndex +#define XML_GetCurrentColumnNumber vtk_expat_XML_GetCurrentColumnNumber +#define XML_GetCurrentLineNumber vtk_expat_XML_GetCurrentLineNumber +#define XML_GetErrorCode vtk_expat_XML_GetErrorCode +#define XML_GetIdAttributeIndex vtk_expat_XML_GetIdAttributeIndex +#define XML_GetInputContext vtk_expat_XML_GetInputContext +#define XML_GetSpecifiedAttributeCount vtk_expat_XML_GetSpecifiedAttributeCount +#define XML_Parse vtk_expat_XML_Parse +#define XML_ParseBuffer vtk_expat_XML_ParseBuffer +#define XML_ParserCreate vtk_expat_XML_ParserCreate +#define XML_ParserCreateNS vtk_expat_XML_ParserCreateNS +#define XML_ParserCreate_MM vtk_expat_XML_ParserCreate_MM +#define XML_ParserFree vtk_expat_XML_ParserFree +#define XML_SetAttlistDeclHandler vtk_expat_XML_SetAttlistDeclHandler +#define XML_SetBase vtk_expat_XML_SetBase +#define XML_SetCdataSectionHandler vtk_expat_XML_SetCdataSectionHandler +#define XML_SetCharacterDataHandler vtk_expat_XML_SetCharacterDataHandler +#define XML_SetCommentHandler vtk_expat_XML_SetCommentHandler +#define XML_SetDefaultHandler vtk_expat_XML_SetDefaultHandler +#define XML_SetDefaultHandlerExpand vtk_expat_XML_SetDefaultHandlerExpand +#define XML_SetDoctypeDeclHandler vtk_expat_XML_SetDoctypeDeclHandler +#define XML_SetElementDeclHandler vtk_expat_XML_SetElementDeclHandler +#define XML_SetElementHandler vtk_expat_XML_SetElementHandler +#define XML_SetEncoding vtk_expat_XML_SetEncoding +#define XML_SetEndCdataSectionHandler vtk_expat_XML_SetEndCdataSectionHandler +#define XML_SetEndDoctypeDeclHandler vtk_expat_XML_SetEndDoctypeDeclHandler +#define XML_SetEndElementHandler vtk_expat_XML_SetEndElementHandler +#define XML_SetEndNamespaceDeclHandler vtk_expat_XML_SetEndNamespaceDeclHandler +#define XML_SetEntityDeclHandler vtk_expat_XML_SetEntityDeclHandler +#define XML_SetExternalEntityRefHandler vtk_expat_XML_SetExternalEntityRefHandler +#define XML_SetExternalEntityRefHandlerArg vtk_expat_XML_SetExternalEntityRefHandlerArg +#define XML_SetNamespaceDeclHandler vtk_expat_XML_SetNamespaceDeclHandler +#define XML_SetNotStandaloneHandler vtk_expat_XML_SetNotStandaloneHandler +#define XML_SetNotationDeclHandler vtk_expat_XML_SetNotationDeclHandler +#define XML_SetParamEntityParsing vtk_expat_XML_SetParamEntityParsing +#define XML_SetProcessingInstructionHandler vtk_expat_XML_SetProcessingInstructionHandler +#define XML_SetReturnNSTriplet vtk_expat_XML_SetReturnNSTriplet +#define XML_SetStartCdataSectionHandler vtk_expat_XML_SetStartCdataSectionHandler +#define XML_SetStartDoctypeDeclHandler vtk_expat_XML_SetStartDoctypeDeclHandler +#define XML_SetStartElementHandler vtk_expat_XML_SetStartElementHandler +#define XML_SetStartNamespaceDeclHandler vtk_expat_XML_SetStartNamespaceDeclHandler +#define XML_SetUnknownEncodingHandler vtk_expat_XML_SetUnknownEncodingHandler +#define XML_SetUnparsedEntityDeclHandler vtk_expat_XML_SetUnparsedEntityDeclHandler +#define XML_SetUserData vtk_expat_XML_SetUserData +#define XML_SetXmlDeclHandler vtk_expat_XML_SetXmlDeclHandler +#define XML_UseParserAsHandlerArg vtk_expat_XML_UseParserAsHandlerArg +#define XmlGetUtf16InternalEncoding vtk_expat_XmlGetUtf16InternalEncoding +#define XmlGetUtf16InternalEncodingNS vtk_expat_XmlGetUtf16InternalEncodingNS +#define XmlGetUtf8InternalEncoding vtk_expat_XmlGetUtf8InternalEncoding +#define XmlGetUtf8InternalEncodingNS vtk_expat_XmlGetUtf8InternalEncodingNS +#define XmlInitEncoding vtk_expat_XmlInitEncoding +#define XmlInitEncodingNS vtk_expat_XmlInitEncodingNS +#define XmlInitUnknownEncoding vtk_expat_XmlInitUnknownEncoding +#define XmlInitUnknownEncodingNS vtk_expat_XmlInitUnknownEncodingNS +#define XmlParseXmlDecl vtk_expat_XmlParseXmlDecl +#define XmlParseXmlDeclNS vtk_expat_XmlParseXmlDeclNS +#define XmlSizeOfUnknownEncoding vtk_expat_XmlSizeOfUnknownEncoding +#define XmlUtf16Encode vtk_expat_XmlUtf16Encode +#define XmlUtf8Encode vtk_expat_XmlUtf8Encode +#define XmlPrologStateInit vtk_expat_XmlPrologStateInit +#define XmlPrologStateInitExternalEntity vtk_expat_XmlPrologStateInitExternalEntity + +#endif diff --git a/Utilities/vtkexpat/xmlparse.c b/Utilities/vtkexpat/xmlparse.c new file mode 100644 index 0000000..ee35e8d --- /dev/null +++ b/Utilities/vtkexpat/xmlparse.c @@ -0,0 +1,4622 @@ +/* +Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +#include +#include "expat.h" + +#include +#include + +#ifdef XML_UNICODE +#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX +#define XmlConvert XmlUtf16Convert +#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding +#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS +#define XmlEncode XmlUtf16Encode +#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1)) +typedef unsigned short ICHAR; +#else +#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX +#define XmlConvert XmlUtf8Convert +#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding +#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS +#define XmlEncode XmlUtf8Encode +#define MUST_CONVERT(enc, s) (!(enc)->isUtf8) +typedef char ICHAR; +#endif + + +#ifndef XML_NS + +#define XmlInitEncodingNS XmlInitEncoding +#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding +#undef XmlGetInternalEncodingNS +#define XmlGetInternalEncodingNS XmlGetInternalEncoding +#define XmlParseXmlDeclNS XmlParseXmlDecl + +#endif + +#ifdef XML_UNICODE_WCHAR_T +#define XML_T(x) L ## x +#else +#define XML_T(x) x +#endif + +/* Round up n to be a multiple of sz, where sz is a power of 2. */ +#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) + +#include "xmltok.h" +#include "xmlrole.h" + +typedef const XML_Char *KEY; + +typedef struct { + KEY name; +} NAMED; + +typedef struct { + NAMED **v; + size_t size; + size_t used; + size_t usedLim; + XML_Memory_Handling_Suite *mem; +} HASH_TABLE; + +typedef struct { + NAMED **p; + NAMED **end; +} HASH_TABLE_ITER; + +#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ +#define INIT_DATA_BUF_SIZE 1024 +#define INIT_ATTS_SIZE 16 +#define INIT_BLOCK_SIZE 1024 +#define INIT_BUFFER_SIZE 1024 + +#define EXPAND_SPARE 24 + +typedef struct binding { + struct prefix *prefix; + struct binding *nextTagBinding; + struct binding *prevPrefixBinding; + const struct attribute_id *attId; + XML_Char *uri; + int uriLen; + int uriAlloc; +} BINDING; + +typedef struct prefix { + const XML_Char *name; + BINDING *binding; +} PREFIX; + +typedef struct { + const XML_Char *str; + const XML_Char *localPart; + int uriLen; +} TAG_NAME; + +typedef struct tag { + struct tag *parent; + const char *rawName; + int rawNameLength; + TAG_NAME name; + char *buf; + char *bufEnd; + BINDING *bindings; +} TAG; + +typedef struct { + const XML_Char *name; + const XML_Char *textPtr; + int textLen; + const XML_Char *systemId; + const XML_Char *base; + const XML_Char *publicId; + const XML_Char *notation; + char open; + char is_param; +} ENTITY; + +typedef struct { + enum XML_Content_Type type; + enum XML_Content_Quant quant; + const XML_Char * name; + int firstchild; + int lastchild; + int childcnt; + int nextsib; +} CONTENT_SCAFFOLD; + +typedef struct block { + struct block *next; + int size; + XML_Char s[1]; +} BLOCK; + +typedef struct { + BLOCK *blocks; + BLOCK *freeBlocks; + const XML_Char *end; + XML_Char *ptr; + XML_Char *start; + XML_Memory_Handling_Suite *mem; +} STRING_POOL; + +/* The XML_Char before the name is used to determine whether +an attribute has been specified. */ +typedef struct attribute_id { + XML_Char *name; + PREFIX *prefix; + char maybeTokenized; + char xmlns; +} ATTRIBUTE_ID; + +typedef struct { + const ATTRIBUTE_ID *id; + char isCdata; + const XML_Char *value; +} DEFAULT_ATTRIBUTE; + +typedef struct { + const XML_Char *name; + PREFIX *prefix; + const ATTRIBUTE_ID *idAtt; + int nDefaultAtts; + int allocDefaultAtts; + DEFAULT_ATTRIBUTE *defaultAtts; +} ELEMENT_TYPE; + +typedef struct { + HASH_TABLE generalEntities; + HASH_TABLE elementTypes; + HASH_TABLE attributeIds; + HASH_TABLE prefixes; + STRING_POOL pool; + int complete; + int standalone; +#ifdef XML_DTD + HASH_TABLE paramEntities; +#endif /* XML_DTD */ + PREFIX defaultPrefix; + /* === scaffolding for building content model === */ + int in_eldecl; + CONTENT_SCAFFOLD *scaffold; + unsigned contentStringLen; + unsigned scaffSize; + unsigned scaffCount; + int scaffLevel; + int *scaffIndex; +} DTD; + +typedef struct open_internal_entity { + const char *internalEventPtr; + const char *internalEventEndPtr; + struct open_internal_entity *next; + ENTITY *entity; +} OPEN_INTERNAL_ENTITY; + +typedef enum XML_Error Processor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr); + +static Processor prologProcessor; +static Processor prologInitProcessor; +static Processor contentProcessor; +static Processor cdataSectionProcessor; +#ifdef XML_DTD +static Processor ignoreSectionProcessor; +#endif /* XML_DTD */ +static Processor epilogProcessor; +static Processor errorProcessor; +static Processor externalEntityInitProcessor; +static Processor externalEntityInitProcessor2; +static Processor externalEntityInitProcessor3; +static Processor externalEntityContentProcessor; + +static enum XML_Error +handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); +static enum XML_Error +processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *); +static enum XML_Error +initializeEncoding(XML_Parser parser); +static enum XML_Error +doProlog(XML_Parser parser, const ENCODING *enc, const char *s, + const char *end, int tok, const char *next, const char **nextPtr); +static enum XML_Error +processInternalParamEntity(XML_Parser parser, ENTITY *entity); +static enum XML_Error +doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, + const char *start, const char *end, const char **endPtr); +static enum XML_Error +doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); +#ifdef XML_DTD +static enum XML_Error +doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr); +#endif /* XML_DTD */ +static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s, + TAG_NAME *tagNamePtr, BINDING **bindingsPtr); +static +int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); + +static int +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, + int isCdata, int isId, const XML_Char *dfltValue, + XML_Parser parser); + +static enum XML_Error +storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, + STRING_POOL *); +static enum XML_Error +appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *, + STRING_POOL *); +static ATTRIBUTE_ID * +getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); +static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *); +static enum XML_Error +storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); +static int +reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); +static int +reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); +static void +reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); + +static const XML_Char *getContext(XML_Parser parser); +static int setContext(XML_Parser parser, const XML_Char *context); +static void normalizePublicId(XML_Char *s); +static int dtdInit(DTD *, XML_Parser parser); + +static void dtdDestroy(DTD *, XML_Parser parser); + +static int dtdCopy(DTD *newDtd, const DTD *oldDtd, XML_Parser parser); + +static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *, + XML_Parser parser); + +#ifdef XML_DTD +static void dtdSwap(DTD *, DTD *); +#endif /* XML_DTD */ + +static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize); + +static void hashTableInit(HASH_TABLE *, XML_Memory_Handling_Suite *ms); + +static void hashTableDestroy(HASH_TABLE *); +static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *); +static NAMED *hashTableIterNext(HASH_TABLE_ITER *); +static void poolInit(STRING_POOL *, XML_Memory_Handling_Suite *ms); +static void poolClear(STRING_POOL *); +static void poolDestroy(STRING_POOL *); +static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end); +static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end); + +static int poolGrow(STRING_POOL *pool); + +static int nextScaffoldPart(XML_Parser parser); +static XML_Content *build_model(XML_Parser parser); + +static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s); +static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); +static const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s); +static ELEMENT_TYPE * getElementType(XML_Parser Paraser, + const ENCODING *enc, + const char *ptr, + const char *end); + +#define poolStart(pool) ((pool)->start) +#define poolEnd(pool) ((pool)->ptr) +#define poolLength(pool) ((pool)->ptr - (pool)->start) +#define poolChop(pool) ((void)--(pool->ptr)) +#define poolLastChar(pool) (((pool)->ptr)[-1]) +#define poolDiscard(pool) ((pool)->ptr = (pool)->start) +#define poolFinish(pool) ((pool)->start = (pool)->ptr) +#define poolAppendChar(pool, c) \ + (((pool)->ptr == (pool)->end && !poolGrow(pool)) \ + ? 0 \ + : ((*((pool)->ptr)++ = c), 1)) + +typedef struct { + /* The first member must be userData so that the XML_GetUserData macro works. */ + void *m_userData; + void *m_handlerArg; + char *m_buffer; + XML_Memory_Handling_Suite m_mem; + /* first character to be parsed */ + const char *m_bufferPtr; + /* past last character to be parsed */ + char *m_bufferEnd; + /* allocated end of buffer */ + const char *m_bufferLim; + long m_parseEndByteIndex; + const char *m_parseEndPtr; + XML_Char *m_dataBuf; + XML_Char *m_dataBufEnd; + XML_StartElementHandler m_startElementHandler; + XML_EndElementHandler m_endElementHandler; + XML_CharacterDataHandler m_characterDataHandler; + XML_ProcessingInstructionHandler m_processingInstructionHandler; + XML_CommentHandler m_commentHandler; + XML_StartCdataSectionHandler m_startCdataSectionHandler; + XML_EndCdataSectionHandler m_endCdataSectionHandler; + XML_DefaultHandler m_defaultHandler; + XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; + XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; + XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; + XML_NotationDeclHandler m_notationDeclHandler; + XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; + XML_NotStandaloneHandler m_notStandaloneHandler; + XML_ExternalEntityRefHandler m_externalEntityRefHandler; + void *m_externalEntityRefHandlerArg; + XML_UnknownEncodingHandler m_unknownEncodingHandler; + XML_ElementDeclHandler m_elementDeclHandler; + XML_AttlistDeclHandler m_attlistDeclHandler; + XML_EntityDeclHandler m_entityDeclHandler; + XML_XmlDeclHandler m_xmlDeclHandler; + const ENCODING *m_encoding; + INIT_ENCODING m_initEncoding; + const ENCODING *m_internalEncoding; + const XML_Char *m_protocolEncodingName; + int m_ns; + int m_ns_triplets; + void *m_unknownEncodingMem; + void *m_unknownEncodingData; + void *m_unknownEncodingHandlerData; + void (*m_unknownEncodingRelease)(void *); + PROLOG_STATE m_prologState; + Processor *m_processor; + enum XML_Error m_errorCode; + const char *m_eventPtr; + const char *m_eventEndPtr; + const char *m_positionPtr; + OPEN_INTERNAL_ENTITY *m_openInternalEntities; + int m_defaultExpandInternalEntities; + int m_tagLevel; + ENTITY *m_declEntity; + const XML_Char *m_doctypeName; + const XML_Char *m_doctypeSysid; + const XML_Char *m_doctypePubid; + const XML_Char *m_declAttributeType; + const XML_Char *m_declNotationName; + const XML_Char *m_declNotationPublicId; + ELEMENT_TYPE *m_declElementType; + ATTRIBUTE_ID *m_declAttributeId; + char m_declAttributeIsCdata; + char m_declAttributeIsId; + DTD m_dtd; + const XML_Char *m_curBase; + TAG *m_tagStack; + TAG *m_freeTagList; + BINDING *m_inheritedBindings; + BINDING *m_freeBindingList; + int m_attsSize; + int m_nSpecifiedAtts; + int m_idAttIndex; + ATTRIBUTE *m_atts; + POSITION m_position; + STRING_POOL m_tempPool; + STRING_POOL m_temp2Pool; + char *m_groupConnector; + unsigned m_groupSize; + int m_hadExternalDoctype; + XML_Char m_namespaceSeparator; +#ifdef XML_DTD + enum XML_ParamEntityParsing m_paramEntityParsing; + XML_Parser m_parentParser; +#endif +} Parser; + +#define MALLOC(s) (((Parser *)parser)->m_mem.malloc_fcn((s))) +#define REALLOC(p,s) (((Parser *)parser)->m_mem.realloc_fcn((p),(s))) +#define FREE(p) (((Parser *)parser)->m_mem.free_fcn((p))) + +#define userData (((Parser *)parser)->m_userData) +#define handlerArg (((Parser *)parser)->m_handlerArg) +#define startElementHandler (((Parser *)parser)->m_startElementHandler) +#define endElementHandler (((Parser *)parser)->m_endElementHandler) +#define characterDataHandler (((Parser *)parser)->m_characterDataHandler) +#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler) +#define commentHandler (((Parser *)parser)->m_commentHandler) +#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler) +#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler) +#define defaultHandler (((Parser *)parser)->m_defaultHandler) +#define startDoctypeDeclHandler (((Parser *)parser)->m_startDoctypeDeclHandler) +#define endDoctypeDeclHandler (((Parser *)parser)->m_endDoctypeDeclHandler) +#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler) +#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler) +#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler) +#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler) +#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler) +#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler) +#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg) +#define internalEntityRefHandler (((Parser *)parser)->m_internalEntityRefHandler) +#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler) +#define elementDeclHandler (((Parser *)parser)->m_elementDeclHandler) +#define attlistDeclHandler (((Parser *)parser)->m_attlistDeclHandler) +#define entityDeclHandler (((Parser *)parser)->m_entityDeclHandler) +#define xmlDeclHandler (((Parser *)parser)->m_xmlDeclHandler) +#define encoding (((Parser *)parser)->m_encoding) +#define initEncoding (((Parser *)parser)->m_initEncoding) +#define internalEncoding (((Parser *)parser)->m_internalEncoding) +#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem) +#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData) +#define unknownEncodingHandlerData \ + (((Parser *)parser)->m_unknownEncodingHandlerData) +#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease) +#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName) +#define ns (((Parser *)parser)->m_ns) +#define ns_triplets (((Parser *)parser)->m_ns_triplets) +#define prologState (((Parser *)parser)->m_prologState) +#define processor (((Parser *)parser)->m_processor) +#define errorCode (((Parser *)parser)->m_errorCode) +#define eventPtr (((Parser *)parser)->m_eventPtr) +#define eventEndPtr (((Parser *)parser)->m_eventEndPtr) +#define positionPtr (((Parser *)parser)->m_positionPtr) +#define position (((Parser *)parser)->m_position) +#define openInternalEntities (((Parser *)parser)->m_openInternalEntities) +#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities) +#define tagLevel (((Parser *)parser)->m_tagLevel) +#define buffer (((Parser *)parser)->m_buffer) +#define bufferPtr (((Parser *)parser)->m_bufferPtr) +#define bufferEnd (((Parser *)parser)->m_bufferEnd) +#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex) +#define parseEndPtr (((Parser *)parser)->m_parseEndPtr) +#define bufferLim (((Parser *)parser)->m_bufferLim) +#define dataBuf (((Parser *)parser)->m_dataBuf) +#define dataBufEnd (((Parser *)parser)->m_dataBufEnd) +#define dtd (((Parser *)parser)->m_dtd) +#define curBase (((Parser *)parser)->m_curBase) +#define declEntity (((Parser *)parser)->m_declEntity) +#define doctypeName (((Parser *)parser)->m_doctypeName) +#define doctypeSysid (((Parser *)parser)->m_doctypeSysid) +#define doctypePubid (((Parser *)parser)->m_doctypePubid) +#define declAttributeType (((Parser *)parser)->m_declAttributeType) +#define declNotationName (((Parser *)parser)->m_declNotationName) +#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId) +#define declElementType (((Parser *)parser)->m_declElementType) +#define declAttributeId (((Parser *)parser)->m_declAttributeId) +#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata) +#define declAttributeIsId (((Parser *)parser)->m_declAttributeIsId) +#define freeTagList (((Parser *)parser)->m_freeTagList) +#define freeBindingList (((Parser *)parser)->m_freeBindingList) +#define inheritedBindings (((Parser *)parser)->m_inheritedBindings) +#define tagStack (((Parser *)parser)->m_tagStack) +#define atts (((Parser *)parser)->m_atts) +#define attsSize (((Parser *)parser)->m_attsSize) +#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts) +#define idAttIndex (((Parser *)parser)->m_idAttIndex) +#define tempPool (((Parser *)parser)->m_tempPool) +#define temp2Pool (((Parser *)parser)->m_temp2Pool) +#define groupConnector (((Parser *)parser)->m_groupConnector) +#define groupSize (((Parser *)parser)->m_groupSize) +#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype) +#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator) +#ifdef XML_DTD +#define parentParser (((Parser *)parser)->m_parentParser) +#define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing) +#endif /* XML_DTD */ + +#ifdef COMPILED_FROM_DSP +BOOL WINAPI DllMain(HINSTANCE h, DWORD r, LPVOID p) { + return TRUE; +} +#endif /* def COMPILED_FROM_DSP */ + +#ifdef _MSC_VER +#ifdef _DEBUG +Parser *asParser(XML_Parser parser) +{ + return parser; +} +#endif +#endif + +XML_Parser XML_ParserCreate(const XML_Char *encodingName) +{ + return XML_ParserCreate_MM(encodingName, NULL, NULL); +} + +XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) +{ + XML_Char tmp[2]; + *tmp = nsSep; + return XML_ParserCreate_MM(encodingName, NULL, tmp); +} + +XML_Parser +XML_ParserCreate_MM(const XML_Char *encodingName, + const XML_Memory_Handling_Suite *memsuite, + const XML_Char *nameSep) { + + XML_Parser parser; + static + const XML_Char implicitContext[] = { + XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='), + XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'), + XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'), + XML_T('.'), XML_T('w'), XML_T('3'), + XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'), + XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'), + XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'), + XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'), + XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'), + XML_T('\0') + }; + + + if (memsuite) { + XML_Memory_Handling_Suite *mtemp; + parser = memsuite->malloc_fcn(sizeof(Parser)); + mtemp = &(((Parser *) parser)->m_mem); + mtemp->malloc_fcn = memsuite->malloc_fcn; + mtemp->realloc_fcn = memsuite->realloc_fcn; + mtemp->free_fcn = memsuite->free_fcn; + } + else { + XML_Memory_Handling_Suite *mtemp; + parser = malloc(sizeof(Parser)); + mtemp = &(((Parser *) parser)->m_mem); + mtemp->malloc_fcn = malloc; + mtemp->realloc_fcn = realloc; + mtemp->free_fcn = free; + } + + if (!parser) + return parser; + processor = prologInitProcessor; + XmlPrologStateInit(&prologState); + userData = 0; + handlerArg = 0; + startElementHandler = 0; + endElementHandler = 0; + characterDataHandler = 0; + processingInstructionHandler = 0; + commentHandler = 0; + startCdataSectionHandler = 0; + endCdataSectionHandler = 0; + defaultHandler = 0; + startDoctypeDeclHandler = 0; + endDoctypeDeclHandler = 0; + unparsedEntityDeclHandler = 0; + notationDeclHandler = 0; + startNamespaceDeclHandler = 0; + endNamespaceDeclHandler = 0; + notStandaloneHandler = 0; + externalEntityRefHandler = 0; + externalEntityRefHandlerArg = parser; + unknownEncodingHandler = 0; + elementDeclHandler = 0; + attlistDeclHandler = 0; + entityDeclHandler = 0; + xmlDeclHandler = 0; + buffer = 0; + bufferPtr = 0; + bufferEnd = 0; + parseEndByteIndex = 0; + parseEndPtr = 0; + bufferLim = 0; + declElementType = 0; + declAttributeId = 0; + declEntity = 0; + doctypeName = 0; + doctypeSysid = 0; + doctypePubid = 0; + declAttributeType = 0; + declNotationName = 0; + declNotationPublicId = 0; + memset(&position, 0, sizeof(POSITION)); + errorCode = XML_ERROR_NONE; + eventPtr = 0; + eventEndPtr = 0; + positionPtr = 0; + openInternalEntities = 0; + tagLevel = 0; + tagStack = 0; + freeTagList = 0; + freeBindingList = 0; + inheritedBindings = 0; + attsSize = INIT_ATTS_SIZE; + atts = MALLOC(attsSize * sizeof(ATTRIBUTE)); + nSpecifiedAtts = 0; + dataBuf = MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char)); + groupSize = 0; + groupConnector = 0; + hadExternalDoctype = 0; + unknownEncodingMem = 0; + unknownEncodingRelease = 0; + unknownEncodingData = 0; + unknownEncodingHandlerData = 0; + namespaceSeparator = '!'; +#ifdef XML_DTD + parentParser = 0; + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; +#endif + ns = 0; + ns_triplets = 0; + poolInit(&tempPool, &(((Parser *) parser)->m_mem)); + poolInit(&temp2Pool, &(((Parser *) parser)->m_mem)); + protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0; + curBase = 0; + if (!dtdInit(&dtd, parser) || !atts || !dataBuf + || (encodingName && !protocolEncodingName)) { + XML_ParserFree(parser); + return 0; + } + dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE; + + if (nameSep) { + XmlInitEncodingNS(&initEncoding, &encoding, 0); + ns = 1; + internalEncoding = XmlGetInternalEncodingNS(); + namespaceSeparator = *nameSep; + + if (! setContext(parser, implicitContext)) { + XML_ParserFree(parser); + return 0; + } + } + else { + XmlInitEncoding(&initEncoding, &encoding, 0); + internalEncoding = XmlGetInternalEncoding(); + } + + return parser; +} /* End XML_ParserCreate_MM */ + +int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + if (!encodingName) + protocolEncodingName = 0; + else { + protocolEncodingName = poolCopyString(&tempPool, encodingName); + if (!protocolEncodingName) + return 0; + } + return 1; +} + +XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser, + const XML_Char *context, + const XML_Char *encodingName) +{ + XML_Parser parser = oldParser; + DTD *oldDtd = &dtd; + XML_StartElementHandler oldStartElementHandler = startElementHandler; + XML_EndElementHandler oldEndElementHandler = endElementHandler; + XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler; + XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler; + XML_CommentHandler oldCommentHandler = commentHandler; + XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler; + XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler; + XML_DefaultHandler oldDefaultHandler = defaultHandler; + XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler; + XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler; + XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler; + XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler; + XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler; + XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler; + XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler; + XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler; + XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler; + XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler; + XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler; + ELEMENT_TYPE * oldDeclElementType = declElementType; + + void *oldUserData = userData; + void *oldHandlerArg = handlerArg; + int oldDefaultExpandInternalEntities = defaultExpandInternalEntities; + void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg; +#ifdef XML_DTD + enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing; +#endif + int oldns_triplets = ns_triplets; + + if (ns) { + XML_Char tmp[2]; + + *tmp = namespaceSeparator; + parser = XML_ParserCreate_MM(encodingName, &((Parser *)parser)->m_mem, + tmp); + } + else { + parser = XML_ParserCreate_MM(encodingName, &((Parser *)parser)->m_mem, + NULL); + } + + if (!parser) + return 0; + + startElementHandler = oldStartElementHandler; + endElementHandler = oldEndElementHandler; + characterDataHandler = oldCharacterDataHandler; + processingInstructionHandler = oldProcessingInstructionHandler; + commentHandler = oldCommentHandler; + startCdataSectionHandler = oldStartCdataSectionHandler; + endCdataSectionHandler = oldEndCdataSectionHandler; + defaultHandler = oldDefaultHandler; + unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; + notationDeclHandler = oldNotationDeclHandler; + startNamespaceDeclHandler = oldStartNamespaceDeclHandler; + endNamespaceDeclHandler = oldEndNamespaceDeclHandler; + notStandaloneHandler = oldNotStandaloneHandler; + externalEntityRefHandler = oldExternalEntityRefHandler; + unknownEncodingHandler = oldUnknownEncodingHandler; + elementDeclHandler = oldElementDeclHandler; + attlistDeclHandler = oldAttlistDeclHandler; + entityDeclHandler = oldEntityDeclHandler; + xmlDeclHandler = oldXmlDeclHandler; + declElementType = oldDeclElementType; + userData = oldUserData; + if (oldUserData == oldHandlerArg) + handlerArg = userData; + else + handlerArg = parser; + if (oldExternalEntityRefHandlerArg != oldParser) + externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; + defaultExpandInternalEntities = oldDefaultExpandInternalEntities; + ns_triplets = oldns_triplets; +#ifdef XML_DTD + paramEntityParsing = oldParamEntityParsing; + if (context) { +#endif /* XML_DTD */ + if (!dtdCopy(&dtd, oldDtd, parser) || !setContext(parser, context)) { + XML_ParserFree(parser); + return 0; + } + processor = externalEntityInitProcessor; +#ifdef XML_DTD + } + else { + dtdSwap(&dtd, oldDtd); + parentParser = oldParser; + XmlPrologStateInitExternalEntity(&prologState); + dtd.complete = 1; + hadExternalDoctype = 1; + } +#endif /* XML_DTD */ + return parser; +} + +static +void destroyBindings(BINDING *bindings, XML_Parser parser) +{ + for (;;) { + BINDING *b = bindings; + if (!b) + break; + bindings = b->nextTagBinding; + FREE(b->uri); + FREE(b); + } +} + +void XML_ParserFree(XML_Parser parser) +{ + for (;;) { + TAG *p; + if (tagStack == 0) { + if (freeTagList == 0) + break; + tagStack = freeTagList; + freeTagList = 0; + } + p = tagStack; + tagStack = tagStack->parent; + FREE(p->buf); + destroyBindings(p->bindings, parser); + FREE(p); + } + destroyBindings(freeBindingList, parser); + destroyBindings(inheritedBindings, parser); + poolDestroy(&tempPool); + poolDestroy(&temp2Pool); +#ifdef XML_DTD + if (parentParser) { + if (hadExternalDoctype) + dtd.complete = 0; + dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd); + } +#endif /* XML_DTD */ + dtdDestroy(&dtd, parser); + FREE((void *)atts); + if (groupConnector) + FREE(groupConnector); + if (buffer) + FREE(buffer); + FREE(dataBuf); + if (unknownEncodingMem) + FREE(unknownEncodingMem); + if (unknownEncodingRelease) + unknownEncodingRelease(unknownEncodingData); + FREE(parser); +} + +void XML_UseParserAsHandlerArg(XML_Parser parser) +{ + handlerArg = parser; +} + +void +XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { + ns_triplets = do_nst; +} + +void XML_SetUserData(XML_Parser parser, void *p) +{ + if (handlerArg == userData) + handlerArg = userData = p; + else + userData = p; +} + +int XML_SetBase(XML_Parser parser, const XML_Char *p) +{ + if (p) { + p = poolCopyString(&dtd.pool, p); + if (!p) + return 0; + curBase = p; + } + else + curBase = 0; + return 1; +} + +const XML_Char *XML_GetBase(XML_Parser parser) +{ + return curBase; +} + +int XML_GetSpecifiedAttributeCount(XML_Parser parser) +{ + return nSpecifiedAtts; +} + +int XML_GetIdAttributeIndex(XML_Parser parser) +{ + return idAttIndex; +} + +void XML_SetElementHandler(XML_Parser parser, + XML_StartElementHandler start, + XML_EndElementHandler end) +{ + startElementHandler = start; + endElementHandler = end; +} + +void XML_SetStartElementHandler(XML_Parser parser, + XML_StartElementHandler start) { + startElementHandler = start; +} + +void XML_SetEndElementHandler(XML_Parser parser, + XML_EndElementHandler end) { + endElementHandler = end; +} + +void XML_SetCharacterDataHandler(XML_Parser parser, + XML_CharacterDataHandler handler) +{ + characterDataHandler = handler; +} + +void XML_SetProcessingInstructionHandler(XML_Parser parser, + XML_ProcessingInstructionHandler handler) +{ + processingInstructionHandler = handler; +} + +void XML_SetCommentHandler(XML_Parser parser, + XML_CommentHandler handler) +{ + commentHandler = handler; +} + +void XML_SetCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start, + XML_EndCdataSectionHandler end) +{ + startCdataSectionHandler = start; + endCdataSectionHandler = end; +} + +void XML_SetStartCdataSectionHandler(XML_Parser parser, + XML_StartCdataSectionHandler start) { + startCdataSectionHandler = start; +} + +void XML_SetEndCdataSectionHandler(XML_Parser parser, + XML_EndCdataSectionHandler end) { + endCdataSectionHandler = end; +} + +void XML_SetDefaultHandler(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = 0; +} + +void XML_SetDefaultHandlerExpand(XML_Parser parser, + XML_DefaultHandler handler) +{ + defaultHandler = handler; + defaultExpandInternalEntities = 1; +} + +void XML_SetDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start, + XML_EndDoctypeDeclHandler end) +{ + startDoctypeDeclHandler = start; + endDoctypeDeclHandler = end; +} + +void XML_SetStartDoctypeDeclHandler(XML_Parser parser, + XML_StartDoctypeDeclHandler start) { + startDoctypeDeclHandler = start; +} + +void XML_SetEndDoctypeDeclHandler(XML_Parser parser, + XML_EndDoctypeDeclHandler end) { + endDoctypeDeclHandler = end; +} + +void XML_SetUnparsedEntityDeclHandler(XML_Parser parser, + XML_UnparsedEntityDeclHandler handler) +{ + unparsedEntityDeclHandler = handler; +} + +void XML_SetNotationDeclHandler(XML_Parser parser, + XML_NotationDeclHandler handler) +{ + notationDeclHandler = handler; +} + +void XML_SetNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end) +{ + startNamespaceDeclHandler = start; + endNamespaceDeclHandler = end; +} + +void XML_SetStartNamespaceDeclHandler(XML_Parser parser, + XML_StartNamespaceDeclHandler start) { + startNamespaceDeclHandler = start; +} + +void XML_SetEndNamespaceDeclHandler(XML_Parser parser, + XML_EndNamespaceDeclHandler end) { + endNamespaceDeclHandler = end; +} + + +void XML_SetNotStandaloneHandler(XML_Parser parser, + XML_NotStandaloneHandler handler) +{ + notStandaloneHandler = handler; +} + +void XML_SetExternalEntityRefHandler(XML_Parser parser, + XML_ExternalEntityRefHandler handler) +{ + externalEntityRefHandler = handler; +} + +void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) +{ + if (arg) + externalEntityRefHandlerArg = arg; + else + externalEntityRefHandlerArg = parser; +} + +void XML_SetUnknownEncodingHandler(XML_Parser parser, + XML_UnknownEncodingHandler handler, + void *data) +{ + unknownEncodingHandler = handler; + unknownEncodingHandlerData = data; +} + +void XML_SetElementDeclHandler(XML_Parser parser, + XML_ElementDeclHandler eldecl) +{ + elementDeclHandler = eldecl; +} + +void XML_SetAttlistDeclHandler(XML_Parser parser, + XML_AttlistDeclHandler attdecl) +{ + attlistDeclHandler = attdecl; +} + +void XML_SetEntityDeclHandler(XML_Parser parser, + XML_EntityDeclHandler handler) +{ + entityDeclHandler = handler; +} + +void XML_SetXmlDeclHandler(XML_Parser parser, + XML_XmlDeclHandler handler) { + xmlDeclHandler = handler; +} + +int XML_SetParamEntityParsing(XML_Parser parser, + enum XML_ParamEntityParsing parsing) +{ +#ifdef XML_DTD + paramEntityParsing = parsing; + return 1; +#else + return parsing == XML_PARAM_ENTITY_PARSING_NEVER; +#endif +} + +int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) +{ + if (len == 0) { + if (!isFinal) + return 1; + positionPtr = bufferPtr; + errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0); + if (errorCode == XML_ERROR_NONE) + return 1; + eventEndPtr = eventPtr; + processor = errorProcessor; + return 0; + } +#ifndef XML_CONTEXT_BYTES + else if (bufferPtr == bufferEnd) { + const char *end; + int nLeftOver; + parseEndByteIndex += len; + positionPtr = s; + if (isFinal) { + errorCode = processor(parser, s, parseEndPtr = s + len, 0); + if (errorCode == XML_ERROR_NONE) + return 1; + eventEndPtr = eventPtr; + processor = errorProcessor; + return 0; + } + errorCode = processor(parser, s, parseEndPtr = s + len, &end); + if (errorCode != XML_ERROR_NONE) { + eventEndPtr = eventPtr; + processor = errorProcessor; + return 0; + } + XmlUpdatePosition(encoding, positionPtr, end, &position); + nLeftOver = s + len - end; + if (nLeftOver) { + if (buffer == 0 || nLeftOver > bufferLim - buffer) { + /* FIXME avoid integer overflow */ + buffer = buffer == 0 ? MALLOC(len * 2) : REALLOC(buffer, len * 2); + /* FIXME storage leak if realloc fails */ + if (!buffer) { + errorCode = XML_ERROR_NO_MEMORY; + eventPtr = eventEndPtr = 0; + processor = errorProcessor; + return 0; + } + bufferLim = buffer + len * 2; + } + memcpy(buffer, end, nLeftOver); + bufferPtr = buffer; + bufferEnd = buffer + nLeftOver; + } + return 1; + } +#endif /* not defined XML_CONTEXT_BYTES */ + else { + memcpy(XML_GetBuffer(parser, len), s, len); + return XML_ParseBuffer(parser, len, isFinal); + } +} + +int XML_ParseBuffer(XML_Parser parser, int len, int isFinal) +{ + const char *start = bufferPtr; + positionPtr = start; + bufferEnd += len; + parseEndByteIndex += len; + errorCode = processor(parser, start, parseEndPtr = bufferEnd, + isFinal ? (const char **)0 : &bufferPtr); + if (errorCode == XML_ERROR_NONE) { + if (!isFinal) + XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position); + return 1; + } + else { + eventEndPtr = eventPtr; + processor = errorProcessor; + return 0; + } +} + +void *XML_GetBuffer(XML_Parser parser, int len) +{ + if (len > bufferLim - bufferEnd) { + /* FIXME avoid integer overflow */ + int neededSize = len + (bufferEnd - bufferPtr); +#ifdef XML_CONTEXT_BYTES + int keep = bufferPtr - buffer; + + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + neededSize += keep; +#endif /* defined XML_CONTEXT_BYTES */ + if (neededSize <= bufferLim - buffer) { +#ifdef XML_CONTEXT_BYTES + if (keep < bufferPtr - buffer) { + int offset = (bufferPtr - buffer) - keep; + memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep); + bufferEnd -= offset; + bufferPtr -= offset; + } +#else + memmove(buffer, bufferPtr, bufferEnd - bufferPtr); + bufferEnd = buffer + (bufferEnd - bufferPtr); + bufferPtr = buffer; +#endif /* not defined XML_CONTEXT_BYTES */ + } + else { + char *newBuf; + int bufferSize = bufferLim - bufferPtr; + if (bufferSize == 0) + bufferSize = INIT_BUFFER_SIZE; + do { + bufferSize *= 2; + } while (bufferSize < neededSize); + newBuf = MALLOC(bufferSize); + if (newBuf == 0) { + errorCode = XML_ERROR_NO_MEMORY; + return 0; + } + bufferLim = newBuf + bufferSize; +#ifdef XML_CONTEXT_BYTES + if (bufferPtr) { + int keep = bufferPtr - buffer; + if (keep > XML_CONTEXT_BYTES) + keep = XML_CONTEXT_BYTES; + memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep); + FREE(buffer); + buffer = newBuf; + bufferEnd = buffer + (bufferEnd - bufferPtr) + keep; + bufferPtr = buffer + keep; + } + else { + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; + } +#else + if (bufferPtr) { + memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr); + FREE(buffer); + } + bufferEnd = newBuf + (bufferEnd - bufferPtr); + bufferPtr = buffer = newBuf; +#endif /* not defined XML_CONTEXT_BYTES */ + } + } + return bufferEnd; +} + +enum XML_Error XML_GetErrorCode(XML_Parser parser) +{ + return errorCode; +} + +long XML_GetCurrentByteIndex(XML_Parser parser) +{ + if (eventPtr) + return parseEndByteIndex - (parseEndPtr - eventPtr); + return -1; +} + +int XML_GetCurrentByteCount(XML_Parser parser) +{ + if (eventEndPtr && eventPtr) + return eventEndPtr - eventPtr; + return 0; +} + +const char * XML_GetInputContext(XML_Parser parser, int *offset, int *size) +{ +#ifdef XML_CONTEXT_BYTES + if (eventPtr && buffer) { + *offset = eventPtr - buffer; + *size = bufferEnd - buffer; + return buffer; + } +#endif /* defined XML_CONTEXT_BYTES */ + return (char *) 0; +} + +int XML_GetCurrentLineNumber(XML_Parser parser) +{ + if (eventPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.lineNumber + 1; +} + +int XML_GetCurrentColumnNumber(XML_Parser parser) +{ + if (eventPtr) { + XmlUpdatePosition(encoding, positionPtr, eventPtr, &position); + positionPtr = eventPtr; + } + return position.columnNumber; +} + +void XML_DefaultCurrent(XML_Parser parser) +{ + if (defaultHandler) { + if (openInternalEntities) + reportDefault(parser, + internalEncoding, + openInternalEntities->internalEventPtr, + openInternalEntities->internalEventEndPtr); + else + reportDefault(parser, encoding, eventPtr, eventEndPtr); + } +} + +const XML_LChar *XML_ErrorString(int code) +{ + static const XML_LChar *message[] = { + 0, + XML_T("out of memory"), + XML_T("syntax error"), + XML_T("no element found"), + XML_T("not well-formed (invalid token)"), + XML_T("unclosed token"), + XML_T("unclosed token"), + XML_T("mismatched tag"), + XML_T("duplicate attribute"), + XML_T("junk after document element"), + XML_T("illegal parameter entity reference"), + XML_T("undefined entity"), + XML_T("recursive entity reference"), + XML_T("asynchronous entity"), + XML_T("reference to invalid character number"), + XML_T("reference to binary entity"), + XML_T("reference to external entity in attribute"), + XML_T("xml processing instruction not at start of external entity"), + XML_T("unknown encoding"), + XML_T("encoding specified in XML declaration is incorrect"), + XML_T("unclosed CDATA section"), + XML_T("error in processing external entity reference"), + XML_T("document is not standalone"), + XML_T("unexpected parser state - please send a bug report") + }; + if (code > 0 && code < (int)(sizeof(message)/sizeof(message[0]))) + return message[code]; + return 0; +} + +const XML_LChar * +XML_ExpatVersion(void) { + return VERSION; +} + +XML_Expat_Version +XML_ExpatVersionInfo(void) { + XML_Expat_Version version; + + version.major = XML_MAJOR_VERSION; + version.minor = XML_MINOR_VERSION; + version.micro = XML_MICRO_VERSION; + + return version; +} + +static +enum XML_Error contentProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + return doContent(parser, 0, encoding, start, end, endPtr); +} + +static +enum XML_Error externalEntityInitProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = externalEntityInitProcessor2; + return externalEntityInitProcessor2(parser, start, end, endPtr); +} + +static +enum XML_Error externalEntityInitProcessor2(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + const char *next; + int tok = XmlContentTok(encoding, start, end, &next); + switch (tok) { + case XML_TOK_BOM: + start = next; + break; + case XML_TOK_PARTIAL: + if (endPtr) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (endPtr) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityInitProcessor3; + return externalEntityInitProcessor3(parser, start, end, endPtr); +} + +static +enum XML_Error externalEntityInitProcessor3(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + const char *next; + int tok = XmlContentTok(encoding, start, end, &next); + switch (tok) { + case XML_TOK_XML_DECL: + { + enum XML_Error result = processXmlDecl(parser, 1, start, next); + if (result != XML_ERROR_NONE) + return result; + start = next; + } + break; + case XML_TOK_PARTIAL: + if (endPtr) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (endPtr) { + *endPtr = start; + return XML_ERROR_NONE; + } + eventPtr = start; + return XML_ERROR_PARTIAL_CHAR; + } + processor = externalEntityContentProcessor; + tagLevel = 1; + return doContent(parser, 1, encoding, start, end, endPtr); +} + +static +enum XML_Error externalEntityContentProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + return doContent(parser, 1, encoding, start, end, endPtr); +} + +static enum XML_Error +doContent(XML_Parser parser, + int startTagLevel, + const ENCODING *enc, + const char *s, + const char *end, + const char **nextPtr) +{ + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + for (;;) { + const char *next = s; /* XmlContentTok doesn't always set the last arg */ + int tok = XmlContentTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_TRAILING_CR: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + *eventEndPP = end; + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + if (startTagLevel == 0) + return XML_ERROR_NO_ELEMENTS; + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + return XML_ERROR_NONE; + case XML_TOK_NONE: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (startTagLevel > 0) { + if (tagLevel != startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + return XML_ERROR_NONE; + } + return XML_ERROR_NO_ELEMENTS; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + XML_Char ch = XmlPredefinedEntityName(enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (characterDataHandler) + characterDataHandler(handlerArg, &ch, 1); + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + name = poolStoreString(&dtd.pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); + poolDiscard(&dtd.pool); + if (!entity) { + if (dtd.complete || dtd.standalone) + return XML_ERROR_UNDEFINED_ENTITY; + if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->notation) + return XML_ERROR_BINARY_ENTITY_REF; + if (entity) { + if (entity->textPtr) { + enum XML_Error result; + OPEN_INTERNAL_ENTITY openEntity; + if (defaultHandler && !defaultExpandInternalEntities) { + reportDefault(parser, enc, s, next); + break; + } + entity->open = 1; + openEntity.next = openInternalEntities; + openInternalEntities = &openEntity; + openEntity.entity = entity; + openEntity.internalEventPtr = 0; + openEntity.internalEventEndPtr = 0; + result = doContent(parser, + tagLevel, + internalEncoding, + (char *)entity->textPtr, + (char *)(entity->textPtr + entity->textLen), + 0); + entity->open = 0; + openInternalEntities = openEntity.next; + if (result) + return result; + } + else if (externalEntityRefHandler) { + const XML_Char *context; + entity->open = 1; + context = getContext(parser); + entity->open = 0; + if (!context) + return XML_ERROR_NO_MEMORY; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + context, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + poolDiscard(&tempPool); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + } + case XML_TOK_START_TAG_WITH_ATTS: + if (!startElementHandler) { + enum XML_Error result = storeAtts(parser, enc, s, 0, 0); + if (result) + return result; + } + /* fall through */ + case XML_TOK_START_TAG_NO_ATTS: + { + TAG *tag; + if (freeTagList) { + tag = freeTagList; + freeTagList = freeTagList->parent; + } + else { + tag = MALLOC(sizeof(TAG)); + if (!tag) + return XML_ERROR_NO_MEMORY; + tag->buf = MALLOC(INIT_TAG_BUF_SIZE); + if (!tag->buf) + return XML_ERROR_NO_MEMORY; + tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; + } + tag->bindings = 0; + tag->parent = tagStack; + tagStack = tag; + tag->name.localPart = 0; + tag->rawName = s + enc->minBytesPerChar; + tag->rawNameLength = XmlNameLength(enc, tag->rawName); + if (nextPtr) { + /* Need to guarantee that: + tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */ + if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) { + int bufSize = tag->rawNameLength * 4; + bufSize = ROUND_UP(bufSize, sizeof(XML_Char)); + tag->buf = REALLOC(tag->buf, bufSize); + if (!tag->buf) + return XML_ERROR_NO_MEMORY; + tag->bufEnd = tag->buf + bufSize; + } + memcpy(tag->buf, tag->rawName, tag->rawNameLength); + tag->rawName = tag->buf; + } + ++tagLevel; + if (startElementHandler) { + enum XML_Error result; + XML_Char *toPtr; + for (;;) { + const char *rawNameEnd = tag->rawName + tag->rawNameLength; + const char *fromPtr = tag->rawName; + int bufSize; + if (nextPtr) + toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char))); + else + toPtr = (XML_Char *)tag->buf; + tag->name.str = toPtr; + XmlConvert(enc, + &fromPtr, rawNameEnd, + (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); + if (fromPtr == rawNameEnd) + break; + bufSize = (tag->bufEnd - tag->buf) << 1; + tag->buf = REALLOC(tag->buf, bufSize); + if (!tag->buf) + return XML_ERROR_NO_MEMORY; + tag->bufEnd = tag->buf + bufSize; + if (nextPtr) + tag->rawName = tag->buf; + } + *toPtr = XML_T('\0'); + result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings)); + if (result) + return result; + startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts); + poolClear(&tempPool); + } + else { + tag->name.str = 0; + if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + } + case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: + if (!startElementHandler) { + enum XML_Error result = storeAtts(parser, enc, s, 0, 0); + if (result) + return result; + } + /* fall through */ + case XML_TOK_EMPTY_ELEMENT_NO_ATTS: + if (startElementHandler || endElementHandler) { + const char *rawName = s + enc->minBytesPerChar; + enum XML_Error result; + BINDING *bindings = 0; + TAG_NAME name; + name.str = poolStoreString(&tempPool, enc, rawName, + rawName + XmlNameLength(enc, rawName)); + if (!name.str) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + result = storeAtts(parser, enc, s, &name, &bindings); + if (result) + return result; + poolFinish(&tempPool); + if (startElementHandler) + startElementHandler(handlerArg, name.str, (const XML_Char **)atts); + if (endElementHandler) { + if (startElementHandler) + *eventPP = *eventEndPP; + endElementHandler(handlerArg, name.str); + } + poolClear(&tempPool); + while (bindings) { + BINDING *b = bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + bindings = bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + break; + case XML_TOK_END_TAG: + if (tagLevel == startTagLevel) + return XML_ERROR_ASYNC_ENTITY; + else { + int len; + const char *rawName; + TAG *tag = tagStack; + tagStack = tag->parent; + tag->parent = freeTagList; + freeTagList = tag; + rawName = s + enc->minBytesPerChar*2; + len = XmlNameLength(enc, rawName); + if (len != tag->rawNameLength + || memcmp(tag->rawName, rawName, len) != 0) { + *eventPP = rawName; + return XML_ERROR_TAG_MISMATCH; + } + --tagLevel; + if (endElementHandler && tag->name.str) { + if (tag->name.localPart) { + XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen; + const XML_Char *from = tag->name.localPart; + while ((*to++ = *from++) != 0) + ; + } + endElementHandler(handlerArg, tag->name.str); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + while (tag->bindings) { + BINDING *b = tag->bindings; + if (endNamespaceDeclHandler) + endNamespaceDeclHandler(handlerArg, b->prefix->name); + tag->bindings = tag->bindings->nextTagBinding; + b->nextTagBinding = freeBindingList; + freeBindingList = b; + b->prefix->binding = b->prevPrefixBinding; + } + if (tagLevel == 0) + return epilogProcessor(parser, next, end, nextPtr); + } + break; + case XML_TOK_CHAR_REF: + { + int n = XmlCharRefNumber(enc, s); + if (n < 0) + return XML_ERROR_BAD_CHAR_REF; + if (characterDataHandler) { + XML_Char buf[XML_ENCODE_MAX]; + characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + } + break; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_CDATA_SECT_OPEN: + { + enum XML_Error result; + if (startCdataSectionHandler) + startCdataSectionHandler(handlerArg); +#if 0 + /* Suppose you doing a transformation on a document that involves + changing only the character data. You set up a defaultHandler + and a characterDataHandler. The defaultHandler simply copies + characters through. The characterDataHandler does the transformation + and writes the characters out escaping them as necessary. This case + will fail to work if we leave out the following two lines (because & + and < inside CDATA sections will be incorrectly escaped). + + However, now we have a start/endCdataSectionHandler, so it seems + easier to let the user deal with this. */ + + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); +#endif + else if (defaultHandler) + reportDefault(parser, enc, s, next); + result = doCdataSection(parser, enc, &next, end, nextPtr); + if (!next) { + processor = cdataSectionProcessor; + return result; + } + } + break; + case XML_TOK_TRAILING_RSQB: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)end - (XML_Char *)s); + } + else if (defaultHandler) + reportDefault(parser, enc, s, end); + if (startTagLevel == 0) { + *eventPP = end; + return XML_ERROR_NO_ELEMENTS; + } + if (tagLevel != startTagLevel) { + *eventPP = end; + return XML_ERROR_ASYNC_ENTITY; + } + return XML_ERROR_NONE; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + if (s == next) + break; + *eventPP = s; + } + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)next - (XML_Char *)s); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + default: + if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + } + *eventPP = s = next; + } + /* not reached */ +} + +/* If tagNamePtr is non-null, build a real list of attributes, +otherwise just check the attributes for well-formedness. */ + +static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, + const char *attStr, TAG_NAME *tagNamePtr, + BINDING **bindingsPtr) +{ + ELEMENT_TYPE *elementType = 0; + int nDefaultAtts = 0; + const XML_Char **appAtts; /* the attribute list to pass to the application */ + int attIndex = 0; + int i; + int n; + int nPrefixes = 0; + BINDING *binding; + const XML_Char *localPart; + + /* lookup the element type name */ + if (tagNamePtr) { + elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str,0); + if (!elementType) { + tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str); + if (!tagNamePtr->str) + return XML_ERROR_NO_MEMORY; + elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE)); + if (!elementType) + return XML_ERROR_NO_MEMORY; + if (ns && !setElementTypePrefix(parser, elementType)) + return XML_ERROR_NO_MEMORY; + } + nDefaultAtts = elementType->nDefaultAtts; + } + /* get the attributes from the tokenizer */ + n = XmlGetAttributes(enc, attStr, attsSize, atts); + if (n + nDefaultAtts > attsSize) { + int oldAttsSize = attsSize; + attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; + atts = REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE)); + if (!atts) + return XML_ERROR_NO_MEMORY; + if (n > oldAttsSize) + XmlGetAttributes(enc, attStr, n, atts); + } + appAtts = (const XML_Char **)atts; + for (i = 0; i < n; i++) { + /* add the name and value to the attribute list */ + ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name, + atts[i].name + + XmlNameLength(enc, atts[i].name)); + if (!attId) + return XML_ERROR_NO_MEMORY; + /* detect duplicate attributes */ + if ((attId->name)[-1]) { + if (enc == encoding) + eventPtr = atts[i].name; + return XML_ERROR_DUPLICATE_ATTRIBUTE; + } + (attId->name)[-1] = 1; + appAtts[attIndex++] = attId->name; + if (!atts[i].normalized) { + enum XML_Error result; + int isCdata = 1; + + /* figure out whether declared as other than CDATA */ + if (attId->maybeTokenized) { + int j; + for (j = 0; j < nDefaultAtts; j++) { + if (attId == elementType->defaultAtts[j].id) { + isCdata = elementType->defaultAtts[j].isCdata; + break; + } + } + } + + /* normalize the attribute value */ + result = storeAttributeValue(parser, enc, isCdata, + atts[i].valuePtr, atts[i].valueEnd, + &tempPool); + if (result) + return result; + if (tagNamePtr) { + appAtts[attIndex] = poolStart(&tempPool); + poolFinish(&tempPool); + } + else + poolDiscard(&tempPool); + } + else if (tagNamePtr) { + /* the value did not need normalizing */ + appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd); + if (appAtts[attIndex] == 0) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } + /* handle prefixed attribute names */ + if (attId->prefix && tagNamePtr) { + if (attId->xmlns) { + /* deal with namespace declarations here */ + if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr)) + return XML_ERROR_NO_MEMORY; + --attIndex; + } + else { + /* deal with other prefixed names later */ + attIndex++; + nPrefixes++; + (attId->name)[-1] = 2; + } + } + else + attIndex++; + } + if (tagNamePtr) { + int j; + nSpecifiedAtts = attIndex; + if (elementType->idAtt && (elementType->idAtt->name)[-1]) { + for (i = 0; i < attIndex; i += 2) + if (appAtts[i] == elementType->idAtt->name) { + idAttIndex = i; + break; + } + } + else + idAttIndex = -1; + /* do attribute defaulting */ + for (j = 0; j < nDefaultAtts; j++) { + const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j; + if (!(da->id->name)[-1] && da->value) { + if (da->id->prefix) { + if (da->id->xmlns) { + if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr)) + return XML_ERROR_NO_MEMORY; + } + else { + (da->id->name)[-1] = 2; + nPrefixes++; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + else { + (da->id->name)[-1] = 1; + appAtts[attIndex++] = da->id->name; + appAtts[attIndex++] = da->value; + } + } + } + appAtts[attIndex] = 0; + } + i = 0; + if (nPrefixes) { + /* expand prefixed attribute names */ + for (; i < attIndex; i += 2) { + if (appAtts[i][-1] == 2) { + ATTRIBUTE_ID *id; + ((XML_Char *)(appAtts[i]))[-1] = 0; + id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0); + if (id->prefix->binding) { + int j; + const BINDING *b = id->prefix->binding; + const XML_Char *s = appAtts[i]; + for (j = 0; j < b->uriLen; j++) { + if (!poolAppendChar(&tempPool, b->uri[j])) + return XML_ERROR_NO_MEMORY; + } + while (*s++ != ':') + ; + do { + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + } while (*s++); + if (ns_triplets) { + tempPool.ptr[-1] = namespaceSeparator; + s = b->prefix->name; + do { + if (!poolAppendChar(&tempPool, *s)) + return XML_ERROR_NO_MEMORY; + } while (*s++); + } + + appAtts[i] = poolStart(&tempPool); + poolFinish(&tempPool); + } + if (!--nPrefixes) + break; + } + else + ((XML_Char *)(appAtts[i]))[-1] = 0; + } + } + /* clear the flags that say whether attributes were specified */ + for (; i < attIndex; i += 2) + ((XML_Char *)(appAtts[i]))[-1] = 0; + if (!tagNamePtr) + return XML_ERROR_NONE; + for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) + binding->attId->name[-1] = 0; + /* expand the element type name */ + if (elementType->prefix) { + binding = elementType->prefix->binding; + if (!binding) + return XML_ERROR_NONE; + localPart = tagNamePtr->str; + while (*localPart++ != XML_T(':')) + ; + } + else if (dtd.defaultPrefix.binding) { + binding = dtd.defaultPrefix.binding; + localPart = tagNamePtr->str; + } + else + return XML_ERROR_NONE; + tagNamePtr->localPart = localPart; + tagNamePtr->uriLen = binding->uriLen; + for (i = 0; localPart[i++];) + ; + n = i + binding->uriLen; + if (n > binding->uriAlloc) { + TAG *p; + XML_Char *uri = MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char)); + if (!uri) + return XML_ERROR_NO_MEMORY; + binding->uriAlloc = n + EXPAND_SPARE; + memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); + for (p = tagStack; p; p = p->parent) + if (p->name.str == binding->uri) + p->name.str = uri; + FREE(binding->uri); + binding->uri = uri; + } + memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char)); + tagNamePtr->str = binding->uri; + return XML_ERROR_NONE; +} + +static +int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) +{ + BINDING *b; + int len; + for (len = 0; uri[len]; len++) + ; + if (namespaceSeparator) + len++; + if (freeBindingList) { + b = freeBindingList; + if (len > b->uriAlloc) { + b->uri = REALLOC(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (!b->uri) + return 0; + b->uriAlloc = len + EXPAND_SPARE; + } + freeBindingList = b->nextTagBinding; + } + else { + b = MALLOC(sizeof(BINDING)); + if (!b) + return 0; + b->uri = MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE)); + if (!b->uri) { + FREE(b); + return 0; + } + b->uriAlloc = len + EXPAND_SPARE; + } + b->uriLen = len; + memcpy(b->uri, uri, len * sizeof(XML_Char)); + if (namespaceSeparator) + b->uri[len - 1] = namespaceSeparator; + b->prefix = prefix; + b->attId = attId; + b->prevPrefixBinding = prefix->binding; + if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix) + prefix->binding = 0; + else + prefix->binding = b; + b->nextTagBinding = *bindingsPtr; + *bindingsPtr = b; + if (startNamespaceDeclHandler) + startNamespaceDeclHandler(handlerArg, prefix->name, + prefix->binding ? uri : 0); + return 1; +} + +/* The idea here is to avoid using stack for each CDATA section when +the whole file is parsed with one call. */ + +static +enum XML_Error cdataSectionProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr); + if (start) { + processor = contentProcessor; + return contentProcessor(parser, start, end, endPtr); + } + return result; +} + +/* startPtr gets set to non-null is the section is closed, and to null if +the section is not yet closed. */ + +static +enum XML_Error doCdataSection(XML_Parser parser, + const ENCODING *enc, + const char **startPtr, + const char *end, + const char **nextPtr) +{ + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + *eventPP = s; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = 0; + for (;;) { + const char *next; + int tok = XmlCdataSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_CDATA_SECT_CLOSE: + if (endCdataSectionHandler) + endCdataSectionHandler(handlerArg); +#if 0 + /* see comment under XML_TOK_CDATA_SECT_OPEN */ + else if (characterDataHandler) + characterDataHandler(handlerArg, dataBuf, 0); +#endif + else if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + return XML_ERROR_NONE; + case XML_TOK_DATA_NEWLINE: + if (characterDataHandler) { + XML_Char c = 0xA; + characterDataHandler(handlerArg, &c, 1); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_DATA_CHARS: + if (characterDataHandler) { + if (MUST_CONVERT(enc, s)) { + for (;;) { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = next; + characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + if (s == next) + break; + *eventPP = s; + } + } + else + characterDataHandler(handlerArg, + (XML_Char *)s, + (XML_Char *)next - (XML_Char *)s); + } + else if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_CDATA_SECTION; + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } + *eventPP = s = next; + } + /* not reached */ +} + +#ifdef XML_DTD + +/* The idea here is to avoid using stack for each IGNORE section when +the whole file is parsed with one call. */ + +static +enum XML_Error ignoreSectionProcessor(XML_Parser parser, + const char *start, + const char *end, + const char **endPtr) +{ + enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, endPtr); + if (start) { + processor = prologProcessor; + return prologProcessor(parser, start, end, endPtr); + } + return result; +} + +/* startPtr gets set to non-null is the section is closed, and to null if +the section is not yet closed. */ + +static +enum XML_Error doIgnoreSection(XML_Parser parser, + const ENCODING *enc, + const char **startPtr, + const char *end, + const char **nextPtr) +{ + const char *next; + int tok; + const char *s = *startPtr; + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + *eventPP = s; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + *eventPP = s; + *startPtr = 0; + tok = XmlIgnoreSectionTok(enc, s, end, &next); + *eventEndPP = next; + switch (tok) { + case XML_TOK_IGNORE_SECT: + if (defaultHandler) + reportDefault(parser, enc, s, next); + *startPtr = next; + return XML_ERROR_NONE; + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_PARTIAL: + case XML_TOK_NONE: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ + default: + *eventPP = next; + return XML_ERROR_UNEXPECTED_STATE; + } + /* not reached */ +} + +#endif /* XML_DTD */ + +static enum XML_Error +initializeEncoding(XML_Parser parser) +{ + const char *s; +#ifdef XML_UNICODE + char encodingBuf[128]; + if (!protocolEncodingName) + s = 0; + else { + int i; + for (i = 0; protocolEncodingName[i]; i++) { + if (i == sizeof(encodingBuf) - 1 + || (protocolEncodingName[i] & ~0x7f) != 0) { + encodingBuf[0] = '\0'; + break; + } + encodingBuf[i] = (char)protocolEncodingName[i]; + } + encodingBuf[i] = '\0'; + s = encodingBuf; + } +#else + s = protocolEncodingName; +#endif + if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s)) + return XML_ERROR_NONE; + return handleUnknownEncoding(parser, protocolEncodingName); +} + +static enum XML_Error +processXmlDecl(XML_Parser parser, int isGeneralTextEntity, + const char *s, const char *next) +{ + const char *encodingName = 0; + const char *storedEncName = 0; + const ENCODING *newEncoding = 0; + const char *version = 0; + const char *versionend; + const char *storedversion = 0; + int standalone = -1; + if (!(ns + ? XmlParseXmlDeclNS + : XmlParseXmlDecl)(isGeneralTextEntity, + encoding, + s, + next, + &eventPtr, + &version, + &versionend, + &encodingName, + &newEncoding, + &standalone)) + return XML_ERROR_SYNTAX; + if (!isGeneralTextEntity && standalone == 1) { + dtd.standalone = 1; +#ifdef XML_DTD + if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) + paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; +#endif /* XML_DTD */ + } + if (xmlDeclHandler) { + if (encodingName) { + storedEncName = poolStoreString(&temp2Pool, + encoding, + encodingName, + encodingName + + XmlNameLength(encoding, encodingName)); + if (! storedEncName) + return XML_ERROR_NO_MEMORY; + poolFinish(&temp2Pool); + } + if (version) { + storedversion = poolStoreString(&temp2Pool, + encoding, + version, + versionend - encoding->minBytesPerChar); + if (! storedversion) + return XML_ERROR_NO_MEMORY; + } + xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone); + } + else if (defaultHandler) + reportDefault(parser, encoding, s, next); + if (!protocolEncodingName) { + if (newEncoding) { + if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) { + eventPtr = encodingName; + return XML_ERROR_INCORRECT_ENCODING; + } + encoding = newEncoding; + } + else if (encodingName) { + enum XML_Error result; + if (! storedEncName) { + storedEncName = poolStoreString(&temp2Pool, + encoding, + encodingName, + encodingName + + XmlNameLength(encoding, encodingName)); + if (! storedEncName) + return XML_ERROR_NO_MEMORY; + } + result = handleUnknownEncoding(parser, storedEncName); + poolClear(&tempPool); + if (result == XML_ERROR_UNKNOWN_ENCODING) + eventPtr = encodingName; + return result; + } + } + + if (storedEncName || storedversion) + poolClear(&temp2Pool); + + return XML_ERROR_NONE; +} + +static enum XML_Error +handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) +{ + if (unknownEncodingHandler) { + XML_Encoding info; + int i; + for (i = 0; i < 256; i++) + info.map[i] = -1; + info.convert = 0; + info.data = 0; + info.release = 0; + if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) { + ENCODING *enc; + unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding()); + if (!unknownEncodingMem) { + if (info.release) + info.release(info.data); + return XML_ERROR_NO_MEMORY; + } + enc = (ns + ? XmlInitUnknownEncodingNS + : XmlInitUnknownEncoding)(unknownEncodingMem, + info.map, + info.convert, + info.data); + if (enc) { + unknownEncodingData = info.data; + unknownEncodingRelease = info.release; + encoding = enc; + return XML_ERROR_NONE; + } + } + if (info.release) + info.release(info.data); + } + return XML_ERROR_UNKNOWN_ENCODING; +} + +static enum XML_Error +prologInitProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + enum XML_Error result = initializeEncoding(parser); + if (result != XML_ERROR_NONE) + return result; + processor = prologProcessor; + return prologProcessor(parser, s, end, nextPtr); +} + +static enum XML_Error +prologProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + const char *next; + int tok = XmlPrologTok(encoding, s, end, &next); + return doProlog(parser, encoding, s, end, tok, next, nextPtr); +} + +static enum XML_Error +doProlog(XML_Parser parser, + const ENCODING *enc, + const char *s, + const char *end, + int tok, + const char *next, + const char **nextPtr) +{ +#ifdef XML_DTD + static const XML_Char externalSubsetName[] = { '#' , '\0' }; +#endif /* XML_DTD */ + + const char **eventPP; + const char **eventEndPP; + enum XML_Content_Quant quant; + + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + for (;;) { + int role; + *eventPP = s; + *eventEndPP = next; + if (tok <= 0) { + if (nextPtr != 0 && tok != XML_TOK_INVALID) { + *nextPtr = s; + return XML_ERROR_NONE; + } + switch (tok) { + case XML_TOK_INVALID: + *eventPP = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + return XML_ERROR_PARTIAL_CHAR; + case XML_TOK_NONE: +#ifdef XML_DTD + if (enc != encoding) + return XML_ERROR_NONE; + if (parentParser) { + if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc) + == XML_ROLE_ERROR) + return XML_ERROR_SYNTAX; + hadExternalDoctype = 0; + return XML_ERROR_NONE; + } +#endif /* XML_DTD */ + return XML_ERROR_NO_ELEMENTS; + default: + tok = -tok; + next = end; + break; + } + } + role = XmlTokenRole(&prologState, tok, s, next, enc); + switch (role) { + case XML_ROLE_XML_DECL: + { + enum XML_Error result = processXmlDecl(parser, 0, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + } + break; + case XML_ROLE_DOCTYPE_NAME: + if (startDoctypeDeclHandler) { + doctypeName = poolStoreString(&tempPool, enc, s, next); + if (! doctypeName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + doctypeSysid = 0; + doctypePubid = 0; + } + break; + case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: + if (startDoctypeDeclHandler) { + startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid, + doctypePubid, 1); + doctypeName = 0; + poolClear(&tempPool); + } + break; +#ifdef XML_DTD + case XML_ROLE_TEXT_DECL: + { + enum XML_Error result = processXmlDecl(parser, 1, s, next); + if (result != XML_ERROR_NONE) + return result; + enc = encoding; + } + break; +#endif /* XML_DTD */ + case XML_ROLE_DOCTYPE_PUBLIC_ID: + if (startDoctypeDeclHandler) { + doctypePubid = poolStoreString(&tempPool, enc, s + 1, next - 1); + if (! doctypePubid) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } +#ifdef XML_DTD + declEntity = (ENTITY *)lookup(&dtd.paramEntities, + externalSubsetName, + sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; +#endif /* XML_DTD */ + /* fall through */ + case XML_ROLE_ENTITY_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_SYNTAX; + if (declEntity) { + XML_Char *tem = poolStoreString(&dtd.pool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declEntity->publicId = tem; + poolFinish(&dtd.pool); + } + break; + case XML_ROLE_DOCTYPE_CLOSE: + if (doctypeName) { + startDoctypeDeclHandler(handlerArg, doctypeName, + doctypeSysid, doctypePubid, 0); + poolClear(&tempPool); + } + if (dtd.complete && hadExternalDoctype) { + dtd.complete = 0; +#ifdef XML_DTD + if (paramEntityParsing && externalEntityRefHandler) { + ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities, + externalSubsetName, + 0); + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } +#endif /* XML_DTD */ + if (!dtd.complete + && !dtd.standalone + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + } + if (endDoctypeDeclHandler) + endDoctypeDeclHandler(handlerArg); + break; + case XML_ROLE_INSTANCE_START: + processor = contentProcessor; + return contentProcessor(parser, s, end, nextPtr); + case XML_ROLE_ATTLIST_ELEMENT_NAME: + declElementType = getElementType(parser, enc, s, next); + if (!declElementType) + return XML_ERROR_NO_MEMORY; + break; + case XML_ROLE_ATTRIBUTE_NAME: + declAttributeId = getAttributeId(parser, enc, s, next); + if (!declAttributeId) + return XML_ERROR_NO_MEMORY; + declAttributeIsCdata = 0; + declAttributeType = 0; + declAttributeIsId = 0; + break; + case XML_ROLE_ATTRIBUTE_TYPE_CDATA: + declAttributeIsCdata = 1; + declAttributeType = "CDATA"; + break; + case XML_ROLE_ATTRIBUTE_TYPE_ID: + declAttributeIsId = 1; + declAttributeType = "ID"; + break; + case XML_ROLE_ATTRIBUTE_TYPE_IDREF: + declAttributeType = "IDREF"; + break; + case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: + declAttributeType = "IDREFS"; + break; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: + declAttributeType = "ENTITY"; + break; + case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: + declAttributeType = "ENTITIES"; + break; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: + declAttributeType = "NMTOKEN"; + break; + case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: + declAttributeType = "NMTOKENS"; + break; + + case XML_ROLE_ATTRIBUTE_ENUM_VALUE: + case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: + if (attlistDeclHandler) + { + char *prefix; + if (declAttributeType) { + prefix = "|"; + } + else { + prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE + ? "NOTATION(" + : "("); + } + if (! poolAppendString(&tempPool, prefix)) + return XML_ERROR_NO_MEMORY; + if (! poolAppend(&tempPool, enc, s, next)) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + } + break; + case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: + case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: + if (dtd.complete + && !defineAttribute(declElementType, declAttributeId, + declAttributeIsCdata, declAttributeIsId, 0, + parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == '(' + || (*declAttributeType == 'N' && declAttributeType[1] == 'O')) { + /* Enumerated or Notation type */ + if (! poolAppendChar(&tempPool, ')') + || ! poolAppendChar(&tempPool, '\0')) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + } + break; + case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: + case XML_ROLE_FIXED_ATTRIBUTE_VALUE: + { + const XML_Char *attVal; + enum XML_Error result + = storeAttributeValue(parser, enc, declAttributeIsCdata, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar, + &dtd.pool); + if (result) + return result; + attVal = poolStart(&dtd.pool); + poolFinish(&dtd.pool); + if (dtd.complete + /* ID attributes aren't allowed to have a default */ + && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0, attVal, parser)) + return XML_ERROR_NO_MEMORY; + if (attlistDeclHandler && declAttributeType) { + if (*declAttributeType == '(' + || (*declAttributeType == 'N' && declAttributeType[1] == 'O')) { + /* Enumerated or Notation type */ + if (! poolAppendChar(&tempPool, ')') + || ! poolAppendChar(&tempPool, '\0')) + return XML_ERROR_NO_MEMORY; + declAttributeType = tempPool.start; + poolFinish(&tempPool); + } + *eventEndPP = s; + attlistDeclHandler(handlerArg, declElementType->name, + declAttributeId->name, declAttributeType, + attVal, + role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); + poolClear(&tempPool); + } + break; + } + case XML_ROLE_ENTITY_VALUE: + { + enum XML_Error result = storeEntityValue(parser, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (declEntity) { + declEntity->textPtr = poolStart(&dtd.pool); + declEntity->textLen = poolLength(&dtd.pool); + poolFinish(&dtd.pool); + if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + declEntity->is_param, + declEntity->textPtr, + declEntity->textLen, + curBase, 0, 0, 0); + } + } + else + poolDiscard(&dtd.pool); + if (result != XML_ERROR_NONE) + return result; + } + break; + case XML_ROLE_DOCTYPE_SYSTEM_ID: + if (startDoctypeDeclHandler) { + doctypeSysid = poolStoreString(&tempPool, enc, s + 1, next - 1); + if (! doctypeSysid) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } + if (!dtd.standalone +#ifdef XML_DTD + && !paramEntityParsing +#endif /* XML_DTD */ + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + hadExternalDoctype = 1; +#ifndef XML_DTD + break; +#else /* XML_DTD */ + if (!declEntity) { + declEntity = (ENTITY *)lookup(&dtd.paramEntities, + externalSubsetName, + sizeof(ENTITY)); + declEntity->publicId = 0; + if (!declEntity) + return XML_ERROR_NO_MEMORY; + } + /* fall through */ +#endif /* XML_DTD */ + case XML_ROLE_ENTITY_SYSTEM_ID: + if (declEntity) { + declEntity->systemId = poolStoreString(&dtd.pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!declEntity->systemId) + return XML_ERROR_NO_MEMORY; + declEntity->base = curBase; + poolFinish(&dtd.pool); + } + break; + case XML_ROLE_ENTITY_COMPLETE: + if (declEntity && entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + 0,0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + 0); + } + break; + case XML_ROLE_ENTITY_NOTATION_NAME: + if (declEntity) { + declEntity->notation = poolStoreString(&dtd.pool, enc, s, next); + if (!declEntity->notation) + return XML_ERROR_NO_MEMORY; + poolFinish(&dtd.pool); + if (unparsedEntityDeclHandler) { + *eventEndPP = s; + unparsedEntityDeclHandler(handlerArg, + declEntity->name, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + } + else if (entityDeclHandler) { + *eventEndPP = s; + entityDeclHandler(handlerArg, + declEntity->name, + 0,0,0, + declEntity->base, + declEntity->systemId, + declEntity->publicId, + declEntity->notation); + } + } + break; + case XML_ROLE_GENERAL_ENTITY_NAME: + { + const XML_Char *name; + if (XmlPredefinedEntityName(enc, s, next)) { + declEntity = 0; + break; + } + name = poolStoreString(&dtd.pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + if (dtd.complete) { + declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd.pool); + declEntity = 0; + } + else { + poolFinish(&dtd.pool); + declEntity->publicId = 0; + declEntity->is_param = 0; + } + } + else { + poolDiscard(&dtd.pool); + declEntity = 0; + } + } + break; + case XML_ROLE_PARAM_ENTITY_NAME: +#ifdef XML_DTD + if (dtd.complete) { + const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next); + if (!name) + return XML_ERROR_NO_MEMORY; + declEntity = (ENTITY *)lookup(&dtd.paramEntities, + name, sizeof(ENTITY)); + if (!declEntity) + return XML_ERROR_NO_MEMORY; + if (declEntity->name != name) { + poolDiscard(&dtd.pool); + declEntity = 0; + } + else { + poolFinish(&dtd.pool); + declEntity->publicId = 0; + declEntity->is_param = 1; + } + } +#else /* not XML_DTD */ + declEntity = 0; +#endif /* not XML_DTD */ + break; + case XML_ROLE_NOTATION_NAME: + declNotationPublicId = 0; + declNotationName = 0; + if (notationDeclHandler) { + declNotationName = poolStoreString(&tempPool, enc, s, next); + if (!declNotationName) + return XML_ERROR_NO_MEMORY; + poolFinish(&tempPool); + } + break; + case XML_ROLE_NOTATION_PUBLIC_ID: + if (!XmlIsPublicId(enc, s, next, eventPP)) + return XML_ERROR_SYNTAX; + if (declNotationName) { + XML_Char *tem = poolStoreString(&tempPool, + enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!tem) + return XML_ERROR_NO_MEMORY; + normalizePublicId(tem); + declNotationPublicId = tem; + poolFinish(&tempPool); + } + break; + case XML_ROLE_NOTATION_SYSTEM_ID: + if (declNotationName && notationDeclHandler) { + const XML_Char *systemId + = poolStoreString(&tempPool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!systemId) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + systemId, + declNotationPublicId); + } + poolClear(&tempPool); + break; + case XML_ROLE_NOTATION_NO_SYSTEM_ID: + if (declNotationPublicId && notationDeclHandler) { + *eventEndPP = s; + notationDeclHandler(handlerArg, + declNotationName, + curBase, + 0, + declNotationPublicId); + } + poolClear(&tempPool); + break; + case XML_ROLE_ERROR: + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: + return XML_ERROR_PARAM_ENTITY_REF; + case XML_TOK_XML_DECL: + return XML_ERROR_MISPLACED_XML_PI; + default: + return XML_ERROR_SYNTAX; + } +#ifdef XML_DTD + case XML_ROLE_IGNORE_SECT: + { + enum XML_Error result; + if (defaultHandler) + reportDefault(parser, enc, s, next); + result = doIgnoreSection(parser, enc, &next, end, nextPtr); + if (!next) { + processor = ignoreSectionProcessor; + return result; + } + } + break; +#endif /* XML_DTD */ + case XML_ROLE_GROUP_OPEN: + if (prologState.level >= groupSize) { + if (groupSize) { + groupConnector = REALLOC(groupConnector, groupSize *= 2); + if (dtd.scaffIndex) + dtd.scaffIndex = REALLOC(dtd.scaffIndex, groupSize * sizeof(int)); + } + else + groupConnector = MALLOC(groupSize = 32); + if (!groupConnector) + return XML_ERROR_NO_MEMORY; + } + groupConnector[prologState.level] = 0; + if (dtd.in_eldecl) { + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd.scaffIndex[dtd.scaffLevel] = myindex; + dtd.scaffLevel++; + dtd.scaffold[myindex].type = XML_CTYPE_SEQ; + } + break; + case XML_ROLE_GROUP_SEQUENCE: + if (groupConnector[prologState.level] == '|') + return XML_ERROR_SYNTAX; + groupConnector[prologState.level] = ','; + break; + case XML_ROLE_GROUP_CHOICE: + if (groupConnector[prologState.level] == ',') + return XML_ERROR_SYNTAX; + if (dtd.in_eldecl + && ! groupConnector[prologState.level] + && dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type != XML_CTYPE_MIXED + ) { + dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type = XML_CTYPE_CHOICE; + } + groupConnector[prologState.level] = '|'; + break; + case XML_ROLE_PARAM_ENTITY_REF: +#ifdef XML_DTD + case XML_ROLE_INNER_PARAM_ENTITY_REF: + if (paramEntityParsing + && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) { + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&dtd.pool, enc, + s + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0); + poolDiscard(&dtd.pool); + if (!entity) { + /* FIXME what to do if !dtd.complete? */ + return XML_ERROR_UNDEFINED_ENTITY; + } + if (entity->open) + return XML_ERROR_RECURSIVE_ENTITY_REF; + if (entity->textPtr) { + enum XML_Error result; + result = processInternalParamEntity(parser, entity); + if (result != XML_ERROR_NONE) + return result; + break; + } + if (role == XML_ROLE_INNER_PARAM_ENTITY_REF) + return XML_ERROR_PARAM_ENTITY_REF; + if (externalEntityRefHandler) { + dtd.complete = 0; + entity->open = 1; + if (!externalEntityRefHandler(externalEntityRefHandlerArg, + 0, + entity->base, + entity->systemId, + entity->publicId)) { + entity->open = 0; + return XML_ERROR_EXTERNAL_ENTITY_HANDLING; + } + entity->open = 0; + if (dtd.complete) + break; + } + } +#endif /* XML_DTD */ + if (!dtd.standalone + && notStandaloneHandler + && !notStandaloneHandler(handlerArg)) + return XML_ERROR_NOT_STANDALONE; + dtd.complete = 0; + if (defaultHandler) + reportDefault(parser, enc, s, next); + break; + + /* Element declaration stuff */ + + case XML_ROLE_ELEMENT_NAME: + if (elementDeclHandler) { + declElementType = getElementType(parser, enc, s, next); + if (! declElementType) + return XML_ERROR_NO_MEMORY; + dtd.scaffLevel = 0; + dtd.scaffCount = 0; + dtd.in_eldecl = 1; + } + break; + + case XML_ROLE_CONTENT_ANY: + case XML_ROLE_CONTENT_EMPTY: + if (dtd.in_eldecl) { + if (elementDeclHandler) { + XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content)); + if (! content) + return XML_ERROR_NO_MEMORY; + content->quant = XML_CQUANT_NONE; + content->name = 0; + content->numchildren = 0; + content->children = 0; + content->type = ((role == XML_ROLE_CONTENT_ANY) ? + XML_CTYPE_ANY : + XML_CTYPE_EMPTY); + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, content); + } + dtd.in_eldecl = 0; + } + break; + + case XML_ROLE_CONTENT_PCDATA: + if (dtd.in_eldecl) { + dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type = XML_CTYPE_MIXED; + } + break; + + case XML_ROLE_CONTENT_ELEMENT: + quant = XML_CQUANT_NONE; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_OPT: + quant = XML_CQUANT_OPT; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_REP: + quant = XML_CQUANT_REP; + goto elementContent; + case XML_ROLE_CONTENT_ELEMENT_PLUS: + quant = XML_CQUANT_PLUS; + elementContent: + if (dtd.in_eldecl) + { + ELEMENT_TYPE *el; + const char *nxt = quant == XML_CQUANT_NONE ? next : next - 1; + int myindex = nextScaffoldPart(parser); + if (myindex < 0) + return XML_ERROR_NO_MEMORY; + dtd.scaffold[myindex].type = XML_CTYPE_NAME; + dtd.scaffold[myindex].quant = quant; + el = getElementType(parser, enc, s, nxt); + if (! el) + return XML_ERROR_NO_MEMORY; + dtd.scaffold[myindex].name = el->name; + dtd.contentStringLen += nxt - s + 1; + } + break; + + case XML_ROLE_GROUP_CLOSE: + quant = XML_CQUANT_NONE; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_OPT: + quant = XML_CQUANT_OPT; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_REP: + quant = XML_CQUANT_REP; + goto closeGroup; + case XML_ROLE_GROUP_CLOSE_PLUS: + quant = XML_CQUANT_PLUS; + closeGroup: + if (dtd.in_eldecl) { + dtd.scaffLevel--; + dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel]].quant = quant; + if (dtd.scaffLevel == 0) { + if (elementDeclHandler) { + XML_Content *model = build_model(parser); + if (! model) + return XML_ERROR_NO_MEMORY; + *eventEndPP = s; + elementDeclHandler(handlerArg, declElementType->name, model); + } + dtd.in_eldecl = 0; + dtd.contentStringLen = 0; + } + } + break; + /* End element declaration stuff */ + + case XML_ROLE_NONE: + switch (tok) { + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, enc, s, next)) + return XML_ERROR_NO_MEMORY; + break; + } + break; + } + if (defaultHandler) { + switch (tok) { + case XML_TOK_PI: + case XML_TOK_COMMENT: + case XML_TOK_BOM: + case XML_TOK_XML_DECL: +#ifdef XML_DTD + case XML_TOK_IGNORE_SECT: +#endif /* XML_DTD */ + case XML_TOK_PARAM_ENTITY_REF: + break; + default: +#ifdef XML_DTD + if (role != XML_ROLE_IGNORE_SECT) +#endif /* XML_DTD */ + reportDefault(parser, enc, s, next); + } + } + s = next; + tok = XmlPrologTok(enc, s, end, &next); + } + /* not reached */ +} + +static +enum XML_Error epilogProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + processor = epilogProcessor; + eventPtr = s; + for (;;) { + const char *next; + int tok = XmlPrologTok(encoding, s, end, &next); + eventEndPtr = next; + switch (tok) { + case -XML_TOK_PROLOG_S: + if (defaultHandler) { + eventEndPtr = end; + reportDefault(parser, encoding, s, end); + } + /* fall through */ + case XML_TOK_NONE: + if (nextPtr) + *nextPtr = end; + return XML_ERROR_NONE; + case XML_TOK_PROLOG_S: + if (defaultHandler) + reportDefault(parser, encoding, s, next); + break; + case XML_TOK_PI: + if (!reportProcessingInstruction(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_COMMENT: + if (!reportComment(parser, encoding, s, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_INVALID: + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_UNCLOSED_TOKEN; + case XML_TOK_PARTIAL_CHAR: + if (nextPtr) { + *nextPtr = s; + return XML_ERROR_NONE; + } + return XML_ERROR_PARTIAL_CHAR; + default: + return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; + } + eventPtr = s = next; + } +} + +#ifdef XML_DTD + +static enum XML_Error +processInternalParamEntity(XML_Parser parser, ENTITY *entity) +{ + const char *s, *end, *next; + int tok; + enum XML_Error result; + OPEN_INTERNAL_ENTITY openEntity; + entity->open = 1; + openEntity.next = openInternalEntities; + openInternalEntities = &openEntity; + openEntity.entity = entity; + openEntity.internalEventPtr = 0; + openEntity.internalEventEndPtr = 0; + s = (char *)entity->textPtr; + end = (char *)(entity->textPtr + entity->textLen); + tok = XmlPrologTok(internalEncoding, s, end, &next); + result = doProlog(parser, internalEncoding, s, end, tok, next, 0); + entity->open = 0; + openInternalEntities = openEntity.next; + return result; +} + +#endif /* XML_DTD */ + +static +enum XML_Error errorProcessor(XML_Parser parser, + const char *s, + const char *end, + const char **nextPtr) +{ + vtkExpatUnused(s); + vtkExpatUnused(end); + vtkExpatUnused(nextPtr); + return errorCode; +} + +static enum XML_Error +storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, + const char *ptr, const char *end, + STRING_POOL *pool) +{ + enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool); + if (result) + return result; + if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) + poolChop(pool); + if (!poolAppendChar(pool, XML_T('\0'))) + return XML_ERROR_NO_MEMORY; + return XML_ERROR_NONE; +} + +static enum XML_Error +appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata, + const char *ptr, const char *end, + STRING_POOL *pool) +{ + for (;;) { + const char *next; + int tok = XmlAttributeValueTok(enc, ptr, end, &next); + switch (tok) { + case XML_TOK_NONE: + return XML_ERROR_NONE; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, ptr); + if (n < 0) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + if (!isCdata + && n == 0x20 /* space */ + && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BAD_CHAR_REF; + } + for (i = 0; i < n; i++) { + if (!poolAppendChar(pool, buf[i])) + return XML_ERROR_NO_MEMORY; + } + } + break; + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, ptr, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_TRAILING_CR: + next = ptr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_ATTRIBUTE_VALUE_S: + case XML_TOK_DATA_NEWLINE: + if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) + break; + if (!poolAppendChar(pool, 0x20)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_ENTITY_REF: + { + const XML_Char *name; + ENTITY *entity; + XML_Char ch = XmlPredefinedEntityName(enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (ch) { + if (!poolAppendChar(pool, ch)) + return XML_ERROR_NO_MEMORY; + break; + } + name = poolStoreString(&temp2Pool, enc, + ptr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0); + poolDiscard(&temp2Pool); + if (!entity) { + if (dtd.complete) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_UNDEFINED_ENTITY; + } + } + else if (entity->open) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_RECURSIVE_ENTITY_REF; + } + else if (entity->notation) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_BINARY_ENTITY_REF; + } + else if (!entity->textPtr) { + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; + } + else { + enum XML_Error result; + const XML_Char *textEnd = entity->textPtr + entity->textLen; + entity->open = 1; + result = appendAttributeValue(parser, internalEncoding, isCdata, (char *)entity->textPtr, (char *)textEnd, pool); + entity->open = 0; + if (result) + return result; + } + } + break; + default: + if (enc == encoding) + eventPtr = ptr; + return XML_ERROR_UNEXPECTED_STATE; + } + ptr = next; + } + /* not reached */ +} + +static +enum XML_Error storeEntityValue(XML_Parser parser, + const ENCODING *enc, + const char *entityTextPtr, + const char *entityTextEnd) +{ + STRING_POOL *pool = &(dtd.pool); + for (;;) { + const char *next; + int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); + switch (tok) { + case XML_TOK_PARAM_ENTITY_REF: +#ifdef XML_DTD + if (parentParser || enc != encoding) { + enum XML_Error result; + const XML_Char *name; + ENTITY *entity; + name = poolStoreString(&tempPool, enc, + entityTextPtr + enc->minBytesPerChar, + next - enc->minBytesPerChar); + if (!name) + return XML_ERROR_NO_MEMORY; + entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0); + poolDiscard(&tempPool); + if (!entity) { + if (enc == encoding) + eventPtr = entityTextPtr; + return XML_ERROR_UNDEFINED_ENTITY; + } + if (entity->open) { + if (enc == encoding) + eventPtr = entityTextPtr; + return XML_ERROR_RECURSIVE_ENTITY_REF; + } + if (entity->systemId) { + if (enc == encoding) + eventPtr = entityTextPtr; + return XML_ERROR_PARAM_ENTITY_REF; + } + entity->open = 1; + result = storeEntityValue(parser, + internalEncoding, + (char *)entity->textPtr, + (char *)(entity->textPtr + entity->textLen)); + entity->open = 0; + if (result) + return result; + break; + } +#endif /* XML_DTD */ + eventPtr = entityTextPtr; + return XML_ERROR_SYNTAX; + case XML_TOK_NONE: + return XML_ERROR_NONE; + case XML_TOK_ENTITY_REF: + case XML_TOK_DATA_CHARS: + if (!poolAppend(pool, enc, entityTextPtr, next)) + return XML_ERROR_NO_MEMORY; + break; + case XML_TOK_TRAILING_CR: + next = entityTextPtr + enc->minBytesPerChar; + /* fall through */ + case XML_TOK_DATA_NEWLINE: + if (pool->end == pool->ptr && !poolGrow(pool)) + return XML_ERROR_NO_MEMORY; + *(pool->ptr)++ = 0xA; + break; + case XML_TOK_CHAR_REF: + { + XML_Char buf[XML_ENCODE_MAX]; + int i; + int n = XmlCharRefNumber(enc, entityTextPtr); + if (n < 0) { + if (enc == encoding) + eventPtr = entityTextPtr; + return XML_ERROR_BAD_CHAR_REF; + } + n = XmlEncode(n, (ICHAR *)buf); + if (!n) { + if (enc == encoding) + eventPtr = entityTextPtr; + return XML_ERROR_BAD_CHAR_REF; + } + for (i = 0; i < n; i++) { + if (pool->end == pool->ptr && !poolGrow(pool)) + return XML_ERROR_NO_MEMORY; + *(pool->ptr)++ = buf[i]; + } + } + break; + case XML_TOK_PARTIAL: + if (enc == encoding) + eventPtr = entityTextPtr; + return XML_ERROR_INVALID_TOKEN; + case XML_TOK_INVALID: + if (enc == encoding) + eventPtr = next; + return XML_ERROR_INVALID_TOKEN; + default: + if (enc == encoding) + eventPtr = entityTextPtr; + return XML_ERROR_UNEXPECTED_STATE; + } + entityTextPtr = next; + } + /* not reached */ +} + +static void +normalizeLines(XML_Char *s) +{ + XML_Char *p; + for (;; s++) { + if (*s == XML_T('\0')) + return; + if (*s == 0xD) + break; + } + p = s; + do { + if (*s == 0xD) { + *p++ = 0xA; + if (*++s == 0xA) + s++; + } + else + *p++ = *s++; + } while (*s); + *p = XML_T('\0'); +} + +static int +reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) +{ + const XML_Char *target; + XML_Char *data; + const char *tem; + if (!processingInstructionHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + start += enc->minBytesPerChar * 2; + tem = start + XmlNameLength(enc, start); + target = poolStoreString(&tempPool, enc, start, tem); + if (!target) + return 0; + poolFinish(&tempPool); + data = poolStoreString(&tempPool, enc, + XmlSkipS(enc, tem), + end - enc->minBytesPerChar*2); + if (!data) + return 0; + normalizeLines(data); + processingInstructionHandler(handlerArg, target, data); + poolClear(&tempPool); + return 1; +} + +static int +reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) +{ + XML_Char *data; + if (!commentHandler) { + if (defaultHandler) + reportDefault(parser, enc, start, end); + return 1; + } + data = poolStoreString(&tempPool, + enc, + start + enc->minBytesPerChar * 4, + end - enc->minBytesPerChar * 3); + if (!data) + return 0; + normalizeLines(data); + commentHandler(handlerArg, data); + poolClear(&tempPool); + return 1; +} + +static void +reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) +{ + if (MUST_CONVERT(enc, s)) { + const char **eventPP; + const char **eventEndPP; + if (enc == encoding) { + eventPP = &eventPtr; + eventEndPP = &eventEndPtr; + } + else { + eventPP = &(openInternalEntities->internalEventPtr); + eventEndPP = &(openInternalEntities->internalEventEndPtr); + } + do { + ICHAR *dataPtr = (ICHAR *)dataBuf; + XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd); + *eventEndPP = s; + defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf); + *eventPP = s; + } while (s != end); + } + else + defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s); +} + + +static int +defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata, + int isId, const XML_Char *value, XML_Parser parser) +{ + DEFAULT_ATTRIBUTE *att; + if (value || isId) { + /* The handling of default attributes gets messed up if we have + a default which duplicates a non-default. */ + int i; + for (i = 0; i < type->nDefaultAtts; i++) + if (attId == type->defaultAtts[i].id) + return 1; + if (isId && !type->idAtt && !attId->xmlns) + type->idAtt = attId; + } + if (type->nDefaultAtts == type->allocDefaultAtts) { + if (type->allocDefaultAtts == 0) { + type->allocDefaultAtts = 8; + type->defaultAtts = MALLOC(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); + } + else { + type->allocDefaultAtts *= 2; + type->defaultAtts = REALLOC(type->defaultAtts, + type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE)); + } + if (!type->defaultAtts) + return 0; + } + att = type->defaultAtts + type->nDefaultAtts; + att->id = attId; + att->value = value; + att->isCdata = isCdata; + if (!isCdata) + attId->maybeTokenized = 1; + type->nDefaultAtts += 1; + return 1; +} + +static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) +{ + const XML_Char *name; + for (name = elementType->name; *name; name++) { + if (*name == XML_T(':')) { + PREFIX *prefix; + const XML_Char *s; + for (s = elementType->name; s != name; s++) { + if (!poolAppendChar(&dtd.pool, *s)) + return 0; + } + if (!poolAppendChar(&dtd.pool, XML_T('\0'))) + return 0; + prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); + if (!prefix) + return 0; + if (prefix->name == poolStart(&dtd.pool)) + poolFinish(&dtd.pool); + else + poolDiscard(&dtd.pool); + elementType->prefix = prefix; + + } + } + return 1; +} + +static ATTRIBUTE_ID * +getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) +{ + ATTRIBUTE_ID *id; + const XML_Char *name; + if (!poolAppendChar(&dtd.pool, XML_T('\0'))) + return 0; + name = poolStoreString(&dtd.pool, enc, start, end); + if (!name) + return 0; + ++name; + id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID)); + if (!id) + return 0; + if (id->name != name) + poolDiscard(&dtd.pool); + else { + poolFinish(&dtd.pool); + if (!ns) + ; + else if (name[0] == 'x' + && name[1] == 'm' + && name[2] == 'l' + && name[3] == 'n' + && name[4] == 's' + && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) { + if (name[5] == '\0') + id->prefix = &dtd.defaultPrefix; + else + id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX)); + id->xmlns = 1; + } + else { + int i; + for (i = 0; name[i]; i++) { + if (name[i] == XML_T(':')) { + int j; + for (j = 0; j < i; j++) { + if (!poolAppendChar(&dtd.pool, name[j])) + return 0; + } + if (!poolAppendChar(&dtd.pool, XML_T('\0'))) + return 0; + id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX)); + if (id->prefix->name == poolStart(&dtd.pool)) + poolFinish(&dtd.pool); + else + poolDiscard(&dtd.pool); + break; + } + } + } + } + return id; +} + +#define CONTEXT_SEP XML_T('\f') + +static +const XML_Char *getContext(XML_Parser parser) +{ + HASH_TABLE_ITER iter; + int needSep = 0; + + if (dtd.defaultPrefix.binding) { + int i; + int len; + if (!poolAppendChar(&tempPool, XML_T('='))) + return 0; + len = dtd.defaultPrefix.binding->uriLen; + if (namespaceSeparator != XML_T('\0')) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i])) + return 0; + needSep = 1; + } + + hashTableIterInit(&iter, &(dtd.prefixes)); + for (;;) { + int i; + int len; + const XML_Char *s; + PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); + if (!prefix) + break; + if (!prefix->binding) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return 0; + for (s = prefix->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return 0; + if (!poolAppendChar(&tempPool, XML_T('='))) + return 0; + len = prefix->binding->uriLen; + if (namespaceSeparator != XML_T('\0')) + len--; + for (i = 0; i < len; i++) + if (!poolAppendChar(&tempPool, prefix->binding->uri[i])) + return 0; + needSep = 1; + } + + + hashTableIterInit(&iter, &(dtd.generalEntities)); + for (;;) { + const XML_Char *s; + ENTITY *e = (ENTITY *)hashTableIterNext(&iter); + if (!e) + break; + if (!e->open) + continue; + if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP)) + return 0; + for (s = e->name; *s; s++) + if (!poolAppendChar(&tempPool, *s)) + return 0; + needSep = 1; + } + + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + return tempPool.start; +} + +static +int setContext(XML_Parser parser, const XML_Char *context) +{ + const XML_Char *s = context; + + while (*context != XML_T('\0')) { + if (*s == CONTEXT_SEP || *s == XML_T('\0')) { + ENTITY *e; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0); + if (e) + e->open = 1; + if (*s != XML_T('\0')) + s++; + context = s; + poolDiscard(&tempPool); + } + else if (*s == '=') { + PREFIX *prefix; + if (poolLength(&tempPool) == 0) + prefix = &dtd.defaultPrefix; + else { + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX)); + if (!prefix) + return 0; + if (prefix->name == poolStart(&tempPool)) { + prefix->name = poolCopyString(&dtd.pool, prefix->name); + if (!prefix->name) + return 0; + } + poolDiscard(&tempPool); + } + for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++) + if (!poolAppendChar(&tempPool, *context)) + return 0; + if (!poolAppendChar(&tempPool, XML_T('\0'))) + return 0; + if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings)) + return 0; + poolDiscard(&tempPool); + if (*context != XML_T('\0')) + ++context; + s = context; + } + else { + if (!poolAppendChar(&tempPool, *s)) + return 0; + s++; + } + } + return 1; +} + + +static +void normalizePublicId(XML_Char *publicId) +{ + XML_Char *p = publicId; + XML_Char *s; + for (s = publicId; *s; s++) { + switch (*s) { + case 0x20: + case 0xD: + case 0xA: + if (p != publicId && p[-1] != 0x20) + *p++ = 0x20; + break; + default: + *p++ = *s; + } + } + if (p != publicId && p[-1] == 0x20) + --p; + *p = XML_T('\0'); +} + +static int dtdInit(DTD *p, XML_Parser parser) +{ + XML_Memory_Handling_Suite *ms = &((Parser *) parser)->m_mem; + poolInit(&(p->pool), ms); + hashTableInit(&(p->generalEntities), ms); + hashTableInit(&(p->elementTypes), ms); + hashTableInit(&(p->attributeIds), ms); + hashTableInit(&(p->prefixes), ms); + p->complete = 1; + p->standalone = 0; +#ifdef XML_DTD + hashTableInit(&(p->paramEntities), ms); +#endif /* XML_DTD */ + p->defaultPrefix.name = 0; + p->defaultPrefix.binding = 0; + + p->in_eldecl = 0; + p->scaffIndex = 0; + p->scaffLevel = 0; + p->scaffold = 0; + p->contentStringLen = 0; + p->scaffSize = 0; + p->scaffCount = 0; + + return 1; +} + +#ifdef XML_DTD + +static void dtdSwap(DTD *p1, DTD *p2) +{ + DTD tem; + memcpy(&tem, p1, sizeof(DTD)); + memcpy(p1, p2, sizeof(DTD)); + memcpy(p2, &tem, sizeof(DTD)); +} + +#endif /* XML_DTD */ + +static void dtdDestroy(DTD *p, XML_Parser parser) +{ + HASH_TABLE_ITER iter; + hashTableIterInit(&iter, &(p->elementTypes)); + for (;;) { + ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!e) + break; + if (e->allocDefaultAtts != 0) + FREE(e->defaultAtts); + } + hashTableDestroy(&(p->generalEntities)); +#ifdef XML_DTD + hashTableDestroy(&(p->paramEntities)); +#endif /* XML_DTD */ + hashTableDestroy(&(p->elementTypes)); + hashTableDestroy(&(p->attributeIds)); + hashTableDestroy(&(p->prefixes)); + poolDestroy(&(p->pool)); + if (p->scaffIndex) + FREE(p->scaffIndex); + if (p->scaffold) + FREE(p->scaffold); +} + +/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise. +The new DTD has already been initialized. */ + +static int dtdCopy(DTD *newDtd, const DTD *oldDtd, XML_Parser parser) +{ + HASH_TABLE_ITER iter; + + /* Copy the prefix table. */ + + hashTableIterInit(&iter, &(oldDtd->prefixes)); + for (;;) { + const XML_Char *name; + const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); + if (!oldP) + break; + name = poolCopyString(&(newDtd->pool), oldP->name); + if (!name) + return 0; + if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX))) + return 0; + } + + hashTableIterInit(&iter, &(oldDtd->attributeIds)); + + /* Copy the attribute id table. */ + + for (;;) { + ATTRIBUTE_ID *newA; + const XML_Char *name; + const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); + + if (!oldA) + break; + /* Remember to allocate the scratch byte before the name. */ + if (!poolAppendChar(&(newDtd->pool), XML_T('\0'))) + return 0; + name = poolCopyString(&(newDtd->pool), oldA->name); + if (!name) + return 0; + ++name; + newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); + if (!newA) + return 0; + newA->maybeTokenized = oldA->maybeTokenized; + if (oldA->prefix) { + newA->xmlns = oldA->xmlns; + if (oldA->prefix == &oldDtd->defaultPrefix) + newA->prefix = &newDtd->defaultPrefix; + else + newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0); + } + } + + /* Copy the element type table. */ + + hashTableIterInit(&iter, &(oldDtd->elementTypes)); + + for (;;) { + int i; + ELEMENT_TYPE *newE; + const XML_Char *name; + const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(&(newDtd->pool), oldE->name); + if (!name) + return 0; + newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); + if (!newE) + return 0; + if (oldE->nDefaultAtts) { + newE->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); + if (!newE->defaultAtts) + return 0; + } + if (oldE->idAtt) + newE->idAtt = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0); + newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; + if (oldE->prefix) + newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0); + for (i = 0; i < newE->nDefaultAtts; i++) { + newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); + newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; + if (oldE->defaultAtts[i].value) { + newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); + if (!newE->defaultAtts[i].value) + return 0; + } + else + newE->defaultAtts[i].value = 0; + } + } + + /* Copy the entity tables. */ + if (!copyEntityTable(&(newDtd->generalEntities), + &(newDtd->pool), + &(oldDtd->generalEntities), parser)) + return 0; + +#ifdef XML_DTD + if (!copyEntityTable(&(newDtd->paramEntities), + &(newDtd->pool), + &(oldDtd->paramEntities), parser)) + return 0; +#endif /* XML_DTD */ + + newDtd->complete = oldDtd->complete; + newDtd->standalone = oldDtd->standalone; + + /* Don't want deep copying for scaffolding */ + newDtd->in_eldecl = oldDtd->in_eldecl; + newDtd->scaffold = oldDtd->scaffold; + newDtd->contentStringLen = oldDtd->contentStringLen; + newDtd->scaffSize = oldDtd->scaffSize; + newDtd->scaffLevel = oldDtd->scaffLevel; + newDtd->scaffIndex = oldDtd->scaffIndex; + + return 1; +} /* End dtdCopy */ + +static int copyEntityTable(HASH_TABLE *newTable, + STRING_POOL *newPool, + const HASH_TABLE *oldTable, + XML_Parser parser) +{ + HASH_TABLE_ITER iter; + const XML_Char *cachedOldBase = 0; + const XML_Char *cachedNewBase = 0; + vtkExpatUnused(parser); + + hashTableIterInit(&iter, oldTable); + + for (;;) { + ENTITY *newE; + const XML_Char *name; + const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); + if (!oldE) + break; + name = poolCopyString(newPool, oldE->name); + if (!name) + return 0; + newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY)); + if (!newE) + return 0; + if (oldE->systemId) { + const XML_Char *tem = poolCopyString(newPool, oldE->systemId); + if (!tem) + return 0; + newE->systemId = tem; + if (oldE->base) { + if (oldE->base == cachedOldBase) + newE->base = cachedNewBase; + else { + cachedOldBase = oldE->base; + tem = poolCopyString(newPool, cachedOldBase); + if (!tem) + return 0; + cachedNewBase = newE->base = tem; + } + } + } + else { + const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen); + if (!tem) + return 0; + newE->textPtr = tem; + newE->textLen = oldE->textLen; + } + if (oldE->notation) { + const XML_Char *tem = poolCopyString(newPool, oldE->notation); + if (!tem) + return 0; + newE->notation = tem; + } + } + return 1; +} + +#define INIT_SIZE 64 + +static +int keyeq(KEY s1, KEY s2) +{ + for (; *s1 == *s2; s1++, s2++) + if (*s1 == 0) + return 1; + return 0; +} + +static +unsigned long hash(KEY s) +{ + unsigned long h = 0; + while (*s) + h = (h << 5) + h + (unsigned char)*s++; + return h; +} + +static +NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize) +{ + size_t i; + if (table->size == 0) { + size_t tsize; + + if (!createSize) + return 0; + tsize = INIT_SIZE * sizeof(NAMED *); + table->v = table->mem->malloc_fcn(tsize); + if (!table->v) + return 0; + memset(table->v, 0, tsize); + table->size = INIT_SIZE; + table->usedLim = INIT_SIZE / 2; + i = hash(name) & (table->size - 1); + } + else { + unsigned long h = hash(name); + for (i = h & (table->size - 1); + table->v[i]; + i == 0 ? i = table->size - 1 : --i) { + if (keyeq(name, table->v[i]->name)) + return table->v[i]; + } + if (!createSize) + return 0; + if (table->used == table->usedLim) { + /* check for overflow */ + size_t newSize = table->size * 2; + size_t tsize = newSize * sizeof(NAMED *); + NAMED **newV = table->mem->malloc_fcn(tsize); + if (!newV) + return 0; + memset(newV, 0, tsize); + for (i = 0; i < table->size; i++) + if (table->v[i]) { + size_t j; + for (j = hash(table->v[i]->name) & (newSize - 1); + newV[j]; + j == 0 ? j = newSize - 1 : --j) + ; + newV[j] = table->v[i]; + } + table->mem->free_fcn(table->v); + table->v = newV; + table->size = newSize; + table->usedLim = newSize/2; + for (i = h & (table->size - 1); + table->v[i]; + i == 0 ? i = table->size - 1 : --i) + ; + } + } + table->v[i] = table->mem->malloc_fcn(createSize); + if (!table->v[i]) + return 0; + memset(table->v[i], 0, createSize); + table->v[i]->name = name; + (table->used)++; + return table->v[i]; +} + +static +void hashTableDestroy(HASH_TABLE *table) +{ + size_t i; + for (i = 0; i < table->size; i++) { + NAMED *p = table->v[i]; + if (p) + table->mem->free_fcn(p); + } + if (table->v) + table->mem->free_fcn(table->v); +} + +static +void hashTableInit(HASH_TABLE *p, XML_Memory_Handling_Suite *ms) +{ + p->size = 0; + p->usedLim = 0; + p->used = 0; + p->v = 0; + p->mem = ms; +} + +static +void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) +{ + iter->p = table->v; + iter->end = iter->p + table->size; +} + +static +NAMED *hashTableIterNext(HASH_TABLE_ITER *iter) +{ + while (iter->p != iter->end) { + NAMED *tem = *(iter->p)++; + if (tem) + return tem; + } + return 0; +} + + +static +void poolInit(STRING_POOL *pool, XML_Memory_Handling_Suite *ms) +{ + pool->blocks = 0; + pool->freeBlocks = 0; + pool->start = 0; + pool->ptr = 0; + pool->end = 0; + pool->mem = ms; +} + +static +void poolClear(STRING_POOL *pool) +{ + if (!pool->freeBlocks) + pool->freeBlocks = pool->blocks; + else { + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + p->next = pool->freeBlocks; + pool->freeBlocks = p; + p = tem; + } + } + pool->blocks = 0; + pool->start = 0; + pool->ptr = 0; + pool->end = 0; +} + +static +void poolDestroy(STRING_POOL *pool) +{ + BLOCK *p = pool->blocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } + pool->blocks = 0; + p = pool->freeBlocks; + while (p) { + BLOCK *tem = p->next; + pool->mem->free_fcn(p); + p = tem; + } + pool->freeBlocks = 0; + pool->ptr = 0; + pool->start = 0; + pool->end = 0; +} + +static +XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!pool->ptr && !poolGrow(pool)) + return 0; + for (;;) { + XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end); + if (ptr == end) + break; + if (!poolGrow(pool)) + return 0; + } + return pool->start; +} + +static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s) +{ + do { + if (!poolAppendChar(pool, *s)) + return 0; + } while (*s++); + s = pool->start; + poolFinish(pool); + return s; +} + +static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) +{ + if (!pool->ptr && !poolGrow(pool)) + return 0; + for (; n > 0; --n, s++) { + if (!poolAppendChar(pool, *s)) + return 0; + + } + s = pool->start; + poolFinish(pool); + return s; +} + +static +const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s) +{ + while (*s) { + if (!poolAppendChar(pool, *s)) + return 0; + s++; + } + return pool->start; +} /* End poolAppendString */ + +static +XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, + const char *ptr, const char *end) +{ + if (!poolAppend(pool, enc, ptr, end)) + return 0; + if (pool->ptr == pool->end && !poolGrow(pool)) + return 0; + *(pool->ptr)++ = 0; + return pool->start; +} + +static +int poolGrow(STRING_POOL *pool) +{ + if (pool->freeBlocks) { + if (pool->start == 0) { + pool->blocks = pool->freeBlocks; + pool->freeBlocks = pool->freeBlocks->next; + pool->blocks->next = 0; + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + pool->ptr = pool->start; + return 1; + } + if (pool->end - pool->start < pool->freeBlocks->size) { + BLOCK *tem = pool->freeBlocks->next; + pool->freeBlocks->next = pool->blocks; + pool->blocks = pool->freeBlocks; + pool->freeBlocks = tem; + memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char)); + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + pool->blocks->size; + return 1; + } + } + if (pool->blocks && pool->start == pool->blocks->s) { + int blockSize = (pool->end - pool->start)*2; + pool->blocks = pool->mem->realloc_fcn(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); + if (!pool->blocks) + return 0; + pool->blocks->size = blockSize; + pool->ptr = pool->blocks->s + (pool->ptr - pool->start); + pool->start = pool->blocks->s; + pool->end = pool->start + blockSize; + } + else { + BLOCK *tem; + int blockSize = pool->end - pool->start; + if (blockSize < INIT_BLOCK_SIZE) + blockSize = INIT_BLOCK_SIZE; + else + blockSize *= 2; + tem = pool->mem->malloc_fcn(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char)); + if (!tem) + return 0; + tem->size = blockSize; + tem->next = pool->blocks; + pool->blocks = tem; + if (pool->ptr != pool->start) + memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char)); + pool->ptr = tem->s + (pool->ptr - pool->start); + pool->start = tem->s; + pool->end = tem->s + blockSize; + } + return 1; +} + +static int +nextScaffoldPart(XML_Parser parser) +{ + CONTENT_SCAFFOLD * me; + int next; + + if (! dtd.scaffIndex) { + dtd.scaffIndex = MALLOC(groupSize * sizeof(int)); + if (! dtd.scaffIndex) + return -1; + dtd.scaffIndex[0] = 0; + } + + if (dtd.scaffCount >= dtd.scaffSize) { + if (dtd.scaffold) { + dtd.scaffSize *= 2; + dtd.scaffold = (CONTENT_SCAFFOLD *) REALLOC(dtd.scaffold, + dtd.scaffSize * sizeof(CONTENT_SCAFFOLD)); + } + else { + dtd.scaffSize = 32; + dtd.scaffold = (CONTENT_SCAFFOLD *) MALLOC(dtd.scaffSize * sizeof(CONTENT_SCAFFOLD)); + } + if (! dtd.scaffold) + return -1; + } + next = dtd.scaffCount++; + me = &dtd.scaffold[next]; + if (dtd.scaffLevel) { + CONTENT_SCAFFOLD *parent = &dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]]; + if (parent->lastchild) { + dtd.scaffold[parent->lastchild].nextsib = next; + } + if (! parent->childcnt) + parent->firstchild = next; + parent->lastchild = next; + parent->childcnt++; + } + me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; + return next; +} /* End nextScaffoldPart */ + +static void +build_node (XML_Parser parser, + int src_node, + XML_Content *dest, + XML_Content **contpos, + char **strpos) +{ + dest->type = dtd.scaffold[src_node].type; + dest->quant = dtd.scaffold[src_node].quant; + if (dest->type == XML_CTYPE_NAME) { + const char *src; + dest->name = *strpos; + src = dtd.scaffold[src_node].name; + for (;;) { + *(*strpos)++ = *src; + if (! *src) + break; + src++; + } + dest->numchildren = 0; + dest->children = 0; + } + else { + unsigned int i; + int cn; + dest->numchildren = dtd.scaffold[src_node].childcnt; + dest->children = *contpos; + *contpos += dest->numchildren; + for (i = 0, cn = dtd.scaffold[src_node].firstchild; + i < dest->numchildren; + i++, cn = dtd.scaffold[cn].nextsib) { + build_node(parser, cn, &(dest->children[i]), contpos, strpos); + } + dest->name = 0; + } +} /* End build_node */ + +static XML_Content * +build_model (XML_Parser parser) +{ + XML_Content *ret; + XML_Content *cpos; + char * str; + int allocsize = dtd.scaffCount * sizeof(XML_Content) + dtd.contentStringLen; + + ret = MALLOC(allocsize); + if (! ret) + return 0; + + str = (char *) (&ret[dtd.scaffCount]); + cpos = &ret[1]; + + build_node(parser, 0, ret, &cpos, &str); + return ret; +} /* End build_model */ + +static ELEMENT_TYPE * +getElementType(XML_Parser parser, + const ENCODING *enc, + const char *ptr, + const char *end) +{ + const XML_Char *name = poolStoreString(&dtd.pool, enc, ptr, end); + ELEMENT_TYPE *ret; + + if (! name) + return 0; + ret = (ELEMENT_TYPE *) lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE)); + if (! ret) + return 0; + if (ret->name != name) + poolDiscard(&dtd.pool); + else { + poolFinish(&dtd.pool); + if (!setElementTypePrefix(parser, ret)) + return 0; + } + return ret; +} /* End getElementType */ diff --git a/Utilities/vtkexpat/xmlrole.c b/Utilities/vtkexpat/xmlrole.c new file mode 100644 index 0000000..2481f9a --- /dev/null +++ b/Utilities/vtkexpat/xmlrole.c @@ -0,0 +1,1401 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +static char RCSId[] + = "$Header: /cvsroot/VTK/VTK/Utilities/vtkexpat/xmlrole.c,v 1.1 2004/04/28 15:49:22 king Exp $"; +const char* vtk_expat_GetXMLRole_RCSId() +{ + /* Avoid warning about unused static without removing RCSId from original. */ + return RCSId; +} + +#include + +#include "xmlrole.h" +#include "ascii.h" + +/* Doesn't check: + + that ,| are not mixed in a model group + content of literals + +*/ + +static const char KW_ANY[] = { ASCII_A, ASCII_N, ASCII_Y, '\0' }; +static const char KW_ATTLIST[] = { ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' }; +static const char KW_CDATA[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_DOCTYPE[] = { ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' }; +static const char KW_ELEMENT[] = { ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' }; +static const char KW_EMPTY[] = { ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' }; +static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' }; +static const char KW_ENTITY[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' }; +static const char KW_FIXED[] = { ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' }; +static const char KW_ID[] = { ASCII_I, ASCII_D, '\0' }; +static const char KW_IDREF[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' }; +static const char KW_IDREFS[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' }; +static const char KW_IGNORE[] = { ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' }; +static const char KW_IMPLIED[] = { ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' }; +static const char KW_INCLUDE[] = { ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' }; +static const char KW_NDATA[] = { ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_NMTOKEN[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' }; +static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' }; +static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0' }; +static const char KW_PCDATA[] = { ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' }; +static const char KW_PUBLIC[] = { ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' }; +static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0' }; +static const char KW_SYSTEM[] = { ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' }; + +#ifndef MIN_BYTES_PER_CHAR +#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) +#endif + +#ifdef XML_DTD +#define setTopLevel(state) \ + ((state)->handler = ((state)->documentEntity \ + ? internalSubset \ + : externalSubset1)) +#else /* not XML_DTD */ +#define setTopLevel(state) ((state)->handler = internalSubset) +#endif /* not XML_DTD */ + +typedef int PROLOG_HANDLER(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc); + +static PROLOG_HANDLER + prolog0, prolog1, prolog2, + doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, + internalSubset, + entity0, entity1, entity2, entity3, entity4, entity5, entity6, + entity7, entity8, entity9, + notation0, notation1, notation2, notation3, notation4, + attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, + attlist7, attlist8, attlist9, + element0, element1, element2, element3, element4, element5, element6, + element7, +#ifdef XML_DTD + externalSubset0, externalSubset1, + condSect0, condSect1, condSect2, +#endif /* XML_DTD */ + declClose, + error; + +static +int common(PROLOG_STATE *state, int tok); + +static +int prolog0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + state->handler = prolog1; + return XML_ROLE_NONE; + case XML_TOK_XML_DECL: + state->handler = prolog1; + return XML_ROLE_XML_DECL; + case XML_TOK_PI: + state->handler = prolog1; + return XML_ROLE_NONE; + case XML_TOK_COMMENT: + state->handler = prolog1; + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static +int prolog1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + case XML_TOK_COMMENT: + case XML_TOK_BOM: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (!XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_DOCTYPE)) + break; + state->handler = doctype0; + return XML_ROLE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static +int prolog2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PI: + case XML_TOK_COMMENT: + return XML_ROLE_NONE; + case XML_TOK_INSTANCE_START: + state->handler = error; + return XML_ROLE_INSTANCE_START; + } + return common(state, tok); +} + +static +int doctype0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = doctype1; + return XML_ROLE_DOCTYPE_NAME; + } + return common(state, tok); +} + +static +int doctype1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = doctype3; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = doctype2; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static +int doctype2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype3; + return XML_ROLE_DOCTYPE_PUBLIC_ID; + } + return common(state, tok); +} + +static +int doctype3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = doctype4; + return XML_ROLE_DOCTYPE_SYSTEM_ID; + } + return common(state, tok); +} + +static +int doctype4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = internalSubset; + return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); +} + +static +int doctype5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + state->handler = prolog2; + return XML_ROLE_DOCTYPE_CLOSE; + } + return common(state, tok); +} + +static +int internalSubset(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_OPEN: + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ENTITY)) { + state->handler = entity0; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ATTLIST)) { + state->handler = attlist0; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_ELEMENT)) { + state->handler = element0; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, + ptr + 2 * MIN_BYTES_PER_CHAR(enc), + end, + KW_NOTATION)) { + state->handler = notation0; + return XML_ROLE_NONE; + } + break; + case XML_TOK_PI: + case XML_TOK_COMMENT: + return XML_ROLE_NONE; + case XML_TOK_PARAM_ENTITY_REF: + return XML_ROLE_PARAM_ENTITY_REF; + case XML_TOK_CLOSE_BRACKET: + state->handler = doctype5; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +#ifdef XML_DTD + +static +int externalSubset0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + state->handler = externalSubset1; + if (tok == XML_TOK_XML_DECL) + return XML_ROLE_TEXT_DECL; + return externalSubset1(state, tok, ptr, end, enc); +} + +static +int externalSubset1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_COND_SECT_OPEN: + state->handler = condSect0; + return XML_ROLE_NONE; + case XML_TOK_COND_SECT_CLOSE: + if (state->includeLevel == 0) + break; + state->includeLevel -= 1; + return XML_ROLE_NONE; + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_BRACKET: + break; + case XML_TOK_NONE: + if (state->includeLevel) + break; + return XML_ROLE_NONE; + default: + return internalSubset(state, tok, ptr, end, enc); + } + return common(state, tok); +} + +#endif /* XML_DTD */ + +static +int entity0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_PERCENT: + state->handler = entity1; + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = entity2; + return XML_ROLE_GENERAL_ENTITY_NAME; + } + return common(state, tok); +} + +static +int entity1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = entity7; + return XML_ROLE_PARAM_ENTITY_NAME; + } + return common(state, tok); +} + +static +int entity2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity4; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity3; + return XML_ROLE_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); +} + +static +int entity3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = entity4; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); +} + + +static +int entity4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = entity5; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); +} + +static +int entity5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_ENTITY_COMPLETE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) { + state->handler = entity6; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static +int entity6(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = declClose; + return XML_ROLE_ENTITY_NOTATION_NAME; + } + return common(state, tok); +} + +static +int entity7(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = entity9; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = entity8; + return XML_ROLE_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_ENTITY_VALUE; + } + return common(state, tok); +} + +static +int entity8(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = entity9; + return XML_ROLE_ENTITY_PUBLIC_ID; + } + return common(state, tok); +} + +static +int entity9(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_ENTITY_SYSTEM_ID; + } + return common(state, tok); +} + +static +int notation0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = notation1; + return XML_ROLE_NOTATION_NAME; + } + return common(state, tok); +} + +static +int notation1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { + state->handler = notation3; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { + state->handler = notation2; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static +int notation2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = notation4; + return XML_ROLE_NOTATION_PUBLIC_ID; + } + return common(state, tok); +} + +static +int notation3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_NOTATION_SYSTEM_ID; + } + return common(state, tok); +} + +static +int notation4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = declClose; + return XML_ROLE_NOTATION_SYSTEM_ID; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NOTATION_NO_SYSTEM_ID; + } + return common(state, tok); +} + +static +int attlist0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist1; + return XML_ROLE_ATTLIST_ELEMENT_NAME; + } + return common(state, tok); +} + +static +int attlist1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist2; + return XML_ROLE_ATTRIBUTE_NAME; + } + return common(state, tok); +} + +static +int attlist2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + { + static const char *types[] = { + KW_CDATA, + KW_ID, + KW_IDREF, + KW_IDREFS, + KW_ENTITY, + KW_ENTITIES, + KW_NMTOKEN, + KW_NMTOKENS, + }; + int i; + for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++) + if (XmlNameMatchesAscii(enc, ptr, end, types[i])) { + state->handler = attlist8; + return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; + } + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) { + state->handler = attlist5; + return XML_ROLE_NONE; + } + break; + case XML_TOK_OPEN_PAREN: + state->handler = attlist3; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int attlist3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NMTOKEN: + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = attlist4; + return XML_ROLE_ATTRIBUTE_ENUM_VALUE; + } + return common(state, tok); +} + +static +int attlist4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_NONE; + case XML_TOK_OR: + state->handler = attlist3; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int attlist5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_PAREN: + state->handler = attlist6; + return XML_ROLE_NONE; + } + return common(state, tok); +} + + +static +int attlist6(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + state->handler = attlist7; + return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; + } + return common(state, tok); +} + +static +int attlist7(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = attlist8; + return XML_ROLE_NONE; + case XML_TOK_OR: + state->handler = attlist6; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +/* default value */ +static +int attlist8(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_IMPLIED)) { + state->handler = attlist1; + return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_REQUIRED)) { + state->handler = attlist1; + return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; + } + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_FIXED)) { + state->handler = attlist9; + return XML_ROLE_NONE; + } + break; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; + } + return common(state, tok); +} + +static +int attlist9(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_LITERAL: + state->handler = attlist1; + return XML_ROLE_FIXED_ATTRIBUTE_VALUE; + } + return common(state, tok); +} + +static +int element0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element1; + return XML_ROLE_ELEMENT_NAME; + } + return common(state, tok); +} + +static +int element1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) { + state->handler = declClose; + return XML_ROLE_CONTENT_EMPTY; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) { + state->handler = declClose; + return XML_ROLE_CONTENT_ANY; + } + break; + case XML_TOK_OPEN_PAREN: + state->handler = element2; + state->level = 1; + return XML_ROLE_GROUP_OPEN; + } + return common(state, tok); +} + +static +int element2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_POUND_NAME: + if (XmlNameMatchesAscii(enc, + ptr + MIN_BYTES_PER_CHAR(enc), + end, + KW_PCDATA)) { + state->handler = element3; + return XML_ROLE_CONTENT_PCDATA; + } + break; + case XML_TOK_OPEN_PAREN: + state->level = 2; + state->handler = element6; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); +} + +static +int element3(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int element4(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element5; + return XML_ROLE_CONTENT_ELEMENT; + } + return common(state, tok); +} + +static +int element5(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_OR: + state->handler = element4; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int element6(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_PAREN: + state->level += 1; + return XML_ROLE_GROUP_OPEN; + case XML_TOK_NAME: + case XML_TOK_PREFIXED_NAME: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT; + case XML_TOK_NAME_QUESTION: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_OPT; + case XML_TOK_NAME_ASTERISK: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_REP; + case XML_TOK_NAME_PLUS: + state->handler = element7; + return XML_ROLE_CONTENT_ELEMENT_PLUS; + } + return common(state, tok); +} + +static +int element7(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_CLOSE_PAREN: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE; + case XML_TOK_CLOSE_PAREN_ASTERISK: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_REP; + case XML_TOK_CLOSE_PAREN_QUESTION: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_OPT; + case XML_TOK_CLOSE_PAREN_PLUS: + state->level -= 1; + if (state->level == 0) + state->handler = declClose; + return XML_ROLE_GROUP_CLOSE_PLUS; + case XML_TOK_COMMA: + state->handler = element6; + return XML_ROLE_GROUP_SEQUENCE; + case XML_TOK_OR: + state->handler = element6; + return XML_ROLE_GROUP_CHOICE; + } + return common(state, tok); +} + +#ifdef XML_DTD + +static +int condSect0(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_NAME: + if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) { + state->handler = condSect1; + return XML_ROLE_NONE; + } + if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) { + state->handler = condSect2; + return XML_ROLE_NONE; + } + break; + } + return common(state, tok); +} + +static +int condSect1(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + state->includeLevel += 1; + return XML_ROLE_NONE; + } + return common(state, tok); +} + +static +int condSect2(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_OPEN_BRACKET: + state->handler = externalSubset1; + return XML_ROLE_IGNORE_SECT; + } + return common(state, tok); +} + +#endif /* XML_DTD */ + +static +int declClose(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_PROLOG_S: + return XML_ROLE_NONE; + case XML_TOK_DECL_CLOSE: + setTopLevel(state); + return XML_ROLE_NONE; + } + return common(state, tok); +} + +#if 0 + +static +int ignore(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + switch (tok) { + case XML_TOK_DECL_CLOSE: + state->handler = internalSubset; + return 0; + default: + return XML_ROLE_NONE; + } + return common(state, tok); +} +#endif + +static +int error(PROLOG_STATE *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc) +{ + vtkExpatUnused(state); + vtkExpatUnused(tok); + vtkExpatUnused(ptr); + vtkExpatUnused(end); + vtkExpatUnused(enc); + return XML_ROLE_NONE; +} + +static +int common(PROLOG_STATE *state, int tok) +{ +#ifdef XML_DTD + if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) + return XML_ROLE_INNER_PARAM_ENTITY_REF; +#endif + state->handler = error; + return XML_ROLE_ERROR; +} + +void XmlPrologStateInit(PROLOG_STATE *state) +{ + state->handler = prolog0; +#ifdef XML_DTD + state->documentEntity = 1; + state->includeLevel = 0; +#endif /* XML_DTD */ +} + +#ifdef XML_DTD + +void XmlPrologStateInitExternalEntity(PROLOG_STATE *state) +{ + state->handler = externalSubset0; + state->documentEntity = 0; + state->includeLevel = 0; +} + +#endif /* XML_DTD */ diff --git a/Utilities/vtkexpat/xmlrole.h b/Utilities/vtkexpat/xmlrole.h new file mode 100644 index 0000000..6f25793 --- /dev/null +++ b/Utilities/vtkexpat/xmlrole.h @@ -0,0 +1,100 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +#ifndef XmlRole_INCLUDED +#define XmlRole_INCLUDED 1 + +#include "xmltok.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + XML_ROLE_ERROR = -1, + XML_ROLE_NONE = 0, + XML_ROLE_XML_DECL, + XML_ROLE_INSTANCE_START, + XML_ROLE_DOCTYPE_NAME, + XML_ROLE_DOCTYPE_SYSTEM_ID, + XML_ROLE_DOCTYPE_PUBLIC_ID, + XML_ROLE_DOCTYPE_INTERNAL_SUBSET, + XML_ROLE_DOCTYPE_CLOSE, + XML_ROLE_GENERAL_ENTITY_NAME, + XML_ROLE_PARAM_ENTITY_NAME, + XML_ROLE_ENTITY_VALUE, + XML_ROLE_ENTITY_SYSTEM_ID, + XML_ROLE_ENTITY_PUBLIC_ID, + XML_ROLE_ENTITY_COMPLETE, + XML_ROLE_ENTITY_NOTATION_NAME, + XML_ROLE_NOTATION_NAME, + XML_ROLE_NOTATION_SYSTEM_ID, + XML_ROLE_NOTATION_NO_SYSTEM_ID, + XML_ROLE_NOTATION_PUBLIC_ID, + XML_ROLE_ATTRIBUTE_NAME, + XML_ROLE_ATTRIBUTE_TYPE_CDATA, + XML_ROLE_ATTRIBUTE_TYPE_ID, + XML_ROLE_ATTRIBUTE_TYPE_IDREF, + XML_ROLE_ATTRIBUTE_TYPE_IDREFS, + XML_ROLE_ATTRIBUTE_TYPE_ENTITY, + XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, + XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, + XML_ROLE_ATTRIBUTE_ENUM_VALUE, + XML_ROLE_ATTRIBUTE_NOTATION_VALUE, + XML_ROLE_ATTLIST_ELEMENT_NAME, + XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, + XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, + XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, + XML_ROLE_FIXED_ATTRIBUTE_VALUE, + XML_ROLE_ELEMENT_NAME, + XML_ROLE_CONTENT_ANY, + XML_ROLE_CONTENT_EMPTY, + XML_ROLE_CONTENT_PCDATA, + XML_ROLE_GROUP_OPEN, + XML_ROLE_GROUP_CLOSE, + XML_ROLE_GROUP_CLOSE_REP, + XML_ROLE_GROUP_CLOSE_OPT, + XML_ROLE_GROUP_CLOSE_PLUS, + XML_ROLE_GROUP_CHOICE, + XML_ROLE_GROUP_SEQUENCE, + XML_ROLE_CONTENT_ELEMENT, + XML_ROLE_CONTENT_ELEMENT_REP, + XML_ROLE_CONTENT_ELEMENT_OPT, + XML_ROLE_CONTENT_ELEMENT_PLUS, +#ifdef XML_DTD + XML_ROLE_TEXT_DECL, + XML_ROLE_IGNORE_SECT, + XML_ROLE_INNER_PARAM_ENTITY_REF, +#endif /* XML_DTD */ + XML_ROLE_PARAM_ENTITY_REF +}; + +typedef struct prolog_state { + int (*handler)(struct prolog_state *state, + int tok, + const char *ptr, + const char *end, + const ENCODING *enc); + unsigned level; +#ifdef XML_DTD + unsigned includeLevel; + int documentEntity; +#endif /* XML_DTD */ +} PROLOG_STATE; + +void XmlPrologStateInit(PROLOG_STATE *); +#ifdef XML_DTD +void XmlPrologStateInitExternalEntity(PROLOG_STATE *); +#endif /* XML_DTD */ + +#define XmlTokenRole(state, tok, ptr, end, enc) \ + (((state)->handler)(state, tok, ptr, end, enc)) + +#ifdef __cplusplus +} +#endif + +#endif /* not XmlRole_INCLUDED */ diff --git a/Utilities/vtkexpat/xmltok.c b/Utilities/vtkexpat/xmltok.c new file mode 100644 index 0000000..2873a5c --- /dev/null +++ b/Utilities/vtkexpat/xmltok.c @@ -0,0 +1,1584 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +#include + +#include "xmltok.h" +#include "nametab.h" + +#if defined(__BORLANDC__) +#pragma warn -8008 // Disable "condition is always true" warning. +#pragma warn -8066 // Disable "unreachable code" warning. +#endif + +#ifdef XML_DTD +#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok) +#else +#define IGNORE_SECTION_TOK_VTABLE /* as nothing */ +#endif + +#define VTABLE1 \ + { PREFIX(prologTok), PREFIX(contentTok), \ + PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \ + { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \ + PREFIX(sameName), \ + PREFIX(nameMatchesAscii), \ + PREFIX(nameLength), \ + PREFIX(skipS), \ + PREFIX(getAtts), \ + PREFIX(charRefNumber), \ + PREFIX(predefinedEntityName), \ + PREFIX(updatePosition), \ + PREFIX(isPublicId) + +#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) + +#define UCS2_GET_NAMING(pages, hi, lo) \ + (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F))) + +/* A 2 byte UTF-8 representation splits the characters 11 bits +between the bottom 5 and 6 bits of the bytes. +We need 8 bits to index into pages, 3 bits to add to that index and +5 bits to generate the mask. */ +#define UTF8_GET_NAMING2(pages, byte) \ + (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ + + ((((byte)[0]) & 3) << 1) \ + + ((((byte)[1]) >> 5) & 1)] \ + & (1 << (((byte)[1]) & 0x1F))) + +/* A 3 byte UTF-8 representation splits the characters 16 bits +between the bottom 4, 6 and 6 bits of the bytes. +We need 8 bits to index into pages, 3 bits to add to that index and +5 bits to generate the mask. */ +#define UTF8_GET_NAMING3(pages, byte) \ + (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \ + + ((((byte)[1]) >> 2) & 0xF)] \ + << 3) \ + + ((((byte)[1]) & 3) << 1) \ + + ((((byte)[2]) >> 5) & 1)] \ + & (1 << (((byte)[2]) & 0x1F))) + +#define UTF8_GET_NAMING(pages, p, n) \ + ((n) == 2 \ + ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \ + : ((n) == 3 \ + ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \ + : 0)) + +#define UTF8_INVALID3(p) \ + ((*p) == 0xED \ + ? (((p)[1] & 0x20) != 0) \ + : ((*p) == 0xEF \ + ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \ + : 0)) + +#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0) + +static +int isNever(const ENCODING *enc, const char *p) +{ + vtkExpatUnused(enc); + vtkExpatUnused(p); + return 0; +} + +static +int utf8_isName2(const ENCODING *enc, const char *p) +{ + vtkExpatUnused(enc); + return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); +} + +static +int utf8_isName3(const ENCODING *enc, const char *p) +{ + vtkExpatUnused(enc); + return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); +} + +#define utf8_isName4 isNever + +static +int utf8_isNmstrt2(const ENCODING *enc, const char *p) +{ + vtkExpatUnused(enc); + return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); +} + +static +int utf8_isNmstrt3(const ENCODING *enc, const char *p) +{ + vtkExpatUnused(enc); + return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); +} + +#define utf8_isNmstrt4 isNever + +#define utf8_isInvalid2 isNever + +static +int utf8_isInvalid3(const ENCODING *enc, const char *p) +{ + vtkExpatUnused(enc); + return UTF8_INVALID3((const unsigned char *)p); +} + +static +int utf8_isInvalid4(const ENCODING *enc, const char *p) +{ + vtkExpatUnused(enc); + return UTF8_INVALID4((const unsigned char *)p); +} + +struct normal_encoding { + ENCODING enc; + unsigned char type[256]; +#ifdef XML_MIN_SIZE + int (*byteType)(const ENCODING *, const char *); + int (*isNameMin)(const ENCODING *, const char *); + int (*isNmstrtMin)(const ENCODING *, const char *); + int (*byteToAscii)(const ENCODING *, const char *); + int (*charMatches)(const ENCODING *, const char *, int); +#endif /* XML_MIN_SIZE */ + int (*isName2)(const ENCODING *, const char *); + int (*isName3)(const ENCODING *, const char *); + int (*isName4)(const ENCODING *, const char *); + int (*isNmstrt2)(const ENCODING *, const char *); + int (*isNmstrt3)(const ENCODING *, const char *); + int (*isNmstrt4)(const ENCODING *, const char *); + int (*isInvalid2)(const ENCODING *, const char *); + int (*isInvalid3)(const ENCODING *, const char *); + int (*isInvalid4)(const ENCODING *, const char *); +}; + +#ifdef XML_MIN_SIZE + +#define STANDARD_VTABLE(E) \ + E ## byteType, \ + E ## isNameMin, \ + E ## isNmstrtMin, \ + E ## byteToAscii, \ + E ## charMatches, + +#else + +#define STANDARD_VTABLE(E) /* as nothing */ + +#endif + +#define NORMAL_VTABLE(E) \ + E ## isName2, \ + E ## isName3, \ + E ## isName4, \ + E ## isNmstrt2, \ + E ## isNmstrt3, \ + E ## isNmstrt4, \ + E ## isInvalid2, \ + E ## isInvalid3, \ + E ## isInvalid4 + +#define EMPTY_VTABLE(E) 0, 0, 0, 0, 0, 0, 0, 0, 0 + +static int checkCharRefNumber(int); + +#include "xmltok_impl.h" +#include "ascii.h" + +#ifdef XML_MIN_SIZE +#define sb_isNameMin isNever +#define sb_isNmstrtMin isNever +#endif + +#ifdef XML_MIN_SIZE +#define MINBPC(enc) ((enc)->minBytesPerChar) +#else +/* minimum bytes per character */ +#define MINBPC(enc) 1 +#endif + +#define SB_BYTE_TYPE(enc, p) \ + (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) + +#ifdef XML_MIN_SIZE +static +int sb_byteType(const ENCODING *enc, const char *p) +{ + return SB_BYTE_TYPE(enc, p); +} +#define BYTE_TYPE(enc, p) \ + (((const struct normal_encoding *)(enc))->byteType(enc, p)) +#else +#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) +#endif + +#ifdef XML_MIN_SIZE +#define BYTE_TO_ASCII(enc, p) \ + (((const struct normal_encoding *)(enc))->byteToAscii(enc, p)) +static +int sb_byteToAscii(const ENCODING *enc, const char *p) +{ + return *p; +} +#else +#define BYTE_TO_ASCII(enc, p) (*(p)) +#endif + +#define IS_NAME_CHAR(enc, p, n) \ + (((const struct normal_encoding *)(enc))->isName ## n(enc, p)) +#define IS_NMSTRT_CHAR(enc, p, n) \ + (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p)) +#define IS_INVALID_CHAR(enc, p, n) \ + (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p)) + +#ifdef XML_MIN_SIZE +#define IS_NAME_CHAR_MINBPC(enc, p) \ + (((const struct normal_encoding *)(enc))->isNameMin(enc, p)) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) \ + (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p)) +#else +#define IS_NAME_CHAR_MINBPC(enc, p) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) +#endif + +#ifdef XML_MIN_SIZE +#define CHAR_MATCHES(enc, p, c) \ + (((const struct normal_encoding *)(enc))->charMatches(enc, p, c)) +static +int sb_charMatches(const ENCODING *enc, const char *p, int c) +{ + return *p == c; +} +#else +/* c is an ASCII character */ +#define CHAR_MATCHES(enc, p, c) (*(p) == c) +#endif + +#define PREFIX(ident) normal_ ## ident +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ + UTF8_cval1 = 0x00, + UTF8_cval2 = 0xc0, + UTF8_cval3 = 0xe0, + UTF8_cval4 = 0xf0 +}; + +static +void utf8_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + char *to; + const char *from; + vtkExpatUnused(enc); + if (fromLim - *fromP > toLim - *toP) { + /* Avoid copying partial characters. */ + for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--) + if (((unsigned char)fromLim[-1] & 0xc0) != 0x80) + break; + } + for (to = *toP, from = *fromP; from != fromLim; from++, to++) + *to = *from; + *fromP = from; + *toP = to; +} + +static +void utf8_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + unsigned short *to = *toP; + const char *from = *fromP; + while (from != fromLim && to != toLim) { + switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) { + case BT_LEAD2: + *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f); + from += 2; + break; + case BT_LEAD3: + *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f); + from += 3; + break; + case BT_LEAD4: + { + unsigned long n; + if (to + 1 == toLim) + break; + n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); + n -= 0x10000; + to[0] = (unsigned short)((n >> 10) | 0xD800); + to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); + to += 2; + from += 4; + } + break; + default: + *to++ = *from++; + break; + } + } + *fromP = from; + *toP = to; +} + +#ifdef XML_NS +static const struct normal_encoding utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#include "asciitab.h" +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; +#endif + +static const struct normal_encoding utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +#ifdef XML_NS + +static const struct normal_encoding internal_utf8_encoding_ns = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#include "iasciitab.h" +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +#endif + +static const struct normal_encoding internal_utf8_encoding = { + { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "utf8tab.h" + }, + STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_) +}; + +static +void latin1_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + vtkExpatUnused(enc); + for (;;) { + unsigned char c; + if (*fromP == fromLim) + break; + c = (unsigned char)**fromP; + if (c & 0x80) { + if (toLim - *toP < 2) + break; + *(*toP)++ = ((c >> 6) | UTF8_cval2); + *(*toP)++ = ((c & 0x3f) | 0x80); + (*fromP)++; + } + else { + if (*toP == toLim) + break; + *(*toP)++ = *(*fromP)++; + } + } +} + +static +void latin1_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + vtkExpatUnused(enc); + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = (unsigned char)*(*fromP)++; +} + +#ifdef XML_NS + +static const struct normal_encoding latin1_encoding_ns = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_) +}; + +#endif + +static const struct normal_encoding latin1_encoding = { + { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_) +}; + +static +void ascii_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + vtkExpatUnused(enc); + while (*fromP != fromLim && *toP != toLim) + *(*toP)++ = *(*fromP)++; +} + +#ifdef XML_NS + +static const struct normal_encoding ascii_encoding_ns = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { +#include "asciitab.h" +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_) +}; + +#endif + +static const struct normal_encoding ascii_encoding = { + { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +/* BT_NONXML == 0 */ + }, + STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_) +}; + +static int unicode_byte_type(char hi, char lo) +{ + switch ((unsigned char)hi) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + return BT_LEAD4; + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return BT_TRAIL; + case 0xFF: + switch ((unsigned char)lo) { + case 0xFF: + case 0xFE: + return BT_NONXML; + } + break; + } + return BT_NONASCII; +} + +#define DEFINE_UTF16_TO_UTF8(E) \ +static \ +void E ## toUtf8(const ENCODING *enc, \ + const char **fromP, const char *fromLim, \ + char **toP, const char *toLim) \ +{ \ + const char *from; \ + vtkExpatUnused(enc);\ + for (from = *fromP; from != fromLim; from += 2) { \ + int plane; \ + unsigned char lo2; \ + unsigned char lo = GET_LO(from); \ + unsigned char hi = GET_HI(from); \ + switch (hi) { \ + case 0: \ + if (lo < 0x80) { \ + if (*toP == toLim) { \ + *fromP = from; \ + return; \ + } \ + *(*toP)++ = lo; \ + break; \ + } \ + /* fall through */ \ + case 0x1: case 0x2: case 0x3: \ + case 0x4: case 0x5: case 0x6: case 0x7: \ + if (toLim - *toP < 2) { \ + *fromP = from; \ + return; \ + } \ + *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ + *(*toP)++ = ((lo & 0x3f) | 0x80); \ + break; \ + default: \ + if (toLim - *toP < 3) { \ + *fromP = from; \ + return; \ + } \ + /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ + *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ + *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ + *(*toP)++ = ((lo & 0x3f) | 0x80); \ + break; \ + case 0xD8: case 0xD9: case 0xDA: case 0xDB: \ + if (toLim - *toP < 4) { \ + *fromP = from; \ + return; \ + } \ + plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ + *(*toP)++ = ((plane >> 2) | UTF8_cval4); \ + *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ + from += 2; \ + lo2 = GET_LO(from); \ + *(*toP)++ = (((lo & 0x3) << 4) \ + | ((GET_HI(from) & 0x3) << 2) \ + | (lo2 >> 6) \ + | 0x80); \ + *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ + break; \ + } \ + } \ + *fromP = from; \ +} + +#define DEFINE_UTF16_TO_UTF16(E) \ +static \ +void E ## toUtf16(const ENCODING *enc, \ + const char **fromP, const char *fromLim, \ + unsigned short **toP, const unsigned short *toLim) \ +{ \ + vtkExpatUnused(enc);\ + /* Avoid copying first half only of surrogate */ \ + if (fromLim - *fromP > ((toLim - *toP) << 1) \ + && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \ + fromLim -= 2; \ + for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \ + *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ +} + +#define SET2(ptr, ch) \ + (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8))) +#define GET_LO(ptr) ((unsigned char)(ptr)[0]) +#define GET_HI(ptr) ((unsigned char)(ptr)[1]) + +DEFINE_UTF16_TO_UTF8(little2_) +DEFINE_UTF16_TO_UTF16(little2_) + +#undef SET2 +#undef GET_LO +#undef GET_HI + +#define SET2(ptr, ch) \ + (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF))) +#define GET_LO(ptr) ((unsigned char)(ptr)[1]) +#define GET_HI(ptr) ((unsigned char)(ptr)[0]) + +DEFINE_UTF16_TO_UTF8(big2_) +DEFINE_UTF16_TO_UTF16(big2_) + +#undef SET2 +#undef GET_LO +#undef GET_HI + +#define LITTLE2_BYTE_TYPE(enc, p) \ + ((p)[1] == 0 \ + ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \ + : unicode_byte_type((p)[1], (p)[0])) +#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1) +#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c) +#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) +#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) + +#ifdef XML_MIN_SIZE + +static +int little2_byteType(const ENCODING *enc, const char *p) +{ + return LITTLE2_BYTE_TYPE(enc, p); +} + +static +int little2_byteToAscii(const ENCODING *enc, const char *p) +{ + return LITTLE2_BYTE_TO_ASCII(enc, p); +} + +static +int little2_charMatches(const ENCODING *enc, const char *p, int c) +{ + return LITTLE2_CHAR_MATCHES(enc, p, c); +} + +static +int little2_isNameMin(const ENCODING *enc, const char *p) +{ + return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p); +} + +static +int little2_isNmstrtMin(const ENCODING *enc, const char *p) +{ + return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p); +} + +#undef VTABLE +#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 + +#else /* not XML_MIN_SIZE */ + +#undef PREFIX +#define PREFIX(ident) little2_ ## ident +#define MINBPC(enc) 2 +/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ +#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) +#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) + +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +#endif /* not XML_MIN_SIZE */ + +#ifdef XML_NS + +static const struct normal_encoding little2_encoding_ns = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 12 + 1 +#else + 0 +#endif + }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_) +}; + +#endif + +static const struct normal_encoding little2_encoding = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 12 + 1 +#else + 0 +#endif + }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_) +}; + +#if XML_BYTE_ORDER != 21 + +#ifdef XML_NS + +static const struct normal_encoding internal_little2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { +#include "iasciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_) +}; + +#endif + +static const struct normal_encoding internal_little2_encoding = { + { VTABLE, 2, 0, 1 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_) +}; + +#endif + + +#define BIG2_BYTE_TYPE(enc, p) \ + ((p)[0] == 0 \ + ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \ + : unicode_byte_type((p)[0], (p)[1])) +#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1) +#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c) +#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) +#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \ + UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) + +#ifdef XML_MIN_SIZE + +static +int big2_byteType(const ENCODING *enc, const char *p) +{ + return BIG2_BYTE_TYPE(enc, p); +} + +static +int big2_byteToAscii(const ENCODING *enc, const char *p) +{ + return BIG2_BYTE_TO_ASCII(enc, p); +} + +static +int big2_charMatches(const ENCODING *enc, const char *p, int c) +{ + return BIG2_CHAR_MATCHES(enc, p, c); +} + +static +int big2_isNameMin(const ENCODING *enc, const char *p) +{ + return BIG2_IS_NAME_CHAR_MINBPC(enc, p); +} + +static +int big2_isNmstrtMin(const ENCODING *enc, const char *p) +{ + return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p); +} + +#undef VTABLE +#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 + +#else /* not XML_MIN_SIZE */ + +#undef PREFIX +#define PREFIX(ident) big2_ ## ident +#define MINBPC(enc) 2 +/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ +#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) +#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) +#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c) +#define IS_NAME_CHAR(enc, p, n) 0 +#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p) +#define IS_NMSTRT_CHAR(enc, p, n) (0) +#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) + +#include "xmltok_impl.c" + +#undef MINBPC +#undef BYTE_TYPE +#undef BYTE_TO_ASCII +#undef CHAR_MATCHES +#undef IS_NAME_CHAR +#undef IS_NAME_CHAR_MINBPC +#undef IS_NMSTRT_CHAR +#undef IS_NMSTRT_CHAR_MINBPC +#undef IS_INVALID_CHAR + +#endif /* not XML_MIN_SIZE */ + +#ifdef XML_NS + +static const struct normal_encoding big2_encoding_ns = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 21 + 1 +#else + 0 +#endif + }, + { +#include "asciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_) +}; + +#endif + +static const struct normal_encoding big2_encoding = { + { VTABLE, 2, 0, +#if XML_BYTE_ORDER == 21 + 1 +#else + 0 +#endif + }, + { +#define BT_COLON BT_NMSTRT +#include "asciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_) +}; + +#if XML_BYTE_ORDER != 12 + +#ifdef XML_NS + +static const struct normal_encoding internal_big2_encoding_ns = { + { VTABLE, 2, 0, 1 }, + { +#include "iasciitab.h" +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_) +}; + +#endif + +static const struct normal_encoding internal_big2_encoding = { + { VTABLE, 2, 0, 1 }, + { +#define BT_COLON BT_NMSTRT +#include "iasciitab.h" +#undef BT_COLON +#include "latin1tab.h" + }, + STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_) +}; + +#endif + +#undef PREFIX + +static +int streqci(const char *s1, const char *s2) +{ + for (;;) { + char c1 = *s1++; + char c2 = *s2++; + if (ASCII_a <= c1 && c1 <= ASCII_z) + c1 += ASCII_A - ASCII_a; + if (ASCII_a <= c2 && c2 <= ASCII_z) + c2 += ASCII_A - ASCII_a; + if (c1 != c2) + return 0; + if (!c1) + break; + } + return 1; +} + +static +void initUpdatePosition(const ENCODING *enc, const char *ptr, + const char *end, POSITION *pos) +{ + vtkExpatUnused(enc); + normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); +} + +static +int toAscii(const ENCODING *enc, const char *ptr, const char *end) +{ + char buf[1]; + char *p = buf; + XmlUtf8Convert(enc, &ptr, end, &p, p + 1); + if (p == buf) + return -1; + else + return buf[0]; +} + +static +int isSpace(int c) +{ + switch (c) { + case 0x20: + case 0xD: + case 0xA: + case 0x9: + return 1; + } + return 0; +} + +/* Return 1 if there's just optional white space +or there's an S followed by name=val. */ +static +int parsePseudoAttribute(const ENCODING *enc, + const char *ptr, + const char *end, + const char **namePtr, + const char **nameEndPtr, + const char **valPtr, + const char **nextTokPtr) +{ + int c; + char open; + if (ptr == end) { + *namePtr = 0; + return 1; + } + if (!isSpace(toAscii(enc, ptr, end))) { + *nextTokPtr = ptr; + return 0; + } + do { + ptr += enc->minBytesPerChar; + } while (isSpace(toAscii(enc, ptr, end))); + if (ptr == end) { + *namePtr = 0; + return 1; + } + *namePtr = ptr; + for (;;) { + c = toAscii(enc, ptr, end); + if (c == -1) { + *nextTokPtr = ptr; + return 0; + } + if (c == ASCII_EQUALS) { + *nameEndPtr = ptr; + break; + } + if (isSpace(c)) { + *nameEndPtr = ptr; + do { + ptr += enc->minBytesPerChar; + } while (isSpace(c = toAscii(enc, ptr, end))); + if (c != ASCII_EQUALS) { + *nextTokPtr = ptr; + return 0; + } + break; + } + ptr += enc->minBytesPerChar; + } + if (ptr == *namePtr) { + *nextTokPtr = ptr; + return 0; + } + ptr += enc->minBytesPerChar; + c = toAscii(enc, ptr, end); + while (isSpace(c)) { + ptr += enc->minBytesPerChar; + c = toAscii(enc, ptr, end); + } + if (c != ASCII_QUOT && c != ASCII_APOS) { + *nextTokPtr = ptr; + return 0; + } + open = c; + ptr += enc->minBytesPerChar; + *valPtr = ptr; + for (;; ptr += enc->minBytesPerChar) { + c = toAscii(enc, ptr, end); + if (c == open) + break; + if (!(ASCII_a <= c && c <= ASCII_z) + && !(ASCII_A <= c && c <= ASCII_Z) + && !(ASCII_0 <= c && c <= ASCII_9) + && c != ASCII_PERIOD + && c != ASCII_MINUS + && c != ASCII_UNDERSCORE) { + *nextTokPtr = ptr; + return 0; + } + } + *nextTokPtr = ptr + enc->minBytesPerChar; + return 1; +} + +static const char KW_version[] = { + ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0' +}; + +static const char KW_encoding[] = { + ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0' +}; + +static const char KW_standalone[] = { + ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0' +}; + +static const char KW_yes[] = { + ASCII_y, ASCII_e, ASCII_s, '\0' +}; + +static const char KW_no[] = { + ASCII_n, ASCII_o, '\0' +}; + +static +int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, + const char *, + const char *), + int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingName, + const ENCODING **encoding, + int *standalone) +{ + const char *val = 0; + const char *name = 0; + const char *nameEnd = 0; + ptr += 5 * enc->minBytesPerChar; + end -= 2 * enc->minBytesPerChar; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || !name) { + *badPtr = ptr; + return 0; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) { + if (!isGeneralTextEntity) { + *badPtr = name; + return 0; + } + } + else { + if (versionPtr) + *versionPtr = val; + if (versionEndPtr) + *versionEndPtr = ptr; + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; + } + if (!name) { + if (isGeneralTextEntity) { + /* a TextDecl must have an EncodingDecl */ + *badPtr = ptr; + return 0; + } + return 1; + } + } + if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) { + int c = toAscii(enc, val, end); + if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) { + *badPtr = val; + return 0; + } + if (encodingName) + *encodingName = val; + if (encoding) + *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); + if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { + *badPtr = ptr; + return 0; + } + if (!name) + return 1; + } + if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) { + *badPtr = name; + return 0; + } + if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) { + if (standalone) + *standalone = 1; + } + else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) { + if (standalone) + *standalone = 0; + } + else { + *badPtr = val; + return 0; + } + while (isSpace(toAscii(enc, ptr, end))) + ptr += enc->minBytesPerChar; + if (ptr != end) { + *badPtr = ptr; + return 0; + } + return 1; +} + +static +int checkCharRefNumber(int result) +{ + switch (result >> 8) { + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + return -1; + case 0: + if (latin1_encoding.type[result] == BT_NONXML) + return -1; + break; + case 0xFF: + if (result == 0xFFFE || result == 0xFFFF) + return -1; + break; + } + return result; +} + +int XmlUtf8Encode(int c, char *buf) +{ + enum { + /* minN is minimum legal resulting value for N byte sequence */ + min2 = 0x80, + min3 = 0x800, + min4 = 0x10000 + }; + + if (c < 0) + return 0; + if (c < min2) { + buf[0] = (c | UTF8_cval1); + return 1; + } + if (c < min3) { + buf[0] = ((c >> 6) | UTF8_cval2); + buf[1] = ((c & 0x3f) | 0x80); + return 2; + } + if (c < min4) { + buf[0] = ((c >> 12) | UTF8_cval3); + buf[1] = (((c >> 6) & 0x3f) | 0x80); + buf[2] = ((c & 0x3f) | 0x80); + return 3; + } + if (c < 0x110000) { + buf[0] = ((c >> 18) | UTF8_cval4); + buf[1] = (((c >> 12) & 0x3f) | 0x80); + buf[2] = (((c >> 6) & 0x3f) | 0x80); + buf[3] = ((c & 0x3f) | 0x80); + return 4; + } + return 0; +} + +int XmlUtf16Encode(int charNum, unsigned short *buf) +{ + if (charNum < 0) + return 0; + if (charNum < 0x10000) { + buf[0] = charNum; + return 1; + } + if (charNum < 0x110000) { + charNum -= 0x10000; + buf[0] = (charNum >> 10) + 0xD800; + buf[1] = (charNum & 0x3FF) + 0xDC00; + return 2; + } + return 0; +} + +struct unknown_encoding { + struct normal_encoding normal; + int (*convert)(void *userData, const char *p); + void *userData; + unsigned short utf16[256]; + char utf8[256][4]; +}; + +int XmlSizeOfUnknownEncoding(void) +{ + return sizeof(struct unknown_encoding); +} + +static +int unknown_isName(const ENCODING *enc, const char *p) +{ + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); +} + +static +int unknown_isNmstrt(const ENCODING *enc, const char *p) +{ + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, p); + if (c & ~0xFFFF) + return 0; + return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); +} + +static +int unknown_isInvalid(const ENCODING *enc, const char *p) +{ + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, p); + return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; +} + +static +void unknown_toUtf8(const ENCODING *enc, + const char **fromP, const char *fromLim, + char **toP, const char *toLim) +{ + char buf[XML_UTF8_ENCODE_MAX]; + for (;;) { + const char *utf8; + int n; + if (*fromP == fromLim) + break; + utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP]; + n = *utf8++; + if (n == 0) { + int c = ((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); + n = XmlUtf8Encode(c, buf); + if (n > toLim - *toP) + break; + utf8 = buf; + *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2); + } + else { + if (n > toLim - *toP) + break; + (*fromP)++; + } + do { + *(*toP)++ = *utf8++; + } while (--n != 0); + } +} + +static +void unknown_toUtf16(const ENCODING *enc, + const char **fromP, const char *fromLim, + unsigned short **toP, const unsigned short *toLim) +{ + while (*fromP != fromLim && *toP != toLim) { + unsigned short c + = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP]; + if (c == 0) { + c = (unsigned short)((const struct unknown_encoding *)enc) + ->convert(((const struct unknown_encoding *)enc)->userData, *fromP); + *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP] + - (BT_LEAD2 - 2); + } + else + (*fromP)++; + *(*toP)++ = c; + } +} + +ENCODING * +XmlInitUnknownEncoding(void *mem, + int *table, + int (*convert)(void *userData, const char *p), + void *userData) +{ + int i; + struct unknown_encoding *e = mem; + for (i = 0; i < (int)sizeof(struct normal_encoding); i++) + ((char *)mem)[i] = ((char *)&latin1_encoding)[i]; + for (i = 0; i < 128; i++) + if (latin1_encoding.type[i] != BT_OTHER + && latin1_encoding.type[i] != BT_NONXML + && table[i] != i) + return 0; + for (i = 0; i < 256; i++) { + int c = table[i]; + if (c == -1) { + e->normal.type[i] = BT_MALFORM; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else if (c < 0) { + if (c < -4) + return 0; + e->normal.type[i] = BT_LEAD2 - (c + 2); + e->utf8[i][0] = 0; + e->utf16[i] = 0; + } + else if (c < 0x80) { + if (latin1_encoding.type[c] != BT_OTHER + && latin1_encoding.type[c] != BT_NONXML + && c != i) + return 0; + e->normal.type[i] = latin1_encoding.type[c]; + e->utf8[i][0] = 1; + e->utf8[i][1] = (char)c; + e->utf16[i] = c == 0 ? 0xFFFF : c; + } + else if (checkCharRefNumber(c) < 0) { + e->normal.type[i] = BT_NONXML; + /* This shouldn't really get used. */ + e->utf16[i] = 0xFFFF; + e->utf8[i][0] = 1; + e->utf8[i][1] = 0; + } + else { + if (c > 0xFFFF) + return 0; + if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NMSTRT; + else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) + e->normal.type[i] = BT_NAME; + else + e->normal.type[i] = BT_OTHER; + e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); + e->utf16[i] = c; + } + } + e->userData = userData; + e->convert = convert; + if (convert) { + e->normal.isName2 = unknown_isName; + e->normal.isName3 = unknown_isName; + e->normal.isName4 = unknown_isName; + e->normal.isNmstrt2 = unknown_isNmstrt; + e->normal.isNmstrt3 = unknown_isNmstrt; + e->normal.isNmstrt4 = unknown_isNmstrt; + e->normal.isInvalid2 = unknown_isInvalid; + e->normal.isInvalid3 = unknown_isInvalid; + e->normal.isInvalid4 = unknown_isInvalid; + } + e->normal.enc.utf8Convert = unknown_toUtf8; + e->normal.enc.utf16Convert = unknown_toUtf16; + return &(e->normal.enc); +} + +/* If this enumeration is changed, getEncodingIndex and encodings +must also be changed. */ +enum { + UNKNOWN_ENC = -1, + ISO_8859_1_ENC = 0, + US_ASCII_ENC, + UTF_8_ENC, + UTF_16_ENC, + UTF_16BE_ENC, + UTF_16LE_ENC, + /* must match encodingNames up to here */ + NO_ENC +}; + +static const char KW_ISO_8859_1[] = { + ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0' +}; +static const char KW_US_ASCII[] = { + ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0' +}; +static const char KW_UTF_8[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0' +}; +static const char KW_UTF_16[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0' +}; +static const char KW_UTF_16BE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0' +}; +static const char KW_UTF_16LE[] = { + ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0' +}; + +static +int getEncodingIndex(const char *name) +{ + static const char *encodingNames[] = { + KW_ISO_8859_1, + KW_US_ASCII, + KW_UTF_8, + KW_UTF_16, + KW_UTF_16BE, + KW_UTF_16LE, + }; + int i; + if (name == 0) + return NO_ENC; + for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++) + if (streqci(name, encodingNames[i])) + return i; + return UNKNOWN_ENC; +} + +/* For binary compatibility, we store the index of the encoding specified +at initialization in the isUtf16 member. */ + +#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16) +#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i) + +/* This is what detects the encoding. +encodingTable maps from encoding indices to encodings; +INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; +state is XML_CONTENT_STATE if we're parsing an external text entity, +and XML_PROLOG_STATE otherwise. +*/ + + +static +int initScan(const ENCODING **encodingTable, + const INIT_ENCODING *enc, + int state, + const char *ptr, + const char *end, + const char **nextTokPtr) +{ + const ENCODING **encPtr; + + if (ptr == end) + return XML_TOK_NONE; + encPtr = enc->encPtr; + if (ptr + 1 == end) { + /* only a single byte available for auto-detection */ +#ifndef XML_DTD /* FIXME */ + /* a well-formed document entity must have more than one byte */ + if (state != XML_CONTENT_STATE) + return XML_TOK_PARTIAL; +#endif + /* so we're parsing an external text entity... */ + /* if UTF-16 was externally specified, then we need at least 2 bytes */ + switch (INIT_ENC_INDEX(enc)) { + case UTF_16_ENC: + case UTF_16LE_ENC: + case UTF_16BE_ENC: + return XML_TOK_PARTIAL; + } + switch ((unsigned char)*ptr) { + case 0xFE: + case 0xFF: + case 0xEF: /* possibly first byte of UTF-8 BOM */ + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + /* fall through */ + case 0x00: + case 0x3C: + return XML_TOK_PARTIAL; + } + } + else { + switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { + case 0xFEFF: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XML_TOK_BOM; + /* 00 3C is handled in the default case */ + case 0x3C00: + if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC + || INIT_ENC_INDEX(enc) == UTF_16_ENC) + && state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + case 0xFFFE: + if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC + && state == XML_CONTENT_STATE) + break; + *nextTokPtr = ptr + 2; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XML_TOK_BOM; + case 0xEFBB: + /* Maybe a UTF-8 BOM (EF BB BF) */ + /* If there's an explicitly specified (external) encoding + of ISO-8859-1 or some flavour of UTF-16 + and this is an external text entity, + don't look for the BOM, + because it might be a legal data. */ + if (state == XML_CONTENT_STATE) { + int e = INIT_ENC_INDEX(enc); + if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) + break; + } + if (ptr + 2 == end) + return XML_TOK_PARTIAL; + if ((unsigned char)ptr[2] == 0xBF) { + *nextTokPtr = ptr + 3; + *encPtr = encodingTable[UTF_8_ENC]; + return XML_TOK_BOM; + } + break; + default: + if (ptr[0] == '\0') { + /* 0 isn't a legal data character. Furthermore a document entity can only + start with ASCII characters. So the only way this can fail to be big-endian + UTF-16 if it it's an external parsed general entity that's labelled as + UTF-16LE. */ + if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) + break; + *encPtr = encodingTable[UTF_16BE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + else if (ptr[1] == '\0') { + /* We could recover here in the case: + - parsing an external entity + - second byte is 0 + - no externally specified encoding + - no encoding declaration + by assuming UTF-16LE. But we don't, because this would mean when + presented just with a single byte, we couldn't reliably determine + whether we needed further bytes. */ + if (state == XML_CONTENT_STATE) + break; + *encPtr = encodingTable[UTF_16LE_ENC]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); + } + break; + } + } + *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; + return XmlTok(*encPtr, state, ptr, end, nextTokPtr); +} + + +#define NS(x) x +#define ns(x) x +#include "xmltok_ns.c" +#undef NS +#undef ns + +#ifdef XML_NS + +#define NS(x) x ## NS +#define ns(x) x ## _ns + +#include "xmltok_ns.c" + +#undef NS +#undef ns + +ENCODING * +XmlInitUnknownEncodingNS(void *mem, + int *table, + int (*convert)(void *userData, const char *p), + void *userData) +{ + ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); + if (enc) + ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; + return enc; +} + +#endif /* XML_NS */ diff --git a/Utilities/vtkexpat/xmltok.h b/Utilities/vtkexpat/xmltok.h new file mode 100644 index 0000000..cdf49b2 --- /dev/null +++ b/Utilities/vtkexpat/xmltok.h @@ -0,0 +1,299 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +#ifndef XmlTok_INCLUDED +#define XmlTok_INCLUDED 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* The following token may be returned by XmlContentTok */ +#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of + illegal ]]> sequence */ +/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ +#define XML_TOK_NONE -4 /* The string to be scanned is empty */ +#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan; + might be part of CRLF sequence */ +#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ +#define XML_TOK_PARTIAL -1 /* only part of a token */ +#define XML_TOK_INVALID 0 + +/* The following tokens are returned by XmlContentTok; some are also + returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */ + +#define XML_TOK_START_TAG_WITH_ATTS 1 +#define XML_TOK_START_TAG_NO_ATTS 2 +#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ +#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 +#define XML_TOK_END_TAG 5 +#define XML_TOK_DATA_CHARS 6 +#define XML_TOK_DATA_NEWLINE 7 +#define XML_TOK_CDATA_SECT_OPEN 8 +#define XML_TOK_ENTITY_REF 9 +#define XML_TOK_CHAR_REF 10 /* numeric character reference */ + +/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */ +#define XML_TOK_PI 11 /* processing instruction */ +#define XML_TOK_XML_DECL 12 /* XML decl or text decl */ +#define XML_TOK_COMMENT 13 +#define XML_TOK_BOM 14 /* Byte order mark */ + +/* The following tokens are returned only by XmlPrologTok */ +#define XML_TOK_PROLOG_S 15 +#define XML_TOK_DECL_OPEN 16 /* */ +#define XML_TOK_NAME 18 +#define XML_TOK_NMTOKEN 19 +#define XML_TOK_POUND_NAME 20 /* #name */ +#define XML_TOK_OR 21 /* | */ +#define XML_TOK_PERCENT 22 +#define XML_TOK_OPEN_PAREN 23 +#define XML_TOK_CLOSE_PAREN 24 +#define XML_TOK_OPEN_BRACKET 25 +#define XML_TOK_CLOSE_BRACKET 26 +#define XML_TOK_LITERAL 27 +#define XML_TOK_PARAM_ENTITY_REF 28 +#define XML_TOK_INSTANCE_START 29 + +/* The following occur only in element type declarations */ +#define XML_TOK_NAME_QUESTION 30 /* name? */ +#define XML_TOK_NAME_ASTERISK 31 /* name* */ +#define XML_TOK_NAME_PLUS 32 /* name+ */ +#define XML_TOK_COND_SECT_OPEN 33 /* */ +#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ +#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ +#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ +#define XML_TOK_COMMA 38 + +/* The following token is returned only by XmlAttributeValueTok */ +#define XML_TOK_ATTRIBUTE_VALUE_S 39 + +/* The following token is returned only by XmlCdataSectionTok */ +#define XML_TOK_CDATA_SECT_CLOSE 40 + +/* With namespace processing this is returned by XmlPrologTok + for a name with a colon. */ +#define XML_TOK_PREFIXED_NAME 41 + +#ifdef XML_DTD +#define XML_TOK_IGNORE_SECT 42 +#endif /* XML_DTD */ + +#ifdef XML_DTD +#define XML_N_STATES 4 +#else /* not XML_DTD */ +#define XML_N_STATES 3 +#endif /* not XML_DTD */ + +#define XML_PROLOG_STATE 0 +#define XML_CONTENT_STATE 1 +#define XML_CDATA_SECTION_STATE 2 +#ifdef XML_DTD +#define XML_IGNORE_SECTION_STATE 3 +#endif /* XML_DTD */ + +#define XML_N_LITERAL_TYPES 2 +#define XML_ATTRIBUTE_VALUE_LITERAL 0 +#define XML_ENTITY_VALUE_LITERAL 1 + +/* The size of the buffer passed to XmlUtf8Encode must be at least this. */ +#define XML_UTF8_ENCODE_MAX 4 +/* The size of the buffer passed to XmlUtf16Encode must be at least this. */ +#define XML_UTF16_ENCODE_MAX 2 + +typedef struct position { + /* first line and first column are 0 not 1 */ + unsigned long lineNumber; + unsigned long columnNumber; +} POSITION; + +typedef struct { + const char *name; + const char *valuePtr; + const char *valueEnd; + char normalized; +} ATTRIBUTE; + +struct encoding; +typedef struct encoding ENCODING; + +struct encoding { + int (*scanners[XML_N_STATES])(const ENCODING *, + const char *, + const char *, + const char **); + int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *, + const char *, + const char *, + const char **); + int (*sameName)(const ENCODING *, + const char *, const char *); + int (*nameMatchesAscii)(const ENCODING *, + const char *, const char *, const char *); + int (*nameLength)(const ENCODING *, const char *); + const char *(*skipS)(const ENCODING *, const char *); + int (*getAtts)(const ENCODING *enc, const char *ptr, + int attsMax, ATTRIBUTE *atts); + int (*charRefNumber)(const ENCODING *enc, const char *ptr); + int (*predefinedEntityName)(const ENCODING *, const char *, const char *); + void (*updatePosition)(const ENCODING *, + const char *ptr, + const char *end, + POSITION *); + int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end, + const char **badPtr); + void (*utf8Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + char **toP, + const char *toLim); + void (*utf16Convert)(const ENCODING *enc, + const char **fromP, + const char *fromLim, + unsigned short **toP, + const unsigned short *toLim); + int minBytesPerChar; + char isUtf8; + char isUtf16; +}; + +/* +Scan the string starting at ptr until the end of the next complete token, +but do not scan past eptr. Return an integer giving the type of token. + +Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. + +Return XML_TOK_PARTIAL when the string does not contain a complete token; +nextTokPtr will not be set. + +Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr +will be set to point to the character which made the token invalid. + +Otherwise the string starts with a valid token; nextTokPtr will be set to point +to the character following the end of that token. + +Each data character counts as a single token, but adjacent data characters +may be returned together. Similarly for characters in the prolog outside +literals, comments and processing instructions. +*/ + + +#define XmlTok(enc, state, ptr, end, nextTokPtr) \ + (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) + +#define XmlPrologTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) + +#define XmlContentTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) + +#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) + +#ifdef XML_DTD + +#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ + XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) + +#endif /* XML_DTD */ + +/* This is used for performing a 2nd-level tokenization on +the content of a literal that has already been returned by XmlTok. */ + +#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ + (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) + +#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) + +#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ + XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) + +#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) + +#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ + (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) + +#define XmlNameLength(enc, ptr) \ + (((enc)->nameLength)(enc, ptr)) + +#define XmlSkipS(enc, ptr) \ + (((enc)->skipS)(enc, ptr)) + +#define XmlGetAttributes(enc, ptr, attsMax, atts) \ + (((enc)->getAtts)(enc, ptr, attsMax, atts)) + +#define XmlCharRefNumber(enc, ptr) \ + (((enc)->charRefNumber)(enc, ptr)) + +#define XmlPredefinedEntityName(enc, ptr, end) \ + (((enc)->predefinedEntityName)(enc, ptr, end)) + +#define XmlUpdatePosition(enc, ptr, end, pos) \ + (((enc)->updatePosition)(enc, ptr, end, pos)) + +#define XmlIsPublicId(enc, ptr, end, badPtr) \ + (((enc)->isPublicId)(enc, ptr, end, badPtr)) + +#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) + +#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ + (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) + +typedef struct { + ENCODING initEnc; + const ENCODING **encPtr; +} INIT_ENCODING; + +int XmlParseXmlDecl(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingNamePtr, + const ENCODING **namedEncodingPtr, + int *standalonePtr); + +int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); +const ENCODING *XmlGetUtf8InternalEncoding(void); +const ENCODING *XmlGetUtf16InternalEncoding(void); +int XmlUtf8Encode(int charNumber, char *buf); +int XmlUtf16Encode(int charNumber, unsigned short *buf); + +int XmlSizeOfUnknownEncoding(void); +ENCODING * +XmlInitUnknownEncoding(void *mem, + int *table, + int (*conv)(void *userData, const char *p), + void *userData); + +int XmlParseXmlDeclNS(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingNamePtr, + const ENCODING **namedEncodingPtr, + int *standalonePtr); +int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); +const ENCODING *XmlGetUtf8InternalEncodingNS(void); +const ENCODING *XmlGetUtf16InternalEncodingNS(void); +ENCODING * +XmlInitUnknownEncodingNS(void *mem, + int *table, + int (*conv)(void *userData, const char *p), + void *userData); +#ifdef __cplusplus +} +#endif + +#endif /* not XmlTok_INCLUDED */ diff --git a/Utilities/vtkexpat/xmltok_impl.c b/Utilities/vtkexpat/xmltok_impl.c new file mode 100644 index 0000000..a3be923 --- /dev/null +++ b/Utilities/vtkexpat/xmltok_impl.c @@ -0,0 +1,1773 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +#ifndef IS_INVALID_CHAR +#define IS_INVALID_CHAR(enc, ptr, n) (0) +#endif + +#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (IS_INVALID_CHAR(enc, ptr, n)) { \ + *(nextTokPtr) = (ptr); \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define INVALID_CASES(ptr, nextTokPtr) \ + INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ + INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ + INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ + case BT_NONXML: \ + case BT_MALFORM: \ + case BT_TRAIL: \ + *(nextTokPtr) = (ptr); \ + return XML_TOK_INVALID; + +#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (!IS_NAME_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ + case BT_NONASCII: \ + if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + case BT_NMSTRT: \ + case BT_HEX: \ + case BT_DIGIT: \ + case BT_NAME: \ + case BT_MINUS: \ + ptr += MINBPC(enc); \ + break; \ + CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ + CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ + CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) + +#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + ptr += n; \ + break; + +#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ + case BT_NONASCII: \ + if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; \ + } \ + case BT_NMSTRT: \ + case BT_HEX: \ + ptr += MINBPC(enc); \ + break; \ + CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ + CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ + CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) + +#ifndef PREFIX +#define PREFIX(ident) ident +#endif + +/* ptr points to character following " */ + switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { + case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + /* fall through */ + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DECL_OPEN; + case BT_NMSTRT: + case BT_HEX: + ptr += MINBPC(enc); + break; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return XML_TOK_PARTIAL; +} + +static +int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) +{ + int upper = 0; + vtkExpatUnused(enc); + *tokPtr = XML_TOK_PI; + if (end - ptr != MINBPC(enc)*3) + return 1; + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_x: + break; + case ASCII_X: + upper = 1; + break; + default: + return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_m: + break; + case ASCII_M: + upper = 1; + break; + default: + return 1; + } + ptr += MINBPC(enc); + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + break; + case ASCII_L: + upper = 1; + break; + default: + return 1; + } + if (upper) + return 0; + *tokPtr = XML_TOK_XML_DECL; + return 1; +} + +/* ptr points to character following " 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CDATA_SECT_CLOSE; + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_DATA_CHARS; \ + } \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + case BT_RSQB: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +/* ptr points to character following " 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_LT: + return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_AMP: + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_CR: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + case BT_LF: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB)) + break; + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_RSQB; + if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr -= MINBPC(enc); + break; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + INVALID_CASES(ptr, nextTokPtr) + default: + ptr += MINBPC(enc); + break; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ + *nextTokPtr = ptr; \ + return XML_TOK_DATA_CHARS; \ + } \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_RSQB: + if (ptr + MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { + ptr += MINBPC(enc); + break; + } + if (ptr + 2*MINBPC(enc) != end) { + if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) { + ptr += MINBPC(enc); + break; + } + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_INVALID; + } + } + /* fall through */ + case BT_AMP: + case BT_LT: + case BT_NONXML: + case BT_MALFORM: + case BT_TRAIL: + case BT_CR: + case BT_LF: + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +/* ptr points to character following "%" */ + +static +int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: + *nextTokPtr = ptr; + return XML_TOK_PERCENT; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_SEMI: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_PARAM_ENTITY_REF; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return XML_TOK_PARTIAL; +} + +static +int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_CR: case BT_LF: case BT_S: + case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: + *nextTokPtr = ptr; + return XML_TOK_POUND_NAME; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return -XML_TOK_POUND_NAME; +} + +static +int PREFIX(scanLit)(int open, const ENCODING *enc, + const char *ptr, const char *end, + const char **nextTokPtr) +{ + while (ptr != end) { + int t = BYTE_TYPE(enc, ptr); + switch (t) { + INVALID_CASES(ptr, nextTokPtr) + case BT_QUOT: + case BT_APOS: + ptr += MINBPC(enc); + if (t != open) + break; + if (ptr == end) + return -XML_TOK_LITERAL; + *nextTokPtr = ptr; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_CR: case BT_LF: + case BT_GT: case BT_PERCNT: case BT_LSQB: + return XML_TOK_LITERAL; + default: + return XML_TOK_INVALID; + } + default: + ptr += MINBPC(enc); + break; + } + } + return XML_TOK_PARTIAL; +} + +static +int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + int tok; + if (ptr == end) + return XML_TOK_NONE; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + if (n == 0) + return XML_TOK_PARTIAL; + end = ptr + n; + } + } + switch (BYTE_TYPE(enc, ptr)) { + case BT_QUOT: + return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_APOS: + return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_LT: + { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_PARTIAL; + switch (BYTE_TYPE(enc, ptr)) { + case BT_EXCL: + return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_QUEST: + return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_NMSTRT: + case BT_HEX: + case BT_NONASCII: + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + *nextTokPtr = ptr - MINBPC(enc); + return XML_TOK_INSTANCE_START; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + case BT_CR: + if (ptr + MINBPC(enc) == end) + return -XML_TOK_PROLOG_S; + /* fall through */ + case BT_S: case BT_LF: + for (;;) { + ptr += MINBPC(enc); + if (ptr == end) + break; + switch (BYTE_TYPE(enc, ptr)) { + case BT_S: case BT_LF: + break; + case BT_CR: + /* don't split CR/LF pair */ + if (ptr + MINBPC(enc) != end) + break; + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_PROLOG_S; + } + } + *nextTokPtr = ptr; + return XML_TOK_PROLOG_S; + case BT_PERCNT: + return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); + case BT_COMMA: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_COMMA; + case BT_LSQB: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_BRACKET; + case BT_RSQB: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_BRACKET; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if (ptr + MINBPC(enc) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) { + *nextTokPtr = ptr + 2*MINBPC(enc); + return XML_TOK_COND_SECT_CLOSE; + } + } + *nextTokPtr = ptr; + return XML_TOK_CLOSE_BRACKET; + case BT_LPAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OPEN_PAREN; + case BT_RPAR: + ptr += MINBPC(enc); + if (ptr == end) + return -XML_TOK_CLOSE_PAREN; + switch (BYTE_TYPE(enc, ptr)) { + case BT_AST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_ASTERISK; + case BT_QUEST: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_QUESTION; + case BT_PLUS: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_CLOSE_PAREN_PLUS; + case BT_CR: case BT_LF: case BT_S: + case BT_GT: case BT_COMMA: case BT_VERBAR: + case BT_RPAR: + *nextTokPtr = ptr; + return XML_TOK_CLOSE_PAREN; + } + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_VERBAR: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_OR; + case BT_GT: + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DECL_CLOSE; + case BT_NUM: + return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (end - ptr < n) \ + return XML_TOK_PARTIAL_CHAR; \ + if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NAME; \ + break; \ + } \ + if (IS_NAME_CHAR(enc, ptr, n)) { \ + ptr += n; \ + tok = XML_TOK_NMTOKEN; \ + break; \ + } \ + *nextTokPtr = ptr; \ + return XML_TOK_INVALID; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NMSTRT: + case BT_HEX: + tok = XML_TOK_NAME; + ptr += MINBPC(enc); + break; + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: +#ifdef XML_NS + case BT_COLON: +#endif + tok = XML_TOK_NMTOKEN; + ptr += MINBPC(enc); + break; + case BT_NONASCII: + if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NAME; + break; + } + if (IS_NAME_CHAR_MINBPC(enc, ptr)) { + ptr += MINBPC(enc); + tok = XML_TOK_NMTOKEN; + break; + } + /* fall through */ + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + case BT_GT: case BT_RPAR: case BT_COMMA: + case BT_VERBAR: case BT_LSQB: case BT_PERCNT: + case BT_S: case BT_CR: case BT_LF: + *nextTokPtr = ptr; + return tok; +#ifdef XML_NS + case BT_COLON: + ptr += MINBPC(enc); + switch (tok) { + case XML_TOK_NAME: + if (ptr == end) + return XML_TOK_PARTIAL; + tok = XML_TOK_PREFIXED_NAME; + switch (BYTE_TYPE(enc, ptr)) { + CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) + default: + tok = XML_TOK_NMTOKEN; + break; + } + break; + case XML_TOK_PREFIXED_NAME: + tok = XML_TOK_NMTOKEN; + break; + } + break; +#endif + case BT_PLUS: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_PLUS; + case BT_AST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_ASTERISK; + case BT_QUEST: + if (tok == XML_TOK_NMTOKEN) { + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_NAME_QUESTION; + default: + *nextTokPtr = ptr; + return XML_TOK_INVALID; + } + } + return -tok; +} + +static +int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LT: + /* this is for inside entity references */ + *nextTokPtr = ptr; + return XML_TOK_INVALID; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_S: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_ATTRIBUTE_VALUE_S; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +static +int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + const char *start; + if (ptr == end) + return XML_TOK_NONE; + start = ptr; + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_AMP: + if (ptr == start) + return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_PERCNT: + if (ptr == start) { + int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc), + end, nextTokPtr); + return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_LF: + if (ptr == start) { + *nextTokPtr = ptr + MINBPC(enc); + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + case BT_CR: + if (ptr == start) { + ptr += MINBPC(enc); + if (ptr == end) + return XML_TOK_TRAILING_CR; + if (BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + *nextTokPtr = ptr; + return XML_TOK_DATA_NEWLINE; + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; + default: + ptr += MINBPC(enc); + break; + } + } + *nextTokPtr = ptr; + return XML_TOK_DATA_CHARS; +} + +#ifdef XML_DTD + +static +int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + int level = 0; + if (MINBPC(enc) > 1) { + size_t n = end - ptr; + if (n & (MINBPC(enc) - 1)) { + n &= ~(MINBPC(enc) - 1); + end = ptr + n; + } + } + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { + INVALID_CASES(ptr, nextTokPtr) + case BT_LT: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) { + ++level; + ptr += MINBPC(enc); + } + } + break; + case BT_RSQB: + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { + if ((ptr += MINBPC(enc)) == end) + return XML_TOK_PARTIAL; + if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { + ptr += MINBPC(enc); + if (level == 0) { + *nextTokPtr = ptr; + return XML_TOK_IGNORE_SECT; + } + --level; + } + } + break; + default: + ptr += MINBPC(enc); + break; + } + } + return XML_TOK_PARTIAL; +} + +#endif /* XML_DTD */ + +static +int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, + const char **badPtr) +{ + ptr += MINBPC(enc); + end -= MINBPC(enc); + for (; ptr != end; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_DIGIT: + case BT_HEX: + case BT_MINUS: + case BT_APOS: + case BT_LPAR: + case BT_RPAR: + case BT_PLUS: + case BT_COMMA: + case BT_SOL: + case BT_EQUALS: + case BT_QUEST: + case BT_CR: + case BT_LF: + case BT_SEMI: + case BT_EXCL: + case BT_AST: + case BT_PERCNT: + case BT_NUM: +#ifdef XML_NS + case BT_COLON: +#endif + break; + case BT_S: + if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) { + *badPtr = ptr; + return 0; + } + break; + case BT_NAME: + case BT_NMSTRT: + if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f)) + break; + default: + switch (BYTE_TO_ASCII(enc, ptr)) { + case 0x24: /* $ */ + case 0x40: /* @ */ + break; + default: + *badPtr = ptr; + return 0; + } + break; + } + } + return 1; +} + +/* This must only be called for a well-formed start-tag or empty element tag. +Returns the number of attributes. Pointers to the first attsMax attributes +are stored in atts. */ + +static +int PREFIX(getAtts)(const ENCODING *enc, const char *ptr, + int attsMax, ATTRIBUTE *atts) +{ + enum { other, inName, inValue } state = inName; + int nAtts = 0; + int open = 0; /* defined when state == inValue; + initialization just to shut up compilers */ + + for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { + switch (BYTE_TYPE(enc, ptr)) { +#define START_NAME \ + if (state == other) { \ + if (nAtts < attsMax) { \ + atts[nAtts].name = ptr; \ + atts[nAtts].normalized = 1; \ + } \ + state = inName; \ + } +#define LEAD_CASE(n) \ + case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONASCII: + case BT_NMSTRT: + case BT_HEX: + START_NAME + break; +#undef START_NAME + case BT_QUOT: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_QUOT; + } + else if (open == BT_QUOT) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_APOS: + if (state != inValue) { + if (nAtts < attsMax) + atts[nAtts].valuePtr = ptr + MINBPC(enc); + state = inValue; + open = BT_APOS; + } + else if (open == BT_APOS) { + state = other; + if (nAtts < attsMax) + atts[nAtts].valueEnd = ptr; + nAtts++; + } + break; + case BT_AMP: + if (nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_S: + if (state == inName) + state = other; + else if (state == inValue + && nAtts < attsMax + && atts[nAtts].normalized + && (ptr == atts[nAtts].valuePtr + || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE + || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE + || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) + atts[nAtts].normalized = 0; + break; + case BT_CR: case BT_LF: + /* This case ensures that the first attribute name is counted + Apart from that we could just change state on the quote. */ + if (state == inName) + state = other; + else if (state == inValue && nAtts < attsMax) + atts[nAtts].normalized = 0; + break; + case BT_GT: + case BT_SOL: + if (state != inValue) + return nAtts; + break; + default: + break; + } + } + /* not reached */ +} + +static +int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) +{ + int result = 0; + vtkExpatUnused(enc); + /* skip &# */ + ptr += 2*MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_x)) { + for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + switch (c) { + case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4: + case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9: + result <<= 4; + result |= (c - ASCII_0); + break; + case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F: + result <<= 4; + result += 10 + (c - ASCII_A); + break; + case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f: + result <<= 4; + result += 10 + (c - ASCII_a); + break; + } + if (result >= 0x110000) + return -1; + } + } + else { + for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { + int c = BYTE_TO_ASCII(enc, ptr); + result *= 10; + result += (c - ASCII_0); + if (result >= 0x110000) + return -1; + } + } + return checkCharRefNumber(result); +} + +static +int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) +{ + vtkExpatUnused(enc); + switch ((end - ptr)/MINBPC(enc)) { + case 2: + if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) { + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_l: + return ASCII_LT; + case ASCII_g: + return ASCII_GT; + } + } + break; + case 3: + if (CHAR_MATCHES(enc, ptr, ASCII_a)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_m)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) + return ASCII_AMP; + } + } + break; + case 4: + switch (BYTE_TO_ASCII(enc, ptr)) { + case ASCII_q: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_u)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_t)) + return ASCII_QUOT; + } + } + break; + case ASCII_a: + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_p)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_o)) { + ptr += MINBPC(enc); + if (CHAR_MATCHES(enc, ptr, ASCII_s)) + return ASCII_APOS; + } + } + break; + } + } + return 0; +} + +static +int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2) +{ + for (;;) { + switch (BYTE_TYPE(enc, ptr1)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + if (*ptr1++ != *ptr2++) \ + return 0; + LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2) +#undef LEAD_CASE + /* fall through */ + if (*ptr1++ != *ptr2++) + return 0; + break; + case BT_NONASCII: + case BT_NMSTRT: +#ifdef XML_NS + case BT_COLON: +#endif + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 1) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 2) { + if (*ptr2++ != *ptr1++) + return 0; + if (MINBPC(enc) > 3) { + if (*ptr2++ != *ptr1++) + return 0; + } + } + } + break; + default: + if (MINBPC(enc) == 1 && *ptr1 == *ptr2) + return 1; + switch (BYTE_TYPE(enc, ptr2)) { + case BT_LEAD2: + case BT_LEAD3: + case BT_LEAD4: + case BT_NONASCII: + case BT_NMSTRT: +#ifdef XML_NS + case BT_COLON: +#endif + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + return 0; + default: + return 1; + } + } + } + /* not reached */ +} + +static +int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, + const char *end1, const char *ptr2) +{ + vtkExpatUnused(enc); + for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { + if (ptr1 == end1) + return 0; + if (!CHAR_MATCHES(enc, ptr1, *ptr2)) + return 0; + } + return ptr1 == end1; +} + +static +int PREFIX(nameLength)(const ENCODING *enc, const char *ptr) +{ + const char *start = ptr; + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: ptr += n; break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_NONASCII: + case BT_NMSTRT: +#ifdef XML_NS + case BT_COLON: +#endif + case BT_HEX: + case BT_DIGIT: + case BT_NAME: + case BT_MINUS: + ptr += MINBPC(enc); + break; + default: + return ptr - start; + } + } +} + +static +const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr) +{ + for (;;) { + switch (BYTE_TYPE(enc, ptr)) { + case BT_LF: + case BT_CR: + case BT_S: + ptr += MINBPC(enc); + break; + default: + return ptr; + } + } +} + +static +void PREFIX(updatePosition)(const ENCODING *enc, + const char *ptr, + const char *end, + POSITION *pos) +{ + while (ptr != end) { + switch (BYTE_TYPE(enc, ptr)) { +#define LEAD_CASE(n) \ + case BT_LEAD ## n: \ + ptr += n; \ + break; + LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) +#undef LEAD_CASE + case BT_LF: + pos->columnNumber = (unsigned)-1; + pos->lineNumber++; + ptr += MINBPC(enc); + break; + case BT_CR: + pos->lineNumber++; + ptr += MINBPC(enc); + if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF) + ptr += MINBPC(enc); + pos->columnNumber = (unsigned)-1; + break; + default: + ptr += MINBPC(enc); + break; + } + pos->columnNumber++; + } +} + +#undef DO_LEAD_CASE +#undef MULTIBYTE_CASES +#undef INVALID_CASES +#undef CHECK_NAME_CASE +#undef CHECK_NAME_CASES +#undef CHECK_NMSTRT_CASE +#undef CHECK_NMSTRT_CASES diff --git a/Utilities/vtkexpat/xmltok_impl.h b/Utilities/vtkexpat/xmltok_impl.h new file mode 100644 index 0000000..da0ea60 --- /dev/null +++ b/Utilities/vtkexpat/xmltok_impl.h @@ -0,0 +1,46 @@ +/* +Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd +See the file COPYING for copying permission. +*/ + +enum { + BT_NONXML, + BT_MALFORM, + BT_LT, + BT_AMP, + BT_RSQB, + BT_LEAD2, + BT_LEAD3, + BT_LEAD4, + BT_TRAIL, + BT_CR, + BT_LF, + BT_GT, + BT_QUOT, + BT_APOS, + BT_EQUALS, + BT_QUEST, + BT_EXCL, + BT_SOL, + BT_SEMI, + BT_NUM, + BT_LSQB, + BT_S, + BT_NMSTRT, + BT_COLON, + BT_HEX, + BT_DIGIT, + BT_NAME, + BT_MINUS, + BT_OTHER, /* known not to be a name or name start character */ + BT_NONASCII, /* might be a name or name start character */ + BT_PERCNT, + BT_LPAR, + BT_RPAR, + BT_AST, + BT_PLUS, + BT_COMMA, + BT_VERBAR +}; + +#include diff --git a/Utilities/vtkexpat/xmltok_ns.c b/Utilities/vtkexpat/xmltok_ns.c new file mode 100644 index 0000000..fa78adf --- /dev/null +++ b/Utilities/vtkexpat/xmltok_ns.c @@ -0,0 +1,98 @@ +const ENCODING *NS(XmlGetUtf8InternalEncoding)(void) +{ + return &ns(internal_utf8_encoding).enc; +} + +const ENCODING *NS(XmlGetUtf16InternalEncoding)(void) +{ +#if XML_BYTE_ORDER == 12 + return &ns(internal_little2_encoding).enc; +#elif XML_BYTE_ORDER == 21 + return &ns(internal_big2_encoding).enc; +#else + const short n = 1; + return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc; +#endif +} + +static +const ENCODING *NS(encodings)[] = { + &ns(latin1_encoding).enc, + &ns(ascii_encoding).enc, + &ns(utf8_encoding).enc, + &ns(big2_encoding).enc, + &ns(big2_encoding).enc, + &ns(little2_encoding).enc, + &ns(utf8_encoding).enc /* NO_ENC */ +}; + +static +int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); +} + +static +int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, + const char **nextTokPtr) +{ + return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); +} + +int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) +{ + int i = getEncodingIndex(name); + if (i == UNKNOWN_ENC) + return 0; + SET_INIT_ENC_INDEX(p, i); + p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); + p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); + p->initEnc.updatePosition = initUpdatePosition; + p->encPtr = encPtr; + *encPtr = &(p->initEnc); + return 1; +} + +static +const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) +{ +#define ENCODING_MAX 128 + char buf[ENCODING_MAX]; + char *p = buf; + int i; + XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); + if (ptr != end) + return 0; + *p = 0; + if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) + return enc; + i = getEncodingIndex(buf); + if (i == UNKNOWN_ENC) + return 0; + return NS(encodings)[i]; +} + +int NS(XmlParseXmlDecl)(int isGeneralTextEntity, + const ENCODING *enc, + const char *ptr, + const char *end, + const char **badPtr, + const char **versionPtr, + const char **versionEndPtr, + const char **encodingName, + const ENCODING **encoding, + int *standalone) +{ + return doParseXmlDecl(NS(findEncoding), + isGeneralTextEntity, + enc, + ptr, + end, + badPtr, + versionPtr, + versionEndPtr, + encodingName, + encoding, + standalone); +} diff --git a/Utilities/vtkfreetype/.NoDartCoverage b/Utilities/vtkfreetype/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/vtkfreetype/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/vtkfreetype/CMakeLists.txt b/Utilities/vtkfreetype/CMakeLists.txt new file mode 100644 index 0000000..6464950 --- /dev/null +++ b/Utilities/vtkfreetype/CMakeLists.txt @@ -0,0 +1,131 @@ +PROJECT (VTKFREETYPE) + +# +# Dependency mask +# +INCLUDE_REGULAR_EXPRESSION (".*") + +# +# Include paths +# +INCLUDE_DIRECTORIES ( + ${VTKFREETYPE_SOURCE_DIR}/include + ${VTKFREETYPE_SOURCE_DIR}/src + ${VTKFREETYPE_BINARY_DIR} + ${VTKFREETYPE_BINARY_DIR}/include +) + +# +# Source files +# +SET (FREETYPE_SRCS + src/autohint/autohint.c + src/base/ftbase.c + src/base/ftbbox.c + src/base/ftglyph.c + src/base/ftinit.c + src/base/ftmm.c + src/bdf/bdf.c + src/cache/ftcache.c + src/cff/cff.c + src/cid/type1cid.c + src/gzip/ftgzip.c + src/lzw/ftlzw.c + src/pcf/pcf.c + src/pfr/pfr.c + src/psaux/psaux.c + src/pshinter/pshinter.c + src/psnames/psmodule.c + src/raster/raster.c + src/sfnt/sfnt.c + src/smooth/smooth.c + src/truetype/truetype.c + src/type1/type1.c + src/type42/type42.c + src/winfonts/winfnt.c +) + +# +# Static or shared lib flags +# +IF (BUILD_SHARED_LIBS) + SET (VTKFREETYPE_DLL 1) +ELSE (BUILD_SHARED_LIBS) + SET (VTKFREETYPE_STATIC 1) +ENDIF (BUILD_SHARED_LIBS) + +# +# Win32 flags and specific drivers +# +IF (WIN32) + SET (FREETYPE_SRCS ${FREETYPE_SRCS} builds/win32/ftdebug.c) + INCLUDE_DIRECTORIES ( + BEFORE + ${VTKFREETYPE_SOURCE_DIR}/builds/win32 + ) + IF (BORLAND) + SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-8004") + ENDIF (BORLAND) +ELSE (WIN32) + SET (FREETYPE_SRCS ${FREETYPE_SRCS} src/base/ftdebug.c) +ENDIF (WIN32) + +# +# Unix flags and specific drivers +# +IF (UNIX) + IF (CMAKE_SYSTEM MATCHES "HP-UX.*") + SET (VTKFREETYPE_HPUX_SOURCE 1) + ENDIF (CMAKE_SYSTEM MATCHES "HP-UX.*") + SET (FREETYPE_SRCS ${FREETYPE_SRCS} builds/unix/ftsystem.c) + INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFileCXX.cmake) + CHECK_INCLUDE_FILE_CXX("fcntl.h" HAVE_FCNTL_H) + CHECK_INCLUDE_FILE_CXX("unistd.h" HAVE_UNISTD_H) + CONFIGURE_FILE (${VTKFREETYPE_SOURCE_DIR}/builds/unix/ftconfig.h.in + ${VTKFREETYPE_BINARY_DIR}/builds/unix/ftconfig.h) + INCLUDE_DIRECTORIES ( + BEFORE + ${VTKFREETYPE_BINARY_DIR}/builds/unix + ) +ELSE (UNIX) + SET (FREETYPE_SRCS ${FREETYPE_SRCS} src/base/ftsystem.c) +ENDIF (UNIX) + +# +# Apple flags and specific drivers +# +IF (APPLE) + SET (VTKFREETYPE_USE_CARBON 0) +# SET (FREETYPE_SRCS ${FREETYPE_SRCS} src/base/ftmac.c) +ENDIF (APPLE) + +# +# Define the library (and install it) +# +ADD_LIBRARY (vtkfreetype ${FREETYPE_SRCS}) +IF (APPLE) + TARGET_LINK_LIBRARIES (vtkfreetype "-framework AppKit") +ENDIF (APPLE) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkfreetype PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS (${VTK_INSTALL_LIB_DIR} vtkfreetype) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) + +# +# Do not cover this lib +# +CONFIGURE_FILE (${VTKFREETYPE_SOURCE_DIR}/.NoDartCoverage + ${VTKFREETYPE_BINARY_DIR}/.NoDartCoverage) + +# +# Create the configuration file +# +ADD_DEFINITIONS (-DVTKFREETYPE) +CONFIGURE_FILE (${VTKFREETYPE_SOURCE_DIR}/include/vtkFreeTypeConfig.h.in + ${VTKFREETYPE_BINARY_DIR}/include/vtkFreeTypeConfig.h) + diff --git a/Utilities/vtkfreetype/README b/Utilities/vtkfreetype/README new file mode 100644 index 0000000..354d67d --- /dev/null +++ b/Utilities/vtkfreetype/README @@ -0,0 +1,39 @@ + Special notes to Unix users + =========================== + + Please read the file "docs/UPGRADE.UNX". It contains important + information regarding the installation of FreeType on Unix systems, + especially GNU based operating systems like GNU/Linux. + + FreeType 2's library is called `libfreetype', FreeType 1's library + is called `libttf'. They are *not* compatible! + + + FreeType 2.1.9 + ============== + + Please read the docs/CHANGES file, it contains IMPORTANT INFORMATION. + + Read the files "docs/INSTALL" for installation instructions. + + Note that the FreeType 2 documentation is now available as a + separate package from our sites. See: + + ftp://ftp.freetype.org/freetype/freetype2/ftdocs-2.1.9.tar.bz2 + ftp://ftp.freetype.org/freetype/freetype2/ftdocs-2.1.9.tar.gz + ftp://ftp.freetype.org/freetype/freetype2/ftdoc219.zip + + + Bugs + ==== + + Please report bugs by e-mail to `devel@freetype.org'. Don't forget + to send a detailed explanation of the problem -- there is nothing + worse than receiving a terse message that only says "it doesn't + work". + + + Enjoy! + + + The FreeType Team diff --git a/Utilities/vtkfreetype/README.VTK.txt b/Utilities/vtkfreetype/README.VTK.txt new file mode 100644 index 0000000..3a9cbd1 --- /dev/null +++ b/Utilities/vtkfreetype/README.VTK.txt @@ -0,0 +1,48 @@ +This directory contains a subset of the Freetype library (2.1.9) + some recent +updates made to the cache subsystem. + +We only include enough of the distribution to provide the functionalities +required by VTK. + +We would like to thank the Freetype team for distributing this library. +http://www.freetype.org + +Modifications +------------- +builds\win32\freetype\config\ftoption.h: + new file, created from include\freetype\config\ftoption.h, used to + support DLL build for Windows + +builds\unix\ftconfig.h.in: + new file, created from ftconfig.in, use CMake vars + +include\ft2build.h: + added: +#if defined(VTKFREETYPE) +#include "vtkFreeTypeConfig.h" +#endif + +include\freetype\config\ftoption.h: +builds\win32\freetype\config\ftoption.h: + comment out FT_CONFIG_OPTION_USE_ZLIB and FT_CONFIG_OPTION_USE_LZW: +/* #define FT_CONFIG_OPTION_USE_ZLIB */ +/* #define FT_CONFIG_OPTION_USE_LZW */ + +---- DO NOT APPLY ANYMORE BUT KEEP AN EYE ON MAC ------- +src\base\ftmac.c: + added: +#if defined(FT_USE_CARBON_HEADER) +#include +#else +[...] +#endif +---- DO NOT APPLY ANYMORE BUT KEEP AN EYE ON MAC ------- + +---- DO NOT APPLY ANYMORE BUT KEEP AN EYE ON MAC ------- +src\raster\ftrend1.c: + replaced: + pitch = ( ( width + 15 ) >> 4 ) << 1; + by the old code: + pitch = ( width + 7 ) >> 3; +---- DO NOT APPLY ANYMORE BUT KEEP AN EYE ON MAC ------- + diff --git a/Utilities/vtkfreetype/builds/unix/ftconfig.h.in b/Utilities/vtkfreetype/builds/unix/ftconfig.h.in new file mode 100644 index 0000000..53bb462 --- /dev/null +++ b/Utilities/vtkfreetype/builds/unix/ftconfig.h.in @@ -0,0 +1,334 @@ +/***************************************************************************/ +/* */ +/* ftconfig.in */ +/* */ +/* UNIX-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This header file contains a number of macro definitions that are used */ + /* by the rest of the engine. Most of the macros here are automatically */ + /* determined at compile time, and you should not need to change it to */ + /* port FreeType, except to compile the library with a non-ANSI */ + /* compiler. */ + /* */ + /* Note however that if some specific modifications are needed, we */ + /* advise you to place a modified copy in your build directory. */ + /* */ + /* The build directory is usually `freetype/builds/', and */ + /* contains system-specific files that are always included first when */ + /* building the library. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTCONFIG_H__ +#define __FTCONFIG_H__ + +#include +#include FT_CONFIG_OPTIONS_H +#include FT_CONFIG_STANDARD_LIBRARY_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* PLATFORM-SPECIFIC CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled to suit a specific system. The current */ + /* ones are defaults used to compile FreeType in an ANSI C environment */ + /* (16bit compilers are also supported). Copy this file to your own */ + /* `freetype/builds/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} +#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} + +#undef SIZEOF_INT +#undef SIZEOF_LONG + + +#define FT_SIZEOF_INT ${CMAKE_SIZEOF_INT} +#define FT_SIZEOF_LONG ${CMAKE_SIZEOF_LONG} + +#define FT_CHAR_BIT CHAR_BIT + + /* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + /* FT_UNUSED is a macro used to indicate that a given parameter is not */ + /* used -- this is only used to get rid of unpleasant compiler warnings */ +#ifndef FT_UNUSED +#define FT_UNUSED( arg ) ( (arg) = (arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you are doing. No */ + /* porter should need to mess with them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Mac support */ + /* */ + /* This is the only necessary change, so it is defined here instead */ + /* providing a new configuration file. */ + /* */ +#if ( defined( __APPLE__ ) && !defined( DARWIN_NO_CARBON ) ) || \ + ( defined( __MWERKS__ ) && defined( macintosh ) ) +#define FT_MACINTOSH 1 +#endif + + + /*************************************************************************/ + /* */ + /* IntN types */ + /* */ + /* Used to guarantee the size of some specific integers. */ + /* */ + typedef signed short FT_Int16; + typedef unsigned short FT_UInt16; + +#if FT_SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_UInt32; + +#elif FT_SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_UInt32; + +#else +#error "no 32bit type found -- please check your configuration files" +#endif + + + /* look up an integer type that is at least 32 bits */ +#if FT_SIZEOF_INT >= 4 + + typedef int FT_Fast; + typedef unsigned int FT_UFast; + +#elif FT_SIZEOF_LONG >= 4 + + typedef long FT_Fast; + typedef unsigned long FT_UFast; + +#endif + + + /* determine whether we have a 64-bit int type for platforms without */ + /* Autoconf */ +#if FT_SIZEOF_LONG == 8 + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ + + /* this compiler provides the __int64 type */ +#define FT_LONG64 +#define FT_INT64 __int64 + +#elif defined( __BORLANDC__ ) /* Borland C++ */ + + /* XXXX: We should probably check the value of __BORLANDC__ in order */ + /* to test the compiler version. */ + + /* this compiler provides the __int64 type */ +#define FT_LONG64 +#define FT_INT64 __int64 + +#elif defined( __WATCOMC__ ) /* Watcom C++ */ + + /* Watcom doesn't provide 64-bit data types */ + +#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */ + +#define FT_LONG64 +#define FT_INT64 long long int + +#elif defined( __GNUC__ ) + + /* GCC provides the "long long" type */ +#define FT_LONG64 +#define FT_INT64 long long int + +#endif /* FT_SIZEOF_LONG == 8 */ + + +#define FT_BEGIN_STMNT do { +#define FT_END_STMNT } while ( 0 ) +#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT + + + /*************************************************************************/ + /* */ + /* A 64-bit data type will create compilation problems if you compile */ + /* in strict ANSI mode. To avoid them, we disable their use if */ + /* __STDC__ is defined. You can however ignore this rule by */ + /* defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ + /* */ +#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 ) + +#ifdef __STDC__ + + /* Undefine the 64-bit macros in strict ANSI compilation mode. */ + /* Since `#undef' doesn't survive in configuration header files */ + /* we use the postprocessing facility of AC_CONFIG_HEADERS to */ + /* replace the leading `/' with `#'. */ +#undef FT_LONG64 +#undef FT_INT64 + +#endif /* __STDC__ */ + +#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */ + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT + +#define FT_LOCAL( x ) static x +#define FT_LOCAL_DEF( x ) static x + +#else + +#ifdef __cplusplus +#define FT_LOCAL( x ) extern "C" x +#define FT_LOCAL_DEF( x ) extern "C" x +#else +#define FT_LOCAL( x ) extern x +#define FT_LOCAL_DEF( x ) x +#endif + +#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */ + + +#ifndef FT_BASE + +#ifdef __cplusplus +#define FT_BASE( x ) extern "C" x +#else +#define FT_BASE( x ) extern x +#endif + +#endif /* !FT_BASE */ + + +#ifndef FT_BASE_DEF + +#ifdef __cplusplus +#define FT_BASE_DEF( x ) extern "C" x +#else +#define FT_BASE_DEF( x ) extern x +#endif + +#endif /* !FT_BASE_DEF */ + + +#ifndef FT_EXPORT + +#ifdef __cplusplus +#define FT_EXPORT( x ) extern "C" x +#else +#define FT_EXPORT( x ) extern x +#endif + +#endif /* !FT_EXPORT */ + + +#ifndef FT_EXPORT_DEF + +#ifdef __cplusplus +#define FT_EXPORT_DEF( x ) extern "C" x +#else +#define FT_EXPORT_DEF( x ) extern x +#endif + +#endif /* !FT_EXPORT_DEF */ + + +#ifndef FT_EXPORT_VAR + +#ifdef __cplusplus +#define FT_EXPORT_VAR( x ) extern "C" x +#else +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* !FT_EXPORT_VAR */ + + /* The following macros are needed to compile the library with a */ + /* C++ compiler and with 16bit compilers. */ + /* */ + + /* This is special. Within C++, you must specify `extern "C"' for */ + /* functions which are used via function pointers, and you also */ + /* must do that for structures which contain function pointers to */ + /* assure C linkage -- it's not possible to have (local) anonymous */ + /* functions which are accessed by (global) function pointers. */ + /* */ + /* */ + /* FT_CALLBACK_DEF is used to _define_ a callback function. */ + /* */ + /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */ + /* contains pointers to callback functions. */ + /* */ + /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable */ + /* that contains pointers to callback functions. */ + /* */ + /* */ + /* Some 16bit compilers have to redefine these macros to insert */ + /* the infamous `_cdecl' or `__fastcall' declarations. */ + /* */ +#ifndef FT_CALLBACK_DEF +#ifdef __cplusplus +#define FT_CALLBACK_DEF( x ) extern "C" x +#else +#define FT_CALLBACK_DEF( x ) static x +#endif +#endif /* FT_CALLBACK_DEF */ + +#ifndef FT_CALLBACK_TABLE +#ifdef __cplusplus +#define FT_CALLBACK_TABLE extern "C" +#define FT_CALLBACK_TABLE_DEF extern "C" +#else +#define FT_CALLBACK_TABLE extern +#define FT_CALLBACK_TABLE_DEF /* nothing */ +#endif +#endif /* FT_CALLBACK_TABLE */ + + +FT_END_HEADER + + +#endif /* __FTCONFIG_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/builds/unix/ftsystem.c b/Utilities/vtkfreetype/builds/unix/ftsystem.c new file mode 100644 index 0000000..af77c0e --- /dev/null +++ b/Utilities/vtkfreetype/builds/unix/ftsystem.c @@ -0,0 +1,397 @@ +/***************************************************************************/ +/* */ +/* ftsystem.c */ +/* */ +/* Unix-specific FreeType low-level system interface (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include + /* we use our special ftconfig.h file, not the standard one */ +#include +#include FT_INTERNAL_DEBUG_H +#include FT_SYSTEM_H +#include FT_ERRORS_H +#include FT_TYPES_H +#include FT_INTERNAL_OBJECTS_H + + /* memory-mapping includes and definitions */ +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#ifndef MAP_FILE +#define MAP_FILE 0x00 +#endif + +#ifdef MUNMAP_USES_VOIDP +#define MUNMAP_ARG_CAST void * +#else +#define MUNMAP_ARG_CAST char * +#endif + +#ifdef NEED_MUNMAP_DECL + +#ifdef __cplusplus + extern "C" +#else + extern +#endif + int + munmap( char* addr, + int len ); + +#define MUNMAP_ARG_CAST char * + +#endif /* NEED_DECLARATION_MUNMAP */ + + +#include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_alloc */ + /* */ + /* */ + /* The memory allocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* size :: The requested size in bytes. */ + /* */ + /* */ + /* The address of newly allocated block. */ + /* */ + FT_CALLBACK_DEF( void* ) + ft_alloc( FT_Memory memory, + long size ) + { + FT_UNUSED( memory ); + + return malloc( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_realloc */ + /* */ + /* */ + /* The memory reallocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* cur_size :: The current size of the allocated memory block. */ + /* */ + /* new_size :: The newly requested size in bytes. */ + /* */ + /* block :: The current address of the block in memory. */ + /* */ + /* */ + /* The address of the reallocated memory block. */ + /* */ + FT_CALLBACK_DEF( void* ) + ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + FT_UNUSED( memory ); + FT_UNUSED( cur_size ); + + return realloc( block, new_size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_free */ + /* */ + /* */ + /* The memory release function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* block :: The address of block in memory to be freed. */ + /* */ + FT_CALLBACK_DEF( void ) + ft_free( FT_Memory memory, + void* block ) + { + FT_UNUSED( memory ); + + free( block ); + } + + + /*************************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + /* We use the macro STREAM_FILE for convenience to extract the */ + /* system-specific stream handle from a given FreeType stream object */ +#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer ) + + + /*************************************************************************/ + /* */ + /* */ + /* ft_close_stream_by_munmap */ + /* */ + /* */ + /* The function to close a stream which is opened by mmap. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + FT_CALLBACK_DEF( void ) + ft_close_stream_by_munmap( FT_Stream stream ) + { + munmap( (MUNMAP_ARG_CAST)stream->descriptor.pointer, stream->size ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_close_stream_by_free */ + /* */ + /* */ + /* The function to close a stream which is created by ft_alloc. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + FT_CALLBACK_DEF( void ) + ft_close_stream_by_free( FT_Stream stream ) + { + ft_free( NULL, stream->descriptor.pointer ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Stream_Open( FT_Stream stream, + const char* filepathname ) + { + int file; + struct stat stat_buf; + + + if ( !stream ) + return FT_Err_Invalid_Stream_Handle; + + /* open the file */ + file = open( filepathname, O_RDONLY ); + if ( file < 0 ) + { + FT_ERROR(( "FT_Stream_Open:" )); + FT_ERROR(( " could not open `%s'\n", filepathname )); + return FT_Err_Cannot_Open_Resource; + } + + /* Here we ensure that a "fork" will _not_ duplicate */ + /* our opened input streams on Unix. This is critical */ + /* since it avoids some (possible) access control */ + /* issues and cleans up the kernel file table a bit. */ + /* */ +#ifdef F_SETFD +#ifdef FD_CLOEXEC + (void)fcntl( file, F_SETFD, FD_CLOEXEC ); +#else + (void)fcntl( file, F_SETFD, 1 ); +#endif /* FD_CLOEXEC */ +#endif /* F_SETFD */ + + if ( fstat( file, &stat_buf ) < 0 ) + { + FT_ERROR(( "FT_Stream_Open:" )); + FT_ERROR(( " could not `fstat' file `%s'\n", filepathname )); + goto Fail_Map; + } + + stream->size = stat_buf.st_size; + stream->pos = 0; + stream->base = (unsigned char *)mmap( NULL, + stream->size, + PROT_READ, + MAP_FILE | MAP_PRIVATE, + file, + 0 ); + + if ( (long)stream->base != -1 ) + stream->close = ft_close_stream_by_munmap; + else + { + ssize_t total_read_count; + + + FT_ERROR(( "FT_Stream_Open:" )); + FT_ERROR(( " could not `mmap' file `%s'\n", filepathname )); + + stream->base = ft_alloc( NULL, stream->size ); + + if ( !stream->base ) + { + FT_ERROR(( "FT_Stream_Open:" )); + FT_ERROR(( " could not `alloc' memory\n" )); + goto Fail_Map; + } + + total_read_count = 0; + do { + ssize_t read_count; + + + read_count = read( file, + stream->base + total_read_count, + stream->size - total_read_count ); + + if ( ( read_count == -1 ) ) + { + if ( errno == EINTR ) + continue; + + FT_ERROR(( "FT_Stream_Open:" )); + FT_ERROR(( " error while `read'ing file `%s'\n", filepathname )); + goto Fail_Read; + } + + total_read_count += read_count; + + } while ( total_read_count != (ssize_t)stream->size ); + + stream->close = ft_close_stream_by_free; + } + + close( file ); + + stream->descriptor.pointer = stream->base; + stream->pathname.pointer = (char*)filepathname; + + stream->read = 0; + + FT_TRACE1(( "FT_Stream_Open:" )); + FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + filepathname, stream->size )); + + return FT_Err_Ok; + + Fail_Read: + ft_free( NULL, stream->base ); + + Fail_Map: + close( file ); + + stream->base = NULL; + stream->size = 0; + stream->pos = 0; + + return FT_Err_Cannot_Open_Stream; + } + + +#ifdef FT_DEBUG_MEMORY + + extern FT_Int + ft_mem_debug_init( FT_Memory memory ); + + extern void + ft_mem_debug_done( FT_Memory memory ); + +#endif + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( FT_Memory ) + FT_New_Memory( void ) + { + FT_Memory memory; + + + memory = (FT_Memory)malloc( sizeof ( *memory ) ); + if ( memory ) + { + memory->user = 0; + memory->alloc = ft_alloc; + memory->realloc = ft_realloc; + memory->free = ft_free; +#ifdef FT_DEBUG_MEMORY + ft_mem_debug_init( memory ); +#endif + } + + return memory; + } + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( void ) + FT_Done_Memory( FT_Memory memory ) + { +#ifdef FT_DEBUG_MEMORY + ft_mem_debug_done( memory ); +#endif + memory->free( memory, memory ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/builds/win32/freetype/config/ftoption.h b/Utilities/vtkfreetype/builds/win32/freetype/config/ftoption.h new file mode 100644 index 0000000..6b1bf48 --- /dev/null +++ b/Utilities/vtkfreetype/builds/win32/freetype/config/ftoption.h @@ -0,0 +1,603 @@ +/***************************************************************************/ +/* */ +/* ftoption.h */ +/* */ +/* User-selectable configuration macros (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTOPTION_H__ +#define __FTOPTION_H__ + + +#ifdef _MSC_VER // MS dev + +#pragma warning( disable : 4244 ) // conversion [...] possible loss of data +#pragma warning( disable : 4761 ) // integral size mismatch in argument; conversion supplied + +#if ( _MSC_VER >= 1300 ) // Visual studio .NET + +#pragma warning( disable : 4267 ) // same +#pragma warning( disable : 4311 ) // same for pointer +#pragma warning( disable : 4312 ) // same for pointer +#pragma warning( disable : 4127 ) // conditional expression is constant +#pragma warning( disable : 4701 ) // local variable 'node' may be used without having been initialized +#pragma warning( disable : 4706 ) // assignment within conditional expression +#pragma warning( disable : 4054 ) // 'type cast' : from function pointer ... to data pointer ... + + +#endif /* _MSC_VER >= 1300 */ +#endif /* _MSC_VER */ + +#include + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* USER-SELECTABLE CONFIGURATION MACROS */ + /* */ + /* This file contains the default configuration macro definitions for */ + /* a standard build of the FreeType library. There are three ways to */ + /* use this file to build project-specific versions of the library: */ + /* */ + /* - You can modify this file by hand, but this is not recommended in */ + /* cases where you would like to build several versions of the */ + /* library from a single source directory. */ + /* */ + /* - You can put a copy of this file in your build directory, more */ + /* precisely in "$BUILD/freetype/config/ftoption.h", where "$BUILD" */ + /* is the name of a directory that is included _before_ the FreeType */ + /* include path during compilation. */ + /* */ + /* The default FreeType Makefiles and Jamfiles use the build */ + /* directory "builds/" by default, but you can easily change */ + /* that for your own projects. */ + /* */ + /* - Copy the file to "$BUILD/ft2build.h" and modify it */ + /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */ + /* locate this file during the build. For example, */ + /* */ + /* #define FT_CONFIG_OPTIONS_H */ + /* #include */ + /* */ + /* will use "$BUILD/myftoptions.h" instead of this file for macro */ + /* definitions. */ + /* */ + /* Note also that you can similarly pre-define the macro */ + /* FT_CONFIG_MODULES_H used to locate the file listing of the modules */ + /* that are statically linked to the library at compile time. By */ + /* default, this file is . */ + /* */ + /* We highly recommend using the third method whenever possible. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Many compilers provide a non-ANSI 64-bit data type that can be used */ + /* by FreeType to speed up some computations. However, this will create */ + /* some problems when compiling the library in strict ANSI mode. */ + /* */ + /* For this reason, the use of 64-bit integers is normally disabled when */ + /* the __STDC__ macro is defined. You can however disable this by */ + /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */ + /* */ + /* For most compilers, this will only create compilation warnings when */ + /* building the library. */ + /* */ + /* ObNote: The compiler-specific 64-bit integers are detected in the */ + /* file "ftconfig.h" either statically or through the */ + /* `configure' script on supported platforms. */ + /* */ +#undef FT_CONFIG_OPTION_FORCE_INT64 + + + /*************************************************************************/ + /* */ + /* LZW-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* 'compress' program. This is mostly used to parse many of the PCF */ + /* files that come with various X11 distributions. The implementation */ + /* uses NetBSD's `zopen' to partially uncompress the file on the fly */ + /* (see src/lzw/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. */ + /* */ +/* #define FT_CONFIG_OPTION_USE_LZW */ + + + /*************************************************************************/ + /* */ + /* Gzip-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* 'gzip' program. This is mostly used to parse many of the PCF files */ + /* that come with XFree86. The implementation uses `zlib' to */ + /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. See also */ + /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */ + /* */ +/* #define FT_CONFIG_OPTION_USE_ZLIB */ + + + /*************************************************************************/ + /* */ + /* ZLib library selection */ + /* */ + /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */ + /* It allows FreeType's `ftgzip' component to link to the system's */ + /* installation of the ZLib library. This is useful on systems like */ + /* Unix or VMS where it generally is already available. */ + /* */ + /* If you let it undefined, the component will use its own copy */ + /* of the zlib sources instead. These have been modified to be */ + /* included directly within the component and *not* export external */ + /* function names. This allows you to link any program with FreeType */ + /* _and_ ZLib without linking conflicts. */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ + + + /*************************************************************************/ + /* */ + /* DLL export compilation */ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front OR after the return type of function */ + /* declarations. */ + /* */ + /* Two macros are used within the FreeType source code to define */ + /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */ + /* */ + /* FT_EXPORT( return_type ) */ + /* */ + /* is used in a function declaration, as in */ + /* */ + /* FT_EXPORT( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ); */ + /* */ + /* */ + /* FT_EXPORT_DEF( return_type ) */ + /* */ + /* is used in a function definition, as in */ + /* */ + /* FT_EXPORT_DEF( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ) */ + /* { */ + /* ... some code ... */ + /* return FT_Err_Ok; */ + /* } */ + /* */ + /* You can provide your own implementation of FT_EXPORT and */ + /* FT_EXPORT_DEF here if you want. If you leave them undefined, they */ + /* will be later automatically defined as `extern return_type' to */ + /* allow normal compilation. */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_EXPORT(x) extern x */ +/* #define FT_EXPORT_DEF(x) x */ + +#if !defined(VTKFREETYPE_STATIC) +#if defined(vtkfreetype_EXPORTS) +#define FT_EXPORT( x ) __declspec( dllexport ) x +#else +#define FT_EXPORT( x ) __declspec( dllimport ) x +#endif +#endif + + /*************************************************************************/ + /* */ + /* Glyph Postscript Names handling */ + /* */ + /* By default, FreeType 2 is compiled with the `PSNames' module. This */ + /* module is in charge of converting a glyph name string into a */ + /* Unicode value, or return a Macintosh standard glyph name for the */ + /* use with the TrueType `post' table. */ + /* */ + /* Undefine this macro if you do not want `PSNames' compiled in your */ + /* build of FreeType. This has the following effects: */ + /* */ + /* - The TrueType driver will provide its own set of glyph names, */ + /* if you build it to support postscript names in the TrueType */ + /* `post' table. */ + /* */ + /* - The Type 1 driver will not be able to synthetize a Unicode */ + /* charmap out of the glyphs found in the fonts. */ + /* */ + /* You would normally undefine this configuration macro when building */ + /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */ + /* */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Postscript Names to Unicode Values support */ + /* */ + /* By default, FreeType 2 is built with the `PSNames' module compiled */ + /* in. Among other things, the module is used to convert a glyph name */ + /* into a Unicode value. This is especially useful in order to */ + /* synthetize on the fly a Unicode charmap from the CFF/Type 1 driver */ + /* through a big table named the `Adobe Glyph List' (AGL). */ + /* */ + /* Undefine this macro if you do not want the Adobe Glyph List */ + /* compiled in your `PSNames' module. The Type 1 driver will not be */ + /* able to synthetize a Unicode charmap out of the glyphs found in the */ + /* fonts. */ + /* */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /*************************************************************************/ + /* */ + /* Support for Mac fonts */ + /* */ + /* Define this macro if you want support for outline fonts in Mac */ + /* format (mac dfont, mac resource, macbinary containing a mac */ + /* resource) on non-Mac platforms. */ + /* */ + /* Note that the `FOND' resource isn't checked. */ + /* */ +#define FT_CONFIG_OPTION_MAC_FONTS + + + /*************************************************************************/ + /* */ + /* Guessing methods to access embedded resource forks */ + /* */ + /* Enable extra Mac fonts support on non-Mac platforms (e.g. */ + /* GNU/Linux). */ + /* */ + /* Resource forks which include fonts data are stored sometimes in */ + /* locations which users or developers don't expected. In some cases, */ + /* resource forks start with some offset from the head of a file. In */ + /* other cases, the actual resource fork is stored in file different */ + /* from what the user specifies. If this option is activated, */ + /* FreeType tries to guess whether such offsets or different file */ + /* names must be used. */ + /* */ + /* Note that normal, direct access of resource forks is controlled via */ + /* the FT_CONFIG_OPTION_MAC_FONTS option. */ + /* */ +#ifdef FT_CONFIG_OPTION_MAC_FONTS +#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK +#endif + + + /*************************************************************************/ + /* */ + /* Allow the use of FT_Incremental_Interface to load typefaces that */ + /* contain no glyph data, but supply it via a callback function. */ + /* This allows FreeType to be used with the PostScript language, using */ + /* the GhostScript interpreter. */ + /* */ +/* #define FT_CONFIG_OPTION_INCREMENTAL */ + + + /*************************************************************************/ + /* */ + /* The size in bytes of the render pool used by the scan-line converter */ + /* to do all of its work. */ + /* */ + /* This must be greater than 4KByte. */ + /* */ +#define FT_RENDER_POOL_SIZE 16384L + + + /*************************************************************************/ + /* */ + /* FT_MAX_MODULES */ + /* */ + /* The maximum number of modules that can be registered in a single */ + /* FreeType library object. 32 is the default. */ + /* */ +#define FT_MAX_MODULES 32 + + + /*************************************************************************/ + /* */ + /* Debug level */ + /* */ + /* FreeType can be compiled in debug or trace mode. In debug mode, */ + /* errors are reported through the `ftdebug' component. In trace */ + /* mode, additional messages are sent to the standard output during */ + /* execution. */ + /* */ + /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */ + /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */ + /* */ + /* Don't define any of these macros to compile in `release' mode! */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_DEBUG_LEVEL_ERROR */ +/* #define FT_DEBUG_LEVEL_TRACE */ + + + /*************************************************************************/ + /* */ + /* Memory Debugging */ + /* */ + /* FreeType now comes with an integrated memory debugger that is */ + /* capable of detecting simple errors like memory leaks or double */ + /* deletes. To compile it within your build of the library, you */ + /* should define FT_DEBUG_MEMORY here. */ + /* */ + /* Note that the memory debugger is only activated at runtime when */ + /* when the _environment_ variable "FT2_DEBUG_MEMORY" is defined also! */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_DEBUG_MEMORY */ + + + /*************************************************************************/ + /* */ + /* Module errors */ + /* */ + /* If this macro is set (which is _not_ the default), the higher byte */ + /* of an error code gives the module in which the error has occurred, */ + /* while the lower byte is the real error code. */ + /* */ + /* Setting this macro makes sense for debugging purposes only, since */ + /* it would break source compatibility of certain programs that use */ + /* FreeType 2. */ + /* */ + /* More details can be found in the files ftmoderr.h and fterrors.h. */ + /* */ +#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in all formats using the SFNT module (namely */ + /* TrueType & OpenType). */ + /* */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ + /* load and enumerate the glyph Postscript names in a TrueType or */ + /* OpenType file. */ + /* */ + /* Note that when you do not compile the `PSNames' module by undefining */ + /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ + /* contain additional code used to read the PS Names table from a font. */ + /* */ + /* (By default, the module uses `PSNames' to extract glyph names.) */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */ + /* access the internal name table in a SFNT-based format like TrueType */ + /* or OpenType. The name table contains various strings used to */ + /* describe the font, like family name, copyright, version, etc. It */ + /* does not contain any glyph name though. */ + /* */ + /* Accessing SFNT names is done through the functions declared in */ + /* `freetype/ftnames.h'. */ + /* */ +#define TT_CONFIG_OPTION_SFNT_NAMES + + + /*************************************************************************/ + /* */ + /* TrueType CMap support */ + /* */ + /* Here you can fine-tune which TrueType CMap table format shall be */ + /* supported. */ +#define TT_CONFIG_CMAP_FORMAT_0 +#define TT_CONFIG_CMAP_FORMAT_2 +#define TT_CONFIG_CMAP_FORMAT_4 +#define TT_CONFIG_CMAP_FORMAT_6 +#define TT_CONFIG_CMAP_FORMAT_8 +#define TT_CONFIG_CMAP_FORMAT_10 +#define TT_CONFIG_CMAP_FORMAT_12 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */ + /* a bytecode interpreter in the TrueType driver. Note that there are */ + /* important patent issues related to the use of the interpreter. */ + /* */ + /* By undefining this, you will only compile the code necessary to load */ + /* TrueType glyphs without hinting. */ + /* */ + /* Do not #undef this macro here, since the build system might */ + /* define it for certain configurations only. */ + /* */ +/* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_UNPATENTED_HINTING (in addition to */ + /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER) to compile the unpatented */ + /* work-around hinting system. Note that for the moment, the algorithm */ + /* is only used when selected at runtime through the parameter tag */ + /* FT_PARAM_TAG_UNPATENTED_HINTING; or when the debug hook */ + /* FT_DEBUG_HOOK_UNPATENTED_HINTING is globally actived */ + /* */ +#define TT_CONFIG_OPTION_UNPATENTED_HINTING + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */ + /* bytecode interpreter with a huge switch statement, rather than a call */ + /* table. This results in smaller and faster code for a number of */ + /* architectures. */ + /* */ + /* Note however that on some compiler/processor combinations, undefining */ + /* this macro will generate faster, though larger, code. */ + /* */ +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */ + /* TrueType glyph loader to use Apple's definition of how to handle */ + /* component offsets in composite glyphs. */ + /* */ + /* Apple and MS disagree on the default behavior of component offsets */ + /* in composites. Apple says that they should be scaled by the scale */ + /* factors in the transformation matrix (roughly, it's more complex) */ + /* while MS says they should not. OpenType defines two bits in the */ + /* composite flags array which can be used to disambiguate, but old */ + /* fonts will not have them. */ + /* */ + /* http://partners.adobe.com/asn/developer/opentype/glyf.html */ + /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */ + /* */ +#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */ + /* support for Apple's distortable font technology (fvar, gvar, cvar, */ + /* and avar tables). This has many similarities to Type 1 Multiple */ + /* Masters support. */ + /* */ +#define TT_CONFIG_OPTION_GX_VAR_SUPPORT + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */ + /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */ + /* required. */ + /* */ +#define T1_MAX_DICT_DEPTH 5 + + + /*************************************************************************/ + /* */ + /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ + /* calls during glyph loading. */ + /* */ +#define T1_MAX_SUBRS_CALLS 16 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */ + /* minimum of 16 is required. */ + /* */ + /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 256 + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of `t1afm', which is in charge of reading Type 1 AFM */ + /* files into an existing face. Note that if set, the T1 driver will be */ + /* unable to produce kerning distances. */ + /* */ +#undef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of the Multiple Masters font support in the Type 1 */ + /* driver. */ + /* */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + + /* */ + +/* + * The FT_CONFIG_OPTION_CHESTER_XXXX macros are used to toggle some recent + * improvements to the auto-hinter contributed by David Chester. They will + * most likely disappear completely in the next release. For now, you + * should always keep them defined. + * + */ +#define FT_CONFIG_OPTION_CHESTER_HINTS + +#ifdef FT_CONFIG_OPTION_CHESTER_HINTS + +#define FT_CONFIG_CHESTER_SMALL_F +#define FT_CONFIG_CHESTER_ASCENDER +#define FT_CONFIG_CHESTER_SERIF +#define FT_CONFIG_CHESTER_STEM +#define FT_CONFIG_CHESTER_BLUE_SCALE + +#endif /* FT_CONFIG_OPTION_CHESTER_HINTS */ + +FT_END_HEADER + + +#endif /* __FTOPTION_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/builds/win32/ftdebug.c b/Utilities/vtkfreetype/builds/win32/ftdebug.c new file mode 100644 index 0000000..5816a4f --- /dev/null +++ b/Utilities/vtkfreetype/builds/win32/ftdebug.c @@ -0,0 +1,211 @@ +/***************************************************************************/ +/* */ +/* ftdebug.c */ +/* */ +/* Debugging and logging component for Win32 (body). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component contains various macros and functions used to ease the */ + /* debugging of the FreeType engine. Its main purpose is in assertion */ + /* checking, tracing, and error detection. */ + /* */ + /* There are now three debugging modes: */ + /* */ + /* - trace mode */ + /* */ + /* Error and trace messages are sent to the log file (which can be the */ + /* standard error output). */ + /* */ + /* - error mode */ + /* */ + /* Only error messages are generated. */ + /* */ + /* - release mode: */ + /* */ + /* No error message is sent or generated. The code is free from any */ + /* debugging parts. */ + /* */ + /*************************************************************************/ + + +#include +#include FT_INTERNAL_DEBUG_H + + +#ifdef FT_DEBUG_LEVEL_ERROR + + +# include +# include +# include + +# include + + + FT_EXPORT_DEF( void ) + FT_Message( const char* fmt, ... ) + { + static char buf[8192]; + va_list ap; + + + va_start( ap, fmt ); + vsprintf( buf, fmt, ap ); + OutputDebugStringA( buf ); + va_end( ap ); + } + + + FT_EXPORT_DEF( void ) + FT_Panic( const char* fmt, ... ) + { + static char buf[8192]; + va_list ap; + + + va_start( ap, fmt ); + vsprintf( buf, fmt, ap ); + OutputDebugStringA( buf ); + va_end( ap ); + + exit( EXIT_FAILURE ); + } + + +# ifdef FT_DEBUG_LEVEL_TRACE + + + /* array of trace levels, initialized to 0 */ + int ft_trace_levels[trace_count]; + + /* define array of trace toggle names */ +# define FT_TRACE_DEF( x ) #x , + + static const char* ft_trace_toggles[trace_count + 1] = + { +# include FT_INTERNAL_TRACE_H + NULL + }; + +# undef FT_TRACE_DEF + + + /*************************************************************************/ + /* */ + /* Initialize the tracing sub-system. This is done by retrieving the */ + /* value of the "FT2_DEBUG" environment variable. It must be a list of */ + /* toggles, separated by spaces, `;' or `,'. Example: */ + /* */ + /* "any:3 memory:6 stream:5" */ + /* */ + /* This will request that all levels be set to 3, except the trace level */ + /* for the memory and stream components which are set to 6 and 5, */ + /* respectively. */ + /* */ + /* See the file for details of the */ + /* available toggle names. */ + /* */ + /* The level must be between 0 and 6; 0 means quiet (except for serious */ + /* runtime errors), and 6 means _very_ verbose. */ + /* */ + FT_BASE_DEF( void ) + ft_debug_init( void ) + { + const char* ft2_debug = getenv( "FT2_DEBUG" ); + + + if ( ft2_debug ) + { + const char* p = ft2_debug; + const char* q; + + + for ( ; *p; p++ ) + { + /* skip leading whitespace and separators */ + if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' ) + continue; + + /* read toggle name, followed by ':' */ + q = p; + while ( *p && *p != ':' ) + p++; + + if ( *p == ':' && p > q ) + { + int n, i, len = p - q; + int level = -1, found = -1; + + + for ( n = 0; n < trace_count; n++ ) + { + const char* toggle = ft_trace_toggles[n]; + + + for ( i = 0; i < len; i++ ) + { + if ( toggle[i] != q[i] ) + break; + } + + if ( i == len && toggle[i] == 0 ) + { + found = n; + break; + } + } + + /* read level */ + p++; + if ( *p ) + { + level = *p++ - '0'; + if ( level < 0 || level > 6 ) + level = -1; + } + + if ( found >= 0 && level >= 0 ) + { + if ( found == trace_any ) + { + /* special case for "any" */ + for ( n = 0; n < trace_count; n++ ) + ft_trace_levels[n] = level; + } + else + ft_trace_levels[found] = level; + } + } + } + } + } + + +# else /* !FT_DEBUG_LEVEL_TRACE */ + + + FT_BASE_DEF( void ) + ft_debug_init( void ) + { + /* nothing */ + } + + +# endif /* !FT_DEBUG_LEVEL_TRACE */ + +#endif /* FT_DEBUG_LEVEL_ERROR */ + +/* END */ diff --git a/Utilities/vtkfreetype/docs/CHANGES b/Utilities/vtkfreetype/docs/CHANGES new file mode 100644 index 0000000..fdb9ce3 --- /dev/null +++ b/Utilities/vtkfreetype/docs/CHANGES @@ -0,0 +1,2477 @@ + +LATEST CHANGES BETWEEN 2.1.9 and 2.1.8 + + I. IMPORTANT BUG FIXES + + - The function `FT_Get_CharMap_Index' was only declared, without + any real code. For consistency, it has been renamed to + `FT_Get_Charmap_Index'. (This function is needed to implement + cmap caches.) + + - `FT_Outline_Get_BBox' sometimes returned incorrect values for + conic outlines (e.g., for TrueType fonts). + + - Handling of `bhed' table has been fixed. + + - The TrueType driver with enabled byte code interpreter sometimes + returned artifacts due to incorrect rounding. This bug has been + introduced after version 2.1.4. + + - The BDF driver dropped the last glyph in the font. + + - The BDF driver now uses the DEFAULT_CHAR property (if available) + to select a glyph shape for the undefined glyph. + + + II. IMPORTANT CHANGES + + - George Williams contributed code to handle Apple's font + distortion technology found in GX fonts (`avar', `cvar', `fvar', + and `gvar' tables; the Multiple Masters API has been slightly + extended to cope with the new functionality). + + - The `FT_GlyphSlotRec' structure has been extended: The elements + `lsb_delta' and `rsb_delta' give the difference between hinted + and unhinted left and right side bearings if autohinting is + active. Using those values can improve the inter-letter spacing + considerably. See the documentation of `FT_GlyphSlotRec' and + the `ftstring' demo program how to use it. + + + III. MISCELLANEOUS + + - A new documentation file `formats.txt' describes various font + formats supported (and not supported) by FreeType. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.8 and 2.1.7 + + I. IMPORTANT BUG FIXES + + - The native TrueType hinter contained some bugs which prevented + some fonts to be rendered correctly, most notably Legendum.otf. + + - The PostScript hinter now produces improved results. + + - The linear advance width and height values were incorrectly + rounded, making them virtually unusable if not loaded with + FT_LOAD_LINEAR_DESIGN. + + - Indexing CID-keyed CFF fonts is now working: The glyph index is + correctly treated as a CID, similar to FreeType's CID driver + module. Note that CID CMap support is still missing. + + - The FT_FACE_FLAGS_GLYPH_NAMES flag is now set correctly for all + font formats. + + - Some subsetted Type 1 fonts weren't parsed correctly. This bug + has been introduced in 2.1.7. In summary, the Type 1 parser has + become more robust. + + - Non-decimal numbers weren't parsed correctly in PS fonts. + + - The WinFNT driver now correctly reports FT_ENCODING_NONE for all + but one encoding. Use the new FT_WinFNT_ID_XXX values together + with FT_Get_WinFNT_Header() to get the WinFNT charset ID. + + - The descender metrics (face->size->metrics.descender) for WinFNT + bitmap fonts had the wrong sign. + + - The (emulated) `seac' support for CFF fonts was broken. + + - The `flex' operator didn't work for CFF fonts. + + - PS glyphs which use the `hintmask' operator haven't been + rendered correctly in some cases. + + - Metrics for BDF and PCF bitmap font formats have been fixed. + + - Autohinting is now disabled for glyphs which are vertically + distorted or mirrored (using a transformation matrix). This + fixes a bug which produced zero-height glyphs. + + - The `freetype-config' script now handles --prefix and + --exec-prefix correctly; it also returns the proper --rpath (or + -R) value if FreeType has been built as a shared library. + + + II. IMPORTANT CHANGES + + - Both PCF and BDF drivers now handle the SETWIDTH_NAME and + ADD_STYLE_NAME properties. Values are appended to + face->style_name; example: `Bold SemiCondensed'. + + - The PCF driver now handles bitmap fonts compressed with the LZW + algorithm (extension .pcf.Z, compressed with `compress'). + + - A new API function `FT_Get_CMap_Language_ID' (declared in + `tttables.h') is available to get the language ID of a + TrueType/SFNT cmap. + + - The hexadecimal format of data after the `StartData' command in + CID-keyed Type 1 fonts is now supported. While this can't occur + in file-based fonts, it can happen in document-embedded + resources of PostScript documents. + + - Embedded bitmaps in SFNT-based CFF fonts are now supported. + + - A simple API is now available to control FreeType's tracing + mechanism if compiled with FT_DEBUG_LEVEL_TRACE. See the file + `ftdebug.h' for more details. + + - YAMATO Masatake contributed improved handling of MacOS resource + forks on non-MacOS platforms (for example, Linux can mount MacOS + file systems). + + - Support for MacOS has been improved; there is now a new function + `FT_New_Face_From_FSSpec' similar to `FT_New_Face' except that + it accepts an FSSpec instead of a path. + + - The cache sub-system has been rewritten. + + - There is now support for deinstallation of faces. + + - A new API function `FTC_Manager_RemoveFaceID' has been added + to delete all `idle' nodes that correspond to a given + FTC_FaceID. All `locked' nodes (i.e., those with a reference + count > 0), will be modified to prevent them from appearing in + further lookups (they will be cleaned normally when their + reference count reaches 0). + + - There is now support for point scaling (i.e., providing + character sizes in points + dpis, instead of pixels). + + - Three abstract cache classes are now available: + + FTC_GCache: Used to store one glyph item per cache node, + with the ability to group common attributes into + `families'. This replaces the old + FTC_GlyphCache class. + + FTC_ICache: Used to store one FT_Glyph per cache node. This + extends FTC_GCache. Family definition, family + comparison, and glyph loading are however left + to sub-classes. + + FTC_SCache: Used to store up to 16 small bitmaps per cache + node. This extends FTC_GCache. Family + definition, family comparison and glyph loading + are however left to sub-classes. + + - The file `src/cache/ftcbasic.c' implements: + + FTC_ImageCache: Extends FTC_ICache; implements family + definitions and glyph loading similar to the + old API. + + FTC_SBitCache: Extends FTC_SCache, implements family + definitions and glyph loading similar to the + old API + + Client applications should be able to extend FTC_GCache, + FTC_ICache, or FTC_SCache much more easily (i.e., less code to + write, and less callbacks). For example, one could envision + caches that are capable of storing transformed (obliqued), + stroked, emboldened, or colored glyph images. Use + `ftcbasic.c' as an example. + + - All public APIs are now in `include/freetype/ftcache.h', (to + be accessed as `FT_CACHE_H'). The contents of + `include/freetype/cache/' is only needed by applications that + wish to implement their own caches. + + - There were some major performance improvements through the use + of various programming tricks. Cache hits are up to 70% + faster than in the old code. + + - The FTC_CMapCache has been simplied. Charmaps can only be + accessed by index right now. There is also a new API named + `FT_Charmap_GetIndex' for this purpose. + + - The demo programs have been updated to the new code. The + previous versions will not work with the current one. + + - Using an invalid face index in FT_Open_Face and friends now + causes an error even if the font contains a single face only. + + + III. MISCELLANEOUS + + - Wolfgang Domröse contributed support files for building FreeType + on the Atari using the PureC compiler. Note that the Atari is a + 16bit platform. + + - Vitaliy Pasternak contributed project files for VS.NET 2003. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.7 and 2.1.6 + + I. IMPORTANT BUG FIXES + + - Updated to newest libtool version, fixing build problems on + various platforms. + + - On Unix platforms, `make install' didn't copy the correct + `ftconfig.h' file. + + Note that version 2.1.7 contains the same library C source code as + version 2.1.6. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.6 and 2.1.5 + + I. IMPORTANT BUG FIXES + + - The PFR font driver didn't load kerning tables correctly, and + the functions in FT_PFR_H didn't work at all. + + - Type 1 font files in binary format (PFB) with an end-of-file + indicator weren't accepted by the FreeType engine. + + - Fonts which contain /PaintType and /StrokeWidth no longer cause + a segfault. This bug has been introduced in version 2.1.5. + + - Fonts loaded with FT_LOAD_RENDER no longer cause strange + results. This bug has been introduced in version 2.1.5. + + - Some Windows (bitmap) FNT/FON files couldn't be handled + correctly. + + + II. IMPORTANT CHANGES + + - The internal module API has been heavily changed in favor of + massive simplifications within the font engine. This also means + that authors of third-party modules must adapt their code to the + new scheme. + + NOTE: THE NEW SCHEME IS NOT COMPLETED YET. PLEASE WAIT UNTIL A + FINAL ANNOUNCEMENT! + + - The PostScript parser has been enhanced to handle comments and + strings correctly. Additionally, more syntax forms are + recognized. + + - Added the optional unpatented hinting system for TrueType. It + allows typefaces which need hinting to produce correct glyph + forms (e.g., Chinese typefaces from Dynalab) to work acceptably + without infringing Apple patents. This system is compiled only + if TT_CONFIG_OPTION_COMPILE_UNPATENTED_HINTING is defined in + ftoption.h (activated by default). + + + III. MISCELLANEOUS + + - There is now a guard in the public header files to protect + against inclusion of freetype.h from FreeType 1. + + - Direct inclusion of freetype.h and other public header files no + longer works. You have to use the documented scheme + + #include + #include FT_FREETYPE_H + + to load freetype.h with a symbolic name. This protects against + renaming of public header files (which shouldn't happen but + actually has, avoiding two public header files with the same + name). + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.5 and 2.1.4 + + I. IMPORTANT BUG FIXES + + - Parsing the /CIDFontName field now removes the leading slash to + be in sync with other font drivers. + + - gzip support was buggy. Some fonts could not be read. + + - Fonts which have nested subglyphs more than one level deep no + longer cause a segfault. + + - Creation of synthetic cmaps for fonts in CFF format was broken + partially. + + - Numeric font dictionary entries for synthetic fonts are no + longer overwritten. + + - The font matrix wasn't applied to the advance width for Type1, + CID, and CFF fonts. This caused problems when loading certain + synthetic Type 1 fonts like `Helvetica Narrow'. + + - The test for the charset registry in BDF and PCF fonts is now + case-insensitive. + + - FT_Vector_Rotate sometimes returned strange values due to + rounding errors. + + - The PCF driver now returns the correct number of glyphs + (including an artificial `notdef' glyph at index 0). + + - FreeType now supports buggy CMaps which are contained in many + CJK fonts from Dynalab. + + - Opening an invalid font on a Mac caused a segfault due to + double-freeing memory. + + - BDF fonts with more than 32768 glyphs weren't supported + properly. + + + II. IMPORTANT CHANGES + + - Accessing bitmap font formats has been synchronized. To do that + the FT_Bitmap_Size structure has been extended to contain new + fields `size', `x_ppem', and `y_ppem'. + + - The FNT driver now returns multiple faces, not multiple strikes. + + - The `psnames' module has been updated to the Adobe Glyph List + version 2.0. + + - The `psnames' module now understands `uXXXX[X[X]]' glyph names. + + - The algorithm for guessing the font style has been improved. + + - For fonts in SFNT format, root->height is no longer increased if + the line gap is zero. There exist fonts (containing e.g. form + drawing characters) which intentionally have a zero line gap + value. + + - ft_glyph_bbox_xxx flags are now deprecated in favour of + FT_GLYPH_BBOX_XXX. + + - ft_module_xxx flags are now deprecated in favour of + FT_MODULE_XXX. + + - FT_ENCODING_MS_{SJIS,GB2312,BIG5,WANSUNG,JOHAB} are now + deprecated in favour of + FT_ENCODING_{SJIS,GB2312,GIB5,WANSONG,JOHAB} -- those encodings + are not specific to Microsoft. + + + III. MISCELLANEOUS + + - The autohinter has been further improved; for example, `m' + glyphs now retain its vertical symmetry. + + - Partial support of Mac fonts on non-Mac platforms. + + - `make refdoc' (after first `make') builds the HTML + documentation. You need Python for this. + + - The make build system should now work more reliably on DOS-like + platforms. + + - Support for EMX gcc and Watson C/C++ compilers on MS-DOS has + been added. + + - Better VMS build support. + + - Support for the pkg-config package by providing a `freetype.pc' + file. + + - New configure option --with-old-mac-fonts for Darwin. + + - Some source files have been renamed (mainly to fit into the 8.3 + naming scheme). + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.4 and 2.1.3 + + I. IMPORTANT BUG FIXES + + - Updated to newest libtool version, fixing build problems on + various platforms. + + - A fix in the Gzip stream reader: It couldn't read certain .gz + files properly due to a small typo. In certain cases, FreeType + could also loop endlessly when trying to load tiny gzipped + files. + + - The configure script now tries to use the system-wide zlib when + it finds one (instead of the copy found in src/gzip). And + "freetype-config" has been updated to return relevant flags in + this case when invoked with "--libs" (e.g. "-lzlib"). + + - Certain fonts couldn't be loaded by 2.1.3 because they lacked a + Unicode charmap (e.g. SYMBOL.TTF). FreeType erroneously + rejected them. + + - The CFF loader was modified to accept fonts which only contain a + subset of their reference charset. This prevented the correct + use of PDF-embedded fonts. + + - The logic to detect Unicode charmaps has been modified. This is + required to support fonts which include both 16-bit and 32-bit + charmaps (like very recent asian ones) using the new 10 and 12 + SFNT formats. + + - The TrueType loader now limits the depth of composite glyphs. + This is necessary to prevent broken fonts to break the engine by + blowing the stack with recursive glyph definitions. + + - The CMap cache is now capable of managing UCS-4 character codes + that are mapped through extended charmaps in recent + TrueType/OpenType fonts. + + - The cache sub-system now properly manages out-of-memory + conditions instead of blindly reporting them to the caller. + This means that it will try to empty the cache before restarting + its allocations to see if that can help. + + - The PFR driver didn't return the list of available embedded + bitmaps properly. + + - There was a nasty memory leak when using embedded bitmaps in + certain font formats. + + + II. IMPORTANT CHANGES + + - David Chester contributed some enhancements to the auto-hinter + that significantly increase the quality of its output. The + Postscript hinter was also improved in several ways. + + - The FT_RENDER_MODE_LIGHT render mode was implemented. + + - A new API function called `FT_Get_BDF_Property' has been added + to FT_BDF_H to retrieve BDF properties from BDF _and_ PCF font + files. THIS IS STILL EXPERIMENTAL, since it hasn't been + properly tested yet. + + - A Windows FNT specific API has been added, mostly to access font + headers. This is used by Wine. + + - TrueType tables without an "hmtx" table are now tolerated when + an incremental interface is used. This happens for certain + Type42 fonts passed from Ghostscript to FreeType. + + - The PFR font driver is now capable of returning the font family + and style names when they are available (instead of the sole + "FontID"). This is performed by parsing an *undocumented* + portion of the font file! + + + III. MISCELLANEOUS + + - The path stroker in FT_STROKER_H has entered beta stage. It now + works very well, but its interface might change a bit in the + future. More on this in later releases. + + - The documentation for FT_Size_Metrics didn't appear properly in + the API reference. + + - The file docs/VERSION.DLL has been updated to explain versioning + with FreeType (i.e., comparing release/libtool/so numbers, and + how to use them in autoconf scripts). + + - The installation documentation has been seriously revamped. + Everything is now in the "docs" directory. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.3 and 2.1.2 + + I. IMPORTANT BUG FIXES + + - FT_Vector_Transform had been incorrectly modified in 2.1.2, + resulting in incorrect transformations being applied (for + example, rotations were processed in opposite angles). + + - The format 8 and 12 TrueType charmap enumeration routines have + been fixed (FT_Get_Next_Char returned invalid values). + + - The PFR font driver returned incorrect advance widths if the + outline and metrics resolution defined in the font file were + different. + + - FT_Glyph_To_Bitmap now returns successfully when called with an + FT_BitmapGlyph argument (it previously returned an error). + + - A bug in the Type 1 loader that prevented valid font bounding + boxes to be loaded from multiple master fonts. + + - The SFNT validation code has been rewritten. FreeType can now + load "broken" fonts that were usable on Windows, but not with + previous versions of the library. + + - The computation of bearings in the BDF driver has been fixed. + + - The Postscript hinter crashed when trying to hint certain glyphs + (more precisely, when trying to apply hints to an empty glyph + outline). + + - The TrueType glyph loader now supports composites in "Apple + format" (they differ slightly from Microsoft/OpenType ones in + the way transformation offsets are computed). + + - FreeType was very slow at opening certain asian CID/CFF fonts, + due to fixed increment in dynamic array re-allocations. This + has been changed to exponential behaviour to get acceptable + performance. + + + + II. IMPORTANT CHANGES + + - The PCF driver now supports gzip-compressed font files natively. + This means that you will be able to use all these bitmap fonts + that come with XFree86 with FreeType (and libXft/libXft2, by + extension). + + - The automatic and postscript hinters have both been updated. + This results in a relatively important increase of rendering + quality since many nasty defaults have been supressed. Please + visit the web page: + + http://www.freetype.org/hinting/smooth-hinting.html + + for additional details on this topic. + + - The "load_flags" parameter of FT_Load_Glyph is now an FT_Int32 + (instead of just being an FT_Int). This breaks source and + binary compatibility for 16bit systems only, while retaining + both of them for 32 and 64 bit ones. + + Some new flags have been added consequently: + + FT_LOAD_NO_AUTOHINT :: Disable the use of the auto-hinter + (but not native format hinters). + + FT_LOAD_TARGET_NORMAL :: Hint and render for normal + anti-aliased displays. + + FT_LOAD_TARGET_MONO :: Hint and render for 1-bit displays. + + FT_LOAD_TARGET_LCD :: Hint and render for horizontal RGB or + BGR sub-pixel displays (like LCD + screens). THIS IS STILL + EXPERIMENTAL! + + FT_LOAD_TARGET_LCD_V :: Same as FT_LOAD_TARGET_LCD, for + vertical sub-pixel displays (like + rotated LCD screens). THIS IS STILL + EXPERIMENTAL! + + FT_LOAD_MONOCHROME is still supported, but only affects + rendering, not the hinting. + + Note that the `ftview' demo program available in the `ft2demos' + package has been updated to support LCD-optimized display on + non-paletted displays (under Win32 and X11). + + - The PFR driver now supports embedded bitmaps (all formats + supported), and returns correct kerning metrics for all glyphs. + + - The TrueType charmap loader now supports certain `broken' fonts + that load under Windows without problems. + + - The cache API has been slightly modified (it's still a beta!): + + - The type FTC_ImageDesc has been removed; it is now replaced + by FTC_ImageTypeRec. Note that one of its fields is a + `load_flag' parameter for FT_Load_Glyph. + + - The field "num_grays" of FT_SBitRec has been changed to + "max_grays" in order to fit within a single byte. Its + maximum value is thus 255 (instead of 256 as previously). + + + III. MISCELLANEOUS + + - Added support for the DESTDIR variable during "make install". + This simplifies packaging of FreeType. + + - Included modified copies of the ZLib sources in `src/gzip' in + order to support gzip-compressed PCF fonts. We do not use the + system-provided zlib for now, though this is a probable + enhancement for future releases. + + - The DocMaker tool used to generate the on-line API reference has + been completely rewritten. It is now located in + "src/tools/docmaker/docmaker.py". Features: + + - better cross-referenced output + - more polished output + - uses Python regular expressions (though it didn't speed the + program) + - much more modular structure, which allows for different + "backends" in order to generate HTML, XML, or whatever + format. + + One can regenerate the API reference by calling: + + python src/tools/docmaker/docmaker.py \ + --prefix=ft2 \ + --title=FreeType-2.1.3 \ + --output= + include/freetype/*.h \ + include/freetype/config/*.h \ + include/freetype/cache/*.h + + - A new, experimental, support for incremental font loading (i.e., + loading of fonts where the glyphs are not in the font file + itself, but provided by an external component, like a Postscript + interpreter) has been added by Graham Asher. This is still work + in progress, however. + + - A new, EXPERIMENTAL, path stroker has been added. It doesn't + suffer from severe rounding errors and treat bezier arcs + directly. Still work in progress (i.e. not part of the official + API). See the file for some of the + details. + + - The massive re-formatting of sources and internal re-design is + still under-way. Many internal functions, constants, and types + have been renamed. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.2 and 2.1.1 + + I. IMPORTANT BUG FIXES + + - Many font drivers didn't select a Unicode charmap by default + when a new face was opened (with the FT_CONFIG_OPTION_USE_CMAPS + options enabled), causing many applications to not be able to + display text correctly with the 2.1.x releases. + + - The PFR driver had a bug in its composite loading code that + produces incorrectly placed accents with many fonts. + + - The Type42 driver crashed sometimes due to a nasty bug. + + - The Type 1 custom encoding charmap didn't handle the case where + the first glyph index wasn't 0. + + - A serious typo in the TrueType composite loader produced + incorrectly placed glyphs in fonts like "Wingdings" and a few + others. + + + II. MISCELLANEOUS + + - The Win32 Visual C++ project file has been updated to include + the PFR driver as well. + + - "freetype.m4" is now installed by default by "make install" on + Unix systems. + + - The function FT_Get_PS_Font_Info now works with CID and Type42 + fonts as well. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.1 and 2.1.0 + + I. IMPORTANT BUG FIXES + + - The `version_info' returned by `freetype-config' in 2.1.0 + returned an invalid value. It now returns 9:1:3 (2.0.9 returned + 9:0:3). + + - Version 2.1.0 couldn't be linked against applications on Win32 + and Amiga systems due to a new debug function that wasn't + properly propagated to the system-specific directory in + `builds'. + + - Various MacOS and Mac OS X specific fixes. + + - Fixed a bug in the TrueType charmap validation routines that + made version 2.1.0 too restrictive -- many popular fonts have + been rejected. + + - There was still a very small difference between the monochrome + glyph bitmaps produced by FreeType 1.x and FreeType 2.x with the + bytecode interpreter enabled. This was caused by an invalid + flag setting in the TrueType glyph loader, making the rasterizer + change its drop-out control mode. Now theresults should + _really_ be completely identical. + + - The TrueType name table loader has been improved to support many + popular though buggy Asian fonts. It now ignores empty name + entries, invalid pointer offsets and a few other incorrect + subtleties. Moreover, name strings are now loaded on demand, + which reduces the memory load of many faces (e.g. the ARIAL.TTF + font file contains a 10kByte name table with 70 names). + + - Fixed a bug in the Postscript hinter that prevented family blues + substitution to happen correctly. + + + II. NEW FEATURES + + - Three new font drivers in this release: + + * A BDF font driver, contributed by Franco Zappa Nardelli, + heavily modified by Werner Lemberg. It also supports + anti-aliased bitmaps (using a slightly extended BDF format). + + * A Type42 font driver, contributed by Roberto Alameda. It is + still experimental but seems to work relatively well. + + * A PFR font driver, contributed by David Turner himself. It + doesn't support PFR hinting -- note that BitStream has at + least two patents on this format! + + + III. MISCELLANEOUS + + - The cache sub-system has been optimized in important ways. + Cache hits are now significantly faster. For example, using the + CMap cache is about twice faster than calling FT_Get_Char_Index + on most platforms. Similarly, using an SBit cache is about five + times faster than loading the bitmaps from a bitmap file, and + 300 to 500 times faster than generating them from a scalable + format. + + Note that you should recompile your sources if you designed a + custom cache class for the FT2 Cache subsystem, since the + changes performed are source, but not binary, compatible. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.1.0 and 2.0.9 + + I. IMPORTANT BUG FIXES + + - The TrueType bytecode interpreter has been fixed to produce + _exactly_ the same output as FreeType 1.x. Previous differences + were due to slightly distinct fixed-point computation routines + used to perform dot products and vector length measurements. + + It seems that native TrueType hinting is _extremely_ sensitive + to rounding errors. The required vector computation routines + have been optimized and placed within the "ttinterp.c" file. + + - Fixed the parsing of accelerator tables in the PCF font driver. + + - Fixed the Type1 glyph loader routine used to compute the font's + maximum advance width. + + + II. NEW FEATURES + + - The `configure' script used on Unix systems has been modified to + check that GNU Make is being used to build the library. + Otherwise, it will display a message proposing to use the + GNUMAKE environment variable to name it. + + The Unix-specific file README.UNX has been modified accordingly. + + + III. MISCELLANEOUS + + - The FreeType License in `docs/FTL.txt' has been updated to + include a proposed preferred disclaimer. If you are using + FreeType in your products, you are encouraged (but not mandated) + to use the following text in your documentation: + + """ + Portions of this software are copyright © 1996-2002 The + FreeType Project (www.freetype.org). All rights reserved. + """ + + - The default size of the render pool has been reduced to 16kByte. + This shouldn't result in any noticeable performance penalty, + unless you are using the engine as-is to render very large and + complex glyphs. + + - The FreeType 2 redesign has begun. More information can be + found at this URL: + + http://www.freetype.org/freetype2/redesign.html + + The following internal changes have been performed within the + sources of this release: + + - Many internal types have been renamed to increase + consistency. The following should be true, except for + public types: + + * All structure types have a name ending in "Rec" (short + for `record'). + + * A pointer-to-structure type has the same name as the + structure, _without_ the "Rec" suffix. + + Example: + + typedef struct FooRec_ + { + ... + + } FooRec, *Foo; + + - Many internal macros have been renamed to increase + consistency. The following should be true: + + * All macros have a name beginning with "FT_". This + required a few changes like + + ALLOC => FT_ALLOC + FREE => FT_FREE + REALLOC => FT_REALLOC + + * All macros are completely UPPERCASE. This required a + few changes like: + + READ_Short => FT_READ_SHORT + NEXT_Short => FT_NEXT_SHORT + GET_ULongLE => FT_GET_ULONG_LE + MEM_Set => FT_MEM_SET + MEM_Copy => FT_MEM_COPY + etc. + + * Whenever possible, all macro names follow the + FT__ pattern. For example + + ACCESS_Frame => FT_FRAME_ENTER + FORGET_Frame => FT_FRAME_EXIT + EXTRACT_Frame => FT_FRAME_EXTRACT + RELEASE_Frame => FT_FRAME_RELEASE + + FILE_Pos => FT_STREAM_POS + FILE_Seek => FT_STREAM_SEEK + FILE_Read => FT_STREAM_READ + FILE_ReadAt => FT_STREAM_READ_AT + READ_Fields => FT_STREAM_READ_FIELDS + + - Many internal functions have been renamed to follow the + FT__ pattern. For example: + + FT_Seek_Stream => FT_Stream_Seek + FT_Read_Stream_At => FT_Stream_ReadAt + FT_Done_Stream => FT_Stream_Close + FT_New_Stream => FT_Stream_Open + FT_New_Memory_Stream => FT_Stream_OpenMemory + FT_Extract_Frame => FT_Stream_ExtractFrame + + Note that method names do not contain "_". + + - The FT_ALLOC_ARRAY and FT_REALLOC_ARRAY have been replaced + with FT_NEW_ARRAY and FT_RENEW_ARRAY which do not take a + type as the fourth argument. Instead, the array element + type size is computed automatically from the type of the + target pointer used. + + - A new object class, FT_CMap, has been introduced. These + internal objects are used to model character maps. This + eases the support of additional charmap types within the + engine. + + - A new configuration file named "ftstdlib.h" has been added + to `include/freetype/config'. It is used to define aliases + for _every_ routine of the ISO C library that the font + engine uses. Each aliases has a "ft_" prefix + (e.g. "ft_strlen" is an alias for "strlen"). + + This is used to ease the porting of FreeType 2 to exotic + runtime environments where the ISO C Library isn't available + (e.g. XFree86 extension modules). + + More details are available in the "ChangeLog" file. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.9 and 2.0.8 + + I. IMPORTANT BUG FIXES + + - Certain fonts like "foxjump.ttf" contain broken name tables with + invalid entries and wild offsets. This caused FreeType to crash + when trying to load them. + + The SFNT `name' table loader has been fixed to be able to + support these strange fonts. + + Moreover, the code in charge of processing this table has been + changed to always favour Windows-formatted entries over other + ones. Hence, a font that works on Windows but not on the Mac + will load cleanly in FreeType and report accurate values for + Family & PostScript names. + + - The CID font driver has been fixed. It unfortunately returned a + Postscript Font name with a leading slash, as in + "/MunhwaGothic-Regular". + + - FreeType 2 should now compile fine on AIX 4.3.3 as a shared + library. + + - A bug in the Postscript hinter has been found and fixed, + removing un-even stem widths at small pixel sizes (like 14-17). + + This improves the quality of a certain number of Postscript + fonts. + + + II. NEW FEATURES + + - A new function named `FT_Library_Version' has been added to + return the current library's major, minor, and patch version + numbers. This is important since the macros FREETYPE_MAJOR, + FREETYPE_MINOR, and FREETYPE_PATCH cannot be used when the + library is dynamically linked by a program. + + - Two new APIs have been added: `FT_Get_First_Char' and + `FT_Get_Next_Char'. + + Together, these can be used to iterate efficiently over the + currently selected charmap of a given face. Read the API + reference for more details. + + + III. MISCELLANEOUS + + - The FreeType sources are under heavy internal re-factoring. As + a consequence, we have created a branch named "STABLE" on the + CVS to hold all future releases/fixes in the 2.0.x family. + + The HEAD branch now contains the re-factored sources and + shouldn't be used for testing or packaging new releases. In + case you would like to access the 2.0.9 sources from our CVS + repository, use the tag `VER-2-0-9'. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.8 and 2.0.7 + + I. IMPORTANT BUG FIXES + + - There was a small but nasty bug in "freetype-config.in" which + caused the "freetype-config" script to fail on Unix. + + This didn't prevent the installation of the library or even its + execution, but caused problems when trying to compile many Unix + packages that depend on it. + + - Some TrueType or OpenType fonts embedded in PDF documents do not + have a 'cmap', 'post' and 'name' as is required by the + specification. FreeType no longer refuses to load such fonts. + + - Various fixes to the PCF font driver. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.7 and 2.0.6 + + I. IMPORTANT BUG FIXES + + - Fixed two bugs in the Type 1 font driver. The first one + resulted in a memory leak in subtle cases. The other one caused + FreeType to crash when trying to load ".gsf" files (Ghostscript + so-called Postscript fonts). + + (This made _many_ KDE applications crash on certain systems. + FreeType _is_ becoming a critical system component on Linux :-) + + - Fixed a memory leak in the CFF font driver. + + - Fixed a memory leak in the PCF font driver. + + - Fixed the Visual C++ project file + "builds/win32/visualc/freetype.dsp" since it didn't include the + Postscript hinter component, causing errors at build time. + + - Fixed a small rendering bug in the anti-aliased renderer that + only occurred when trying to draw thin (less than 1 pixel) + strokes. + + - Fixed "builds/unix/freetype2.a4" which is used to generate a + valid "freetype2.m4" for use with autoconf. + + - Fixed the OpenVMS Makefiles. + + + II. MISCELLANEOUS + + - Added "configure" and "install" scripts to the top-level + directory. A GNU-style installation is thus now easily possible + with + + ./configure + make + make install + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.6 and 2.0.5 + + I. IMPORTANT BUG FIXES + + - It wasn't possible to load embedded bitmaps when the auto-hinter + was used. This is now fixed. + + - The TrueType font driver didn't load some composites properly + (the sub-glyphs were slightly shifted, and this was only + noticeable when using monochrome rendering). + + - Various fixes to the auto-hinter. They merely improve the + output of sans-serif fonts. Note that there are still problems + with serifed fonts and composites (accented characters). + + - All scalable font drivers erroneously returned un-fitted glyph + advances when hinting was requested. This created problems for + a number of layout applications. This is a very old bug that + got undetected mainly because most test/demo program perform + rounding explicitly or implicitly (through the cache). + + - FT_Glyph_To_Bitmap() did erroneously modify the source glyph in + certain cases. + + - "glnames.py" still contained a bug that made FreeType return + invalid names for certain glyphs. + + - The library crashed when loading certain Type 1 fonts like + "sadn.pfb" ("Stalingrad Normal"), which appear to contain + pathetic font info dictionaries. + + - The TrueType glyph loader is now much more paranoid and checks + everything when loading a given glyph image. This was necessary + to avoid problems (crashes and/or memory overwrites) with broken + fonts that came from a really buggy automatic font converter. + + + II. IMPORTANT UPDATES AND NEW FEATURES + + - Important updates to the Mac-specific parts of the library. + + - The caching sub-system has been completely re-designed, and its + API has evolved (the old one is still supported for backwards + compatibility). + + The documentation for it is not yet completed, sorry. For now, + you are encouraged to continue using the old API. However, the + ftview demo program in the ft2demos package has already been + updated to use the new caching functions. + + - A new charmap cache is provided too. See FTC_CMapCache(). This + is useful to perform character code -> glyph index translations + quickly, without the need for an opened FT_Face. + + - A NEW POSTSCRIPT HINTER module has been added to support native + hints in the following formats: PostScript Type 1, PostScript + CID, and CFF/CEF. + + Please test! Note that the auto-hinter produces better results + for a number of badly-hinted fonts (mostly auto-generated ones) + though. + + - A memory debugger is now part of the standard FreeType sources. + To enable it, define FT_DEBUG_MEMORY in + , and recompile the library. + + Additionally, define the _environment_ variable FT_DEBUG_MEMORY + and run any program using FreeType. When the library is exited, + a summary of memory footprints and possible leaks will be + displayed. + + This works transparently with _any_ program that uses FreeType. + However, you will need a lot of memory to use this (allocated + blocks are never released to the heap to detect double deletes + easily). + + + III. MISCELLANEOUS + + - We are aware of subtle differences between the output of + FreeType versions 1 and 2 when it comes to monochrome + TrueType-hinted glyphs. These are most probably due to small + differences in the monochrome rasterizers and will be worked out + in an upcoming release. + + - We have decided to fork the sources in a "stable" branch, and an + "unstable" one, since FreeType is becoming a critical component + of many Unix systems. + + The next bug-fix releases of the library will be named 2.0.7, + 2.0.8, etc., while the "2.1" branch will contain a version of + the sources where we will start major reworking of the library's + internals, in order to produce FreeType 2.2.0 (or even 3.0) in a + more distant future. + + We also hope that this scheme will allow much more frequent + releases than in the past. + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.5 and 2.0.4 + + NOTE THAT 2.0.5 DOES NOT CONTAIN THE POSTSCRIPT HINTER. THIS MODULE + WILL BE PART OF THE NEXT RELEASE (EITHER 2.0.6 or 2.1) + + - Fixed a bug that made certain glyphs, like "Cacute", "cacute" and + "lslash" unavailable from Unicode charmaps of Postscript fonts. + This prevented the correct display of Polish text, for example. + + - The kerning table of Type 1 fonts was loaded by FreeType, when its + AFM file was attached to its face, but the + FT_FACE_FLAG_HAS_KERNING bit flags was not set correctly, + preventing FT_Get_Kerning to return meaningful values. + + - Improved SFNT (TrueType & OpenType) charmap support. Slightly + better performance, as well as support for the new formats defined + by the OpenType 1.3 specification (8, 10, and 12) + + - Fixed a serious typo in "src/base/ftcalc.c" which caused invalid + computations in certain rare cases, producing ugly artefacts. + + - The size of the EM square is computed with a more accurate + algorithm for Postscript fonts. The old one caused slight errors + with embedded fonts found in PDF documents. + + - Fixed a bug in the cache manager that prevented normal LRU + behaviour within the cache manager, causing unnecessary reloads + (for FT_Face and FT_Size objects only). + + - Added a new function named "FT_Get_Name_Index" to retrieve the + glyph index of a given glyph name, when found in a face. + + - Added a new function named "FT_Get_Postscript_Name" to retrieve + the "unique" Postscript font name of a given face. + + - Added a new public header size named FT_SIZES_H (or + ) providing new FT_Size-management functions: + FT_New_Size, FT_Activate_Size, FT_Done_Size. + + - Fixed a reallocation bug that generated a dangling pointer (and + possibly memory leaks) with Postscript fonts (in + src/psaux/psobjs.c). + + - Many fixes for 16-bit correctness. + + - Removed many pedantic compiler warnings from the sources. + + - Added an Amiga build directory in "builds/amiga". + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.4 and 2.0.3 + + - Fixed a rather annoying bug that was introduced in 2.0.3. Namely, + the font transformation set through FT_Set_Transform was applied + twice to auto-hinted glyphs, resulting in incorrectly rotated text + output. + + - Fixed _many_ compiler warnings. FT2 should now compile cleanly + with Visual C++'s most pedantic warning level (/W4). It already + compiled fine with GCC and a few other compilers. + + - Fixed a bug that prevented the linear advance width of composite + TrueType glyphs to be correctly returned. + + - Fixed the Visual C++ project files located in + "builds/win32/visualc" (previous versions used older names of the + library). + + - Many 32-bit constants have an "L" appended to their value, in + order to improve the 16-bitness of the code. Someone is actually + trying to use FT2 on an Atari ST machine! + + - Updated the "builds/detect.mk" file in order to automatically + build FT2 on AIX systems. AIX uses "/usr/sbin/init" instead of + "/sbin/init" and wasn't previously detected as a Unix platform by + the FreeType build system. + + - Updated the Unix-specific portions of the build system (new + libtool version, etc.). + + - The SFNT kerning lodaer now ensures that the table is sorted + (since some problem fonts do not meet this requirement). + + +======================================================================= + +LATEST CHANGES BETWEEN 2.0.3 and 2.0.2 + + I. CHANGES TO THE MODULES / FONT DRIVERS + + - THE AUTO-HINTER HAS BEEN SLIGHTLY IMPROVED, in order to fix + several annoying artefacts, mainly: + + - Blue zone alignement of horizontal stems wasn't performed + correctly, resulting in artefacts like the "d" being placed + one pixel below the "b" in some fonts like Time New Roman. + + - Overshoot thresholding wasn't performed correctly, creating + unpleasant artefacts at large character pixel sizes. + + - Composite glyph loading has been simplified. This gets rid + of various artefacts where the components of a composite + glyphs were not correctly spaced. + + These are the last changes to the current auto-hinting module. + A new hinting sub-system is currently in the work in order to + support native hints in Type 1 / CFF / OpenType fonts, as well + as globally improve rendering. + + - The PCF driver has been fixed. It reported invalid glyph + dimensions for the fonts available on Solaris. + + - The Type 1, CID and CFF drivers have been modified to fix the + computation of the EM size. + + - The Type 1 driver has been fixed to avoid a dangerous bug that + crashed the library with non-conforming fonts (i.e. ones that do + not place the .notdef glyph at position 0). + + - The TrueType driver had a rather subtle bug (dangling pointer + when loading composite glyphs) that could crash the library in + rare occasions! + + + II. HIGH-LEVEL API CHANGES + + - The error code enumeration values have been changed. An error + value is decomposed in a generic error code, and a module + number. see for details. + + - A new public header file has been introduced, named + FT_TRIGONOMETRY_H (include/freetype/fttrig.h), providing + trigonometric functions to compute sines, cosines, arctangents, + etc. with 16.16 fixed precision. The implementation is based on + the CORDIC algorithm and is very fast while being sufficiently + accurate. + + + III. INTERNALS + + - Added BeOS-specific files in the old build sub-system. Note + that no changes were required to compile the library with Jam. + + - The configuration is now capable of automatically detecting + 64-bit integers on a set of predefined compilers (GCC, Visual + C++, Borland C++) and will use them by default. This provides a + small performance boost. + + - A small memory leak that happened when opening 0-sized files + (duh!) have been fixed. + + - Fixed bezier stack depth bug in the routines provided by the + FT_BBOX_H header file. Also fixed similar bugs in the + rasterizers. + + - The outline bounding box code has been rewritten to use direct + computations, instead of bezier sub-division, to compute the + exact bounding box of glyphs. This is slightly slower but more + accurate. + + - The build system has been improved and fixed, mainly to support + "make" on Windows 2000 correctly, avoid problems with "make + distclean" on non Unix systems, etc. + + - Hexadecimal constants have been suffixed with "U" to avoid + problems with certain compilers on 64-bit platforms. + + - A new directory named "src/tools" has been created. It contains + Python scripts and simple unit test programs used to develop the + library. + + - The DocMaker tool has been moved from "docs" to "src/tools" and + has been updated with the following: + + - Now accepts the "--title=XXXX" or "-t XXXX" option from the + command line to set the project's name in the generated API + reference. + + - Now accepts the "--output=DIR" or "-o DIR" option from the + command line to set the output directory for all generated + HTML files. + + - Now accepts the "--prefix=XXXX" or "-p XXX" option from the + command line to set the file prefix to use for all + generated HTML files. + + - Now generates the current time/data on each generated page + in order to distinguish between versions. + + DocMaker can be used with other projects now, not only FT2 + (e.g. MLib, FTLayout, etc.). + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.2 and 2.0.1 + + I. CHANGES TO THE MODULES / FONT DRIVERS + + - THE TRUETYPE BYTECODE INTERPRETER IS NOW TURNED OFF, in order to + avoid legal problems with the Apple patents. It seems that we + mistakenly turned this option on in previous releases of the + build. + + Note that if you want to use the bytecode interpreter in order + to get high-quality TrueType rendering, you will need to toggle + by hand the definition of the + TT_CONFIG_OPTION_BYTECODE_INTERPRETER macro in the file + "include/freetype/config/ftoption.h". + + - The CFF driver has been improved by Tom Kacvinsky and Sander van + der Wal: + + * Support for "seac" emulation. + * Support for "dotsection". + * Support for retrieving glyph names through + "FT_Get_Glyph_Name". + + The first two items are necessary to correctly a large number of + Type 1 fonts converted to the CFF formats by Adobe Acrobat. + + - The Type 1 driver was also improved by Tom & others: + + * Better EM size computation. + * Better support for synthetic (transformed) fonts. + * The Type 1 driver returns the charstrings corresponding to + each glyph in the "glyph->control_data" field after a call to + "FT_Load_Glyph" (thanks Ha Shao). + + - Various other bugfixes, including the following: + + * Fixed a nasty memory leak in the Type 1 driver. + * The autohinter and the pcf driver used static writable data + when they shouldn't. + * Many casts were added to make the code more 64-bits safe. It + also now compiles on Windows XP 64-bits without warnings. + * Some incorrect writable statics were removed in the "autohint" + and "pcf" drivers. FreeType 2 now compiles on Epoc again. + + + II. CHANGES TO THE HIGH-LEVEL API + + - The library header files inclusion scheme has been changed. The + old scheme looked like: + + #include + #include + #include + #include + + Now you should use: + + #include + #include FT_FREETYPE_H + #include FT_GLYPH_H + #include FT_CACHE_H + #include FT_CACHE_IMAGE_H + + NOTE THAT THE OLD INCLUSION SCHEME WILL STILL WORK WITH THIS + RELEASE. HOWEVER, WE DO NOT GUARANTEE THAT THIS WILL STILL BE + TRUE IN THE NEXT ONE (A.K.A. FREETYPE 2.1). + + The file is used to define the header filename + macros. The complete and commented list of macros is available + in the API reference under the section name "Header File Macros" + in Chapter I. + + For more information, see section I of the following document: + + http://www.freetype.org/ + freetype2/docs/tutorial/step1.html + + or + + http://freetype.sourceforge.net/ + freetype2/docs/tutorial/step1.html + + - Many, many comments have been added to the public source file in + order to automatically generate the API Reference through the + "docmaker.py" Python script. + + The latter has been updated to support the grouping of sections + in chapters and better index sort. See: + + http://www.freetype.org/freetype2/docs/reference/ft2-toc.html + + + III. CHANGES TO THE BUILD PROCESS + + - If you are not building FreeType 2 with its own build system + (but with your own Makefiles or project files), you will need to + be aware that the build process has changed a little bit. + + You don't need to put the "src" directory in the include path + when compiling any FT2 component. Instead, simply put the + component's directory in the current include path. + + So, if you were doing something like: + + cc -c -Iinclude -Isrc src/base/ftbase.c + + change the line to: + + cc -c -Iinclude -Isrc/base src/base/ftbase.c + + If you were doing something like: + + cd src/base + cc -c -I../../include -I.. ftbase.c + + change it to: + + cd src/base + cc -c -I../../include ftbase.c + + +====================================================================== + +LATEST CHANGES BETWEEN 2.0.1 and 2.0 + + 2.0.1 introduces a few changes: + + - Fixed many bugs related to the support of CFF / OpenType fonts. + These formats are now much better supported though there is + still work planned to deal with charset tables and PDF-embedded + CFF files that use the old "seac" command. + + - The library could not be compiled in debug mode with a very + small number of C compilers whose pre-processors didn't + implement the "##" directive correctly (i.e. per se the ANSI C + specification!) An elegant fix was found. + + - Added support for the free Borland command-line C++ Builder + compiler. Use "make setup bcc32". Also fixed a few source + lines that generated new warnings with BCC32. + + - Fixed a bug in FT_Outline_Get_BBox when computing the extrema of + a conic Bezier arc. + + - Updated the INSTALL file to add IDE compilation. + + - Other minor bug fixes, from invalid Type 1 style flags to + correct support of synthetic (obliqued) fonts in the + auto-hinter, better support for embedded bitmaps in a SFNT font. + + - Fixed some problems with "freetype-config". + + Finally, the "standard" scheme for including FreeType headers is now + gradually changing, but this will be explained in a later release + (probably 2.0.2). + + And very special thanks to Tom Kacvinsky and YAMANO-UCHI Hidetoshi + for their contributions! + + +====================================================================== + +CHANGES BETWEEN beta8 and 2.0 + + - Changed the default installation path for public headers from + "include/freetype" to "include/freetype2". + + Also added a new "freetype-config" that is automatically generated + and installed on Unix and Cygwin systems. The script itself is + used to retrieve the current install path, C compilation flags as + well as linker flags. + + - Fixed several small bugs: + + * Incorrect max advance width for fixed-pitch Type 1 fonts. + * Incorrect glyph names for certain TrueType fonts. + * The glyph advance was not copied when FT_Glyph_To_Bitmap was + called. + * The linearHoriAdvance and linerVertAdvance fields were not + correctly returned for glyphs processed by the auto-hinter. + * "type1z" renamed back to "type1"; the old "type1" module has + been removed. + + - Revamped the build system to make it a lot more generic. This + will allow us to re-use nearly un-modified in lots of other + projects (including FreeType Layout). + + - Changed "cid" to use "psaux" too. + + - Added the cache sub-system. See as well as + the sources in "src/cache". Note that it compiles but is still + untested for now. + + - Updated "docs/docmaker.py", a draft API reference is available at + http://www.freetype.org/ft2api.html. + + - Changed "type1" to use "psaux". + + - Created a new module named "psaux" to hold the Type 1 & Type 2 + parsing routines. It should be used by "type1", "cid", and "cff" + in the future. + + - Fixed an important bug in "FT_Glyph_Get_CBox". + + - Fixed some compiler warnings that happened since the TrueType + bytecode decoder was deactivated by default. + + - Fixed two memory leaks: + + * The memory manager (16 bytes) isn't released in + FT_Done_FreeType! + * Using custom input streams, the copy of the original stream was + never released. + + - Fixed the auto-hinter by performing automatic computation of the + "filling direction" of each glyph. This is done through a simple + and fast approximation, and seems to work (problems spotted by + Werner though). The Arphic fonts are a lot nicer though there are + still a lot of things to do to handle Asian fonts correctly. + + +====================================================================== + +BETA-8 (RELEASE CANDIDATE) CHANGES + + - Deactivated the TrueType bytecode interpreter by default. + + - Deactivated the "src/type1" font driver. Now "src/type1z" is used + by default. + + - Updates to the build system. We now compile the library correctly + under Unix system through "configure" which is automatically + called on the first "make" invocation. + + - Added the auto-hinting module! Fixing some bugs here and there. + + - Found some bugs in the composite loader (seac) of the Type1-based + font drivers. + + - Renamed the directory "freetype2/config" to "freetype2/builds" and + updated all relevant files. + + - Found a memory leak in the "type1" driver. + + - Incorporated Tom's patches to support flex operators correctly in + OpenType/CFF fonts. Now all I need is to support pure CFF and CEF + fonts to be done with this driver :-) + + - Added the Windows FNT/FON driver in "src/winfonts". For now, it + always "simulates" a Unicode charmap, so it shouldn't be + considered completed right now. + + It is there to be more a proof of concept than anything else + anyway. The driver is a single C source file, that compiles to 3 + Kb of code. + + I'm still working on the PCF/BDF drivers, but I'm too lazy to + finish them now. + + - CHANGES TO THE HIGH-LEVEL API + + * FT_Get_Kerning has a new parameter that allows you to select the + coordinates of the kerning vector (font units, scaled, scaled + + grid-fitted). + * The outline functions are now in and not + part of anymore. + * now contains declarations for + FT_New_Library, FT_Done_Library, FT_Add_Default_Modules. + * The so-called convenience functions have moved from "ftoutln.c" + to "ftglyph.c", and are thus available with this optional + component of the library. They are declared in + now. + * Anti-aliased rendering is now the default for FT_Render_Glyph + (i.e. corresponds to render_mode == 0 == ft_render_mode_normal). + To generate a monochrome bitmap, use ft_render_mode_mono, or the + FT_LOAD_MONOCHROME flag in FT_Load_Glyph/FT_Load_Char. + FT_LOAD_ANTI_ALIAS is still defined, but values to 0. + * now include , + solving a few headaches :-) + * The type FT_GlyphSlotRec has now a "library" field. + + - CHANGES TO THE "ftglyph.h" API + + This API has been severely modified in order to make it simpler, + clearer, and more efficient. It certainly now looks like a real + "glyph factory" object, and allows client applications to manage + (i.e. transform, bbox and render) glyph images without ever + knowing their original format. + + - Added support for CID-keyed fonts to the CFF driver. Maybe + support for pure CFF + CEF fonts should come in? + + - Cleaned up source code in order to avoid two functions with the + same name. Also changed the names of the files in "type1z" from + "t1XXXX" to "z1XXXX" in order to avoid any conflicts. + + "make multi" now works well :-) + + Also removed the use of "cidafm" for now, even if the source files + are still there. This functionality will certainly go into a + specific module. + + - ADDED SUPPORT FOR THE AUTO-HINTER + + It works :-) I have a demo program which simply is a copy of + "ftview" that does a `FT_Add_Module(library, + &autohinter_module_class)' after library initialization, and Type + 1 & OpenType/CFF fonts are now hinted. + + CID fonts are not hinted, as they include no charmap and the + auto-hinter doesn't include "generic" global metrics computations + yet. + + Now, I need to release this thing to the FreeType 2 source. + + - CHANGES TO THE RENDERER MODULES + + The monochrome and smooth renderers are now in two distinct + directories, namely "src/raster1" and "src/smooth". Note that the + old "src/renderer" is now gone. + + I ditched the 5-gray-levels renderers. Basically, it involved a + simple #define toggle in 'src/raster1/ftraster.c'. + + FT_Render_Glyph, FT_Outline_Render & FT_Outline_Get_Bitmap now + select the best renderer available, depending on render mode. If + the current renderer for a given glyph image format isn't capable + of supporting the render mode, another one will be found in the + library's list. This means that client applications do not need + to switch or set the renderers themselves (as in the latest + change), they'll get what they want automatically. At last. + + Changed the demo programs accordingly. + + - MAJOR INTERNAL REDESIGN: + + A lot of internal modifications have been performed lately on the + source in order to provide the following enhancements: + + * More generic module support: + + The FT_Module type is now defined to represent a handle to a + given module. The file contains the + FT_Module_Class definition, as well as the module-loading public + API. + + The FT_Driver type is still defined, and still represents a + pointer to a font driver. Note that FT_Add_Driver is replaced + by FT_Add_Module, FT_Get_Driver by FT_Get_Module, etc. + + * Support for generic glyph image types: + + The FT_Renderer type is a pointer to a module used to perform + various operations on glyph image. + + Each renderer is capable of handling images in a single format + (e.g. ft_glyph_format_outline). Its functions are used to: + + - transform an glyph image + - render a glyph image into a bitmap + - return the control box (dimensions) of a given glyph image + + The scan converters "ftraster.c" and "ftgrays.c" have been moved + to the new directory "src/renderer", and are used to provide two + default renderer modules. + + One corresponds to the "standard" scan-converter, the other to + the "smooth" one. + + he current renderer can be set through the new function + FT_Set_Renderer. + + The old raster-related function FT_Set_Raster, FT_Get_Raster and + FT_Set_Raster_Mode have now disappeared, in favor of the new: + + FT_Get_Renderer + FT_Set_Renderer + + See the file for more details. + + These changes were necessary to properly support different + scalable formats in the future, like bi-color glyphs, etc. + + * Glyph loader object: + + A new internal object, called a 'glyph loader' has been + introduced in the base layer. It is used by all scalable format + font drivers to load glyphs and composites. + + This object has been created to reduce the code size of each + driver, as each one of them basically re-implemented its + functionality. + + See and the FT_GlyphLoader type for + more information. + + * FT_GlyphSlot has new fields: + + In order to support extended features (see below), the + FT_GlyphSlot structure has a few new fields: + + linearHoriAdvance: + + This field gives the linearly scaled (i.e. scaled but + unhinted) advance width for the glyph, expressed as a 16.16 + fixed pixel value. This is useful to perform WYSIWYG text. + + linearVertAdvance: + This field gives the linearly scaled advance height for the + glyph (relevant in vertical glyph layouts only). This is + useful to perform WYSIWYG text. + + Note that the two above field replace the removed "metrics2" + field in the glyph slot. + + advance: + This field is a vector that gives the transformed advance for + the glyph. By default, it corresponds to the advance width, + unless FT_LOAD_VERTICAL_LAYOUT was specified when calling + FT_Load_Glyph or FT_Load_Char. + + bitmap_left: + This field gives the distance in integer pixels from the + current pen position to the left-most pixel of a glyph image + IF IT IS A BITMAP. It is only valid when the "format" field + is set to "ft_glyph_format_bitmap", for example, after calling + the new function FT_Render_Glyph. + + bitmap_top: + This field gives the distance in integer pixels from the + current pen position (located on the baseline) to the top-most + pixel of the glyph image IF IT IS A BITMAP. Positive values + correspond to upwards Y. + + loader: + This is a new private field for the glyph slot. Client + applications should not touch it. + + + * Support for transforms and direct rendering in FT_Load_Glyph: + + Most of the functionality found in has been + moved to the core library. Hence, the following: + + - A transform can be specified for a face through + FT_Set_Transform. this transform is applied by FT_Load_Glyph + to scalable glyph images (i.e. NOT TO BITMAPS) before the + function returns, unless the bit flag FT_LOAD_IGNORE_TRANSFORM + was set in the load flags. + + - Once a glyph image has been loaded, it can be directly + converted to a bitmap by using the new FT_Render_Glyph + function. Note that this function takes the glyph image from + the glyph slot, and converts it to a bitmap whose properties + are returned in "face.glyph.bitmap", "face.glyph.bitmap_left" + and "face.glyph.bitmap_top". The original native image might + be lost after the conversion. + + - When using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph + and FT_Load_Char functions will call FT_Render_Glyph + automatically when needed. + + - Reformatted all modules source code in order to get rid of the + basic data types redifinitions (i.e. "TT_Int" instead of "FT_Int", + "T1_Fixed" instead of "FT_Fixed"). Hence the format-specific + prefixes like "TT_", "T1_", "T2_" and "CID_" are only used for + relevant structures. + + +====================================================================== + +OLD CHANGES FOR BETA 7 + + - bug-fixed the OpenType/CFF parser. It now loads and displays my + two fonts nicely, but I'm pretty certain that more testing is + needed :-) + + - fixed the crummy Type 1 hinter, it now handles accented characters + correctly (well, the accent is not always well placed, but that's + another problem..) + + - added the CID-keyed Type 1 driver in "src/cid". Works pretty well + for only 13 Kb of code ;-) Doesn't read AFM files though, nor the + really useful CMAP files.. + + - fixed two bugs in the smooth renderer (src/base/ftgrays.c). + Thanks to Boris Letocha for spotting them and providing a fix. + + - fixed potential "divide by zero" bugs in ftcalc.c. + + - added source code for the OpenType/CFF driver (still incomplete + though..) + + - modified the SFNT driver slightly to perform more robust header + checks in TT_Load_SFNT_Header. This prevents certain font files + (e.g. some Type 1 Multiple Masters) from being incorrectly + "recognized" as TrueType font files.. + + - moved a lot of stuff from the TrueType driver to the SFNT module, + this allows greater code re-use between font drivers + (e.g. TrueType, OpenType, Compact-TrueType, etc..) + + - added a tiny segment cache to the SFNT Charmap 4 decoder, in order + to minimally speed it up.. + + - added support for Multiple Master fonts in "type1z". There is + also a new file named which defines functions to + manage them from client applications. + + The new file "src/base/ftmm.c" is also optional to the engine.. + + - various formatting changes (e.g. EXPORT_DEF -> FT_EXPORT_DEF) + + small bug fixes in FT_Load_Glyph, the "type1" driver, etc.. + + - a minor fix to the Type 1 driver to let them apply the font matrix + correctly (used for many oblique fonts..) + + - some fixes for 64-bit systems (mainly changing some FT_TRACE calls + to use %p instead of %lx). Thanks to Karl Robillard. + + - fixed some bugs in the sbit loader (src/base/sfnt/ttsbit.c) + + added a new flag, FT_LOAD_CROP_BITMAP to query that bitmaps be + cropped when loaded from a file (maybe I should move the bitmap + cropper to the base layer ??). + + - changed the default number of gray levels of the smooth renderer + to 256 (instead of the previous 128). Of course, the human eye + can't see any difference ;-) + + - removed TT_MAX_SUBGLYPHS, there is no static limit on the number + of subglyphs in a TrueType font now.. + + +====================================================================== + +OLD CHANGES 16 May 2000 + + - tagged "BETA-6" in the CVS tree. This one is a serious release + candidate even though it doesn't incorporate the auto-hinter yet.. + + - various obsolete files were removed, and copyright header updated + + - finally updated the standard raster to fix the monochrome + rendering bug + re-enable support for 5-gray levels anti-aliasing + (suck, suck..) + + - created new header files, and modified sources accordingly: + + + - simple FreeType types, without the API + + - definition of memory-management macros + + - added the "DSIG" (OpenType Digital Signature) tag to + + + - light update/cleaning of the build system + changes to the sources + in order to get rid of _all_ compiler warnings with three + compilers, i.e: + + gcc with "-ansi -pedantic -Wall -W", Visual C++ with "/W3 /WX" and + LCC + + IMPORTANT NOTE FOR WIN32-LCC USERS: + | + | It seems the C pre-processor that comes with LCC is broken, it + | doesn't recognize the ANSI standard directives # and ## + | correctly when one of the argument is a macro. Also, + | something like: + | + | #define F(x) print##x + | + | F(("hello")) + | + | will get incorrectly translated to: + | + | print "hello") + | + | by its pre-processor. For this reason, you simply cannot build + | FreeType 2 in debug mode with this compiler.. + + - yet another massive grunt work. I've changed the definition of + the EXPORT_DEF, EXPORT_FUNC, BASE_DEF & BASE_FUNC macros. These + now take an argument, which is the function's return value type. + + This is necessary to compile FreeType as a DLL on Windows and + OS/2. Depending on the compiler used, a compiler-specific keyword + like __export or __system must be placed before (VisualC++) or + after (BorlandC++) the type.. + + Of course, this needed a lot of changes throughout the source code + to make it compile again... All cleaned up now, apparently.. + + Note also that there is a new EXPORT_VAR macro defined to allow + the _declaration_ of an exportable public (constant) + variable. This is the case of the raster interfaces (see + ftraster.h and ftgrays.h), as well as each module's interface (see + sfdriver.h, psdriver.h, etc..) + + - new feature: it is now possible to pass extra parameters to font + drivers when creating a new face object. For now, + this capability is unused. It could however prove to + be useful in a near future.. + + the FT_Open_Args structure was changes, as well as the internal + driver interface (the specific "init_face" module function has + now a different signature). + + - updated the tutorial (not finished though). + + - updated the top-level BUILD document + + - fixed a potential memory leak that could occur when loading + embedded bitmaps. + + - added the declaration of FT_New_Memory_Face in + , as it was missing from the public header + (the implementation was already in "ftobjs.c"). + + - the file has been seriously updated in order + to allow the automatic generation of error message tables. See + the comments within it for more information. + + - major directory hierarchy re-organisation. This was done for two + things: + + * first, to ease the "manual" compilation of the library by + requiring at lot less include paths :-) + + * second, to allow external programs to effectively access + internal data fields. For example, this can be extremely + useful if someone wants to write a font producer or a font + manager on top of FreeType. + + Basically, you should now use the 'freetype/' prefix for header + inclusion, as in: + + #include + #include + + Some new include sub-directories are available: + + a. the "freetype/config" directory, contains two files used to + configure the build of the library. Client applications + should not need to look at these normally, but they can if + they want. + + #include + #include + + b. the "freetype/internal" directory, contains header files that + describes library internals. These are the header files that + were previously found in the "src/base" and "src/shared" + directories. + + + As usual, the build system and the demos have been updated to + reflect the change.. + + Here's a layout of the new directory hierarchy: + + TOP_DIR + include/ + freetype/ + freetype.h + ... + config/ + ftoption.h + ftconfig.h + ftmodule.h + + internal/ + ftobjs.h + ftstream.h + ftcalc.h + ... + + src/ + base/ + ... + + sfnt/ + psnames/ + truetype/ + type1/ + type1z/ + + + Compiling a module is now much easier, for example, the following + should work when in the TOP_DIR directory on an ANSI build: + + gcc -c -I./include -I./src/base src/base/ftbase.c + gcc -c -I./include -I./src/sfnt src/sfnt/sfnt.c + etc.. + + (of course, using -Iconfig/ if you provide system-specific + configuration files). + + - updated the structure of FT_Outline_Funcs in order to allow direct + coordinate scaling within the outline decomposition routine (this + is important for virtual "on" points with TrueType outlines) + + updates to the rasters to support this.. + + - updated the OS/2 table loading code in "src/sfnt/ttload.c" in + order to support version 2 of the table (see OpenType 1.2 spec) + + - created "include/tttables.h" and "include/t1tables.h" to allow + client applications to access some of the SFNT and T1 tables of a + face with a procedural interface (see FT_Get_Sfnt_Table()) + + updates to internal source files to reflect the change.. + + - some cleanups in the source code to get rid of warnings when + compiling with the "-Wall -W -ansi -pedantic" options in gcc. + + - debugged and moved the smooth renderer to "src/base/ftgrays.c" and + its header to "include/ftgrays.h" + + - updated TT_MAX_SUBGLYPHS to 96 as some CJK fonts have composites + with up to 80 sub-glyphs !! Thanks to Werner + + +====================================================================== + +OLD CHANGES - 14-apr-2000 + + - fixed a bug in the TrueType glyph loader that prevented the + correct loading of some CJK glyphs in mingli.ttf + + - improved the standard Type 1 hinter in "src/type1" + + - fixed two bugs in the experimental Type 1 driver in "src/type1z" + to handle the new XFree86 4.0 fonts (and a few other ones..) + + - the smooth renderer is now complete and supports sub-banding to + render large glyphs at high speed. However, it is still located + in "demos/src/ftgrays.c" and should move to the library itself in + the next beta. NOTE: The smooth renderer doesn't compile in + stand-alone mode anymore, but this should be fixed RSN.. + + - introduced convenience functions to more easily deal with glyph + images, see "include/ftglyph.h" for more details, as well as the + new demo program named "demos/src/ftstring.c" that demonstrates + its use + + - implemented FT_LOAD_NO_RECURSE in both the TrueType and Type 1 + drivers (this is required by the auto-hinter to improve its + results). + + - changed the raster interface, in order to allow client + applications to provide their own span-drawing callbacks. + However, only the smooth renderer supports this. See + "FT_Raster_Params" in the file "include/ftimage.h". + + - fixed a small bug in FT_MulFix that caused incorrect transform + computation! + + - Note: The tutorial is out-of-date. + + +====================================================================== + +OLD CHANGES - 12-mar-2000 + + - changed the layout of configuration files : now, all ANSI + configuration files are located in + "freetype2/config". System-specific over-rides can be placed in + "freetype2/config/". + + - moved all configuration macros to "config/ftoption.h" + + - improvements in the Type 1 driver with AFM support + + - changed the fields in the FT_Outline structure : the old "flags" + array is re-named "tags", while all ancient flags are encoded into + a single unsigned int named "flags". + + - introduced new flags in FT_Outline.flags (see + ft_outline_.... enums in "ftimage.h"). + + - changed outline functions to "FT_Outline_" syntax + + - added a smooth anti-alias renderer to the demonstration programs + + - added Mac graphics driver (thanks Just) + + - FT_Open_Face changed in order to received a pointer to a + FT_Open_Args descriptor.. + + - various cleanups, a few more API functions implemented (see + FT_Attach_File) + + - updated some docs + + +====================================================================== + +OLD CHANGES - 22-feb-2000 + + - introduced the "psnames" module. It is used to: + + o convert a Postscript glyph name into the equivalent Unicode + character code (used by the Type 1 driver(s) to synthetize on + the fly a Unicode charmap). + + o provide an interface to retrieve the Postscript names of the + Macintosh, Adobe Standard & Adobe Expert character codes. + (the Macintosh names are used by the SFNT-module postscript + names support routines, while the other two tables are used by + the Type 1 driver(s)). + + - introduced the "type1z" alternate Type 1 driver. This is a (still + experimental) driver for the Type 1 format that will ultimately + replace the one in "src/type1". It uses pattern matching to load + data from the font, instead of a finite state analyzer. It works + much better than the "old" driver with "broken" fonts. It is also + much smaller (under 15 Kb). + + - the Type 1 drivers (both in "src/type1" and "src/type1z") are + nearly complete. They both provide automatic Unicode charmap + synthesis through the "psnames" module. No re-encoding vector is + needed. (note that they still leak memory due to some code + missing, and I'm getting lazy). + + Trivial AFM support has been added to read kerning information but + wasn't exactly tested as it should ;-) + + - The TrueType glyph loader has been seriously rewritten (see the + file "src/truetype/ttgload.c". It is now much, much simpler as + well as easier to read, maintain and understand :-) Preliminary + versions introduced a memory leak that has been reported by Jack + Davis, and is now fixed.. + + - introduced the new "ft_glyph_format_plotter", used to represent + stroked outlines like Windows "Vector" fonts, and certain Type 1 + fonts like "Hershey". The corresponding raster will be written + soon. + + - FT_New_Memory_Face is gone. Likewise, FT_Open_Face has a new + interface that uses a structure to describe the input stream, the + driver (if required), etc.. + + +TODO + + - Write FT_Get_Glyph_Bitmap and FT_Load_Glyph_Bitmap + + - Add a function like FT_Load_Character( face, char_code, load_flags + ) that would really embbed a call to FT_Get_Char_Index then + FT_Load_Glyph to ease developer's work. + + - Update the tutorial! + + - consider adding support for Multiple Master fonts in the Type 1 + drivers. + + - Test the AFM routines of the Type 1 drivers to check that kerning + information is returned correctly. + + - write a decent auto-gridding component !! We need this to release + FreeType 2.0 gold ! + + +less urgent needs: + + - add a CFF/Type2 driver + - add a BDF driver + - add a FNT/PCF/HBF driver + - add a Speedo driver from the X11 sources + + +====================================================================== + +OLDER CHANGES - 27-jan-2000 + + - updated the "sfnt" module interface to allow several SFNT-based + drivers to co-exist peacefully + + - updated the "T1_Face" type to better separate Postscript font + content from the rest of the FT_Face structure. Might be used + later by the CFF/Type2 driver.. + + - added an experimental replacement Type 1 driver featuring advanced + (and speedy) pattern matching to retrieve the data from postscript + fonts. + + - very minor changes in the implementation of FT_Set_Char_Size and + FT_Set_Pixel_Sizes (they now implement default to ligthen the font + driver's code). + + +====================================================================== + +OLD MESSAGE + +This file summarizes the changes that occured since the last "beta" of +FreeType 2. Because the list is important, it has been divided into +separate sections: + +Table Of Contents: + + I High-Level Interface (easier !) + II Directory Structure + III Glyph Image Formats + IV Build System + V Portability + VI Font Drivers + + +---------------------------------------------------------------------- + +High-Level Interface: + + The high-level API has been considerably simplified. Here is how: + + - resource objects have disappeared. this means that face objects + can now be created with a single function call (see FT_New_Face + and FT_Open_Face) + + - when calling either FT_New_Face & FT_Open_Face, a size object + and a glyph slot object are automatically created for the face, + and can be accessed through "face->glyph" and "face->size" if + one really needs to. In most cases, there's no need to call + FT_New_Size or FT_New_Glyph. + + - similarly, FT_Load_Glyph now only takes a "face" argument + (instead of a glyph slot and a size). Also, it's "result" + parameter is gone, as the glyph image type is returned in the + field "face->glyph.format" + + - the list of available charmaps is directly accessible through + "face->charmaps", counting "face->num_charmaps" elements. Each + charmap has an 'encoding' field which specifies which known + encoding it deals with. Valid values are, for example: + + ft_encoding_unicode (for ASCII, Latin-1 and Unicode) + ft_encoding_apple_roman + ft_encoding_sjis + ft_encoding_adobe_standard + ft_encoding_adobe_expert + + other values may be added in the future. Each charmap still + holds its "platform_id" and "encoding_id" values in case the + encoding is too exotic for the current library + + +---------------------------------------------------------------------- + +Directory Structure: + + Should seem obvious to most of you: + + freetype/ + config/ -- configuration sub-makefiles + ansi/ + unix/ -- platform-specific configuration files + win32/ + os2/ + msdos/ + + include/ -- public header files, those to be included + directly by client apps + + src/ -- sources of the library + base/ -- the base layer + sfnt/ -- the sfnt "driver" (see the drivers section + below) + truetype/ -- the truetype driver + type1/ -- the type1 driver + shared/ -- some header files shared between drivers + + demos/ -- demos/tools + + docs/ -- documentation (a bit empty for now) + + +---------------------------------------------------------------------- + +Glyph Image Formats: + + Drivers are now able to register new glyph image formats within the + library. For now, the base layer supports of course bitmaps and + vector outlines, but one could imagine something different like + colored bitmaps, bi-color vectors or wathever else (Metafonts anyone + ??). + + See the file `include/ftimage.h'. Note also that the type + FT_Raster_Map is gone, and is now replaced by FT_Bitmap, which + should encompass all known bitmap types. + + Each new image format must provide at least one "raster", i.e. a + module capable of transforming the glyph image into a bitmap. It's + also possible to change the default raster used for a given glyph + image format. + + The default outline scan-converter now uses 128 levels of grays by + default, which tends to smooth many things. Note that the demo + programs have been updated significantly in order to display these.. + + +---------------------------------------------------------------------- + +Build system: + + You still need GNU Make to build the library. The build system has + been very seriously re-vamped in order to provide things like : + + - automatic host platform detection (reverting to 'config/ansi' if + it is not detected, with pseudo-standard compilation flags) + + - the ability to compile from the Makefiles with very different and + exotic compilers. Note that linking the library can be difficult + for some platforms. + + For example, the file `config/win32/lcclib.bat' is invoked by the + build system to create the ".lib" file with LCC-Win32 because its + librarian has too many flaws to be invoked directly from the + Makefile. + + Here's how it works: + + - the first time you type `make', the build system runs a series of + sub-makefiles in order to detect your host platform. It then + dumps what it found, and creates a file called `config.mk' in the + current directory. This is a sub-Makefile used to define many + important Make variables used to build the library. + + - the second time, the build system detects the `config.mk' then use + it to build the library. All object files go into 'obj' by + default, as well as the library file, but this can easily be + changed. + + Note that you can run "make setup" to force another host platform + detection even if a `config.mk' is present in the current + directory. Another solution is simply to delete the file, then + re-run make. + + Finally, the default compiler for all platforms is gcc (for now, + this will hopefully changed in the future). You can however specify + a different compiler by specifying it after the 'setup' target as + in: + + gnumake setup lcc on Win32 to use the LCC compiler + gnumake setup visualc on Win32 to use Visual C++ + + See the file `config//detect.mk' for a list of supported + compilers for your platforms. + + It should be relatively easy to write new detection rules files and + config.mk.. + + Finally, to build the demo programs, go to `demos' and launch GNU + Make, it will use the `config.mk' in the top directory to build the + test programs.. + + +---------------------------------------------------------------------- + +Portability: + + In the previous beta, a single FT_System object was used to + encompass all low-level operations like thread synchronisation, + memory management and i/o access. This has been greatly simplified: + + - thread synchronisation has been dropped, for the simple reason + that the library is already re-entrant, and that if you really + need two threads accessing the same FT_Library, you should + really synchronize access to it yourself with a simple mutex. + + - memory management is performed through a very simple object + called "FT_Memory", which really is a table containing a table + of pointers to functions like malloc, realloc and free as well + as some user data (closure). + + - resources have disappeared (they created more problems than they + solved), and i/o management have been simplified greatly as a + result. Streams are defined through FT_Stream objects, which + can be either memory-based or disk-based. + + Note that each face has its own stream, which is closed only + when the face object is destroyed. Hence, a function like + TT_Flush_Face in 1.x cannot be directly supported. However, if + you really need something like this, you can easily tailor your + own streams to achieve the same feature at a lower level (and + use FT_Open_Face instead of FT_New_Face to create the face). + + See the file "include/ftsystem.h" for more details, as well as the + implementations found in "config/unix" and "config/ansi". + + +---------------------------------------------------------------------- + +Font Drivers: + + The Font Driver interface has been modified in order to support + extensions & versioning. + + + The list of the font drivers that are statically linked to the + library at compile time is managed through a new configuration file + called `config//ftmodule.h'. + + This file is autogenerated when invoking `make modules'. This + target will parse all sub-directories of 'src', looking for a + "module.mk" rules file, used to describe the driver to the build + system. + + Hence, one should call `make modules' each time a font driver is + added or removed from the `src' directory. + + Finally, this version provides a "pseudo-driver" in `src/sfnt'. + This driver doesn't support font files directly, but provides + services used by all TrueType-like font drivers. Hence, its code is + shared between the TrueType & OpenType font formats, and possibly + more formats to come if we're lucky.. + + +---------------------------------------------------------------------- + +Extensions support: + + The extensions support is inspired by the one found in 1.x. + + Now, each font driver has its own "extension registry", which lists + which extensions are available for the font faces managed by the + driver. + + Extension ids are now strings, rather than 4-byte tags, as this is + usually more readable. + + Each extension has: + - some data, associated to each face object + - an interface (table of function pointers) + + An extension that is format-specific should simply register itself + to the correct font driver. Here is some example code: + + // Registering an extensions + // + FT_Error FT_Init_XXXX_Extension( FT_Library library ) + { + FT_DriverInterface* tt_driver; + + driver = FT_Get_Driver( library, "truetype" ); + if (!driver) return FT_Err_Unimplemented_Feature; + + return FT_Register_Extension( driver, &extension_class ); + } + + + // Implementing the extensions + // + FT_Error FT_Proceed_Extension_XXX( FT_Face face ) + { + FT_XXX_Extension ext; + FT_XXX_Extension_Interface ext_interface; + + ext = FT_Get_Extension( face, "extensionid", &ext_interface ); + if (!ext) return error; + + return ext_interface->do_it(ext); + } + +--- end of CHANGES --- diff --git a/Utilities/vtkfreetype/docs/CUSTOMIZE b/Utilities/vtkfreetype/docs/CUSTOMIZE new file mode 100644 index 0000000..8709b3d --- /dev/null +++ b/Utilities/vtkfreetype/docs/CUSTOMIZE @@ -0,0 +1,125 @@ +How to customize the compilation of the library: +================================================ + + FreeType is highly customizable to fit various needs, and this + document describes how it is possible to select options and components + at compilation time. + + +I. Configuration macros + + The file found in "include/freetype/config/ftoption.h" contains a list + of commented configuration macros that can be toggled by developers to + indicate which features should be active while building the library. + + These options range from debug level to availability of certain + features, like native TrueType hinting through a bytecode interpreter. + + We invite you to read this file for more information. You can change + the file's content to suit your needs, or override it with one of the + techniques described below. + + +II. Modules list + + The file found in "include/freetype/config/ftmodule.h" contains a list + of names corresponding to the modules and font drivers to be + statically compiled in the FreeType library during the build. + + You can change it to suit your own preferences. Be aware that certain + modules depend on others, as described by the file "modules.txt" in + this directory. + + You can modify the file's content to suit your needs, or override it + at compile time with one of the methods described below. + + +III. System interface + + FreeType's default interface to the system (i.e., the parts that deal + with memory management and i/o streams) is located in + "src/base/ftsystem.c". + + The current implementation uses standard C library calls to manage + memory and to read font files. It is however possible to write custom + implementations to suit specific systems. + + To tell the GNU Make-based build system to use a custom system + interface, you have to define the environment variable FTSYS_SRC to + point to the relevant implementation: + + on Unix: + + ./configure + export FTSYS_SRC=foo/my_ftsystem.c + make + make install + + on Windows: + + make setup + set FTSYS_SRC=foo/my_ftsystem.c + make + + +IV. Overriding default configuration and module headers + + It is possible to override the default configuration and module + headers without changing the original files. There are two ways to do + that: + + + 1. Using the C include path + + Use the C include path to ensure that your own versions of the files + are used at compile time when the lines + + #include FT_CONFIG_OPTIONS_H + #include FT_CONFIG_MODULES_H + + are compiled. Their default values being + and , you + can do something like: + + custom/ + freetype/ + config/ + ftoption.h => custom options header + ftmodule.h => custom modules list + + include/ => normal FreeType 2 include + freetype/ + ... + + then change the C include path to always give the path to "custom" + before the FreeType 2 "include". + + + 2. Re-defining FT_CONFIG_OPTIONS_H and FT_CONFIG_MODULES_H + + Another way to do the same thing is to redefine the macros used to + name the configuration headers. To do so, you need a custom + "ft2build.h" whose content can be as simple as: + + #ifndef __FT2_BUILD_MY_PLATFORM_H__ + #define __FT2_BUILD_MY_PLATFORM_H__ + + #define FT_CONFIG_OPTIONS_H + #define FT_CONFIG_MODULES_H + + #include + + #endif /* __FT2_BUILD_MY_PLATFORM_H__ */ + + Place those files in a separate directory, e.g.: + + custom/ + ft2build.h => custom version described above + my-ftoption.h => custom options header + my-ftmodule.h => custom modules list header + + and change the C include path to ensure that "custom" is always + placed before the FT2 "include" during compilation. + + +--- end of CUSTOMIZE --- diff --git a/Utilities/vtkfreetype/docs/DEBUG b/Utilities/vtkfreetype/docs/DEBUG new file mode 100644 index 0000000..c85ef3c --- /dev/null +++ b/Utilities/vtkfreetype/docs/DEBUG @@ -0,0 +1,183 @@ +Debugging within the FreeType sources +===================================== + +I. Configuration macros +----------------------- + +There are several ways to enable debugging features in a FreeType 2 +builds. This is controlled through the definition of special macros +located in the file "ftoptions.h". The macros are: + + + FT_DEBUG_LEVEL_ERROR + + #define this macro if you want to compile the FT_ERROR macro calls + to print error messages during program execution. This will not + stop the program. Very useful to spot invalid fonts during + development and to code workarounds for them. + + FT_DEBUG_LEVEL_TRACE + + #define this macro if you want to compile both macros FT_ERROR and + FT_TRACE. This also includes the variants FT_TRACE0, FT_TRACE1, + FT_TRACE2, ..., FT_TRACE6. + + The trace macros are used to send debugging messages when an + appropriate "debug level" is configured at runtime through the + FT2_DEBUG environment variable (more on this later). + + FT_DEBUG_MEMORY + + If this macro is #defined, the FreeType engine is linked with a + small but effective debugging memory manager that tracks all + allocations and frees that are performed within the font engine. + + When the FT2_DEBUG_MEMORY environment variable is defined at + runtime, a call to FT_Done_FreeType will dump memory statistics, + including the list of leaked memory blocks with the source locations + where these were allocated. It is always a very good idea to define + this in development builds. This works with _any_ program linked to + FreeType, but requires a big deal of memory (the debugging memory + manager never frees the blocks to the heap in order to detect double + frees). + + When FT2_DEBUG_MEMORY isn't defined at runtime, the debugging memory + manager is ignored, and performance is unaffected. + + +II. Debugging macros +-------------------- + +Several macros can be used within the FreeType sources to help debugging +its code: + + 1. FT_ERROR(( ... )) + + This macro is used to send debug messages that indicate relatively + serious errors (like broken font files), but will not stop the + execution of the running program. Its code is compiled only when + either FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined in + "ftoption.h". + + Note that you have to use a printf-like signature, but with double + parentheses, like in: + + FT_ERROR(( "your %s is not %s\n", "foo", "bar" )); + + + 2. FT_ASSERT( condition ) + + This macro is used to check strong assertions at runtime. If its + condition isn't TRUE, the program will abort with a panic message. + Its code is compiled when either FT_DEBUG_LEVEL_ERROR or + FT_DEBUG_LEVEL_TRACE are defined. You don't need double-parentheses + here. For example: + + FT_ASSERT( ptr != NULL ); + + + 3. FT_TRACE( level, (message...) ) + + The FT_TRACE macro is used to send general-purpose debugging + messages during program execution. This macro uses an *implicit* + macro named FT_COMPONENT used to name the current FreeType component + being run. + + The developer should always define FT_COMPONENT as appropriate, for + example as in: + + #undef FT_COMPONENT + #define FT_COMPONENT trace_io + + The value of the FT_COMPONENT macro is an enumeration named + trace_XXXX where XXXX is one of the component names defined in the + internal file . + + Each such component is assigned a "debug level", ranging from 0 + to 6, through the use of the FT2_DEBUG environment variable + (described below) when a program linked with FreeType starts. + + When FT_TRACE is called, its level is compared to the one of the + corresponding component. Messages with trace levels *higher* than + the corresponding component level are filtered and never printed. + + This means that trace messages with level 0 are always printed, + those with level 2 are only printed when the component level is *at + least* 2. + + The second parameter to FT_TRACE must contain parentheses and + correspond to a printf-like call, as in: + + FT_TRACE( 2, ( "your %s is not %s\n", "foo", "bar" ) ) + + The shortcut macros FT_TRACE0, FT_TRACE1, FT_TRACE2_, ... FT_TRACE6 + can be used with constant level indices, and are much cleaner to + use, as in + + FT_TRACE2(( "your %s is not %s\n", "foo", "bar" )); + + +III. Environment variables +-------------------------- + +The following environment variables control debugging output and +behaviour of FreeType at runtime: + + FT2_DEBUG + + This variable is only used when FreeType is built with + FT_DEBUG_LEVEL_TRACE defined. It contains a list of component level + definitions, following this format: + + component1:level1 component2:level2 component3:level3 ... + + where "componentX" is the name of a tracing component, as defined in + "fttrace.h", but without the "trace_" prefix. "levelX" is the + corresponding level to use at runtime. + + "any" is a special component name that will be interpreted as + "any/all components". For example, the following definitions + + set FT2_DEBUG=any:2 memory:5 io:4 (on Windows) + export FT2_DEBUG="any:2 memory:5 io:4" (on Linux with bash) + + both stipulate that all components should have level 2, except for + the memory and io components which will be set to trace levels 5 + and 4, respectively. + + FT2_DEBUG_MEMORY + + This environment variable, when defined, tells FreeType to use a + debugging memory manager that will track leaking memory blocks as + well as other common errors like double frees. It is also capable + of reporting _where_ the leaking blocks were allocated, which + considerably saves time when debugging new additions to the library. + + This code is only compiled when FreeType is built with the + FT_DEBUG_MEMORY macro #defined in "ftoption.h" though, it will be + ignored in other builds. + + FT2_ALLOC_TOTAL_MAX + + This variable is ignored if FT2_DEBUG_MEMORY is not defined. It + allows you to specify a maximum heap size for all memory allocations + performed by FreeType. This is very useful to test the robustness + of the font engine and programs that use it in tight memory + conditions. + + If it is undefined, or if its value is not strictly positive, then + no allocation bounds are checked at runtime. + + FT2_ALLOC_COUNT_MAX + + This variable is ignored if FT2_DEBUG_MEMORY is not defined. It + allows you to specify a maximum number of memory allocations + performed by FreeType before returning the error + FT_Err_Out_Of_Memory. This is useful for debugging and testing the + engine's robustness. + + If it is undefined, or if its value is not strictly positive, then + no allocation bounsd are checked at runtime. + + +--- end of DEBUG --- diff --git a/Utilities/vtkfreetype/docs/FTL.txt b/Utilities/vtkfreetype/docs/FTL.txt new file mode 100644 index 0000000..0967302 --- /dev/null +++ b/Utilities/vtkfreetype/docs/FTL.txt @@ -0,0 +1,174 @@ + The FreeType Project LICENSE + ---------------------------- + + 2002-Apr-11 + + Copyright 1996-2002 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright © 1996-2002 The FreeType + Project (www.freetype.org). All rights reserved. + """ + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@freetype.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o devel@freetype.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + o http://www.freetype.org + + Holds the current FreeType web page, which will allow you to + download our latest development version and read online + documentation. + + You can also contact us individually at: + + David Turner + Robert Wilhelm + Werner Lemberg + + +--- end of LICENSE.TXT --- diff --git a/Utilities/vtkfreetype/docs/INSTALL b/Utilities/vtkfreetype/docs/INSTALL new file mode 100644 index 0000000..8fb6657 --- /dev/null +++ b/Utilities/vtkfreetype/docs/INSTALL @@ -0,0 +1,67 @@ + +There are several ways to build the FreeType library, depending on your +system and the level of customization you need. Here is a short +overview of the documentation available: + + +I. Normal installation and upgrades +=================================== + + 1. Native TrueType Hinting + + Native TrueType hinting is disabled by default[1]. If you really + need it, read the file "TRUETYPE" for information. + + 2. Unix Systems (as well as Cygwin or MSys on Windows) + + Please read *both* UPGRADE.UNX and INSTALL.UNX to install or upgrade + FreeType 2 on a Unix system. Note that you *will* need GNU Make, + since other make tools won't work (this includes BSD Make). + + 3. On VMS with the "mms" build tool + + See INSTALL.VMS for installation instructions on this platform. + + 4. Other systems using GNU Make + + On non-Unix platforms, it is possible to build the library using GNU + Make utility. Note that *NO OTHER MAKE TOOL WILL WORK*[2]! This + methods supports several compilers on Windows, OS/2, and BeOS, + including Mingw, Visual C++, Borland C++, and more. + + Instructions are provided in the file "INSTALL.GNU". + + 5. With an IDE Project File (e.g. for Visual Studio or CodeWarrior) + + We provide a small number of "project files" for various IDEs to + automatically build the library as well. Note that these files are + not supported and sporadically maintained by FreeType developers, so + don't expect them to work in each release. + + To find them, have a look at the content of the "builds/" + directory, where stands for your OS or environment. + + 6. From you own IDE, or own Makefiles + + If you want to create your own project file, follow the instructions + given in the "INSTALL.ANY" document of this directory. + + +II. Custom builds of the library +================================ + + Customizing the compilation of FreeType is easy, and allows you to + select only the components of the font engine that you really need. + For more details read the file "CUSTOMIZE". + + +------------------------------------------------------------------------ + +[1] More details on: http://www.freetype.org/patents.html + +[2] make++, a make tool written in Perl, has sufficient support of GNU + make extensions to build FreeType. See + http://makepp.sourceforge.net for more information; you need version + 1.19 or newer, and you must pass option `--norc-substitution'. + +--- end of INSTALL --- diff --git a/Utilities/vtkfreetype/docs/INSTALL.ANY b/Utilities/vtkfreetype/docs/INSTALL.ANY new file mode 100644 index 0000000..af3f6e7 --- /dev/null +++ b/Utilities/vtkfreetype/docs/INSTALL.ANY @@ -0,0 +1,99 @@ +Instructions on how to build FreeType with your own build tool +============================================================== + +See the file "CUSTOMIZE" to learn how to customize FreeType to specific +environments. + + +I. Standard procedure +--------------------- + + * DISABLE PRE-COMPILED HEADERS! This is very important for Visual + C++, because FreeType uses lines like: + + #include FT_FREETYPE_H + + which are not correctly supported by this compiler while being ISO C + compliant! + + * You need to add the directories "freetype2/include" to your include + path when compiling the library. + + * FreeType 2 is made of several components; each of them is located in + a subdirectory of "freetype2/src". For example, + 'freetype2/src/truetype/' contains the TrueType font driver. + + * DO NOT COMPILE ALL C FILES! Rather, compile the following ones: + + -- base components (required) + + src/base/ftsystem.c + src/base/ftinit.c + src/base/ftdebug.c + src/base/ftbase.c + src/base/ftglyph.c + src/base/ftbbox.c + src/base/ftmm.c + src/base/ftpfr.c -- optional, see + src/base/ftbdf.c -- optional, see + src/base/ftwinfnt.c -- optional, see + + src/base/ftmac.c -- only on the Macintosh + + -- other components (optional) + + src/autohint/autohint.c -- auto hinting module + src/cache/ftcache.c -- cache sub-system (in beta) + src/sfnt/sfnt.c -- SFNT files support + (TrueType & OpenType) + src/cff/cff.c -- CFF/OpenType font driver + src/pfr/pfr.c -- PFR/TrueDoc font driver + src/bdf/bdf.c -- BDF font driver + src/pcf/pcf.c -- PCF font driver + src/psnames/psnames.c -- PostScript glyph names support + src/psaux/psaux.c -- PostScript Type 1 parsing + src/truetype/truetype.c -- TrueType font driver + src/type1/type1.c -- Type 1 font driver + src/cid/type1cid.c -- Type 1 CID-keyed font driver + src/winfonts/winfonts.c -- Windows FONT / FNT font driver + src/raster1/raster1.c -- monochrome rasterizer + src/smooth/smooth.c -- anti-aliasing rasterizer + + Notes: + + `truetype.c' needs `sfnt.c' and `psnames.c' + `type1.c' needs `psaux.c' and `psnames.c' + `type1cid.c' needs `psaux.c' and `psnames.c' + `cff.c' needs `sfnt.c', `psaux.c', and `psnames.c' + + + You are done. In case of problems, see the archives of the FreeType + development mailing list. + + +II. Support for flat-directory compilation +------------------------------------------ + + It is possible to put all FreeType 2 source files into a single + directory, with the *exception* of the `include' hierarchy. + + 1. Copy all files in current directory + + cp freetype2/src/base/*.[hc] . + cp freetype2/src/raster1/*.[hc] . + cp freetype2/src/smooth/*.[hc] . + etc. + + 2. Compile sources + + cc -c -Ifreetype2/include ftsystem.c + cc -c -Ifreetype2/include ftinit.c + cc -c -Ifreetype2/include ftdebug.c + cc -c -Ifreetype2/include ftbase.c + etc. + + You don't need to define the FT_FLAT_COMPILATION macro (as this was + required in previous releases of FreeType 2). + + +--- end of INSTALL.ANY --- diff --git a/Utilities/vtkfreetype/docs/INSTALL.GNU b/Utilities/vtkfreetype/docs/INSTALL.GNU new file mode 100644 index 0000000..4a56d6d --- /dev/null +++ b/Utilities/vtkfreetype/docs/INSTALL.GNU @@ -0,0 +1,140 @@ +This document contains instructions how to build the FreeType library on +non-Unix systems with the help of GNU Make. Note that if you are +running Cygwin or MSys in Windows, you should follow the instructions in +the file INSTALL.UNX instead. + + + FreeType 2 includes a powerful and flexible build system that allows + you to easily compile it on a great variety of platforms from the + command line. To do so, just follow these simple instructions: + + 1. Install GNU Make + ------------------- + + Because GNU Make is the only Make tool supported to compile + FreeType 2, you should install it on your machine. + + The FreeType 2 build system relies on many features special to GNU + Make -- trying to build the library with any other Make tool will + *fail*. + + NEARLY ALL OTHER MAKE TOOLS WILL FAIL, INCLUDING "BSD MAKE", SO + REALLY INSTALL A RECENT VERSION OF GNU MAKE ON YOUR SYSTEM! + + Note that make++, a make tool written in Perl, supports enough + features of GNU make to compile FreeType. See + http://makepp.sourceforge.net for more information; you need version + 1.19 or newer, and you must pass option `--norc-substitution'. + + Make sure that you are invoking GNU Make from the command line, by + typing something like: + + make -v + + to display its version number. + + VERSION 3.78.1 OR NEWER IS NEEDED! + + + 2. Invoke 'make' + ---------------- + + Go to the root directory of FreeType 2, then simply invoke GNU Make + from the command line. This will launch the FreeType 2 host + platform detection routines. A summary will be displayed, for + example, on Win32: + + + ============================================================== + FreeType build system -- automatic system detection + + The following settings are used: + + platform win32 + compiler gcc + configuration directory ./builds/win32 + configuration rules ./builds/win32/w32-gcc.mk + + If this does not correspond to your system or settings please + remove the file 'config.mk' from this directory then read the + INSTALL file for help. + + Otherwise, simply type 'make' again to build the library. + ============================================================= + + + If the detected settings correspond to your platform and compiler, + skip to step 5. Note that if your platform is completely alien to + the build system, the detected platform will be 'ansi'. + + + 3. Configure the build system for a different compiler + ------------------------------------------------------ + + If the build system correctly detected your platform, but you want + to use a different compiler than the one specified in the summary + (for most platforms, gcc is the defaut compiler), invoke GNU Make + with + + make setup + + Examples: + + to use Visual C++ on Win32, type: "make setup visualc" + to use Borland C++ on Win32, type "make setup bcc32" + to use Watcom C++ on Win32, type "make setup watcom" + to use Intel C++ on Win32, type "make setup intelc" + to use LCC-Win32 on Win32, type: "make setup lcc" + to use Watcom C++ on OS/2, type "make setup watcom" + to use VisualAge C++ on OS/2, type "make setup visualage" + + The name to use is platform-dependent. The list of + available compilers for your system is available in the file + `builds//detect.mk' + + If you are satisfied by the new configuration summary, skip to + step 5. + + + 4. Configure the build system for an unknown platform/compiler + -------------------------------------------------------------- + + The auto-detection/setup phase of the build system copies a file to + the current directory under the name `config.mk'. + + For example, on OS/2+gcc, it would simply copy + `builds/os2/os2-gcc.mk' to `./config.mk'. + + If for some reason your platform isn't correctly detected, copy + manually the configuration sub-makefile to `./config.mk' and go to + step 5. + + Note that this file is a sub-Makefile used to specify Make variables + for compiler and linker invocation during the build. You can easily + create your own version from one of the existing configuration + files, then copy it to the current directory under the name + `./config.mk'. + + + 5. Build the library + -------------------- + + The auto-detection/setup phase should have copied a file in the + current directory, called `./config.mk'. This file contains + definitions of various Make variables used to invoke the compiler + and linker during the build. + + To launch the build, simply invoke GNU Make again: The top Makefile + will detect the configuration file and run the build with it. + + + Final note + + The build system builds a statically linked library of the font + engine in the "objs" directory. It does _not_ support the build of + DLLs on Windows and OS/2. If you need these, you have to either use + a IDE-specific project file, or follow the instructions in + "INSTALL.ANY" to create your own Makefiles. + + +--- end of INSTALL.GNU --- diff --git a/Utilities/vtkfreetype/docs/PATENTS b/Utilities/vtkfreetype/docs/PATENTS new file mode 100644 index 0000000..717bb7d --- /dev/null +++ b/Utilities/vtkfreetype/docs/PATENTS @@ -0,0 +1,27 @@ + + FreeType Patents Disclaimer + August 1999 + + + +WE HAVE DISCOVERED THAT APPLE OWNS SEVERAL PATENTS RELATED TO THE +RENDERING OF TRUETYPE FONTS. THIS COULD MEAN THAT THE FREE USE OF +FREETYPE MIGHT BE ILLEGAL IN THE USA, JAPAN, AND POSSIBLY OTHER +COUNTRIES, BE IT IN COMMERCIAL OR OPEN SOURCE PRODUCTS. + +FOR MORE DETAILS, WE STRONGLY ADVISE YOU TO GO TO THE FREETYPE +PATENTS PAGE AT THE FOLLOWING WEB ADDRESS: + + http://www.freetype.org/patents.html + +WE WILL NOT PLACE INFORMATION IN THIS FILE AS THE SITUATION IS STILL +UNDETERMINED FOR NOW. AT THE TIME THESE LINES ARE WRITTEN, WE HAVE +CONTACTED APPLE'S LEGAL DEPARTMENT AND ARE STILL WAITING FOR THEIR +ANSWER ON THE SUBJECT. + +PLEASE READ THE `INSTALL' FILE TO SEE HOW TO DISABLE THE ENGINE'S +BYTECODE INTERPRETER IN ORDER TO BUILD A PATENT-FREE ENGINE, AT THE +COST OF RENDERING QUALITY. + + +--- end of PATENTS --- diff --git a/Utilities/vtkfreetype/docs/VERSION.DLL b/Utilities/vtkfreetype/docs/VERSION.DLL new file mode 100644 index 0000000..9e27a57 --- /dev/null +++ b/Utilities/vtkfreetype/docs/VERSION.DLL @@ -0,0 +1,110 @@ +Due to our use of "libtool" to generate and install the FreeType 2 +libraries on Unix systems, as well as other historical events, it is +generally very difficult to know precisely which release of the font +engine is installed on a given system. + +This file tries to explain why and to document ways to properly detect +FreeType on Unix. + + +1. Version & Release numbers +---------------------------- + +For each new public release of FreeType 2, there are generally *three* +distinct "version" numbers to consider: + + * The official FT2 release number, like 2.0.9, or 2.1.3. + + * The libtool (and Unix) specific version number, like "9.2.3". This + is what "freetype-config --version" will return. + + * The platform-specific shared object number, used for example when + the library is installed as "/usr/lib/libfreetype.so.6.3.2". + +The platform-specific number is, unsurprisingly, platform-specific and +varies with the operating system you are using (several variants of +Linux, FreeBSD, Solaris, etc.). You should thus _never_ use it, even +for simple tests. + +The libtool-specific number does not equal the release number but is +tied to it. + +The release number is available at *compile* time through the following +macros defined in FT_FREETYPE_H: + + - FREETYPE_MAJOR : major release number + - FREETYPE_MINOR : minor release number + - FREETYPE_PATCH : patch release number + +See below for a small autoconf fragment. + +The release number is also available at *runtime* through the +"FT_Library_Version" API. Unfortunately, this one wasn't available or +working correctly before the 2.1.3 official release. + + +2. History +---------- + +The following table gives, for each official release, the corresponding +libtool number, as well as the shared object number found on _most_ +systems, but not all of them: + + release libtool so + ------------------------------- + 2.1.9 9.7.3 6.3.7 + 2.1.8 9.6.3 6.3.6 + 2.1.7 9.5.3 6.3.5 + 2.1.6 9.5.3 6.3.5 + 2.1.5 9.4.3 6.3.4 + 2.1.4 9.3.3 6.3.3 + 2.1.3 9.2.3 6.3.2 + 2.1.2 9.1.3 6.3.1 + 2.1.1 9.0.3 ? + 2.1.0 8.0.2 ? + 2.0.9 9.0.3 ? + 2.0.8 8.0.2 ? + 2.0.4 7.0.1 ? + 2.0.1 6.1.0 ? + +The libtool numbers are a bit inconsistent due to the library's history: + + - 2.1.0 was created as a development branch from 2.0.8 (hence the same + libtool numbers). + + - 2.0.9 was a bug-fix release of the "stable" branch, and we + incorrectly increased its libtool number. + + - 2.1.4 is still in the "development" branch, however it is stable + enough to be the basis of an upcoming 2.2.0 release. + + +3. Autoconf Code Fragment +------------------------- + +Lars Clausen contributed the following autoconf fragment to detect which +version of FreeType is installed on a system. This one tests for a +version that is at least 2.0.9; you should change it to check against +other release numbers. + + + AC_MSG_CHECKING([whether FreeType version is 2.0.9 or higher]) + old_CPPFLAGS="$CPPFLAGS" + CPPFLAGS=`freetype-config --cflags` + AC_TRY_CPP([ + +#include +#include FT_FREETYPE_H +#if (FREETYPE_MAJOR*1000 + FREETYPE_MINOR)*1000 + FREETYPE_PATCH < 2000009 +#error Freetype version too low. +#endif + ], + [AC_MSG_RESULT(yes) + FREETYPE_LIBS=`freetype-config --libs` + AC_SUBST(FREETYPE_LIBS) + AC_DEFINE(HAVE_FREETYPE,1,[Define if you have the FreeType2 library]) + CPPFLAGS="$old_CPPFLAGS"], + [AC_MSG_ERROR([Need FreeType library version 2.0.9 or higher])]) + + +--- end of VERSION.DLL --- diff --git a/Utilities/vtkfreetype/docs/license.txt b/Utilities/vtkfreetype/docs/license.txt new file mode 100644 index 0000000..876cc4b --- /dev/null +++ b/Utilities/vtkfreetype/docs/license.txt @@ -0,0 +1,28 @@ + +The FreeType 2 font engine is copyrighted work and cannot be used +legally without a software license. In order to make this project +usable to a vast majority of developers, we distribute it under two +mutually exclusive open-source licenses. + +This means that *you* must choose *one* of the two licenses described +below, then obey all its terms and conditions when using FreeType 2 in +any of your projects or products. + + - The FreeType License, found in the file `FTL.TXT', which is similar + to the original BSD license *with* an advertising clause that forces + you to explicitly cite the FreeType project in your product's + documentation. All details are in the license file. This license + is suited to products which don't use the GNU General Public + License. + + - The GNU General Public License version 2, found in `GPL.TXT' (any + later version can be used also), for programs which already use the + GPL. Note that the FTL is incompatible with the GPL due to its + advertisement clause. + +The contributed PCF driver comes with a license similar to that of the X +Window System. It is compatible to the above two licenses (see file +src/pcf/readme). + + +--- end of licence.txt --- diff --git a/Utilities/vtkfreetype/docs/modules.txt b/Utilities/vtkfreetype/docs/modules.txt new file mode 100644 index 0000000..04f4d12 --- /dev/null +++ b/Utilities/vtkfreetype/docs/modules.txt @@ -0,0 +1,14 @@ +This file shows the interdependencies of various FreeType modules. + +Note that the use of `psnames' can be controlled in ftconfig.h +(FT_CONFIG_OPTION_POSTSCRIPT_NAMES). + + module dependency + --------------------------------------- + cff sfnt, pshinter, psnames + cid psaux, pshinter, psnames + truetype sfnt + type1 psaux, pshinter, psnames + type42 truetype + psaux psnames + sfnt psnames diff --git a/Utilities/vtkfreetype/include/freetype/cache/ftccache.h b/Utilities/vtkfreetype/include/freetype/cache/ftccache.h new file mode 100644 index 0000000..7c7688d --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/cache/ftccache.h @@ -0,0 +1,272 @@ +/***************************************************************************/ +/* */ +/* ftccache.h */ +/* */ +/* FreeType internal cache interface (specification). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTCCACHE_H__ +#define __FTCCACHE_H__ + + +#include FT_CACHE_INTERNAL_MRU_H + +FT_BEGIN_HEADER + + /* handle to cache object */ + typedef struct FTC_CacheRec_* FTC_Cache; + + /* handle to cache class */ + typedef const struct FTC_CacheClassRec_* FTC_CacheClass; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CACHE NODE DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Each cache controls one or more cache nodes. Each node is part of */ + /* the global_lru list of the manager. Its `data' field however is used */ + /* as a reference count for now. */ + /* */ + /* A node can be anything, depending on the type of information held by */ + /* the cache. It can be an individual glyph image, a set of bitmaps */ + /* glyphs for a given size, some metrics, etc. */ + /* */ + /*************************************************************************/ + + /* structure size should be 20 bytes on 32-bits machines */ + typedef struct FTC_NodeRec_ + { + FTC_MruNodeRec mru; /* circular mru list pointer */ + FTC_Node link; /* used for hashing */ + FT_UInt32 hash; /* used for hashing too */ + FT_UShort cache_index; /* index of cache the node belongs to */ + FT_Short ref_count; /* reference count for this node */ + + } FTC_NodeRec; + + +#define FTC_NODE( x ) ( (FTC_Node)(x) ) +#define FTC_NODE_P( x ) ( (FTC_Node*)(x) ) + +#define FTC_NODE__NEXT(x) FTC_NODE( (x)->mru.next ) +#define FTC_NODE__PREV(x) FTC_NODE( (x)->mru.prev ) + + + /*************************************************************************/ + /* */ + /* These functions are exported so that they can be called from */ + /* user-provided cache classes; otherwise, they are really part of the */ + /* cache sub-system internals. */ + /* */ + + /* reserved for manager's use */ + FT_EXPORT( void ) + ftc_node_destroy( FTC_Node node, + FTC_Manager manager ); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CACHE DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* initialize a new cache node */ + typedef FT_Error + (*FTC_Node_NewFunc)( FTC_Node *pnode, + FT_Pointer query, + FTC_Cache cache ); + + typedef FT_ULong + (*FTC_Node_WeightFunc)( FTC_Node node, + FTC_Cache cache ); + + /* compare a node to a given key pair */ + typedef FT_Bool + (*FTC_Node_CompareFunc)( FTC_Node node, + FT_Pointer key, + FTC_Cache cache ); + + + typedef void + (*FTC_Node_FreeFunc)( FTC_Node node, + FTC_Cache cache ); + + typedef FT_Error + (*FTC_Cache_InitFunc)( FTC_Cache cache ); + + typedef void + (*FTC_Cache_DoneFunc)( FTC_Cache cache ); + + + typedef struct FTC_CacheClassRec_ + { + FTC_Node_NewFunc node_new; + FTC_Node_WeightFunc node_weight; + FTC_Node_CompareFunc node_compare; + FTC_Node_CompareFunc node_remove_faceid; + FTC_Node_FreeFunc node_free; + + FT_UInt cache_size; + FTC_Cache_InitFunc cache_init; + FTC_Cache_DoneFunc cache_done; + + } FTC_CacheClassRec; + + + /* each cache really implements a dynamic hash table to manage its nodes */ + typedef struct FTC_CacheRec_ + { + FT_UFast p; + FT_UFast mask; + FT_Long slack; + FTC_Node* buckets; + + FTC_CacheClassRec clazz; /* local copy, for speed */ + + FTC_Manager manager; + FT_Memory memory; + FT_UInt index; /* in manager's table */ + + FTC_CacheClass org_class; /* original class pointer */ + + } FTC_CacheRec; + + +#define FTC_CACHE( x ) ( (FTC_Cache)(x) ) +#define FTC_CACHE_P( x ) ( (FTC_Cache*)(x) ) + + + /* default cache initialize */ + FT_EXPORT( FT_Error ) + FTC_Cache_Init( FTC_Cache cache ); + + /* default cache finalizer */ + FT_EXPORT( void ) + FTC_Cache_Done( FTC_Cache cache ); + + /* Call this function to lookup the cache. If no corresponding + * node is found, a new one is automatically created. This function + * is capable of flushing the cache adequately to make room for the + * new cache object. + */ + FT_EXPORT( FT_Error ) + FTC_Cache_Lookup( FTC_Cache cache, + FT_UInt32 hash, + FT_Pointer query, + FTC_Node *anode ); + + FT_EXPORT( FT_Error ) + FTC_Cache_NewNode( FTC_Cache cache, + FT_UInt32 hash, + FT_Pointer query, + FTC_Node *anode ); + + /* Remove all nodes that relate to a given face_id. This is useful + * when un-installing fonts. Note that if a cache node relates to + * the face_id, but is locked (i.e., has 'ref_count > 0'), the node + * will _not_ be destroyed, but its internal face_id reference will + * be modified. + * + * The final result will be that the node will never come back + * in further lookup requests, and will be flushed on demand from + * the cache normally when its reference count reaches 0. + */ + FT_EXPORT( void ) + FTC_Cache_RemoveFaceID( FTC_Cache cache, + FTC_FaceID face_id ); + + +#ifdef FTC_INLINE + +#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ + FT_BEGIN_STMNT \ + FTC_Node *_bucket, *_pnode, _node; \ + FTC_Cache _cache = FTC_CACHE(cache); \ + FT_UInt32 _hash = (FT_UInt32)(hash); \ + FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \ + FT_UInt _idx; \ + \ + \ + error = 0; \ + node = NULL; \ + _idx = _hash & _cache->mask; \ + if ( _idx < _cache->p ) \ + _idx = _hash & ( _cache->mask*2 + 1 ); \ + \ + _bucket = _pnode = _cache->buckets + _idx; \ + for (;;) \ + { \ + _node = *_pnode; \ + if ( _node == NULL ) \ + goto _NewNode; \ + \ + if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) ) \ + break; \ + \ + _pnode = &_node->link; \ + } \ + \ + if ( _node != *_bucket ) \ + { \ + *_pnode = _node->link; \ + _node->link = *_bucket; \ + *_bucket = _node; \ + } \ + \ + { \ + FTC_Manager _manager = _cache->manager; \ + \ + \ + if ( _node != _manager->nodes_list ) \ + FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list, \ + (FTC_MruNode)_node ); \ + } \ + goto _Ok; \ + \ + _NewNode: \ + error = FTC_Cache_NewNode( _cache, _hash, query, &_node ); \ + \ + _Ok: \ + *(FTC_Node*)&(node) = _node; \ + FT_END_STMNT + +#else /* !FTC_INLINE */ + +#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \ + FT_BEGIN_STMNT \ + error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, \ + (FTC_Node*)&(node) ); \ + FT_END_STMNT + +#endif /* !FTC_INLINE */ + + /* */ + +FT_END_HEADER + + +#endif /* __FTCCACHE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/cache/ftccmap.h b/Utilities/vtkfreetype/include/freetype/cache/ftccmap.h new file mode 100644 index 0000000..a41989b --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/cache/ftccmap.h @@ -0,0 +1,216 @@ +/***************************************************************************/ +/* */ +/* ftccmap.h */ +/* */ +/* FreeType charmap cache (specification). */ +/* */ +/* Copyright 2000-2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTCCMAP_H__ +#define __FTCCMAP_H__ + +#include +#include FT_CACHE_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /*
*/ + /* cache_subsystem */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* @type: */ + /* FTC_CMapCache */ + /* */ + /* @description: */ + /* An opaque handle used to manager a charmap cache. This cache is */ + /* to hold character codes -> glyph indices mappings. */ + /* */ + typedef struct FTC_CMapCacheRec_* FTC_CMapCache; + + + /*************************************************************************/ + /* */ + /* @type: */ + /* FTC_CMapDesc */ + /* */ + /* @description: */ + /* A handle to an @FTC_CMapDescRec structure used to describe a given */ + /* charmap in a charmap cache. */ + /* */ + /* Each @FTC_CMapDesc describes which charmap (of which @FTC_FaceID) */ + /* we want to use in @FTC_CMapCache_Lookup. */ + /* */ + typedef struct FTC_CMapDescRec_* FTC_CMapDesc; + + + /*************************************************************************/ + /* */ + /* @enum: */ + /* FTC_CMapType */ + /* */ + /* @description: */ + /* The list of valid @FTC_CMapDesc types. They indicate how we want */ + /* to address a charmap within an @FTC_FaceID. */ + /* */ + /* @values: */ + /* FTC_CMAP_BY_INDEX :: */ + /* Address a charmap by its index in the corresponding @FT_Face. */ + /* */ + /* FTC_CMAP_BY_ENCODING :: */ + /* Use a @FT_Face charmap that corresponds to a given encoding. */ + /* */ + /* FTC_CMAP_BY_ID :: */ + /* Use an @FT_Face charmap that corresponds to a given */ + /* (platform,encoding) ID. See @FTC_CMapIdRec. */ + /* */ + typedef enum FTC_CMapType_ + { + FTC_CMAP_BY_INDEX = 0, + FTC_CMAP_BY_ENCODING = 1, + FTC_CMAP_BY_ID = 2 + + } FTC_CMapType; + + + /*************************************************************************/ + /* */ + /* @struct: */ + /* FTC_CMapIdRec */ + /* */ + /* @description: */ + /* A short structure to identify a charmap by a (platform,encoding) */ + /* pair of values. */ + /* */ + /* @fields: */ + /* platform :: The platform ID. */ + /* */ + /* encoding :: The encoding ID. */ + /* */ + typedef struct FTC_CMapIdRec_ + { + FT_UInt platform; + FT_UInt encoding; + + } FTC_CMapIdRec; + + + /*************************************************************************/ + /* */ + /* @struct: */ + /* FTC_CMapDescRec */ + /* */ + /* @description: */ + /* A structure to describe a given charmap to @FTC_CMapCache. */ + /* */ + /* @fields: */ + /* face_id :: @FTC_FaceID of the face this charmap belongs to. */ + /* */ + /* type :: The type of charmap, see @FTC_CMapType. */ + /* */ + /* u.index :: For @FTC_CMAP_BY_INDEX types, this is the charmap */ + /* index (within a @FT_Face) we want to use. */ + /* */ + /* u.encoding :: For @FTC_CMAP_BY_ENCODING types, this is the charmap */ + /* encoding we want to use. see @FT_Encoding. */ + /* */ + /* u.id :: For @FTC_CMAP_BY_ID types, this is the */ + /* (platform,encoding) pair we want to use. see */ + /* @FTC_CMapIdRec and @FT_CharMapRec. */ + /* */ + typedef struct FTC_CMapDescRec_ + { + FTC_FaceID face_id; + FTC_CMapType type; + + union + { + FT_UInt index; + FT_Encoding encoding; + FTC_CMapIdRec id; + + } u; + + } FTC_CMapDescRec; + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FTC_CMapCache_New */ + /* */ + /* @description: */ + /* Creates a new charmap cache. */ + /* */ + /* @input: */ + /* manager :: A handle to the cache manager. */ + /* */ + /* @output: */ + /* acache :: A new cache handle. NULL in case of error. */ + /* */ + /* @return: */ + /* FreeType error code. 0 means success. */ + /* */ + /* @note: */ + /* Like all other caches, this one will be destroyed with the cache */ + /* manager. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_CMapCache_New( FTC_Manager manager, + FTC_CMapCache *acache ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FTC_CMapCache_Lookup */ + /* */ + /* @description: */ + /* Translates a character code into a glyph index, using the charmap */ + /* cache. */ + /* */ + /* @input: */ + /* cache :: A charmap cache handle. */ + /* */ + /* cmap_desc :: A charmap descriptor handle. */ + /* */ + /* char_code :: The character code (in the corresponding charmap). */ + /* */ + /* @return: */ + /* Glyph index. 0 means "no glyph". */ + /* */ + /* @note: */ + /* This function doesn't return @FTC_Node handles, since there is no */ + /* real use for them with typical uses of charmaps. */ + /* */ + FT_EXPORT( FT_UInt ) + FTC_CMapCache_Lookup( FTC_CMapCache cache, + FTC_CMapDesc cmap_desc, + FT_UInt32 char_code ); + + /* */ + + +FT_END_HEADER + + +#endif /* __FTCCMAP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/cache/ftcglyph.h b/Utilities/vtkfreetype/include/freetype/cache/ftcglyph.h new file mode 100644 index 0000000..3f8301a --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/cache/ftcglyph.h @@ -0,0 +1,313 @@ +/***************************************************************************/ +/* */ +/* ftcglyph.h */ +/* */ +/* FreeType abstract glyph cache (specification). */ +/* */ +/* Copyright 2000-2001, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /* + * + * FTC_GCache is an _abstract_ cache object optimized to store glyph + * data. It works as follows: + * + * - It manages FTC_GNode objects. Each one of them can hold one or more + * glyph `items'. Item types are not specified in the FTC_GCache but + * in classes that extend it. + * + * - Glyph attributes, like face ID, character size, render mode, etc., + * can be grouped into abstract `glyph families'. This avoids storing + * the attributes within the FTC_GCache, since it is likely that many + * FTC_GNodes will belong to the same family in typical uses. + * + * - Each FTC_GNode is thus an FTC_Node with two additional fields: + * + * * gindex: A glyph index, or the first index in a glyph range. + * * family: A pointer to a glyph `family'. + * + * - Family types are not fully specific in the FTC_Family type, but + * by classes that extend it. + * + * Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache. + * They share an FTC_Family sub-class called FTC_BasicFamily which is + * used to store the following data: face ID, pixel/point sizes, load + * flags. For more details see the file `src/cache/ftcbasic.c'. + * + * Client applications can extend FTC_GNode with their own FTC_GNode + * and FTC_Family sub-classes to implement more complex caches (e.g., + * handling automatic synthesis, like obliquing & emboldening, colored + * glyphs, etc.). + * + * See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and + * `ftcsbits.h', which both extend FTC_GCache with additional + * optimizations. + * + * A typical FTC_GCache implementation must provide at least the + * following: + * + * - FTC_GNode sub-class, e.g. MyNode, with relevant methods: + * my_node_new (must call FTC_GNode_Init) + * my_node_free (must call FTC_GNode_Done) + * my_node_compare (must call FTC_GNode_Compare) + * my_node_remove_faceid (must call ftc_gnode_unselect in case + * of match) + * + * - FTC_Family sub-class, e.g. MyFamily, with relevant methods: + * my_family_compare + * my_family_init + * my_family_reset (optional) + * my_family_done + * + * - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query + * data. + * + * - Constant structures for a FTC_GNodeClass. + * + * - MyCacheNew() can be implemented easily as a call to the convenience + * function FTC_GCache_New. + * + * - MyCacheLookup with a call to FTC_GCache_Lookup. This function will + * automatically: + * + * - Search for the corresponding family in the cache, or create + * a new one if necessary. Put it in FTC_GQUERY(myquery).family + * + * - Call FTC_Cache_Lookup. + * + * If it returns NULL, you should create a new node, then call + * ftc_cache_add as usual. + */ + + + /*************************************************************************/ + /* */ + /* Important: The functions defined in this file are only used to */ + /* implement an abstract glyph cache class. You need to */ + /* provide additional logic to implement a complete cache. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********* *********/ + /********* WARNING, THIS IS BETA CODE. *********/ + /********* *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#ifndef __FTCGLYPH_H__ +#define __FTCGLYPH_H__ + + +#include +#include FT_CACHE_INTERNAL_MANAGER_H + + +FT_BEGIN_HEADER + + + /* + * We can group glyphs into `families'. Each family correspond to a + * given face ID, character size, transform, etc. + * + * Families are implemented as MRU list nodes. They are + * reference-counted. + */ + + typedef struct FTC_FamilyRec_ + { + FTC_MruNodeRec mrunode; + FT_UInt num_nodes; /* current number of nodes in this family */ + FTC_Cache cache; + FTC_MruListClass clazz; + + } FTC_FamilyRec, *FTC_Family; + +#define FTC_FAMILY(x) ( (FTC_Family)(x) ) +#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) ) + + + typedef struct FTC_GNodeRec_ + { + FTC_NodeRec node; + FTC_Family family; + FT_UInt gindex; + + } FTC_GNodeRec, *FTC_GNode; + +#define FTC_GNODE( x ) ( (FTC_GNode)(x) ) +#define FTC_GNODE_P( x ) ( (FTC_GNode*)(x) ) + + + typedef struct FTC_GQueryRec_ + { + FT_UInt gindex; + FTC_Family family; + + } FTC_GQueryRec, *FTC_GQuery; + +#define FTC_GQUERY( x ) ( (FTC_GQuery)(x) ) + + + /*************************************************************************/ + /* */ + /* These functions are exported so that they can be called from */ + /* user-provided cache classes; otherwise, they are really part of the */ + /* cache sub-system internals. */ + /* */ + + /* must be called by derived FTC_Node_InitFunc routines */ + FT_EXPORT( void ) + FTC_GNode_Init( FTC_GNode node, + FT_UInt gindex, /* glyph index for node */ + FTC_Family family ); + + /* returns TRUE iff the query's glyph index correspond to the node; */ + /* this assumes that the "family" and "hash" fields of the query are */ + /* already correctly set */ + FT_EXPORT( FT_Bool ) + FTC_GNode_Compare( FTC_GNode gnode, + FTC_GQuery gquery ); + + /* call this function to clear a node's family -- this is necessary */ + /* to implement the `node_remove_faceid' cache method correctly */ + FT_EXPORT( void ) + FTC_GNode_UnselectFamily( FTC_GNode gnode, + FTC_Cache cache ); + + /* must be called by derived FTC_Node_DoneFunc routines */ + FT_EXPORT( void ) + FTC_GNode_Done( FTC_GNode node, + FTC_Cache cache ); + + + FT_EXPORT( void ) + FTC_Family_Init( FTC_Family family, + FTC_Cache cache ); + + typedef struct FTC_GCacheRec_ + { + FTC_CacheRec cache; + FTC_MruListRec families; + + } FTC_GCacheRec, *FTC_GCache; + +#define FTC_GCACHE( x ) ((FTC_GCache)(x)) + + + /* can be used as @FTC_Cache_InitFunc */ + FT_EXPORT( FT_Error ) + FTC_GCache_Init( FTC_GCache cache ); + + + /* can be used as @FTC_Cache_DoneFunc */ + FT_EXPORT( void ) + FTC_GCache_Done( FTC_GCache cache ); + + + /* the glyph cache class adds fields for the family implementation */ + typedef struct FTC_GCacheClassRec_ + { + FTC_CacheClassRec clazz; + FTC_MruListClass family_class; + + } FTC_GCacheClassRec; + + typedef const FTC_GCacheClassRec* FTC_GCacheClass; + +#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x)) + +#define FTC_CACHE__GCACHE_CLASS( x ) \ + FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class ) +#define FTC_CACHE__FAMILY_CLASS( x ) \ + ( (FTC_MruListClass)FTC_CACHE__GCACHE_CLASS( x )->family_class ) + + + /* convenience function; use it instead of FTC_Manager_Register_Cache */ + FT_EXPORT( FT_Error ) + FTC_GCache_New( FTC_Manager manager, + FTC_GCacheClass clazz, + FTC_GCache *acache ); + + FT_EXPORT( FT_Error ) + FTC_GCache_Lookup( FTC_GCache cache, + FT_UInt32 hash, + FT_UInt gindex, + FTC_GQuery query, + FTC_Node *anode ); + + + /* */ + + +#define FTC_FAMILY_FREE( family, cache ) \ + FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \ + (FTC_MruNode)(family) ) + + +#ifdef FTC_INLINE + +#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ + gindex, query, node, error ) \ + FT_BEGIN_STMNT \ + FTC_GCache _gcache = FTC_GCACHE( cache ); \ + FTC_GQuery _gquery = (FTC_GQuery)( query ); \ + FTC_MruNode_CompareFunc _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \ + \ + \ + _gquery->gindex = (gindex); \ + \ + FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare, \ + _gquery->family, error ); \ + if ( !error ) \ + { \ + FTC_Family _gqfamily = _gquery->family; \ + \ + \ + _gqfamily->num_nodes++; \ + \ + FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ); \ + \ + if ( --_gqfamily->num_nodes == 0 ) \ + FTC_FAMILY_FREE( _gqfamily, _gcache ); \ + } \ + FT_END_STMNT + /* */ + +#else /* !FTC_INLINE */ + +#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash, \ + gindex, query, node, error ) \ + FT_BEGIN_STMNT \ + error = FTC_GCache_Lookup( FTC_GCACHE( cache ), hash, gindex, \ + FTC_GQUERY( query ), (FTC_Node*)&(node) ); \ + FT_END_STMNT + +#endif /* !FTC_INLINE */ + + +FT_END_HEADER + + +#endif /* __FTCGLYPH_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/cache/ftcimage.h b/Utilities/vtkfreetype/include/freetype/cache/ftcimage.h new file mode 100644 index 0000000..1bf12db --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/cache/ftcimage.h @@ -0,0 +1,104 @@ +/***************************************************************************/ +/* */ +/* ftcimage.h */ +/* */ +/* FreeType Generic Image cache (specification) */ +/* */ +/* Copyright 2000-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /* + * FTC_ICache is an _abstract_ cache used to store a single FT_Glyph + * image per cache node. + * + * FTC_ICache extends FTC_GCache. For an implementation example, + * see FTC_ImageCache in `src/cache/ftbasic.c'. + */ + + + /*************************************************************************/ + /* */ + /* Each image cache really manages FT_Glyph objects. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTCIMAGE_H__ +#define __FTCIMAGE_H__ + + +#include +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_GLYPH_H + +FT_BEGIN_HEADER + + + /* the FT_Glyph image node type - we store only 1 glyph per node */ + typedef struct FTC_INodeRec_ + { + FTC_GNodeRec gnode; + FT_Glyph glyph; + + } FTC_INodeRec, *FTC_INode; + +#define FTC_INODE( x ) ( (FTC_INode)( x ) ) +#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex +#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family + + typedef FT_Error + (*FTC_IFamily_LoadGlyphFunc)( FTC_Family family, + FT_UInt gindex, + FTC_Cache cache, + FT_Glyph *aglyph ); + + typedef struct FTC_IFamilyClassRec_ + { + FTC_MruListClassRec clazz; + FTC_IFamily_LoadGlyphFunc family_load_glyph; + + } FTC_IFamilyClassRec; + + typedef const FTC_IFamilyClassRec* FTC_IFamilyClass; + +#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x)) + +#define FTC_CACHE__IFAMILY_CLASS( x ) \ + FTC_IFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS(x)->family_class ) + + + /* can be used as a @FTC_Node_FreeFunc */ + FT_EXPORT( void ) + FTC_INode_Free( FTC_INode inode, + FTC_Cache cache ); + + /* Can be used as @FTC_Node_NewFunc. `gquery.index' and `gquery.family' + * must be set correctly. This function will call the `family_load_glyph' + * method to load the FT_Glyph into the cache node. + */ + FT_EXPORT( FT_Error ) + FTC_INode_New( FTC_INode *pinode, + FTC_GQuery gquery, + FTC_Cache cache ); + + /* can be used as @FTC_Node_WeightFunc */ + FT_EXPORT( FT_ULong ) + FTC_INode_Weight( FTC_INode inode ); + + /* */ + +FT_END_HEADER + +#endif /* __FTCIMAGE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/cache/ftcmanag.h b/Utilities/vtkfreetype/include/freetype/cache/ftcmanag.h new file mode 100644 index 0000000..5265848 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/cache/ftcmanag.h @@ -0,0 +1,175 @@ +/***************************************************************************/ +/* */ +/* ftcmanag.h */ +/* */ +/* FreeType Cache Manager (specification). */ +/* */ +/* Copyright 2000-2001, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* A cache manager is in charge of the following: */ + /* */ + /* - Maintain a mapping between generic FTC_FaceIDs and live FT_Face */ + /* objects. The mapping itself is performed through a user-provided */ + /* callback. However, the manager maintains a small cache of FT_Face */ + /* and FT_Size objects in order to speed up things considerably. */ + /* */ + /* - Manage one or more cache objects. Each cache is in charge of */ + /* holding a varying number of `cache nodes'. Each cache node */ + /* represents a minimal amount of individually accessible cached */ + /* data. For example, a cache node can be an FT_Glyph image */ + /* containing a vector outline, or some glyph metrics, or anything */ + /* else. */ + /* */ + /* Each cache node has a certain size in bytes that is added to the */ + /* total amount of `cache memory' within the manager. */ + /* */ + /* All cache nodes are located in a global LRU list, where the oldest */ + /* node is at the tail of the list. */ + /* */ + /* Each node belongs to a single cache, and includes a reference */ + /* count to avoid destroying it (due to caching). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********* *********/ + /********* WARNING, THIS IS BETA CODE. *********/ + /********* *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#ifndef __FTCMANAG_H__ +#define __FTCMANAG_H__ + + +#include +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_MRU_H +#include FT_CACHE_INTERNAL_CACHE_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /*
*/ + /* cache_subsystem */ + /* */ + /*************************************************************************/ + + +#define FTC_MAX_FACES_DEFAULT 2 +#define FTC_MAX_SIZES_DEFAULT 4 +#define FTC_MAX_BYTES_DEFAULT 200000L /* ~200kByte by default */ + + /* maximum number of caches registered in a single manager */ +#define FTC_MAX_CACHES 16 + + + typedef struct FTC_ManagerRec_ + { + FT_Library library; + FT_Memory memory; + + FTC_Node nodes_list; + FT_ULong max_weight; + FT_ULong cur_weight; + FT_UInt num_nodes; + + FTC_Cache caches[FTC_MAX_CACHES]; + FT_UInt num_caches; + + FTC_MruListRec faces; + FTC_MruListRec sizes; + + FT_Pointer request_data; + FTC_Face_Requester request_face; + + } FTC_ManagerRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FTC_Manager_Compress */ + /* */ + /* */ + /* This function is used to check the state of the cache manager if */ + /* its `num_bytes' field is greater than its `max_bytes' field. It */ + /* will flush as many old cache nodes as possible (ignoring cache */ + /* nodes with a non-zero reference count). */ + /* */ + /* */ + /* manager :: A handle to the cache manager. */ + /* */ + /* */ + /* Client applications should not call this function directly. It is */ + /* normally invoked by specific cache implementations. */ + /* */ + /* The reason this function is exported is to allow client-specific */ + /* cache classes. */ + /* */ + FT_EXPORT( void ) + FTC_Manager_Compress( FTC_Manager manager ); + + + /* try to flush `count' old nodes from the cache; return the number + * of really flushed nodes + */ + FT_EXPORT( FT_UInt ) + FTC_Manager_FlushN( FTC_Manager manager, + FT_UInt count ); + + + /* this must be used internally for the moment */ + FT_EXPORT( FT_Error ) + FTC_Manager_RegisterCache( FTC_Manager manager, + FTC_CacheClass clazz, + FTC_Cache *acache ); + + /* */ + +#define FTC_SCALER_COMPARE( a, b ) \ + ( (a)->face_id == (b)->face_id && \ + (a)->width == (b)->width && \ + (a)->height == (b)->height && \ + ((a)->pixel != 0) == ((b)->pixel != 0) && \ + ( (a)->pixel || \ + ( (a)->x_res == (b)->x_res && \ + (a)->y_res == (b)->y_res ) ) ) + +#define FTC_SCALER_HASH( q ) \ + ( FTC_FACE_ID_HASH( (q)->face_id ) + \ + (q)->width + (q)->height*7 + \ + ( (q)->pixel ? 0 : ( (q)->x_res*33 ^ (q)->y_res*61 ) ) ) + + /* */ + +FT_END_HEADER + +#endif /* __FTCMANAG_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/cache/ftcmru.h b/Utilities/vtkfreetype/include/freetype/cache/ftcmru.h new file mode 100644 index 0000000..d70c5cc --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/cache/ftcmru.h @@ -0,0 +1,246 @@ +/***************************************************************************/ +/* */ +/* ftcmru.h */ +/* */ +/* Simple MRU list-cache (specification). */ +/* */ +/* Copyright 2000-2001, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* An MRU is a list that cannot hold more than a certain number of */ + /* elements (`max_elements'). All elements in the list are sorted in */ + /* least-recently-used order, i.e., the `oldest' element is at the tail */ + /* of the list. */ + /* */ + /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'), */ + /* the list is searched for an element with the corresponding key. If */ + /* it is found, the element is moved to the head of the list and is */ + /* returned. */ + /* */ + /* If no corresponding element is found, the lookup routine will try to */ + /* obtain a new element with the relevant key. If the list is already */ + /* full, the oldest element from the list is discarded and replaced by a */ + /* new one; a new element is added to the list otherwise. */ + /* */ + /* Note that it is possible to pre-allocate the element list nodes. */ + /* This is handy if `max_elements' is sufficiently small, as it saves */ + /* allocations/releases during the lookup process. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTCMRU_H__ +#define __FTCMRU_H__ + + +#include +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + +#define xxFT_DEBUG_ERROR +#define FTC_INLINE + +FT_BEGIN_HEADER + + typedef struct FTC_MruNodeRec_* FTC_MruNode; + + typedef struct FTC_MruNodeRec_ + { + FTC_MruNode next; + FTC_MruNode prev; + + } FTC_MruNodeRec; + + + FT_EXPORT( void ) + FTC_MruNode_Prepend( FTC_MruNode *plist, + FTC_MruNode node ); + + FT_EXPORT( void ) + FTC_MruNode_Up( FTC_MruNode *plist, + FTC_MruNode node ); + + FT_EXPORT( void ) + FTC_MruNode_Remove( FTC_MruNode *plist, + FTC_MruNode node ); + + + typedef struct FTC_MruListRec_* FTC_MruList; + + typedef struct FTC_MruListClassRec_ const * FTC_MruListClass; + + + typedef FT_Bool + (*FTC_MruNode_CompareFunc)( FTC_MruNode node, + FT_Pointer key ); + + typedef FT_Error + (*FTC_MruNode_InitFunc)( FTC_MruNode node, + FT_Pointer key, + FT_Pointer data ); + + typedef FT_Error + (*FTC_MruNode_ResetFunc)( FTC_MruNode node, + FT_Pointer key, + FT_Pointer data ); + + typedef void + (*FTC_MruNode_DoneFunc)( FTC_MruNode node, + FT_Pointer data ); + + + typedef struct FTC_MruListClassRec_ + { + FT_UInt node_size; + FTC_MruNode_CompareFunc node_compare; + FTC_MruNode_InitFunc node_init; + FTC_MruNode_ResetFunc node_reset; + FTC_MruNode_DoneFunc node_done; + + } FTC_MruListClassRec; + + typedef struct FTC_MruListRec_ + { + FT_UInt num_nodes; + FT_UInt max_nodes; + FTC_MruNode nodes; + FT_Pointer data; + FTC_MruListClassRec clazz; + FT_Memory memory; + + } FTC_MruListRec; + + + FT_EXPORT( void ) + FTC_MruList_Init( FTC_MruList list, + FTC_MruListClass clazz, + FT_UInt max_nodes, + FT_Pointer data, + FT_Memory memory ); + + FT_EXPORT( void ) + FTC_MruList_Reset( FTC_MruList list ); + + + FT_EXPORT( void ) + FTC_MruList_Done( FTC_MruList list ); + + FT_EXPORT( FTC_MruNode ) + FTC_MruList_Find( FTC_MruList list, + FT_Pointer key ); + + FT_EXPORT( FT_Error ) + FTC_MruList_New( FTC_MruList list, + FT_Pointer key, + FTC_MruNode *anode ); + + FT_EXPORT( FT_Error ) + FTC_MruList_Lookup( FTC_MruList list, + FT_Pointer key, + FTC_MruNode *pnode ); + + + FT_EXPORT( void ) + FTC_MruList_Remove( FTC_MruList list, + FTC_MruNode node ); + + FT_EXPORT( void ) + FTC_MruList_RemoveSelection( FTC_MruList list, + FTC_MruNode_CompareFunc selection, + FT_Pointer key ); + + +#ifdef FTC_INLINE + +#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \ + FT_BEGIN_STMNT \ + FTC_MruNode* _pfirst = &(list)->nodes; \ + FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \ + FTC_MruNode _first, _node; \ + \ + \ + error = 0; \ + _first = *(_pfirst); \ + _node = NULL; \ + \ + if ( _first ) \ + { \ + _node = _first; \ + do \ + { \ + if ( _compare( _node, (key) ) ) \ + { \ + if ( _node != _first ) \ + FTC_MruNode_Up( _pfirst, _node ); \ + \ + *(FTC_MruNode*)&(node) = _node; \ + goto _MruOk; \ + } \ + _node = _node->next; \ + \ + } while ( _node != _first) ; \ + } \ + \ + error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) ); \ + _MruOk: \ + ; \ + FT_END_STMNT + +#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ + FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error ) + +#else /* !FTC_INLINE */ + +#define FTC_MRULIST_LOOKUP( list, key, node, error ) \ + error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) ) + +#endif /* !FTC_INLINE */ + + +#define FTC_MRULIST_LOOP( list, node ) \ + FT_BEGIN_STMNT \ + FTC_MruNode _first = (list)->nodes; \ + \ + \ + if ( _first ) \ + { \ + FTC_MruNode _node = _first; \ + \ + \ + do \ + { \ + *(FTC_MruNode*)&(node) = _node; + + +#define FTC_MRULIST_LOOP_END() \ + _node = _node->next; \ + \ + } while ( _node != _first ); \ + } \ + FT_END_STMNT + + /* */ + +FT_END_HEADER + + +#endif /* __FTCMRU_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/cache/ftcsbits.h b/Utilities/vtkfreetype/include/freetype/cache/ftcsbits.h new file mode 100644 index 0000000..b2ef0f1 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/cache/ftcsbits.h @@ -0,0 +1,96 @@ +/***************************************************************************/ +/* */ +/* ftcsbits.h */ +/* */ +/* A small-bitmap cache (specification). */ +/* */ +/* Copyright 2000-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTCSBITS_H__ +#define __FTCSBITS_H__ + + +#include +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_GLYPH_H + + +FT_BEGIN_HEADER + +#define FTC_SBIT_ITEMS_PER_NODE 16 + + typedef struct FTC_SNodeRec_ + { + FTC_GNodeRec gnode; + FT_UInt count; + FTC_SBitRec sbits[FTC_SBIT_ITEMS_PER_NODE]; + + } FTC_SNodeRec, *FTC_SNode; + + +#define FTC_SNODE( x ) ( (FTC_SNode)( x ) ) +#define FTC_SNODE_GINDEX( x ) FTC_GNODE( x )->gindex +#define FTC_SNODE_FAMILY( x ) FTC_GNODE( x )->family + + typedef FT_UInt + (*FTC_SFamily_GetCountFunc)( FTC_Family family, + FTC_Manager manager ); + + typedef FT_Error + (*FTC_SFamily_LoadGlyphFunc)( FTC_Family family, + FT_UInt gindex, + FTC_Manager manager, + FT_Face *aface ); + + typedef struct FTC_SFamilyClassRec_ + { + FTC_MruListClassRec clazz; + FTC_SFamily_GetCountFunc family_get_count; + FTC_SFamily_LoadGlyphFunc family_load_glyph; + + } FTC_SFamilyClassRec; + + typedef const FTC_SFamilyClassRec* FTC_SFamilyClass; + +#define FTC_SFAMILY_CLASS( x ) ((FTC_SFamilyClass)(x)) + +#define FTC_CACHE__SFAMILY_CLASS( x ) \ + FTC_SFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS( x )->family_class ) + + + FT_EXPORT( void ) + FTC_SNode_Free( FTC_SNode snode, + FTC_Cache cache ); + + FT_EXPORT( FT_Error ) + FTC_SNode_New( FTC_SNode *psnode, + FTC_GQuery gquery, + FTC_Cache cache ); + + FT_EXPORT( FT_ULong ) + FTC_SNode_Weight( FTC_SNode inode ); + + + FT_EXPORT( FT_Bool ) + FTC_SNode_Compare( FTC_SNode snode, + FTC_GQuery gquery, + FTC_Cache cache ); + + /* */ + +FT_END_HEADER + +#endif /* __FTCSBITS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/config/ftconfig.h b/Utilities/vtkfreetype/include/freetype/config/ftconfig.h new file mode 100644 index 0000000..4bd8cf6 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/config/ftconfig.h @@ -0,0 +1,353 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This header file contains a number of macro definitions that are used */ + /* by the rest of the engine. Most of the macros here are automatically */ + /* determined at compile time, and you should not need to change it to */ + /* port FreeType, except to compile the library with a non-ANSI */ + /* compiler. */ + /* */ + /* Note however that if some specific modifications are needed, we */ + /* advise you to place a modified copy in your build directory. */ + /* */ + /* The build directory is usually `freetype/builds/', and */ + /* contains system-specific files that are always included first when */ + /* building the library. */ + /* */ + /* This ANSI version should stay in `include/freetype/config'. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTCONFIG_H__ +#define __FTCONFIG_H__ + +#include +#include FT_CONFIG_OPTIONS_H +#include FT_CONFIG_STANDARD_LIBRARY_H + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* PLATFORM-SPECIFIC CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled to suit a specific system. The current */ + /* ones are defaults used to compile FreeType in an ANSI C environment */ + /* (16bit compilers are also supported). Copy this file to your own */ + /* `freetype/builds/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + + /* There are systems (like the Texas Instruments 'C54x) where a `char' */ + /* has 16 bits. ANSI C says that sizeof(char) is always 1. Since an */ + /* `int' has 16 bits also for this system, sizeof(int) gives 1 which */ + /* is probably unexpected. */ + /* */ + /* `CHAR_BIT' (defined in limits.h) gives the number of bits in a */ + /* `char' type. */ + +#ifndef FT_CHAR_BIT +#define FT_CHAR_BIT CHAR_BIT +#endif + + + /* The size of an `int' type. */ +#if FT_UINT_MAX == 0xFFFFFFFFUL +#define FT_SIZEOF_INT (32 / FT_CHAR_BIT) +#elif FT_UINT_MAX == 0xFFFFU +#define FT_SIZEOF_INT (16 / FT_CHAR_BIT) +#elif FT_UINT_MAX > 0xFFFFFFFFU && FT_UINT_MAX == 0xFFFFFFFFFFFFFFFFU +#define FT_SIZEOF_INT (64 / FT_CHAR_BIT) +#else +#error "Unsupported size of `int' type!" +#endif + + /* The size of a `long' type. */ +#if FT_ULONG_MAX == 0xFFFFFFFFUL +#define FT_SIZEOF_LONG (32 / FT_CHAR_BIT) +#elif FT_ULONG_MAX > 0xFFFFFFFFU && FT_ULONG_MAX == 0xFFFFFFFFFFFFFFFFU +#define FT_SIZEOF_LONG (64 / FT_CHAR_BIT) +#else +#error "Unsupported size of `long' type!" +#endif + + + /* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + /* FT_UNUSED is a macro used to indicate that a given parameter is not */ + /* used -- this is only used to get rid of unpleasant compiler warnings */ +#ifndef FT_UNUSED +#define FT_UNUSED( arg ) ( (arg) = (arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you are doing. No */ + /* porter should need to mess with them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Mac support */ + /* */ + /* This is the only necessary change, so it is defined here instead */ + /* providing a new configuration file. */ + /* */ +#if ( defined( __APPLE__ ) && !defined( DARWIN_NO_CARBON ) ) || \ + ( defined( __MWERKS__ ) && defined( macintosh ) ) +#define FT_MACINTOSH 1 +#endif + + + /*************************************************************************/ + /* */ + /* IntN types */ + /* */ + /* Used to guarantee the size of some specific integers. */ + /* */ + typedef signed short FT_Int16; + typedef unsigned short FT_UInt16; + +#if FT_SIZEOF_INT == (32 / FT_CHAR_BIT) + + typedef signed int FT_Int32; + typedef unsigned int FT_UInt32; + +#elif FT_SIZEOF_LONG == (32 / FT_CHAR_BIT) + + typedef signed long FT_Int32; + typedef unsigned long FT_UInt32; + +#else +#error "no 32bit type found -- please check your configuration files" +#endif + + /* look up an integer type that is at least 32 bits */ +#if FT_SIZEOF_INT >= (32 / FT_CHAR_BIT) + + typedef int FT_Fast; + typedef unsigned int FT_UFast; + +#elif FT_SIZEOF_LONG >= (32 / FT_CHAR_BIT) + + typedef long FT_Fast; + typedef unsigned long FT_UFast; + +#endif + + + /* determine whether we have a 64-bit int type for platforms without */ + /* Autoconf */ +#if FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */ + + /* this compiler provides the __int64 type */ +#define FT_LONG64 +#define FT_INT64 __int64 + +#elif defined( __BORLANDC__ ) /* Borland C++ */ + + /* XXXX: We should probably check the value of __BORLANDC__ in order */ + /* to test the compiler version. */ + + /* this compiler provides the __int64 type */ +#define FT_LONG64 +#define FT_INT64 __int64 + +#elif defined( __WATCOMC__ ) /* Watcom C++ */ + + /* Watcom doesn't provide 64-bit data types */ + +#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */ + +#define FT_LONG64 +#define FT_INT64 long long int + +#elif defined( __GNUC__ ) + + /* GCC provides the "long long" type */ +#define FT_LONG64 +#define FT_INT64 long long int + +#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */ + + +#define FT_BEGIN_STMNT do { +#define FT_END_STMNT } while ( 0 ) +#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT + + + /*************************************************************************/ + /* */ + /* A 64-bit data type will create compilation problems if you compile */ + /* in strict ANSI mode. To avoid them, we disable their use if */ + /* __STDC__ is defined. You can however ignore this rule by */ + /* defining the FT_CONFIG_OPTION_FORCE_INT64 configuration macro. */ + /* */ +#if defined( FT_LONG64 ) && !defined( FT_CONFIG_OPTION_FORCE_INT64 ) + +#ifdef __STDC__ + + /* undefine the 64-bit macros in strict ANSI compilation mode */ +#undef FT_LONG64 +#undef FT_INT64 + +#endif /* __STDC__ */ + +#endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */ + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT + +#define FT_LOCAL( x ) static x +#define FT_LOCAL_DEF( x ) static x + +#else + +#ifdef __cplusplus +#define FT_LOCAL( x ) extern "C" x +#define FT_LOCAL_DEF( x ) extern "C" x +#else +#define FT_LOCAL( x ) extern x +#define FT_LOCAL_DEF( x ) x +#endif + +#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */ + + +#ifndef FT_BASE + +#ifdef __cplusplus +#define FT_BASE( x ) extern "C" x +#else +#define FT_BASE( x ) extern x +#endif + +#endif /* !FT_BASE */ + + +#ifndef FT_BASE_DEF + +#ifdef __cplusplus +#define FT_BASE_DEF( x ) extern "C" x +#else +#define FT_BASE_DEF( x ) extern x +#endif + +#endif /* !FT_BASE_DEF */ + + +#ifndef FT_EXPORT + +#ifdef __cplusplus +#define FT_EXPORT( x ) extern "C" x +#else +#define FT_EXPORT( x ) extern x +#endif + +#endif /* !FT_EXPORT */ + + +#ifndef FT_EXPORT_DEF + +#ifdef __cplusplus +#define FT_EXPORT_DEF( x ) extern "C" x +#else +#define FT_EXPORT_DEF( x ) extern x +#endif + +#endif /* !FT_EXPORT_DEF */ + + +#ifndef FT_EXPORT_VAR + +#ifdef __cplusplus +#define FT_EXPORT_VAR( x ) extern "C" x +#else +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* !FT_EXPORT_VAR */ + + /* The following macros are needed to compile the library with a */ + /* C++ compiler and with 16bit compilers. */ + /* */ + + /* This is special. Within C++, you must specify `extern "C"' for */ + /* functions which are used via function pointers, and you also */ + /* must do that for structures which contain function pointers to */ + /* assure C linkage -- it's not possible to have (local) anonymous */ + /* functions which are accessed by (global) function pointers. */ + /* */ + /* */ + /* FT_CALLBACK_DEF is used to _define_ a callback function. */ + /* */ + /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */ + /* contains pointers to callback functions. */ + /* */ + /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable */ + /* that contains pointers to callback functions. */ + /* */ + /* */ + /* Some 16bit compilers have to redefine these macros to insert */ + /* the infamous `_cdecl' or `__fastcall' declarations. */ + /* */ +#ifndef FT_CALLBACK_DEF +#ifdef __cplusplus +#define FT_CALLBACK_DEF( x ) extern "C" x +#else +#define FT_CALLBACK_DEF( x ) static x +#endif +#endif /* FT_CALLBACK_DEF */ + +#ifndef FT_CALLBACK_TABLE +#ifdef __cplusplus +#define FT_CALLBACK_TABLE extern "C" +#define FT_CALLBACK_TABLE_DEF extern "C" +#else +#define FT_CALLBACK_TABLE extern +#define FT_CALLBACK_TABLE_DEF /* nothing */ +#endif +#endif /* FT_CALLBACK_TABLE */ + + +FT_END_HEADER + + +#endif /* __FTCONFIG_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/config/ftheader.h b/Utilities/vtkfreetype/include/freetype/config/ftheader.h new file mode 100644 index 0000000..b996a7a --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/config/ftheader.h @@ -0,0 +1,564 @@ +/***************************************************************************/ +/* */ +/* ftheader.h */ +/* */ +/* Build macros of the FreeType 2 library. */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#ifndef __FT_HEADER_H__ +#define __FT_HEADER_H__ + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_BEGIN_HEADER */ + /* */ + /* */ + /* This macro is used in association with @FT_END_HEADER in header */ + /* files to ensure that the declarations within are properly */ + /* encapsulated in an `extern "C" { .. }' block when included from a */ + /* C++ compiler. */ + /* */ +#ifdef __cplusplus +#define FT_BEGIN_HEADER extern "C" { +#else +#define FT_BEGIN_HEADER /* nothing */ +#endif + + + /*@***********************************************************************/ + /* */ + /* */ + /* FT_END_HEADER */ + /* */ + /* */ + /* This macro is used in association with @FT_BEGIN_HEADER in header */ + /* files to ensure that the declarations within are properly */ + /* encapsulated in an `extern "C" { .. }' block when included from a */ + /* C++ compiler. */ + /* */ +#ifdef __cplusplus +#define FT_END_HEADER } +#else +#define FT_END_HEADER /* nothing */ +#endif + + + /*************************************************************************/ + /* */ + /* Aliases for the FreeType 2 public and configuration files. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /*
*/ + /* header_file_macros */ + /* */ + /* */ + /* Header File Macros */ + /* */ + /* <Abstract> */ + /* Macro definitions used to #include specific header files. */ + /* */ + /* <Description> */ + /* The following macros are defined to the name of specific */ + /* FreeType 2 header files. They can be used directly in #include */ + /* statements as in: */ + /* */ + /* { */ + /* #include FT_FREETYPE_H */ + /* #include FT_MULTIPLE_MASTERS_H */ + /* #include FT_GLYPH_H */ + /* } */ + /* */ + /* There are several reasons why we are now using macros to name */ + /* public header files. The first one is that such macros are not */ + /* limited to the infamous 8.3 naming rule required by DOS (and */ + /* `FT_MULTIPLE_MASTERS_H' is a lot more meaningful than `ftmm.h'). */ + /* */ + /* The second reason is that is allows for more flexibility in the */ + /* way FreeType 2 is installed on a given system. */ + /* */ + /*************************************************************************/ + + /* configuration files */ + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CONFIG_CONFIG_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* FreeType 2 configuration data. */ + /* */ +#ifndef FT_CONFIG_CONFIG_H +#define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h> +#endif + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CONFIG_STANDARD_LIBRARY_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* FreeType 2 configuration data. */ + /* */ +#ifndef FT_CONFIG_STANDARD_LIBRARY_H +#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h> +#endif + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CONFIG_OPTIONS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* FreeType 2 project-specific configuration options. */ + /* */ +#ifndef FT_CONFIG_OPTIONS_H +#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h> +#endif + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CONFIG_MODULES_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the list of FreeType 2 modules that are statically linked to new */ + /* library instances in @FT_Init_FreeType. */ + /* */ +#ifndef FT_CONFIG_MODULES_H +#define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h> +#endif + + + /* public headers */ + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_FREETYPE_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the base FreeType 2 API. */ + /* */ +#define FT_FREETYPE_H <freetype/freetype.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_ERRORS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the list of FreeType 2 error codes (and messages). */ + /* */ + /* It is included by @FT_FREETYPE_H. */ + /* */ +#define FT_ERRORS_H <freetype/fterrors.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_MODULE_ERRORS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the list of FreeType 2 module error offsets (and messages). */ + /* */ +#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_SYSTEM_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the FreeType 2 interface to low-level operations (i.e. memory */ + /* management and stream i/o). */ + /* */ + /* It is included by @FT_FREETYPE_H. */ + /* */ +#define FT_SYSTEM_H <freetype/ftsystem.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_IMAGE_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* types definitions related to glyph images (i.e. bitmaps, outlines, */ + /* scan-converter parameters). */ + /* */ + /* It is included by @FT_FREETYPE_H. */ + /* */ +#define FT_IMAGE_H <freetype/ftimage.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_TYPES_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the basic data types defined by FreeType 2. */ + /* */ + /* It is included by @FT_FREETYPE_H. */ + /* */ +#define FT_TYPES_H <freetype/fttypes.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_LIST_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the list management API of FreeType 2. */ + /* */ + /* (Most applications will never need to include this file.) */ + /* */ +#define FT_LIST_H <freetype/ftlist.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_OUTLINE_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the scalable outline management API of FreeType 2. */ + /* */ +#define FT_OUTLINE_H <freetype/ftoutln.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_SIZES_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the API used to manage multiple @FT_Size objects per face. */ + /* */ +#define FT_SIZES_H <freetype/ftsizes.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_MODULE_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the module management API of FreeType 2. */ + /* */ +#define FT_MODULE_H <freetype/ftmodapi.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_RENDER_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the renderer module management API of FreeType 2. */ + /* */ +#define FT_RENDER_H <freetype/ftrender.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_TYPE1_TABLES_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the types and API specific to the Type 1 format. */ + /* */ +#define FT_TYPE1_TABLES_H <freetype/t1tables.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_TRUETYPE_IDS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the enumeration values used to identify name strings, languages, */ + /* encodings, etc. This file really contains a _large_ set of */ + /* constant macro definitions, taken from the TrueType and OpenType */ + /* specifications. */ + /* */ +#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_TRUETYPE_TABLES_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the types and API specific to the TrueType (as well as OpenType) */ + /* format. */ + /* */ +#define FT_TRUETYPE_TABLES_H <freetype/tttables.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_TRUETYPE_TAGS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the definitions of TrueType 4-byte `tags' used to identify blocks */ + /* in SFNT-based font formats (i.e. TrueType and OpenType). */ + /* */ +#define FT_TRUETYPE_TAGS_H <freetype/tttags.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_BDF_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the definitions of an API to access BDF-specific strings from a */ + /* face. */ + /* */ +#define FT_BDF_H <freetype/ftbdf.h> + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_GZIP_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the definitions of an API to support for gzip-compressed files. */ + /* */ +#define FT_GZIP_H <freetype/ftgzip.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_LZW_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the definitions of an API to support for LZW-compressed files. */ + /* */ +#define FT_LZW_H <freetype/ftlzw.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_WINFONTS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the definitions of an API to support Windows .FNT files */ + /* */ +#define FT_WINFONTS_H <freetype/ftwinfnt.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_GLYPH_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the API of the optional glyph management component. */ + /* */ +#define FT_GLYPH_H <freetype/ftglyph.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_BBOX_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the API of the optional exact bounding box computation routines. */ + /* */ +#define FT_BBOX_H <freetype/ftbbox.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CACHE_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the API of the optional FreeType 2 cache sub-system. */ + /* */ +#define FT_CACHE_H <freetype/ftcache.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CACHE_IMAGE_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the `glyph image' API of the FreeType 2 cache sub-system. */ + /* */ + /* It is used to define a cache for @FT_Glyph elements. You can also */ + /* see the API defined in @FT_CACHE_SMALL_BITMAPS_H if you only need */ + /* to store small glyph bitmaps, as it will use less memory. */ + /* */ + /* This macro is deprecated. Simply include @FT_CACHE_H to have all */ + /* glyph image-related cache declarations. */ + /* */ +#define FT_CACHE_IMAGE_H FT_CACHE_H + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CACHE_SMALL_BITMAPS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the `small bitmaps' API of the FreeType 2 cache sub-system. */ + /* */ + /* It is used to define a cache for small glyph bitmaps in a */ + /* relatively memory-efficient way. You can also use the API defined */ + /* in @FT_CACHE_IMAGE_H if you want to cache arbitrary glyph images, */ + /* including scalable outlines. */ + /* */ + /* This macro is deprecated. Simply include @FT_CACHE_H to have all */ + /* small bitmaps-related cache declarations. */ + /* */ +#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_CACHE_CHARMAP_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the `charmap' API of the FreeType 2 cache sub-system. */ + /* */ + /* This macro is deprecated. Simply include @FT_CACHE_H to have all */ + /* charmap-based cache declarations. */ + /* */ +#define FT_CACHE_CHARMAP_H FT_CACHE_H + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_MAC_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the Macintosh-specific FreeType 2 API. The latter is used to */ + /* access fonts embedded in resource forks. */ + /* */ + /* This header file must be explicitly included by client */ + /* applications compiled on the Mac (note that the base API still */ + /* works though). */ + /* */ +#define FT_MAC_H <freetype/ftmac.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_MULTIPLE_MASTERS_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the optional multiple-masters management API of FreeType 2. */ + /* */ +#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h> + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_SFNT_NAMES_H */ + /* */ + /* @description: */ + /* A macro used in #include statements to name the file containing */ + /* the optional FreeType 2 API used to access embedded `name' strings */ + /* in SFNT-based font formats (i.e. TrueType and OpenType). */ + /* */ +#define FT_SFNT_NAMES_H <freetype/ftsnames.h> + + /* */ + +#define FT_TRIGONOMETRY_H <freetype/fttrigon.h> +#define FT_STROKER_H <freetype/ftstroke.h> +#define FT_SYNTHESIS_H <freetype/ftsynth.h> +#define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h> + +#define FT_CACHE_MANAGER_H <freetype/cache/ftcmanag.h> + +#define FT_CACHE_INTERNAL_MRU_H <freetype/cache/ftcmru.h> +#define FT_CACHE_INTERNAL_MANAGER_H <freetype/cache/ftcmanag.h> +#define FT_CACHE_INTERNAL_CACHE_H <freetype/cache/ftccache.h> +#define FT_CACHE_INTERNAL_GLYPH_H <freetype/cache/ftcglyph.h> +#define FT_CACHE_INTERNAL_IMAGE_H <freetype/cache/ftcimage.h> +#define FT_CACHE_INTERNAL_SBITS_H <freetype/cache/ftcsbits.h> + + +#define FT_XFREE86_H <freetype/ftxf86.h> + +#define FT_INCREMENTAL_H <freetype/ftincrem.h> + +#define FT_TRUETYPE_UNPATENTED_H <freetype/ttunpat.h> + + /* now include internal headers definitions from <freetype/internal/...> */ + +#define FT_INTERNAL_INTERNAL_H <freetype/internal/internal.h> +#include FT_INTERNAL_INTERNAL_H + + +#endif /* __FT2_BUILD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/config/ftmodule.h b/Utilities/vtkfreetype/include/freetype/config/ftmodule.h new file mode 100644 index 0000000..c00a489 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/config/ftmodule.h @@ -0,0 +1,19 @@ +FT_USE_MODULE(autohint_module_class) +FT_USE_MODULE(tt_driver_class) +FT_USE_MODULE(t1_driver_class) +FT_USE_MODULE(cff_driver_class) +FT_USE_MODULE(t1cid_driver_class) +FT_USE_MODULE(pcf_driver_class) +FT_USE_MODULE(bdf_driver_class) +FT_USE_MODULE(psaux_module_class) +FT_USE_MODULE(psnames_module_class) +FT_USE_MODULE(pshinter_module_class) +FT_USE_MODULE(ft_raster1_renderer_class) +FT_USE_MODULE(sfnt_module_class) +FT_USE_MODULE(ft_smooth_renderer_class) +FT_USE_MODULE(ft_smooth_lcd_renderer_class) +FT_USE_MODULE(ft_smooth_lcdv_renderer_class) +FT_USE_MODULE(t42_driver_class) +FT_USE_MODULE(pfr_driver_class) +FT_USE_MODULE(winfnt_driver_class) + diff --git a/Utilities/vtkfreetype/include/freetype/config/ftoption.h b/Utilities/vtkfreetype/include/freetype/config/ftoption.h new file mode 100644 index 0000000..57ea1a1 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/config/ftoption.h @@ -0,0 +1,577 @@ +/***************************************************************************/ +/* */ +/* ftoption.h */ +/* */ +/* User-selectable configuration macros (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTOPTION_H__ +#define __FTOPTION_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* USER-SELECTABLE CONFIGURATION MACROS */ + /* */ + /* This file contains the default configuration macro definitions for */ + /* a standard build of the FreeType library. There are three ways to */ + /* use this file to build project-specific versions of the library: */ + /* */ + /* - You can modify this file by hand, but this is not recommended in */ + /* cases where you would like to build several versions of the */ + /* library from a single source directory. */ + /* */ + /* - You can put a copy of this file in your build directory, more */ + /* precisely in "$BUILD/freetype/config/ftoption.h", where "$BUILD" */ + /* is the name of a directory that is included _before_ the FreeType */ + /* include path during compilation. */ + /* */ + /* The default FreeType Makefiles and Jamfiles use the build */ + /* directory "builds/<system>" by default, but you can easily change */ + /* that for your own projects. */ + /* */ + /* - Copy the file <ft2build.h> to "$BUILD/ft2build.h" and modify it */ + /* slightly to pre-define the macro FT_CONFIG_OPTIONS_H used to */ + /* locate this file during the build. For example, */ + /* */ + /* #define FT_CONFIG_OPTIONS_H <myftoptions.h> */ + /* #include <freetype/config/ftheader.h> */ + /* */ + /* will use "$BUILD/myftoptions.h" instead of this file for macro */ + /* definitions. */ + /* */ + /* Note also that you can similarly pre-define the macro */ + /* FT_CONFIG_MODULES_H used to locate the file listing of the modules */ + /* that are statically linked to the library at compile time. By */ + /* default, this file is <freetype/config/ftmodule.h>. */ + /* */ + /* We highly recommend using the third method whenever possible. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Many compilers provide a non-ANSI 64-bit data type that can be used */ + /* by FreeType to speed up some computations. However, this will create */ + /* some problems when compiling the library in strict ANSI mode. */ + /* */ + /* For this reason, the use of 64-bit integers is normally disabled when */ + /* the __STDC__ macro is defined. You can however disable this by */ + /* defining the macro FT_CONFIG_OPTION_FORCE_INT64 here. */ + /* */ + /* For most compilers, this will only create compilation warnings when */ + /* building the library. */ + /* */ + /* ObNote: The compiler-specific 64-bit integers are detected in the */ + /* file "ftconfig.h" either statically or through the */ + /* `configure' script on supported platforms. */ + /* */ +#undef FT_CONFIG_OPTION_FORCE_INT64 + + + /*************************************************************************/ + /* */ + /* LZW-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* 'compress' program. This is mostly used to parse many of the PCF */ + /* files that come with various X11 distributions. The implementation */ + /* uses NetBSD's `zopen' to partially uncompress the file on the fly */ + /* (see src/lzw/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. */ + /* */ +/* #define FT_CONFIG_OPTION_USE_LZW */ + + + /*************************************************************************/ + /* */ + /* Gzip-compressed file support. */ + /* */ + /* FreeType now handles font files that have been compressed with the */ + /* 'gzip' program. This is mostly used to parse many of the PCF files */ + /* that come with XFree86. The implementation uses `zlib' to */ + /* partially uncompress the file on the fly (see src/gzip/ftgzip.c). */ + /* */ + /* Define this macro if you want to enable this `feature'. See also */ + /* the macro FT_CONFIG_OPTION_SYSTEM_ZLIB below. */ + /* */ +/* #define FT_CONFIG_OPTION_USE_ZLIB */ + + + /*************************************************************************/ + /* */ + /* ZLib library selection */ + /* */ + /* This macro is only used when FT_CONFIG_OPTION_USE_ZLIB is defined. */ + /* It allows FreeType's `ftgzip' component to link to the system's */ + /* installation of the ZLib library. This is useful on systems like */ + /* Unix or VMS where it generally is already available. */ + /* */ + /* If you let it undefined, the component will use its own copy */ + /* of the zlib sources instead. These have been modified to be */ + /* included directly within the component and *not* export external */ + /* function names. This allows you to link any program with FreeType */ + /* _and_ ZLib without linking conflicts. */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ + + + /*************************************************************************/ + /* */ + /* DLL export compilation */ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front OR after the return type of function */ + /* declarations. */ + /* */ + /* Two macros are used within the FreeType source code to define */ + /* exported library functions: FT_EXPORT and FT_EXPORT_DEF. */ + /* */ + /* FT_EXPORT( return_type ) */ + /* */ + /* is used in a function declaration, as in */ + /* */ + /* FT_EXPORT( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ); */ + /* */ + /* */ + /* FT_EXPORT_DEF( return_type ) */ + /* */ + /* is used in a function definition, as in */ + /* */ + /* FT_EXPORT_DEF( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ) */ + /* { */ + /* ... some code ... */ + /* return FT_Err_Ok; */ + /* } */ + /* */ + /* You can provide your own implementation of FT_EXPORT and */ + /* FT_EXPORT_DEF here if you want. If you leave them undefined, they */ + /* will be later automatically defined as `extern return_type' to */ + /* allow normal compilation. */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_EXPORT(x) extern x */ +/* #define FT_EXPORT_DEF(x) x */ + + + /*************************************************************************/ + /* */ + /* Glyph Postscript Names handling */ + /* */ + /* By default, FreeType 2 is compiled with the `PSNames' module. This */ + /* module is in charge of converting a glyph name string into a */ + /* Unicode value, or return a Macintosh standard glyph name for the */ + /* use with the TrueType `post' table. */ + /* */ + /* Undefine this macro if you do not want `PSNames' compiled in your */ + /* build of FreeType. This has the following effects: */ + /* */ + /* - The TrueType driver will provide its own set of glyph names, */ + /* if you build it to support postscript names in the TrueType */ + /* `post' table. */ + /* */ + /* - The Type 1 driver will not be able to synthetize a Unicode */ + /* charmap out of the glyphs found in the fonts. */ + /* */ + /* You would normally undefine this configuration macro when building */ + /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */ + /* */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Postscript Names to Unicode Values support */ + /* */ + /* By default, FreeType 2 is built with the `PSNames' module compiled */ + /* in. Among other things, the module is used to convert a glyph name */ + /* into a Unicode value. This is especially useful in order to */ + /* synthetize on the fly a Unicode charmap from the CFF/Type 1 driver */ + /* through a big table named the `Adobe Glyph List' (AGL). */ + /* */ + /* Undefine this macro if you do not want the Adobe Glyph List */ + /* compiled in your `PSNames' module. The Type 1 driver will not be */ + /* able to synthetize a Unicode charmap out of the glyphs found in the */ + /* fonts. */ + /* */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /*************************************************************************/ + /* */ + /* Support for Mac fonts */ + /* */ + /* Define this macro if you want support for outline fonts in Mac */ + /* format (mac dfont, mac resource, macbinary containing a mac */ + /* resource) on non-Mac platforms. */ + /* */ + /* Note that the `FOND' resource isn't checked. */ + /* */ +#define FT_CONFIG_OPTION_MAC_FONTS + + + /*************************************************************************/ + /* */ + /* Guessing methods to access embedded resource forks */ + /* */ + /* Enable extra Mac fonts support on non-Mac platforms (e.g. */ + /* GNU/Linux). */ + /* */ + /* Resource forks which include fonts data are stored sometimes in */ + /* locations which users or developers don't expected. In some cases, */ + /* resource forks start with some offset from the head of a file. In */ + /* other cases, the actual resource fork is stored in file different */ + /* from what the user specifies. If this option is activated, */ + /* FreeType tries to guess whether such offsets or different file */ + /* names must be used. */ + /* */ + /* Note that normal, direct access of resource forks is controlled via */ + /* the FT_CONFIG_OPTION_MAC_FONTS option. */ + /* */ +#ifdef FT_CONFIG_OPTION_MAC_FONTS +#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK +#endif + + + /*************************************************************************/ + /* */ + /* Allow the use of FT_Incremental_Interface to load typefaces that */ + /* contain no glyph data, but supply it via a callback function. */ + /* This allows FreeType to be used with the PostScript language, using */ + /* the GhostScript interpreter. */ + /* */ +/* #define FT_CONFIG_OPTION_INCREMENTAL */ + + + /*************************************************************************/ + /* */ + /* The size in bytes of the render pool used by the scan-line converter */ + /* to do all of its work. */ + /* */ + /* This must be greater than 4KByte. */ + /* */ +#define FT_RENDER_POOL_SIZE 16384L + + + /*************************************************************************/ + /* */ + /* FT_MAX_MODULES */ + /* */ + /* The maximum number of modules that can be registered in a single */ + /* FreeType library object. 32 is the default. */ + /* */ +#define FT_MAX_MODULES 32 + + + /*************************************************************************/ + /* */ + /* Debug level */ + /* */ + /* FreeType can be compiled in debug or trace mode. In debug mode, */ + /* errors are reported through the `ftdebug' component. In trace */ + /* mode, additional messages are sent to the standard output during */ + /* execution. */ + /* */ + /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */ + /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */ + /* */ + /* Don't define any of these macros to compile in `release' mode! */ + /* */ + /* Do not #undef these macros here since the build system might define */ + /* them for certain configurations only. */ + /* */ +/* #define FT_DEBUG_LEVEL_ERROR */ +/* #define FT_DEBUG_LEVEL_TRACE */ + + + /*************************************************************************/ + /* */ + /* Memory Debugging */ + /* */ + /* FreeType now comes with an integrated memory debugger that is */ + /* capable of detecting simple errors like memory leaks or double */ + /* deletes. To compile it within your build of the library, you */ + /* should define FT_DEBUG_MEMORY here. */ + /* */ + /* Note that the memory debugger is only activated at runtime when */ + /* when the _environment_ variable "FT2_DEBUG_MEMORY" is defined also! */ + /* */ + /* Do not #undef this macro here since the build system might define */ + /* it for certain configurations only. */ + /* */ +/* #define FT_DEBUG_MEMORY */ + + + /*************************************************************************/ + /* */ + /* Module errors */ + /* */ + /* If this macro is set (which is _not_ the default), the higher byte */ + /* of an error code gives the module in which the error has occurred, */ + /* while the lower byte is the real error code. */ + /* */ + /* Setting this macro makes sense for debugging purposes only, since */ + /* it would break source compatibility of certain programs that use */ + /* FreeType 2. */ + /* */ + /* More details can be found in the files ftmoderr.h and fterrors.h. */ + /* */ +#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in all formats using the SFNT module (namely */ + /* TrueType & OpenType). */ + /* */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ + /* load and enumerate the glyph Postscript names in a TrueType or */ + /* OpenType file. */ + /* */ + /* Note that when you do not compile the `PSNames' module by undefining */ + /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ + /* contain additional code used to read the PS Names table from a font. */ + /* */ + /* (By default, the module uses `PSNames' to extract glyph names.) */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */ + /* access the internal name table in a SFNT-based format like TrueType */ + /* or OpenType. The name table contains various strings used to */ + /* describe the font, like family name, copyright, version, etc. It */ + /* does not contain any glyph name though. */ + /* */ + /* Accessing SFNT names is done through the functions declared in */ + /* `freetype/ftnames.h'. */ + /* */ +#define TT_CONFIG_OPTION_SFNT_NAMES + + + /*************************************************************************/ + /* */ + /* TrueType CMap support */ + /* */ + /* Here you can fine-tune which TrueType CMap table format shall be */ + /* supported. */ +#define TT_CONFIG_CMAP_FORMAT_0 +#define TT_CONFIG_CMAP_FORMAT_2 +#define TT_CONFIG_CMAP_FORMAT_4 +#define TT_CONFIG_CMAP_FORMAT_6 +#define TT_CONFIG_CMAP_FORMAT_8 +#define TT_CONFIG_CMAP_FORMAT_10 +#define TT_CONFIG_CMAP_FORMAT_12 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */ + /* a bytecode interpreter in the TrueType driver. Note that there are */ + /* important patent issues related to the use of the interpreter. */ + /* */ + /* By undefining this, you will only compile the code necessary to load */ + /* TrueType glyphs without hinting. */ + /* */ + /* Do not #undef this macro here, since the build system might */ + /* define it for certain configurations only. */ + /* */ +/* #define TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_UNPATENTED_HINTING (in addition to */ + /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER) to compile the unpatented */ + /* work-around hinting system. Note that for the moment, the algorithm */ + /* is only used when selected at runtime through the parameter tag */ + /* FT_PARAM_TAG_UNPATENTED_HINTING; or when the debug hook */ + /* FT_DEBUG_HOOK_UNPATENTED_HINTING is globally actived */ + /* */ +#define TT_CONFIG_OPTION_UNPATENTED_HINTING + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */ + /* bytecode interpreter with a huge switch statement, rather than a call */ + /* table. This results in smaller and faster code for a number of */ + /* architectures. */ + /* */ + /* Note however that on some compiler/processor combinations, undefining */ + /* this macro will generate faster, though larger, code. */ + /* */ +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED to compile the */ + /* TrueType glyph loader to use Apple's definition of how to handle */ + /* component offsets in composite glyphs. */ + /* */ + /* Apple and MS disagree on the default behavior of component offsets */ + /* in composites. Apple says that they should be scaled by the scale */ + /* factors in the transformation matrix (roughly, it's more complex) */ + /* while MS says they should not. OpenType defines two bits in the */ + /* composite flags array which can be used to disambiguate, but old */ + /* fonts will not have them. */ + /* */ + /* http://partners.adobe.com/asn/developer/opentype/glyf.html */ + /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */ + /* */ +#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_GX_VAR_SUPPORT if you want to include */ + /* support for Apple's distortable font technology (fvar, gvar, cvar, */ + /* and avar tables). This has many similarities to Type 1 Multiple */ + /* Masters support. */ + /* */ +#define TT_CONFIG_OPTION_GX_VAR_SUPPORT + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */ + /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */ + /* required. */ + /* */ +#define T1_MAX_DICT_DEPTH 5 + + + /*************************************************************************/ + /* */ + /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ + /* calls during glyph loading. */ + /* */ +#define T1_MAX_SUBRS_CALLS 16 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */ + /* minimum of 16 is required. */ + /* */ + /* The Chinese font MingTiEG-Medium (CNS 11643 character set) needs 256. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 256 + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of `t1afm', which is in charge of reading Type 1 AFM */ + /* files into an existing face. Note that if set, the T1 driver will be */ + /* unable to produce kerning distances. */ + /* */ +#undef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of the Multiple Masters font support in the Type 1 */ + /* driver. */ + /* */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + + /* */ + +/* + * The FT_CONFIG_OPTION_CHESTER_XXXX macros are used to toggle some recent + * improvements to the auto-hinter contributed by David Chester. They will + * most likely disappear completely in the next release. For now, you + * should always keep them defined. + * + */ +#define FT_CONFIG_OPTION_CHESTER_HINTS + +#ifdef FT_CONFIG_OPTION_CHESTER_HINTS + +#define FT_CONFIG_CHESTER_SMALL_F +#define FT_CONFIG_CHESTER_ASCENDER +#define FT_CONFIG_CHESTER_SERIF +#define FT_CONFIG_CHESTER_STEM +#define FT_CONFIG_CHESTER_BLUE_SCALE + +#endif /* FT_CONFIG_OPTION_CHESTER_HINTS */ + +FT_END_HEADER + + +#endif /* __FTOPTION_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/config/ftstdlib.h b/Utilities/vtkfreetype/include/freetype/config/ftstdlib.h new file mode 100644 index 0000000..db2f3db --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/config/ftstdlib.h @@ -0,0 +1,148 @@ +/***************************************************************************/ +/* */ +/* ftstdlib.h */ +/* */ +/* ANSI-specific library and header configuration file (specification */ +/* only). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to group all #includes to the ANSI C library that */ + /* FreeType normally requires. It also defines macros to rename the */ + /* standard functions within the FreeType source code. */ + /* */ + /* Load a file which defines __FTSTDLIB_H__ before this one to override */ + /* it. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTSTDLIB_H__ +#define __FTSTDLIB_H__ + + + /**********************************************************************/ + /* */ + /* integer limits */ + /* */ + /* UINT_MAX and ULONG_MAX are used to automatically compute the size */ + /* of `int' and `long' in bytes at compile-time. So far, this works */ + /* for all platforms the library has been tested on. */ + /* */ + /* Note that on the extremely rare platforms that do not provide */ + /* integer types that are _exactly_ 16 and 32 bits wide (e.g. some */ + /* old Crays where `int' is 36 bits), we do not make any guarantee */ + /* about the correct behaviour of FT2 with all fonts. */ + /* */ + /* In these case, "ftconfig.h" will refuse to compile anyway with a */ + /* message like "couldn't find 32-bit type" or something similar. */ + /* */ + /* IMPORTANT NOTE: We do not define aliases for heap management and */ + /* i/o routines (i.e. malloc/free/fopen/fread/...) */ + /* since these functions should all be encapsulated */ + /* by platform-specific implementations of */ + /* "ftsystem.c". */ + /* */ + /**********************************************************************/ + + +#include <limits.h> + +#define FT_UINT_MAX UINT_MAX +#define FT_ULONG_MAX ULONG_MAX + + + /**********************************************************************/ + /* */ + /* character and string processing */ + /* */ + /**********************************************************************/ + + +#include <ctype.h> + +#define ft_isalnum isalnum +#define ft_isupper isupper +#define ft_islower islower +#define ft_isdigit isdigit +#define ft_isxdigit isxdigit + + +#include <string.h> + +#define ft_memcmp memcmp +#define ft_memcpy memcpy +#define ft_memmove memmove +#define ft_memset memset +#define ft_strcat strcat +#define ft_strcmp strcmp +#define ft_strcpy strcpy +#define ft_strlen strlen +#define ft_strncmp strncmp +#define ft_strncpy strncpy +#define ft_strrchr strrchr + + +#include <stdio.h> + +#define ft_sprintf sprintf + + + /**********************************************************************/ + /* */ + /* sorting */ + /* */ + /**********************************************************************/ + + +#include <stdlib.h> + +#define ft_qsort qsort +#define ft_exit exit /* only used to exit from unhandled exceptions */ + +#define ft_atol atol + + + /**********************************************************************/ + /* */ + /* execution control */ + /* */ + /**********************************************************************/ + +#if defined(__sgi) && !defined(__GNUC__) +# if (_COMPILER_VERSION >= 730) +# pragma set woff 3505 +# endif +#endif +#include <setjmp.h> + +#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */ + /* jmp_buf is defined as a macro */ + /* on certain platforms */ + +#define ft_setjmp setjmp /* same thing here */ +#define ft_longjmp longjmp /* " */ + + + /* the following is only used for debugging purposes, i.e. when */ + /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE are defined */ + /* */ +#include <stdarg.h> + + +#endif /* __FTSTDLIB_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/freetype.h b/Utilities/vtkfreetype/include/freetype/freetype.h new file mode 100644 index 0000000..3780a28 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/freetype.h @@ -0,0 +1,3083 @@ +/***************************************************************************/ +/* */ +/* freetype.h */ +/* */ +/* FreeType high-level API and common types (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FT_FREETYPE_H +#error "`ft2build.h' hasn't been included yet!" +#error "Please always use macros to include FreeType header files." +#error "Example:" +#error " #include <ft2build.h>" +#error " #include FT_FREETYPE_H" +#endif + + +#ifndef __FREETYPE_H__ +#define __FREETYPE_H__ + + + /*************************************************************************/ + /* */ + /* The `raster' component duplicates some of the declarations in */ + /* freetype.h for stand-alone use if _FREETYPE_ isn't defined. */ + /* */ + + + /*************************************************************************/ + /* */ + /* The FREETYPE_MAJOR and FREETYPE_MINOR macros are used to version the */ + /* new FreeType design, which is able to host several kinds of font */ + /* drivers. It starts at 2.0. */ + /* */ +#define FREETYPE_MAJOR 2 +#define FREETYPE_MINOR 1 +#define FREETYPE_PATCH 9 + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_ERRORS_H +#include FT_TYPES_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S I C T Y P E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* base_interface */ + /* */ + /* <Title> */ + /* Base Interface */ + /* */ + /* <Abstract> */ + /* The FreeType 2 base font interface. */ + /* */ + /* <Description> */ + /* This section describes the public high-level API of FreeType 2. */ + /* */ + /* <Order> */ + /* FT_Library */ + /* FT_Face */ + /* FT_Size */ + /* FT_GlyphSlot */ + /* FT_CharMap */ + /* FT_Encoding */ + /* */ + /* FT_FaceRec */ + /* */ + /* FT_FACE_FLAG_SCALABLE */ + /* FT_FACE_FLAG_FIXED_SIZES */ + /* FT_FACE_FLAG_FIXED_WIDTH */ + /* FT_FACE_FLAG_HORIZONTAL */ + /* FT_FACE_FLAG_VERTICAL */ + /* FT_FACE_FLAG_SFNT */ + /* FT_FACE_FLAG_KERNING */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS */ + /* FT_FACE_FLAG_GLYPH_NAMES */ + /* FT_FACE_FLAG_EXTERNAL_STREAM */ + /* FT_FACE_FLAG_FAST_GLYPHS */ + /* */ + /* FT_STYLE_FLAG_BOLD */ + /* FT_STYLE_FLAG_ITALIC */ + /* */ + /* FT_SizeRec */ + /* FT_Size_Metrics */ + /* */ + /* FT_GlyphSlotRec */ + /* FT_Glyph_Metrics */ + /* FT_SubGlyph */ + /* */ + /* FT_Bitmap_Size */ + /* */ + /* FT_Init_FreeType */ + /* FT_Done_FreeType */ + /* FT_Library_Version */ + /* */ + /* FT_New_Face */ + /* FT_Done_Face */ + /* FT_New_Memory_Face */ + /* FT_Open_Face */ + /* FT_Open_Args */ + /* FT_Parameter */ + /* FT_Attach_File */ + /* FT_Attach_Stream */ + /* */ + /* FT_Set_Char_Size */ + /* FT_Set_Pixel_Sizes */ + /* FT_Set_Transform */ + /* FT_Load_Glyph */ + /* FT_Get_Char_Index */ + /* FT_Get_Name_Index */ + /* FT_Load_Char */ + /* */ + /* FT_OPEN_MEMORY */ + /* FT_OPEN_STREAM */ + /* FT_OPEN_PATHNAME */ + /* FT_OPEN_DRIVER */ + /* FT_OPEN_PARAMS */ + /* */ + /* FT_LOAD_DEFAULT */ + /* FT_LOAD_RENDER */ + /* FT_LOAD_MONOCHROME */ + /* FT_LOAD_LINEAR_DESIGN */ + /* FT_LOAD_NO_SCALE */ + /* FT_LOAD_NO_HINTING */ + /* FT_LOAD_NO_BITMAP */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* FT_LOAD_VERTICAL_LAYOUT */ + /* FT_LOAD_IGNORE_TRANSFORM */ + /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */ + /* FT_LOAD_FORCE_AUTOHINT */ + /* FT_LOAD_NO_RECURSE */ + /* FT_LOAD_PEDANTIC */ + /* */ + /* FT_LOAD_TARGET_NORMAL */ + /* FT_LOAD_TARGET_LIGHT */ + /* FT_LOAD_TARGET_MONO */ + /* FT_LOAD_TARGET_LCD */ + /* FT_LOAD_TARGET_LCD_V */ + /* */ + /* FT_Render_Glyph */ + /* FT_Render_Mode */ + /* FT_Get_Kerning */ + /* FT_Kerning_Mode */ + /* FT_Get_Glyph_Name */ + /* FT_Get_Postscript_Name */ + /* */ + /* FT_CharMapRec */ + /* FT_Select_Charmap */ + /* FT_Set_Charmap */ + /* FT_Get_Charmap_Index */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Glyph_Metrics */ + /* */ + /* <Description> */ + /* A structure used to model the metrics of a single glyph. The */ + /* values are expressed in 26.6 fractional pixel format; if the flag */ + /* FT_LOAD_NO_SCALE is used, values are returned in font units */ + /* instead. */ + /* */ + /* <Fields> */ + /* width :: */ + /* The glyph's width. */ + /* */ + /* height :: */ + /* The glyph's height. */ + /* */ + /* horiBearingX :: */ + /* Left side bearing for horizontal layout. */ + /* */ + /* horiBearingY :: */ + /* Top side bearing for horizontal layout. */ + /* */ + /* horiAdvance :: */ + /* Advance width for horizontal layout. */ + /* */ + /* vertBearingX :: */ + /* Left side bearing for vertical layout. */ + /* */ + /* vertBearingY :: */ + /* Top side bearing for vertical layout. */ + /* */ + /* vertAdvance :: */ + /* Advance height for vertical layout. */ + /* */ + typedef struct FT_Glyph_Metrics_ + { + FT_Pos width; + FT_Pos height; + + FT_Pos horiBearingX; + FT_Pos horiBearingY; + FT_Pos horiAdvance; + + FT_Pos vertBearingX; + FT_Pos vertBearingY; + FT_Pos vertAdvance; + + } FT_Glyph_Metrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Bitmap_Size */ + /* */ + /* <Description> */ + /* This structure models the size of a bitmap strike (i.e., a bitmap */ + /* instance of the font for a given resolution) in a fixed-size font */ + /* face. It is used for the `available_sizes' field of the */ + /* @FT_FaceRec structure. */ + /* */ + /* <Fields> */ + /* height :: The (vertical) baseline-to-baseline distance in pixels. */ + /* It makes most sense to define the height of a bitmap */ + /* font in this way. */ + /* */ + /* width :: The average width of the font (in pixels). Since the */ + /* algorithms to compute this value are different for the */ + /* various bitmap formats, it can only give an additional */ + /* hint if the `height' value isn't sufficient to select */ + /* the proper font. For monospaced fonts the average width */ + /* is the same as the maximum width. */ + /* */ + /* size :: The point size in 26.6 fractional format this font shall */ + /* represent (for a given vertical resolution). */ + /* */ + /* x_ppem :: The horizontal ppem value (in 26.6 fractional format). */ + /* */ + /* y_ppem :: The vertical ppem value (in 26.6 fractional format). */ + /* Usually, this is the `nominal' pixel height of the font. */ + /* */ + /* <Note> */ + /* The values in this structure are taken from the bitmap font. If */ + /* the font doesn't provide a parameter it is set to zero to indicate */ + /* that the information is not available. */ + /* */ + /* The following formula converts from dpi to ppem: */ + /* */ + /* ppem = size * dpi / 72 */ + /* */ + /* where `size' is in points. */ + /* */ + /* Windows FNT: */ + /* The `size' parameter is not reliable: There exist fonts (e.g., */ + /* app850.fon) which have a wrong size for some subfonts; x_ppem */ + /* and y_ppem are thus set equal to pixel width and height given in */ + /* in the Windows FNT header. */ + /* */ + /* TrueType embedded bitmaps: */ + /* `size', `width', and `height' values are not contained in the */ + /* bitmap strike itself. They are computed from the global font */ + /* parameters. */ + /* */ + typedef struct FT_Bitmap_Size_ + { + FT_Short height; + FT_Short width; + + FT_Pos size; + + FT_Pos x_ppem; + FT_Pos y_ppem; + + } FT_Bitmap_Size; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Library */ + /* */ + /* <Description> */ + /* A handle to a FreeType library instance. Each `library' is */ + /* completely independent from the others; it is the `root' of a set */ + /* of objects like fonts, faces, sizes, etc. */ + /* */ + /* It also embeds a memory manager (see @FT_Memory), as well as a */ + /* scan-line converter object (see @FT_Raster). */ + /* */ + /* <Note> */ + /* Library objects are normally created by @FT_Init_FreeType, and */ + /* destroyed with @FT_Done_FreeType. */ + /* */ + typedef struct FT_LibraryRec_ *FT_Library; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Module */ + /* */ + /* <Description> */ + /* A handle to a given FreeType module object. Each module can be a */ + /* font driver, a renderer, or anything else that provides services */ + /* to the formers. */ + /* */ + typedef struct FT_ModuleRec_* FT_Module; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Driver */ + /* */ + /* <Description> */ + /* A handle to a given FreeType font driver object. Each font driver */ + /* is a special module capable of creating faces from font files. */ + /* */ + typedef struct FT_DriverRec_* FT_Driver; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Renderer */ + /* */ + /* <Description> */ + /* A handle to a given FreeType renderer. A renderer is a special */ + /* module in charge of converting a glyph image to a bitmap, when */ + /* necessary. Each renderer supports a given glyph image format, and */ + /* one or more target surface depths. */ + /* */ + typedef struct FT_RendererRec_* FT_Renderer; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Face */ + /* */ + /* <Description> */ + /* A handle to a given typographic face object. A face object models */ + /* a given typeface, in a given style. */ + /* */ + /* <Note> */ + /* Each face object also owns a single @FT_GlyphSlot object, as well */ + /* as one or more @FT_Size objects. */ + /* */ + /* Use @FT_New_Face or @FT_Open_Face to create a new face object from */ + /* a given filepathname or a custom input stream. */ + /* */ + /* Use @FT_Done_Face to destroy it (along with its slot and sizes). */ + /* */ + /* <Also> */ + /* The @FT_FaceRec details the publicly accessible fields of a given */ + /* face object. */ + /* */ + typedef struct FT_FaceRec_* FT_Face; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Size */ + /* */ + /* <Description> */ + /* A handle to a given size object. Such an object models the data */ + /* that depends on the current _resolution_ and _character size_ in a */ + /* given @FT_Face. */ + /* */ + /* <Note> */ + /* Each face object owns one or more sizes. There is however a */ + /* single _active_ size for the face at any time that will be used by */ + /* functions like @FT_Load_Glyph, @FT_Get_Kerning, etc. */ + /* */ + /* You can use the @FT_Activate_Size API to change the current */ + /* active size of any given face. */ + /* */ + /* <Also> */ + /* The @FT_SizeRec structure details the publicly accessible fields */ + /* of a given face object. */ + /* */ + typedef struct FT_SizeRec_* FT_Size; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_GlyphSlot */ + /* */ + /* <Description> */ + /* A handle to a given `glyph slot'. A slot is a container where it */ + /* is possible to load any one of the glyphs contained in its parent */ + /* face. */ + /* */ + /* In other words, each time you call @FT_Load_Glyph or */ + /* @FT_Load_Char, the slot's content is erased by the new glyph data, */ + /* i.e. the glyph's metrics, its image (bitmap or outline), and */ + /* other control information. */ + /* */ + /* <Also> */ + /* @FT_GlyphSlotRec details the publicly accessible glyph fields. */ + /* */ + typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_CharMap */ + /* */ + /* <Description> */ + /* A handle to a given character map. A charmap is used to translate */ + /* character codes in a given encoding into glyph indexes for its */ + /* parent's face. Some font formats may provide several charmaps per */ + /* font. */ + /* */ + /* Each face object owns zero or more charmaps, but only one of them */ + /* can be "active" and used by @FT_Get_Char_Index or @FT_Load_Char. */ + /* */ + /* The list of available charmaps in a face is available through the */ + /* "face->num_charmaps" and "face->charmaps" fields of @FT_FaceRec. */ + /* */ + /* The currently active charmap is available as "face->charmap". */ + /* You should call @FT_Set_Charmap to change it. */ + /* */ + /* <Note> */ + /* When a new face is created (either through @FT_New_Face or */ + /* @FT_Open_Face), the library looks for a Unicode charmap within */ + /* the list and automatically activates it. */ + /* */ + /* <Also> */ + /* The @FT_CharMapRec details the publicly accessible fields of a */ + /* given character map. */ + /* */ + typedef struct FT_CharMapRec_* FT_CharMap; + + + /*************************************************************************/ + /* */ + /* <Macro> */ + /* FT_ENC_TAG */ + /* */ + /* <Description> */ + /* This macro converts four letter tags into an unsigned long. It is */ + /* used to define "encoding" identifiers (see @FT_Encoding). */ + /* */ + /* <Note> */ + /* Since many 16bit compilers don't like 32bit enumerations, you */ + /* should redefine this macro in case of problems to something like */ + /* this: */ + /* */ + /* #define FT_ENC_TAG( value, a, b, c, d ) value */ + /* */ + /* to get a simple enumeration without assigning special numbers. */ + /* */ + +#ifndef FT_ENC_TAG +#define FT_ENC_TAG( value, a, b, c, d ) \ + value = ( ( (FT_UInt32)(a) << 24 ) | \ + ( (FT_UInt32)(b) << 16 ) | \ + ( (FT_UInt32)(c) << 8 ) | \ + (FT_UInt32)(d) ) + +#endif /* FT_ENC_TAG */ + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Encoding */ + /* */ + /* <Description> */ + /* An enumeration used to specify encodings supported by charmaps. */ + /* Used in the @FT_Select_Charmap API function. */ + /* */ + /* <Note> */ + /* Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */ + /* all character codes must be expressed as FT_Longs. */ + /* */ + /* The values of this type correspond to specific character */ + /* repertories (i.e. charsets), and not to text encoding methods */ + /* (like UTF-8, UTF-16, GB2312_EUC, etc.). */ + /* */ + /* Other encodings might be defined in the future. */ + /* */ + /* <Values> */ + /* FT_ENCODING_NONE :: */ + /* The encoding value 0 is reserved. */ + /* */ + /* FT_ENCODING_UNICODE :: */ + /* Corresponds to the Unicode character set. This value covers */ + /* all versions of the Unicode repertoire, including ASCII and */ + /* Latin-1. Most fonts include a Unicode charmap, but not all */ + /* of them. */ + /* */ + /* FT_ENCODING_MS_SYMBOL :: */ + /* Corresponds to the Microsoft Symbol encoding, used to encode */ + /* mathematical symbols in the 32..255 character code range. For */ + /* more information, see `http://www.ceviz.net/symbol.htm'. */ + /* */ + /* FT_ENCODING_SJIS :: */ + /* Corresponds to Japanese SJIS encoding. More info at */ + /* at `http://langsupport.japanreference.com/encoding.shtml'. */ + /* See note on multi-byte encodings below. */ + /* */ + /* FT_ENCODING_GB2312 :: */ + /* Corresponds to an encoding system for Simplified Chinese as used */ + /* used in mainland China. */ + /* */ + /* FT_ENCODING_BIG5 :: */ + /* Corresponds to an encoding system for Traditional Chinese as used */ + /* in Taiwan and Hong Kong. */ + /* */ + /* FT_ENCODING_WANSUNG :: */ + /* Corresponds to the Korean encoding system known as Wansung. */ + /* For more information see */ + /* `http://www.microsoft.com/typography/unicode/949.txt'. */ + /* */ + /* FT_ENCODING_JOHAB :: */ + /* The Korean standard character set (KS C-5601-1992), which */ + /* corresponds to MS Windows code page 1361. This character set */ + /* includes all possible Hangeul character combinations. */ + /* */ + /* FT_ENCODING_ADOBE_LATIN_1 :: */ + /* Corresponds to a Latin-1 encoding as defined in a Type 1 */ + /* Postscript font. It is limited to 256 character codes. */ + /* */ + /* FT_ENCODING_ADOBE_STANDARD :: */ + /* Corresponds to the Adobe Standard encoding, as found in Type 1, */ + /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ + /* codes. */ + /* */ + /* FT_ENCODING_ADOBE_EXPERT :: */ + /* Corresponds to the Adobe Expert encoding, as found in Type 1, */ + /* CFF, and OpenType/CFF fonts. It is limited to 256 character */ + /* codes. */ + /* */ + /* FT_ENCODING_ADOBE_CUSTOM :: */ + /* Corresponds to a custom encoding, as found in Type 1, CFF, and */ + /* OpenType/CFF fonts. It is limited to 256 character codes. */ + /* */ + /* FT_ENCODING_APPLE_ROMAN :: */ + /* Corresponds to the 8-bit Apple roman encoding. Many TrueType and */ + /* OpenType fonts contain a charmap for this encoding, since older */ + /* versions of Mac OS are able to use it. */ + /* */ + /* FT_ENCODING_OLD_LATIN_2 :: */ + /* This value is deprecated and was never used nor reported by */ + /* FreeType. Don't use or test for it. */ + /* */ + /* FT_ENCODING_MS_SJIS :: */ + /* Same as FT_ENCODING_SJIS. Deprecated. */ + /* */ + /* FT_ENCODING_MS_GB2312 :: */ + /* Same as FT_ENCODING_GB2312. Deprecated. */ + /* */ + /* FT_ENCODING_MS_BIG5 :: */ + /* Same as FT_ENCODING_BIG5. Deprecated. */ + /* */ + /* FT_ENCODING_MS_WANSUNG :: */ + /* Same as FT_ENCODING_WANSUNG. Deprecated. */ + /* */ + /* FT_ENCODING_MS_JOHAB :: */ + /* Same as FT_ENCODING_JOHAB. Deprecated. */ + /* */ + /* <Note> */ + /* By default, FreeType automatically synthetizes a Unicode charmap */ + /* for Postscript fonts, using their glyph names dictionaries. */ + /* However, it will also report the encodings defined explicitly in */ + /* the font file, for the cases when they are needed, with the Adobe */ + /* values as well. */ + /* */ + /* FT_ENCODING_NONE is set by the BDF and PCF drivers if the charmap */ + /* is neither Unicode nor ISO-8859-1 (otherwise it is set to */ + /* FT_ENCODING_UNICODE). Use `FT_Get_BDF_Charset_ID' to find out */ + /* which encoding is really present. If, for example, the */ + /* `cs_registry' field is `KOI8' and the `cs_encoding' field is `R', */ + /* the font is encoded in KOI8-R. */ + /* */ + /* FT_ENCODING_NONE is always set (with a single exception) by the */ + /* winfonts driver. Use `FT_Get_WinFNT_Header' and examine the */ + /* `charset' field of the `FT_WinFNT_HeaderRec' structure to find out */ + /* which encoding is really present. For example, FT_WinFNT_ID_CP1251 */ + /* (204) means Windows code page 1251 (for Russian). */ + /* */ + /* FT_ENCODING_NONE is set if `platform_id' is `TT_PLATFORM_MACINTOSH' */ + /* and `encoding_id' is not `TT_MAC_ID_ROMAN' (otherwise it is set to */ + /* FT_ENCODING_APPLE_ROMAN). */ + /* */ + /* If `platform_id' is `TT_PLATFORM_MACINTOSH', use the function */ + /* `FT_Get_CMap_Language_ID' to query the Mac language ID which may be */ + /* needed to be able to distinguish Apple encoding variants. See */ + /* */ + /* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/README.TXT */ + /* */ + /* to get an idea how to do that. Basically, if the language ID is 0, */ + /* dont use it, otherwise subtract 1 from the language ID. Then */ + /* examine `encoding_id'. If, for example, `encoding_id' is */ + /* `TT_MAC_ID_ROMAN' and the language ID (minus 1) is */ + /* `TT_MAC_LANGID_GREEK', it is the Greek encoding, not Roman. */ + /* `TT_MAC_ID_ARABIC' with `TT_MAC_LANGID_FARSI' means the Farsi */ + /* variant the Arabic encoding. */ + /* */ + typedef enum FT_Encoding_ + { + FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ), + + FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ), + FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ), + + FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ), + FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ), + FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ), + FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ), + FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ), + + /* for backwards compatibility */ + FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS, + FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312, + FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5, + FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG, + FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB, + + FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ), + FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ), + FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ), + FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ), + + FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ), + + FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' ) + + } FT_Encoding; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_encoding_xxx */ + /* */ + /* <Description> */ + /* These constants are deprecated; use the corresponding @FT_Encoding */ + /* values instead. */ + /* */ + /* <Values> */ + /* ft_encoding_none :: see @FT_ENCODING_NONE */ + /* ft_encoding_unicode :: see @FT_ENCODING_UNICODE */ + /* ft_encoding_latin_2 :: see @FT_ENCODING_OLD_LATIN_2 */ + /* ft_encoding_symbol :: see @FT_ENCODING_MS_SYMBOL */ + /* ft_encoding_sjis :: see @FT_ENCODING_SJIS */ + /* ft_encoding_gb2312 :: see @FT_ENCODING_GB2312 */ + /* ft_encoding_big5 :: see @FT_ENCODING_BIG5 */ + /* ft_encoding_wansung :: see @FT_ENCODING_WANSUNG */ + /* ft_encoding_johab :: see @FT_ENCODING_JOHAB */ + /* */ + /* ft_encoding_adobe_standard :: see @FT_ENCODING_ADOBE_STANDARD */ + /* ft_encoding_adobe_expert :: see @FT_ENCODING_ADOBE_EXPERT */ + /* ft_encoding_adobe_custom :: see @FT_ENCODING_ADOBE_CUSTOM */ + /* ft_encoding_latin_1 :: see @FT_ENCODING_ADOBE_LATIN_1 */ + /* */ + /* ft_encoding_apple_roman :: see @FT_ENCODING_APPLE_ROMAN */ + /* */ +#define ft_encoding_none FT_ENCODING_NONE +#define ft_encoding_unicode FT_ENCODING_UNICODE +#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL +#define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1 +#define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2 +#define ft_encoding_sjis FT_ENCODING_SJIS +#define ft_encoding_gb2312 FT_ENCODING_GB2312 +#define ft_encoding_big5 FT_ENCODING_BIG5 +#define ft_encoding_wansung FT_ENCODING_WANSUNG +#define ft_encoding_johab FT_ENCODING_JOHAB + +#define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD +#define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT +#define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM +#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_CharMapRec */ + /* */ + /* <Description> */ + /* The base charmap structure. */ + /* */ + /* <Fields> */ + /* face :: A handle to the parent face object. */ + /* */ + /* encoding :: An @FT_Encoding tag identifying the charmap. Use */ + /* this with @FT_Select_Charmap. */ + /* */ + /* platform_id :: An ID number describing the platform for the */ + /* following encoding ID. This comes directly from */ + /* the TrueType specification and should be emulated */ + /* for other formats. */ + /* */ + /* encoding_id :: A platform specific encoding number. This also */ + /* comes from the TrueType specification and should be */ + /* emulated similarly. */ + /* */ + typedef struct FT_CharMapRec_ + { + FT_Face face; + FT_Encoding encoding; + FT_UShort platform_id; + FT_UShort encoding_id; + + } FT_CharMapRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S E O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Face_Internal */ + /* */ + /* <Description> */ + /* An opaque handle to an FT_Face_InternalRec structure, used to */ + /* model private data of a given @FT_Face object. */ + /* */ + /* This structure might change between releases of FreeType 2 and is */ + /* not generally available to client applications. */ + /* */ + typedef struct FT_Face_InternalRec_* FT_Face_Internal; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_FaceRec */ + /* */ + /* <Description> */ + /* FreeType root face class structure. A face object models the */ + /* resolution and point-size independent data found in a font file. */ + /* */ + /* <Fields> */ + /* num_faces :: In the case where the face is located in a */ + /* collection (i.e., a file which embeds */ + /* several faces), this is the total number of */ + /* faces found in the resource. 1 by default. */ + /* Accessing non-existent face indices causes */ + /* an error. */ + /* */ + /* face_index :: The index of the face in its font file. */ + /* Usually, this is 0 for all normal font */ + /* formats. It can be > 0 in the case of */ + /* collections (which embed several fonts in a */ + /* single resource/file). */ + /* */ + /* face_flags :: A set of bit flags that give important */ + /* information about the face; see the */ + /* @FT_FACE_FLAG_XXX constants for details. */ + /* */ + /* style_flags :: A set of bit flags indicating the style of */ + /* the face (i.e., italic, bold, underline, */ + /* etc). See the @FT_STYLE_FLAG_XXX */ + /* constants. */ + /* */ + /* num_glyphs :: The total number of glyphs in the face. */ + /* */ + /* family_name :: The face's family name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's family (like `Times New */ + /* Roman', `Bodoni', `Garamond', etc). This */ + /* is a least common denominator used to list */ + /* fonts. Some formats (TrueType & OpenType) */ + /* provide localized and Unicode versions of */ + /* this string. Applications should use the */ + /* format specific interface to access them. */ + /* */ + /* style_name :: The face's style name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's style (like `Italic', */ + /* `Bold', `Condensed', etc). Not all font */ + /* formats provide a style name, so this field */ + /* is optional, and can be set to NULL. As */ + /* for `family_name', some formats provide */ + /* localized/Unicode versions of this string. */ + /* Applications should use the format specific */ + /* interface to access them. */ + /* */ + /* num_fixed_sizes :: The number of fixed sizes available in this */ + /* face. This should be set to 0 for scalable */ + /* fonts, unless its face includes a set of */ + /* glyphs (called a `strike') for the */ + /* specified sizes. */ + /* */ + /* available_sizes :: An array of sizes specifying the available */ + /* bitmap/graymap sizes that are contained in */ + /* in the font face. Should be set to NULL if */ + /* the field `num_fixed_sizes' is set to 0. */ + /* */ + /* num_charmaps :: The total number of character maps in the */ + /* face. */ + /* */ + /* charmaps :: A table of pointers to the face's charmaps. */ + /* Used to scan the list of available charmaps */ + /* -- this table might change after a call to */ + /* @FT_Attach_File or @FT_Attach_Stream (e.g. */ + /* if used to hook an additional encoding or */ + /* CMap to the face object). */ + /* */ + /* generic :: A field reserved for client uses. See the */ + /* @FT_Generic type description. */ + /* */ + /* bbox :: The font bounding box. Coordinates are */ + /* expressed in font units (see units_per_EM). */ + /* The box is large enough to contain any */ + /* glyph from the font. Thus, bbox.yMax can */ + /* be seen as the `maximal ascender', */ + /* bbox.yMin as the `minimal descender', and */ + /* the maximal glyph width is given by */ + /* `bbox.xMax-bbox.xMin' (not to be confused */ + /* with the maximal _advance_width_). Only */ + /* relevant for scalable formats. */ + /* */ + /* units_per_EM :: The number of font units per EM square for */ + /* this face. This is typically 2048 for */ + /* TrueType fonts, 1000 for Type1 fonts, and */ + /* should be set to the (unrealistic) value 1 */ + /* for fixed-sizes fonts. Only relevant for */ + /* scalable formats. */ + /* */ + /* ascender :: The face's ascender is the vertical */ + /* distance from the baseline to the topmost */ + /* point of any glyph in the face. This */ + /* field's value is positive, expressed in */ + /* font units. Some font designs use a value */ + /* different from `bbox.yMax'. Only relevant */ + /* for scalable formats. */ + /* */ + /* descender :: The face's descender is the vertical */ + /* distance from the baseline to the */ + /* bottommost point of any glyph in the face. */ + /* This field's value is *negative* for values */ + /* below the baseline. It is expressed in */ + /* font units. Some font designs use a value */ + /* different from `bbox.yMin'. Only relevant */ + /* for scalable formats. */ + /* */ + /* height :: The face's height is the vertical distance */ + /* from one baseline to the next when writing */ + /* several lines of text. Its value is always */ + /* positive, expressed in font units. The */ + /* value can be computed as */ + /* `ascender+descender+line_gap' where the */ + /* value of `line_gap' is also called */ + /* `external leading'. Only relevant for */ + /* scalable formats. */ + /* */ + /* max_advance_width :: The maximal advance width, in font units, */ + /* for all glyphs in this face. This can be */ + /* used to make word wrapping computations */ + /* faster. Only relevant for scalable */ + /* formats. */ + /* */ + /* max_advance_height :: The maximal advance height, in font units, */ + /* for all glyphs in this face. This is only */ + /* relevant for vertical layouts, and should */ + /* be set to the `height' for fonts that do */ + /* not provide vertical metrics. Only */ + /* relevant for scalable formats. */ + /* */ + /* underline_position :: The position, in font units, of the */ + /* underline line for this face. It's the */ + /* center of the underlining stem. Only */ + /* relevant for scalable formats. */ + /* */ + /* underline_thickness :: The thickness, in font units, of the */ + /* underline for this face. Only relevant for */ + /* scalable formats. */ + /* */ + /* glyph :: The face's associated glyph slot(s). This */ + /* object is created automatically with a new */ + /* face object. However, certain kinds of */ + /* applications (mainly tools like converters) */ + /* can need more than one slot to ease their */ + /* task. */ + /* */ + /* size :: The current active size for this face. */ + /* */ + /* charmap :: The current active charmap for this face. */ + /* */ + typedef struct FT_FaceRec_ + { + FT_Long num_faces; + FT_Long face_index; + + FT_Long face_flags; + FT_Long style_flags; + + FT_Long num_glyphs; + + FT_String* family_name; + FT_String* style_name; + + FT_Int num_fixed_sizes; + FT_Bitmap_Size* available_sizes; + + FT_Int num_charmaps; + FT_CharMap* charmaps; + + FT_Generic generic; + + /*# the following are only relevant to scalable outlines */ + FT_BBox bbox; + + FT_UShort units_per_EM; + FT_Short ascender; + FT_Short descender; + FT_Short height; + + FT_Short max_advance_width; + FT_Short max_advance_height; + + FT_Short underline_position; + FT_Short underline_thickness; + + FT_GlyphSlot glyph; + FT_Size size; + FT_CharMap charmap; + + /*@private begin */ + + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + + FT_ListRec sizes_list; + + FT_Generic autohint; + void* extensions; + + FT_Face_Internal internal; + + /*@private end */ + + } FT_FaceRec; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_FACE_FLAG_XXX */ + /* */ + /* <Description> */ + /* A list of bit flags used in the `face_flags' field of the */ + /* @FT_FaceRec structure. They inform client applications of */ + /* properties of the corresponding face. */ + /* */ + /* <Values> */ + /* FT_FACE_FLAG_SCALABLE :: */ + /* Indicates that the face provides vectorial outlines. This */ + /* doesn't prevent embedded bitmaps, i.e., a face can have both */ + /* this bit and @FT_FACE_FLAG_FIXED_SIZES set. */ + /* */ + /* FT_FACE_FLAG_FIXED_SIZES :: */ + /* Indicates that the face contains `fixed sizes', i.e., bitmap */ + /* strikes for some given pixel sizes. See the `num_fixed_sizes' */ + /* and `available_sizes' fields of @FT_FaceRec. */ + /* */ + /* FT_FACE_FLAG_FIXED_WIDTH :: */ + /* Indicates that the face contains fixed-width characters (like */ + /* Courier, Lucido, MonoType, etc.). */ + /* */ + /* FT_FACE_FLAG_SFNT :: */ + /* Indicates that the face uses the `sfnt' storage scheme. For */ + /* now, this means TrueType and OpenType. */ + /* */ + /* FT_FACE_FLAG_HORIZONTAL :: */ + /* Indicates that the face contains horizontal glyph metrics. This */ + /* should be set for all common formats. */ + /* */ + /* FT_FACE_FLAG_VERTICAL :: */ + /* Indicates that the face contains vertical glyph metrics. This */ + /* is only available in some formats, not all of them. */ + /* */ + /* FT_FACE_FLAG_KERNING :: */ + /* Indicates that the face contains kerning information. If set, */ + /* the kerning distance can be retrieved through the function */ + /* @FT_Get_Kerning. Note that if unset, this function will always */ + /* return the vector (0,0). */ + /* */ + /* FT_FACE_FLAG_FAST_GLYPHS :: */ + /* THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT. */ + /* */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS :: */ + /* Indicates that the font contains multiple masters and is capable */ + /* of interpolating between them. See the multiple-masters */ + /* specific API for details. */ + /* */ + /* FT_FACE_FLAG_GLYPH_NAMES :: */ + /* Indicates that the font contains glyph names that can be */ + /* retrieved through @FT_Get_Glyph_Name. Note that some TrueType */ + /* fonts contain broken glyph name tables. Use the function */ + /* @FT_Has_PS_Glyph_Names when needed. */ + /* */ + /* FT_FACE_FLAG_EXTERNAL_STREAM :: */ + /* Used internally by FreeType to indicate that a face's stream was */ + /* provided by the client application and should not be destroyed */ + /* when @FT_Done_Face is called. Don't read or test this flag. */ + /* */ +#define FT_FACE_FLAG_SCALABLE ( 1L << 0 ) +#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 ) +#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 ) +#define FT_FACE_FLAG_SFNT ( 1L << 3 ) +#define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 ) +#define FT_FACE_FLAG_VERTICAL ( 1L << 5 ) +#define FT_FACE_FLAG_KERNING ( 1L << 6 ) +#define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 ) +#define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 ) +#define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 ) +#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 ) + + /* */ + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_HAS_HORIZONTAL( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains */ + /* horizontal metrics (this is true for all font formats though). */ + /* */ + /* @also: */ + /* @FT_HAS_VERTICAL can be used to check for vertical metrics. */ + /* */ +#define FT_HAS_HORIZONTAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_HORIZONTAL ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_HAS_VERTICAL( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains vertical */ + /* metrics. */ + /* */ +#define FT_HAS_VERTICAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_VERTICAL ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_HAS_KERNING( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains kerning */ + /* data that can be accessed with @FT_Get_Kerning. */ + /* */ +#define FT_HAS_KERNING( face ) \ + ( face->face_flags & FT_FACE_FLAG_KERNING ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_IS_SCALABLE( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains a */ + /* scalable font face (true for TrueType, Type 1, CID, and */ + /* OpenType/CFF font formats. */ + /* */ +#define FT_IS_SCALABLE( face ) \ + ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_IS_SFNT( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains a font */ + /* whose format is based on the SFNT storage scheme. This usually */ + /* means: TrueType fonts, OpenType fonts, as well as SFNT-based */ + /* embedded bitmap fonts. */ + /* */ + /* If this macro is true, all functions defined in @FT_SFNT_NAMES_H */ + /* and @FT_TRUETYPE_TABLES_H are available. */ + /* */ +#define FT_IS_SFNT( face ) \ + ( face->face_flags & FT_FACE_FLAG_SFNT ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_IS_FIXED_WIDTH( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains a font */ + /* face that contains fixed-width (or "monospace", "fixed-pitch", */ + /* etc.) glyphs. */ + /* */ +#define FT_IS_FIXED_WIDTH( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_HAS_FIXED_SIZES( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains some */ + /* embedded bitmaps. See the `available_sizes' field of the */ + /* @FT_FaceRec structure. */ + /* */ +#define FT_HAS_FIXED_SIZES( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) + + + /* */ + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_HAS_FAST_GLYPHS( face ) */ + /* */ + /* @description: */ + /* Deprecated; indicates that the face contains so-called "fast" */ + /* glyph bitmaps. */ + /* */ +#define FT_HAS_FAST_GLYPHS( face ) \ + ( face->face_flags & FT_FACE_FLAG_FAST_GLYPHS ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_HAS_GLYPH_NAMES( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains some */ + /* glyph names that can be accessed through @FT_Get_Glyph_Name. */ + /* */ +#define FT_HAS_GLYPH_NAMES( face ) \ + ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_HAS_MULTIPLE_MASTERS( face ) */ + /* */ + /* @description: */ + /* A macro that returns true whenever a face object contains some */ + /* multiple masters. The functions provided by */ + /* @FT_MULTIPLE_MASTERS_H are then available to choose the exact */ + /* design you want. */ + /* */ +#define FT_HAS_MULTIPLE_MASTERS( face ) \ + ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) + + + /*************************************************************************/ + /* */ + /* <Constant> */ + /* FT_STYLE_FLAG_XXX */ + /* */ + /* <Description> */ + /* A list of bit-flags used to indicate the style of a given face. */ + /* These are used in the `style_flags' field of @FT_FaceRec. */ + /* */ + /* <Values> */ + /* FT_STYLE_FLAG_ITALIC :: */ + /* Indicates that a given face is italicized. */ + /* */ + /* FT_STYLE_FLAG_BOLD :: */ + /* Indicates that a given face is bold. */ + /* */ +#define FT_STYLE_FLAG_ITALIC ( 1 << 0 ) +#define FT_STYLE_FLAG_BOLD ( 1 << 1 ) + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Size_Internal */ + /* */ + /* <Description> */ + /* An opaque handle to an FT_Size_InternalRec structure, used to */ + /* model private data of a given FT_Size object. */ + /* */ + typedef struct FT_Size_InternalRec_* FT_Size_Internal; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Size_Metrics */ + /* */ + /* <Description> */ + /* The size metrics structure returned scaled important distances for */ + /* a given size object. */ + /* */ + /* <Fields> */ + /* x_ppem :: The character width, expressed in integer pixels. */ + /* This is the width of the EM square expressed in */ + /* pixels, hence the term `ppem' (pixels per EM). */ + /* */ + /* y_ppem :: The character height, expressed in integer pixels. */ + /* This is the height of the EM square expressed in */ + /* pixels, hence the term `ppem' (pixels per EM). */ + /* */ + /* x_scale :: A simple 16.16 fixed point format coefficient used */ + /* to scale horizontal distances expressed in font */ + /* units to fractional (26.6) pixel coordinates. */ + /* */ + /* y_scale :: A simple 16.16 fixed point format coefficient used */ + /* to scale vertical distances expressed in font */ + /* units to fractional (26.6) pixel coordinates. */ + /* */ + /* ascender :: The ascender, expressed in 26.6 fixed point */ + /* pixels. Positive for ascenders above the */ + /* baseline. */ + /* */ + /* descender :: The descender, expressed in 26.6 fixed point */ + /* pixels. Negative for descenders below the */ + /* baseline. */ + /* */ + /* height :: The text height, expressed in 26.6 fixed point */ + /* pixels. Always positive. */ + /* */ + /* max_advance :: Maximum horizontal advance, expressed in 26.6 */ + /* fixed point pixels. Always positive. */ + /* */ + /* <Note> */ + /* For scalable fonts, the values of `ascender', `descender', and */ + /* `height' are scaled versions of `face->ascender', */ + /* `face->descender', and `face->height', respectively. */ + /* */ + /* Unfortunately, due to glyph hinting, these values might not be */ + /* exact for certain fonts. They thus must be treated as unreliable */ + /* with an error margin of at least one pixel! */ + /* */ + /* Indeed, the only way to get the exact pixel ascender and descender */ + /* is to render _all_ glyphs. As this would be a definite */ + /* performance hit, it is up to client applications to perform such */ + /* computations. */ + /* */ + typedef struct FT_Size_Metrics_ + { + FT_UShort x_ppem; /* horizontal pixels per EM */ + FT_UShort y_ppem; /* vertical pixels per EM */ + + FT_Fixed x_scale; /* two scales used to convert font units */ + FT_Fixed y_scale; /* to 26.6 frac. pixel coordinates */ + + FT_Pos ascender; /* ascender in 26.6 frac. pixels */ + FT_Pos descender; /* descender in 26.6 frac. pixels */ + FT_Pos height; /* text height in 26.6 frac. pixels */ + FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ + + } FT_Size_Metrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_SizeRec */ + /* */ + /* <Description> */ + /* FreeType root size class structure. A size object models the */ + /* resolution and pointsize dependent data of a given face. */ + /* */ + /* <Fields> */ + /* face :: Handle to the parent face object. */ + /* */ + /* generic :: A typeless pointer, which is unused by the FreeType */ + /* library or any of its drivers. It can be used by */ + /* client applications to link their own data to each size */ + /* object. */ + /* */ + /* metrics :: Metrics for this size object. This field is read-only. */ + /* */ + typedef struct FT_SizeRec_ + { + FT_Face face; /* parent face object */ + FT_Generic generic; /* generic pointer for client uses */ + FT_Size_Metrics metrics; /* size metrics */ + FT_Size_Internal internal; + + } FT_SizeRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_SubGlyph */ + /* */ + /* <Description> */ + /* The subglyph structure is an internal object used to describe */ + /* subglyphs (for example, in the case of composites). */ + /* */ + /* <Note> */ + /* The subglyph implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_SubGlyphRec_* FT_SubGlyph; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Slot_Internal */ + /* */ + /* <Description> */ + /* An opaque handle to an FT_Slot_InternalRec structure, used to */ + /* model private data of a given FT_GlyphSlot object. */ + /* */ + typedef struct FT_Slot_InternalRec_* FT_Slot_Internal; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_GlyphSlotRec */ + /* */ + /* <Description> */ + /* FreeType root glyph slot class structure. A glyph slot is a */ + /* container where individual glyphs can be loaded, be they */ + /* vectorial or bitmap/graymaps. */ + /* */ + /* <Fields> */ + /* library :: A handle to the FreeType library instance */ + /* this slot belongs to. */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* next :: In some cases (like some font tools), several */ + /* glyph slots per face object can be a good */ + /* thing. As this is rare, the glyph slots are */ + /* listed through a direct, single-linked list */ + /* using its `next' field. */ + /* */ + /* generic :: A typeless pointer which is unused by the */ + /* FreeType library or any of its drivers. It */ + /* can be used by client applications to link */ + /* their own data to each glyph slot object. */ + /* */ + /* metrics :: The metrics of the last loaded glyph in the */ + /* slot. The returned values depend on the last */ + /* load flags (see the @FT_Load_Glyph API */ + /* function) and can be expressed either in 26.6 */ + /* fractional pixels or font units. */ + /* */ + /* Note that even when the glyph image is */ + /* transformed, the metrics are not. */ + /* */ + /* linearHoriAdvance :: For scalable formats only, this field holds */ + /* the linearly scaled horizontal advance width */ + /* for the glyph (i.e. the scaled and unhinted */ + /* value of the hori advance). This can be */ + /* important to perform correct WYSIWYG layout. */ + /* */ + /* Note that this value is expressed by default */ + /* in 16.16 pixels. However, when the glyph is */ + /* loaded with the FT_LOAD_LINEAR_DESIGN flag, */ + /* this field contains simply the value of the */ + /* advance in original font units. */ + /* */ + /* linearVertAdvance :: For scalable formats only, this field holds */ + /* the linearly scaled vertical advance height */ + /* for the glyph. See linearHoriAdvance for */ + /* comments. */ + /* */ + /* advance :: This is the transformed advance width for the */ + /* glyph. */ + /* */ + /* format :: This field indicates the format of the image */ + /* contained in the glyph slot. Typically */ + /* FT_GLYPH_FORMAT_BITMAP, */ + /* FT_GLYPH_FORMAT_OUTLINE, and */ + /* FT_GLYPH_FORMAT_COMPOSITE, but others are */ + /* possible. */ + /* */ + /* bitmap :: This field is used as a bitmap descriptor */ + /* when the slot format is */ + /* FT_GLYPH_FORMAT_BITMAP. Note that the */ + /* address and content of the bitmap buffer can */ + /* change between calls of @FT_Load_Glyph and a */ + /* few other functions. */ + /* */ + /* bitmap_left :: This is the bitmap's left bearing expressed */ + /* in integer pixels. Of course, this is only */ + /* valid if the format is */ + /* FT_GLYPH_FORMAT_BITMAP. */ + /* */ + /* bitmap_top :: This is the bitmap's top bearing expressed in */ + /* integer pixels. Remember that this is the */ + /* distance from the baseline to the top-most */ + /* glyph scanline, upwards y-coordinates being */ + /* *positive*. */ + /* */ + /* outline :: The outline descriptor for the current glyph */ + /* image if its format is */ + /* FT_GLYPH_FORMAT_OUTLINE. */ + /* */ + /* num_subglyphs :: The number of subglyphs in a composite glyph. */ + /* This field is only valid for the composite */ + /* glyph format that should normally only be */ + /* loaded with the @FT_LOAD_NO_RECURSE flag. */ + /* For now this is internal to FreeType. */ + /* */ + /* subglyphs :: An array of subglyph descriptors for */ + /* composite glyphs. There are `num_subglyphs' */ + /* elements in there. Currently internal to */ + /* FreeType. */ + /* */ + /* control_data :: Certain font drivers can also return the */ + /* control data for a given glyph image (e.g. */ + /* TrueType bytecode, Type 1 charstrings, etc.). */ + /* This field is a pointer to such data. */ + /* */ + /* control_len :: This is the length in bytes of the control */ + /* data. */ + /* */ + /* other :: Really wicked formats can use this pointer to */ + /* present their own glyph image to client apps. */ + /* Note that the app will need to know about the */ + /* image format. */ + /* */ + /* lsb_delta :: The difference between hinted and unhinted */ + /* left side bearing while autohinting is */ + /* active. Zero otherwise. */ + /* */ + /* rsb_delta :: The difference between hinted and unhinted */ + /* right side bearing while autohinting is */ + /* active. Zero otherwise. */ + /* */ + /* <Note> */ + /* If @FT_Load_Glyph is called with default flags (see */ + /* @FT_LOAD_DEFAULT) the glyph image is loaded in the glyph slot in */ + /* its native format (e.g. a vectorial outline for TrueType and */ + /* Type 1 formats). */ + /* */ + /* This image can later be converted into a bitmap by calling */ + /* @FT_Render_Glyph. This function finds the current renderer for */ + /* the native image's format then invokes it. */ + /* */ + /* The renderer is in charge of transforming the native image through */ + /* the slot's face transformation fields, then convert it into a */ + /* bitmap that is returned in `slot->bitmap'. */ + /* */ + /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */ + /* to specify the position of the bitmap relative to the current pen */ + /* position (e.g. coordinates [0,0] on the baseline). Of course, */ + /* `slot->format' is also changed to `FT_GLYPH_FORMAT_BITMAP' . */ + /* */ + /* <Note> */ + /* Here a small pseudo code fragment which shows how to use */ + /* `lsb_delta' and `rsb_delta': */ + /* */ + /* { */ + /* FT_Pos origin_x = 0; */ + /* FT_Pos prev_rsb_delta = 0; */ + /* */ + /* */ + /* for all glyphs do */ + /* <compute kern between current and previous glyph and add it to */ + /* `origin_x'> */ + /* */ + /* <load glyph with `FT_Load_Glyph'> */ + /* */ + /* if ( prev_rsb_delta - face->glyph->lsb_delta >= 32 ) */ + /* origin_x -= 64; */ + /* else if ( prev_rsb_delta - face->glyph->lsb_delta < -32 ) */ + /* origin_x += 64; */ + /* */ + /* prev_rsb_delta = face->glyph->rsb_delta; */ + /* */ + /* <save glyph image, or render glyph, or ...> */ + /* */ + /* origin_x += face->glyph->advance.x; */ + /* endfor */ + /* } */ + /* */ + typedef struct FT_GlyphSlotRec_ + { + FT_Library library; + FT_Face face; + FT_GlyphSlot next; + FT_UInt reserved; /* retained for binary compatibility */ + FT_Generic generic; + + FT_Glyph_Metrics metrics; + FT_Fixed linearHoriAdvance; + FT_Fixed linearVertAdvance; + FT_Vector advance; + + FT_Glyph_Format format; + + FT_Bitmap bitmap; + FT_Int bitmap_left; + FT_Int bitmap_top; + + FT_Outline outline; + + FT_UInt num_subglyphs; + FT_SubGlyph subglyphs; + + void* control_data; + long control_len; + + FT_Pos lsb_delta; + FT_Pos rsb_delta; + + void* other; + + FT_Slot_Internal internal; + + } FT_GlyphSlotRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* F U N C T I O N S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Init_FreeType */ + /* */ + /* <Description> */ + /* Initializes a new FreeType library object. The set of modules */ + /* that are registered by this function is determined at build time. */ + /* */ + /* <Output> */ + /* alibrary :: A handle to a new library object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Init_FreeType( FT_Library *alibrary ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Library_Version */ + /* */ + /* <Description> */ + /* Return the version of the FreeType library being used. This is */ + /* useful when dynamically linking to the library, since one cannot */ + /* use the macros FT_FREETYPE_MAJOR, FT_FREETYPE_MINOR, and */ + /* FT_FREETYPE_PATCH. */ + /* */ + /* <Input> */ + /* library :: A source library handle. */ + /* */ + /* <Output> */ + /* amajor :: The major version number. */ + /* */ + /* aminor :: The minor version number. */ + /* */ + /* apatch :: The patch version number. */ + /* */ + /* <Note> */ + /* The reason why this function takes a 'library' argument is because */ + /* certain programs implement library initialization in a custom way */ + /* that doesn't use `FT_Init_FreeType'. */ + /* */ + /* In such cases, the library version might not be available before */ + /* the library object has been created. */ + /* */ + FT_EXPORT( void ) + FT_Library_Version( FT_Library library, + FT_Int *amajor, + FT_Int *aminor, + FT_Int *apatch ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_FreeType */ + /* */ + /* <Description> */ + /* Destroys a given FreeType library object and all of its childs, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* <Input> */ + /* library :: A handle to the target library object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_FreeType( FT_Library library ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_OPEN_XXX */ + /* */ + /* <Description> */ + /* A list of bit-field constants used within the `flags' field of the */ + /* @FT_Open_Args structure. */ + /* */ + /* <Values> */ + /* FT_OPEN_MEMORY :: This is a memory-based stream. */ + /* */ + /* FT_OPEN_STREAM :: Copy the stream from the `stream' field. */ + /* */ + /* FT_OPEN_PATHNAME :: Create a new input stream from a C */ + /* path name. */ + /* */ + /* FT_OPEN_DRIVER :: Use the `driver' field. */ + /* */ + /* FT_OPEN_PARAMS :: Use the `num_params' & `params' field. */ + /* */ + /* ft_open_memory :: Deprecated; use @FT_OPEN_MEMORY instead. */ + /* */ + /* ft_open_stream :: Deprecated; use @FT_OPEN_STREAM instead. */ + /* */ + /* ft_open_pathname :: Deprecated; use @FT_OPEN_PATHNAME instead. */ + /* */ + /* ft_open_driver :: Deprecated; use @FT_OPEN_DRIVER instead. */ + /* */ + /* ft_open_params :: Deprecated; use @FT_OPEN_PARAMS instead. */ + /* */ + /* <Note> */ + /* The `FT_OPEN_MEMORY', `FT_OPEN_STREAM', and `FT_OPEN_PATHNAME' */ + /* flags are mutually exclusive. */ + /* */ +#define FT_OPEN_MEMORY 0x1 +#define FT_OPEN_STREAM 0x2 +#define FT_OPEN_PATHNAME 0x4 +#define FT_OPEN_DRIVER 0x8 +#define FT_OPEN_PARAMS 0x10 + +#define ft_open_memory FT_OPEN_MEMORY /* deprecated */ +#define ft_open_stream FT_OPEN_STREAM /* deprecated */ +#define ft_open_pathname FT_OPEN_PATHNAME /* deprecated */ +#define ft_open_driver FT_OPEN_DRIVER /* deprecated */ +#define ft_open_params FT_OPEN_PARAMS /* deprecated */ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Parameter */ + /* */ + /* <Description> */ + /* A simple structure used to pass more or less generic parameters */ + /* to @FT_Open_Face. */ + /* */ + /* <Fields> */ + /* tag :: A 4-byte identification tag. */ + /* */ + /* data :: A pointer to the parameter data. */ + /* */ + /* <Note> */ + /* The id and function of parameters are driver-specific. */ + /* */ + typedef struct FT_Parameter_ + { + FT_ULong tag; + FT_Pointer data; + + } FT_Parameter; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Open_Args */ + /* */ + /* <Description> */ + /* A structure used to indicate how to open a new font file/stream. */ + /* A pointer to such a structure can be used as a parameter for the */ + /* functions @FT_Open_Face and @FT_Attach_Stream. */ + /* */ + /* <Fields> */ + /* flags :: A set of bit flags indicating how to use the */ + /* structure. */ + /* */ + /* memory_base :: The first byte of the file in memory. */ + /* */ + /* memory_size :: The size in bytes of the file in memory. */ + /* */ + /* pathname :: A pointer to an 8-bit file pathname. */ + /* */ + /* stream :: A handle to a source stream object. */ + /* */ + /* driver :: This field is exclusively used by @FT_Open_Face; */ + /* it simply specifies the font driver to use to open */ + /* the face. If set to 0, FreeType will try to load */ + /* the face with each one of the drivers in its list. */ + /* */ + /* num_params :: The number of extra parameters. */ + /* */ + /* params :: Extra parameters passed to the font driver when */ + /* opening a new face. */ + /* */ + /* <Note> */ + /* The stream type is determined by the contents of `flags' which */ + /* are tested in the following order by @FT_Open_Face: */ + /* */ + /* If the `FT_OPEN_MEMORY' bit is set, assume that this is a */ + /* memory file of `memory_size' bytes,located at `memory_address'. */ + /* */ + /* Otherwise, if the `FT_OPEN_STREAM' bit is set, assume that a */ + /* custom input stream `stream' is used. */ + /* */ + /* Otherwise, if the `FT_OPEN_PATHNAME' bit is set, assume that this */ + /* is a normal file and use `pathname' to open it. */ + /* */ + /* If the `FT_OPEN_DRIVER' bit is set, @FT_Open_Face will only try to */ + /* open the file with the driver whose handler is in `driver'. */ + /* */ + /* If the `FT_OPEN_PARAMS' bit is set, the parameters given by */ + /* `num_params' and `params' will be used. They are ignored */ + /* otherwise. */ + /* */ + typedef struct FT_Open_Args_ + { + FT_UInt flags; + const FT_Byte* memory_base; + FT_Long memory_size; + FT_String* pathname; + FT_Stream stream; + FT_Module driver; + FT_Int num_params; + FT_Parameter* params; + + } FT_Open_Args; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face */ + /* */ + /* <Description> */ + /* Creates a new face object from a given resource and typeface index */ + /* using a pathname to the font file. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* @FT_New_Face can be used to determine and/or check the font format */ + /* of a given font resource. If the `face_index' field is negative, */ + /* the function will _not_ return any face handle in `aface'; the */ + /* return value is 0 if the font format is recognized, or non-zero */ + /* otherwise. */ + /* */ + /* Each new face object created with this function also owns a */ + /* default @FT_Size object, accessible as `face->size'. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Face( FT_Library library, + const char* filepathname, + FT_Long face_index, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Memory_Face */ + /* */ + /* <Description> */ + /* Creates a new face object from a given resource and typeface index */ + /* using a font file already loaded into memory. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* file_base :: A pointer to the beginning of the font data. */ + /* */ + /* file_size :: The size of the memory chunk used by the font data. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The font data bytes are used _directly_ by the @FT_Face object. */ + /* This means that they are not copied, and that the client is */ + /* responsible for releasing/destroying them _after_ the */ + /* corresponding call to @FT_Done_Face . */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* @FT_New_Memory_Face can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `aface'; the return value is 0 if the font format is recognized, */ + /* or non-zero otherwise. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Memory_Face( FT_Library library, + const FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Open_Face */ + /* */ + /* <Description> */ + /* Opens a face object from a given resource and typeface index using */ + /* an `FT_Open_Args' structure. If the face object doesn't exist, it */ + /* will be created. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* args :: A pointer to an `FT_Open_Args' structure which must */ + /* be filled by the caller. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* @FT_Open_Face can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `*face'; the return value is 0 if the font format is recognized, */ + /* or non-zero otherwise. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Open_Face( FT_Library library, + const FT_Open_Args* args, + FT_Long face_index, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Attach_File */ + /* */ + /* <Description> */ + /* `Attaches' a given font file to an existing face. This is usually */ + /* to read additional information for a single face object. For */ + /* example, it is used to read the AFM files that come with Type 1 */ + /* fonts in order to add kerning data and other metrics. */ + /* */ + /* <InOut> */ + /* face :: The target face object. */ + /* */ + /* <Input> */ + /* filepathname :: An 8-bit pathname naming the `metrics' file. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* If your font file is in memory, or if you want to provide your */ + /* own input stream object, use @FT_Attach_Stream. */ + /* */ + /* The meaning of the `attach' action (i.e., what really happens when */ + /* the new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Attach_File( FT_Face face, + const char* filepathname ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Attach_Stream */ + /* */ + /* <Description> */ + /* This function is similar to @FT_Attach_File with the exception */ + /* that it reads the attachment from an arbitrary stream. */ + /* */ + /* <InOut> */ + /* face :: The target face object. */ + /* */ + /* <Input> */ + /* parameters :: A pointer to an FT_Open_Args structure used to */ + /* describe the input stream to FreeType. */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The meaning of the `attach' (i.e. what really happens when the */ + /* new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Attach_Stream( FT_Face face, + FT_Open_Args* parameters ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Face */ + /* */ + /* <Description> */ + /* Discards a given face object, as well as all of its child slots */ + /* and sizes. */ + /* */ + /* <Input> */ + /* face :: A handle to a target face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_Face( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Char_Size */ + /* */ + /* <Description> */ + /* Sets the character dimensions of a given face object. The */ + /* `char_width' and `char_height' values are used for the width and */ + /* height, respectively, expressed in 26.6 fractional points. */ + /* */ + /* If the horizontal or vertical resolution values are zero, a */ + /* default value of 72dpi is used. Similarly, if one of the */ + /* character dimensions is zero, its value is set equal to the other. */ + /* */ + /* <InOut> */ + /* face :: A handle to a target face object. */ + /* */ + /* <Input> */ + /* char_width :: The character width, in 26.6 fractional points. */ + /* */ + /* char_height :: The character height, in 26.6 fractional */ + /* points. */ + /* */ + /* horz_resolution :: The horizontal resolution. */ + /* */ + /* vert_resolution :: The vertical resolution. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* @FT_Set_Pixel_Sizes provides a more convenient interface. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Char_Size( FT_Face face, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Pixel_Sizes */ + /* */ + /* <Description> */ + /* Sets the character dimensions of a given face object. The width */ + /* and height are expressed in integer pixels. */ + /* */ + /* If one of the character dimensions is zero, its value is set equal */ + /* to the other. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Input> */ + /* pixel_width :: The character width, in integer pixels. */ + /* */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The values of `pixel_width' and `pixel_height' correspond to the */ + /* pixel values of the _typographic_ character size, which are NOT */ + /* necessarily the same as the dimensions of the glyph `bitmap */ + /* cells'. */ + /* */ + /* The `character size' is really the size of an abstract square */ + /* called the `EM', used to design the font. However, depending */ + /* on the font design, glyphs will be smaller or greater than the */ + /* EM. */ + /* */ + /* This means that setting the pixel size to, say, 8x8 doesn't */ + /* guarantee in any way that you will get glyph bitmaps that all fit */ + /* within an 8x8 cell (sometimes even far from it). */ + /* */ + /* For bitmap fonts, `pixel_height' usually is a reliable value for */ + /* the height of the bitmap cell. Drivers for bitmap font formats */ + /* which contain a single bitmap strike only (BDF, PCF, FNT) ignore */ + /* `pixel_width'. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Load_Glyph */ + /* */ + /* <Description> */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object where the glyph */ + /* will be loaded. */ + /* */ + /* <Input> */ + /* glyph_index :: The index of the glyph in the font file. For */ + /* CID-keyed fonts (either in PS or in CFF format) */ + /* this argument specifies the CID value. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* @FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* @FT_Set_Transform. */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Load_Char */ + /* */ + /* <Description> */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size, according to its character code. */ + /* */ + /* <InOut> */ + /* face :: A handle to a target face object where the glyph */ + /* will be loaded. */ + /* */ + /* <Input> */ + /* char_code :: The glyph's character code, according to the */ + /* current charmap used in the face. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* @FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* If the face has no current charmap, or if the character code */ + /* is not defined in the charmap, this function will return an */ + /* error. */ + /* */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* @FT_Set_Transform. */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int32 load_flags ); + + + /*************************************************************************** + * + * @enum: + * FT_LOAD_XXX + * + * @description: + * A list of bit-field constants, used with @FT_Load_Glyph to indicate + * what kind of operations to perform during glyph loading. + * + * @values: + * FT_LOAD_DEFAULT :: + * Corresponding to 0, this value is used a default glyph load. In this + * case, the following will happen: + * + * 1. FreeType looks for a bitmap for the glyph corresponding to the + * face's current size. If one is found, the function returns. The + * bitmap data can be accessed from the glyph slot (see note below). + * + * 2. If no embedded bitmap is searched or found, FreeType looks for a + * scalable outline. If one is found, it is loaded from the font + * file, scaled to device pixels, then "hinted" to the pixel grid in + * order to optimize it. The outline data can be accessed from the + * glyph slot (see note below). + * + * Note that by default, the glyph loader doesn't render outlines into + * bitmaps. The following flags are used to modify this default + * behaviour to more specific and useful cases. + * + * FT_LOAD_NO_SCALE :: + * Don't scale the vector outline being loaded to 26.6 fractional + * pixels, but kept in font units. Note that this also disables + * hinting and the loading of embedded bitmaps. You should only use it + * when you want to retrieve the original glyph outlines in font units. + * + * FT_LOAD_NO_HINTING :: + * Don't hint glyph outlines after their scaling to device pixels. + * This generally generates "blurrier" glyphs in anti-aliased modes. + * + * This flag is ignored if @FT_LOAD_NO_SCALE is set. + * + * FT_LOAD_RENDER :: + * Render the glyph outline immediately into a bitmap before the glyph + * loader returns. By default, the glyph is rendered for the + * @FT_RENDER_MODE_NORMAL mode, which corresponds to 8-bit anti-aliased + * bitmaps using 256 opacity levels. You can use either + * @FT_LOAD_TARGET_MONO or @FT_LOAD_MONOCHROME to render 1-bit + * monochrome bitmaps. + * + * This flag is ignored if @FT_LOAD_NO_SCALE is set. + * + * FT_LOAD_NO_BITMAP :: + * Don't look for bitmaps when loading the glyph. Only scalable + * outlines will be loaded when available, and scaled, hinted, or + * rendered depending on other bit flags. + * + * This does not prevent you from rendering outlines to bitmaps + * with @FT_LOAD_RENDER, however. + * + * FT_LOAD_VERTICAL_LAYOUT :: + * Prepare the glyph image for vertical text layout. This basically + * means that `face.glyph.advance' will correspond to the vertical + * advance height (instead of the default horizontal advance width), + * and that the glyph image will be translated to match the vertical + * bearings positions. + * + * FT_LOAD_FORCE_AUTOHINT :: + * Force the use of the FreeType auto-hinter when a glyph outline is + * loaded. You shouldn't need this in a typical application, since it + * is mostly used to experiment with its algorithm. + * + * FT_LOAD_CROP_BITMAP :: + * Indicates that the glyph loader should try to crop the bitmap (i.e., + * remove all space around its black bits) when loading it. This is + * only useful when loading embedded bitmaps in certain fonts, since + * bitmaps rendered with @FT_LOAD_RENDER are always cropped by default. + * + * FT_LOAD_PEDANTIC :: + * Indicates that the glyph loader should perform pedantic + * verifications during glyph loading, rejecting invalid fonts. This + * is mostly used to detect broken glyphs in fonts. By default, + * FreeType tries to handle broken fonts also. + * + * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH :: + * Indicates that the glyph loader should ignore the global advance + * width defined in the font. As far as we know, this is only used by + * the X-TrueType font server, in order to deal correctly with the + * incorrect metrics contained in DynaLab's TrueType CJK fonts. + * + * FT_LOAD_NO_RECURSE :: + * This flag is only used internally. It merely indicates that the + * glyph loader should not load composite glyphs recursively. Instead, + * it should set the `num_subglyph' and `subglyphs' values of the glyph + * slot accordingly, and set "glyph->format" to + * @FT_GLYPH_FORMAT_COMPOSITE. + * + * The description of sub-glyphs is not available to client + * applications for now. + * + * FT_LOAD_IGNORE_TRANSFORM :: + * Indicates that the glyph loader should not try to transform the + * loaded glyph image. This doesn't prevent scaling, hinting, or + * rendering. + * + * FT_LOAD_MONOCHROME :: + * This flag is used with @FT_LOAD_RENDER to indicate that you want + * to render a 1-bit monochrome glyph bitmap from a vectorial outline. + * + * Note that this has no effect on the hinting algorithm used by the + * glyph loader. You should better use @FT_LOAD_TARGET_MONO if you + * want to render monochrome-optimized glyph images instead. + * + * FT_LOAD_LINEAR_DESIGN :: + * Return the linearly scaled metrics expressed in original font units + * instead of the default 16.16 pixel values. + * + * FT_LOAD_NO_AUTOHINT :: + * Indicates that the auto-hinter should never be used to hint glyph + * outlines. This doesn't prevent native format-specific hinters from + * being used. This can be important for certain fonts where unhinted + * output is better than auto-hinted one. + * + * FT_LOAD_TARGET_NORMAL :: + * Use hinting for @FT_RENDER_MODE_NORMAL. + * + * FT_LOAD_TARGET_LIGHT :: + * Use hinting for @FT_RENDER_MODE_LIGHT. + * + * FT_LOAD_TARGET_MONO :: + * Use hinting for @FT_RENDER_MODE_MONO. + * + * FT_LOAD_TARGET_LCD :: + * Use hinting for @FT_RENDER_MODE_LCD. + * + * FT_LOAD_TARGET_LCD_V :: + * Use hinting for @FT_RENDER_MODE_LCD_V. + */ +#define FT_LOAD_DEFAULT 0x0 +#define FT_LOAD_NO_SCALE 0x1 +#define FT_LOAD_NO_HINTING 0x2 +#define FT_LOAD_RENDER 0x4 +#define FT_LOAD_NO_BITMAP 0x8 +#define FT_LOAD_VERTICAL_LAYOUT 0x10 +#define FT_LOAD_FORCE_AUTOHINT 0x20 +#define FT_LOAD_CROP_BITMAP 0x40 +#define FT_LOAD_PEDANTIC 0x80 +#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200 +#define FT_LOAD_NO_RECURSE 0x400 +#define FT_LOAD_IGNORE_TRANSFORM 0x800 +#define FT_LOAD_MONOCHROME 0x1000 +#define FT_LOAD_LINEAR_DESIGN 0x2000 + + /* temporary hack! */ +#define FT_LOAD_SBITS_ONLY 0x4000 +#define FT_LOAD_NO_AUTOHINT 0x8000U + + /* */ + +#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 ) +#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) ) + +#define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL ) +#define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT ) +#define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO ) +#define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD ) +#define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V ) + + /* */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Transform */ + /* */ + /* <Description> */ + /* A function used to set the transformation that is applied to glyph */ + /* images just before they are converted to bitmaps in a glyph slot */ + /* when @FT_Render_Glyph is called. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */ + /* the identity matrix. */ + /* delta :: A pointer to the translation vector. Use 0 for the null */ + /* vector. */ + /* */ + /* <Note> */ + /* The transformation is only applied to scalable image formats after */ + /* the glyph has been loaded. It means that hinting is unaltered by */ + /* the transformation and is performed on the character size given in */ + /* the last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes. */ + /* */ + FT_EXPORT( void ) + FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Render_Mode */ + /* */ + /* <Description> */ + /* An enumeration type that lists the render modes supported by */ + /* FreeType 2. Each mode corresponds to a specific type of scanline */ + /* conversion performed on the outline, as well as specific */ + /* hinting optimizations. */ + /* */ + /* For bitmap fonts the `bitmap->pixel_mode' field in the */ + /* @FT_GlyphSlotRec structure gives the format of the returned */ + /* bitmap. */ + /* */ + /* <Values> */ + /* FT_RENDER_MODE_NORMAL :: */ + /* This is the default render mode; it corresponds to 8-bit */ + /* anti-aliased bitmaps, using 256 levels of opacity. */ + /* */ + /* FT_RENDER_MODE_LIGHT :: */ + /* This is similar to @FT_RENDER_MODE_NORMAL -- you have to use */ + /* @FT_LOAD_TARGET_LIGHT in calls to @FT_Load_Glyph to get any */ + /* effect since the rendering process no longer influences the */ + /* positioning of glyph outlines. */ + /* */ + /* The resulting glyph shapes are more similar to the original, */ + /* while being a bit more fuzzy (`better shapes' instead of `better */ + /* contrast', so to say. */ + /* */ + /* FT_RENDER_MODE_MONO :: */ + /* This mode corresponds to 1-bit bitmaps. */ + /* */ + /* FT_RENDER_MODE_LCD :: */ + /* This mode corresponds to horizontal RGB/BGR sub-pixel displays, */ + /* like LCD-screens. It produces 8-bit bitmaps that are 3 times */ + /* the width of the original glyph outline in pixels, and which use */ + /* the @FT_PIXEL_MODE_LCD mode. */ + /* */ + /* FT_RENDER_MODE_LCD_V :: */ + /* This mode corresponds to vertical RGB/BGR sub-pixel displays */ + /* (like PDA screens, rotated LCD displays, etc.). It produces */ + /* 8-bit bitmaps that are 3 times the height of the original */ + /* glyph outline in pixels and use the @FT_PIXEL_MODE_LCD_V mode. */ + /* */ + /* <Note> */ + /* The LCD-optimized glyph bitmaps produced by FT_Render_Glyph are */ + /* _not filtered_ to reduce color-fringes. It is up to the caller to */ + /* perform this pass. */ + /* */ + typedef enum FT_Render_Mode_ + { + FT_RENDER_MODE_NORMAL = 0, + FT_RENDER_MODE_LIGHT, + FT_RENDER_MODE_MONO, + FT_RENDER_MODE_LCD, + FT_RENDER_MODE_LCD_V, + + FT_RENDER_MODE_MAX + + } FT_Render_Mode; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_render_mode_xxx */ + /* */ + /* <Description> */ + /* These constats are deprecated. Use the corresponding */ + /* @FT_Render_Mode values instead. */ + /* */ + /* <Values> */ + /* ft_render_mode_normal :: see @FT_RENDER_MODE_NORMAL */ + /* ft_render_mode_mono :: see @FT_RENDER_MODE_MONO */ + /* */ +#define ft_render_mode_normal FT_RENDER_MODE_NORMAL +#define ft_render_mode_mono FT_RENDER_MODE_MONO + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Render_Glyph */ + /* */ + /* <Description> */ + /* Converts a given glyph image to a bitmap. It does so by */ + /* inspecting the glyph image format, find the relevant renderer, and */ + /* invoke it. */ + /* */ + /* <InOut> */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* <Input> */ + /* render_mode :: This is the render mode used to render the glyph */ + /* image into a bitmap. See FT_Render_Mode for a list */ + /* of possible values. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Render_Glyph( FT_GlyphSlot slot, + FT_Render_Mode render_mode ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Kerning_Mode */ + /* */ + /* <Description> */ + /* An enumeration used to specify which kerning values to return in */ + /* @FT_Get_Kerning. */ + /* */ + /* <Values> */ + /* FT_KERNING_DEFAULT :: Return scaled and grid-fitted kerning */ + /* distances (value is 0). */ + /* */ + /* FT_KERNING_UNFITTED :: Return scaled but un-grid-fitted kerning */ + /* distances. */ + /* */ + /* FT_KERNING_UNSCALED :: Return the kerning vector in original font */ + /* units. */ + /* */ + typedef enum FT_Kerning_Mode_ + { + FT_KERNING_DEFAULT = 0, + FT_KERNING_UNFITTED, + FT_KERNING_UNSCALED + + } FT_Kerning_Mode; + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* ft_kerning_default */ + /* */ + /* <Description> */ + /* This constant is deprecated. Please use @FT_KERNING_DEFAULT */ + /* instead. */ + /* */ +#define ft_kerning_default FT_KERNING_DEFAULT + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* ft_kerning_unfitted */ + /* */ + /* <Description> */ + /* This constant is deprecated. Please use @FT_KERNING_UNFITTED */ + /* instead. */ + /* */ +#define ft_kerning_unfitted FT_KERNING_UNFITTED + + + /*************************************************************************/ + /* */ + /* <Const> */ + /* ft_kerning_unscaled */ + /* */ + /* <Description> */ + /* This constant is deprecated. Please use @FT_KERNING_UNSCALED */ + /* instead. */ + /* */ +#define ft_kerning_unscaled FT_KERNING_UNSCALED + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Kerning */ + /* */ + /* <Description> */ + /* Returns the kerning vector between two glyphs of a same face. */ + /* */ + /* <Input> */ + /* face :: A handle to a source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* kern_mode :: See @FT_Kerning_Mode for more information. */ + /* Determines the scale/dimension of the returned */ + /* kerning vector. */ + /* */ + /* <Output> */ + /* akerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this method. Other layouts, or more sophisticated */ + /* kernings, are out of the scope of this API function -- they can be */ + /* implemented through format-specific interfaces. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector *akerning ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Glyph_Name */ + /* */ + /* <Description> */ + /* Retrieves the ASCII name of a given glyph in a face. This only */ + /* works for those faces where FT_HAS_GLYPH_NAME(face) returns true. */ + /* */ + /* <Input> */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* <Output> */ + /* buffer :: A pointer to a target buffer where the name will be */ + /* copied to. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* An error is returned if the face doesn't provide glyph names or if */ + /* the glyph index is invalid. In all cases of failure, the first */ + /* byte of `buffer' will be set to 0 to indicate an empty name. */ + /* */ + /* The glyph name is truncated to fit within the buffer if it is too */ + /* long. The returned string is always zero-terminated. */ + /* */ + /* This function is not compiled within the library if the config */ + /* macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in */ + /* `include/freetype/config/ftoptions.h' */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Postscript_Name */ + /* */ + /* <Description> */ + /* Retrieves the ASCII Postscript name of a given face, if available. */ + /* This should only work with Postscript and TrueType fonts. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Return> */ + /* A pointer to the face's Postscript name. NULL if un-available. */ + /* */ + /* <Note> */ + /* The returned pointer is owned by the face and will be destroyed */ + /* with it. */ + /* */ + FT_EXPORT( const char* ) + FT_Get_Postscript_Name( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Select_Charmap */ + /* */ + /* <Description> */ + /* Selects a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Input> */ + /* encoding :: A handle to the selected charmap. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function will return an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Charmap */ + /* */ + /* <Description> */ + /* Selects a given charmap for character code to glyph index */ + /* decoding. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Input> */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function will return an error if the charmap is not part of */ + /* the face (i.e., if it is not listed in the face->charmaps[] */ + /* table). */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Get_Charmap_Index */ + /* */ + /* @description: */ + /* Retrieve index of a given charmap. */ + /* */ + /* @input: */ + /* charmap :: A handle to a charmap. */ + /* */ + /* @return: */ + /* The index into the array of character maps within the face to */ + /* which `charmap' belongs. */ + /* */ + FT_EXPORT( FT_Int ) + FT_Get_Charmap_Index( FT_CharMap charmap ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Char_Index */ + /* */ + /* <Description> */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* <Return> */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + /* <Note> */ + /* FreeType computes its own glyph indices which are not necessarily */ + /* the same as used in the font in case the font is based on glyph */ + /* indices. Reason for this behaviour is to assure that index 0 is */ + /* never used, representing the missing glyph. */ + /* */ + FT_EXPORT( FT_UInt ) + FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_First_Char */ + /* */ + /* <Description> */ + /* This function is used to return the first character code in the */ + /* current charmap of a given face. It will also return the */ + /* corresponding glyph index. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Output> */ + /* agindex :: Glyph index of first character code. 0 if charmap is */ + /* empty. */ + /* */ + /* <Return> */ + /* The charmap's first character code. */ + /* */ + /* <Note> */ + /* You should use this function with @FT_Get_Next_Char to be able to */ + /* parse all character codes available in a given charmap. The code */ + /* should look like this: */ + /* */ + /* { */ + /* FT_ULong charcode; */ + /* FT_UInt gindex; */ + /* */ + /* */ + /* charcode = FT_Get_First_Char( face, &gindex ); */ + /* while ( gindex != 0 ) */ + /* { */ + /* ... do something with (charcode,gindex) pair ... */ + /* */ + /* charcode = FT_Get_Next_Char( face, charcode, &gindex ); */ + /* } */ + /* } */ + /* */ + /* Note that `*agindex' will be set to 0 if the charmap is empty. */ + /* The result itself can be 0 in two cases: if the charmap is empty */ + /* or when the value 0 is the first valid character code. */ + /* */ + FT_EXPORT( FT_ULong ) + FT_Get_First_Char( FT_Face face, + FT_UInt *agindex ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Next_Char */ + /* */ + /* <Description> */ + /* This function is used to return the next character code in the */ + /* current charmap of a given face following the value 'char_code', */ + /* as well as the corresponding glyph index. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* char_code :: The starting character code. */ + /* */ + /* <Output> */ + /* agindex :: Glyph index of first character code. 0 if charmap */ + /* is empty. */ + /* */ + /* <Return> */ + /* The charmap's next character code. */ + /* */ + /* <Note> */ + /* You should use this function with @FT_Get_First_Char to walk */ + /* through all character codes available in a given charmap. See */ + /* the note for this function for a simple code example. */ + /* */ + /* Note that `*agindex' will be set to 0 when there are no more codes */ + /* in the charmap. */ + /* */ + FT_EXPORT( FT_ULong ) + FT_Get_Next_Char( FT_Face face, + FT_ULong char_code, + FT_UInt *agindex ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Name_Index */ + /* */ + /* <Description> */ + /* Returns the glyph index of a given glyph name. This function uses */ + /* driver specific objects to do the translation. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* glyph_name :: The glyph name. */ + /* */ + /* <Return> */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + FT_EXPORT( FT_UInt ) + FT_Get_Name_Index( FT_Face face, + FT_String* glyph_name ); + + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* computations */ + /* */ + /* <Title> */ + /* Computations */ + /* */ + /* <Abstract> */ + /* Crunching fixed numbers and vectors */ + /* */ + /* <Description> */ + /* This section contains various functions used to perform */ + /* computations on 16.16 fixed-float numbers or 2d vectors. */ + /* */ + /* <Order> */ + /* FT_MulDiv */ + /* FT_MulFix */ + /* FT_DivFix */ + /* FT_RoundFix */ + /* FT_CeilFix */ + /* FT_FloorFix */ + /* FT_Vector_Transform */ + /* FT_Matrix_Multiply */ + /* FT_Matrix_Invert */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_MulDiv */ + /* */ + /* <Description> */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* with maximal accuracy (it uses a 64-bit intermediate integer */ + /* whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* <Input> */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* <Return> */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + FT_EXPORT( FT_Long ) + FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_MulFix */ + /* */ + /* <Description> */ + /* A very simple function used to perform the computation */ + /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */ + /* used to multiply a given value by a 16.16 fixed float factor. */ + /* */ + /* <Input> */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* <Return> */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* <Note> */ + /* This function has been optimized for the case where the absolute */ + /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */ + /* As this happens mainly when scaling from notional units to */ + /* fractional pixels in FreeType, it resulted in noticeable speed */ + /* improvements between versions 2.x and 1.x. */ + /* */ + /* As a conclusion, always try to place a 16.16 factor as the */ + /* _second_ argument of this function; this can make a great */ + /* difference. */ + /* */ + FT_EXPORT( FT_Long ) + FT_MulFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_DivFix */ + /* */ + /* <Description> */ + /* A very simple function used to perform the computation */ + /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */ + /* used to divide a given value by a 16.16 fixed float factor. */ + /* */ + /* <Input> */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* <Return> */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* <Note> */ + /* The optimization for FT_DivFix() is simple: If (a << 16) fits in */ + /* 32 bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of @FT_MulDiv. */ + /* */ + FT_EXPORT( FT_Long ) + FT_DivFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_RoundFix */ + /* */ + /* <Description> */ + /* A very simple function used to round a 16.16 fixed number. */ + /* */ + /* <Input> */ + /* a :: The number to be rounded. */ + /* */ + /* <Return> */ + /* The result of `(a + 0x8000) & -0x10000'. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_RoundFix( FT_Fixed a ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_CeilFix */ + /* */ + /* <Description> */ + /* A very simple function used to compute the ceiling function of a */ + /* 16.16 fixed number. */ + /* */ + /* <Input> */ + /* a :: The number for which the ceiling function is to be computed. */ + /* */ + /* <Return> */ + /* The result of `(a + 0x10000 - 1) & -0x10000'. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_CeilFix( FT_Fixed a ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_FloorFix */ + /* */ + /* <Description> */ + /* A very simple function used to compute the floor function of a */ + /* 16.16 fixed number. */ + /* */ + /* <Input> */ + /* a :: The number for which the floor function is to be computed. */ + /* */ + /* <Return> */ + /* The result of `a & -0x10000'. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_FloorFix( FT_Fixed a ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Vector_Transform */ + /* */ + /* <Description> */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* <InOut> */ + /* vector :: The target vector to transform. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* <Note> */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT( void ) + FT_Vector_Transform( FT_Vector* vec, + FT_Matrix* matrix ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FREETYPE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftbbox.h b/Utilities/vtkfreetype/include/freetype/ftbbox.h new file mode 100644 index 0000000..f98c89e --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftbbox.h @@ -0,0 +1,89 @@ +/***************************************************************************/ +/* */ +/* ftbbox.h */ +/* */ +/* FreeType exact bbox computation (specification). */ +/* */ +/* Copyright 1996-2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component has a _single_ role: to compute exact outline bounding */ + /* boxes. */ + /* */ + /* It is separated from the rest of the engine for various technical */ + /* reasons. It may well be integrated in `ftoutln' later. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTBBOX_H__ +#define __FTBBOX_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* outline_processing */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Get_BBox */ + /* */ + /* <Description> */ + /* Computes the exact bounding box of an outline. This is slower */ + /* than computing the control box. However, it uses an advanced */ + /* algorithm which returns _very_ quickly when the two boxes */ + /* coincide. Otherwise, the outline Bezier arcs are walked over to */ + /* extract their extrema. */ + /* */ + /* <Input> */ + /* outline :: A pointer to the source outline. */ + /* */ + /* <Output> */ + /* abbox :: The outline's exact bounding box. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Get_BBox( FT_Outline* outline, + FT_BBox *abbox ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTBBOX_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftbdf.h b/Utilities/vtkfreetype/include/freetype/ftbdf.h new file mode 100644 index 0000000..aa41144 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftbdf.h @@ -0,0 +1,200 @@ +/***************************************************************************/ +/* */ +/* ftbdf.h */ +/* */ +/* FreeType API for accessing BDF-specific strings (specification). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTBDF_H__ +#define __FTBDF_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* bdf_fonts */ + /* */ + /* <Title> */ + /* BDF Fonts */ + /* */ + /* <Abstract> */ + /* BDF-specific APIs */ + /* */ + /* <Description> */ + /* This section contains the declaration of BDF-specific functions. */ + /* */ + /*************************************************************************/ + + + /********************************************************************** + * + * @enum: + * FT_PropertyType + * + * @description: + * A list of BDF property types. + * + * @values: + * BDF_PROPERTY_TYPE_NONE :: + * Value 0 is used to indicate a missing property. + * + * BDF_PROPERTY_TYPE_ATOM :: + * Property is a string atom. + * + * BDF_PROPERTY_TYPE_INTEGER :: + * Property is a 32-bit signed integer. + * + * BDF_PROPERTY_TYPE_CARDINAL :: + * Property is a 32-bit unsigned integer. + */ + typedef enum BDF_PropertyType_ + { + BDF_PROPERTY_TYPE_NONE = 0, + BDF_PROPERTY_TYPE_ATOM = 1, + BDF_PROPERTY_TYPE_INTEGER = 2, + BDF_PROPERTY_TYPE_CARDINAL = 3 + + } BDF_PropertyType; + + + /********************************************************************** + * + * @type: + * BDF_Property + * + * @description: + * A handle to a @BDF_PropertyRec structure to model a given + * BDF/PCF property. + */ + typedef struct BDF_PropertyRec_* BDF_Property; + + + /********************************************************************** + * + * @struct: + * BDF_PropertyRec + * + * @description: + * This structure models a given BDF/PCF property. + * + * @fields: + * type :: + * The property type. + * + * u.atom :: + * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. + * + * u.integer :: + * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER. + * + * u.cardinal :: + * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL. + */ + typedef struct BDF_PropertyRec_ + { + BDF_PropertyType type; + union { + const char* atom; + FT_Int32 integer; + FT_UInt32 cardinal; + + } u; + + } BDF_PropertyRec; + + + /********************************************************************** + * + * @function: + * FT_Get_BDF_Charset_ID + * + * @description: + * Retrieves a BDF font character set identity, according to + * the BDF specification. + * + * @input: + * face :: + * A handle to the input face. + * + * @output: + * acharset_encoding :: + * Charset encoding, as a C string, owned by the face. + * + * acharset_registry :: + * Charset registry, as a C string, owned by the face. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * This function only works with BDF faces, returning an error otherwise. + */ + FT_EXPORT( FT_Error ) + FT_Get_BDF_Charset_ID( FT_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ); + + + /********************************************************************** + * + * @function: + * FT_Get_BDF_Property + * + * @description: + * Retrieves a BDF property from a BDF or PCF font file. + * + * @input: + * face :: A handle to the input face. + * + * name :: The property name. + * + * @output: + * aproperty :: The property. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * This function works with BDF _and_ PCF fonts. It returns an error + * otherwise. It also returns an error if the property is not in the + * font. + * + * In case of error, "aproperty->type" is always set to + * @BDF_PROPERTY_TYPE_NONE. + */ + FT_EXPORT( FT_Error ) + FT_Get_BDF_Property( FT_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ); + + /* */ + +FT_END_HEADER + +#endif /* __FTBDF_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftcache.h b/Utilities/vtkfreetype/include/freetype/ftcache.h new file mode 100644 index 0000000..c26ce6b --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftcache.h @@ -0,0 +1,825 @@ +/***************************************************************************/ +/* */ +/* ftcache.h */ +/* */ +/* FreeType Cache subsystem (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********* *********/ + /********* WARNING, THIS IS BETA CODE. *********/ + /********* *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#ifndef __FTCACHE_H__ +#define __FTCACHE_H__ + + +#include <ft2build.h> +#include FT_GLYPH_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* cache_subsystem */ + /* */ + /* <Title> */ + /* Cache Sub-System */ + /* */ + /* <Abstract> */ + /* How to cache face, size, and glyph data with FreeType 2. */ + /* */ + /* <Description> */ + /* This section describes the FreeType 2 cache sub-system which is */ + /* still in beta. */ + /* */ + /* <Order> */ + /* FTC_Manager */ + /* FTC_FaceID */ + /* FTC_Face_Requester */ + /* */ + /* FTC_Manager_New */ + /* FTC_Manager_Reset */ + /* FTC_Manager_Done */ + /* FTC_Manager_LookupFace */ + /* FTC_Manager_LookupSize */ + /* FTC_Manager_RemoveFaceID */ + /* */ + /* FTC_Node */ + /* FTC_Node_Unref */ + /* */ + /* FTC_Font */ + /* FTC_ImageCache */ + /* FTC_ImageCache_New */ + /* FTC_ImageCache_Lookup */ + /* */ + /* FTC_SBit */ + /* FTC_SBitCache */ + /* FTC_SBitCache_New */ + /* FTC_SBitCache_Lookup */ + /* */ + /* FTC_CMapCache */ + /* FTC_CMapCache_New */ + /* FTC_CMapCache_Lookup */ + /* */ + /* */ + /* FTC_Image_Desc */ + /* FTC_Image_Cache */ + /* FTC_Image_Cache_Lookup */ + /* */ + /* FTC_SBit_Cache */ + /* FTC_SBit_Cache_Lookup */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BASIC TYPE DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_FaceID */ + /* */ + /* <Description> */ + /* An opaque pointer type that is used to identity face objects. The */ + /* contents of such objects is application-dependent. */ + /* */ + typedef struct FTC_FaceIDRec_* FTC_FaceID; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FTC_Face_Requester */ + /* */ + /* <Description> */ + /* A callback function provided by client applications. It is used */ + /* to translate a given @FTC_FaceID into a new valid @FT_Face object. */ + /* */ + /* <Input> */ + /* face_id :: The face ID to resolve. */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* data :: Application-provided request data. */ + /* */ + /* <Output> */ + /* aface :: A new @FT_Face handle. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The face requester should not perform funny things on the returned */ + /* face object, like creating a new @FT_Size for it, or setting a */ + /* transformation through @FT_Set_Transform! */ + /* */ + typedef FT_Error + (*FTC_Face_Requester)( FTC_FaceID face_id, + FT_Library library, + FT_Pointer request_data, + FT_Face* aface ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FTC_FontRec */ + /* */ + /* <Description> */ + /* A simple structure used to describe a given `font' to the cache */ + /* manager. Note that a `font' is the combination of a given face */ + /* with a given character size. */ + /* */ + /* <Fields> */ + /* face_id :: The ID of the face to use. */ + /* */ + /* pix_width :: The character width in integer pixels. */ + /* */ + /* pix_height :: The character height in integer pixels. */ + /* */ + typedef struct FTC_FontRec_ + { + FTC_FaceID face_id; + FT_UShort pix_width; + FT_UShort pix_height; + + } FTC_FontRec; + + + /* */ + + +#define FTC_FONT_COMPARE( f1, f2 ) \ + ( (f1)->face_id == (f2)->face_id && \ + (f1)->pix_width == (f2)->pix_width && \ + (f1)->pix_height == (f2)->pix_height ) + +#define FT_POINTER_TO_ULONG( p ) ((FT_ULong)(FT_Pointer)(p)) + +#define FTC_FACE_ID_HASH( i ) \ + ((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^ \ + ( FT_POINTER_TO_ULONG( i ) << 7 ) ) ) + +#define FTC_FONT_HASH( f ) \ + (FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \ + ((f)->pix_width << 8) ^ \ + ((f)->pix_height) ) + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_Font */ + /* */ + /* <Description> */ + /* A simple handle to an @FTC_FontRec structure. */ + /* */ + typedef FTC_FontRec* FTC_Font; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CACHE MANAGER OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_Manager */ + /* */ + /* <Description> */ + /* This object is used to cache one or more @FT_Face objects, along */ + /* with corresponding @FT_Size objects. */ + /* */ + typedef struct FTC_ManagerRec_* FTC_Manager; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_Node */ + /* */ + /* <Description> */ + /* An opaque handle to a cache node object. Each cache node is */ + /* reference-counted. A node with a count of 0 might be flushed */ + /* out of a full cache whenever a lookup request is performed. */ + /* */ + /* If you lookup nodes, you have the ability to "acquire" them, i.e., */ + /* to increment their reference count. This will prevent the node */ + /* from being flushed out of the cache until you explicitly "release" */ + /* it (see @FTC_Node_Unref). */ + /* */ + /* See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup. */ + /* */ + typedef struct FTC_NodeRec_* FTC_Node; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_New */ + /* */ + /* <Description> */ + /* Creates a new cache manager. */ + /* */ + /* <Input> */ + /* library :: The parent FreeType library handle to use. */ + /* */ + /* max_bytes :: Maximum number of bytes to use for cached data. */ + /* Use 0 for defaults. */ + /* */ + /* requester :: An application-provided callback used to translate */ + /* face IDs into real @FT_Face objects. */ + /* */ + /* req_data :: A generic pointer that is passed to the requester */ + /* each time it is called (see @FTC_Face_Requester). */ + /* */ + /* <Output> */ + /* amanager :: A handle to a new manager object. 0 in case of */ + /* failure. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_Manager_New( FT_Library library, + FT_UInt max_faces, + FT_UInt max_sizes, + FT_ULong max_bytes, + FTC_Face_Requester requester, + FT_Pointer req_data, + FTC_Manager *amanager ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_Reset */ + /* */ + /* <Description> */ + /* Empties a given cache manager. This simply gets rid of all the */ + /* currently cached @FT_Face and @FT_Size objects within the manager. */ + /* */ + /* <InOut> */ + /* manager :: A handle to the manager. */ + /* */ + FT_EXPORT( void ) + FTC_Manager_Reset( FTC_Manager manager ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_Done */ + /* */ + /* <Description> */ + /* Destroys a given manager after emptying it. */ + /* */ + /* <Input> */ + /* manager :: A handle to the target cache manager object. */ + /* */ + FT_EXPORT( void ) + FTC_Manager_Done( FTC_Manager manager ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_LookupFace */ + /* */ + /* <Description> */ + /* Retrieves the @FT_Face object that corresponds to a given face ID */ + /* through a cache manager. */ + /* */ + /* <Input> */ + /* manager :: A handle to the cache manager. */ + /* */ + /* face_id :: The ID of the face object. */ + /* */ + /* <Output> */ + /* aface :: A handle to the face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The returned @FT_Face object is always owned by the manager. You */ + /* should never try to discard it yourself. */ + /* */ + /* The @FT_Face object doesn't necessarily have a current size object */ + /* (i.e., face->size can be 0). If you need a specific `font size', */ + /* use @FTC_Manager_LookupSize instead. */ + /* */ + /* Never change the face's transformation matrix (i.e., never call */ + /* the @FT_Set_Transform function) on a returned face! If you need */ + /* to transform glyphs, do it yourself after glyph loading. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_Manager_LookupFace( FTC_Manager manager, + FTC_FaceID face_id, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FTC_ScalerRec */ + /* */ + /* <Description> */ + /* A structure used to describe a given character size in either */ + /* pixels or points to the cache manager. See */ + /* @FTC_Manager_LookupSize. */ + /* */ + /* <Fields> */ + /* face_id :: The source face ID. */ + /* */ + /* width :: The character width. */ + /* */ + /* height :: The character height. */ + /* */ + /* pixel :: A Boolean. If TRUE, the `width' and `height' fields */ + /* are interpreted as integer pixel character sizes. */ + /* Otherwise, they are expressed as 1/64th of points. */ + /* */ + /* x_res :: Only used when `pixel' is FALSE to indicate the */ + /* horizontal resolution in dpi. */ + /* */ + /* y_res :: Only used when `pixel' is FALSE to indicate the */ + /* vertical resolution in dpi. */ + /* */ + /* <Note> */ + /* This type is mainly used to retrieve @FT_Size objects through the */ + /* cache manager. */ + /* */ + typedef struct FTC_ScalerRec_ + { + FTC_FaceID face_id; + FT_UInt width; + FT_UInt height; + FT_Int pixel; + FT_UInt x_res; + FT_UInt y_res; + + } FTC_ScalerRec, *FTC_Scaler; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Manager_LookupSize */ + /* */ + /* <Description> */ + /* Retrieve the @FT_Size object that corresponds to a given */ + /* @FTC_Scaler through a cache manager. */ + /* */ + /* <Input> */ + /* manager :: A handle to the cache manager. */ + /* */ + /* scaler :: A scaler handle. */ + /* */ + /* <Output> */ + /* asize :: A handle to the size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The returned @FT_Size object is always owned by the manager. You */ + /* should never try to discard it by yourself. */ + /* */ + /* You can access the parent @FT_Face object simply as `size->face' */ + /* if you need it. Note that this object is also owned by the */ + /* manager. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_Manager_LookupSize( FTC_Manager manager, + FTC_Scaler scaler, + FT_Size *asize ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_Node_Unref */ + /* */ + /* <Description> */ + /* Decrement a cache node's internal reference count. When the count */ + /* reaches 0, it is not destroyed but becomes eligible for subsequent */ + /* cache flushes. */ + /* */ + /* <Input> */ + /* node :: The cache node handle. */ + /* */ + /* manager :: The cache manager handle. */ + /* */ + FT_EXPORT( void ) + FTC_Node_Unref( FTC_Node node, + FTC_Manager manager ); + + + /* remove all nodes belonging to a given face_id */ + FT_EXPORT( void ) + FTC_Manager_RemoveFaceID( FTC_Manager manager, + FTC_FaceID face_id ); + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* cache_subsystem */ + /* */ + /*************************************************************************/ + + /************************************************************************ + * + * @type: + * FTC_CMapCache + * + * @description: + * An opaque handle used to manager a charmap cache. This cache is + * to hold character codes -> glyph indices mappings. + */ + typedef struct FTC_CMapCacheRec_* FTC_CMapCache; + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FTC_CMapCache_New */ + /* */ + /* @description: */ + /* Create a new charmap cache. */ + /* */ + /* @input: */ + /* manager :: A handle to the cache manager. */ + /* */ + /* @output: */ + /* acache :: A new cache handle. NULL in case of error. */ + /* */ + /* @return: */ + /* FreeType error code. 0 means success. */ + /* */ + /* @note: */ + /* Like all other caches, this one will be destroyed with the cache */ + /* manager. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_CMapCache_New( FTC_Manager manager, + FTC_CMapCache *acache ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FTC_CMapCache_Lookup */ + /* */ + /* @description: */ + /* Translate a character code into a glyph index, using the charmap */ + /* cache. */ + /* */ + /* @input: */ + /* cache :: A charmap cache handle. */ + /* */ + /* face_id :: The source face ID. */ + /* */ + /* cmap_index :: The index of the charmap in the source face. */ + /* */ + /* char_code :: The character code (in the corresponding charmap). */ + /* */ + /* @return: */ + /* Glyph index. 0 means `no glyph'. */ + /* */ + FT_EXPORT( FT_UInt ) + FTC_CMapCache_Lookup( FTC_CMapCache cache, + FTC_FaceID face_id, + FT_Int cmap_index, + FT_UInt32 char_code ); + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* cache_subsystem */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMAGE CACHE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct FTC_ImageTypeRec_ + { + FTC_FaceID face_id; + FT_Int width; + FT_Int height; + FT_Int32 flags; + + } FTC_ImageTypeRec; + + typedef struct FTC_ImageTypeRec_* FTC_ImageType; + + /* */ + +#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \ + ( FTC_FONT_COMPARE( &(d1)->font, &(d2)->font ) && \ + (d1)->flags == (d2)->flags ) + +#define FTC_IMAGE_TYPE_HASH( d ) \ + (FT_UFast)( FTC_FONT_HASH( &(d)->font ) ^ \ + ( (d)->flags << 4 ) ) + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_ImageCache */ + /* */ + /* <Description> */ + /* A handle to an glyph image cache object. They are designed to */ + /* hold many distinct glyph images while not exceeding a certain */ + /* memory threshold. */ + /* */ + typedef struct FTC_ImageCacheRec_* FTC_ImageCache; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_ImageCache_New */ + /* */ + /* <Description> */ + /* Creates a new glyph image cache. */ + /* */ + /* <Input> */ + /* manager :: The parent manager for the image cache. */ + /* */ + /* <Output> */ + /* acache :: A handle to the new glyph image cache object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_ImageCache_New( FTC_Manager manager, + FTC_ImageCache *acache ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_ImageCache_Lookup */ + /* */ + /* <Description> */ + /* Retrieves a given glyph image from a glyph image cache. */ + /* */ + /* <Input> */ + /* cache :: A handle to the source glyph image cache. */ + /* */ + /* type :: A pointer to a glyph image type descriptor. */ + /* */ + /* gindex :: The glyph index to retrieve. */ + /* */ + /* <Output> */ + /* aglyph :: The corresponding @FT_Glyph object. 0 in case of */ + /* failure. */ + /* */ + /* anode :: Used to return the address of of the corresponding cache */ + /* node after incrementing its reference count (see note */ + /* below). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The returned glyph is owned and managed by the glyph image cache. */ + /* Never try to transform or discard it manually! You can however */ + /* create a copy with @FT_Glyph_Copy and modify the new one. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the glyph image, after increasing its reference */ + /* count. This ensures that the node (as well as the FT_Glyph) will */ + /* always be kept in the cache until you call @FTC_Node_Unref to */ + /* `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the FT_Glyph could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + FT_EXPORT( FT_Error ) + FTC_ImageCache_Lookup( FTC_ImageCache cache, + FTC_ImageType type, + FT_UInt gindex, + FT_Glyph *aglyph, + FTC_Node *anode ); + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_SBit */ + /* */ + /* <Description> */ + /* A handle to a small bitmap descriptor. See the @FTC_SBitRec */ + /* structure for details. */ + /* */ + typedef struct FTC_SBitRec_* FTC_SBit; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FTC_SBitRec */ + /* */ + /* <Description> */ + /* A very compact structure used to describe a small glyph bitmap. */ + /* */ + /* <Fields> */ + /* width :: The bitmap width in pixels. */ + /* */ + /* height :: The bitmap height in pixels. */ + /* */ + /* left :: The horizontal distance from the pen position to the */ + /* left bitmap border (a.k.a. `left side bearing', or */ + /* `lsb'). */ + /* */ + /* top :: The vertical distance from the pen position (on the */ + /* baseline) to the upper bitmap border (a.k.a. `top */ + /* side bearing'). The distance is positive for upwards */ + /* Y coordinates. */ + /* */ + /* format :: The format of the glyph bitmap (monochrome or gray). */ + /* */ + /* max_grays :: Maximum gray level value (in the range 1 to 255). */ + /* */ + /* pitch :: The number of bytes per bitmap line. May be positive */ + /* or negative. */ + /* */ + /* xadvance :: The horizontal advance width in pixels. */ + /* */ + /* yadvance :: The vertical advance height in pixels. */ + /* */ + /* buffer :: A pointer to the bitmap pixels. */ + /* */ + typedef struct FTC_SBitRec_ + { + FT_Byte width; + FT_Byte height; + FT_Char left; + FT_Char top; + + FT_Byte format; + FT_Byte max_grays; + FT_Short pitch; + FT_Char xadvance; + FT_Char yadvance; + + FT_Byte* buffer; + + } FTC_SBitRec; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FTC_SBitCache */ + /* */ + /* <Description> */ + /* A handle to a small bitmap cache. These are special cache objects */ + /* used to store small glyph bitmaps (and anti-aliased pixmaps) in a */ + /* much more efficient way than the traditional glyph image cache */ + /* implemented by @FTC_ImageCache. */ + /* */ + typedef struct FTC_SBitCacheRec_* FTC_SBitCache; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_SBitCache_New */ + /* */ + /* <Description> */ + /* Creates a new cache to store small glyph bitmaps. */ + /* */ + /* <Input> */ + /* manager :: A handle to the source cache manager. */ + /* */ + /* <Output> */ + /* acache :: A handle to the new sbit cache. NULL in case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FTC_SBitCache_New( FTC_Manager manager, + FTC_SBitCache *acache ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FTC_SBitCache_Lookup */ + /* */ + /* <Description> */ + /* Looks up a given small glyph bitmap in a given sbit cache and */ + /* `lock' it to prevent its flushing from the cache until needed. */ + /* */ + /* <Input> */ + /* cache :: A handle to the source sbit cache. */ + /* */ + /* type :: A pointer to the glyph image type descriptor. */ + /* */ + /* gindex :: The glyph index. */ + /* */ + /* <Output> */ + /* sbit :: A handle to a small bitmap descriptor. */ + /* */ + /* anode :: Used to return the address of of the corresponding cache */ + /* node after incrementing its reference count (see note */ + /* below). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The small bitmap descriptor and its bit buffer are owned by the */ + /* cache and should never be freed by the application. They might */ + /* as well disappear from memory on the next cache lookup, so don't */ + /* treat them as persistent data. */ + /* */ + /* The descriptor's `buffer' field is set to 0 to indicate a missing */ + /* glyph bitmap. */ + /* */ + /* If `anode' is _not_ NULL, it receives the address of the cache */ + /* node containing the bitmap, after increasing its reference count. */ + /* This ensures that the node (as well as the image) will always be */ + /* kept in the cache until you call @FTC_Node_Unref to `release' it. */ + /* */ + /* If `anode' is NULL, the cache node is left unchanged, which means */ + /* that the bitmap could be flushed out of the cache on the next */ + /* call to one of the caching sub-system APIs. Don't assume that it */ + /* is persistent! */ + /* */ + FT_EXPORT( FT_Error ) + FTC_SBitCache_Lookup( FTC_SBitCache cache, + FTC_ImageType type, + FT_UInt gindex, + FTC_SBit *sbit, + FTC_Node *anode ); + + + /* */ + +FT_END_HEADER + +#endif /* __FTCACHE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftchapters.h b/Utilities/vtkfreetype/include/freetype/ftchapters.h new file mode 100644 index 0000000..c134ec1 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftchapters.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* core_api */ +/* */ +/* <Title> */ +/* Core API */ +/* */ +/* <Sections> */ +/* basic_types */ +/* base_interface */ +/* glyph_management */ +/* mac_specific */ +/* sizes_management */ +/* header_file_macros */ +/* */ +/***************************************************************************/ + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* format_specific */ +/* */ +/* <Title> */ +/* Format-Specific API */ +/* */ +/* <Sections> */ +/* multiple_masters */ +/* truetype_tables */ +/* type1_tables */ +/* sfnt_names */ +/* bdf_fonts */ +/* pfr_fonts */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* cache_subsystem */ +/* */ +/* <Title> */ +/* Cache Sub-System */ +/* */ +/* <Sections> */ +/* cache_subsystem */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* <Chapter> */ +/* support_api */ +/* */ +/* <Title> */ +/* Support API */ +/* */ +/* <Sections> */ +/* computations */ +/* list_processing */ +/* outline_processing */ +/* raster */ +/* system_interface */ +/* module_management */ +/* */ +/***************************************************************************/ + diff --git a/Utilities/vtkfreetype/include/freetype/fterrdef.h b/Utilities/vtkfreetype/include/freetype/fterrdef.h new file mode 100644 index 0000000..2f73c08 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/fterrdef.h @@ -0,0 +1,231 @@ +/***************************************************************************/ +/* */ +/* fterrdef.h */ +/* */ +/* FreeType error codes (specification). */ +/* */ +/* Copyright 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** LIST OF ERROR CODES/MESSAGES *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + + /* You need to define both FT_ERRORDEF_ and FT_NOERRORDEF_ before */ + /* including this file. */ + + + /* generic errors */ + + FT_NOERRORDEF_( Ok, 0x00, \ + "no error" ) + + FT_ERRORDEF_( Cannot_Open_Resource, 0x01, \ + "cannot open resource" ) + FT_ERRORDEF_( Unknown_File_Format, 0x02, \ + "unknown file format" ) + FT_ERRORDEF_( Invalid_File_Format, 0x03, \ + "broken file" ) + FT_ERRORDEF_( Invalid_Version, 0x04, \ + "invalid FreeType version" ) + FT_ERRORDEF_( Lower_Module_Version, 0x05, \ + "module version is too low" ) + FT_ERRORDEF_( Invalid_Argument, 0x06, \ + "invalid argument" ) + FT_ERRORDEF_( Unimplemented_Feature, 0x07, \ + "unimplemented feature" ) + FT_ERRORDEF_( Invalid_Table, 0x08, \ + "broken table" ) + FT_ERRORDEF_( Invalid_Offset, 0x09, \ + "broken offset within table" ) + + /* glyph/character errors */ + + FT_ERRORDEF_( Invalid_Glyph_Index, 0x10, \ + "invalid glyph index" ) + FT_ERRORDEF_( Invalid_Character_Code, 0x11, \ + "invalid character code" ) + FT_ERRORDEF_( Invalid_Glyph_Format, 0x12, \ + "unsupported glyph image format" ) + FT_ERRORDEF_( Cannot_Render_Glyph, 0x13, \ + "cannot render this glyph format" ) + FT_ERRORDEF_( Invalid_Outline, 0x14, \ + "invalid outline" ) + FT_ERRORDEF_( Invalid_Composite, 0x15, \ + "invalid composite glyph" ) + FT_ERRORDEF_( Too_Many_Hints, 0x16, \ + "too many hints" ) + FT_ERRORDEF_( Invalid_Pixel_Size, 0x17, \ + "invalid pixel size" ) + + /* handle errors */ + + FT_ERRORDEF_( Invalid_Handle, 0x20, \ + "invalid object handle" ) + FT_ERRORDEF_( Invalid_Library_Handle, 0x21, \ + "invalid library handle" ) + FT_ERRORDEF_( Invalid_Driver_Handle, 0x22, \ + "invalid module handle" ) + FT_ERRORDEF_( Invalid_Face_Handle, 0x23, \ + "invalid face handle" ) + FT_ERRORDEF_( Invalid_Size_Handle, 0x24, \ + "invalid size handle" ) + FT_ERRORDEF_( Invalid_Slot_Handle, 0x25, \ + "invalid glyph slot handle" ) + FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26, \ + "invalid charmap handle" ) + FT_ERRORDEF_( Invalid_Cache_Handle, 0x27, \ + "invalid cache manager handle" ) + FT_ERRORDEF_( Invalid_Stream_Handle, 0x28, \ + "invalid stream handle" ) + + /* driver errors */ + + FT_ERRORDEF_( Too_Many_Drivers, 0x30, \ + "too many modules" ) + FT_ERRORDEF_( Too_Many_Extensions, 0x31, \ + "too many extensions" ) + + /* memory errors */ + + FT_ERRORDEF_( Out_Of_Memory, 0x40, \ + "out of memory" ) + FT_ERRORDEF_( Unlisted_Object, 0x41, \ + "unlisted object" ) + + /* stream errors */ + + FT_ERRORDEF_( Cannot_Open_Stream, 0x51, \ + "cannot open stream" ) + FT_ERRORDEF_( Invalid_Stream_Seek, 0x52, \ + "invalid stream seek" ) + FT_ERRORDEF_( Invalid_Stream_Skip, 0x53, \ + "invalid stream skip" ) + FT_ERRORDEF_( Invalid_Stream_Read, 0x54, \ + "invalid stream read" ) + FT_ERRORDEF_( Invalid_Stream_Operation, 0x55, \ + "invalid stream operation" ) + FT_ERRORDEF_( Invalid_Frame_Operation, 0x56, \ + "invalid frame operation" ) + FT_ERRORDEF_( Nested_Frame_Access, 0x57, \ + "nested frame access" ) + FT_ERRORDEF_( Invalid_Frame_Read, 0x58, \ + "invalid frame read" ) + + /* raster errors */ + + FT_ERRORDEF_( Raster_Uninitialized, 0x60, \ + "raster uninitialized" ) + FT_ERRORDEF_( Raster_Corrupted, 0x61, \ + "raster corrupted" ) + FT_ERRORDEF_( Raster_Overflow, 0x62, \ + "raster overflow" ) + FT_ERRORDEF_( Raster_Negative_Height, 0x63, \ + "negative height while rastering" ) + + /* cache errors */ + + FT_ERRORDEF_( Too_Many_Caches, 0x70, \ + "too many registered caches" ) + + /* TrueType and SFNT errors */ + + FT_ERRORDEF_( Invalid_Opcode, 0x80, \ + "invalid opcode" ) + FT_ERRORDEF_( Too_Few_Arguments, 0x81, \ + "too few arguments" ) + FT_ERRORDEF_( Stack_Overflow, 0x82, \ + "stack overflow" ) + FT_ERRORDEF_( Code_Overflow, 0x83, \ + "code overflow" ) + FT_ERRORDEF_( Bad_Argument, 0x84, \ + "bad argument" ) + FT_ERRORDEF_( Divide_By_Zero, 0x85, \ + "division by zero" ) + FT_ERRORDEF_( Invalid_Reference, 0x86, \ + "invalid reference" ) + FT_ERRORDEF_( Debug_OpCode, 0x87, \ + "found debug opcode" ) + FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88, \ + "found ENDF opcode in execution stream" ) + FT_ERRORDEF_( Nested_DEFS, 0x89, \ + "nested DEFS" ) + FT_ERRORDEF_( Invalid_CodeRange, 0x8A, \ + "invalid code range" ) + FT_ERRORDEF_( Execution_Too_Long, 0x8B, \ + "execution context too long" ) + FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C, \ + "too many function definitions" ) + FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D, \ + "too many instruction definitions" ) + FT_ERRORDEF_( Table_Missing, 0x8E, \ + "SFNT font table missing" ) + FT_ERRORDEF_( Horiz_Header_Missing, 0x8F, \ + "horizontal header (hhea) table missing" ) + FT_ERRORDEF_( Locations_Missing, 0x90, \ + "locations (loca) table missing" ) + FT_ERRORDEF_( Name_Table_Missing, 0x91, \ + "name table missing" ) + FT_ERRORDEF_( CMap_Table_Missing, 0x92, \ + "character map (cmap) table missing" ) + FT_ERRORDEF_( Hmtx_Table_Missing, 0x93, \ + "horizontal metrics (hmtx) table missing" ) + FT_ERRORDEF_( Post_Table_Missing, 0x94, \ + "PostScript (post) table missing" ) + FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95, \ + "invalid horizontal metrics" ) + FT_ERRORDEF_( Invalid_CharMap_Format, 0x96, \ + "invalid character map (cmap) format" ) + FT_ERRORDEF_( Invalid_PPem, 0x97, \ + "invalid ppem value" ) + FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98, \ + "invalid vertical metrics" ) + FT_ERRORDEF_( Could_Not_Find_Context, 0x99, \ + "could not find context" ) + FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A, \ + "invalid PostScript (post) table format" ) + FT_ERRORDEF_( Invalid_Post_Table, 0x9B, \ + "invalid PostScript (post) table" ) + + /* CFF, CID, and Type 1 errors */ + + FT_ERRORDEF_( Syntax_Error, 0xA0, \ + "opcode syntax error" ) + FT_ERRORDEF_( Stack_Underflow, 0xA1, \ + "argument stack underflow" ) + FT_ERRORDEF_( Ignore, 0xA2, \ + "ignore" ) + + /* BDF errors */ + + FT_ERRORDEF_( Missing_Startfont_Field, 0xB0, \ + "`STARTFONT' field missing" ) + FT_ERRORDEF_( Missing_Font_Field, 0xB1, \ + "`FONT' field missing" ) + FT_ERRORDEF_( Missing_Size_Field, 0xB2, \ + "`SIZE' field missing" ) + FT_ERRORDEF_( Missing_Chars_Field, 0xB3, \ + "`CHARS' field missing" ) + FT_ERRORDEF_( Missing_Startchar_Field, 0xB4, \ + "`STARTCHAR' field missing" ) + FT_ERRORDEF_( Missing_Encoding_Field, 0xB5, \ + "`ENCODING' field missing" ) + FT_ERRORDEF_( Missing_Bbx_Field, 0xB6, \ + "`BBX' field missing" ) + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/fterrors.h b/Utilities/vtkfreetype/include/freetype/fterrors.h new file mode 100644 index 0000000..1def4f9 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/fterrors.h @@ -0,0 +1,207 @@ +/***************************************************************************/ +/* */ +/* fterrors.h */ +/* */ +/* FreeType error code handling (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This special header file is used to define the handling of FT2 */ + /* enumeration constants. It can also be used to generate error message */ + /* strings with a small macro trick explained below. */ + /* */ + /* I - Error Formats */ + /* ----------------- */ + /* */ + /* Since release 2.1, the error constants have changed. The lower */ + /* byte of the error value gives the "generic" error code, while the */ + /* higher byte indicates in which module the error occurred. */ + /* */ + /* You can use the macro FT_ERROR_BASE(x) macro to extract the generic */ + /* error code from an FT_Error value. */ + /* */ + /* The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be */ + /* undefined in ftoption.h in order to make the higher byte always */ + /* zero, in case you need to be compatible with previous versions of */ + /* FreeType 2. */ + /* */ + /* */ + /* II - Error Message strings */ + /* -------------------------- */ + /* */ + /* The error definitions below are made through special macros that */ + /* allow client applications to build a table of error message strings */ + /* if they need it. The strings are not included in a normal build of */ + /* FreeType 2 to save space (most client applications do not use */ + /* them). */ + /* */ + /* To do so, you have to define the following macros before including */ + /* this file: */ + /* */ + /* FT_ERROR_START_LIST :: */ + /* This macro is called before anything else to define the start of */ + /* the error list. It is followed by several FT_ERROR_DEF calls */ + /* (see below). */ + /* */ + /* FT_ERROR_DEF( e, v, s ) :: */ + /* This macro is called to define one single error. */ + /* `e' is the error code identifier (e.g. FT_Err_Invalid_Argument). */ + /* `v' is the error numerical value. */ + /* `s' is the corresponding error string. */ + /* */ + /* FT_ERROR_END_LIST :: */ + /* This macro ends the list. */ + /* */ + /* Additionally, you have to undefine __FTERRORS_H__ before #including */ + /* this file. */ + /* */ + /* Here is a simple example: */ + /* */ + /* { */ + /* #undef __FTERRORS_H__ */ + /* #define FT_ERRORDEF( e, v, s ) { e, s }, */ + /* #define FT_ERROR_START_LIST { */ + /* #define FT_ERROR_END_LIST { 0, 0 } }; */ + /* */ + /* const struct */ + /* { */ + /* int err_code; */ + /* const char* err_msg */ + /* } ft_errors[] = */ + /* */ + /* #include FT_ERRORS_H */ + /* } */ + /* */ + /*************************************************************************/ + + +#ifndef __FTERRORS_H__ +#define __FTERRORS_H__ + + + /* include module base error codes */ +#include FT_MODULE_ERRORS_H + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** SETUP MACROS *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#undef FT_NEED_EXTERN_C + +#undef FT_ERR_XCAT +#undef FT_ERR_CAT + +#define FT_ERR_XCAT( x, y ) x ## y +#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) + + + /* FT_ERR_PREFIX is used as a prefix for error identifiers. */ + /* By default, we use `FT_Err_'. */ + /* */ +#ifndef FT_ERR_PREFIX +#define FT_ERR_PREFIX FT_Err_ +#endif + + + /* FT_ERR_BASE is used as the base for module-specific errors. */ + /* */ +#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS + +#ifndef FT_ERR_BASE +#define FT_ERR_BASE FT_Mod_Err_Base +#endif + +#else + +#undef FT_ERR_BASE +#define FT_ERR_BASE 0 + +#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */ + + + /* If FT_ERRORDEF is not defined, we need to define a simple */ + /* enumeration type. */ + /* */ +#ifndef FT_ERRORDEF + +#define FT_ERRORDEF( e, v, s ) e = v, +#define FT_ERROR_START_LIST enum { +#define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) }; + +#ifdef __cplusplus +#define FT_NEED_EXTERN_C + extern "C" { +#endif + +#endif /* !FT_ERRORDEF */ + + + /* this macro is used to define an error */ +#define FT_ERRORDEF_( e, v, s ) \ + FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s ) + + /* this is only used for FT_Err_Ok, which must be 0! */ +#define FT_NOERRORDEF_( e, v, s ) \ + FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s ) + + +#ifdef FT_ERROR_START_LIST + FT_ERROR_START_LIST +#endif + + + /* no include the error codes */ +#include FT_ERROR_DEFINITIONS_H + + +#ifdef FT_ERROR_END_LIST + FT_ERROR_END_LIST +#endif + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** SIMPLE CLEANUP *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + +#ifdef FT_NEED_EXTERN_C + } +#endif + +#undef FT_ERROR_START_LIST +#undef FT_ERROR_END_LIST + +#undef FT_ERRORDEF +#undef FT_ERRORDEF_ +#undef FT_NOERRORDEF_ + +#undef FT_NEED_EXTERN_C +#undef FT_ERR_PREFIX +#undef FT_ERR_BASE +#undef FT_ERR_CONCAT + +#endif /* __FTERRORS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftglyph.h b/Utilities/vtkfreetype/include/freetype/ftglyph.h new file mode 100644 index 0000000..14050a2 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftglyph.h @@ -0,0 +1,565 @@ +/***************************************************************************/ +/* */ +/* ftglyph.h */ +/* */ +/* FreeType convenience functions to handle glyphs (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file contains the definition of several convenience functions */ + /* that can be used by client applications to easily retrieve glyph */ + /* bitmaps and outlines from a given face. */ + /* */ + /* These functions should be optional if you are writing a font server */ + /* or text layout engine on top of FreeType. However, they are pretty */ + /* handy for many other simple uses of the library. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTGLYPH_H__ +#define __FTGLYPH_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* glyph_management */ + /* */ + /* <Title> */ + /* Glyph Management */ + /* */ + /* <Abstract> */ + /* Generic interface to manage individual glyph data. */ + /* */ + /* <Description> */ + /* This section contains definitions used to manage glyph data */ + /* through generic FT_Glyph objects. Each of them can contain a */ + /* bitmap, a vector outline, or even images in other formats. */ + /* */ + /*************************************************************************/ + + + /* forward declaration to a private type */ + typedef struct FT_Glyph_Class_ FT_Glyph_Class; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Glyph */ + /* */ + /* <Description> */ + /* Handle to an object used to model generic glyph images. It is a */ + /* pointer to the @FT_GlyphRec structure and can contain a glyph */ + /* bitmap or pointer. */ + /* */ + /* <Note> */ + /* Glyph objects are not owned by the library. You must thus release */ + /* them manually (through @FT_Done_Glyph) _before_ calling */ + /* @FT_Done_FreeType. */ + /* */ + typedef struct FT_GlyphRec_* FT_Glyph; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_GlyphRec */ + /* */ + /* <Description> */ + /* The root glyph structure contains a given glyph image plus its */ + /* advance width in 16.16 fixed float format. */ + /* */ + /* <Fields> */ + /* library :: A handle to the FreeType library object. */ + /* */ + /* clazz :: A pointer to the glyph's class. Private. */ + /* */ + /* format :: The format of the glyph's image. */ + /* */ + /* advance :: A 16.16 vector that gives the glyph's advance width. */ + /* */ + typedef struct FT_GlyphRec_ + { + FT_Library library; + const FT_Glyph_Class* clazz; + FT_Glyph_Format format; + FT_Vector advance; + + } FT_GlyphRec; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_BitmapGlyph */ + /* */ + /* <Description> */ + /* A handle to an object used to model a bitmap glyph image. This is */ + /* a sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec. */ + /* */ + typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_BitmapGlyphRec */ + /* */ + /* <Description> */ + /* A structure used for bitmap glyph images. This really is a */ + /* `sub-class' of `FT_GlyphRec'. */ + /* */ + /* <Fields> */ + /* root :: The root FT_Glyph fields. */ + /* */ + /* left :: The left-side bearing, i.e., the horizontal distance */ + /* from the current pen position to the left border of the */ + /* glyph bitmap. */ + /* */ + /* top :: The top-side bearing, i.e., the vertical distance from */ + /* the current pen position to the top border of the glyph */ + /* bitmap. This distance is positive for upwards-y! */ + /* */ + /* bitmap :: A descriptor for the bitmap. */ + /* */ + /* <Note> */ + /* You can typecast FT_Glyph to FT_BitmapGlyph if you have */ + /* glyph->format == FT_GLYPH_FORMAT_BITMAP. This lets you access */ + /* the bitmap's contents easily. */ + /* */ + /* The corresponding pixel buffer is always owned by the BitmapGlyph */ + /* and is thus created and destroyed with it. */ + /* */ + typedef struct FT_BitmapGlyphRec_ + { + FT_GlyphRec root; + FT_Int left; + FT_Int top; + FT_Bitmap bitmap; + + } FT_BitmapGlyphRec; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_OutlineGlyph */ + /* */ + /* <Description> */ + /* A handle to an object used to model an outline glyph image. This */ + /* is a sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec. */ + /* */ + typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_OutlineGlyphRec */ + /* */ + /* <Description> */ + /* A structure used for outline (vectorial) glyph images. This */ + /* really is a `sub-class' of `FT_GlyphRec'. */ + /* */ + /* <Fields> */ + /* root :: The root FT_Glyph fields. */ + /* */ + /* outline :: A descriptor for the outline. */ + /* */ + /* <Note> */ + /* You can typecast FT_Glyph to FT_OutlineGlyph if you have */ + /* glyph->format == FT_GLYPH_FORMAT_OUTLINE. This lets you access */ + /* the outline's content easily. */ + /* */ + /* As the outline is extracted from a glyph slot, its coordinates are */ + /* expressed normally in 26.6 pixels, unless the flag */ + /* FT_LOAD_NO_SCALE was used in FT_Load_Glyph() or FT_Load_Char(). */ + /* */ + /* The outline's tables are always owned by the object and are */ + /* destroyed with it. */ + /* */ + typedef struct FT_OutlineGlyphRec_ + { + FT_GlyphRec root; + FT_Outline outline; + + } FT_OutlineGlyphRec; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Glyph */ + /* */ + /* <Description> */ + /* A function used to extract a glyph image from a slot. */ + /* */ + /* <Input> */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* <Output> */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Glyph( FT_GlyphSlot slot, + FT_Glyph *aglyph ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_Copy */ + /* */ + /* <Description> */ + /* A function used to copy a glyph image. Note that the created */ + /* @FT_Glyph object must be released with @FT_Done_Glyph. */ + /* */ + /* <Input> */ + /* source :: A handle to the source glyph object. */ + /* */ + /* <Output> */ + /* target :: A handle to the target glyph object. 0 in case of */ + /* error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Glyph_Copy( FT_Glyph source, + FT_Glyph *target ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_Transform */ + /* */ + /* <Description> */ + /* Transforms a glyph image if its format is scalable. */ + /* */ + /* <InOut> */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to a 2x2 matrix to apply. */ + /* */ + /* delta :: A pointer to a 2d vector to apply. Coordinates are */ + /* expressed in 1/64th of a pixel. */ + /* */ + /* <Return> */ + /* FreeType error code (the glyph format is not scalable if it is */ + /* not zero). */ + /* */ + /* <Note> */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Glyph_Transform( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Glyph_BBox_Mode */ + /* */ + /* <Description> */ + /* The mode how the values of @FT_Glyph_Get_CBox are returned. */ + /* */ + /* <Values> */ + /* FT_GLYPH_BBOX_UNSCALED :: */ + /* Return unscaled font units. */ + /* */ + /* FT_GLYPH_BBOX_SUBPIXELS :: */ + /* Return unfitted 26.6 coordinates. */ + /* */ + /* FT_GLYPH_BBOX_GRIDFIT :: */ + /* Return grid-fitted 26.6 coordinates. */ + /* */ + /* FT_GLYPH_BBOX_TRUNCATE :: */ + /* Return coordinates in integer pixels. */ + /* */ + /* FT_GLYPH_BBOX_PIXELS :: */ + /* Return grid-fitted pixel coordinates. */ + /* */ + typedef enum FT_Glyph_BBox_Mode_ + { + FT_GLYPH_BBOX_UNSCALED = 0, + FT_GLYPH_BBOX_SUBPIXELS = 0, + FT_GLYPH_BBOX_GRIDFIT = 1, + FT_GLYPH_BBOX_TRUNCATE = 2, + FT_GLYPH_BBOX_PIXELS = 3 + + } FT_Glyph_BBox_Mode; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_glyph_bbox_xxx */ + /* */ + /* <Description> */ + /* These constants are deprecated. Use the corresponding */ + /* @FT_Glyph_BBox_Mode values instead. */ + /* */ + /* <Values> */ + /* ft_glyph_bbox_unscaled :: see @FT_GLYPH_BBOX_UNSCALED */ + /* ft_glyph_bbox_subpixels :: see @FT_GLYPH_BBOX_SUBPIXELS */ + /* ft_glyph_bbox_gridfit :: see @FT_GLYPH_BBOX_GRIDFIT */ + /* ft_glyph_bbox_truncate :: see @FT_GLYPH_BBOX_TRUNCATE */ + /* ft_glyph_bbox_pixels :: see @FT_GLYPH_BBOX_PIXELS */ + /* */ +#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED +#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS +#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT +#define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE +#define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_Get_CBox */ + /* */ + /* <Description> */ + /* Returns a glyph's `control box'. The control box encloses all the */ + /* outline's points, including Bezier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bezier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* <Input> */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: The mode which indicates how to interpret the returned */ + /* bounding box values. */ + /* */ + /* <Output> */ + /* acbox :: The glyph coordinate bounding box. Coordinates are */ + /* expressed in 1/64th of pixels if it is grid-fitted. */ + /* */ + /* <Note> */ + /* Coordinates are relative to the glyph origin, using the Y-upwards */ + /* convention. */ + /* */ + /* If the glyph has been loaded with FT_LOAD_NO_SCALE, `bbox_mode' */ + /* must be set to `FT_GLYPH_BBOX_UNSCALED' to get unscaled font */ + /* units in 26.6 pixel format. The value `FT_GLYPH_BBOX_SUBPIXELS' */ + /* is another name for this constant. */ + /* */ + /* Note that the maximum coordinates are exclusive, which means that */ + /* one can compute the width and height of the glyph image (be it in */ + /* integer or 26.6 pixels) as: */ + /* */ + /* width = bbox.xMax - bbox.xMin; */ + /* height = bbox.yMax - bbox.yMin; */ + /* */ + /* Note also that for 26.6 coordinates, if `bbox_mode' is set to */ + /* `FT_GLYPH_BBOX_GRIDFIT', the coordinates will also be grid-fitted, */ + /* which corresponds to: */ + /* */ + /* bbox.xMin = FLOOR(bbox.xMin); */ + /* bbox.yMin = FLOOR(bbox.yMin); */ + /* bbox.xMax = CEILING(bbox.xMax); */ + /* bbox.yMax = CEILING(bbox.yMax); */ + /* */ + /* To get the bbox in pixel coordinates, set `bbox_mode' to */ + /* `FT_GLYPH_BBOX_TRUNCATE'. */ + /* */ + /* To get the bbox in grid-fitted pixel coordinates, set `bbox_mode' */ + /* to `FT_GLYPH_BBOX_PIXELS'. */ + /* */ + FT_EXPORT( void ) + FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox *acbox ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* <Description> */ + /* Converts a given glyph object to a bitmap glyph object. */ + /* */ + /* <InOut> */ + /* the_glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* <Input> */ + /* render_mode :: An enumeration that describe how the data is */ + /* rendered. */ + /* */ + /* origin :: A pointer to a vector used to translate the glyph */ + /* image before rendering. Can be 0 (if no */ + /* translation). The origin is expressed in */ + /* 26.6 pixels. */ + /* */ + /* destroy :: A boolean that indicates that the original glyph */ + /* image should be destroyed by this function. It is */ + /* never destroyed in case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The glyph image is translated with the `origin' vector before */ + /* rendering. */ + /* */ + /* The first parameter is a pointer to a FT_Glyph handle, that will */ + /* be replaced by this function. Typically, you would use (omitting */ + /* error handling): */ + /* */ + /* */ + /* { */ + /* FT_Glyph glyph; */ + /* FT_BitmapGlyph glyph_bitmap; */ + /* */ + /* */ + /* // load glyph */ + /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ + /* */ + /* // extract glyph image */ + /* error = FT_Get_Glyph( face->glyph, &glyph ); */ + /* */ + /* // convert to a bitmap (default render mode + destroy old) */ + /* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP ) */ + /* { */ + /* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_DEFAULT, */ + /* 0, 1 ); */ + /* if ( error ) // glyph unchanged */ + /* ... */ + /* } */ + /* */ + /* // access bitmap content by typecasting */ + /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ + /* */ + /* // do funny stuff with it, like blitting/drawing */ + /* ... */ + /* */ + /* // discard glyph image (bitmap or not) */ + /* FT_Done_Glyph( glyph ); */ + /* } */ + /* */ + /* */ + /* This function does nothing if the glyph format isn't scalable. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_Render_Mode render_mode, + FT_Vector* origin, + FT_Bool destroy ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Glyph */ + /* */ + /* <Description> */ + /* Destroys a given glyph. */ + /* */ + /* <Input> */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT( void ) + FT_Done_Glyph( FT_Glyph glyph ); + + + /* other helpful functions */ + + /*************************************************************************/ + /* */ + /* <Section> */ + /* computations */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Matrix_Multiply */ + /* */ + /* <Description> */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* <Input> */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* <InOut> */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* <Note> */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT( void ) + FT_Matrix_Multiply( const FT_Matrix* a, + FT_Matrix* b ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Matrix_Invert */ + /* */ + /* <Description> */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* <InOut> */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Matrix_Invert( FT_Matrix* matrix ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTGLYPH_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftgzip.h b/Utilities/vtkfreetype/include/freetype/ftgzip.h new file mode 100644 index 0000000..5d7228b --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftgzip.h @@ -0,0 +1,100 @@ +/***************************************************************************/ +/* */ +/* ftgzip.h */ +/* */ +/* Gzip-compressed stream support. */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTGZIP_H__ +#define __FTGZIP_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* <Section> */ + /* gzip */ + /* */ + /* <Title> */ + /* GZIP Streams */ + /* */ + /* <Abstract> */ + /* Using gzip-compressed font files */ + /* */ + /* <Description> */ + /* This section contains the declaration of Gzip-specific functions. */ + /* */ + /*************************************************************************/ + + + /************************************************************************ + * + * @function: + * FT_Stream_OpenGzip + * + * @description: + * Open a new stream to parse gzip-compressed font files. This is + * mainly used to support the compressed *.pcf.gz fonts that come + * with XFree86. + * + * @input: + * stream :: The target embedding stream. + * + * source :: The source stream. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * The source stream must be opened _before_ calling this function. + * + * Calling the internal function FT_Stream_Close on the new stream will + * *not* call FT_Stream_Close on the source stream. None of the stream + * objects will be released to the heap. + * + * The stream implementation is very basic and resets the decompression + * process each time seeking backwards is needed within the stream. + * + * In certain builds of the library, gzip compression recognition is + * automatically handled when calling @FT_New_Face or @FT_Open_Face. + * This means that if no font driver is capable of handling the raw + * compressed file, the library will try to open a gzipped stream from + * it and re-open the face with it. + * + * This function may return "FT_Err_Unimplemented" if your build of + * FreeType was not compiled with zlib support. + */ + FT_EXPORT( FT_Error ) + FT_Stream_OpenGzip( FT_Stream stream, + FT_Stream source ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTGZIP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftimage.h b/Utilities/vtkfreetype/include/freetype/ftimage.h new file mode 100644 index 0000000..4682a4c --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftimage.h @@ -0,0 +1,1236 @@ +/***************************************************************************/ +/* */ +/* ftimage.h */ +/* */ +/* FreeType glyph image formats and default raster interface */ +/* (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* Note: A `raster' is simply a scan-line converter, used to render */ + /* FT_Outlines into FT_Bitmaps. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTIMAGE_H__ +#define __FTIMAGE_H__ + + +/* _STANDALONE_ is from ftgrays.c */ +#ifndef _STANDALONE_ +#include <ft2build.h> +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* basic_types */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Pos */ + /* */ + /* <Description> */ + /* The type FT_Pos is a 32-bit integer used to store vectorial */ + /* coordinates. Depending on the context, these can represent */ + /* distances in integer font units, or 16,16, or 26.6 fixed float */ + /* pixel coordinates. */ + /* */ + typedef signed long FT_Pos; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Vector */ + /* */ + /* <Description> */ + /* A simple structure used to store a 2D vector; coordinates are of */ + /* the FT_Pos type. */ + /* */ + /* <Fields> */ + /* x :: The horizontal coordinate. */ + /* y :: The vertical coordinate. */ + /* */ + typedef struct FT_Vector_ + { + FT_Pos x; + FT_Pos y; + + } FT_Vector; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_BBox */ + /* */ + /* <Description> */ + /* A structure used to hold an outline's bounding box, i.e., the */ + /* coordinates of its extrema in the horizontal and vertical */ + /* directions. */ + /* */ + /* <Fields> */ + /* xMin :: The horizontal minimum (left-most). */ + /* */ + /* yMin :: The vertical minimum (bottom-most). */ + /* */ + /* xMax :: The horizontal maximum (right-most). */ + /* */ + /* yMax :: The vertical maximum (top-most). */ + /* */ + typedef struct FT_BBox_ + { + FT_Pos xMin, yMin; + FT_Pos xMax, yMax; + + } FT_BBox; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Pixel_Mode */ + /* */ + /* <Description> */ + /* An enumeration type used to describe the format of pixels in a */ + /* given bitmap. Note that additional formats may be added in the */ + /* future. */ + /* */ + /* <Values> */ + /* FT_PIXEL_MODE_NONE :: */ + /* Value 0 is reserved. */ + /* */ + /* FT_PIXEL_MODE_MONO :: */ + /* A monochrome bitmap, using 1 bit per pixel. Note that pixels */ + /* are stored in most-significant order (MSB), which means that */ + /* the left-most pixel in a byte has value 128. */ + /* */ + /* FT_PIXEL_MODE_GRAY :: */ + /* An 8-bit bitmap, generally used to represent anti-aliased glyph */ + /* images. Each pixel is stored in one byte. Note that the number */ + /* of value "gray" levels is stored in the `num_bytes' field of */ + /* the @FT_Bitmap structure (it generally is 256). */ + /* */ + /* FT_PIXEL_MODE_GRAY2 :: */ + /* A 2-bit/pixel bitmap, used to represent embedded anti-aliased */ + /* bitmaps in font files according to the OpenType specification. */ + /* We haven't found a single font using this format, however. */ + /* */ + /* FT_PIXEL_MODE_GRAY4 :: */ + /* A 4-bit/pixel bitmap, used to represent embedded anti-aliased */ + /* bitmaps in font files according to the OpenType specification. */ + /* We haven't found a single font using this format, however. */ + /* */ + /* FT_PIXEL_MODE_LCD :: */ + /* An 8-bit bitmap, used to represent RGB or BGR decimated glyph */ + /* images used for display on LCD displays; the bitmap's width is */ + /* three times wider than the original glyph image. See also */ + /* @FT_RENDER_MODE_LCD. */ + /* */ + /* FT_PIXEL_MODE_LCD_V :: */ + /* An 8-bit bitmap, used to represent RGB or BGR decimated glyph */ + /* images used for display on rotated LCD displays; the bitmap's */ + /* height is three times taller than the original glyph image. */ + /* See also @FT_RENDER_MODE_LCD_V. */ + /* */ + typedef enum FT_Pixel_Mode_ + { + FT_PIXEL_MODE_NONE = 0, + FT_PIXEL_MODE_MONO, + FT_PIXEL_MODE_GRAY, + FT_PIXEL_MODE_GRAY2, + FT_PIXEL_MODE_GRAY4, + FT_PIXEL_MODE_LCD, + FT_PIXEL_MODE_LCD_V, + + FT_PIXEL_MODE_MAX /* do not remove */ + + } FT_Pixel_Mode; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_pixel_mode_xxx */ + /* */ + /* <Description> */ + /* A list of deprecated constants. Use the corresponding */ + /* @FT_Pixel_Mode values instead. */ + /* */ + /* <Values> */ + /* ft_pixel_mode_none :: see @FT_PIXEL_MODE_NONE */ + /* ft_pixel_mode_mono :: see @FT_PIXEL_MODE_MONO */ + /* ft_pixel_mode_grays :: see @FT_PIXEL_MODE_GRAY */ + /* ft_pixel_mode_pal2 :: see @FT_PIXEL_MODE_GRAY2 */ + /* ft_pixel_mode_pal4 :: see @FT_PIXEL_MODE_GRAY4 */ + /* */ +#define ft_pixel_mode_none FT_PIXEL_MODE_NONE +#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO +#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY +#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2 +#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4 + + /* */ + +#if 0 + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Palette_Mode */ + /* */ + /* <Description> */ + /* THIS TYPE IS DEPRECATED. DO NOT USE IT! */ + /* */ + /* An enumeration type used to describe the format of a bitmap */ + /* palette, used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */ + /* */ + /* <Fields> */ + /* ft_palette_mode_rgb :: The palette is an array of 3-bytes RGB */ + /* records. */ + /* */ + /* ft_palette_mode_rgba :: The palette is an array of 4-bytes RGBA */ + /* records. */ + /* */ + /* <Note> */ + /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */ + /* FreeType, these types are not handled by the library itself. */ + /* */ + typedef enum FT_Palette_Mode_ + { + ft_palette_mode_rgb = 0, + ft_palette_mode_rgba, + + ft_palettte_mode_max /* do not remove */ + + } FT_Palette_Mode; + + /* */ + +#endif + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Bitmap */ + /* */ + /* <Description> */ + /* A structure used to describe a bitmap or pixmap to the raster. */ + /* Note that we now manage pixmaps of various depths through the */ + /* `pixel_mode' field. */ + /* */ + /* <Fields> */ + /* rows :: The number of bitmap rows. */ + /* */ + /* width :: The number of pixels in bitmap row. */ + /* */ + /* pitch :: The pitch's absolute value is the number of bytes */ + /* taken by one bitmap row, including padding. */ + /* However, the pitch is positive when the bitmap has */ + /* a `down' flow, and negative when it has an `up' */ + /* flow. In all cases, the pitch is an offset to add */ + /* to a bitmap pointer in order to go down one row. */ + /* */ + /* buffer :: A typeless pointer to the bitmap buffer. This */ + /* value should be aligned on 32-bit boundaries in */ + /* most cases. */ + /* */ + /* num_grays :: This field is only used with */ + /* `FT_PIXEL_MODE_GRAY'; it gives the number of gray */ + /* levels used in the bitmap. */ + /* */ + /* pixel_mode :: The pixel mode, i.e., how pixel bits are stored. */ + /* See @FT_Pixel_Mode for possible values. */ + /* */ + /* palette_mode :: This field is only used with paletted pixel modes; */ + /* it indicates how the palette is stored. */ + /* */ + /* palette :: A typeless pointer to the bitmap palette; only */ + /* used for paletted pixel modes. */ + /* */ + /* <Note> */ + /* For now, the only pixel mode supported by FreeType are mono and */ + /* grays. However, drivers might be added in the future to support */ + /* more `colorful' options. */ + /* */ + /* When using pixel modes pal2, pal4 and pal8 with a void `palette' */ + /* field, a gray pixmap with respectively 4, 16, and 256 levels of */ + /* gray is assumed. This, in order to be compatible with some */ + /* embedded bitmap formats defined in the TrueType specification. */ + /* */ + /* Note that no font was found presenting such embedded bitmaps, so */ + /* this is currently completely unhandled by the library. */ + /* */ + typedef struct FT_Bitmap_ + { + int rows; + int width; + int pitch; + unsigned char* buffer; + short num_grays; + char pixel_mode; + char palette_mode; + void* palette; + + } FT_Bitmap; + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* outline_processing */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Outline */ + /* */ + /* <Description> */ + /* This structure is used to describe an outline to the scan-line */ + /* converter. */ + /* */ + /* <Fields> */ + /* n_contours :: The number of contours in the outline. */ + /* */ + /* n_points :: The number of points in the outline. */ + /* */ + /* points :: A pointer to an array of `n_points' FT_Vector */ + /* elements, giving the outline's point coordinates. */ + /* */ + /* tags :: A pointer to an array of `n_points' chars, giving */ + /* each outline point's type. If bit 0 is unset, the */ + /* point is `off' the curve, i.e. a Bezier control */ + /* point, while it is `on' when set. */ + /* */ + /* Bit 1 is meaningful for `off' points only. If set, */ + /* it indicates a third-order Bezier arc control point; */ + /* and a second-order control point if unset. */ + /* */ + /* contours :: An array of `n_contours' shorts, giving the end */ + /* point of each contour within the outline. For */ + /* example, the first contour is defined by the points */ + /* `0' to `contours[0]', the second one is defined by */ + /* the points `contours[0]+1' to `contours[1]', etc. */ + /* */ + /* flags :: A set of bit flags used to characterize the outline */ + /* and give hints to the scan-converter and hinter on */ + /* how to convert/grid-fit it. See FT_Outline_Flags. */ + /* */ + typedef struct FT_Outline_ + { + short n_contours; /* number of contours in glyph */ + short n_points; /* number of points in the glyph */ + + FT_Vector* points; /* the outline's points */ + char* tags; /* the points flags */ + short* contours; /* the contour end points */ + + int flags; /* outline masks */ + + } FT_Outline; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_OUTLINE_FLAGS */ + /* */ + /* <Description> */ + /* A list of bit-field constants use for the flags in an outline's */ + /* `flags' field. */ + /* */ + /* <Values> */ + /* FT_OUTLINE_NONE :: Value 0 is reserved. */ + /* */ + /* FT_OUTLINE_OWNER :: If set, this flag indicates that the */ + /* outline's field arrays (i.e. */ + /* `points', `flags' & `contours') are */ + /* `owned' by the outline object, and */ + /* should thus be freed when it is */ + /* destroyed. */ + /* */ + /* FT_OUTLINE_EVEN_ODD_FILL :: By default, outlines are filled using */ + /* the non-zero winding rule. If set to */ + /* 1, the outline will be filled using */ + /* the even-odd fill rule (only works */ + /* with the smooth raster). */ + /* */ + /* FT_OUTLINE_REVERSE_FILL :: By default, outside contours of an */ + /* outline are oriented in clock-wise */ + /* direction, as defined in the TrueType */ + /* specification. This flag is set if */ + /* the outline uses the opposite */ + /* direction (typically for Type 1 */ + /* fonts). This flag is ignored by the */ + /* scan-converter. However, it is very */ + /* important for the auto-hinter. */ + /* */ + /* FT_OUTLINE_IGNORE_DROPOUTS :: By default, the scan converter will */ + /* try to detect drop-outs in an outline */ + /* and correct the glyph bitmap to */ + /* ensure consistent shape continuity. */ + /* If set, this flag hints the scan-line */ + /* converter to ignore such cases. */ + /* */ + /* FT_OUTLINE_HIGH_PRECISION :: This flag indicates that the */ + /* scan-line converter should try to */ + /* convert this outline to bitmaps with */ + /* the highest possible quality. It is */ + /* typically set for small character */ + /* sizes. Note that this is only a */ + /* hint, that might be completely */ + /* ignored by a given scan-converter. */ + /* */ + /* FT_OUTLINE_SINGLE_PASS :: This flag is set to force a given */ + /* scan-converter to only use a single */ + /* pass over the outline to render a */ + /* bitmap glyph image. Normally, it is */ + /* set for very large character sizes. */ + /* It is only a hint, that might be */ + /* completely ignored by a given */ + /* scan-converter. */ + /* */ +#define FT_OUTLINE_NONE 0x0 +#define FT_OUTLINE_OWNER 0x1 +#define FT_OUTLINE_EVEN_ODD_FILL 0x2 +#define FT_OUTLINE_REVERSE_FILL 0x4 +#define FT_OUTLINE_IGNORE_DROPOUTS 0x8 + +#define FT_OUTLINE_HIGH_PRECISION 0x100 +#define FT_OUTLINE_SINGLE_PASS 0x200 + + + /************************************************************************* + * + * @enum: + * ft_outline_flags + * + * @description: + * These constants are deprecated. Please use the corresponding + * @FT_OUTLINE_FLAGS values. + * + * @values: + * ft_outline_none :: See @FT_OUTLINE_NONE. + * ft_outline_owner :: See @FT_OUTLINE_OWNER. + * ft_outline_even_odd_fill :: See @FT_OUTLINE_EVEN_ODD_FILL. + * ft_outline_reverse_fill :: See @FT_OUTLINE_REVERSE_FILL. + * ft_outline_ignore_dropouts :: See @FT_OUTLINE_IGNORE_DROPOUTS. + * ft_outline_high_precision :: See @FT_OUTLINE_HIGH_PRECISION. + * ft_outline_single_pass :: See @FT_OUTLINE_SINGLE_PASS. + */ +#define ft_outline_none FT_OUTLINE_NONE +#define ft_outline_owner FT_OUTLINE_OWNER +#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL +#define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL +#define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS +#define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION +#define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS + + /* */ + +#define FT_CURVE_TAG( flag ) ( flag & 3 ) + +#define FT_CURVE_TAG_ON 1 +#define FT_CURVE_TAG_CONIC 0 +#define FT_CURVE_TAG_CUBIC 2 + +#define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */ +#define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */ + +#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \ + FT_CURVE_TAG_TOUCH_Y ) + +#define FT_Curve_Tag_On FT_CURVE_TAG_ON +#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC +#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC +#define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X +#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_MoveToFunc */ + /* */ + /* <Description> */ + /* A function pointer type used to describe the signature of a `move */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `move to' is emitted to start a new contour in an outline. */ + /* */ + /* <Input> */ + /* to :: A pointer to the target point of the `move to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + typedef int + (*FT_Outline_MoveToFunc)( FT_Vector* to, + void* user ); + +#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_LineToFunc */ + /* */ + /* <Description> */ + /* A function pointer type used to describe the signature of a `line */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `line to' is emitted to indicate a segment in the outline. */ + /* */ + /* <Input> */ + /* to :: A pointer to the target point of the `line to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + typedef int + (*FT_Outline_LineToFunc)( FT_Vector* to, + void* user ); + +#define FT_Outline_LineTo_Func FT_Outline_LineToFunc + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_ConicToFunc */ + /* */ + /* <Description> */ + /* A function pointer type use to describe the signature of a `conic */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `conic to' is emitted to indicate a second-order Bezier arc in */ + /* the outline. */ + /* */ + /* <Input> */ + /* control :: An intermediate control point between the last position */ + /* and the new target in `to'. */ + /* */ + /* to :: A pointer to the target end point of the conic arc. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + typedef int + (*FT_Outline_ConicToFunc)( FT_Vector* control, + FT_Vector* to, + void* user ); + +#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Outline_CubicToFunc */ + /* */ + /* <Description> */ + /* A function pointer type used to describe the signature of a `cubic */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `cubic to' is emitted to indicate a third-order Bezier arc. */ + /* */ + /* <Input> */ + /* control1 :: A pointer to the first Bezier control point. */ + /* */ + /* control2 :: A pointer to the second Bezier control point. */ + /* */ + /* to :: A pointer to the target end point. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + typedef int + (*FT_Outline_CubicToFunc)( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + void* user ); + +#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Outline_Funcs */ + /* */ + /* <Description> */ + /* A structure to hold various function pointers used during outline */ + /* decomposition in order to emit segments, conic, and cubic Beziers, */ + /* as well as `move to' and `close to' operations. */ + /* */ + /* <Fields> */ + /* move_to :: The `move to' emitter. */ + /* */ + /* line_to :: The segment emitter. */ + /* */ + /* conic_to :: The second-order Bezier arc emitter. */ + /* */ + /* cubic_to :: The third-order Bezier arc emitter. */ + /* */ + /* shift :: The shift that is applied to coordinates before they */ + /* are sent to the emitter. */ + /* */ + /* delta :: The delta that is applied to coordinates before they */ + /* are sent to the emitter, but after the shift. */ + /* */ + /* <Note> */ + /* The point coordinates sent to the emitters are the transformed */ + /* version of the original coordinates (this is important for high */ + /* accuracy during scan-conversion). The transformation is simple: */ + /* */ + /* x' = (x << shift) - delta */ + /* y' = (x << shift) - delta */ + /* */ + /* Set the value of `shift' and `delta' to 0 to get the original */ + /* point coordinates. */ + /* */ + typedef struct FT_Outline_Funcs_ + { + FT_Outline_MoveToFunc move_to; + FT_Outline_LineToFunc line_to; + FT_Outline_ConicToFunc conic_to; + FT_Outline_CubicToFunc cubic_to; + + int shift; + FT_Pos delta; + + } FT_Outline_Funcs; + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* basic_types */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Macro> */ + /* FT_IMAGE_TAG */ + /* */ + /* <Description> */ + /* This macro converts four letter tags into an unsigned long. */ + /* */ + /* <Note> */ + /* Since many 16bit compilers don't like 32bit enumerations, you */ + /* should redefine this macro in case of problems to something like */ + /* this: */ + /* */ + /* #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value */ + /* */ + /* to get a simple enumeration without assigning special numbers. */ + /* */ +#ifndef FT_IMAGE_TAG +#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \ + value = ( ( (unsigned long)_x1 << 24 ) | \ + ( (unsigned long)_x2 << 16 ) | \ + ( (unsigned long)_x3 << 8 ) | \ + (unsigned long)_x4 ) +#endif /* FT_IMAGE_TAG */ + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Glyph_Format */ + /* */ + /* <Description> */ + /* An enumeration type used to describe the format of a given glyph */ + /* image. Note that this version of FreeType only supports two image */ + /* formats, even though future font drivers will be able to register */ + /* their own format. */ + /* */ + /* <Values> */ + /* FT_GLYPH_FORMAT_NONE :: */ + /* The value 0 is reserved and does describe a glyph format. */ + /* */ + /* FT_GLYPH_FORMAT_COMPOSITE :: */ + /* The glyph image is a composite of several other images. This */ + /* format is _only_ used with @FT_LOAD_NO_RECURSE, and is used to */ + /* report compound glyphs (like accented characters). */ + /* */ + /* FT_GLYPH_FORMAT_BITMAP :: */ + /* The glyph image is a bitmap, and can be described as an */ + /* @FT_Bitmap. You generally need to access the `bitmap' field of */ + /* the @FT_GlyphSlotRec structure to read it. */ + /* */ + /* FT_GLYPH_FORMAT_OUTLINE :: */ + /* The glyph image is a vertorial outline made of line segments */ + /* and Bezier arcs; it can be described as an @FT_Outline; you */ + /* generally want to access the `outline' field of the */ + /* @FT_GlyphSlotRec structure to read it. */ + /* */ + /* FT_GLYPH_FORMAT_PLOTTER :: */ + /* The glyph image is a vectorial path with no inside/outside */ + /* contours. Some Type 1 fonts, like those in the Hershey family, */ + /* contain glyphs in this format. These are described as */ + /* @FT_Outline, but FreeType isn't currently capable of rendering */ + /* them correctly. */ + /* */ + typedef enum FT_Glyph_Format_ + { + FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ), + + FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ), + FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ) + + } FT_Glyph_Format; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* ft_glyph_format_xxx */ + /* */ + /* <Description> */ + /* A list of decprecated constants. Use the corresponding */ + /* @FT_Glyph_Format values instead. */ + /* */ + /* <Values> */ + /* ft_glyph_format_none :: see @FT_GLYPH_FORMAT_NONE */ + /* ft_glyph_format_composite :: see @FT_GLYPH_FORMAT_COMPOSITE */ + /* ft_glyph_format_bitmap :: see @FT_GLYPH_FORMAT_BITMAP */ + /* ft_glyph_format_outline :: see @FT_GLYPH_FORMAT_OUTLINE */ + /* ft_glyph_format_plotter :: see @FT_GLYPH_FORMAT_PLOTTER */ + /* */ +#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE +#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE +#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP +#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE +#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** R A S T E R D E F I N I T I O N S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* A raster is a scan converter, in charge of rendering an outline into */ + /* a a bitmap. This section contains the public API for rasters. */ + /* */ + /* Note that in FreeType 2, all rasters are now encapsulated within */ + /* specific modules called `renderers'. See `freetype/ftrender.h' for */ + /* more details on renderers. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* raster */ + /* */ + /* <Title> */ + /* Scanline converter */ + /* */ + /* <Abstract> */ + /* How vectorial outlines are converted into bitmaps and pixmaps. */ + /* */ + /* <Description> */ + /* This section contains technical definitions. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Raster */ + /* */ + /* <Description> */ + /* A handle (pointer) to a raster object. Each object can be used */ + /* independently to convert an outline into a bitmap or pixmap. */ + /* */ + typedef struct FT_RasterRec_* FT_Raster; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Span */ + /* */ + /* <Description> */ + /* A structure used to model a single span of gray (or black) pixels */ + /* when rendering a monochrome or anti-aliased bitmap. */ + /* */ + /* <Fields> */ + /* x :: The span's horizontal start position. */ + /* */ + /* len :: The span's length in pixels. */ + /* */ + /* coverage :: The span color/coverage, ranging from 0 (background) */ + /* to 255 (foreground). Only used for anti-aliased */ + /* rendering. */ + /* */ + /* <Note> */ + /* This structure is used by the span drawing callback type named */ + /* FT_SpanFunc which takes the y-coordinate of the span as a */ + /* a parameter. */ + /* */ + /* The coverage value is always between 0 and 255, even if the number */ + /* of gray levels have been set through FT_Set_Gray_Levels(). */ + /* */ + typedef struct FT_Span_ + { + short x; + unsigned short len; + unsigned char coverage; + + } FT_Span; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_SpanFunc */ + /* */ + /* <Description> */ + /* A function used as a call-back by the anti-aliased renderer in */ + /* order to let client applications draw themselves the gray pixel */ + /* spans on each scan line. */ + /* */ + /* <Input> */ + /* y :: The scanline's y-coordinate. */ + /* */ + /* count :: The number of spans to draw on this scanline. */ + /* */ + /* spans :: A table of `count' spans to draw on the scanline. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* <Note> */ + /* This callback allows client applications to directly render the */ + /* gray spans of the anti-aliased bitmap to any kind of surfaces. */ + /* */ + /* This can be used to write anti-aliased outlines directly to a */ + /* given background bitmap, and even perform translucency. */ + /* */ + /* Note that the `count' field cannot be greater than a fixed value */ + /* defined by the FT_MAX_GRAY_SPANS configuration macro in */ + /* ftoption.h. By default, this value is set to 32, which means that */ + /* if there are more than 32 spans on a given scanline, the callback */ + /* will be called several times with the same `y' parameter in order */ + /* to draw all callbacks. */ + /* */ + /* Otherwise, the callback is only called once per scan-line, and */ + /* only for those scanlines that do have `gray' pixels on them. */ + /* */ + typedef void + (*FT_SpanFunc)( int y, + int count, + FT_Span* spans, + void* user ); + +#define FT_Raster_Span_Func FT_SpanFunc + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_BitTest_Func */ + /* */ + /* <Description> */ + /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to test whether a given target pixel is already set to the drawing */ + /* `color'. These tests are crucial to implement drop-out control */ + /* per-se the TrueType spec. */ + /* */ + /* <Input> */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* <Return> */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef int + (*FT_Raster_BitTest_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_BitSet_Func */ + /* */ + /* <Description> */ + /* THIS TYPE IS DEPRECATED. DO NOT USE IT. */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to set an individual target pixel. This is crucial to implement */ + /* drop-out control according to the TrueType specification. */ + /* */ + /* <Input> */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* <Return> */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef void + (*FT_Raster_BitSet_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_RASTER_FLAG_XXX */ + /* */ + /* <Description> */ + /* A list of bit flag constants as used in the `flags' field of a */ + /* @FT_Raster_Params structure. */ + /* */ + /* <Values> */ + /* FT_RASTER_FLAG_DEFAULT :: This value is 0. */ + /* */ + /* FT_RASTER_FLAG_AA :: This flag is set to indicate that an */ + /* anti-aliased glyph image should be */ + /* generated. Otherwise, it will be */ + /* monochrome (1-bit). */ + /* */ + /* FT_RASTER_FLAG_DIRECT :: This flag is set to indicate direct */ + /* rendering. In this mode, client */ + /* applications must provide their own span */ + /* callback. This lets them directly */ + /* draw or compose over an existing bitmap. */ + /* If this bit is not set, the target */ + /* pixmap's buffer _must_ be zeroed before */ + /* rendering. */ + /* */ + /* Note that for now, direct rendering is */ + /* only possible with anti-aliased glyphs. */ + /* */ + /* FT_RASTER_FLAG_CLIP :: This flag is only used in direct */ + /* rendering mode. If set, the output will */ + /* be clipped to a box specified in the */ + /* "clip_box" field of the FT_Raster_Params */ + /* structure. */ + /* */ + /* Note that by default, the glyph bitmap */ + /* is clipped to the target pixmap, except */ + /* in direct rendering mode where all spans */ + /* are generated if no clipping box is set. */ + /* */ +#define FT_RASTER_FLAG_DEFAULT 0x0 +#define FT_RASTER_FLAG_AA 0x1 +#define FT_RASTER_FLAG_DIRECT 0x2 +#define FT_RASTER_FLAG_CLIP 0x4 + + /* deprecated */ +#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT +#define ft_raster_flag_aa FT_RASTER_FLAG_AA +#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT +#define ft_raster_flag_clip FT_RASTER_FLAG_CLIP + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Raster_Params */ + /* */ + /* <Description> */ + /* A structure to hold the arguments used by a raster's render */ + /* function. */ + /* */ + /* <Fields> */ + /* target :: The target bitmap. */ + /* */ + /* source :: A pointer to the source glyph image (e.g. an */ + /* FT_Outline). */ + /* */ + /* flags :: The rendering flags. */ + /* */ + /* gray_spans :: The gray span drawing callback. */ + /* */ + /* black_spans :: The black span drawing callback. */ + /* */ + /* bit_test :: The bit test callback. UNIMPLEMENTED! */ + /* */ + /* bit_set :: The bit set callback. UNIMPLEMENTED! */ + /* */ + /* user :: User-supplied data that is passed to each drawing */ + /* callback. */ + /* */ + /* clip_box :: An optional clipping box. It is only used in */ + /* direct rendering mode. Note that coordinates here */ + /* should be expressed in _integer_ pixels (and not in */ + /* 26.6 fixed-point units). */ + /* */ + /* <Note> */ + /* An anti-aliased glyph bitmap is drawn if the FT_RASTER_FLAG_AA bit */ + /* flag is set in the `flags' field, otherwise a monochrome bitmap */ + /* will be generated. */ + /* */ + /* If the FT_RASTER_FLAG_DIRECT bit flag is set in `flags', the */ + /* raster will call the `gray_spans' callback to draw gray pixel */ + /* spans, in the case of an aa glyph bitmap, it will call */ + /* `black_spans', and `bit_test' and `bit_set' in the case of a */ + /* monochrome bitmap. This allows direct composition over a */ + /* pre-existing bitmap through user-provided callbacks to perform the */ + /* span drawing/composition. */ + /* */ + /* Note that the `bit_test' and `bit_set' callbacks are required when */ + /* rendering a monochrome bitmap, as they are crucial to implement */ + /* correct drop-out control as defined in the TrueType specification. */ + /* */ + typedef struct FT_Raster_Params_ + { + FT_Bitmap* target; + void* source; + int flags; + FT_SpanFunc gray_spans; + FT_SpanFunc black_spans; + FT_Raster_BitTest_Func bit_test; /* doesn't work! */ + FT_Raster_BitSet_Func bit_set; /* doesn't work! */ + void* user; + FT_BBox clip_box; + + } FT_Raster_Params; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_NewFunc */ + /* */ + /* <Description> */ + /* A function used to create a new raster object. */ + /* */ + /* <Input> */ + /* memory :: A handle to the memory allocator. */ + /* */ + /* <Output> */ + /* raster :: A handle to the new raster object. */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* The `memory' parameter is a typeless pointer in order to avoid */ + /* un-wanted dependencies on the rest of the FreeType code. In */ + /* practice, it is a FT_Memory, i.e., a handle to the standard */ + /* FreeType memory allocator. However, this field can be completely */ + /* ignored by a given raster implementation. */ + /* */ + typedef int + (*FT_Raster_NewFunc)( void* memory, + FT_Raster* raster ); + +#define FT_Raster_New_Func FT_Raster_NewFunc + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_DoneFunc */ + /* */ + /* <Description> */ + /* A function used to destroy a given raster object. */ + /* */ + /* <Input> */ + /* raster :: A handle to the raster object. */ + /* */ + typedef void + (*FT_Raster_DoneFunc)( FT_Raster raster ); + +#define FT_Raster_Done_Func FT_Raster_DoneFunc + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_ResetFunc */ + /* */ + /* <Description> */ + /* FreeType provides an area of memory called the `render pool', */ + /* available to all registered rasters. This pool can be freely used */ + /* during a given scan-conversion but is shared by all rasters. Its */ + /* content is thus transient. */ + /* */ + /* This function is called each time the render pool changes, or just */ + /* after a new raster object is created. */ + /* */ + /* <Input> */ + /* raster :: A handle to the new raster object. */ + /* */ + /* pool_base :: The address in memory of the render pool. */ + /* */ + /* pool_size :: The size in bytes of the render pool. */ + /* */ + /* <Note> */ + /* Rasters can ignore the render pool and rely on dynamic memory */ + /* allocation if they want to (a handle to the memory allocator is */ + /* passed to the raster constructor). However, this is not */ + /* recommended for efficiency purposes. */ + /* */ + typedef void + (*FT_Raster_ResetFunc)( FT_Raster raster, + unsigned char* pool_base, + unsigned long pool_size ); + +#define FT_Raster_Reset_Func FT_Raster_ResetFunc + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_SetModeFunc */ + /* */ + /* <Description> */ + /* This function is a generic facility to change modes or attributes */ + /* in a given raster. This can be used for debugging purposes, or */ + /* simply to allow implementation-specific `features' in a given */ + /* raster module. */ + /* */ + /* <Input> */ + /* raster :: A handle to the new raster object. */ + /* */ + /* mode :: A 4-byte tag used to name the mode or property. */ + /* */ + /* args :: A pointer to the new mode/property to use. */ + /* */ + typedef int + (*FT_Raster_SetModeFunc)( FT_Raster raster, + unsigned long mode, + void* args ); + +#define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Raster_RenderFunc */ + /* */ + /* <Description> */ + /* Invokes a given raster to scan-convert a given glyph image into a */ + /* target bitmap. */ + /* */ + /* <Input> */ + /* raster :: A handle to the raster object. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to store */ + /* the rendering parameters. */ + /* */ + /* <Return> */ + /* Error code. 0 means success. */ + /* */ + /* <Note> */ + /* The exact format of the source image depends on the raster's glyph */ + /* format defined in its FT_Raster_Funcs structure. It can be an */ + /* FT_Outline or anything else in order to support a large array of */ + /* glyph formats. */ + /* */ + /* Note also that the render function can fail and return a */ + /* FT_Err_Unimplemented_Feature error code if the raster used does */ + /* not support direct composition. */ + /* */ + /* XXX: For now, the standard raster doesn't support direct */ + /* composition but this should change for the final release (see */ + /* the files demos/src/ftgrays.c and demos/src/ftgrays2.c for */ + /* examples of distinct implementations which support direct */ + /* composition). */ + /* */ + typedef int + (*FT_Raster_RenderFunc)( FT_Raster raster, + FT_Raster_Params* params ); + +#define FT_Raster_Render_Func FT_Raster_RenderFunc + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Raster_Funcs */ + /* */ + /* <Description> */ + /* A structure used to describe a given raster class to the library. */ + /* */ + /* <Fields> */ + /* glyph_format :: The supported glyph format for this raster. */ + /* */ + /* raster_new :: The raster constructor. */ + /* */ + /* raster_reset :: Used to reset the render pool within the raster. */ + /* */ + /* raster_render :: A function to render a glyph into a given bitmap. */ + /* */ + /* raster_done :: The raster destructor. */ + /* */ + typedef struct FT_Raster_Funcs_ + { + FT_Glyph_Format glyph_format; + FT_Raster_NewFunc raster_new; + FT_Raster_ResetFunc raster_reset; + FT_Raster_SetModeFunc raster_set_mode; + FT_Raster_RenderFunc raster_render; + FT_Raster_DoneFunc raster_done; + + } FT_Raster_Funcs; + + + /* */ + + +FT_END_HEADER + +#endif /* __FTIMAGE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftincrem.h b/Utilities/vtkfreetype/include/freetype/ftincrem.h new file mode 100644 index 0000000..6a1aa1f --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftincrem.h @@ -0,0 +1,292 @@ +/***************************************************************************/ +/* */ +/* ftincrem.h */ +/* */ +/* FreeType incremental loading (specification). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTINCREM_H__ +#define __FTINCREM_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************** + * + * @type: + * FT_Incremental + * + * @description: + * An opaque type describing a user-provided object used to implement + * "incremental" glyph loading within FreeType. This is used to support + * embedded fonts in certain environments (e.g. Postscript interpreters), + * where the glyph data isn't in the font file, or must be overridden by + * different values. + * + * @note: + * It is up to client applications to create and implement @FT_Incremental + * objects, as long as they provide implementations for the methods + * @FT_Incremental_GetGlyphDataFunc, @FT_Incremental_FreeGlyphDataFunc + * and @FT_Incremental_GetGlyphMetricsFunc. + * + * See the description of @FT_Incremental_InterfaceRec to understand how + * to use incremental objects with FreeType. + */ + typedef struct FT_IncrementalRec_* FT_Incremental; + + + /*************************************************************************** + * + * @struct: + * FT_Incremental_Metrics + * + * @description: + * A small structure used to contain the basic glyph metrics returned + * by the @FT_Incremental_GetGlyphMetricsFunc method. + * + * @fields: + * bearing_x :: + * Left bearing, in font units. + * + * bearing_y :: + * Top bearing, in font units. + * + * advance :: + * Glyph advance, in font units. + * + * @note: + * These correspond to horizontal or vertical metrics depending on the + * value of the 'vertical' argument to the function + * @FT_Incremental_GetGlyphMetricsFunc. + */ + typedef struct FT_Incremental_MetricsRec_ + { + FT_Long bearing_x; + FT_Long bearing_y; + FT_Long advance; + + } FT_Incremental_MetricsRec, *FT_Incremental_Metrics; + + + /*************************************************************************** + * + * @type: + * FT_Incremental_GetGlyphDataFunc + * + * @description: + * A function called by FreeType to access a given glyph's data bytes + * during @FT_Load_Glyph or @FT_Load_Char if incremental loading is + * enabled. + * + * Note that the format of the glyph's data bytes depends on the font + * file format. For TrueType, it must correspond to the raw bytes within + * the 'glyf' table. For Postscript formats, it must correspond to the + * *unencrypted* charstring bytes, without any 'lenIV' header. It is + * undefined for any other format. + * + * @input: + * incremental :: + * Handle to an opaque @FT_Incremental handle provided by the client + * application. + * + * glyph_index :: + * Index of relevant glyph. + * + * @output: + * adata :: + * A structure describing the returned glyph data bytes (which will be + * accessed as a read-only byte block). + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * If this function returns succesfully the method + * @FT_Incremental_FreeGlyphDataFunc will be called later to release + * the data bytes. + * + * Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for + * compound glyphs. + */ + typedef FT_Error + (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental incremental, + FT_UInt glyph_index, + FT_Data* adata ); + + + /*************************************************************************** + * + * @type: + * FT_Incremental_FreeGlyphDataFunc + * + * @description: + * A function used to release the glyph data bytes returned by a + * successful call to @FT_Incremental_GetGlyphDataFunc. + * + * @input: + * incremental :: + * A handle to an opaque @FT_Incremental handle provided by the client + * application. + * + * data :: + * A structure describing the glyph data bytes (which will be accessed + * as a read-only byte block). + */ + typedef void + (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental incremental, + FT_Data* data ); + + + /*************************************************************************** + * + * @type: + * FT_Incremental_GetGlyphMetricsFunc + * + * @description: + * A function used to retrieve the basic metrics of a given glyph index + * before accessing its data. This is necessary because, in certain + * formats like TrueType, the metrics are stored in a different place from + * the glyph images proper. + * + * @input: + * incremental :: + * A handle to an opaque @FT_Incremental handle provided by the client + * application. + * + * glyph_index :: + * Index of relevant glyph. + * + * vertical :: + * If true, return vertical metrics. + * + * ametrics :: + * This parameter is used for both input and output. + * The original glyph metrics, if any, in font units. If metrics are + * not available all the values must be set to zero. + * + * @output: + * ametrics :: + * The replacement glyph metrics in font units. + * + */ + typedef FT_Error + (*FT_Incremental_GetGlyphMetricsFunc) + ( FT_Incremental incremental, + FT_UInt glyph_index, + FT_Bool vertical, + FT_Incremental_MetricsRec *ametrics ); + + + /************************************************************************** + * + * @struct: + * FT_Incremental_FuncsRec + * + * @description: + * A table of functions for accessing fonts that load data + * incrementally. Used in @FT_Incremental_InterfaceRec. + * + * @fields: + * get_glyph_data :: + * The function to get glyph data. Must not be null. + * + * free_glyph_data :: + * The function to release glyph data. Must not be null. + * + * get_glyph_metrics :: + * The function to get glyph metrics. May be null if the font does + * not provide overriding glyph metrics. + */ + typedef struct FT_Incremental_FuncsRec_ + { + FT_Incremental_GetGlyphDataFunc get_glyph_data; + FT_Incremental_FreeGlyphDataFunc free_glyph_data; + FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics; + + } FT_Incremental_FuncsRec; + + + /*************************************************************************** + * + * @struct: + * FT_Incremental_InterfaceRec + * + * @description: + * A structure to be used with @FT_Open_Face to indicate that the user + * wants to support incremental glyph loading. You should use it with + * @FT_PARAM_TAG_INCREMENTAL as in the following example: + * + * { + * FT_Incremental_InterfaceRec inc_int; + * FT_Parameter parameter; + * FT_Open_Args open_args; + * + * + * // set up incremental descriptor + * inc_int.funcs = my_funcs; + * inc_int.object = my_object; + * + * // set up optional parameter + * parameter.tag = FT_PARAM_TAG_INCREMENTAL; + * parameter.data = &inc_int; + * + * // set up FT_Open_Args structure + * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS; + * open_args.pathname = my_font_pathname; + * open_args.num_params = 1; + * open_args.params = ¶meter; // we use one optional argument + * + * // open the font + * error = FT_Open_Face( library, &open_args, index, &face ); + * ... + * } + */ + typedef struct FT_Incremental_InterfaceRec_ + { + const FT_Incremental_FuncsRec* funcs; + FT_Incremental object; + + } FT_Incremental_InterfaceRec; + + + /*************************************************************************** + * + * @constant: + * FT_PARAM_TAG_INCREMENTAL + * + * @description: + * A constant used as the tag of @FT_Parameter structures to indicate + * an incremental loading object to be used by FreeType. + * + */ +#define FT_PARAM_TAG_INCREMENTAL FT_MAKE_TAG( 'i', 'n', 'c', 'r' ) + + /* */ + +FT_END_HEADER + +#endif /* __FTINCREM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftlist.h b/Utilities/vtkfreetype/include/freetype/ftlist.h new file mode 100644 index 0000000..ae9801b --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftlist.h @@ -0,0 +1,274 @@ +/***************************************************************************/ +/* */ +/* ftlist.h */ +/* */ +/* Generic list support for FreeType (specification). */ +/* */ +/* Copyright 1996-2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file implements functions relative to list processing. Its */ + /* data structures are defined in `freetype.h'. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTLIST_H__ +#define __FTLIST_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* list_processing */ + /* */ + /* <Title> */ + /* List Processing */ + /* */ + /* <Abstract> */ + /* Simple management of lists. */ + /* */ + /* <Description> */ + /* This section contains various definitions related to list */ + /* processing using doubly-linked nodes. */ + /* */ + /* <Order> */ + /* FT_List */ + /* FT_ListNode */ + /* FT_ListRec */ + /* FT_ListNodeRec */ + /* */ + /* FT_List_Add */ + /* FT_List_Insert */ + /* FT_List_Find */ + /* FT_List_Remove */ + /* FT_List_Up */ + /* FT_List_Iterate */ + /* FT_List_Iterator */ + /* FT_List_Finalize */ + /* FT_List_Destructor */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Find */ + /* */ + /* <Description> */ + /* Finds the list node for a given listed object. */ + /* */ + /* <Input> */ + /* list :: A pointer to the parent list. */ + /* data :: The address of the listed object. */ + /* */ + /* <Return> */ + /* List node. NULL if it wasn't found. */ + /* */ + FT_EXPORT( FT_ListNode ) + FT_List_Find( FT_List list, + void* data ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Add */ + /* */ + /* <Description> */ + /* Appends an element to the end of a list. */ + /* */ + /* <InOut> */ + /* list :: A pointer to the parent list. */ + /* node :: The node to append. */ + /* */ + FT_EXPORT( void ) + FT_List_Add( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Insert */ + /* */ + /* <Description> */ + /* Inserts an element at the head of a list. */ + /* */ + /* <InOut> */ + /* list :: A pointer to parent list. */ + /* node :: The node to insert. */ + /* */ + FT_EXPORT( void ) + FT_List_Insert( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Remove */ + /* */ + /* <Description> */ + /* Removes a node from a list. This function doesn't check whether */ + /* the node is in the list! */ + /* */ + /* <Input> */ + /* node :: The node to remove. */ + /* */ + /* <InOut> */ + /* list :: A pointer to the parent list. */ + /* */ + FT_EXPORT( void ) + FT_List_Remove( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Up */ + /* */ + /* <Description> */ + /* Moves a node to the head/top of a list. Used to maintain LRU */ + /* lists. */ + /* */ + /* <InOut> */ + /* list :: A pointer to the parent list. */ + /* node :: The node to move. */ + /* */ + FT_EXPORT( void ) + FT_List_Up( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_List_Iterator */ + /* */ + /* <Description> */ + /* An FT_List iterator function which is called during a list parse */ + /* by FT_List_Iterate(). */ + /* */ + /* <Input> */ + /* node :: The current iteration list node. */ + /* */ + /* user :: A typeless pointer passed to FT_List_Iterate(). */ + /* Can be used to point to the iteration's state. */ + /* */ + typedef FT_Error + (*FT_List_Iterator)( FT_ListNode node, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Iterate */ + /* */ + /* <Description> */ + /* Parses a list and calls a given iterator function on each element. */ + /* Note that parsing is stopped as soon as one of the iterator calls */ + /* returns a non-zero value. */ + /* */ + /* <Input> */ + /* list :: A handle to the list. */ + /* iterator :: An interator function, called on each node of the */ + /* list. */ + /* user :: A user-supplied field which is passed as the second */ + /* argument to the iterator. */ + /* */ + /* <Return> */ + /* The result (a FreeType error code) of the last iterator call. */ + /* */ + FT_EXPORT( FT_Error ) + FT_List_Iterate( FT_List list, + FT_List_Iterator iterator, + void* user ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_List_Destructor */ + /* */ + /* <Description> */ + /* An FT_List iterator function which is called during a list */ + /* finalization by FT_List_Finalize() to destroy all elements in a */ + /* given list. */ + /* */ + /* <Input> */ + /* system :: The current system object. */ + /* */ + /* data :: The current object to destroy. */ + /* */ + /* user :: A typeless pointer passed to FT_List_Iterate(). It can */ + /* be used to point to the iteration's state. */ + /* */ + typedef void + (*FT_List_Destructor)( FT_Memory memory, + void* data, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_List_Finalize */ + /* */ + /* <Description> */ + /* Destroys all elements in the list as well as the list itself. */ + /* */ + /* <Input> */ + /* list :: A handle to the list. */ + /* */ + /* destroy :: A list destructor that will be applied to each element */ + /* of the list. */ + /* */ + /* memory :: The current memory object which handles deallocation. */ + /* */ + /* user :: A user-supplied field which is passed as the last */ + /* argument to the destructor. */ + /* */ + FT_EXPORT( void ) + FT_List_Finalize( FT_List list, + FT_List_Destructor destroy, + FT_Memory memory, + void* user ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTLIST_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftlzw.h b/Utilities/vtkfreetype/include/freetype/ftlzw.h new file mode 100644 index 0000000..a0a042e --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftlzw.h @@ -0,0 +1,99 @@ +/***************************************************************************/ +/* */ +/* ftlzw.h */ +/* */ +/* LZW-compressed stream support. */ +/* */ +/* Copyright 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTLZW_H__ +#define __FTLZW_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* <Section> */ + /* lzw */ + /* */ + /* <Title> */ + /* LZW Streams */ + /* */ + /* <Abstract> */ + /* Using LZW-compressed font files */ + /* */ + /* <Description> */ + /* This section contains the declaration of LZW-specific functions. */ + /* */ + /*************************************************************************/ + + /************************************************************************ + * + * @function: + * FT_Stream_OpenLZW + * + * @description: + * Open a new stream to parse LZW-compressed font files. This is + * mainly used to support the compressed *.pcf.Z fonts that come + * with XFree86. + * + * @input: + * stream :: The target embedding stream. + * + * source :: The source stream. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * The source stream must be opened _before_ calling this function. + * + * Calling the internal function FT_Stream_Close on the new stream will + * *not* call FT_Stream_Close on the source stream. None of the stream + * objects will be released to the heap. + * + * The stream implementation is very basic and resets the decompression + * process each time seeking backwards is needed within the stream + * + * In certain builds of the library, LZW compression recognition is + * automatically handled when calling @FT_New_Face or @FT_Open_Face. + * This means that if no font driver is capable of handling the raw + * compressed file, the library will try to open a LZW stream from it + * and re-open the face with it. + * + * This function may return "FT_Err_Unimplemented" if your build of + * FreeType was not compiled with LZW support. + */ + FT_EXPORT( FT_Error ) + FT_Stream_OpenLZW( FT_Stream stream, + FT_Stream source ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTLZW_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftmac.h b/Utilities/vtkfreetype/include/freetype/ftmac.h new file mode 100644 index 0000000..78ed779 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftmac.h @@ -0,0 +1,162 @@ +/***************************************************************************/ +/* */ +/* ftmac.h */ +/* */ +/* Additional Mac-specific API. */ +/* */ +/* Copyright 1996-2001, 2004 by */ +/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* NOTE: Include this file after <freetype/freetype.h> and after the */ +/* Mac-specific <Types.h> header (or any other Mac header that */ +/* includes <Types.h>); we use Handle type. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTMAC_H__ +#define __FTMAC_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* mac_specific */ + /* */ + /* <Title> */ + /* Mac-Specific Interface */ + /* */ + /* <Abstract> */ + /* Only available on the Macintosh. */ + /* */ + /* <Description> */ + /* The following definitions are only available if FreeType is */ + /* compiled on a Macintosh. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face_From_FOND */ + /* */ + /* <Description> */ + /* Creates a new face object from an FOND resource. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* fond :: An FOND resource. */ + /* */ + /* face_index :: Only supported for the -1 `sanity check' special */ + /* case. */ + /* */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Notes> */ + /* This function can be used to create FT_Face abjects from fonts */ + /* that are installed in the system like so: */ + /* */ + /* { */ + /* fond = GetResource( 'FOND', fontName ); */ + /* error = FT_New_Face_From_FOND( library, fond, 0, &face ); */ + /* } */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Face_From_FOND( FT_Library library, + Handle fond, + FT_Long face_index, + FT_Face *aface ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_GetFile_From_Mac_Name */ + /* */ + /* <Description> */ + /* Returns an FSSpec for the disk file containing the named font. */ + /* */ + /* <Input> */ + /* fontName :: Mac OS name of the font (eg. Times New Roman Bold). */ + /* */ + /* <Output> */ + /* pathSpec :: FSSpec to the file. For passing to @FT_New_Face. */ + /* */ + /* face_index :: Index of the face. For passing to @FT_New_Face. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_GetFile_From_Mac_Name( const char* fontName, + FSSpec* pathSpec, + FT_Long* face_index ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face_From_FSSpec */ + /* */ + /* <Description> */ + /* Creates a new face object from a given resource and typeface index */ + /* using an FSSpec to the font file. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library resource. */ + /* */ + /* <Input> */ + /* spec :: FSSpec to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* <Output> */ + /* aface :: A handle to a new face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* @FT_New_Face_From_FSSpec is identical to @FT_New_Face except */ + /* it accepts an FSSpec instead of a path. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Face_From_FSSpec( FT_Library library, + const FSSpec *spec, + FT_Long face_index, + FT_Face *aface ); + + /* */ + + +FT_END_HEADER + + +#endif /* __FTMAC_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftmm.h b/Utilities/vtkfreetype/include/freetype/ftmm.h new file mode 100644 index 0000000..525b5c0 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftmm.h @@ -0,0 +1,378 @@ +/***************************************************************************/ +/* */ +/* ftmm.h */ +/* */ +/* FreeType Multiple Master font interface (specification). */ +/* */ +/* Copyright 1996-2001, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTMM_H__ +#define __FTMM_H__ + + +#include <ft2build.h> +#include FT_TYPE1_TABLES_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* multiple_masters */ + /* */ + /* <Title> */ + /* Multiple Masters */ + /* */ + /* <Abstract> */ + /* How to manage Multiple Masters fonts. */ + /* */ + /* <Description> */ + /* The following types and functions are used to manage Multiple */ + /* Master fonts, i.e. the selection of specific design instances by */ + /* setting design axis coordinates. */ + /* */ + /* George Williams has extended this interface to make it work with */ + /* both Type 1 Multiple Masters fonts, and GX distortable (var) */ + /* fonts. Some of these routines only work with MM fonts, others */ + /* will work with both types. They are similar enough that a */ + /* consistent interface makes sense. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_MM_Axis */ + /* */ + /* <Description> */ + /* A simple structure used to model a given axis in design space for */ + /* Multiple Masters fonts. */ + /* */ + /* This structure can't be used for GX var fonts. */ + /* */ + /* <Fields> */ + /* name :: The axis's name. */ + /* */ + /* minimum :: The axis's minimum design coordinate. */ + /* */ + /* maximum :: The axis's maximum design coordinate. */ + /* */ + typedef struct FT_MM_Axis_ + { + FT_String* name; + FT_Long minimum; + FT_Long maximum; + + } FT_MM_Axis; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Multi_Master */ + /* */ + /* <Description> */ + /* A structure used to model the axes and space of a Multiple Masters */ + /* font. */ + /* */ + /* This structure can't be used for GX var fonts. */ + /* */ + /* <Fields> */ + /* num_axis :: Number of axes. Cannot exceed 4. */ + /* */ + /* num_designs :: Number of designs; should ne normally 2^num_axis */ + /* even though the Type 1 specification strangely */ + /* allows for intermediate designs to be present. This */ + /* number cannot exceed 16. */ + /* */ + /* axis :: A table of axis descriptors. */ + /* */ + typedef struct FT_Multi_Master_ + { + FT_UInt num_axis; + FT_UInt num_designs; + FT_MM_Axis axis[T1_MAX_MM_AXIS]; + + } FT_Multi_Master; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Var_Axis */ + /* */ + /* <Description> */ + /* A simple structure used to model a given axis in design space for */ + /* Multiple Masters and GX var fonts. */ + /* */ + /* <Fields> */ + /* name :: The axis's name. */ + /* Not always meaningful for GX. */ + /* */ + /* minimum :: The axis's minimum design coordinate. */ + /* */ + /* def :: The axis's default design coordinate. */ + /* FreeType computes meaningful default values for MM; it */ + /* is then an integer value, not in 16.16 format. */ + /* */ + /* maximum :: The axis's maximum design coordinate. */ + /* */ + /* tag :: The axis's tag (the GX equivalent to `name'). */ + /* FreeType provides default values for MM if possible. */ + /* */ + /* strid :: The entry in `name' table (another GX version of */ + /* `name'). */ + /* Not meaningful for MM. */ + /* */ + typedef struct FT_Var_Axis_ + { + FT_String* name; + + FT_Fixed minimum; + FT_Fixed def; + FT_Fixed maximum; + + FT_ULong tag; + FT_UInt strid; + + } FT_Var_Axis; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Var_Named_Style */ + /* */ + /* <Description> */ + /* A simple structure used to model a named style in a GX var font. */ + /* */ + /* This structure can't be used for MM fonts. */ + /* */ + /* <Fields> */ + /* coords :: The design coordinates for this style. */ + /* This is an array with one entry for each axis. */ + /* */ + /* strid :: The entry in `name' table identifying this style. */ + /* */ + typedef struct FT_Var_Named_Style_ + { + FT_Fixed* coords; + FT_UInt strid; + + } FT_Var_Named_Style; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_MM_Var */ + /* */ + /* <Description> */ + /* A structure used to model the axes and space of a Multiple Masters */ + /* or GX var distortable font. */ + /* */ + /* Some fields are specific to one format and not to the other. */ + /* */ + /* <Fields> */ + /* num_axis :: The number of axes. The maximum value is 4 for */ + /* MM; no limit in GX. */ + /* */ + /* num_designs :: The number of designs; should be normally */ + /* 2^num_axis for MM fonts. Not meaningful for GX */ + /* (where every glyph could have a different */ + /* number of designs). */ + /* */ + /* num_namedstyles :: The number of named styles; only meaningful for */ + /* GX which allows certain design coordinates to */ + /* have a string ID (in the `name' table) */ + /* associated with them. The font can tell the */ + /* user that, for example, Weight=1.5 is `Bold'. */ + /* */ + /* axis :: A table of axis descriptors. */ + /* GX fonts contain slightly more data than MM. */ + /* */ + /* namedstyles :: A table of named styles. */ + /* Only meaningful with GX. */ + /* */ + typedef struct FT_MM_Var_ + { + FT_UInt num_axis; + FT_UInt num_designs; + FT_UInt num_namedstyles; + FT_Var_Axis* axis; + FT_Var_Named_Style* namedstyle; + + } FT_MM_Var; + + + /* */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Multi_Master */ + /* */ + /* <Description> */ + /* Retrieves the Multiple Master descriptor of a given font. */ + /* */ + /* This function can't be used with GX fonts. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* <Output> */ + /* amaster :: The Multiple Masters descriptor. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master *amaster ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_MM_Var */ + /* */ + /* <Description> */ + /* Retrieves the Multiple Master/GX var descriptor of a given font. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* <Output> */ + /* amaster :: The Multiple Masters descriptor. */ + /* Allocates a data structure, which the user must free */ + /* (a single call to FT_FREE will do it). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_MM_Var( FT_Face face, + FT_MM_Var* *amaster ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* <Description> */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* This function can't be used with GX fonts. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face. */ + /* */ + /* <Input> */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: An array of design coordinates. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_MM_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Var_Design_Coordinates */ + /* */ + /* <Description> */ + /* For Multiple Master or GX Var fonts, choose an interpolated font */ + /* design through design coordinates. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face. */ + /* */ + /* <Input> */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: An array of design coordinates. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Var_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* <Description> */ + /* For Multiple Masters and GX var fonts, choose an interpolated font */ + /* design through normalized blend coordinates. */ + /* */ + /* <InOut> */ + /* face :: A handle to the source face. */ + /* */ + /* <Input> */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates array (each element must be */ + /* between 0 and 1.0). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_MM_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Var_Blend_Coordinates */ + /* */ + /* <Description> */ + /* This is another name of @FT_Set_MM_Blend_Coordinates. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Var_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTMM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftmodapi.h b/Utilities/vtkfreetype/include/freetype/ftmodapi.h new file mode 100644 index 0000000..1929ca0 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftmodapi.h @@ -0,0 +1,319 @@ +/***************************************************************************/ +/* */ +/* ftmodapi.h */ +/* */ +/* FreeType modules public interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTMODAPI_H__ +#define __FTMODAPI_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* module_management */ + /* */ + /* <Title> */ + /* Module Management */ + /* */ + /* <Abstract> */ + /* How to add, upgrade, and remove modules from FreeType. */ + /* */ + /* <Description> */ + /* The definitions below are used to manage modules within FreeType. */ + /* Modules can be added, upgraded, and removed at runtime. */ + /* */ + /*************************************************************************/ + + + /* module bit flags */ +#define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */ +#define FT_MODULE_RENDERER 2 /* this module is a renderer */ +#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */ +#define FT_MODULE_STYLER 8 /* this module is a styler */ + +#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */ + /* scalable fonts */ +#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */ + /* support vector outlines */ +#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */ + /* own hinter */ + + + /* deprecated values */ +#define ft_module_font_driver FT_MODULE_FONT_DRIVER +#define ft_module_renderer FT_MODULE_RENDERER +#define ft_module_hinter FT_MODULE_HINTER +#define ft_module_styler FT_MODULE_STYLER + +#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE +#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES +#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER + + + typedef FT_Pointer FT_Module_Interface; + + typedef FT_Error + (*FT_Module_Constructor)( FT_Module module ); + + typedef void + (*FT_Module_Destructor)( FT_Module module ); + + typedef FT_Module_Interface + (*FT_Module_Requester)( FT_Module module, + const char* name ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Module_Class */ + /* */ + /* <Description> */ + /* The module class descriptor. */ + /* */ + /* <Fields> */ + /* module_flags :: Bit flags describing the module. */ + /* */ + /* module_size :: The size of one module object/instance in */ + /* bytes. */ + /* */ + /* module_name :: The name of the module. */ + /* */ + /* module_version :: The version, as a 16.16 fixed number */ + /* (major.minor). */ + /* */ + /* module_requires :: The version of FreeType this module requires */ + /* (starts at version 2.0, i.e 0x20000) */ + /* */ + /* module_init :: A function used to initialize (not create) a */ + /* new module object. */ + /* */ + /* module_done :: A function used to finalize (not destroy) a */ + /* given module object */ + /* */ + /* get_interface :: Queries a given module for a specific */ + /* interface by name. */ + /* */ + typedef struct FT_Module_Class_ + { + FT_ULong module_flags; + FT_Long module_size; + const FT_String* module_name; + FT_Fixed module_version; + FT_Fixed module_requires; + + const void* module_interface; + + FT_Module_Constructor module_init; + FT_Module_Destructor module_done; + FT_Module_Requester get_interface; + + } FT_Module_Class; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Add_Module */ + /* */ + /* <Description> */ + /* Adds a new module to a given library instance. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library object. */ + /* */ + /* <Input> */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Add_Module( FT_Library library, + const FT_Module_Class* clazz ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Module */ + /* */ + /* <Description> */ + /* Finds a module by its name. */ + /* */ + /* <Input> */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* <Return> */ + /* A module handle. 0 if none was found. */ + /* */ + /* <Note> */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for :-) */ + /* */ + FT_EXPORT( FT_Module ) + FT_Get_Module( FT_Library library, + const char* module_name ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Remove_Module */ + /* */ + /* <Description> */ + /* Removes a given module from a library instance. */ + /* */ + /* <InOut> */ + /* library :: A handle to a library object. */ + /* */ + /* <Input> */ + /* module :: A handle to a module object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Remove_Module( FT_Library library, + FT_Module module ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Library */ + /* */ + /* <Description> */ + /* This function is used to create a new FreeType library instance */ + /* from a given memory object. It is thus possible to use libraries */ + /* with distinct memory allocators within the same program. */ + /* */ + /* <Input> */ + /* memory :: A handle to the original memory object. */ + /* */ + /* <Output> */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Library( FT_Memory memory, + FT_Library *alibrary ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Library */ + /* */ + /* <Description> */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* <Input> */ + /* library :: A handle to the target library. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_Library( FT_Library library ); + + + + typedef void + (*FT_DebugHook_Func)( void* arg ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Debug_Hook */ + /* */ + /* <Description> */ + /* Sets a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library object. */ + /* */ + /* <Input> */ + /* hook_index :: The index of the debug hook. You should use the */ + /* values defined in ftobjs.h, e.g. */ + /* FT_DEBUG_HOOK_TRUETYPE. */ + /* */ + /* debug_hook :: The function used to debug the interpreter. */ + /* */ + /* <Note> */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type 1 interpreter) are defined. */ + /* */ + FT_EXPORT( void ) + FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ); + + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Add_Default_Modules */ + /* */ + /* <Description> */ + /* Adds the set of default drivers to a given library object. */ + /* This is only useful when you create a library object with */ + /* FT_New_Library() (usually to plug a custom memory manager). */ + /* */ + /* <InOut> */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT( void ) + FT_Add_Default_Modules( FT_Library library ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTMODAPI_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftmoderr.h b/Utilities/vtkfreetype/include/freetype/ftmoderr.h new file mode 100644 index 0000000..d190167 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftmoderr.h @@ -0,0 +1,154 @@ +/***************************************************************************/ +/* */ +/* ftmoderr.h */ +/* */ +/* FreeType module error offsets (specification). */ +/* */ +/* Copyright 2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the FreeType module error offsets. */ + /* */ + /* The lower byte gives the error code, the higher byte gives the */ + /* module. The base module has error offset 0. For example, the error */ + /* `FT_Err_Invalid_File_Format' has value 0x003, the error */ + /* `TT_Err_Invalid_File_Format' has value 0x1003, the error */ + /* `T1_Err_Invalid_File_Format' has value 0x1103, etc. */ + /* */ + /* Undefine the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in ftoption.h */ + /* to make the higher byte always zero (disabling the module error */ + /* mechanism). */ + /* */ + /* It can also be used to create a module error message table easily */ + /* with something like */ + /* */ + /* { */ + /* #undef __FTMODERR_H__ */ + /* #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s }, */ + /* #define FT_MODERR_START_LIST { */ + /* #define FT_MODERR_END_LIST { 0, 0 } }; */ + /* */ + /* const struct */ + /* { */ + /* int mod_err_offset; */ + /* const char* mod_err_msg */ + /* } ft_mod_errors[] = */ + /* */ + /* #include FT_MODULE_ERRORS_H */ + /* } */ + /* */ + /* To use such a table, all errors must be ANDed with 0xFF00 to remove */ + /* the error code. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTMODERR_H__ +#define __FTMODERR_H__ + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** SETUP MACROS *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#undef FT_NEED_EXTERN_C + +#ifndef FT_MODERRDEF + +#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS +#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = v, +#else +#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = 0, +#endif + +#define FT_MODERR_START_LIST enum { +#define FT_MODERR_END_LIST FT_Mod_Err_Max }; + +#ifdef __cplusplus +#define FT_NEED_EXTERN_C + extern "C" { +#endif + +#endif /* !FT_MODERRDEF */ + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** LIST MODULE ERROR BASES *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#ifdef FT_MODERR_START_LIST + FT_MODERR_START_LIST +#endif + + + FT_MODERRDEF( Base, 0x000, "base module" ) + FT_MODERRDEF( Autohint, 0x100, "autohinter module" ) + FT_MODERRDEF( BDF, 0x200, "BDF module" ) + FT_MODERRDEF( Cache, 0x300, "cache module" ) + FT_MODERRDEF( CFF, 0x400, "CFF module" ) + FT_MODERRDEF( CID, 0x500, "CID module" ) + FT_MODERRDEF( Gzip, 0x600, "Gzip module" ) + FT_MODERRDEF( LZW, 0x700, "LZW module" ) + FT_MODERRDEF( PCF, 0x800, "PCF module" ) + FT_MODERRDEF( PFR, 0x900, "PFR module" ) + FT_MODERRDEF( PSaux, 0xA00, "PS auxiliary module" ) + FT_MODERRDEF( PShinter, 0xB00, "PS hinter module" ) + FT_MODERRDEF( PSnames, 0xC00, "PS names module" ) + FT_MODERRDEF( Raster, 0xD00, "raster module" ) + FT_MODERRDEF( SFNT, 0xE00, "SFNT module" ) + FT_MODERRDEF( Smooth, 0xF00, "smooth raster module" ) + FT_MODERRDEF( TrueType, 0x1000, "TrueType module" ) + FT_MODERRDEF( Type1, 0x1100, "Type 1 module" ) + FT_MODERRDEF( Type42, 0x1200, "Type 42 module" ) + FT_MODERRDEF( Winfonts, 0x1300, "Windows FON/FNT module" ) + + +#ifdef FT_MODERR_END_LIST + FT_MODERR_END_LIST +#endif + + + /*******************************************************************/ + /*******************************************************************/ + /***** *****/ + /***** CLEANUP *****/ + /***** *****/ + /*******************************************************************/ + /*******************************************************************/ + + +#ifdef FT_NEED_EXTERN_C + } +#endif + +#undef FT_MODERR_START_LIST +#undef FT_MODERR_END_LIST +#undef FT_MODERRDEF +#undef FT_NEED_EXTERN_C + + +#endif /* __FTMODERR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftoutln.h b/Utilities/vtkfreetype/include/freetype/ftoutln.h new file mode 100644 index 0000000..79ed35b --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftoutln.h @@ -0,0 +1,472 @@ +/***************************************************************************/ +/* */ +/* ftoutln.h */ +/* */ +/* Support for the FT_Outline type used to store glyph shapes of */ +/* most scalable font formats (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTOUTLN_H__ +#define __FTOUTLN_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* outline_processing */ + /* */ + /* <Title> */ + /* Outline Processing */ + /* */ + /* <Abstract> */ + /* Functions to create, transform, and render vectorial glyph images. */ + /* */ + /* <Description> */ + /* This section contains routines used to create and destroy scalable */ + /* glyph images known as `outlines'. These can also be measured, */ + /* transformed, and converted into bitmaps and pixmaps. */ + /* */ + /* <Order> */ + /* FT_Outline */ + /* FT_OUTLINE_FLAGS */ + /* FT_Outline_New */ + /* FT_Outline_Done */ + /* FT_Outline_Copy */ + /* FT_Outline_Translate */ + /* FT_Outline_Transform */ + /* FT_Outline_Reverse */ + /* FT_Outline_Check */ + /* */ + /* FT_Outline_Get_CBox */ + /* FT_Outline_Get_BBox */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* FT_Outline_Render */ + /* */ + /* FT_Outline_Decompose */ + /* FT_Outline_Funcs */ + /* FT_Outline_MoveTo_Func */ + /* FT_Outline_LineTo_Func */ + /* FT_Outline_ConicTo_Func */ + /* FT_Outline_CubicTo_Func */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Decompose */ + /* */ + /* <Description> */ + /* Walks over an outline's structure to decompose it into individual */ + /* segments and Bezier arcs. This function is also able to emit */ + /* `move to' and `close to' operations to indicate the start and end */ + /* of new contours in the outline. */ + /* */ + /* <Input> */ + /* outline :: A pointer to the source target. */ + /* */ + /* func_interface :: A table of `emitters', i.e,. function pointers */ + /* called during decomposition to indicate path */ + /* operations. */ + /* */ + /* <InOut> */ + /* user :: A typeless pointer which is passed to each */ + /* emitter during the decomposition. It can be */ + /* used to store the state during the */ + /* decomposition. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means sucess. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Decompose( FT_Outline* outline, + const FT_Outline_Funcs* func_interface, + void* user ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_New */ + /* */ + /* <Description> */ + /* Creates a new outline of a given size. */ + /* */ + /* <Input> */ + /* library :: A handle to the library object from where the */ + /* outline is allocated. Note however that the new */ + /* outline will NOT necessarily be FREED, when */ + /* destroying the library, by FT_Done_FreeType(). */ + /* */ + /* numPoints :: The maximal number of points within the outline. */ + /* */ + /* numContours :: The maximal number of contours within the outline. */ + /* */ + /* <Output> */ + /* anoutline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline *anoutline ); + + + FT_EXPORT( FT_Error ) + FT_Outline_New_Internal( FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline *anoutline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Done */ + /* */ + /* <Description> */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* <Input> */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `library' parameter is */ + /* simply to use FT_Free(). */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Done( FT_Library library, + FT_Outline* outline ); + + + FT_EXPORT( FT_Error ) + FT_Outline_Done_Internal( FT_Memory memory, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Check */ + /* */ + /* <Description> */ + /* Check the contents of an outline descriptor. */ + /* */ + /* <Input> */ + /* outline :: A handle to a source outline. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Check( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Get_CBox */ + /* */ + /* <Description> */ + /* Returns an outline's `control box'. The control box encloses all */ + /* the outline's points, including Bezier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bezier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* <Input> */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* <Output> */ + /* acbox :: The outline's control box. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox *acbox ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Translate */ + /* */ + /* <Description> */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* <InOut> */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* <Input> */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Translate( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Copy */ + /* */ + /* <Description> */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* <Input> */ + /* source :: A handle to the source outline. */ + /* */ + /* <Output> */ + /* target :: A handle to the target outline. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Copy( FT_Outline* source, + FT_Outline *target ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Transform */ + /* */ + /* <Description> */ + /* Applies a simple 2x2 matrix to all of an outline's points. Useful */ + /* for applying rotations, slanting, flipping, etc. */ + /* */ + /* <InOut> */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* <Input> */ + /* matrix :: A pointer to the transformation matrix. */ + /* */ + /* <Note> */ + /* You can use FT_Outline_Translate() if you need to translate the */ + /* outline's points. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Transform( FT_Outline* outline, + FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Reverse */ + /* */ + /* <Description> */ + /* Reverses the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* <InOut> */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* <Note> */ + /* This functions toggles the bit flag `FT_OUTLINE_REVERSE_FILL' in */ + /* the outline's `flags' field. */ + /* */ + /* It shouldn't be used by a normal client application, unless it */ + /* knows what it is doing. */ + /* */ + FT_EXPORT( void ) + FT_Outline_Reverse( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* <Description> */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* <Input> */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* <Output> */ + /* abitmap :: A pointer to the target bitmap descriptor. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function does NOT CREATE the bitmap, it only renders an */ + /* outline image within the one you pass to it! */ + /* */ + /* It will use the raster correponding to the default glyph format. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap *abitmap ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Render */ + /* */ + /* <Description> */ + /* Renders an outline within a bitmap using the current scan-convert. */ + /* This functions uses an FT_Raster_Params structure as an argument, */ + /* allowing advanced features like direct composition, translucency, */ + /* etc. */ + /* */ + /* <Input> */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* <InOut> */ + /* params :: A pointer to a FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* You should know what you are doing and how FT_Raster_Params works */ + /* to use this function. */ + /* */ + /* The field `params.source' will be set to `outline' before the scan */ + /* converter is called, which means that the value you give to it is */ + /* actually ignored. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ); + + + /************************************************************************** + * + * @enum: + * FT_Orientation + * + * @description: + * A list of values used to describe an outline's contour orientation. + * + * The TrueType and Postscript specifications use different conventions + * to determine whether outline contours should be filled or unfilled. + * + * @values: + * FT_ORIENTATION_TRUETYPE :: + * According to the TrueType specification, clockwise contours must + * be filled, and counter-clockwise ones must be unfilled. + * + * FT_ORIENTATION_POSTSCRIPT :: + * According to the Postscript specification, counter-clockwise contours + * must be filled, and clockwise ones must be unfilled. + * + * FT_ORIENTATION_FILL_RIGHT :: + * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to + * remember that in TrueType, everything that is to the right of + * the drawing direction of a contour must be filled. + * + * FT_ORIENTATION_FILL_LEFT :: + * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to + * remember that in Postscript, everything that is to the left of + * the drawing direction of a contour must be filled. + */ + typedef enum + { + FT_ORIENTATION_TRUETYPE = 0, + FT_ORIENTATION_POSTSCRIPT = 1, + FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE, + FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT + + } FT_Orientation; + + + /************************************************************************** + * + * @function: + * FT_Outline_Get_Orientation + * + * @description: + * This function analyzes a glyph outline and tries to compute its + * fill orientation (see @FT_Orientation). This is done by computing + * the direction of each global horizontal and/or vertical extrema + * within the outline. + * + * Note that this will return @FT_ORIENTATION_TRUETYPE for empty + * outlines. + * + * @input: + * outline :: + * A handle to the source outline. + * + * @return: + * The orientation. + * + */ + FT_EXPORT( FT_Orientation ) + FT_Outline_Get_Orientation( FT_Outline* outline ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTOUTLN_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftpfr.h b/Utilities/vtkfreetype/include/freetype/ftpfr.h new file mode 100644 index 0000000..c9a5675 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftpfr.h @@ -0,0 +1,172 @@ +/***************************************************************************/ +/* */ +/* ftpfr.h */ +/* */ +/* FreeType API for accessing PFR-specific data (specification only). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTPFR_H__ +#define __FTPFR_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* pfr_fonts */ + /* */ + /* <Title> */ + /* PFR Fonts */ + /* */ + /* <Abstract> */ + /* PFR/TrueDoc specific APIs */ + /* */ + /* <Description> */ + /* This section contains the declaration of PFR-specific functions. */ + /* */ + /*************************************************************************/ + + + /********************************************************************** + * + * @function: + * FT_Get_PFR_Metrics + * + * @description: + * Return the outline and metrics resolutions of a given PFR face. + * + * @input: + * face :: Handle to the input face. It can be a non-PFR face. + * + * @output: + * aoutline_resolution :: + * Outline resolution. This is equivalent to `face->units_per_EM'. + * Optional (parameter can be NULL). + * + * ametrics_resolution :: + * Metrics resolution. This is equivalent to `outline_resolution' + * for non-PFR fonts. Optional (parameter can be NULL). + * + * ametrics_x_scale :: + * A 16.16 fixed-point number used to scale distance expressed + * in metrics units to device sub-pixels. This is equivalent to + * `face->size->x_scale', but for metrics only. Optional (parameter + * can be NULL) + * + * ametrics_y_scale :: + * Same as `ametrics_x_scale' but for the vertical direction. + * optional (parameter can be NULL) + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * If the input face is not a PFR, this function will return an error. + * However, in all cases, it will return valid values. + */ + FT_EXPORT( FT_Error ) + FT_Get_PFR_Metrics( FT_Face face, + FT_UInt *aoutline_resolution, + FT_UInt *ametrics_resolution, + FT_Fixed *ametrics_x_scale, + FT_Fixed *ametrics_y_scale ); + + + /********************************************************************** + * + * @function: + * FT_Get_PFR_Kerning + * + * @description: + * Return the kerning pair corresponding to two glyphs in a PFR face. + * The distance is expressed in metrics units, unlike the result of + * @FT_Get_Kerning. + * + * @input: + * face :: A handle to the input face. + * + * left :: Index of the left glyph. + * + * right :: Index of the right glyph. + * + * @output: + * avector :: A kerning vector. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * This function always return distances in original PFR metrics + * units. This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED + * mode, which always returns distances converted to outline units. + * + * You can use the value of the `x_scale' and `y_scale' parameters + * returned by @FT_Get_PFR_Metrics to scale these to device sub-pixels. + */ + FT_EXPORT( FT_Error ) + FT_Get_PFR_Kerning( FT_Face face, + FT_UInt left, + FT_UInt right, + FT_Vector *avector ); + + + /********************************************************************** + * + * @function: + * FT_Get_PFR_Advance + * + * @description: + * Return a given glyph advance, expressed in original metrics units, + * from a PFR font. + * + * @input: + * face :: A handle to the input face. + * + * gindex :: The glyph index. + * + * @output: + * aadvance :: The glyph advance in metrics units. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * You can use the `x_scale' or `y_scale' results of @FT_Get_PFR_Metrics + * to convert the advance to device sub-pixels (i.e. 1/64th of pixels). + */ + FT_EXPORT( FT_Error ) + FT_Get_PFR_Advance( FT_Face face, + FT_UInt gindex, + FT_Pos *aadvance ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTBDF_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftrender.h b/Utilities/vtkfreetype/include/freetype/ftrender.h new file mode 100644 index 0000000..db3ca94 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftrender.h @@ -0,0 +1,229 @@ +/***************************************************************************/ +/* */ +/* ftrender.h */ +/* */ +/* FreeType renderer modules public interface (specification). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTRENDER_H__ +#define __FTRENDER_H__ + + +#include <ft2build.h> +#include FT_MODULE_H +#include FT_GLYPH_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* module_management */ + /* */ + /*************************************************************************/ + + + /* create a new glyph object */ + typedef FT_Error + (*FT_Glyph_InitFunc)( FT_Glyph glyph, + FT_GlyphSlot slot ); + + /* destroys a given glyph object */ + typedef void + (*FT_Glyph_DoneFunc)( FT_Glyph glyph ); + + typedef void + (*FT_Glyph_TransformFunc)( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + typedef void + (*FT_Glyph_GetBBoxFunc)( FT_Glyph glyph, + FT_BBox* abbox ); + + typedef FT_Error + (*FT_Glyph_CopyFunc)( FT_Glyph source, + FT_Glyph target ); + + typedef FT_Error + (*FT_Glyph_PrepareFunc)( FT_Glyph glyph, + FT_GlyphSlot slot ); + +/* deprecated */ +#define FT_Glyph_Init_Func FT_Glyph_InitFunc +#define FT_Glyph_Done_Func FT_Glyph_DoneFunc +#define FT_Glyph_Transform_Func FT_Glyph_TransformFunc +#define FT_Glyph_BBox_Func FT_Glyph_GetBBoxFunc +#define FT_Glyph_Copy_Func FT_Glyph_CopyFunc +#define FT_Glyph_Prepare_Func FT_Glyph_PrepareFunc + + + struct FT_Glyph_Class_ + { + FT_Long glyph_size; + FT_Glyph_Format glyph_format; + FT_Glyph_InitFunc glyph_init; + FT_Glyph_DoneFunc glyph_done; + FT_Glyph_CopyFunc glyph_copy; + FT_Glyph_TransformFunc glyph_transform; + FT_Glyph_GetBBoxFunc glyph_bbox; + FT_Glyph_PrepareFunc glyph_prepare; + }; + + + typedef FT_Error + (*FT_Renderer_RenderFunc)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_UInt mode, + FT_Vector* origin ); + + typedef FT_Error + (*FT_Renderer_TransformFunc)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_Matrix* matrix, + FT_Vector* delta ); + + + typedef void + (*FT_Renderer_GetCBoxFunc)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_BBox* cbox ); + + + typedef FT_Error + (*FT_Renderer_SetModeFunc)( FT_Renderer renderer, + FT_ULong mode_tag, + FT_Pointer mode_ptr ); + +/* deprecated identifiers */ +#define FTRenderer_render FT_Renderer_RenderFunc +#define FTRenderer_transform FT_Renderer_TransformFunc +#define FTRenderer_getCBox FT_Renderer_GetCBoxFunc +#define FTRenderer_setMode FT_Renderer_SetModeFunc + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Renderer_Class */ + /* */ + /* <Description> */ + /* The renderer module class descriptor. */ + /* */ + /* <Fields> */ + /* root :: The root FT_Module_Class fields. */ + /* */ + /* glyph_format :: The glyph image format this renderer handles. */ + /* */ + /* render_glyph :: A method used to render the image that is in a */ + /* given glyph slot into a bitmap. */ + /* */ + /* set_mode :: A method used to pass additional parameters. */ + /* */ + /* raster_class :: For `FT_GLYPH_FORMAT_OUTLINE' renderers only, this */ + /* is a pointer to its raster's class. */ + /* */ + /* raster :: For `FT_GLYPH_FORMAT_OUTLINE' renderers only. this */ + /* is a pointer to the corresponding raster object, */ + /* if any. */ + /* */ + typedef struct FT_Renderer_Class_ + { + FT_Module_Class root; + + FT_Glyph_Format glyph_format; + + FT_Renderer_RenderFunc render_glyph; + FT_Renderer_TransformFunc transform_glyph; + FT_Renderer_GetCBoxFunc get_glyph_cbox; + FT_Renderer_SetModeFunc set_mode; + + FT_Raster_Funcs* raster_class; + + } FT_Renderer_Class; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Renderer */ + /* */ + /* <Description> */ + /* Retrieves the current renderer for a given glyph format. */ + /* */ + /* <Input> */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* <Return> */ + /* A renderer handle. 0 if none found. */ + /* */ + /* <Note> */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */ + /* renderer by its name, use FT_Get_Module(). */ + /* */ + FT_EXPORT( FT_Renderer ) + FT_Get_Renderer( FT_Library library, + FT_Glyph_Format format ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Set_Renderer */ + /* */ + /* <Description> */ + /* Sets the current renderer to use, and set additional mode. */ + /* */ + /* <InOut> */ + /* library :: A handle to the library object. */ + /* */ + /* <Input> */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* In case of success, the renderer will be used to convert glyph */ + /* images in the renderer's known format into bitmaps. */ + /* */ + /* This doesn't change the current renderer for other formats. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Set_Renderer( FT_Library library, + FT_Renderer renderer, + FT_UInt num_params, + FT_Parameter* parameters ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FTRENDER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftsizes.h b/Utilities/vtkfreetype/include/freetype/ftsizes.h new file mode 100644 index 0000000..f0ec915 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftsizes.h @@ -0,0 +1,159 @@ +/***************************************************************************/ +/* */ +/* ftsizes.h */ +/* */ +/* FreeType size objects management (specification). */ +/* */ +/* Copyright 1996-2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Typical application would normally not need to use these functions. */ + /* However, they have been placed in a public API for the rare cases */ + /* where they are needed. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTSIZES_H__ +#define __FTSIZES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* sizes_management */ + /* */ + /* <Title> */ + /* Size management */ + /* */ + /* <Abstract> */ + /* Managing multiple sizes per face */ + /* */ + /* <Description> */ + /* When creating a new face object (e.g. with @FT_New_Face), an */ + /* @FT_Size object is automatically created and used to store all */ + /* pixel-size dependent information, available in the "face->size" */ + /* field. */ + /* */ + /* It is however possible to create more sizes for a given face, */ + /* mostly in order to manage several character pixel sizes of the */ + /* same font family and style. See @FT_New_Size and @FT_Done_Size. */ + /* */ + /* Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only */ + /* modify the contents of the current "active" size; you thus need */ + /* to use @FT_Activate_Size to change it. */ + /* */ + /* 99% of applications won't need the functions provided here, */ + /* especially if they use the caching sub-system, so be cautious */ + /* when using these. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Size */ + /* */ + /* <Description> */ + /* Creates a new size object from a given face object. */ + /* */ + /* <Input> */ + /* face :: A handle to a parent face object. */ + /* */ + /* <Output> */ + /* asize :: A handle to a new size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* You need to call @FT_Activate_Size in order to select the new size */ + /* for upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size, */ + /* @FT_Load_Glyph, @FT_Load_Char, etc. */ + /* */ + FT_EXPORT( FT_Error ) + FT_New_Size( FT_Face face, + FT_Size* size ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Size */ + /* */ + /* <Description> */ + /* Discards a given size object. Note that @FT_Done_Face */ + /* automatically discards all size objects allocated with */ + /* @FT_New_Size. */ + /* */ + /* <Input> */ + /* size :: A handle to a target size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Done_Size( FT_Size size ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Activate_Size */ + /* */ + /* <Description> */ + /* Even though it is possible to create several size objects for a */ + /* given face (see @FT_New_Size for details), functions like */ + /* @FT_Load_Glyph or @FT_Load_Char only use the last-created one to */ + /* determine the "current character pixel size". */ + /* */ + /* This function can be used to "activate" a previously created size */ + /* object. */ + /* */ + /* <Input> */ + /* size :: A handle to a target size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* If "face" is the size's parent face object, this function changes */ + /* the value of "face->size" to the input size handle. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Activate_Size( FT_Size size ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTSIZES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftsnames.h b/Utilities/vtkfreetype/include/freetype/ftsnames.h new file mode 100644 index 0000000..0e2d9a4 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftsnames.h @@ -0,0 +1,167 @@ +/***************************************************************************/ +/* */ +/* ftsnames.h */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.) (specification). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FT_SFNT_NAMES_H__ +#define __FT_SFNT_NAMES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* sfnt_names */ + /* */ + /* <Title> */ + /* SFNT Names */ + /* */ + /* <Abstract> */ + /* Access the names embedded in TrueType and OpenType files. */ + /* */ + /* <Description> */ + /* The TrueType and OpenType specification allow the inclusion of */ + /* a special `names table' in font files. This table contains */ + /* textual (and internationalized) information regarding the font, */ + /* like family name, copyright, version, etc. */ + /* */ + /* The definitions below are used to access them if available. */ + /* */ + /* Note that this has nothing to do with glyph names! */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_SfntName */ + /* */ + /* <Description> */ + /* A structure used to model an SFNT `name' table entry. */ + /* */ + /* <Fields> */ + /* platform_id :: The platform ID for `string'. */ + /* */ + /* encoding_id :: The encoding ID for `string'. */ + /* */ + /* language_id :: The language ID for `string'. */ + /* */ + /* name_id :: An identifier for `string'. */ + /* */ + /* string :: The `name' string. Note that its format differs */ + /* depending on the (platform,encoding) pair. It can */ + /* be a Pascal String, a UTF-16 one, etc.. */ + /* */ + /* Generally speaking, the string is not */ + /* zero-terminated. Please refer to the TrueType */ + /* specification for details.. */ + /* */ + /* string_len :: The length of `string' in bytes. */ + /* */ + /* <Note> */ + /* Possible values for `platform_id', `encoding_id', `language_id', */ + /* and `name_id' are given in the file `ttnameid.h'. For details */ + /* please refer to the TrueType or OpenType specification. */ + /* */ + typedef struct FT_SfntName_ + { + FT_UShort platform_id; + FT_UShort encoding_id; + FT_UShort language_id; + FT_UShort name_id; + + FT_Byte* string; /* this string is *not* null-terminated! */ + FT_UInt string_len; /* in bytes */ + + } FT_SfntName; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Sfnt_Name_Count */ + /* */ + /* <Description> */ + /* Retrieves the number of name strings in the SFNT `name' table. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* <Return> */ + /* The number of strings in the `name' table. */ + /* */ + FT_EXPORT( FT_UInt ) + FT_Get_Sfnt_Name_Count( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Sfnt_Name */ + /* */ + /* <Description> */ + /* Retrieves a string of the SFNT `name' table for a given index. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face. */ + /* */ + /* idx :: The index of the `name' string. */ + /* */ + /* <Output> */ + /* aname :: The indexed FT_SfntName structure. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The `string' array returned in the `aname' structure is not */ + /* null-terminated. */ + /* */ + /* Use FT_Get_Sfnt_Name_Count() to get the total number of available */ + /* `name' table entries, then do a loop until you get the right */ + /* platform, encoding, and name ID. */ + /* */ + FT_EXPORT( FT_Error ) + FT_Get_Sfnt_Name( FT_Face face, + FT_UInt idx, + FT_SfntName *aname ); + + + /* */ + + +FT_END_HEADER + +#endif /* __FT_SFNT_NAMES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftstroke.h b/Utilities/vtkfreetype/include/freetype/ftstroke.h new file mode 100644 index 0000000..a3052e8 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftstroke.h @@ -0,0 +1,686 @@ +/***************************************************************************/ +/* */ +/* ftstroke.h */ +/* */ +/* FreeType path stroker (specification). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FT_STROKE_H__ +#define __FT_STROKE_H__ + +#include <ft2build.h> +#include FT_OUTLINE_H +#include FT_GLYPH_H + +FT_BEGIN_HEADER + + /*@************************************************************* + * + * @type: + * FT_Stroker + * + * @description: + * Opaque handler to a path stroker object. + */ + typedef struct FT_StrokerRec_* FT_Stroker; + + + /*@************************************************************* + * + * @enum: + * FT_Stroker_LineJoin + * + * @description: + * These values determine how two joining lines are rendered + * in a stroker. + * + * @values: + * FT_STROKER_LINEJOIN_ROUND :: + * Used to render rounded line joins. Circular arcs are used + * to join two lines smoothly. + * + * FT_STROKER_LINEJOIN_BEVEL :: + * Used to render beveled line joins; i.e., the two joining lines + * are extended until they intersect. + * + * FT_STROKER_LINEJOIN_MITER :: + * Same as beveled rendering, except that an additional line + * break is added if the angle between the two joining lines + * is too closed (this is useful to avoid unpleasant spikes + * in beveled rendering). + */ + typedef enum + { + FT_STROKER_LINEJOIN_ROUND = 0, + FT_STROKER_LINEJOIN_BEVEL, + FT_STROKER_LINEJOIN_MITER + + } FT_Stroker_LineJoin; + + + /*@************************************************************* + * + * @enum: + * FT_Stroker_LineCap + * + * @description: + * These values determine how the end of opened sub-paths are + * rendered in a stroke. + * + * @values: + * FT_STROKER_LINECAP_BUTT :: + * The end of lines is rendered as a full stop on the last + * point itself. + * + * FT_STROKER_LINECAP_ROUND :: + * The end of lines is rendered as a half-circle around the + * last point. + * + * FT_STROKER_LINECAP_SQUARE :: + * The end of lines is rendered as a square around the + * last point. + */ + typedef enum + { + FT_STROKER_LINECAP_BUTT = 0, + FT_STROKER_LINECAP_ROUND, + FT_STROKER_LINECAP_SQUARE + + } FT_Stroker_LineCap; + + + /************************************************************** + * + * @enum: + * FT_StrokerBorder + * + * @description: + * These values are used to select a given stroke border + * in @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder. + * + * @values: + * FT_STROKER_BORDER_LEFT :: + * Select the left border, relative to the drawing direction. + * + * FT_STROKER_BORDER_RIGHT :: + * Select the right border, relative to the drawing direction. + * + * @note: + * Applications are generally interested in the `inside' and `outside' + * borders. However, there is no direct mapping between these and + * the `left' / `right' ones, since this really depends on the glyph's + * drawing orientation, which varies between font formats. + * + * You can however use @FT_Outline_GetInsideBorder and + * @FT_Outline_GetOutsideBorder to get these. + */ + typedef enum + { + FT_STROKER_BORDER_LEFT = 0, + FT_STROKER_BORDER_RIGHT + + } FT_StrokerBorder; + + + /************************************************************** + * + * @function: + * FT_Outline_GetInsideBorder + * + * @description: + * Retrieve the @FT_StrokerBorder value corresponding to the + * `inside' borders of a given outline. + * + * @input: + * outline :: + * The source outline handle. + * + * @return: + * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid + * outlines. + */ + FT_EXPORT( FT_StrokerBorder ) + FT_Outline_GetInsideBorder( FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Outline_GetOutsideBorder + * + * @description: + * Retrieve the @FT_StrokerBorder value corresponding to the + * `outside' borders of a given outline. + * + * @input: + * outline :: + * The source outline handle. + * + * @return: + * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid + * outlines. + */ + FT_EXPORT( FT_StrokerBorder ) + FT_Outline_GetOutsideBorder( FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Stroker_New + * + * @description: + * Create a new stroker object. + * + * @input: + * memory :: + * The memory manager handle. + * + * @output: + * A new stroker object handle. NULL in case of error. + * + * @return: + * FreeType error code. 0 means success. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_New( FT_Memory memory, + FT_Stroker *astroker ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Set + * + * @description: + * Reset a stroker object's attributes. + * + * @input: + * stroker :: + * The target stroker handle. + * + * radius :: + * The border radius. + * + * line_cap :: + * The line cap style. + * + * line_join :: + * The line join style. + * + * miter_limit :: + * The miter limit for the FT_STROKER_LINEJOIN_MITER style, + * expressed as 16.16 fixed point value. + * + * @note: + * The radius is expressed in the same units that the outline + * coordinates. + */ + FT_EXPORT( void ) + FT_Stroker_Set( FT_Stroker stroker, + FT_Fixed radius, + FT_Stroker_LineCap line_cap, + FT_Stroker_LineJoin line_join, + FT_Fixed miter_limit ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Rewind + * + * @description: + * Reset a stroker object without changing its attributes. + * You should call this function before beginning a new + * series of calls to @FT_Stroker_BeginSubPath or + * @FT_Stroker_EndSubPath. + * + * @input: + * stroker :: + * The target stroker handle. + */ + FT_EXPORT( void ) + FT_Stroker_Rewind( FT_Stroker stroker ); + + + /************************************************************** + * + * @function: + * FT_Stroker_ParseOutline + * + * @description: + * A convenience function used to parse a whole outline with + * the stroker. The resulting outline(s) can be retrieved + * later by functions like @FT_Stroker_GetCounts and @FT_Stroker_Export. + * + * @input: + * stroker :: + * The target stroker handle. + * + * outline :: + * The source outline. + * + * opened :: + * A boolean. If TRUE, the outline is treated as an open path + * instead of a closed one. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * If `opened' is 0 (the default), the outline is treated as a closed + * path, and the stroker will generate two distinct `border' outlines. + * + * If `opened' is 1, the outline is processed as an open path, and the + * stroker will generate a single `stroke' outline. + * + * This function calls @FT_Stroker_Rewind automatically. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_ParseOutline( FT_Stroker stroker, + FT_Outline* outline, + FT_Bool opened ); + + + /************************************************************** + * + * @function: + * FT_Stroker_BeginSubPath + * + * @description: + * Start a new sub-path in the stroker. + * + * @input: + * stroker :: + * The target stroker handle. + * + * to :: + * A pointer to the start vector. + * + * open :: + * A boolean. If TRUE, the sub-path is treated as an open one. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * This function is useful when you need to stroke a path that is + * not stored as a @FT_Outline object. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_BeginSubPath( FT_Stroker stroker, + FT_Vector* to, + FT_Bool open ); + + + /************************************************************** + * + * @function: + * FT_Stroker_EndSubPath + * + * @description: + * Close the current sub-path in the stroker. + * + * @input: + * stroker :: + * The target stroker handle. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * You should call this function after @FT_Stroker_BeginSubPath. + * If the subpath was not `opened', this function will `draw' a + * single line segment to the start position when needed. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_EndSubPath( FT_Stroker stroker ); + + + /************************************************************** + * + * @function: + * FT_Stroker_LineTo + * + * @description: + * `Draw' a single line segment in the stroker's current sub-path, + * from the last position. + * + * @input: + * stroker :: + * The target stroker handle. + * + * to :: + * A pointer to the destination point. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * You should call this function between @FT_Stroker_BeginSubPath and + * @FT_Stroker_EndSubPath. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_LineTo( FT_Stroker stroker, + FT_Vector* to ); + + + /************************************************************** + * + * @function: + * FT_Stroker_ConicTo + * + * @description: + * `Draw; a single quadratic bezier in the stroker's current sub-path, + * from the last position. + * + * @input: + * stroker :: + * The target stroker handle. + * + * control :: + * A pointer to a Bézier control point. + * + * to :: + * A pointer to the destination point. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * You should call this function between @FT_Stroker_BeginSubPath and + * @FT_Stroker_EndSubPath. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_ConicTo( FT_Stroker stroker, + FT_Vector* control, + FT_Vector* to ); + + + /************************************************************** + * + * @function: + * FT_Stroker_CubicTo + * + * @description: + * `Draw' a single cubic Bézier in the stroker's current sub-path, + * from the last position. + * + * @input: + * stroker :: + * The target stroker handle. + * + * control1 :: + * A pointer to the first Bézier control point. + * + * control2 :: + * A pointer to second Bézier control point. + * + * to :: + * A pointer to the destination point. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * You should call this function between @FT_Stroker_BeginSubPath and + * @FT_Stroker_EndSubPath. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_CubicTo( FT_Stroker stroker, + FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to ); + + + /************************************************************** + * + * @function: + * FT_Stroker_GetBorderCounts + * + * @description: + * Vall this function once you have finished parsing your paths + * with the stroker. It will return the number of points and + * contours necessary to export one of the `border' or `stroke' + * outlines generated by the stroker. + * + * @input: + * stroker :: + * The target stroker handle. + * + * border :: + * The border index. + * + * @output: + * anum_points :: + * The number of points. + * + * anum_contours :: + * The number of contours. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * When an outline, or a sub-path, is `closed', the stroker generates + * two independent `border' outlines, named `left' and `right'. + * + * When the outline, or a sub-path, is `opened', the stroker merges + * the `border' outlines with caps. The `left' border receives all + * points, while the `right' border becomes empty. + * + * Use the function @FT_Stroker_GetCounts instead if you want to + * retrieve the counts associated to both borders. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_GetBorderCounts( FT_Stroker stroker, + FT_StrokerBorder border, + FT_UInt *anum_points, + FT_UInt *anum_contours ); + + + /************************************************************** + * + * @function: + * FT_Stroker_ExportBorder + * + * @description: + * Call this function after @FT_Stroker_GetBorderCounts to + * export the corresponding border to your own @FT_Outline + * structure. + * + * Note that this function will append the border points and + * contours to your outline, but will not try to resize its + * arrays. + * + * @input: + * stroker :: + * The target stroker handle. + * + * border :: + * The border index. + * + * outline :: + * The target outline handle. + * + * @note: + * Always call this function after @FT_Stroker_GetBorderCounts to + * get sure that there is enough room in your @FT_Outline object to + * receive all new data. + * + * When an outline, or a sub-path, is `closed', the stroker generates + * two independent `border' outlines, named `left' and `right' + * + * When the outline, or a sub-path, is `opened', the stroker merges + * the `border' outlines with caps. The `left' border receives all + * points, while the `right' border becomes empty. + * + * Use the function @FT_Stroker_Export instead if you want to + * retrieve all borders at once. + */ + FT_EXPORT( void ) + FT_Stroker_ExportBorder( FT_Stroker stroker, + FT_StrokerBorder border, + FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Stroker_GetCounts + * + * @description: + * Call this function once you have finished parsing your paths + * with the stroker. It returns the number of points and + * contours necessary to export all points/borders from the stroked + * outline/path. + * + * @input: + * stroker :: + * The target stroker handle. + * + * @output: + * anum_points :: + * The number of points. + * + * anum_contours :: + * The number of contours. + * + * @return: + * FreeType error code. 0 means success. + */ + FT_EXPORT( FT_Error ) + FT_Stroker_GetCounts( FT_Stroker stroker, + FT_UInt *anum_points, + FT_UInt *anum_contours ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Export + * + * @description: + * Call this function after @FT_Stroker_GetBorderCounts to + * export the all borders to your own @FT_Outline structure. + * + * Note that this function will append the border points and + * contours to your outline, but will not try to resize its + * arrays. + * + * @input: + * stroker :: + * The target stroker handle. + * + * outline :: + * The target outline handle. + */ + FT_EXPORT( void ) + FT_Stroker_Export( FT_Stroker stroker, + FT_Outline* outline ); + + + /************************************************************** + * + * @function: + * FT_Stroker_Done + * + * @description: + * Destroy a stroker object. + * + * @input: + * stroker :: + * A stroker handle. Can be NULL. + */ + FT_EXPORT( void ) + FT_Stroker_Done( FT_Stroker stroker ); + + + /************************************************************** + * + * @function: + * FT_Glyph_Stroke + * + * @description: + * Stroke a given outline glyph object with a given stroker. + * + * @inout: + * pglyph :: Source glyph handle on input, new glyph handle + * on output. + * + * @input: + * stroker :: + * A stroker handle. + * + * destroy :: + * A Boolean. If TRUE, the source glyph object is destroyed + * on success. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * The source glyph is untouched in case of error. + */ + FT_EXPORT( FT_Error ) + FT_Glyph_Stroke( FT_Glyph *pglyph, + FT_Stroker stroker, + FT_Bool destroy ); + + + /************************************************************** + * + * @function: + * FT_Glyph_StrokeBorder + * + * @description: + * Stroke a given outline glyph object with a given stroker, but + * only return either its inside or outside border. + * + * @inout: + * pglyph :: + * Source glyph handle on input, new glyph handle on output. + * + * @input: + * stroker :: + * A stroker handle. + * + * inside :: + * A Boolean. If TRUE, return the inside border, otherwise + * the outside border. + * + * destroy :: + * A Boolean. If TRUE, the source glyph object is destroyed + * on success. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * The source glyph is untouched in case of error. + */ + FT_EXPORT( FT_Error ) + FT_Glyph_StrokeBorder( FT_Glyph *pglyph, + FT_Stroker stroker, + FT_Bool inside, + FT_Bool destroy ); + + /* */ + +FT_END_HEADER + +#endif /* __FT_STROKE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftsynth.h b/Utilities/vtkfreetype/include/freetype/ftsynth.h new file mode 100644 index 0000000..f0c7385 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftsynth.h @@ -0,0 +1,71 @@ +/***************************************************************************/ +/* */ +/* ftsynth.h */ +/* */ +/* FreeType synthesizing code for emboldening and slanting */ +/* (specification). */ +/* */ +/* Copyright 2000-2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********* *********/ + /********* WARNING, THIS IS ALPHA CODE, THIS API *********/ + /********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/ + /********* FREETYPE DEVELOPMENT TEAM *********/ + /********* *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#ifndef __FTSYNTH_H__ +#define __FTSYNTH_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /* This code is completely experimental -- use with care! */ + /* It will probably be completely rewritten in the future */ + /* or even integrated into the library. */ + FT_EXPORT( void ) + FT_GlyphSlot_Embolden( FT_GlyphSlot slot ); + + + FT_EXPORT( void ) + FT_GlyphSlot_Oblique( FT_GlyphSlot slot ); + + /* */ + +FT_END_HEADER + +#endif /* __FTSYNTH_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftsysio.h b/Utilities/vtkfreetype/include/freetype/ftsysio.h new file mode 100644 index 0000000..f8e4954 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftsysio.h @@ -0,0 +1,195 @@ +#ifndef __FT_SYSTEM_IO_H__ +#define __FT_SYSTEM_IO_H__ + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** NOTE: THE CONTENT OF THIS FILE IS NOT CURRENTLY USED *****/ + /***** IN NORMAL BUILDS. CONSIDER IT EXPERIMENTAL. *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + + + /******************************************************************** + * + * designing custom streams is a bit different now + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +#include <ft2build.h> +#include FT_INTERNAL_OBJECT_H + +FT_BEGIN_HEADER + + /*@******************************************************************* + * + * @type: FT_Stream + * + * @description: + * handle to an input stream object. These are also @FT_Object handles + */ + typedef struct FT_StreamRec_* FT_Stream; + + + /*@******************************************************************* + * + * @type: FT_Stream_Class + * + * @description: + * opaque handle to a @FT_Stream_ClassRec class structure describing + * the methods of input streams + */ + typedef const struct FT_Stream_ClassRec_* FT_Stream_Class; + + + /*@******************************************************************* + * + * @functype: FT_Stream_ReadFunc + * + * @description: + * a method used to read bytes from an input stream into memory + * + * @input: + * stream :: target stream handle + * buffer :: target buffer address + * size :: number of bytes to read + * + * @return: + * number of bytes effectively read. Must be <= 'size'. + */ + typedef FT_ULong (*FT_Stream_ReadFunc)( FT_Stream stream, + FT_Byte* buffer, + FT_ULong size ); + + + /*@******************************************************************* + * + * @functype: FT_Stream_SeekFunc + * + * @description: + * a method used to seek to a new position within a stream + * + * @input: + * stream :: target stream handle + * pos :: new read position, from start of stream + * + * @return: + * error code. 0 means success + */ + typedef FT_Error (*FT_Stream_SeekFunc)( FT_Stream stream, + FT_ULong pos ); + + + /*@******************************************************************* + * + * @struct: FT_Stream_ClassRec + * + * @description: + * a structure used to describe an input stream class + * + * @input: + * clazz :: root @FT_ClassRec fields + * stream_read :: stream byte read method + * stream_seek :: stream seek method + */ + typedef struct FT_Stream_ClassRec_ + { + FT_ClassRec clazz; + FT_Stream_ReadFunc stream_read; + FT_Stream_SeekFunc stream_seek; + + } FT_Stream_ClassRec; + + /* */ + +#define FT_STREAM_CLASS(x) ((FT_Stream_Class)(x)) +#define FT_STREAM_CLASS__READ(x) FT_STREAM_CLASS(x)->stream_read +#define FT_STREAM_CLASS__SEEK(x) FT_STREAM_CLASS(x)->stream_seek; + + /*@******************************************************************* + * + * @struct: FT_StreamRec + * + * @description: + * the input stream object structure. See @FT_Stream_ClassRec for + * its class descriptor + * + * @fields: + * object :: root @FT_ObjectRec fields + * size :: size of stream in bytes (0 if unknown) + * pos :: current position within stream + * base :: for memory-based streams, the address of the stream's + * first data byte in memory. NULL otherwise + * + * cursor :: the current cursor position within an input stream + * frame. Only valid within a FT_FRAME_ENTER .. FT_FRAME_EXIT + * block; NULL otherwise + * + * limit :: the current frame limit within a FT_FRAME_ENTER .. + * FT_FRAME_EXIT block. NULL otherwise + */ + typedef struct FT_StreamRec_ + { + FT_ObjectRec object; + FT_ULong size; + FT_ULong pos; + const FT_Byte* base; + const FT_Byte* cursor; + const FT_Byte* limit; + + } FT_StreamRec; + + /* some useful macros */ +#define FT_STREAM(x) ((FT_Stream)(x)) +#define FT_STREAM_P(x) ((FT_Stream*)(x)) + +#define FT_STREAM__READ(x) FT_STREAM_CLASS__READ(FT_OBJECT__CLASS(x)) +#define FT_STREAM__SEEK(x) FT_STREAM_CLASS__SEEK(FT_OBJECT__CLASS(x)) + +#define FT_STREAM_IS_BASED(x) ( FT_STREAM(x)->base != NULL ) + + /* */ + + /* create new memory-based stream */ + FT_BASE( FT_Error ) ft_stream_new_memory( const FT_Byte* stream_base, + FT_ULong stream_size, + FT_Memory memory, + FT_Stream *astream ); + + FT_BASE( FT_Error ) ft_stream_new_iso( const char* pathanme, + FT_Memory memory, + FT_Stream *astream ); + + + /* handle to default stream class implementation for a given build */ + /* this is used by "FT_New_Face" */ + /* */ + FT_APIVAR( FT_Type ) ft_stream_default_type; + +FT_END_HEADER + +#endif /* __FT_SYSTEM_STREAM_H__ */ diff --git a/Utilities/vtkfreetype/include/freetype/ftsysmem.h b/Utilities/vtkfreetype/include/freetype/ftsysmem.h new file mode 100644 index 0000000..8de0c4d --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftsysmem.h @@ -0,0 +1,202 @@ +#ifndef __FT_SYSTEM_MEMORY_H__ +#define __FT_SYSTEM_MEMORY_H__ + +#include <ft2build.h> + +FT_BEGIN_HEADER + + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** NOTE: THE CONTENT OF THIS FILE IS NOT CURRENTLY USED *****/ + /***** IN NORMAL BUILDS. CONSIDER IT EXPERIMENTAL. *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + + + /*@********************************************************************** + * + * @type: FT_Memory + * + * @description: + * opaque handle to a memory manager handle. Note that since FreeType + * 2.2, the memory manager structure FT_MemoryRec is hidden to client + * applications. + * + * however, you can still define custom allocators easily using the + * @ft_memory_new API + */ + typedef struct FT_MemoryRec_* FT_Memory; + + + /*@********************************************************************** + * + * @functype: FT_Memory_AllocFunc + * + * @description: + * a function used to allocate a block of memory. + * + * @input: + * size :: size of blocks in bytes. Always > 0 !! + * mem_data :: memory-manager specific optional argument + * (see @ft_memory_new) + * + * @return: + * address of new block. NULL in case of memory exhaustion + */ + typedef FT_Pointer (*FT_Memory_AllocFunc)( FT_ULong size, + FT_Pointer mem_data ); + + + /*@********************************************************************** + * + * @functype: FT_Memory_FreeFunc + * + * @description: + * a function used to release a block of memory created through + * @FT_Memory_AllocFunc or @FT_Memory_ReallocFunc + * + * @input: + * block :: address of target memory block. cannot be NULL !! + * mem_data :: memory-manager specific optional argument + * (see @ft_memory_new) + */ + typedef void (*FT_Memory_FreeFunc) ( FT_Pointer block, + FT_Pointer mem_data ); + + + /*@********************************************************************** + * + * @functype: FT_Memory_ReallocFunc + * + * @description: + * a function used to reallocate a memory block. + * + * @input: + * block :: address of target memory block. cannot be NULL !! + * new_size :: new requested size in bytes + * cur_size :: current block size in bytes + * mem_data :: memory-manager specific optional argument + * (see @ft_memory_new) + */ + typedef FT_Pointer (*FT_Memory_ReallocFunc)( FT_Pointer block, + FT_ULong new_size, + FT_ULong cur_size, + FT_Pointer mem_data ); + + + /*@********************************************************************** + * + * @functype: FT_Memory_CreateFunc + * + * @description: + * a function used to create a @FT_Memory object to model a + * memory manager + * + * @input: + * size :: size of memory manager structure in bytes + * init_data :: optional initialisation argument + * + * @output: + * amem_data :: memory-manager specific argument to block management + * routines. + * + * @return: + * handle to new memory manager object. NULL in case of failure + */ + typedef FT_Pointer (*FT_Memory_CreateFunc)( FT_UInt size, + FT_Pointer init_data, + FT_Pointer *amem_data ); + + + /*@********************************************************************** + * + * @functype: FT_Memory_DestroyFunc + * + * @description: + * a function used to destroy a given @FT_Memory manager + * + * @input: + * memory :: target memory manager handle + * mem_data :: option manager-specific argument + */ + typedef void (*FT_Memory_DestroyFunc)( FT_Memory memory, + FT_Pointer mem_data ); + + + /*@********************************************************************** + * + * @struct: FT_Memory_FuncsRec + * + * @description: + * a function used to hold all methods of a given memory manager + * implementation. + * + * @fields: + * mem_alloc :: block allocation routine + * mem_free :: block release routine + * mem_realloc :: block re-allocation routine + * mem_create :: manager creation routine + * mem_destroy :: manager destruction routine + */ + typedef struct FT_Memory_FuncsRec_ + { + FT_Memory_AllocFunc mem_alloc; + FT_Memory_FreeFunc mem_free; + FT_Memory_ReallocFunc mem_realloc; + FT_Memory_CreateFunc mem_create; + FT_Memory_DestroyFunc mem_destroy; + + } FT_Memory_FuncsRec, *FT_Memory_Funcs; + + + /*@********************************************************************** + * + * @type: FT_Memory_Funcs + * + * @description: + * a pointer to a constant @FT_Memory_FuncsRec structure used to + * describe a given memory manager implementation. + */ + typedef const FT_Memory_FuncsRec* FT_Memory_Funcs; + + + /*@********************************************************************** + * + * @function: ft_memory_new + * + * @description: + * create a new memory manager, given a set of memory methods + * + * @input: + * mem_funcs :: handle to memory manager implementation descriptor + * mem_init_data :: optional initialisation argument, passed to + * @FT_Memory_CreateFunc + * + * @return: + * new memory manager handle. NULL in case of failure + */ + FT_BASE( FT_Memory ) + ft_memory_new( FT_Memory_Funcs mem_funcs, + FT_Pointer mem_init_data ); + + + /*@********************************************************************** + * + * @function: ft_memory_destroy + * + * @description: + * destroy a given memory manager + * + * @input: + * memory :: handle to target memory manager + */ + FT_BASE( void ) + ft_memory_destroy( FT_Memory memory ); + +/* */ + +FT_END_HEADER + +#endif /* __FT_SYSTEM_MEMORY_H__ */ diff --git a/Utilities/vtkfreetype/include/freetype/ftsystem.h b/Utilities/vtkfreetype/include/freetype/ftsystem.h new file mode 100644 index 0000000..d1c55f7 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftsystem.h @@ -0,0 +1,309 @@ +/***************************************************************************/ +/* */ +/* ftsystem.h */ +/* */ +/* FreeType low-level system interface definition (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTSYSTEM_H__ +#define __FTSYSTEM_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* system_interface */ + /* */ + /* <Title> */ + /* System Interface */ + /* */ + /* <Abstract> */ + /* How FreeType manages memory and i/o. */ + /* */ + /* <Description> */ + /* This section contains various definitions related to memory */ + /* management and i/o access. You need to understand this */ + /* information if you want to use a custom memory manager or you own */ + /* input i/o streams. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* M E M O R Y M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* @type: */ + /* FT_Memory */ + /* */ + /* @description: */ + /* A handle to a given memory manager object, defined with a */ + /* @FT_MemoryRec structure. */ + /* */ + typedef struct FT_MemoryRec_* FT_Memory; + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* FT_Alloc_Func */ + /* */ + /* @description: */ + /* A function used to allocate `size' bytes from `memory'. */ + /* */ + /* @input: */ + /* memory :: A handle to the source memory manager. */ + /* */ + /* size :: The size in bytes to allocate. */ + /* */ + /* @return: */ + /* Address of new memory block. 0 in case of failure. */ + /* */ + typedef void* + (*FT_Alloc_Func)( FT_Memory memory, + long size ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* FT_Free_Func */ + /* */ + /* @description: */ + /* A function used to release a given block of memory. */ + /* */ + /* @input: */ + /* memory :: A handle to the source memory manager. */ + /* */ + /* block :: The address of the target memory block. */ + /* */ + typedef void + (*FT_Free_Func)( FT_Memory memory, + void* block ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* FT_Realloc_Func */ + /* */ + /* @description: */ + /* a function used to re-allocate a given block of memory. */ + /* */ + /* @input: */ + /* memory :: A handle to the source memory manager. */ + /* */ + /* cur_size :: The block's current size in bytes. */ + /* */ + /* new_size :: The block's requested new size. */ + /* */ + /* block :: The block's current address. */ + /* */ + /* @return: */ + /* New block address. 0 in case of memory shortage. */ + /* */ + /* @note: */ + /* In case of error, the old block must still be available. */ + /* */ + typedef void* + (*FT_Realloc_Func)( FT_Memory memory, + long cur_size, + long new_size, + void* block ); + + + /*************************************************************************/ + /* */ + /* @struct: */ + /* FT_MemoryRec */ + /* */ + /* @description: */ + /* A structure used to describe a given memory manager to FreeType 2. */ + /* */ + /* @fields: */ + /* user :: A generic typeless pointer for user data. */ + /* */ + /* alloc :: A pointer type to an allocation function. */ + /* */ + /* free :: A pointer type to an memory freeing function. */ + /* */ + /* realloc :: A pointer type to a reallocation function. */ + /* */ + struct FT_MemoryRec_ + { + void* user; + FT_Alloc_Func alloc; + FT_Free_Func free; + FT_Realloc_Func realloc; + }; + + + /*************************************************************************/ + /* */ + /* I / O M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* @type: */ + /* FT_Stream */ + /* */ + /* @description: */ + /* A handle to an input stream. */ + /* */ + typedef struct FT_StreamRec_* FT_Stream; + + + /*************************************************************************/ + /* */ + /* @struct: */ + /* FT_StreamDesc */ + /* */ + /* @description: */ + /* A union type used to store either a long or a pointer. This is */ + /* used to store a file descriptor or a FILE* in an input stream. */ + /* */ + typedef union FT_StreamDesc_ + { + long value; + void* pointer; + + } FT_StreamDesc; + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* FT_Stream_IoFunc */ + /* */ + /* @description: */ + /* A function used to seek and read data from a given input stream. */ + /* */ + /* @input: */ + /* stream :: A handle to the source stream. */ + /* */ + /* offset :: The offset of read in stream (always from start). */ + /* */ + /* buffer :: The address of the read buffer. */ + /* */ + /* count :: The number of bytes to read from the stream. */ + /* */ + /* @return: */ + /* The number of bytes effectively read by the stream. */ + /* */ + /* @note: */ + /* This function might be called to perform a seek or skip operation */ + /* with a `count' of 0. */ + /* */ + typedef unsigned long + (*FT_Stream_IoFunc)( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* FT_Stream_CloseFunc */ + /* */ + /* @description: */ + /* A function used to close a given input stream. */ + /* */ + /* @input: */ + /* stream :: A handle to the target stream. */ + /* */ + typedef void + (*FT_Stream_CloseFunc)( FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* @struct: */ + /* FT_StreamRec */ + /* */ + /* @description: */ + /* A structure used to describe an input stream. */ + /* */ + /* @input: */ + /* base :: For memory-based streams, this is the address of the */ + /* first stream byte in memory. This field should */ + /* always be set to NULL for disk-based streams. */ + /* */ + /* size :: The stream size in bytes. */ + /* */ + /* pos :: The current position within the stream. */ + /* */ + /* descriptor :: This field is a union that can hold an integer or a */ + /* pointer. It is used by stream implementations to */ + /* store file descriptors or FILE* pointers. */ + /* */ + /* pathname :: This field is completely ignored by FreeType. */ + /* However, it is often useful during debugging to use */ + /* it to store the stream's filename (where available). */ + /* */ + /* read :: The stream's input function. */ + /* */ + /* close :: The stream;s close function. */ + /* */ + /* memory :: The memory manager to use to preload frames. This is */ + /* set internally by FreeType and shouldn't be touched */ + /* by stream implementations. */ + /* */ + /* cursor :: This field is set and used internally by FreeType */ + /* when parsing frames. */ + /* */ + /* limit :: This field is set and used internally by FreeType */ + /* when parsing frames. */ + /* */ + typedef struct FT_StreamRec_ + { + unsigned char* base; + unsigned long size; + unsigned long pos; + + FT_StreamDesc descriptor; + FT_StreamDesc pathname; + FT_Stream_IoFunc read; + FT_Stream_CloseFunc close; + + FT_Memory memory; + unsigned char* cursor; + unsigned char* limit; + + } FT_StreamRec; + + + /* */ + + +FT_END_HEADER + +#endif /* __FTSYSTEM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/fttrigon.h b/Utilities/vtkfreetype/include/freetype/fttrigon.h new file mode 100644 index 0000000..0462265 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/fttrigon.h @@ -0,0 +1,315 @@ +/***************************************************************************/ +/* */ +/* fttrigon.h */ +/* */ +/* FreeType trigonometric functions (specification). */ +/* */ +/* Copyright 2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTTRIGON_H__ +#define __FTTRIGON_H__ + +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* @section: */ + /* computations */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* @type: */ + /* FT_Angle */ + /* */ + /* @description: */ + /* This type is used to model angle values in FreeType. Note that */ + /* the angle is a 16.16 fixed float value expressed in degrees. */ + /* */ + typedef FT_Fixed FT_Angle; + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_ANGLE_PI */ + /* */ + /* @description: */ + /* The angle pi expressed in @FT_Angle units. */ + /* */ +#define FT_ANGLE_PI ( 180L << 16 ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_ANGLE_2PI */ + /* */ + /* @description: */ + /* The angle 2*pi expressed in @FT_Angle units. */ + /* */ +#define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_ANGLE_PI2 */ + /* */ + /* @description: */ + /* The angle pi/2 expressed in @FT_Angle units. */ + /* */ +#define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 ) + + + /*************************************************************************/ + /* */ + /* @macro: */ + /* FT_ANGLE_PI4 */ + /* */ + /* @description: */ + /* The angle pi/4 expressed in @FT_Angle units. */ + /* */ +#define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 ) + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Sin */ + /* */ + /* @description: */ + /* Return the sinus of a given angle in fixed point format. */ + /* */ + /* @input: */ + /* angle :: The input angle. */ + /* */ + /* @return: */ + /* The sinus value. */ + /* */ + /* @note: */ + /* If you need both the sinus and cosinus for a given angle, use the */ + /* function @FT_Vector_Unit. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_Sin( FT_Angle angle ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Cos */ + /* */ + /* @description: */ + /* Return the cosinus of a given angle in fixed point format. */ + /* */ + /* @input: */ + /* angle :: The input angle. */ + /* */ + /* @return: */ + /* The cosinus value. */ + /* */ + /* @note: */ + /* If you need both the sinus and cosinus for a given angle, use the */ + /* function @FT_Vector_Unit. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_Cos( FT_Angle angle ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Tan */ + /* */ + /* @description: */ + /* Return the tangent of a given angle in fixed point format. */ + /* */ + /* @input: */ + /* angle :: The input angle. */ + /* */ + /* @return: */ + /* The tangent value. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_Tan( FT_Angle angle ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Atan2 */ + /* */ + /* @description: */ + /* Return the arc-tangent corresponding to a given vector (x,y) in */ + /* the 2d plane. */ + /* */ + /* @input: */ + /* x :: The horizontal vector coordinate. */ + /* */ + /* y :: The vertical vector coordinate. */ + /* */ + /* @return: */ + /* The arc-tangent value (i.e. angle). */ + /* */ + FT_EXPORT( FT_Angle ) + FT_Atan2( FT_Fixed x, + FT_Fixed y ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Angle_Diff */ + /* */ + /* @description: */ + /* Return the difference between two angles. The result is always */ + /* constrained to the ]-PI..PI] interval. */ + /* */ + /* @input: */ + /* angle1 :: First angle. */ + /* */ + /* angle2 :: Second angle. */ + /* */ + /* @return: */ + /* Contrainted value of `value2-value1'. */ + /* */ + FT_EXPORT( FT_Angle ) + FT_Angle_Diff( FT_Angle angle1, + FT_Angle angle2 ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Vector_Unit */ + /* */ + /* @description: */ + /* Return the unit vector corresponding to a given angle. After the */ + /* call, the value of `vec.x' will be `sin(angle)', and the value of */ + /* `vec.y' will be `cos(angle)'. */ + /* */ + /* This function is useful to retrieve both the sinus and cosinus of */ + /* a given angle quickly. */ + /* */ + /* @output: */ + /* vec :: The address of target vector. */ + /* */ + /* @input: */ + /* angle :: The address of angle. */ + /* */ + FT_EXPORT( void ) + FT_Vector_Unit( FT_Vector* vec, + FT_Angle angle ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Vector_Rotate */ + /* */ + /* @description: */ + /* Rotate a vector by a given angle. */ + /* */ + /* @inout: */ + /* vec :: The address of target vector. */ + /* */ + /* @input: */ + /* angle :: The address of angle. */ + /* */ + FT_EXPORT( void ) + FT_Vector_Rotate( FT_Vector* vec, + FT_Angle angle ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Vector_Length */ + /* */ + /* @description: */ + /* Return the length of a given vector. */ + /* */ + /* @input: */ + /* vec :: The address of target vector. */ + /* */ + /* @return: */ + /* The vector length, expressed in the same units that the original */ + /* vector coordinates. */ + /* */ + FT_EXPORT( FT_Fixed ) + FT_Vector_Length( FT_Vector* vec ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Vector_Polarize */ + /* */ + /* @description: */ + /* Compute both the length and angle of a given vector. */ + /* */ + /* @input: */ + /* vec :: The address of source vector. */ + /* */ + /* @output: */ + /* length :: The vector length. */ + /* angle :: The vector angle. */ + /* */ + FT_EXPORT( void ) + FT_Vector_Polarize( FT_Vector* vec, + FT_Fixed *length, + FT_Angle *angle ); + + + /*************************************************************************/ + /* */ + /* @function: */ + /* FT_Vector_From_Polar */ + /* */ + /* @description: */ + /* Compute vector coordinates from a length and angle. */ + /* */ + /* @output: */ + /* vec :: The address of source vector. */ + /* */ + /* @input: */ + /* length :: The vector length. */ + /* angle :: The vector angle. */ + /* */ + FT_EXPORT( void ) + FT_Vector_From_Polar( FT_Vector* vec, + FT_Fixed length, + FT_Angle angle ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTTRIGON_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/fttypes.h b/Utilities/vtkfreetype/include/freetype/fttypes.h new file mode 100644 index 0000000..58a1924 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/fttypes.h @@ -0,0 +1,558 @@ +/***************************************************************************/ +/* */ +/* fttypes.h */ +/* */ +/* FreeType simple types definitions (specification only). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTTYPES_H__ +#define __FTTYPES_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_SYSTEM_H +#include FT_IMAGE_H + +#include <stddef.h> + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* basic_types */ + /* */ + /* <Title> */ + /* Basic Data Types */ + /* */ + /* <Abstract> */ + /* The basic data types defined by the library. */ + /* */ + /* <Description> */ + /* This section contains the basic data types defined by FreeType 2, */ + /* ranging from simple scalar types to bitmap descriptors. More */ + /* font-specific structures are defined in a different section. */ + /* */ + /* <Order> */ + /* FT_Byte */ + /* FT_Char */ + /* FT_Int */ + /* FT_UInt */ + /* FT_Short */ + /* FT_UShort */ + /* FT_Long */ + /* FT_ULong */ + /* FT_Bool */ + /* FT_Offset */ + /* FT_PtrDist */ + /* FT_String */ + /* FT_Error */ + /* FT_Fixed */ + /* FT_Pointer */ + /* FT_Pos */ + /* FT_Vector */ + /* FT_BBox */ + /* FT_Matrix */ + /* FT_FWord */ + /* FT_UFWord */ + /* FT_F2Dot14 */ + /* FT_UnitVector */ + /* FT_F26Dot6 */ + /* */ + /* */ + /* FT_Generic */ + /* FT_Generic_Finalizer */ + /* */ + /* FT_Bitmap */ + /* FT_Pixel_Mode */ + /* FT_Palette_Mode */ + /* FT_Glyph_Format */ + /* FT_IMAGE_TAG */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Bool */ + /* */ + /* <Description> */ + /* A typedef of unsigned char, used for simple booleans. */ + /* */ + typedef unsigned char FT_Bool; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_FWord */ + /* */ + /* <Description> */ + /* A signed 16-bit integer used to store a distance in original font */ + /* units. */ + /* */ + typedef signed short FT_FWord; /* distance in FUnits */ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_UFWord */ + /* */ + /* <Description> */ + /* An unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + typedef unsigned short FT_UFWord; /* unsigned distance */ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Char */ + /* */ + /* <Description> */ + /* A simple typedef for the _signed_ char type. */ + /* */ + typedef signed char FT_Char; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Byte */ + /* */ + /* <Description> */ + /* A simple typedef for the _unsigned_ char type. */ + /* */ + typedef unsigned char FT_Byte; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_String */ + /* */ + /* <Description> */ + /* A simple typedef for the char type, usually used for strings. */ + /* */ + typedef char FT_String; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Short */ + /* */ + /* <Description> */ + /* A typedef for signed short. */ + /* */ + typedef signed short FT_Short; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_UShort */ + /* */ + /* <Description> */ + /* A typedef for unsigned short. */ + /* */ + typedef unsigned short FT_UShort; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Int */ + /* */ + /* <Description> */ + /* A typedef for the int type. */ + /* */ + typedef int FT_Int; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_UInt */ + /* */ + /* <Description> */ + /* A typedef for the unsigned int type. */ + /* */ + typedef unsigned int FT_UInt; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Long */ + /* */ + /* <Description> */ + /* A typedef for signed long. */ + /* */ + typedef signed long FT_Long; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_ULong */ + /* */ + /* <Description> */ + /* A typedef for unsigned long. */ + /* */ + typedef unsigned long FT_ULong; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_F2Dot14 */ + /* */ + /* <Description> */ + /* A signed 2.14 fixed float type used for unit vectors. */ + /* */ + typedef signed short FT_F2Dot14; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_F26Dot6 */ + /* */ + /* <Description> */ + /* A signed 26.6 fixed float type used for vectorial pixel */ + /* coordinates. */ + /* */ + typedef signed long FT_F26Dot6; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Fixed */ + /* */ + /* <Description> */ + /* This type is used to store 16.16 fixed float values, like scales */ + /* or matrix coefficients. */ + /* */ + typedef signed long FT_Fixed; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Error */ + /* */ + /* <Description> */ + /* The FreeType error code type. A value of 0 is always interpreted */ + /* as a successful operation. */ + /* */ + typedef int FT_Error; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Pointer */ + /* */ + /* <Description> */ + /* A simple typedef for a typeless pointer. */ + /* */ + typedef void* FT_Pointer; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_Offset */ + /* */ + /* <Description> */ + /* This is equivalent to the ANSI C `size_t' type, i.e. the largest */ + /* _unsigned_ integer type used to express a file size or position, */ + /* or a memory block size. */ + /* */ + typedef size_t FT_Offset; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_PtrDist */ + /* */ + /* <Description> */ + /* This is equivalent to the ANSI C `ptrdiff_t' type, i.e. the */ + /* largest _signed_ integer type used to express the distance */ + /* between two pointers. */ + /* */ + typedef size_t FT_PtrDist; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_UnitVector */ + /* */ + /* <Description> */ + /* A simple structure used to store a 2D vector unit vector. Uses */ + /* FT_F2Dot14 types. */ + /* */ + /* <Fields> */ + /* x :: Horizontal coordinate. */ + /* */ + /* y :: Vertical coordinate. */ + /* */ + typedef struct FT_UnitVector_ + { + FT_F2Dot14 x; + FT_F2Dot14 y; + + } FT_UnitVector; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Matrix */ + /* */ + /* <Description> */ + /* A simple structure used to store a 2x2 matrix. Coefficients are */ + /* in 16.16 fixed float format. The computation performed is: */ + /* */ + /* { */ + /* x' = x*xx + y*xy */ + /* y' = x*yx + y*yy */ + /* } */ + /* */ + /* <Fields> */ + /* xx :: Matrix coefficient. */ + /* */ + /* xy :: Matrix coefficient. */ + /* */ + /* yx :: Matrix coefficient. */ + /* */ + /* yy :: Matrix coefficient. */ + /* */ + typedef struct FT_Matrix_ + { + FT_Fixed xx, xy; + FT_Fixed yx, yy; + + } FT_Matrix; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Data */ + /* */ + /* <Description> */ + /* Read-only binary data represented as a pointer and a length. */ + /* */ + /* <Fields> */ + /* pointer :: The data. */ + /* */ + /* length :: The length of the data in bytes. */ + /* */ + typedef struct FT_Data_ + { + const FT_Byte* pointer; + FT_Int length; + + } FT_Data; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_Generic_Finalizer */ + /* */ + /* <Description> */ + /* Describes a function used to destroy the `client' data of any */ + /* FreeType object. See the description of the FT_Generic type for */ + /* details of usage. */ + /* */ + /* <Input> */ + /* The address of the FreeType object which is under finalization. */ + /* Its client data is accessed through its `generic' field. */ + /* */ + typedef void (*FT_Generic_Finalizer)(void* object); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Generic */ + /* */ + /* <Description> */ + /* Client applications often need to associate their own data to a */ + /* variety of FreeType core objects. For example, a text layout API */ + /* might want to associate a glyph cache to a given size object. */ + /* */ + /* Most FreeType object contains a `generic' field, of type */ + /* FT_Generic, which usage is left to client applications and font */ + /* servers. */ + /* */ + /* It can be used to store a pointer to client-specific data, as well */ + /* as the address of a `finalizer' function, which will be called by */ + /* FreeType when the object is destroyed (for example, the previous */ + /* client example would put the address of the glyph cache destructor */ + /* in the `finalizer' field). */ + /* */ + /* <Fields> */ + /* data :: A typeless pointer to any client-specified data. This */ + /* field is completely ignored by the FreeType library. */ + /* */ + /* finalizer :: A pointer to a `generic finalizer' function, which */ + /* will be called when the object is destroyed. If this */ + /* field is set to NULL, no code will be called. */ + /* */ + typedef struct FT_Generic_ + { + void* data; + FT_Generic_Finalizer finalizer; + + } FT_Generic; + + + /*************************************************************************/ + /* */ + /* <Macro> */ + /* FT_MAKE_TAG */ + /* */ + /* <Description> */ + /* This macro converts four letter tags which are used to label */ + /* TrueType tables into an unsigned long to be used within FreeType. */ + /* */ + /* <Note> */ + /* The produced values *must* be 32bit integers. Don't redefine this */ + /* macro. */ + /* */ +#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (FT_ULong)_x1 << 24 ) | \ + ( (FT_ULong)_x2 << 16 ) | \ + ( (FT_ULong)_x3 << 8 ) | \ + (FT_ULong)_x4 ) + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* L I S T M A N A G E M E N T */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* list_processing */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_ListNode */ + /* */ + /* <Description> */ + /* Many elements and objects in FreeType are listed through a */ + /* FT_List record (see FT_ListRec). As its name suggests, a */ + /* FT_ListNode is a handle to a single list element. */ + /* */ + typedef struct FT_ListNodeRec_* FT_ListNode; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* FT_List */ + /* */ + /* <Description> */ + /* A handle to a list record (see FT_ListRec). */ + /* */ + typedef struct FT_ListRec_* FT_List; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_ListNodeRec */ + /* */ + /* <Description> */ + /* A structure used to hold a single list element. */ + /* */ + /* <Fields> */ + /* prev :: The previous element in the list. NULL if first. */ + /* */ + /* next :: The next element in the list. NULL if last. */ + /* */ + /* data :: A typeless pointer to the listed object. */ + /* */ + typedef struct FT_ListNodeRec_ + { + FT_ListNode prev; + FT_ListNode next; + void* data; + + } FT_ListNodeRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_ListRec */ + /* */ + /* <Description> */ + /* A structure used to hold a simple doubly-linked list. These are */ + /* used in many parts of FreeType. */ + /* */ + /* <Fields> */ + /* head :: The head (first element) of doubly-linked list. */ + /* */ + /* tail :: The tail (last element) of doubly-linked list. */ + /* */ + typedef struct FT_ListRec_ + { + FT_ListNode head; + FT_ListNode tail; + + } FT_ListRec; + + + /* */ + +#define FT_IS_EMPTY( list ) ( (list).head == 0 ) + + /* return base error code (without module-specific prefix) */ +#define FT_ERROR_BASE( x ) ( (x) & 0xFF ) + + /* return module error code */ +#define FT_ERROR_MODULE( x ) ( (x) & 0xFF00U ) + +#define FT_BOOL( x ) ( (FT_Bool)( x ) ) + +FT_END_HEADER + +#endif /* __FTTYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftwinfnt.h b/Utilities/vtkfreetype/include/freetype/ftwinfnt.h new file mode 100644 index 0000000..a19a12d --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftwinfnt.h @@ -0,0 +1,257 @@ +/***************************************************************************/ +/* */ +/* ftwinfnt.h */ +/* */ +/* FreeType API for accessing Windows fnt-specific data. */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTWINFNT_H__ +#define __FTWINFNT_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* winfnt_fonts */ + /* */ + /* <Title> */ + /* Window FNT Fonts */ + /* */ + /* <Abstract> */ + /* Windows FNT specific APIs */ + /* */ + /* <Description> */ + /* This section contains the declaration of Windows FNT specific */ + /* functions. */ + /* */ + /*************************************************************************/ + + + /************************************************************************* + * + * @enum: + * FT_WinFNT_ID_XXX + * + * @description: + * A list of valid values for the `charset' byte in + * @FT_WinFNT_HeaderRec. Exact mapping tables for the various cpXXXX + * encodings (except for cp1361) can be found at ftp://ftp.unicode.org + * in the MAPPINGS/VENDORS/MICSFT/WINDOWS subdirectory. cp1361 is + * roughly a superset of MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT. + * + * @values: + * FT_WinFNT_ID_DEFAULT :: + * This is used for font enumeration and font creation as a + * `don't care' value. Valid font files don't contain this value. + * When querying for information about the character set of the font + * that is currently selected into a specified device context, this + * return value (of the related Windows API) simply denotes failure. + * + * FT_WinFNT_ID_SYMBOL :: + * There is no known mapping table available. + * + * FT_WinFNT_ID_MAC :: + * Mac Roman encoding. + * + * FT_WinFNT_ID_OEM :: + * From Michael Pöttgen <michael@poettgen.de>: + * The `Windows Font Mapping' article says that FT_WinFNT_ID_OEM + * is used for the charset of vector fonts, like `modern.fon', + * `roman.fon', and `script.fon' on Windows. + * + * The `CreateFont' documentation says: The FT_WinFNT_ID_OEM value + * specifies a character set that is operating-system dependent. + * + * The `IFIMETRICS' documentation from the `Windows Driver + * Development Kit' says: This font supports an OEM-specific + * character set. The OEM character set is system dependent. + * + * In general OEM, as opposed to ANSI (i.e., cp1252), denotes the + * second default codepage that most international versions of + * Windows have. It is one of the OEM codepages from + * + * http://www.microsoft.com/globaldev/reference/cphome.mspx, + * + * and is used for the `DOS boxes', to support legacy applications. + * A German Windows version for example usually uses ANSI codepage + * 1252 and OEM codepage 850. + * + * FT_WinFNT_ID_CP874 :: + * A superset of Thai TIS 620 and ISO 8859-11. + * + * FT_WinFNT_ID_CP932 :: + * A superset of Japanese Shift-JIS (with minor deviations). + * + * FT_WinFNT_ID_CP936 :: + * A superset of simplified Chinese GB 2312-1980 (with different + * ordering and minor deviations). + * + * FT_WinFNT_ID_CP949 :: + * A superset of Korean Hangul KS C 5601-1987 (with different + * ordering and minor deviations). + * + * FT_WinFNT_ID_CP950 :: + * A superset of traditional Chinese Big 5 ETen (with different + * ordering and minor deviations). + * + * FT_WinFNT_ID_CP1250 :: + * A superset of East European ISO 8859-2 (with slightly different + * ordering). + * + * FT_WinFNT_ID_CP1251 :: + * A superset of Russian ISO 8859-5 (with different ordering). + * + * FT_WinFNT_ID_CP1252 :: + * ANSI encoding. A superset of ISO 8859-1. + * + * FT_WinFNT_ID_CP1253 :: + * A superset of Greek ISO 8859-7 (with minor modifications). + * + * FT_WinFNT_ID_CP1254 :: + * A superset of Turkish ISO 8859-9. + * + * FT_WinFNT_ID_CP1255 :: + * A superset of Hebrew ISO 8859-8 (with some modifications). + * + * FT_WinFNT_ID_CP1256 :: + * A superset of Arabic ISO 8859-6 (with different ordering). + * + * FT_WinFNT_ID_CP1257 :: + * A superset of Baltic ISO 8859-13 (with some deviations). + * + * FT_WinFNT_ID_CP1258 :: + * For Vietnamese. This encoding doesn't cover all necessary + * characters. + * + * FT_WinFNT_ID_CP1361 :: + * Korean (Johab). + */ + +#define FT_WinFNT_ID_CP1252 0 +#define FT_WinFNT_ID_DEFAULT 1 +#define FT_WinFNT_ID_SYMBOL 2 +#define FT_WinFNT_ID_MAC 77 +#define FT_WinFNT_ID_CP932 128 +#define FT_WinFNT_ID_CP949 129 +#define FT_WinFNT_ID_CP1361 130 +#define FT_WinFNT_ID_CP936 134 +#define FT_WinFNT_ID_CP950 136 +#define FT_WinFNT_ID_CP1253 161 +#define FT_WinFNT_ID_CP1254 162 +#define FT_WinFNT_ID_CP1258 163 +#define FT_WinFNT_ID_CP1255 177 +#define FT_WinFNT_ID_CP1256 178 +#define FT_WinFNT_ID_CP1257 186 +#define FT_WinFNT_ID_CP1251 204 +#define FT_WinFNT_ID_CP874 222 +#define FT_WinFNT_ID_CP1250 238 +#define FT_WinFNT_ID_OEM 255 + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_WinFNT_HeaderRec */ + /* */ + /* <Description> */ + /* Windows FNT Header info. */ + /* */ + typedef struct FT_WinFNT_HeaderRec_ + { + FT_UShort version; + FT_ULong file_size; + FT_Byte copyright[60]; + FT_UShort file_type; + FT_UShort nominal_point_size; + FT_UShort vertical_resolution; + FT_UShort horizontal_resolution; + FT_UShort ascent; + FT_UShort internal_leading; + FT_UShort external_leading; + FT_Byte italic; + FT_Byte underline; + FT_Byte strike_out; + FT_UShort weight; + FT_Byte charset; + FT_UShort pixel_width; + FT_UShort pixel_height; + FT_Byte pitch_and_family; + FT_UShort avg_width; + FT_UShort max_width; + FT_Byte first_char; + FT_Byte last_char; + FT_Byte default_char; + FT_Byte break_char; + FT_UShort bytes_per_row; + FT_ULong device_offset; + FT_ULong face_name_offset; + FT_ULong bits_pointer; + FT_ULong bits_offset; + FT_Byte reserved; + FT_ULong flags; + FT_UShort A_space; + FT_UShort B_space; + FT_UShort C_space; + FT_UShort color_table_offset; + FT_ULong reserved1[4]; + + } FT_WinFNT_HeaderRec, *FT_WinFNT_Header; + + + /********************************************************************** + * + * @function: + * FT_Get_WinFNT_Header + * + * @description: + * Retrieve a Windows FNT font info header. + * + * @input: + * face :: A handle to the input face. + * + * @output: + * aheader :: The WinFNT header. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * This function only works with Windows FNT faces, returning an error + * otherwise. + */ + FT_EXPORT( FT_Error ) + FT_Get_WinFNT_Header( FT_Face face, + FT_WinFNT_HeaderRec *aheader ); + + + /* */ + +FT_END_HEADER + +#endif /* __FTWINFNT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ftxf86.h b/Utilities/vtkfreetype/include/freetype/ftxf86.h new file mode 100644 index 0000000..3362883 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ftxf86.h @@ -0,0 +1,60 @@ +/***************************************************************************/ +/* */ +/* ftxf86.h */ +/* */ +/* Support functions for X11. */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTXF86_H__ +#define __FTXF86_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /* this comment is intentionally disabled for now, to prevent this */ + /* function from appearing in the API Reference. */ + + /*@***********************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_X11_Font_Format */ + /* */ + /* <Description> */ + /* Return a string describing the format of a given face as an X11 */ + /* FONT_PROPERTY. It should only be used by the FreeType 2 font */ + /* backend of the XFree86 font server. */ + /* */ + /* <Input> */ + /* face :: Input face handle. */ + /* */ + /* <Return> */ + /* Font format string. NULL in case of error. */ + /* */ + FT_EXPORT( const char* ) + FT_Get_X11_Font_Format( FT_Face face ); + + /* */ + +FT_END_HEADER + +#endif /* __FTXF86_H__ */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/autohint.h b/Utilities/vtkfreetype/include/freetype/internal/autohint.h new file mode 100644 index 0000000..22340af --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/autohint.h @@ -0,0 +1,205 @@ +/***************************************************************************/ +/* */ +/* autohint.h */ +/* */ +/* High-level `autohint' module-specific interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The auto-hinter is used to load and automatically hint glyphs if a */ + /* format-specific hinter isn't available. */ + /* */ + /*************************************************************************/ + + +#ifndef __AUTOHINT_H__ +#define __AUTOHINT_H__ + + + /*************************************************************************/ + /* */ + /* A small technical note regarding automatic hinting in order to */ + /* clarify this module interface. */ + /* */ + /* An automatic hinter might compute two kinds of data for a given face: */ + /* */ + /* - global hints: Usually some metrics that describe global properties */ + /* of the face. It is computed by scanning more or less */ + /* agressively the glyphs in the face, and thus can be */ + /* very slow to compute (even if the size of global */ + /* hints is really small). */ + /* */ + /* - glyph hints: These describe some important features of the glyph */ + /* outline, as well as how to align them. They are */ + /* generally much faster to compute than global hints. */ + /* */ + /* The current FreeType auto-hinter does a pretty good job while */ + /* performing fast computations for both global and glyph hints. */ + /* However, we might be interested in introducing more complex and */ + /* powerful algorithms in the future, like the one described in the John */ + /* D. Hobby paper, which unfortunately requires a lot more horsepower. */ + /* */ + /* Because a sufficiently sophisticated font management system would */ + /* typically implement an LRU cache of opened face objects to reduce */ + /* memory usage, it is a good idea to be able to avoid recomputing */ + /* global hints every time the same face is re-opened. */ + /* */ + /* We thus provide the ability to cache global hints outside of the face */ + /* object, in order to speed up font re-opening time. Of course, this */ + /* feature is purely optional, so most client programs won't even notice */ + /* it. */ + /* */ + /* I initially thought that it would be a good idea to cache the glyph */ + /* hints too. However, my general idea now is that if you really need */ + /* to cache these too, you are simply in need of a new font format, */ + /* where all this information could be stored within the font file and */ + /* decoded on the fly. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_FREETYPE_H + + +FT_BEGIN_HEADER + + + typedef struct FT_AutoHinterRec_ *FT_AutoHinter; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_AutoHinter_GlobalGetFunc */ + /* */ + /* <Description> */ + /* Retrieves the global hints computed for a given face object the */ + /* resulting data is dissociated from the face and will survive a */ + /* call to FT_Done_Face(). It must be discarded through the API */ + /* FT_AutoHinter_GlobalDoneFunc(). */ + /* */ + /* <Input> */ + /* hinter :: A handle to the source auto-hinter. */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* <Output> */ + /* global_hints :: A typeless pointer to the global hints. */ + /* */ + /* global_len :: The size in bytes of the global hints. */ + /* */ + typedef void + (*FT_AutoHinter_GlobalGetFunc)( FT_AutoHinter hinter, + FT_Face face, + void** global_hints, + long* global_len ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_AutoHinter_GlobalDoneFunc */ + /* */ + /* <Description> */ + /* Discards the global hints retrieved through */ + /* FT_AutoHinter_GlobalGetFunc(). This is the only way these hints */ + /* are freed from memory. */ + /* */ + /* <Input> */ + /* hinter :: A handle to the auto-hinter module. */ + /* */ + /* global :: A pointer to retrieved global hints to discard. */ + /* */ + typedef void + (*FT_AutoHinter_GlobalDoneFunc)( FT_AutoHinter hinter, + void* global ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_AutoHinter_GlobalResetFunc */ + /* */ + /* <Description> */ + /* This function is used to recompute the global metrics in a given */ + /* font. This is useful when global font data changes (e.g. Multiple */ + /* Masters fonts where blend coordinates change). */ + /* */ + /* <Input> */ + /* hinter :: A handle to the source auto-hinter. */ + /* */ + /* face :: A handle to the face. */ + /* */ + typedef void + (*FT_AutoHinter_GlobalResetFunc)( FT_AutoHinter hinter, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* FT_AutoHinter_GlyphLoadFunc */ + /* */ + /* <Description> */ + /* This function is used to load, scale, and automatically hint a */ + /* glyph from a given face. */ + /* */ + /* <Input> */ + /* face :: A handle to the face. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* load_flags :: The load flags. */ + /* */ + /* <Note> */ + /* This function is capable of loading composite glyphs by hinting */ + /* each sub-glyph independently (which improves quality). */ + /* */ + /* It will call the font driver with FT_Load_Glyph(), with */ + /* FT_LOAD_NO_SCALE set. */ + /* */ + typedef FT_Error + (*FT_AutoHinter_GlyphLoadFunc)( FT_AutoHinter hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_AutoHinter_ServiceRec */ + /* */ + /* <Description> */ + /* The auto-hinter module's interface. */ + /* */ + typedef struct FT_AutoHinter_ServiceRec_ + { + FT_AutoHinter_GlobalResetFunc reset_face; + FT_AutoHinter_GlobalGetFunc get_global_hints; + FT_AutoHinter_GlobalDoneFunc done_global_hints; + FT_AutoHinter_GlyphLoadFunc load_glyph; + + } FT_AutoHinter_ServiceRec, *FT_AutoHinter_Service; + + +FT_END_HEADER + +#endif /* __AUTOHINT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftcalc.h b/Utilities/vtkfreetype/include/freetype/internal/ftcalc.h new file mode 100644 index 0000000..7866c46 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftcalc.h @@ -0,0 +1,111 @@ +/***************************************************************************/ +/* */ +/* ftcalc.h */ +/* */ +/* Arithmetic computations (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTCALC_H__ +#define __FTCALC_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + + +FT_BEGIN_HEADER + + + FT_EXPORT( FT_Int32 ) + FT_SqrtFixed( FT_Int32 x ); + + +#define SQRT_32( x ) FT_Sqrt32( x ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Sqrt32 */ + /* */ + /* <Description> */ + /* Computes the square root of an Int32 integer (which will be */ + /* handled as an unsigned long value). */ + /* */ + /* <Input> */ + /* x :: The value to compute the root for. */ + /* */ + /* <Return> */ + /* The result of `sqrt(x)'. */ + /* */ + FT_EXPORT( FT_Int32 ) + FT_Sqrt32( FT_Int32 x ); + + + /*************************************************************************/ + /* */ + /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_MulDiv_No_Round */ + /* */ + /* <Description> */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* (without rounding) with maximal accuracy (it uses a 64-bit */ + /* intermediate integer whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* <Input> */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* <Return> */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + FT_BASE( FT_Long ) + FT_MulDiv_No_Round( FT_Long a, + FT_Long b, + FT_Long c ); + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + +#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) +#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) +#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) +#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 ) +#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) ) + +#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \ + : ( -( ( 32 - (x) ) & -64 ) ) ) + + +FT_END_HEADER + +#endif /* __FTCALC_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftdebug.h b/Utilities/vtkfreetype/include/freetype/internal/ftdebug.h new file mode 100644 index 0000000..ce142c5 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftdebug.h @@ -0,0 +1,244 @@ +/***************************************************************************/ +/* */ +/* ftdebug.h */ +/* */ +/* Debugging and logging component (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* */ +/* IMPORTANT: A description of FreeType's debugging support can be */ +/* found in "docs/DEBUG.TXT". Read it if you need to use or */ +/* understand this code. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTDEBUG_H__ +#define __FTDEBUG_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_FREETYPE_H + + +FT_BEGIN_HEADER + + + /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */ + /* is already defined; this simplifies the following #ifdefs */ + /* */ +#ifdef FT_DEBUG_LEVEL_TRACE +#undef FT_DEBUG_LEVEL_ERROR +#define FT_DEBUG_LEVEL_ERROR +#endif + + + /*************************************************************************/ + /* */ + /* Define the trace enums as well as the trace levels array when they */ + /* are needed. */ + /* */ + /*************************************************************************/ + +#ifdef FT_DEBUG_LEVEL_TRACE + +#define FT_TRACE_DEF( x ) trace_ ## x , + + /* defining the enumeration */ + typedef enum + { +#include FT_INTERNAL_TRACE_H + trace_count + + } FT_Trace; + + + /* defining the array of trace levels, provided by `src/base/ftdebug.c' */ + extern int ft_trace_levels[trace_count]; + +#undef FT_TRACE_DEF + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + + /*************************************************************************/ + /* */ + /* Define the FT_TRACE macro */ + /* */ + /* IMPORTANT! */ + /* */ + /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */ + /* value before using any TRACE macro. */ + /* */ + /*************************************************************************/ + +#ifdef FT_DEBUG_LEVEL_TRACE + +#define FT_TRACE( level, varformat ) \ + do \ + { \ + if ( ft_trace_levels[FT_COMPONENT] >= level ) \ + FT_Message varformat; \ + } while ( 0 ) + +#else /* !FT_DEBUG_LEVEL_TRACE */ + +#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */ + +#endif /* !FT_DEBUG_LEVEL_TRACE */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Trace_Get_Count */ + /* */ + /* <Description> */ + /* Return the number of available trace components. */ + /* */ + /* <Return> */ + /* The number of trace components. 0 if FreeType 2 is not built with */ + /* FT_DEBUG_LEVEL_TRACE definition. */ + /* */ + /* <Note> */ + /* This function may be useful if you want to access elements of */ + /* the internal `ft_trace_levels' array by an index. */ + /* */ + FT_EXPORT( FT_Int ) + FT_Trace_Get_Count( void ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Trace_Get_Name */ + /* */ + /* <Description> */ + /* Return the name of a trace component. */ + /* */ + /* <Input> */ + /* The index of the trace component. */ + /* */ + /* <Return> */ + /* The name of the trace component. This is a statically allocated */ + /* C string, so do not free it after use. NULL if FreeType 2 is not */ + /* built with FT_DEBUG_LEVEL_TRACE definition. */ + /* */ + /* <Note> */ + /* Use @FT_Trace_Get_Count to get the number of available trace */ + /* components. */ + /* */ + /* This function may be useful if you want to control FreeType 2's */ + /* debug level in your appliaciton. */ + /* */ + FT_EXPORT( const char * ) + FT_Trace_Get_Name( FT_Int idx ); + + + /*************************************************************************/ + /* */ + /* You need two opening resp. closing parentheses! */ + /* */ + /* Example: FT_TRACE0(( "Value is %i", foo )) */ + /* */ + /*************************************************************************/ + +#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat ) +#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat ) +#define FT_TRACE2( varformat ) FT_TRACE( 2, varformat ) +#define FT_TRACE3( varformat ) FT_TRACE( 3, varformat ) +#define FT_TRACE4( varformat ) FT_TRACE( 4, varformat ) +#define FT_TRACE5( varformat ) FT_TRACE( 5, varformat ) +#define FT_TRACE6( varformat ) FT_TRACE( 6, varformat ) +#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat ) + + + /*************************************************************************/ + /* */ + /* Define the FT_ERROR macro */ + /* */ + /*************************************************************************/ + +#ifdef FT_DEBUG_LEVEL_ERROR + +#define FT_ERROR( varformat ) FT_Message varformat + +#else /* !FT_DEBUG_LEVEL_ERROR */ + +#define FT_ERROR( varformat ) do ; while ( 0 ) /* nothing */ + +#endif /* !FT_DEBUG_LEVEL_ERROR */ + + + /*************************************************************************/ + /* */ + /* Define the FT_ASSERT macro */ + /* */ + /*************************************************************************/ + +#ifdef FT_DEBUG_LEVEL_ERROR + +#define FT_ASSERT( condition ) \ + do \ + { \ + if ( !( condition ) ) \ + FT_Panic( "assertion failed on line %d of file %s\n", \ + __LINE__, __FILE__ ); \ + } while ( 0 ) + +#else /* !FT_DEBUG_LEVEL_ERROR */ + +#define FT_ASSERT( condition ) do ; while ( 0 ) + +#endif /* !FT_DEBUG_LEVEL_ERROR */ + + + /*************************************************************************/ + /* */ + /* Define 'FT_Message' and 'FT_Panic' when needed */ + /* */ + /*************************************************************************/ + +#ifdef FT_DEBUG_LEVEL_ERROR + +#include "stdio.h" /* for vprintf() */ + + /* print a message */ + FT_EXPORT( void ) + FT_Message( const char* fmt, ... ); + + /* print a message and exit */ + FT_EXPORT( void ) + FT_Panic( const char* fmt, ... ); + +#endif /* FT_DEBUG_LEVEL_ERROR */ + + + FT_BASE( void ) + ft_debug_init( void ); + + +#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ + + /* we disable the warning `conditional expression is constant' here */ + /* in order to compile cleanly with the maximum level of warnings */ +#pragma warning( disable : 4127 ) + +#endif /* _MSC_VER */ + + +FT_END_HEADER + +#endif /* __FTDEBUG_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftdriver.h b/Utilities/vtkfreetype/include/freetype/internal/ftdriver.h new file mode 100644 index 0000000..02f585d --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftdriver.h @@ -0,0 +1,206 @@ +/***************************************************************************/ +/* */ +/* ftdriver.h */ +/* */ +/* FreeType font driver interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTDRIVER_H__ +#define __FTDRIVER_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + typedef FT_Error + (*FT_Face_InitFunc)( FT_Stream stream, + FT_Face face, + FT_Int typeface_index, + FT_Int num_params, + FT_Parameter* parameters ); + + typedef void + (*FT_Face_DoneFunc)( FT_Face face ); + + + typedef FT_Error + (*FT_Size_InitFunc)( FT_Size size ); + + typedef void + (*FT_Size_DoneFunc)( FT_Size size ); + + + typedef FT_Error + (*FT_Slot_InitFunc)( FT_GlyphSlot slot ); + + typedef void + (*FT_Slot_DoneFunc)( FT_GlyphSlot slot ); + + + typedef FT_Error + (*FT_Size_ResetPointsFunc)( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + typedef FT_Error + (*FT_Size_ResetPixelsFunc)( FT_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + typedef FT_Error + (*FT_Slot_LoadFunc)( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + + typedef FT_UInt + (*FT_CharMap_CharIndexFunc)( FT_CharMap charmap, + FT_Long charcode ); + + typedef FT_Long + (*FT_CharMap_CharNextFunc)( FT_CharMap charmap, + FT_Long charcode ); + + typedef FT_Error + (*FT_Face_GetKerningFunc)( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ); + + + typedef FT_Error + (*FT_Face_AttachFunc)( FT_Face face, + FT_Stream stream ); + + + typedef FT_Error + (*FT_Face_GetAdvancesFunc)( FT_Face face, + FT_UInt first, + FT_UInt count, + FT_Bool vertical, + FT_UShort* advances ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Driver_ClassRec */ + /* */ + /* <Description> */ + /* The font driver class. This structure mostly contains pointers to */ + /* driver methods. */ + /* */ + /* <Fields> */ + /* root :: The parent module. */ + /* */ + /* face_object_size :: The size of a face object in bytes. */ + /* */ + /* size_object_size :: The size of a size object in bytes. */ + /* */ + /* slot_object_size :: The size of a glyph object in bytes. */ + /* */ + /* init_face :: The format-specific face constructor. */ + /* */ + /* done_face :: The format-specific face destructor. */ + /* */ + /* init_size :: The format-specific size constructor. */ + /* */ + /* done_size :: The format-specific size destructor. */ + /* */ + /* init_slot :: The format-specific slot constructor. */ + /* */ + /* done_slot :: The format-specific slot destructor. */ + /* */ + /* set_char_sizes :: A handle to a function used to set the new */ + /* character size in points + resolution. Can be */ + /* set to 0 to indicate default behaviour. */ + /* */ + /* set_pixel_sizes :: A handle to a function used to set the new */ + /* character size in pixels. Can be set to 0 to */ + /* indicate default behaviour. */ + /* */ + /* load_glyph :: A function handle to load a given glyph image */ + /* in a slot. This field is mandatory! */ + /* */ + /* get_char_index :: A function handle to return the glyph index of */ + /* a given character for a given charmap. This */ + /* field is mandatory! */ + /* */ + /* get_kerning :: A function handle to return the unscaled */ + /* kerning for a given pair of glyphs. Can be */ + /* set to 0 if the format doesn't support */ + /* kerning. */ + /* */ + /* attach_file :: This function handle is used to read */ + /* additional data for a face from another */ + /* file/stream. For example, this can be used to */ + /* add data from AFM or PFM files on a Type 1 */ + /* face, or a CIDMap on a CID-keyed face. */ + /* */ + /* get_advances :: A function handle used to return advance */ + /* widths of 'count' glyphs (in font units), */ + /* starting at `first'. The `vertical' flag must */ + /* be set to get vertical advance heights. The */ + /* `advances' buffer is caller-allocated. */ + /* Currently not implemented. The idea of this */ + /* function is to be able to perform */ + /* device-independent text layout without loading */ + /* a single glyph image. */ + /* */ + /* <Note> */ + /* Most function pointers, with the exception of `load_glyph' and */ + /* `get_char_index' can be set to 0 to indicate a default behaviour. */ + /* */ + typedef struct FT_Driver_ClassRec_ + { + FT_Module_Class root; + + FT_Long face_object_size; + FT_Long size_object_size; + FT_Long slot_object_size; + + FT_Face_InitFunc init_face; + FT_Face_DoneFunc done_face; + + FT_Size_InitFunc init_size; + FT_Size_DoneFunc done_size; + + FT_Slot_InitFunc init_slot; + FT_Slot_DoneFunc done_slot; + + FT_Size_ResetPointsFunc set_char_sizes; + FT_Size_ResetPixelsFunc set_pixel_sizes; + + FT_Slot_LoadFunc load_glyph; + + FT_Face_GetKerningFunc get_kerning; + FT_Face_AttachFunc attach_file; + FT_Face_GetAdvancesFunc get_advances; + + } FT_Driver_ClassRec, *FT_Driver_Class; + + +FT_END_HEADER + +#endif /* __FTDRIVER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftgloadr.h b/Utilities/vtkfreetype/include/freetype/internal/ftgloadr.h new file mode 100644 index 0000000..abc56e2 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftgloadr.h @@ -0,0 +1,147 @@ +/***************************************************************************/ +/* */ +/* ftgloadr.h */ +/* */ +/* The FreeType glyph loader (specification). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTGLOADR_H__ +#define __FTGLOADR_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_GlyphLoader */ + /* */ + /* <Description> */ + /* The glyph loader is an internal object used to load several glyphs */ + /* together (for example, in the case of composites). */ + /* */ + /* <Note> */ + /* The glyph loader implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_GlyphLoaderRec_* FT_GlyphLoader ; + + +#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 +#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 +#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 +#define FT_SUBGLYPH_FLAG_SCALE 8 +#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 +#define FT_SUBGLYPH_FLAG_2X2 0x80 +#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 + + + typedef struct FT_SubGlyphRec_ + { + FT_Int index; + FT_UShort flags; + FT_Int arg1; + FT_Int arg2; + FT_Matrix transform; + + } FT_SubGlyphRec; + + + typedef struct FT_GlyphLoadRec_ + { + FT_Outline outline; /* outline */ + FT_Vector* extra_points; /* extra points table */ + FT_UInt num_subglyphs; /* number of subglyphs */ + FT_SubGlyph subglyphs; /* subglyphs */ + + } FT_GlyphLoadRec, *FT_GlyphLoad; + + + typedef struct FT_GlyphLoaderRec_ + { + FT_Memory memory; + FT_UInt max_points; + FT_UInt max_contours; + FT_UInt max_subglyphs; + FT_Bool use_extra; + + FT_GlyphLoadRec base; + FT_GlyphLoadRec current; + + void* other; /* for possible future extension? */ + + } FT_GlyphLoaderRec; + + + /* create new empty glyph loader */ + FT_BASE( FT_Error ) + FT_GlyphLoader_New( FT_Memory memory, + FT_GlyphLoader *aloader ); + + /* add an extra points table to a glyph loader */ + FT_BASE( FT_Error ) + FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader ); + + /* destroy a glyph loader */ + FT_BASE( void ) + FT_GlyphLoader_Done( FT_GlyphLoader loader ); + + /* reset a glyph loader (frees everything int it) */ + FT_BASE( void ) + FT_GlyphLoader_Reset( FT_GlyphLoader loader ); + + /* rewind a glyph loader */ + FT_BASE( void ) + FT_GlyphLoader_Rewind( FT_GlyphLoader loader ); + + /* check that there is enough space to add `n_points' and `n_contours' */ + /* to the glyph loader */ + FT_BASE( FT_Error ) + FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, + FT_UInt n_points, + FT_UInt n_contours ); + + /* check that there is enough space to add `n_subs' sub-glyphs to */ + /* a glyph loader */ + FT_BASE( FT_Error ) + FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, + FT_UInt n_subs ); + + /* prepare a glyph loader, i.e. empty the current glyph */ + FT_BASE( void ) + FT_GlyphLoader_Prepare( FT_GlyphLoader loader ); + + /* add the current glyph to the base glyph */ + FT_BASE( void ) + FT_GlyphLoader_Add( FT_GlyphLoader loader ); + + /* copy points from one glyph loader to another */ + FT_BASE( FT_Error ) + FT_GlyphLoader_CopyPoints( FT_GlyphLoader target, + FT_GlyphLoader source ); + + /* */ + + +FT_END_HEADER + +#endif /* __FTGLOADR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftmemory.h b/Utilities/vtkfreetype/include/freetype/internal/ftmemory.h new file mode 100644 index 0000000..ea9870f --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftmemory.h @@ -0,0 +1,367 @@ +/***************************************************************************/ +/* */ +/* ftmemory.h */ +/* */ +/* The FreeType memory management macros (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTMEMORY_H__ +#define __FTMEMORY_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_TYPES_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Macro> */ + /* FT_SET_ERROR */ + /* */ + /* <Description> */ + /* This macro is used to set an implicit `error' variable to a given */ + /* expression's value (usually a function call), and convert it to a */ + /* boolean which is set whenever the value is != 0. */ + /* */ +#undef FT_SET_ERROR +#define FT_SET_ERROR( expression ) \ + ( ( error = (expression) ) != 0 ) + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M E M O R Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + +#ifdef FT_DEBUG_MEMORY + + FT_BASE( FT_Error ) + FT_Alloc_Debug( FT_Memory memory, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ); + + FT_BASE( FT_Error ) + FT_QAlloc_Debug( FT_Memory memory, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ); + + FT_BASE( FT_Error ) + FT_Realloc_Debug( FT_Memory memory, + FT_Long current, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ); + + FT_BASE( FT_Error ) + FT_QRealloc_Debug( FT_Memory memory, + FT_Long current, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ); + + FT_BASE( void ) + FT_Free_Debug( FT_Memory memory, + FT_Pointer block, + const char* file_name, + FT_Long line_no ); + +#endif + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Alloc */ + /* */ + /* <Description> */ + /* Allocates a new block of memory. The returned area is always */ + /* zero-filled; this is a strong convention in many FreeType parts. */ + /* */ + /* <Input> */ + /* memory :: A handle to a given `memory object' which handles */ + /* allocation. */ + /* */ + /* size :: The size in bytes of the block to allocate. */ + /* */ + /* <Output> */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_BASE( FT_Error ) + FT_Alloc( FT_Memory memory, + FT_Long size, + void* *P ); + + + FT_BASE( FT_Error ) + FT_QAlloc( FT_Memory memory, + FT_Long size, + void* *p ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Realloc */ + /* */ + /* <Description> */ + /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */ + /* from the heap, possibly changing `*P'. */ + /* */ + /* <Input> */ + /* memory :: A handle to a given `memory object' which handles */ + /* reallocation. */ + /* */ + /* current :: The current block size in bytes. */ + /* */ + /* size :: The new block size in bytes. */ + /* */ + /* <InOut> */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* All callers of FT_Realloc() _must_ provide the current block size */ + /* as well as the new one. */ + /* */ + FT_BASE( FT_Error ) + FT_Realloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void* *P ); + + + FT_BASE( FT_Error ) + FT_QRealloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void* *p ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Free */ + /* */ + /* <Description> */ + /* Releases a given block of memory allocated through FT_Alloc(). */ + /* */ + /* <Input> */ + /* memory :: A handle to a given `memory object' which handles */ + /* memory deallocation */ + /* */ + /* P :: This is the _address_ of a _pointer_ which points to the */ + /* allocated block. It is always set to NULL on exit. */ + /* */ + /* <Note> */ + /* If P or *P is NULL, this function should return successfully. */ + /* This is a strong convention within all of FreeType and its */ + /* drivers. */ + /* */ + FT_BASE( void ) + FT_Free( FT_Memory memory, + void* *P ); + + +#define FT_MEM_SET( dest, byte, count ) ft_memset( dest, byte, count ) + +#define FT_MEM_COPY( dest, source, count ) ft_memcpy( dest, source, count ) + +#define FT_MEM_MOVE( dest, source, count ) ft_memmove( dest, source, count ) + + +#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count ) + +#define FT_ZERO( p ) FT_MEM_ZERO( p, sizeof ( *(p) ) ) + +#define FT_ARRAY_COPY( dest, source, count ) \ + FT_MEM_COPY( dest, source, (count) * sizeof( *(dest) ) ) + +#define FT_ARRAY_MOVE( dest, source, count ) \ + FT_MEM_MOVE( dest, source, (count) * sizeof( *(dest) ) ) + + + /*************************************************************************/ + /* */ + /* We first define FT_MEM_ALLOC, FT_MEM_REALLOC, and FT_MEM_FREE. All */ + /* macros use an _implicit_ `memory' parameter to access the current */ + /* memory allocator. */ + /* */ + +#ifdef FT_DEBUG_MEMORY + +#define FT_MEM_ALLOC( _pointer_, _size_ ) \ + FT_Alloc_Debug( memory, _size_, \ + (void**)&(_pointer_), __FILE__, __LINE__ ) + +#define FT_MEM_REALLOC( _pointer_, _current_, _size_ ) \ + FT_Realloc_Debug( memory, _current_, _size_, \ + (void**)&(_pointer_), __FILE__, __LINE__ ) + +#define FT_MEM_QALLOC( _pointer_, _size_ ) \ + FT_QAlloc_Debug( memory, _size_, \ + (void**)&(_pointer_), __FILE__, __LINE__ ) + +#define FT_MEM_QREALLOC( _pointer_, _current_, _size_ ) \ + FT_QRealloc_Debug( memory, _current_, _size_, \ + (void**)&(_pointer_), __FILE__, __LINE__ ) + +#define FT_MEM_FREE( _pointer_ ) \ + FT_Free_Debug( memory, (void**)&(_pointer_), __FILE__, __LINE__ ) + + +#else /* !FT_DEBUG_MEMORY */ + + +#define FT_MEM_ALLOC( _pointer_, _size_ ) \ + FT_Alloc( memory, _size_, (void**)&(_pointer_) ) + +#define FT_MEM_FREE( _pointer_ ) \ + FT_Free( memory, (void**)&(_pointer_) ) + +#define FT_MEM_REALLOC( _pointer_, _current_, _size_ ) \ + FT_Realloc( memory, _current_, _size_, (void**)&(_pointer_) ) + +#define FT_MEM_QALLOC( _pointer_, _size_ ) \ + FT_QAlloc( memory, _size_, (void**)&(_pointer_) ) + +#define FT_MEM_QREALLOC( _pointer_, _current_, _size_ ) \ + FT_QRealloc( memory, _current_, _size_, (void**)&(_pointer_) ) + +#endif /* !FT_DEBUG_MEMORY */ + + + /*************************************************************************/ + /* */ + /* The following functions macros expect that their pointer argument is */ + /* _typed_ in order to automatically compute array element sizes. */ + /* */ + +#define FT_MEM_NEW( _pointer_ ) \ + FT_MEM_ALLOC( _pointer_, sizeof ( *(_pointer_) ) ) + +#define FT_MEM_NEW_ARRAY( _pointer_, _count_ ) \ + FT_MEM_ALLOC( _pointer_, (_count_) * sizeof ( *(_pointer_) ) ) + +#define FT_MEM_RENEW_ARRAY( _pointer_, _old_, _new_ ) \ + FT_MEM_REALLOC( _pointer_, (_old_) * sizeof ( *(_pointer_) ), \ + (_new_) * sizeof ( *(_pointer_) ) ) + +#define FT_MEM_QNEW( _pointer_ ) \ + FT_MEM_QALLOC( _pointer_, sizeof ( *(_pointer_) ) ) + +#define FT_MEM_QNEW_ARRAY( _pointer_, _count_ ) \ + FT_MEM_QALLOC( _pointer_, (_count_) * sizeof ( *(_pointer_) ) ) + +#define FT_MEM_QRENEW_ARRAY( _pointer_, _old_, _new_ ) \ + FT_MEM_QREALLOC( _pointer_, (_old_) * sizeof ( *(_pointer_) ), \ + (_new_) * sizeof ( *(_pointer_) ) ) + + + /*************************************************************************/ + /* */ + /* the following macros are obsolete but kept for compatibility reasons */ + /* */ + +#define FT_MEM_ALLOC_ARRAY( _pointer_, _count_, _type_ ) \ + FT_MEM_ALLOC( _pointer_, (_count_) * sizeof ( _type_ ) ) + +#define FT_MEM_REALLOC_ARRAY( _pointer_, _old_, _new_, _type_ ) \ + FT_MEM_REALLOC( _pointer_, (_old_) * sizeof ( _type ), \ + (_new_) * sizeof ( _type_ ) ) + + + /*************************************************************************/ + /* */ + /* The following macros are variants of their FT_MEM_XXXX equivalents; */ + /* they are used to set an _implicit_ `error' variable and return TRUE */ + /* if an error occured (i.e. if 'error != 0'). */ + /* */ + +#define FT_ALLOC( _pointer_, _size_ ) \ + FT_SET_ERROR( FT_MEM_ALLOC( _pointer_, _size_ ) ) + +#define FT_REALLOC( _pointer_, _current_, _size_ ) \ + FT_SET_ERROR( FT_MEM_REALLOC( _pointer_, _current_, _size_ ) ) + +#define FT_FREE( _pointer_ ) \ + FT_MEM_FREE( _pointer_ ) + +#define FT_QALLOC( _pointer_, _size_ ) \ + FT_SET_ERROR( FT_MEM_QALLOC( _pointer_, _size_ ) ) + +#define FT_QREALLOC( _pointer_, _current_, _size_ ) \ + FT_SET_ERROR( FT_MEM_QREALLOC( _pointer_, _current_, _size_ ) ) + + +#define FT_NEW( _pointer_ ) \ + FT_SET_ERROR( FT_MEM_NEW( _pointer_ ) ) + +#define FT_NEW_ARRAY( _pointer_, _count_ ) \ + FT_SET_ERROR( FT_MEM_NEW_ARRAY( _pointer_, _count_ ) ) + +#define FT_RENEW_ARRAY( _pointer_, _old_, _new_ ) \ + FT_SET_ERROR( FT_MEM_RENEW_ARRAY( _pointer_, _old_, _new_ ) ) + +#define FT_QNEW( _pointer_ ) \ + FT_SET_ERROR( FT_MEM_QNEW( _pointer_ ) ) + +#define FT_QNEW_ARRAY( _pointer_, _count_ ) \ + FT_SET_ERROR( FT_MEM_QNEW_ARRAY( _pointer_, _count_ ) ) + +#define FT_QRENEW_ARRAY( _pointer_, _old_, _new_ ) \ + FT_SET_ERROR( FT_MEM_QRENEW_ARRAY( _pointer_, _old_, _new_ ) ) + + +#define FT_ALLOC_ARRAY( _pointer_, _count_, _type_ ) \ + FT_SET_ERROR( FT_MEM_ALLOC( _pointer_, \ + (_count_) * sizeof ( _type_ ) ) ) + +#define FT_REALLOC_ARRAY( _pointer_, _old_, _new_, _type_ ) \ + FT_SET_ERROR( FT_MEM_REALLOC( _pointer_, \ + (_old_) * sizeof ( _type_ ), \ + (_new_) * sizeof ( _type_ ) ) ) + + /* */ + + +FT_END_HEADER + +#endif /* __FTMEMORY_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftobjs.h b/Utilities/vtkfreetype/include/freetype/internal/ftobjs.h new file mode 100644 index 0000000..3a28119 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftobjs.h @@ -0,0 +1,847 @@ +/***************************************************************************/ +/* */ +/* ftobjs.h */ +/* */ +/* The FreeType private base classes (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file contains the definition of all internal FreeType classes. */ + /* */ + /*************************************************************************/ + + +#ifndef __FTOBJS_H__ +#define __FTOBJS_H__ + +#include <ft2build.h> +#include FT_CONFIG_STANDARD_LIBRARY_H /* for ft_setjmp and ft_longjmp */ +#include FT_RENDER_H +#include FT_SIZES_H +#include FT_INTERNAL_MEMORY_H +#include FT_INTERNAL_GLYPH_LOADER_H +#include FT_INTERNAL_DRIVER_H +#include FT_INTERNAL_AUTOHINT_H +#include FT_INTERNAL_SERVICE_H + +#ifdef FT_CONFIG_OPTION_INCREMENTAL +#include FT_INCREMENTAL_H +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* Some generic definitions. */ + /* */ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + + + /*************************************************************************/ + /* */ + /* The min and max functions missing in C. As usual, be careful not to */ + /* write things like FT_MIN( a++, b++ ) to avoid side effects. */ + /* */ +#define FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) ) +#define FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) ) + +#define FT_ABS( a ) ( (a) < 0 ? -(a) : (a) ) + + +#define FT_PAD_FLOOR( x, n ) ( (x) & ~((n)-1) ) +#define FT_PAD_ROUND( x, n ) FT_PAD_FLOOR( (x) + ((n)/2), n ) +#define FT_PAD_CEIL( x, n ) FT_PAD_FLOOR( (x) + ((n)-1), n ) + +#define FT_PIX_FLOOR( x ) ( (x) & ~63 ) +#define FT_PIX_ROUND( x ) FT_PIX_FLOOR( (x) + 32 ) +#define FT_PIX_CEIL( x ) FT_PIX_FLOOR( (x) + 63 ) + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** V A L I D A T I O N ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* handle to a validation object */ + typedef struct FT_ValidatorRec_* FT_Validator; + + + /*************************************************************************/ + /* */ + /* There are three distinct validation levels defined here: */ + /* */ + /* FT_VALIDATE_DEFAULT :: */ + /* A table that passes this validation level can be used reliably by */ + /* FreeType. It generally means that all offsets have been checked to */ + /* prevent out-of-bound reads, array counts are correct, etc. */ + /* */ + /* FT_VALIDATE_TIGHT :: */ + /* A table that passes this validation level can be used reliably and */ + /* doesn't contain invalid data. For example, a charmap table that */ + /* returns invalid glyph indices will not pass, even though it can */ + /* be used with FreeType in default mode (the library will simply */ + /* return an error later when trying to load the glyph). */ + /* */ + /* It also check that fields that must be a multiple of 2, 4, or 8 */ + /* don't have incorrect values, etc. */ + /* */ + /* FT_VALIDATE_PARANOID :: */ + /* Only for font debugging. Checks that a table follows the */ + /* specification by 100%. Very few fonts will be able to pass this */ + /* level anyway but it can be useful for certain tools like font */ + /* editors/converters. */ + /* */ + typedef enum FT_ValidationLevel_ + { + FT_VALIDATE_DEFAULT = 0, + FT_VALIDATE_TIGHT, + FT_VALIDATE_PARANOID + + } FT_ValidationLevel; + + + /* validator structure */ + typedef struct FT_ValidatorRec_ + { + const FT_Byte* base; /* address of table in memory */ + const FT_Byte* limit; /* `base' + sizeof(table) in memory */ + FT_ValidationLevel level; /* validation level */ + FT_Error error; /* error returned. 0 means success */ + + ft_jmp_buf jump_buffer; /* used for exception handling */ + + } FT_ValidatorRec; + + +#define FT_VALIDATOR( x ) ((FT_Validator)( x )) + + + FT_BASE( void ) + ft_validator_init( FT_Validator valid, + const FT_Byte* base, + const FT_Byte* limit, + FT_ValidationLevel level ); + + FT_BASE( FT_Int ) + ft_validator_run( FT_Validator valid ); + + /* Sets the error field in a validator, then calls `longjmp' to return */ + /* to high-level caller. Using `setjmp/longjmp' avoids many stupid */ + /* error checks within the validation routines. */ + /* */ + FT_BASE( void ) + ft_validator_error( FT_Validator valid, + FT_Error error ); + + + /* Calls ft_validate_error. Assumes that the `valid' local variable */ + /* holds a pointer to the current validator object. */ + /* */ +#define FT_INVALID( _error ) ft_validator_error( valid, _error ) + + /* called when a broken table is detected */ +#define FT_INVALID_TOO_SHORT FT_INVALID( FT_Err_Invalid_Table ) + + /* called when an invalid offset is detected */ +#define FT_INVALID_OFFSET FT_INVALID( FT_Err_Invalid_Offset ) + + /* called when an invalid format/value is detected */ +#define FT_INVALID_FORMAT FT_INVALID( FT_Err_Invalid_Table ) + + /* called when an invalid glyph index is detected */ +#define FT_INVALID_GLYPH_ID FT_INVALID( FT_Err_Invalid_Glyph_Index ) + + /* called when an invalid field value is detected */ +#define FT_INVALID_DATA FT_INVALID( FT_Err_Invalid_Table ) + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** C H A R M A P S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* handle to internal charmap object */ + typedef struct FT_CMapRec_* FT_CMap; + + /* handle to charmap class structure */ + typedef const struct FT_CMap_ClassRec_* FT_CMap_Class; + + /* internal charmap object structure */ + typedef struct FT_CMapRec_ + { + FT_CharMapRec charmap; + FT_CMap_Class clazz; + + } FT_CMapRec; + + /* typecase any pointer to a charmap handle */ +#define FT_CMAP( x ) ((FT_CMap)( x )) + + /* obvious macros */ +#define FT_CMAP_PLATFORM_ID( x ) FT_CMAP( x )->charmap.platform_id +#define FT_CMAP_ENCODING_ID( x ) FT_CMAP( x )->charmap.encoding_id +#define FT_CMAP_ENCODING( x ) FT_CMAP( x )->charmap.encoding +#define FT_CMAP_FACE( x ) FT_CMAP( x )->charmap.face + + + /* class method definitions */ + typedef FT_Error + (*FT_CMap_InitFunc)( FT_CMap cmap, + FT_Pointer init_data ); + + typedef void + (*FT_CMap_DoneFunc)( FT_CMap cmap ); + + typedef FT_UInt + (*FT_CMap_CharIndexFunc)( FT_CMap cmap, + FT_UInt32 char_code ); + + typedef FT_UInt + (*FT_CMap_CharNextFunc)( FT_CMap cmap, + FT_UInt32 *achar_code ); + + + typedef struct FT_CMap_ClassRec_ + { + FT_ULong size; + FT_CMap_InitFunc init; + FT_CMap_DoneFunc done; + FT_CMap_CharIndexFunc char_index; + FT_CMap_CharNextFunc char_next; + + } FT_CMap_ClassRec; + + + /* create a new charmap and add it to charmap->face */ + FT_BASE( FT_Error ) + FT_CMap_New( FT_CMap_Class clazz, + FT_Pointer init_data, + FT_CharMap charmap, + FT_CMap *acmap ); + + /* destroy a charmap (don't remove it from face's list though) */ + FT_BASE( void ) + FT_CMap_Done( FT_CMap cmap ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Face_InternalRec */ + /* */ + /* <Description> */ + /* This structure contains the internal fields of each FT_Face */ + /* object. These fields may change between different releases of */ + /* FreeType. */ + /* */ + /* <Fields> */ + /* max_points :: */ + /* The maximal number of points used to store the vectorial outline */ + /* of any glyph in this face. If this value cannot be known in */ + /* advance, or if the face isn't scalable, this should be set to 0. */ + /* Only relevant for scalable formats. */ + /* */ + /* max_contours :: */ + /* The maximal number of contours used to store the vectorial */ + /* outline of any glyph in this face. If this value cannot be */ + /* known in advance, or if the face isn't scalable, this should be */ + /* set to 0. Only relevant for scalable formats. */ + /* */ + /* transform_matrix :: */ + /* A 2x2 matrix of 16.16 coefficients used to transform glyph */ + /* outlines after they are loaded from the font. Only used by the */ + /* convenience functions. */ + /* */ + /* transform_delta :: */ + /* A translation vector used to transform glyph outlines after they */ + /* are loaded from the font. Only used by the convenience */ + /* functions. */ + /* */ + /* transform_flags :: */ + /* Some flags used to classify the transform. Only used by the */ + /* convenience functions. */ + /* */ + /* services :: */ + /* A cache for frequently used services. It should be only */ + /* accessed with the macro `FT_FACE_LOOKUP_SERVICE'. */ + /* */ + /* incremental_interface :: */ + /* If non-null, the interface through which glyph data and metrics */ + /* are loaded incrementally for faces that do not provide all of */ + /* this data when first opened. This field exists only if */ + /* @FT_CONFIG_OPTION_INCREMENTAL is defined. */ + /* */ + typedef struct FT_Face_InternalRec_ + { + FT_UShort max_points; + FT_Short max_contours; + + FT_Matrix transform_matrix; + FT_Vector transform_delta; + FT_Int transform_flags; + + FT_ServiceCacheRec services; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + FT_Incremental_InterfaceRec* incremental_interface; +#endif + + } FT_Face_InternalRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_Slot_InternalRec */ + /* */ + /* <Description> */ + /* This structure contains the internal fields of each FT_GlyphSlot */ + /* object. These fields may change between different releases of */ + /* FreeType. */ + /* */ + /* <Fields> */ + /* loader :: The glyph loader object used to load outlines */ + /* into the glyph slot. */ + /* */ + /* flags :: Possible values are zero or */ + /* FT_GLYPH_OWN_BITMAP. The latter indicates */ + /* that the FT_GlyphSlot structure owns the */ + /* bitmap buffer. */ + /* */ + /* glyph_transformed :: Boolean. Set to TRUE when the loaded glyph */ + /* must be transformed through a specific */ + /* font transformation. This is _not_ the same */ + /* as the face transform set through */ + /* FT_Set_Transform(). */ + /* */ + /* glyph_matrix :: The 2x2 matrix corresponding to the glyph */ + /* transformation, if necessary. */ + /* */ + /* glyph_delta :: The 2d translation vector corresponding to */ + /* the glyph transformation, if necessary. */ + /* */ + /* glyph_hints :: Format-specific glyph hints management. */ + /* */ + +#define FT_GLYPH_OWN_BITMAP 0x1 + + typedef struct FT_Slot_InternalRec_ + { + FT_GlyphLoader loader; + FT_UInt flags; + FT_Bool glyph_transformed; + FT_Matrix glyph_matrix; + FT_Vector glyph_delta; + void* glyph_hints; + + } FT_GlyphSlot_InternalRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M O D U L E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_ModuleRec */ + /* */ + /* <Description> */ + /* A module object instance. */ + /* */ + /* <Fields> */ + /* clazz :: A pointer to the module's class. */ + /* */ + /* library :: A handle to the parent library object. */ + /* */ + /* memory :: A handle to the memory manager. */ + /* */ + /* generic :: A generic structure for user-level extensibility (?). */ + /* */ + typedef struct FT_ModuleRec_ + { + FT_Module_Class* clazz; + FT_Library library; + FT_Memory memory; + FT_Generic generic; + + } FT_ModuleRec; + + + /* typecast an object to a FT_Module */ +#define FT_MODULE( x ) ((FT_Module)( x )) +#define FT_MODULE_CLASS( x ) FT_MODULE( x )->clazz +#define FT_MODULE_LIBRARY( x ) FT_MODULE( x )->library +#define FT_MODULE_MEMORY( x ) FT_MODULE( x )->memory + + +#define FT_MODULE_IS_DRIVER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + FT_MODULE_FONT_DRIVER ) + +#define FT_MODULE_IS_RENDERER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + FT_MODULE_RENDERER ) + +#define FT_MODULE_IS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + FT_MODULE_HINTER ) + +#define FT_MODULE_IS_STYLER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + FT_MODULE_STYLER ) + +#define FT_DRIVER_IS_SCALABLE( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + FT_MODULE_DRIVER_SCALABLE ) + +#define FT_DRIVER_USES_OUTLINES( x ) !( FT_MODULE_CLASS( x )->module_flags & \ + FT_MODULE_DRIVER_NO_OUTLINES ) + +#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + FT_MODULE_DRIVER_HAS_HINTER ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Module_Interface */ + /* */ + /* <Description> */ + /* Finds a module and returns its specific interface as a typeless */ + /* pointer. */ + /* */ + /* <Input> */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* <Return> */ + /* A module-specific interface if available, 0 otherwise. */ + /* */ + /* <Note> */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for, and what its interface is :-) */ + /* */ + FT_BASE( const void* ) + FT_Get_Module_Interface( FT_Library library, + const char* mod_name ); + + FT_BASE( FT_Pointer ) + ft_module_get_service( FT_Module module, + const char* service_id ); + + /* */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* a few macros used to perform easy typecasts with minimal brain damage */ + +#define FT_FACE( x ) ((FT_Face)(x)) +#define FT_SIZE( x ) ((FT_Size)(x)) +#define FT_SLOT( x ) ((FT_GlyphSlot)(x)) + +#define FT_FACE_DRIVER( x ) FT_FACE( x )->driver +#define FT_FACE_LIBRARY( x ) FT_FACE_DRIVER( x )->root.library +#define FT_FACE_MEMORY( x ) FT_FACE( x )->memory +#define FT_FACE_STREAM( x ) FT_FACE( x )->stream + +#define FT_SIZE_FACE( x ) FT_SIZE( x )->face +#define FT_SLOT_FACE( x ) FT_SLOT( x )->face + +#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph +#define FT_FACE_SIZE( x ) FT_FACE( x )->size + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_GlyphSlot */ + /* */ + /* <Description> */ + /* It is sometimes useful to have more than one glyph slot for a */ + /* given face object. This function is used to create additional */ + /* slots. All of them are automatically discarded when the face is */ + /* destroyed. */ + /* */ + /* <Input> */ + /* face :: A handle to a parent face object. */ + /* */ + /* <Output> */ + /* aslot :: A handle to a new glyph slot object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_BASE( FT_Error ) + FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot *aslot ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_GlyphSlot */ + /* */ + /* <Description> */ + /* Destroys a given glyph slot. Remember however that all slots are */ + /* automatically destroyed with its parent. Using this function is */ + /* not always mandatory. */ + /* */ + /* <Input> */ + /* slot :: A handle to a target glyph slot. */ + /* */ + FT_BASE( void ) + FT_Done_GlyphSlot( FT_GlyphSlot slot ); + + /* */ + + /* + * Free the bitmap of a given glyphslot when needed + * (i.e., only when it was allocated with ft_glyphslot_alloc_bitmap). + */ + FT_BASE( void ) + ft_glyphslot_free_bitmap( FT_GlyphSlot slot ); + + + /* + * Allocate a new bitmap buffer in a glyph slot. + */ + FT_BASE( FT_Error ) + ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, + FT_ULong size ); + + + /* + * Set the bitmap buffer in a glyph slot to a given pointer. + * The buffer will not be freed by a later call to ft_glyphslot_free_bitmap. + */ + FT_BASE( void ) + ft_glyphslot_set_bitmap( FT_GlyphSlot slot, + FT_Byte* buffer ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** R E N D E R E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FT_RENDERER( x ) ((FT_Renderer)( x )) +#define FT_GLYPH( x ) ((FT_Glyph)( x )) +#define FT_BITMAP_GLYPH( x ) ((FT_BitmapGlyph)( x )) +#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x )) + + + typedef struct FT_RendererRec_ + { + FT_ModuleRec root; + FT_Renderer_Class* clazz; + FT_Glyph_Format glyph_format; + FT_Glyph_Class glyph_class; + + FT_Raster raster; + FT_Raster_Render_Func raster_render; + FT_Renderer_RenderFunc render; + + } FT_RendererRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F O N T D R I V E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* typecast a module into a driver easily */ +#define FT_DRIVER( x ) ((FT_Driver)(x)) + + /* typecast a module as a driver, and get its driver class */ +#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_DriverRec */ + /* */ + /* <Description> */ + /* The root font driver class. A font driver is responsible for */ + /* managing and loading font files of a given format. */ + /* */ + /* <Fields> */ + /* root :: Contains the fields of the root module class. */ + /* */ + /* clazz :: A pointer to the font driver's class. Note that */ + /* this is NOT root.clazz. `class' wasn't used */ + /* as it is a reserved word in C++. */ + /* */ + /* faces_list :: The list of faces currently opened by this */ + /* driver. */ + /* */ + /* extensions :: A typeless pointer to the driver's extensions */ + /* registry, if they are supported through the */ + /* configuration macro FT_CONFIG_OPTION_EXTENSIONS. */ + /* */ + /* glyph_loader :: The glyph loader for all faces managed by this */ + /* driver. This object isn't defined for unscalable */ + /* formats. */ + /* */ + typedef struct FT_DriverRec_ + { + FT_ModuleRec root; + FT_Driver_Class clazz; + + FT_ListRec faces_list; + void* extensions; + + FT_GlyphLoader glyph_loader; + + } FT_DriverRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** L I B R A R I E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +/* this hook is used by the TrueType debugger. It must be set to an alternate + * truetype bytecode interpreter function + */ +#define FT_DEBUG_HOOK_TRUETYPE 0 + + +/* set this debug hook to a non-null pointer to force unpatented hinting + * for all faces when both TT_CONFIG_OPTION_BYTECODE_INTERPRETER and + * TT_CONFIG_OPTION_UNPATENTED_HINTING are defined. this is only used + * during debugging + */ +#define FT_DEBUG_HOOK_UNPATENTED_HINTING 1 + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* FT_LibraryRec */ + /* */ + /* <Description> */ + /* The FreeType library class. This is the root of all FreeType */ + /* data. Use FT_New_Library() to create a library object, and */ + /* FT_Done_Library() to discard it and all child objects. */ + /* */ + /* <Fields> */ + /* memory :: The library's memory object. Manages memory */ + /* allocation. */ + /* */ + /* generic :: Client data variable. Used to extend the */ + /* Library class by higher levels and clients. */ + /* */ + /* version_major :: The major version number of the library. */ + /* */ + /* version_minor :: The minor version number of the library. */ + /* */ + /* version_patch :: The current patch level of the library. */ + /* */ + /* num_modules :: The number of modules currently registered */ + /* within this library. This is set to 0 for new */ + /* libraries. New modules are added through the */ + /* FT_Add_Module() API function. */ + /* */ + /* modules :: A table used to store handles to the currently */ + /* registered modules. Note that each font driver */ + /* contains a list of its opened faces. */ + /* */ + /* renderers :: The list of renderers currently registered */ + /* within the library. */ + /* */ + /* cur_renderer :: The current outline renderer. This is a */ + /* shortcut used to avoid parsing the list on */ + /* each call to FT_Outline_Render(). It is a */ + /* handle to the current renderer for the */ + /* FT_GLYPH_FORMAT_OUTLINE format. */ + /* */ + /* auto_hinter :: XXX */ + /* */ + /* raster_pool :: The raster object's render pool. This can */ + /* ideally be changed dynamically at run-time. */ + /* */ + /* raster_pool_size :: The size of the render pool in bytes. */ + /* */ + /* debug_hooks :: XXX */ + /* */ + typedef struct FT_LibraryRec_ + { + FT_Memory memory; /* library's memory manager */ + + FT_Generic generic; + + FT_Int version_major; + FT_Int version_minor; + FT_Int version_patch; + + FT_UInt num_modules; + FT_Module modules[FT_MAX_MODULES]; /* module objects */ + + FT_ListRec renderers; /* list of renderers */ + FT_Renderer cur_renderer; /* current outline renderer */ + FT_Module auto_hinter; + + FT_Byte* raster_pool; /* scan-line conversion */ + /* render pool */ + FT_ULong raster_pool_size; /* size of render pool in bytes */ + + FT_DebugHook_Func debug_hooks[4]; + + } FT_LibraryRec; + + + FT_BASE( FT_Renderer ) + FT_Lookup_Renderer( FT_Library library, + FT_Glyph_Format format, + FT_ListNode* node ); + + FT_BASE( FT_Error ) + FT_Render_Glyph_Internal( FT_Library library, + FT_GlyphSlot slot, + FT_Render_Mode render_mode ); + + typedef const char* + (*FT_Face_GetPostscriptNameFunc)( FT_Face face ); + + typedef FT_Error + (*FT_Face_GetGlyphNameFunc)( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + typedef FT_UInt + (*FT_Face_GetGlyphNameIndexFunc)( FT_Face face, + FT_String* glyph_name ); + + +#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Memory */ + /* */ + /* <Description> */ + /* Creates a new memory object. */ + /* */ + /* <Return> */ + /* A pointer to the new memory object. 0 in case of error. */ + /* */ + FT_EXPORT( FT_Memory ) + FT_New_Memory( void ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Done_Memory */ + /* */ + /* <Description> */ + /* Discards memory manager. */ + /* */ + /* <Input> */ + /* memory :: A handle to the memory manager. */ + /* */ + FT_EXPORT( void ) + FT_Done_Memory( FT_Memory memory ); + +#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */ + + + /* Define default raster's interface. The default raster is located in */ + /* `src/base/ftraster.c'. */ + /* */ + /* Client applications can register new rasters through the */ + /* FT_Set_Raster() API. */ + +#ifndef FT_NO_DEFAULT_RASTER + FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster; +#endif + + +FT_END_HEADER + +#endif /* __FTOBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftrfork.h b/Utilities/vtkfreetype/include/freetype/internal/ftrfork.h new file mode 100644 index 0000000..e7b1002 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftrfork.h @@ -0,0 +1,184 @@ +/***************************************************************************/ +/* */ +/* ftrfork.h */ +/* */ +/* Embedded resource forks accessor (specification). */ +/* */ +/* Copyright 2004 by */ +/* Masatake YAMATO and Redhat K.K. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +/***************************************************************************/ +/* Development of the code in this file is support of */ +/* Information-technology Promotion Agency, Japan. */ +/***************************************************************************/ + + +#ifndef __FTRFORK_H__ +#define __FTRFORK_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H + + +FT_BEGIN_HEADER + + + /* Number of guessing rules supported in `FT_Raccess_Guess'. */ + /* Don't forget to increment the number if you add a new guessing rule. */ +#define FT_RACCESS_N_RULES 8 + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Raccess_Guess */ + /* */ + /* <Description> */ + /* Guess a file name and offset where the actual resource fork is */ + /* stored. The macro FT_RACCESS_N_RULES holds the number of */ + /* guessing rules; the guessed result for the Nth rule is */ + /* represented as a triplet: a new file name (new_names[N]), a file */ + /* offset (offsets[N]), and an error code (errors[N]). */ + /* */ + /* <Input> */ + /* library :: */ + /* A FreeType library instance. */ + /* */ + /* stream :: */ + /* A file stream containing the resource fork. */ + /* */ + /* base_name :: */ + /* The (base) file name of the resource fork used for some */ + /* guessing rules. */ + /* */ + /* <Output> */ + /* new_names :: */ + /* An array of guessed file names in which the resource forks may */ + /* exist. If `new_names[N]' is NULL, the guessed file name is */ + /* equal to `base_name'. */ + /* */ + /* offsets :: */ + /* An array of guessed file offsets. `offsets[N]' holds the file */ + /* offset of the possible start of the resource fork in file */ + /* `new_names[N]'. */ + /* */ + /* errors :: */ + /* An array of FreeType error codes. `errors[N]' is the error */ + /* code of Nth guessing rule function. If `errors[N]' is not */ + /* FT_Err_Ok, `new_names[N]' and `offsets[N]' are meaningless. */ + /* */ + FT_BASE( void ) + FT_Raccess_Guess( FT_Library library, + FT_Stream stream, + char* base_name, + char** new_names, + FT_Long* offsets, + FT_Error* errors ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Raccess_Get_HeaderInfo */ + /* */ + /* <Description> */ + /* Get the information from the header of resource fork. The */ + /* information includes the file offset where the resource map */ + /* starts, and the file offset where the resource data starts. */ + /* `FT_Raccess_Get_DataOffsets' requires these two data. */ + /* */ + /* <Input> */ + /* library :: */ + /* A FreeType library instance. */ + /* */ + /* stream :: */ + /* A file stream containing the resource fork. */ + /* */ + /* rfork_offset :: */ + /* The file offset where the resource fork starts. */ + /* */ + /* <Output> */ + /* map_offset :: */ + /* The file offset where the resource map starts. */ + /* */ + /* rdata_pos :: */ + /* The file offset where the resource data starts. */ + /* */ + /* <Return> */ + /* FreeType error code. FT_Err_Ok means success. */ + /* */ + FT_BASE( FT_Error ) + FT_Raccess_Get_HeaderInfo( FT_Library library, + FT_Stream stream, + FT_Long rfork_offset, + FT_Long *map_offset, + FT_Long *rdata_pos ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Raccess_Get_DataOffsets */ + /* */ + /* <Description> */ + /* Get the data offsets for a tag in a resource fork. Offsets are */ + /* stored in an array because, in some cases, resources in a resource */ + /* fork have the same tag. */ + /* */ + /* <Input> */ + /* library :: */ + /* A FreeType library instance. */ + /* */ + /* stream :: */ + /* A file stream containing the resource fork. */ + /* */ + /* map_offset :: */ + /* The file offset where the resource map starts. */ + /* */ + /* rdata_pos :: */ + /* The file offset where the resource data starts. */ + /* */ + /* tag :: */ + /* The resource tag. */ + /* */ + /* <Output> */ + /* offsets :: */ + /* The stream offsets for the resource data specified by `tag'. */ + /* This array is allocated by the function, so you have to call */ + /* @FT_Free after use. */ + /* */ + /* count :: */ + /* The length of offsets array. */ + /* */ + /* <Return> */ + /* FreeType error code. FT_Err_Ok means success. */ + /* */ + /* <Note> */ + /* Normally you should use `FT_Raccess_Get_HeaderInfo' to get the */ + /* value for `map_offset' and `rdata_pos'. */ + /* */ + FT_BASE( FT_Error ) + FT_Raccess_Get_DataOffsets( FT_Library library, + FT_Stream stream, + FT_Long map_offset, + FT_Long rdata_pos, + FT_Long tag, + FT_Long **offsets, + FT_Long *count ); + + +FT_END_HEADER + +#endif /* __FTRFORK_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftserv.h b/Utilities/vtkfreetype/include/freetype/internal/ftserv.h new file mode 100644 index 0000000..e5ed889 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftserv.h @@ -0,0 +1,260 @@ +/***************************************************************************/ +/* */ +/* ftserv.h */ +/* */ +/* The FreeType services (specification only). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* Each module can export one or more `services'. Each service is */ + /* identified by a constant string and modeled by a pointer; the latter */ + /* generally corresponds to a structure containing function pointers. */ + /* */ + /* Note that a service's data cannot be a mere function pointer because */ + /* in C it is possible that function pointers might be implemented */ + /* differently than data pointers (e.g. 48 bits instead of 32). */ + /* */ + /*************************************************************************/ + + +#ifndef __FTSERV_H__ +#define __FTSERV_H__ + + +FT_BEGIN_HEADER + + + /* + * @macro: + * FT_FACE_FIND_SERVICE + * + * @description: + * This macro is used to look up a service from a face's driver module. + * + * @input: + * face :: + * The source face handle. + * + * id :: + * A string describing the service as defined in the service's + * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to + * `multi-masters'). It is automatically prefixed with + * `FT_SERVICE_ID_'. + * + * @output: + * ptr :: + * A variable that receives the service pointer. Will be NULL + * if not found. + */ +#define FT_FACE_FIND_SERVICE( face, ptr, id ) \ + FT_BEGIN_STMNT \ + FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \ + /* the strange cast is to allow C++ compilation */ \ + FT_Pointer* Pptr = (FT_Pointer*) &(ptr); \ + \ + \ + *Pptr = NULL; \ + if ( module->clazz->get_interface ) \ + *Pptr = module->clazz->get_interface( module, FT_SERVICE_ID_ ## id ); \ + FT_END_STMNT + + + /* + * @macro: + * FT_FACE_FIND_GLOBAL_SERVICE + * + * @description: + * This macro is used to look up a service from all modules. + * + * @input: + * face :: + * The source face handle. + * + * id :: + * A string describing the service as defined in the service's + * header files (e.g. FT_SERVICE_ID_MULTI_MASTERS which expands to + * `multi-masters'). It is automatically prefixed with + * `FT_SERVICE_ID_'. + * + * @output: + * ptr :: + * A variable that receives the service pointer. Will be NULL + * if not found. + */ +#define FT_FACE_FIND_GLOBAL_SERVICE( face, ptr, id ) \ + FT_BEGIN_STMNT \ + FT_Module module = FT_MODULE( FT_FACE(face)->driver ); \ + /* the strange cast is to allow C++ compilation */ \ + FT_Pointer* Pptr = (FT_Pointer*) &(ptr); \ + \ + \ + *Pptr = ft_module_get_service( module, FT_SERVICE_ID_ ## id ); \ + FT_END_STMNT + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** S E R V I C E D E S C R I P T O R S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* + * The following structure is used to _describe_ a given service + * to the library. This is useful to build simple static service lists. + */ + typedef struct FT_ServiceDescRec_ + { + const char* serv_id; /* service name */ + const void* serv_data; /* service pointer/data */ + + } FT_ServiceDescRec; + + typedef const FT_ServiceDescRec* FT_ServiceDesc; + + + /* + * Parse a list of FT_ServiceDescRec descriptors and look for + * a specific service by ID. Note that the last element in the + * array must be { NULL, NULL }, and that the function should + * return NULL if the service isn't available. + * + * This function can be used by modules to implement their + * `get_service' method. + */ + FT_BASE( FT_Pointer ) + ft_service_list_lookup( FT_ServiceDesc service_descriptors, + const char* service_id ); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** S E R V I C E S C A C H E *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* + * This structure is used to store a cache for several frequently used + * services. It is the type of `face->internal->services'. You + * should only use FT_FACE_LOOKUP_SERVICE to access it. + * + * All fields should have the type FT_Pointer to relax compilation + * dependencies. We assume the developer isn't completely stupid. + * + * Each field must be named `service_XXXX' where `XXX' corresponds to + * the correct FT_SERVICE_ID_XXXX macro. See the definition of + * FT_FACE_LOOKUP_SERVICE below how this is implemented. + * + */ + typedef struct FT_ServiceCacheRec_ + { + FT_Pointer service_POSTSCRIPT_FONT_NAME; + FT_Pointer service_MULTI_MASTERS; + FT_Pointer service_GLYPH_DICT; + FT_Pointer service_PFR_METRICS; + FT_Pointer service_WINFNT; + + } FT_ServiceCacheRec, *FT_ServiceCache; + + + /* + * A magic number used within the services cache. + */ +#define FT_SERVICE_UNAVAILABLE ((FT_Pointer)-2) /* magic number */ + + + /* + * @macro: + * FT_FACE_LOOKUP_SERVICE + * + * @description: + * This macro is used to lookup a service from a face's driver module + * using its cache. + * + * @input: + * face:: + * The source face handle containing the cache. + * + * field :: + * The field name in the cache. + * + * id :: + * The service ID. + * + * @output: + * ptr :: + * A variable receiving the service data. NULL if not available. + */ +#define FT_FACE_LOOKUP_SERVICE( face, ptr, id ) \ + FT_BEGIN_STMNT \ + /* the strange cast is to allow C++ compilation */ \ + FT_Pointer* pptr = (FT_Pointer*)&(ptr); \ + FT_Pointer svc; \ + \ + \ + svc = FT_FACE(face)->internal->services. service_ ## id ; \ + if ( svc == FT_SERVICE_UNAVAILABLE ) \ + svc = NULL; \ + else if ( svc == NULL ) \ + { \ + FT_FACE_FIND_SERVICE( face, svc, id ); \ + \ + FT_FACE(face)->internal->services. service_ ## id = \ + (FT_Pointer)( svc != NULL ? svc \ + : FT_SERVICE_UNAVAILABLE ); \ + } \ + *pptr = svc; \ + FT_END_STMNT + + + /* + * A macro used to define new service structure types. + */ + +#define FT_DEFINE_SERVICE( name ) \ + typedef struct FT_Service_ ## name ## Rec_ \ + FT_Service_ ## name ## Rec ; \ + typedef struct FT_Service_ ## name ## Rec_ \ + const * FT_Service_ ## name ; \ + struct FT_Service_ ## name ## Rec_ + + /* */ + + /* + * The header files containing the services. + */ + +#define FT_SERVICE_MULTIPLE_MASTERS_H <freetype/internal/services/svmm.h> +#define FT_SERVICE_POSTSCRIPT_NAME_H <freetype/internal/services/svpostnm.h> +#define FT_SERVICE_POSTSCRIPT_CMAPS_H <freetype/internal/services/svpscmap.h> +#define FT_SERVICE_POSTSCRIPT_INFO_H <freetype/internal/services/svpsinfo.h> +#define FT_SERVICE_GLYPH_DICT_H <freetype/internal/services/svgldict.h> +#define FT_SERVICE_BDF_H <freetype/internal/services/svbdf.h> +#define FT_SERVICE_XFREE86_NAME_H <freetype/internal/services/svxf86nm.h> +#define FT_SERVICE_SFNT_H <freetype/internal/services/svsfnt.h> +#define FT_SERVICE_PFR_H <freetype/internal/services/svpfr.h> +#define FT_SERVICE_WINFNT_H <freetype/internal/services/svwinfnt.h> +#define FT_SERVICE_TT_CMAP_H <freetype/internal/services/svttcmap.h> + + /* */ + +FT_END_HEADER + +#endif /* __FTSERV_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/ftstream.h b/Utilities/vtkfreetype/include/freetype/internal/ftstream.h new file mode 100644 index 0000000..9833cd0 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/ftstream.h @@ -0,0 +1,529 @@ +/***************************************************************************/ +/* */ +/* ftstream.h */ +/* */ +/* Stream handling (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTSTREAM_H__ +#define __FTSTREAM_H__ + + +#include <ft2build.h> +#include FT_SYSTEM_H +#include FT_INTERNAL_OBJECTS_H + + +FT_BEGIN_HEADER + + + /* format of an 8-bit frame_op value: */ + /* */ + /* bit 76543210 */ + /* xxxxxxes */ + /* */ + /* s is set to 1 if the value is signed. */ + /* e is set to 1 if the value is little-endian. */ + /* xxx is a command. */ + +#define FT_FRAME_OP_SHIFT 2 +#define FT_FRAME_OP_SIGNED 1 +#define FT_FRAME_OP_LITTLE 2 +#define FT_FRAME_OP_COMMAND( x ) ( x >> FT_FRAME_OP_SHIFT ) + +#define FT_MAKE_FRAME_OP( command, little, sign ) \ + ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign ) + +#define FT_FRAME_OP_END 0 +#define FT_FRAME_OP_START 1 /* start a new frame */ +#define FT_FRAME_OP_BYTE 2 /* read 1-byte value */ +#define FT_FRAME_OP_SHORT 3 /* read 2-byte value */ +#define FT_FRAME_OP_LONG 4 /* read 4-byte value */ +#define FT_FRAME_OP_OFF3 5 /* read 3-byte value */ +#define FT_FRAME_OP_BYTES 6 /* read a bytes sequence */ + + + typedef enum FT_Frame_Op_ + { + ft_frame_end = 0, + ft_frame_start = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ), + + ft_frame_byte = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 0 ), + ft_frame_schar = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 1 ), + + ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ), + ft_frame_short_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ), + ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ), + ft_frame_short_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ), + + ft_frame_ulong_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ), + ft_frame_long_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ), + ft_frame_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ), + ft_frame_long_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ), + + ft_frame_uoff3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ), + ft_frame_off3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ), + ft_frame_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ), + ft_frame_off3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ), + + ft_frame_bytes = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ), + ft_frame_skip = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 ) + + } FT_Frame_Op; + + + typedef struct FT_Frame_Field_ + { + FT_Byte value; + FT_Byte size; + FT_UShort offset; + + } FT_Frame_Field; + + + /* Construct an FT_Frame_Field out of a structure type and a field name. */ + /* The structure type must be set in the FT_STRUCTURE macro before */ + /* calling the FT_FRAME_START() macro. */ + /* */ +#define FT_FIELD_SIZE( f ) \ + (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f ) + +#define FT_FIELD_SIZE_DELTA( f ) \ + (FT_Byte)sizeof ( ((FT_STRUCTURE*)0)->f[0] ) + +#define FT_FIELD_OFFSET( f ) \ + (FT_UShort)( offsetof( FT_STRUCTURE, f ) ) + +#define FT_FRAME_FIELD( frame_op, field ) \ + { \ + frame_op, \ + FT_FIELD_SIZE( field ), \ + FT_FIELD_OFFSET( field ) \ + } + +#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 } + +#define FT_FRAME_START( size ) { ft_frame_start, 0, size } +#define FT_FRAME_END { ft_frame_end, 0, 0 } + +#define FT_FRAME_LONG( f ) FT_FRAME_FIELD( ft_frame_long_be, f ) +#define FT_FRAME_ULONG( f ) FT_FRAME_FIELD( ft_frame_ulong_be, f ) +#define FT_FRAME_SHORT( f ) FT_FRAME_FIELD( ft_frame_short_be, f ) +#define FT_FRAME_USHORT( f ) FT_FRAME_FIELD( ft_frame_ushort_be, f ) +#define FT_FRAME_OFF3( f ) FT_FRAME_FIELD( ft_frame_off3_be, f ) +#define FT_FRAME_UOFF3( f ) FT_FRAME_FIELD( ft_frame_uoff3_be, f ) +#define FT_FRAME_BYTE( f ) FT_FRAME_FIELD( ft_frame_byte, f ) +#define FT_FRAME_CHAR( f ) FT_FRAME_FIELD( ft_frame_schar, f ) + +#define FT_FRAME_LONG_LE( f ) FT_FRAME_FIELD( ft_frame_long_le, f ) +#define FT_FRAME_ULONG_LE( f ) FT_FRAME_FIELD( ft_frame_ulong_le, f ) +#define FT_FRAME_SHORT_LE( f ) FT_FRAME_FIELD( ft_frame_short_le, f ) +#define FT_FRAME_USHORT_LE( f ) FT_FRAME_FIELD( ft_frame_ushort_le, f ) +#define FT_FRAME_OFF3_LE( f ) FT_FRAME_FIELD( ft_frame_off3_le, f ) +#define FT_FRAME_UOFF3_LE( f ) FT_FRAME_FIELD( ft_frame_uoff3_le, f ) + +#define FT_FRAME_SKIP_LONG { ft_frame_long_be, 0, 0 } +#define FT_FRAME_SKIP_SHORT { ft_frame_short_be, 0, 0 } +#define FT_FRAME_SKIP_BYTE { ft_frame_byte, 0, 0 } + +#define FT_FRAME_BYTES( field, count ) \ + { \ + ft_frame_bytes, \ + count, \ + FT_FIELD_OFFSET( field ) \ + } + +#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 } + + + /*************************************************************************/ + /* */ + /* Integer extraction macros -- the `buffer' parameter must ALWAYS be of */ + /* type `char*' or equivalent (1-byte elements). */ + /* */ + +#define FT_BYTE_( p, i ) ( ((const FT_Byte*)(p))[(i)] ) +#define FT_INT8_( p, i ) ( ((const FT_Char*)(p))[(i)] ) + +#define FT_INT16( x ) ( (FT_Int16)(x) ) +#define FT_UINT16( x ) ( (FT_UInt16)(x) ) +#define FT_INT32( x ) ( (FT_Int32)(x) ) +#define FT_UINT32( x ) ( (FT_UInt32)(x) ) + +#define FT_BYTE_I16( p, i, s ) ( FT_INT16( FT_BYTE_( p, i ) ) << (s) ) +#define FT_BYTE_U16( p, i, s ) ( FT_UINT16( FT_BYTE_( p, i ) ) << (s) ) +#define FT_BYTE_I32( p, i, s ) ( FT_INT32( FT_BYTE_( p, i ) ) << (s) ) +#define FT_BYTE_U32( p, i, s ) ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) ) + +#define FT_INT8_I16( p, i, s ) ( FT_INT16( FT_INT8_( p, i ) ) << (s) ) +#define FT_INT8_U16( p, i, s ) ( FT_UINT16( FT_INT8_( p, i ) ) << (s) ) +#define FT_INT8_I32( p, i, s ) ( FT_INT32( FT_INT8_( p, i ) ) << (s) ) +#define FT_INT8_U32( p, i, s ) ( FT_UINT32( FT_INT8_( p, i ) ) << (s) ) + + +#define FT_PEEK_SHORT( p ) FT_INT16( FT_INT8_I16( p, 0, 8) | \ + FT_BYTE_I16( p, 1, 0) ) + +#define FT_PEEK_USHORT( p ) FT_UINT16( FT_BYTE_U16( p, 0, 8 ) | \ + FT_BYTE_U16( p, 1, 0 ) ) + +#define FT_PEEK_LONG( p ) FT_INT32( FT_INT8_I32( p, 0, 24 ) | \ + FT_BYTE_I32( p, 1, 16 ) | \ + FT_BYTE_I32( p, 2, 8 ) | \ + FT_BYTE_I32( p, 3, 0 ) ) + +#define FT_PEEK_ULONG( p ) FT_UINT32( FT_BYTE_U32( p, 0, 24 ) | \ + FT_BYTE_U32( p, 1, 16 ) | \ + FT_BYTE_U32( p, 2, 8 ) | \ + FT_BYTE_U32( p, 3, 0 ) ) + +#define FT_PEEK_OFF3( p ) FT_INT32( FT_INT8_I32( p, 0, 16 ) | \ + FT_BYTE_I32( p, 1, 8 ) | \ + FT_BYTE_I32( p, 2, 0 ) ) + +#define FT_PEEK_UOFF3( p ) FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \ + FT_BYTE_U32( p, 1, 8 ) | \ + FT_BYTE_U32( p, 2, 0 ) ) + +#define FT_PEEK_SHORT_LE( p ) FT_INT16( FT_INT8_I16( p, 1, 8 ) | \ + FT_BYTE_I16( p, 0, 0 ) ) + +#define FT_PEEK_USHORT_LE( p ) FT_UINT16( FT_BYTE_U16( p, 1, 8 ) | \ + FT_BYTE_U16( p, 0, 0 ) ) + +#define FT_PEEK_LONG_LE( p ) FT_INT32( FT_INT8_I32( p, 3, 24 ) | \ + FT_BYTE_I32( p, 2, 16 ) | \ + FT_BYTE_I32( p, 1, 8 ) | \ + FT_BYTE_I32( p, 0, 0 ) ) + +#define FT_PEEK_ULONG_LE( p ) FT_UINT32( FT_BYTE_U32( p, 3, 24 ) | \ + FT_BYTE_U32( p, 2, 16 ) | \ + FT_BYTE_U32( p, 1, 8 ) | \ + FT_BYTE_U32( p, 0, 0 ) ) + +#define FT_PEEK_OFF3_LE( p ) FT_INT32( FT_INT8_I32( p, 2, 16 ) | \ + FT_BYTE_I32( p, 1, 8 ) | \ + FT_BYTE_I32( p, 0, 0 ) ) + +#define FT_PEEK_UOFF3_LE( p ) FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \ + FT_BYTE_U32( p, 1, 8 ) | \ + FT_BYTE_U32( p, 0, 0 ) ) + + +#define FT_NEXT_CHAR( buffer ) \ + ( (signed char)*buffer++ ) + +#define FT_NEXT_BYTE( buffer ) \ + ( (unsigned char)*buffer++ ) + +#define FT_NEXT_SHORT( buffer ) \ + ( (short)( buffer += 2, FT_PEEK_SHORT( buffer - 2 ) ) ) + +#define FT_NEXT_USHORT( buffer ) \ + ( (unsigned short)( buffer += 2, FT_PEEK_USHORT( buffer - 2 ) ) ) + +#define FT_NEXT_OFF3( buffer ) \ + ( (long)( buffer += 3, FT_PEEK_OFF3( buffer - 3 ) ) ) + +#define FT_NEXT_UOFF3( buffer ) \ + ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3( buffer - 3 ) ) ) + +#define FT_NEXT_LONG( buffer ) \ + ( (long)( buffer += 4, FT_PEEK_LONG( buffer - 4 ) ) ) + +#define FT_NEXT_ULONG( buffer ) \ + ( (unsigned long)( buffer += 4, FT_PEEK_ULONG( buffer - 4 ) ) ) + + +#define FT_NEXT_SHORT_LE( buffer ) \ + ( (short)( buffer += 2, FT_PEEK_SHORT_LE( buffer - 2 ) ) ) + +#define FT_NEXT_USHORT_LE( buffer ) \ + ( (unsigned short)( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) ) + +#define FT_NEXT_OFF3_LE( buffer ) \ + ( (long)( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) ) + +#define FT_NEXT_UOFF3_LE( buffer ) \ + ( (unsigned long)( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) ) + +#define FT_NEXT_LONG_LE( buffer ) \ + ( (long)( buffer += 4, FT_PEEK_LONG_LE( buffer - 4 ) ) ) + +#define FT_NEXT_ULONG_LE( buffer ) \ + ( (unsigned long)( buffer += 4, FT_PEEK_ULONG_LE( buffer - 4 ) ) ) + + + /*************************************************************************/ + /* */ + /* Each GET_xxxx() macro uses an implicit `stream' variable. */ + /* */ +#if 0 +#define FT_GET_MACRO( type ) FT_NEXT_ ## type ( stream->cursor ) + +#define FT_GET_CHAR() FT_GET_MACRO( CHAR ) +#define FT_GET_BYTE() FT_GET_MACRO( BYTE ) +#define FT_GET_SHORT() FT_GET_MACRO( SHORT ) +#define FT_GET_USHORT() FT_GET_MACRO( USHORT ) +#define FT_GET_OFF3() FT_GET_MACRO( OFF3 ) +#define FT_GET_UOFF3() FT_GET_MACRO( UOFF3 ) +#define FT_GET_LONG() FT_GET_MACRO( LONG ) +#define FT_GET_ULONG() FT_GET_MACRO( ULONG ) +#define FT_GET_TAG4() FT_GET_MACRO( ULONG ) + +#define FT_GET_SHORT_LE() FT_GET_MACRO( SHORT_LE ) +#define FT_GET_USHORT_LE() FT_GET_MACRO( USHORT_LE ) +#define FT_GET_LONG_LE() FT_GET_MACRO( LONG_LE ) +#define FT_GET_ULONG_LE() FT_GET_MACRO( ULONG_LE ) + +#else +#define FT_GET_MACRO( func, type ) ( (type)func( stream ) ) + +#define FT_GET_CHAR() FT_GET_MACRO( FT_Stream_GetChar, FT_Char ) +#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetChar, FT_Byte ) +#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_Short ) +#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetShort, FT_UShort ) +#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_Long ) +#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetOffset, FT_ULong ) +#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetLong, FT_Long ) +#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong ) +#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetLong, FT_ULong ) + +#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_Short ) +#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetShortLE, FT_UShort ) +#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_Long ) +#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetLongLE, FT_ULong ) +#endif + +#define FT_READ_MACRO( func, type, var ) \ + ( var = (type)func( stream, &error ), \ + error != FT_Err_Ok ) + +#define FT_READ_BYTE( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var ) +#define FT_READ_CHAR( var ) FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var ) +#define FT_READ_SHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_Short, var ) +#define FT_READ_USHORT( var ) FT_READ_MACRO( FT_Stream_ReadShort, FT_UShort, var ) +#define FT_READ_OFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_Long, var ) +#define FT_READ_UOFF3( var ) FT_READ_MACRO( FT_Stream_ReadOffset, FT_ULong, var ) +#define FT_READ_LONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_Long, var ) +#define FT_READ_ULONG( var ) FT_READ_MACRO( FT_Stream_ReadLong, FT_ULong, var ) + +#define FT_READ_SHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_Short, var ) +#define FT_READ_USHORT_LE( var ) FT_READ_MACRO( FT_Stream_ReadShortLE, FT_UShort, var ) +#define FT_READ_LONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_Long, var ) +#define FT_READ_ULONG_LE( var ) FT_READ_MACRO( FT_Stream_ReadLongLE, FT_ULong, var ) + + +#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + /* initialize a stream for reading a regular system stream */ + FT_EXPORT( FT_Error ) + FT_Stream_Open( FT_Stream stream, + const char* filepathname ); + +#endif /* FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */ + + + /* create a new (input) stream from an FT_Open_Args structure */ + FT_BASE( FT_Error ) + FT_Stream_New( FT_Library library, + const FT_Open_Args* args, + FT_Stream *astream ); + + /* free a stream */ + FT_BASE( void ) + FT_Stream_Free( FT_Stream stream, + FT_Int external ); + + /* initialize a stream for reading in-memory data */ + FT_BASE( void ) + FT_Stream_OpenMemory( FT_Stream stream, + const FT_Byte* base, + FT_ULong size ); + + /* close a stream (does not destroy the stream structure) */ + FT_BASE( void ) + FT_Stream_Close( FT_Stream stream ); + + + /* seek within a stream. position is relative to start of stream */ + FT_BASE( FT_Error ) + FT_Stream_Seek( FT_Stream stream, + FT_ULong pos ); + + /* skip bytes in a stream */ + FT_BASE( FT_Error ) + FT_Stream_Skip( FT_Stream stream, + FT_Long distance ); + + /* return current stream position */ + FT_BASE( FT_Long ) + FT_Stream_Pos( FT_Stream stream ); + + /* read bytes from a stream into a user-allocated buffer, returns an */ + /* error if not all bytes could be read. */ + FT_BASE( FT_Error ) + FT_Stream_Read( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ); + + /* read bytes from a stream at a given position */ + FT_BASE( FT_Error ) + FT_Stream_ReadAt( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ); + + /* Enter a frame of `count' consecutive bytes in a stream. Returns an */ + /* error if the frame could not be read/accessed. The caller can use */ + /* the FT_Stream_Get_XXX functions to retrieve frame data without */ + /* error checks. */ + /* */ + /* You must _always_ call FT_Stream_ExitFrame() once you have entered */ + /* a stream frame! */ + /* */ + FT_BASE( FT_Error ) + FT_Stream_EnterFrame( FT_Stream stream, + FT_ULong count ); + + /* exit a stream frame */ + FT_BASE( void ) + FT_Stream_ExitFrame( FT_Stream stream ); + + /* Extract a stream frame. If the stream is disk-based, a heap block */ + /* is allocated and the frame bytes are read into it. If the stream */ + /* is memory-based, this function simply set a pointer to the data. */ + /* */ + /* Useful to optimize access to memory-based streams transparently. */ + /* */ + /* All extracted frames must be `freed` with a call to the function */ + /* FT_Stream_ReleaseFrame(). */ + /* */ + FT_BASE( FT_Error ) + FT_Stream_ExtractFrame( FT_Stream stream, + FT_ULong count, + FT_Byte** pbytes ); + + /* release an extract frame (see FT_Stream_ExtractFrame) */ + FT_BASE( void ) + FT_Stream_ReleaseFrame( FT_Stream stream, + FT_Byte** pbytes ); + + /* read a byte from an entered frame */ + FT_BASE( FT_Char ) + FT_Stream_GetChar( FT_Stream stream ); + + /* read a 16-bit big-endian integer from an entered frame */ + FT_BASE( FT_Short ) + FT_Stream_GetShort( FT_Stream stream ); + + /* read a 24-bit big-endian integer from an entered frame */ + FT_BASE( FT_Long ) + FT_Stream_GetOffset( FT_Stream stream ); + + /* read a 32-bit big-endian integer from an entered frame */ + FT_BASE( FT_Long ) + FT_Stream_GetLong( FT_Stream stream ); + + /* read a 16-bit little-endian integer from an entered frame */ + FT_BASE( FT_Short ) + FT_Stream_GetShortLE( FT_Stream stream ); + + /* read a 32-bit little-endian integer from an entered frame */ + FT_BASE( FT_Long ) + FT_Stream_GetLongLE( FT_Stream stream ); + + + /* read a byte from a stream */ + FT_BASE( FT_Char ) + FT_Stream_ReadChar( FT_Stream stream, + FT_Error* error ); + + /* read a 16-bit big-endian integer from a stream */ + FT_BASE( FT_Short ) + FT_Stream_ReadShort( FT_Stream stream, + FT_Error* error ); + + /* read a 24-bit big-endian integer from a stream */ + FT_BASE( FT_Long ) + FT_Stream_ReadOffset( FT_Stream stream, + FT_Error* error ); + + /* read a 32-bit big-endian integer from a stream */ + FT_BASE( FT_Long ) + FT_Stream_ReadLong( FT_Stream stream, + FT_Error* error ); + + /* read a 16-bit little-endian integer from a stream */ + FT_BASE( FT_Short ) + FT_Stream_ReadShortLE( FT_Stream stream, + FT_Error* error ); + + /* read a 32-bit little-endian integer from a stream */ + FT_BASE( FT_Long ) + FT_Stream_ReadLongLE( FT_Stream stream, + FT_Error* error ); + + /* Read a structure from a stream. The structure must be described */ + /* by an array of FT_Frame_Field records. */ + FT_BASE( FT_Error ) + FT_Stream_ReadFields( FT_Stream stream, + const FT_Frame_Field* fields, + void* structure ); + + +#define FT_STREAM_POS() \ + FT_Stream_Pos( stream ) + +#define FT_STREAM_SEEK( position ) \ + FT_SET_ERROR( FT_Stream_Seek( stream, position ) ) + +#define FT_STREAM_SKIP( distance ) \ + FT_SET_ERROR( FT_Stream_Skip( stream, distance ) ) + +#define FT_STREAM_READ( buffer, count ) \ + FT_SET_ERROR( FT_Stream_Read( stream, \ + (FT_Byte*)buffer, \ + count ) ) + +#define FT_STREAM_READ_AT( position, buffer, count ) \ + FT_SET_ERROR( FT_Stream_ReadAt( stream, \ + position, \ + (FT_Byte*)buffer, \ + count ) ) + +#define FT_STREAM_READ_FIELDS( fields, object ) \ + FT_SET_ERROR( FT_Stream_ReadFields( stream, fields, object ) ) + + +#define FT_FRAME_ENTER( size ) \ + FT_SET_ERROR( FT_Stream_EnterFrame( stream, size ) ) + +#define FT_FRAME_EXIT() \ + FT_Stream_ExitFrame( stream ) + +#define FT_FRAME_EXTRACT( size, bytes ) \ + FT_SET_ERROR( FT_Stream_ExtractFrame( stream, size, \ + (FT_Byte**)&(bytes) ) ) + +#define FT_FRAME_RELEASE( bytes ) \ + FT_Stream_ReleaseFrame( stream, (FT_Byte**)&(bytes) ) + + +FT_END_HEADER + +#endif /* __FTSTREAM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/fttrace.h b/Utilities/vtkfreetype/include/freetype/internal/fttrace.h new file mode 100644 index 0000000..a9a15a2 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/fttrace.h @@ -0,0 +1,108 @@ +/***************************************************************************/ +/* */ +/* fttrace.h */ +/* */ +/* Tracing handling (specification only). */ +/* */ +/* Copyright 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /* definitions of trace levels for FreeType 2 */ + + /* the first level must always be `trace_any' */ +FT_TRACE_DEF( any ) + + /* base components */ +FT_TRACE_DEF( calc ) /* calculations (ftcalc.c) */ +FT_TRACE_DEF( memory ) /* memory manager (ftobjs.c) */ +FT_TRACE_DEF( stream ) /* stream manager (ftstream.c) */ +FT_TRACE_DEF( io ) /* i/o interface (ftsystem.c) */ +FT_TRACE_DEF( list ) /* list management (ftlist.c) */ +FT_TRACE_DEF( init ) /* initialization (ftinit.c) */ +FT_TRACE_DEF( objs ) /* base objects (ftobjs.c) */ +FT_TRACE_DEF( outline ) /* outline management (ftoutln.c) */ +FT_TRACE_DEF( glyph ) /* glyph management (ftglyph.c) */ + +FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */ +FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */ +FT_TRACE_DEF( mm ) /* MM interface (ftmm.c) */ +FT_TRACE_DEF( raccess ) /* resource fork accessor (ftrfork.c) */ + +/* Cache sub-system */ +FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */ + +/* SFNT driver components */ +FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */ +FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */ +FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */ +FT_TRACE_DEF( ttpost ) /* PS table processing (ttpost.c) */ +FT_TRACE_DEF( ttsbit ) /* TrueType sbit handling (ttsbit.c) */ + +/* TrueType driver components */ +FT_TRACE_DEF( ttdriver ) /* TT font driver (ttdriver.c) */ +FT_TRACE_DEF( ttgload ) /* TT glyph loader (ttgload.c) */ +FT_TRACE_DEF( ttinterp ) /* bytecode interpreter (ttinterp.c) */ +FT_TRACE_DEF( ttobjs ) /* TT objects manager (ttobjs.c) */ +FT_TRACE_DEF( ttpload ) /* TT data/program loader (ttpload.c) */ +FT_TRACE_DEF( ttgxvar ) /* TrueType GX var handler (ttgxvar.c) */ + +/* Type 1 driver components */ +FT_TRACE_DEF( t1driver ) +FT_TRACE_DEF( t1gload ) +FT_TRACE_DEF( t1hint ) +FT_TRACE_DEF( t1load ) +FT_TRACE_DEF( t1objs ) +FT_TRACE_DEF( t1parse ) + +/* PostScript helper module `psaux' */ +FT_TRACE_DEF( t1decode ) +FT_TRACE_DEF( psobjs ) + +/* PostScript hinting module `pshinter' */ +FT_TRACE_DEF( pshrec ) +FT_TRACE_DEF( pshalgo1 ) +FT_TRACE_DEF( pshalgo2 ) + +/* Type 2 driver components */ +FT_TRACE_DEF( cffdriver ) +FT_TRACE_DEF( cffgload ) +FT_TRACE_DEF( cffload ) +FT_TRACE_DEF( cffobjs ) +FT_TRACE_DEF( cffparse ) + +/* Type 42 driver component */ +FT_TRACE_DEF( t42 ) + +/* CID driver components */ +FT_TRACE_DEF( cidafm ) +FT_TRACE_DEF( ciddriver ) +FT_TRACE_DEF( cidgload ) +FT_TRACE_DEF( cidload ) +FT_TRACE_DEF( cidobjs ) +FT_TRACE_DEF( cidparse ) + +/* Windows fonts component */ +FT_TRACE_DEF( winfnt ) + +/* PCF fonts components */ +FT_TRACE_DEF( pcfdriver ) +FT_TRACE_DEF( pcfread ) + +/* BDF fonts component */ +FT_TRACE_DEF( bdfdriver ) +FT_TRACE_DEF( bdflib ) + +/* PFR fonts component */ +FT_TRACE_DEF( pfr ) + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/internal.h b/Utilities/vtkfreetype/include/freetype/internal/internal.h new file mode 100644 index 0000000..1e5ac44 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/internal.h @@ -0,0 +1,49 @@ +/***************************************************************************/ +/* */ +/* internal.h */ +/* */ +/* Internal header files (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is automatically included by `ft2build.h'. */ + /* Do not include it manually! */ + /* */ + /*************************************************************************/ + + +#define FT_INTERNAL_OBJECTS_H <freetype/internal/ftobjs.h> +#define FT_INTERNAL_STREAM_H <freetype/internal/ftstream.h> +#define FT_INTERNAL_MEMORY_H <freetype/internal/ftmemory.h> +#define FT_INTERNAL_DEBUG_H <freetype/internal/ftdebug.h> +#define FT_INTERNAL_CALC_H <freetype/internal/ftcalc.h> +#define FT_INTERNAL_DRIVER_H <freetype/internal/ftdriver.h> +#define FT_INTERNAL_TRACE_H <freetype/internal/fttrace.h> +#define FT_INTERNAL_GLYPH_LOADER_H <freetype/internal/ftgloadr.h> +#define FT_INTERNAL_SFNT_H <freetype/internal/sfnt.h> +#define FT_INTERNAL_SERVICE_H <freetype/internal/ftserv.h> +#define FT_INTERNAL_RFORK_H <freetype/internal/ftrfork.h> + +#define FT_INTERNAL_TRUETYPE_TYPES_H <freetype/internal/tttypes.h> +#define FT_INTERNAL_TYPE1_TYPES_H <freetype/internal/t1types.h> + +#define FT_INTERNAL_POSTSCRIPT_AUX_H <freetype/internal/psaux.h> +#define FT_INTERNAL_POSTSCRIPT_HINTS_H <freetype/internal/pshints.h> +#define FT_INTERNAL_POSTSCRIPT_GLOBALS_H <freetype/internal/psglobal.h> + +#define FT_INTERNAL_AUTOHINT_H <freetype/internal/autohint.h> + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/pcftypes.h b/Utilities/vtkfreetype/include/freetype/internal/pcftypes.h new file mode 100644 index 0000000..382796f --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/pcftypes.h @@ -0,0 +1,56 @@ +/* pcftypes.h + + FreeType font driver for pcf fonts + + Copyright (C) 2000, 2001, 2002 by + Francesco Zappa Nardelli + +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. +*/ + + +#ifndef __PCFTYPES_H__ +#define __PCFTYPES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + + +FT_BEGIN_HEADER + + + typedef struct PCF_Public_FaceRec_ + { + FT_FaceRec root; + FT_StreamRec gzip_stream; + FT_Stream gzip_source; + + char* charset_encoding; + char* charset_registry; + + } PCF_Public_FaceRec, *PCF_Public_Face; + + +FT_END_HEADER + +#endif /* __PCFTYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/psaux.h b/Utilities/vtkfreetype/include/freetype/internal/psaux.h new file mode 100644 index 0000000..cf1abf4 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/psaux.h @@ -0,0 +1,741 @@ +/***************************************************************************/ +/* */ +/* psaux.h */ +/* */ +/* Auxiliary functions and data structures related to PostScript fonts */ +/* (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSAUX_H__ +#define __PSAUX_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_TYPE1_TYPES_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1_TABLE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + typedef struct PS_TableRec_* PS_Table; + typedef const struct PS_Table_FuncsRec_* PS_Table_Funcs; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_Table_FuncsRec */ + /* */ + /* <Description> */ + /* A set of function pointers to manage PS_Table objects. */ + /* */ + /* <Fields> */ + /* table_init :: Used to initialize a table. */ + /* */ + /* table_done :: Finalizes resp. destroy a given table. */ + /* */ + /* table_add :: Adds a new object to a table. */ + /* */ + /* table_release :: Releases table data, then finalizes it. */ + /* */ + typedef struct PS_Table_FuncsRec_ + { + FT_Error + (*init)( PS_Table table, + FT_Int count, + FT_Memory memory ); + + void + (*done)( PS_Table table ); + + FT_Error + (*add)( PS_Table table, + FT_Int idx, + void* object, + FT_PtrDist length ); + + void + (*release)( PS_Table table ); + + } PS_Table_FuncsRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_TableRec */ + /* */ + /* <Description> */ + /* A PS_Table is a simple object used to store an array of objects in */ + /* a single memory block. */ + /* */ + /* <Fields> */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to */ + /* reallocation. */ + /* */ + /* cursor :: The current top of the grow heap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments by */ + /* 1kByte chunks. */ + /* */ + /* max_elems :: The maximum number of elements in table. */ + /* */ + /* num_elems :: The current number of elements in table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The object used for memory operations */ + /* (alloc/realloc). */ + /* */ + /* funcs :: A table of method pointers for this object. */ + /* */ + typedef struct PS_TableRec_ + { + FT_Byte* block; /* current memory block */ + FT_Offset cursor; /* current cursor in memory block */ + FT_Offset capacity; /* current size of memory block */ + FT_Long init; + + FT_Int max_elems; + FT_Int num_elems; + FT_Byte** elements; /* addresses of table elements */ + FT_PtrDist* lengths; /* lengths of table elements */ + + FT_Memory memory; + PS_Table_FuncsRec funcs; + + } PS_TableRec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 FIELDS & TOKENS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct PS_ParserRec_* PS_Parser; + + typedef struct T1_TokenRec_* T1_Token; + + typedef struct T1_FieldRec_* T1_Field; + + + /* simple enumeration type used to identify token types */ + typedef enum T1_TokenType_ + { + T1_TOKEN_TYPE_NONE = 0, + T1_TOKEN_TYPE_ANY, + T1_TOKEN_TYPE_STRING, + T1_TOKEN_TYPE_ARRAY, + + /* do not remove */ + T1_TOKEN_TYPE_MAX + + } T1_TokenType; + + + /* a simple structure used to identify tokens */ + typedef struct T1_TokenRec_ + { + FT_Byte* start; /* first character of token in input stream */ + FT_Byte* limit; /* first character after the token */ + T1_TokenType type; /* type of token */ + + } T1_TokenRec; + + + /* enumeration type used to identify object fields */ + typedef enum T1_FieldType_ + { + T1_FIELD_TYPE_NONE = 0, + T1_FIELD_TYPE_BOOL, + T1_FIELD_TYPE_INTEGER, + T1_FIELD_TYPE_FIXED, + T1_FIELD_TYPE_FIXED_1000, + T1_FIELD_TYPE_STRING, + T1_FIELD_TYPE_KEY, + T1_FIELD_TYPE_BBOX, + T1_FIELD_TYPE_INTEGER_ARRAY, + T1_FIELD_TYPE_FIXED_ARRAY, + T1_FIELD_TYPE_CALLBACK, + + /* do not remove */ + T1_FIELD_TYPE_MAX + + } T1_FieldType; + + + typedef enum T1_FieldLocation_ + { + T1_FIELD_LOCATION_CID_INFO, + T1_FIELD_LOCATION_FONT_DICT, + T1_FIELD_LOCATION_FONT_INFO, + T1_FIELD_LOCATION_PRIVATE, + T1_FIELD_LOCATION_BBOX, + + /* do not remove */ + T1_FIELD_LOCATION_MAX + + } T1_FieldLocation; + + + typedef void + (*T1_Field_ParseFunc)( FT_Face face, + FT_Pointer parser ); + + + /* structure type used to model object fields */ + typedef struct T1_FieldRec_ + { + const char* ident; /* field identifier */ + T1_FieldLocation location; + T1_FieldType type; /* type of field */ + T1_Field_ParseFunc reader; + FT_UInt offset; /* offset of field in object */ + FT_Byte size; /* size of field in bytes */ + FT_UInt array_max; /* maximal number of elements for */ + /* array */ + FT_UInt count_offset; /* offset of element count for */ + /* arrays */ + } T1_FieldRec; + + +#define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + FT_FIELD_OFFSET( _fname ), \ + FT_FIELD_SIZE( _fname ), \ + 0, 0 \ + }, + +#define T1_NEW_CALLBACK_FIELD( _ident, _reader ) \ + { \ + _ident, T1CODE, T1_FIELD_TYPE_CALLBACK, \ + (T1_Field_ParseFunc)_reader, \ + 0, 0, \ + 0, 0 \ + }, + +#define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + FT_FIELD_OFFSET( _fname ), \ + FT_FIELD_SIZE_DELTA( _fname ), \ + _max, \ + FT_FIELD_OFFSET( num_ ## _fname ) \ + }, + +#define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + FT_FIELD_OFFSET( _fname ), \ + FT_FIELD_SIZE_DELTA( _fname ), \ + _max, 0 \ + }, + + +#define T1_FIELD_BOOL( _ident, _fname ) \ + T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BOOL, _fname ) + +#define T1_FIELD_NUM( _ident, _fname ) \ + T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER, _fname ) + +#define T1_FIELD_FIXED( _ident, _fname ) \ + T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED, _fname ) + +#define T1_FIELD_FIXED_1000( _ident, _fname ) \ + T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_1000, _fname ) + +#define T1_FIELD_STRING( _ident, _fname ) \ + T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_STRING, _fname ) + +#define T1_FIELD_KEY( _ident, _fname ) \ + T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_KEY, _fname ) + +#define T1_FIELD_BBOX( _ident, _fname ) \ + T1_NEW_SIMPLE_FIELD( _ident, T1_FIELD_TYPE_BBOX, _fname ) + + +#define T1_FIELD_NUM_TABLE( _ident, _fname, _fmax ) \ + T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \ + _fname, _fmax ) + +#define T1_FIELD_FIXED_TABLE( _ident, _fname, _fmax ) \ + T1_NEW_TABLE_FIELD( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \ + _fname, _fmax ) + +#define T1_FIELD_NUM_TABLE2( _ident, _fname, _fmax ) \ + T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_INTEGER_ARRAY, \ + _fname, _fmax ) + +#define T1_FIELD_FIXED_TABLE2( _ident, _fname, _fmax ) \ + T1_NEW_TABLE_FIELD2( _ident, T1_FIELD_TYPE_FIXED_ARRAY, \ + _fname, _fmax ) + +#define T1_FIELD_CALLBACK( _ident, _name ) \ + T1_NEW_CALLBACK_FIELD( _ident, _name ) + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef const struct PS_Parser_FuncsRec_* PS_Parser_Funcs; + + typedef struct PS_Parser_FuncsRec_ + { + void + (*init)( PS_Parser parser, + FT_Byte* base, + FT_Byte* limit, + FT_Memory memory ); + + void + (*done)( PS_Parser parser ); + + void + (*skip_spaces)( PS_Parser parser ); + void + (*skip_PS_token)( PS_Parser parser ); + + FT_Long + (*to_int)( PS_Parser parser ); + FT_Fixed + (*to_fixed)( PS_Parser parser, + FT_Int power_ten ); + + FT_Error + (*to_bytes)( PS_Parser parser, + FT_Byte* bytes, + FT_Long max_bytes, + FT_Long* pnum_bytes, + FT_Bool delimiters ); + + FT_Int + (*to_coord_array)( PS_Parser parser, + FT_Int max_coords, + FT_Short* coords ); + FT_Int + (*to_fixed_array)( PS_Parser parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + + void + (*to_token)( PS_Parser parser, + T1_Token token ); + void + (*to_token_array)( PS_Parser parser, + T1_Token tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ); + + FT_Error + (*load_field)( PS_Parser parser, + const T1_Field field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + FT_Error + (*load_field_table)( PS_Parser parser, + const T1_Field field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + } PS_Parser_FuncsRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_ParserRec */ + /* */ + /* <Description> */ + /* A PS_Parser is an object used to parse a Type 1 font very quickly. */ + /* */ + /* <Fields> */ + /* cursor :: The current position in the text. */ + /* */ + /* base :: Start of the processed text. */ + /* */ + /* limit :: End of the processed text. */ + /* */ + /* error :: The last error returned. */ + /* */ + /* memory :: The object used for memory operations (alloc/realloc). */ + /* */ + /* funcs :: A table of functions for the parser. */ + /* */ + typedef struct PS_ParserRec_ + { + FT_Byte* cursor; + FT_Byte* base; + FT_Byte* limit; + FT_Error error; + FT_Memory memory; + + PS_Parser_FuncsRec funcs; + + } PS_ParserRec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + typedef struct T1_BuilderRec_* T1_Builder; + + + typedef FT_Error + (*T1_Builder_Check_Points_Func)( T1_Builder builder, + FT_Int count ); + + typedef void + (*T1_Builder_Add_Point_Func)( T1_Builder builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ); + + typedef FT_Error + (*T1_Builder_Add_Point1_Func)( T1_Builder builder, + FT_Pos x, + FT_Pos y ); + + typedef FT_Error + (*T1_Builder_Add_Contour_Func)( T1_Builder builder ); + + typedef FT_Error + (*T1_Builder_Start_Point_Func)( T1_Builder builder, + FT_Pos x, + FT_Pos y ); + + typedef void + (*T1_Builder_Close_Contour_Func)( T1_Builder builder ); + + + typedef const struct T1_Builder_FuncsRec_* T1_Builder_Funcs; + + typedef struct T1_Builder_FuncsRec_ + { + void + (*init)( T1_Builder builder, + FT_Face face, + FT_Size size, + FT_GlyphSlot slot, + FT_Bool hinting ); + + void + (*done)( T1_Builder builder ); + + T1_Builder_Check_Points_Func check_points; + T1_Builder_Add_Point_Func add_point; + T1_Builder_Add_Point1_Func add_point1; + T1_Builder_Add_Contour_Func add_contour; + T1_Builder_Start_Point_Func start_point; + T1_Builder_Close_Contour_Func close_contour; + + } T1_Builder_FuncsRec; + + + /* an enumeration type to handle charstring parsing states */ + typedef enum T1_ParseState_ + { + T1_Parse_Start, + T1_Parse_Have_Width, + T1_Parse_Have_Moveto, + T1_Parse_Have_Path + + } T1_ParseState; + + + /*************************************************************************/ + /* */ + /* <Structure> */ + /* T1_BuilderRec */ + /* */ + /* <Description> */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* <Fields> */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: XXX */ + /* */ + /* base :: The base glyph outline. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* max_points :: maximum points in builder outline */ + /* */ + /* max_contours :: Maximal number of contours in builder outline. */ + /* */ + /* last :: The last point position. */ + /* */ + /* scale_x :: The horizontal scale (FUnits to sub-pixels). */ + /* */ + /* scale_y :: The vertical scale (FUnits to sub-pixels). */ + /* */ + /* pos_x :: The horizontal translation (if composite glyph). */ + /* */ + /* pos_y :: The vertical translation (if composite glyph). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* bbox :: Unused. */ + /* */ + /* parse_state :: An enumeration which controls the charstring */ + /* parsing state. */ + /* */ + /* load_points :: If this flag is not set, no points are loaded. */ + /* */ + /* no_recurse :: Set but not used. */ + /* */ + /* metrics_only :: A boolean indicating that we only want to compute */ + /* the metrics of a given glyph, not load all of its */ + /* points. */ + /* */ + /* funcs :: An array of function pointers for the builder. */ + /* */ + typedef struct T1_BuilderRec_ + { + FT_Memory memory; + FT_Face face; + FT_GlyphSlot glyph; + FT_GlyphLoader loader; + FT_Outline* base; + FT_Outline* current; + + FT_Vector last; + + FT_Fixed scale_x; + FT_Fixed scale_y; + + FT_Pos pos_x; + FT_Pos pos_y; + + FT_Vector left_bearing; + FT_Vector advance; + + FT_BBox bbox; /* bounding box */ + T1_ParseState parse_state; + FT_Bool load_points; + FT_Bool no_recurse; + FT_Bool shift; + + FT_Bool metrics_only; + + void* hints_funcs; /* hinter-specific */ + void* hints_globals; /* hinter-specific */ + + T1_Builder_FuncsRec funcs; + + } T1_BuilderRec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 DECODER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#if 0 + + /*************************************************************************/ + /* */ + /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ + /* calls during glyph loading. */ + /* */ +#define T1_MAX_SUBRS_CALLS 8 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. A */ + /* minimum of 16 is required. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 32 + +#endif /* 0 */ + + + typedef struct T1_Decoder_ZoneRec_ + { + FT_Byte* cursor; + FT_Byte* base; + FT_Byte* limit; + + } T1_Decoder_ZoneRec, *T1_Decoder_Zone; + + + typedef struct T1_DecoderRec_* T1_Decoder; + typedef const struct T1_Decoder_FuncsRec_* T1_Decoder_Funcs; + + + typedef FT_Error + (*T1_Decoder_Callback)( T1_Decoder decoder, + FT_UInt glyph_index ); + + + typedef struct T1_Decoder_FuncsRec_ + { + FT_Error + (*init)( T1_Decoder decoder, + FT_Face face, + FT_Size size, + FT_GlyphSlot slot, + FT_Byte** glyph_names, + PS_Blend blend, + FT_Bool hinting, + FT_Render_Mode hint_mode, + T1_Decoder_Callback callback ); + + void + (*done)( T1_Decoder decoder ); + + FT_Error + (*parse_charstrings)( T1_Decoder decoder, + FT_Byte* base, + FT_UInt len ); + + } T1_Decoder_FuncsRec; + + + typedef struct T1_DecoderRec_ + { + T1_BuilderRec builder; + + FT_Long stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Long* top; + + T1_Decoder_ZoneRec zones[T1_MAX_SUBRS_CALLS + 1]; + T1_Decoder_Zone zone; + + FT_Service_PsCMaps psnames; /* for seac */ + FT_UInt num_glyphs; + FT_Byte** glyph_names; + + FT_Int lenIV; /* internal for sub routine calls */ + FT_UInt num_subrs; + FT_Byte** subrs; + FT_PtrDist* subrs_len; /* array of subrs length (optional) */ + + FT_Matrix font_matrix; + FT_Vector font_offset; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + PS_Blend blend; /* for multiple master support */ + + FT_Render_Mode hint_mode; + + T1_Decoder_Callback parse_callback; + T1_Decoder_FuncsRec funcs; + + } T1_DecoderRec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 CHARMAPS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef const struct T1_CMap_ClassesRec_* T1_CMap_Classes; + + typedef struct T1_CMap_ClassesRec_ + { + FT_CMap_Class standard; + FT_CMap_Class expert; + FT_CMap_Class custom; + FT_CMap_Class unicode; + + } T1_CMap_ClassesRec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PSAux Module Interface *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct PSAux_ServiceRec_ + { + /* don't use `PS_Table_Funcs' and friends to avoid compiler warnings */ + const PS_Table_FuncsRec* ps_table_funcs; + const PS_Parser_FuncsRec* ps_parser_funcs; + const T1_Builder_FuncsRec* t1_builder_funcs; + const T1_Decoder_FuncsRec* t1_decoder_funcs; + + void + (*t1_decrypt)( FT_Byte* buffer, + FT_Offset length, + FT_UShort seed ); + + T1_CMap_Classes t1_cmap_classes; + + } PSAux_ServiceRec, *PSAux_Service; + + /* backwards-compatible type definition */ + typedef PSAux_ServiceRec PSAux_Interface; + +FT_END_HEADER + +#endif /* __PSAUX_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/pshints.h b/Utilities/vtkfreetype/include/freetype/internal/pshints.h new file mode 100644 index 0000000..cd48f6c --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/pshints.h @@ -0,0 +1,626 @@ +/***************************************************************************/ +/* */ +/* pshints.h */ +/* */ +/* Interface to Postscript-specific (Type 1 and Type 2) hints */ +/* recorders (specification only). These are used to support native */ +/* T1/T2 hints in the "type1", "cid" and "cff" font drivers. */ +/* */ +/* Copyright 2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSHINTS_H__ +#define __PSHINTS_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_TYPE1_TABLES_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INTERNAL REPRESENTATION OF GLOBALS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct PSH_GlobalsRec_* PSH_Globals; + + typedef FT_Error + (*PSH_Globals_NewFunc)( FT_Memory memory, + T1_Private* private_dict, + PSH_Globals* aglobals ); + + typedef FT_Error + (*PSH_Globals_SetScaleFunc)( PSH_Globals globals, + FT_Fixed x_scale, + FT_Fixed y_scale, + FT_Fixed x_delta, + FT_Fixed y_delta ); + + typedef void + (*PSH_Globals_DestroyFunc)( PSH_Globals globals ); + + + typedef struct PSH_Globals_FuncsRec_ + { + PSH_Globals_NewFunc create; + PSH_Globals_SetScaleFunc set_scale; + PSH_Globals_DestroyFunc destroy; + + } PSH_Globals_FuncsRec, *PSH_Globals_Funcs; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PUBLIC TYPE 1 HINTS RECORDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* @type: */ + /* T1_Hints */ + /* */ + /* @description: */ + /* This is a handle to an opaque structure used to record glyph hints */ + /* from a Type 1 character glyph character string. */ + /* */ + /* The methods used to operate on this object are defined by the */ + /* @T1_Hints_FuncsRec structure. Recording glyph hints is normally */ + /* achieved through the following scheme: */ + /* */ + /* - Open a new hint recording session by calling the "open" method. */ + /* This will rewind the recorder and prepare it for new input. */ + /* */ + /* - For each hint found in the glyph charstring, call the */ + /* corresponding method ("stem", "stem3", or "reset"). Note that */ + /* these functions do not return an error code. */ + /* */ + /* - Close the recording session by calling the "close" method. It */ + /* will return an error code if the hints were invalid or something */ + /* strange happened (e.g. memory shortage). */ + /* */ + /* The hints accumulated in the object can later be used by the */ + /* PostScript hinter. */ + /* */ + typedef struct T1_HintsRec_* T1_Hints; + + + /*************************************************************************/ + /* */ + /* @type: */ + /* T1_Hints_Funcs */ + /* */ + /* @description: */ + /* A pointer to the @T1_Hints_FuncsRec structure that defines the */ + /* API of a given @T1_Hints object. */ + /* */ + typedef const struct T1_Hints_FuncsRec_* T1_Hints_Funcs; + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T1_Hints_OpenFunc */ + /* */ + /* @description: */ + /* A method of the @T1_Hints class used to prepare it for a new */ + /* Type 1 hints recording session. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 1 hints recorder. */ + /* */ + /* @note: */ + /* You should always call the @T1_Hints_CloseFunc method in order to */ + /* close an opened recording session. */ + /* */ + typedef void + (*T1_Hints_OpenFunc)( T1_Hints hints ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T1_Hints_SetStemFunc */ + /* */ + /* @description: */ + /* A method of the @T1_Hints class used to record a new horizontal or */ + /* vertical stem. This corresponds to the Type 1 "hstem" and "vstem" */ + /* operators. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 1 hints recorder. */ + /* */ + /* dimension :: 0 for horizontal stems (hstem), 1 for vertical ones */ + /* (vstem). */ + /* */ + /* coords :: Array of 2 integers, used as (position,length) stem */ + /* descriptor. */ + /* */ + /* @note: */ + /* Use vertical coordinates (y) for horizontal stems (dim=0). Use */ + /* horizontal coordinates (x) for vertical stems (dim=1). */ + /* */ + /* "coords[0]" is the absolute stem position (lowest coordinate); */ + /* "coords[1]" is the length. */ + /* */ + /* The length can be negative, in which case it must be either -20 or */ + /* -21. It will be interpreted as a "ghost" stem, according to */ + /* Type 1 specification. */ + /* */ + /* If the length is -21 (corresponding to a bottom ghost stem), then */ + /* the real stem position is "coords[0]+coords[1]". */ + /* */ + typedef void + (*T1_Hints_SetStemFunc)( T1_Hints hints, + FT_UInt dimension, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T1_Hints_SetStem3Func */ + /* */ + /* @description: */ + /* A method of the @T1_Hints class used to record three */ + /* counter-controlled horizontal or vertical stems at once. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 1 hints recorder. */ + /* */ + /* dimension :: 0 for horizontal stems, 1 for vertical ones. */ + /* */ + /* coords :: An array of 6 integers, holding 3 (position,length) */ + /* pairs for the counter-controlled stems. */ + /* */ + /* @note: */ + /* Use vertical coordinates (y) for horizontal stems (dim=0). Use */ + /* horizontal coordinates (x) for vertical stems (dim=1). */ + /* */ + /* The lengths cannot be negative (ghost stems are never */ + /* counter-controlled). */ + /* */ + typedef void + (*T1_Hints_SetStem3Func)( T1_Hints hints, + FT_UInt dimension, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T1_Hints_ResetFunc */ + /* */ + /* @description: */ + /* A method of the @T1_Hints class used to reset the stems hints in a */ + /* recording session. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 1 hints recorder. */ + /* */ + /* end_point :: The index of the last point in the input glyph in */ + /* which the previously defined hints apply. */ + /* */ + typedef void + (*T1_Hints_ResetFunc)( T1_Hints hints, + FT_UInt end_point ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T1_Hints_CloseFunc */ + /* */ + /* @description: */ + /* A method of the @T1_Hints class used to close a hint recording */ + /* session. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 1 hints recorder. */ + /* */ + /* end_point :: The index of the last point in the input glyph. */ + /* */ + /* @return: */ + /* FreeType error code. 0 means success. */ + /* */ + /* @note: */ + /* The error code will be set to indicate that an error occured */ + /* during the recording session. */ + /* */ + typedef FT_Error + (*T1_Hints_CloseFunc)( T1_Hints hints, + FT_UInt end_point ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T1_Hints_ApplyFunc */ + /* */ + /* @description: */ + /* A method of the @T1_Hints class used to apply hints to the */ + /* corresponding glyph outline. Must be called once all hints have */ + /* been recorded. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 1 hints recorder. */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* globals :: The hinter globals for this font. */ + /* */ + /* hint_mode :: Hinting information. */ + /* */ + /* @return: */ + /* FreeType error code. 0 means success. */ + /* */ + /* @note: */ + /* On input, all points within the outline are in font coordinates. */ + /* On output, they are in 1/64th of pixels. */ + /* */ + /* The scaling transformation is taken from the "globals" object */ + /* which must correspond to the same font as the glyph. */ + /* */ + typedef FT_Error + (*T1_Hints_ApplyFunc)( T1_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ); + + + /*************************************************************************/ + /* */ + /* @struct: */ + /* T1_Hints_FuncsRec */ + /* */ + /* @description: */ + /* The structure used to provide the API to @T1_Hints objects. */ + /* */ + /* @fields: */ + /* hints :: A handle to the T1 Hints recorder. */ + /* */ + /* open :: The function to open a recording session. */ + /* */ + /* close :: The function to close a recording session. */ + /* */ + /* stem :: The function to set a simple stem. */ + /* */ + /* stem3 :: The function to set counter-controlled stems. */ + /* */ + /* reset :: The function to reset stem hints. */ + /* */ + /* apply :: The function to apply the hints to the corresponding */ + /* glyph outline. */ + /* */ + typedef struct T1_Hints_FuncsRec_ + { + T1_Hints hints; + T1_Hints_OpenFunc open; + T1_Hints_CloseFunc close; + T1_Hints_SetStemFunc stem; + T1_Hints_SetStem3Func stem3; + T1_Hints_ResetFunc reset; + T1_Hints_ApplyFunc apply; + + } T1_Hints_FuncsRec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PUBLIC TYPE 2 HINTS RECORDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* @type: */ + /* T2_Hints */ + /* */ + /* @description: */ + /* This is a handle to an opaque structure used to record glyph hints */ + /* from a Type 2 character glyph character string. */ + /* */ + /* The methods used to operate on this object are defined by the */ + /* @T2_Hints_FuncsRec structure. Recording glyph hints is normally */ + /* achieved through the following scheme: */ + /* */ + /* - Open a new hint recording session by calling the "open" method. */ + /* This will rewind the recorder and prepare it for new input. */ + /* */ + /* - For each hint found in the glyph charstring, call the */ + /* corresponding method ("stems", "hintmask", "counters"). Note */ + /* that these functions do not return an error code. */ + /* */ + /* - Close the recording session by calling the "close" method. It */ + /* will return an error code if the hints were invalid or something */ + /* strange happened (e.g. memory shortage). */ + /* */ + /* The hints accumulated in the object can later be used by the */ + /* Postscript hinter. */ + /* */ + typedef struct T2_HintsRec_* T2_Hints; + + + /*************************************************************************/ + /* */ + /* @type: */ + /* T2_Hints_Funcs */ + /* */ + /* @description: */ + /* A pointer to the @T2_Hints_FuncsRec structure that defines the API */ + /* of a given @T2_Hints object. */ + /* */ + typedef const struct T2_Hints_FuncsRec_* T2_Hints_Funcs; + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T2_Hints_OpenFunc */ + /* */ + /* @description: */ + /* A method of the @T2_Hints class used to prepare it for a new */ + /* Type 2 hints recording session. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 2 hints recorder. */ + /* */ + /* @note: */ + /* You should always call the @T2_Hints_CloseFunc method in order to */ + /* close an opened recording session. */ + /* */ + typedef void + (*T2_Hints_OpenFunc)( T2_Hints hints ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T2_Hints_StemsFunc */ + /* */ + /* @description: */ + /* A method of the @T2_Hints class used to set the table of stems in */ + /* either the vertical or horizontal dimension. Equivalent to the */ + /* "hstem", "vstem", "hstemhm", and "vstemhm" Type 2 operators. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 2 hints recorder. */ + /* */ + /* dimension :: 0 for horizontal stems (hstem), 1 for vertical ones */ + /* (vstem). */ + /* */ + /* count :: The number of stems. */ + /* */ + /* coords :: An array of "count" (position,length) pairs. */ + /* */ + /* @note: */ + /* Use vertical coordinates (y) for horizontal stems (dim=0). Use */ + /* horizontal coordinates (x) for vertical stems (dim=1). */ + /* */ + /* There are "2*count" elements in the "coords" aray. Each even */ + /* element is an absolute position in font units, each odd element is */ + /* a length in font units. */ + /* */ + /* A length can be negative, in which case it must be either -20 or */ + /* -21. It will be interpreted as a "ghost" stem, according to the */ + /* Type 1 specification. */ + /* */ + typedef void + (*T2_Hints_StemsFunc)( T2_Hints hints, + FT_UInt dimension, + FT_UInt count, + FT_Fixed* coordinates ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T2_Hints_MaskFunc */ + /* */ + /* @description: */ + /* A method of the @T2_Hints class used to set a given hintmask */ + /* (this corresponds to the "hintmask" Type 2 operator). */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 2 hints recorder. */ + /* */ + /* end_point :: The glyph index of the last point to which the */ + /* previously defined/activated hints apply. */ + /* */ + /* bit_count :: The number of bits in the hint mask. */ + /* */ + /* bytes :: An array of bytes modelling the hint mask. */ + /* */ + /* @note: */ + /* If the hintmask starts the charstring (before any glyph point */ + /* definition), the value of "end_point" should be 0. */ + /* */ + /* "bit_count" is the number of meaningful bits in the "bytes" array; */ + /* it must be equal to the total number of hints defined so far */ + /* (i.e. horizontal+verticals). */ + /* */ + /* The "bytes" array can come directly from the Type 2 charstring and */ + /* respects the same format. */ + /* */ + typedef void + (*T2_Hints_MaskFunc)( T2_Hints hints, + FT_UInt end_point, + FT_UInt bit_count, + const FT_Byte* bytes ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T2_Hints_CounterFunc */ + /* */ + /* @description: */ + /* A method of the @T2_Hints class used to set a given counter mask */ + /* (this corresponds to the "hintmask" Type 2 operator). */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 2 hints recorder. */ + /* */ + /* end_point :: A glyph index of the last point to which the */ + /* previously defined/active hints apply. */ + /* */ + /* bit_count :: The number of bits in the hint mask. */ + /* */ + /* bytes :: An array of bytes modelling the hint mask. */ + /* */ + /* @note: */ + /* If the hintmask starts the charstring (before any glyph point */ + /* definition), the value of "end_point" should be 0. */ + /* */ + /* "bit_count" is the number of meaningful bits in the "bytes" array; */ + /* it must be equal to the total number of hints defined so far */ + /* (i.e. horizontal+verticals). */ + /* */ + /* The "bytes" array can come directly from the Type 2 charstring and */ + /* respects the same format. */ + /* */ + typedef void + (*T2_Hints_CounterFunc)( T2_Hints hints, + FT_UInt bit_count, + const FT_Byte* bytes ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T2_Hints_CloseFunc */ + /* */ + /* @description: */ + /* A method of the @T2_Hints class used to close a hint recording */ + /* session. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 2 hints recorder. */ + /* */ + /* end_point :: The index of the last point in the input glyph. */ + /* */ + /* @return: */ + /* FreeType error code. 0 means success. */ + /* */ + /* @note: */ + /* The error code will be set to indicate that an error occured */ + /* during the recording session. */ + /* */ + typedef FT_Error + (*T2_Hints_CloseFunc)( T2_Hints hints, + FT_UInt end_point ); + + + /*************************************************************************/ + /* */ + /* @functype: */ + /* T2_Hints_ApplyFunc */ + /* */ + /* @description: */ + /* A method of the @T2_Hints class used to apply hints to the */ + /* corresponding glyph outline. Must be called after the "close" */ + /* method. */ + /* */ + /* @input: */ + /* hints :: A handle to the Type 2 hints recorder. */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* globals :: The hinter globals for this font. */ + /* */ + /* hint_mode :: Hinting information. */ + /* */ + /* @return: */ + /* FreeType error code. 0 means success. */ + /* */ + /* @note: */ + /* On input, all points within the outline are in font coordinates. */ + /* On output, they are in 1/64th of pixels. */ + /* */ + /* The scaling transformation is taken from the "globals" object */ + /* which must correspond to the same font than the glyph. */ + /* */ + typedef FT_Error + (*T2_Hints_ApplyFunc)( T2_Hints hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ); + + + /*************************************************************************/ + /* */ + /* @struct: */ + /* T2_Hints_FuncsRec */ + /* */ + /* @description: */ + /* The structure used to provide the API to @T2_Hints objects. */ + /* */ + /* @fields: */ + /* hints :: A handle to the T2 hints recorder object. */ + /* */ + /* open :: The function to open a recording session. */ + /* */ + /* close :: The function to close a recording session. */ + /* */ + /* stems :: The function to set the dimension's stems table. */ + /* */ + /* hintmask :: The function to set hint masks. */ + /* */ + /* counter :: The function to set counter masks. */ + /* */ + /* apply :: The function to apply the hints on the corresponding */ + /* glyph outline. */ + /* */ + typedef struct T2_Hints_FuncsRec_ + { + T2_Hints hints; + T2_Hints_OpenFunc open; + T2_Hints_CloseFunc close; + T2_Hints_StemsFunc stems; + T2_Hints_MaskFunc hintmask; + T2_Hints_CounterFunc counter; + T2_Hints_ApplyFunc apply; + + } T2_Hints_FuncsRec; + + + /* */ + + + typedef struct PSHinter_Interface_ + { + PSH_Globals_Funcs (*get_globals_funcs)( FT_Module module ); + T1_Hints_Funcs (*get_t1_funcs) ( FT_Module module ); + T2_Hints_Funcs (*get_t2_funcs) ( FT_Module module ); + + } PSHinter_Interface; + + typedef PSHinter_Interface* PSHinter_Service; + + +FT_END_HEADER + +#endif /* __PSHINTS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svbdf.h b/Utilities/vtkfreetype/include/freetype/internal/services/svbdf.h new file mode 100644 index 0000000..0f7fc61 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svbdf.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* svbdf.h */ +/* */ +/* The FreeType BDF services (specification). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVBDF_H__ +#define __SVBDF_H__ + +#include FT_BDF_H +#include FT_INTERNAL_SERVICE_H + + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_BDF "bdf" + + typedef FT_Error + (*FT_BDF_GetCharsetIdFunc)( FT_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ); + + typedef FT_Error + (*FT_BDF_GetPropertyFunc)( FT_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ); + + + FT_DEFINE_SERVICE( BDF ) + { + FT_BDF_GetCharsetIdFunc get_charset_id; + FT_BDF_GetPropertyFunc get_property; + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVBDF_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svgldict.h b/Utilities/vtkfreetype/include/freetype/internal/services/svgldict.h new file mode 100644 index 0000000..e5e56b2 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svgldict.h @@ -0,0 +1,60 @@ +/***************************************************************************/ +/* */ +/* svgldict.h */ +/* */ +/* The FreeType glyph dictionary services (specification). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVGLDICT_H__ +#define __SVGLDICT_H__ + +#include FT_INTERNAL_SERVICE_H + + +FT_BEGIN_HEADER + + + /* + * A service used to retrieve glyph names, as well as to find the + * index of a given glyph name in a font. + * + */ + +#define FT_SERVICE_ID_GLYPH_DICT "glyph-dict" + + + typedef FT_Error + (*FT_GlyphDict_GetNameFunc)( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + typedef FT_UInt + (*FT_GlyphDict_NameIndexFunc)( FT_Face face, + FT_String* glyph_name ); + + + FT_DEFINE_SERVICE( GlyphDict ) + { + FT_GlyphDict_GetNameFunc get_name; + FT_GlyphDict_NameIndexFunc name_index; /* optional */ + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVGLDICT_H__ */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svmm.h b/Utilities/vtkfreetype/include/freetype/internal/services/svmm.h new file mode 100644 index 0000000..8a99ec4 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svmm.h @@ -0,0 +1,79 @@ +/***************************************************************************/ +/* */ +/* svmm.h */ +/* */ +/* The FreeType Multiple Masters and GX var services (specification). */ +/* */ +/* Copyright 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVMM_H__ +#define __SVMM_H__ + +#include FT_INTERNAL_SERVICE_H + + +FT_BEGIN_HEADER + + + /* + * A service used to manage multiple-masters data in a given face. + * + * See the related APIs in `ftmm.h' (FT_MULTIPLE_MASTERS_H). + * + */ + +#define FT_SERVICE_ID_MULTI_MASTERS "multi-masters" + + + typedef FT_Error + (*FT_Get_MM_Func)( FT_Face face, + FT_Multi_Master* master ); + + typedef FT_Error + (*FT_Get_MM_Var_Func)( FT_Face face, + FT_MM_Var* *master ); + + typedef FT_Error + (*FT_Set_MM_Design_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + typedef FT_Error + (*FT_Set_Var_Design_Func)( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + typedef FT_Error + (*FT_Set_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + FT_DEFINE_SERVICE( MultiMasters ) + { + FT_Get_MM_Func get_mm; + FT_Set_MM_Design_Func set_mm_design; + FT_Set_MM_Blend_Func set_mm_blend; + FT_Get_MM_Var_Func get_mm_var; + FT_Set_Var_Design_Func set_var_design; + }; + + /* */ + + +FT_END_HEADER + +#endif /* __SVMM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svpfr.h b/Utilities/vtkfreetype/include/freetype/internal/services/svpfr.h new file mode 100644 index 0000000..b610505 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svpfr.h @@ -0,0 +1,65 @@ +/***************************************************************************/ +/* */ +/* svpfr.h */ +/* */ +/* Internal PFR service functions (specification). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVPFR_H__ +#define __SVPFR_H__ + +#include FT_INTERNAL_SERVICE_H + + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_PFR_METRICS "pfr-metrics" + + + typedef FT_Error + (*FT_PFR_GetMetricsFunc)( FT_Face face, + FT_UInt *aoutline, + FT_UInt *ametrics, + FT_Fixed *ax_scale, + FT_Fixed *ay_scale ); + + typedef FT_Error + (*FT_PFR_GetKerningFunc)( FT_Face face, + FT_UInt left, + FT_UInt right, + FT_Vector *avector ); + + typedef FT_Error + (*FT_PFR_GetAdvanceFunc)( FT_Face face, + FT_UInt gindex, + FT_Pos *aadvance ); + + + FT_DEFINE_SERVICE( PfrMetrics ) + { + FT_PFR_GetMetricsFunc get_metrics; + FT_PFR_GetKerningFunc get_kerning; + FT_PFR_GetAdvanceFunc get_advance; + + }; + + /* */ + +FT_END_HEADER + +#endif /* __SVPFR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svpostnm.h b/Utilities/vtkfreetype/include/freetype/internal/services/svpostnm.h new file mode 100644 index 0000000..7f1700a --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svpostnm.h @@ -0,0 +1,58 @@ +/***************************************************************************/ +/* */ +/* svpostnm.h */ +/* */ +/* The FreeType PostScript name services (specification). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVPOSTNM_H__ +#define __SVPOSTNM_H__ + +#include FT_INTERNAL_SERVICE_H + + +FT_BEGIN_HEADER + + /* + * A trivial service used to retrieve the PostScript name of a given + * font when available. The `get_name' field should never be NULL. + * + * The correponding function can return NULL to indicate that the + * PostScript name is not available. + * + * The name is owned by the face and will be destroyed with it. + */ + +#define FT_SERVICE_ID_POSTSCRIPT_FONT_NAME "postscript-font-name" + + + typedef const char* + (*FT_PsName_GetFunc)( FT_Face face ); + + + FT_DEFINE_SERVICE( PsFontName ) + { + FT_PsName_GetFunc get_ps_font_name; + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVPOSTNM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svpscmap.h b/Utilities/vtkfreetype/include/freetype/internal/services/svpscmap.h new file mode 100644 index 0000000..ade96ef --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svpscmap.h @@ -0,0 +1,113 @@ +/***************************************************************************/ +/* */ +/* svpscmap.h */ +/* */ +/* The FreeType PostScript charmap service (specification). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVPSCMAP_H__ +#define __SVPSCMAP_H__ + + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_POSTSCRIPT_CMAPS "postscript-cmaps" + + + /* + * Adobe glyph name to unicode value + */ + typedef FT_UInt32 + (*PS_Unicode_ValueFunc)( const char* glyph_name ); + + /* + * Unicode value to Adobe glyph name index. 0xFFFF if not found. + */ + typedef FT_UInt + (*PS_Unicode_Index_Func)( FT_UInt num_glyphs, + const char** glyph_names, + FT_ULong unicode ); + + /* + * Macintosh name id to glyph name. NULL if invalid index. + */ + typedef const char* + (*PS_Macintosh_Name_Func)( FT_UInt name_index ); + + /* + * Adobe standard string ID to glyph name. NULL if invalid index. + */ + typedef const char* + (*PS_Adobe_Std_Strings_Func)( FT_UInt string_index ); + + /* + * Simple unicode -> glyph index charmap built from font glyph names + * table. + */ + typedef struct PS_UniMap_ + { + FT_UInt unicode; + FT_UInt glyph_index; + + } PS_UniMap; + + + typedef struct PS_Unicodes_ + { + FT_UInt num_maps; + PS_UniMap* maps; + + } PS_Unicodes; + + + typedef FT_Error + (*PS_Unicodes_InitFunc)( FT_Memory memory, + FT_UInt num_glyphs, + const char** glyph_names, + PS_Unicodes* unicodes ); + + typedef FT_UInt + (*PS_Unicodes_CharIndexFunc)( PS_Unicodes* unicodes, + FT_UInt unicode ); + + typedef FT_ULong + (*PS_Unicodes_CharNextFunc)( PS_Unicodes* unicodes, + FT_ULong unicode ); + + + FT_DEFINE_SERVICE( PsCMaps ) + { + PS_Unicode_ValueFunc unicode_value; + + PS_Unicodes_InitFunc unicodes_init; + PS_Unicodes_CharIndexFunc unicodes_char_index; + PS_Unicodes_CharNextFunc unicodes_char_next; + + PS_Macintosh_Name_Func macintosh_name; + PS_Adobe_Std_Strings_Func adobe_std_strings; + const unsigned short* adobe_std_encoding; + const unsigned short* adobe_expert_encoding; + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVPSCMAP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svpsinfo.h b/Utilities/vtkfreetype/include/freetype/internal/services/svpsinfo.h new file mode 100644 index 0000000..73c02cd --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svpsinfo.h @@ -0,0 +1,55 @@ +/***************************************************************************/ +/* */ +/* svpsinfo.h */ +/* */ +/* The FreeType PostScript info service (specification). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVPSINFO_H__ +#define __SVPSINFO_H__ + +#include FT_INTERNAL_SERVICE_H +#include FT_INTERNAL_TYPE1_TYPES_H + + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_POSTSCRIPT_INFO "postscript-info" + + + typedef FT_Error + (*PS_GetFontInfoFunc)( FT_Face face, + PS_FontInfoRec* afont_info ); + + typedef FT_Int + (*PS_HasGlyphNamesFunc)( FT_Face face ); + + + FT_DEFINE_SERVICE( PsInfo ) + { + PS_GetFontInfoFunc ps_get_font_info; + PS_HasGlyphNamesFunc ps_has_glyph_names; + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVPSINFO_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svsfnt.h b/Utilities/vtkfreetype/include/freetype/internal/services/svsfnt.h new file mode 100644 index 0000000..cdd0751 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svsfnt.h @@ -0,0 +1,80 @@ +/***************************************************************************/ +/* */ +/* svsfnt.h */ +/* */ +/* The FreeType PostScript name services (specification). */ +/* */ +/* Copyright 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVSFNT_H__ +#define __SVSFNT_H__ + +#include FT_INTERNAL_SERVICE_H +#include FT_TRUETYPE_TABLES_H + + +FT_BEGIN_HEADER + + + /* + * SFNT table loading service. + */ + +#define FT_SERVICE_ID_SFNT_TABLE "sfnt-table" + + + /* + * Used to implement FT_Load_Sfnt_Table(). + */ + typedef FT_Error + (*FT_SFNT_TableLoadFunc)( FT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + /* + * Used to implement FT_Get_Sfnt_Table(). + */ + typedef void* + (*FT_SFNT_TableGetFunc)( FT_Face face, + FT_Sfnt_Tag tag ); + + + /* + * Used to implement FT_Sfnt_Table_Info(). + */ + typedef FT_Error + (*FT_SFNT_TableInfoFunc)( FT_Face face, + FT_UInt idx, + FT_ULong *tag, + FT_ULong *length ); + + + FT_DEFINE_SERVICE( SFNT_Table ) + { + FT_SFNT_TableLoadFunc load_table; + FT_SFNT_TableGetFunc get_table; + FT_SFNT_TableInfoFunc table_info; + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVSFNT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svttcmap.h b/Utilities/vtkfreetype/include/freetype/internal/services/svttcmap.h new file mode 100644 index 0000000..f92fcd0 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svttcmap.h @@ -0,0 +1,77 @@ +/***************************************************************************/ +/* */ +/* svsttcmap.h */ +/* */ +/* The FreeType TrueType/sfnt cmap extra information service. */ +/* */ +/* Copyright 2003 by */ +/* Masatake YAMATO, Redhat K.K. */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +/* Development of this service is support of + Information-technology Promotion Agency, Japan. */ + +#ifndef __SVTTCMAP_H__ +#define __SVTTCMAP_H__ + +#include FT_INTERNAL_SERVICE_H +#include FT_TRUETYPE_TABLES_H + + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_TT_CMAP "tt-cmaps" + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_CMapInfo */ + /* */ + /* <Description> */ + /* A structure used to store TrueType/sfnt specific cmap information */ + /* which is not covered by the generic @FT_CharMap structure. This */ + /* structure can be accessed with the @FT_Get_TT_CMap_Info function. */ + /* */ + /* <Fields> */ + /* language :: */ + /* The language ID used in Mac fonts. Definitions of values are in */ + /* freetype/ttnameid.h. */ + /* */ + typedef struct TT_CMapInfo_ + { + FT_ULong language; + + } TT_CMapInfo; + + + typedef FT_Error + (*TT_CMap_Info_GetFunc)( FT_CharMap charmap, + TT_CMapInfo *cmap_info ); + + + FT_DEFINE_SERVICE( TTCMaps ) + { + TT_CMap_Info_GetFunc get_cmap_info; + }; + + /* */ + + +FT_END_HEADER + +#endif /* __SVTTCMAP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svwinfnt.h b/Utilities/vtkfreetype/include/freetype/internal/services/svwinfnt.h new file mode 100644 index 0000000..57f7765 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svwinfnt.h @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* */ +/* svwinfnt.h */ +/* */ +/* The FreeType Windows FNT/FONT service (specification). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVWINFNT_H__ +#define __SVWINFNT_H__ + +#include FT_INTERNAL_SERVICE_H +#include FT_WINFONTS_H + + +FT_BEGIN_HEADER + + +#define FT_SERVICE_ID_WINFNT "winfonts" + + typedef FT_Error + (*FT_WinFnt_GetHeaderFunc)( FT_Face face, + FT_WinFNT_HeaderRec *aheader ); + + + FT_DEFINE_SERVICE( WinFnt ) + { + FT_WinFnt_GetHeaderFunc get_header; + }; + + /* */ + + +FT_END_HEADER + + +#endif /* __SVWINFNT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/services/svxf86nm.h b/Utilities/vtkfreetype/include/freetype/internal/services/svxf86nm.h new file mode 100644 index 0000000..3a33abc --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/services/svxf86nm.h @@ -0,0 +1,55 @@ +/***************************************************************************/ +/* */ +/* svxf86nm.h */ +/* */ +/* The FreeType XFree86 services (specification only). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SVXF86NM_H__ +#define __SVXF86NM_H__ + +#include FT_INTERNAL_SERVICE_H + + +FT_BEGIN_HEADER + + + /* + * A trivial service used to return the name of a face's font driver, + * according to the XFree86 nomenclature. Note that the service data + * is a simple constant string pointer. + */ + +#define FT_SERVICE_ID_XF86_NAME "xf86-driver-name" + +#define FT_XF86_FORMAT_TRUETYPE "TrueType" +#define FT_XF86_FORMAT_TYPE_1 "Type 1" +#define FT_XF86_FORMAT_BDF "BDF" +#define FT_XF86_FORMAT_PCF "PCF" +#define FT_XF86_FORMAT_TYPE_42 "Type 42" +#define FT_XF86_FORMAT_CID "CID Type 1" +#define FT_XF86_FORMAT_CFF "CFF" +#define FT_XF86_FORMAT_PFR "PFR" +#define FT_XF86_FORMAT_WINFNT "Windows FNT" + + /* */ + + +FT_END_HEADER + + +#endif /* __SVXF86NM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/sfnt.h b/Utilities/vtkfreetype/include/freetype/internal/sfnt.h new file mode 100644 index 0000000..9a23b1f --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/sfnt.h @@ -0,0 +1,553 @@ +/***************************************************************************/ +/* */ +/* sfnt.h */ +/* */ +/* High-level `sfnt' driver interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SFNT_H__ +#define __SFNT_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H +#include FT_INTERNAL_TRUETYPE_TYPES_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Init_Face_Func */ + /* */ + /* <Description> */ + /* First part of the SFNT face object initialization. This will find */ + /* the face in a SFNT file or collection, and load its format tag in */ + /* face->format_tag. */ + /* */ + /* <Input> */ + /* stream :: The input stream. */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* params :: Optional additional parameters. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType */ + /* collection'. */ + /* */ + /* Once the format tag has been validated by the font driver, it */ + /* should then call the TT_Load_Face_Func() callback to read the rest */ + /* of the SFNT tables in the object. */ + /* */ + typedef FT_Error + (*TT_Init_Face_Func)( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_Face_Func */ + /* */ + /* <Description> */ + /* Second part of the SFNT face object initialization. This will */ + /* load the common SFNT tables (head, OS/2, maxp, metrics, etc.) in */ + /* the face object. */ + /* */ + /* <Input> */ + /* stream :: The input stream. */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* params :: Optional additional parameters. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function must be called after TT_Init_Face_Func(). */ + /* */ + typedef FT_Error + (*TT_Load_Face_Func)( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Done_Face_Func */ + /* */ + /* <Description> */ + /* A callback used to delete the common SFNT data from a face. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Note> */ + /* This function does NOT destroy the face object. */ + /* */ + typedef void + (*TT_Done_Face_Func)( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_SFNT_HeaderRec_Func */ + /* */ + /* <Description> */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* <Output> */ + /* sfnt :: The SFNT header. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType */ + /* collection'. */ + /* */ + /* This function checks that the header is valid by looking at the */ + /* values of `search_range', `entry_selector', and `range_shift'. */ + /* */ + typedef FT_Error + (*TT_Load_SFNT_HeaderRec_Func)( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header sfnt ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_Directory_Func */ + /* */ + /* <Description> */ + /* Loads the table directory into a face object. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be on the first byte after the 4-byte font */ + /* format tag. This is the case just after a call to */ + /* TT_Load_Format_Tag(). */ + /* */ + typedef FT_Error + (*TT_Load_Directory_Func)( TT_Face face, + FT_Stream stream, + SFNT_Header sfnt ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_Any_Func */ + /* */ + /* <Description> */ + /* Loads any font table into client memory. */ + /* */ + /* <Input> */ + /* face :: The face object to look for. */ + /* */ + /* tag :: The tag of table to load. Use the value 0 if you want */ + /* to access the whole font file, else set this parameter */ + /* to a valid TrueType table tag that you can forge with */ + /* the MAKE_TT_TAG macro. */ + /* */ + /* offset :: The starting offset in the table (or the file if */ + /* tag == 0). */ + /* */ + /* length :: The address of the decision variable: */ + /* */ + /* If length == NULL: */ + /* Loads the whole table. Returns an error if */ + /* `offset' == 0! */ + /* */ + /* If *length == 0: */ + /* Exits immediately; returning the length of the given */ + /* table or of the font file, depending on the value of */ + /* `tag'. */ + /* */ + /* If *length != 0: */ + /* Loads the next `length' bytes of table or font, */ + /* starting at offset `offset' (in table or font too). */ + /* */ + /* <Output> */ + /* buffer :: The address of target buffer. */ + /* */ + /* <Return> */ + /* TrueType error code. 0 means success. */ + /* */ + typedef FT_Error + (*TT_Load_Any_Func)( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte *buffer, + FT_ULong* length ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Find_SBit_Image_Func */ + /* */ + /* <Description> */ + /* Checks whether an embedded bitmap (an `sbit') exists for a given */ + /* glyph, at a given strike. */ + /* */ + /* <Input> */ + /* face :: The target face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* strike_index :: The current strike index. */ + /* */ + /* <Output> */ + /* arange :: The SBit range containing the glyph index. */ + /* */ + /* astrike :: The SBit strike containing the glyph index. */ + /* */ + /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. Returns */ + /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */ + /* glyph. */ + /* */ + typedef FT_Error + (*TT_Find_SBit_Image_Func)( TT_Face face, + FT_UInt glyph_index, + FT_ULong strike_index, + TT_SBit_Range *arange, + TT_SBit_Strike *astrike, + FT_ULong *aglyph_offset ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_SBit_Metrics_Func */ + /* */ + /* <Description> */ + /* Gets the big metrics for a given embedded bitmap. */ + /* */ + /* <Input> */ + /* stream :: The input stream. */ + /* */ + /* range :: The SBit range containing the glyph. */ + /* */ + /* <Output> */ + /* big_metrics :: A big SBit metrics structure for the glyph. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be positioned at the glyph's offset within */ + /* the `EBDT' table before the call. */ + /* */ + /* If the image format uses variable metrics, the stream cursor is */ + /* positioned just after the metrics header in the `EBDT' table on */ + /* function exit. */ + /* */ + typedef FT_Error + (*TT_Load_SBit_Metrics_Func)( FT_Stream stream, + TT_SBit_Range range, + TT_SBit_Metrics metrics ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_SBit_Image_Func */ + /* */ + /* <Description> */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* <Input> */ + /* face :: */ + /* The target face object. */ + /* */ + /* strike_index :: */ + /* The strike index. */ + /* */ + /* glyph_index :: */ + /* The current glyph index. */ + /* */ + /* load_flags :: */ + /* The current load flags. */ + /* */ + /* stream :: */ + /* The input stream. */ + /* */ + /* <Output> */ + /* amap :: */ + /* The target pixmap. */ + /* */ + /* ametrics :: */ + /* A big sbit metrics structure for the glyph image. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* <Note> */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + typedef FT_Error + (*TT_Load_SBit_Image_Func)( TT_Face face, + FT_ULong strike_index, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap *amap, + TT_SBit_MetricsRec *ametrics ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Set_SBit_Strike_Func */ + /* */ + /* <Description> */ + /* Selects an sbit strike for given horizontal and vertical ppem */ + /* values. */ + /* */ + /* <Input> */ + /* face :: The target face object. */ + /* */ + /* x_ppem :: The horizontal resolution in points per EM. */ + /* */ + /* y_ppem :: The vertical resolution in points per EM. */ + /* */ + /* <Output> */ + /* astrike_index :: The index of the sbit strike. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* sbit strike exists for the selected ppem values. */ + /* */ + typedef FT_Error + (*TT_Set_SBit_Strike_Func)( TT_Face face, + FT_UInt x_ppem, + FT_UInt y_ppem, + FT_ULong *astrike_index ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Get_PS_Name_Func */ + /* */ + /* <Description> */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* <Input> */ + /* idx :: The glyph index. */ + /* */ + /* PSname :: The address of a string pointer. Will be NULL in case */ + /* of error, otherwise it is a pointer to the glyph name. */ + /* */ + /* You must not modify the returned string! */ + /* */ + /* <Output> */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error + (*TT_Get_PS_Name_Func)( TT_Face face, + FT_UInt idx, + FT_String** PSname ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_Metrics_Func */ + /* */ + /* <Description> */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error + (*TT_Load_Metrics_Func)( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Load_Table_Func */ + /* */ + /* <Description> */ + /* Loads a given TrueType table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The function will use `face->goto_table' to seek the stream to */ + /* the start of the table. */ + /* */ + typedef FT_Error + (*TT_Load_Table_Func)( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Free_Table_Func */ + /* */ + /* <Description> */ + /* Frees a given TrueType table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + typedef void + (*TT_Free_Table_Func)( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* SFNT_Interface */ + /* */ + /* <Description> */ + /* This structure holds pointers to the functions used to load and */ + /* free the basic tables that are required in a `sfnt' font file. */ + /* */ + /* <Fields> */ + /* Check the various xxx_Func() descriptions for details. */ + /* */ + typedef struct SFNT_Interface_ + { + TT_Loader_GotoTableFunc goto_table; + + TT_Init_Face_Func init_face; + TT_Load_Face_Func load_face; + TT_Done_Face_Func done_face; + FT_Module_Requester get_interface; + + TT_Load_Any_Func load_any; + TT_Load_SFNT_HeaderRec_Func load_sfnt_header; + TT_Load_Directory_Func load_directory; + + /* these functions are called by `load_face' but they can also */ + /* be called from external modules, if there is a need to do so */ + TT_Load_Table_Func load_header; + TT_Load_Metrics_Func load_metrics; + TT_Load_Table_Func load_charmaps; + TT_Load_Table_Func load_max_profile; + TT_Load_Table_Func load_os2; + TT_Load_Table_Func load_psnames; + + TT_Load_Table_Func load_names; + TT_Free_Table_Func free_names; + + /* optional tables */ + TT_Load_Table_Func load_hdmx; + TT_Free_Table_Func free_hdmx; + + TT_Load_Table_Func load_kerning; + TT_Load_Table_Func load_gasp; + TT_Load_Table_Func load_pclt; + + /* see `ttload.h' */ + TT_Load_Table_Func load_bitmap_header; + + /* see `ttsbit.h' */ + TT_Set_SBit_Strike_Func set_sbit_strike; + TT_Load_Table_Func load_sbits; + TT_Find_SBit_Image_Func find_sbit_image; + TT_Load_SBit_Metrics_Func load_sbit_metrics; + TT_Load_SBit_Image_Func load_sbit_image; + TT_Free_Table_Func free_sbits; + + /* see `ttpost.h' */ + TT_Get_PS_Name_Func get_psname; + TT_Free_Table_Func free_psnames; + + } SFNT_Interface; + + + /* transitional */ + typedef SFNT_Interface* SFNT_Service; + + +FT_END_HEADER + +#endif /* __SFNT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/t1types.h b/Utilities/vtkfreetype/include/freetype/internal/t1types.h new file mode 100644 index 0000000..702bb1e --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/t1types.h @@ -0,0 +1,191 @@ +/***************************************************************************/ +/* */ +/* t1types.h */ +/* */ +/* Basic Type1/Type2 type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1TYPES_H__ +#define __T1TYPES_H__ + + +#include <ft2build.h> +#include FT_TYPE1_TABLES_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H +#include FT_INTERNAL_SERVICE_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* T1_EncodingRec */ + /* */ + /* <Description> */ + /* A structure modeling a custom encoding. */ + /* */ + /* <Fields> */ + /* num_chars :: The number of character codes in the encoding. */ + /* Usually 256. */ + /* */ + /* code_first :: The lowest valid character code in the encoding. */ + /* */ + /* code_last :: The highest valid character code in the encoding. */ + /* */ + /* char_index :: An array of corresponding glyph indices. */ + /* */ + /* char_name :: An array of corresponding glyph names. */ + /* */ + typedef struct T1_EncodingRecRec_ + { + FT_Int num_chars; + FT_Int code_first; + FT_Int code_last; + + FT_UShort* char_index; + FT_String** char_name; + + } T1_EncodingRec, *T1_Encoding; + + + typedef enum T1_EncodingType_ + { + T1_ENCODING_TYPE_NONE = 0, + T1_ENCODING_TYPE_ARRAY, + T1_ENCODING_TYPE_STANDARD, + T1_ENCODING_TYPE_ISOLATIN1, + T1_ENCODING_TYPE_EXPERT + + } T1_EncodingType; + + + typedef struct T1_FontRec_ + { + PS_FontInfoRec font_info; /* font info dictionary */ + PS_PrivateRec private_dict; /* private dictionary */ + FT_String* font_name; /* top-level dictionary */ + + T1_EncodingType encoding_type; + T1_EncodingRec encoding; + + FT_Byte* subrs_block; + FT_Byte* charstrings_block; + FT_Byte* glyph_names_block; + + FT_Int num_subrs; + FT_Byte** subrs; + FT_PtrDist* subrs_len; + + FT_Int num_glyphs; + FT_String** glyph_names; /* array of glyph names */ + FT_Byte** charstrings; /* array of glyph charstrings */ + FT_PtrDist* charstrings_len; + + FT_Byte paint_type; + FT_Byte font_type; + FT_Matrix font_matrix; + FT_Vector font_offset; + FT_BBox font_bbox; + FT_Long font_id; + + FT_Fixed stroke_width; + + } T1_FontRec, *T1_Font; + + + typedef struct CID_SubrsRec_ + { + FT_UInt num_subrs; + FT_Byte** code; + + } CID_SubrsRec, *CID_Subrs; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** ORIGINAL T1_FACE CLASS DEFINITION ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + typedef struct T1_FaceRec_* T1_Face; + typedef struct CID_FaceRec_* CID_Face; + + + typedef struct T1_FaceRec_ + { + FT_FaceRec root; + T1_FontRec type1; + const void* psnames; + const void* psaux; + const void* afm_data; + FT_CharMapRec charmaprecs[2]; + FT_CharMap charmaps[2]; + PS_Unicodes unicode_map; + + /* support for Multiple Masters fonts */ + PS_Blend blend; + + /* since FT 2.1 - interface to PostScript hinter */ + const void* pshinter; + + } T1_FaceRec; + + + typedef struct CID_FaceRec_ + { + FT_FaceRec root; + void* psnames; + void* psaux; + CID_FaceInfoRec cid; + void* afm_data; + FT_Byte* binary_data; /* used if hex data has been converted */ + FT_Stream cid_stream; + CID_Subrs subrs; + + /* since FT 2.1 - interface to PostScript hinter */ + void* pshinter; + + } CID_FaceRec; + + +FT_END_HEADER + +#endif /* __T1TYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/internal/tttypes.h b/Utilities/vtkfreetype/include/freetype/internal/tttypes.h new file mode 100644 index 0000000..4a3aab1 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/internal/tttypes.h @@ -0,0 +1,1413 @@ +/***************************************************************************/ +/* */ +/* tttypes.h */ +/* */ +/* Basic SFNT/TrueType type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTTYPES_H__ +#define __TTTYPES_H__ + + +#include <ft2build.h> +#include FT_TRUETYPE_TABLES_H +#include FT_INTERNAL_OBJECTS_H + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TTC_HeaderRec */ + /* */ + /* <Description> */ + /* TrueType collection header. This table contains the offsets of */ + /* the font headers of each distinct TrueType face in the file. */ + /* */ + /* <Fields> */ + /* tag :: Must be `ttc ' to indicate a TrueType collection. */ + /* */ + /* version :: The version number. */ + /* */ + /* count :: The number of faces in the collection. The */ + /* specification says this should be an unsigned long, but */ + /* we use a signed long since we need the value -1 for */ + /* specific purposes. */ + /* */ + /* offsets :: The offsets of the font headers, one per face. */ + /* */ + typedef struct TTC_HeaderRec_ + { + FT_ULong tag; + FT_Fixed version; + FT_Long count; + FT_ULong* offsets; + + } TTC_HeaderRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* SFNT_HeaderRec */ + /* */ + /* <Description> */ + /* SFNT file format header. */ + /* */ + /* <Fields> */ + /* format_tag :: The font format tag. */ + /* */ + /* num_tables :: The number of tables in file. */ + /* */ + /* search_range :: Must be `16 * (max power of 2 <= num_tables)'. */ + /* */ + /* entry_selector :: Must be log2 of `search_range / 16'. */ + /* */ + /* range_shift :: Must be `num_tables * 16 - search_range'. */ + /* */ + typedef struct SFNT_HeaderRec_ + { + FT_ULong format_tag; + FT_UShort num_tables; + FT_UShort search_range; + FT_UShort entry_selector; + FT_UShort range_shift; + + FT_ULong offset; /* not in file */ + + } SFNT_HeaderRec, *SFNT_Header; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_TableRec */ + /* */ + /* <Description> */ + /* This structure describes a given table of a TrueType font. */ + /* */ + /* <Fields> */ + /* Tag :: A four-bytes tag describing the table. */ + /* */ + /* CheckSum :: The table checksum. This value can be ignored. */ + /* */ + /* Offset :: The offset of the table from the start of the TrueType */ + /* font in its resource. */ + /* */ + /* Length :: The table length (in bytes). */ + /* */ + typedef struct TT_TableRec_ + { + FT_ULong Tag; /* table type */ + FT_ULong CheckSum; /* table checksum */ + FT_ULong Offset; /* table file offset */ + FT_ULong Length; /* table length */ + + } TT_TableRec, *TT_Table; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_LongMetricsRec */ + /* */ + /* <Description> */ + /* A structure modeling the long metrics of the `hmtx' and `vmtx' */ + /* TrueType tables. The values are expressed in font units. */ + /* */ + /* <Fields> */ + /* advance :: The advance width or height for the glyph. */ + /* */ + /* bearing :: The left-side or top-side bearing for the glyph. */ + /* */ + typedef struct TT_LongMetricsRec_ + { + FT_UShort advance; + FT_Short bearing; + + } TT_LongMetricsRec, *TT_LongMetrics; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* TT_ShortMetrics */ + /* */ + /* <Description> */ + /* A simple type to model the short metrics of the `hmtx' and `vmtx' */ + /* tables. */ + /* */ + typedef FT_Short TT_ShortMetrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_NameEntryRec */ + /* */ + /* <Description> */ + /* A structure modeling TrueType name records. Name records are used */ + /* to store important strings like family name, style name, */ + /* copyright, etc. in _localized_ versions (i.e., language, encoding, */ + /* etc). */ + /* */ + /* <Fields> */ + /* platformID :: The ID of the name's encoding platform. */ + /* */ + /* encodingID :: The platform-specific ID for the name's encoding. */ + /* */ + /* languageID :: The platform-specific ID for the name's language. */ + /* */ + /* nameID :: The ID specifying what kind of name this is. */ + /* */ + /* stringLength :: The length of the string in bytes. */ + /* */ + /* stringOffset :: The offset to the string in the `name' table. */ + /* */ + /* string :: A pointer to the string's bytes. Note that these */ + /* are usually UTF-16 encoded characters. */ + /* */ + typedef struct TT_NameEntryRec_ + { + FT_UShort platformID; + FT_UShort encodingID; + FT_UShort languageID; + FT_UShort nameID; + FT_UShort stringLength; + FT_ULong stringOffset; + + /* this last field is not defined in the spec */ + /* but used by the FreeType engine */ + + FT_Byte* string; + + } TT_NameEntryRec, *TT_NameEntry; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_NameTableRec */ + /* */ + /* <Description> */ + /* A structure modeling the TrueType name table. */ + /* */ + /* <Fields> */ + /* format :: The format of the name table. */ + /* */ + /* numNameRecords :: The number of names in table. */ + /* */ + /* storageOffset :: The offset of the name table in the `name' */ + /* TrueType table. */ + /* */ + /* names :: An array of name records. */ + /* */ + /* stream :: the file's input stream. */ + /* */ + typedef struct TT_NameTableRec_ + { + FT_UShort format; + FT_UInt numNameRecords; + FT_UInt storageOffset; + TT_NameEntryRec* names; + FT_Stream stream; + + } TT_NameTableRec, *TT_NameTable; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_GaspRangeRec */ + /* */ + /* <Description> */ + /* A tiny structure used to model a gasp range according to the */ + /* TrueType specification. */ + /* */ + /* <Fields> */ + /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */ + /* */ + /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */ + /* modes to be used. */ + /* */ + typedef struct TT_GaspRangeRec_ + { + FT_UShort maxPPEM; + FT_UShort gaspFlag; + + } TT_GaspRangeRec, *TT_GaspRange; + + +#define TT_GASP_GRIDFIT 0x01 +#define TT_GASP_DOGRAY 0x02 + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_GaspRec */ + /* */ + /* <Description> */ + /* A structure modeling the TrueType `gasp' table used to specify */ + /* grid-fitting and anti-aliasing behaviour. */ + /* */ + /* <Fields> */ + /* version :: The version number. */ + /* */ + /* numRanges :: The number of gasp ranges in table. */ + /* */ + /* gaspRanges :: An array of gasp ranges. */ + /* */ + typedef struct TT_Gasp_ + { + FT_UShort version; + FT_UShort numRanges; + TT_GaspRange gaspRanges; + + } TT_GaspRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_HdmxEntryRec */ + /* */ + /* <Description> */ + /* A small structure used to model the pre-computed widths of a given */ + /* size. They are found in the `hdmx' table. */ + /* */ + /* <Fields> */ + /* ppem :: The pixels per EM value at which these metrics apply. */ + /* */ + /* max_width :: The maximum advance width for this metric. */ + /* */ + /* widths :: An array of widths. Note: These are 8-bit bytes. */ + /* */ + typedef struct TT_HdmxEntryRec_ + { + FT_Byte ppem; + FT_Byte max_width; + FT_Byte* widths; + + } TT_HdmxEntryRec, *TT_HdmxEntry; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_HdmxRec */ + /* */ + /* <Description> */ + /* A structure used to model the `hdmx' table, which contains */ + /* pre-computed widths for a set of given sizes/dimensions. */ + /* */ + /* <Fields> */ + /* version :: The version number. */ + /* */ + /* num_records :: The number of hdmx records. */ + /* */ + /* records :: An array of hdmx records. */ + /* */ + typedef struct TT_HdmxRec_ + { + FT_UShort version; + FT_Short num_records; + TT_HdmxEntry records; + + } TT_HdmxRec, *TT_Hdmx; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Kern0_PairRec */ + /* */ + /* <Description> */ + /* A structure used to model a kerning pair for the kerning table */ + /* format 0. The engine now loads this table if it finds one in the */ + /* font file. */ + /* */ + /* <Fields> */ + /* left :: The index of the left glyph in pair. */ + /* */ + /* right :: The index of the right glyph in pair. */ + /* */ + /* value :: The kerning distance. A positive value spaces the */ + /* glyphs, a negative one makes them closer. */ + /* */ + typedef struct TT_Kern0_PairRec_ + { + FT_UShort left; /* index of left glyph in pair */ + FT_UShort right; /* index of right glyph in pair */ + FT_FWord value; /* kerning value */ + + } TT_Kern0_PairRec, *TT_Kern0_Pair; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** EMBEDDED BITMAPS SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_SBit_MetricsRec */ + /* */ + /* <Description> */ + /* A structure used to hold the big metrics of a given glyph bitmap */ + /* in a TrueType or OpenType font. These are usually found in the */ + /* `EBDT' (Microsoft) or `bloc' (Apple) table. */ + /* */ + /* <Fields> */ + /* height :: The glyph height in pixels. */ + /* */ + /* width :: The glyph width in pixels. */ + /* */ + /* horiBearingX :: The horizontal left bearing. */ + /* */ + /* horiBearingY :: The horizontal top bearing. */ + /* */ + /* horiAdvance :: The horizontal advance. */ + /* */ + /* vertBearingX :: The vertical left bearing. */ + /* */ + /* vertBearingY :: The vertical top bearing. */ + /* */ + /* vertAdvance :: The vertical advance. */ + /* */ + typedef struct TT_SBit_MetricsRec_ + { + FT_Byte height; + FT_Byte width; + + FT_Char horiBearingX; + FT_Char horiBearingY; + FT_Byte horiAdvance; + + FT_Char vertBearingX; + FT_Char vertBearingY; + FT_Byte vertAdvance; + + } TT_SBit_MetricsRec, *TT_SBit_Metrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_SBit_SmallMetricsRec */ + /* */ + /* <Description> */ + /* A structure used to hold the small metrics of a given glyph bitmap */ + /* in a TrueType or OpenType font. These are usually found in the */ + /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */ + /* */ + /* <Fields> */ + /* height :: The glyph height in pixels. */ + /* */ + /* width :: The glyph width in pixels. */ + /* */ + /* bearingX :: The left-side bearing. */ + /* */ + /* bearingY :: The top-side bearing. */ + /* */ + /* advance :: The advance width or height. */ + /* */ + typedef struct TT_SBit_Small_Metrics_ + { + FT_Byte height; + FT_Byte width; + + FT_Char bearingX; + FT_Char bearingY; + FT_Byte advance; + + } TT_SBit_SmallMetricsRec, *TT_SBit_SmallMetrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_SBit_LineMetricsRec */ + /* */ + /* <Description> */ + /* A structure used to describe the text line metrics of a given */ + /* bitmap strike, for either a horizontal or vertical layout. */ + /* */ + /* <Fields> */ + /* ascender :: The ascender in pixels. */ + /* */ + /* descender :: The descender in pixels. */ + /* */ + /* max_width :: The maximum glyph width in pixels. */ + /* */ + /* caret_slope_enumerator :: Rise of the caret slope, typically set */ + /* to 1 for non-italic fonts. */ + /* */ + /* caret_slope_denominator :: Rise of the caret slope, typically set */ + /* to 0 for non-italic fonts. */ + /* */ + /* caret_offset :: Offset in pixels to move the caret for */ + /* proper positioning. */ + /* */ + /* min_origin_SB :: Minimum of horiBearingX (resp. */ + /* vertBearingY). */ + /* min_advance_SB :: Minimum of */ + /* */ + /* horizontal advance - */ + /* ( horiBearingX + width ) */ + /* */ + /* resp. */ + /* */ + /* vertical advance - */ + /* ( vertBearingY + height ) */ + /* */ + /* max_before_BL :: Maximum of horiBearingY (resp. */ + /* vertBearingY). */ + /* */ + /* min_after_BL :: Minimum of */ + /* */ + /* horiBearingY - height */ + /* */ + /* resp. */ + /* */ + /* vertBearingX - width */ + /* */ + /* pads :: Unused (to make the size of the record */ + /* a multiple of 32 bits. */ + /* */ + typedef struct TT_SBit_LineMetricsRec_ + { + FT_Char ascender; + FT_Char descender; + FT_Byte max_width; + FT_Char caret_slope_numerator; + FT_Char caret_slope_denominator; + FT_Char caret_offset; + FT_Char min_origin_SB; + FT_Char min_advance_SB; + FT_Char max_before_BL; + FT_Char min_after_BL; + FT_Char pads[2]; + + } TT_SBit_LineMetricsRec, *TT_SBit_LineMetrics; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_SBit_RangeRec */ + /* */ + /* <Description> */ + /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* <Fields> */ + /* first_glyph :: The first glyph index in the range. */ + /* */ + /* last_glyph :: The last glyph index in the range. */ + /* */ + /* index_format :: The format of index table. Valid values are 1 */ + /* to 5. */ + /* */ + /* image_format :: The format of `EBDT' image data. */ + /* */ + /* image_offset :: The offset to image data in `EBDT'. */ + /* */ + /* image_size :: For index formats 2 and 5. This is the size in */ + /* bytes of each glyph bitmap. */ + /* */ + /* big_metrics :: For index formats 2 and 5. This is the big */ + /* metrics for each glyph bitmap. */ + /* */ + /* num_glyphs :: For index formats 4 and 5. This is the number of */ + /* glyphs in the code array. */ + /* */ + /* glyph_offsets :: For index formats 1 and 3. */ + /* */ + /* glyph_codes :: For index formats 4 and 5. */ + /* */ + /* table_offset :: The offset of the index table in the `EBLC' */ + /* table. Only used during strike loading. */ + /* */ + typedef struct TT_SBit_RangeRec + { + FT_UShort first_glyph; + FT_UShort last_glyph; + + FT_UShort index_format; + FT_UShort image_format; + FT_ULong image_offset; + + FT_ULong image_size; + TT_SBit_MetricsRec metrics; + FT_ULong num_glyphs; + + FT_ULong* glyph_offsets; + FT_UShort* glyph_codes; + + FT_ULong table_offset; + + } TT_SBit_RangeRec, *TT_SBit_Range; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_SBit_StrikeRec */ + /* */ + /* <Description> */ + /* A structure used describe a given bitmap strike in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* <Fields> */ + /* num_index_ranges :: The number of index ranges. */ + /* */ + /* index_ranges :: An array of glyph index ranges. */ + /* */ + /* color_ref :: Unused. `color_ref' is put in for future */ + /* enhancements, but these fields are already */ + /* in use by other platforms (e.g. Newton). */ + /* For details, please see */ + /* */ + /* http://fonts.apple.com/ */ + /* TTRefMan/RM06/Chap6bloc.html */ + /* */ + /* hori :: The line metrics for horizontal layouts. */ + /* */ + /* vert :: The line metrics for vertical layouts. */ + /* */ + /* start_glyph :: The lowest glyph index for this strike. */ + /* */ + /* end_glyph :: The highest glyph index for this strike. */ + /* */ + /* x_ppem :: The number of horizontal pixels per EM. */ + /* */ + /* y_ppem :: The number of vertical pixels per EM. */ + /* */ + /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */ + /* and 8. */ + /* */ + /* flags :: Is this a vertical or horizontal strike? For */ + /* details, please see */ + /* */ + /* http://fonts.apple.com/ */ + /* TTRefMan/RM06/Chap6bloc.html */ + /* */ + typedef struct TT_SBit_StrikeRec_ + { + FT_Int num_ranges; + TT_SBit_Range sbit_ranges; + FT_ULong ranges_offset; + + FT_ULong color_ref; + + TT_SBit_LineMetricsRec hori; + TT_SBit_LineMetricsRec vert; + + FT_UShort start_glyph; + FT_UShort end_glyph; + + FT_Byte x_ppem; + FT_Byte y_ppem; + + FT_Byte bit_depth; + FT_Char flags; + + } TT_SBit_StrikeRec, *TT_SBit_Strike; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_SBit_ComponentRec */ + /* */ + /* <Description> */ + /* A simple structure to describe a compound sbit element. */ + /* */ + /* <Fields> */ + /* glyph_code :: The element's glyph index. */ + /* */ + /* x_offset :: The element's left bearing. */ + /* */ + /* y_offset :: The element's top bearing. */ + /* */ + typedef struct TT_SBit_ComponentRec_ + { + FT_UShort glyph_code; + FT_Char x_offset; + FT_Char y_offset; + + } TT_SBit_ComponentRec, *TT_SBit_Component; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_SBit_ScaleRec */ + /* */ + /* <Description> */ + /* A structure used describe a given bitmap scaling table, as defined */ + /* in the `EBSC' table. */ + /* */ + /* <Fields> */ + /* hori :: The horizontal line metrics. */ + /* */ + /* vert :: The vertical line metrics. */ + /* */ + /* x_ppem :: The number of horizontal pixels per EM. */ + /* */ + /* y_ppem :: The number of vertical pixels per EM. */ + /* */ + /* x_ppem_substitute :: Substitution x_ppem value. */ + /* */ + /* y_ppem_substitute :: Substitution y_ppem value. */ + /* */ + typedef struct TT_SBit_ScaleRec_ + { + TT_SBit_LineMetricsRec hori; + TT_SBit_LineMetricsRec vert; + + FT_Byte x_ppem; + FT_Byte y_ppem; + + FT_Byte x_ppem_substitute; + FT_Byte y_ppem_substitute; + + } TT_SBit_ScaleRec, *TT_SBit_Scale; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** POSTSCRIPT GLYPH NAMES SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Post_20Rec */ + /* */ + /* <Description> */ + /* Postscript names sub-table, format 2.0. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* <Fields> */ + /* num_glyphs :: The number of named glyphs in the table. */ + /* */ + /* num_names :: The number of PS names stored in the table. */ + /* */ + /* glyph_indices :: The indices of the glyphs in the names arrays. */ + /* */ + /* glyph_names :: The PS names not in Mac Encoding. */ + /* */ + typedef struct TT_Post_20Rec_ + { + FT_UShort num_glyphs; + FT_UShort num_names; + FT_UShort* glyph_indices; + FT_Char** glyph_names; + + } TT_Post_20Rec, *TT_Post_20; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Post_25Rec */ + /* */ + /* <Description> */ + /* Postscript names sub-table, format 2.5. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* <Fields> */ + /* num_glyphs :: The number of glyphs in the table. */ + /* */ + /* offsets :: An array of signed offsets in a normal Mac */ + /* Postscript name encoding. */ + /* */ + typedef struct TT_Post_25_ + { + FT_UShort num_glyphs; + FT_Char* offsets; + + } TT_Post_25Rec, *TT_Post_25; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Post_NamesRec */ + /* */ + /* <Description> */ + /* Postscript names table, either format 2.0 or 2.5. */ + /* */ + /* <Fields> */ + /* loaded :: A flag to indicate whether the PS names are loaded. */ + /* */ + /* format_20 :: The sub-table used for format 2.0. */ + /* */ + /* format_25 :: The sub-table used for format 2.5. */ + /* */ + typedef struct TT_Post_NamesRec_ + { + FT_Bool loaded; + + union + { + TT_Post_20Rec format_20; + TT_Post_25Rec format_25; + + } names; + + } TT_Post_NamesRec, *TT_Post_Names; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** GX VARIATION TABLE SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + typedef struct GX_BlendRec_ *GX_Blend; +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** ORIGINAL TT_FACE CLASS DEFINITION ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This structure/class is defined here because it is common to the */ + /* following formats: TTF, OpenType-TT, and OpenType-CFF. */ + /* */ + /* Note, however, that the classes TT_Size and TT_GlyphSlot are not */ + /* shared between font drivers, and are thus defined in `ttobjs.h'. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* TT_Face */ + /* */ + /* <Description> */ + /* A handle to a TrueType face/font object. A TT_Face encapsulates */ + /* the resolution and scaling independent parts of a TrueType font */ + /* resource. */ + /* */ + /* <Note> */ + /* The TT_Face structure is also used as a `parent class' for the */ + /* OpenType-CFF class (T2_Face). */ + /* */ + typedef struct TT_FaceRec_* TT_Face; + + + /* a function type used for the truetype bytecode interpreter hooks */ + typedef FT_Error + (*TT_Interpreter)( void* exec_context ); + + /* forward declaration */ + typedef struct TT_LoaderRec_* TT_Loader; + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Loader_GotoTableFunc */ + /* */ + /* <Description> */ + /* Seeks a stream to the start of a given TrueType table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* tag :: A 4-byte tag used to name the table. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Output> */ + /* length :: The length of the table in bytes. Set to 0 if not */ + /* needed. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be at the font file's origin. */ + /* */ + typedef FT_Error + (*TT_Loader_GotoTableFunc)( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Loader_StartGlyphFunc */ + /* */ + /* <Description> */ + /* Seeks a stream to the start of a given glyph element, and opens a */ + /* frame for it. */ + /* */ + /* <Input> */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + /* glyph index :: The index of the glyph to access. */ + /* */ + /* offset :: The offset of the glyph according to the */ + /* `locations' table. */ + /* */ + /* byte_count :: The size of the frame in bytes. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* This function is normally equivalent to FT_STREAM_SEEK(offset) */ + /* followed by FT_FRAME_ENTER(byte_count) with the loader's stream, */ + /* but alternative formats (e.g. compressed ones) might use something */ + /* different. */ + /* */ + typedef FT_Error + (*TT_Loader_StartGlyphFunc)( TT_Loader loader, + FT_UInt glyph_index, + FT_ULong offset, + FT_UInt byte_count ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Loader_ReadGlyphFunc */ + /* */ + /* <Description> */ + /* Reads one glyph element (its header, a simple glyph, or a */ + /* composite) from the loader's current stream frame. */ + /* */ + /* <Input> */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + typedef FT_Error + (*TT_Loader_ReadGlyphFunc)( TT_Loader loader ); + + + /*************************************************************************/ + /* */ + /* <FuncType> */ + /* TT_Loader_EndGlyphFunc */ + /* */ + /* <Description> */ + /* Closes the current loader stream frame for the glyph. */ + /* */ + /* <Input> */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + typedef void + (*TT_Loader_EndGlyphFunc)( TT_Loader loader ); + + + /*************************************************************************/ + /* */ + /* TrueType Face Type */ + /* */ + /* <Struct> */ + /* TT_Face */ + /* */ + /* <Description> */ + /* The TrueType face class. These objects model the resolution and */ + /* point-size independent data found in a TrueType font file. */ + /* */ + /* <Fields> */ + /* root :: The base FT_Face structure, managed by the */ + /* base layer. */ + /* */ + /* ttc_header :: The TrueType collection header, used when */ + /* the file is a `ttc' rather than a `ttf'. */ + /* For ordinary font files, the field */ + /* `ttc_header.count' is set to 0. */ + /* */ + /* format_tag :: The font format tag. */ + /* */ + /* num_tables :: The number of TrueType tables in this font */ + /* file. */ + /* */ + /* dir_tables :: The directory of TrueType tables for this */ + /* font file. */ + /* */ + /* header :: The font's font header (`head' table). */ + /* Read on font opening. */ + /* */ + /* horizontal :: The font's horizontal header (`hhea' */ + /* table). This field also contains the */ + /* associated horizontal metrics table */ + /* (`hmtx'). */ + /* */ + /* max_profile :: The font's maximum profile table. Read on */ + /* font opening. Note that some maximum */ + /* values cannot be taken directly from this */ + /* table. We thus define additional fields */ + /* below to hold the computed maxima. */ + /* */ + /* max_components :: The maximum number of glyph components */ + /* required to load any composite glyph from */ + /* this font. Used to size the load stack. */ + /* */ + /* vertical_info :: A boolean which is set when the font file */ + /* contains vertical metrics. If not, the */ + /* value of the `vertical' field is */ + /* undefined. */ + /* */ + /* vertical :: The font's vertical header (`vhea' table). */ + /* This field also contains the associated */ + /* vertical metrics table (`vmtx'), if found. */ + /* IMPORTANT: The contents of this field is */ + /* undefined if the `verticalInfo' field is */ + /* unset. */ + /* */ + /* num_names :: The number of name records within this */ + /* TrueType font. */ + /* */ + /* name_table :: The table of name records (`name'). */ + /* */ + /* os2 :: The font's OS/2 table (`OS/2'). */ + /* */ + /* postscript :: The font's PostScript table (`post' */ + /* table). The PostScript glyph names are */ + /* not loaded by the driver on face opening. */ + /* See the `ttpost' module for more details. */ + /* */ + /* cmap_table :: Address of the face's `cmap' SFNT table */ + /* in memory (it's an extracted frame). */ + /* */ + /* cmap_size :: The size in bytes of the `cmap_table' */ + /* described above. */ + /* */ + /* goto_table :: A function called by each TrueType table */ + /* loader to position a stream's cursor to */ + /* the start of a given table according to */ + /* its tag. It defaults to TT_Goto_Face but */ + /* can be different for strange formats (e.g. */ + /* Type 42). */ + /* */ + /* access_glyph_frame :: A function used to access the frame of a */ + /* given glyph within the face's font file. */ + /* */ + /* forget_glyph_frame :: A function used to forget the frame of a */ + /* given glyph when all data has been loaded. */ + /* */ + /* read_glyph_header :: A function used to read a glyph header. */ + /* It must be called between an `access' and */ + /* `forget'. */ + /* */ + /* read_simple_glyph :: A function used to read a simple glyph. */ + /* It must be called after the header was */ + /* read, and before the `forget'. */ + /* */ + /* read_composite_glyph :: A function used to read a composite glyph. */ + /* It must be called after the header was */ + /* read, and before the `forget'. */ + /* */ + /* sfnt :: A pointer to the SFNT service. */ + /* */ + /* psnames :: A pointer to the PostScript names service. */ + /* */ + /* hdmx :: The face's horizontal device metrics */ + /* (`hdmx' table). This table is optional in */ + /* TrueType/OpenType fonts. */ + /* */ + /* gasp :: The grid-fitting and scaling properties */ + /* table (`gasp'). This table is optional in */ + /* TrueType/OpenType fonts. */ + /* */ + /* pclt :: The `pclt' SFNT table. */ + /* */ + /* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */ + /* sizes, embedded in this font. */ + /* */ + /* sbit_strikes :: An array of sbit strikes embedded in this */ + /* font. This table is optional in a */ + /* TrueType/OpenType font. */ + /* */ + /* num_sbit_scales :: The number of sbit scales for this font. */ + /* */ + /* sbit_scales :: Array of sbit scales embedded in this */ + /* font. This table is optional in a */ + /* TrueType/OpenType font. */ + /* */ + /* postscript_names :: A table used to store the Postscript names */ + /* of the glyphs for this font. See the */ + /* file `ttconfig.h' for comments on the */ + /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */ + /* */ + /* num_locations :: The number of glyph locations in this */ + /* TrueType file. This should be */ + /* identical to the number of glyphs. */ + /* Ignored for Type 2 fonts. */ + /* */ + /* glyph_locations :: An array of longs. These are offsets to */ + /* glyph data within the `glyf' table. */ + /* Ignored for Type 2 font faces. */ + /* */ + /* font_program_size :: Size in bytecodes of the face's font */ + /* program. 0 if none defined. Ignored for */ + /* Type 2 fonts. */ + /* */ + /* font_program :: The face's font program (bytecode stream) */ + /* executed at load time, also used during */ + /* glyph rendering. Comes from the `fpgm' */ + /* table. Ignored for Type 2 font fonts. */ + /* */ + /* cvt_program_size :: The size in bytecodes of the face's cvt */ + /* program. Ignored for Type 2 fonts. */ + /* */ + /* cvt_program :: The face's cvt program (bytecode stream) */ + /* executed each time an instance/size is */ + /* changed/reset. Comes from the `prep' */ + /* table. Ignored for Type 2 fonts. */ + /* */ + /* cvt_size :: Size of the control value table (in */ + /* entries). Ignored for Type 2 fonts. */ + /* */ + /* cvt :: The face's original control value table. */ + /* Coordinates are expressed in unscaled font */ + /* units. Comes from the `cvt ' table. */ + /* Ignored for Type 2 fonts. */ + /* */ + /* num_kern_pairs :: The number of kerning pairs present in the */ + /* font file. The engine only loads the */ + /* first horizontal format 0 kern table it */ + /* finds in the font file. Ignored for */ + /* Type 2 fonts. */ + /* */ + /* kern_table_index :: The index of the kerning table in the font */ + /* kerning directory. Ignored for Type 2 */ + /* fonts. */ + /* */ + /* interpreter :: A pointer to the TrueType bytecode */ + /* interpreters field is also used to hook */ + /* the debugger in `ttdebug'. */ + /* */ + /* unpatented_hinting :: If true, use only unpatented methods in */ + /* the bytecode interpreter. */ + /* */ + /* doblend :: A boolean which is set if the font should */ + /* be blended (this is for GX var). */ + /* */ + /* blend :: Contains the data needed to control GX */ + /* variation tables (rather like Multiple */ + /* Master data). */ + /* */ + /* extra :: Reserved for third-party font drivers. */ + /* */ + /* postscript_name :: The PS name of the font. Used by the */ + /* postscript name service. */ + /* */ + typedef struct TT_FaceRec_ + { + FT_FaceRec root; + + TTC_HeaderRec ttc_header; + + FT_ULong format_tag; + FT_UShort num_tables; + TT_Table dir_tables; + + TT_Header header; /* TrueType header table */ + TT_HoriHeader horizontal; /* TrueType horizontal header */ + + TT_MaxProfile max_profile; + FT_ULong max_components; + + FT_Bool vertical_info; + TT_VertHeader vertical; /* TT Vertical header, if present */ + + FT_UShort num_names; /* number of name records */ + TT_NameTableRec name_table; /* name table */ + + TT_OS2 os2; /* TrueType OS/2 table */ + TT_Postscript postscript; /* TrueType Postscript table */ + + FT_Byte* cmap_table; /* extracted 'cmap' table */ + FT_ULong cmap_size; + + TT_Loader_GotoTableFunc goto_table; + + TT_Loader_StartGlyphFunc access_glyph_frame; + TT_Loader_EndGlyphFunc forget_glyph_frame; + TT_Loader_ReadGlyphFunc read_glyph_header; + TT_Loader_ReadGlyphFunc read_simple_glyph; + TT_Loader_ReadGlyphFunc read_composite_glyph; + + /* a typeless pointer to the SFNT_Interface table used to load */ + /* the basic TrueType tables in the face object */ + void* sfnt; + + /* a typeless pointer to the FT_Service_PsCMapsRec table used to */ + /* handle glyph names <-> unicode & Mac values */ + void* psnames; + + + /***********************************************************************/ + /* */ + /* Optional TrueType/OpenType tables */ + /* */ + /***********************************************************************/ + + /* horizontal device metrics */ + TT_HdmxRec hdmx; + + /* grid-fitting and scaling table */ + TT_GaspRec gasp; /* the `gasp' table */ + + /* PCL 5 table */ + TT_PCLT pclt; + + /* embedded bitmaps support */ + FT_ULong num_sbit_strikes; + TT_SBit_Strike sbit_strikes; + + FT_ULong num_sbit_scales; + TT_SBit_Scale sbit_scales; + + /* postscript names table */ + TT_Post_NamesRec postscript_names; + + + /***********************************************************************/ + /* */ + /* TrueType-specific fields (ignored by the OTF-Type2 driver) */ + /* */ + /***********************************************************************/ + + /* the glyph locations */ + FT_UShort num_locations; + FT_Long* glyph_locations; + + /* the font program, if any */ + FT_ULong font_program_size; + FT_Byte* font_program; + + /* the cvt program, if any */ + FT_ULong cvt_program_size; + FT_Byte* cvt_program; + + /* the original, unscaled, control value table */ + FT_ULong cvt_size; + FT_Short* cvt; + + /* the format 0 kerning table, if any */ + FT_Int num_kern_pairs; + FT_Int kern_table_index; + TT_Kern0_Pair kern_pairs; + + /* A pointer to the bytecode interpreter to use. This is also */ + /* used to hook the debugger for the `ttdebug' utility. */ + TT_Interpreter interpreter; + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + /* Use unpatented hinting only. */ + FT_Bool unpatented_hinting; +#endif + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + FT_Bool doblend; + GX_Blend blend; +#endif + + /***********************************************************************/ + /* */ + /* Other tables or fields. This is used by derivative formats like */ + /* OpenType. */ + /* */ + /***********************************************************************/ + + FT_Generic extra; + + const char* postscript_name; + + } TT_FaceRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_GlyphZoneRec */ + /* */ + /* <Description> */ + /* A glyph zone is used to load, scale and hint glyph outline */ + /* coordinates. */ + /* */ + /* <Fields> */ + /* memory :: A handle to the memory manager. */ + /* */ + /* max_points :: The maximal size in points of the zone. */ + /* */ + /* max_contours :: Max size in links contours of thez one. */ + /* */ + /* n_points :: The current number of points in the zone. */ + /* */ + /* n_contours :: The current number of contours in the zone. */ + /* */ + /* org :: The original glyph coordinates (font */ + /* units/scaled). */ + /* */ + /* cur :: The current glyph coordinates (scaled/hinted). */ + /* */ + /* tags :: The point control tags. */ + /* */ + /* contours :: The contours end points. */ + /* */ + typedef struct TT_GlyphZoneRec_ + { + FT_Memory memory; + FT_UShort max_points; + FT_UShort max_contours; + FT_UShort n_points; /* number of points in zone */ + FT_Short n_contours; /* number of contours */ + + FT_Vector* org; /* original point coordinates */ + FT_Vector* cur; /* current point coordinates */ + + FT_Byte* tags; /* current touch flags */ + FT_UShort* contours; /* contour end points */ + + } TT_GlyphZoneRec, *TT_GlyphZone; + + + /* handle to execution context */ + typedef struct TT_ExecContextRec_* TT_ExecContext; + + /* glyph loader structure */ + typedef struct TT_LoaderRec_ + { + FT_Face face; + FT_Size size; + FT_GlyphSlot glyph; + FT_GlyphLoader gloader; + + FT_ULong load_flags; + FT_UInt glyph_index; + + FT_Stream stream; + FT_Int byte_len; + + FT_Short n_contours; + FT_BBox bbox; + FT_Int left_bearing; + FT_Int advance; + FT_Int top_bearing; + FT_Int vadvance; + FT_Int linear; + FT_Bool linear_def; + FT_Bool preserve_pps; + FT_Vector pp1; + FT_Vector pp2; + FT_Vector pp3; + FT_Vector pp4; + + FT_ULong glyf_offset; + + /* the zone where we load our glyphs */ + TT_GlyphZoneRec base; + TT_GlyphZoneRec zone; + + TT_ExecContext exec; + FT_Byte* instructions; + FT_ULong ins_pos; + + /* for possible extensibility in other formats */ + void* other; + + } TT_LoaderRec; + + +FT_END_HEADER + +#endif /* __TTTYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/t1tables.h b/Utilities/vtkfreetype/include/freetype/t1tables.h new file mode 100644 index 0000000..60938aa --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/t1tables.h @@ -0,0 +1,399 @@ +/***************************************************************************/ +/* */ +/* t1tables.h */ +/* */ +/* Basic Type 1/Type 2 tables definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1TABLES_H__ +#define __T1TABLES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Section> */ + /* type1_tables */ + /* */ + /* <Title> */ + /* Type 1 Tables */ + /* */ + /* <Abstract> */ + /* Type 1 (PostScript) specific font tables. */ + /* */ + /* <Description> */ + /* This section contains the definition of Type 1-specific tables, */ + /* including structures related to other PostScript font formats. */ + /* */ + /*************************************************************************/ + + + /* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */ + /* structures in order to support Multiple Master fonts. */ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_FontInfoRec */ + /* */ + /* <Description> */ + /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */ + /* that for Multiple Master fonts, each instance has its own */ + /* FontInfo. */ + /* */ + typedef struct PS_FontInfoRec + { + FT_String* version; + FT_String* notice; + FT_String* full_name; + FT_String* family_name; + FT_String* weight; + FT_Long italic_angle; + FT_Bool is_fixed_pitch; + FT_Short underline_position; + FT_UShort underline_thickness; + + } PS_FontInfoRec, *PS_FontInfo; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* T1_FontInfo */ + /* */ + /* <Description> */ + /* This type is equivalent to @PS_FontInfoRec. It is deprecated but */ + /* kept to maintain source compatibility between various versions of */ + /* FreeType. */ + /* */ + typedef PS_FontInfoRec T1_FontInfo; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* PS_PrivateRec */ + /* */ + /* <Description> */ + /* A structure used to model a Type1/Type2 private dictionary. Note */ + /* that for Multiple Master fonts, each instance has its own Private */ + /* dictionary. */ + /* */ + typedef struct PS_PrivateRec_ + { + FT_Int unique_id; + FT_Int lenIV; + + FT_Byte num_blue_values; + FT_Byte num_other_blues; + FT_Byte num_family_blues; + FT_Byte num_family_other_blues; + + FT_Short blue_values[14]; + FT_Short other_blues[10]; + + FT_Short family_blues [14]; + FT_Short family_other_blues[10]; + + FT_Fixed blue_scale; + FT_Int blue_shift; + FT_Int blue_fuzz; + + FT_UShort standard_width[1]; + FT_UShort standard_height[1]; + + FT_Byte num_snap_widths; + FT_Byte num_snap_heights; + FT_Bool force_bold; + FT_Bool round_stem_up; + + FT_Short snap_widths [13]; /* including std width */ + FT_Short snap_heights[13]; /* including std height */ + + FT_Fixed expansion_factor; + + FT_Long language_group; + FT_Long password; + + FT_Short min_feature[2]; + + } PS_PrivateRec, *PS_Private; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* T1_Private */ + /* */ + /* <Description> */ + /* This type is equivalent to @PS_PrivateRec. It is deprecated but */ + /* kept to maintain source compatibility between various versions of */ + /* FreeType. */ + /* */ + typedef PS_PrivateRec T1_Private; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* T1_Blend_Flags */ + /* */ + /* <Description> */ + /* A set of flags used to indicate which fields are present in a */ + /* given blend dictionary (font info or private). Used to support */ + /* Multiple Masters fonts. */ + /* */ + typedef enum + { + /*# required fields in a FontInfo blend dictionary */ + T1_BLEND_UNDERLINE_POSITION = 0, + T1_BLEND_UNDERLINE_THICKNESS, + T1_BLEND_ITALIC_ANGLE, + + /*# required fields in a Private blend dictionary */ + T1_BLEND_BLUE_VALUES, + T1_BLEND_OTHER_BLUES, + T1_BLEND_STANDARD_WIDTH, + T1_BLEND_STANDARD_HEIGHT, + T1_BLEND_STEM_SNAP_WIDTHS, + T1_BLEND_STEM_SNAP_HEIGHTS, + T1_BLEND_BLUE_SCALE, + T1_BLEND_BLUE_SHIFT, + T1_BLEND_FAMILY_BLUES, + T1_BLEND_FAMILY_OTHER_BLUES, + T1_BLEND_FORCE_BOLD, + + /*# never remove */ + T1_BLEND_MAX + + } T1_Blend_Flags; + + + /*# backwards compatible definitions */ +#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION +#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS +#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE +#define t1_blend_blue_values T1_BLEND_BLUE_VALUES +#define t1_blend_other_blues T1_BLEND_OTHER_BLUES +#define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH +#define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT +#define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS +#define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS +#define t1_blend_blue_scale T1_BLEND_BLUE_SCALE +#define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT +#define t1_blend_family_blues T1_BLEND_FAMILY_BLUES +#define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES +#define t1_blend_force_bold T1_BLEND_FORCE_BOLD +#define t1_blend_max T1_BLEND_MAX + + + /* maximum number of Multiple Masters designs, as defined in the spec */ +#define T1_MAX_MM_DESIGNS 16 + + /* maximum number of Multiple Masters axes, as defined in the spec */ +#define T1_MAX_MM_AXIS 4 + + /* maximum number of elements in a design map */ +#define T1_MAX_MM_MAP_POINTS 20 + + + /* this structure is used to store the BlendDesignMap entry for an axis */ + typedef struct PS_DesignMap_ + { + FT_Byte num_points; + FT_Long* design_points; + FT_Fixed* blend_points; + + } PS_DesignMapRec, *PS_DesignMap; + + /* backwards-compatible definition */ + typedef PS_DesignMapRec T1_DesignMap; + + + typedef struct PS_BlendRec_ + { + FT_UInt num_designs; + FT_UInt num_axis; + + FT_String* axis_names[T1_MAX_MM_AXIS]; + FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; + PS_DesignMapRec design_map[T1_MAX_MM_AXIS]; + + FT_Fixed* weight_vector; + FT_Fixed* default_weight_vector; + + PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1]; + PS_Private privates [T1_MAX_MM_DESIGNS + 1]; + + FT_ULong blend_bitflags; + + FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1]; + + } PS_BlendRec, *PS_Blend; + + + /* backwards-compatible definition */ + typedef PS_BlendRec T1_Blend; + + + typedef struct CID_FaceDictRec_ + { + PS_PrivateRec private_dict; + + FT_UInt len_buildchar; + FT_Fixed forcebold_threshold; + FT_Pos stroke_width; + FT_Fixed expansion_factor; + + FT_Byte paint_type; + FT_Byte font_type; + FT_Matrix font_matrix; + FT_Vector font_offset; + + FT_UInt num_subrs; + FT_ULong subrmap_offset; + FT_Int sd_bytes; + + } CID_FaceDictRec, *CID_FaceDict; + + + /* backwards-compatible definition */ + typedef CID_FaceDictRec CID_FontDict; + + + typedef struct CID_FaceInfoRec_ + { + FT_String* cid_font_name; + FT_Fixed cid_version; + FT_Int cid_font_type; + + FT_String* registry; + FT_String* ordering; + FT_Int supplement; + + PS_FontInfoRec font_info; + FT_BBox font_bbox; + FT_ULong uid_base; + + FT_Int num_xuid; + FT_ULong xuid[16]; + + FT_ULong cidmap_offset; + FT_Int fd_bytes; + FT_Int gd_bytes; + FT_ULong cid_count; + + FT_Int num_dicts; + CID_FaceDict font_dicts; + + FT_ULong data_offset; + + } CID_FaceInfoRec, *CID_FaceInfo; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CID_Info */ + /* */ + /* <Description> */ + /* This type is equivalent to CID_FaceInfoRec. It is deprecated but */ + /* kept to maintain source compatibility between various versions of */ + /* FreeType. */ + /* */ + typedef CID_FaceInfoRec CID_Info; + + /* */ + + + /************************************************************************ + * + * @function: + * FT_Has_PS_Glyph_Names + * + * @description: + * Return true if a given face provides reliable Postscript glyph + * names. This is similar to using the @FT_HAS_GLYPH_NAMES macro, + * except that certain fonts (mostly TrueType) contain incorrect + * glyph name tables. + * + * When this function returns true, the caller is sure that the glyph + * names returned by @FT_Get_Glyph_Name are reliable. + * + * @input: + * face :: + * face handle + * + * @return: + * Boolean. True if glyph names are reliable. + */ + FT_EXPORT( FT_Int ) + FT_Has_PS_Glyph_Names( FT_Face face ); + + + /************************************************************************ + * + * @function: + * FT_Get_PS_Font_Info + * + * @description: + * Retrieve the @PS_FontInfoRec structure corresponding to a given + * Postscript font. + * + * @input: + * face :: + * Postscript face handle. + * + * @output: + * afont_info :: + * Output font info structure pointer. + * + * @return: + * FreeType error code. 0 means success. + * + * @note: + * The string pointers within the font info structure are owned by + * the face and don't need to be freed by the caller. + * + * If the font's format is not Postscript-based, this function will + * return the FT_Err_Invalid_Argument error code. + */ + FT_EXPORT( FT_Error ) + FT_Get_PS_Font_Info( FT_Face face, + PS_FontInfoRec *afont_info ); + + /* */ + + + +FT_END_HEADER + +#endif /* __T1TABLES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ttnameid.h b/Utilities/vtkfreetype/include/freetype/ttnameid.h new file mode 100644 index 0000000..848374f --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ttnameid.h @@ -0,0 +1,1076 @@ +/***************************************************************************/ +/* */ +/* ttnameid.h */ +/* */ +/* TrueType name ID definitions (specification only). */ +/* */ +/* Copyright 1996-2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTNAMEID_H__ +#define __TTNAMEID_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* Possible values for the `platform' identifier code in the name */ + /* records of the TTF `name' table. */ + /* */ + /*************************************************************************/ + + + /*********************************************************************** + * + * @enum: + * TT_PLATFORM_XXX + * + * @description: + * A list of valid values for the `platform_id' identifier code in + * @FT_CharMapRec and @FT_SfntName structures. + * + * @values: + * TT_PLATFORM_APPLE_UNICODE :: + * Used by Apple to indicate a Unicode character map and/or name entry. + * See @TT_APPLE_ID_XXX for corresponding `encoding_id' values. Note + * that name entries in this format are coded as big-endian UCS-2 + * character codes _only_. + * + * TT_PLATFORM_MACINTOSH :: + * Used by Apple to indicate a MacOS-specific charmap and/or name entry. + * See @TT_MAC_ID_XXX for corresponding `encoding_id' values. Note that + * most TrueType fonts contain an Apple roman charmap to be usable on + * MacOS systems (even if they contain a Microsoft charmap as well). + * + * TT_PLATFORM_ISO :: + * This value was used to specify Unicode charmaps. It is however + * now deprecated. See @TT_ISO_ID_XXX for a list of corresponding + * `encoding_id' values. + * + * TT_PLATFORM_MICROSOFT :: + * Used by Microsoft to indicate Windows-specific charmaps. See + * @TT_MS_ID_XXX for a list of corresponding `encoding_id' values. + * Note that most fonts contain a Unicode charmap using + * (@TT_PLATFORM_MICROSOFT, @TT_MS_ID_UNICODE_CS). + * + * TT_PLATFORM_CUSTOM :: + * Used to indicate application-specific charmaps. + * + * TT_PLATFORM_ADOBE :: + * This value isn't part of any font format specification, but is used + * by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec + * structure. See @TT_ADOBE_ID_XXX. + */ + +#define TT_PLATFORM_APPLE_UNICODE 0 +#define TT_PLATFORM_MACINTOSH 1 +#define TT_PLATFORM_ISO 2 /* deprecated */ +#define TT_PLATFORM_MICROSOFT 3 +#define TT_PLATFORM_CUSTOM 4 +#define TT_PLATFORM_ADOBE 7 /* artificial */ + + + /*********************************************************************** + * + * @enum: + * TT_APPLE_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_APPLE_UNICODE charmaps and name entries. + * + * @values: + * TT_APPLE_ID_DEFAULT :: + * Unicode version 1.0. + * TT_APPLE_ID_UNICODE_1_1 :: + * Unicode 1.1; specifies Hangul characters starting at U+34xx. + * TT_APPLE_ID_ISO_10646 :: + * Deprecated (identical to preceding.) + * TT_APPLE_ID_UNICODE_2_0 :: + * Unicode 2.0 and beyond (UTF-16 BMP only.) + * TT_APPLE_ID_UNICODE_32 :: + * Unicode 3.1 and beyond, using UTF-32 + */ + +#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */ +#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ +#define TT_APPLE_ID_ISO_10646 2 /* deprecated */ +#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ +#define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */ + + + /*********************************************************************** + * + * @enum: + * TT_MAC_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_MACINTOSH charmaps and name entries. + * + * @values: + * TT_MAC_ID_ROMAN :: + * TT_MAC_ID_JAPANESE :: + * TT_MAC_ID_TRADITIONAL_CHINESE :: + * TT_MAC_ID_KOREAN :: + * TT_MAC_ID_ARABIC :: + * TT_MAC_ID_HEBREW :: + * TT_MAC_ID_GREEK :: + * TT_MAC_ID_RUSSIAN :: + * TT_MAC_ID_RSYMBOL :: + * TT_MAC_ID_DEVANAGARI :: + * TT_MAC_ID_GURMUKHI :: + * TT_MAC_ID_GUJARATI :: + * TT_MAC_ID_ORIYA :: + * TT_MAC_ID_BENGALI :: + * TT_MAC_ID_TAMIL :: + * TT_MAC_ID_TELUGU :: + * TT_MAC_ID_KANNADA :: + * TT_MAC_ID_MALAYALAM :: + * TT_MAC_ID_SINHALESE :: + * TT_MAC_ID_BURMESE :: + * TT_MAC_ID_KHMER :: + * TT_MAC_ID_THAI :: + * TT_MAC_ID_LAOTIAN :: + * TT_MAC_ID_GEORGIAN :: + * TT_MAC_ID_ARMENIAN :: + * TT_MAC_ID_MALDIVIAN :: + * TT_MAC_ID_SIMPLIFIED_CHINESE :: + * TT_MAC_ID_TIBETAN :: + * TT_MAC_ID_MONGOLIAN :: + * TT_MAC_ID_GEEZ :: + * TT_MAC_ID_SLAVIC :: + * TT_MAC_ID_VIETNAMESE :: + * TT_MAC_ID_SINDHI :: + * TT_MAC_ID_UNINTERP :: + */ + +#define TT_MAC_ID_ROMAN 0 +#define TT_MAC_ID_JAPANESE 1 +#define TT_MAC_ID_TRADITIONAL_CHINESE 2 +#define TT_MAC_ID_KOREAN 3 +#define TT_MAC_ID_ARABIC 4 +#define TT_MAC_ID_HEBREW 5 +#define TT_MAC_ID_GREEK 6 +#define TT_MAC_ID_RUSSIAN 7 +#define TT_MAC_ID_RSYMBOL 8 +#define TT_MAC_ID_DEVANAGARI 9 +#define TT_MAC_ID_GURMUKHI 10 +#define TT_MAC_ID_GUJARATI 11 +#define TT_MAC_ID_ORIYA 12 +#define TT_MAC_ID_BENGALI 13 +#define TT_MAC_ID_TAMIL 14 +#define TT_MAC_ID_TELUGU 15 +#define TT_MAC_ID_KANNADA 16 +#define TT_MAC_ID_MALAYALAM 17 +#define TT_MAC_ID_SINHALESE 18 +#define TT_MAC_ID_BURMESE 19 +#define TT_MAC_ID_KHMER 20 +#define TT_MAC_ID_THAI 21 +#define TT_MAC_ID_LAOTIAN 22 +#define TT_MAC_ID_GEORGIAN 23 +#define TT_MAC_ID_ARMENIAN 24 +#define TT_MAC_ID_MALDIVIAN 25 +#define TT_MAC_ID_SIMPLIFIED_CHINESE 25 +#define TT_MAC_ID_TIBETAN 26 +#define TT_MAC_ID_MONGOLIAN 27 +#define TT_MAC_ID_GEEZ 28 +#define TT_MAC_ID_SLAVIC 29 +#define TT_MAC_ID_VIETNAMESE 30 +#define TT_MAC_ID_SINDHI 31 +#define TT_MAC_ID_UNINTERP 32 + + + /*********************************************************************** + * + * @enum: + * TT_ISO_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_ISO charmaps and name entries. + * + * Their use is now deprecated. + * + * @values: + * TT_ISO_ID_7BIT_ASCII :: + * ASCII. + * TT_ISO_ID_10646 :: + * ISO/10646. + * TT_ISO_ID_8859_1 :: + * Also known as Latin-1. + */ + +#define TT_ISO_ID_7BIT_ASCII 0 +#define TT_ISO_ID_10646 1 +#define TT_ISO_ID_8859_1 2 + + + /*********************************************************************** + * + * @enum: + * TT_MS_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_MICROSOFT charmaps and name entries. + * + * @values: + * TT_MS_ID_SYMBOL_CS :: + * Corresponds to Microsoft symbol encoding. See + * @FT_ENCODING_MS_SYMBOL. + * + * TT_MS_ID_UNICODE_CS :: + * Corresponds to a Microsoft WGL4 charmap, matching Unicode. See + * @FT_ENCODING_UNICODE. + * + * TT_MS_ID_SJIS :: + * Corresponds to SJIS Japanese encoding. See @FT_ENCODING_SJIS. + * + * TT_MS_ID_GB2312 :: + * Corresponds to Simplified Chinese as used in Mainland China. See + * @FT_ENCODING_GB2312. + * + * TT_MS_ID_BIG_5 :: + * Corresponds to Traditional Chinese as used in Taiwan and Hong Kong. + * See @FT_ENCODING_BIG5. + * + * TT_MS_ID_WANSUNG :: + * Corresponds to Korean Wansung encoding. See @FT_ENCODING_WANSUNG. + * + * TT_MS_ID_JOHAB :: + * Corresponds to Johab encoding. See @FT_ENCODING_JOHAB. + * + * TT_MS_ID_UCS_4 :: + * Corresponds to UCS-4 or UTF-32 charmaps. This has been added to + * the OpenType specification version 1.4 (mid-2001.) + */ + +#define TT_MS_ID_SYMBOL_CS 0 +#define TT_MS_ID_UNICODE_CS 1 +#define TT_MS_ID_SJIS 2 +#define TT_MS_ID_GB2312 3 +#define TT_MS_ID_BIG_5 4 +#define TT_MS_ID_WANSUNG 5 +#define TT_MS_ID_JOHAB 6 +#define TT_MS_ID_UCS_4 10 + + + /*********************************************************************** + * + * @enum: + * TT_ADOBE_ID_XXX + * + * @description: + * A list of valid values for the `encoding_id' for + * @TT_PLATFORM_ADOBE charmaps. This is a FreeType-specific extension! + * + * @values: + * TT_ADOBE_ID_STANDARD :: + * Adobe standard encoding. + * TT_ADOBE_ID_EXPERT :: + * Adobe expert encoding. + * TT_ADOBE_ID_CUSTOM :: + * Adobe custom encoding. + */ + +#define TT_ADOBE_ID_STANDARD 0 +#define TT_ADOBE_ID_EXPERT 1 +#define TT_ADOBE_ID_CUSTOM 2 +#define TT_ADOBE_ID_LATIN_1 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MACINTOSH. */ + /* */ + /* The canonical source for the Apple assigned Language ID's is at */ + /* */ + /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */ + /* */ +#define TT_MAC_LANGID_ENGLISH 0 +#define TT_MAC_LANGID_FRENCH 1 +#define TT_MAC_LANGID_GERMAN 2 +#define TT_MAC_LANGID_ITALIAN 3 +#define TT_MAC_LANGID_DUTCH 4 +#define TT_MAC_LANGID_SWEDISH 5 +#define TT_MAC_LANGID_SPANISH 6 +#define TT_MAC_LANGID_DANISH 7 +#define TT_MAC_LANGID_PORTUGUESE 8 +#define TT_MAC_LANGID_NORWEGIAN 9 +#define TT_MAC_LANGID_HEBREW 10 +#define TT_MAC_LANGID_JAPANESE 11 +#define TT_MAC_LANGID_ARABIC 12 +#define TT_MAC_LANGID_FINNISH 13 +#define TT_MAC_LANGID_GREEK 14 +#define TT_MAC_LANGID_ICELANDIC 15 +#define TT_MAC_LANGID_MALTESE 16 +#define TT_MAC_LANGID_TURKISH 17 +#define TT_MAC_LANGID_CROATIAN 18 +#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 +#define TT_MAC_LANGID_URDU 20 +#define TT_MAC_LANGID_HINDI 21 +#define TT_MAC_LANGID_THAI 22 +#define TT_MAC_LANGID_KOREAN 23 +#define TT_MAC_LANGID_LITHUANIAN 24 +#define TT_MAC_LANGID_POLISH 25 +#define TT_MAC_LANGID_HUNGARIAN 26 +#define TT_MAC_LANGID_ESTONIAN 27 +#define TT_MAC_LANGID_LETTISH 28 +#define TT_MAC_LANGID_SAAMISK 29 +#define TT_MAC_LANGID_FAEROESE 30 +#define TT_MAC_LANGID_FARSI 31 +#define TT_MAC_LANGID_RUSSIAN 32 +#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 +#define TT_MAC_LANGID_FLEMISH 34 +#define TT_MAC_LANGID_IRISH 35 +#define TT_MAC_LANGID_ALBANIAN 36 +#define TT_MAC_LANGID_ROMANIAN 37 +#define TT_MAC_LANGID_CZECH 38 +#define TT_MAC_LANGID_SLOVAK 39 +#define TT_MAC_LANGID_SLOVENIAN 40 +#define TT_MAC_LANGID_YIDDISH 41 +#define TT_MAC_LANGID_SERBIAN 42 +#define TT_MAC_LANGID_MACEDONIAN 43 +#define TT_MAC_LANGID_BULGARIAN 44 +#define TT_MAC_LANGID_UKRAINIAN 45 +#define TT_MAC_LANGID_BYELORUSSIAN 46 +#define TT_MAC_LANGID_UZBEK 47 +#define TT_MAC_LANGID_KAZAKH 48 +#define TT_MAC_LANGID_AZERBAIJANI 49 +#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 +#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 +#define TT_MAC_LANGID_ARMENIAN 51 +#define TT_MAC_LANGID_GEORGIAN 52 +#define TT_MAC_LANGID_MOLDAVIAN 53 +#define TT_MAC_LANGID_KIRGHIZ 54 +#define TT_MAC_LANGID_TAJIKI 55 +#define TT_MAC_LANGID_TURKMEN 56 +#define TT_MAC_LANGID_MONGOLIAN 57 +#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 +#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 +#define TT_MAC_LANGID_PASHTO 59 +#define TT_MAC_LANGID_KURDISH 60 +#define TT_MAC_LANGID_KASHMIRI 61 +#define TT_MAC_LANGID_SINDHI 62 +#define TT_MAC_LANGID_TIBETAN 63 +#define TT_MAC_LANGID_NEPALI 64 +#define TT_MAC_LANGID_SANSKRIT 65 +#define TT_MAC_LANGID_MARATHI 66 +#define TT_MAC_LANGID_BENGALI 67 +#define TT_MAC_LANGID_ASSAMESE 68 +#define TT_MAC_LANGID_GUJARATI 69 +#define TT_MAC_LANGID_PUNJABI 70 +#define TT_MAC_LANGID_ORIYA 71 +#define TT_MAC_LANGID_MALAYALAM 72 +#define TT_MAC_LANGID_KANNADA 73 +#define TT_MAC_LANGID_TAMIL 74 +#define TT_MAC_LANGID_TELUGU 75 +#define TT_MAC_LANGID_SINHALESE 76 +#define TT_MAC_LANGID_BURMESE 77 +#define TT_MAC_LANGID_KHMER 78 +#define TT_MAC_LANGID_LAO 79 +#define TT_MAC_LANGID_VIETNAMESE 80 +#define TT_MAC_LANGID_INDONESIAN 81 +#define TT_MAC_LANGID_TAGALOG 82 +#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 +#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 +#define TT_MAC_LANGID_AMHARIC 85 +#define TT_MAC_LANGID_TIGRINYA 86 +#define TT_MAC_LANGID_GALLA 87 +#define TT_MAC_LANGID_SOMALI 88 +#define TT_MAC_LANGID_SWAHILI 89 +#define TT_MAC_LANGID_RUANDA 90 +#define TT_MAC_LANGID_RUNDI 91 +#define TT_MAC_LANGID_CHEWA 92 +#define TT_MAC_LANGID_MALAGASY 93 +#define TT_MAC_LANGID_ESPERANTO 94 +#define TT_MAC_LANGID_WELSH 128 +#define TT_MAC_LANGID_BASQUE 129 +#define TT_MAC_LANGID_CATALAN 130 +#define TT_MAC_LANGID_LATIN 131 +#define TT_MAC_LANGID_QUECHUA 132 +#define TT_MAC_LANGID_GUARANI 133 +#define TT_MAC_LANGID_AYMARA 134 +#define TT_MAC_LANGID_TATAR 135 +#define TT_MAC_LANGID_UIGHUR 136 +#define TT_MAC_LANGID_DZONGKHA 137 +#define TT_MAC_LANGID_JAVANESE 138 +#define TT_MAC_LANGID_SUNDANESE 139 + + +#if 0 /* these seem to be errors that have been dropped */ + +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 + +#endif + + + /* The following codes are new as of 2000-03-10 */ +#define TT_MAC_LANGID_GALICIAN 140 +#define TT_MAC_LANGID_AFRIKAANS 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 144 +#define TT_MAC_LANGID_MANX_GAELIC 145 +#define TT_MAC_LANGID_IRISH_GAELIC 146 +#define TT_MAC_LANGID_TONGAN 147 +#define TT_MAC_LANGID_GREEK_POLYTONIC 148 +#define TT_MAC_LANGID_GREELANDIC 149 +#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MICROSOFT. */ + /* */ + /* The canonical source for the MS assigned LCID's used to be at */ + /* */ + /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */ + /* */ + /* Now (2002-11-15), the Microsoft site directs to */ + /* */ + /* http://www.microsoft.com/globaldev/reference/loclanghome.asp */ + /* http://support.microsoft.com/support/kb/articles/Q224/8/04.ASP */ + /* */ +#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 +#define TT_MS_LANGID_ARABIC_IRAQ 0x0801 +#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01 +#define TT_MS_LANGID_ARABIC_LIBYA 0x1001 +#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 +#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 +#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01 +#define TT_MS_LANGID_ARABIC_OMAN 0x2001 +#define TT_MS_LANGID_ARABIC_YEMEN 0x2401 +#define TT_MS_LANGID_ARABIC_SYRIA 0x2801 +#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01 +#define TT_MS_LANGID_ARABIC_LEBANON 0x3001 +#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 +#define TT_MS_LANGID_ARABIC_UAE 0x3801 +#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01 +#define TT_MS_LANGID_ARABIC_QATAR 0x4001 +#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 +#define TT_MS_LANGID_CATALAN_SPAIN 0x0403 +#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 +#define TT_MS_LANGID_CHINESE_PRC 0x0804 +#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04 +#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 + +#if 1 /* this used to be this value (and it still is in many places) */ +#define TT_MS_LANGID_CHINESE_MACAU 0x1404 +#else /* but beware, Microsoft may change its mind... + the most recent Word reference has the following: */ +#define TT_MS_LANGID_CHINESE_MACAU TT_MS_LANGID_CHINESE_HONG_KONG +#endif + +#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 +#define TT_MS_LANGID_DANISH_DENMARK 0x0406 +#define TT_MS_LANGID_GERMAN_GERMANY 0x0407 +#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 +#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07 +#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 +#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 +#define TT_MS_LANGID_GREEK_GREECE 0x0408 +#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 +#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 +#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09 +#define TT_MS_LANGID_ENGLISH_CANADA 0x1009 +#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 +#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 +#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09 +#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 +#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 +#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 +#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09 +#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 +#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 +#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a +#define TT_MS_LANGID_SPANISH_MEXICO 0x080a +#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a +#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a +#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a +#define TT_MS_LANGID_SPANISH_PANAMA 0x180a +#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a +#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a +#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a +#define TT_MS_LANGID_SPANISH_PERU 0x280a +#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a +#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a +#define TT_MS_LANGID_SPANISH_CHILE 0x340a +#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a +#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a +#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a +#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a +#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a +#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a +#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a +#define TT_MS_LANGID_FINNISH_FINLAND 0x040b +#define TT_MS_LANGID_FRENCH_FRANCE 0x040c +#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c +#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c +#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c +#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c +#define TT_MS_LANGID_FRENCH_MONACO 0x180c +#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d +#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e +#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f +#define TT_MS_LANGID_ITALIAN_ITALY 0x0410 +#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 +#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 +#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 +#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 +#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 +#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 +#define TT_MS_LANGID_POLISH_POLAND 0x0415 +#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 +#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 +#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 +#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 +#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 +#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 +#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 +#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a +#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a +#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a +#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b +#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c +#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d +#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d +#define TT_MS_LANGID_THAI_THAILAND 0x041e +#define TT_MS_LANGID_TURKISH_TURKEY 0x041f +#define TT_MS_LANGID_URDU_PAKISTAN 0x0420 +#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 +#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 +#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 +#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 +#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 +#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 +#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 +#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 + +#if 0 /* this seems to be an error that have been dropped */ +#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0428 +#endif + +#define TT_MS_LANGID_FARSI_IRAN 0x0429 +#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a +#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b +#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c +#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c +#define TT_MS_LANGID_BASQUE_SPAIN 0x042d +#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e +#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f +#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 +#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 +#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 +#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 +#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 +#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 +#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 +#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 +#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 +#define TT_MS_LANGID_HINDI_INDIA 0x0439 +#define TT_MS_LANGID_MALTESE_MALTA 0x043a +#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b + +#if 0 /* this seems to be a previous invertion */ +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#else +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#endif + +#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e +#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e +#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f +#define TT_MS_LANGID_SWAHILI_KENYA 0x0441 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 +#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 +#define TT_MS_LANGID_BENGALI_INDIA 0x0445 +#define TT_MS_LANGID_PUNJABI_INDIA 0x0446 +#define TT_MS_LANGID_GUJARATI_INDIA 0x0447 +#define TT_MS_LANGID_ORIYA_INDIA 0x0448 +#define TT_MS_LANGID_TAMIL_INDIA 0x0449 +#define TT_MS_LANGID_TELUGU_INDIA 0x044a +#define TT_MS_LANGID_KANNADA_INDIA 0x044b +#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c +#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d +#define TT_MS_LANGID_MARATHI_INDIA 0x044e +#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f +#define TT_MS_LANGID_KONKANI_INDIA 0x0457 + + /* new as of 2001-01-01 */ +#define TT_MS_LANGID_ARABIC_GENERAL 0x0001 +#define TT_MS_LANGID_CHINESE_GENERAL 0x0004 +#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009 +#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1c0c +#define TT_MS_LANGID_FRENCH_REUNION 0x200c +#define TT_MS_LANGID_FRENCH_CONGO 0x240c + /* which was formerly: */ +#define TT_MS_LANGID_FRENCH_ZAIRE TT_MS_LANGID_FRENCH_CONGO + +#define TT_MS_LANGID_FRENCH_SENEGAL 0x280c +#define TT_MS_LANGID_FRENCH_CAMEROON 0x2c0c +#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300c +#define TT_MS_LANGID_FRENCH_MALI 0x340c +#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x101a +#define TT_MS_LANGID_URDU_INDIA 0x0820 +#define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428 +#define TT_MS_LANGID_YIDDISH_GERMANY 0x043d +#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN 0x0440 + /* alias declared in Windows 2000 */ +#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \ + TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN + +#define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442 +#define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450 + + /* the following seems to be inconsistent; + here is the current "official" way: */ +#define TT_MS_LANGID_TIBETAN_BHUTAN 0x0451 + /* and here is what is used by Passport SDK */ +#define TT_MS_LANGID_TIBETAN_CHINA 0x0451 +#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851 + /* end of inconsistency */ + +#define TT_MS_LANGID_WELSH_WALES 0x0452 +#define TT_MS_LANGID_KHMER_CAMBODIA 0x0453 +#define TT_MS_LANGID_LAO_LAOS 0x0454 +#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455 +#define TT_MS_LANGID_GALICIAN_SPAIN 0x0456 +#define TT_MS_LANGID_MANIPURI_INDIA 0x0458 +#define TT_MS_LANGID_SINDHI_INDIA 0x0459 + /* the following one is only encountered in Microsoft RTF specification */ +#define TT_MS_LANGID_KASHMIRI_PAKISTAN 0x0460 + /* the following one is not in the Passport list, looks like an omission */ +#define TT_MS_LANGID_KASHMIRI_INDIA 0x0860 +#define TT_MS_LANGID_NEPALI_NEPAL 0x0461 +#define TT_MS_LANGID_NEPALI_INDIA 0x0861 +#define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462 + + /* new as of 2001-03-01 (from Office Xp) */ +#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3c09 +#define TT_MS_LANGID_ENGLISH_INDIA 0x4009 +#define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409 +#define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809 +#define TT_MS_LANGID_SYRIAC_SYRIA 0x045a +#define TT_MS_LANGID_SINHALESE_SRI_LANKA 0x045b +#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045c +#define TT_MS_LANGID_INUKTITUT_CANADA 0x045d +#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045e +#define TT_MS_LANGID_TAMAZIGHT_MOROCCO 0x045f +#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN 0x085f +#define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463 +#define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464 +#define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465 + /* alias declared in Windows 2000 */ +#define TT_MS_LANGID_DIVEHI_MALDIVES TT_MS_LANGID_DHIVEHI_MALDIVES + /* for language codes from 0x0466 to 0x0471 see below */ +#define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472 +#define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473 +#define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873 + /* also spelled in the `Passport SDK' list as: */ +#define TT_MS_LANGID_TIGRIGNA_ERYTREA TT_MS_LANGID_TIGRIGNA_ERYTHREA + + /* New additions from Windows Xp/Passport SDK 2001-11-10. */ + + /* don't ask what this one means... It is commented out currently. */ +#if 0 +#define TT_MS_LANGID_GREEK_GREECE2 0x2008 +#endif + +#define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540a + /* The following two IDs blatantly violate MS specs by using a */ + /* sublanguage > 0x1F. */ +#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40aU +#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40cU + +#define TT_MS_LANGID_FRENCH_MOROCCO 0x380c +#define TT_MS_LANGID_FRENCH_HAITI 0x3c0c +#define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845 +#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846 +#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN 0x0850 +#define TT_MS_LANGID_EDO_NIGERIA 0x0466 +#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467 +#define TT_MS_LANGID_HAUSA_NIGERIA 0x0468 +#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469 +#define TT_MS_LANGID_YORUBA_NIGERIA 0x046a + /* language codes from 0x046b to 0x046f are (still) unknown. */ +#define TT_MS_LANGID_IGBO_NIGERIA 0x0470 +#define TT_MS_LANGID_KANURI_NIGERIA 0x0471 +#define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474 +#define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475 +#define TT_MS_LANGID_LATIN 0x0476 +#define TT_MS_LANGID_SOMALI_SOMALIA 0x0477 + /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */ + /* not written (but OTOH the peculiar writing system is worth */ + /* studying). */ +#define TT_MS_LANGID_YI_CHINA 0x0478 +#define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479 + + + /*************************************************************************/ + /* */ + /* Possible values of the `name' identifier field in the name records of */ + /* the TTF `name' table. These values are platform independent. */ + /* */ +#define TT_NAME_ID_COPYRIGHT 0 +#define TT_NAME_ID_FONT_FAMILY 1 +#define TT_NAME_ID_FONT_SUBFAMILY 2 +#define TT_NAME_ID_UNIQUE_ID 3 +#define TT_NAME_ID_FULL_NAME 4 +#define TT_NAME_ID_VERSION_STRING 5 +#define TT_NAME_ID_PS_NAME 6 +#define TT_NAME_ID_TRADEMARK 7 + + /* the following values are from the OpenType spec */ +#define TT_NAME_ID_MANUFACTURER 8 +#define TT_NAME_ID_DESIGNER 9 +#define TT_NAME_ID_DESCRIPTION 10 +#define TT_NAME_ID_VENDOR_URL 11 +#define TT_NAME_ID_DESIGNER_URL 12 +#define TT_NAME_ID_LICENSE 13 +#define TT_NAME_ID_LICENSE_URL 14 + /* number 15 is reserved */ +#define TT_NAME_ID_PREFERRED_FAMILY 16 +#define TT_NAME_ID_PREFERRED_SUBFAMILY 17 +#define TT_NAME_ID_MAC_FULL_NAME 18 + + /* The following code is new as of 2000-01-21 */ +#define TT_NAME_ID_SAMPLE_TEXT 19 + + /* This is new in OpenType 1.3 */ +#define TT_NAME_ID_CID_FINDFONT_NAME 20 + + + /*************************************************************************/ + /* */ + /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ + /* */ + /* Updated 02-Jul-2000. */ + /* */ + + /* General Scripts Area */ + + /* Bit 0 Basic Latin */ +#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ + /* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */ + /* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ + /* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ + /* Bit 4 IPA Extensions */ +#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ + /* Bit 5 Spacing Modifier Letters */ +#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ + /* Bit 6 Combining Diacritical Marks */ +#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ + /* Bit 7 Greek and Coptic */ +#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ + /* Bit 8 is reserved (was: Greek Symbols and Coptic) */ + /* Bit 9 Cyrillic + */ + /* Cyrillic Supplementary */ +#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ + /* U+0500-U+052F */ + /* Bit 10 Armenian */ +#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ + /* Bit 11 Hebrew */ +#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ + /* Bit 12 is reserved (was: Hebrew Extended) */ + /* Bit 13 Arabic */ +#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ + /* Bit 14 is reserved (was: Arabic Extended) */ + /* Bit 15 Devanagari */ +#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ + /* Bit 16 Bengali */ +#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ + /* Bit 17 Gurmukhi */ +#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ + /* Bit 18 Gujarati */ +#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ + /* Bit 19 Oriya */ +#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ + /* Bit 20 Tamil */ +#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ + /* Bit 21 Telugu */ +#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ + /* Bit 22 Kannada */ +#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ + /* Bit 23 Malayalam */ +#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ + /* Bit 24 Thai */ +#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ + /* Bit 25 Lao */ +#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ + /* Bit 26 Georgian */ +#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ + /* Bit 27 is reserved (was Georgian Extended) */ + /* Bit 28 Hangul Jamo */ +#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ + /* Bit 29 Latin Extended Additional */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ + /* Bit 30 Greek Extended */ +#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ + + /* Symbols Area */ + + /* Bit 31 General Punctuation */ +#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ + /* Bit 32 Superscripts And Subscripts */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ + /* Bit 33 Currency Symbols */ +#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ + /* Bit 34 Combining Diacritical Marks For Symbols */ +#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ + /* Bit 35 Letterlike Symbols */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ + /* Bit 36 Number Forms */ +#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ + /* Bit 37 Arrows + */ + /* Supplemental Arrows-A + */ + /* Supplemental Arrows-B */ +#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ + /* U+27F0-U+27FF */ + /* U+2900-U+297F */ + /* Bit 38 Mathematical Operators + */ + /* Supplemental Mathematical Operators + */ + /* Miscellaneous Mathematical Symbols-A + */ + /* Miscellaneous Mathematical Symbols-B */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ + /* U+2A00-U+2AFF */ + /* U+27C0-U+27EF */ + /* U+2980-U+29FF */ + /* Bit 39 Miscellaneous Technical */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ + /* Bit 40 Control Pictures */ +#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ + /* Bit 41 Optical Character Recognition */ +#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ + /* Bit 42 Enclosed Alphanumerics */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ + /* Bit 43 Box Drawing */ +#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ + /* Bit 44 Block Elements */ +#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ + /* Bit 45 Geometric Shapes */ +#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ + /* Bit 46 Miscellaneous Symbols */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ + /* Bit 47 Dingbats */ +#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ + + /* CJK Phonetics and Symbols Area */ + + /* Bit 48 CJK Symbols and Punctuation */ +#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ + /* Bit 49 Hiragana */ +#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ + /* Bit 50 Katakana + */ + /* Katakana Phonetic Extensions */ +#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ + /* U+31F0-U+31FF */ + /* Bit 51 Bopomofo + */ + /* Bopomofo Extended */ +#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ + /* U+31A0-U+31BF */ + /* Bit 52 Hangul Compatibility Jamo */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ + /* Bit 53 Kanbun */ +#define TT_UCR_CJK_MISC (1L << 21) /* U+3190-U+319F */ +#define TT_UCR_KANBUN TT_UCR_CJK_MISC + /* Bit 54 Enclosed CJK Letters and Months */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ + /* Bit 55 CJK Compatibility */ +#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ + + /* Hangul Syllables Area */ + + /* Bit 56 Hangul */ +#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ + + /* Surrogates Area */ + + /* Bit 57 High Surrogates + */ + /* High Private Use Surrogates + */ + /* Low Surrogates */ +#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */ + /* U+DB80-U+DBFF */ + /* U+DC00-U+DFFF */ + /* According to OpenType specs v.1.3+, setting bit 57 implies that there */ + /* is at least one codepoint beyond the Basic Multilingual Plane that is */ + /* supported by this font. So it really means: >= U+10000 */ + + /* Bit 58 is reserved for Unicode SubRanges */ + + /* CJK Ideographs Area */ + + /* Bit 59 CJK Unified Ideographs + */ + /* CJK Radicals Supplement + */ + /* Kangxi Radicals + */ + /* Ideographic Description Characters + */ + /* CJK Unified Ideographs Extension A */ + /* CJK Unified Ideographs Extension A + */ + /* CJK Unified Ideographs Extension B + */ + /* Kanbun */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ + /* U+2E80-U+2EFF */ + /* U+2F00-U+2FDF */ + /* U+2FF0-U+2FFF */ + /* U+3400-U+4DB5 */ + /*U+20000-U+2A6DF*/ + /* U+3190-U+319F */ + + /* Private Use Area */ + + /* Bit 60 Private Use */ +#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ + + /* Compatibility Area and Specials */ + + /* Bit 61 CJK Compatibility Ideographs + */ + /* CJK Compatibility Ideographs Supplement */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+F900-U+FAFF */ + /*U+2F800-U+2FA1F*/ + /* Bit 62 Alphabetic Presentation Forms */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ + /* Bit 63 Arabic Presentation Forms-A */ +#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */ + /* Bit 64 Combining Half Marks */ +#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ + /* Bit 65 CJK Compatibility Forms */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE30-U+FE4F */ + /* Bit 66 Small Form Variants */ +#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ + /* Bit 67 Arabic Presentation Forms-B */ +#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */ + /* Bit 68 Halfwidth and Fullwidth Forms */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ + /* Bit 69 Specials */ +#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ + /* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */ + /* Bit 71 Syriac */ +#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ + /* Bit 72 Thaana */ +#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ + /* Bit 73 Sinhala */ +#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ + /* Bit 74 Myanmar */ +#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ + /* Bit 75 Ethiopic */ +#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */ + /* Bit 76 Cherokee */ +#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ + /* Bit 77 Unified Canadian Aboriginal Syllabics */ +#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */ + /* Bit 78 Ogham */ +#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ + /* Bit 79 Runic */ +#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ + /* Bit 80 Khmer */ +#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ + /* Bit 81 Mongolian */ +#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ + /* Bit 82 Braille Patterns */ +#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ + /* Bit 83 Yi Syllables + */ + /* Yi Radicals */ +#define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */ + /* U+A490-U+A4CF */ + /* Bit 84 Tagalog + */ + /* Hanunoo + */ + /* Buhid + */ + /* Tagbanwa */ +#define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */ + /* U+1720-U+173F */ + /* U+1740-U+175F */ + /* U+1760-U+177F */ + /* Bit 85 Old Italic */ +#define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/ + /* Bit 86 Gothic */ +#define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/ + /* Bit 87 Deseret */ +#define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/ + /* Bit 88 Byzantine Musical Symbols + */ + /* Musical Symbols */ +#define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/ + /*U+1D100-U+1D1FF*/ + /* Bit 89 Mathematical Alphanumeric Symbols */ +#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/ + /* Bit 90 Private Use (plane 15) + */ + /* Private Use (plane 16) */ +#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/ + /*U+100000-U+10FFFD*/ + /* Bit 91 Variation Selectors */ +#define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */ + /* Bit 92 Tags */ +#define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/ + + + /*************************************************************************/ + /* */ + /* Some compilers have a very limited length of identifiers. */ + /* */ +#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) +#define HAVE_LIMIT_ON_IDENTS +#endif + + +#ifndef HAVE_LIMIT_ON_IDENTS + + + /*************************************************************************/ + /* */ + /* Here some alias #defines in order to be clearer. */ + /* */ + /* These are not always #defined to stay within the 31 character limit */ + /* which some compilers have. */ + /* */ + /* Credits go to Dave Hoo <dhoo@flash.net> for pointing out that modern */ + /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */ + /* If you get a warning with such a compiler, use the -i40 switch. */ + /* */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ + TT_UCR_ARABIC_PRESENTATIONS_A +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ + TT_UCR_ARABIC_PRESENTATIONS_B + +#define TT_UCR_COMBINING_DIACRITICAL_MARKS \ + TT_UCR_COMBINING_DIACRITICS +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ + TT_UCR_COMBINING_DIACRITICS_SYMB + + +#endif /* !HAVE_LIMIT_ON_IDENTS */ + + +FT_END_HEADER + +#endif /* __TTNAMEID_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/tttables.h b/Utilities/vtkfreetype/include/freetype/tttables.h new file mode 100644 index 0000000..ccf43c6 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/tttables.h @@ -0,0 +1,731 @@ +/***************************************************************************/ +/* */ +/* tttables.h */ +/* */ +/* Basic SFNT/TrueType tables definitions and interface */ +/* (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTTABLES_H__ +#define __TTTABLES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + /*************************************************************************/ + /* */ + /* <Section> */ + /* truetype_tables */ + /* */ + /* <Title> */ + /* TrueType Tables */ + /* */ + /* <Abstract> */ + /* TrueType-specific table types and functions. */ + /* */ + /* <Description> */ + /* This section contains the definition of TrueType-specific tables */ + /* as well as some routines used to access and process them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Header */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType font header table. All */ + /* fields follow the TrueType specification. */ + /* */ + typedef struct TT_Header_ + { + FT_Fixed Table_Version; + FT_Fixed Font_Revision; + + FT_Long CheckSum_Adjust; + FT_Long Magic_Number; + + FT_UShort Flags; + FT_UShort Units_Per_EM; + + FT_Long Created [2]; + FT_Long Modified[2]; + + FT_Short xMin; + FT_Short yMin; + FT_Short xMax; + FT_Short yMax; + + FT_UShort Mac_Style; + FT_UShort Lowest_Rec_PPEM; + + FT_Short Font_Direction; + FT_Short Index_To_Loc_Format; + FT_Short Glyph_Data_Format; + + } TT_Header; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_HoriHeader */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType horizontal header, the `hhea' */ + /* table, as well as the corresponding horizontal metrics table, */ + /* i.e., the `hmtx' table. */ + /* */ + /* <Fields> */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of all */ + /* glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoAscender' field */ + /* of the OS/2 table instead if you want */ + /* the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the distance */ + /* from the baseline to the bottom-most of */ + /* all glyph points found in the font. It */ + /* is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Width_Max :: This field is the maximum of all advance */ + /* widths found in the font. It can be */ + /* used to compute the maximum width of an */ + /* arbitrary string of text. */ + /* */ + /* min_Left_Side_Bearing :: The minimum left side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Right_Side_Bearing :: The minimum right side bearing of all */ + /* glyphs within the font. */ + /* */ + /* xMax_Extent :: The maximum horizontal extent (i.e., the */ + /* `width' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* Reserved :: 10 reserved bytes. */ + /* */ + /* metric_Data_Format :: Always 0. */ + /* */ + /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */ + /* table -- this value can be smaller than */ + /* the total number of glyphs in the font. */ + /* */ + /* long_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* <Note> */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_HoriHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Width_Max; /* advance width maximum */ + + FT_Short min_Left_Side_Bearing; /* minimum left-sb */ + FT_Short min_Right_Side_Bearing; /* minimum right-sb */ + FT_Short xMax_Extent; /* xmax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_HMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they are used to connect the metrics header to the relevant */ + /* `HMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_HoriHeader; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_VertHeader */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType vertical header, the `vhea' */ + /* table, as well as the corresponding vertical metrics table, i.e., */ + /* the `vmtx' table. */ + /* */ + /* <Fields> */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of */ + /* all glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoAscender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the */ + /* distance from the baseline to the */ + /* bottom-most of all glyph points found */ + /* in the font. It is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Height_Max :: This field is the maximum of all */ + /* advance heights found in the font. It */ + /* can be used to compute the maximum */ + /* height of an arbitrary string of text. */ + /* */ + /* min_Top_Side_Bearing :: The minimum top side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */ + /* glyphs within the font. */ + /* */ + /* yMax_Extent :: The maximum vertical extent (i.e., the */ + /* `height' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* caret_Offset :: The cursor's offset for slanted fonts. */ + /* This value is `reserved' in vmtx */ + /* version 1.0. */ + /* */ + /* Reserved :: 8 reserved bytes. */ + /* */ + /* metric_Data_Format :: Always 0. */ + /* */ + /* number_Of_HMetrics :: Number of VMetrics entries in the */ + /* `vmtx' table -- this value can be */ + /* smaller than the total number of glyphs */ + /* in the font. */ + /* */ + /* long_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* <Note> */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_VertHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Height_Max; /* advance height maximum */ + + FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + FT_Short yMax_Extent; /* xmax or ymax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_VMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' or `VMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_VertHeader; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_OS2 */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType OS/2 table. This is the long */ + /* table version. All fields comply to the TrueType specification. */ + /* */ + /* Note that we now support old Mac fonts which do not include an */ + /* OS/2 table. In this case, the `version' field is always set to */ + /* 0xFFFF. */ + /* */ + typedef struct TT_OS2_ + { + FT_UShort version; /* 0x0001 - more or 0xFFFF */ + FT_Short xAvgCharWidth; + FT_UShort usWeightClass; + FT_UShort usWidthClass; + FT_Short fsType; + FT_Short ySubscriptXSize; + FT_Short ySubscriptYSize; + FT_Short ySubscriptXOffset; + FT_Short ySubscriptYOffset; + FT_Short ySuperscriptXSize; + FT_Short ySuperscriptYSize; + FT_Short ySuperscriptXOffset; + FT_Short ySuperscriptYOffset; + FT_Short yStrikeoutSize; + FT_Short yStrikeoutPosition; + FT_Short sFamilyClass; + + FT_Byte panose[10]; + + FT_ULong ulUnicodeRange1; /* Bits 0-31 */ + FT_ULong ulUnicodeRange2; /* Bits 32-63 */ + FT_ULong ulUnicodeRange3; /* Bits 64-95 */ + FT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + FT_Char achVendID[4]; + + FT_UShort fsSelection; + FT_UShort usFirstCharIndex; + FT_UShort usLastCharIndex; + FT_Short sTypoAscender; + FT_Short sTypoDescender; + FT_Short sTypoLineGap; + FT_UShort usWinAscent; + FT_UShort usWinDescent; + + /* only version 1 tables: */ + + FT_ULong ulCodePageRange1; /* Bits 0-31 */ + FT_ULong ulCodePageRange2; /* Bits 32-63 */ + + /* only version 2 tables: */ + + FT_Short sxHeight; + FT_Short sCapHeight; + FT_UShort usDefaultChar; + FT_UShort usBreakChar; + FT_UShort usMaxContext; + + } TT_OS2; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_Postscript */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType Postscript table. All fields */ + /* comply to the TrueType table. This structure does not reference */ + /* the Postscript glyph names, which can be nevertheless accessed */ + /* with the `ttpost' module. */ + /* */ + typedef struct TT_Postscript_ + { + FT_Fixed FormatType; + FT_Fixed italicAngle; + FT_Short underlinePosition; + FT_Short underlineThickness; + FT_ULong isFixedPitch; + FT_ULong minMemType42; + FT_ULong maxMemType42; + FT_ULong minMemType1; + FT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ttpost.c file. */ + + } TT_Postscript; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_PCLT */ + /* */ + /* <Description> */ + /* A structure used to model a TrueType PCLT table. All fields */ + /* comply to the TrueType table. */ + /* */ + typedef struct TT_PCLT_ + { + FT_Fixed Version; + FT_ULong FontNumber; + FT_UShort Pitch; + FT_UShort xHeight; + FT_UShort Style; + FT_UShort TypeFamily; + FT_UShort CapHeight; + FT_UShort SymbolSet; + FT_Char TypeFace[16]; + FT_Char CharacterComplement[8]; + FT_Char FileName[6]; + FT_Char StrokeWeight; + FT_Char WidthType; + FT_Byte SerifStyle; + FT_Byte Reserved; + + } TT_PCLT; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_MaxProfile */ + /* */ + /* <Description> */ + /* The maximum profile is a table containing many max values which */ + /* can be used to pre-allocate arrays. This ensures that no memory */ + /* allocation occurs during a glyph load. */ + /* */ + /* <Fields> */ + /* version :: The version number. */ + /* */ + /* numGlyphs :: The number of glyphs in this TrueType */ + /* font. */ + /* */ + /* maxPoints :: The maximum number of points in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositePoints'. */ + /* */ + /* maxContours :: The maximum number of contours in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositeContours'. */ + /* */ + /* maxCompositePoints :: The maximum number of points in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxPoints'. */ + /* */ + /* maxCompositeContours :: The maximum number of contours in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxContours'. */ + /* */ + /* maxZones :: The maximum number of zones used for */ + /* glyph hinting. */ + /* */ + /* maxTwilightPoints :: The maximum number of points in the */ + /* twilight zone used for glyph hinting. */ + /* */ + /* maxStorage :: The maximum number of elements in the */ + /* storage area used for glyph hinting. */ + /* */ + /* maxFunctionDefs :: The maximum number of function */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxInstructionDefs :: The maximum number of instruction */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxStackElements :: The maximum number of stack elements used */ + /* during bytecode interpretation. */ + /* */ + /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */ + /* used for glyph hinting. */ + /* */ + /* maxComponentElements :: The maximum number of simple (i.e., non- */ + /* composite) glyphs in a composite glyph. */ + /* */ + /* maxComponentDepth :: The maximum nesting depth of composite */ + /* glyphs. */ + /* */ + /* <Note> */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_MaxProfile_ + { + FT_Fixed version; + FT_UShort numGlyphs; + FT_UShort maxPoints; + FT_UShort maxContours; + FT_UShort maxCompositePoints; + FT_UShort maxCompositeContours; + FT_UShort maxZones; + FT_UShort maxTwilightPoints; + FT_UShort maxStorage; + FT_UShort maxFunctionDefs; + FT_UShort maxInstructionDefs; + FT_UShort maxStackElements; + FT_UShort maxSizeOfInstructions; + FT_UShort maxComponentElements; + FT_UShort maxComponentDepth; + + } TT_MaxProfile; + + + /*************************************************************************/ + /* */ + /* <Enum> */ + /* FT_Sfnt_Tag */ + /* */ + /* <Description> */ + /* An enumeration used to specify the index of an SFNT table. */ + /* Used in the @FT_Get_Sfnt_Table API function. */ + /* */ + typedef enum + { + ft_sfnt_head = 0, + ft_sfnt_maxp = 1, + ft_sfnt_os2 = 2, + ft_sfnt_hhea = 3, + ft_sfnt_vhea = 4, + ft_sfnt_post = 5, + ft_sfnt_pclt = 6, + + sfnt_max /* internal end mark */ + + } FT_Sfnt_Tag; + + /* */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_Sfnt_Table */ + /* */ + /* <Description> */ + /* Returns a pointer to a given SFNT table within a face. */ + /* */ + /* <Input> */ + /* face :: A handle to the source. */ + /* */ + /* tag :: The index of the SFNT table. */ + /* */ + /* <Return> */ + /* A type-less pointer to the table. This will be 0 in case of */ + /* error, or if the corresponding table was not found *OR* loaded */ + /* from the file. */ + /* */ + /* <Note> */ + /* The table is owned by the face object and disappears with it. */ + /* */ + /* This function is only useful to access SFNT tables that are loaded */ + /* by the sfnt/truetype/opentype drivers. See @FT_Sfnt_Tag for a */ + /* list. */ + /* */ + FT_EXPORT( void* ) + FT_Get_Sfnt_Table( FT_Face face, + FT_Sfnt_Tag tag ); + + + /************************************************************************** + * + * <Function> + * FT_Load_Sfnt_Table + * + * <Description> + * Loads any font table into client memory. + * + * <Input> + * face :: A handle to the source face. + * + * tag :: The 4-byte tag of the table to load. Use the value 0 if + * you want to access the whole font file. Otherwise, you can + * use one of the definitions found in the @FT_TRUETYPE_TAGS_H + * file, or forge a new one with @FT_MAKE_TAG. + * + * offset :: The starting offset in the table (or file if tag == 0). + * + * <Output> + * buffer :: The target buffer address. The client must ensure that + * the memory array is big enough to hold the data. + * + * <InOut> + * length :: If the `length' parameter is NULL, then try to load the whole + * table. Return an error code if it fails. + * + * Else, if `*length' is 0, exit immediately while returning + * the table's (or file) full size in it. + * + * Else the number of bytes to read from the table or file, + * from the starting offset. + * + * <Return> + * FreeType error code. 0 means success. + * + * <Note> + * If you need to determine the table's length you should first call this + * function with `*length' set to 0, as in the following example: + * + * { + * FT_ULong length = 0; + * + * + * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length ); + * if ( error ) { ... table does not exist ... } + * + * buffer = malloc( length ); + * if ( buffer == NULL ) { ... not enough memory ... } + * + * error = FT_Load_Sfnt_Table( face,tag, 0, buffer, &length ); + * if ( error ) { ... could not load table ... } + * } + */ + FT_EXPORT( FT_Error ) + FT_Load_Sfnt_Table( FT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + /************************************************************************** + * + * <Function> + * FT_Sfnt_Table_Info + * + * <Description> + * Returns information on an SFNT table. + * + * <Input> + * face :: + * A handle to the source face. + * + * table_index :: + * The index of an SFNT table. The function returns + * FT_Err_Table_Missing for an invalid value. + * + * <Output> + * tag :: + * The name tag of the SFNT table. + * + * length :: + * The length of the SFNT table. + * + * <Return> + * FreeType error code. 0 means success. + * + * <Note> + * SFNT tables with length zero are treated as missing by Windows. + * + */ + FT_EXPORT( FT_Error ) + FT_Sfnt_Table_Info( FT_Face face, + FT_UInt table_index, + FT_ULong *tag, + FT_ULong *length ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Get_CMap_Language_ID */ + /* */ + /* <Description> */ + /* Return TrueType/sfnt specific cmap language ID. Definitions of */ + /* language ID values are in freetype/ttnameid.h. */ + /* */ + /* <Input> */ + /* charmap :: */ + /* The target charmap. */ + /* */ + /* <Return> */ + /* The language ID of `charmap'. If `charmap' doesn't belong to a */ + /* TrueType/sfnt face, just return 0 as the default value. */ + /* */ + FT_EXPORT( FT_ULong ) + FT_Get_CMap_Language_ID( FT_CharMap charmap ); + + /* */ + + +FT_END_HEADER + +#endif /* __TTTABLES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/tttags.h b/Utilities/vtkfreetype/include/freetype/tttags.h new file mode 100644 index 0000000..a6876d4 --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/tttags.h @@ -0,0 +1,83 @@ +/***************************************************************************/ +/* */ +/* tttags.h */ +/* */ +/* Tags for TrueType tables (specification only). */ +/* */ +/* Copyright 1996-2001, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTAGS_H__ +#define __TTAGS_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + +#define TTAG_avar FT_MAKE_TAG( 'a', 'v', 'a', 'r' ) +#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' ) +#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' ) +#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' ) +#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' ) +#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' ) +#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' ) +#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' ) +#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' ) +#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' ) +#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' ) +#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' ) +#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' ) +#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' ) +#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' ) +#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' ) +#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' ) +#define TTAG_gvar FT_MAKE_TAG( 'g', 'v', 'a', 'r' ) +#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' ) +#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' ) +#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' ) +#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' ) +#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' ) +#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' ) +#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' ) +#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' ) +#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' ) +#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' ) +#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' ) +#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' ) +#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) +#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' ) +#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' ) +#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' ) +#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) +#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) +#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' ) +#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' ) +#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' ) +#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' ) + + +FT_END_HEADER + +#endif /* __TTAGS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/freetype/ttunpat.h b/Utilities/vtkfreetype/include/freetype/ttunpat.h new file mode 100644 index 0000000..0bc0a6f --- /dev/null +++ b/Utilities/vtkfreetype/include/freetype/ttunpat.h @@ -0,0 +1,59 @@ +/***************************************************************************/ +/* */ +/* ttunpat.h */ +/* */ +/* Definitions for the unpatented TrueType hinting system */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* Written by Graham Asher <graham.asher@btinternet.com> */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTUNPAT_H__ +#define __TTUNPAT_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + +#ifdef FREETYPE_H +#error "freetype.h of FreeType 1 has been loaded!" +#error "Please fix the directory search order for header files" +#error "so that freetype.h of FreeType 2 is found first." +#endif + + +FT_BEGIN_HEADER + + + /*************************************************************************** + * + * @constant: + * FT_PARAM_TAG_UNPATENTED_HINTING + * + * @description: + * A constant used as the tag of an @FT_Parameter structure to indicate + * that unpatented methods only should be used by the TrueType bytecode + * interpreter for a typeface opened by FT_Open_Face. + * + */ +#define FT_PARAM_TAG_UNPATENTED_HINTING FT_MAKE_TAG( 'u', 'n', 'p', 'a' ) + + /* */ + +FT_END_HEADER + + +#endif /* __TTUNPAT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/ft2build.h b/Utilities/vtkfreetype/include/ft2build.h new file mode 100644 index 0000000..6c855d2 --- /dev/null +++ b/Utilities/vtkfreetype/include/ft2build.h @@ -0,0 +1,43 @@ +/***************************************************************************/ +/* */ +/* ft2build.h */ +/* */ +/* FreeType 2 build and setup macros. */ +/* (Generic version) */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file corresponds to the default "ft2build.h" file for */ + /* FreeType 2. It uses the "freetype" include root. */ + /* */ + /* Note that specific platforms might use a different configuration. */ + /* See builds/unix/ft2unix.h for an example. */ + /* */ + /*************************************************************************/ + + +#ifndef __FT2_BUILD_GENERIC_H__ +#define __FT2_BUILD_GENERIC_H__ + +#include <freetype/config/ftheader.h> + +#if defined(VTKFREETYPE) +#include "vtkFreeTypeConfig.h" +#endif + +#endif /* __FT2_BUILD_GENERIC_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/include/vtkFreeTypeConfig.h.in b/Utilities/vtkfreetype/include/vtkFreeTypeConfig.h.in new file mode 100644 index 0000000..9b6cced --- /dev/null +++ b/Utilities/vtkfreetype/include/vtkFreeTypeConfig.h.in @@ -0,0 +1,30 @@ +#ifndef _freetypeConfig_h +#define _freetypeConfig_h + +#if defined(__BORLANDC__) +#pragma warn -8004 /* Disable "foo is assigned a value that is never used." */ +#endif + +/* + Static or shared lib flags +*/ +#cmakedefine VTKFREETYPE_DLL +#cmakedefine VTKFREETYPE_STATIC + +/* + HPUX workaround +*/ +#cmakedefine VTKFREETYPE_HPUX_SOURCE +#if defined(VTKFREETYPE_HPUX_SOURCE) && !defined(_HPUX_SOURCE) +#define _HPUX_SOURCE +#endif + +/* + Carbon framework +*/ +#cmakedefine VTKFREETYPE_USE_CARBON +#if defined(VTKFREETYPE_USE_CARBON) && !defined(FT_USE_CARBON_HEADER) +#define FT_USE_CARBON_HEADER +#endif + +#endif diff --git a/Utilities/vtkfreetype/src/autohint/CatharonLicense.txt b/Utilities/vtkfreetype/src/autohint/CatharonLicense.txt new file mode 100644 index 0000000..789c8c9 --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/CatharonLicense.txt @@ -0,0 +1,123 @@ + The Catharon Open Source LICENSE + ---------------------------- + + 2000-Jul-04 + + Copyright (C) 2000 by Catharon Productions, Inc. + + + +Introduction +============ + + This license applies to source files distributed by Catharon + Productions, Inc. in several archive packages. This license + applies to all files found in such packages which do not fall + under their own explicit license. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we are + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + Catharon Code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering the packages distributed by + Catharon Productions, Inc. and assume no liability related to + their use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `Catharon Package', `package', + and `Catharon Code' refer to the set of files originally + distributed by Catharon Productions, Inc. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using one of the + Catharon Packages'. + + This license applies to all files distributed in the original + Catharon Package(s), including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The Catharon Packages are copyright (C) 2000 by Catharon + Productions, Inc. All rights reserved except as specified below. + +1. No Warranty +-------------- + + THE CATHARON PACKAGES ARE PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OF OR THE INABILITY TO + USE THE CATHARON PACKAGE. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the Catharon Packages (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`license.txt') unaltered; any additions, deletions or changes + to the original files must be clearly indicated in + accompanying documentation. The copyright notices of the + unaltered, original files must be preserved in all copies of + source files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part on the work of + Catharon Productions, Inc. in the distribution documentation. + + These conditions apply to any software derived from or based on + the Catharon Packages, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither Catharon Productions, Inc. and contributors nor you shall + use the name of the other for commercial, advertising, or + promotional purposes without specific prior written permission. + + We suggest, but do not require, that you use the following phrase + to refer to this software in your documentation: 'this software is + based in part on the Catharon Typography Project'. + + As you have not signed this license, you are not required to + accept it. However, as the Catharon Packages are copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the Catharon + Packages, you indicate that you understand and accept all the + terms of this license. + +--- end of license.txt --- diff --git a/Utilities/vtkfreetype/src/autohint/ahangles.c b/Utilities/vtkfreetype/src/autohint/ahangles.c new file mode 100644 index 0000000..ef5a88e --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahangles.c @@ -0,0 +1,147 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (body). */ +/* */ +/* Copyright 2000-2001, 2002 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "ahangles.h" + + + /* the following table has been automatically generated with */ + /* the `mather.py' Python script */ + + const AH_Angle ah_arctan[1L << AH_ATAN_BITS] = + { + 0, 0, 1, 1, 1, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 5, + 5, 5, 6, 6, 6, 7, 7, 7, + 8, 8, 8, 9, 9, 9, 10, 10, + 10, 10, 11, 11, 11, 12, 12, 12, + 13, 13, 13, 14, 14, 14, 14, 15, + 15, 15, 16, 16, 16, 17, 17, 17, + 18, 18, 18, 18, 19, 19, 19, 20, + 20, 20, 21, 21, 21, 21, 22, 22, + 22, 23, 23, 23, 24, 24, 24, 24, + 25, 25, 25, 26, 26, 26, 26, 27, + 27, 27, 28, 28, 28, 28, 29, 29, + 29, 30, 30, 30, 30, 31, 31, 31, + 31, 32, 32, 32, 33, 33, 33, 33, + 34, 34, 34, 34, 35, 35, 35, 35, + 36, 36, 36, 36, 37, 37, 37, 38, + 38, 38, 38, 39, 39, 39, 39, 40, + 40, 40, 40, 41, 41, 41, 41, 42, + 42, 42, 42, 42, 43, 43, 43, 43, + 44, 44, 44, 44, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 47, 47, 47, + 47, 48, 48, 48, 48, 48, 49, 49, + 49, 49, 50, 50, 50, 50, 50, 51, + 51, 51, 51, 51, 52, 52, 52, 52, + 52, 53, 53, 53, 53, 53, 54, 54, + 54, 54, 54, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 57, 57, 57, + 57, 57, 57, 58, 58, 58, 58, 58, + 59, 59, 59, 59, 59, 59, 60, 60, + 60, 60, 60, 61, 61, 61, 61, 61, + 61, 62, 62, 62, 62, 62, 62, 63, + 63, 63, 63, 63, 63, 64, 64, 64 + }; + + + FT_LOCAL_DEF( AH_Angle ) + ah_angle( FT_Vector* v ) + { + FT_Pos dx, dy; + AH_Angle angle; + + + dx = v->x; + dy = v->y; + + /* check trivial cases */ + if ( dy == 0 ) + { + angle = 0; + if ( dx < 0 ) + angle = AH_PI; + return angle; + } + else if ( dx == 0 ) + { + angle = AH_HALF_PI; + if ( dy < 0 ) + angle = -AH_HALF_PI; + return angle; + } + + angle = 0; + if ( dx < 0 ) + { + dx = -v->x; + dy = -v->y; + angle = AH_PI; + } + + if ( dy < 0 ) + { + FT_Pos tmp; + + + tmp = dx; + dx = -dy; + dy = tmp; + angle -= AH_HALF_PI; + } + + if ( dx == 0 && dy == 0 ) + return 0; + + if ( dx == dy ) + angle += AH_PI / 4; + else if ( dx > dy ) + angle += ah_arctan[FT_DivFix( dy, dx ) >> ( 16 - AH_ATAN_BITS )]; + else + angle += AH_HALF_PI - + ah_arctan[FT_DivFix( dx, dy ) >> ( 16 - AH_ATAN_BITS )]; + + if ( angle > AH_PI ) + angle -= AH_2PI; + + return angle; + } + + + FT_LOCAL_DEF( AH_Angle ) + ah_angle_diff( AH_Angle angle1, + AH_Angle angle2 ) + { + AH_Angle delta; + + + delta = ( angle2 - angle1 ); + if ( delta < 0 ) + delta += AH_2PI; + + if ( delta > AH_PI ) + delta -= AH_2PI; + + return delta; + } + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahangles.h b/Utilities/vtkfreetype/src/autohint/ahangles.h new file mode 100644 index 0000000..f46bfaa --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahangles.h @@ -0,0 +1,64 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (specification). */ +/* */ +/* Copyright 2000-2001, 2002 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef __AHANGLES_H__ +#define __AHANGLES_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include "ahtypes.h" + + +FT_BEGIN_HEADER + + + /* PI expressed in ah_angles -- we don't really need an important */ + /* precision, so 256 should be enough */ +#define AH_PI 256 +#define AH_2PI ( AH_PI * 2 ) +#define AH_HALF_PI ( AH_PI / 2 ) +#define AH_2PIMASK ( AH_2PI - 1 ) + + /* the number of bits used to express an arc tangent; */ + /* see the structure of the lookup table */ +#define AH_ATAN_BITS 8 + + extern + const AH_Angle ah_arctan[1L << AH_ATAN_BITS]; + + + FT_LOCAL( AH_Angle ) + ah_angle( FT_Vector* v ); + + + FT_LOCAL( AH_Angle ) + ah_angle_diff( AH_Angle angle1, + AH_Angle angle2 ); + + +FT_END_HEADER + +#endif /* __AHANGLES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/aherrors.h b/Utilities/vtkfreetype/src/autohint/aherrors.h new file mode 100644 index 0000000..bce6107 --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/aherrors.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* aherrors.h */ +/* */ +/* Autohinter error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the Autohinter error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __AHERRORS_H__ +#define __AHERRORS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX AH_Err_ +#define FT_ERR_BASE FT_Mod_Err_Autohint + +#include FT_ERRORS_H + +#endif /* __AHERRORS_H__ */ + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahglobal.c b/Utilities/vtkfreetype/src/autohint/ahglobal.c new file mode 100644 index 0000000..e157014 --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahglobal.c @@ -0,0 +1,402 @@ +/***************************************************************************/ +/* */ +/* ahglobal.c */ +/* */ +/* Routines used to compute global metrics automatically (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include "ahglobal.h" +#include "ahglyph.h" + + +#define MAX_TEST_CHARACTERS 12 + + /* cf. AH_BLUE_XXX constants in ahtypes.h */ + + static + const char* const blue_chars[AH_BLUE_MAX] = + { + "THEZOCQS", + "HEZLOCUS", +#ifdef FT_CONFIG_CHESTER_SMALL_F + "fijkdbh", +#endif + "xzroesc", + "xzroesc", + "pqgjy" + }; + + + /* simple insertion sort */ + static void + sort_values( FT_Int count, + FT_Pos* table ) + { + FT_Int i, j; + FT_Pos swap; + + + for ( i = 1; i < count; i++ ) + { + for ( j = i; j > 0; j-- ) + { + if ( table[j] > table[j - 1] ) + break; + + swap = table[j]; + table[j] = table[j - 1]; + table[j - 1] = swap; + } + } + } + + + static FT_Error + ah_hinter_compute_blues( AH_Hinter hinter ) + { + AH_Blue blue; + AH_Globals globals = &hinter->globals->design; + FT_Pos flats [MAX_TEST_CHARACTERS]; + FT_Pos rounds[MAX_TEST_CHARACTERS]; + FT_Int num_flats; + FT_Int num_rounds; + + FT_Face face; + FT_GlyphSlot glyph; + FT_Error error; + FT_CharMap charmap; + + + face = hinter->face; + glyph = face->glyph; + + /* save current charmap */ + charmap = face->charmap; + + /* do we have a Unicode charmap in there? */ + error = FT_Select_Charmap( face, FT_ENCODING_UNICODE ); + if ( error ) + goto Exit; + + /* we compute the blues simply by loading each character from the */ + /* `blue_chars[blues]' string, then compute its top-most or */ + /* bottom-most points (depending on `AH_IS_TOP_BLUE') */ + + AH_LOG(( "blue zones computation\n" )); + AH_LOG(( "------------------------------------------------\n" )); + + for ( blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++ ) + { + const char* p = blue_chars[blue]; + const char* limit = p + MAX_TEST_CHARACTERS; + + FT_Pos *blue_ref, *blue_shoot; + + + AH_LOG(( "blue %3d: ", blue )); + + num_flats = 0; + num_rounds = 0; + + for ( ; p < limit; p++ ) + { + FT_UInt glyph_index; + FT_Vector* extremum; + FT_Vector* points; + FT_Vector* point_limit; + FT_Vector* point; + FT_Bool round; + + + /* exit if we reach the end of the string */ + if ( !*p ) + break; + + AH_LOG(( "`%c'", *p )); + + /* load the character in the face -- skip unknown or empty ones */ + glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); + if ( glyph_index == 0 ) + continue; + + error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); + if ( error || glyph->outline.n_points <= 0 ) + continue; + + /* now compute min or max point indices and coordinates */ + points = glyph->outline.points; + point_limit = points + glyph->outline.n_points; + point = points; + extremum = point; + point++; + + if ( AH_IS_TOP_BLUE( blue ) ) + { + for ( ; point < point_limit; point++ ) + if ( point->y > extremum->y ) + extremum = point; + } + else + { + for ( ; point < point_limit; point++ ) + if ( point->y < extremum->y ) + extremum = point; + } + + AH_LOG(( "%5d", (int)extremum->y )); + + /* now, check whether the point belongs to a straight or round */ + /* segment; we first need to find in which contour the extremum */ + /* lies, then see its previous and next points */ + { + FT_Int idx = (FT_Int)( extremum - points ); + FT_Int n; + FT_Int first, last, prev, next, end; + FT_Pos dist; + + + last = -1; + first = 0; + + for ( n = 0; n < glyph->outline.n_contours; n++ ) + { + end = glyph->outline.contours[n]; + if ( end >= idx ) + { + last = end; + break; + } + first = end + 1; + } + + /* XXX: should never happen! */ + if ( last < 0 ) + continue; + + /* now look for the previous and next points that are not on the */ + /* same Y coordinate. Threshold the `closeness'... */ + + prev = idx; + next = prev; + + do + { + if ( prev > first ) + prev--; + else + prev = last; + + dist = points[prev].y - extremum->y; + if ( dist < -5 || dist > 5 ) + break; + + } while ( prev != idx ); + + do + { + if ( next < last ) + next++; + else + next = first; + + dist = points[next].y - extremum->y; + if ( dist < -5 || dist > 5 ) + break; + + } while ( next != idx ); + + /* now, set the `round' flag depending on the segment's kind */ + round = FT_BOOL( + FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON || + FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON ); + + AH_LOG(( "%c ", round ? 'r' : 'f' )); + } + + if ( round ) + rounds[num_rounds++] = extremum->y; + else + flats[num_flats++] = extremum->y; + } + + AH_LOG(( "\n" )); + + /* we have computed the contents of the `rounds' and `flats' tables, */ + /* now determine the reference and overshoot position of the blue -- */ + /* we simply take the median value after a simple sort */ + sort_values( num_rounds, rounds ); + sort_values( num_flats, flats ); + + blue_ref = globals->blue_refs + blue; + blue_shoot = globals->blue_shoots + blue; + if ( num_flats == 0 && num_rounds == 0 ) + { + *blue_ref = -10000; + *blue_shoot = -10000; + } + else if ( num_flats == 0 ) + { + *blue_ref = + *blue_shoot = rounds[num_rounds / 2]; + } + else if ( num_rounds == 0 ) + { + *blue_ref = + *blue_shoot = flats[num_flats / 2]; + } + else + { + *blue_ref = flats[num_flats / 2]; + *blue_shoot = rounds[num_rounds / 2]; + } + + /* there are sometimes problems: if the overshoot position of top */ + /* zones is under its reference position, or the opposite for bottom */ + /* zones. We must thus check everything there and correct the errors */ + if ( *blue_shoot != *blue_ref ) + { + FT_Pos ref = *blue_ref; + FT_Pos shoot = *blue_shoot; + FT_Bool over_ref = FT_BOOL( shoot > ref ); + + + if ( AH_IS_TOP_BLUE( blue ) ^ over_ref ) + *blue_shoot = *blue_ref = ( shoot + ref ) / 2; + } + + AH_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); + } + + /* reset original face charmap */ + FT_Set_Charmap( face, charmap ); + error = 0; + + Exit: + return error; + } + + + static FT_Error + ah_hinter_compute_widths( AH_Hinter hinter ) + { + /* scan the array of segments in each direction */ + AH_Outline outline = hinter->glyph; + AH_Segment segments; + AH_Segment limit; + AH_Globals globals = &hinter->globals->design; + FT_Pos* widths; + FT_Int dimension; + FT_Int* p_num_widths; + FT_Error error = 0; + FT_Pos edge_distance_threshold = 32000; + + + globals->num_widths = 0; + globals->num_heights = 0; + + /* For now, compute the standard width and height from the `o' */ + /* character. I started computing the stem width of the `i' and the */ + /* stem height of the "-", but it wasn't too good. Moreover, we now */ + /* have a single character that gives us standard width and height. */ + { + FT_UInt glyph_index; + + + glyph_index = FT_Get_Char_Index( hinter->face, 'o' ); + if ( glyph_index == 0 ) + return 0; + + error = FT_Load_Glyph( hinter->face, glyph_index, FT_LOAD_NO_SCALE ); + if ( error ) + goto Exit; + + error = ah_outline_load( hinter->glyph, 0x10000L, 0x10000L, + hinter->face ); + if ( error ) + goto Exit; + + ah_outline_compute_segments( hinter->glyph ); + ah_outline_link_segments( hinter->glyph ); + } + + segments = outline->horz_segments; + limit = segments + outline->num_hsegments; + widths = globals->heights; + p_num_widths = &globals->num_heights; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Segment seg = segments; + AH_Segment link; + FT_Int num_widths = 0; + + + for ( ; seg < limit; seg++ ) + { + link = seg->link; + /* we only consider stem segments there! */ + if ( link && link->link == seg && link > seg ) + { + FT_Pos dist; + + + dist = seg->pos - link->pos; + if ( dist < 0 ) + dist = -dist; + + if ( num_widths < AH_MAX_WIDTHS ) + widths[num_widths++] = dist; + } + } + + sort_values( num_widths, widths ); + *p_num_widths = num_widths; + + /* we will now try to find the smallest width */ + if ( num_widths > 0 && widths[0] < edge_distance_threshold ) + edge_distance_threshold = widths[0]; + + segments = outline->vert_segments; + limit = segments + outline->num_vsegments; + widths = globals->widths; + p_num_widths = &globals->num_widths; + } + + /* Now, compute the edge distance threshold as a fraction of the */ + /* smallest width in the font. Set it in `hinter->glyph' too! */ + if ( edge_distance_threshold == 32000 ) + edge_distance_threshold = 50; + + /* let's try 20% */ + hinter->glyph->edge_distance_threshold = edge_distance_threshold / 5; + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + ah_hinter_compute_globals( AH_Hinter hinter ) + { + return ah_hinter_compute_widths( hinter ) || + ah_hinter_compute_blues ( hinter ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahglobal.h b/Utilities/vtkfreetype/src/autohint/ahglobal.h new file mode 100644 index 0000000..5a9bcf8 --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahglobal.h @@ -0,0 +1,59 @@ +/***************************************************************************/ +/* */ +/* ahglobal.h */ +/* */ +/* Routines used to compute global metrics automatically */ +/* (specification). */ +/* */ +/* Copyright 2000-2001, 2002, 2003 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef __AHGLOBAL_H__ +#define __AHGLOBAL_H__ + + +#include <ft2build.h> +#include "ahtypes.h" +#include FT_INTERNAL_OBJECTS_H + + +FT_BEGIN_HEADER + + +#ifdef FT_CONFIG_CHESTER_SMALL_F + +#define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || \ + (b) == AH_BLUE_SMALL_F_TOP || \ + (b) == AH_BLUE_SMALL_TOP ) + +#else /* !FT_CONFIG_CHESTER_SMALL_F */ + +#define AH_IS_TOP_BLUE( b ) ( (b) == AH_BLUE_CAPITAL_TOP || \ + (b) == AH_BLUE_SMALL_TOP ) + +#endif /* !FT_CONFIG_CHESTER_SMALL_F */ + + + /* compute global metrics automatically */ + FT_LOCAL( FT_Error ) + ah_hinter_compute_globals( AH_Hinter hinter ); + + +FT_END_HEADER + +#endif /* __AHGLOBAL_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahglyph.c b/Utilities/vtkfreetype/src/autohint/ahglyph.c new file mode 100644 index 0000000..2a0390b --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahglyph.c @@ -0,0 +1,1699 @@ +/***************************************************************************/ +/* */ +/* ahglyph.c */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "ahglyph.h" +#include "ahangles.h" +#include "ahglobal.h" +#include "aherrors.h" + + +#ifdef AH_DEBUG + +#include <stdio.h> + + void + ah_dump_edges( AH_Outline outline ) + { + AH_Edge edges; + AH_Edge edge_limit; + AH_Segment segments; + FT_Int dimension; + + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + segments = outline->horz_segments; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge edge; + + + printf ( "Table of %s edges:\n", + !dimension ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link |" + " serif | blue | opos | pos ]\n" ); + + for ( edge = edges; edge < edge_limit; edge++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n", + edge - edges, + (int)edge->fpos, + edge->dir == AH_DIR_UP + ? "up" + : ( edge->dir == AH_DIR_DOWN + ? "down" + : ( edge->dir == AH_DIR_LEFT + ? "left" + : ( edge->dir == AH_DIR_RIGHT + ? "right" + : "none" ) ) ), + edge->link ? ( edge->link - edges ) : -1, + edge->serif ? ( edge->serif - edges ) : -1, + edge->blue_edge ? 'y' : 'n', + edge->opos / 64.0, + edge->pos / 64.0 ); + } + + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + segments = outline->vert_segments; + } + } + + + /* A function used to dump the array of linked segments */ + void + ah_dump_segments( AH_Outline outline ) + { + AH_Segment segments; + AH_Segment segment_limit; + AH_Point points; + FT_Int dimension; + + + points = outline->points; + segments = outline->horz_segments; + segment_limit = segments + outline->num_hsegments; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Segment seg; + + + printf ( "Table of %s segments:\n", + !dimension ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link | serif |" + " numl | first | start ]\n" ); + + for ( seg = segments; seg < segment_limit; seg++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n", + seg - segments, + (int)seg->pos, + seg->dir == AH_DIR_UP + ? "up" + : ( seg->dir == AH_DIR_DOWN + ? "down" + : ( seg->dir == AH_DIR_LEFT + ? "left" + : ( seg->dir == AH_DIR_RIGHT + ? "right" + : "none" ) ) ), + seg->link ? ( seg->link - segments ) : -1, + seg->serif ? ( seg->serif - segments ) : -1, + (int)seg->num_linked, + seg->first - points, + seg->last - points ); + } + + segments = outline->vert_segments; + segment_limit = segments + outline->num_vsegments; + } + } + +#endif /* AH_DEBUG */ + + + /* compute the direction value of a given vector */ + static AH_Direction + ah_compute_direction( FT_Pos dx, + FT_Pos dy ) + { + AH_Direction dir; + FT_Pos ax = FT_ABS( dx ); + FT_Pos ay = FT_ABS( dy ); + + + dir = AH_DIR_NONE; + + /* atan(1/12) == 4.7 degrees */ + + /* test for vertical direction */ + if ( ax * 12 < ay ) + { + dir = dy > 0 ? AH_DIR_UP : AH_DIR_DOWN; + } + /* test for horizontal direction */ + else if ( ay * 12 < ax ) + { + dir = dx > 0 ? AH_DIR_RIGHT : AH_DIR_LEFT; + } + + return dir; + } + + + /* this function is used by ah_get_orientation (see below) to test */ + /* the fill direction of given bbox extremum */ + static FT_Int + ah_test_extremum( FT_Outline* outline, + FT_Int n ) + { + FT_Vector *prev, *cur, *next; + FT_Pos product; + FT_Int first, last, c; + FT_Int retval; + + + /* we need to compute the `previous' and `next' point */ + /* for this extremum; we check whether the extremum */ + /* is start or end of a contour and providing */ + /* appropriate values if so */ + cur = outline->points + n; + prev = cur - 1; + next = cur + 1; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + last = outline->contours[c]; + + if ( n == first ) + prev = outline->points + last; + + if ( n == last ) + next = outline->points + first; + + first = last + 1; + } + + /* compute the vectorial product -- since we know that the angle */ + /* is <= 180 degrees (otherwise it wouldn't be an extremum) we */ + /* can determine the filling orientation if the product is */ + /* either positive or negative */ + product = FT_MulDiv( cur->x - prev->x, /* in.x */ + next->y - cur->y, /* out.y */ + 0x40 ) + - + FT_MulDiv( cur->y - prev->y, /* in.y */ + next->x - cur->x, /* out.x */ + 0x40 ); + + retval = 0; + if ( product ) + retval = product > 0 ? 2 : 1; + + return retval; + } + + + /* Compute the orientation of path filling. It differs between TrueType */ + /* and Type1 formats. We could use the `FT_OUTLINE_REVERSE_FILL' flag, */ + /* but it is better to re-compute it directly (it seems that this flag */ + /* isn't correctly set for some weird composite glyphs currently). */ + /* */ + /* We do this by computing bounding box points, and computing their */ + /* curvature. */ + /* */ + /* The function returns either 1 or 2. */ + /* */ + static FT_Int + ah_get_orientation( FT_Outline* outline ) + { + FT_BBox box; + FT_Int indices_xMin, indices_yMin, indices_xMax, indices_yMax; + FT_Int n, last; + + + indices_xMin = -1; + indices_yMin = -1; + indices_xMax = -1; + indices_yMax = -1; + + box.xMin = box.yMin = 32767L; + box.xMax = box.yMax = -32768L; + + /* is it empty? */ + if ( outline->n_contours < 1 ) + return 1; + + last = outline->contours[outline->n_contours - 1]; + + for ( n = 0; n <= last; n++ ) + { + FT_Pos x, y; + + + x = outline->points[n].x; + if ( x < box.xMin ) + { + box.xMin = x; + indices_xMin = n; + } + if ( x > box.xMax ) + { + box.xMax = x; + indices_xMax = n; + } + + y = outline->points[n].y; + if ( y < box.yMin ) + { + box.yMin = y; + indices_yMin = n; + } + if ( y > box.yMax ) + { + box.yMax = y; + indices_yMax = n; + } + } + + /* test orientation of the extrema */ + n = ah_test_extremum( outline, indices_xMin ); + if ( n ) + goto Exit; + + n = ah_test_extremum( outline, indices_yMin ); + if ( n ) + goto Exit; + + n = ah_test_extremum( outline, indices_xMax ); + if ( n ) + goto Exit; + + n = ah_test_extremum( outline, indices_yMax ); + if ( !n ) + n = 1; + + Exit: + return n; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ah_outline_new */ + /* */ + /* <Description> */ + /* Creates a new and empty AH_OutlineRec object. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + ah_outline_new( FT_Memory memory, + AH_Outline* aoutline ) + { + FT_Error error; + AH_Outline outline; + + + if ( !FT_NEW( outline ) ) + { + outline->memory = memory; + *aoutline = outline; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ah_outline_done */ + /* */ + /* <Description> */ + /* Destroys a given AH_OutlineRec object. */ + /* */ + FT_LOCAL_DEF( void ) + ah_outline_done( AH_Outline outline ) + { + FT_Memory memory = outline->memory; + + + FT_FREE( outline->horz_edges ); + FT_FREE( outline->horz_segments ); + FT_FREE( outline->contours ); + FT_FREE( outline->points ); + + FT_FREE( outline ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ah_outline_save */ + /* */ + /* <Description> */ + /* Saves the contents of a given AH_OutlineRec object into a face's */ + /* glyph slot. */ + /* */ + FT_LOCAL_DEF( void ) + ah_outline_save( AH_Outline outline, + AH_Loader gloader ) + { + AH_Point point = outline->points; + AH_Point point_limit = point + outline->num_points; + FT_Vector* vec = gloader->current.outline.points; + char* tag = gloader->current.outline.tags; + + + /* we assume that the glyph loader has already been checked for storage */ + for ( ; point < point_limit; point++, vec++, tag++ ) + { + vec->x = point->x; + vec->y = point->y; + + if ( point->flags & AH_FLAG_CONIC ) + tag[0] = FT_CURVE_TAG_CONIC; + else if ( point->flags & AH_FLAG_CUBIC ) + tag[0] = FT_CURVE_TAG_CUBIC; + else + tag[0] = FT_CURVE_TAG_ON; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ah_outline_load */ + /* */ + /* <Description> */ + /* Loads an unscaled outline from a glyph slot into an AH_OutlineRec */ + /* object. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + ah_outline_load( AH_Outline outline, + FT_Fixed x_scale, + FT_Fixed y_scale, + FT_Face face ) + { + FT_Memory memory = outline->memory; + FT_Error error = AH_Err_Ok; + FT_Outline* source = &face->glyph->outline; + FT_Int num_points = source->n_points; + FT_Int num_contours = source->n_contours; + AH_Point points; + + + /* check arguments */ + if ( !face || + !face->size || + face->glyph->format != FT_GLYPH_FORMAT_OUTLINE ) + return AH_Err_Invalid_Argument; + + /* first of all, reallocate the contours array if necessary */ + if ( num_contours > outline->max_contours ) + { + FT_Int new_contours = FT_PAD_CEIL( num_contours, 4 ); + + + if ( FT_RENEW_ARRAY( outline->contours, + outline->max_contours, + new_contours ) ) + goto Exit; + + outline->max_contours = new_contours; + } + + /* then, reallocate the points, segments & edges arrays if needed -- */ + /* note that we reserved two additional point positions, used to */ + /* hint metrics appropriately */ + /* */ + if ( num_points + 2 > outline->max_points ) + { + FT_Int news = FT_PAD_CEIL( num_points + 2, 8 ); + FT_Int max = outline->max_points; + + + if ( FT_RENEW_ARRAY( outline->points, max, news ) || + FT_RENEW_ARRAY( outline->horz_edges, max * 2, news * 2 ) || + FT_RENEW_ARRAY( outline->horz_segments, max * 2, news * 2 ) ) + goto Exit; + + /* readjust some pointers */ + outline->vert_edges = outline->horz_edges + news; + outline->vert_segments = outline->horz_segments + news; + outline->max_points = news; + } + + outline->num_points = num_points; + outline->num_contours = num_contours; + + outline->num_hedges = 0; + outline->num_vedges = 0; + outline->num_hsegments = 0; + outline->num_vsegments = 0; + + /* We can't rely on the value of `FT_Outline.flags' to know the fill */ + /* direction used for a glyph, given that some fonts are broken (e.g. */ + /* the Arphic ones). We thus recompute it each time we need to. */ + /* */ + outline->vert_major_dir = AH_DIR_UP; + outline->horz_major_dir = AH_DIR_LEFT; + + if ( ah_get_orientation( source ) > 1 ) + { + outline->vert_major_dir = AH_DIR_DOWN; + outline->horz_major_dir = AH_DIR_RIGHT; + } + + outline->x_scale = x_scale; + outline->y_scale = y_scale; + + points = outline->points; + if ( outline->num_points == 0 ) + goto Exit; + + { + /* do one thing at a time -- it is easier to understand, and */ + /* the code is clearer */ + AH_Point point; + AH_Point point_limit = points + outline->num_points; + + + /* compute coordinates */ + { + FT_Vector* vec = source->points; + + + for ( point = points; point < point_limit; vec++, point++ ) + { + point->fx = vec->x; + point->fy = vec->y; + point->ox = point->x = FT_MulFix( vec->x, x_scale ); + point->oy = point->y = FT_MulFix( vec->y, y_scale ); + + point->flags = 0; + } + } + + /* compute Bezier flags */ + { + char* tag = source->tags; + + + for ( point = points; point < point_limit; point++, tag++ ) + { + switch ( FT_CURVE_TAG( *tag ) ) + { + case FT_CURVE_TAG_CONIC: + point->flags = AH_FLAG_CONIC; + break; + case FT_CURVE_TAG_CUBIC: + point->flags = AH_FLAG_CUBIC; + break; + default: + ; + } + } + } + + /* compute `next' and `prev' */ + { + FT_Int contour_index; + AH_Point prev; + AH_Point first; + AH_Point end; + + + contour_index = 0; + + first = points; + end = points + source->contours[0]; + prev = end; + + for ( point = points; point < point_limit; point++ ) + { + point->prev = prev; + if ( point < end ) + { + point->next = point + 1; + prev = point; + } + else + { + point->next = first; + contour_index++; + if ( point + 1 < point_limit ) + { + end = points + source->contours[contour_index]; + first = point + 1; + prev = end; + } + } + } + } + + /* set-up the contours array */ + { + AH_Point* contour = outline->contours; + AH_Point* contour_limit = contour + outline->num_contours; + short* end = source->contours; + short idx = 0; + + + for ( ; contour < contour_limit; contour++, end++ ) + { + contour[0] = points + idx; + idx = (short)( end[0] + 1 ); + } + } + + /* compute directions of in & out vectors */ + { + for ( point = points; point < point_limit; point++ ) + { + AH_Point prev; + AH_Point next; + FT_Vector ivec, ovec; + + + prev = point->prev; + ivec.x = point->fx - prev->fx; + ivec.y = point->fy - prev->fy; + + point->in_dir = ah_compute_direction( ivec.x, ivec.y ); + + next = point->next; + ovec.x = next->fx - point->fx; + ovec.y = next->fy - point->fy; + + point->out_dir = ah_compute_direction( ovec.x, ovec.y ); + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + if ( point->flags & ( AH_FLAG_CONIC | AH_FLAG_CUBIC ) ) + { + Is_Weak_Point: + point->flags |= AH_FLAG_WEAK_INTERPOLATION; + } + else if ( point->out_dir == point->in_dir ) + { + AH_Angle angle_in, angle_out, delta; + + + if ( point->out_dir != AH_DIR_NONE ) + goto Is_Weak_Point; + + angle_in = ah_angle( &ivec ); + angle_out = ah_angle( &ovec ); + delta = angle_in - angle_out; + + if ( delta > AH_PI ) + delta = AH_2PI - delta; + + if ( delta < 0 ) + delta = -delta; + + if ( delta < 2 ) + goto Is_Weak_Point; + } + else if ( point->in_dir == -point->out_dir ) + goto Is_Weak_Point; +#endif + } + } + } + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + ah_setup_uv( AH_Outline outline, + AH_UV source ) + { + AH_Point point = outline->points; + AH_Point point_limit = point + outline->num_points; + + + switch ( source ) + { + case AH_UV_FXY: + for ( ; point < point_limit; point++ ) + { + point->u = point->fx; + point->v = point->fy; + } + break; + + case AH_UV_FYX: + for ( ; point < point_limit; point++ ) + { + point->u = point->fy; + point->v = point->fx; + } + break; + + case AH_UV_OXY: + for ( ; point < point_limit; point++ ) + { + point->u = point->ox; + point->v = point->oy; + } + break; + + case AH_UV_OYX: + for ( ; point < point_limit; point++ ) + { + point->u = point->oy; + point->v = point->ox; + } + break; + + case AH_UV_YX: + for ( ; point < point_limit; point++ ) + { + point->u = point->y; + point->v = point->x; + } + break; + + case AH_UV_OX: + for ( ; point < point_limit; point++ ) + { + point->u = point->x; + point->v = point->ox; + } + break; + + case AH_UV_OY: + for ( ; point < point_limit; point++ ) + { + point->u = point->y; + point->v = point->oy; + } + break; + + default: + for ( ; point < point_limit; point++ ) + { + point->u = point->x; + point->v = point->y; + } + } + } + + + /* compute all inflex points in a given glyph */ + static void + ah_outline_compute_inflections( AH_Outline outline ) + { + AH_Point* contour = outline->contours; + AH_Point* contour_limit = contour + outline->num_contours; + + + /* load original coordinates in (u,v) */ + ah_setup_uv( outline, AH_UV_FXY ); + + /* do each contour separately */ + for ( ; contour < contour_limit; contour++ ) + { + FT_Vector vec; + AH_Point point = contour[0]; + AH_Point first = point; + AH_Point start = point; + AH_Point end = point; + AH_Point before; + AH_Point after; + AH_Angle angle_in, angle_seg, angle_out; + AH_Angle diff_in, diff_out; + FT_Int finished = 0; + + + /* compute first segment in contour */ + first = point; + + start = end = first; + do + { + end = end->next; + if ( end == first ) + goto Skip; + + } while ( end->u == first->u && end->v == first->v ); + + vec.x = end->u - start->u; + vec.y = end->v - start->v; + angle_seg = ah_angle( &vec ); + + /* extend the segment start whenever possible */ + before = start; + do + { + do + { + start = before; + before = before->prev; + if ( before == first ) + goto Skip; + + } while ( before->u == start->u && before->v == start->v ); + + vec.x = start->u - before->u; + vec.y = start->v - before->v; + angle_in = ah_angle( &vec ); + + } while ( angle_in == angle_seg ); + + first = start; + diff_in = ah_angle_diff( angle_in, angle_seg ); + + /* now, process all segments in the contour */ + do + { + /* first, extend current segment's end whenever possible */ + after = end; + do + { + do + { + end = after; + after = after->next; + if ( after == first ) + finished = 1; + + } while ( end->u == after->u && end->v == after->v ); + + vec.x = after->u - end->u; + vec.y = after->v - end->v; + angle_out = ah_angle( &vec ); + + } while ( angle_out == angle_seg ); + + diff_out = ah_angle_diff( angle_seg, angle_out ); + + if ( ( diff_in ^ diff_out ) < 0 ) + { + /* diff_in and diff_out have different signs, we have */ + /* inflection points here... */ + do + { + start->flags |= AH_FLAG_INFLECTION; + start = start->next; + + } while ( start != end ); + + start->flags |= AH_FLAG_INFLECTION; + } + + start = end; + end = after; + angle_seg = angle_out; + diff_in = diff_out; + + } while ( !finished ); + + Skip: + ; + } + } + + + FT_LOCAL_DEF( void ) + ah_outline_compute_segments( AH_Outline outline ) + { + int dimension; + AH_Segment segments; + FT_Int* p_num_segments; + AH_Direction segment_dir; + AH_Direction major_dir; + + + segments = outline->horz_segments; + p_num_segments = &outline->num_hsegments; + major_dir = AH_DIR_RIGHT; /* This value must be positive! */ + segment_dir = major_dir; + + /* set up (u,v) in each point */ + ah_setup_uv( outline, AH_UV_FYX ); + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Point* contour = outline->contours; + AH_Point* contour_limit = contour + outline->num_contours; + AH_Segment segment = segments; + FT_Int num_segments = 0; + +#ifdef AH_HINT_METRICS + AH_Point min_point = 0; + AH_Point max_point = 0; + FT_Pos min_coord = 32000; + FT_Pos max_coord = -32000; +#endif + + + /* do each contour separately */ + for ( ; contour < contour_limit; contour++ ) + { + AH_Point point = contour[0]; + AH_Point last = point->prev; + int on_edge = 0; + FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */ + FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */ + FT_Bool passed; + + +#ifdef AH_HINT_METRICS + if ( point->u < min_coord ) + { + min_coord = point->u; + min_point = point; + } + if ( point->u > max_coord ) + { + max_coord = point->u; + max_point = point; + } +#endif + + if ( point == last ) /* skip singletons -- just in case */ + continue; + + if ( FT_ABS( last->out_dir ) == major_dir && + FT_ABS( point->out_dir ) == major_dir ) + { + /* we are already on an edge, try to locate its start */ + last = point; + + for (;;) + { + point = point->prev; + if ( FT_ABS( point->out_dir ) != major_dir ) + { + point = point->next; + break; + } + if ( point == last ) + break; + } + } + + last = point; + passed = 0; + + for (;;) + { + FT_Pos u, v; + + + if ( on_edge ) + { + u = point->u; + if ( u < min_pos ) + min_pos = u; + if ( u > max_pos ) + max_pos = u; + + if ( point->out_dir != segment_dir || point == last ) + { + /* we are just leaving an edge; record a new segment! */ + segment->last = point; + segment->pos = ( min_pos + max_pos ) >> 1; + + /* a segment is round if either its first or last point */ + /* is a control point */ + if ( ( segment->first->flags | point->flags ) & + AH_FLAG_CONTROL ) + segment->flags |= AH_EDGE_ROUND; + + /* compute segment size */ + min_pos = max_pos = point->v; + + v = segment->first->v; + if ( v < min_pos ) + min_pos = v; + if ( v > max_pos ) + max_pos = v; + + segment->min_coord = min_pos; + segment->max_coord = max_pos; + + on_edge = 0; + num_segments++; + segment++; + /* fallthrough */ + } + } + + /* now exit if we are at the start/end point */ + if ( point == last ) + { + if ( passed ) + break; + passed = 1; + } + + if ( !on_edge && FT_ABS( point->out_dir ) == major_dir ) + { + /* this is the start of a new segment! */ + segment_dir = point->out_dir; + + /* clear all segment fields */ + FT_ZERO( segment ); + + segment->dir = segment_dir; + segment->flags = AH_EDGE_NORMAL; + min_pos = max_pos = point->u; + segment->first = point; + segment->last = point; + segment->contour = contour; + segment->score = 32000; + segment->link = NULL; + on_edge = 1; + +#ifdef AH_HINT_METRICS + if ( point == max_point ) + max_point = 0; + + if ( point == min_point ) + min_point = 0; +#endif + } + + point = point->next; + } + + } /* contours */ + +#ifdef AH_HINT_METRICS + /* we need to ensure that there are edges on the left-most and */ + /* right-most points of the glyph in order to hint the metrics; */ + /* we do this by inserting fake segments when needed */ + if ( dimension == 0 ) + { + AH_Point point = outline->points; + AH_Point point_limit = point + outline->num_points; + + FT_Pos min_pos = 32000; + FT_Pos max_pos = -32000; + + + min_point = 0; + max_point = 0; + + /* compute minimum and maximum points */ + for ( ; point < point_limit; point++ ) + { + FT_Pos x = point->fx; + + + if ( x < min_pos ) + { + min_pos = x; + min_point = point; + } + if ( x > max_pos ) + { + max_pos = x; + max_point = point; + } + } + + /* insert minimum segment */ + if ( min_point ) + { + /* clear all segment fields */ + FT_ZERO( segment ); + + segment->dir = segment_dir; + segment->flags = AH_EDGE_NORMAL; + segment->first = min_point; + segment->last = min_point; + segment->pos = min_pos; + segment->score = 32000; + segment->link = NULL; + + num_segments++; + segment++; + } + + /* insert maximum segment */ + if ( max_point ) + { + /* clear all segment fields */ + FT_ZERO( segment ); + + segment->dir = segment_dir; + segment->flags = AH_EDGE_NORMAL; + segment->first = max_point; + segment->last = max_point; + segment->pos = max_pos; + segment->score = 32000; + segment->link = NULL; + + num_segments++; + segment++; + } + } +#endif /* AH_HINT_METRICS */ + + *p_num_segments = num_segments; + + segments = outline->vert_segments; + major_dir = AH_DIR_UP; + p_num_segments = &outline->num_vsegments; + + ah_setup_uv( outline, AH_UV_FXY ); + } + } + + + FT_LOCAL_DEF( void ) + ah_outline_link_segments( AH_Outline outline ) + { + AH_Segment segments; + AH_Segment segment_limit; + AH_Direction major_dir; + int dimension; + + + segments = outline->horz_segments; + segment_limit = segments + outline->num_hsegments; + major_dir = outline->horz_major_dir; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Segment seg1; + AH_Segment seg2; + +#if 0 + /* now compare each segment to the others */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { + FT_Pos best_score; + AH_Segment best_segment; + + + /* the fake segments are introduced to hint the metrics -- */ + /* we must never link them to anything */ + if ( seg1->first == seg1->last ) + continue; + + best_segment = seg1->link; + if ( best_segment ) + best_score = seg1->score; + else + best_score = +32000; + + for ( seg2 = segments; seg2 < segment_limit; seg2++ ) + if ( seg1 != seg2 && seg1->dir + seg2->dir == 0 ) + { + FT_Pos pos1 = seg1->pos; + FT_Pos pos2 = seg2->pos; + FT_Bool is_dir; + FT_Bool is_pos; + + + /* check that the segments are correctly oriented and */ + /* positioned to form a black distance */ + + is_dir = (FT_Bool)( seg1->dir == outline->horz_major_dir || + seg1->dir == outline->vert_major_dir ); + is_pos = (FT_Bool)( pos1 > pos2 ); + + if ( pos1 == pos2 || !(is_dir ^ is_pos) ) + continue; + + { + FT_Pos min = seg1->min_coord; + FT_Pos max = seg1->max_coord; + FT_Pos len, dist, score; + + + if ( min < seg2->min_coord ) + min = seg2->min_coord; + + if ( max > seg2->max_coord ) + max = seg2->max_coord; + + len = max - min; + if ( len >= 8 ) + { + dist = seg2->pos - seg1->pos; + if ( dist < 0 ) + dist = -dist; + + score = dist + 3000 / len; + + if ( score < best_score ) + { + best_score = score; + best_segment = seg2; + } + } + } + } + + if ( best_segment ) + { + seg1->link = best_segment; + seg1->score = best_score; + best_segment->num_linked++; + } + } +#endif /* 0 */ + +#if 1 + /* the following code does the same, but much faster! */ + + /* now compare each segment to the others */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { + /* the fake segments are introduced to hint the metrics -- */ + /* we must never link them to anything */ + if ( seg1->first == seg1->last || seg1->dir != major_dir ) + continue; + + for ( seg2 = segments; seg2 < segment_limit; seg2++ ) + if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 ) + { + FT_Pos pos1 = seg1->pos; + FT_Pos pos2 = seg2->pos; + FT_Pos dist = pos2 - pos1; + + + if ( dist < 0 ) + continue; + + { + FT_Pos min = seg1->min_coord; + FT_Pos max = seg1->max_coord; + FT_Pos len, score; + + + if ( min < seg2->min_coord ) + min = seg2->min_coord; + + if ( max > seg2->max_coord ) + max = seg2->max_coord; + + len = max - min; + if ( len >= 8 ) + { + score = dist + 3000 / len; + + if ( score < seg1->score ) + { + seg1->score = score; + seg1->link = seg2; + } + + if ( score < seg2->score ) + { + seg2->score = score; + seg2->link = seg1; + } + } + } + } + } +#endif /* 1 */ + + /* now, compute the `serif' segments */ + for ( seg1 = segments; seg1 < segment_limit; seg1++ ) + { + seg2 = seg1->link; + + if ( seg2 ) + { + seg2->num_linked++; + if ( seg2->link != seg1 ) + { + seg1->link = 0; + seg1->serif = seg2->link; + } + } + } + + segments = outline->vert_segments; + segment_limit = segments + outline->num_vsegments; + major_dir = outline->vert_major_dir; + } + } + + + static void + ah_outline_compute_edges( AH_Outline outline ) + { + AH_Edge edges; + AH_Segment segments; + AH_Segment segment_limit; + AH_Direction up_dir; + FT_Int* p_num_edges; + FT_Int dimension; + FT_Fixed scale; + FT_Pos edge_distance_threshold; + + + edges = outline->horz_edges; + segments = outline->horz_segments; + segment_limit = segments + outline->num_hsegments; + p_num_edges = &outline->num_hedges; + up_dir = AH_DIR_RIGHT; + scale = outline->y_scale; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge edge; + AH_Edge edge_limit; /* really == edge + num_edges */ + AH_Segment seg; + + + /*********************************************************************/ + /* */ + /* We will begin by generating a sorted table of edges for the */ + /* current direction. To do so, we simply scan each segment and try */ + /* to find an edge in our table that corresponds to its position. */ + /* */ + /* If no edge is found, we create and insert a new edge in the */ + /* sorted table. Otherwise, we simply add the segment to the edge's */ + /* list which will be processed in the second step to compute the */ + /* edge's properties. */ + /* */ + /* Note that the edges table is sorted along the segment/edge */ + /* position. */ + /* */ + /*********************************************************************/ + + edge_distance_threshold = FT_MulFix( outline->edge_distance_threshold, + scale ); + if ( edge_distance_threshold > 64 / 4 ) + edge_distance_threshold = 64 / 4; + + edge_distance_threshold = FT_DivFix( edge_distance_threshold, + scale ); + + edge_limit = edges; + for ( seg = segments; seg < segment_limit; seg++ ) + { + AH_Edge found = 0; + + + /* look for an edge corresponding to the segment */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + FT_Pos dist; + + + dist = seg->pos - edge->fpos; + if ( dist < 0 ) + dist = -dist; + + if ( dist < edge_distance_threshold ) + { + found = edge; + break; + } + } + + if ( !found ) + { + /* insert a new edge in the list and */ + /* sort according to the position */ + while ( edge > edges && edge[-1].fpos > seg->pos ) + { + edge[0] = edge[-1]; + edge--; + } + edge_limit++; + + /* clear all edge fields */ + FT_MEM_ZERO( edge, sizeof ( *edge ) ); + + /* add the segment to the new edge's list */ + edge->first = seg; + edge->last = seg; + edge->fpos = seg->pos; + edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); + seg->edge_next = seg; + } + else + { + /* if an edge was found, simply add the segment to the edge's */ + /* list */ + seg->edge_next = edge->first; + edge->last->edge_next = seg; + edge->last = seg; + } + } + *p_num_edges = (FT_Int)( edge_limit - edges ); + + + /*********************************************************************/ + /* */ + /* Good, we will now compute each edge's properties according to */ + /* segments found on its position. Basically, these are: */ + /* */ + /* - edge's main direction */ + /* - stem edge, serif edge or both (which defaults to stem then) */ + /* - rounded edge, straight or both (which defaults to straight) */ + /* - link for edge */ + /* */ + /*********************************************************************/ + + /* first of all, set the `edge' field in each segment -- this is */ + /* required in order to compute edge links */ + + /* Note that I've tried to remove this loop, setting + * the "edge" field of each segment directly in the + * code above. For some reason, it slows down execution + * speed -- on a Sun. + */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + seg = edge->first; + if ( seg ) + do + { + seg->edge = edge; + seg = seg->edge_next; + } + while ( seg != edge->first ); + } + + /* now, compute each edge properties */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + FT_Int is_round = 0; /* does it contain round segments? */ + FT_Int is_straight = 0; /* does it contain straight segments? */ + FT_Pos ups = 0; /* number of upwards segments */ + FT_Pos downs = 0; /* number of downwards segments */ + + + seg = edge->first; + + do + { + FT_Bool is_serif; + + + /* check for roundness of segment */ + if ( seg->flags & AH_EDGE_ROUND ) + is_round++; + else + is_straight++; + + /* check for segment direction */ + if ( seg->dir == up_dir ) + ups += seg->max_coord-seg->min_coord; + else + downs += seg->max_coord-seg->min_coord; + + /* check for links -- if seg->serif is set, then seg->link must */ + /* be ignored */ + is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge ); + + if ( seg->link || is_serif ) + { + AH_Edge edge2; + AH_Segment seg2; + + + edge2 = edge->link; + seg2 = seg->link; + + if ( is_serif ) + { + seg2 = seg->serif; + edge2 = edge->serif; + } + + if ( edge2 ) + { + FT_Pos edge_delta; + FT_Pos seg_delta; + + + edge_delta = edge->fpos - edge2->fpos; + if ( edge_delta < 0 ) + edge_delta = -edge_delta; + + seg_delta = seg->pos - seg2->pos; + if ( seg_delta < 0 ) + seg_delta = -seg_delta; + + if ( seg_delta < edge_delta ) + edge2 = seg2->edge; + } + else + edge2 = seg2->edge; + +#ifdef FT_CONFIG_CHESTER_SERIF + if ( is_serif ) + { + edge->serif = edge2; + edge2->flags |= AH_EDGE_SERIF; + } + else + edge->link = edge2; +#else /* !FT_CONFIG_CHESTER_SERIF */ + if ( is_serif ) + edge->serif = edge2; + else + edge->link = edge2; +#endif /* !FT_CONFIG_CHESTER_SERIF */ + } + + seg = seg->edge_next; + + } while ( seg != edge->first ); + + /* set the round/straight flags */ + edge->flags = AH_EDGE_NORMAL; + + if ( is_round > 0 && is_round >= is_straight ) + edge->flags |= AH_EDGE_ROUND; + + /* set the edge's main direction */ + edge->dir = AH_DIR_NONE; + + if ( ups > downs ) + edge->dir = up_dir; + + else if ( ups < downs ) + edge->dir = -up_dir; + + else if ( ups == downs ) + edge->dir = 0; /* both up and down! */ + + /* gets rid of serifs if link is set */ + /* XXX: This gets rid of many unpleasant artefacts! */ + /* Example: the `c' in cour.pfa at size 13 */ + + if ( edge->serif && edge->link ) + edge->serif = 0; + } + + edges = outline->vert_edges; + segments = outline->vert_segments; + segment_limit = segments + outline->num_vsegments; + p_num_edges = &outline->num_vedges; + up_dir = AH_DIR_UP; + scale = outline->x_scale; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ah_outline_detect_features */ + /* */ + /* <Description> */ + /* Performs feature detection on a given AH_OutlineRec object. */ + /* */ + FT_LOCAL_DEF( void ) + ah_outline_detect_features( AH_Outline outline ) + { + ah_outline_compute_segments ( outline ); + ah_outline_link_segments ( outline ); + ah_outline_compute_edges ( outline ); + ah_outline_compute_inflections( outline ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ah_outline_compute_blue_edges */ + /* */ + /* <Description> */ + /* Computes the `blue edges' in a given outline (i.e. those that must */ + /* be snapped to a blue zone edge (top or bottom). */ + /* */ + FT_LOCAL_DEF( void ) + ah_outline_compute_blue_edges( AH_Outline outline, + AH_Face_Globals face_globals ) + { + AH_Edge edge = outline->horz_edges; + AH_Edge edge_limit = edge + outline->num_hedges; + AH_Globals globals = &face_globals->design; + FT_Fixed y_scale = outline->y_scale; + + FT_Bool blue_active[AH_BLUE_MAX]; + + + /* compute which blue zones are active, i.e. have their scaled */ + /* size < 3/4 pixels */ + { + AH_Blue blue; + FT_Bool check = 0; + + + for ( blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++ ) + { + FT_Pos ref, shoot, dist; + + + ref = globals->blue_refs[blue]; + shoot = globals->blue_shoots[blue]; + dist = ref - shoot; + if ( dist < 0 ) + dist = -dist; + + blue_active[blue] = 0; + + if ( FT_MulFix( dist, y_scale ) < 48 ) + { + blue_active[blue] = 1; + check = 1; + } + } + + /* return immediately if no blue zone is active */ + if ( !check ) + return; + } + + /* for each horizontal edge search the blue zone which is closest */ + for ( ; edge < edge_limit; edge++ ) + { + AH_Blue blue; + FT_Pos* best_blue = 0; + FT_Pos best_dist; /* initial threshold */ + + + /* compute the initial threshold as a fraction of the EM size */ + best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale ); + +#ifdef FT_CONFIG_CHESTER_SMALL_F + if ( best_dist > 64 / 2 ) + best_dist = 64 / 2; +#else + if ( best_dist > 64 / 4 ) + best_dist = 64 / 4; +#endif + + for ( blue = AH_BLUE_CAPITAL_TOP; blue < AH_BLUE_MAX; blue++ ) + { + /* if it is a top zone, check for right edges -- if it is a bottom */ + /* zone, check for left edges */ + /* */ + /* of course, that's for TrueType XXX */ + FT_Bool is_top_blue = + FT_BOOL( AH_IS_TOP_BLUE( blue ) ); + FT_Bool is_major_dir = + FT_BOOL( edge->dir == outline->horz_major_dir ); + + + if ( !blue_active[blue] ) + continue; + + /* if it is a top zone, the edge must be against the major */ + /* direction; if it is a bottom zone, it must be in the major */ + /* direction */ + if ( is_top_blue ^ is_major_dir ) + { + FT_Pos dist; + FT_Pos* blue_pos = globals->blue_refs + blue; + + + /* first of all, compare it to the reference position */ + dist = edge->fpos - *blue_pos; + if ( dist < 0 ) + dist = -dist; + + dist = FT_MulFix( dist, y_scale ); + if ( dist < best_dist ) + { + best_dist = dist; + best_blue = blue_pos; + } + + /* now, compare it to the overshoot position if the edge is */ + /* rounded, and if the edge is over the reference position of a */ + /* top zone, or under the reference position of a bottom zone */ + if ( edge->flags & AH_EDGE_ROUND && dist != 0 ) + { + FT_Bool is_under_ref = FT_BOOL( edge->fpos < *blue_pos ); + + + if ( is_top_blue ^ is_under_ref ) + { + blue_pos = globals->blue_shoots + blue; + dist = edge->fpos - *blue_pos; + if ( dist < 0 ) + dist = -dist; + + dist = FT_MulFix( dist, y_scale ); + if ( dist < best_dist ) + { + best_dist = dist; + best_blue = blue_pos; + } + } + } + } + } + + if ( best_blue ) + edge->blue_edge = best_blue; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ah_outline_scale_blue_edges */ + /* */ + /* <Description> */ + /* This function must be called before hinting in order to re-adjust */ + /* the contents of the detected edges (basically change the `blue */ + /* edge' pointer from `design units' to `scaled ones'). */ + /* */ + FT_LOCAL_DEF( void ) + ah_outline_scale_blue_edges( AH_Outline outline, + AH_Face_Globals globals ) + { + AH_Edge edge = outline->horz_edges; + AH_Edge edge_limit = edge + outline->num_hedges; + FT_Pos delta; + + + delta = globals->scaled.blue_refs - globals->design.blue_refs; + + for ( ; edge < edge_limit; edge++ ) + { + if ( edge->blue_edge ) + edge->blue_edge += delta; + } + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahglyph.h b/Utilities/vtkfreetype/src/autohint/ahglyph.h new file mode 100644 index 0000000..b346cbe --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahglyph.h @@ -0,0 +1,95 @@ +/***************************************************************************/ +/* */ +/* ahglyph.h */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (specification). */ +/* */ +/* Copyright 2000-2001, 2002 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef __AHGLYPH_H__ +#define __AHGLYPH_H__ + + +#include <ft2build.h> +#include "ahtypes.h" + + +FT_BEGIN_HEADER + + + typedef enum AH_UV_ + { + AH_UV_FXY, + AH_UV_FYX, + AH_UV_OXY, + AH_UV_OYX, + AH_UV_OX, + AH_UV_OY, + AH_UV_YX, + AH_UV_XY /* should always be last! */ + + } AH_UV; + + + FT_LOCAL( void ) + ah_setup_uv( AH_Outline outline, + AH_UV source ); + + + /* AH_OutlineRec functions - they should be typically called in this order */ + + FT_LOCAL( FT_Error ) + ah_outline_new( FT_Memory memory, + AH_Outline* aoutline ); + + FT_LOCAL( FT_Error ) + ah_outline_load( AH_Outline outline, + FT_Fixed x_scale, + FT_Fixed y_scale, + FT_Face face ); + + FT_LOCAL( void ) + ah_outline_compute_segments( AH_Outline outline ); + + FT_LOCAL( void ) + ah_outline_link_segments( AH_Outline outline ); + + FT_LOCAL( void ) + ah_outline_detect_features( AH_Outline outline ); + + FT_LOCAL( void ) + ah_outline_compute_blue_edges( AH_Outline outline, + AH_Face_Globals globals ); + + FT_LOCAL( void ) + ah_outline_scale_blue_edges( AH_Outline outline, + AH_Face_Globals globals ); + + FT_LOCAL( void ) + ah_outline_save( AH_Outline outline, + AH_Loader loader ); + + FT_LOCAL( void ) + ah_outline_done( AH_Outline outline ); + + +FT_END_HEADER + +#endif /* __AHGLYPH_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahhint.c b/Utilities/vtkfreetype/src/autohint/ahhint.c new file mode 100644 index 0000000..8e8afea --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahhint.c @@ -0,0 +1,1937 @@ +/***************************************************************************/ +/* */ +/* ahhint.c */ +/* */ +/* Glyph hinter (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "ahhint.h" +#include "ahglyph.h" +#include "ahangles.h" +#include "aherrors.h" +#include FT_OUTLINE_H + + +#define FACE_GLOBALS( face ) ( (AH_Face_Globals)(face)->autohint.data ) + +#define AH_USE_IUP +#define OPTIM_STEM_SNAP + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** Hinting routines ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /* snap a given width in scaled coordinates to one of the */ + /* current standard widths */ + static FT_Pos + ah_snap_width( FT_Pos* widths, + FT_Int count, + FT_Pos width ) + { + int n; + FT_Pos best = 64 + 32 + 2; + FT_Pos reference = width; + FT_Pos scaled; + + + for ( n = 0; n < count; n++ ) + { + FT_Pos w; + FT_Pos dist; + + + w = widths[n]; + dist = width - w; + if ( dist < 0 ) + dist = -dist; + if ( dist < best ) + { + best = dist; + reference = w; + } + } + + scaled = FT_PIX_ROUND( reference ); + + if ( width >= reference ) + { + if ( width < scaled + 48 ) + width = reference; + } + else + { + if ( width > scaled - 48 ) + width = reference; + } + + return width; + } + + + /* compute the snapped width of a given stem */ + +#ifdef FT_CONFIG_CHESTER_SERIF + + static FT_Pos + ah_compute_stem_width( AH_Hinter hinter, + int vertical, + FT_Pos width, + AH_Edge_Flags base_flags, + AH_Edge_Flags stem_flags ) + { + AH_Globals globals = &hinter->globals->scaled; + FT_Pos dist = width; + FT_Int sign = 0; + + + if ( dist < 0 ) + { + dist = -width; + sign = 1; + } + + if ( !hinter->do_stem_adjust ) + { + /* leave stem widths unchanged */ + } + else if ( ( vertical && !hinter->do_vert_snapping ) || + ( !vertical && !hinter->do_horz_snapping ) ) + { + /* smooth hinting process: very lightly quantize the stem width */ + /* */ + + /* leave the widths of serifs alone */ + + if ( ( stem_flags & AH_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) ) + goto Done_Width; + + else if ( ( base_flags & AH_EDGE_ROUND ) ) + { + if ( dist < 80 ) + dist = 64; + } + else if ( dist < 56 ) + dist = 56; + + { + FT_Pos delta = dist - globals->stds[vertical]; + + + if ( delta < 0 ) + delta = -delta; + + if ( delta < 40 ) + { + dist = globals->stds[vertical]; + if ( dist < 48 ) + dist = 48; + + goto Done_Width; + } + + if ( dist < 3 * 64 ) + { + delta = dist & 63; + dist &= -64; + + if ( delta < 10 ) + dist += delta; + + else if ( delta < 32 ) + dist += 10; + + else if ( delta < 54 ) + dist += 54; + + else + dist += delta; + } + else + dist = ( dist + 32 ) & ~63; + } + } + else + { + /* strong hinting process: snap the stem width to integer pixels */ + /* */ + if ( vertical ) + { + dist = ah_snap_width( globals->heights, globals->num_heights, dist ); + + /* in the case of vertical hinting, always round */ + /* the stem heights to integer pixels */ + if ( dist >= 64 ) + dist = ( dist + 16 ) & ~63; + else + dist = 64; + } + else + { + dist = ah_snap_width( globals->widths, globals->num_widths, dist ); + + if ( hinter->flags & AH_HINTER_MONOCHROME ) + { + /* monochrome horizontal hinting: snap widths to integer pixels */ + /* with a different threshold */ + if ( dist < 64 ) + dist = 64; + else + dist = ( dist + 32 ) & ~63; + } + else + { + /* for horizontal anti-aliased hinting, we adopt a more subtle */ + /* approach: we strengthen small stems, round stems whose size */ + /* is between 1 and 2 pixels to an integer, otherwise nothing */ + if ( dist < 48 ) + dist = ( dist + 64 ) >> 1; + + else if ( dist < 128 ) + dist = ( dist + 22 ) & ~63; + else + /* XXX: round otherwise to prevent color fringes in LCD mode */ + dist = ( dist + 32 ) & ~63; + } + } + } + + Done_Width: + if ( sign ) + dist = -dist; + + return dist; + } + +#else /* !FT_CONFIG_CHESTER_SERIF */ + + static FT_Pos + ah_compute_stem_width( AH_Hinter hinter, + int vertical, + FT_Pos width ) + { + AH_Globals globals = &hinter->globals->scaled; + FT_Pos dist = width; + FT_Int sign = 0; + + + if ( dist < 0 ) + { + dist = -width; + sign = 1; + } + + if ( !hinter->do_stem_adjust ) + { + /* leave stem widths unchanged */ + } + else if ( ( vertical && !hinter->do_vert_snapping ) || + ( !vertical && !hinter->do_horz_snapping ) ) + { + /* smooth hinting process: very lightly quantize the stem width */ + /* */ + if ( dist < 64 ) + dist = 64; + + { + FT_Pos delta = dist - globals->stds[vertical]; + + + if ( delta < 0 ) + delta = -delta; + + if ( delta < 40 ) + { + dist = globals->stds[vertical]; + if ( dist < 48 ) + dist = 48; + } + + if ( dist < 3 * 64 ) + { + delta = dist & 63; + dist &= -64; + + if ( delta < 10 ) + dist += delta; + + else if ( delta < 32 ) + dist += 10; + + else if ( delta < 54 ) + dist += 54; + + else + dist += delta; + } + else + dist = ( dist + 32 ) & ~63; + } + } + else + { + /* strong hinting process: snap the stem width to integer pixels */ + /* */ + if ( vertical ) + { + dist = ah_snap_width( globals->heights, globals->num_heights, dist ); + + /* in the case of vertical hinting, always round */ + /* the stem heights to integer pixels */ + if ( dist >= 64 ) + dist = ( dist + 16 ) & ~63; + else + dist = 64; + } + else + { + dist = ah_snap_width( globals->widths, globals->num_widths, dist ); + + if ( hinter->flags & AH_HINTER_MONOCHROME ) + { + /* monochrome horizontal hinting: snap widths to integer pixels */ + /* with a different threshold */ + if ( dist < 64 ) + dist = 64; + else + dist = ( dist + 32 ) & ~63; + } + else + { + /* for horizontal anti-aliased hinting, we adopt a more subtle */ + /* approach: we strengthen small stems, round stems whose size */ + /* is between 1 and 2 pixels to an integer, otherwise nothing */ + if ( dist < 48 ) + dist = ( dist + 64 ) >> 1; + + else if ( dist < 128 ) + dist = ( dist + 22 ) & ~63; + else + /* XXX: round otherwise to prevent color fringes in LCD mode */ + dist = ( dist + 32 ) & ~63; + } + } + } + + if ( sign ) + dist = -dist; + + return dist; + } + +#endif /* !FT_CONFIG_CHESTER_SERIF */ + + + /* align one stem edge relative to the previous stem edge */ + static void + ah_align_linked_edge( AH_Hinter hinter, + AH_Edge base_edge, + AH_Edge stem_edge, + int vertical ) + { + FT_Pos dist = stem_edge->opos - base_edge->opos; + +#ifdef FT_CONFIG_CHESTER_SERIF + + FT_Pos fitted_width = ah_compute_stem_width( hinter, + vertical, + dist, + base_edge->flags, + stem_edge->flags ); + + + stem_edge->pos = base_edge->pos + fitted_width; + +#else + + stem_edge->pos = base_edge->pos + + ah_compute_stem_width( hinter, vertical, dist ); + +#endif + + } + + + static void + ah_align_serif_edge( AH_Hinter hinter, + AH_Edge base, + AH_Edge serif, + int vertical ) + { + FT_Pos dist; + FT_Pos sign = 1; + + FT_UNUSED( hinter ); + FT_UNUSED( vertical ); + + + dist = serif->opos - base->opos; + if ( dist < 0 ) + { + dist = -dist; + sign = -1; + } + +#if 0 + /* do not touch serifs widths! */ + if ( base->flags & AH_EDGE_DONE ) + { + if ( dist >= 64 ) + dist = ( dist + 8 ) & ~63; + + else if ( dist <= 32 && !vertical ) + dist = ( dist + 33 ) >> 1; + + else + dist = 0; + } +#endif + + serif->pos = base->pos + sign * dist; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** E D G E H I N T I N G ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( void ) + ah_hinter_hint_edges( AH_Hinter hinter ) + { + AH_Edge edges; + AH_Edge edge_limit; + AH_Outline outline = hinter->glyph; + FT_Int dimension; + FT_Int n_edges; + + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge edge; + AH_Edge anchor = 0; + int has_serifs = 0; + + + if ( !hinter->do_horz_hints && !dimension ) + goto Next_Dimension; + + if ( !hinter->do_vert_hints && dimension ) + goto Next_Dimension; + + /* we begin by aligning all stems relative to the blue zone */ + /* if needed -- that's only for horizontal edges */ + if ( dimension ) + { + for ( edge = edges; edge < edge_limit; edge++ ) + { + FT_Pos* blue; + AH_EdgeRec *edge1, *edge2; + + + if ( edge->flags & AH_EDGE_DONE ) + continue; + + blue = edge->blue_edge; + edge1 = 0; + edge2 = edge->link; + + if ( blue ) + { + edge1 = edge; + } + else if ( edge2 && edge2->blue_edge ) + { + blue = edge2->blue_edge; + edge1 = edge2; + edge2 = edge; + } + + if ( !edge1 ) + continue; + + edge1->pos = blue[0]; + edge1->flags |= AH_EDGE_DONE; + + if ( edge2 && !edge2->blue_edge ) + { + ah_align_linked_edge( hinter, edge1, edge2, dimension ); + edge2->flags |= AH_EDGE_DONE; + } + + if ( !anchor ) + anchor = edge; + } + } + + /* now we will align all stem edges, trying to maintain the */ + /* relative order of stems in the glyph */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + AH_EdgeRec* edge2; + + + if ( edge->flags & AH_EDGE_DONE ) + continue; + + /* skip all non-stem edges */ + edge2 = edge->link; + if ( !edge2 ) + { + has_serifs++; + continue; + } + + /* now align the stem */ + + /* this should not happen, but it's better to be safe */ + if ( edge2->blue_edge || edge2 < edge ) + { + ah_align_linked_edge( hinter, edge2, edge, dimension ); + edge->flags |= AH_EDGE_DONE; + continue; + } + + if ( !anchor ) + { + +#ifdef FT_CONFIG_CHESTER_STEM + + FT_Pos org_len, org_center, cur_len; + FT_Pos cur_pos1, error1, error2, u_off, d_off; + + + org_len = edge2->opos - edge->opos; + cur_len = ah_compute_stem_width( hinter, dimension, org_len, + edge->flags, edge2->flags ); + + if ( cur_len <= 64 ) + u_off = d_off = 32; + else + { + u_off = 38; + d_off = 26; + } + + if ( cur_len < 96 ) + { + org_center = edge->opos + ( org_len >> 1 ); + + cur_pos1 = FT_PIX_ROUND( org_center ); + + error1 = org_center - ( cur_pos1 - u_off ); + if ( error1 < 0 ) + error1 = -error1; + + error2 = org_center - ( cur_pos1 + d_off ); + if ( error2 < 0 ) + error2 = -error2; + + if ( error1 < error2 ) + cur_pos1 -= u_off; + else + cur_pos1 += d_off; + + edge->pos = cur_pos1 - cur_len / 2; + edge2->pos = cur_pos1 + cur_len / 2; + + } + else + edge->pos = FT_PIX_ROUND( edge->opos ); + + anchor = edge; + + edge->flags |= AH_EDGE_DONE; + + ah_align_linked_edge( hinter, edge, edge2, dimension ); + +#else /* !FT_CONFIG_CHESTER_STEM */ + + edge->pos = FT_PIX_ROUND( edge->opos ); + anchor = edge; + + edge->flags |= AH_EDGE_DONE; + + ah_align_linked_edge( hinter, edge, edge2, dimension ); + +#endif /* !FT_CONFIG_CHESTER_STEM */ + + } + else + { + FT_Pos org_pos, org_len, org_center, cur_len; + FT_Pos cur_pos1, cur_pos2, delta1, delta2; + + + org_pos = anchor->pos + ( edge->opos - anchor->opos ); + org_len = edge2->opos - edge->opos; + org_center = org_pos + ( org_len >> 1 ); + +#ifdef FT_CONFIG_CHESTER_SERIF + + cur_len = ah_compute_stem_width( hinter, dimension, org_len, + edge->flags, edge2->flags ); + + +#else /* !FT_CONFIG_CHESTER_SERIF */ + + cur_len = ah_compute_stem_width( hinter, dimension, org_len ); + +#endif /* !FT_CONFIG_CHESTER_SERIF */ + +#ifdef FT_CONFIG_CHESTER_STEM + + if ( cur_len < 96 ) + { + FT_Pos u_off, d_off; + + + cur_pos1 = FT_PIX_ROUND( org_center ); + + if (cur_len <= 64 ) + u_off = d_off = 32; + else + { + u_off = 38; + d_off = 26; + } + + delta1 = org_center - ( cur_pos1 - u_off ); + if ( delta1 < 0 ) + delta1 = -delta1; + + delta2 = org_center - ( cur_pos1 + d_off ); + if ( delta2 < 0 ) + delta2 = -delta2; + + if ( delta1 < delta2 ) + cur_pos1 -= u_off; + else + cur_pos1 += d_off; + + edge->pos = cur_pos1 - cur_len / 2; + edge2->pos = cur_pos1 + cur_len / 2; + } + else + { + org_pos = anchor->pos + ( edge->opos - anchor->opos ); + org_len = edge2->opos - edge->opos; + org_center = org_pos + ( org_len >> 1 ); + + cur_len = ah_compute_stem_width( hinter, dimension, org_len, + edge->flags, edge2->flags ); + + cur_pos1 = FT_PIX_ROUND( org_pos ); + delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center ); + if ( delta1 < 0 ) + delta1 = -delta1; + + cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len; + delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center ); + if ( delta2 < 0 ) + delta2 = -delta2; + + edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2; + edge2->pos = edge->pos + cur_len; + } + +#else /* !FT_CONFIG_CHESTER_STEM */ + + cur_pos1 = FT_PIX_ROUND( org_pos ); + delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center ); + if ( delta1 < 0 ) + delta1 = -delta1; + + cur_pos2 = FT_PIX_ROUND( org_pos + org_len ) - cur_len; + delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center ); + if ( delta2 < 0 ) + delta2 = -delta2; + + edge->pos = ( delta1 <= delta2 ) ? cur_pos1 : cur_pos2; + edge2->pos = edge->pos + cur_len; + +#endif /* !FT_CONFIG_CHESTER_STEM */ + + edge->flags |= AH_EDGE_DONE; + edge2->flags |= AH_EDGE_DONE; + + if ( edge > edges && edge->pos < edge[-1].pos ) + edge->pos = edge[-1].pos; + } + } + + /* make sure that lowercase m's maintain their symmetry */ + + /* In general, lowercase m's have six vertical edges if they are sans */ + /* serif, or twelve if they are avec serif. This implementation is */ + /* based on that assumption, and seems to work very well with most */ + /* faces. However, if for a certain face this assumption is not */ + /* true, the m is just rendered like before. In addition, any stem */ + /* correction will only be applied to symmetrical glyphs (even if the */ + /* glyph is not an m), so the potential for unwanted distortion is */ + /* relatively low. */ + + /* We don't handle horizontal edges since we can't easily assure that */ + /* the third (lowest) stem aligns with the base line; it might end up */ + /* one pixel higher or lower. */ + + n_edges = (FT_Int)( edge_limit - edges ); + if ( !dimension && ( n_edges == 6 || n_edges == 12 ) ) + { + AH_EdgeRec *edge1, *edge2, *edge3; + FT_Pos dist1, dist2, span, delta; + + + if ( n_edges == 6 ) + { + edge1 = edges; + edge2 = edges + 2; + edge3 = edges + 4; + } + else + { + edge1 = edges + 1; + edge2 = edges + 5; + edge3 = edges + 9; + } + + dist1 = edge2->opos - edge1->opos; + dist2 = edge3->opos - edge2->opos; + + span = dist1 - dist2; + if ( span < 0 ) + span = -span; + + if ( span < 8 ) + { + delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); + edge3->pos -= delta; + if ( edge3->link ) + edge3->link->pos -= delta; + + /* move the serifs along with the stem */ + if ( n_edges == 12 ) + { + ( edges + 8 )->pos -= delta; + ( edges + 11 )->pos -= delta; + } + + edge3->flags |= AH_EDGE_DONE; + if ( edge3->link ) + edge3->link->flags |= AH_EDGE_DONE; + } + } + + if ( !has_serifs ) + goto Next_Dimension; + + /* now hint the remaining edges (serifs and single) in order */ + /* to complete our processing */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + if ( edge->flags & AH_EDGE_DONE ) + continue; + + if ( edge->serif ) + ah_align_serif_edge( hinter, edge->serif, edge, dimension ); + else if ( !anchor ) + { + edge->pos = FT_PIX_ROUND( edge->opos ); + anchor = edge; + } + else + edge->pos = anchor->pos + + FT_PIX_ROUND( edge->opos - anchor->opos ); + + edge->flags |= AH_EDGE_DONE; + + if ( edge > edges && edge->pos < edge[-1].pos ) + edge->pos = edge[-1].pos; + + if ( edge + 1 < edge_limit && + edge[1].flags & AH_EDGE_DONE && + edge->pos > edge[1].pos ) + edge->pos = edge[1].pos; + } + + Next_Dimension: + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** P O I N T H I N T I N G ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + static void + ah_hinter_align_edge_points( AH_Hinter hinter ) + { + AH_Outline outline = hinter->glyph; + AH_Edge edges; + AH_Edge edge_limit; + FT_Int dimension; + + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge edge; + + + edge = edges; + for ( ; edge < edge_limit; edge++ ) + { + /* move the points of each segment */ + /* in each edge to the edge's position */ + AH_Segment seg = edge->first; + + + do + { + AH_Point point = seg->first; + + + for (;;) + { + if ( dimension ) + { + point->y = edge->pos; + point->flags |= AH_FLAG_TOUCH_Y; + } + else + { + point->x = edge->pos; + point->flags |= AH_FLAG_TOUCH_X; + } + + if ( point == seg->last ) + break; + + point = point->next; + } + + seg = seg->edge_next; + + } while ( seg != edge->first ); + } + + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + } + } + + + /* hint the strong points -- this is equivalent to the TrueType `IP' */ + /* hinting instruction */ + static void + ah_hinter_align_strong_points( AH_Hinter hinter ) + { + AH_Outline outline = hinter->glyph; + FT_Int dimension; + AH_Edge edges; + AH_Edge edge_limit; + AH_Point points; + AH_Point point_limit; + AH_Flags touch_flag; + + + points = outline->points; + point_limit = points + outline->num_points; + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + touch_flag = AH_FLAG_TOUCH_Y; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Point point; + AH_Edge edge; + + + if ( edges < edge_limit ) + for ( point = points; point < point_limit; point++ ) + { + FT_Pos u, ou, fu; /* point position */ + FT_Pos delta; + + + if ( point->flags & touch_flag ) + continue; + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + /* if this point is candidate to weak interpolation, we will */ + /* interpolate it after all strong points have been processed */ + if ( ( point->flags & AH_FLAG_WEAK_INTERPOLATION ) && + !( point->flags & AH_FLAG_INFLECTION ) ) + continue; +#endif + + if ( dimension ) + { + u = point->fy; + ou = point->oy; + } + else + { + u = point->fx; + ou = point->ox; + } + + fu = u; + + /* is the point before the first edge? */ + edge = edges; + delta = edge->fpos - u; + if ( delta >= 0 ) + { + u = edge->pos - ( edge->opos - ou ); + goto Store_Point; + } + + /* is the point after the last edge? */ + edge = edge_limit - 1; + delta = u - edge->fpos; + if ( delta >= 0 ) + { + u = edge->pos + ( ou - edge->opos ); + goto Store_Point; + } + +#if 1 + { + FT_UInt min, max, mid; + FT_Pos fpos; + + + /* find enclosing edges */ + min = 0; + max = (FT_UInt)( edge_limit - edges ); + + while ( min < max ) + { + mid = ( max + min ) >> 1; + edge = edges + mid; + fpos = edge->fpos; + + if ( u < fpos ) + max = mid; + else if ( u > fpos ) + min = mid + 1; + else + { + /* we are on the edge */ + u = edge->pos; + goto Store_Point; + } + } + + { + AH_Edge before = edges + min - 1; + AH_Edge after = edges + min + 0; + + + /* assert( before && after && before != after ) */ + if ( before->scale == 0 ) + before->scale = FT_DivFix( after->pos - before->pos, + after->fpos - before->fpos ); + + u = before->pos + FT_MulFix( fu - before->fpos, + before->scale ); + } + } + +#else /* !0 */ + + /* otherwise, interpolate the point in between */ + { + AH_Edge before = 0; + AH_Edge after = 0; + + + for ( edge = edges; edge < edge_limit; edge++ ) + { + if ( u == edge->fpos ) + { + u = edge->pos; + goto Store_Point; + } + if ( u < edge->fpos ) + break; + before = edge; + } + + for ( edge = edge_limit - 1; edge >= edges; edge-- ) + { + if ( u == edge->fpos ) + { + u = edge->pos; + goto Store_Point; + } + if ( u > edge->fpos ) + break; + after = edge; + } + + if ( before->scale == 0 ) + before->scale = FT_DivFix( after->pos - before->pos, + after->fpos - before->fpos ); + + u = before->pos + FT_MulFix( fu - before->fpos, + before->scale ); + } + +#endif /* !0 */ + + Store_Point: + + /* save the point position */ + if ( dimension ) + point->y = u; + else + point->x = u; + + point->flags |= touch_flag; + } + + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + touch_flag = AH_FLAG_TOUCH_X; + } + } + + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + + static void + ah_iup_shift( AH_Point p1, + AH_Point p2, + AH_Point ref ) + { + AH_Point p; + FT_Pos delta = ref->u - ref->v; + + + for ( p = p1; p < ref; p++ ) + p->u = p->v + delta; + + for ( p = ref + 1; p <= p2; p++ ) + p->u = p->v + delta; + } + + + static void + ah_iup_interp( AH_Point p1, + AH_Point p2, + AH_Point ref1, + AH_Point ref2 ) + { + AH_Point p; + FT_Pos u; + FT_Pos v1 = ref1->v; + FT_Pos v2 = ref2->v; + FT_Pos d1 = ref1->u - v1; + FT_Pos d2 = ref2->u - v2; + + + if ( p1 > p2 ) + return; + + if ( v1 == v2 ) + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v1 ) + u += d1; + else + u += d2; + + p->u = u; + } + return; + } + + if ( v1 < v2 ) + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v1 ) + u += d1; + else if ( u >= v2 ) + u += d2; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); + + p->u = u; + } + } + else + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v2 ) + u += d2; + else if ( u >= v1 ) + u += d1; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); + + p->u = u; + } + } + } + + + /* interpolate weak points -- this is equivalent to the TrueType `IUP' */ + /* hinting instruction */ + static void + ah_hinter_align_weak_points( AH_Hinter hinter ) + { + AH_Outline outline = hinter->glyph; + FT_Int dimension; + AH_Point points; + AH_Point point_limit; + AH_Point* contour_limit; + AH_Flags touch_flag; + + + points = outline->points; + point_limit = points + outline->num_points; + + /* PASS 1: Move segment points to edge positions */ + + touch_flag = AH_FLAG_TOUCH_Y; + + contour_limit = outline->contours + outline->num_contours; + + ah_setup_uv( outline, AH_UV_OY ); + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Point point; + AH_Point end_point; + AH_Point first_point; + AH_Point* contour; + + + point = points; + contour = outline->contours; + + for ( ; contour < contour_limit; contour++ ) + { + point = *contour; + end_point = point->prev; + first_point = point; + + while ( point <= end_point && !( point->flags & touch_flag ) ) + point++; + + if ( point <= end_point ) + { + AH_Point first_touched = point; + AH_Point cur_touched = point; + + + point++; + while ( point <= end_point ) + { + if ( point->flags & touch_flag ) + { + /* we found two successive touched points; we interpolate */ + /* all contour points between them */ + ah_iup_interp( cur_touched + 1, point - 1, + cur_touched, point ); + cur_touched = point; + } + point++; + } + + if ( cur_touched == first_touched ) + { + /* this is a special case: only one point was touched in the */ + /* contour; we thus simply shift the whole contour */ + ah_iup_shift( first_point, end_point, cur_touched ); + } + else + { + /* now interpolate after the last touched point to the end */ + /* of the contour */ + ah_iup_interp( cur_touched + 1, end_point, + cur_touched, first_touched ); + + /* if the first contour point isn't touched, interpolate */ + /* from the contour start to the first touched point */ + if ( first_touched > points ) + ah_iup_interp( first_point, first_touched - 1, + cur_touched, first_touched ); + } + } + } + + /* now save the interpolated values back to x/y */ + if ( dimension ) + { + for ( point = points; point < point_limit; point++ ) + point->y = point->u; + + touch_flag = AH_FLAG_TOUCH_X; + ah_setup_uv( outline, AH_UV_OX ); + } + else + { + for ( point = points; point < point_limit; point++ ) + point->x = point->u; + + break; /* exit loop */ + } + } + } + +#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */ + + + FT_LOCAL_DEF( void ) + ah_hinter_align_points( AH_Hinter hinter ) + { + ah_hinter_align_edge_points( hinter ); + +#ifndef AH_OPTION_NO_STRONG_INTERPOLATION + ah_hinter_align_strong_points( hinter ); +#endif + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + ah_hinter_align_weak_points( hinter ); +#endif + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** H I N T E R O B J E C T M E T H O D S ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* scale and fit the global metrics */ + static void + ah_hinter_scale_globals( AH_Hinter hinter, + FT_Fixed x_scale, + FT_Fixed y_scale ) + { + FT_Int n; + AH_Face_Globals globals = hinter->globals; + AH_Globals design = &globals->design; + AH_Globals scaled = &globals->scaled; + + + /* copy content */ + *scaled = *design; + + /* scale the standard widths & heights */ + for ( n = 0; n < design->num_widths; n++ ) + scaled->widths[n] = FT_MulFix( design->widths[n], x_scale ); + + for ( n = 0; n < design->num_heights; n++ ) + scaled->heights[n] = FT_MulFix( design->heights[n], y_scale ); + + scaled->stds[0] = ( design->num_widths > 0 ) ? scaled->widths[0] : 32000; + scaled->stds[1] = ( design->num_heights > 0 ) ? scaled->heights[0] : 32000; + + /* scale the blue zones */ + for ( n = 0; n < AH_BLUE_MAX; n++ ) + { + FT_Pos delta, delta2; + + + delta = design->blue_shoots[n] - design->blue_refs[n]; + delta2 = delta; + if ( delta < 0 ) + delta2 = -delta2; + delta2 = FT_MulFix( delta2, y_scale ); + + if ( delta2 < 32 ) + delta2 = 0; + else if ( delta2 < 64 ) + delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 ); + else + delta2 = FT_PIX_ROUND( delta2 ); + + if ( delta < 0 ) + delta2 = -delta2; + + scaled->blue_refs[n] = + FT_PIX_ROUND( FT_MulFix( design->blue_refs[n], y_scale ) ); + + scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2; + } + + globals->x_scale = x_scale; + globals->y_scale = y_scale; + } + + + static void + ah_hinter_align( AH_Hinter hinter ) + { + ah_hinter_align_edge_points( hinter ); + ah_hinter_align_points( hinter ); + } + + + /* finalize a hinter object */ + FT_LOCAL_DEF( void ) + ah_hinter_done( AH_Hinter hinter ) + { + if ( hinter ) + { + FT_Memory memory = hinter->memory; + + + ah_loader_done( hinter->loader ); + ah_outline_done( hinter->glyph ); + + /* note: the `globals' pointer is _not_ owned by the hinter */ + /* but by the current face object; we don't need to */ + /* release it */ + hinter->globals = 0; + hinter->face = 0; + + FT_FREE( hinter ); + } + } + + + /* create a new empty hinter object */ + FT_LOCAL_DEF( FT_Error ) + ah_hinter_new( FT_Library library, + AH_Hinter *ahinter ) + { + AH_Hinter hinter = 0; + FT_Memory memory = library->memory; + FT_Error error; + + + *ahinter = 0; + + /* allocate object */ + if ( FT_NEW( hinter ) ) + goto Exit; + + hinter->memory = memory; + hinter->flags = 0; + + /* allocate outline and loader */ + error = ah_outline_new( memory, &hinter->glyph ) || + ah_loader_new ( memory, &hinter->loader ) || + ah_loader_create_extra( hinter->loader ); + if ( error ) + goto Exit; + + *ahinter = hinter; + + Exit: + if ( error ) + ah_hinter_done( hinter ); + + return error; + } + + + /* create a face's autohint globals */ + FT_LOCAL_DEF( FT_Error ) + ah_hinter_new_face_globals( AH_Hinter hinter, + FT_Face face, + AH_Globals globals ) + { + FT_Error error; + FT_Memory memory = hinter->memory; + AH_Face_Globals face_globals; + + + if ( FT_NEW( face_globals ) ) + goto Exit; + + hinter->face = face; + hinter->globals = face_globals; + + if ( globals ) + face_globals->design = *globals; + else + ah_hinter_compute_globals( hinter ); + + face->autohint.data = face_globals; + face->autohint.finalizer = (FT_Generic_Finalizer) + ah_hinter_done_face_globals; + face_globals->face = face; + + Exit: + return error; + } + + + /* discard a face's autohint globals */ + FT_LOCAL_DEF( void ) + ah_hinter_done_face_globals( AH_Face_Globals globals ) + { + FT_Face face = globals->face; + FT_Memory memory = face->memory; + + + FT_FREE( globals ); + } + + + static FT_Error + ah_hinter_load( AH_Hinter hinter, + FT_UInt glyph_index, + FT_Int32 load_flags, + FT_UInt depth ) + { + FT_Face face = hinter->face; + FT_GlyphSlot slot = face->glyph; + FT_Slot_Internal internal = slot->internal; + FT_Fixed x_scale = hinter->globals->x_scale; + FT_Fixed y_scale = hinter->globals->y_scale; + FT_Error error; + AH_Outline outline = hinter->glyph; + AH_Loader gloader = hinter->loader; + + + /* load the glyph */ + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if ( error ) + goto Exit; + + /* Set `hinter->transformed' after loading with FT_LOAD_NO_RECURSE. */ + hinter->transformed = internal->glyph_transformed; + + if ( hinter->transformed ) + { + FT_Matrix imatrix; + + + imatrix = internal->glyph_matrix; + hinter->trans_delta = internal->glyph_delta; + hinter->trans_matrix = imatrix; + + FT_Matrix_Invert( &imatrix ); + FT_Vector_Transform( &hinter->trans_delta, &imatrix ); + } + + /* set linear horizontal metrics */ + slot->linearHoriAdvance = slot->metrics.horiAdvance; + slot->linearVertAdvance = slot->metrics.vertAdvance; + + switch ( slot->format ) + { + case FT_GLYPH_FORMAT_OUTLINE: + + /* translate glyph outline if we need to */ + if ( hinter->transformed ) + { + FT_UInt n = slot->outline.n_points; + FT_Vector* point = slot->outline.points; + + + for ( ; n > 0; point++, n-- ) + { + point->x += hinter->trans_delta.x; + point->y += hinter->trans_delta.y; + } + } + + /* copy the outline points in the loader's current */ + /* extra points which is used to keep original glyph coordinates */ + error = ah_loader_check_points( gloader, slot->outline.n_points + 4, + slot->outline.n_contours ); + if ( error ) + goto Exit; + + FT_ARRAY_COPY( gloader->current.extra_points, slot->outline.points, + slot->outline.n_points ); + + FT_ARRAY_COPY( gloader->current.outline.contours, slot->outline.contours, + slot->outline.n_contours ); + + FT_ARRAY_COPY( gloader->current.outline.tags, slot->outline.tags, + slot->outline.n_points ); + + gloader->current.outline.n_points = slot->outline.n_points; + gloader->current.outline.n_contours = slot->outline.n_contours; + + /* compute original horizontal phantom points, ignoring vertical ones */ + hinter->pp1.x = 0; + hinter->pp1.y = 0; + hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale ); + hinter->pp2.y = 0; + + /* be sure to check for spacing glyphs */ + if ( slot->outline.n_points == 0 ) + goto Hint_Metrics; + + /* now load the slot image into the auto-outline and run the */ + /* automatic hinting process */ + error = ah_outline_load( outline, x_scale, y_scale, face ); + if ( error ) + goto Exit; + + /* perform feature detection */ + ah_outline_detect_features( outline ); + + if ( hinter->do_vert_hints ) + { + ah_outline_compute_blue_edges( outline, hinter->globals ); + ah_outline_scale_blue_edges( outline, hinter->globals ); + } + + /* perform alignment control */ + ah_hinter_hint_edges( hinter ); + ah_hinter_align( hinter ); + + /* now save the current outline into the loader's current table */ + ah_outline_save( outline, gloader ); + + /* we now need to hint the metrics according to the change in */ + /* width/positioning that occured during the hinting process */ + if ( outline->num_vedges > 0 ) + { + FT_Pos old_advance, old_rsb, old_lsb, new_lsb, pp1x_uh, pp2x_uh; + AH_Edge edge1 = outline->vert_edges; /* leftmost edge */ + AH_Edge edge2 = edge1 + + outline->num_vedges - 1; /* rightmost edge */ + + + old_advance = hinter->pp2.x; + old_rsb = old_advance - edge2->opos; + old_lsb = edge1->opos; + new_lsb = edge1->pos; + + /* remember unhinted values to later account for rounding errors */ + + pp1x_uh = new_lsb - old_lsb; + pp2x_uh = edge2->pos + old_rsb; + + /* prefer too much space over too little space for very small sizes */ + + if ( old_lsb < 24 ) + pp1x_uh -= 5; + + if ( old_rsb < 24 ) + pp2x_uh += 5; + + hinter->pp1.x = FT_PIX_ROUND( pp1x_uh ); + hinter->pp2.x = FT_PIX_ROUND( pp2x_uh ); + + slot->lsb_delta = hinter->pp1.x - pp1x_uh; + slot->rsb_delta = hinter->pp2.x - pp2x_uh; + +#if 0 + /* try to fix certain bad advance computations */ + if ( hinter->pp2.x + hinter->pp1.x == edge2->pos && old_rsb > 4 ) + hinter->pp2.x += 64; +#endif + } + + else + { + hinter->pp1.x = ( hinter->pp1.x + 32 ) & -64; + hinter->pp2.x = ( hinter->pp2.x + 32 ) & -64; + } + + /* good, we simply add the glyph to our loader's base */ + ah_loader_add( gloader ); + break; + + case FT_GLYPH_FORMAT_COMPOSITE: + { + FT_UInt nn, num_subglyphs = slot->num_subglyphs; + FT_UInt num_base_subgs, start_point; + FT_SubGlyph subglyph; + + + start_point = gloader->base.outline.n_points; + + /* first of all, copy the subglyph descriptors in the glyph loader */ + error = ah_loader_check_subglyphs( gloader, num_subglyphs ); + if ( error ) + goto Exit; + + FT_ARRAY_COPY( gloader->current.subglyphs, slot->subglyphs, + num_subglyphs ); + + gloader->current.num_subglyphs = num_subglyphs; + num_base_subgs = gloader->base.num_subglyphs; + + /* now, read each subglyph independently */ + for ( nn = 0; nn < num_subglyphs; nn++ ) + { + FT_Vector pp1, pp2; + FT_Pos x, y; + FT_UInt num_points, num_new_points, num_base_points; + + + /* gloader.current.subglyphs can change during glyph loading due */ + /* to re-allocation -- we must recompute the current subglyph on */ + /* each iteration */ + subglyph = gloader->base.subglyphs + num_base_subgs + nn; + + pp1 = hinter->pp1; + pp2 = hinter->pp2; + + num_base_points = gloader->base.outline.n_points; + + error = ah_hinter_load( hinter, subglyph->index, + load_flags, depth + 1 ); + if ( error ) + goto Exit; + + /* recompute subglyph pointer */ + subglyph = gloader->base.subglyphs + num_base_subgs + nn; + + if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) + { + pp1 = hinter->pp1; + pp2 = hinter->pp2; + } + else + { + hinter->pp1 = pp1; + hinter->pp2 = pp2; + } + + num_points = gloader->base.outline.n_points; + num_new_points = num_points - num_base_points; + + /* now perform the transform required for this subglyph */ + + if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE | + FT_SUBGLYPH_FLAG_XY_SCALE | + FT_SUBGLYPH_FLAG_2X2 ) ) + { + FT_Vector* cur = gloader->base.outline.points + + num_base_points; + FT_Vector* org = gloader->base.extra_points + + num_base_points; + FT_Vector* limit = cur + num_new_points; + + + for ( ; cur < limit; cur++, org++ ) + { + FT_Vector_Transform( cur, &subglyph->transform ); + FT_Vector_Transform( org, &subglyph->transform ); + } + } + + /* apply offset */ + + if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) ) + { + FT_Int k = subglyph->arg1; + FT_UInt l = subglyph->arg2; + FT_Vector* p1; + FT_Vector* p2; + + + if ( start_point + k >= num_base_points || + l >= (FT_UInt)num_new_points ) + { + error = AH_Err_Invalid_Composite; + goto Exit; + } + + l += num_base_points; + + /* for now, only use the current point coordinates; */ + /* we may consider another approach in the near future */ + p1 = gloader->base.outline.points + start_point + k; + p2 = gloader->base.outline.points + start_point + l; + + x = p1->x - p2->x; + y = p1->y - p2->y; + } + else + { + x = FT_MulFix( subglyph->arg1, x_scale ); + y = FT_MulFix( subglyph->arg2, y_scale ); + + x = FT_PIX_ROUND(x); + y = FT_PIX_ROUND(y); + } + + { + FT_Outline dummy = gloader->base.outline; + + + dummy.points += num_base_points; + dummy.n_points = (short)num_new_points; + + FT_Outline_Translate( &dummy, x, y ); + } + } + } + break; + + default: + /* we don't support other formats (yet?) */ + error = AH_Err_Unimplemented_Feature; + } + + Hint_Metrics: + if ( depth == 0 ) + { + FT_BBox bbox; + + + /* transform the hinted outline if needed */ + if ( hinter->transformed ) + FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix ); + + /* we must translate our final outline by -pp1.x and compute */ + /* the new metrics */ + if ( hinter->pp1.x ) + FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 ); + + FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); + bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); + bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); + bbox.xMax = FT_PIX_CEIL( bbox.xMax ); + bbox.yMax = FT_PIX_CEIL( bbox.yMax ); + + slot->metrics.width = bbox.xMax - bbox.xMin; + slot->metrics.height = bbox.yMax - bbox.yMin; + slot->metrics.horiBearingX = bbox.xMin; + slot->metrics.horiBearingY = bbox.yMax; + + /* for mono-width fonts (like Andale, Courier, etc.) we need */ + /* to keep the original rounded advance width */ + if ( !FT_IS_FIXED_WIDTH( slot->face ) ) + slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x; + else + slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance, + x_scale ); + + slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance ); + + /* now copy outline into glyph slot */ + ah_loader_rewind( slot->internal->loader ); + error = ah_loader_copy_points( slot->internal->loader, gloader ); + if ( error ) + goto Exit; + + slot->outline = slot->internal->loader->base.outline; + slot->format = FT_GLYPH_FORMAT_OUTLINE; + } + +#ifdef DEBUG_HINTER + ah_debug_hinter = hinter; +#endif + + Exit: + return error; + } + + + /* load and hint a given glyph */ + FT_LOCAL_DEF( FT_Error ) + ah_hinter_load_glyph( AH_Hinter hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + FT_Face face = slot->face; + FT_Error error; + FT_Fixed x_scale = size->metrics.x_scale; + FT_Fixed y_scale = size->metrics.y_scale; + AH_Face_Globals face_globals = FACE_GLOBALS( face ); + FT_Render_Mode hint_mode = FT_LOAD_TARGET_MODE( load_flags ); + + + /* first of all, we need to check that we're using the correct face and */ + /* global hints to load the glyph */ + if ( hinter->face != face || hinter->globals != face_globals ) + { + hinter->face = face; + if ( !face_globals ) + { + error = ah_hinter_new_face_globals( hinter, face, 0 ); + if ( error ) + goto Exit; + + } + hinter->globals = FACE_GLOBALS( face ); + face_globals = FACE_GLOBALS( face ); + + } + +#ifdef FT_CONFIG_CHESTER_BLUE_SCALE + + /* try to optimize the y_scale so that the top of non-capital letters + * is aligned on a pixel boundary whenever possible + */ + { + AH_Globals design = &face_globals->design; + FT_Pos shoot = design->blue_shoots[AH_BLUE_SMALL_TOP]; + + + /* the value of 'shoot' will be -1000 if the font doesn't have */ + /* small latin letters; we simply check the sign here... */ + if ( shoot > 0 ) + { + FT_Pos scaled = FT_MulFix( shoot, y_scale ); + FT_Pos fitted = FT_PIX_ROUND( scaled ); + + + if ( scaled != fitted ) + { + /* adjust y_scale + */ + y_scale = FT_MulDiv( y_scale, fitted, scaled ); + + /* adust x_scale + */ + if ( fitted < scaled ) + x_scale -= x_scale / 50; /* x_scale*0.98 with integers */ + } + } + } + +#endif /* FT_CONFIG_CHESTER_BLUE_SCALE */ + + /* now, we must check the current character pixel size to see if we */ + /* need to rescale the global metrics */ + if ( face_globals->x_scale != x_scale || + face_globals->y_scale != y_scale ) + ah_hinter_scale_globals( hinter, x_scale, y_scale ); + + ah_loader_rewind( hinter->loader ); + + /* reset hinting flags according to load flags and current render target */ + hinter->do_horz_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) ); + hinter->do_vert_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) ); + +#ifdef DEBUG_HINTER + hinter->do_horz_hints = !ah_debug_disable_vert; /* not a bug, the meaning */ + hinter->do_vert_hints = !ah_debug_disable_horz; /* of h/v is inverted! */ +#endif + + /* we snap the width of vertical stems for the monochrome and */ + /* horizontal LCD rendering targets only. Corresponds to X snapping. */ + hinter->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || + hint_mode == FT_RENDER_MODE_LCD ); + + /* we snap the width of horizontal stems for the monochrome and */ + /* vertical LCD rendering targets only. Corresponds to Y snapping. */ + hinter->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || + hint_mode == FT_RENDER_MODE_LCD_V ); + + hinter->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); + + load_flags |= FT_LOAD_NO_SCALE + | FT_LOAD_IGNORE_TRANSFORM; + load_flags &= ~FT_LOAD_RENDER; + + error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); + + Exit: + return error; + } + + + /* retrieve a face's autohint globals for client applications */ + FT_LOCAL_DEF( void ) + ah_hinter_get_global_hints( AH_Hinter hinter, + FT_Face face, + void** global_hints, + long* global_len ) + { + AH_Globals globals = 0; + FT_Memory memory = hinter->memory; + FT_Error error; + + + /* allocate new master globals */ + if ( FT_NEW( globals ) ) + goto Fail; + + /* compute face globals if needed */ + if ( !FACE_GLOBALS( face ) ) + { + error = ah_hinter_new_face_globals( hinter, face, 0 ); + if ( error ) + goto Fail; + } + + *globals = FACE_GLOBALS( face )->design; + *global_hints = globals; + *global_len = sizeof( *globals ); + + return; + + Fail: + FT_FREE( globals ); + + *global_hints = 0; + *global_len = 0; + } + + + FT_LOCAL_DEF( void ) + ah_hinter_done_global_hints( AH_Hinter hinter, + void* global_hints ) + { + FT_Memory memory = hinter->memory; + + + FT_FREE( global_hints ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahhint.h b/Utilities/vtkfreetype/src/autohint/ahhint.h new file mode 100644 index 0000000..2c352d0 --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahhint.h @@ -0,0 +1,75 @@ +/***************************************************************************/ +/* */ +/* ahhint.h */ +/* */ +/* Glyph hinter (declaration). */ +/* */ +/* Copyright 2000-2001, 2002 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef __AHHINT_H__ +#define __AHHINT_H__ + + +#include <ft2build.h> +#include "ahglobal.h" + + +FT_BEGIN_HEADER + + +#define AH_HINT_DEFAULT 0 +#define AH_HINT_NO_ALIGNMENT 1 +#define AH_HINT_NO_HORZ_EDGES 0x200000L /* temporary hack */ +#define AH_HINT_NO_VERT_EDGES 0x400000L /* temporary hack */ + + + /* create a new empty hinter object */ + FT_LOCAL( FT_Error ) + ah_hinter_new( FT_Library library, + AH_Hinter* ahinter ); + + /* Load a hinted glyph in the hinter */ + FT_LOCAL( FT_Error ) + ah_hinter_load_glyph( AH_Hinter hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + /* finalize a hinter object */ + FT_LOCAL( void ) + ah_hinter_done( AH_Hinter hinter ); + + FT_LOCAL( void ) + ah_hinter_done_face_globals( AH_Face_Globals globals ); + + FT_LOCAL( void ) + ah_hinter_get_global_hints( AH_Hinter hinter, + FT_Face face, + void** global_hints, + long* global_len ); + + FT_LOCAL( void ) + ah_hinter_done_global_hints( AH_Hinter hinter, + void* global_hints ); + + +FT_END_HEADER + +#endif /* __AHHINT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahloader.h b/Utilities/vtkfreetype/src/autohint/ahloader.h new file mode 100644 index 0000000..c8e42ef --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahloader.h @@ -0,0 +1,61 @@ +/***************************************************************************/ +/* */ +/* ahloader.h */ +/* */ +/* Glyph loader for the auto-hinting module (declaration only). */ +/* */ +/* Copyright 2000-2001, 2002 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This defines the AH_GlyphLoader type; it is simply a typedef to */ + /* FT_GlyphLoader. */ + /* */ + /*************************************************************************/ + + +#ifndef __AHLOADER_H__ +#define __AHLOADER_H__ + + +#include <ft2build.h> + + +FT_BEGIN_HEADER + +#include FT_INTERNAL_GLYPH_LOADER_H + + #define AH_Load FT_GlyphLoad + #define AH_Loader FT_GlyphLoader + + #define ah_loader_new FT_GlyphLoader_New + #define ah_loader_done FT_GlyphLoader_Done + #define ah_loader_reset FT_GlyphLoader_Reset + #define ah_loader_rewind FT_GlyphLoader_Rewind + #define ah_loader_create_extra FT_GlyphLoader_CreateExtra + #define ah_loader_check_points FT_GlyphLoader_CheckPoints + #define ah_loader_check_subglyphs FT_GlyphLoader_CheckSubGlyphs + #define ah_loader_prepare FT_GlyphLoader_Prepare + #define ah_loader_add FT_GlyphLoader_Add + #define ah_loader_copy_points FT_GlyphLoader_CopyPoints + + +FT_END_HEADER + +#endif /* __AHLOADER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahmodule.c b/Utilities/vtkfreetype/src/autohint/ahmodule.c new file mode 100644 index 0000000..03d067b --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahmodule.c @@ -0,0 +1,143 @@ +/***************************************************************************/ +/* */ +/* ahmodule.c */ +/* */ +/* Auto-hinting module implementation (declaration). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_MODULE_H +#include "ahhint.h" + + +#ifdef DEBUG_HINTER + AH_Hinter ah_debug_hinter = NULL; + FT_Bool ah_debug_disable_horz = 0; + FT_Bool ah_debug_disable_vert = 0; +#endif + + typedef struct FT_AutoHinterRec_ + { + FT_ModuleRec root; + AH_Hinter hinter; + + } FT_AutoHinterRec; + + + FT_CALLBACK_DEF( FT_Error ) + ft_autohinter_init( FT_Module module ) /* FT_AutoHinter */ + { + FT_AutoHinter autohinter = (FT_AutoHinter)module; + FT_Error error; + + + error = ah_hinter_new( module->library, &autohinter->hinter ); + +#ifdef DEBUG_HINTER + if ( !error ) + ah_debug_hinter = autohinter->hinter; +#endif + + return error; + } + + + FT_CALLBACK_DEF( void ) + ft_autohinter_done( FT_Module module ) + { + FT_AutoHinter autohinter = (FT_AutoHinter)module; + + + ah_hinter_done( autohinter->hinter ); + +#ifdef DEBUG_HINTER + ah_debug_hinter = NULL; +#endif + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_autohinter_load_glyph( FT_AutoHinter module, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + return ah_hinter_load_glyph( module->hinter, + slot, size, glyph_index, load_flags ); + } + + + FT_CALLBACK_DEF( void ) + ft_autohinter_reset_globals( FT_AutoHinter module, + FT_Face face ) + { + FT_UNUSED( module ); + + if ( face->autohint.data ) + ah_hinter_done_face_globals( (AH_Face_Globals)(face->autohint.data) ); + } + + + FT_CALLBACK_DEF( void ) + ft_autohinter_get_globals( FT_AutoHinter module, + FT_Face face, + void** global_hints, + long* global_len ) + { + ah_hinter_get_global_hints( module->hinter, face, + global_hints, global_len ); + } + + + FT_CALLBACK_DEF( void ) + ft_autohinter_done_globals( FT_AutoHinter module, + void* global_hints ) + { + ah_hinter_done_global_hints( module->hinter, global_hints ); + } + + + FT_CALLBACK_TABLE_DEF + const FT_AutoHinter_ServiceRec ft_autohinter_service = + { + ft_autohinter_reset_globals, + ft_autohinter_get_globals, + ft_autohinter_done_globals, + ft_autohinter_load_glyph + }; + + + FT_CALLBACK_TABLE_DEF + const FT_Module_Class autohint_module_class = + { + FT_MODULE_HINTER, + sizeof ( FT_AutoHinterRec ), + + "autohinter", + 0x10000L, /* version 1.0 of the autohinter */ + 0x20000L, /* requires FreeType 2.0 or above */ + + (const void*) &ft_autohinter_service, + + ft_autohinter_init, + ft_autohinter_done, + 0 /* FT_Module_Requester */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahmodule.h b/Utilities/vtkfreetype/src/autohint/ahmodule.h new file mode 100644 index 0000000..43b1dbe --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahmodule.h @@ -0,0 +1,42 @@ +/***************************************************************************/ +/* */ +/* ahmodule.h */ +/* */ +/* Auto-hinting module (declaration). */ +/* */ +/* Copyright 2000-2001 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef __AHMODULE_H__ +#define __AHMODULE_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_CALLBACK_TABLE + const FT_Module_Class autohint_module_class; + + +FT_END_HEADER + +#endif /* __AHMODULE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/ahtypes.h b/Utilities/vtkfreetype/src/autohint/ahtypes.h new file mode 100644 index 0000000..f2cedd2 --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/ahtypes.h @@ -0,0 +1,527 @@ +/***************************************************************************/ +/* */ +/* ahtypes.h */ +/* */ +/* General types and definitions for the auto-hint module */ +/* (specification only). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef __AHTYPES_H__ +#define __AHTYPES_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H + +#ifdef DEBUG_HINTER +#include <../src/autohint/ahloader.h> +#else +#include "ahloader.h" +#endif + + +#define xxAH_DEBUG + + +#ifdef AH_DEBUG + +#include <stdio.h> +#define AH_LOG( x ) printf ## x + +#else + +#define AH_LOG( x ) do ; while ( 0 ) /* nothing */ + +#endif /* AH_DEBUG */ + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** COMPILE-TIME BUILD OPTIONS ****/ + /**** ****/ + /**** Toggle these configuration macros to experiment with `features' ****/ + /**** of the auto-hinter. ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* If this option is defined, only strong interpolation will be used to */ + /* place the points between edges. Otherwise, `smooth' points are */ + /* detected and later hinted through weak interpolation to correct some */ + /* unpleasant artefacts. */ + /* */ +#undef AH_OPTION_NO_WEAK_INTERPOLATION + + + /*************************************************************************/ + /* */ + /* Undefine this macro if you don't want to hint the metrics. There is */ + /* no reason to do this (at least for non-CJK scripts), except for */ + /* experimentation. */ + /* */ +#undef AH_HINT_METRICS + + + /*************************************************************************/ + /* */ + /* Define this macro if you do not want to insert extra edges at a */ + /* glyph's x and y extremum (if there isn't one already available). */ + /* This helps to reduce a number of artefacts and allows hinting of */ + /* metrics. */ + /* */ +#undef AH_OPTION_NO_EXTREMUM_EDGES + + + /* don't touch for now */ +#define AH_MAX_WIDTHS 12 +#define AH_MAX_HEIGHTS 12 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** TYPE DEFINITIONS ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* see ahangles.h */ + typedef FT_Int AH_Angle; + + + /* hint flags */ +#define AH_FLAG_NONE 0 + + /* bezier control points flags */ +#define AH_FLAG_CONIC 1 +#define AH_FLAG_CUBIC 2 +#define AH_FLAG_CONTROL ( AH_FLAG_CONIC | AH_FLAG_CUBIC ) + + /* extrema flags */ +#define AH_FLAG_EXTREMA_X 4 +#define AH_FLAG_EXTREMA_Y 8 + + /* roundness */ +#define AH_FLAG_ROUND_X 16 +#define AH_FLAG_ROUND_Y 32 + + /* touched */ +#define AH_FLAG_TOUCH_X 64 +#define AH_FLAG_TOUCH_Y 128 + + /* weak interpolation */ +#define AH_FLAG_WEAK_INTERPOLATION 256 +#define AH_FLAG_INFLECTION 512 + + typedef FT_Int AH_Flags; + + + /* edge hint flags */ +#define AH_EDGE_NORMAL 0 +#define AH_EDGE_ROUND 1 +#define AH_EDGE_SERIF 2 +#define AH_EDGE_DONE 4 + + typedef FT_Int AH_Edge_Flags; + + + /* hint directions -- the values are computed so that two vectors are */ + /* in opposite directions iff `dir1+dir2 == 0' */ +#define AH_DIR_NONE 4 +#define AH_DIR_RIGHT 1 +#define AH_DIR_LEFT -1 +#define AH_DIR_UP 2 +#define AH_DIR_DOWN -2 + + typedef FT_Int AH_Direction; + + + typedef struct AH_PointRec_* AH_Point; + typedef struct AH_SegmentRec_* AH_Segment; + typedef struct AH_EdgeRec_* AH_Edge; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* AH_PointRec */ + /* */ + /* <Description> */ + /* A structure used to model an outline point to the AH_OutlineRec */ + /* type. */ + /* */ + /* <Fields> */ + /* flags :: The current point hint flags. */ + /* */ + /* ox, oy :: The current original scaled coordinates. */ + /* */ + /* fx, fy :: The current coordinates in font units. */ + /* */ + /* x, y :: The current hinted coordinates. */ + /* */ + /* u, v :: Point coordinates -- meaning varies with context. */ + /* */ + /* in_dir :: The direction of the inwards vector (prev->point). */ + /* */ + /* out_dir :: The direction of the outwards vector (point->next). */ + /* */ + /* next :: The next point in same contour. */ + /* */ + /* prev :: The previous point in same contour. */ + /* */ + typedef struct AH_PointRec_ + { + AH_Flags flags; /* point flags used by hinter */ + FT_Pos ox, oy; + FT_Pos fx, fy; + FT_Pos x, y; + FT_Pos u, v; + + AH_Direction in_dir; /* direction of inwards vector */ + AH_Direction out_dir; /* direction of outwards vector */ + + AH_Point next; /* next point in contour */ + AH_Point prev; /* previous point in contour */ + + } AH_PointRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* AH_SegmentRec */ + /* */ + /* <Description> */ + /* A structure used to describe an edge segment to the auto-hinter. */ + /* A segment is simply a sequence of successive points located on the */ + /* same horizontal or vertical `position', in a given direction. */ + /* */ + /* <Fields> */ + /* flags :: The segment edge flags (straight, rounded, etc.). */ + /* */ + /* dir :: The segment direction. */ + /* */ + /* min_coord :: The minimum coordinate of the segment. */ + /* */ + /* max_coord :: The maximum coordinate of the segment. */ + /* */ + /* edge :: The edge of the current segment. */ + /* */ + /* edge_next :: The next segment on the same edge. */ + /* */ + /* link :: The pairing segment for this edge. */ + /* */ + /* serif :: The primary segment for serifs. */ + /* */ + /* num_linked :: The number of other segments that link to this one. */ + /* */ + /* score :: Used to score the segment when selecting them. */ + /* */ + /* first :: The first point in the segment. */ + /* */ + /* last :: The last point in the segment. */ + /* */ + /* contour :: A pointer to the first point of the segment's */ + /* contour. */ + /* */ + typedef struct AH_SegmentRec_ + { + AH_Edge_Flags flags; + AH_Direction dir; + FT_Pos pos; /* position of segment */ + FT_Pos min_coord; /* minimum coordinate of segment */ + FT_Pos max_coord; /* maximum coordinate of segment */ + + AH_Edge edge; + AH_Segment edge_next; + + AH_Segment link; /* link segment */ + AH_Segment serif; /* primary segment for serifs */ + FT_Pos num_linked; /* number of linked segments */ + FT_Pos score; + + AH_Point first; /* first point in edge segment */ + AH_Point last; /* last point in edge segment */ + AH_Point* contour; /* ptr to first point of segment's contour */ + + } AH_SegmentRec; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* AH_EdgeRec */ + /* */ + /* <Description> */ + /* A structure used to describe an edge, which really is a horizontal */ + /* or vertical coordinate to be hinted depending on the segments */ + /* located on it. */ + /* */ + /* <Fields> */ + /* fpos :: The original edge position in font units. */ + /* */ + /* opos :: The original scaled edge position. */ + /* */ + /* pos :: The hinted edge position. */ + /* */ + /* flags :: The segment edge flags (straight, rounded, etc.). */ + /* */ + /* dir :: The main segment direction on this edge. */ + /* */ + /* scale :: Scaling factor between original and hinted edge */ + /* positions. */ + /* */ + /* blue_edge :: Indicate the blue zone edge this edge is related to. */ + /* Only set for some of the horizontal edges in a latin */ + /* font. */ + /* */ + /* link :: The linked edge. */ + /* */ + /* serif :: The serif edge. */ + /* */ + /* num_linked :: The number of other edges that pair to this one. */ + /* */ + /* score :: Used to score the edge when selecting them. */ + /* */ + /* first :: The first edge segment. */ + /* */ + /* last :: The last edge segment. */ + /* */ + typedef struct AH_EdgeRec_ + { + FT_Pos fpos; + FT_Pos opos; + FT_Pos pos; + + AH_Edge_Flags flags; + AH_Direction dir; + FT_Fixed scale; + FT_Pos* blue_edge; + + AH_Edge link; + AH_Edge serif; + FT_Int num_linked; + + FT_Int score; + + AH_Segment first; + AH_Segment last; + + + } AH_EdgeRec; + + + /* an outline as seen by the hinter */ + typedef struct AH_OutlineRec_ + { + FT_Memory memory; + + AH_Direction vert_major_dir; /* vertical major direction */ + AH_Direction horz_major_dir; /* horizontal major direction */ + + FT_Fixed x_scale; + FT_Fixed y_scale; + FT_Pos edge_distance_threshold; + + FT_Int max_points; + FT_Int num_points; + AH_Point points; + + FT_Int max_contours; + FT_Int num_contours; + AH_Point* contours; + + FT_Int num_hedges; + AH_Edge horz_edges; + + FT_Int num_vedges; + AH_Edge vert_edges; + + FT_Int num_hsegments; + AH_Segment horz_segments; + + FT_Int num_vsegments; + AH_Segment vert_segments; + + } AH_OutlineRec, *AH_Outline; + + +#ifdef FT_CONFIG_CHESTER_SMALL_F + +#define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */ +#define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */ +#define AH_BLUE_SMALL_F_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* fijkdbh */ +#define AH_BLUE_SMALL_TOP ( AH_BLUE_SMALL_F_TOP + 1 ) /* xzroesc */ +#define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */ +#define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */ +#define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 ) + +#else /* !FT_CONFIG_CHESTER_SMALL_F */ + +#define AH_BLUE_CAPITAL_TOP 0 /* THEZOCQS */ +#define AH_BLUE_CAPITAL_BOTTOM ( AH_BLUE_CAPITAL_TOP + 1 ) /* HEZLOCUS */ +#define AH_BLUE_SMALL_TOP ( AH_BLUE_CAPITAL_BOTTOM + 1 ) /* xzroesc */ +#define AH_BLUE_SMALL_BOTTOM ( AH_BLUE_SMALL_TOP + 1 ) /* xzroesc */ +#define AH_BLUE_SMALL_MINOR ( AH_BLUE_SMALL_BOTTOM + 1 ) /* pqgjy */ +#define AH_BLUE_MAX ( AH_BLUE_SMALL_MINOR + 1 ) + +#endif /* !FT_CONFIG_CHESTER_SMALL_F */ + + typedef FT_Int AH_Blue; + + +#define AH_HINTER_MONOCHROME 1 +#define AH_HINTER_OPTIMIZE 2 + + typedef FT_Int AH_Hinter_Flags; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* AH_GlobalsRec */ + /* */ + /* <Description> */ + /* Holds the global metrics for a given font face (be it in design */ + /* units or scaled pixel values). */ + /* */ + /* <Fields> */ + /* num_widths :: The number of widths. */ + /* */ + /* num_heights :: The number of heights. */ + /* */ + /* stds :: A two-element array giving the default stem width */ + /* and height. */ + /* */ + /* widths :: Snap widths, including standard one. */ + /* */ + /* heights :: Snap height, including standard one. */ + /* */ + /* blue_refs :: The reference positions of blue zones. */ + /* */ + /* blue_shoots :: The overshoot positions of blue zones. */ + /* */ + typedef struct AH_GlobalsRec_ + { + FT_Int num_widths; + FT_Int num_heights; + + FT_Pos stds[2]; + + FT_Pos widths [AH_MAX_WIDTHS]; + FT_Pos heights[AH_MAX_HEIGHTS]; + + FT_Pos blue_refs [AH_BLUE_MAX]; + FT_Pos blue_shoots[AH_BLUE_MAX]; + + } AH_GlobalsRec, *AH_Globals; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* AH_Face_GlobalsRec */ + /* */ + /* <Description> */ + /* Holds the complete global metrics for a given font face (i.e., the */ + /* design units version + a scaled version + the current scales */ + /* used). */ + /* */ + /* <Fields> */ + /* face :: A handle to the source face object */ + /* */ + /* design :: The globals in font design units. */ + /* */ + /* scaled :: Scaled globals in sub-pixel values. */ + /* */ + /* x_scale :: The current horizontal scale. */ + /* */ + /* y_scale :: The current vertical scale. */ + /* */ + /* control_overshoot :: */ + /* Currently unused. */ + /* */ + typedef struct AH_Face_GlobalsRec_ + { + FT_Face face; + AH_GlobalsRec design; + AH_GlobalsRec scaled; + FT_Fixed x_scale; + FT_Fixed y_scale; + FT_Bool control_overshoot; + + } AH_Face_GlobalsRec, *AH_Face_Globals; + + + typedef struct AH_HinterRec_ + { + FT_Memory memory; + AH_Hinter_Flags flags; + + FT_Int algorithm; + FT_Face face; + + AH_Face_Globals globals; + + AH_Outline glyph; + + AH_Loader loader; + FT_Vector pp1; /* horizontal phantom points */ + FT_Vector pp2; + /* we ignore vertical phantom points */ + + FT_Bool transformed; + FT_Vector trans_delta; + FT_Matrix trans_matrix; + + FT_Bool do_horz_hints; /* disable X hinting */ + FT_Bool do_vert_hints; /* disable Y hinting */ + FT_Bool do_horz_snapping; /* disable X stem size snapping */ + FT_Bool do_vert_snapping; /* disable Y stem size snapping */ + FT_Bool do_stem_adjust; /* disable light stem snapping */ + + } AH_HinterRec, *AH_Hinter; + + +#ifdef DEBUG_HINTER + extern AH_Hinter ah_debug_hinter; + extern FT_Bool ah_debug_disable_horz; + extern FT_Bool ah_debug_disable_vert; +#else +#define ah_debug_disable_horz 0 +#define ah_debug_disable_vert 0 +#endif /* DEBUG_HINTER */ + + +FT_END_HEADER + +#endif /* __AHTYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/autohint/autohint.c b/Utilities/vtkfreetype/src/autohint/autohint.c new file mode 100644 index 0000000..3783a82 --- /dev/null +++ b/Utilities/vtkfreetype/src/autohint/autohint.c @@ -0,0 +1,32 @@ +/***************************************************************************/ +/* */ +/* autohint.c */ +/* */ +/* Automatic Hinting wrapper (body only). */ +/* */ +/* Copyright 2000-2001 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "ahangles.c" +#include "ahglyph.c" +#include "ahglobal.c" +#include "ahhint.c" +#include "ahmodule.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftapi.c b/Utilities/vtkfreetype/src/base/ftapi.c new file mode 100644 index 0000000..1ef3005 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftapi.c @@ -0,0 +1,121 @@ +/***************************************************************************/ +/* */ +/* ftapi.c */ +/* */ +/* The FreeType compatibility functions (body). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_LIST_H +#include FT_OUTLINE_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_TABLES_H +#include FT_OUTLINE_H + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** C O M P A T I B I L I T Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* backwards compatibility API */ + + FT_BASE_DEF( void ) + FT_New_Memory_Stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream stream ) + { + FT_UNUSED( library ); + + FT_Stream_OpenMemory( stream, base, size ); + } + + + FT_BASE_DEF( FT_Error ) + FT_Seek_Stream( FT_Stream stream, + FT_ULong pos ) + { + return FT_Stream_Seek( stream, pos ); + } + + + FT_BASE_DEF( FT_Error ) + FT_Skip_Stream( FT_Stream stream, + FT_Long distance ) + { + return FT_Stream_Skip( stream, distance ); + } + + + FT_BASE_DEF( FT_Error ) + FT_Read_Stream( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ) + { + return FT_Stream_Read( stream, buffer, count ); + } + + + FT_BASE_DEF( FT_Error ) + FT_Read_Stream_At( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ) + { + return FT_Stream_ReadAt( stream, pos, buffer, count ); + } + + + FT_BASE_DEF( FT_Error ) + FT_Extract_Frame( FT_Stream stream, + FT_ULong count, + FT_Byte** pbytes ) + { + return FT_Stream_ExtractFrame( stream, count, pbytes ); + } + + + FT_BASE_DEF( void ) + FT_Release_Frame( FT_Stream stream, + FT_Byte** pbytes ) + { + FT_Stream_ReleaseFrame( stream, pbytes ); + } + + FT_BASE_DEF( FT_Error ) + FT_Access_Frame( FT_Stream stream, + FT_ULong count ) + { + return FT_Stream_EnterFrame( stream, count ); + } + + + FT_BASE_DEF( void ) + FT_Forget_Frame( FT_Stream stream ) + { + FT_Stream_ExitFrame( stream ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftbase.c b/Utilities/vtkfreetype/src/base/ftbase.c new file mode 100644 index 0000000..7d5a7fd --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftbase.c @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* ftbase.c */ +/* */ +/* Single object library component (body only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include "ftutil.c" +#include "ftdbgmem.c" +#include "ftstream.c" +#include "ftcalc.c" +#include "fttrigon.c" +#include "ftoutln.c" +#include "ftgloadr.c" +#include "ftobjs.c" +#include "ftnames.c" +#include "ftrfork.c" + +#if defined( __APPLE__ ) && !defined ( DARWIN_NO_CARBON ) +#include "ftmac.c" +#endif + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftbbox.c b/Utilities/vtkfreetype/src/base/ftbbox.c new file mode 100644 index 0000000..8886995 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftbbox.c @@ -0,0 +1,659 @@ +/***************************************************************************/ +/* */ +/* ftbbox.c */ +/* */ +/* FreeType bbox computation (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component has a _single_ role: to compute exact outline bounding */ + /* boxes. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_BBOX_H +#include FT_IMAGE_H +#include FT_OUTLINE_H +#include FT_INTERNAL_CALC_H + + + typedef struct TBBox_Rec_ + { + FT_Vector last; + FT_BBox bbox; + + } TBBox_Rec; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* BBox_Move_To */ + /* */ + /* <Description> */ + /* This function is used as a `move_to' and `line_to' emitter during */ + /* FT_Outline_Decompose(). It simply records the destination point */ + /* in `user->last'; no further computations are necessary since we */ + /* use the cbox as the starting bbox which must be refined. */ + /* */ + /* <Input> */ + /* to :: A pointer to the destination vector. */ + /* */ + /* <InOut> */ + /* user :: A pointer to the current walk context. */ + /* */ + /* <Return> */ + /* Always 0. Needed for the interface only. */ + /* */ + static int + BBox_Move_To( FT_Vector* to, + TBBox_Rec* user ) + { + user->last = *to; + + return 0; + } + + +#define CHECK_X( p, bbox ) \ + ( p->x < bbox.xMin || p->x > bbox.xMax ) + +#define CHECK_Y( p, bbox ) \ + ( p->y < bbox.yMin || p->y > bbox.yMax ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* BBox_Conic_Check */ + /* */ + /* <Description> */ + /* Finds the extrema of a 1-dimensional conic Bezier curve and update */ + /* a bounding range. This version uses direct computation, as it */ + /* doesn't need square roots. */ + /* */ + /* <Input> */ + /* y1 :: The start coordinate. */ + /* */ + /* y2 :: The coordinate of the control point. */ + /* */ + /* y3 :: The end coordinate. */ + /* */ + /* <InOut> */ + /* min :: The address of the current minimum. */ + /* */ + /* max :: The address of the current maximum. */ + /* */ + static void + BBox_Conic_Check( FT_Pos y1, + FT_Pos y2, + FT_Pos y3, + FT_Pos* min, + FT_Pos* max ) + { + if ( y1 <= y3 && y2 == y1 ) /* flat arc */ + goto Suite; + + if ( y1 < y3 ) + { + if ( y2 >= y1 && y2 <= y3 ) /* ascending arc */ + goto Suite; + } + else + { + if ( y2 >= y3 && y2 <= y1 ) /* descending arc */ + { + y2 = y1; + y1 = y3; + y3 = y2; + goto Suite; + } + } + + y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 ); + + Suite: + if ( y1 < *min ) *min = y1; + if ( y3 > *max ) *max = y3; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* BBox_Conic_To */ + /* */ + /* <Description> */ + /* This function is used as a `conic_to' emitter during */ + /* FT_Raster_Decompose(). It checks a conic Bezier curve with the */ + /* current bounding box, and computes its extrema if necessary to */ + /* update it. */ + /* */ + /* <Input> */ + /* control :: A pointer to a control point. */ + /* */ + /* to :: A pointer to the destination vector. */ + /* */ + /* <InOut> */ + /* user :: The address of the current walk context. */ + /* */ + /* <Return> */ + /* Always 0. Needed for the interface only. */ + /* */ + /* <Note> */ + /* In the case of a non-monotonous arc, we compute directly the */ + /* extremum coordinates, as it is sufficiently fast. */ + /* */ + static int + BBox_Conic_To( FT_Vector* control, + FT_Vector* to, + TBBox_Rec* user ) + { + /* we don't need to check `to' since it is always an `on' point, thus */ + /* within the bbox */ + + if ( CHECK_X( control, user->bbox ) ) + BBox_Conic_Check( user->last.x, + control->x, + to->x, + &user->bbox.xMin, + &user->bbox.xMax ); + + if ( CHECK_Y( control, user->bbox ) ) + BBox_Conic_Check( user->last.y, + control->y, + to->y, + &user->bbox.yMin, + &user->bbox.yMax ); + + user->last = *to; + + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* BBox_Cubic_Check */ + /* */ + /* <Description> */ + /* Finds the extrema of a 1-dimensional cubic Bezier curve and */ + /* updates a bounding range. This version uses splitting because we */ + /* don't want to use square roots and extra accuracy. */ + /* */ + /* <Input> */ + /* p1 :: The start coordinate. */ + /* */ + /* p2 :: The coordinate of the first control point. */ + /* */ + /* p3 :: The coordinate of the second control point. */ + /* */ + /* p4 :: The end coordinate. */ + /* */ + /* <InOut> */ + /* min :: The address of the current minimum. */ + /* */ + /* max :: The address of the current maximum. */ + /* */ + +#if 0 + + static void + BBox_Cubic_Check( FT_Pos p1, + FT_Pos p2, + FT_Pos p3, + FT_Pos p4, + FT_Pos* min, + FT_Pos* max ) + { + FT_Pos stack[32*3 + 1], *arc; + + + arc = stack; + + arc[0] = p1; + arc[1] = p2; + arc[2] = p3; + arc[3] = p4; + + do + { + FT_Pos y1 = arc[0]; + FT_Pos y2 = arc[1]; + FT_Pos y3 = arc[2]; + FT_Pos y4 = arc[3]; + + + if ( y1 == y4 ) + { + if ( y1 == y2 && y1 == y3 ) /* flat */ + goto Test; + } + else if ( y1 < y4 ) + { + if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */ + goto Test; + } + else + { + if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */ + { + y2 = y1; + y1 = y4; + y4 = y2; + goto Test; + } + } + + /* unknown direction -- split the arc in two */ + arc[6] = y4; + arc[1] = y1 = ( y1 + y2 ) / 2; + arc[5] = y4 = ( y4 + y3 ) / 2; + y2 = ( y2 + y3 ) / 2; + arc[2] = y1 = ( y1 + y2 ) / 2; + arc[4] = y4 = ( y4 + y2 ) / 2; + arc[3] = ( y1 + y4 ) / 2; + + arc += 3; + goto Suite; + + Test: + if ( y1 < *min ) *min = y1; + if ( y4 > *max ) *max = y4; + arc -= 3; + + Suite: + ; + } while ( arc >= stack ); + } + +#else + + static void + test_cubic_extrema( FT_Pos y1, + FT_Pos y2, + FT_Pos y3, + FT_Pos y4, + FT_Fixed u, + FT_Pos* min, + FT_Pos* max ) + { + /* FT_Pos a = y4 - 3*y3 + 3*y2 - y1; */ + FT_Pos b = y3 - 2*y2 + y1; + FT_Pos c = y2 - y1; + FT_Pos d = y1; + FT_Pos y; + FT_Fixed uu; + + FT_UNUSED ( y4 ); + + + /* The polynom is */ + /* */ + /* P(x) = a*x^3 + 3b*x^2 + 3c*x + d , */ + /* */ + /* dP/dx = 3a*x^2 + 6b*x + 3c . */ + /* */ + /* However, we also have */ + /* */ + /* dP/dx(u) = 0 , */ + /* */ + /* which implies by subtraction that */ + /* */ + /* P(u) = b*u^2 + 2c*u + d . */ + + if ( u > 0 && u < 0x10000L ) + { + uu = FT_MulFix( u, u ); + y = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu ); + + if ( y < *min ) *min = y; + if ( y > *max ) *max = y; + } + } + + + static void + BBox_Cubic_Check( FT_Pos y1, + FT_Pos y2, + FT_Pos y3, + FT_Pos y4, + FT_Pos* min, + FT_Pos* max ) + { + /* always compare first and last points */ + if ( y1 < *min ) *min = y1; + else if ( y1 > *max ) *max = y1; + + if ( y4 < *min ) *min = y4; + else if ( y4 > *max ) *max = y4; + + /* now, try to see if there are split points here */ + if ( y1 <= y4 ) + { + /* flat or ascending arc test */ + if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 ) + return; + } + else /* y1 > y4 */ + { + /* descending arc test */ + if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 ) + return; + } + + /* There are some split points. Find them. */ + { + FT_Pos a = y4 - 3*y3 + 3*y2 - y1; + FT_Pos b = y3 - 2*y2 + y1; + FT_Pos c = y2 - y1; + FT_Pos d; + FT_Fixed t; + + + /* We need to solve `ax^2+2bx+c' here, without floating points! */ + /* The trick is to normalize to a different representation in order */ + /* to use our 16.16 fixed point routines. */ + /* */ + /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */ + /* These values must fit into a single 16.16 value. */ + /* */ + /* We normalize a, b, and c to `8.16' fixed float values to ensure */ + /* that its product is held in a `16.16' value. */ + + { + FT_ULong t1, t2; + int shift = 0; + + + /* The following computation is based on the fact that for */ + /* any value `y', if `n' is the position of the most */ + /* significant bit of `abs(y)' (starting from 0 for the */ + /* least significant bit), then `y' is in the range */ + /* */ + /* -2^n..2^n-1 */ + /* */ + /* We want to shift `a', `b', and `c' concurrently in order */ + /* to ensure that they all fit in 8.16 values, which maps */ + /* to the integer range `-2^23..2^23-1'. */ + /* */ + /* Necessarily, we need to shift `a', `b', and `c' so that */ + /* the most significant bit of its absolute values is at */ + /* _most_ at position 23. */ + /* */ + /* We begin by computing `t1' as the bitwise `OR' of the */ + /* absolute values of `a', `b', `c'. */ + + t1 = (FT_ULong)( ( a >= 0 ) ? a : -a ); + t2 = (FT_ULong)( ( b >= 0 ) ? b : -b ); + t1 |= t2; + t2 = (FT_ULong)( ( c >= 0 ) ? c : -c ); + t1 |= t2; + + /* Now we can be sure that the most significant bit of `t1' */ + /* is the most significant bit of either `a', `b', or `c', */ + /* depending on the greatest integer range of the particular */ + /* variable. */ + /* */ + /* Next, we compute the `shift', by shifting `t1' as many */ + /* times as necessary to move its MSB to position 23. This */ + /* corresponds to a value of `t1' that is in the range */ + /* 0x40_0000..0x7F_FFFF. */ + /* */ + /* Finally, we shift `a', `b', and `c' by the same amount. */ + /* This ensures that all values are now in the range */ + /* -2^23..2^23, i.e., they are now expressed as 8.16 */ + /* fixed-float numbers. This also means that we are using */ + /* 24 bits of precision to compute the zeros, independently */ + /* of the range of the original polynomial coefficients. */ + /* */ + /* This algorithm should ensure reasonably accurate values */ + /* for the zeros. Note that they are only expressed with */ + /* 16 bits when computing the extrema (the zeros need to */ + /* be in 0..1 exclusive to be considered part of the arc). */ + + if ( t1 == 0 ) /* all coefficients are 0! */ + return; + + if ( t1 > 0x7FFFFFUL ) + { + do + { + shift++; + t1 >>= 1; + + } while ( t1 > 0x7FFFFFUL ); + + /* this loses some bits of precision, but we use 24 of them */ + /* for the computation anyway */ + a >>= shift; + b >>= shift; + c >>= shift; + } + else if ( t1 < 0x400000UL ) + { + do + { + shift++; + t1 <<= 1; + + } while ( t1 < 0x400000UL ); + + a <<= shift; + b <<= shift; + c <<= shift; + } + } + + /* handle a == 0 */ + if ( a == 0 ) + { + if ( b != 0 ) + { + t = - FT_DivFix( c, b ) / 2; + test_cubic_extrema( y1, y2, y3, y4, t, min, max ); + } + } + else + { + /* solve the equation now */ + d = FT_MulFix( b, b ) - FT_MulFix( a, c ); + if ( d < 0 ) + return; + + if ( d == 0 ) + { + /* there is a single split point at -b/a */ + t = - FT_DivFix( b, a ); + test_cubic_extrema( y1, y2, y3, y4, t, min, max ); + } + else + { + /* there are two solutions; we need to filter them */ + d = FT_SqrtFixed( (FT_Int32)d ); + t = - FT_DivFix( b - d, a ); + test_cubic_extrema( y1, y2, y3, y4, t, min, max ); + + t = - FT_DivFix( b + d, a ); + test_cubic_extrema( y1, y2, y3, y4, t, min, max ); + } + } + } + } + +#endif + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* BBox_Cubic_To */ + /* */ + /* <Description> */ + /* This function is used as a `cubic_to' emitter during */ + /* FT_Raster_Decompose(). It checks a cubic Bezier curve with the */ + /* current bounding box, and computes its extrema if necessary to */ + /* update it. */ + /* */ + /* <Input> */ + /* control1 :: A pointer to the first control point. */ + /* */ + /* control2 :: A pointer to the second control point. */ + /* */ + /* to :: A pointer to the destination vector. */ + /* */ + /* <InOut> */ + /* user :: The address of the current walk context. */ + /* */ + /* <Return> */ + /* Always 0. Needed for the interface only. */ + /* */ + /* <Note> */ + /* In the case of a non-monotonous arc, we don't compute directly */ + /* extremum coordinates, we subdivide instead. */ + /* */ + static int + BBox_Cubic_To( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + TBBox_Rec* user ) + { + /* we don't need to check `to' since it is always an `on' point, thus */ + /* within the bbox */ + + if ( CHECK_X( control1, user->bbox ) || + CHECK_X( control2, user->bbox ) ) + BBox_Cubic_Check( user->last.x, + control1->x, + control2->x, + to->x, + &user->bbox.xMin, + &user->bbox.xMax ); + + if ( CHECK_Y( control1, user->bbox ) || + CHECK_Y( control2, user->bbox ) ) + BBox_Cubic_Check( user->last.y, + control1->y, + control2->y, + to->y, + &user->bbox.yMin, + &user->bbox.yMax ); + + user->last = *to; + + return 0; + } + + + /* documentation is in ftbbox.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Get_BBox( FT_Outline* outline, + FT_BBox *abbox ) + { + FT_BBox cbox; + FT_BBox bbox; + FT_Vector* vec; + FT_UShort n; + + + if ( !abbox ) + return FT_Err_Invalid_Argument; + + if ( !outline ) + return FT_Err_Invalid_Outline; + + /* if outline is empty, return (0,0,0,0) */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + { + abbox->xMin = abbox->xMax = 0; + abbox->yMin = abbox->yMax = 0; + return 0; + } + + /* We compute the control box as well as the bounding box of */ + /* all `on' points in the outline. Then, if the two boxes */ + /* coincide, we exit immediately. */ + + vec = outline->points; + bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x; + bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y; + vec++; + + for ( n = 1; n < outline->n_points; n++ ) + { + FT_Pos x = vec->x; + FT_Pos y = vec->y; + + + /* update control box */ + if ( x < cbox.xMin ) cbox.xMin = x; + if ( x > cbox.xMax ) cbox.xMax = x; + + if ( y < cbox.yMin ) cbox.yMin = y; + if ( y > cbox.yMax ) cbox.yMax = y; + + if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON ) + { + /* update bbox for `on' points only */ + if ( x < bbox.xMin ) bbox.xMin = x; + if ( x > bbox.xMax ) bbox.xMax = x; + + if ( y < bbox.yMin ) bbox.yMin = y; + if ( y > bbox.yMax ) bbox.yMax = y; + } + + vec++; + } + + /* test two boxes for equality */ + if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax || + cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax ) + { + /* the two boxes are different, now walk over the outline to */ + /* get the Bezier arc extrema. */ + + static const FT_Outline_Funcs bbox_interface = + { + (FT_Outline_MoveTo_Func) BBox_Move_To, + (FT_Outline_LineTo_Func) BBox_Move_To, + (FT_Outline_ConicTo_Func)BBox_Conic_To, + (FT_Outline_CubicTo_Func)BBox_Cubic_To, + 0, 0 + }; + + FT_Error error; + TBBox_Rec user; + + + user.bbox = bbox; + + error = FT_Outline_Decompose( outline, &bbox_interface, &user ); + if ( error ) + return error; + + *abbox = user.bbox; + } + else + *abbox = bbox; + + return FT_Err_Ok; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftbdf.c b/Utilities/vtkfreetype/src/base/ftbdf.c new file mode 100644 index 0000000..d2f133d --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftbdf.c @@ -0,0 +1,84 @@ +/***************************************************************************/ +/* */ +/* ftbdf.c */ +/* */ +/* FreeType API for accessing BDF-specific strings (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_SERVICE_BDF_H + + + FT_EXPORT_DEF( FT_Error ) + FT_Get_BDF_Charset_ID( FT_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ) + { + FT_Error error; + const char* encoding = NULL; + const char* registry = NULL; + + + error = FT_Err_Invalid_Argument; + + if ( face ) + { + FT_Service_BDF service; + + + FT_FACE_FIND_SERVICE( face, service, BDF ); + + if ( service && service->get_charset_id ) + error = service->get_charset_id( face, &encoding, ®istry ); + } + + if ( acharset_encoding ) + *acharset_encoding = encoding; + + if ( acharset_registry ) + *acharset_registry = registry; + + return error; + } + + + FT_EXPORT( FT_Error ) + FT_Get_BDF_Property( FT_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ) + { + FT_Error error; + + + error = FT_Err_Invalid_Argument; + + aproperty->type = BDF_PROPERTY_TYPE_NONE; + + if ( face ) + { + FT_Service_BDF service; + + + FT_FACE_FIND_SERVICE( face, service, BDF ); + + if ( service && service->get_property ) + error = service->get_property( face, prop_name, aproperty ); + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftcalc.c b/Utilities/vtkfreetype/src/base/ftcalc.c new file mode 100644 index 0000000..f169642 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftcalc.c @@ -0,0 +1,624 @@ +/***************************************************************************/ +/* */ +/* ftcalc.c */ +/* */ +/* Arithmetic computations (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* Support for 1-complement arithmetic has been totally dropped in this */ + /* release. You can still write your own code if you need it. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Implementing basic computation routines. */ + /* */ + /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */ + /* and FT_FloorFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_OBJECTS_H + + +/* we need to define a 64-bits data type here */ + +#ifdef FT_LONG64 + + typedef FT_INT64 FT_Int64; + +#else + + typedef struct FT_Int64_ + { + FT_UInt32 lo; + FT_UInt32 hi; + + } FT_Int64; + +#endif /* FT_LONG64 */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_calc + + + /* The following three functions are available regardless of whether */ + /* FT_LONG64 is defined. */ + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Fixed ) + FT_RoundFix( FT_Fixed a ) + { + return ( a >= 0 ) ? ( a + 0x8000L ) & ~0xFFFFL + : -((-a + 0x8000L ) & ~0xFFFFL ); + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Fixed ) + FT_CeilFix( FT_Fixed a ) + { + return ( a >= 0 ) ? ( a + 0xFFFFL ) & ~0xFFFFL + : -((-a + 0xFFFFL ) & ~0xFFFFL ); + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Fixed ) + FT_FloorFix( FT_Fixed a ) + { + return ( a >= 0 ) ? a & ~0xFFFFL + : -((-a) & ~0xFFFFL ); + } + + + /* documentation is in ftcalc.h */ + + FT_EXPORT_DEF( FT_Int32 ) + FT_Sqrt32( FT_Int32 x ) + { + FT_ULong val, root, newroot, mask; + + + root = 0; + mask = 0x40000000L; + val = (FT_ULong)x; + + do + { + newroot = root + mask; + if ( newroot <= val ) + { + val -= newroot; + root = newroot + mask; + } + + root >>= 1; + mask >>= 2; + + } while ( mask != 0 ); + + return root; + } + + +#ifdef FT_LONG64 + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ) + { + FT_Int s; + FT_Long d; + + + s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c + : 0x7FFFFFFFL ); + + return ( s > 0 ) ? d : -d; + } + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* documentation is in ftcalc.h */ + + FT_BASE_DEF( FT_Long ) + FT_MulDiv_No_Round( FT_Long a, + FT_Long b, + FT_Long c ) + { + FT_Int s; + FT_Long d; + + + s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c + : 0x7FFFFFFFL ); + + return ( s > 0 ) ? d : -d; + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_MulFix( FT_Long a, + FT_Long b ) + { + FT_Int s = 1; + FT_Long c; + + + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + + c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 ); + return ( s > 0 ) ? c : -c ; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_DivFix( FT_Long a, + FT_Long b ) + { + FT_Int32 s; + FT_UInt32 q; + + s = 1; + if ( a < 0 ) { a = -a; s = -1; } + if ( b < 0 ) { b = -b; s = -s; } + + if ( b == 0 ) + /* check for division by 0 */ + q = 0x7FFFFFFFL; + else + /* compute result directly */ + q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b ); + + return ( s < 0 ? -(FT_Long)q : (FT_Long)q ); + } + + +#else /* FT_LONG64 */ + + + static void + ft_multo64( FT_UInt32 x, + FT_UInt32 y, + FT_Int64 *z ) + { + FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; + + + lo1 = x & 0x0000FFFFU; hi1 = x >> 16; + lo2 = y & 0x0000FFFFU; hi2 = y >> 16; + + lo = lo1 * lo2; + i1 = lo1 * hi2; + i2 = lo2 * hi1; + hi = hi1 * hi2; + + /* Check carry overflow of i1 + i2 */ + i1 += i2; + hi += (FT_UInt32)( i1 < i2 ) << 16; + + hi += i1 >> 16; + i1 = i1 << 16; + + /* Check carry overflow of i1 + lo */ + lo += i1; + hi += ( lo < i1 ); + + z->lo = lo; + z->hi = hi; + } + + + static FT_UInt32 + ft_div64by32( FT_UInt32 hi, + FT_UInt32 lo, + FT_UInt32 y ) + { + FT_UInt32 r, q; + FT_Int i; + + + q = 0; + r = hi; + + if ( r >= y ) + return (FT_UInt32)0x7FFFFFFFL; + + i = 32; + do + { + r <<= 1; + q <<= 1; + r |= lo >> 31; + + if ( r >= (FT_UInt32)y ) + { + r -= y; + q |= 1; + } + lo <<= 1; + } while ( --i ); + + return q; + } + + + /* documentation is in ftcalc.h */ + + FT_EXPORT_DEF( void ) + FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64 *z ) + { + register FT_UInt32 lo, hi, max; + + + max = x->lo > y->lo ? x->lo : y->lo; + lo = x->lo + y->lo; + hi = x->hi + y->hi + ( lo < max ); + + z->lo = lo; + z->hi = hi; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ) + { + long s; + + + if ( a == 0 || b == c ) + return a; + + s = a; a = FT_ABS( a ); + s ^= b; b = FT_ABS( b ); + s ^= c; c = FT_ABS( c ); + + if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 ) + a = ( a * b + ( c >> 1 ) ) / c; + + else if ( c > 0 ) + { + FT_Int64 temp, temp2; + + + ft_multo64( a, b, &temp ); + + temp2.hi = 0; + temp2.lo = (FT_UInt32)(c >> 1); + FT_Add64( &temp, &temp2, &temp ); + a = ft_div64by32( temp.hi, temp.lo, c ); + } + else + a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_BASE_DEF( FT_Long ) + FT_MulDiv_No_Round( FT_Long a, + FT_Long b, + FT_Long c ) + { + long s; + + + if ( a == 0 || b == c ) + return a; + + s = a; a = FT_ABS( a ); + s ^= b; b = FT_ABS( b ); + s ^= c; c = FT_ABS( c ); + + if ( a <= 46340L && b <= 46340L && c > 0 ) + a = a * b / c; + + else if ( c > 0 ) + { + FT_Int64 temp; + + + ft_multo64( a, b, &temp ); + a = ft_div64by32( temp.hi, temp.lo, c ); + } + else + a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_MulFix( FT_Long a, + FT_Long b ) + { + FT_Long s; + FT_ULong ua, ub; + + + if ( a == 0 || b == 0x10000L ) + return a; + + s = a; a = FT_ABS(a); + s ^= b; b = FT_ABS(b); + + ua = (FT_ULong)a; + ub = (FT_ULong)b; + + if ( ua <= 2048 && ub <= 1048576L ) + { + ua = ( ua * ub + 0x8000L ) >> 16; + } + else + { + FT_ULong al = ua & 0xFFFFL; + + + ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) + + ( ( al * ( ub & 0xFFFFL ) + 0x8000L ) >> 16 ); + } + + return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua ); + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Long ) + FT_DivFix( FT_Long a, + FT_Long b ) + { + FT_Int32 s; + FT_UInt32 q; + + + s = a; a = FT_ABS(a); + s ^= b; b = FT_ABS(b); + + if ( b == 0 ) + { + /* check for division by 0 */ + q = 0x7FFFFFFFL; + } + else if ( ( a >> 16 ) == 0 ) + { + /* compute result directly */ + q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b; + } + else + { + /* we need more bits; we have to do it by hand */ + FT_Int64 temp, temp2; + + temp.hi = (FT_Int32) (a >> 16); + temp.lo = (FT_UInt32)(a << 16); + temp2.hi = 0; + temp2.lo = (FT_UInt32)( b >> 1 ); + FT_Add64( &temp, &temp2, &temp ); + q = ft_div64by32( temp.hi, temp.lo, b ); + } + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + + /* documentation is in ftcalc.h */ + + FT_EXPORT_DEF( void ) + FT_MulTo64( FT_Int32 x, + FT_Int32 y, + FT_Int64 *z ) + { + FT_Int32 s; + + + s = x; x = FT_ABS( x ); + s ^= y; y = FT_ABS( y ); + + ft_multo64( x, y, z ); + + if ( s < 0 ) + { + z->lo = (FT_UInt32)-(FT_Int32)z->lo; + z->hi = ~z->hi + !( z->lo ); + } + } + + + /* documentation is in ftcalc.h */ + + /* apparently, the second version of this code is not compiled correctly */ + /* on Mac machines with the MPW C compiler.. tsss, tsss, tss... */ + +#if 1 + + FT_EXPORT_DEF( FT_Int32 ) + FT_Div64by32( FT_Int64* x, + FT_Int32 y ) + { + FT_Int32 s; + FT_UInt32 q, r, i, lo; + + + s = x->hi; + if ( s < 0 ) + { + x->lo = (FT_UInt32)-(FT_Int32)x->lo; + x->hi = ~x->hi + !x->lo; + } + s ^= y; y = FT_ABS( y ); + + /* Shortcut */ + if ( x->hi == 0 ) + { + if ( y > 0 ) + q = x->lo / y; + else + q = 0x7FFFFFFFL; + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + r = x->hi; + lo = x->lo; + + if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */ + return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL ); + /* Return Max/Min Int32 if division overflow. */ + /* This includes division by zero! */ + q = 0; + for ( i = 0; i < 32; i++ ) + { + r <<= 1; + q <<= 1; + r |= lo >> 31; + + if ( r >= (FT_UInt32)y ) + { + r -= y; + q |= 1; + } + lo <<= 1; + } + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + +#else /* 0 */ + + FT_EXPORT_DEF( FT_Int32 ) + FT_Div64by32( FT_Int64* x, + FT_Int32 y ) + { + FT_Int32 s; + FT_UInt32 q; + + + s = x->hi; + if ( s < 0 ) + { + x->lo = (FT_UInt32)-(FT_Int32)x->lo; + x->hi = ~x->hi + !x->lo; + } + s ^= y; y = FT_ABS( y ); + + /* Shortcut */ + if ( x->hi == 0 ) + { + if ( y > 0 ) + q = ( x->lo + ( y >> 1 ) ) / y; + else + q = 0x7FFFFFFFL; + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + q = ft_div64by32( x->hi, x->lo, y ); + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + +#endif /* 0 */ + + +#endif /* FT_LONG64 */ + + + /* a not-so-fast but working 16.16 fixed point square root function */ + + FT_EXPORT_DEF( FT_Int32 ) + FT_SqrtFixed( FT_Int32 x ) + { + FT_UInt32 root, rem_hi, rem_lo, test_div; + FT_Int count; + + + root = 0; + + if ( x > 0 ) + { + rem_hi = 0; + rem_lo = x; + count = 24; + do + { + rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 ); + rem_lo <<= 2; + root <<= 1; + test_div = ( root << 1 ) + 1; + + if ( rem_hi >= test_div ) + { + rem_hi -= test_div; + root += 1; + } + } while ( --count ); + } + + return (FT_Int32)root; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftdbgmem.c b/Utilities/vtkfreetype/src/base/ftdbgmem.c new file mode 100644 index 0000000..61227b6 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftdbgmem.c @@ -0,0 +1,763 @@ +/***************************************************************************/ +/* */ +/* ftdbgmem.c */ +/* */ +/* Memory debugger (body). */ +/* */ +/* Copyright 2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_MEMORY_H +#include FT_SYSTEM_H +#include FT_ERRORS_H +#include FT_TYPES_H + + +#ifdef FT_DEBUG_MEMORY + + +#include <stdio.h> +#include <stdlib.h> + + + typedef struct FT_MemNodeRec_* FT_MemNode; + typedef struct FT_MemTableRec_* FT_MemTable; + +#define FT_MEM_VAL( addr ) ((FT_ULong)(FT_Pointer)( addr )) + + typedef struct FT_MemNodeRec_ + { + FT_Byte* address; + FT_Long size; /* < 0 if the block was freed */ + + const char* alloc_file_name; + FT_Long alloc_line_no; + + const char* free_file_name; + FT_Long free_line_no; + + FT_MemNode link; + + } FT_MemNodeRec; + + + typedef struct FT_MemTableRec_ + { + FT_ULong size; + FT_ULong nodes; + FT_MemNode* buckets; + + FT_ULong alloc_total; + FT_ULong alloc_current; + FT_ULong alloc_max; + FT_ULong alloc_count; + + FT_Bool bound_total; + FT_ULong alloc_total_max; + + FT_Bool bound_count; + FT_ULong alloc_count_max; + + const char* file_name; + FT_Long line_no; + + FT_Memory memory; + FT_Pointer memory_user; + FT_Alloc_Func alloc; + FT_Free_Func free; + FT_Realloc_Func realloc; + + } FT_MemTableRec; + + +#define FT_MEM_SIZE_MIN 7 +#define FT_MEM_SIZE_MAX 13845163 + +#define FT_FILENAME( x ) ((x) ? (x) : "unknown file") + + + static const FT_UInt ft_mem_primes[] = + { + 7, + 11, + 19, + 37, + 73, + 109, + 163, + 251, + 367, + 557, + 823, + 1237, + 1861, + 2777, + 4177, + 6247, + 9371, + 14057, + 21089, + 31627, + 47431, + 71143, + 106721, + 160073, + 240101, + 360163, + 540217, + 810343, + 1215497, + 1823231, + 2734867, + 4102283, + 6153409, + 9230113, + 13845163, + }; + + + + extern void + ft_mem_debug_panic( const char* fmt, ... ) + { + va_list ap; + + + printf( "FreeType.Debug: " ); + + va_start( ap, fmt ); + vprintf( fmt, ap ); + va_end( ap ); + + printf( "\n" ); + exit( EXIT_FAILURE ); + } + + + static FT_ULong + ft_mem_closest_prime( FT_ULong num ) + { + FT_UInt i; + + + for ( i = 0; + i < sizeof ( ft_mem_primes ) / sizeof ( ft_mem_primes[0] ); i++ ) + if ( ft_mem_primes[i] > num ) + return ft_mem_primes[i]; + + return FT_MEM_SIZE_MAX; + } + + + static FT_Pointer + ft_mem_table_alloc( FT_MemTable table, + FT_Long size ) + { + FT_Memory memory = table->memory; + FT_Pointer block; + + + memory->user = table->memory_user; + block = table->alloc( memory, size ); + memory->user = table; + + return block; + } + + + static void + ft_mem_table_free( FT_MemTable table, + FT_Pointer block ) + { + FT_Memory memory = table->memory; + + + memory->user = table->memory_user; + table->free( memory, block ); + memory->user = table; + } + + + static void + ft_mem_table_resize( FT_MemTable table ) + { + FT_ULong new_size; + + + new_size = ft_mem_closest_prime( table->nodes ); + if ( new_size != table->size ) + { + FT_MemNode* new_buckets ; + FT_ULong i; + + + new_buckets = (FT_MemNode *) + ft_mem_table_alloc( table, + new_size * sizeof ( FT_MemNode ) ); + if ( new_buckets == NULL ) + return; + + FT_MEM_ZERO( new_buckets, sizeof ( FT_MemNode ) * new_size ); + + for ( i = 0; i < table->size; i++ ) + { + FT_MemNode node, next, *pnode; + FT_ULong hash; + + + node = table->buckets[i]; + while ( node ) + { + next = node->link; + hash = FT_MEM_VAL( node->address ) % new_size; + pnode = new_buckets + hash; + + node->link = pnode[0]; + pnode[0] = node; + + node = next; + } + } + + if ( table->buckets ) + ft_mem_table_free( table, table->buckets ); + + table->buckets = new_buckets; + table->size = new_size; + } + } + + + static FT_MemTable + ft_mem_table_new( FT_Memory memory ) + { + FT_MemTable table; + + + table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) ); + if ( table == NULL ) + goto Exit; + + FT_MEM_ZERO( table, sizeof ( *table ) ); + + table->size = FT_MEM_SIZE_MIN; + table->nodes = 0; + + table->memory = memory; + + table->memory_user = memory->user; + + table->alloc = memory->alloc; + table->realloc = memory->realloc; + table->free = memory->free; + + table->buckets = (FT_MemNode *) + memory->alloc( memory, + table->size * sizeof ( FT_MemNode ) ); + if ( table->buckets ) + FT_MEM_ZERO( table->buckets, sizeof ( FT_MemNode ) * table->size ); + else + { + memory->free( memory, table ); + table = NULL; + } + + Exit: + return table; + } + + + static void + ft_mem_table_destroy( FT_MemTable table ) + { + FT_ULong i; + + + if ( table ) + { + FT_Long leak_count = 0; + FT_ULong leaks = 0; + + + for ( i = 0; i < table->size; i++ ) + { + FT_MemNode *pnode = table->buckets + i, next, node = *pnode; + + + while ( node ) + { + next = node->link; + node->link = 0; + + if ( node->size > 0 ) + { + printf( + "leaked memory block at address %p, size %8ld in (%s:%ld)\n", + node->address, node->size, + FT_FILENAME( node->alloc_file_name ), + node->alloc_line_no ); + + leak_count++; + leaks += node->size; + + ft_mem_table_free( table, node->address ); + } + + node->address = NULL; + node->size = 0; + + free( node ); + node = next; + } + table->buckets[i] = 0; + } + ft_mem_table_free( table, table->buckets ); + table->buckets = NULL; + + table->size = 0; + table->nodes = 0; + + printf( + "FreeType: total memory allocations = %ld\n", table->alloc_total ); + printf( + "FreeType: maximum memory footprint = %ld\n", table->alloc_max ); + + free( table ); + + if ( leak_count > 0 ) + ft_mem_debug_panic( + "FreeType: %ld bytes of memory leaked in %ld blocks\n", + leaks, leak_count ); + printf( "FreeType: No memory leaks detected!\n" ); + } + } + + + static FT_MemNode* + ft_mem_table_get_nodep( FT_MemTable table, + FT_Byte* address ) + { + FT_ULong hash; + FT_MemNode *pnode, node; + + + hash = FT_MEM_VAL( address ); + pnode = table->buckets + ( hash % table->size ); + + for (;;) + { + node = pnode[0]; + if ( !node ) + break; + + if ( node->address == address ) + break; + + pnode = &node->link; + } + return pnode; + } + + + static void + ft_mem_table_set( FT_MemTable table, + FT_Byte* address, + FT_ULong size ) + { + FT_MemNode *pnode, node; + + + if ( table ) + { + pnode = ft_mem_table_get_nodep( table, address ); + node = *pnode; + if ( node ) + { + if ( node->size < 0 ) + { + /* this block was already freed. This means that our memory is */ + /* now completely corrupted! */ + ft_mem_debug_panic( + "memory heap corrupted (allocating freed block)" ); + } + else + { + /* this block was already allocated. This means that our memory */ + /* is also corrupted! */ + ft_mem_debug_panic( + "memory heap corrupted (re-allocating allocated block)" ); + } + } + + /* we need to create a new node in this table */ + node = (FT_MemNode)ft_mem_table_alloc( table, sizeof ( *node ) ); + if ( node == NULL ) + ft_mem_debug_panic( "not enough memory to run memory tests" ); + + node->address = address; + node->size = size; + + node->alloc_file_name = table->file_name; + node->alloc_line_no = table->line_no; + + node->free_file_name = NULL; + node->free_line_no = 0; + + node->link = pnode[0]; + + pnode[0] = node; + table->nodes++; + + table->alloc_total += size; + table->alloc_current += size; + if ( table->alloc_current > table->alloc_max ) + table->alloc_max = table->alloc_current; + + if ( table->nodes * 3 < table->size || + table->size * 3 < table->nodes ) + ft_mem_table_resize( table ); + } + } + + + static void + ft_mem_table_remove( FT_MemTable table, + FT_Byte* address ) + { + if ( table ) + { + FT_MemNode *pnode, node; + + + pnode = ft_mem_table_get_nodep( table, address ); + node = *pnode; + if ( node ) + { + if ( node->size < 0 ) + ft_mem_debug_panic( + "freeing memory block at %p more than once at (%s:%ld)\n" + "block allocated at (%s:%ld) and released at (%s:%ld)", + address, + FT_FILENAME( table->file_name ), table->line_no, + FT_FILENAME( node->alloc_file_name ), node->alloc_line_no, + FT_FILENAME( node->free_file_name ), node->free_line_no ); + + /* we simply invert the node's size to indicate that the node */ + /* was freed. We also change its contents. */ + FT_MEM_SET( address, 0xF3, node->size ); + + table->alloc_current -= node->size; + node->size = -node->size; + node->free_file_name = table->file_name; + node->free_line_no = table->line_no; + } + else + ft_mem_debug_panic( + "trying to free unknown block at %p in (%s:%ld)\n", + address, + FT_FILENAME( table->file_name ), table->line_no ); + } + } + + + extern FT_Pointer + ft_mem_debug_alloc( FT_Memory memory, + FT_Long size ) + { + FT_MemTable table = (FT_MemTable)memory->user; + FT_Byte* block; + + + if ( size <= 0 ) + ft_mem_debug_panic( "negative block size allocation (%ld)", size ); + + /* return NULL if the maximum number of allocations was reached */ + if ( table->bound_count && + table->alloc_count >= table->alloc_count_max ) + return NULL; + + /* return NULL if this allocation would overflow the maximum heap size */ + if ( table->bound_total && + table->alloc_current + (FT_ULong)size > table->alloc_total_max ) + return NULL; + + block = (FT_Byte *)ft_mem_table_alloc( table, size ); + if ( block ) + ft_mem_table_set( table, block, (FT_ULong)size ); + + table->alloc_count++; + + table->file_name = NULL; + table->line_no = 0; + + return (FT_Pointer) block; + } + + + extern void + ft_mem_debug_free( FT_Memory memory, + FT_Pointer block ) + { + FT_MemTable table = (FT_MemTable)memory->user; + + + if ( block == NULL ) + ft_mem_debug_panic( "trying to free NULL in (%s:%ld)", + FT_FILENAME( table->file_name ), + table->line_no ); + + ft_mem_table_remove( table, (FT_Byte*)block ); + + /* we never really free the block */ + table->file_name = NULL; + table->line_no = 0; + } + + + extern FT_Pointer + ft_mem_debug_realloc( FT_Memory memory, + FT_Long cur_size, + FT_Long new_size, + FT_Pointer block ) + { + FT_MemTable table = (FT_MemTable)memory->user; + FT_MemNode node, *pnode; + FT_Pointer new_block; + + const char* file_name = FT_FILENAME( table->file_name ); + FT_Long line_no = table->line_no; + + + /* the following is valid according to ANSI C */ +#if 0 + if ( block == NULL || cur_size == 0 ) + ft_mem_debug_panic( "trying to reallocate NULL in (%s:%ld)", + file_name, line_no ); +#endif + + /* while the following is allowed in ANSI C also, we abort since */ + /* such code shouldn't be in FreeType... */ + if ( new_size <= 0 ) + ft_mem_debug_panic( + "trying to reallocate %p to size 0 (current is %ld) in (%s:%ld)", + block, cur_size, file_name, line_no ); + + /* check 'cur_size' value */ + pnode = ft_mem_table_get_nodep( table, (FT_Byte*)block ); + node = *pnode; + if ( !node ) + ft_mem_debug_panic( + "trying to reallocate unknown block at %p in (%s:%ld)", + block, file_name, line_no ); + + if ( node->size <= 0 ) + ft_mem_debug_panic( + "trying to reallocate freed block at %p in (%s:%ld)", + block, file_name, line_no ); + + if ( node->size != cur_size ) + ft_mem_debug_panic( "invalid ft_realloc request for %p. cur_size is " + "%ld instead of %ld in (%s:%ld)", + block, cur_size, node->size, file_name, line_no ); + + new_block = ft_mem_debug_alloc( memory, new_size ); + if ( new_block == NULL ) + return NULL; + + ft_memcpy( new_block, block, cur_size < new_size ? cur_size : new_size ); + + table->file_name = file_name; + table->line_no = line_no; + + ft_mem_debug_free( memory, (FT_Byte*)block ); + + return new_block; + } + + + extern FT_Int + ft_mem_debug_init( FT_Memory memory ) + { + FT_MemTable table; + FT_Int result = 0; + + + if ( getenv( "FT2_DEBUG_MEMORY" ) ) + { + table = ft_mem_table_new( memory ); + if ( table ) + { + const char* p; + + memory->user = table; + memory->alloc = ft_mem_debug_alloc; + memory->realloc = ft_mem_debug_realloc; + memory->free = ft_mem_debug_free; + + p = getenv( "FT2_ALLOC_TOTAL_MAX" ); + if ( p != NULL ) + { + FT_Long total_max = ft_atol(p); + + if ( total_max > 0 ) + { + table->bound_total = 1; + table->alloc_total_max = (FT_ULong) total_max; + } + } + + p = getenv( "FT2_ALLOC_COUNT_MAX" ); + if ( p != NULL ) + { + FT_Long total_count = ft_atol(p); + + if ( total_count > 0 ) + { + table->bound_count = 1; + table->alloc_count_max = (FT_ULong) total_count; + } + } + + result = 1; + } + } + return result; + } + + + extern void + ft_mem_debug_done( FT_Memory memory ) + { + FT_MemTable table = (FT_MemTable)memory->user; + + + if ( table ) + { + memory->free = table->free; + memory->realloc = table->realloc; + memory->alloc = table->alloc; + + ft_mem_table_destroy( table ); + memory->user = NULL; + } + } + + + FT_BASE_DEF( FT_Error ) + FT_Alloc_Debug( FT_Memory memory, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ) + { + FT_MemTable table = (FT_MemTable)memory->user; + + + if ( table ) + { + table->file_name = file_name; + table->line_no = line_no; + } + return FT_Alloc( memory, size, P ); + } + + + FT_BASE_DEF( FT_Error ) + FT_Realloc_Debug( FT_Memory memory, + FT_Long current, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ) + { + FT_MemTable table = (FT_MemTable)memory->user; + + + if ( table ) + { + table->file_name = file_name; + table->line_no = line_no; + } + return FT_Realloc( memory, current, size, P ); + } + + + FT_BASE_DEF( FT_Error ) + FT_QAlloc_Debug( FT_Memory memory, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ) + { + FT_MemTable table = (FT_MemTable)memory->user; + + + if ( table ) + { + table->file_name = file_name; + table->line_no = line_no; + } + + return FT_QAlloc( memory, size, P ); + } + + + FT_BASE_DEF( FT_Error ) + FT_QRealloc_Debug( FT_Memory memory, + FT_Long current, + FT_Long size, + void* *P, + const char* file_name, + FT_Long line_no ) + { + FT_MemTable table = (FT_MemTable)memory->user; + + + if ( table ) + { + table->file_name = file_name; + table->line_no = line_no; + } + return FT_QRealloc( memory, current, size, P ); + } + + + FT_BASE_DEF( void ) + FT_Free_Debug( FT_Memory memory, + FT_Pointer block, + const char* file_name, + FT_Long line_no ) + { + FT_MemTable table = (FT_MemTable)memory->user; + + + if ( table ) + { + table->file_name = file_name; + table->line_no = line_no; + } + FT_Free( memory, (void **)block ); + } + + +#else /* !FT_DEBUG_MEMORY */ + + /* ANSI C doesn't like empty source files */ + const FT_Byte _debug_mem_dummy = 0; + +#endif /* !FT_DEBUG_MEMORY */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftdebug.c b/Utilities/vtkfreetype/src/base/ftdebug.c new file mode 100644 index 0000000..a6c1841 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftdebug.c @@ -0,0 +1,242 @@ +/***************************************************************************/ +/* */ +/* ftdebug.c */ +/* */ +/* Debugging and logging component (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component contains various macros and functions used to ease the */ + /* debugging of the FreeType engine. Its main purpose is in assertion */ + /* checking, tracing, and error detection. */ + /* */ + /* There are now three debugging modes: */ + /* */ + /* - trace mode */ + /* */ + /* Error and trace messages are sent to the log file (which can be the */ + /* standard error output). */ + /* */ + /* - error mode */ + /* */ + /* Only error messages are generated. */ + /* */ + /* - release mode: */ + /* */ + /* No error message is sent or generated. The code is free from any */ + /* debugging parts. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_INTERNAL_DEBUG_H + + +#if defined( FT_DEBUG_LEVEL_ERROR ) + + FT_EXPORT_DEF( void ) + FT_Message( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); + vprintf( fmt, ap ); + va_end( ap ); + } + + + FT_EXPORT_DEF( void ) + FT_Panic( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); + vprintf( fmt, ap ); + va_end( ap ); + + exit( EXIT_FAILURE ); + } + +#endif /* FT_DEBUG_LEVEL_ERROR */ + + + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* array of trace levels, initialized to 0 */ + int ft_trace_levels[trace_count]; + + + /* define array of trace toggle names */ +#define FT_TRACE_DEF( x ) #x , + + static const char* ft_trace_toggles[trace_count + 1] = + { +#include FT_INTERNAL_TRACE_H + NULL + }; + +#undef FT_TRACE_DEF + + + /* documentation is in ftdebug.h */ + + FT_EXPORT_DEF( FT_Int ) + FT_Trace_Get_Count( void ) + { + return trace_count; + } + + + /* documentation is in ftdebug.h */ + + FT_EXPORT_DEF( const char * ) + FT_Trace_Get_Name( FT_Int idx ) + { + int max = FT_Trace_Get_Count(); + + + if ( idx < max ) + return ft_trace_toggles[idx]; + else + return NULL; + } + + + /*************************************************************************/ + /* */ + /* Initialize the tracing sub-system. This is done by retrieving the */ + /* value of the `FT2_DEBUG' environment variable. It must be a list of */ + /* toggles, separated by spaces, `;', or `,'. Example: */ + /* */ + /* export FT2_DEBUG="any:3 memory:6 stream:5" */ + /* */ + /* This requests that all levels be set to 3, except the trace level for */ + /* the memory and stream components which are set to 6 and 5, */ + /* respectively. */ + /* */ + /* See the file <include/freetype/internal/fttrace.h> for details of the */ + /* available toggle names. */ + /* */ + /* The level must be between 0 and 6; 0 means quiet (except for serious */ + /* runtime errors), and 6 means _very_ verbose. */ + /* */ + FT_BASE_DEF( void ) + ft_debug_init( void ) + { + const char* ft2_debug = getenv( "FT2_DEBUG" ); + + + if ( ft2_debug ) + { + const char* p = ft2_debug; + const char* q; + + + for ( ; *p; p++ ) + { + /* skip leading whitespace and separators */ + if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' ) + continue; + + /* read toggle name, followed by ':' */ + q = p; + while ( *p && *p != ':' ) + p++; + + if ( *p == ':' && p > q ) + { + FT_Int n, i, len = (FT_Int)( p - q ); + FT_Int level = -1, found = -1; + + + for ( n = 0; n < trace_count; n++ ) + { + const char* toggle = ft_trace_toggles[n]; + + + for ( i = 0; i < len; i++ ) + { + if ( toggle[i] != q[i] ) + break; + } + + if ( i == len && toggle[i] == 0 ) + { + found = n; + break; + } + } + + /* read level */ + p++; + if ( *p ) + { + level = *p++ - '0'; + if ( level < 0 || level > 6 ) + level = -1; + } + + if ( found >= 0 && level >= 0 ) + { + if ( found == trace_any ) + { + /* special case for `any' */ + for ( n = 0; n < trace_count; n++ ) + ft_trace_levels[n] = level; + } + else + ft_trace_levels[found] = level; + } + } + } + } + } + + +#else /* !FT_DEBUG_LEVEL_TRACE */ + + + FT_BASE_DEF( void ) + ft_debug_init( void ) + { + /* nothing */ + } + + + FT_EXPORT_DEF( FT_Int ) + FT_Trace_Get_Count( void ) + { + return 0; + } + + + FT_EXPORT_DEF( const char * ) + FT_Trace_Get_Name( FT_Int idx ) + { + FT_UNUSED( idx ); + + return NULL; + } + + +#endif /* !FT_DEBUG_LEVEL_TRACE */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftgloadr.c b/Utilities/vtkfreetype/src/base/ftgloadr.c new file mode 100644 index 0000000..94a0706 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftgloadr.c @@ -0,0 +1,362 @@ +/***************************************************************************/ +/* */ +/* ftgloadr.c */ +/* */ +/* The FreeType glyph loader (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_GLYPH_LOADER_H +#include FT_INTERNAL_MEMORY_H +#include FT_INTERNAL_OBJECTS_H + +#undef FT_COMPONENT +#define FT_COMPONENT trace_gloader + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** *****/ + /***** G L Y P H L O A D E R *****/ + /***** *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* The glyph loader is a simple object which is used to load a set of */ + /* glyphs easily. It is critical for the correct loading of composites. */ + /* */ + /* Ideally, one can see it as a stack of abstract `glyph' objects. */ + /* */ + /* loader.base Is really the bottom of the stack. It describes a */ + /* single glyph image made of the juxtaposition of */ + /* several glyphs (those `in the stack'). */ + /* */ + /* loader.current Describes the top of the stack, on which a new */ + /* glyph can be loaded. */ + /* */ + /* Rewind Clears the stack. */ + /* Prepare Set up `loader.current' for addition of a new glyph */ + /* image. */ + /* Add Add the `current' glyph image to the `base' one, */ + /* and prepare for another one. */ + /* */ + /* The glyph loader is now a base object. Each driver used to */ + /* re-implement it in one way or the other, which wasted code and */ + /* energy. */ + /* */ + /*************************************************************************/ + + + /* create a new glyph loader */ + FT_BASE_DEF( FT_Error ) + FT_GlyphLoader_New( FT_Memory memory, + FT_GlyphLoader *aloader ) + { + FT_GlyphLoader loader; + FT_Error error; + + + if ( !FT_NEW( loader ) ) + { + loader->memory = memory; + *aloader = loader; + } + return error; + } + + + /* rewind the glyph loader - reset counters to 0 */ + FT_BASE_DEF( void ) + FT_GlyphLoader_Rewind( FT_GlyphLoader loader ) + { + FT_GlyphLoad base = &loader->base; + FT_GlyphLoad current = &loader->current; + + + base->outline.n_points = 0; + base->outline.n_contours = 0; + base->num_subglyphs = 0; + + *current = *base; + } + + + /* reset the glyph loader, frees all allocated tables */ + /* and starts from zero */ + FT_BASE_DEF( void ) + FT_GlyphLoader_Reset( FT_GlyphLoader loader ) + { + FT_Memory memory = loader->memory; + + + FT_FREE( loader->base.outline.points ); + FT_FREE( loader->base.outline.tags ); + FT_FREE( loader->base.outline.contours ); + FT_FREE( loader->base.extra_points ); + FT_FREE( loader->base.subglyphs ); + + loader->max_points = 0; + loader->max_contours = 0; + loader->max_subglyphs = 0; + + FT_GlyphLoader_Rewind( loader ); + } + + + /* delete a glyph loader */ + FT_BASE_DEF( void ) + FT_GlyphLoader_Done( FT_GlyphLoader loader ) + { + if ( loader ) + { + FT_Memory memory = loader->memory; + + + FT_GlyphLoader_Reset( loader ); + FT_FREE( loader ); + } + } + + + /* re-adjust the `current' outline fields */ + static void + FT_GlyphLoader_Adjust_Points( FT_GlyphLoader loader ) + { + FT_Outline* base = &loader->base.outline; + FT_Outline* current = &loader->current.outline; + + + current->points = base->points + base->n_points; + current->tags = base->tags + base->n_points; + current->contours = base->contours + base->n_contours; + + /* handle extra points table - if any */ + if ( loader->use_extra ) + loader->current.extra_points = + loader->base.extra_points + base->n_points; + } + + + FT_BASE_DEF( FT_Error ) + FT_GlyphLoader_CreateExtra( FT_GlyphLoader loader ) + { + FT_Error error; + FT_Memory memory = loader->memory; + + + if ( !FT_NEW_ARRAY( loader->base.extra_points, loader->max_points ) ) + { + loader->use_extra = 1; + FT_GlyphLoader_Adjust_Points( loader ); + } + return error; + } + + + /* re-adjust the `current' subglyphs field */ + static void + FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader loader ) + { + FT_GlyphLoad base = &loader->base; + FT_GlyphLoad current = &loader->current; + + + current->subglyphs = base->subglyphs + base->num_subglyphs; + } + + + /* Ensure that we can add `n_points' and `n_contours' to our glyph. */ + /* This function reallocates its outline tables if necessary. Note that */ + /* it DOESN'T change the number of points within the loader! */ + /* */ + FT_BASE_DEF( FT_Error ) + FT_GlyphLoader_CheckPoints( FT_GlyphLoader loader, + FT_UInt n_points, + FT_UInt n_contours ) + { + FT_Memory memory = loader->memory; + FT_Error error = FT_Err_Ok; + FT_Outline* base = &loader->base.outline; + FT_Outline* current = &loader->current.outline; + FT_Bool adjust = 1; + + FT_UInt new_max, old_max; + + + /* check points & tags */ + new_max = base->n_points + current->n_points + n_points; + old_max = loader->max_points; + + if ( new_max > old_max ) + { + new_max = FT_PAD_CEIL( new_max, 8 ); + + if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) || + FT_RENEW_ARRAY( base->tags, old_max, new_max ) ) + goto Exit; + + if ( loader->use_extra && + FT_RENEW_ARRAY( loader->base.extra_points, old_max, new_max ) ) + goto Exit; + + adjust = 1; + loader->max_points = new_max; + } + + /* check contours */ + old_max = loader->max_contours; + new_max = base->n_contours + current->n_contours + + n_contours; + if ( new_max > old_max ) + { + new_max = FT_PAD_CEIL( new_max, 4 ); + if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) ) + goto Exit; + + adjust = 1; + loader->max_contours = new_max; + } + + if ( adjust ) + FT_GlyphLoader_Adjust_Points( loader ); + + Exit: + return error; + } + + + /* Ensure that we can add `n_subglyphs' to our glyph. this function */ + /* reallocates its subglyphs table if necessary. Note that it DOES */ + /* NOT change the number of subglyphs within the loader! */ + /* */ + FT_BASE_DEF( FT_Error ) + FT_GlyphLoader_CheckSubGlyphs( FT_GlyphLoader loader, + FT_UInt n_subs ) + { + FT_Memory memory = loader->memory; + FT_Error error = FT_Err_Ok; + FT_UInt new_max, old_max; + + FT_GlyphLoad base = &loader->base; + FT_GlyphLoad current = &loader->current; + + + new_max = base->num_subglyphs + current->num_subglyphs + n_subs; + old_max = loader->max_subglyphs; + if ( new_max > old_max ) + { + new_max = FT_PAD_CEIL( new_max, 2 ); + if ( FT_RENEW_ARRAY( base->subglyphs, old_max, new_max ) ) + goto Exit; + + loader->max_subglyphs = new_max; + + FT_GlyphLoader_Adjust_Subglyphs( loader ); + } + + Exit: + return error; + } + + + /* prepare loader for the addition of a new glyph on top of the base one */ + FT_BASE_DEF( void ) + FT_GlyphLoader_Prepare( FT_GlyphLoader loader ) + { + FT_GlyphLoad current = &loader->current; + + + current->outline.n_points = 0; + current->outline.n_contours = 0; + current->num_subglyphs = 0; + + FT_GlyphLoader_Adjust_Points ( loader ); + FT_GlyphLoader_Adjust_Subglyphs( loader ); + } + + + /* add current glyph to the base image - and prepare for another */ + FT_BASE_DEF( void ) + FT_GlyphLoader_Add( FT_GlyphLoader loader ) + { + FT_GlyphLoad base = &loader->base; + FT_GlyphLoad current = &loader->current; + + FT_UInt n_curr_contours = current->outline.n_contours; + FT_UInt n_base_points = base->outline.n_points; + FT_UInt n; + + + base->outline.n_points = + (short)( base->outline.n_points + current->outline.n_points ); + base->outline.n_contours = + (short)( base->outline.n_contours + current->outline.n_contours ); + + base->num_subglyphs += current->num_subglyphs; + + /* adjust contours count in newest outline */ + for ( n = 0; n < n_curr_contours; n++ ) + current->outline.contours[n] = + (short)( current->outline.contours[n] + n_base_points ); + + /* prepare for another new glyph image */ + FT_GlyphLoader_Prepare( loader ); + } + + + FT_BASE_DEF( FT_Error ) + FT_GlyphLoader_CopyPoints( FT_GlyphLoader target, + FT_GlyphLoader source ) + { + FT_Error error; + FT_UInt num_points = source->base.outline.n_points; + FT_UInt num_contours = source->base.outline.n_contours; + + + error = FT_GlyphLoader_CheckPoints( target, num_points, num_contours ); + if ( !error ) + { + FT_Outline* out = &target->base.outline; + FT_Outline* in = &source->base.outline; + + + FT_ARRAY_COPY( out->points, in->points, + num_points ); + FT_ARRAY_COPY( out->tags, in->tags, + num_points ); + FT_ARRAY_COPY( out->contours, in->contours, + num_contours ); + + /* do we need to copy the extra points? */ + if ( target->use_extra && source->use_extra ) + FT_ARRAY_COPY( target->base.extra_points, source->base.extra_points, + num_points ); + + out->n_points = (short)num_points; + out->n_contours = (short)num_contours; + + FT_GlyphLoader_Adjust_Points( target ); + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftglyph.c b/Utilities/vtkfreetype/src/base/ftglyph.c new file mode 100644 index 0000000..1b22ab6 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftglyph.c @@ -0,0 +1,712 @@ +/***************************************************************************/ +/* */ +/* ftglyph.c */ +/* */ +/* FreeType convenience functions to handle glyphs (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This file contains the definition of several convenience functions */ + /* that can be used by client applications to easily retrieve glyph */ + /* bitmaps and outlines from a given face. */ + /* */ + /* These functions should be optional if you are writing a font server */ + /* or text layout engine on top of FreeType. However, they are pretty */ + /* handy for many other simple uses of the library. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_INTERNAL_OBJECTS_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_glyph + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** Convenience functions ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( void ) + FT_Matrix_Multiply( const FT_Matrix* a, + FT_Matrix *b ) + { + FT_Fixed xx, xy, yx, yy; + + + if ( !a || !b ) + return; + + xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx ); + xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy ); + yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx ); + yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy ); + + b->xx = xx; b->xy = xy; + b->yx = yx; b->yy = yy; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Matrix_Invert( FT_Matrix* matrix ) + { + FT_Pos delta, xx, yy; + + + if ( !matrix ) + return FT_Err_Invalid_Argument; + + /* compute discriminant */ + delta = FT_MulFix( matrix->xx, matrix->yy ) - + FT_MulFix( matrix->xy, matrix->yx ); + + if ( !delta ) + return FT_Err_Invalid_Argument; /* matrix can't be inverted */ + + matrix->xy = - FT_DivFix( matrix->xy, delta ); + matrix->yx = - FT_DivFix( matrix->yx, delta ); + + xx = matrix->xx; + yy = matrix->yy; + + matrix->xx = FT_DivFix( yy, delta ); + matrix->yy = FT_DivFix( xx, delta ); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_BitmapGlyph support ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + static FT_Error + ft_bitmap_copy( FT_Memory memory, + FT_Bitmap* source, + FT_Bitmap* target ) + { + FT_Error error; + FT_Int pitch = source->pitch; + FT_ULong size; + + + *target = *source; + + if ( pitch < 0 ) + pitch = -pitch; + + size = (FT_ULong)( pitch * source->rows ); + + if ( !FT_ALLOC( target->buffer, size ) ) + FT_MEM_COPY( target->buffer, source->buffer, size ); + + return error; + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_bitmap_glyph_init( FT_Glyph bitmap_glyph, + FT_GlyphSlot slot ) + { + FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; + FT_Error error = FT_Err_Ok; + FT_Library library = FT_GLYPH( glyph )->library; + FT_Memory memory = library->memory; + + + if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) + { + error = FT_Err_Invalid_Glyph_Format; + goto Exit; + } + + /* grab the bitmap in the slot - do lazy copying whenever possible */ + glyph->bitmap = slot->bitmap; + glyph->left = slot->bitmap_left; + glyph->top = slot->bitmap_top; + + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + else + { + /* copy the bitmap into a new buffer */ + error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap ); + } + + Exit: + return error; + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_bitmap_glyph_copy( FT_Glyph bitmap_source, + FT_Glyph bitmap_target ) + { + FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source; + FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target; + FT_Memory memory = bitmap_source->library->memory; + + + target->left = source->left; + target->top = source->top; + + return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap ); + } + + + FT_CALLBACK_DEF( void ) + ft_bitmap_glyph_done( FT_Glyph bitmap_glyph ) + { + FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; + FT_Memory memory = FT_GLYPH( glyph )->library->memory; + + + FT_FREE( glyph->bitmap.buffer ); + } + + + FT_CALLBACK_DEF( void ) + ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph, + FT_BBox* cbox ) + { + FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; + + + cbox->xMin = glyph->left << 6; + cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 ); + cbox->yMax = glyph->top << 6; + cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 ); + } + + + FT_CALLBACK_TABLE_DEF + const FT_Glyph_Class ft_bitmap_glyph_class = + { + sizeof ( FT_BitmapGlyphRec ), + FT_GLYPH_FORMAT_BITMAP, + + ft_bitmap_glyph_init, + ft_bitmap_glyph_done, + ft_bitmap_glyph_copy, + 0, /* FT_Glyph_TransformFunc */ + ft_bitmap_glyph_bbox, + 0 /* FT_Glyph_PrepareFunc */ + }; + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_OutlineGlyph support ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_CALLBACK_DEF( FT_Error ) + ft_outline_glyph_init( FT_Glyph outline_glyph, + FT_GlyphSlot slot ) + { + FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; + FT_Error error = FT_Err_Ok; + FT_Library library = FT_GLYPH( glyph )->library; + FT_Outline* source = &slot->outline; + FT_Outline* target = &glyph->outline; + + + /* check format in glyph slot */ + if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) + { + error = FT_Err_Invalid_Glyph_Format; + goto Exit; + } + + /* allocate new outline */ + error = FT_Outline_New( library, source->n_points, source->n_contours, + &glyph->outline ); + if ( error ) + goto Exit; + + /* copy it */ + FT_ARRAY_COPY( target->points, source->points, source->n_points ); + + FT_ARRAY_COPY( target->tags, source->tags, source->n_points ); + + FT_ARRAY_COPY( target->contours, source->contours, source->n_contours ); + + /* copy all flags, except the `FT_OUTLINE_OWNER' one */ + target->flags = source->flags | FT_OUTLINE_OWNER; + + Exit: + return error; + } + + + FT_CALLBACK_DEF( void ) + ft_outline_glyph_done( FT_Glyph outline_glyph ) + { + FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; + + + FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline ); + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_outline_glyph_copy( FT_Glyph outline_source, + FT_Glyph outline_target ) + { + FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source; + FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target; + FT_Error error; + FT_Library library = FT_GLYPH( source )->library; + + + error = FT_Outline_New( library, source->outline.n_points, + source->outline.n_contours, &target->outline ); + if ( !error ) + FT_Outline_Copy( &source->outline, &target->outline ); + + return error; + } + + + FT_CALLBACK_DEF( void ) + ft_outline_glyph_transform( FT_Glyph outline_glyph, + FT_Matrix* matrix, + FT_Vector* delta ) + { + FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; + + + if ( matrix ) + FT_Outline_Transform( &glyph->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &glyph->outline, delta->x, delta->y ); + } + + + FT_CALLBACK_DEF( void ) + ft_outline_glyph_bbox( FT_Glyph outline_glyph, + FT_BBox* bbox ) + { + FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; + + + FT_Outline_Get_CBox( &glyph->outline, bbox ); + } + + + FT_CALLBACK_DEF( FT_Error ) + ft_outline_glyph_prepare( FT_Glyph outline_glyph, + FT_GlyphSlot slot ) + { + FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; + + + slot->format = FT_GLYPH_FORMAT_OUTLINE; + slot->outline = glyph->outline; + slot->outline.flags &= ~FT_OUTLINE_OWNER; + + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const FT_Glyph_Class ft_outline_glyph_class = + { + sizeof ( FT_OutlineGlyphRec ), + FT_GLYPH_FORMAT_OUTLINE, + + ft_outline_glyph_init, + ft_outline_glyph_done, + ft_outline_glyph_copy, + ft_outline_glyph_transform, + ft_outline_glyph_bbox, + ft_outline_glyph_prepare + }; + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_Glyph class and API ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + static FT_Error + ft_new_glyph( FT_Library library, + const FT_Glyph_Class* clazz, + FT_Glyph* aglyph ) + { + FT_Memory memory = library->memory; + FT_Error error; + FT_Glyph glyph; + + + *aglyph = 0; + + if ( !FT_ALLOC( glyph, clazz->glyph_size ) ) + { + glyph->library = library; + glyph->clazz = clazz; + glyph->format = clazz->glyph_format; + + *aglyph = glyph; + } + + return error; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Glyph_Copy( FT_Glyph source, + FT_Glyph *target ) + { + FT_Glyph copy; + FT_Error error; + const FT_Glyph_Class* clazz; + + + /* check arguments */ + if ( !target || !source || !source->clazz ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + *target = 0; + + clazz = source->clazz; + error = ft_new_glyph( source->library, clazz, © ); + if ( error ) + goto Exit; + + copy->advance = source->advance; + copy->format = source->format; + + if ( clazz->glyph_copy ) + error = clazz->glyph_copy( source, copy ); + + if ( error ) + FT_Done_Glyph( copy ); + else + *target = copy; + + Exit: + return error; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Glyph( FT_GlyphSlot slot, + FT_Glyph *aglyph ) + { + FT_Library library; + FT_Error error; + FT_Glyph glyph; + + const FT_Glyph_Class* clazz = 0; + + + if ( !slot ) + return FT_Err_Invalid_Slot_Handle; + + library = slot->library; + + if ( !aglyph ) + return FT_Err_Invalid_Argument; + + /* if it is a bitmap, that's easy :-) */ + if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) + clazz = &ft_bitmap_glyph_class; + + /* it it is an outline too */ + else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) + clazz = &ft_outline_glyph_class; + + else + { + /* try to find a renderer that supports the glyph image format */ + FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 ); + + + if ( render ) + clazz = &render->glyph_class; + } + + if ( !clazz ) + { + error = FT_Err_Invalid_Glyph_Format; + goto Exit; + } + + /* create FT_Glyph object */ + error = ft_new_glyph( library, clazz, &glyph ); + if ( error ) + goto Exit; + + /* copy advance while converting it to 16.16 format */ + glyph->advance.x = slot->advance.x << 10; + glyph->advance.y = slot->advance.y << 10; + + /* now import the image from the glyph slot */ + error = clazz->glyph_init( glyph, slot ); + + /* if an error occurred, destroy the glyph */ + if ( error ) + FT_Done_Glyph( glyph ); + else + *aglyph = glyph; + + Exit: + return error; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Glyph_Transform( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ) + { + const FT_Glyph_Class* clazz; + FT_Error error = FT_Err_Ok; + + + if ( !glyph || !glyph->clazz ) + error = FT_Err_Invalid_Argument; + else + { + clazz = glyph->clazz; + if ( clazz->glyph_transform ) + { + /* transform glyph image */ + clazz->glyph_transform( glyph, matrix, delta ); + + /* transform advance vector */ + if ( matrix ) + FT_Vector_Transform( &glyph->advance, matrix ); + } + else + error = FT_Err_Invalid_Glyph_Format; + } + return error; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( void ) + FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox *acbox ) + { + const FT_Glyph_Class* clazz; + + + if ( !acbox ) + return; + + acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0; + + if ( !glyph || !glyph->clazz ) + return; + else + { + clazz = glyph->clazz; + if ( !clazz->glyph_bbox ) + return; + else + { + /* retrieve bbox in 26.6 coordinates */ + clazz->glyph_bbox( glyph, acbox ); + + /* perform grid fitting if needed */ + if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT || + bbox_mode == FT_GLYPH_BBOX_PIXELS ) + { + acbox->xMin = FT_PIX_FLOOR( acbox->xMin ); + acbox->yMin = FT_PIX_FLOOR( acbox->yMin ); + acbox->xMax = FT_PIX_CEIL( acbox->xMax ); + acbox->yMax = FT_PIX_CEIL( acbox->yMax ); + } + + /* convert to integer pixels if needed */ + if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE || + bbox_mode == FT_GLYPH_BBOX_PIXELS ) + { + acbox->xMin >>= 6; + acbox->yMin >>= 6; + acbox->xMax >>= 6; + acbox->yMax >>= 6; + } + } + } + return; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_Render_Mode render_mode, + FT_Vector* origin, + FT_Bool destroy ) + { + FT_GlyphSlotRec dummy; + FT_GlyphSlot_InternalRec dummy_internal; + FT_Error error = FT_Err_Ok; + FT_Glyph glyph; + FT_BitmapGlyph bitmap = NULL; + + const FT_Glyph_Class* clazz; + + + /* check argument */ + if ( !the_glyph ) + goto Bad; + + /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ + /* then calling FT_Render_Glyph_Internal() */ + + glyph = *the_glyph; + if ( !glyph ) + goto Bad; + + clazz = glyph->clazz; + + /* when called with a bitmap glyph, do nothing and return successfully */ + if ( clazz == &ft_bitmap_glyph_class ) + goto Exit; + + if ( !clazz || !clazz->glyph_prepare ) + goto Bad; + + FT_MEM_ZERO( &dummy, sizeof ( dummy ) ); + FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) ); + dummy.internal = &dummy_internal; + dummy.library = glyph->library; + dummy.format = clazz->glyph_format; + + /* create result bitmap glyph */ + error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class, + (FT_Glyph*)&bitmap ); + if ( error ) + goto Exit; + +#if 1 + /* if `origin' is set, translate the glyph image */ + if ( origin ) + FT_Glyph_Transform( glyph, 0, origin ); +#else + FT_UNUSED( origin ); +#endif + + /* prepare dummy slot for rendering */ + error = clazz->glyph_prepare( glyph, &dummy ); + if ( !error ) + error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); + +#if 1 + if ( !destroy && origin ) + { + FT_Vector v; + + + v.x = -origin->x; + v.y = -origin->y; + FT_Glyph_Transform( glyph, 0, &v ); + } +#endif + + if ( error ) + goto Exit; + + /* in case of success, copy the bitmap to the glyph bitmap */ + error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy ); + if ( error ) + goto Exit; + + /* copy advance */ + bitmap->root.advance = glyph->advance; + + if ( destroy ) + FT_Done_Glyph( glyph ); + + *the_glyph = FT_GLYPH( bitmap ); + + Exit: + if ( error && bitmap ) + FT_Done_Glyph( FT_GLYPH( bitmap ) ); + + return error; + + Bad: + error = FT_Err_Invalid_Argument; + goto Exit; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( void ) + FT_Done_Glyph( FT_Glyph glyph ) + { + if ( glyph ) + { + FT_Memory memory = glyph->library->memory; + const FT_Glyph_Class* clazz = glyph->clazz; + + + if ( clazz->glyph_done ) + clazz->glyph_done( glyph ); + + FT_FREE( glyph ); + } + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftinit.c b/Utilities/vtkfreetype/src/base/ftinit.c new file mode 100644 index 0000000..79ba9f0 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftinit.c @@ -0,0 +1,161 @@ +/***************************************************************************/ +/* */ +/* ftinit.c */ +/* */ +/* FreeType initialization layer (body). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* The purpose of this file is to implement the following two */ + /* functions: */ + /* */ + /* FT_Add_Default_Modules(): */ + /* This function is used to add the set of default modules to a */ + /* fresh new library object. The set is taken from the header file */ + /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */ + /* Build System' for more information. */ + /* */ + /* FT_Init_FreeType(): */ + /* This function creates a system object for the current platform, */ + /* builds a library out of it, then calls FT_Default_Drivers(). */ + /* */ + /* Note that even if FT_Init_FreeType() uses the implementation of the */ + /* system object defined at build time, client applications are still */ + /* able to provide their own `ftsystem.c'. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include FT_MODULE_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_init + +#undef FT_USE_MODULE +#ifdef __cplusplus +#define FT_USE_MODULE( x ) extern "C" const FT_Module_Class* x; +#else +#define FT_USE_MODULE( x ) extern const FT_Module_Class* x; +#endif + + +#include FT_CONFIG_MODULES_H + + +#undef FT_USE_MODULE +#define FT_USE_MODULE( x ) (const FT_Module_Class*)&x, + + static + const FT_Module_Class* const ft_default_modules[] = + { +#include FT_CONFIG_MODULES_H + 0 + }; + + + /* documentation is in ftmodule.h */ + + FT_EXPORT_DEF( void ) + FT_Add_Default_Modules( FT_Library library ) + { + FT_Error error; + const FT_Module_Class* const* cur; + + + /* test for valid `library' delayed to FT_Add_Module() */ + + cur = ft_default_modules; + while ( *cur ) + { + error = FT_Add_Module( library, *cur ); + /* notify errors, but don't stop */ + if ( error ) + { + FT_ERROR(( "FT_Add_Default_Module: Cannot install `%s', error = 0x%x\n", + (*cur)->module_name, error )); + } + cur++; + } + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Init_FreeType( FT_Library *alibrary ) + { + FT_Error error; + FT_Memory memory; + + + /* First of all, allocate a new system object -- this function is part */ + /* of the system-specific component, i.e. `ftsystem.c'. */ + + memory = FT_New_Memory(); + if ( !memory ) + { + FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" )); + return FT_Err_Unimplemented_Feature; + } + + /* build a library out of it, then fill it with the set of */ + /* default drivers. */ + + error = FT_New_Library( memory, alibrary ); + if ( !error ) + { + (*alibrary)->version_major = FREETYPE_MAJOR; + (*alibrary)->version_minor = FREETYPE_MINOR; + (*alibrary)->version_patch = FREETYPE_PATCH; + + FT_Add_Default_Modules( *alibrary ); + } + + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Done_FreeType( FT_Library library ) + { + if ( library ) + { + FT_Memory memory = library->memory; + + + /* Discard the library object */ + FT_Done_Library( library ); + + /* discard memory manager */ + FT_Done_Memory( memory ); + } + + return FT_Err_Ok; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftmac.c b/Utilities/vtkfreetype/src/base/ftmac.c new file mode 100644 index 0000000..f3ae209 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftmac.c @@ -0,0 +1,1090 @@ +/***************************************************************************/ +/* */ +/* ftmac.c */ +/* */ +/* Mac FOND support. Written by just@letterror.com. */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /* + Notes + + Mac suitcase files can (and often do!) contain multiple fonts. To + support this I use the face_index argument of FT_(Open|New)_Face() + functions, and pretend the suitcase file is a collection. + + Warning: Although the FOND driver sets face->num_faces field to the + number of available fonts, but the Type 1 driver sets it to 1 anyway. + So this field is currently not reliable, and I don't see a clean way + to resolve that. The face_index argument translates to + + Get1IndResource( 'FOND', face_index + 1 ); + + so clients should figure out the resource index of the FOND. + (I'll try to provide some example code for this at some point.) + + The Mac FOND support works roughly like this: + + - Check whether the offered stream points to a Mac suitcase file. + This is done by checking the file type: it has to be 'FFIL' or 'tfil'. + The stream that gets passed to our init_face() routine is a stdio + stream, which isn't usable for us, since the FOND resources live + in the resource fork. So we just grab the stream->pathname field. + + - Read the FOND resource into memory, then check whether there is + a TrueType font and/or(!) a Type 1 font available. + + - If there is a Type 1 font available (as a separate 'LWFN' file), + read its data into memory, massage it slightly so it becomes + PFB data, wrap it into a memory stream, load the Type 1 driver + and delegate the rest of the work to it by calling FT_Open_Face(). + (XXX TODO: after this has been done, the kerning data from the FOND + resource should be appended to the face: On the Mac there are usually + no AFM files available. However, this is tricky since we need to map + Mac char codes to ps glyph names to glyph ID's...) + + - If there is a TrueType font (an 'sfnt' resource), read it into + memory, wrap it into a memory stream, load the TrueType driver + and delegate the rest of the work to it, by calling FT_Open_Face(). + */ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_INTERNAL_STREAM_H + +#if defined( __GNUC__ ) || defined( __IBMC__ ) + /* This is for Mac OS X. Without redefinition, OS_INLINE */ + /* expands to `static inline' which doesn't survive the */ + /* -ansi compilation flag of GCC. */ +#define OS_INLINE static __inline__ +#include <Carbon/Carbon.h> +#else +#include <Resources.h> +#include <Fonts.h> +#include <Errors.h> +#include <Files.h> +#include <TextUtils.h> +#endif + +#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO +#include <FSp_fopen.h> +#endif + +#include FT_MAC_H + + + /* Set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over + TrueType in case *both* are available (this is not common, + but it *is* possible). */ +#ifndef PREFER_LWFN +#define PREFER_LWFN 1 +#endif + + +#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO + +#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer ) + + + FT_CALLBACK_DEF( void ) + ft_FSp_stream_close( FT_Stream stream ) + { + fclose( STREAM_FILE( stream ) ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + FT_CALLBACK_DEF( unsigned long ) + ft_FSp_stream_io( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ) + { + FILE* file; + + + file = STREAM_FILE( stream ); + + fseek( file, offset, SEEK_SET ); + + return (unsigned long)fread( buffer, 1, count, file ); + } + +#endif /* __MWERKS__ && !TARGET_RT_MAC_MACHO */ + + + /* Given a pathname, fill in a file spec. */ + static int + file_spec_from_path( const char* pathname, + FSSpec* spec ) + { + +#if !TARGET_API_MAC_OS8 && \ + !( defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO ) + + OSErr e; + FSRef ref; + + + e = FSPathMakeRef( (UInt8 *)pathname, &ref, false /* not a directory */ ); + if ( e == noErr ) + e = FSGetCatalogInfo( &ref, kFSCatInfoNone, NULL, NULL, spec, NULL ); + + return ( e == noErr ) ? 0 : (-1); + +#else + + Str255 p_path; + FT_ULong path_len; + + + /* convert path to a pascal string */ + path_len = ft_strlen( pathname ); + if ( path_len > 255 ) + return -1; + p_path[0] = (unsigned char)path_len; + ft_strncpy( (char*)p_path + 1, pathname, path_len ); + + if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr ) + return -1; + else + return 0; + +#endif + + } + + + /* Return the file type of the file specified by spec. */ + static OSType + get_file_type( const FSSpec* spec ) + { + FInfo finfo; + + + if ( FSpGetFInfo( spec, &finfo ) != noErr ) + return 0; /* file might not exist */ + + return finfo.fdType; + } + + + /* Given a PostScript font name, create the Macintosh LWFN file name. */ + static void + create_lwfn_name( char* ps_name, + Str255 lwfn_file_name ) + { + int max = 5, count = 0; + FT_Byte* p = lwfn_file_name; + FT_Byte* q = (FT_Byte*)ps_name; + + + lwfn_file_name[0] = 0; + + while ( *q ) + { + if ( ft_isupper( *q ) ) + { + if ( count ) + max = 3; + count = 0; + } + if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) ) + { + *++p = *q; + lwfn_file_name[0]++; + count++; + } + q++; + } + } + + + /* Given a file reference, answer its location as a vRefNum + and a dirID. */ + static FT_Error + get_file_location( short ref_num, + short* v_ref_num, + long* dir_id, + unsigned char* file_name ) + { + FCBPBRec pb; + OSErr error; + + + pb.ioNamePtr = file_name; + pb.ioVRefNum = 0; + pb.ioRefNum = ref_num; + pb.ioFCBIndx = 0; + + error = PBGetFCBInfoSync( &pb ); + if ( error == noErr ) + { + *v_ref_num = pb.ioFCBVRefNum; + *dir_id = pb.ioFCBParID; + } + return error; + } + + + /* Make a file spec for an LWFN file from a FOND resource and + a file name. */ + static FT_Error + make_lwfn_spec( Handle fond, + const unsigned char* file_name, + FSSpec* spec ) + { + FT_Error error; + short ref_num, v_ref_num; + long dir_id; + Str255 fond_file_name; + + + ref_num = HomeResFile( fond ); + + error = ResError(); + if ( !error ) + error = get_file_location( ref_num, &v_ref_num, + &dir_id, fond_file_name ); + if ( !error ) + error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec ); + + return error; + } + + + static short + count_faces_sfnt( char *fond_data ) + { + /* The count is 1 greater than the value in the FOND. */ + /* Isn't that cute? :-) */ + + return 1 + *( (short *)( fond_data + sizeof ( FamRec ) ) ); + } + + + /* Look inside the FOND data, answer whether there should be an SFNT + resource, and answer the name of a possible LWFN Type 1 file. + + Thanks to Paul Miller (paulm@profoundeffects.com) for the fix + to load a face OTHER than the first one in the FOND! + */ + + + static void + parse_fond( char* fond_data, + short* have_sfnt, + short* sfnt_id, + Str255 lwfn_file_name, + short face_index ) + { + AsscEntry* assoc; + AsscEntry* base_assoc; + FamRec* fond; + + + *sfnt_id = 0; + *have_sfnt = 0; + lwfn_file_name[0] = 0; + + fond = (FamRec*)fond_data; + assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); + base_assoc = assoc; + + /* Let's do a little range checking before we get too excited here */ + if ( face_index < count_faces_sfnt( fond_data ) ) + { + assoc += face_index; /* add on the face_index! */ + + /* if the face at this index is not scalable, + fall back to the first one (old behavior) */ + if ( assoc->fontSize == 0 ) + { + *have_sfnt = 1; + *sfnt_id = assoc->fontID; + } + else if ( base_assoc->fontSize == 0 ) + { + *have_sfnt = 1; + *sfnt_id = base_assoc->fontID; + } + } + + if ( fond->ffStylOff ) + { + unsigned char* p = (unsigned char*)fond_data; + StyleTable* style; + unsigned short string_count; + char ps_name[256]; + unsigned char* names[64]; + int i; + + + p += fond->ffStylOff; + style = (StyleTable*)p; + p += sizeof ( StyleTable ); + string_count = *(unsigned short*)(p); + p += sizeof ( short ); + + for ( i = 0 ; i < string_count && i < 64; i++ ) + { + names[i] = p; + p += names[i][0]; + p++; + } + + { + size_t ps_name_len = (size_t)names[0][0]; + + + if ( ps_name_len != 0 ) + { + ft_memcpy(ps_name, names[0] + 1, ps_name_len); + ps_name[ps_name_len] = 0; + } + if ( style->indexes[0] > 1 ) + { + unsigned char* suffixes = names[style->indexes[0] - 1]; + + + for ( i = 1; i <= suffixes[0]; i++ ) + { + unsigned char* s; + size_t j = suffixes[i] - 1; + + + if ( j < string_count && ( s = names[j] ) != NULL ) + { + size_t s_len = (size_t)s[0]; + + + if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) ) + { + ft_memcpy( ps_name + ps_name_len, s + 1, s_len ); + ps_name_len += s_len; + ps_name[ps_name_len] = 0; + } + } + } + } + } + + create_lwfn_name( ps_name, lwfn_file_name ); + } + } + + + static short + count_faces( Handle fond ) + { + short sfnt_id, have_sfnt, have_lwfn = 0; + Str255 lwfn_file_name; + FSSpec lwfn_spec; + + + HLock( fond ); + parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, 0 ); + HUnlock( fond ); + + if ( lwfn_file_name[0] ) + { + if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok ) + have_lwfn = 1; /* yeah, we got one! */ + else + have_lwfn = 0; /* no LWFN file found */ + } + + if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) ) + return 1; + else + return count_faces_sfnt( *fond ); + } + + + /* Read Type 1 data from the POST resources inside the LWFN file, + return a PFB buffer. This is somewhat convoluted because the FT2 + PFB parser wants the ASCII header as one chunk, and the LWFN + chunks are often not organized that way, so we'll glue chunks + of the same type together. */ + static FT_Error + read_lwfn( FT_Memory memory, + short res_ref, + FT_Byte** pfb_data, + FT_ULong* size ) + { + FT_Error error = FT_Err_Ok; + short res_id; + unsigned char *buffer, *p, *size_p = NULL; + FT_ULong total_size = 0; + FT_ULong post_size, pfb_chunk_size; + Handle post_data; + char code, last_code; + + + UseResFile( res_ref ); + + /* First pass: load all POST resources, and determine the size of */ + /* the output buffer. */ + res_id = 501; + last_code = -1; + + for (;;) + { + post_data = Get1Resource( 'POST', res_id++ ); + if ( post_data == NULL ) + break; /* we're done */ + + code = (*post_data)[0]; + + if ( code != last_code ) + { + if ( code == 5 ) + total_size += 2; /* just the end code */ + else + total_size += 6; /* code + 4 bytes chunk length */ + } + + total_size += GetHandleSize( post_data ) - 2; + last_code = code; + } + + if ( FT_ALLOC( buffer, (FT_Long)total_size ) ) + goto Error; + + /* Second pass: append all POST data to the buffer, add PFB fields. */ + /* Glue all consecutive chunks of the same type together. */ + p = buffer; + res_id = 501; + last_code = -1; + pfb_chunk_size = 0; + + for (;;) + { + post_data = Get1Resource( 'POST', res_id++ ); + if ( post_data == NULL ) + break; /* we're done */ + + post_size = (FT_ULong)GetHandleSize( post_data ) - 2; + code = (*post_data)[0]; + + if ( code != last_code ) + { + if ( last_code != -1 ) + { + /* we're done adding a chunk, fill in the size field */ + if ( size_p != NULL ) + { + *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF ); + *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF ); + *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF ); + *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF ); + } + pfb_chunk_size = 0; + } + + *p++ = 0x80; + if ( code == 5 ) + *p++ = 0x03; /* the end */ + else if ( code == 2 ) + *p++ = 0x02; /* binary segment */ + else + *p++ = 0x01; /* ASCII segment */ + + if ( code != 5 ) + { + size_p = p; /* save for later */ + p += 4; /* make space for size field */ + } + } + + ft_memcpy( p, *post_data + 2, post_size ); + pfb_chunk_size += post_size; + p += post_size; + last_code = code; + } + + *pfb_data = buffer; + *size = total_size; + + Error: + CloseResFile( res_ref ); + return error; + } + + + /* Finalizer for a memory stream; gets called by FT_Done_Face(). + It frees the memory it uses. */ + static void + memory_stream_close( FT_Stream stream ) + { + FT_Memory memory = stream->memory; + + + FT_FREE( stream->base ); + + stream->size = 0; + stream->base = 0; + stream->close = 0; + } + + + /* Create a new memory stream from a buffer and a size. */ + static FT_Error + new_memory_stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream_CloseFunc close, + FT_Stream *astream ) + { + FT_Error error; + FT_Memory memory; + FT_Stream stream; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !base ) + return FT_Err_Invalid_Argument; + + *astream = 0; + memory = library->memory; + if ( FT_NEW( stream ) ) + goto Exit; + + FT_Stream_OpenMemory( stream, base, size ); + + stream->close = close; + + *astream = stream; + + Exit: + return error; + } + + + /* Create a new FT_Face given a buffer and a driver name. */ + static FT_Error + open_face_from_buffer( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Long face_index, + char* driver_name, + FT_Face *aface ) + { + FT_Open_Args args; + FT_Error error; + FT_Stream stream; + FT_Memory memory = library->memory; + + + error = new_memory_stream( library, + base, + size, + memory_stream_close, + &stream ); + if ( error ) + { + FT_FREE( base ); + return error; + } + + args.flags = FT_OPEN_STREAM; + args.stream = stream; + if ( driver_name ) + { + args.flags = args.flags | FT_OPEN_DRIVER; + args.driver = FT_Get_Module( library, driver_name ); + } + + /* At this point, face_index has served its purpose; */ + /* whoever calls this function has already used it to */ + /* locate the correct font data. We should not propagate */ + /* this index to FT_Open_Face() (unless it is negative). */ + + if ( face_index > 0 ) + face_index = 0; + + error = FT_Open_Face( library, &args, face_index, aface ); + if ( error == FT_Err_Ok ) + (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; + + return error; + } + + + static FT_Error + OpenFileAsResource( const FSSpec* spec, + short *p_res_ref ) + { + FT_Error error; + +#if !TARGET_API_MAC_OS8 + + FSRef hostContainerRef; + + + error = FSpMakeFSRef( spec, &hostContainerRef ); + if ( error == noErr ) + error = FSOpenResourceFile( &hostContainerRef, + 0, NULL, fsRdPerm, p_res_ref ); + + /* If the above fails, then it is probably not a resource file */ + /* However, it has been reported that FSOpenResourceFile() sometimes */ + /* fails on some old resource-fork files, which FSpOpenResFile() can */ + /* open. So, just try again with FSpOpenResFile() and see what */ + /* happens :-) */ + + if ( error != noErr ) + +#endif /* !TARGET_API_MAC_OS8 */ + + { + *p_res_ref = FSpOpenResFile( spec, fsRdPerm ); + error = ResError(); + } + + return error ? FT_Err_Cannot_Open_Resource : FT_Err_Ok; + } + + + /* Create a new FT_Face from a file spec to an LWFN file. */ + static FT_Error + FT_New_Face_From_LWFN( FT_Library library, + const FSSpec* lwfn_spec, + FT_Long face_index, + FT_Face *aface ) + { + FT_Byte* pfb_data; + FT_ULong pfb_size; + FT_Error error; + short res_ref; + + + error = OpenFileAsResource( lwfn_spec, &res_ref ); + if ( error ) + return error; + + error = read_lwfn( library->memory, res_ref, &pfb_data, &pfb_size ); + if ( error ) + return error; + + return open_face_from_buffer( library, + pfb_data, + pfb_size, + face_index, + "type1", + aface ); + } + + + /* Create a new FT_Face from an SFNT resource, specified by res ID. */ + static FT_Error + FT_New_Face_From_SFNT( FT_Library library, + short sfnt_id, + FT_Long face_index, + FT_Face *aface ) + { + Handle sfnt = NULL; + FT_Byte* sfnt_data; + size_t sfnt_size; + FT_Error error = 0; + FT_Memory memory = library->memory; + int is_cff; + + + sfnt = GetResource( 'sfnt', sfnt_id ); + if ( ResError() ) + return FT_Err_Invalid_Handle; + + sfnt_size = (FT_ULong)GetHandleSize( sfnt ); + if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) ) + { + ReleaseResource( sfnt ); + return error; + } + + HLock( sfnt ); + ft_memcpy( sfnt_data, *sfnt, sfnt_size ); + HUnlock( sfnt ); + ReleaseResource( sfnt ); + + is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' && + sfnt_data[1] == 'T' && + sfnt_data[2] == 'T' && + sfnt_data[3] == 'O'; + + return open_face_from_buffer( library, + sfnt_data, + sfnt_size, + face_index, + is_cff ? "cff" : "truetype", + aface ); + } + + + /* Create a new FT_Face from a file spec to a suitcase file. */ + static FT_Error + FT_New_Face_From_Suitcase( FT_Library library, + short res_ref, + FT_Long face_index, + FT_Face *aface ) + { + FT_Error error = FT_Err_Ok; + short res_index; + Handle fond; + short num_faces; + + + UseResFile( res_ref ); + + for ( res_index = 1; ; ++res_index ) + { + fond = Get1IndResource( 'FOND', res_index ); + if ( ResError() ) + { + error = FT_Err_Cannot_Open_Resource; + goto Error; + } + if ( face_index < 0 ) + break; + + num_faces = count_faces( fond ); + if ( face_index < num_faces ) + break; + + face_index -= num_faces; + } + + error = FT_New_Face_From_FOND( library, fond, face_index, aface ); + + Error: + CloseResFile( res_ref ); + return error; + } + + + /* documentation is in ftmac.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_New_Face_From_FOND( FT_Library library, + Handle fond, + FT_Long face_index, + FT_Face *aface ) + { + short sfnt_id, have_sfnt, have_lwfn = 0; + Str255 lwfn_file_name; + short fond_id; + OSType fond_type; + Str255 fond_name; + FSSpec lwfn_spec; + + + GetResInfo( fond, &fond_id, &fond_type, fond_name ); + if ( ResError() != noErr || fond_type != 'FOND' ) + return FT_Err_Invalid_File_Format; + + HLock( fond ); + parse_fond( *fond, &have_sfnt, &sfnt_id, lwfn_file_name, face_index ); + HUnlock( fond ); + + if ( lwfn_file_name[0] ) + { + if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok ) + have_lwfn = 1; /* yeah, we got one! */ + else + have_lwfn = 0; /* no LWFN file found */ + } + + if ( have_lwfn && ( !have_sfnt || PREFER_LWFN ) ) + return FT_New_Face_From_LWFN( library, + &lwfn_spec, + face_index, + aface ); + else if ( have_sfnt ) + return FT_New_Face_From_SFNT( library, + sfnt_id, + face_index, + aface ); + + return FT_Err_Unknown_File_Format; + } + + + /* documentation is in ftmac.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_GetFile_From_Mac_Name( const char* fontName, + FSSpec* pathSpec, + FT_Long* face_index ) + { + OptionBits options = kFMUseGlobalScopeOption; + + FMFontFamilyIterator famIter; + OSStatus status = FMCreateFontFamilyIterator( NULL, NULL, + options, + &famIter ); + FMFont the_font = 0; + FMFontFamily family = 0; + + + *face_index = 0; + while ( status == 0 && !the_font ) + { + status = FMGetNextFontFamily( &famIter, &family ); + if ( status == 0 ) + { + int stat2; + FMFontFamilyInstanceIterator instIter; + Str255 famNameStr; + char famName[256]; + + + /* get the family name */ + FMGetFontFamilyName( family, famNameStr ); + CopyPascalStringToC( famNameStr, famName ); + + /* iterate through the styles */ + FMCreateFontFamilyInstanceIterator( family, &instIter ); + + *face_index = 0; + stat2 = 0; + while ( stat2 == 0 && !the_font ) + { + FMFontStyle style; + FMFontSize size; + FMFont font; + + + stat2 = FMGetNextFontFamilyInstance( &instIter, &font, + &style, &size ); + if ( stat2 == 0 && size == 0 ) + { + char fullName[256]; + + + /* build up a complete face name */ + ft_strcpy( fullName, famName ); + if ( style & bold ) + strcat( fullName, " Bold" ); + if ( style & italic ) + strcat( fullName, " Italic" ); + + /* compare with the name we are looking for */ + if ( ft_strcmp( fullName, fontName ) == 0 ) + { + /* found it! */ + the_font = font; + } + else + ++(*face_index); + } + } + + FMDisposeFontFamilyInstanceIterator( &instIter ); + } + } + + FMDisposeFontFamilyIterator( &famIter ); + + if ( the_font ) + { + FMGetFontContainer( the_font, pathSpec ); + return FT_Err_Ok; + } + else + return FT_Err_Unknown_File_Format; + } + + /* Common function to load a new FT_Face from a resource file. */ + + static FT_Error + FT_New_Face_From_Resource( FT_Library library, + const FSSpec *spec, + FT_Long face_index, + FT_Face *aface ) + { + OSType file_type; + short res_ref; + FT_Error error; + + + if ( OpenFileAsResource( spec, &res_ref ) == FT_Err_Ok ) + { + /* LWFN is a (very) specific file format, check for it explicitly */ + + file_type = get_file_type( spec ); + if ( file_type == 'LWFN' ) + return FT_New_Face_From_LWFN( library, spec, face_index, aface ); + + /* Otherwise the file type doesn't matter (there are more than */ + /* `FFIL' and `tfil'). Just try opening it as a font suitcase; */ + /* if it works, fine. */ + + error = FT_New_Face_From_Suitcase( library, res_ref, + face_index, aface ); + if ( error == 0 ) + return error; + + /* else forget about the resource fork and fall through to */ + /* data fork formats */ + + CloseResFile( res_ref ); + } + + /* let it fall through to normal loader (.ttf, .otf, etc.); */ + /* we signal this by returning no error and no FT_Face */ + *aface = NULL; + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face */ + /* */ + /* <Description> */ + /* This is the Mac-specific implementation of FT_New_Face. In */ + /* addition to the standard FT_New_Face() functionality, it also */ + /* accepts pathnames to Mac suitcase files. For further */ + /* documentation see the original FT_New_Face() in freetype.h. */ + /* */ + FT_EXPORT_DEF( FT_Error ) + FT_New_Face( FT_Library library, + const char* pathname, + FT_Long face_index, + FT_Face *aface ) + { + FT_Open_Args args; + FSSpec spec; + FT_Error error; + + + /* test for valid `library' and `aface' delayed to FT_Open_Face() */ + if ( !pathname ) + return FT_Err_Invalid_Argument; + + if ( file_spec_from_path( pathname, &spec ) ) + return FT_Err_Invalid_Argument; + + error = FT_New_Face_From_Resource( library, &spec, face_index, aface ); + if ( error != 0 || *aface != NULL ) + return error; + + /* let it fall through to normal loader (.ttf, .otf, etc.) */ + args.flags = FT_OPEN_PATHNAME; + args.pathname = (char*)pathname; + return FT_Open_Face( library, &args, face_index, aface ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_New_Face_From_FSSpec */ + /* */ + /* <Description> */ + /* FT_New_Face_From_FSSpec is identical to FT_New_Face except it */ + /* accepts an FSSpec instead of a path. */ + /* */ + FT_EXPORT_DEF( FT_Error ) + FT_New_Face_From_FSSpec( FT_Library library, + const FSSpec *spec, + FT_Long face_index, + FT_Face *aface ) + { +#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO + FT_Open_Args args; + FT_Stream stream; + FILE* file; + FT_Memory memory; +#endif + FT_Error error; + + + /* test for valid `library' and `aface' delayed to FT_Open_Face() */ + if ( !spec ) + return FT_Err_Invalid_Argument; + + error = FT_New_Face_From_Resource( library, spec, face_index, aface ); + if ( error != 0 || *aface != NULL ) + return error; + + /* let it fall through to normal loader (.ttf, .otf, etc.) */ + +#if defined( __MWERKS__ ) && !TARGET_RT_MAC_MACHO + + /* Codewarrior's C library can open a FILE from a FSSpec */ + /* but we must compile with FSp_fopen.c in addition to */ + /* runtime libraries. */ + + memory = library->memory; + + if ( FT_NEW( stream ) ) + return error; + stream->memory = memory; + + file = FSp_fopen( spec, "rb" ); + if ( !file ) + return FT_Err_Cannot_Open_Resource; + + fseek( file, 0, SEEK_END ); + stream->size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + stream->descriptor.pointer = file; + stream->pathname.pointer = NULL; + stream->pos = 0; + + stream->read = ft_FSp_stream_io; + stream->close = ft_FSp_stream_close; + + args.flags = FT_OPEN_STREAM; + args.stream = stream; + + error = FT_Open_Face( library, &args, face_index, aface ); + if ( error == FT_Err_Ok ) + (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; + +#else /* !(__MWERKS__ && !TARGET_RT_MAC_MACHO) */ + + { + FSRef ref; + UInt8 path[256]; + OSErr err; + + + err = FSpMakeFSRef(spec, &ref); + if ( !err ) + { + err = FSRefMakePath( &ref, path, sizeof ( path ) ); + if ( !err ) + error = FT_New_Face( library, (const char*)path, + face_index, aface ); + } + if ( err ) + error = FT_Err_Cannot_Open_Resource; + } + +#endif /* !(__MWERKS__ && !TARGET_RT_MAC_MACHO) */ + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftmm.c b/Utilities/vtkfreetype/src/base/ftmm.c new file mode 100644 index 0000000..940f864 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftmm.c @@ -0,0 +1,202 @@ +/***************************************************************************/ +/* */ +/* ftmm.c */ +/* */ +/* Multiple Master font support (body). */ +/* */ +/* Copyright 1996-2001, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_MULTIPLE_MASTERS_H +#include FT_INTERNAL_OBJECTS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_mm + + + static FT_Error + ft_face_get_mm_service( FT_Face face, + FT_Service_MultiMasters *aservice ) + { + FT_Error error; + + + *aservice = NULL; + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + error = FT_Err_Invalid_Argument; + + if ( FT_HAS_MULTIPLE_MASTERS( face ) ) + { + FT_FACE_LOOKUP_SERVICE( face, + *aservice, + MULTI_MASTERS ); + + if ( aservice ) + error = FT_Err_Ok; + } + + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master *amaster ) + { + FT_Error error; + FT_Service_MultiMasters service; + + + error = ft_face_get_mm_service( face, &service ); + if ( !error ) + { + error = FT_Err_Invalid_Argument; + if ( service->get_mm ) + error = service->get_mm( face, amaster ); + } + + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_MM_Var( FT_Face face, + FT_MM_Var* *amaster ) + { + FT_Error error; + FT_Service_MultiMasters service; + + + error = ft_face_get_mm_service( face, &service ); + if ( !error ) + { + error = FT_Err_Invalid_Argument; + if ( service->get_mm_var ) + error = service->get_mm_var( face, amaster ); + } + + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_MM_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ) + { + FT_Error error; + FT_Service_MultiMasters service; + + + error = ft_face_get_mm_service( face, &service ); + if ( !error ) + { + error = FT_Err_Invalid_Argument; + if ( service->set_mm_design ) + error = service->set_mm_design( face, num_coords, coords ); + } + + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_Var_Design_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error; + FT_Service_MultiMasters service; + + + error = ft_face_get_mm_service( face, &service ); + if ( !error ) + { + error = FT_Err_Invalid_Argument; + if ( service->set_var_design ) + error = service->set_var_design( face, num_coords, coords ); + } + + return error; + } + + + /* documentation is in ftmm.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_MM_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error; + FT_Service_MultiMasters service; + + + error = ft_face_get_mm_service( face, &service ); + if ( !error ) + { + error = FT_Err_Invalid_Argument; + if ( service->set_mm_blend ) + error = service->set_mm_blend( face, num_coords, coords ); + } + + return error; + } + + + /* documentation is in ftmm.h */ + + /* This is exactly the same as the previous function. It exists for */ + /* orthogonality. */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_Var_Blend_Coordinates( FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error; + FT_Service_MultiMasters service; + + + error = ft_face_get_mm_service( face, &service ); + if ( !error ) + { + error = FT_Err_Invalid_Argument; + if ( service->set_mm_blend ) + error = service->set_mm_blend( face, num_coords, coords ); + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftnames.c b/Utilities/vtkfreetype/src/base/ftnames.c new file mode 100644 index 0000000..7fde5c4 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftnames.c @@ -0,0 +1,94 @@ +/***************************************************************************/ +/* */ +/* ftnames.c */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.) (body). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_SFNT_NAMES_H +#include FT_INTERNAL_TRUETYPE_TYPES_H +#include FT_INTERNAL_STREAM_H + + +#ifdef TT_CONFIG_OPTION_SFNT_NAMES + + + /* documentation is in ftnames.h */ + + FT_EXPORT_DEF( FT_UInt ) + FT_Get_Sfnt_Name_Count( FT_Face face ) + { + return (face && FT_IS_SFNT( face )) ? ((TT_Face)face)->num_names : 0; + } + + + /* documentation is in ftnames.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Sfnt_Name( FT_Face face, + FT_UInt idx, + FT_SfntName *aname ) + { + FT_Error error = FT_Err_Invalid_Argument; + + + if ( aname && face && FT_IS_SFNT( face ) ) + { + TT_Face ttface = (TT_Face)face; + + + if ( idx < (FT_UInt)ttface->num_names ) + { + TT_NameEntryRec* entry = ttface->name_table.names + idx; + + + /* load name on demand */ + if ( entry->stringLength > 0 && entry->string == NULL ) + { + FT_Memory memory = face->memory; + FT_Stream stream = face->stream; + + + if ( FT_NEW_ARRAY ( entry->string, entry->stringLength ) || + FT_STREAM_SEEK( entry->stringOffset ) || + FT_STREAM_READ( entry->string, entry->stringLength ) ) + { + FT_FREE( entry->string ); + entry->stringLength = 0; + } + } + + aname->platform_id = entry->platformID; + aname->encoding_id = entry->encodingID; + aname->language_id = entry->languageID; + aname->name_id = entry->nameID; + aname->string = (FT_Byte*)entry->string; + aname->string_len = entry->stringLength; + + error = FT_Err_Ok; + } + } + + return error; + } + + +#endif /* TT_CONFIG_OPTION_SFNT_NAMES */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftobjs.c b/Utilities/vtkfreetype/src/base/ftobjs.c new file mode 100644 index 0000000..931c856 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftobjs.c @@ -0,0 +1,3333 @@ +/***************************************************************************/ +/* */ +/* ftobjs.c */ +/* */ +/* The FreeType private base classes (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_LIST_H +#include FT_OUTLINE_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_RFORK_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */ +#include FT_TRUETYPE_TABLES_H +#include FT_TRUETYPE_IDS_H +#include FT_OUTLINE_H + +#include FT_SERVICE_SFNT_H +#include FT_SERVICE_POSTSCRIPT_NAME_H +#include FT_SERVICE_GLYPH_DICT_H +#include FT_SERVICE_TT_CMAP_H + + + FT_BASE_DEF( FT_Pointer ) + ft_service_list_lookup( FT_ServiceDesc service_descriptors, + const char* service_id ) + { + FT_Pointer result = NULL; + FT_ServiceDesc desc = service_descriptors; + + + if ( desc && service_id ) + { + for ( ; desc->serv_id != NULL; desc++ ) + { + if ( ft_strcmp( desc->serv_id, service_id ) == 0 ) + { + result = (FT_Pointer)desc->serv_data; + break; + } + } + } + + return result; + } + + + FT_BASE_DEF( void ) + ft_validator_init( FT_Validator valid, + const FT_Byte* base, + const FT_Byte* limit, + FT_ValidationLevel level ) + { + valid->base = base; + valid->limit = limit; + valid->level = level; + valid->error = 0; + } + + + FT_BASE_DEF( FT_Int ) + ft_validator_run( FT_Validator valid ) + { + int result; + + + result = ft_setjmp( valid->jump_buffer ); + return result; + } + + + FT_BASE_DEF( void ) + ft_validator_error( FT_Validator valid, + FT_Error error ) + { + valid->error = error; + ft_longjmp( valid->jump_buffer, 1 ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** S T R E A M ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* create a new input stream from an FT_Open_Args structure */ + /* */ + FT_BASE_DEF( FT_Error ) + FT_Stream_New( FT_Library library, + const FT_Open_Args* args, + FT_Stream *astream ) + { + FT_Error error; + FT_Memory memory; + FT_Stream stream; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !args ) + return FT_Err_Invalid_Argument; + + *astream = 0; + memory = library->memory; + + if ( FT_NEW( stream ) ) + goto Exit; + + stream->memory = memory; + + if ( args->flags & FT_OPEN_MEMORY ) + { + /* create a memory-based stream */ + FT_Stream_OpenMemory( stream, + (const FT_Byte*)args->memory_base, + args->memory_size ); + } + else if ( args->flags & FT_OPEN_PATHNAME ) + { + /* create a normal system stream */ + error = FT_Stream_Open( stream, args->pathname ); + stream->pathname.pointer = args->pathname; + } + else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream ) + { + /* use an existing, user-provided stream */ + + /* in this case, we do not need to allocate a new stream object */ + /* since the caller is responsible for closing it himself */ + FT_FREE( stream ); + stream = args->stream; + } + else + error = FT_Err_Invalid_Argument; + + if ( error ) + FT_FREE( stream ); + else + stream->memory = memory; /* just to be certain */ + + *astream = stream; + + Exit: + return error; + } + + + FT_BASE_DEF( void ) + FT_Stream_Free( FT_Stream stream, + FT_Int external ) + { + if ( stream ) + { + FT_Memory memory = stream->memory; + + + FT_Stream_Close( stream ); + + if ( !external ) + FT_FREE( stream ); + } + } + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_objs + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static FT_Error + ft_glyphslot_init( FT_GlyphSlot slot ) + { + FT_Driver driver = slot->face->driver; + FT_Driver_Class clazz = driver->clazz; + FT_Memory memory = driver->root.memory; + FT_Error error = FT_Err_Ok; + FT_Slot_Internal internal; + + + slot->library = driver->root.library; + + if ( FT_NEW( internal ) ) + goto Exit; + + slot->internal = internal; + + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + error = FT_GlyphLoader_New( memory, &internal->loader ); + + if ( !error && clazz->init_slot ) + error = clazz->init_slot( slot ); + + Exit: + return error; + } + + + FT_BASE_DEF( void ) + ft_glyphslot_free_bitmap( FT_GlyphSlot slot ) + { + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_Memory memory = FT_FACE_MEMORY( slot->face ); + + + FT_FREE( slot->bitmap.buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + else + { + /* assume that the bitmap buffer was stolen or not */ + /* allocated from the heap */ + slot->bitmap.buffer = NULL; + } + } + + + FT_BASE_DEF( void ) + ft_glyphslot_set_bitmap( FT_GlyphSlot slot, + FT_Byte* buffer ) + { + ft_glyphslot_free_bitmap( slot ); + + slot->bitmap.buffer = buffer; + + FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 ); + } + + + FT_BASE_DEF( FT_Error ) + ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot, + FT_ULong size ) + { + FT_Memory memory = FT_FACE_MEMORY( slot->face ); + + + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + FT_FREE( slot->bitmap.buffer ); + else + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + return FT_MEM_ALLOC( slot->bitmap.buffer, size ); + } + + + static void + ft_glyphslot_clear( FT_GlyphSlot slot ) + { + /* free bitmap if needed */ + ft_glyphslot_free_bitmap( slot ); + + /* clear all public fields in the glyph slot */ + FT_ZERO( &slot->metrics ); + FT_ZERO( &slot->outline ); + + slot->bitmap.width = 0; + slot->bitmap.rows = 0; + slot->bitmap.pitch = 0; + slot->bitmap.pixel_mode = 0; + /* don't touch 'slot->bitmap.buffer'! */ + + slot->bitmap_left = 0; + slot->bitmap_top = 0; + slot->num_subglyphs = 0; + slot->subglyphs = 0; + slot->control_data = 0; + slot->control_len = 0; + slot->other = 0; + slot->format = FT_GLYPH_FORMAT_NONE; + + slot->linearHoriAdvance = 0; + slot->linearVertAdvance = 0; + } + + + static void + ft_glyphslot_done( FT_GlyphSlot slot ) + { + FT_Driver driver = slot->face->driver; + FT_Driver_Class clazz = driver->clazz; + FT_Memory memory = driver->root.memory; + + + if ( clazz->done_slot ) + clazz->done_slot( slot ); + + /* free bitmap buffer if needed */ + ft_glyphslot_free_bitmap( slot ); + + /* free glyph loader */ + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + { + FT_GlyphLoader_Done( slot->internal->loader ); + slot->internal->loader = 0; + } + + FT_FREE( slot->internal ); + } + + + /* documentation is in ftobjs.h */ + + FT_BASE_DEF( FT_Error ) + FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot *aslot ) + { + FT_Error error; + FT_Driver driver; + FT_Driver_Class clazz; + FT_Memory memory; + FT_GlyphSlot slot; + + + if ( !face || !aslot || !face->driver ) + return FT_Err_Invalid_Argument; + + *aslot = 0; + + driver = face->driver; + clazz = driver->clazz; + memory = driver->root.memory; + + FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" )); + if ( !FT_ALLOC( slot, clazz->slot_object_size ) ) + { + slot->face = face; + + error = ft_glyphslot_init( slot ); + if ( error ) + { + ft_glyphslot_done( slot ); + FT_FREE( slot ); + goto Exit; + } + + *aslot = slot; + } + + Exit: + FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); + return error; + } + + + /* documentation is in ftobjs.h */ + + FT_BASE_DEF( void ) + FT_Done_GlyphSlot( FT_GlyphSlot slot ) + { + if ( slot ) + { + FT_Driver driver = slot->face->driver; + FT_Memory memory = driver->root.memory; + FT_GlyphSlot* parent; + FT_GlyphSlot cur; + + + /* Remove slot from its parent face's list */ + parent = &slot->face->glyph; + cur = *parent; + + while ( cur ) + { + if ( cur == slot ) + { + *parent = cur->next; + ft_glyphslot_done( slot ); + FT_FREE( slot ); + break; + } + cur = cur->next; + } + } + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( void ) + FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ) + { + FT_Face_Internal internal; + + + if ( !face ) + return; + + internal = face->internal; + + internal->transform_flags = 0; + + if ( !matrix ) + { + internal->transform_matrix.xx = 0x10000L; + internal->transform_matrix.xy = 0; + internal->transform_matrix.yx = 0; + internal->transform_matrix.yy = 0x10000L; + matrix = &internal->transform_matrix; + } + else + internal->transform_matrix = *matrix; + + /* set transform_flags bit flag 0 if `matrix' isn't the identity */ + if ( ( matrix->xy | matrix->yx ) || + matrix->xx != 0x10000L || + matrix->yy != 0x10000L ) + internal->transform_flags |= 1; + + if ( !delta ) + { + internal->transform_delta.x = 0; + internal->transform_delta.y = 0; + delta = &internal->transform_delta; + } + else + internal->transform_delta = *delta; + + /* set transform_flags bit flag 1 if `delta' isn't the null vector */ + if ( delta->x | delta->y ) + internal->transform_flags |= 2; + } + + + static FT_Renderer + ft_lookup_glyph_renderer( FT_GlyphSlot slot ); + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + FT_Error error; + FT_Driver driver; + FT_GlyphSlot slot; + FT_Library library; + FT_Bool autohint; + FT_Module hinter; + + + if ( !face || !face->size || !face->glyph ) + return FT_Err_Invalid_Face_Handle; + + if ( glyph_index >= (FT_UInt)face->num_glyphs ) + return FT_Err_Invalid_Argument; + + slot = face->glyph; + ft_glyphslot_clear( slot ); + + driver = face->driver; + + /* if the flag NO_RECURSE is set, we disable hinting and scaling */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + /* disable scaling, hinting, and transformation */ + load_flags |= FT_LOAD_NO_SCALE | + FT_LOAD_NO_HINTING | + FT_LOAD_NO_BITMAP | + FT_LOAD_IGNORE_TRANSFORM; + + /* disable bitmap rendering */ + load_flags &= ~FT_LOAD_RENDER; + } + + /* do we need to load the glyph through the auto-hinter? */ + library = driver->root.library; + hinter = library->auto_hinter; + autohint = + FT_BOOL( hinter && + !( load_flags & ( FT_LOAD_NO_SCALE | + FT_LOAD_NO_HINTING | + FT_LOAD_NO_AUTOHINT ) ) && + FT_DRIVER_IS_SCALABLE( driver ) && + FT_DRIVER_USES_OUTLINES( driver ) ); + if ( autohint ) + { + if ( FT_DRIVER_HAS_HINTER( driver ) && + !( load_flags & FT_LOAD_FORCE_AUTOHINT ) ) + autohint = 0; + } + + /* don't apply autohinting if glyph is vertically distorted or */ + /* mirrored */ + if ( autohint && !( face->internal->transform_matrix.yy <= 0 || + face->internal->transform_matrix.yx != 0 ) ) + { + FT_AutoHinter_Service hinting; + + + /* try to load embedded bitmaps first if available */ + /* */ + /* XXX: This is really a temporary hack that should disappear */ + /* promptly with FreeType 2.1! */ + /* */ + if ( FT_HAS_FIXED_SIZES( face ) && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) + { + error = driver->clazz->load_glyph( slot, face->size, + glyph_index, + load_flags | FT_LOAD_SBITS_ONLY ); + + if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP ) + goto Load_Ok; + } + + /* load auto-hinted outline */ + hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface; + + error = hinting->load_glyph( (FT_AutoHinter)hinter, + slot, face->size, + glyph_index, load_flags ); + } + else + { + error = driver->clazz->load_glyph( slot, + face->size, + glyph_index, + load_flags ); + if ( error ) + goto Exit; + + /* check that the loaded outline is correct */ + error = FT_Outline_Check( &slot->outline ); + if ( error ) + goto Exit; + } + + Load_Ok: + /* compute the advance */ + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + slot->advance.x = 0; + slot->advance.y = slot->metrics.vertAdvance; + } + else + { + slot->advance.x = slot->metrics.horiAdvance; + slot->advance.y = 0; + } + + /* compute the linear advance in 16.16 pixels */ + if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 && + ( face->face_flags & FT_FACE_FLAG_SCALABLE ) ) + { + FT_Size_Metrics* metrics = &face->size->metrics; + + + slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance, + metrics->x_scale, 64 ); + + slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance, + metrics->y_scale, 64 ); + } + + if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 ) + { + FT_Face_Internal internal = face->internal; + + + /* now, transform the glyph image if needed */ + if ( internal->transform_flags ) + { + /* get renderer */ + FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); + + + if ( renderer ) + error = renderer->clazz->transform_glyph( + renderer, slot, + &internal->transform_matrix, + &internal->transform_delta ); + /* transform advance */ + FT_Vector_Transform( &slot->advance, &internal->transform_matrix ); + } + } + + /* do we need to render the image now? */ + if ( !error && + slot->format != FT_GLYPH_FORMAT_BITMAP && + slot->format != FT_GLYPH_FORMAT_COMPOSITE && + load_flags & FT_LOAD_RENDER ) + { + FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags ); + + + if ( mode == FT_RENDER_MODE_NORMAL && + (load_flags & FT_LOAD_MONOCHROME ) ) + mode = FT_RENDER_MODE_MONO; + + error = FT_Render_Glyph( slot, mode ); + } + + Exit: + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int32 load_flags ) + { + FT_UInt glyph_index; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + glyph_index = (FT_UInt)char_code; + if ( face->charmap ) + glyph_index = FT_Get_Char_Index( face, char_code ); + + return FT_Load_Glyph( face, glyph_index, load_flags ); + } + + + /* destructor for sizes list */ + static void + destroy_size( FT_Memory memory, + FT_Size size, + FT_Driver driver ) + { + /* finalize client-specific data */ + if ( size->generic.finalizer ) + size->generic.finalizer( size ); + + /* finalize format-specific stuff */ + if ( driver->clazz->done_size ) + driver->clazz->done_size( size ); + + FT_FREE( size->internal ); + FT_FREE( size ); + } + + + static void + destroy_charmaps( FT_Face face, + FT_Memory memory ) + { + FT_Int n; + + + for ( n = 0; n < face->num_charmaps; n++ ) + { + FT_CMap cmap = FT_CMAP( face->charmaps[n] ); + + + FT_CMap_Done( cmap ); + + face->charmaps[n] = NULL; + } + + FT_FREE( face->charmaps ); + face->num_charmaps = 0; + } + + + /* destructor for faces list */ + static void + destroy_face( FT_Memory memory, + FT_Face face, + FT_Driver driver ) + { + FT_Driver_Class clazz = driver->clazz; + + + /* discard auto-hinting data */ + if ( face->autohint.finalizer ) + face->autohint.finalizer( face->autohint.data ); + + /* Discard glyph slots for this face. */ + /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */ + while ( face->glyph ) + FT_Done_GlyphSlot( face->glyph ); + + /* discard all sizes for this face */ + FT_List_Finalize( &face->sizes_list, + (FT_List_Destructor)destroy_size, + memory, + driver ); + face->size = 0; + + /* now discard client data */ + if ( face->generic.finalizer ) + face->generic.finalizer( face ); + + /* discard charmaps */ + destroy_charmaps( face, memory ); + + /* finalize format-specific stuff */ + if ( clazz->done_face ) + clazz->done_face( face ); + + /* close the stream for this face if needed */ + FT_Stream_Free( + face->stream, + ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); + + face->stream = 0; + + /* get rid of it */ + if ( face->internal ) + { + FT_FREE( face->internal ); + } + FT_FREE( face ); + } + + + static void + Destroy_Driver( FT_Driver driver ) + { + FT_List_Finalize( &driver->faces_list, + (FT_List_Destructor)destroy_face, + driver->root.memory, + driver ); + + /* check whether we need to drop the driver's glyph loader */ + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + FT_GlyphLoader_Done( driver->glyph_loader ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* find_unicode_charmap */ + /* */ + /* <Description> */ + /* This function finds a Unicode charmap, if there is one. */ + /* And if there is more than one, it tries to favour the more */ + /* extensive one, i.e., one that supports UCS-4 against those which */ + /* are limited to the BMP (said UCS-2 encoding.) */ + /* */ + /* This function is called from open_face() (just below), and also */ + /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE). */ + /* */ + static FT_Error + find_unicode_charmap( FT_Face face ) + { + FT_CharMap* first; + FT_CharMap* cur; + FT_CharMap* unicmap = NULL; /* some UCS-2 map, if we found it */ + + + /* caller should have already checked that `face' is valid */ + FT_ASSERT( face ); + + first = face->charmaps; + + if ( !first ) + return FT_Err_Invalid_CharMap_Handle; + + /* + * The original TrueType specification(s) only specified charmap + * formats that are capable of mapping 8 or 16 bit character codes to + * glyph indices. + * + * However, recent updates to the Apple and OpenType specifications + * introduced new formats that are capable of mapping 32-bit character + * codes as well. And these are already used on some fonts, mainly to + * map non-BMP Asian ideographs as defined in Unicode. + * + * For compatibility purposes, these fonts generally come with + * *several* Unicode charmaps: + * + * - One of them in the "old" 16-bit format, that cannot access + * all glyphs in the font. + * + * - Another one in the "new" 32-bit format, that can access all + * the glyphs. + * + * This function has been written to always favor a 32-bit charmap + * when found. Otherwise, a 16-bit one is returned when found. + */ + + /* since the `interesting' table, with id's 3,10, is normally the */ + /* last one, we loop backwards. This looses with type1 fonts with */ + /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */ + /* chars (.01% ?), and this is the same about 99.99% of the time! */ + + cur = first + face->num_charmaps; /* points after the last one */ + + for ( ; --cur >= first; ) + { + if ( cur[0]->encoding == FT_ENCODING_UNICODE ) + { + unicmap = cur; /* record we found a Unicode charmap */ + + /* XXX If some new encodings to represent UCS-4 are added, */ + /* they should be added here. */ + if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT && + cur[0]->encoding_id == TT_MS_ID_UCS_4 ) || + ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE && + cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32 ) ) + + /* Hurray! We found a UCS-4 charmap. We can stop the scan! */ + { + face->charmap = cur[0]; + return 0; + } + } + } + + /* We do not have any UCS-4 charmap. Sigh. */ + /* Let's see if we have some other kind of Unicode charmap, though. */ + if ( unicmap != NULL ) + { + face->charmap = unicmap[0]; + return 0; + } + + /* Chou blanc! */ + return FT_Err_Invalid_CharMap_Handle; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* open_face */ + /* */ + /* <Description> */ + /* This function does some work for FT_Open_Face(). */ + /* */ + static FT_Error + open_face( FT_Driver driver, + FT_Stream stream, + FT_Long face_index, + FT_Int num_params, + FT_Parameter* params, + FT_Face *aface ) + { + FT_Memory memory; + FT_Driver_Class clazz; + FT_Face face = 0; + FT_Error error, error2; + FT_Face_Internal internal; + + + clazz = driver->clazz; + memory = driver->root.memory; + + /* allocate the face object and perform basic initialization */ + if ( FT_ALLOC( face, clazz->face_object_size ) ) + goto Fail; + + if ( FT_NEW( internal ) ) + goto Fail; + + face->internal = internal; + + face->driver = driver; + face->memory = memory; + face->stream = stream; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + { + int i; + + + face->internal->incremental_interface = 0; + for ( i = 0; i < num_params && !face->internal->incremental_interface; + i++ ) + if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL ) + face->internal->incremental_interface = params[i].data; + } +#endif + + error = clazz->init_face( stream, + face, + (FT_Int)face_index, + num_params, + params ); + if ( error ) + goto Fail; + + /* select Unicode charmap by default */ + error2 = find_unicode_charmap( face ); + + /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */ + /* is returned. */ + + /* no error should happen, but we want to play safe */ + if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle ) + { + error = error2; + goto Fail; + } + + *aface = face; + + Fail: + if ( error ) + { + destroy_charmaps( face, memory ); + clazz->done_face( face ); + FT_FREE( internal ); + FT_FREE( face ); + *aface = 0; + } + + return error; + } + + + /* there's a Mac-specific extended implementation of FT_New_Face() */ + /* in src/base/ftmac.c */ + +#ifndef FT_MACINTOSH + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_New_Face( FT_Library library, + const char* pathname, + FT_Long face_index, + FT_Face *aface ) + { + FT_Open_Args args; + + + /* test for valid `library' and `aface' delayed to FT_Open_Face() */ + if ( !pathname ) + return FT_Err_Invalid_Argument; + + args.flags = FT_OPEN_PATHNAME; + args.pathname = (char*)pathname; + + return FT_Open_Face( library, &args, face_index, aface ); + } + +#endif /* !FT_MACINTOSH */ + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_New_Memory_Face( FT_Library library, + const FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face *aface ) + { + FT_Open_Args args; + + + /* test for valid `library' and `face' delayed to FT_Open_Face() */ + if ( !file_base ) + return FT_Err_Invalid_Argument; + + args.flags = FT_OPEN_MEMORY; + args.memory_base = file_base; + args.memory_size = file_size; + + return FT_Open_Face( library, &args, face_index, aface ); + } + + +#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) + + /* The behavior here is very similar to that in base/ftmac.c, but it */ + /* is designed to work on non-mac systems, so no mac specific calls. */ + /* */ + /* We look at the file and determine if it is a mac dfont file or a mac */ + /* resource file, or a macbinary file containing a mac resource file. */ + /* */ + /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */ + /* the point, especially since there may be multiple `FOND' resources. */ + /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */ + /* they occur in the file. */ + /* */ + /* Note that multiple `POST' resources do not mean multiple postscript */ + /* fonts; they all get jammed together to make what is essentially a */ + /* pfb file. */ + /* */ + /* We aren't interested in `NFNT' or `FONT' bitmap resources. */ + /* */ + /* As soon as we get an `sfnt' load it into memory and pass it off to */ + /* FT_Open_Face. */ + /* */ + /* If we have a (set of) `POST' resources, massage them into a (memory) */ + /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */ + /* going to try to save the kerning info. After all that lives in the */ + /* `FOND' which isn't in the file containing the `POST' resources so */ + /* we don't really have access to it. */ + + + /* Finalizer for a memory stream; gets called by FT_Done_Face(). + It frees the memory it uses. */ + /* from ftmac.c */ + static void + memory_stream_close( FT_Stream stream ) + { + FT_Memory memory = stream->memory; + + + FT_FREE( stream->base ); + + stream->size = 0; + stream->base = 0; + stream->close = 0; + } + + + /* Create a new memory stream from a buffer and a size. */ + /* from ftmac.c */ + static FT_Error + new_memory_stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream_CloseFunc close, + FT_Stream *astream ) + { + FT_Error error; + FT_Memory memory; + FT_Stream stream; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !base ) + return FT_Err_Invalid_Argument; + + *astream = 0; + memory = library->memory; + if ( FT_NEW( stream ) ) + goto Exit; + + FT_Stream_OpenMemory( stream, base, size ); + + stream->close = close; + + *astream = stream; + + Exit: + return error; + } + + + /* Create a new FT_Face given a buffer and a driver name. */ + /* from ftmac.c */ + static FT_Error + open_face_from_buffer( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Long face_index, + const char* driver_name, + FT_Face *aface ) + { + FT_Open_Args args; + FT_Error error; + FT_Stream stream; + FT_Memory memory = library->memory; + + + error = new_memory_stream( library, + base, + size, + memory_stream_close, + &stream ); + if ( error ) + { + FT_FREE( base ); + return error; + } + + args.flags = FT_OPEN_STREAM; + args.stream = stream; + if ( driver_name ) + { + args.flags = args.flags | FT_OPEN_DRIVER; + args.driver = FT_Get_Module( library, driver_name ); + } + + error = FT_Open_Face( library, &args, face_index, aface ); + + if ( error == FT_Err_Ok ) + (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; + else + { + FT_Stream_Close( stream ); + FT_FREE( stream ); + } + + return error; + } + + + /* The resource header says we've got resource_cnt `POST' (type1) */ + /* resources in this file. They all need to be coalesced into */ + /* one lump which gets passed on to the type1 driver. */ + /* Here can be only one PostScript font in a file so face_index */ + /* must be 0 (or -1). */ + /* */ + static FT_Error + Mac_Read_POST_Resource( FT_Library library, + FT_Stream stream, + FT_Long *offsets, + FT_Long resource_cnt, + FT_Long face_index, + FT_Face *aface ) + { + FT_Error error = FT_Err_Cannot_Open_Resource; + FT_Memory memory = library->memory; + FT_Byte* pfb_data; + int i, type, flags; + FT_Long len; + FT_Long pfb_len, pfb_pos, pfb_lenpos; + FT_Long rlen, temp; + + + if ( face_index == -1 ) + face_index = 0; + if ( face_index != 0 ) + return error; + + /* Find the length of all the POST resources, concatenated. Assume */ + /* worst case (each resource in its own section). */ + pfb_len = 0; + for ( i = 0; i < resource_cnt; ++i ) + { + error = FT_Stream_Seek( stream, offsets[i] ); + if ( error ) + goto Exit; + if ( FT_READ_LONG( temp ) ) + goto Exit; + pfb_len += temp + 6; + } + + if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) ) + goto Exit; + + pfb_data[0] = 0x80; + pfb_data[1] = 1; /* Ascii section */ + pfb_data[2] = 0; /* 4-byte length, fill in later */ + pfb_data[3] = 0; + pfb_data[4] = 0; + pfb_data[5] = 0; + pfb_pos = 7; + pfb_lenpos = 2; + + len = 0; + type = 1; + for ( i = 0; i < resource_cnt; ++i ) + { + error = FT_Stream_Seek( stream, offsets[i] ); + if ( error ) + goto Exit2; + if ( FT_READ_LONG( rlen ) ) + goto Exit; + if ( FT_READ_USHORT( flags ) ) + goto Exit; + rlen -= 2; /* the flags are part of the resource */ + if ( ( flags >> 8 ) == type ) + len += rlen; + else + { + pfb_data[pfb_lenpos ] = (FT_Byte)( len ); + pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); + pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); + pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); + + if ( ( flags >> 8 ) == 5 ) /* End of font mark */ + break; + + pfb_data[pfb_pos++] = 0x80; + + type = flags >> 8; + len = rlen; + + pfb_data[pfb_pos++] = (FT_Byte)type; + pfb_lenpos = (FT_Byte)pfb_pos; + pfb_data[pfb_pos++] = 0; /* 4-byte length, fill in later */ + pfb_data[pfb_pos++] = 0; + pfb_data[pfb_pos++] = 0; + pfb_data[pfb_pos++] = 0; + } + + error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); + pfb_pos += rlen; + } + + pfb_data[pfb_pos++] = 0x80; + pfb_data[pfb_pos++] = 3; + + pfb_data[pfb_lenpos ] = (FT_Byte)( len ); + pfb_data[pfb_lenpos + 1] = (FT_Byte)( len >> 8 ); + pfb_data[pfb_lenpos + 2] = (FT_Byte)( len >> 16 ); + pfb_data[pfb_lenpos + 3] = (FT_Byte)( len >> 24 ); + + return open_face_from_buffer( library, + pfb_data, + pfb_pos, + face_index, + "type1", + aface ); + + Exit2: + FT_FREE( pfb_data ); + + Exit: + return error; + } + + + /* The resource header says we've got resource_cnt `sfnt' */ + /* (TrueType/OpenType) resources in this file. Look through */ + /* them for the one indicated by face_index, load it into mem, */ + /* pass it on the the truetype driver and return it. */ + /* */ + static FT_Error + Mac_Read_sfnt_Resource( FT_Library library, + FT_Stream stream, + FT_Long *offsets, + FT_Long resource_cnt, + FT_Long face_index, + FT_Face *aface ) + { + FT_Memory memory = library->memory; + FT_Byte* sfnt_data; + FT_Error error; + FT_Long flag_offset; + FT_Long rlen; + int is_cff; + + + if ( face_index == -1 ) + face_index = 0; + if ( face_index >= resource_cnt ) + return FT_Err_Cannot_Open_Resource; + + flag_offset = offsets[face_index]; + error = FT_Stream_Seek( stream, flag_offset ); + if ( error ) + goto Exit; + + if ( FT_READ_LONG( rlen ) ) + goto Exit; + if ( rlen == -1 ) + return FT_Err_Cannot_Open_Resource; + + if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) ) + return error; + error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); + if ( error ) + goto Exit; + + is_cff = rlen > 4 && sfnt_data[0] == 'O' && + sfnt_data[1] == 'T' && + sfnt_data[2] == 'T' && + sfnt_data[3] == 'O'; + + error = open_face_from_buffer( library, + sfnt_data, + rlen, + face_index, + is_cff ? "cff" : "truetype", + aface ); + + Exit: + return error; + } + + + /* Check for a valid resource fork header, or a valid dfont */ + /* header. In a resource fork the first 16 bytes are repeated */ + /* at the location specified by bytes 4-7. In a dfont bytes */ + /* 4-7 point to 16 bytes of zeroes instead. */ + /* */ + static FT_Error + IsMacResource( FT_Library library, + FT_Stream stream, + FT_Long resource_offset, + FT_Long face_index, + FT_Face *aface ) + { + FT_Memory memory = library->memory; + FT_Error error; + FT_Long map_offset, rdara_pos; + FT_Long *data_offsets; + FT_Long count; + + + error = FT_Raccess_Get_HeaderInfo( library, stream, resource_offset, + &map_offset, &rdara_pos ); + if ( error ) + return error; + + error = FT_Raccess_Get_DataOffsets( library, stream, + map_offset, rdara_pos, + FT_MAKE_TAG( 'P', 'O', 'S', 'T' ), + &data_offsets, &count ); + if ( !error ) + { + error = Mac_Read_POST_Resource( library, stream, data_offsets, count, + face_index, aface ); + FT_FREE( data_offsets ); + return error; + } + + error = FT_Raccess_Get_DataOffsets( library, stream, + map_offset, rdara_pos, + FT_MAKE_TAG( 's', 'f', 'n', 't' ), + &data_offsets, &count ); + if ( !error ) + { + error = Mac_Read_sfnt_Resource( library, stream, data_offsets, count, + face_index, aface ); + FT_FREE( data_offsets ); + } + + return error; + } + + + /* Check for a valid macbinary header, and if we find one */ + /* check that the (flattened) resource fork in it is valid. */ + /* */ + static FT_Error + IsMacBinary( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Face *aface ) + { + unsigned char header[128]; + FT_Error error; + FT_Long dlen, offset; + + + error = FT_Stream_Seek( stream, 0 ); + if ( error ) + goto Exit; + + error = FT_Stream_Read( stream, (FT_Byte*)header, 128 ); + if ( error ) + goto Exit; + + if ( header[ 0] != 0 || + header[74] != 0 || + header[82] != 0 || + header[ 1] == 0 || + header[ 1] > 33 || + header[63] != 0 || + header[2 + header[1]] != 0 ) + return FT_Err_Unknown_File_Format; + + dlen = ( header[0x53] << 24 ) | + ( header[0x54] << 16 ) | + ( header[0x55] << 8 ) | + header[0x56]; +#if 0 + rlen = ( header[0x57] << 24 ) | + ( header[0x58] << 16 ) | + ( header[0x59] << 8 ) | + header[0x5a]; +#endif /* 0 */ + offset = 128 + ( ( dlen + 127 ) & ~127 ); + + return IsMacResource( library, stream, offset, face_index, aface ); + + Exit: + return error; + } + + + static FT_Error + load_face_in_embedded_rfork( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Face *aface, + const FT_Open_Args *args ) + { + +#undef FT_COMPONENT +#define FT_COMPONENT trace_raccess + + FT_Memory memory = library->memory; + FT_Error error = FT_Err_Unknown_File_Format; + int i; + + char * file_names[FT_RACCESS_N_RULES]; + FT_Long offsets[FT_RACCESS_N_RULES]; + FT_Error errors[FT_RACCESS_N_RULES]; + + FT_Open_Args args2; + FT_Stream stream2; + + + FT_Raccess_Guess( library, stream, + args->pathname, file_names, offsets, errors ); + + for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) + { + if ( errors[i] ) + { + FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors[i], i )); + continue; + } + + args2.flags = FT_OPEN_PATHNAME; + args2.pathname = file_names[i] ? file_names[i] : args->pathname; + + FT_TRACE3(( "Try rule %d: %s (offset=%d) ...", + i, args2.pathname, offsets[i] )); + + error = FT_Stream_New( library, &args2, &stream2 ); + if ( error ) + { + FT_TRACE3(( "failed\n" )); + continue; + } + + error = IsMacResource( library, stream2, offsets[i], + face_index, aface ); + FT_Stream_Close( stream2 ); + + FT_TRACE3(( "%s\n", error ? "failed": "successful" )); + + if ( !error ) + break; + } + + for (i = 0; i < FT_RACCESS_N_RULES; i++) + { + if ( file_names[i] ) + FT_FREE( file_names[i] ); + } + + /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */ + if ( error ) + error = FT_Err_Unknown_File_Format; + + return error; + +#undef FT_COMPONENT +#define FT_COMPONENT trace_objs + + } + + + /* Check for some macintosh formats. */ + /* Is this a macbinary file? If so look at the resource fork. */ + /* Is this a mac dfont file? */ + /* Is this an old style resource fork? (in data) */ + /* Else call load_face_in_embedded_rfork to try extra rules */ + /* (defined in `ftrfork.c'). */ + /* */ + static FT_Error + load_mac_face( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Face *aface, + const FT_Open_Args *args ) + { + FT_Error error; + FT_UNUSED( args ); + + + error = IsMacBinary( library, stream, face_index, aface ); + if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format ) + { + +#undef FT_COMPONENT +#define FT_COMPONENT trace_raccess + + FT_TRACE3(( "Try as dfont: %s ...", args->pathname )); + + error = IsMacResource( library, stream, 0, face_index, aface ); + + FT_TRACE3(( "%s\n", error ? "failed" : "successful" )); + +#undef FT_COMPONENT +#define FT_COMPONENT trace_objs + + } + + if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format || + FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) && + ( args->flags & FT_OPEN_PATHNAME ) ) + error = load_face_in_embedded_rfork( library, stream, + face_index, aface, args ); + return error; + } + +#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Open_Face( FT_Library library, + const FT_Open_Args* args, + FT_Long face_index, + FT_Face *aface ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + FT_Face face = 0; + FT_ListNode node = 0; + FT_Bool external_stream; + + + /* test for valid `library' delayed to */ + /* FT_Stream_New() */ + + if ( !aface || !args ) + return FT_Err_Invalid_Argument; + + *aface = 0; + + external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) && + args->stream ); + + /* create input stream */ + error = FT_Stream_New( library, args, &stream ); + if ( error ) + goto Exit; + + memory = library->memory; + + /* If the font driver is specified in the `args' structure, use */ + /* it. Otherwise, we scan the list of registered drivers. */ + if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver ) + { + driver = FT_DRIVER( args->driver ); + + /* not all modules are drivers, so check... */ + if ( FT_MODULE_IS_DRIVER( driver ) ) + { + FT_Int num_params = 0; + FT_Parameter* params = 0; + + + if ( args->flags & FT_OPEN_PARAMS ) + { + num_params = args->num_params; + params = args->params; + } + + error = open_face( driver, stream, face_index, + num_params, params, &face ); + if ( !error ) + goto Success; + } + else + error = FT_Err_Invalid_Handle; + + FT_Stream_Free( stream, external_stream ); + goto Fail; + } + else + { + /* check each font driver for an appropriate format */ + FT_Module* cur = library->modules; + FT_Module* limit = cur + library->num_modules; + + + for ( ; cur < limit; cur++ ) + { + /* not all modules are font drivers, so check... */ + if ( FT_MODULE_IS_DRIVER( cur[0] ) ) + { + FT_Int num_params = 0; + FT_Parameter* params = 0; + + + driver = FT_DRIVER( cur[0] ); + + if ( args->flags & FT_OPEN_PARAMS ) + { + num_params = args->num_params; + params = args->params; + } + + error = open_face( driver, stream, face_index, + num_params, params, &face ); + if ( !error ) + goto Success; + + if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) + goto Fail3; + } + } + + Fail3: + /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */ + /* it may be because we have an empty data fork, so we need to check */ + /* the resource fork. */ + if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format && + FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation ) + goto Fail2; + +#if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS ) + error = load_mac_face( library, stream, face_index, aface, args ); + if ( !error ) + { + /* We don't want to go to Success here. We've already done that. */ + /* On the other hand, if we succeeded we still need to close this */ + /* stream (we opened a different stream which extracted the */ + /* interesting information out of this stream here. That stream */ + /* will still be open and the face will point to it). */ + FT_Stream_Free( stream, external_stream ); + return error; + } + + if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format ) + goto Fail2; +#endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */ + + /* no driver is able to handle this format */ + error = FT_Err_Unknown_File_Format; + + Fail2: + FT_Stream_Free( stream, external_stream ); + goto Fail; + } + + Success: + FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" )); + + /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ + if ( external_stream ) + face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; + + /* add the face object to its driver's list */ + if ( FT_NEW( node ) ) + goto Fail; + + node->data = face; + /* don't assume driver is the same as face->driver, so use */ + /* face->driver instead. */ + FT_List_Add( &face->driver->faces_list, node ); + + /* now allocate a glyph slot object for the face */ + { + FT_GlyphSlot slot; + + + FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" )); + + error = FT_New_GlyphSlot( face, &slot ); + if ( error ) + goto Fail; + + face->glyph = slot; + } + + /* finally, allocate a size object for the face */ + { + FT_Size size; + + + FT_TRACE4(( "FT_Open_Face: Creating size object\n" )); + + error = FT_New_Size( face, &size ); + if ( error ) + goto Fail; + + face->size = size; + } + + /* initialize internal face data */ + { + FT_Face_Internal internal = face->internal; + + + internal->transform_matrix.xx = 0x10000L; + internal->transform_matrix.xy = 0; + internal->transform_matrix.yx = 0; + internal->transform_matrix.yy = 0x10000L; + + internal->transform_delta.x = 0; + internal->transform_delta.y = 0; + } + + *aface = face; + goto Exit; + + Fail: + FT_Done_Face( face ); + + Exit: + FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); + + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Attach_File( FT_Face face, + const char* filepathname ) + { + FT_Open_Args open; + + + /* test for valid `face' delayed to FT_Attach_Stream() */ + + if ( !filepathname ) + return FT_Err_Invalid_Argument; + + open.flags = FT_OPEN_PATHNAME; + open.pathname = (char*)filepathname; + + return FT_Attach_Stream( face, &open ); + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Attach_Stream( FT_Face face, + FT_Open_Args* parameters ) + { + FT_Stream stream; + FT_Error error; + FT_Driver driver; + + FT_Driver_Class clazz; + + + /* test for valid `parameters' delayed to FT_Stream_New() */ + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + if ( !driver ) + return FT_Err_Invalid_Driver_Handle; + + error = FT_Stream_New( driver->root.library, parameters, &stream ); + if ( error ) + goto Exit; + + /* we implement FT_Attach_Stream in each driver through the */ + /* `attach_file' interface */ + + error = FT_Err_Unimplemented_Feature; + clazz = driver->clazz; + if ( clazz->attach_file ) + error = clazz->attach_file( face, stream ); + + /* close the attached stream */ + FT_Stream_Free( stream, + (FT_Bool)( parameters->stream && + ( parameters->flags & FT_OPEN_STREAM ) ) ); + + Exit: + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Done_Face( FT_Face face ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_ListNode node; + + + error = FT_Err_Invalid_Face_Handle; + if ( face && face->driver ) + { + driver = face->driver; + memory = driver->root.memory; + + /* find face in driver's list */ + node = FT_List_Find( &driver->faces_list, face ); + if ( node ) + { + /* remove face object from the driver's list */ + FT_List_Remove( &driver->faces_list, node ); + FT_FREE( node ); + + /* now destroy the object proper */ + destroy_face( memory, face, driver ); + error = FT_Err_Ok; + } + } + return error; + } + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_New_Size( FT_Face face, + FT_Size *asize ) + { + FT_Error error; + FT_Memory memory; + FT_Driver driver; + FT_Driver_Class clazz; + + FT_Size size = 0; + FT_ListNode node = 0; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + if ( !asize ) + return FT_Err_Invalid_Size_Handle; + + if ( !face->driver ) + return FT_Err_Invalid_Driver_Handle; + + *asize = 0; + + driver = face->driver; + clazz = driver->clazz; + memory = face->memory; + + /* Allocate new size object and perform basic initialisation */ + if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) ) + goto Exit; + + size->face = face; + + /* for now, do not use any internal fields in size objects */ + size->internal = 0; + + if ( clazz->init_size ) + error = clazz->init_size( size ); + + /* in case of success, add to the face's list */ + if ( !error ) + { + *asize = size; + node->data = size; + FT_List_Add( &face->sizes_list, node ); + } + + Exit: + if ( error ) + { + FT_FREE( node ); + FT_FREE( size ); + } + + return error; + } + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Done_Size( FT_Size size ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_Face face; + FT_ListNode node; + + + if ( !size ) + return FT_Err_Invalid_Size_Handle; + + face = size->face; + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + if ( !driver ) + return FT_Err_Invalid_Driver_Handle; + + memory = driver->root.memory; + + error = FT_Err_Ok; + node = FT_List_Find( &face->sizes_list, size ); + if ( node ) + { + FT_List_Remove( &face->sizes_list, node ); + FT_FREE( node ); + + if ( face->size == size ) + { + face->size = 0; + if ( face->sizes_list.head ) + face->size = (FT_Size)(face->sizes_list.head->data); + } + + destroy_size( memory, size, driver ); + } + else + error = FT_Err_Invalid_Size_Handle; + + return error; + } + + + static void + ft_recompute_scaled_metrics( FT_Face face, + FT_Size_Metrics* metrics ) + { + /* Compute root ascender, descender, test height, and max_advance */ + + metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender, + metrics->y_scale ) ); + + metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender, + metrics->y_scale ) ); + + metrics->height = FT_PIX_ROUND( FT_MulFix( face->height, + metrics->y_scale ) ); + + metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width, + metrics->x_scale ) ); + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_Char_Size( FT_Face face, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + FT_Driver_Class clazz; + FT_Size_Metrics* metrics; + FT_Long dim_x, dim_y; + + + if ( !face || !face->size || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + metrics = &face->size->metrics; + clazz = driver->clazz; + + if ( !char_width ) + char_width = char_height; + + else if ( !char_height ) + char_height = char_width; + + if ( !horz_resolution ) + horz_resolution = 72; + + if ( !vert_resolution ) + vert_resolution = 72; + + /* default processing -- this can be overridden by the driver */ + if ( char_width < 1 * 64 ) + char_width = 1 * 64; + if ( char_height < 1 * 64 ) + char_height = 1 * 64; + + /* Compute pixel sizes in 26.6 units */ + dim_x = ( char_width * horz_resolution + 36 ) / 72; + dim_y = ( char_height * vert_resolution + 36 ) / 72; + + { + FT_UShort x_ppem = (FT_UShort)( ( dim_x + 32 ) >> 6 ); + FT_UShort y_ppem = (FT_UShort)( ( dim_y + 32 ) >> 6 ); + + if ( x_ppem == metrics->x_ppem && y_ppem == metrics->y_ppem ) + return FT_Err_Ok; + + metrics->x_ppem = x_ppem; + metrics->y_ppem = y_ppem; + } + + metrics->x_scale = 0x10000L; + metrics->y_scale = 0x10000L; + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + { + metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM ); + metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM ); + + ft_recompute_scaled_metrics( face, metrics ); + } + + if ( clazz->set_char_sizes ) + error = clazz->set_char_sizes( face->size, + char_width, + char_height, + horz_resolution, + vert_resolution ); + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + FT_Driver_Class clazz; + FT_Size_Metrics* metrics; + + + if ( !face || !face->size || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + metrics = &face->size->metrics; + clazz = driver->clazz; + + if ( pixel_width == 0 ) + pixel_width = pixel_height; + + else if ( pixel_height == 0 ) + pixel_height = pixel_width; + + if ( pixel_width < 1 ) + pixel_width = 1; + if ( pixel_height < 1 ) + pixel_height = 1; + + /* use `>=' to avoid potention compiler warning on 16bit platforms */ + if ( pixel_width >= 0xFFFFU ) + pixel_width = 0xFFFFU; + if ( pixel_height >= 0xFFFFU ) + pixel_height = 0xFFFFU; + + metrics->x_ppem = (FT_UShort)pixel_width; + metrics->y_ppem = (FT_UShort)pixel_height; + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + { + metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, + face->units_per_EM ); + + metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, + face->units_per_EM ); + + ft_recompute_scaled_metrics( face, metrics ); + } + + if ( clazz->set_pixel_sizes ) + error = clazz->set_pixel_sizes( face->size, + pixel_width, + pixel_height ); + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector *akerning ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + if ( !akerning ) + return FT_Err_Invalid_Argument; + + driver = face->driver; + + akerning->x = 0; + akerning->y = 0; + + if ( driver->clazz->get_kerning ) + { + error = driver->clazz->get_kerning( face, + left_glyph, + right_glyph, + akerning ); + if ( !error ) + { + if ( kern_mode != FT_KERNING_UNSCALED ) + { + akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale ); + akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale ); + + if ( kern_mode != FT_KERNING_UNFITTED ) + { + akerning->x = FT_PIX_ROUND( akerning->x ); + akerning->y = FT_PIX_ROUND( akerning->y ); + } + } + } + } + + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ) + { + FT_CharMap* cur; + FT_CharMap* limit; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */ + /* charmap available, i.e., one with UCS-4 characters, if possible. */ + /* */ + /* This is done by find_unicode_charmap() above, to share code. */ + if ( encoding == FT_ENCODING_UNICODE ) + return find_unicode_charmap( face ); + + cur = face->charmaps; + if ( !cur ) + return FT_Err_Invalid_CharMap_Handle; + + limit = cur + face->num_charmaps; + + for ( ; cur < limit; cur++ ) + { + if ( cur[0]->encoding == encoding ) + { + face->charmap = cur[0]; + return 0; + } + } + + return FT_Err_Invalid_Argument; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ) + { + FT_CharMap* cur; + FT_CharMap* limit; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + cur = face->charmaps; + if ( !cur ) + return FT_Err_Invalid_CharMap_Handle; + + limit = cur + face->num_charmaps; + + for ( ; cur < limit; cur++ ) + { + if ( cur[0] == charmap ) + { + face->charmap = cur[0]; + return 0; + } + } + return FT_Err_Invalid_Argument; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Int ) + FT_Get_Charmap_Index( FT_CharMap charmap ) + { + FT_Int i; + + + for ( i = 0; i < charmap->face->num_charmaps; i++ ) + if ( charmap->face->charmaps[i] == charmap ) + break; + + FT_ASSERT( i < charmap->face->num_charmaps ); + + return i; + } + + + FT_BASE_DEF( void ) + FT_CMap_Done( FT_CMap cmap ) + { + if ( cmap ) + { + FT_CMap_Class clazz = cmap->clazz; + FT_Face face = cmap->charmap.face; + FT_Memory memory = FT_FACE_MEMORY(face); + + + if ( clazz->done ) + clazz->done( cmap ); + + FT_FREE( cmap ); + } + } + + + FT_BASE_DEF( FT_Error ) + FT_CMap_New( FT_CMap_Class clazz, + FT_Pointer init_data, + FT_CharMap charmap, + FT_CMap *acmap ) + { + FT_Error error = 0; + FT_Face face; + FT_Memory memory; + FT_CMap cmap; + + + if ( clazz == NULL || charmap == NULL || charmap->face == NULL ) + return FT_Err_Invalid_Argument; + + face = charmap->face; + memory = FT_FACE_MEMORY( face ); + + if ( !FT_ALLOC( cmap, clazz->size ) ) + { + cmap->charmap = *charmap; + cmap->clazz = clazz; + + if ( clazz->init ) + { + error = clazz->init( cmap, init_data ); + if ( error ) + goto Fail; + } + + /* add it to our list of charmaps */ + if ( FT_RENEW_ARRAY( face->charmaps, + face->num_charmaps, + face->num_charmaps+1 ) ) + goto Fail; + + face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap; + } + + Exit: + if ( acmap ) + *acmap = cmap; + + return error; + + Fail: + FT_CMap_Done( cmap ); + cmap = NULL; + goto Exit; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_UInt ) + FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ) + { + FT_UInt result = 0; + + + if ( face && face->charmap ) + { + FT_CMap cmap = FT_CMAP( face->charmap ); + + + result = cmap->clazz->char_index( cmap, charcode ); + } + return result; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_ULong ) + FT_Get_First_Char( FT_Face face, + FT_UInt *agindex ) + { + FT_ULong result = 0; + FT_UInt gindex = 0; + + + if ( face && face->charmap ) + { + gindex = FT_Get_Char_Index( face, 0 ); + if ( gindex == 0 ) + result = FT_Get_Next_Char( face, 0, &gindex ); + } + + if ( agindex ) + *agindex = gindex; + + return result; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_ULong ) + FT_Get_Next_Char( FT_Face face, + FT_ULong charcode, + FT_UInt *agindex ) + { + FT_ULong result = 0; + FT_UInt gindex = 0; + + + if ( face && face->charmap ) + { + FT_UInt32 code = (FT_UInt32)charcode; + FT_CMap cmap = FT_CMAP( face->charmap ); + + + gindex = cmap->clazz->char_next( cmap, &code ); + result = ( gindex == 0 ) ? 0 : code; + } + + if ( agindex ) + *agindex = gindex; + + return result; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_UInt ) + FT_Get_Name_Index( FT_Face face, + FT_String* glyph_name ) + { + FT_UInt result = 0; + + + if ( face && FT_HAS_GLYPH_NAMES( face ) ) + { + FT_Service_GlyphDict service; + + + FT_FACE_LOOKUP_SERVICE( face, + service, + GLYPH_DICT ); + + if ( service && service->name_index ) + result = service->name_index( face, glyph_name ); + } + + return result; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_Error error = FT_Err_Invalid_Argument; + + + /* clean up buffer */ + if ( buffer && buffer_max > 0 ) + ((FT_Byte*)buffer)[0] = 0; + + if ( face && + glyph_index <= (FT_UInt)face->num_glyphs && + FT_HAS_GLYPH_NAMES( face ) ) + { + FT_Service_GlyphDict service; + + + FT_FACE_LOOKUP_SERVICE( face, + service, + GLYPH_DICT ); + + if ( service && service->get_name ) + error = service->get_name( face, glyph_index, buffer, buffer_max ); + } + + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( const char* ) + FT_Get_Postscript_Name( FT_Face face ) + { + const char* result = NULL; + + + if ( !face ) + goto Exit; + + if ( !result ) + { + FT_Service_PsFontName service; + + + FT_FACE_LOOKUP_SERVICE( face, + service, + POSTSCRIPT_FONT_NAME ); + + if ( service && service->get_ps_font_name ) + result = service->get_ps_font_name( face ); + } + + Exit: + return result; + } + + + /* documentation is in tttables.h */ + + FT_EXPORT_DEF( void* ) + FT_Get_Sfnt_Table( FT_Face face, + FT_Sfnt_Tag tag ) + { + void* table = 0; + FT_Service_SFNT_Table service; + + + if ( face && FT_IS_SFNT( face ) ) + { + FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); + if ( service != NULL ) + table = service->get_table( face, tag ); + } + + return table; + } + + + /* documentation is in tttables.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Load_Sfnt_Table( FT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ) + { + FT_Service_SFNT_Table service; + + + if ( !face || !FT_IS_SFNT( face ) ) + return FT_Err_Invalid_Face_Handle; + + FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); + if ( service == NULL ) + return FT_Err_Unimplemented_Feature; + + return service->load_table( face, tag, offset, buffer, length ); + } + + + /* documentation is in tttables.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Sfnt_Table_Info( FT_Face face, + FT_UInt table_index, + FT_ULong *tag, + FT_ULong *length ) + { + FT_Service_SFNT_Table service; + + + if ( !face || !FT_IS_SFNT( face ) ) + return FT_Err_Invalid_Face_Handle; + + FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE ); + if ( service == NULL ) + return FT_Err_Unimplemented_Feature; + + return service->table_info( face, table_index, tag, length ); + } + + + FT_EXPORT_DEF( FT_ULong ) + FT_Get_CMap_Language_ID( FT_CharMap charmap ) + { + FT_Service_TTCMaps service; + FT_Face face; + TT_CMapInfo cmap_info; + + + if ( !charmap || !charmap->face ) + return 0; + + face = charmap->face; + FT_FACE_FIND_SERVICE( face, service, TT_CMAP ); + if ( service == NULL ) + return 0; + if ( service->get_cmap_info( charmap, &cmap_info )) + return 0; + + return cmap_info.language; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Activate_Size( FT_Size size ) + { + FT_Face face; + + + if ( size == NULL ) + return FT_Err_Bad_Argument; + + face = size->face; + if ( face == NULL || face->driver == NULL ) + return FT_Err_Bad_Argument; + + /* we don't need anything more complex than that; all size objects */ + /* are already listed by the face */ + face->size = size; + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** R E N D E R E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* lookup a renderer by glyph format in the library's list */ + FT_BASE_DEF( FT_Renderer ) + FT_Lookup_Renderer( FT_Library library, + FT_Glyph_Format format, + FT_ListNode* node ) + { + FT_ListNode cur; + FT_Renderer result = 0; + + + if ( !library ) + goto Exit; + + cur = library->renderers.head; + + if ( node ) + { + if ( *node ) + cur = (*node)->next; + *node = 0; + } + + while ( cur ) + { + FT_Renderer renderer = FT_RENDERER( cur->data ); + + + if ( renderer->glyph_format == format ) + { + if ( node ) + *node = cur; + + result = renderer; + break; + } + cur = cur->next; + } + + Exit: + return result; + } + + + static FT_Renderer + ft_lookup_glyph_renderer( FT_GlyphSlot slot ) + { + FT_Face face = slot->face; + FT_Library library = FT_FACE_LIBRARY( face ); + FT_Renderer result = library->cur_renderer; + + + if ( !result || result->glyph_format != slot->format ) + result = FT_Lookup_Renderer( library, slot->format, 0 ); + + return result; + } + + + static void + ft_set_current_renderer( FT_Library library ) + { + FT_Renderer renderer; + + + renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 ); + library->cur_renderer = renderer; + } + + + static FT_Error + ft_add_renderer( FT_Module module ) + { + FT_Library library = module->library; + FT_Memory memory = library->memory; + FT_Error error; + FT_ListNode node; + + + if ( FT_NEW( node ) ) + goto Exit; + + { + FT_Renderer render = FT_RENDERER( module ); + FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz; + + + render->clazz = clazz; + render->glyph_format = clazz->glyph_format; + + /* allocate raster object if needed */ + if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE && + clazz->raster_class->raster_new ) + { + error = clazz->raster_class->raster_new( memory, &render->raster ); + if ( error ) + goto Fail; + + render->raster_render = clazz->raster_class->raster_render; + render->render = clazz->render_glyph; + } + + /* add to list */ + node->data = module; + FT_List_Add( &library->renderers, node ); + + ft_set_current_renderer( library ); + } + + Fail: + if ( error ) + FT_FREE( node ); + + Exit: + return error; + } + + + static void + ft_remove_renderer( FT_Module module ) + { + FT_Library library = module->library; + FT_Memory memory = library->memory; + FT_ListNode node; + + + node = FT_List_Find( &library->renderers, module ); + if ( node ) + { + FT_Renderer render = FT_RENDERER( module ); + + + /* release raster object, if any */ + if ( render->raster ) + render->clazz->raster_class->raster_done( render->raster ); + + /* remove from list */ + FT_List_Remove( &library->renderers, node ); + FT_FREE( node ); + + ft_set_current_renderer( library ); + } + } + + + /* documentation is in ftrender.h */ + + FT_EXPORT_DEF( FT_Renderer ) + FT_Get_Renderer( FT_Library library, + FT_Glyph_Format format ) + { + /* test for valid `library' delayed to FT_Lookup_Renderer() */ + + return FT_Lookup_Renderer( library, format, 0 ); + } + + + /* documentation is in ftrender.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Set_Renderer( FT_Library library, + FT_Renderer renderer, + FT_UInt num_params, + FT_Parameter* parameters ) + { + FT_ListNode node; + FT_Error error = FT_Err_Ok; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !renderer ) + return FT_Err_Invalid_Argument; + + node = FT_List_Find( &library->renderers, renderer ); + if ( !node ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + FT_List_Up( &library->renderers, node ); + + if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE ) + library->cur_renderer = renderer; + + if ( num_params > 0 ) + { + FT_Renderer_SetModeFunc set_mode = renderer->clazz->set_mode; + + + for ( ; num_params > 0; num_params-- ) + { + error = set_mode( renderer, parameters->tag, parameters->data ); + if ( error ) + break; + } + } + + Exit: + return error; + } + + + FT_BASE_DEF( FT_Error ) + FT_Render_Glyph_Internal( FT_Library library, + FT_GlyphSlot slot, + FT_Render_Mode render_mode ) + { + FT_Error error = FT_Err_Ok; + FT_Renderer renderer; + + + /* if it is already a bitmap, no need to do anything */ + switch ( slot->format ) + { + case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */ + break; + + default: + { + FT_ListNode node = 0; + FT_Bool update = 0; + + + /* small shortcut for the very common case */ + if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) + { + renderer = library->cur_renderer; + node = library->renderers.head; + } + else + renderer = FT_Lookup_Renderer( library, slot->format, &node ); + + error = FT_Err_Unimplemented_Feature; + while ( renderer ) + { + error = renderer->render( renderer, slot, render_mode, NULL ); + if ( !error || + FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) + break; + + /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ + /* is unsupported by the current renderer for this glyph image */ + /* format. */ + + /* now, look for another renderer that supports the same */ + /* format. */ + renderer = FT_Lookup_Renderer( library, slot->format, &node ); + update = 1; + } + + /* if we changed the current renderer for the glyph image format */ + /* we need to select it as the next current one */ + if ( !error && update && renderer ) + FT_Set_Renderer( library, renderer, 0, 0 ); + } + } + + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Render_Glyph( FT_GlyphSlot slot, + FT_Render_Mode render_mode ) + { + FT_Library library; + + + if ( !slot ) + return FT_Err_Invalid_Argument; + + library = FT_FACE_LIBRARY( slot->face ); + + return FT_Render_Glyph_Internal( library, slot, render_mode ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M O D U L E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Destroy_Module */ + /* */ + /* <Description> */ + /* Destroys a given module object. For drivers, this also destroys */ + /* all child faces. */ + /* */ + /* <InOut> */ + /* module :: A handle to the target driver object. */ + /* */ + /* <Note> */ + /* The driver _must_ be LOCKED! */ + /* */ + static void + Destroy_Module( FT_Module module ) + { + FT_Memory memory = module->memory; + FT_Module_Class* clazz = module->clazz; + FT_Library library = module->library; + + + /* finalize client-data - before anything else */ + if ( module->generic.finalizer ) + module->generic.finalizer( module ); + + if ( library && library->auto_hinter == module ) + library->auto_hinter = 0; + + /* if the module is a renderer */ + if ( FT_MODULE_IS_RENDERER( module ) ) + ft_remove_renderer( module ); + + /* if the module is a font driver, add some steps */ + if ( FT_MODULE_IS_DRIVER( module ) ) + Destroy_Driver( FT_DRIVER( module ) ); + + /* finalize the module object */ + if ( clazz->module_done ) + clazz->module_done( module ); + + /* discard it */ + FT_FREE( module ); + } + + + /* documentation is in ftmodule.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Add_Module( FT_Library library, + const FT_Module_Class* clazz ) + { + FT_Error error; + FT_Memory memory; + FT_Module module; + FT_UInt nn; + + +#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \ + FREETYPE_MINOR ) + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !clazz ) + return FT_Err_Invalid_Argument; + + /* check freetype version */ + if ( clazz->module_requires > FREETYPE_VER_FIXED ) + return FT_Err_Invalid_Version; + + /* look for a module with the same name in the library's table */ + for ( nn = 0; nn < library->num_modules; nn++ ) + { + module = library->modules[nn]; + if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 ) + { + /* this installed module has the same name, compare their versions */ + if ( clazz->module_version <= module->clazz->module_version ) + return FT_Err_Lower_Module_Version; + + /* remove the module from our list, then exit the loop to replace */ + /* it by our new version.. */ + FT_Remove_Module( library, module ); + break; + } + } + + memory = library->memory; + error = FT_Err_Ok; + + if ( library->num_modules >= FT_MAX_MODULES ) + { + error = FT_Err_Too_Many_Drivers; + goto Exit; + } + + /* allocate module object */ + if ( FT_ALLOC( module, clazz->module_size ) ) + goto Exit; + + /* base initialization */ + module->library = library; + module->memory = memory; + module->clazz = (FT_Module_Class*)clazz; + + /* check whether the module is a renderer - this must be performed */ + /* before the normal module initialization */ + if ( FT_MODULE_IS_RENDERER( module ) ) + { + /* add to the renderers list */ + error = ft_add_renderer( module ); + if ( error ) + goto Fail; + } + + /* is the module a auto-hinter? */ + if ( FT_MODULE_IS_HINTER( module ) ) + library->auto_hinter = module; + + /* if the module is a font driver */ + if ( FT_MODULE_IS_DRIVER( module ) ) + { + /* allocate glyph loader if needed */ + FT_Driver driver = FT_DRIVER( module ); + + + driver->clazz = (FT_Driver_Class)module->clazz; + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + { + error = FT_GlyphLoader_New( memory, &driver->glyph_loader ); + if ( error ) + goto Fail; + } + } + + if ( clazz->module_init ) + { + error = clazz->module_init( module ); + if ( error ) + goto Fail; + } + + /* add module to the library's table */ + library->modules[library->num_modules++] = module; + + Exit: + return error; + + Fail: + if ( FT_MODULE_IS_DRIVER( module ) ) + { + FT_Driver driver = FT_DRIVER( module ); + + + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + FT_GlyphLoader_Done( driver->glyph_loader ); + } + + if ( FT_MODULE_IS_RENDERER( module ) ) + { + FT_Renderer renderer = FT_RENDERER( module ); + + + if ( renderer->raster ) + renderer->clazz->raster_class->raster_done( renderer->raster ); + } + + FT_FREE( module ); + goto Exit; + } + + + /* documentation is in ftmodule.h */ + + FT_EXPORT_DEF( FT_Module ) + FT_Get_Module( FT_Library library, + const char* module_name ) + { + FT_Module result = 0; + FT_Module* cur; + FT_Module* limit; + + + if ( !library || !module_name ) + return result; + + cur = library->modules; + limit = cur + library->num_modules; + + for ( ; cur < limit; cur++ ) + if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 ) + { + result = cur[0]; + break; + } + + return result; + } + + + /* documentation is in ftobjs.h */ + + FT_BASE_DEF( const void* ) + FT_Get_Module_Interface( FT_Library library, + const char* mod_name ) + { + FT_Module module; + + + /* test for valid `library' delayed to FT_Get_Module() */ + + module = FT_Get_Module( library, mod_name ); + + return module ? module->clazz->module_interface : 0; + } + + + FT_BASE_DEF( FT_Pointer ) + ft_module_get_service( FT_Module module, + const char* service_id ) + { + FT_Pointer result = NULL; + + if ( module ) + { + FT_ASSERT( module->clazz && module->clazz->get_interface ); + + /* first, look for the service in the module + */ + if ( module->clazz->get_interface ) + result = module->clazz->get_interface( module, service_id ); + + if ( result == NULL ) + { + /* we didn't find it, look in all other modules then + */ + FT_Library library = module->library; + FT_Module* cur = library->modules; + FT_Module* limit = cur + library->num_modules; + + for ( ; cur < limit; cur++ ) + { + if ( cur[0] != module ) + { + FT_ASSERT( cur[0]->clazz ); + + if ( cur[0]->clazz->get_interface ) + { + result = cur[0]->clazz->get_interface( cur[0], service_id ); + if ( result != NULL ) + break; + } + } + } + } + } + + return result; + } + + + /* documentation is in ftmodule.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Remove_Module( FT_Library library, + FT_Module module ) + { + /* try to find the module from the table, then remove it from there */ + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( module ) + { + FT_Module* cur = library->modules; + FT_Module* limit = cur + library->num_modules; + + + for ( ; cur < limit; cur++ ) + { + if ( cur[0] == module ) + { + /* remove it from the table */ + library->num_modules--; + limit--; + while ( cur < limit ) + { + cur[0] = cur[1]; + cur++; + } + limit[0] = 0; + + /* destroy the module */ + Destroy_Module( module ); + + return FT_Err_Ok; + } + } + } + return FT_Err_Invalid_Driver_Handle; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** L I B R A R Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* documentation is in ftmodule.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_New_Library( FT_Memory memory, + FT_Library *alibrary ) + { + FT_Library library = 0; + FT_Error error; + + + if ( !memory ) + return FT_Err_Invalid_Argument; + +#ifdef FT_DEBUG_LEVEL_ERROR + /* init debugging support */ + ft_debug_init(); +#endif + + /* first of all, allocate the library object */ + if ( FT_NEW( library ) ) + return error; + + library->memory = memory; + + /* allocate the render pool */ + library->raster_pool_size = FT_RENDER_POOL_SIZE; + if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) + goto Fail; + + /* That's ok now */ + *alibrary = library; + + return FT_Err_Ok; + + Fail: + FT_FREE( library ); + return error; + } + + + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( void ) + FT_Library_Version( FT_Library library, + FT_Int *amajor, + FT_Int *aminor, + FT_Int *apatch ) + { + FT_Int major = 0; + FT_Int minor = 0; + FT_Int patch = 0; + + + if ( library ) + { + major = library->version_major; + minor = library->version_minor; + patch = library->version_patch; + } + + if ( amajor ) + *amajor = major; + + if ( aminor ) + *aminor = minor; + + if ( apatch ) + *apatch = patch; + } + + + /* documentation is in ftmodule.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Done_Library( FT_Library library ) + { + FT_Memory memory; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + memory = library->memory; + + /* Discard client-data */ + if ( library->generic.finalizer ) + library->generic.finalizer( library ); + + /* Close all modules in the library */ +#if 1 + while ( library->num_modules > 0 ) + FT_Remove_Module( library, library->modules[0] ); +#else + { + FT_UInt n; + + + for ( n = 0; n < library->num_modules; n++ ) + { + FT_Module module = library->modules[n]; + + + if ( module ) + { + Destroy_Module( module ); + library->modules[n] = 0; + } + } + } +#endif + + /* Destroy raster objects */ + FT_FREE( library->raster_pool ); + library->raster_pool_size = 0; + + FT_FREE( library ); + return FT_Err_Ok; + } + + + /* documentation is in ftmodule.h */ + + FT_EXPORT_DEF( void ) + FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ) + { + if ( library && debug_hook && + hook_index < + ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) ) + library->debug_hooks[hook_index] = debug_hook; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftoutln.c b/Utilities/vtkfreetype/src/base/ftoutln.c new file mode 100644 index 0000000..5cae931 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftoutln.c @@ -0,0 +1,795 @@ +/***************************************************************************/ +/* */ +/* ftoutln.c */ +/* */ +/* FreeType outline management (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* All functions are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_OUTLINE_H +#include FT_INTERNAL_OBJECTS_H +#include FT_TRIGONOMETRY_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_outline + + + static + const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Decompose( FT_Outline* outline, + const FT_Outline_Funcs* func_interface, + void* user ) + { +#undef SCALED +#define SCALED( x ) ( ( (x) << shift ) - delta ) + + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + FT_Error error; + + FT_Int n; /* index of contour in outline */ + FT_UInt first; /* index of first point in contour */ + FT_Int tag; /* current point's state */ + + FT_Int shift; + FT_Pos delta; + + + if ( !outline || !func_interface ) + return FT_Err_Invalid_Argument; + + shift = func_interface->shift; + delta = func_interface->delta; + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + FT_Int last; /* index of last point in contour */ + + + last = outline->contours[n]; + limit = outline->points + last; + + v_start = outline->points[first]; + v_last = outline->points[last]; + + v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y ); + v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y ); + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_CURVE_TAG_CONIC ) + { + /* first point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + error = func_interface->move_to( &v_start, user ); + if ( error ) + goto Exit; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + switch ( tag ) + { + case FT_CURVE_TAG_ON: /* emit a single line_to */ + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = func_interface->line_to( &vec, user ); + if ( error ) + goto Exit; + continue; + } + + case FT_CURVE_TAG_CONIC: /* consume conic arcs */ + v_control.x = SCALED( point->x ); + v_control.y = SCALED( point->y ); + + Do_Conic: + if ( point < limit ) + { + FT_Vector vec; + FT_Vector v_middle; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + if ( tag == FT_CURVE_TAG_ON ) + { + error = func_interface->conic_to( &v_control, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + if ( tag != FT_CURVE_TAG_CONIC ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + vec.x ) / 2; + v_middle.y = ( v_control.y + vec.y ) / 2; + + error = func_interface->conic_to( &v_control, &v_middle, user ); + if ( error ) + goto Exit; + + v_control = vec; + goto Do_Conic; + } + + error = func_interface->conic_to( &v_control, &v_start, user ); + goto Close; + + default: /* FT_CURVE_TAG_CUBIC */ + { + FT_Vector vec1, vec2; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y ); + vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y ); + + if ( point <= limit ) + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); + goto Close; + } + } + } + + /* close the contour with a line segment */ + error = func_interface->line_to( &v_start, user ); + + Close: + if ( error ) + goto Exit; + + first = last + 1; + } + + return 0; + + Exit: + return error; + + Invalid_Outline: + return FT_Err_Invalid_Outline; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_New_Internal( FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline *anoutline ) + { + FT_Error error; + + + if ( !anoutline || !memory ) + return FT_Err_Invalid_Argument; + + *anoutline = null_outline; + + if ( FT_NEW_ARRAY( anoutline->points, numPoints * 2L ) || + FT_NEW_ARRAY( anoutline->tags, numPoints ) || + FT_NEW_ARRAY( anoutline->contours, numContours ) ) + goto Fail; + + anoutline->n_points = (FT_UShort)numPoints; + anoutline->n_contours = (FT_Short)numContours; + anoutline->flags |= FT_OUTLINE_OWNER; + + return FT_Err_Ok; + + Fail: + anoutline->flags |= FT_OUTLINE_OWNER; + FT_Outline_Done_Internal( memory, anoutline ); + + return error; + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline *anoutline ) + { + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + return FT_Outline_New_Internal( library->memory, numPoints, + numContours, anoutline ); + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Check( FT_Outline* outline ) + { + if ( outline ) + { + FT_Int n_points = outline->n_points; + FT_Int n_contours = outline->n_contours; + FT_Int end0, end; + FT_Int n; + + + /* empty glyph? */ + if ( n_points == 0 && n_contours == 0 ) + return 0; + + /* check point and contour counts */ + if ( n_points <= 0 || n_contours <= 0 ) + goto Bad; + + end0 = end = -1; + for ( n = 0; n < n_contours; n++ ) + { + end = outline->contours[n]; + + /* note that we don't accept empty contours */ + if ( end <= end0 || end >= n_points ) + goto Bad; + + end0 = end; + } + + if ( end != n_points - 1 ) + goto Bad; + + /* XXX: check the tags array */ + return 0; + } + + Bad: + return FT_Err_Invalid_Argument; + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Copy( FT_Outline* source, + FT_Outline *target ) + { + FT_Int is_owner; + + + if ( !source || !target || + source->n_points != target->n_points || + source->n_contours != target->n_contours ) + return FT_Err_Invalid_Argument; + + FT_ARRAY_COPY( target->points, source->points, source->n_points ); + + FT_ARRAY_COPY( target->tags, source->tags, source->n_points ); + + FT_ARRAY_COPY( target->contours, source->contours, source->n_contours ); + + /* copy all flags, except the `FT_OUTLINE_OWNER' one */ + is_owner = target->flags & FT_OUTLINE_OWNER; + target->flags = source->flags; + + target->flags &= ~FT_OUTLINE_OWNER; + target->flags |= is_owner; + + return FT_Err_Ok; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Done_Internal( FT_Memory memory, + FT_Outline* outline ) + { + if ( outline ) + { + if ( outline->flags & FT_OUTLINE_OWNER ) + { + FT_FREE( outline->points ); + FT_FREE( outline->tags ); + FT_FREE( outline->contours ); + } + *outline = null_outline; + + return FT_Err_Ok; + } + else + return FT_Err_Invalid_Argument; + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Done( FT_Library library, + FT_Outline* outline ) + { + /* check for valid `outline' in FT_Outline_Done_Internal() */ + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + return FT_Outline_Done_Internal( library->memory, outline ); + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( void ) + FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox *acbox ) + { + FT_Pos xMin, yMin, xMax, yMax; + + + if ( outline && acbox ) + { + if ( outline->n_points == 0 ) + { + xMin = 0; + yMin = 0; + xMax = 0; + yMax = 0; + } + else + { + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + outline->n_points; + + + xMin = xMax = vec->x; + yMin = yMax = vec->y; + vec++; + + for ( ; vec < limit; vec++ ) + { + FT_Pos x, y; + + + x = vec->x; + if ( x < xMin ) xMin = x; + if ( x > xMax ) xMax = x; + + y = vec->y; + if ( y < yMin ) yMin = y; + if ( y > yMax ) yMax = y; + } + } + acbox->xMin = xMin; + acbox->xMax = xMax; + acbox->yMin = yMin; + acbox->yMax = yMax; + } + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( void ) + FT_Outline_Translate( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ) + { + FT_UShort n; + FT_Vector* vec = outline->points; + + + for ( n = 0; n < outline->n_points; n++ ) + { + vec->x += xOffset; + vec->y += yOffset; + vec++; + } + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( void ) + FT_Outline_Reverse( FT_Outline* outline ) + { + FT_UShort n; + FT_Int first, last; + + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + last = outline->contours[n]; + + /* reverse point table */ + { + FT_Vector* p = outline->points + first; + FT_Vector* q = outline->points + last; + FT_Vector swap; + + + while ( p < q ) + { + swap = *p; + *p = *q; + *q = swap; + p++; + q--; + } + } + + /* reverse tags table */ + { + char* p = outline->tags + first; + char* q = outline->tags + last; + char swap; + + + while ( p < q ) + { + swap = *p; + *p = *q; + *q = swap; + p++; + q--; + } + } + + first = last + 1; + } + + outline->flags ^= FT_OUTLINE_REVERSE_FILL; + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ) + { + FT_Error error; + FT_Bool update = 0; + FT_Renderer renderer; + FT_ListNode node; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !params ) + return FT_Err_Invalid_Argument; + + renderer = library->cur_renderer; + node = library->renderers.head; + + params->source = (void*)outline; + + error = FT_Err_Cannot_Render_Glyph; + while ( renderer ) + { + error = renderer->raster_render( renderer->raster, params ); + if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) + break; + + /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ + /* is unsupported by the current renderer for this glyph image */ + /* format */ + + /* now, look for another renderer that supports the same */ + /* format */ + renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, + &node ); + update = 1; + } + + /* if we changed the current renderer for the glyph image format */ + /* we need to select it as the next current one */ + if ( !error && update && renderer ) + FT_Set_Renderer( library, renderer, 0, 0 ); + + return error; + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap *abitmap ) + { + FT_Raster_Params params; + + + if ( !abitmap ) + return FT_Err_Invalid_Argument; + + /* other checks are delayed to FT_Outline_Render() */ + + params.target = abitmap; + params.flags = 0; + + if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY || + abitmap->pixel_mode == FT_PIXEL_MODE_LCD || + abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) + params.flags |= FT_RASTER_FLAG_AA; + + return FT_Outline_Render( library, outline, ¶ms ); + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( void ) + FT_Vector_Transform( FT_Vector* vector, + FT_Matrix* matrix ) + { + FT_Pos xz, yz; + + + if ( !vector || !matrix ) + return; + + xz = FT_MulFix( vector->x, matrix->xx ) + + FT_MulFix( vector->y, matrix->xy ); + + yz = FT_MulFix( vector->x, matrix->yx ) + + FT_MulFix( vector->y, matrix->yy ); + + vector->x = xz; + vector->y = yz; + } + + + /* documentation is in ftoutln.h */ + + FT_EXPORT_DEF( void ) + FT_Outline_Transform( FT_Outline* outline, + FT_Matrix* matrix ) + { + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + outline->n_points; + + + for ( ; vec < limit; vec++ ) + FT_Vector_Transform( vec, matrix ); + } + + + typedef struct FT_OrientationExtremumRec_ + { + FT_Int index; + FT_Long pos; + FT_Int first; + FT_Int last; + + } FT_OrientationExtremumRec; + + + static FT_Orientation + ft_orientation_extremum_compute( FT_OrientationExtremumRec* extremum, + FT_Outline* outline ) + { + FT_Vector *point, *first, *last, *prev, *next; + FT_Vector* points = outline->points; + FT_Angle angle_in, angle_out; + + + /* compute the previous and next points in the same contour */ + point = points + extremum->index; + first = points + extremum->first; + last = points + extremum->last; + + prev = point; + next = point; + + do + { + prev = ( prev == first ) ? last : prev - 1; + if ( prev == point ) + return FT_ORIENTATION_TRUETYPE; /* degenerate case */ + + } while ( prev->x != point->x || prev->y != point->y ); + + do + { + next = ( next == last ) ? first : next + 1; + if ( next == point ) + return FT_ORIENTATION_TRUETYPE; /* shouldn't happen */ + + } while ( next->x != point->x || next->y != point->y ); + + /* now compute the orientation of the `out' vector relative */ + /* to the `in' vector. */ + angle_in = FT_Atan2( point->x - prev->x, point->y - prev->y ); + angle_out = FT_Atan2( next->x - point->x, next->y - point->y ); + + return ( FT_Angle_Diff( angle_in, angle_out ) >= 0 ) + ? FT_ORIENTATION_TRUETYPE + : FT_ORIENTATION_POSTSCRIPT; + } + + + FT_EXPORT_DEF( FT_Orientation ) + FT_Outline_Get_Orientation( FT_Outline* outline ) + { + FT_Orientation result = FT_ORIENTATION_TRUETYPE; + + + if ( outline && outline->n_points > 0 ) + { + FT_OrientationExtremumRec xmin, ymin, xmax, ymax; + FT_Int n; + FT_Int first, last; + FT_Vector* points = outline->points; + + + xmin.pos = ymin.pos = +32768L; + xmax.pos = ymax.pos = -32768L; + + xmin.index = ymin.index = xmax.index = ymax.index = -1; + + first = 0; + for ( n = 0; n < outline->n_contours; n++, first = last + 1 ) + { + last = outline->contours[n]; + + /* skip single-point contours; these are degenerated cases */ + if ( last > first + 1 ) + { + FT_Int i; + + + for ( i = first; i < last; i++ ) + { + FT_Pos x = points[i].x; + FT_Pos y = points[i].y; + + + if ( x < xmin.pos ) + { + xmin.pos = x; + xmin.index = i; + xmin.first = first; + xmin.last = last; + } + if ( x > xmax.pos ) + { + xmax.pos = x; + xmax.index = i; + xmax.first = first; + xmax.last = last; + } + if ( y < ymin.pos ) + { + ymin.pos = y; + ymin.index = i; + ymin.first = first; + ymin.last = last; + } + if ( y > ymax.pos ) + { + ymax.pos = y; + ymax.index = i; + ymax.first = first; + ymax.last = last; + } + } + } + + if ( xmin.index >= 0 ) + result = ft_orientation_extremum_compute( &xmin, outline ); + + else if ( xmax.index >= 0 ) + result = ft_orientation_extremum_compute( &xmax, outline ); + + else if ( ymin.index >= 0 ) + result = ft_orientation_extremum_compute( &ymin, outline ); + + else if ( ymax.index >= 0 ) + result = ft_orientation_extremum_compute( &ymax, outline ); + } + } + + return result; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftpfr.c b/Utilities/vtkfreetype/src/base/ftpfr.c new file mode 100644 index 0000000..fb959e3 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftpfr.c @@ -0,0 +1,126 @@ +/***************************************************************************/ +/* */ +/* ftpfr.c */ +/* */ +/* FreeType API for accessing PFR-specific data (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_SERVICE_PFR_H + + + /* check the format */ + static FT_Service_PfrMetrics + ft_pfr_check( FT_Face face ) + { + FT_Service_PfrMetrics service; + + + FT_FACE_LOOKUP_SERVICE( face, service, PFR_METRICS ); + + return service; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Get_PFR_Metrics( FT_Face face, + FT_UInt *aoutline_resolution, + FT_UInt *ametrics_resolution, + FT_Fixed *ametrics_x_scale, + FT_Fixed *ametrics_y_scale ) + { + FT_Error error = FT_Err_Ok; + FT_Service_PfrMetrics service; + + + service = ft_pfr_check( face ); + if ( service ) + { + error = service->get_metrics( face, + aoutline_resolution, + ametrics_resolution, + ametrics_x_scale, + ametrics_y_scale ); + } + else if ( face ) + { + FT_Fixed x_scale, y_scale; + + + /* this is not a PFR font */ + *aoutline_resolution = face->units_per_EM; + *ametrics_resolution = face->units_per_EM; + + x_scale = y_scale = 0x10000L; + if ( face->size ) + { + x_scale = face->size->metrics.x_scale; + y_scale = face->size->metrics.y_scale; + } + *ametrics_x_scale = x_scale; + *ametrics_y_scale = y_scale; + } + else + error = FT_Err_Invalid_Argument; + + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Get_PFR_Kerning( FT_Face face, + FT_UInt left, + FT_UInt right, + FT_Vector *avector ) + { + FT_Error error; + FT_Service_PfrMetrics service; + + + service = ft_pfr_check( face ); + if ( service ) + error = service->get_kerning( face, left, right, avector ); + else if ( face ) + error = FT_Get_Kerning( face, left, right, + FT_KERNING_UNSCALED, avector ); + else + error = FT_Err_Invalid_Argument; + + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Get_PFR_Advance( FT_Face face, + FT_UInt gindex, + FT_Pos *aadvance ) + { + FT_Error error; + FT_Service_PfrMetrics service; + + + service = ft_pfr_check( face ); + if ( service ) + { + error = service->get_advance( face, gindex, aadvance ); + } + else + /* XXX: TODO: PROVIDE ADVANCE-LOADING METHOD TO ALL FONT DRIVERS */ + error = FT_Err_Invalid_Argument; + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftrfork.c b/Utilities/vtkfreetype/src/base/ftrfork.c new file mode 100644 index 0000000..c9dbe4a --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftrfork.c @@ -0,0 +1,721 @@ +/***************************************************************************/ +/* */ +/* ftrfork.c */ +/* */ +/* Embedded resource forks accessor (body). */ +/* */ +/* Copyright 2004 by */ +/* Masatake YAMATO and Redhat K.K. */ +/* */ +/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */ +/* derived from ftobjs.c. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +/***************************************************************************/ +/* Development of the code in this file is support of */ +/* Information-technology Promotion Agency, Japan. */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_RFORK_H + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_raccess + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** Resource fork directory access ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + FT_BASE_DEF( FT_Error ) + FT_Raccess_Get_HeaderInfo( FT_Library library, + FT_Stream stream, + FT_Long rfork_offset, + FT_Long *map_offset, + FT_Long *rdata_pos ) + { + FT_Error error; + unsigned char head[16], head2[16]; + FT_Long map_pos, rdata_len; + int allzeros, allmatch, i; + FT_Long type_list; + + FT_UNUSED( library ); + + + error = FT_Stream_Seek( stream, rfork_offset ); + if ( error ) + return error; + + error = FT_Stream_Read( stream, (FT_Byte *)head, 16 ); + if ( error ) + return error; + + *rdata_pos = rfork_offset + ( ( head[0] << 24 ) | + ( head[1] << 16 ) | + ( head[2] << 8 ) | + head[3] ); + map_pos = rfork_offset + ( ( head[4] << 24 ) | + ( head[5] << 16 ) | + ( head[6] << 8 ) | + head[7] ); + rdata_len = ( head[ 8] << 24 ) | + ( head[ 9] << 16 ) | + ( head[10] << 8 ) | + head[11]; + + /* map_len = head[12] .. head[15] */ + + if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset ) + return FT_Err_Unknown_File_Format; + + error = FT_Stream_Seek( stream, map_pos ); + if ( error ) + return error; + + head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */ + + error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 ); + if ( error ) + return error; + + allzeros = 1; + allmatch = 1; + for ( i = 0; i < 16; ++i ) + { + if ( head2[i] != 0 ) + allzeros = 0; + if ( head2[i] != head[i] ) + allmatch = 0; + } + if ( !allzeros && !allmatch ) + return FT_Err_Unknown_File_Format; + + /* If we have reached this point then it is probably a mac resource */ + /* file. Now, does it contain any interesting resources? */ + /* Skip handle to next resource map, the file resource number, and */ + /* attributes. */ + (void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */ + + 2 /* skip file resource number */ + + 2 ); /* skip attributes */ + + if ( FT_READ_USHORT( type_list ) ) + return error; + if ( type_list == -1 ) + return FT_Err_Unknown_File_Format; + + error = FT_Stream_Seek( stream, map_pos + type_list ); + if ( error ) + return error; + + *map_offset = map_pos + type_list; + return FT_Err_Ok; + } + + + FT_BASE_DEF( FT_Error ) + FT_Raccess_Get_DataOffsets( FT_Library library, + FT_Stream stream, + FT_Long map_offset, + FT_Long rdata_pos, + FT_Long tag, + FT_Long **offsets, + FT_Long *count ) + { + FT_Error error; + int i, j, cnt, subcnt; + FT_Long tag_internal, rpos; + FT_Memory memory = library->memory; + FT_Long temp; + FT_Long *offsets_internal; + + + error = FT_Stream_Seek( stream, map_offset ); + if ( error ) + return error; + + if ( FT_READ_USHORT( cnt ) ) + return error; + cnt++; + + for ( i = 0; i < cnt; ++i ) + { + if ( FT_READ_LONG( tag_internal ) || + FT_READ_USHORT( subcnt ) || + FT_READ_USHORT( rpos ) ) + return error; + + FT_TRACE2(( "Resource tags: %c%c%c%c\n", + (char)( 0xff & ( tag_internal >> 24 ) ), + (char)( 0xff & ( tag_internal >> 16 ) ), + (char)( 0xff & ( tag_internal >> 8 ) ), + (char)( 0xff & ( tag_internal >> 0 ) ) )); + + if ( tag_internal == tag ) + { + *count = subcnt + 1; + rpos += map_offset; + + error = FT_Stream_Seek( stream, rpos ); + if ( error ) + return error; + + if ( FT_ALLOC( offsets_internal, *count * sizeof( FT_Long ) ) ) + return error; + + for ( j = 0; j < *count; ++j ) + { + (void)FT_STREAM_SKIP( 2 ); /* resource id */ + (void)FT_STREAM_SKIP( 2 ); /* rsource name */ + + if ( FT_READ_LONG( temp ) ) + { + FT_FREE( offsets_internal ); + return error; + } + + offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL ); + + (void)FT_STREAM_SKIP( 4 ); /* mbz */ + } + + *offsets = offsets_internal; + + return FT_Err_Ok; + } + } + + return FT_Err_Cannot_Open_Resource; + } + + +#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** Guessing functions ****/ + /**** ****/ + /**** When you add a new guessing function, ****/ + /**** update FT_RACCESS_N_RULES in ftrfork.h. ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + typedef FT_Error + (*raccess_guess_func)( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + + static FT_Error + raccess_guess_apple_double( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_apple_single( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_darwin_ufs_export( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_darwin_hfsplus( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_vfat( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_linux_cap( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_linux_double( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_linux_netatalk( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ); + + + /*************************************************************************/ + /**** ****/ + /**** Helper functions ****/ + /**** ****/ + /*************************************************************************/ + + static FT_Error + raccess_guess_apple_generic( FT_Library library, + FT_Stream stream, + char * base_file_name, + FT_Int32 magic, + FT_Long *result_offset ); + + static FT_Error + raccess_guess_linux_double_from_file_name( FT_Library library, + char * file_name, + FT_Long *result_offset ); + + static char * + raccess_make_file_name( FT_Memory memory, + const char *original_name, + const char *insertion ); + + + FT_BASE_DEF( void ) + FT_Raccess_Guess( FT_Library library, + FT_Stream stream, + char* base_name, + char **new_names, + FT_Long *offsets, + FT_Error *errors ) + { + FT_Long i; + + + raccess_guess_func funcs[FT_RACCESS_N_RULES] = + { + raccess_guess_apple_double, + raccess_guess_apple_single, + raccess_guess_darwin_ufs_export, + raccess_guess_darwin_hfsplus, + raccess_guess_vfat, + raccess_guess_linux_cap, + raccess_guess_linux_double, + raccess_guess_linux_netatalk, + }; + + for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) + { + new_names[i] = NULL; + errors[i] = FT_Stream_Seek( stream, 0 ); + if ( errors[i] ) + continue ; + + errors[i] = (funcs[i])( library, stream, base_name, + &(new_names[i]), &(offsets[i]) ); + } + + return; + } + + + static FT_Error + raccess_guess_apple_double( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + FT_Int32 magic = ( 0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x07 ); + + + *result_file_name = NULL; + return raccess_guess_apple_generic( library, stream, base_file_name, + magic, result_offset ); + } + + + static FT_Error + raccess_guess_apple_single( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + FT_Int32 magic = (0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x00); + + + *result_file_name = NULL; + return raccess_guess_apple_generic( library, stream, base_file_name, + magic, result_offset ); + } + + + static FT_Error + raccess_guess_darwin_ufs_export( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + char* newpath; + FT_Error error; + FT_Memory memory; + + FT_UNUSED( stream ); + + + memory = library->memory; + newpath = raccess_make_file_name( memory, base_file_name, "._" ); + if ( !newpath ) + return FT_Err_Out_Of_Memory; + + error = raccess_guess_linux_double_from_file_name( library, newpath, + result_offset ); + if ( !error ) + *result_file_name = newpath; + else + FT_FREE( newpath ); + + return error; + } + + + static FT_Error + raccess_guess_darwin_hfsplus( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + /* + Only meaningful on systems with hfs+ drivers (or Macs). + */ + FT_Error error; + char* newpath; + FT_Memory memory; + + FT_UNUSED( stream ); + + + memory = library->memory; + + if ( FT_ALLOC( newpath, + ft_strlen( base_file_name ) + ft_strlen( "/rsrc" ) + 1 ) ) + return error; + + ft_strcpy( newpath, base_file_name ); + ft_strcat( newpath, "/rsrc" ); + *result_file_name = newpath; + *result_offset = 0; + return FT_Err_Ok; + } + + + static FT_Error + raccess_guess_vfat( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + char* newpath; + FT_Memory memory; + + FT_UNUSED( stream ); + + + memory = library->memory; + + newpath = raccess_make_file_name( memory, base_file_name, + "resource.frk/" ); + if ( !newpath ) + return FT_Err_Out_Of_Memory; + + *result_file_name = newpath; + *result_offset = 0; + + return FT_Err_Ok; + } + + + static FT_Error + raccess_guess_linux_cap( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + char* newpath; + FT_Memory memory; + + FT_UNUSED( stream ); + + + memory = library->memory; + + newpath = raccess_make_file_name( memory, base_file_name, ".resource/" ); + if ( !newpath ) + return FT_Err_Out_Of_Memory; + + *result_file_name = newpath; + *result_offset = 0; + + return FT_Err_Ok; + } + + + static FT_Error + raccess_guess_linux_double( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + char* newpath; + FT_Error error; + FT_Memory memory; + + FT_UNUSED( stream ); + + + memory = library->memory; + + newpath = raccess_make_file_name( memory, base_file_name, "%" ); + if ( !newpath ) + return FT_Err_Out_Of_Memory; + + error = raccess_guess_linux_double_from_file_name( library, newpath, + result_offset ); + if ( !error ) + *result_file_name = newpath; + else + FT_FREE( newpath ); + + return error; + } + + + static FT_Error + raccess_guess_linux_netatalk( FT_Library library, + FT_Stream stream, + char * base_file_name, + char **result_file_name, + FT_Long *result_offset ) + { + char* newpath; + FT_Error error; + FT_Memory memory; + + FT_UNUSED( stream ); + + + memory = library->memory; + + newpath = raccess_make_file_name( memory, base_file_name, + ".AppleDouble/" ); + if ( !newpath ) + return FT_Err_Out_Of_Memory; + + error = raccess_guess_linux_double_from_file_name( library, newpath, + result_offset ); + if ( !error ) + *result_file_name = newpath; + else + FT_FREE( newpath ); + + return error; + } + + + static FT_Error + raccess_guess_apple_generic( FT_Library library, + FT_Stream stream, + char * base_file_name, + FT_Int32 magic, + FT_Long *result_offset ) + { + FT_Int32 magic_from_stream; + FT_Error error; + FT_Int32 version_number; + FT_UShort n_of_entries; + + int i; + FT_UInt32 entry_id, entry_offset, entry_length; + + const FT_UInt32 resource_fork_entry_id = 0x2; + + FT_UNUSED( library ); + FT_UNUSED( base_file_name ); + + + if ( FT_READ_LONG ( magic_from_stream ) ) + return error; + if ( magic_from_stream != magic ) + return FT_Err_Unknown_File_Format; + + if ( FT_READ_LONG( version_number ) ) + return error; + + /* filler */ + error = FT_Stream_Skip( stream, 16 ); + if ( error ) + return error; + + if ( FT_READ_USHORT( n_of_entries ) ) + return error; + if ( n_of_entries == 0 ) + return FT_Err_Unknown_File_Format; + + for ( i = 0; i < n_of_entries; i++ ) + { + if ( FT_READ_LONG( entry_id ) ) + return error; + if ( entry_id == resource_fork_entry_id ) + { + if ( FT_READ_LONG( entry_offset ) || + FT_READ_LONG( entry_length ) ) + continue; + *result_offset = entry_offset; + + return FT_Err_Ok; + } + else + FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */ + } + + return FT_Err_Unknown_File_Format; + } + + + static FT_Error + raccess_guess_linux_double_from_file_name( FT_Library library, + char * file_name, + FT_Long *result_offset ) + { + FT_Memory memory; + FT_Open_Args args2; + FT_Stream stream2; + char * nouse = NULL; + FT_Error error; + + + memory = library->memory; + + args2.flags = FT_OPEN_PATHNAME; + args2.pathname = file_name; + error = FT_Stream_New( library, &args2, &stream2 ); + if ( error ) + return error; + + error = raccess_guess_apple_double( library, stream2, file_name, + &nouse, result_offset ); + + FT_Stream_Close( stream2 ); + + return error; + } + + + static char* + raccess_make_file_name( FT_Memory memory, + const char *original_name, + const char *insertion ) + { + char* new_name; + char* tmp; + const char* slash; + unsigned new_length; + FT_ULong error; + + new_length = ft_strlen( original_name ) + ft_strlen( insertion ); + if ( FT_ALLOC( new_name, new_length + 1 ) ) + return NULL; + + tmp = ft_strrchr( original_name, '/' ); + if ( tmp ) + { + ft_strncpy( new_name, original_name, tmp - original_name + 1 ); + new_name[tmp - original_name + 1] = '\0'; + slash = tmp + 1; + } + else + { + slash = original_name; + new_name[0] = '\0'; + } + + ft_strcat( new_name, insertion ); + ft_strcat( new_name, slash ); + + return new_name; + } + + +#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ + + + /*************************************************************************/ + /* Dummy function; just sets errors */ + /*************************************************************************/ + + FT_BASE_DEF( void ) + FT_Raccess_Guess( FT_Library library, + FT_Stream stream, + char* base_name, + char **new_names, + FT_Long *offsets, + FT_Error *errors ) + { + int i; + + FT_UNUSED( library ); + FT_UNUSED( stream ); + FT_UNUSED( base_name ); + + + for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) + { + new_names[i] = NULL; + offsets[i] = 0; + errors[i] = FT_Err_Unimplemented_Feature; + } + } + + +#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftstream.c b/Utilities/vtkfreetype/src/base/ftstream.c new file mode 100644 index 0000000..932fe1b --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftstream.c @@ -0,0 +1,803 @@ +/***************************************************************************/ +/* */ +/* ftstream.c */ +/* */ +/* I/O stream support (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_DEBUG_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_stream + + + FT_BASE_DEF( void ) + FT_Stream_OpenMemory( FT_Stream stream, + const FT_Byte* base, + FT_ULong size ) + { + stream->base = (FT_Byte*) base; + stream->size = size; + stream->pos = 0; + stream->cursor = 0; + stream->read = 0; + stream->close = 0; + } + + + FT_BASE_DEF( void ) + FT_Stream_Close( FT_Stream stream ) + { + if ( stream && stream->close ) + { + stream->close( stream ); + stream->close = NULL; + } + } + + + FT_BASE_DEF( FT_Error ) + FT_Stream_Seek( FT_Stream stream, + FT_ULong pos ) + { + FT_Error error = FT_Err_Ok; + + + stream->pos = pos; + + if ( stream->read ) + { + if ( stream->read( stream, pos, 0, 0 ) ) + { + FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + + error = FT_Err_Invalid_Stream_Operation; + } + } + /* note that seeking to the first position after the file is valid */ + else if ( pos > stream->size ) + { + FT_ERROR(( "FT_Stream_Seek: invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + + error = FT_Err_Invalid_Stream_Operation; + } + + return error; + } + + + FT_BASE_DEF( FT_Error ) + FT_Stream_Skip( FT_Stream stream, + FT_Long distance ) + { + return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) ); + } + + + FT_BASE_DEF( FT_Long ) + FT_Stream_Pos( FT_Stream stream ) + { + return stream->pos; + } + + + FT_BASE_DEF( FT_Error ) + FT_Stream_Read( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ) + { + return FT_Stream_ReadAt( stream, stream->pos, buffer, count ); + } + + + FT_BASE_DEF( FT_Error ) + FT_Stream_ReadAt( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ) + { + FT_Error error = FT_Err_Ok; + FT_ULong read_bytes; + + + if ( pos >= stream->size ) + { + FT_ERROR(( "FT_Stream_ReadAt: invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + + return FT_Err_Invalid_Stream_Operation; + } + + if ( stream->read ) + read_bytes = stream->read( stream, pos, buffer, count ); + else + { + read_bytes = stream->size - pos; + if ( read_bytes > count ) + read_bytes = count; + + FT_MEM_COPY( buffer, stream->base + pos, read_bytes ); + } + + stream->pos = pos + read_bytes; + + if ( read_bytes < count ) + { + FT_ERROR(( "FT_Stream_ReadAt:" )); + FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n", + count, read_bytes )); + + error = FT_Err_Invalid_Stream_Operation; + } + + return error; + } + + + FT_BASE_DEF( FT_Error ) + FT_Stream_ExtractFrame( FT_Stream stream, + FT_ULong count, + FT_Byte** pbytes ) + { + FT_Error error; + + + error = FT_Stream_EnterFrame( stream, count ); + if ( !error ) + { + *pbytes = (FT_Byte*)stream->cursor; + + /* equivalent to FT_Stream_ExitFrame(), with no memory block release */ + stream->cursor = 0; + stream->limit = 0; + } + + return error; + } + + + FT_BASE_DEF( void ) + FT_Stream_ReleaseFrame( FT_Stream stream, + FT_Byte** pbytes ) + { + if ( stream->read ) + { + FT_Memory memory = stream->memory; + + + FT_FREE( *pbytes ); + } + *pbytes = 0; + } + + + FT_BASE_DEF( FT_Error ) + FT_Stream_EnterFrame( FT_Stream stream, + FT_ULong count ) + { + FT_Error error = FT_Err_Ok; + FT_ULong read_bytes; + + + /* check for nested frame access */ + FT_ASSERT( stream && stream->cursor == 0 ); + + if ( stream->read ) + { + /* allocate the frame in memory */ + FT_Memory memory = stream->memory; + + + if ( FT_QALLOC( stream->base, count ) ) + goto Exit; + + /* read it */ + read_bytes = stream->read( stream, stream->pos, + stream->base, count ); + if ( read_bytes < count ) + { + FT_ERROR(( "FT_Stream_EnterFrame:" )); + FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n", + count, read_bytes )); + + FT_FREE( stream->base ); + error = FT_Err_Invalid_Stream_Operation; + } + stream->cursor = stream->base; + stream->limit = stream->cursor + count; + stream->pos += read_bytes; + } + else + { + /* check current and new position */ + if ( stream->pos >= stream->size || + stream->pos + count > stream->size ) + { + FT_ERROR(( "FT_Stream_EnterFrame:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n", + stream->pos, count, stream->size )); + + error = FT_Err_Invalid_Stream_Operation; + goto Exit; + } + + /* set cursor */ + stream->cursor = stream->base + stream->pos; + stream->limit = stream->cursor + count; + stream->pos += count; + } + + Exit: + return error; + } + + + FT_BASE_DEF( void ) + FT_Stream_ExitFrame( FT_Stream stream ) + { + /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */ + /* that it is possible to access a frame of length 0 in */ + /* some weird fonts (usually, when accessing an array of */ + /* 0 records, like in some strange kern tables). */ + /* */ + /* In this case, the loader code handles the 0-length table */ + /* gracefully; however, stream.cursor is really set to 0 by the */ + /* FT_Stream_EnterFrame() call, and this is not an error. */ + /* */ + FT_ASSERT( stream ); + + if ( stream->read ) + { + FT_Memory memory = stream->memory; + + + FT_FREE( stream->base ); + } + stream->cursor = 0; + stream->limit = 0; + } + + + FT_BASE_DEF( FT_Char ) + FT_Stream_GetChar( FT_Stream stream ) + { + FT_Char result; + + + FT_ASSERT( stream && stream->cursor ); + + result = 0; + if ( stream->cursor < stream->limit ) + result = *stream->cursor++; + + return result; + } + + + FT_BASE_DEF( FT_Short ) + FT_Stream_GetShort( FT_Stream stream ) + { + FT_Byte* p; + FT_Short result; + + + FT_ASSERT( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 1 < stream->limit ) + result = FT_NEXT_SHORT( p ); + stream->cursor = p; + + return result; + } + + + FT_BASE_DEF( FT_Short ) + FT_Stream_GetShortLE( FT_Stream stream ) + { + FT_Byte* p; + FT_Short result; + + + FT_ASSERT( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 1 < stream->limit ) + result = FT_NEXT_SHORT_LE( p ); + stream->cursor = p; + + return result; + } + + + FT_BASE_DEF( FT_Long ) + FT_Stream_GetOffset( FT_Stream stream ) + { + FT_Byte* p; + FT_Long result; + + + FT_ASSERT( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 2 < stream->limit ) + result = FT_NEXT_OFF3( p ); + stream->cursor = p; + return result; + } + + + FT_BASE_DEF( FT_Long ) + FT_Stream_GetLong( FT_Stream stream ) + { + FT_Byte* p; + FT_Long result; + + + FT_ASSERT( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 3 < stream->limit ) + result = FT_NEXT_LONG( p ); + stream->cursor = p; + return result; + } + + + FT_BASE_DEF( FT_Long ) + FT_Stream_GetLongLE( FT_Stream stream ) + { + FT_Byte* p; + FT_Long result; + + + FT_ASSERT( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 3 < stream->limit ) + result = FT_NEXT_LONG_LE( p ); + stream->cursor = p; + return result; + } + + + FT_BASE_DEF( FT_Char ) + FT_Stream_ReadChar( FT_Stream stream, + FT_Error* error ) + { + FT_Byte result = 0; + + + FT_ASSERT( stream ); + + *error = FT_Err_Ok; + + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, &result, 1L ) != 1L ) + goto Fail; + } + else + { + if ( stream->pos < stream->size ) + result = stream->base[stream->pos]; + else + goto Fail; + } + stream->pos++; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Stream_ReadChar: invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + FT_BASE_DEF( FT_Short ) + FT_Stream_ReadShort( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[2]; + FT_Byte* p = 0; + FT_Short result = 0; + + + FT_ASSERT( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 1 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = FT_NEXT_SHORT( p ); + } + else + goto Fail; + + stream->pos += 2; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Stream_ReadShort:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + FT_BASE_DEF( FT_Short ) + FT_Stream_ReadShortLE( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[2]; + FT_Byte* p = 0; + FT_Short result = 0; + + + FT_ASSERT( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 1 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = FT_NEXT_SHORT_LE( p ); + } + else + goto Fail; + + stream->pos += 2; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Stream_ReadShortLE:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + FT_BASE_DEF( FT_Long ) + FT_Stream_ReadOffset( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[3]; + FT_Byte* p = 0; + FT_Long result = 0; + + + FT_ASSERT( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 2 < stream->size ) + { + if ( stream->read ) + { + if (stream->read( stream, stream->pos, reads, 3L ) != 3L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = FT_NEXT_OFF3( p ); + } + else + goto Fail; + + stream->pos += 3; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Stream_ReadOffset:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + FT_BASE_DEF( FT_Long ) + FT_Stream_ReadLong( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[4]; + FT_Byte* p = 0; + FT_Long result = 0; + + + FT_ASSERT( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 3 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = FT_NEXT_LONG( p ); + } + else + goto Fail; + + stream->pos += 4; + + return result; + + Fail: + FT_ERROR(( "FT_Stream_ReadLong: invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + *error = FT_Err_Invalid_Stream_Operation; + + return 0; + } + + + FT_BASE_DEF( FT_Long ) + FT_Stream_ReadLongLE( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[4]; + FT_Byte* p = 0; + FT_Long result = 0; + + + FT_ASSERT( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 3 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = FT_NEXT_LONG_LE( p ); + } + else + goto Fail; + + stream->pos += 4; + + return result; + + Fail: + FT_ERROR(( "FT_Stream_ReadLongLE:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + *error = FT_Err_Invalid_Stream_Operation; + + return 0; + } + + + FT_BASE_DEF( FT_Error ) + FT_Stream_ReadFields( FT_Stream stream, + const FT_Frame_Field* fields, + void* structure ) + { + FT_Error error; + FT_Bool frame_accessed = 0; + FT_Byte* cursor = stream->cursor; + + + if ( !fields || !stream ) + return FT_Err_Invalid_Argument; + + error = FT_Err_Ok; + do + { + FT_ULong value; + FT_Int sign_shift; + FT_Byte* p; + + + switch ( fields->value ) + { + case ft_frame_start: /* access a new frame */ + error = FT_Stream_EnterFrame( stream, fields->offset ); + if ( error ) + goto Exit; + + frame_accessed = 1; + cursor = stream->cursor; + fields++; + continue; /* loop! */ + + case ft_frame_bytes: /* read a byte sequence */ + case ft_frame_skip: /* skip some bytes */ + { + FT_UInt len = fields->size; + + + if ( cursor + len > stream->limit ) + { + error = FT_Err_Invalid_Stream_Operation; + goto Exit; + } + + if ( fields->value == ft_frame_bytes ) + { + p = (FT_Byte*)structure + fields->offset; + FT_MEM_COPY( p, cursor, len ); + } + cursor += len; + fields++; + continue; + } + + case ft_frame_byte: + case ft_frame_schar: /* read a single byte */ + value = FT_NEXT_BYTE(cursor); + sign_shift = 24; + break; + + case ft_frame_short_be: + case ft_frame_ushort_be: /* read a 2-byte big-endian short */ + value = FT_NEXT_USHORT(cursor); + sign_shift = 16; + break; + + case ft_frame_short_le: + case ft_frame_ushort_le: /* read a 2-byte little-endian short */ + value = FT_NEXT_USHORT_LE(cursor); + sign_shift = 16; + break; + + case ft_frame_long_be: + case ft_frame_ulong_be: /* read a 4-byte big-endian long */ + value = FT_NEXT_ULONG(cursor); + sign_shift = 0; + break; + + case ft_frame_long_le: + case ft_frame_ulong_le: /* read a 4-byte little-endian long */ + value = FT_NEXT_ULONG_LE(cursor); + sign_shift = 0; + break; + + case ft_frame_off3_be: + case ft_frame_uoff3_be: /* read a 3-byte big-endian long */ + value = FT_NEXT_UOFF3(cursor); + sign_shift = 8; + break; + + case ft_frame_off3_le: + case ft_frame_uoff3_le: /* read a 3-byte little-endian long */ + value = FT_NEXT_UOFF3_LE(cursor); + sign_shift = 8; + break; + + default: + /* otherwise, exit the loop */ + stream->cursor = cursor; + goto Exit; + } + + /* now, compute the signed value is necessary */ + if ( fields->value & FT_FRAME_OP_SIGNED ) + value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift ); + + /* finally, store the value in the object */ + + p = (FT_Byte*)structure + fields->offset; + switch ( fields->size ) + { + case (8 / FT_CHAR_BIT): + *(FT_Byte*)p = (FT_Byte)value; + break; + + case (16 / FT_CHAR_BIT): + *(FT_UShort*)p = (FT_UShort)value; + break; + + case (32 / FT_CHAR_BIT): + *(FT_UInt32*)p = (FT_UInt32)value; + break; + + default: /* for 64-bit systems */ + *(FT_ULong*)p = (FT_ULong)value; + } + + /* go to next field */ + fields++; + } + while ( 1 ); + + Exit: + /* close the frame if it was opened by this read */ + if ( frame_accessed ) + FT_Stream_ExitFrame( stream ); + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftstroke.c b/Utilities/vtkfreetype/src/base/ftstroke.c new file mode 100644 index 0000000..10aad2d --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftstroke.c @@ -0,0 +1,1906 @@ +/***************************************************************************/ +/* */ +/* ftstroke.c */ +/* */ +/* FreeType path stroker (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_STROKER_H +#include FT_TRIGONOMETRY_H +#include FT_OUTLINE_H +#include FT_INTERNAL_MEMORY_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_OBJECTS_H + + FT_EXPORT_DEF( FT_StrokerBorder ) + FT_Outline_GetInsideBorder( FT_Outline* outline ) + { + FT_Orientation o = FT_Outline_Get_Orientation( outline ); + + + return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT + : FT_STROKER_BORDER_LEFT ; + } + + + FT_EXPORT_DEF( FT_StrokerBorder ) + FT_Outline_GetOutsideBorder( FT_Outline* outline ) + { + FT_Orientation o = FT_Outline_Get_Orientation( outline ); + + + return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT + : FT_STROKER_BORDER_RIGHT ; + } + + + /***************************************************************************/ + /***************************************************************************/ + /***** *****/ + /***** BEZIER COMPUTATIONS *****/ + /***** *****/ + /***************************************************************************/ + /***************************************************************************/ + +#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 ) +#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 6 ) +#define FT_EPSILON 2 + +#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON ) + + + static FT_Pos + ft_pos_abs( FT_Pos x ) + { + return x >= 0 ? x : -x ; + } + + + static void + ft_conic_split( FT_Vector* base ) + { + FT_Pos a, b; + + + base[4].x = base[2].x; + b = base[1].x; + a = base[3].x = ( base[2].x + b ) / 2; + b = base[1].x = ( base[0].x + b ) / 2; + base[2].x = ( a + b ) / 2; + + base[4].y = base[2].y; + b = base[1].y; + a = base[3].y = ( base[2].y + b ) / 2; + b = base[1].y = ( base[0].y + b ) / 2; + base[2].y = ( a + b ) / 2; + } + + + static FT_Bool + ft_conic_is_small_enough( FT_Vector* base, + FT_Angle *angle_in, + FT_Angle *angle_out ) + { + FT_Vector d1, d2; + FT_Angle theta; + FT_Int close1, close2; + + + d1.x = base[1].x - base[2].x; + d1.y = base[1].y - base[2].y; + d2.x = base[0].x - base[1].x; + d2.y = base[0].y - base[1].y; + + close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); + close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); + + if ( close1 ) + { + if ( close2 ) + *angle_in = *angle_out = 0; + else + *angle_in = *angle_out = FT_Atan2( d2.x, d2.y ); + } + else if ( close2 ) + { + *angle_in = *angle_out = FT_Atan2( d1.x, d1.y ); + } + else + { + *angle_in = FT_Atan2( d1.x, d1.y ); + *angle_out = FT_Atan2( d2.x, d2.y ); + } + + theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) ); + + return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD ); + } + + + static void + ft_cubic_split( FT_Vector* base ) + { + FT_Pos a, b, c, d; + + + base[6].x = base[3].x; + c = base[1].x; + d = base[2].x; + base[1].x = a = ( base[0].x + c ) / 2; + base[5].x = b = ( base[3].x + d ) / 2; + c = ( c + d ) / 2; + base[2].x = a = ( a + c ) / 2; + base[4].x = b = ( b + c ) / 2; + base[3].x = ( a + b ) / 2; + + base[6].y = base[3].y; + c = base[1].y; + d = base[2].y; + base[1].y = a = ( base[0].y + c ) / 2; + base[5].y = b = ( base[3].y + d ) / 2; + c = ( c + d ) / 2; + base[2].y = a = ( a + c ) / 2; + base[4].y = b = ( b + c ) / 2; + base[3].y = ( a + b ) / 2; + } + + + static FT_Bool + ft_cubic_is_small_enough( FT_Vector* base, + FT_Angle *angle_in, + FT_Angle *angle_mid, + FT_Angle *angle_out ) + { + FT_Vector d1, d2, d3; + FT_Angle theta1, theta2; + FT_Int close1, close2, close3; + + + d1.x = base[2].x - base[3].x; + d1.y = base[2].y - base[3].y; + d2.x = base[1].x - base[2].x; + d2.y = base[1].y - base[2].y; + d3.x = base[0].x - base[1].x; + d3.y = base[0].y - base[1].y; + + close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y ); + close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y ); + close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y ); + + if ( close1 || close3 ) + { + if ( close2 ) + { + /* basically a point */ + *angle_in = *angle_out = *angle_mid = 0; + } + else if ( close1 ) + { + *angle_in = *angle_mid = FT_Atan2( d2.x, d2.y ); + *angle_out = FT_Atan2( d3.x, d3.y ); + } + else /* close2 */ + { + *angle_in = FT_Atan2( d1.x, d1.y ); + *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y ); + } + } + else if ( close2 ) + { + *angle_in = *angle_mid = FT_Atan2( d1.x, d1.y ); + *angle_out = FT_Atan2( d3.x, d3.y ); + } + else + { + *angle_in = FT_Atan2( d1.x, d1.y ); + *angle_mid = FT_Atan2( d2.x, d2.y ); + *angle_out = FT_Atan2( d3.x, d3.y ); + } + + theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) ); + theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) ); + + return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD && + theta2 < FT_SMALL_CUBIC_THRESHOLD ); + } + + + /***************************************************************************/ + /***************************************************************************/ + /***** *****/ + /***** STROKE BORDERS *****/ + /***** *****/ + /***************************************************************************/ + /***************************************************************************/ + + typedef enum + { + FT_STROKE_TAG_ON = 1, /* on-curve point */ + FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */ + FT_STROKE_TAG_BEGIN = 4, /* sub-path start */ + FT_STROKE_TAG_END = 8 /* sub-path end */ + + } FT_StrokeTags; + + + typedef struct FT_StrokeBorderRec_ + { + FT_UInt num_points; + FT_UInt max_points; + FT_Vector* points; + FT_Byte* tags; + FT_Bool movable; + FT_Int start; /* index of current sub-path start point */ + FT_Memory memory; + FT_Bool valid; + + } FT_StrokeBorderRec, *FT_StrokeBorder; + + + static FT_Error + ft_stroke_border_grow( FT_StrokeBorder border, + FT_UInt new_points ) + { + FT_UInt old_max = border->max_points; + FT_UInt new_max = border->num_points + new_points; + FT_Error error = 0; + + + if ( new_max > old_max ) + { + FT_UInt cur_max = old_max; + FT_Memory memory = border->memory; + + + while ( cur_max < new_max ) + cur_max += ( cur_max >> 1 ) + 16; + + if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) || + FT_RENEW_ARRAY( border->tags, old_max, cur_max ) ) + goto Exit; + + border->max_points = cur_max; + } + Exit: + return error; + } + + + static void + ft_stroke_border_close( FT_StrokeBorder border ) + { + FT_ASSERT( border->start >= 0 ); + + /* don't record empty paths! */ + if ( border->num_points > (FT_UInt)border->start ) + { + border->tags[border->start ] |= FT_STROKE_TAG_BEGIN; + border->tags[border->num_points - 1] |= FT_STROKE_TAG_END; + } + + border->start = -1; + border->movable = 0; + } + + + static FT_Error + ft_stroke_border_lineto( FT_StrokeBorder border, + FT_Vector* to, + FT_Bool movable ) + { + FT_Error error = 0; + + + FT_ASSERT( border->start >= 0 ); + + if ( border->movable ) + { + /* move last point */ + border->points[border->num_points - 1] = *to; + } + else + { + /* add one point */ + error = ft_stroke_border_grow( border, 1 ); + if ( !error ) + { + FT_Vector* vec = border->points + border->num_points; + FT_Byte* tag = border->tags + border->num_points; + + + vec[0] = *to; + tag[0] = FT_STROKE_TAG_ON; + + border->num_points += 1; + } + } + border->movable = movable; + return error; + } + + + static FT_Error + ft_stroke_border_conicto( FT_StrokeBorder border, + FT_Vector* control, + FT_Vector* to ) + { + FT_Error error; + + + FT_ASSERT( border->start >= 0 ); + + error = ft_stroke_border_grow( border, 2 ); + if ( !error ) + { + FT_Vector* vec = border->points + border->num_points; + FT_Byte* tag = border->tags + border->num_points; + + vec[0] = *control; + vec[1] = *to; + + tag[0] = 0; + tag[1] = FT_STROKE_TAG_ON; + + border->num_points += 2; + } + border->movable = 0; + return error; + } + + + static FT_Error + ft_stroke_border_cubicto( FT_StrokeBorder border, + FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to ) + { + FT_Error error; + + + FT_ASSERT( border->start >= 0 ); + + error = ft_stroke_border_grow( border, 3 ); + if ( !error ) + { + FT_Vector* vec = border->points + border->num_points; + FT_Byte* tag = border->tags + border->num_points; + + + vec[0] = *control1; + vec[1] = *control2; + vec[2] = *to; + + tag[0] = FT_STROKE_TAG_CUBIC; + tag[1] = FT_STROKE_TAG_CUBIC; + tag[2] = FT_STROKE_TAG_ON; + + border->num_points += 3; + } + border->movable = 0; + return error; + } + + +#define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 ) + + + static FT_Error + ft_stroke_border_arcto( FT_StrokeBorder border, + FT_Vector* center, + FT_Fixed radius, + FT_Angle angle_start, + FT_Angle angle_diff ) + { + FT_Angle total, angle, step, rotate, next, theta; + FT_Vector a, b, a2, b2; + FT_Fixed length; + FT_Error error = 0; + + + /* compute start point */ + FT_Vector_From_Polar( &a, radius, angle_start ); + a.x += center->x; + a.y += center->y; + + total = angle_diff; + angle = angle_start; + rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2; + + while ( total != 0 ) + { + step = total; + if ( step > FT_ARC_CUBIC_ANGLE ) + step = FT_ARC_CUBIC_ANGLE; + + else if ( step < -FT_ARC_CUBIC_ANGLE ) + step = -FT_ARC_CUBIC_ANGLE; + + next = angle + step; + theta = step; + if ( theta < 0 ) + theta = -theta; + + theta >>= 1; + + /* compute end point */ + FT_Vector_From_Polar( &b, radius, next ); + b.x += center->x; + b.y += center->y; + + /* compute first and second control points */ + length = FT_MulDiv( radius, FT_Sin( theta ) * 4, + ( 0x10000L + FT_Cos( theta ) ) * 3 ); + + FT_Vector_From_Polar( &a2, length, angle + rotate ); + a2.x += a.x; + a2.y += a.y; + + FT_Vector_From_Polar( &b2, length, next - rotate ); + b2.x += b.x; + b2.y += b.y; + + /* add cubic arc */ + error = ft_stroke_border_cubicto( border, &a2, &b2, &b ); + if ( error ) + break; + + /* process the rest of the arc ?? */ + a = b; + total -= step; + angle = next; + } + + return error; + } + + + static FT_Error + ft_stroke_border_moveto( FT_StrokeBorder border, + FT_Vector* to ) + { + /* close current open path if any ? */ + if ( border->start >= 0 ) + ft_stroke_border_close( border ); + + border->start = border->num_points; + border->movable = 0; + + return ft_stroke_border_lineto( border, to, 0 ); + } + + + static void + ft_stroke_border_init( FT_StrokeBorder border, + FT_Memory memory ) + { + border->memory = memory; + border->points = NULL; + border->tags = NULL; + + border->num_points = 0; + border->max_points = 0; + border->start = -1; + border->valid = 0; + } + + + static void + ft_stroke_border_reset( FT_StrokeBorder border ) + { + border->num_points = 0; + border->start = -1; + border->valid = 0; + } + + + static void + ft_stroke_border_done( FT_StrokeBorder border ) + { + FT_Memory memory = border->memory; + + + FT_FREE( border->points ); + FT_FREE( border->tags ); + + border->num_points = 0; + border->max_points = 0; + border->start = -1; + border->valid = 0; + } + + + static FT_Error + ft_stroke_border_get_counts( FT_StrokeBorder border, + FT_UInt *anum_points, + FT_UInt *anum_contours ) + { + FT_Error error = 0; + FT_UInt num_points = 0; + FT_UInt num_contours = 0; + + FT_UInt count = border->num_points; + FT_Vector* point = border->points; + FT_Byte* tags = border->tags; + FT_Int in_contour = 0; + + + for ( ; count > 0; count--, num_points++, point++, tags++ ) + { + if ( tags[0] & FT_STROKE_TAG_BEGIN ) + { + if ( in_contour != 0 ) + goto Fail; + + in_contour = 1; + } + else if ( in_contour == 0 ) + goto Fail; + + if ( tags[0] & FT_STROKE_TAG_END ) + { + if ( in_contour == 0 ) + goto Fail; + + in_contour = 0; + num_contours++; + } + } + + if ( in_contour != 0 ) + goto Fail; + + border->valid = 1; + + Exit: + *anum_points = num_points; + *anum_contours = num_contours; + return error; + + Fail: + num_points = 0; + num_contours = 0; + goto Exit; + } + + + static void + ft_stroke_border_export( FT_StrokeBorder border, + FT_Outline* outline ) + { + /* copy point locations */ + FT_ARRAY_COPY( outline->points + outline->n_points, + border->points, + border->num_points ); + + /* copy tags */ + { + FT_UInt count = border->num_points; + FT_Byte* read = border->tags; + FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points; + + + for ( ; count > 0; count--, read++, write++ ) + { + if ( *read & FT_STROKE_TAG_ON ) + *write = FT_CURVE_TAG_ON; + else if ( *read & FT_STROKE_TAG_CUBIC ) + *write = FT_CURVE_TAG_CUBIC; + else + *write = FT_CURVE_TAG_CONIC; + } + } + + /* copy contours */ + { + FT_UInt count = border->num_points; + FT_Byte* tags = border->tags; + FT_Short* write = outline->contours + outline->n_contours; + FT_Short idx = (FT_Short)outline->n_points; + + + for ( ; count > 0; count--, tags++, idx++ ) + { + if ( *tags & FT_STROKE_TAG_END ) + { + *write++ = idx; + outline->n_contours++; + } + } + } + + outline->n_points = (short)( outline->n_points + border->num_points ); + + FT_ASSERT( FT_Outline_Check( outline ) == 0 ); + } + + + /***************************************************************************/ + /***************************************************************************/ + /***** *****/ + /***** STROKER *****/ + /***** *****/ + /***************************************************************************/ + /***************************************************************************/ + +#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI ) + + typedef struct FT_StrokerRec_ + { + FT_Angle angle_in; + FT_Angle angle_out; + FT_Vector center; + FT_Bool first_point; + FT_Bool subpath_open; + FT_Angle subpath_angle; + FT_Vector subpath_start; + + FT_Stroker_LineCap line_cap; + FT_Stroker_LineJoin line_join; + FT_Fixed miter_limit; + FT_Fixed radius; + + FT_Bool valid; + FT_StrokeBorderRec borders[2]; + FT_Memory memory; + + } FT_StrokerRec; + + + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_New( FT_Memory memory, + FT_Stroker *astroker ) + { + FT_Error error; + FT_Stroker stroker; + + + if ( !FT_NEW( stroker ) ) + { + stroker->memory = memory; + + ft_stroke_border_init( &stroker->borders[0], memory ); + ft_stroke_border_init( &stroker->borders[1], memory ); + } + *astroker = stroker; + return error; + } + + + FT_EXPORT_DEF( void ) + FT_Stroker_Set( FT_Stroker stroker, + FT_Fixed radius, + FT_Stroker_LineCap line_cap, + FT_Stroker_LineJoin line_join, + FT_Fixed miter_limit ) + { + stroker->radius = radius; + stroker->line_cap = line_cap; + stroker->line_join = line_join; + stroker->miter_limit = miter_limit; + + FT_Stroker_Rewind( stroker ); + } + + + FT_EXPORT_DEF( void ) + FT_Stroker_Rewind( FT_Stroker stroker ) + { + if ( stroker ) + { + ft_stroke_border_reset( &stroker->borders[0] ); + ft_stroke_border_reset( &stroker->borders[1] ); + } + } + + + FT_EXPORT_DEF( void ) + FT_Stroker_Done( FT_Stroker stroker ) + { + if ( stroker ) + { + FT_Memory memory = stroker->memory; + + + ft_stroke_border_done( &stroker->borders[0] ); + ft_stroke_border_done( &stroker->borders[1] ); + + stroker->memory = NULL; + FT_FREE( stroker ); + } + } + + + /* creates a circular arc at a corner or cap */ + static FT_Error + ft_stroker_arcto( FT_Stroker stroker, + FT_Int side ) + { + FT_Angle total, rotate; + FT_Fixed radius = stroker->radius; + FT_Error error = 0; + FT_StrokeBorder border = stroker->borders + side; + + + rotate = FT_SIDE_TO_ROTATE( side ); + + total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); + if ( total == FT_ANGLE_PI ) + total = -rotate * 2; + + error = ft_stroke_border_arcto( border, + &stroker->center, + radius, + stroker->angle_in + rotate, + total ); + border->movable = 0; + return error; + } + + + /* adds a cap at the end of an opened path */ + static FT_Error + ft_stroker_cap( FT_Stroker stroker, + FT_Angle angle, + FT_Int side ) + { + FT_Error error = 0; + + + if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND ) + { + /* add a round cap */ + stroker->angle_in = angle; + stroker->angle_out = angle + FT_ANGLE_PI; + error = ft_stroker_arcto( stroker, side ); + } + else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE ) + { + /* add a square cap */ + FT_Vector delta, delta2; + FT_Angle rotate = FT_SIDE_TO_ROTATE( side ); + FT_Fixed radius = stroker->radius; + FT_StrokeBorder border = stroker->borders + side; + + + FT_Vector_From_Polar( &delta2, radius, angle + rotate ); + FT_Vector_From_Polar( &delta, radius, angle ); + + delta.x += stroker->center.x + delta2.x; + delta.y += stroker->center.y + delta2.y; + + error = ft_stroke_border_lineto( border, &delta, 0 ); + if ( error ) + goto Exit; + + FT_Vector_From_Polar( &delta2, radius, angle - rotate ); + FT_Vector_From_Polar( &delta, radius, angle ); + + delta.x += delta2.x + stroker->center.x; + delta.y += delta2.y + stroker->center.y; + + error = ft_stroke_border_lineto( border, &delta, 0 ); + } + + Exit: + return error; + } + + + /* process an inside corner, i.e. compute intersection */ + static FT_Error + ft_stroker_inside( FT_Stroker stroker, + FT_Int side) + { + FT_StrokeBorder border = stroker->borders + side; + FT_Angle phi, theta, rotate; + FT_Fixed length, thcos, sigma; + FT_Vector delta; + FT_Error error = 0; + + + rotate = FT_SIDE_TO_ROTATE( side ); + + /* compute median angle */ + theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); + if ( theta == FT_ANGLE_PI ) + theta = rotate; + else + theta = theta / 2; + + phi = stroker->angle_in + theta; + + thcos = FT_Cos( theta ); + sigma = FT_MulFix( stroker->miter_limit, thcos ); + + if ( sigma < 0x10000L ) + { + FT_Vector_From_Polar( &delta, stroker->radius, + stroker->angle_out + rotate ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; + border->movable = 0; + } + else + { + length = FT_DivFix( stroker->radius, thcos ); + + FT_Vector_From_Polar( &delta, length, phi + rotate ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; + } + + error = ft_stroke_border_lineto( border, &delta, 0 ); + + return error; + } + + + /* process an outside corner, i.e. compute bevel/miter/round */ + static FT_Error + ft_stroker_outside( FT_Stroker stroker, + FT_Int side ) + { + FT_StrokeBorder border = stroker->borders + side; + FT_Error error; + FT_Angle rotate; + + + if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND ) + { + error = ft_stroker_arcto( stroker, side ); + } + else + { + /* this is a mitered or beveled corner */ + FT_Fixed sigma, radius = stroker->radius; + FT_Angle theta, phi; + FT_Fixed thcos; + FT_Bool miter; + + + rotate = FT_SIDE_TO_ROTATE( side ); + miter = FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_MITER ); + + theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); + if ( theta == FT_ANGLE_PI ) + { + theta = rotate; + phi = stroker->angle_in; + } + else + { + theta = theta / 2; + phi = stroker->angle_in + theta + rotate; + } + + thcos = FT_Cos( theta ); + sigma = FT_MulFix( stroker->miter_limit, thcos ); + + if ( sigma >= 0x10000L ) + miter = 0; + + if ( miter ) /* this is a miter (broken angle) */ + { + FT_Vector middle, delta; + FT_Fixed length; + + + /* compute middle point */ + FT_Vector_From_Polar( &middle, + FT_MulFix( radius, stroker->miter_limit ), + phi ); + middle.x += stroker->center.x; + middle.y += stroker->center.y; + + /* compute first angle point */ + length = FT_MulFix( radius, + FT_DivFix( 0x10000L - sigma, + ft_pos_abs( FT_Sin( theta ) ) ) ); + + FT_Vector_From_Polar( &delta, length, phi + rotate ); + delta.x += middle.x; + delta.y += middle.y; + + error = ft_stroke_border_lineto( border, &delta, 0 ); + if ( error ) + goto Exit; + + /* compute second angle point */ + FT_Vector_From_Polar( &delta, length, phi - rotate ); + delta.x += middle.x; + delta.y += middle.y; + + error = ft_stroke_border_lineto( border, &delta, 0 ); + if ( error ) + goto Exit; + + /* finally, add a movable end point */ + FT_Vector_From_Polar( &delta, radius, stroker->angle_out + rotate ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; + + error = ft_stroke_border_lineto( border, &delta, 1 ); + } + + else /* this is a bevel (intersection) */ + { + FT_Fixed length; + FT_Vector delta; + + + length = FT_DivFix( stroker->radius, thcos ); + + FT_Vector_From_Polar( &delta, length, phi ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; + + error = ft_stroke_border_lineto( border, &delta, 0 ); + if (error) goto Exit; + + /* now add end point */ + FT_Vector_From_Polar( &delta, stroker->radius, + stroker->angle_out + rotate ); + delta.x += stroker->center.x; + delta.y += stroker->center.y; + + error = ft_stroke_border_lineto( border, &delta, 1 ); + } + } + + Exit: + return error; + } + + + static FT_Error + ft_stroker_process_corner( FT_Stroker stroker ) + { + FT_Error error = 0; + FT_Angle turn; + FT_Int inside_side; + + + turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); + + /* no specific corner processing is required if the turn is 0 */ + if ( turn == 0 ) + goto Exit; + + /* when we turn to the right, the inside side is 0 */ + inside_side = 0; + + /* otherwise, the inside side is 1 */ + if ( turn < 0 ) + inside_side = 1; + + /* process the inside side */ + error = ft_stroker_inside( stroker, inside_side ); + if ( error ) + goto Exit; + + /* process the outside side */ + error = ft_stroker_outside( stroker, 1 - inside_side ); + + Exit: + return error; + } + + + /* add two points to the left and right borders corresponding to the */ + /* start of the subpath.. */ + static FT_Error + ft_stroker_subpath_start( FT_Stroker stroker, + FT_Angle start_angle ) + { + FT_Vector delta; + FT_Vector point; + FT_Error error; + FT_StrokeBorder border; + + + FT_Vector_From_Polar( &delta, stroker->radius, + start_angle + FT_ANGLE_PI2 ); + + point.x = stroker->center.x + delta.x; + point.y = stroker->center.y + delta.y; + + border = stroker->borders; + error = ft_stroke_border_moveto( border, &point ); + if ( error ) + goto Exit; + + point.x = stroker->center.x - delta.x; + point.y = stroker->center.y - delta.y; + + border++; + error = ft_stroke_border_moveto( border, &point ); + + /* save angle for last cap */ + stroker->subpath_angle = start_angle; + stroker->first_point = 0; + + Exit: + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_LineTo( FT_Stroker stroker, + FT_Vector* to ) + { + FT_Error error = 0; + FT_StrokeBorder border; + FT_Vector delta; + FT_Angle angle; + FT_Int side; + + delta.x = to->x - stroker->center.x; + delta.y = to->y - stroker->center.y; + + angle = FT_Atan2( delta.x, delta.y ); + FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 ); + + /* process corner if necessary */ + if ( stroker->first_point ) + { + /* This is the first segment of a subpath. We need to */ + /* add a point to each border at their respective starting */ + /* point locations. */ + error = ft_stroker_subpath_start( stroker, angle ); + if ( error ) + goto Exit; + } + else + { + /* process the current corner */ + stroker->angle_out = angle; + error = ft_stroker_process_corner( stroker ); + if ( error ) + goto Exit; + } + + /* now add a line segment to both the "inside" and "outside" paths */ + + for ( border = stroker->borders, side = 1; side >= 0; side--, border++ ) + { + FT_Vector point; + + + point.x = to->x + delta.x; + point.y = to->y + delta.y; + + error = ft_stroke_border_lineto( border, &point, 1 ); + if ( error ) + goto Exit; + + delta.x = -delta.x; + delta.y = -delta.y; + } + + stroker->angle_in = angle; + stroker->center = *to; + + Exit: + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_ConicTo( FT_Stroker stroker, + FT_Vector* control, + FT_Vector* to ) + { + FT_Error error = 0; + FT_Vector bez_stack[34]; + FT_Vector* arc; + FT_Vector* limit = bez_stack + 30; + FT_Angle start_angle; + FT_Bool first_arc = 1; + + + arc = bez_stack; + arc[0] = *to; + arc[1] = *control; + arc[2] = stroker->center; + + while ( arc >= bez_stack ) + { + FT_Angle angle_in, angle_out; + + + angle_in = angle_out = 0; /* remove compiler warnings */ + + if ( arc < limit && + !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) ) + { + ft_conic_split( arc ); + arc += 2; + continue; + } + + if ( first_arc ) + { + first_arc = 0; + + start_angle = angle_in; + + /* process corner if necessary */ + if ( stroker->first_point ) + error = ft_stroker_subpath_start( stroker, start_angle ); + else + { + stroker->angle_out = start_angle; + error = ft_stroker_process_corner( stroker ); + } + } + + /* the arc's angle is small enough; we can add it directly to each */ + /* border */ + { + FT_Vector ctrl, end; + FT_Angle theta, phi, rotate; + FT_Fixed length; + FT_Int side; + + + theta = FT_Angle_Diff( angle_in, angle_out ) / 2; + phi = angle_in + theta; + length = FT_DivFix( stroker->radius, FT_Cos( theta ) ); + + for ( side = 0; side <= 1; side++ ) + { + rotate = FT_SIDE_TO_ROTATE( side ); + + /* compute control point */ + FT_Vector_From_Polar( &ctrl, length, phi + rotate ); + ctrl.x += arc[1].x; + ctrl.y += arc[1].y; + + /* compute end point */ + FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); + end.x += arc[0].x; + end.y += arc[0].y; + + error = ft_stroke_border_conicto( stroker->borders + side, + &ctrl, &end ); + if ( error ) + goto Exit; + } + } + + arc -= 2; + + if ( arc < bez_stack ) + stroker->angle_in = angle_out; + } + + stroker->center = *to; + + Exit: + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_CubicTo( FT_Stroker stroker, + FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to ) + { + FT_Error error = 0; + FT_Vector bez_stack[37]; + FT_Vector* arc; + FT_Vector* limit = bez_stack + 32; + FT_Angle start_angle; + FT_Bool first_arc = 1; + + + arc = bez_stack; + arc[0] = *to; + arc[1] = *control2; + arc[2] = *control1; + arc[3] = stroker->center; + + while ( arc >= bez_stack ) + { + FT_Angle angle_in, angle_mid, angle_out; + + + /* remove compiler warnings */ + angle_in = angle_out = angle_mid = 0; + + if ( arc < limit && + !ft_cubic_is_small_enough( arc, &angle_in, + &angle_mid, &angle_out ) ) + { + ft_cubic_split( arc ); + arc += 3; + continue; + } + + if ( first_arc ) + { + first_arc = 0; + + /* process corner if necessary */ + start_angle = angle_in; + + if ( stroker->first_point ) + error = ft_stroker_subpath_start( stroker, start_angle ); + else + { + stroker->angle_out = start_angle; + error = ft_stroker_process_corner( stroker ); + } + if ( error ) + goto Exit; + } + + /* the arc's angle is small enough; we can add it directly to each */ + /* border */ + { + FT_Vector ctrl1, ctrl2, end; + FT_Angle theta1, phi1, theta2, phi2, rotate; + FT_Fixed length1, length2; + FT_Int side; + + + theta1 = ft_pos_abs( angle_mid - angle_in ) / 2; + theta2 = ft_pos_abs( angle_out - angle_mid ) / 2; + phi1 = (angle_mid + angle_in ) / 2; + phi2 = (angle_mid + angle_out ) / 2; + length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) ); + length2 = FT_DivFix( stroker->radius, FT_Cos(theta2) ); + + for ( side = 0; side <= 1; side++ ) + { + rotate = FT_SIDE_TO_ROTATE( side ); + + /* compute control points */ + FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate ); + ctrl1.x += arc[2].x; + ctrl1.y += arc[2].y; + + FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate ); + ctrl2.x += arc[1].x; + ctrl2.y += arc[1].y; + + /* compute end point */ + FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate ); + end.x += arc[0].x; + end.y += arc[0].y; + + error = ft_stroke_border_cubicto( stroker->borders + side, + &ctrl1, &ctrl2, &end ); + if ( error ) + goto Exit; + } + } + + arc -= 3; + if ( arc < bez_stack ) + stroker->angle_in = angle_out; + } + + stroker->center = *to; + + Exit: + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_BeginSubPath( FT_Stroker stroker, + FT_Vector* to, + FT_Bool open ) + { + /* We cannot process the first point, because there is not enough */ + /* information regarding its corner/cap. The latter will be processed */ + /* in the "end_subpath" routine. */ + /* */ + stroker->first_point = 1; + stroker->center = *to; + stroker->subpath_open = open; + + /* record the subpath start point index for each border */ + stroker->subpath_start = *to; + return 0; + } + + + static FT_Error + ft_stroker_add_reverse_left( FT_Stroker stroker, + FT_Bool open ) + { + FT_StrokeBorder right = stroker->borders + 0; + FT_StrokeBorder left = stroker->borders + 1; + FT_Int new_points; + FT_Error error = 0; + + + FT_ASSERT( left->start >= 0 ); + + new_points = left->num_points - left->start; + if ( new_points > 0 ) + { + error = ft_stroke_border_grow( right, (FT_UInt)new_points ); + if ( error ) + goto Exit; + + { + FT_Vector* dst_point = right->points + right->num_points; + FT_Byte* dst_tag = right->tags + right->num_points; + FT_Vector* src_point = left->points + left->num_points - 1; + FT_Byte* src_tag = left->tags + left->num_points - 1; + + while ( src_point >= left->points + left->start ) + { + *dst_point = *src_point; + *dst_tag = *src_tag; + + if ( open ) + dst_tag[0] &= ~( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ); + else + { + /* switch begin/end tags if necessary.. */ + if ( dst_tag[0] & ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ) ) + dst_tag[0] ^= ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ); + } + + src_point--; + src_tag--; + dst_point++; + dst_tag++; + } + } + + left->num_points = left->start; + right->num_points += new_points; + + right->movable = 0; + left->movable = 0; + } + + Exit: + return error; + } + + + /* there's a lot of magic in this function! */ + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_EndSubPath( FT_Stroker stroker ) + { + FT_Error error = 0; + + if ( stroker->subpath_open ) + { + FT_StrokeBorder right = stroker->borders; + + /* All right, this is an opened path, we need to add a cap between */ + /* right & left, add the reverse of left, then add a final cap */ + /* between left & right. */ + error = ft_stroker_cap( stroker, stroker->angle_in, 0 ); + if ( error ) + goto Exit; + + /* add reversed points from "left" to "right" */ + error = ft_stroker_add_reverse_left( stroker, 1 ); + if ( error ) + goto Exit; + + /* now add the final cap */ + stroker->center = stroker->subpath_start; + error = ft_stroker_cap( stroker, + stroker->subpath_angle + FT_ANGLE_PI, 0 ); + if ( error ) + goto Exit; + + /* Now end the right subpath accordingly. The left one is */ + /* rewind and doesn't need further processing. */ + ft_stroke_border_close( right ); + } + else + { + FT_Angle turn; + FT_Int inside_side; + + /* close the path if needed */ + if ( stroker->center.x != stroker->subpath_start.x || + stroker->center.y != stroker->subpath_start.y ) + { + error = FT_Stroker_LineTo( stroker, &stroker->subpath_start ); + if ( error ) + goto Exit; + } + + /* process the corner */ + stroker->angle_out = stroker->subpath_angle; + turn = FT_Angle_Diff( stroker->angle_in, + stroker->angle_out ); + + /* no specific corner processing is required if the turn is 0 */ + if ( turn != 0 ) + { + /* when we turn to the right, the inside side is 0 */ + inside_side = 0; + + /* otherwise, the inside side is 1 */ + if ( turn < 0 ) + inside_side = 1; + + /* IMPORTANT: WE DO NOT PROCESS THE INSIDE BORDER HERE! */ + /* process the inside side */ + /* error = ft_stroker_inside( stroker, inside_side ); */ + /* if ( error ) */ + /* goto Exit; */ + + /* process the outside side */ + error = ft_stroker_outside( stroker, 1 - inside_side ); + if ( error ) + goto Exit; + } + + /* then end our two subpaths */ + ft_stroke_border_close( stroker->borders + 0 ); + ft_stroke_border_close( stroker->borders + 1 ); + } + + Exit: + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_GetBorderCounts( FT_Stroker stroker, + FT_StrokerBorder border, + FT_UInt *anum_points, + FT_UInt *anum_contours ) + { + FT_UInt num_points = 0, num_contours = 0; + FT_Error error; + + + if ( !stroker || border > 1 ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + error = ft_stroke_border_get_counts( stroker->borders + border, + &num_points, &num_contours ); + Exit: + if ( anum_points ) + *anum_points = num_points; + + if ( anum_contours ) + *anum_contours = num_contours; + + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_GetCounts( FT_Stroker stroker, + FT_UInt *anum_points, + FT_UInt *anum_contours ) + { + FT_UInt count1, count2, num_points = 0; + FT_UInt count3, count4, num_contours = 0; + FT_Error error; + + + error = ft_stroke_border_get_counts( stroker->borders + 0, + &count1, &count2 ); + if ( error ) + goto Exit; + + error = ft_stroke_border_get_counts( stroker->borders + 1, + &count3, &count4 ); + if ( error ) + goto Exit; + + num_points = count1 + count3; + num_contours = count2 + count4; + + Exit: + *anum_points = num_points; + *anum_contours = num_contours; + return error; + } + + + FT_EXPORT_DEF( void ) + FT_Stroker_ExportBorder( FT_Stroker stroker, + FT_StrokerBorder border, + FT_Outline* outline ) + { + if ( border == FT_STROKER_BORDER_LEFT || + border == FT_STROKER_BORDER_RIGHT ) + { + FT_StrokeBorder sborder = & stroker->borders[border]; + + + if ( sborder->valid ) + ft_stroke_border_export( sborder, outline ); + } + } + + + FT_EXPORT_DEF( void ) + FT_Stroker_Export( FT_Stroker stroker, + FT_Outline* outline ) + { + FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline ); + FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline ); + } + + + /* + * The following is very similar to FT_Outline_Decompose, except + * that we do support opened paths, and do not scale the outline. + */ + FT_EXPORT_DEF( FT_Error ) + FT_Stroker_ParseOutline( FT_Stroker stroker, + FT_Outline* outline, + FT_Bool opened ) + { + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + FT_Error error; + + FT_Int n; /* index of contour in outline */ + FT_UInt first; /* index of first point in contour */ + FT_Int tag; /* current point's state */ + + + if ( !outline || !stroker ) + return FT_Err_Invalid_Argument; + + FT_Stroker_Rewind( stroker ); + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + FT_Int last; /* index of last point in contour */ + + + last = outline->contours[n]; + limit = outline->points + last; + + v_start = outline->points[first]; + v_last = outline->points[last]; + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_CURVE_TAG_CONIC ) + { + /* First point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + error = FT_Stroker_BeginSubPath( stroker, &v_start, opened ); + if ( error ) + goto Exit; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + switch ( tag ) + { + case FT_CURVE_TAG_ON: /* emit a single line_to */ + { + FT_Vector vec; + + + vec.x = point->x; + vec.y = point->y; + + error = FT_Stroker_LineTo( stroker, &vec ); + if ( error ) + goto Exit; + continue; + } + + case FT_CURVE_TAG_CONIC: /* consume conic arcs */ + v_control.x = point->x; + v_control.y = point->y; + + Do_Conic: + if ( point < limit ) + { + FT_Vector vec; + FT_Vector v_middle; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + vec = point[0]; + + if ( tag == FT_CURVE_TAG_ON ) + { + error = FT_Stroker_ConicTo( stroker, &v_control, &vec ); + if ( error ) + goto Exit; + continue; + } + + if ( tag != FT_CURVE_TAG_CONIC ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + vec.x ) / 2; + v_middle.y = ( v_control.y + vec.y ) / 2; + + error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle ); + if ( error ) + goto Exit; + + v_control = vec; + goto Do_Conic; + } + + error = FT_Stroker_ConicTo( stroker, &v_control, &v_start ); + goto Close; + + default: /* FT_CURVE_TAG_CUBIC */ + { + FT_Vector vec1, vec2; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + vec1 = point[-2]; + vec2 = point[-1]; + + if ( point <= limit ) + { + FT_Vector vec; + + + vec = point[0]; + + error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec ); + if ( error ) + goto Exit; + continue; + } + + error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start ); + goto Close; + } + } + } + + Close: + if ( error ) + goto Exit; + + error = FT_Stroker_EndSubPath( stroker ); + if ( error ) + goto Exit; + + first = last + 1; + } + + return 0; + + Exit: + return error; + + Invalid_Outline: + return FT_Err_Invalid_Outline; + } + + + extern const FT_Glyph_Class ft_outline_glyph_class; + + + FT_EXPORT_DEF( FT_Error ) + FT_Glyph_Stroke( FT_Glyph *pglyph, + FT_Stroker stroker, + FT_Bool destroy ) + { + FT_Error error = FT_Err_Invalid_Argument; + FT_Glyph glyph = NULL; + + + if ( pglyph == NULL ) + goto Exit; + + glyph = *pglyph; + if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class ) + goto Exit; + + { + FT_Glyph copy; + + + error = FT_Glyph_Copy( glyph, © ); + if ( error ) + goto Exit; + + glyph = copy; + } + + { + FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph; + FT_Outline* outline = &oglyph->outline; + FT_UInt num_points, num_contours; + + + error = FT_Stroker_ParseOutline( stroker, outline, 0 ); + if ( error ) + goto Fail; + + (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours ); + + FT_Outline_Done( glyph->library, outline ); + + error = FT_Outline_New( glyph->library, + num_points, num_contours, outline ); + if ( error ) + goto Fail; + + outline->n_points = 0; + outline->n_contours = 0; + + FT_Stroker_Export( stroker, outline ); + } + + if ( destroy ) + FT_Done_Glyph( *pglyph ); + + *pglyph = glyph; + goto Exit; + + Fail: + FT_Done_Glyph( glyph ); + glyph = NULL; + + if ( !destroy ) + *pglyph = NULL; + + Exit: + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Glyph_StrokeBorder( FT_Glyph *pglyph, + FT_Stroker stroker, + FT_Bool inside, + FT_Bool destroy ) + { + FT_Error error = FT_Err_Invalid_Argument; + FT_Glyph glyph = NULL; + + + if ( pglyph == NULL ) + goto Exit; + + glyph = *pglyph; + if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class ) + goto Exit; + + { + FT_Glyph copy; + + + error = FT_Glyph_Copy( glyph, © ); + if ( error ) + goto Exit; + + glyph = copy; + } + + { + FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph; + FT_StrokerBorder border; + FT_Outline* outline = &oglyph->outline; + FT_UInt num_points, num_contours; + + + border = FT_Outline_GetOutsideBorder( outline ); + if ( inside ) + { + if ( border == FT_STROKER_BORDER_LEFT ) + border = FT_STROKER_BORDER_RIGHT; + else + border = FT_STROKER_BORDER_LEFT; + } + + error = FT_Stroker_ParseOutline( stroker, outline, 0 ); + if ( error ) + goto Fail; + + (void)FT_Stroker_GetBorderCounts( stroker, border, + &num_points, &num_contours ); + + FT_Outline_Done( glyph->library, outline ); + + error = FT_Outline_New( glyph->library, + num_points, + num_contours, + outline ); + if ( error ) + goto Fail; + + outline->n_points = 0; + outline->n_contours = 0; + + FT_Stroker_ExportBorder( stroker, border, outline ); + } + + if ( destroy ) + FT_Done_Glyph( *pglyph ); + + *pglyph = glyph; + goto Exit; + + Fail: + FT_Done_Glyph( glyph ); + glyph = NULL; + + if ( !destroy ) + *pglyph = NULL; + + Exit: + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftsynth.c b/Utilities/vtkfreetype/src/base/ftsynth.c new file mode 100644 index 0000000..cee3682 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftsynth.c @@ -0,0 +1,287 @@ +/***************************************************************************/ +/* */ +/* ftsynth.c */ +/* */ +/* FreeType synthesizing code for emboldening and slanting (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_CALC_H +#include FT_OUTLINE_H +#include FT_TRIGONOMETRY_H +#include FT_SYNTHESIS_H + + +#define FT_BOLD_THRESHOLD 0x0100 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** EXPERIMENTAL OBLIQUING SUPPORT ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_EXPORT_DEF( void ) + FT_GlyphSlot_Oblique( FT_GlyphSlot slot ) + { + FT_Matrix transform; + FT_Outline* outline = &slot->outline; + + + /* only oblique outline glyphs */ + if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) + return; + + /* we don't touch the advance width */ + + /* For italic, simply apply a shear transform, with an angle */ + /* of about 12 degrees. */ + + transform.xx = 0x10000L; + transform.yx = 0x00000L; + + transform.xy = 0x06000L; + transform.yy = 0x10000L; + + FT_Outline_Transform( outline, &transform ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + + static int + ft_test_extrema( FT_Outline* outline, + int n ) + { + FT_Vector *prev, *cur, *next; + FT_Pos product; + FT_Int c, first, last; + + + /* we need to compute the `previous' and `next' point */ + /* for these extrema. */ + cur = outline->points + n; + prev = cur - 1; + next = cur + 1; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + last = outline->contours[c]; + + if ( n == first ) + prev = outline->points + last; + + if ( n == last ) + next = outline->points + first; + + first = last + 1; + } + + product = FT_MulDiv( cur->x - prev->x, /* in.x */ + next->y - cur->y, /* out.y */ + 0x40 ) + - + FT_MulDiv( cur->y - prev->y, /* in.y */ + next->x - cur->x, /* out.x */ + 0x40 ); + + if ( product ) + product = product > 0 ? 1 : -1; + + return product; + } + + + /* Compute the orientation of path filling. It differs between TrueType */ + /* and Type1 formats. We could use the `FT_OUTLINE_REVERSE_FILL' flag, */ + /* but it is better to re-compute it directly (it seems that this flag */ + /* isn't correctly set for some weird composite glyphs currently). */ + /* */ + /* We do this by computing bounding box points, and computing their */ + /* curvature. */ + /* */ + /* The function returns either 1 or -1. */ + /* */ + static int + ft_get_orientation( FT_Outline* outline ) + { + FT_BBox box; + FT_BBox indices; + int n, last; + + + indices.xMin = -1; + indices.yMin = -1; + indices.xMax = -1; + indices.yMax = -1; + + box.xMin = box.yMin = 32767; + box.xMax = box.yMax = -32768; + + /* is it empty ? */ + if ( outline->n_contours < 1 ) + return 1; + + last = outline->contours[outline->n_contours - 1]; + + for ( n = 0; n <= last; n++ ) + { + FT_Pos x, y; + + + x = outline->points[n].x; + if ( x < box.xMin ) + { + box.xMin = x; + indices.xMin = n; + } + if ( x > box.xMax ) + { + box.xMax = x; + indices.xMax = n; + } + + y = outline->points[n].y; + if ( y < box.yMin ) + { + box.yMin = y; + indices.yMin = n; + } + if ( y > box.yMax ) + { + box.yMax = y; + indices.yMax = n; + } + } + + /* test orientation of the xmin */ + n = ft_test_extrema( outline, indices.xMin ); + if ( n ) + goto Exit; + + n = ft_test_extrema( outline, indices.yMin ); + if ( n ) + goto Exit; + + n = ft_test_extrema( outline, indices.xMax ); + if ( n ) + goto Exit; + + n = ft_test_extrema( outline, indices.yMax ); + if ( !n ) + n = 1; + + Exit: + return n; + } + + + FT_EXPORT_DEF( void ) + FT_GlyphSlot_Embolden( FT_GlyphSlot slot ) + { + FT_Vector* points; + FT_Vector v_prev, v_first, v_next, v_cur; + FT_Pos distance; + FT_Outline* outline = &slot->outline; + FT_Face face = FT_SLOT_FACE( slot ); + FT_Angle rotate, angle_in, angle_out; + FT_Int c, n, first, orientation; + + + /* only embolden outline glyph images */ + if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) + return; + + /* compute control distance */ + distance = FT_MulFix( face->units_per_EM / 60, + face->size->metrics.y_scale ); + + orientation = ft_get_orientation( outline ); + rotate = FT_ANGLE_PI2*orientation; + + points = outline->points; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + int last = outline->contours[c]; + + + v_first = points[first]; + v_prev = points[last]; + v_cur = v_first; + + for ( n = first; n <= last; n++ ) + { + FT_Pos d; + FT_Vector in, out; + FT_Fixed scale; + FT_Angle angle_diff; + + + if ( n < last ) v_next = points[n + 1]; + else v_next = v_first; + + /* compute the in and out vectors */ + in.x = v_cur.x - v_prev.x; + in.y = v_cur.y - v_prev.y; + + out.x = v_next.x - v_cur.x; + out.y = v_next.y - v_cur.y; + + angle_in = FT_Atan2( in.x, in.y ); + angle_out = FT_Atan2( out.x, out.y ); + angle_diff = FT_Angle_Diff( angle_in, angle_out ); + scale = FT_Cos( angle_diff/2 ); + + if ( scale < 0x400L && scale > -0x400L ) + { + if ( scale >= 0 ) + scale = 0x400L; + else + scale = -0x400L; + } + + d = FT_DivFix( distance, scale ); + + FT_Vector_From_Polar( &in, d, angle_in + angle_diff/2 - rotate ); + + outline->points[n].x = v_cur.x + distance + in.x; + outline->points[n].y = v_cur.y + distance + in.y; + + v_prev = v_cur; + v_cur = v_next; + } + + first = last + 1; + } + + slot->metrics.horiAdvance = + ( slot->metrics.horiAdvance + distance*4 ) & ~63; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftsystem.c b/Utilities/vtkfreetype/src/base/ftsystem.c new file mode 100644 index 0000000..2365de2 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftsystem.c @@ -0,0 +1,303 @@ +/***************************************************************************/ +/* */ +/* ftsystem.c */ +/* */ +/* ANSI-specific FreeType low-level system interface (body). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This file contains the default interface used by FreeType to access */ + /* low-level, i.e. memory management, i/o access as well as thread */ + /* synchronisation. It can be replaced by user-specific routines if */ + /* necessary. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_DEBUG_H +#include FT_SYSTEM_H +#include FT_ERRORS_H +#include FT_TYPES_H + +#include <stdio.h> +#include <stdlib.h> + + + /*************************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* It is not necessary to do any error checking for the */ + /* allocation-related functions. This will be done by the higher level */ + /* routines like FT_Alloc() or FT_Realloc(). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_alloc */ + /* */ + /* <Description> */ + /* The memory allocation function. */ + /* */ + /* <Input> */ + /* memory :: A pointer to the memory object. */ + /* */ + /* size :: The requested size in bytes. */ + /* */ + /* <Return> */ + /* The address of newly allocated block. */ + /* */ + FT_CALLBACK_DEF( void* ) + ft_alloc( FT_Memory memory, + long size ) + { + FT_UNUSED( memory ); + + return malloc( size ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_realloc */ + /* */ + /* <Description> */ + /* The memory reallocation function. */ + /* */ + /* <Input> */ + /* memory :: A pointer to the memory object. */ + /* */ + /* cur_size :: The current size of the allocated memory block. */ + /* */ + /* new_size :: The newly requested size in bytes. */ + /* */ + /* block :: The current address of the block in memory. */ + /* */ + /* <Return> */ + /* The address of the reallocated memory block. */ + /* */ + FT_CALLBACK_DEF( void* ) + ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + FT_UNUSED( memory ); + FT_UNUSED( cur_size ); + + return realloc( block, new_size ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_free */ + /* */ + /* <Description> */ + /* The memory release function. */ + /* */ + /* <Input> */ + /* memory :: A pointer to the memory object. */ + /* */ + /* block :: The address of block in memory to be freed. */ + /* */ + FT_CALLBACK_DEF( void ) + ft_free( FT_Memory memory, + void* block ) + { + FT_UNUSED( memory ); + + free( block ); + } + + + /*************************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + /* We use the macro STREAM_FILE for convenience to extract the */ + /* system-specific stream handle from a given FreeType stream object */ +#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_ansi_stream_close */ + /* */ + /* <Description> */ + /* The function to close a stream. */ + /* */ + /* <Input> */ + /* stream :: A pointer to the stream object. */ + /* */ + FT_CALLBACK_DEF( void ) + ft_ansi_stream_close( FT_Stream stream ) + { + fclose( STREAM_FILE( stream ) ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_ansi_stream_io */ + /* */ + /* <Description> */ + /* The function to open a stream. */ + /* */ + /* <Input> */ + /* stream :: A pointer to the stream object. */ + /* */ + /* offset :: The position in the data stream to start reading. */ + /* */ + /* buffer :: The address of buffer to store the read data. */ + /* */ + /* count :: The number of bytes to read from the stream. */ + /* */ + /* <Return> */ + /* The number of bytes actually read. */ + /* */ + FT_CALLBACK_DEF( unsigned long ) + ft_ansi_stream_io( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ) + { + FILE* file; + + + file = STREAM_FILE( stream ); + + fseek( file, offset, SEEK_SET ); + + return (unsigned long)fread( buffer, 1, count, file ); + } + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Stream_Open( FT_Stream stream, + const char* filepathname ) + { + FILE* file; + + + if ( !stream ) + return FT_Err_Invalid_Stream_Handle; + + file = fopen( filepathname, "rb" ); + if ( !file ) + { + FT_ERROR(( "FT_Stream_Open:" )); + FT_ERROR(( " could not open `%s'\n", filepathname )); + + return FT_Err_Cannot_Open_Resource; + } + + fseek( file, 0, SEEK_END ); + stream->size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + stream->descriptor.pointer = file; + stream->pathname.pointer = (char*)filepathname; + stream->pos = 0; + + stream->read = ft_ansi_stream_io; + stream->close = ft_ansi_stream_close; + + FT_TRACE1(( "FT_Stream_Open:" )); + FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + filepathname, stream->size )); + + return FT_Err_Ok; + } + + +#ifdef FT_DEBUG_MEMORY + + extern FT_Int + ft_mem_debug_init( FT_Memory memory ); + + extern void + ft_mem_debug_done( FT_Memory memory ); + +#endif + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( FT_Memory ) + FT_New_Memory( void ) + { + FT_Memory memory; + + + memory = (FT_Memory)malloc( sizeof ( *memory ) ); + if ( memory ) + { + memory->user = 0; + memory->alloc = ft_alloc; + memory->realloc = ft_realloc; + memory->free = ft_free; +#ifdef FT_DEBUG_MEMORY + ft_mem_debug_init( memory ); +#endif + } + + return memory; + } + + + /* documentation is in ftobjs.h */ + + FT_EXPORT_DEF( void ) + FT_Done_Memory( FT_Memory memory ) + { +#ifdef FT_DEBUG_MEMORY + ft_mem_debug_done( memory ); +#endif + memory->free( memory, memory ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/fttrigon.c b/Utilities/vtkfreetype/src/base/fttrigon.c new file mode 100644 index 0000000..5347dd8 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/fttrigon.c @@ -0,0 +1,499 @@ +/***************************************************************************/ +/* */ +/* fttrigon.c */ +/* */ +/* FreeType trigonometric functions (body). */ +/* */ +/* Copyright 2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_TRIGONOMETRY_H + + + /* the following is 0.2715717684432231 * 2^30 */ +#define FT_TRIG_COSCALE 0x11616E8EUL + + /* this table was generated for FT_PI = 180L << 16, i.e. degrees */ +#define FT_TRIG_MAX_ITERS 23 + + static const FT_Fixed + ft_trig_arctan_table[24] = + { + 4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L, + 58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, + 57L, 29L, 14L, 7L, 4L, 2L, 1L + }; + + /* the Cordic shrink factor, multiplied by 2^32 */ +#define FT_TRIG_SCALE 1166391785UL /* 0x4585BA38UL */ + + +#ifdef FT_CONFIG_HAS_INT64 + + /* multiply a given value by the CORDIC shrink factor */ + static FT_Fixed + ft_trig_downscale( FT_Fixed val ) + { + FT_Fixed s; + FT_Int64 v; + + + s = val; + val = ( val >= 0 ) ? val : -val; + + v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL; + val = (FT_Fixed)( v >> 32 ); + + return ( s >= 0 ) ? val : -val; + } + +#else /* !FT_CONFIG_HAS_INT64 */ + + /* multiply a given value by the CORDIC shrink factor */ + static FT_Fixed + ft_trig_downscale( FT_Fixed val ) + { + FT_Fixed s; + FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3; + + + s = val; + val = ( val >= 0 ) ? val : -val; + + v1 = (FT_UInt32)val >> 16; + v2 = (FT_UInt32)val & 0xFFFFL; + + k1 = FT_TRIG_SCALE >> 16; /* constant */ + k2 = FT_TRIG_SCALE & 0xFFFFL; /* constant */ + + hi = k1 * v1; + lo1 = k1 * v2 + k2 * v1; /* can't overflow */ + + lo2 = ( k2 * v2 ) >> 16; + lo3 = ( lo1 >= lo2 ) ? lo1 : lo2; + lo1 += lo2; + + hi += lo1 >> 16; + if ( lo1 < lo3 ) + hi += 0x10000UL; + + val = (FT_Fixed)hi; + + return ( s >= 0 ) ? val : -val; + } + +#endif /* !FT_CONFIG_HAS_INT64 */ + + + static FT_Int + ft_trig_prenorm( FT_Vector* vec ) + { + FT_Fixed x, y, z; + FT_Int shift; + + + x = vec->x; + y = vec->y; + + z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y ); + shift = 0; + + if ( z < ( 1L << 27 ) ) + { + do + { + shift++; + z <<= 1; + } while ( z < ( 1L << 27 ) ); + + vec->x = x << shift; + vec->y = y << shift; + } + else if ( z > ( 1L << 28 ) ) + { + do + { + shift++; + z >>= 1; + } while ( z > ( 1L << 28 ) ); + + vec->x = x >> shift; + vec->y = y >> shift; + shift = -shift; + } + return shift; + } + + + static void + ft_trig_pseudo_rotate( FT_Vector* vec, + FT_Angle theta ) + { + FT_Int i; + FT_Fixed x, y, xtemp; + const FT_Fixed *arctanptr; + + + x = vec->x; + y = vec->y; + + /* Get angle between -90 and 90 degrees */ + while ( theta <= -FT_ANGLE_PI2 ) + { + x = -x; + y = -y; + theta += FT_ANGLE_PI; + } + + while ( theta > FT_ANGLE_PI2 ) + { + x = -x; + y = -y; + theta -= FT_ANGLE_PI; + } + + /* Initial pseudorotation, with left shift */ + arctanptr = ft_trig_arctan_table; + + if ( theta < 0 ) + { + xtemp = x + ( y << 1 ); + y = y - ( x << 1 ); + x = xtemp; + theta += *arctanptr++; + } + else + { + xtemp = x - ( y << 1 ); + y = y + ( x << 1 ); + x = xtemp; + theta -= *arctanptr++; + } + + /* Subsequent pseudorotations, with right shifts */ + i = 0; + do + { + if ( theta < 0 ) + { + xtemp = x + ( y >> i ); + y = y - ( x >> i ); + x = xtemp; + theta += *arctanptr++; + } + else + { + xtemp = x - ( y >> i ); + y = y + ( x >> i ); + x = xtemp; + theta -= *arctanptr++; + } + } while ( ++i < FT_TRIG_MAX_ITERS ); + + vec->x = x; + vec->y = y; + } + + + static void + ft_trig_pseudo_polarize( FT_Vector* vec ) + { + FT_Fixed theta; + FT_Fixed yi, i; + FT_Fixed x, y; + const FT_Fixed *arctanptr; + + + x = vec->x; + y = vec->y; + + /* Get the vector into the right half plane */ + theta = 0; + if ( x < 0 ) + { + x = -x; + y = -y; + theta = 2 * FT_ANGLE_PI2; + } + + if ( y > 0 ) + theta = - theta; + + arctanptr = ft_trig_arctan_table; + + if ( y < 0 ) + { + /* Rotate positive */ + yi = y + ( x << 1 ); + x = x - ( y << 1 ); + y = yi; + theta -= *arctanptr++; /* Subtract angle */ + } + else + { + /* Rotate negative */ + yi = y - ( x << 1 ); + x = x + ( y << 1 ); + y = yi; + theta += *arctanptr++; /* Add angle */ + } + + i = 0; + do + { + if ( y < 0 ) + { + /* Rotate positive */ + yi = y + ( x >> i ); + x = x - ( y >> i ); + y = yi; + theta -= *arctanptr++; + } + else + { + /* Rotate negative */ + yi = y - ( x >> i ); + x = x + ( y >> i ); + y = yi; + theta += *arctanptr++; + } + } while ( ++i < FT_TRIG_MAX_ITERS ); + + /* round theta */ + if ( theta >= 0 ) + theta = FT_PAD_ROUND( theta, 32 ); + else + theta = - FT_PAD_ROUND( -theta, 32 ); + + vec->x = x; + vec->y = theta; + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( FT_Fixed ) + FT_Cos( FT_Angle angle ) + { + FT_Vector v; + + + v.x = FT_TRIG_COSCALE >> 2; + v.y = 0; + ft_trig_pseudo_rotate( &v, angle ); + + return v.x / ( 1 << 12 ); + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( FT_Fixed ) + FT_Sin( FT_Angle angle ) + { + return FT_Cos( FT_ANGLE_PI2 - angle ); + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( FT_Fixed ) + FT_Tan( FT_Angle angle ) + { + FT_Vector v; + + + v.x = FT_TRIG_COSCALE >> 2; + v.y = 0; + ft_trig_pseudo_rotate( &v, angle ); + + return FT_DivFix( v.y, v.x ); + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( FT_Angle ) + FT_Atan2( FT_Fixed dx, + FT_Fixed dy ) + { + FT_Vector v; + + + if ( dx == 0 && dy == 0 ) + return 0; + + v.x = dx; + v.y = dy; + ft_trig_prenorm( &v ); + ft_trig_pseudo_polarize( &v ); + + return v.y; + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( void ) + FT_Vector_Unit( FT_Vector* vec, + FT_Angle angle ) + { + vec->x = FT_TRIG_COSCALE >> 2; + vec->y = 0; + ft_trig_pseudo_rotate( vec, angle ); + vec->x >>= 12; + vec->y >>= 12; + } + + + /* these macros return 0 for positive numbers, + and -1 for negative ones */ +#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) ) +#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) ) +#define FT_SIGN_INT32( x ) ( (x) >> 31 ) +#define FT_SIGN_INT16( x ) ( (x) >> 15 ) + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( void ) + FT_Vector_Rotate( FT_Vector* vec, + FT_Angle angle ) + { + FT_Int shift; + FT_Vector v; + + + v.x = vec->x; + v.y = vec->y; + + if ( angle && ( v.x != 0 || v.y != 0 ) ) + { + shift = ft_trig_prenorm( &v ); + ft_trig_pseudo_rotate( &v, angle ); + v.x = ft_trig_downscale( v.x ); + v.y = ft_trig_downscale( v.y ); + + if ( shift > 0 ) + { + FT_Int32 half = 1L << ( shift - 1 ); + + + vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift; + vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift; + } + else + { + shift = -shift; + vec->x = v.x << shift; + vec->y = v.y << shift; + } + } + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( FT_Fixed ) + FT_Vector_Length( FT_Vector* vec ) + { + FT_Int shift; + FT_Vector v; + + + v = *vec; + + /* handle trivial cases */ + if ( v.x == 0 ) + { + return ( v.y >= 0 ) ? v.y : -v.y; + } + else if ( v.y == 0 ) + { + return ( v.x >= 0 ) ? v.x : -v.x; + } + + /* general case */ + shift = ft_trig_prenorm( &v ); + ft_trig_pseudo_polarize( &v ); + + v.x = ft_trig_downscale( v.x ); + + if ( shift > 0 ) + return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift; + + return v.x << -shift; + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( void ) + FT_Vector_Polarize( FT_Vector* vec, + FT_Fixed *length, + FT_Angle *angle ) + { + FT_Int shift; + FT_Vector v; + + + v = *vec; + + if ( v.x == 0 && v.y == 0 ) + return; + + shift = ft_trig_prenorm( &v ); + ft_trig_pseudo_polarize( &v ); + + v.x = ft_trig_downscale( v.x ); + + *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift ); + *angle = v.y; + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( void ) + FT_Vector_From_Polar( FT_Vector* vec, + FT_Fixed length, + FT_Angle angle ) + { + vec->x = length; + vec->y = 0; + + FT_Vector_Rotate( vec, angle ); + } + + + /* documentation is in fttrigon.h */ + + FT_EXPORT_DEF( FT_Angle ) + FT_Angle_Diff( FT_Angle angle1, + FT_Angle angle2 ) + { + FT_Angle delta = angle2 - angle1; + + delta %= FT_ANGLE_2PI; + if ( delta < 0 ) + delta += FT_ANGLE_2PI; + + if ( delta > FT_ANGLE_PI ) + delta -= FT_ANGLE_2PI; + + return delta; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/fttype1.c b/Utilities/vtkfreetype/src/base/fttype1.c new file mode 100644 index 0000000..553b84f --- /dev/null +++ b/Utilities/vtkfreetype/src/base/fttype1.c @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* fttype1.c */ +/* */ +/* FreeType utility file for PS names support (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_SERVICE_H +#include FT_SERVICE_POSTSCRIPT_INFO_H + + + /* documentation is in t1tables.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Get_PS_Font_Info( FT_Face face, + PS_FontInfoRec* afont_info ) + { + FT_Error error = FT_Err_Invalid_Argument; + + + if ( face ) + { + FT_Service_PsInfo service = NULL; + + + FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO ); + + if ( service && service->ps_get_font_info ) + error = service->ps_get_font_info( face, afont_info ); + } + + return error; + } + + + /* documentation is in t1tables.h */ + + FT_EXPORT_DEF( FT_Int ) + FT_Has_PS_Glyph_Names( FT_Face face ) + { + FT_Int result = 0; + FT_Service_PsInfo service = NULL; + + + if ( face ) + { + FT_FACE_FIND_SERVICE( face, service, POSTSCRIPT_INFO ); + + if ( service && service->ps_has_glyph_names ) + result = service->ps_has_glyph_names( face ); + } + + return result; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftutil.c b/Utilities/vtkfreetype/src/base/ftutil.c new file mode 100644 index 0000000..9d3ec43 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftutil.c @@ -0,0 +1,397 @@ +/***************************************************************************/ +/* */ +/* ftutil.c */ +/* */ +/* FreeType utility file for memory and list management (body). */ +/* */ +/* Copyright 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_MEMORY_H +#include FT_LIST_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_memory + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** *****/ + /***** M E M O R Y M A N A G E M E N T *****/ + /***** *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* documentation is in ftmemory.h */ + + FT_BASE_DEF( FT_Error ) + FT_Alloc( FT_Memory memory, + FT_Long size, + void* *P ) + { + FT_ASSERT( P != 0 ); + + if ( size > 0 ) + { + *P = memory->alloc( memory, size ); + if ( !*P ) + { + FT_ERROR(( "FT_Alloc:" )); + FT_ERROR(( " Out of memory? (%ld requested)\n", + size )); + + return FT_Err_Out_Of_Memory; + } + FT_MEM_ZERO( *P, size ); + } + else + *P = NULL; + + FT_TRACE7(( "FT_Alloc:" )); + FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n", + size, *P, P )); + + return FT_Err_Ok; + } + + + FT_BASE_DEF( FT_Error ) + FT_QAlloc( FT_Memory memory, + FT_Long size, + void* *P ) + { + FT_ASSERT( P != 0 ); + + if ( size > 0 ) + { + *P = memory->alloc( memory, size ); + if ( !*P ) + { + FT_ERROR(( "FT_QAlloc:" )); + FT_ERROR(( " Out of memory? (%ld requested)\n", + size )); + + return FT_Err_Out_Of_Memory; + } + } + else + *P = NULL; + + FT_TRACE7(( "FT_QAlloc:" )); + FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n", + size, *P, P )); + + return FT_Err_Ok; + } + + + /* documentation is in ftmemory.h */ + + FT_BASE_DEF( FT_Error ) + FT_Realloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void** P ) + { + void* Q; + + + FT_ASSERT( P != 0 ); + + /* if the original pointer is NULL, call FT_Alloc() */ + if ( !*P ) + return FT_Alloc( memory, size, P ); + + /* if the new block if zero-sized, clear the current one */ + if ( size <= 0 ) + { + FT_Free( memory, P ); + return FT_Err_Ok; + } + + Q = memory->realloc( memory, current, size, *P ); + if ( !Q ) + goto Fail; + + if ( size > current ) + FT_MEM_ZERO( (char*)Q + current, size - current ); + + *P = Q; + return FT_Err_Ok; + + Fail: + FT_ERROR(( "FT_Realloc:" )); + FT_ERROR(( " Failed (current %ld, requested %ld)\n", + current, size )); + return FT_Err_Out_Of_Memory; + } + + + FT_BASE_DEF( FT_Error ) + FT_QRealloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void** P ) + { + void* Q; + + + FT_ASSERT( P != 0 ); + + /* if the original pointer is NULL, call FT_QAlloc() */ + if ( !*P ) + return FT_QAlloc( memory, size, P ); + + /* if the new block if zero-sized, clear the current one */ + if ( size <= 0 ) + { + FT_Free( memory, P ); + return FT_Err_Ok; + } + + Q = memory->realloc( memory, current, size, *P ); + if ( !Q ) + goto Fail; + + *P = Q; + return FT_Err_Ok; + + Fail: + FT_ERROR(( "FT_QRealloc:" )); + FT_ERROR(( " Failed (current %ld, requested %ld)\n", + current, size )); + return FT_Err_Out_Of_Memory; + } + + + /* documentation is in ftmemory.h */ + + FT_BASE_DEF( void ) + FT_Free( FT_Memory memory, + void** P ) + { + FT_TRACE7(( "FT_Free:" )); + FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n", + P, P ? *P : (void*)0 )); + + if ( P && *P ) + { + memory->free( memory, *P ); + *P = 0; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** *****/ + /***** D O U B L Y L I N K E D L I S T S *****/ + /***** *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + +#undef FT_COMPONENT +#define FT_COMPONENT trace_list + + /* documentation is in ftlist.h */ + + FT_EXPORT_DEF( FT_ListNode ) + FT_List_Find( FT_List list, + void* data ) + { + FT_ListNode cur; + + + cur = list->head; + while ( cur ) + { + if ( cur->data == data ) + return cur; + + cur = cur->next; + } + + return (FT_ListNode)0; + } + + + /* documentation is in ftlist.h */ + + FT_EXPORT_DEF( void ) + FT_List_Add( FT_List list, + FT_ListNode node ) + { + FT_ListNode before = list->tail; + + + node->next = 0; + node->prev = before; + + if ( before ) + before->next = node; + else + list->head = node; + + list->tail = node; + } + + + /* documentation is in ftlist.h */ + + FT_EXPORT_DEF( void ) + FT_List_Insert( FT_List list, + FT_ListNode node ) + { + FT_ListNode after = list->head; + + + node->next = after; + node->prev = 0; + + if ( !after ) + list->tail = node; + else + after->prev = node; + + list->head = node; + } + + + /* documentation is in ftlist.h */ + + FT_EXPORT_DEF( void ) + FT_List_Remove( FT_List list, + FT_ListNode node ) + { + FT_ListNode before, after; + + + before = node->prev; + after = node->next; + + if ( before ) + before->next = after; + else + list->head = after; + + if ( after ) + after->prev = before; + else + list->tail = before; + } + + + /* documentation is in ftlist.h */ + + FT_EXPORT_DEF( void ) + FT_List_Up( FT_List list, + FT_ListNode node ) + { + FT_ListNode before, after; + + + before = node->prev; + after = node->next; + + /* check whether we are already on top of the list */ + if ( !before ) + return; + + before->next = after; + + if ( after ) + after->prev = before; + else + list->tail = before; + + node->prev = 0; + node->next = list->head; + list->head->prev = node; + list->head = node; + } + + + /* documentation is in ftlist.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_List_Iterate( FT_List list, + FT_List_Iterator iterator, + void* user ) + { + FT_ListNode cur = list->head; + FT_Error error = FT_Err_Ok; + + + while ( cur ) + { + FT_ListNode next = cur->next; + + + error = iterator( cur, user ); + if ( error ) + break; + + cur = next; + } + + return error; + } + + + /* documentation is in ftlist.h */ + + FT_EXPORT_DEF( void ) + FT_List_Finalize( FT_List list, + FT_List_Destructor destroy, + FT_Memory memory, + void* user ) + { + FT_ListNode cur; + + + cur = list->head; + while ( cur ) + { + FT_ListNode next = cur->next; + void* data = cur->data; + + + if ( destroy ) + destroy( memory, data, user ); + + FT_FREE( cur ); + cur = next; + } + + list->head = 0; + list->tail = 0; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftwinfnt.c b/Utilities/vtkfreetype/src/base/ftwinfnt.c new file mode 100644 index 0000000..46f618c --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftwinfnt.c @@ -0,0 +1,49 @@ +/***************************************************************************/ +/* */ +/* ftwinfnt.c */ +/* */ +/* FreeType API for accessing Windows FNT specific info (body). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_WINFONTS_H +#include FT_INTERNAL_OBJECTS_H +#include FT_SERVICE_WINFNT_H + + + FT_EXPORT_DEF( FT_Error ) + FT_Get_WinFNT_Header( FT_Face face, + FT_WinFNT_HeaderRec *header ) + { + FT_Service_WinFnt service; + FT_Error error; + + + error = FT_Err_Invalid_Argument; + + if ( face != NULL ) + { + FT_FACE_LOOKUP_SERVICE( face, service, WINFNT ); + + if ( service != NULL ) + { + error = service->get_header( face, header ); + } + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/base/ftxf86.c b/Utilities/vtkfreetype/src/base/ftxf86.c new file mode 100644 index 0000000..04e8023 --- /dev/null +++ b/Utilities/vtkfreetype/src/base/ftxf86.c @@ -0,0 +1,37 @@ +/***************************************************************************/ +/* */ +/* ftxf86.c */ +/* */ +/* FreeType utility file for X11 support (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_XFREE86_H +#include FT_INTERNAL_OBJECTS_H +#include FT_SERVICE_XFREE86_NAME_H + + FT_EXPORT_DEF( const char* ) + FT_Get_X11_Font_Format( FT_Face face ) + { + const char* result = NULL; + + + if ( face ) + FT_FACE_FIND_SERVICE( face, result, XF86_NAME ); + + return result; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/bdf/README b/Utilities/vtkfreetype/src/bdf/README new file mode 100644 index 0000000..d45e4fb --- /dev/null +++ b/Utilities/vtkfreetype/src/bdf/README @@ -0,0 +1,148 @@ + FreeType font driver for BDF fonts + + Francesco Zappa Nardelli + <francesco.zappa.nardelli@ens.fr> + + +Introduction +************ + +BDF (Bitmap Distribution Format) is a bitmap font format defined by Adobe, +which is intended to be easily understood by both humans and computers. +This code implements a BDF driver for the FreeType library, following the +Adobe Specification V 2.2. The specification of the BDF font format is +available from Adobe's web site: + + http://partners.adobe.com/asn/developer/PDFS/TN/5005.BDF_Spec.pdf + +Many good bitmap fonts in bdf format come with XFree86 (www.XFree86.org). +They do not define vertical metrics, because the X Consortium BDF +specification has removed them. + + +Encodings +********* + +The variety of encodings that accompanies bdf fonts appears to encompass the +small set defined in freetype.h. On the other hand, two properties that +specify encoding and registry are usually defined in bdf fonts. + +I decided to make these two properties directly accessible, leaving to the +client application the work of interpreting them. For instance: + + + #include FT_INTERNAL_BDF_TYPES_H + + FT_Face face; + BDF_Public_Face bdfface; + + + FT_New_Face( library, ..., &face ); + + bdfface = (BDF_Public_Face)face; + + if ( ( bdfface->charset_registry == "ISO10646" ) && + ( bdfface->charset_encoding == "1" ) ) + [..] + + +Thus the driver always exports `ft_encoding_none' as face->charmap.encoding. +FT_Get_Char_Index's behavior is unmodified, that is, it converts the ULong +value given as argument into the corresponding glyph number. + +If the two properties are not available, Adobe Standard Encoding should be +assumed. + + +Anti-Aliased Bitmaps +******************** + +The driver supports an extension to the BDF format as used in Mark Leisher's +xmbdfed bitmap font editor. Microsoft's SBIT tool expects bitmap fonts in +that format for adding anti-aliased them to TrueType fonts. It introduces a +fourth field to the `SIZE' keyword which gives the bpp value (bits per +pixel) of the glyph data in the font. Possible values are 1 (the default), +2 (four gray levels), 4 (16 gray levels), and 8 (256 gray levels). The +driver returns either a bitmap with 1 bit per pixel or a pixmap with 8bits +per pixel (using 4, 16, and 256 gray levels, respectively). + + +Known problems +************** + +- A font is entirely loaded into memory. Obviously, this is not the Right + Thing(TM). If you have big fonts I suggest you convert them into PCF + format (using the bdftopcf utility): the PCF font drive of FreeType can + perform incremental glyph loading. + +When I have some time, I will implement on-demand glyph parsing. + +- Except for encodings properties, client applications have no visibility of + the PCF_Face object. This means that applications cannot directly access + font tables and must trust FreeType. + +- Currently, glyph names are ignored. + + I plan to give full visibility of the BDF_Face object in an upcoming + revision of the driver, thus implementing also glyph names. + +- As I have never seen a BDF font that defines vertical metrics, vertical + metrics are (parsed and) discarded. If you own a BDF font that defines + vertical metrics, please let me know (I will implement them in 5-10 + minutes). + + +License +******* + +Copyright (C) 2001-2002 by Francesco Zappa Nardelli + +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. + +*** Portions of the driver (that is, bdflib.c and bdf.h): + +Copyright 2000 Computing Research Labs, New Mexico State University +Copyright 2001-2002 Francesco Zappa Nardelli + +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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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. + + +Credits +******* + +This driver is based on excellent Mark Leisher's bdf library. If you +find something good in this driver you should probably thank him, not +me. diff --git a/Utilities/vtkfreetype/src/bdf/bdf.c b/Utilities/vtkfreetype/src/bdf/bdf.c new file mode 100644 index 0000000..9c82885 --- /dev/null +++ b/Utilities/vtkfreetype/src/bdf/bdf.c @@ -0,0 +1,34 @@ +/* bdf.c + + FreeType font driver for bdf files + + Copyright (C) 2001, 2002 by + Francesco Zappa Nardelli + +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. +*/ + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "bdflib.c" +#include "bdfdrivr.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/bdf/bdf.h b/Utilities/vtkfreetype/src/bdf/bdf.h new file mode 100644 index 0000000..b42baa6 --- /dev/null +++ b/Utilities/vtkfreetype/src/bdf/bdf.h @@ -0,0 +1,295 @@ +/* + * Copyright 2000 Computing Research Labs, New Mexico State University + * Copyright 2001, 2002, 2003, 2004 Francesco Zappa Nardelli + * + * 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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef __BDF_H__ +#define __BDF_H__ + + +/* + * Based on bdf.h,v 1.16 2000/03/16 20:08:51 mleisher + */ + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_STREAM_H + + +FT_BEGIN_HEADER + + +/* Imported from bdfP.h */ + +#define _bdf_glyph_modified( map, e ) \ + ( (map)[(e) >> 5] & ( 1 << ( (e) & 31 ) ) ) +#define _bdf_set_glyph_modified( map, e ) \ + ( (map)[(e) >> 5] |= ( 1 << ( (e) & 31 ) ) ) +#define _bdf_clear_glyph_modified( map, e ) \ + ( (map)[(e) >> 5] &= ~( 1 << ( (e) & 31 ) ) ) + +/* end of bdfP.h */ + + + /*************************************************************************/ + /* */ + /* BDF font options macros and types. */ + /* */ + /*************************************************************************/ + + +#define BDF_CORRECT_METRICS 0x01 /* Correct invalid metrics when loading. */ +#define BDF_KEEP_COMMENTS 0x02 /* Preserve the font comments. */ +#define BDF_KEEP_UNENCODED 0x04 /* Keep the unencoded glyphs. */ +#define BDF_PROPORTIONAL 0x08 /* Font has proportional spacing. */ +#define BDF_MONOWIDTH 0x10 /* Font has mono width. */ +#define BDF_CHARCELL 0x20 /* Font has charcell spacing. */ + +#define BDF_ALL_SPACING ( BDF_PROPORTIONAL | \ + BDF_MONOWIDTH | \ + BDF_CHARCELL ) + +#define BDF_DEFAULT_LOAD_OPTIONS ( BDF_CORRECT_METRICS | \ + BDF_KEEP_COMMENTS | \ + BDF_KEEP_UNENCODED | \ + BDF_PROPORTIONAL ) + + + typedef struct bdf_options_t_ + { + int correct_metrics; + int keep_unencoded; + int keep_comments; + int font_spacing; + + } bdf_options_t; + + + /* Callback function type for unknown configuration options. */ + typedef int + (*bdf_options_callback_t)( bdf_options_t* opts, + char** params, + unsigned long nparams, + void* client_data ); + + + /*************************************************************************/ + /* */ + /* BDF font property macros and types. */ + /* */ + /*************************************************************************/ + + +#define BDF_ATOM 1 +#define BDF_INTEGER 2 +#define BDF_CARDINAL 3 + + + /* This structure represents a particular property of a font. */ + /* There are a set of defaults and each font has their own. */ + typedef struct bdf_property_t_ + { + char* name; /* Name of the property. */ + int format; /* Format of the property. */ + int builtin; /* A builtin property. */ + union + { + char* atom; + long int32; + unsigned long card32; + + } value; /* Value of the property. */ + + } bdf_property_t; + + + /*************************************************************************/ + /* */ + /* BDF font metric and glyph types. */ + /* */ + /*************************************************************************/ + + + typedef struct bdf_bbx_t_ + { + unsigned short width; + unsigned short height; + + short x_offset; + short y_offset; + + short ascent; + short descent; + + } bdf_bbx_t; + + + typedef struct bdf_glyph_t_ + { + char* name; /* Glyph name. */ + long encoding; /* Glyph encoding. */ + unsigned short swidth; /* Scalable width. */ + unsigned short dwidth; /* Device width. */ + bdf_bbx_t bbx; /* Glyph bounding box. */ + unsigned char* bitmap; /* Glyph bitmap. */ + unsigned long bpr; /* Number of bytes used per row. */ + unsigned short bytes; /* Number of bytes used for the bitmap. */ + + } bdf_glyph_t; + + + typedef struct _hashnode_ + { + const char* key; + void* data; + + } _hashnode, *hashnode; + + + typedef struct hashtable_ + { + int limit; + int size; + int used; + hashnode* table; + + } hashtable; + + + typedef struct bdf_glyphlist_t_ + { + unsigned short pad; /* Pad to 4-byte boundary. */ + unsigned short bpp; /* Bits per pixel. */ + long start; /* Beginning encoding value of glyphs. */ + long end; /* Ending encoding value of glyphs. */ + bdf_glyph_t* glyphs; /* Glyphs themselves. */ + unsigned long glyphs_size; /* Glyph structures allocated. */ + unsigned long glyphs_used; /* Glyph structures used. */ + bdf_bbx_t bbx; /* Overall bounding box of glyphs. */ + + } bdf_glyphlist_t; + + + typedef struct bdf_font_t_ + { + char* name; /* Name of the font. */ + bdf_bbx_t bbx; /* Font bounding box. */ + + long point_size; /* Point size of the font. */ + unsigned long resolution_x; /* Font horizontal resolution. */ + unsigned long resolution_y; /* Font vertical resolution. */ + + int spacing; /* Font spacing value. */ + + unsigned short monowidth; /* Logical width for monowidth font. */ + + long default_char; /* Encoding of the default glyph. */ + + long font_ascent; /* Font ascent. */ + long font_descent; /* Font descent. */ + + unsigned long glyphs_size; /* Glyph structures allocated. */ + unsigned long glyphs_used; /* Glyph structures used. */ + bdf_glyph_t* glyphs; /* Glyphs themselves. */ + + unsigned long unencoded_size; /* Unencoded glyph struct. allocated. */ + unsigned long unencoded_used; /* Unencoded glyph struct. used. */ + bdf_glyph_t* unencoded; /* Unencoded glyphs themselves. */ + + unsigned long props_size; /* Font properties allocated. */ + unsigned long props_used; /* Font properties used. */ + bdf_property_t* props; /* Font properties themselves. */ + + char* comments; /* Font comments. */ + unsigned long comments_len; /* Length of comment string. */ + + bdf_glyphlist_t overflow; /* Storage used for glyph insertion. */ + + void* internal; /* Internal data for the font. */ + + unsigned long nmod[2048]; /* Bitmap indicating modified glyphs. */ + unsigned long umod[2048]; /* Bitmap indicating modified */ + /* unencoded glyphs. */ + unsigned short modified; /* Boolean indicating font modified. */ + unsigned short bpp; /* Bits per pixel. */ + + FT_Memory memory; + + bdf_property_t* user_props; + unsigned long nuser_props; + hashtable proptbl; + + } bdf_font_t; + + + /*************************************************************************/ + /* */ + /* Types for load/save callbacks. */ + /* */ + /*************************************************************************/ + + + /* Error codes. */ +#define BDF_MISSING_START -1 +#define BDF_MISSING_FONTNAME -2 +#define BDF_MISSING_SIZE -3 +#define BDF_MISSING_CHARS -4 +#define BDF_MISSING_STARTCHAR -5 +#define BDF_MISSING_ENCODING -6 +#define BDF_MISSING_BBX -7 + +#define BDF_OUT_OF_MEMORY -20 + +#define BDF_INVALID_LINE -100 + + + /*************************************************************************/ + /* */ + /* BDF font API. */ + /* */ + /*************************************************************************/ + + FT_LOCAL( FT_Error ) + bdf_load_font( FT_Stream stream, + FT_Memory memory, + bdf_options_t* opts, + bdf_font_t* *font ); + + FT_LOCAL( void ) + bdf_free_font( bdf_font_t* font ); + + FT_LOCAL( bdf_property_t * ) + bdf_get_property( char* name, + bdf_font_t* font ); + + FT_LOCAL( bdf_property_t * ) + bdf_get_font_property( bdf_font_t* font, + const char* name ); + + +FT_END_HEADER + + +#endif /* __BDF_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/bdf/bdfdrivr.c b/Utilities/vtkfreetype/src/bdf/bdfdrivr.c new file mode 100644 index 0000000..8f33d53 --- /dev/null +++ b/Utilities/vtkfreetype/src/bdf/bdfdrivr.c @@ -0,0 +1,915 @@ +/* bdfdrivr.c + + FreeType font driver for bdf files + + Copyright (C) 2001, 2002, 2003, 2004 by + Francesco Zappa Nardelli + +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. +*/ + +#include <ft2build.h> + +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H +#include FT_BDF_H + +#include FT_SERVICE_BDF_H +#include FT_SERVICE_XFREE86_NAME_H + +#include "bdf.h" +#include "bdfdrivr.h" + +#include "bdferror.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_bdfdriver + + + typedef struct BDF_CMapRec_ + { + FT_CMapRec cmap; + FT_UInt num_encodings; + BDF_encoding_el* encodings; + + } BDF_CMapRec, *BDF_CMap; + + + FT_CALLBACK_DEF( FT_Error ) + bdf_cmap_init( FT_CMap bdfcmap, + FT_Pointer init_data ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + BDF_Face face = (BDF_Face)FT_CMAP_FACE( cmap ); + FT_UNUSED( init_data ); + + + cmap->num_encodings = face->bdffont->glyphs_used; + cmap->encodings = face->en_table; + + return BDF_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + bdf_cmap_done( FT_CMap bdfcmap ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + + + cmap->encodings = NULL; + cmap->num_encodings = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + bdf_cmap_char_index( FT_CMap bdfcmap, + FT_UInt32 charcode ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + BDF_encoding_el* encodings = cmap->encodings; + FT_UInt min, max, mid; + FT_UInt result = 0; + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_UInt32 code; + + + mid = ( min + max ) >> 1; + code = encodings[mid].enc; + + if ( charcode == code ) + { + /* increase glyph index by 1 -- */ + /* we reserve slot 0 for the undefined glyph */ + result = encodings[mid].glyph + 1; + break; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + bdf_cmap_char_next( FT_CMap bdfcmap, + FT_UInt32 *acharcode ) + { + BDF_CMap cmap = (BDF_CMap)bdfcmap; + BDF_encoding_el* encodings = cmap->encodings; + FT_UInt min, max, mid; + FT_UInt32 charcode = *acharcode + 1; + FT_UInt result = 0; + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_UInt32 code; + + + mid = ( min + max ) >> 1; + code = encodings[mid].enc; + + if ( charcode == code ) + { + /* increase glyph index by 1 -- */ + /* we reserve slot 0 for the undefined glyph */ + result = encodings[mid].glyph + 1; + goto Exit; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + charcode = 0; + if ( min < cmap->num_encodings ) + { + charcode = encodings[min].enc; + result = encodings[min].glyph + 1; + } + + Exit: + *acharcode = charcode; + return result; + } + + + FT_CALLBACK_TABLE_DEF + const FT_CMap_ClassRec bdf_cmap_class = + { + sizeof ( BDF_CMapRec ), + bdf_cmap_init, + bdf_cmap_done, + bdf_cmap_char_index, + bdf_cmap_char_next + }; + + + static FT_Error + bdf_interpret_style( BDF_Face bdf ) + { + FT_Error error = BDF_Err_Ok; + FT_Face face = FT_FACE( bdf ); + FT_Memory memory = face->memory; + bdf_font_t* font = bdf->bdffont; + bdf_property_t* prop; + + char *istr = NULL, *bstr = NULL; + char *sstr = NULL, *astr = NULL; + + int parts = 0, len = 0; + + + face->style_flags = 0; + + prop = bdf_get_font_property( font, (char *)"SLANT" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && + ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' || + *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) ) + { + face->style_flags |= FT_STYLE_FLAG_ITALIC; + istr = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ) + ? (char *)"Oblique" + : (char *)"Italic"; + len += ft_strlen( istr ); + parts++; + } + + prop = bdf_get_font_property( font, (char *)"WEIGHT_NAME" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && + ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) ) + { + face->style_flags |= FT_STYLE_FLAG_BOLD; + bstr = (char *)"Bold"; + len += ft_strlen( bstr ); + parts++; + } + + prop = bdf_get_font_property( font, (char *)"SETWIDTH_NAME" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && *(prop->value.atom) && + !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) + { + sstr = (char *)(prop->value.atom); + len += ft_strlen( sstr ); + parts++; + } + + prop = bdf_get_font_property( font, (char *)"ADD_STYLE_NAME" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && *(prop->value.atom) && + !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) + { + astr = (char *)(prop->value.atom); + len += ft_strlen( astr ); + parts++; + } + + if ( !parts || !len ) + face->style_name = (char *)"Regular"; + else + { + char *style, *s; + unsigned int i; + + + if ( FT_ALLOC( style, len + parts ) ) + return error; + + s = style; + + if ( astr ) + { + ft_strcpy( s, astr ); + for ( i = 0; i < ft_strlen( astr ); i++, s++ ) + if ( *s == ' ' ) + *s = '-'; /* replace spaces with dashes */ + *(s++) = ' '; + } + if ( bstr ) + { + ft_strcpy( s, bstr ); + s += ft_strlen( bstr ); + *(s++) = ' '; + } + if ( istr ) + { + ft_strcpy( s, istr ); + s += ft_strlen( istr ); + *(s++) = ' '; + } + if ( sstr ) + { + ft_strcpy( s, sstr ); + for ( i = 0; i < ft_strlen( sstr ); i++, s++ ) + if ( *s == ' ' ) + *s = '-'; /* replace spaces with dashes */ + *(s++) = ' '; + } + *(--s) = '\0'; /* overwrite last ' ', terminate the string */ + + face->style_name = style; /* allocated string */ + } + + return error; + } + + + FT_CALLBACK_DEF( void ) + BDF_Face_Done( FT_Face bdfface ) /* BDF_Face */ + { + BDF_Face face = (BDF_Face)bdfface; + FT_Memory memory = FT_FACE_MEMORY( face ); + + + bdf_free_font( face->bdffont ); + + FT_FREE( face->en_table ); + + FT_FREE( face->charset_encoding ); + FT_FREE( face->charset_registry ); + FT_FREE( bdfface->family_name ); + + FT_FREE( bdfface->available_sizes ); + + FT_FREE( face->bdffont ); + + FT_TRACE4(( "BDF_Face_Done: done face\n" )); + } + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Face_Init( FT_Stream stream, + FT_Face bdfface, /* BDF_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error = BDF_Err_Ok; + BDF_Face face = (BDF_Face)bdfface; + FT_Memory memory = FT_FACE_MEMORY( face ); + + bdf_font_t* font; + bdf_options_t options; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + + + if ( FT_STREAM_SEEK( 0 ) ) + goto Exit; + + options.correct_metrics = 1; /* FZ XXX: options semantics */ + options.keep_unencoded = 1; + options.keep_comments = 0; + options.font_spacing = BDF_PROPORTIONAL; + + error = bdf_load_font( stream, memory, &options, &font ); + if ( error == BDF_Err_Missing_Startfont_Field ) + { + FT_TRACE2(( "[not a valid BDF file]\n" )); + goto Fail; + } + else if ( error ) + goto Exit; + + /* we have a bdf font: let's construct the face object */ + face->bdffont = font; + { + bdf_property_t* prop = NULL; + + + FT_TRACE4(( "number of glyphs: %d (%d)\n", + font->glyphs_size, + font->glyphs_used )); + FT_TRACE4(( "number of unencoded glyphs: %d (%d)\n", + font->unencoded_size, + font->unencoded_used )); + + bdfface->num_faces = 1; + bdfface->face_index = 0; + bdfface->face_flags = FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL | + FT_FACE_FLAG_FAST_GLYPHS; + + prop = bdf_get_font_property( font, "SPACING" ); + if ( prop && prop->format == BDF_ATOM && + prop->value.atom && + ( *(prop->value.atom) == 'M' || *(prop->value.atom) == 'm' || + *(prop->value.atom) == 'C' || *(prop->value.atom) == 'c' ) ) + bdfface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* FZ XXX: TO DO: FT_FACE_FLAGS_VERTICAL */ + /* FZ XXX: I need a font to implement this */ + + prop = bdf_get_font_property( font, "FAMILY_NAME" ); + if ( prop && prop->value.atom ) + { + int l = ft_strlen( prop->value.atom ) + 1; + + + if ( FT_NEW_ARRAY( bdfface->family_name, l ) ) + goto Exit; + ft_strcpy( bdfface->family_name, prop->value.atom ); + } + else + bdfface->family_name = 0; + + if ( ( error = bdf_interpret_style( face ) ) != 0 ) + goto Exit; + + /* the number of glyphs (with one slot for the undefined glyph */ + /* at position 0 and all unencoded glyphs) */ + bdfface->num_glyphs = font->glyphs_size + 1; + + bdfface->num_fixed_sizes = 1; + if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) ) + goto Exit; + + { + FT_Bitmap_Size* bsize = bdfface->available_sizes; + FT_Short resolution_x = 0, resolution_y = 0; + + + FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) ); + + bsize->height = font->font_ascent + font->font_descent; + + prop = bdf_get_font_property( font, "AVERAGE_WIDTH" ); + if ( prop ) + bsize->width = (FT_Short)( ( prop->value.int32 + 5 ) / 10 ); + else + bsize->width = bsize->height * 2/3; + + prop = bdf_get_font_property( font, "POINT_SIZE" ); + if ( prop ) + /* convert from 722.7 decipoints to 72 points per inch */ + bsize->size = + (FT_Pos)( ( prop->value.int32 * 64 * 7200 + 36135L ) / 72270L ); + + prop = bdf_get_font_property( font, "PIXEL_SIZE" ); + if ( prop ) + bsize->y_ppem = (FT_Short)prop->value.int32 << 6; + + prop = bdf_get_font_property( font, "RESOLUTION_X" ); + if ( prop ) + resolution_x = (FT_Short)prop->value.int32; + + prop = bdf_get_font_property( font, "RESOLUTION_Y" ); + if ( prop ) + resolution_y = (FT_Short)prop->value.int32; + + if ( bsize->y_ppem == 0 ) + { + bsize->y_ppem = bsize->size; + if ( resolution_y ) + bsize->y_ppem = bsize->y_ppem * resolution_y / 72; + } + if ( resolution_x && resolution_y ) + bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y; + else + bsize->x_ppem = bsize->y_ppem; + } + + /* encoding table */ + { + bdf_glyph_t* cur = font->glyphs; + unsigned long n; + + + if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) ) + goto Exit; + + face->default_glyph = 0; + for ( n = 0; n < font->glyphs_size; n++ ) + { + (face->en_table[n]).enc = cur[n].encoding; + FT_TRACE4(( "idx %d, val 0x%lX\n", n, cur[n].encoding )); + (face->en_table[n]).glyph = (FT_Short)n; + + if ( cur[n].encoding == font->default_char ) + face->default_glyph = n; + } + } + + /* charmaps */ + { + bdf_property_t *charset_registry = 0, *charset_encoding = 0; + FT_Bool unicode_charmap = 0; + + + charset_registry = + bdf_get_font_property( font, "CHARSET_REGISTRY" ); + charset_encoding = + bdf_get_font_property( font, "CHARSET_ENCODING" ); + if ( charset_registry && charset_encoding ) + { + if ( charset_registry->format == BDF_ATOM && + charset_encoding->format == BDF_ATOM && + charset_registry->value.atom && + charset_encoding->value.atom ) + { + const char* s; + + + if ( FT_NEW_ARRAY( face->charset_encoding, + ft_strlen( charset_encoding->value.atom ) + 1 ) ) + goto Exit; + if ( FT_NEW_ARRAY( face->charset_registry, + ft_strlen( charset_registry->value.atom ) + 1 ) ) + goto Exit; + + ft_strcpy( face->charset_registry, charset_registry->value.atom ); + ft_strcpy( face->charset_encoding, charset_encoding->value.atom ); + + /* Uh, oh, compare first letters manually to avoid dependency + on locales. */ + s = face->charset_registry; + if ( ( s[0] == 'i' || s[0] == 'I' ) && + ( s[1] == 's' || s[1] == 'S' ) && + ( s[2] == 'o' || s[2] == 'O' ) ) + { + s += 3; + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( face->charset_encoding, "1" ) ) ) + unicode_charmap = 1; + } + + { + FT_CharMapRec charmap; + + + charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_NONE; + charmap.platform_id = 0; + charmap.encoding_id = 0; + + if ( unicode_charmap ) + { + charmap.encoding = FT_ENCODING_UNICODE; + charmap.platform_id = 3; + charmap.encoding_id = 1; + } + + error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); + +#if 0 + /* Select default charmap */ + if ( bdfface->num_charmaps ) + bdfface->charmap = bdfface->charmaps[0]; +#endif + } + + goto Exit; + } + } + + /* otherwise assume Adobe standard encoding */ + + { + FT_CharMapRec charmap; + + + charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_ADOBE_STANDARD; + charmap.platform_id = 7; + charmap.encoding_id = 0; + + error = FT_CMap_New( &bdf_cmap_class, NULL, &charmap, NULL ); + + /* Select default charmap */ + if ( bdfface->num_charmaps ) + bdfface->charmap = bdfface->charmaps[0]; + } + } + } + + Exit: + return error; + + Fail: + BDF_Face_Done( bdfface ); + return BDF_Err_Unknown_File_Format; + } + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Set_Pixel_Size( FT_Size size, + FT_UInt char_width, + FT_UInt char_height ) + { + BDF_Face face = (BDF_Face)FT_SIZE_FACE( size ); + FT_Face root = FT_FACE( face ); + + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + + + FT_TRACE4(( "rec %d - pres %d\n", + size->metrics.y_ppem, root->available_sizes->y_ppem )); + + if ( size->metrics.y_ppem == root->available_sizes->y_ppem >> 6 ) + { + size->metrics.ascender = face->bdffont->font_ascent << 6; + size->metrics.descender = -face->bdffont->font_descent << 6; + size->metrics.height = ( face->bdffont->font_ascent + + face->bdffont->font_descent ) << 6; + size->metrics.max_advance = face->bdffont->bbx.width << 6; + + return BDF_Err_Ok; + } + else + return BDF_Err_Invalid_Pixel_Size; + } + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Set_Point_Size( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + FT_UNUSED( horz_resolution ); + FT_UNUSED( vert_resolution ); + + return BDF_Set_Pixel_Size( size, 0, 0 ); + } + + + FT_CALLBACK_DEF( FT_Error ) + BDF_Glyph_Load( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + BDF_Face face = (BDF_Face)FT_SIZE_FACE( size ); + FT_Error error = BDF_Err_Ok; + FT_Bitmap* bitmap = &slot->bitmap; + bdf_glyph_t glyph; + int bpp = face->bdffont->bpp; + int i, j, count; + unsigned char *p, *pp; + + FT_UNUSED( load_flags ); + + + if ( !face ) + { + error = BDF_Err_Invalid_Argument; + goto Exit; + } + + /* index 0 is the undefined glyph */ + if ( glyph_index == 0 ) + glyph_index = face->default_glyph; + else + glyph_index--; + + /* slot, bitmap => freetype, glyph => bdflib */ + glyph = face->bdffont->glyphs[glyph_index]; + + bitmap->rows = glyph.bbx.height; + bitmap->width = glyph.bbx.width; + + if ( bpp == 1 ) + { + bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + bitmap->pitch = glyph.bpr; + + /* note: we don't allocate a new array to hold the bitmap, we */ + /* can simply point to it */ + ft_glyphslot_set_bitmap( slot, glyph.bitmap ); + } + else + { + /* blow up pixmap to have 8 bits per pixel */ + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap->pitch = bitmap->width; + + error = ft_glyphslot_alloc_bitmap( slot, bitmap->rows * bitmap->pitch ); + if ( error ) + goto Exit; + + switch ( bpp ) + { + case 2: + bitmap->num_grays = 4; + + count = 0; + p = glyph.bitmap; + + for ( i = 0; i < bitmap->rows; i++ ) + { + pp = p; + + /* get the full bytes */ + for ( j = 0; j < ( bitmap->width >> 2 ); j++ ) + { + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xC0 ) >> 6 ); + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x30 ) >> 4 ); + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x0C ) >> 2 ); + bitmap->buffer[count++] = (FT_Byte)( *pp & 0x03 ); + + pp++; + } + + /* get remaining pixels (if any) */ + switch ( bitmap->width & 3 ) + { + case 3: + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xC0 ) >> 6 ); + /* fall through */ + case 2: + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x30 ) >> 4 ); + /* fall through */ + case 1: + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0x0C ) >> 2 ); + /* fall through */ + case 0: + break; + } + + p += glyph.bpr; + } + break; + + case 4: + bitmap->num_grays = 16; + + count = 0; + p = glyph.bitmap; + + for ( i = 0; i < bitmap->rows; i++ ) + { + pp = p; + + /* get the full bytes */ + for ( j = 0; j < ( bitmap->width >> 1 ); j++ ) + { + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xF0 ) >> 4 ); + bitmap->buffer[count++] = (FT_Byte)( *pp & 0x0F ); + + pp++; + } + + /* get remaining pixel (if any) */ + switch ( bitmap->width & 1 ) + { + case 1: + bitmap->buffer[count++] = (FT_Byte)( ( *pp & 0xF0 ) >> 4 ); + /* fall through */ + case 0: + break; + } + + p += glyph.bpr; + } + break; + + case 8: + bitmap->num_grays = 256; + + FT_MEM_COPY( bitmap->buffer, glyph.bitmap, + bitmap->rows * bitmap->pitch ); + break; + } + } + + slot->bitmap_left = glyph.bbx.x_offset; + slot->bitmap_top = glyph.bbx.ascent; + + /* FZ XXX: TODO: vertical metrics */ + slot->metrics.horiAdvance = glyph.dwidth << 6; + slot->metrics.horiBearingX = glyph.bbx.x_offset << 6; + slot->metrics.horiBearingY = glyph.bbx.ascent << 6; + slot->metrics.width = bitmap->width << 6; + slot->metrics.height = bitmap->rows << 6; + + slot->linearHoriAdvance = (FT_Fixed)glyph.dwidth << 16; + slot->format = FT_GLYPH_FORMAT_BITMAP; + + Exit: + return error; + } + + + /* + * + * BDF SERVICE + * + */ + + static FT_Error + bdf_get_bdf_property( BDF_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ) + { + bdf_property_t* prop; + + + FT_ASSERT( face && face->bdffont ); + + prop = bdf_get_font_property( face->bdffont, prop_name ); + if ( prop ) + { + switch ( prop->format ) + { + case BDF_ATOM: + aproperty->type = BDF_PROPERTY_TYPE_ATOM; + aproperty->u.atom = prop->value.atom; + break; + + case BDF_INTEGER: + aproperty->type = BDF_PROPERTY_TYPE_INTEGER; + aproperty->u.integer = prop->value.int32; + break; + + case BDF_CARDINAL: + aproperty->type = BDF_PROPERTY_TYPE_CARDINAL; + aproperty->u.cardinal = prop->value.card32; + break; + + default: + goto Fail; + } + return 0; + } + + Fail: + return BDF_Err_Invalid_Argument; + } + + + static FT_Error + bdf_get_charset_id( BDF_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ) + { + *acharset_encoding = face->charset_encoding; + *acharset_registry = face->charset_registry; + + return 0; + } + + + static const FT_Service_BDFRec bdf_service_bdf = + { + (FT_BDF_GetCharsetIdFunc)bdf_get_charset_id, + (FT_BDF_GetPropertyFunc) bdf_get_bdf_property + }; + + + /* + * + * SERVICES LIST + * + */ + + static const FT_ServiceDescRec bdf_services[] = + { + { FT_SERVICE_ID_BDF, &bdf_service_bdf }, + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_BDF }, + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + bdf_driver_requester( FT_Module module, + const char* name ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( bdf_services, name ); + } + + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec bdf_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_NO_OUTLINES, + sizeof ( FT_DriverRec ), + + "bdf", + 0x10000L, + 0x20000L, + + 0, + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) bdf_driver_requester + }, + + sizeof ( BDF_FaceRec ), + sizeof ( FT_SizeRec ), + sizeof ( FT_GlyphSlotRec ), + + BDF_Face_Init, + BDF_Face_Done, + 0, /* FT_Size_InitFunc */ + 0, /* FT_Size_DoneFunc */ + 0, /* FT_Slot_InitFunc */ + 0, /* FT_Slot_DoneFunc */ + + BDF_Set_Point_Size, + BDF_Set_Pixel_Size, + + BDF_Glyph_Load, + + 0, /* FT_Face_GetKerningFunc */ + 0, /* FT_Face_AttachFunc */ + 0, /* FT_Face_GetAdvancesFunc */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/bdf/bdfdrivr.h b/Utilities/vtkfreetype/src/bdf/bdfdrivr.h new file mode 100644 index 0000000..86f40ee --- /dev/null +++ b/Utilities/vtkfreetype/src/bdf/bdfdrivr.h @@ -0,0 +1,76 @@ +/* bdfdrivr.h + + FreeType font driver for bdf fonts + + Copyright (C) 2001, 2002, 2003, 2004 by + Francesco Zappa Nardelli + +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. +*/ + + +#ifndef __BDFDRIVR_H__ +#define __BDFDRIVR_H__ + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + +#include "bdf.h" + + +FT_BEGIN_HEADER + + + typedef struct BDF_encoding_el_ + { + FT_ULong enc; + FT_UShort glyph; + + } BDF_encoding_el; + + + typedef struct BDF_FaceRec_ + { + FT_FaceRec root; + + char* charset_encoding; + char* charset_registry; + + bdf_font_t* bdffont; + + BDF_encoding_el* en_table; + + FT_CharMap charmap_handle; + FT_CharMapRec charmap; /* a single charmap per face */ + + FT_UInt default_glyph; + + } BDF_FaceRec, *BDF_Face; + + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) bdf_driver_class; + + +FT_END_HEADER + + +#endif /* __BDFDRIVR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/bdf/bdferror.h b/Utilities/vtkfreetype/src/bdf/bdferror.h new file mode 100644 index 0000000..b27fa33 --- /dev/null +++ b/Utilities/vtkfreetype/src/bdf/bdferror.h @@ -0,0 +1,44 @@ +/* + * Copyright 2001, 2002 Francesco Zappa Nardelli + * + * 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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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. + */ + + /*************************************************************************/ + /* */ + /* This file is used to define the BDF error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __BDFERROR_H__ +#define __BDFERROR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX BDF_Err_ +#define FT_ERR_BASE FT_Mod_Err_BDF + +#include FT_ERRORS_H + +#endif /* __BDFERROR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/bdf/bdflib.c b/Utilities/vtkfreetype/src/bdf/bdflib.c new file mode 100644 index 0000000..825385e --- /dev/null +++ b/Utilities/vtkfreetype/src/bdf/bdflib.c @@ -0,0 +1,2435 @@ +/* + * Copyright 2000 Computing Research Labs, New Mexico State University + * Copyright 2001, 2002, 2003, 2004 Francesco Zappa Nardelli + * + * 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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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. + */ + + /*************************************************************************/ + /* */ + /* This file is based on bdf.c,v 1.22 2000/03/16 20:08:50 */ + /* */ + /* taken from Mark Leisher's xmbdfed package */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> + +#include FT_FREETYPE_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H + +#include "bdf.h" +#include "bdferror.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_bdflib + + + /*************************************************************************/ + /* */ + /* Default BDF font options. */ + /* */ + /*************************************************************************/ + + + static const bdf_options_t _bdf_opts = + { + 1, /* Correct metrics. */ + 1, /* Preserve unencoded glyphs. */ + 0, /* Preserve comments. */ + BDF_PROPORTIONAL /* Default spacing. */ + }; + + + /*************************************************************************/ + /* */ + /* Builtin BDF font properties. */ + /* */ + /*************************************************************************/ + + /* List of most properties that might appear in a font. Doesn't include */ + /* the RAW_* and AXIS_* properties in X11R6 polymorphic fonts. */ + + static const bdf_property_t _bdf_properties[] = + { + { (char *)"ADD_STYLE_NAME", BDF_ATOM, 1, { 0 } }, + { (char *)"AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"CAP_HEIGHT", BDF_INTEGER, 1, { 0 } }, + { (char *)"CHARSET_COLLECTIONS", BDF_ATOM, 1, { 0 } }, + { (char *)"CHARSET_ENCODING", BDF_ATOM, 1, { 0 } }, + { (char *)"CHARSET_REGISTRY", BDF_ATOM, 1, { 0 } }, + { (char *)"COMMENT", BDF_ATOM, 1, { 0 } }, + { (char *)"COPYRIGHT", BDF_ATOM, 1, { 0 } }, + { (char *)"DEFAULT_CHAR", BDF_CARDINAL, 1, { 0 } }, + { (char *)"DESTINATION", BDF_CARDINAL, 1, { 0 } }, + { (char *)"DEVICE_FONT_NAME", BDF_ATOM, 1, { 0 } }, + { (char *)"END_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"FACE_NAME", BDF_ATOM, 1, { 0 } }, + { (char *)"FAMILY_NAME", BDF_ATOM, 1, { 0 } }, + { (char *)"FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"FONT", BDF_ATOM, 1, { 0 } }, + { (char *)"FONTNAME_REGISTRY", BDF_ATOM, 1, { 0 } }, + { (char *)"FONT_ASCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"FONT_DESCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"FOUNDRY", BDF_ATOM, 1, { 0 } }, + { (char *)"FULL_NAME", BDF_ATOM, 1, { 0 } }, + { (char *)"ITALIC_ANGLE", BDF_INTEGER, 1, { 0 } }, + { (char *)"MAX_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"MIN_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"NORM_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"NOTICE", BDF_ATOM, 1, { 0 } }, + { (char *)"PIXEL_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"POINT_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"QUAD_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_ASCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_AVERAGE_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_AVG_CAPITAL_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_AVG_LOWERCASE_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_CAP_HEIGHT", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_DESCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_END_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_FIGURE_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_MAX_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_MIN_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_NORM_SPACE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_PIXEL_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_POINT_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_PIXELSIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_POINTSIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_QUAD_WIDTH", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } }, + { (char *)"RAW_X_HEIGHT", BDF_INTEGER, 1, { 0 } }, + { (char *)"RELATIVE_SETWIDTH", BDF_CARDINAL, 1, { 0 } }, + { (char *)"RELATIVE_WEIGHT", BDF_CARDINAL, 1, { 0 } }, + { (char *)"RESOLUTION", BDF_INTEGER, 1, { 0 } }, + { (char *)"RESOLUTION_X", BDF_CARDINAL, 1, { 0 } }, + { (char *)"RESOLUTION_Y", BDF_CARDINAL, 1, { 0 } }, + { (char *)"SETWIDTH_NAME", BDF_ATOM, 1, { 0 } }, + { (char *)"SLANT", BDF_ATOM, 1, { 0 } }, + { (char *)"SMALL_CAP_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"SPACING", BDF_ATOM, 1, { 0 } }, + { (char *)"STRIKEOUT_ASCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"STRIKEOUT_DESCENT", BDF_INTEGER, 1, { 0 } }, + { (char *)"SUBSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"SUBSCRIPT_X", BDF_INTEGER, 1, { 0 } }, + { (char *)"SUBSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, + { (char *)"SUPERSCRIPT_SIZE", BDF_INTEGER, 1, { 0 } }, + { (char *)"SUPERSCRIPT_X", BDF_INTEGER, 1, { 0 } }, + { (char *)"SUPERSCRIPT_Y", BDF_INTEGER, 1, { 0 } }, + { (char *)"UNDERLINE_POSITION", BDF_INTEGER, 1, { 0 } }, + { (char *)"UNDERLINE_THICKNESS", BDF_INTEGER, 1, { 0 } }, + { (char *)"WEIGHT", BDF_CARDINAL, 1, { 0 } }, + { (char *)"WEIGHT_NAME", BDF_ATOM, 1, { 0 } }, + { (char *)"X_HEIGHT", BDF_INTEGER, 1, { 0 } }, + { (char *)"_MULE_BASELINE_OFFSET", BDF_INTEGER, 1, { 0 } }, + { (char *)"_MULE_RELATIVE_COMPOSE", BDF_INTEGER, 1, { 0 } }, + }; + + static const unsigned long + _num_bdf_properties = sizeof ( _bdf_properties ) / + sizeof ( _bdf_properties[0] ); + + + /*************************************************************************/ + /* */ + /* Hash table utilities for the properties. */ + /* */ + /*************************************************************************/ + + /* XXX: Replace this with FreeType's hash functions */ + + +#define INITIAL_HT_SIZE 241 + + typedef void + (*hash_free_func)( hashnode node ); + + static hashnode* + hash_bucket( const char* key, + hashtable* ht ) + { + const char* kp = key; + unsigned long res = 0; + hashnode* bp = ht->table, *ndp; + + + /* Mocklisp hash function. */ + while ( *kp ) + res = ( res << 5 ) - res + *kp++; + + ndp = bp + ( res % ht->size ); + while ( *ndp ) + { + kp = (*ndp)->key; + if ( kp[0] == key[0] && ft_strcmp( kp, key ) == 0 ) + break; + ndp--; + if ( ndp < bp ) + ndp = bp + ( ht->size - 1 ); + } + + return ndp; + } + + + static FT_Error + hash_rehash( hashtable* ht, + FT_Memory memory ) + { + hashnode* obp = ht->table, *bp, *nbp; + int i, sz = ht->size; + FT_Error error = BDF_Err_Ok; + + + ht->size <<= 1; + ht->limit = ht->size / 3; + + if ( FT_NEW_ARRAY( ht->table, ht->size ) ) + goto Exit; + FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * ht->size ); + + for ( i = 0, bp = obp; i < sz; i++, bp++ ) + { + if ( *bp ) + { + nbp = hash_bucket( (*bp)->key, ht ); + *nbp = *bp; + } + } + FT_FREE( obp ); + + Exit: + return error; + } + + + static FT_Error + hash_init( hashtable* ht, + FT_Memory memory ) + { + int sz = INITIAL_HT_SIZE; + FT_Error error = BDF_Err_Ok; + + + ht->size = sz; + ht->limit = sz / 3; + ht->used = 0; + + if ( FT_NEW_ARRAY( ht->table, sz ) ) + goto Exit; + FT_MEM_ZERO( ht->table, sizeof ( hashnode ) * sz ); + + Exit: + return error; + } + + + static void + hash_free( hashtable* ht, + FT_Memory memory ) + { + if ( ht != 0 ) + { + int i, sz = ht->size; + hashnode* bp = ht->table; + + + for ( i = 0; i < sz; i++, bp++ ) + FT_FREE( *bp ); + + FT_FREE( ht->table ); + } + } + + + static FT_Error + hash_insert( char* key, + void* data, + hashtable* ht, + FT_Memory memory ) + { + hashnode nn, *bp = hash_bucket( key, ht ); + FT_Error error = BDF_Err_Ok; + + + nn = *bp; + if ( !nn ) + { + if ( FT_NEW( nn ) ) + goto Exit; + *bp = nn; + + nn->key = key; + nn->data = data; + + if ( ht->used >= ht->limit ) + { + error = hash_rehash( ht, memory ); + if ( error ) + goto Exit; + } + ht->used++; + } + else + nn->data = data; + + Exit: + return error; + } + + + static hashnode + hash_lookup( const char* key, + hashtable* ht ) + { + hashnode *np = hash_bucket( key, ht ); + + + return *np; + } + + + /*************************************************************************/ + /* */ + /* Utility types and functions. */ + /* */ + /*************************************************************************/ + + + /* Function type for parsing lines of a BDF font. */ + + typedef FT_Error + (*_bdf_line_func_t)( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data ); + + + /* List structure for splitting lines into fields. */ + + typedef struct _bdf_list_t_ + { + char** field; + unsigned long size; + unsigned long used; + + } _bdf_list_t; + + + /* Structure used while loading BDF fonts. */ + + typedef struct _bdf_parse_t_ + { + unsigned long flags; + unsigned long cnt; + unsigned long row; + + short minlb; + short maxlb; + short maxrb; + short maxas; + short maxds; + + short rbearing; + + char* glyph_name; + long glyph_enc; + + bdf_font_t* font; + bdf_options_t* opts; + + unsigned long have[2048]; + _bdf_list_t list; + + FT_Memory memory; + + } _bdf_parse_t; + + +#define setsbit( m, cc ) ( m[(cc) >> 3] |= (FT_Byte)( 1 << ( (cc) & 7 ) ) ) +#define sbitset( m, cc ) ( m[(cc) >> 3] & ( 1 << ( (cc) & 7 ) ) ) + + + /* An empty string for empty fields. */ + + static const char empty[1] = { 0 }; /* XXX eliminate this */ + + + /* Assume the line is NULL-terminated and that the `list' parameter */ + /* was initialized the first time it was used. */ + + static FT_Error + _bdf_split( char* separators, + char* line, + unsigned long linelen, + _bdf_list_t* list, + FT_Memory memory ) + { + int mult, final_empty; + char *sp, *ep, *end; + char seps[32]; + FT_Error error = BDF_Err_Ok; + + + /* Initialize the list. */ + list->used = 0; + + /* If the line is empty, then simply return. */ + if ( linelen == 0 || line[0] == 0 ) + goto Exit; + + /* In the original code, if the `separators' parameter is NULL or */ + /* empty, the list is split into individual bytes. We don't need */ + /* this, so an error is signaled. */ + if ( separators == 0 || *separators == 0 ) + { + error = BDF_Err_Invalid_Argument; + goto Exit; + } + + /* Prepare the separator bitmap. */ + FT_MEM_ZERO( seps, 32 ); + + /* If the very last character of the separator string is a plus, then */ + /* set the `mult' flag to indicate that multiple separators should be */ + /* collapsed into one. */ + for ( mult = 0, sp = separators; sp && *sp; sp++ ) + { + if ( *sp == '+' && *( sp + 1 ) == 0 ) + mult = 1; + else + setsbit( seps, *sp ); + } + + /* Break the line up into fields. */ + for ( final_empty = 0, sp = ep = line, end = sp + linelen; + sp < end && *sp; ) + { + /* Collect everything that is not a separator. */ + for ( ; *ep && !sbitset( seps, *ep ); ep++ ) + ; + + /* Resize the list if necessary. */ + if ( list->used == list->size ) + { + if ( list->size == 0 ) + { + if ( FT_NEW_ARRAY( list->field, 5 ) ) + goto Exit; + } + else + { + if ( FT_RENEW_ARRAY ( list->field , + list->size, + list->size + 5 ) ) + goto Exit; + } + + list->size += 5; + } + + /* Assign the field appropriately. */ + list->field[list->used++] = ( ep > sp ) ? sp : (char*)empty; + + sp = ep; + + if ( mult ) + { + /* If multiple separators should be collapsed, do it now by */ + /* setting all the separator characters to 0. */ + for ( ; *ep && sbitset( seps, *ep ); ep++ ) + *ep = 0; + } + else if ( *ep != 0 ) + /* Don't collapse multiple separators by making them 0, so just */ + /* make the one encountered 0. */ + *ep++ = 0; + + final_empty = ( ep > sp && *ep == 0 ); + sp = ep; + } + + /* Finally, NULL-terminate the list. */ + if ( list->used + final_empty + 1 >= list->size ) + { + if ( list->used == list->size ) + { + if ( list->size == 0 ) + { + if ( FT_NEW_ARRAY( list->field, 5 ) ) + goto Exit; + } + else + { + if ( FT_RENEW_ARRAY( list->field, + list->size, + list->size + 5 ) ) + goto Exit; + } + + list->size += 5; + } + } + + if ( final_empty ) + list->field[list->used++] = (char*)empty; + + if ( list->used == list->size ) + { + if ( list->size == 0 ) + { + if ( FT_NEW_ARRAY( list->field, 5 ) ) + goto Exit; + } + else + { + if ( FT_RENEW_ARRAY( list->field, + list->size, + list->size + 5 ) ) + goto Exit; + } + + list->size += 5; + } + + list->field[list->used] = 0; + + Exit: + return error; + } + + + static void + _bdf_shift( unsigned long n, + _bdf_list_t* list ) + { + unsigned long i, u; + + + if ( list == 0 || list->used == 0 || n == 0 ) + return; + + if ( n >= list->used ) + { + list->used = 0; + return; + } + + for ( u = n, i = 0; u < list->used; i++, u++ ) + list->field[i] = list->field[u]; + list->used -= n; + } + + + static char * + _bdf_join( int c, + unsigned long* len, + _bdf_list_t* list ) + { + unsigned long i, j; + char *fp, *dp; + + + if ( list == 0 || list->used == 0 ) + return 0; + + *len = 0; + + dp = list->field[0]; + for ( i = j = 0; i < list->used; i++ ) + { + fp = list->field[i]; + while ( *fp ) + dp[j++] = *fp++; + + if ( i + 1 < list->used ) + dp[j++] = (char)c; + } + dp[j] = 0; + + *len = j; + return dp; + } + + + /* High speed file reader that passes each line to a callback. */ + static FT_Error + bdf_internal_readstream( FT_Stream stream, + char* buffer, + int count, + int *read_bytes ) + { + int rbytes; + unsigned long pos = stream->pos; + FT_Error error = BDF_Err_Ok; + + + if ( pos > stream->size ) + { + FT_ERROR(( "bdf_internal_readstream:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + error = BDF_Err_Invalid_Stream_Operation; + goto Exit; + } + + if ( stream->read ) + rbytes = stream->read( stream, pos, + (unsigned char *)buffer, count ); + else + { + rbytes = stream->size - pos; + if ( rbytes > count ) + rbytes = count; + + FT_MEM_COPY( buffer, stream->base + pos, rbytes ); + } + + stream->pos = pos + rbytes; + + *read_bytes = rbytes; + + Exit: + return error; + } + + + static FT_Error + _bdf_readstream( FT_Stream stream, + _bdf_line_func_t callback, + void* client_data, + unsigned long *lno ) + { + _bdf_line_func_t cb; + unsigned long lineno; + int n, done, refill, bytes, hold; + char *ls, *le, *pp, *pe, *hp; + char *buf = 0; + FT_Memory memory = stream->memory; + FT_Error error = BDF_Err_Ok; + + + if ( callback == 0 ) + { + error = BDF_Err_Invalid_Argument; + goto Exit; + } + + if ( FT_NEW_ARRAY( buf, 65536L ) ) + goto Exit; + + cb = callback; + lineno = 1; + buf[0] = 0; + + done = 0; + pp = ls = le = buf; + + bytes = 65536L; + + while ( !done ) + { + error = bdf_internal_readstream( stream, pp, bytes, &n ); + if ( error ) + goto Exit; + + if ( n == 0 ) + break; + + /* Determine the new end of the buffer pages. */ + pe = pp + n; + + for ( refill = 0; done == 0 && refill == 0; ) + { + while ( le < pe && *le != '\n' && *le != '\r' ) + le++; + + if ( le == pe ) + { + /* Hit the end of the last page in the buffer. Need to find */ + /* out how many pages to shift and how many pages need to be */ + /* read in. Adjust the line start and end pointers down to */ + /* point to the right places in the pages. */ + + pp = buf + ( ( ( ls - buf ) >> 13 ) << 13 ); + n = pp - buf; + ls -= n; + le -= n; + n = pe - pp; + + FT_MEM_MOVE( buf, pp, n ); + + pp = buf + n; + bytes = 65536L - n; + refill = 1; + } + else + { + /* Temporarily NULL-terminate the line. */ + hp = le; + hold = *le; + *le = 0; + + /* XXX: Use encoding independent value for 0x1a */ + if ( *ls != '#' && *ls != 0x1a && + le > ls && + ( error = (*cb)( ls, le - ls, lineno, (void *)&cb, + client_data ) ) != BDF_Err_Ok ) + done = 1; + else + { + ls = ++le; + /* Handle the case of DOS crlf sequences. */ + if ( le < pe && hold == '\n' && *le =='\r' ) + ls = ++le; + } + + /* Increment the line number. */ + lineno++; + + /* Restore the character at the end of the line. */ + *hp = (char)hold; + } + } + } + + *lno = lineno; + + Exit: + FT_FREE( buf ); + return error; + } + + + /* XXX: make this work with EBCDIC also */ + + static const unsigned char a2i[128] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + static const unsigned char odigits[32] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static const unsigned char ddigits[32] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static const unsigned char hdigits[32] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, + 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + +#define isdigok( m, d ) (m[(d) >> 3] & ( 1 << ( (d) & 7 ) ) ) + + + /* Routine to convert an ASCII string into an unsigned long integer. */ + static unsigned long + _bdf_atoul( char* s, + char** end, + int base ) + { + unsigned long v; + const unsigned char* dmap; + + + if ( s == 0 || *s == 0 ) + return 0; + + /* Make sure the radix is something recognizable. Default to 10. */ + switch ( base ) + { + case 8: + dmap = odigits; + break; + case 16: + dmap = hdigits; + break; + default: + base = 10; + dmap = ddigits; + break; + } + + /* Check for the special hex prefix. */ + if ( *s == '0' && + ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) + { + base = 16; + dmap = hdigits; + s += 2; + } + + for ( v = 0; isdigok( dmap, *s ); s++ ) + v = v * base + a2i[(int)*s]; + + if ( end != 0 ) + *end = s; + + return v; + } + + + /* Routine to convert an ASCII string into an signed long integer. */ + static long + _bdf_atol( char* s, + char** end, + int base ) + { + long v, neg; + const unsigned char* dmap; + + + if ( s == 0 || *s == 0 ) + return 0; + + /* Make sure the radix is something recognizable. Default to 10. */ + switch ( base ) + { + case 8: + dmap = odigits; + break; + case 16: + dmap = hdigits; + break; + default: + base = 10; + dmap = ddigits; + break; + } + + /* Check for a minus sign. */ + neg = 0; + if ( *s == '-' ) + { + s++; + neg = 1; + } + + /* Check for the special hex prefix. */ + if ( *s == '0' && + ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) + { + base = 16; + dmap = hdigits; + s += 2; + } + + for ( v = 0; isdigok( dmap, *s ); s++ ) + v = v * base + a2i[(int)*s]; + + if ( end != 0 ) + *end = s; + + return ( !neg ) ? v : -v; + } + + + /* Routine to convert an ASCII string into an signed short integer. */ + static short + _bdf_atos( char* s, + char** end, + int base ) + { + short v, neg; + const unsigned char* dmap; + + + if ( s == 0 || *s == 0 ) + return 0; + + /* Make sure the radix is something recognizable. Default to 10. */ + switch ( base ) + { + case 8: + dmap = odigits; + break; + case 16: + dmap = hdigits; + break; + default: + base = 10; + dmap = ddigits; + break; + } + + /* Check for a minus. */ + neg = 0; + if ( *s == '-' ) + { + s++; + neg = 1; + } + + /* Check for the special hex prefix. */ + if ( *s == '0' && + ( *( s + 1 ) == 'x' || *( s + 1 ) == 'X' ) ) + { + base = 16; + dmap = hdigits; + s += 2; + } + + for ( v = 0; isdigok( dmap, *s ); s++ ) + v = (short)( v * base + a2i[(int)*s] ); + + if ( end != 0 ) + *end = s; + + return (short)( ( !neg ) ? v : -v ); + } + + + /* Routine to compare two glyphs by encoding so they can be sorted. */ + static int + by_encoding( const void* a, + const void* b ) + { + bdf_glyph_t *c1, *c2; + + + c1 = (bdf_glyph_t *)a; + c2 = (bdf_glyph_t *)b; + + if ( c1->encoding < c2->encoding ) + return -1; + else if ( c1->encoding > c2->encoding ) + return 1; + + return 0; + } + + + static FT_Error + bdf_create_property( char* name, + int format, + bdf_font_t* font ) + { + unsigned long n; + bdf_property_t* p; + FT_Memory memory = font->memory; + FT_Error error = BDF_Err_Ok; + + + /* First check to see if the property has */ + /* already been added or not. If it has, then */ + /* simply ignore it. */ + if ( hash_lookup( name, &(font->proptbl) ) ) + goto Exit; + + if ( font->nuser_props == 0 ) + { + if ( FT_NEW_ARRAY( font->user_props, 1 ) ) + goto Exit; + } + else + { + if ( FT_RENEW_ARRAY( font->user_props, + font->nuser_props, + font->nuser_props + 1 ) ) + goto Exit; + } + + p = font->user_props + font->nuser_props; + FT_MEM_ZERO( p, sizeof ( bdf_property_t ) ); + + n = (unsigned long)( ft_strlen( name ) + 1 ); + if ( FT_NEW_ARRAY( p->name, n ) ) + goto Exit; + + FT_MEM_COPY( (char *)p->name, name, n ); + + p->format = format; + p->builtin = 0; + + n = _num_bdf_properties + font->nuser_props; + + error = hash_insert( p->name, (void *)n, &(font->proptbl), memory ); + if ( error ) + goto Exit; + + font->nuser_props++; + + Exit: + return error; + } + + + FT_LOCAL_DEF( bdf_property_t * ) + bdf_get_property( char* name, + bdf_font_t* font ) + { + hashnode hn; + unsigned long propid; + + + if ( name == 0 || *name == 0 ) + return 0; + + if ( ( hn = hash_lookup( name, &(font->proptbl) ) ) == 0 ) + return 0; + + propid = (unsigned long)hn->data; + if ( propid >= _num_bdf_properties ) + return font->user_props + ( propid - _num_bdf_properties ); + + return (bdf_property_t*)_bdf_properties + propid; + } + + + /*************************************************************************/ + /* */ + /* BDF font file parsing flags and functions. */ + /* */ + /*************************************************************************/ + + + /* Parse flags. */ + +#define _BDF_START 0x0001 +#define _BDF_FONT_NAME 0x0002 +#define _BDF_SIZE 0x0004 +#define _BDF_FONT_BBX 0x0008 +#define _BDF_PROPS 0x0010 +#define _BDF_GLYPHS 0x0020 +#define _BDF_GLYPH 0x0040 +#define _BDF_ENCODING 0x0080 +#define _BDF_SWIDTH 0x0100 +#define _BDF_DWIDTH 0x0200 +#define _BDF_BBX 0x0400 +#define _BDF_BITMAP 0x0800 + +#define _BDF_SWIDTH_ADJ 0x1000 + +#define _BDF_GLYPH_BITS ( _BDF_GLYPH | \ + _BDF_ENCODING | \ + _BDF_SWIDTH | \ + _BDF_DWIDTH | \ + _BDF_BBX | \ + _BDF_BITMAP ) + +#define _BDF_GLYPH_WIDTH_CHECK 0x40000000L +#define _BDF_GLYPH_HEIGHT_CHECK 0x80000000L + + + /* Auto correction messages. */ +#define ACMSG1 "FONT_ASCENT property missing. " \ + "Added \"FONT_ASCENT %hd\".\n" +#define ACMSG2 "FONT_DESCENT property missing. " \ + "Added \"FONT_DESCENT %hd\".\n" +#define ACMSG3 "Font width != actual width. Old: %hd New: %hd.\n" +#define ACMSG4 "Font left bearing != actual left bearing. " \ + "Old: %hd New: %hd.\n" +#define ACMSG5 "Font ascent != actual ascent. Old: %hd New: %hd.\n" +#define ACMSG6 "Font descent != actual descent. Old: %hd New: %hd.\n" +#define ACMSG7 "Font height != actual height. Old: %hd New: %hd.\n" +#define ACMSG8 "Glyph scalable width (SWIDTH) adjustments made.\n" +#define ACMSG9 "SWIDTH field missing at line %ld. Set automatically.\n" +#define ACMSG10 "DWIDTH field missing at line %ld. Set to glyph width.\n" +#define ACMSG11 "SIZE bits per pixel field adjusted to %hd.\n" +#define ACMSG12 "Duplicate encoding %ld (%s) changed to unencoded.\n" +#define ACMSG13 "Glyph %ld extra rows removed.\n" +#define ACMSG14 "Glyph %ld extra columns removed.\n" +#define ACMSG15 "Incorrect glyph count: %ld indicated but %ld found.\n" + + /* Error messages. */ +#define ERRMSG1 "[line %ld] Missing \"%s\" line.\n" +#define ERRMSG2 "[line %ld] Font header corrupted or missing fields.\n" +#define ERRMSG3 "[line %ld] Font glyphs corrupted or missing fields.\n" + + + static FT_Error + _bdf_add_comment( bdf_font_t* font, + char* comment, + unsigned long len ) + { + char* cp; + FT_Memory memory = font->memory; + FT_Error error = BDF_Err_Ok; + + + if ( font->comments_len == 0 ) + { + if ( FT_NEW_ARRAY( font->comments, len + 1 ) ) + goto Exit; + } + else + { + if ( FT_RENEW_ARRAY( font->comments, + font->comments_len, + font->comments_len + len + 1 ) ) + goto Exit; + } + + cp = font->comments + font->comments_len; + FT_MEM_COPY( cp, comment, len ); + cp += len; + *cp++ = '\n'; + font->comments_len += len + 1; + + Exit: + return error; + } + + + /* Set the spacing from the font name if it exists, or set it to the */ + /* default specified in the options. */ + static FT_Error + _bdf_set_default_spacing( bdf_font_t* font, + bdf_options_t* opts ) + { + unsigned long len; + char name[128]; + _bdf_list_t list; + FT_Memory memory; + FT_Error error = BDF_Err_Ok; + + + if ( font == 0 || font->name == 0 || font->name[0] == 0 ) + { + error = BDF_Err_Invalid_Argument; + goto Exit; + } + + memory = font->memory; + + font->spacing = opts->font_spacing; + + len = (unsigned long)( ft_strlen( font->name ) + 1 ); + FT_MEM_COPY( name, font->name, len ); + + list.size = list.used = 0; + + error = _bdf_split( (char *)"-", name, len, &list, memory ); + if ( error ) + goto Exit; + + if ( list.used == 15 ) + { + switch ( list.field[11][0] ) + { + case 'C': + case 'c': + font->spacing = BDF_CHARCELL; + break; + case 'M': + case 'm': + font->spacing = BDF_MONOWIDTH; + break; + case 'P': + case 'p': + font->spacing = BDF_PROPORTIONAL; + break; + } + } + + FT_FREE( list.field ); + + Exit: + return error; + } + + + /* Determine whether the property is an atom or not. If it is, then */ + /* clean it up so the double quotes are removed if they exist. */ + static int + _bdf_is_atom( char* line, + unsigned long linelen, + char** name, + char** value, + bdf_font_t* font ) + { + int hold; + char *sp, *ep; + bdf_property_t* p; + + + *name = sp = ep = line; + + while ( *ep && *ep != ' ' && *ep != '\t' ) + ep++; + + hold = -1; + if ( *ep ) + { + hold = *ep; + *ep = 0; + } + + p = bdf_get_property( sp, font ); + + /* Restore the character that was saved before any return can happen. */ + if ( hold != -1 ) + *ep = (char)hold; + + /* If the property exists and is not an atom, just return here. */ + if ( p && p->format != BDF_ATOM ) + return 0; + + /* The property is an atom. Trim all leading and trailing whitespace */ + /* and double quotes for the atom value. */ + sp = ep; + ep = line + linelen; + + /* Trim the leading whitespace if it exists. */ + *sp++ = 0; + while ( *sp && + ( *sp == ' ' || *sp == '\t' ) ) + sp++; + + /* Trim the leading double quote if it exists. */ + if ( *sp == '"' ) + sp++; + *value = sp; + + /* Trim the trailing whitespace if it exists. */ + while ( ep > sp && + ( *( ep - 1 ) == ' ' || *( ep - 1 ) == '\t' ) ) + *--ep = 0; + + /* Trim the trailing double quote if it exists. */ + if ( ep > sp && *( ep - 1 ) == '"' ) + *--ep = 0; + + return 1; + } + + + static FT_Error + _bdf_add_property( bdf_font_t* font, + char* name, + char* value ) + { + unsigned long propid; + hashnode hn; + int len; + bdf_property_t *prop, *fp; + FT_Memory memory = font->memory; + FT_Error error = BDF_Err_Ok; + + + /* First, check to see if the property already exists in the font. */ + if ( ( hn = hash_lookup( name, (hashtable *)font->internal ) ) != 0 ) + { + /* The property already exists in the font, so simply replace */ + /* the value of the property with the current value. */ + fp = font->props + (unsigned long)hn->data; + + switch ( fp->format ) + { + case BDF_ATOM: + /* Delete the current atom if it exists. */ + FT_FREE( fp->value.atom ); + + if ( value == 0 ) + len = 1; + else + len = ft_strlen( value ) + 1; + + if ( len > 1 ) + { + if ( FT_NEW_ARRAY( fp->value.atom, len ) ) + goto Exit; + FT_MEM_COPY( fp->value.atom, value, len ); + } + else + fp->value.atom = 0; + break; + + case BDF_INTEGER: + fp->value.int32 = _bdf_atol( value, 0, 10 ); + break; + + case BDF_CARDINAL: + fp->value.card32 = _bdf_atoul( value, 0, 10 ); + break; + + default: + ; + } + + goto Exit; + } + + /* See whether this property type exists yet or not. */ + /* If not, create it. */ + hn = hash_lookup( name, &(font->proptbl) ); + if ( hn == 0 ) + { + error = bdf_create_property( name, BDF_ATOM, font ); + if ( error ) + goto Exit; + hn = hash_lookup( name, &(font->proptbl) ); + } + + /* Allocate another property if this is overflow. */ + if ( font->props_used == font->props_size ) + { + if ( font->props_size == 0 ) + { + if ( FT_NEW_ARRAY( font->props, 1 ) ) + goto Exit; + } + else + { + if ( FT_RENEW_ARRAY( font->props, + font->props_size, + font->props_size + 1 ) ) + goto Exit; + } + + fp = font->props + font->props_size; + FT_MEM_ZERO( fp, sizeof ( bdf_property_t ) ); + font->props_size++; + } + + propid = (unsigned long)hn->data; + if ( propid >= _num_bdf_properties ) + prop = font->user_props + ( propid - _num_bdf_properties ); + else + prop = (bdf_property_t*)_bdf_properties + propid; + + fp = font->props + font->props_used; + + fp->name = prop->name; + fp->format = prop->format; + fp->builtin = prop->builtin; + + switch ( prop->format ) + { + case BDF_ATOM: + if ( value == 0 ) + len = 1; + else + len = ft_strlen( value ) + 1; + + if ( len > 1 ) + { + if ( FT_NEW_ARRAY( fp->value.atom, len ) ) + goto Exit; + FT_MEM_COPY( fp->value.atom, value, len ); + } + else + fp->value.atom = 0; + break; + + case BDF_INTEGER: + fp->value.int32 = _bdf_atol( value, 0, 10 ); + break; + + case BDF_CARDINAL: + fp->value.card32 = _bdf_atoul( value, 0, 10 ); + break; + } + + /* If the property happens to be a comment, then it doesn't need */ + /* to be added to the internal hash table. */ + if ( ft_memcmp( name, "COMMENT", 7 ) != 0 ) { + /* Add the property to the font property table. */ + error = hash_insert( fp->name, + (void *)font->props_used, + (hashtable *)font->internal, + memory ); + if ( error ) + goto Exit; + } + + font->props_used++; + + /* Some special cases need to be handled here. The DEFAULT_CHAR */ + /* property needs to be located if it exists in the property list, the */ + /* FONT_ASCENT and FONT_DESCENT need to be assigned if they are */ + /* present, and the SPACING property should override the default */ + /* spacing. */ + if ( ft_memcmp( name, "DEFAULT_CHAR", 12 ) == 0 ) + font->default_char = fp->value.int32; + else if ( ft_memcmp( name, "FONT_ASCENT", 11 ) == 0 ) + font->font_ascent = fp->value.int32; + else if ( ft_memcmp( name, "FONT_DESCENT", 12 ) == 0 ) + font->font_descent = fp->value.int32; + else if ( ft_memcmp( name, "SPACING", 7 ) == 0 ) + { + if ( fp->value.atom[0] == 'p' || fp->value.atom[0] == 'P' ) + font->spacing = BDF_PROPORTIONAL; + else if ( fp->value.atom[0] == 'm' || fp->value.atom[0] == 'M' ) + font->spacing = BDF_MONOWIDTH; + else if ( fp->value.atom[0] == 'c' || fp->value.atom[0] == 'C' ) + font->spacing = BDF_CHARCELL; + } + + Exit: + return error; + } + + + static const unsigned char nibble_mask[8] = + { + 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE + }; + + + /* Actually parse the glyph info and bitmaps. */ + static FT_Error + _bdf_parse_glyphs( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data ) + { + int c, mask_index; + char* s; + unsigned char* bp; + unsigned long i, slen, nibbles; + + _bdf_parse_t* p; + bdf_glyph_t* glyph; + bdf_font_t* font; + + FT_Memory memory; + FT_Error error = BDF_Err_Ok; + + FT_UNUSED( call_data ); + FT_UNUSED( lineno ); /* only used in debug mode */ + + + p = (_bdf_parse_t *)client_data; + + font = p->font; + memory = font->memory; + + /* Check for a comment. */ + if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) + { + linelen -= 7; + + s = line + 7; + if ( *s != 0 ) + { + s++; + linelen--; + } + error = _bdf_add_comment( p->font, s, linelen ); + goto Exit; + } + + /* The very first thing expected is the number of glyphs. */ + if ( !( p->flags & _BDF_GLYPHS ) ) + { + if ( ft_memcmp( line, "CHARS", 5 ) != 0 ) + { + FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "CHARS" )); + error = BDF_Err_Missing_Chars_Field; + goto Exit; + } + + error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); + if ( error ) + goto Exit; + p->cnt = font->glyphs_size = _bdf_atoul( p->list.field[1], 0, 10 ); + + /* Make sure the number of glyphs is non-zero. */ + if ( p->cnt == 0 ) + font->glyphs_size = 64; + + if ( FT_NEW_ARRAY( font->glyphs, font->glyphs_size ) ) + goto Exit; + + p->flags |= _BDF_GLYPHS; + + goto Exit; + } + + /* Check for the ENDFONT field. */ + if ( ft_memcmp( line, "ENDFONT", 7 ) == 0 ) + { + /* Sort the glyphs by encoding. */ + ft_qsort( (char *)font->glyphs, + font->glyphs_used, + sizeof ( bdf_glyph_t ), + by_encoding ); + + p->flags &= ~_BDF_START; + + goto Exit; + } + + /* Check for the ENDCHAR field. */ + if ( ft_memcmp( line, "ENDCHAR", 7 ) == 0 ) + { + p->glyph_enc = 0; + p->flags &= ~_BDF_GLYPH_BITS; + + goto Exit; + } + + /* Check to see whether a glyph is being scanned but should be */ + /* ignored because it is an unencoded glyph. */ + if ( ( p->flags & _BDF_GLYPH ) && + p->glyph_enc == -1 && + p->opts->keep_unencoded == 0 ) + goto Exit; + + /* Check for the STARTCHAR field. */ + if ( ft_memcmp( line, "STARTCHAR", 9 ) == 0 ) + { + /* Set the character name in the parse info first until the */ + /* encoding can be checked for an unencoded character. */ + FT_FREE( p->glyph_name ); + + error = _bdf_split( (char *)" +", line, linelen, &p->list,memory ); + if ( error ) + goto Exit; + _bdf_shift( 1, &p->list ); + + s = _bdf_join( ' ', &slen, &p->list ); + + if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) ) + goto Exit; + FT_MEM_COPY( p->glyph_name, s, slen + 1 ); + + p->flags |= _BDF_GLYPH; + + goto Exit; + } + + /* Check for the ENCODING field. */ + if ( ft_memcmp( line, "ENCODING", 8 ) == 0 ) + { + if ( !( p->flags & _BDF_GLYPH ) ) + { + /* Missing STARTCHAR field. */ + FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "STARTCHAR" )); + error = BDF_Err_Missing_Startchar_Field; + goto Exit; + } + + error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); + if ( error ) + goto Exit; + p->glyph_enc = _bdf_atol( p->list.field[1], 0, 10 ); + + /* Check to see whether this encoding has already been encountered. */ + /* If it has then change it to unencoded so it gets added if */ + /* indicated. */ + if ( p->glyph_enc >= 0 ) + { + if ( _bdf_glyph_modified( p->have, p->glyph_enc ) ) + { + /* Emit a message saying a glyph has been moved to the */ + /* unencoded area. */ + FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG12, + p->glyph_enc, p->glyph_name )); + p->glyph_enc = -1; + font->modified = 1; + } + else + _bdf_set_glyph_modified( p->have, p->glyph_enc ); + } + + if ( p->glyph_enc >= 0 ) + { + /* Make sure there are enough glyphs allocated in case the */ + /* number of characters happen to be wrong. */ + if ( font->glyphs_used == font->glyphs_size ) + { + if ( FT_RENEW_ARRAY( font->glyphs, + font->glyphs_size, + font->glyphs_size + 64 ) ) + goto Exit; + FT_MEM_ZERO( font->glyphs + font->glyphs_size, + sizeof ( bdf_glyph_t ) * 64 ); /* FZ inutile */ + font->glyphs_size += 64; + } + + glyph = font->glyphs + font->glyphs_used++; + glyph->name = p->glyph_name; + glyph->encoding = p->glyph_enc; + + /* Reset the initial glyph info. */ + p->glyph_name = 0; + } + else + { + /* Unencoded glyph. Check to see whether it should */ + /* be added or not. */ + if ( p->opts->keep_unencoded != 0 ) + { + /* Allocate the next unencoded glyph. */ + if ( font->unencoded_used == font->unencoded_size ) + { + if ( font->unencoded_size == 0 ) + { + if ( FT_NEW_ARRAY( font->unencoded, 4 ) ) + goto Exit; + } + else + { + if ( FT_RENEW_ARRAY( font->unencoded , + font->unencoded_size, + font->unencoded_size + 4 ) ) + goto Exit; + } + font->unencoded_size += 4; + } + + glyph = font->unencoded + font->unencoded_used; + glyph->name = p->glyph_name; + glyph->encoding = font->unencoded_used++; + } + else + /* Free up the glyph name if the unencoded shouldn't be */ + /* kept. */ + FT_FREE( p->glyph_name ); + + p->glyph_name = 0; + } + + /* Clear the flags that might be added when width and height are */ + /* checked for consistency. */ + p->flags &= ~( _BDF_GLYPH_WIDTH_CHECK | _BDF_GLYPH_HEIGHT_CHECK ); + + p->flags |= _BDF_ENCODING; + + goto Exit; + } + + /* Point at the glyph being constructed. */ + if ( p->glyph_enc == -1 ) + glyph = font->unencoded + ( font->unencoded_used - 1 ); + else + glyph = font->glyphs + ( font->glyphs_used - 1 ); + + /* Check to see whether a bitmap is being constructed. */ + if ( p->flags & _BDF_BITMAP ) + { + /* If there are more rows than are specified in the glyph metrics, */ + /* ignore the remaining lines. */ + if ( p->row >= (unsigned long)glyph->bbx.height ) + { + if ( !( p->flags & _BDF_GLYPH_HEIGHT_CHECK ) ) + { + FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG13, glyph->encoding )); + p->flags |= _BDF_GLYPH_HEIGHT_CHECK; + font->modified = 1; + } + + goto Exit; + } + + /* Only collect the number of nibbles indicated by the glyph */ + /* metrics. If there are more columns, they are simply ignored. */ + nibbles = glyph->bpr << 1; + bp = glyph->bitmap + p->row * glyph->bpr; + + for ( i = 0, *bp = 0; i < nibbles; i++ ) + { + c = line[i]; + *bp = (FT_Byte)( ( *bp << 4 ) + a2i[c] ); + if ( i + 1 < nibbles && ( i & 1 ) ) + *++bp = 0; + } + + /* Remove possible garbage at the right. */ + mask_index = ( glyph->bbx.width * p->font->bpp ) & 7; + *bp &= nibble_mask[mask_index]; + + /* If any line has extra columns, indicate they have been removed. */ + if ( ( line[nibbles] == '0' || a2i[(int)line[nibbles]] != 0 ) && + !( p->flags & _BDF_GLYPH_WIDTH_CHECK ) ) + { + FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG14, glyph->encoding )); + p->flags |= _BDF_GLYPH_WIDTH_CHECK; + font->modified = 1; + } + + p->row++; + goto Exit; + } + + /* Expect the SWIDTH (scalable width) field next. */ + if ( ft_memcmp( line, "SWIDTH", 6 ) == 0 ) + { + if ( !( p->flags & _BDF_ENCODING ) ) + { + /* Missing ENCODING field. */ + FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "ENCODING" )); + error = BDF_Err_Missing_Encoding_Field; + goto Exit; + } + + error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); + if ( error ) + goto Exit; + glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 ); + p->flags |= _BDF_SWIDTH; + + goto Exit; + } + + /* Expect the DWIDTH (scalable width) field next. */ + if ( ft_memcmp( line, "DWIDTH", 6 ) == 0 ) + { + error = _bdf_split( (char *)" +", line, linelen, &p->list,memory ); + if ( error ) + goto Exit; + glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1], 0, 10 ); + + if ( !( p->flags & _BDF_SWIDTH ) ) + { + /* Missing SWIDTH field. Emit an auto correction message and set */ + /* the scalable width from the device width. */ + FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG9, lineno )); + + glyph->swidth = (unsigned short)FT_MulDiv( + glyph->dwidth, 72000L, + (FT_Long)( font->point_size * + font->resolution_x ) ); + } + + p->flags |= _BDF_DWIDTH; + goto Exit; + } + + /* Expect the BBX field next. */ + if ( ft_memcmp( line, "BBX", 3 ) == 0 ) + { + error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); + if ( error ) + goto Exit; + + glyph->bbx.width = _bdf_atos( p->list.field[1], 0, 10 ); + glyph->bbx.height = _bdf_atos( p->list.field[2], 0, 10 ); + glyph->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 ); + glyph->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 ); + + /* Generate the ascent and descent of the character. */ + glyph->bbx.ascent = (short)( glyph->bbx.height + glyph->bbx.y_offset ); + glyph->bbx.descent = (short)( -glyph->bbx.y_offset ); + + /* Determine the overall font bounding box as the characters are */ + /* loaded so corrections can be done later if indicated. */ + p->maxas = (short)FT_MAX( glyph->bbx.ascent, p->maxas ); + p->maxds = (short)FT_MAX( glyph->bbx.descent, p->maxds ); + + p->rbearing = (short)( glyph->bbx.width + glyph->bbx.x_offset ); + + p->maxrb = (short)FT_MAX( p->rbearing, p->maxrb ); + p->minlb = (short)FT_MIN( glyph->bbx.x_offset, p->minlb ); + p->maxlb = (short)FT_MAX( glyph->bbx.x_offset, p->maxlb ); + + if ( !( p->flags & _BDF_DWIDTH ) ) + { + /* Missing DWIDTH field. Emit an auto correction message and set */ + /* the device width to the glyph width. */ + FT_TRACE2(( "_bdf_parse_glyphs: " ACMSG10, lineno )); + glyph->dwidth = glyph->bbx.width; + } + + /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */ + /* value if necessary. */ + if ( p->opts->correct_metrics != 0 ) + { + /* Determine the point size of the glyph. */ + unsigned short sw = (unsigned short)FT_MulDiv( + glyph->dwidth, 72000L, + (FT_Long)( font->point_size * + font->resolution_x ) ); + + + if ( sw != glyph->swidth ) + { + glyph->swidth = sw; + + if ( p->glyph_enc == -1 ) + _bdf_set_glyph_modified( font->umod, + font->unencoded_used - 1 ); + else + _bdf_set_glyph_modified( font->nmod, glyph->encoding ); + + p->flags |= _BDF_SWIDTH_ADJ; + font->modified = 1; + } + } + + p->flags |= _BDF_BBX; + goto Exit; + } + + /* And finally, gather up the bitmap. */ + if ( ft_memcmp( line, "BITMAP", 6 ) == 0 ) + { + if ( !( p->flags & _BDF_BBX ) ) + { + /* Missing BBX field. */ + FT_ERROR(( "_bdf_parse_glyphs: " ERRMSG1, lineno, "BBX" )); + error = BDF_Err_Missing_Bbx_Field; + goto Exit; + } + + /* Allocate enough space for the bitmap. */ + glyph->bpr = ( glyph->bbx.width * p->font->bpp + 7 ) >> 3; + glyph->bytes = (unsigned short)( glyph->bpr * glyph->bbx.height ); + + if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) ) + goto Exit; + + p->row = 0; + p->flags |= _BDF_BITMAP; + + goto Exit; + } + + error = BDF_Err_Invalid_File_Format; + + Exit: + return error; + } + + + /* Load the font properties. */ + static FT_Error + _bdf_parse_properties( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data ) + { + unsigned long vlen; + _bdf_line_func_t* next; + _bdf_parse_t* p; + char* name; + char* value; + char nbuf[128]; + FT_Memory memory; + FT_Error error = BDF_Err_Ok; + + FT_UNUSED( lineno ); + + + next = (_bdf_line_func_t *)call_data; + p = (_bdf_parse_t *) client_data; + + memory = p->font->memory; + + /* Check for the end of the properties. */ + if ( ft_memcmp( line, "ENDPROPERTIES", 13 ) == 0 ) + { + /* If the FONT_ASCENT or FONT_DESCENT properties have not been */ + /* encountered yet, then make sure they are added as properties and */ + /* make sure they are set from the font bounding box info. */ + /* */ + /* This is *always* done regardless of the options, because X11 */ + /* requires these two fields to compile fonts. */ + if ( bdf_get_font_property( p->font, "FONT_ASCENT" ) == 0 ) + { + p->font->font_ascent = p->font->bbx.ascent; + ft_sprintf( nbuf, "%hd", p->font->bbx.ascent ); + error = _bdf_add_property( p->font, (char *)"FONT_ASCENT", nbuf ); + if ( error ) + goto Exit; + + FT_TRACE2(( "_bdf_parse_properties: " ACMSG1, p->font->bbx.ascent )); + p->font->modified = 1; + } + + if ( bdf_get_font_property( p->font, "FONT_DESCENT" ) == 0 ) + { + p->font->font_descent = p->font->bbx.descent; + ft_sprintf( nbuf, "%hd", p->font->bbx.descent ); + error = _bdf_add_property( p->font, (char *)"FONT_DESCENT", nbuf ); + if ( error ) + goto Exit; + + FT_TRACE2(( "_bdf_parse_properties: " ACMSG2, p->font->bbx.descent )); + p->font->modified = 1; + } + + p->flags &= ~_BDF_PROPS; + *next = _bdf_parse_glyphs; + + goto Exit; + } + + /* Ignore the _XFREE86_GLYPH_RANGES properties. */ + if ( ft_memcmp( line, "_XFREE86_GLYPH_RANGES", 21 ) == 0 ) + goto Exit; + + /* Handle COMMENT fields and properties in a special way to preserve */ + /* the spacing. */ + if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) + { + name = value = line; + value += 7; + if ( *value ) + *value++ = 0; + error = _bdf_add_property( p->font, name, value ); + if ( error ) + goto Exit; + } + else if ( _bdf_is_atom( line, linelen, &name, &value, p->font ) ) + { + error = _bdf_add_property( p->font, name, value ); + if ( error ) + goto Exit; + } + else + { + error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); + if ( error ) + goto Exit; + name = p->list.field[0]; + + _bdf_shift( 1, &p->list ); + value = _bdf_join( ' ', &vlen, &p->list ); + + error = _bdf_add_property( p->font, name, value ); + if ( error ) + goto Exit; + } + + Exit: + return error; + } + + + /* Load the font header. */ + static FT_Error + _bdf_parse_start( char* line, + unsigned long linelen, + unsigned long lineno, + void* call_data, + void* client_data ) + { + unsigned long slen; + _bdf_line_func_t* next; + _bdf_parse_t* p; + bdf_font_t* font; + char *s; + + FT_Memory memory = NULL; + FT_Error error = BDF_Err_Ok; + + FT_UNUSED( lineno ); /* only used in debug mode */ + + + next = (_bdf_line_func_t *)call_data; + p = (_bdf_parse_t *) client_data; + + if ( p->font ) + memory = p->font->memory; + + /* Check for a comment. This is done to handle those fonts that have */ + /* comments before the STARTFONT line for some reason. */ + if ( ft_memcmp( line, "COMMENT", 7 ) == 0 ) + { + if ( p->opts->keep_comments != 0 && p->font != 0 ) + { + linelen -= 7; + + s = line + 7; + if ( *s != 0 ) + { + s++; + linelen--; + } + + error = _bdf_add_comment( p->font, s, linelen ); + if ( error ) + goto Exit; + /* here font is not defined! */ + } + + goto Exit; + } + + if ( !( p->flags & _BDF_START ) ) + { + memory = p->memory; + + if ( ft_memcmp( line, "STARTFONT", 9 ) != 0 ) + { + /* No STARTFONT field is a good indication of a problem. */ + error = BDF_Err_Missing_Startfont_Field; + goto Exit; + } + + p->flags = _BDF_START; + font = p->font = 0; + + if ( FT_NEW( font ) ) + goto Exit; + p->font = font; + + font->memory = p->memory; + p->memory = 0; + + { /* setup */ + unsigned long i; + bdf_property_t* prop; + + + error = hash_init( &(font->proptbl), memory ); + if ( error ) + goto Exit; + for ( i = 0, prop = (bdf_property_t*)_bdf_properties; + i < _num_bdf_properties; i++, prop++ ) + { + error = hash_insert( prop->name, (void *)i, + &(font->proptbl), memory ); + if ( error ) + goto Exit; + } + } + + if ( FT_ALLOC( p->font->internal, sizeof ( hashtable ) ) ) + goto Exit; + error = hash_init( (hashtable *)p->font->internal,memory ); + if ( error ) + goto Exit; + p->font->spacing = p->opts->font_spacing; + p->font->default_char = -1; + + goto Exit; + } + + /* Check for the start of the properties. */ + if ( ft_memcmp( line, "STARTPROPERTIES", 15 ) == 0 ) + { + error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); + if ( error ) + goto Exit; + p->cnt = p->font->props_size = _bdf_atoul( p->list.field[1], 0, 10 ); + + if ( FT_NEW_ARRAY( p->font->props, p->cnt ) ) + goto Exit; + + p->flags |= _BDF_PROPS; + *next = _bdf_parse_properties; + + goto Exit; + } + + /* Check for the FONTBOUNDINGBOX field. */ + if ( ft_memcmp( line, "FONTBOUNDINGBOX", 15 ) == 0 ) + { + if ( !(p->flags & _BDF_SIZE ) ) + { + /* Missing the SIZE field. */ + FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "SIZE" )); + error = BDF_Err_Missing_Size_Field; + goto Exit; + } + + error = _bdf_split( (char *)" +", line, linelen, &p->list , memory ); + if ( error ) + goto Exit; + + p->font->bbx.width = _bdf_atos( p->list.field[1], 0, 10 ); + p->font->bbx.height = _bdf_atos( p->list.field[2], 0, 10 ); + + p->font->bbx.x_offset = _bdf_atos( p->list.field[3], 0, 10 ); + p->font->bbx.y_offset = _bdf_atos( p->list.field[4], 0, 10 ); + + p->font->bbx.ascent = (short)( p->font->bbx.height + + p->font->bbx.y_offset ); + + p->font->bbx.descent = (short)( -p->font->bbx.y_offset ); + + p->flags |= _BDF_FONT_BBX; + + goto Exit; + } + + /* The next thing to check for is the FONT field. */ + if ( ft_memcmp( line, "FONT", 4 ) == 0 ) + { + error = _bdf_split( (char *)" +", line, linelen, &p->list , memory ); + if ( error ) + goto Exit; + _bdf_shift( 1, &p->list ); + + s = _bdf_join( ' ', &slen, &p->list ); + if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) ) + goto Exit; + FT_MEM_COPY( p->font->name, s, slen + 1 ); + + /* If the font name is an XLFD name, set the spacing to the one in */ + /* the font name. If there is no spacing fall back on the default. */ + error = _bdf_set_default_spacing( p->font, p->opts ); + if ( error ) + goto Exit; + + p->flags |= _BDF_FONT_NAME; + + goto Exit; + } + + /* Check for the SIZE field. */ + if ( ft_memcmp( line, "SIZE", 4 ) == 0 ) + { + if ( !( p->flags & _BDF_FONT_NAME ) ) + { + /* Missing the FONT field. */ + FT_ERROR(( "_bdf_parse_start: " ERRMSG1, lineno, "FONT" )); + error = BDF_Err_Missing_Font_Field; + goto Exit; + } + + error = _bdf_split( (char *)" +", line, linelen, &p->list, memory ); + if ( error ) + goto Exit; + + p->font->point_size = _bdf_atoul( p->list.field[1], 0, 10 ); + p->font->resolution_x = _bdf_atoul( p->list.field[2], 0, 10 ); + p->font->resolution_y = _bdf_atoul( p->list.field[3], 0, 10 ); + + /* Check for the bits per pixel field. */ + if ( p->list.used == 5 ) + { + unsigned short bitcount, i, shift; + + + p->font->bpp = (unsigned short)_bdf_atos( p->list.field[4], 0, 10 ); + + /* Only values 1, 2, 4, 8 are allowed. */ + shift = p->font->bpp; + bitcount = 0; + for ( i = 0; shift > 0; i++ ) + { + if ( shift & 1 ) + bitcount = i; + shift >>= 1; + } + + shift = (short)( ( bitcount > 3 ) ? 8 : ( 1 << bitcount ) ); + + if ( p->font->bpp > shift || p->font->bpp != shift ) + { + /* select next higher value */ + p->font->bpp = (unsigned short)( shift << 1 ); + FT_TRACE2(( "_bdf_parse_start: " ACMSG11, p->font->bpp )); + } + } + else + p->font->bpp = 1; + + p->flags |= _BDF_SIZE; + + goto Exit; + } + + error = BDF_Err_Invalid_File_Format; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* API. */ + /* */ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + bdf_load_font( FT_Stream stream, + FT_Memory extmemory, + bdf_options_t* opts, + bdf_font_t* *font ) + { + unsigned long lineno; + _bdf_parse_t *p; + + FT_Memory memory = extmemory; + FT_Error error = BDF_Err_Ok; + + + if ( FT_ALLOC( p, sizeof ( _bdf_parse_t ) ) ) + goto Exit; + + memory = NULL; + p->opts = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts ); + p->minlb = 32767; + p->memory = extmemory; /* only during font creation */ + + error = _bdf_readstream( stream, _bdf_parse_start, + (void *)p, &lineno ); + if ( error ) + goto Exit; + + if ( p->font != 0 ) + { + /* If the font is not proportional, set the font's monowidth */ + /* field to the width of the font bounding box. */ + memory = p->font->memory; + + if ( p->font->spacing != BDF_PROPORTIONAL ) + p->font->monowidth = p->font->bbx.width; + + /* If the number of glyphs loaded is not that of the original count, */ + /* indicate the difference. */ + if ( p->cnt != p->font->glyphs_used + p->font->unencoded_used ) + { + FT_TRACE2(( "bdf_load_font: " ACMSG15, p->cnt, + p->font->glyphs_used + p->font->unencoded_used )); + p->font->modified = 1; + } + + /* Once the font has been loaded, adjust the overall font metrics if */ + /* necessary. */ + if ( p->opts->correct_metrics != 0 && + ( p->font->glyphs_used > 0 || p->font->unencoded_used > 0 ) ) + { + if ( p->maxrb - p->minlb != p->font->bbx.width ) + { + FT_TRACE2(( "bdf_load_font: " ACMSG3, + p->font->bbx.width, p->maxrb - p->minlb )); + p->font->bbx.width = (unsigned short)( p->maxrb - p->minlb ); + p->font->modified = 1; + } + + if ( p->font->bbx.x_offset != p->minlb ) + { + FT_TRACE2(( "bdf_load_font: " ACMSG4, + p->font->bbx.x_offset, p->minlb )); + p->font->bbx.x_offset = p->minlb; + p->font->modified = 1; + } + + if ( p->font->bbx.ascent != p->maxas ) + { + FT_TRACE2(( "bdf_load_font: " ACMSG5, + p->font->bbx.ascent, p->maxas )); + p->font->bbx.ascent = p->maxas; + p->font->modified = 1; + } + + if ( p->font->bbx.descent != p->maxds ) + { + FT_TRACE2(( "bdf_load_font: " ACMSG6, + p->font->bbx.descent, p->maxds )); + p->font->bbx.descent = p->maxds; + p->font->bbx.y_offset = (short)( -p->maxds ); + p->font->modified = 1; + } + + if ( p->maxas + p->maxds != p->font->bbx.height ) + { + FT_TRACE2(( "bdf_load_font: " ACMSG7, + p->font->bbx.height, p->maxas + p->maxds )); + p->font->bbx.height = (unsigned short)( p->maxas + p->maxds ); + } + + if ( p->flags & _BDF_SWIDTH_ADJ ) + FT_TRACE2(( "bdf_load_font: " ACMSG8 )); + } + } + + if ( p->flags & _BDF_START ) + { + { + /* The ENDFONT field was never reached or did not exist. */ + if ( !( p->flags & _BDF_GLYPHS ) ) + /* Error happened while parsing header. */ + FT_ERROR(( "bdf_load_font: " ERRMSG2, lineno )); + else + /* Error happened when parsing glyphs. */ + FT_ERROR(( "bdf_load_font: " ERRMSG3, lineno )); + } + } + + /* Free up the list used during the parsing. */ + if ( memory != NULL ) + FT_FREE( p->list.field ); + + if ( p->font != 0 ) + { + /* Make sure the comments are NULL terminated if they exist. */ + memory = p->font->memory; + + if ( p->font->comments_len > 0 ) { + if ( FT_RENEW_ARRAY( p->font->comments, + p->font->comments_len, + p->font->comments_len + 1 ) ) + goto Exit; + + p->font->comments[p->font->comments_len] = 0; + } + } + else if ( error == BDF_Err_Ok ) + error = BDF_Err_Invalid_File_Format; + + *font = p->font; + + Exit: + if ( p ) + { + memory = extmemory; + FT_FREE( p ); + } + + return error; + } + + + FT_LOCAL_DEF( void ) + bdf_free_font( bdf_font_t* font ) + { + bdf_property_t* prop; + unsigned long i; + bdf_glyph_t* glyphs; + FT_Memory memory; + + + if ( font == 0 ) + return; + + memory = font->memory; + + FT_FREE( font->name ); + + /* Free up the internal hash table of property names. */ + if ( font->internal ) + { + hash_free( (hashtable *)font->internal, memory ); + FT_FREE( font->internal ); + } + + /* Free up the comment info. */ + FT_FREE( font->comments ); + + /* Free up the properties. */ + for ( i = 0; i < font->props_size; i++ ) + { + if ( font->props[i].format == BDF_ATOM ) + FT_FREE( font->props[i].value.atom ); + } + + FT_FREE( font->props ); + + /* Free up the character info. */ + for ( i = 0, glyphs = font->glyphs; + i < font->glyphs_used; i++, glyphs++ ) + { + FT_FREE( glyphs->name ); + FT_FREE( glyphs->bitmap ); + } + + for ( i = 0, glyphs = font->unencoded; i < font->unencoded_used; + i++, glyphs++ ) + { + FT_FREE( glyphs->name ); + FT_FREE( glyphs->bitmap ); + } + + FT_FREE( font->glyphs ); + FT_FREE( font->unencoded ); + + /* Free up the overflow storage if it was used. */ + for ( i = 0, glyphs = font->overflow.glyphs; + i < font->overflow.glyphs_used; i++, glyphs++ ) + { + FT_FREE( glyphs->name ); + FT_FREE( glyphs->bitmap ); + } + + FT_FREE( font->overflow.glyphs ); + + /* bdf_cleanup */ + hash_free( &(font->proptbl), memory ); + + /* Free up the user defined properties. */ + for (prop = font->user_props, i = 0; + i < font->nuser_props; i++, prop++ ) + { + FT_FREE( prop->name ); + if ( prop->format == BDF_ATOM ) + FT_FREE( prop->value.atom ); + } + + FT_FREE( font->user_props ); + + /* FREE( font ); */ /* XXX Fixme */ + } + + + FT_LOCAL_DEF( bdf_property_t * ) + bdf_get_font_property( bdf_font_t* font, + const char* name ) + { + hashnode hn; + + + if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 ) + return 0; + + hn = hash_lookup( name, (hashtable *)font->internal ); + + return hn ? ( font->props + (unsigned long)hn->data ) : 0; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcache.c b/Utilities/vtkfreetype/src/cache/ftcache.c new file mode 100644 index 0000000..d41e91e --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcache.c @@ -0,0 +1,31 @@ +/***************************************************************************/ +/* */ +/* ftcache.c */ +/* */ +/* The FreeType Caching sub-system (body only). */ +/* */ +/* Copyright 2000-2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "ftcmru.c" +#include "ftcmanag.c" +#include "ftccache.c" +#include "ftccmap.c" +#include "ftcglyph.c" +#include "ftcimage.c" +#include "ftcsbits.c" +#include "ftcbasic.c" + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcbasic.c b/Utilities/vtkfreetype/src/cache/ftcbasic.c new file mode 100644 index 0000000..9a91f35 --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcbasic.c @@ -0,0 +1,445 @@ +/***************************************************************************/ +/* */ +/* ftcbasic.c */ +/* */ +/* The FreeType basic cache interface (body). */ +/* */ +/* Copyright 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_GLYPH_H +#include FT_CACHE_INTERNAL_IMAGE_H +#include FT_CACHE_INTERNAL_SBITS_H +#include FT_INTERNAL_MEMORY_H + +#include "ftccback.h" +#include "ftcerror.h" + + + /* + * Basic Families + * + */ + typedef struct FTC_BasicAttrRec_ + { + FTC_ScalerRec scaler; + FT_UInt load_flags; + + } FTC_BasicAttrRec, *FTC_BasicAttrs; + +#define FTC_BASIC_ATTR_COMPARE( a, b ) \ + ( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \ + (a)->load_flags == (b)->load_flags ) + +#define FTC_BASIC_ATTR_HASH( a ) \ + ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags ) + + + typedef struct FTC_BasicQueryRec_ + { + FTC_GQueryRec gquery; + FTC_BasicAttrRec attrs; + + } FTC_BasicQueryRec, *FTC_BasicQuery; + + + typedef struct FTC_BasicFamilyRec_ + { + FTC_FamilyRec family; + FTC_BasicAttrRec attrs; + + } FTC_BasicFamilyRec, *FTC_BasicFamily; + + + FT_CALLBACK_DEF( FT_Bool ) + ftc_basic_family_compare( FTC_MruNode ftcfamily, + FT_Pointer ftcquery ) + { + FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; + FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; + + + return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs ); + } + + + FT_CALLBACK_DEF( FT_Error ) + ftc_basic_family_init( FTC_MruNode ftcfamily, + FT_Pointer ftcquery, + FT_Pointer ftccache ) + { + FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; + FTC_BasicQuery query = (FTC_BasicQuery)ftcquery; + FTC_Cache cache = (FTC_Cache)ftccache; + + + FTC_Family_Init( FTC_FAMILY( family ), cache ); + family->attrs = query->attrs; + return 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + ftc_basic_family_get_count( FTC_Family ftcfamily, + FTC_Manager manager ) + { + FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; + FT_Error error; + FT_Face face; + FT_UInt result = 0; + + + error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id, + &face ); + if ( !error ) + result = face->num_glyphs; + + return result; + } + + + FT_CALLBACK_DEF( FT_Error ) + ftc_basic_family_load_bitmap( FTC_Family ftcfamily, + FT_UInt gindex, + FTC_Manager manager, + FT_Face *aface ) + { + FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; + FT_Error error; + FT_Size size; + + + error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size ); + if ( !error ) + { + FT_Face face = size->face; + + + error = FT_Load_Glyph( face, gindex, + family->attrs.load_flags | FT_LOAD_RENDER ); + if ( !error ) + *aface = face; + } + + return error; + } + + + FT_CALLBACK_DEF( FT_Error ) + ftc_basic_family_load_glyph( FTC_Family ftcfamily, + FT_UInt gindex, + FTC_Cache cache, + FT_Glyph *aglyph ) + { + FTC_BasicFamily family = (FTC_BasicFamily)ftcfamily; + FT_Error error; + FTC_Scaler scaler = &family->attrs.scaler; + FT_Face face; + FT_Size size; + + + /* we will now load the glyph image */ + error = FTC_Manager_LookupSize( cache->manager, + scaler, + &size ); + if ( !error ) + { + face = size->face; + + error = FT_Load_Glyph( face, gindex, family->attrs.load_flags ); + if ( !error ) + { + if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP || + face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ) + { + /* ok, copy it */ + FT_Glyph glyph; + + + error = FT_Get_Glyph( face->glyph, &glyph ); + if ( !error ) + { + *aglyph = glyph; + goto Exit; + } + } + else + error = FTC_Err_Invalid_Argument; + } + } + + Exit: + return error; + } + + + FT_CALLBACK_DEF( FT_Bool ) + ftc_basic_gnode_compare_faceid( FTC_Node ftcgnode, + FT_Pointer ftcface_id, + FTC_Cache cache ) + { + FTC_GNode gnode = (FTC_GNode)ftcgnode; + FTC_FaceID face_id = (FTC_FaceID)ftcface_id; + FTC_BasicFamily family = (FTC_BasicFamily)gnode->family; + FT_Bool result; + + + result = FT_BOOL( family->attrs.scaler.face_id == face_id ); + if ( result ) + { + /* we must call this function to avoid this node from appearing + * in later lookups with the same face_id! + */ + FTC_GNode_UnselectFamily( gnode, cache ); + } + return result; + } + + + /* + * + * basic image cache + * + */ + + FT_CALLBACK_TABLE_DEF + const FTC_IFamilyClassRec ftc_basic_image_family_class = + { + { + sizeof ( FTC_BasicFamilyRec ), + ftc_basic_family_compare, + ftc_basic_family_init, + 0, /* FTC_MruNode_ResetFunc */ + 0 /* FTC_MruNode_DoneFunc */ + }, + ftc_basic_family_load_glyph + }; + + + FT_CALLBACK_TABLE_DEF + const FTC_GCacheClassRec ftc_basic_image_cache_class = + { + { + ftc_inode_new, + ftc_inode_weight, + ftc_gnode_compare, + ftc_basic_gnode_compare_faceid, + ftc_inode_free, + + sizeof ( FTC_GCacheRec ), + ftc_gcache_init, + ftc_gcache_done + }, + (FTC_MruListClass)&ftc_basic_image_family_class + }; + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_ImageCache_New( FTC_Manager manager, + FTC_ImageCache *acache ) + { + return FTC_GCache_New( manager, &ftc_basic_image_cache_class, + (FTC_GCache*)acache ); + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_ImageCache_Lookup( FTC_ImageCache cache, + FTC_ImageType type, + FT_UInt gindex, + FT_Glyph *aglyph, + FTC_Node *anode ) + { + FTC_BasicQueryRec query; + FTC_INode node; + FT_Error error; + FT_UInt32 hash; + + + /* some argument checks are delayed to FTC_Cache_Lookup */ + if ( !aglyph ) + { + error = FTC_Err_Invalid_Argument; + goto Exit; + } + + *aglyph = NULL; + if ( anode ) + *anode = NULL; + + query.attrs.scaler.face_id = type->face_id; + query.attrs.scaler.width = type->width; + query.attrs.scaler.height = type->height; + query.attrs.scaler.pixel = 1; + query.attrs.load_flags = type->flags; + + query.attrs.scaler.x_res = 0; /* make compilers happy */ + query.attrs.scaler.y_res = 0; + + hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex; + +#if 1 /* inlining is about 50% faster! */ + FTC_GCACHE_LOOKUP_CMP( cache, + ftc_basic_family_compare, + FTC_GNode_Compare, + hash, gindex, + &query, + node, + error ); +#else + error = FTC_GCache_Lookup( FTC_GCACHE( cache ), + hash, gindex, + FTC_GQUERY( &query ), + (FTC_Node*) &node ); +#endif + if ( !error ) + { + *aglyph = FTC_INODE( node )->glyph; + + if ( anode ) + { + *anode = FTC_NODE( node ); + FTC_NODE( node )->ref_count++; + } + } + + Exit: + return error; + } + + + /* + * + * basic small bitmap cache + * + */ + + + FT_CALLBACK_TABLE_DEF + const FTC_SFamilyClassRec ftc_basic_sbit_family_class = + { + { + sizeof( FTC_BasicFamilyRec ), + ftc_basic_family_compare, + ftc_basic_family_init, + 0, /* FTC_MruNode_ResetFunc */ + 0 /* FTC_MruNode_DoneFunc */ + }, + ftc_basic_family_get_count, + ftc_basic_family_load_bitmap + }; + + + FT_CALLBACK_TABLE_DEF + const FTC_GCacheClassRec ftc_basic_sbit_cache_class = + { + { + ftc_snode_new, + ftc_snode_weight, + ftc_snode_compare, + ftc_basic_gnode_compare_faceid, + ftc_snode_free, + + sizeof ( FTC_GCacheRec ), + ftc_gcache_init, + ftc_gcache_done + }, + (FTC_MruListClass)&ftc_basic_sbit_family_class + }; + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_SBitCache_New( FTC_Manager manager, + FTC_SBitCache *acache ) + { + return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class, + (FTC_GCache*)acache ); + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_SBitCache_Lookup( FTC_SBitCache cache, + FTC_ImageType type, + FT_UInt gindex, + FTC_SBit *ansbit, + FTC_Node *anode ) + { + FT_Error error; + FTC_BasicQueryRec query; + FTC_SNode node; + FT_UInt32 hash; + + + if ( anode ) + *anode = NULL; + + /* other argument checks delayed to FTC_Cache_Lookup */ + if ( !ansbit ) + return FTC_Err_Invalid_Argument; + + *ansbit = NULL; + + query.attrs.scaler.face_id = type->face_id; + query.attrs.scaler.width = type->width; + query.attrs.scaler.height = type->height; + query.attrs.scaler.pixel = 1; + query.attrs.load_flags = type->flags; + + query.attrs.scaler.x_res = 0; /* make compilers happy */ + query.attrs.scaler.y_res = 0; + + /* beware, the hash must be the same for all glyph ranges! */ + hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + + gindex / FTC_SBIT_ITEMS_PER_NODE; + +#if 1 /* inlining is about 50% faster! */ + FTC_GCACHE_LOOKUP_CMP( cache, + ftc_basic_family_compare, + FTC_SNode_Compare, + hash, gindex, + &query, + node, + error ); +#else + error = FTC_GCache_Lookup( FTC_GCACHE( cache ), + hash, + gindex, + FTC_GQUERY( &query ), + (FTC_Node*)&node ); +#endif + if ( error ) + goto Exit; + + *ansbit = node->sbits + ( gindex - FTC_GNODE( node )->gindex ); + + if ( anode ) + { + *anode = FTC_NODE( node ); + FTC_NODE( node )->ref_count++; + } + + Exit: + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftccache.c b/Utilities/vtkfreetype/src/cache/ftccache.c new file mode 100644 index 0000000..3a8a40c --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftccache.c @@ -0,0 +1,604 @@ +/***************************************************************************/ +/* */ +/* ftccache.c */ +/* */ +/* The FreeType internal cache interface (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CACHE_INTERNAL_MANAGER_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H + +#include "ftccback.h" +#include "ftcerror.h" + + +#define FTC_HASH_MAX_LOAD 2 +#define FTC_HASH_MIN_LOAD 1 +#define FTC_HASH_SUB_LOAD ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD ) + +/* this one _must_ be a power of 2! */ +#define FTC_HASH_INITIAL_SIZE 8 + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CACHE NODE DEFINITIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* add a new node to the head of the manager's circular MRU list */ + static void + ftc_node_mru_link( FTC_Node node, + FTC_Manager manager ) + { + FTC_MruNode_Prepend( (FTC_MruNode*)&manager->nodes_list, + (FTC_MruNode)node ); + manager->num_nodes++; + } + + + /* remove a node from the manager's MRU list */ + static void + ftc_node_mru_unlink( FTC_Node node, + FTC_Manager manager ) + { + FTC_MruNode_Remove( (FTC_MruNode*)&manager->nodes_list, + (FTC_MruNode)node ); + manager->num_nodes--; + } + + + /* move a node to the head of the manager's MRU list */ + static void + ftc_node_mru_up( FTC_Node node, + FTC_Manager manager ) + { + FTC_MruNode_Up( (FTC_MruNode*)&manager->nodes_list, + (FTC_MruNode)node ); + } + + + /* Note that this function cannot fail. If we cannot re-size the + * buckets array appropriately, we simply degrade the hash table's + * performance! + */ + static void + ftc_cache_resize( FTC_Cache cache ) + { + for (;;) + { + FTC_Node node, *pnode; + FT_UInt p = cache->p; + FT_UInt mask = cache->mask; + FT_UInt count = mask + p + 1; /* number of buckets */ + + + /* do we need to shrink the buckets array? */ + if ( cache->slack < 0 ) + { + FTC_Node new_list = NULL; + + + /* try to expand the buckets array _before_ splitting + * the bucket lists + */ + if ( p >= mask ) + { + FT_Memory memory = cache->memory; + + + /* if we can't expand the array, leave immediately */ + if ( FT_MEM_RENEW_ARRAY( cache->buckets, (mask+1)*2, (mask+1)*4 ) ) + break; + } + + /* split a single bucket */ + pnode = cache->buckets + p; + + for (;;) + { + node = *pnode; + if ( node == NULL ) + break; + + if ( node->hash & ( mask + 1 ) ) + { + *pnode = node->link; + node->link = new_list; + new_list = node; + } + else + pnode = &node->link; + } + + cache->buckets[p + mask + 1] = new_list; + + cache->slack += FTC_HASH_MAX_LOAD; + + if ( p >= mask ) + { + cache->mask = 2 * mask + 1; + cache->p = 0; + } + else + cache->p = p + 1; + } + + /* do we need to expand the buckets array? */ + else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD ) + { + FT_UInt old_index = p + mask; + FTC_Node* pold; + + + if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE ) + break; + + if ( p == 0 ) + { + FT_Memory memory = cache->memory; + + + /* if we can't shrink the array, leave immediately */ + if ( FT_MEM_RENEW_ARRAY( cache->buckets, + ( mask + 1 ) * 2, mask + 1 ) ) + break; + + cache->mask >>= 1; + p = cache->mask; + } + else + p--; + + pnode = cache->buckets + p; + while ( *pnode ) + pnode = &(*pnode)->link; + + pold = cache->buckets + old_index; + *pnode = *pold; + *pold = NULL; + + cache->slack -= FTC_HASH_MAX_LOAD; + cache->p = p; + } + else /* the hash table is balanced */ + break; + } + } + + + /* remove a node from its cache's hash table */ + static void + ftc_node_hash_unlink( FTC_Node node0, + FTC_Cache cache ) + { + FTC_Node *pnode; + FT_UInt idx; + + + idx = (FT_UInt)( node0->hash & cache->mask ); + if ( idx < cache->p ) + idx = (FT_UInt)( node0->hash & ( 2 * cache->mask + 1 ) ); + + pnode = cache->buckets + idx; + + for (;;) + { + FTC_Node node = *pnode; + + + if ( node == NULL ) + { + FT_ERROR(( "ftc_node_hash_unlink: unknown node!\n" )); + return; + } + + if ( node == node0 ) + break; + + pnode = &(*pnode)->link; + } + + *pnode = node0->link; + node0->link = NULL; + + cache->slack++; + ftc_cache_resize( cache ); + } + + + /* add a node to the `top' of its cache's hash table */ + static void + ftc_node_hash_link( FTC_Node node, + FTC_Cache cache ) + { + FTC_Node *pnode; + FT_UInt idx; + + + idx = (FT_UInt)( node->hash & cache->mask ); + if ( idx < cache->p ) + idx = (FT_UInt)( node->hash & (2 * cache->mask + 1 ) ); + + pnode = cache->buckets + idx; + + node->link = *pnode; + *pnode = node; + + cache->slack--; + ftc_cache_resize( cache ); + } + + + /* remove a node from the cache manager */ + FT_EXPORT_DEF( void ) + ftc_node_destroy( FTC_Node node, + FTC_Manager manager ) + { + FTC_Cache cache; + + +#ifdef FT_DEBUG_ERROR + /* find node's cache */ + if ( node->cache_index >= manager->num_caches ) + { + FT_ERROR(( "ftc_node_destroy: invalid node handle\n" )); + return; + } +#endif + + cache = manager->caches[node->cache_index]; + +#ifdef FT_DEBUG_ERROR + if ( cache == NULL ) + { + FT_ERROR(( "ftc_node_destroy: invalid node handle\n" )); + return; + } +#endif + + manager->cur_weight -= cache->clazz.node_weight( node, cache ); + + /* remove node from mru list */ + ftc_node_mru_unlink( node, manager ); + + /* remove node from cache's hash table */ + ftc_node_hash_unlink( node, cache ); + + /* now finalize it */ + cache->clazz.node_free( node, cache ); + +#if 0 + /* check, just in case of general corruption :-) */ + if ( manager->num_nodes == 0 ) + FT_ERROR(( "ftc_node_destroy: invalid cache node count! = %d\n", + manager->num_nodes )); +#endif + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** ABSTRACT CACHE CLASS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_EXPORT_DEF( FT_Error ) + FTC_Cache_Init( FTC_Cache cache ) + { + return ftc_cache_init( cache ); + } + + + FT_LOCAL_DEF( FT_Error ) + ftc_cache_init( FTC_Cache cache ) + { + FT_Memory memory = cache->memory; + + + cache->p = 0; + cache->mask = FTC_HASH_INITIAL_SIZE - 1; + cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD; + + return ( FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 ) ); + } + + + FT_EXPORT_DEF( void ) + FTC_Cache_Clear( FTC_Cache cache ) + { + if ( cache ) + { + FTC_Manager manager = cache->manager; + FT_UFast i; + FT_UInt count; + + + count = cache->p + cache->mask + 1; + + for ( i = 0; i < count; i++ ) + { + FTC_Node *pnode = cache->buckets + i, next, node = *pnode; + + + while ( node ) + { + next = node->link; + node->link = NULL; + + /* remove node from mru list */ + ftc_node_mru_unlink( node, manager ); + + /* now finalize it */ + manager->cur_weight -= cache->clazz.node_weight( node, cache ); + + cache->clazz.node_free( node, cache ); + node = next; + } + cache->buckets[i] = NULL; + } + ftc_cache_resize( cache ); + } + } + + + FT_LOCAL_DEF( void ) + ftc_cache_done( FTC_Cache cache ) + { + if ( cache->memory ) + { + FT_Memory memory = cache->memory; + + + FTC_Cache_Clear( cache ); + + FT_FREE( cache->buckets ); + cache->mask = 0; + cache->p = 0; + cache->slack = 0; + + cache->memory = NULL; + } + } + + + FT_EXPORT_DEF( void ) + FTC_Cache_Done( FTC_Cache cache ) + { + ftc_cache_done( cache ); + } + + + static void + ftc_cache_add( FTC_Cache cache, + FT_UInt32 hash, + FTC_Node node ) + { + node->hash = hash; + node->cache_index = (FT_UInt16) cache->index; + node->ref_count = 0; + + ftc_node_hash_link( node, cache ); + ftc_node_mru_link( node, cache->manager ); + + { + FTC_Manager manager = cache->manager; + + + manager->cur_weight += cache->clazz.node_weight( node, cache ); + + if ( manager->cur_weight >= manager->max_weight ) + { + node->ref_count++; + FTC_Manager_Compress( manager ); + node->ref_count--; + } + } + } + + + FT_EXPORT_DEF( FT_Error ) + FTC_Cache_NewNode( FTC_Cache cache, + FT_UInt32 hash, + FT_Pointer query, + FTC_Node *anode ) + { + FT_Error error; + FTC_Node node; + + /* + * Try to allocate a new cache node. Note that in case of + * out-of-memory error (OOM), we'll flush the cache a bit, + * then try again. + * + * On each try, the `tries' variable gives the number + * of old nodes we want to flush from the manager's global list + * before the next allocation attempt. It barely doubles on + * each iteration. + * + */ + error = cache->clazz.node_new( &node, query, cache ); + if ( error ) + goto FlushCache; + + AddNode: + /* don't assume that the cache has the same number of buckets, since + * our allocation request might have triggered global cache flushing + */ + ftc_cache_add( cache, hash, node ); + + Exit: + *anode = node; + return error; + + FlushCache: + node = NULL; + if ( error != FT_Err_Out_Of_Memory ) + goto Exit; + + { + FTC_Manager manager = cache->manager; + FT_UInt count, tries = 1; + + + for (;;) + { + error = cache->clazz.node_new( &node, query, cache ); + if ( !error ) + break; + + node = NULL; + if ( error != FT_Err_Out_Of_Memory ) + goto Exit; + + count = FTC_Manager_FlushN( manager, tries ); + if ( count == 0 ) + goto Exit; + + if ( count == tries ) + { + count = tries * 2; + if ( count < tries || count > manager->num_nodes ) + count = manager->num_nodes; + } + tries = count; + } + } + goto AddNode; + } + + + FT_EXPORT_DEF( FT_Error ) + FTC_Cache_Lookup( FTC_Cache cache, + FT_UInt32 hash, + FT_Pointer query, + FTC_Node *anode ) + { + FT_UFast idx; + FTC_Node* bucket; + FTC_Node* pnode; + FTC_Node node; + FT_Error error = 0; + + FTC_Node_CompareFunc compare = cache->clazz.node_compare; + + + if ( cache == NULL || anode == NULL ) + return FT_Err_Invalid_Argument; + + idx = hash & cache->mask; + if ( idx < cache->p ) + idx = hash & ( cache->mask * 2 + 1 ); + + bucket = cache->buckets + idx; + pnode = bucket; + for (;;) + { + node = *pnode; + if ( node == NULL ) + goto NewNode; + + if ( node->hash == hash && compare( node, query, cache ) ) + break; + + pnode = &node->link; + } + + if ( node != *bucket ) + { + *pnode = node->link; + node->link = *bucket; + *bucket = node; + } + + /* move to head of MRU list */ + { + FTC_Manager manager = cache->manager; + + + if ( node != manager->nodes_list ) + ftc_node_mru_up( node, manager ); + } + *anode = node; + return error; + + NewNode: + return FTC_Cache_NewNode( cache, hash, query, anode ); + } + + + FT_EXPORT_DEF( void ) + FTC_Cache_RemoveFaceID( FTC_Cache cache, + FTC_FaceID face_id ) + { + FT_UFast i, count; + FTC_Manager manager = cache->manager; + FTC_Node frees = NULL; + + + count = cache->p + cache->mask; + for ( i = 0; i < count; i++ ) + { + FTC_Node* bucket = cache->buckets + i; + FTC_Node* pnode = bucket; + + + for ( ;; ) + { + FTC_Node node = *pnode; + + + if ( node == NULL ) + break; + + if ( cache->clazz.node_remove_faceid( node, face_id, cache ) ) + { + *pnode = node->link; + node->link = frees; + frees = node; + } + else + pnode = &node->link; + } + } + + /* remove all nodes in the free list */ + while ( frees ) + { + FTC_Node node; + + + node = frees; + frees = node->link; + + manager->cur_weight -= cache->clazz.node_weight( node, cache ); + ftc_node_mru_unlink( node, manager ); + + cache->clazz.node_free( node, cache ); + + cache->slack++; + } + + ftc_cache_resize( cache ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftccback.h b/Utilities/vtkfreetype/src/cache/ftccback.h new file mode 100644 index 0000000..6b47e09 --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftccback.h @@ -0,0 +1,85 @@ +/***************************************************************************/ +/* */ +/* ftccback.h */ +/* */ +/* Callback functions of the caching sub-system (specification only). */ +/* */ +/* Copyright 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#ifndef __FTCCBACK_H__ +#define __FTCCBACK_H__ + +#include <ft2build.h> +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_MRU_H +#include FT_CACHE_INTERNAL_IMAGE_H +#include FT_CACHE_INTERNAL_MANAGER_H +#include FT_CACHE_INTERNAL_GLYPH_H +#include FT_CACHE_INTERNAL_SBITS_H + + + FT_LOCAL( void ) + ftc_inode_free( FTC_Node inode, + FTC_Cache cache ); + + FT_LOCAL( FT_Error ) + ftc_inode_new( FTC_Node *pinode, + FT_Pointer gquery, + FTC_Cache cache ); + + FT_LOCAL( FT_ULong ) + ftc_inode_weight( FTC_Node inode, + FTC_Cache cache ); + + + FT_LOCAL( void ) + ftc_snode_free( FTC_Node snode, + FTC_Cache cache ); + + FT_LOCAL( FT_Error ) + ftc_snode_new( FTC_Node *psnode, + FT_Pointer gquery, + FTC_Cache cache ); + + FT_LOCAL( FT_ULong ) + ftc_snode_weight( FTC_Node snode, + FTC_Cache cache ); + + FT_LOCAL( FT_Bool ) + ftc_snode_compare( FTC_Node snode, + FT_Pointer gquery, + FTC_Cache cache ); + + + FT_LOCAL( FT_Bool ) + ftc_gnode_compare( FTC_Node gnode, + FT_Pointer gquery, + FTC_Cache cache ); + + + FT_LOCAL( FT_Error ) + ftc_gcache_init( FTC_Cache cache ); + + FT_LOCAL( void ) + ftc_gcache_done( FTC_Cache cache ); + + + FT_LOCAL( FT_Error ) + ftc_cache_init( FTC_Cache cache ); + + FT_LOCAL( void ) + ftc_cache_done( FTC_Cache cache ); + + +#endif /* __FTCCBACK_H__ */ + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftccmap.c b/Utilities/vtkfreetype/src/cache/ftccmap.c new file mode 100644 index 0000000..b2812c9 --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftccmap.c @@ -0,0 +1,303 @@ +/***************************************************************************/ +/* */ +/* ftccmap.c */ +/* */ +/* FreeType CharMap cache (body) */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_MANAGER_H +#include FT_INTERNAL_MEMORY_H +#include FT_INTERNAL_DEBUG_H +#include FT_TRUETYPE_IDS_H + +#include "ftccback.h" +#include "ftcerror.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_cache + + + /*************************************************************************/ + /* */ + /* Each FTC_CMapNode contains a simple array to map a range of character */ + /* codes to equivalent glyph indices. */ + /* */ + /* For now, the implementation is very basic: Each node maps a range of */ + /* 128 consecutive character codes to their corresponding glyph indices. */ + /* */ + /* We could do more complex things, but I don't think it is really very */ + /* useful. */ + /* */ + /*************************************************************************/ + + + /* number of glyph indices / character code per node */ +#define FTC_CMAP_INDICES_MAX 128 + + /* compute a query/node hash */ +#define FTC_CMAP_HASH( faceid, index, charcode ) \ + ( FTC_FACE_ID_HASH( faceid ) + 211 * ( index ) + \ + ( (char_code) / FTC_CMAP_INDICES_MAX ) ) + + /* the charmap query */ + typedef struct FTC_CMapQueryRec_ + { + FTC_FaceID face_id; + FT_UInt cmap_index; + FT_UInt32 char_code; + + } FTC_CMapQueryRec, *FTC_CMapQuery; + +#define FTC_CMAP_QUERY( x ) ((FTC_CMapQuery)(x)) +#define FTC_CMAP_QUERY_HASH( x ) \ + FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code ) + + /* the cmap cache node */ + typedef struct FTC_CMapNodeRec_ + { + FTC_NodeRec node; + FTC_FaceID face_id; + FT_UInt cmap_index; + FT_UInt32 first; /* first character in node */ + FT_UInt16 indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices */ + + } FTC_CMapNodeRec, *FTC_CMapNode; + +#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) ) +#define FTC_CMAP_NODE_HASH( x ) \ + FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first ) + + /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */ + /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet */ +#define FTC_CMAP_UNKNOWN ( (FT_UInt16)-1 ) + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CHARMAP NODES *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /* no need for specific finalizer; we use `ftc_node_done' directly */ + + FT_CALLBACK_DEF( void ) + ftc_cmap_node_free( FTC_Node ftcnode, + FTC_Cache cache ) + { + FTC_CMapNode node = (FTC_CMapNode)ftcnode; + FT_Memory memory = cache->memory; + + + FT_FREE( node ); + } + + + /* initialize a new cmap node */ + FT_CALLBACK_DEF( FT_Error ) + ftc_cmap_node_new( FTC_Node *ftcanode, + FT_Pointer ftcquery, + FTC_Cache cache ) + { + FTC_CMapNode *anode = (FTC_CMapNode*)ftcanode; + FTC_CMapQuery query = (FTC_CMapQuery)ftcquery; + FT_Error error; + FT_Memory memory = cache->memory; + FTC_CMapNode node; + FT_UInt nn; + + + if ( !FT_NEW( node ) ) + { + node->face_id = query->face_id; + node->cmap_index = query->cmap_index; + node->first = (query->char_code / FTC_CMAP_INDICES_MAX) * + FTC_CMAP_INDICES_MAX; + + for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ ) + node->indices[nn] = FTC_CMAP_UNKNOWN; + } + + *anode = node; + return error; + } + + + /* compute the weight of a given cmap node */ + FT_CALLBACK_DEF( FT_ULong ) + ftc_cmap_node_weight( FTC_Node cnode, + FTC_Cache cache ) + { + FT_UNUSED( cnode ); + FT_UNUSED( cache ); + + return sizeof ( *cnode ); + } + + + /* compare a cmap node to a given query */ + FT_CALLBACK_DEF( FT_Bool ) + ftc_cmap_node_compare( FTC_Node ftcnode, + FT_Pointer ftcquery, + FTC_Cache cache ) + { + FTC_CMapNode node = (FTC_CMapNode)ftcnode; + FTC_CMapQuery query = (FTC_CMapQuery)ftcquery; + FT_UNUSED( cache ); + + + if ( node->face_id == query->face_id && + node->cmap_index == query->cmap_index ) + { + FT_UInt32 offset = (FT_UInt32)( query->char_code - node->first ); + + + return FT_BOOL( offset < FTC_CMAP_INDICES_MAX ); + } + + return 0; + } + + + FT_CALLBACK_DEF( FT_Bool ) + ftc_cmap_node_remove_faceid( FTC_Node ftcnode, + FT_Pointer ftcface_id, + FTC_Cache cache ) + { + FTC_CMapNode node = (FTC_CMapNode)ftcnode; + FTC_FaceID face_id = (FTC_FaceID)ftcface_id; + FT_UNUSED( cache ); + + return FT_BOOL( node->face_id == face_id ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** GLYPH IMAGE CACHE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_CALLBACK_TABLE_DEF + const FTC_CacheClassRec ftc_cmap_cache_class = + { + ftc_cmap_node_new, + ftc_cmap_node_weight, + ftc_cmap_node_compare, + ftc_cmap_node_remove_faceid, + ftc_cmap_node_free, + + sizeof ( FTC_CacheRec ), + ftc_cache_init, + ftc_cache_done, + }; + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_CMapCache_New( FTC_Manager manager, + FTC_CMapCache *acache ) + { + return FTC_Manager_RegisterCache( manager, + &ftc_cmap_cache_class, + FTC_CACHE_P( acache ) ); + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_UInt ) + FTC_CMapCache_Lookup( FTC_CMapCache cmap_cache, + FTC_FaceID face_id, + FT_Int cmap_index, + FT_UInt32 char_code ) + { + FTC_Cache cache = FTC_CACHE( cmap_cache ); + FTC_CMapQueryRec query; + FTC_CMapNode node; + FT_Error error; + FT_UInt gindex = 0; + FT_UInt32 hash; + + + if ( !cache ) + { + FT_ERROR(( "FTC_CMapCache_Lookup: bad arguments, returning 0!\n" )); + return 0; + } + + query.face_id = face_id; + query.cmap_index = (FT_UInt)cmap_index; + query.char_code = char_code; + + hash = FTC_CMAP_HASH( face_id, cmap_index, char_code ); + +#if 1 + FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query, + node, error ); +#else + error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node ); +#endif + if ( error ) + goto Exit; + + FT_ASSERT( (FT_UInt)( char_code - node->first ) < FTC_CMAP_INDICES_MAX ); + + gindex = node->indices[char_code - node->first]; + if ( gindex == FTC_CMAP_UNKNOWN ) + { + FT_Face face; + + + gindex = 0; + + error = FTC_Manager_LookupFace( cache->manager, node->face_id, &face ); + if ( error ) + goto Exit; + + if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps ) + { + FT_CharMap old, cmap = NULL; + + + old = face->charmap; + cmap = face->charmaps[cmap_index]; + + if ( old != cmap ) + FT_Set_Charmap( face, cmap ); + + gindex = FT_Get_Char_Index( face, char_code ); + + if ( old != cmap ) + FT_Set_Charmap( face, old ); + } + + node->indices[char_code - node->first] = gindex; + } + + Exit: + return gindex; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcerror.h b/Utilities/vtkfreetype/src/cache/ftcerror.h new file mode 100644 index 0000000..5998d42 --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcerror.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* ftcerror.h */ +/* */ +/* Caching sub-system error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the caching sub-system error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __FTCERROR_H__ +#define __FTCERROR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX FTC_Err_ +#define FT_ERR_BASE FT_Mod_Err_Cache + +#include FT_ERRORS_H + +#endif /* __FTCERROR_H__ */ + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcglyph.c b/Utilities/vtkfreetype/src/cache/ftcglyph.c new file mode 100644 index 0000000..d524c9c --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcglyph.c @@ -0,0 +1,199 @@ +/***************************************************************************/ +/* */ +/* ftcglyph.c */ +/* */ +/* FreeType Glyph Image (FT_Glyph) cache (body). */ +/* */ +/* Copyright 2000-2001, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_GLYPH_H +#include FT_ERRORS_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H + +#include "ftccback.h" +#include "ftcerror.h" + + + /* create a new chunk node, setting its cache index and ref count */ + FT_EXPORT_DEF( void ) + FTC_GNode_Init( FTC_GNode gnode, + FT_UInt gindex, + FTC_Family family ) + { + gnode->family = family; + gnode->gindex = gindex; + family->num_nodes++; + } + + + FT_EXPORT_DEF( void ) + FTC_GNode_UnselectFamily( FTC_GNode gnode, + FTC_Cache cache ) + { + FTC_Family family = gnode->family; + + + gnode->family = NULL; + if ( family && --family->num_nodes <= 0 ) + FTC_FAMILY_FREE( family, cache ); + } + + + FT_EXPORT_DEF( void ) + FTC_GNode_Done( FTC_GNode gnode, + FTC_Cache cache ) + { + /* finalize the node */ + gnode->gindex = 0; + + FTC_GNode_UnselectFamily( gnode, cache ); + } + + + FT_LOCAL_DEF( FT_Bool ) + ftc_gnode_compare( FTC_Node ftcgnode, + FT_Pointer ftcgquery, + FTC_Cache cache ) + { + FTC_GNode gnode = (FTC_GNode)ftcgnode; + FTC_GQuery gquery = (FTC_GQuery)ftcgquery; + FT_UNUSED( cache ); + + + return FT_BOOL( gnode->family == gquery->family && + gnode->gindex == gquery->gindex ); + } + + + FT_EXPORT_DEF( FT_Bool ) + FTC_GNode_Compare( FTC_GNode gnode, + FTC_GQuery gquery ) + { + return ftc_gnode_compare( FTC_NODE( gnode ), gquery, NULL ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CHUNK SETS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_EXPORT_DEF( void ) + FTC_Family_Init( FTC_Family family, + FTC_Cache cache ) + { + FTC_GCacheClass clazz = FTC_CACHE__GCACHE_CLASS( cache ); + + + family->clazz = clazz->family_class; + family->num_nodes = 0; + family->cache = cache; + } + + + FT_LOCAL_DEF( FT_Error ) + ftc_gcache_init( FTC_Cache ftccache ) + { + FTC_GCache cache = (FTC_GCache)ftccache; + FT_Error error; + + + error = FTC_Cache_Init( FTC_CACHE( cache ) ); + if ( !error ) + { + FTC_GCacheClass clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class; + + FTC_MruList_Init( &cache->families, + clazz->family_class, + 0, /* no maximum here! */ + cache, + FTC_CACHE( cache )->memory ); + } + + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FTC_GCache_Init( FTC_GCache cache ) + { + return ftc_gcache_init( FTC_CACHE( cache ) ); + } + + + FT_LOCAL_DEF( void ) + ftc_gcache_done( FTC_Cache ftccache ) + { + FTC_GCache cache = (FTC_GCache)ftccache; + + + FTC_Cache_Done( (FTC_Cache)cache ); + FTC_MruList_Done( &cache->families ); + } + + + FT_EXPORT_DEF( void ) + FTC_GCache_Done( FTC_GCache cache ) + { + ftc_gcache_done( FTC_CACHE( cache ) ); + } + + + FT_EXPORT_DEF( FT_Error ) + FTC_GCache_New( FTC_Manager manager, + FTC_GCacheClass clazz, + FTC_GCache *acache ) + { + return FTC_Manager_RegisterCache( manager, (FTC_CacheClass)clazz, + (FTC_Cache*)acache ); + } + + + FT_EXPORT_DEF( FT_Error ) + FTC_GCache_Lookup( FTC_GCache cache, + FT_UInt32 hash, + FT_UInt gindex, + FTC_GQuery query, + FTC_Node *anode ) + { + FT_Error error; + + + query->gindex = gindex; + + FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error ); + if ( !error ) + { + FTC_Family family = query->family; + + + /* prevent the family from being destroyed too early when an */ + /* out-of-memory condition occurs during glyph node initialization. */ + family->num_nodes++; + + error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode ); + + if ( --family->num_nodes <= 0 ) + FTC_FAMILY_FREE( family, cache ); + } + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcimage.c b/Utilities/vtkfreetype/src/cache/ftcimage.c new file mode 100644 index 0000000..508ed6c --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcimage.c @@ -0,0 +1,154 @@ +/***************************************************************************/ +/* */ +/* ftcimage.c */ +/* */ +/* FreeType Image cache (body). */ +/* */ +/* Copyright 2000-2001, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_IMAGE_H +#include FT_INTERNAL_MEMORY_H + +#include "ftccback.h" +#include "ftcerror.h" + + + /* finalize a given glyph image node */ + FT_LOCAL_DEF( void ) + ftc_inode_free( FTC_Node ftcinode, + FTC_Cache cache ) + { + FTC_INode inode = (FTC_INode)ftcinode; + FT_Memory memory = cache->memory; + + + if ( inode->glyph ) + { + FT_Done_Glyph( inode->glyph ); + inode->glyph = NULL; + } + + FTC_GNode_Done( FTC_GNODE( inode ), cache ); + FT_FREE( inode ); + } + + + FT_EXPORT_DEF( void ) + FTC_INode_Free( FTC_INode inode, + FTC_Cache cache ) + { + ftc_inode_free( FTC_NODE( inode ), cache ); + } + + + /* initialize a new glyph image node */ + FT_EXPORT_DEF( FT_Error ) + FTC_INode_New( FTC_INode *pinode, + FTC_GQuery gquery, + FTC_Cache cache ) + { + FT_Memory memory = cache->memory; + FT_Error error; + FTC_INode inode; + + + if ( !FT_NEW( inode ) ) + { + FTC_GNode gnode = FTC_GNODE( inode ); + FTC_Family family = gquery->family; + FT_UInt gindex = gquery->gindex; + FTC_IFamilyClass clazz = FTC_CACHE__IFAMILY_CLASS( cache ); + + + /* initialize its inner fields */ + FTC_GNode_Init( gnode, gindex, family ); + + /* we will now load the glyph image */ + error = clazz->family_load_glyph( family, gindex, cache, + &inode->glyph ); + } + + *pinode = inode; + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + ftc_inode_new( FTC_Node *ftcpinode, + FT_Pointer ftcgquery, + FTC_Cache cache ) + { + FTC_INode *pinode = (FTC_INode*)ftcpinode; + FTC_GQuery gquery = (FTC_GQuery)ftcgquery; + + + return FTC_INode_New( pinode, gquery, cache ); + } + + + FT_LOCAL_DEF( FT_ULong ) + ftc_inode_weight( FTC_Node ftcinode, + FTC_Cache ftccache ) + { + FTC_INode inode = (FTC_INode)ftcinode; + FT_ULong size = 0; + FT_Glyph glyph = inode->glyph; + + FT_UNUSED( ftccache ); + + + switch ( glyph->format ) + { + case FT_GLYPH_FORMAT_BITMAP: + { + FT_BitmapGlyph bitg; + + + bitg = (FT_BitmapGlyph)glyph; + size = bitg->bitmap.rows * labs( bitg->bitmap.pitch ) + + sizeof ( *bitg ); + } + break; + + case FT_GLYPH_FORMAT_OUTLINE: + { + FT_OutlineGlyph outg; + + + outg = (FT_OutlineGlyph)glyph; + size = outg->outline.n_points * + ( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) + + outg->outline.n_contours * sizeof ( FT_Short ) + + sizeof ( *outg ); + } + break; + + default: + ; + } + + size += sizeof ( *inode ); + return size; + } + + + FT_EXPORT_DEF( FT_ULong ) + FTC_INode_Weight( FTC_INode inode ) + { + return ftc_inode_weight( FTC_NODE( inode ), NULL ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcmanag.c b/Utilities/vtkfreetype/src/cache/ftcmanag.c new file mode 100644 index 0000000..3935f72 --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcmanag.c @@ -0,0 +1,680 @@ +/***************************************************************************/ +/* */ +/* ftcmanag.c */ +/* */ +/* FreeType Cache Manager (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_MANAGER_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include FT_SIZES_H + +#include "ftcerror.h" + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_cache + +#define FTC_LRU_GET_MANAGER( lru ) ( (FTC_Manager)(lru)->user_data ) + + + static FT_Error + ftc_scaler_lookup_size( FTC_Manager manager, + FTC_Scaler scaler, + FT_Size *asize ) + { + FT_Face face; + FT_Size size = NULL; + FT_Error error; + + + error = FTC_Manager_LookupFace( manager, scaler->face_id, &face ); + if ( error ) + goto Exit; + + error = FT_New_Size( face, &size ); + if ( error ) + goto Exit; + + FT_Activate_Size( size ); + + if ( scaler->pixel ) + error = FT_Set_Pixel_Sizes( face, scaler->width, scaler->height ); + else + error = FT_Set_Char_Size( face, scaler->width, scaler->height, + scaler->x_res, scaler->y_res ); + if ( error ) + { + FT_Done_Size( size ); + size = NULL; + } + + Exit: + *asize = size; + return error; + } + + + typedef struct FTC_SizeNodeRec_ + { + FTC_MruNodeRec node; + FT_Size size; + FTC_ScalerRec scaler; + + } FTC_SizeNodeRec, *FTC_SizeNode; + + + FT_CALLBACK_DEF( void ) + ftc_size_node_done( FTC_MruNode ftcnode, + FT_Pointer data ) + { + FTC_SizeNode node = (FTC_SizeNode)ftcnode; + FT_Size size = node->size; + FT_UNUSED( data ); + + + if ( size ) + FT_Done_Size( size ); + } + + + FT_CALLBACK_DEF( FT_Bool ) + ftc_size_node_compare( FTC_MruNode ftcnode, + FT_Pointer ftcscaler ) + { + FTC_SizeNode node = (FTC_SizeNode)ftcnode; + FTC_Scaler scaler = (FTC_Scaler)ftcscaler; + FTC_Scaler scaler0 = &node->scaler; + + + if ( FTC_SCALER_COMPARE( scaler0, scaler ) ) + { + FT_Activate_Size( node->size ); + return 1; + } + return 0; + } + + + FT_CALLBACK_DEF( FT_Error ) + ftc_size_node_init( FTC_MruNode ftcnode, + FT_Pointer ftcscaler, + FT_Pointer ftcmanager ) + { + FTC_SizeNode node = (FTC_SizeNode)ftcnode; + FTC_Scaler scaler = (FTC_Scaler)ftcscaler; + FTC_Manager manager = (FTC_Manager)ftcmanager; + + + node->scaler = scaler[0]; + + return ftc_scaler_lookup_size( manager, scaler, &node->size ); + } + + + FT_CALLBACK_DEF( FT_Error ) + ftc_size_node_reset( FTC_MruNode ftcnode, + FT_Pointer ftcscaler, + FT_Pointer ftcmanager ) + { + FTC_SizeNode node = (FTC_SizeNode)ftcnode; + FTC_Scaler scaler = (FTC_Scaler)ftcscaler; + FTC_Manager manager = (FTC_Manager)ftcmanager; + + + FT_Done_Size( node->size ); + + node->scaler = scaler[0]; + + return ftc_scaler_lookup_size( manager, scaler, &node->size ); + } + + + FT_CALLBACK_TABLE_DEF + const FTC_MruListClassRec ftc_size_list_class = + { + sizeof ( FTC_SizeNodeRec ), + ftc_size_node_compare, + ftc_size_node_init, + ftc_size_node_reset, + ftc_size_node_done + }; + + + /* helper function used by ftc_face_node_done */ + static FT_Bool + ftc_size_node_compare_faceid( FTC_MruNode ftcnode, + FT_Pointer ftcface_id ) + { + FTC_SizeNode node = (FTC_SizeNode)ftcnode; + FTC_FaceID face_id = (FTC_FaceID)ftcface_id; + + + return node->scaler.face_id == face_id; + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_Manager_LookupSize( FTC_Manager manager, + FTC_Scaler scaler, + FT_Size *asize ) + { + FT_Error error; + FTC_SizeNode node; + + + if ( asize == NULL ) + return FTC_Err_Bad_Argument; + + *asize = NULL; + + if ( !manager ) + return FTC_Err_Invalid_Cache_Handle; + +#ifdef FTC_INLINE + + FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare, + node, error ); + +#else + error = FTC_MruList_Lookup( &manager->sizes, scaler, (FTC_MruNode*)&node ); +#endif + + if ( !error ) + *asize = node->size; + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FACE MRU IMPLEMENTATION *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct FTC_FaceNodeRec_ + { + FTC_MruNodeRec node; + FTC_FaceID face_id; + FT_Face face; + + } FTC_FaceNodeRec, *FTC_FaceNode; + + + FT_CALLBACK_DEF( FT_Error ) + ftc_face_node_init( FTC_MruNode ftcnode, + FT_Pointer ftcface_id, + FT_Pointer ftcmanager ) + { + FTC_FaceNode node = (FTC_FaceNode)ftcnode; + FTC_FaceID face_id = (FTC_FaceID)ftcface_id; + FTC_Manager manager = (FTC_Manager)ftcmanager; + FT_Error error; + + + node->face_id = face_id; + + error = manager->request_face( face_id, + manager->library, + manager->request_data, + &node->face ); + if ( !error ) + { + /* destroy initial size object; it will be re-created later */ + if ( node->face->size ) + FT_Done_Size( node->face->size ); + } + + return error; + } + + + FT_CALLBACK_DEF( void ) + ftc_face_node_done( FTC_MruNode ftcnode, + FT_Pointer ftcmanager ) + { + FTC_FaceNode node = (FTC_FaceNode)ftcnode; + FTC_Manager manager = (FTC_Manager)ftcmanager; + + + /* we must begin by removing all scalers for the target face */ + /* from the manager's list */ + FTC_MruList_RemoveSelection( &manager->sizes, + ftc_size_node_compare_faceid, + node->face_id ); + + /* all right, we can discard the face now */ + FT_Done_Face( node->face ); + node->face = NULL; + node->face_id = NULL; + } + + + FT_CALLBACK_DEF( FT_Bool ) + ftc_face_node_compare( FTC_MruNode ftcnode, + FT_Pointer ftcface_id ) + { + FTC_FaceNode node = (FTC_FaceNode)ftcnode; + FTC_FaceID face_id = (FTC_FaceID)ftcface_id; + + + return FT_BOOL( node->face_id == face_id ); + } + + + FT_CALLBACK_TABLE_DEF + const FTC_MruListClassRec ftc_face_list_class = + { + sizeof ( FTC_FaceNodeRec), + + ftc_face_node_compare, + ftc_face_node_init, + 0, /* FTC_MruNode_ResetFunc */ + ftc_face_node_done + }; + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_Manager_LookupFace( FTC_Manager manager, + FTC_FaceID face_id, + FT_Face *aface ) + { + FT_Error error; + FTC_FaceNode node; + + + if ( aface == NULL ) + return FTC_Err_Bad_Argument; + + *aface = NULL; + + if ( !manager ) + return FTC_Err_Invalid_Cache_Handle; + + /* we break encapsulation for the sake of speed */ +#ifdef FTC_INLINE + + FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare, + node, error ); + +#else + error = FTC_MruList_Lookup( &manager->faces, face_id, (FTC_MruNode*)&node ); +#endif + + if ( !error ) + *aface = node->face; + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CACHE MANAGER ROUTINES *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_Manager_New( FT_Library library, + FT_UInt max_faces, + FT_UInt max_sizes, + FT_ULong max_bytes, + FTC_Face_Requester requester, + FT_Pointer req_data, + FTC_Manager *amanager ) + { + FT_Error error; + FT_Memory memory; + FTC_Manager manager = 0; + + + if ( !library ) + return FTC_Err_Invalid_Library_Handle; + + memory = library->memory; + + if ( FT_NEW( manager ) ) + goto Exit; + + if ( max_faces == 0 ) + max_faces = FTC_MAX_FACES_DEFAULT; + + if ( max_sizes == 0 ) + max_sizes = FTC_MAX_SIZES_DEFAULT; + + if ( max_bytes == 0 ) + max_bytes = FTC_MAX_BYTES_DEFAULT; + + manager->library = library; + manager->memory = memory; + manager->max_weight = max_bytes; + + manager->request_face = requester; + manager->request_data = req_data; + + FTC_MruList_Init( &manager->faces, + &ftc_face_list_class, + max_faces, + manager, + memory ); + + FTC_MruList_Init( &manager->sizes, + &ftc_size_list_class, + max_sizes, + manager, + memory ); + + *amanager = manager; + + Exit: + return error; + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( void ) + FTC_Manager_Done( FTC_Manager manager ) + { + FT_Memory memory; + FT_UInt idx; + + + if ( !manager || !manager->library ) + return; + + memory = manager->memory; + + /* now discard all caches */ + for (idx = manager->num_caches; idx-- > 0; ) + { + FTC_Cache cache = manager->caches[idx]; + + + if ( cache ) + { + cache->clazz.cache_done( cache ); + FT_FREE( cache ); + manager->caches[idx] = NULL; + } + } + manager->num_caches = 0; + + /* discard faces and sizes */ + FTC_MruList_Done( &manager->sizes ); + FTC_MruList_Done( &manager->faces ); + + manager->library = NULL; + manager->memory = NULL; + + FT_FREE( manager ); + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( void ) + FTC_Manager_Reset( FTC_Manager manager ) + { + if ( manager ) + { + FTC_MruList_Reset( &manager->sizes ); + FTC_MruList_Reset( &manager->faces ); + } + /* XXX: FIXME: flush the caches? */ + } + + +#ifdef FT_DEBUG_ERROR + + FT_EXPORT_DEF( void ) + FTC_Manager_Check( FTC_Manager manager ) + { + FTC_Node node, first; + + + first = manager->nodes_list; + + /* check node weights */ + if ( first ) + { + FT_ULong weight = 0; + + + node = first; + + do + { + FTC_Cache cache = manager->caches[node->cache_index]; + + + if ( (FT_UInt)node->cache_index >= manager->num_caches ) + FT_ERROR(( "FTC_Manager_Check: invalid node (cache index = %ld\n", + node->cache_index )); + else + weight += cache->clazz.node_weight( node, cache ); + + node = FTC_NODE__NEXT( node ); + + } while ( node != first ); + + if ( weight != manager->cur_weight ) + FT_ERROR(( "FTC_Manager_Check: invalid weight %ld instead of %ld\n", + manager->cur_weight, weight )); + } + + /* check circular list */ + if ( first ) + { + FT_UFast count = 0; + + + node = first; + do + { + count++; + node = FTC_NODE__NEXT( node ); + + } while ( node != first ); + + if ( count != manager->num_nodes ) + FT_ERROR(( + "FTC_Manager_Check: invalid cache node count %d instead of %d\n", + manager->num_nodes, count )); + } + } + +#endif /* FT_DEBUG_ERROR */ + + + /* `Compress' the manager's data, i.e., get rid of old cache nodes */ + /* that are not referenced anymore in order to limit the total */ + /* memory used by the cache. */ + + /* documentation is in ftcmanag.h */ + + FT_EXPORT_DEF( void ) + FTC_Manager_Compress( FTC_Manager manager ) + { + FTC_Node node, first; + + + if ( !manager ) + return; + + first = manager->nodes_list; + +#ifdef FT_DEBUG_ERROR + FTC_Manager_Check( manager ); + + FT_ERROR(( "compressing, weight = %ld, max = %ld, nodes = %d\n", + manager->cur_weight, manager->max_weight, + manager->num_nodes )); +#endif + + if ( manager->cur_weight < manager->max_weight || first == NULL ) + return; + + /* go to last node -- it's a circular list */ + node = FTC_NODE__PREV( first ); + do + { + FTC_Node prev; + + + prev = ( node == first ) ? NULL : FTC_NODE__PREV( node ); + + if ( node->ref_count <= 0 ) + ftc_node_destroy( node, manager ); + + node = prev; + + } while ( node && manager->cur_weight > manager->max_weight ); + } + + + /* documentation is in ftcmanag.h */ + + FT_EXPORT_DEF( FT_Error ) + FTC_Manager_RegisterCache( FTC_Manager manager, + FTC_CacheClass clazz, + FTC_Cache *acache ) + { + FT_Error error = FTC_Err_Invalid_Argument; + FTC_Cache cache = NULL; + + + if ( manager && clazz && acache ) + { + FT_Memory memory = manager->memory; + + + if ( manager->num_caches >= FTC_MAX_CACHES ) + { + error = FTC_Err_Too_Many_Caches; + FT_ERROR(( "%s: too many registered caches\n", + "FTC_Manager_Register_Cache" )); + goto Exit; + } + + if ( !FT_ALLOC( cache, clazz->cache_size ) ) + { + cache->manager = manager; + cache->memory = memory; + cache->clazz = clazz[0]; + cache->org_class = clazz; + + /* THIS IS VERY IMPORTANT! IT WILL WRETCH THE MANAGER */ + /* IF IT IS NOT SET CORRECTLY */ + cache->index = manager->num_caches; + + error = clazz->cache_init( cache ); + if ( error ) + { + clazz->cache_done( cache ); + FT_FREE( cache ); + goto Exit; + } + + manager->caches[manager->num_caches++] = cache; + } + } + + Exit: + *acache = cache; + return error; + } + + + FT_EXPORT_DEF( FT_UInt ) + FTC_Manager_FlushN( FTC_Manager manager, + FT_UInt count ) + { + FTC_Node first = manager->nodes_list; + FTC_Node node; + FT_UInt result; + + + /* try to remove `count' nodes from the list */ + if ( first == NULL ) /* empty list! */ + return 0; + + /* go to last node - it's a circular list */ + node = FTC_NODE__PREV(first); + for ( result = 0; result < count; ) + { + FTC_Node prev = FTC_NODE__PREV( node ); + + + /* don't touch locked nodes */ + if ( node->ref_count <= 0 ) + { + ftc_node_destroy( node, manager ); + result++; + } + + if ( node == first ) + break; + + node = prev; + } + return result; + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( void ) + FTC_Manager_RemoveFaceID( FTC_Manager manager, + FTC_FaceID face_id ) + { + FT_UInt nn; + + /* this will remove all FTC_SizeNode that correspond to + * the face_id as well + */ + FTC_MruList_RemoveSelection( &manager->faces, NULL, face_id ); + + for ( nn = 0; nn < manager->num_caches; nn++ ) + FTC_Cache_RemoveFaceID( manager->caches[nn], face_id ); + } + + + /* documentation is in ftcache.h */ + + FT_EXPORT_DEF( void ) + FTC_Node_Unref( FTC_Node node, + FTC_Manager manager ) + { + if ( node && (FT_UInt)node->cache_index < manager->num_caches ) + node->ref_count--; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcmru.c b/Utilities/vtkfreetype/src/cache/ftcmru.c new file mode 100644 index 0000000..d4f733a --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcmru.c @@ -0,0 +1,355 @@ +/***************************************************************************/ +/* */ +/* ftcmru.c */ +/* */ +/* FreeType MRU support (body). */ +/* */ +/* Copyright 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_MRU_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H + +#include "ftcerror.h" + + + FT_EXPORT_DEF( void ) + FTC_MruNode_Prepend( FTC_MruNode *plist, + FTC_MruNode node ) + { + FTC_MruNode first = *plist; + + + if ( first ) + { + FTC_MruNode last = first->prev; + + +#ifdef FT_DEBUG_ERROR + { + FTC_MruNode cnode = first; + + + do + { + if ( cnode == node ) + { + fprintf( stderr, "FTC_MruNode_Prepend: invalid action!\n" ); + exit( 2 ); + } + cnode = cnode->next; + + } while ( cnode != first ); + } +#endif + + first->prev = node; + last->next = node; + node->next = first; + node->prev = last; + } + else + { + node->next = node; + node->prev = node; + } + *plist = node; + } + + + FT_EXPORT_DEF( void ) + FTC_MruNode_Up( FTC_MruNode *plist, + FTC_MruNode node ) + { + FTC_MruNode first = *plist; + + + FT_ASSERT( first != NULL ); + + if ( first != node ) + { + FTC_MruNode prev, next, last; + + +#ifdef FT_DEBUG_ERROR + { + FTC_MruNode cnode = first; + do + { + if ( cnode == node ) + goto Ok; + cnode = cnode->next; + + } while ( cnode != first ); + + fprintf( stderr, "FTC_MruNode_Up: invalid action!\n" ); + exit( 2 ); + Ok: + } +#endif + prev = node->prev; + next = node->next; + + prev->next = next; + next->prev = prev; + + last = first->prev; + + last->next = node; + first->prev = node; + + node->next = first; + node->prev = last; + + *plist = node; + } + } + + + FT_EXPORT_DEF( void ) + FTC_MruNode_Remove( FTC_MruNode *plist, + FTC_MruNode node ) + { + FTC_MruNode first = *plist; + FTC_MruNode prev, next; + + + FT_ASSERT( first != NULL ); + +#ifdef FT_DEBUG_ERROR + { + FTC_MruNode cnode = first; + + + do + { + if ( cnode == node ) + goto Ok; + cnode = cnode->next; + + } while ( cnode != first ); + + fprintf( stderr, "FTC_MruNode_Remove: invalid action!\n" ); + exit( 2 ); + Ok: + } +#endif + + prev = node->prev; + next = node->next; + + prev->next = next; + next->prev = prev; + + if ( node == next ) + { + FT_ASSERT( first == node ); + FT_ASSERT( prev == node ); + + *plist = NULL; + } + else if ( node == first ) + *plist = next; + } + + + FT_EXPORT_DEF( void ) + FTC_MruList_Init( FTC_MruList list, + FTC_MruListClass clazz, + FT_UInt max_nodes, + FT_Pointer data, + FT_Memory memory ) + { + list->num_nodes = 0; + list->max_nodes = max_nodes; + list->nodes = NULL; + list->clazz = *clazz; + list->data = data; + list->memory = memory; + } + + + FT_EXPORT( void ) + FTC_MruList_Reset( FTC_MruList list ) + { + while ( list->nodes ) + FTC_MruList_Remove( list, list->nodes ); + + FT_ASSERT( list->num_nodes == 0 ); + } + + + FT_EXPORT( void ) + FTC_MruList_Done( FTC_MruList list ) + { + FTC_MruList_Reset( list ); + } + + + FT_EXPORT_DEF( FTC_MruNode ) + FTC_MruList_Find( FTC_MruList list, + FT_Pointer key ) + { + FTC_MruNode_CompareFunc compare = list->clazz.node_compare; + FTC_MruNode first, node; + + + first = list->nodes; + node = NULL; + + if ( first ) + { + node = first; + do + { + if ( compare( node, key ) ) + { + if ( node != first ) + FTC_MruNode_Up( &list->nodes, node ); + + return node; + } + + node = node->next; + + } while ( node != first); + } + + return NULL; + } + + + FT_EXPORT_DEF( FT_Error ) + FTC_MruList_New( FTC_MruList list, + FT_Pointer key, + FTC_MruNode *anode ) + { + FT_Error error; + FTC_MruNode node; + FT_Memory memory = list->memory; + + + if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 ) + { + node = list->nodes->prev; + + FT_ASSERT( node ); + + if ( list->clazz.node_reset ) + { + FTC_MruNode_Up( &list->nodes, node ); + + error = list->clazz.node_reset( node, key, list->data ); + if ( !error ) + goto Exit; + } + + FTC_MruNode_Remove( &list->nodes, node ); + list->num_nodes--; + + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); + } + else if ( FT_ALLOC( node, list->clazz.node_size ) ) + goto Exit; + + error = list->clazz.node_init( node, key, list->data ); + if ( error ) + goto Fail; + + FTC_MruNode_Prepend( &list->nodes, node ); + list->num_nodes++; + + Exit: + *anode = node; + return error; + + Fail: + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); + + FT_FREE( node ); + goto Exit; + } + + + FT_EXPORT( FT_Error ) + FTC_MruList_Lookup( FTC_MruList list, + FT_Pointer key, + FTC_MruNode *anode ) + { + FTC_MruNode node; + + + node = FTC_MruList_Find( list, key ); + if ( node == NULL ) + return FTC_MruList_New( list, key, anode ); + + *anode = node; + return 0; + } + + + FT_EXPORT_DEF( void ) + FTC_MruList_Remove( FTC_MruList list, + FTC_MruNode node ) + { + FTC_MruNode_Remove( &list->nodes, node ); + list->num_nodes--; + + { + FT_Memory memory = list->memory; + + + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); + + FT_FREE( node ); + } + } + + + FT_EXPORT_DEF( void ) + FTC_MruList_RemoveSelection( FTC_MruList list, + FTC_MruNode_CompareFunc selection, + FT_Pointer key ) + { + FTC_MruNode first, node, next; + + + first = list->nodes; + while ( first && ( selection == NULL || selection( first, key ) ) ) + { + FTC_MruList_Remove( list, first ); + first = list->nodes; + } + + if ( first ) + { + node = first->next; + while ( node != first ) + { + next = node->next; + + if ( selection( node, key ) ) + FTC_MruList_Remove( list, node ); + + node = next; + } + } + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cache/ftcsbits.c b/Utilities/vtkfreetype/src/cache/ftcsbits.c new file mode 100644 index 0000000..7159971 --- /dev/null +++ b/Utilities/vtkfreetype/src/cache/ftcsbits.c @@ -0,0 +1,344 @@ +/***************************************************************************/ +/* */ +/* ftcsbits.c */ +/* */ +/* FreeType sbits manager (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_CACHE_H +#include FT_CACHE_INTERNAL_SBITS_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include FT_ERRORS_H + +#include "ftccback.h" +#include "ftcerror.h" + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** SBIT CACHE NODES *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + static FT_Error + ftc_sbit_copy_bitmap( FTC_SBit sbit, + FT_Bitmap* bitmap, + FT_Memory memory ) + { + FT_Error error; + FT_Int pitch = bitmap->pitch; + FT_ULong size; + + + if ( pitch < 0 ) + pitch = -pitch; + + size = (FT_ULong)( pitch * bitmap->rows ); + + if ( !FT_ALLOC( sbit->buffer, size ) ) + FT_MEM_COPY( sbit->buffer, bitmap->buffer, size ); + + return error; + } + + + FT_LOCAL_DEF( void ) + ftc_snode_free( FTC_Node ftcsnode, + FTC_Cache cache ) + { + FTC_SNode snode = (FTC_SNode)ftcsnode; + FTC_SBit sbit = snode->sbits; + FT_UInt count = snode->count; + FT_Memory memory = cache->memory; + + + for ( ; count > 0; sbit++, count-- ) + FT_FREE( sbit->buffer ); + + FTC_GNode_Done( FTC_GNODE( snode ), cache ); + + FT_FREE( snode ); + } + + + FT_EXPORT_DEF( void ) + FTC_SNode_Free( FTC_SNode snode, + FTC_Cache cache ) + { + ftc_snode_free( FTC_NODE( snode ), cache ); + } + + + static FT_Error + ftc_snode_load( FTC_SNode snode, + FTC_Manager manager, + FT_UInt gindex, + FT_ULong *asize ) + { + FT_Error error; + FTC_GNode gnode = FTC_GNODE( snode ); + FTC_Family family = gnode->family; + FT_Memory memory = manager->memory; + FT_Face face; + FTC_SBit sbit; + FTC_SFamilyClass clazz; + + + if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count ) + { + FT_ERROR(( "ftc_snode_load: invalid glyph index" )); + return FTC_Err_Invalid_Argument; + } + + sbit = snode->sbits + ( gindex - gnode->gindex ); + clazz = (FTC_SFamilyClass)family->clazz; + + sbit->buffer = 0; + + error = clazz->family_load_glyph( family, gindex, manager, &face ); + if ( error ) + goto BadGlyph; + + { + FT_Int temp; + FT_GlyphSlot slot = face->glyph; + FT_Bitmap* bitmap = &slot->bitmap; + FT_Int xadvance, yadvance; + + + if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) + { + FT_ERROR(( "%s: glyph loaded didn't return a bitmap!\n", + "ftc_snode_load" )); + goto BadGlyph; + } + + /* Check that our values fit into 8-bit containers! */ + /* If this is not the case, our bitmap is too large */ + /* and we will leave it as `missing' with sbit.buffer = 0 */ + +#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d ) +#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d ) + + /* horizontal advance in pixels */ + xadvance = ( slot->advance.x + 32 ) >> 6; + yadvance = ( slot->advance.y + 32 ) >> 6; + + if ( !CHECK_BYTE( bitmap->rows ) || + !CHECK_BYTE( bitmap->width ) || + !CHECK_CHAR( bitmap->pitch ) || + !CHECK_CHAR( slot->bitmap_left ) || + !CHECK_CHAR( slot->bitmap_top ) || + !CHECK_CHAR( xadvance ) || + !CHECK_CHAR( yadvance ) ) + goto BadGlyph; + + sbit->width = (FT_Byte)bitmap->width; + sbit->height = (FT_Byte)bitmap->rows; + sbit->pitch = (FT_Char)bitmap->pitch; + sbit->left = (FT_Char)slot->bitmap_left; + sbit->top = (FT_Char)slot->bitmap_top; + sbit->xadvance = (FT_Char)xadvance; + sbit->yadvance = (FT_Char)yadvance; + sbit->format = (FT_Byte)bitmap->pixel_mode; + sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1); + + /* copy the bitmap into a new buffer -- ignore error */ + error = ftc_sbit_copy_bitmap( sbit, bitmap, memory ); + + /* now, compute size */ + if ( asize ) + *asize = FT_ABS( sbit->pitch ) * sbit->height; + + } /* glyph loading successful */ + + /* ignore the errors that might have occurred -- */ + /* we mark unloaded glyphs with `sbit.buffer == 0' */ + /* and `width == 255', `height == 0' */ + /* */ + if ( error && error != FTC_Err_Out_Of_Memory ) + { + BadGlyph: + sbit->width = 255; + sbit->height = 0; + sbit->buffer = NULL; + error = 0; + if ( asize ) + *asize = 0; + } + + return error; + } + + + FT_EXPORT_DEF( FT_Error ) + FTC_SNode_New( FTC_SNode *psnode, + FTC_GQuery gquery, + FTC_Cache cache ) + { + FT_Memory memory = cache->memory; + FT_Error error; + FTC_SNode snode = NULL; + FT_UInt gindex = gquery->gindex; + FTC_Family family = gquery->family; + + FTC_SFamilyClass clazz = FTC_CACHE__SFAMILY_CLASS( cache ); + FT_UInt total; + + + total = clazz->family_get_count( family, cache->manager ); + if ( total == 0 || gindex >= total ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + if ( !FT_NEW( snode ) ) + { + FT_UInt count, start; + + + start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE ); + count = total - start; + if ( count > FTC_SBIT_ITEMS_PER_NODE ) + count = FTC_SBIT_ITEMS_PER_NODE; + + FTC_GNode_Init( FTC_GNODE( snode ), start, family ); + + snode->count = count; + + error = ftc_snode_load( snode, + cache->manager, + gindex, + NULL ); + if ( error ) + { + FTC_SNode_Free( snode, cache ); + snode = NULL; + } + } + + Exit: + *psnode = snode; + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + ftc_snode_new( FTC_Node *ftcpsnode, + FT_Pointer ftcgquery, + FTC_Cache cache ) + { + FTC_SNode *psnode = (FTC_SNode*)ftcpsnode; + FTC_GQuery gquery = (FTC_GQuery)ftcgquery; + + + return FTC_SNode_New( psnode, gquery, cache ); + } + + + FT_LOCAL_DEF( FT_ULong ) + ftc_snode_weight( FTC_Node ftcsnode, + FTC_Cache cache ) + { + FTC_SNode snode = (FTC_SNode)ftcsnode; + FT_UInt count = snode->count; + FTC_SBit sbit = snode->sbits; + FT_Int pitch; + FT_ULong size; + + FT_UNUSED( cache ); + + + FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE ); + + /* the node itself */ + size = sizeof ( *snode ); + + for ( ; count > 0; count--, sbit++ ) + { + if ( sbit->buffer ) + { + pitch = sbit->pitch; + if ( pitch < 0 ) + pitch = -pitch; + + /* add the size of a given glyph image */ + size += pitch * sbit->height; + } + } + + return size; + } + + + FT_EXPORT_DEF( FT_ULong ) + FTC_SNode_Weight( FTC_SNode snode ) + { + return ftc_snode_weight( FTC_NODE( snode ), NULL ); + } + + + FT_LOCAL_DEF( FT_Bool ) + ftc_snode_compare( FTC_Node ftcsnode, + FT_Pointer ftcgquery, + FTC_Cache cache ) + { + FTC_SNode snode = (FTC_SNode)ftcsnode; + FTC_GQuery gquery = (FTC_GQuery)ftcgquery; + FTC_GNode gnode = FTC_GNODE( snode ); + FT_UInt gindex = gquery->gindex; + FT_Bool result; + + + result = FT_BOOL( gnode->family == gquery->family && + (FT_UInt)( gindex - gnode->gindex ) < snode->count ); + if ( result ) + { + /* check if we need to load the glyph bitmap now */ + FTC_SBit sbit = snode->sbits + ( gindex - gnode->gindex ); + + + if ( sbit->buffer == NULL && sbit->width != 255 ) + { + FT_ULong size; + + + if ( !ftc_snode_load( snode, cache->manager, + gindex, &size ) ) + { + cache->manager->cur_weight += size; + } + } + } + + return result; + } + + + FT_EXPORT_DEF( FT_Bool ) + FTC_SNode_Compare( FTC_SNode snode, + FTC_GQuery gquery, + FTC_Cache cache ) + { + return ftc_snode_compare( FTC_NODE( snode ), gquery, cache ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cff.c b/Utilities/vtkfreetype/src/cff/cff.c new file mode 100644 index 0000000..e6d8954 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cff.c @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* cff.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "cffdrivr.c" +#include "cffparse.c" +#include "cffload.c" +#include "cffobjs.c" +#include "cffgload.c" +#include "cffcmap.c" + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffcmap.c b/Utilities/vtkfreetype/src/cff/cffcmap.c new file mode 100644 index 0000000..82e04d2 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffcmap.c @@ -0,0 +1,326 @@ +/***************************************************************************/ +/* */ +/* cffcmap.c */ +/* */ +/* CFF character mapping table (cmap) support (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "cffcmap.h" +#include "cffload.h" + +#include "cfferrs.h" + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CFF STANDARD (AND EXPERT) ENCODING CMAPS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_CALLBACK_DEF( FT_Error ) + cff_cmap_encoding_init( CFF_CMapStd cmap ) + { + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + CFF_Font cff = (CFF_Font)face->extra.data; + CFF_Encoding encoding = &cff->encoding; + + + cmap->gids = encoding->codes; + + return 0; + } + + + FT_CALLBACK_DEF( void ) + cff_cmap_encoding_done( CFF_CMapStd cmap ) + { + cmap->gids = NULL; + } + + + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_encoding_char_index( CFF_CMapStd cmap, + FT_UInt32 char_code ) + { + FT_UInt result = 0; + + + if ( char_code < 256 ) + result = cmap->gids[char_code]; + + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_encoding_char_next( CFF_CMapStd cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; + + + *pchar_code = 0; + + if ( char_code < 255 ) + { + FT_UInt code = (FT_UInt)(char_code + 1); + + + for (;;) + { + if ( code >= 256 ) + break; + + result = cmap->gids[code]; + if ( result != 0 ) + { + *pchar_code = code; + break; + } + + code++; + } + } + return result; + } + + + FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec + cff_cmap_encoding_class_rec = + { + sizeof ( CFF_CMapStdRec ), + + (FT_CMap_InitFunc) cff_cmap_encoding_init, + (FT_CMap_DoneFunc) cff_cmap_encoding_done, + (FT_CMap_CharIndexFunc)cff_cmap_encoding_char_index, + (FT_CMap_CharNextFunc) cff_cmap_encoding_char_next + }; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_CALLBACK_DEF( FT_Int ) + cff_cmap_uni_pair_compare( const void* pair1, + const void* pair2 ) + { + FT_UInt32 u1 = ((CFF_CMapUniPair)pair1)->unicode; + FT_UInt32 u2 = ((CFF_CMapUniPair)pair2)->unicode; + + + if ( u1 < u2 ) + return -1; + + if ( u1 > u2 ) + return +1; + + return 0; + } + + + FT_CALLBACK_DEF( FT_Error ) + cff_cmap_unicode_init( CFF_CMapUnicode cmap ) + { + FT_Error error; + FT_UInt count; + TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + CFF_Font cff = (CFF_Font)face->extra.data; + CFF_Charset charset = &cff->charset; + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; + + + cmap->num_pairs = 0; + cmap->pairs = NULL; + + count = cff->num_glyphs; + + if ( !FT_NEW_ARRAY( cmap->pairs, count ) ) + { + FT_UInt n, new_count; + CFF_CMapUniPair pair; + FT_UInt32 uni_code; + + + pair = cmap->pairs; + for ( n = 0; n < count; n++ ) + { + FT_UInt sid = charset->sids[n]; + const char* gname; + + + gname = cff_index_get_sid_string( &cff->string_index, sid, psnames ); + + /* build unsorted pair table by matching glyph names */ + if ( gname ) + { + uni_code = psnames->unicode_value( gname ); + + if ( uni_code != 0 ) + { + pair->unicode = uni_code; + pair->gindex = n; + pair++; + } + + FT_FREE( gname ); + } + } + + new_count = (FT_UInt)( pair - cmap->pairs ); + if ( new_count == 0 ) + { + /* there are no unicode characters in here! */ + FT_FREE( cmap->pairs ); + error = CFF_Err_Invalid_Argument; + } + else + { + /* re-allocate if the new array is much smaller than the original */ + /* one */ + if ( new_count != count && new_count < count / 2 ) + { + (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count ); + error = CFF_Err_Ok; + } + + /* sort the pairs table to allow efficient binary searches */ + ft_qsort( cmap->pairs, + new_count, + sizeof ( CFF_CMapUniPairRec ), + cff_cmap_uni_pair_compare ); + + cmap->num_pairs = new_count; + } + } + + return error; + } + + + FT_CALLBACK_DEF( void ) + cff_cmap_unicode_done( CFF_CMapUnicode cmap ) + { + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( cmap->pairs ); + cmap->num_pairs = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_unicode_char_index( CFF_CMapUnicode cmap, + FT_UInt32 char_code ) + { + FT_UInt min = 0; + FT_UInt max = cmap->num_pairs; + FT_UInt mid; + CFF_CMapUniPair pair; + + + while ( min < max ) + { + mid = min + ( max - min ) / 2; + pair = cmap->pairs + mid; + + if ( pair->unicode == char_code ) + return pair->gindex; + + if ( pair->unicode < char_code ) + min = mid + 1; + else + max = mid; + } + return 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + cff_cmap_unicode_char_next( CFF_CMapUnicode cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code + 1; + + + Restart: + { + FT_UInt min = 0; + FT_UInt max = cmap->num_pairs; + FT_UInt mid; + CFF_CMapUniPair pair; + + + while ( min < max ) + { + mid = min + ( ( max - min ) >> 1 ); + pair = cmap->pairs + mid; + + if ( pair->unicode == char_code ) + { + result = pair->gindex; + if ( result != 0 ) + goto Exit; + + char_code++; + goto Restart; + } + + if ( pair->unicode < char_code ) + min = mid+1; + else + max = mid; + } + + /* we didn't find it, but we have a pair just above it */ + char_code = 0; + + if ( min < cmap->num_pairs ) + { + pair = cmap->pairs + min; + result = pair->gindex; + if ( result != 0 ) + char_code = pair->unicode; + } + } + + Exit: + *pchar_code = char_code; + return result; + } + + + FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec + cff_cmap_unicode_class_rec = + { + sizeof ( CFF_CMapUnicodeRec ), + + (FT_CMap_InitFunc) cff_cmap_unicode_init, + (FT_CMap_DoneFunc) cff_cmap_unicode_done, + (FT_CMap_CharIndexFunc)cff_cmap_unicode_char_index, + (FT_CMap_CharNextFunc) cff_cmap_unicode_char_next + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffcmap.h b/Utilities/vtkfreetype/src/cff/cffcmap.h new file mode 100644 index 0000000..ceb32cd --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffcmap.h @@ -0,0 +1,87 @@ +/***************************************************************************/ +/* */ +/* cffcmap.h */ +/* */ +/* CFF character mapping table (cmap) support (specification). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CFFCMAP_H__ +#define __CFFCMAP_H__ + +#include "cffobjs.h" + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* standard (and expert) encoding cmaps */ + typedef struct CFF_CMapStdRec_* CFF_CMapStd; + + typedef struct CFF_CMapStdRec_ + { + FT_CMapRec cmap; + FT_UShort* gids; /* up to 256 elements */ + + } CFF_CMapStdRec; + + + FT_CALLBACK_TABLE const FT_CMap_ClassRec + cff_cmap_encoding_class_rec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** CFF SYNTHETIC UNICODE ENCODING CMAP *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* unicode (synthetic) cmaps */ + typedef struct CFF_CMapUnicodeRec_* CFF_CMapUnicode; + + typedef struct CFF_CMapUniPairRec_ + { + FT_UInt32 unicode; + FT_UInt gindex; + + } CFF_CMapUniPairRec, *CFF_CMapUniPair; + + + typedef struct CFF_CMapUnicodeRec_ + { + FT_CMapRec cmap; + FT_UInt num_pairs; + CFF_CMapUniPair pairs; + + } CFF_CMapUnicodeRec; + + + FT_CALLBACK_TABLE const FT_CMap_ClassRec + cff_cmap_unicode_class_rec; + + +FT_END_HEADER + +#endif /* __CFFCMAP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffdrivr.c b/Utilities/vtkfreetype/src/cff/cffdrivr.c new file mode 100644 index 0000000..e1f274e --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffdrivr.c @@ -0,0 +1,480 @@ +/***************************************************************************/ +/* */ +/* cffdrivr.c */ +/* */ +/* OpenType font driver implementation (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_SFNT_H +#include FT_TRUETYPE_IDS_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_SERVICE_POSTSCRIPT_INFO_H +#include FT_SERVICE_TT_CMAP_H + +#include "cffdrivr.h" +#include "cffgload.h" +#include "cffload.h" +#include "cffcmap.h" + +#include "cfferrs.h" + +#include FT_SERVICE_XFREE86_NAME_H +#include FT_SERVICE_GLYPH_DICT_H + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cffdriver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Get_Kerning */ + /* */ + /* <Description> */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* <Output> */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings, are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + FT_CALLBACK_DEF( FT_Error ) + Get_Kerning( FT_Face ttface, /* TT_Face */ + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + TT_Face face = (TT_Face)ttface; + TT_Kern0_Pair pair; + + + if ( !face ) + return CFF_Err_Invalid_Face_Handle; + + kerning->x = 0; + kerning->y = 0; + + if ( face->kern_pairs ) + { + /* there are some kerning pairs in this font file! */ + FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph ); + FT_Long left, right; + + + left = 0; + right = face->num_kern_pairs - 1; + + while ( left <= right ) + { + FT_Long middle = left + ( ( right - left ) >> 1 ); + FT_ULong cur_pair; + + + pair = face->kern_pairs + middle; + cur_pair = PAIR_TAG( pair->left, pair->right ); + + if ( cur_pair == search_tag ) + goto Found; + + if ( cur_pair < search_tag ) + left = middle + 1; + else + right = middle - 1; + } + } + + Exit: + return CFF_Err_Ok; + + Found: + kerning->x = pair->value; + goto Exit; + } + + +#undef PAIR_TAG + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Load_Glyph */ + /* */ + /* <Description> */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* <Input> */ + /* slot :: A handle to the target slot object where the glyph */ + /* will be loaded. */ + /* */ + /* size :: A handle to the source face size at which the glyph */ + /* must be scaled, loaded, etc. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_??? constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_CALLBACK_DEF( FT_Error ) + Load_Glyph( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ + FT_Size cffsize, /* CFF_Size */ + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + FT_Error error; + CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; + CFF_Size size = (CFF_Size)cffsize; + + + if ( !slot ) + return CFF_Err_Invalid_Slot_Handle; + + /* check whether we want a scaled outline or bitmap */ + if ( !size ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + if ( load_flags & FT_LOAD_NO_SCALE ) + size = NULL; + + /* reset the size object if necessary */ + if ( size ) + { + /* these two objects must have the same parent */ + if ( cffsize->face != cffslot->face ) + return CFF_Err_Invalid_Face_Handle; + } + + /* now load the glyph outline if necessary */ + error = cff_slot_load( slot, size, glyph_index, load_flags ); + + /* force drop-out mode to 2 - irrelevant now */ + /* slot->outline.dropout_mode = 2; */ + + return error; + } + + + /* + * GLYPH DICT SERVICE + * + */ + + static FT_Error + cff_get_glyph_name( CFF_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + CFF_Font font = (CFF_Font)face->extra.data; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_String* gname; + FT_UShort sid; + FT_Service_PsCMaps psnames; + FT_Error error; + + + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); + if ( !psnames ) + { + FT_ERROR(( "cff_get_glyph_name:" )); + FT_ERROR(( " cannot get glyph name from CFF & CEF fonts\n" )); + FT_ERROR(( " " )); + FT_ERROR(( " without the `PSNames' module\n" )); + error = CFF_Err_Unknown_File_Format; + goto Exit; + } + + /* first, locate the sid in the charset table */ + sid = font->charset.sids[glyph_index]; + + /* now, lookup the name itself */ + gname = cff_index_get_sid_string( &font->string_index, sid, psnames ); + + if ( gname && buffer_max > 0 ) + { + FT_UInt len = (FT_UInt)ft_strlen( gname ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + FT_MEM_COPY( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + FT_FREE( gname ); + error = CFF_Err_Ok; + + Exit: + return error; + } + + + static FT_UInt + cff_get_name_index( CFF_Face face, + FT_String* glyph_name ) + { + CFF_Font cff; + CFF_Charset charset; + FT_Service_PsCMaps psnames; + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_String* name; + FT_UShort sid; + FT_UInt i; + FT_Int result; + + + cff = (CFF_FontRec *)face->extra.data; + charset = &cff->charset; + + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); + if ( !psnames ) + return 0; + + for ( i = 0; i < cff->num_glyphs; i++ ) + { + sid = charset->sids[i]; + + if ( sid > 390 ) + name = cff_index_get_name( &cff->string_index, sid - 391 ); + else + name = (FT_String *)psnames->adobe_std_strings( sid ); + + result = ft_strcmp( glyph_name, name ); + + if ( sid > 390 ) + FT_FREE( name ); + + if ( !result ) + return i; + } + + return 0; + } + + + static const FT_Service_GlyphDictRec cff_service_glyph_dict = + { + (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, + (FT_GlyphDict_NameIndexFunc)cff_get_name_index, + }; + + + /* + * POSTSCRIPT INFO SERVICE + * + */ + + static FT_Int + cff_ps_has_glyph_names( FT_Face face ) + { + return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; + } + + + static const FT_Service_PsInfoRec cff_service_ps_info = + { + (PS_GetFontInfoFunc) NULL, /* unsupported with CFF fonts */ + (PS_HasGlyphNamesFunc)cff_ps_has_glyph_names + }; + + + /* + * TT CMAP INFO + * + * If the charmap is a synthetic Unicode encoding cmap or + * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO + * service defined in SFNT module. + * + * Otherwise call the service function in the sfnt module. + * + */ + static FT_Error + cff_get_cmap_info( FT_CharMap charmap, + TT_CMapInfo *cmap_info ) + { + FT_CMap cmap = FT_CMAP( charmap ); + FT_Error error = CFF_Err_Ok; + + + cmap_info->language = 0; + + if ( cmap->clazz != &cff_cmap_encoding_class_rec && + cmap->clazz != &cff_cmap_unicode_class_rec ) + { + FT_Face face = FT_CMAP_FACE( cmap ); + FT_Library library = FT_FACE_LIBRARY( face ); + FT_Module sfnt = FT_Get_Module( library, "sfnt" ); + FT_Service_TTCMaps service = + (FT_Service_TTCMaps)ft_module_get_service( sfnt, + FT_SERVICE_ID_TT_CMAP ); + + + if ( service && service->get_cmap_info ) + error = service->get_cmap_info( charmap, cmap_info ); + } + + return error; + } + + + static const FT_Service_TTCMapsRec cff_service_get_cmap_info = + { + (TT_CMap_Info_GetFunc)cff_get_cmap_info + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R I N T E R F A C E ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + static const FT_ServiceDescRec cff_services[] = + { + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF }, + { FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info }, +#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES + { FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict }, +#endif + { FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info }, + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + cff_get_interface( FT_Module driver, /* CFF_Driver */ + const char* module_interface ) + { + FT_Module sfnt; + FT_Module_Interface result; + + + result = ft_service_list_lookup( cff_services, module_interface ); + if ( result != NULL ) + return result; + + /* we pass our request to the `sfnt' module */ + sfnt = FT_Get_Module( driver->library, "sfnt" ); + + return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; + } + + + /* The FT_DriverInterface structure is defined in ftdriver.h. */ + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec cff_driver_class = + { + /* begin with the FT_Module_Class fields */ + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_SCALABLE | + FT_MODULE_DRIVER_HAS_HINTER, + + sizeof( CFF_DriverRec ), + "cff", + 0x10000L, + 0x20000L, + + 0, /* module-specific interface */ + + cff_driver_init, + cff_driver_done, + cff_get_interface, + }, + + /* now the specific driver fields */ + sizeof( TT_FaceRec ), + sizeof( CFF_SizeRec ), + sizeof( CFF_GlyphSlotRec ), + + cff_face_init, + cff_face_done, + cff_size_init, + cff_size_done, + cff_slot_init, + cff_slot_done, + + cff_point_size_reset, + cff_size_reset, + + Load_Glyph, + + Get_Kerning, + 0, /* FT_Face_AttachFunc */ + 0 /* FT_Face_GetAdvancesFunc */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffdrivr.h b/Utilities/vtkfreetype/src/cff/cffdrivr.h new file mode 100644 index 0000000..553848c --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffdrivr.h @@ -0,0 +1,39 @@ +/***************************************************************************/ +/* */ +/* cffdrivr.h */ +/* */ +/* High-level OpenType driver interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CFFDRIVER_H__ +#define __CFFDRIVER_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + + FT_CALLBACK_TABLE + const FT_Driver_ClassRec cff_driver_class; + + +FT_END_HEADER + +#endif /* __CFFDRIVER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cfferrs.h b/Utilities/vtkfreetype/src/cff/cfferrs.h new file mode 100644 index 0000000..1b2a5c9 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cfferrs.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* cfferrs.h */ +/* */ +/* CFF error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the CFF error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __CFFERRS_H__ +#define __CFFERRS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX CFF_Err_ +#define FT_ERR_BASE FT_Mod_Err_CFF + + +#include FT_ERRORS_H + +#endif /* __CFFERRS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffgload.c b/Utilities/vtkfreetype/src/cff/cffgload.c new file mode 100644 index 0000000..934dcb0 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffgload.c @@ -0,0 +1,2594 @@ +/***************************************************************************/ +/* */ +/* cffgload.c */ +/* */ +/* OpenType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_SFNT_H +#include FT_OUTLINE_H +#include FT_TRUETYPE_TAGS_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H + +#include "cffobjs.h" +#include "cffload.h" +#include "cffgload.h" + +#include "cfferrs.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cffgload + + + typedef enum CFF_Operator_ + { + cff_op_unknown = 0, + + cff_op_rmoveto, + cff_op_hmoveto, + cff_op_vmoveto, + + cff_op_rlineto, + cff_op_hlineto, + cff_op_vlineto, + + cff_op_rrcurveto, + cff_op_hhcurveto, + cff_op_hvcurveto, + cff_op_rcurveline, + cff_op_rlinecurve, + cff_op_vhcurveto, + cff_op_vvcurveto, + + cff_op_flex, + cff_op_hflex, + cff_op_hflex1, + cff_op_flex1, + + cff_op_endchar, + + cff_op_hstem, + cff_op_vstem, + cff_op_hstemhm, + cff_op_vstemhm, + + cff_op_hintmask, + cff_op_cntrmask, + cff_op_dotsection, /* deprecated, acts as no-op */ + + cff_op_abs, + cff_op_add, + cff_op_sub, + cff_op_div, + cff_op_neg, + cff_op_random, + cff_op_mul, + cff_op_sqrt, + + cff_op_blend, + + cff_op_drop, + cff_op_exch, + cff_op_index, + cff_op_roll, + cff_op_dup, + + cff_op_put, + cff_op_get, + cff_op_store, + cff_op_load, + + cff_op_and, + cff_op_or, + cff_op_not, + cff_op_eq, + cff_op_ifelse, + + cff_op_callsubr, + cff_op_callgsubr, + cff_op_return, + + /* do not remove */ + cff_op_max + + } CFF_Operator; + + +#define CFF_COUNT_CHECK_WIDTH 0x80 +#define CFF_COUNT_EXACT 0x40 +#define CFF_COUNT_CLEAR_STACK 0x20 + + + static const FT_Byte cff_argument_counts[] = + { + 0, /* unknown */ + + 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ + 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, + 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, + + 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + + 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + 0 | CFF_COUNT_CLEAR_STACK, + + 13, /* flex */ + 7, + 9, + 11, + + 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ + + 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ + 2 | CFF_COUNT_CHECK_WIDTH, + 2 | CFF_COUNT_CHECK_WIDTH, + 2 | CFF_COUNT_CHECK_WIDTH, + + 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ + 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ + 0, /* dotsection */ + + 1, /* abs */ + 2, + 2, + 2, + 1, + 0, + 2, + 1, + + 1, /* blend */ + + 1, /* drop */ + 2, + 1, + 2, + 1, + + 2, /* put */ + 1, + 4, + 3, + + 2, /* and */ + 2, + 1, + 2, + 4, + + 1, /* callsubr */ + 1, + 0 + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_builder_init */ + /* */ + /* <Description> */ + /* Initializes a given glyph builder. */ + /* */ + /* <InOut> */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + static void + cff_builder_init( CFF_Builder* builder, + TT_Face face, + CFF_Size size, + CFF_GlyphSlot glyph, + FT_Bool hinting ) + { + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader loader = glyph->root.internal->loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + FT_GlyphLoader_Rewind( loader ); + + builder->hints_globals = 0; + builder->hints_funcs = 0; + + if ( hinting && size ) + { + builder->hints_globals = size->root.internal; + builder->hints_funcs = glyph->root.internal->glyph_hints; + } + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.metrics.y_scale; + } + + builder->pos_x = 0; + builder->pos_y = 0; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + builder->advance.x = 0; + builder->advance.y = 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_builder_done */ + /* */ + /* <Description> */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* <Input> */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + static void + cff_builder_done( CFF_Builder* builder ) + { + CFF_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_compute_bias */ + /* */ + /* <Description> */ + /* Computes the bias value in dependence of the number of glyph */ + /* subroutines. */ + /* */ + /* <Input> */ + /* num_subrs :: The number of glyph subroutines. */ + /* */ + /* <Return> */ + /* The bias value. */ + static FT_Int + cff_compute_bias( FT_UInt num_subrs ) + { + FT_Int result; + + + if ( num_subrs < 1240 ) + result = 107; + else if ( num_subrs < 33900U ) + result = 1131; + else + result = 32768U; + + return result; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_decoder_init */ + /* */ + /* <Description> */ + /* Initializes a given glyph decoder. */ + /* */ + /* <InOut> */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* slot :: The current glyph object. */ + /* */ + FT_LOCAL_DEF( void ) + cff_decoder_init( CFF_Decoder* decoder, + TT_Face face, + CFF_Size size, + CFF_GlyphSlot slot, + FT_Bool hinting, + FT_Render_Mode hint_mode ) + { + CFF_Font cff = (CFF_Font)face->extra.data; + + + /* clear everything */ + FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); + + /* initialize builder */ + cff_builder_init( &decoder->builder, face, size, slot, hinting ); + + /* initialize Type2 decoder */ + decoder->num_globals = cff->num_global_subrs; + decoder->globals = cff->global_subrs; + decoder->globals_bias = cff_compute_bias( decoder->num_globals ); + + decoder->hint_mode = hint_mode; + } + + + /* this function is used to select the locals subrs array */ + FT_LOCAL_DEF( void ) + cff_decoder_prepare( CFF_Decoder* decoder, + FT_UInt glyph_index ) + { + CFF_Font cff = (CFF_Font)decoder->builder.face->extra.data; + CFF_SubFont sub = &cff->top_font; + + + /* manage CID fonts */ + if ( cff->num_subfonts >= 1 ) + { + FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); + + + sub = cff->subfonts[fd_index]; + } + + decoder->num_locals = sub->num_local_subrs; + decoder->locals = sub->local_subrs; + decoder->locals_bias = cff_compute_bias( decoder->num_locals ); + + decoder->glyph_width = sub->private_dict.default_width; + decoder->nominal_width = sub->private_dict.nominal_width; + } + + + /* check that there is enough space for `count' more points */ + static FT_Error + check_points( CFF_Builder* builder, + FT_Int count ) + { + return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 ); + } + + + /* add a new point, do not check space */ + static void + cff_builder_add_point( CFF_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + + + point->x = x >> 16; + point->y = y >> 16; + *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); + + builder->last = *point; + } + + outline->n_points++; + } + + + /* check space for a new on-curve point, then add it */ + static FT_Error + cff_builder_add_point1( CFF_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error; + + + error = check_points( builder, 1 ); + if ( !error ) + cff_builder_add_point( builder, x, y, 1 ); + + return error; + } + + + /* check space for a new contour, then add it */ + static FT_Error + cff_builder_add_contour( CFF_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return CFF_Err_Ok; + } + + error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + + outline->n_contours++; + } + + return error; + } + + + /* if a path was begun, add its first on-curve point */ + static FT_Error + cff_builder_start_point( CFF_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error = CFF_Err_Ok; + + + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + builder->path_begun = 1; + error = cff_builder_add_contour( builder ); + if ( !error ) + error = cff_builder_add_point1( builder, x, y ); + } + + return error; + } + + + /* close the current contour */ + static void + cff_builder_close_contour( CFF_Builder* builder ) + { + FT_Outline* outline = builder->current; + + + /* XXXX: We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( outline->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + outline->n_points - 1; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + /* `delete' last point only if it coincides with the first */ + /* point and if it is not a control point (which can happen). */ + if ( p1->x == p2->x && p1->y == p2->y ) + if ( *control == FT_CURVE_TAG_ON ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + } + + + static FT_Int + cff_lookup_glyph_by_stdcharcode( CFF_Font cff, + FT_Int charcode ) + { + FT_UInt n; + FT_UShort glyph_sid; + + + /* CID-keyed fonts don't have glyph names */ + if ( !cff->charset.sids ) + return -1; + + /* check range of standard char code */ + if ( charcode < 0 || charcode > 255 ) + return -1; + + /* Get code to SID mapping from `cff_standard_encoding'. */ + glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); + + for ( n = 0; n < cff->num_glyphs; n++ ) + { + if ( cff->charset.sids[n] == glyph_sid ) + return n; + } + + return -1; + } + + + static FT_Error + cff_get_glyph_data( TT_Face face, + FT_UInt glyph_index, + FT_Byte** pointer, + FT_ULong* length ) + { +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* For incremental fonts get the character data using the */ + /* callback function. */ + if ( face->root.internal->incremental_interface ) + { + FT_Data data; + FT_Error error = + face->root.internal->incremental_interface->funcs->get_glyph_data( + face->root.internal->incremental_interface->object, + glyph_index, &data ); + + + *pointer = (FT_Byte*)data.pointer; + *length = data.length; + + return error; + } + else +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + { + CFF_Font cff = (CFF_Font)(face->extra.data); + + + return cff_index_access_element( &cff->charstrings_index, glyph_index, + pointer, length ); + } + } + + + static void + cff_free_glyph_data( TT_Face face, + FT_Byte** pointer, + FT_ULong length ) + { +#ifndef FT_CONFIG_OPTION_INCREMENTAL + FT_UNUSED( length ); +#endif + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* For incremental fonts get the character data using the */ + /* callback function. */ + if ( face->root.internal->incremental_interface ) + { + FT_Data data; + + + data.pointer = *pointer; + data.length = length; + + face->root.internal->incremental_interface->funcs->free_glyph_data( + face->root.internal->incremental_interface->object,&data ); + } + else +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + { + CFF_Font cff = (CFF_Font)(face->extra.data); + + + cff_index_forget_element( &cff->charstrings_index, pointer ); + } + } + + + static FT_Error + cff_operator_seac( CFF_Decoder* decoder, + FT_Pos adx, + FT_Pos ady, + FT_Int bchar, + FT_Int achar ) + { + FT_Error error; + CFF_Builder* builder = &decoder->builder; + FT_Int bchar_index, achar_index; + TT_Face face = decoder->builder.face; + FT_Vector left_bearing, advance; + FT_Byte* charstring; + FT_ULong charstring_len; + + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* Incremental fonts don't necessarily have valid charsets. */ + /* They use the character code, not the glyph index, in this case. */ + if ( face->root.internal->incremental_interface ) + { + bchar_index = bchar; + achar_index = achar; + } + else +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + { + CFF_Font cff = (CFF_Font)(face->extra.data); + + + bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); + achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); + } + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "cff_operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return CFF_Err_Syntax_Error; + } + + /* If we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if ( builder->no_recurse ) + { + FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; + FT_GlyphLoader loader = glyph->internal->loader; + FT_SubGlyph subg; + + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); + if ( error ) + goto Exit; + + subg = loader->current.subglyphs; + + /* subglyph 0 = base character */ + subg->index = bchar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | + FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg->arg1 = 0; + subg->arg2 = 0; + subg++; + + /* subglyph 1 = accent character */ + subg->index = achar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg->arg1 = (FT_Int)( adx >> 16 ); + subg->arg2 = (FT_Int)( ady >> 16 ); + + /* set up remaining glyph fields */ + glyph->num_subglyphs = 2; + glyph->subglyphs = loader->base.subglyphs; + glyph->format = FT_GLYPH_FORMAT_COMPOSITE; + + loader->current.num_subglyphs = 2; + } + + FT_GlyphLoader_Prepare( builder->loader ); + + /* First load `bchar' in builder */ + error = cff_get_glyph_data( face, bchar_index, + &charstring, &charstring_len ); + if ( !error ) + { + error = cff_decoder_parse_charstrings( decoder, charstring, + charstring_len ); + + if ( error ) + goto Exit; + + cff_free_glyph_data( face, &charstring, charstring_len ); + } + + /* Save the left bearing and width of the base character */ + /* as they will be erased by the next load. */ + + left_bearing = builder->left_bearing; + advance = builder->advance; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + + builder->pos_x = adx; + builder->pos_y = ady; + + /* Now load `achar' on top of the base outline. */ + error = cff_get_glyph_data( face, achar_index, + &charstring, &charstring_len ); + if ( !error ) + { + error = cff_decoder_parse_charstrings( decoder, charstring, + charstring_len ); + + if ( error ) + goto Exit; + + cff_free_glyph_data( face, &charstring, charstring_len ); + } + + /* Restore the left side bearing and advance width */ + /* of the base character. */ + builder->left_bearing = left_bearing; + builder->advance = advance; + + builder->pos_x = 0; + builder->pos_y = 0; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cff_decoder_parse_charstrings */ + /* */ + /* <Description> */ + /* Parses a given Type 2 charstrings program. */ + /* */ + /* <InOut> */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* <Input> */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + cff_decoder_parse_charstrings( CFF_Decoder* decoder, + FT_Byte* charstring_base, + FT_ULong charstring_len ) + { + FT_Error error; + CFF_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + CFF_Builder* builder = &decoder->builder; + FT_Pos x, y; + FT_Fixed seed; + FT_Fixed* stack; + + T2_Hints_Funcs hinter; + + + /* set default width */ + decoder->num_hints = 0; + decoder->read_width = 1; + + /* compute random seed from stack address of parameter */ + seed = (FT_Fixed)(char*)&seed ^ + (FT_Fixed)(char*)&decoder ^ + (FT_Fixed)(char*)&charstring_base; + seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; + if ( seed == 0 ) + seed = 0x7384; + + /* initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + stack = decoder->top; + + hinter = (T2_Hints_Funcs)builder->hints_funcs; + + builder->path_begun = 0; + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + error = CFF_Err_Ok; + + x = builder->pos_x; + y = builder->pos_y; + + /* begin hints recording session, if any */ + if ( hinter ) + hinter->open( hinter->hints ); + + /* now execute loop */ + while ( ip < limit ) + { + CFF_Operator op; + FT_Byte v; + + + /********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + v = *ip++; + if ( v >= 32 || v == 28 ) + { + FT_Int shift = 16; + FT_Int32 val; + + + /* this is an operand, push it on the stack */ + if ( v == 28 ) + { + if ( ip + 1 >= limit ) + goto Syntax_Error; + val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] ); + ip += 2; + } + else if ( v < 247 ) + val = (FT_Long)v - 139; + else if ( v < 251 ) + { + if ( ip >= limit ) + goto Syntax_Error; + val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108; + } + else if ( v < 255 ) + { + if ( ip >= limit ) + goto Syntax_Error; + val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108; + } + else + { + if ( ip + 3 >= limit ) + goto Syntax_Error; + val = ( (FT_Int32)ip[0] << 24 ) | + ( (FT_Int32)ip[1] << 16 ) | + ( (FT_Int32)ip[2] << 8 ) | + ip[3]; + ip += 4; + shift = 0; + } + if ( decoder->top - stack >= CFF_MAX_OPERANDS ) + goto Stack_Overflow; + + val <<= shift; + *decoder->top++ = val; + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( !( val & 0xFFFFL ) ) + FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) )); + else + FT_TRACE4(( " %.2f", val / 65536.0 )); +#endif + + } + else + { + FT_Fixed* args = decoder->top; + FT_Int num_args = (FT_Int)( args - decoder->stack ); + FT_Int req_args; + + + /* find operator */ + op = cff_op_unknown; + + switch ( v ) + { + case 1: + op = cff_op_hstem; + break; + case 3: + op = cff_op_vstem; + break; + case 4: + op = cff_op_vmoveto; + break; + case 5: + op = cff_op_rlineto; + break; + case 6: + op = cff_op_hlineto; + break; + case 7: + op = cff_op_vlineto; + break; + case 8: + op = cff_op_rrcurveto; + break; + case 10: + op = cff_op_callsubr; + break; + case 11: + op = cff_op_return; + break; + case 12: + { + if ( ip >= limit ) + goto Syntax_Error; + v = *ip++; + + switch ( v ) + { + case 0: + op = cff_op_dotsection; + break; + case 3: + op = cff_op_and; + break; + case 4: + op = cff_op_or; + break; + case 5: + op = cff_op_not; + break; + case 8: + op = cff_op_store; + break; + case 9: + op = cff_op_abs; + break; + case 10: + op = cff_op_add; + break; + case 11: + op = cff_op_sub; + break; + case 12: + op = cff_op_div; + break; + case 13: + op = cff_op_load; + break; + case 14: + op = cff_op_neg; + break; + case 15: + op = cff_op_eq; + break; + case 18: + op = cff_op_drop; + break; + case 20: + op = cff_op_put; + break; + case 21: + op = cff_op_get; + break; + case 22: + op = cff_op_ifelse; + break; + case 23: + op = cff_op_random; + break; + case 24: + op = cff_op_mul; + break; + case 26: + op = cff_op_sqrt; + break; + case 27: + op = cff_op_dup; + break; + case 28: + op = cff_op_exch; + break; + case 29: + op = cff_op_index; + break; + case 30: + op = cff_op_roll; + break; + case 34: + op = cff_op_hflex; + break; + case 35: + op = cff_op_flex; + break; + case 36: + op = cff_op_hflex1; + break; + case 37: + op = cff_op_flex1; + break; + default: + /* decrement ip for syntax error message */ + ip--; + } + } + break; + case 14: + op = cff_op_endchar; + break; + case 16: + op = cff_op_blend; + break; + case 18: + op = cff_op_hstemhm; + break; + case 19: + op = cff_op_hintmask; + break; + case 20: + op = cff_op_cntrmask; + break; + case 21: + op = cff_op_rmoveto; + break; + case 22: + op = cff_op_hmoveto; + break; + case 23: + op = cff_op_vstemhm; + break; + case 24: + op = cff_op_rcurveline; + break; + case 25: + op = cff_op_rlinecurve; + break; + case 26: + op = cff_op_vvcurveto; + break; + case 27: + op = cff_op_hhcurveto; + break; + case 29: + op = cff_op_callgsubr; + break; + case 30: + op = cff_op_vhcurveto; + break; + case 31: + op = cff_op_hvcurveto; + break; + default: + ; + } + if ( op == cff_op_unknown ) + goto Syntax_Error; + + /* check arguments */ + req_args = cff_argument_counts[op]; + if ( req_args & CFF_COUNT_CHECK_WIDTH ) + { + args = stack; + + if ( num_args > 0 && decoder->read_width ) + { + /* If `nominal_width' is non-zero, the number is really a */ + /* difference against `nominal_width'. Else, the number here */ + /* is truly a width, not a difference against `nominal_width'. */ + /* If the font does not set `nominal_width', then */ + /* `nominal_width' defaults to zero, and so we can set */ + /* `glyph_width' to `nominal_width' plus number on the stack */ + /* -- for either case. */ + + FT_Int set_width_ok; + + + switch ( op ) + { + case cff_op_hmoveto: + case cff_op_vmoveto: + set_width_ok = num_args & 2; + break; + + case cff_op_hstem: + case cff_op_vstem: + case cff_op_hstemhm: + case cff_op_vstemhm: + case cff_op_rmoveto: + case cff_op_hintmask: + case cff_op_cntrmask: + set_width_ok = num_args & 1; + break; + + case cff_op_endchar: + /* If there is a width specified for endchar, we either have */ + /* 1 argument or 5 arguments. We like to argue. */ + set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) ); + break; + + default: + set_width_ok = 0; + break; + } + + if ( set_width_ok ) + { + decoder->glyph_width = decoder->nominal_width + + ( stack[0] >> 16 ); + + /* Consumed an argument. */ + num_args--; + args++; + } + } + + decoder->read_width = 0; + req_args = 0; + } + + req_args &= 15; + if ( num_args < req_args ) + goto Stack_Underflow; + args -= req_args; + num_args -= req_args; + + switch ( op ) + { + case cff_op_hstem: + case cff_op_vstem: + case cff_op_hstemhm: + case cff_op_vstemhm: + /* the number of arguments is always even here */ + FT_TRACE4(( op == cff_op_hstem ? " hstem" : + ( op == cff_op_vstem ? " vstem" : + ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) )); + + if ( hinter ) + hinter->stems( hinter->hints, + ( op == cff_op_hstem || op == cff_op_hstemhm ), + num_args / 2, + args ); + + decoder->num_hints += num_args / 2; + args = stack; + break; + + case cff_op_hintmask: + case cff_op_cntrmask: + FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); + + /* implement vstem when needed -- */ + /* the specification doesn't say it, but this also works */ + /* with the 'cntrmask' operator */ + /* */ + if ( num_args > 0 ) + { + if ( hinter ) + hinter->stems( hinter->hints, + 0, + num_args / 2, + args ); + + decoder->num_hints += num_args / 2; + } + + if ( hinter ) + { + if ( op == cff_op_hintmask ) + hinter->hintmask( hinter->hints, + builder->current->n_points, + decoder->num_hints, + ip ); + else + hinter->counter( hinter->hints, + decoder->num_hints, + ip ); + } + +#ifdef FT_DEBUG_LEVEL_TRACE + { + FT_UInt maskbyte; + + + FT_TRACE4(( " " )); + + for ( maskbyte = 0; + maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3); + maskbyte++, ip++ ) + FT_TRACE4(( "0x%02X", *ip )); + } +#else + ip += ( decoder->num_hints + 7 ) >> 3; +#endif + if ( ip >= limit ) + goto Syntax_Error; + args = stack; + break; + + case cff_op_rmoveto: + FT_TRACE4(( " rmoveto" )); + + cff_builder_close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + y += args[1]; + args = stack; + break; + + case cff_op_vmoveto: + FT_TRACE4(( " vmoveto" )); + + cff_builder_close_contour( builder ); + builder->path_begun = 0; + y += args[0]; + args = stack; + break; + + case cff_op_hmoveto: + FT_TRACE4(( " hmoveto" )); + + cff_builder_close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + args = stack; + break; + + case cff_op_rlineto: + FT_TRACE4(( " rlineto" )); + + if ( cff_builder_start_point ( builder, x, y ) || + check_points( builder, num_args / 2 ) ) + goto Fail; + + if ( num_args < 2 || num_args & 1 ) + goto Stack_Underflow; + + args = stack; + while ( args < decoder->top ) + { + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 1 ); + args += 2; + } + args = stack; + break; + + case cff_op_hlineto: + case cff_op_vlineto: + { + FT_Int phase = ( op == cff_op_hlineto ); + + + FT_TRACE4(( op == cff_op_hlineto ? " hlineto" + : " vlineto" )); + + if ( cff_builder_start_point ( builder, x, y ) || + check_points( builder, num_args ) ) + goto Fail; + + args = stack; + while (args < decoder->top ) + { + if ( phase ) + x += args[0]; + else + y += args[0]; + + if ( cff_builder_add_point1( builder, x, y ) ) + goto Fail; + + args++; + phase ^= 1; + } + args = stack; + } + break; + + case cff_op_rrcurveto: + FT_TRACE4(( " rrcurveto" )); + + /* check number of arguments; must be a multiple of 6 */ + if ( num_args % 6 != 0 ) + goto Stack_Underflow; + + if ( cff_builder_start_point ( builder, x, y ) || + check_points( builder, num_args / 2 ) ) + goto Fail; + + args = stack; + while ( args < decoder->top ) + { + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[2]; + y += args[3]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[4]; + y += args[5]; + cff_builder_add_point( builder, x, y, 1 ); + args += 6; + } + args = stack; + break; + + case cff_op_vvcurveto: + FT_TRACE4(( " vvcurveto" )); + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + args = stack; + if ( num_args & 1 ) + { + x += args[0]; + args++; + num_args--; + } + + if ( num_args % 4 != 0 ) + goto Stack_Underflow; + + if ( check_points( builder, 3 * ( num_args / 4 ) ) ) + goto Fail; + + while ( args < decoder->top ) + { + y += args[0]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + cff_builder_add_point( builder, x, y, 0 ); + y += args[3]; + cff_builder_add_point( builder, x, y, 1 ); + args += 4; + } + args = stack; + break; + + case cff_op_hhcurveto: + FT_TRACE4(( " hhcurveto" )); + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + args = stack; + if ( num_args & 1 ) + { + y += args[0]; + args++; + num_args--; + } + + if ( num_args % 4 != 0 ) + goto Stack_Underflow; + + if ( check_points( builder, 3 * ( num_args / 4 ) ) ) + goto Fail; + + while ( args < decoder->top ) + { + x += args[0]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[3]; + cff_builder_add_point( builder, x, y, 1 ); + args += 4; + } + args = stack; + break; + + case cff_op_vhcurveto: + case cff_op_hvcurveto: + { + FT_Int phase; + + + FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto" + : " hvcurveto" )); + + if ( cff_builder_start_point( builder, x, y ) ) + goto Fail; + + args = stack; + if (num_args < 4 || ( num_args % 4 ) > 1 ) + goto Stack_Underflow; + + if ( check_points( builder, ( num_args / 4 ) * 3 ) ) + goto Stack_Underflow; + + phase = ( op == cff_op_hvcurveto ); + + while ( num_args >= 4 ) + { + num_args -= 4; + if ( phase ) + { + x += args[0]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + cff_builder_add_point( builder, x, y, 0 ); + y += args[3]; + if ( num_args == 1 ) + x += args[4]; + cff_builder_add_point( builder, x, y, 1 ); + } + else + { + y += args[0]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[3]; + if ( num_args == 1 ) + y += args[4]; + cff_builder_add_point( builder, x, y, 1 ); + } + args += 4; + phase ^= 1; + } + args = stack; + } + break; + + case cff_op_rlinecurve: + { + FT_Int num_lines = ( num_args - 6 ) / 2; + + + FT_TRACE4(( " rlinecurve" )); + + if ( num_args < 8 || ( num_args - 6 ) & 1 ) + goto Stack_Underflow; + + if ( cff_builder_start_point( builder, x, y ) || + check_points( builder, num_lines + 3 ) ) + goto Fail; + + args = stack; + + /* first, add the line segments */ + while ( num_lines > 0 ) + { + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 1 ); + args += 2; + num_lines--; + } + + /* then the curve */ + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[2]; + y += args[3]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[4]; + y += args[5]; + cff_builder_add_point( builder, x, y, 1 ); + args = stack; + } + break; + + case cff_op_rcurveline: + { + FT_Int num_curves = ( num_args - 2 ) / 6; + + + FT_TRACE4(( " rcurveline" )); + + if ( num_args < 8 || ( num_args - 2 ) % 6 ) + goto Stack_Underflow; + + if ( cff_builder_start_point ( builder, x, y ) || + check_points( builder, num_curves*3 + 2 ) ) + goto Fail; + + args = stack; + + /* first, add the curves */ + while ( num_curves > 0 ) + { + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[2]; + y += args[3]; + cff_builder_add_point( builder, x, y, 0 ); + x += args[4]; + y += args[5]; + cff_builder_add_point( builder, x, y, 1 ); + args += 6; + num_curves--; + } + + /* then the final line */ + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 1 ); + args = stack; + } + break; + + case cff_op_hflex1: + { + FT_Pos start_y; + + + FT_TRACE4(( " hflex1" )); + + args = stack; + + /* adding five more points; 4 control points, 1 on-curve point */ + /* make sure we have enough space for the start point if it */ + /* needs to be added */ + if ( cff_builder_start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Fail; + + /* Record the starting point's y postion for later use */ + start_y = y; + + /* first control point */ + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, 0 ); + + /* second control point */ + x += args[2]; + y += args[3]; + cff_builder_add_point( builder, x, y, 0 ); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x += args[4]; + cff_builder_add_point( builder, x, y, 1 ); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x += args[5]; + cff_builder_add_point( builder, x, y, 0 ); + + /* fourth control point */ + x += args[6]; + y += args[7]; + cff_builder_add_point( builder, x, y, 0 ); + + /* ending point, with y-value the same as the start */ + x += args[8]; + y = start_y; + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case cff_op_hflex: + { + FT_Pos start_y; + + + FT_TRACE4(( " hflex" )); + + args = stack; + + /* adding six more points; 4 control points, 2 on-curve points */ + if ( cff_builder_start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Fail; + + /* record the starting point's y-position for later use */ + start_y = y; + + /* first control point */ + x += args[0]; + cff_builder_add_point( builder, x, y, 0 ); + + /* second control point */ + x += args[1]; + y += args[2]; + cff_builder_add_point( builder, x, y, 0 ); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x += args[3]; + cff_builder_add_point( builder, x, y, 1 ); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x += args[4]; + cff_builder_add_point( builder, x, y, 0 ); + + /* fourth control point */ + x += args[5]; + y = start_y; + cff_builder_add_point( builder, x, y, 0 ); + + /* ending point, with y-value the same as the start point's */ + /* y-value -- we don't add this point, though */ + x += args[6]; + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case cff_op_flex1: + { + FT_Pos start_x, start_y; /* record start x, y values for */ + /* alter use */ + FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ + /* algorithm below */ + FT_Int horizontal, count; + + + FT_TRACE4(( " flex1" )); + + /* adding six more points; 4 control points, 2 on-curve points */ + if ( cff_builder_start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Fail; + + /* record the starting point's x, y postion for later use */ + start_x = x; + start_y = y; + + /* XXX: figure out whether this is supposed to be a horizontal */ + /* or vertical flex; the Type 2 specification is vague... */ + + args = stack; + + /* grab up to the last argument */ + for ( count = 5; count > 0; count-- ) + { + dx += args[0]; + dy += args[1]; + args += 2; + } + + /* rewind */ + args = stack; + + if ( dx < 0 ) dx = -dx; + if ( dy < 0 ) dy = -dy; + + /* strange test, but here it is... */ + horizontal = ( dx > dy ); + + for ( count = 5; count > 0; count-- ) + { + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) ); + args += 2; + } + + /* is last operand an x- or y-delta? */ + if ( horizontal ) + { + x += args[0]; + y = start_y; + } + else + { + x = start_x; + y += args[0]; + } + + cff_builder_add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case cff_op_flex: + { + FT_UInt count; + + + FT_TRACE4(( " flex" )); + + if ( cff_builder_start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Fail; + + args = stack; + for ( count = 6; count > 0; count-- ) + { + x += args[0]; + y += args[1]; + cff_builder_add_point( builder, x, y, + (FT_Bool)( count == 4 || count == 1 ) ); + args += 2; + } + + args = stack; + } + break; + + case cff_op_endchar: + FT_TRACE4(( " endchar" )); + + /* We are going to emulate the seac operator. */ + if ( num_args == 4 ) + { + /* Save glyph width so that the subglyphs don't overwrite it. */ + FT_Pos glyph_width = decoder->glyph_width; + + + error = cff_operator_seac( decoder, + args[0], + args[1], + (FT_Int)( args[2] >> 16 ), + (FT_Int)( args[3] >> 16 ) ); + args += 4; + + decoder->glyph_width = glyph_width; + } + else + { + if ( !error ) + error = CFF_Err_Ok; + + cff_builder_close_contour( builder ); + + /* close hints recording session */ + if ( hinter ) + { + if (hinter->close( hinter->hints, builder->current->n_points ) ) + goto Syntax_Error; + + /* apply hints to the loaded glyph outline now */ + hinter->apply( hinter->hints, + builder->current, + (PSH_Globals)builder->hints_globals, + decoder->hint_mode ); + } + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add( builder->loader ); + } + + /* return now! */ + FT_TRACE4(( "\n\n" )); + return error; + + case cff_op_abs: + FT_TRACE4(( " abs" )); + + if ( args[0] < 0 ) + args[0] = -args[0]; + args++; + break; + + case cff_op_add: + FT_TRACE4(( " add" )); + + args[0] += args[1]; + args++; + break; + + case cff_op_sub: + FT_TRACE4(( " sub" )); + + args[0] -= args[1]; + args++; + break; + + case cff_op_div: + FT_TRACE4(( " div" )); + + args[0] = FT_DivFix( args[0], args[1] ); + args++; + break; + + case cff_op_neg: + FT_TRACE4(( " neg" )); + + args[0] = -args[0]; + args++; + break; + + case cff_op_random: + { + FT_Fixed Rand; + + + FT_TRACE4(( " rand" )); + + Rand = seed; + if ( Rand >= 0x8000L ) + Rand++; + + args[0] = Rand; + seed = FT_MulFix( seed, 0x10000L - seed ); + if ( seed == 0 ) + seed += 0x2873; + args++; + } + break; + + case cff_op_mul: + FT_TRACE4(( " mul" )); + + args[0] = FT_MulFix( args[0], args[1] ); + args++; + break; + + case cff_op_sqrt: + FT_TRACE4(( " sqrt" )); + + if ( args[0] > 0 ) + { + FT_Int count = 9; + FT_Fixed root = args[0]; + FT_Fixed new_root; + + + for (;;) + { + new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; + if ( new_root == root || count <= 0 ) + break; + root = new_root; + } + args[0] = new_root; + } + else + args[0] = 0; + args++; + break; + + case cff_op_drop: + /* nothing */ + FT_TRACE4(( " drop" )); + + break; + + case cff_op_exch: + { + FT_Fixed tmp; + + + FT_TRACE4(( " exch" )); + + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + args += 2; + } + break; + + case cff_op_index: + { + FT_Int idx = (FT_Int)( args[0] >> 16 ); + + + FT_TRACE4(( " index" )); + + if ( idx < 0 ) + idx = 0; + else if ( idx > num_args - 2 ) + idx = num_args - 2; + args[0] = args[-( idx + 1 )]; + args++; + } + break; + + case cff_op_roll: + { + FT_Int count = (FT_Int)( args[0] >> 16 ); + FT_Int idx = (FT_Int)( args[1] >> 16 ); + + + FT_TRACE4(( " roll" )); + + if ( count <= 0 ) + count = 1; + + args -= count; + if ( args < stack ) + goto Stack_Underflow; + + if ( idx >= 0 ) + { + while ( idx > 0 ) + { + FT_Fixed tmp = args[count - 1]; + FT_Int i; + + + for ( i = count - 2; i >= 0; i-- ) + args[i + 1] = args[i]; + args[0] = tmp; + idx--; + } + } + else + { + while ( idx < 0 ) + { + FT_Fixed tmp = args[0]; + FT_Int i; + + + for ( i = 0; i < count - 1; i++ ) + args[i] = args[i + 1]; + args[count - 1] = tmp; + idx++; + } + } + args += count; + } + break; + + case cff_op_dup: + FT_TRACE4(( " dup" )); + + args[1] = args[0]; + args++; + break; + + case cff_op_put: + { + FT_Fixed val = args[0]; + FT_Int idx = (FT_Int)( args[1] >> 16 ); + + + FT_TRACE4(( " put" )); + + if ( idx >= 0 && idx < decoder->len_buildchar ) + decoder->buildchar[idx] = val; + } + break; + + case cff_op_get: + { + FT_Int idx = (FT_Int)( args[0] >> 16 ); + FT_Fixed val = 0; + + + FT_TRACE4(( " get" )); + + if ( idx >= 0 && idx < decoder->len_buildchar ) + val = decoder->buildchar[idx]; + + args[0] = val; + args++; + } + break; + + case cff_op_store: + FT_TRACE4(( " store ")); + + goto Unimplemented; + + case cff_op_load: + FT_TRACE4(( " load" )); + + goto Unimplemented; + + case cff_op_dotsection: + /* this operator is deprecated and ignored by the parser */ + FT_TRACE4(( " dotsection" )); + break; + + case cff_op_and: + { + FT_Fixed cond = args[0] && args[1]; + + + FT_TRACE4(( " and" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case cff_op_or: + { + FT_Fixed cond = args[0] || args[1]; + + + FT_TRACE4(( " or" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case cff_op_eq: + { + FT_Fixed cond = !args[0]; + + + FT_TRACE4(( " eq" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case cff_op_ifelse: + { + FT_Fixed cond = (args[2] <= args[3]); + + + FT_TRACE4(( " ifelse" )); + + if ( !cond ) + args[0] = args[1]; + args++; + } + break; + + case cff_op_callsubr: + { + FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + + decoder->locals_bias ); + + + FT_TRACE4(( " callsubr(%d)", idx )); + + if ( idx >= decoder->num_locals ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" )); + FT_ERROR(( " invalid local subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->locals[idx]; + zone->limit = decoder->locals[idx + 1]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case cff_op_callgsubr: + { + FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + + decoder->globals_bias ); + + + FT_TRACE4(( " callgsubr(%d)", idx )); + + if ( idx >= decoder->num_globals ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" )); + FT_ERROR(( " invalid global subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->globals[idx]; + zone->limit = decoder->globals[idx + 1]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case cff_op_return: + FT_TRACE4(( " return" )); + + if ( decoder->zone <= decoder->zones ) + { + FT_ERROR(( "cff_decoder_parse_charstrings:" + " unexpected return\n" )); + goto Syntax_Error; + } + + decoder->zone--; + zone = decoder->zone; + ip = zone->cursor; + limit = zone->limit; + break; + + default: + Unimplemented: + FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); + + if ( ip[-1] == 12 ) + FT_ERROR(( " %d", ip[0] )); + FT_ERROR(( "\n" )); + + return CFF_Err_Unimplemented_Feature; + } + + decoder->top = args; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + Fail: + return error; + + Syntax_Error: + FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" )); + return CFF_Err_Invalid_File_Format; + + Stack_Underflow: + FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" )); + return CFF_Err_Too_Few_Arguments; + + Stack_Overflow: + FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" )); + return CFF_Err_Stack_Overflow; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#if 0 /* unused until we support pure CFF fonts */ + + + FT_LOCAL_DEF( FT_Error ) + cff_compute_max_advance( TT_Face face, + FT_Int* max_advance ) + { + FT_Error error = CFF_Err_Ok; + CFF_Decoder decoder; + FT_Int glyph_index; + CFF_Font cff = (CFF_Font)face->other; + + + *max_advance = 0; + + /* Initialize load decoder */ + cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + /* For each glyph, parse the glyph charstring and extract */ + /* the advance width. */ + for ( glyph_index = 0; glyph_index < face->root.num_glyphs; + glyph_index++ ) + { + FT_Byte* charstring; + FT_ULong charstring_len; + + + /* now get load the unscaled outline */ + error = cff_get_glyph_data( face, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + cff_decoder_prepare( &decoder, glyph_index ); + error = cff_decoder_parse_charstrings( &decoder, + charstring, charstring_len ); + + cff_free_glyph_data( face, &charstring, &charstring_len ); + } + + /* ignore the error if one has occurred -- skip to next glyph */ + error = CFF_Err_Ok; + } + + *max_advance = decoder.builder.advance.x; + + return CFF_Err_Ok; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** UNHINTED GLYPH LOADER *********/ + /********** *********/ + /********** The following code is in charge of loading a *********/ + /********** single outline. It completely ignores hinting *********/ + /********** and is used when FT_LOAD_NO_HINTING is set. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + cff_slot_load( CFF_GlyphSlot glyph, + CFF_Size size, + FT_Int glyph_index, + FT_Int32 load_flags ) + { + FT_Error error; + CFF_Decoder decoder; + TT_Face face = (TT_Face)glyph->root.face; + FT_Bool hinting; + CFF_Font cff = (CFF_Font)face->extra.data; + + FT_Matrix font_matrix; + FT_Vector font_offset; + + + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + glyph->x_scale = 0x10000L; + glyph->y_scale = 0x10000L; + if ( size ) + { + glyph->x_scale = size->root.metrics.x_scale; + glyph->y_scale = size->root.metrics.y_scale; + } + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* try to load embedded bitmap if any */ + /* */ + /* XXX: The convention should be emphasized in */ + /* the documents because it can be confusing. */ + if ( size ) + { + CFF_Face cff_face = (CFF_Face)size->root.face; + SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; + FT_Stream stream = cff_face->root.stream; + + + if ( size->strike_index != 0xFFFFU && + sfnt->load_sbits && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) + { + TT_SBit_MetricsRec metrics; + + + error = sfnt->load_sbit_image( face, + (FT_ULong)size->strike_index, + (FT_UInt)glyph_index, + (FT_Int)load_flags, + stream, + &glyph->root.bitmap, + &metrics ); + + if ( !error ) + { + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + glyph->root.metrics.width = (FT_Pos)metrics.width << 6; + glyph->root.metrics.height = (FT_Pos)metrics.height << 6; + + glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; + glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; + glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; + + glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; + glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; + glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; + + glyph->root.format = FT_GLYPH_FORMAT_BITMAP; + + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + glyph->root.bitmap_left = metrics.vertBearingX; + glyph->root.bitmap_top = metrics.vertBearingY; + } + else + { + glyph->root.bitmap_left = metrics.horiBearingX; + glyph->root.bitmap_top = metrics.horiBearingY; + } + return error; + } + } + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* return immediately if we only want the embedded bitmaps */ + if ( load_flags & FT_LOAD_SBITS_ONLY ) + return CFF_Err_Invalid_Argument; + + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + + glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ + + { + FT_Byte* charstring; + FT_ULong charstring_len; + + + /* in a CID-keyed font, consider `glyph_index' as a CID and map */ + /* it immediately to the real glyph_index -- if it isn't a */ + /* subsetted font, glyph_indices and CIDs are identical, though */ + if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && + cff->charset.cids ) + glyph_index = cff->charset.cids[glyph_index]; + + cff_decoder_init( &decoder, face, size, glyph, hinting, + FT_LOAD_TARGET_MODE( load_flags ) ); + + decoder.builder.no_recurse = + (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); + + /* now load the unscaled outline */ + error = cff_get_glyph_data( face, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + cff_decoder_prepare( &decoder, glyph_index ); + error = cff_decoder_parse_charstrings( &decoder, + charstring, charstring_len ); + + cff_free_glyph_data( face, &charstring, charstring_len ); + + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* Control data and length may not be available for incremental */ + /* fonts. */ + if ( face->root.internal->incremental_interface ) + { + glyph->root.control_data = 0; + glyph->root.control_len = 0; + } + else +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + /* We set control_data and control_len if charstrings is loaded. */ + /* See how charstring loads at cff_index_access_element() in */ + /* cffload.c. */ + { + CFF_IndexRec csindex = cff->charstrings_index; + + + glyph->root.control_data = + csindex.bytes + csindex.offsets[glyph_index] - 1; + glyph->root.control_len = + charstring_len; + } + } + + /* save new glyph tables */ + cff_builder_done( &decoder.builder ); + } + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* Incremental fonts can optionally override the metrics. */ + if ( !error && + face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + { + FT_Incremental_MetricsRec metrics; + + + metrics.bearing_x = decoder.builder.left_bearing.x; + metrics.bearing_y = decoder.builder.left_bearing.y; + metrics.advance = decoder.builder.advance.x; + error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( + face->root.internal->incremental_interface->object, + glyph_index, FALSE, &metrics ); + decoder.builder.left_bearing.x = metrics.bearing_x; + decoder.builder.left_bearing.y = metrics.bearing_y; + decoder.builder.advance.x = metrics.advance; + decoder.builder.advance.y = 0; + } + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + font_matrix = cff->top_font.font_dict.font_matrix; + font_offset = cff->top_font.font_dict.font_offset; + + /* Now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax. */ + if ( !error ) + { + /* For composite glyphs, return only left side bearing and */ + /* advance width. */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + FT_Slot_Internal internal = glyph->root.internal; + + + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.glyph_width; + internal->glyph_matrix = font_matrix; + internal->glyph_delta = font_offset; + internal->glyph_transformed = 1; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + FT_Vector advance; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.glyph_width; + glyph->root.linearHoriAdvance = decoder.glyph_width; + glyph->root.internal->glyph_transformed = 0; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.linearVertAdvance = 0; + + glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; + + glyph->root.outline.flags = 0; + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; + + glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, &font_matrix ); + + FT_Outline_Translate( &glyph->root.outline, + font_offset.x, + font_offset.y ); + + advance.x = metrics->horiAdvance; + advance.y = 0; + FT_Vector_Transform( &advance, &font_matrix ); + metrics->horiAdvance = advance.x + font_offset.x; + advance.x = 0; + advance.y = metrics->vertAdvance; + FT_Vector_Transform( &advance, &font_matrix ); + metrics->vertAdvance = advance.y + font_offset.y; + + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + /* scale the outline and the metrics */ + FT_Int n; + FT_Outline* cur = &glyph->root.outline; + FT_Vector* vec = cur->points; + FT_Fixed x_scale = glyph->x_scale; + FT_Fixed y_scale = glyph->y_scale; + + + /* First of all, scale the points */ + if ( !hinting ) + for ( n = cur->n_points; n > 0; n--, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* Then scale the metrics */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + + if ( hinting ) + { + metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance ); + metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance ); + + metrics->vertBearingX = FT_PIX_ROUND( metrics->vertBearingX ); + metrics->vertBearingY = FT_PIX_ROUND( metrics->vertBearingY ); + } + } + + /* compute the other metrics */ + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* grid fit the bounding box if necessary */ + if ( hinting ) + { + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = ( cbox.xMax + 63 ) & -64; + cbox.yMax = ( cbox.yMax + 63 ) & -64; + } + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax; + } + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffgload.h b/Utilities/vtkfreetype/src/cff/cffgload.h new file mode 100644 index 0000000..89ae049 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffgload.h @@ -0,0 +1,208 @@ +/***************************************************************************/ +/* */ +/* cffgload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CFFGLOAD_H__ +#define __CFFGLOAD_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include "cffobjs.h" + + +FT_BEGIN_HEADER + + +#define CFF_MAX_OPERANDS 48 +#define CFF_MAX_SUBRS_CALLS 32 + + + /*************************************************************************/ + /* */ + /* <Structure> */ + /* CFF_Builder */ + /* */ + /* <Description> */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* <Fields> */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: The current glyph loader. */ + /* */ + /* base :: The base glyph outline. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* last :: The last point position. */ + /* */ + /* scale_x :: The horizontal scale (FUnits to sub-pixels). */ + /* */ + /* scale_y :: The vertical scale (FUnits to sub-pixels). */ + /* */ + /* pos_x :: The horizontal translation (if composite glyph). */ + /* */ + /* pos_y :: The vertical translation (if composite glyph). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* bbox :: Unused. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: If this flag is not set, no points are loaded. */ + /* */ + /* no_recurse :: Set but not used. */ + /* */ + /* metrics_only :: A boolean indicating that we only want to compute */ + /* the metrics of a given glyph, not load all of its */ + /* points. */ + /* */ + /* hints_funcs :: Auxiliary pointer for hinting. */ + /* */ + /* hints_globals :: Auxiliary pointer for hinting. */ + /* */ + typedef struct CFF_Builder_ + { + FT_Memory memory; + TT_Face face; + CFF_GlyphSlot glyph; + FT_GlyphLoader loader; + FT_Outline* base; + FT_Outline* current; + + FT_Vector last; + + FT_Fixed scale_x; + FT_Fixed scale_y; + + FT_Pos pos_x; + FT_Pos pos_y; + + FT_Vector left_bearing; + FT_Vector advance; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + FT_Bool no_recurse; + + FT_Bool metrics_only; + + void* hints_funcs; /* hinter-specific */ + void* hints_globals; /* hinter-specific */ + + } CFF_Builder; + + + /* execution context charstring zone */ + + typedef struct CFF_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } CFF_Decoder_Zone; + + + typedef struct CFF_Decoder_ + { + CFF_Builder builder; + CFF_Font cff; + + FT_Fixed stack[CFF_MAX_OPERANDS + 1]; + FT_Fixed* top; + + CFF_Decoder_Zone zones[CFF_MAX_SUBRS_CALLS + 1]; + CFF_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + FT_Pos glyph_width; + FT_Pos nominal_width; + + FT_Bool read_width; + FT_Int num_hints; + FT_Fixed* buildchar; + FT_Int len_buildchar; + + FT_UInt num_locals; + FT_UInt num_globals; + + FT_Int locals_bias; + FT_Int globals_bias; + + FT_Byte** locals; + FT_Byte** globals; + + FT_Byte** glyph_names; /* for pure CFF fonts only */ + FT_UInt num_glyphs; /* number of glyphs in font */ + + FT_Render_Mode hint_mode; + + } CFF_Decoder; + + + FT_LOCAL( void ) + cff_decoder_init( CFF_Decoder* decoder, + TT_Face face, + CFF_Size size, + CFF_GlyphSlot slot, + FT_Bool hinting, + FT_Render_Mode hint_mode ); + + FT_LOCAL( void ) + cff_decoder_prepare( CFF_Decoder* decoder, + FT_UInt glyph_index ); + +#if 0 /* unused until we support pure CFF fonts */ + + /* Compute the maximum advance width of a font through quick parsing */ + FT_LOCAL( FT_Error ) + cff_compute_max_advance( TT_Face face, + FT_Int* max_advance ); + +#endif /* 0 */ + + FT_LOCAL( FT_Error ) + cff_decoder_parse_charstrings( CFF_Decoder* decoder, + FT_Byte* charstring_base, + FT_ULong charstring_len ); + + FT_LOCAL( FT_Error ) + cff_slot_load( CFF_GlyphSlot glyph, + CFF_Size size, + FT_Int glyph_index, + FT_Int32 load_flags ); + + +FT_END_HEADER + +#endif /* __CFFGLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffload.c b/Utilities/vtkfreetype/src/cff/cffload.c new file mode 100644 index 0000000..350e01f --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffload.c @@ -0,0 +1,2313 @@ +/***************************************************************************/ +/* */ +/* cffload.c */ +/* */ +/* OpenType and CFF data/program tables loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_STREAM_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_TRUETYPE_TAGS_H + +#include "cffload.h" +#include "cffparse.h" + +#include "cfferrs.h" + + +#if 1 + static const FT_UShort cff_isoadobe_charset[229] = + { + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228 + }; + + static const FT_UShort cff_expert_charset[166] = + { + 0, + 1, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 13, + 14, + 15, + 99, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 27, + 28, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 109, + 110, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 158, + 155, + 163, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 150, + 164, + 169, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378 + }; + + static const FT_UShort cff_expertsubset_charset[87] = + { + 0, + 1, + 231, + 232, + 235, + 236, + 237, + 238, + 13, + 14, + 15, + 99, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 27, + 28, + 249, + 250, + 251, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 109, + 110, + 267, + 268, + 269, + 270, + 272, + 300, + 301, + 302, + 305, + 314, + 315, + 158, + 155, + 163, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 150, + 164, + 169, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346 + }; + + static const FT_UShort cff_standard_encoding[256] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 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, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 0, + 111, + 112, + 113, + 114, + 0, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 0, + 123, + 0, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 0, + 132, + 133, + 0, + 134, + 135, + 136, + 137, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 138, + 0, + 139, + 0, + 0, + 0, + 0, + 140, + 141, + 142, + 143, + 0, + 0, + 0, + 0, + 0, + 144, + 0, + 0, + 0, + 145, + 0, + 0, + 146, + 147, + 148, + 149, + 0, + 0, + 0, + 0 + }; + + static const FT_UShort cff_expert_encoding[256] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 229, + 230, + 0, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 13, + 14, + 15, + 99, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 27, + 28, + 249, + 250, + 251, + 252, + 0, + 253, + 254, + 255, + 256, + 257, + 0, + 0, + 0, + 258, + 0, + 0, + 259, + 260, + 261, + 262, + 0, + 0, + 263, + 264, + 265, + 0, + 266, + 109, + 110, + 267, + 268, + 269, + 0, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 304, + 305, + 306, + 0, + 0, + 307, + 308, + 309, + 310, + 311, + 0, + 312, + 0, + 0, + 312, + 0, + 0, + 314, + 315, + 0, + 0, + 316, + 317, + 318, + 0, + 0, + 0, + 158, + 155, + 163, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 0, + 0, + 326, + 150, + 164, + 169, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378 + }; +#endif + + + FT_LOCAL_DEF( FT_UShort ) + cff_get_standard_encoding( FT_UInt charcode ) + { + return (FT_UShort)(charcode < 256 ? cff_standard_encoding[charcode] : 0); + } + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cffload + + + /* read a CFF offset from memory */ + static FT_ULong + cff_get_offset( FT_Byte* p, + FT_Byte off_size ) + { + FT_ULong result; + + + for ( result = 0; off_size > 0; off_size-- ) + { + result <<= 8; + result |= *p++; + } + + return result; + } + + + static FT_Error + cff_new_index( CFF_Index idx, + FT_Stream stream, + FT_Bool load ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_UShort count; + + + FT_MEM_ZERO( idx, sizeof ( *idx ) ); + + idx->stream = stream; + if ( !FT_READ_USHORT( count ) && + count > 0 ) + { + FT_Byte* p; + FT_Byte offsize; + FT_ULong data_size; + FT_ULong* poff; + + + /* there is at least one element; read the offset size, */ + /* then access the offset table to compute the index's total size */ + if ( FT_READ_BYTE( offsize ) ) + goto Exit; + + idx->stream = stream; + idx->count = count; + idx->off_size = offsize; + data_size = (FT_ULong)( count + 1 ) * offsize; + + if ( FT_NEW_ARRAY( idx->offsets, count + 1 ) || + FT_FRAME_ENTER( data_size ) ) + goto Exit; + + poff = idx->offsets; + p = (FT_Byte*)stream->cursor; + + for ( ; (FT_Short)count >= 0; count-- ) + { + poff[0] = cff_get_offset( p, offsize ); + poff++; + p += offsize; + } + + FT_FRAME_EXIT(); + + idx->data_offset = FT_STREAM_POS(); + data_size = poff[-1] - 1; + + if ( load ) + { + /* load the data */ + if ( FT_FRAME_EXTRACT( data_size, idx->bytes ) ) + goto Exit; + } + else + { + /* skip the data */ + if ( FT_STREAM_SKIP( data_size ) ) + goto Exit; + } + } + + Exit: + if ( error ) + FT_FREE( idx->offsets ); + + return error; + } + + + static void + cff_done_index( CFF_Index idx ) + { + if ( idx->stream ) + { + FT_Stream stream = idx->stream; + FT_Memory memory = stream->memory; + + + if ( idx->bytes ) + FT_FRAME_RELEASE( idx->bytes ); + + FT_FREE( idx->offsets ); + FT_MEM_ZERO( idx, sizeof ( *idx ) ); + } + } + + + /* allocate a table containing pointers to an index's elements */ + static FT_Error + cff_index_get_pointers( CFF_Index idx, + FT_Byte*** table ) + { + FT_Error error = CFF_Err_Ok; + FT_Memory memory = idx->stream->memory; + FT_ULong n, offset, old_offset; + FT_Byte** t; + + + *table = 0; + + if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) ) + { + old_offset = 1; + for ( n = 0; n <= idx->count; n++ ) + { + offset = idx->offsets[n]; + if ( !offset ) + offset = old_offset; + + t[n] = idx->bytes + offset - 1; + + old_offset = offset; + } + *table = t; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + cff_index_access_element( CFF_Index idx, + FT_UInt element, + FT_Byte** pbytes, + FT_ULong* pbyte_len ) + { + FT_Error error = CFF_Err_Ok; + + + if ( idx && idx->count > element ) + { + /* compute start and end offsets */ + FT_ULong off1, off2 = 0; + + + off1 = idx->offsets[element]; + if ( off1 ) + { + do + { + element++; + off2 = idx->offsets[element]; + + } while ( off2 == 0 && element < idx->count ); + + if ( !off2 ) + off1 = 0; + } + + /* access element */ + if ( off1 ) + { + *pbyte_len = off2 - off1; + + if ( idx->bytes ) + { + /* this index was completely loaded in memory, that's easy */ + *pbytes = idx->bytes + off1 - 1; + } + else + { + /* this index is still on disk/file, access it through a frame */ + FT_Stream stream = idx->stream; + + + if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) || + FT_FRAME_EXTRACT( off2 - off1, *pbytes ) ) + goto Exit; + } + } + else + { + /* empty index element */ + *pbytes = 0; + *pbyte_len = 0; + } + } + else + error = CFF_Err_Invalid_Argument; + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + cff_index_forget_element( CFF_Index idx, + FT_Byte** pbytes ) + { + if ( idx->bytes == 0 ) + { + FT_Stream stream = idx->stream; + + + FT_FRAME_RELEASE( *pbytes ); + } + } + + + FT_LOCAL_DEF( FT_String* ) + cff_index_get_name( CFF_Index idx, + FT_UInt element ) + { + FT_Memory memory = idx->stream->memory; + FT_Byte* bytes; + FT_ULong byte_len; + FT_Error error; + FT_String* name = 0; + + + error = cff_index_access_element( idx, element, &bytes, &byte_len ); + if ( error ) + goto Exit; + + if ( !FT_ALLOC( name, byte_len + 1 ) ) + { + FT_MEM_COPY( name, bytes, byte_len ); + name[byte_len] = 0; + } + cff_index_forget_element( idx, &bytes ); + + Exit: + return name; + } + + + FT_LOCAL_DEF( FT_String* ) + cff_index_get_sid_string( CFF_Index idx, + FT_UInt sid, + FT_Service_PsCMaps psnames ) + { + /* value 0xFFFFU indicates a missing dictionary entry */ + if ( sid == 0xFFFFU ) + return 0; + + /* if it is not a standard string, return it */ + if ( sid > 390 ) + return cff_index_get_name( idx, sid - 391 ); + + /* CID-keyed CFF fonts don't have glyph names */ + if ( !psnames ) + return 0; + + /* that's a standard string, fetch a copy from the PSName module */ + { + FT_String* name = 0; + const char* adobe_name = psnames->adobe_std_strings( sid ); + FT_UInt len; + + + if ( adobe_name ) + { + FT_Memory memory = idx->stream->memory; + FT_Error error; + + + len = (FT_UInt)ft_strlen( adobe_name ); + if ( !FT_ALLOC( name, len + 1 ) ) + { + FT_MEM_COPY( name, adobe_name, len ); + name[len] = 0; + } + + FT_UNUSED( error ); + } + + return name; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** FD Select table support ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + + + static void + CFF_Done_FD_Select( CFF_FDSelect fdselect, + FT_Stream stream ) + { + if ( fdselect->data ) + FT_FRAME_RELEASE( fdselect->data ); + + fdselect->data_size = 0; + fdselect->format = 0; + fdselect->range_count = 0; + } + + + static FT_Error + CFF_Load_FD_Select( CFF_FDSelect fdselect, + FT_UInt num_glyphs, + FT_Stream stream, + FT_ULong offset ) + { + FT_Error error; + FT_Byte format; + FT_UInt num_ranges; + + + /* read format */ + if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) ) + goto Exit; + + fdselect->format = format; + fdselect->cache_count = 0; /* clear cache */ + + switch ( format ) + { + case 0: /* format 0, that's simple */ + fdselect->data_size = num_glyphs; + goto Load_Data; + + case 3: /* format 3, a tad more complex */ + if ( FT_READ_USHORT( num_ranges ) ) + goto Exit; + + fdselect->data_size = num_ranges * 3 + 2; + + Load_Data: + if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) ) + goto Exit; + break; + + default: /* hmm... that's wrong */ + error = CFF_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Byte ) + cff_fd_select_get( CFF_FDSelect fdselect, + FT_UInt glyph_index ) + { + FT_Byte fd = 0; + + + switch ( fdselect->format ) + { + case 0: + fd = fdselect->data[glyph_index]; + break; + + case 3: + /* first, compare to cache */ + if ( (FT_UInt)( glyph_index - fdselect->cache_first ) < + fdselect->cache_count ) + { + fd = fdselect->cache_fd; + break; + } + + /* then, lookup the ranges array */ + { + FT_Byte* p = fdselect->data; + FT_Byte* p_limit = p + fdselect->data_size; + FT_Byte fd2; + FT_UInt first, limit; + + + first = FT_NEXT_USHORT( p ); + do + { + if ( glyph_index < first ) + break; + + fd2 = *p++; + limit = FT_NEXT_USHORT( p ); + + if ( glyph_index < limit ) + { + fd = fd2; + + /* update cache */ + fdselect->cache_first = first; + fdselect->cache_count = limit-first; + fdselect->cache_fd = fd2; + break; + } + first = limit; + + } while ( p < p_limit ); + } + break; + + default: + ; + } + + return fd; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** CFF font support ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + + static void + cff_charset_done( CFF_Charset charset, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + + + FT_FREE( charset->sids ); + FT_FREE( charset->cids ); + charset->format = 0; + charset->offset = 0; + } + + + static FT_Error + cff_charset_load( CFF_Charset charset, + FT_UInt num_glyphs, + FT_Stream stream, + FT_ULong base_offset, + FT_ULong offset, + FT_Bool invert ) + { + FT_Memory memory = stream->memory; + FT_Error error = CFF_Err_Ok; + FT_UShort glyph_sid; + + + /* If the the offset is greater than 2, we have to parse the */ + /* charset table. */ + if ( offset > 2 ) + { + FT_UInt j; + + + charset->offset = base_offset + offset; + + /* Get the format of the table. */ + if ( FT_STREAM_SEEK( charset->offset ) || + FT_READ_BYTE( charset->format ) ) + goto Exit; + + /* Allocate memory for sids. */ + if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + goto Exit; + + /* assign the .notdef glyph */ + charset->sids[0] = 0; + + switch ( charset->format ) + { + case 0: + if ( num_glyphs > 0 ) + { + if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) ) + goto Exit; + + for ( j = 1; j < num_glyphs; j++ ) + charset->sids[j] = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + } + break; + + case 1: + case 2: + { + FT_UInt nleft; + FT_UInt i; + + + j = 1; + + while ( j < num_glyphs ) + { + /* Read the first glyph sid of the range. */ + if ( FT_READ_USHORT( glyph_sid ) ) + goto Exit; + + /* Read the number of glyphs in the range. */ + if ( charset->format == 2 ) + { + if ( FT_READ_USHORT( nleft ) ) + goto Exit; + } + else + { + if ( FT_READ_BYTE( nleft ) ) + goto Exit; + } + + /* Fill in the range of sids -- `nleft + 1' glyphs. */ + for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ ) + charset->sids[j] = glyph_sid; + } + } + break; + + default: + FT_ERROR(( "cff_charset_load: invalid table format!\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + } + else + { + /* Parse default tables corresponding to offset == 0, 1, or 2. */ + /* CFF specification intimates the following: */ + /* */ + /* In order to use a predefined charset, the following must be */ + /* true: The charset constructed for the glyphs in the font's */ + /* charstrings dictionary must match the predefined charset in */ + /* the first num_glyphs. */ + + charset->offset = offset; /* record charset type */ + + switch ( (FT_UInt)offset ) + { + case 0: + if ( num_glyphs > 229 ) + { + FT_ERROR(( "cff_charset_load: implicit charset larger than\n" + "predefined charset (Adobe ISO-Latin)!\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + + /* Allocate memory for sids. */ + if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + goto Exit; + + /* Copy the predefined charset into the allocated memory. */ + FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs ); + + break; + + case 1: + if ( num_glyphs > 166 ) + { + FT_ERROR(( "cff_charset_load: implicit charset larger than\n" + "predefined charset (Adobe Expert)!\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + + /* Allocate memory for sids. */ + if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + goto Exit; + + /* Copy the predefined charset into the allocated memory. */ + FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs ); + + break; + + case 2: + if ( num_glyphs > 87 ) + { + FT_ERROR(( "cff_charset_load: implicit charset larger than\n" + "predefined charset (Adobe Expert Subset)!\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + + /* Allocate memory for sids. */ + if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) ) + goto Exit; + + /* Copy the predefined charset into the allocated memory. */ + FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs ); + + break; + + default: + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + } + + /* we have to invert the `sids' array for subsetted CID-keyed fonts */ + if ( invert ) + { + FT_UInt i; + FT_UShort max_cid = 0; + + + for ( i = 0; i < num_glyphs; i++ ) + if ( charset->sids[i] > max_cid ) + max_cid = charset->sids[i]; + max_cid++; + + if ( FT_NEW_ARRAY( charset->cids, max_cid ) ) + goto Exit; + FT_MEM_ZERO( charset->cids, sizeof ( FT_UShort ) * max_cid ); + + for ( i = 0; i < num_glyphs; i++ ) + charset->cids[charset->sids[i]] = i; + } + + Exit: + /* Clean up if there was an error. */ + if ( error ) + { + FT_FREE( charset->sids ); + FT_FREE( charset->cids ); + charset->format = 0; + charset->offset = 0; + charset->sids = 0; + } + + return error; + } + + + static void + cff_encoding_done( CFF_Encoding encoding ) + { + encoding->format = 0; + encoding->offset = 0; + encoding->count = 0; + } + + + static FT_Error + cff_encoding_load( CFF_Encoding encoding, + CFF_Charset charset, + FT_UInt num_glyphs, + FT_Stream stream, + FT_ULong base_offset, + FT_ULong offset ) + { + FT_Error error = CFF_Err_Ok; + FT_UInt count; + FT_UInt j; + FT_UShort glyph_sid; + FT_UInt glyph_code; + + + /* Check for charset->sids. If we do not have this, we fail. */ + if ( !charset->sids ) + { + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + + /* Zero out the code to gid/sid mappings. */ + for ( j = 0; j < 256; j++ ) + { + encoding->sids [j] = 0; + encoding->codes[j] = 0; + } + + /* Note: The encoding table in a CFF font is indexed by glyph index; */ + /* the first encoded glyph index is 1. Hence, we read the character */ + /* code (`glyph_code') at index j and make the assignment: */ + /* */ + /* encoding->codes[glyph_code] = j + 1 */ + /* */ + /* We also make the assignment: */ + /* */ + /* encoding->sids[glyph_code] = charset->sids[j + 1] */ + /* */ + /* This gives us both a code to GID and a code to SID mapping. */ + + if ( offset > 1 ) + { + encoding->offset = base_offset + offset; + + /* we need to parse the table to determine its size */ + if ( FT_STREAM_SEEK( encoding->offset ) || + FT_READ_BYTE( encoding->format ) || + FT_READ_BYTE( count ) ) + goto Exit; + + switch ( encoding->format & 0x7F ) + { + case 0: + { + FT_Byte* p; + + + /* By convention, GID 0 is always ".notdef" and is never */ + /* coded in the font. Hence, the number of codes found */ + /* in the table is `count+1'. */ + /* */ + encoding->count = count + 1; + + if ( FT_FRAME_ENTER( count ) ) + goto Exit; + + p = (FT_Byte*)stream->cursor; + + for ( j = 1; j <= count; j++ ) + { + glyph_code = *p++; + + /* Make sure j is not too big. */ + if ( j < num_glyphs ) + { + /* Assign code to GID mapping. */ + encoding->codes[glyph_code] = (FT_UShort)j; + + /* Assign code to SID mapping. */ + encoding->sids[glyph_code] = charset->sids[j]; + } + } + + FT_FRAME_EXIT(); + } + break; + + case 1: + { + FT_UInt nleft; + FT_UInt i = 1; + FT_UInt k; + + + encoding->count = 0; + + /* Parse the Format1 ranges. */ + for ( j = 0; j < count; j++, i += nleft ) + { + /* Read the first glyph code of the range. */ + if ( FT_READ_BYTE( glyph_code ) ) + goto Exit; + + /* Read the number of codes in the range. */ + if ( FT_READ_BYTE( nleft ) ) + goto Exit; + + /* Increment nleft, so we read `nleft + 1' codes/sids. */ + nleft++; + + /* compute max number of character codes */ + if ( (FT_UInt)nleft > encoding->count ) + encoding->count = nleft; + + /* Fill in the range of codes/sids. */ + for ( k = i; k < nleft + i; k++, glyph_code++ ) + { + /* Make sure k is not too big. */ + if ( k < num_glyphs && glyph_code < 256 ) + { + /* Assign code to GID mapping. */ + encoding->codes[glyph_code] = (FT_UShort)k; + + /* Assign code to SID mapping. */ + encoding->sids[glyph_code] = charset->sids[k]; + } + } + } + + /* simple check; one never knows what can be found in a font */ + if ( encoding->count > 256 ) + encoding->count = 256; + } + break; + + default: + FT_ERROR(( "cff_encoding_load: invalid table format!\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + + /* Parse supplemental encodings, if any. */ + if ( encoding->format & 0x80 ) + { + FT_UInt gindex; + + + /* count supplements */ + if ( FT_READ_BYTE( count ) ) + goto Exit; + + for ( j = 0; j < count; j++ ) + { + /* Read supplemental glyph code. */ + if ( FT_READ_BYTE( glyph_code ) ) + goto Exit; + + /* Read the SID associated with this glyph code. */ + if ( FT_READ_USHORT( glyph_sid ) ) + goto Exit; + + /* Assign code to SID mapping. */ + encoding->sids[glyph_code] = glyph_sid; + + /* First, look up GID which has been assigned to */ + /* SID glyph_sid. */ + for ( gindex = 0; gindex < num_glyphs; gindex++ ) + { + if ( charset->sids[gindex] == glyph_sid ) + { + encoding->codes[glyph_code] = (FT_UShort)gindex; + break; + } + } + } + } + } + else + { + FT_UInt i; + + + /* We take into account the fact a CFF font can use a predefined */ + /* encoding without containing all of the glyphs encoded by this */ + /* encoding (see the note at the end of section 12 in the CFF */ + /* specification). */ + + switch ( (FT_UInt)offset ) + { + case 0: + /* First, copy the code to SID mapping. */ + FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 ); + goto Populate; + + case 1: + /* First, copy the code to SID mapping. */ + FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 ); + + Populate: + /* Construct code to GID mapping from code to SID mapping */ + /* and charset. */ + + encoding->count = 0; + + for ( j = 0; j < 256; j++ ) + { + /* If j is encoded, find the GID for it. */ + if ( encoding->sids[j] ) + { + for ( i = 1; i < num_glyphs; i++ ) + /* We matched, so break. */ + if ( charset->sids[i] == encoding->sids[j] ) + break; + + /* i will be equal to num_glyphs if we exited the above */ + /* loop without a match. In this case, we also have to */ + /* fix the code to SID mapping. */ + if ( i == num_glyphs ) + { + encoding->codes[j] = 0; + encoding->sids [j] = 0; + } + else + { + encoding->codes[j] = (FT_UShort)i; + + /* update encoding count */ + if ( encoding->count < j + 1 ) + encoding->count = j + 1; + } + } + } + break; + + default: + FT_ERROR(( "cff_encoding_load: invalid table format!\n" )); + error = CFF_Err_Invalid_File_Format; + goto Exit; + } + } + + Exit: + + /* Clean up if there was an error. */ + return error; + } + + + static FT_Error + cff_subfont_load( CFF_SubFont font, + CFF_Index idx, + FT_UInt font_index, + FT_Stream stream, + FT_ULong base_offset ) + { + FT_Error error; + CFF_ParserRec parser; + FT_Byte* dict = NULL; + FT_ULong dict_len; + CFF_FontRecDict top = &font->font_dict; + CFF_Private priv = &font->private_dict; + + + cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict ); + + /* set defaults */ + FT_MEM_ZERO( top, sizeof ( *top ) ); + + top->underline_position = -100L << 16; + top->underline_thickness = 50L << 16; + top->charstring_type = 2; + top->font_matrix.xx = 0x10000L; + top->font_matrix.yy = 0x10000L; + top->cid_count = 8720; + + /* we use the implementation specific SID value 0xFFFF to indicate */ + /* missing entries */ + top->version = 0xFFFFU; + top->notice = 0xFFFFU; + top->copyright = 0xFFFFU; + top->full_name = 0xFFFFU; + top->family_name = 0xFFFFU; + top->weight = 0xFFFFU; + top->embedded_postscript = 0xFFFFU; + + top->cid_registry = 0xFFFFU; + top->cid_ordering = 0xFFFFU; + top->cid_font_name = 0xFFFFU; + + error = cff_index_access_element( idx, font_index, &dict, &dict_len ) || + cff_parser_run( &parser, dict, dict + dict_len ); + + cff_index_forget_element( idx, &dict ); + + if ( error ) + goto Exit; + + /* if it is a CID font, we stop there */ + if ( top->cid_registry != 0xFFFFU ) + goto Exit; + + /* parse the private dictionary, if any */ + if ( top->private_offset && top->private_size ) + { + /* set defaults */ + FT_MEM_ZERO( priv, sizeof ( *priv ) ); + + priv->blue_shift = 7; + priv->blue_fuzz = 1; + priv->lenIV = -1; + priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); + priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); + + cff_parser_init( &parser, CFF_CODE_PRIVATE, priv ); + + if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) || + FT_FRAME_ENTER( font->font_dict.private_size ) ) + goto Exit; + + error = cff_parser_run( &parser, + (FT_Byte*)stream->cursor, + (FT_Byte*)stream->limit ); + FT_FRAME_EXIT(); + if ( error ) + goto Exit; + } + + /* read the local subrs, if any */ + if ( priv->local_subrs_offset ) + { + if ( FT_STREAM_SEEK( base_offset + top->private_offset + + priv->local_subrs_offset ) ) + goto Exit; + + error = cff_new_index( &font->local_subrs_index, stream, 1 ); + if ( error ) + goto Exit; + + font->num_local_subrs = font->local_subrs_index.count; + error = cff_index_get_pointers( &font->local_subrs_index, + &font->local_subrs ); + if ( error ) + goto Exit; + } + + Exit: + return error; + } + + + static void + cff_subfont_done( FT_Memory memory, + CFF_SubFont subfont ) + { + if ( subfont ) + { + cff_done_index( &subfont->local_subrs_index ); + FT_FREE( subfont->local_subrs ); + } + } + + + FT_LOCAL_DEF( FT_Error ) + cff_font_load( FT_Stream stream, + FT_Int face_index, + CFF_Font font ) + { + static const FT_Frame_Field cff_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE CFF_FontRec + + FT_FRAME_START( 4 ), + FT_FRAME_BYTE( version_major ), + FT_FRAME_BYTE( version_minor ), + FT_FRAME_BYTE( header_size ), + FT_FRAME_BYTE( absolute_offsize ), + FT_FRAME_END + }; + + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong base_offset; + CFF_FontRecDict dict; + + FT_ZERO( font ); + + font->stream = stream; + font->memory = memory; + dict = &font->top_font.font_dict; + base_offset = FT_STREAM_POS(); + + /* read CFF font header */ + if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) ) + goto Exit; + + /* check format */ + if ( font->version_major != 1 || + font->header_size < 4 || + font->absolute_offsize > 4 ) + { + FT_TRACE2(( "[not a CFF font header!]\n" )); + error = CFF_Err_Unknown_File_Format; + goto Exit; + } + + /* skip the rest of the header */ + if ( FT_STREAM_SKIP( font->header_size - 4 ) ) + goto Exit; + + /* read the name, top dict, string and global subrs index */ + if ( FT_SET_ERROR( cff_new_index( &font->name_index, stream, 0 )) || + FT_SET_ERROR( cff_new_index( &font->font_dict_index, stream, 0 )) || + FT_SET_ERROR( cff_new_index( &font->string_index, stream, 0 )) || + FT_SET_ERROR( cff_new_index( &font->global_subrs_index, stream, 1 )) ) + goto Exit; + + /* well, we don't really forget the `disabled' fonts... */ + font->num_faces = font->name_index.count; + if ( face_index >= (FT_Int)font->num_faces ) + { + FT_ERROR(( "cff_font_load: incorrect face index = %d\n", + face_index )); + error = CFF_Err_Invalid_Argument; + } + + /* in case of a font format check, simply exit now */ + if ( face_index < 0 ) + goto Exit; + + /* now, parse the top-level font dictionary */ + error = cff_subfont_load( &font->top_font, + &font->font_dict_index, + face_index, + stream, + base_offset ); + if ( error ) + goto Exit; + + if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) ) + goto Exit; + + error = cff_new_index( &font->charstrings_index, stream, 0 ); + if ( error ) + goto Exit; + + /* now, check for a CID font */ + if ( dict->cid_registry != 0xFFFFU ) + { + CFF_IndexRec fd_index; + CFF_SubFont sub; + FT_UInt idx; + + + /* this is a CID-keyed font, we must now allocate a table of */ + /* sub-fonts, then load each of them separately */ + if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) ) + goto Exit; + + error = cff_new_index( &fd_index, stream, 0 ); + if ( error ) + goto Exit; + + if ( fd_index.count > CFF_MAX_CID_FONTS ) + { + FT_ERROR(( "cff_font_load: FD array too large in CID font\n" )); + goto Fail_CID; + } + + /* allocate & read each font dict independently */ + font->num_subfonts = fd_index.count; + if ( FT_NEW_ARRAY( sub, fd_index.count ) ) + goto Fail_CID; + + /* setup pointer table */ + for ( idx = 0; idx < fd_index.count; idx++ ) + font->subfonts[idx] = sub + idx; + + /* now load each sub font independently */ + for ( idx = 0; idx < fd_index.count; idx++ ) + { + sub = font->subfonts[idx]; + error = cff_subfont_load( sub, &fd_index, idx, + stream, base_offset ); + if ( error ) + goto Fail_CID; + } + + /* now load the FD Select array */ + error = CFF_Load_FD_Select( &font->fd_select, + font->charstrings_index.count, + stream, + base_offset + dict->cid_fd_select_offset ); + + Fail_CID: + cff_done_index( &fd_index ); + + if ( error ) + goto Exit; + } + else + font->num_subfonts = 0; + + /* read the charstrings index now */ + if ( dict->charstrings_offset == 0 ) + { + FT_ERROR(( "cff_font_load: no charstrings offset!\n" )); + error = CFF_Err_Unknown_File_Format; + goto Exit; + } + + /* explicit the global subrs */ + font->num_global_subrs = font->global_subrs_index.count; + font->num_glyphs = font->charstrings_index.count; + + error = cff_index_get_pointers( &font->global_subrs_index, + &font->global_subrs ) ; + + if ( error ) + goto Exit; + + /* read the Charset and Encoding tables if available */ + if ( font->num_glyphs > 0 ) + { + FT_Bool invert; + + + invert = dict->cid_registry != 0xFFFFU && + font->charstrings_index.count != dict->cid_count; + error = cff_charset_load( &font->charset, font->num_glyphs, stream, + base_offset, dict->charset_offset, invert ); + if ( error ) + goto Exit; + + /* CID-keyed CFFs don't have an encoding */ + if ( dict->cid_registry == 0xFFFFU ) + { + error = cff_encoding_load( &font->encoding, + &font->charset, + font->num_glyphs, + stream, + base_offset, + dict->encoding_offset ); + if ( error ) + goto Exit; + } + else + /* CID-keyed fonts only need CIDs */ + FT_FREE( font->charset.sids ); + } + + /* get the font name (/CIDFontName for CID-keyed fonts, */ + /* /FontName otherwise) */ + font->font_name = cff_index_get_name( &font->name_index, face_index ); + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + cff_font_done( CFF_Font font ) + { + FT_Memory memory = font->memory; + FT_UInt idx; + + + cff_done_index( &font->global_subrs_index ); + cff_done_index( &font->string_index ); + cff_done_index( &font->font_dict_index ); + cff_done_index( &font->name_index ); + cff_done_index( &font->charstrings_index ); + + /* release font dictionaries, but only if working with */ + /* a CID keyed CFF font */ + if ( font->num_subfonts > 0 ) + { + for ( idx = 0; idx < font->num_subfonts; idx++ ) + cff_subfont_done( memory, font->subfonts[idx] ); + + FT_FREE( font->subfonts ); + } + + cff_encoding_done( &font->encoding ); + cff_charset_done( &font->charset, font->stream ); + + cff_subfont_done( memory, &font->top_font ); + + CFF_Done_FD_Select( &font->fd_select, font->stream ); + + FT_FREE( font->global_subrs ); + FT_FREE( font->font_name ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffload.h b/Utilities/vtkfreetype/src/cff/cffload.h new file mode 100644 index 0000000..ccf8ada --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffload.h @@ -0,0 +1,74 @@ +/***************************************************************************/ +/* */ +/* cffload.h */ +/* */ +/* OpenType & CFF data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CFFLOAD_H__ +#define __CFFLOAD_H__ + + +#include <ft2build.h> +#include "cfftypes.h" +#include FT_SERVICE_POSTSCRIPT_CMAPS_H + + +FT_BEGIN_HEADER + + FT_LOCAL( FT_UShort ) + cff_get_standard_encoding( FT_UInt charcode ); + + + FT_LOCAL( FT_String* ) + cff_index_get_name( CFF_Index idx, + FT_UInt element ); + + FT_LOCAL( FT_String* ) + cff_index_get_sid_string( CFF_Index idx, + FT_UInt sid, + FT_Service_PsCMaps psnames ); + + + FT_LOCAL( FT_Error ) + cff_index_access_element( CFF_Index idx, + FT_UInt element, + FT_Byte** pbytes, + FT_ULong* pbyte_len ); + + FT_LOCAL( void ) + cff_index_forget_element( CFF_Index idx, + FT_Byte** pbytes ); + + + FT_LOCAL( FT_Error ) + cff_font_load( FT_Stream stream, + FT_Int face_index, + CFF_Font font ); + + FT_LOCAL( void ) + cff_font_done( CFF_Font font ); + + + FT_LOCAL( FT_Byte ) + cff_fd_select_get( CFF_FDSelect fdselect, + FT_UInt glyph_index ); + + +FT_END_HEADER + +#endif /* __CFFLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffobjs.c b/Utilities/vtkfreetype/src/cff/cffobjs.c new file mode 100644 index 0000000..ec4d1e4 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffobjs.c @@ -0,0 +1,775 @@ +/***************************************************************************/ +/* */ +/* cffobjs.c */ +/* */ +/* OpenType objects manager (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_STREAM_H +#include FT_ERRORS_H +#include FT_TRUETYPE_IDS_H +#include FT_TRUETYPE_TAGS_H +#include FT_INTERNAL_SFNT_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H +#include "cffobjs.h" +#include "cffload.h" +#include "cffcmap.h" +#include "cfferrs.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cffobjs + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /* Note that we store the global hints in the size's `internal' root */ + /* field. */ + /* */ + /*************************************************************************/ + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + static FT_Error + sbit_size_reset( CFF_Size size ) + { + CFF_Face face; + FT_Error error = CFF_Err_Ok; + + FT_ULong strike_index; + FT_Size_Metrics* metrics; + FT_Size_Metrics* sbit_metrics; + SFNT_Service sfnt; + + + metrics = &size->root.metrics; + + face = (CFF_Face)size->root.face; + sfnt = (SFNT_Service)face->sfnt; + + sbit_metrics = &size->strike_metrics; + + error = sfnt->set_sbit_strike( face, + metrics->x_ppem, metrics->y_ppem, + &strike_index ); + + if ( !error ) + { + TT_SBit_Strike strike = face->sbit_strikes + strike_index; + + + sbit_metrics->x_ppem = metrics->x_ppem; + sbit_metrics->y_ppem = metrics->y_ppem; + + sbit_metrics->ascender = strike->hori.ascender << 6; + sbit_metrics->descender = strike->hori.descender << 6; + + /* XXX: Is this correct? */ + sbit_metrics->height = sbit_metrics->ascender - + sbit_metrics->descender; + + /* XXX: Is this correct? */ + sbit_metrics->max_advance = ( strike->hori.min_origin_SB + + strike->hori.max_width + + strike->hori.min_advance_SB ) << 6; + + size->strike_index = (FT_UInt)strike_index; + } + else + { + size->strike_index = 0xFFFFU; + + sbit_metrics->x_ppem = 0; + sbit_metrics->y_ppem = 0; + sbit_metrics->ascender = 0; + sbit_metrics->descender = 0; + sbit_metrics->height = 0; + sbit_metrics->max_advance = 0; + } + + return error; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + + static PSH_Globals_Funcs + cff_size_get_globals_funcs( CFF_Size size ) + { + CFF_Face face = (CFF_Face)size->root.face; + CFF_Font font = (CFF_FontRec *)face->extra.data; + PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; + FT_Module module; + + + module = FT_Get_Module( size->root.face->driver->root.library, + "pshinter" ); + return ( module && pshinter && pshinter->get_globals_funcs ) + ? pshinter->get_globals_funcs( module ) + : 0; + } + + + FT_LOCAL_DEF( void ) + cff_size_done( FT_Size cffsize ) /* CFF_Size */ + { + CFF_Size size = (CFF_Size)cffsize; + + + if ( cffsize->internal ) + { + PSH_Globals_Funcs funcs; + + + funcs = cff_size_get_globals_funcs( size ); + if ( funcs ) + funcs->destroy( (PSH_Globals)cffsize->internal ); + + cffsize->internal = 0; + } + } + + + FT_LOCAL_DEF( FT_Error ) + cff_size_init( FT_Size cffsize ) /* CFF_Size */ + { + CFF_Size size = (CFF_Size)cffsize; + FT_Error error = CFF_Err_Ok; + PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); + + + if ( funcs ) + { + PSH_Globals globals; + CFF_Face face = (CFF_Face)cffsize->face; + CFF_Font font = (CFF_FontRec *)face->extra.data; + CFF_SubFont subfont = &font->top_font; + + CFF_Private cpriv = &subfont->private_dict; + PS_PrivateRec priv; + + + /* IMPORTANT: The CFF and Type1 private dictionaries have */ + /* slightly different structures; we need to */ + /* synthetize a type1 dictionary on the fly here. */ + + { + FT_UInt n, count; + + + FT_MEM_ZERO( &priv, sizeof ( priv ) ); + + count = priv.num_blue_values = cpriv->num_blue_values; + for ( n = 0; n < count; n++ ) + priv.blue_values[n] = (FT_Short)cpriv->blue_values[n]; + + count = priv.num_other_blues = cpriv->num_other_blues; + for ( n = 0; n < count; n++ ) + priv.other_blues[n] = (FT_Short)cpriv->other_blues[n]; + + count = priv.num_family_blues = cpriv->num_family_blues; + for ( n = 0; n < count; n++ ) + priv.family_blues[n] = (FT_Short)cpriv->family_blues[n]; + + count = priv.num_family_other_blues = cpriv->num_family_other_blues; + for ( n = 0; n < count; n++ ) + priv.family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; + + priv.blue_scale = cpriv->blue_scale; + priv.blue_shift = (FT_Int)cpriv->blue_shift; + priv.blue_fuzz = (FT_Int)cpriv->blue_fuzz; + + priv.standard_width[0] = (FT_UShort)cpriv->standard_width; + priv.standard_height[0] = (FT_UShort)cpriv->standard_height; + + count = priv.num_snap_widths = cpriv->num_snap_widths; + for ( n = 0; n < count; n++ ) + priv.snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; + + count = priv.num_snap_heights = cpriv->num_snap_heights; + for ( n = 0; n < count; n++ ) + priv.snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; + + priv.force_bold = cpriv->force_bold; + priv.language_group = cpriv->language_group; + priv.lenIV = cpriv->lenIV; + } + + error = funcs->create( cffsize->face->memory, &priv, &globals ); + if ( !error ) + cffsize->internal = (FT_Size_Internal)(void*)globals; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + cff_size_reset( FT_Size cffsize, /* CFF_Size */ + FT_UInt char_width, + FT_UInt char_height ) + { + CFF_Size size = (CFF_Size)cffsize; + PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); + FT_Error error = CFF_Err_Ok; + FT_Face face = cffsize->face; + + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + + + if ( funcs ) + error = funcs->set_scale( (PSH_Globals)cffsize->internal, + cffsize->metrics.x_scale, + cffsize->metrics.y_scale, + 0, 0 ); + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) + { + error = sbit_size_reset( size ); + + if ( !error && !( face->face_flags & FT_FACE_FLAG_SCALABLE ) ) + cffsize->metrics = size->strike_metrics; + } + +#endif + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + return CFF_Err_Ok; + else + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + cff_point_size_reset( FT_Size cffsize, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + FT_UNUSED( horz_resolution ); + FT_UNUSED( vert_resolution ); + + return cff_size_reset( cffsize, 0, 0 ); + } + + + /*************************************************************************/ + /* */ + /* SLOT FUNCTIONS */ + /* */ + /*************************************************************************/ + + FT_LOCAL_DEF( void ) + cff_slot_done( FT_GlyphSlot slot ) + { + slot->internal->glyph_hints = 0; + } + + + FT_LOCAL_DEF( FT_Error ) + cff_slot_init( FT_GlyphSlot slot ) + { + CFF_Face face = (CFF_Face)slot->face; + CFF_Font font = (CFF_FontRec *)face->extra.data; + PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; + + + if ( pshinter ) + { + FT_Module module; + + + module = FT_Get_Module( slot->face->driver->root.library, + "pshinter" ); + if ( module ) + { + T2_Hints_Funcs funcs; + + + funcs = pshinter->get_t2_funcs( module ); + slot->internal->glyph_hints = (void*)funcs; + } + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + static FT_String* + cff_strcpy( FT_Memory memory, + const FT_String* source ) + { + FT_Error error; + FT_String* result = 0; + FT_Int len = (FT_Int)ft_strlen( source ); + + + if ( !FT_ALLOC( result, len + 1 ) ) + { + FT_MEM_COPY( result, source, len ); + result[len] = 0; + } + + FT_UNUSED( error ); + + return result; + } + + + FT_LOCAL_DEF( FT_Error ) + cff_face_init( FT_Stream stream, + FT_Face cffface, /* CFF_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + CFF_Face face = (CFF_Face)cffface; + FT_Error error; + SFNT_Service sfnt; + FT_Service_PsCMaps psnames; + PSHinter_Service pshinter; + FT_Bool pure_cff = 1; + FT_Bool sfnt_format = 0; + +#if 0 + FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt, SFNT ); + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_NAMES ); + FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER ); + + if ( !sfnt ) + goto Bad_Format; +#else + sfnt = (SFNT_Service)FT_Get_Module_Interface( + cffface->driver->root.library, "sfnt" ); + if ( !sfnt ) + goto Bad_Format; + + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); + + pshinter = (PSHinter_Service)FT_Get_Module_Interface( + cffface->driver->root.library, "pshinter" ); +#endif + + /* create input stream from resource */ + if ( FT_STREAM_SEEK( 0 ) ) + goto Exit; + + /* check whether we have a valid OpenType file */ + error = sfnt->init_face( stream, face, face_index, num_params, params ); + if ( !error ) + { + if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ + { + FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); + goto Bad_Format; + } + + /* if we are performing a simple font format check, exit immediately */ + if ( face_index < 0 ) + return CFF_Err_Ok; + + sfnt_format = 1; + + /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ + /* font; in the latter case it doesn't have a `head' table */ + error = face->goto_table( face, TTAG_head, stream, 0 ); + if ( !error ) + { + pure_cff = 0; + + /* load font directory */ + error = sfnt->load_face( stream, face, + face_index, num_params, params ); + if ( error ) + goto Exit; + } + else + { + /* load the `cmap' table explicitly */ + error = sfnt->load_charmaps( face, stream ); + if ( error ) + goto Exit; + + /* XXX: we don't load the GPOS table, as OpenType Layout */ + /* support will be added later to a layout library on top of */ + /* FreeType 2 */ + } + + /* now load the CFF part of the file */ + error = face->goto_table( face, TTAG_CFF, stream, 0 ); + if ( error ) + goto Exit; + } + else + { + /* rewind to start of file; we are going to load a pure-CFF font */ + if ( FT_STREAM_SEEK( 0 ) ) + goto Exit; + error = CFF_Err_Ok; + } + + /* now load and parse the CFF table in the file */ + { + CFF_Font cff; + CFF_FontRecDict dict; + FT_Memory memory = cffface->memory; + FT_Int32 flags; + + + if ( FT_NEW( cff ) ) + goto Exit; + + face->extra.data = cff; + error = cff_font_load( stream, face_index, cff ); + if ( error ) + goto Exit; + + cff->pshinter = pshinter; + cff->psnames = (void*)psnames; + + /* Complement the root flags with some interesting information. */ + /* Note that this is only necessary for pure CFF and CEF fonts. */ + + cffface->num_glyphs = cff->num_glyphs; + + dict = &cff->top_font.font_dict; + + /* we need the `PSNames' module for CFF and CEF formats */ + /* which aren't CID-keyed */ + if ( dict->cid_registry == 0xFFFFU && !psnames ) + { + FT_ERROR(( "cff_face_init:" )); + FT_ERROR(( " cannot open CFF & CEF fonts\n" )); + FT_ERROR(( " " )); + FT_ERROR(( " without the `PSNames' module\n" )); + goto Bad_Format; + } + + if ( pure_cff ) + { + char* style_name = NULL; + + + /* Set up num_faces. */ + cffface->num_faces = cff->num_faces; + + /* compute number of glyphs */ + if ( dict->cid_registry != 0xFFFFU ) + cffface->num_glyphs = dict->cid_count; + else + cffface->num_glyphs = cff->charstrings_index.count; + + /* set global bbox, as well as EM size */ + cffface->bbox.xMin = dict->font_bbox.xMin >> 16; + cffface->bbox.yMin = dict->font_bbox.yMin >> 16; + cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16; + cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16; + + cffface->ascender = (FT_Short)( cffface->bbox.yMax ); + cffface->descender = (FT_Short)( cffface->bbox.yMin ); + cffface->height = (FT_Short)( + ( ( cffface->ascender - cffface->descender ) * 12 ) / 10 ); + + if ( dict->units_per_em ) + cffface->units_per_EM = dict->units_per_em; + else + cffface->units_per_EM = 1000; + + cffface->underline_position = + (FT_Short)( dict->underline_position >> 16 ); + cffface->underline_thickness = + (FT_Short)( dict->underline_thickness >> 16 ); + + /* retrieve font family & style name */ + cffface->family_name = cff_index_get_name( &cff->name_index, + face_index ); + + if ( cffface->family_name ) + { + char* full = cff_index_get_sid_string( &cff->string_index, + dict->full_name, + psnames ); + char* fullp = full; + char* family = cffface->family_name; + + /* We try to extract the style name from the full name. */ + /* We need to ignore spaces and dashes during the search. */ + if ( full ) + { + while ( *fullp ) + { + /* skip common characters at the start of both strings */ + if ( *fullp == *family ) + { + family++; + fullp++; + continue; + } + + /* ignore spaces and dashes in full name during comparison */ + if ( *fullp == ' ' || *fullp == '-' ) + { + fullp++; + continue; + } + + /* ignore spaces and dashes in family name during comparison */ + if ( *family == ' ' || *family == '-' ) + { + family++; + continue; + } + + if ( !*family && *fullp ) + { + /* Rhe full name begins with the same characters as the */ + /* family name, with spaces and dashes removed. In this */ + /* case, the remaining string in `fullp' will be used as */ + /* the style name. */ + style_name = cff_strcpy( memory, fullp ); + } + break; + } + FT_FREE( full ); + } + } + else + { + char *cid_font_name = + cff_index_get_sid_string( &cff->string_index, + dict->cid_font_name, + psnames ); + + + /* do we have a `/FontName' for a CID-keyed font? */ + if ( cid_font_name ) + cffface->family_name = cid_font_name; + } + + if ( style_name ) + cffface->style_name = style_name; + else + /* assume "Regular" style if we don't know better */ + cffface->style_name = cff_strcpy( memory, (char *)"Regular" ); + + /*******************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ + + if ( sfnt_format ) + flags |= FT_FACE_FLAG_SFNT; + + /* fixed width font? */ + if ( dict->is_fixed_pitch ) + flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ +#if 0 + /* kerning available? */ + if ( face->kern_pairs ) + flags |= FT_FACE_FLAG_KERNING; +#endif + + cffface->face_flags = flags; + + /*******************************************************************/ + /* */ + /* Compute style flags. */ + /* */ + flags = 0; + + if ( dict->italic_angle ) + flags |= FT_STYLE_FLAG_ITALIC; + + { + char *weight = cff_index_get_sid_string( &cff->string_index, + dict->weight, + psnames ); + + + if ( weight ) + if ( !ft_strcmp( weight, "Bold" ) || + !ft_strcmp( weight, "Black" ) ) + flags |= FT_STYLE_FLAG_BOLD; + FT_FREE( weight ); + } + + cffface->style_flags = flags; + } + +#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES + /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ + /* has unset this flag because of the 3.0 `post' table */ + if ( dict->cid_registry == 0xFFFFU ) + cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; +#endif + + /*******************************************************************/ + /* */ + /* Compute char maps. */ + /* */ + + /* Try to synthetize a Unicode charmap if there is none available */ + /* already. If an OpenType font contains a Unicode "cmap", we */ + /* will use it, whatever be in the CFF part of the file. */ + { + FT_CharMapRec cmaprec; + FT_CharMap cmap; + FT_UInt nn; + CFF_Encoding encoding = &cff->encoding; + + + for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) + { + cmap = cffface->charmaps[nn]; + + /* Windows Unicode (3,1)? */ + if ( cmap->platform_id == 3 && cmap->encoding_id == 1 ) + goto Skip_Unicode; + + /* Deprecated Unicode platform id? */ + if ( cmap->platform_id == 0 ) + goto Skip_Unicode; /* Standard Unicode (deprecated) */ + } + + /* since CID-keyed fonts don't contain glyph names, we can't */ + /* construct a cmap */ + if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) + goto Exit; + + /* we didn't find a Unicode charmap -- synthetize one */ + cmaprec.face = cffface; + cmaprec.platform_id = 3; + cmaprec.encoding_id = 1; + cmaprec.encoding = FT_ENCODING_UNICODE; + + nn = (FT_UInt)cffface->num_charmaps; + + FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL ); + + /* if no Unicode charmap was previously selected, select this one */ + if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) + cffface->charmap = cffface->charmaps[nn]; + + Skip_Unicode: + if ( encoding->count > 0 ) + { + FT_CMap_Class clazz; + + + cmaprec.face = cffface; + cmaprec.platform_id = 7; /* Adobe platform id */ + + if ( encoding->offset == 0 ) + { + cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; + cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; + clazz = &cff_cmap_encoding_class_rec; + } + else if ( encoding->offset == 1 ) + { + cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; + cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; + clazz = &cff_cmap_encoding_class_rec; + } + else + { + cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; + cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; + clazz = &cff_cmap_encoding_class_rec; + } + + FT_CMap_New( clazz, NULL, &cmaprec, NULL ); + } + } + } + + Exit: + return error; + + Bad_Format: + error = CFF_Err_Unknown_File_Format; + goto Exit; + } + + + FT_LOCAL_DEF( void ) + cff_face_done( FT_Face cffface ) /* CFF_Face */ + { + CFF_Face face = (CFF_Face)cffface; + FT_Memory memory = cffface->memory; + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + + if ( sfnt ) + sfnt->done_face( face ); + + { + CFF_Font cff = (CFF_Font)face->extra.data; + + + if ( cff ) + { + cff_font_done( cff ); + FT_FREE( face->extra.data ); + } + } + } + + + FT_LOCAL_DEF( FT_Error ) + cff_driver_init( FT_Module module ) + { + FT_UNUSED( module ); + + return CFF_Err_Ok; + } + + + FT_LOCAL_DEF( void ) + cff_driver_done( FT_Module module ) + { + FT_UNUSED( module ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffobjs.h b/Utilities/vtkfreetype/src/cff/cffobjs.h new file mode 100644 index 0000000..338ec74 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffobjs.h @@ -0,0 +1,171 @@ +/***************************************************************************/ +/* */ +/* cffobjs.h */ +/* */ +/* OpenType objects manager (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CFFOBJS_H__ +#define __CFFOBJS_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include "cfftypes.h" +#include FT_INTERNAL_TRUETYPE_TYPES_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* CFF_Driver */ + /* */ + /* <Description> */ + /* A handle to an OpenType driver object. */ + /* */ + typedef struct CFF_DriverRec_* CFF_Driver; + + typedef TT_Face CFF_Face; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* CFF_Size */ + /* */ + /* <Description> */ + /* A handle to an OpenType size object. */ + /* */ + typedef struct CFF_SizeRec_ + { + FT_SizeRec root; + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + FT_UInt strike_index; /* 0xFFFF to indicate invalid */ + FT_Size_Metrics strike_metrics; /* current strike's metrics */ + +#endif + + } CFF_SizeRec, *CFF_Size; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* CFF_GlyphSlot */ + /* */ + /* <Description> */ + /* A handle to an OpenType glyph slot object. */ + /* */ + typedef struct CFF_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + } CFF_GlyphSlotRec, *CFF_GlyphSlot; + + + + /*************************************************************************/ + /* */ + /* Subglyph transformation record. */ + /* */ + typedef struct CFF_Transform_ + { + FT_Fixed xx, xy; /* transformation matrix coefficients */ + FT_Fixed yx, yy; + FT_F26Dot6 ox, oy; /* offsets */ + + } CFF_Transform; + + + /***********************************************************************/ + /* */ + /* TrueType driver class. */ + /* */ + typedef struct CFF_DriverRec_ + { + FT_DriverRec root; + void* extension_component; + + } CFF_DriverRec; + + + FT_LOCAL( FT_Error ) + cff_size_init( FT_Size size ); /* CFF_Size */ + + FT_LOCAL( void ) + cff_size_done( FT_Size size ); /* CFF_Size */ + + FT_LOCAL( FT_Error ) + cff_size_reset( FT_Size size, /* CFF_Size */ + FT_UInt char_width, + FT_UInt char_height ); + + FT_LOCAL( FT_Error ) + cff_point_size_reset( FT_Size cffsize, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + FT_LOCAL( void ) + cff_slot_done( FT_GlyphSlot slot ); + + FT_LOCAL( FT_Error ) + cff_slot_init( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* Face functions */ + /* */ + FT_LOCAL( FT_Error ) + cff_face_init( FT_Stream stream, + FT_Face face, /* CFF_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + FT_LOCAL( void ) + cff_face_done( FT_Face face ); /* CFF_Face */ + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + FT_LOCAL( FT_Error ) + cff_driver_init( FT_Module module ); + + FT_LOCAL( void ) + cff_driver_done( FT_Module module ); + + +FT_END_HEADER + +#endif /* __CFFOBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffparse.c b/Utilities/vtkfreetype/src/cff/cffparse.c new file mode 100644 index 0000000..8f1a98c --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffparse.c @@ -0,0 +1,688 @@ +/***************************************************************************/ +/* */ +/* cffparse.c */ +/* */ +/* CFF token stream parser (body) */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "cffparse.h" +#include FT_INTERNAL_STREAM_H + +#include "cfferrs.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cffparse + + + enum + { + cff_kind_none = 0, + cff_kind_num, + cff_kind_fixed, + cff_kind_fixed_thousand, + cff_kind_string, + cff_kind_bool, + cff_kind_delta, + cff_kind_callback, + + cff_kind_max /* do not remove */ + }; + + + /* now generate handlers for the most simple fields */ + typedef FT_Error (*CFF_Field_Reader)( CFF_Parser parser ); + + typedef struct CFF_Field_Handler_ + { + int kind; + int code; + FT_UInt offset; + FT_Byte size; + CFF_Field_Reader reader; + FT_UInt array_max; + FT_UInt count_offset; + + } CFF_Field_Handler; + + + FT_LOCAL_DEF( void ) + cff_parser_init( CFF_Parser parser, + FT_UInt code, + void* object ) + { + FT_MEM_ZERO( parser, sizeof ( *parser ) ); + + parser->top = parser->stack; + parser->object_code = code; + parser->object = object; + } + + + /* read an integer */ + static FT_Long + cff_parse_integer( FT_Byte* start, + FT_Byte* limit ) + { + FT_Byte* p = start; + FT_Int v = *p++; + FT_Long val = 0; + + + if ( v == 28 ) + { + if ( p + 2 > limit ) + goto Bad; + + val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] ); + p += 2; + } + else if ( v == 29 ) + { + if ( p + 4 > limit ) + goto Bad; + + val = ( (FT_Long)p[0] << 24 ) | + ( (FT_Long)p[1] << 16 ) | + ( (FT_Long)p[2] << 8 ) | + p[3]; + p += 4; + } + else if ( v < 247 ) + { + val = v - 139; + } + else if ( v < 251 ) + { + if ( p + 1 > limit ) + goto Bad; + + val = ( v - 247 ) * 256 + p[0] + 108; + p++; + } + else + { + if ( p + 1 > limit ) + goto Bad; + + val = -( v - 251 ) * 256 - p[0] - 108; + p++; + } + + Exit: + return val; + + Bad: + val = 0; + goto Exit; + } + + + /* read a real */ + static FT_Fixed + cff_parse_real( FT_Byte* start, + FT_Byte* limit, + FT_Int power_ten ) + { + FT_Byte* p = start; + FT_Long num, divider, result, exp; + FT_Int sign = 0, exp_sign = 0; + FT_UInt nib; + FT_UInt phase; + + + result = 0; + num = 0; + divider = 1; + + /* first of all, read the integer part */ + phase = 4; + + for (;;) + { + /* If we entered this iteration with phase == 4, we need to */ + /* read a new byte. This also skips past the intial 0x1E. */ + if ( phase ) + { + p++; + + /* Make sure we don't read past the end. */ + if ( p >= limit ) + goto Bad; + } + + /* Get the nibble. */ + nib = ( p[0] >> phase ) & 0xF; + phase = 4 - phase; + + if ( nib == 0xE ) + sign = 1; + else if ( nib > 9 ) + break; + else + result = result * 10 + nib; + } + + /* read decimal part, if any */ + if ( nib == 0xa ) + for (;;) + { + /* If we entered this iteration with phase == 4, we need */ + /* to read a new byte. */ + if ( phase ) + { + p++; + + /* Make sure we don't read past the end. */ + if ( p >= limit ) + goto Bad; + } + + /* Get the nibble. */ + nib = ( p[0] >> phase ) & 0xF; + phase = 4 - phase; + if ( nib >= 10 ) + break; + + if ( divider < 10000000L ) + { + num = num * 10 + nib; + divider *= 10; + } + } + + /* read exponent, if any */ + if ( nib == 12 ) + { + exp_sign = 1; + nib = 11; + } + + if ( nib == 11 ) + { + exp = 0; + + for (;;) + { + /* If we entered this iteration with phase == 4, we need */ + /* to read a new byte. */ + if ( phase ) + { + p++; + + /* Make sure we don't read past the end. */ + if ( p >= limit ) + goto Bad; + } + + /* Get the nibble. */ + nib = ( p[0] >> phase ) & 0xF; + phase = 4 - phase; + if ( nib >= 10 ) + break; + + exp = exp * 10 + nib; + } + + if ( exp_sign ) + exp = -exp; + + power_ten += (FT_Int)exp; + } + + /* raise to power of ten if needed */ + while ( power_ten > 0 ) + { + result = result * 10; + num = num * 10; + + power_ten--; + } + + while ( power_ten < 0 ) + { + result = result / 10; + divider = divider * 10; + + power_ten++; + } + + /* Move the integer part into the high 16 bits. */ + result <<= 16; + + /* Place the decimal part into the low 16 bits. */ + if ( num ) + result |= FT_DivFix( num, divider ); + + if ( sign ) + result = -result; + + Exit: + return result; + + Bad: + result = 0; + goto Exit; + } + + + /* read a number, either integer or real */ + static FT_Long + cff_parse_num( FT_Byte** d ) + { + return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 ) + : cff_parse_integer( d[0], d[1] ) ); + } + + + /* read a floating point number, either integer or real */ + static FT_Fixed + cff_parse_fixed( FT_Byte** d ) + { + return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 ) + : cff_parse_integer( d[0], d[1] ) << 16 ); + } + + /* read a floating point number, either integer or real, */ + /* but return 1000 times the number read in. */ + static FT_Fixed + cff_parse_fixed_thousand( FT_Byte** d ) + { + return **d == + 30 ? cff_parse_real ( d[0], d[1], 3 ) + : (FT_Fixed)FT_MulFix( cff_parse_integer( d[0], d[1] ) << 16, 1000 ); + } + + static FT_Error + cff_parse_font_matrix( CFF_Parser parser ) + { + CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; + FT_Matrix* matrix = &dict->font_matrix; + FT_Vector* offset = &dict->font_offset; + FT_UShort* upm = &dict->units_per_em; + FT_Byte** data = parser->stack; + FT_Error error; + FT_Fixed temp; + + + error = CFF_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 6 ) + { + matrix->xx = cff_parse_fixed_thousand( data++ ); + matrix->yx = cff_parse_fixed_thousand( data++ ); + matrix->xy = cff_parse_fixed_thousand( data++ ); + matrix->yy = cff_parse_fixed_thousand( data++ ); + offset->x = cff_parse_fixed_thousand( data++ ); + offset->y = cff_parse_fixed_thousand( data ); + + temp = FT_ABS( matrix->yy ); + + *upm = (FT_UShort)FT_DivFix( 0x10000L, FT_DivFix( temp, 1000 ) ); + + if ( temp != 0x10000L ) + { + matrix->xx = FT_DivFix( matrix->xx, temp ); + matrix->yx = FT_DivFix( matrix->yx, temp ); + matrix->xy = FT_DivFix( matrix->xy, temp ); + matrix->yy = FT_DivFix( matrix->yy, temp ); + offset->x = FT_DivFix( offset->x, temp ); + offset->y = FT_DivFix( offset->y, temp ); + } + + /* note that the offsets must be expressed in integer font units */ + offset->x >>= 16; + offset->y >>= 16; + + error = CFF_Err_Ok; + } + + return error; + } + + + static FT_Error + cff_parse_font_bbox( CFF_Parser parser ) + { + CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; + FT_BBox* bbox = &dict->font_bbox; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = CFF_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 4 ) + { + bbox->xMin = FT_RoundFix( cff_parse_fixed( data++ ) ); + bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) ); + bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) ); + bbox->yMax = FT_RoundFix( cff_parse_fixed( data ) ); + error = CFF_Err_Ok; + } + + return error; + } + + + static FT_Error + cff_parse_private_dict( CFF_Parser parser ) + { + CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = CFF_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 2 ) + { + dict->private_size = cff_parse_num( data++ ); + dict->private_offset = cff_parse_num( data ); + error = CFF_Err_Ok; + } + + return error; + } + + + static FT_Error + cff_parse_cid_ros( CFF_Parser parser ) + { + CFF_FontRecDict dict = (CFF_FontRecDict)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = CFF_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 3 ) + { + dict->cid_registry = (FT_UInt)cff_parse_num ( data++ ); + dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ ); + dict->cid_supplement = (FT_ULong)cff_parse_num( data ); + error = CFF_Err_Ok; + } + + return error; + } + + +#define CFF_FIELD_NUM( code, name ) \ + CFF_FIELD( code, name, cff_kind_num ) +#define CFF_FIELD_FIXED( code, name ) \ + CFF_FIELD( code, name, cff_kind_fixed ) +#define CFF_FIELD_FIXED_1000( code, name ) \ + CFF_FIELD( code, name, cff_kind_fixed_thousand ) +#define CFF_FIELD_STRING( code, name ) \ + CFF_FIELD( code, name, cff_kind_string ) +#define CFF_FIELD_BOOL( code, name ) \ + CFF_FIELD( code, name, cff_kind_bool ) +#define CFF_FIELD_DELTA( code, name, max ) \ + CFF_FIELD( code, name, cff_kind_delta ) + +#define CFF_FIELD_CALLBACK( code, name ) \ + { \ + cff_kind_callback, \ + code | CFFCODE, \ + 0, 0, \ + cff_parse_ ## name, \ + 0, 0 \ + }, + +#undef CFF_FIELD +#define CFF_FIELD( code, name, kind ) \ + { \ + kind, \ + code | CFFCODE, \ + FT_FIELD_OFFSET( name ), \ + FT_FIELD_SIZE( name ), \ + 0, 0, 0 \ + }, + +#undef CFF_FIELD_DELTA +#define CFF_FIELD_DELTA( code, name, max ) \ + { \ + cff_kind_delta, \ + code | CFFCODE, \ + FT_FIELD_OFFSET( name ), \ + FT_FIELD_SIZE_DELTA( name ), \ + 0, \ + max, \ + FT_FIELD_OFFSET( num_ ## name ) \ + }, + +#define CFFCODE_TOPDICT 0x1000 +#define CFFCODE_PRIVATE 0x2000 + + static const CFF_Field_Handler cff_field_handlers[] = + { + +#include "cfftoken.h" + + { 0, 0, 0, 0, 0, 0, 0 } + }; + + + FT_LOCAL_DEF( FT_Error ) + cff_parser_run( CFF_Parser parser, + FT_Byte* start, + FT_Byte* limit ) + { + FT_Byte* p = start; + FT_Error error = CFF_Err_Ok; + + + parser->top = parser->stack; + parser->start = start; + parser->limit = limit; + parser->cursor = start; + + while ( p < limit ) + { + FT_UInt v = *p; + + + if ( v >= 27 && v != 31 ) + { + /* it's a number; we will push its position on the stack */ + if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH ) + goto Stack_Overflow; + + *parser->top ++ = p; + + /* now, skip it */ + if ( v == 30 ) + { + /* skip real number */ + p++; + for (;;) + { + if ( p >= limit ) + goto Syntax_Error; + v = p[0] >> 4; + if ( v == 15 ) + break; + v = p[0] & 0xF; + if ( v == 15 ) + break; + p++; + } + } + else if ( v == 28 ) + p += 2; + else if ( v == 29 ) + p += 4; + else if ( v > 246 ) + p += 1; + } + else + { + /* This is not a number, hence it's an operator. Compute its code */ + /* and look for it in our current list. */ + + FT_UInt code; + FT_UInt num_args = (FT_UInt) + ( parser->top - parser->stack ); + const CFF_Field_Handler* field; + + + *parser->top = p; + code = v; + if ( v == 12 ) + { + /* two byte operator */ + p++; + if ( p >= limit ) + goto Syntax_Error; + + code = 0x100 | p[0]; + } + code = code | parser->object_code; + + for ( field = cff_field_handlers; field->kind; field++ ) + { + if ( field->code == (FT_Int)code ) + { + /* we found our field's handler; read it */ + FT_Long val; + FT_Byte* q = (FT_Byte*)parser->object + field->offset; + + + /* check that we have enough arguments -- except for */ + /* delta encoded arrays, which can be empty */ + if ( field->kind != cff_kind_delta && num_args < 1 ) + goto Stack_Underflow; + + switch ( field->kind ) + { + case cff_kind_bool: + case cff_kind_string: + case cff_kind_num: + val = cff_parse_num( parser->stack ); + goto Store_Number; + + case cff_kind_fixed: + val = cff_parse_fixed( parser->stack ); + goto Store_Number; + + case cff_kind_fixed_thousand: + val = cff_parse_fixed_thousand( parser->stack ); + + Store_Number: + switch ( field->size ) + { + case (8 / FT_CHAR_BIT): + *(FT_Byte*)q = (FT_Byte)val; + break; + + case (16 / FT_CHAR_BIT): + *(FT_Short*)q = (FT_Short)val; + break; + + case (32 / FT_CHAR_BIT): + *(FT_Int32*)q = (FT_Int)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + break; + + case cff_kind_delta: + { + FT_Byte* qcount = (FT_Byte*)parser->object + + field->count_offset; + + FT_Byte** data = parser->stack; + + + if ( num_args > field->array_max ) + num_args = field->array_max; + + /* store count */ + *qcount = (FT_Byte)num_args; + + val = 0; + while ( num_args > 0 ) + { + val += cff_parse_num( data++ ); + switch ( field->size ) + { + case (8 / FT_CHAR_BIT): + *(FT_Byte*)q = (FT_Byte)val; + break; + + case (16 / FT_CHAR_BIT): + *(FT_Short*)q = (FT_Short)val; + break; + + case (32 / FT_CHAR_BIT): + *(FT_Int32*)q = (FT_Int)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + + q += field->size; + num_args--; + } + } + break; + + default: /* callback */ + error = field->reader( parser ); + if ( error ) + goto Exit; + } + goto Found; + } + } + + /* this is an unknown operator, or it is unsupported; */ + /* we will ignore it for now. */ + + Found: + /* clear stack */ + parser->top = parser->stack; + } + p++; + } + + Exit: + return error; + + Stack_Overflow: + error = CFF_Err_Invalid_Argument; + goto Exit; + + Stack_Underflow: + error = CFF_Err_Invalid_Argument; + goto Exit; + + Syntax_Error: + error = CFF_Err_Invalid_Argument; + goto Exit; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cffparse.h b/Utilities/vtkfreetype/src/cff/cffparse.h new file mode 100644 index 0000000..8f3fa58 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cffparse.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* cffparse.h */ +/* */ +/* CFF token stream parser (specification) */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CFF_PARSE_H__ +#define __CFF_PARSE_H__ + + +#include <ft2build.h> +#include "cfftypes.h" +#include FT_INTERNAL_OBJECTS_H + + +FT_BEGIN_HEADER + + +#define CFF_MAX_STACK_DEPTH 96 + +#define CFF_CODE_TOPDICT 0x1000 +#define CFF_CODE_PRIVATE 0x2000 + + + typedef struct CFF_ParserRec_ + { + FT_Byte* start; + FT_Byte* limit; + FT_Byte* cursor; + + FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1]; + FT_Byte** top; + + FT_UInt object_code; + void* object; + + } CFF_ParserRec, *CFF_Parser; + + + FT_LOCAL( void ) + cff_parser_init( CFF_Parser parser, + FT_UInt code, + void* object ); + + FT_LOCAL( FT_Error ) + cff_parser_run( CFF_Parser parser, + FT_Byte* start, + FT_Byte* limit ); + + +FT_END_HEADER + + +#endif /* __CFF_PARSE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cfftoken.h b/Utilities/vtkfreetype/src/cff/cfftoken.h new file mode 100644 index 0000000..659d157 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cfftoken.h @@ -0,0 +1,97 @@ +/***************************************************************************/ +/* */ +/* cfftoken.h */ +/* */ +/* CFF token definitions (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#undef FT_STRUCTURE +#define FT_STRUCTURE CFF_FontRecDictRec + +#undef CFFCODE +#define CFFCODE CFFCODE_TOPDICT + + CFF_FIELD_STRING ( 0, version ) + CFF_FIELD_STRING ( 1, notice ) + CFF_FIELD_STRING ( 0x100, copyright ) + CFF_FIELD_STRING ( 2, full_name ) + CFF_FIELD_STRING ( 3, family_name ) + CFF_FIELD_STRING ( 4, weight ) + CFF_FIELD_BOOL ( 0x101, is_fixed_pitch ) + CFF_FIELD_FIXED ( 0x102, italic_angle ) + CFF_FIELD_FIXED ( 0x103, underline_position ) + CFF_FIELD_FIXED ( 0x104, underline_thickness ) + CFF_FIELD_NUM ( 0x105, paint_type ) + CFF_FIELD_NUM ( 0x106, charstring_type ) + CFF_FIELD_CALLBACK( 0x107, font_matrix ) + CFF_FIELD_NUM ( 13, unique_id ) + CFF_FIELD_CALLBACK( 5, font_bbox ) + CFF_FIELD_NUM ( 0x108, stroke_width ) + CFF_FIELD_NUM ( 15, charset_offset ) + CFF_FIELD_NUM ( 16, encoding_offset ) + CFF_FIELD_NUM ( 17, charstrings_offset ) + CFF_FIELD_CALLBACK( 18, private_dict ) + CFF_FIELD_NUM ( 0x114, synthetic_base ) + CFF_FIELD_STRING ( 0x115, embedded_postscript ) + +#if 0 + CFF_FIELD_STRING ( 0x116, base_font_name ) + CFF_FIELD_DELTA ( 0x117, base_font_blend, 16 ) + CFF_FIELD_CALLBACK( 0x118, multiple_master ) + CFF_FIELD_CALLBACK( 0x119, blend_axit_types ) +#endif + + CFF_FIELD_CALLBACK( 0x11E, cid_ros ) + CFF_FIELD_NUM ( 0x11F, cid_font_version ) + CFF_FIELD_NUM ( 0x120, cid_font_revision ) + CFF_FIELD_NUM ( 0x121, cid_font_type ) + CFF_FIELD_NUM ( 0x122, cid_count ) + CFF_FIELD_NUM ( 0x123, cid_uid_base ) + CFF_FIELD_NUM ( 0x124, cid_fd_array_offset ) + CFF_FIELD_NUM ( 0x125, cid_fd_select_offset ) + CFF_FIELD_STRING ( 0x126, cid_font_name ) + +#if 0 + CFF_FIELD_NUM ( 0x127, chameleon ) +#endif + + +#undef FT_STRUCTURE +#define FT_STRUCTURE CFF_PrivateRec +#undef CFFCODE +#define CFFCODE CFFCODE_PRIVATE + + CFF_FIELD_DELTA ( 6, blue_values, 14 ) + CFF_FIELD_DELTA ( 7, other_blues, 10 ) + CFF_FIELD_DELTA ( 8, family_blues, 14 ) + CFF_FIELD_DELTA ( 9, family_other_blues, 10 ) + CFF_FIELD_FIXED_1000( 0x109, blue_scale ) + CFF_FIELD_NUM ( 0x10A, blue_shift ) + CFF_FIELD_NUM ( 0x10B, blue_fuzz ) + CFF_FIELD_NUM ( 10, standard_width ) + CFF_FIELD_NUM ( 11, standard_height ) + CFF_FIELD_DELTA ( 0x10C, snap_widths, 13 ) + CFF_FIELD_DELTA ( 0x10D, snap_heights, 13 ) + CFF_FIELD_BOOL ( 0x10E, force_bold ) + CFF_FIELD_FIXED ( 0x10F, force_bold_threshold ) + CFF_FIELD_NUM ( 0x110, lenIV ) + CFF_FIELD_NUM ( 0x111, language_group ) + CFF_FIELD_FIXED ( 0x112, expansion_factor ) + CFF_FIELD_NUM ( 0x113, initial_random_seed ) + CFF_FIELD_NUM ( 19, local_subrs_offset ) + CFF_FIELD_NUM ( 20, default_width ) + CFF_FIELD_NUM ( 21, nominal_width ) + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cff/cfftypes.h b/Utilities/vtkfreetype/src/cff/cfftypes.h new file mode 100644 index 0000000..9ddc663 --- /dev/null +++ b/Utilities/vtkfreetype/src/cff/cfftypes.h @@ -0,0 +1,255 @@ +/***************************************************************************/ +/* */ +/* cfftypes.h */ +/* */ +/* Basic OpenType/CFF type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CFFTYPES_H__ +#define __CFFTYPES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CFF_IndexRec */ + /* */ + /* <Description> */ + /* A structure used to model a CFF Index table. */ + /* */ + /* <Fields> */ + /* stream :: The source input stream. */ + /* */ + /* count :: The number of elements in the index. */ + /* */ + /* off_size :: The size in bytes of object offsets in index. */ + /* */ + /* data_offset :: The position of first data byte in the index's */ + /* bytes. */ + /* */ + /* offsets :: A table of element offsets in the index. */ + /* */ + /* bytes :: If the index is loaded in memory, its bytes. */ + /* */ + typedef struct CFF_IndexRec_ + { + FT_Stream stream; + FT_UInt count; + FT_Byte off_size; + FT_ULong data_offset; + + FT_ULong* offsets; + FT_Byte* bytes; + + } CFF_IndexRec, *CFF_Index; + + + typedef struct CFF_EncodingRec_ + { + FT_UInt format; + FT_ULong offset; + + FT_UInt count; + FT_UShort sids [256]; /* avoid dynamic allocations */ + FT_UShort codes[256]; + + } CFF_EncodingRec, *CFF_Encoding; + + + typedef struct CFF_CharsetRec_ + { + + FT_UInt format; + FT_ULong offset; + + FT_UShort* sids; + FT_UShort* cids; /* the inverse mapping of `sids'; only needed */ + /* for CID-keyed fonts */ + } CFF_CharsetRec, *CFF_Charset; + + + typedef struct CFF_FontRecDictRec_ + { + FT_UInt version; + FT_UInt notice; + FT_UInt copyright; + FT_UInt full_name; + FT_UInt family_name; + FT_UInt weight; + FT_Bool is_fixed_pitch; + FT_Fixed italic_angle; + FT_Fixed underline_position; + FT_Fixed underline_thickness; + FT_Int paint_type; + FT_Int charstring_type; + FT_Matrix font_matrix; + FT_UShort units_per_em; + FT_Vector font_offset; + FT_ULong unique_id; + FT_BBox font_bbox; + FT_Pos stroke_width; + FT_ULong charset_offset; + FT_ULong encoding_offset; + FT_ULong charstrings_offset; + FT_ULong private_offset; + FT_ULong private_size; + FT_Long synthetic_base; + FT_UInt embedded_postscript; + + /* these should only be used for the top-level font dictionary */ + FT_UInt cid_registry; + FT_UInt cid_ordering; + FT_ULong cid_supplement; + + FT_Long cid_font_version; + FT_Long cid_font_revision; + FT_Long cid_font_type; + FT_ULong cid_count; + FT_ULong cid_uid_base; + FT_ULong cid_fd_array_offset; + FT_ULong cid_fd_select_offset; + FT_UInt cid_font_name; + + } CFF_FontRecDictRec, *CFF_FontRecDict; + + + typedef struct CFF_PrivateRec_ + { + FT_Byte num_blue_values; + FT_Byte num_other_blues; + FT_Byte num_family_blues; + FT_Byte num_family_other_blues; + + FT_Pos blue_values[14]; + FT_Pos other_blues[10]; + FT_Pos family_blues[14]; + FT_Pos family_other_blues[10]; + + FT_Fixed blue_scale; + FT_Pos blue_shift; + FT_Pos blue_fuzz; + FT_Pos standard_width; + FT_Pos standard_height; + + FT_Byte num_snap_widths; + FT_Byte num_snap_heights; + FT_Pos snap_widths[13]; + FT_Pos snap_heights[13]; + FT_Bool force_bold; + FT_Fixed force_bold_threshold; + FT_Int lenIV; + FT_Int language_group; + FT_Fixed expansion_factor; + FT_Long initial_random_seed; + FT_ULong local_subrs_offset; + FT_Pos default_width; + FT_Pos nominal_width; + + } CFF_PrivateRec, *CFF_Private; + + + typedef struct CFF_FDSelectRec_ + { + FT_Byte format; + FT_UInt range_count; + + /* that's the table, taken from the file `as is' */ + FT_Byte* data; + FT_UInt data_size; + + /* small cache for format 3 only */ + FT_UInt cache_first; + FT_UInt cache_count; + FT_Byte cache_fd; + + } CFF_FDSelectRec, *CFF_FDSelect; + + + /* A SubFont packs a font dict and a private dict together. They are */ + /* needed to support CID-keyed CFF fonts. */ + typedef struct CFF_SubFontRec_ + { + CFF_FontRecDictRec font_dict; + CFF_PrivateRec private_dict; + + CFF_IndexRec local_subrs_index; + FT_UInt num_local_subrs; + FT_Byte** local_subrs; + + } CFF_SubFontRec, *CFF_SubFont; + + + /* maximum number of sub-fonts in a CID-keyed file */ +#define CFF_MAX_CID_FONTS 32 + + + typedef struct CFF_FontRec_ + { + FT_Stream stream; + FT_Memory memory; + FT_UInt num_faces; + FT_UInt num_glyphs; + + FT_Byte version_major; + FT_Byte version_minor; + FT_Byte header_size; + FT_Byte absolute_offsize; + + + CFF_IndexRec name_index; + CFF_IndexRec top_dict_index; + CFF_IndexRec string_index; + CFF_IndexRec global_subrs_index; + + CFF_EncodingRec encoding; + CFF_CharsetRec charset; + + CFF_IndexRec charstrings_index; + CFF_IndexRec font_dict_index; + CFF_IndexRec private_index; + CFF_IndexRec local_subrs_index; + + FT_String* font_name; + FT_UInt num_global_subrs; + FT_Byte** global_subrs; + + CFF_SubFontRec top_font; + FT_UInt num_subfonts; + CFF_SubFont subfonts[CFF_MAX_CID_FONTS]; + + CFF_FDSelectRec fd_select; + + /* interface to PostScript hinter */ + void* pshinter; + + /* interface to Postscript Names service */ + void* psnames; + + } CFF_FontRec, *CFF_Font; + + +FT_END_HEADER + +#endif /* __CFFTYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/ciderrs.h b/Utilities/vtkfreetype/src/cid/ciderrs.h new file mode 100644 index 0000000..01813e1 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/ciderrs.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* ciderrs.h */ +/* */ +/* CID error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the CID error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __CIDERRS_H__ +#define __CIDERRS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX CID_Err_ +#define FT_ERR_BASE FT_Mod_Err_CID + +#include FT_ERRORS_H + +#endif /* __CIDERRS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidgload.c b/Utilities/vtkfreetype/src/cid/cidgload.c new file mode 100644 index 0000000..cbd0865 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidgload.c @@ -0,0 +1,449 @@ +/***************************************************************************/ +/* */ +/* cidgload.c */ +/* */ +/* CID-keyed Type1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "cidload.h" +#include "cidgload.h" +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_OUTLINE_H + +#include "ciderrs.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidgload + + + FT_CALLBACK_DEF( FT_Error ) + cid_load_glyph( T1_Decoder decoder, + FT_UInt glyph_index ) + { + CID_Face face = (CID_Face)decoder->builder.face; + CID_FaceInfo cid = &face->cid; + FT_Byte* p; + FT_UInt fd_select; + FT_Stream stream = face->cid_stream; + FT_Error error = 0; + FT_Byte* charstring = 0; + FT_Memory memory = face->root.memory; + FT_ULong glyph_length = 0; + PSAux_Service psaux = (PSAux_Service)face->psaux; + + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* For incremental fonts get the character data using */ + /* the callback function. */ + if ( face->root.internal->incremental_interface ) + { + FT_Data glyph_data; + + + error = face->root.internal->incremental_interface->funcs->get_glyph_data( + face->root.internal->incremental_interface->object, + glyph_index, + &glyph_data ); + if ( error ) + goto Exit; + + p = (FT_Byte*)glyph_data.pointer; + fd_select = (FT_UInt)cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); + + if ( glyph_data.length != 0 ) + { + glyph_length = glyph_data.length - cid->fd_bytes; + FT_ALLOC( charstring, glyph_length ); + if ( !error ) + ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes, + glyph_length ); + } + + face->root.internal->incremental_interface->funcs->free_glyph_data( + face->root.internal->incremental_interface->object, + &glyph_data ); + + if ( error ) + goto Exit; + } + + else + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + /* For ordinary fonts read the CID font dictionary index */ + /* and charstring offset from the CIDMap. */ + { + FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; + FT_ULong off1; + + + if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + + glyph_index * entry_len ) || + FT_FRAME_ENTER( 2 * entry_len ) ) + goto Exit; + + p = (FT_Byte*)stream->cursor; + fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); + off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); + p += cid->fd_bytes; + glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; + FT_FRAME_EXIT(); + + if ( glyph_length == 0 ) + goto Exit; + if ( FT_ALLOC( charstring, glyph_length ) ) + goto Exit; + if ( FT_STREAM_READ_AT( cid->data_offset + off1, + charstring, glyph_length ) ) + goto Exit; + } + + /* Now set up the subrs array and parse the charstrings. */ + { + CID_FaceDict dict; + CID_Subrs cid_subrs = face->subrs + fd_select; + FT_Int cs_offset; + + + /* Set up subrs */ + decoder->num_subrs = cid_subrs->num_subrs; + decoder->subrs = cid_subrs->code; + decoder->subrs_len = 0; + + /* Set up font matrix */ + dict = cid->font_dicts + fd_select; + + decoder->font_matrix = dict->font_matrix; + decoder->font_offset = dict->font_offset; + decoder->lenIV = dict->private_dict.lenIV; + + /* Decode the charstring. */ + + /* Adjustment for seed bytes. */ + cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); + + /* Decrypt only if lenIV >= 0. */ + if ( decoder->lenIV >= 0 ) + psaux->t1_decrypt( charstring, glyph_length, 4330 ); + + error = decoder->funcs.parse_charstrings( + decoder, charstring + cs_offset, + (FT_Int)glyph_length - cs_offset ); + } + + FT_FREE( charstring ); + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* Incremental fonts can optionally override the metrics. */ + if ( !error && + face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + { + FT_Incremental_MetricsRec metrics; + + + metrics.bearing_x = decoder->builder.left_bearing.x; + metrics.bearing_y = decoder->builder.left_bearing.y; + metrics.advance = decoder->builder.advance.x; + error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( + face->root.internal->incremental_interface->object, + glyph_index, FALSE, &metrics ); + decoder->builder.left_bearing.x = metrics.bearing_x; + decoder->builder.left_bearing.y = metrics.bearing_y; + decoder->builder.advance.x = metrics.advance; + decoder->builder.advance.y = 0; + } + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + Exit: + return error; + } + + +#if 0 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + cid_face_compute_max_advance( CID_Face face, + FT_Int* max_advance ) + { + FT_Error error; + T1_DecoderRec decoder; + FT_Int glyph_index; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + *max_advance = 0; + + /* Initialize load decoder */ + error = psaux->t1_decoder_funcs->init( &decoder, + (FT_Face)face, + 0, /* size */ + 0, /* glyph slot */ + 0, /* glyph names! XXX */ + 0, /* blend == 0 */ + 0, /* hinting == 0 */ + cid_load_glyph ); + if ( error ) + return error; + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + /* for each glyph, parse the glyph charstring and extract */ + /* the advance width */ + for ( glyph_index = 0; glyph_index < face->root.num_glyphs; + glyph_index++ ) + { + /* now get load the unscaled outline */ + error = cid_load_glyph( &decoder, glyph_index ); + /* ignore the error if one occurred - skip to next glyph */ + } + + *max_advance = decoder.builder.advance.x; + + return CID_Err_Ok; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** UNHINTED GLYPH LOADER *********/ + /********** *********/ + /********** The following code is in charge of loading a *********/ + /********** single outline. It completely ignores hinting *********/ + /********** and is used when FT_LOAD_NO_HINTING is set. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + cid_slot_load_glyph( FT_GlyphSlot cidglyph, /* CID_GlyphSlot */ + FT_Size cidsize, /* CID_Size */ + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + CID_GlyphSlot glyph = (CID_GlyphSlot)cidglyph; + CID_Size size = (CID_Size)cidsize; + FT_Error error; + T1_DecoderRec decoder; + CID_Face face = (CID_Face)cidglyph->face; + FT_Bool hinting; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + FT_Matrix font_matrix; + FT_Vector font_offset; + + + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + glyph->x_scale = cidsize->metrics.x_scale; + glyph->y_scale = cidsize->metrics.y_scale; + + cidglyph->outline.n_points = 0; + cidglyph->outline.n_contours = 0; + + hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + + cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; + + { + error = psaux->t1_decoder_funcs->init( &decoder, + cidglyph->face, + cidsize, + cidglyph, + 0, /* glyph names -- XXX */ + 0, /* blend == 0 */ + hinting, + FT_LOAD_TARGET_MODE( load_flags ), + cid_load_glyph ); + + /* set up the decoder */ + decoder.builder.no_recurse = FT_BOOL( + ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) ); + + error = cid_load_glyph( &decoder, glyph_index ); + + font_matrix = decoder.font_matrix; + font_offset = decoder.font_offset; + + /* save new glyph tables */ + psaux->t1_decoder_funcs->done( &decoder ); + } + + /* now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax */ + if ( !error ) + { + cidglyph->outline.flags &= FT_OUTLINE_OWNER; + cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; + + /* for composite glyphs, return only left side bearing and */ + /* advance width */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + FT_Slot_Internal internal = cidglyph->internal; + + + cidglyph->metrics.horiBearingX = decoder.builder.left_bearing.x; + cidglyph->metrics.horiAdvance = decoder.builder.advance.x; + + internal->glyph_matrix = font_matrix; + internal->glyph_delta = font_offset; + internal->glyph_transformed = 1; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &cidglyph->metrics; + FT_Vector advance; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + cidglyph->linearHoriAdvance = decoder.builder.advance.x; + cidglyph->internal->glyph_transformed = 0; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + cidglyph->linearVertAdvance = 0; + cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; + + if ( size && cidsize->metrics.y_ppem < 24 ) + cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; + + /* apply the font matrix */ + FT_Outline_Transform( &cidglyph->outline, &font_matrix ); + + FT_Outline_Translate( &cidglyph->outline, + font_offset.x, + font_offset.y ); + + advance.x = metrics->horiAdvance; + advance.y = 0; + FT_Vector_Transform( &advance, &font_matrix ); + metrics->horiAdvance = advance.x + font_offset.x; + advance.x = 0; + advance.y = metrics->vertAdvance; + FT_Vector_Transform( &advance, &font_matrix ); + metrics->vertAdvance = advance.y + font_offset.y; + + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + /* scale the outline and the metrics */ + FT_Int n; + FT_Outline* cur = decoder.builder.base; + FT_Vector* vec = cur->points; + FT_Fixed x_scale = glyph->x_scale; + FT_Fixed y_scale = glyph->y_scale; + + + /* First of all, scale the points */ + if ( !hinting ) + for ( n = cur->n_points; n > 0; n--, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + FT_Outline_Get_CBox( &cidglyph->outline, &cbox ); + + /* Then scale the metrics */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + + if ( hinting ) + { + metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance ); + metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance ); + + metrics->vertBearingX = FT_PIX_ROUND( metrics->vertBearingX ); + metrics->vertBearingY = FT_PIX_ROUND( metrics->vertBearingY ); + } + } + + /* compute the other metrics */ + FT_Outline_Get_CBox( &cidglyph->outline, &cbox ); + + /* grid fit the bounding box if necessary */ + if ( hinting ) + { + cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); + cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); + cbox.xMax = FT_PIX_CEIL( cbox.xMax ); + cbox.yMax = FT_PIX_CEIL( cbox.yMax ); + } + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax; + } + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidgload.h b/Utilities/vtkfreetype/src/cid/cidgload.h new file mode 100644 index 0000000..a0a91bf --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidgload.h @@ -0,0 +1,51 @@ +/***************************************************************************/ +/* */ +/* cidgload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CIDGLOAD_H__ +#define __CIDGLOAD_H__ + + +#include <ft2build.h> +#include "cidobjs.h" + + +FT_BEGIN_HEADER + + +#if 0 + + /* Compute the maximum advance width of a font through quick parsing */ + FT_LOCAL( FT_Error ) + cid_face_compute_max_advance( CID_Face face, + FT_Int* max_advance ); + +#endif /* 0 */ + + FT_LOCAL( FT_Error ) + cid_slot_load_glyph( FT_GlyphSlot glyph, /* CID_Glyph_Slot */ + FT_Size size, /* CID_Size */ + FT_UInt glyph_index, + FT_Int32 load_flags ); + + +FT_END_HEADER + +#endif /* __CIDGLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidload.c b/Utilities/vtkfreetype/src/cid/cidload.c new file mode 100644 index 0000000..ad29dd5 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidload.c @@ -0,0 +1,644 @@ +/***************************************************************************/ +/* */ +/* cidload.c */ +/* */ +/* CID-keyed Type1 font loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_CONFIG_CONFIG_H +#include FT_MULTIPLE_MASTERS_H +#include FT_INTERNAL_TYPE1_TYPES_H + +#include "cidload.h" + +#include "ciderrs.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidload + + + /* read a single offset */ + FT_LOCAL_DEF( FT_Long ) + cid_get_offset( FT_Byte* *start, + FT_Byte offsize ) + { + FT_Long result; + FT_Byte* p = *start; + + + for ( result = 0; offsize > 0; offsize-- ) + { + result <<= 8; + result |= *p++; + } + + *start = p; + return result; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + static FT_Error + cid_load_keyword( CID_Face face, + CID_Loader* loader, + const T1_Field keyword ) + { + FT_Error error; + CID_Parser* parser = &loader->parser; + FT_Byte* object; + void* dummy_object; + CID_FaceInfo cid = &face->cid; + + + /* if the keyword has a dedicated callback, call it */ + if ( keyword->type == T1_FIELD_TYPE_CALLBACK ) + { + keyword->reader( (FT_Face)face, parser ); + error = parser->root.error; + goto Exit; + } + + /* we must now compute the address of our target object */ + switch ( keyword->location ) + { + case T1_FIELD_LOCATION_CID_INFO: + object = (FT_Byte*)cid; + break; + + case T1_FIELD_LOCATION_FONT_INFO: + object = (FT_Byte*)&cid->font_info; + break; + + case T1_FIELD_LOCATION_BBOX: + object = (FT_Byte*)&cid->font_bbox; + break; + + default: + { + CID_FaceDict dict; + + + if ( parser->num_dict < 0 ) + { + FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n", + keyword->ident )); + error = CID_Err_Syntax_Error; + goto Exit; + } + + dict = cid->font_dicts + parser->num_dict; + switch ( keyword->location ) + { + case T1_FIELD_LOCATION_PRIVATE: + object = (FT_Byte*)&dict->private_dict; + break; + + default: + object = (FT_Byte*)dict; + } + } + } + + dummy_object = object; + + /* now, load the keyword data in the object's field(s) */ + if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY || + keyword->type == T1_FIELD_TYPE_FIXED_ARRAY ) + error = cid_parser_load_field_table( &loader->parser, keyword, + &dummy_object ); + else + error = cid_parser_load_field( &loader->parser, + keyword, &dummy_object ); + Exit: + return error; + } + + + FT_CALLBACK_DEF( FT_Error ) + parse_font_matrix( CID_Face face, + CID_Parser* parser ) + { + FT_Matrix* matrix; + FT_Vector* offset; + CID_FaceDict dict; + FT_Face root = (FT_Face)&face->root; + FT_Fixed temp[6]; + FT_Fixed temp_scale; + + + if ( parser->num_dict >= 0 ) + { + dict = face->cid.font_dicts + parser->num_dict; + matrix = &dict->font_matrix; + offset = &dict->font_offset; + + (void)cid_parser_to_fixed_array( parser, 6, temp, 3 ); + + temp_scale = FT_ABS( temp[3] ); + + /* Set units per EM based on FontMatrix values. We set the value to */ + /* `1000/temp_scale', because temp_scale was already multiplied by */ + /* 1000 (in `t1_tofixed', from psobjs.c). */ + root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L, + FT_DivFix( temp_scale, 1000 ) ) ); + + /* we need to scale the values by 1.0/temp[3] */ + if ( temp_scale != 0x10000L ) + { + temp[0] = FT_DivFix( temp[0], temp_scale ); + temp[1] = FT_DivFix( temp[1], temp_scale ); + temp[2] = FT_DivFix( temp[2], temp_scale ); + temp[4] = FT_DivFix( temp[4], temp_scale ); + temp[5] = FT_DivFix( temp[5], temp_scale ); + temp[3] = 0x10000L; + } + + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + + /* note that the font offsets are expressed in integer font units */ + offset->x = temp[4] >> 16; + offset->y = temp[5] >> 16; + } + + return CID_Err_Ok; /* this is a callback function; */ + /* we must return an error code */ + } + + + FT_CALLBACK_DEF( FT_Error ) + parse_fd_array( CID_Face face, + CID_Parser* parser ) + { + CID_FaceInfo cid = &face->cid; + FT_Memory memory = face->root.memory; + FT_Error error = CID_Err_Ok; + FT_Long num_dicts; + + + num_dicts = cid_parser_to_int( parser ); + + if ( !cid->font_dicts ) + { + FT_Int n; + + + if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) ) + goto Exit; + + cid->num_dicts = (FT_UInt)num_dicts; + + /* don't forget to set a few defaults */ + for ( n = 0; n < cid->num_dicts; n++ ) + { + CID_FaceDict dict = cid->font_dicts + n; + + + /* default value for lenIV */ + dict->private_dict.lenIV = 4; + } + } + + Exit: + return error; + } + + + static + const T1_FieldRec cid_field_records[] = + { + +#include "cidtoken.h" + + T1_FIELD_CALLBACK( "FDArray", parse_fd_array ) + T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix ) + + { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 } + }; + + + static FT_Error + cid_parse_dict( CID_Face face, + CID_Loader* loader, + FT_Byte* base, + FT_Long size ) + { + CID_Parser* parser = &loader->parser; + + + parser->root.cursor = base; + parser->root.limit = base + size; + parser->root.error = CID_Err_Ok; + + { + FT_Byte* cur = base; + FT_Byte* limit = cur + size; + + + for (;;) + { + FT_Byte* newlimit; + + + parser->root.cursor = cur; + cid_parser_skip_spaces( parser ); + + if ( parser->root.cursor >= limit ) + newlimit = limit - 1 - 17; + else + newlimit = parser->root.cursor - 17; + + /* look for `%ADOBeginFontDict' */ + for ( ; cur < newlimit; cur++ ) + { + if ( *cur == '%' && + ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 ) + { + /* if /FDArray was found, then cid->num_dicts is > 0, and */ + /* we can start increasing parser->num_dict */ + if ( face->cid.num_dicts > 0 ) + parser->num_dict++; + } + } + + cur = parser->root.cursor; + /* no error can occur in cid_parser_skip_spaces */ + if ( cur >= limit ) + break; + + cid_parser_skip_PS_token( parser ); + if ( parser->root.cursor >= limit || parser->root.error ) + break; + + /* look for immediates */ + if ( *cur == '/' && cur + 2 < limit ) + { + FT_PtrDist len; + + + cur++; + len = parser->root.cursor - cur; + + if ( len > 0 && len < 22 ) + { + /* now compare the immediate name to the keyword table */ + T1_Field keyword = (T1_Field)cid_field_records; + + + for (;;) + { + FT_Byte* name; + + + name = (FT_Byte*)keyword->ident; + if ( !name ) + break; + + if ( cur[0] == name[0] && + len == ft_strlen( (const char*)name ) ) + { + FT_PtrDist n; + + + for ( n = 1; n < len; n++ ) + if ( cur[n] != name[n] ) + break; + + if ( n >= len ) + { + /* we found it - run the parsing callback */ + parser->root.error = cid_load_keyword( face, + loader, + keyword ); + if ( parser->root.error ) + return parser->root.error; + break; + } + } + keyword++; + } + } + } + + cur = parser->root.cursor; + } + } + return parser->root.error; + } + + + /* read the subrmap and the subrs of each font dict */ + static FT_Error + cid_read_subrs( CID_Face face ) + { + CID_FaceInfo cid = &face->cid; + FT_Memory memory = face->root.memory; + FT_Stream stream = face->cid_stream; + FT_Error error; + FT_Int n; + CID_Subrs subr; + FT_UInt max_offsets = 0; + FT_ULong* offsets = 0; + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) ) + goto Exit; + + subr = face->subrs; + for ( n = 0; n < cid->num_dicts; n++, subr++ ) + { + CID_FaceDict dict = cid->font_dicts + n; + FT_Int lenIV = dict->private_dict.lenIV; + FT_UInt count, num_subrs = dict->num_subrs; + FT_ULong data_len; + FT_Byte* p; + + + /* reallocate offsets array if needed */ + if ( num_subrs + 1 > max_offsets ) + { + FT_UInt new_max = FT_PAD_CEIL( num_subrs + 1, 4 ); + + + if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) ) + goto Fail; + + max_offsets = new_max; + } + + /* read the subrmap's offsets */ + if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) || + FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes ) ) + goto Fail; + + p = (FT_Byte*)stream->cursor; + for ( count = 0; count <= num_subrs; count++ ) + offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes ); + + FT_FRAME_EXIT(); + + /* now, compute the size of subrs charstrings, */ + /* allocate, and read them */ + data_len = offsets[num_subrs] - offsets[0]; + + if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) || + FT_ALLOC( subr->code[0], data_len ) ) + goto Fail; + + if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) || + FT_STREAM_READ( subr->code[0], data_len ) ) + goto Fail; + + /* set up pointers */ + for ( count = 1; count <= num_subrs; count++ ) + { + FT_ULong len; + + + len = offsets[count] - offsets[count - 1]; + subr->code[count] = subr->code[count - 1] + len; + } + + /* decrypt subroutines, but only if lenIV >= 0 */ + if ( lenIV >= 0 ) + { + for ( count = 0; count < num_subrs; count++ ) + { + FT_ULong len; + + + len = offsets[count + 1] - offsets[count]; + psaux->t1_decrypt( subr->code[count], len, 4330 ); + } + } + + subr->num_subrs = num_subrs; + } + + Exit: + FT_FREE( offsets ); + return error; + + Fail: + if ( face->subrs ) + { + for ( n = 0; n < cid->num_dicts; n++ ) + { + if ( face->subrs[n].code ) + FT_FREE( face->subrs[n].code[0] ); + + FT_FREE( face->subrs[n].code ); + } + FT_FREE( face->subrs ); + } + goto Exit; + } + + + static void + t1_init_loader( CID_Loader* loader, + CID_Face face ) + { + FT_UNUSED( face ); + + FT_MEM_ZERO( loader, sizeof ( *loader ) ); + } + + + static void + t1_done_loader( CID_Loader* loader ) + { + CID_Parser* parser = &loader->parser; + + + /* finalize parser */ + cid_parser_done( parser ); + } + + + static FT_Error + cid_hex_to_binary( FT_Byte* data, + FT_Long data_len, + FT_ULong offset, + CID_Face face ) + { + FT_Stream stream = face->root.stream; + FT_Error error; + + FT_Byte buffer[256]; + FT_Byte *p, *plimit; + FT_Byte *d, *dlimit; + FT_Byte val; + + FT_Bool upper_nibble, done; + + + if ( FT_STREAM_SEEK( offset ) ) + goto Exit; + + d = data; + dlimit = d + data_len; + p = buffer; + plimit = p; + + upper_nibble = 1; + done = 0; + + while ( d < dlimit ) + { + if ( p >= plimit ) + { + FT_ULong oldpos = FT_STREAM_POS(); + FT_ULong size = stream->size - oldpos; + + + if ( size == 0 ) + { + error = CID_Err_Syntax_Error; + goto Exit; + } + + if ( FT_STREAM_READ( buffer, 256 > size ? size : 256 ) ) + goto Exit; + p = buffer; + plimit = p + FT_STREAM_POS() - oldpos; + } + + if ( ft_isdigit( *p ) ) + val = *p - '0'; + else if ( *p >= 'a' && *p <= 'f' ) + val = *p - 'a'; + else if ( *p >= 'A' && *p <= 'F' ) + val = *p - 'A' + 10; + else if ( *p == ' ' || + *p == '\t' || + *p == '\r' || + *p == '\n' || + *p == '\f' || + *p == '\0' ) + { + p++; + continue; + } + else if ( *p == '>' ) + { + val = 0; + done = 1; + } + else + { + error = CID_Err_Syntax_Error; + goto Exit; + } + + if ( upper_nibble ) + *d = val << 4; + else + { + *d += val; + d++; + } + + upper_nibble = 1 - upper_nibble; + + if ( done ) + break; + + p++; + } + + error = CID_Err_Ok; + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + cid_face_open( CID_Face face, + FT_Int face_index ) + { + CID_Loader loader; + CID_Parser* parser; + FT_Memory memory = face->root.memory; + FT_Error error; + + + t1_init_loader( &loader, face ); + + parser = &loader.parser; + error = cid_parser_new( parser, face->root.stream, face->root.memory, + (PSAux_Service)face->psaux ); + if ( error ) + goto Exit; + + error = cid_parse_dict( face, &loader, + parser->postscript, + parser->postscript_len ); + if ( error ) + goto Exit; + + if ( face_index < 0 ) + goto Exit; + + if ( FT_NEW( face->cid_stream ) ) + goto Exit; + + if ( parser->binary_length ) + { + /* we must convert the data section from hexadecimal to binary */ + if ( FT_ALLOC( face->binary_data, parser->binary_length ) || + cid_hex_to_binary( face->binary_data, parser->binary_length, + parser->data_offset, face ) ) + goto Exit; + + FT_Stream_OpenMemory( face->cid_stream, + face->binary_data, parser->binary_length ); + face->cid.data_offset = 0; + } + else + { + *face->cid_stream = *face->root.stream; + face->cid.data_offset = loader.parser.data_offset; + } + + error = cid_read_subrs( face ); + + Exit: + t1_done_loader( &loader ); + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidload.h b/Utilities/vtkfreetype/src/cid/cidload.h new file mode 100644 index 0000000..8c172ff --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidload.h @@ -0,0 +1,53 @@ +/***************************************************************************/ +/* */ +/* cidload.h */ +/* */ +/* CID-keyed Type1 font loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CIDLOAD_H__ +#define __CIDLOAD_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_STREAM_H +#include "cidparse.h" + + +FT_BEGIN_HEADER + + + typedef struct CID_Loader_ + { + CID_Parser parser; /* parser used to read the stream */ + FT_Int num_chars; /* number of characters in encoding */ + + } CID_Loader; + + + FT_LOCAL( FT_Long ) + cid_get_offset( FT_Byte** start, + FT_Byte offsize ); + + FT_LOCAL( FT_Error ) + cid_face_open( CID_Face face, + FT_Int face_index ); + + +FT_END_HEADER + +#endif /* __CIDLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidobjs.c b/Utilities/vtkfreetype/src/cid/cidobjs.c new file mode 100644 index 0000000..691ec17 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidobjs.c @@ -0,0 +1,501 @@ +/***************************************************************************/ +/* */ +/* cidobjs.c */ +/* */ +/* CID objects manager (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H + +#include "cidgload.h" +#include "cidload.h" + +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H + +#include "ciderrs.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidobjs + + + /*************************************************************************/ + /* */ + /* SLOT FUNCTIONS */ + /* */ + /*************************************************************************/ + + FT_LOCAL_DEF( void ) + cid_slot_done( FT_GlyphSlot slot ) + { + slot->internal->glyph_hints = 0; + } + + + FT_LOCAL_DEF( FT_Error ) + cid_slot_init( FT_GlyphSlot slot ) + { + CID_Face face; + PSHinter_Service pshinter; + + + face = (CID_Face)slot->face; + pshinter = (PSHinter_Service)face->pshinter; + + if ( pshinter ) + { + FT_Module module; + + + module = FT_Get_Module( slot->face->driver->root.library, + "pshinter" ); + if ( module ) + { + T1_Hints_Funcs funcs; + + + funcs = pshinter->get_t1_funcs( module ); + slot->internal->glyph_hints = (void*)funcs; + } + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + static PSH_Globals_Funcs + cid_size_get_globals_funcs( CID_Size size ) + { + CID_Face face = (CID_Face)size->root.face; + PSHinter_Service pshinter = (PSHinter_Service)face->pshinter; + FT_Module module; + + + module = FT_Get_Module( size->root.face->driver->root.library, + "pshinter" ); + return ( module && pshinter && pshinter->get_globals_funcs ) + ? pshinter->get_globals_funcs( module ) + : 0; + } + + + FT_LOCAL_DEF( void ) + cid_size_done( FT_Size cidsize ) /* CID_Size */ + { + CID_Size size = (CID_Size)cidsize; + + + if ( cidsize->internal ) + { + PSH_Globals_Funcs funcs; + + + funcs = cid_size_get_globals_funcs( size ); + if ( funcs ) + funcs->destroy( (PSH_Globals)cidsize->internal ); + + cidsize->internal = 0; + } + } + + + FT_LOCAL_DEF( FT_Error ) + cid_size_init( FT_Size cidsize ) /* CID_Size */ + { + CID_Size size = (CID_Size)cidsize; + FT_Error error = 0; + PSH_Globals_Funcs funcs = cid_size_get_globals_funcs( size ); + + + if ( funcs ) + { + PSH_Globals globals; + CID_Face face = (CID_Face)cidsize->face; + CID_FaceDict dict = face->cid.font_dicts + face->root.face_index; + PS_Private priv = &dict->private_dict; + + + error = funcs->create( cidsize->face->memory, priv, &globals ); + if ( !error ) + cidsize->internal = (FT_Size_Internal)(void*)globals; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + cid_size_reset( FT_Size cidsize, /* CID_Size */ + FT_UInt char_width, + FT_UInt char_height ) + { + CID_Size size = (CID_Size)cidsize; + PSH_Globals_Funcs funcs = cid_size_get_globals_funcs( size ); + FT_Error error = 0; + + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + + + if ( funcs ) + error = funcs->set_scale( (PSH_Globals)cidsize->internal, + cidsize->metrics.x_scale, + cidsize->metrics.y_scale, + 0, 0 ); + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + cid_point_size_reset( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + FT_UNUSED( horz_resolution ); + FT_UNUSED( vert_resolution ); + + return cid_size_reset( size, 0, 0 ); + } + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cid_face_done */ + /* */ + /* <Description> */ + /* Finalizes a given face object. */ + /* */ + /* <Input> */ + /* face :: A pointer to the face object to destroy. */ + /* */ + FT_LOCAL_DEF( void ) + cid_face_done( FT_Face cidface ) /* CID_Face */ + { + CID_Face face = (CID_Face)cidface; + FT_Memory memory; + + + if ( face ) + { + CID_FaceInfo cid = &face->cid; + PS_FontInfo info = &cid->font_info; + + + memory = cidface->memory; + + /* release subrs */ + if ( face->subrs ) + { + FT_Int n; + + + for ( n = 0; n < cid->num_dicts; n++ ) + { + CID_Subrs subr = face->subrs + n; + + + if ( subr->code ) + { + FT_FREE( subr->code[0] ); + FT_FREE( subr->code ); + } + } + + FT_FREE( face->subrs ); + } + + /* release FontInfo strings */ + FT_FREE( info->version ); + FT_FREE( info->notice ); + FT_FREE( info->full_name ); + FT_FREE( info->family_name ); + FT_FREE( info->weight ); + + /* release font dictionaries */ + FT_FREE( cid->font_dicts ); + cid->num_dicts = 0; + + /* release other strings */ + FT_FREE( cid->cid_font_name ); + FT_FREE( cid->registry ); + FT_FREE( cid->ordering ); + + cidface->family_name = 0; + cidface->style_name = 0; + + FT_FREE( face->binary_data ); + FT_FREE( face->cid_stream ); + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cid_face_init */ + /* */ + /* <Description> */ + /* Initializes a given CID face object. */ + /* */ + /* <Input> */ + /* stream :: The source font stream. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* <InOut> */ + /* face :: The newly built face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + cid_face_init( FT_Stream stream, + FT_Face cidface, /* CID_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + CID_Face face = (CID_Face)cidface; + FT_Error error; + FT_Service_PsCMaps psnames; + PSAux_Service psaux; + PSHinter_Service pshinter; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( stream ); + + + cidface->num_faces = 1; + + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); + + psaux = (PSAux_Service)face->psaux; + if ( !psaux ) + { + psaux = (PSAux_Service)FT_Get_Module_Interface( + FT_FACE_LIBRARY( face ), "psaux" ); + + face->psaux = psaux; + } + + pshinter = (PSHinter_Service)face->pshinter; + if ( !pshinter ) + { + pshinter = (PSHinter_Service)FT_Get_Module_Interface( + FT_FACE_LIBRARY( face ), "pshinter" ); + + face->pshinter = pshinter; + } + + /* open the tokenizer; this will also check the font format */ + if ( FT_STREAM_SEEK( 0 ) ) + goto Exit; + + error = cid_face_open( face, face_index ); + if ( error ) + goto Exit; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Exit; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "cid_face_init: invalid face index\n" )); + error = CID_Err_Invalid_Argument; + goto Exit; + } + + /* now load the font program into the face object */ + + /* initialize the face object fields */ + + /* set up root face fields */ + { + CID_FaceInfo cid = &face->cid; + PS_FontInfo info = &cid->font_info; + + + cidface->num_glyphs = cid->cid_count; + cidface->num_charmaps = 0; + + cidface->face_index = face_index; + cidface->face_flags = FT_FACE_FLAG_SCALABLE; + + cidface->face_flags |= FT_FACE_FLAG_HORIZONTAL; + + if ( info->is_fixed_pitch ) + cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX: TODO: add kerning with .afm support */ + + /* get style name -- be careful, some broken fonts only */ + /* have a /FontName dictionary entry! */ + cidface->family_name = info->family_name; + /* assume "Regular" style if we don't know better */ + cidface->style_name = (char *)"Regular"; + if ( cidface->family_name ) + { + char* full = info->full_name; + char* family = cidface->family_name; + + + if ( full ) + { + while ( *full ) + { + if ( *full == *family ) + { + family++; + full++; + } + else + { + if ( *full == ' ' || *full == '-' ) + full++; + else if ( *family == ' ' || *family == '-' ) + family++; + else + { + if ( !*family ) + cidface->style_name = full; + break; + } + } + } + } + } + else + { + /* do we have a `/FontName'? */ + if ( cid->cid_font_name ) + cidface->family_name = cid->cid_font_name; + } + + /* compute style flags */ + cidface->style_flags = 0; + if ( info->italic_angle ) + cidface->style_flags |= FT_STYLE_FLAG_ITALIC; + if ( info->weight ) + { + if ( !ft_strcmp( info->weight, "Bold" ) || + !ft_strcmp( info->weight, "Black" ) ) + cidface->style_flags |= FT_STYLE_FLAG_BOLD; + } + + /* no embedded bitmap support */ + cidface->num_fixed_sizes = 0; + cidface->available_sizes = 0; + + cidface->bbox.xMin = cid->font_bbox.xMin >> 16; + cidface->bbox.yMin = cid->font_bbox.yMin >> 16; + cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFFU ) >> 16; + cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFFU ) >> 16; + + if ( !cidface->units_per_EM ) + cidface->units_per_EM = 1000; + + cidface->ascender = (FT_Short)( cidface->bbox.yMax ); + cidface->descender = (FT_Short)( cidface->bbox.yMin ); + cidface->height = (FT_Short)( + ( ( cidface->ascender - cidface->descender ) * 12 ) / 10 ); + + cidface->underline_position = (FT_Short)info->underline_position; + cidface->underline_thickness = (FT_Short)info->underline_thickness; + + cidface->internal->max_points = 0; + cidface->internal->max_contours = 0; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cid_driver_init */ + /* */ + /* <Description> */ + /* Initializes a given CID driver object. */ + /* */ + /* <Input> */ + /* driver :: A handle to the target driver object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + cid_driver_init( FT_Module driver ) + { + FT_UNUSED( driver ); + + return CID_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* cid_driver_done */ + /* */ + /* <Description> */ + /* Finalizes a given CID driver. */ + /* */ + /* <Input> */ + /* driver :: A handle to the target CID driver. */ + /* */ + FT_LOCAL_DEF( void ) + cid_driver_done( FT_Module driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidobjs.h b/Utilities/vtkfreetype/src/cid/cidobjs.h new file mode 100644 index 0000000..9d230ba --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidobjs.h @@ -0,0 +1,163 @@ +/***************************************************************************/ +/* */ +/* cidobjs.h */ +/* */ +/* CID objects manager (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CIDOBJS_H__ +#define __CIDOBJS_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_TYPE1_TYPES_H + + +FT_BEGIN_HEADER + + + /* The following structures must be defined by the hinter */ + typedef struct CID_Size_Hints_ CID_Size_Hints; + typedef struct CID_Glyph_Hints_ CID_Glyph_Hints; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* CID_Driver */ + /* */ + /* <Description> */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct CID_DriverRec_* CID_Driver; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* CID_Size */ + /* */ + /* <Description> */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct CID_SizeRec_* CID_Size; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* CID_GlyphSlot */ + /* */ + /* <Description> */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct CID_GlyphSlotRec_* CID_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* CID_CharMap */ + /* */ + /* <Description> */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* <Note> */ + /* The Type 1 format doesn't use a charmap but an encoding table. */ + /* The driver is responsible for making up charmap objects */ + /* corresponding to these tables. */ + /* */ + typedef struct CID_CharMapRec_* CID_CharMap; + + + /*************************************************************************/ + /* */ + /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF */ + /* */ + /*************************************************************************/ + + + typedef struct CID_SizeRec_ + { + FT_SizeRec root; + FT_Bool valid; + + } CID_SizeRec; + + + typedef struct CID_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + } CID_GlyphSlotRec; + + + FT_LOCAL( void ) + cid_slot_done( FT_GlyphSlot slot ); + + FT_LOCAL( FT_Error ) + cid_slot_init( FT_GlyphSlot slot ); + + + FT_LOCAL( void ) + cid_size_done( FT_Size size ); /* CID_Size */ + + FT_LOCAL( FT_Error ) + cid_size_init( FT_Size size ); /* CID_Size */ + + FT_LOCAL( FT_Error ) + cid_size_reset( FT_Size size, /* CID_Size */ + FT_UInt char_width, + FT_UInt char_height ); + + FT_LOCAL( FT_Error ) + cid_point_size_reset( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + + FT_LOCAL( FT_Error ) + cid_face_init( FT_Stream stream, + FT_Face face, /* CID_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + FT_LOCAL( void ) + cid_face_done( FT_Face face ); /* CID_Face */ + + + FT_LOCAL( FT_Error ) + cid_driver_init( FT_Module driver ); + + FT_LOCAL( void ) + cid_driver_done( FT_Module driver ); + + +FT_END_HEADER + +#endif /* __CIDOBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidparse.c b/Utilities/vtkfreetype/src/cid/cidparse.c new file mode 100644 index 0000000..3f18749 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidparse.c @@ -0,0 +1,198 @@ +/***************************************************************************/ +/* */ +/* cidparse.c */ +/* */ +/* CID-keyed Type1 parser (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_STREAM_H + +#include "cidparse.h" + +#include "ciderrs.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidparse + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + cid_parser_new( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory, + PSAux_Service psaux ) + { + FT_Error error; + FT_ULong base_offset, offset, ps_len; + FT_Byte buffer[256 + 10]; + FT_Int buff_len; + FT_Byte *cur, *limit; + FT_Byte *arg1, *arg2; + + + FT_MEM_ZERO( parser, sizeof ( *parser ) ); + psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); + + parser->stream = stream; + + base_offset = FT_STREAM_POS(); + + /* first of all, check the font format in the header */ + if ( FT_FRAME_ENTER( 31 ) ) + goto Exit; + + if ( ft_strncmp( (char *)stream->cursor, + "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) + { + FT_TRACE2(( "[not a valid CID-keyed font]\n" )); + error = CID_Err_Unknown_File_Format; + } + + FT_FRAME_EXIT(); + if ( error ) + goto Exit; + + Again: + /* now, read the rest of the file until we find a `StartData' */ + buff_len = 256; + for (;;) + { + FT_Byte* p; + FT_ULong top_position; + + + /* fill input buffer */ + limit = buffer + 256; + buff_len -= 256; + if ( buff_len > 0 ) + FT_MEM_MOVE( buffer, limit, buff_len ); + + p = buffer + buff_len; + + if ( FT_STREAM_READ( p, 256 + 10 - buff_len ) ) + goto Exit; + + top_position = FT_STREAM_POS() - buff_len; + buff_len = 256 + 10; + + /* look for `StartData' */ + for ( p = buffer; p < limit; p++ ) + { + if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 ) + { + /* save offset of binary data after `StartData' */ + offset = (FT_ULong)( top_position - ( limit - p ) + 10 ); + goto Found; + } + } + } + + Found: + /* we have found the start of the binary data. We will now */ + /* rewind and extract the frame corresponding to the PostScript */ + /* section */ + + ps_len = offset - base_offset; + if ( FT_STREAM_SEEK( base_offset ) || + FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) + goto Exit; + + parser->data_offset = offset; + parser->postscript_len = ps_len; + parser->root.base = parser->postscript; + parser->root.cursor = parser->postscript; + parser->root.limit = parser->root.cursor + ps_len; + parser->num_dict = -1; + + /* Finally, we check whether `StartData' was real -- it could be */ + /* in a comment or string. We also get its arguments to find out */ + /* whether the data is represented in binary or hex format. */ + + arg1 = parser->root.cursor; + cid_parser_skip_PS_token( parser ); + cid_parser_skip_spaces ( parser ); + arg2 = parser->root.cursor; + cid_parser_skip_PS_token( parser ); + cid_parser_skip_spaces ( parser ); + + limit = parser->root.limit; + cur = parser->root.cursor; + + while ( cur < limit ) + { + if ( *cur == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 ) + { + if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) + parser->binary_length = ft_atol( (const char *)arg2 ); + + limit = parser->root.limit; + cur = parser->root.cursor; + goto Exit; + } + + cid_parser_skip_PS_token( parser ); + cid_parser_skip_spaces ( parser ); + arg1 = arg2; + arg2 = cur; + cur = parser->root.cursor; + } + + /* we haven't found the correct `StartData'; go back and continue */ + /* searching */ + FT_FRAME_RELEASE( parser->postscript ); + if ( !FT_STREAM_SEEK( offset ) ) + goto Again; + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + cid_parser_done( CID_Parser* parser ) + { + /* always free the private dictionary */ + if ( parser->postscript ) + { + FT_Stream stream = parser->stream; + + + FT_FRAME_RELEASE( parser->postscript ); + } + parser->root.funcs.done( &parser->root ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidparse.h b/Utilities/vtkfreetype/src/cid/cidparse.h new file mode 100644 index 0000000..ca37dea --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidparse.h @@ -0,0 +1,123 @@ +/***************************************************************************/ +/* */ +/* cidparse.h */ +/* */ +/* CID-keyed Type1 parser (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CIDPARSE_H__ +#define __CIDPARSE_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_TYPE1_TYPES_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* CID_Parser */ + /* */ + /* <Description> */ + /* A CID_Parser is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* <Fields> */ + /* root :: The root PS_ParserRec fields. */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* postscript :: A pointer to the data to be parsed. */ + /* */ + /* postscript_len :: The length of the data to be parsed. */ + /* */ + /* data_offset :: The start position of the binary data (i.e., the */ + /* end of the data to be parsed. */ + /* */ + /* binary_length :: The length of the data after the `StartData' */ + /* command if the data format is hexadecimal. */ + /* */ + /* cid :: A structure which holds the information about */ + /* the current font. */ + /* */ + /* num_dict :: The number of font dictionaries. */ + /* */ + typedef struct CID_Parser_ + { + PS_ParserRec root; + FT_Stream stream; + + FT_Byte* postscript; + FT_Long postscript_len; + + FT_ULong data_offset; + + FT_Long binary_length; + + CID_FaceInfo cid; + FT_Int num_dict; + + } CID_Parser; + + + FT_LOCAL( FT_Error ) + cid_parser_new( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory, + PSAux_Service psaux ); + + FT_LOCAL( void ) + cid_parser_done( CID_Parser* parser ); + + + /*************************************************************************/ + /* */ + /* PARSING ROUTINES */ + /* */ + /*************************************************************************/ + +#define cid_parser_skip_spaces( p ) \ + (p)->root.funcs.skip_spaces( &(p)->root ) +#define cid_parser_skip_PS_token( p ) \ + (p)->root.funcs.skip_PS_token( &(p)->root ) + +#define cid_parser_to_int( p ) (p)->root.funcs.to_int( &(p)->root ) +#define cid_parser_to_fixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t ) + +#define cid_parser_to_coord_array( p, m, c ) \ + (p)->root.funcs.to_coord_array( &(p)->root, m, c ) +#define cid_parser_to_fixed_array( p, m, f, t ) \ + (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t ) +#define cid_parser_to_token( p, t ) \ + (p)->root.funcs.to_token( &(p)->root, t ) +#define cid_parser_to_token_array( p, t, m, c ) \ + (p)->root.funcs.to_token_array( &(p)->root, t, m, c ) + +#define cid_parser_load_field( p, f, o ) \ + (p)->root.funcs.load_field( &(p)->root, f, o, 0, 0 ) +#define cid_parser_load_field_table( p, f, o ) \ + (p)->root.funcs.load_field_table( &(p)->root, f, o, 0, 0 ) + + +FT_END_HEADER + +#endif /* __CIDPARSE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidriver.c b/Utilities/vtkfreetype/src/cid/cidriver.c new file mode 100644 index 0000000..7d885a8 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidriver.c @@ -0,0 +1,157 @@ +/***************************************************************************/ +/* */ +/* cidriver.c */ +/* */ +/* CID driver interface (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "cidriver.h" +#include "cidgload.h" +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H + +#include "ciderrs.h" + +#include FT_SERVICE_POSTSCRIPT_NAME_H +#include FT_SERVICE_XFREE86_NAME_H +#include FT_SERVICE_POSTSCRIPT_INFO_H + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ciddriver + + + /* + * POSTSCRIPT NAME SERVICE + * + */ + + static const char* + cid_get_postscript_name( CID_Face face ) + { + const char* result = face->cid.cid_font_name; + + + if ( result && result[0] == '/' ) + result++; + + return result; + } + + + static const FT_Service_PsFontNameRec cid_service_ps_name = + { + (FT_PsName_GetFunc) cid_get_postscript_name + }; + + + /* + * POSTSCRIPT INFO SERVICE + * + */ + + static FT_Error + cid_ps_get_font_info( FT_Face face, + PS_FontInfoRec* afont_info ) + { + *afont_info = ((CID_Face)face)->cid.font_info; + return 0; + } + + + static const FT_Service_PsInfoRec cid_service_ps_info = + { + (PS_GetFontInfoFunc) cid_ps_get_font_info, + (PS_HasGlyphNamesFunc)NULL /* unsupported with CID fonts */ + }; + + + /* + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec cid_services[] = + { + { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cid_service_ps_name }, + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CID }, + { FT_SERVICE_ID_POSTSCRIPT_INFO, &cid_service_ps_info }, + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + cid_get_interface( FT_Module module, + const char* cid_interface ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( cid_services, cid_interface ); + } + + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec t1cid_driver_class = + { + /* first of all, the FT_Module_Class fields */ + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_SCALABLE | + FT_MODULE_DRIVER_HAS_HINTER, + + sizeof( FT_DriverRec ), + "t1cid", /* module name */ + 0x10000L, /* version 1.0 of driver */ + 0x20000L, /* requires FreeType 2.0 */ + + 0, + + cid_driver_init, + cid_driver_done, + cid_get_interface + }, + + /* then the other font drivers fields */ + sizeof( CID_FaceRec ), + sizeof( CID_SizeRec ), + sizeof( CID_GlyphSlotRec ), + + cid_face_init, + cid_face_done, + + cid_size_init, + cid_size_done, + cid_slot_init, + cid_slot_done, + + cid_point_size_reset, + cid_size_reset, + + cid_slot_load_glyph, + + 0, /* FT_Face_GetKerningFunc */ + 0, /* FT_Face_AttachFunc */ + + 0 /* FT_Face_GetAdvancesFunc */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidriver.h b/Utilities/vtkfreetype/src/cid/cidriver.h new file mode 100644 index 0000000..d5a80f6 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidriver.h @@ -0,0 +1,39 @@ +/***************************************************************************/ +/* */ +/* cidriver.h */ +/* */ +/* High-level CID driver interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __CIDRIVER_H__ +#define __CIDRIVER_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + + FT_CALLBACK_TABLE + const FT_Driver_ClassRec t1cid_driver_class; + + +FT_END_HEADER + +#endif /* __CIDRIVER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/cidtoken.h b/Utilities/vtkfreetype/src/cid/cidtoken.h new file mode 100644 index 0000000..2070aa9 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/cidtoken.h @@ -0,0 +1,103 @@ +/***************************************************************************/ +/* */ +/* cidtoken.h */ +/* */ +/* CID token definitions (specification only). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#undef FT_STRUCTURE +#define FT_STRUCTURE CID_FaceInfoRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_CID_INFO + + T1_FIELD_KEY ( "CIDFontName", cid_font_name ) + T1_FIELD_NUM ( "CIDFontVersion", cid_version ) + T1_FIELD_NUM ( "CIDFontType", cid_font_type ) + T1_FIELD_STRING( "Registry", registry ) + T1_FIELD_STRING( "Ordering", ordering ) + T1_FIELD_NUM ( "Supplement", supplement ) + T1_FIELD_NUM ( "UIDBase", uid_base ) + T1_FIELD_NUM ( "CIDMapOffset", cidmap_offset ) + T1_FIELD_NUM ( "FDBytes", fd_bytes ) + T1_FIELD_NUM ( "GDBytes", gd_bytes ) + T1_FIELD_NUM ( "CIDCount", cid_count ) + + +#undef FT_STRUCTURE +#define FT_STRUCTURE PS_FontInfoRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_FONT_INFO + + T1_FIELD_STRING( "version", version ) + T1_FIELD_STRING( "Notice", notice ) + T1_FIELD_STRING( "FullName", full_name ) + T1_FIELD_STRING( "FamilyName", family_name ) + T1_FIELD_STRING( "Weight", weight ) + T1_FIELD_NUM ( "ItalicAngle", italic_angle ) + T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch ) + T1_FIELD_NUM ( "UnderlinePosition", underline_position ) + T1_FIELD_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef FT_STRUCTURE +#define FT_STRUCTURE CID_FaceDictRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_FONT_DICT + + T1_FIELD_NUM ( "PaintType", paint_type ) + T1_FIELD_NUM ( "FontType", font_type ) + T1_FIELD_NUM ( "SubrMapOffset", subrmap_offset ) + T1_FIELD_NUM ( "SDBytes", sd_bytes ) + T1_FIELD_NUM ( "SubrCount", num_subrs ) + T1_FIELD_NUM ( "lenBuildCharArray", len_buildchar ) + T1_FIELD_FIXED( "ForceBoldThreshold", forcebold_threshold ) + T1_FIELD_FIXED( "ExpansionFactor", expansion_factor ) + T1_FIELD_FIXED( "StrokeWidth", stroke_width ) + + +#undef FT_STRUCTURE +#define FT_STRUCTURE PS_PrivateRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_PRIVATE + + T1_FIELD_NUM ( "UniqueID", unique_id ) + T1_FIELD_NUM ( "lenIV", lenIV ) + T1_FIELD_NUM ( "LanguageGroup", language_group ) + T1_FIELD_NUM ( "password", password ) + + T1_FIELD_FIXED_1000( "BlueScale", blue_scale ) + T1_FIELD_NUM ( "BlueShift", blue_shift ) + T1_FIELD_NUM ( "BlueFuzz", blue_fuzz ) + + T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 ) + T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 ) + T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 ) + T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 ) + + T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 ) + T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 ) + T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 ) + T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 ) + +#undef FT_STRUCTURE +#define FT_STRUCTURE FT_BBox +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_BBOX + + T1_FIELD_BBOX( "FontBBox", xMin ) + + +/* END */ diff --git a/Utilities/vtkfreetype/src/cid/type1cid.c b/Utilities/vtkfreetype/src/cid/type1cid.c new file mode 100644 index 0000000..0b866e9 --- /dev/null +++ b/Utilities/vtkfreetype/src/cid/type1cid.c @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* type1cid.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "cidparse.c" +#include "cidload.c" +#include "cidobjs.c" +#include "cidriver.c" +#include "cidgload.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/gzip/ftgzip.c b/Utilities/vtkfreetype/src/gzip/ftgzip.c new file mode 100644 index 0000000..a78c195 --- /dev/null +++ b/Utilities/vtkfreetype/src/gzip/ftgzip.c @@ -0,0 +1,605 @@ +/***************************************************************************/ +/* */ +/* ftgzip.c */ +/* */ +/* FreeType support for .gz compressed files. */ +/* */ +/* This optional component relies on zlib. It should mainly be used to */ +/* parse compressed PCF fonts, as found with many X11 server */ +/* distributions. */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_MEMORY_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_DEBUG_H +#include <string.h> + + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX Gzip_Err_ +#define FT_ERR_BASE FT_Mod_Err_Gzip + +#include FT_ERRORS_H + + +#ifdef FT_CONFIG_OPTION_USE_ZLIB + +#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB + +#include <zlib.h> + +#else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */ + + /* In this case, we include our own modified sources of the ZLib */ + /* within the "ftgzip" component. The modifications were necessary */ + /* to #include all files without conflicts, as well as preventing */ + /* the definition of "extern" functions that may cause linking */ + /* conflicts when a program is linked with both FreeType and the */ + /* original ZLib. */ + +#define NO_DUMMY_DECL +#define MY_ZCALLOC + +#include "zlib.h" + +#undef SLOW +#define SLOW 1 /* we can't use asm-optimized sources here! */ + + /* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like + this. We temporarily disable it and load all necessary header files. */ +#define NO_INFLATE_MASK +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#undef NO_INFLATE_MASK + + /* infutil.c must be included before infcodes.c */ +#include "zutil.c" +#include "inftrees.c" +#include "infutil.c" +#include "infcodes.c" +#include "infblock.c" +#include "inflate.c" +#include "adler32.c" + +#endif /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */ + + +/***************************************************************************/ +/***************************************************************************/ +/***** *****/ +/***** Z L I B M E M O R Y M A N A G E M E N T *****/ +/***** *****/ +/***************************************************************************/ +/***************************************************************************/ + + /* it is better to use FreeType memory routines instead of raw + 'malloc/free' */ + + static voidpf + ft_gzip_alloc( FT_Memory memory, + uInt items, + uInt size ) + { + FT_ULong sz = (FT_ULong)size * items; + FT_Pointer p; + + + FT_MEM_ALLOC( p, sz ); + + return (voidpf) p; + } + + + static void + ft_gzip_free( FT_Memory memory, + voidpf address ) + { + FT_MEM_FREE( address ); + } + + +#ifndef FT_CONFIG_OPTION_SYSTEM_ZLIB + + local voidpf + zcalloc ( voidpf opaque, + unsigned items, + unsigned size ) + { + return ft_gzip_alloc( (FT_Memory)opaque, items, size ); + } + + local void + zcfree( voidpf opaque, + voidpf ptr ) + { + ft_gzip_free( (FT_Memory)opaque, ptr ); + } + +#endif /* !SYSTEM_ZLIB */ + + +/***************************************************************************/ +/***************************************************************************/ +/***** *****/ +/***** Z L I B F I L E D E S C R I P T O R *****/ +/***** *****/ +/***************************************************************************/ +/***************************************************************************/ + +#define FT_GZIP_BUFFER_SIZE 4096 + + typedef struct FT_GZipFileRec_ + { + FT_Stream source; /* parent/source stream */ + FT_Stream stream; /* embedding stream */ + FT_Memory memory; /* memory allocator */ + z_stream zstream; /* zlib input stream */ + + FT_ULong start; /* starting position, after .gz header */ + FT_Byte input[FT_GZIP_BUFFER_SIZE]; /* input read buffer */ + + FT_Byte buffer[FT_GZIP_BUFFER_SIZE]; /* output buffer */ + FT_ULong pos; /* position in output */ + FT_Byte* cursor; + FT_Byte* limit; + + } FT_GZipFileRec, *FT_GZipFile; + + + /* gzip flag byte */ +#define FT_GZIP_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define FT_GZIP_HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define FT_GZIP_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define FT_GZIP_ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define FT_GZIP_COMMENT 0x10 /* bit 4 set: file comment present */ +#define FT_GZIP_RESERVED 0xE0 /* bits 5..7: reserved */ + + + /* check and skip .gz header - we don't support `transparent' compression */ + static FT_Error + ft_gzip_check_header( FT_Stream stream ) + { + FT_Error error; + FT_Byte head[4]; + + + if ( FT_STREAM_SEEK( 0 ) || + FT_STREAM_READ( head, 4 ) ) + goto Exit; + + /* head[0] && head[1] are the magic numbers; */ + /* head[2] is the method, and head[3] the flags */ + if ( head[0] != 0x1f || + head[1] != 0x8b || + head[2] != Z_DEFLATED || + (head[3] & FT_GZIP_RESERVED) ) + { + error = Gzip_Err_Invalid_File_Format; + goto Exit; + } + + /* skip time, xflags and os code */ + (void)FT_STREAM_SKIP( 6 ); + + /* skip the extra field */ + if ( head[3] & FT_GZIP_EXTRA_FIELD ) + { + FT_UInt len; + + + if ( FT_READ_USHORT_LE( len ) || + FT_STREAM_SKIP( len ) ) + goto Exit; + } + + /* skip original file name */ + if ( head[3] & FT_GZIP_ORIG_NAME ) + for (;;) + { + FT_UInt c; + + + if ( FT_READ_BYTE( c ) ) + goto Exit; + + if ( c == 0 ) + break; + } + + /* skip .gz comment */ + if ( head[3] & FT_GZIP_COMMENT ) + for (;;) + { + FT_UInt c; + + + if ( FT_READ_BYTE( c ) ) + goto Exit; + + if ( c == 0 ) + break; + } + + /* skip CRC */ + if ( head[3] & FT_GZIP_HEAD_CRC ) + if ( FT_STREAM_SKIP( 2 ) ) + goto Exit; + + Exit: + return error; + } + + + static FT_Error + ft_gzip_file_init( FT_GZipFile zip, + FT_Stream stream, + FT_Stream source ) + { + z_stream* zstream = &zip->zstream; + FT_Error error = Gzip_Err_Ok; + + + zip->stream = stream; + zip->source = source; + zip->memory = stream->memory; + + zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE; + zip->cursor = zip->limit; + zip->pos = 0; + + /* check and skip .gz header */ + { + stream = source; + + error = ft_gzip_check_header( stream ); + if ( error ) + goto Exit; + + zip->start = FT_STREAM_POS(); + } + + /* initialize zlib -- there is no zlib header in the compressed stream */ + zstream->zalloc = (alloc_func)ft_gzip_alloc; + zstream->zfree = (free_func) ft_gzip_free; + zstream->opaque = stream->memory; + + zstream->avail_in = 0; + zstream->next_in = zip->buffer; + + if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK || + zstream->next_in == NULL ) + error = Gzip_Err_Invalid_File_Format; + + Exit: + return error; + } + + + static void + ft_gzip_file_done( FT_GZipFile zip ) + { + z_stream* zstream = &zip->zstream; + + + inflateEnd( zstream ); + + /* clear the rest */ + zstream->zalloc = NULL; + zstream->zfree = NULL; + zstream->opaque = NULL; + zstream->next_in = NULL; + zstream->next_out = NULL; + zstream->avail_in = 0; + zstream->avail_out = 0; + + zip->memory = NULL; + zip->source = NULL; + zip->stream = NULL; + } + + + static FT_Error + ft_gzip_file_reset( FT_GZipFile zip ) + { + FT_Stream stream = zip->source; + FT_Error error; + + + if ( !FT_STREAM_SEEK( zip->start ) ) + { + z_stream* zstream = &zip->zstream; + + + inflateReset( zstream ); + + zstream->avail_in = 0; + zstream->next_in = zip->input; + zstream->avail_out = 0; + zstream->next_out = zip->buffer; + + zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE; + zip->cursor = zip->limit; + zip->pos = 0; + } + + return error; + } + + + static FT_Error + ft_gzip_file_fill_input( FT_GZipFile zip ) + { + z_stream* zstream = &zip->zstream; + FT_Stream stream = zip->source; + FT_ULong size; + + + if ( stream->read ) + { + size = stream->read( stream, stream->pos, zip->input, + FT_GZIP_BUFFER_SIZE ); + if ( size == 0 ) + return Gzip_Err_Invalid_Stream_Operation; + } + else + { + size = stream->size - stream->pos; + if ( size > FT_GZIP_BUFFER_SIZE ) + size = FT_GZIP_BUFFER_SIZE; + + if ( size == 0 ) + return Gzip_Err_Invalid_Stream_Operation; + + FT_MEM_COPY( zip->input, stream->base + stream->pos, size ); + } + stream->pos += size; + + zstream->next_in = zip->input; + zstream->avail_in = size; + + return Gzip_Err_Ok; + } + + + static FT_Error + ft_gzip_file_fill_output( FT_GZipFile zip ) + { + z_stream* zstream = &zip->zstream; + FT_Error error = 0; + + + zip->cursor = zip->buffer; + zstream->next_out = zip->cursor; + zstream->avail_out = FT_GZIP_BUFFER_SIZE; + + while ( zstream->avail_out > 0 ) + { + int err; + + + if ( zstream->avail_in == 0 ) + { + error = ft_gzip_file_fill_input( zip ); + if ( error ) + break; + } + + err = inflate( zstream, Z_NO_FLUSH ); + + if ( err == Z_STREAM_END ) + { + zip->limit = zstream->next_out; + if ( zip->limit == zip->cursor ) + error = Gzip_Err_Invalid_Stream_Operation; + break; + } + else if ( err != Z_OK ) + { + error = Gzip_Err_Invalid_Stream_Operation; + break; + } + } + + return error; + } + + + /* fill output buffer; `count' must be <= FT_GZIP_BUFFER_SIZE */ + static FT_Error + ft_gzip_file_skip_output( FT_GZipFile zip, + FT_ULong count ) + { + FT_Error error = Gzip_Err_Ok; + FT_ULong delta; + + + for (;;) + { + delta = (FT_ULong)( zip->limit - zip->cursor ); + if ( delta >= count ) + delta = count; + + zip->cursor += delta; + zip->pos += delta; + + count -= delta; + if ( count == 0 ) + break; + + error = ft_gzip_file_fill_output( zip ); + if ( error ) + break; + } + + return error; + } + + + static FT_ULong + ft_gzip_file_io( FT_GZipFile zip, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ) + { + FT_ULong result = 0; + FT_Error error; + + + /* Reset inflate stream if we're seeking backwards. */ + /* Yes, that is not too efficient, but it saves memory :-) */ + if ( pos < zip->pos ) + { + error = ft_gzip_file_reset( zip ); + if ( error ) + goto Exit; + } + + /* skip unwanted bytes */ + if ( pos > zip->pos ) + { + error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) ); + if ( error ) + goto Exit; + } + + if ( count == 0 ) + goto Exit; + + /* now read the data */ + for (;;) + { + FT_ULong delta; + + + delta = (FT_ULong)( zip->limit - zip->cursor ); + if ( delta >= count ) + delta = count; + + FT_MEM_COPY( buffer, zip->cursor, delta ); + buffer += delta; + result += delta; + zip->cursor += delta; + zip->pos += delta; + + count -= delta; + if ( count == 0 ) + break; + + error = ft_gzip_file_fill_output( zip ); + if ( error ) + break; + } + + Exit: + return result; + } + + +/***************************************************************************/ +/***************************************************************************/ +/***** *****/ +/***** G Z E M B E D D I N G S T R E A M *****/ +/***** *****/ +/***************************************************************************/ +/***************************************************************************/ + + static void + ft_gzip_stream_close( FT_Stream stream ) + { + FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer; + FT_Memory memory = stream->memory; + + + if ( zip ) + { + /* finalize gzip file descriptor */ + ft_gzip_file_done( zip ); + + FT_FREE( zip ); + + stream->descriptor.pointer = NULL; + } + } + + + static FT_ULong + ft_gzip_stream_io( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ) + { + FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer; + + + return ft_gzip_file_io( zip, pos, buffer, count ); + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stream_OpenGzip( FT_Stream stream, + FT_Stream source ) + { + FT_Error error; + FT_Memory memory = source->memory; + FT_GZipFile zip; + + + FT_ZERO( stream ); + stream->memory = memory; + + if ( !FT_QNEW( zip ) ) + { + error = ft_gzip_file_init( zip, stream, source ); + if ( error ) + { + FT_FREE( zip ); + goto Exit; + } + + stream->descriptor.pointer = zip; + } + + stream->size = 0x7FFFFFFFL; /* don't know the real size! */ + stream->pos = 0; + stream->base = 0; + stream->read = ft_gzip_stream_io; + stream->close = ft_gzip_stream_close; + + Exit: + return error; + } + +#else /* !FT_CONFIG_OPTION_USE_ZLIB */ + + FT_EXPORT_DEF( FT_Error ) + FT_Stream_OpenGzip( FT_Stream stream, + FT_Stream source ) + { + FT_UNUSED( stream ); + FT_UNUSED( source ); + + return Gzip_Err_Unimplemented_Feature; + } + +#endif /* !FT_CONFIG_OPTION_USE_ZLIB */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/lzw/ftlzw.c b/Utilities/vtkfreetype/src/lzw/ftlzw.c new file mode 100644 index 0000000..a0e4cc5 --- /dev/null +++ b/Utilities/vtkfreetype/src/lzw/ftlzw.c @@ -0,0 +1,463 @@ +/***************************************************************************/ +/* */ +/* ftlzw.c */ +/* */ +/* FreeType support for .Z compressed files. */ +/* */ +/* This optional component relies on NetBSD's zopen(). It should mainly */ +/* be used to parse compressed PCF fonts, as found with many X11 server */ +/* distributions. */ +/* */ +/* Copyright 2004 by */ +/* Albert Chin-A-Young. */ +/* */ +/* Based on code in src/gzip/ftgzip.c, Copyright 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#include <ft2build.h> +#include FT_INTERNAL_MEMORY_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_DEBUG_H +#include <string.h> +#include <stdio.h> + + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX LZW_Err_ +#define FT_ERR_BASE FT_Mod_Err_LZW + +#include FT_ERRORS_H + + +#ifdef FT_CONFIG_OPTION_USE_LZW + +#include "zopen.h" + + +/***************************************************************************/ +/***************************************************************************/ +/***** *****/ +/***** M E M O R Y M A N A G E M E N T *****/ +/***** *****/ +/***************************************************************************/ +/***************************************************************************/ + +/***************************************************************************/ +/***************************************************************************/ +/***** *****/ +/***** F I L E D E S C R I P T O R *****/ +/***** *****/ +/***************************************************************************/ +/***************************************************************************/ + +#define FT_LZW_BUFFER_SIZE 4096 + + typedef struct FT_LZWFileRec_ + { + FT_Stream source; /* parent/source stream */ + FT_Stream stream; /* embedding stream */ + FT_Memory memory; /* memory allocator */ + s_zstate_t zstream; /* lzw input stream */ + + FT_ULong start; /* starting position, after .Z header */ + FT_Byte input[FT_LZW_BUFFER_SIZE]; /* input buffer */ + + FT_Byte buffer[FT_LZW_BUFFER_SIZE]; /* output buffer */ + FT_ULong pos; /* position in output */ + FT_Byte* cursor; + FT_Byte* limit; + + } FT_LZWFileRec, *FT_LZWFile; + + + /* check and skip .Z header */ + static FT_Error + ft_lzw_check_header( FT_Stream stream ) + { + FT_Error error; + FT_Byte head[2]; + + + if ( FT_STREAM_SEEK( 0 ) || + FT_STREAM_READ( head, 2 ) ) + goto Exit; + + /* head[0] && head[1] are the magic numbers */ + if ( head[0] != 0x1f || + head[1] != 0x9d ) + error = LZW_Err_Invalid_File_Format; + + Exit: + return error; + } + + + static FT_Error + ft_lzw_file_init( FT_LZWFile zip, + FT_Stream stream, + FT_Stream source ) + { + s_zstate_t* zstream = &zip->zstream; + FT_Error error = LZW_Err_Ok; + + + zip->stream = stream; + zip->source = source; + zip->memory = stream->memory; + + zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE; + zip->cursor = zip->limit; + zip->pos = 0; + + /* check and skip .Z header */ + { + stream = source; + + error = ft_lzw_check_header( source ); + if ( error ) + goto Exit; + + zip->start = FT_STREAM_POS(); + } + + /* initialize internal lzw variable */ + zinit( zstream ); + + zstream->avail_in = 0; + zstream->next_in = zip->buffer; + zstream->zs_in_count = source->size - 2; + + if ( zstream->next_in == NULL ) + error = LZW_Err_Invalid_File_Format; + + Exit: + return error; + } + + + static void + ft_lzw_file_done( FT_LZWFile zip ) + { + s_zstate_t* zstream = &zip->zstream; + + + /* clear the rest */ + zstream->next_in = NULL; + zstream->next_out = NULL; + zstream->avail_in = 0; + zstream->avail_out = 0; + zstream->total_in = 0; + zstream->total_out = 0; + + zip->memory = NULL; + zip->source = NULL; + zip->stream = NULL; + } + + + static FT_Error + ft_lzw_file_reset( FT_LZWFile zip ) + { + FT_Stream stream = zip->source; + FT_Error error; + + + if ( !FT_STREAM_SEEK( zip->start ) ) + { + s_zstate_t* zstream = &zip->zstream; + + + zinit( zstream ); + + zstream->avail_in = 0; + zstream->next_in = zip->input; + zstream->total_in = 0; + zstream->avail_out = 0; + zstream->next_out = zip->buffer; + zstream->total_out = 0; + zstream->zs_in_count = zip->source->size - 2; + + zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE; + zip->cursor = zip->limit; + zip->pos = 0; + } + + return error; + } + + + static FT_Error + ft_lzw_file_fill_input( FT_LZWFile zip ) + { + s_zstate_t* zstream = &zip->zstream; + FT_Stream stream = zip->source; + FT_ULong size; + + + if ( stream->read ) + { + size = stream->read( stream, stream->pos, zip->input, + FT_LZW_BUFFER_SIZE ); + if ( size == 0 ) + return LZW_Err_Invalid_Stream_Operation; + } + else + { + size = stream->size - stream->pos; + if ( size > FT_LZW_BUFFER_SIZE ) + size = FT_LZW_BUFFER_SIZE; + + if ( size == 0 ) + return LZW_Err_Invalid_Stream_Operation; + + FT_MEM_COPY( zip->input, stream->base + stream->pos, size ); + } + stream->pos += size; + + zstream->next_in = zip->input; + zstream->avail_in = size; + + return LZW_Err_Ok; + } + + + + static FT_Error + ft_lzw_file_fill_output( FT_LZWFile zip ) + { + s_zstate_t* zstream = &zip->zstream; + FT_Error error = 0; + + + zip->cursor = zip->buffer; + zstream->next_out = zip->cursor; + zstream->avail_out = FT_LZW_BUFFER_SIZE; + + while ( zstream->avail_out > 0 ) + { + int num_read = 0; + + + if ( zstream->avail_in == 0 ) + { + error = ft_lzw_file_fill_input( zip ); + if ( error ) + break; + } + + num_read = zread( zstream ); + + if ( num_read == -1 && zstream->zs_in_count == 0 ) + { + zip->limit = zstream->next_out; + if ( zip->limit == zip->cursor ) + error = LZW_Err_Invalid_Stream_Operation; + break; + } + else if ( num_read == -1 ) + break; + else + zstream->avail_out -= num_read; + } + + return error; + } + + + /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */ + static FT_Error + ft_lzw_file_skip_output( FT_LZWFile zip, + FT_ULong count ) + { + FT_Error error = LZW_Err_Ok; + FT_ULong delta; + + + for (;;) + { + delta = (FT_ULong)( zip->limit - zip->cursor ); + if ( delta >= count ) + delta = count; + + zip->cursor += delta; + zip->pos += delta; + + count -= delta; + if ( count == 0 ) + break; + + error = ft_lzw_file_fill_output( zip ); + if ( error ) + break; + } + + return error; + } + + + static FT_ULong + ft_lzw_file_io( FT_LZWFile zip, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ) + { + FT_ULong result = 0; + FT_Error error; + + + /* Teset inflate stream if we're seeking backwards. */ + /* Yes, that is not too efficient, but it saves memory :-) */ + if ( pos < zip->pos ) + { + error = ft_lzw_file_reset( zip ); + if ( error ) + goto Exit; + } + + /* skip unwanted bytes */ + if ( pos > zip->pos ) + { + error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) ); + if ( error ) + goto Exit; + } + + if ( count == 0 ) + goto Exit; + + /* now read the data */ + for (;;) + { + FT_ULong delta; + + + delta = (FT_ULong)( zip->limit - zip->cursor ); + if ( delta >= count ) + delta = count; + + FT_MEM_COPY( buffer, zip->cursor, delta ); + buffer += delta; + result += delta; + zip->cursor += delta; + zip->pos += delta; + + count -= delta; + if ( count == 0 ) + break; + + error = ft_lzw_file_fill_output( zip ); + if ( error ) + break; + } + + Exit: + return result; + } + + +/***************************************************************************/ +/***************************************************************************/ +/***** *****/ +/***** L Z W E M B E D D I N G S T R E A M *****/ +/***** *****/ +/***************************************************************************/ +/***************************************************************************/ + + static void + ft_lzw_stream_close( FT_Stream stream ) + { + FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer; + FT_Memory memory = stream->memory; + + + if ( zip ) + { + /* finalize lzw file descriptor */ + ft_lzw_file_done( zip ); + + FT_FREE( zip ); + + stream->descriptor.pointer = NULL; + } + } + + + static FT_ULong + ft_lzw_stream_io( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ) + { + FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer; + + + return ft_lzw_file_io( zip, pos, buffer, count ); + } + + + FT_EXPORT_DEF( FT_Error ) + FT_Stream_OpenLZW( FT_Stream stream, + FT_Stream source ) + { + FT_Error error; + FT_Memory memory = source->memory; + FT_LZWFile zip; + + + FT_ZERO( stream ); + stream->memory = memory; + + if ( !FT_NEW( zip ) ) + { + error = ft_lzw_file_init( zip, stream, source ); + if ( error ) + { + FT_FREE( zip ); + goto Exit; + } + + stream->descriptor.pointer = zip; + } + + stream->size = 0x7FFFFFFFL; /* don't know the real size! */ + stream->pos = 0; + stream->base = 0; + stream->read = ft_lzw_stream_io; + stream->close = ft_lzw_stream_close; + + Exit: + return error; + } + +#include "zopen.c" + + +#else /* !FT_CONFIG_OPTION_USE_LZW */ + + + FT_EXPORT_DEF( FT_Error ) + FT_Stream_OpenLZW( FT_Stream stream, + FT_Stream source ) + { + FT_UNUSED( stream ); + FT_UNUSED( source ); + + return LZW_Err_Unimplemented_Feature; + } + + +#endif /* !FT_CONFIG_OPTION_USE_LZW */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcf.c b/Utilities/vtkfreetype/src/pcf/pcf.c new file mode 100644 index 0000000..11d5b7b --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcf.c @@ -0,0 +1,36 @@ +/* pcf.c + + FreeType font driver for pcf fonts + + Copyright 2000-2001, 2003 by + Francesco Zappa Nardelli + +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. +*/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#include <ft2build.h> +#include "pcfutil.c" +#include "pcfread.c" +#include "pcfdrivr.c" + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcf.h b/Utilities/vtkfreetype/src/pcf/pcf.h new file mode 100644 index 0000000..64acefc --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcf.h @@ -0,0 +1,237 @@ +/* pcf.h + + FreeType font driver for pcf fonts + + Copyright (C) 2000, 2001, 2002, 2003 by + Francesco Zappa Nardelli + +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. +*/ + + +#ifndef __PCF_H__ +#define __PCF_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H +#include FT_INTERNAL_STREAM_H + + +FT_BEGIN_HEADER + + typedef struct PCF_TableRec_ + { + FT_ULong type; + FT_ULong format; + FT_ULong size; + FT_ULong offset; + + } PCF_TableRec, *PCF_Table; + + + typedef struct PCF_TocRec_ + { + FT_ULong version; + FT_ULong count; + PCF_Table tables; + + } PCF_TocRec, *PCF_Toc; + + + typedef struct PCF_ParsePropertyRec_ + { + FT_Long name; + FT_Byte isString; + FT_Long value; + + } PCF_ParsePropertyRec, *PCF_ParseProperty; + + + typedef struct PCF_PropertyRec_ + { + FT_String* name; + FT_Byte isString; + + union + { + FT_String* atom; + FT_Long integer; + FT_ULong cardinal; + + } value; + + } PCF_PropertyRec, *PCF_Property; + + + typedef struct PCF_Compressed_MetricRec_ + { + FT_Byte leftSideBearing; + FT_Byte rightSideBearing; + FT_Byte characterWidth; + FT_Byte ascent; + FT_Byte descent; + + } PCF_Compressed_MetricRec, *PCF_Compressed_Metric; + + + typedef struct PCF_MetricRec_ + { + FT_Short leftSideBearing; + FT_Short rightSideBearing; + FT_Short characterWidth; + FT_Short ascent; + FT_Short descent; + FT_Short attributes; + FT_ULong bits; + + } PCF_MetricRec, *PCF_Metric; + + + typedef struct PCF_AccelRec_ + { + FT_Byte noOverlap; + FT_Byte constantMetrics; + FT_Byte terminalFont; + FT_Byte constantWidth; + FT_Byte inkInside; + FT_Byte inkMetrics; + FT_Byte drawDirection; + FT_Long fontAscent; + FT_Long fontDescent; + FT_Long maxOverlap; + PCF_MetricRec minbounds; + PCF_MetricRec maxbounds; + PCF_MetricRec ink_minbounds; + PCF_MetricRec ink_maxbounds; + + } PCF_AccelRec, *PCF_Accel; + + + typedef struct PCF_EncodingRec_ + { + FT_Long enc; + FT_UShort glyph; + + } PCF_EncodingRec, *PCF_Encoding; + + + typedef struct PCF_FaceRec_ + { + FT_FaceRec root; + + FT_StreamRec gzip_stream; + FT_Stream gzip_source; + + char* charset_encoding; + char* charset_registry; + + PCF_TocRec toc; + PCF_AccelRec accel; + + int nprops; + PCF_Property properties; + + FT_Long nmetrics; + PCF_Metric metrics; + FT_Long nencodings; + PCF_Encoding encodings; + + FT_Short defaultChar; + + FT_ULong bitmapsFormat; + + FT_CharMap charmap_handle; + FT_CharMapRec charmap; /* a single charmap per face */ + + } PCF_FaceRec, *PCF_Face; + + + /* macros for pcf font format */ + +#define LSBFirst 0 +#define MSBFirst 1 + +#define PCF_FILE_VERSION ( ( 'p' << 24 ) | \ + ( 'c' << 16 ) | \ + ( 'f' << 8 ) | 1 ) +#define PCF_FORMAT_MASK 0xFFFFFF00L + +#define PCF_DEFAULT_FORMAT 0x00000000L +#define PCF_INKBOUNDS 0x00000200L +#define PCF_ACCEL_W_INKBOUNDS 0x00000100L +#define PCF_COMPRESSED_METRICS 0x00000100L + +#define PCF_FORMAT_MATCH( a, b ) \ + ( ( (a) & PCF_FORMAT_MASK ) == ( (b) & PCF_FORMAT_MASK ) ) + +#define PCF_GLYPH_PAD_MASK ( 3 << 0 ) +#define PCF_BYTE_MASK ( 1 << 2 ) +#define PCF_BIT_MASK ( 1 << 3 ) +#define PCF_SCAN_UNIT_MASK ( 3 << 4 ) + +#define PCF_BYTE_ORDER( f ) \ + ( ( (f) & PCF_BYTE_MASK ) ? MSBFirst : LSBFirst ) +#define PCF_BIT_ORDER( f ) \ + ( ( (f) & PCF_BIT_MASK ) ? MSBFirst : LSBFirst ) +#define PCF_GLYPH_PAD_INDEX( f ) \ + ( (f) & PCF_GLYPH_PAD_MASK ) +#define PCF_GLYPH_PAD( f ) \ + ( 1 << PCF_GLYPH_PAD_INDEX( f ) ) +#define PCF_SCAN_UNIT_INDEX( f ) \ + ( ( (f) & PCF_SCAN_UNIT_MASK ) >> 4 ) +#define PCF_SCAN_UNIT( f ) \ + ( 1 << PCF_SCAN_UNIT_INDEX( f ) ) +#define PCF_FORMAT_BITS( f ) \ + ( (f) & ( PCF_GLYPH_PAD_MASK | \ + PCF_BYTE_MASK | \ + PCF_BIT_MASK | \ + PCF_SCAN_UNIT_MASK ) ) + +#define PCF_SIZE_TO_INDEX( s ) ( (s) == 4 ? 2 : (s) == 2 ? 1 : 0 ) +#define PCF_INDEX_TO_SIZE( b ) ( 1 << b ) + +#define PCF_FORMAT( bit, byte, glyph, scan ) \ + ( ( PCF_SIZE_TO_INDEX( scan ) << 4 ) | \ + ( ( (bit) == MSBFirst ? 1 : 0 ) << 3 ) | \ + ( ( (byte) == MSBFirst ? 1 : 0 ) << 2 ) | \ + ( PCF_SIZE_TO_INDEX( glyph ) << 0 ) ) + +#define PCF_PROPERTIES ( 1 << 0 ) +#define PCF_ACCELERATORS ( 1 << 1 ) +#define PCF_METRICS ( 1 << 2 ) +#define PCF_BITMAPS ( 1 << 3 ) +#define PCF_INK_METRICS ( 1 << 4 ) +#define PCF_BDF_ENCODINGS ( 1 << 5 ) +#define PCF_SWIDTHS ( 1 << 6 ) +#define PCF_GLYPH_NAMES ( 1 << 7 ) +#define PCF_BDF_ACCELERATORS ( 1 << 8 ) + +#define GLYPHPADOPTIONS 4 /* I'm not sure about this */ + + FT_LOCAL( FT_Error ) + pcf_load_font( FT_Stream, + PCF_Face ); + +FT_END_HEADER + +#endif /* __PCF_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcfdrivr.c b/Utilities/vtkfreetype/src/pcf/pcfdrivr.c new file mode 100644 index 0000000..b6b04b9 --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcfdrivr.c @@ -0,0 +1,651 @@ +/* pcfdrivr.c + + FreeType font driver for pcf files + + Copyright (C) 2000, 2001, 2002, 2003, 2004 by + Francesco Zappa Nardelli + +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. +*/ + + +#include <ft2build.h> + +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H +#include FT_GZIP_H +#include FT_LZW_H +#include FT_ERRORS_H +#include FT_BDF_H + +#include "pcf.h" +#include "pcfdrivr.h" +#include "pcfread.h" + +#include "pcferror.h" +#include "pcfutil.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pcfread + +#include FT_SERVICE_BDF_H +#include FT_SERVICE_XFREE86_NAME_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_pcfdriver + + + typedef struct PCF_CMapRec_ + { + FT_CMapRec root; + FT_UInt num_encodings; + PCF_Encoding encodings; + + } PCF_CMapRec, *PCF_CMap; + + + FT_CALLBACK_DEF( FT_Error ) + pcf_cmap_init( FT_CMap pcfcmap, /* PCF_CMap */ + FT_Pointer init_data ) + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_Face face = (PCF_Face)FT_CMAP_FACE( pcfcmap ); + + FT_UNUSED( init_data ); + + + cmap->num_encodings = (FT_UInt)face->nencodings; + cmap->encodings = face->encodings; + + return PCF_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + pcf_cmap_done( FT_CMap pcfcmap ) /* PCF_CMap */ + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + + + cmap->encodings = NULL; + cmap->num_encodings = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + pcf_cmap_char_index( FT_CMap pcfcmap, /* PCF_CMap */ + FT_UInt32 charcode ) + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_Encoding encodings = cmap->encodings; + FT_UInt min, max, mid; + FT_UInt result = 0; + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_UInt32 code; + + + mid = ( min + max ) >> 1; + code = encodings[mid].enc; + + if ( charcode == code ) + { + result = encodings[mid].glyph + 1; + break; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + pcf_cmap_char_next( FT_CMap pcfcmap, /* PCF_CMap */ + FT_UInt32 *acharcode ) + { + PCF_CMap cmap = (PCF_CMap)pcfcmap; + PCF_Encoding encodings = cmap->encodings; + FT_UInt min, max, mid; + FT_UInt32 charcode = *acharcode + 1; + FT_UInt result = 0; + + + min = 0; + max = cmap->num_encodings; + + while ( min < max ) + { + FT_UInt32 code; + + + mid = ( min + max ) >> 1; + code = encodings[mid].enc; + + if ( charcode == code ) + { + result = encodings[mid].glyph + 1; + goto Exit; + } + + if ( charcode < code ) + max = mid; + else + min = mid + 1; + } + + charcode = 0; + if ( min < cmap->num_encodings ) + { + charcode = encodings[min].enc; + result = encodings[min].glyph + 1; + } + + Exit: + *acharcode = charcode; + return result; + } + + + FT_CALLBACK_TABLE_DEF + const FT_CMap_ClassRec pcf_cmap_class = + { + sizeof ( PCF_CMapRec ), + pcf_cmap_init, + pcf_cmap_done, + pcf_cmap_char_index, + pcf_cmap_char_next + }; + + + FT_CALLBACK_DEF( void ) + PCF_Face_Done( FT_Face pcfface ) /* PCF_Face */ + { + PCF_Face face = (PCF_Face)pcfface; + FT_Memory memory = FT_FACE_MEMORY( face ); + + + FT_FREE( face->encodings ); + FT_FREE( face->metrics ); + + /* free properties */ + { + PCF_Property prop = face->properties; + FT_Int i; + + + for ( i = 0; i < face->nprops; i++ ) + { + prop = &face->properties[i]; + + FT_FREE( prop->name ); + if ( prop->isString ) + FT_FREE( prop->value ); + } + + FT_FREE( face->properties ); + } + + FT_FREE( face->toc.tables ); + FT_FREE( pcfface->family_name ); + FT_FREE( pcfface->available_sizes ); + FT_FREE( face->charset_encoding ); + FT_FREE( face->charset_registry ); + + FT_TRACE4(( "PCF_Face_Done: done face\n" )); + + /* close gzip/LZW stream if any */ + if ( pcfface->stream == &face->gzip_stream ) + { + FT_Stream_Close( &face->gzip_stream ); + pcfface->stream = face->gzip_source; + } + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Face_Init( FT_Stream stream, + FT_Face pcfface, /* PCF_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + PCF_Face face = (PCF_Face)pcfface; + FT_Error error = PCF_Err_Ok; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + + + error = pcf_load_font( stream, face ); + if ( error ) + { + FT_Error error2; + + + /* this didn't work, try gzip support! */ + error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream ); + if ( FT_ERROR_BASE( error2 ) == FT_Err_Unimplemented_Feature ) + goto Fail; + + error = error2; + if ( error ) + { + FT_Error error3; + + + /* this didn't work, try LZW support! */ + error3 = FT_Stream_OpenLZW( &face->gzip_stream, stream ); + if ( FT_ERROR_BASE( error3 ) == FT_Err_Unimplemented_Feature ) + goto Fail; + + error = error3; + if ( error ) + goto Fail; + + face->gzip_source = stream; + pcfface->stream = &face->gzip_stream; + + stream = pcfface->stream; + + error = pcf_load_font( stream, face ); + if ( error ) + goto Fail; + } + else + { + face->gzip_source = stream; + pcfface->stream = &face->gzip_stream; + + stream = pcfface->stream; + + error = pcf_load_font( stream, face ); + if ( error ) + goto Fail; + } + } + + /* set up charmap */ + { + FT_String *charset_registry = face->charset_registry; + FT_String *charset_encoding = face->charset_encoding; + FT_Bool unicode_charmap = 0; + + + if ( charset_registry && charset_encoding ) + { + char* s = charset_registry; + + + /* Uh, oh, compare first letters manually to avoid dependency + on locales. */ + if ( ( s[0] == 'i' || s[0] == 'I' ) && + ( s[1] == 's' || s[1] == 'S' ) && + ( s[2] == 'o' || s[2] == 'O' ) ) + { + s += 3; + if ( !ft_strcmp( s, "10646" ) || + ( !ft_strcmp( s, "8859" ) && + !ft_strcmp( face->charset_encoding, "1" ) ) ) + unicode_charmap = 1; + } + } + + { + FT_CharMapRec charmap; + + + charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_NONE; + charmap.platform_id = 0; + charmap.encoding_id = 0; + + if ( unicode_charmap ) + { + charmap.encoding = FT_ENCODING_UNICODE; + charmap.platform_id = 3; + charmap.encoding_id = 1; + } + + error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL ); + +#if 0 + /* Select default charmap */ + if ( pcfface->num_charmaps ) + pcfface->charmap = pcfface->charmaps[0]; +#endif + } + } + + Exit: + return error; + + Fail: + FT_TRACE2(( "[not a valid PCF file]\n" )); + error = PCF_Err_Unknown_File_Format; /* error */ + goto Exit; + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Set_Pixel_Size( FT_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ) + { + PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); + + FT_UNUSED( pixel_width ); + FT_UNUSED( pixel_height ); + + + FT_TRACE4(( "rec %d - pres %d\n", size->metrics.y_ppem, + face->root.available_sizes->y_ppem >> 6 )); + + if ( size->metrics.y_ppem == face->root.available_sizes->y_ppem >> 6 ) + { + size->metrics.ascender = face->accel.fontAscent << 6; + size->metrics.descender = face->accel.fontDescent * (-64); +#if 0 + size->metrics.height = face->accel.maxbounds.ascent << 6; +#endif + size->metrics.height = size->metrics.ascender - + size->metrics.descender; + + size->metrics.max_advance = face->accel.maxbounds.characterWidth << 6; + + return PCF_Err_Ok; + } + else + { + FT_TRACE4(( "size WRONG\n" )); + return PCF_Err_Invalid_Pixel_Size; + } + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Set_Point_Size( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + FT_UNUSED( horz_resolution ); + FT_UNUSED( vert_resolution ); + + return PCF_Set_Pixel_Size( size, 0, 0 ); + } + + + FT_CALLBACK_DEF( FT_Error ) + PCF_Glyph_Load( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + PCF_Face face = (PCF_Face)FT_SIZE_FACE( size ); + FT_Stream stream = face->root.stream; + FT_Error error = PCF_Err_Ok; + FT_Bitmap* bitmap = &slot->bitmap; + PCF_Metric metric; + int bytes; + + FT_UNUSED( load_flags ); + + + FT_TRACE4(( "load_glyph %d ---", glyph_index )); + + if ( !face ) + { + error = PCF_Err_Invalid_Argument; + goto Exit; + } + + if ( glyph_index > 0 ) + glyph_index--; + + metric = face->metrics + glyph_index; + + bitmap->rows = metric->ascent + metric->descent; + bitmap->width = metric->rightSideBearing - metric->leftSideBearing; + bitmap->num_grays = 1; + bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + + FT_TRACE6(( "BIT_ORDER %d ; BYTE_ORDER %d ; GLYPH_PAD %d\n", + PCF_BIT_ORDER( face->bitmapsFormat ), + PCF_BYTE_ORDER( face->bitmapsFormat ), + PCF_GLYPH_PAD( face->bitmapsFormat ) )); + + switch ( PCF_GLYPH_PAD( face->bitmapsFormat ) ) + { + case 1: + bitmap->pitch = ( bitmap->width + 7 ) >> 3; + break; + + case 2: + bitmap->pitch = ( ( bitmap->width + 15 ) >> 4 ) << 1; + break; + + case 4: + bitmap->pitch = ( ( bitmap->width + 31 ) >> 5 ) << 2; + break; + + case 8: + bitmap->pitch = ( ( bitmap->width + 63 ) >> 6 ) << 3; + break; + + default: + return PCF_Err_Invalid_File_Format; + } + + /* XXX: to do: are there cases that need repadding the bitmap? */ + bytes = bitmap->pitch * bitmap->rows; + + error = ft_glyphslot_alloc_bitmap( slot, bytes ); + if ( error ) + goto Exit; + + if ( FT_STREAM_SEEK( metric->bits ) || + FT_STREAM_READ( bitmap->buffer, bytes ) ) + goto Exit; + + if ( PCF_BIT_ORDER( face->bitmapsFormat ) != MSBFirst ) + BitOrderInvert( bitmap->buffer, bytes ); + + if ( ( PCF_BYTE_ORDER( face->bitmapsFormat ) != + PCF_BIT_ORDER( face->bitmapsFormat ) ) ) + { + switch ( PCF_SCAN_UNIT( face->bitmapsFormat ) ) + { + case 1: + break; + + case 2: + TwoByteSwap( bitmap->buffer, bytes ); + break; + + case 4: + FourByteSwap( bitmap->buffer, bytes ); + break; + } + } + + slot->bitmap_left = metric->leftSideBearing; + slot->bitmap_top = metric->ascent; + + slot->metrics.horiAdvance = metric->characterWidth << 6; + slot->metrics.horiBearingX = metric->leftSideBearing << 6; + slot->metrics.horiBearingY = metric->ascent << 6; + slot->metrics.width = ( metric->rightSideBearing - + metric->leftSideBearing ) << 6; + slot->metrics.height = bitmap->rows << 6; + + slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16; + slot->format = FT_GLYPH_FORMAT_BITMAP; + + FT_TRACE4(( " --- ok\n" )); + + Exit: + return error; + } + + + /* + * + * BDF SERVICE + * + */ + + static FT_Error + pcf_get_bdf_property( PCF_Face face, + const char* prop_name, + BDF_PropertyRec *aproperty ) + { + PCF_Property prop; + + + prop = pcf_find_property( face, prop_name ); + if ( prop != NULL ) + { + if ( prop->isString ) + { + aproperty->type = BDF_PROPERTY_TYPE_ATOM; + aproperty->u.atom = prop->value.atom; + } + else + { + /* Apparently, the PCF driver loads all properties as signed integers! + * This really doesn't seem to be a problem, because this is + * sufficient for any meaningful values. + */ + aproperty->type = BDF_PROPERTY_TYPE_INTEGER; + aproperty->u.integer = prop->value.integer; + } + return 0; + } + + return PCF_Err_Invalid_Argument; + } + + + static FT_Error + pcf_get_charset_id( PCF_Face face, + const char* *acharset_encoding, + const char* *acharset_registry ) + { + *acharset_encoding = face->charset_encoding; + *acharset_registry = face->charset_registry; + + return 0; + } + + + static const FT_Service_BDFRec pcf_service_bdf = + { + (FT_BDF_GetCharsetIdFunc)pcf_get_charset_id, + (FT_BDF_GetPropertyFunc) pcf_get_bdf_property + }; + + + /* + * + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec pcf_services[] = + { + { FT_SERVICE_ID_BDF, &pcf_service_bdf }, + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PCF }, + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + pcf_driver_requester( FT_Module module, + const char* name ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( pcf_services, name ); + } + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec pcf_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_NO_OUTLINES, + sizeof ( FT_DriverRec ), + + "pcf", + 0x10000L, + 0x20000L, + + 0, + + 0, + 0, + pcf_driver_requester + }, + + sizeof ( PCF_FaceRec ), + sizeof ( FT_SizeRec ), + sizeof ( FT_GlyphSlotRec ), + + PCF_Face_Init, + PCF_Face_Done, + 0, /* FT_Size_InitFunc */ + 0, /* FT_Size_DoneFunc */ + 0, /* FT_Slot_InitFunc */ + 0, /* FT_Slot_DoneFunc */ + + PCF_Set_Point_Size, + PCF_Set_Pixel_Size, + + PCF_Glyph_Load, + + 0, /* FT_Face_GetKerningFunc */ + 0, /* FT_Face_AttachFunc */ + 0 /* FT_Face_GetAdvancesFunc */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcfdrivr.h b/Utilities/vtkfreetype/src/pcf/pcfdrivr.h new file mode 100644 index 0000000..7ddf697 --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcfdrivr.h @@ -0,0 +1,44 @@ +/* pcfdrivr.h + + FreeType font driver for pcf fonts + + Copyright 2000-2001, 2002 by + Francesco Zappa Nardelli + +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. +*/ + + +#ifndef __PCFDRIVR_H__ +#define __PCFDRIVR_H__ + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + +FT_BEGIN_HEADER + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) pcf_driver_class; + +FT_END_HEADER + + +#endif /* __PCFDRIVR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcferror.h b/Utilities/vtkfreetype/src/pcf/pcferror.h new file mode 100644 index 0000000..d75c067 --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcferror.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* pcferror.h */ +/* */ +/* PCF error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the PCF error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __PCFERROR_H__ +#define __PCFERROR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX PCF_Err_ +#define FT_ERR_BASE FT_Mod_Err_PCF + +#include FT_ERRORS_H + +#endif /* __PCFERROR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcfread.c b/Utilities/vtkfreetype/src/pcf/pcfread.c new file mode 100644 index 0000000..383daaa --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcfread.c @@ -0,0 +1,1175 @@ +/* pcfread.c + + FreeType font driver for pcf fonts + + Copyright 2000, 2001, 2002, 2003, 2004 by + Francesco Zappa Nardelli + +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. +*/ + + +#include <ft2build.h> + +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H + +#include "pcf.h" +#include "pcfdrivr.h" +#include "pcfread.h" + +#include "pcferror.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_pcfread + + +#if defined( FT_DEBUG_LEVEL_TRACE ) + static const char* const tableNames[] = + { + "prop", "accl", "mtrcs", "bmps", "imtrcs", + "enc", "swidth", "names", "accel" + }; +#endif + + + static + const FT_Frame_Field pcf_toc_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_TocRec + + FT_FRAME_START( 8 ), + FT_FRAME_ULONG_LE( version ), + FT_FRAME_ULONG_LE( count ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_table_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_TableRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG_LE( type ), + FT_FRAME_ULONG_LE( format ), + FT_FRAME_ULONG_LE( size ), + FT_FRAME_ULONG_LE( offset ), + FT_FRAME_END + }; + + + static FT_Error + pcf_read_TOC( FT_Stream stream, + PCF_Face face ) + { + FT_Error error; + PCF_Toc toc = &face->toc; + PCF_Table tables; + + FT_Memory memory = FT_FACE(face)->memory; + FT_UInt n; + + + if ( FT_STREAM_SEEK ( 0 ) || + FT_STREAM_READ_FIELDS ( pcf_toc_header, toc ) ) + return PCF_Err_Cannot_Open_Resource; + + if ( toc->version != PCF_FILE_VERSION ) + return PCF_Err_Invalid_File_Format; + + if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) ) + return PCF_Err_Out_Of_Memory; + + tables = face->toc.tables; + for ( n = 0; n < toc->count; n++ ) + { + if ( FT_STREAM_READ_FIELDS( pcf_table_header, tables ) ) + goto Exit; + tables++; + } + +#if defined( FT_DEBUG_LEVEL_TRACE ) + + { + FT_UInt i, j; + const char* name = "?"; + + + FT_TRACE4(( "pcf_read_TOC:\n" )); + + FT_TRACE4(( " number of tables: %ld\n", face->toc.count )); + + tables = face->toc.tables; + for ( i = 0; i < toc->count; i++ ) + { + for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ ) + if ( tables[i].type == (FT_UInt)( 1 << j ) ) + name = tableNames[j]; + + FT_TRACE4(( " %d: type=%s, format=0x%X, " + "size=%ld (0x%lX), offset=%ld (0x%lX)\n", + i, name, + tables[i].format, + tables[i].size, tables[i].size, + tables[i].offset, tables[i].offset )); + } + } + +#endif + + return PCF_Err_Ok; + + Exit: + FT_FREE( face->toc.tables ); + return error; + } + + + static + const FT_Frame_Field pcf_metric_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_MetricRec + + FT_FRAME_START( 12 ), + FT_FRAME_SHORT_LE( leftSideBearing ), + FT_FRAME_SHORT_LE( rightSideBearing ), + FT_FRAME_SHORT_LE( characterWidth ), + FT_FRAME_SHORT_LE( ascent ), + FT_FRAME_SHORT_LE( descent ), + FT_FRAME_SHORT_LE( attributes ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_metric_msb_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_MetricRec + + FT_FRAME_START( 12 ), + FT_FRAME_SHORT( leftSideBearing ), + FT_FRAME_SHORT( rightSideBearing ), + FT_FRAME_SHORT( characterWidth ), + FT_FRAME_SHORT( ascent ), + FT_FRAME_SHORT( descent ), + FT_FRAME_SHORT( attributes ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_compressed_metric_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_Compressed_MetricRec + + FT_FRAME_START( 5 ), + FT_FRAME_BYTE( leftSideBearing ), + FT_FRAME_BYTE( rightSideBearing ), + FT_FRAME_BYTE( characterWidth ), + FT_FRAME_BYTE( ascent ), + FT_FRAME_BYTE( descent ), + FT_FRAME_END + }; + + + static FT_Error + pcf_get_metric( FT_Stream stream, + FT_ULong format, + PCF_Metric metric ) + { + FT_Error error = PCF_Err_Ok; + + + if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + { + const FT_Frame_Field* fields; + + + /* parsing normal metrics */ + fields = PCF_BYTE_ORDER( format ) == MSBFirst + ? pcf_metric_msb_header + : pcf_metric_header; + + /* the following sets 'error' but doesn't return in case of failure */ + (void)FT_STREAM_READ_FIELDS( fields, metric ); + } + else + { + PCF_Compressed_MetricRec compr; + + + /* parsing compressed metrics */ + if ( FT_STREAM_READ_FIELDS( pcf_compressed_metric_header, &compr ) ) + goto Exit; + + metric->leftSideBearing = (FT_Short)( compr.leftSideBearing - 0x80 ); + metric->rightSideBearing = (FT_Short)( compr.rightSideBearing - 0x80 ); + metric->characterWidth = (FT_Short)( compr.characterWidth - 0x80 ); + metric->ascent = (FT_Short)( compr.ascent - 0x80 ); + metric->descent = (FT_Short)( compr.descent - 0x80 ); + metric->attributes = 0; + } + + Exit: + return error; + } + + + static FT_Error + pcf_seek_to_table_type( FT_Stream stream, + PCF_Table tables, + FT_Int ntables, + FT_ULong type, + FT_ULong *aformat, + FT_ULong *asize ) + { + FT_Error error = PCF_Err_Invalid_File_Format; + FT_Int i; + + + for ( i = 0; i < ntables; i++ ) + if ( tables[i].type == type ) + { + if ( stream->pos > tables[i].offset ) { + error = PCF_Err_Invalid_Stream_Skip; + goto Fail; + } + + if ( FT_STREAM_SKIP( tables[i].offset - stream->pos ) ) { + error = PCF_Err_Invalid_Stream_Skip; + goto Fail; + } + + *asize = tables[i].size; /* unused - to be removed */ + *aformat = tables[i].format; + + return PCF_Err_Ok; + } + + Fail: + return error; + } + + + static FT_Bool + pcf_has_table_type( PCF_Table tables, + FT_Int ntables, + FT_ULong type ) + { + FT_Int i; + + + for ( i = 0; i < ntables; i++ ) + if ( tables[i].type == type ) + return TRUE; + + return FALSE; + } + + + static + const FT_Frame_Field pcf_property_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_ParsePropertyRec + + FT_FRAME_START( 9 ), + FT_FRAME_LONG_LE( name ), + FT_FRAME_BYTE ( isString ), + FT_FRAME_LONG_LE( value ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_property_msb_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_ParsePropertyRec + + FT_FRAME_START( 9 ), + FT_FRAME_LONG( name ), + FT_FRAME_BYTE( isString ), + FT_FRAME_LONG( value ), + FT_FRAME_END + }; + + + FT_LOCAL_DEF( PCF_Property ) + pcf_find_property( PCF_Face face, + const FT_String* prop ) + { + PCF_Property properties = face->properties; + FT_Bool found = 0; + int i; + + + for ( i = 0 ; i < face->nprops && !found; i++ ) + { + if ( !ft_strcmp( properties[i].name, prop ) ) + found = 1; + } + + if ( found ) + return properties + i - 1; + else + return NULL; + } + + + static FT_Error + pcf_get_properties( FT_Stream stream, + PCF_Face face ) + { + PCF_ParseProperty props = 0; + PCF_Property properties = 0; + FT_Int nprops, i; + FT_ULong format, size; + FT_Error error; + FT_Memory memory = FT_FACE(face)->memory; + FT_ULong string_size; + FT_String* strings = 0; + + + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + PCF_PROPERTIES, + &format, + &size ); + if ( error ) + goto Bail; + + if ( FT_READ_ULONG_LE( format ) ) + goto Bail; + + FT_TRACE4(( "pcf_get_properties:\n" )); + + FT_TRACE4(( " format = %ld\n", format )); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + goto Bail; + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)FT_READ_ULONG( nprops ); + else + (void)FT_READ_ULONG_LE( nprops ); + if ( error ) + goto Bail; + + FT_TRACE4(( " nprop = %d\n", nprops )); + + if ( FT_NEW_ARRAY( props, nprops ) ) + goto Bail; + + for ( i = 0; i < nprops; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + { + if ( FT_STREAM_READ_FIELDS( pcf_property_msb_header, props + i ) ) + goto Bail; + } + else + { + if ( FT_STREAM_READ_FIELDS( pcf_property_header, props + i ) ) + goto Bail; + } + } + + /* pad the property array */ + /* */ + /* clever here - nprops is the same as the number of odd-units read, */ + /* as only isStringProp are odd length (Keith Packard) */ + /* */ + if ( nprops & 3 ) + { + i = 4 - ( nprops & 3 ); + FT_Stream_Skip( stream, i ); + } + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)FT_READ_ULONG( string_size ); + else + (void)FT_READ_ULONG_LE( string_size ); + if ( error ) + goto Bail; + + FT_TRACE4(( " string_size = %ld\n", string_size )); + + if ( FT_NEW_ARRAY( strings, string_size ) ) + goto Bail; + + error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size ); + if ( error ) + goto Bail; + + if ( FT_NEW_ARRAY( properties, nprops ) ) + goto Bail; + + for ( i = 0; i < nprops; i++ ) + { + /* XXX: make atom */ + if ( FT_NEW_ARRAY( properties[i].name, + ft_strlen( strings + props[i].name ) + 1 ) ) + goto Bail; + ft_strcpy( properties[i].name, strings + props[i].name ); + + FT_TRACE4(( " %s:", properties[i].name )); + + properties[i].isString = props[i].isString; + + if ( props[i].isString ) + { + if ( FT_NEW_ARRAY( properties[i].value.atom, + ft_strlen( strings + props[i].value ) + 1 ) ) + goto Bail; + ft_strcpy( properties[i].value.atom, strings + props[i].value ); + + FT_TRACE4(( " `%s'\n", properties[i].value.atom )); + } + else + { + properties[i].value.integer = props[i].value; + + FT_TRACE4(( " %d\n", properties[i].value.integer )); + } + } + + face->properties = properties; + face->nprops = nprops; + + FT_FREE( props ); + FT_FREE( strings ); + + return PCF_Err_Ok; + + Bail: + FT_FREE( props ); + FT_FREE( strings ); + + return error; + } + + + static FT_Error + pcf_get_metrics( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = PCF_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_ULong format = 0; + FT_ULong size = 0; + PCF_Metric metrics = 0; + int i; + int nmetrics = -1; + + + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + PCF_METRICS, + &format, + &size ); + if ( error ) + return error; + + error = FT_READ_ULONG_LE( format ); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && + !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ) + return PCF_Err_Invalid_File_Format; + + if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)FT_READ_ULONG( nmetrics ); + else + (void)FT_READ_ULONG_LE( nmetrics ); + } + else + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)FT_READ_USHORT( nmetrics ); + else + (void)FT_READ_USHORT_LE( nmetrics ); + } + if ( error || nmetrics == -1 ) + return PCF_Err_Invalid_File_Format; + + face->nmetrics = nmetrics; + + if ( FT_NEW_ARRAY( face->metrics, nmetrics ) ) + return PCF_Err_Out_Of_Memory; + + FT_TRACE4(( "pcf_get_metrics:\n" )); + + metrics = face->metrics; + for ( i = 0; i < nmetrics; i++ ) + { + pcf_get_metric( stream, format, metrics + i ); + + metrics[i].bits = 0; + + FT_TRACE4(( " idx %d: width=%d, " + "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n", + i, + ( metrics + i )->characterWidth, + ( metrics + i )->leftSideBearing, + ( metrics + i )->rightSideBearing, + ( metrics + i )->ascent, + ( metrics + i )->descent, + ( metrics + i )->attributes )); + + if ( error ) + break; + } + + if ( error ) + FT_FREE( face->metrics ); + return error; + } + + + static FT_Error + pcf_get_bitmaps( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = PCF_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_Long* offsets; + FT_Long bitmapSizes[GLYPHPADOPTIONS]; + FT_ULong format, size; + int nbitmaps, i, sizebitmaps = 0; + char* bitmaps; + + + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + PCF_BITMAPS, + &format, + &size ); + if ( error ) + return error; + + error = FT_Stream_EnterFrame( stream, 8 ); + if ( error ) + return error; + + format = FT_GET_ULONG_LE(); + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + nbitmaps = FT_GET_ULONG(); + else + nbitmaps = FT_GET_ULONG_LE(); + + FT_Stream_ExitFrame( stream ); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + return PCF_Err_Invalid_File_Format; + + if ( nbitmaps != face->nmetrics ) + return PCF_Err_Invalid_File_Format; + + if ( FT_NEW_ARRAY( offsets, nbitmaps ) ) + return error; + + FT_TRACE4(( "pcf_get_bitmaps:\n" )); + + for ( i = 0; i < nbitmaps; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)FT_READ_LONG( offsets[i] ); + else + (void)FT_READ_LONG_LE( offsets[i] ); + + FT_TRACE4(( " bitmap %d: offset %ld (0x%lX)\n", + i, offsets[i], offsets[i] )); + } + if ( error ) + goto Bail; + + for ( i = 0; i < GLYPHPADOPTIONS; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + (void)FT_READ_LONG( bitmapSizes[i] ); + else + (void)FT_READ_LONG_LE( bitmapSizes[i] ); + if ( error ) + goto Bail; + + sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )]; + + FT_TRACE4(( " padding %d implies a size of %ld\n", i, bitmapSizes[i] )); + } + + FT_TRACE4(( " %d bitmaps, padding index %ld\n", + nbitmaps, + PCF_GLYPH_PAD_INDEX( format ) )); + FT_TRACE4(( " bitmap size = %d\n", sizebitmaps )); + + FT_UNUSED( sizebitmaps ); /* only used for debugging */ + + for ( i = 0; i < nbitmaps; i++ ) + face->metrics[i].bits = stream->pos + offsets[i]; + + face->bitmapsFormat = format; + + FT_FREE ( offsets ); + return error; + + Bail: + FT_FREE ( offsets ); + FT_FREE ( bitmaps ); + return error; + } + + + static FT_Error + pcf_get_encodings( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = PCF_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_ULong format, size; + int firstCol, lastCol; + int firstRow, lastRow; + int nencoding, encodingOffset; + int i, j; + PCF_Encoding tmpEncoding, encoding = 0; + + + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + PCF_BDF_ENCODINGS, + &format, + &size ); + if ( error ) + return error; + + error = FT_Stream_EnterFrame( stream, 14 ); + if ( error ) + return error; + + format = FT_GET_ULONG_LE(); + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + { + firstCol = FT_GET_SHORT(); + lastCol = FT_GET_SHORT(); + firstRow = FT_GET_SHORT(); + lastRow = FT_GET_SHORT(); + face->defaultChar = FT_GET_SHORT(); + } + else + { + firstCol = FT_GET_SHORT_LE(); + lastCol = FT_GET_SHORT_LE(); + firstRow = FT_GET_SHORT_LE(); + lastRow = FT_GET_SHORT_LE(); + face->defaultChar = FT_GET_SHORT_LE(); + } + + FT_Stream_ExitFrame( stream ); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) ) + return PCF_Err_Invalid_File_Format; + + FT_TRACE4(( "pdf_get_encodings:\n" )); + + FT_TRACE4(( " firstCol %d, lastCol %d, firstRow %d, lastRow %d\n", + firstCol, lastCol, firstRow, lastRow )); + + nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 ); + + if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) ) + return PCF_Err_Out_Of_Memory; + + error = FT_Stream_EnterFrame( stream, 2 * nencoding ); + if ( error ) + goto Bail; + + for ( i = 0, j = 0 ; i < nencoding; i++ ) + { + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + encodingOffset = FT_GET_SHORT(); + else + encodingOffset = FT_GET_SHORT_LE(); + + if ( encodingOffset != -1 ) + { + tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) + + firstRow ) * 256 ) + + ( ( i % ( lastCol - firstCol + 1 ) ) + + firstCol ); + + tmpEncoding[j].glyph = (FT_Short)encodingOffset; + + FT_TRACE4(( " code %d (0x%04X): idx %d\n", + tmpEncoding[j].enc, tmpEncoding[j].enc, + tmpEncoding[j].glyph )); + + j++; + } + } + FT_Stream_ExitFrame( stream ); + + if ( FT_NEW_ARRAY( encoding, j ) ) + goto Bail; + + for ( i = 0; i < j; i++ ) + { + encoding[i].enc = tmpEncoding[i].enc; + encoding[i].glyph = tmpEncoding[i].glyph; + } + + face->nencodings = j; + face->encodings = encoding; + FT_FREE( tmpEncoding ); + + return error; + + Bail: + FT_FREE( encoding ); + FT_FREE( tmpEncoding ); + return error; + } + + + static + const FT_Frame_Field pcf_accel_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_AccelRec + + FT_FRAME_START( 20 ), + FT_FRAME_BYTE ( noOverlap ), + FT_FRAME_BYTE ( constantMetrics ), + FT_FRAME_BYTE ( terminalFont ), + FT_FRAME_BYTE ( constantWidth ), + FT_FRAME_BYTE ( inkInside ), + FT_FRAME_BYTE ( inkMetrics ), + FT_FRAME_BYTE ( drawDirection ), + FT_FRAME_SKIP_BYTES( 1 ), + FT_FRAME_LONG_LE ( fontAscent ), + FT_FRAME_LONG_LE ( fontDescent ), + FT_FRAME_LONG_LE ( maxOverlap ), + FT_FRAME_END + }; + + + static + const FT_Frame_Field pcf_accel_msb_header[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PCF_AccelRec + + FT_FRAME_START( 20 ), + FT_FRAME_BYTE ( noOverlap ), + FT_FRAME_BYTE ( constantMetrics ), + FT_FRAME_BYTE ( terminalFont ), + FT_FRAME_BYTE ( constantWidth ), + FT_FRAME_BYTE ( inkInside ), + FT_FRAME_BYTE ( inkMetrics ), + FT_FRAME_BYTE ( drawDirection ), + FT_FRAME_SKIP_BYTES( 1 ), + FT_FRAME_LONG ( fontAscent ), + FT_FRAME_LONG ( fontDescent ), + FT_FRAME_LONG ( maxOverlap ), + FT_FRAME_END + }; + + + static FT_Error + pcf_get_accel( FT_Stream stream, + PCF_Face face, + FT_ULong type ) + { + FT_ULong format, size; + FT_Error error = PCF_Err_Ok; + PCF_Accel accel = &face->accel; + + + error = pcf_seek_to_table_type( stream, + face->toc.tables, + face->toc.count, + type, + &format, + &size ); + if ( error ) + goto Bail; + + error = FT_READ_ULONG_LE( format ); + + if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) && + !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) + goto Bail; + + if ( PCF_BYTE_ORDER( format ) == MSBFirst ) + { + if ( FT_STREAM_READ_FIELDS( pcf_accel_msb_header, accel ) ) + goto Bail; + } + else + { + if ( FT_STREAM_READ_FIELDS( pcf_accel_header, accel ) ) + goto Bail; + } + + error = pcf_get_metric( stream, + format & ( ~PCF_FORMAT_MASK ), + &(accel->minbounds) ); + if ( error ) + goto Bail; + + error = pcf_get_metric( stream, + format & ( ~PCF_FORMAT_MASK ), + &(accel->maxbounds) ); + if ( error ) + goto Bail; + + if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ) + { + error = pcf_get_metric( stream, + format & ( ~PCF_FORMAT_MASK ), + &(accel->ink_minbounds) ); + if ( error ) + goto Bail; + + error = pcf_get_metric( stream, + format & ( ~PCF_FORMAT_MASK ), + &(accel->ink_maxbounds) ); + if ( error ) + goto Bail; + } + else + { + accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */ + accel->ink_maxbounds = accel->maxbounds; + } + return error; + + Bail: + return error; + } + + + static FT_Error + pcf_interpret_style( PCF_Face pcf ) + { + FT_Error error = PCF_Err_Ok; + FT_Face face = FT_FACE( pcf ); + FT_Memory memory = face->memory; + + PCF_Property prop; + + char *istr = NULL, *bstr = NULL; + char *sstr = NULL, *astr = NULL; + + int parts = 0, len = 0; + + + face->style_flags = 0; + + prop = pcf_find_property( pcf, "SLANT" ); + if ( prop && prop->isString && + ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' || + *(prop->value.atom) == 'I' || *(prop->value.atom) == 'i' ) ) + { + face->style_flags |= FT_STYLE_FLAG_ITALIC; + istr = ( *(prop->value.atom) == 'O' || *(prop->value.atom) == 'o' ) + ? (char *)"Oblique" + : (char *)"Italic"; + len += ft_strlen( istr ); + parts++; + } + + prop = pcf_find_property( pcf, "WEIGHT_NAME" ); + if ( prop && prop->isString && + ( *(prop->value.atom) == 'B' || *(prop->value.atom) == 'b' ) ) + { + face->style_flags |= FT_STYLE_FLAG_BOLD; + bstr = (char *)"Bold"; + len += ft_strlen( bstr ); + parts++; + } + + prop = pcf_find_property( pcf, "SETWIDTH_NAME" ); + if ( prop && prop->isString && + *(prop->value.atom) && + !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) + { + sstr = (char *)(prop->value.atom); + len += ft_strlen( sstr ); + parts++; + } + + prop = pcf_find_property( pcf, "ADD_STYLE_NAME" ); + if ( prop && prop->isString && + *(prop->value.atom) && + !( *(prop->value.atom) == 'N' || *(prop->value.atom) == 'n' ) ) + { + astr = (char *)(prop->value.atom); + len += ft_strlen( astr ); + parts++; + } + + if ( !parts || !len ) + face->style_name = (char *)"Regular"; + else + { + char *style, *s; + unsigned int i; + + + if ( FT_ALLOC( style, len + parts ) ) + return error; + + s = style; + + if ( astr ) + { + ft_strcpy( s, astr ); + for ( i = 0; i < ft_strlen( astr ); i++, s++ ) + if ( *s == ' ' ) + *s = '-'; /* replace spaces with dashes */ + *(s++) = ' '; + } + if ( bstr ) + { + ft_strcpy( s, bstr ); + s += ft_strlen( bstr ); + *(s++) = ' '; + } + if ( istr ) + { + ft_strcpy( s, istr ); + s += ft_strlen( istr ); + *(s++) = ' '; + } + if ( sstr ) + { + ft_strcpy( s, sstr ); + for ( i = 0; i < ft_strlen( sstr ); i++, s++ ) + if ( *s == ' ' ) + *s = '-'; /* replace spaces with dashes */ + *(s++) = ' '; + } + *(--s) = '\0'; /* overwrite last ' ', terminate the string */ + + face->style_name = style; /* allocated string */ + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + pcf_load_font( FT_Stream stream, + PCF_Face face ) + { + FT_Error error = PCF_Err_Ok; + FT_Memory memory = FT_FACE(face)->memory; + FT_Bool hasBDFAccelerators; + + + error = pcf_read_TOC( stream, face ); + if ( error ) + goto Exit; + + error = pcf_get_properties( stream, face ); + if ( error ) + goto Exit; + + /* Use the old accelerators if no BDF accelerators are in the file. */ + hasBDFAccelerators = pcf_has_table_type( face->toc.tables, + face->toc.count, + PCF_BDF_ACCELERATORS ); + if ( !hasBDFAccelerators ) + { + error = pcf_get_accel( stream, face, PCF_ACCELERATORS ); + if ( error ) + goto Exit; + } + + /* metrics */ + error = pcf_get_metrics( stream, face ); + if ( error ) + goto Exit; + + /* bitmaps */ + error = pcf_get_bitmaps( stream, face ); + if ( error ) + goto Exit; + + /* encodings */ + error = pcf_get_encodings( stream, face ); + if ( error ) + goto Exit; + + /* BDF style accelerators (i.e. bounds based on encoded glyphs) */ + if ( hasBDFAccelerators ) + { + error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS ); + if ( error ) + goto Exit; + } + + /* XXX: TO DO: inkmetrics and glyph_names are missing */ + + /* now construct the face object */ + { + FT_Face root = FT_FACE( face ); + PCF_Property prop; + + + root->num_faces = 1; + root->face_index = 0; + root->face_flags = FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL | + FT_FACE_FLAG_FAST_GLYPHS; + + if ( face->accel.constantWidth ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + if ( ( error = pcf_interpret_style( face ) ) != 0 ) + goto Exit; + + prop = pcf_find_property( face, "FAMILY_NAME" ); + if ( prop && prop->isString ) + { + int l = ft_strlen( prop->value.atom ) + 1; + + + if ( FT_NEW_ARRAY( root->family_name, l ) ) + goto Exit; + ft_strcpy( root->family_name, prop->value.atom ); + } + else + root->family_name = NULL; + + /* Note: We shift all glyph indices by +1 since we must + * respect the convention that glyph 0 always corresponds + * to the "missing glyph". + * + * This implies bumping the number of "available" glyphs by 1. + */ + root->num_glyphs = face->nmetrics + 1; + + root->num_fixed_sizes = 1; + if ( FT_NEW_ARRAY( root->available_sizes, 1 ) ) + goto Exit; + + { + FT_Bitmap_Size* bsize = root->available_sizes; + FT_Short resolution_x = 0, resolution_y = 0; + + + FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) ); + + bsize->height = face->accel.fontAscent + face->accel.fontDescent; + + prop = pcf_find_property( face, "AVERAGE_WIDTH" ); + if ( prop ) + bsize->width = (FT_Short)( ( prop->value.integer + 5 ) / 10 ); + else + bsize->width = bsize->height * 2/3; + + prop = pcf_find_property( face, "POINT_SIZE" ); + if ( prop ) + /* convert from 722.7 decipoints to 72 points per inch */ + bsize->size = + (FT_Pos)( ( prop->value.integer * 64 * 7200 + 36135L ) / 72270L ); + + prop = pcf_find_property( face, "PIXEL_SIZE" ); + if ( prop ) + bsize->y_ppem = (FT_Short)prop->value.integer << 6; + + prop = pcf_find_property( face, "RESOLUTION_X" ); + if ( prop ) + resolution_x = (FT_Short)prop->value.integer; + + prop = pcf_find_property( face, "RESOLUTION_Y" ); + if ( prop ) + resolution_y = (FT_Short)prop->value.integer; + + if ( bsize->y_ppem == 0 ) + { + bsize->y_ppem = bsize->size; + if ( resolution_y ) + bsize->y_ppem = bsize->y_ppem * resolution_y / 72; + } + if ( resolution_x && resolution_y ) + bsize->x_ppem = bsize->y_ppem * resolution_x / resolution_y; + else + bsize->x_ppem = bsize->y_ppem; + } + + /* set up charset */ + { + PCF_Property charset_registry = 0, charset_encoding = 0; + + + charset_registry = pcf_find_property( face, "CHARSET_REGISTRY" ); + charset_encoding = pcf_find_property( face, "CHARSET_ENCODING" ); + + if ( charset_registry && charset_registry->isString && + charset_encoding && charset_encoding->isString ) + { + if ( FT_NEW_ARRAY( face->charset_encoding, + ft_strlen( charset_encoding->value.atom ) + 1 ) ) + goto Exit; + + if ( FT_NEW_ARRAY( face->charset_registry, + ft_strlen( charset_registry->value.atom ) + 1 ) ) + goto Exit; + + ft_strcpy( face->charset_registry, charset_registry->value.atom ); + ft_strcpy( face->charset_encoding, charset_encoding->value.atom ); + } + } + } + + Exit: + if ( error ) + { + /* this is done to respect the behaviour of the original */ + /* PCF font driver. */ + error = PCF_Err_Invalid_File_Format; + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcfread.h b/Utilities/vtkfreetype/src/pcf/pcfread.h new file mode 100644 index 0000000..c9524f1 --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcfread.h @@ -0,0 +1,45 @@ +/* pcfread.h + + FreeType font driver for pcf fonts + + Copyright 2003 by + Francesco Zappa Nardelli + +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. +*/ + + +#ifndef __PCFREAD_H__ +#define __PCFREAD_H__ + + +#include <ft2build.h> + +FT_BEGIN_HEADER + + FT_LOCAL( PCF_Property ) + pcf_find_property( PCF_Face face, + const FT_String* prop ); + +FT_END_HEADER + +#endif /* __PCFREAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcfutil.c b/Utilities/vtkfreetype/src/pcf/pcfutil.c new file mode 100644 index 0000000..8fcf23d --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcfutil.c @@ -0,0 +1,132 @@ +/* + +Copyright 1990, 1994, 1998 The Open Group + +All Rights Reserved. + +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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ +/* $XFree86: xc/lib/font/util/utilbitmap.c,v 1.3 1999/08/22 08:58:58 dawes Exp $ */ + +/* + * Author: Keith Packard, MIT X Consortium + */ + +/* Modified for use with FreeType */ + + +#include <ft2build.h> +#include "pcfutil.h" + + + /* Utility functions for reformatting font bitmaps */ + + static const unsigned char _reverse_byte[0x100] = + { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff + }; + + /* + * Invert bit order within each BYTE of an array. + */ + + FT_LOCAL_DEF( void ) + BitOrderInvert( unsigned char* buf, + int nbytes ) + { + const unsigned char* rev = _reverse_byte; + + + for ( ; --nbytes >= 0; buf++ ) + *buf = rev[*buf]; + } + + + /* + * Invert byte order within each 16-bits of an array. + */ + + FT_LOCAL_DEF( void ) + TwoByteSwap( unsigned char* buf, + int nbytes ) + { + unsigned char c; + + + for ( ; nbytes > 0; nbytes -= 2, buf += 2 ) + { + c = buf[0]; + buf[0] = buf[1]; + buf[1] = c; + } + } + + /* + * Invert byte order within each 32-bits of an array. + */ + + FT_LOCAL_DEF( void ) + FourByteSwap( unsigned char* buf, + int nbytes ) + { + unsigned char c; + + + for ( ; nbytes > 0; nbytes -= 4, buf += 4 ) + { + c = buf[0]; + buf[0] = buf[3]; + buf[3] = c; + + c = buf[1]; + buf[1] = buf[2]; + buf[2] = c; + } + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/pcfutil.h b/Utilities/vtkfreetype/src/pcf/pcfutil.h new file mode 100644 index 0000000..1557be3 --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/pcfutil.h @@ -0,0 +1,55 @@ +/* pcfutil.h + + FreeType font driver for pcf fonts + + Copyright 2000, 2001, 2004 by + Francesco Zappa Nardelli + +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. +*/ + + +#ifndef __PCFUTIL_H__ +#define __PCFUTIL_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H + + +FT_BEGIN_HEADER + + FT_LOCAL( void ) + BitOrderInvert( unsigned char* buf, + int nbytes ); + + FT_LOCAL( void ) + TwoByteSwap( unsigned char* buf, + int nbytes ); + + FT_LOCAL( void ) + FourByteSwap( unsigned char* buf, + int nbytes ); + +FT_END_HEADER + +#endif /* __PCFUTIL_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pcf/readme b/Utilities/vtkfreetype/src/pcf/readme new file mode 100644 index 0000000..75f49e1 --- /dev/null +++ b/Utilities/vtkfreetype/src/pcf/readme @@ -0,0 +1,114 @@ + FreeType font driver for PCF fonts + + Francesco Zappa Nardelli + <francesco.zappa.nardelli@ens.fr> + + +Introduction +************ + +PCF (Portable Compiled Format) is a binary bitmap font format, largely used +in X world. This code implements a PCF driver for the FreeType library. +Glyph images are loaded into memory only on demand, thus leading to a small +memory footprint. + +Informations on the PCF font format can only be worked out from +``pcfread.c'', and ``pcfwrite.c'', to be found, for instance, in the XFree86 +(www.xfree86.org) source tree (xc/lib/font/bitmap/). + +Many good bitmap fonts in bdf format come with XFree86: they can be +compiled into the pcf format using the ``bdftopcf'' utility. + + +Supported hardware +****************** + +The driver has been tested on linux/x86 and sunos5.5/sparc. In both +cases the compiler was gcc. When back in Paris, I will test it also +on linux/alpha. + + +Encodings +********* + +The variety of encodings that accompanies pcf fonts appears to encompass the +small set defined in freetype.h. On the other hand, each pcf font defines +two properties that specify encoding and registry. + +I decided to make these two properties directly accessible, leaving to the +client application the work of interpreting them. For instance: + + #include "pcftypes.h" /* include/freetype/internal/pcftypes.h */ + + FT_Face face; + PCF_Public_Face pcfface; + + FT_New_Face( library,..., &face ); + + pcfface = (PCF_Public_Face)face; + + if ((pcfface->charset_registry == "ISO10646") && + (pcfface->charset_encoding) == "1")) [..] + +Thus the driver always export ``ft_encoding_none'' as +face->charmap.encoding. FT_Get_Char_Index() behavior is unmodified, that +is, it converts the ULong value given as argument into the corresponding +glyph number. + + +Known problems +************** + +- dealing explicitly with encodings breaks the uniformity of freetype2 + api. + +- except for encodings properties, client applications have no + visibility of the PCF_Face object. This means that applications + cannot directly access font tables and are obliged to trust + FreeType. + +- currently, glyph names and ink_metrics are ignored. + +I plan to give full visibility of the PCF_Face object in the next +release of the driver, thus implementing also glyph names and +ink_metrics. + +- height is defined as (ascent - descent). Is this correct? + +- if unable to read size informations from the font, PCF_Init_Face + sets available_size->width and available_size->height to 12. + +- too many english grammar errors in the readme file :-( + + +License +******* + +Copyright (C) 2000 by Francesco Zappa Nardelli + +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. + + +Credits +******* + +Keith Packard wrote the pcf driver found in XFree86. His work is at +the same time the specification and the sample implementation of the +PCF format. Undoubtedly, this driver is inspired from his work. diff --git a/Utilities/vtkfreetype/src/pfr/pfr.c b/Utilities/vtkfreetype/src/pfr/pfr.c new file mode 100644 index 0000000..eb2c4ed --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfr.c @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* pfr.c */ +/* */ +/* FreeType PFR driver component. */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> + +#include "pfrload.c" +#include "pfrgload.c" +#include "pfrcmap.c" +#include "pfrobjs.c" +#include "pfrdrivr.c" +#include "pfrsbit.c" + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrcmap.c b/Utilities/vtkfreetype/src/pfr/pfrcmap.c new file mode 100644 index 0000000..de6c5a0 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrcmap.c @@ -0,0 +1,158 @@ +/***************************************************************************/ +/* */ +/* pfrcmap.c */ +/* */ +/* FreeType PFR cmap handling (body). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "pfrcmap.h" +#include "pfrobjs.h" +#include FT_INTERNAL_DEBUG_H + + + FT_CALLBACK_DEF( FT_Error ) + pfr_cmap_init( PFR_CMap cmap ) + { + PFR_Face face = (PFR_Face)FT_CMAP_FACE( cmap ); + + + cmap->num_chars = face->phy_font.num_chars; + cmap->chars = face->phy_font.chars; + + /* just for safety, check that the character entries are correctly */ + /* sorted in increasing character code order */ + { + FT_UInt n; + + + for ( n = 1; n < cmap->num_chars; n++ ) + { + if ( cmap->chars[n - 1].char_code >= cmap->chars[n].char_code ) + FT_ASSERT( 0 ); + } + } + + return 0; + } + + + FT_CALLBACK_DEF( void ) + pfr_cmap_done( PFR_CMap cmap ) + { + cmap->chars = NULL; + cmap->num_chars = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + pfr_cmap_char_index( PFR_CMap cmap, + FT_UInt32 char_code ) + { + FT_UInt min = 0; + FT_UInt max = cmap->num_chars; + FT_UInt mid; + PFR_Char gchar; + + + while ( min < max ) + { + mid = min + ( max - min ) / 2; + gchar = cmap->chars + mid; + + if ( gchar->char_code == char_code ) + return mid + 1; + + if ( gchar->char_code < char_code ) + min = mid + 1; + else + max = mid; + } + return 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + pfr_cmap_char_next( PFR_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code + 1; + + + Restart: + { + FT_UInt min = 0; + FT_UInt max = cmap->num_chars; + FT_UInt mid; + PFR_Char gchar; + + + while ( min < max ) + { + mid = min + ( ( max - min ) >> 1 ); + gchar = cmap->chars + mid; + + if ( gchar->char_code == char_code ) + { + result = mid; + if ( result != 0 ) + { + result++; + goto Exit; + } + + char_code++; + goto Restart; + } + + if ( gchar->char_code < char_code ) + min = mid+1; + else + max = mid; + } + + /* we didn't find it, but we have a pair just above it */ + char_code = 0; + + if ( min < cmap->num_chars ) + { + gchar = cmap->chars + min; + result = min; + if ( result != 0 ) + { + result++; + char_code = gchar->char_code; + } + } + } + + Exit: + *pchar_code = char_code; + return result; + } + + + FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec + pfr_cmap_class_rec = + { + sizeof ( PFR_CMapRec ), + + (FT_CMap_InitFunc) pfr_cmap_init, + (FT_CMap_DoneFunc) pfr_cmap_done, + (FT_CMap_CharIndexFunc)pfr_cmap_char_index, + (FT_CMap_CharNextFunc) pfr_cmap_char_next + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrcmap.h b/Utilities/vtkfreetype/src/pfr/pfrcmap.h new file mode 100644 index 0000000..d77813e --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrcmap.h @@ -0,0 +1,46 @@ +/***************************************************************************/ +/* */ +/* pfrcmap.h */ +/* */ +/* FreeType PFR cmap handling (specification). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PFRCMAP_H__ +#define __PFRCMAP_H__ + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include "pfrtypes.h" + + +FT_BEGIN_HEADER + + typedef struct PFR_CMapRec_ + { + FT_CMapRec cmap; + FT_UInt num_chars; + PFR_Char chars; + + } PFR_CMapRec, *PFR_CMap; + + + FT_CALLBACK_TABLE const FT_CMap_ClassRec pfr_cmap_class_rec; + +FT_END_HEADER + + +#endif /* __PFRCMAP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrdrivr.c b/Utilities/vtkfreetype/src/pfr/pfrdrivr.c new file mode 100644 index 0000000..55752a5 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrdrivr.c @@ -0,0 +1,203 @@ +/***************************************************************************/ +/* */ +/* pfrdrivr.c */ +/* */ +/* FreeType PFR driver interface (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_SERVICE_PFR_H +#include FT_SERVICE_XFREE86_NAME_H +#include "pfrdrivr.h" +#include "pfrobjs.h" + +#include "pfrerror.h" + + + FT_CALLBACK_DEF( FT_Error ) + pfr_get_kerning( FT_Face pfrface, /* PFR_Face */ + FT_UInt left, + FT_UInt right, + FT_Vector *avector ) + { + PFR_Face face = (PFR_Face)pfrface; + PFR_PhyFont phys = &face->phy_font; + + + pfr_face_get_kerning( pfrface, left, right, avector ); + + /* convert from metrics to outline units when necessary */ + if ( phys->outline_resolution != phys->metrics_resolution ) + { + if ( avector->x != 0 ) + avector->x = FT_MulDiv( avector->x, phys->outline_resolution, + phys->metrics_resolution ); + + if ( avector->y != 0 ) + avector->y = FT_MulDiv( avector->x, phys->outline_resolution, + phys->metrics_resolution ); + } + + return PFR_Err_Ok; + } + + + /* + * PFR METRICS SERVICE + * + */ + + FT_CALLBACK_DEF( FT_Error ) + pfr_get_advance( FT_Face pfrface, /* PFR_Face */ + FT_UInt gindex, + FT_Pos *anadvance ) + { + PFR_Face face = (PFR_Face)pfrface; + FT_Error error = PFR_Err_Bad_Argument; + + + *anadvance = 0; + if ( face ) + { + PFR_PhyFont phys = &face->phy_font; + + + if ( gindex < phys->num_chars ) + { + *anadvance = phys->chars[gindex].advance; + error = 0; + } + } + + return error; + } + + + FT_CALLBACK_DEF( FT_Error ) + pfr_get_metrics( FT_Face pfrface, /* PFR_Face */ + FT_UInt *anoutline_resolution, + FT_UInt *ametrics_resolution, + FT_Fixed *ametrics_x_scale, + FT_Fixed *ametrics_y_scale ) + { + PFR_Face face = (PFR_Face)pfrface; + PFR_PhyFont phys = &face->phy_font; + FT_Fixed x_scale, y_scale; + FT_Size size = face->root.size; + + + if ( anoutline_resolution ) + *anoutline_resolution = phys->outline_resolution; + + if ( ametrics_resolution ) + *ametrics_resolution = phys->metrics_resolution; + + x_scale = 0x10000L; + y_scale = 0x10000L; + + if ( size ) + { + x_scale = FT_DivFix( size->metrics.x_ppem << 6, + phys->metrics_resolution ); + + y_scale = FT_DivFix( size->metrics.y_ppem << 6, + phys->metrics_resolution ); + } + + if ( ametrics_x_scale ) + *ametrics_x_scale = x_scale; + + if ( ametrics_y_scale ) + *ametrics_y_scale = y_scale; + + return PFR_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const FT_Service_PfrMetricsRec pfr_metrics_service_rec = + { + pfr_get_metrics, + pfr_face_get_kerning, + pfr_get_advance + }; + + + /* + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec pfr_services[] = + { + { FT_SERVICE_ID_PFR_METRICS, &pfr_metrics_service_rec }, + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_PFR }, + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + pfr_get_service( FT_Module module, + const FT_String* service_id ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( pfr_services, service_id ); + } + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec pfr_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_SCALABLE, + + sizeof( FT_DriverRec ), + + "pfr", + 0x10000L, + 0x20000L, + + NULL, + + 0, + 0, + pfr_get_service + }, + + sizeof( PFR_FaceRec ), + sizeof( PFR_SizeRec ), + sizeof( PFR_SlotRec ), + + pfr_face_init, + pfr_face_done, + 0, /* FT_Size_InitFunc */ + 0, /* FT_Size_DoneFunc */ + pfr_slot_init, + pfr_slot_done, + + 0, /* FT_Size_ResetPointsFunc */ + 0, /* FT_Size_ResetPixelsFunc */ + pfr_slot_load, + + pfr_get_kerning, + 0, /* FT_Face_AttachFunc */ + 0 /* FT_Face_GetAdvancesFunc */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrdrivr.h b/Utilities/vtkfreetype/src/pfr/pfrdrivr.h new file mode 100644 index 0000000..36f1205 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrdrivr.h @@ -0,0 +1,39 @@ +/***************************************************************************/ +/* */ +/* pfrdrivr.h */ +/* */ +/* High-level Type PFR driver interface (specification). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PFRDRIVR_H__ +#define __PFRDRIVR_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) pfr_driver_class; + + +FT_END_HEADER + + +#endif /* __PFRDRIVR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrerror.h b/Utilities/vtkfreetype/src/pfr/pfrerror.h new file mode 100644 index 0000000..2e1c401 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrerror.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* pfrerror.h */ +/* */ +/* PFR error codes (specification only). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the PFR error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __PFRERROR_H__ +#define __PFRERROR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX PFR_Err_ +#define FT_ERR_BASE FT_Mod_Err_PFR + +#include FT_ERRORS_H + +#endif /* __PFRERROR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrgload.c b/Utilities/vtkfreetype/src/pfr/pfrgload.c new file mode 100644 index 0000000..87ba684 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrgload.c @@ -0,0 +1,801 @@ +/***************************************************************************/ +/* */ +/* pfrgload.c */ +/* */ +/* FreeType PFR glyph loader (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "pfrgload.h" +#include "pfrsbit.h" +#include "pfrload.h" /* for macro definitions */ +#include FT_INTERNAL_DEBUG_H + +#include "pfrerror.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pfr + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PFR GLYPH BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( void ) + pfr_glyph_init( PFR_Glyph glyph, + FT_GlyphLoader loader ) + { + FT_ZERO( glyph ); + + glyph->loader = loader; + glyph->path_begun = 0; + + FT_GlyphLoader_Rewind( loader ); + } + + + FT_LOCAL_DEF( void ) + pfr_glyph_done( PFR_Glyph glyph ) + { + FT_Memory memory = glyph->loader->memory; + + + FT_FREE( glyph->x_control ); + glyph->y_control = NULL; + + glyph->max_xy_control = 0; + glyph->num_x_control = 0; + glyph->num_y_control = 0; + + FT_FREE( glyph->subs ); + + glyph->max_subs = 0; + glyph->num_subs = 0; + + glyph->loader = NULL; + glyph->path_begun = 0; + } + + + /* close current contour, if any */ + static void + pfr_glyph_close_contour( PFR_Glyph glyph ) + { + FT_GlyphLoader loader = glyph->loader; + FT_Outline* outline = &loader->current.outline; + FT_Int last, first; + + + if ( !glyph->path_begun ) + return; + + /* compute first and last point indices in current glyph outline */ + last = outline->n_points - 1; + first = 0; + if ( outline->n_contours > 0 ) + first = outline->contours[outline->n_contours - 1]; + + /* if the last point falls on the same location than the first one */ + /* we need to delete it */ + if ( last > first ) + { + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + last; + + + if ( p1->x == p2->x && p1->y == p2->y ) + { + outline->n_points--; + last--; + } + } + + /* don't add empty contours */ + if ( last >= first ) + outline->contours[outline->n_contours++] = (short)last; + + glyph->path_begun = 0; + } + + + /* reset glyph to start the loading of a new glyph */ + static void + pfr_glyph_start( PFR_Glyph glyph ) + { + glyph->path_begun = 0; + } + + + static FT_Error + pfr_glyph_line_to( PFR_Glyph glyph, + FT_Vector* to ) + { + FT_GlyphLoader loader = glyph->loader; + FT_Outline* outline = &loader->current.outline; + FT_Error error; + + + /* check that we have begun a new path */ + FT_ASSERT( glyph->path_begun != 0 ); + + error = FT_GlyphLoader_CheckPoints( loader, 1, 0 ); + if ( !error ) + { + FT_UInt n = outline->n_points; + + + outline->points[n] = *to; + outline->tags [n] = FT_CURVE_TAG_ON; + + outline->n_points++; + } + + return error; + } + + + static FT_Error + pfr_glyph_curve_to( PFR_Glyph glyph, + FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to ) + { + FT_GlyphLoader loader = glyph->loader; + FT_Outline* outline = &loader->current.outline; + FT_Error error; + + + /* check that we have begun a new path */ + FT_ASSERT( glyph->path_begun != 0 ); + + error = FT_GlyphLoader_CheckPoints( loader, 3, 0 ); + if ( !error ) + { + FT_Vector* vec = outline->points + outline->n_points; + FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points; + + + vec[0] = *control1; + vec[1] = *control2; + vec[2] = *to; + tag[0] = FT_CURVE_TAG_CUBIC; + tag[1] = FT_CURVE_TAG_CUBIC; + tag[2] = FT_CURVE_TAG_ON; + + outline->n_points = (FT_Short)( outline->n_points + 3 ); + } + + return error; + } + + + static FT_Error + pfr_glyph_move_to( PFR_Glyph glyph, + FT_Vector* to ) + { + FT_GlyphLoader loader = glyph->loader; + FT_Error error; + + + /* close current contour if any */ + pfr_glyph_close_contour( glyph ); + + /* indicate that a new contour has started */ + glyph->path_begun = 1; + + /* check that there is space for a new contour and a new point */ + error = FT_GlyphLoader_CheckPoints( loader, 1, 1 ); + if ( !error ) + /* add new start point */ + error = pfr_glyph_line_to( glyph, to ); + + return error; + } + + + static void + pfr_glyph_end( PFR_Glyph glyph ) + { + /* close current contour if any */ + pfr_glyph_close_contour( glyph ); + + /* merge the current glyph into the stack */ + FT_GlyphLoader_Add( glyph->loader ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PFR GLYPH LOADER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /* load a simple glyph */ + static FT_Error + pfr_glyph_load_simple( PFR_Glyph glyph, + FT_Byte* p, + FT_Byte* limit ) + { + FT_Error error = 0; + FT_Memory memory = glyph->loader->memory; + FT_UInt flags, x_count, y_count, i, count, mask; + FT_Int x; + + + PFR_CHECK( 1 ); + flags = PFR_NEXT_BYTE( p ); + + /* test for composite glyphs */ + FT_ASSERT( ( flags & PFR_GLYPH_IS_COMPOUND ) == 0 ); + + x_count = 0; + y_count = 0; + + if ( flags & PFR_GLYPH_1BYTE_XYCOUNT ) + { + PFR_CHECK( 1 ); + count = PFR_NEXT_BYTE( p ); + x_count = ( count & 15 ); + y_count = ( count >> 4 ); + } + else + { + if ( flags & PFR_GLYPH_XCOUNT ) + { + PFR_CHECK( 1 ); + x_count = PFR_NEXT_BYTE( p ); + } + + if ( flags & PFR_GLYPH_YCOUNT ) + { + PFR_CHECK( 1 ); + y_count = PFR_NEXT_BYTE( p ); + } + } + + count = x_count + y_count; + + /* re-allocate array when necessary */ + if ( count > glyph->max_xy_control ) + { + FT_UInt new_max = FT_PAD_CEIL( count, 8 ); + + + if ( FT_RENEW_ARRAY( glyph->x_control, + glyph->max_xy_control, + new_max ) ) + goto Exit; + + glyph->max_xy_control = new_max; + } + + glyph->y_control = glyph->x_control + x_count; + + mask = 0; + x = 0; + + for ( i = 0; i < count; i++ ) + { + if ( ( i & 7 ) == 0 ) + { + PFR_CHECK( 1 ); + mask = PFR_NEXT_BYTE( p ); + } + + if ( mask & 1 ) + { + PFR_CHECK( 2 ); + x = PFR_NEXT_SHORT( p ); + } + else + { + PFR_CHECK( 1 ); + x += PFR_NEXT_BYTE( p ); + } + + glyph->x_control[i] = x; + + mask >>= 1; + } + + /* XXX: for now we ignore the secondary stroke and edge definitions */ + /* since we don't want to support native PFR hinting */ + /* */ + if ( flags & PFR_GLYPH_EXTRA_ITEMS ) + { + error = pfr_extra_items_skip( &p, limit ); + if ( error ) + goto Exit; + } + + pfr_glyph_start( glyph ); + + /* now load a simple glyph */ + { + FT_Vector pos[4]; + FT_Vector* cur; + + + pos[0].x = pos[0].y = 0; + pos[3] = pos[0]; + + for (;;) + { + FT_Int format, args_format = 0, args_count, n; + + + /***************************************************************/ + /* read instruction */ + /* */ + PFR_CHECK( 1 ); + format = PFR_NEXT_BYTE( p ); + + switch ( format >> 4 ) + { + case 0: /* end glyph */ + FT_TRACE6(( "- end glyph" )); + args_count = 0; + break; + + case 1: /* general line operation */ + FT_TRACE6(( "- general line" )); + goto Line1; + + case 4: /* move to inside contour */ + FT_TRACE6(( "- move to inside" )); + goto Line1; + + case 5: /* move to outside contour */ + FT_TRACE6(( "- move to outside" )); + Line1: + args_format = format & 15; + args_count = 1; + break; + + case 2: /* horizontal line to */ + FT_TRACE6(( "- horizontal line to cx.%d", format & 15 )); + pos[0].y = pos[3].y; + pos[0].x = glyph->x_control[format & 15]; + pos[3] = pos[0]; + args_count = 0; + break; + + case 3: /* vertical line to */ + FT_TRACE6(( "- vertical line to cy.%d", format & 15 )); + pos[0].x = pos[3].x; + pos[0].y = glyph->y_control[format & 15]; + pos[3] = pos[0]; + args_count = 0; + break; + + case 6: /* horizontal to vertical curve */ + FT_TRACE6(( "- hv curve " )); + args_format = 0xB8E; + args_count = 3; + break; + + case 7: /* vertical to horizontal curve */ + FT_TRACE6(( "- vh curve" )); + args_format = 0xE2B; + args_count = 3; + break; + + default: /* general curve to */ + FT_TRACE6(( "- general curve" )); + args_count = 4; + args_format = format & 15; + } + + /***********************************************************/ + /* now read arguments */ + /* */ + cur = pos; + for ( n = 0; n < args_count; n++ ) + { + FT_Int idx, delta; + + + /* read the X argument */ + switch ( args_format & 3 ) + { + case 0: /* 8-bit index */ + PFR_CHECK( 1 ); + idx = PFR_NEXT_BYTE( p ); + cur->x = glyph->x_control[idx]; + FT_TRACE7(( " cx#%d", idx )); + break; + + case 1: /* 16-bit value */ + PFR_CHECK( 2 ); + cur->x = PFR_NEXT_SHORT( p ); + FT_TRACE7(( " x.%d", cur->x )); + break; + + case 2: /* 8-bit delta */ + PFR_CHECK( 1 ); + delta = PFR_NEXT_INT8( p ); + cur->x = pos[3].x + delta; + FT_TRACE7(( " dx.%d", delta )); + break; + + default: + FT_TRACE7(( " |" )); + cur->x = pos[3].x; + } + + /* read the Y argument */ + switch ( ( args_format >> 2 ) & 3 ) + { + case 0: /* 8-bit index */ + PFR_CHECK( 1 ); + idx = PFR_NEXT_BYTE( p ); + cur->y = glyph->y_control[idx]; + FT_TRACE7(( " cy#%d", idx )); + break; + + case 1: /* 16-bit absolute value */ + PFR_CHECK( 2 ); + cur->y = PFR_NEXT_SHORT( p ); + FT_TRACE7(( " y.%d", cur->y )); + break; + + case 2: /* 8-bit delta */ + PFR_CHECK( 1 ); + delta = PFR_NEXT_INT8( p ); + cur->y = pos[3].y + delta; + FT_TRACE7(( " dy.%d", delta )); + break; + + default: + FT_TRACE7(( " -" )); + cur->y = pos[3].y; + } + + /* read the additional format flag for the general curve */ + if ( n == 0 && args_count == 4 ) + { + PFR_CHECK( 1 ); + args_format = PFR_NEXT_BYTE( p ); + args_count--; + } + else + args_format >>= 4; + + /* save the previous point */ + pos[3] = cur[0]; + cur++; + } + + FT_TRACE7(( "\n" )); + + /***********************************************************/ + /* finally, execute instruction */ + /* */ + switch ( format >> 4 ) + { + case 0: /* end glyph => EXIT */ + pfr_glyph_end( glyph ); + goto Exit; + + case 1: /* line operations */ + case 2: + case 3: + error = pfr_glyph_line_to( glyph, pos ); + goto Test_Error; + + case 4: /* move to inside contour */ + case 5: /* move to outside contour */ + error = pfr_glyph_move_to( glyph, pos ); + goto Test_Error; + + default: /* curve operations */ + error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 ); + + Test_Error: /* test error condition */ + if ( error ) + goto Exit; + } + } /* for (;;) */ + } + + Exit: + return error; + + Too_Short: + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" )); + goto Exit; + } + + + /* load a composite/compound glyph */ + static FT_Error + pfr_glyph_load_compound( PFR_Glyph glyph, + FT_Byte* p, + FT_Byte* limit ) + { + FT_Error error = 0; + FT_GlyphLoader loader = glyph->loader; + FT_Memory memory = loader->memory; + PFR_SubGlyph subglyph; + FT_UInt flags, i, count, org_count; + FT_Int x_pos, y_pos; + + + PFR_CHECK( 1 ); + flags = PFR_NEXT_BYTE( p ); + + /* test for composite glyphs */ + FT_ASSERT( ( flags & PFR_GLYPH_IS_COMPOUND ) != 0 ); + + count = flags & 0x3F; + + /* ignore extra items when present */ + /* */ + if ( flags & PFR_GLYPH_EXTRA_ITEMS ) + { + error = pfr_extra_items_skip( &p, limit ); + if (error) goto Exit; + } + + /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because */ + /* the PFR format is dumb, using direct file offsets to point to the */ + /* sub-glyphs (instead of glyph indices). Sigh. */ + /* */ + /* For now, we load the list of sub-glyphs into a different array */ + /* but this will prevent us from using the auto-hinter at its best */ + /* quality. */ + /* */ + org_count = glyph->num_subs; + + if ( org_count + count > glyph->max_subs ) + { + FT_UInt new_max = ( org_count + count + 3 ) & -4; + + + if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) ) + goto Exit; + + glyph->max_subs = new_max; + } + + subglyph = glyph->subs + org_count; + + for ( i = 0; i < count; i++, subglyph++ ) + { + FT_UInt format; + + + x_pos = 0; + y_pos = 0; + + PFR_CHECK( 1 ); + format = PFR_NEXT_BYTE( p ); + + /* read scale when available */ + subglyph->x_scale = 0x10000L; + if ( format & PFR_SUBGLYPH_XSCALE ) + { + PFR_CHECK( 2 ); + subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4; + } + + subglyph->y_scale = 0x10000L; + if ( format & PFR_SUBGLYPH_YSCALE ) + { + PFR_CHECK( 2 ); + subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4; + } + + /* read offset */ + switch ( format & 3 ) + { + case 1: + PFR_CHECK( 2 ); + x_pos = PFR_NEXT_SHORT( p ); + break; + + case 2: + PFR_CHECK( 1 ); + x_pos += PFR_NEXT_INT8( p ); + break; + + default: + ; + } + + switch ( ( format >> 2 ) & 3 ) + { + case 1: + PFR_CHECK( 2 ); + y_pos = PFR_NEXT_SHORT( p ); + break; + + case 2: + PFR_CHECK( 1 ); + y_pos += PFR_NEXT_INT8( p ); + break; + + default: + ; + } + + subglyph->x_delta = x_pos; + subglyph->y_delta = y_pos; + + /* read glyph position and size now */ + if ( format & PFR_SUBGLYPH_2BYTE_SIZE ) + { + PFR_CHECK( 2 ); + subglyph->gps_size = PFR_NEXT_USHORT( p ); + } + else + { + PFR_CHECK( 1 ); + subglyph->gps_size = PFR_NEXT_BYTE( p ); + } + + if ( format & PFR_SUBGLYPH_3BYTE_OFFSET ) + { + PFR_CHECK( 3 ); + subglyph->gps_offset = PFR_NEXT_LONG( p ); + } + else + { + PFR_CHECK( 2 ); + subglyph->gps_offset = PFR_NEXT_USHORT( p ); + } + + glyph->num_subs++; + } + + Exit: + return error; + + Too_Short: + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" )); + goto Exit; + } + + + + + + static FT_Error + pfr_glyph_load_rec( PFR_Glyph glyph, + FT_Stream stream, + FT_ULong gps_offset, + FT_ULong offset, + FT_ULong size ) + { + FT_Error error; + FT_Byte* p; + FT_Byte* limit; + + + if ( FT_STREAM_SEEK( gps_offset + offset ) || + FT_FRAME_ENTER( size ) ) + goto Exit; + + p = (FT_Byte*)stream->cursor; + limit = p + size; + + if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND ) + { + FT_Int n, old_count, count; + FT_GlyphLoader loader = glyph->loader; + FT_Outline* base = &loader->base.outline; + + + old_count = glyph->num_subs; + + /* this is a compound glyph - load it */ + error = pfr_glyph_load_compound( glyph, p, limit ); + + FT_FRAME_EXIT(); + + if ( error ) + goto Exit; + + count = glyph->num_subs - old_count; + + /* now, load each individual glyph */ + for ( n = 0; n < count; n++ ) + { + FT_Int i, old_points, num_points; + PFR_SubGlyph subglyph; + + + subglyph = glyph->subs + old_count + n; + old_points = base->n_points; + + error = pfr_glyph_load_rec( glyph, stream, gps_offset, + subglyph->gps_offset, + subglyph->gps_size ); + if ( error ) + goto Exit; + + /* note that `glyph->subs' might have been re-allocated */ + subglyph = glyph->subs + old_count + n; + num_points = base->n_points - old_points; + + /* translate and eventually scale the new glyph points */ + if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L ) + { + FT_Vector* vec = base->points + old_points; + + + for ( i = 0; i < num_points; i++, vec++ ) + { + vec->x = FT_MulFix( vec->x, subglyph->x_scale ) + + subglyph->x_delta; + vec->y = FT_MulFix( vec->y, subglyph->y_scale ) + + subglyph->y_delta; + } + } + else + { + FT_Vector* vec = loader->base.outline.points + old_points; + + + for ( i = 0; i < num_points; i++, vec++ ) + { + vec->x += subglyph->x_delta; + vec->y += subglyph->y_delta; + } + } + + /* proceed to next sub-glyph */ + } + } + else + { + /* load a simple glyph */ + error = pfr_glyph_load_simple( glyph, p, limit ); + + FT_FRAME_EXIT(); + } + + Exit: + return error; + } + + + + + + FT_LOCAL_DEF( FT_Error ) + pfr_glyph_load( PFR_Glyph glyph, + FT_Stream stream, + FT_ULong gps_offset, + FT_ULong offset, + FT_ULong size ) + { + /* initialize glyph loader */ + FT_GlyphLoader_Rewind( glyph->loader ); + + /* load the glyph, recursively when needed */ + return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrgload.h b/Utilities/vtkfreetype/src/pfr/pfrgload.h new file mode 100644 index 0000000..7cc7a87 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrgload.h @@ -0,0 +1,49 @@ +/***************************************************************************/ +/* */ +/* pfrgload.h */ +/* */ +/* FreeType PFR glyph loader (specification). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PFRGLOAD_H__ +#define __PFRGLOAD_H__ + +#include "pfrtypes.h" + +FT_BEGIN_HEADER + + + FT_LOCAL( void ) + pfr_glyph_init( PFR_Glyph glyph, + FT_GlyphLoader loader ); + + FT_LOCAL( void ) + pfr_glyph_done( PFR_Glyph glyph ); + + + FT_LOCAL( FT_Error ) + pfr_glyph_load( PFR_Glyph glyph, + FT_Stream stream, + FT_ULong gps_offset, + FT_ULong offset, + FT_ULong size ); + + +FT_END_HEADER + + +#endif /* __PFRGLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrload.c b/Utilities/vtkfreetype/src/pfr/pfrload.c new file mode 100644 index 0000000..19ced45 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrload.c @@ -0,0 +1,1081 @@ +/***************************************************************************/ +/* */ +/* pfrload.c */ +/* */ +/* FreeType PFR loader (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "pfrload.h" +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H + +#include "pfrerror.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pfr + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** EXTRA ITEMS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + pfr_extra_items_skip( FT_Byte* *pp, + FT_Byte* limit ) + { + return pfr_extra_items_parse( pp, limit, NULL, NULL ); + } + + + FT_LOCAL_DEF( FT_Error ) + pfr_extra_items_parse( FT_Byte* *pp, + FT_Byte* limit, + PFR_ExtraItem item_list, + FT_Pointer item_data ) + { + FT_Error error = 0; + FT_Byte* p = *pp; + FT_UInt num_items, item_type, item_size; + + + PFR_CHECK( 1 ); + num_items = PFR_NEXT_BYTE( p ); + + for ( ; num_items > 0; num_items-- ) + { + PFR_CHECK( 2 ); + item_size = PFR_NEXT_BYTE( p ); + item_type = PFR_NEXT_BYTE( p ); + + PFR_CHECK( item_size ); + + if ( item_list ) + { + PFR_ExtraItem extra = item_list; + + + for ( extra = item_list; extra->parser != NULL; extra++ ) + { + if ( extra->type == item_type ) + { + error = extra->parser( p, p + item_size, item_data ); + if ( error ) goto Exit; + + break; + } + } + } + + p += item_size; + } + + Exit: + *pp = p; + return error; + + Too_Short: + FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" )); + error = PFR_Err_Invalid_Table; + goto Exit; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PFR HEADER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static const FT_Frame_Field pfr_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE PFR_HeaderRec + + FT_FRAME_START( 58 ), + FT_FRAME_ULONG ( signature ), + FT_FRAME_USHORT( version ), + FT_FRAME_USHORT( signature2 ), + FT_FRAME_USHORT( header_size ), + + FT_FRAME_USHORT( log_dir_size ), + FT_FRAME_USHORT( log_dir_offset ), + + FT_FRAME_USHORT( log_font_max_size ), + FT_FRAME_UOFF3 ( log_font_section_size ), + FT_FRAME_UOFF3 ( log_font_section_offset ), + + FT_FRAME_USHORT( phy_font_max_size ), + FT_FRAME_UOFF3 ( phy_font_section_size ), + FT_FRAME_UOFF3 ( phy_font_section_offset ), + + FT_FRAME_USHORT( gps_max_size ), + FT_FRAME_UOFF3 ( gps_section_size ), + FT_FRAME_UOFF3 ( gps_section_offset ), + + FT_FRAME_BYTE ( max_blue_values ), + FT_FRAME_BYTE ( max_x_orus ), + FT_FRAME_BYTE ( max_y_orus ), + + FT_FRAME_BYTE ( phy_font_max_size_high ), + FT_FRAME_BYTE ( color_flags ), + + FT_FRAME_UOFF3 ( bct_max_size ), + FT_FRAME_UOFF3 ( bct_set_max_size ), + FT_FRAME_UOFF3 ( phy_bct_set_max_size ), + + FT_FRAME_USHORT( num_phy_fonts ), + FT_FRAME_BYTE ( max_vert_stem_snap ), + FT_FRAME_BYTE ( max_horz_stem_snap ), + FT_FRAME_USHORT( max_chars ), + FT_FRAME_END + }; + + + FT_LOCAL_DEF( FT_Error ) + pfr_header_load( PFR_Header header, + FT_Stream stream ) + { + FT_Error error; + + + /* read header directly */ + if ( !FT_STREAM_SEEK( 0 ) && + !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) ) + { + /* make a few adjustments to the header */ + header->phy_font_max_size += + (FT_UInt32)header->phy_font_max_size_high << 16; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Bool ) + pfr_header_check( PFR_Header header ) + { + FT_Bool result = 1; + + + /* check signature and header size */ + if ( header->signature != 0x50465230L || /* "PFR0" */ + header->version > 4 || + header->header_size < 58 || + header->signature2 != 0x0d0a ) /* CR/LF */ + { + result = 0; + } + return result; + } + + + /***********************************************************************/ + /***********************************************************************/ + /***** *****/ + /***** PFR LOGICAL FONTS *****/ + /***** *****/ + /***********************************************************************/ + /***********************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + pfr_log_font_count( FT_Stream stream, + FT_UInt32 section_offset, + FT_UInt *acount ) + { + FT_Error error; + FT_UInt count; + FT_UInt result = 0; + + + if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) ) + goto Exit; + + result = count; + + Exit: + *acount = result; + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + pfr_log_font_load( PFR_LogFont log_font, + FT_Stream stream, + FT_UInt idx, + FT_UInt32 section_offset, + FT_Bool size_increment ) + { + FT_UInt num_log_fonts; + FT_UInt flags; + FT_UInt32 offset; + FT_UInt32 size; + FT_Error error; + + + if ( FT_STREAM_SEEK( section_offset ) || + FT_READ_USHORT( num_log_fonts ) ) + goto Exit; + + if ( idx >= num_log_fonts ) + return PFR_Err_Invalid_Argument; + + if ( FT_STREAM_SKIP( idx * 5 ) || + FT_READ_USHORT( size ) || + FT_READ_UOFF3 ( offset ) ) + goto Exit; + + /* save logical font size and offset */ + log_font->size = size; + log_font->offset = offset; + + /* now, check the rest of the table before loading it */ + { + FT_Byte* p; + FT_Byte* limit; + FT_UInt local; + + + if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) ) + goto Exit; + + p = stream->cursor; + limit = p + size; + + PFR_CHECK(13); + + log_font->matrix[0] = PFR_NEXT_LONG( p ); + log_font->matrix[1] = PFR_NEXT_LONG( p ); + log_font->matrix[2] = PFR_NEXT_LONG( p ); + log_font->matrix[3] = PFR_NEXT_LONG( p ); + + flags = PFR_NEXT_BYTE( p ); + + local = 0; + if ( flags & PFR_LOG_STROKE ) + { + local++; + if ( flags & PFR_LOG_2BYTE_STROKE ) + local++; + + if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER ) + local += 3; + } + if ( flags & PFR_LOG_BOLD ) + { + local++; + if ( flags & PFR_LOG_2BYTE_BOLD ) + local++; + } + + PFR_CHECK( local ); + + if ( flags & PFR_LOG_STROKE ) + { + log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE ) + ? PFR_NEXT_SHORT( p ) + : PFR_NEXT_BYTE( p ); + + if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER ) + log_font->miter_limit = PFR_NEXT_LONG( p ); + } + + if ( flags & PFR_LOG_BOLD ) + { + log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD ) + ? PFR_NEXT_SHORT( p ) + : PFR_NEXT_BYTE( p ); + } + + if ( flags & PFR_LOG_EXTRA_ITEMS ) + { + error = pfr_extra_items_skip( &p, limit ); + if (error) goto Fail; + } + + PFR_CHECK(5); + log_font->phys_size = PFR_NEXT_USHORT( p ); + log_font->phys_offset = PFR_NEXT_ULONG( p ); + if ( size_increment ) + { + PFR_CHECK( 1 ); + log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16; + } + } + + Fail: + FT_FRAME_EXIT(); + + Exit: + return error; + + Too_Short: + FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" )); + error = PFR_Err_Invalid_Table; + goto Fail; + } + + + /***********************************************************************/ + /***********************************************************************/ + /***** *****/ + /***** PFR PHYSICAL FONTS *****/ + /***** *****/ + /***********************************************************************/ + /***********************************************************************/ + + + /* load bitmap strikes lists */ + FT_CALLBACK_DEF( FT_Error ) + pfr_extra_item_load_bitmap_info( FT_Byte* p, + FT_Byte* limit, + PFR_PhyFont phy_font ) + { + FT_Memory memory = phy_font->memory; + PFR_Strike strike; + FT_UInt flags0; + FT_UInt n, count, size1; + FT_Error error = 0; + + + PFR_CHECK( 5 ); + + p += 3; /* skip bctSize */ + flags0 = PFR_NEXT_BYTE( p ); + count = PFR_NEXT_BYTE( p ); + + /* re-allocate when needed */ + if ( phy_font->num_strikes + count > phy_font->max_strikes ) + { + FT_UInt new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 ); + + + if ( FT_RENEW_ARRAY( phy_font->strikes, + phy_font->num_strikes, + new_max ) ) + goto Exit; + + phy_font->max_strikes = new_max; + } + + size1 = 1 + 1 + 1 + 2 + 2 + 1; + if ( flags0 & PFR_STRIKE_2BYTE_XPPM ) + size1++; + + if ( flags0 & PFR_STRIKE_2BYTE_YPPM ) + size1++; + + if ( flags0 & PFR_STRIKE_3BYTE_SIZE ) + size1++; + + if ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) + size1++; + + if ( flags0 & PFR_STRIKE_2BYTE_COUNT ) + size1++; + + strike = phy_font->strikes + phy_font->num_strikes; + + PFR_CHECK( count * size1 ); + + for ( n = 0; n < count; n++, strike++ ) + { + strike->x_ppm = ( flags0 & PFR_STRIKE_2BYTE_XPPM ) + ? PFR_NEXT_USHORT( p ) + : PFR_NEXT_BYTE( p ); + + strike->y_ppm = ( flags0 & PFR_STRIKE_2BYTE_YPPM ) + ? PFR_NEXT_USHORT( p ) + : PFR_NEXT_BYTE( p ); + + strike->flags = PFR_NEXT_BYTE( p ); + + strike->bct_size = ( flags0 & PFR_STRIKE_3BYTE_SIZE ) + ? PFR_NEXT_ULONG( p ) + : PFR_NEXT_USHORT( p ); + + strike->bct_offset = ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) + ? PFR_NEXT_ULONG( p ) + : PFR_NEXT_USHORT( p ); + + strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT ) + ? PFR_NEXT_USHORT( p ) + : PFR_NEXT_BYTE( p ); + } + + phy_font->num_strikes += count; + + Exit: + return error; + + Too_Short: + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_extra_item_load_bitmap_info: invalid bitmap info table\n" )); + goto Exit; + } + + + /* Load font ID. This is a so-called "unique" name that is rather + * long and descriptive (like "Tiresias ScreenFont v7.51"). + * + * Note that a PFR font's family name is contained in an *undocumented* + * string of the "auxiliary data" portion of a physical font record. This + * may also contain the "real" style name! + * + * If no family name is present, the font ID is used instead for the + * family. + */ + FT_CALLBACK_DEF( FT_Error ) + pfr_extra_item_load_font_id( FT_Byte* p, + FT_Byte* limit, + PFR_PhyFont phy_font ) + { + FT_Error error = 0; + FT_Memory memory = phy_font->memory; + FT_PtrDist len = limit - p; + + + if ( phy_font->font_id != NULL ) + goto Exit; + + if ( FT_ALLOC( phy_font->font_id, len + 1 ) ) + goto Exit; + + /* copy font ID name, and terminate it for safety */ + FT_MEM_COPY( phy_font->font_id, p, len ); + phy_font->font_id[len] = 0; + + Exit: + return error; + } + + + /* load stem snap tables */ + FT_CALLBACK_DEF( FT_Error ) + pfr_extra_item_load_stem_snaps( FT_Byte* p, + FT_Byte* limit, + PFR_PhyFont phy_font ) + { + FT_UInt count, num_vert, num_horz; + FT_Int* snaps; + FT_Error error = 0; + FT_Memory memory = phy_font->memory; + + + if ( phy_font->vertical.stem_snaps != NULL ) + goto Exit; + + PFR_CHECK( 1 ); + count = PFR_NEXT_BYTE( p ); + + num_vert = count & 15; + num_horz = count >> 4; + count = num_vert + num_horz; + + PFR_CHECK( count * 2 ); + + if ( FT_NEW_ARRAY( snaps, count ) ) + goto Exit; + + phy_font->vertical.stem_snaps = snaps; + phy_font->horizontal.stem_snaps = snaps + num_vert; + + for ( ; count > 0; count--, snaps++ ) + *snaps = FT_NEXT_SHORT( p ); + + Exit: + return error; + + Too_Short: + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_exta_item_load_stem_snaps: invalid stem snaps table\n" )); + goto Exit; + } + + + + /* load kerning pair data */ + FT_CALLBACK_DEF( FT_Error ) + pfr_extra_item_load_kerning_pairs( FT_Byte* p, + FT_Byte* limit, + PFR_PhyFont phy_font ) + { + PFR_KernItem item; + FT_Error error = 0; + FT_Memory memory = phy_font->memory; + + + FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" )); + + if ( FT_NEW( item ) ) + goto Exit; + + PFR_CHECK( 4 ); + + item->pair_count = PFR_NEXT_BYTE( p ); + item->base_adj = PFR_NEXT_SHORT( p ); + item->flags = PFR_NEXT_BYTE( p ); + item->offset = phy_font->offset + ( p - phy_font->cursor ); + +#ifndef PFR_CONFIG_NO_CHECKS + item->pair_size = 3; + + if ( item->flags & PFR_KERN_2BYTE_CHAR ) + item->pair_size += 2; + + if ( item->flags & PFR_KERN_2BYTE_ADJ ) + item->pair_size += 1; + + PFR_CHECK( item->pair_count * item->pair_size ); +#endif + + /* load first and last pairs into the item to speed up */ + /* lookup later... */ + if ( item->pair_count > 0 ) + { + FT_UInt char1, char2; + FT_Byte* q; + + + if ( item->flags & PFR_KERN_2BYTE_CHAR ) + { + q = p; + char1 = PFR_NEXT_USHORT( q ); + char2 = PFR_NEXT_USHORT( q ); + + item->pair1 = PFR_KERN_INDEX( char1, char2 ); + + q = p + item->pair_size * ( item->pair_count - 1 ); + char1 = PFR_NEXT_USHORT( q ); + char2 = PFR_NEXT_USHORT( q ); + + item->pair2 = PFR_KERN_INDEX( char1, char2 ); + } + else + { + q = p; + char1 = PFR_NEXT_BYTE( q ); + char2 = PFR_NEXT_BYTE( q ); + + item->pair1 = PFR_KERN_INDEX( char1, char2 ); + + q = p + item->pair_size * ( item->pair_count - 1 ); + char1 = PFR_NEXT_BYTE( q ); + char2 = PFR_NEXT_BYTE( q ); + + item->pair2 = PFR_KERN_INDEX( char1, char2 ); + } + + /* add new item to the current list */ + item->next = NULL; + *phy_font->kern_items_tail = item; + phy_font->kern_items_tail = &item->next; + phy_font->num_kern_pairs += item->pair_count; + } + else + { + /* empty item! */ + FT_FREE( item ); + } + + Exit: + return error; + + Too_Short: + FT_FREE( item ); + + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_extra_item_load_kerning_pairs: " + "invalid kerning pairs table\n" )); + goto Exit; + } + + + /* + * The kerning data embedded in a PFR font are (charcode,charcode) + * pairs; we need to translate them to (gindex,gindex) and sort + * the resulting array. + */ + static FT_UInt + pfr_get_gindex( PFR_Char chars, + FT_UInt count, + FT_UInt charcode ) + { + FT_UInt min = 0; + FT_UInt max = count; + + + while ( min < max ) + { + FT_UInt mid = ( min + max ) >> 1; + PFR_Char c = chars + mid; + + + if ( c->char_code == charcode ) + return mid + 1; + + if ( c->char_code < charcode ) + min = mid + 1; + else + max = mid; + } + return 0; + } + + + FT_CALLBACK_DEF( int ) + pfr_compare_kern_pairs( const void* pair1, + const void* pair2 ) + { + FT_UInt32 p1 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair1 ); + FT_UInt32 p2 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair2 ); + + + if ( p1 < p2 ) + return -1; + if ( p1 > p2 ) + return 1; + return 0; + } + + + static FT_Error + pfr_sort_kerning_pairs( FT_Stream stream, + PFR_PhyFont phy_font ) + { + FT_Error error; + FT_Memory memory = stream->memory; + PFR_KernPair pairs; + PFR_KernItem item; + PFR_Char chars = phy_font->chars; + FT_UInt num_chars = phy_font->num_chars; + FT_UInt count; + + + /* create kerning pairs array + */ + if ( FT_NEW_ARRAY( phy_font->kern_pairs, phy_font->num_kern_pairs ) ) + goto Exit; + + /* load all kerning items into the array, + * converting character codes into glyph indices + */ + pairs = phy_font->kern_pairs; + item = phy_font->kern_items; + count = 0; + + for ( ; item; item = item->next ) + { + FT_UInt limit = count + item->pair_count; + FT_Byte* p; + + + if ( limit > phy_font->num_kern_pairs ) + { + error = PFR_Err_Invalid_Table; + goto Exit; + } + + if ( FT_STREAM_SEEK( item->offset ) || + FT_FRAME_ENTER( item->pair_count * item->pair_size ) ) + goto Exit; + + p = stream->cursor; + + for ( ; count < limit; count++ ) + { + PFR_KernPair pair = pairs + count; + FT_UInt char1, char2; + FT_Int kerning; + + + if ( item->flags & PFR_KERN_2BYTE_CHAR ) + { + char1 = FT_NEXT_USHORT( p ); + char2 = FT_NEXT_USHORT( p ); + } + else + { + char1 = FT_NEXT_BYTE( p ); + char2 = FT_NEXT_BYTE( p ); + } + + if ( item->flags & PFR_KERN_2BYTE_ADJ ) + kerning = item->base_adj + FT_NEXT_SHORT( p ); + else + kerning = item->base_adj + FT_NEXT_CHAR( p ); + + pair->glyph1 = pfr_get_gindex( chars, num_chars, char1 ); + pair->glyph2 = pfr_get_gindex( chars, num_chars, char2 ); + pair->kerning = kerning; + } + + FT_FRAME_EXIT(); + } + + /* sort the resulting array + */ + ft_qsort( pairs, count, + sizeof ( PFR_KernPairRec ), + pfr_compare_kern_pairs ); + + Exit: + if ( error ) + { + /* disable kerning data in case of error + */ + phy_font->num_kern_pairs = 0; + } + + return error; + } + + + static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = + { + { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info }, + { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id }, + { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps }, + { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs }, + { 0, NULL } + }; + + + /* Loads a name from the auxiliary data. Since this extracts undocumented + * strings from the font file, we need to be careful here. + */ + static FT_Error + pfr_aux_name_load( FT_Byte* p, + FT_UInt len, + FT_Memory memory, + FT_String* *astring ) + { + FT_Error error = 0; + FT_String* result = NULL; + FT_UInt n, ok; + + + if ( len > 0 && p[len - 1] == 0 ) + len--; + + /* check that each character is ASCII for making sure not to + load garbage + */ + ok = ( len > 0 ); + for ( n = 0; n < len; n++ ) + if ( p[n] < 32 || p[n] > 127 ) + { + ok = 0; + break; + } + + if ( ok ) + { + if ( FT_ALLOC( result, len + 1 ) ) + goto Exit; + + FT_MEM_COPY( result, p, len ); + result[len] = 0; + } + Exit: + *astring = result; + return error; + } + + + FT_LOCAL_DEF( void ) + pfr_phy_font_done( PFR_PhyFont phy_font, + FT_Memory memory ) + { + FT_FREE( phy_font->font_id ); + FT_FREE( phy_font->family_name ); + FT_FREE( phy_font->style_name ); + + FT_FREE( phy_font->vertical.stem_snaps ); + phy_font->vertical.num_stem_snaps = 0; + + phy_font->horizontal.stem_snaps = NULL; + phy_font->horizontal.num_stem_snaps = 0; + + FT_FREE( phy_font->strikes ); + phy_font->num_strikes = 0; + phy_font->max_strikes = 0; + + FT_FREE( phy_font->chars ); + phy_font->num_chars = 0; + phy_font->chars_offset = 0; + + FT_FREE( phy_font->blue_values ); + phy_font->num_blue_values = 0; + + FT_FREE( phy_font->kern_pairs ); + { + PFR_KernItem item, next; + + + item = phy_font->kern_items; + while ( item ) + { + next = item->next; + FT_FREE( item ); + item = next; + } + phy_font->kern_items = NULL; + phy_font->kern_items_tail = NULL; + } + + phy_font->num_kern_pairs = 0; + } + + + FT_LOCAL_DEF( FT_Error ) + pfr_phy_font_load( PFR_PhyFont phy_font, + FT_Stream stream, + FT_UInt32 offset, + FT_UInt32 size ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_UInt flags, num_aux; + FT_Byte* p; + FT_Byte* limit; + + + phy_font->memory = memory; + phy_font->offset = offset; + + phy_font->kern_items = NULL; + phy_font->kern_items_tail = &phy_font->kern_items; + + if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) ) + goto Exit; + + phy_font->cursor = stream->cursor; + + p = stream->cursor; + limit = p + size; + + PFR_CHECK( 15 ); + phy_font->font_ref_number = PFR_NEXT_USHORT( p ); + phy_font->outline_resolution = PFR_NEXT_USHORT( p ); + phy_font->metrics_resolution = PFR_NEXT_USHORT( p ); + phy_font->bbox.xMin = PFR_NEXT_SHORT( p ); + phy_font->bbox.yMin = PFR_NEXT_SHORT( p ); + phy_font->bbox.xMax = PFR_NEXT_SHORT( p ); + phy_font->bbox.yMax = PFR_NEXT_SHORT( p ); + phy_font->flags = flags = PFR_NEXT_BYTE( p ); + + /* get the standard advance for non-proprotional fonts */ + if ( !(flags & PFR_PHY_PROPORTIONAL) ) + { + PFR_CHECK( 2 ); + phy_font->standard_advance = PFR_NEXT_SHORT( p ); + } + + /* load the extra items when present */ + if ( flags & PFR_PHY_EXTRA_ITEMS ) + { + error = pfr_extra_items_parse( &p, limit, + pfr_phy_font_extra_items, phy_font ); + + if ( error ) + goto Fail; + } + + /* In certain fonts, the auxiliary bytes contain interesting */ + /* information. These are not in the specification but can be */ + /* guessed by looking at the content of a few PFR0 fonts. */ + PFR_CHECK( 3 ); + num_aux = PFR_NEXT_ULONG( p ); + + if ( num_aux > 0 ) + { + FT_Byte* q = p; + FT_Byte* q2; + + + PFR_CHECK( num_aux ); + p += num_aux; + + while ( num_aux > 0 ) + { + FT_UInt length, type; + + + if ( q + 4 > p ) + break; + + length = PFR_NEXT_USHORT( q ); + if ( length < 4 || length > num_aux ) + break; + + q2 = q + length - 2; + type = PFR_NEXT_USHORT( q ); + + switch ( type ) + { + case 1: + /* this seems to correspond to the font's family name, + * padded to 16-bits with one zero when necessary + */ + error = pfr_aux_name_load( q, length - 4U, memory, + &phy_font->family_name ); + if ( error ) + goto Exit; + break; + + case 2: + if ( q + 32 > q2 ) + break; + + q += 10; + phy_font->ascent = PFR_NEXT_SHORT( q ); + phy_font->descent = PFR_NEXT_SHORT( q ); + phy_font->leading = PFR_NEXT_SHORT( q ); + q += 16; + break; + + case 3: + /* this seems to correspond to the font's style name, + * padded to 16-bits with one zero when necessary + */ + error = pfr_aux_name_load( q, length - 4U, memory, + &phy_font->style_name ); + if ( error ) + goto Exit; + break; + + default: + ; + } + + q = q2; + num_aux -= length; + } + } + + /* read the blue values */ + { + FT_UInt n, count; + + + PFR_CHECK( 1 ); + phy_font->num_blue_values = count = PFR_NEXT_BYTE( p ); + + PFR_CHECK( count * 2 ); + + if ( FT_NEW_ARRAY( phy_font->blue_values, count ) ) + goto Fail; + + for ( n = 0; n < count; n++ ) + phy_font->blue_values[n] = PFR_NEXT_SHORT( p ); + } + + PFR_CHECK( 8 ); + phy_font->blue_fuzz = PFR_NEXT_BYTE( p ); + phy_font->blue_scale = PFR_NEXT_BYTE( p ); + + phy_font->vertical.standard = PFR_NEXT_USHORT( p ); + phy_font->horizontal.standard = PFR_NEXT_USHORT( p ); + + /* read the character descriptors */ + { + FT_UInt n, count, Size; + + + phy_font->num_chars = count = PFR_NEXT_USHORT( p ); + phy_font->chars_offset = offset + ( p - stream->cursor ); + + if ( FT_NEW_ARRAY( phy_font->chars, count ) ) + goto Fail; + + Size = 1 + 1 + 2; + if ( flags & PFR_PHY_2BYTE_CHARCODE ) + Size += 1; + + if ( flags & PFR_PHY_PROPORTIONAL ) + Size += 2; + + if ( flags & PFR_PHY_ASCII_CODE ) + Size += 1; + + if ( flags & PFR_PHY_2BYTE_GPS_SIZE ) + Size += 1; + + if ( flags & PFR_PHY_3BYTE_GPS_OFFSET ) + Size += 1; + + PFR_CHECK( count * Size ); + + for ( n = 0; n < count; n++ ) + { + PFR_Char cur = &phy_font->chars[n]; + + + cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE ) + ? PFR_NEXT_USHORT( p ) + : PFR_NEXT_BYTE( p ); + + cur->advance = ( flags & PFR_PHY_PROPORTIONAL ) + ? PFR_NEXT_SHORT( p ) + : (FT_Int) phy_font->standard_advance; + +#if 0 + cur->ascii = ( flags & PFR_PHY_ASCII_CODE ) + ? PFR_NEXT_BYTE( p ) + : 0; +#else + if ( flags & PFR_PHY_ASCII_CODE ) + p += 1; +#endif + cur->gps_size = ( flags & PFR_PHY_2BYTE_GPS_SIZE ) + ? PFR_NEXT_USHORT( p ) + : PFR_NEXT_BYTE( p ); + + cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET ) + ? PFR_NEXT_ULONG( p ) + : PFR_NEXT_USHORT( p ); + } + } + + /* that's it! */ + + Fail: + FT_FRAME_EXIT(); + + /* save position of bitmap info */ + phy_font->bct_offset = FT_STREAM_POS(); + phy_font->cursor = NULL; + + /* now sort kerning pairs */ + error = pfr_sort_kerning_pairs( stream, phy_font ); + + Exit: + return error; + + Too_Short: + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" )); + goto Fail; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrload.h b/Utilities/vtkfreetype/src/pfr/pfrload.h new file mode 100644 index 0000000..9e54b7d --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrload.h @@ -0,0 +1,118 @@ +/***************************************************************************/ +/* */ +/* pfrload.h */ +/* */ +/* FreeType PFR loader (specification). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PFRLOAD_H__ +#define __PFRLOAD_H__ + +#include "pfrobjs.h" +#include FT_INTERNAL_STREAM_H + + +FT_BEGIN_HEADER + +#ifdef PFR_CONFIG_NO_CHECKS +#define PFR_CHECK( x ) do { } while ( 0 ) +#else +#define PFR_CHECK( x ) do \ + { \ + if ( p + (x) > limit ) \ + goto Too_Short; \ + } while ( 0 ) +#endif + +#define PFR_NEXT_BYTE( p ) FT_NEXT_BYTE( p ) +#define PFR_NEXT_INT8( p ) FT_NEXT_CHAR( p ) +#define PFR_NEXT_SHORT( p ) FT_NEXT_SHORT( p ) +#define PFR_NEXT_USHORT( p ) FT_NEXT_USHORT( p ) +#define PFR_NEXT_LONG( p ) FT_NEXT_OFF3( p ) +#define PFR_NEXT_ULONG( p ) FT_NEXT_UOFF3( p ) + + + /* handling extra items */ + + typedef FT_Error + (*PFR_ExtraItem_ParseFunc)( FT_Byte* p, + FT_Byte* limit, + FT_Pointer data ); + + typedef struct PFR_ExtraItemRec_ + { + FT_UInt type; + PFR_ExtraItem_ParseFunc parser; + + } PFR_ExtraItemRec; + + typedef const struct PFR_ExtraItemRec_* PFR_ExtraItem; + + + FT_LOCAL( FT_Error ) + pfr_extra_items_skip( FT_Byte* *pp, + FT_Byte* limit ); + + FT_LOCAL( FT_Error ) + pfr_extra_items_parse( FT_Byte* *pp, + FT_Byte* limit, + PFR_ExtraItem item_list, + FT_Pointer item_data ); + + + /* load a PFR header */ + FT_LOCAL( FT_Error ) + pfr_header_load( PFR_Header header, + FT_Stream stream ); + + /* check a PFR header */ + FT_LOCAL( FT_Bool ) + pfr_header_check( PFR_Header header ); + + + /* return number of logical fonts in this file */ + FT_LOCAL( FT_Error ) + pfr_log_font_count( FT_Stream stream, + FT_UInt32 log_section_offset, + FT_UInt *acount ); + + /* load a pfr logical font entry */ + FT_LOCAL( FT_Error ) + pfr_log_font_load( PFR_LogFont log_font, + FT_Stream stream, + FT_UInt face_index, + FT_UInt32 section_offset, + FT_Bool size_increment ); + + + /* load a physical font entry */ + FT_LOCAL( FT_Error ) + pfr_phy_font_load( PFR_PhyFont phy_font, + FT_Stream stream, + FT_UInt32 offset, + FT_UInt32 size ); + + /* finalize a physical font */ + FT_LOCAL( void ) + pfr_phy_font_done( PFR_PhyFont phy_font, + FT_Memory memory ); + + /* */ + +FT_END_HEADER + +#endif /* __PFRLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrobjs.c b/Utilities/vtkfreetype/src/pfr/pfrobjs.c new file mode 100644 index 0000000..8b318e9 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrobjs.c @@ -0,0 +1,465 @@ +/***************************************************************************/ +/* */ +/* pfrobjs.c */ +/* */ +/* FreeType PFR object methods (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "pfrobjs.h" +#include "pfrload.h" +#include "pfrgload.h" +#include "pfrcmap.h" +#include "pfrsbit.h" +#include FT_OUTLINE_H +#include FT_INTERNAL_DEBUG_H + +#include "pfrerror.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pfr + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FACE OBJECT METHODS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL_DEF( void ) + pfr_face_done( FT_Face pfrface ) /* PFR_Face */ + { + PFR_Face face = (PFR_Face)pfrface; + FT_Memory memory = pfrface->driver->root.memory; + + + /* we don't want dangling pointers */ + pfrface->family_name = NULL; + pfrface->style_name = NULL; + + /* finalize the physical font record */ + pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) ); + + /* no need to finalize the logical font or the header */ + FT_FREE( pfrface->available_sizes ); + } + + + FT_LOCAL_DEF( FT_Error ) + pfr_face_init( FT_Stream stream, + FT_Face pfrface, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + PFR_Face face = (PFR_Face)pfrface; + FT_Error error; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + /* load the header and check it */ + error = pfr_header_load( &face->header, stream ); + if ( error ) + goto Exit; + + if ( !pfr_header_check( &face->header ) ) + { + FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" )); + error = PFR_Err_Unknown_File_Format; + goto Exit; + } + + /* check face index */ + { + FT_UInt num_faces; + + + error = pfr_log_font_count( stream, + face->header.log_dir_offset, + &num_faces ); + if ( error ) + goto Exit; + + pfrface->num_faces = num_faces; + } + + if ( face_index < 0 ) + goto Exit; + + if ( face_index >= pfrface->num_faces ) + { + FT_ERROR(( "pfr_face_init: invalid face index\n" )); + error = PFR_Err_Invalid_Argument; + goto Exit; + } + + /* load the face */ + error = pfr_log_font_load( + &face->log_font, stream, face_index, + face->header.log_dir_offset, + FT_BOOL( face->header.phy_font_max_size_high != 0 ) ); + if ( error ) + goto Exit; + + /* now load the physical font descriptor */ + error = pfr_phy_font_load( &face->phy_font, stream, + face->log_font.phys_offset, + face->log_font.phys_size ); + if ( error ) + goto Exit; + + /* now, set-up all root face fields */ + { + PFR_PhyFont phy_font = &face->phy_font; + + + pfrface->face_index = face_index; + pfrface->num_glyphs = phy_font->num_chars; + pfrface->face_flags = FT_FACE_FLAG_SCALABLE; + + if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 ) + pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + if ( phy_font->flags & PFR_PHY_VERTICAL ) + pfrface->face_flags |= FT_FACE_FLAG_VERTICAL; + else + pfrface->face_flags |= FT_FACE_FLAG_HORIZONTAL; + + if ( phy_font->num_strikes > 0 ) + pfrface->face_flags |= FT_FACE_FLAG_FIXED_SIZES; + + if ( phy_font->num_kern_pairs > 0 ) + pfrface->face_flags |= FT_FACE_FLAG_KERNING; + + /* If no family name was found in the "undocumented" auxiliary + * data, use the font ID instead. This sucks but is better than + * nothing. + */ + pfrface->family_name = phy_font->family_name; + if ( pfrface->family_name == NULL ) + pfrface->family_name = phy_font->font_id; + + /* note that the style name can be NULL in certain PFR fonts, + * probably meaning "Regular" + */ + pfrface->style_name = phy_font->style_name; + + pfrface->num_fixed_sizes = 0; + pfrface->available_sizes = 0; + + pfrface->bbox = phy_font->bbox; + pfrface->units_per_EM = (FT_UShort)phy_font->outline_resolution; + pfrface->ascender = (FT_Short) phy_font->bbox.yMax; + pfrface->descender = (FT_Short) phy_font->bbox.yMin; + pfrface->height = (FT_Short)( + ( ( pfrface->ascender - pfrface->descender ) * 12 ) / 10 ); + + if ( phy_font->num_strikes > 0 ) + { + FT_UInt n, count = phy_font->num_strikes; + FT_Bitmap_Size* size; + PFR_Strike strike; + FT_Memory memory = pfrface->stream->memory; + + + if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) ) + goto Exit; + + size = pfrface->available_sizes; + strike = phy_font->strikes; + for ( n = 0; n < count; n++, size++, strike++ ) + { + size->height = (FT_UShort)strike->y_ppm; + size->width = (FT_UShort)strike->x_ppm; + } + pfrface->num_fixed_sizes = count; + } + + /* now compute maximum advance width */ + if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 ) + pfrface->max_advance_width = (FT_Short)phy_font->standard_advance; + else + { + FT_Int max = 0; + FT_UInt count = phy_font->num_chars; + PFR_Char gchar = phy_font->chars; + + + for ( ; count > 0; count--, gchar++ ) + { + if ( max < gchar->advance ) + max = gchar->advance; + } + + pfrface->max_advance_width = (FT_Short)max; + } + + pfrface->max_advance_height = pfrface->height; + + pfrface->underline_position = (FT_Short)( -pfrface->units_per_EM / 10 ); + pfrface->underline_thickness = (FT_Short)( pfrface->units_per_EM / 30 ); + + /* create charmap */ + { + FT_CharMapRec charmap; + + + charmap.face = pfrface; + charmap.platform_id = 3; + charmap.encoding_id = 1; + charmap.encoding = FT_ENCODING_UNICODE; + + FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL ); + +#if 0 + /* Select default charmap */ + if ( pfrface->num_charmaps ) + pfrface->charmap = pfrface->charmaps[0]; +#endif + } + + /* check whether we've loaded any kerning pairs */ + if ( phy_font->num_kern_pairs ) + pfrface->face_flags |= FT_FACE_FLAG_KERNING; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** SLOT OBJECT METHOD *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL_DEF( FT_Error ) + pfr_slot_init( FT_GlyphSlot pfrslot ) /* PFR_Slot */ + { + PFR_Slot slot = (PFR_Slot)pfrslot; + FT_GlyphLoader loader = pfrslot->internal->loader; + + + pfr_glyph_init( &slot->glyph, loader ); + + return 0; + } + + + FT_LOCAL_DEF( void ) + pfr_slot_done( FT_GlyphSlot pfrslot ) /* PFR_Slot */ + { + PFR_Slot slot = (PFR_Slot)pfrslot; + + + pfr_glyph_done( &slot->glyph ); + } + + + FT_LOCAL_DEF( FT_Error ) + pfr_slot_load( FT_GlyphSlot pfrslot, /* PFR_Slot */ + FT_Size pfrsize, /* PFR_Size */ + FT_UInt gindex, + FT_Int32 load_flags ) + { + PFR_Slot slot = (PFR_Slot)pfrslot; + PFR_Size size = (PFR_Size)pfrsize; + FT_Error error; + PFR_Face face = (PFR_Face)pfrslot->face; + PFR_Char gchar; + FT_Outline* outline = &pfrslot->outline; + FT_ULong gps_offset; + + + if ( gindex > 0 ) + gindex--; + + /* check that the glyph index is correct */ + FT_ASSERT( gindex < face->phy_font.num_chars ); + + /* try to load an embedded bitmap */ + if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) + { + error = pfr_slot_load_bitmap( slot, size, gindex ); + if ( error == 0 ) + goto Exit; + } + + if ( load_flags & FT_LOAD_SBITS_ONLY ) + { + error = PFR_Err_Invalid_Argument; + goto Exit; + } + + gchar = face->phy_font.chars + gindex; + pfrslot->format = FT_GLYPH_FORMAT_OUTLINE; + outline->n_points = 0; + outline->n_contours = 0; + gps_offset = face->header.gps_section_offset; + + /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */ + error = pfr_glyph_load( &slot->glyph, face->root.stream, + gps_offset, gchar->gps_offset, gchar->gps_size ); + + if ( !error ) + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &pfrslot->metrics; + FT_Pos advance; + FT_Int em_metrics, em_outline; + FT_Bool scaling; + + + scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); + + /* copy outline data */ + *outline = slot->glyph.loader->base.outline; + + outline->flags &= ~FT_OUTLINE_OWNER; + outline->flags |= FT_OUTLINE_REVERSE_FILL; + + if ( size && pfrsize->metrics.y_ppem < 24 ) + outline->flags |= FT_OUTLINE_HIGH_PRECISION; + + /* compute the advance vector */ + metrics->horiAdvance = 0; + metrics->vertAdvance = 0; + + advance = gchar->advance; + em_metrics = face->phy_font.metrics_resolution; + em_outline = face->phy_font.outline_resolution; + + if ( em_metrics != em_outline ) + advance = FT_MulDiv( advance, em_outline, em_metrics ); + + if ( face->phy_font.flags & PFR_PHY_VERTICAL ) + metrics->vertAdvance = advance; + else + metrics->horiAdvance = advance; + + pfrslot->linearHoriAdvance = metrics->horiAdvance; + pfrslot->linearVertAdvance = metrics->vertAdvance; + + /* make-up vertical metrics(?) */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + + /* Apply the font matrix, if any. */ + /* TODO: Test existing fonts with unusual matrix */ + /* whether we have to adjust Units per EM. */ + { + FT_Matrix font_matrix; + + + font_matrix.xx = face->log_font.matrix[0] << 8; + font_matrix.yx = face->log_font.matrix[1] << 8; + font_matrix.xy = face->log_font.matrix[2] << 8; + font_matrix.yy = face->log_font.matrix[3] << 8; + + FT_Outline_Transform( outline, &font_matrix ); + } + + /* scale when needed */ + if ( scaling ) + { + FT_Int n; + FT_Fixed x_scale = pfrsize->metrics.x_scale; + FT_Fixed y_scale = pfrsize->metrics.y_scale; + FT_Vector* vec = outline->points; + + + /* scale outline points */ + for ( n = 0; n < outline->n_points; n++, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + /* scale the advance */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + } + + /* compute the rest of the metrics */ + FT_Outline_Get_CBox( outline, &cbox ); + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax - metrics->height; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** KERNING METHOD *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL_DEF( FT_Error ) + pfr_face_get_kerning( FT_Face pfrface, /* PFR_Face */ + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + PFR_Face face = (PFR_Face)pfrface; + FT_Error error = PFR_Err_Ok; + PFR_PhyFont phy_font = &face->phy_font; + PFR_KernPair pairs = phy_font->kern_pairs; + FT_UInt32 idx = PFR_KERN_INDEX( glyph1, glyph2 ); + FT_UInt min, max; + + + kerning->x = 0; + kerning->y = 0; + + min = 0; + max = phy_font->num_kern_pairs; + + while ( min < max ) + { + FT_UInt mid = ( min + max ) >> 1; + PFR_KernPair pair = pairs + mid; + FT_UInt32 pidx = PFR_KERN_PAIR_INDEX( pair ); + + + if ( pidx == idx ) + { + kerning->x = pair->kerning; + break; + } + + if ( pidx < idx ) + min = mid + 1; + else + max = mid; + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrobjs.h b/Utilities/vtkfreetype/src/pfr/pfrobjs.h new file mode 100644 index 0000000..f6aa8b4 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrobjs.h @@ -0,0 +1,96 @@ +/***************************************************************************/ +/* */ +/* pfrobjs.h */ +/* */ +/* FreeType PFR object methods (specification). */ +/* */ +/* Copyright 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PFROBJS_H__ +#define __PFROBJS_H__ + +#include "pfrtypes.h" + + +FT_BEGIN_HEADER + + typedef struct PFR_FaceRec_* PFR_Face; + + typedef struct PFR_SizeRec_* PFR_Size; + + typedef struct PFR_SlotRec_* PFR_Slot; + + + typedef struct PFR_FaceRec_ + { + FT_FaceRec root; + PFR_HeaderRec header; + PFR_LogFontRec log_font; + PFR_PhyFontRec phy_font; + + } PFR_FaceRec; + + + typedef struct PFR_SizeRec_ + { + FT_SizeRec root; + + } PFR_SizeRec; + + + typedef struct PFR_SlotRec_ + { + FT_GlyphSlotRec root; + PFR_GlyphRec glyph; + + } PFR_SlotRec; + + + FT_LOCAL( FT_Error ) + pfr_face_init( FT_Stream stream, + FT_Face face, /* PFR_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + FT_LOCAL( void ) + pfr_face_done( FT_Face face ); /* PFR_Face */ + + + FT_LOCAL( FT_Error ) + pfr_face_get_kerning( FT_Face face, /* PFR_Face */ + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + + FT_LOCAL( FT_Error ) + pfr_slot_init( FT_GlyphSlot slot ); /* PFR_Slot */ + + FT_LOCAL( void ) + pfr_slot_done( FT_GlyphSlot slot ); /* PFR_Slot */ + + + FT_LOCAL( FT_Error ) + pfr_slot_load( FT_GlyphSlot slot, /* PFR_Slot */ + FT_Size size, /* PFR_Size */ + FT_UInt gindex, + FT_Int32 load_flags ); + + +FT_END_HEADER + +#endif /* __PFROBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrsbit.c b/Utilities/vtkfreetype/src/pfr/pfrsbit.c new file mode 100644 index 0000000..da8fdba --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrsbit.c @@ -0,0 +1,671 @@ +/***************************************************************************/ +/* */ +/* pfrsbit.c */ +/* */ +/* FreeType PFR bitmap loader (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "pfrsbit.h" +#include "pfrload.h" +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H + +#include "pfrerror.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pfr + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PFR BIT WRITER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct PFR_BitWriter_ + { + FT_Byte* line; /* current line start */ + FT_Int pitch; /* line size in bytes */ + FT_Int width; /* width in pixels/bits */ + FT_Int rows; /* number of remaining rows to scan */ + FT_Int total; /* total number of bits to draw */ + + } PFR_BitWriterRec, *PFR_BitWriter; + + + static void + pfr_bitwriter_init( PFR_BitWriter writer, + FT_Bitmap* target, + FT_Bool decreasing ) + { + writer->line = target->buffer; + writer->pitch = target->pitch; + writer->width = target->width; + writer->rows = target->rows; + writer->total = writer->width * writer->rows; + + if ( !decreasing ) + { + writer->line += writer->pitch * ( target->rows-1 ); + writer->pitch = -writer->pitch; + } + } + + + static void + pfr_bitwriter_decode_bytes( PFR_BitWriter writer, + FT_Byte* p, + FT_Byte* limit ) + { + FT_Int n, reload; + FT_Int left = writer->width; + FT_Byte* cur = writer->line; + FT_UInt mask = 0x80; + FT_UInt val = 0; + FT_UInt c = 0; + + + n = (FT_Int)( limit - p ) * 8; + if ( n > writer->total ) + n = writer->total; + + reload = n & 7; + + for ( ; n > 0; n-- ) + { + if ( ( n & 7 ) == reload ) + val = *p++; + + if ( val & 0x80 ) + c |= mask; + + val <<= 1; + mask >>= 1; + + if ( --left <= 0 ) + { + cur[0] = (FT_Byte)c; + left = writer->width; + mask = 0x80; + + writer->line += writer->pitch; + cur = writer->line; + c = 0; + } + else if ( mask == 0 ) + { + cur[0] = (FT_Byte)c; + mask = 0x80; + c = 0; + cur ++; + } + } + + if ( mask != 0x80 ) + cur[0] = (FT_Byte)c; + } + + + static void + pfr_bitwriter_decode_rle1( PFR_BitWriter writer, + FT_Byte* p, + FT_Byte* limit ) + { + FT_Int n, phase, count, counts[2], reload; + FT_Int left = writer->width; + FT_Byte* cur = writer->line; + FT_UInt mask = 0x80; + FT_UInt c = 0; + + + n = writer->total; + + phase = 1; + counts[0] = 0; + counts[1] = 0; + count = 0; + reload = 1; + + for ( ; n > 0; n-- ) + { + if ( reload ) + { + do + { + if ( phase ) + { + FT_Int v; + + + if ( p >= limit ) + break; + + v = *p++; + counts[0] = v >> 4; + counts[1] = v & 15; + phase = 0; + count = counts[0]; + } + else + { + phase = 1; + count = counts[1]; + } + + } while ( count == 0 ); + } + + if ( phase ) + c |= mask; + + mask >>= 1; + + if ( --left <= 0 ) + { + cur[0] = (FT_Byte) c; + left = writer->width; + mask = 0x80; + + writer->line += writer->pitch; + cur = writer->line; + c = 0; + } + else if ( mask == 0 ) + { + cur[0] = (FT_Byte)c; + mask = 0x80; + c = 0; + cur ++; + } + + reload = ( --count <= 0 ); + } + + if ( mask != 0x80 ) + cur[0] = (FT_Byte) c; + } + + + static void + pfr_bitwriter_decode_rle2( PFR_BitWriter writer, + FT_Byte* p, + FT_Byte* limit ) + { + FT_Int n, phase, count, reload; + FT_Int left = writer->width; + FT_Byte* cur = writer->line; + FT_UInt mask = 0x80; + FT_UInt c = 0; + + + n = writer->total; + + phase = 1; + count = 0; + reload = 1; + + for ( ; n > 0; n-- ) + { + if ( reload ) + { + do + { + if ( p >= limit ) + break; + + count = *p++; + phase = phase ^ 1; + + } while ( count == 0 ); + } + + if ( phase ) + c |= mask; + + mask >>= 1; + + if ( --left <= 0 ) + { + cur[0] = (FT_Byte) c; + c = 0; + mask = 0x80; + left = writer->width; + + writer->line += writer->pitch; + cur = writer->line; + } + else if ( mask == 0 ) + { + cur[0] = (FT_Byte)c; + c = 0; + mask = 0x80; + cur ++; + } + + reload = ( --count <= 0 ); + } + + if ( mask != 0x80 ) + cur[0] = (FT_Byte) c; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BITMAP DATA DECODING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + pfr_lookup_bitmap_data( FT_Byte* base, + FT_Byte* limit, + FT_UInt count, + FT_UInt flags, + FT_UInt char_code, + FT_ULong* found_offset, + FT_ULong* found_size ) + { + FT_UInt left, right, char_len; + FT_Bool two = FT_BOOL( flags & 1 ); + FT_Byte* buff; + + + char_len = 4; + if ( two ) char_len += 1; + if ( flags & 2 ) char_len += 1; + if ( flags & 4 ) char_len += 1; + + left = 0; + right = count; + + while ( left < right ) + { + FT_UInt middle, code; + + + middle = ( left + right ) >> 1; + buff = base + middle * char_len; + + /* check that we are not outside of the table -- */ + /* this is possible with broken fonts... */ + if ( buff + char_len > limit ) + goto Fail; + + if ( two ) + code = PFR_NEXT_USHORT( buff ); + else + code = PFR_NEXT_BYTE( buff ); + + if ( code == char_code ) + goto Found_It; + + if ( code < char_code ) + left = middle; + else + right = middle; + } + + Fail: + /* Not found */ + *found_size = 0; + *found_offset = 0; + return; + + Found_It: + if ( flags & 2 ) + *found_size = PFR_NEXT_USHORT( buff ); + else + *found_size = PFR_NEXT_BYTE( buff ); + + if ( flags & 4 ) + *found_offset = PFR_NEXT_ULONG( buff ); + else + *found_offset = PFR_NEXT_USHORT( buff ); + } + + + /* load bitmap metrics. "*padvance" must be set to the default value */ + /* before calling this function... */ + /* */ + static FT_Error + pfr_load_bitmap_metrics( FT_Byte** pdata, + FT_Byte* limit, + FT_Long scaled_advance, + FT_Long *axpos, + FT_Long *aypos, + FT_UInt *axsize, + FT_UInt *aysize, + FT_Long *aadvance, + FT_UInt *aformat ) + { + FT_Error error = 0; + FT_Byte flags; + FT_Char b; + FT_Byte* p = *pdata; + FT_Long xpos, ypos, advance; + FT_UInt xsize, ysize; + + + PFR_CHECK( 1 ); + flags = PFR_NEXT_BYTE( p ); + + xpos = 0; + ypos = 0; + xsize = 0; + ysize = 0; + advance = 0; + + switch ( flags & 3 ) + { + case 0: + PFR_CHECK( 1 ); + b = PFR_NEXT_INT8( p ); + xpos = b >> 4; + ypos = ( (FT_Char)( b << 4 ) ) >> 4; + break; + + case 1: + PFR_CHECK( 2 ); + xpos = PFR_NEXT_INT8( p ); + ypos = PFR_NEXT_INT8( p ); + break; + + case 2: + PFR_CHECK( 4 ); + xpos = PFR_NEXT_SHORT( p ); + ypos = PFR_NEXT_SHORT( p ); + break; + + case 3: + PFR_CHECK( 6 ); + xpos = PFR_NEXT_LONG( p ); + ypos = PFR_NEXT_LONG( p ); + break; + + default: + ; + } + + flags >>= 2; + switch ( flags & 3 ) + { + case 0: + /* blank image */ + xsize = 0; + ysize = 0; + break; + + case 1: + PFR_CHECK( 1 ); + b = PFR_NEXT_BYTE( p ); + xsize = ( b >> 4 ) & 0xF; + ysize = b & 0xF; + break; + + case 2: + PFR_CHECK( 2 ); + xsize = PFR_NEXT_BYTE( p ); + ysize = PFR_NEXT_BYTE( p ); + break; + + case 3: + PFR_CHECK( 4 ); + xsize = PFR_NEXT_USHORT( p ); + ysize = PFR_NEXT_USHORT( p ); + break; + + default: + ; + } + + flags >>= 2; + switch ( flags & 3 ) + { + case 0: + advance = scaled_advance; + break; + + case 1: + PFR_CHECK( 1 ); + advance = PFR_NEXT_INT8( p ) << 8; + break; + + case 2: + PFR_CHECK( 2 ); + advance = PFR_NEXT_SHORT( p ); + break; + + case 3: + PFR_CHECK( 3 ); + advance = PFR_NEXT_LONG( p ); + break; + + default: + ; + } + + *axpos = xpos; + *aypos = ypos; + *axsize = xsize; + *aysize = ysize; + *aadvance = advance; + *aformat = flags >> 2; + *pdata = p; + + Exit: + return error; + + Too_Short: + error = PFR_Err_Invalid_Table; + FT_ERROR(( "pfr_load_bitmap_metrics: invalid glyph data\n" )); + goto Exit; + } + + + static FT_Error + pfr_load_bitmap_bits( FT_Byte* p, + FT_Byte* limit, + FT_UInt format, + FT_Bool decreasing, + FT_Bitmap* target ) + { + FT_Error error = 0; + PFR_BitWriterRec writer; + + + if ( target->rows > 0 && target->width > 0 ) + { + pfr_bitwriter_init( &writer, target, decreasing ); + + switch ( format ) + { + case 0: /* packed bits */ + pfr_bitwriter_decode_bytes( &writer, p, limit ); + break; + + case 1: /* RLE1 */ + pfr_bitwriter_decode_rle1( &writer, p, limit ); + break; + + case 2: /* RLE2 */ + pfr_bitwriter_decode_rle2( &writer, p, limit ); + break; + + default: + FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" )); + error = PFR_Err_Invalid_File_Format; + } + } + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BITMAP LOADING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL( FT_Error ) + pfr_slot_load_bitmap( PFR_Slot glyph, + PFR_Size size, + FT_UInt glyph_index ) + { + FT_Error error; + PFR_Face face = (PFR_Face) glyph->root.face; + FT_Stream stream = face->root.stream; + PFR_PhyFont phys = &face->phy_font; + FT_ULong gps_offset; + FT_ULong gps_size; + PFR_Char character; + PFR_Strike strike; + + + character = &phys->chars[glyph_index]; + + /* Look-up a bitmap strike corresponding to the current */ + /* character dimensions */ + { + FT_UInt n; + + + strike = phys->strikes; + for ( n = 0; n < phys->num_strikes; n++ ) + { + if ( strike->x_ppm == (FT_UInt)size->root.metrics.x_ppem && + strike->y_ppm == (FT_UInt)size->root.metrics.y_ppem ) + { + goto Found_Strike; + } + + strike++; + } + + /* couldn't find it */ + return PFR_Err_Invalid_Argument; + } + + Found_Strike: + + /* Now lookup the glyph's position within the file */ + { + FT_UInt char_len; + + + char_len = 4; + if ( strike->flags & 1 ) char_len += 1; + if ( strike->flags & 2 ) char_len += 1; + if ( strike->flags & 4 ) char_len += 1; + + /* Access data directly in the frame to speed lookups */ + if ( FT_STREAM_SEEK( phys->bct_offset + strike->bct_offset ) || + FT_FRAME_ENTER( char_len * strike->num_bitmaps ) ) + goto Exit; + + pfr_lookup_bitmap_data( stream->cursor, + stream->limit, + strike->num_bitmaps, + strike->flags, + character->char_code, + &gps_offset, + &gps_size ); + + FT_FRAME_EXIT(); + + if ( gps_size == 0 ) + { + /* Could not find a bitmap program string for this glyph */ + error = PFR_Err_Invalid_Argument; + goto Exit; + } + } + + /* get the bitmap metrics */ + { + FT_Long xpos, ypos, advance; + FT_UInt xsize, ysize, format; + FT_Byte* p; + + + advance = FT_MulDiv( size->root.metrics.x_ppem << 8, + character->advance, + phys->metrics_resolution ); + + /* XXX: handle linearHoriAdvance correctly! */ + + if ( FT_STREAM_SEEK( face->header.gps_section_offset + gps_offset ) || + FT_FRAME_ENTER( gps_size ) ) + goto Exit; + + p = stream->cursor; + error = pfr_load_bitmap_metrics( &p, stream->limit, + advance, + &xpos, &ypos, + &xsize, &ysize, + &advance, &format ); + if ( !error ) + { + glyph->root.format = FT_GLYPH_FORMAT_BITMAP; + + /* Set up glyph bitmap and metrics */ + glyph->root.bitmap.width = (FT_Int)xsize; + glyph->root.bitmap.rows = (FT_Int)ysize; + glyph->root.bitmap.pitch = (FT_Long)( xsize + 7 ) >> 3; + glyph->root.bitmap.pixel_mode = FT_PIXEL_MODE_MONO; + + glyph->root.metrics.width = (FT_Long)xsize << 6; + glyph->root.metrics.height = (FT_Long)ysize << 6; + glyph->root.metrics.horiBearingX = xpos << 6; + glyph->root.metrics.horiBearingY = ypos << 6; + glyph->root.metrics.horiAdvance = FT_PIX_ROUND( ( advance >> 2 ) ); + glyph->root.metrics.vertBearingX = - glyph->root.metrics.width >> 1; + glyph->root.metrics.vertBearingY = 0; + glyph->root.metrics.vertAdvance = size->root.metrics.height; + + glyph->root.bitmap_left = xpos; + glyph->root.bitmap_top = ypos + ysize; + + /* Allocate and read bitmap data */ + { + FT_ULong len = glyph->root.bitmap.pitch * ysize; + + + error = ft_glyphslot_alloc_bitmap( &glyph->root, len ); + if ( !error ) + { + error = pfr_load_bitmap_bits( + p, + stream->limit, + format, + FT_BOOL(face->header.color_flags & 2), + &glyph->root.bitmap ); + } + } + } + + FT_FRAME_EXIT(); + } + + Exit: + return error; + } + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrsbit.h b/Utilities/vtkfreetype/src/pfr/pfrsbit.h new file mode 100644 index 0000000..015e9e6 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrsbit.h @@ -0,0 +1,36 @@ +/***************************************************************************/ +/* */ +/* pfrsbit.h */ +/* */ +/* FreeType PFR bitmap loader (specification). */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PFRSBIT_H__ +#define __PFRSBIT_H__ + +#include "pfrobjs.h" + +FT_BEGIN_HEADER + + FT_LOCAL( FT_Error ) + pfr_slot_load_bitmap( PFR_Slot glyph, + PFR_Size size, + FT_UInt glyph_index ); + +FT_END_HEADER + +#endif /* __PFR_SBIT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pfr/pfrtypes.h b/Utilities/vtkfreetype/src/pfr/pfrtypes.h new file mode 100644 index 0000000..a10a2b2 --- /dev/null +++ b/Utilities/vtkfreetype/src/pfr/pfrtypes.h @@ -0,0 +1,364 @@ +/***************************************************************************/ +/* */ +/* pfrtypes.h */ +/* */ +/* FreeType PFR data structures (specification only). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PFRTYPES_H__ +#define __PFRTYPES_H__ + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H + +FT_BEGIN_HEADER + + /************************************************************************/ + + /* the PFR Header structure */ + typedef struct PFR_HeaderRec_ + { + FT_UInt32 signature; + FT_UInt version; + FT_UInt signature2; + FT_UInt header_size; + + FT_UInt log_dir_size; + FT_UInt log_dir_offset; + + FT_UInt log_font_max_size; + FT_UInt32 log_font_section_size; + FT_UInt32 log_font_section_offset; + + FT_UInt32 phy_font_max_size; + FT_UInt32 phy_font_section_size; + FT_UInt32 phy_font_section_offset; + + FT_UInt gps_max_size; + FT_UInt32 gps_section_size; + FT_UInt32 gps_section_offset; + + FT_UInt max_blue_values; + FT_UInt max_x_orus; + FT_UInt max_y_orus; + + FT_UInt phy_font_max_size_high; + FT_UInt color_flags; + + FT_UInt32 bct_max_size; + FT_UInt32 bct_set_max_size; + FT_UInt32 phy_bct_set_max_size; + + FT_UInt num_phy_fonts; + FT_UInt max_vert_stem_snap; + FT_UInt max_horz_stem_snap; + FT_UInt max_chars; + + } PFR_HeaderRec, *PFR_Header; + + + /* used in `color_flags' field of the PFR_Header */ + typedef enum PFR_HeaderFlags_ + { + PFR_FLAG_BLACK_PIXEL = 1, + PFR_FLAG_INVERT_BITMAP = 2 + + } PFR_HeaderFlags; + + + /************************************************************************/ + + typedef struct PFR_LogFontRec_ + { + FT_UInt32 size; + FT_UInt32 offset; + + FT_Int32 matrix[4]; + FT_UInt stroke_flags; + FT_Int stroke_thickness; + FT_Int bold_thickness; + FT_Int32 miter_limit; + + FT_UInt32 phys_size; + FT_UInt32 phys_offset; + + } PFR_LogFontRec, *PFR_LogFont; + + + typedef enum PFR_LogFlags_ + { + PFR_LOG_EXTRA_ITEMS = 0x40, + PFR_LOG_2BYTE_BOLD = 0x20, + PFR_LOG_BOLD = 0x10, + PFR_LOG_2BYTE_STROKE = 8, + PFR_LOG_STROKE = 4, + PFR_LINE_JOIN_MASK = 3 + + } PFR_LogFlags; + + + typedef enum PFR_LineJoinFlags_ + { + PFR_LINE_JOIN_MITER = 0, + PFR_LINE_JOIN_ROUND = 1, + PFR_LINE_JOIN_BEVEL = 2 + + } PFR_LineJoinFlags; + + + /************************************************************************/ + + typedef enum PFR_BitmapFlags_ + { + PFR_BITMAP_3BYTE_OFFSET = 4, + PFR_BITMAP_2BYTE_SIZE = 2, + PFR_BITMAP_2BYTE_CHARCODE = 1 + + } PFR_BitmapFlags; + + + typedef struct PFR_BitmapCharRec_ + { + FT_UInt char_code; + FT_UInt gps_size; + FT_UInt32 gps_offset; + + } PFR_BitmapCharRec, *PFR_BitmapChar; + + + typedef enum PFR_StrikeFlags_ + { + PFR_STRIKE_2BYTE_COUNT = 0x10, + PFR_STRIKE_3BYTE_OFFSET = 0x08, + PFR_STRIKE_3BYTE_SIZE = 0x04, + PFR_STRIKE_2BYTE_YPPM = 0x02, + PFR_STRIKE_2BYTE_XPPM = 0x01 + + } PFR_StrikeFlags; + + + typedef struct PFR_StrikeRec_ + { + FT_UInt x_ppm; + FT_UInt y_ppm; + FT_UInt flags; + + FT_UInt32 gps_size; + FT_UInt32 gps_offset; + + FT_UInt32 bct_size; + FT_UInt32 bct_offset; + + /* optional */ + FT_UInt num_bitmaps; + PFR_BitmapChar bitmaps; + + } PFR_StrikeRec, *PFR_Strike; + + + /************************************************************************/ + + typedef struct PFR_CharRec_ + { + FT_UInt char_code; + FT_Int advance; + FT_UInt gps_size; + FT_UInt32 gps_offset; + + } PFR_CharRec, *PFR_Char; + + + /************************************************************************/ + + typedef struct PFR_DimensionRec_ + { + FT_UInt standard; + FT_UInt num_stem_snaps; + FT_Int* stem_snaps; + + } PFR_DimensionRec, *PFR_Dimension; + + /************************************************************************/ + + typedef struct PFR_KernItemRec_* PFR_KernItem; + + typedef struct PFR_KernItemRec_ + { + PFR_KernItem next; + FT_UInt pair_count; + FT_UInt pair_size; + FT_Int base_adj; + FT_UInt flags; + FT_UInt32 offset; + FT_UInt32 pair1; + FT_UInt32 pair2; + + } PFR_KernItemRec; + +#define PFR_KERN_INDEX( g1, g2 ) \ + ( ( (FT_UInt32)(g1) << 16 ) | (FT_UInt16)(g2) ) + +#define PFR_KERN_PAIR_INDEX( pair ) \ + PFR_KERN_INDEX( (pair)->glyph1, (pair)->glyph2 ) + + typedef struct PFR_KernPairRec_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Int kerning; + + } PFR_KernPairRec, *PFR_KernPair; + + /************************************************************************/ + + typedef struct PFR_PhyFontRec_ + { + FT_Memory memory; + FT_UInt32 offset; + + FT_UInt font_ref_number; + FT_UInt outline_resolution; + FT_UInt metrics_resolution; + FT_BBox bbox; + FT_UInt flags; + FT_UInt standard_advance; + + FT_Int ascent; /* optional, bbox.yMax if not present */ + FT_Int descent; /* optional, bbox.yMin if not present */ + FT_Int leading; /* optional, 0 if not present */ + + PFR_DimensionRec horizontal; + PFR_DimensionRec vertical; + + FT_String* font_id; + FT_String* family_name; + FT_String* style_name; + + FT_UInt num_strikes; + FT_UInt max_strikes; + PFR_StrikeRec* strikes; + + FT_UInt num_blue_values; + FT_Int *blue_values; + FT_UInt blue_fuzz; + FT_UInt blue_scale; + + FT_UInt num_chars; + FT_UInt32 chars_offset; + PFR_Char chars; + + FT_UInt num_kern_pairs; + PFR_KernItem kern_items; + PFR_KernItem* kern_items_tail; + PFR_KernPair kern_pairs; + + /* not part of the spec, but used during load */ + FT_UInt32 bct_offset; + FT_Byte* cursor; + + } PFR_PhyFontRec, *PFR_PhyFont; + + + typedef enum PFR_PhyFlags_ + { + PFR_PHY_EXTRA_ITEMS = 0x80, + PFR_PHY_3BYTE_GPS_OFFSET = 0x20, + PFR_PHY_2BYTE_GPS_SIZE = 0x10, + PFR_PHY_ASCII_CODE = 0x08, + PFR_PHY_PROPORTIONAL = 0x04, + PFR_PHY_2BYTE_CHARCODE = 0x02, + PFR_PHY_VERTICAL = 0x01 + + } PFR_PhyFlags; + + + typedef enum PFR_KernFlags_ + { + PFR_KERN_2BYTE_CHAR = 0x01, + PFR_KERN_2BYTE_ADJ = 0x02 + + } PFR_KernFlags; + + + /************************************************************************/ + + typedef enum PFR_GlyphFlags_ + { + PFR_GLYPH_IS_COMPOUND = 0x80, + PFR_GLYPH_EXTRA_ITEMS = 0x08, + PFR_GLYPH_1BYTE_XYCOUNT = 0x04, + PFR_GLYPH_XCOUNT = 0x02, + PFR_GLYPH_YCOUNT = 0x01 + + } PFR_GlyphFlags; + + + /* controlled coordinate */ + typedef struct PFR_CoordRec_ + { + FT_UInt org; + FT_UInt cur; + + } PFR_CoordRec, *PFR_Coord; + + + typedef struct PFR_SubGlyphRec_ + { + FT_Fixed x_scale; + FT_Fixed y_scale; + FT_Int x_delta; + FT_Int y_delta; + FT_UInt32 gps_offset; + FT_UInt gps_size; + + } PFR_SubGlyphRec, *PFR_SubGlyph; + + + typedef enum PFR_SubgGlyphFlags_ + { + PFR_SUBGLYPH_3BYTE_OFFSET = 0x80, + PFR_SUBGLYPH_2BYTE_SIZE = 0x40, + PFR_SUBGLYPH_YSCALE = 0x20, + PFR_SUBGLYPH_XSCALE = 0x10 + + } PFR_SubGlyphFlags; + + + typedef struct PFR_GlyphRec_ + { + FT_Byte format; + + FT_UInt num_x_control; + FT_UInt num_y_control; + FT_UInt max_xy_control; + FT_Pos* x_control; + FT_Pos* y_control; + + + FT_UInt num_subs; + FT_UInt max_subs; + PFR_SubGlyphRec* subs; + + FT_GlyphLoader loader; + FT_Bool path_begun; + + } PFR_GlyphRec, *PFR_Glyph; + + +FT_END_HEADER + +#endif /* __PFRTYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/psaux.c b/Utilities/vtkfreetype/src/psaux/psaux.c new file mode 100644 index 0000000..9928184 --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/psaux.c @@ -0,0 +1,28 @@ +/***************************************************************************/ +/* */ +/* psaux.c */ +/* */ +/* FreeType auxiliary PostScript driver component (body only). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "psobjs.c" +#include "psauxmod.c" +#include "t1decode.c" +#include "t1cmap.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/psauxerr.h b/Utilities/vtkfreetype/src/psaux/psauxerr.h new file mode 100644 index 0000000..d0baa3c --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/psauxerr.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* psauxerr.h */ +/* */ +/* PS auxiliary module error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the PS auxiliary module error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __PSAUXERR_H__ +#define __PSAUXERR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX PSaux_Err_ +#define FT_ERR_BASE FT_Mod_Err_PSaux + +#include FT_ERRORS_H + +#endif /* __PSAUXERR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/psauxmod.c b/Utilities/vtkfreetype/src/psaux/psauxmod.c new file mode 100644 index 0000000..756ec1c --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/psauxmod.c @@ -0,0 +1,119 @@ +/***************************************************************************/ +/* */ +/* psauxmod.c */ +/* */ +/* FreeType auxiliary PostScript module implementation (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "psauxmod.h" +#include "psobjs.h" +#include "t1decode.h" +#include "t1cmap.h" + + + FT_CALLBACK_TABLE_DEF + const PS_Table_FuncsRec ps_table_funcs = + { + ps_table_new, + ps_table_done, + ps_table_add, + ps_table_release + }; + + + FT_CALLBACK_TABLE_DEF + const PS_Parser_FuncsRec ps_parser_funcs = + { + ps_parser_init, + ps_parser_done, + ps_parser_skip_spaces, + ps_parser_skip_PS_token, + ps_parser_to_int, + ps_parser_to_fixed, + ps_parser_to_bytes, + ps_parser_to_coord_array, + ps_parser_to_fixed_array, + ps_parser_to_token, + ps_parser_to_token_array, + ps_parser_load_field, + ps_parser_load_field_table + }; + + + FT_CALLBACK_TABLE_DEF + const T1_Builder_FuncsRec t1_builder_funcs = + { + t1_builder_init, + t1_builder_done, + t1_builder_check_points, + t1_builder_add_point, + t1_builder_add_point1, + t1_builder_add_contour, + t1_builder_start_point, + t1_builder_close_contour + }; + + + FT_CALLBACK_TABLE_DEF + const T1_Decoder_FuncsRec t1_decoder_funcs = + { + t1_decoder_init, + t1_decoder_done, + t1_decoder_parse_charstrings + }; + + + FT_CALLBACK_TABLE_DEF + const T1_CMap_ClassesRec t1_cmap_classes = + { + &t1_cmap_standard_class_rec, + &t1_cmap_expert_class_rec, + &t1_cmap_custom_class_rec, + &t1_cmap_unicode_class_rec + }; + + + static + const PSAux_Interface psaux_interface = + { + &ps_table_funcs, + &ps_parser_funcs, + &t1_builder_funcs, + &t1_decoder_funcs, + + t1_decrypt, + + (const T1_CMap_ClassesRec*) &t1_cmap_classes, + }; + + + FT_CALLBACK_TABLE_DEF + const FT_Module_Class psaux_module_class = + { + 0, + sizeof( FT_ModuleRec ), + "psaux", + 0x20000L, + 0x20000L, + + &psaux_interface, /* module-specific interface */ + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/psauxmod.h b/Utilities/vtkfreetype/src/psaux/psauxmod.h new file mode 100644 index 0000000..92ac056 --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/psauxmod.h @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* psauxmod.h */ +/* */ +/* FreeType auxiliary PostScript module implementation (specification). */ +/* */ +/* Copyright 2000-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSAUXMOD_H__ +#define __PSAUXMOD_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Module_Class ) psaux_driver_class; + + +FT_END_HEADER + +#endif /* __PSAUXMOD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/psobjs.c b/Utilities/vtkfreetype/src/psaux/psobjs.c new file mode 100644 index 0000000..d02986c --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/psobjs.c @@ -0,0 +1,1784 @@ +/***************************************************************************/ +/* */ +/* psobjs.c */ +/* */ +/* Auxiliary functions for PostScript fonts (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_DEBUG_H + +#include "psobjs.h" + +#include "psauxerr.h" + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS_TABLE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ps_table_new */ + /* */ + /* <Description> */ + /* Initializes a PS_Table. */ + /* */ + /* <InOut> */ + /* table :: The address of the target table. */ + /* */ + /* <Input> */ + /* count :: The table size = the maximum number of elements. */ + /* */ + /* memory :: The memory object to use for all subsequent */ + /* reallocations. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + ps_table_new( PS_Table table, + FT_Int count, + FT_Memory memory ) + { + FT_Error error; + + + table->memory = memory; + if ( FT_NEW_ARRAY( table->elements, count ) || + FT_NEW_ARRAY( table->lengths, count ) ) + goto Exit; + + table->max_elems = count; + table->init = 0xDEADBEEFUL; + table->num_elems = 0; + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs; + + Exit: + if ( error ) + FT_FREE( table->elements ); + + return error; + } + + + static void + shift_elements( PS_Table table, + FT_Byte* old_base ) + { + FT_Long delta = (FT_Long)( table->block - old_base ); + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + for ( ; offset < limit; offset++ ) + { + if ( offset[0] ) + offset[0] += delta; + } + } + + + static FT_Error + reallocate_t1_table( PS_Table table, + FT_Long new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* allocate new base block */ + if ( FT_ALLOC( table->block, new_size ) ) + { + table->block = old_base; + return error; + } + + /* copy elements and shift offsets */ + if (old_base ) + { + FT_MEM_COPY( table->block, old_base, table->capacity ); + shift_elements( table, old_base ); + FT_FREE( old_base ); + } + + table->capacity = new_size; + + return PSaux_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ps_table_add */ + /* */ + /* <Description> */ + /* Adds an object to a PS_Table, possibly growing its memory block. */ + /* */ + /* <InOut> */ + /* table :: The target table. */ + /* */ + /* <Input> */ + /* idx :: The index of the object in the table. */ + /* */ + /* object :: The address of the object to copy in memory. */ + /* */ + /* length :: The length in bytes of the source object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. An error is returned if a */ + /* reallocation fails. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + ps_table_add( PS_Table table, + FT_Int idx, + void* object, + FT_PtrDist length ) + { + if ( idx < 0 || idx > table->max_elems ) + { + FT_ERROR(( "ps_table_add: invalid index\n" )); + return PSaux_Err_Invalid_Argument; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Offset new_size = table->capacity; + FT_Long in_offset; + + + in_offset = (FT_Long)((FT_Byte*)object - table->block); + if ( (FT_ULong)in_offset >= table->capacity ) + in_offset = -1; + + while ( new_size < table->cursor + length ) + { + /* increase size by 25% and round up to the nearest multiple + of 1024 */ + new_size += ( new_size >> 2 ) + 1; + new_size = FT_PAD_CEIL( new_size, 1024 ); + } + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + + if ( in_offset >= 0 ) + object = table->block + in_offset; + } + + /* add the object to the base block and adjust offset */ + table->elements[idx] = table->block + table->cursor; + table->lengths [idx] = length; + FT_MEM_COPY( table->block + table->cursor, object, length ); + + table->cursor += length; + return PSaux_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ps_table_done */ + /* */ + /* <Description> */ + /* Finalizes a PS_TableRec (i.e., reallocate it to its current */ + /* cursor). */ + /* */ + /* <InOut> */ + /* table :: The target table. */ + /* */ + /* <Note> */ + /* This function does NOT release the heap's memory block. It is up */ + /* to the caller to clean it, or reference it in its own structures. */ + /* */ + FT_LOCAL_DEF( void ) + ps_table_done( PS_Table table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base = table->block; + + + /* should never fail, because rec.cursor <= rec.size */ + if ( !old_base ) + return; + + if ( FT_ALLOC( table->block, table->cursor ) ) + return; + FT_MEM_COPY( table->block, old_base, table->cursor ); + shift_elements( table, old_base ); + + table->capacity = table->cursor; + FT_FREE( old_base ); + + FT_UNUSED( error ); + } + + + FT_LOCAL_DEF( void ) + ps_table_release( PS_Table table ) + { + FT_Memory memory = table->memory; + + + if ( (FT_ULong)table->init == 0xDEADBEEFUL ) + { + FT_FREE( table->block ); + FT_FREE( table->elements ); + FT_FREE( table->lengths ); + table->init = 0; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* In the PostScript Language Reference Manual (PLRM) the following */ + /* characters are called `whitespace characters'. */ +#define IS_T1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) +#define IS_T1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' || (c) == '\f' ) +#define IS_T1_NULLSPACE( c ) ( (c) == '\0' ) + + /* According to the PLRM all whitespace characters are equivalent, */ + /* except in comments and strings. */ +#define IS_T1_SPACE( c ) ( IS_T1_WHITESPACE( c ) || \ + IS_T1_LINESPACE( c ) || \ + IS_T1_NULLSPACE( c ) ) + + + /* The following array is used by various functions to quickly convert */ + /* digits (both decimal and non-decimal) into numbers. */ + +#if 'A' == 65 + /* ASCII */ + + static const char ft_char_table[128] = + { + /* 0x00 */ + -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, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + }; + + /* no character >= 0x80 can represent a valid number */ +#define OP >= + +#endif /* 'A' == 65 */ + +#if 'A' == 193 + /* EBCDIC */ + + static const char ft_char_table[128] = + { + /* 0x80 */ + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, + -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, + -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + } + + /* no character < 0x80 can represent a valid number */ +#define OP < + +#endif /* 'A' == 193 */ + + + /* first character must be already part of the comment */ + + static void + skip_comment( FT_Byte* *acur, + FT_Byte* limit ) + { + FT_Byte* cur = *acur; + + + while ( cur < limit ) + { + if ( IS_T1_LINESPACE( *cur ) ) + break; + cur++; + } + + *acur = cur; + } + + + static void + skip_spaces( FT_Byte* *acur, + FT_Byte* limit ) + { + FT_Byte* cur = *acur; + + + while ( cur < limit ) + { + if ( !IS_T1_SPACE( *cur ) ) + { + if ( *cur == '%' ) + /* According to the PLRM, a comment is equal to a space. */ + skip_comment( &cur, limit ); + else + break; + } + cur++; + } + + *acur = cur; + } + + + /* first character must be `(' */ + + static void + skip_literal_string( FT_Byte* *acur, + FT_Byte* limit ) + { + FT_Byte* cur = *acur; + FT_Int embed = 0; + + + while ( cur < limit ) + { + if ( *cur == '\\' ) + cur++; + else if ( *cur == '(' ) + embed++; + else if ( *cur == ')' ) + { + embed--; + if ( embed == 0 ) + { + cur++; + break; + } + } + cur++; + } + + *acur = cur; + } + + + /* first character must be `<' */ + + static void + skip_string( PS_Parser parser ) + { + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + while ( ++cur < limit ) + { + int d; + + + /* All whitespace characters are ignored. */ + skip_spaces( &cur, limit ); + if ( cur >= limit ) + break; + + if ( *cur OP 0x80 ) + break; + + d = ft_char_table[*cur & 0x7F]; + if ( d < 0 || d >= 16 ) + break; + } + + if ( cur < limit && *cur != '>' ) + parser->error = PSaux_Err_Invalid_File_Format; + else + cur++; + + parser->cursor = cur; + } + + + /***********************************************************************/ + /* */ + /* All exported parsing routines handle leading whitespace and stop at */ + /* the first character which isn't part of the just handled token. */ + /* */ + /***********************************************************************/ + + + FT_LOCAL_DEF( void ) + ps_parser_skip_PS_token( PS_Parser parser ) + { + /* Note: PostScript allows any non-delimiting, non-whitespace */ + /* character in a name (PS Ref Manual, 3rd ed, p31). */ + /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */ + + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + skip_spaces( &cur, limit ); /* this also skips comments */ + if ( cur >= limit ) + goto Exit; + + /* self-delimiting, single-character tokens */ + if ( *cur == '[' || *cur == ']' || + *cur == '{' || *cur == '}' ) + { + cur++; + goto Exit; + } + + if ( *cur == '(' ) /* (...) */ + { + skip_literal_string( &cur, limit ); + goto Exit; + } + + if ( *cur == '<' ) /* <...> */ + { + if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */ + { + cur++; + cur++; + goto Exit; + } + parser->cursor = cur; + skip_string( parser ); + return; + } + + if ( *cur == '>' ) + { + cur++; + if ( cur >= limit || *cur != '>' ) /* >> */ + { + parser->error = PSaux_Err_Invalid_File_Format; + goto Exit; + } + cur++; + goto Exit; + } + + if ( *cur == '/' ) + cur++; + + /* anything else */ + while ( cur < limit ) + { + if ( IS_T1_SPACE( *cur ) || + *cur == '(' || + *cur == '/' || + *cur == '%' || + *cur == '[' || *cur == ']' || + *cur == '{' || *cur == '}' || + *cur == '<' || *cur == '>' ) + break; + + if ( *cur == ')' ) + { + parser->error = PSaux_Err_Invalid_File_Format; + goto Exit; + } + + cur++; + } + + Exit: + parser->cursor = cur; + } + + + FT_LOCAL_DEF( void ) + ps_parser_skip_spaces( PS_Parser parser ) + { + skip_spaces( &parser->cursor, parser->limit ); + } + + + /* `token' here means either something between balanced delimiters */ + /* or the next token; the delimiters are not removed. */ + + FT_LOCAL_DEF( void ) + ps_parser_to_token( PS_Parser parser, + T1_Token token ) + { + FT_Byte* cur; + FT_Byte* limit; + FT_Byte starter, ender; + FT_Int embed; + + + token->type = T1_TOKEN_TYPE_NONE; + token->start = 0; + token->limit = 0; + + /* first of all, skip leading whitespace */ + ps_parser_skip_spaces( parser ); + + cur = parser->cursor; + limit = parser->limit; + + if ( cur >= limit ) + return; + + switch ( *cur ) + { + /************* check for literal string *****************/ + case '(': + token->type = T1_TOKEN_TYPE_STRING; + token->start = cur; + skip_literal_string( &cur, limit ); + if ( cur < limit ) + token->limit = cur; + break; + + /************* check for programs/array *****************/ + case '{': + token->type = T1_TOKEN_TYPE_ARRAY; + ender = '}'; + goto Lookup_Ender; + + /************* check for table/array ********************/ + case '[': + token->type = T1_TOKEN_TYPE_ARRAY; + ender = ']'; + /* fall through */ + + Lookup_Ender: + embed = 1; + starter = *cur; + token->start = cur++; + + /* we need this to catch `[ ]' */ + parser->cursor = cur; + ps_parser_skip_spaces( parser ); + cur = parser->cursor; + + while ( cur < limit && !parser->error ) + { + if ( *cur == starter ) + embed++; + else if ( *cur == ender ) + { + embed--; + if ( embed <= 0 ) + { + token->limit = ++cur; + break; + } + } + + parser->cursor = cur; + ps_parser_skip_PS_token( parser ); + /* we need this to catch `[XXX ]' */ + ps_parser_skip_spaces ( parser ); + cur = parser->cursor; + } + break; + + /* ************ otherwise, it is any token **************/ + default: + token->start = cur; + token->type = T1_TOKEN_TYPE_ANY; + ps_parser_skip_PS_token( parser ); + cur = parser->cursor; + if ( !parser->error ) + token->limit = cur; + } + + if ( !token->limit ) + { + token->start = 0; + token->type = T1_TOKEN_TYPE_NONE; + } + + parser->cursor = cur; + } + + + FT_LOCAL_DEF( void ) + ps_parser_to_token_array( PS_Parser parser, + T1_Token tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ) + { + T1_TokenRec master; + + + *pnum_tokens = -1; + + /* this also handles leading whitespace */ + ps_parser_to_token( parser, &master ); + + if ( master.type == T1_TOKEN_TYPE_ARRAY ) + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + T1_Token cur = tokens; + T1_Token limit = cur + max_tokens; + + + /* don't include outermost delimiters */ + parser->cursor = master.start + 1; + parser->limit = master.limit - 1; + + while ( parser->cursor < parser->limit ) + { + T1_TokenRec token; + + + ps_parser_to_token( parser, &token ); + if ( !token.type ) + break; + + if ( cur < limit ) + *cur = token; + + cur++; + } + + *pnum_tokens = (FT_Int)( cur - tokens ); + + parser->cursor = old_cursor; + parser->limit = old_limit; + } + } + + + /* first character must be already part of the number */ + + static FT_Long + ps_radix( FT_Long radixBase, + FT_Byte* *acur, + FT_Byte* limit ) + { + FT_Long result = 0; + FT_Byte* cur = *acur; + + + if ( radixBase < 2 || radixBase > 36 ) + return 0; + + while ( cur < limit ) + { + int d; + + + if ( *cur OP 0x80 ) + break; + + d = ft_char_table[*cur & 0x7F]; + if ( d < 0 || d >= radixBase ) + break; + + result = result * radixBase + d; + + cur++; + } + + *acur = cur; + + return result; + } + + + /* first character must be already part of the number */ + + static FT_Long + ps_toint( FT_Byte* *acur, + FT_Byte* limit ) + { + FT_Long result = 0; + FT_Byte* cur = *acur; + FT_Byte c; + + + if ( cur >= limit ) + goto Exit; + + c = *cur; + if ( c == '-' ) + cur++; + + while ( cur < limit ) + { + int d; + + + if ( *cur == '#' ) + { + cur++; + result = ps_radix( result, &cur, limit ); + break; + } + + if ( *cur OP 0x80 ) + break; + + d = ft_char_table[*cur & 0x7F]; + if ( d < 0 || d >= 10 ) + break; + result = result * 10 + d; + + cur++; + }; + + if ( c == '-' ) + result = -result; + + Exit: + *acur = cur; + return result; + } + + + /* first character must be `<' if `delimiters' is non-zero */ + + static FT_Error + ps_tobytes( FT_Byte* *acur, + FT_Byte* limit, + FT_Long max_bytes, + FT_Byte* bytes, + FT_Long* pnum_bytes, + FT_Bool delimiters ) + { + FT_Error error = PSaux_Err_Ok; + + FT_Byte* cur = *acur; + FT_Long n = 0; + + + if ( cur >= limit ) + goto Exit; + + if ( delimiters ) + { + if ( *cur != '<' ) + { + error = PSaux_Err_Invalid_File_Format; + goto Exit; + } + + cur++; + } + + max_bytes = max_bytes * 2; + + for ( n = 0; cur < limit; n++, cur++ ) + { + int d; + + + if ( n >= max_bytes ) + /* buffer is full */ + goto Exit; + + /* All whitespace characters are ignored. */ + skip_spaces( &cur, limit ); + if ( cur >= limit ) + break; + + if ( *cur OP 0x80 ) + break; + + d = ft_char_table[*cur & 0x7F]; + if ( d < 0 || d >= 16 ) + break; + + /* <f> == <f0> != <0f> */ + bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + d + : d * 16 ); + } + + if ( delimiters ) + { + if ( cur < limit && *cur != '>' ) + { + error = PSaux_Err_Invalid_File_Format; + goto Exit; + } + + cur++; + } + + *acur = cur; + + Exit: + *pnum_bytes = ( n + 1 ) / 2; + + return error; + } + + + /* first character must be already part of the number */ + + static FT_Long + ps_tofixed( FT_Byte* *acur, + FT_Byte* limit, + FT_Long power_ten ) + { + FT_Byte* cur = *acur; + FT_Long num, divider, result; + FT_Int sign = 0; + + + if ( cur >= limit ) + return 0; + + /* first of all, check the sign */ + if ( *cur == '-' && cur + 1 < limit ) + { + sign = 1; + cur++; + } + + /* then, read the integer part, if any */ + if ( *cur != '.' ) + result = ps_toint( &cur, limit ) << 16; + else + result = 0; + + num = 0; + divider = 1; + + if ( cur >= limit ) + goto Exit; + + /* read decimal part, if any */ + if ( *cur == '.' && cur + 1 < limit ) + { + cur++; + + for (;;) + { + int d; + + + if ( *cur OP 0x80 ) + break; + + d = ft_char_table[*cur & 0x7F]; + if ( d < 0 || d >= 10 ) + break; + + if ( divider < 10000000L ) + { + num = num * 10 + d; + divider *= 10; + } + + cur++; + if ( cur >= limit ) + break; + } + } + + /* read exponent, if any */ + if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) ) + { + cur++; + power_ten += ps_toint( &cur, limit ); + } + + Exit: + /* raise to power of ten if needed */ + while ( power_ten > 0 ) + { + result = result * 10; + num = num * 10; + power_ten--; + } + + while ( power_ten < 0 ) + { + result = result / 10; + divider = divider * 10; + power_ten++; + } + + if ( num ) + result += FT_DivFix( num, divider ); + + if ( sign ) + result = -result; + + *acur = cur; + return result; + } + + + /* first character must be a delimiter or a part of a number */ + + static FT_Int + ps_tocoordarray( FT_Byte* *acur, + FT_Byte* limit, + FT_Int max_coords, + FT_Short* coords ) + { + FT_Byte* cur = *acur; + FT_Int count = 0; + FT_Byte c, ender; + + + if ( cur >= limit ) + goto Exit; + + /* check for the beginning of an array; otherwise, only one number */ + /* will be read */ + c = *cur; + ender = 0; + + if ( c == '[' ) + ender = ']'; + + if ( c == '{' ) + ender = '}'; + + if ( ender ) + cur++; + + /* now, read the coordinates */ + while ( cur < limit ) + { + /* skip whitespace in front of data */ + skip_spaces( &cur, limit ); + if ( cur >= limit ) + goto Exit; + + if ( count >= max_coords ) + break; + + if ( c == ender ) + { + cur++; + break; + } + + coords[count] = (FT_Short)( ps_tofixed( &cur, limit, 0 ) >> 16 ); + count++; + + if ( !ender ) + break; + } + + Exit: + *acur = cur; + return count; + } + + + /* first character must be a delimiter or a part of a number */ + + static FT_Int + ps_tofixedarray( FT_Byte* *acur, + FT_Byte* limit, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ) + { + FT_Byte* cur = *acur; + FT_Int count = 0; + FT_Byte c, ender; + + + if ( cur >= limit ) + goto Exit; + + /* Check for the beginning of an array. Otherwise, only one number */ + /* will be read. */ + c = *cur; + ender = 0; + + if ( c == '[' ) + ender = ']'; + + if ( c == '{' ) + ender = '}'; + + if ( ender ) + cur++; + + /* now, read the values */ + while ( cur < limit ) + { + /* skip whitespace in front of data */ + skip_spaces( &cur, limit ); + if ( cur >= limit ) + goto Exit; + + if ( count >= max_values ) + break; + + if ( c == ender ) + { + cur++; + break; + } + + values[count] = ps_tofixed( &cur, limit, power_ten ); + count++; + + if ( !ender ) + break; + } + + Exit: + *acur = cur; + return count; + } + + +#if 0 + + static FT_String* + ps_tostring( FT_Byte** cursor, + FT_Byte* limit, + FT_Memory memory ) + { + FT_Byte* cur = *cursor; + FT_PtrDist len = 0; + FT_Int count; + FT_String* result; + FT_Error error; + + + /* XXX: some stupid fonts have a `Notice' or `Copyright' string */ + /* that simply doesn't begin with an opening parenthesis, even */ + /* though they have a closing one! E.g. "amuncial.pfb" */ + /* */ + /* We must deal with these ill-fated cases there. Note that */ + /* these fonts didn't work with the old Type 1 driver as the */ + /* notice/copyright was not recognized as a valid string token */ + /* and made the old token parser commit errors. */ + + while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) ) + cur++; + if ( cur + 1 >= limit ) + return 0; + + if ( *cur == '(' ) + cur++; /* skip the opening parenthesis, if there is one */ + + *cursor = cur; + count = 0; + + /* then, count its length */ + for ( ; cur < limit; cur++ ) + { + if ( *cur == '(' ) + count++; + + else if ( *cur == ')' ) + { + count--; + if ( count < 0 ) + break; + } + } + + len = cur - *cursor; + if ( cur >= limit || FT_ALLOC( result, len + 1 ) ) + return 0; + + /* now copy the string */ + FT_MEM_COPY( result, *cursor, len ); + result[len] = '\0'; + *cursor = cur; + return result; + } + +#endif /* 0 */ + + + static int + ps_tobool( FT_Byte* *acur, + FT_Byte* limit ) + { + FT_Byte* cur = *acur; + FT_Bool result = 0; + + + /* return 1 if we find `true', 0 otherwise */ + if ( cur + 3 < limit && + cur[0] == 't' && + cur[1] == 'r' && + cur[2] == 'u' && + cur[3] == 'e' ) + { + result = 1; + cur += 5; + } + else if ( cur + 4 < limit && + cur[0] == 'f' && + cur[1] == 'a' && + cur[2] == 'l' && + cur[3] == 's' && + cur[4] == 'e' ) + { + result = 0; + cur += 6; + } + + *acur = cur; + return result; + } + + + /* load a simple field (i.e. non-table) into the current list of objects */ + + FT_LOCAL_DEF( FT_Error ) + ps_parser_load_field( PS_Parser parser, + const T1_Field field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + T1_TokenRec token; + FT_Byte* cur; + FT_Byte* limit; + FT_UInt count; + FT_UInt idx; + FT_Error error; + + + /* this also skips leading whitespace */ + ps_parser_to_token( parser, &token ); + if ( !token.type ) + goto Fail; + + count = 1; + idx = 0; + cur = token.start; + limit = token.limit; + + /* we must detect arrays in /FontBBox */ + if ( field->type == T1_FIELD_TYPE_BBOX ) + { + T1_TokenRec token2; + FT_Byte* old_cur = parser->cursor; + FT_Byte* old_limit = parser->limit; + + + /* don't include delimiters */ + parser->cursor = token.start + 1; + parser->limit = token.limit - 1; + + ps_parser_to_token( parser, &token2 ); + parser->cursor = old_cur; + parser->limit = old_limit; + + if ( token2.type == T1_TOKEN_TYPE_ARRAY ) + goto FieldArray; + } + else if ( token.type == T1_TOKEN_TYPE_ARRAY ) + { + FieldArray: + /* if this is an array and we have no blend, an error occurs */ + if ( max_objects == 0 ) + goto Fail; + + count = max_objects; + idx = 1; + + /* don't include delimiters */ + cur++; + limit--; + } + + for ( ; count > 0; count--, idx++ ) + { + FT_Byte* q = (FT_Byte*)objects[idx] + field->offset; + FT_Long val; + FT_String* string; + + + skip_spaces( &cur, limit ); + + switch ( field->type ) + { + case T1_FIELD_TYPE_BOOL: + val = ps_tobool( &cur, limit ); + goto Store_Integer; + + case T1_FIELD_TYPE_FIXED: + val = ps_tofixed( &cur, limit, 0 ); + goto Store_Integer; + + case T1_FIELD_TYPE_FIXED_1000: + val = ps_tofixed( &cur, limit, 3 ); + goto Store_Integer; + + case T1_FIELD_TYPE_INTEGER: + val = ps_toint( &cur, limit ); + /* fall through */ + + Store_Integer: + switch ( field->size ) + { + case (8 / FT_CHAR_BIT): + *(FT_Byte*)q = (FT_Byte)val; + break; + + case (16 / FT_CHAR_BIT): + *(FT_UShort*)q = (FT_UShort)val; + break; + + case (32 / FT_CHAR_BIT): + *(FT_UInt32*)q = (FT_UInt32)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + break; + + case T1_FIELD_TYPE_STRING: + case T1_FIELD_TYPE_KEY: + { + FT_Memory memory = parser->memory; + FT_UInt len = (FT_UInt)( limit - cur ); + + + if ( cur >= limit ) + break; + + if ( field->type == T1_FIELD_TYPE_KEY ) + { + /* don't include leading `/' */ + len--; + cur++; + } + else + { + /* don't include delimiting parentheses */ + cur++; + len -= 2; + } + + if ( FT_ALLOC( string, len + 1 ) ) + goto Exit; + + FT_MEM_COPY( string, cur, len ); + string[len] = 0; + + *(FT_String**)q = string; + } + break; + + case T1_FIELD_TYPE_BBOX: + { + FT_Fixed temp[4]; + FT_BBox* bbox = (FT_BBox*)q; + + + (void)ps_tofixedarray( &token.start, token.limit, 4, temp, 0 ); + + bbox->xMin = FT_RoundFix( temp[0] ); + bbox->yMin = FT_RoundFix( temp[1] ); + bbox->xMax = FT_RoundFix( temp[2] ); + bbox->yMax = FT_RoundFix( temp[3] ); + } + break; + + default: + /* an error occured */ + goto Fail; + } + } + +#if 0 /* obsolete -- keep for reference */ + if ( pflags ) + *pflags |= 1L << field->flag_bit; +#else + FT_UNUSED( pflags ); +#endif + + error = PSaux_Err_Ok; + + Exit: + return error; + + Fail: + error = PSaux_Err_Invalid_File_Format; + goto Exit; + } + + +#define T1_MAX_TABLE_ELEMENTS 32 + + + FT_LOCAL_DEF( FT_Error ) + ps_parser_load_field_table( PS_Parser parser, + const T1_Field field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS]; + T1_Token token; + FT_Int num_elements; + FT_Error error = PSaux_Err_Ok; + FT_Byte* old_cursor; + FT_Byte* old_limit; + T1_FieldRec fieldrec = *(T1_Field)field; + + +#if 1 + fieldrec.type = T1_FIELD_TYPE_INTEGER; + if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ) + fieldrec.type = T1_FIELD_TYPE_FIXED; +#endif + + ps_parser_to_token_array( parser, elements, + T1_MAX_TABLE_ELEMENTS, &num_elements ); + if ( num_elements < 0 ) + { + error = PSaux_Err_Ignore; + goto Exit; + } + if ( num_elements > T1_MAX_TABLE_ELEMENTS ) + num_elements = T1_MAX_TABLE_ELEMENTS; + + old_cursor = parser->cursor; + old_limit = parser->limit; + + /* we store the elements count */ + *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) = + (FT_Byte)num_elements; + + /* we now load each element, adjusting the field.offset on each one */ + token = elements; + for ( ; num_elements > 0; num_elements--, token++ ) + { + parser->cursor = token->start; + parser->limit = token->limit; + ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 ); + fieldrec.offset += fieldrec.size; + } + +#if 0 /* obsolete -- keep for reference */ + if ( pflags ) + *pflags |= 1L << field->flag_bit; +#else + FT_UNUSED( pflags ); +#endif + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Long ) + ps_parser_to_int( PS_Parser parser ) + { + ps_parser_skip_spaces( parser ); + return ps_toint( &parser->cursor, parser->limit ); + } + + + FT_LOCAL_DEF( FT_Error ) + ps_parser_to_bytes( PS_Parser parser, + FT_Byte* bytes, + FT_Long max_bytes, + FT_Long* pnum_bytes, + FT_Bool delimiters ) + { + ps_parser_skip_spaces( parser ); + return ps_tobytes( &parser->cursor, + parser->limit, + max_bytes, + bytes, + pnum_bytes, + delimiters ); + } + + + FT_LOCAL_DEF( FT_Fixed ) + ps_parser_to_fixed( PS_Parser parser, + FT_Int power_ten ) + { + ps_parser_skip_spaces( parser ); + return ps_tofixed( &parser->cursor, parser->limit, power_ten ); + } + + + FT_LOCAL_DEF( FT_Int ) + ps_parser_to_coord_array( PS_Parser parser, + FT_Int max_coords, + FT_Short* coords ) + { + ps_parser_skip_spaces( parser ); + return ps_tocoordarray( &parser->cursor, parser->limit, + max_coords, coords ); + } + + + FT_LOCAL_DEF( FT_Int ) + ps_parser_to_fixed_array( PS_Parser parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ) + { + ps_parser_skip_spaces( parser ); + return ps_tofixedarray( &parser->cursor, parser->limit, + max_values, values, power_ten ); + } + + +#if 0 + + FT_LOCAL_DEF( FT_String* ) + T1_ToString( PS_Parser parser ) + { + return ps_tostring( &parser->cursor, parser->limit, parser->memory ); + } + + + FT_LOCAL_DEF( FT_Bool ) + T1_ToBool( PS_Parser parser ) + { + return ps_tobool( &parser->cursor, parser->limit ); + } + +#endif /* 0 */ + + + FT_LOCAL_DEF( void ) + ps_parser_init( PS_Parser parser, + FT_Byte* base, + FT_Byte* limit, + FT_Memory memory ) + { + parser->error = PSaux_Err_Ok; + parser->base = base; + parser->limit = limit; + parser->cursor = base; + parser->memory = memory; + parser->funcs = ps_parser_funcs; + } + + + FT_LOCAL_DEF( void ) + ps_parser_done( PS_Parser parser ) + { + FT_UNUSED( parser ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Function> */ + /* t1_builder_init */ + /* */ + /* <Description> */ + /* Initializes a given glyph builder. */ + /* */ + /* <InOut> */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + /* hinting :: Whether hinting should be applied. */ + /* */ + FT_LOCAL_DEF( void ) + t1_builder_init( T1_Builder builder, + FT_Face face, + FT_Size size, + FT_GlyphSlot glyph, + FT_Bool hinting ) + { + builder->parse_state = T1_Parse_Start; + builder->load_points = 1; + + builder->face = face; + builder->glyph = glyph; + builder->memory = face->memory; + + if ( glyph ) + { + FT_GlyphLoader loader = glyph->internal->loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + FT_GlyphLoader_Rewind( loader ); + + builder->hints_globals = size->internal; + builder->hints_funcs = 0; + + if ( hinting ) + builder->hints_funcs = glyph->internal->glyph_hints; + } + + if ( size ) + { + builder->scale_x = size->metrics.x_scale; + builder->scale_y = size->metrics.y_scale; + } + + builder->pos_x = 0; + builder->pos_y = 0; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + builder->advance.x = 0; + builder->advance.y = 0; + + builder->funcs = t1_builder_funcs; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* t1_builder_done */ + /* */ + /* <Description> */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* <Input> */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + FT_LOCAL_DEF( void ) + t1_builder_done( T1_Builder builder ) + { + FT_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->outline = *builder->base; + } + + + /* check that there is enough space for `count' more points */ + FT_LOCAL_DEF( FT_Error ) + t1_builder_check_points( T1_Builder builder, + FT_Int count ) + { + return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 ); + } + + + /* add a new point, do not check space */ + FT_LOCAL_DEF( void ) + t1_builder_add_point( T1_Builder builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + + + if ( builder->shift ) + { + x >>= 16; + y >>= 16; + } + point->x = x; + point->y = y; + *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); + + builder->last = *point; + } + outline->n_points++; + } + + + /* check space for a new on-curve point, then add it */ + FT_LOCAL_DEF( FT_Error ) + t1_builder_add_point1( T1_Builder builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error; + + + error = t1_builder_check_points( builder, 1 ); + if ( !error ) + t1_builder_add_point( builder, x, y, 1 ); + + return error; + } + + + /* check space for a new contour, then add it */ + FT_LOCAL_DEF( FT_Error ) + t1_builder_add_contour( T1_Builder builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return PSaux_Err_Ok; + } + + error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + + outline->n_contours++; + } + + return error; + } + + + /* if a path was begun, add its first on-curve point */ + FT_LOCAL_DEF( FT_Error ) + t1_builder_start_point( T1_Builder builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error = PSaux_Err_Invalid_File_Format; + + + /* test whether we are building a new contour */ + + if ( builder->parse_state == T1_Parse_Have_Path ) + error = PSaux_Err_Ok; + else if ( builder->parse_state == T1_Parse_Have_Moveto ) + { + builder->parse_state = T1_Parse_Have_Path; + error = t1_builder_add_contour( builder ); + if ( !error ) + error = t1_builder_add_point1( builder, x, y ); + } + + return error; + } + + + /* close the current contour */ + FT_LOCAL_DEF( void ) + t1_builder_close_contour( T1_Builder builder ) + { + FT_Outline* outline = builder->current; + + + /* XXXX: We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( outline->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + outline->n_points - 1; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + /* `delete' last point only if it coincides with the first */ + /* point and it is not a control point (which can happen). */ + if ( p1->x == p2->x && p1->y == p2->y ) + if ( *control == FT_CURVE_TAG_ON ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = + (short)( outline->n_points - 1 ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** OTHER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL_DEF( void ) + t1_decrypt( FT_Byte* buffer, + FT_Offset length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = (FT_Byte)( *buffer ^ ( seed >> 8 ) ); + seed = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 ); + *buffer++ = plain; + length--; + } + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/psobjs.h b/Utilities/vtkfreetype/src/psaux/psobjs.h new file mode 100644 index 0000000..c2cbf2c --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/psobjs.h @@ -0,0 +1,212 @@ +/***************************************************************************/ +/* */ +/* psobjs.h */ +/* */ +/* Auxiliary functions for PostScript fonts (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSOBJS_H__ +#define __PSOBJS_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_POSTSCRIPT_AUX_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1_TABLE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_CALLBACK_TABLE + const PS_Table_FuncsRec ps_table_funcs; + + FT_CALLBACK_TABLE + const PS_Parser_FuncsRec ps_parser_funcs; + + FT_CALLBACK_TABLE + const T1_Builder_FuncsRec t1_builder_funcs; + + + FT_LOCAL( FT_Error ) + ps_table_new( PS_Table table, + FT_Int count, + FT_Memory memory ); + + FT_LOCAL( FT_Error ) + ps_table_add( PS_Table table, + FT_Int idx, + void* object, + FT_PtrDist length ); + + FT_LOCAL( void ) + ps_table_done( PS_Table table ); + + + FT_LOCAL( void ) + ps_table_release( PS_Table table ); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL( void ) + ps_parser_skip_spaces( PS_Parser parser ); + + FT_LOCAL( void ) + ps_parser_skip_PS_token( PS_Parser parser ); + + FT_LOCAL( void ) + ps_parser_to_token( PS_Parser parser, + T1_Token token ); + + FT_LOCAL( void ) + ps_parser_to_token_array( PS_Parser parser, + T1_Token tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ); + + FT_LOCAL( FT_Error ) + ps_parser_load_field( PS_Parser parser, + const T1_Field field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + FT_LOCAL( FT_Error ) + ps_parser_load_field_table( PS_Parser parser, + const T1_Field field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + FT_LOCAL( FT_Long ) + ps_parser_to_int( PS_Parser parser ); + + + FT_LOCAL( FT_Error ) + ps_parser_to_bytes( PS_Parser parser, + FT_Byte* bytes, + FT_Long max_bytes, + FT_Long* pnum_bytes, + FT_Bool delimiters ); + + + FT_LOCAL( FT_Fixed ) + ps_parser_to_fixed( PS_Parser parser, + FT_Int power_ten ); + + + FT_LOCAL( FT_Int ) + ps_parser_to_coord_array( PS_Parser parser, + FT_Int max_coords, + FT_Short* coords ); + + FT_LOCAL( FT_Int ) + ps_parser_to_fixed_array( PS_Parser parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + + + FT_LOCAL( void ) + ps_parser_init( PS_Parser parser, + FT_Byte* base, + FT_Byte* limit, + FT_Memory memory ); + + FT_LOCAL( void ) + ps_parser_done( PS_Parser parser ); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** T1 BUILDER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL( void ) + t1_builder_init( T1_Builder builder, + FT_Face face, + FT_Size size, + FT_GlyphSlot glyph, + FT_Bool hinting ); + + FT_LOCAL( void ) + t1_builder_done( T1_Builder builder ); + + FT_LOCAL( FT_Error ) + t1_builder_check_points( T1_Builder builder, + FT_Int count ); + + FT_LOCAL( void ) + t1_builder_add_point( T1_Builder builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ); + + FT_LOCAL( FT_Error ) + t1_builder_add_point1( T1_Builder builder, + FT_Pos x, + FT_Pos y ); + + FT_LOCAL( FT_Error ) + t1_builder_add_contour( T1_Builder builder ); + + + FT_LOCAL( FT_Error ) + t1_builder_start_point( T1_Builder builder, + FT_Pos x, + FT_Pos y ); + + + FT_LOCAL( void ) + t1_builder_close_contour( T1_Builder builder ); + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** OTHER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_LOCAL( void ) + t1_decrypt( FT_Byte* buffer, + FT_Offset length, + FT_UShort seed ); + + +FT_END_HEADER + +#endif /* __PSOBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/t1cmap.c b/Utilities/vtkfreetype/src/psaux/t1cmap.c new file mode 100644 index 0000000..dcd99be --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/t1cmap.c @@ -0,0 +1,456 @@ +/***************************************************************************/ +/* */ +/* t1cmap.c */ +/* */ +/* Type 1 character map support (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "t1cmap.h" + +#include FT_INTERNAL_DEBUG_H + +#include "psauxerr.h" + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + t1_cmap_std_init( T1_CMapStd cmap, + FT_Int is_expert ) + { + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + cmap->num_glyphs = face->type1.num_glyphs; + cmap->glyph_names = (const char* const*)face->type1.glyph_names; + cmap->sid_to_string = psnames->adobe_std_strings; + cmap->code_to_sid = is_expert ? psnames->adobe_expert_encoding + : psnames->adobe_std_encoding; + + FT_ASSERT( cmap->code_to_sid != NULL ); + } + + + FT_CALLBACK_DEF( void ) + t1_cmap_std_done( T1_CMapStd cmap ) + { + cmap->num_glyphs = 0; + cmap->glyph_names = NULL; + cmap->sid_to_string = NULL; + cmap->code_to_sid = NULL; + } + + + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_std_char_index( T1_CMapStd cmap, + FT_UInt32 char_code ) + { + FT_UInt result = 0; + + + if ( char_code < 256 ) + { + FT_UInt code, n; + const char* glyph_name; + + + /* convert character code to Adobe SID string */ + code = cmap->code_to_sid[char_code]; + glyph_name = cmap->sid_to_string( code ); + + /* look for the corresponding glyph name */ + for ( n = 0; n < cmap->num_glyphs; n++ ) + { + const char* gname = cmap->glyph_names[n]; + + + if ( gname && gname[0] == glyph_name[0] && + ft_strcmp( gname, glyph_name ) == 0 ) + { + result = n; + break; + } + } + } + + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_std_char_next( T1_CMapStd cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code + 1; + + + while ( char_code < 256 ) + { + result = t1_cmap_std_char_index( cmap, char_code ); + if ( result != 0 ) + goto Exit; + + char_code++; + } + char_code = 0; + + Exit: + *pchar_code = char_code; + return result; + } + + + FT_CALLBACK_DEF( FT_Error ) + t1_cmap_standard_init( T1_CMapStd cmap ) + { + t1_cmap_std_init( cmap, 0 ); + return 0; + } + + + FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec + t1_cmap_standard_class_rec = + { + sizeof ( T1_CMapStdRec ), + + (FT_CMap_InitFunc) t1_cmap_standard_init, + (FT_CMap_DoneFunc) t1_cmap_std_done, + (FT_CMap_CharIndexFunc)t1_cmap_std_char_index, + (FT_CMap_CharNextFunc) t1_cmap_std_char_next + }; + + + FT_CALLBACK_DEF( FT_Error ) + t1_cmap_expert_init( T1_CMapStd cmap ) + { + t1_cmap_std_init( cmap, 1 ); + return 0; + } + + FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec + t1_cmap_expert_class_rec = + { + sizeof ( T1_CMapStdRec ), + + (FT_CMap_InitFunc) t1_cmap_expert_init, + (FT_CMap_DoneFunc) t1_cmap_std_done, + (FT_CMap_CharIndexFunc)t1_cmap_std_char_index, + (FT_CMap_CharNextFunc) t1_cmap_std_char_next + }; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 CUSTOM ENCODING CMAP *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_CALLBACK_DEF( FT_Error ) + t1_cmap_custom_init( T1_CMapCustom cmap ) + { + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + T1_Encoding encoding = &face->type1.encoding; + + + cmap->first = encoding->code_first; + cmap->count = (FT_UInt)( encoding->code_last - cmap->first + 1 ); + cmap->indices = encoding->char_index; + + FT_ASSERT( cmap->indices != NULL ); + FT_ASSERT( encoding->code_first <= encoding->code_last ); + + return 0; + } + + + FT_CALLBACK_DEF( void ) + t1_cmap_custom_done( T1_CMapCustom cmap ) + { + cmap->indices = NULL; + cmap->first = 0; + cmap->count = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_custom_char_index( T1_CMapCustom cmap, + FT_UInt32 char_code ) + { + FT_UInt result = 0; + + + if ( ( char_code >= cmap->first ) && + ( char_code < ( cmap->first + cmap->count ) ) ) + result = cmap->indices[char_code]; + + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_custom_char_next( T1_CMapCustom cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code; + + + ++char_code; + + if ( char_code < cmap->first ) + char_code = cmap->first; + + for ( ; char_code < ( cmap->first + cmap->count ); char_code++ ) + { + result = cmap->indices[char_code]; + if ( result != 0 ) + goto Exit; + } + + char_code = 0; + + Exit: + *pchar_code = char_code; + return result; + } + + + FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec + t1_cmap_custom_class_rec = + { + sizeof ( T1_CMapCustomRec ), + + (FT_CMap_InitFunc) t1_cmap_custom_init, + (FT_CMap_DoneFunc) t1_cmap_custom_done, + (FT_CMap_CharIndexFunc)t1_cmap_custom_char_index, + (FT_CMap_CharNextFunc) t1_cmap_custom_char_next + }; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_CALLBACK_DEF( FT_Int ) + t1_cmap_uni_pair_compare( const void* pair1, + const void* pair2 ) + { + FT_UInt32 u1 = ((T1_CMapUniPair)pair1)->unicode; + FT_UInt32 u2 = ((T1_CMapUniPair)pair2)->unicode; + + + if ( u1 < u2 ) + return -1; + + if ( u1 > u2 ) + return +1; + + return 0; + } + + + FT_CALLBACK_DEF( FT_Error ) + t1_cmap_unicode_init( T1_CMapUnicode cmap ) + { + FT_Error error; + FT_UInt count; + T1_Face face = (T1_Face)FT_CMAP_FACE( cmap ); + FT_Memory memory = FT_FACE_MEMORY( face ); + FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; + + + cmap->num_pairs = 0; + cmap->pairs = NULL; + + count = face->type1.num_glyphs; + + if ( !FT_NEW_ARRAY( cmap->pairs, count ) ) + { + FT_UInt n, new_count; + T1_CMapUniPair pair; + FT_UInt32 uni_code; + + + pair = cmap->pairs; + for ( n = 0; n < count; n++ ) + { + const char* gname = face->type1.glyph_names[n]; + + + /* build unsorted pair table by matching glyph names */ + if ( gname ) + { + uni_code = psnames->unicode_value( gname ); + + if ( uni_code != 0 ) + { + pair->unicode = uni_code; + pair->gindex = n; + pair++; + } + } + } + + new_count = (FT_UInt)( pair - cmap->pairs ); + if ( new_count == 0 ) + { + /* there are no unicode characters in here! */ + FT_FREE( cmap->pairs ); + error = PSaux_Err_Invalid_Argument; + } + else + { + /* re-allocate if the new array is much smaller than the original */ + /* one */ + if ( new_count != count && new_count < count / 2 ) + { + (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count ); + error = 0; + } + + /* sort the pairs table to allow efficient binary searches */ + ft_qsort( cmap->pairs, + new_count, + sizeof ( T1_CMapUniPairRec ), + t1_cmap_uni_pair_compare ); + + cmap->num_pairs = new_count; + } + } + + return error; + } + + + FT_CALLBACK_DEF( void ) + t1_cmap_unicode_done( T1_CMapUnicode cmap ) + { + FT_Face face = FT_CMAP_FACE(cmap); + FT_Memory memory = FT_FACE_MEMORY(face); + + FT_FREE( cmap->pairs ); + cmap->num_pairs = 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_unicode_char_index( T1_CMapUnicode cmap, + FT_UInt32 char_code ) + { + FT_UInt min = 0; + FT_UInt max = cmap->num_pairs; + FT_UInt mid; + T1_CMapUniPair pair; + + + while ( min < max ) + { + mid = min + ( max - min ) / 2; + pair = cmap->pairs + mid; + + if ( pair->unicode == char_code ) + return pair->gindex; + + if ( pair->unicode < char_code ) + min = mid + 1; + else + max = mid; + } + return 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + t1_cmap_unicode_char_next( T1_CMapUnicode cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt result = 0; + FT_UInt32 char_code = *pchar_code + 1; + + + Restart: + { + FT_UInt min = 0; + FT_UInt max = cmap->num_pairs; + FT_UInt mid; + T1_CMapUniPair pair; + + + while ( min < max ) + { + mid = min + ( ( max - min ) >> 1 ); + pair = cmap->pairs + mid; + + if ( pair->unicode == char_code ) + { + result = pair->gindex; + if ( result != 0 ) + goto Exit; + + char_code++; + goto Restart; + } + + if ( pair->unicode < char_code ) + min = mid+1; + else + max = mid; + } + + /* we didn't find it, but we have a pair just above it */ + char_code = 0; + + if ( min < cmap->num_pairs ) + { + pair = cmap->pairs + min; + result = pair->gindex; + if ( result != 0 ) + char_code = pair->unicode; + } + } + + Exit: + *pchar_code = char_code; + return result; + } + + + FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec + t1_cmap_unicode_class_rec = + { + sizeof ( T1_CMapUnicodeRec ), + + (FT_CMap_InitFunc) t1_cmap_unicode_init, + (FT_CMap_DoneFunc) t1_cmap_unicode_done, + (FT_CMap_CharIndexFunc)t1_cmap_unicode_char_index, + (FT_CMap_CharNextFunc) t1_cmap_unicode_char_next + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/t1cmap.h b/Utilities/vtkfreetype/src/psaux/t1cmap.h new file mode 100644 index 0000000..aa93d74 --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/t1cmap.h @@ -0,0 +1,123 @@ +/***************************************************************************/ +/* */ +/* t1cmap.h */ +/* */ +/* Type 1 character map support (specification). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1CMAP_H__ +#define __T1CMAP_H__ + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_TYPE1_TYPES_H + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 STANDARD (AND EXPERT) ENCODING CMAPS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* standard (and expert) encoding cmaps */ + typedef struct T1_CMapStdRec_* T1_CMapStd; + + typedef struct T1_CMapStdRec_ + { + FT_CMapRec cmap; + + const FT_UShort* code_to_sid; + PS_Adobe_Std_Strings_Func sid_to_string; + + FT_UInt num_glyphs; + const char* const* glyph_names; + + } T1_CMapStdRec; + + + FT_CALLBACK_TABLE const FT_CMap_ClassRec + t1_cmap_standard_class_rec; + + FT_CALLBACK_TABLE const FT_CMap_ClassRec + t1_cmap_expert_class_rec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 CUSTOM ENCODING CMAP *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + typedef struct T1_CMapCustomRec_* T1_CMapCustom; + + typedef struct T1_CMapCustomRec_ + { + FT_CMapRec cmap; + FT_UInt first; + FT_UInt count; + FT_UShort* indices; + + } T1_CMapCustomRec; + + + FT_CALLBACK_TABLE const FT_CMap_ClassRec + t1_cmap_custom_class_rec; + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE1 SYNTHETIC UNICODE ENCODING CMAP *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* unicode (syntehtic) cmaps */ + typedef struct T1_CMapUnicodeRec_* T1_CMapUnicode; + + typedef struct T1_CMapUniPairRec_ + { + FT_UInt32 unicode; + FT_UInt gindex; + + } T1_CMapUniPairRec, *T1_CMapUniPair; + + + typedef struct T1_CMapUnicodeRec_ + { + FT_CMapRec cmap; + FT_UInt num_pairs; + T1_CMapUniPair pairs; + + } T1_CMapUnicodeRec; + + + FT_CALLBACK_TABLE const FT_CMap_ClassRec + t1_cmap_unicode_class_rec; + + /* */ + + +FT_END_HEADER + +#endif /* __T1CMAP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/t1decode.c b/Utilities/vtkfreetype/src/psaux/t1decode.c new file mode 100644 index 0000000..c2adf48 --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/t1decode.c @@ -0,0 +1,1165 @@ +/***************************************************************************/ +/* */ +/* t1decode.c */ +/* */ +/* PostScript Type 1 decoding routines (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H +#include FT_OUTLINE_H + +#include "t1decode.h" +#include "psobjs.h" + +#include "psauxerr.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1decode + + + typedef enum T1_Operator_ + { + op_none = 0, + op_endchar, + op_hsbw, + op_seac, + op_sbw, + op_closepath, + op_hlineto, + op_hmoveto, + op_hvcurveto, + op_rlineto, + op_rmoveto, + op_rrcurveto, + op_vhcurveto, + op_vlineto, + op_vmoveto, + op_dotsection, + op_hstem, + op_hstem3, + op_vstem, + op_vstem3, + op_div, + op_callothersubr, + op_callsubr, + op_pop, + op_return, + op_setcurrentpoint, + + op_max /* never remove this one */ + + } T1_Operator; + + + static + const FT_Int t1_args_count[op_max] = + { + 0, /* none */ + 0, /* endchar */ + 2, /* hsbw */ + 5, /* seac */ + 4, /* sbw */ + 0, /* closepath */ + 1, /* hlineto */ + 1, /* hmoveto */ + 4, /* hvcurveto */ + 2, /* rlineto */ + 2, /* rmoveto */ + 6, /* rrcurveto */ + 4, /* vhcurveto */ + 1, /* vlineto */ + 1, /* vmoveto */ + 0, /* dotsection */ + 2, /* hstem */ + 6, /* hstem3 */ + 2, /* vstem */ + 6, /* vstem3 */ + 2, /* div */ + -1, /* callothersubr */ + 1, /* callsubr */ + 0, /* pop */ + 0, /* return */ + 2 /* setcurrentpoint */ + }; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* t1_lookup_glyph_by_stdcharcode */ + /* */ + /* <Description> */ + /* Looks up a given glyph by its StandardEncoding charcode. Used to */ + /* implement the SEAC Type 1 operator. */ + /* */ + /* <Input> */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* <Return> */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static FT_Int + t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder, + FT_Int charcode ) + { + FT_UInt n; + const FT_String* glyph_name; + FT_Service_PsCMaps psnames = decoder->psnames; + + + /* check range of standard char code */ + if ( charcode < 0 || charcode > 255 ) + return -1; + + glyph_name = psnames->adobe_std_strings( + psnames->adobe_std_encoding[charcode]); + + for ( n = 0; n < decoder->num_glyphs; n++ ) + { + FT_String* name = (FT_String*)decoder->glyph_names[n]; + + + if ( name && name[0] == glyph_name[0] && + ft_strcmp( name, glyph_name ) == 0 ) + return n; + } + + return -1; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* t1operator_seac */ + /* */ + /* <Description> */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* <Input> */ + /* decoder :: The current CID decoder. */ + /* */ + /* asb :: The accent's side bearing. */ + /* */ + /* adx :: The horizontal offset of the accent. */ + /* */ + /* ady :: The vertical offset of the accent. */ + /* */ + /* bchar :: The base character's StandardEncoding charcode. */ + /* */ + /* achar :: The accent character's StandardEncoding charcode. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + t1operator_seac( T1_Decoder decoder, + FT_Pos asb, + FT_Pos adx, + FT_Pos ady, + FT_Int bchar, + FT_Int achar ) + { + FT_Error error; + FT_Int bchar_index, achar_index; +#if 0 + FT_Int n_base_points; + FT_Outline* base = decoder->builder.base; +#endif + FT_Vector left_bearing, advance; + + + /* seac weirdness */ + adx += decoder->builder.left_bearing.x; + + /* `glyph_names' is set to 0 for CID fonts which do not */ + /* include an encoding. How can we deal with these? */ + if ( decoder->glyph_names == 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " glyph names table not available in this font!\n" )); + return PSaux_Err_Syntax_Error; + } + + bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); + achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return PSaux_Err_Syntax_Error; + } + + /* if we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if ( decoder->builder.no_recurse ) + { + FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; + FT_GlyphLoader loader = glyph->internal->loader; + FT_SubGlyph subg; + + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); + if ( error ) + goto Exit; + + subg = loader->current.subglyphs; + + /* subglyph 0 = base character */ + subg->index = bchar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | + FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg->arg1 = 0; + subg->arg2 = 0; + subg++; + + /* subglyph 1 = accent character */ + subg->index = achar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg->arg1 = (FT_Int)( adx - asb ); + subg->arg2 = (FT_Int)ady; + + /* set up remaining glyph fields */ + glyph->num_subglyphs = 2; + glyph->subglyphs = loader->base.subglyphs; + glyph->format = FT_GLYPH_FORMAT_COMPOSITE; + + loader->current.num_subglyphs = 2; + goto Exit; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + + FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ + + error = t1_decoder_parse_glyph( decoder, bchar_index ); + if ( error ) + goto Exit; + + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load. */ + + left_bearing = decoder->builder.left_bearing; + advance = decoder->builder.advance; + + decoder->builder.left_bearing.x = 0; + decoder->builder.left_bearing.y = 0; + + decoder->builder.pos_x = adx - asb; + decoder->builder.pos_y = ady; + + /* Now load `achar' on top of */ + /* the base outline */ + error = t1_decoder_parse_glyph( decoder, achar_index ); + if ( error ) + goto Exit; + + /* restore the left side bearing and */ + /* advance width of the base character */ + + decoder->builder.left_bearing = left_bearing; + decoder->builder.advance = advance; + + decoder->builder.pos_x = 0; + decoder->builder.pos_y = 0; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* t1_decoder_parse_charstrings */ + /* */ + /* <Description> */ + /* Parses a given Type 1 charstrings program. */ + /* */ + /* <Input> */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* charstring_base :: The base address of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + t1_decoder_parse_charstrings( T1_Decoder decoder, + FT_Byte* charstring_base, + FT_UInt charstring_len ) + { + FT_Error error; + T1_Decoder_Zone zone; + FT_Byte* ip; + FT_Byte* limit; + T1_Builder builder = &decoder->builder; + FT_Pos x, y, orig_x, orig_y; + + T1_Hints_Funcs hinter; + + + /* we don't want to touch the source code -- use macro trick */ +#define start_point t1_builder_start_point +#define check_points t1_builder_check_points +#define add_point t1_builder_add_point +#define add_point1 t1_builder_add_point1 +#define add_contour t1_builder_add_contour +#define close_contour t1_builder_close_contour + + /* First of all, initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + + builder->parse_state = T1_Parse_Start; + + hinter = (T1_Hints_Funcs)builder->hints_funcs; + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + error = PSaux_Err_Ok; + + x = orig_x = builder->pos_x; + y = orig_y = builder->pos_y; + + /* begin hints recording session, if any */ + if ( hinter ) + hinter->open( hinter->hints ); + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Long* top = decoder->top; + T1_Operator op = op_none; + FT_Long value = 0; + + + /*********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + /* */ + + /* first of all, decompress operator or value */ + switch ( *ip++ ) + { + case 1: + op = op_hstem; + break; + + case 3: + op = op_vstem; + break; + case 4: + op = op_vmoveto; + break; + case 5: + op = op_rlineto; + break; + case 6: + op = op_hlineto; + break; + case 7: + op = op_vlineto; + break; + case 8: + op = op_rrcurveto; + break; + case 9: + op = op_closepath; + break; + case 10: + op = op_callsubr; + break; + case 11: + op = op_return; + break; + + case 13: + op = op_hsbw; + break; + case 14: + op = op_endchar; + break; + + case 15: /* undocumented, obsolete operator */ + op = op_none; + break; + + case 21: + op = op_rmoveto; + break; + case 22: + op = op_hmoveto; + break; + + case 30: + op = op_vhcurveto; + break; + case 31: + op = op_hvcurveto; + break; + + case 12: + if ( ip > limit ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invalid escape (12+EOF)\n" )); + goto Syntax_Error; + } + + switch ( *ip++ ) + { + case 0: + op = op_dotsection; + break; + case 1: + op = op_vstem3; + break; + case 2: + op = op_hstem3; + break; + case 6: + op = op_seac; + break; + case 7: + op = op_sbw; + break; + case 12: + op = op_div; + break; + case 16: + op = op_callothersubr; + break; + case 17: + op = op_pop; + break; + case 33: + op = op_setcurrentpoint; + break; + + default: + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = (FT_Int32)( ((FT_Long)ip[0] << 24) | + ((FT_Long)ip[1] << 16) | + ((FT_Long)ip[2] << 8 ) | + ip[3] ); + ip += 4; + break; + + default: + if ( ip[-1] >= 32 ) + { + if ( ip[-1] < 247 ) + value = (FT_Long)ip[-1] - 139; + else + { + if ( ++ip > limit ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " )); + FT_ERROR(( "unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if ( ip[-2] < 251 ) + value = ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108; + else + value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); + } + } + else + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invalid byte (%d)\n", ip[-1] )); + goto Syntax_Error; + } + } + + /*********************************************************************/ + /* */ + /* Push value on stack, or process operator */ + /* */ + /* */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow!\n" )); + goto Syntax_Error; + } + + FT_TRACE4(( " %ld", value )); + + *top++ = value; + decoder->top = top; + } + else if ( op == op_callothersubr ) /* callothersubr */ + { + FT_TRACE4(( " callothersubr" )); + + if ( top - decoder->stack < 2 ) + goto Stack_Underflow; + + top -= 2; + switch ( (FT_Int)top[1] ) + { + case 1: /* start flex feature */ + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + decoder->flex_state = 1; + decoder->num_flex_vectors = 0; + if ( start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Fail; + break; + + case 2: /* add flex vectors */ + { + FT_Int idx; + + + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + /* note that we should not add a point for index 0; */ + /* this will move our current position to the flex */ + /* point without adding any point to the outline */ + idx = decoder->num_flex_vectors++; + if ( idx > 0 && idx < 7 ) + add_point( builder, + x, + y, + (FT_Byte)( idx == 3 || idx == 6 ) ); + } + break; + + case 0: /* end flex feature */ + if ( top[0] != 3 ) + goto Unexpected_OtherSubr; + + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "unexpected flex end\n" )); + goto Syntax_Error; + } + + /* now consume the remaining `pop pop setcurpoint' */ + if ( ip + 6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */ + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invalid flex charstring\n" )); + goto Syntax_Error; + } + + ip += 6; + decoder->flex_state = 0; + break; + + case 3: /* change hints */ + if ( top[0] != 1 ) + goto Unexpected_OtherSubr; + + /* eat the following `pop' */ + if ( ip + 2 > limit ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invalid escape (12+%d)\n", ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " )); + FT_ERROR(( "`pop' expected, found (%d %d)\n", ip[0], ip[1] )); + goto Syntax_Error; + } + ip += 2; + + if ( hinter ) + hinter->reset( hinter->hints, builder->current->n_points ); + + break; + + case 12: + case 13: + /* counter control hints, clear stack */ + top = decoder->stack; + break; + + case 14: + case 15: + case 16: + case 17: + case 18: /* multiple masters */ + { + PS_Blend blend = decoder->blend; + FT_UInt num_points, nn, mm; + FT_Long* delta; + FT_Long* values; + + + if ( !blend ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " )); + FT_ERROR(( "unexpected multiple masters operator!\n" )); + goto Syntax_Error; + } + + num_points = (FT_UInt)top[1] - 13 + ( top[1] == 18 ); + if ( top[0] != (FT_Int)( num_points * blend->num_designs ) ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " )); + FT_ERROR(( "incorrect number of mm arguments\n" )); + goto Syntax_Error; + } + + top -= blend->num_designs * num_points; + if ( top < decoder->stack ) + goto Stack_Underflow; + + /* we want to compute: */ + /* */ + /* a0*w0 + a1*w1 + ... + ak*wk */ + /* */ + /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */ + /* however, given that w0 + w1 + ... + wk == 1, we can */ + /* rewrite it easily as: */ + /* */ + /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */ + /* */ + /* where k == num_designs-1 */ + /* */ + /* I guess that's why it's written in this `compact' */ + /* form. */ + /* */ + delta = top + num_points; + values = top; + for ( nn = 0; nn < num_points; nn++ ) + { + FT_Long tmp = values[0]; + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); + + *values++ = tmp; + } + /* note that `top' will be incremented later by calls to `pop' */ + break; + } + + default: + Unexpected_OtherSubr: + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invalid othersubr [%d %d]!\n", top[0], top[1] )); + goto Syntax_Error; + } + decoder->top = top; + } + else /* general operator */ + { + FT_Int num_args = t1_args_count[op]; + + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + + top -= num_args; + + switch ( op ) + { + case op_endchar: + FT_TRACE4(( " endchar" )); + + close_contour( builder ); + + /* close hints recording session */ + if ( hinter ) + { + if (hinter->close( hinter->hints, builder->current->n_points )) + goto Syntax_Error; + + /* apply hints to the loaded glyph outline now */ + hinter->apply( hinter->hints, + builder->current, + (PSH_Globals) builder->hints_globals, + decoder->hint_mode ); + } + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add( builder->loader ); + + /* return now! */ + FT_TRACE4(( "\n\n" )); + return PSaux_Err_Ok; + + case op_hsbw: + FT_TRACE4(( " hsbw" )); + + builder->parse_state = T1_Parse_Have_Width; + + builder->left_bearing.x += top[0]; + builder->advance.x = top[1]; + builder->advance.y = 0; + + orig_x = builder->last.x = x = builder->pos_x + top[0]; + orig_y = builder->last.y = y = builder->pos_y; + + FT_UNUSED( orig_y ); + + /* the `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it; so exit immediately */ + if ( builder->metrics_only ) + return PSaux_Err_Ok; + + break; + + case op_seac: + /* return immediately after the processing */ + return t1operator_seac( decoder, top[0], top[1], top[2], + (FT_Int)top[3], (FT_Int)top[4] ); + + case op_sbw: + FT_TRACE4(( " sbw" )); + + builder->parse_state = T1_Parse_Have_Width; + + builder->left_bearing.x += top[0]; + builder->left_bearing.y += top[1]; + builder->advance.x = top[2]; + builder->advance.y = top[3]; + + builder->last.x = x = builder->pos_x + top[0]; + builder->last.y = y = builder->pos_y + top[1]; + + /* the `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it; so exit immediately */ + if ( builder->metrics_only ) + return PSaux_Err_Ok; + + break; + + case op_closepath: + FT_TRACE4(( " closepath" )); + + close_contour( builder ); + if ( builder->parse_state != T1_Parse_Have_Path ) + goto Syntax_Error; + builder->parse_state = T1_Parse_Have_Width; + break; + + case op_hlineto: + FT_TRACE4(( " hlineto" )); + + if ( start_point( builder, x, y ) ) + goto Fail; + + x += top[0]; + goto Add_Line; + + case op_hmoveto: + FT_TRACE4(( " hmoveto" )); + + x += top[0]; + if ( !decoder->flex_state ) + { + if ( builder->parse_state == T1_Parse_Start ) + goto Syntax_Error; + builder->parse_state = T1_Parse_Have_Moveto; + } + break; + + case op_hvcurveto: + FT_TRACE4(( " hvcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Fail; + + x += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + y += top[3]; + add_point( builder, x, y, 1 ); + break; + + case op_rlineto: + FT_TRACE4(( " rlineto" )); + + if ( start_point( builder, x, y ) ) + goto Fail; + + x += top[0]; + y += top[1]; + + Add_Line: + if ( add_point1( builder, x, y ) ) + goto Fail; + break; + + case op_rmoveto: + FT_TRACE4(( " rmoveto" )); + + x += top[0]; + y += top[1]; + if ( !decoder->flex_state ) + { + if ( builder->parse_state == T1_Parse_Start ) + goto Syntax_Error; + builder->parse_state = T1_Parse_Have_Moveto; + } + break; + + case op_rrcurveto: + FT_TRACE4(( " rcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Fail; + + x += top[0]; + y += top[1]; + add_point( builder, x, y, 0 ); + + x += top[2]; + y += top[3]; + add_point( builder, x, y, 0 ); + + x += top[4]; + y += top[5]; + add_point( builder, x, y, 1 ); + break; + + case op_vhcurveto: + FT_TRACE4(( " vhcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Fail; + + y += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + x += top[3]; + add_point( builder, x, y, 1 ); + break; + + case op_vlineto: + FT_TRACE4(( " vlineto" )); + + if ( start_point( builder, x, y ) ) + goto Fail; + + y += top[0]; + goto Add_Line; + + case op_vmoveto: + FT_TRACE4(( " vmoveto" )); + + y += top[0]; + if ( !decoder->flex_state ) + { + if ( builder->parse_state == T1_Parse_Start ) + goto Syntax_Error; + builder->parse_state = T1_Parse_Have_Moveto; + } + break; + + case op_div: + FT_TRACE4(( " div" )); + + if ( top[1] ) + { + *top = top[0] / top[1]; + ++top; + } + else + { + FT_ERROR(( "t1_decoder_parse_charstrings: division by 0\n" )); + goto Syntax_Error; + } + break; + + case op_callsubr: + { + FT_Int idx; + + + FT_TRACE4(( " callsubr" )); + + idx = (FT_Int)top[0]; + if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + + /* The Type 1 driver stores subroutines without the seed bytes. */ + /* The CID driver stores subroutines with seed bytes. This */ + /* case is taken care of when decoder->subrs_len == 0. */ + zone->base = decoder->subrs[idx]; + + if ( decoder->subrs_len ) + zone->limit = zone->base + decoder->subrs_len[idx]; + else + { + /* We are using subroutines from a CID font. We must adjust */ + /* for the seed bytes. */ + zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); + zone->limit = decoder->subrs[idx + 1]; + } + + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: " + "invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + break; + } + + case op_pop: + FT_TRACE4(( " pop" )); + + /* theoretically, the arguments are already on the stack */ + top++; + break; + + case op_return: + FT_TRACE4(( " return" )); + + if ( zone <= decoder->zones ) + { + FT_ERROR(( "t1_decoder_parse_charstrings: unexpected return\n" )); + goto Syntax_Error; + } + + zone--; + ip = zone->cursor; + limit = zone->limit; + decoder->zone = zone; + break; + + case op_dotsection: + FT_TRACE4(( " dotsection" )); + + break; + + case op_hstem: + FT_TRACE4(( " hstem" )); + + /* record horizontal hint */ + if ( hinter ) + { + /* top[0] += builder->left_bearing.y; */ + hinter->stem( hinter->hints, 1, top ); + } + + break; + + case op_hstem3: + FT_TRACE4(( " hstem3" )); + + /* record horizontal counter-controlled hints */ + if ( hinter ) + hinter->stem3( hinter->hints, 1, top ); + + break; + + case op_vstem: + FT_TRACE4(( " vstem" )); + + /* record vertical hint */ + if ( hinter ) + { + top[0] += orig_x; + hinter->stem( hinter->hints, 0, top ); + } + + break; + + case op_vstem3: + FT_TRACE4(( " vstem3" )); + + /* record vertical counter-controlled hints */ + if ( hinter ) + { + FT_Pos dx = orig_x; + + + top[0] += dx; + top[2] += dx; + top[4] += dx; + hinter->stem3( hinter->hints, 0, top ); + } + break; + + case op_setcurrentpoint: + FT_TRACE4(( " setcurrentpoint" )); + + FT_ERROR(( "t1_decoder_parse_charstrings: " )); + FT_ERROR(( "unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + + default: + FT_ERROR(( "t1_decoder_parse_charstrings: " + "unhandled opcode %d\n", op )); + goto Syntax_Error; + } + + decoder->top = top; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + Fail: + return error; + + Syntax_Error: + return PSaux_Err_Syntax_Error; + + Stack_Underflow: + return PSaux_Err_Stack_Underflow; + } + + + /* parse a single Type 1 glyph */ + FT_LOCAL_DEF( FT_Error ) + t1_decoder_parse_glyph( T1_Decoder decoder, + FT_UInt glyph ) + { + return decoder->parse_callback( decoder, glyph ); + } + + + /* initialize T1 decoder */ + FT_LOCAL_DEF( FT_Error ) + t1_decoder_init( T1_Decoder decoder, + FT_Face face, + FT_Size size, + FT_GlyphSlot slot, + FT_Byte** glyph_names, + PS_Blend blend, + FT_Bool hinting, + FT_Render_Mode hint_mode, + T1_Decoder_Callback parse_callback ) + { + FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); + + /* retrieve PSNames interface from list of current modules */ + { + FT_Service_PsCMaps psnames = 0; + + + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); + if ( !psnames ) + { + FT_ERROR(( "t1_decoder_init: " )); + FT_ERROR(( "the `psnames' module is not available\n" )); + return PSaux_Err_Unimplemented_Feature; + } + + decoder->psnames = psnames; + } + + t1_builder_init( &decoder->builder, face, size, slot, hinting ); + + decoder->num_glyphs = (FT_UInt)face->num_glyphs; + decoder->glyph_names = glyph_names; + decoder->hint_mode = hint_mode; + decoder->blend = blend; + decoder->parse_callback = parse_callback; + + decoder->funcs = t1_decoder_funcs; + + return 0; + } + + + /* finalize T1 decoder */ + FT_LOCAL_DEF( void ) + t1_decoder_done( T1_Decoder decoder ) + { + t1_builder_done( &decoder->builder ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psaux/t1decode.h b/Utilities/vtkfreetype/src/psaux/t1decode.h new file mode 100644 index 0000000..00728db --- /dev/null +++ b/Utilities/vtkfreetype/src/psaux/t1decode.h @@ -0,0 +1,64 @@ +/***************************************************************************/ +/* */ +/* t1decode.h */ +/* */ +/* PostScript Type 1 decoding routines (specification). */ +/* */ +/* Copyright 2000-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1DECODE_H__ +#define __T1DECODE_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_INTERNAL_TYPE1_TYPES_H + + +FT_BEGIN_HEADER + + + FT_CALLBACK_TABLE + const T1_Decoder_FuncsRec t1_decoder_funcs; + + + FT_LOCAL( FT_Error ) + t1_decoder_parse_glyph( T1_Decoder decoder, + FT_UInt glyph_index ); + + FT_LOCAL( FT_Error ) + t1_decoder_parse_charstrings( T1_Decoder decoder, + FT_Byte* base, + FT_UInt len ); + + FT_LOCAL( FT_Error ) + t1_decoder_init( T1_Decoder decoder, + FT_Face face, + FT_Size size, + FT_GlyphSlot slot, + FT_Byte** glyph_names, + PS_Blend blend, + FT_Bool hinting, + FT_Render_Mode hint_mode, + T1_Decoder_Callback parse_glyph ); + + FT_LOCAL( void ) + t1_decoder_done( T1_Decoder decoder ); + + +FT_END_HEADER + +#endif /* __T1DECODE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshalgo.c b/Utilities/vtkfreetype/src/pshinter/pshalgo.c new file mode 100644 index 0000000..5f077d5 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshalgo.c @@ -0,0 +1,2091 @@ +/***************************************************************************/ +/* */ +/* pshalgo.c */ +/* */ +/* PostScript hinting algorithm (body). */ +/* */ +/* Copyright 2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include "pshalgo.h" + +#include "pshnterr.h" + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pshalgo2 + + +#ifdef DEBUG_HINTER + PSH_Hint_Table ps_debug_hint_table = 0; + PSH_HintFunc ps_debug_hint_func = 0; + PSH_Glyph ps_debug_glyph = 0; +#endif + + +#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */ + /* and similar glyphs */ +#define STRONGER /* slightly increase the contrast of smooth */ + /* hinting */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BASIC HINTS RECORDINGS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* return true if two stem hints overlap */ + static FT_Int + psh_hint_overlap( PSH_Hint hint1, + PSH_Hint hint2 ) + { + return hint1->org_pos + hint1->org_len >= hint2->org_pos && + hint2->org_pos + hint2->org_len >= hint1->org_pos; + } + + + /* destroy hints table */ + static void + psh_hint_table_done( PSH_Hint_Table table, + FT_Memory memory ) + { + FT_FREE( table->zones ); + table->num_zones = 0; + table->zone = 0; + + FT_FREE( table->sort ); + FT_FREE( table->hints ); + table->num_hints = 0; + table->max_hints = 0; + table->sort_global = 0; + } + + + /* deactivate all hints in a table */ + static void + psh_hint_table_deactivate( PSH_Hint_Table table ) + { + FT_UInt count = table->max_hints; + PSH_Hint hint = table->hints; + + + for ( ; count > 0; count--, hint++ ) + { + psh_hint_deactivate( hint ); + hint->order = -1; + } + } + + + /* internal function to record a new hint */ + static void + psh_hint_table_record( PSH_Hint_Table table, + FT_UInt idx ) + { + PSH_Hint hint = table->hints + idx; + + + if ( idx >= table->max_hints ) + { + FT_ERROR(( "psh_hint_table_record: invalid hint index %d\n", idx )); + return; + } + + /* ignore active hints */ + if ( psh_hint_is_active( hint ) ) + return; + + psh_hint_activate( hint ); + + /* now scan the current active hint set to check */ + /* whether `hint' overlaps with another hint */ + { + PSH_Hint* sorted = table->sort_global; + FT_UInt count = table->num_hints; + PSH_Hint hint2; + + + hint->parent = 0; + for ( ; count > 0; count--, sorted++ ) + { + hint2 = sorted[0]; + + if ( psh_hint_overlap( hint, hint2 ) ) + { + hint->parent = hint2; + break; + } + } + } + + if ( table->num_hints < table->max_hints ) + table->sort_global[table->num_hints++] = hint; + else + FT_ERROR(( "psh_hint_table_record: too many sorted hints! BUG!\n" )); + } + + + static void + psh_hint_table_record_mask( PSH_Hint_Table table, + PS_Mask hint_mask ) + { + FT_Int mask = 0, val = 0; + FT_Byte* cursor = hint_mask->bytes; + FT_UInt idx, limit; + + + limit = hint_mask->num_bits; + + for ( idx = 0; idx < limit; idx++ ) + { + if ( mask == 0 ) + { + val = *cursor++; + mask = 0x80; + } + + if ( val & mask ) + psh_hint_table_record( table, idx ); + + mask >>= 1; + } + } + + + /* create hints table */ + static FT_Error + psh_hint_table_init( PSH_Hint_Table table, + PS_Hint_Table hints, + PS_Mask_Table hint_masks, + PS_Mask_Table counter_masks, + FT_Memory memory ) + { + FT_UInt count; + FT_Error error; + + FT_UNUSED( counter_masks ); + + + count = hints->num_hints; + + /* allocate our tables */ + if ( FT_NEW_ARRAY( table->sort, 2 * count ) || + FT_NEW_ARRAY( table->hints, count ) || + FT_NEW_ARRAY( table->zones, 2 * count + 1 ) ) + goto Exit; + + table->max_hints = count; + table->sort_global = table->sort + count; + table->num_hints = 0; + table->num_zones = 0; + table->zone = 0; + + /* initialize the `table->hints' array */ + { + PSH_Hint write = table->hints; + PS_Hint read = hints->hints; + + + for ( ; count > 0; count--, write++, read++ ) + { + write->org_pos = read->pos; + write->org_len = read->len; + write->flags = read->flags; + } + } + + /* we now need to determine the initial `parent' stems; first */ + /* activate the hints that are given by the initial hint masks */ + if ( hint_masks ) + { + PS_Mask mask = hint_masks->masks; + + + count = hint_masks->num_masks; + table->hint_masks = hint_masks; + + for ( ; count > 0; count--, mask++ ) + psh_hint_table_record_mask( table, mask ); + } + + /* finally, do a linear parse in case some hints were left alone */ + if ( table->num_hints != table->max_hints ) + { + FT_UInt idx; + + + FT_ERROR(( "psh_hint_table_init: missing/incorrect hint masks!\n" )); + + count = table->max_hints; + for ( idx = 0; idx < count; idx++ ) + psh_hint_table_record( table, idx ); + } + + Exit: + return error; + } + + + static void + psh_hint_table_activate_mask( PSH_Hint_Table table, + PS_Mask hint_mask ) + { + FT_Int mask = 0, val = 0; + FT_Byte* cursor = hint_mask->bytes; + FT_UInt idx, limit, count; + + + limit = hint_mask->num_bits; + count = 0; + + psh_hint_table_deactivate( table ); + + for ( idx = 0; idx < limit; idx++ ) + { + if ( mask == 0 ) + { + val = *cursor++; + mask = 0x80; + } + + if ( val & mask ) + { + PSH_Hint hint = &table->hints[idx]; + + + if ( !psh_hint_is_active( hint ) ) + { + FT_UInt count2; + +#if 0 + PSH_Hint* sort = table->sort; + PSH_Hint hint2; + + + for ( count2 = count; count2 > 0; count2--, sort++ ) + { + hint2 = sort[0]; + if ( psh_hint_overlap( hint, hint2 ) ) + FT_ERROR(( "psh_hint_table_activate_mask:" + " found overlapping hints\n" )) + } +#else + count2 = 0; +#endif + + if ( count2 == 0 ) + { + psh_hint_activate( hint ); + if ( count < table->max_hints ) + table->sort[count++] = hint; + else + FT_ERROR(( "psh_hint_tableactivate_mask:" + " too many active hints\n" )); + } + } + } + + mask >>= 1; + } + table->num_hints = count; + + /* now, sort the hints; they are guaranteed to not overlap */ + /* so we can compare their "org_pos" field directly */ + { + FT_Int i1, i2; + PSH_Hint hint1, hint2; + PSH_Hint* sort = table->sort; + + + /* a simple bubble sort will do, since in 99% of cases, the hints */ + /* will be already sorted -- and the sort will be linear */ + for ( i1 = 1; i1 < (FT_Int)count; i1++ ) + { + hint1 = sort[i1]; + for ( i2 = i1 - 1; i2 >= 0; i2-- ) + { + hint2 = sort[i2]; + + if ( hint2->org_pos < hint1->org_pos ) + break; + + sort[i2 + 1] = hint2; + sort[i2] = hint1; + } + } + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** HINTS GRID-FITTING AND OPTIMIZATION *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#if 1 + static FT_Pos + psh_dimension_quantize_len( PSH_Dimension dim, + FT_Pos len, + FT_Bool do_snapping ) + { + if ( len <= 64 ) + len = 64; + else + { + FT_Pos delta = len - dim->stdw.widths[0].cur; + + + if ( delta < 0 ) + delta = -delta; + + if ( delta < 40 ) + { + len = dim->stdw.widths[0].cur; + if ( len < 48 ) + len = 48; + } + + if ( len < 3 * 64 ) + { + delta = ( len & 63 ); + len &= -64; + + if ( delta < 10 ) + len += delta; + + else if ( delta < 32 ) + len += 10; + + else if ( delta < 54 ) + len += 54; + + else + len += delta; + } + else + len = FT_PIX_ROUND( len ); + } + + if ( do_snapping ) + len = FT_PIX_ROUND( len ); + + return len; + } +#endif /* 0 */ + + +#ifdef DEBUG_HINTER + + static void + ps_simple_scale( PSH_Hint_Table table, + FT_Fixed scale, + FT_Fixed delta, + FT_Int dimension ) + { + PSH_Hint hint; + FT_UInt count; + + + for ( count = 0; count < table->max_hints; count++ ) + { + hint = table->hints + count; + + hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta; + hint->cur_len = FT_MulFix( hint->org_len, scale ); + + if ( ps_debug_hint_func ) + ps_debug_hint_func( hint, dimension ); + } + } + +#endif /* DEBUG_HINTER */ + + + static FT_Fixed + psh_hint_snap_stem_side_delta( FT_Fixed pos, + FT_Fixed len ) + { + FT_Fixed delta1 = FT_PIX_ROUND( pos ) - pos; + FT_Fixed delta2 = FT_PIX_ROUND( pos + len ) - pos - len; + + + if ( FT_ABS( delta1 ) <= FT_ABS( delta2 ) ) + return delta1; + else + return delta2; + } + + + static void + psh_hint_align( PSH_Hint hint, + PSH_Globals globals, + FT_Int dimension, + PSH_Glyph glyph ) + { + PSH_Dimension dim = &globals->dimension[dimension]; + FT_Fixed scale = dim->scale_mult; + FT_Fixed delta = dim->scale_delta; + + + if ( !psh_hint_is_fitted( hint ) ) + { + FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; + FT_Pos len = FT_MulFix( hint->org_len, scale ); + + FT_Int do_snapping; + FT_Pos fit_len; + PSH_AlignmentRec align; + + + /* ignore stem alignments when requested through the hint flags */ + if ( ( dimension == 0 && !glyph->do_horz_hints ) || + ( dimension == 1 && !glyph->do_vert_hints ) ) + { + hint->cur_pos = pos; + hint->cur_len = len; + + psh_hint_set_fitted( hint ); + return; + } + + /* perform stem snapping when requested - this is necessary + * for monochrome and LCD hinting modes only + */ + do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) || + ( dimension == 1 && glyph->do_vert_snapping ); + + hint->cur_len = fit_len = len; + + /* check blue zones for horizontal stems */ + align.align = PSH_BLUE_ALIGN_NONE; + align.align_bot = align.align_top = 0; + + if ( dimension == 1 ) + psh_blues_snap_stem( &globals->blues, + hint->org_pos + hint->org_len, + hint->org_pos, + &align ); + + switch ( align.align ) + { + case PSH_BLUE_ALIGN_TOP: + /* the top of the stem is aligned against a blue zone */ + hint->cur_pos = align.align_top - fit_len; + break; + + case PSH_BLUE_ALIGN_BOT: + /* the bottom of the stem is aligned against a blue zone */ + hint->cur_pos = align.align_bot; + break; + + case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: + /* both edges of the stem are aligned against blue zones */ + hint->cur_pos = align.align_bot; + hint->cur_len = align.align_top - align.align_bot; + break; + + default: + { + PSH_Hint parent = hint->parent; + + + if ( parent ) + { + FT_Pos par_org_center, par_cur_center; + FT_Pos cur_org_center, cur_delta; + + + /* ensure that parent is already fitted */ + if ( !psh_hint_is_fitted( parent ) ) + psh_hint_align( parent, globals, dimension, glyph ); + + /* keep original relation between hints, this is, use the */ + /* scaled distance between the centers of the hints to */ + /* compute the new position */ + par_org_center = parent->org_pos + ( parent->org_len >> 1 ); + par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 ); + cur_org_center = hint->org_pos + ( hint->org_len >> 1 ); + + cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); + pos = par_cur_center + cur_delta - ( len >> 1 ); + } + + hint->cur_pos = pos; + hint->cur_len = fit_len; + + /* Stem adjustment tries to snap stem widths to standard + * ones. This is important to prevent unpleasant rounding + * artefacts. + */ + if ( glyph->do_stem_adjust ) + { + if ( len <= 64 ) + { + /* the stem is less than one pixel; we will center it + * around the nearest pixel center + */ +#if 1 + pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ); +#else + /* this seems to be a bug! */ + pos = pos + FT_PIX_FLOOR( len >> 1 ); +#endif + len = 64; + } + else + { + len = psh_dimension_quantize_len( dim, len, 0 ); + } + } + + /* now that we have a good hinted stem width, try to position */ + /* the stem along a pixel grid integer coordinate */ + hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len ); + hint->cur_len = len; + } + } + + if ( do_snapping ) + { + pos = hint->cur_pos; + len = hint->cur_len; + + if ( len < 64 ) + len = 64; + else + len = FT_PIX_ROUND( len ); + + switch ( align.align ) + { + case PSH_BLUE_ALIGN_TOP: + hint->cur_pos = align.align_top - len; + hint->cur_len = len; + break; + + case PSH_BLUE_ALIGN_BOT: + hint->cur_len = len; + break; + + case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP: + /* don't touch */ + break; + + + default: + hint->cur_len = len; + if ( len & 64 ) + pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32; + else + pos = FT_PIX_ROUND( pos + ( len >> 1 ) ); + + hint->cur_pos = pos - ( len >> 1 ); + hint->cur_len = len; + } + } + + psh_hint_set_fitted( hint ); + +#ifdef DEBUG_HINTER + if ( ps_debug_hint_func ) + ps_debug_hint_func( hint, dimension ); +#endif + } + } + + +#if 0 /* not used for now, experimental */ + + /* + * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT) + * of stems + */ + static void + psh_hint_align_light( PSH_Hint hint, + PSH_Globals globals, + FT_Int dimension, + PSH_Glyph glyph ) + { + PSH_Dimension dim = &globals->dimension[dimension]; + FT_Fixed scale = dim->scale_mult; + FT_Fixed delta = dim->scale_delta; + + + if ( !psh_hint_is_fitted( hint ) ) + { + FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; + FT_Pos len = FT_MulFix( hint->org_len, scale ); + + FT_Pos fit_len; + + PSH_AlignmentRec align; + + + /* ignore stem alignments when requested through the hint flags */ + if ( ( dimension == 0 && !glyph->do_horz_hints ) || + ( dimension == 1 && !glyph->do_vert_hints ) ) + { + hint->cur_pos = pos; + hint->cur_len = len; + + psh_hint_set_fitted( hint ); + return; + } + + fit_len = len; + + hint->cur_len = fit_len; + + /* check blue zones for horizontal stems */ + align.align = PSH_BLUE_ALIGN_NONE; + align.align_bot = align.align_top = 0; + + if ( dimension == 1 ) + psh_blues_snap_stem( &globals->blues, + hint->org_pos + hint->org_len, + hint->org_pos, + &align ); + + switch ( align.align ) + { + case PSH_BLUE_ALIGN_TOP: + /* the top of the stem is aligned against a blue zone */ + hint->cur_pos = align.align_top - fit_len; + break; + + case PSH_BLUE_ALIGN_BOT: + /* the bottom of the stem is aligned against a blue zone */ + hint->cur_pos = align.align_bot; + break; + + case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: + /* both edges of the stem are aligned against blue zones */ + hint->cur_pos = align.align_bot; + hint->cur_len = align.align_top - align.align_bot; + break; + + default: + { + PSH_Hint parent = hint->parent; + + + if ( parent ) + { + FT_Pos par_org_center, par_cur_center; + FT_Pos cur_org_center, cur_delta; + + + /* ensure that parent is already fitted */ + if ( !psh_hint_is_fitted( parent ) ) + psh_hint_align_light( parent, globals, dimension, glyph ); + + par_org_center = parent->org_pos + ( parent->org_len / 2 ); + par_cur_center = parent->cur_pos + ( parent->cur_len / 2 ); + cur_org_center = hint->org_pos + ( hint->org_len / 2 ); + + cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); + pos = par_cur_center + cur_delta - ( len >> 1 ); + } + + /* Stems less than one pixel wide are easy -- we want to + * make them as dark as possible, so they must fall within + * one pixel. If the stem is split between two pixels + * then snap the edge that is nearer to the pixel boundary + * to the pixel boundary. + */ + if ( len <= 64 ) + { + if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 ) + pos += psh_hint_snap_stem_side_delta ( pos, len ); + } + + /* Position stems other to minimize the amount of mid-grays. + * There are, in general, two positions that do this, + * illustrated as A) and B) below. + * + * + + + + + * + * A) |--------------------------------| + * B) |--------------------------------| + * C) |--------------------------------| + * + * Position A) (split the excess stem equally) should be better + * for stems of width N + f where f < 0.5. + * + * Position B) (split the deficiency equally) should be better + * for stems of width N + f where f > 0.5. + * + * It turns out though that minimizing the total number of lit + * pixels is also important, so position C), with one edge + * aligned with a pixel boundary is actually preferable + * to A). There are also more possibile positions for C) than + * for A) or B), so it involves less distortion of the overall + * character shape. + */ + else /* len > 64 */ + { + FT_Fixed frac_len = len & 63; + FT_Fixed center = pos + ( len >> 1 ); + FT_Fixed delta_a, delta_b; + + + if ( ( len / 64 ) & 1 ) + { + delta_a = FT_PIX_FLOOR( center ) + 32 - center; + delta_b = FT_PIX_ROUND( center ) - center; + } + else + { + delta_a = FT_PIX_ROUND( center ) - center; + delta_b = FT_PIX_FLOOR( center ) + 32 - center; + } + + /* We choose between B) and C) above based on the amount + * of fractinal stem width; for small amounts, choose + * C) always, for large amounts, B) always, and inbetween, + * pick whichever one involves less stem movement. + */ + if ( frac_len < 32 ) + { + pos += psh_hint_snap_stem_side_delta ( pos, len ); + } + else if ( frac_len < 48 ) + { + FT_Fixed side_delta = psh_hint_snap_stem_side_delta ( pos, + len ); + + if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) ) + pos += side_delta; + else + pos += delta_b; + } + else + { + pos += delta_b; + } + } + + hint->cur_pos = pos; + } + } /* switch */ + + psh_hint_set_fitted( hint ); + +#ifdef DEBUG_HINTER + if ( ps_debug_hint_func ) + ps_debug_hint_func( hint, dimension ); +#endif + } + } + +#endif /* 0 */ + + + static void + psh_hint_table_align_hints( PSH_Hint_Table table, + PSH_Globals globals, + FT_Int dimension, + PSH_Glyph glyph ) + { + PSH_Hint hint; + FT_UInt count; + +#ifdef DEBUG_HINTER + + PSH_Dimension dim = &globals->dimension[dimension]; + FT_Fixed scale = dim->scale_mult; + FT_Fixed delta = dim->scale_delta; + + + if ( ps_debug_no_vert_hints && dimension == 0 ) + { + ps_simple_scale( table, scale, delta, dimension ); + return; + } + + if ( ps_debug_no_horz_hints && dimension == 1 ) + { + ps_simple_scale( table, scale, delta, dimension ); + return; + } + +#endif /* DEBUG_HINTER*/ + + hint = table->hints; + count = table->max_hints; + + for ( ; count > 0; count--, hint++ ) + psh_hint_align( hint, globals, dimension, glyph ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** POINTS INTERPOLATION ROUTINES *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#define PSH_ZONE_MIN -3200000L +#define PSH_ZONE_MAX +3200000L + +#define xxDEBUG_ZONES + + +#ifdef DEBUG_ZONES + +#include <stdio.h> + + static void + psh_print_zone( PSH_Zone zone ) + { + printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n", + zone->scale / 65536.0, + zone->delta / 64.0, + zone->min, + zone->max ); + } + +#else + +#define psh_print_zone( x ) do { } while ( 0 ) + +#endif /* DEBUG_ZONES */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** HINTER GLYPH MANAGEMENT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + +#ifdef COMPUTE_INFLEXS + + /* compute all inflex points in a given glyph */ + static void + psh_glyph_compute_inflections( PSH_Glyph glyph ) + { + FT_UInt n; + + + for ( n = 0; n < glyph->num_contours; n++ ) + { + PSH_Point first, start, end, before, after; + FT_Angle angle_in, angle_seg, angle_out; + FT_Angle diff_in, diff_out; + FT_Int finished = 0; + + + /* we need at least 4 points to create an inflection point */ + if ( glyph->contours[n].count < 4 ) + continue; + + /* compute first segment in contour */ + first = glyph->contours[n].start; + + start = end = first; + do + { + end = end->next; + if ( end == first ) + goto Skip; + + } while ( PSH_POINT_EQUAL_ORG( end, first ) ); + + angle_seg = PSH_POINT_ANGLE( start, end ); + + /* extend the segment start whenever possible */ + before = start; + do + { + do + { + start = before; + before = before->prev; + if ( before == first ) + goto Skip; + + } while ( PSH_POINT_EQUAL_ORG( before, start ) ); + + angle_in = PSH_POINT_ANGLE( before, start ); + + } while ( angle_in == angle_seg ); + + first = start; + diff_in = FT_Angle_Diff( angle_in, angle_seg ); + + /* now, process all segments in the contour */ + do + { + /* first, extend current segment's end whenever possible */ + after = end; + do + { + do + { + end = after; + after = after->next; + if ( after == first ) + finished = 1; + + } while ( PSH_POINT_EQUAL_ORG( end, after ) ); + + angle_out = PSH_POINT_ANGLE( end, after ); + + } while ( angle_out == angle_seg ); + + diff_out = FT_Angle_Diff( angle_seg, angle_out ); + + if ( ( diff_in ^ diff_out ) < 0 ) + { + /* diff_in and diff_out have different signs, we have */ + /* inflection points here... */ + + do + { + psh_point_set_inflex( start ); + start = start->next; + } + while ( start != end ); + + psh_point_set_inflex( start ); + } + + start = end; + end = after; + angle_seg = angle_out; + diff_in = diff_out; + + } while ( !finished ); + + Skip: + ; + } + } + +#endif /* COMPUTE_INFLEXS */ + + + static void + psh_glyph_done( PSH_Glyph glyph ) + { + FT_Memory memory = glyph->memory; + + + psh_hint_table_done( &glyph->hint_tables[1], memory ); + psh_hint_table_done( &glyph->hint_tables[0], memory ); + + FT_FREE( glyph->points ); + FT_FREE( glyph->contours ); + + glyph->num_points = 0; + glyph->num_contours = 0; + + glyph->memory = 0; + } + + + static int + psh_compute_dir( FT_Pos dx, + FT_Pos dy ) + { + FT_Pos ax, ay; + int result = PSH_DIR_NONE; + + + ax = ( dx >= 0 ) ? dx : -dx; + ay = ( dy >= 0 ) ? dy : -dy; + + if ( ay * 12 < ax ) + { + /* |dy| <<< |dx| means a near-horizontal segment */ + result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT; + } + else if ( ax * 12 < ay ) + { + /* |dx| <<< |dy| means a near-vertical segment */ + result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN; + } + + return result; + } + + + /* load outline point coordinates into hinter glyph */ + static void + psh_glyph_load_points( PSH_Glyph glyph, + FT_Int dimension ) + { + FT_Vector* vec = glyph->outline->points; + PSH_Point point = glyph->points; + FT_UInt count = glyph->num_points; + + + for ( ; count > 0; count--, point++, vec++ ) + { + point->flags2 = 0; + point->hint = NULL; + if ( dimension == 0 ) + { + point->org_u = vec->x; + point->org_v = vec->y; + } + else + { + point->org_u = vec->y; + point->org_v = vec->x; + } + +#ifdef DEBUG_HINTER + point->org_x = vec->x; + point->org_y = vec->y; +#endif + + } + } + + + /* save hinted point coordinates back to outline */ + static void + psh_glyph_save_points( PSH_Glyph glyph, + FT_Int dimension ) + { + FT_UInt n; + PSH_Point point = glyph->points; + FT_Vector* vec = glyph->outline->points; + char* tags = glyph->outline->tags; + + + for ( n = 0; n < glyph->num_points; n++ ) + { + if ( dimension == 0 ) + vec[n].x = point->cur_u; + else + vec[n].y = point->cur_u; + + if ( psh_point_is_strong( point ) ) + tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 ); + +#ifdef DEBUG_HINTER + + if ( dimension == 0 ) + { + point->cur_x = point->cur_u; + point->flags_x = point->flags2 | point->flags; + } + else + { + point->cur_y = point->cur_u; + point->flags_y = point->flags2 | point->flags; + } + +#endif + + point++; + } + } + + + static FT_Error + psh_glyph_init( PSH_Glyph glyph, + FT_Outline* outline, + PS_Hints ps_hints, + PSH_Globals globals ) + { + FT_Error error; + FT_Memory memory; + + + /* clear all fields */ + FT_MEM_ZERO( glyph, sizeof ( *glyph ) ); + + memory = glyph->memory = globals->memory; + + /* allocate and setup points + contours arrays */ + if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) || + FT_NEW_ARRAY( glyph->contours, outline->n_contours ) ) + goto Exit; + + glyph->num_points = outline->n_points; + glyph->num_contours = outline->n_contours; + + { + FT_UInt first = 0, next, n; + PSH_Point points = glyph->points; + PSH_Contour contour = glyph->contours; + + + for ( n = 0; n < glyph->num_contours; n++ ) + { + FT_Int count; + PSH_Point point; + + + next = outline->contours[n] + 1; + count = next - first; + + contour->start = points + first; + contour->count = (FT_UInt)count; + + if ( count > 0 ) + { + point = points + first; + + point->prev = points + next - 1; + point->contour = contour; + + for ( ; count > 1; count-- ) + { + point[0].next = point + 1; + point[1].prev = point; + point++; + point->contour = contour; + } + point->next = points + first; + } + + contour++; + first = next; + } + } + + { + PSH_Point points = glyph->points; + PSH_Point point = points; + FT_Vector* vec = outline->points; + FT_UInt n; + + + for ( n = 0; n < glyph->num_points; n++, point++ ) + { + FT_Int n_prev = (FT_Int)( point->prev - points ); + FT_Int n_next = (FT_Int)( point->next - points ); + FT_Pos dxi, dyi, dxo, dyo; + + + if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) ) + point->flags = PSH_POINT_OFF; + + dxi = vec[n].x - vec[n_prev].x; + dyi = vec[n].y - vec[n_prev].y; + + point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi ); + + dxo = vec[n_next].x - vec[n].x; + dyo = vec[n_next].y - vec[n].y; + + point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo ); + + /* detect smooth points */ + if ( point->flags & PSH_POINT_OFF ) + point->flags |= PSH_POINT_SMOOTH; + else if ( point->dir_in != PSH_DIR_NONE || + point->dir_out != PSH_DIR_NONE ) + { + if ( point->dir_in == point->dir_out ) + point->flags |= PSH_POINT_SMOOTH; + } + else + { + FT_Angle angle_in, angle_out, diff; + + + angle_in = FT_Atan2( dxi, dyi ); + angle_out = FT_Atan2( dxo, dyo ); + + diff = angle_in - angle_out; + if ( diff < 0 ) + diff = -diff; + + if ( diff > FT_ANGLE_PI ) + diff = FT_ANGLE_2PI - diff; + + if ( diff < FT_ANGLE_PI / 16 ) + point->flags |= PSH_POINT_SMOOTH; + } + } + } + + glyph->outline = outline; + glyph->globals = globals; + +#ifdef COMPUTE_INFLEXS + psh_glyph_load_points( glyph, 0 ); + psh_glyph_compute_inflections( glyph ); +#endif /* COMPUTE_INFLEXS */ + + /* now deal with hints tables */ + error = psh_hint_table_init( &glyph->hint_tables [0], + &ps_hints->dimension[0].hints, + &ps_hints->dimension[0].masks, + &ps_hints->dimension[0].counters, + memory ); + if ( error ) + goto Exit; + + error = psh_hint_table_init( &glyph->hint_tables [1], + &ps_hints->dimension[1].hints, + &ps_hints->dimension[1].masks, + &ps_hints->dimension[1].counters, + memory ); + if ( error ) + goto Exit; + + Exit: + return error; + } + + + /* compute all extrema in a glyph for a given dimension */ + static void + psh_glyph_compute_extrema( PSH_Glyph glyph ) + { + FT_UInt n; + + + /* first of all, compute all local extrema */ + for ( n = 0; n < glyph->num_contours; n++ ) + { + PSH_Point first = glyph->contours[n].start; + PSH_Point point, before, after; + + + if ( glyph->contours[n].count == 0 ) + continue; + + point = first; + before = point; + after = point; + + do + { + before = before->prev; + if ( before == first ) + goto Skip; + + } while ( before->org_u == point->org_u ); + + first = point = before->next; + + for (;;) + { + after = point; + do + { + after = after->next; + if ( after == first ) + goto Next; + + } while ( after->org_u == point->org_u ); + + if ( before->org_u < point->org_u ) + { + if ( after->org_u < point->org_u ) + { + /* local maximum */ + goto Extremum; + } + } + else /* before->org_u > point->org_u */ + { + if ( after->org_u > point->org_u ) + { + /* local minimum */ + Extremum: + do + { + psh_point_set_extremum( point ); + point = point->next; + + } while ( point != after ); + } + } + + before = after->prev; + point = after; + + } /* for */ + + Next: + ; + } + + /* for each extremum, determine its direction along the */ + /* orthogonal axis */ + for ( n = 0; n < glyph->num_points; n++ ) + { + PSH_Point point, before, after; + + + point = &glyph->points[n]; + before = point; + after = point; + + if ( psh_point_is_extremum( point ) ) + { + do + { + before = before->prev; + if ( before == point ) + goto Skip; + + } while ( before->org_v == point->org_v ); + + do + { + after = after->next; + if ( after == point ) + goto Skip; + + } while ( after->org_v == point->org_v ); + } + + if ( before->org_v < point->org_v && + after->org_v > point->org_v ) + { + psh_point_set_positive( point ); + } + else if ( before->org_v > point->org_v && + after->org_v < point->org_v ) + { + psh_point_set_negative( point ); + } + + Skip: + ; + } + } + + + /* major_dir is the direction for points on the bottom/left of the stem; */ + /* Points on the top/right of the stem will have a direction of */ + /* -major_dir. */ + + static void + psh_hint_table_find_strong_point( PSH_Hint_Table table, + PSH_Point point, + FT_Int threshold, + FT_Int major_dir ) + { + PSH_Hint* sort = table->sort; + FT_UInt num_hints = table->num_hints; + FT_Int point_dir = 0; + + + if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) ) + point_dir = point->dir_in; + + else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) ) + point_dir = point->dir_out; + + if ( point_dir ) + { + FT_UInt flag; + + + for ( ; num_hints > 0; num_hints--, sort++ ) + { + PSH_Hint hint = sort[0]; + FT_Pos d; + + + if ( point_dir == major_dir ) + { + flag = PSH_POINT_EDGE_MIN; + d = point->org_u - hint->org_pos; + + if ( FT_ABS( d ) < threshold ) + { + Is_Strong: + psh_point_set_strong( point ); + point->flags2 |= flag; + point->hint = hint; + break; + } + } + else if ( point_dir == -major_dir ) + { + flag = PSH_POINT_EDGE_MAX; + d = point->org_u - hint->org_pos - hint->org_len; + + if ( FT_ABS( d ) < threshold ) + goto Is_Strong; + } + } + } + +#if 1 + else if ( psh_point_is_extremum( point ) ) + { + /* treat extrema as special cases for stem edge alignment */ + FT_UInt min_flag, max_flag; + + + if ( major_dir == PSH_DIR_HORIZONTAL ) + { + min_flag = PSH_POINT_POSITIVE; + max_flag = PSH_POINT_NEGATIVE; + } + else + { + min_flag = PSH_POINT_NEGATIVE; + max_flag = PSH_POINT_POSITIVE; + } + + for ( ; num_hints > 0; num_hints--, sort++ ) + { + PSH_Hint hint = sort[0]; + FT_Pos d; + FT_Int flag; + + + if ( point->flags2 & min_flag ) + { + flag = PSH_POINT_EDGE_MIN; + d = point->org_u - hint->org_pos; + + if ( FT_ABS( d ) < threshold ) + { + Is_Strong2: + point->flags2 |= flag; + point->hint = hint; + psh_point_set_strong( point ); + break; + } + } + else if ( point->flags2 & max_flag ) + { + flag = PSH_POINT_EDGE_MAX; + d = point->org_u - hint->org_pos - hint->org_len; + + if ( FT_ABS( d ) < threshold ) + goto Is_Strong2; + } + + if ( point->org_u >= hint->org_pos && + point->org_u <= hint->org_pos + hint->org_len ) + { + point->hint = hint; + } + } + } + +#endif /* 1 */ + } + + + /* the accepted shift for strong points in fractional pixels */ +#define PSH_STRONG_THRESHOLD 32 + + /* the maximum shift value in font units */ +#define PSH_STRONG_THRESHOLD_MAXIMUM 30 + + + /* find strong points in a glyph */ + static void + psh_glyph_find_strong_points( PSH_Glyph glyph, + FT_Int dimension ) + { + /* a point is `strong' if it is located on a stem edge and */ + /* has an `in' or `out' tangent parallel to the hint's direction */ + + PSH_Hint_Table table = &glyph->hint_tables[dimension]; + PS_Mask mask = table->hint_masks->masks; + FT_UInt num_masks = table->hint_masks->num_masks; + FT_UInt first = 0; + FT_Int major_dir = dimension == 0 ? PSH_DIR_VERTICAL + : PSH_DIR_HORIZONTAL; + PSH_Dimension dim = &glyph->globals->dimension[dimension]; + FT_Fixed scale = dim->scale_mult; + FT_Int threshold; + + + threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale ); + if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM ) + threshold = PSH_STRONG_THRESHOLD_MAXIMUM; + + /* process secondary hints to `selected' points */ + if ( num_masks > 1 && glyph->num_points > 0 ) + { + first = mask->end_point; + mask++; + for ( ; num_masks > 1; num_masks--, mask++ ) + { + FT_UInt next; + FT_Int count; + + + next = mask->end_point; + count = next - first; + if ( count > 0 ) + { + PSH_Point point = glyph->points + first; + + + psh_hint_table_activate_mask( table, mask ); + + for ( ; count > 0; count--, point++ ) + psh_hint_table_find_strong_point( table, point, + threshold, major_dir ); + } + first = next; + } + } + + /* process primary hints for all points */ + if ( num_masks == 1 ) + { + FT_UInt count = glyph->num_points; + PSH_Point point = glyph->points; + + + psh_hint_table_activate_mask( table, table->hint_masks->masks ); + for ( ; count > 0; count--, point++ ) + { + if ( !psh_point_is_strong( point ) ) + psh_hint_table_find_strong_point( table, point, + threshold, major_dir ); + } + } + + /* now, certain points may have been attached to a hint and */ + /* not marked as strong; update their flags then */ + { + FT_UInt count = glyph->num_points; + PSH_Point point = glyph->points; + + + for ( ; count > 0; count--, point++ ) + if ( point->hint && !psh_point_is_strong( point ) ) + psh_point_set_strong( point ); + } + } + + + /* find points in a glyph which are in a blue zone and have `in' or */ + /* `out' tangents parallel to the horizontal axis */ + static void + psh_glyph_find_blue_points( PSH_Blues blues, + PSH_Glyph glyph ) + { + PSH_Blue_Table table; + PSH_Blue_Zone zone; + FT_UInt glyph_count = glyph->num_points; + FT_UInt blue_count; + PSH_Point point = glyph->points; + + + for ( ; glyph_count > 0; glyph_count--, point++ ) + { + FT_Pos y; + + + /* check tangents */ + if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) && + !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) ) + continue; + + /* skip strong points */ + if ( psh_point_is_strong( point ) ) + continue; + + y = point->org_u; + + /* look up top zones */ + table = &blues->normal_top; + blue_count = table->count; + zone = table->zones; + + for ( ; blue_count > 0; blue_count--, zone++ ) + { + FT_Pos delta = y - zone->org_bottom; + + + if ( delta < -blues->blue_fuzz ) + break; + + if ( y <= zone->org_top + blues->blue_fuzz ) + if ( blues->no_overshoots || delta <= blues->blue_threshold ) + { + point->cur_u = zone->cur_bottom; + psh_point_set_strong( point ); + psh_point_set_fitted( point ); + } + } + + /* look up bottom zones */ + table = &blues->normal_bottom; + blue_count = table->count; + zone = table->zones + blue_count - 1; + + for ( ; blue_count > 0; blue_count--, zone-- ) + { + FT_Pos delta = zone->org_top - y; + + + if ( delta < -blues->blue_fuzz ) + break; + + if ( y >= zone->org_bottom - blues->blue_fuzz ) + if ( blues->no_overshoots || delta < blues->blue_threshold ) + { + point->cur_u = zone->cur_top; + psh_point_set_strong( point ); + psh_point_set_fitted( point ); + } + } + } + } + + + /* interpolate strong points with the help of hinted coordinates */ + static void + psh_glyph_interpolate_strong_points( PSH_Glyph glyph, + FT_Int dimension ) + { + PSH_Dimension dim = &glyph->globals->dimension[dimension]; + FT_Fixed scale = dim->scale_mult; + + FT_UInt count = glyph->num_points; + PSH_Point point = glyph->points; + + + for ( ; count > 0; count--, point++ ) + { + PSH_Hint hint = point->hint; + + + if ( hint ) + { + FT_Pos delta; + + + if ( psh_point_is_edge_min( point ) ) + point->cur_u = hint->cur_pos; + + else if ( psh_point_is_edge_max( point ) ) + point->cur_u = hint->cur_pos + hint->cur_len; + + else + { + delta = point->org_u - hint->org_pos; + + if ( delta <= 0 ) + point->cur_u = hint->cur_pos + FT_MulFix( delta, scale ); + + else if ( delta >= hint->org_len ) + point->cur_u = hint->cur_pos + hint->cur_len + + FT_MulFix( delta - hint->org_len, scale ); + + else if ( hint->org_len > 0 ) + point->cur_u = hint->cur_pos + + FT_MulDiv( delta, hint->cur_len, + hint->org_len ); + else + point->cur_u = hint->cur_pos; + } + psh_point_set_fitted( point ); + } + } + } + + + static void + psh_glyph_interpolate_normal_points( PSH_Glyph glyph, + FT_Int dimension ) + { + +#if 1 + /* first technique: a point is strong if it is a local extremum */ + + PSH_Dimension dim = &glyph->globals->dimension[dimension]; + FT_Fixed scale = dim->scale_mult; + + FT_UInt count = glyph->num_points; + PSH_Point point = glyph->points; + + + for ( ; count > 0; count--, point++ ) + { + if ( psh_point_is_strong( point ) ) + continue; + + /* sometimes, some local extrema are smooth points */ + if ( psh_point_is_smooth( point ) ) + { + if ( point->dir_in == PSH_DIR_NONE || + point->dir_in != point->dir_out ) + continue; + + if ( !psh_point_is_extremum( point ) && + !psh_point_is_inflex( point ) ) + continue; + + point->flags &= ~PSH_POINT_SMOOTH; + } + + /* find best enclosing point coordinates */ + { + PSH_Point before = 0; + PSH_Point after = 0; + + FT_Pos diff_before = -32000; + FT_Pos diff_after = 32000; + FT_Pos u = point->org_u; + + FT_Int count2 = glyph->num_points; + PSH_Point cur = glyph->points; + + + for ( ; count2 > 0; count2--, cur++ ) + { + if ( psh_point_is_strong( cur ) ) + { + FT_Pos diff = cur->org_u - u; + + + if ( diff <= 0 ) + { + if ( diff > diff_before ) + { + diff_before = diff; + before = cur; + } + } + + else if ( diff >= 0 ) + { + if ( diff < diff_after ) + { + diff_after = diff; + after = cur; + } + } + } + } + + if ( !before ) + { + if ( !after ) + continue; + + /* we are before the first strong point coordinate; */ + /* simply translate the point */ + point->cur_u = after->cur_u + + FT_MulFix( point->org_u - after->org_u, scale ); + } + else if ( !after ) + { + /* we are after the last strong point coordinate; */ + /* simply translate the point */ + point->cur_u = before->cur_u + + FT_MulFix( point->org_u - before->org_u, scale ); + } + else + { + if ( diff_before == 0 ) + point->cur_u = before->cur_u; + + else if ( diff_after == 0 ) + point->cur_u = after->cur_u; + + else + point->cur_u = before->cur_u + + FT_MulDiv( u - before->org_u, + after->cur_u - before->cur_u, + after->org_u - before->org_u ); + } + + psh_point_set_fitted( point ); + } + } + +#endif /* 1 */ + + } + + + /* interpolate other points */ + static void + psh_glyph_interpolate_other_points( PSH_Glyph glyph, + FT_Int dimension ) + { + PSH_Dimension dim = &glyph->globals->dimension[dimension]; + FT_Fixed scale = dim->scale_mult; + FT_Fixed delta = dim->scale_delta; + PSH_Contour contour = glyph->contours; + FT_UInt num_contours = glyph->num_contours; + + + for ( ; num_contours > 0; num_contours--, contour++ ) + { + PSH_Point start = contour->start; + PSH_Point first, next, point; + FT_UInt fit_count; + + + /* count the number of strong points in this contour */ + next = start + contour->count; + fit_count = 0; + first = 0; + + for ( point = start; point < next; point++ ) + if ( psh_point_is_fitted( point ) ) + { + if ( !first ) + first = point; + + fit_count++; + } + + /* if there are less than 2 fitted points in the contour, we */ + /* simply scale and eventually translate the contour points */ + if ( fit_count < 2 ) + { + if ( fit_count == 1 ) + delta = first->cur_u - FT_MulFix( first->org_u, scale ); + + for ( point = start; point < next; point++ ) + if ( point != first ) + point->cur_u = FT_MulFix( point->org_u, scale ) + delta; + + goto Next_Contour; + } + + /* there are more than 2 strong points in this contour; we */ + /* need to interpolate weak points between them */ + start = first; + do + { + point = first; + + /* skip consecutive fitted points */ + for (;;) + { + next = first->next; + if ( next == start ) + goto Next_Contour; + + if ( !psh_point_is_fitted( next ) ) + break; + + first = next; + } + + /* find next fitted point after unfitted one */ + for (;;) + { + next = next->next; + if ( psh_point_is_fitted( next ) ) + break; + } + + /* now interpolate between them */ + { + FT_Pos org_a, org_ab, cur_a, cur_ab; + FT_Pos org_c, org_ac, cur_c; + FT_Fixed scale_ab; + + + if ( first->org_u <= next->org_u ) + { + org_a = first->org_u; + cur_a = first->cur_u; + org_ab = next->org_u - org_a; + cur_ab = next->cur_u - cur_a; + } + else + { + org_a = next->org_u; + cur_a = next->cur_u; + org_ab = first->org_u - org_a; + cur_ab = first->cur_u - cur_a; + } + + scale_ab = 0x10000L; + if ( org_ab > 0 ) + scale_ab = FT_DivFix( cur_ab, org_ab ); + + point = first->next; + do + { + org_c = point->org_u; + org_ac = org_c - org_a; + + if ( org_ac <= 0 ) + { + /* on the left of the interpolation zone */ + cur_c = cur_a + FT_MulFix( org_ac, scale ); + } + else if ( org_ac >= org_ab ) + { + /* on the right on the interpolation zone */ + cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale ); + } + else + { + /* within the interpolation zone */ + cur_c = cur_a + FT_MulFix( org_ac, scale_ab ); + } + + point->cur_u = cur_c; + + point = point->next; + + } while ( point != next ); + } + + /* keep going until all points in the contours have been processed */ + first = next; + + } while ( first != start ); + + Next_Contour: + ; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** HIGH-LEVEL INTERFACE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + FT_Error + ps_hints_apply( PS_Hints ps_hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ) + { + PSH_GlyphRec glyphrec; + PSH_Glyph glyph = &glyphrec; + FT_Error error; +#ifdef DEBUG_HINTER + FT_Memory memory; +#endif + FT_Int dimension; + + + /* something to do? */ + if ( outline->n_points == 0 || outline->n_contours == 0 ) + return PSH_Err_Ok; + +#ifdef DEBUG_HINTER + + memory = globals->memory; + + if ( ps_debug_glyph ) + { + psh_glyph_done( ps_debug_glyph ); + FT_FREE( ps_debug_glyph ); + } + + if ( FT_NEW( glyph ) ) + return error; + + ps_debug_glyph = glyph; + +#endif /* DEBUG_HINTER */ + + error = psh_glyph_init( glyph, outline, ps_hints, globals ); + if ( error ) + goto Exit; + + /* try to optimize the y_scale so that the top of non-capital letters + * is aligned on a pixel boundary whenever possible + */ + { + PSH_Dimension dim_x = &glyph->globals->dimension[0]; + PSH_Dimension dim_y = &glyph->globals->dimension[1]; + + FT_Fixed x_scale = dim_x->scale_mult; + FT_Fixed y_scale = dim_y->scale_mult; + + FT_Fixed scaled; + FT_Fixed fitted; + + + scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); + fitted = FT_PIX_ROUND( scaled ); + + if (scaled != fitted ) { + y_scale = FT_MulDiv( y_scale, fitted, scaled ); + + if ( fitted < scaled ) + x_scale -= x_scale / 50; + + psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 ); + } + } + + glyph->do_horz_hints = 1; + glyph->do_vert_hints = 1; + + glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || + hint_mode == FT_RENDER_MODE_LCD ); + + glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || + hint_mode == FT_RENDER_MODE_LCD_V ); + + glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); + + for ( dimension = 0; dimension < 2; dimension++ ) + { + /* load outline coordinates into glyph */ + psh_glyph_load_points( glyph, dimension ); + + /* compute local extrema */ + psh_glyph_compute_extrema( glyph ); + + /* compute aligned stem/hints positions */ + psh_hint_table_align_hints( &glyph->hint_tables[dimension], + glyph->globals, + dimension, + glyph ); + + /* find strong points, align them, then interpolate others */ + psh_glyph_find_strong_points( glyph, dimension ); + if ( dimension == 1 ) + psh_glyph_find_blue_points( &globals->blues, glyph ); + psh_glyph_interpolate_strong_points( glyph, dimension ); + psh_glyph_interpolate_normal_points( glyph, dimension ); + psh_glyph_interpolate_other_points( glyph, dimension ); + + /* save hinted coordinates back to outline */ + psh_glyph_save_points( glyph, dimension ); + } + + Exit: + +#ifndef DEBUG_HINTER + psh_glyph_done( glyph ); +#endif + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshalgo.h b/Utilities/vtkfreetype/src/pshinter/pshalgo.h new file mode 100644 index 0000000..f68de71 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshalgo.h @@ -0,0 +1,255 @@ +/***************************************************************************/ +/* */ +/* pshalgo.h */ +/* */ +/* PostScript hinting algorithm (specification). */ +/* */ +/* Copyright 2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSHALGO_H__ +#define __PSHALGO_H__ + + +#include "pshrec.h" +#include "pshglob.h" +#include FT_TRIGONOMETRY_H + + +FT_BEGIN_HEADER + + + /* handle to Hint structure */ + typedef struct PSH_HintRec_* PSH_Hint; + + /* hint bit-flags */ + typedef enum + { + PSH_HINT_GHOST = PS_HINT_FLAG_GHOST, + PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM, + PSH_HINT_ACTIVE = 4, + PSH_HINT_FITTED = 8 + + } PSH_Hint_Flags; + + +#define psh_hint_is_active( x ) ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 ) +#define psh_hint_is_ghost( x ) ( ( (x)->flags & PSH_HINT_GHOST ) != 0 ) +#define psh_hint_is_fitted( x ) ( ( (x)->flags & PSH_HINT_FITTED ) != 0 ) + +#define psh_hint_activate( x ) (x)->flags |= PSH_HINT_ACTIVE +#define psh_hint_deactivate( x ) (x)->flags &= ~PSH_HINT_ACTIVE +#define psh_hint_set_fitted( x ) (x)->flags |= PSH_HINT_FITTED + + /* hint structure */ + typedef struct PSH_HintRec_ + { + FT_Int org_pos; + FT_Int org_len; + FT_Pos cur_pos; + FT_Pos cur_len; + FT_UInt flags; + PSH_Hint parent; + FT_Int order; + + } PSH_HintRec; + + + /* this is an interpolation zone used for strong points; */ + /* weak points are interpolated according to their strong */ + /* neighbours */ + typedef struct PSH_ZoneRec_ + { + FT_Fixed scale; + FT_Fixed delta; + FT_Pos min; + FT_Pos max; + + } PSH_ZoneRec, *PSH_Zone; + + + typedef struct PSH_Hint_TableRec_ + { + FT_UInt max_hints; + FT_UInt num_hints; + PSH_Hint hints; + PSH_Hint* sort; + PSH_Hint* sort_global; + FT_UInt num_zones; + PSH_ZoneRec* zones; + PSH_Zone zone; + PS_Mask_Table hint_masks; + PS_Mask_Table counter_masks; + + } PSH_Hint_TableRec, *PSH_Hint_Table; + + + typedef struct PSH_PointRec_* PSH_Point; + typedef struct PSH_ContourRec_* PSH_Contour; + + enum + { + PSH_DIR_NONE = 4, + PSH_DIR_UP = -1, + PSH_DIR_DOWN = 1, + PSH_DIR_LEFT = -2, + PSH_DIR_RIGHT = 2 + }; + +#define PSH_DIR_HORIZONTAL 2 +#define PSH_DIR_VERTICAL 1 + +#define PSH_DIR_COMPARE( d1, d2 ) ( (d1) == (d2) || (d1) == -(d2) ) +#define PSH_DIR_IS_HORIZONTAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL ) +#define PSH_DIR_IS_VERTICAL( d ) PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL ) + + + /* the following bit-flags are computed once by the glyph */ + /* analyzer, for both dimensions */ + enum + { + PSH_POINT_OFF = 1, /* point is off the curve */ + PSH_POINT_SMOOTH = 2, /* point is smooth */ + PSH_POINT_INFLEX = 4 /* point is inflection */ + }; + +#define psh_point_is_smooth( p ) ( (p)->flags & PSH_POINT_SMOOTH ) +#define psh_point_is_off( p ) ( (p)->flags & PSH_POINT_OFF ) +#define psh_point_is_inflex( p ) ( (p)->flags & PSH_POINT_INFLEX ) + +#define psh_point_set_smooth( p ) (p)->flags |= PSH_POINT_SMOOTH +#define psh_point_set_off( p ) (p)->flags |= PSH_POINT_OFF +#define psh_point_set_inflex( p ) (p)->flags |= PSH_POINT_INFLEX + + /* the following bit-flags are re-computed for each dimension */ + enum + { + PSH_POINT_STRONG = 16, /* point is strong */ + PSH_POINT_FITTED = 32, /* point is already fitted */ + PSH_POINT_EXTREMUM = 64, /* point is local extremum */ + PSH_POINT_POSITIVE = 128, /* extremum has positive contour flow */ + PSH_POINT_NEGATIVE = 256, /* extremum has negative contour flow */ + PSH_POINT_EDGE_MIN = 512, /* point is aligned to left/bottom stem edge */ + PSH_POINT_EDGE_MAX = 1024 /* point is aligned to top/right stem edge */ + }; + +#define psh_point_is_strong( p ) ( (p)->flags2 & PSH_POINT_STRONG ) +#define psh_point_is_fitted( p ) ( (p)->flags2 & PSH_POINT_FITTED ) +#define psh_point_is_extremum( p ) ( (p)->flags2 & PSH_POINT_EXTREMUM ) +#define psh_point_is_positive( p ) ( (p)->flags2 & PSH_POINT_POSITIVE ) +#define psh_point_is_negative( p ) ( (p)->flags2 & PSH_POINT_NEGATIVE ) +#define psh_point_is_edge_min( p ) ( (p)->flags2 & PSH_POINT_EDGE_MIN ) +#define psh_point_is_edge_max( p ) ( (p)->flags2 & PSH_POINT_EDGE_MAX ) + +#define psh_point_set_strong( p ) (p)->flags2 |= PSH_POINT_STRONG +#define psh_point_set_fitted( p ) (p)->flags2 |= PSH_POINT_FITTED +#define psh_point_set_extremum( p ) (p)->flags2 |= PSH_POINT_EXTREMUM +#define psh_point_set_positive( p ) (p)->flags2 |= PSH_POINT_POSITIVE +#define psh_point_set_negative( p ) (p)->flags2 |= PSH_POINT_NEGATIVE +#define psh_point_set_edge_min( p ) (p)->flags2 |= PSH_POINT_EDGE_MIN +#define psh_point_set_edge_max( p ) (p)->flags2 |= PSH_POINT_EDGE_MAX + + + typedef struct PSH_PointRec_ + { + PSH_Point prev; + PSH_Point next; + PSH_Contour contour; + FT_UInt flags; + FT_UInt flags2; + FT_Char dir_in; + FT_Char dir_out; + FT_Angle angle_in; + FT_Angle angle_out; + PSH_Hint hint; + FT_Pos org_u; + FT_Pos org_v; + FT_Pos cur_u; +#ifdef DEBUG_HINTER + FT_Pos org_x; + FT_Pos cur_x; + FT_Pos org_y; + FT_Pos cur_y; + FT_UInt flags_x; + FT_UInt flags_y; +#endif + + } PSH_PointRec; + + +#define PSH_POINT_EQUAL_ORG( a, b ) ( (a)->org_u == (b)->org_u && \ + (a)->org_v == (b)->org_v ) + +#define PSH_POINT_ANGLE( a, b ) FT_Atan2( (b)->org_u - (a)->org_u, \ + (b)->org_v - (a)->org_v ) + + typedef struct PSH_ContourRec_ + { + PSH_Point start; + FT_UInt count; + + } PSH_ContourRec; + + + typedef struct PSH_GlyphRec_ + { + FT_UInt num_points; + FT_UInt num_contours; + + PSH_Point points; + PSH_Contour contours; + + FT_Memory memory; + FT_Outline* outline; + PSH_Globals globals; + PSH_Hint_TableRec hint_tables[2]; + + FT_Bool vertical; + FT_Int major_dir; + FT_Int minor_dir; + + FT_Bool do_horz_hints; + FT_Bool do_vert_hints; + FT_Bool do_horz_snapping; + FT_Bool do_vert_snapping; + FT_Bool do_stem_adjust; + + } PSH_GlyphRec, *PSH_Glyph; + + +#ifdef DEBUG_HINTER + extern PSH_Hint_Table ps_debug_hint_table; + + typedef void + (*PSH_HintFunc)( PSH_Hint hint, + FT_Bool vertical ); + + extern PSH_HintFunc ps_debug_hint_func; + + extern PSH_Glyph ps_debug_glyph; +#endif + + + extern FT_Error + ps_hints_apply( PS_Hints ps_hints, + FT_Outline* outline, + PSH_Globals globals, + FT_Render_Mode hint_mode ); + + +FT_END_HEADER + + +#endif /* __PSHALGO_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshglob.c b/Utilities/vtkfreetype/src/pshinter/pshglob.c new file mode 100644 index 0000000..21d45e9 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshglob.c @@ -0,0 +1,750 @@ +/***************************************************************************/ +/* */ +/* pshglob.c */ +/* */ +/* PostScript hinter global hinting management (body). */ +/* Inspired by the new auto-hinter module. */ +/* */ +/* Copyright 2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_INTERNAL_OBJECTS_H +#include "pshglob.h" + +#ifdef DEBUG_HINTER + PSH_Globals ps_debug_globals = 0; +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** STANDARD WIDTHS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /* scale the widths/heights table */ + static void + psh_globals_scale_widths( PSH_Globals globals, + FT_UInt direction ) + { + PSH_Dimension dim = &globals->dimension[direction]; + PSH_Widths stdw = &dim->stdw; + FT_UInt count = stdw->count; + PSH_Width width = stdw->widths; + PSH_Width stand = width; /* standard width/height */ + FT_Fixed scale = dim->scale_mult; + + + if ( count > 0 ) + { + width->cur = FT_MulFix( width->org, scale ); + width->fit = FT_PIX_ROUND( width->cur ); + + width++; + count--; + + for ( ; count > 0; count--, width++ ) + { + FT_Pos w, dist; + + + w = FT_MulFix( width->org, scale ); + dist = w - stand->cur; + + if ( dist < 0 ) + dist = -dist; + + if ( dist < 128 ) + w = stand->cur; + + width->cur = w; + width->fit = FT_PIX_ROUND( w ); + } + } + } + + +#if 0 + + /* org_width is is font units, result in device pixels, 26.6 format */ + FT_LOCAL_DEF( FT_Pos ) + psh_dimension_snap_width( PSH_Dimension dimension, + FT_Int org_width ) + { + FT_UInt n; + FT_Pos width = FT_MulFix( org_width, dimension->scale_mult ); + FT_Pos best = 64 + 32 + 2; + FT_Pos reference = width; + + + for ( n = 0; n < dimension->stdw.count; n++ ) + { + FT_Pos w; + FT_Pos dist; + + + w = dimension->stdw.widths[n].cur; + dist = width - w; + if ( dist < 0 ) + dist = -dist; + if ( dist < best ) + { + best = dist; + reference = w; + } + } + + if ( width >= reference ) + { + width -= 0x21; + if ( width < reference ) + width = reference; + } + else + { + width += 0x21; + if ( width > reference ) + width = reference; + } + + return width; + } + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** BLUE ZONES *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + psh_blues_set_zones_0( PSH_Blues target, + FT_Bool is_others, + FT_UInt read_count, + FT_Short* read, + PSH_Blue_Table top_table, + PSH_Blue_Table bot_table ) + { + FT_UInt count_top = top_table->count; + FT_UInt count_bot = bot_table->count; + FT_Bool first = 1; + + FT_UNUSED( target ); + + + for ( ; read_count > 0; read_count -= 2 ) + { + FT_Int reference, delta; + FT_UInt count; + PSH_Blue_Zone zones, zone; + FT_Bool top; + + + /* read blue zone entry, and select target top/bottom zone */ + top = 0; + if ( first || is_others ) + { + reference = read[1]; + delta = read[0] - reference; + + zones = bot_table->zones; + count = count_bot; + first = 0; + } + else + { + reference = read[0]; + delta = read[1] - reference; + + zones = top_table->zones; + count = count_top; + top = 1; + } + + /* insert into sorted table */ + zone = zones; + for ( ; count > 0; count--, zone++ ) + { + if ( reference < zone->org_ref ) + break; + + if ( reference == zone->org_ref ) + { + FT_Int delta0 = zone->org_delta; + + + /* we have two zones on the same reference position -- */ + /* only keep the largest one */ + if ( delta < 0 ) + { + if ( delta < delta0 ) + zone->org_delta = delta; + } + else + { + if ( delta > delta0 ) + zone->org_delta = delta; + } + goto Skip; + } + } + + for ( ; count > 0; count-- ) + zone[count] = zone[count-1]; + + zone->org_ref = reference; + zone->org_delta = delta; + + if ( top ) + count_top++; + else + count_bot++; + + Skip: + read += 2; + } + + top_table->count = count_top; + bot_table->count = count_bot; + } + + + /* Re-read blue zones from the original fonts and store them into out */ + /* private structure. This function re-orders, sanitizes and */ + /* fuzz-expands the zones as well. */ + static void + psh_blues_set_zones( PSH_Blues target, + FT_UInt count, + FT_Short* blues, + FT_UInt count_others, + FT_Short* other_blues, + FT_Int fuzz, + FT_Int family ) + { + PSH_Blue_Table top_table, bot_table; + FT_Int count_top, count_bot; + + + if ( family ) + { + top_table = &target->family_top; + bot_table = &target->family_bottom; + } + else + { + top_table = &target->normal_top; + bot_table = &target->normal_bottom; + } + + /* read the input blue zones, and build two sorted tables */ + /* (one for the top zones, the other for the bottom zones) */ + top_table->count = 0; + bot_table->count = 0; + + /* first, the blues */ + psh_blues_set_zones_0( target, 0, + count, blues, top_table, bot_table ); + psh_blues_set_zones_0( target, 1, + count_others, other_blues, top_table, bot_table ); + + count_top = top_table->count; + count_bot = bot_table->count; + + /* sanitize top table */ + if ( count_top > 0 ) + { + PSH_Blue_Zone zone = top_table->zones; + + + for ( count = count_top; count > 0; count--, zone++ ) + { + FT_Int delta; + + + if ( count > 1 ) + { + delta = zone[1].org_ref - zone[0].org_ref; + if ( zone->org_delta > delta ) + zone->org_delta = delta; + } + + zone->org_bottom = zone->org_ref; + zone->org_top = zone->org_delta + zone->org_ref; + } + } + + /* sanitize bottom table */ + if ( count_bot > 0 ) + { + PSH_Blue_Zone zone = bot_table->zones; + + + for ( count = count_bot; count > 0; count--, zone++ ) + { + FT_Int delta; + + + if ( count > 1 ) + { + delta = zone[0].org_ref - zone[1].org_ref; + if ( zone->org_delta < delta ) + zone->org_delta = delta; + } + + zone->org_top = zone->org_ref; + zone->org_bottom = zone->org_delta + zone->org_ref; + } + } + + /* expand top and bottom tables with blue fuzz */ + { + FT_Int dim, top, bot, delta; + PSH_Blue_Zone zone; + + + zone = top_table->zones; + count = count_top; + + for ( dim = 1; dim >= 0; dim-- ) + { + if ( count > 0 ) + { + /* expand the bottom of the lowest zone normally */ + zone->org_bottom -= fuzz; + + /* expand the top and bottom of intermediate zones; */ + /* checking that the interval is smaller than the fuzz */ + top = zone->org_top; + + for ( count--; count > 0; count-- ) + { + bot = zone[1].org_bottom; + delta = bot - top; + + if ( delta < 2 * fuzz ) + zone[0].org_top = zone[1].org_bottom = top + delta / 2; + else + { + zone[0].org_top = top + fuzz; + zone[1].org_bottom = bot - fuzz; + } + + zone++; + top = zone->org_top; + } + + /* expand the top of the highest zone normally */ + zone->org_top = top + fuzz; + } + zone = bot_table->zones; + count = count_bot; + } + } + } + + + /* reset the blues table when the device transform changes */ + static void + psh_blues_scale_zones( PSH_Blues blues, + FT_Fixed scale, + FT_Pos delta ) + { + FT_UInt count; + FT_UInt num; + PSH_Blue_Table table = 0; + + /* */ + /* Determine whether we need to suppress overshoots or */ + /* not. We simply need to compare the vertical scale */ + /* parameter to the raw bluescale value. Here is why: */ + /* */ + /* We need to suppress overshoots for all pointsizes. */ + /* At 300dpi that satisfies: */ + /* */ + /* pointsize < 240*bluescale + 0.49 */ + /* */ + /* This corresponds to: */ + /* */ + /* pixelsize < 1000*bluescale + 49/24 */ + /* */ + /* scale*EM_Size < 1000*bluescale + 49/24 */ + /* */ + /* However, for normal Type 1 fonts, EM_Size is 1000! */ + /* We thus only check: */ + /* */ + /* scale < bluescale + 49/24000 */ + /* */ + /* which we shorten to */ + /* */ + /* "scale < bluescale" */ + /* */ + /* Note that `blue_scale' is stored 1000 times its real */ + /* value, and that `scale' converts from font units to */ + /* fractional pixels. */ + /* */ + + /* 1000 / 64 = 125 / 8 */ + if ( scale >= 0x20C49BAL ) + blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 ); + else + blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 ); + + /* */ + /* The blue threshold is the font units distance under */ + /* which overshoots are suppressed due to the BlueShift */ + /* even if the scale is greater than BlueScale. */ + /* */ + /* It is the smallest distance such that */ + /* */ + /* dist <= BlueShift && dist*scale <= 0.5 pixels */ + /* */ + { + FT_Int threshold = blues->blue_shift; + + + while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 ) + threshold--; + + blues->blue_threshold = threshold; + } + + for ( num = 0; num < 4; num++ ) + { + PSH_Blue_Zone zone; + + + switch ( num ) + { + case 0: + table = &blues->normal_top; + break; + case 1: + table = &blues->normal_bottom; + break; + case 2: + table = &blues->family_top; + break; + default: + table = &blues->family_bottom; + break; + } + + zone = table->zones; + count = table->count; + for ( ; count > 0; count--, zone++ ) + { + zone->cur_top = FT_MulFix( zone->org_top, scale ) + delta; + zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta; + zone->cur_ref = FT_MulFix( zone->org_ref, scale ) + delta; + zone->cur_delta = FT_MulFix( zone->org_delta, scale ); + + /* round scaled reference position */ + zone->cur_ref = FT_PIX_ROUND( zone->cur_ref ); + +#if 0 + if ( zone->cur_ref > zone->cur_top ) + zone->cur_ref -= 64; + else if ( zone->cur_ref < zone->cur_bottom ) + zone->cur_ref += 64; +#endif + } + } + + /* process the families now */ + + for ( num = 0; num < 2; num++ ) + { + PSH_Blue_Zone zone1, zone2; + FT_UInt count1, count2; + PSH_Blue_Table normal, family; + + + switch ( num ) + { + case 0: + normal = &blues->normal_top; + family = &blues->family_top; + break; + + default: + normal = &blues->normal_bottom; + family = &blues->family_bottom; + } + + zone1 = normal->zones; + count1 = normal->count; + + for ( ; count1 > 0; count1--, zone1++ ) + { + /* try to find a family zone whose reference position is less */ + /* than 1 pixel far from the current zone */ + zone2 = family->zones; + count2 = family->count; + + for ( ; count2 > 0; count2--, zone2++ ) + { + FT_Pos Delta; + + + Delta = zone1->org_ref - zone2->org_ref; + if ( Delta < 0 ) + Delta = -Delta; + + if ( FT_MulFix( Delta, scale ) < 64 ) + { + zone1->cur_top = zone2->cur_top; + zone1->cur_bottom = zone2->cur_bottom; + zone1->cur_ref = zone2->cur_ref; + zone1->cur_delta = zone2->cur_delta; + break; + } + } + } + } + } + + + FT_LOCAL_DEF( void ) + psh_blues_snap_stem( PSH_Blues blues, + FT_Int stem_top, + FT_Int stem_bot, + PSH_Alignment alignment ) + { + PSH_Blue_Table table; + FT_UInt count; + FT_Pos delta; + PSH_Blue_Zone zone; + FT_Int no_shoots; + + + alignment->align = PSH_BLUE_ALIGN_NONE; + + no_shoots = blues->no_overshoots; + + /* look up stem top in top zones table */ + table = &blues->normal_top; + count = table->count; + zone = table->zones; + + for ( ; count > 0; count--, zone++ ) + { + delta = stem_top - zone->org_bottom; + if ( delta < -blues->blue_fuzz ) + break; + + if ( stem_top <= zone->org_top + blues->blue_fuzz ) + { + if ( no_shoots || delta <= blues->blue_threshold ) + { + alignment->align |= PSH_BLUE_ALIGN_TOP; + alignment->align_top = zone->cur_ref; + } + break; + } + } + + /* look up stem bottom in bottom zones table */ + table = &blues->normal_bottom; + count = table->count; + zone = table->zones + count-1; + + for ( ; count > 0; count--, zone-- ) + { + delta = zone->org_top - stem_bot; + if ( delta < -blues->blue_fuzz ) + break; + + if ( stem_bot >= zone->org_bottom - blues->blue_fuzz ) + { + if ( no_shoots || delta < blues->blue_threshold ) + { + alignment->align |= PSH_BLUE_ALIGN_BOT; + alignment->align_bot = zone->cur_ref; + } + break; + } + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** GLOBAL HINTS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + psh_globals_destroy( PSH_Globals globals ) + { + if ( globals ) + { + FT_Memory memory; + + + memory = globals->memory; + globals->dimension[0].stdw.count = 0; + globals->dimension[1].stdw.count = 0; + + globals->blues.normal_top.count = 0; + globals->blues.normal_bottom.count = 0; + globals->blues.family_top.count = 0; + globals->blues.family_bottom.count = 0; + + FT_FREE( globals ); + +#ifdef DEBUG_HINTER + ps_debug_globals = 0; +#endif + } + } + + + static FT_Error + psh_globals_new( FT_Memory memory, + T1_Private* priv, + PSH_Globals *aglobals ) + { + PSH_Globals globals; + FT_Error error; + + + if ( !FT_NEW( globals ) ) + { + FT_UInt count; + FT_Short* read; + + + globals->memory = memory; + + /* copy standard widths */ + { + PSH_Dimension dim = &globals->dimension[1]; + PSH_Width write = dim->stdw.widths; + + + write->org = priv->standard_width[0]; + write++; + + read = priv->snap_widths; + for ( count = priv->num_snap_widths; count > 0; count-- ) + { + write->org = *read; + write++; + read++; + } + + dim->stdw.count = priv->num_snap_widths + 1; + } + + /* copy standard heights */ + { + PSH_Dimension dim = &globals->dimension[0]; + PSH_Width write = dim->stdw.widths; + + + write->org = priv->standard_height[0]; + write++; + read = priv->snap_heights; + for ( count = priv->num_snap_heights; count > 0; count-- ) + { + write->org = *read; + write++; + read++; + } + + dim->stdw.count = priv->num_snap_heights + 1; + } + + /* copy blue zones */ + psh_blues_set_zones( &globals->blues, priv->num_blue_values, + priv->blue_values, priv->num_other_blues, + priv->other_blues, priv->blue_fuzz, 0 ); + + psh_blues_set_zones( &globals->blues, priv->num_family_blues, + priv->family_blues, priv->num_family_other_blues, + priv->family_other_blues, priv->blue_fuzz, 1 ); + + globals->blues.blue_scale = priv->blue_scale; + globals->blues.blue_shift = priv->blue_shift; + globals->blues.blue_fuzz = priv->blue_fuzz; + + globals->dimension[0].scale_mult = 0; + globals->dimension[0].scale_delta = 0; + globals->dimension[1].scale_mult = 0; + globals->dimension[1].scale_delta = 0; + +#ifdef DEBUG_HINTER + ps_debug_globals = globals; +#endif + } + + *aglobals = globals; + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + psh_globals_set_scale( PSH_Globals globals, + FT_Fixed x_scale, + FT_Fixed y_scale, + FT_Fixed x_delta, + FT_Fixed y_delta ) + { + PSH_Dimension dim = &globals->dimension[0]; + + + dim = &globals->dimension[0]; + if ( x_scale != dim->scale_mult || + x_delta != dim->scale_delta ) + { + dim->scale_mult = x_scale; + dim->scale_delta = x_delta; + + psh_globals_scale_widths( globals, 0 ); + } + + dim = &globals->dimension[1]; + if ( y_scale != dim->scale_mult || + y_delta != dim->scale_delta ) + { + dim->scale_mult = y_scale; + dim->scale_delta = y_delta; + + psh_globals_scale_widths( globals, 1 ); + psh_blues_scale_zones( &globals->blues, y_scale, y_delta ); + } + + return 0; + } + + + FT_LOCAL_DEF( void ) + psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ) + { + funcs->create = psh_globals_new; + funcs->set_scale = psh_globals_set_scale; + funcs->destroy = psh_globals_destroy; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshglob.h b/Utilities/vtkfreetype/src/pshinter/pshglob.h new file mode 100644 index 0000000..c511626 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshglob.h @@ -0,0 +1,196 @@ +/***************************************************************************/ +/* */ +/* pshglob.h */ +/* */ +/* PostScript hinter global hinting management. */ +/* */ +/* Copyright 2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSHGLOB_H__ +#define __PSHGLOB_H__ + + +#include FT_FREETYPE_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** GLOBAL HINTS INTERNALS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* @constant: */ + /* PS_GLOBALS_MAX_BLUE_ZONES */ + /* */ + /* @description: */ + /* The maximum number of blue zones in a font global hints structure. */ + /* See @PS_Globals_BluesRec. */ + /* */ +#define PS_GLOBALS_MAX_BLUE_ZONES 16 + + + /*************************************************************************/ + /* */ + /* @constant: */ + /* PS_GLOBALS_MAX_STD_WIDTHS */ + /* */ + /* @description: */ + /* The maximum number of standard and snap widths in either the */ + /* horizontal or vertical direction. See @PS_Globals_WidthsRec. */ + /* */ +#define PS_GLOBALS_MAX_STD_WIDTHS 16 + + + /* standard and snap width */ + typedef struct PSH_WidthRec_ + { + FT_Int org; + FT_Pos cur; + FT_Pos fit; + + } PSH_WidthRec, *PSH_Width; + + + /* standard and snap widths table */ + typedef struct PSH_WidthsRec_ + { + FT_UInt count; + PSH_WidthRec widths[PS_GLOBALS_MAX_STD_WIDTHS]; + + } PSH_WidthsRec, *PSH_Widths; + + + typedef struct PSH_DimensionRec_ + { + PSH_WidthsRec stdw; + FT_Fixed scale_mult; + FT_Fixed scale_delta; + + } PSH_DimensionRec, *PSH_Dimension; + + + /* blue zone descriptor */ + typedef struct PSH_Blue_ZoneRec_ + { + FT_Int org_ref; + FT_Int org_delta; + FT_Int org_top; + FT_Int org_bottom; + + FT_Pos cur_ref; + FT_Pos cur_delta; + FT_Pos cur_bottom; + FT_Pos cur_top; + + } PSH_Blue_ZoneRec, *PSH_Blue_Zone; + + + typedef struct PSH_Blue_TableRec_ + { + FT_UInt count; + PSH_Blue_ZoneRec zones[PS_GLOBALS_MAX_BLUE_ZONES]; + + } PSH_Blue_TableRec, *PSH_Blue_Table; + + + /* blue zones table */ + typedef struct PSH_BluesRec_ + { + PSH_Blue_TableRec normal_top; + PSH_Blue_TableRec normal_bottom; + PSH_Blue_TableRec family_top; + PSH_Blue_TableRec family_bottom; + + FT_Fixed blue_scale; + FT_Int blue_shift; + FT_Int blue_threshold; + FT_Int blue_fuzz; + FT_Bool no_overshoots; + + } PSH_BluesRec, *PSH_Blues; + + + /* font globals. */ + /* dimension 0 => X coordinates + vertical hints/stems */ + /* dimension 1 => Y coordinates + horizontal hints/stems */ + typedef struct PSH_GlobalsRec_ + { + FT_Memory memory; + PSH_DimensionRec dimension[2]; + PSH_BluesRec blues; + + } PSH_GlobalsRec; + + +#define PSH_BLUE_ALIGN_NONE 0 +#define PSH_BLUE_ALIGN_TOP 1 +#define PSH_BLUE_ALIGN_BOT 2 + + + typedef struct PSH_AlignmentRec_ + { + int align; + FT_Pos align_top; + FT_Pos align_bot; + + } PSH_AlignmentRec, *PSH_Alignment; + + + FT_LOCAL( void ) + psh_globals_funcs_init( PSH_Globals_FuncsRec* funcs ); + + +#if 0 + /* snap a stem width to fitter coordinates. `org_width' is in font */ + /* units. The result is in device pixels (26.6 format). */ + FT_LOCAL( FT_Pos ) + psh_dimension_snap_width( PSH_Dimension dimension, + FT_Int org_width ); +#endif + + FT_LOCAL( FT_Error ) + psh_globals_set_scale( PSH_Globals globals, + FT_Fixed x_scale, + FT_Fixed y_scale, + FT_Fixed x_delta, + FT_Fixed y_delta ); + + /* snap a stem to one or two blue zones */ + FT_LOCAL( void ) + psh_blues_snap_stem( PSH_Blues blues, + FT_Int stem_top, + FT_Int stem_bot, + PSH_Alignment alignment ); + /* */ + +#ifdef DEBUG_HINTER + extern PSH_Globals ps_debug_globals; +#endif + + +FT_END_HEADER + + +#endif /* __PSHGLOB_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshinter.c b/Utilities/vtkfreetype/src/pshinter/pshinter.c new file mode 100644 index 0000000..8e3f193 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshinter.c @@ -0,0 +1,28 @@ +/***************************************************************************/ +/* */ +/* pshinter.c */ +/* */ +/* FreeType PostScript Hinting module */ +/* */ +/* Copyright 2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "pshrec.c" +#include "pshglob.c" +#include "pshalgo.c" +#include "pshmod.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshmod.c b/Utilities/vtkfreetype/src/pshinter/pshmod.c new file mode 100644 index 0000000..5b18684 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshmod.c @@ -0,0 +1,120 @@ +/***************************************************************************/ +/* */ +/* pshmod.c */ +/* */ +/* FreeType PostScript hinter module implementation (body). */ +/* */ +/* Copyright 2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include "pshrec.h" +#include "pshalgo.h" + + + /* the Postscript Hinter module structure */ + typedef struct PS_Hinter_Module_Rec_ + { + FT_ModuleRec root; + PS_HintsRec ps_hints; + + PSH_Globals_FuncsRec globals_funcs; + T1_Hints_FuncsRec t1_funcs; + T2_Hints_FuncsRec t2_funcs; + + } PS_Hinter_ModuleRec, *PS_Hinter_Module; + + + /* finalize module */ + FT_CALLBACK_DEF( void ) + ps_hinter_done( PS_Hinter_Module module ) + { + module->t1_funcs.hints = NULL; + module->t2_funcs.hints = NULL; + + ps_hints_done( &module->ps_hints ); + } + + + /* initialize module, create hints recorder and the interface */ + FT_CALLBACK_DEF( FT_Error ) + ps_hinter_init( PS_Hinter_Module module ) + { + FT_Memory memory = module->root.memory; + + + ps_hints_init( &module->ps_hints, memory ); + + psh_globals_funcs_init( &module->globals_funcs ); + + t1_hints_funcs_init( &module->t1_funcs ); + module->t1_funcs.hints = (T1_Hints)&module->ps_hints; + + t2_hints_funcs_init( &module->t2_funcs ); + module->t2_funcs.hints = (T2_Hints)&module->ps_hints; + + return 0; + } + + + /* returns global hints interface */ + FT_CALLBACK_DEF( PSH_Globals_Funcs ) + pshinter_get_globals_funcs( FT_Module module ) + { + return &((PS_Hinter_Module)module)->globals_funcs; + } + + + /* return Type 1 hints interface */ + FT_CALLBACK_DEF( T1_Hints_Funcs ) + pshinter_get_t1_funcs( FT_Module module ) + { + return &((PS_Hinter_Module)module)->t1_funcs; + } + + + /* return Type 2 hints interface */ + FT_CALLBACK_DEF( T2_Hints_Funcs ) + pshinter_get_t2_funcs( FT_Module module ) + { + return &((PS_Hinter_Module)module)->t2_funcs; + } + + + static + const PSHinter_Interface pshinter_interface = + { + pshinter_get_globals_funcs, + pshinter_get_t1_funcs, + pshinter_get_t2_funcs + }; + + + FT_CALLBACK_TABLE_DEF + const FT_Module_Class pshinter_module_class = + { + 0, + sizeof ( PS_Hinter_ModuleRec ), + "pshinter", + 0x10000L, + 0x20000L, + + &pshinter_interface, /* module-specific interface */ + + (FT_Module_Constructor)ps_hinter_init, + (FT_Module_Destructor) ps_hinter_done, + (FT_Module_Requester) 0 /* no additional interface for now */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshmod.h b/Utilities/vtkfreetype/src/pshinter/pshmod.h new file mode 100644 index 0000000..1a91025 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshmod.h @@ -0,0 +1,39 @@ +/***************************************************************************/ +/* */ +/* pshmod.h */ +/* */ +/* PostScript hinter module interface (specification). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSHMOD_H__ +#define __PSHMOD_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Module_Class ) pshinter_module_class; + + +FT_END_HEADER + + +#endif /* __PSHMOD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshnterr.h b/Utilities/vtkfreetype/src/pshinter/pshnterr.h new file mode 100644 index 0000000..3c0029f --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshnterr.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* pshnterr.h */ +/* */ +/* PS Hinter error codes (specification only). */ +/* */ +/* Copyright 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the PSHinter error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __PSHNTERR_H__ +#define __PSHNTERR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX PSH_Err_ +#define FT_ERR_BASE FT_Mod_Err_PShinter + +#include FT_ERRORS_H + +#endif /* __PSHNTERR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshrec.c b/Utilities/vtkfreetype/src/pshinter/pshrec.c new file mode 100644 index 0000000..648de18 --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshrec.c @@ -0,0 +1,1215 @@ +/***************************************************************************/ +/* */ +/* pshrec.c */ +/* */ +/* FreeType PostScript hints recorder (body). */ +/* */ +/* Copyright 2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include "pshrec.h" +#include "pshalgo.h" + +#include "pshnterr.h" + +#undef FT_COMPONENT +#define FT_COMPONENT trace_pshrec + +#ifdef DEBUG_HINTER + PS_Hints ps_debug_hints = 0; + int ps_debug_no_horz_hints = 0; + int ps_debug_no_vert_hints = 0; +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS_HINT MANAGEMENT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* destroy hints table */ + static void + ps_hint_table_done( PS_Hint_Table table, + FT_Memory memory ) + { + FT_FREE( table->hints ); + table->num_hints = 0; + table->max_hints = 0; + } + + + /* ensure that a table can contain "count" elements */ + static FT_Error + ps_hint_table_ensure( PS_Hint_Table table, + FT_UInt count, + FT_Memory memory ) + { + FT_UInt old_max = table->max_hints; + FT_UInt new_max = count; + FT_Error error = 0; + + + if ( new_max > old_max ) + { + /* try to grow the table */ + new_max = FT_PAD_CEIL( new_max, 8 ); + if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) ) + table->max_hints = new_max; + } + return error; + } + + + static FT_Error + ps_hint_table_alloc( PS_Hint_Table table, + FT_Memory memory, + PS_Hint *ahint ) + { + FT_Error error = 0; + FT_UInt count; + PS_Hint hint = 0; + + + count = table->num_hints; + count++; + + if ( count >= table->max_hints ) + { + error = ps_hint_table_ensure( table, count, memory ); + if ( error ) + goto Exit; + } + + hint = table->hints + count - 1; + hint->pos = 0; + hint->len = 0; + hint->flags = 0; + + table->num_hints = count; + + Exit: + *ahint = hint; + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS_MASK MANAGEMENT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* destroy mask */ + static void + ps_mask_done( PS_Mask mask, + FT_Memory memory ) + { + FT_FREE( mask->bytes ); + mask->num_bits = 0; + mask->max_bits = 0; + mask->end_point = 0; + } + + + /* ensure that a mask can contain "count" bits */ + static FT_Error + ps_mask_ensure( PS_Mask mask, + FT_UInt count, + FT_Memory memory ) + { + FT_UInt old_max = ( mask->max_bits + 7 ) >> 3; + FT_UInt new_max = ( count + 7 ) >> 3; + FT_Error error = 0; + + + if ( new_max > old_max ) + { + new_max = FT_PAD_CEIL( new_max, 8 ); + if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) ) + mask->max_bits = new_max * 8; + } + return error; + } + + + /* test a bit value in a given mask */ + static FT_Int + ps_mask_test_bit( PS_Mask mask, + FT_Int idx ) + { + if ( (FT_UInt)idx >= mask->num_bits ) + return 0; + + return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) ); + } + + + /* clear a given bit */ + static void + ps_mask_clear_bit( PS_Mask mask, + FT_Int idx ) + { + FT_Byte* p; + + + if ( (FT_UInt)idx >= mask->num_bits ) + return; + + p = mask->bytes + ( idx >> 3 ); + p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) ); + } + + + /* set a given bit, possibly grow the mask */ + static FT_Error + ps_mask_set_bit( PS_Mask mask, + FT_Int idx, + FT_Memory memory ) + { + FT_Error error = 0; + FT_Byte* p; + + + if ( idx < 0 ) + goto Exit; + + if ( (FT_UInt)idx >= mask->num_bits ) + { + error = ps_mask_ensure( mask, idx + 1, memory ); + if ( error ) + goto Exit; + + mask->num_bits = idx + 1; + } + + p = mask->bytes + ( idx >> 3 ); + p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) ); + + Exit: + return error; + } + + + /* destroy mask table */ + static void + ps_mask_table_done( PS_Mask_Table table, + FT_Memory memory ) + { + FT_UInt count = table->max_masks; + PS_Mask mask = table->masks; + + + for ( ; count > 0; count--, mask++ ) + ps_mask_done( mask, memory ); + + FT_FREE( table->masks ); + table->num_masks = 0; + table->max_masks = 0; + } + + + /* ensure that a mask table can contain "count" masks */ + static FT_Error + ps_mask_table_ensure( PS_Mask_Table table, + FT_UInt count, + FT_Memory memory ) + { + FT_UInt old_max = table->max_masks; + FT_UInt new_max = count; + FT_Error error = 0; + + + if ( new_max > old_max ) + { + new_max = FT_PAD_CEIL( new_max, 8 ); + if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) ) + table->max_masks = new_max; + } + return error; + } + + + /* allocate a new mask in a table */ + static FT_Error + ps_mask_table_alloc( PS_Mask_Table table, + FT_Memory memory, + PS_Mask *amask ) + { + FT_UInt count; + FT_Error error = 0; + PS_Mask mask = 0; + + + count = table->num_masks; + count++; + + if ( count > table->max_masks ) + { + error = ps_mask_table_ensure( table, count, memory ); + if ( error ) + goto Exit; + } + + mask = table->masks + count - 1; + mask->num_bits = 0; + mask->end_point = 0; + table->num_masks = count; + + Exit: + *amask = mask; + return error; + } + + + /* return last hint mask in a table, create one if the table is empty */ + static FT_Error + ps_mask_table_last( PS_Mask_Table table, + FT_Memory memory, + PS_Mask *amask ) + { + FT_Error error = 0; + FT_UInt count; + PS_Mask mask; + + + count = table->num_masks; + if ( count == 0 ) + { + error = ps_mask_table_alloc( table, memory, &mask ); + if ( error ) + goto Exit; + } + else + mask = table->masks + count - 1; + + Exit: + *amask = mask; + return error; + } + + + /* set a new mask to a given bit range */ + static FT_Error + ps_mask_table_set_bits( PS_Mask_Table table, + FT_Byte* source, + FT_UInt bit_pos, + FT_UInt bit_count, + FT_Memory memory ) + { + FT_Error error = 0; + PS_Mask mask; + + + error = ps_mask_table_last( table, memory, &mask ); + if ( error ) + goto Exit; + + error = ps_mask_ensure( mask, bit_count, memory ); + if ( error ) + goto Exit; + + mask->num_bits = bit_count; + + /* now, copy bits */ + { + FT_Byte* read = source + ( bit_pos >> 3 ); + FT_Int rmask = 0x80 >> ( bit_pos & 7 ); + FT_Byte* write = mask->bytes; + FT_Int wmask = 0x80; + FT_Int val; + + + for ( ; bit_count > 0; bit_count-- ) + { + val = write[0] & ~wmask; + + if ( read[0] & rmask ) + val |= wmask; + + write[0] = (FT_Byte)val; + + rmask >>= 1; + if ( rmask == 0 ) + { + read++; + rmask = 0x80; + } + + wmask >>= 1; + if ( wmask == 0 ) + { + write++; + wmask = 0x80; + } + } + } + + Exit: + return error; + } + + + /* test whether two masks in a table intersect */ + static FT_Int + ps_mask_table_test_intersect( PS_Mask_Table table, + FT_Int index1, + FT_Int index2 ) + { + PS_Mask mask1 = table->masks + index1; + PS_Mask mask2 = table->masks + index2; + FT_Byte* p1 = mask1->bytes; + FT_Byte* p2 = mask2->bytes; + FT_UInt count1 = mask1->num_bits; + FT_UInt count2 = mask2->num_bits; + FT_UInt count; + + + count = ( count1 <= count2 ) ? count1 : count2; + for ( ; count >= 8; count -= 8 ) + { + if ( p1[0] & p2[0] ) + return 1; + + p1++; + p2++; + } + + if ( count == 0 ) + return 0; + + return ( p1[0] & p2[0] ) & ~( 0xFF >> count ); + } + + + /* merge two masks, used by ps_mask_table_merge_all */ + static FT_Error + ps_mask_table_merge( PS_Mask_Table table, + FT_Int index1, + FT_Int index2, + FT_Memory memory ) + { + FT_UInt temp; + FT_Error error = 0; + + + /* swap index1 and index2 so that index1 < index2 */ + if ( index1 > index2 ) + { + temp = index1; + index1 = index2; + index2 = temp; + } + + if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks ) + { + /* we need to merge the bitsets of index1 and index2 with a */ + /* simple union */ + PS_Mask mask1 = table->masks + index1; + PS_Mask mask2 = table->masks + index2; + FT_UInt count1 = mask1->num_bits; + FT_UInt count2 = mask2->num_bits; + FT_Int delta; + + + if ( count2 > 0 ) + { + FT_UInt pos; + FT_Byte* read; + FT_Byte* write; + + + /* if "count2" is greater than "count1", we need to grow the */ + /* first bitset, and clear the highest bits */ + if ( count2 > count1 ) + { + error = ps_mask_ensure( mask1, count2, memory ); + if ( error ) + goto Exit; + + for ( pos = count1; pos < count2; pos++ ) + ps_mask_clear_bit( mask1, pos ); + } + + /* merge (unite) the bitsets */ + read = mask2->bytes; + write = mask1->bytes; + pos = (FT_UInt)( ( count2 + 7 ) >> 3 ); + + for ( ; pos > 0; pos-- ) + { + write[0] = (FT_Byte)( write[0] | read[0] ); + write++; + read++; + } + } + + /* Now, remove "mask2" from the list. We need to keep the masks */ + /* sorted in order of importance, so move table elements. */ + mask2->num_bits = 0; + mask2->end_point = 0; + + delta = table->num_masks - 1 - index2; /* number of masks to move */ + if ( delta > 0 ) + { + /* move to end of table for reuse */ + PS_MaskRec dummy = *mask2; + + + ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) ); + + mask2[delta] = dummy; + } + + table->num_masks--; + } + else + FT_ERROR(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n", + index1, index2 )); + + Exit: + return error; + } + + + /* Try to merge all masks in a given table. This is used to merge */ + /* all counter masks into independent counter "paths". */ + /* */ + static FT_Error + ps_mask_table_merge_all( PS_Mask_Table table, + FT_Memory memory ) + { + FT_Int index1, index2; + FT_Error error = 0; + + + for ( index1 = table->num_masks - 1; index1 > 0; index1-- ) + { + for ( index2 = index1 - 1; index2 >= 0; index2-- ) + { + if ( ps_mask_table_test_intersect( table, index1, index2 ) ) + { + error = ps_mask_table_merge( table, index2, index1, memory ); + if ( error ) + goto Exit; + + break; + } + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS_DIMENSION MANAGEMENT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /* finalize a given dimension */ + static void + ps_dimension_done( PS_Dimension dimension, + FT_Memory memory ) + { + ps_mask_table_done( &dimension->counters, memory ); + ps_mask_table_done( &dimension->masks, memory ); + ps_hint_table_done( &dimension->hints, memory ); + } + + + /* initialize a given dimension */ + static void + ps_dimension_init( PS_Dimension dimension ) + { + dimension->hints.num_hints = 0; + dimension->masks.num_masks = 0; + dimension->counters.num_masks = 0; + } + + +#if 0 + + /* set a bit at a given index in the current hint mask */ + static FT_Error + ps_dimension_set_mask_bit( PS_Dimension dim, + FT_UInt idx, + FT_Memory memory ) + { + PS_Mask mask; + FT_Error error = 0; + + + /* get last hint mask */ + error = ps_mask_table_last( &dim->masks, memory, &mask ); + if ( error ) + goto Exit; + + error = ps_mask_set_bit( mask, idx, memory ); + + Exit: + return error; + } + +#endif + + /* set the end point in a mask, called from "End" & "Reset" methods */ + static void + ps_dimension_end_mask( PS_Dimension dim, + FT_UInt end_point ) + { + FT_UInt count = dim->masks.num_masks; + PS_Mask mask; + + + if ( count > 0 ) + { + mask = dim->masks.masks + count - 1; + mask->end_point = end_point; + } + } + + + /* set the end point in the current mask, then create a new empty one */ + /* (called by "Reset" method) */ + static FT_Error + ps_dimension_reset_mask( PS_Dimension dim, + FT_UInt end_point, + FT_Memory memory ) + { + PS_Mask mask; + + + /* end current mask */ + ps_dimension_end_mask( dim, end_point ); + + /* allocate new one */ + return ps_mask_table_alloc( &dim->masks, memory, &mask ); + } + + + /* set a new mask, called from the "T2Stem" method */ + static FT_Error + ps_dimension_set_mask_bits( PS_Dimension dim, + const FT_Byte* source, + FT_UInt source_pos, + FT_UInt source_bits, + FT_UInt end_point, + FT_Memory memory ) + { + FT_Error error = 0; + + + /* reset current mask, if any */ + error = ps_dimension_reset_mask( dim, end_point, memory ); + if ( error ) + goto Exit; + + /* set bits in new mask */ + error = ps_mask_table_set_bits( &dim->masks, (FT_Byte*)source, + source_pos, source_bits, memory ); + + Exit: + return error; + } + + + /* add a new single stem (called from "T1Stem" method) */ + static FT_Error + ps_dimension_add_t1stem( PS_Dimension dim, + FT_Int pos, + FT_Int len, + FT_Memory memory, + FT_Int *aindex ) + { + FT_Error error = 0; + FT_UInt flags = 0; + + + /* detect ghost stem */ + if ( len < 0 ) + { + flags |= PS_HINT_FLAG_GHOST; + if ( len == -21 ) + { + flags |= PS_HINT_FLAG_BOTTOM; + pos += len; + } + len = 0; + } + + if ( aindex ) + *aindex = -1; + + /* now, lookup stem in the current hints table */ + { + PS_Mask mask; + FT_UInt idx; + FT_UInt max = dim->hints.num_hints; + PS_Hint hint = dim->hints.hints; + + + for ( idx = 0; idx < max; idx++, hint++ ) + { + if ( hint->pos == pos && hint->len == len ) + break; + } + + /* we need to create a new hint in the table */ + if ( idx >= max ) + { + error = ps_hint_table_alloc( &dim->hints, memory, &hint ); + if ( error ) + goto Exit; + + hint->pos = pos; + hint->len = len; + hint->flags = flags; + } + + /* now, store the hint in the current mask */ + error = ps_mask_table_last( &dim->masks, memory, &mask ); + if ( error ) + goto Exit; + + error = ps_mask_set_bit( mask, idx, memory ); + if ( error ) + goto Exit; + + if ( aindex ) + *aindex = (FT_Int)idx; + } + + Exit: + return error; + } + + + /* add a "hstem3/vstem3" counter to our dimension table */ + static FT_Error + ps_dimension_add_counter( PS_Dimension dim, + FT_Int hint1, + FT_Int hint2, + FT_Int hint3, + FT_Memory memory ) + { + FT_Error error = 0; + FT_UInt count = dim->counters.num_masks; + PS_Mask counter = dim->counters.masks; + + + /* try to find an existing counter mask that already uses */ + /* one of these stems here */ + for ( ; count > 0; count--, counter++ ) + { + if ( ps_mask_test_bit( counter, hint1 ) || + ps_mask_test_bit( counter, hint2 ) || + ps_mask_test_bit( counter, hint3 ) ) + break; + } + + /* creat a new counter when needed */ + if ( count == 0 ) + { + error = ps_mask_table_alloc( &dim->counters, memory, &counter ); + if ( error ) + goto Exit; + } + + /* now, set the bits for our hints in the counter mask */ + error = ps_mask_set_bit( counter, hint1, memory ); + if ( error ) + goto Exit; + + error = ps_mask_set_bit( counter, hint2, memory ); + if ( error ) + goto Exit; + + error = ps_mask_set_bit( counter, hint3, memory ); + if ( error ) + goto Exit; + + Exit: + return error; + } + + + /* end of recording session for a given dimension */ + static FT_Error + ps_dimension_end( PS_Dimension dim, + FT_UInt end_point, + FT_Memory memory ) + { + /* end hint mask table */ + ps_dimension_end_mask( dim, end_point ); + + /* merge all counter masks into independent "paths" */ + return ps_mask_table_merge_all( &dim->counters, memory ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** PS_RECORDER MANAGEMENT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /* destroy hints */ + FT_LOCAL( void ) + ps_hints_done( PS_Hints hints ) + { + FT_Memory memory = hints->memory; + + + ps_dimension_done( &hints->dimension[0], memory ); + ps_dimension_done( &hints->dimension[1], memory ); + + hints->error = 0; + hints->memory = 0; + } + + + FT_LOCAL( FT_Error ) + ps_hints_init( PS_Hints hints, + FT_Memory memory ) + { + FT_MEM_ZERO( hints, sizeof ( *hints ) ); + hints->memory = memory; + return 0; + } + + + /* initialize a hints for a new session */ + static void + ps_hints_open( PS_Hints hints, + PS_Hint_Type hint_type ) + { + switch ( hint_type ) + { + case PS_HINT_TYPE_1: + case PS_HINT_TYPE_2: + hints->error = 0; + hints->hint_type = hint_type; + + ps_dimension_init( &hints->dimension[0] ); + ps_dimension_init( &hints->dimension[1] ); + break; + + default: + hints->error = PSH_Err_Invalid_Argument; + hints->hint_type = hint_type; + + FT_ERROR(( "ps_hints_open: invalid charstring type!\n" )); + break; + } + } + + + /* add one or more stems to the current hints table */ + static void + ps_hints_stem( PS_Hints hints, + FT_Int dimension, + FT_UInt count, + FT_Long* stems ) + { + if ( !hints->error ) + { + /* limit "dimension" to 0..1 */ + if ( dimension < 0 || dimension > 1 ) + { + FT_ERROR(( "ps_hints_stem: invalid dimension (%d) used\n", + dimension )); + dimension = ( dimension != 0 ); + } + + /* record the stems in the current hints/masks table */ + switch ( hints->hint_type ) + { + case PS_HINT_TYPE_1: /* Type 1 "hstem" or "vstem" operator */ + case PS_HINT_TYPE_2: /* Type 2 "hstem" or "vstem" operator */ + { + PS_Dimension dim = &hints->dimension[dimension]; + + + for ( ; count > 0; count--, stems += 2 ) + { + FT_Error error; + FT_Memory memory = hints->memory; + + + error = ps_dimension_add_t1stem( + dim, (FT_Int)stems[0], (FT_Int)stems[1], + memory, NULL ); + if ( error ) + { + FT_ERROR(( "ps_hints_stem: could not add stem" + " (%d,%d) to hints table\n", stems[0], stems[1] )); + + hints->error = error; + return; + } + } + break; + } + + default: + FT_ERROR(( "ps_hints_stem: called with invalid hint type (%d)\n", + hints->hint_type )); + break; + } + } + } + + + /* add one Type1 counter stem to the current hints table */ + static void + ps_hints_t1stem3( PS_Hints hints, + FT_Int dimension, + FT_Long* stems ) + { + FT_Error error = 0; + + + if ( !hints->error ) + { + PS_Dimension dim; + FT_Memory memory = hints->memory; + FT_Int count; + FT_Int idx[3]; + + + /* limit "dimension" to 0..1 */ + if ( dimension < 0 || dimension > 1 ) + { + FT_ERROR(( "ps_hints_t1stem3: invalid dimension (%d) used\n", + dimension )); + dimension = ( dimension != 0 ); + } + + dim = &hints->dimension[dimension]; + + /* there must be 6 elements in the 'stem' array */ + if ( hints->hint_type == PS_HINT_TYPE_1 ) + { + /* add the three stems to our hints/masks table */ + for ( count = 0; count < 3; count++, stems += 2 ) + { + error = ps_dimension_add_t1stem( + dim, (FT_Int)stems[0], (FT_Int)stems[1], + memory, &idx[count] ); + if ( error ) + goto Fail; + } + + /* now, add the hints to the counters table */ + error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2], + memory ); + if ( error ) + goto Fail; + } + else + { + FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type!\n" )); + error = PSH_Err_Invalid_Argument; + goto Fail; + } + } + + return; + + Fail: + FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" )); + hints->error = error; + } + + + /* reset hints (only with Type 1 hints) */ + static void + ps_hints_t1reset( PS_Hints hints, + FT_UInt end_point ) + { + FT_Error error = 0; + + + if ( !hints->error ) + { + FT_Memory memory = hints->memory; + + + if ( hints->hint_type == PS_HINT_TYPE_1 ) + { + error = ps_dimension_reset_mask( &hints->dimension[0], + end_point, memory ); + if ( error ) + goto Fail; + + error = ps_dimension_reset_mask( &hints->dimension[1], + end_point, memory ); + if ( error ) + goto Fail; + } + else + { + /* invalid hint type */ + error = PSH_Err_Invalid_Argument; + goto Fail; + } + } + return; + + Fail: + hints->error = error; + } + + + /* Type2 "hintmask" operator, add a new hintmask to each direction */ + static void + ps_hints_t2mask( PS_Hints hints, + FT_UInt end_point, + FT_UInt bit_count, + const FT_Byte* bytes ) + { + FT_Error error; + + + if ( !hints->error ) + { + PS_Dimension dim = hints->dimension; + FT_Memory memory = hints->memory; + FT_UInt count1 = dim[0].hints.num_hints; + FT_UInt count2 = dim[1].hints.num_hints; + + + /* check bit count; must be equal to current total hint count */ + if ( bit_count != count1 + count2 ) + { + FT_ERROR(( "ps_hints_t2mask: " + "called with invalid bitcount %d (instead of %d)\n", + bit_count, count1 + count2 )); + + /* simply ignore the operator */ + return; + } + + /* set-up new horizontal and vertical hint mask now */ + error = ps_dimension_set_mask_bits( &dim[0], bytes, count2, count1, + end_point, memory ); + if ( error ) + goto Fail; + + error = ps_dimension_set_mask_bits( &dim[1], bytes, 0, count2, + end_point, memory ); + if ( error ) + goto Fail; + } + return; + + Fail: + hints->error = error; + } + + + static void + ps_hints_t2counter( PS_Hints hints, + FT_UInt bit_count, + const FT_Byte* bytes ) + { + FT_Error error; + + + if ( !hints->error ) + { + PS_Dimension dim = hints->dimension; + FT_Memory memory = hints->memory; + FT_UInt count1 = dim[0].hints.num_hints; + FT_UInt count2 = dim[1].hints.num_hints; + + + /* check bit count, must be equal to current total hint count */ + if ( bit_count != count1 + count2 ) + { + FT_ERROR(( "ps_hints_t2counter: " + "called with invalid bitcount %d (instead of %d)\n", + bit_count, count1 + count2 )); + + /* simply ignore the operator */ + return; + } + + /* set-up new horizontal and vertical hint mask now */ + error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1, + 0, memory ); + if ( error ) + goto Fail; + + error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2, + 0, memory ); + if ( error ) + goto Fail; + } + return; + + Fail: + hints->error = error; + } + + + /* end recording session */ + static FT_Error + ps_hints_close( PS_Hints hints, + FT_UInt end_point ) + { + FT_Error error; + + + error = hints->error; + if ( !error ) + { + FT_Memory memory = hints->memory; + PS_Dimension dim = hints->dimension; + + + error = ps_dimension_end( &dim[0], end_point, memory ); + if ( !error ) + { + error = ps_dimension_end( &dim[1], end_point, memory ); + } + } + +#ifdef DEBUG_HINTER + if ( !error ) + ps_debug_hints = hints; +#endif + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 HINTS RECORDING INTERFACE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + t1_hints_open( T1_Hints hints ) + { + ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 ); + } + + static void + t1_hints_stem( T1_Hints hints, + FT_Int dimension, + FT_Long* coords ) + { + ps_hints_stem( (PS_Hints)hints, dimension, 1, coords ); + } + + + FT_LOCAL_DEF( void ) + t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ) + { + FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) ); + + funcs->open = (T1_Hints_OpenFunc) t1_hints_open; + funcs->close = (T1_Hints_CloseFunc) ps_hints_close; + funcs->stem = (T1_Hints_SetStemFunc) t1_hints_stem; + funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3; + funcs->reset = (T1_Hints_ResetFunc) ps_hints_t1reset; + funcs->apply = (T1_Hints_ApplyFunc) ps_hints_apply; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 2 HINTS RECORDING INTERFACE *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static void + t2_hints_open( T2_Hints hints ) + { + ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 ); + } + + + static void + t2_hints_stems( T2_Hints hints, + FT_Int dimension, + FT_Int count, + FT_Fixed* coords ) + { + FT_Pos stems[32], y, n; + FT_Int total = count; + + + y = 0; + while ( total > 0 ) + { + /* determine number of stems to write */ + count = total; + if ( count > 16 ) + count = 16; + + /* compute integer stem positions in font units */ + for ( n = 0; n < count * 2; n++ ) + { + y += coords[n]; + stems[n] = ( y + 0x8000L ) >> 16; + } + + /* compute lengths */ + for ( n = 0; n < count * 2; n += 2 ) + stems[n + 1] = stems[n + 1] - stems[n]; + + /* add them to the current dimension */ + ps_hints_stem( (PS_Hints)hints, dimension, count, stems ); + + total -= count; + } + } + + + FT_LOCAL_DEF( void ) + t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ) + { + FT_MEM_ZERO( funcs, sizeof ( *funcs ) ); + + funcs->open = (T2_Hints_OpenFunc) t2_hints_open; + funcs->close = (T2_Hints_CloseFunc) ps_hints_close; + funcs->stems = (T2_Hints_StemsFunc) t2_hints_stems; + funcs->hintmask= (T2_Hints_MaskFunc) ps_hints_t2mask; + funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter; + funcs->apply = (T2_Hints_ApplyFunc) ps_hints_apply; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/pshinter/pshrec.h b/Utilities/vtkfreetype/src/pshinter/pshrec.h new file mode 100644 index 0000000..0159e9c --- /dev/null +++ b/Utilities/vtkfreetype/src/pshinter/pshrec.h @@ -0,0 +1,176 @@ +/***************************************************************************/ +/* */ +/* pshrec.h */ +/* */ +/* Postscript (Type1/Type2) hints recorder (specification). */ +/* */ +/* Copyright 2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /**************************************************************************/ + /* */ + /* The functions defined here are called from the Type 1, CID and CFF */ + /* font drivers to record the hints of a given character/glyph. */ + /* */ + /* The hints are recorded in a unified format, and are later processed */ + /* by the "optimizer" and "fitter" to adjust the outlines to the pixel */ + /* grid. */ + /* */ + /**************************************************************************/ + + +#ifndef __PSHREC_H__ +#define __PSHREC_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_POSTSCRIPT_HINTS_H +#include "pshglob.h" + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** GLYPH HINTS RECORDER INTERNALS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /* handle to hint record */ + typedef struct PS_HintRec_* PS_Hint; + + /* hint types */ + typedef enum + { + PS_HINT_TYPE_1 = 1, + PS_HINT_TYPE_2 = 2 + + } PS_Hint_Type; + + + /* hint flags */ + typedef enum + { + PS_HINT_FLAG_GHOST = 1, + PS_HINT_FLAG_BOTTOM = 2 + + } PS_Hint_Flags; + + + /* hint descriptor */ + typedef struct PS_HintRec_ + { + FT_Int pos; + FT_Int len; + FT_UInt flags; + + } PS_HintRec; + + +#define ps_hint_is_active( x ) ( (x)->flags & PS_HINT_FLAG_ACTIVE ) +#define ps_hint_is_ghost( x ) ( (x)->flags & PS_HINT_FLAG_GHOST ) +#define ps_hint_is_bottom( x ) ( (x)->flags & PS_HINT_FLAG_BOTTOM ) + + + /* hints table descriptor */ + typedef struct PS_Hint_TableRec_ + { + FT_UInt num_hints; + FT_UInt max_hints; + PS_Hint hints; + + } PS_Hint_TableRec, *PS_Hint_Table; + + + /* hint and counter mask descriptor */ + typedef struct PS_MaskRec_ + { + FT_UInt num_bits; + FT_UInt max_bits; + FT_Byte* bytes; + FT_UInt end_point; + + } PS_MaskRec, *PS_Mask; + + + /* masks and counters table descriptor */ + typedef struct PS_Mask_TableRec_ + { + FT_UInt num_masks; + FT_UInt max_masks; + PS_Mask masks; + + } PS_Mask_TableRec, *PS_Mask_Table; + + + /* dimension-specific hints descriptor */ + typedef struct PS_DimensionRec_ + { + PS_Hint_TableRec hints; + PS_Mask_TableRec masks; + PS_Mask_TableRec counters; + + } PS_DimensionRec, *PS_Dimension; + + + /* glyph hints descriptor */ + /* dimension 0 => X coordinates + vertical hints/stems */ + /* dimension 1 => Y coordinates + horizontal hints/stems */ + typedef struct PS_HintsRec_ + { + FT_Memory memory; + FT_Error error; + FT_UInt32 magic; + PS_Hint_Type hint_type; + PS_DimensionRec dimension[2]; + + } PS_HintsRec, *PS_Hints; + + /* */ + + /* initialize hints recorder */ + FT_LOCAL( FT_Error ) + ps_hints_init( PS_Hints hints, + FT_Memory memory ); + + /* finalize hints recorder */ + FT_LOCAL( void ) + ps_hints_done( PS_Hints hints ); + + /* initialize Type1 hints recorder interface */ + FT_LOCAL( void ) + t1_hints_funcs_init( T1_Hints_FuncsRec* funcs ); + + /* initialize Type2 hints recorder interface */ + FT_LOCAL( void ) + t2_hints_funcs_init( T2_Hints_FuncsRec* funcs ); + + +#ifdef DEBUG_HINTER + extern PS_Hints ps_debug_hints; + extern int ps_debug_no_horz_hints; + extern int ps_debug_no_vert_hints; +#endif + + /* */ + + +FT_END_HEADER + + +#endif /* __PS_HINTER_RECORD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psnames/psmodule.c b/Utilities/vtkfreetype/src/psnames/psmodule.c new file mode 100644 index 0000000..f6d6ae3 --- /dev/null +++ b/Utilities/vtkfreetype/src/psnames/psmodule.c @@ -0,0 +1,408 @@ +/***************************************************************************/ +/* */ +/* psmodule.c */ +/* */ +/* PSNames module implementation (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H + +#include "psmodule.h" +#include "pstables.h" + +#include "psnamerr.h" + + +#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES + + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /* return the Unicode value corresponding to a given glyph. Note that */ + /* we do deal with glyph variants by detecting a non-initial dot in */ + /* the name, as in `A.swash' or `e.final', etc. */ + /* */ + static FT_UInt32 + ps_unicode_value( const char* glyph_name ) + { + FT_Int n; + char first = glyph_name[0]; + char temp[64]; + + + /* If the name begins with `uni', then the glyph name may be a */ + /* hard-coded unicode character code. */ + if ( glyph_name[0] == 'u' && + glyph_name[1] == 'n' && + glyph_name[2] == 'i' ) + { + /* determine whether the next four characters following are */ + /* hexadecimal. */ + + /* XXX: Add code to deal with ligatures, i.e. glyph names like */ + /* `uniXXXXYYYYZZZZ'... */ + + FT_Int count; + FT_ULong value = 0; + const char* p = glyph_name + 3; + + + for ( count = 4; count > 0; count--, p++ ) + { + char c = *p; + unsigned int d; + + + d = (unsigned char)c - '0'; + if ( d >= 10 ) + { + d = (unsigned char)c - 'A'; + if ( d >= 6 ) + d = 16; + else + d += 10; + } + + /* exit if a non-uppercase hexadecimal character was found */ + if ( d >= 16 ) + break; + + value = ( value << 4 ) + d; + } + + /* there must be exactly four hex digits */ + if ( ( *p == '\0' || *p == '.' ) && count == 0 ) + return value; + } + + /* If the name begins with `u', followed by four to six uppercase */ + /* hexadicimal digits, it is a hard-coded unicode character code. */ + if ( glyph_name[0] == 'u' ) + { + FT_Int count; + FT_ULong value = 0; + const char* p = glyph_name + 1; + + + for ( count = 6; count > 0; count--, p++ ) + { + char c = *p; + unsigned int d; + + + d = (unsigned char)c - '0'; + if ( d >= 10 ) + { + d = (unsigned char)c - 'A'; + if ( d >= 6 ) + d = 16; + else + d += 10; + } + + if ( d >= 16 ) + break; + + value = ( value << 4 ) + d; + } + + if ( ( *p == '\0' || *p == '.' ) && count <= 2 ) + return value; + } + + /* look for a non-initial dot in the glyph name in order to */ + /* sort-out variants like `A.swash', `e.final', etc. */ + { + const char* p; + int len; + + + p = glyph_name; + + while ( *p && *p != '.' ) + p++; + + len = (int)( p - glyph_name ); + + if ( *p && len < 64 ) + { + ft_strncpy( temp, glyph_name, len ); + temp[len] = 0; + glyph_name = temp; + } + } + + /* now, look up the glyph in the Adobe Glyph List */ + for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ ) + { + const char* name = sid_standard_names[n]; + + + if ( first == name[0] && ft_strcmp( glyph_name, name ) == 0 ) + return ps_names_to_unicode[n]; + } + + /* not found, there is probably no Unicode value for this glyph name */ + return 0; + } + + + /* ft_qsort callback to sort the unicode map */ + FT_CALLBACK_DEF( int ) + compare_uni_maps( const void* a, + const void* b ) + { + PS_UniMap* map1 = (PS_UniMap*)a; + PS_UniMap* map2 = (PS_UniMap*)b; + + + return ( map1->unicode - map2->unicode ); + } + + + /* Builds a table that maps Unicode values to glyph indices */ + static FT_Error + ps_unicodes_init( FT_Memory memory, + FT_UInt num_glyphs, + const char** glyph_names, + PS_Unicodes* table ) + { + FT_Error error; + + + /* we first allocate the table */ + table->num_maps = 0; + table->maps = 0; + + if ( !FT_NEW_ARRAY( table->maps, num_glyphs ) ) + { + FT_UInt n; + FT_UInt count; + PS_UniMap* map; + FT_UInt32 uni_char; + + + map = table->maps; + + for ( n = 0; n < num_glyphs; n++ ) + { + const char* gname = glyph_names[n]; + + + if ( gname ) + { + uni_char = ps_unicode_value( gname ); + + if ( uni_char != 0 && uni_char != 0xFFFFL ) + { + map->unicode = (FT_UInt)uni_char; + map->glyph_index = n; + map++; + } + } + } + + /* now, compress the table a bit */ + count = (FT_UInt)( map - table->maps ); + + if ( count > 0 && FT_REALLOC( table->maps, + num_glyphs * sizeof ( PS_UniMap ), + count * sizeof ( PS_UniMap ) ) ) + count = 0; + + if ( count == 0 ) + { + FT_FREE( table->maps ); + if ( !error ) + error = PSnames_Err_Invalid_Argument; /* no unicode chars here! */ + } + else + /* sort the table in increasing order of unicode values */ + ft_qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps ); + + table->num_maps = count; + } + + return error; + } + + + static FT_UInt + ps_unicodes_char_index( PS_Unicodes* table, + FT_ULong unicode ) + { + PS_UniMap *min, *max, *mid; + + + /* perform a binary search on the table */ + + min = table->maps; + max = min + table->num_maps - 1; + + while ( min <= max ) + { + mid = min + ( max - min ) / 2; + if ( mid->unicode == unicode ) + return mid->glyph_index; + + if ( min == max ) + break; + + if ( mid->unicode < unicode ) + min = mid + 1; + else + max = mid - 1; + } + + return 0xFFFFU; + } + + + static FT_ULong + ps_unicodes_char_next( PS_Unicodes* table, + FT_ULong unicode ) + { + PS_UniMap *min, *max, *mid; + + + unicode++; + /* perform a binary search on the table */ + + min = table->maps; + max = min + table->num_maps - 1; + + while ( min <= max ) + { + mid = min + ( max - min ) / 2; + if ( mid->unicode == unicode ) + return unicode; + + if ( min == max ) + break; + + if ( mid->unicode < unicode ) + min = mid + 1; + else + max = mid - 1; + } + + if ( max < table->maps ) + max = table->maps; + + while ( max < table->maps + table->num_maps ) + { + if ( unicode < max->unicode ) + return max->unicode; + max++; + } + + return 0; + } + + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + + + static const char* + ps_get_macintosh_name( FT_UInt name_index ) + { + if ( name_index >= 258 ) + name_index = 0; + + return ps_glyph_names[mac_standard_names[name_index]]; + } + + + static const char* + ps_get_standard_strings( FT_UInt sid ) + { + return ( sid < NUM_SID_GLYPHS ? sid_standard_names[sid] : 0 ); + } + + + static + const FT_Service_PsCMapsRec pscmaps_interface = + { +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + (PS_Unicode_ValueFunc) ps_unicode_value, + (PS_Unicodes_InitFunc) ps_unicodes_init, + (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, + (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, + +#else + + 0, + 0, + 0, + 0, + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + + (PS_Macintosh_Name_Func) ps_get_macintosh_name, + (PS_Adobe_Std_Strings_Func)ps_get_standard_strings, + + t1_standard_encoding, + t1_expert_encoding + }; + + + static const FT_ServiceDescRec pscmaps_services[] = + { + { FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface }, + { NULL, NULL } + }; + + + static FT_Pointer + psnames_get_service( FT_Module module, + const char* service_id ) + { + FT_UNUSED( module ); + + return ft_service_list_lookup( pscmaps_services, service_id ); + } + +#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */ + + + + FT_CALLBACK_TABLE_DEF + const FT_Module_Class psnames_module_class = + { + 0, /* this is not a font driver, nor a renderer */ + sizeof ( FT_ModuleRec ), + + "psnames", /* driver name */ + 0x10000L, /* driver version */ + 0x20000L, /* driver requires FreeType 2 or above */ + +#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES + 0, + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 +#else + (void*)&pscmaps_interface, /* module specific interface */ + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) psnames_get_service +#endif + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psnames/psmodule.h b/Utilities/vtkfreetype/src/psnames/psmodule.h new file mode 100644 index 0000000..232fdfb --- /dev/null +++ b/Utilities/vtkfreetype/src/psnames/psmodule.h @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* psmodule.h */ +/* */ +/* High-level PSNames module interface (specification). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSMODULE_H__ +#define __PSMODULE_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Module_Class ) psnames_module_class; + + +FT_END_HEADER + +#endif /* __PSMODULE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psnames/psnamerr.h b/Utilities/vtkfreetype/src/psnames/psnamerr.h new file mode 100644 index 0000000..ae1541d --- /dev/null +++ b/Utilities/vtkfreetype/src/psnames/psnamerr.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* psnamerr.h */ +/* */ +/* PS names module error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the PS names module error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __PSNAMERR_H__ +#define __PSNAMERR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX PSnames_Err_ +#define FT_ERR_BASE FT_Mod_Err_PSnames + +#include FT_ERRORS_H + +#endif /* __PSNAMERR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psnames/psnames.c b/Utilities/vtkfreetype/src/psnames/psnames.c new file mode 100644 index 0000000..d6ed998 --- /dev/null +++ b/Utilities/vtkfreetype/src/psnames/psnames.c @@ -0,0 +1,25 @@ +/***************************************************************************/ +/* */ +/* psnames.c */ +/* */ +/* FreeType PSNames module component (body only). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "psmodule.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/psnames/pstables.h b/Utilities/vtkfreetype/src/psnames/pstables.h new file mode 100644 index 0000000..7c07393 --- /dev/null +++ b/Utilities/vtkfreetype/src/psnames/pstables.h @@ -0,0 +1,9437 @@ +/***************************************************************************/ +/* */ +/* pstables.h.new */ +/* */ +/* PostScript glyph names (specification only). */ +/* */ +/* Copyright 2000-2001, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /* this file has been generated automatically -- do not edit! */ + + + static const char* const ps_glyph_names[] = + { + ".null", + "nonmarkingreturn", + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcentered", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "lslash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold", + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + "AEacute", + "AEmacron", + "Abreve", + "Abreveacute", + "Abrevecyrillic", + "Abrevedotbelow", + "Abrevegrave", + "Abrevehookabove", + "Abrevetilde", + "Acaron", + "Acircle", + "Acircumflexacute", + "Acircumflexdotbelow", + "Acircumflexgrave", + "Acircumflexhookabove", + "Acircumflextilde", + "Acute", + "Acyrillic", + "Adblgrave", + "Adieresiscyrillic", + "Adieresismacron", + "Adotbelow", + "Adotmacron", + "Ahookabove", + "Aiecyrillic", + "Ainvertedbreve", + "Alpha", + "Alphatonos", + "Amacron", + "Amonospace", + "Aogonek", + "Aringacute", + "Aringbelow", + "Aybarmenian", + "Bcircle", + "Bdotaccent", + "Bdotbelow", + "Becyrillic", + "Benarmenian", + "Beta", + "Bhook", + "Blinebelow", + "Bmonospace", + "Btopbar", + "Caarmenian", + "Cacute", + "Caron", + "Ccaron", + "Ccedillaacute", + "Ccircle", + "Ccircumflex", + "Cdot", + "Cdotaccent", + "Chaarmenian", + "Cheabkhasiancyrillic", + "Checyrillic", + "Chedescenderabkhasiancyrillic", + "Chedescendercyrillic", + "Chedieresiscyrillic", + "Cheharmenian", + "Chekhakassiancyrillic", + "Cheverticalstrokecyrillic", + "Chi", + "Chook", + "Cmonospace", + "Coarmenian", + "DZ", + "DZcaron", + "Daarmenian", + "Dafrican", + "Dcaron", + "Dcedilla", + "Dcircle", + "Dcircumflexbelow", + "Dcroat", + "Ddotaccent", + "Ddotbelow", + "Decyrillic", + "Deicoptic", + "Delta", + "Deltagreek", + "Dhook", + "Dieresis", + "DieresisAcute", + "DieresisGrave", + "Digammagreek", + "Djecyrillic", + "Dlinebelow", + "Dmonospace", + "Dslash", + "Dtopbar", + "Dz", + "Dzcaron", + "Dzeabkhasiancyrillic", + "Dzecyrillic", + "Dzhecyrillic", + "Ebreve", + "Ecaron", + "Ecedillabreve", + "Echarmenian", + "Ecircle", + "Ecircumflexacute", + "Ecircumflexbelow", + "Ecircumflexdotbelow", + "Ecircumflexgrave", + "Ecircumflexhookabove", + "Ecircumflextilde", + "Ecyrillic", + "Edblgrave", + "Edot", + "Edotaccent", + "Edotbelow", + "Efcyrillic", + "Eharmenian", + "Ehookabove", + "Eightroman", + "Einvertedbreve", + "Eiotifiedcyrillic", + "Elcyrillic", + "Elevenroman", + "Emacron", + "Emacronacute", + "Emacrongrave", + "Emcyrillic", + "Emonospace", + "Encyrillic", + "Endescendercyrillic", + "Eng", + "Enghecyrillic", + "Enhookcyrillic", + "Eogonek", + "Eopen", + "Epsilon", + "Epsilontonos", + "Ercyrillic", + "Ereversed", + "Ereversedcyrillic", + "Escyrillic", + "Esdescendercyrillic", + "Esh", + "Eta", + "Etarmenian", + "Etatonos", + "Etilde", + "Etildebelow", + "Euro", + "Ezh", + "Ezhcaron", + "Ezhreversed", + "Fcircle", + "Fdotaccent", + "Feharmenian", + "Feicoptic", + "Fhook", + "Fitacyrillic", + "Fiveroman", + "Fmonospace", + "Fourroman", + "GBsquare", + "Gacute", + "Gamma", + "Gammaafrican", + "Gangiacoptic", + "Gbreve", + "Gcaron", + "Gcedilla", + "Gcircle", + "Gcircumflex", + "Gcommaaccent", + "Gdot", + "Gdotaccent", + "Gecyrillic", + "Ghadarmenian", + "Ghemiddlehookcyrillic", + "Ghestrokecyrillic", + "Gheupturncyrillic", + "Ghook", + "Gimarmenian", + "Gjecyrillic", + "Gmacron", + "Gmonospace", + "Grave", + "Gsmallhook", + "Gstroke", + "H18533", + "H18543", + "H18551", + "H22073", + "HPsquare", + "Haabkhasiancyrillic", + "Hadescendercyrillic", + "Hardsigncyrillic", + "Hbar", + "Hbrevebelow", + "Hcedilla", + "Hcircle", + "Hcircumflex", + "Hdieresis", + "Hdotaccent", + "Hdotbelow", + "Hmonospace", + "Hoarmenian", + "Horicoptic", + "Hungarumlaut", + "Hzsquare", + "IAcyrillic", + "IJ", + "IUcyrillic", + "Ibreve", + "Icaron", + "Icircle", + "Icyrillic", + "Idblgrave", + "Idieresisacute", + "Idieresiscyrillic", + "Idot", + "Idotaccent", + "Idotbelow", + "Iebrevecyrillic", + "Iecyrillic", + "Ifraktur", + "Ihookabove", + "Iicyrillic", + "Iinvertedbreve", + "Iishortcyrillic", + "Imacron", + "Imacroncyrillic", + "Imonospace", + "Iniarmenian", + "Iocyrillic", + "Iogonek", + "Iota", + "Iotaafrican", + "Iotadieresis", + "Iotatonos", + "Istroke", + "Itilde", + "Itildebelow", + "Izhitsacyrillic", + "Izhitsadblgravecyrillic", + "Jaarmenian", + "Jcircle", + "Jcircumflex", + "Jecyrillic", + "Jheharmenian", + "Jmonospace", + "KBsquare", + "KKsquare", + "Kabashkircyrillic", + "Kacute", + "Kacyrillic", + "Kadescendercyrillic", + "Kahookcyrillic", + "Kappa", + "Kastrokecyrillic", + "Kaverticalstrokecyrillic", + "Kcaron", + "Kcedilla", + "Kcircle", + "Kcommaaccent", + "Kdotbelow", + "Keharmenian", + "Kenarmenian", + "Khacyrillic", + "Kheicoptic", + "Khook", + "Kjecyrillic", + "Klinebelow", + "Kmonospace", + "Koppacyrillic", + "Koppagreek", + "Ksicyrillic", + "LJ", + "LL", + "Lacute", + "Lambda", + "Lcaron", + "Lcedilla", + "Lcircle", + "Lcircumflexbelow", + "Lcommaaccent", + "Ldot", + "Ldotaccent", + "Ldotbelow", + "Ldotbelowmacron", + "Liwnarmenian", + "Lj", + "Ljecyrillic", + "Llinebelow", + "Lmonospace", + "MBsquare", + "Macron", + "Macute", + "Mcircle", + "Mdotaccent", + "Mdotbelow", + "Menarmenian", + "Mmonospace", + "Mturned", + "Mu", + "NJ", + "Nacute", + "Ncaron", + "Ncedilla", + "Ncircle", + "Ncircumflexbelow", + "Ncommaaccent", + "Ndotaccent", + "Ndotbelow", + "Nhookleft", + "Nineroman", + "Nj", + "Njecyrillic", + "Nlinebelow", + "Nmonospace", + "Nowarmenian", + "Nu", + "Obarredcyrillic", + "Obarreddieresiscyrillic", + "Obreve", + "Ocaron", + "Ocenteredtilde", + "Ocircle", + "Ocircumflexacute", + "Ocircumflexdotbelow", + "Ocircumflexgrave", + "Ocircumflexhookabove", + "Ocircumflextilde", + "Ocyrillic", + "Odblacute", + "Odblgrave", + "Odieresiscyrillic", + "Odotbelow", + "Oharmenian", + "Ohm", + "Ohookabove", + "Ohorn", + "Ohornacute", + "Ohorndotbelow", + "Ohorngrave", + "Ohornhookabove", + "Ohorntilde", + "Ohungarumlaut", + "Oi", + "Oinvertedbreve", + "Omacron", + "Omacronacute", + "Omacrongrave", + "Omega", + "Omegacyrillic", + "Omegagreek", + "Omegaroundcyrillic", + "Omegatitlocyrillic", + "Omegatonos", + "Omicron", + "Omicrontonos", + "Omonospace", + "Oneroman", + "Oogonek", + "Oogonekmacron", + "Oopen", + "Oslashacute", + "Ostrokeacute", + "Otcyrillic", + "Otildeacute", + "Otildedieresis", + "Pacute", + "Pcircle", + "Pdotaccent", + "Pecyrillic", + "Peharmenian", + "Pemiddlehookcyrillic", + "Phi", + "Phook", + "Pi", + "Piwrarmenian", + "Pmonospace", + "Psi", + "Psicyrillic", + "Qcircle", + "Qmonospace", + "Raarmenian", + "Racute", + "Rcaron", + "Rcedilla", + "Rcircle", + "Rcommaaccent", + "Rdblgrave", + "Rdotaccent", + "Rdotbelow", + "Rdotbelowmacron", + "Reharmenian", + "Rfraktur", + "Rho", + "Rinvertedbreve", + "Rlinebelow", + "Rmonospace", + "Rsmallinverted", + "Rsmallinvertedsuperior", + "SF010000", + "SF020000", + "SF030000", + "SF040000", + "SF050000", + "SF060000", + "SF070000", + "SF080000", + "SF090000", + "SF100000", + "SF110000", + "SF190000", + "SF200000", + "SF210000", + "SF220000", + "SF230000", + "SF240000", + "SF250000", + "SF260000", + "SF270000", + "SF280000", + "SF360000", + "SF370000", + "SF380000", + "SF390000", + "SF400000", + "SF410000", + "SF420000", + "SF430000", + "SF440000", + "SF450000", + "SF460000", + "SF470000", + "SF480000", + "SF490000", + "SF500000", + "SF510000", + "SF520000", + "SF530000", + "SF540000", + "Sacute", + "Sacutedotaccent", + "Sampigreek", + "Scarondotaccent", + "Scedilla", + "Schwa", + "Schwacyrillic", + "Schwadieresiscyrillic", + "Scircle", + "Scircumflex", + "Scommaaccent", + "Sdotaccent", + "Sdotbelow", + "Sdotbelowdotaccent", + "Seharmenian", + "Sevenroman", + "Shaarmenian", + "Shacyrillic", + "Shchacyrillic", + "Sheicoptic", + "Shhacyrillic", + "Shimacoptic", + "Sigma", + "Sixroman", + "Smonospace", + "Softsigncyrillic", + "Stigmagreek", + "Tau", + "Tbar", + "Tcaron", + "Tcedilla", + "Tcircle", + "Tcircumflexbelow", + "Tcommaaccent", + "Tdotaccent", + "Tdotbelow", + "Tecyrillic", + "Tedescendercyrillic", + "Tenroman", + "Tetsecyrillic", + "Theta", + "Thook", + "Threeroman", + "Tiwnarmenian", + "Tlinebelow", + "Tmonospace", + "Toarmenian", + "Tonefive", + "Tonesix", + "Tonetwo", + "Tretroflexhook", + "Tsecyrillic", + "Tshecyrillic", + "Twelveroman", + "Tworoman", + "Ubreve", + "Ucaron", + "Ucircle", + "Ucircumflexbelow", + "Ucyrillic", + "Udblacute", + "Udblgrave", + "Udieresisacute", + "Udieresisbelow", + "Udieresiscaron", + "Udieresiscyrillic", + "Udieresisgrave", + "Udieresismacron", + "Udotbelow", + "Uhookabove", + "Uhorn", + "Uhornacute", + "Uhorndotbelow", + "Uhorngrave", + "Uhornhookabove", + "Uhorntilde", + "Uhungarumlaut", + "Uhungarumlautcyrillic", + "Uinvertedbreve", + "Ukcyrillic", + "Umacron", + "Umacroncyrillic", + "Umacrondieresis", + "Umonospace", + "Uogonek", + "Upsilon", + "Upsilon1", + "Upsilonacutehooksymbolgreek", + "Upsilonafrican", + "Upsilondieresis", + "Upsilondieresishooksymbolgreek", + "Upsilonhooksymbol", + "Upsilontonos", + "Uring", + "Ushortcyrillic", + "Ustraightcyrillic", + "Ustraightstrokecyrillic", + "Utilde", + "Utildeacute", + "Utildebelow", + "Vcircle", + "Vdotbelow", + "Vecyrillic", + "Vewarmenian", + "Vhook", + "Vmonospace", + "Voarmenian", + "Vtilde", + "Wacute", + "Wcircle", + "Wcircumflex", + "Wdieresis", + "Wdotaccent", + "Wdotbelow", + "Wgrave", + "Wmonospace", + "Xcircle", + "Xdieresis", + "Xdotaccent", + "Xeharmenian", + "Xi", + "Xmonospace", + "Yatcyrillic", + "Ycircle", + "Ycircumflex", + "Ydotaccent", + "Ydotbelow", + "Yericyrillic", + "Yerudieresiscyrillic", + "Ygrave", + "Yhook", + "Yhookabove", + "Yiarmenian", + "Yicyrillic", + "Yiwnarmenian", + "Ymonospace", + "Ytilde", + "Yusbigcyrillic", + "Yusbigiotifiedcyrillic", + "Yuslittlecyrillic", + "Yuslittleiotifiedcyrillic", + "Zaarmenian", + "Zacute", + "Zcircle", + "Zcircumflex", + "Zdot", + "Zdotaccent", + "Zdotbelow", + "Zecyrillic", + "Zedescendercyrillic", + "Zedieresiscyrillic", + "Zeta", + "Zhearmenian", + "Zhebrevecyrillic", + "Zhecyrillic", + "Zhedescendercyrillic", + "Zhedieresiscyrillic", + "Zlinebelow", + "Zmonospace", + "Zstroke", + "aabengali", + "aadeva", + "aagujarati", + "aagurmukhi", + "aamatragurmukhi", + "aarusquare", + "aavowelsignbengali", + "aavowelsigndeva", + "aavowelsigngujarati", + "abbreviationmarkarmenian", + "abbreviationsigndeva", + "abengali", + "abopomofo", + "abreve", + "abreveacute", + "abrevecyrillic", + "abrevedotbelow", + "abrevegrave", + "abrevehookabove", + "abrevetilde", + "acaron", + "acircle", + "acircumflexacute", + "acircumflexdotbelow", + "acircumflexgrave", + "acircumflexhookabove", + "acircumflextilde", + "acutebelowcmb", + "acutecmb", + "acutecomb", + "acutedeva", + "acutelowmod", + "acutetonecmb", + "acyrillic", + "adblgrave", + "addakgurmukhi", + "adeva", + "adieresiscyrillic", + "adieresismacron", + "adotbelow", + "adotmacron", + "aeacute", + "aekorean", + "aemacron", + "afii00208", + "afii08941", + "afii10017", + "afii10018", + "afii10019", + "afii10020", + "afii10021", + "afii10022", + "afii10023", + "afii10024", + "afii10025", + "afii10026", + "afii10027", + "afii10028", + "afii10029", + "afii10030", + "afii10031", + "afii10032", + "afii10033", + "afii10034", + "afii10035", + "afii10036", + "afii10037", + "afii10038", + "afii10039", + "afii10040", + "afii10041", + "afii10042", + "afii10043", + "afii10044", + "afii10045", + "afii10046", + "afii10047", + "afii10048", + "afii10049", + "afii10050", + "afii10051", + "afii10052", + "afii10053", + "afii10054", + "afii10055", + "afii10056", + "afii10057", + "afii10058", + "afii10059", + "afii10060", + "afii10061", + "afii10062", + "afii10063", + "afii10064", + "afii10065", + "afii10066", + "afii10067", + "afii10068", + "afii10069", + "afii10070", + "afii10071", + "afii10072", + "afii10073", + "afii10074", + "afii10075", + "afii10076", + "afii10077", + "afii10078", + "afii10079", + "afii10080", + "afii10081", + "afii10082", + "afii10083", + "afii10084", + "afii10085", + "afii10086", + "afii10087", + "afii10088", + "afii10089", + "afii10090", + "afii10091", + "afii10092", + "afii10093", + "afii10094", + "afii10095", + "afii10096", + "afii10097", + "afii10098", + "afii10099", + "afii10100", + "afii10101", + "afii10102", + "afii10103", + "afii10104", + "afii10105", + "afii10106", + "afii10107", + "afii10108", + "afii10109", + "afii10110", + "afii10145", + "afii10146", + "afii10147", + "afii10148", + "afii10192", + "afii10193", + "afii10194", + "afii10195", + "afii10196", + "afii10831", + "afii10832", + "afii10846", + "afii299", + "afii300", + "afii301", + "afii57381", + "afii57388", + "afii57392", + "afii57393", + "afii57394", + "afii57395", + "afii57396", + "afii57397", + "afii57398", + "afii57399", + "afii57400", + "afii57401", + "afii57403", + "afii57407", + "afii57409", + "afii57410", + "afii57411", + "afii57412", + "afii57413", + "afii57414", + "afii57415", + "afii57416", + "afii57417", + "afii57418", + "afii57419", + "afii57420", + "afii57421", + "afii57422", + "afii57423", + "afii57424", + "afii57425", + "afii57426", + "afii57427", + "afii57428", + "afii57429", + "afii57430", + "afii57431", + "afii57432", + "afii57433", + "afii57434", + "afii57440", + "afii57441", + "afii57442", + "afii57443", + "afii57444", + "afii57445", + "afii57446", + "afii57448", + "afii57449", + "afii57450", + "afii57451", + "afii57452", + "afii57453", + "afii57454", + "afii57455", + "afii57456", + "afii57457", + "afii57458", + "afii57470", + "afii57505", + "afii57506", + "afii57507", + "afii57508", + "afii57509", + "afii57511", + "afii57512", + "afii57513", + "afii57514", + "afii57519", + "afii57534", + "afii57636", + "afii57645", + "afii57658", + "afii57664", + "afii57665", + "afii57666", + "afii57667", + "afii57668", + "afii57669", + "afii57670", + "afii57671", + "afii57672", + "afii57673", + "afii57674", + "afii57675", + "afii57676", + "afii57677", + "afii57678", + "afii57679", + "afii57680", + "afii57681", + "afii57682", + "afii57683", + "afii57684", + "afii57685", + "afii57686", + "afii57687", + "afii57688", + "afii57689", + "afii57690", + "afii57694", + "afii57695", + "afii57700", + "afii57705", + "afii57716", + "afii57717", + "afii57718", + "afii57723", + "afii57793", + "afii57794", + "afii57795", + "afii57796", + "afii57797", + "afii57798", + "afii57799", + "afii57800", + "afii57801", + "afii57802", + "afii57803", + "afii57804", + "afii57806", + "afii57807", + "afii57839", + "afii57841", + "afii57842", + "afii57929", + "afii61248", + "afii61289", + "afii61352", + "afii61573", + "afii61574", + "afii61575", + "afii61664", + "afii63167", + "afii64937", + "agujarati", + "agurmukhi", + "ahiragana", + "ahookabove", + "aibengali", + "aibopomofo", + "aideva", + "aiecyrillic", + "aigujarati", + "aigurmukhi", + "aimatragurmukhi", + "ainarabic", + "ainfinalarabic", + "aininitialarabic", + "ainmedialarabic", + "ainvertedbreve", + "aivowelsignbengali", + "aivowelsigndeva", + "aivowelsigngujarati", + "akatakana", + "akatakanahalfwidth", + "akorean", + "alef", + "alefarabic", + "alefdageshhebrew", + "aleffinalarabic", + "alefhamzaabovearabic", + "alefhamzaabovefinalarabic", + "alefhamzabelowarabic", + "alefhamzabelowfinalarabic", + "alefhebrew", + "aleflamedhebrew", + "alefmaddaabovearabic", + "alefmaddaabovefinalarabic", + "alefmaksuraarabic", + "alefmaksurafinalarabic", + "alefmaksurainitialarabic", + "alefmaksuramedialarabic", + "alefpatahhebrew", + "alefqamatshebrew", + "aleph", + "allequal", + "alpha", + "alphatonos", + "amacron", + "amonospace", + "ampersandmonospace", + "amsquare", + "anbopomofo", + "angbopomofo", + "angkhankhuthai", + "angle", + "anglebracketleft", + "anglebracketleftvertical", + "anglebracketright", + "anglebracketrightvertical", + "angleleft", + "angleright", + "angstrom", + "anoteleia", + "anudattadeva", + "anusvarabengali", + "anusvaradeva", + "anusvaragujarati", + "aogonek", + "apaatosquare", + "aparen", + "apostrophearmenian", + "apostrophemod", + "apple", + "approaches", + "approxequal", + "approxequalorimage", + "approximatelyequal", + "araeaekorean", + "araeakorean", + "arc", + "arighthalfring", + "aringacute", + "aringbelow", + "arrowboth", + "arrowdashdown", + "arrowdashleft", + "arrowdashright", + "arrowdashup", + "arrowdblboth", + "arrowdbldown", + "arrowdblleft", + "arrowdblright", + "arrowdblup", + "arrowdown", + "arrowdownleft", + "arrowdownright", + "arrowdownwhite", + "arrowheaddownmod", + "arrowheadleftmod", + "arrowheadrightmod", + "arrowheadupmod", + "arrowhorizex", + "arrowleft", + "arrowleftdbl", + "arrowleftdblstroke", + "arrowleftoverright", + "arrowleftwhite", + "arrowright", + "arrowrightdblstroke", + "arrowrightheavy", + "arrowrightoverleft", + "arrowrightwhite", + "arrowtableft", + "arrowtabright", + "arrowup", + "arrowupdn", + "arrowupdnbse", + "arrowupdownbase", + "arrowupleft", + "arrowupleftofdown", + "arrowupright", + "arrowupwhite", + "arrowvertex", + "asciicircummonospace", + "asciitildemonospace", + "ascript", + "ascriptturned", + "asmallhiragana", + "asmallkatakana", + "asmallkatakanahalfwidth", + "asteriskaltonearabic", + "asteriskarabic", + "asteriskmath", + "asteriskmonospace", + "asterisksmall", + "asterism", + "asymptoticallyequal", + "atmonospace", + "atsmall", + "aturned", + "aubengali", + "aubopomofo", + "audeva", + "augujarati", + "augurmukhi", + "aulengthmarkbengali", + "aumatragurmukhi", + "auvowelsignbengali", + "auvowelsigndeva", + "auvowelsigngujarati", + "avagrahadeva", + "aybarmenian", + "ayin", + "ayinaltonehebrew", + "ayinhebrew", + "babengali", + "backslashmonospace", + "badeva", + "bagujarati", + "bagurmukhi", + "bahiragana", + "bahtthai", + "bakatakana", + "barmonospace", + "bbopomofo", + "bcircle", + "bdotaccent", + "bdotbelow", + "beamedsixteenthnotes", + "because", + "becyrillic", + "beharabic", + "behfinalarabic", + "behinitialarabic", + "behiragana", + "behmedialarabic", + "behmeeminitialarabic", + "behmeemisolatedarabic", + "behnoonfinalarabic", + "bekatakana", + "benarmenian", + "bet", + "beta", + "betasymbolgreek", + "betdagesh", + "betdageshhebrew", + "bethebrew", + "betrafehebrew", + "bhabengali", + "bhadeva", + "bhagujarati", + "bhagurmukhi", + "bhook", + "bihiragana", + "bikatakana", + "bilabialclick", + "bindigurmukhi", + "birusquare", + "blackcircle", + "blackdiamond", + "blackdownpointingtriangle", + "blackleftpointingpointer", + "blackleftpointingtriangle", + "blacklenticularbracketleft", + "blacklenticularbracketleftvertical", + "blacklenticularbracketright", + "blacklenticularbracketrightvertical", + "blacklowerlefttriangle", + "blacklowerrighttriangle", + "blackrectangle", + "blackrightpointingpointer", + "blackrightpointingtriangle", + "blacksmallsquare", + "blacksmilingface", + "blacksquare", + "blackstar", + "blackupperlefttriangle", + "blackupperrighttriangle", + "blackuppointingsmalltriangle", + "blackuppointingtriangle", + "blank", + "blinebelow", + "block", + "bmonospace", + "bobaimaithai", + "bohiragana", + "bokatakana", + "bparen", + "bqsquare", + "braceex", + "braceleftbt", + "braceleftmid", + "braceleftmonospace", + "braceleftsmall", + "bracelefttp", + "braceleftvertical", + "bracerightbt", + "bracerightmid", + "bracerightmonospace", + "bracerightsmall", + "bracerighttp", + "bracerightvertical", + "bracketleftbt", + "bracketleftex", + "bracketleftmonospace", + "bracketlefttp", + "bracketrightbt", + "bracketrightex", + "bracketrightmonospace", + "bracketrighttp", + "brevebelowcmb", + "brevecmb", + "breveinvertedbelowcmb", + "breveinvertedcmb", + "breveinverteddoublecmb", + "bridgebelowcmb", + "bridgeinvertedbelowcmb", + "bstroke", + "btopbar", + "buhiragana", + "bukatakana", + "bulletinverse", + "bulletoperator", + "bullseye", + "caarmenian", + "cabengali", + "cacute", + "cadeva", + "cagujarati", + "cagurmukhi", + "calsquare", + "candrabindubengali", + "candrabinducmb", + "candrabindudeva", + "candrabindugujarati", + "capslock", + "careof", + "caronbelowcmb", + "caroncmb", + "carriagereturn", + "cbopomofo", + "ccaron", + "ccedillaacute", + "ccircle", + "ccircumflex", + "ccurl", + "cdot", + "cdotaccent", + "cdsquare", + "cedillacmb", + "centigrade", + "centmonospace", + "chaarmenian", + "chabengali", + "chadeva", + "chagujarati", + "chagurmukhi", + "chbopomofo", + "cheabkhasiancyrillic", + "checkmark", + "checyrillic", + "chedescenderabkhasiancyrillic", + "chedescendercyrillic", + "chedieresiscyrillic", + "cheharmenian", + "chekhakassiancyrillic", + "cheverticalstrokecyrillic", + "chi", + "chieuchacirclekorean", + "chieuchaparenkorean", + "chieuchcirclekorean", + "chieuchkorean", + "chieuchparenkorean", + "chochangthai", + "chochanthai", + "chochingthai", + "chochoethai", + "chook", + "cieucacirclekorean", + "cieucaparenkorean", + "cieuccirclekorean", + "cieuckorean", + "cieucparenkorean", + "cieucuparenkorean", + "circle", + "circlemultiply", + "circleot", + "circleplus", + "circlepostalmark", + "circlewithlefthalfblack", + "circlewithrighthalfblack", + "circumflexbelowcmb", + "circumflexcmb", + "clear", + "clickalveolar", + "clickdental", + "clicklateral", + "clickretroflex", + "club", + "clubsuitblack", + "clubsuitwhite", + "cmcubedsquare", + "cmonospace", + "cmsquaredsquare", + "coarmenian", + "colonmonospace", + "colonsign", + "colonsmall", + "colontriangularhalfmod", + "colontriangularmod", + "commaabovecmb", + "commaaboverightcmb", + "commaaccent", + "commaarabic", + "commaarmenian", + "commamonospace", + "commareversedabovecmb", + "commareversedmod", + "commasmall", + "commaturnedabovecmb", + "commaturnedmod", + "compass", + "congruent", + "contourintegral", + "control", + "controlACK", + "controlBEL", + "controlBS", + "controlCAN", + "controlCR", + "controlDC1", + "controlDC2", + "controlDC3", + "controlDC4", + "controlDEL", + "controlDLE", + "controlEM", + "controlENQ", + "controlEOT", + "controlESC", + "controlETB", + "controlETX", + "controlFF", + "controlFS", + "controlGS", + "controlHT", + "controlLF", + "controlNAK", + "controlRS", + "controlSI", + "controlSO", + "controlSOT", + "controlSTX", + "controlSUB", + "controlSYN", + "controlUS", + "controlVT", + "copyrightsans", + "copyrightserif", + "cornerbracketleft", + "cornerbracketlefthalfwidth", + "cornerbracketleftvertical", + "cornerbracketright", + "cornerbracketrighthalfwidth", + "cornerbracketrightvertical", + "corporationsquare", + "cosquare", + "coverkgsquare", + "cparen", + "cruzeiro", + "cstretched", + "curlyand", + "curlyor", + "cyrBreve", + "cyrFlex", + "cyrbreve", + "cyrflex", + "daarmenian", + "dabengali", + "dadarabic", + "dadeva", + "dadfinalarabic", + "dadinitialarabic", + "dadmedialarabic", + "dagesh", + "dageshhebrew", + "dagujarati", + "dagurmukhi", + "dahiragana", + "dakatakana", + "dalarabic", + "dalet", + "daletdagesh", + "daletdageshhebrew", + "dalethatafpatah", + "dalethatafpatahhebrew", + "dalethatafsegol", + "dalethatafsegolhebrew", + "dalethebrew", + "dalethiriq", + "dalethiriqhebrew", + "daletholam", + "daletholamhebrew", + "daletpatah", + "daletpatahhebrew", + "daletqamats", + "daletqamatshebrew", + "daletqubuts", + "daletqubutshebrew", + "daletsegol", + "daletsegolhebrew", + "daletsheva", + "daletshevahebrew", + "dalettsere", + "dalettserehebrew", + "dalfinalarabic", + "dammaarabic", + "dammalowarabic", + "dammatanaltonearabic", + "dammatanarabic", + "danda", + "dargahebrew", + "dargalefthebrew", + "dasiapneumatacyrilliccmb", + "dblGrave", + "dblanglebracketleft", + "dblanglebracketleftvertical", + "dblanglebracketright", + "dblanglebracketrightvertical", + "dblarchinvertedbelowcmb", + "dblarrowleft", + "dblarrowright", + "dbldanda", + "dblgrave", + "dblgravecmb", + "dblintegral", + "dbllowline", + "dbllowlinecmb", + "dbloverlinecmb", + "dblprimemod", + "dblverticalbar", + "dblverticallineabovecmb", + "dbopomofo", + "dbsquare", + "dcaron", + "dcedilla", + "dcircle", + "dcircumflexbelow", + "dcroat", + "ddabengali", + "ddadeva", + "ddagujarati", + "ddagurmukhi", + "ddalarabic", + "ddalfinalarabic", + "dddhadeva", + "ddhabengali", + "ddhadeva", + "ddhagujarati", + "ddhagurmukhi", + "ddotaccent", + "ddotbelow", + "decimalseparatorarabic", + "decimalseparatorpersian", + "decyrillic", + "dehihebrew", + "dehiragana", + "deicoptic", + "dekatakana", + "deleteleft", + "deleteright", + "delta", + "deltaturned", + "denominatorminusonenumeratorbengali", + "dezh", + "dhabengali", + "dhadeva", + "dhagujarati", + "dhagurmukhi", + "dhook", + "dialytikatonos", + "dialytikatonoscmb", + "diamond", + "diamondsuitwhite", + "dieresisacute", + "dieresisbelowcmb", + "dieresiscmb", + "dieresisgrave", + "dieresistonos", + "dihiragana", + "dikatakana", + "dittomark", + "divides", + "divisionslash", + "djecyrillic", + "dkshade", + "dlinebelow", + "dlsquare", + "dmacron", + "dmonospace", + "dnblock", + "dochadathai", + "dodekthai", + "dohiragana", + "dokatakana", + "dollarmonospace", + "dollarsmall", + "dong", + "dorusquare", + "dotaccentcmb", + "dotbelowcmb", + "dotbelowcomb", + "dotkatakana", + "dotlessj", + "dotlessjstrokehook", + "dotmath", + "dottedcircle", + "doubleyodpatah", + "doubleyodpatahhebrew", + "downtackbelowcmb", + "downtackmod", + "dparen", + "dtail", + "dtopbar", + "duhiragana", + "dukatakana", + "dz", + "dzaltone", + "dzcaron", + "dzcurl", + "dzeabkhasiancyrillic", + "dzecyrillic", + "dzhecyrillic", + "earth", + "ebengali", + "ebopomofo", + "ebreve", + "ecandradeva", + "ecandragujarati", + "ecandravowelsigndeva", + "ecandravowelsigngujarati", + "ecaron", + "ecedillabreve", + "echarmenian", + "echyiwnarmenian", + "ecircle", + "ecircumflexacute", + "ecircumflexbelow", + "ecircumflexdotbelow", + "ecircumflexgrave", + "ecircumflexhookabove", + "ecircumflextilde", + "ecyrillic", + "edblgrave", + "edeva", + "edot", + "edotaccent", + "edotbelow", + "eegurmukhi", + "eematragurmukhi", + "efcyrillic", + "egujarati", + "eharmenian", + "ehbopomofo", + "ehiragana", + "ehookabove", + "eibopomofo", + "eightarabic", + "eightbengali", + "eightcircle", + "eightcircleinversesansserif", + "eightdeva", + "eighteencircle", + "eighteenparen", + "eighteenperiod", + "eightgujarati", + "eightgurmukhi", + "eighthackarabic", + "eighthangzhou", + "eighthnotebeamed", + "eightideographicparen", + "eightmonospace", + "eightparen", + "eightperiod", + "eightpersian", + "eightroman", + "eightthai", + "einvertedbreve", + "eiotifiedcyrillic", + "ekatakana", + "ekatakanahalfwidth", + "ekonkargurmukhi", + "ekorean", + "elcyrillic", + "element", + "elevencircle", + "elevenparen", + "elevenperiod", + "elevenroman", + "ellipsisvertical", + "emacron", + "emacronacute", + "emacrongrave", + "emcyrillic", + "emdashvertical", + "emonospace", + "emphasismarkarmenian", + "emptyset", + "enbopomofo", + "encyrillic", + "endashvertical", + "endescendercyrillic", + "eng", + "engbopomofo", + "enghecyrillic", + "enhookcyrillic", + "enspace", + "eogonek", + "eokorean", + "eopen", + "eopenclosed", + "eopenreversed", + "eopenreversedclosed", + "eopenreversedhook", + "eparen", + "epsilon", + "epsilontonos", + "equalmonospace", + "equalsmall", + "equalsuperior", + "equivalence", + "erbopomofo", + "ercyrillic", + "ereversed", + "ereversedcyrillic", + "escyrillic", + "esdescendercyrillic", + "esh", + "eshcurl", + "eshortdeva", + "eshortvowelsigndeva", + "eshreversedloop", + "eshsquatreversed", + "esmallhiragana", + "esmallkatakana", + "esmallkatakanahalfwidth", + "estimated", + "eta", + "etarmenian", + "etatonos", + "etilde", + "etildebelow", + "etnahtafoukhhebrew", + "etnahtafoukhlefthebrew", + "etnahtahebrew", + "etnahtalefthebrew", + "eturned", + "eukorean", + "euro", + "evowelsignbengali", + "evowelsigndeva", + "evowelsigngujarati", + "exclamarmenian", + "exclamdbl", + "exclammonospace", + "existential", + "ezh", + "ezhcaron", + "ezhcurl", + "ezhreversed", + "ezhtail", + "fadeva", + "fagurmukhi", + "fahrenheit", + "fathaarabic", + "fathalowarabic", + "fathatanarabic", + "fbopomofo", + "fcircle", + "fdotaccent", + "feharabic", + "feharmenian", + "fehfinalarabic", + "fehinitialarabic", + "fehmedialarabic", + "feicoptic", + "female", + "fifteencircle", + "fifteenparen", + "fifteenperiod", + "filledbox", + "filledrect", + "finalkaf", + "finalkafdagesh", + "finalkafdageshhebrew", + "finalkafhebrew", + "finalkafqamats", + "finalkafqamatshebrew", + "finalkafsheva", + "finalkafshevahebrew", + "finalmem", + "finalmemhebrew", + "finalnun", + "finalnunhebrew", + "finalpe", + "finalpehebrew", + "finaltsadi", + "finaltsadihebrew", + "firsttonechinese", + "fisheye", + "fitacyrillic", + "fivearabic", + "fivebengali", + "fivecircle", + "fivecircleinversesansserif", + "fivedeva", + "fivegujarati", + "fivegurmukhi", + "fivehackarabic", + "fivehangzhou", + "fiveideographicparen", + "fivemonospace", + "fiveparen", + "fiveperiod", + "fivepersian", + "fiveroman", + "fivethai", + "fmonospace", + "fmsquare", + "fofanthai", + "fofathai", + "fongmanthai", + "forall", + "fourarabic", + "fourbengali", + "fourcircle", + "fourcircleinversesansserif", + "fourdeva", + "fourgujarati", + "fourgurmukhi", + "fourhackarabic", + "fourhangzhou", + "fourideographicparen", + "fourmonospace", + "fournumeratorbengali", + "fourparen", + "fourperiod", + "fourpersian", + "fourroman", + "fourteencircle", + "fourteenparen", + "fourteenperiod", + "fourthai", + "fourthtonechinese", + "fparen", + "franc", + "gabengali", + "gacute", + "gadeva", + "gafarabic", + "gaffinalarabic", + "gafinitialarabic", + "gafmedialarabic", + "gagujarati", + "gagurmukhi", + "gahiragana", + "gakatakana", + "gamma", + "gammalatinsmall", + "gammasuperior", + "gangiacoptic", + "gbopomofo", + "gbreve", + "gcaron", + "gcedilla", + "gcircle", + "gcircumflex", + "gcommaaccent", + "gdot", + "gdotaccent", + "gecyrillic", + "gehiragana", + "gekatakana", + "geometricallyequal", + "gereshaccenthebrew", + "gereshhebrew", + "gereshmuqdamhebrew", + "gershayimaccenthebrew", + "gershayimhebrew", + "getamark", + "ghabengali", + "ghadarmenian", + "ghadeva", + "ghagujarati", + "ghagurmukhi", + "ghainarabic", + "ghainfinalarabic", + "ghaininitialarabic", + "ghainmedialarabic", + "ghemiddlehookcyrillic", + "ghestrokecyrillic", + "gheupturncyrillic", + "ghhadeva", + "ghhagurmukhi", + "ghook", + "ghzsquare", + "gihiragana", + "gikatakana", + "gimarmenian", + "gimel", + "gimeldagesh", + "gimeldageshhebrew", + "gimelhebrew", + "gjecyrillic", + "glottalinvertedstroke", + "glottalstop", + "glottalstopinverted", + "glottalstopmod", + "glottalstopreversed", + "glottalstopreversedmod", + "glottalstopreversedsuperior", + "glottalstopstroke", + "glottalstopstrokereversed", + "gmacron", + "gmonospace", + "gohiragana", + "gokatakana", + "gparen", + "gpasquare", + "gradient", + "gravebelowcmb", + "gravecmb", + "gravecomb", + "gravedeva", + "gravelowmod", + "gravemonospace", + "gravetonecmb", + "greaterequal", + "greaterequalorless", + "greatermonospace", + "greaterorequivalent", + "greaterorless", + "greateroverequal", + "greatersmall", + "gscript", + "gstroke", + "guhiragana", + "gukatakana", + "guramusquare", + "gysquare", + "haabkhasiancyrillic", + "haaltonearabic", + "habengali", + "hadescendercyrillic", + "hadeva", + "hagujarati", + "hagurmukhi", + "haharabic", + "hahfinalarabic", + "hahinitialarabic", + "hahiragana", + "hahmedialarabic", + "haitusquare", + "hakatakana", + "hakatakanahalfwidth", + "halantgurmukhi", + "hamzaarabic", + "hamzadammaarabic", + "hamzadammatanarabic", + "hamzafathaarabic", + "hamzafathatanarabic", + "hamzalowarabic", + "hamzalowkasraarabic", + "hamzalowkasratanarabic", + "hamzasukunarabic", + "hangulfiller", + "hardsigncyrillic", + "harpoonleftbarbup", + "harpoonrightbarbup", + "hasquare", + "hatafpatah", + "hatafpatah16", + "hatafpatah23", + "hatafpatah2f", + "hatafpatahhebrew", + "hatafpatahnarrowhebrew", + "hatafpatahquarterhebrew", + "hatafpatahwidehebrew", + "hatafqamats", + "hatafqamats1b", + "hatafqamats28", + "hatafqamats34", + "hatafqamatshebrew", + "hatafqamatsnarrowhebrew", + "hatafqamatsquarterhebrew", + "hatafqamatswidehebrew", + "hatafsegol", + "hatafsegol17", + "hatafsegol24", + "hatafsegol30", + "hatafsegolhebrew", + "hatafsegolnarrowhebrew", + "hatafsegolquarterhebrew", + "hatafsegolwidehebrew", + "hbar", + "hbopomofo", + "hbrevebelow", + "hcedilla", + "hcircle", + "hcircumflex", + "hdieresis", + "hdotaccent", + "hdotbelow", + "he", + "heart", + "heartsuitblack", + "heartsuitwhite", + "hedagesh", + "hedageshhebrew", + "hehaltonearabic", + "heharabic", + "hehebrew", + "hehfinalaltonearabic", + "hehfinalalttwoarabic", + "hehfinalarabic", + "hehhamzaabovefinalarabic", + "hehhamzaaboveisolatedarabic", + "hehinitialaltonearabic", + "hehinitialarabic", + "hehiragana", + "hehmedialaltonearabic", + "hehmedialarabic", + "heiseierasquare", + "hekatakana", + "hekatakanahalfwidth", + "hekutaarusquare", + "henghook", + "herutusquare", + "het", + "hethebrew", + "hhook", + "hhooksuperior", + "hieuhacirclekorean", + "hieuhaparenkorean", + "hieuhcirclekorean", + "hieuhkorean", + "hieuhparenkorean", + "hihiragana", + "hikatakana", + "hikatakanahalfwidth", + "hiriq", + "hiriq14", + "hiriq21", + "hiriq2d", + "hiriqhebrew", + "hiriqnarrowhebrew", + "hiriqquarterhebrew", + "hiriqwidehebrew", + "hlinebelow", + "hmonospace", + "hoarmenian", + "hohipthai", + "hohiragana", + "hokatakana", + "hokatakanahalfwidth", + "holam", + "holam19", + "holam26", + "holam32", + "holamhebrew", + "holamnarrowhebrew", + "holamquarterhebrew", + "holamwidehebrew", + "honokhukthai", + "hookabovecomb", + "hookcmb", + "hookpalatalizedbelowcmb", + "hookretroflexbelowcmb", + "hoonsquare", + "horicoptic", + "horizontalbar", + "horncmb", + "hotsprings", + "house", + "hparen", + "hsuperior", + "hturned", + "huhiragana", + "huiitosquare", + "hukatakana", + "hukatakanahalfwidth", + "hungarumlautcmb", + "hv", + "hyphenmonospace", + "hyphensmall", + "hyphentwo", + "iacyrillic", + "ibengali", + "ibopomofo", + "ibreve", + "icaron", + "icircle", + "icyrillic", + "idblgrave", + "ideographearthcircle", + "ideographfirecircle", + "ideographicallianceparen", + "ideographiccallparen", + "ideographiccentrecircle", + "ideographicclose", + "ideographiccomma", + "ideographiccommaleft", + "ideographiccongratulationparen", + "ideographiccorrectcircle", + "ideographicearthparen", + "ideographicenterpriseparen", + "ideographicexcellentcircle", + "ideographicfestivalparen", + "ideographicfinancialcircle", + "ideographicfinancialparen", + "ideographicfireparen", + "ideographichaveparen", + "ideographichighcircle", + "ideographiciterationmark", + "ideographiclaborcircle", + "ideographiclaborparen", + "ideographicleftcircle", + "ideographiclowcircle", + "ideographicmedicinecircle", + "ideographicmetalparen", + "ideographicmoonparen", + "ideographicnameparen", + "ideographicperiod", + "ideographicprintcircle", + "ideographicreachparen", + "ideographicrepresentparen", + "ideographicresourceparen", + "ideographicrightcircle", + "ideographicsecretcircle", + "ideographicselfparen", + "ideographicsocietyparen", + "ideographicspace", + "ideographicspecialparen", + "ideographicstockparen", + "ideographicstudyparen", + "ideographicsunparen", + "ideographicsuperviseparen", + "ideographicwaterparen", + "ideographicwoodparen", + "ideographiczero", + "ideographmetalcircle", + "ideographmooncircle", + "ideographnamecircle", + "ideographsuncircle", + "ideographwatercircle", + "ideographwoodcircle", + "ideva", + "idieresisacute", + "idieresiscyrillic", + "idotbelow", + "iebrevecyrillic", + "iecyrillic", + "ieungacirclekorean", + "ieungaparenkorean", + "ieungcirclekorean", + "ieungkorean", + "ieungparenkorean", + "igujarati", + "igurmukhi", + "ihiragana", + "ihookabove", + "iibengali", + "iicyrillic", + "iideva", + "iigujarati", + "iigurmukhi", + "iimatragurmukhi", + "iinvertedbreve", + "iishortcyrillic", + "iivowelsignbengali", + "iivowelsigndeva", + "iivowelsigngujarati", + "ij", + "ikatakana", + "ikatakanahalfwidth", + "ikorean", + "ilde", + "iluyhebrew", + "imacron", + "imacroncyrillic", + "imageorapproximatelyequal", + "imatragurmukhi", + "imonospace", + "increment", + "infinity", + "iniarmenian", + "integral", + "integralbottom", + "integralbt", + "integralex", + "integraltop", + "integraltp", + "intersection", + "intisquare", + "invbullet", + "invcircle", + "invsmileface", + "iocyrillic", + "iogonek", + "iota", + "iotadieresis", + "iotadieresistonos", + "iotalatin", + "iotatonos", + "iparen", + "irigurmukhi", + "ismallhiragana", + "ismallkatakana", + "ismallkatakanahalfwidth", + "issharbengali", + "istroke", + "iterationhiragana", + "iterationkatakana", + "itilde", + "itildebelow", + "iubopomofo", + "iucyrillic", + "ivowelsignbengali", + "ivowelsigndeva", + "ivowelsigngujarati", + "izhitsacyrillic", + "izhitsadblgravecyrillic", + "jaarmenian", + "jabengali", + "jadeva", + "jagujarati", + "jagurmukhi", + "jbopomofo", + "jcaron", + "jcircle", + "jcircumflex", + "jcrossedtail", + "jdotlessstroke", + "jecyrillic", + "jeemarabic", + "jeemfinalarabic", + "jeeminitialarabic", + "jeemmedialarabic", + "jeharabic", + "jehfinalarabic", + "jhabengali", + "jhadeva", + "jhagujarati", + "jhagurmukhi", + "jheharmenian", + "jis", + "jmonospace", + "jparen", + "jsuperior", + "kabashkircyrillic", + "kabengali", + "kacute", + "kacyrillic", + "kadescendercyrillic", + "kadeva", + "kaf", + "kafarabic", + "kafdagesh", + "kafdageshhebrew", + "kaffinalarabic", + "kafhebrew", + "kafinitialarabic", + "kafmedialarabic", + "kafrafehebrew", + "kagujarati", + "kagurmukhi", + "kahiragana", + "kahookcyrillic", + "kakatakana", + "kakatakanahalfwidth", + "kappa", + "kappasymbolgreek", + "kapyeounmieumkorean", + "kapyeounphieuphkorean", + "kapyeounpieupkorean", + "kapyeounssangpieupkorean", + "karoriisquare", + "kashidaautoarabic", + "kashidaautonosidebearingarabic", + "kasmallkatakana", + "kasquare", + "kasraarabic", + "kasratanarabic", + "kastrokecyrillic", + "katahiraprolongmarkhalfwidth", + "kaverticalstrokecyrillic", + "kbopomofo", + "kcalsquare", + "kcaron", + "kcedilla", + "kcircle", + "kcommaaccent", + "kdotbelow", + "keharmenian", + "kehiragana", + "kekatakana", + "kekatakanahalfwidth", + "kenarmenian", + "kesmallkatakana", + "kgreenlandic", + "khabengali", + "khacyrillic", + "khadeva", + "khagujarati", + "khagurmukhi", + "khaharabic", + "khahfinalarabic", + "khahinitialarabic", + "khahmedialarabic", + "kheicoptic", + "khhadeva", + "khhagurmukhi", + "khieukhacirclekorean", + "khieukhaparenkorean", + "khieukhcirclekorean", + "khieukhkorean", + "khieukhparenkorean", + "khokhaithai", + "khokhonthai", + "khokhuatthai", + "khokhwaithai", + "khomutthai", + "khook", + "khorakhangthai", + "khzsquare", + "kihiragana", + "kikatakana", + "kikatakanahalfwidth", + "kiroguramusquare", + "kiromeetorusquare", + "kirosquare", + "kiyeokacirclekorean", + "kiyeokaparenkorean", + "kiyeokcirclekorean", + "kiyeokkorean", + "kiyeokparenkorean", + "kiyeoksioskorean", + "kjecyrillic", + "klinebelow", + "klsquare", + "kmcubedsquare", + "kmonospace", + "kmsquaredsquare", + "kohiragana", + "kohmsquare", + "kokaithai", + "kokatakana", + "kokatakanahalfwidth", + "kooposquare", + "koppacyrillic", + "koreanstandardsymbol", + "koroniscmb", + "kparen", + "kpasquare", + "ksicyrillic", + "ktsquare", + "kturned", + "kuhiragana", + "kukatakana", + "kukatakanahalfwidth", + "kvsquare", + "kwsquare", + "labengali", + "lacute", + "ladeva", + "lagujarati", + "lagurmukhi", + "lakkhangyaothai", + "lamaleffinalarabic", + "lamalefhamzaabovefinalarabic", + "lamalefhamzaaboveisolatedarabic", + "lamalefhamzabelowfinalarabic", + "lamalefhamzabelowisolatedarabic", + "lamalefisolatedarabic", + "lamalefmaddaabovefinalarabic", + "lamalefmaddaaboveisolatedarabic", + "lamarabic", + "lambda", + "lambdastroke", + "lamed", + "lameddagesh", + "lameddageshhebrew", + "lamedhebrew", + "lamedholam", + "lamedholamdagesh", + "lamedholamdageshhebrew", + "lamedholamhebrew", + "lamfinalarabic", + "lamhahinitialarabic", + "laminitialarabic", + "lamjeeminitialarabic", + "lamkhahinitialarabic", + "lamlamhehisolatedarabic", + "lammedialarabic", + "lammeemhahinitialarabic", + "lammeeminitialarabic", + "lammeemjeeminitialarabic", + "lammeemkhahinitialarabic", + "largecircle", + "lbar", + "lbelt", + "lbopomofo", + "lcaron", + "lcedilla", + "lcircle", + "lcircumflexbelow", + "lcommaaccent", + "ldot", + "ldotaccent", + "ldotbelow", + "ldotbelowmacron", + "leftangleabovecmb", + "lefttackbelowcmb", + "lessequal", + "lessequalorgreater", + "lessmonospace", + "lessorequivalent", + "lessorgreater", + "lessoverequal", + "lesssmall", + "lezh", + "lfblock", + "lhookretroflex", + "lira", + "liwnarmenian", + "lj", + "ljecyrillic", + "ll", + "lladeva", + "llagujarati", + "llinebelow", + "llladeva", + "llvocalicbengali", + "llvocalicdeva", + "llvocalicvowelsignbengali", + "llvocalicvowelsigndeva", + "lmiddletilde", + "lmonospace", + "lmsquare", + "lochulathai", + "logicaland", + "logicalnotreversed", + "logicalor", + "lolingthai", + "longs", + "lowlinecenterline", + "lowlinecmb", + "lowlinedashed", + "lozenge", + "lparen", + "lsquare", + "ltshade", + "luthai", + "lvocalicbengali", + "lvocalicdeva", + "lvocalicvowelsignbengali", + "lvocalicvowelsigndeva", + "lxsquare", + "mabengali", + "macronbelowcmb", + "macroncmb", + "macronlowmod", + "macronmonospace", + "macute", + "madeva", + "magujarati", + "magurmukhi", + "mahapakhhebrew", + "mahapakhlefthebrew", + "mahiragana", + "maichattawalowleftthai", + "maichattawalowrightthai", + "maichattawathai", + "maichattawaupperleftthai", + "maieklowleftthai", + "maieklowrightthai", + "maiekthai", + "maiekupperleftthai", + "maihanakatleftthai", + "maihanakatthai", + "maitaikhuleftthai", + "maitaikhuthai", + "maitholowleftthai", + "maitholowrightthai", + "maithothai", + "maithoupperleftthai", + "maitrilowleftthai", + "maitrilowrightthai", + "maitrithai", + "maitriupperleftthai", + "maiyamokthai", + "makatakana", + "makatakanahalfwidth", + "male", + "mansyonsquare", + "maqafhebrew", + "mars", + "masoracirclehebrew", + "masquare", + "mbopomofo", + "mbsquare", + "mcircle", + "mcubedsquare", + "mdotaccent", + "mdotbelow", + "meemarabic", + "meemfinalarabic", + "meeminitialarabic", + "meemmedialarabic", + "meemmeeminitialarabic", + "meemmeemisolatedarabic", + "meetorusquare", + "mehiragana", + "meizierasquare", + "mekatakana", + "mekatakanahalfwidth", + "mem", + "memdagesh", + "memdageshhebrew", + "memhebrew", + "menarmenian", + "merkhahebrew", + "merkhakefulahebrew", + "merkhakefulalefthebrew", + "merkhalefthebrew", + "mhook", + "mhzsquare", + "middledotkatakanahalfwidth", + "middot", + "mieumacirclekorean", + "mieumaparenkorean", + "mieumcirclekorean", + "mieumkorean", + "mieumpansioskorean", + "mieumparenkorean", + "mieumpieupkorean", + "mieumsioskorean", + "mihiragana", + "mikatakana", + "mikatakanahalfwidth", + "minusbelowcmb", + "minuscircle", + "minusmod", + "minusplus", + "minute", + "miribaarusquare", + "mirisquare", + "mlonglegturned", + "mlsquare", + "mmcubedsquare", + "mmonospace", + "mmsquaredsquare", + "mohiragana", + "mohmsquare", + "mokatakana", + "mokatakanahalfwidth", + "molsquare", + "momathai", + "moverssquare", + "moverssquaredsquare", + "mparen", + "mpasquare", + "mssquare", + "mturned", + "mu1", + "muasquare", + "muchgreater", + "muchless", + "mufsquare", + "mugreek", + "mugsquare", + "muhiragana", + "mukatakana", + "mukatakanahalfwidth", + "mulsquare", + "mumsquare", + "munahhebrew", + "munahlefthebrew", + "musicalnote", + "musicalnotedbl", + "musicflatsign", + "musicsharpsign", + "mussquare", + "muvsquare", + "muwsquare", + "mvmegasquare", + "mvsquare", + "mwmegasquare", + "mwsquare", + "nabengali", + "nabla", + "nacute", + "nadeva", + "nagujarati", + "nagurmukhi", + "nahiragana", + "nakatakana", + "nakatakanahalfwidth", + "napostrophe", + "nasquare", + "nbopomofo", + "nbspace", + "ncaron", + "ncedilla", + "ncircle", + "ncircumflexbelow", + "ncommaaccent", + "ndotaccent", + "ndotbelow", + "nehiragana", + "nekatakana", + "nekatakanahalfwidth", + "newsheqelsign", + "nfsquare", + "ngabengali", + "ngadeva", + "ngagujarati", + "ngagurmukhi", + "ngonguthai", + "nhiragana", + "nhookleft", + "nhookretroflex", + "nieunacirclekorean", + "nieunaparenkorean", + "nieuncieuckorean", + "nieuncirclekorean", + "nieunhieuhkorean", + "nieunkorean", + "nieunpansioskorean", + "nieunparenkorean", + "nieunsioskorean", + "nieuntikeutkorean", + "nihiragana", + "nikatakana", + "nikatakanahalfwidth", + "nikhahitleftthai", + "nikhahitthai", + "ninearabic", + "ninebengali", + "ninecircle", + "ninecircleinversesansserif", + "ninedeva", + "ninegujarati", + "ninegurmukhi", + "ninehackarabic", + "ninehangzhou", + "nineideographicparen", + "ninemonospace", + "nineparen", + "nineperiod", + "ninepersian", + "nineroman", + "nineteencircle", + "nineteenparen", + "nineteenperiod", + "ninethai", + "nj", + "njecyrillic", + "nkatakana", + "nkatakanahalfwidth", + "nlegrightlong", + "nlinebelow", + "nmonospace", + "nmsquare", + "nnabengali", + "nnadeva", + "nnagujarati", + "nnagurmukhi", + "nnnadeva", + "nohiragana", + "nokatakana", + "nokatakanahalfwidth", + "nonbreakingspace", + "nonenthai", + "nonuthai", + "noonarabic", + "noonfinalarabic", + "noonghunnaarabic", + "noonghunnafinalarabic", + "noonhehinitialarabic", + "nooninitialarabic", + "noonjeeminitialarabic", + "noonjeemisolatedarabic", + "noonmedialarabic", + "noonmeeminitialarabic", + "noonmeemisolatedarabic", + "noonnoonfinalarabic", + "notcontains", + "notelement", + "notelementof", + "notequal", + "notgreater", + "notgreaternorequal", + "notgreaternorless", + "notidentical", + "notless", + "notlessnorequal", + "notparallel", + "notprecedes", + "notsubset", + "notsucceeds", + "notsuperset", + "nowarmenian", + "nparen", + "nssquare", + "nu", + "nuhiragana", + "nukatakana", + "nukatakanahalfwidth", + "nuktabengali", + "nuktadeva", + "nuktagujarati", + "nuktagurmukhi", + "numbersignmonospace", + "numbersignsmall", + "numeralsigngreek", + "numeralsignlowergreek", + "numero", + "nun", + "nundagesh", + "nundageshhebrew", + "nunhebrew", + "nvsquare", + "nwsquare", + "nyabengali", + "nyadeva", + "nyagujarati", + "nyagurmukhi", + "oangthai", + "obarred", + "obarredcyrillic", + "obarreddieresiscyrillic", + "obengali", + "obopomofo", + "obreve", + "ocandradeva", + "ocandragujarati", + "ocandravowelsigndeva", + "ocandravowelsigngujarati", + "ocaron", + "ocircle", + "ocircumflexacute", + "ocircumflexdotbelow", + "ocircumflexgrave", + "ocircumflexhookabove", + "ocircumflextilde", + "ocyrillic", + "odblacute", + "odblgrave", + "odeva", + "odieresiscyrillic", + "odotbelow", + "oekorean", + "ogonekcmb", + "ogujarati", + "oharmenian", + "ohiragana", + "ohookabove", + "ohorn", + "ohornacute", + "ohorndotbelow", + "ohorngrave", + "ohornhookabove", + "ohorntilde", + "ohungarumlaut", + "oi", + "oinvertedbreve", + "okatakana", + "okatakanahalfwidth", + "okorean", + "olehebrew", + "omacron", + "omacronacute", + "omacrongrave", + "omdeva", + "omega", + "omega1", + "omegacyrillic", + "omegalatinclosed", + "omegaroundcyrillic", + "omegatitlocyrillic", + "omegatonos", + "omgujarati", + "omicron", + "omicrontonos", + "omonospace", + "onearabic", + "onebengali", + "onecircle", + "onecircleinversesansserif", + "onedeva", + "onegujarati", + "onegurmukhi", + "onehackarabic", + "onehangzhou", + "oneideographicparen", + "onemonospace", + "onenumeratorbengali", + "oneparen", + "oneperiod", + "onepersian", + "oneroman", + "onethai", + "oogonek", + "oogonekmacron", + "oogurmukhi", + "oomatragurmukhi", + "oopen", + "oparen", + "openbullet", + "option", + "orthogonal", + "oshortdeva", + "oshortvowelsigndeva", + "oslashacute", + "osmallhiragana", + "osmallkatakana", + "osmallkatakanahalfwidth", + "ostrokeacute", + "otcyrillic", + "otildeacute", + "otildedieresis", + "oubopomofo", + "overline", + "overlinecenterline", + "overlinecmb", + "overlinedashed", + "overlinedblwavy", + "overlinewavy", + "overscore", + "ovowelsignbengali", + "ovowelsigndeva", + "ovowelsigngujarati", + "paampssquare", + "paasentosquare", + "pabengali", + "pacute", + "padeva", + "pagedown", + "pageup", + "pagujarati", + "pagurmukhi", + "pahiragana", + "paiyannoithai", + "pakatakana", + "palatalizationcyrilliccmb", + "palochkacyrillic", + "pansioskorean", + "parallel", + "parenleftaltonearabic", + "parenleftbt", + "parenleftex", + "parenleftmonospace", + "parenleftsmall", + "parenlefttp", + "parenleftvertical", + "parenrightaltonearabic", + "parenrightbt", + "parenrightex", + "parenrightmonospace", + "parenrightsmall", + "parenrighttp", + "parenrightvertical", + "partialdiff", + "paseqhebrew", + "pashtahebrew", + "pasquare", + "patah", + "patah11", + "patah1d", + "patah2a", + "patahhebrew", + "patahnarrowhebrew", + "patahquarterhebrew", + "patahwidehebrew", + "pazerhebrew", + "pbopomofo", + "pcircle", + "pdotaccent", + "pe", + "pecyrillic", + "pedagesh", + "pedageshhebrew", + "peezisquare", + "pefinaldageshhebrew", + "peharabic", + "peharmenian", + "pehebrew", + "pehfinalarabic", + "pehinitialarabic", + "pehiragana", + "pehmedialarabic", + "pekatakana", + "pemiddlehookcyrillic", + "perafehebrew", + "percentarabic", + "percentmonospace", + "percentsmall", + "periodarmenian", + "periodhalfwidth", + "periodmonospace", + "periodsmall", + "perispomenigreekcmb", + "perpendicular", + "peseta", + "pfsquare", + "phabengali", + "phadeva", + "phagujarati", + "phagurmukhi", + "phi", + "phi1", + "phieuphacirclekorean", + "phieuphaparenkorean", + "phieuphcirclekorean", + "phieuphkorean", + "phieuphparenkorean", + "philatin", + "phinthuthai", + "phisymbolgreek", + "phook", + "phophanthai", + "phophungthai", + "phosamphaothai", + "pi", + "pieupacirclekorean", + "pieupaparenkorean", + "pieupcieuckorean", + "pieupcirclekorean", + "pieupkiyeokkorean", + "pieupkorean", + "pieupparenkorean", + "pieupsioskiyeokkorean", + "pieupsioskorean", + "pieupsiostikeutkorean", + "pieupthieuthkorean", + "pieuptikeutkorean", + "pihiragana", + "pikatakana", + "pisymbolgreek", + "piwrarmenian", + "plusbelowcmb", + "pluscircle", + "plusmod", + "plusmonospace", + "plussmall", + "plussuperior", + "pmonospace", + "pmsquare", + "pohiragana", + "pointingindexdownwhite", + "pointingindexleftwhite", + "pointingindexrightwhite", + "pointingindexupwhite", + "pokatakana", + "poplathai", + "postalmark", + "postalmarkface", + "pparen", + "precedes", + "prescription", + "primemod", + "primereversed", + "product", + "projective", + "prolongedkana", + "propellor", + "propersubset", + "propersuperset", + "proportion", + "proportional", + "psi", + "psicyrillic", + "psilipneumatacyrilliccmb", + "pssquare", + "puhiragana", + "pukatakana", + "pvsquare", + "pwsquare", + "qadeva", + "qadmahebrew", + "qafarabic", + "qaffinalarabic", + "qafinitialarabic", + "qafmedialarabic", + "qamats", + "qamats10", + "qamats1a", + "qamats1c", + "qamats27", + "qamats29", + "qamats33", + "qamatsde", + "qamatshebrew", + "qamatsnarrowhebrew", + "qamatsqatanhebrew", + "qamatsqatannarrowhebrew", + "qamatsqatanquarterhebrew", + "qamatsqatanwidehebrew", + "qamatsquarterhebrew", + "qamatswidehebrew", + "qarneyparahebrew", + "qbopomofo", + "qcircle", + "qhook", + "qmonospace", + "qof", + "qofdagesh", + "qofdageshhebrew", + "qofhatafpatah", + "qofhatafpatahhebrew", + "qofhatafsegol", + "qofhatafsegolhebrew", + "qofhebrew", + "qofhiriq", + "qofhiriqhebrew", + "qofholam", + "qofholamhebrew", + "qofpatah", + "qofpatahhebrew", + "qofqamats", + "qofqamatshebrew", + "qofqubuts", + "qofqubutshebrew", + "qofsegol", + "qofsegolhebrew", + "qofsheva", + "qofshevahebrew", + "qoftsere", + "qoftserehebrew", + "qparen", + "quarternote", + "qubuts", + "qubuts18", + "qubuts25", + "qubuts31", + "qubutshebrew", + "qubutsnarrowhebrew", + "qubutsquarterhebrew", + "qubutswidehebrew", + "questionarabic", + "questionarmenian", + "questiongreek", + "questionmonospace", + "quotedblmonospace", + "quotedblprime", + "quotedblprimereversed", + "quoteleftreversed", + "quotereversed", + "quoterightn", + "quotesinglemonospace", + "raarmenian", + "rabengali", + "racute", + "radeva", + "radical", + "radicalex", + "radoverssquare", + "radoverssquaredsquare", + "radsquare", + "rafe", + "rafehebrew", + "ragujarati", + "ragurmukhi", + "rahiragana", + "rakatakana", + "rakatakanahalfwidth", + "ralowerdiagonalbengali", + "ramiddlediagonalbengali", + "ramshorn", + "ratio", + "rbopomofo", + "rcaron", + "rcedilla", + "rcircle", + "rcommaaccent", + "rdblgrave", + "rdotaccent", + "rdotbelow", + "rdotbelowmacron", + "referencemark", + "reflexsubset", + "reflexsuperset", + "registersans", + "registerserif", + "reharabic", + "reharmenian", + "rehfinalarabic", + "rehiragana", + "rehyehaleflamarabic", + "rekatakana", + "rekatakanahalfwidth", + "resh", + "reshdageshhebrew", + "reshhatafpatah", + "reshhatafpatahhebrew", + "reshhatafsegol", + "reshhatafsegolhebrew", + "reshhebrew", + "reshhiriq", + "reshhiriqhebrew", + "reshholam", + "reshholamhebrew", + "reshpatah", + "reshpatahhebrew", + "reshqamats", + "reshqamatshebrew", + "reshqubuts", + "reshqubutshebrew", + "reshsegol", + "reshsegolhebrew", + "reshsheva", + "reshshevahebrew", + "reshtsere", + "reshtserehebrew", + "reversedtilde", + "reviahebrew", + "reviamugrashhebrew", + "revlogicalnot", + "rfishhook", + "rfishhookreversed", + "rhabengali", + "rhadeva", + "rho", + "rhook", + "rhookturned", + "rhookturnedsuperior", + "rhosymbolgreek", + "rhotichookmod", + "rieulacirclekorean", + "rieulaparenkorean", + "rieulcirclekorean", + "rieulhieuhkorean", + "rieulkiyeokkorean", + "rieulkiyeoksioskorean", + "rieulkorean", + "rieulmieumkorean", + "rieulpansioskorean", + "rieulparenkorean", + "rieulphieuphkorean", + "rieulpieupkorean", + "rieulpieupsioskorean", + "rieulsioskorean", + "rieulthieuthkorean", + "rieultikeutkorean", + "rieulyeorinhieuhkorean", + "rightangle", + "righttackbelowcmb", + "righttriangle", + "rihiragana", + "rikatakana", + "rikatakanahalfwidth", + "ringbelowcmb", + "ringcmb", + "ringhalfleft", + "ringhalfleftarmenian", + "ringhalfleftbelowcmb", + "ringhalfleftcentered", + "ringhalfright", + "ringhalfrightbelowcmb", + "ringhalfrightcentered", + "rinvertedbreve", + "rittorusquare", + "rlinebelow", + "rlongleg", + "rlonglegturned", + "rmonospace", + "rohiragana", + "rokatakana", + "rokatakanahalfwidth", + "roruathai", + "rparen", + "rrabengali", + "rradeva", + "rragurmukhi", + "rreharabic", + "rrehfinalarabic", + "rrvocalicbengali", + "rrvocalicdeva", + "rrvocalicgujarati", + "rrvocalicvowelsignbengali", + "rrvocalicvowelsigndeva", + "rrvocalicvowelsigngujarati", + "rtblock", + "rturned", + "rturnedsuperior", + "ruhiragana", + "rukatakana", + "rukatakanahalfwidth", + "rupeemarkbengali", + "rupeesignbengali", + "ruthai", + "rvocalicbengali", + "rvocalicdeva", + "rvocalicgujarati", + "rvocalicvowelsignbengali", + "rvocalicvowelsigndeva", + "rvocalicvowelsigngujarati", + "sabengali", + "sacute", + "sacutedotaccent", + "sadarabic", + "sadeva", + "sadfinalarabic", + "sadinitialarabic", + "sadmedialarabic", + "sagujarati", + "sagurmukhi", + "sahiragana", + "sakatakana", + "sakatakanahalfwidth", + "sallallahoualayhewasallamarabic", + "samekh", + "samekhdagesh", + "samekhdageshhebrew", + "samekhhebrew", + "saraaathai", + "saraaethai", + "saraaimaimalaithai", + "saraaimaimuanthai", + "saraamthai", + "saraathai", + "saraethai", + "saraiileftthai", + "saraiithai", + "saraileftthai", + "saraithai", + "saraothai", + "saraueeleftthai", + "saraueethai", + "saraueleftthai", + "sarauethai", + "sarauthai", + "sarauuthai", + "sbopomofo", + "scarondotaccent", + "scedilla", + "schwa", + "schwacyrillic", + "schwadieresiscyrillic", + "schwahook", + "scircle", + "scircumflex", + "scommaaccent", + "sdotaccent", + "sdotbelow", + "sdotbelowdotaccent", + "seagullbelowcmb", + "second", + "secondtonechinese", + "seenarabic", + "seenfinalarabic", + "seeninitialarabic", + "seenmedialarabic", + "segol", + "segol13", + "segol1f", + "segol2c", + "segolhebrew", + "segolnarrowhebrew", + "segolquarterhebrew", + "segoltahebrew", + "segolwidehebrew", + "seharmenian", + "sehiragana", + "sekatakana", + "sekatakanahalfwidth", + "semicolonarabic", + "semicolonmonospace", + "semicolonsmall", + "semivoicedmarkkana", + "semivoicedmarkkanahalfwidth", + "sentisquare", + "sentosquare", + "sevenarabic", + "sevenbengali", + "sevencircle", + "sevencircleinversesansserif", + "sevendeva", + "sevengujarati", + "sevengurmukhi", + "sevenhackarabic", + "sevenhangzhou", + "sevenideographicparen", + "sevenmonospace", + "sevenparen", + "sevenperiod", + "sevenpersian", + "sevenroman", + "seventeencircle", + "seventeenparen", + "seventeenperiod", + "seventhai", + "sfthyphen", + "shaarmenian", + "shabengali", + "shacyrillic", + "shaddaarabic", + "shaddadammaarabic", + "shaddadammatanarabic", + "shaddafathaarabic", + "shaddafathatanarabic", + "shaddakasraarabic", + "shaddakasratanarabic", + "shade", + "shadedark", + "shadelight", + "shademedium", + "shadeva", + "shagujarati", + "shagurmukhi", + "shalshelethebrew", + "shbopomofo", + "shchacyrillic", + "sheenarabic", + "sheenfinalarabic", + "sheeninitialarabic", + "sheenmedialarabic", + "sheicoptic", + "sheqel", + "sheqelhebrew", + "sheva", + "sheva115", + "sheva15", + "sheva22", + "sheva2e", + "shevahebrew", + "shevanarrowhebrew", + "shevaquarterhebrew", + "shevawidehebrew", + "shhacyrillic", + "shimacoptic", + "shin", + "shindagesh", + "shindageshhebrew", + "shindageshshindot", + "shindageshshindothebrew", + "shindageshsindot", + "shindageshsindothebrew", + "shindothebrew", + "shinhebrew", + "shinshindot", + "shinshindothebrew", + "shinsindot", + "shinsindothebrew", + "shook", + "sigma", + "sigma1", + "sigmafinal", + "sigmalunatesymbolgreek", + "sihiragana", + "sikatakana", + "sikatakanahalfwidth", + "siluqhebrew", + "siluqlefthebrew", + "similar", + "sindothebrew", + "siosacirclekorean", + "siosaparenkorean", + "sioscieuckorean", + "sioscirclekorean", + "sioskiyeokkorean", + "sioskorean", + "siosnieunkorean", + "siosparenkorean", + "siospieupkorean", + "siostikeutkorean", + "sixarabic", + "sixbengali", + "sixcircle", + "sixcircleinversesansserif", + "sixdeva", + "sixgujarati", + "sixgurmukhi", + "sixhackarabic", + "sixhangzhou", + "sixideographicparen", + "sixmonospace", + "sixparen", + "sixperiod", + "sixpersian", + "sixroman", + "sixteencircle", + "sixteencurrencydenominatorbengali", + "sixteenparen", + "sixteenperiod", + "sixthai", + "slashmonospace", + "slong", + "slongdotaccent", + "smileface", + "smonospace", + "sofpasuqhebrew", + "softhyphen", + "softsigncyrillic", + "sohiragana", + "sokatakana", + "sokatakanahalfwidth", + "soliduslongoverlaycmb", + "solidusshortoverlaycmb", + "sorusithai", + "sosalathai", + "sosothai", + "sosuathai", + "spacehackarabic", + "spade", + "spadesuitblack", + "spadesuitwhite", + "sparen", + "squarebelowcmb", + "squarecc", + "squarecm", + "squarediagonalcrosshatchfill", + "squarehorizontalfill", + "squarekg", + "squarekm", + "squarekmcapital", + "squareln", + "squarelog", + "squaremg", + "squaremil", + "squaremm", + "squaremsquared", + "squareorthogonalcrosshatchfill", + "squareupperlefttolowerrightfill", + "squareupperrighttolowerleftfill", + "squareverticalfill", + "squarewhitewithsmallblack", + "srsquare", + "ssabengali", + "ssadeva", + "ssagujarati", + "ssangcieuckorean", + "ssanghieuhkorean", + "ssangieungkorean", + "ssangkiyeokkorean", + "ssangnieunkorean", + "ssangpieupkorean", + "ssangsioskorean", + "ssangtikeutkorean", + "sterlingmonospace", + "strokelongoverlaycmb", + "strokeshortoverlaycmb", + "subset", + "subsetnotequal", + "subsetorequal", + "succeeds", + "suchthat", + "suhiragana", + "sukatakana", + "sukatakanahalfwidth", + "sukunarabic", + "summation", + "sun", + "superset", + "supersetnotequal", + "supersetorequal", + "svsquare", + "syouwaerasquare", + "tabengali", + "tackdown", + "tackleft", + "tadeva", + "tagujarati", + "tagurmukhi", + "taharabic", + "tahfinalarabic", + "tahinitialarabic", + "tahiragana", + "tahmedialarabic", + "taisyouerasquare", + "takatakana", + "takatakanahalfwidth", + "tatweelarabic", + "tau", + "tav", + "tavdages", + "tavdagesh", + "tavdageshhebrew", + "tavhebrew", + "tbar", + "tbopomofo", + "tcaron", + "tccurl", + "tcedilla", + "tcheharabic", + "tchehfinalarabic", + "tchehinitialarabic", + "tchehmedialarabic", + "tchehmeeminitialarabic", + "tcircle", + "tcircumflexbelow", + "tcommaaccent", + "tdieresis", + "tdotaccent", + "tdotbelow", + "tecyrillic", + "tedescendercyrillic", + "teharabic", + "tehfinalarabic", + "tehhahinitialarabic", + "tehhahisolatedarabic", + "tehinitialarabic", + "tehiragana", + "tehjeeminitialarabic", + "tehjeemisolatedarabic", + "tehmarbutaarabic", + "tehmarbutafinalarabic", + "tehmedialarabic", + "tehmeeminitialarabic", + "tehmeemisolatedarabic", + "tehnoonfinalarabic", + "tekatakana", + "tekatakanahalfwidth", + "telephone", + "telephoneblack", + "telishagedolahebrew", + "telishaqetanahebrew", + "tencircle", + "tenideographicparen", + "tenparen", + "tenperiod", + "tenroman", + "tesh", + "tet", + "tetdagesh", + "tetdageshhebrew", + "tethebrew", + "tetsecyrillic", + "tevirhebrew", + "tevirlefthebrew", + "thabengali", + "thadeva", + "thagujarati", + "thagurmukhi", + "thalarabic", + "thalfinalarabic", + "thanthakhatlowleftthai", + "thanthakhatlowrightthai", + "thanthakhatthai", + "thanthakhatupperleftthai", + "theharabic", + "thehfinalarabic", + "thehinitialarabic", + "thehmedialarabic", + "thereexists", + "therefore", + "theta", + "theta1", + "thetasymbolgreek", + "thieuthacirclekorean", + "thieuthaparenkorean", + "thieuthcirclekorean", + "thieuthkorean", + "thieuthparenkorean", + "thirteencircle", + "thirteenparen", + "thirteenperiod", + "thonangmonthothai", + "thook", + "thophuthaothai", + "thothahanthai", + "thothanthai", + "thothongthai", + "thothungthai", + "thousandcyrillic", + "thousandsseparatorarabic", + "thousandsseparatorpersian", + "threearabic", + "threebengali", + "threecircle", + "threecircleinversesansserif", + "threedeva", + "threegujarati", + "threegurmukhi", + "threehackarabic", + "threehangzhou", + "threeideographicparen", + "threemonospace", + "threenumeratorbengali", + "threeparen", + "threeperiod", + "threepersian", + "threeroman", + "threethai", + "thzsquare", + "tihiragana", + "tikatakana", + "tikatakanahalfwidth", + "tikeutacirclekorean", + "tikeutaparenkorean", + "tikeutcirclekorean", + "tikeutkorean", + "tikeutparenkorean", + "tildebelowcmb", + "tildecmb", + "tildecomb", + "tildedoublecmb", + "tildeoperator", + "tildeoverlaycmb", + "tildeverticalcmb", + "timescircle", + "tipehahebrew", + "tipehalefthebrew", + "tippigurmukhi", + "titlocyrilliccmb", + "tiwnarmenian", + "tlinebelow", + "tmonospace", + "toarmenian", + "tohiragana", + "tokatakana", + "tokatakanahalfwidth", + "tonebarextrahighmod", + "tonebarextralowmod", + "tonebarhighmod", + "tonebarlowmod", + "tonebarmidmod", + "tonefive", + "tonesix", + "tonetwo", + "tonos", + "tonsquare", + "topatakthai", + "tortoiseshellbracketleft", + "tortoiseshellbracketleftsmall", + "tortoiseshellbracketleftvertical", + "tortoiseshellbracketright", + "tortoiseshellbracketrightsmall", + "tortoiseshellbracketrightvertical", + "totaothai", + "tpalatalhook", + "tparen", + "trademarksans", + "trademarkserif", + "tretroflexhook", + "triagdn", + "triaglf", + "triagrt", + "triagup", + "ts", + "tsadi", + "tsadidagesh", + "tsadidageshhebrew", + "tsadihebrew", + "tsecyrillic", + "tsere", + "tsere12", + "tsere1e", + "tsere2b", + "tserehebrew", + "tserenarrowhebrew", + "tserequarterhebrew", + "tserewidehebrew", + "tshecyrillic", + "ttabengali", + "ttadeva", + "ttagujarati", + "ttagurmukhi", + "tteharabic", + "ttehfinalarabic", + "ttehinitialarabic", + "ttehmedialarabic", + "tthabengali", + "tthadeva", + "tthagujarati", + "tthagurmukhi", + "tturned", + "tuhiragana", + "tukatakana", + "tukatakanahalfwidth", + "tusmallhiragana", + "tusmallkatakana", + "tusmallkatakanahalfwidth", + "twelvecircle", + "twelveparen", + "twelveperiod", + "twelveroman", + "twentycircle", + "twentyhangzhou", + "twentyparen", + "twentyperiod", + "twoarabic", + "twobengali", + "twocircle", + "twocircleinversesansserif", + "twodeva", + "twodotleader", + "twodotleadervertical", + "twogujarati", + "twogurmukhi", + "twohackarabic", + "twohangzhou", + "twoideographicparen", + "twomonospace", + "twonumeratorbengali", + "twoparen", + "twoperiod", + "twopersian", + "tworoman", + "twostroke", + "twothai", + "ubar", + "ubengali", + "ubopomofo", + "ubreve", + "ucaron", + "ucircle", + "ucircumflexbelow", + "ucyrillic", + "udattadeva", + "udblacute", + "udblgrave", + "udeva", + "udieresisacute", + "udieresisbelow", + "udieresiscaron", + "udieresiscyrillic", + "udieresisgrave", + "udieresismacron", + "udotbelow", + "ugujarati", + "ugurmukhi", + "uhiragana", + "uhookabove", + "uhorn", + "uhornacute", + "uhorndotbelow", + "uhorngrave", + "uhornhookabove", + "uhorntilde", + "uhungarumlaut", + "uhungarumlautcyrillic", + "uinvertedbreve", + "ukatakana", + "ukatakanahalfwidth", + "ukcyrillic", + "ukorean", + "umacron", + "umacroncyrillic", + "umacrondieresis", + "umatragurmukhi", + "umonospace", + "underscoredbl", + "underscoremonospace", + "underscorevertical", + "underscorewavy", + "union", + "universal", + "uogonek", + "uparen", + "upblock", + "upperdothebrew", + "upsilon", + "upsilondieresis", + "upsilondieresistonos", + "upsilonlatin", + "upsilontonos", + "uptackbelowcmb", + "uptackmod", + "uragurmukhi", + "uring", + "ushortcyrillic", + "usmallhiragana", + "usmallkatakana", + "usmallkatakanahalfwidth", + "ustraightcyrillic", + "ustraightstrokecyrillic", + "utilde", + "utildeacute", + "utildebelow", + "uubengali", + "uudeva", + "uugujarati", + "uugurmukhi", + "uumatragurmukhi", + "uuvowelsignbengali", + "uuvowelsigndeva", + "uuvowelsigngujarati", + "uvowelsignbengali", + "uvowelsigndeva", + "uvowelsigngujarati", + "vadeva", + "vagujarati", + "vagurmukhi", + "vakatakana", + "vav", + "vavdagesh", + "vavdagesh65", + "vavdageshhebrew", + "vavhebrew", + "vavholam", + "vavholamhebrew", + "vavvavhebrew", + "vavyodhebrew", + "vcircle", + "vdotbelow", + "vecyrillic", + "veharabic", + "vehfinalarabic", + "vehinitialarabic", + "vehmedialarabic", + "vekatakana", + "venus", + "verticalbar", + "verticallineabovecmb", + "verticallinebelowcmb", + "verticallinelowmod", + "verticallinemod", + "vewarmenian", + "vhook", + "vikatakana", + "viramabengali", + "viramadeva", + "viramagujarati", + "visargabengali", + "visargadeva", + "visargagujarati", + "vmonospace", + "voarmenian", + "voicediterationhiragana", + "voicediterationkatakana", + "voicedmarkkana", + "voicedmarkkanahalfwidth", + "vokatakana", + "vparen", + "vtilde", + "vturned", + "vuhiragana", + "vukatakana", + "wacute", + "waekorean", + "wahiragana", + "wakatakana", + "wakatakanahalfwidth", + "wakorean", + "wasmallhiragana", + "wasmallkatakana", + "wattosquare", + "wavedash", + "wavyunderscorevertical", + "wawarabic", + "wawfinalarabic", + "wawhamzaabovearabic", + "wawhamzaabovefinalarabic", + "wbsquare", + "wcircle", + "wcircumflex", + "wdieresis", + "wdotaccent", + "wdotbelow", + "wehiragana", + "weierstrass", + "wekatakana", + "wekorean", + "weokorean", + "wgrave", + "whitebullet", + "whitecircle", + "whitecircleinverse", + "whitecornerbracketleft", + "whitecornerbracketleftvertical", + "whitecornerbracketright", + "whitecornerbracketrightvertical", + "whitediamond", + "whitediamondcontainingblacksmalldiamond", + "whitedownpointingsmalltriangle", + "whitedownpointingtriangle", + "whiteleftpointingsmalltriangle", + "whiteleftpointingtriangle", + "whitelenticularbracketleft", + "whitelenticularbracketright", + "whiterightpointingsmalltriangle", + "whiterightpointingtriangle", + "whitesmallsquare", + "whitesmilingface", + "whitesquare", + "whitestar", + "whitetelephone", + "whitetortoiseshellbracketleft", + "whitetortoiseshellbracketright", + "whiteuppointingsmalltriangle", + "whiteuppointingtriangle", + "wihiragana", + "wikatakana", + "wikorean", + "wmonospace", + "wohiragana", + "wokatakana", + "wokatakanahalfwidth", + "won", + "wonmonospace", + "wowaenthai", + "wparen", + "wring", + "wsuperior", + "wturned", + "wynn", + "xabovecmb", + "xbopomofo", + "xcircle", + "xdieresis", + "xdotaccent", + "xeharmenian", + "xi", + "xmonospace", + "xparen", + "xsuperior", + "yaadosquare", + "yabengali", + "yadeva", + "yaekorean", + "yagujarati", + "yagurmukhi", + "yahiragana", + "yakatakana", + "yakatakanahalfwidth", + "yakorean", + "yamakkanthai", + "yasmallhiragana", + "yasmallkatakana", + "yasmallkatakanahalfwidth", + "yatcyrillic", + "ycircle", + "ycircumflex", + "ydotaccent", + "ydotbelow", + "yeharabic", + "yehbarreearabic", + "yehbarreefinalarabic", + "yehfinalarabic", + "yehhamzaabovearabic", + "yehhamzaabovefinalarabic", + "yehhamzaaboveinitialarabic", + "yehhamzaabovemedialarabic", + "yehinitialarabic", + "yehmedialarabic", + "yehmeeminitialarabic", + "yehmeemisolatedarabic", + "yehnoonfinalarabic", + "yehthreedotsbelowarabic", + "yekorean", + "yenmonospace", + "yeokorean", + "yeorinhieuhkorean", + "yerahbenyomohebrew", + "yerahbenyomolefthebrew", + "yericyrillic", + "yerudieresiscyrillic", + "yesieungkorean", + "yesieungpansioskorean", + "yesieungsioskorean", + "yetivhebrew", + "ygrave", + "yhook", + "yhookabove", + "yiarmenian", + "yicyrillic", + "yikorean", + "yinyang", + "yiwnarmenian", + "ymonospace", + "yod", + "yoddagesh", + "yoddageshhebrew", + "yodhebrew", + "yodyodhebrew", + "yodyodpatahhebrew", + "yohiragana", + "yoikorean", + "yokatakana", + "yokatakanahalfwidth", + "yokorean", + "yosmallhiragana", + "yosmallkatakana", + "yosmallkatakanahalfwidth", + "yotgreek", + "yoyaekorean", + "yoyakorean", + "yoyakthai", + "yoyingthai", + "yparen", + "ypogegrammeni", + "ypogegrammenigreekcmb", + "yr", + "yring", + "ysuperior", + "ytilde", + "yturned", + "yuhiragana", + "yuikorean", + "yukatakana", + "yukatakanahalfwidth", + "yukorean", + "yusbigcyrillic", + "yusbigiotifiedcyrillic", + "yuslittlecyrillic", + "yuslittleiotifiedcyrillic", + "yusmallhiragana", + "yusmallkatakana", + "yusmallkatakanahalfwidth", + "yuyekorean", + "yuyeokorean", + "yyabengali", + "yyadeva", + "zaarmenian", + "zacute", + "zadeva", + "zagurmukhi", + "zaharabic", + "zahfinalarabic", + "zahinitialarabic", + "zahiragana", + "zahmedialarabic", + "zainarabic", + "zainfinalarabic", + "zakatakana", + "zaqefgadolhebrew", + "zaqefqatanhebrew", + "zarqahebrew", + "zayin", + "zayindagesh", + "zayindageshhebrew", + "zayinhebrew", + "zbopomofo", + "zcircle", + "zcircumflex", + "zcurl", + "zdot", + "zdotaccent", + "zdotbelow", + "zecyrillic", + "zedescendercyrillic", + "zedieresiscyrillic", + "zehiragana", + "zekatakana", + "zeroarabic", + "zerobengali", + "zerodeva", + "zerogujarati", + "zerogurmukhi", + "zerohackarabic", + "zeromonospace", + "zeropersian", + "zerothai", + "zerowidthjoiner", + "zerowidthnonjoiner", + "zerowidthspace", + "zeta", + "zhbopomofo", + "zhearmenian", + "zhebrevecyrillic", + "zhecyrillic", + "zhedescendercyrillic", + "zhedieresiscyrillic", + "zihiragana", + "zikatakana", + "zinorhebrew", + "zlinebelow", + "zmonospace", + "zohiragana", + "zokatakana", + "zparen", + "zretroflexhook", + "zstroke", + "zuhiragana", + "zukatakana", + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + + NULL + }; + + + static const char* const * const sid_standard_names = ps_glyph_names + 2; + + +#define NUM_SID_GLYPHS 391 + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST +#define NUM_ADOBE_GLYPHS 4294 +#else +#define NUM_ADOBE_GLYPHS 391 +#endif + + + static const unsigned short mac_standard_names[259] = + { + 2, + 0, + 1, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 106, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 126, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 175, + 177, + 179, + 180, + 188, + 191, + 197, + 202, + 205, + 203, + 204, + 207, + 206, + 208, + 209, + 212, + 210, + 211, + 213, + 216, + 214, + 215, + 217, + 218, + 221, + 219, + 220, + 222, + 224, + 227, + 225, + 226, + 114, + 163, + 99, + 100, + 104, + 118, + 117, + 151, + 167, + 172, + 155, + 127, + 133, + 2919, + 140, + 143, + 2413, + 158, + 2642, + 2156, + 102, + 154, + 3092, + 3681, + 3192, + 3153, + 2415, + 141, + 145, + 741, + 146, + 149, + 125, + 98, + 153, + 3284, + 103, + 1353, + 472, + 108, + 122, + 123, + 2901, + 176, + 178, + 193, + 144, + 150, + 113, + 139, + 107, + 121, + 67, + 10, + 161, + 2677, + 229, + 200, + 101, + 105, + 109, + 110, + 111, + 112, + 115, + 116, + 119, + 120, + 124, + 174, + 181, + 173, + 182, + 183, + 184, + 185, + 186, + 187, + 189, + 190, + 1351, + 192, + 195, + 196, + 198, + 147, + 128, + 129, + 130, + 131, + 132, + 134, + 135, + 136, + 137, + 138, + 142, + 148, + 194, + 223, + 201, + 230, + 162, + 156, + 169, + 199, + 228, + 159, + 164, + 168, + 170, + 152, + 166, + 171, + 157, + 160, + 165, + 2074, + 556, + 2091, + 609, + 836, + 3465, + 438, + 1545, + 440, + 1560, + 1767, + 0 + }; + + + + static const unsigned short ps_names_to_unicode[4295] = + { + 0, + 0x0020U, + 0x0021U, + 0x0022U, + 0x0023U, + 0x0024U, + 0x0025U, + 0x0026U, + 0x2019U, + 0x0028U, + 0x0029U, + 0x002AU, + 0x002BU, + 0x002CU, + 0x002DU, + 0x002EU, + 0x002FU, + 0x0030U, + 0x0031U, + 0x0032U, + 0x0033U, + 0x0034U, + 0x0035U, + 0x0036U, + 0x0037U, + 0x0038U, + 0x0039U, + 0x003AU, + 0x003BU, + 0x003CU, + 0x003DU, + 0x003EU, + 0x003FU, + 0x0040U, + 0x0041U, + 0x0042U, + 0x0043U, + 0x0044U, + 0x0045U, + 0x0046U, + 0x0047U, + 0x0048U, + 0x0049U, + 0x004AU, + 0x004BU, + 0x004CU, + 0x004DU, + 0x004EU, + 0x004FU, + 0x0050U, + 0x0051U, + 0x0052U, + 0x0053U, + 0x0054U, + 0x0055U, + 0x0056U, + 0x0057U, + 0x0058U, + 0x0059U, + 0x005AU, + 0x005BU, + 0x005CU, + 0x005DU, + 0x005EU, + 0x005FU, + 0x2018U, + 0x0061U, + 0x0062U, + 0x0063U, + 0x0064U, + 0x0065U, + 0x0066U, + 0x0067U, + 0x0068U, + 0x0069U, + 0x006AU, + 0x006BU, + 0x006CU, + 0x006DU, + 0x006EU, + 0x006FU, + 0x0070U, + 0x0071U, + 0x0072U, + 0x0073U, + 0x0074U, + 0x0075U, + 0x0076U, + 0x0077U, + 0x0078U, + 0x0079U, + 0x007AU, + 0x007BU, + 0x007CU, + 0x007DU, + 0x007EU, + 0x00A1U, + 0x00A2U, + 0x00A3U, + 0x2044U, + 0x00A5U, + 0x0192U, + 0x00A7U, + 0x00A4U, + 0x0027U, + 0x201CU, + 0x00ABU, + 0x2039U, + 0x203AU, + 0xFB01U, + 0xFB02U, + 0x2013U, + 0x2020U, + 0x2021U, + 0x00B7U, + 0x00B6U, + 0x2022U, + 0x201AU, + 0x201EU, + 0x201DU, + 0x00BBU, + 0x2026U, + 0x2030U, + 0x00BFU, + 0x0060U, + 0x00B4U, + 0x02C6U, + 0x02DCU, + 0x00AFU, + 0x02D8U, + 0x02D9U, + 0x00A8U, + 0x02DAU, + 0x00B8U, + 0x02DDU, + 0x02DBU, + 0x02C7U, + 0x2014U, + 0x00C6U, + 0x00AAU, + 0x0141U, + 0x00D8U, + 0x0152U, + 0x00BAU, + 0x00E6U, + 0x0131U, + 0x0142U, + 0x00F8U, + 0x0153U, + 0x00DFU, + 0x00B9U, + 0x00ACU, + 0x00B5U, + 0x2122U, + 0x00D0U, + 0x00BDU, + 0x00B1U, + 0x00DEU, + 0x00BCU, + 0x00F7U, + 0x00A6U, + 0x00B0U, + 0x00FEU, + 0x00BEU, + 0x00B2U, + 0x00AEU, + 0x2212U, + 0x00F0U, + 0x00D7U, + 0x00B3U, + 0x00A9U, + 0x00C1U, + 0x00C2U, + 0x00C4U, + 0x00C0U, + 0x00C5U, + 0x00C3U, + 0x00C7U, + 0x00C9U, + 0x00CAU, + 0x00CBU, + 0x00C8U, + 0x00CDU, + 0x00CEU, + 0x00CFU, + 0x00CCU, + 0x00D1U, + 0x00D3U, + 0x00D4U, + 0x00D6U, + 0x00D2U, + 0x00D5U, + 0x0160U, + 0x00DAU, + 0x00DBU, + 0x00DCU, + 0x00D9U, + 0x00DDU, + 0x0178U, + 0x017DU, + 0x00E1U, + 0x00E2U, + 0x00E4U, + 0x00E0U, + 0x00E5U, + 0x00E3U, + 0x00E7U, + 0x00E9U, + 0x00EAU, + 0x00EBU, + 0x00E8U, + 0x00EDU, + 0x00EEU, + 0x00EFU, + 0x00ECU, + 0x00F1U, + 0x00F3U, + 0x00F4U, + 0x00F6U, + 0x00F2U, + 0x00F5U, + 0x0161U, + 0x00FAU, + 0x00FBU, + 0x00FCU, + 0x00F9U, + 0x00FDU, + 0x00FFU, + 0x017EU, + 0xF721U, + 0xF6F8U, + 0xF724U, + 0xF6E4U, + 0xF726U, + 0xF7B4U, + 0x207DU, + 0x207EU, + 0x2025U, + 0x2024U, + 0xF730U, + 0xF731U, + 0xF732U, + 0xF733U, + 0xF734U, + 0xF735U, + 0xF736U, + 0xF737U, + 0xF738U, + 0xF739U, + 0xF6E2U, + 0xF6DEU, + 0xF6E8U, + 0xF73FU, + 0xF6E9U, + 0xF6EAU, + 0xF6E0U, + 0xF6EBU, + 0xF6ECU, + 0xF6EDU, + 0xF6EEU, + 0xF6EFU, + 0x207FU, + 0xF6F0U, + 0xF6F1U, + 0xF6F2U, + 0xF6F3U, + 0xFB00U, + 0xFB03U, + 0xFB04U, + 0x208DU, + 0x208EU, + 0xF6F6U, + 0xF6E6U, + 0xF760U, + 0xF761U, + 0xF762U, + 0xF763U, + 0xF764U, + 0xF765U, + 0xF766U, + 0xF767U, + 0xF768U, + 0xF769U, + 0xF76AU, + 0xF76BU, + 0xF76CU, + 0xF76DU, + 0xF76EU, + 0xF76FU, + 0xF770U, + 0xF771U, + 0xF772U, + 0xF773U, + 0xF774U, + 0xF775U, + 0xF776U, + 0xF777U, + 0xF778U, + 0xF779U, + 0xF77AU, + 0x20A1U, + 0xF6DCU, + 0xF6DDU, + 0xF6FEU, + 0xF7A1U, + 0xF7A2U, + 0xF6F9U, + 0xF6FDU, + 0xF6FFU, + 0xF7A8U, + 0xF6F4U, + 0xF6F5U, + 0xF6F7U, + 0xF7AFU, + 0x2012U, + 0xF6E5U, + 0xF6FBU, + 0xF6FCU, + 0xF7B8U, + 0xF7BFU, + 0x215BU, + 0x215CU, + 0x215DU, + 0x215EU, + 0x2153U, + 0x2154U, + 0x2070U, + 0x2074U, + 0x2075U, + 0x2076U, + 0x2077U, + 0x2078U, + 0x2079U, + 0x2080U, + 0x2081U, + 0x2082U, + 0x2083U, + 0x2084U, + 0x2085U, + 0x2086U, + 0x2087U, + 0x2088U, + 0x2089U, + 0xF6DFU, + 0xF6E3U, + 0xF6E7U, + 0xF6E1U, + 0xF7E0U, + 0xF7E1U, + 0xF7E2U, + 0xF7E3U, + 0xF7E4U, + 0xF7E5U, + 0xF7E6U, + 0xF7E7U, + 0xF7E8U, + 0xF7E9U, + 0xF7EAU, + 0xF7EBU, + 0xF7ECU, + 0xF7EDU, + 0xF7EEU, + 0xF7EFU, + 0xF7F0U, + 0xF7F1U, + 0xF7F2U, + 0xF7F3U, + 0xF7F4U, + 0xF7F5U, + 0xF7F6U, + 0xF6FAU, + 0xF7F8U, + 0xF7F9U, + 0xF7FAU, + 0xF7FBU, + 0xF7FCU, + 0xF7FDU, + 0xF7FEU, + 0xF7FFU, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + 0x01FCU, + 0x01E2U, + 0x0102U, + 0x1EAEU, + 0x04D0U, + 0x1EB6U, + 0x1EB0U, + 0x1EB2U, + 0x1EB4U, + 0x01CDU, + 0x24B6U, + 0x1EA4U, + 0x1EACU, + 0x1EA6U, + 0x1EA8U, + 0x1EAAU, + 0xF6C9U, + 0x0410U, + 0x0200U, + 0x04D2U, + 0x01DEU, + 0x1EA0U, + 0x01E0U, + 0x1EA2U, + 0x04D4U, + 0x0202U, + 0x0391U, + 0x0386U, + 0x0100U, + 0xFF21U, + 0x0104U, + 0x01FAU, + 0x1E00U, + 0x0531U, + 0x24B7U, + 0x1E02U, + 0x1E04U, + 0x0411U, + 0x0532U, + 0x0392U, + 0x0181U, + 0x1E06U, + 0xFF22U, + 0x0182U, + 0x053EU, + 0x0106U, + 0xF6CAU, + 0x010CU, + 0x1E08U, + 0x24B8U, + 0x0108U, + 0x010AU, + 0x010AU, + 0x0549U, + 0x04BCU, + 0x0427U, + 0x04BEU, + 0x04B6U, + 0x04F4U, + 0x0543U, + 0x04CBU, + 0x04B8U, + 0x03A7U, + 0x0187U, + 0xFF23U, + 0x0551U, + 0x01F1U, + 0x01C4U, + 0x0534U, + 0x0189U, + 0x010EU, + 0x1E10U, + 0x24B9U, + 0x1E12U, + 0x0110U, + 0x1E0AU, + 0x1E0CU, + 0x0414U, + 0x03EEU, + 0x2206U, + 0x0394U, + 0x018AU, + 0xF6CBU, + 0xF6CCU, + 0xF6CDU, + 0x03DCU, + 0x0402U, + 0x1E0EU, + 0xFF24U, + 0x0110U, + 0x018BU, + 0x01F2U, + 0x01C5U, + 0x04E0U, + 0x0405U, + 0x040FU, + 0x0114U, + 0x011AU, + 0x1E1CU, + 0x0535U, + 0x24BAU, + 0x1EBEU, + 0x1E18U, + 0x1EC6U, + 0x1EC0U, + 0x1EC2U, + 0x1EC4U, + 0x0404U, + 0x0204U, + 0x0116U, + 0x0116U, + 0x1EB8U, + 0x0424U, + 0x0537U, + 0x1EBAU, + 0x2167U, + 0x0206U, + 0x0464U, + 0x041BU, + 0x216AU, + 0x0112U, + 0x1E16U, + 0x1E14U, + 0x041CU, + 0xFF25U, + 0x041DU, + 0x04A2U, + 0x014AU, + 0x04A4U, + 0x04C7U, + 0x0118U, + 0x0190U, + 0x0395U, + 0x0388U, + 0x0420U, + 0x018EU, + 0x042DU, + 0x0421U, + 0x04AAU, + 0x01A9U, + 0x0397U, + 0x0538U, + 0x0389U, + 0x1EBCU, + 0x1E1AU, + 0x20ACU, + 0x01B7U, + 0x01EEU, + 0x01B8U, + 0x24BBU, + 0x1E1EU, + 0x0556U, + 0x03E4U, + 0x0191U, + 0x0472U, + 0x2164U, + 0xFF26U, + 0x2163U, + 0x3387U, + 0x01F4U, + 0x0393U, + 0x0194U, + 0x03EAU, + 0x011EU, + 0x01E6U, + 0x0122U, + 0x24BCU, + 0x011CU, + 0x0122U, + 0x0120U, + 0x0120U, + 0x0413U, + 0x0542U, + 0x0494U, + 0x0492U, + 0x0490U, + 0x0193U, + 0x0533U, + 0x0403U, + 0x1E20U, + 0xFF27U, + 0xF6CEU, + 0x029BU, + 0x01E4U, + 0x25CFU, + 0x25AAU, + 0x25ABU, + 0x25A1U, + 0x33CBU, + 0x04A8U, + 0x04B2U, + 0x042AU, + 0x0126U, + 0x1E2AU, + 0x1E28U, + 0x24BDU, + 0x0124U, + 0x1E26U, + 0x1E22U, + 0x1E24U, + 0xFF28U, + 0x0540U, + 0x03E8U, + 0xF6CFU, + 0x3390U, + 0x042FU, + 0x0132U, + 0x042EU, + 0x012CU, + 0x01CFU, + 0x24BEU, + 0x0406U, + 0x0208U, + 0x1E2EU, + 0x04E4U, + 0x0130U, + 0x0130U, + 0x1ECAU, + 0x04D6U, + 0x0415U, + 0x2111U, + 0x1EC8U, + 0x0418U, + 0x020AU, + 0x0419U, + 0x012AU, + 0x04E2U, + 0xFF29U, + 0x053BU, + 0x0401U, + 0x012EU, + 0x0399U, + 0x0196U, + 0x03AAU, + 0x038AU, + 0x0197U, + 0x0128U, + 0x1E2CU, + 0x0474U, + 0x0476U, + 0x0541U, + 0x24BFU, + 0x0134U, + 0x0408U, + 0x054BU, + 0xFF2AU, + 0x3385U, + 0x33CDU, + 0x04A0U, + 0x1E30U, + 0x041AU, + 0x049AU, + 0x04C3U, + 0x039AU, + 0x049EU, + 0x049CU, + 0x01E8U, + 0x0136U, + 0x24C0U, + 0x0136U, + 0x1E32U, + 0x0554U, + 0x053FU, + 0x0425U, + 0x03E6U, + 0x0198U, + 0x040CU, + 0x1E34U, + 0xFF2BU, + 0x0480U, + 0x03DEU, + 0x046EU, + 0x01C7U, + 0xF6BFU, + 0x0139U, + 0x039BU, + 0x013DU, + 0x013BU, + 0x24C1U, + 0x1E3CU, + 0x013BU, + 0x013FU, + 0x013FU, + 0x1E36U, + 0x1E38U, + 0x053CU, + 0x01C8U, + 0x0409U, + 0x1E3AU, + 0xFF2CU, + 0x3386U, + 0xF6D0U, + 0x1E3EU, + 0x24C2U, + 0x1E40U, + 0x1E42U, + 0x0544U, + 0xFF2DU, + 0x019CU, + 0x039CU, + 0x01CAU, + 0x0143U, + 0x0147U, + 0x0145U, + 0x24C3U, + 0x1E4AU, + 0x0145U, + 0x1E44U, + 0x1E46U, + 0x019DU, + 0x2168U, + 0x01CBU, + 0x040AU, + 0x1E48U, + 0xFF2EU, + 0x0546U, + 0x039DU, + 0x04E8U, + 0x04EAU, + 0x014EU, + 0x01D1U, + 0x019FU, + 0x24C4U, + 0x1ED0U, + 0x1ED8U, + 0x1ED2U, + 0x1ED4U, + 0x1ED6U, + 0x041EU, + 0x0150U, + 0x020CU, + 0x04E6U, + 0x1ECCU, + 0x0555U, + 0x2126U, + 0x1ECEU, + 0x01A0U, + 0x1EDAU, + 0x1EE2U, + 0x1EDCU, + 0x1EDEU, + 0x1EE0U, + 0x0150U, + 0x01A2U, + 0x020EU, + 0x014CU, + 0x1E52U, + 0x1E50U, + 0x2126U, + 0x0460U, + 0x03A9U, + 0x047AU, + 0x047CU, + 0x038FU, + 0x039FU, + 0x038CU, + 0xFF2FU, + 0x2160U, + 0x01EAU, + 0x01ECU, + 0x0186U, + 0x01FEU, + 0x01FEU, + 0x047EU, + 0x1E4CU, + 0x1E4EU, + 0x1E54U, + 0x24C5U, + 0x1E56U, + 0x041FU, + 0x054AU, + 0x04A6U, + 0x03A6U, + 0x01A4U, + 0x03A0U, + 0x0553U, + 0xFF30U, + 0x03A8U, + 0x0470U, + 0x24C6U, + 0xFF31U, + 0x054CU, + 0x0154U, + 0x0158U, + 0x0156U, + 0x24C7U, + 0x0156U, + 0x0210U, + 0x1E58U, + 0x1E5AU, + 0x1E5CU, + 0x0550U, + 0x211CU, + 0x03A1U, + 0x0212U, + 0x1E5EU, + 0xFF32U, + 0x0281U, + 0x02B6U, + 0x250CU, + 0x2514U, + 0x2510U, + 0x2518U, + 0x253CU, + 0x252CU, + 0x2534U, + 0x251CU, + 0x2524U, + 0x2500U, + 0x2502U, + 0x2561U, + 0x2562U, + 0x2556U, + 0x2555U, + 0x2563U, + 0x2551U, + 0x2557U, + 0x255DU, + 0x255CU, + 0x255BU, + 0x255EU, + 0x255FU, + 0x255AU, + 0x2554U, + 0x2569U, + 0x2566U, + 0x2560U, + 0x2550U, + 0x256CU, + 0x2567U, + 0x2568U, + 0x2564U, + 0x2565U, + 0x2559U, + 0x2558U, + 0x2552U, + 0x2553U, + 0x256BU, + 0x256AU, + 0x015AU, + 0x1E64U, + 0x03E0U, + 0x1E66U, + 0x015EU, + 0x018FU, + 0x04D8U, + 0x04DAU, + 0x24C8U, + 0x015CU, + 0x0218U, + 0x1E60U, + 0x1E62U, + 0x1E68U, + 0x054DU, + 0x2166U, + 0x0547U, + 0x0428U, + 0x0429U, + 0x03E2U, + 0x04BAU, + 0x03ECU, + 0x03A3U, + 0x2165U, + 0xFF33U, + 0x042CU, + 0x03DAU, + 0x03A4U, + 0x0166U, + 0x0164U, + 0x0162U, + 0x24C9U, + 0x1E70U, + 0x0162U, + 0x1E6AU, + 0x1E6CU, + 0x0422U, + 0x04ACU, + 0x2169U, + 0x04B4U, + 0x0398U, + 0x01ACU, + 0x2162U, + 0x054FU, + 0x1E6EU, + 0xFF34U, + 0x0539U, + 0x01BCU, + 0x0184U, + 0x01A7U, + 0x01AEU, + 0x0426U, + 0x040BU, + 0x216BU, + 0x2161U, + 0x016CU, + 0x01D3U, + 0x24CAU, + 0x1E76U, + 0x0423U, + 0x0170U, + 0x0214U, + 0x01D7U, + 0x1E72U, + 0x01D9U, + 0x04F0U, + 0x01DBU, + 0x01D5U, + 0x1EE4U, + 0x1EE6U, + 0x01AFU, + 0x1EE8U, + 0x1EF0U, + 0x1EEAU, + 0x1EECU, + 0x1EEEU, + 0x0170U, + 0x04F2U, + 0x0216U, + 0x0478U, + 0x016AU, + 0x04EEU, + 0x1E7AU, + 0xFF35U, + 0x0172U, + 0x03A5U, + 0x03D2U, + 0x03D3U, + 0x01B1U, + 0x03ABU, + 0x03D4U, + 0x03D2U, + 0x038EU, + 0x016EU, + 0x040EU, + 0x04AEU, + 0x04B0U, + 0x0168U, + 0x1E78U, + 0x1E74U, + 0x24CBU, + 0x1E7EU, + 0x0412U, + 0x054EU, + 0x01B2U, + 0xFF36U, + 0x0548U, + 0x1E7CU, + 0x1E82U, + 0x24CCU, + 0x0174U, + 0x1E84U, + 0x1E86U, + 0x1E88U, + 0x1E80U, + 0xFF37U, + 0x24CDU, + 0x1E8CU, + 0x1E8AU, + 0x053DU, + 0x039EU, + 0xFF38U, + 0x0462U, + 0x24CEU, + 0x0176U, + 0x1E8EU, + 0x1EF4U, + 0x042BU, + 0x04F8U, + 0x1EF2U, + 0x01B3U, + 0x1EF6U, + 0x0545U, + 0x0407U, + 0x0552U, + 0xFF39U, + 0x1EF8U, + 0x046AU, + 0x046CU, + 0x0466U, + 0x0468U, + 0x0536U, + 0x0179U, + 0x24CFU, + 0x1E90U, + 0x017BU, + 0x017BU, + 0x1E92U, + 0x0417U, + 0x0498U, + 0x04DEU, + 0x0396U, + 0x053AU, + 0x04C1U, + 0x0416U, + 0x0496U, + 0x04DCU, + 0x1E94U, + 0xFF3AU, + 0x01B5U, + 0x0986U, + 0x0906U, + 0x0A86U, + 0x0A06U, + 0x0A3EU, + 0x3303U, + 0x09BEU, + 0x093EU, + 0x0ABEU, + 0x055FU, + 0x0970U, + 0x0985U, + 0x311AU, + 0x0103U, + 0x1EAFU, + 0x04D1U, + 0x1EB7U, + 0x1EB1U, + 0x1EB3U, + 0x1EB5U, + 0x01CEU, + 0x24D0U, + 0x1EA5U, + 0x1EADU, + 0x1EA7U, + 0x1EA9U, + 0x1EABU, + 0x0317U, + 0x0301U, + 0x0301U, + 0x0954U, + 0x02CFU, + 0x0341U, + 0x0430U, + 0x0201U, + 0x0A71U, + 0x0905U, + 0x04D3U, + 0x01DFU, + 0x1EA1U, + 0x01E1U, + 0x01FDU, + 0x3150U, + 0x01E3U, + 0x2015U, + 0x20A4U, + 0x0410U, + 0x0411U, + 0x0412U, + 0x0413U, + 0x0414U, + 0x0415U, + 0x0401U, + 0x0416U, + 0x0417U, + 0x0418U, + 0x0419U, + 0x041AU, + 0x041BU, + 0x041CU, + 0x041DU, + 0x041EU, + 0x041FU, + 0x0420U, + 0x0421U, + 0x0422U, + 0x0423U, + 0x0424U, + 0x0425U, + 0x0426U, + 0x0427U, + 0x0428U, + 0x0429U, + 0x042AU, + 0x042BU, + 0x042CU, + 0x042DU, + 0x042EU, + 0x042FU, + 0x0490U, + 0x0402U, + 0x0403U, + 0x0404U, + 0x0405U, + 0x0406U, + 0x0407U, + 0x0408U, + 0x0409U, + 0x040AU, + 0x040BU, + 0x040CU, + 0x040EU, + 0xF6C4U, + 0xF6C5U, + 0x0430U, + 0x0431U, + 0x0432U, + 0x0433U, + 0x0434U, + 0x0435U, + 0x0451U, + 0x0436U, + 0x0437U, + 0x0438U, + 0x0439U, + 0x043AU, + 0x043BU, + 0x043CU, + 0x043DU, + 0x043EU, + 0x043FU, + 0x0440U, + 0x0441U, + 0x0442U, + 0x0443U, + 0x0444U, + 0x0445U, + 0x0446U, + 0x0447U, + 0x0448U, + 0x0449U, + 0x044AU, + 0x044BU, + 0x044CU, + 0x044DU, + 0x044EU, + 0x044FU, + 0x0491U, + 0x0452U, + 0x0453U, + 0x0454U, + 0x0455U, + 0x0456U, + 0x0457U, + 0x0458U, + 0x0459U, + 0x045AU, + 0x045BU, + 0x045CU, + 0x045EU, + 0x040FU, + 0x0462U, + 0x0472U, + 0x0474U, + 0xF6C6U, + 0x045FU, + 0x0463U, + 0x0473U, + 0x0475U, + 0xF6C7U, + 0xF6C8U, + 0x04D9U, + 0x200EU, + 0x200FU, + 0x200DU, + 0x066AU, + 0x060CU, + 0x0660U, + 0x0661U, + 0x0662U, + 0x0663U, + 0x0664U, + 0x0665U, + 0x0666U, + 0x0667U, + 0x0668U, + 0x0669U, + 0x061BU, + 0x061FU, + 0x0621U, + 0x0622U, + 0x0623U, + 0x0624U, + 0x0625U, + 0x0626U, + 0x0627U, + 0x0628U, + 0x0629U, + 0x062AU, + 0x062BU, + 0x062CU, + 0x062DU, + 0x062EU, + 0x062FU, + 0x0630U, + 0x0631U, + 0x0632U, + 0x0633U, + 0x0634U, + 0x0635U, + 0x0636U, + 0x0637U, + 0x0638U, + 0x0639U, + 0x063AU, + 0x0640U, + 0x0641U, + 0x0642U, + 0x0643U, + 0x0644U, + 0x0645U, + 0x0646U, + 0x0648U, + 0x0649U, + 0x064AU, + 0x064BU, + 0x064CU, + 0x064DU, + 0x064EU, + 0x064FU, + 0x0650U, + 0x0651U, + 0x0652U, + 0x0647U, + 0x06A4U, + 0x067EU, + 0x0686U, + 0x0698U, + 0x06AFU, + 0x0679U, + 0x0688U, + 0x0691U, + 0x06BAU, + 0x06D2U, + 0x06D5U, + 0x20AAU, + 0x05BEU, + 0x05C3U, + 0x05D0U, + 0x05D1U, + 0x05D2U, + 0x05D3U, + 0x05D4U, + 0x05D5U, + 0x05D6U, + 0x05D7U, + 0x05D8U, + 0x05D9U, + 0x05DAU, + 0x05DBU, + 0x05DCU, + 0x05DDU, + 0x05DEU, + 0x05DFU, + 0x05E0U, + 0x05E1U, + 0x05E2U, + 0x05E3U, + 0x05E4U, + 0x05E5U, + 0x05E6U, + 0x05E7U, + 0x05E8U, + 0x05E9U, + 0x05EAU, + 0xFB2AU, + 0xFB2BU, + 0xFB4BU, + 0xFB1FU, + 0x05F0U, + 0x05F1U, + 0x05F2U, + 0xFB35U, + 0x05B4U, + 0x05B5U, + 0x05B6U, + 0x05BBU, + 0x05B8U, + 0x05B7U, + 0x05B0U, + 0x05B2U, + 0x05B1U, + 0x05B3U, + 0x05C2U, + 0x05C1U, + 0x05B9U, + 0x05BCU, + 0x05BDU, + 0x05BFU, + 0x05C0U, + 0x02BCU, + 0x2105U, + 0x2113U, + 0x2116U, + 0x202CU, + 0x202DU, + 0x202EU, + 0x200CU, + 0x066DU, + 0x02BDU, + 0x0A85U, + 0x0A05U, + 0x3042U, + 0x1EA3U, + 0x0990U, + 0x311EU, + 0x0910U, + 0x04D5U, + 0x0A90U, + 0x0A10U, + 0x0A48U, + 0x0639U, + 0xFECAU, + 0xFECBU, + 0xFECCU, + 0x0203U, + 0x09C8U, + 0x0948U, + 0x0AC8U, + 0x30A2U, + 0xFF71U, + 0x314FU, + 0x05D0U, + 0x0627U, + 0xFB30U, + 0xFE8EU, + 0x0623U, + 0xFE84U, + 0x0625U, + 0xFE88U, + 0x05D0U, + 0xFB4FU, + 0x0622U, + 0xFE82U, + 0x0649U, + 0xFEF0U, + 0xFEF3U, + 0xFEF4U, + 0xFB2EU, + 0xFB2FU, + 0x2135U, + 0x224CU, + 0x03B1U, + 0x03ACU, + 0x0101U, + 0xFF41U, + 0xFF06U, + 0x33C2U, + 0x3122U, + 0x3124U, + 0x0E5AU, + 0x2220U, + 0x3008U, + 0xFE3FU, + 0x3009U, + 0xFE40U, + 0x2329U, + 0x232AU, + 0x212BU, + 0x0387U, + 0x0952U, + 0x0982U, + 0x0902U, + 0x0A82U, + 0x0105U, + 0x3300U, + 0x249CU, + 0x055AU, + 0x02BCU, + 0xF8FFU, + 0x2250U, + 0x2248U, + 0x2252U, + 0x2245U, + 0x318EU, + 0x318DU, + 0x2312U, + 0x1E9AU, + 0x01FBU, + 0x1E01U, + 0x2194U, + 0x21E3U, + 0x21E0U, + 0x21E2U, + 0x21E1U, + 0x21D4U, + 0x21D3U, + 0x21D0U, + 0x21D2U, + 0x21D1U, + 0x2193U, + 0x2199U, + 0x2198U, + 0x21E9U, + 0x02C5U, + 0x02C2U, + 0x02C3U, + 0x02C4U, + 0xF8E7U, + 0x2190U, + 0x21D0U, + 0x21CDU, + 0x21C6U, + 0x21E6U, + 0x2192U, + 0x21CFU, + 0x279EU, + 0x21C4U, + 0x21E8U, + 0x21E4U, + 0x21E5U, + 0x2191U, + 0x2195U, + 0x21A8U, + 0x21A8U, + 0x2196U, + 0x21C5U, + 0x2197U, + 0x21E7U, + 0xF8E6U, + 0xFF3EU, + 0xFF5EU, + 0x0251U, + 0x0252U, + 0x3041U, + 0x30A1U, + 0xFF67U, + 0x066DU, + 0x066DU, + 0x2217U, + 0xFF0AU, + 0xFE61U, + 0x2042U, + 0x2243U, + 0xFF20U, + 0xFE6BU, + 0x0250U, + 0x0994U, + 0x3120U, + 0x0914U, + 0x0A94U, + 0x0A14U, + 0x09D7U, + 0x0A4CU, + 0x09CCU, + 0x094CU, + 0x0ACCU, + 0x093DU, + 0x0561U, + 0x05E2U, + 0xFB20U, + 0x05E2U, + 0x09ACU, + 0xFF3CU, + 0x092CU, + 0x0AACU, + 0x0A2CU, + 0x3070U, + 0x0E3FU, + 0x30D0U, + 0xFF5CU, + 0x3105U, + 0x24D1U, + 0x1E03U, + 0x1E05U, + 0x266CU, + 0x2235U, + 0x0431U, + 0x0628U, + 0xFE90U, + 0xFE91U, + 0x3079U, + 0xFE92U, + 0xFC9FU, + 0xFC08U, + 0xFC6DU, + 0x30D9U, + 0x0562U, + 0x05D1U, + 0x03B2U, + 0x03D0U, + 0xFB31U, + 0xFB31U, + 0x05D1U, + 0xFB4CU, + 0x09ADU, + 0x092DU, + 0x0AADU, + 0x0A2DU, + 0x0253U, + 0x3073U, + 0x30D3U, + 0x0298U, + 0x0A02U, + 0x3331U, + 0x25CFU, + 0x25C6U, + 0x25BCU, + 0x25C4U, + 0x25C0U, + 0x3010U, + 0xFE3BU, + 0x3011U, + 0xFE3CU, + 0x25E3U, + 0x25E2U, + 0x25ACU, + 0x25BAU, + 0x25B6U, + 0x25AAU, + 0x263BU, + 0x25A0U, + 0x2605U, + 0x25E4U, + 0x25E5U, + 0x25B4U, + 0x25B2U, + 0x2423U, + 0x1E07U, + 0x2588U, + 0xFF42U, + 0x0E1AU, + 0x307CU, + 0x30DCU, + 0x249DU, + 0x33C3U, + 0xF8F4U, + 0xF8F3U, + 0xF8F2U, + 0xFF5BU, + 0xFE5BU, + 0xF8F1U, + 0xFE37U, + 0xF8FEU, + 0xF8FDU, + 0xFF5DU, + 0xFE5CU, + 0xF8FCU, + 0xFE38U, + 0xF8F0U, + 0xF8EFU, + 0xFF3BU, + 0xF8EEU, + 0xF8FBU, + 0xF8FAU, + 0xFF3DU, + 0xF8F9U, + 0x032EU, + 0x0306U, + 0x032FU, + 0x0311U, + 0x0361U, + 0x032AU, + 0x033AU, + 0x0180U, + 0x0183U, + 0x3076U, + 0x30D6U, + 0x25D8U, + 0x2219U, + 0x25CEU, + 0x056EU, + 0x099AU, + 0x0107U, + 0x091AU, + 0x0A9AU, + 0x0A1AU, + 0x3388U, + 0x0981U, + 0x0310U, + 0x0901U, + 0x0A81U, + 0x21EAU, + 0x2105U, + 0x032CU, + 0x030CU, + 0x21B5U, + 0x3118U, + 0x010DU, + 0x1E09U, + 0x24D2U, + 0x0109U, + 0x0255U, + 0x010BU, + 0x010BU, + 0x33C5U, + 0x0327U, + 0x2103U, + 0xFFE0U, + 0x0579U, + 0x099BU, + 0x091BU, + 0x0A9BU, + 0x0A1BU, + 0x3114U, + 0x04BDU, + 0x2713U, + 0x0447U, + 0x04BFU, + 0x04B7U, + 0x04F5U, + 0x0573U, + 0x04CCU, + 0x04B9U, + 0x03C7U, + 0x3277U, + 0x3217U, + 0x3269U, + 0x314AU, + 0x3209U, + 0x0E0AU, + 0x0E08U, + 0x0E09U, + 0x0E0CU, + 0x0188U, + 0x3276U, + 0x3216U, + 0x3268U, + 0x3148U, + 0x3208U, + 0x321CU, + 0x25CBU, + 0x2297U, + 0x2299U, + 0x2295U, + 0x3036U, + 0x25D0U, + 0x25D1U, + 0x032DU, + 0x0302U, + 0x2327U, + 0x01C2U, + 0x01C0U, + 0x01C1U, + 0x01C3U, + 0x2663U, + 0x2663U, + 0x2667U, + 0x33A4U, + 0xFF43U, + 0x33A0U, + 0x0581U, + 0xFF1AU, + 0x20A1U, + 0xFE55U, + 0x02D1U, + 0x02D0U, + 0x0313U, + 0x0315U, + 0xF6C3U, + 0x060CU, + 0x055DU, + 0xFF0CU, + 0x0314U, + 0x02BDU, + 0xFE50U, + 0x0312U, + 0x02BBU, + 0x263CU, + 0x2245U, + 0x222EU, + 0x2303U, + 0x0006U, + 0x0007U, + 0x0008U, + 0x0018U, + 0x000DU, + 0x0011U, + 0x0012U, + 0x0013U, + 0x0014U, + 0x007FU, + 0x0010U, + 0x0019U, + 0x0005U, + 0x0004U, + 0x001BU, + 0x0017U, + 0x0003U, + 0x000CU, + 0x001CU, + 0x001DU, + 0x0009U, + 0x000AU, + 0x0015U, + 0x001EU, + 0x000FU, + 0x000EU, + 0x0002U, + 0x0001U, + 0x001AU, + 0x0016U, + 0x001FU, + 0x000BU, + 0xF8E9U, + 0xF6D9U, + 0x300CU, + 0xFF62U, + 0xFE41U, + 0x300DU, + 0xFF63U, + 0xFE42U, + 0x337FU, + 0x33C7U, + 0x33C6U, + 0x249EU, + 0x20A2U, + 0x0297U, + 0x22CFU, + 0x22CEU, + 0xF6D1U, + 0xF6D2U, + 0xF6D4U, + 0xF6D5U, + 0x0564U, + 0x09A6U, + 0x0636U, + 0x0926U, + 0xFEBEU, + 0xFEBFU, + 0xFEC0U, + 0x05BCU, + 0x05BCU, + 0x0AA6U, + 0x0A26U, + 0x3060U, + 0x30C0U, + 0x062FU, + 0x05D3U, + 0xFB33U, + 0xFB33U, + 0, + 0, + 0, + 0, + 0x05D3U, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0xFEAAU, + 0x064FU, + 0x064FU, + 0x064CU, + 0x064CU, + 0x0964U, + 0x05A7U, + 0x05A7U, + 0x0485U, + 0xF6D3U, + 0x300AU, + 0xFE3DU, + 0x300BU, + 0xFE3EU, + 0x032BU, + 0x21D4U, + 0x21D2U, + 0x0965U, + 0xF6D6U, + 0x030FU, + 0x222CU, + 0x2017U, + 0x0333U, + 0x033FU, + 0x02BAU, + 0x2016U, + 0x030EU, + 0x3109U, + 0x33C8U, + 0x010FU, + 0x1E11U, + 0x24D3U, + 0x1E13U, + 0x0111U, + 0x09A1U, + 0x0921U, + 0x0AA1U, + 0x0A21U, + 0x0688U, + 0xFB89U, + 0x095CU, + 0x09A2U, + 0x0922U, + 0x0AA2U, + 0x0A22U, + 0x1E0BU, + 0x1E0DU, + 0x066BU, + 0x066BU, + 0x0434U, + 0x05ADU, + 0x3067U, + 0x03EFU, + 0x30C7U, + 0x232BU, + 0x2326U, + 0x03B4U, + 0x018DU, + 0x09F8U, + 0x02A4U, + 0x09A7U, + 0x0927U, + 0x0AA7U, + 0x0A27U, + 0x0257U, + 0x0385U, + 0x0344U, + 0x2666U, + 0x2662U, + 0xF6D7U, + 0x0324U, + 0x0308U, + 0xF6D8U, + 0x0385U, + 0x3062U, + 0x30C2U, + 0x3003U, + 0x2223U, + 0x2215U, + 0x0452U, + 0x2593U, + 0x1E0FU, + 0x3397U, + 0x0111U, + 0xFF44U, + 0x2584U, + 0x0E0EU, + 0x0E14U, + 0x3069U, + 0x30C9U, + 0xFF04U, + 0xFE69U, + 0x20ABU, + 0x3326U, + 0x0307U, + 0x0323U, + 0x0323U, + 0x30FBU, + 0xF6BEU, + 0x0284U, + 0x22C5U, + 0x25CCU, + 0xFB1FU, + 0xFB1FU, + 0x031EU, + 0x02D5U, + 0x249FU, + 0x0256U, + 0x018CU, + 0x3065U, + 0x30C5U, + 0x01F3U, + 0x02A3U, + 0x01C6U, + 0x02A5U, + 0x04E1U, + 0x0455U, + 0x045FU, + 0x2641U, + 0x098FU, + 0x311CU, + 0x0115U, + 0x090DU, + 0x0A8DU, + 0x0945U, + 0x0AC5U, + 0x011BU, + 0x1E1DU, + 0x0565U, + 0x0587U, + 0x24D4U, + 0x1EBFU, + 0x1E19U, + 0x1EC7U, + 0x1EC1U, + 0x1EC3U, + 0x1EC5U, + 0x0454U, + 0x0205U, + 0x090FU, + 0x0117U, + 0x0117U, + 0x1EB9U, + 0x0A0FU, + 0x0A47U, + 0x0444U, + 0x0A8FU, + 0x0567U, + 0x311DU, + 0x3048U, + 0x1EBBU, + 0x311FU, + 0x0668U, + 0x09EEU, + 0x2467U, + 0x2791U, + 0x096EU, + 0x2471U, + 0x2485U, + 0x2499U, + 0x0AEEU, + 0x0A6EU, + 0x0668U, + 0x3028U, + 0x266BU, + 0x3227U, + 0xFF18U, + 0x247BU, + 0x248FU, + 0x06F8U, + 0x2177U, + 0x0E58U, + 0x0207U, + 0x0465U, + 0x30A8U, + 0xFF74U, + 0x0A74U, + 0x3154U, + 0x043BU, + 0x2208U, + 0x246AU, + 0x247EU, + 0x2492U, + 0x217AU, + 0x22EEU, + 0x0113U, + 0x1E17U, + 0x1E15U, + 0x043CU, + 0xFE31U, + 0xFF45U, + 0x055BU, + 0x2205U, + 0x3123U, + 0x043DU, + 0xFE32U, + 0x04A3U, + 0x014BU, + 0x3125U, + 0x04A5U, + 0x04C8U, + 0x2002U, + 0x0119U, + 0x3153U, + 0x025BU, + 0x029AU, + 0x025CU, + 0x025EU, + 0x025DU, + 0x24A0U, + 0x03B5U, + 0x03ADU, + 0xFF1DU, + 0xFE66U, + 0x207CU, + 0x2261U, + 0x3126U, + 0x0440U, + 0x0258U, + 0x044DU, + 0x0441U, + 0x04ABU, + 0x0283U, + 0x0286U, + 0x090EU, + 0x0946U, + 0x01AAU, + 0x0285U, + 0x3047U, + 0x30A7U, + 0xFF6AU, + 0x212EU, + 0x03B7U, + 0x0568U, + 0x03AEU, + 0x1EBDU, + 0x1E1BU, + 0x0591U, + 0x0591U, + 0x0591U, + 0x0591U, + 0x01DDU, + 0x3161U, + 0x20ACU, + 0x09C7U, + 0x0947U, + 0x0AC7U, + 0x055CU, + 0x203CU, + 0xFF01U, + 0x2203U, + 0x0292U, + 0x01EFU, + 0x0293U, + 0x01B9U, + 0x01BAU, + 0x095EU, + 0x0A5EU, + 0x2109U, + 0x064EU, + 0x064EU, + 0x064BU, + 0x3108U, + 0x24D5U, + 0x1E1FU, + 0x0641U, + 0x0586U, + 0xFED2U, + 0xFED3U, + 0xFED4U, + 0x03E5U, + 0x2640U, + 0x246EU, + 0x2482U, + 0x2496U, + 0x25A0U, + 0x25ACU, + 0x05DAU, + 0xFB3AU, + 0xFB3AU, + 0x05DAU, + 0, + 0, + 0, + 0, + 0x05DDU, + 0x05DDU, + 0x05DFU, + 0x05DFU, + 0x05E3U, + 0x05E3U, + 0x05E5U, + 0x05E5U, + 0x02C9U, + 0x25C9U, + 0x0473U, + 0x0665U, + 0x09EBU, + 0x2464U, + 0x278EU, + 0x096BU, + 0x0AEBU, + 0x0A6BU, + 0x0665U, + 0x3025U, + 0x3224U, + 0xFF15U, + 0x2478U, + 0x248CU, + 0x06F5U, + 0x2174U, + 0x0E55U, + 0xFF46U, + 0x3399U, + 0x0E1FU, + 0x0E1DU, + 0x0E4FU, + 0x2200U, + 0x0664U, + 0x09EAU, + 0x2463U, + 0x278DU, + 0x096AU, + 0x0AEAU, + 0x0A6AU, + 0x0664U, + 0x3024U, + 0x3223U, + 0xFF14U, + 0x09F7U, + 0x2477U, + 0x248BU, + 0x06F4U, + 0x2173U, + 0x246DU, + 0x2481U, + 0x2495U, + 0x0E54U, + 0x02CBU, + 0x24A1U, + 0x20A3U, + 0x0997U, + 0x01F5U, + 0x0917U, + 0x06AFU, + 0xFB93U, + 0xFB94U, + 0xFB95U, + 0x0A97U, + 0x0A17U, + 0x304CU, + 0x30ACU, + 0x03B3U, + 0x0263U, + 0x02E0U, + 0x03EBU, + 0x310DU, + 0x011FU, + 0x01E7U, + 0x0123U, + 0x24D6U, + 0x011DU, + 0x0123U, + 0x0121U, + 0x0121U, + 0x0433U, + 0x3052U, + 0x30B2U, + 0x2251U, + 0x059CU, + 0x05F3U, + 0x059DU, + 0x059EU, + 0x05F4U, + 0x3013U, + 0x0998U, + 0x0572U, + 0x0918U, + 0x0A98U, + 0x0A18U, + 0x063AU, + 0xFECEU, + 0xFECFU, + 0xFED0U, + 0x0495U, + 0x0493U, + 0x0491U, + 0x095AU, + 0x0A5AU, + 0x0260U, + 0x3393U, + 0x304EU, + 0x30AEU, + 0x0563U, + 0x05D2U, + 0xFB32U, + 0xFB32U, + 0x05D2U, + 0x0453U, + 0x01BEU, + 0x0294U, + 0x0296U, + 0x02C0U, + 0x0295U, + 0x02C1U, + 0x02E4U, + 0x02A1U, + 0x02A2U, + 0x1E21U, + 0xFF47U, + 0x3054U, + 0x30B4U, + 0x24A2U, + 0x33ACU, + 0x2207U, + 0x0316U, + 0x0300U, + 0x0300U, + 0x0953U, + 0x02CEU, + 0xFF40U, + 0x0340U, + 0x2265U, + 0x22DBU, + 0xFF1EU, + 0x2273U, + 0x2277U, + 0x2267U, + 0xFE65U, + 0x0261U, + 0x01E5U, + 0x3050U, + 0x30B0U, + 0x3318U, + 0x33C9U, + 0x04A9U, + 0x06C1U, + 0x09B9U, + 0x04B3U, + 0x0939U, + 0x0AB9U, + 0x0A39U, + 0x062DU, + 0xFEA2U, + 0xFEA3U, + 0x306FU, + 0xFEA4U, + 0x332AU, + 0x30CFU, + 0xFF8AU, + 0x0A4DU, + 0x0621U, + 0, + 0, + 0, + 0, + 0x0621U, + 0, + 0, + 0, + 0x3164U, + 0x044AU, + 0x21BCU, + 0x21C0U, + 0x33CAU, + 0x05B2U, + 0x05B2U, + 0x05B2U, + 0x05B2U, + 0x05B2U, + 0x05B2U, + 0x05B2U, + 0x05B2U, + 0x05B3U, + 0x05B3U, + 0x05B3U, + 0x05B3U, + 0x05B3U, + 0x05B3U, + 0x05B3U, + 0x05B3U, + 0x05B1U, + 0x05B1U, + 0x05B1U, + 0x05B1U, + 0x05B1U, + 0x05B1U, + 0x05B1U, + 0x05B1U, + 0x0127U, + 0x310FU, + 0x1E2BU, + 0x1E29U, + 0x24D7U, + 0x0125U, + 0x1E27U, + 0x1E23U, + 0x1E25U, + 0x05D4U, + 0x2665U, + 0x2665U, + 0x2661U, + 0xFB34U, + 0xFB34U, + 0x06C1U, + 0x0647U, + 0x05D4U, + 0xFBA7U, + 0xFEEAU, + 0xFEEAU, + 0xFBA5U, + 0xFBA4U, + 0xFBA8U, + 0xFEEBU, + 0x3078U, + 0xFBA9U, + 0xFEECU, + 0x337BU, + 0x30D8U, + 0xFF8DU, + 0x3336U, + 0x0267U, + 0x3339U, + 0x05D7U, + 0x05D7U, + 0x0266U, + 0x02B1U, + 0x327BU, + 0x321BU, + 0x326DU, + 0x314EU, + 0x320DU, + 0x3072U, + 0x30D2U, + 0xFF8BU, + 0x05B4U, + 0x05B4U, + 0x05B4U, + 0x05B4U, + 0x05B4U, + 0x05B4U, + 0x05B4U, + 0x05B4U, + 0x1E96U, + 0xFF48U, + 0x0570U, + 0x0E2BU, + 0x307BU, + 0x30DBU, + 0xFF8EU, + 0x05B9U, + 0x05B9U, + 0x05B9U, + 0x05B9U, + 0x05B9U, + 0x05B9U, + 0x05B9U, + 0x05B9U, + 0x0E2EU, + 0x0309U, + 0x0309U, + 0x0321U, + 0x0322U, + 0x3342U, + 0x03E9U, + 0x2015U, + 0x031BU, + 0x2668U, + 0x2302U, + 0x24A3U, + 0x02B0U, + 0x0265U, + 0x3075U, + 0x3333U, + 0x30D5U, + 0xFF8CU, + 0x030BU, + 0x0195U, + 0xFF0DU, + 0xFE63U, + 0x2010U, + 0x044FU, + 0x0987U, + 0x3127U, + 0x012DU, + 0x01D0U, + 0x24D8U, + 0x0456U, + 0x0209U, + 0x328FU, + 0x328BU, + 0x323FU, + 0x323AU, + 0x32A5U, + 0x3006U, + 0x3001U, + 0xFF64U, + 0x3237U, + 0x32A3U, + 0x322FU, + 0x323DU, + 0x329DU, + 0x3240U, + 0x3296U, + 0x3236U, + 0x322BU, + 0x3232U, + 0x32A4U, + 0x3005U, + 0x3298U, + 0x3238U, + 0x32A7U, + 0x32A6U, + 0x32A9U, + 0x322EU, + 0x322AU, + 0x3234U, + 0x3002U, + 0x329EU, + 0x3243U, + 0x3239U, + 0x323EU, + 0x32A8U, + 0x3299U, + 0x3242U, + 0x3233U, + 0x3000U, + 0x3235U, + 0x3231U, + 0x323BU, + 0x3230U, + 0x323CU, + 0x322CU, + 0x322DU, + 0x3007U, + 0x328EU, + 0x328AU, + 0x3294U, + 0x3290U, + 0x328CU, + 0x328DU, + 0x0907U, + 0x1E2FU, + 0x04E5U, + 0x1ECBU, + 0x04D7U, + 0x0435U, + 0x3275U, + 0x3215U, + 0x3267U, + 0x3147U, + 0x3207U, + 0x0A87U, + 0x0A07U, + 0x3044U, + 0x1EC9U, + 0x0988U, + 0x0438U, + 0x0908U, + 0x0A88U, + 0x0A08U, + 0x0A40U, + 0x020BU, + 0x0439U, + 0x09C0U, + 0x0940U, + 0x0AC0U, + 0x0133U, + 0x30A4U, + 0xFF72U, + 0x3163U, + 0x02DCU, + 0x05ACU, + 0x012BU, + 0x04E3U, + 0x2253U, + 0x0A3FU, + 0xFF49U, + 0x2206U, + 0x221EU, + 0x056BU, + 0x222BU, + 0x2321U, + 0x2321U, + 0xF8F5U, + 0x2320U, + 0x2320U, + 0x2229U, + 0x3305U, + 0x25D8U, + 0x25D9U, + 0x263BU, + 0x0451U, + 0x012FU, + 0x03B9U, + 0x03CAU, + 0x0390U, + 0x0269U, + 0x03AFU, + 0x24A4U, + 0x0A72U, + 0x3043U, + 0x30A3U, + 0xFF68U, + 0x09FAU, + 0x0268U, + 0x309DU, + 0x30FDU, + 0x0129U, + 0x1E2DU, + 0x3129U, + 0x044EU, + 0x09BFU, + 0x093FU, + 0x0ABFU, + 0x0475U, + 0x0477U, + 0x0571U, + 0x099CU, + 0x091CU, + 0x0A9CU, + 0x0A1CU, + 0x3110U, + 0x01F0U, + 0x24D9U, + 0x0135U, + 0x029DU, + 0x025FU, + 0x0458U, + 0x062CU, + 0xFE9EU, + 0xFE9FU, + 0xFEA0U, + 0x0698U, + 0xFB8BU, + 0x099DU, + 0x091DU, + 0x0A9DU, + 0x0A1DU, + 0x057BU, + 0x3004U, + 0xFF4AU, + 0x24A5U, + 0x02B2U, + 0x04A1U, + 0x0995U, + 0x1E31U, + 0x043AU, + 0x049BU, + 0x0915U, + 0x05DBU, + 0x0643U, + 0xFB3BU, + 0xFB3BU, + 0xFEDAU, + 0x05DBU, + 0xFEDBU, + 0xFEDCU, + 0xFB4DU, + 0x0A95U, + 0x0A15U, + 0x304BU, + 0x04C4U, + 0x30ABU, + 0xFF76U, + 0x03BAU, + 0x03F0U, + 0x3171U, + 0x3184U, + 0x3178U, + 0x3179U, + 0x330DU, + 0x0640U, + 0x0640U, + 0x30F5U, + 0x3384U, + 0x0650U, + 0x064DU, + 0x049FU, + 0xFF70U, + 0x049DU, + 0x310EU, + 0x3389U, + 0x01E9U, + 0x0137U, + 0x24DAU, + 0x0137U, + 0x1E33U, + 0x0584U, + 0x3051U, + 0x30B1U, + 0xFF79U, + 0x056FU, + 0x30F6U, + 0x0138U, + 0x0996U, + 0x0445U, + 0x0916U, + 0x0A96U, + 0x0A16U, + 0x062EU, + 0xFEA6U, + 0xFEA7U, + 0xFEA8U, + 0x03E7U, + 0x0959U, + 0x0A59U, + 0x3278U, + 0x3218U, + 0x326AU, + 0x314BU, + 0x320AU, + 0x0E02U, + 0x0E05U, + 0x0E03U, + 0x0E04U, + 0x0E5BU, + 0x0199U, + 0x0E06U, + 0x3391U, + 0x304DU, + 0x30ADU, + 0xFF77U, + 0x3315U, + 0x3316U, + 0x3314U, + 0x326EU, + 0x320EU, + 0x3260U, + 0x3131U, + 0x3200U, + 0x3133U, + 0x045CU, + 0x1E35U, + 0x3398U, + 0x33A6U, + 0xFF4BU, + 0x33A2U, + 0x3053U, + 0x33C0U, + 0x0E01U, + 0x30B3U, + 0xFF7AU, + 0x331EU, + 0x0481U, + 0x327FU, + 0x0343U, + 0x24A6U, + 0x33AAU, + 0x046FU, + 0x33CFU, + 0x029EU, + 0x304FU, + 0x30AFU, + 0xFF78U, + 0x33B8U, + 0x33BEU, + 0x09B2U, + 0x013AU, + 0x0932U, + 0x0AB2U, + 0x0A32U, + 0x0E45U, + 0xFEFCU, + 0xFEF8U, + 0xFEF7U, + 0xFEFAU, + 0xFEF9U, + 0xFEFBU, + 0xFEF6U, + 0xFEF5U, + 0x0644U, + 0x03BBU, + 0x019BU, + 0x05DCU, + 0xFB3CU, + 0xFB3CU, + 0x05DCU, + 0, + 0, + 0, + 0, + 0xFEDEU, + 0xFCCAU, + 0xFEDFU, + 0xFCC9U, + 0xFCCBU, + 0xFDF2U, + 0xFEE0U, + 0xFD88U, + 0xFCCCU, + 0, + 0, + 0x25EFU, + 0x019AU, + 0x026CU, + 0x310CU, + 0x013EU, + 0x013CU, + 0x24DBU, + 0x1E3DU, + 0x013CU, + 0x0140U, + 0x0140U, + 0x1E37U, + 0x1E39U, + 0x031AU, + 0x0318U, + 0x2264U, + 0x22DAU, + 0xFF1CU, + 0x2272U, + 0x2276U, + 0x2266U, + 0xFE64U, + 0x026EU, + 0x258CU, + 0x026DU, + 0x20A4U, + 0x056CU, + 0x01C9U, + 0x0459U, + 0xF6C0U, + 0x0933U, + 0x0AB3U, + 0x1E3BU, + 0x0934U, + 0x09E1U, + 0x0961U, + 0x09E3U, + 0x0963U, + 0x026BU, + 0xFF4CU, + 0x33D0U, + 0x0E2CU, + 0x2227U, + 0x2310U, + 0x2228U, + 0x0E25U, + 0x017FU, + 0xFE4EU, + 0x0332U, + 0xFE4DU, + 0x25CAU, + 0x24A7U, + 0x2113U, + 0x2591U, + 0x0E26U, + 0x098CU, + 0x090CU, + 0x09E2U, + 0x0962U, + 0x33D3U, + 0x09AEU, + 0x0331U, + 0x0304U, + 0x02CDU, + 0xFFE3U, + 0x1E3FU, + 0x092EU, + 0x0AAEU, + 0x0A2EU, + 0x05A4U, + 0x05A4U, + 0x307EU, + 0xF895U, + 0xF894U, + 0x0E4BU, + 0xF893U, + 0xF88CU, + 0xF88BU, + 0x0E48U, + 0xF88AU, + 0xF884U, + 0x0E31U, + 0xF889U, + 0x0E47U, + 0xF88FU, + 0xF88EU, + 0x0E49U, + 0xF88DU, + 0xF892U, + 0xF891U, + 0x0E4AU, + 0xF890U, + 0x0E46U, + 0x30DEU, + 0xFF8FU, + 0x2642U, + 0x3347U, + 0x05BEU, + 0x2642U, + 0x05AFU, + 0x3383U, + 0x3107U, + 0x33D4U, + 0x24DCU, + 0x33A5U, + 0x1E41U, + 0x1E43U, + 0x0645U, + 0xFEE2U, + 0xFEE3U, + 0xFEE4U, + 0xFCD1U, + 0xFC48U, + 0x334DU, + 0x3081U, + 0x337EU, + 0x30E1U, + 0xFF92U, + 0x05DEU, + 0xFB3EU, + 0xFB3EU, + 0x05DEU, + 0x0574U, + 0x05A5U, + 0x05A6U, + 0x05A6U, + 0x05A5U, + 0x0271U, + 0x3392U, + 0xFF65U, + 0x00B7U, + 0x3272U, + 0x3212U, + 0x3264U, + 0x3141U, + 0x3170U, + 0x3204U, + 0x316EU, + 0x316FU, + 0x307FU, + 0x30DFU, + 0xFF90U, + 0x0320U, + 0x2296U, + 0x02D7U, + 0x2213U, + 0x2032U, + 0x334AU, + 0x3349U, + 0x0270U, + 0x3396U, + 0x33A3U, + 0xFF4DU, + 0x339FU, + 0x3082U, + 0x33C1U, + 0x30E2U, + 0xFF93U, + 0x33D6U, + 0x0E21U, + 0x33A7U, + 0x33A8U, + 0x24A8U, + 0x33ABU, + 0x33B3U, + 0x026FU, + 0x00B5U, + 0x3382U, + 0x226BU, + 0x226AU, + 0x338CU, + 0x03BCU, + 0x338DU, + 0x3080U, + 0x30E0U, + 0xFF91U, + 0x3395U, + 0x339BU, + 0x05A3U, + 0x05A3U, + 0x266AU, + 0x266BU, + 0x266DU, + 0x266FU, + 0x33B2U, + 0x33B6U, + 0x33BCU, + 0x33B9U, + 0x33B7U, + 0x33BFU, + 0x33BDU, + 0x09A8U, + 0x2207U, + 0x0144U, + 0x0928U, + 0x0AA8U, + 0x0A28U, + 0x306AU, + 0x30CAU, + 0xFF85U, + 0x0149U, + 0x3381U, + 0x310BU, + 0x00A0U, + 0x0148U, + 0x0146U, + 0x24DDU, + 0x1E4BU, + 0x0146U, + 0x1E45U, + 0x1E47U, + 0x306DU, + 0x30CDU, + 0xFF88U, + 0x20AAU, + 0x338BU, + 0x0999U, + 0x0919U, + 0x0A99U, + 0x0A19U, + 0x0E07U, + 0x3093U, + 0x0272U, + 0x0273U, + 0x326FU, + 0x320FU, + 0x3135U, + 0x3261U, + 0x3136U, + 0x3134U, + 0x3168U, + 0x3201U, + 0x3167U, + 0x3166U, + 0x306BU, + 0x30CBU, + 0xFF86U, + 0xF899U, + 0x0E4DU, + 0x0669U, + 0x09EFU, + 0x2468U, + 0x2792U, + 0x096FU, + 0x0AEFU, + 0x0A6FU, + 0x0669U, + 0x3029U, + 0x3228U, + 0xFF19U, + 0x247CU, + 0x2490U, + 0x06F9U, + 0x2178U, + 0x2472U, + 0x2486U, + 0x249AU, + 0x0E59U, + 0x01CCU, + 0x045AU, + 0x30F3U, + 0xFF9DU, + 0x019EU, + 0x1E49U, + 0xFF4EU, + 0x339AU, + 0x09A3U, + 0x0923U, + 0x0AA3U, + 0x0A23U, + 0x0929U, + 0x306EU, + 0x30CEU, + 0xFF89U, + 0x00A0U, + 0x0E13U, + 0x0E19U, + 0x0646U, + 0xFEE6U, + 0x06BAU, + 0xFB9FU, + 0, + 0xFEE7U, + 0xFCD2U, + 0xFC4BU, + 0xFEE8U, + 0xFCD5U, + 0xFC4EU, + 0xFC8DU, + 0x220CU, + 0x2209U, + 0x2209U, + 0x2260U, + 0x226FU, + 0x2271U, + 0x2279U, + 0x2262U, + 0x226EU, + 0x2270U, + 0x2226U, + 0x2280U, + 0x2284U, + 0x2281U, + 0x2285U, + 0x0576U, + 0x24A9U, + 0x33B1U, + 0x03BDU, + 0x306CU, + 0x30CCU, + 0xFF87U, + 0x09BCU, + 0x093CU, + 0x0ABCU, + 0x0A3CU, + 0xFF03U, + 0xFE5FU, + 0x0374U, + 0x0375U, + 0x2116U, + 0x05E0U, + 0xFB40U, + 0xFB40U, + 0x05E0U, + 0x33B5U, + 0x33BBU, + 0x099EU, + 0x091EU, + 0x0A9EU, + 0x0A1EU, + 0x0E2DU, + 0x0275U, + 0x04E9U, + 0x04EBU, + 0x0993U, + 0x311BU, + 0x014FU, + 0x0911U, + 0x0A91U, + 0x0949U, + 0x0AC9U, + 0x01D2U, + 0x24DEU, + 0x1ED1U, + 0x1ED9U, + 0x1ED3U, + 0x1ED5U, + 0x1ED7U, + 0x043EU, + 0x0151U, + 0x020DU, + 0x0913U, + 0x04E7U, + 0x1ECDU, + 0x315AU, + 0x0328U, + 0x0A93U, + 0x0585U, + 0x304AU, + 0x1ECFU, + 0x01A1U, + 0x1EDBU, + 0x1EE3U, + 0x1EDDU, + 0x1EDFU, + 0x1EE1U, + 0x0151U, + 0x01A3U, + 0x020FU, + 0x30AAU, + 0xFF75U, + 0x3157U, + 0x05ABU, + 0x014DU, + 0x1E53U, + 0x1E51U, + 0x0950U, + 0x03C9U, + 0x03D6U, + 0x0461U, + 0x0277U, + 0x047BU, + 0x047DU, + 0x03CEU, + 0x0AD0U, + 0x03BFU, + 0x03CCU, + 0xFF4FU, + 0x0661U, + 0x09E7U, + 0x2460U, + 0x278AU, + 0x0967U, + 0x0AE7U, + 0x0A67U, + 0x0661U, + 0x3021U, + 0x3220U, + 0xFF11U, + 0x09F4U, + 0x2474U, + 0x2488U, + 0x06F1U, + 0x2170U, + 0x0E51U, + 0x01EBU, + 0x01EDU, + 0x0A13U, + 0x0A4BU, + 0x0254U, + 0x24AAU, + 0x25E6U, + 0x2325U, + 0x221FU, + 0x0912U, + 0x094AU, + 0x01FFU, + 0x3049U, + 0x30A9U, + 0xFF6BU, + 0x01FFU, + 0x047FU, + 0x1E4DU, + 0x1E4FU, + 0x3121U, + 0x203EU, + 0xFE4AU, + 0x0305U, + 0xFE49U, + 0xFE4CU, + 0xFE4BU, + 0x00AFU, + 0x09CBU, + 0x094BU, + 0x0ACBU, + 0x3380U, + 0x332BU, + 0x09AAU, + 0x1E55U, + 0x092AU, + 0x21DFU, + 0x21DEU, + 0x0AAAU, + 0x0A2AU, + 0x3071U, + 0x0E2FU, + 0x30D1U, + 0x0484U, + 0x04C0U, + 0x317FU, + 0x2225U, + 0xFD3EU, + 0xF8EDU, + 0xF8ECU, + 0xFF08U, + 0xFE59U, + 0xF8EBU, + 0xFE35U, + 0xFD3FU, + 0xF8F8U, + 0xF8F7U, + 0xFF09U, + 0xFE5AU, + 0xF8F6U, + 0xFE36U, + 0x2202U, + 0x05C0U, + 0x0599U, + 0x33A9U, + 0x05B7U, + 0x05B7U, + 0x05B7U, + 0x05B7U, + 0x05B7U, + 0x05B7U, + 0x05B7U, + 0x05B7U, + 0x05A1U, + 0x3106U, + 0x24DFU, + 0x1E57U, + 0x05E4U, + 0x043FU, + 0xFB44U, + 0xFB44U, + 0x333BU, + 0xFB43U, + 0x067EU, + 0x057AU, + 0x05E4U, + 0xFB57U, + 0xFB58U, + 0x307AU, + 0xFB59U, + 0x30DAU, + 0x04A7U, + 0xFB4EU, + 0x066AU, + 0xFF05U, + 0xFE6AU, + 0x0589U, + 0xFF61U, + 0xFF0EU, + 0xFE52U, + 0x0342U, + 0x22A5U, + 0x20A7U, + 0x338AU, + 0x09ABU, + 0x092BU, + 0x0AABU, + 0x0A2BU, + 0x03C6U, + 0x03D5U, + 0x327AU, + 0x321AU, + 0x326CU, + 0x314DU, + 0x320CU, + 0x0278U, + 0x0E3AU, + 0x03D5U, + 0x01A5U, + 0x0E1EU, + 0x0E1CU, + 0x0E20U, + 0x03C0U, + 0x3273U, + 0x3213U, + 0x3176U, + 0x3265U, + 0x3172U, + 0x3142U, + 0x3205U, + 0x3174U, + 0x3144U, + 0x3175U, + 0x3177U, + 0x3173U, + 0x3074U, + 0x30D4U, + 0x03D6U, + 0x0583U, + 0x031FU, + 0x2295U, + 0x02D6U, + 0xFF0BU, + 0xFE62U, + 0x207AU, + 0xFF50U, + 0x33D8U, + 0x307DU, + 0x261FU, + 0x261CU, + 0x261EU, + 0x261DU, + 0x30DDU, + 0x0E1BU, + 0x3012U, + 0x3020U, + 0x24ABU, + 0x227AU, + 0x211EU, + 0x02B9U, + 0x2035U, + 0x220FU, + 0x2305U, + 0x30FCU, + 0x2318U, + 0x2282U, + 0x2283U, + 0x2237U, + 0x221DU, + 0x03C8U, + 0x0471U, + 0x0486U, + 0x33B0U, + 0x3077U, + 0x30D7U, + 0x33B4U, + 0x33BAU, + 0x0958U, + 0x05A8U, + 0x0642U, + 0xFED6U, + 0xFED7U, + 0xFED8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x05B8U, + 0x059FU, + 0x3111U, + 0x24E0U, + 0x02A0U, + 0xFF51U, + 0x05E7U, + 0xFB47U, + 0xFB47U, + 0, + 0, + 0, + 0, + 0x05E7U, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0x24ACU, + 0x2669U, + 0x05BBU, + 0x05BBU, + 0x05BBU, + 0x05BBU, + 0x05BBU, + 0x05BBU, + 0x05BBU, + 0x05BBU, + 0x061FU, + 0x055EU, + 0x037EU, + 0xFF1FU, + 0xFF02U, + 0x301EU, + 0x301DU, + 0x201BU, + 0x201BU, + 0x0149U, + 0xFF07U, + 0x057CU, + 0x09B0U, + 0x0155U, + 0x0930U, + 0x221AU, + 0xF8E5U, + 0x33AEU, + 0x33AFU, + 0x33ADU, + 0x05BFU, + 0x05BFU, + 0x0AB0U, + 0x0A30U, + 0x3089U, + 0x30E9U, + 0xFF97U, + 0x09F1U, + 0x09F0U, + 0x0264U, + 0x2236U, + 0x3116U, + 0x0159U, + 0x0157U, + 0x24E1U, + 0x0157U, + 0x0211U, + 0x1E59U, + 0x1E5BU, + 0x1E5DU, + 0x203BU, + 0x2286U, + 0x2287U, + 0xF8E8U, + 0xF6DAU, + 0x0631U, + 0x0580U, + 0xFEAEU, + 0x308CU, + 0, + 0x30ECU, + 0xFF9AU, + 0x05E8U, + 0xFB48U, + 0, + 0, + 0, + 0, + 0x05E8U, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0x223DU, + 0x0597U, + 0x0597U, + 0x2310U, + 0x027EU, + 0x027FU, + 0x09DDU, + 0x095DU, + 0x03C1U, + 0x027DU, + 0x027BU, + 0x02B5U, + 0x03F1U, + 0x02DEU, + 0x3271U, + 0x3211U, + 0x3263U, + 0x3140U, + 0x313AU, + 0x3169U, + 0x3139U, + 0x313BU, + 0x316CU, + 0x3203U, + 0x313FU, + 0x313CU, + 0x316BU, + 0x313DU, + 0x313EU, + 0x316AU, + 0x316DU, + 0x221FU, + 0x0319U, + 0x22BFU, + 0x308AU, + 0x30EAU, + 0xFF98U, + 0x0325U, + 0x030AU, + 0x02BFU, + 0x0559U, + 0x031CU, + 0x02D3U, + 0x02BEU, + 0x0339U, + 0x02D2U, + 0x0213U, + 0x3351U, + 0x1E5FU, + 0x027CU, + 0x027AU, + 0xFF52U, + 0x308DU, + 0x30EDU, + 0xFF9BU, + 0x0E23U, + 0x24ADU, + 0x09DCU, + 0x0931U, + 0x0A5CU, + 0x0691U, + 0xFB8DU, + 0x09E0U, + 0x0960U, + 0x0AE0U, + 0x09C4U, + 0x0944U, + 0x0AC4U, + 0x2590U, + 0x0279U, + 0x02B4U, + 0x308BU, + 0x30EBU, + 0xFF99U, + 0x09F2U, + 0x09F3U, + 0x0E24U, + 0x098BU, + 0x090BU, + 0x0A8BU, + 0x09C3U, + 0x0943U, + 0x0AC3U, + 0x09B8U, + 0x015BU, + 0x1E65U, + 0x0635U, + 0x0938U, + 0xFEBAU, + 0xFEBBU, + 0xFEBCU, + 0x0AB8U, + 0x0A38U, + 0x3055U, + 0x30B5U, + 0xFF7BU, + 0xFDFAU, + 0x05E1U, + 0xFB41U, + 0xFB41U, + 0x05E1U, + 0x0E32U, + 0x0E41U, + 0x0E44U, + 0x0E43U, + 0x0E33U, + 0x0E30U, + 0x0E40U, + 0xF886U, + 0x0E35U, + 0xF885U, + 0x0E34U, + 0x0E42U, + 0xF888U, + 0x0E37U, + 0xF887U, + 0x0E36U, + 0x0E38U, + 0x0E39U, + 0x3119U, + 0x1E67U, + 0x015FU, + 0x0259U, + 0x04D9U, + 0x04DBU, + 0x025AU, + 0x24E2U, + 0x015DU, + 0x0219U, + 0x1E61U, + 0x1E63U, + 0x1E69U, + 0x033CU, + 0x2033U, + 0x02CAU, + 0x0633U, + 0xFEB2U, + 0xFEB3U, + 0xFEB4U, + 0x05B6U, + 0x05B6U, + 0x05B6U, + 0x05B6U, + 0x05B6U, + 0x05B6U, + 0x05B6U, + 0x0592U, + 0x05B6U, + 0x057DU, + 0x305BU, + 0x30BBU, + 0xFF7EU, + 0x061BU, + 0xFF1BU, + 0xFE54U, + 0x309CU, + 0xFF9FU, + 0x3322U, + 0x3323U, + 0x0667U, + 0x09EDU, + 0x2466U, + 0x2790U, + 0x096DU, + 0x0AEDU, + 0x0A6DU, + 0x0667U, + 0x3027U, + 0x3226U, + 0xFF17U, + 0x247AU, + 0x248EU, + 0x06F7U, + 0x2176U, + 0x2470U, + 0x2484U, + 0x2498U, + 0x0E57U, + 0x00ADU, + 0x0577U, + 0x09B6U, + 0x0448U, + 0x0651U, + 0xFC61U, + 0xFC5EU, + 0xFC60U, + 0, + 0xFC62U, + 0xFC5FU, + 0x2592U, + 0x2593U, + 0x2591U, + 0x2592U, + 0x0936U, + 0x0AB6U, + 0x0A36U, + 0x0593U, + 0x3115U, + 0x0449U, + 0x0634U, + 0xFEB6U, + 0xFEB7U, + 0xFEB8U, + 0x03E3U, + 0x20AAU, + 0x20AAU, + 0x05B0U, + 0x05B0U, + 0x05B0U, + 0x05B0U, + 0x05B0U, + 0x05B0U, + 0x05B0U, + 0x05B0U, + 0x05B0U, + 0x04BBU, + 0x03EDU, + 0x05E9U, + 0xFB49U, + 0xFB49U, + 0xFB2CU, + 0xFB2CU, + 0xFB2DU, + 0xFB2DU, + 0x05C1U, + 0x05E9U, + 0xFB2AU, + 0xFB2AU, + 0xFB2BU, + 0xFB2BU, + 0x0282U, + 0x03C3U, + 0x03C2U, + 0x03C2U, + 0x03F2U, + 0x3057U, + 0x30B7U, + 0xFF7CU, + 0x05BDU, + 0x05BDU, + 0x223CU, + 0x05C2U, + 0x3274U, + 0x3214U, + 0x317EU, + 0x3266U, + 0x317AU, + 0x3145U, + 0x317BU, + 0x3206U, + 0x317DU, + 0x317CU, + 0x0666U, + 0x09ECU, + 0x2465U, + 0x278FU, + 0x096CU, + 0x0AECU, + 0x0A6CU, + 0x0666U, + 0x3026U, + 0x3225U, + 0xFF16U, + 0x2479U, + 0x248DU, + 0x06F6U, + 0x2175U, + 0x246FU, + 0x09F9U, + 0x2483U, + 0x2497U, + 0x0E56U, + 0xFF0FU, + 0x017FU, + 0x1E9BU, + 0x263AU, + 0xFF53U, + 0x05C3U, + 0x00ADU, + 0x044CU, + 0x305DU, + 0x30BDU, + 0xFF7FU, + 0x0338U, + 0x0337U, + 0x0E29U, + 0x0E28U, + 0x0E0BU, + 0x0E2AU, + 0x0020U, + 0x2660U, + 0x2660U, + 0x2664U, + 0x24AEU, + 0x033BU, + 0x33C4U, + 0x339DU, + 0x25A9U, + 0x25A4U, + 0x338FU, + 0x339EU, + 0x33CEU, + 0x33D1U, + 0x33D2U, + 0x338EU, + 0x33D5U, + 0x339CU, + 0x33A1U, + 0x25A6U, + 0x25A7U, + 0x25A8U, + 0x25A5U, + 0x25A3U, + 0x33DBU, + 0x09B7U, + 0x0937U, + 0x0AB7U, + 0x3149U, + 0x3185U, + 0x3180U, + 0x3132U, + 0x3165U, + 0x3143U, + 0x3146U, + 0x3138U, + 0xFFE1U, + 0x0336U, + 0x0335U, + 0x2282U, + 0x228AU, + 0x2286U, + 0x227BU, + 0x220BU, + 0x3059U, + 0x30B9U, + 0xFF7DU, + 0x0652U, + 0x2211U, + 0x263CU, + 0x2283U, + 0x228BU, + 0x2287U, + 0x33DCU, + 0x337CU, + 0x09A4U, + 0x22A4U, + 0x22A3U, + 0x0924U, + 0x0AA4U, + 0x0A24U, + 0x0637U, + 0xFEC2U, + 0xFEC3U, + 0x305FU, + 0xFEC4U, + 0x337DU, + 0x30BFU, + 0xFF80U, + 0x0640U, + 0x03C4U, + 0x05EAU, + 0xFB4AU, + 0xFB4AU, + 0xFB4AU, + 0x05EAU, + 0x0167U, + 0x310AU, + 0x0165U, + 0x02A8U, + 0x0163U, + 0x0686U, + 0xFB7BU, + 0xFB7CU, + 0xFB7DU, + 0, + 0x24E3U, + 0x1E71U, + 0x0163U, + 0x1E97U, + 0x1E6BU, + 0x1E6DU, + 0x0442U, + 0x04ADU, + 0x062AU, + 0xFE96U, + 0xFCA2U, + 0xFC0CU, + 0xFE97U, + 0x3066U, + 0xFCA1U, + 0xFC0BU, + 0x0629U, + 0xFE94U, + 0xFE98U, + 0xFCA4U, + 0xFC0EU, + 0xFC73U, + 0x30C6U, + 0xFF83U, + 0x2121U, + 0x260EU, + 0x05A0U, + 0x05A9U, + 0x2469U, + 0x3229U, + 0x247DU, + 0x2491U, + 0x2179U, + 0x02A7U, + 0x05D8U, + 0xFB38U, + 0xFB38U, + 0x05D8U, + 0x04B5U, + 0x059BU, + 0x059BU, + 0x09A5U, + 0x0925U, + 0x0AA5U, + 0x0A25U, + 0x0630U, + 0xFEACU, + 0xF898U, + 0xF897U, + 0x0E4CU, + 0xF896U, + 0x062BU, + 0xFE9AU, + 0xFE9BU, + 0xFE9CU, + 0x2203U, + 0x2234U, + 0x03B8U, + 0x03D1U, + 0x03D1U, + 0x3279U, + 0x3219U, + 0x326BU, + 0x314CU, + 0x320BU, + 0x246CU, + 0x2480U, + 0x2494U, + 0x0E11U, + 0x01ADU, + 0x0E12U, + 0x0E17U, + 0x0E10U, + 0x0E18U, + 0x0E16U, + 0x0482U, + 0x066CU, + 0x066CU, + 0x0663U, + 0x09E9U, + 0x2462U, + 0x278CU, + 0x0969U, + 0x0AE9U, + 0x0A69U, + 0x0663U, + 0x3023U, + 0x3222U, + 0xFF13U, + 0x09F6U, + 0x2476U, + 0x248AU, + 0x06F3U, + 0x2172U, + 0x0E53U, + 0x3394U, + 0x3061U, + 0x30C1U, + 0xFF81U, + 0x3270U, + 0x3210U, + 0x3262U, + 0x3137U, + 0x3202U, + 0x0330U, + 0x0303U, + 0x0303U, + 0x0360U, + 0x223CU, + 0x0334U, + 0x033EU, + 0x2297U, + 0x0596U, + 0x0596U, + 0x0A70U, + 0x0483U, + 0x057FU, + 0x1E6FU, + 0xFF54U, + 0x0569U, + 0x3068U, + 0x30C8U, + 0xFF84U, + 0x02E5U, + 0x02E9U, + 0x02E6U, + 0x02E8U, + 0x02E7U, + 0x01BDU, + 0x0185U, + 0x01A8U, + 0x0384U, + 0x3327U, + 0x0E0FU, + 0x3014U, + 0xFE5DU, + 0xFE39U, + 0x3015U, + 0xFE5EU, + 0xFE3AU, + 0x0E15U, + 0x01ABU, + 0x24AFU, + 0xF8EAU, + 0xF6DBU, + 0x0288U, + 0x25BCU, + 0x25C4U, + 0x25BAU, + 0x25B2U, + 0x02A6U, + 0x05E6U, + 0xFB46U, + 0xFB46U, + 0x05E6U, + 0x0446U, + 0x05B5U, + 0x05B5U, + 0x05B5U, + 0x05B5U, + 0x05B5U, + 0x05B5U, + 0x05B5U, + 0x05B5U, + 0x045BU, + 0x099FU, + 0x091FU, + 0x0A9FU, + 0x0A1FU, + 0x0679U, + 0xFB67U, + 0xFB68U, + 0xFB69U, + 0x09A0U, + 0x0920U, + 0x0AA0U, + 0x0A20U, + 0x0287U, + 0x3064U, + 0x30C4U, + 0xFF82U, + 0x3063U, + 0x30C3U, + 0xFF6FU, + 0x246BU, + 0x247FU, + 0x2493U, + 0x217BU, + 0x2473U, + 0x5344U, + 0x2487U, + 0x249BU, + 0x0662U, + 0x09E8U, + 0x2461U, + 0x278BU, + 0x0968U, + 0x2025U, + 0xFE30U, + 0x0AE8U, + 0x0A68U, + 0x0662U, + 0x3022U, + 0x3221U, + 0xFF12U, + 0x09F5U, + 0x2475U, + 0x2489U, + 0x06F2U, + 0x2171U, + 0x01BBU, + 0x0E52U, + 0x0289U, + 0x0989U, + 0x3128U, + 0x016DU, + 0x01D4U, + 0x24E4U, + 0x1E77U, + 0x0443U, + 0x0951U, + 0x0171U, + 0x0215U, + 0x0909U, + 0x01D8U, + 0x1E73U, + 0x01DAU, + 0x04F1U, + 0x01DCU, + 0x01D6U, + 0x1EE5U, + 0x0A89U, + 0x0A09U, + 0x3046U, + 0x1EE7U, + 0x01B0U, + 0x1EE9U, + 0x1EF1U, + 0x1EEBU, + 0x1EEDU, + 0x1EEFU, + 0x0171U, + 0x04F3U, + 0x0217U, + 0x30A6U, + 0xFF73U, + 0x0479U, + 0x315CU, + 0x016BU, + 0x04EFU, + 0x1E7BU, + 0x0A41U, + 0xFF55U, + 0x2017U, + 0xFF3FU, + 0xFE33U, + 0xFE4FU, + 0x222AU, + 0x2200U, + 0x0173U, + 0x24B0U, + 0x2580U, + 0x05C4U, + 0x03C5U, + 0x03CBU, + 0x03B0U, + 0x028AU, + 0x03CDU, + 0x031DU, + 0x02D4U, + 0x0A73U, + 0x016FU, + 0x045EU, + 0x3045U, + 0x30A5U, + 0xFF69U, + 0x04AFU, + 0x04B1U, + 0x0169U, + 0x1E79U, + 0x1E75U, + 0x098AU, + 0x090AU, + 0x0A8AU, + 0x0A0AU, + 0x0A42U, + 0x09C2U, + 0x0942U, + 0x0AC2U, + 0x09C1U, + 0x0941U, + 0x0AC1U, + 0x0935U, + 0x0AB5U, + 0x0A35U, + 0x30F7U, + 0x05D5U, + 0xFB35U, + 0xFB35U, + 0xFB35U, + 0x05D5U, + 0xFB4BU, + 0xFB4BU, + 0x05F0U, + 0x05F1U, + 0x24E5U, + 0x1E7FU, + 0x0432U, + 0x06A4U, + 0xFB6BU, + 0xFB6CU, + 0xFB6DU, + 0x30F9U, + 0x2640U, + 0x007CU, + 0x030DU, + 0x0329U, + 0x02CCU, + 0x02C8U, + 0x057EU, + 0x028BU, + 0x30F8U, + 0x09CDU, + 0x094DU, + 0x0ACDU, + 0x0983U, + 0x0903U, + 0x0A83U, + 0xFF56U, + 0x0578U, + 0x309EU, + 0x30FEU, + 0x309BU, + 0xFF9EU, + 0x30FAU, + 0x24B1U, + 0x1E7DU, + 0x028CU, + 0x3094U, + 0x30F4U, + 0x1E83U, + 0x3159U, + 0x308FU, + 0x30EFU, + 0xFF9CU, + 0x3158U, + 0x308EU, + 0x30EEU, + 0x3357U, + 0x301CU, + 0xFE34U, + 0x0648U, + 0xFEEEU, + 0x0624U, + 0xFE86U, + 0x33DDU, + 0x24E6U, + 0x0175U, + 0x1E85U, + 0x1E87U, + 0x1E89U, + 0x3091U, + 0x2118U, + 0x30F1U, + 0x315EU, + 0x315DU, + 0x1E81U, + 0x25E6U, + 0x25CBU, + 0x25D9U, + 0x300EU, + 0xFE43U, + 0x300FU, + 0xFE44U, + 0x25C7U, + 0x25C8U, + 0x25BFU, + 0x25BDU, + 0x25C3U, + 0x25C1U, + 0x3016U, + 0x3017U, + 0x25B9U, + 0x25B7U, + 0x25ABU, + 0x263AU, + 0x25A1U, + 0x2606U, + 0x260FU, + 0x3018U, + 0x3019U, + 0x25B5U, + 0x25B3U, + 0x3090U, + 0x30F0U, + 0x315FU, + 0xFF57U, + 0x3092U, + 0x30F2U, + 0xFF66U, + 0x20A9U, + 0xFFE6U, + 0x0E27U, + 0x24B2U, + 0x1E98U, + 0x02B7U, + 0x028DU, + 0x01BFU, + 0x033DU, + 0x3112U, + 0x24E7U, + 0x1E8DU, + 0x1E8BU, + 0x056DU, + 0x03BEU, + 0xFF58U, + 0x24B3U, + 0x02E3U, + 0x334EU, + 0x09AFU, + 0x092FU, + 0x3152U, + 0x0AAFU, + 0x0A2FU, + 0x3084U, + 0x30E4U, + 0xFF94U, + 0x3151U, + 0x0E4EU, + 0x3083U, + 0x30E3U, + 0xFF6CU, + 0x0463U, + 0x24E8U, + 0x0177U, + 0x1E8FU, + 0x1EF5U, + 0x064AU, + 0x06D2U, + 0xFBAFU, + 0xFEF2U, + 0x0626U, + 0xFE8AU, + 0xFE8BU, + 0xFE8CU, + 0xFEF3U, + 0xFEF4U, + 0xFCDDU, + 0xFC58U, + 0xFC94U, + 0x06D1U, + 0x3156U, + 0xFFE5U, + 0x3155U, + 0x3186U, + 0x05AAU, + 0x05AAU, + 0x044BU, + 0x04F9U, + 0x3181U, + 0x3183U, + 0x3182U, + 0x059AU, + 0x1EF3U, + 0x01B4U, + 0x1EF7U, + 0x0575U, + 0x0457U, + 0x3162U, + 0x262FU, + 0x0582U, + 0xFF59U, + 0x05D9U, + 0xFB39U, + 0xFB39U, + 0x05D9U, + 0x05F2U, + 0xFB1FU, + 0x3088U, + 0x3189U, + 0x30E8U, + 0xFF96U, + 0x315BU, + 0x3087U, + 0x30E7U, + 0xFF6EU, + 0x03F3U, + 0x3188U, + 0x3187U, + 0x0E22U, + 0x0E0DU, + 0x24B4U, + 0x037AU, + 0x0345U, + 0x01A6U, + 0x1E99U, + 0x02B8U, + 0x1EF9U, + 0x028EU, + 0x3086U, + 0x318CU, + 0x30E6U, + 0xFF95U, + 0x3160U, + 0x046BU, + 0x046DU, + 0x0467U, + 0x0469U, + 0x3085U, + 0x30E5U, + 0xFF6DU, + 0x318BU, + 0x318AU, + 0x09DFU, + 0x095FU, + 0x0566U, + 0x017AU, + 0x095BU, + 0x0A5BU, + 0x0638U, + 0xFEC6U, + 0xFEC7U, + 0x3056U, + 0xFEC8U, + 0x0632U, + 0xFEB0U, + 0x30B6U, + 0x0595U, + 0x0594U, + 0x0598U, + 0x05D6U, + 0xFB36U, + 0xFB36U, + 0x05D6U, + 0x3117U, + 0x24E9U, + 0x1E91U, + 0x0291U, + 0x017CU, + 0x017CU, + 0x1E93U, + 0x0437U, + 0x0499U, + 0x04DFU, + 0x305CU, + 0x30BCU, + 0x0660U, + 0x09E6U, + 0x0966U, + 0x0AE6U, + 0x0A66U, + 0x0660U, + 0xFF10U, + 0x06F0U, + 0x0E50U, + 0xFEFFU, + 0x200CU, + 0x200BU, + 0x03B6U, + 0x3113U, + 0x056AU, + 0x04C2U, + 0x0436U, + 0x0497U, + 0x04DDU, + 0x3058U, + 0x30B8U, + 0x05AEU, + 0x1E95U, + 0xFF5AU, + 0x305EU, + 0x30BEU, + 0x24B5U, + 0x0290U, + 0x01B6U, + 0x305AU, + 0x30BAU, + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + 0 + }; + + + + static const unsigned short t1_standard_encoding[257] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 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, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 0, + 111, + 112, + 113, + 114, + 0, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 0, + 123, + 0, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 0, + 132, + 133, + 0, + 134, + 135, + 136, + 137, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 138, + 0, + 139, + 0, + 0, + 0, + 0, + 140, + 141, + 142, + 143, + 0, + 0, + 0, + 0, + 0, + 144, + 0, + 0, + 0, + 145, + 0, + 0, + 146, + 147, + 148, + 149, + 0, + 0, + 0, + 0, + 0 + }; + + + static const unsigned short t1_expert_encoding[257] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 229, + 230, + 0, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 13, + 14, + 15, + 99, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 27, + 28, + 249, + 250, + 251, + 252, + 0, + 253, + 254, + 255, + 256, + 257, + 0, + 0, + 0, + 258, + 0, + 0, + 259, + 260, + 261, + 262, + 0, + 0, + 263, + 264, + 265, + 0, + 266, + 109, + 110, + 267, + 268, + 269, + 0, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 304, + 305, + 306, + 0, + 0, + 307, + 308, + 309, + 310, + 311, + 0, + 312, + 0, + 0, + 313, + 0, + 0, + 314, + 315, + 0, + 0, + 316, + 317, + 318, + 0, + 0, + 0, + 158, + 155, + 163, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 0, + 0, + 326, + 150, + 164, + 169, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 0 + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/raster/ftraster.c b/Utilities/vtkfreetype/src/raster/ftraster.c new file mode 100644 index 0000000..0ba27e8 --- /dev/null +++ b/Utilities/vtkfreetype/src/raster/ftraster.c @@ -0,0 +1,3298 @@ +/***************************************************************************/ +/* */ +/* ftraster.c */ +/* */ +/* The FreeType glyph rasterizer (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This is a rewrite of the FreeType 1.x scan-line converter */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include "ftraster.h" +#include FT_INTERNAL_CALC_H /* for FT_MulDiv only */ + + + /*************************************************************************/ + /* */ + /* A simple technical note on how the raster works */ + /* ----------------------------------------------- */ + /* */ + /* Converting an outline into a bitmap is achieved in several steps: */ + /* */ + /* 1 - Decomposing the outline into successive `profiles'. Each */ + /* profile is simply an array of scanline intersections on a given */ + /* dimension. A profile's main attributes are */ + /* */ + /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */ + /* */ + /* o an array of intersection coordinates for each scanline */ + /* between `Ymin' and `Ymax'. */ + /* */ + /* o a direction, indicating whether it was built going `up' or */ + /* `down', as this is very important for filling rules. */ + /* */ + /* 2 - Sweeping the target map's scanlines in order to compute segment */ + /* `spans' which are then filled. Additionally, this pass */ + /* performs drop-out control. */ + /* */ + /* The outline data is parsed during step 1 only. The profiles are */ + /* built from the bottom of the render pool, used as a stack. The */ + /* following graphics shows the profile list under construction: */ + /* */ + /* ____________________________________________________________ _ _ */ + /* | | | | | */ + /* | profile | coordinates for | profile | coordinates for |--> */ + /* | 1 | profile 1 | 2 | profile 2 |--> */ + /* |_________|___________________|_________|_________________|__ _ _ */ + /* */ + /* ^ ^ */ + /* | | */ + /* start of render pool top */ + /* */ + /* The top of the profile stack is kept in the `top' variable. */ + /* */ + /* As you can see, a profile record is pushed on top of the render */ + /* pool, which is then followed by its coordinates/intersections. If */ + /* a change of direction is detected in the outline, a new profile is */ + /* generated until the end of the outline. */ + /* */ + /* Note that when all profiles have been generated, the function */ + /* Finalize_Profile_Table() is used to record, for each profile, its */ + /* bottom-most scanline as well as the scanline above its upmost */ + /* boundary. These positions are called `y-turns' because they (sort */ + /* of) correspond to local extrema. They are stored in a sorted list */ + /* built from the top of the render pool as a downwards stack: */ + /* */ + /* _ _ _______________________________________ */ + /* | | */ + /* <--| sorted list of | */ + /* <--| extrema scanlines | */ + /* _ _ __________________|____________________| */ + /* */ + /* ^ ^ */ + /* | | */ + /* maxBuff sizeBuff = end of pool */ + /* */ + /* This list is later used during the sweep phase in order to */ + /* optimize performance (see technical note on the sweep below). */ + /* */ + /* Of course, the raster detects whether the two stacks collide and */ + /* handles the situation propertly. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** CONFIGURATION MACROS **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + /* define DEBUG_RASTER if you want to compile a debugging version */ +#define xxxDEBUG_RASTER + + /* The default render pool size in bytes */ +#define RASTER_RENDER_POOL 8192 + + /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */ + /* 5-levels anti-aliasing */ +#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS +#define FT_RASTER_OPTION_ANTI_ALIASING +#endif + + /* The size of the two-lines intermediate bitmap used */ + /* for anti-aliasing, in bytes. */ +#define RASTER_GRAY_LINES 2048 + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** OTHER MACROS (do not change) **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_raster + + +#ifdef _STANDALONE_ + + + /* This macro is used to indicate that a function parameter is unused. */ + /* Its purpose is simply to reduce compiler warnings. Note also that */ + /* simply defining it as `(void)x' doesn't avoid warnings with certain */ + /* ANSI compilers (e.g. LCC). */ +#define FT_UNUSED( x ) (x) = (x) + + /* Disable the tracing mechanism for simplicity -- developers can */ + /* activate it easily by redefining these two macros. */ +#ifndef FT_ERROR +#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */ +#endif + +#ifndef FT_TRACE +#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */ +#endif + +#define Raster_Err_None 0 +#define Raster_Err_Not_Ini -1 +#define Raster_Err_Overflow -2 +#define Raster_Err_Neg_Height -3 +#define Raster_Err_Invalid -4 +#define Raster_Err_Unsupported -5 + + +#else /* _STANDALONE_ */ + + +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H /* for FT_TRACE() and FT_ERROR() */ + +#include "rasterrs.h" + +#define Raster_Err_None Raster_Err_Ok +#define Raster_Err_Not_Ini Raster_Err_Raster_Uninitialized +#define Raster_Err_Overflow Raster_Err_Raster_Overflow +#define Raster_Err_Neg_Height Raster_Err_Raster_Negative_Height +#define Raster_Err_Invalid Raster_Err_Invalid_Outline +#define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph + + +#endif /* _STANDALONE_ */ + + +#ifndef FT_MEM_SET +#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c ) +#endif + + + /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */ + /* typically a small value and the result of a*b is known to fit into */ + /* 32 bits. */ +#define FMulDiv( a, b, c ) ( (a) * (b) / (c) ) + + /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */ + /* for clipping computations. It simply uses the FT_MulDiv() function */ + /* defined in `ftcalc.h'. */ +#define SMulDiv FT_MulDiv + + /* The rasterizer is a very general purpose component; please leave */ + /* the following redefinitions there (you never know your target */ + /* environment). */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + +#ifndef SUCCESS +#define SUCCESS 0 +#endif + +#ifndef FAILURE +#define FAILURE 1 +#endif + + +#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */ + /* Setting this constant to more than 32 is a */ + /* pure waste of space. */ + +#define Pixel_Bits 6 /* fractional bits of *input* coordinates */ + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** SIMPLE TYPE DECLARATIONS **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + typedef int Int; + typedef unsigned int UInt; + typedef short Short; + typedef unsigned short UShort, *PUShort; + typedef long Long, *PLong; + typedef unsigned long ULong; + + typedef unsigned char Byte, *PByte; + typedef char Bool; + + + typedef union Alignment_ + { + long l; + void* p; + void (*f)(void); + + } Alignment, *PAlignment; + + + typedef struct TPoint_ + { + Long x; + Long y; + + } TPoint; + + + typedef enum TFlow_ + { + Flow_None = 0, + Flow_Up = 1, + Flow_Down = -1 + + } TFlow; + + + /* States of each line, arc, and profile */ + typedef enum TStates_ + { + Unknown_State, + Ascending_State, + Descending_State, + Flat_State + + } TStates; + + + typedef struct TProfile_ TProfile; + typedef TProfile* PProfile; + + struct TProfile_ + { + FT_F26Dot6 X; /* current coordinate during sweep */ + PProfile link; /* link to next profile - various purpose */ + PLong offset; /* start of profile's data in render pool */ + int flow; /* Profile orientation: Asc/Descending */ + long height; /* profile's height in scanlines */ + long start; /* profile's starting scanline */ + + unsigned countL; /* number of lines to step before this */ + /* profile becomes drawable */ + + PProfile next; /* next profile in same contour, used */ + /* during drop-out control */ + }; + + typedef PProfile TProfileList; + typedef PProfile* PProfileList; + + + /* Simple record used to implement a stack of bands, required */ + /* by the sub-banding mechanism */ + typedef struct TBand_ + { + Short y_min; /* band's minimum */ + Short y_max; /* band's maximum */ + + } TBand; + + +#define AlignProfileSize \ + ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) ) + + +#ifdef TT_STATIC_RASTER + + +#define RAS_ARGS /* void */ +#define RAS_ARG /* void */ + +#define RAS_VARS /* void */ +#define RAS_VAR /* void */ + +#define FT_UNUSED_RASTER do ; while ( 0 ) + + +#else /* TT_STATIC_RASTER */ + + +#define RAS_ARGS TRaster_Instance* raster, +#define RAS_ARG TRaster_Instance* raster + +#define RAS_VARS raster, +#define RAS_VAR raster + +#define FT_UNUSED_RASTER FT_UNUSED( raster ) + + +#endif /* TT_STATIC_RASTER */ + + + typedef struct TRaster_Instance_ TRaster_Instance; + + + /* prototypes used for sweep function dispatch */ + typedef void + Function_Sweep_Init( RAS_ARGS Short* min, + Short* max ); + + typedef void + Function_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ); + + typedef void + Function_Sweep_Step( RAS_ARG ); + + + /* NOTE: These operations are only valid on 2's complement processors */ + +#define FLOOR( x ) ( (x) & -ras.precision ) +#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision ) +#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits ) +#define FRAC( x ) ( (x) & ( ras.precision - 1 ) ) +#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half ) + + /* Note that I have moved the location of some fields in the */ + /* structure to ensure that the most used variables are used */ + /* at the top. Thus, their offset can be coded with less */ + /* opcodes, and it results in a smaller executable. */ + + struct TRaster_Instance_ + { + Int precision_bits; /* precision related variables */ + Int precision; + Int precision_half; + Long precision_mask; + Int precision_shift; + Int precision_step; + Int precision_jitter; + + Int scale_shift; /* == precision_shift for bitmaps */ + /* == precision_shift+1 for pixmaps */ + + PLong buff; /* The profiles buffer */ + PLong sizeBuff; /* Render pool size */ + PLong maxBuff; /* Profiles buffer size */ + PLong top; /* Current cursor in buffer */ + + FT_Error error; + + Int numTurns; /* number of Y-turns in outline */ + + TPoint* arc; /* current Bezier arc pointer */ + + UShort bWidth; /* target bitmap width */ + PByte bTarget; /* target bitmap buffer */ + PByte gTarget; /* target pixmap buffer */ + + Long lastX, lastY, minY, maxY; + + UShort num_Profs; /* current number of profiles */ + + Bool fresh; /* signals a fresh new profile which */ + /* 'start' field must be completed */ + Bool joint; /* signals that the last arc ended */ + /* exactly on a scanline. Allows */ + /* removal of doublets */ + PProfile cProfile; /* current profile */ + PProfile fProfile; /* head of linked list of profiles */ + PProfile gProfile; /* contour's first profile in case */ + /* of impact */ + + TStates state; /* rendering state */ + + FT_Bitmap target; /* description of target bit/pixmap */ + FT_Outline outline; + + Long traceOfs; /* current offset in target bitmap */ + Long traceG; /* current offset in target pixmap */ + + Short traceIncr; /* sweep's increment in target bitmap */ + + Short gray_min_x; /* current min x during gray rendering */ + Short gray_max_x; /* current max x during gray rendering */ + + /* dispatch variables */ + + Function_Sweep_Init* Proc_Sweep_Init; + Function_Sweep_Span* Proc_Sweep_Span; + Function_Sweep_Span* Proc_Sweep_Drop; + Function_Sweep_Step* Proc_Sweep_Step; + + Byte dropOutControl; /* current drop_out control method */ + + Bool second_pass; /* indicates wether a horizontal pass */ + /* should be performed to control */ + /* drop-out accurately when calling */ + /* Render_Glyph. Note that there is */ + /* no horizontal pass during gray */ + /* rendering. */ + + TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */ + + TBand band_stack[16]; /* band stack used for sub-banding */ + Int band_top; /* band stack top */ + + Int count_table[256]; /* Look-up table used to quickly count */ + /* set bits in a gray 2x2 cell */ + + void* memory; + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + Byte grays[5]; /* Palette of gray levels used for */ + /* render. */ + + Byte gray_lines[RASTER_GRAY_LINES]; + /* Intermediate table used to render the */ + /* graylevels pixmaps. */ + /* gray_lines is a buffer holding two */ + /* monochrome scanlines */ + + Short gray_width; /* width in bytes of one monochrome */ + /* intermediate scanline of gray_lines. */ + /* Each gray pixel takes 2 bits long there */ + + /* The gray_lines must hold 2 lines, thus with size */ + /* in bytes of at least `gray_width*2'. */ + +#endif /* FT_RASTER_ANTI_ALIASING */ + +#if 0 + PByte flags; /* current flags table */ + PUShort outs; /* current outlines table */ + FT_Vector* coords; + + UShort nPoints; /* number of points in current glyph */ + Short nContours; /* number of contours in current glyph */ +#endif + + }; + + +#ifdef FT_CONFIG_OPTION_STATIC_RASTER + + static TRaster_Instance cur_ras; +#define ras cur_ras + +#else + +#define ras (*raster) + +#endif /* FT_CONFIG_OPTION_STATIC_RASTER */ + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** PROFILES COMPUTATION **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Set_High_Precision */ + /* */ + /* <Description> */ + /* Sets precision variables according to param flag. */ + /* */ + /* <Input> */ + /* High :: Set to True for high precision (typically for ppem < 18), */ + /* false otherwise. */ + /* */ + static void + Set_High_Precision( RAS_ARGS Int High ) + { + if ( High ) + { + ras.precision_bits = 10; + ras.precision_step = 128; + ras.precision_jitter = 24; + } + else + { + ras.precision_bits = 6; + ras.precision_step = 32; + ras.precision_jitter = 2; + } + + FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" )); + + ras.precision = 1 << ras.precision_bits; + ras.precision_half = ras.precision / 2; + ras.precision_shift = ras.precision_bits - Pixel_Bits; + ras.precision_mask = -ras.precision; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* New_Profile */ + /* */ + /* <Description> */ + /* Creates a new profile in the render pool. */ + /* */ + /* <Input> */ + /* aState :: The state/orientation of the new profile. */ + /* */ + /* <Return> */ + /* SUCCESS on success. FAILURE in case of overflow or of incoherent */ + /* profile. */ + /* */ + static Bool + New_Profile( RAS_ARGS TStates aState ) + { + if ( !ras.fProfile ) + { + ras.cProfile = (PProfile)ras.top; + ras.fProfile = ras.cProfile; + ras.top += AlignProfileSize; + } + + if ( ras.top >= ras.maxBuff ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + switch ( aState ) + { + case Ascending_State: + ras.cProfile->flow = Flow_Up; + FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile )); + break; + + case Descending_State: + ras.cProfile->flow = Flow_Down; + FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile )); + break; + + default: + FT_ERROR(( "New_Profile: invalid profile direction!\n" )); + ras.error = Raster_Err_Invalid; + return FAILURE; + } + + ras.cProfile->start = 0; + ras.cProfile->height = 0; + ras.cProfile->offset = ras.top; + ras.cProfile->link = (PProfile)0; + ras.cProfile->next = (PProfile)0; + + if ( !ras.gProfile ) + ras.gProfile = ras.cProfile; + + ras.state = aState; + ras.fresh = TRUE; + ras.joint = FALSE; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* End_Profile */ + /* */ + /* <Description> */ + /* Finalizes the current profile. */ + /* */ + /* <Return> */ + /* SUCCESS on success. FAILURE in case of overflow or incoherency. */ + /* */ + static Bool + End_Profile( RAS_ARG ) + { + Long h; + PProfile oldProfile; + + + h = (Long)( ras.top - ras.cProfile->offset ); + + if ( h < 0 ) + { + FT_ERROR(( "End_Profile: negative height encountered!\n" )); + ras.error = Raster_Err_Neg_Height; + return FAILURE; + } + + if ( h > 0 ) + { + FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n", + (long)ras.cProfile, ras.cProfile->start, h )); + + oldProfile = ras.cProfile; + ras.cProfile->height = h; + ras.cProfile = (PProfile)ras.top; + + ras.top += AlignProfileSize; + + ras.cProfile->height = 0; + ras.cProfile->offset = ras.top; + oldProfile->next = ras.cProfile; + ras.num_Profs++; + } + + if ( ras.top >= ras.maxBuff ) + { + FT_TRACE1(( "overflow in End_Profile\n" )); + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + ras.joint = FALSE; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Insert_Y_Turn */ + /* */ + /* <Description> */ + /* Inserts a salient into the sorted list placed on top of the render */ + /* pool. */ + /* */ + /* <Input> */ + /* New y scanline position. */ + /* */ + /* <Return> */ + /* SUCCESS on success. FAILURE in case of overflow. */ + /* */ + static Bool + Insert_Y_Turn( RAS_ARGS Int y ) + { + PLong y_turns; + Int y2, n; + + + n = ras.numTurns - 1; + y_turns = ras.sizeBuff - ras.numTurns; + + /* look for first y value that is <= */ + while ( n >= 0 && y < y_turns[n] ) + n--; + + /* if it is <, simply insert it, ignore if == */ + if ( n >= 0 && y > y_turns[n] ) + while ( n >= 0 ) + { + y2 = (Int)y_turns[n]; + y_turns[n] = y; + y = y2; + n--; + } + + if ( n < 0 ) + { + ras.maxBuff--; + if ( ras.maxBuff <= ras.top ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + ras.numTurns++; + ras.sizeBuff[-ras.numTurns] = y; + } + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Finalize_Profile_Table */ + /* */ + /* <Description> */ + /* Adjusts all links in the profiles list. */ + /* */ + /* <Return> */ + /* SUCCESS on success. FAILURE in case of overflow. */ + /* */ + static Bool + Finalize_Profile_Table( RAS_ARG ) + { + Int bottom, top; + UShort n; + PProfile p; + + + n = ras.num_Profs; + + if ( n > 1 ) + { + p = ras.fProfile; + while ( n > 0 ) + { + if ( n > 1 ) + p->link = (PProfile)( p->offset + p->height ); + else + p->link = NULL; + + switch ( p->flow ) + { + case Flow_Down: + bottom = (Int)( p->start - p->height + 1 ); + top = (Int)p->start; + p->start = bottom; + p->offset += p->height - 1; + break; + + case Flow_Up: + default: + bottom = (Int)p->start; + top = (Int)( p->start + p->height - 1 ); + } + + if ( Insert_Y_Turn( RAS_VARS bottom ) || + Insert_Y_Turn( RAS_VARS top + 1 ) ) + return FAILURE; + + p = p->link; + n--; + } + } + else + ras.fProfile = NULL; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Split_Conic */ + /* */ + /* <Description> */ + /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */ + /* stack. */ + /* */ + /* <Input> */ + /* None (subdivided Bezier is taken from the top of the stack). */ + /* */ + /* <Note> */ + /* This routine is the `beef' of this component. It is _the_ inner */ + /* loop that should be optimized to hell to get the best performance. */ + /* */ + static void + Split_Conic( TPoint* base ) + { + Long a, b; + + + base[4].x = base[2].x; + b = base[1].x; + a = base[3].x = ( base[2].x + b ) / 2; + b = base[1].x = ( base[0].x + b ) / 2; + base[2].x = ( a + b ) / 2; + + base[4].y = base[2].y; + b = base[1].y; + a = base[3].y = ( base[2].y + b ) / 2; + b = base[1].y = ( base[0].y + b ) / 2; + base[2].y = ( a + b ) / 2; + + /* hand optimized. gcc doesn't seem to be too good at common */ + /* expression substitution and instruction scheduling ;-) */ + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Split_Cubic */ + /* */ + /* <Description> */ + /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */ + /* Bezier stack. */ + /* */ + /* <Note> */ + /* This routine is the `beef' of the component. It is one of _the_ */ + /* inner loops that should be optimized like hell to get the best */ + /* performance. */ + /* */ + static void + Split_Cubic( TPoint* base ) + { + Long a, b, c, d; + + + base[6].x = base[3].x; + c = base[1].x; + d = base[2].x; + base[1].x = a = ( base[0].x + c + 1 ) >> 1; + base[5].x = b = ( base[3].x + d + 1 ) >> 1; + c = ( c + d + 1 ) >> 1; + base[2].x = a = ( a + c + 1 ) >> 1; + base[4].x = b = ( b + c + 1 ) >> 1; + base[3].x = ( a + b + 1 ) >> 1; + + base[6].y = base[3].y; + c = base[1].y; + d = base[2].y; + base[1].y = a = ( base[0].y + c + 1 ) >> 1; + base[5].y = b = ( base[3].y + d + 1 ) >> 1; + c = ( c + d + 1 ) >> 1; + base[2].y = a = ( a + c + 1 ) >> 1; + base[4].y = b = ( b + c + 1 ) >> 1; + base[3].y = ( a + b + 1 ) >> 1; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Line_Up */ + /* */ + /* <Description> */ + /* Computes the x-coordinates of an ascending line segment and stores */ + /* them in the render pool. */ + /* */ + /* <Input> */ + /* x1 :: The x-coordinate of the segment's start point. */ + /* */ + /* y1 :: The y-coordinate of the segment's start point. */ + /* */ + /* x2 :: The x-coordinate of the segment's end point. */ + /* */ + /* y2 :: The y-coordinate of the segment's end point. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static Bool + Line_Up( RAS_ARGS Long x1, + Long y1, + Long x2, + Long y2, + Long miny, + Long maxy ) + { + Long Dx, Dy; + Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */ + Long Ix, Rx, Ax; + + PLong top; + + + Dx = x2 - x1; + Dy = y2 - y1; + + if ( Dy <= 0 || y2 < miny || y1 > maxy ) + return SUCCESS; + + if ( y1 < miny ) + { + /* Take care: miny-y1 can be a very large value; we use */ + /* a slow MulDiv function to avoid clipping bugs */ + x1 += SMulDiv( Dx, miny - y1, Dy ); + e1 = (Int)TRUNC( miny ); + f1 = 0; + } + else + { + e1 = (Int)TRUNC( y1 ); + f1 = (Int)FRAC( y1 ); + } + + if ( y2 > maxy ) + { + /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */ + e2 = (Int)TRUNC( maxy ); + f2 = 0; + } + else + { + e2 = (Int)TRUNC( y2 ); + f2 = (Int)FRAC( y2 ); + } + + if ( f1 > 0 ) + { + if ( e1 == e2 ) + return SUCCESS; + else + { + x1 += FMulDiv( Dx, ras.precision - f1, Dy ); + e1 += 1; + } + } + else + if ( ras.joint ) + { + ras.top--; + ras.joint = FALSE; + } + + ras.joint = (char)( f2 == 0 ); + + if ( ras.fresh ) + { + ras.cProfile->start = e1; + ras.fresh = FALSE; + } + + size = e2 - e1 + 1; + if ( ras.top + size >= ras.maxBuff ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + if ( Dx > 0 ) + { + Ix = ( ras.precision * Dx ) / Dy; + Rx = ( ras.precision * Dx ) % Dy; + Dx = 1; + } + else + { + Ix = -( ( ras.precision * -Dx ) / Dy ); + Rx = ( ras.precision * -Dx ) % Dy; + Dx = -1; + } + + Ax = -Dy; + top = ras.top; + + while ( size > 0 ) + { + *top++ = x1; + + x1 += Ix; + Ax += Rx; + if ( Ax >= 0 ) + { + Ax -= Dy; + x1 += Dx; + } + size--; + } + + ras.top = top; + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Line_Down */ + /* */ + /* <Description> */ + /* Computes the x-coordinates of an descending line segment and */ + /* stores them in the render pool. */ + /* */ + /* <Input> */ + /* x1 :: The x-coordinate of the segment's start point. */ + /* */ + /* y1 :: The y-coordinate of the segment's start point. */ + /* */ + /* x2 :: The x-coordinate of the segment's end point. */ + /* */ + /* y2 :: The y-coordinate of the segment's end point. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static Bool + Line_Down( RAS_ARGS Long x1, + Long y1, + Long x2, + Long y2, + Long miny, + Long maxy ) + { + Bool result, fresh; + + + fresh = ras.fresh; + + result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny ); + + if ( fresh && !ras.fresh ) + ras.cProfile->start = -ras.cProfile->start; + + return result; + } + + + /* A function type describing the functions used to split Bezier arcs */ + typedef void (*TSplitter)( TPoint* base ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Bezier_Up */ + /* */ + /* <Description> */ + /* Computes the x-coordinates of an ascending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* <Input> */ + /* degree :: The degree of the Bezier arc (either 2 or 3). */ + /* */ + /* splitter :: The function to split Bezier arcs. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static Bool + Bezier_Up( RAS_ARGS Int degree, + TSplitter splitter, + Long miny, + Long maxy ) + { + Long y1, y2, e, e2, e0; + Short f1; + + TPoint* arc; + TPoint* start_arc; + + PLong top; + + + arc = ras.arc; + y1 = arc[degree].y; + y2 = arc[0].y; + top = ras.top; + + if ( y2 < miny || y1 > maxy ) + goto Fin; + + e2 = FLOOR( y2 ); + + if ( e2 > maxy ) + e2 = maxy; + + e0 = miny; + + if ( y1 < miny ) + e = miny; + else + { + e = CEILING( y1 ); + f1 = (Short)( FRAC( y1 ) ); + e0 = e; + + if ( f1 == 0 ) + { + if ( ras.joint ) + { + top--; + ras.joint = FALSE; + } + + *top++ = arc[degree].x; + + e += ras.precision; + } + } + + if ( ras.fresh ) + { + ras.cProfile->start = TRUNC( e0 ); + ras.fresh = FALSE; + } + + if ( e2 < e ) + goto Fin; + + if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff ) + { + ras.top = top; + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + start_arc = arc; + + while ( arc >= start_arc && e <= e2 ) + { + ras.joint = FALSE; + + y2 = arc[0].y; + + if ( y2 > e ) + { + y1 = arc[degree].y; + if ( y2 - y1 >= ras.precision_step ) + { + splitter( arc ); + arc += degree; + } + else + { + *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x, + e - y1, y2 - y1 ); + arc -= degree; + e += ras.precision; + } + } + else + { + if ( y2 == e ) + { + ras.joint = TRUE; + *top++ = arc[0].x; + + e += ras.precision; + } + arc -= degree; + } + } + + Fin: + ras.top = top; + ras.arc -= degree; + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Bezier_Down */ + /* */ + /* <Description> */ + /* Computes the x-coordinates of an descending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* <Input> */ + /* degree :: The degree of the Bezier arc (either 2 or 3). */ + /* */ + /* splitter :: The function to split Bezier arcs. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static Bool + Bezier_Down( RAS_ARGS Int degree, + TSplitter splitter, + Long miny, + Long maxy ) + { + TPoint* arc = ras.arc; + Bool result, fresh; + + + arc[0].y = -arc[0].y; + arc[1].y = -arc[1].y; + arc[2].y = -arc[2].y; + if ( degree > 2 ) + arc[3].y = -arc[3].y; + + fresh = ras.fresh; + + result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny ); + + if ( fresh && !ras.fresh ) + ras.cProfile->start = -ras.cProfile->start; + + arc[0].y = -arc[0].y; + return result; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Line_To */ + /* */ + /* <Description> */ + /* Injects a new line segment and adjusts Profiles list. */ + /* */ + /* <Input> */ + /* x :: The x-coordinate of the segment's end point (its start point */ + /* is stored in `LastX'). */ + /* */ + /* y :: The y-coordinate of the segment's end point (its start point */ + /* is stored in `LastY'). */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ + /* profile. */ + /* */ + static Bool + Line_To( RAS_ARGS Long x, + Long y ) + { + /* First, detect a change of direction */ + + switch ( ras.state ) + { + case Unknown_State: + if ( y > ras.lastY ) + { + if ( New_Profile( RAS_VARS Ascending_State ) ) + return FAILURE; + } + else + { + if ( y < ras.lastY ) + if ( New_Profile( RAS_VARS Descending_State ) ) + return FAILURE; + } + break; + + case Ascending_State: + if ( y < ras.lastY ) + { + if ( End_Profile( RAS_VAR ) || + New_Profile( RAS_VARS Descending_State ) ) + return FAILURE; + } + break; + + case Descending_State: + if ( y > ras.lastY ) + { + if ( End_Profile( RAS_VAR ) || + New_Profile( RAS_VARS Ascending_State ) ) + return FAILURE; + } + break; + + default: + ; + } + + /* Then compute the lines */ + + switch ( ras.state ) + { + case Ascending_State: + if ( Line_Up( RAS_VARS ras.lastX, ras.lastY, + x, y, ras.minY, ras.maxY ) ) + return FAILURE; + break; + + case Descending_State: + if ( Line_Down( RAS_VARS ras.lastX, ras.lastY, + x, y, ras.minY, ras.maxY ) ) + return FAILURE; + break; + + default: + ; + } + + ras.lastX = x; + ras.lastY = y; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Conic_To */ + /* */ + /* <Description> */ + /* Injects a new conic arc and adjusts the profile list. */ + /* */ + /* <Input> */ + /* cx :: The x-coordinate of the arc's new control point. */ + /* */ + /* cy :: The y-coordinate of the arc's new control point. */ + /* */ + /* x :: The x-coordinate of the arc's end point (its start point is */ + /* stored in `LastX'). */ + /* */ + /* y :: The y-coordinate of the arc's end point (its start point is */ + /* stored in `LastY'). */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ + /* profile. */ + /* */ + static Bool + Conic_To( RAS_ARGS Long cx, + Long cy, + Long x, + Long y ) + { + Long y1, y2, y3, x3, ymin, ymax; + TStates state_bez; + + + ras.arc = ras.arcs; + ras.arc[2].x = ras.lastX; + ras.arc[2].y = ras.lastY; + ras.arc[1].x = cx; ras.arc[1].y = cy; + ras.arc[0].x = x; ras.arc[0].y = y; + + do + { + y1 = ras.arc[2].y; + y2 = ras.arc[1].y; + y3 = ras.arc[0].y; + x3 = ras.arc[0].x; + + /* first, categorize the Bezier arc */ + + if ( y1 <= y3 ) + { + ymin = y1; + ymax = y3; + } + else + { + ymin = y3; + ymax = y1; + } + + if ( y2 < ymin || y2 > ymax ) + { + /* this arc has no given direction, split it! */ + Split_Conic( ras.arc ); + ras.arc += 2; + } + else if ( y1 == y3 ) + { + /* this arc is flat, ignore it and pop it from the Bezier stack */ + ras.arc -= 2; + } + else + { + /* the arc is y-monotonous, either ascending or descending */ + /* detect a change of direction */ + state_bez = y1 < y3 ? Ascending_State : Descending_State; + if ( ras.state != state_bez ) + { + /* finalize current profile if any */ + if ( ras.state != Unknown_State && + End_Profile( RAS_VAR ) ) + goto Fail; + + /* create a new profile */ + if ( New_Profile( RAS_VARS state_bez ) ) + goto Fail; + } + + /* now call the appropriate routine */ + if ( state_bez == Ascending_State ) + { + if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) + goto Fail; + } + else + if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) + goto Fail; + } + + } while ( ras.arc >= ras.arcs ); + + ras.lastX = x3; + ras.lastY = y3; + + return SUCCESS; + + Fail: + return FAILURE; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Cubic_To */ + /* */ + /* <Description> */ + /* Injects a new cubic arc and adjusts the profile list. */ + /* */ + /* <Input> */ + /* cx1 :: The x-coordinate of the arc's first new control point. */ + /* */ + /* cy1 :: The y-coordinate of the arc's first new control point. */ + /* */ + /* cx2 :: The x-coordinate of the arc's second new control point. */ + /* */ + /* cy2 :: The y-coordinate of the arc's second new control point. */ + /* */ + /* x :: The x-coordinate of the arc's end point (its start point is */ + /* stored in `LastX'). */ + /* */ + /* y :: The y-coordinate of the arc's end point (its start point is */ + /* stored in `LastY'). */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ + /* profile. */ + /* */ + static Bool + Cubic_To( RAS_ARGS Long cx1, + Long cy1, + Long cx2, + Long cy2, + Long x, + Long y ) + { + Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2; + TStates state_bez; + + + ras.arc = ras.arcs; + ras.arc[3].x = ras.lastX; + ras.arc[3].y = ras.lastY; + ras.arc[2].x = cx1; ras.arc[2].y = cy1; + ras.arc[1].x = cx2; ras.arc[1].y = cy2; + ras.arc[0].x = x; ras.arc[0].y = y; + + do + { + y1 = ras.arc[3].y; + y2 = ras.arc[2].y; + y3 = ras.arc[1].y; + y4 = ras.arc[0].y; + x4 = ras.arc[0].x; + + /* first, categorize the Bezier arc */ + + if ( y1 <= y4 ) + { + ymin1 = y1; + ymax1 = y4; + } + else + { + ymin1 = y4; + ymax1 = y1; + } + + if ( y2 <= y3 ) + { + ymin2 = y2; + ymax2 = y3; + } + else + { + ymin2 = y3; + ymax2 = y2; + } + + if ( ymin2 < ymin1 || ymax2 > ymax1 ) + { + /* this arc has no given direction, split it! */ + Split_Cubic( ras.arc ); + ras.arc += 3; + } + else if ( y1 == y4 ) + { + /* this arc is flat, ignore it and pop it from the Bezier stack */ + ras.arc -= 3; + } + else + { + state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State; + + /* detect a change of direction */ + if ( ras.state != state_bez ) + { + if ( ras.state != Unknown_State && + End_Profile( RAS_VAR ) ) + goto Fail; + + if ( New_Profile( RAS_VARS state_bez ) ) + goto Fail; + } + + /* compute intersections */ + if ( state_bez == Ascending_State ) + { + if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) + goto Fail; + } + else + if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) + goto Fail; + } + + } while ( ras.arc >= ras.arcs ); + + ras.lastX = x4; + ras.lastY = y4; + + return SUCCESS; + + Fail: + return FAILURE; + } + + +#undef SWAP_ +#define SWAP_( x, y ) do \ + { \ + Long swap = x; \ + \ + \ + x = y; \ + y = swap; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Decompose_Curve */ + /* */ + /* <Description> */ + /* Scans the outline arays in order to emit individual segments and */ + /* Beziers by calling Line_To() and Bezier_To(). It handles all */ + /* weird cases, like when the first point is off the curve, or when */ + /* there are simply no `on' points in the contour! */ + /* */ + /* <Input> */ + /* first :: The index of the first point in the contour. */ + /* */ + /* last :: The index of the last point in the contour. */ + /* */ + /* flipped :: If set, flip the direction of the curve. */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE on error. */ + /* */ + static Bool + Decompose_Curve( RAS_ARGS UShort first, + UShort last, + int flipped ) + { + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* points; + FT_Vector* point; + FT_Vector* limit; + char* tags; + + unsigned tag; /* current point's state */ + + + points = ras.outline.points; + limit = points + last; + + v_start.x = SCALED( points[first].x ); + v_start.y = SCALED( points[first].y ); + v_last.x = SCALED( points[last].x ); + v_last.y = SCALED( points[last].y ); + + if ( flipped ) + { + SWAP_( v_start.x, v_start.y ); + SWAP_( v_last.x, v_last.y ); + } + + v_control = v_start; + + point = points + first; + tags = ras.outline.tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_CURVE_TAG_CONIC ) + { + /* first point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + ras.lastX = v_start.x; + ras.lastY = v_start.y; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + + switch ( tag ) + { + case FT_CURVE_TAG_ON: /* emit a single line_to */ + { + Long x, y; + + + x = SCALED( point->x ); + y = SCALED( point->y ); + if ( flipped ) + SWAP_( x, y ); + + if ( Line_To( RAS_VARS x, y ) ) + goto Fail; + continue; + } + + case FT_CURVE_TAG_CONIC: /* consume conic arcs */ + v_control.x = SCALED( point[0].x ); + v_control.y = SCALED( point[0].y ); + + if ( flipped ) + SWAP_( v_control.x, v_control.y ); + + Do_Conic: + if ( point < limit ) + { + FT_Vector v_middle; + Long x, y; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + x = SCALED( point[0].x ); + y = SCALED( point[0].y ); + + if ( flipped ) + SWAP_( x, y ); + + if ( tag == FT_CURVE_TAG_ON ) + { + if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) ) + goto Fail; + continue; + } + + if ( tag != FT_CURVE_TAG_CONIC ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + x ) / 2; + v_middle.y = ( v_control.y + y ) / 2; + + if ( Conic_To( RAS_VARS v_control.x, v_control.y, + v_middle.x, v_middle.y ) ) + goto Fail; + + v_control.x = x; + v_control.y = y; + + goto Do_Conic; + } + + if ( Conic_To( RAS_VARS v_control.x, v_control.y, + v_start.x, v_start.y ) ) + goto Fail; + + goto Close; + + default: /* FT_CURVE_TAG_CUBIC */ + { + Long x1, y1, x2, y2, x3, y3; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + x1 = SCALED( point[-2].x ); + y1 = SCALED( point[-2].y ); + x2 = SCALED( point[-1].x ); + y2 = SCALED( point[-1].y ); + x3 = SCALED( point[ 0].x ); + y3 = SCALED( point[ 0].y ); + + if ( flipped ) + { + SWAP_( x1, y1 ); + SWAP_( x2, y2 ); + SWAP_( x3, y3 ); + } + + if ( point <= limit ) + { + if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) ) + goto Fail; + continue; + } + + if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) ) + goto Fail; + goto Close; + } + } + } + + /* close the contour with a line segment */ + if ( Line_To( RAS_VARS v_start.x, v_start.y ) ) + goto Fail; + + Close: + return SUCCESS; + + Invalid_Outline: + ras.error = Raster_Err_Invalid; + + Fail: + return FAILURE; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Convert_Glyph */ + /* */ + /* <Description> */ + /* Converts a glyph into a series of segments and arcs and makes a */ + /* profiles list with them. */ + /* */ + /* <Input> */ + /* flipped :: If set, flip the direction of curve. */ + /* */ + /* <Return> */ + /* SUCCESS on success, FAILURE if any error was encountered during */ + /* rendering. */ + /* */ + static Bool + Convert_Glyph( RAS_ARGS int flipped ) + { + int i; + unsigned start; + + PProfile lastProfile; + + + ras.fProfile = NULL; + ras.joint = FALSE; + ras.fresh = FALSE; + + ras.maxBuff = ras.sizeBuff - AlignProfileSize; + + ras.numTurns = 0; + + ras.cProfile = (PProfile)ras.top; + ras.cProfile->offset = ras.top; + ras.num_Profs = 0; + + start = 0; + + for ( i = 0; i < ras.outline.n_contours; i++ ) + { + ras.state = Unknown_State; + ras.gProfile = NULL; + + if ( Decompose_Curve( RAS_VARS (unsigned short)start, + ras.outline.contours[i], + flipped ) ) + return FAILURE; + + start = ras.outline.contours[i] + 1; + + /* We must now see whether the extreme arcs join or not */ + if ( FRAC( ras.lastY ) == 0 && + ras.lastY >= ras.minY && + ras.lastY <= ras.maxY ) + if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow ) + ras.top--; + /* Note that ras.gProfile can be nil if the contour was too small */ + /* to be drawn. */ + + lastProfile = ras.cProfile; + if ( End_Profile( RAS_VAR ) ) + return FAILURE; + + /* close the `next profile in contour' linked list */ + if ( ras.gProfile ) + lastProfile->next = ras.gProfile; + } + + if ( Finalize_Profile_Table( RAS_VAR ) ) + return FAILURE; + + return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** SCAN-LINE SWEEPS AND DRAWING **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Init_Linked */ + /* */ + /* Initializes an empty linked list. */ + /* */ + static void + Init_Linked( TProfileList* l ) + { + *l = NULL; + } + + + /*************************************************************************/ + /* */ + /* InsNew */ + /* */ + /* Inserts a new profile in a linked list. */ + /* */ + static void + InsNew( PProfileList list, + PProfile profile ) + { + PProfile *old, current; + Long x; + + + old = list; + current = *old; + x = profile->X; + + while ( current ) + { + if ( x < current->X ) + break; + old = ¤t->link; + current = *old; + } + + profile->link = current; + *old = profile; + } + + + /*************************************************************************/ + /* */ + /* DelOld */ + /* */ + /* Removes an old profile from a linked list. */ + /* */ + static void + DelOld( PProfileList list, + PProfile profile ) + { + PProfile *old, current; + + + old = list; + current = *old; + + while ( current ) + { + if ( current == profile ) + { + *old = current->link; + return; + } + + old = ¤t->link; + current = *old; + } + + /* we should never get there, unless the profile was not part of */ + /* the list. */ + } + + + /*************************************************************************/ + /* */ + /* Sort */ + /* */ + /* Sorts a trace list. In 95%, the list is already sorted. We need */ + /* an algorithm which is fast in this case. Bubble sort is enough */ + /* and simple. */ + /* */ + static void + Sort( PProfileList list ) + { + PProfile *old, current, next; + + + /* First, set the new X coordinate of each profile */ + current = *list; + while ( current ) + { + current->X = *current->offset; + current->offset += current->flow; + current->height--; + current = current->link; + } + + /* Then sort them */ + old = list; + current = *old; + + if ( !current ) + return; + + next = current->link; + + while ( next ) + { + if ( current->X <= next->X ) + { + old = ¤t->link; + current = *old; + + if ( !current ) + return; + } + else + { + *old = next; + current->link = next->link; + next->link = current; + + old = list; + current = *old; + } + + next = current->link; + } + } + + + /*************************************************************************/ + /* */ + /* Vertical Sweep Procedure Set */ + /* */ + /* These four routines are used during the vertical black/white sweep */ + /* phase by the generic Draw_Sweep() function. */ + /* */ + /*************************************************************************/ + + static void + Vertical_Sweep_Init( RAS_ARGS Short* min, + Short* max ) + { + Long pitch = ras.target.pitch; + + FT_UNUSED( max ); + + + ras.traceIncr = (Short)-pitch; + ras.traceOfs = -*min * pitch; + if ( pitch > 0 ) + ras.traceOfs += ( ras.target.rows - 1 ) * pitch; + + ras.gray_min_x = 0; + ras.gray_max_x = 0; + } + + + static void + Vertical_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + int c1, c2; + Byte f1, f2; + Byte* target; + + FT_UNUSED( y ); + FT_UNUSED( left ); + FT_UNUSED( right ); + + + /* Drop-out control */ + + e1 = TRUNC( CEILING( x1 ) ); + + if ( x2 - x1 - ras.precision <= ras.precision_jitter ) + e2 = e1; + else + e2 = TRUNC( FLOOR( x2 ) ); + + if ( e2 >= 0 && e1 < ras.bWidth ) + { + if ( e1 < 0 ) + e1 = 0; + if ( e2 >= ras.bWidth ) + e2 = ras.bWidth - 1; + + c1 = (Short)( e1 >> 3 ); + c2 = (Short)( e2 >> 3 ); + + f1 = (Byte) ( 0xFF >> ( e1 & 7 ) ); + f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) ); + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1; + if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2; + + target = ras.bTarget + ras.traceOfs + c1; + c2 -= c1; + + if ( c2 > 0 ) + { + target[0] |= f1; + + /* memset() is slower than the following code on many platforms. */ + /* This is due to the fact that, in the vast majority of cases, */ + /* the span length in bytes is relatively small. */ + c2--; + while ( c2 > 0 ) + { + *(++target) = 0xFF; + c2--; + } + target[1] |= f2; + } + else + *target |= ( f1 & f2 ); + } + } + + + static void + Vertical_Sweep_Drop( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + Short c1, f1; + + + /* Drop-out control */ + + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( (x1 + x2 + 1) / 2 ); + break; + + case 2: + case 5: + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of `stubs'. */ + /* */ + /* Here, we only get rid of stubs recognized if: */ + /* */ + /* upper stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Right is the successor of P_Left in that contour */ + /* - y is the top of P_Left and P_Right */ + /* */ + /* lower stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Left is the successor of P_Right in that contour */ + /* - y is the bottom of P_Left */ + /* */ + + /* FIXXXME: uncommenting this line solves the disappearing */ + /* bit problem in the `7' of verdana 10pts, but */ + /* makes a new one in the `C' of arial 14pts */ + +#if 0 + if ( x2 - x1 < ras.precision_half ) +#endif + { + /* upper stub test */ + if ( left->next == right && left->height <= 0 ) + return; + + /* lower stub test */ + if ( right->next == left && left->start == y ) + return; + } + + /* check that the rightmost pixel isn't set */ + + e1 = TRUNC( e1 ); + + c1 = (Short)( e1 >> 3 ); + f1 = (Short)( e1 & 7 ); + + if ( e1 >= 0 && e1 < ras.bWidth && + ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.bWidth ) + { + c1 = (Short)( e1 >> 3 ); + f1 = (Short)( e1 & 7 ); + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1; + + ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 ); + } + } + + + static void + Vertical_Sweep_Step( RAS_ARG ) + { + ras.traceOfs += ras.traceIncr; + } + + + /***********************************************************************/ + /* */ + /* Horizontal Sweep Procedure Set */ + /* */ + /* These four routines are used during the horizontal black/white */ + /* sweep phase by the generic Draw_Sweep() function. */ + /* */ + /***********************************************************************/ + + static void + Horizontal_Sweep_Init( RAS_ARGS Short* min, + Short* max ) + { + /* nothing, really */ + FT_UNUSED( raster ); + FT_UNUSED( min ); + FT_UNUSED( max ); + } + + + static void + Horizontal_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte bits; + Byte f1; + + FT_UNUSED( left ); + FT_UNUSED( right ); + + + if ( x2 - x1 < ras.precision ) + { + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 == e2 ) + { + bits = ras.bTarget + ( y >> 3 ); + f1 = (Byte)( 0x80 >> ( y & 7 ) ); + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.target.rows ) + { + PByte p; + + + p = bits - e1*ras.target.pitch; + if ( ras.target.pitch > 0 ) + p += ( ras.target.rows - 1 ) * ras.target.pitch; + + p[0] |= f1; + } + } + } + } + + + static void + Horizontal_Sweep_Drop( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte bits; + Byte f1; + + + /* During the horizontal sweep, we only take care of drop-outs */ + + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + break; + + case 2: + case 5: + + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of `stubs'. */ + /* */ + + /* rightmost stub test */ + if ( left->next == right && left->height <= 0 ) + return; + + /* leftmost stub test */ + if ( right->next == left && left->start == y ) + return; + + /* check that the rightmost pixel isn't set */ + + e1 = TRUNC( e1 ); + + bits = ras.bTarget + ( y >> 3 ); + f1 = (Byte)( 0x80 >> ( y & 7 ) ); + + bits -= e1 * ras.target.pitch; + if ( ras.target.pitch > 0 ) + bits += ( ras.target.rows - 1 ) * ras.target.pitch; + + if ( e1 >= 0 && + e1 < ras.target.rows && + *bits & f1 ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + bits = ras.bTarget + ( y >> 3 ); + f1 = (Byte)( 0x80 >> ( y & 7 ) ); + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.target.rows ) + { + bits -= e1 * ras.target.pitch; + if ( ras.target.pitch > 0 ) + bits += ( ras.target.rows - 1 ) * ras.target.pitch; + + bits[0] |= f1; + } + } + + + static void + Horizontal_Sweep_Step( RAS_ARG ) + { + /* Nothing, really */ + FT_UNUSED( raster ); + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + + /*************************************************************************/ + /* */ + /* Vertical Gray Sweep Procedure Set */ + /* */ + /* These two routines are used during the vertical gray-levels sweep */ + /* phase by the generic Draw_Sweep() function. */ + /* */ + /* NOTES */ + /* */ + /* - The target pixmap's width *must* be a multiple of 4. */ + /* */ + /* - You have to use the function Vertical_Sweep_Span() for the gray */ + /* span call. */ + /* */ + /*************************************************************************/ + + static void + Vertical_Gray_Sweep_Init( RAS_ARGS Short* min, + Short* max ) + { + Long pitch, byte_len; + + + *min = *min & -2; + *max = ( *max + 3 ) & -2; + + ras.traceOfs = 0; + pitch = ras.target.pitch; + byte_len = -pitch; + ras.traceIncr = (Short)byte_len; + ras.traceG = ( *min / 2 ) * byte_len; + + if ( pitch > 0 ) + { + ras.traceG += ( ras.target.rows - 1 ) * pitch; + byte_len = -byte_len; + } + + ras.gray_min_x = (Short)byte_len; + ras.gray_max_x = -(Short)byte_len; + } + + + static void + Vertical_Gray_Sweep_Step( RAS_ARG ) + { + Int c1, c2; + PByte pix, bit, bit2; + Int* count = ras.count_table; + Byte* grays; + + + ras.traceOfs += ras.gray_width; + + if ( ras.traceOfs > ras.gray_width ) + { + pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4; + grays = ras.grays; + + if ( ras.gray_max_x >= 0 ) + { + Long last_pixel = ras.target.width - 1; + Int last_cell = last_pixel >> 2; + Int last_bit = last_pixel & 3; + Bool over = 0; + + + if ( ras.gray_max_x >= last_cell && last_bit != 3 ) + { + ras.gray_max_x = last_cell - 1; + over = 1; + } + + if ( ras.gray_min_x < 0 ) + ras.gray_min_x = 0; + + bit = ras.bTarget + ras.gray_min_x; + bit2 = bit + ras.gray_width; + + c1 = ras.gray_max_x - ras.gray_min_x; + + while ( c1 >= 0 ) + { + c2 = count[*bit] + count[*bit2]; + + if ( c2 ) + { + pix[0] = grays[(c2 >> 12) & 0x000F]; + pix[1] = grays[(c2 >> 8 ) & 0x000F]; + pix[2] = grays[(c2 >> 4 ) & 0x000F]; + pix[3] = grays[ c2 & 0x000F]; + + *bit = 0; + *bit2 = 0; + } + + bit++; + bit2++; + pix += 4; + c1--; + } + + if ( over ) + { + c2 = count[*bit] + count[*bit2]; + if ( c2 ) + { + switch ( last_bit ) + { + case 2: + pix[2] = grays[(c2 >> 4 ) & 0x000F]; + case 1: + pix[1] = grays[(c2 >> 8 ) & 0x000F]; + default: + pix[0] = grays[(c2 >> 12) & 0x000F]; + } + + *bit = 0; + *bit2 = 0; + } + } + } + + ras.traceOfs = 0; + ras.traceG += ras.traceIncr; + + ras.gray_min_x = 32000; + ras.gray_max_x = -32000; + } + } + + + static void + Horizontal_Gray_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + /* nothing, really */ + FT_UNUSED( raster ); + FT_UNUSED( y ); + FT_UNUSED( x1 ); + FT_UNUSED( x2 ); + FT_UNUSED( left ); + FT_UNUSED( right ); + } + + + static void + Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte pixel; + Byte color; + + + /* During the horizontal sweep, we only take care of drop-outs */ + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + break; + + case 2: + case 5: + + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of `stubs'. */ + /* */ + + /* rightmost stub test */ + if ( left->next == right && left->height <= 0 ) + return; + + /* leftmost stub test */ + if ( right->next == left && left->start == y ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + if ( e1 >= 0 ) + { + if ( x2 - x1 >= ras.precision_half ) + color = ras.grays[2]; + else + color = ras.grays[1]; + + e1 = TRUNC( e1 ) / 2; + if ( e1 < ras.target.rows ) + { + pixel = ras.gTarget - e1 * ras.target.pitch + y / 2; + if ( ras.target.pitch > 0 ) + pixel += ( ras.target.rows - 1 ) * ras.target.pitch; + + if ( pixel[0] == ras.grays[0] ) + pixel[0] = color; + } + } + } + + +#endif /* FT_RASTER_OPTION_ANTI_ALIASING */ + + + /*************************************************************************/ + /* */ + /* Generic Sweep Drawing routine */ + /* */ + /*************************************************************************/ + + static Bool + Draw_Sweep( RAS_ARG ) + { + Short y, y_change, y_height; + + PProfile P, Q, P_Left, P_Right; + + Short min_Y, max_Y, top, bottom, dropouts; + + Long x1, x2, xs, e1, e2; + + TProfileList waiting; + TProfileList draw_left, draw_right; + + + /* Init empty linked lists */ + + Init_Linked( &waiting ); + + Init_Linked( &draw_left ); + Init_Linked( &draw_right ); + + /* first, compute min and max Y */ + + P = ras.fProfile; + max_Y = (Short)TRUNC( ras.minY ); + min_Y = (Short)TRUNC( ras.maxY ); + + while ( P ) + { + Q = P->link; + + bottom = (Short)P->start; + top = (Short)( P->start + P->height - 1 ); + + if ( min_Y > bottom ) min_Y = bottom; + if ( max_Y < top ) max_Y = top; + + P->X = 0; + InsNew( &waiting, P ); + + P = Q; + } + + /* Check the Y-turns */ + if ( ras.numTurns == 0 ) + { + ras.error = Raster_Err_Invalid; + return FAILURE; + } + + /* Now inits the sweep */ + + ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y ); + + /* Then compute the distance of each profile from min_Y */ + + P = waiting; + + while ( P ) + { + P->countL = (UShort)( P->start - min_Y ); + P = P->link; + } + + /* Let's go */ + + y = min_Y; + y_height = 0; + + if ( ras.numTurns > 0 && + ras.sizeBuff[-ras.numTurns] == min_Y ) + ras.numTurns--; + + while ( ras.numTurns > 0 ) + { + /* look in the waiting list for new activations */ + + P = waiting; + + while ( P ) + { + Q = P->link; + P->countL -= y_height; + if ( P->countL == 0 ) + { + DelOld( &waiting, P ); + + switch ( P->flow ) + { + case Flow_Up: + InsNew( &draw_left, P ); + break; + + case Flow_Down: + InsNew( &draw_right, P ); + break; + } + } + + P = Q; + } + + /* Sort the drawing lists */ + + Sort( &draw_left ); + Sort( &draw_right ); + + y_change = (Short)ras.sizeBuff[-ras.numTurns--]; + y_height = (Short)( y_change - y ); + + while ( y < y_change ) + { + /* Let's trace */ + + dropouts = 0; + + P_Left = draw_left; + P_Right = draw_right; + + while ( P_Left ) + { + x1 = P_Left ->X; + x2 = P_Right->X; + + if ( x1 > x2 ) + { + xs = x1; + x1 = x2; + x2 = xs; + } + + if ( x2 - x1 <= ras.precision ) + { + e1 = FLOOR( x1 ); + e2 = CEILING( x2 ); + + if ( ras.dropOutControl != 0 && + ( e1 > e2 || e2 == e1 + ras.precision ) ) + { + /* a drop out was detected */ + + P_Left ->X = x1; + P_Right->X = x2; + + /* mark profile for drop-out processing */ + P_Left->countL = 1; + dropouts++; + + goto Skip_To_Next; + } + } + + ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right ); + + Skip_To_Next: + + P_Left = P_Left->link; + P_Right = P_Right->link; + } + + /* now perform the dropouts _after_ the span drawing -- */ + /* drop-outs processing has been moved out of the loop */ + /* for performance tuning */ + if ( dropouts > 0 ) + goto Scan_DropOuts; + + Next_Line: + + ras.Proc_Sweep_Step( RAS_VAR ); + + y++; + + if ( y < y_change ) + { + Sort( &draw_left ); + Sort( &draw_right ); + } + } + + /* Now finalize the profiles that needs it */ + + P = draw_left; + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_left, P ); + P = Q; + } + + P = draw_right; + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_right, P ); + P = Q; + } + } + + /* for gray-scaling, flushes the bitmap scanline cache */ + while ( y <= max_Y ) + { + ras.Proc_Sweep_Step( RAS_VAR ); + y++; + } + + return SUCCESS; + + Scan_DropOuts: + + P_Left = draw_left; + P_Right = draw_right; + + while ( P_Left ) + { + if ( P_Left->countL ) + { + P_Left->countL = 0; +#if 0 + dropouts--; /* -- this is useful when debugging only */ +#endif + ras.Proc_Sweep_Drop( RAS_VARS y, + P_Left->X, + P_Right->X, + P_Left, + P_Right ); + } + + P_Left = P_Left->link; + P_Right = P_Right->link; + } + + goto Next_Line; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Render_Single_Pass */ + /* */ + /* <Description> */ + /* Performs one sweep with sub-banding. */ + /* */ + /* <Input> */ + /* flipped :: If set, flip the direction of the outline. */ + /* */ + /* <Return> */ + /* Renderer error code. */ + /* */ + static int + Render_Single_Pass( RAS_ARGS Bool flipped ) + { + Short i, j, k; + + + while ( ras.band_top >= 0 ) + { + ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision; + ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision; + + ras.top = ras.buff; + + ras.error = Raster_Err_None; + + if ( Convert_Glyph( RAS_VARS flipped ) ) + { + if ( ras.error != Raster_Err_Overflow ) + return FAILURE; + + ras.error = Raster_Err_None; + + /* sub-banding */ + +#ifdef DEBUG_RASTER + ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) ); +#endif + + i = ras.band_stack[ras.band_top].y_min; + j = ras.band_stack[ras.band_top].y_max; + + k = (Short)( ( i + j ) / 2 ); + + if ( ras.band_top >= 7 || k < i ) + { + ras.band_top = 0; + ras.error = Raster_Err_Invalid; + + return ras.error; + } + + ras.band_stack[ras.band_top + 1].y_min = k; + ras.band_stack[ras.band_top + 1].y_max = j; + + ras.band_stack[ras.band_top].y_max = (Short)( k - 1 ); + + ras.band_top++; + } + else + { + if ( ras.fProfile ) + if ( Draw_Sweep( RAS_VAR ) ) + return ras.error; + ras.band_top--; + } + } + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Render_Glyph */ + /* */ + /* <Description> */ + /* Renders a glyph in a bitmap. Sub-banding if needed. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + Render_Glyph( RAS_ARG ) + { + FT_Error error; + + + Set_High_Precision( RAS_VARS ras.outline.flags & + FT_OUTLINE_HIGH_PRECISION ); + ras.scale_shift = ras.precision_shift; + ras.dropOutControl = 2; + ras.second_pass = (FT_Byte)( !( ras.outline.flags & + FT_OUTLINE_SINGLE_PASS ) ); + + /* Vertical Sweep */ + ras.Proc_Sweep_Init = Vertical_Sweep_Init; + ras.Proc_Sweep_Span = Vertical_Sweep_Span; + ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; + ras.Proc_Sweep_Step = Vertical_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = (short)( ras.target.rows - 1 ); + + ras.bWidth = (unsigned short)ras.target.width; + ras.bTarget = (Byte*)ras.target.buffer; + + if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 ) + return error; + + /* Horizontal Sweep */ + if ( ras.second_pass && ras.dropOutControl != 0 ) + { + ras.Proc_Sweep_Init = Horizontal_Sweep_Init; + ras.Proc_Sweep_Span = Horizontal_Sweep_Span; + ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop; + ras.Proc_Sweep_Step = Horizontal_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = (short)( ras.target.width - 1 ); + + if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 ) + return error; + } + + return Raster_Err_Ok; + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Render_Gray_Glyph */ + /* */ + /* <Description> */ + /* Renders a glyph with grayscaling. Sub-banding if needed. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + Render_Gray_Glyph( RAS_ARG ) + { + Long pixel_width; + FT_Error error; + + + Set_High_Precision( RAS_VARS ras.outline.flags & + FT_OUTLINE_HIGH_PRECISION ); + ras.scale_shift = ras.precision_shift + 1; + ras.dropOutControl = 2; + ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ); + + /* Vertical Sweep */ + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = 2 * ras.target.rows - 1; + + ras.bWidth = ras.gray_width; + pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 ); + + if ( ras.bWidth > pixel_width ) + ras.bWidth = pixel_width; + + ras.bWidth = ras.bWidth * 8; + ras.bTarget = (Byte*)ras.gray_lines; + ras.gTarget = (Byte*)ras.target.buffer; + + ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init; + ras.Proc_Sweep_Span = Vertical_Sweep_Span; + ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; + ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step; + + error = Render_Single_Pass( RAS_VARS 0 ); + if ( error ) + return error; + + /* Horizontal Sweep */ + if ( ras.second_pass && ras.dropOutControl != 0 ) + { + ras.Proc_Sweep_Init = Horizontal_Sweep_Init; + ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span; + ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop; + ras.Proc_Sweep_Step = Horizontal_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.width * 2 - 1; + + error = Render_Single_Pass( RAS_VARS 1 ); + if ( error ) + return error; + } + + return Raster_Err_Ok; + } + +#else /* !FT_RASTER_OPTION_ANTI_ALIASING */ + + FT_LOCAL_DEF( FT_Error ) + Render_Gray_Glyph( RAS_ARG ) + { + FT_UNUSED_RASTER; + + return Raster_Err_Cannot_Render_Glyph; + } + +#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */ + + + static void + ft_black_init( TRaster_Instance* raster ) + { + FT_UInt n; + FT_ULong c; + + + /* setup count table */ + for ( n = 0; n < 256; n++ ) + { + c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 ); + + c = ( ( c << 6 ) & 0x3000 ) | + ( ( c << 4 ) & 0x0300 ) | + ( ( c << 2 ) & 0x0030 ) | + (c & 0x0003 ); + + raster->count_table[n] = (UInt)c; + } + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + /* set default 5-levels gray palette */ + for ( n = 0; n < 5; n++ ) + raster->grays[n] = n * 255 / 4; + + raster->gray_width = RASTER_GRAY_LINES / 2; + +#endif + } + + + /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ + /**** a static object. *****/ + + +#ifdef _STANDALONE_ + + + static int + ft_black_new( void* memory, + FT_Raster *araster ) + { + static FT_RasterRec_ the_raster; + + + *araster = &the_raster; + FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) ); + ft_black_init( &the_raster ); + + return 0; + } + + + static void + ft_black_done( FT_Raster raster ) + { + /* nothing */ + raster->init = 0; + } + + +#else /* _STANDALONE_ */ + + + static int + ft_black_new( FT_Memory memory, + TRaster_Instance** araster ) + { + FT_Error error; + TRaster_Instance* raster; + + + *araster = 0; + if ( !FT_NEW( raster ) ) + { + raster->memory = memory; + ft_black_init( raster ); + + *araster = raster; + } + + return error; + } + + + static void + ft_black_done( TRaster_Instance* raster ) + { + FT_Memory memory = (FT_Memory)raster->memory; + FT_FREE( raster ); + } + + +#endif /* _STANDALONE_ */ + + + static void + ft_black_reset( TRaster_Instance* raster, + const char* pool_base, + long pool_size ) + { + if ( raster && pool_base && pool_size >= 4096 ) + { + /* save the pool */ + raster->buff = (PLong)pool_base; + raster->sizeBuff = raster->buff + pool_size / sizeof ( Long ); + } + } + + + static void + ft_black_set_mode( TRaster_Instance* raster, + unsigned long mode, + const char* palette ) + { +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) ) + { + /* set 5-levels gray palette */ + raster->grays[0] = palette[0]; + raster->grays[1] = palette[1]; + raster->grays[2] = palette[2]; + raster->grays[3] = palette[3]; + raster->grays[4] = palette[4]; + } + +#else + + FT_UNUSED( raster ); + FT_UNUSED( mode ); + FT_UNUSED( palette ); + +#endif + } + + + static int + ft_black_render( TRaster_Instance* raster, + FT_Raster_Params* params ) + { + FT_Outline* outline = (FT_Outline*)params->source; + FT_Bitmap* target_map = params->target; + + + if ( !raster || !raster->buff || !raster->sizeBuff ) + return Raster_Err_Not_Ini; + + /* return immediately if the outline is empty */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + return Raster_Err_None; + + if ( !outline || !outline->contours || !outline->points ) + return Raster_Err_Invalid; + + if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 ) + return Raster_Err_Invalid; + + /* this version of the raster does not support direct rendering, sorry */ + if ( params->flags & FT_RASTER_FLAG_DIRECT ) + return Raster_Err_Unsupported; + + if ( !target_map || !target_map->buffer ) + return Raster_Err_Invalid; + + ras.outline = *outline; + ras.target = *target_map; + + return ( ( params->flags & FT_RASTER_FLAG_AA ) + ? Render_Gray_Glyph( raster ) + : Render_Glyph( raster ) ); + } + + + const FT_Raster_Funcs ft_standard_raster = + { + FT_GLYPH_FORMAT_OUTLINE, + (FT_Raster_New_Func) ft_black_new, + (FT_Raster_Reset_Func) ft_black_reset, + (FT_Raster_Set_Mode_Func)ft_black_set_mode, + (FT_Raster_Render_Func) ft_black_render, + (FT_Raster_Done_Func) ft_black_done + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/raster/ftraster.h b/Utilities/vtkfreetype/src/raster/ftraster.h new file mode 100644 index 0000000..80fe46d --- /dev/null +++ b/Utilities/vtkfreetype/src/raster/ftraster.h @@ -0,0 +1,46 @@ +/***************************************************************************/ +/* */ +/* ftraster.h */ +/* */ +/* The FreeType glyph rasterizer (specification). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTRASTER_H__ +#define __FTRASTER_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_IMAGE_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* Uncomment the following line if you are using ftraster.c as a */ + /* standalone module, fully independent of FreeType. */ + /* */ +/* #define _STANDALONE_ */ + + FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_standard_raster; + + +FT_END_HEADER + +#endif /* __FTRASTER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/raster/ftrend1.c b/Utilities/vtkfreetype/src/raster/ftrend1.c new file mode 100644 index 0000000..a17ef9b --- /dev/null +++ b/Utilities/vtkfreetype/src/raster/ftrend1.c @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* ftrend1.c */ +/* */ +/* The FreeType glyph rasterizer interface (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_OUTLINE_H +#include "ftrend1.h" +#include "ftraster.h" + +#include "rasterrs.h" + + + /* initialize renderer -- init its raster */ + static FT_Error + ft_raster1_init( FT_Renderer render ) + { + FT_Library library = FT_MODULE_LIBRARY( render ); + + + render->clazz->raster_class->raster_reset( render->raster, + library->raster_pool, + library->raster_pool_size ); + + return Raster_Err_Ok; + } + + + /* set render-specific mode */ + static FT_Error + ft_raster1_set_mode( FT_Renderer render, + FT_ULong mode_tag, + FT_Pointer data ) + { + /* we simply pass it to the raster */ + return render->clazz->raster_class->raster_set_mode( render->raster, + mode_tag, + data ); + } + + + /* transform a given glyph image */ + static FT_Error + ft_raster1_transform( FT_Renderer render, + FT_GlyphSlot slot, + FT_Matrix* matrix, + FT_Vector* delta ) + { + FT_Error error = Raster_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = Raster_Err_Invalid_Argument; + goto Exit; + } + + if ( matrix ) + FT_Outline_Transform( &slot->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &slot->outline, delta->x, delta->y ); + + Exit: + return error; + } + + + /* return the glyph's control box */ + static void + ft_raster1_get_cbox( FT_Renderer render, + FT_GlyphSlot slot, + FT_BBox* cbox ) + { + FT_MEM_ZERO( cbox, sizeof ( *cbox ) ); + + if ( slot->format == render->glyph_format ) + FT_Outline_Get_CBox( &slot->outline, cbox ); + } + + + /* convert a slot's glyph image into a bitmap */ + static FT_Error + ft_raster1_render( FT_Renderer render, + FT_GlyphSlot slot, + FT_Render_Mode mode, + FT_Vector* origin ) + { + FT_Error error; + FT_Outline* outline; + FT_BBox cbox; + FT_UInt width, height, pitch; + FT_Bitmap* bitmap; + FT_Memory memory; + + FT_Raster_Params params; + + + /* check glyph image format */ + if ( slot->format != render->glyph_format ) + { + error = Raster_Err_Invalid_Argument; + goto Exit; + } + + /* check rendering mode */ + if ( mode != FT_RENDER_MODE_MONO ) + { + /* raster1 is only capable of producing monochrome bitmaps */ + if ( render->clazz == &ft_raster1_renderer_class ) + return Raster_Err_Cannot_Render_Glyph; + } + else + { + /* raster5 is only capable of producing 5-gray-levels bitmaps */ + if ( render->clazz == &ft_raster5_renderer_class ) + return Raster_Err_Cannot_Render_Glyph; + } + + outline = &slot->outline; + + /* translate the outline to the new origin if needed */ + if ( origin ) + FT_Outline_Translate( outline, origin->x, origin->y ); + + /* compute the control box, and grid fit it */ + FT_Outline_Get_CBox( outline, &cbox ); + + cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); + cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); + cbox.xMax = FT_PIX_CEIL( cbox.xMax ); + cbox.yMax = FT_PIX_CEIL( cbox.yMax ); + + width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 ); + height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 ); + bitmap = &slot->bitmap; + memory = render->root.memory; + + /* release old bitmap buffer */ + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( bitmap->buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + + /* allocate new one, depends on pixel format */ + if ( !( mode & FT_RENDER_MODE_MONO ) ) + { + /* we pad to 32 bits, only for backwards compatibility with FT 1.x */ + pitch = FT_PAD_CEIL( width, 4 ); + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap->num_grays = 256; + } + else + { + pitch = ( ( width + 15 ) >> 4 ) << 1; + bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + } + + bitmap->width = width; + bitmap->rows = height; + bitmap->pitch = pitch; + + if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) + goto Exit; + + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + /* translate outline to render it into the bitmap */ + FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin ); + + /* set up parameters */ + params.target = bitmap; + params.source = outline; + params.flags = 0; + + if ( bitmap->pixel_mode == FT_PIXEL_MODE_GRAY ) + params.flags |= FT_RASTER_FLAG_AA; + + /* render outline into the bitmap */ + error = render->raster_render( render->raster, ¶ms ); + + FT_Outline_Translate( outline, cbox.xMin, cbox.yMin ); + + if ( error ) + goto Exit; + + slot->format = FT_GLYPH_FORMAT_BITMAP; + slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 ); + slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 ); + + Exit: + return error; + } + + + FT_CALLBACK_TABLE_DEF + const FT_Renderer_Class ft_raster1_renderer_class = + { + { + FT_MODULE_RENDERER, + sizeof( FT_RendererRec ), + + "raster1", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_raster1_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Renderer_RenderFunc) ft_raster1_render, + (FT_Renderer_TransformFunc)ft_raster1_transform, + (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, + (FT_Renderer_SetModeFunc) ft_raster1_set_mode, + + (FT_Raster_Funcs*) &ft_standard_raster + }; + + + /* This renderer is _NOT_ part of the default modules; you will need */ + /* to register it by hand in your application. It should only be */ + /* used for backwards-compatibility with FT 1.x anyway. */ + /* */ + FT_CALLBACK_TABLE_DEF + const FT_Renderer_Class ft_raster5_renderer_class = + { + { + FT_MODULE_RENDERER, + sizeof( FT_RendererRec ), + + "raster5", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_raster1_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Renderer_RenderFunc) ft_raster1_render, + (FT_Renderer_TransformFunc)ft_raster1_transform, + (FT_Renderer_GetCBoxFunc) ft_raster1_get_cbox, + (FT_Renderer_SetModeFunc) ft_raster1_set_mode, + + (FT_Raster_Funcs*) &ft_standard_raster + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/raster/ftrend1.h b/Utilities/vtkfreetype/src/raster/ftrend1.h new file mode 100644 index 0000000..76e9a5f --- /dev/null +++ b/Utilities/vtkfreetype/src/raster/ftrend1.h @@ -0,0 +1,44 @@ +/***************************************************************************/ +/* */ +/* ftrend1.h */ +/* */ +/* The FreeType glyph rasterizer interface (specification). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTREND1_H__ +#define __FTREND1_H__ + + +#include <ft2build.h> +#include FT_RENDER_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster1_renderer_class; + + /* this renderer is _NOT_ part of the default modules, you'll need */ + /* to register it by hand in your application. It should only be */ + /* used for backwards-compatibility with FT 1.x anyway. */ + /* */ + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster5_renderer_class; + + +FT_END_HEADER + +#endif /* __FTREND1_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/raster/raster.c b/Utilities/vtkfreetype/src/raster/raster.c new file mode 100644 index 0000000..f13a67a --- /dev/null +++ b/Utilities/vtkfreetype/src/raster/raster.c @@ -0,0 +1,26 @@ +/***************************************************************************/ +/* */ +/* raster.c */ +/* */ +/* FreeType monochrome rasterer module component (body only). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "ftraster.c" +#include "ftrend1.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/raster/rasterrs.h b/Utilities/vtkfreetype/src/raster/rasterrs.h new file mode 100644 index 0000000..5df9a7a --- /dev/null +++ b/Utilities/vtkfreetype/src/raster/rasterrs.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* rasterrs.h */ +/* */ +/* monochrome renderer error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the monochrome renderer error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __RASTERRS_H__ +#define __RASTERRS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX Raster_Err_ +#define FT_ERR_BASE FT_Mod_Err_Raster + +#include FT_ERRORS_H + +#endif /* __RASTERRS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/sfdriver.c b/Utilities/vtkfreetype/src/sfnt/sfdriver.c new file mode 100644 index 0000000..05f6299 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/sfdriver.c @@ -0,0 +1,420 @@ +/***************************************************************************/ +/* */ +/* sfdriver.c */ +/* */ +/* High-level SFNT driver interface (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_SFNT_H +#include FT_INTERNAL_OBJECTS_H + +#include "sfdriver.h" +#include "ttload.h" +#include "sfobjs.h" + +#include "sferrors.h" + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include "ttsbit.h" +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttpost.h" +#endif + +#include "ttcmap0.h" + +#include FT_SERVICE_GLYPH_DICT_H +#include FT_SERVICE_POSTSCRIPT_NAME_H +#include FT_SERVICE_SFNT_H +#include FT_SERVICE_TT_CMAP_H + + + /* + * SFNT TABLE SERVICE + * + */ + + static void* + get_sfnt_table( TT_Face face, + FT_Sfnt_Tag tag ) + { + void* table; + + + switch ( tag ) + { + case ft_sfnt_head: + table = &face->header; + break; + + case ft_sfnt_hhea: + table = &face->horizontal; + break; + + case ft_sfnt_vhea: + table = face->vertical_info ? &face->vertical : 0; + break; + + case ft_sfnt_os2: + table = face->os2.version == 0xFFFFU ? 0 : &face->os2; + break; + + case ft_sfnt_post: + table = &face->postscript; + break; + + case ft_sfnt_maxp: + table = &face->max_profile; + break; + + case ft_sfnt_pclt: + table = face->pclt.Version ? &face->pclt : 0; + break; + + default: + table = 0; + } + + return table; + } + + + static FT_Error + sfnt_table_info( TT_Face face, + FT_UInt idx, + FT_ULong *tag, + FT_ULong *length ) + { + if ( !tag || !length ) + return SFNT_Err_Invalid_Argument; + + if ( idx >= face->num_tables ) + return SFNT_Err_Table_Missing; + + *tag = face->dir_tables[idx].Tag; + *length = face->dir_tables[idx].Length; + + return SFNT_Err_Ok; + } + + + static const FT_Service_SFNT_TableRec sfnt_service_sfnt_table = + { + (FT_SFNT_TableLoadFunc)tt_face_load_any, + (FT_SFNT_TableGetFunc) get_sfnt_table, + (FT_SFNT_TableInfoFunc)sfnt_table_info + }; + + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + /* + * GLYPH DICT SERVICE + * + */ + + static FT_Error + sfnt_get_glyph_name( TT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_String* gname; + FT_Error error; + + + error = tt_face_get_ps_name( face, glyph_index, &gname ); + if ( !error && buffer_max > 0 ) + { + FT_UInt len = (FT_UInt)( ft_strlen( gname ) ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + FT_MEM_COPY( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return error; + } + + + static const FT_Service_GlyphDictRec sfnt_service_glyph_dict = + { + (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, + (FT_GlyphDict_NameIndexFunc)NULL + }; + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + /* + * POSTSCRIPT NAME SERVICE + * + */ + + static const char* + sfnt_get_ps_name( TT_Face face ) + { + FT_Int n, found_win, found_apple; + const char* result = NULL; + + + /* shouldn't happen, but just in case to avoid memory leaks */ + if ( face->postscript_name ) + return face->postscript_name; + + /* scan the name table to see whether we have a Postscript name here, */ + /* either in Macintosh or Windows platform encodings */ + found_win = -1; + found_apple = -1; + + for ( n = 0; n < face->num_names; n++ ) + { + TT_NameEntryRec* name = face->name_table.names + n; + + + if ( name->nameID == 6 && name->stringLength > 0 ) + { + if ( name->platformID == 3 && + name->encodingID == 1 && + name->languageID == 0x409 ) + found_win = n; + + if ( name->platformID == 1 && + name->encodingID == 0 && + name->languageID == 0 ) + found_apple = n; + } + } + + if ( found_win != -1 ) + { + FT_Memory memory = face->root.memory; + TT_NameEntryRec* name = face->name_table.names + found_win; + FT_UInt len = name->stringLength / 2; + FT_Error error = SFNT_Err_Ok; + + FT_UNUSED( error ); + + + if ( !FT_ALLOC( result, name->stringLength + 1 ) ) + { + FT_Stream stream = face->name_table.stream; + FT_String* r = (FT_String*)result; + FT_Byte* p = (FT_Byte*)name->string; + + + if ( FT_STREAM_SEEK( name->stringOffset ) || + FT_FRAME_ENTER( name->stringLength ) ) + { + FT_FREE( result ); + name->stringLength = 0; + name->stringOffset = 0; + FT_FREE( name->string ); + + goto Exit; + } + + p = (FT_Byte*)stream->cursor; + + for ( ; len > 0; len--, p += 2 ) + { + if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 ) + *r++ = p[1]; + } + *r = '\0'; + + FT_FRAME_EXIT(); + } + goto Exit; + } + + if ( found_apple != -1 ) + { + FT_Memory memory = face->root.memory; + TT_NameEntryRec* name = face->name_table.names + found_apple; + FT_UInt len = name->stringLength; + FT_Error error = SFNT_Err_Ok; + + FT_UNUSED( error ); + + + if ( !FT_ALLOC( result, len + 1 ) ) + { + FT_Stream stream = face->name_table.stream; + + + if ( FT_STREAM_SEEK( name->stringOffset ) || + FT_STREAM_READ( result, len ) ) + { + name->stringOffset = 0; + name->stringLength = 0; + FT_FREE( name->string ); + FT_FREE( result ); + goto Exit; + } + ((char*)result)[len] = '\0'; + } + } + + Exit: + face->postscript_name = result; + return result; + } + + static const FT_Service_PsFontNameRec sfnt_service_ps_name = + { + (FT_PsName_GetFunc)sfnt_get_ps_name + }; + + + /* + * TT CMAP INFO + * + */ + static const FT_Service_TTCMapsRec tt_service_get_cmap_info = + { + (TT_CMap_Info_GetFunc)tt_get_cmap_info + }; + + + /* + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec sfnt_services[] = + { + { FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table }, + { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name }, +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + { FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict }, +#endif + { FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info }, + + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + sfnt_get_interface( FT_Module module, + const char* module_interface ) + { + FT_UNUSED( module ); + + if ( ft_strcmp( module_interface, "get_sfnt" ) == 0 ) + return (FT_Module_Interface)get_sfnt_table; + + if ( ft_strcmp( module_interface, "load_sfnt" ) == 0 ) + return (FT_Module_Interface)tt_face_load_any; + + return ft_service_list_lookup( sfnt_services, module_interface ); + } + + + static + const SFNT_Interface sfnt_interface = + { + tt_face_goto_table, + + sfnt_init_face, + sfnt_load_face, + sfnt_done_face, + sfnt_get_interface, + + tt_face_load_any, + tt_face_load_sfnt_header, + tt_face_load_directory, + + tt_face_load_header, + tt_face_load_metrics_header, + tt_face_load_cmap, + tt_face_load_max_profile, + tt_face_load_os2, + tt_face_load_postscript, + + tt_face_load_names, + tt_face_free_names, + + tt_face_load_hdmx, + tt_face_free_hdmx, + + tt_face_load_kern, + tt_face_load_gasp, + tt_face_load_pclt, + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* see `ttload.h' */ + tt_face_load_bitmap_header, + + /* see `ttsbit.h' and `sfnt.h' */ + tt_face_set_sbit_strike, + tt_face_load_sbit_strikes, + tt_find_sbit_image, + tt_load_sbit_metrics, + tt_face_load_sbit_image, + tt_face_free_sbit_strikes, + +#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + 0, + 0, + 0, + 0, + 0, + 0, + 0, + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + /* see `ttpost.h' */ + tt_face_get_ps_name, + tt_face_free_ps_names, + +#else /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + 0, + 0, + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + }; + + + FT_CALLBACK_TABLE_DEF + const FT_Module_Class sfnt_module_class = + { + 0, /* not a font driver or renderer */ + sizeof( FT_ModuleRec ), + + "sfnt", /* driver name */ + 0x10000L, /* driver version 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or higher */ + + (const void*)&sfnt_interface, /* module specific interface */ + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) sfnt_get_interface + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/sfdriver.h b/Utilities/vtkfreetype/src/sfnt/sfdriver.h new file mode 100644 index 0000000..92db796 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/sfdriver.h @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* sfdriver.h */ +/* */ +/* High-level SFNT driver interface (specification). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SFDRIVER_H__ +#define __SFDRIVER_H__ + + +#include <ft2build.h> +#include FT_MODULE_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Module_Class ) sfnt_module_class; + + +FT_END_HEADER + +#endif /* __SFDRIVER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/sferrors.h b/Utilities/vtkfreetype/src/sfnt/sferrors.h new file mode 100644 index 0000000..fd2736b --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/sferrors.h @@ -0,0 +1,39 @@ +/***************************************************************************/ +/* */ +/* sferrors.h */ +/* */ +/* SFNT error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the SFNT error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __SFERRORS_H__ +#define __SFERRORS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX SFNT_Err_ +#define FT_ERR_BASE FT_Mod_Err_SFNT + +#include FT_ERRORS_H + +#endif /* __SFERRORS_H__ */ + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/sfnt.c b/Utilities/vtkfreetype/src/sfnt/sfnt.c new file mode 100644 index 0000000..90c1bee --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/sfnt.c @@ -0,0 +1,36 @@ +/***************************************************************************/ +/* */ +/* sfnt.c */ +/* */ +/* Single object library component. */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "ttload.c" +#include "ttcmap0.c" +#include "sfobjs.c" +#include "sfdriver.c" + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include "ttsbit.c" +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttpost.c" +#endif + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/sfobjs.c b/Utilities/vtkfreetype/src/sfnt/sfobjs.c new file mode 100644 index 0000000..aef3f5d --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/sfobjs.c @@ -0,0 +1,854 @@ +/***************************************************************************/ +/* */ +/* sfobjs.c */ +/* */ +/* SFNT object management (base). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "sfobjs.h" +#include "ttload.h" +#include "ttcmap0.h" +#include FT_INTERNAL_SFNT_H +#include FT_TRUETYPE_IDS_H +#include FT_TRUETYPE_TAGS_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include "sferrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_sfobjs + + + + /* convert a UTF-16 name entry to ASCII */ + static FT_String* + tt_name_entry_ascii_from_utf16( TT_NameEntry entry, + FT_Memory memory ) + { + FT_String* string; + FT_UInt len, code, n; + FT_Byte* read = (FT_Byte*)entry->string; + + + len = (FT_UInt)entry->stringLength / 2; + + if ( FT_MEM_NEW_ARRAY( string, len + 1 ) ) + return NULL; + + for ( n = 0; n < len; n++ ) + { + code = FT_NEXT_USHORT( read ); + if ( code < 32 || code > 127 ) + code = '?'; + + string[n] = (char)code; + } + + string[len] = 0; + + return string; + } + + + /* convert a UCS-4 name entry to ASCII */ + static FT_String* + tt_name_entry_ascii_from_ucs4( TT_NameEntry entry, + FT_Memory memory ) + { + FT_String* string; + FT_UInt len, code, n; + FT_Byte* read = (FT_Byte*)entry->string; + + + len = (FT_UInt)entry->stringLength / 4; + + if ( FT_MEM_NEW_ARRAY( string, len + 1 ) ) + return NULL; + + for ( n = 0; n < len; n++ ) + { + code = (FT_UInt)FT_NEXT_ULONG( read ); + if ( code < 32 || code > 127 ) + code = '?'; + + string[n] = (char)code; + } + + string[len] = 0; + + return string; + } + + + /* convert an Apple Roman or symbol name entry to ASCII */ + static FT_String* + tt_name_entry_ascii_from_other( TT_NameEntry entry, + FT_Memory memory ) + { + FT_String* string; + FT_UInt len, code, n; + FT_Byte* read = (FT_Byte*)entry->string; + + + len = (FT_UInt)entry->stringLength; + + if ( FT_MEM_NEW_ARRAY( string, len + 1 ) ) + return NULL; + + for ( n = 0; n < len; n++ ) + { + code = *read++; + if ( code < 32 || code > 127 ) + code = '?'; + + string[n] = (char)code; + } + + string[len] = 0; + + return string; + } + + + typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, + FT_Memory memory ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_get_name */ + /* */ + /* <Description> */ + /* Returns a given ENGLISH name record in ASCII. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* nameid :: The name id of the name record to return. */ + /* */ + /* <Return> */ + /* Character string. NULL if no name is present. */ + /* */ + static FT_String* + tt_face_get_name( TT_Face face, + FT_UShort nameid ) + { + FT_Memory memory = face->root.memory; + FT_String* result = NULL; + FT_UShort n; + TT_NameEntryRec* rec; + FT_Int found_apple = -1; + FT_Int found_win = -1; + FT_Int found_unicode = -1; + + FT_Bool is_english = 0; + + TT_NameEntry_ConvertFunc convert; + + + rec = face->name_table.names; + for ( n = 0; n < face->num_names; n++, rec++ ) + { + /* According to the OpenType 1.3 specification, only Microsoft or */ + /* Apple platform IDs might be used in the `name' table. The */ + /* `Unicode' platform is reserved for the `cmap' table, and the */ + /* `Iso' one is deprecated. */ + /* */ + /* However, the Apple TrueType specification doesn't say the same */ + /* thing and goes to suggest that all Unicode `name' table entries */ + /* should be coded in UTF-16 (in big-endian format I suppose). */ + /* */ + if ( rec->nameID == nameid && rec->stringLength > 0 ) + { + switch ( rec->platformID ) + { + case TT_PLATFORM_APPLE_UNICODE: + case TT_PLATFORM_ISO: + /* there is `languageID' to check there. We should use this */ + /* field only as a last solution when nothing else is */ + /* available. */ + /* */ + found_unicode = n; + break; + + case TT_PLATFORM_MACINTOSH: + if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) + found_apple = n; + + break; + + case TT_PLATFORM_MICROSOFT: + /* we only take a non-English name when there is nothing */ + /* else available in the font */ + /* */ + if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) + { + switch ( rec->encodingID ) + { + case TT_MS_ID_SYMBOL_CS: + case TT_MS_ID_UNICODE_CS: + case TT_MS_ID_UCS_4: + is_english = ( rec->languageID & 0x3FF ) == 0x009; + found_win = n; + break; + + default: + ; + } + } + break; + + default: + ; + } + } + } + + /* some fonts contain invalid Unicode or Macintosh formatted entries; */ + /* we will thus favor names encoded in Windows formats if available */ + /* (provided it is an English name) */ + /* */ + convert = NULL; + if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) + { + rec = face->name_table.names + found_win; + switch ( rec->encodingID ) + { + case TT_MS_ID_UNICODE_CS: + case TT_MS_ID_SYMBOL_CS: + convert = tt_name_entry_ascii_from_utf16; + break; + + case TT_MS_ID_UCS_4: + convert = tt_name_entry_ascii_from_ucs4; + break; + + default: + ; + } + } + else if ( found_apple >= 0 ) + { + rec = face->name_table.names + found_apple; + convert = tt_name_entry_ascii_from_other; + } + else if ( found_unicode >= 0 ) + { + rec = face->name_table.names + found_unicode; + convert = tt_name_entry_ascii_from_utf16; + } + + if ( rec && convert ) + { + if ( rec->string == NULL ) + { + FT_Error error = SFNT_Err_Ok; + FT_Stream stream = face->name_table.stream; + + FT_UNUSED( error ); + + + if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || + FT_STREAM_SEEK( rec->stringOffset ) || + FT_STREAM_READ( rec->string, rec->stringLength ) ) + { + FT_FREE( rec->string ); + rec->stringLength = 0; + result = NULL; + goto Exit; + } + } + + result = convert( rec, memory ); + } + + Exit: + return result; + } + + + static FT_Encoding + sfnt_find_encoding( int platform_id, + int encoding_id ) + { + typedef struct TEncoding + { + int platform_id; + int encoding_id; + FT_Encoding encoding; + + } TEncoding; + + static + const TEncoding tt_encodings[] = + { + { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, + + { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, + + { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN }, + + { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } + }; + + const TEncoding *cur, *limit; + + + cur = tt_encodings; + limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); + + for ( ; cur < limit; cur++ ) + { + if ( cur->platform_id == platform_id ) + { + if ( cur->encoding_id == encoding_id || + cur->encoding_id == -1 ) + return cur->encoding; + } + } + + return FT_ENCODING_NONE; + } + + + FT_LOCAL_DEF( FT_Error ) + sfnt_init_face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Library library = face->root.driver->root.library; + SFNT_Service sfnt; + SFNT_HeaderRec sfnt_header; + + /* for now, parameters are unused */ + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + sfnt = (SFNT_Service)face->sfnt; + if ( !sfnt ) + { + sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); + if ( !sfnt ) + { + error = SFNT_Err_Invalid_File_Format; + goto Exit; + } + + face->sfnt = sfnt; + face->goto_table = sfnt->goto_table; + } + + FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); + + /* check that we have a valid TrueType file */ + error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header ); + if ( error ) + goto Exit; + + face->format_tag = sfnt_header.format_tag; + face->num_tables = sfnt_header.num_tables; + + /* Load font directory */ + error = sfnt->load_directory( face, stream, &sfnt_header ); + if ( error ) + goto Exit; + + face->root.num_faces = face->ttc_header.count; + if ( face->root.num_faces < 1 ) + face->root.num_faces = 1; + + Exit: + return error; + } + + +#undef LOAD_ +#define LOAD_( x ) ( ( error = sfnt->load_##x( face, stream ) ) \ + != SFNT_Err_Ok ) + + + FT_LOCAL_DEF( FT_Error ) + sfnt_load_face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error, psnames_error; + FT_Bool has_outline; + FT_Bool is_apple_sbit; + + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + FT_UNUSED( face_index ); + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + /* Load tables */ + + /* We now support two SFNT-based bitmapped font formats. They */ + /* are recognized easily as they do not include a `glyf' */ + /* table. */ + /* */ + /* The first format comes from Apple, and uses a table named */ + /* `bhed' instead of `head' to store the font header (using */ + /* the same format). It also doesn't include horizontal and */ + /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ + /* missing). */ + /* */ + /* The other format comes from Microsoft, and is used with */ + /* WinCE/PocketPC. It looks like a standard TTF, except that */ + /* it doesn't contain outlines. */ + /* */ + + /* do we have outlines in there? */ +#ifdef FT_CONFIG_OPTION_INCREMENTAL + has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || + tt_face_lookup_table( face, TTAG_glyf ) != 0 || + tt_face_lookup_table( face, TTAG_CFF ) != 0 ); +#else + has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || + tt_face_lookup_table( face, TTAG_CFF ) != 0 ); +#endif + + is_apple_sbit = 0; + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* if this font doesn't contain outlines, we try to load */ + /* a `bhed' table */ + if ( !has_outline ) + is_apple_sbit = FT_BOOL( !LOAD_( bitmap_header ) ); + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* load the font header (`head' table) if this isn't an Apple */ + /* sbit font file */ + if ( !is_apple_sbit && LOAD_( header ) ) + goto Exit; + + /* the following tables are often not present in embedded TrueType */ + /* fonts within PDF documents, so don't check for them. */ + (void)LOAD_( max_profile ); + (void)LOAD_( charmaps ); + + /* the following tables are optional in PCL fonts -- */ + /* don't check for errors */ + (void)LOAD_( names ); + psnames_error = LOAD_( psnames ); + + /* do not load the metrics headers and tables if this is an Apple */ + /* sbit font file */ + if ( !is_apple_sbit ) + { + /* load the `hhea' and `hmtx' tables at once */ + error = sfnt->load_metrics( face, stream, 0 ); + if ( error ) + goto Exit; + + /* try to load the `vhea' and `vmtx' tables at once */ + error = sfnt->load_metrics( face, stream, 1 ); + if ( error ) + goto Exit; + + if ( LOAD_( os2 ) ) + goto Exit; + } + + /* the optional tables */ + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* embedded bitmap support. */ + if ( sfnt->load_sbits && LOAD_( sbits ) ) + { + /* return an error if this font file has no outlines */ + if ( error == SFNT_Err_Table_Missing && has_outline ) + error = SFNT_Err_Ok; + else + goto Exit; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + if ( LOAD_( hdmx ) || + LOAD_( gasp ) || + LOAD_( kerning ) || + LOAD_( pclt ) ) + goto Exit; + + face->root.family_name = tt_face_get_name( face, + TT_NAME_ID_FONT_FAMILY ); + face->root.style_name = tt_face_get_name( face, + TT_NAME_ID_FONT_SUBFAMILY ); + + /* now set up root fields */ + { + FT_Face root = &face->root; + FT_Int32 flags = 0; + FT_Memory memory; + + + memory = root->memory; + + /*********************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + if ( has_outline == TRUE ) + flags = FT_FACE_FLAG_SCALABLE; /* scalable outlines */ + + flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ + FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + if ( psnames_error == SFNT_Err_Ok && + face->postscript.FormatType != 0x00030000L ) + flags |= FT_FACE_FLAG_GLYPH_NAMES; +#endif + + /* fixed width font? */ + if ( face->postscript.isFixedPitch ) + flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* vertical information? */ + if ( face->vertical_info ) + flags |= FT_FACE_FLAG_VERTICAL; + + /* kerning available ? */ + if ( face->kern_pairs ) + flags |= FT_FACE_FLAG_KERNING; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + /* Don't bother to load the tables unless somebody asks for them. */ + /* No need to do work which will (probably) not be used. */ + if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && + tt_face_lookup_table( face, TTAG_fvar ) != 0 && + tt_face_lookup_table( face, TTAG_gvar ) != 0 ) + flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; +#endif + + root->face_flags = flags; + + /*********************************************************************/ + /* */ + /* Compute style flags. */ + /* */ + flags = 0; + if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) + { + /* we have an OS/2 table; use the `fsSelection' field */ + if ( face->os2.fsSelection & 1 ) + flags |= FT_STYLE_FLAG_ITALIC; + + if ( face->os2.fsSelection & 32 ) + flags |= FT_STYLE_FLAG_BOLD; + } + else + { + /* this is an old Mac font, use the header field */ + if ( face->header.Mac_Style & 1 ) + flags |= FT_STYLE_FLAG_BOLD; + + if ( face->header.Mac_Style & 2 ) + flags |= FT_STYLE_FLAG_ITALIC; + } + + root->style_flags = flags; + + /*********************************************************************/ + /* */ + /* Polish the charmaps. */ + /* */ + /* Try to set the charmap encoding according to the platform & */ + /* encoding ID of each charmap. */ + /* */ + + tt_face_build_cmaps( face ); /* ignore errors */ + + + /* set the encoding fields */ + { + FT_Int m; + + + for ( m = 0; m < root->num_charmaps; m++ ) + { + FT_CharMap charmap = root->charmaps[m]; + + + charmap->encoding = sfnt_find_encoding( charmap->platform_id, + charmap->encoding_id ); + +#if 0 + if ( root->charmap == NULL && + charmap->encoding == FT_ENCODING_UNICODE ) + { + /* set 'root->charmap' to the first Unicode encoding we find */ + root->charmap = charmap; + } +#endif + } + } + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + if ( face->num_sbit_strikes ) + { + FT_ULong n; + + + root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; + +#if 0 + /* XXX: I don't know criteria whether layout is horizontal */ + /* or vertical. */ + if ( has_outline.... ) + { + ... + root->face_flags |= FT_FACE_FLAG_VERTICAL; + } +#endif + root->num_fixed_sizes = (FT_Int)face->num_sbit_strikes; + + if ( FT_NEW_ARRAY( root->available_sizes, face->num_sbit_strikes ) ) + goto Exit; + + for ( n = 0 ; n < face->num_sbit_strikes ; n++ ) + { + FT_Bitmap_Size* bsize = root->available_sizes + n; + TT_SBit_Strike strike = face->sbit_strikes + n; + FT_UShort fupem = face->header.Units_Per_EM; + FT_Short height = (FT_Short)( face->horizontal.Ascender - + face->horizontal.Descender + + face->horizontal.Line_Gap ); + FT_Short avg = face->os2.xAvgCharWidth; + + + /* assume 72dpi */ + bsize->height = + (FT_Short)( ( height * strike->y_ppem + fupem/2 ) / fupem ); + bsize->width = + (FT_Short)( ( avg * strike->y_ppem + fupem/2 ) / fupem ); + bsize->size = strike->y_ppem << 6; + bsize->x_ppem = strike->x_ppem << 6; + bsize->y_ppem = strike->y_ppem << 6; + } + } + else + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + { + root->num_fixed_sizes = 0; + root->available_sizes = 0; + } + + /*********************************************************************/ + /* */ + /* Set up metrics. */ + /* */ + if ( has_outline == TRUE ) + { + /* XXX What about if outline header is missing */ + /* (e.g. sfnt wrapped bitmap)? */ + root->bbox.xMin = face->header.xMin; + root->bbox.yMin = face->header.yMin; + root->bbox.xMax = face->header.xMax; + root->bbox.yMax = face->header.yMax; + root->units_per_EM = face->header.Units_Per_EM; + + + /* XXX: Computing the ascender/descender/height is very different */ + /* from what the specification tells you. Apparently, we */ + /* must be careful because */ + /* */ + /* - not all fonts have an OS/2 table; in this case, we take */ + /* the values in the horizontal header. However, these */ + /* values very often are not reliable. */ + /* */ + /* - otherwise, the correct typographic values are in the */ + /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ + /* */ + /* However, certains fonts have these fields set to 0. */ + /* Rather, they have usWinAscent & usWinDescent correctly */ + /* set (but with different values). */ + /* */ + /* As an example, Arial Narrow is implemented through four */ + /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ + /* */ + /* Strangely, all fonts have the same values in their */ + /* sTypoXXX fields, except ARIALNB which sets them to 0. */ + /* */ + /* On the other hand, they all have different */ + /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ + /* table cannot be used to compute the text height reliably! */ + /* */ + + /* The ascender/descender/height are computed from the OS/2 table */ + /* when found. Otherwise, they're taken from the horizontal */ + /* header. */ + /* */ + + root->ascender = face->horizontal.Ascender; + root->descender = face->horizontal.Descender; + + root->height = (FT_Short)( root->ascender - root->descender + + face->horizontal.Line_Gap ); + +#if 0 + /* if the line_gap is 0, we add an extra 15% to the text height -- */ + /* this computation is based on various versions of Times New Roman */ + if ( face->horizontal.Line_Gap == 0 ) + root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 ); +#endif + +#if 0 + + /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */ + /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */ + if ( face->os2.version != 0xFFFFU && root->ascender ) + { + FT_Int height; + + + root->ascender = face->os2.sTypoAscender; + root->descender = -face->os2.sTypoDescender; + + height = root->ascender + root->descender + face->os2.sTypoLineGap; + if ( height > root->height ) + root->height = height; + } + +#endif /* 0 */ + + root->max_advance_width = face->horizontal.advance_Width_Max; + + root->max_advance_height = (FT_Short)( face->vertical_info + ? face->vertical.advance_Height_Max + : root->height ); + + root->underline_position = face->postscript.underlinePosition; + root->underline_thickness = face->postscript.underlineThickness; + + /* root->max_points -- already set up */ + /* root->max_contours -- already set up */ + } + } + + Exit: + return error; + } + + +#undef LOAD_ + + + FT_LOCAL_DEF( void ) + sfnt_done_face( TT_Face face ) + { + FT_Memory memory = face->root.memory; + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + + if ( sfnt ) + { + /* destroy the postscript names table if it is loaded */ + if ( sfnt->free_psnames ) + sfnt->free_psnames( face ); + + /* destroy the embedded bitmaps table if it is loaded */ + if ( sfnt->free_sbits ) + sfnt->free_sbits( face ); + } + + /* freeing the kerning table */ + FT_FREE( face->kern_pairs ); + face->num_kern_pairs = 0; + + /* freeing the collection table */ + FT_FREE( face->ttc_header.offsets ); + face->ttc_header.count = 0; + + /* freeing table directory */ + FT_FREE( face->dir_tables ); + face->num_tables = 0; + + { + FT_Stream stream = FT_FACE_STREAM( face ); + + + /* simply release the 'cmap' table frame */ + FT_FRAME_RELEASE( face->cmap_table ); + face->cmap_size = 0; + } + + /* freeing the horizontal metrics */ + FT_FREE( face->horizontal.long_metrics ); + FT_FREE( face->horizontal.short_metrics ); + + /* freeing the vertical ones, if any */ + if ( face->vertical_info ) + { + FT_FREE( face->vertical.long_metrics ); + FT_FREE( face->vertical.short_metrics ); + face->vertical_info = 0; + } + + /* freeing the gasp table */ + FT_FREE( face->gasp.gaspRanges ); + face->gasp.numRanges = 0; + + /* freeing the name table */ + sfnt->free_names( face ); + + /* freeing the hdmx table */ + sfnt->free_hdmx( face ); + + /* freeing family and style name */ + FT_FREE( face->root.family_name ); + FT_FREE( face->root.style_name ); + + /* freeing sbit size table */ + FT_FREE( face->root.available_sizes ); + face->root.num_fixed_sizes = 0; + + FT_FREE( face->postscript_name ); + + face->sfnt = 0; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/sfobjs.h b/Utilities/vtkfreetype/src/sfnt/sfobjs.h new file mode 100644 index 0000000..6241c93 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/sfobjs.h @@ -0,0 +1,54 @@ +/***************************************************************************/ +/* */ +/* sfobjs.h */ +/* */ +/* SFNT object management (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __SFOBJS_H__ +#define __SFOBJS_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_SFNT_H +#include FT_INTERNAL_OBJECTS_H + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + sfnt_init_face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + FT_LOCAL( FT_Error ) + sfnt_load_face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + FT_LOCAL( void ) + sfnt_done_face( TT_Face face ); + + +FT_END_HEADER + +#endif /* __SFDRIVER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttcmap0.c b/Utilities/vtkfreetype/src/sfnt/ttcmap0.c new file mode 100644 index 0000000..dd1c76a --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttcmap0.c @@ -0,0 +1,1991 @@ +/***************************************************************************/ +/* */ +/* ttcmap0.c */ +/* */ +/* TrueType new character mapping table (cmap) support (body). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_STREAM_H +#include "ttload.h" +#include "ttcmap0.h" + +#include "sferrors.h" + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttcmap + + +#define TT_PEEK_SHORT FT_PEEK_SHORT +#define TT_PEEK_USHORT FT_PEEK_USHORT +#define TT_PEEK_LONG FT_PEEK_LONG +#define TT_PEEK_ULONG FT_PEEK_ULONG + +#define TT_NEXT_SHORT FT_NEXT_SHORT +#define TT_NEXT_USHORT FT_NEXT_USHORT +#define TT_NEXT_LONG FT_NEXT_LONG +#define TT_NEXT_ULONG FT_NEXT_ULONG + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap_init( TT_CMap cmap, + FT_Byte* table ) + { + cmap->data = table; + return 0; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FORMAT 0 *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* TABLE OVERVIEW */ + /* -------------- */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* format 0 USHORT must be 0 */ + /* length 2 USHORT table length in bytes */ + /* language 4 USHORT Mac language code */ + /* glyph_ids 6 BYTE[256] array of glyph indices */ + /* 262 */ + /* */ + +#ifdef TT_CONFIG_CMAP_FORMAT_0 + + FT_CALLBACK_DEF( void ) + tt_cmap0_validate( FT_Byte* table, + FT_Validator valid ) + { + FT_Byte* p = table + 2; + FT_UInt length = TT_NEXT_USHORT( p ); + + + if ( table + length > valid->limit || length < 262 ) + FT_INVALID_TOO_SHORT; + + /* check glyph indices whenever necessary */ + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + FT_UInt n, idx; + + + p = table + 6; + for ( n = 0; n < 256; n++ ) + { + idx = *p++; + if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) + FT_INVALID_GLYPH_ID; + } + } + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap0_char_index( TT_CMap cmap, + FT_UInt32 char_code ) + { + FT_Byte* table = cmap->data; + + + return char_code < 256 ? table[6 + char_code] : 0; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap0_char_next( TT_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_Byte* table = cmap->data; + FT_UInt32 charcode = *pchar_code; + FT_UInt32 result = 0; + FT_UInt gindex = 0; + + + table += 6; /* go to glyph ids */ + while ( ++charcode < 256 ) + { + gindex = table[charcode]; + if ( gindex != 0 ) + { + result = charcode; + break; + } + } + + *pchar_code = result; + return gindex; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap0_get_info( TT_CMap cmap, + TT_CMapInfo *cmap_info ) + { + FT_Byte* p = cmap->data + 4; + + + cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const TT_CMap_ClassRec tt_cmap0_class_rec = + { + { + sizeof( TT_CMapRec ), + + (FT_CMap_InitFunc) tt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)tt_cmap0_char_index, + (FT_CMap_CharNextFunc) tt_cmap0_char_next + }, + 0, + (TT_CMap_ValidateFunc) tt_cmap0_validate, + (TT_CMap_Info_GetFunc) tt_cmap0_get_info + }; + +#endif /* TT_CONFIG_CMAP_FORMAT_0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FORMAT 2 *****/ + /***** *****/ + /***** This is used for certain CJK encodings that encode text in a *****/ + /***** mixed 8/16 bits encoding along the following lines: *****/ + /***** *****/ + /***** * Certain byte values correspond to an 8-bit character code *****/ + /***** (typically in the range 0..127 for ASCII compatibility). *****/ + /***** *****/ + /***** * Certain byte values signal the first byte of a 2-byte *****/ + /***** character code (but these values are also valid as the *****/ + /***** second byte of a 2-byte character). *****/ + /***** *****/ + /***** The following charmap lookup and iteration functions all *****/ + /***** assume that the value "charcode" correspond to following: *****/ + /***** *****/ + /***** - For one byte characters, "charcode" is simply the *****/ + /***** character code. *****/ + /***** *****/ + /***** - For two byte characters, "charcode" is the 2-byte *****/ + /***** character code in big endian format. More exactly: *****/ + /***** *****/ + /***** (charcode >> 8) is the first byte value *****/ + /***** (charcode & 0xFF) is the second byte value *****/ + /***** *****/ + /***** Note that not all values of "charcode" are valid according *****/ + /***** to these rules, and the function moderately check the *****/ + /***** arguments. *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* TABLE OVERVIEW */ + /* -------------- */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* format 0 USHORT must be 2 */ + /* length 2 USHORT table length in bytes */ + /* language 4 USHORT Mac language code */ + /* keys 6 USHORT[256] sub-header keys */ + /* subs 518 SUBHEAD[NSUBS] sub-headers array */ + /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */ + /* */ + /* The `keys' table is used to map charcode high-bytes to sub-headers. */ + /* The value of `NSUBS' is the number of sub-headers defined in the */ + /* table and is computed by finding the maximum of the `keys' table. */ + /* */ + /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ + /* table, i.e., it is the corresponding sub-header index multiplied */ + /* by 8. */ + /* */ + /* Each sub-header has the following format: */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* first 0 USHORT first valid low-byte */ + /* count 2 USHORT number of valid low-bytes */ + /* delta 4 SHORT see below */ + /* offset 6 USHORT see below */ + /* */ + /* A sub-header defines, for each high-byte, the range of valid */ + /* low-bytes within the charmap. Note that the range defined by `first' */ + /* and `count' must be completely included in the interval [0..255] */ + /* according to the specification. */ + /* */ + /* If a character code is contained within a given sub-header, then */ + /* mapping it to a glyph index is done as follows: */ + /* */ + /* * The value of `offset' is read. This is a _byte_ distance from the */ + /* location of the `offset' field itself into a slice of the */ + /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */ + /* */ + /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ + /* no glyph for the charcode. Otherwise, the value of `delta' is */ + /* added to it (modulo 65536) to form a new glyph index. */ + /* */ + /* It is up to the validation routine to check that all offsets fall */ + /* within the glyph ids table (and not within the `subs' table itself or */ + /* outside of the CMap). */ + /* */ + +#ifdef TT_CONFIG_CMAP_FORMAT_2 + + FT_CALLBACK_DEF( void ) + tt_cmap2_validate( FT_Byte* table, + FT_Validator valid ) + { + FT_Byte* p = table + 2; /* skip format */ + FT_UInt length = TT_PEEK_USHORT( p ); + FT_UInt n, max_subs; + FT_Byte* keys; /* keys table */ + FT_Byte* subs; /* sub-headers */ + FT_Byte* glyph_ids; /* glyph id array */ + + + if ( table + length > valid->limit || length < 6 + 512 ) + FT_INVALID_TOO_SHORT; + + keys = table + 6; + + /* parse keys to compute sub-headers count */ + p = keys; + max_subs = 0; + for ( n = 0; n < 256; n++ ) + { + FT_UInt idx = TT_NEXT_USHORT( p ); + + + /* value must be multiple of 8 */ + if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) + FT_INVALID_DATA; + + idx >>= 3; + + if ( idx > max_subs ) + max_subs = idx; + } + + FT_ASSERT( p == table + 518 ); + + subs = p; + glyph_ids = subs + (max_subs + 1) * 8; + if ( glyph_ids > valid->limit ) + FT_INVALID_TOO_SHORT; + + /* parse sub-headers */ + for ( n = 0; n <= max_subs; n++ ) + { + FT_UInt first_code, code_count, offset; + FT_Int delta; + FT_Byte* ids; + + + first_code = TT_NEXT_USHORT( p ); + code_count = TT_NEXT_USHORT( p ); + delta = TT_NEXT_SHORT( p ); + offset = TT_NEXT_USHORT( p ); + + /* check range within 0..255 */ + if ( valid->level >= FT_VALIDATE_PARANOID ) + { + if ( first_code >= 256 || first_code + code_count > 256 ) + FT_INVALID_DATA; + } + + /* check offset */ + if ( offset != 0 ) + { + ids = p - 2 + offset; + if ( ids < glyph_ids || ids + code_count*2 > table + length ) + FT_INVALID_OFFSET; + + /* check glyph ids */ + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + FT_Byte* limit = p + code_count * 2; + FT_UInt idx; + + + for ( ; p < limit; ) + { + idx = TT_NEXT_USHORT( p ); + if ( idx != 0 ) + { + idx = ( idx + delta ) & 0xFFFFU; + if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) + FT_INVALID_GLYPH_ID; + } + } + } + } + } + } + + + /* return sub header corresponding to a given character code */ + /* NULL on invalid charcode */ + static FT_Byte* + tt_cmap2_get_subheader( FT_Byte* table, + FT_UInt32 char_code ) + { + FT_Byte* result = NULL; + + + if ( char_code < 0x10000UL ) + { + FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); + FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); + FT_Byte* p = table + 6; /* keys table */ + FT_Byte* subs = table + 518; /* subheaders table */ + FT_Byte* sub; + + + if ( char_hi == 0 ) + { + /* an 8-bit character code -- we use subHeader 0 in this case */ + /* to test whether the character code is in the charmap */ + /* */ + sub = subs; /* jump to first sub-header */ + + /* check that the sub-header for this byte is 0, which */ + /* indicates that it's really a valid one-byte value */ + /* Otherwise, return 0 */ + /* */ + p += char_lo * 2; + if ( TT_PEEK_USHORT( p ) != 0 ) + goto Exit; + } + else + { + /* a 16-bit character code */ + + /* jump to key entry */ + p += char_hi * 2; + /* jump to sub-header */ + sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) ); + + /* check that the high byte isn't a valid one-byte value */ + if ( sub == subs ) + goto Exit; + } + result = sub; + } + Exit: + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap2_char_index( TT_CMap cmap, + FT_UInt32 char_code ) + { + FT_Byte* table = cmap->data; + FT_UInt result = 0; + FT_Byte* subheader; + + + subheader = tt_cmap2_get_subheader( table, char_code ); + if ( subheader ) + { + FT_Byte* p = subheader; + FT_UInt idx = (FT_UInt)(char_code & 0xFF); + FT_UInt start, count; + FT_Int delta; + FT_UInt offset; + + + start = TT_NEXT_USHORT( p ); + count = TT_NEXT_USHORT( p ); + delta = TT_NEXT_SHORT ( p ); + offset = TT_PEEK_USHORT( p ); + + idx -= start; + if ( idx < count && offset != 0 ) + { + p += offset + 2 * idx; + idx = TT_PEEK_USHORT( p ); + + if ( idx != 0 ) + result = (FT_UInt)( idx + delta ) & 0xFFFFU; + } + } + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap2_char_next( TT_CMap cmap, + FT_UInt32 *pcharcode ) + { + FT_Byte* table = cmap->data; + FT_UInt gindex = 0; + FT_UInt32 result = 0; + FT_UInt32 charcode = *pcharcode + 1; + FT_Byte* subheader; + + + while ( charcode < 0x10000UL ) + { + subheader = tt_cmap2_get_subheader( table, charcode ); + if ( subheader ) + { + FT_Byte* p = subheader; + FT_UInt start = TT_NEXT_USHORT( p ); + FT_UInt count = TT_NEXT_USHORT( p ); + FT_Int delta = TT_NEXT_SHORT ( p ); + FT_UInt offset = TT_PEEK_USHORT( p ); + FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); + FT_UInt pos, idx; + + + if ( offset == 0 ) + goto Next_SubHeader; + + if ( char_lo < start ) + { + char_lo = start; + pos = 0; + } + else + pos = (FT_UInt)( char_lo - start ); + + p += offset + pos * 2; + charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo; + + for ( ; pos < count; pos++, charcode++ ) + { + idx = TT_NEXT_USHORT( p ); + + if ( idx != 0 ) + { + gindex = ( idx + delta ) & 0xFFFFU; + if ( gindex != 0 ) + { + result = charcode; + goto Exit; + } + } + } + } + + /* jump to next sub-header, i.e. higher byte value */ + Next_SubHeader: + charcode = FT_PAD_FLOOR( charcode, 256 ) + 256; + } + + Exit: + *pcharcode = result; + + return gindex; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap2_get_info( TT_CMap cmap, + TT_CMapInfo *cmap_info ) + { + FT_Byte* p = cmap->data + 4; + + + cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const TT_CMap_ClassRec tt_cmap2_class_rec = + { + { + sizeof( TT_CMapRec ), + + (FT_CMap_InitFunc) tt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)tt_cmap2_char_index, + (FT_CMap_CharNextFunc) tt_cmap2_char_next + }, + 2, + (TT_CMap_ValidateFunc) tt_cmap2_validate, + (TT_CMap_Info_GetFunc) tt_cmap2_get_info + }; + +#endif /* TT_CONFIG_CMAP_FORMAT_2 */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FORMAT 4 *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* TABLE OVERVIEW */ + /* -------------- */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* format 0 USHORT must be 4 */ + /* length 2 USHORT table length */ + /* in bytes */ + /* language 4 USHORT Mac language code */ + /* */ + /* segCountX2 6 USHORT 2*NUM_SEGS */ + /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ + /* entrySelector 10 USHORT LOG_SEGS */ + /* rangeShift 12 USHORT segCountX2 - */ + /* searchRange */ + /* */ + /* endCount 14 USHORT[NUM_SEGS] end charcode for */ + /* each segment; last */ + /* is 0xFFFF */ + /* */ + /* pad 14+NUM_SEGS*2 USHORT padding */ + /* */ + /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ + /* each segment */ + /* */ + /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ + /* segment */ + /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ + /* each segment; can be */ + /* zero */ + /* */ + /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */ + /* ranges */ + /* */ + /* Character codes are modelled by a series of ordered (increasing) */ + /* intervals called segments. Each segment has start and end codes, */ + /* provided by the `startCount' and `endCount' arrays. Segments must */ + /* not be overlapping and the last segment should always contain the */ + /* `0xFFFF' endCount. */ + /* */ + /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ + /* ignored (they are traces of over-engineering in the TrueType */ + /* specification). */ + /* */ + /* Each segment also has a signed `delta', as well as an optional offset */ + /* within the `glyphIds' table. */ + /* */ + /* If a segment's idOffset is 0, the glyph index corresponding to any */ + /* charcode within the segment is obtained by adding the value of */ + /* `idDelta' directly to the charcode, modulo 65536. */ + /* */ + /* Otherwise, a glyph index is taken from the glyph ids sub-array for */ + /* the segment, and the value of `idDelta' is added to it. */ + /* */ + /* */ + /* Finally, note that certain fonts contain invalid charmaps that */ + /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */ + /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */ + /* we need special code to deal with them correctly... */ + /* */ + +#ifdef TT_CONFIG_CMAP_FORMAT_4 + + FT_CALLBACK_DEF( void ) + tt_cmap4_validate( FT_Byte* table, + FT_Validator valid ) + { + FT_Byte* p = table + 2; /* skip format */ + FT_UInt length = TT_NEXT_USHORT( p ); + FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; + FT_UInt num_segs; + + + /* in certain fonts, the `length' field is invalid and goes */ + /* out of bound. We try to correct this here... */ + if ( length < 16 ) + FT_INVALID_TOO_SHORT; + + if ( table + length > valid->limit ) + { + if ( valid->level >= FT_VALIDATE_TIGHT ) + FT_INVALID_TOO_SHORT; + + length = (FT_UInt)( valid->limit - table ); + } + + p = table + 6; + num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ + + if ( valid->level >= FT_VALIDATE_PARANOID ) + { + /* check that we have an even value here */ + if ( num_segs & 1 ) + FT_INVALID_DATA; + } + + num_segs /= 2; + + /* check the search parameters - even though we never use them */ + /* */ + if ( valid->level >= FT_VALIDATE_PARANOID ) + { + /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */ + FT_UInt search_range = TT_NEXT_USHORT( p ); + FT_UInt entry_selector = TT_NEXT_USHORT( p ); + FT_UInt range_shift = TT_NEXT_USHORT( p ); + + + if ( ( search_range | range_shift ) & 1 ) /* must be even values */ + FT_INVALID_DATA; + + search_range /= 2; + range_shift /= 2; + + /* `search range' is the greatest power of 2 that is <= num_segs */ + + if ( search_range > num_segs || + search_range * 2 < num_segs || + search_range + range_shift != num_segs || + search_range != ( 1U << entry_selector ) ) + FT_INVALID_DATA; + } + + ends = table + 14; + starts = table + 16 + num_segs * 2; + deltas = starts + num_segs * 2; + offsets = deltas + num_segs * 2; + glyph_ids = offsets + num_segs * 2; + + if ( glyph_ids > table + length ) + FT_INVALID_TOO_SHORT; + + /* check last segment, its end count must be FFFF */ + if ( valid->level >= FT_VALIDATE_PARANOID ) + { + p = ends + ( num_segs - 1 ) * 2; + if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) + FT_INVALID_DATA; + } + + /* check that segments are sorted in increasing order and do not */ + /* overlap; check also the offsets */ + { + FT_UInt start, end, last = 0, offset, n; + FT_Int delta; + + + for ( n = 0; n < num_segs; n++ ) + { + p = starts + n * 2; + start = TT_PEEK_USHORT( p ); + p = ends + n * 2; + end = TT_PEEK_USHORT( p ); + p = deltas + n * 2; + delta = TT_PEEK_SHORT( p ); + p = offsets + n * 2; + offset = TT_PEEK_USHORT( p ); + + if ( start > end ) + FT_INVALID_DATA; + + /* this test should be performed at default validation level; */ + /* unfortunately, some popular Asian fonts present overlapping */ + /* ranges in their charmaps */ + /* */ + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + if ( n > 0 && start <= last ) + FT_INVALID_DATA; + } + + if ( offset && offset != 0xFFFFU ) + { + p += offset; /* start of glyph id array */ + + /* check that we point within the glyph ids table only */ + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + if ( p < glyph_ids || + p + ( end - start + 1 ) * 2 > table + length ) + FT_INVALID_DATA; + } + else + { + if ( p < glyph_ids || + p + ( end - start + 1 ) * 2 > valid->limit ) + FT_INVALID_DATA; + } + + /* check glyph indices within the segment range */ + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + FT_UInt i, idx; + + + for ( i = start; i < end; i++ ) + { + idx = FT_NEXT_USHORT( p ); + if ( idx != 0 ) + { + idx = (FT_UInt)( idx + delta ) & 0xFFFFU; + + if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) + FT_INVALID_GLYPH_ID; + } + } + } + } + else if ( offset == 0xFFFFU ) + { + /* Some fonts (erroneously?) use a range offset of 0xFFFF */ + /* to mean missing glyph in cmap table */ + /* */ + if ( valid->level >= FT_VALIDATE_PARANOID || + n != num_segs - 1 || + !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) ) + FT_INVALID_DATA; + } + + last = end; + } + } + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap4_char_index( TT_CMap cmap, + FT_UInt32 char_code ) + { + FT_Byte* table = cmap->data; + FT_UInt result = 0; + + + if ( char_code < 0x10000UL ) + { + FT_UInt idx, num_segs2; + FT_Int delta; + FT_UInt code = (FT_UInt)char_code; + FT_Byte* p; + + + p = table + 6; + num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* be paranoid! */ + +#if 1 + /* Some fonts have more than 170 segments in their charmaps! */ + /* We changed this function to use a more efficient binary */ + /* search for improving performance */ + { + FT_UInt min = 0; + FT_UInt max = num_segs2 >> 1; + FT_UInt mid, start, end, offset; + + + while ( min < max ) + { + mid = ( min + max ) >> 1; + p = table + 14 + mid * 2; + end = TT_NEXT_USHORT( p ); + p += num_segs2; + start = TT_PEEK_USHORT( p); + + if ( code < start ) + max = mid; + else if ( code > end ) + min = mid + 1; + else + { + /* we found the segment */ + idx = code; + + p += num_segs2; + delta = TT_PEEK_SHORT( p ); + + p += num_segs2; + offset = TT_PEEK_USHORT( p ); + + if ( offset == 0xFFFFU ) + goto Exit; + + if ( offset != 0 ) + { + p += offset + 2 * ( idx - start ); + idx = TT_PEEK_USHORT( p ); + } + + if ( idx != 0 ) + result = (FT_UInt)( idx + delta ) & 0xFFFFU; + + goto Exit; + } + } + } + +#else /* 0 - old code */ + + { + FT_UInt n; + FT_Byte* q; + + + p = table + 14; /* ends table */ + q = table + 16 + num_segs2; /* starts table */ + + + for ( n = 0; n < num_segs2; n += 2 ) + { + FT_UInt end = TT_NEXT_USHORT( p ); + FT_UInt start = TT_NEXT_USHORT( q ); + FT_UInt offset; + + + if ( code < start ) + break; + + if ( code <= end ) + { + idx = code; + + p = q + num_segs2 - 2; + delta = TT_PEEK_SHORT( p ); + p += num_segs2; + offset = TT_PEEK_USHORT( p ); + + if ( offset == 0xFFFFU ) + goto Exit; + + if ( offset != 0 ) + { + p += offset + 2 * ( idx - start ); + idx = TT_PEEK_USHORT( p ); + } + + if ( idx != 0 ) + result = (FT_UInt)( idx + delta ) & 0xFFFFU; + } + } + } + +#endif /* 0 */ + + } + + Exit: + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap4_char_next( TT_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_Byte* table = cmap->data; + FT_UInt32 result = 0; + FT_UInt gindex = 0; + FT_UInt32 char_code = *pchar_code; + FT_Byte* p; + FT_UInt code, num_segs2; + + + if ( char_code >= 0xFFFFUL ) + goto Exit; + + code = (FT_UInt)char_code + 1; + p = table + 6; + num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT(p), 2 ); /* ensure even-ness */ + +#if 1 + + for (;;) + { + /* Some fonts have more than 170 segments in their charmaps! */ + /* We changed this function to use a more efficient binary */ + /* search */ + FT_UInt offset; + FT_Int delta; + FT_UInt min = 0; + FT_UInt max = num_segs2 >> 1; + FT_UInt mid, start, end; + FT_UInt hi; + + + /* we begin by finding the segment which end is + closer to our code point */ + hi = max + 1; + while ( min < max ) + { + mid = ( min + max ) >> 1; + p = table + 14 + mid * 2; + end = TT_PEEK_USHORT( p ); + + if ( end < code ) + min = mid + 1; + else + { + hi = mid; + max = mid; + } + } + + if ( hi > max ) + { + /* the point is behind the last segment; + we will exit right now */ + goto Exit; + } + + p = table + 14 + hi * 2; + end = TT_PEEK_USHORT( p ); + + p += 2 + num_segs2; + start = TT_PEEK_USHORT( p ); + + if ( code < start ) + code = start; + + p += num_segs2; + delta = TT_PEEK_USHORT( p ); + + p += num_segs2; + offset = TT_PEEK_USHORT( p ); + + if ( offset != 0 && offset != 0xFFFFU ) + { + /* parse the glyph ids array for non-zero index */ + p += offset + ( code - start ) * 2; + while ( code <= end ) + { + gindex = TT_NEXT_USHORT( p ); + if ( gindex != 0 ) + { + gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; + if ( gindex != 0 ) + { + result = code; + goto Exit; + } + } + code++; + } + } + else if ( offset == 0xFFFFU ) + { + /* an offset of 0xFFFF means an empty glyph in certain fonts! */ + code = end + 1; + } + else /* offset == 0 */ + { + gindex = (FT_UInt)( code + delta ) & 0xFFFFU; + if ( gindex != 0 ) + { + result = code; + goto Exit; + } + code++; + } + } + +#else /* old code -- kept for reference */ + + for ( ;; ) + { + FT_UInt offset, n; + FT_Int delta; + FT_Byte* q; + + + p = table + 14; /* ends table */ + q = table + 16 + num_segs2; /* starts table */ + + for ( n = 0; n < num_segs2; n += 2 ) + { + FT_UInt end = TT_NEXT_USHORT( p ); + FT_UInt start = TT_NEXT_USHORT( q ); + + + if ( code < start ) + code = start; + + if ( code <= end ) + { + p = q + num_segs2 - 2; + delta = TT_PEEK_SHORT( p ); + p += num_segs2; + offset = TT_PEEK_USHORT( p ); + + if ( offset != 0 && offset != 0xFFFFU ) + { + /* parse the glyph ids array for non-0 index */ + p += offset + ( code - start ) * 2; + while ( code <= end ) + { + gindex = TT_NEXT_USHORT( p ); + if ( gindex != 0 ) + { + gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; + if ( gindex != 0 ) + break; + } + code++; + } + } + else if ( offset == 0xFFFFU ) + { + /* an offset of 0xFFFF means an empty glyph in certain fonts! */ + code = end; + break; + } + else + gindex = (FT_UInt)( code + delta ) & 0xFFFFU; + + if ( gindex == 0 ) + break; + + result = code; + goto Exit; + } + } + /* loop to next trial charcode */ + if ( code >= 0xFFFFU ) + break; + + code++; + } + +#endif /* !1 */ + + Exit: + *pchar_code = result; + return gindex; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap4_get_info( TT_CMap cmap, + TT_CMapInfo *cmap_info ) + { + FT_Byte* p = cmap->data + 4; + + + cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const TT_CMap_ClassRec tt_cmap4_class_rec = + { + { + sizeof ( TT_CMapRec ), + + (FT_CMap_InitFunc) tt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)tt_cmap4_char_index, + (FT_CMap_CharNextFunc) tt_cmap4_char_next + }, + 4, + (TT_CMap_ValidateFunc) tt_cmap4_validate, + (TT_CMap_Info_GetFunc) tt_cmap4_get_info + }; + +#endif /* TT_CONFIG_CMAP_FORMAT_4 */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FORMAT 6 *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* TABLE OVERVIEW */ + /* -------------- */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* format 0 USHORT must be 4 */ + /* length 2 USHORT table length in bytes */ + /* language 4 USHORT Mac language code */ + /* */ + /* first 6 USHORT first segment code */ + /* count 8 USHORT segment size in chars */ + /* glyphIds 10 USHORT[count] glyph ids */ + /* */ + /* A very simplified segment mapping. */ + /* */ + +#ifdef TT_CONFIG_CMAP_FORMAT_6 + + FT_CALLBACK_DEF( void ) + tt_cmap6_validate( FT_Byte* table, + FT_Validator valid ) + { + FT_Byte* p; + FT_UInt length, count; + + + if ( table + 10 > valid->limit ) + FT_INVALID_TOO_SHORT; + + p = table + 2; + length = TT_NEXT_USHORT( p ); + + p = table + 8; /* skip language and start index */ + count = TT_NEXT_USHORT( p ); + + if ( table + length > valid->limit || length < 10 + count * 2 ) + FT_INVALID_TOO_SHORT; + + /* check glyph indices */ + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + FT_UInt gindex; + + + for ( ; count > 0; count-- ) + { + gindex = TT_NEXT_USHORT( p ); + if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) + FT_INVALID_GLYPH_ID; + } + } + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap6_char_index( TT_CMap cmap, + FT_UInt32 char_code ) + { + FT_Byte* table = cmap->data; + FT_UInt result = 0; + FT_Byte* p = table + 6; + FT_UInt start = TT_NEXT_USHORT( p ); + FT_UInt count = TT_NEXT_USHORT( p ); + FT_UInt idx = (FT_UInt)( char_code - start ); + + + if ( idx < count ) + { + p += 2 * idx; + result = TT_PEEK_USHORT( p ); + } + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap6_char_next( TT_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_Byte* table = cmap->data; + FT_UInt32 result = 0; + FT_UInt32 char_code = *pchar_code + 1; + FT_UInt gindex = 0; + + FT_Byte* p = table + 6; + FT_UInt start = TT_NEXT_USHORT( p ); + FT_UInt count = TT_NEXT_USHORT( p ); + FT_UInt idx; + + + if ( char_code >= 0x10000UL ) + goto Exit; + + if ( char_code < start ) + char_code = start; + + idx = (FT_UInt)( char_code - start ); + p += 2 * idx; + + for ( ; idx < count; idx++ ) + { + gindex = TT_NEXT_USHORT( p ); + if ( gindex != 0 ) + { + result = char_code; + break; + } + char_code++; + } + + Exit: + *pchar_code = result; + return gindex; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap6_get_info( TT_CMap cmap, + TT_CMapInfo *cmap_info ) + { + FT_Byte* p = cmap->data + 4; + + + cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); + + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const TT_CMap_ClassRec tt_cmap6_class_rec = + { + { + sizeof ( TT_CMapRec ), + + (FT_CMap_InitFunc) tt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)tt_cmap6_char_index, + (FT_CMap_CharNextFunc) tt_cmap6_char_next + }, + 6, + (TT_CMap_ValidateFunc) tt_cmap6_validate, + (TT_CMap_Info_GetFunc) tt_cmap6_get_info + }; + +#endif /* TT_CONFIG_CMAP_FORMAT_6 */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FORMAT 8 *****/ + /***** *****/ + /***** It's hard to completely understand what the OpenType spec *****/ + /***** says about this format, but here is my conclusion. *****/ + /***** *****/ + /***** The purpose of this format is to easily map UTF-16 text to *****/ + /***** glyph indices. Basically, the `char_code' must be in one of *****/ + /***** the following formats: *****/ + /***** *****/ + /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ + /***** Area (i.e. U+D800-U+DFFF). *****/ + /***** *****/ + /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ + /***** `char_code = (char_hi << 16) | char_lo', then both *****/ + /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ + /***** Area. *****/ + /***** *****/ + /***** The 'is32' table embedded in the charmap indicates whether a *****/ + /***** given 16-bit value is in the surrogates area or not. *****/ + /***** *****/ + /***** So, for any given `char_code', we can assert the following: *****/ + /***** *****/ + /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ + /***** *****/ + /***** If `char_hi != 0' then we must have both *****/ + /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* TABLE OVERVIEW */ + /* -------------- */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* format 0 USHORT must be 8 */ + /* reseved 2 USHORT reserved */ + /* length 4 ULONG length in bytes */ + /* language 8 ULONG Mac language code */ + /* is32 12 BYTE[8192] 32-bitness bitmap */ + /* count 8204 ULONG number of groups */ + /* */ + /* This header is followed by 'count' groups of the following format: */ + /* */ + /* start 0 ULONG first charcode */ + /* end 4 ULONG last charcode */ + /* startId 8 ULONG start glyph id for the group */ + /* */ + +#ifdef TT_CONFIG_CMAP_FORMAT_8 + + FT_CALLBACK_DEF( void ) + tt_cmap8_validate( FT_Byte* table, + FT_Validator valid ) + { + FT_Byte* p = table + 4; + FT_Byte* is32; + FT_UInt32 length; + FT_UInt32 num_groups; + + + if ( table + 16 + 8192 > valid->limit ) + FT_INVALID_TOO_SHORT; + + length = TT_NEXT_ULONG( p ); + if ( table + length > valid->limit || length < 8208 ) + FT_INVALID_TOO_SHORT; + + is32 = table + 12; + p = is32 + 8192; /* skip `is32' array */ + num_groups = TT_NEXT_ULONG( p ); + + if ( p + num_groups * 12 > valid->limit ) + FT_INVALID_TOO_SHORT; + + /* check groups, they must be in increasing order */ + { + FT_UInt32 n, start, end, start_id, count, last = 0; + + + for ( n = 0; n < num_groups; n++ ) + { + FT_UInt hi, lo; + + + start = TT_NEXT_ULONG( p ); + end = TT_NEXT_ULONG( p ); + start_id = TT_NEXT_ULONG( p ); + + if ( start > end ) + FT_INVALID_DATA; + + if ( n > 0 && start <= last ) + FT_INVALID_DATA; + + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) + FT_INVALID_GLYPH_ID; + + count = (FT_UInt32)( end - start + 1 ); + + if ( start & ~0xFFFFU ) + { + /* start_hi != 0; check that is32[i] is 1 for each i in */ + /* the `hi' and `lo' of the range [start..end] */ + for ( ; count > 0; count--, start++ ) + { + hi = (FT_UInt)( start >> 16 ); + lo = (FT_UInt)( start & 0xFFFFU ); + + if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) + FT_INVALID_DATA; + + if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) + FT_INVALID_DATA; + } + } + else + { + /* start_hi == 0; check that is32[i] is 0 for each i in */ + /* the range [start..end] */ + + /* end_hi cannot be != 0! */ + if ( end & ~0xFFFFU ) + FT_INVALID_DATA; + + for ( ; count > 0; count--, start++ ) + { + lo = (FT_UInt)( start & 0xFFFFU ); + + if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) + FT_INVALID_DATA; + } + } + } + + last = end; + } + } + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap8_char_index( TT_CMap cmap, + FT_UInt32 char_code ) + { + FT_Byte* table = cmap->data; + FT_UInt result = 0; + FT_Byte* p = table + 8204; + FT_UInt32 num_groups = TT_NEXT_ULONG( p ); + FT_UInt32 start, end, start_id; + + + for ( ; num_groups > 0; num_groups-- ) + { + start = TT_NEXT_ULONG( p ); + end = TT_NEXT_ULONG( p ); + start_id = TT_NEXT_ULONG( p ); + + if ( char_code < start ) + break; + + if ( char_code <= end ) + { + result = (FT_UInt)( start_id + char_code - start ); + break; + } + } + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap8_char_next( TT_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt32 result = 0; + FT_UInt32 char_code = *pchar_code + 1; + FT_UInt gindex = 0; + FT_Byte* table = cmap->data; + FT_Byte* p = table + 8204; + FT_UInt32 num_groups = TT_NEXT_ULONG( p ); + FT_UInt32 start, end, start_id; + + + p = table + 8208; + + for ( ; num_groups > 0; num_groups-- ) + { + start = TT_NEXT_ULONG( p ); + end = TT_NEXT_ULONG( p ); + start_id = TT_NEXT_ULONG( p ); + + if ( char_code < start ) + char_code = start; + + if ( char_code <= end ) + { + gindex = (FT_UInt)( char_code - start + start_id ); + if ( gindex != 0 ) + { + result = char_code; + goto Exit; + } + } + } + + Exit: + *pchar_code = result; + return gindex; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap8_get_info( TT_CMap cmap, + TT_CMapInfo *cmap_info ) + { + FT_Byte* p = cmap->data + 8; + + + cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const TT_CMap_ClassRec tt_cmap8_class_rec = + { + { + sizeof ( TT_CMapRec ), + + (FT_CMap_InitFunc) tt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)tt_cmap8_char_index, + (FT_CMap_CharNextFunc) tt_cmap8_char_next + }, + 8, + (TT_CMap_ValidateFunc) tt_cmap8_validate, + (TT_CMap_Info_GetFunc) tt_cmap8_get_info + }; + +#endif /* TT_CONFIG_CMAP_FORMAT_8 */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FORMAT 10 *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* TABLE OVERVIEW */ + /* -------------- */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* format 0 USHORT must be 10 */ + /* reserved 2 USHORT reserved */ + /* length 4 ULONG length in bytes */ + /* language 8 ULONG Mac language code */ + /* */ + /* start 12 ULONG first char in range */ + /* count 16 ULONG number of chars in range */ + /* glyphIds 20 USHORT[count] glyph indices covered */ + /* */ + +#ifdef TT_CONFIG_CMAP_FORMAT_10 + + FT_CALLBACK_DEF( void ) + tt_cmap10_validate( FT_Byte* table, + FT_Validator valid ) + { + FT_Byte* p = table + 4; + FT_ULong length, count; + + + if ( table + 20 > valid->limit ) + FT_INVALID_TOO_SHORT; + + length = TT_NEXT_ULONG( p ); + p = table + 16; + count = TT_NEXT_ULONG( p ); + + if ( table + length > valid->limit || length < 20 + count * 2 ) + FT_INVALID_TOO_SHORT; + + /* check glyph indices */ + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + FT_UInt gindex; + + + for ( ; count > 0; count-- ) + { + gindex = TT_NEXT_USHORT( p ); + if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) + FT_INVALID_GLYPH_ID; + } + } + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap10_char_index( TT_CMap cmap, + FT_UInt32 char_code ) + { + FT_Byte* table = cmap->data; + FT_UInt result = 0; + FT_Byte* p = table + 12; + FT_UInt32 start = TT_NEXT_ULONG( p ); + FT_UInt32 count = TT_NEXT_ULONG( p ); + FT_UInt32 idx = (FT_ULong)( char_code - start ); + + + if ( idx < count ) + { + p += 2 * idx; + result = TT_PEEK_USHORT( p ); + } + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap10_char_next( TT_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_Byte* table = cmap->data; + FT_UInt32 char_code = *pchar_code + 1; + FT_UInt gindex = 0; + FT_Byte* p = table + 12; + FT_UInt32 start = TT_NEXT_ULONG( p ); + FT_UInt32 count = TT_NEXT_ULONG( p ); + FT_UInt32 idx; + + + if ( char_code < start ) + char_code = start; + + idx = (FT_UInt32)( char_code - start ); + p += 2 * idx; + + for ( ; idx < count; idx++ ) + { + gindex = TT_NEXT_USHORT( p ); + if ( gindex != 0 ) + break; + char_code++; + } + + *pchar_code = char_code; + return gindex; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap10_get_info( TT_CMap cmap, + TT_CMapInfo *cmap_info ) + { + FT_Byte* p = cmap->data + 8; + + + cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); + + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const TT_CMap_ClassRec tt_cmap10_class_rec = + { + { + sizeof ( TT_CMapRec ), + + (FT_CMap_InitFunc) tt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)tt_cmap10_char_index, + (FT_CMap_CharNextFunc) tt_cmap10_char_next + }, + 10, + (TT_CMap_ValidateFunc) tt_cmap10_validate, + (TT_CMap_Info_GetFunc) tt_cmap10_get_info + }; + +#endif /* TT_CONFIG_CMAP_FORMAT_10 */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** FORMAT 12 *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* TABLE OVERVIEW */ + /* -------------- */ + /* */ + /* NAME OFFSET TYPE DESCRIPTION */ + /* */ + /* format 0 USHORT must be 12 */ + /* reserved 2 USHORT reserved */ + /* length 4 ULONG length in bytes */ + /* language 8 ULONG Mac language code */ + /* count 12 ULONG number of groups */ + /* 16 */ + /* */ + /* This header is followed by `count' groups of the following format: */ + /* */ + /* start 0 ULONG first charcode */ + /* end 4 ULONG last charcode */ + /* startId 8 ULONG start glyph id for the group */ + /* */ + +#ifdef TT_CONFIG_CMAP_FORMAT_12 + + FT_CALLBACK_DEF( void ) + tt_cmap12_validate( FT_Byte* table, + FT_Validator valid ) + { + FT_Byte* p; + FT_ULong length; + FT_ULong num_groups; + + + if ( table + 16 > valid->limit ) + FT_INVALID_TOO_SHORT; + + p = table + 4; + length = TT_NEXT_ULONG( p ); + + p = table + 12; + num_groups = TT_NEXT_ULONG( p ); + + if ( table + length > valid->limit || length < 16 + 12 * num_groups ) + FT_INVALID_TOO_SHORT; + + /* check groups, they must be in increasing order */ + { + FT_ULong n, start, end, start_id, last = 0; + + + for ( n = 0; n < num_groups; n++ ) + { + start = TT_NEXT_ULONG( p ); + end = TT_NEXT_ULONG( p ); + start_id = TT_NEXT_ULONG( p ); + + if ( start > end ) + FT_INVALID_DATA; + + if ( n > 0 && start <= last ) + FT_INVALID_DATA; + + if ( valid->level >= FT_VALIDATE_TIGHT ) + { + if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) + FT_INVALID_GLYPH_ID; + } + + last = end; + } + } + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap12_char_index( TT_CMap cmap, + FT_UInt32 char_code ) + { + FT_UInt result = 0; + FT_Byte* table = cmap->data; + FT_Byte* p = table + 12; + FT_UInt32 num_groups = TT_NEXT_ULONG( p ); + FT_UInt32 start, end, start_id; + + + for ( ; num_groups > 0; num_groups-- ) + { + start = TT_NEXT_ULONG( p ); + end = TT_NEXT_ULONG( p ); + start_id = TT_NEXT_ULONG( p ); + + if ( char_code < start ) + break; + + if ( char_code <= end ) + { + result = (FT_UInt)( start_id + char_code - start ); + break; + } + } + return result; + } + + + FT_CALLBACK_DEF( FT_UInt ) + tt_cmap12_char_next( TT_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_Byte* table = cmap->data; + FT_UInt32 result = 0; + FT_UInt32 char_code = *pchar_code + 1; + FT_UInt gindex = 0; + FT_Byte* p = table + 12; + FT_UInt32 num_groups = TT_NEXT_ULONG( p ); + FT_UInt32 start, end, start_id; + + + p = table + 16; + + for ( ; num_groups > 0; num_groups-- ) + { + start = TT_NEXT_ULONG( p ); + end = TT_NEXT_ULONG( p ); + start_id = TT_NEXT_ULONG( p ); + + if ( char_code < start ) + char_code = start; + + if ( char_code <= end ) + { + gindex = (FT_UInt)(char_code - start + start_id); + if ( gindex != 0 ) + { + result = char_code; + goto Exit; + } + } + } + + Exit: + *pchar_code = result; + return gindex; + } + + + FT_CALLBACK_DEF( FT_Error ) + tt_cmap12_get_info( TT_CMap cmap, + TT_CMapInfo *cmap_info ) + { + FT_Byte* p = cmap->data + 8; + + + cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); + + return FT_Err_Ok; + } + + + FT_CALLBACK_TABLE_DEF + const TT_CMap_ClassRec tt_cmap12_class_rec = + { + { + sizeof ( TT_CMapRec ), + + (FT_CMap_InitFunc) tt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)tt_cmap12_char_index, + (FT_CMap_CharNextFunc) tt_cmap12_char_next + }, + 12, + (TT_CMap_ValidateFunc) tt_cmap12_validate, + (TT_CMap_Info_GetFunc) tt_cmap12_get_info + }; + + +#endif /* TT_CONFIG_CMAP_FORMAT_12 */ + + + static const TT_CMap_Class tt_cmap_classes[] = + { +#ifdef TT_CONFIG_CMAP_FORMAT_0 + &tt_cmap0_class_rec, +#endif + +#ifdef TT_CONFIG_CMAP_FORMAT_2 + &tt_cmap2_class_rec, +#endif + +#ifdef TT_CONFIG_CMAP_FORMAT_4 + &tt_cmap4_class_rec, +#endif + +#ifdef TT_CONFIG_CMAP_FORMAT_6 + &tt_cmap6_class_rec, +#endif + +#ifdef TT_CONFIG_CMAP_FORMAT_8 + &tt_cmap8_class_rec, +#endif + +#ifdef TT_CONFIG_CMAP_FORMAT_10 + &tt_cmap10_class_rec, +#endif + +#ifdef TT_CONFIG_CMAP_FORMAT_12 + &tt_cmap12_class_rec, +#endif + + NULL, + }; + + + /* parse the `cmap' table and build the corresponding TT_CMap objects */ + /* in the current face */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_build_cmaps( TT_Face face ) + { + FT_Byte* table = face->cmap_table; + FT_Byte* limit = table + face->cmap_size; + FT_UInt volatile num_cmaps; + FT_Byte* volatile p = table; + + + if ( p + 4 > limit ) + return SFNT_Err_Invalid_Table; + + /* only recognize format 0 */ + if ( TT_NEXT_USHORT( p ) != 0 ) + { + p -= 2; + FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n", + TT_PEEK_USHORT( p ) )); + return SFNT_Err_Invalid_Table; + } + + num_cmaps = TT_NEXT_USHORT( p ); + + for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) + { + FT_CharMapRec charmap; + FT_UInt32 offset; + + + charmap.platform_id = TT_NEXT_USHORT( p ); + charmap.encoding_id = TT_NEXT_USHORT( p ); + charmap.face = FT_FACE( face ); + charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ + offset = TT_NEXT_ULONG( p ); + + if ( offset && table + offset + 2 < limit ) + { + FT_Byte* cmap = table + offset; + volatile FT_UInt format = TT_PEEK_USHORT( cmap ); + const TT_CMap_Class* volatile pclazz = tt_cmap_classes; + TT_CMap_Class clazz; + + + for ( ; *pclazz; pclazz++ ) + { + clazz = *pclazz; + if ( clazz->format == format ) + { + volatile TT_ValidatorRec valid; + + + ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, + FT_VALIDATE_DEFAULT ); + + valid.num_glyphs = (FT_UInt)face->root.num_glyphs; + + if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 ) + { + /* validate this cmap sub-table */ + clazz->validate( cmap, FT_VALIDATOR( &valid ) ); + } + + if ( valid.validator.error == 0 ) + (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL ); + else + { + FT_ERROR(( "tt_face_build_cmaps:" )); + FT_ERROR(( " broken cmap sub-table ignored!\n" )); + } + break; + } + } + } + } + + return 0; + } + + + FT_LOCAL( FT_Error ) + tt_get_cmap_info( FT_CharMap charmap, + TT_CMapInfo *cmap_info ) + { + FT_CMap cmap = (FT_CMap)charmap; + TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; + + + return clazz->get_cmap_info( charmap, cmap_info ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttcmap0.h b/Utilities/vtkfreetype/src/sfnt/ttcmap0.h new file mode 100644 index 0000000..6ca9ca1 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttcmap0.h @@ -0,0 +1,80 @@ +/***************************************************************************/ +/* */ +/* ttcmap0.h */ +/* */ +/* TrueType new character mapping table (cmap) support (specification). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTCMAP0_H__ +#define __TTCMAP0_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_TRUETYPE_TYPES_H +#include FT_INTERNAL_OBJECTS_H +#include FT_SERVICE_TT_CMAP_H + +FT_BEGIN_HEADER + + typedef struct TT_CMapRec_ + { + FT_CMapRec cmap; + FT_Byte* data; /* pointer to in-memory cmap table */ + + } TT_CMapRec, *TT_CMap; + + typedef const struct TT_CMap_ClassRec_* TT_CMap_Class; + + + typedef FT_Error + (*TT_CMap_ValidateFunc)( FT_Byte* data, + FT_Validator valid ); + + typedef struct TT_CMap_ClassRec_ + { + FT_CMap_ClassRec clazz; + FT_UInt format; + TT_CMap_ValidateFunc validate; + TT_CMap_Info_GetFunc get_cmap_info; + + } TT_CMap_ClassRec; + + + typedef struct TT_ValidatorRec_ + { + FT_ValidatorRec validator; + FT_UInt num_glyphs; + + } TT_ValidatorRec, *TT_Validator; + + +#define TT_VALIDATOR( x ) ((TT_Validator)( x )) +#define TT_VALID_GLYPH_COUNT( x ) TT_VALIDATOR( x )->num_glyphs + + + FT_LOCAL( FT_Error ) + tt_face_build_cmaps( TT_Face face ); + + /* used in tt-cmaps service */ + FT_LOCAL( FT_Error ) + tt_get_cmap_info( FT_CharMap charmap, + TT_CMapInfo *cmap_info ); + + +FT_END_HEADER + +#endif /* __TTCMAP0_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttload.c b/Utilities/vtkfreetype/src/sfnt/ttload.c new file mode 100644 index 0000000..fa5c6a7 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttload.c @@ -0,0 +1,1912 @@ +/***************************************************************************/ +/* */ +/* ttload.c */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_TAGS_H +#include "ttload.h" + +#include "sferrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttload + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_lookup_table */ + /* */ + /* <Description> */ + /* Looks for a TrueType table by name. */ + /* */ + /* <Input> */ + /* face :: A face object handle. */ + /* */ + /* tag :: The searched tag. */ + /* */ + /* <Return> */ + /* A pointer to the table directory entry. 0 if not found. */ + /* */ + FT_LOCAL_DEF( TT_Table ) + tt_face_lookup_table( TT_Face face, + FT_ULong tag ) + { + TT_Table entry; + TT_Table limit; + + + FT_TRACE3(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", + face, + (FT_Char)( tag >> 24 ), + (FT_Char)( tag >> 16 ), + (FT_Char)( tag >> 8 ), + (FT_Char)( tag ) )); + + entry = face->dir_tables; + limit = entry + face->num_tables; + + for ( ; entry < limit; entry++ ) + { + /* For compatibility with Windows, we consider 0-length */ + /* tables the same as missing tables. */ + if ( entry->Tag == tag && entry->Length != 0 ) + { + FT_TRACE3(( "found table.\n" )); + return entry; + } + } + + FT_TRACE3(( "could not find table!\n" )); + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_goto_table */ + /* */ + /* <Description> */ + /* Looks for a TrueType table by name, then seek a stream to it. */ + /* */ + /* <Input> */ + /* face :: A face object handle. */ + /* */ + /* tag :: The searched tag. */ + /* */ + /* stream :: The stream to seek when the table is found. */ + /* */ + /* <Output> */ + /* length :: The length of the table if found, undefined otherwise. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_goto_table( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ) + { + TT_Table table; + FT_Error error; + + + table = tt_face_lookup_table( face, tag ); + if ( table ) + { + if ( length ) + *length = table->Length; + + if ( FT_STREAM_SEEK( table->Offset ) ) + goto Exit; + } + else + error = SFNT_Err_Table_Missing; + + Exit: + return error; + } + + + /* In theory, we should check the values of `search_range', */ + /* `entry_selector', and `range_shift' to detect non-SFNT based files */ + /* whose header might also start with 0x100000L (yes, these exist). */ + /* */ + /* Very unfortunately, many TrueType fonts don't have these fields */ + /* set correctly and we must ignore them to support them. An alternative */ + /* way to check the font file is thus to: */ + /* */ + /* - check that `num_tables' is valid */ + /* - look for a "head" table, check its size, and parse it to */ + /* see if its "magic" field is correctly set */ + /* */ + /* When checking directory entries, ignore the tables `glyx' and `locx' */ + /* which are hacked-out versions of `glyf' and `loca' in some PostScript */ + /* Type 42 fonts, and will generally be invalid. */ + /* */ + static FT_Error + sfnt_dir_check( FT_Stream stream, + FT_ULong offset, + FT_UInt num_tables ) + { + FT_Error error; + FT_UInt nn, has_head = 0; + + const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' ); + const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' ); + + static const FT_Frame_Field sfnt_dir_entry_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_TableRec + + FT_FRAME_START( 16 ), + FT_FRAME_ULONG( Tag ), + FT_FRAME_ULONG( CheckSum ), + FT_FRAME_ULONG( Offset ), + FT_FRAME_ULONG( Length ), + FT_FRAME_END + }; + + + /* if 'num_tables' is 0, read the table count from the file */ + if ( num_tables == 0 ) + { + if ( FT_STREAM_SEEK( offset ) || + FT_STREAM_SKIP( 4 ) || + FT_READ_USHORT( num_tables ) || + FT_STREAM_SKIP( 6 ) ) + goto Bad_Format; + + if ( offset + 12 + num_tables*16 > stream->size ) + goto Bad_Format; + } + else if ( FT_STREAM_SEEK( offset + 12 ) ) + goto Bad_Format; + + for ( nn = 0; nn < num_tables; nn++ ) + { + TT_TableRec table; + + + if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) ) + goto Bad_Format; + + if ( table.Offset + table.Length > stream->size && + table.Tag != glyx_tag && table.Tag != locx_tag ) + goto Bad_Format; + + if ( table.Tag == TTAG_head ) + { + FT_UInt32 magic; + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + head_retry: +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + has_head = 1; + + /* The table length should be 0x36, but certain font tools + * make it 0x38, so we will just check that it is greater. + * + * Note that according to the specification, + * the table must be padded to 32-bit lengths, but this doesn't + * apply to the value of its "Length" field! + */ + if ( table.Length < 0x36 || + FT_STREAM_SEEK( table.Offset + 12 ) || + FT_READ_ULONG( magic ) || + magic != 0x5F0F3CF5UL ) + goto Bad_Format; + + if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) ) + goto Bad_Format; + } +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + else if ( table.Tag == TTAG_bhed ) + goto head_retry; +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + } + + if ( has_head == 0 ) + goto Bad_Format; + + Exit: + return error; + + Bad_Format: + error = SFNT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_sfnt_header */ + /* */ + /* <Description> */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face_index :: If the font is a collection, the number of the font */ + /* in the collection. Must be zero otherwise. */ + /* */ + /* <Output> */ + /* sfnt :: The SFNT header. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType collection' */ + /* */ + /* The header will be checked whether it is valid by looking at the */ + /* values of `search_range', `entry_selector', and `range_shift'. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_sfnt_header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header sfnt ) + { + FT_Error error; + FT_ULong font_format_tag, format_tag, offset; + FT_Memory memory = stream->memory; + + static const FT_Frame_Field sfnt_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE SFNT_HeaderRec + + FT_FRAME_START( 8 ), + FT_FRAME_USHORT( num_tables ), + FT_FRAME_USHORT( search_range ), + FT_FRAME_USHORT( entry_selector ), + FT_FRAME_USHORT( range_shift ), + FT_FRAME_END + }; + + static const FT_Frame_Field ttc_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TTC_HeaderRec + + FT_FRAME_START( 8 ), + FT_FRAME_LONG( version ), + FT_FRAME_LONG( count ), + FT_FRAME_END + }; + + + FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n", + face, face_index )); + + face->ttc_header.tag = 0; + face->ttc_header.version = 0; + face->ttc_header.count = 0; + + face->num_tables = 0; + + /* First of all, read the first 4 bytes. If it is `ttcf', then the */ + /* file is a TrueType collection, otherwise it is a single-face font. */ + /* */ + offset = FT_STREAM_POS(); + + if ( FT_READ_ULONG( font_format_tag ) ) + goto Exit; + + format_tag = font_format_tag; + + if ( font_format_tag == TTAG_ttcf ) + { + FT_Int n; + + + FT_TRACE3(( "tt_face_load_sfnt_header: file is a collection\n" )); + + /* It is a TrueType collection, i.e. a file containing several */ + /* font files. Read the font directory now */ + if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) + goto Exit; + + /* now read the offsets of each font in the file */ + if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) || + FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) + goto Exit; + + for ( n = 0; n < face->ttc_header.count; n++ ) + face->ttc_header.offsets[n] = FT_GET_ULONG(); + + FT_FRAME_EXIT(); + + /* check face index */ + if ( face_index >= face->ttc_header.count ) + { + error = SFNT_Err_Bad_Argument; + goto Exit; + } + + /* seek to the appropriate TrueType file, then read tag */ + offset = face->ttc_header.offsets[face_index]; + + if ( FT_STREAM_SEEK( offset ) || + FT_READ_LONG( format_tag ) ) + goto Exit; + } + + /* the format tag was read, now check the rest of the header */ + sfnt->format_tag = format_tag; + sfnt->offset = offset; + + if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) ) + goto Exit; + + /* now check the sfnt directory */ + error = sfnt_dir_check( stream, offset, sfnt->num_tables ); + if ( error ) + { + FT_TRACE2(( "tt_face_load_sfnt_header: file is not SFNT!\n" )); + error = SFNT_Err_Unknown_File_Format; + goto Exit; + } + + /* disallow face index values > 0 for non-TTC files */ + if ( font_format_tag != TTAG_ttcf && face_index > 0 ) + error = SFNT_Err_Bad_Argument; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_directory */ + /* */ + /* <Description> */ + /* Loads the table directory into a face object. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Input> */ + /* stream :: The input stream. */ + /* */ + /* sfnt :: The SFNT directory header. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be at the font file's origin. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_directory( TT_Face face, + FT_Stream stream, + SFNT_Header sfnt ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + TT_TableRec *entry, *limit; + + + FT_TRACE2(( "tt_face_load_directory: %08p\n", face )); + + FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables )); + FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag )); + + face->num_tables = sfnt->num_tables; + + if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) ) + goto Exit; + + if ( FT_STREAM_SEEK( sfnt->offset + 12 ) || + FT_FRAME_ENTER( face->num_tables * 16L ) ) + goto Exit; + + entry = face->dir_tables; + limit = entry + face->num_tables; + + for ( ; entry < limit; entry++ ) + { /* loop through the tables and get all entries */ + entry->Tag = FT_GET_TAG4(); + entry->CheckSum = FT_GET_ULONG(); + entry->Offset = FT_GET_LONG(); + entry->Length = FT_GET_LONG(); + + FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n", + (FT_Char)( entry->Tag >> 24 ), + (FT_Char)( entry->Tag >> 16 ), + (FT_Char)( entry->Tag >> 8 ), + (FT_Char)( entry->Tag ), + entry->Offset, + entry->Length )); + } + + FT_FRAME_EXIT(); + + FT_TRACE2(( "Directory loaded\n\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_any */ + /* */ + /* <Description> */ + /* Loads any font table into client memory. */ + /* */ + /* <Input> */ + /* face :: The face object to look for. */ + /* */ + /* tag :: The tag of table to load. Use the value 0 if you want */ + /* to access the whole font file, else set this parameter */ + /* to a valid TrueType table tag that you can forge with */ + /* the MAKE_TT_TAG macro. */ + /* */ + /* offset :: The starting offset in the table (or the file if */ + /* tag == 0). */ + /* */ + /* length :: The address of the decision variable: */ + /* */ + /* If length == NULL: */ + /* Loads the whole table. Returns an error if */ + /* `offset' == 0! */ + /* */ + /* If *length == 0: */ + /* Exits immediately; returning the length of the given */ + /* table or of the font file, depending on the value of */ + /* `tag'. */ + /* */ + /* If *length != 0: */ + /* Loads the next `length' bytes of table or font, */ + /* starting at offset `offset' (in table or font too). */ + /* */ + /* <Output> */ + /* buffer :: The address of target buffer. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_any( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ) + { + FT_Error error; + FT_Stream stream; + TT_Table table; + FT_ULong size; + + + if ( tag != 0 ) + { + /* look for tag in font directory */ + table = tt_face_lookup_table( face, tag ); + if ( !table ) + { + error = SFNT_Err_Table_Missing; + goto Exit; + } + + offset += table->Offset; + size = table->Length; + } + else + /* tag == 0 -- the user wants to access the font file directly */ + size = face->root.stream->size; + + if ( length && *length == 0 ) + { + *length = size; + + return SFNT_Err_Ok; + } + + if ( length ) + size = *length; + + stream = face->root.stream; + /* the `if' is syntactic sugar for picky compilers */ + if ( FT_STREAM_READ_AT( offset, buffer, size ) ) + goto Exit; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_generic_header */ + /* */ + /* <Description> */ + /* Loads the TrueType table `head' or `bhed'. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + tt_face_load_generic_header( TT_Face face, + FT_Stream stream, + FT_ULong tag ) + { + FT_Error error; + TT_Header* header; + + static const FT_Frame_Field header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_Header + + FT_FRAME_START( 54 ), + FT_FRAME_ULONG ( Table_Version ), + FT_FRAME_ULONG ( Font_Revision ), + FT_FRAME_LONG ( CheckSum_Adjust ), + FT_FRAME_LONG ( Magic_Number ), + FT_FRAME_USHORT( Flags ), + FT_FRAME_USHORT( Units_Per_EM ), + FT_FRAME_LONG ( Created[0] ), + FT_FRAME_LONG ( Created[1] ), + FT_FRAME_LONG ( Modified[0] ), + FT_FRAME_LONG ( Modified[1] ), + FT_FRAME_SHORT ( xMin ), + FT_FRAME_SHORT ( yMin ), + FT_FRAME_SHORT ( xMax ), + FT_FRAME_SHORT ( yMax ), + FT_FRAME_USHORT( Mac_Style ), + FT_FRAME_USHORT( Lowest_Rec_PPEM ), + FT_FRAME_SHORT ( Font_Direction ), + FT_FRAME_SHORT ( Index_To_Loc_Format ), + FT_FRAME_SHORT ( Glyph_Data_Format ), + FT_FRAME_END + }; + + + FT_TRACE2(( "tt_face_load_generic_header: " + "%08p, looking up font table `%c%c%c%c'.\n", + face, + (FT_Char)( tag >> 24 ), + (FT_Char)( tag >> 16 ), + (FT_Char)( tag >> 8 ), + (FT_Char)( tag ) )); + + error = face->goto_table( face, tag, stream, 0 ); + if ( error ) + { + FT_TRACE2(( "tt_face_load_generic_header: Font table is missing!\n" )); + goto Exit; + } + + header = &face->header; + + if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) + goto Exit; + + FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM )); + FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format )); + FT_TRACE2(( "tt_face_load_generic_header: Font table loaded.\n" )); + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_header( TT_Face face, + FT_Stream stream ) + { + return tt_face_load_generic_header( face, stream, TTAG_head ); + } + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_bitmap_header( TT_Face face, + FT_Stream stream ) + { + return tt_face_load_generic_header( face, stream, TTAG_bhed ); + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_max_profile */ + /* */ + /* <Description> */ + /* Loads the maximum profile into a face object. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_max_profile( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_MaxProfile* maxProfile = &face->max_profile; + + const FT_Frame_Field maxp_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_MaxProfile + + FT_FRAME_START( 6 ), + FT_FRAME_LONG ( version ), + FT_FRAME_USHORT( numGlyphs ), + FT_FRAME_END + }; + + const FT_Frame_Field maxp_fields_extra[] = + { + FT_FRAME_START( 26 ), + FT_FRAME_USHORT( maxPoints ), + FT_FRAME_USHORT( maxContours ), + FT_FRAME_USHORT( maxCompositePoints ), + FT_FRAME_USHORT( maxCompositeContours ), + FT_FRAME_USHORT( maxZones ), + FT_FRAME_USHORT( maxTwilightPoints ), + FT_FRAME_USHORT( maxStorage ), + FT_FRAME_USHORT( maxFunctionDefs ), + FT_FRAME_USHORT( maxInstructionDefs ), + FT_FRAME_USHORT( maxStackElements ), + FT_FRAME_USHORT( maxSizeOfInstructions ), + FT_FRAME_USHORT( maxComponentElements ), + FT_FRAME_USHORT( maxComponentDepth ), + FT_FRAME_END + }; + + + FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face )); + + error = face->goto_table( face, TTAG_maxp, stream, 0 ); + if ( error ) + goto Exit; + + if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) ) + goto Exit; + + face->root.num_glyphs = maxProfile->numGlyphs; + + maxProfile->maxPoints = 0; + maxProfile->maxContours = 0; + maxProfile->maxCompositePoints = 0; + maxProfile->maxCompositeContours = 0; + maxProfile->maxZones = 0; + maxProfile->maxTwilightPoints = 0; + maxProfile->maxStorage = 0; + maxProfile->maxFunctionDefs = 0; + maxProfile->maxInstructionDefs = 0; + maxProfile->maxStackElements = 0; + maxProfile->maxSizeOfInstructions = 0; + maxProfile->maxComponentElements = 0; + maxProfile->maxComponentDepth = 0; + + if ( maxProfile->version >= 0x10000L ) + { + if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) ) + goto Exit; + + /* XXX: an adjustment that is necessary to load certain */ + /* broken fonts like `Keystrokes MT' :-( */ + /* */ + /* We allocate 64 function entries by default when */ + /* the maxFunctionDefs field is null. */ + + if ( maxProfile->maxFunctionDefs == 0 ) + maxProfile->maxFunctionDefs = 64; + + face->root.internal->max_points = + (FT_UShort)FT_MAX( maxProfile->maxCompositePoints, + maxProfile->maxPoints ); + + face->root.internal->max_contours = + (FT_Short)FT_MAX( maxProfile->maxCompositeContours, + maxProfile->maxContours ); + + face->max_components = (FT_ULong)maxProfile->maxComponentElements + + maxProfile->maxComponentDepth; + + /* XXX: some fonts have maxComponents set to 0; we will */ + /* then use 16 of them by default. */ + if ( face->max_components == 0 ) + face->max_components = 16; + + /* We also increase maxPoints and maxContours in order to support */ + /* some broken fonts. */ + face->root.internal->max_points += (FT_UShort)8; + face->root.internal->max_contours += (FT_Short) 4; + } + + FT_TRACE2(( "MAXP loaded.\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_metrics */ + /* */ + /* <Description> */ + /* Loads the horizontal or vertical metrics table into a face object. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + tt_face_load_metrics( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_ULong table_len; + FT_Long num_shorts, num_longs, num_shorts_checked; + + TT_LongMetrics * longs; + TT_ShortMetrics** shorts; + + + FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" + : "Horizontal", + face )); + + if ( vertical ) + { + /* The table is optional, quit silently if it wasn't found */ + /* */ + /* XXX: Some fonts have a valid vertical header with a non-null */ + /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ + /* table to get the metrics from (e.g. mingliu). */ + /* */ + /* For safety, we set the field to 0! */ + /* */ + error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); + if ( error ) + { + /* Set number_Of_VMetrics to 0! */ + FT_TRACE2(( " no vertical header in file.\n" )); + face->vertical.number_Of_VMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } + + num_longs = face->vertical.number_Of_VMetrics; + longs = (TT_LongMetrics *)&face->vertical.long_metrics; + shorts = (TT_ShortMetrics**)&face->vertical.short_metrics; + } + else + { + error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); + if ( error ) + { + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + /* If this is an incrementally loaded font and there are */ + /* overriding metrics tolerate a missing 'hmtx' table. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs-> + get_glyph_metrics ) + { + face->horizontal.number_Of_HMetrics = 0; + error = SFNT_Err_Ok; + goto Exit; + } +#endif + + FT_ERROR(( " no horizontal metrics in file!\n" )); + error = SFNT_Err_Hmtx_Table_Missing; + goto Exit; + } + + num_longs = face->horizontal.number_Of_HMetrics; + longs = (TT_LongMetrics *)&face->horizontal.long_metrics; + shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics; + } + + /* never trust derived values */ + + num_shorts = face->max_profile.numGlyphs - num_longs; + num_shorts_checked = ( table_len - num_longs * 4L ) / 2; + + if ( num_shorts < 0 ) + { + FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n", + vertical ? "Vertical" + : "Horizontal" )); + + error = vertical ? SFNT_Err_Invalid_Vert_Metrics + : SFNT_Err_Invalid_Horiz_Metrics; + goto Exit; + } + + if ( FT_QNEW_ARRAY( *longs, num_longs ) || + FT_QNEW_ARRAY( *shorts, num_shorts ) ) + goto Exit; + + if ( FT_FRAME_ENTER( table_len ) ) + goto Exit; + + { + TT_LongMetrics cur = *longs; + TT_LongMetrics limit = cur + num_longs; + + + for ( ; cur < limit; cur++ ) + { + cur->advance = FT_GET_USHORT(); + cur->bearing = FT_GET_SHORT(); + } + } + + /* do we have an inconsistent number of metric values? */ + { + TT_ShortMetrics* cur = *shorts; + TT_ShortMetrics* limit = cur + + FT_MIN( num_shorts, num_shorts_checked ); + + + for ( ; cur < limit; cur++ ) + *cur = FT_GET_SHORT(); + + /* we fill up the missing left side bearings with the */ + /* last valid value. Since this will occur for buggy CJK */ + /* fonts usually only, nothing serious will happen */ + if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) + { + FT_Short val = (*shorts)[num_shorts_checked - 1]; + + + limit = *shorts + num_shorts; + for ( ; cur < limit; cur++ ) + *cur = val; + } + } + + FT_FRAME_EXIT(); + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_metrics_header */ + /* */ + /* <Description> */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_metrics_header( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + TT_HoriHeader* header; + + const FT_Frame_Field metrics_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_HoriHeader + + FT_FRAME_START( 36 ), + FT_FRAME_ULONG ( Version ), + FT_FRAME_SHORT ( Ascender ), + FT_FRAME_SHORT ( Descender ), + FT_FRAME_SHORT ( Line_Gap ), + FT_FRAME_USHORT( advance_Width_Max ), + FT_FRAME_SHORT ( min_Left_Side_Bearing ), + FT_FRAME_SHORT ( min_Right_Side_Bearing ), + FT_FRAME_SHORT ( xMax_Extent ), + FT_FRAME_SHORT ( caret_Slope_Rise ), + FT_FRAME_SHORT ( caret_Slope_Run ), + FT_FRAME_SHORT ( caret_Offset ), + FT_FRAME_SHORT ( Reserved[0] ), + FT_FRAME_SHORT ( Reserved[1] ), + FT_FRAME_SHORT ( Reserved[2] ), + FT_FRAME_SHORT ( Reserved[3] ), + FT_FRAME_SHORT ( metric_Data_Format ), + FT_FRAME_USHORT( number_Of_HMetrics ), + FT_FRAME_END + }; + + + FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " )); + + if ( vertical ) + { + face->vertical_info = 0; + + /* The vertical header table is optional, so return quietly if */ + /* we don't find it. */ + error = face->goto_table( face, TTAG_vhea, stream, 0 ); + if ( error ) + { + error = SFNT_Err_Ok; + goto Exit; + } + + face->vertical_info = 1; + header = (TT_HoriHeader*)&face->vertical; + } + else + { + /* The horizontal header is mandatory; return an error if we */ + /* don't find it. */ + error = face->goto_table( face, TTAG_hhea, stream, 0 ); + if ( error ) + { + error = SFNT_Err_Horiz_Header_Missing; + goto Exit; + } + + header = &face->horizontal; + } + + if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) ) + goto Exit; + + header->long_metrics = NULL; + header->short_metrics = NULL; + + FT_TRACE2(( "loaded\n" )); + + /* Now try to load the corresponding metrics */ + + error = tt_face_load_metrics( face, stream, vertical ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_names */ + /* */ + /* <Description> */ + /* Loads the name records. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_names( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong table_pos, table_len; + FT_ULong storage_start, storage_limit; + FT_UInt count; + TT_NameTable table; + + static const FT_Frame_Field name_table_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_NameTableRec + + FT_FRAME_START( 6 ), + FT_FRAME_USHORT( format ), + FT_FRAME_USHORT( numNameRecords ), + FT_FRAME_USHORT( storageOffset ), + FT_FRAME_END + }; + + static const FT_Frame_Field name_record_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_NameEntryRec + + /* no FT_FRAME_START */ + FT_FRAME_USHORT( platformID ), + FT_FRAME_USHORT( encodingID ), + FT_FRAME_USHORT( languageID ), + FT_FRAME_USHORT( nameID ), + FT_FRAME_USHORT( stringLength ), + FT_FRAME_USHORT( stringOffset ), + FT_FRAME_END + }; + + + table = &face->name_table; + table->stream = stream; + + FT_TRACE2(( "Names " )); + + error = face->goto_table( face, TTAG_name, stream, &table_len ); + if ( error ) + { + /* The name table is required so indicate failure. */ + FT_TRACE2(( "is missing!\n" )); + error = SFNT_Err_Name_Table_Missing; + goto Exit; + } + + table_pos = FT_STREAM_POS(); + + + if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) + goto Exit; + + /* Some popular Asian fonts have an invalid `storageOffset' value */ + /* (it should be at least "6 + 12*num_names"). However, the string */ + /* offsets, computed as "storageOffset + entry->stringOffset", are */ + /* valid pointers within the name table... */ + /* */ + /* We thus can't check `storageOffset' right now. */ + /* */ + storage_start = table_pos + 6 + 12*table->numNameRecords; + storage_limit = table_pos + table_len; + + if ( storage_start > storage_limit ) + { + FT_ERROR(( "tt_face_load_names: invalid `name' table\n" )); + error = SFNT_Err_Name_Table_Missing; + goto Exit; + } + + /* Allocate the array of name records. */ + count = table->numNameRecords; + table->numNameRecords = 0; + + if ( FT_NEW_ARRAY( table->names, count ) || + FT_FRAME_ENTER( count * 12 ) ) + goto Exit; + + /* Load the name records and determine how much storage is needed */ + /* to hold the strings themselves. */ + { + TT_NameEntryRec* entry = table->names; + + + for ( ; count > 0; count-- ) + { + if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) ) + continue; + + /* check that the name is not empty */ + if ( entry->stringLength == 0 ) + continue; + + /* check that the name string is within the table */ + entry->stringOffset += table_pos + table->storageOffset; + if ( entry->stringOffset < storage_start || + entry->stringOffset + entry->stringLength > storage_limit ) + { + /* invalid entry - ignore it */ + entry->stringOffset = 0; + entry->stringLength = 0; + continue; + } + + entry++; + } + + table->numNameRecords = (FT_UInt)( entry - table->names ); + } + + FT_FRAME_EXIT(); + + FT_TRACE2(( "loaded\n" )); + + /* everything went well, update face->num_names */ + face->num_names = (FT_UShort) table->numNameRecords; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_free_names */ + /* */ + /* <Description> */ + /* Frees the name records. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + FT_LOCAL_DEF( void ) + tt_face_free_names( TT_Face face ) + { + FT_Memory memory = face->root.driver->root.memory; + TT_NameTable table = &face->name_table; + TT_NameEntry entry = table->names; + FT_UInt count = table->numNameRecords; + + + if ( table->names ) + { + for ( ; count > 0; count--, entry++ ) + { + FT_FREE( entry->string ); + entry->stringLength = 0; + } + + /* free strings table */ + FT_FREE( table->names ); + } + + table->numNameRecords = 0; + table->format = 0; + table->storageOffset = 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_cmap */ + /* */ + /* <Description> */ + /* Loads the cmap directory in a face object. The cmaps itselves are */ + /* loaded on demand in the `ttcmap.c' module. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_cmap( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + + + error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size ); + if ( error ) + { + FT_TRACE2(( "No `cmap' table in font !\n" )); + error = SFNT_Err_CMap_Table_Missing; + goto Exit; + } + + if ( !FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) ) + FT_TRACE2(( "`cmap' table loaded\n" )); + else + { + FT_ERROR(( "`cmap' table is too short!\n" )); + face->cmap_size = 0; + } + + Exit: + return error; + } + + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_os2 */ + /* */ + /* <Description> */ + /* Loads the OS2 table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_os2( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_OS2* os2; + + const FT_Frame_Field os2_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_OS2 + + FT_FRAME_START( 78 ), + FT_FRAME_USHORT( version ), + FT_FRAME_SHORT ( xAvgCharWidth ), + FT_FRAME_USHORT( usWeightClass ), + FT_FRAME_USHORT( usWidthClass ), + FT_FRAME_SHORT ( fsType ), + FT_FRAME_SHORT ( ySubscriptXSize ), + FT_FRAME_SHORT ( ySubscriptYSize ), + FT_FRAME_SHORT ( ySubscriptXOffset ), + FT_FRAME_SHORT ( ySubscriptYOffset ), + FT_FRAME_SHORT ( ySuperscriptXSize ), + FT_FRAME_SHORT ( ySuperscriptYSize ), + FT_FRAME_SHORT ( ySuperscriptXOffset ), + FT_FRAME_SHORT ( ySuperscriptYOffset ), + FT_FRAME_SHORT ( yStrikeoutSize ), + FT_FRAME_SHORT ( yStrikeoutPosition ), + FT_FRAME_SHORT ( sFamilyClass ), + FT_FRAME_BYTE ( panose[0] ), + FT_FRAME_BYTE ( panose[1] ), + FT_FRAME_BYTE ( panose[2] ), + FT_FRAME_BYTE ( panose[3] ), + FT_FRAME_BYTE ( panose[4] ), + FT_FRAME_BYTE ( panose[5] ), + FT_FRAME_BYTE ( panose[6] ), + FT_FRAME_BYTE ( panose[7] ), + FT_FRAME_BYTE ( panose[8] ), + FT_FRAME_BYTE ( panose[9] ), + FT_FRAME_ULONG ( ulUnicodeRange1 ), + FT_FRAME_ULONG ( ulUnicodeRange2 ), + FT_FRAME_ULONG ( ulUnicodeRange3 ), + FT_FRAME_ULONG ( ulUnicodeRange4 ), + FT_FRAME_BYTE ( achVendID[0] ), + FT_FRAME_BYTE ( achVendID[1] ), + FT_FRAME_BYTE ( achVendID[2] ), + FT_FRAME_BYTE ( achVendID[3] ), + + FT_FRAME_USHORT( fsSelection ), + FT_FRAME_USHORT( usFirstCharIndex ), + FT_FRAME_USHORT( usLastCharIndex ), + FT_FRAME_SHORT ( sTypoAscender ), + FT_FRAME_SHORT ( sTypoDescender ), + FT_FRAME_SHORT ( sTypoLineGap ), + FT_FRAME_USHORT( usWinAscent ), + FT_FRAME_USHORT( usWinDescent ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_ULONG( ulCodePageRange1 ), + FT_FRAME_ULONG( ulCodePageRange2 ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra2[] = + { + FT_FRAME_START( 10 ), + FT_FRAME_SHORT ( sxHeight ), + FT_FRAME_SHORT ( sCapHeight ), + FT_FRAME_USHORT( usDefaultChar ), + FT_FRAME_USHORT( usBreakChar ), + FT_FRAME_USHORT( usMaxContext ), + FT_FRAME_END + }; + + + FT_TRACE2(( "OS/2 Table " )); + + /* We now support old Mac fonts where the OS/2 table doesn't */ + /* exist. Simply put, we set the `version' field to 0xFFFF */ + /* and test this value each time we need to access the table. */ + error = face->goto_table( face, TTAG_OS2, stream, 0 ); + if ( error ) + { + FT_TRACE2(( "is missing!\n" )); + face->os2.version = 0xFFFFU; + error = SFNT_Err_Ok; + goto Exit; + } + + os2 = &face->os2; + + if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) ) + goto Exit; + + os2->ulCodePageRange1 = 0; + os2->ulCodePageRange2 = 0; + os2->sxHeight = 0; + os2->sCapHeight = 0; + os2->usDefaultChar = 0; + os2->usBreakChar = 0; + os2->usMaxContext = 0; + + if ( os2->version >= 0x0001 ) + { + /* only version 1 tables */ + if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) ) + goto Exit; + + if ( os2->version >= 0x0002 ) + { + /* only version 2 tables */ + if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) ) + goto Exit; + } + } + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_postscript */ + /* */ + /* <Description> */ + /* Loads the Postscript table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_postscript( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_Postscript* post = &face->postscript; + + static const FT_Frame_Field post_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_Postscript + + FT_FRAME_START( 32 ), + FT_FRAME_ULONG( FormatType ), + FT_FRAME_ULONG( italicAngle ), + FT_FRAME_SHORT( underlinePosition ), + FT_FRAME_SHORT( underlineThickness ), + FT_FRAME_ULONG( isFixedPitch ), + FT_FRAME_ULONG( minMemType42 ), + FT_FRAME_ULONG( maxMemType42 ), + FT_FRAME_ULONG( minMemType1 ), + FT_FRAME_ULONG( maxMemType1 ), + FT_FRAME_END + }; + + + FT_TRACE2(( "PostScript " )); + + error = face->goto_table( face, TTAG_post, stream, 0 ); + if ( error ) + return SFNT_Err_Post_Table_Missing; + + if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) + return error; + + /* we don't load the glyph names, we do that in another */ + /* module (ttpost). */ + FT_TRACE2(( "loaded\n" )); + + return SFNT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_pclt */ + /* */ + /* <Description> */ + /* Loads the PCL 5 Table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_pclt( TT_Face face, + FT_Stream stream ) + { + static const FT_Frame_Field pclt_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_PCLT + + FT_FRAME_START( 54 ), + FT_FRAME_ULONG ( Version ), + FT_FRAME_ULONG ( FontNumber ), + FT_FRAME_USHORT( Pitch ), + FT_FRAME_USHORT( xHeight ), + FT_FRAME_USHORT( Style ), + FT_FRAME_USHORT( TypeFamily ), + FT_FRAME_USHORT( CapHeight ), + FT_FRAME_BYTES ( TypeFace, 16 ), + FT_FRAME_BYTES ( CharacterComplement, 8 ), + FT_FRAME_BYTES ( FileName, 6 ), + FT_FRAME_CHAR ( StrokeWeight ), + FT_FRAME_CHAR ( WidthType ), + FT_FRAME_BYTE ( SerifStyle ), + FT_FRAME_BYTE ( Reserved ), + FT_FRAME_END + }; + + FT_Error error; + TT_PCLT* pclt = &face->pclt; + + + FT_TRACE2(( "PCLT " )); + + /* optional table */ + error = face->goto_table( face, TTAG_PCLT, stream, 0 ); + if ( error ) + { + FT_TRACE2(( "missing (optional)\n" )); + pclt->Version = 0; + return SFNT_Err_Ok; + } + + if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) ) + goto Exit; + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_gasp */ + /* */ + /* <Description> */ + /* Loads the `gasp' table into a face object. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_gasp( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_UInt j,num_ranges; + TT_GaspRange gaspranges; + + + FT_TRACE2(( "tt_face_load_gasp: %08p\n", face )); + + /* the gasp table is optional */ + error = face->goto_table( face, TTAG_gasp, stream, 0 ); + if ( error ) + return SFNT_Err_Ok; + + if ( FT_FRAME_ENTER( 4L ) ) + goto Exit; + + face->gasp.version = FT_GET_USHORT(); + face->gasp.numRanges = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + + num_ranges = face->gasp.numRanges; + FT_TRACE3(( "number of ranges = %d\n", num_ranges )); + + if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) || + FT_FRAME_ENTER( num_ranges * 4L ) ) + goto Exit; + + face->gasp.gaspRanges = gaspranges; + + for ( j = 0; j < num_ranges; j++ ) + { + gaspranges[j].maxPPEM = FT_GET_USHORT(); + gaspranges[j].gaspFlag = FT_GET_USHORT(); + + FT_TRACE3(( " [max:%d flag:%d]", + gaspranges[j].maxPPEM, + gaspranges[j].gaspFlag )); + } + FT_TRACE3(( "\n" )); + + FT_FRAME_EXIT(); + FT_TRACE2(( "GASP loaded\n" )); + + Exit: + return error; + } + + + FT_CALLBACK_DEF( int ) + tt_kern_pair_compare( const void* a, + const void* b ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_kern */ + /* */ + /* <Description> */ + /* Loads the first kerning table with format 0 in the font. Only */ + /* accepts the first horizontal kerning table. Developers should use */ + /* the `ftxkern' extension to access other kerning tables in the font */ + /* file, if they really want to. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + +#undef TT_KERN_INDEX +#define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) + + + FT_LOCAL_DEF( FT_Error ) + tt_face_load_kern( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_UInt n, num_tables; + + + /* the kern table is optional; exit silently if it is missing */ + error = face->goto_table( face, TTAG_kern, stream, 0 ); + if ( error ) + return SFNT_Err_Ok; + + if ( FT_FRAME_ENTER( 4L ) ) + goto Exit; + + (void)FT_GET_USHORT(); /* version */ + num_tables = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + + for ( n = 0; n < num_tables; n++ ) + { + FT_UInt coverage; + FT_UInt length; + + + if ( FT_FRAME_ENTER( 6L ) ) + goto Exit; + + (void)FT_GET_USHORT(); /* version */ + length = FT_GET_USHORT() - 6; /* substract header length */ + coverage = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + + if ( coverage == 0x0001 ) + { + FT_UInt num_pairs; + TT_Kern0_Pair pair; + TT_Kern0_Pair limit; + + + /* found a horizontal format 0 kerning table! */ + if ( FT_FRAME_ENTER( 8L ) ) + goto Exit; + + num_pairs = FT_GET_USHORT(); + + /* skip the rest */ + + FT_FRAME_EXIT(); + + /* allocate array of kerning pairs */ + if ( FT_QNEW_ARRAY( face->kern_pairs, num_pairs ) || + FT_FRAME_ENTER( 6L * num_pairs ) ) + goto Exit; + + pair = face->kern_pairs; + limit = pair + num_pairs; + for ( ; pair < limit; pair++ ) + { + pair->left = FT_GET_USHORT(); + pair->right = FT_GET_USHORT(); + pair->value = FT_GET_USHORT(); + } + + FT_FRAME_EXIT(); + + face->num_kern_pairs = num_pairs; + face->kern_table_index = n; + + /* ensure that the kerning pair table is sorted (yes, some */ + /* fonts have unsorted tables!) */ + +#if 1 + if ( num_pairs > 0 ) + { + TT_Kern0_Pair pair0 = face->kern_pairs; + FT_ULong prev = TT_KERN_INDEX( pair0->left, pair0->right ); + + + for ( pair0++; pair0 < limit; pair0++ ) + { + FT_ULong next = TT_KERN_INDEX( pair0->left, pair0->right ); + + + if ( next < prev ) + goto SortIt; + + prev = next; + } + goto Exit; + + SortIt: + ft_qsort( (void*)face->kern_pairs, (int)num_pairs, + sizeof ( TT_Kern0_PairRec ), tt_kern_pair_compare ); + } +#else + { + TT_Kern0_Pair pair0 = face->kern_pairs; + FT_UInt i; + + + for ( i = 1; i < num_pairs; i++, pair0++ ) + { + if ( tt_kern_pair_compare( pair0, pair0 + 1 ) != -1 ) + { + ft_qsort( (void*)face->kern_pairs, (int)num_pairs, + sizeof ( TT_Kern0_PairRec ), tt_kern_pair_compare ); + break; + } + } + } +#endif + + goto Exit; + } + + if ( FT_STREAM_SKIP( length ) ) + goto Exit; + } + + /* no kern table found -- doesn't matter */ + face->kern_table_index = -1; + face->num_kern_pairs = 0; + face->kern_pairs = NULL; + + Exit: + return error; + } + + + FT_CALLBACK_DEF( int ) + tt_kern_pair_compare( const void* a, + const void* b ) + { + TT_Kern0_Pair pair1 = (TT_Kern0_Pair)a; + TT_Kern0_Pair pair2 = (TT_Kern0_Pair)b; + + FT_ULong index1 = TT_KERN_INDEX( pair1->left, pair1->right ); + FT_ULong index2 = TT_KERN_INDEX( pair2->left, pair2->right ); + + + return ( index1 < index2 ? -1 : + ( index1 > index2 ? 1 : 0 )); + } + + +#undef TT_KERN_INDEX + + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_hdmx */ + /* */ + /* <Description> */ + /* Loads the horizontal device metrics table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_hdmx( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + TT_Hdmx hdmx = &face->hdmx; + FT_Short num_records; + FT_Long num_glyphs; + FT_Long record_size; + + + hdmx->version = 0; + hdmx->num_records = 0; + hdmx->records = 0; + + /* this table is optional */ + error = face->goto_table( face, TTAG_hdmx, stream, 0 ); + if ( error ) + return SFNT_Err_Ok; + + if ( FT_FRAME_ENTER( 8L ) ) + goto Exit; + + hdmx->version = FT_GET_USHORT(); + num_records = FT_GET_SHORT(); + record_size = FT_GET_LONG(); + + FT_FRAME_EXIT(); + + /* Only recognize format 0 */ + if ( hdmx->version != 0 ) + goto Exit; + + if ( FT_QNEW_ARRAY( hdmx->records, num_records ) ) + goto Exit; + + hdmx->num_records = num_records; + num_glyphs = face->root.num_glyphs; + record_size -= num_glyphs + 2; + + { + TT_HdmxEntry cur = hdmx->records; + TT_HdmxEntry limit = cur + hdmx->num_records; + + + for ( ; cur < limit; cur++ ) + { + /* read record */ + if ( FT_READ_BYTE( cur->ppem ) || + FT_READ_BYTE( cur->max_width ) ) + goto Exit; + + if ( FT_QALLOC( cur->widths, num_glyphs ) || + FT_STREAM_READ( cur->widths, num_glyphs ) ) + goto Exit; + + /* skip padding bytes */ + if ( record_size > 0 && FT_STREAM_SKIP( record_size ) ) + goto Exit; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_free_hdmx */ + /* */ + /* <Description> */ + /* Frees the horizontal device metrics table. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + FT_LOCAL_DEF( void ) + tt_face_free_hdmx( TT_Face face ) + { + if ( face ) + { + FT_Int n; + FT_Memory memory = face->root.driver->root.memory; + + + for ( n = 0; n < face->hdmx.num_records; n++ ) + FT_FREE( face->hdmx.records[n].widths ); + + FT_FREE( face->hdmx.records ); + face->hdmx.num_records = 0; + } + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttload.h b/Utilities/vtkfreetype/src/sfnt/ttload.h new file mode 100644 index 0000000..27c41b5 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttload.h @@ -0,0 +1,137 @@ +/***************************************************************************/ +/* */ +/* ttload.h */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTLOAD_H__ +#define __TTLOAD_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_TRUETYPE_TYPES_H + + +FT_BEGIN_HEADER + + + FT_LOCAL( TT_Table ) + tt_face_lookup_table( TT_Face face, + FT_ULong tag ); + + FT_LOCAL( FT_Error ) + tt_face_goto_table( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ); + + + FT_LOCAL( FT_Error ) + tt_face_load_sfnt_header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header sfnt ); + + FT_LOCAL( FT_Error ) + tt_face_load_directory( TT_Face face, + FT_Stream stream, + SFNT_Header sfnt ); + + FT_LOCAL( FT_Error ) + tt_face_load_any( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + FT_LOCAL( FT_Error ) + tt_face_load_header( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_metrics_header( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + FT_LOCAL( FT_Error ) + tt_face_load_cmap( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_max_profile( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_names( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_os2( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_postscript( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_hdmx( TT_Face face, + FT_Stream stream ); + + FT_LOCAL( FT_Error ) + tt_face_load_pclt( TT_Face face, + FT_Stream stream ); + + FT_LOCAL( void ) + tt_face_free_names( TT_Face face ); + + + FT_LOCAL( void ) + tt_face_free_hdmx ( TT_Face face ); + + + FT_LOCAL( FT_Error ) + tt_face_load_kern( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + tt_face_load_gasp( TT_Face face, + FT_Stream stream ); + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + FT_LOCAL( FT_Error ) + tt_face_load_bitmap_header( TT_Face face, + FT_Stream stream ); + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + +FT_END_HEADER + +#endif /* __TTLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttpost.c b/Utilities/vtkfreetype/src/sfnt/ttpost.c new file mode 100644 index 0000000..3d526db --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttpost.c @@ -0,0 +1,521 @@ +/***************************************************************************/ +/* */ +/* ttpost.c */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* The post table is not completely loaded by the core engine. This */ + /* file loads the missing PS glyph names and implements an API to access */ + /* them. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_TAGS_H +#include "ttpost.h" +#include "ttload.h" + +#include "sferrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttpost + + + /* If this configuration macro is defined, we rely on the `PSNames' */ + /* module to grab the glyph names. */ + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + +#include FT_SERVICE_POSTSCRIPT_CMAPS_H + +#define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) ) + + +#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + /* Otherwise, we ignore the `PSNames' module, and provide our own */ + /* table of Mac names. Thus, it is possible to build a version of */ + /* FreeType without the Type 1 driver & PSNames module. */ + +#define MAC_NAME( x ) tt_post_default_names[x] + + /* the 258 default Mac PS glyph names */ + + static const FT_String* tt_post_default_names[258] = + { + /* 0 */ + ".notdef", ".null", "CR", "space", "exclam", + "quotedbl", "numbersign", "dollar", "percent", "ampersand", + /* 10 */ + "quotesingle", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", + /* 20 */ + "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "colon", + /* 30 */ + "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", + /* 40 */ + "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", + /* 50 */ + "O", "P", "Q", "R", "S", + "T", "U", "V", "W", "X", + /* 60 */ + "Y", "Z", "bracketleft", "backslash", "bracketright", + "asciicircum", "underscore", "grave", "a", "b", + /* 70 */ + "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", + /* 80 */ + "m", "n", "o", "p", "q", + "r", "s", "t", "u", "v", + /* 90 */ + "w", "x", "y", "z", "braceleft", + "bar", "braceright", "asciitilde", "Adieresis", "Aring", + /* 100 */ + "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", + "aacute", "agrave", "acircumflex", "adieresis", "atilde", + /* 110 */ + "aring", "ccedilla", "eacute", "egrave", "ecircumflex", + "edieresis", "iacute", "igrave", "icircumflex", "idieresis", + /* 120 */ + "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", + "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", + /* 130 */ + "dagger", "degree", "cent", "sterling", "section", + "bullet", "paragraph", "germandbls", "registered", "copyright", + /* 140 */ + "trademark", "acute", "dieresis", "notequal", "AE", + "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", + /* 150 */ + "yen", "mu", "partialdiff", "summation", "product", + "pi", "integral", "ordfeminine", "ordmasculine", "Omega", + /* 160 */ + "ae", "oslash", "questiondown", "exclamdown", "logicalnot", + "radical", "florin", "approxequal", "Delta", "guillemotleft", + /* 170 */ + "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", + "Otilde", "OE", "oe", "endash", "emdash", + /* 180 */ + "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", + "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", + /* 190 */ + "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", + "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", + /* 200 */ + "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", + "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", + /* 210 */ + "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", + "dotlessi", "circumflex", "tilde", "macron", "breve", + /* 220 */ + "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", + "caron", "Lslash", "lslash", "Scaron", "scaron", + /* 230 */ + "Zcaron", "zcaron", "brokenbar", "Eth", "eth", + "Yacute", "yacute", "Thorn", "thorn", "minus", + /* 240 */ + "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", + "onequarter", "threequarters", "franc", "Gbreve", "gbreve", + /* 250 */ + "Idot", "Scedilla", "scedilla", "Cacute", "cacute", + "Ccaron", "ccaron", "dmacron", + }; + + +#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + static FT_Error + load_format_20( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + FT_Error error; + + FT_Int num_glyphs; + FT_UShort num_names; + + FT_UShort* glyph_indices = 0; + FT_Char** name_strings = 0; + + + if ( FT_READ_USHORT( num_glyphs ) ) + goto Exit; + + /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ + /* than the value in the maxp table (cf. cyberbit.ttf). */ + + /* There already exist fonts which have more than 32768 glyph names */ + /* in this table, so the test for this threshold has been dropped. */ + + if ( num_glyphs > face->root.num_glyphs ) + { + error = SFNT_Err_Invalid_File_Format; + goto Exit; + } + + /* load the indices */ + { + FT_Int n; + + + if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs * 2L ) ) + goto Fail; + + for ( n = 0; n < num_glyphs; n++ ) + glyph_indices[n] = FT_GET_USHORT(); + + FT_FRAME_EXIT(); + } + + /* compute number of names stored in table */ + { + FT_Int n; + + + num_names = 0; + + for ( n = 0; n < num_glyphs; n++ ) + { + FT_Int idx; + + + idx = glyph_indices[n]; + if ( idx >= 258 ) + { + idx -= 257; + if ( idx > num_names ) + num_names = (FT_UShort)idx; + } + } + } + + /* now load the name strings */ + { + FT_UShort n; + + + if ( FT_NEW_ARRAY( name_strings, num_names ) ) + goto Fail; + + for ( n = 0; n < num_names; n++ ) + { + FT_UInt len; + + + if ( FT_READ_BYTE ( len ) || + FT_NEW_ARRAY( name_strings[n], len + 1 ) || + FT_STREAM_READ ( name_strings[n], len ) ) + goto Fail1; + + name_strings[n][len] = '\0'; + } + } + + /* all right, set table fields and exit successfuly */ + { + TT_Post_20 table = &face->postscript_names.names.format_20; + + + table->num_glyphs = (FT_UShort)num_glyphs; + table->num_names = (FT_UShort)num_names; + table->glyph_indices = glyph_indices; + table->glyph_names = name_strings; + } + return SFNT_Err_Ok; + + Fail1: + { + FT_UShort n; + + + for ( n = 0; n < num_names; n++ ) + FT_FREE( name_strings[n] ); + } + + Fail: + FT_FREE( name_strings ); + FT_FREE( glyph_indices ); + + Exit: + return error; + } + + + static FT_Error + load_format_25( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + FT_Error error; + + FT_Int num_glyphs; + FT_Char* offset_table = 0; + + + /* UNDOCUMENTED! This value appears only in the Apple TT specs. */ + if ( FT_READ_USHORT( num_glyphs ) ) + goto Exit; + + /* check the number of glyphs */ + if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 ) + { + error = SFNT_Err_Invalid_File_Format; + goto Exit; + } + + if ( FT_ALLOC( offset_table, num_glyphs ) || + FT_STREAM_READ( offset_table, num_glyphs ) ) + goto Fail; + + /* now check the offset table */ + { + FT_Int n; + + + for ( n = 0; n < num_glyphs; n++ ) + { + FT_Long idx = (FT_Long)n + offset_table[n]; + + + if ( idx < 0 || idx > num_glyphs ) + { + error = SFNT_Err_Invalid_File_Format; + goto Fail; + } + } + } + + /* OK, set table fields and exit successfuly */ + { + TT_Post_25 table = &face->postscript_names.names.format_25; + + + table->num_glyphs = (FT_UShort)num_glyphs; + table->offsets = offset_table; + } + + return SFNT_Err_Ok; + + Fail: + FT_FREE( offset_table ); + + Exit: + return error; + } + + + static FT_Error + load_post_names( TT_Face face ) + { + FT_Stream stream; + FT_Error error; + FT_Fixed format; + + + /* get a stream for the face's resource */ + stream = face->root.stream; + + /* seek to the beginning of the PS names table */ + error = face->goto_table( face, TTAG_post, stream, 0 ); + if ( error ) + goto Exit; + + format = face->postscript.FormatType; + + /* go to beginning of subtable */ + if ( FT_STREAM_SKIP( 32 ) ) + goto Exit; + + /* now read postscript table */ + if ( format == 0x00020000L ) + error = load_format_20( face, stream ); + else if ( format == 0x00028000L ) + error = load_format_25( face, stream ); + else + error = SFNT_Err_Invalid_File_Format; + + face->postscript_names.loaded = 1; + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + tt_face_free_ps_names( TT_Face face ) + { + FT_Memory memory = face->root.memory; + TT_Post_Names names = &face->postscript_names; + FT_Fixed format; + + + if ( names->loaded ) + { + format = face->postscript.FormatType; + + if ( format == 0x00020000L ) + { + TT_Post_20 table = &names->names.format_20; + FT_UShort n; + + + FT_FREE( table->glyph_indices ); + table->num_glyphs = 0; + + for ( n = 0; n < table->num_names; n++ ) + FT_FREE( table->glyph_names[n] ); + + FT_FREE( table->glyph_names ); + table->num_names = 0; + } + else if ( format == 0x00028000L ) + { + TT_Post_25 table = &names->names.format_25; + + + FT_FREE( table->offsets ); + table->num_glyphs = 0; + } + } + names->loaded = 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_get_ps_name */ + /* */ + /* <Description> */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* <Input> */ + /* face :: A handle to the parent face. */ + /* */ + /* idx :: The glyph index. */ + /* */ + /* PSname :: The address of a string pointer. Will be NULL in case */ + /* of error, otherwise it is a pointer to the glyph name. */ + /* */ + /* You must not modify the returned string! */ + /* */ + /* <Output> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_get_ps_name( TT_Face face, + FT_UInt idx, + FT_String** PSname ) + { + FT_Error error; + TT_Post_Names names; + FT_Fixed format; + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + FT_Service_PsCMaps psnames; +#endif + + + if ( !face ) + return SFNT_Err_Invalid_Face_Handle; + + if ( idx >= (FT_UInt)face->root.num_glyphs ) + return SFNT_Err_Invalid_Glyph_Index; + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + psnames = (FT_Service_PsCMaps)face->psnames; + if ( !psnames ) + return SFNT_Err_Unimplemented_Feature; +#endif + + names = &face->postscript_names; + + /* `.notdef' by default */ + *PSname = MAC_NAME( 0 ); + + format = face->postscript.FormatType; + + if ( format == 0x00010000L ) + { + if ( idx < 258 ) /* paranoid checking */ + *PSname = MAC_NAME( idx ); + } + else if ( format == 0x00020000L ) + { + TT_Post_20 table = &names->names.format_20; + + + if ( !names->loaded ) + { + error = load_post_names( face ); + if ( error ) + goto End; + } + + if ( idx < (FT_UInt)table->num_glyphs ) + { + FT_UShort name_index = table->glyph_indices[idx]; + + + if ( name_index < 258 ) + *PSname = MAC_NAME( name_index ); + else + *PSname = (FT_String*)table->glyph_names[name_index - 258]; + } + } + else if ( format == 0x00028000L ) + { + TT_Post_25 table = &names->names.format_25; + + + if ( !names->loaded ) + { + error = load_post_names( face ); + if ( error ) + goto End; + } + + if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */ + { + idx += table->offsets[idx]; + *PSname = MAC_NAME( idx ); + } + } + + /* nothing to do for format == 0x00030000L */ + + End: + return SFNT_Err_Ok; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttpost.h b/Utilities/vtkfreetype/src/sfnt/ttpost.h new file mode 100644 index 0000000..6f06d75 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttpost.h @@ -0,0 +1,46 @@ +/***************************************************************************/ +/* */ +/* ttpost.h */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTPOST_H__ +#define __TTPOST_H__ + + +#include <ft2build.h> +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_TRUETYPE_TYPES_H + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + tt_face_get_ps_name( TT_Face face, + FT_UInt idx, + FT_String** PSname ); + + FT_LOCAL( void ) + tt_face_free_ps_names( TT_Face face ); + + +FT_END_HEADER + +#endif /* __TTPOST_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttsbit.c b/Utilities/vtkfreetype/src/sfnt/ttsbit.c new file mode 100644 index 0000000..444c27a --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttsbit.c @@ -0,0 +1,1467 @@ +/***************************************************************************/ +/* */ +/* ttsbit.c */ +/* */ +/* TrueType and OpenType embedded bitmap support (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_TAGS_H +#include "ttsbit.h" + +#include "sferrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttsbit + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* blit_sbit */ + /* */ + /* <Description> */ + /* Blits a bitmap from an input stream into a given target. Supports */ + /* x and y offsets as well as byte padded lines. */ + /* */ + /* <Input> */ + /* target :: The target bitmap/pixmap. */ + /* */ + /* source :: The input packed bitmap data. */ + /* */ + /* line_bits :: The number of bits per line. */ + /* */ + /* byte_padded :: A flag which is true if lines are byte-padded. */ + /* */ + /* x_offset :: The horizontal offset. */ + /* */ + /* y_offset :: The vertical offset. */ + /* */ + /* <Note> */ + /* IMPORTANT: The x and y offsets are relative to the top corner of */ + /* the target bitmap (unlike the normal TrueType */ + /* convention). A positive y offset indicates a downwards */ + /* direction! */ + /* */ + static void + blit_sbit( FT_Bitmap* target, + FT_Byte* source, + FT_Int line_bits, + FT_Bool byte_padded, + FT_Int x_offset, + FT_Int y_offset ) + { + FT_Byte* line_buff; + FT_Int line_incr; + FT_Int height; + + FT_UShort acc; + FT_UInt loaded; + + + /* first of all, compute starting write position */ + line_incr = target->pitch; + line_buff = target->buffer; + + if ( line_incr < 0 ) + line_buff -= line_incr * ( target->rows - 1 ); + + line_buff += ( x_offset >> 3 ) + y_offset * line_incr; + + /***********************************************************************/ + /* */ + /* We use the extra-classic `accumulator' trick to extract the bits */ + /* from the source byte stream. */ + /* */ + /* Namely, the variable `acc' is a 16-bit accumulator containing the */ + /* last `loaded' bits from the input stream. The bits are shifted to */ + /* the upmost position in `acc'. */ + /* */ + /***********************************************************************/ + + acc = 0; /* clear accumulator */ + loaded = 0; /* no bits were loaded */ + + for ( height = target->rows; height > 0; height-- ) + { + FT_Byte* cur = line_buff; /* current write cursor */ + FT_Int count = line_bits; /* # of bits to extract per line */ + FT_Byte shift = (FT_Byte)( x_offset & 7 ); /* current write shift */ + FT_Byte space = (FT_Byte)( 8 - shift ); + + + /* first of all, read individual source bytes */ + if ( count >= 8 ) + { + count -= 8; + { + do + { + FT_Byte val; + + + /* ensure that there are at least 8 bits in the accumulator */ + if ( loaded < 8 ) + { + acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); + loaded += 8; + } + + /* now write one byte */ + val = (FT_Byte)( acc >> 8 ); + if ( shift ) + { + cur[0] |= (FT_Byte)( val >> shift ); + cur[1] |= (FT_Byte)( val << space ); + } + else + cur[0] |= val; + + cur++; + acc <<= 8; /* remove bits from accumulator */ + loaded -= 8; + count -= 8; + + } while ( count >= 0 ); + } + + /* restore `count' to correct value */ + count += 8; + } + + /* now write remaining bits (count < 8) */ + if ( count > 0 ) + { + FT_Byte val; + + + /* ensure that there are at least `count' bits in the accumulator */ + if ( (FT_Int)loaded < count ) + { + acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); + loaded += 8; + } + + /* now write remaining bits */ + val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) ); + cur[0] |= (FT_Byte)( val >> shift ); + + if ( count > space ) + cur[1] |= (FT_Byte)( val << space ); + + acc <<= count; + loaded -= count; + } + + /* now, skip to next line */ + if ( byte_padded ) + { + acc = 0; + loaded = 0; /* clear accumulator on byte-padded lines */ + } + + line_buff += line_incr; + } + } + + + const FT_Frame_Field sbit_metrics_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_SBit_MetricsRec + + FT_FRAME_START( 8 ), + FT_FRAME_BYTE( height ), + FT_FRAME_BYTE( width ), + + FT_FRAME_CHAR( horiBearingX ), + FT_FRAME_CHAR( horiBearingY ), + FT_FRAME_BYTE( horiAdvance ), + + FT_FRAME_CHAR( vertBearingX ), + FT_FRAME_CHAR( vertBearingY ), + FT_FRAME_BYTE( vertAdvance ), + FT_FRAME_END + }; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_SBit_Const_Metrics */ + /* */ + /* <Description> */ + /* Loads the metrics for `EBLC' index tables format 2 and 5. */ + /* */ + /* <Input> */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Load_SBit_Const_Metrics( TT_SBit_Range range, + FT_Stream stream ) + { + FT_Error error; + + + if ( FT_READ_ULONG( range->image_size ) ) + return error; + + return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_SBit_Range_Codes */ + /* */ + /* <Description> */ + /* Loads the range codes for `EBLC' index tables format 4 and 5. */ + /* */ + /* <Input> */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* load_offsets :: A flag whether to load the glyph offset table. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Load_SBit_Range_Codes( TT_SBit_Range range, + FT_Stream stream, + FT_Bool load_offsets ) + { + FT_Error error; + FT_ULong count, n, size; + FT_Memory memory = stream->memory; + + + if ( FT_READ_ULONG( count ) ) + goto Exit; + + range->num_glyphs = count; + + /* Allocate glyph offsets table if needed */ + if ( load_offsets ) + { + if ( FT_NEW_ARRAY( range->glyph_offsets, count ) ) + goto Exit; + + size = count * 4L; + } + else + size = count * 2L; + + /* Allocate glyph codes table and access frame */ + if ( FT_NEW_ARRAY ( range->glyph_codes, count ) || + FT_FRAME_ENTER( size ) ) + goto Exit; + + for ( n = 0; n < count; n++ ) + { + range->glyph_codes[n] = FT_GET_USHORT(); + + if ( load_offsets ) + range->glyph_offsets[n] = (FT_ULong)range->image_offset + + FT_GET_USHORT(); + } + + FT_FRAME_EXIT(); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_SBit_Range */ + /* */ + /* <Description> */ + /* Loads a given `EBLC' index/range table. */ + /* */ + /* <Input> */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Load_SBit_Range( TT_SBit_Range range, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + + switch( range->index_format ) + { + case 1: /* variable metrics with 4-byte offsets */ + case 3: /* variable metrics with 2-byte offsets */ + { + FT_ULong num_glyphs, n; + FT_Int size_elem; + FT_Bool large = FT_BOOL( range->index_format == 1 ); + + + num_glyphs = range->last_glyph - range->first_glyph + 1L; + range->num_glyphs = num_glyphs; + num_glyphs++; /* XXX: BEWARE - see spec */ + + size_elem = large ? 4 : 2; + + if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) || + FT_FRAME_ENTER( num_glyphs * size_elem ) ) + goto Exit; + + for ( n = 0; n < num_glyphs; n++ ) + range->glyph_offsets[n] = (FT_ULong)( range->image_offset + + ( large ? FT_GET_ULONG() + : FT_GET_USHORT() ) ); + FT_FRAME_EXIT(); + } + break; + + case 2: /* all glyphs have identical metrics */ + error = Load_SBit_Const_Metrics( range, stream ); + break; + + case 4: + error = Load_SBit_Range_Codes( range, stream, 1 ); + break; + + case 5: + error = Load_SBit_Const_Metrics( range, stream ) || + Load_SBit_Range_Codes( range, stream, 0 ); + break; + + default: + error = SFNT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_sbit_strikes */ + /* */ + /* <Description> */ + /* Loads the table of embedded bitmap sizes for this face. */ + /* */ + /* <Input> */ + /* face :: The target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_sbit_strikes( TT_Face face, + FT_Stream stream ) + { + FT_Error error = 0; + FT_Memory memory = stream->memory; + FT_Fixed version; + FT_ULong num_strikes; + FT_ULong table_base; + + const FT_Frame_Field sbit_line_metrics_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_SBit_LineMetricsRec + + /* no FT_FRAME_START */ + FT_FRAME_CHAR( ascender ), + FT_FRAME_CHAR( descender ), + FT_FRAME_BYTE( max_width ), + + FT_FRAME_CHAR( caret_slope_numerator ), + FT_FRAME_CHAR( caret_slope_denominator ), + FT_FRAME_CHAR( caret_offset ), + + FT_FRAME_CHAR( min_origin_SB ), + FT_FRAME_CHAR( min_advance_SB ), + FT_FRAME_CHAR( max_before_BL ), + FT_FRAME_CHAR( min_after_BL ), + FT_FRAME_CHAR( pads[0] ), + FT_FRAME_CHAR( pads[1] ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_start_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_SBit_StrikeRec + + /* no FT_FRAME_START */ + FT_FRAME_ULONG( ranges_offset ), + FT_FRAME_SKIP_LONG, + FT_FRAME_ULONG( num_ranges ), + FT_FRAME_ULONG( color_ref ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_end_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_USHORT( start_glyph ), + FT_FRAME_USHORT( end_glyph ), + FT_FRAME_BYTE ( x_ppem ), + FT_FRAME_BYTE ( y_ppem ), + FT_FRAME_BYTE ( bit_depth ), + FT_FRAME_CHAR ( flags ), + FT_FRAME_END + }; + + + face->num_sbit_strikes = 0; + + /* this table is optional */ + error = face->goto_table( face, TTAG_EBLC, stream, 0 ); + if ( error ) + error = face->goto_table( face, TTAG_bloc, stream, 0 ); + if ( error ) + goto Exit; + + table_base = FT_STREAM_POS(); + if ( FT_FRAME_ENTER( 8L ) ) + goto Exit; + + version = FT_GET_LONG(); + num_strikes = FT_GET_ULONG(); + + FT_FRAME_EXIT(); + + /* check version number and strike count */ + if ( version != 0x00020000L || + num_strikes >= 0x10000L ) + { + FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version!\n" )); + error = SFNT_Err_Invalid_File_Format; + + goto Exit; + } + + /* allocate the strikes table */ + if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) ) + goto Exit; + + face->num_sbit_strikes = num_strikes; + + /* now read each strike table separately */ + { + TT_SBit_Strike strike = face->sbit_strikes; + FT_ULong count = num_strikes; + + + if ( FT_FRAME_ENTER( 48L * num_strikes ) ) + goto Exit; + + while ( count > 0 ) + { + if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) || + FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) || + FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) || + FT_STREAM_READ_FIELDS( strike_end_fields, strike ) ) + break; + + count--; + strike++; + } + + FT_FRAME_EXIT(); + } + + /* allocate the index ranges for each strike table */ + { + TT_SBit_Strike strike = face->sbit_strikes; + FT_ULong count = num_strikes; + + + while ( count > 0 ) + { + TT_SBit_Range range; + FT_ULong count2 = strike->num_ranges; + + + if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) ) + goto Exit; + + /* read each range */ + if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) || + FT_FRAME_ENTER( strike->num_ranges * 8L ) ) + goto Exit; + + range = strike->sbit_ranges; + while ( count2 > 0 ) + { + range->first_glyph = FT_GET_USHORT(); + range->last_glyph = FT_GET_USHORT(); + range->table_offset = table_base + strike->ranges_offset + + FT_GET_ULONG(); + count2--; + range++; + } + + FT_FRAME_EXIT(); + + /* Now, read each index table */ + count2 = strike->num_ranges; + range = strike->sbit_ranges; + while ( count2 > 0 ) + { + /* Read the header */ + if ( FT_STREAM_SEEK( range->table_offset ) || + FT_FRAME_ENTER( 8L ) ) + goto Exit; + + range->index_format = FT_GET_USHORT(); + range->image_format = FT_GET_USHORT(); + range->image_offset = FT_GET_ULONG(); + + FT_FRAME_EXIT(); + + error = Load_SBit_Range( range, stream ); + if ( error ) + goto Exit; + + count2--; + range++; + } + + count--; + strike++; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_free_sbit_strikes */ + /* */ + /* <Description> */ + /* Releases the embedded bitmap tables. */ + /* */ + /* <Input> */ + /* face :: The target face object. */ + /* */ + FT_LOCAL_DEF( void ) + tt_face_free_sbit_strikes( TT_Face face ) + { + FT_Memory memory = face->root.memory; + TT_SBit_Strike strike = face->sbit_strikes; + TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes; + + + if ( strike ) + { + for ( ; strike < strike_limit; strike++ ) + { + TT_SBit_Range range = strike->sbit_ranges; + TT_SBit_Range range_limit = range + strike->num_ranges; + + + if ( range ) + { + for ( ; range < range_limit; range++ ) + { + /* release the glyph offsets and codes tables */ + /* where appropriate */ + FT_FREE( range->glyph_offsets ); + FT_FREE( range->glyph_codes ); + } + } + FT_FREE( strike->sbit_ranges ); + strike->num_ranges = 0; + } + FT_FREE( face->sbit_strikes ); + } + face->num_sbit_strikes = 0; + } + + + FT_LOCAL_DEF( FT_Error ) + tt_face_set_sbit_strike( TT_Face face, + FT_UInt x_ppem, + FT_UInt y_ppem, + FT_ULong *astrike_index ) + { + FT_ULong i; + + + if ( x_ppem > 255 || + y_ppem < 1 || y_ppem > 255 ) + return SFNT_Err_Invalid_PPem; + + for ( i = 0; i < face->num_sbit_strikes; i++ ) + { + if ( ( (FT_UInt)face->sbit_strikes[i].y_ppem == y_ppem ) && + ( ( x_ppem == 0 ) || + ( (FT_UInt)face->sbit_strikes[i].x_ppem == x_ppem ) ) ) + { + *astrike_index = i; + return SFNT_Err_Ok; + } + } + + return SFNT_Err_Invalid_PPem; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* find_sbit_range */ + /* */ + /* <Description> */ + /* Scans a given strike's ranges and return, for a given glyph */ + /* index, the corresponding sbit range, and `EBDT' offset. */ + /* */ + /* <Input> */ + /* glyph_index :: The glyph index. */ + /* */ + /* strike :: The source/current sbit strike. */ + /* */ + /* <Output> */ + /* arange :: The sbit range containing the glyph index. */ + /* */ + /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means the glyph index was found. */ + /* */ + static FT_Error + find_sbit_range( FT_UInt glyph_index, + TT_SBit_Strike strike, + TT_SBit_Range *arange, + FT_ULong *aglyph_offset ) + { + TT_SBit_RangeRec *range, *range_limit; + + + /* check whether the glyph index is within this strike's */ + /* glyph range */ + if ( glyph_index < (FT_UInt)strike->start_glyph || + glyph_index > (FT_UInt)strike->end_glyph ) + goto Fail; + + /* scan all ranges in strike */ + range = strike->sbit_ranges; + range_limit = range + strike->num_ranges; + if ( !range ) + goto Fail; + + for ( ; range < range_limit; range++ ) + { + if ( glyph_index >= (FT_UInt)range->first_glyph && + glyph_index <= (FT_UInt)range->last_glyph ) + { + FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph ); + + + switch ( range->index_format ) + { + case 1: + case 3: + *aglyph_offset = range->glyph_offsets[delta]; + break; + + case 2: + *aglyph_offset = range->image_offset + + range->image_size * delta; + break; + + case 4: + case 5: + { + FT_ULong n; + + + for ( n = 0; n < range->num_glyphs; n++ ) + { + if ( (FT_UInt)range->glyph_codes[n] == glyph_index ) + { + if ( range->index_format == 4 ) + *aglyph_offset = range->glyph_offsets[n]; + else + *aglyph_offset = range->image_offset + + n * range->image_size; + goto Found; + } + } + } + + /* fall-through */ + default: + goto Fail; + } + + Found: + /* return successfully! */ + *arange = range; + return 0; + } + } + + Fail: + *arange = 0; + *aglyph_offset = 0; + + return SFNT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_find_sbit_image */ + /* */ + /* <Description> */ + /* Checks whether an embedded bitmap (an `sbit') exists for a given */ + /* glyph, at a given strike. */ + /* */ + /* <Input> */ + /* face :: The target face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* strike_index :: The current strike index. */ + /* */ + /* <Output> */ + /* arange :: The SBit range containing the glyph index. */ + /* */ + /* astrike :: The SBit strike containing the glyph index. */ + /* */ + /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. Returns */ + /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */ + /* glyph. */ + /* */ + FT_LOCAL( FT_Error ) + tt_find_sbit_image( TT_Face face, + FT_UInt glyph_index, + FT_ULong strike_index, + TT_SBit_Range *arange, + TT_SBit_Strike *astrike, + FT_ULong *aglyph_offset ) + { + FT_Error error; + TT_SBit_Strike strike; + + + if ( !face->sbit_strikes || + ( face->num_sbit_strikes <= strike_index ) ) + goto Fail; + + strike = &face->sbit_strikes[strike_index]; + + error = find_sbit_range( glyph_index, strike, + arange, aglyph_offset ); + if ( error ) + goto Fail; + + *astrike = strike; + + return SFNT_Err_Ok; + + Fail: + /* no embedded bitmap for this glyph in face */ + *arange = 0; + *astrike = 0; + *aglyph_offset = 0; + + return SFNT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_load_sbit_metrics */ + /* */ + /* <Description> */ + /* Gets the big metrics for a given SBit. */ + /* */ + /* <Input> */ + /* stream :: The input stream. */ + /* */ + /* range :: The SBit range containing the glyph. */ + /* */ + /* <Output> */ + /* big_metrics :: A big SBit metrics structure for the glyph. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* The stream cursor must be positioned at the glyph's offset within */ + /* the `EBDT' table before the call. */ + /* */ + /* If the image format uses variable metrics, the stream cursor is */ + /* positioned just after the metrics header in the `EBDT' table on */ + /* function exit. */ + /* */ + FT_LOCAL( FT_Error ) + tt_load_sbit_metrics( FT_Stream stream, + TT_SBit_Range range, + TT_SBit_Metrics metrics ) + { + FT_Error error = SFNT_Err_Ok; + + + switch ( range->image_format ) + { + case 1: + case 2: + case 8: + /* variable small metrics */ + { + TT_SBit_SmallMetricsRec smetrics; + + const FT_Frame_Field sbit_small_metrics_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE TT_SBit_SmallMetricsRec + + FT_FRAME_START( 5 ), + FT_FRAME_BYTE( height ), + FT_FRAME_BYTE( width ), + FT_FRAME_CHAR( bearingX ), + FT_FRAME_CHAR( bearingY ), + FT_FRAME_BYTE( advance ), + FT_FRAME_END + }; + + + /* read small metrics */ + if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) ) + goto Exit; + + /* convert it to a big metrics */ + metrics->height = smetrics.height; + metrics->width = smetrics.width; + metrics->horiBearingX = smetrics.bearingX; + metrics->horiBearingY = smetrics.bearingY; + metrics->horiAdvance = smetrics.advance; + + /* these metrics are made up at a higher level when */ + /* needed. */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + } + break; + + case 6: + case 7: + case 9: + /* variable big metrics */ + if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) ) + goto Exit; + break; + + case 5: + default: /* constant metrics */ + if ( range->index_format == 2 || range->index_format == 5 ) + *metrics = range->metrics; + else + return SFNT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* crop_bitmap */ + /* */ + /* <Description> */ + /* Crops a bitmap to its tightest bounding box, and adjusts its */ + /* metrics. */ + /* */ + /* <InOut> */ + /* map :: The bitmap. */ + /* */ + /* metrics :: The corresponding metrics structure. */ + /* */ + static void + crop_bitmap( FT_Bitmap* map, + TT_SBit_Metrics metrics ) + { + /***********************************************************************/ + /* */ + /* In this situation, some bounding boxes of embedded bitmaps are too */ + /* large. We need to crop it to a reasonable size. */ + /* */ + /* --------- */ + /* | | ----- */ + /* | *** | |***| */ + /* | * | | * | */ + /* | * | ------> | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | *** | |***| */ + /* --------- ----- */ + /* */ + /***********************************************************************/ + + FT_Int rows, count; + FT_Long line_len; + FT_Byte* line; + + + /***********************************************************************/ + /* */ + /* first of all, check the top-most lines of the bitmap, and remove */ + /* them if they're empty. */ + /* */ + { + line = (FT_Byte*)map->buffer; + rows = map->rows; + line_len = map->pitch; + + + for ( count = 0; count < rows; count++ ) + { + FT_Byte* cur = line; + FT_Byte* limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Top; + + /* the current line was empty - skip to next one */ + line = limit; + } + + Found_Top: + /* check that we have at least one filled line */ + if ( count >= rows ) + goto Empty_Bitmap; + + /* now, crop the empty upper lines */ + if ( count > 0 ) + { + line = (FT_Byte*)map->buffer; + + FT_MEM_MOVE( line, line + count * line_len, + ( rows - count ) * line_len ); + + metrics->height = (FT_Byte)( metrics->height - count ); + metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count ); + metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count ); + + map->rows -= count; + rows -= count; + } + } + + /***********************************************************************/ + /* */ + /* second, crop the lower lines */ + /* */ + { + line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len; + + for ( count = 0; count < rows; count++ ) + { + FT_Byte* cur = line; + FT_Byte* limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Bottom; + + /* the current line was empty - skip to previous one */ + line -= line_len; + } + + Found_Bottom: + if ( count > 0 ) + { + metrics->height = (FT_Byte)( metrics->height - count ); + rows -= count; + map->rows -= count; + } + } + + /***********************************************************************/ + /* */ + /* third, get rid of the space on the left side of the glyph */ + /* */ + do + { + FT_Byte* limit; + + + line = (FT_Byte*)map->buffer; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + if ( line[0] & 0x80 ) + goto Found_Left; + + /* shift the whole glyph one pixel to the left */ + line = (FT_Byte*)map->buffer; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + { + FT_Int n, width = map->width; + FT_Byte old; + FT_Byte* cur = line; + + + old = (FT_Byte)(cur[0] << 1); + for ( n = 8; n < width; n += 8 ) + { + FT_Byte val; + + + val = cur[1]; + cur[0] = (FT_Byte)( old | ( val >> 7 ) ); + old = (FT_Byte)( val << 1 ); + cur++; + } + cur[0] = old; + } + + map->width--; + metrics->horiBearingX++; + metrics->vertBearingX++; + metrics->width--; + + } while ( map->width > 0 ); + + Found_Left: + + /***********************************************************************/ + /* */ + /* finally, crop the bitmap width to get rid of the space on the right */ + /* side of the glyph. */ + /* */ + do + { + FT_Int right = map->width - 1; + FT_Byte* limit; + FT_Byte mask; + + + line = (FT_Byte*)map->buffer + ( right >> 3 ); + limit = line + rows * line_len; + mask = (FT_Byte)( 0x80 >> ( right & 7 ) ); + + for ( ; line < limit; line += line_len ) + if ( line[0] & mask ) + goto Found_Right; + + /* crop the whole glyph to the right */ + map->width--; + metrics->width--; + + } while ( map->width > 0 ); + + Found_Right: + /* all right, the bitmap was cropped */ + return; + + Empty_Bitmap: + map->width = 0; + map->rows = 0; + map->pitch = 0; + map->pixel_mode = FT_PIXEL_MODE_MONO; + } + + + static FT_Error + Load_SBit_Single( FT_Bitmap* map, + FT_Int x_offset, + FT_Int y_offset, + FT_Int pix_bits, + FT_UShort image_format, + TT_SBit_Metrics metrics, + FT_Stream stream ) + { + FT_Error error; + + + /* check that the source bitmap fits into the target pixmap */ + if ( x_offset < 0 || x_offset + metrics->width > map->width || + y_offset < 0 || y_offset + metrics->height > map->rows ) + { + error = SFNT_Err_Invalid_Argument; + + goto Exit; + } + + { + FT_Int glyph_width = metrics->width; + FT_Int glyph_height = metrics->height; + FT_Int glyph_size; + FT_Int line_bits = pix_bits * glyph_width; + FT_Bool pad_bytes = 0; + + + /* compute size of glyph image */ + switch ( image_format ) + { + case 1: /* byte-padded formats */ + case 6: + { + FT_Int line_length; + + + switch ( pix_bits ) + { + case 1: + line_length = ( glyph_width + 7 ) >> 3; + break; + case 2: + line_length = ( glyph_width + 3 ) >> 2; + break; + case 4: + line_length = ( glyph_width + 1 ) >> 1; + break; + default: + line_length = glyph_width; + } + + glyph_size = glyph_height * line_length; + pad_bytes = 1; + } + break; + + case 2: + case 5: + case 7: + line_bits = glyph_width * pix_bits; + glyph_size = ( glyph_height * line_bits + 7 ) >> 3; + break; + + default: /* invalid format */ + return SFNT_Err_Invalid_File_Format; + } + + /* Now read data and draw glyph into target pixmap */ + if ( FT_FRAME_ENTER( glyph_size ) ) + goto Exit; + + /* don't forget to multiply `x_offset' by `map->pix_bits' as */ + /* the sbit blitter doesn't make a difference between pixmap */ + /* depths. */ + blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes, + x_offset * pix_bits, y_offset ); + + FT_FRAME_EXIT(); + } + + Exit: + return error; + } + + + static FT_Error + Load_SBit_Image( TT_SBit_Strike strike, + TT_SBit_Range range, + FT_ULong ebdt_pos, + FT_ULong glyph_offset, + FT_GlyphSlot slot, + FT_Int x_offset, + FT_Int y_offset, + FT_Stream stream, + TT_SBit_Metrics metrics, + FT_Int depth ) + { + FT_Memory memory = stream->memory; + FT_Bitmap* map = &slot->bitmap; + FT_Error error; + + + /* place stream at beginning of glyph data and read metrics */ + if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) ) + goto Exit; + + error = tt_load_sbit_metrics( stream, range, metrics ); + if ( error ) + goto Exit; + + /* This function is recursive. At the top-level call, we */ + /* compute the dimensions of the higher-level glyph to */ + /* allocate the final pixmap buffer. */ + if ( depth == 0 ) + { + FT_Long size; + + + map->width = metrics->width; + map->rows = metrics->height; + + switch ( strike->bit_depth ) + { + case 1: + map->pixel_mode = FT_PIXEL_MODE_MONO; + map->pitch = ( map->width + 7 ) >> 3; + break; + + case 2: + map->pixel_mode = FT_PIXEL_MODE_GRAY2; + map->pitch = ( map->width + 3 ) >> 2; + break; + + case 4: + map->pixel_mode = FT_PIXEL_MODE_GRAY4; + map->pitch = ( map->width + 1 ) >> 1; + break; + + case 8: + map->pixel_mode = FT_PIXEL_MODE_GRAY; + map->pitch = map->width; + break; + + default: + return SFNT_Err_Invalid_File_Format; + } + + size = map->rows * map->pitch; + + /* check that there is no empty image */ + if ( size == 0 ) + goto Exit; /* exit successfully! */ + + error = ft_glyphslot_alloc_bitmap( slot, size ); + if (error) + goto Exit; + } + + switch ( range->image_format ) + { + case 1: /* single sbit image - load it */ + case 2: + case 5: + case 6: + case 7: + return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth, + range->image_format, metrics, stream ); + + case 8: /* compound format */ + FT_Stream_Skip( stream, 1L ); + /* fallthrough */ + + case 9: + break; + + default: /* invalid image format */ + return SFNT_Err_Invalid_File_Format; + } + + /* All right, we have a compound format. First of all, read */ + /* the array of elements. */ + { + TT_SBit_Component components; + TT_SBit_Component comp; + FT_UShort num_components, count; + + + if ( FT_READ_USHORT( num_components ) || + FT_NEW_ARRAY( components, num_components ) ) + goto Exit; + + count = num_components; + + if ( FT_FRAME_ENTER( 4L * num_components ) ) + goto Fail_Memory; + + for ( comp = components; count > 0; count--, comp++ ) + { + comp->glyph_code = FT_GET_USHORT(); + comp->x_offset = FT_GET_CHAR(); + comp->y_offset = FT_GET_CHAR(); + } + + FT_FRAME_EXIT(); + + /* Now recursively load each element glyph */ + count = num_components; + comp = components; + for ( ; count > 0; count--, comp++ ) + { + TT_SBit_Range elem_range; + TT_SBit_MetricsRec elem_metrics; + FT_ULong elem_offset; + + + /* find the range for this element */ + error = find_sbit_range( comp->glyph_code, + strike, + &elem_range, + &elem_offset ); + if ( error ) + goto Fail_Memory; + + /* now load the element, recursively */ + error = Load_SBit_Image( strike, + elem_range, + ebdt_pos, + elem_offset, + slot, + x_offset + comp->x_offset, + y_offset + comp->y_offset, + stream, + &elem_metrics, + depth + 1 ); + if ( error ) + goto Fail_Memory; + } + + Fail_Memory: + FT_FREE( components ); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_sbit_image */ + /* */ + /* <Description> */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* <Input> */ + /* face :: The target face object. */ + /* */ + /* strike_index :: The current strike index. */ + /* */ + /* glyph_index :: The current glyph index. */ + /* */ + /* load_flags :: The glyph load flags (the code checks for the flag */ + /* FT_LOAD_CROP_BITMAP). */ + /* */ + /* stream :: The input stream. */ + /* */ + /* <Output> */ + /* map :: The target pixmap. */ + /* */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* <Note> */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_sbit_image( TT_Face face, + FT_ULong strike_index, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap *map, + TT_SBit_MetricsRec *metrics ) + { + FT_Error error; + FT_ULong ebdt_pos, glyph_offset; + + TT_SBit_Strike strike; + TT_SBit_Range range; + + + /* Check whether there is a glyph sbit for the current index */ + error = tt_find_sbit_image( face, glyph_index, strike_index, + &range, &strike, &glyph_offset ); + if ( error ) + goto Exit; + + /* now, find the location of the `EBDT' table in */ + /* the font file */ + error = face->goto_table( face, TTAG_EBDT, stream, 0 ); + if ( error ) + error = face->goto_table( face, TTAG_bdat, stream, 0 ); + if (error) + goto Exit; + + ebdt_pos = FT_STREAM_POS(); + + error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset, + face->root.glyph, 0, 0, stream, metrics, 0 ); + if ( error ) + goto Exit; + + /* setup vertical metrics if needed */ + if ( strike->flags & 1 ) + { + /* in case of a horizontal strike only */ + FT_Int advance; + + + advance = strike->hori.ascender - strike->hori.descender; + + /* some heuristic values */ + + metrics->vertBearingX = (FT_Char)(-metrics->width / 2 ); + metrics->vertBearingY = (FT_Char)( advance / 10 ); + metrics->vertAdvance = (FT_Char)( advance * 12 / 10 ); + } + + /* Crop the bitmap now, unless specified otherwise */ + if ( load_flags & FT_LOAD_CROP_BITMAP ) + crop_bitmap( map, metrics ); + + Exit: + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/sfnt/ttsbit.h b/Utilities/vtkfreetype/src/sfnt/ttsbit.h new file mode 100644 index 0000000..f1b63b7 --- /dev/null +++ b/Utilities/vtkfreetype/src/sfnt/ttsbit.h @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* */ +/* ttsbit.h */ +/* */ +/* TrueType and OpenType embedded bitmap support (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTSBIT_H__ +#define __TTSBIT_H__ + + +#include <ft2build.h> +#include "ttload.h" + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + tt_face_load_sbit_strikes( TT_Face face, + FT_Stream stream ); + + FT_LOCAL( void ) + tt_face_free_sbit_strikes( TT_Face face ); + + + FT_LOCAL( FT_Error ) + tt_face_set_sbit_strike( TT_Face face, + FT_UInt x_ppem, + FT_UInt y_ppem, + FT_ULong *astrike_index ); + + FT_LOCAL( FT_Error ) + tt_find_sbit_image( TT_Face face, + FT_UInt glyph_index, + FT_ULong strike_index, + TT_SBit_Range *arange, + TT_SBit_Strike *astrike, + FT_ULong *aglyph_offset ); + + FT_LOCAL( FT_Error ) + tt_load_sbit_metrics( FT_Stream stream, + TT_SBit_Range range, + TT_SBit_Metrics metrics ); + + FT_LOCAL( FT_Error ) + tt_face_load_sbit_image( TT_Face face, + FT_ULong strike_index, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap *map, + TT_SBit_MetricsRec *metrics ); + + +FT_END_HEADER + +#endif /* __TTSBIT_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/smooth/ftgrays.c b/Utilities/vtkfreetype/src/smooth/ftgrays.c new file mode 100644 index 0000000..499cc8c --- /dev/null +++ b/Utilities/vtkfreetype/src/smooth/ftgrays.c @@ -0,0 +1,2159 @@ +/***************************************************************************/ +/* */ +/* ftgrays.c */ +/* */ +/* A new `perfect' anti-aliasing renderer (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This file can be compiled without the rest of the FreeType engine, by */ + /* defining the _STANDALONE_ macro when compiling it. You also need to */ + /* put the files `ftgrays.h' and `ftimage.h' into the current */ + /* compilation directory. Typically, you could do something like */ + /* */ + /* - copy `src/smooth/ftgrays.c' (this file) to your current directory */ + /* */ + /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */ + /* same directory */ + /* */ + /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */ + /* */ + /* cc -c -D_STANDALONE_ ftgrays.c */ + /* */ + /* The renderer can be initialized with a call to */ + /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated */ + /* with a call to `ft_gray_raster.raster_render'. */ + /* */ + /* See the comments and documentation in the file `ftimage.h' for more */ + /* details on how the raster works. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* This is a new anti-aliasing scan-converter for FreeType 2. The */ + /* algorithm used here is _very_ different from the one in the standard */ + /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */ + /* coverage of the outline on each pixel cell. */ + /* */ + /* It is based on ideas that I initially found in Raph Levien's */ + /* excellent LibArt graphics library (see http://www.levien.com/libart */ + /* for more information, though the web pages do not tell anything */ + /* about the renderer; you'll have to dive into the source code to */ + /* understand how it works). */ + /* */ + /* Note, however, that this is a _very_ different implementation */ + /* compared to Raph's. Coverage information is stored in a very */ + /* different way, and I don't use sorted vector paths. Also, it doesn't */ + /* use floating point values. */ + /* */ + /* This renderer has the following advantages: */ + /* */ + /* - It doesn't need an intermediate bitmap. Instead, one can supply a */ + /* callback function that will be called by the renderer to draw gray */ + /* spans on any target surface. You can thus do direct composition on */ + /* any kind of bitmap, provided that you give the renderer the right */ + /* callback. */ + /* */ + /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */ + /* each pixel cell. */ + /* */ + /* - It performs a single pass on the outline (the `standard' FT2 */ + /* renderer makes two passes). */ + /* */ + /* - It can easily be modified to render to _any_ number of gray levels */ + /* cheaply. */ + /* */ + /* - For small (< 20) pixel sizes, it is faster than the standard */ + /* renderer. */ + /* */ + /*************************************************************************/ + + + +/* experimental support for gamma correction within the rasterizer */ +#define xxxGRAYS_USE_GAMMA + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_smooth + + +#define ErrRaster_MemoryOverflow -4 + + +#ifdef _STANDALONE_ + +#include <string.h> /* for ft_memcpy() */ +#include <setjmp.h> +#include <limits.h> +#define FT_UINT_MAX UINT_MAX + +#define ft_memset memset + +#define ft_setjmp setjmp +#define ft_longjmp longjmp +#define ft_jmp_buf jmp_buf + + +#define ErrRaster_Invalid_Mode -2 +#define ErrRaster_Invalid_Outline -1 + +#define FT_BEGIN_HEADER +#define FT_END_HEADER + +#include "ftimage.h" +#include "ftgrays.h" + + /* This macro is used to indicate that a function parameter is unused. */ + /* Its purpose is simply to reduce compiler warnings. Note also that */ + /* simply defining it as `(void)x' doesn't avoid warnings with certain */ + /* ANSI compilers (e.g. LCC). */ +#define FT_UNUSED( x ) (x) = (x) + + /* Disable the tracing mechanism for simplicity -- developers can */ + /* activate it easily by redefining these two macros. */ +#ifndef FT_ERROR +#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */ +#endif + +#ifndef FT_TRACE +#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */ +#endif + + +#else /* _STANDALONE_ */ + + +#include <ft2build.h> +#include "ftgrays.h" +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H +#include FT_OUTLINE_H + +#include "ftsmerrs.h" + +#define ErrRaster_Invalid_Mode Smooth_Err_Cannot_Render_Glyph +#define ErrRaster_Invalid_Outline Smooth_Err_Invalid_Outline + + +#endif /* _STANDALONE_ */ + + +#ifndef FT_MEM_SET +#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c ) +#endif + +#ifndef FT_MEM_ZERO +#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count ) +#endif + + /* define this to dump debugging information */ +#define xxxDEBUG_GRAYS + + /* as usual, for the speed hungry :-) */ + +#ifndef FT_STATIC_RASTER + + +#define RAS_ARG PRaster raster +#define RAS_ARG_ PRaster raster, + +#define RAS_VAR raster +#define RAS_VAR_ raster, + +#define ras (*raster) + + +#else /* FT_STATIC_RASTER */ + + +#define RAS_ARG /* empty */ +#define RAS_ARG_ /* empty */ +#define RAS_VAR /* empty */ +#define RAS_VAR_ /* empty */ + + static TRaster ras; + + +#endif /* FT_STATIC_RASTER */ + + + /* must be at least 6 bits! */ +#define PIXEL_BITS 8 + +#define ONE_PIXEL ( 1L << PIXEL_BITS ) +#define PIXEL_MASK ( -1L << PIXEL_BITS ) +#define TRUNC( x ) ( (TCoord)((x) >> PIXEL_BITS) ) +#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS ) +#define FLOOR( x ) ( (x) & -ONE_PIXEL ) +#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL ) +#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL ) + +#if PIXEL_BITS >= 6 +#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) ) +#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) ) +#else +#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) ) +#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) ) +#endif + + /* Define this if you want to use a more compact storage scheme. This */ + /* increases the number of cells available in the render pool but slows */ + /* down the rendering a bit. It is useful if you have a really tiny */ + /* render pool. */ +#undef GRAYS_COMPACT + + + /*************************************************************************/ + /* */ + /* TYPE DEFINITIONS */ + /* */ + + /* don't change the following types to FT_Int or FT_Pos, since we might */ + /* need to define them to "float" or "double" when experimenting with */ + /* new algorithms */ + + typedef int TCoord; /* integer scanline/pixel coordinate */ + typedef long TPos; /* sub-pixel coordinate */ + + /* determine the type used to store cell areas. This normally takes at */ + /* least PIXEL_BYTES*2 + 1. On 16-bit systems, we need to use `long' */ + /* instead of `int', otherwise bad things happen */ + +#if PIXEL_BITS <= 7 + + typedef int TArea; + +#else /* PIXEL_BITS >= 8 */ + + /* approximately determine the size of integers using an ANSI-C header */ +#if FT_UINT_MAX == 0xFFFFU + typedef long TArea; +#else + typedef int TArea; +#endif + +#endif /* PIXEL_BITS >= 8 */ + + + /* maximal number of gray spans in a call to the span callback */ +#define FT_MAX_GRAY_SPANS 32 + + +#ifdef GRAYS_COMPACT + + typedef struct TCell_ + { + short x : 14; + short y : 14; + int cover : PIXEL_BITS + 2; + int area : PIXEL_BITS * 2 + 2; + + } TCell, *PCell; + +#else /* GRAYS_COMPACT */ + + typedef struct TCell_ + { + TCoord x; + TCoord y; + int cover; + TArea area; + + } TCell, *PCell; + +#endif /* GRAYS_COMPACT */ + + + typedef struct TRaster_ + { + PCell cells; + int max_cells; + int num_cells; + + TPos min_ex, max_ex; + TPos min_ey, max_ey; + + TArea area; + int cover; + int invalid; + + TCoord ex, ey; + TCoord cx, cy; + TPos x, y; + + TPos last_ey; + + FT_Vector bez_stack[32 * 3 + 1]; + int lev_stack[32]; + + FT_Outline outline; + FT_Bitmap target; + FT_BBox clip_box; + + FT_Span gray_spans[FT_MAX_GRAY_SPANS]; + int num_gray_spans; + + FT_Raster_Span_Func render_span; + void* render_span_data; + int span_y; + + int band_size; + int band_shoot; + int conic_level; + int cubic_level; + + void* memory; + ft_jmp_buf jump_buffer; + +#ifdef GRAYS_USE_GAMMA + unsigned char gamma[257]; +#endif + + } TRaster, *PRaster; + + + /*************************************************************************/ + /* */ + /* Initialize the cells table. */ + /* */ + static void + gray_init_cells( RAS_ARG_ void* buffer, + long byte_size ) + { + ras.cells = (PCell)buffer; + ras.max_cells = (int)( byte_size / sizeof ( TCell ) ); + ras.num_cells = 0; + ras.area = 0; + ras.cover = 0; + ras.invalid = 1; + } + + + /*************************************************************************/ + /* */ + /* Compute the outline bounding box. */ + /* */ + static void + gray_compute_cbox( RAS_ARG ) + { + FT_Outline* outline = &ras.outline; + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + outline->n_points; + + + if ( outline->n_points <= 0 ) + { + ras.min_ex = ras.max_ex = 0; + ras.min_ey = ras.max_ey = 0; + return; + } + + ras.min_ex = ras.max_ex = vec->x; + ras.min_ey = ras.max_ey = vec->y; + + vec++; + + for ( ; vec < limit; vec++ ) + { + TPos x = vec->x; + TPos y = vec->y; + + + if ( x < ras.min_ex ) ras.min_ex = x; + if ( x > ras.max_ex ) ras.max_ex = x; + if ( y < ras.min_ey ) ras.min_ey = y; + if ( y > ras.max_ey ) ras.max_ey = y; + } + + /* truncate the bounding box to integer pixels */ + ras.min_ex = ras.min_ex >> 6; + ras.min_ey = ras.min_ey >> 6; + ras.max_ex = ( ras.max_ex + 63 ) >> 6; + ras.max_ey = ( ras.max_ey + 63 ) >> 6; + } + + + /*************************************************************************/ + /* */ + /* Record the current cell in the table. */ + /* */ + static void + gray_record_cell( RAS_ARG ) + { + PCell cell; + + + if ( !ras.invalid && ( ras.area | ras.cover ) ) + { + if ( ras.num_cells >= ras.max_cells ) + ft_longjmp( ras.jump_buffer, 1 ); + + cell = ras.cells + ras.num_cells++; + cell->x = (TCoord)(ras.ex - ras.min_ex); + cell->y = (TCoord)(ras.ey - ras.min_ey); + cell->area = ras.area; + cell->cover = ras.cover; + } + } + + + /*************************************************************************/ + /* */ + /* Set the current cell to a new position. */ + /* */ + static void + gray_set_cell( RAS_ARG_ TCoord ex, + TCoord ey ) + { + int invalid, record, clean; + + + /* Move the cell pointer to a new position. We set the `invalid' */ + /* flag to indicate that the cell isn't part of those we're interested */ + /* in during the render phase. This means that: */ + /* */ + /* . the new vertical position must be within min_ey..max_ey-1. */ + /* . the new horizontal position must be strictly less than max_ex */ + /* */ + /* Note that if a cell is to the left of the clipping region, it is */ + /* actually set to the (min_ex-1) horizontal position. */ + + record = 0; + clean = 1; + + invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex ); + if ( !invalid ) + { + /* All cells that are on the left of the clipping region go to the */ + /* min_ex - 1 horizontal position. */ + if ( ex < ras.min_ex ) + ex = (TCoord)(ras.min_ex - 1); + + /* if our position is new, then record the previous cell */ + if ( ex != ras.ex || ey != ras.ey ) + record = 1; + else + clean = ras.invalid; /* do not clean if we didn't move from */ + /* a valid cell */ + } + + /* record the previous cell if needed (i.e., if we changed the cell */ + /* position, of changed the `invalid' flag) */ + if ( ras.invalid != invalid || record ) + gray_record_cell( RAS_VAR ); + + if ( clean ) + { + ras.area = 0; + ras.cover = 0; + } + + ras.invalid = invalid; + ras.ex = ex; + ras.ey = ey; + } + + + /*************************************************************************/ + /* */ + /* Start a new contour at a given cell. */ + /* */ + static void + gray_start_cell( RAS_ARG_ TCoord ex, + TCoord ey ) + { + if ( ex < ras.min_ex ) + ex = (TCoord)(ras.min_ex - 1); + + ras.area = 0; + ras.cover = 0; + ras.ex = ex; + ras.ey = ey; + ras.last_ey = SUBPIXELS( ey ); + ras.invalid = 0; + + gray_set_cell( RAS_VAR_ ex, ey ); + } + + + /*************************************************************************/ + /* */ + /* Render a scanline as one or more cells. */ + /* */ + static void + gray_render_scanline( RAS_ARG_ TCoord ey, + TPos x1, + TCoord y1, + TPos x2, + TCoord y2 ) + { + TCoord ex1, ex2, fx1, fx2, delta; + long p, first, dx; + int incr, lift, mod, rem; + + + dx = x2 - x1; + + ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */ + ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */ + fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) ); + fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) ); + + /* trivial case. Happens often */ + if ( y1 == y2 ) + { + gray_set_cell( RAS_VAR_ ex2, ey ); + return; + } + + /* everything is located in a single cell. That is easy! */ + /* */ + if ( ex1 == ex2 ) + { + delta = y2 - y1; + ras.area += (TArea)( fx1 + fx2 ) * delta; + ras.cover += delta; + return; + } + + /* ok, we'll have to render a run of adjacent cells on the same */ + /* scanline... */ + /* */ + p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 ); + first = ONE_PIXEL; + incr = 1; + + if ( dx < 0 ) + { + p = fx1 * ( y2 - y1 ); + first = 0; + incr = -1; + dx = -dx; + } + + delta = (TCoord)( p / dx ); + mod = (TCoord)( p % dx ); + if ( mod < 0 ) + { + delta--; + mod += (TCoord)dx; + } + + ras.area += (TArea)( fx1 + first ) * delta; + ras.cover += delta; + + ex1 += incr; + gray_set_cell( RAS_VAR_ ex1, ey ); + y1 += delta; + + if ( ex1 != ex2 ) + { + p = ONE_PIXEL * ( y2 - y1 + delta ); + lift = (TCoord)( p / dx ); + rem = (TCoord)( p % dx ); + if ( rem < 0 ) + { + lift--; + rem += (TCoord)dx; + } + + mod -= (int)dx; + + while ( ex1 != ex2 ) + { + delta = lift; + mod += rem; + if ( mod >= 0 ) + { + mod -= (TCoord)dx; + delta++; + } + + ras.area += (TArea)ONE_PIXEL * delta; + ras.cover += delta; + y1 += delta; + ex1 += incr; + gray_set_cell( RAS_VAR_ ex1, ey ); + } + } + + delta = y2 - y1; + ras.area += (TArea)( fx2 + ONE_PIXEL - first ) * delta; + ras.cover += delta; + } + + + /*************************************************************************/ + /* */ + /* Render a given line as a series of scanlines. */ + /* */ + static void + gray_render_line( RAS_ARG_ TPos to_x, + TPos to_y ) + { + TCoord ey1, ey2, fy1, fy2; + TPos dx, dy, x, x2; + long p, first; + int delta, rem, mod, lift, incr; + + + ey1 = TRUNC( ras.last_ey ); + ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */ + fy1 = (TCoord)( ras.y - ras.last_ey ); + fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) ); + + dx = to_x - ras.x; + dy = to_y - ras.y; + + /* XXX: we should do something about the trivial case where dx == 0, */ + /* as it happens very often! */ + + /* perform vertical clipping */ + { + TCoord min, max; + + + min = ey1; + max = ey2; + if ( ey1 > ey2 ) + { + min = ey2; + max = ey1; + } + if ( min >= ras.max_ey || max < ras.min_ey ) + goto End; + } + + /* everything is on a single scanline */ + if ( ey1 == ey2 ) + { + gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ); + goto End; + } + + /* vertical line - avoid calling gray_render_scanline */ + incr = 1; + + if ( dx == 0 ) + { + TCoord ex = TRUNC( ras.x ); + TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 ); + TPos area; + + + first = ONE_PIXEL; + if ( dy < 0 ) + { + first = 0; + incr = -1; + } + + delta = (int)( first - fy1 ); + ras.area += (TArea)two_fx * delta; + ras.cover += delta; + ey1 += incr; + + gray_set_cell( raster, ex, ey1 ); + + delta = (int)( first + first - ONE_PIXEL ); + area = (TArea)two_fx * delta; + while ( ey1 != ey2 ) + { + ras.area += area; + ras.cover += delta; + ey1 += incr; + gray_set_cell( raster, ex, ey1 ); + } + + delta = (int)( fy2 - ONE_PIXEL + first ); + ras.area += (TArea)two_fx * delta; + ras.cover += delta; + goto End; + } + + /* ok, we have to render several scanlines */ + p = ( ONE_PIXEL - fy1 ) * dx; + first = ONE_PIXEL; + incr = 1; + + if ( dy < 0 ) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = (int)( p / dy ); + mod = (int)( p % dy ); + if ( mod < 0 ) + { + delta--; + mod += (TCoord)dy; + } + + x = ras.x + delta; + gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first ); + + ey1 += incr; + gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 ); + + if ( ey1 != ey2 ) + { + p = ONE_PIXEL * dx; + lift = (int)( p / dy ); + rem = (int)( p % dy ); + if ( rem < 0 ) + { + lift--; + rem += (int)dy; + } + mod -= (int)dy; + + while ( ey1 != ey2 ) + { + delta = lift; + mod += rem; + if ( mod >= 0 ) + { + mod -= (int)dy; + delta++; + } + + x2 = x + delta; + gray_render_scanline( RAS_VAR_ ey1, x, + (TCoord)( ONE_PIXEL - first ), x2, + (TCoord)first ); + x = x2; + + ey1 += incr; + gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 ); + } + } + + gray_render_scanline( RAS_VAR_ ey1, x, + (TCoord)( ONE_PIXEL - first ), to_x, + fy2 ); + + End: + ras.x = to_x; + ras.y = to_y; + ras.last_ey = SUBPIXELS( ey2 ); + } + + + static void + gray_split_conic( FT_Vector* base ) + { + TPos a, b; + + + base[4].x = base[2].x; + b = base[1].x; + a = base[3].x = ( base[2].x + b ) / 2; + b = base[1].x = ( base[0].x + b ) / 2; + base[2].x = ( a + b ) / 2; + + base[4].y = base[2].y; + b = base[1].y; + a = base[3].y = ( base[2].y + b ) / 2; + b = base[1].y = ( base[0].y + b ) / 2; + base[2].y = ( a + b ) / 2; + } + + + static void + gray_render_conic( RAS_ARG_ FT_Vector* control, + FT_Vector* to ) + { + TPos dx, dy; + int top, level; + int* levels; + FT_Vector* arc; + + + dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 ); + if ( dx < 0 ) + dx = -dx; + dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 ); + if ( dy < 0 ) + dy = -dy; + if ( dx < dy ) + dx = dy; + + level = 1; + dx = dx / ras.conic_level; + while ( dx > 0 ) + { + dx >>= 2; + level++; + } + + /* a shortcut to speed things up */ + if ( level <= 1 ) + { + /* we compute the mid-point directly in order to avoid */ + /* calling gray_split_conic() */ + TPos to_x, to_y, mid_x, mid_y; + + + to_x = UPSCALE( to->x ); + to_y = UPSCALE( to->y ); + mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4; + mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4; + + gray_render_line( RAS_VAR_ mid_x, mid_y ); + gray_render_line( RAS_VAR_ to_x, to_y ); + return; + } + + arc = ras.bez_stack; + levels = ras.lev_stack; + top = 0; + levels[0] = level; + + arc[0].x = UPSCALE( to->x ); + arc[0].y = UPSCALE( to->y ); + arc[1].x = UPSCALE( control->x ); + arc[1].y = UPSCALE( control->y ); + arc[2].x = ras.x; + arc[2].y = ras.y; + + while ( top >= 0 ) + { + level = levels[top]; + if ( level > 1 ) + { + /* check that the arc crosses the current band */ + TPos min, max, y; + + + min = max = arc[0].y; + + y = arc[1].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + + y = arc[2].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + + if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) + goto Draw; + + gray_split_conic( arc ); + arc += 2; + top++; + levels[top] = levels[top - 1] = level - 1; + continue; + } + + Draw: + { + TPos to_x, to_y, mid_x, mid_y; + + + to_x = arc[0].x; + to_y = arc[0].y; + mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4; + mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4; + + gray_render_line( RAS_VAR_ mid_x, mid_y ); + gray_render_line( RAS_VAR_ to_x, to_y ); + + top--; + arc -= 2; + } + } + return; + } + + + static void + gray_split_cubic( FT_Vector* base ) + { + TPos a, b, c, d; + + + base[6].x = base[3].x; + c = base[1].x; + d = base[2].x; + base[1].x = a = ( base[0].x + c ) / 2; + base[5].x = b = ( base[3].x + d ) / 2; + c = ( c + d ) / 2; + base[2].x = a = ( a + c ) / 2; + base[4].x = b = ( b + c ) / 2; + base[3].x = ( a + b ) / 2; + + base[6].y = base[3].y; + c = base[1].y; + d = base[2].y; + base[1].y = a = ( base[0].y + c ) / 2; + base[5].y = b = ( base[3].y + d ) / 2; + c = ( c + d ) / 2; + base[2].y = a = ( a + c ) / 2; + base[4].y = b = ( b + c ) / 2; + base[3].y = ( a + b ) / 2; + } + + + static void + gray_render_cubic( RAS_ARG_ FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to ) + { + TPos dx, dy, da, db; + int top, level; + int* levels; + FT_Vector* arc; + + + dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 ); + if ( dx < 0 ) + dx = -dx; + dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 ); + if ( dy < 0 ) + dy = -dy; + if ( dx < dy ) + dx = dy; + da = dx; + + dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x ); + if ( dx < 0 ) + dx = -dx; + dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y ); + if ( dy < 0 ) + dy = -dy; + if ( dx < dy ) + dx = dy; + db = dx; + + level = 1; + da = da / ras.cubic_level; + db = db / ras.conic_level; + while ( da > 0 || db > 0 ) + { + da >>= 2; + db >>= 3; + level++; + } + + if ( level <= 1 ) + { + TPos to_x, to_y, mid_x, mid_y; + + + to_x = UPSCALE( to->x ); + to_y = UPSCALE( to->y ); + mid_x = ( ras.x + to_x + + 3 * UPSCALE( control1->x + control2->x ) ) / 8; + mid_y = ( ras.y + to_y + + 3 * UPSCALE( control1->y + control2->y ) ) / 8; + + gray_render_line( RAS_VAR_ mid_x, mid_y ); + gray_render_line( RAS_VAR_ to_x, to_y ); + return; + } + + arc = ras.bez_stack; + arc[0].x = UPSCALE( to->x ); + arc[0].y = UPSCALE( to->y ); + arc[1].x = UPSCALE( control2->x ); + arc[1].y = UPSCALE( control2->y ); + arc[2].x = UPSCALE( control1->x ); + arc[2].y = UPSCALE( control1->y ); + arc[3].x = ras.x; + arc[3].y = ras.y; + + levels = ras.lev_stack; + top = 0; + levels[0] = level; + + while ( top >= 0 ) + { + level = levels[top]; + if ( level > 1 ) + { + /* check that the arc crosses the current band */ + TPos min, max, y; + + + min = max = arc[0].y; + y = arc[1].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + y = arc[2].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + y = arc[3].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 ) + goto Draw; + gray_split_cubic( arc ); + arc += 3; + top ++; + levels[top] = levels[top - 1] = level - 1; + continue; + } + + Draw: + { + TPos to_x, to_y, mid_x, mid_y; + + + to_x = arc[0].x; + to_y = arc[0].y; + mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8; + mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8; + + gray_render_line( RAS_VAR_ mid_x, mid_y ); + gray_render_line( RAS_VAR_ to_x, to_y ); + top --; + arc -= 3; + } + } + return; + } + + + /* a macro comparing two cell pointers. Returns true if a <= b. */ +#if 1 + +#define PACK( a ) ( ( (long)(a)->y << 16 ) + (a)->x ) +#define LESS_THAN( a, b ) ( PACK( a ) < PACK( b ) ) + +#else /* 1 */ + +#define LESS_THAN( a, b ) ( (a)->y < (b)->y || \ + ( (a)->y == (b)->y && (a)->x < (b)->x ) ) + +#endif /* 1 */ + +#define SWAP_CELLS( a, b, temp ) do \ + { \ + temp = *(a); \ + *(a) = *(b); \ + *(b) = temp; \ + } while ( 0 ) +#define DEBUG_SORT +#define QUICK_SORT + +#ifdef SHELL_SORT + + /* a simple shell sort algorithm that works directly on our */ + /* cells table */ + static void + gray_shell_sort ( PCell cells, + int count ) + { + PCell i, j, limit = cells + count; + TCell temp; + int gap; + + + /* compute initial gap */ + for ( gap = 0; ++gap < count; gap *= 3 ) + ; + + while ( gap /= 3 ) + { + for ( i = cells + gap; i < limit; i++ ) + { + for ( j = i - gap; ; j -= gap ) + { + PCell k = j + gap; + + + if ( LESS_THAN( j, k ) ) + break; + + SWAP_CELLS( j, k, temp ); + + if ( j < cells + gap ) + break; + } + } + } + } + +#endif /* SHELL_SORT */ + + +#ifdef QUICK_SORT + + /* This is a non-recursive quicksort that directly process our cells */ + /* array. It should be faster than calling the stdlib qsort(), and we */ + /* can even tailor our insertion threshold... */ + +#define QSORT_THRESHOLD 9 /* below this size, a sub-array will be sorted */ + /* through a normal insertion sort */ + + static void + gray_quick_sort( PCell cells, + int count ) + { + PCell stack[40]; /* should be enough ;-) */ + PCell* top; /* top of stack */ + PCell base, limit; + TCell temp; + + + limit = cells + count; + base = cells; + top = stack; + + for (;;) + { + int len = (int)( limit - base ); + PCell i, j, pivot; + + + if ( len > QSORT_THRESHOLD ) + { + /* we use base + len/2 as the pivot */ + pivot = base + len / 2; + SWAP_CELLS( base, pivot, temp ); + + i = base + 1; + j = limit - 1; + + /* now ensure that *i <= *base <= *j */ + if ( LESS_THAN( j, i ) ) + SWAP_CELLS( i, j, temp ); + + if ( LESS_THAN( base, i ) ) + SWAP_CELLS( base, i, temp ); + + if ( LESS_THAN( j, base ) ) + SWAP_CELLS( base, j, temp ); + + for (;;) + { + do i++; while ( LESS_THAN( i, base ) ); + do j--; while ( LESS_THAN( base, j ) ); + + if ( i > j ) + break; + + SWAP_CELLS( i, j, temp ); + } + + SWAP_CELLS( base, j, temp ); + + /* now, push the largest sub-array */ + if ( j - base > limit - i ) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + /* the sub-array is small, perform insertion sort */ + j = base; + i = j + 1; + + for ( ; i < limit; j = i, i++ ) + { + for ( ; LESS_THAN( j + 1, j ); j-- ) + { + SWAP_CELLS( j + 1, j, temp ); + if ( j == base ) + break; + } + } + if ( top > stack ) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + break; + } + } + } + +#endif /* QUICK_SORT */ + + +#ifdef DEBUG_GRAYS +#ifdef DEBUG_SORT + + static int + gray_check_sort( PCell cells, + int count ) + { + PCell p, q; + + + for ( p = cells + count - 2; p >= cells; p-- ) + { + q = p + 1; + if ( !LESS_THAN( p, q ) ) + return 0; + } + return 1; + } + +#endif /* DEBUG_SORT */ +#endif /* DEBUG_GRAYS */ + + + static int + gray_move_to( FT_Vector* to, + FT_Raster raster ) + { + TPos x, y; + + + /* record current cell, if any */ + gray_record_cell( (PRaster)raster ); + + /* start to a new position */ + x = UPSCALE( to->x ); + y = UPSCALE( to->y ); + + gray_start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) ); + + ((PRaster)raster)->x = x; + ((PRaster)raster)->y = y; + return 0; + } + + + static int + gray_line_to( FT_Vector* to, + FT_Raster raster ) + { + gray_render_line( (PRaster)raster, + UPSCALE( to->x ), UPSCALE( to->y ) ); + return 0; + } + + + static int + gray_conic_to( FT_Vector* control, + FT_Vector* to, + FT_Raster raster ) + { + gray_render_conic( (PRaster)raster, control, to ); + return 0; + } + + + static int + gray_cubic_to( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + FT_Raster raster ) + { + gray_render_cubic( (PRaster)raster, control1, control2, to ); + return 0; + } + + + static void + gray_render_span( int y, + int count, + FT_Span* spans, + PRaster raster ) + { + unsigned char* p; + FT_Bitmap* map = &raster->target; + + + /* first of all, compute the scanline offset */ + p = (unsigned char*)map->buffer - y * map->pitch; + if ( map->pitch >= 0 ) + p += ( map->rows - 1 ) * map->pitch; + + for ( ; count > 0; count--, spans++ ) + { + unsigned char coverage = spans->coverage; + + +#ifdef GRAYS_USE_GAMMA + coverage = raster->gamma[coverage]; +#endif + + if ( coverage ) +#if 1 + FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len ); +#else /* 1 */ + { + q = p + spans->x; + limit = q + spans->len; + for ( ; q < limit; q++ ) + q[0] = (unsigned char)coverage; + } +#endif /* 1 */ + } + } + + +#ifdef DEBUG_GRAYS + +#include <stdio.h> + + static void + gray_dump_cells( RAS_ARG ) + { + PCell cell, limit; + int y = -1; + + + cell = ras.cells; + limit = cell + ras.num_cells; + + for ( ; cell < limit; cell++ ) + { + if ( cell->y != y ) + { + fprintf( stderr, "\n%2d: ", cell->y ); + y = cell->y; + } + fprintf( stderr, "[%d %d %d]", + cell->x, cell->area, cell->cover ); + } + fprintf(stderr, "\n" ); + } + +#endif /* DEBUG_GRAYS */ + + + static void + gray_hline( RAS_ARG_ TCoord x, + TCoord y, + TPos area, + int acount ) + { + FT_Span* span; + int count; + int coverage; + + + /* compute the coverage line's coverage, depending on the */ + /* outline fill rule */ + /* */ + /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ + /* */ + coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); + /* use range 0..256 */ + if ( coverage < 0 ) + coverage = -coverage; + + if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) + { + coverage &= 511; + + if ( coverage > 256 ) + coverage = 512 - coverage; + else if ( coverage == 256 ) + coverage = 255; + } + else + { + /* normal non-zero winding rule */ + if ( coverage >= 256 ) + coverage = 255; + } + + y += (TCoord)ras.min_ey; + x += (TCoord)ras.min_ex; + + if ( coverage ) + { + /* see if we can add this span to the current list */ + count = ras.num_gray_spans; + span = ras.gray_spans + count - 1; + if ( count > 0 && + ras.span_y == y && + (int)span->x + span->len == (int)x && + span->coverage == coverage ) + { + span->len = (unsigned short)( span->len + acount ); + return; + } + + if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS ) + { + if ( ras.render_span && count > 0 ) + ras.render_span( ras.span_y, count, ras.gray_spans, + ras.render_span_data ); + /* ras.render_span( span->y, ras.gray_spans, count ); */ + +#ifdef DEBUG_GRAYS + + if ( ras.span_y >= 0 ) + { + int n; + + + fprintf( stderr, "y=%3d ", ras.span_y ); + span = ras.gray_spans; + for ( n = 0; n < count; n++, span++ ) + fprintf( stderr, "[%d..%d]:%02x ", + span->x, span->x + span->len - 1, span->coverage ); + fprintf( stderr, "\n" ); + } + +#endif /* DEBUG_GRAYS */ + + ras.num_gray_spans = 0; + ras.span_y = y; + + count = 0; + span = ras.gray_spans; + } + else + span++; + + /* add a gray span to the current list */ + span->x = (short)x; + span->len = (unsigned short)acount; + span->coverage = (unsigned char)coverage; + ras.num_gray_spans++; + } + } + + + static void + gray_sweep( RAS_ARG_ FT_Bitmap* target ) + { + TCoord x, y, cover; + TArea area; + PCell start, cur, limit; + + FT_UNUSED( target ); + + + if ( ras.num_cells == 0 ) + return; + + cur = ras.cells; + limit = cur + ras.num_cells; + + cover = 0; + ras.span_y = -1; + ras.num_gray_spans = 0; + + for (;;) + { + start = cur; + y = start->y; + x = start->x; + + area = start->area; + cover += start->cover; + + /* accumulate all start cells */ + for (;;) + { + ++cur; + if ( cur >= limit || cur->y != start->y || cur->x != start->x ) + break; + + area += cur->area; + cover += cur->cover; + } + + /* if the start cell has a non-null area, we must draw an */ + /* individual gray pixel there */ + if ( area && x >= 0 ) + { + gray_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 ); + x++; + } + + if ( x < 0 ) + x = 0; + + if ( cur < limit && start->y == cur->y ) + { + /* draw a gray span between the start cell and the current one */ + if ( cur->x > x ) + gray_hline( RAS_VAR_ x, y, + cover * ( ONE_PIXEL * 2 ), cur->x - x ); + } + else + { + /* draw a gray span until the end of the clipping region */ + if ( cover && x < ras.max_ex - ras.min_ex ) + gray_hline( RAS_VAR_ x, y, + cover * ( ONE_PIXEL * 2 ), + (int)( ras.max_ex - x - ras.min_ex ) ); + cover = 0; + } + + if ( cur >= limit ) + break; + } + + if ( ras.render_span && ras.num_gray_spans > 0 ) + ras.render_span( ras.span_y, ras.num_gray_spans, + ras.gray_spans, ras.render_span_data ); + +#ifdef DEBUG_GRAYS + + { + int n; + FT_Span* span; + + + fprintf( stderr, "y=%3d ", ras.span_y ); + span = ras.gray_spans; + for ( n = 0; n < ras.num_gray_spans; n++, span++ ) + fprintf( stderr, "[%d..%d]:%02x ", + span->x, span->x + span->len - 1, span->coverage ); + fprintf( stderr, "\n" ); + } + +#endif /* DEBUG_GRAYS */ + + } + + +#ifdef _STANDALONE_ + + /*************************************************************************/ + /* */ + /* The following function should only compile in stand_alone mode, */ + /* i.e., when building this component without the rest of FreeType. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* <Function> */ + /* FT_Outline_Decompose */ + /* */ + /* <Description> */ + /* Walks over an outline's structure to decompose it into individual */ + /* segments and Bezier arcs. This function is also able to emit */ + /* `move to' and `close to' operations to indicate the start and end */ + /* of new contours in the outline. */ + /* */ + /* <Input> */ + /* outline :: A pointer to the source target. */ + /* */ + /* func_interface :: A table of `emitters', i.e,. function pointers */ + /* called during decomposition to indicate path */ + /* operations. */ + /* */ + /* user :: A typeless pointer which is passed to each */ + /* emitter during the decomposition. It can be */ + /* used to store the state during the */ + /* decomposition. */ + /* */ + /* <Return> */ + /* Error code. 0 means sucess. */ + /* */ + static + int FT_Outline_Decompose( FT_Outline* outline, + const FT_Outline_Funcs* func_interface, + void* user ) + { +#undef SCALED +#if 0 +#define SCALED( x ) ( ( (x) << shift ) - delta ) +#else +#define SCALED( x ) (x) +#endif + + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + int error; + char tag; /* current point's state */ + +#if 0 + int shift = func_interface->shift; + TPos delta = func_interface->delta; +#endif + + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + int last; /* index of last point in contour */ + + + last = outline->contours[n]; + limit = outline->points + last; + + v_start = outline->points[first]; + v_last = outline->points[last]; + + v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y ); + v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y ); + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_CURVE_TAG_CONIC ) + { + /* first point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + error = func_interface->move_to( &v_start, user ); + if ( error ) + goto Exit; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + switch ( tag ) + { + case FT_CURVE_TAG_ON: /* emit a single line_to */ + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = func_interface->line_to( &vec, user ); + if ( error ) + goto Exit; + continue; + } + + case FT_CURVE_TAG_CONIC: /* consume conic arcs */ + { + v_control.x = SCALED( point->x ); + v_control.y = SCALED( point->y ); + + Do_Conic: + if ( point < limit ) + { + FT_Vector vec; + FT_Vector v_middle; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + if ( tag == FT_CURVE_TAG_ON ) + { + error = func_interface->conic_to( &v_control, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + if ( tag != FT_CURVE_TAG_CONIC ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + vec.x ) / 2; + v_middle.y = ( v_control.y + vec.y ) / 2; + + error = func_interface->conic_to( &v_control, &v_middle, user ); + if ( error ) + goto Exit; + + v_control = vec; + goto Do_Conic; + } + + error = func_interface->conic_to( &v_control, &v_start, user ); + goto Close; + } + + default: /* FT_CURVE_TAG_CUBIC */ + { + FT_Vector vec1, vec2; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y ); + vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y ); + + if ( point <= limit ) + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); + goto Close; + } + } + } + + /* close the contour with a line segment */ + error = func_interface->line_to( &v_start, user ); + + Close: + if ( error ) + goto Exit; + + first = last + 1; + } + + return 0; + + Exit: + return error; + + Invalid_Outline: + return ErrRaster_Invalid_Outline; + } + +#endif /* _STANDALONE_ */ + + + typedef struct TBand_ + { + TPos min, max; + + } TBand; + + + static int + gray_convert_glyph_inner( RAS_ARG ) + { + static + const FT_Outline_Funcs func_interface = + { + (FT_Outline_MoveTo_Func) gray_move_to, + (FT_Outline_LineTo_Func) gray_line_to, + (FT_Outline_ConicTo_Func)gray_conic_to, + (FT_Outline_CubicTo_Func)gray_cubic_to, + 0, + 0 + }; + + volatile int error = 0; + + if ( ft_setjmp( ras.jump_buffer ) == 0 ) + { + error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); + gray_record_cell( RAS_VAR ); + } + else + { + error = ErrRaster_MemoryOverflow; + } + + return error; + } + + + static int + gray_convert_glyph( RAS_ARG ) + { + TBand bands[40]; + TBand* volatile band; + int volatile n, num_bands; + TPos volatile min, max, max_y; + FT_BBox* clip; + + + /* Set up state in the raster object */ + gray_compute_cbox( RAS_VAR ); + + /* clip to target bitmap, exit if nothing to do */ + clip = &ras.clip_box; + + if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax || + ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax ) + return 0; + + if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin; + if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin; + + if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax; + if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax; + + /* simple heuristic used to speed-up the bezier decomposition -- see */ + /* the code in gray_render_conic() and gray_render_cubic() for more */ + /* details */ + ras.conic_level = 32; + ras.cubic_level = 16; + + { + int level = 0; + + + if ( ras.max_ex > 24 || ras.max_ey > 24 ) + level++; + if ( ras.max_ex > 120 || ras.max_ey > 120 ) + level++; + + ras.conic_level <<= level; + ras.cubic_level <<= level; + } + + /* setup vertical bands */ + num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size ); + if ( num_bands == 0 ) num_bands = 1; + if ( num_bands >= 39 ) num_bands = 39; + + ras.band_shoot = 0; + + min = ras.min_ey; + max_y = ras.max_ey; + + for ( n = 0; n < num_bands; n++, min = max ) + { + max = min + ras.band_size; + if ( n == num_bands - 1 || max > max_y ) + max = max_y; + + bands[0].min = min; + bands[0].max = max; + band = bands; + + while ( band >= bands ) + { + TPos bottom, top, middle; + int error; + + + ras.num_cells = 0; + ras.invalid = 1; + ras.min_ey = band->min; + ras.max_ey = band->max; + +#if 1 + error = gray_convert_glyph_inner( RAS_VAR ); +#else + error = FT_Outline_Decompose( outline, &func_interface, &ras ) || + gray_record_cell( RAS_VAR ); +#endif + + if ( !error ) + { +#ifdef SHELL_SORT + gray_shell_sort( ras.cells, ras.num_cells ); +#else + gray_quick_sort( ras.cells, ras.num_cells ); +#endif + +#ifdef DEBUG_GRAYS + gray_check_sort( ras.cells, ras.num_cells ); + gray_dump_cells( RAS_VAR ); +#endif + + gray_sweep( RAS_VAR_ &ras.target ); + band--; + continue; + } + else if ( error != ErrRaster_MemoryOverflow ) + return 1; + + /* render pool overflow, we will reduce the render band by half */ + bottom = band->min; + top = band->max; + middle = bottom + ( ( top - bottom ) >> 1 ); + + /* waoow! This is too complex for a single scanline, something */ + /* must be really rotten here! */ + if ( middle == bottom ) + { +#ifdef DEBUG_GRAYS + fprintf( stderr, "Rotten glyph!\n" ); +#endif + return 1; + } + + if ( bottom-top >= ras.band_size ) + ras.band_shoot++; + + band[1].min = bottom; + band[1].max = middle; + band[0].min = middle; + band[0].max = top; + band++; + } + } + + if ( ras.band_shoot > 8 && ras.band_size > 16 ) + ras.band_size = ras.band_size / 2; + + return 0; + } + + + extern int + gray_raster_render( PRaster raster, + FT_Raster_Params* params ) + { + FT_Outline* outline = (FT_Outline*)params->source; + FT_Bitmap* target_map = params->target; + + + if ( !raster || !raster->cells || !raster->max_cells ) + return -1; + + /* return immediately if the outline is empty */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + return 0; + + if ( !outline || !outline->contours || !outline->points ) + return ErrRaster_Invalid_Outline; + + if ( outline->n_points != + outline->contours[outline->n_contours - 1] + 1 ) + return ErrRaster_Invalid_Outline; + + /* if direct mode is not set, we must have a target bitmap */ + if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 && + ( !target_map || !target_map->buffer ) ) + return -1; + + /* this version does not support monochrome rendering */ + if ( !( params->flags & FT_RASTER_FLAG_AA ) ) + return ErrRaster_Invalid_Mode; + + /* compute clipping box */ + if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 ) + { + /* compute clip box from target pixmap */ + ras.clip_box.xMin = 0; + ras.clip_box.yMin = 0; + ras.clip_box.xMax = target_map->width; + ras.clip_box.yMax = target_map->rows; + } + else if ( params->flags & FT_RASTER_FLAG_CLIP ) + { + ras.clip_box = params->clip_box; + } + else + { + ras.clip_box.xMin = -32768L; + ras.clip_box.yMin = -32768L; + ras.clip_box.xMax = 32767L; + ras.clip_box.yMax = 32767L; + } + + ras.outline = *outline; + ras.num_cells = 0; + ras.invalid = 1; + + if ( target_map ) + ras.target = *target_map; + + ras.render_span = (FT_Raster_Span_Func)gray_render_span; + ras.render_span_data = &ras; + + if ( params->flags & FT_RASTER_FLAG_DIRECT ) + { + ras.render_span = (FT_Raster_Span_Func)params->gray_spans; + ras.render_span_data = params->user; + } + + return gray_convert_glyph( (PRaster)raster ); + } + + + /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ + /**** a static object. *****/ + +#ifdef GRAYS_USE_GAMMA + + /* initialize the "gamma" table. Yes, this is really a crummy function */ + /* but the results look pretty good for something that simple. */ + /* */ +#define M_MAX 255 +#define M_X 128 +#define M_Y 192 + + static void + grays_init_gamma( PRaster raster ) + { + unsigned int x, a; + + + for ( x = 0; x < 256; x++ ) + { + if ( x <= M_X ) + a = ( x * M_Y + M_X / 2) / M_X; + else + a = M_Y + ( ( x - M_X ) * ( M_MAX - M_Y ) + + ( M_MAX - M_X ) / 2 ) / ( M_MAX - M_X ); + + raster->gamma[x] = (unsigned char)a; + } + } + +#endif /* GRAYS_USE_GAMMA */ + +#ifdef _STANDALONE_ + + static int + gray_raster_new( void* memory, + FT_Raster* araster ) + { + static TRaster the_raster; + + FT_UNUSED( memory ); + + + *araster = (FT_Raster)&the_raster; + FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) ); + +#ifdef GRAYS_USE_GAMMA + grays_init_gamma( (PRaster)*araster ); +#endif + + return 0; + } + + + static void + gray_raster_done( FT_Raster raster ) + { + /* nothing */ + FT_UNUSED( raster ); + } + +#else /* _STANDALONE_ */ + + static int + gray_raster_new( FT_Memory memory, + FT_Raster* araster ) + { + FT_Error error; + PRaster raster; + + + *araster = 0; + if ( !FT_ALLOC( raster, sizeof ( TRaster ) ) ) + { + raster->memory = memory; + *araster = (FT_Raster)raster; + +#ifdef GRAYS_USE_GAMMA + grays_init_gamma( raster ); +#endif + } + + return error; + } + + + static void + gray_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((PRaster)raster)->memory; + + + FT_FREE( raster ); + } + +#endif /* _STANDALONE_ */ + + + static void + gray_raster_reset( FT_Raster raster, + const char* pool_base, + long pool_size ) + { + PRaster rast = (PRaster)raster; + + + if ( raster && pool_base && pool_size >= 4096 ) + gray_init_cells( rast, (char*)pool_base, pool_size ); + + rast->band_size = (int)( ( pool_size / sizeof ( TCell ) ) / 8 ); + } + + + const FT_Raster_Funcs ft_grays_raster = + { + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Raster_New_Func) gray_raster_new, + (FT_Raster_Reset_Func) gray_raster_reset, + (FT_Raster_Set_Mode_Func)0, + (FT_Raster_Render_Func) gray_raster_render, + (FT_Raster_Done_Func) gray_raster_done + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/smooth/ftgrays.h b/Utilities/vtkfreetype/src/smooth/ftgrays.h new file mode 100644 index 0000000..2d40954 --- /dev/null +++ b/Utilities/vtkfreetype/src/smooth/ftgrays.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* ftgrays.h */ +/* */ +/* FreeType smooth renderer declaration */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTGRAYS_H__ +#define __FTGRAYS_H__ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef _STANDALONE_ +#include "ftimage.h" +#else +#include <ft2build.h> +#include FT_IMAGE_H +#endif + + + /*************************************************************************/ + /* */ + /* To make ftgrays.h independent from configuration files we check */ + /* whether FT_EXPORT_VAR has been defined already. */ + /* */ + /* On some systems and compilers (Win32 mostly), an extra keyword is */ + /* necessary to compile the library as a DLL. */ + /* */ +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + + FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_grays_raster; + + +#ifdef __cplusplus + } +#endif + +#endif /* __FTGRAYS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/smooth/ftsmerrs.h b/Utilities/vtkfreetype/src/smooth/ftsmerrs.h new file mode 100644 index 0000000..0c2a2ec --- /dev/null +++ b/Utilities/vtkfreetype/src/smooth/ftsmerrs.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* ftsmerrs.h */ +/* */ +/* smooth renderer error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the smooth renderer error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __FTSMERRS_H__ +#define __FTSMERRS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX Smooth_Err_ +#define FT_ERR_BASE FT_Mod_Err_Smooth + +#include FT_ERRORS_H + +#endif /* __FTSMERRS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/smooth/ftsmooth.c b/Utilities/vtkfreetype/src/smooth/ftsmooth.c new file mode 100644 index 0000000..af8783e --- /dev/null +++ b/Utilities/vtkfreetype/src/smooth/ftsmooth.c @@ -0,0 +1,374 @@ +/***************************************************************************/ +/* */ +/* ftsmooth.c */ +/* */ +/* Anti-aliasing renderer interface (body). */ +/* */ +/* Copyright 2000-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_OUTLINE_H +#include "ftsmooth.h" +#include "ftgrays.h" + +#include "ftsmerrs.h" + + + /* initialize renderer -- init its raster */ + static FT_Error + ft_smooth_init( FT_Renderer render ) + { + FT_Library library = FT_MODULE_LIBRARY( render ); + + + render->clazz->raster_class->raster_reset( render->raster, + library->raster_pool, + library->raster_pool_size ); + + return 0; + } + + + /* sets render-specific mode */ + static FT_Error + ft_smooth_set_mode( FT_Renderer render, + FT_ULong mode_tag, + FT_Pointer data ) + { + /* we simply pass it to the raster */ + return render->clazz->raster_class->raster_set_mode( render->raster, + mode_tag, + data ); + } + + /* transform a given glyph image */ + static FT_Error + ft_smooth_transform( FT_Renderer render, + FT_GlyphSlot slot, + FT_Matrix* matrix, + FT_Vector* delta ) + { + FT_Error error = Smooth_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = Smooth_Err_Invalid_Argument; + goto Exit; + } + + if ( matrix ) + FT_Outline_Transform( &slot->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &slot->outline, delta->x, delta->y ); + + Exit: + return error; + } + + + /* return the glyph's control box */ + static void + ft_smooth_get_cbox( FT_Renderer render, + FT_GlyphSlot slot, + FT_BBox* cbox ) + { + FT_MEM_ZERO( cbox, sizeof ( *cbox ) ); + + if ( slot->format == render->glyph_format ) + FT_Outline_Get_CBox( &slot->outline, cbox ); + } + + + /* convert a slot's glyph image into a bitmap */ + static FT_Error + ft_smooth_render_generic( FT_Renderer render, + FT_GlyphSlot slot, + FT_Render_Mode mode, + FT_Vector* origin, + FT_Render_Mode required_mode, + FT_Int hmul, + FT_Int vmul ) + { + FT_Error error; + FT_Outline* outline = NULL; + FT_BBox cbox; + FT_UInt width, height, pitch; + FT_Bitmap* bitmap; + FT_Memory memory; + + FT_Raster_Params params; + + + /* check glyph image format */ + if ( slot->format != render->glyph_format ) + { + error = Smooth_Err_Invalid_Argument; + goto Exit; + } + + /* check mode */ + if ( mode != required_mode ) + return Smooth_Err_Cannot_Render_Glyph; + + outline = &slot->outline; + + /* translate the outline to the new origin if needed */ + if ( origin ) + FT_Outline_Translate( outline, origin->x, origin->y ); + + /* compute the control box, and grid fit it */ + FT_Outline_Get_CBox( outline, &cbox ); + + cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); + cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); + cbox.xMax = FT_PIX_CEIL( cbox.xMax ); + cbox.yMax = FT_PIX_CEIL( cbox.yMax ); + + width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 ); + height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 ); + bitmap = &slot->bitmap; + memory = render->root.memory; + + /* release old bitmap buffer */ + if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) + { + FT_FREE( bitmap->buffer ); + slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; + } + + /* allocate new one, depends on pixel format */ + pitch = width; + if ( hmul ) + { + width = width * hmul; + pitch = FT_PAD_CEIL( width, 4 ); + } + + if ( vmul ) + height *= vmul; + + bitmap->pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap->num_grays = 256; + bitmap->width = width; + bitmap->rows = height; + bitmap->pitch = pitch; + + if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) + goto Exit; + + slot->internal->flags |= FT_GLYPH_OWN_BITMAP; + + /* translate outline to render it into the bitmap */ + FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin ); + + /* set up parameters */ + params.target = bitmap; + params.source = outline; + params.flags = FT_RASTER_FLAG_AA; + + /* implode outline if needed */ + { + FT_Int n; + FT_Vector* vec; + + + if ( hmul ) + for ( vec = outline->points, n = 0; n < outline->n_points; n++, vec++ ) + vec->x *= hmul; + + if ( vmul ) + for ( vec = outline->points, n = 0; n < outline->n_points; n++, vec++ ) + vec->y *= vmul; + } + + /* render outline into the bitmap */ + error = render->raster_render( render->raster, ¶ms ); + + /* deflate outline if needed */ + { + FT_Int n; + FT_Vector* vec; + + + if ( hmul ) + for ( vec = outline->points, n = 0; n < outline->n_points; n++, vec++ ) + vec->x /= hmul; + + if ( vmul ) + for ( vec = outline->points, n = 0; n < outline->n_points; n++, vec++ ) + vec->y /= vmul; + } + + FT_Outline_Translate( outline, cbox.xMin, cbox.yMin ); + + if ( error ) + goto Exit; + + slot->format = FT_GLYPH_FORMAT_BITMAP; + slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 ); + slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 ); + + Exit: + if ( outline && origin ) + FT_Outline_Translate( outline, -origin->x, -origin->y ); + + return error; + } + + + /* convert a slot's glyph image into a bitmap */ + static FT_Error + ft_smooth_render( FT_Renderer render, + FT_GlyphSlot slot, + FT_Render_Mode mode, + FT_Vector* origin ) + { + if ( mode == FT_RENDER_MODE_LIGHT ) + mode = FT_RENDER_MODE_NORMAL; + + return ft_smooth_render_generic( render, slot, mode, origin, + FT_RENDER_MODE_NORMAL, + 0, 0 ); + } + + + /* convert a slot's glyph image into a horizontal LCD bitmap */ + static FT_Error + ft_smooth_render_lcd( FT_Renderer render, + FT_GlyphSlot slot, + FT_Render_Mode mode, + FT_Vector* origin ) + { + FT_Error error; + + error = ft_smooth_render_generic( render, slot, mode, origin, + FT_RENDER_MODE_LCD, + 3, 0 ); + if ( !error ) + slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD; + + return error; + } + + + /* convert a slot's glyph image into a vertical LCD bitmap */ + static FT_Error + ft_smooth_render_lcd_v( FT_Renderer render, + FT_GlyphSlot slot, + FT_Render_Mode mode, + FT_Vector* origin ) + { + FT_Error error; + + error = ft_smooth_render_generic( render, slot, mode, origin, + FT_RENDER_MODE_LCD_V, + 0, 3 ); + if ( !error ) + slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V; + + return error; + } + + + FT_CALLBACK_TABLE_DEF + const FT_Renderer_Class ft_smooth_renderer_class = + { + { + FT_MODULE_RENDERER, + sizeof( FT_RendererRec ), + + "smooth", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_smooth_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Renderer_RenderFunc) ft_smooth_render, + (FT_Renderer_TransformFunc)ft_smooth_transform, + (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, + (FT_Renderer_SetModeFunc) ft_smooth_set_mode, + + (FT_Raster_Funcs*) &ft_grays_raster + }; + + + FT_CALLBACK_TABLE_DEF + const FT_Renderer_Class ft_smooth_lcd_renderer_class = + { + { + FT_MODULE_RENDERER, + sizeof( FT_RendererRec ), + + "smooth-lcd", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_smooth_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Renderer_RenderFunc) ft_smooth_render_lcd, + (FT_Renderer_TransformFunc)ft_smooth_transform, + (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, + (FT_Renderer_SetModeFunc) ft_smooth_set_mode, + + (FT_Raster_Funcs*) &ft_grays_raster + }; + + + + FT_CALLBACK_TABLE_DEF + const FT_Renderer_Class ft_smooth_lcdv_renderer_class = + { + { + FT_MODULE_RENDERER, + sizeof( FT_RendererRec ), + + "smooth-lcdv", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_smooth_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + FT_GLYPH_FORMAT_OUTLINE, + + (FT_Renderer_RenderFunc) ft_smooth_render_lcd_v, + (FT_Renderer_TransformFunc)ft_smooth_transform, + (FT_Renderer_GetCBoxFunc) ft_smooth_get_cbox, + (FT_Renderer_SetModeFunc) ft_smooth_set_mode, + + (FT_Raster_Funcs*) &ft_grays_raster + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/smooth/ftsmooth.h b/Utilities/vtkfreetype/src/smooth/ftsmooth.h new file mode 100644 index 0000000..62cced4 --- /dev/null +++ b/Utilities/vtkfreetype/src/smooth/ftsmooth.h @@ -0,0 +1,49 @@ +/***************************************************************************/ +/* */ +/* ftsmooth.h */ +/* */ +/* Anti-aliasing renderer interface (specification). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __FTSMOOTH_H__ +#define __FTSMOOTH_H__ + + +#include <ft2build.h> +#include FT_RENDER_H + + +FT_BEGIN_HEADER + + +#ifndef FT_CONFIG_OPTION_NO_STD_RASTER + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_std_renderer_class; +#endif + +#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_renderer_class; + + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_lcd_renderer_class; + + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_lcd_v_renderer_class; +#endif + + + +FT_END_HEADER + +#endif /* __FTSMOOTH_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/smooth/smooth.c b/Utilities/vtkfreetype/src/smooth/smooth.c new file mode 100644 index 0000000..ff6be3e --- /dev/null +++ b/Utilities/vtkfreetype/src/smooth/smooth.c @@ -0,0 +1,26 @@ +/***************************************************************************/ +/* */ +/* smooth.c */ +/* */ +/* FreeType anti-aliasing rasterer module component (body only). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "ftgrays.c" +#include "ftsmooth.c" + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/truetype.c b/Utilities/vtkfreetype/src/truetype/truetype.c new file mode 100644 index 0000000..4abb01e --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/truetype.c @@ -0,0 +1,36 @@ +/***************************************************************************/ +/* */ +/* truetype.c */ +/* */ +/* FreeType TrueType driver component (body only). */ +/* */ +/* Copyright 1996-2001, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "ttdriver.c" /* driver interface */ +#include "ttpload.c" /* tables loader */ +#include "ttgload.c" /* glyph loader */ +#include "ttobjs.c" /* object manager */ + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.c" +#endif + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include "ttgxvar.c" /* gx distortable font */ +#endif + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttdriver.c b/Utilities/vtkfreetype/src/truetype/ttdriver.c new file mode 100644 index 0000000..2594883 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttdriver.c @@ -0,0 +1,465 @@ +/***************************************************************************/ +/* */ +/* ttdriver.c */ +/* */ +/* TrueType font driver implementation (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_SFNT_H +#include FT_TRUETYPE_IDS_H +#include FT_SERVICE_XFREE86_NAME_H + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include FT_MULTIPLE_MASTERS_H +#include FT_SERVICE_MULTIPLE_MASTERS_H +#endif + +#include "ttdriver.h" +#include "ttgload.h" + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include "ttgxvar.h" +#endif + +#include "tterrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttdriver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Get_Kerning */ + /* */ + /* <Description> */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* <Output> */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings, are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + static FT_Error + Get_Kerning( FT_Face ttface, /* TT_Face */ + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + TT_Face face = (TT_Face)ttface; + TT_Kern0_Pair pair; + + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + kerning->x = 0; + kerning->y = 0; + + if ( face->kern_pairs ) + { + /* there are some kerning pairs in this font file! */ + FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph ); + FT_Long left, right; + + + left = 0; + right = face->num_kern_pairs - 1; + + while ( left <= right ) + { + FT_Long middle = left + ( ( right - left ) >> 1 ); + FT_ULong cur_pair; + + + pair = face->kern_pairs + middle; + cur_pair = PAIR_TAG( pair->left, pair->right ); + + if ( cur_pair == search_tag ) + goto Found; + + if ( cur_pair < search_tag ) + left = middle + 1; + else + right = middle - 1; + } + } + + Exit: + return TT_Err_Ok; + + Found: + kerning->x = pair->value; + goto Exit; + } + + +#undef PAIR_TAG + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** S I Z E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Set_Char_Sizes */ + /* */ + /* <Description> */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* <Input> */ + /* char_width :: The character width expressed in 26.6 */ + /* fractional points. */ + /* */ + /* char_height :: The character height expressed in 26.6 */ + /* fractional points. */ + /* */ + /* horz_resolution :: The horizontal resolution of the output device. */ + /* */ + /* vert_resolution :: The vertical resolution of the output device. */ + /* */ + /* <InOut> */ + /* size :: A handle to the target size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Set_Char_Sizes( FT_Size ttsize, /* TT_Size */ + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + TT_Size size = (TT_Size)ttsize; + FT_Size_Metrics* metrics = &size->root.metrics; + FT_Size_Metrics* metrics2 = &size->metrics; + TT_Face face = (TT_Face)size->root.face; + FT_Long dim_x, dim_y; + + + *metrics2 = *metrics; + + /* This bit flag, when set, indicates that the pixel size must be */ + /* truncated to an integer. Nearly all TrueType fonts have this */ + /* bit set, as hinting won't work really well otherwise. */ + /* */ + if ( ( face->header.Flags & 8 ) != 0 ) + { + /* we need to use rounding in the following computations. Otherwise, + * the resulting hinted outlines will be very slightly distorted + */ + dim_x = ( ( char_width * horz_resolution + (36+32*72) ) / 72 ) & ~63; + dim_y = ( ( char_height * vert_resolution + (36+32*72) ) / 72 ) & ~63; + } + else + { + dim_x = ( ( char_width * horz_resolution + 36 ) / 72 ); + dim_y = ( ( char_height * vert_resolution + 36 ) / 72 ); + } + + /* we only modify "metrics2", not "metrics", so these changes have */ + /* no effect on the result of the auto-hinter when it is used */ + /* */ + metrics2->x_ppem = (FT_UShort)( dim_x >> 6 ); + metrics2->y_ppem = (FT_UShort)( dim_y >> 6 ); + metrics2->x_scale = FT_DivFix( dim_x, face->root.units_per_EM ); + metrics2->y_scale = FT_DivFix( dim_y, face->root.units_per_EM ); + + size->ttmetrics.valid = FALSE; +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + size->strike_index = 0xFFFFU; +#endif + + return tt_size_reset( size ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Set_Pixel_Sizes */ + /* */ + /* <Description> */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* <InOut> */ + /* size :: A handle to the target size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Set_Pixel_Sizes( FT_Size ttsize, /* TT_Size */ + FT_UInt pixel_width, + FT_UInt pixel_height ) + { + TT_Size size = (TT_Size)ttsize; + + FT_UNUSED( pixel_width ); + FT_UNUSED( pixel_height ); + + + /* many things have been pre-computed by the base layer */ + + size->metrics = size->root.metrics; + size->ttmetrics.valid = FALSE; +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + size->strike_index = 0xFFFFU; +#endif + + return tt_size_reset( size ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Load_Glyph */ + /* */ + /* <Description> */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* <Input> */ + /* slot :: A handle to the target slot object where the glyph */ + /* will be loaded. */ + /* */ + /* size :: A handle to the source face size at which the glyph */ + /* must be scaled, loaded, etc. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FTLOAD_??? constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Load_Glyph( FT_GlyphSlot ttslot, /* TT_GlyphSlot */ + FT_Size ttsize, /* TT_Size */ + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; + TT_Size size = (TT_Size)ttsize; + FT_Error error; + + + if ( !slot ) + return TT_Err_Invalid_Slot_Handle; + + /* check whether we want a scaled outline or bitmap */ + if ( !size ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + if ( load_flags & FT_LOAD_NO_SCALE ) + size = NULL; + + /* reset the size object if necessary */ + if ( size ) + { + /* these two object must have the same parent */ + if ( size->root.face != slot->face ) + return TT_Err_Invalid_Face_Handle; + + if ( !size->ttmetrics.valid ) + { + if ( FT_SET_ERROR( tt_size_reset( size ) ) ) + return error; + } + } + + /* now load the glyph outline if necessary */ + error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); + + /* force drop-out mode to 2 - irrelevant now */ + /* slot->outline.dropout_mode = 2; */ + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R I N T E R F A C E ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + static const FT_Service_MultiMastersRec tt_service_gx_multi_masters = + { + (FT_Get_MM_Func) NULL, + (FT_Set_MM_Design_Func) NULL, + (FT_Set_MM_Blend_Func) TT_Set_MM_Blend, + (FT_Get_MM_Var_Func) TT_Get_MM_Var, + (FT_Set_Var_Design_Func)TT_Set_Var_Design + }; +#endif + + + static const FT_ServiceDescRec tt_services[] = + { + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TRUETYPE }, +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + { FT_SERVICE_ID_MULTI_MASTERS, &tt_service_gx_multi_masters }, +#endif + { NULL, NULL } + }; + + + FT_CALLBACK_DEF( FT_Module_Interface ) + tt_get_interface( FT_Module driver, /* TT_Driver */ + const char* tt_interface ) + { + FT_Module_Interface result; + FT_Module sfntd; + SFNT_Service sfnt; + + + result = ft_service_list_lookup( tt_services, tt_interface ); + if ( result != NULL ) + return result; + + /* only return the default interface from the SFNT module */ + sfntd = FT_Get_Module( driver->library, "sfnt" ); + if ( sfntd ) + { + sfnt = (SFNT_Service)( sfntd->clazz->module_interface ); + if ( sfnt ) + return sfnt->get_interface( driver, tt_interface ); + } + + return 0; + } + + + /* The FT_DriverInterface structure is defined in ftdriver.h. */ + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec tt_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_SCALABLE | +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_MODULE_DRIVER_HAS_HINTER, +#else + 0, +#endif + + sizeof ( TT_DriverRec ), + + "truetype", /* driver name */ + 0x10000L, /* driver version == 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or above */ + + (void*)0, /* driver specific interface */ + + tt_driver_init, + tt_driver_done, + tt_get_interface, + }, + + sizeof ( TT_FaceRec ), + sizeof ( TT_SizeRec ), + sizeof ( FT_GlyphSlotRec ), + + tt_face_init, + tt_face_done, + tt_size_init, + tt_size_done, + 0, /* FT_Slot_InitFunc */ + 0, /* FT_Slot_DoneFunc */ + + Set_Char_Sizes, + Set_Pixel_Sizes, + Load_Glyph, + + Get_Kerning, + 0, /* FT_Face_AttachFunc */ + 0 /* FT_Face_GetAdvancesFunc */ + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttdriver.h b/Utilities/vtkfreetype/src/truetype/ttdriver.h new file mode 100644 index 0000000..f6f26e4 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttdriver.h @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* ttdriver.h */ +/* */ +/* High-level TrueType driver interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTDRIVER_H__ +#define __TTDRIVER_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) tt_driver_class; + + +FT_END_HEADER + +#endif /* __TTDRIVER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/tterrors.h b/Utilities/vtkfreetype/src/truetype/tterrors.h new file mode 100644 index 0000000..d317c70 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/tterrors.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* tterrors.h */ +/* */ +/* TrueType error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the TrueType error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __TTERRORS_H__ +#define __TTERRORS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX TT_Err_ +#define FT_ERR_BASE FT_Mod_Err_TrueType + +#include FT_ERRORS_H + +#endif /* __TTERRORS_H__ */ + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttgload.c b/Utilities/vtkfreetype/src/truetype/ttgload.c new file mode 100644 index 0000000..9fc2d03 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttgload.c @@ -0,0 +1,2039 @@ +/***************************************************************************/ +/* */ +/* ttgload.c */ +/* */ +/* TrueType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_SFNT_H +#include FT_TRUETYPE_TAGS_H +#include FT_OUTLINE_H + +#include "ttgload.h" + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include "ttgxvar.h" +#endif + +#include "tterrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttgload + + + /*************************************************************************/ + /* */ + /* Composite font flags. */ + /* */ +#define ARGS_ARE_WORDS 0x0001 +#define ARGS_ARE_XY_VALUES 0x0002 +#define ROUND_XY_TO_GRID 0x0004 +#define WE_HAVE_A_SCALE 0x0008 +/* reserved 0x0010 */ +#define MORE_COMPONENTS 0x0020 +#define WE_HAVE_AN_XY_SCALE 0x0040 +#define WE_HAVE_A_2X2 0x0080 +#define WE_HAVE_INSTR 0x0100 +#define USE_MY_METRICS 0x0200 +#define OVERLAP_COMPOUND 0x0400 +#define SCALED_COMPONENT_OFFSET 0x0800 +#define UNSCALED_COMPONENT_OFFSET 0x1000 + + +/* Maximum recursion depth we allow for composite glyphs. + * The TrueType spec doesn't say anything about recursion, + * so it isn't clear that recursion is allowed at all. But + * we'll be generous. + */ +#define TT_MAX_COMPOSITE_RECURSE 5 + + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Get_Metrics */ + /* */ + /* <Description> */ + /* Returns the horizontal or vertical metrics in font units for a */ + /* given glyph. The metrics are the left side bearing (resp. top */ + /* side bearing) and advance width (resp. advance height). */ + /* */ + /* <Input> */ + /* header :: A pointer to either the horizontal or vertical metrics */ + /* structure. */ + /* */ + /* idx :: The glyph index. */ + /* */ + /* <Output> */ + /* bearing :: The bearing, either left side or top side. */ + /* */ + /* advance :: The advance width resp. advance height. */ + /* */ + /* <Note> */ + /* This function will much probably move to another component in the */ + /* near future, but I haven't decided which yet. */ + /* */ + FT_LOCAL_DEF( void ) + TT_Get_Metrics( TT_HoriHeader* header, + FT_UInt idx, + FT_Short* bearing, + FT_UShort* advance ) + { + TT_LongMetrics longs_m; + FT_UShort k = header->number_Of_HMetrics; + + + if ( k == 0 ) + { + *bearing = *advance = 0; + return; + } + + if ( idx < (FT_UInt)k ) + { + longs_m = (TT_LongMetrics )header->long_metrics + idx; + *bearing = longs_m->bearing; + *advance = longs_m->advance; + } + else + { + *bearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k]; + *advance = ((TT_LongMetrics )header->long_metrics)[k - 1].advance; + } + } + + + /*************************************************************************/ + /* */ + /* Returns the horizontal metrics in font units for a given glyph. If */ + /* `check' is true, take care of monospaced fonts by returning the */ + /* advance width maximum. */ + /* */ + static void + Get_HMetrics( TT_Face face, + FT_UInt idx, + FT_Bool check, + FT_Short* lsb, + FT_UShort* aw ) + { + TT_Get_Metrics( &face->horizontal, idx, lsb, aw ); + + if ( check && face->postscript.isFixedPitch ) + *aw = face->horizontal.advance_Width_Max; + } + + + /*************************************************************************/ + /* */ + /* Returns the advance width table for a given pixel size if it is found */ + /* in the font's `hdmx' table (if any). */ + /* */ + static FT_Byte* + Get_Advance_Widths( TT_Face face, + FT_UShort ppem ) + { + FT_UShort n; + + + for ( n = 0; n < face->hdmx.num_records; n++ ) + if ( face->hdmx.records[n].ppem == ppem ) + return face->hdmx.records[n].widths; + + return NULL; + } + + + /*************************************************************************/ + /* */ + /* Returns the vertical metrics in font units for a given glyph. */ + /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */ + /* table, typoAscender/Descender from the `OS/2' table would be used */ + /* instead, and if there were no `OS/2' table, use ascender/descender */ + /* from the `hhea' table. But that is not what Microsoft's rasterizer */ + /* apparently does: It uses the ppem value as the advance height, and */ + /* sets the top side bearing to be zero. */ + /* */ + /* The monospace `check' is probably not meaningful here, but we leave */ + /* it in for a consistent interface. */ + /* */ + static void + Get_VMetrics( TT_Face face, + FT_UInt idx, + FT_Bool check, + FT_Short* tsb, + FT_UShort* ah ) + { + FT_UNUSED( check ); + + if ( face->vertical_info ) + TT_Get_Metrics( (TT_HoriHeader *)&face->vertical, idx, tsb, ah ); + +#if 1 /* Emperically determined, at variance with what MS said */ + + else + { + *tsb = 0; + *ah = face->root.units_per_EM; + } + +#else /* This is what MS said to do. It isn't what they do, however. */ + + else if ( face->os2.version != 0xFFFFU ) + { + *tsb = face->os2.sTypoAscender; + *ah = face->os2.sTypoAscender - face->os2.sTypoDescender; + } + else + { + *tsb = face->horizontal.Ascender; + *ah = face->horizontal.Ascender - face->horizontal.Descender; + } + +#endif + + } + + +#define cur_to_org( n, zone ) \ + FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) ) + +#define org_to_cur( n, zone ) \ + FT_ARRAY_COPY( (zone)->cur, (zone)->org, (n) ) + + + /*************************************************************************/ + /* */ + /* Translates an array of coordinates. */ + /* */ + static void + translate_array( FT_UInt n, + FT_Vector* coords, + FT_Pos delta_x, + FT_Pos delta_y ) + { + FT_UInt k; + + + if ( delta_x ) + for ( k = 0; k < n; k++ ) + coords[k].x += delta_x; + + if ( delta_y ) + for ( k = 0; k < n; k++ ) + coords[k].y += delta_y; + } + + + static void + tt_prepare_zone( TT_GlyphZone zone, + FT_GlyphLoad load, + FT_UInt start_point, + FT_UInt start_contour ) + { + zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); + zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour ); + zone->org = load->extra_points + start_point; + zone->cur = load->outline.points + start_point; + zone->tags = (FT_Byte*)load->outline.tags + start_point; + zone->contours = (FT_UShort*)load->outline.contours + start_contour; + } + + +#undef IS_HINTED +#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) + + + /*************************************************************************/ + /* */ + /* The following functions are used by default with TrueType fonts. */ + /* However, they can be replaced by alternatives if we need to support */ + /* TrueType-compressed formats (like MicroType) in the future. */ + /* */ + /*************************************************************************/ + + FT_CALLBACK_DEF( FT_Error ) + TT_Access_Glyph_Frame( TT_Loader loader, + FT_UInt glyph_index, + FT_ULong offset, + FT_UInt byte_count ) + { + FT_Error error; + FT_Stream stream = loader->stream; + + /* for non-debug mode */ + FT_UNUSED( glyph_index ); + + + FT_TRACE5(( "Glyph %ld\n", glyph_index )); + + /* the following line sets the `error' variable through macros! */ + if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) + return error; + + return TT_Err_Ok; + } + + + FT_CALLBACK_DEF( void ) + TT_Forget_Glyph_Frame( TT_Loader loader ) + { + FT_Stream stream = loader->stream; + + + FT_FRAME_EXIT(); + } + + + FT_CALLBACK_DEF( FT_Error ) + TT_Load_Glyph_Header( TT_Loader loader ) + { + FT_Stream stream = loader->stream; + FT_Int byte_len = loader->byte_len - 10; + + + if ( byte_len < 0 ) + return TT_Err_Invalid_Outline; + + loader->n_contours = FT_GET_SHORT(); + + loader->bbox.xMin = FT_GET_SHORT(); + loader->bbox.yMin = FT_GET_SHORT(); + loader->bbox.xMax = FT_GET_SHORT(); + loader->bbox.yMax = FT_GET_SHORT(); + + FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); + FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, + loader->bbox.xMax )); + FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, + loader->bbox.yMax )); + loader->byte_len = byte_len; + + return TT_Err_Ok; + } + + + FT_CALLBACK_DEF( FT_Error ) + TT_Load_Simple_Glyph( TT_Loader load ) + { + FT_Error error; + FT_Stream stream = load->stream; + FT_GlyphLoader gloader = load->gloader; + FT_Int n_contours = load->n_contours; + FT_Outline* outline; + TT_Face face = (TT_Face)load->face; + TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph; + FT_UShort n_ins; + FT_Int n, n_points; + FT_Int byte_len = load->byte_len; + + FT_Byte *flag, *flag_limit; + FT_Byte c, count; + FT_Vector *vec, *vec_limit; + FT_Pos x; + FT_Short *cont, *cont_limit; + + + /* reading the contours' endpoints & number of points */ + cont = gloader->current.outline.contours; + cont_limit = cont + n_contours; + + /* check space for contours array + instructions count */ + byte_len -= 2 * ( n_contours + 1 ); + if ( byte_len < 0 ) + goto Invalid_Outline; + + for ( ; cont < cont_limit; cont++ ) + cont[0] = FT_GET_USHORT(); + + n_points = 0; + if ( n_contours > 0 ) + n_points = cont[-1] + 1; + + error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 ); + if ( error ) + goto Fail; + + /* we'd better check the contours table right now */ + outline = &gloader->current.outline; + + for ( cont = outline->contours + 1; cont < cont_limit; cont++ ) + if ( cont[-1] >= cont[0] ) + goto Invalid_Outline; + + /* reading the bytecode instructions */ + slot->control_len = 0; + slot->control_data = 0; + + n_ins = FT_GET_USHORT(); + + FT_TRACE5(( " Instructions size: %u\n", n_ins )); + + if ( n_ins > face->max_profile.maxSizeOfInstructions ) + { + FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" )); + error = TT_Err_Too_Many_Hints; + goto Fail; + } + + byte_len -= (FT_Int)n_ins; + if ( byte_len < 0 ) + { + FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" )); + error = TT_Err_Too_Many_Hints; + goto Fail; + } + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( ( load->load_flags & + ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 && + load->instructions ) + { + slot->control_len = n_ins; + slot->control_data = load->instructions; + + FT_MEM_COPY( load->instructions, stream->cursor, (FT_Long)n_ins ); + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + stream->cursor += (FT_Int)n_ins; + + /* reading the point tags */ + flag = (FT_Byte*)outline->tags; + flag_limit = flag + n_points; + + while ( flag < flag_limit ) + { + if ( --byte_len < 0 ) + goto Invalid_Outline; + + *flag++ = c = FT_GET_BYTE(); + if ( c & 8 ) + { + if ( --byte_len < 0 ) + goto Invalid_Outline; + + count = FT_GET_BYTE(); + if ( flag + (FT_Int)count > flag_limit ) + goto Invalid_Outline; + + for ( ; count > 0; count-- ) + *flag++ = c; + } + } + + /* check that there is enough room to load the coordinates */ + for ( flag = (FT_Byte*)outline->tags; flag < flag_limit; flag++ ) + { + if ( *flag & 2 ) + byte_len -= 1; + else if ( ( *flag & 16 ) == 0 ) + byte_len -= 2; + + if ( *flag & 4 ) + byte_len -= 1; + else if ( ( *flag & 32 ) == 0 ) + byte_len -= 2; + } + + if ( byte_len < 0 ) + goto Invalid_Outline; + + /* reading the X coordinates */ + + vec = outline->points; + vec_limit = vec + n_points; + flag = (FT_Byte*)outline->tags; + x = 0; + + for ( ; vec < vec_limit; vec++, flag++ ) + { + FT_Pos y = 0; + + + if ( *flag & 2 ) + { + y = (FT_Pos)FT_GET_BYTE(); + if ( ( *flag & 16 ) == 0 ) + y = -y; + } + else if ( ( *flag & 16 ) == 0 ) + y = (FT_Pos)FT_GET_SHORT(); + + x += y; + vec->x = x; + } + + /* reading the Y coordinates */ + + vec = gloader->current.outline.points; + vec_limit = vec + n_points; + flag = (FT_Byte*)outline->tags; + x = 0; + + for ( ; vec < vec_limit; vec++, flag++ ) + { + FT_Pos y = 0; + + + if ( *flag & 4 ) + { + y = (FT_Pos)FT_GET_BYTE(); + if ( ( *flag & 32 ) == 0 ) + y = -y; + } + else if ( ( *flag & 32 ) == 0 ) + y = (FT_Pos)FT_GET_SHORT(); + + x += y; + vec->y = x; + } + + /* clear the touch tags */ + for ( n = 0; n < n_points; n++ ) + outline->tags[n] &= FT_CURVE_TAG_ON; + + outline->n_points = (FT_UShort)n_points; + outline->n_contours = (FT_Short) n_contours; + + load->byte_len = byte_len; + + Fail: + return error; + + Invalid_Outline: + error = TT_Err_Invalid_Outline; + goto Fail; + } + + + FT_CALLBACK_DEF( FT_Error ) + TT_Load_Composite_Glyph( TT_Loader loader ) + { + FT_Error error; + FT_Stream stream = loader->stream; + FT_GlyphLoader gloader = loader->gloader; + FT_SubGlyph subglyph; + FT_UInt num_subglyphs; + FT_Int byte_len = loader->byte_len; + + + num_subglyphs = 0; + + do + { + FT_Fixed xx, xy, yy, yx; + + + /* check that we can load a new subglyph */ + error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 ); + if ( error ) + goto Fail; + + /* check space */ + byte_len -= 4; + if ( byte_len < 0 ) + goto Invalid_Composite; + + subglyph = gloader->current.subglyphs + num_subglyphs; + + subglyph->arg1 = subglyph->arg2 = 0; + + subglyph->flags = FT_GET_USHORT(); + subglyph->index = FT_GET_USHORT(); + + /* check space */ + byte_len -= 2; + if ( subglyph->flags & ARGS_ARE_WORDS ) + byte_len -= 2; + if ( subglyph->flags & WE_HAVE_A_SCALE ) + byte_len -= 2; + else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) + byte_len -= 4; + else if ( subglyph->flags & WE_HAVE_A_2X2 ) + byte_len -= 8; + + if ( byte_len < 0 ) + goto Invalid_Composite; + + /* read arguments */ + if ( subglyph->flags & ARGS_ARE_WORDS ) + { + subglyph->arg1 = FT_GET_SHORT(); + subglyph->arg2 = FT_GET_SHORT(); + } + else + { + subglyph->arg1 = FT_GET_CHAR(); + subglyph->arg2 = FT_GET_CHAR(); + } + + /* read transform */ + xx = yy = 0x10000L; + xy = yx = 0; + + if ( subglyph->flags & WE_HAVE_A_SCALE ) + { + xx = (FT_Fixed)FT_GET_SHORT() << 2; + yy = xx; + } + else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) + { + xx = (FT_Fixed)FT_GET_SHORT() << 2; + yy = (FT_Fixed)FT_GET_SHORT() << 2; + } + else if ( subglyph->flags & WE_HAVE_A_2X2 ) + { + xx = (FT_Fixed)FT_GET_SHORT() << 2; + yx = (FT_Fixed)FT_GET_SHORT() << 2; + xy = (FT_Fixed)FT_GET_SHORT() << 2; + yy = (FT_Fixed)FT_GET_SHORT() << 2; + } + + subglyph->transform.xx = xx; + subglyph->transform.xy = xy; + subglyph->transform.yx = yx; + subglyph->transform.yy = yy; + + num_subglyphs++; + + } while ( subglyph->flags & MORE_COMPONENTS ); + + gloader->current.num_subglyphs = num_subglyphs; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + { + /* we must undo the FT_FRAME_ENTER in order to point to the */ + /* composite instructions, if we find some. */ + /* we will process them later... */ + /* */ + loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + + stream->cursor - stream->limit ); + } +#endif + + loader->byte_len = byte_len; + + Fail: + return error; + + Invalid_Composite: + error = TT_Err_Invalid_Composite; + goto Fail; + } + + + FT_LOCAL_DEF( void ) + TT_Init_Glyph_Loading( TT_Face face ) + { + face->access_glyph_frame = TT_Access_Glyph_Frame; + face->read_glyph_header = TT_Load_Glyph_Header; + face->read_simple_glyph = TT_Load_Simple_Glyph; + face->read_composite_glyph = TT_Load_Composite_Glyph; + face->forget_glyph_frame = TT_Forget_Glyph_Frame; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Process_Simple_Glyph */ + /* */ + /* <Description> */ + /* Once a simple glyph has been loaded, it needs to be processed. */ + /* Usually, this means scaling and hinting through bytecode */ + /* interpretation. */ + /* */ + static FT_Error + TT_Process_Simple_Glyph( TT_Loader load, + FT_Bool debug ) + { + FT_GlyphLoader gloader = load->gloader; + FT_Outline* outline = &gloader->current.outline; + FT_UInt n_points = outline->n_points; +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_UInt n_ins; +#endif + TT_GlyphZone zone = &load->zone; + FT_Error error = TT_Err_Ok; + + FT_UNUSED( debug ); /* used by truetype interpreter only */ + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + n_ins = load->glyph->control_len; +#endif + + /* add shadow points */ + + /* Add two horizontal shadow points at n and n+1. */ + /* We need the left side bearing and advance width. */ + /* Add two vertical shadow points at n+2 and n+3. */ + /* We need the top side bearing and advance height. */ + + { + FT_Vector* pp1; + FT_Vector* pp2; + FT_Vector* pp3; + FT_Vector* pp4; + + + /* pp1 = xMin - lsb */ + pp1 = outline->points + n_points; + pp1->x = load->bbox.xMin - load->left_bearing; + pp1->y = 0; + + /* pp2 = pp1 + aw */ + pp2 = pp1 + 1; + pp2->x = pp1->x + load->advance; + pp2->y = 0; + + /* pp3 = top side bearing */ + pp3 = pp1 + 2; + pp3->x = 0; + pp3->y = load->top_bearing + load->bbox.yMax; + + /* pp4 = pp3 - ah */ + pp4 = pp1 + 3; + pp4->x = 0; + pp4->y = pp3->y - load->vadvance; + + outline->tags[n_points ] = 0; + outline->tags[n_points + 1] = 0; + outline->tags[n_points + 2] = 0; + outline->tags[n_points + 3] = 0; + } + + /* Note that we return four more points that are not */ + /* part of the glyph outline. */ + + n_points += 4; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + if ( ((TT_Face)load->face)->doblend ) + { + /* Deltas apply to the unscaled data. */ + FT_Vector* deltas; + FT_Memory memory = load->face->memory; + FT_StreamRec saved_stream = *(load->stream); + FT_UInt i; + + + /* TT_Vary_Get_Glyph_Deltas uses a frame, thus we have to save */ + /* (and restore) the current one */ + load->stream->cursor = 0; + load->stream->limit = 0; + + error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(load->face), + load->glyph_index, + &deltas, + n_points ); + + *(load->stream) = saved_stream; + + if ( error ) + goto Exit; + + for ( i = 0; i < n_points; ++i ) + { + outline->points[i].x += deltas[i].x; + outline->points[i].y += deltas[i].y; + } + + FT_FREE( deltas ); + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + /* set up zone for hinting */ + tt_prepare_zone( zone, &gloader->current, 0, 0 ); + + /* eventually scale the glyph */ + if ( !( load->load_flags & FT_LOAD_NO_SCALE ) ) + { + FT_Vector* vec = zone->cur; + FT_Vector* limit = vec + n_points; + FT_Fixed x_scale = ((TT_Size)load->size)->metrics.x_scale; + FT_Fixed y_scale = ((TT_Size)load->size)->metrics.y_scale; + + /* first scale the glyph points */ + for ( ; vec < limit; vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + } + + cur_to_org( n_points, zone ); + + /* eventually hint the glyph */ + if ( IS_HINTED( load->load_flags ) ) + { + FT_Pos x = zone->org[n_points-4].x; + FT_Pos y = zone->org[n_points-2].y; + + + x = FT_PIX_ROUND( x ) - x; + y = FT_PIX_ROUND( y ) - y; + translate_array( n_points, zone->org, x, y ); + + org_to_cur( n_points, zone ); + + zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x ); + zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* now consider hinting */ + if ( n_ins > 0 ) + { + error = TT_Set_CodeRange( load->exec, tt_coderange_glyph, + load->exec->glyphIns, n_ins ); + if ( error ) + goto Exit; + + load->exec->is_composite = FALSE; + load->exec->pedantic_hinting = (FT_Bool)( load->load_flags & + FT_LOAD_PEDANTIC ); + load->exec->pts = *zone; + load->exec->pts.n_points += 4; + + error = TT_Run_Context( load->exec, debug ); + if ( error && load->exec->pedantic_hinting ) + goto Exit; + + error = TT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */ + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + } + + /* save glyph phantom points */ + if ( !load->preserve_pps ) + { + load->pp1 = zone->cur[n_points - 4]; + load->pp2 = zone->cur[n_points - 3]; + load->pp3 = zone->cur[n_points - 2]; + load->pp4 = zone->cur[n_points - 1]; + } + +#if defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) || \ + defined( TT_CONFIG_OPTION_GX_VAR_SUPPORT ) + Exit: +#endif + + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* load_truetype_glyph */ + /* */ + /* <Description> */ + /* Loads a given truetype glyph. Handles composites and uses a */ + /* TT_Loader object. */ + /* */ + static FT_Error + load_truetype_glyph( TT_Loader loader, + FT_UInt glyph_index, + FT_UInt recurse_count ) + { + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_Stream stream = loader->stream; +#endif + + FT_Error error; + TT_Face face = (TT_Face)loader->face; + FT_ULong offset; + FT_Int contours_count; + FT_UInt num_points, count; + FT_Fixed x_scale, y_scale; + FT_GlyphLoader gloader = loader->gloader; + FT_Bool opened_frame = 0; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + FT_StreamRec inc_stream; + FT_Data glyph_data; + FT_Bool glyph_data_loaded = 0; +#endif + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + FT_Vector *deltas; +#endif + + + if ( recurse_count >= TT_MAX_COMPOSITE_RECURSE ) + { + error = TT_Err_Invalid_Composite; + goto Exit; + } + + /* check glyph index */ + if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) + { + error = TT_Err_Invalid_Glyph_Index; + goto Exit; + } + + loader->glyph_index = glyph_index; + num_points = 0; + + x_scale = 0x10000L; + y_scale = 0x10000L; + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + x_scale = ((TT_Size)loader->size)->metrics.x_scale; + y_scale = ((TT_Size)loader->size)->metrics.y_scale; + } + + /* get metrics, horizontal and vertical */ + { + FT_Short left_bearing = 0, top_bearing = 0; + FT_UShort advance_width = 0, advance_height = 0; + + + Get_HMetrics( face, glyph_index, + (FT_Bool)!( loader->load_flags & + FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), + &left_bearing, + &advance_width ); + Get_VMetrics( face, glyph_index, + (FT_Bool)!( loader->load_flags & + FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), + &top_bearing, + &advance_height ); + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* If this is an incrementally loaded font see if there are */ + /* overriding metrics for this glyph. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + { + FT_Incremental_MetricsRec metrics; + + + metrics.bearing_x = left_bearing; + metrics.bearing_y = 0; + metrics.advance = advance_width; + error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( + face->root.internal->incremental_interface->object, + glyph_index, FALSE, &metrics ); + if ( error ) + goto Exit; + left_bearing = (FT_Short)metrics.bearing_x; + advance_width = (FT_UShort)metrics.advance; + } + +# if 0 + /* GWW: Do I do the same for vertical metrics ??? */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + { + FT_Incremental_MetricsRec metrics; + + + metrics.bearing_x = 0; + metrics.bearing_y = top_bearing; + metrics.advance = advance_height; + error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( + face->root.internal->incremental_interface->object, + glyph_index, TRUE, &metrics ); + if ( error ) + goto Exit; + top_bearing = (FT_Short)metrics.bearing_y; + advance_height = (FT_UShort)metrics.advance; + } +# endif + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + loader->left_bearing = left_bearing; + loader->advance = advance_width; + loader->top_bearing = top_bearing; + loader->vadvance = advance_height; + + if ( !loader->linear_def ) + { + loader->linear_def = 1; + loader->linear = advance_width; + } + } + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* Set `offset' to the start of the glyph program relative to the */ + /* start of the 'glyf' table, and `count' to the length of the */ + /* glyph program in bytes. */ + /* */ + /* If we are loading glyph data via the incremental interface, set */ + /* the loader stream to a memory stream reading the data returned */ + /* by the interface. */ + + if ( face->root.internal->incremental_interface ) + { + error = face->root.internal->incremental_interface->funcs->get_glyph_data( + face->root.internal->incremental_interface->object, + glyph_index, &glyph_data ); + if ( error ) + goto Exit; + + glyph_data_loaded = 1; + offset = 0; + count = glyph_data.length; + + FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) ); + FT_Stream_OpenMemory( &inc_stream, + glyph_data.pointer, glyph_data.length ); + + loader->stream = &inc_stream; + } + else + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + { + offset = face->glyph_locations[glyph_index]; + count = 0; + + if ( glyph_index < (FT_UInt)face->num_locations - 1 ) + count = (FT_UInt)( face->glyph_locations[glyph_index + 1] - offset ); + } + + if ( count == 0 ) + { + /* as described by Frederic Loyer, these are spaces, and */ + /* not the unknown glyph. */ + loader->bbox.xMin = 0; + loader->bbox.xMax = 0; + loader->bbox.yMin = 0; + loader->bbox.yMax = 0; + + loader->pp1.x = 0; + loader->pp2.x = loader->advance; + loader->pp3.y = 0; + loader->pp4.y = loader->pp3.y-loader->vadvance; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( ((TT_Face)(loader->face))->doblend ) + { + /* this must be done before scaling */ + FT_Memory memory = loader->face->memory; + + + if ( (error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), + glyph_index, + &deltas, + 4 ) ) ) + goto Exit; + + loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y; + loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y; + loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y; + loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y; + + FT_FREE( deltas ); + } +#endif + + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); + loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); + } + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( loader->exec ) + loader->exec->glyphSize = 0; + +#endif + + error = TT_Err_Ok; + goto Exit; + } + + loader->byte_len = (FT_Int)count; + + offset = loader->glyf_offset + offset; + + /* access glyph frame */ + error = face->access_glyph_frame( loader, glyph_index, offset, count ); + if ( error ) + goto Exit; + + opened_frame = 1; + + /* read first glyph header */ + error = face->read_glyph_header( loader ); + if ( error ) + goto Fail; + + contours_count = loader->n_contours; + + count -= 10; + + loader->pp1.x = loader->bbox.xMin - loader->left_bearing; + loader->pp1.y = 0; + loader->pp2.x = loader->pp1.x + loader->advance; + loader->pp2.y = 0; + + loader->pp3.x = 0; + loader->pp3.y = loader->top_bearing + loader->bbox.yMax; + loader->pp4.x = 0; + loader->pp4.y = loader->pp3.y - loader->vadvance; + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + /* if it is a simple glyph, load it */ + + if ( contours_count >= 0 ) + { + /* check that we can add the contours to the glyph */ + error = FT_GlyphLoader_CheckPoints( gloader, 0, contours_count ); + if ( error ) + goto Fail; + + error = face->read_simple_glyph( loader ); + if ( error ) + goto Fail; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + { + TT_Size size = (TT_Size)loader->size; + + + error = TT_Process_Simple_Glyph( loader, + (FT_Bool)( size && size->debug ) ); + } + +#else + + error = TT_Process_Simple_Glyph( loader, 0 ); + +#endif + + if ( error ) + goto Fail; + + FT_GlyphLoader_Add( gloader ); + + /* Note: We could have put the simple loader source there */ + /* but the code is fat enough already :-) */ + } + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + /* otherwise, load a composite! */ + else if ( contours_count == -1 ) + { + TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph; + FT_UInt start_point; +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_UInt start_contour; + FT_ULong ins_pos; /* position of composite instructions, if any */ +#endif + + + /* for each subglyph, read composite header */ + start_point = gloader->base.outline.n_points; +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + start_contour = gloader->base.outline.n_contours; +#endif + + error = face->read_composite_glyph( loader ); + if ( error ) + goto Fail; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + ins_pos = loader->ins_pos; +#endif + face->forget_glyph_frame( loader ); + opened_frame = 0; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + if ( face->doblend ) + { + FT_Int i, limit; + FT_SubGlyph subglyph; + FT_Memory memory = face->root.memory; + + + /* this provides additional offsets */ + /* for each component's translation */ + + if ( (error = TT_Vary_Get_Glyph_Deltas( + face, + glyph_index, + &deltas, + gloader->current.num_subglyphs + 4 ) ) ) + goto Exit; + + /* Note: No subglyph reallocation here, our pointers are stable. */ + subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs; + limit = gloader->current.num_subglyphs; + + for ( i = 0; i < limit; ++i, ++subglyph ) + { + if ( subglyph->flags & ARGS_ARE_XY_VALUES ) + { + subglyph->arg1 += deltas[i].x; + subglyph->arg2 += deltas[i].y; + } + } + + loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y; + loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y; + loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y; + loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y; + + FT_FREE( deltas ); + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); + loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); + loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); + loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); + } + + /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ + /* `as is' in the glyph slot (the client application will be */ + /* responsible for interpreting these data)... */ + /* */ + if ( loader->load_flags & FT_LOAD_NO_RECURSE ) + { + /* set up remaining glyph fields */ + FT_GlyphLoader_Add( gloader ); + + glyph->num_subglyphs = gloader->base.num_subglyphs; + glyph->format = FT_GLYPH_FORMAT_COMPOSITE; + glyph->subglyphs = gloader->base.subglyphs; + + goto Exit; + } + + /*********************************************************************/ + /*********************************************************************/ + /*********************************************************************/ + + /* Now, read each subglyph independently. */ + { + FT_Int n, num_base_points, num_new_points; + FT_SubGlyph subglyph = 0; + + FT_UInt num_subglyphs = gloader->current.num_subglyphs; + FT_UInt num_base_subgs = gloader->base.num_subglyphs; + + + FT_GlyphLoader_Add( gloader ); + + for ( n = 0; n < (FT_Int)num_subglyphs; n++ ) + { + FT_Vector pp1, pp2, pp3, pp4; + FT_Pos x, y; + + + /* Each time we call load_truetype_glyph in this loop, the */ + /* value of `gloader.base.subglyphs' can change due to table */ + /* reallocations. We thus need to recompute the subglyph */ + /* pointer on each iteration. */ + subglyph = gloader->base.subglyphs + num_base_subgs + n; + + pp1 = loader->pp1; + pp2 = loader->pp2; + pp3 = loader->pp3; + pp4 = loader->pp4; + + num_base_points = gloader->base.outline.n_points; + + error = load_truetype_glyph( loader, subglyph->index, + recurse_count + 1 ); + if ( error ) + goto Fail; + + /* restore subglyph pointer */ + subglyph = gloader->base.subglyphs + num_base_subgs + n; + + if ( subglyph->flags & USE_MY_METRICS ) + { + pp1 = loader->pp1; + pp2 = loader->pp2; + pp3 = loader->pp3; + pp4 = loader->pp4; + } + else + { + loader->pp1 = pp1; + loader->pp2 = pp2; + loader->pp3 = pp3; + loader->pp4 = pp4; + } + + num_points = gloader->base.outline.n_points; + + num_new_points = num_points - num_base_points; + + /* now perform the transform required for this subglyph */ + + if ( subglyph->flags & ( WE_HAVE_A_SCALE | + WE_HAVE_AN_XY_SCALE | + WE_HAVE_A_2X2 ) ) + { + FT_Vector* cur = gloader->base.outline.points + + num_base_points; + FT_Vector* org = gloader->base.extra_points + + num_base_points; + FT_Vector* limit = cur + num_new_points; + + + for ( ; cur < limit; cur++, org++ ) + { + FT_Vector_Transform( cur, &subglyph->transform ); + FT_Vector_Transform( org, &subglyph->transform ); + } + } + + /* apply offset */ + + if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) + { + FT_UInt k = subglyph->arg1; + FT_UInt l = subglyph->arg2; + FT_Vector* p1; + FT_Vector* p2; + + + if ( start_point + k >= (FT_UInt)num_base_points || + l >= (FT_UInt)num_new_points ) + { + error = TT_Err_Invalid_Composite; + goto Fail; + } + + l += num_base_points; + + p1 = gloader->base.outline.points + start_point + k; + p2 = gloader->base.outline.points + start_point + l; + + x = p1->x - p2->x; + y = p1->y - p2->y; + } + else + { + x = subglyph->arg1; + y = subglyph->arg2; + + /* Use a default value dependent on */ + /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */ + /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */ + +#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + if ( !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) && +#else + if ( ( subglyph->flags & SCALED_COMPONENT_OFFSET ) && +#endif + ( subglyph->flags & ( WE_HAVE_A_SCALE | + WE_HAVE_AN_XY_SCALE | + WE_HAVE_A_2X2 )) ) + { +#if 0 + + /*************************************************************************/ + /* */ + /* This algorithm is what Apple documents. But it doesn't work. */ + /* */ + int a = subglyph->transform.xx > 0 ? subglyph->transform.xx + : -subglyph->transform.xx; + int b = subglyph->transform.yx > 0 ? subglyph->transform.yx + : -subglyph->transform.yx; + int c = subglyph->transform.xy > 0 ? subglyph->transform.xy + : -subglyph->transform.xy; + int d = subglyph->transform.yy > 0 ? subglyph->transform.yy + : -subglyph->transform.yy; + int m = a > b ? a : b; + int n = c > d ? c : d; + + + if ( a - b <= 33 && a - b >= -33 ) + m *= 2; + if ( c - d <= 33 && c - d >= -33 ) + n *= 2; + x = FT_MulFix( x, m ); + y = FT_MulFix( y, n ); + +#else /* 0 */ + + /*************************************************************************/ + /* */ + /* This algorithm is a guess and works much better than the above. */ + /* */ + FT_Fixed mac_xscale = FT_SqrtFixed( + FT_MulFix( subglyph->transform.xx, + subglyph->transform.xx ) + + FT_MulFix( subglyph->transform.xy, + subglyph->transform.xy) ); + FT_Fixed mac_yscale = FT_SqrtFixed( + FT_MulFix( subglyph->transform.yy, + subglyph->transform.yy ) + + FT_MulFix( subglyph->transform.yx, + subglyph->transform.yx ) ); + + + x = FT_MulFix( x, mac_xscale ); + y = FT_MulFix( y, mac_yscale ); +#endif /* 0 */ + + } + + if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) + { + x = FT_MulFix( x, x_scale ); + y = FT_MulFix( y, y_scale ); + + if ( subglyph->flags & ROUND_XY_TO_GRID ) + { + x = FT_PIX_ROUND( x ); + y = FT_PIX_ROUND( y ); + } + } + } + + if ( x || y ) + { + translate_array( num_new_points, + gloader->base.outline.points + num_base_points, + x, y ); + + translate_array( num_new_points, + gloader->base.extra_points + num_base_points, + x, y ); + } + } + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* we have finished loading all sub-glyphs; now, look for */ + /* instructions for this composite! */ + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( num_subglyphs > 0 && + loader->exec && + ins_pos > 0 && + subglyph->flags & WE_HAVE_INSTR ) + { + FT_UShort n_ins; + TT_ExecContext exec = loader->exec; + TT_GlyphZone pts; + FT_Vector* pp1; + + + /* read size of instructions */ + if ( FT_STREAM_SEEK( ins_pos ) || + FT_READ_USHORT( n_ins ) ) + goto Fail; + FT_TRACE5(( " Instructions size = %d\n", n_ins )); + + /* in some fonts? */ + if ( n_ins == 0xFFFFU ) + n_ins = 0; + + /* check it */ + if ( n_ins > face->max_profile.maxSizeOfInstructions ) + { + FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n", + n_ins, subglyph->index )); + error = TT_Err_Too_Many_Hints; + goto Fail; + } + + /* read the instructions */ + if ( FT_STREAM_READ( exec->glyphIns, n_ins ) ) + goto Fail; + + glyph->control_data = exec->glyphIns; + glyph->control_len = n_ins; + + error = TT_Set_CodeRange( exec, + tt_coderange_glyph, + exec->glyphIns, + n_ins ); + if ( error ) + goto Fail; + + error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 ); + if ( error ) + goto Fail; + + /* prepare the execution context */ + tt_prepare_zone( &exec->pts, &gloader->base, + start_point, start_contour ); + pts = &exec->pts; + + pts->n_points = (short)( num_points + 4 ); + pts->n_contours = gloader->base.outline.n_contours; + + /* add phantom points */ + pp1 = pts->cur + num_points; + pp1[0] = loader->pp1; + pp1[1] = loader->pp2; + pp1[2] = loader->pp3; + pp1[3] = loader->pp4; + + pts->tags[num_points ] = 0; + pts->tags[num_points + 1] = 0; + pts->tags[num_points + 2] = 0; + pts->tags[num_points + 3] = 0; + + /* if hinting, round the phantom points */ + if ( IS_HINTED( loader->load_flags ) ) + { + pp1[0].x = FT_PIX_ROUND( loader->pp1.x ); + pp1[1].x = FT_PIX_ROUND( loader->pp2.x ); + pp1[2].y = FT_PIX_ROUND( loader->pp3.y ); + pp1[3].y = FT_PIX_ROUND( loader->pp4.y ); + } + + { + FT_UInt k; + + + for ( k = 0; k < num_points; k++ ) + pts->tags[k] &= FT_CURVE_TAG_ON; + } + + cur_to_org( num_points + 4, pts ); + + /* now consider hinting */ + if ( IS_HINTED( loader->load_flags ) && n_ins > 0 ) + { + exec->is_composite = TRUE; + exec->pedantic_hinting = + (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC ); + error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug ); + if ( error && exec->pedantic_hinting ) + goto Fail; + } + + /* save glyph origin and advance points */ + loader->pp1 = pp1[0]; + loader->pp2 = pp1[1]; + loader->pp3 = pp1[2]; + loader->pp4 = pp1[3]; + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + } + /* end of composite loading */ + } + else + { + /* invalid composite count ( negative but not -1 ) */ + error = TT_Err_Invalid_Outline; + goto Fail; + } + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + Fail: + if ( opened_frame ) + face->forget_glyph_frame( loader ); + + Exit: + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( glyph_data_loaded ) + face->root.internal->incremental_interface->funcs->free_glyph_data( + face->root.internal->incremental_interface->object, + &glyph_data ); +#endif + + return error; + } + + + static FT_Error + compute_glyph_metrics( TT_Loader loader, + FT_UInt glyph_index ) + { + FT_BBox bbox; + TT_Face face = (TT_Face)loader->face; + FT_Fixed y_scale; + TT_GlyphSlot glyph = loader->glyph; + TT_Size size = (TT_Size)loader->size; + + + y_scale = 0x10000L; + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + y_scale = size->root.metrics.y_scale; + + if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) + { + glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; + + /* copy outline to our glyph slot */ + FT_GlyphLoader_CopyPoints( glyph->internal->loader, loader->gloader ); + glyph->outline = glyph->internal->loader->base.outline; + + /* translate array so that (0,0) is the glyph's origin */ + FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 ); + + FT_Outline_Get_CBox( &glyph->outline, &bbox ); + + if ( IS_HINTED( loader->load_flags ) ) + { + /* grid-fit the bounding box */ + bbox.xMin = FT_PIX_FLOOR( bbox.xMin ); + bbox.yMin = FT_PIX_FLOOR( bbox.yMin ); + bbox.xMax = FT_PIX_CEIL( bbox.xMax ); + bbox.yMax = FT_PIX_CEIL( bbox.yMax ); + } + } + else + bbox = loader->bbox; + + /* get the device-independent horizontal advance. It is scaled later */ + /* by the base layer. */ + { + FT_Pos advance = loader->linear; + + + /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */ + /* correctly support DynaLab fonts, which have an incorrect */ + /* `advance_Width_Max' field! It is used, to my knowledge, */ + /* exclusively in the X-TrueType font server. */ + /* */ + if ( face->postscript.isFixedPitch && + ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 ) + advance = face->horizontal.advance_Width_Max; + + /* we need to return the advance in font units in linearHoriAdvance, */ + /* it will be scaled later by the base layer. */ + glyph->linearHoriAdvance = advance; + } + + glyph->metrics.horiBearingX = bbox.xMin; + glyph->metrics.horiBearingY = bbox.yMax; + glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; + + /* don't forget to hint the advance when we need to */ + if ( IS_HINTED( loader->load_flags ) ) + glyph->metrics.horiAdvance = FT_PIX_ROUND( glyph->metrics.horiAdvance ); + + /* Now take care of vertical metrics. In the case where there is */ + /* no vertical information within the font (relatively common), make */ + /* up some metrics by `hand'... */ + + { + FT_Short top_bearing; /* vertical top side bearing (EM units) */ + FT_UShort advance_height; /* vertical advance height (EM units) */ + + FT_Pos left; /* scaled vertical left side bearing */ + FT_Pos top; /* scaled vertical top side bearing */ + FT_Pos advance; /* scaled vertical advance height */ + + + /* Get the unscaled top bearing and advance height. */ + if ( face->vertical_info && + face->vertical.number_Of_VMetrics > 0 ) + { + advance_height = (FT_UShort)( loader->pp4.y - loader->pp3.y ); + top_bearing = (FT_Short)( loader->pp3.y - bbox.yMax ); + } + else + { + /* Make up the distances from the horizontal header. */ + + /* NOTE: The OS/2 values are the only `portable' ones, */ + /* which is why we use them, if there is an OS/2 */ + /* table in the font. Otherwise, we use the */ + /* values defined in the horizontal header. */ + /* */ + /* NOTE2: The sTypoDescender is negative, which is why */ + /* we compute the baseline-to-baseline distance */ + /* here with: */ + /* ascender - descender + linegap */ + /* */ + /* NOTE3: This is different from what MS's rasterizer */ + /* appears to do when getting default values */ + /* for the vertical phantom points. We leave */ + /* the old code untouched, but relying on */ + /* phantom points alone might be reasonable */ + /* (i.e., removing the `if' above). */ + if ( face->os2.version != 0xFFFFU ) + { + top_bearing = (FT_Short)( face->os2.sTypoLineGap / 2 ); + advance_height = (FT_UShort)( face->os2.sTypoAscender - + face->os2.sTypoDescender + + face->os2.sTypoLineGap ); + } + else + { + top_bearing = (FT_Short)( face->horizontal.Line_Gap / 2 ); + advance_height = (FT_UShort)( face->horizontal.Ascender + + face->horizontal.Descender + + face->horizontal.Line_Gap ); + } + } + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* If this is an incrementally loaded font see if there are */ + /* overriding metrics for this glyph. */ + if ( face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + { + FT_Incremental_MetricsRec metrics; + FT_Error error = 0; + + + metrics.bearing_x = 0; + metrics.bearing_y = top_bearing; + metrics.advance = advance_height; + error = + face->root.internal->incremental_interface->funcs->get_glyph_metrics( + face->root.internal->incremental_interface->object, + glyph_index, TRUE, &metrics ); + + if ( error ) + return error; + + top_bearing = (FT_Short)metrics.bearing_y; + advance_height = (FT_UShort)metrics.advance; + } + + /* GWW: Do vertical metrics get loaded incrementally too? */ + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + /* We must adjust the top_bearing value from the bounding box given */ + /* in the glyph header to the bounding box calculated with */ + /* FT_Get_Outline_CBox(). */ + + /* scale the metrics */ + if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) + { + top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale ) + - bbox.yMax; + advance = FT_MulFix( advance_height, y_scale ); + } + else + { + top = top_bearing + loader->bbox.yMax - bbox.yMax; + advance = advance_height; + } + + /* set the advance height in design units. It is scaled later by */ + /* the base layer. */ + glyph->linearVertAdvance = advance_height; + + /* XXX: for now, we have no better algorithm for the lsb, but it */ + /* should work fine. */ + /* */ + left = ( bbox.xMin - bbox.xMax ) / 2; + + /* grid-fit them if necessary */ + if ( IS_HINTED( loader->load_flags ) ) + { + left = FT_PIX_FLOOR( left ); + top = FT_PIX_CEIL( top ); + advance = FT_PIX_ROUND( advance ); + } + + glyph->metrics.vertBearingX = left; + glyph->metrics.vertBearingY = top; + glyph->metrics.vertAdvance = advance; + } + + /* adjust advance width to the value contained in the hdmx table */ + if ( !face->postscript.isFixedPitch && size && + IS_HINTED( loader->load_flags ) ) + { + FT_Byte* widths = Get_Advance_Widths( face, + size->root.metrics.x_ppem ); + + + if ( widths ) + glyph->metrics.horiAdvance = widths[glyph_index] << 6; + } + + /* set glyph dimensions */ + glyph->metrics.width = bbox.xMax - bbox.xMin; + glyph->metrics.height = bbox.yMax - bbox.yMin; + + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_Glyph */ + /* */ + /* <Description> */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* <Input> */ + /* glyph :: A handle to a target slot object where the glyph */ + /* will be loaded. */ + /* */ + /* size :: A handle to the source face size at which the glyph */ + /* must be scaled/loaded. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + SFNT_Service sfnt; + TT_Face face; + FT_Stream stream; + FT_Error error; + TT_LoaderRec loader; + + + face = (TT_Face)glyph->face; + sfnt = (SFNT_Service)face->sfnt; + stream = face->root.stream; + error = 0; + + if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) || + ( load_flags & FT_LOAD_NO_RECURSE ) ) + { + size = NULL; + load_flags |= FT_LOAD_NO_SCALE | + FT_LOAD_NO_HINTING | + FT_LOAD_NO_BITMAP; + } + + glyph->num_subglyphs = 0; + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* try to load embedded bitmap if any */ + /* */ + /* XXX: The convention should be emphasized in */ + /* the documents because it can be confusing. */ + if ( size && + size->strike_index != 0xFFFFU && + sfnt->load_sbits && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) + + { + TT_SBit_MetricsRec metrics; + + + error = sfnt->load_sbit_image( face, + (FT_ULong)size->strike_index, + glyph_index, + (FT_Int)load_flags, + stream, + &glyph->bitmap, + &metrics ); + if ( !error ) + { + glyph->outline.n_points = 0; + glyph->outline.n_contours = 0; + + glyph->metrics.width = (FT_Pos)metrics.width << 6; + glyph->metrics.height = (FT_Pos)metrics.height << 6; + + glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; + glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; + glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; + + glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; + glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; + glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; + + glyph->format = FT_GLYPH_FORMAT_BITMAP; + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + glyph->bitmap_left = metrics.vertBearingX; + glyph->bitmap_top = metrics.vertBearingY; + } + else + { + glyph->bitmap_left = metrics.horiBearingX; + glyph->bitmap_top = metrics.horiBearingY; + } + return error; + } + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* return immediately if we only want the embedded bitmaps */ + if ( load_flags & FT_LOAD_SBITS_ONLY ) + return TT_Err_Invalid_Argument; + + /* seek to the beginning of the glyph table. For Type 42 fonts */ + /* the table might be accessed from a Postscript stream or something */ + /* else... */ + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* Don't look for the glyph table if this is an incremental font. */ + if ( !face->root.internal->incremental_interface ) + +#endif + + { + error = face->goto_table( face, TTAG_glyf, stream, 0 ); + if ( error ) + { + FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" )); + goto Exit; + } + } + + FT_MEM_ZERO( &loader, sizeof ( loader ) ); + + /* update the glyph zone bounds */ + { + FT_GlyphLoader gloader = FT_FACE_DRIVER(face)->glyph_loader; + + + loader.gloader = gloader; + + FT_GlyphLoader_Rewind( gloader ); + + tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 ); + tt_prepare_zone( &loader.base, &gloader->base, 0, 0 ); + } + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( size ) + { + /* query new execution context */ + loader.exec = size->debug ? size->context : TT_New_Context( face ); + if ( !loader.exec ) + return TT_Err_Could_Not_Find_Context; + + TT_Load_Context( loader.exec, face, size ); + loader.instructions = loader.exec->glyphIns; + + /* load default graphics state - if needed */ + if ( size->GS.instruct_control & 2 ) + loader.exec->GS = tt_default_graphics_state; + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + /* clear all outline flags, except the `owner' one */ + glyph->outline.flags = 0; + + /* let's initialize the rest of our loader now */ + + loader.load_flags = load_flags; + + loader.face = (FT_Face)face; + loader.size = (FT_Size)size; + loader.glyph = (FT_GlyphSlot)glyph; + loader.stream = stream; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + if ( face->root.internal->incremental_interface ) + loader.glyf_offset = 0; + else + +#endif + + loader.glyf_offset = FT_STREAM_POS(); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* if the cvt program has disabled hinting, the argument */ + /* is ignored. */ + if ( size && ( size->GS.instruct_control & 1 ) ) + loader.load_flags |= FT_LOAD_NO_HINTING; + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + /* Main loading loop */ + glyph->format = FT_GLYPH_FORMAT_OUTLINE; + glyph->num_subglyphs = 0; + + error = load_truetype_glyph( &loader, glyph_index, 0 ); + if ( !error ) + compute_glyph_metrics( &loader, glyph_index ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( !size || !size->debug ) + TT_Done_Context( loader.exec ); + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + /* Set the `high precision' bit flag. */ + /* This is _critical_ to get correct output for monochrome */ + /* TrueType glyphs at all sizes using the bytecode interpreter. */ + /* */ + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; + + Exit: + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttgload.h b/Utilities/vtkfreetype/src/truetype/ttgload.h new file mode 100644 index 0000000..dfa2a60 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttgload.h @@ -0,0 +1,55 @@ +/***************************************************************************/ +/* */ +/* ttgload.h */ +/* */ +/* TrueType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTGLOAD_H__ +#define __TTGLOAD_H__ + + +#include <ft2build.h> +#include "ttobjs.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + + +FT_BEGIN_HEADER + + + FT_LOCAL( void ) + TT_Get_Metrics( TT_HoriHeader* header, + FT_UInt idx, + FT_Short* bearing, + FT_UShort* advance ); + + FT_LOCAL( void ) + TT_Init_Glyph_Loading( TT_Face face ); + + FT_LOCAL( FT_Error ) + TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + +FT_END_HEADER + +#endif /* __TTGLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttgxvar.c b/Utilities/vtkfreetype/src/truetype/ttgxvar.c new file mode 100644 index 0000000..e48bb50 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttgxvar.c @@ -0,0 +1,1520 @@ +/***************************************************************************/ +/* */ +/* ttgxvar.c */ +/* */ +/* TrueType GX Font Variation loader */ +/* */ +/* Copyright 2004 by */ +/* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +/***************************************************************************/ +/* */ +/* Apple documents the `fvar', `gvar', `cvar', and `avar' tables at */ +/* */ +/* http://developer.apple.com/fonts/TTRefMan/RM06/Chap6[fgca]var.html */ +/* */ +/* The documentation for `fvar' is inconsistant. At one point it says */ +/* that `countSizePairs' should be 3, at another point 2. It should be 2. */ +/* */ +/* The documentation for `gvar' is not intelligible; `cvar' refers you to */ +/* `gvar' and is thus also incomprehensible. */ +/* */ +/* The documentation for `avar' appears correct, but Apple has no fonts */ +/* with an `avar' table, so it is hard to test. */ +/* */ +/* Many thanks to John Jenkins (at Apple) in figuring this out. */ +/* */ +/* */ +/* Apple's `kern' table has some references to tuple indices, but as there */ +/* is no indication where these indices are defined, nor how to */ +/* interpolate the kerning values (different tuples have different */ +/* classes) this issue is ignored. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_SFNT_H +#include FT_TRUETYPE_IDS_H +#include FT_TRUETYPE_TAGS_H +#include FT_MULTIPLE_MASTERS_H + +#include "ttdriver.h" +#include "ttpload.h" +#include "ttgxvar.h" + +#include "tterrors.h" + + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + + +#define FT_Stream_FTell( stream ) \ + ( (stream)->cursor - (stream)->base ) +#define FT_Stream_SeekSet( stream, off ) \ + ( (stream)->cursor = (stream)->base+(off) ) + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttgxvar + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** Internal Routines *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro ALL_POINTS is used in `ft_var_readpackedpoints'. It */ + /* indicates that there is a delta for every point without needing to */ + /* enumerate all of them. */ + /* */ +#define ALL_POINTS (FT_UShort*)(-1) + + + enum + { + GX_PT_POINTS_ARE_WORDS = 0x80, + GX_PT_POINT_RUN_COUNT_MASK = 0x7F + }; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_var_readpackedpoints */ + /* */ + /* <Description> */ + /* Read a set of points to which the following deltas will apply. */ + /* Points are packed with a run length encoding. */ + /* */ + /* <Input> */ + /* stream :: The data stream. */ + /* */ + /* <Output> */ + /* point_cnt :: The number of points read. A zero value means that */ + /* all points in the glyph will be affected, without */ + /* enumerating them individually. */ + /* */ + /* <Return> */ + /* An array of FT_UShort containing the affected points or the */ + /* special value ALL_POINTS. */ + /* */ + static FT_UShort* + ft_var_readpackedpoints( FT_Stream stream, + FT_UInt *point_cnt ) + { + FT_UShort *points; + FT_Int n; + FT_Int runcnt; + FT_Int i; + FT_Int j; + FT_Int first; + FT_Memory memory = stream->memory; + FT_Error error; + + + *point_cnt = n = FT_GET_BYTE(); + if ( n == 0 ) + return ALL_POINTS; + + if ( n & GX_PT_POINTS_ARE_WORDS ) + n = FT_GET_BYTE() | ( ( n & GX_PT_POINT_RUN_COUNT_MASK ) << 8 ); + + if ( FT_NEW_ARRAY( points, n ) ) + return NULL; + + i = 0; + while ( i < n ) + { + runcnt = FT_GET_BYTE(); + if ( runcnt & GX_PT_POINTS_ARE_WORDS ) + { + runcnt = runcnt & GX_PT_POINT_RUN_COUNT_MASK; + points[i++] = first = FT_GET_USHORT(); + + /* first point not included in runcount */ + for ( j = 0; j < runcnt; ++j ) + points[i++] = ( first += FT_GET_USHORT() ); + } + else + { + points[i++] = first = FT_GET_BYTE(); + + for ( j = 0; j < runcnt; ++j ) + points[i++] = ( first += FT_GET_BYTE() ); + } + } + + return points; + } + + + enum + { + GX_DT_DELTAS_ARE_ZERO = 0x80, + GX_DT_DELTAS_ARE_WORDS = 0x40, + GX_DT_DELTA_RUN_COUNT_MASK = 0x3F + }; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_var_readpackeddeltas */ + /* */ + /* <Description> */ + /* Read a set of deltas. These are packed slightly differently than */ + /* points. In particular there is no overall count. */ + /* */ + /* <Input> */ + /* stream :: The data stream. */ + /* */ + /* delta_cnt :: The number of to be read. */ + /* */ + /* <Return> */ + /* An array of FT_Short containing the deltas for the affected */ + /* points. (This only gets the deltas for one dimension. It will */ + /* generally be called twice, once for x, once for y. When used in */ + /* cvt table, it will only be called once.) */ + /* */ + static FT_Short* + ft_var_readpackeddeltas( FT_Stream stream, + FT_Int delta_cnt ) + { + FT_Short *deltas; + FT_Int runcnt; + FT_Int i; + FT_Int j; + FT_Memory memory = stream->memory; + FT_Error error; + + + if ( FT_NEW_ARRAY( deltas, delta_cnt ) ) + return NULL; + + i = 0; + while ( i < delta_cnt ) + { + runcnt = FT_GET_BYTE(); + if ( runcnt & GX_DT_DELTAS_ARE_ZERO ) + { + /* runcnt zeroes get added */ + for ( j = 0; + j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; + ++j ) + deltas[i++] = 0; + } + else if ( runcnt & GX_DT_DELTAS_ARE_WORDS ) + { + /* runcnt shorts from the stack */ + for ( j = 0; + j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; + ++j ) + deltas[i++] = FT_GET_SHORT(); + } + else + { + /* runcnt signed bytes from the stack */ + for ( j = 0; + j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) && i < delta_cnt; + ++j ) + deltas[i++] = FT_GET_CHAR(); + } + + if ( j <= ( runcnt & GX_DT_DELTA_RUN_COUNT_MASK ) ) + { + /* Bad format */ + FT_FREE( deltas ); + return NULL; + } + } + + return deltas; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_var_load_avar */ + /* */ + /* <Description> */ + /* Parse the `avar' table if present. It need not be, so we return */ + /* nothing. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + static void + ft_var_load_avar( TT_Face face ) + { + FT_Stream stream = FT_FACE_STREAM(face); + FT_Memory memory = stream->memory; + GX_Blend blend = face->blend; + GX_AVarSegment segment; + FT_Error error; + FT_ULong version; + FT_Long axisCount; + FT_Int i, j; + FT_ULong table_len; + + + blend->avar_checked = TRUE; + if ( ( error = face->goto_table( face, TTAG_avar, stream, &table_len ) ) ) + return; + if ( FT_FRAME_ENTER( table_len ) ) + return; + + version = FT_GET_LONG(); + axisCount = FT_GET_LONG(); + + if ( version != 0x00010000L || + axisCount != (FT_Long)blend->mmvar->num_axis ) + goto Exit; + + if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) ) + goto Exit; + + segment = &blend->avar_segment[0]; + for ( i = 0; i < axisCount; ++i, ++segment ) + { + segment->pairCount = FT_GET_USHORT(); + if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) ) + { + /* Failure. Free everything we have done so far. We must do */ + /* it right now since loading the `avar' table is optional. */ + + for ( j = i - 1; j >= 0; --j ) + FT_FREE( blend->avar_segment[j].correspondence ); + + FT_FREE( blend->avar_segment ); + blend->avar_segment = NULL; + goto Exit; + } + + for ( j = 0; j < segment->pairCount; ++j ) + { + segment->correspondence[j].fromCoord = + FT_GET_SHORT() << 2; /* convert to Fixed */ + segment->correspondence[j].toCoord = + FT_GET_SHORT()<<2; /* convert to Fixed */ + } + } + + Exit: + FT_FRAME_EXIT(); + } + + + typedef struct GX_GVar_Head_ { + FT_Long version; + FT_UShort axisCount; + FT_UShort globalCoordCount; + FT_ULong offsetToCoord; + FT_UShort glyphCount; + FT_UShort flags; + FT_ULong offsetToData; + + } GX_GVar_Head; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_var_load_gvar */ + /* */ + /* <Description> */ + /* Parses the `gvar' table if present. If `fvar' is there, `gvar' */ + /* had better be there too. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + ft_var_load_gvar( TT_Face face ) + { + FT_Stream stream = FT_FACE_STREAM(face); + FT_Memory memory = stream->memory; + GX_Blend blend = face->blend; + FT_Error error; + FT_UInt i, j; + FT_ULong table_len; + FT_ULong gvar_start; + FT_ULong offsetToData; + GX_GVar_Head gvar_head; + + static const FT_Frame_Field gvar_fields[] = + { + +#undef FT_STRUCTURE +#define FT_STRUCTURE GX_GVar_Head + + FT_FRAME_START( 20 ), + FT_FRAME_LONG ( version ), + FT_FRAME_USHORT( axisCount ), + FT_FRAME_USHORT( globalCoordCount ), + FT_FRAME_ULONG ( offsetToCoord ), + FT_FRAME_USHORT( glyphCount ), + FT_FRAME_USHORT( flags ), + FT_FRAME_ULONG ( offsetToData ), + FT_FRAME_END + }; + + if ( ( error = face->goto_table( face, TTAG_gvar, stream, &table_len ) ) ) + goto Exit; + + gvar_start = FT_STREAM_POS( ); + if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) ) + goto Exit; + + blend->tuplecount = gvar_head.globalCoordCount; + blend->gv_glyphcnt = gvar_head.glyphCount; + offsetToData = gvar_start + gvar_head.offsetToData; + + if ( gvar_head.version != 0x00010000L || + gvar_head.axisCount != blend->mmvar->num_axis ) + { + error = TT_Err_Invalid_Table; + goto Exit; + } + + if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) ) + goto Exit; + + if ( gvar_head.flags & 1 ) + { + /* long offsets (one more offset than glyphs, to mark size of last) */ + if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 4L ) ) + goto Exit; + + for ( i = 0; i <= blend->gv_glyphcnt; ++i ) + blend->glyphoffsets[i] = offsetToData + FT_GET_LONG(); + + FT_FRAME_EXIT(); + } + else + { + /* short offsets (one more offset than glyphs, to mark size of last) */ + if ( FT_FRAME_ENTER( ( blend->gv_glyphcnt + 1 ) * 2L ) ) + goto Exit; + + for ( i = 0; i <= blend->gv_glyphcnt; ++i ) + blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2; + /* XXX: Undocumented: `*2'! */ + + FT_FRAME_EXIT(); + } + + if ( blend->tuplecount != 0 ) + { + if ( FT_NEW_ARRAY( blend->tuplecoords, + gvar_head.axisCount * blend->tuplecount ) ) + goto Exit; + + if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) || + FT_FRAME_ENTER( blend->tuplecount * gvar_head.axisCount * 2L ) ) + goto Exit; + + for ( i = 0; i < blend->tuplecount; ++i ) + for ( j = 0 ; j < gvar_head.axisCount; ++j ) + blend->tuplecoords[i * gvar_head.axisCount + j] = + FT_GET_SHORT() << 2; /* convert to FT_Fixed */ + + FT_FRAME_EXIT(); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* ft_var_apply_tuple */ + /* */ + /* <Description> */ + /* Figure out whether a given tuple (design) applies to the current */ + /* blend, and if so, what is the scaling factor. */ + /* */ + /* <Input> */ + /* blend :: The current blend of the font. */ + /* */ + /* tupleIndex :: A flag saying whether this is an intermediate */ + /* tuple or not. */ + /* */ + /* tuple_coords :: The coordinates of the tuple in normalized axis */ + /* units. */ + /* */ + /* im_start_coords :: The initial coordinates where this tuple starts */ + /* to apply (for intermediate coordinates). */ + /* */ + /* im_end_coords :: The final coordinates after which this tuple no */ + /* longer applies (for intermediate coordinates). */ + /* */ + /* <Return> */ + /* An FT_Fixed value containing the scaling factor. */ + /* */ + static FT_Fixed + ft_var_apply_tuple( GX_Blend blend, + FT_UShort tupleIndex, + FT_Fixed* tuple_coords, + FT_Fixed* im_start_coords, + FT_Fixed* im_end_coords ) + { + FT_UInt i; + FT_Fixed apply; + FT_Fixed temp; + + + apply = 0x10000L; + for ( i = 0; i < blend->num_axis; ++i ) + { + if ( tuple_coords[i] == 0 ) + /* It's not clear why (for intermediate tuples) we don't need */ + /* to check against start/end -- the documentation says we don't. */ + /* Similarly, it's unclear why we don't need to scale along the */ + /* axis. */ + continue; + + else if ( blend->normalizedcoords[i] == 0 || + ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) || + ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) ) + { + apply = 0; + break; + } + + else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) + /* not an intermediate tuple */ + apply = FT_MulDiv( apply, + blend->normalizedcoords[i] > 0 + ? blend->normalizedcoords[i] + : -blend->normalizedcoords[i], + 0x10000L ); + + else if ( blend->normalizedcoords[i] <= im_start_coords[i] || + blend->normalizedcoords[i] >= im_end_coords[i] ) + { + apply = 0; + break; + } + + else if ( blend->normalizedcoords[i] < tuple_coords[i] ) + { + temp = FT_MulDiv( blend->normalizedcoords[i] - im_start_coords[i], + 0x10000L, + tuple_coords[i] - im_start_coords[i]); + apply = FT_MulDiv( apply, temp, 0x10000L ); + } + + else + { + temp = FT_MulDiv( im_end_coords[i] - blend->normalizedcoords[i], + 0x10000L, + im_end_coords[i] - tuple_coords[i] ); + apply = FT_MulDiv( apply, temp, 0x10000L ); + } + } + + return apply; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** MULTIPLE MASTERS SERVICE FUNCTIONS *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + typedef struct GX_FVar_Head_ { + FT_Long version; + FT_UShort offsetToData; + FT_UShort countSizePairs; + FT_UShort axisCount; + FT_UShort axisSize; + FT_UShort instanceCount; + FT_UShort instanceSize; + + } GX_FVar_Head; + + + typedef struct fvar_axis { + FT_ULong axisTag; + FT_ULong minValue; + FT_ULong defaultValue; + FT_ULong maxValue; + FT_UShort flags; + FT_UShort nameID; + + } GX_FVar_Axis; + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Get_MM_Var */ + /* */ + /* <Description> */ + /* Check that the font's `fvar' table is valid, parse it, and return */ + /* those data. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* TT_Get_MM_Var initializes the blend structure. */ + /* */ + /* <Output> */ + /* master :: The `fvar' data (must be freed by caller). */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Get_MM_Var( TT_Face face, + FT_MM_Var* *master ) + { + FT_Stream stream = face->root.stream; + FT_Memory memory = face->root.memory; + FT_ULong table_len; + FT_Error error = TT_Err_Ok; + FT_ULong fvar_start; + FT_Int i, j; + FT_MM_Var* mmvar; + FT_Fixed* next_coords; + FT_String* next_name; + FT_Var_Axis* a; + FT_Var_Named_Style* ns; + GX_FVar_Head fvar_head; + + static const FT_Frame_Field fvar_fields[] = + { + +#undef FT_STRUCTURE +#define FT_STRUCTURE GX_FVar_Head + + FT_FRAME_START( 16 ), + FT_FRAME_LONG ( version ), + FT_FRAME_USHORT( offsetToData ), + FT_FRAME_USHORT( countSizePairs ), + FT_FRAME_USHORT( axisCount ), + FT_FRAME_USHORT( axisSize ), + FT_FRAME_USHORT( instanceCount ), + FT_FRAME_USHORT( instanceSize ), + FT_FRAME_END + }; + + static const FT_Frame_Field fvaraxis_fields[] = + { + +#undef FT_STRUCTURE +#define FT_STRUCTURE GX_FVar_Axis + + FT_FRAME_START( 20 ), + FT_FRAME_ULONG ( axisTag ), + FT_FRAME_ULONG ( minValue ), + FT_FRAME_ULONG ( defaultValue ), + FT_FRAME_ULONG ( maxValue ), + FT_FRAME_USHORT( flags ), + FT_FRAME_USHORT( nameID ), + FT_FRAME_END + }; + + + if ( face->blend == NULL ) + { + /* both `fvar' and `gvar' must be present */ + if ( ( error = face->goto_table( face, TTAG_gvar, + stream, &table_len ) ) ) + goto Exit; + if ( ( error = face->goto_table( face, TTAG_fvar, + stream, &table_len ) ) ) + goto Exit; + + fvar_start = FT_STREAM_POS( ); + + if ( FT_STREAM_READ_FIELDS( fvar_fields, &fvar_head ) ) + goto Exit; + + if ( fvar_head.version != 0x00010000UL || + fvar_head.countSizePairs != 2 || + fvar_head.axisSize != 20 || + fvar_head.instanceSize != 4 + 4 * fvar_head.axisCount || + fvar_head.offsetToData + fvar_head.axisCount * 20U + + fvar_head.instanceCount * fvar_head.instanceSize > table_len ) + { + error = TT_Err_Invalid_Table; + goto Exit; + } + + if ( FT_ALLOC( face->blend, sizeof ( GX_BlendRec ) ) ) + goto Exit; + + face->blend->mmvar_len = + sizeof ( FT_MM_Var ) + + fvar_head.axisCount * sizeof ( FT_Var_Axis ) + + fvar_head.instanceCount * sizeof ( FT_Var_Named_Style ) + + fvar_head.instanceCount * fvar_head.axisCount * sizeof ( FT_Fixed ) + + 5 * fvar_head.axisCount; + if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + goto Exit; + face->blend->mmvar = mmvar; + + mmvar->num_axis = + fvar_head.axisCount; + mmvar->num_designs = + (FT_UInt)-1; /* meaningless in this context; each glyph */ + /* may have a different number of designs */ + /* (or tuples, as called by Apple) */ + mmvar->num_namedstyles = + fvar_head.instanceCount; + mmvar->axis = + (FT_Var_Axis*)&(mmvar[1]); + mmvar->namedstyle = + (FT_Var_Named_Style*)&(mmvar->axis[fvar_head.axisCount]); + + next_coords = + (FT_Fixed*)&(mmvar->namedstyle[fvar_head.instanceCount]); + for ( i = 0; i < fvar_head.instanceCount; ++i ) + { + mmvar->namedstyle[i].coords = next_coords; + next_coords += fvar_head.axisCount; + } + + next_name = (FT_String*)next_coords; + for ( i = 0; i < fvar_head.axisCount; ++i ) + { + mmvar->axis[i].name = next_name; + next_name += 5; + } + + if ( FT_STREAM_SEEK( fvar_start + fvar_head.offsetToData ) ) + goto Exit; + + a = mmvar->axis; + for ( i = 0; i < fvar_head.axisCount; ++i ) + { + GX_FVar_Axis axis_rec; + + + if ( FT_STREAM_READ_FIELDS( fvaraxis_fields, &axis_rec ) ) + goto Exit; + a->tag = axis_rec.axisTag; + a->minimum = axis_rec.minValue; /* A Fixed */ + a->def = axis_rec.defaultValue; /* A Fixed */ + a->maximum = axis_rec.maxValue; /* A Fixed */ + a->strid = axis_rec.nameID; + + a->name[0] = a->tag >> 24; + a->name[1] = ( a->tag >> 16 ) & 0xFF; + a->name[2] = ( a->tag >> 8 ) & 0xFF; + a->name[3] = ( a->tag ) & 0xFF; + a->name[4] = 0; + + ++a; + } + + ns = mmvar->namedstyle; + for ( i = 0; i < fvar_head.instanceCount; ++i ) + { + if ( FT_FRAME_ENTER( 4L + 4L * fvar_head.axisCount ) ) + goto Exit; + + ns->strid = FT_GET_USHORT(); + (void) /* flags = */ FT_GET_USHORT(); + + for ( j = 0; j < fvar_head.axisCount; ++j ) + ns->coords[j] = FT_GET_ULONG(); /* A Fixed */ + + FT_FRAME_EXIT(); + } + } + + if ( master != NULL ) + { + FT_UInt n; + + + if ( FT_ALLOC( mmvar, face->blend->mmvar_len ) ) + goto Exit; + FT_MEM_COPY( mmvar, face->blend->mmvar, face->blend->mmvar_len ); + + mmvar->axis = + (FT_Var_Axis*)&(mmvar[1]); + mmvar->namedstyle = + (FT_Var_Named_Style*)&(mmvar->axis[mmvar->num_axis]); + next_coords = + (FT_Fixed*)&(mmvar->namedstyle[mmvar->num_namedstyles]); + + for ( n = 0; n < mmvar->num_namedstyles; ++n ) + { + mmvar->namedstyle[n].coords = next_coords; + next_coords += mmvar->num_axis; + } + + a = mmvar->axis; + next_name = (FT_String*)next_coords; + for ( n = 0; n < mmvar->num_axis; ++n ) + { + a->name = next_name; + + /* standard PostScript names for some standard apple tags */ + if ( a->tag == TTAG_wght ) + a->name = (char *)"Weight"; + else if ( a->tag == TTAG_wdth ) + a->name = (char *)"Width"; + else if ( a->tag == TTAG_opsz ) + a->name = (char *)"OpticalSize"; + else if ( a->tag == TTAG_slnt ) + a->name = (char *)"Slant"; + + next_name += 5; + ++a; + } + + *master = mmvar; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Set_MM_Blend */ + /* */ + /* <Description> */ + /* Set the blend (normalized) coordinates for this instance of the */ + /* font. Check that the `gvar' table is reasonable and does some */ + /* initial preparation. */ + /* */ + /* <InOut> */ + /* face :: The font. */ + /* Initialize the blend structure with `gvar' data. */ + /* */ + /* <Input> */ + /* num_coords :: Must be the axis count of the font. */ + /* */ + /* coords :: An array of num_coords, each between [-1,1]. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Set_MM_Blend( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error = TT_Err_Ok; + GX_Blend blend; + FT_MM_Var* mmvar; + FT_UInt i; + FT_Memory memory = face->root.memory; + + enum + { + mcvt_retain, + mcvt_modify, + mcvt_load + + } manageCvt; + + + face->doblend = FALSE; + + if ( face->blend == NULL ) + { + if ( ( error = TT_Get_MM_Var( face, NULL) ) ) + goto Exit; + } + + blend = face->blend; + mmvar = blend->mmvar; + + if ( num_coords != mmvar->num_axis ) + { + error = TT_Err_Invalid_Argument; + goto Exit; + } + + for ( i = 0; i < num_coords; ++i ) + if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L ) + { + error = TT_Err_Invalid_Argument; + goto Exit; + } + + if ( blend->glyphoffsets == NULL ) + if ( ( error = ft_var_load_gvar( face ) ) ) + goto Exit; + + if ( blend->normalizedcoords == NULL ) + { + if ( FT_NEW_ARRAY( blend->normalizedcoords, num_coords ) ) + goto Exit; + + manageCvt = mcvt_modify; + + /* If we have not set the blend coordinates before this, then the */ + /* cvt table will still be what we read from the `cvt ' table and */ + /* we don't need to reload it. We may need to change it though... */ + } + else + { + for ( i = 0; + i < num_coords && blend->normalizedcoords[i] == coords[i]; + ++i ); + if ( i == num_coords ) + manageCvt = mcvt_retain; + else + manageCvt = mcvt_load; + + /* If we don't change the blend coords then we don't need to do */ + /* anything to the cvt table. It will be correct. Otherwise we */ + /* no longer have the original cvt (it was modified when we set */ + /* the blend last time), so we must reload and then modify it. */ + } + + blend->num_axis = num_coords; + FT_MEM_COPY( blend->normalizedcoords, + coords, + num_coords * sizeof ( FT_Fixed ) ); + + face->doblend = TRUE; + + if ( face->cvt != NULL ) + { + switch ( manageCvt ) + { + case mcvt_load: + /* The cvt table has been loaded already; every time we change the */ + /* blend we may need to reload and remodify the cvt table. */ + FT_FREE( face->cvt ); + face->cvt = NULL; + + tt_face_load_cvt( face, face->root.stream ); + break; + + case mcvt_modify: + /* The original cvt table is in memory. All we need to do is */ + /* apply the `cvar' table (if any). */ + tt_face_vary_cvt( face, face->root.stream ); + break; + + case mcvt_retain: + /* The cvt table is correct for this set of coordinates. */ + break; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Set_Var_Design */ + /* */ + /* <Description> */ + /* Set the coordinates for the instance, measured in the user */ + /* coordinate system. Parse the `avar' table (if present) to convert */ + /* from user to normalized coordinates. */ + /* */ + /* <InOut> */ + /* face :: The font face. */ + /* Initialize the blend struct with `gvar' data. */ + /* */ + /* <Input> */ + /* num_coords :: This must be the axis count of the font. */ + /* */ + /* coords :: A coordinate array with `num_coords' elements. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Set_Var_Design( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error = TT_Err_Ok; + FT_Fixed* normalized = NULL; + GX_Blend blend; + FT_MM_Var* mmvar; + FT_UInt i, j; + FT_Var_Axis* a; + GX_AVarSegment av; + FT_Memory memory = face->root.memory; + + + if ( face->blend == NULL ) + { + if ( ( error = TT_Get_MM_Var( face, NULL ) ) ) + goto Exit; + } + + blend = face->blend; + mmvar = blend->mmvar; + + if ( num_coords != mmvar->num_axis ) + { + error = TT_Err_Invalid_Argument; + goto Exit; + } + + /* Axis normalization is a two stage process. First we normalize */ + /* based on the [min,def,max] values for the axis to be [-1,0,1]. */ + /* Then, if there's an `avar' table, we renormalize this range. */ + + if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) ) + goto Exit; + + a = mmvar->axis; + for ( i = 0; i < mmvar->num_axis; ++i, ++a ) + { + if ( coords[i] > a->maximum || coords[i] < a->minimum ) + { + error = TT_Err_Invalid_Argument; + goto Exit; + } + + if ( coords[i] < a->def ) + { + normalized[i] = -FT_MulDiv( coords[i] - a->def, + 0x10000L, + a->minimum - a->def ); + } + else if ( a->maximum == a->def ) + normalized[i] = 0; + else + { + normalized[i] = FT_MulDiv( coords[i] - a->def, + 0x10000L, + a->maximum - a->def ); + } + } + + if ( !blend->avar_checked ) + ft_var_load_avar( face ); + + if ( blend->avar_segment != NULL ) + { + av = blend->avar_segment; + for ( i = 0; i < mmvar->num_axis; ++i, ++av ) + { + for ( j = 1; j < av->pairCount; ++j ) + if ( normalized[i] < av->correspondence[j].fromCoord ) + { + normalized[i] = + FT_MulDiv( + FT_MulDiv( + normalized[i] - av->correspondence[j - 1].fromCoord, + 0x10000L, + av->correspondence[j].fromCoord - + av->correspondence[j - 1].fromCoord ), + av->correspondence[j].toCoord - + av->correspondence[j - 1].toCoord, + 0x10000L ) + + av->correspondence[j - 1].toCoord; + break; + } + } + } + + error = TT_Set_MM_Blend( face, num_coords, normalized ); + + Exit: + FT_FREE( normalized ); + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** GX VAR PARSING ROUTINES *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_vary_cvt */ + /* */ + /* <Description> */ + /* Modify the loaded cvt table according to the `cvar' table and the */ + /* font's blend. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Input> */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* Most errors are ignored. It is perfectly valid not to have a */ + /* `cvar' table even if there is a `gvar' and `fvar' table. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_vary_cvt( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong table_start; + FT_ULong table_len; + FT_UInt tupleCount; + FT_ULong offsetToData; + FT_ULong here; + FT_UInt i, j; + FT_Fixed* tuple_coords = NULL; + FT_Fixed* im_start_coords = NULL; + FT_Fixed* im_end_coords = NULL; + GX_Blend blend = face->blend; + FT_UInt point_count; + FT_UShort* localpoints; + FT_Short* deltas; + + + FT_TRACE2(( "CVAR " )); + + if ( blend == NULL ) + { + FT_TRACE2(( "no blend specified!\n" )); + + error = TT_Err_Ok; + goto Exit; + } + + if ( face->cvt == NULL ) + { + FT_TRACE2(( "no `cvt ' table!\n" )); + + error = TT_Err_Ok; + goto Exit; + } + + error = face->goto_table( face, TTAG_cvar, stream, &table_len ); + if ( error ) + { + FT_TRACE2(( "is missing!\n" )); + + error = TT_Err_Ok; + goto Exit; + } + + if ( FT_FRAME_ENTER( table_len ) ) + { + error = TT_Err_Ok; + goto Exit; + } + + table_start = FT_Stream_FTell( stream ); + if ( FT_GET_LONG() != 0x00010000L ) + { + FT_TRACE2(( "bad table version!\n" )); + + error = TT_Err_Ok; + goto FExit; + } + + if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || + FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || + FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) + goto FExit; + + tupleCount = FT_GET_USHORT(); + offsetToData = table_start + FT_GET_USHORT(); + + /* The documentation implies there are flags packed into the */ + /* tuplecount, but John Jenkins says that shared points don't apply */ + /* to `cvar', and no other flags are defined. */ + + for ( i = 0; i < ( tupleCount & 0xFFF ); ++i ) + { + FT_UInt tupleDataSize; + FT_UInt tupleIndex; + FT_Fixed apply; + + + tupleDataSize = FT_GET_USHORT(); + tupleIndex = FT_GET_USHORT(); + + /* There is no provision here for a global tuple coordinate section, */ + /* so John says. There are no tuple indices, just embedded tuples. */ + + if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) + { + for ( j = 0; j < blend->num_axis; ++j ) + tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */ + /* short frac to fixed */ + } + else + { + /* skip this tuple; it makes no sense */ + + if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) + for ( j = 0; j < 2 * blend->num_axis; ++j ) + (void)FT_GET_SHORT(); + + offsetToData += tupleDataSize; + continue; + } + + if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) + { + for ( j = 0; j < blend->num_axis; ++j ) + im_start_coords[j] = FT_GET_SHORT() << 2; + for ( j = 0; j < blend->num_axis; ++j ) + im_end_coords[j] = FT_GET_SHORT() << 2; + } + + apply = ft_var_apply_tuple( blend, + tupleIndex, + tuple_coords, + im_start_coords, + im_end_coords ); + if ( /* tuple isn't active for our blend */ + apply == 0 || + /* global points not allowed, */ + /* if they aren't local, makes no sense */ + !( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) ) + { + offsetToData += tupleDataSize; + continue; + } + + here = FT_Stream_FTell( stream ); + + FT_Stream_SeekSet( stream, offsetToData ); + + localpoints = ft_var_readpackedpoints( stream, &point_count ); + deltas = ft_var_readpackeddeltas( stream, + point_count == 0 ? face->cvt_size + : point_count ); + if ( localpoints == NULL || deltas == NULL ) + /* failure, ignore it */; + + else if ( localpoints == ALL_POINTS ) + { + /* this means that there are deltas for every entry in cvt */ + for ( j = 0; j < face->cvt_size; ++j ) + face->cvt[j] += FT_MulFix( deltas[j], apply ); + } + + else + { + for ( j = 0; j < point_count; ++j ) + face->cvt[localpoints[j]] += FT_MulFix( deltas[j], apply ); + } + + if ( localpoints != ALL_POINTS ) + FT_FREE( localpoints ); + FT_FREE( deltas ); + + offsetToData += tupleDataSize; + + FT_Stream_SeekSet( stream, here ); + } + + FExit: + FT_FRAME_EXIT(); + + Exit: + FT_FREE( tuple_coords ); + FT_FREE( im_start_coords ); + FT_FREE( im_end_coords ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Vary_Get_Glyph_Deltas */ + /* */ + /* <Description> */ + /* Load the appropriate deltas for the current glyph. */ + /* */ + /* <Input> */ + /* face :: A handle to the target face object. */ + /* */ + /* glyph_index :: The index of the glyph being modified. */ + /* */ + /* n_points :: The number of the points in the glyph, including */ + /* phantom points. */ + /* */ + /* <Output> */ + /* deltas :: The array of points to change. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Vary_Get_Glyph_Deltas( TT_Face face, + FT_UInt glyph_index, + FT_Vector* *deltas, + FT_UInt n_points ) + { + FT_Stream stream = face->root.stream; + FT_Memory memory = stream->memory; + GX_Blend blend = face->blend; + FT_Vector* delta_xy; + + FT_Error error; + FT_ULong glyph_start; + FT_UInt tupleCount; + FT_ULong offsetToData; + FT_ULong here; + FT_UInt i, j; + FT_Fixed* tuple_coords = NULL; + FT_Fixed* im_start_coords = NULL; + FT_Fixed* im_end_coords = NULL; + FT_UInt point_count, spoint_count = 0; + FT_UShort* sharedpoints = NULL; + FT_UShort* localpoints; + FT_UShort* points; + FT_Short *deltas_x, *deltas_y; + + + if ( !face->doblend || blend == NULL ) + return TT_Err_Invalid_Argument; + + /* to be freed by the caller */ + if ( ( error = FT_NEW_ARRAY( delta_xy, n_points ) ) ) + goto Exit; + *deltas = delta_xy; + + if ( glyph_index >= blend->gv_glyphcnt || + blend->glyphoffsets[glyph_index] == + blend->glyphoffsets[glyph_index + 1] ) + return TT_Err_Ok; /* no variation data for this glyph */ + + if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) || + FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] - + blend->glyphoffsets[glyph_index] ) ) + goto Fail1; + + glyph_start = FT_Stream_FTell( stream ); + + /* each set of glyph variation data is formatted similarly to `cvar' */ + /* (except we get shared points and global tuples) */ + + if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) || + FT_NEW_ARRAY( im_start_coords, blend->num_axis ) || + FT_NEW_ARRAY( im_end_coords, blend->num_axis ) ) + goto Fail2; + + tupleCount = FT_GET_USHORT(); + offsetToData = glyph_start + FT_GET_USHORT(); + + if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS ) + { + here = FT_Stream_FTell( stream ); + + FT_Stream_SeekSet( stream, offsetToData ); + + sharedpoints = ft_var_readpackedpoints( stream, &spoint_count ); + offsetToData = FT_Stream_FTell( stream ); + + FT_Stream_SeekSet( stream, here ); + } + + for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i ) + { + FT_UInt tupleDataSize; + FT_UInt tupleIndex; + FT_Fixed apply; + + + tupleDataSize = FT_GET_USHORT(); + tupleIndex = FT_GET_USHORT(); + + if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD ) + { + for ( j = 0; j < blend->num_axis; ++j ) + tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */ + /* short frac to fixed */ + } + else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount ) + { + error = TT_Err_Invalid_Table; + goto Fail3; + } + else + { + FT_MEM_COPY( + tuple_coords, + &blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis], + blend->num_axis * sizeof ( FT_Fixed ) ); + } + + if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) + { + for ( j = 0; j < blend->num_axis; ++j ) + im_start_coords[j] = FT_GET_SHORT() << 2; + for ( j = 0; j < blend->num_axis; ++j ) + im_end_coords[j] = FT_GET_SHORT() << 2; + } + + apply = ft_var_apply_tuple( blend, + tupleIndex, + tuple_coords, + im_start_coords, + im_end_coords ); + + if ( apply == 0 ) /* tuple isn't active for our blend */ + { + offsetToData += tupleDataSize; + continue; + } + + here = FT_Stream_FTell( stream ); + + if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) + { + FT_Stream_SeekSet( stream, offsetToData ); + + localpoints = ft_var_readpackedpoints( stream, &point_count ); + points = localpoints; + } + else + { + points = sharedpoints; + point_count = spoint_count; + } + + deltas_x = ft_var_readpackeddeltas( stream, + point_count == 0 ? n_points + : point_count ); + deltas_y = ft_var_readpackeddeltas( stream, + point_count == 0 ? n_points + : point_count ); + + if ( points == NULL || deltas_y == NULL || deltas_x == NULL ) + ; /* failure, ignore it */ + + else if ( points == ALL_POINTS ) + { + /* this means that there are deltas for every point in the glyph */ + for ( j = 0; j < n_points; ++j ) + { + delta_xy[j].x += FT_MulFix( deltas_x[j], apply ); + delta_xy[j].y += FT_MulFix( deltas_y[j], apply ); + } + } + + else + { + for ( j = 0; j < point_count; ++j ) + { + delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply ); + delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply ); + } + } + + if ( localpoints != ALL_POINTS ) + FT_FREE( localpoints ); + FT_FREE( deltas_x ); + FT_FREE( deltas_y ); + + offsetToData += tupleDataSize; + + FT_Stream_SeekSet( stream, here ); + } + + Fail3: + FT_FREE( tuple_coords ); + FT_FREE( im_start_coords ); + FT_FREE( im_end_coords ); + + Fail2: + FT_FRAME_EXIT(); + + Fail1: + if ( error ) + { + FT_FREE( delta_xy ); + *deltas = NULL; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_done_blend */ + /* */ + /* <Description> */ + /* Frees the blend internal data structure. */ + /* */ + FT_LOCAL_DEF( void ) + tt_done_blend( FT_Memory memory, + GX_Blend blend ) + { + if ( blend != NULL ) + { + FT_UInt i; + + + FT_FREE( blend->normalizedcoords ); + FT_FREE( blend->mmvar ); + + if ( blend->avar_segment != NULL ) + { + for ( i = 0; i < blend->num_axis; ++i ) + FT_FREE( blend->avar_segment[i].correspondence ); + FT_FREE( blend->avar_segment ); + } + + FT_FREE( blend->tuplecoords ); + FT_FREE( blend->glyphoffsets ); + FT_FREE( blend ); + } + } + +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttgxvar.h b/Utilities/vtkfreetype/src/truetype/ttgxvar.h new file mode 100644 index 0000000..e86c7ee --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttgxvar.h @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ttgxvar.h */ +/* */ +/* TrueType GX Font Variation loader (specification) */ +/* */ +/* Copyright 2004 by */ +/* David Turner, Robert Wilhelm, Werner Lemberg and George Williams. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTGXVAR_H__ +#define __TTGXVAR_H__ + + +#include <ft2build.h> +#include "ttobjs.h" + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* GX_AVarCorrespondenceRec */ + /* */ + /* <Description> */ + /* A data structure representing `shortFracCorrespondence' in `avar' */ + /* table according to the specifications from Apple. */ + /* */ + typedef struct GX_AVarCorrespondenceRec_ + { + FT_Fixed fromCoord; + FT_Fixed toCoord; + + } GX_AVarCorrespondenceRec_, *GX_AVarCorrespondence; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* GX_AVarRec */ + /* */ + /* <Description> */ + /* Data from the segment field of `avar' table. */ + /* There is one of these for each axis. */ + /* */ + typedef struct GX_AVarSegmentRec_ + { + FT_UShort pairCount; + GX_AVarCorrespondence correspondence; /* array with pairCount entries */ + + } GX_AVarSegmentRec, *GX_AVarSegment; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* GX_BlendRec */ + /* */ + /* <Description> */ + /* Data for interpolating a font from a distortable font specified */ + /* by the GX *var tables ([fgca]var). */ + /* */ + /* <Fields> */ + /* num_axis :: The number of axes along which interpolation */ + /* may happen */ + /* */ + /* normalizedcoords :: A normalized value (between [-1,1]) indicating */ + /* the contribution along each axis to the final */ + /* interpolated font. */ + /* */ + typedef struct GX_BlendRec_ + { + FT_UInt num_axis; + FT_Fixed* normalizedcoords; + + FT_MM_Var* mmvar; + FT_Int mmvar_len; + + FT_Bool avar_checked; + GX_AVarSegment avar_segment; + + FT_UInt tuplecount; /* shared tuples in `gvar' */ + FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ + + FT_UInt gv_glyphcnt; + FT_ULong* glyphoffsets; + + } GX_BlendRec; + + + /*************************************************************************/ + /* */ + /* <enum> */ + /* GX_TupleCountFlags */ + /* */ + /* <Description> */ + /* Flags used within the `TupleCount' field of the `gvar' table. */ + /* */ + typedef enum GX_TupleCountFlags_ + { + GX_TC_TUPLES_SHARE_POINT_NUMBERS = 0x8000, + GX_TC_RESERVED_TUPLE_FLAGS = 0x7000, + GX_TC_TUPLE_COUNT_MASK = 0x0FFF + + } GX_TupleCountFlags; + + + /*************************************************************************/ + /* */ + /* <enum> */ + /* GX_TupleIndexFlags */ + /* */ + /* <Description> */ + /* Flags used within the `TupleIndex' field of the `gvar' and `cvar' */ + /* tables. */ + /* */ + typedef enum GX_TupleIndexFlags_ + { + GX_TI_EMBEDDED_TUPLE_COORD = 0x8000, + GX_TI_INTERMEDIATE_TUPLE = 0x4000, + GX_TI_PRIVATE_POINT_NUMBERS = 0x2000, + GX_TI_RESERVED_TUPLE_FLAG = 0x1000, + GX_TI_TUPLE_INDEX_MASK = 0x0FFF + + } GX_TupleIndexFlags; + + +#define TTAG_wght FT_MAKE_TAG( 'w', 'g', 'h', 't' ) +#define TTAG_wdth FT_MAKE_TAG( 'w', 'd', 't', 'h' ) +#define TTAG_opsz FT_MAKE_TAG( 'o', 'p', 's', 'z' ) +#define TTAG_slnt FT_MAKE_TAG( 's', 'l', 'n', 't' ) + + + FT_LOCAL( FT_Error ) + TT_Set_MM_Blend( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + FT_LOCAL( FT_Error ) + TT_Set_Var_Design( TT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + FT_LOCAL( FT_Error ) + TT_Get_MM_Var( TT_Face face, + FT_MM_Var* *master ); + + + FT_LOCAL( FT_Error ) + tt_face_vary_cvt( TT_Face face, + FT_Stream stream ); + + + FT_LOCAL( FT_Error ) + TT_Vary_Get_Glyph_Deltas( TT_Face face, + FT_UInt glyph_index, + FT_Vector* *deltas, + FT_UInt n_points ); + + + FT_LOCAL( void ) + tt_done_blend( FT_Memory memory, + GX_Blend blend ); + + +FT_END_HEADER + + +#endif /* __TTGXVAR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttinterp.c b/Utilities/vtkfreetype/src/truetype/ttinterp.c new file mode 100644 index 0000000..889ebbf --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttinterp.c @@ -0,0 +1,7742 @@ +/***************************************************************************/ +/* */ +/* ttinterp.c */ +/* */ +/* TrueType bytecode interpreter (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_TRIGONOMETRY_H +#include FT_SYSTEM_H + +#include "ttinterp.h" + +#include "tterrors.h" + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + +#define TT_MULFIX FT_MulFix +#define TT_MULDIV FT_MulDiv +#define TT_MULDIV_NO_ROUND FT_MulDiv_No_Round + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttinterp + + /*************************************************************************/ + /* */ + /* In order to detect infinite loops in the code, we set up a counter */ + /* within the run loop. A single stroke of interpretation is now */ + /* limitet to a maximal number of opcodes defined below. */ + /* */ +#define MAX_RUNNABLE_OPCODES 1000000L + + + /*************************************************************************/ + /* */ + /* There are two kinds of implementations: */ + /* */ + /* a. static implementation */ + /* */ + /* The current execution context is a static variable, which fields */ + /* are accessed directly by the interpreter during execution. The */ + /* context is named `cur'. */ + /* */ + /* This version is non-reentrant, of course. */ + /* */ + /* b. indirect implementation */ + /* */ + /* The current execution context is passed to _each_ function as its */ + /* first argument, and each field is thus accessed indirectly. */ + /* */ + /* This version is fully re-entrant. */ + /* */ + /* The idea is that an indirect implementation may be slower to execute */ + /* on low-end processors that are used in some systems (like 386s or */ + /* even 486s). */ + /* */ + /* As a consequence, the indirect implementation is now the default, as */ + /* its performance costs can be considered negligible in our context. */ + /* Note, however, that we kept the same source with macros because: */ + /* */ + /* - The code is kept very close in design to the Pascal code used for */ + /* development. */ + /* */ + /* - It's much more readable that way! */ + /* */ + /* - It's still open to experimentation and tuning. */ + /* */ + /*************************************************************************/ + + +#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */ + +#define CUR (*exc) /* see ttobjs.h */ + +#else /* static implementation */ + +#define CUR cur + + static + TT_ExecContextRec cur; /* static exec. context variable */ + + /* apparently, we have a _lot_ of direct indexing when accessing */ + /* the static `cur', which makes the code bigger (due to all the */ + /* four bytes addresses). */ + +#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */ + + + /*************************************************************************/ + /* */ + /* The instruction argument stack. */ + /* */ +#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */ + + + /*************************************************************************/ + /* */ + /* This macro is used whenever `exec' is unused in a function, to avoid */ + /* stupid warnings from pedantic compilers. */ + /* */ +#define FT_UNUSED_EXEC FT_UNUSED( CUR ) + + + /*************************************************************************/ + /* */ + /* This macro is used whenever `args' is unused in a function, to avoid */ + /* stupid warnings from pedantic compilers. */ + /* */ +#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args ) + + + /*************************************************************************/ + /* */ + /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */ + /* increase readabilty of the code. */ + /* */ + /*************************************************************************/ + + +#define SKIP_Code() \ + SkipCode( EXEC_ARG ) + +#define GET_ShortIns() \ + GetShortIns( EXEC_ARG ) + +#define NORMalize( x, y, v ) \ + Normalize( EXEC_ARG_ x, y, v ) + +#define SET_SuperRound( scale, flags ) \ + SetSuperRound( EXEC_ARG_ scale, flags ) + +#define ROUND_None( d, c ) \ + Round_None( EXEC_ARG_ d, c ) + +#define INS_Goto_CodeRange( range, ip ) \ + Ins_Goto_CodeRange( EXEC_ARG_ range, ip ) + +#define CUR_Func_project( x, y ) \ + CUR.func_project( EXEC_ARG_ x, y ) + +#define CUR_Func_move( z, p, d ) \ + CUR.func_move( EXEC_ARG_ z, p, d ) + +#define CUR_Func_move_orig( z, p, d ) \ + CUR.func_move_orig( EXEC_ARG_ z, p, d ) + +#define CUR_Func_dualproj( x, y ) \ + CUR.func_dualproj( EXEC_ARG_ x, y ) + +#define CUR_Func_round( d, c ) \ + CUR.func_round( EXEC_ARG_ d, c ) + +#define CUR_Func_read_cvt( index ) \ + CUR.func_read_cvt( EXEC_ARG_ index ) + +#define CUR_Func_write_cvt( index, val ) \ + CUR.func_write_cvt( EXEC_ARG_ index, val ) + +#define CUR_Func_move_cvt( index, val ) \ + CUR.func_move_cvt( EXEC_ARG_ index, val ) + +#define CURRENT_Ratio() \ + Current_Ratio( EXEC_ARG ) + +#define CURRENT_Ppem() \ + Current_Ppem( EXEC_ARG ) + +#define CUR_Ppem() \ + Cur_PPEM( EXEC_ARG ) + +#define INS_SxVTL( a, b, c, d ) \ + Ins_SxVTL( EXEC_ARG_ a, b, c, d ) + +#define COMPUTE_Funcs() \ + Compute_Funcs( EXEC_ARG ) + +#define COMPUTE_Round( a ) \ + Compute_Round( EXEC_ARG_ a ) + +#define COMPUTE_Point_Displacement( a, b, c, d ) \ + Compute_Point_Displacement( EXEC_ARG_ a, b, c, d ) + +#define MOVE_Zp2_Point( a, b, c, t ) \ + Move_Zp2_Point( EXEC_ARG_ a, b, c, t ) + + + /*************************************************************************/ + /* */ + /* Instruction dispatch function, as used by the interpreter. */ + /* */ + typedef void (*TInstruction_Function)( INS_ARG ); + + + /*************************************************************************/ + /* */ + /* A simple bounds-checking macro. */ + /* */ +#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) + +#undef SUCCESS +#define SUCCESS 0 + +#undef FAILURE +#define FAILURE 1 + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING +#define GUESS_VECTOR( V ) \ + if ( CUR.face->unpatented_hinting ) \ + { \ + CUR.GS.V.x = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0x4000 : 0 ); \ + CUR.GS.V.y = (FT_F2Dot14)( CUR.GS.both_x_axis ? 0 : 0x4000 ); \ + } +#else +#define GUESS_VECTOR( V ) +#endif + + /*************************************************************************/ + /* */ + /* CODERANGE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Goto_CodeRange */ + /* */ + /* <Description> */ + /* Switches to a new code range (updates the code related elements in */ + /* `exec', and `IP'). */ + /* */ + /* <Input> */ + /* range :: The new execution code range. */ + /* */ + /* IP :: The new IP in the new code range. */ + /* */ + /* <InOut> */ + /* exec :: The target execution context. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Goto_CodeRange( TT_ExecContext exec, + FT_Int range, + FT_Long IP ) + { + TT_CodeRange* coderange; + + + FT_ASSERT( range >= 1 && range <= 3 ); + + coderange = &exec->codeRangeTable[range - 1]; + + FT_ASSERT( coderange->base != NULL ); + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for IP <= Size instead of IP < Size. */ + /* */ + FT_ASSERT( (FT_ULong)IP <= coderange->size ); + + exec->code = coderange->base; + exec->codeSize = coderange->size; + exec->IP = IP; + exec->curRange = range; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Set_CodeRange */ + /* */ + /* <Description> */ + /* Sets a code range. */ + /* */ + /* <Input> */ + /* range :: The code range index. */ + /* */ + /* base :: The new code base. */ + /* */ + /* length :: The range size in bytes. */ + /* */ + /* <InOut> */ + /* exec :: The target execution context. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Set_CodeRange( TT_ExecContext exec, + FT_Int range, + void* base, + FT_Long length ) + { + FT_ASSERT( range >= 1 && range <= 3 ); + + exec->codeRangeTable[range - 1].base = (FT_Byte*)base; + exec->codeRangeTable[range - 1].size = length; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Clear_CodeRange */ + /* */ + /* <Description> */ + /* Clears a code range. */ + /* */ + /* <Input> */ + /* range :: The code range index. */ + /* */ + /* <InOut> */ + /* exec :: The target execution context. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Does not set the Error variable. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Clear_CodeRange( TT_ExecContext exec, + FT_Int range ) + { + FT_ASSERT( range >= 1 && range <= 3 ); + + exec->codeRangeTable[range - 1].base = NULL; + exec->codeRangeTable[range - 1].size = 0; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* EXECUTION CONTEXT ROUTINES */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Destroy_Context */ + /* */ + /* <Description> */ + /* Destroys a given context. */ + /* */ + /* <Input> */ + /* exec :: A handle to the target execution context. */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ) + { + /* free composite load stack */ + FT_FREE( exec->loadStack ); + exec->loadSize = 0; + + /* points zone */ + exec->maxPoints = 0; + exec->maxContours = 0; + + /* free stack */ + FT_FREE( exec->stack ); + exec->stackSize = 0; + + /* free call stack */ + FT_FREE( exec->callStack ); + exec->callSize = 0; + exec->callTop = 0; + + /* free glyph code range */ + FT_FREE( exec->glyphIns ); + exec->glyphSize = 0; + + exec->size = NULL; + exec->face = NULL; + + FT_FREE( exec ); + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Init_Context */ + /* */ + /* <Description> */ + /* Initializes a context object. */ + /* */ + /* <Input> */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* face :: A handle to the source TrueType face object. */ + /* */ + /* <InOut> */ + /* exec :: A handle to the target execution context. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Init_Context( TT_ExecContext exec, + TT_Face face, + FT_Memory memory ) + { + FT_Error error; + + + FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n", + exec, face )); + + exec->memory = memory; + exec->callSize = 32; + + if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) ) + goto Fail_Memory; + + /* all values in the context are set to 0 already, but this is */ + /* here as a remainder */ + exec->maxPoints = 0; + exec->maxContours = 0; + + exec->stackSize = 0; + exec->loadSize = 0; + exec->glyphSize = 0; + + exec->stack = NULL; + exec->loadStack = NULL; + exec->glyphIns = NULL; + + exec->face = face; + exec->size = NULL; + + return TT_Err_Ok; + + Fail_Memory: + FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n", + (FT_Long)exec )); + TT_Destroy_Context( exec, memory ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Update_Max */ + /* */ + /* <Description> */ + /* Checks the size of a buffer and reallocates it if necessary. */ + /* */ + /* <Input> */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* multiplier :: The size in bytes of each element in the buffer. */ + /* */ + /* new_max :: The new capacity (size) of the buffer. */ + /* */ + /* <InOut> */ + /* size :: The address of the buffer's current size expressed */ + /* in elements. */ + /* */ + /* buff :: The address of the buffer base pointer. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + static FT_Error + Update_Max( FT_Memory memory, + FT_ULong* size, + FT_Long multiplier, + void** buff, + FT_ULong new_max ) + { + FT_Error error; + + + if ( *size < new_max ) + { + if ( FT_REALLOC( *buff, *size, new_max * multiplier ) ) + return error; + *size = new_max; + } + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Load_Context */ + /* */ + /* <Description> */ + /* Prepare an execution context for glyph hinting. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* size :: A handle to the source size object. */ + /* */ + /* <InOut> */ + /* exec :: A handle to the target execution context. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ) + { + FT_Int i; + FT_ULong tmp; + TT_MaxProfile* maxp; + FT_Error error; + + + exec->face = face; + maxp = &face->max_profile; + exec->size = size; + + if ( size ) + { + exec->numFDefs = size->num_function_defs; + exec->maxFDefs = size->max_function_defs; + exec->numIDefs = size->num_instruction_defs; + exec->maxIDefs = size->max_instruction_defs; + exec->FDefs = size->function_defs; + exec->IDefs = size->instruction_defs; + exec->tt_metrics = size->ttmetrics; + exec->metrics = size->metrics; + + exec->maxFunc = size->max_func; + exec->maxIns = size->max_ins; + + for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) + exec->codeRangeTable[i] = size->codeRangeTable[i]; + + /* set graphics state */ + exec->GS = size->GS; + + exec->cvtSize = size->cvt_size; + exec->cvt = size->cvt; + + exec->storeSize = size->storage_size; + exec->storage = size->storage; + + exec->twilight = size->twilight; + } + + error = Update_Max( exec->memory, + &exec->loadSize, + sizeof ( TT_SubGlyphRec ), + (void**)&exec->loadStack, + exec->face->max_components + 1 ); + if ( error ) + return error; + + /* XXX: We reserve a little more elements on the stack to deal safely */ + /* with broken fonts like arialbs, courbs, timesbs, etc. */ + tmp = exec->stackSize; + error = Update_Max( exec->memory, + &tmp, + sizeof ( FT_F26Dot6 ), + (void**)&exec->stack, + maxp->maxStackElements + 32 ); + exec->stackSize = (FT_UInt)tmp; + if ( error ) + return error; + + tmp = exec->glyphSize; + error = Update_Max( exec->memory, + &tmp, + sizeof ( FT_Byte ), + (void**)&exec->glyphIns, + maxp->maxSizeOfInstructions ); + exec->glyphSize = (FT_UShort)tmp; + if ( error ) + return error; + + exec->pts.n_points = 0; + exec->pts.n_contours = 0; + + exec->instruction_trap = FALSE; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Save_Context */ + /* */ + /* <Description> */ + /* Saves the code ranges in a `size' object. */ + /* */ + /* <Input> */ + /* exec :: A handle to the source execution context. */ + /* */ + /* <InOut> */ + /* size :: A handle to the target size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Save_Context( TT_ExecContext exec, + TT_Size size ) + { + FT_Int i; + + + /* XXXX: Will probably disappear soon with all the code range */ + /* management, which is now rather obsolete. */ + /* */ + size->num_function_defs = exec->numFDefs; + size->num_instruction_defs = exec->numIDefs; + + size->max_func = exec->maxFunc; + size->max_ins = exec->maxIns; + + for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) + size->codeRangeTable[i] = exec->codeRangeTable[i]; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Run_Context */ + /* */ + /* <Description> */ + /* Executes one or more instructions in the execution context. */ + /* */ + /* <Input> */ + /* debug :: A Boolean flag. If set, the function sets some internal */ + /* variables and returns immediately, otherwise TT_RunIns() */ + /* is called. */ + /* */ + /* This is commented out currently. */ + /* */ + /* <Input> */ + /* exec :: A handle to the target execution context. */ + /* */ + /* <Return> */ + /* TrueTyoe error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Run_Context( TT_ExecContext exec, + FT_Bool debug ) + { + FT_Error error; + + + if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) ) + != TT_Err_Ok ) + return error; + + exec->zp0 = exec->pts; + exec->zp1 = exec->pts; + exec->zp2 = exec->pts; + + exec->GS.gep0 = 1; + exec->GS.gep1 = 1; + exec->GS.gep2 = 1; + + exec->GS.projVector.x = 0x4000; + exec->GS.projVector.y = 0x0000; + + exec->GS.freeVector = exec->GS.projVector; + exec->GS.dualVector = exec->GS.projVector; + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + exec->GS.both_x_axis = TRUE; +#endif + + exec->GS.round_state = 1; + exec->GS.loop = 1; + + /* some glyphs leave something on the stack. so we clean it */ + /* before a new execution. */ + exec->top = 0; + exec->callTop = 0; + +#if 1 + FT_UNUSED( debug ); + + return exec->face->interpreter( exec ); +#else + if ( !debug ) + return TT_RunIns( exec ); + else + return TT_Err_Ok; +#endif + } + + + const TT_GraphicsState tt_default_graphics_state = + { + 0, 0, 0, + { 0x4000, 0 }, + { 0x4000, 0 }, + { 0x4000, 0 }, + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + TRUE, +#endif + + 1, 64, 1, + TRUE, 68, 0, 0, 9, 3, + 0, FALSE, 2, 1, 1, 1 + }; + + + /* documentation is in ttinterp.h */ + + FT_EXPORT_DEF( TT_ExecContext ) + TT_New_Context( TT_Face face ) + { + TT_Driver driver; + TT_ExecContext exec; + FT_Memory memory; + + + if ( !face ) + return 0; + + driver = (TT_Driver)face->root.driver; + + memory = driver->root.root.memory; + exec = driver->context; + + if ( !driver->context ) + { + FT_Error error; + + + /* allocate object */ + if ( FT_NEW( exec ) ) + goto Exit; + + /* initialize it */ + error = Init_Context( exec, face, memory ); + if ( error ) + goto Fail; + + /* store it into the driver */ + driver->context = exec; + } + + Exit: + return driver->context; + + Fail: + FT_FREE( exec ); + + return 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_Done_Context */ + /* */ + /* <Description> */ + /* Discards an execution context. */ + /* */ + /* <Input> */ + /* exec :: A handle to the target execution context. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + TT_Done_Context( TT_ExecContext exec ) + { + /* Nothing at all for now */ + FT_UNUSED( exec ); + + return TT_Err_Ok; + } + + + + /*************************************************************************/ + /* */ + /* Before an opcode is executed, the interpreter verifies that there are */ + /* enough arguments on the stack, with the help of the Pop_Push_Count */ + /* table. */ + /* */ + /* For each opcode, the first column gives the number of arguments that */ + /* are popped from the stack; the second one gives the number of those */ + /* that are pushed in result. */ + /* */ + /* Note that for opcodes with a varying number of parameters, either 0 */ + /* or 1 arg is verified before execution, depending on the nature of the */ + /* instruction: */ + /* */ + /* - if the number of arguments is given by the bytecode stream or the */ + /* loop variable, 0 is chosen. */ + /* */ + /* - if the first argument is a count n that is followed by arguments */ + /* a1 .. an, then 1 is chosen. */ + /* */ + /*************************************************************************/ + + +#undef PACK +#define PACK( x, y ) ( ( x << 4 ) | y ) + + + static + const FT_Byte Pop_Push_Count[256] = + { + /* opcodes are gathered in groups of 16 */ + /* please keep the spaces as they are */ + + /* SVTCA y */ PACK( 0, 0 ), + /* SVTCA x */ PACK( 0, 0 ), + /* SPvTCA y */ PACK( 0, 0 ), + /* SPvTCA x */ PACK( 0, 0 ), + /* SFvTCA y */ PACK( 0, 0 ), + /* SFvTCA x */ PACK( 0, 0 ), + /* SPvTL // */ PACK( 2, 0 ), + /* SPvTL + */ PACK( 2, 0 ), + /* SFvTL // */ PACK( 2, 0 ), + /* SFvTL + */ PACK( 2, 0 ), + /* SPvFS */ PACK( 2, 0 ), + /* SFvFS */ PACK( 2, 0 ), + /* GPV */ PACK( 0, 2 ), + /* GFV */ PACK( 0, 2 ), + /* SFvTPv */ PACK( 0, 0 ), + /* ISECT */ PACK( 5, 0 ), + + /* SRP0 */ PACK( 1, 0 ), + /* SRP1 */ PACK( 1, 0 ), + /* SRP2 */ PACK( 1, 0 ), + /* SZP0 */ PACK( 1, 0 ), + /* SZP1 */ PACK( 1, 0 ), + /* SZP2 */ PACK( 1, 0 ), + /* SZPS */ PACK( 1, 0 ), + /* SLOOP */ PACK( 1, 0 ), + /* RTG */ PACK( 0, 0 ), + /* RTHG */ PACK( 0, 0 ), + /* SMD */ PACK( 1, 0 ), + /* ELSE */ PACK( 0, 0 ), + /* JMPR */ PACK( 1, 0 ), + /* SCvTCi */ PACK( 1, 0 ), + /* SSwCi */ PACK( 1, 0 ), + /* SSW */ PACK( 1, 0 ), + + /* DUP */ PACK( 1, 2 ), + /* POP */ PACK( 1, 0 ), + /* CLEAR */ PACK( 0, 0 ), + /* SWAP */ PACK( 2, 2 ), + /* DEPTH */ PACK( 0, 1 ), + /* CINDEX */ PACK( 1, 1 ), + /* MINDEX */ PACK( 1, 0 ), + /* AlignPTS */ PACK( 2, 0 ), + /* INS_$28 */ PACK( 0, 0 ), + /* UTP */ PACK( 1, 0 ), + /* LOOPCALL */ PACK( 2, 0 ), + /* CALL */ PACK( 1, 0 ), + /* FDEF */ PACK( 1, 0 ), + /* ENDF */ PACK( 0, 0 ), + /* MDAP[0] */ PACK( 1, 0 ), + /* MDAP[1] */ PACK( 1, 0 ), + + /* IUP[0] */ PACK( 0, 0 ), + /* IUP[1] */ PACK( 0, 0 ), + /* SHP[0] */ PACK( 0, 0 ), + /* SHP[1] */ PACK( 0, 0 ), + /* SHC[0] */ PACK( 1, 0 ), + /* SHC[1] */ PACK( 1, 0 ), + /* SHZ[0] */ PACK( 1, 0 ), + /* SHZ[1] */ PACK( 1, 0 ), + /* SHPIX */ PACK( 1, 0 ), + /* IP */ PACK( 0, 0 ), + /* MSIRP[0] */ PACK( 2, 0 ), + /* MSIRP[1] */ PACK( 2, 0 ), + /* AlignRP */ PACK( 0, 0 ), + /* RTDG */ PACK( 0, 0 ), + /* MIAP[0] */ PACK( 2, 0 ), + /* MIAP[1] */ PACK( 2, 0 ), + + /* NPushB */ PACK( 0, 0 ), + /* NPushW */ PACK( 0, 0 ), + /* WS */ PACK( 2, 0 ), + /* RS */ PACK( 1, 1 ), + /* WCvtP */ PACK( 2, 0 ), + /* RCvt */ PACK( 1, 1 ), + /* GC[0] */ PACK( 1, 1 ), + /* GC[1] */ PACK( 1, 1 ), + /* SCFS */ PACK( 2, 0 ), + /* MD[0] */ PACK( 2, 1 ), + /* MD[1] */ PACK( 2, 1 ), + /* MPPEM */ PACK( 0, 1 ), + /* MPS */ PACK( 0, 1 ), + /* FlipON */ PACK( 0, 0 ), + /* FlipOFF */ PACK( 0, 0 ), + /* DEBUG */ PACK( 1, 0 ), + + /* LT */ PACK( 2, 1 ), + /* LTEQ */ PACK( 2, 1 ), + /* GT */ PACK( 2, 1 ), + /* GTEQ */ PACK( 2, 1 ), + /* EQ */ PACK( 2, 1 ), + /* NEQ */ PACK( 2, 1 ), + /* ODD */ PACK( 1, 1 ), + /* EVEN */ PACK( 1, 1 ), + /* IF */ PACK( 1, 0 ), + /* EIF */ PACK( 0, 0 ), + /* AND */ PACK( 2, 1 ), + /* OR */ PACK( 2, 1 ), + /* NOT */ PACK( 1, 1 ), + /* DeltaP1 */ PACK( 1, 0 ), + /* SDB */ PACK( 1, 0 ), + /* SDS */ PACK( 1, 0 ), + + /* ADD */ PACK( 2, 1 ), + /* SUB */ PACK( 2, 1 ), + /* DIV */ PACK( 2, 1 ), + /* MUL */ PACK( 2, 1 ), + /* ABS */ PACK( 1, 1 ), + /* NEG */ PACK( 1, 1 ), + /* FLOOR */ PACK( 1, 1 ), + /* CEILING */ PACK( 1, 1 ), + /* ROUND[0] */ PACK( 1, 1 ), + /* ROUND[1] */ PACK( 1, 1 ), + /* ROUND[2] */ PACK( 1, 1 ), + /* ROUND[3] */ PACK( 1, 1 ), + /* NROUND[0] */ PACK( 1, 1 ), + /* NROUND[1] */ PACK( 1, 1 ), + /* NROUND[2] */ PACK( 1, 1 ), + /* NROUND[3] */ PACK( 1, 1 ), + + /* WCvtF */ PACK( 2, 0 ), + /* DeltaP2 */ PACK( 1, 0 ), + /* DeltaP3 */ PACK( 1, 0 ), + /* DeltaCn[0] */ PACK( 1, 0 ), + /* DeltaCn[1] */ PACK( 1, 0 ), + /* DeltaCn[2] */ PACK( 1, 0 ), + /* SROUND */ PACK( 1, 0 ), + /* S45Round */ PACK( 1, 0 ), + /* JROT */ PACK( 2, 0 ), + /* JROF */ PACK( 2, 0 ), + /* ROFF */ PACK( 0, 0 ), + /* INS_$7B */ PACK( 0, 0 ), + /* RUTG */ PACK( 0, 0 ), + /* RDTG */ PACK( 0, 0 ), + /* SANGW */ PACK( 1, 0 ), + /* AA */ PACK( 1, 0 ), + + /* FlipPT */ PACK( 0, 0 ), + /* FlipRgON */ PACK( 2, 0 ), + /* FlipRgOFF */ PACK( 2, 0 ), + /* INS_$83 */ PACK( 0, 0 ), + /* INS_$84 */ PACK( 0, 0 ), + /* ScanCTRL */ PACK( 1, 0 ), + /* SDVPTL[0] */ PACK( 2, 0 ), + /* SDVPTL[1] */ PACK( 2, 0 ), + /* GetINFO */ PACK( 1, 1 ), + /* IDEF */ PACK( 1, 0 ), + /* ROLL */ PACK( 3, 3 ), + /* MAX */ PACK( 2, 1 ), + /* MIN */ PACK( 2, 1 ), + /* ScanTYPE */ PACK( 1, 0 ), + /* InstCTRL */ PACK( 2, 0 ), + /* INS_$8F */ PACK( 0, 0 ), + + /* INS_$90 */ PACK( 0, 0 ), + /* INS_$91 */ PACK( 0, 0 ), + /* INS_$92 */ PACK( 0, 0 ), + /* INS_$93 */ PACK( 0, 0 ), + /* INS_$94 */ PACK( 0, 0 ), + /* INS_$95 */ PACK( 0, 0 ), + /* INS_$96 */ PACK( 0, 0 ), + /* INS_$97 */ PACK( 0, 0 ), + /* INS_$98 */ PACK( 0, 0 ), + /* INS_$99 */ PACK( 0, 0 ), + /* INS_$9A */ PACK( 0, 0 ), + /* INS_$9B */ PACK( 0, 0 ), + /* INS_$9C */ PACK( 0, 0 ), + /* INS_$9D */ PACK( 0, 0 ), + /* INS_$9E */ PACK( 0, 0 ), + /* INS_$9F */ PACK( 0, 0 ), + + /* INS_$A0 */ PACK( 0, 0 ), + /* INS_$A1 */ PACK( 0, 0 ), + /* INS_$A2 */ PACK( 0, 0 ), + /* INS_$A3 */ PACK( 0, 0 ), + /* INS_$A4 */ PACK( 0, 0 ), + /* INS_$A5 */ PACK( 0, 0 ), + /* INS_$A6 */ PACK( 0, 0 ), + /* INS_$A7 */ PACK( 0, 0 ), + /* INS_$A8 */ PACK( 0, 0 ), + /* INS_$A9 */ PACK( 0, 0 ), + /* INS_$AA */ PACK( 0, 0 ), + /* INS_$AB */ PACK( 0, 0 ), + /* INS_$AC */ PACK( 0, 0 ), + /* INS_$AD */ PACK( 0, 0 ), + /* INS_$AE */ PACK( 0, 0 ), + /* INS_$AF */ PACK( 0, 0 ), + + /* PushB[0] */ PACK( 0, 1 ), + /* PushB[1] */ PACK( 0, 2 ), + /* PushB[2] */ PACK( 0, 3 ), + /* PushB[3] */ PACK( 0, 4 ), + /* PushB[4] */ PACK( 0, 5 ), + /* PushB[5] */ PACK( 0, 6 ), + /* PushB[6] */ PACK( 0, 7 ), + /* PushB[7] */ PACK( 0, 8 ), + /* PushW[0] */ PACK( 0, 1 ), + /* PushW[1] */ PACK( 0, 2 ), + /* PushW[2] */ PACK( 0, 3 ), + /* PushW[3] */ PACK( 0, 4 ), + /* PushW[4] */ PACK( 0, 5 ), + /* PushW[5] */ PACK( 0, 6 ), + /* PushW[6] */ PACK( 0, 7 ), + /* PushW[7] */ PACK( 0, 8 ), + + /* MDRP[00] */ PACK( 1, 0 ), + /* MDRP[01] */ PACK( 1, 0 ), + /* MDRP[02] */ PACK( 1, 0 ), + /* MDRP[03] */ PACK( 1, 0 ), + /* MDRP[04] */ PACK( 1, 0 ), + /* MDRP[05] */ PACK( 1, 0 ), + /* MDRP[06] */ PACK( 1, 0 ), + /* MDRP[07] */ PACK( 1, 0 ), + /* MDRP[08] */ PACK( 1, 0 ), + /* MDRP[09] */ PACK( 1, 0 ), + /* MDRP[10] */ PACK( 1, 0 ), + /* MDRP[11] */ PACK( 1, 0 ), + /* MDRP[12] */ PACK( 1, 0 ), + /* MDRP[13] */ PACK( 1, 0 ), + /* MDRP[14] */ PACK( 1, 0 ), + /* MDRP[15] */ PACK( 1, 0 ), + + /* MDRP[16] */ PACK( 1, 0 ), + /* MDRP[17] */ PACK( 1, 0 ), + /* MDRP[18] */ PACK( 1, 0 ), + /* MDRP[19] */ PACK( 1, 0 ), + /* MDRP[20] */ PACK( 1, 0 ), + /* MDRP[21] */ PACK( 1, 0 ), + /* MDRP[22] */ PACK( 1, 0 ), + /* MDRP[23] */ PACK( 1, 0 ), + /* MDRP[24] */ PACK( 1, 0 ), + /* MDRP[25] */ PACK( 1, 0 ), + /* MDRP[26] */ PACK( 1, 0 ), + /* MDRP[27] */ PACK( 1, 0 ), + /* MDRP[28] */ PACK( 1, 0 ), + /* MDRP[29] */ PACK( 1, 0 ), + /* MDRP[30] */ PACK( 1, 0 ), + /* MDRP[31] */ PACK( 1, 0 ), + + /* MIRP[00] */ PACK( 2, 0 ), + /* MIRP[01] */ PACK( 2, 0 ), + /* MIRP[02] */ PACK( 2, 0 ), + /* MIRP[03] */ PACK( 2, 0 ), + /* MIRP[04] */ PACK( 2, 0 ), + /* MIRP[05] */ PACK( 2, 0 ), + /* MIRP[06] */ PACK( 2, 0 ), + /* MIRP[07] */ PACK( 2, 0 ), + /* MIRP[08] */ PACK( 2, 0 ), + /* MIRP[09] */ PACK( 2, 0 ), + /* MIRP[10] */ PACK( 2, 0 ), + /* MIRP[11] */ PACK( 2, 0 ), + /* MIRP[12] */ PACK( 2, 0 ), + /* MIRP[13] */ PACK( 2, 0 ), + /* MIRP[14] */ PACK( 2, 0 ), + /* MIRP[15] */ PACK( 2, 0 ), + + /* MIRP[16] */ PACK( 2, 0 ), + /* MIRP[17] */ PACK( 2, 0 ), + /* MIRP[18] */ PACK( 2, 0 ), + /* MIRP[19] */ PACK( 2, 0 ), + /* MIRP[20] */ PACK( 2, 0 ), + /* MIRP[21] */ PACK( 2, 0 ), + /* MIRP[22] */ PACK( 2, 0 ), + /* MIRP[23] */ PACK( 2, 0 ), + /* MIRP[24] */ PACK( 2, 0 ), + /* MIRP[25] */ PACK( 2, 0 ), + /* MIRP[26] */ PACK( 2, 0 ), + /* MIRP[27] */ PACK( 2, 0 ), + /* MIRP[28] */ PACK( 2, 0 ), + /* MIRP[29] */ PACK( 2, 0 ), + /* MIRP[30] */ PACK( 2, 0 ), + /* MIRP[31] */ PACK( 2, 0 ) + }; + + + static + const FT_Char opcode_length[256] = + { + 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, 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, + 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17, + + 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 + const FT_Vector Null_Vector = {0,0}; + + +#undef PACK + + +#undef NULL_Vector +#define NULL_Vector (FT_Vector*)&Null_Vector + + + /* compute (a*b)/2^14 with maximal accuracy and rounding */ + static FT_Int32 + TT_MulFix14( FT_Int32 a, + FT_Int b ) + { + FT_Int32 m, s, hi; + FT_UInt32 l, lo; + + + /* compute ax*bx as 64-bit value */ + l = (FT_UInt32)( ( a & 0xFFFFU ) * b ); + m = ( a >> 16 ) * b; + + lo = l + (FT_UInt32)( m << 16 ); + hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l ); + + /* divide the result by 2^14 with rounding */ + s = hi >> 31; + l = lo + (FT_UInt32)s; + hi += s + ( l < lo ); + lo = l; + + l = lo + 0x2000U; + hi += (l < lo); + + return ( hi << 18 ) | ( l >> 14 ); + } + + + /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */ + static FT_Int32 + TT_DotFix14( FT_Int32 ax, + FT_Int32 ay, + FT_Int bx, + FT_Int by ) + { + FT_Int32 m, s, hi1, hi2, hi; + FT_UInt32 l, lo1, lo2, lo; + + + /* compute ax*bx as 64-bit value */ + l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx ); + m = ( ax >> 16 ) * bx; + + lo1 = l + (FT_UInt32)( m << 16 ); + hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l ); + + /* compute ay*by as 64-bit value */ + l = (FT_UInt32)( ( ay & 0xFFFFU ) * by ); + m = ( ay >> 16 ) * by; + + lo2 = l + (FT_UInt32)( m << 16 ); + hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l ); + + /* add them */ + lo = lo1 + lo2; + hi = hi1 + hi2 + ( lo < lo1 ); + + /* divide the result by 2^14 with rounding */ + s = hi >> 31; + l = lo + (FT_UInt32)s; + hi += s + ( l < lo ); + lo = l; + + l = lo + 0x2000U; + hi += ( l < lo ); + + return ( hi << 18 ) | ( l >> 14 ); + } + + + /* return length of given vector */ + +#if 0 + + static FT_Int32 + TT_VecLen( FT_Int32 x, + FT_Int32 y ) + { + FT_Int32 m, hi1, hi2, hi; + FT_UInt32 l, lo1, lo2, lo; + + + /* compute x*x as 64-bit value */ + lo = (FT_UInt32)( x & 0xFFFFU ); + hi = x >> 16; + + l = lo * lo; + m = hi * lo; + hi = hi * hi; + + lo1 = l + (FT_UInt32)( m << 17 ); + hi1 = hi + ( m >> 15 ) + ( lo1 < l ); + + /* compute y*y as 64-bit value */ + lo = (FT_UInt32)( y & 0xFFFFU ); + hi = y >> 16; + + l = lo * lo; + m = hi * lo; + hi = hi * hi; + + lo2 = l + (FT_UInt32)( m << 17 ); + hi2 = hi + ( m >> 15 ) + ( lo2 < l ); + + /* add them to get 'x*x+y*y' as 64-bit value */ + lo = lo1 + lo2; + hi = hi1 + hi2 + ( lo < lo1 ); + + /* compute the square root of this value */ + { + FT_UInt32 root, rem, test_div; + FT_Int count; + + + root = 0; + + { + rem = 0; + count = 32; + do + { + rem = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 ); + hi = ( hi << 2 ) | ( lo >> 30 ); + lo <<= 2; + root <<= 1; + test_div = ( root << 1 ) + 1; + + if ( rem >= test_div ) + { + rem -= test_div; + root += 1; + } + } while ( --count ); + } + + return (FT_Int32)root; + } + } + +#else + + /* this version uses FT_Vector_Length which computes the same value */ + /* much, much faster.. */ + /* */ + static FT_F26Dot6 + TT_VecLen( FT_F26Dot6 X, + FT_F26Dot6 Y ) + { + FT_Vector v; + + + v.x = X; + v.y = Y; + + return FT_Vector_Length( &v ); + } + +#endif + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Current_Ratio */ + /* */ + /* <Description> */ + /* Returns the current aspect ratio scaling factor depending on the */ + /* projection vector's state and device resolutions. */ + /* */ + /* <Return> */ + /* The aspect ratio in 16.16 format, always <= 1.0 . */ + /* */ + static FT_Long + Current_Ratio( EXEC_OP ) + { + if ( !CUR.tt_metrics.ratio ) + { +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + if ( CUR.face->unpatented_hinting ) + { + if ( CUR.GS.both_x_axis ) + CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio; + else + CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio; + } + else +#endif + { + if ( CUR.GS.projVector.y == 0 ) + CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio; + + else if ( CUR.GS.projVector.x == 0 ) + CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio; + + else + { + FT_Long x, y; + + + x = TT_MULDIV( CUR.GS.projVector.x, + CUR.tt_metrics.x_ratio, 0x4000 ); + y = TT_MULDIV( CUR.GS.projVector.y, + CUR.tt_metrics.y_ratio, 0x4000 ); + CUR.tt_metrics.ratio = TT_VecLen( x, y ); + } + } + } + return CUR.tt_metrics.ratio; + } + + + static FT_Long + Current_Ppem( EXEC_OP ) + { + return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() ); + } + + + /*************************************************************************/ + /* */ + /* Functions related to the control value table (CVT). */ + /* */ + /*************************************************************************/ + + + FT_CALLBACK_DEF( FT_F26Dot6 ) + Read_CVT( EXEC_OP_ FT_ULong idx ) + { + return CUR.cvt[idx]; + } + + + FT_CALLBACK_DEF( FT_F26Dot6 ) + Read_CVT_Stretched( EXEC_OP_ FT_ULong idx ) + { + return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() ); + } + + + FT_CALLBACK_DEF( void ) + Write_CVT( EXEC_OP_ FT_ULong idx, + FT_F26Dot6 value ) + { + CUR.cvt[idx] = value; + } + + + FT_CALLBACK_DEF( void ) + Write_CVT_Stretched( EXEC_OP_ FT_ULong idx, + FT_F26Dot6 value ) + { + CUR.cvt[idx] = FT_DivFix( value, CURRENT_Ratio() ); + } + + + FT_CALLBACK_DEF( void ) + Move_CVT( EXEC_OP_ FT_ULong idx, + FT_F26Dot6 value ) + { + CUR.cvt[idx] += value; + } + + + FT_CALLBACK_DEF( void ) + Move_CVT_Stretched( EXEC_OP_ FT_ULong idx, + FT_F26Dot6 value ) + { + CUR.cvt[idx] += FT_DivFix( value, CURRENT_Ratio() ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* GetShortIns */ + /* */ + /* <Description> */ + /* Returns a short integer taken from the instruction stream at */ + /* address IP. */ + /* */ + /* <Return> */ + /* Short read at code[IP]. */ + /* */ + /* <Note> */ + /* This one could become a macro. */ + /* */ + static FT_Short + GetShortIns( EXEC_OP ) + { + /* Reading a byte stream so there is no endianess (DaveP) */ + CUR.IP += 2; + return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) + + CUR.code[CUR.IP - 1] ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Ins_Goto_CodeRange */ + /* */ + /* <Description> */ + /* Goes to a certain code range in the instruction stream. */ + /* */ + /* <Input> */ + /* aRange :: The index of the code range. */ + /* */ + /* aIP :: The new IP address in the code range. */ + /* */ + /* <Return> */ + /* SUCCESS or FAILURE. */ + /* */ + static FT_Bool + Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange, + FT_ULong aIP ) + { + TT_CodeRange* range; + + + if ( aRange < 1 || aRange > 3 ) + { + CUR.error = TT_Err_Bad_Argument; + return FAILURE; + } + + range = &CUR.codeRangeTable[aRange - 1]; + + if ( range->base == NULL ) /* invalid coderange */ + { + CUR.error = TT_Err_Invalid_CodeRange; + return FAILURE; + } + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for AIP <= Size, instead of AIP < Size. */ + + if ( aIP > range->size ) + { + CUR.error = TT_Err_Code_Overflow; + return FAILURE; + } + + CUR.code = range->base; + CUR.codeSize = range->size; + CUR.IP = aIP; + CUR.curRange = aRange; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Direct_Move */ + /* */ + /* <Description> */ + /* Moves a point by a given distance along the freedom vector. The */ + /* point will be `touched'. */ + /* */ + /* <Input> */ + /* point :: The index of the point to move. */ + /* */ + /* distance :: The distance to apply. */ + /* */ + /* <InOut> */ + /* zone :: The affected glyph zone. */ + /* */ + static void + Direct_Move( EXEC_OP_ TT_GlyphZone zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_F26Dot6 v; + + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + FT_ASSERT( !CUR.face->unpatented_hinting ); +#endif + + v = CUR.GS.freeVector.x; + + if ( v != 0 ) + { + zone->cur[point].x += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + + zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; + } + + v = CUR.GS.freeVector.y; + + if ( v != 0 ) + { + zone->cur[point].y += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + + zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Direct_Move_Orig */ + /* */ + /* <Description> */ + /* Moves the *original* position of a point by a given distance along */ + /* the freedom vector. Obviously, the point will not be `touched'. */ + /* */ + /* <Input> */ + /* point :: The index of the point to move. */ + /* */ + /* distance :: The distance to apply. */ + /* */ + /* <InOut> */ + /* zone :: The affected glyph zone. */ + /* */ + static void + Direct_Move_Orig( EXEC_OP_ TT_GlyphZone zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_F26Dot6 v; + + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + FT_ASSERT( !CUR.face->unpatented_hinting ); +#endif + + v = CUR.GS.freeVector.x; + + if ( v != 0 ) + zone->org[point].x += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + + v = CUR.GS.freeVector.y; + + if ( v != 0 ) + zone->org[point].y += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + } + + + /*************************************************************************/ + /* */ + /* Special versions of Direct_Move() */ + /* */ + /* The following versions are used whenever both vectors are both */ + /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ + /* */ + /*************************************************************************/ + + + static void + Direct_Move_X( EXEC_OP_ TT_GlyphZone zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_UNUSED_EXEC; + + zone->cur[point].x += distance; + zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; + } + + + static void + Direct_Move_Y( EXEC_OP_ TT_GlyphZone zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_UNUSED_EXEC; + + zone->cur[point].y += distance; + zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; + } + + + /*************************************************************************/ + /* */ + /* Special versions of Direct_Move_Orig() */ + /* */ + /* The following versions are used whenever both vectors are both */ + /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ + /* */ + /*************************************************************************/ + + + static void + Direct_Move_Orig_X( EXEC_OP_ TT_GlyphZone zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_UNUSED_EXEC; + + zone->org[point].x += distance; + } + + + static void + Direct_Move_Orig_Y( EXEC_OP_ TT_GlyphZone zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_UNUSED_EXEC; + + zone->org[point].y += distance; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_None */ + /* */ + /* <Description> */ + /* Does not round, but adds engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance (not) to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* The compensated distance. */ + /* */ + /* <Note> */ + /* The TrueType specification says very few about the relationship */ + /* between rounding and engine compensation. However, it seems from */ + /* the description of super round that we should add the compensation */ + /* before rounding. */ + /* */ + static FT_F26Dot6 + Round_None( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation; + if ( distance && val < 0 ) + val = 0; + } + else { + val = distance - compensation; + if ( val > 0 ) + val = 0; + } + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_To_Grid */ + /* */ + /* <Description> */ + /* Rounds value to grid after adding engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* Rounded distance. */ + /* */ + static FT_F26Dot6 + Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation + 32; + if ( distance && val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -FT_PIX_ROUND( compensation - distance ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_To_Half_Grid */ + /* */ + /* <Description> */ + /* Rounds value to half grid after adding engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* Rounded distance. */ + /* */ + static FT_F26Dot6 + Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = FT_PIX_FLOOR( distance + compensation ) + 32; + if ( distance && val < 0 ) + val = 0; + } + else + { + val = -( FT_PIX_FLOOR( compensation - distance ) + 32 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_Down_To_Grid */ + /* */ + /* <Description> */ + /* Rounds value down to grid after adding engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* Rounded distance. */ + /* */ + static FT_F26Dot6 + Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation; + if ( distance && val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -( ( compensation - distance ) & -64 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_Up_To_Grid */ + /* */ + /* <Description> */ + /* Rounds value up to grid after adding engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* Rounded distance. */ + /* */ + static FT_F26Dot6 + Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + + FT_UNUSED_EXEC; + + if ( distance >= 0 ) + { + val = distance + compensation + 63; + if ( distance && val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = - FT_PIX_CEIL( compensation - distance ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_To_Double_Grid */ + /* */ + /* <Description> */ + /* Rounds value to double grid after adding engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* Rounded distance. */ + /* */ + static FT_F26Dot6 + Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation + 16; + if ( distance && val > 0 ) + val &= ~31; + else + val = 0; + } + else + { + val = -FT_PAD_ROUND( compensation - distance, 32 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_Super */ + /* */ + /* <Description> */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* Rounded distance. */ + /* */ + /* <Note> */ + /* The TrueType specification says very few about the relationship */ + /* between rounding and engine compensation. However, it seems from */ + /* the description of super round that we should add the compensation */ + /* before rounding. */ + /* */ + static FT_F26Dot6 + Round_Super( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = ( distance - CUR.phase + CUR.threshold + compensation ) & + -CUR.period; + if ( distance && val < 0 ) + val = 0; + val += CUR.phase; + } + else + { + val = -( ( CUR.threshold - CUR.phase - distance + compensation ) & + -CUR.period ); + if ( val > 0 ) + val = 0; + val -= CUR.phase; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Round_Super_45 */ + /* */ + /* <Description> */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* <Input> */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* <Return> */ + /* Rounded distance. */ + /* */ + /* <Note> */ + /* There is a separate function for Round_Super_45() as we may need */ + /* greater precision. */ + /* */ + static FT_F26Dot6 + Round_Super_45( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = ( ( distance - CUR.phase + CUR.threshold + compensation ) / + CUR.period ) * CUR.period; + if ( distance && val < 0 ) + val = 0; + val += CUR.phase; + } + else + { + val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) / + CUR.period ) * CUR.period ); + if ( val > 0 ) + val = 0; + val -= CUR.phase; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Compute_Round */ + /* */ + /* <Description> */ + /* Sets the rounding mode. */ + /* */ + /* <Input> */ + /* round_mode :: The rounding mode to be used. */ + /* */ + static void + Compute_Round( EXEC_OP_ FT_Byte round_mode ) + { + switch ( round_mode ) + { + case TT_Round_Off: + CUR.func_round = (TT_Round_Func)Round_None; + break; + + case TT_Round_To_Grid: + CUR.func_round = (TT_Round_Func)Round_To_Grid; + break; + + case TT_Round_Up_To_Grid: + CUR.func_round = (TT_Round_Func)Round_Up_To_Grid; + break; + + case TT_Round_Down_To_Grid: + CUR.func_round = (TT_Round_Func)Round_Down_To_Grid; + break; + + case TT_Round_To_Half_Grid: + CUR.func_round = (TT_Round_Func)Round_To_Half_Grid; + break; + + case TT_Round_To_Double_Grid: + CUR.func_round = (TT_Round_Func)Round_To_Double_Grid; + break; + + case TT_Round_Super: + CUR.func_round = (TT_Round_Func)Round_Super; + break; + + case TT_Round_Super_45: + CUR.func_round = (TT_Round_Func)Round_Super_45; + break; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* SetSuperRound */ + /* */ + /* <Description> */ + /* Sets Super Round parameters. */ + /* */ + /* <Input> */ + /* GridPeriod :: Grid period */ + /* selector :: SROUND opcode */ + /* */ + static void + SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod, + FT_Long selector ) + { + switch ( (FT_Int)( selector & 0xC0 ) ) + { + case 0: + CUR.period = GridPeriod / 2; + break; + + case 0x40: + CUR.period = GridPeriod; + break; + + case 0x80: + CUR.period = GridPeriod * 2; + break; + + /* This opcode is reserved, but... */ + + case 0xC0: + CUR.period = GridPeriod; + break; + } + + switch ( (FT_Int)( selector & 0x30 ) ) + { + case 0: + CUR.phase = 0; + break; + + case 0x10: + CUR.phase = CUR.period / 4; + break; + + case 0x20: + CUR.phase = CUR.period / 2; + break; + + case 0x30: + CUR.phase = CUR.period * 3 / 4; + break; + } + + if ( (selector & 0x0F) == 0 ) + CUR.threshold = CUR.period - 1; + else + CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8; + + CUR.period /= 256; + CUR.phase /= 256; + CUR.threshold /= 256; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Project */ + /* */ + /* <Description> */ + /* Computes the projection of vector given by (v2-v1) along the */ + /* current projection vector. */ + /* */ + /* <Input> */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* <Return> */ + /* The distance in F26dot6 format. */ + /* */ + static FT_F26Dot6 + Project( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + FT_ASSERT( !CUR.face->unpatented_hinting ); +#endif + + return TT_DotFix14( v1->x - v2->x, + v1->y - v2->y, + CUR.GS.projVector.x, + CUR.GS.projVector.y ); + } + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Dual_Project */ + /* */ + /* <Description> */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* current dual vector. */ + /* */ + /* <Input> */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* <Return> */ + /* The distance in F26dot6 format. */ + /* */ + static FT_F26Dot6 + Dual_Project( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + return TT_DotFix14( v1->x - v2->x, + v1->y - v2->y, + CUR.GS.dualVector.x, + CUR.GS.dualVector.y ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Project_x */ + /* */ + /* <Description> */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* horizontal axis. */ + /* */ + /* <Input> */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* <Return> */ + /* The distance in F26dot6 format. */ + /* */ + static FT_F26Dot6 + Project_x( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + FT_UNUSED_EXEC; + + return ( v1->x - v2->x ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Project_y */ + /* */ + /* <Description> */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* vertical axis. */ + /* */ + /* <Input> */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* <Return> */ + /* The distance in F26dot6 format. */ + /* */ + static FT_F26Dot6 + Project_y( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + FT_UNUSED_EXEC; + + return ( v1->y - v2->y ); + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Compute_Funcs */ + /* */ + /* <Description> */ + /* Computes the projection and movement function pointers according */ + /* to the current graphics state. */ + /* */ + static void + Compute_Funcs( EXEC_OP ) + { +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + if ( CUR.face->unpatented_hinting ) + { + /* If both vectors point rightwards along the x axis, set */ + /* `both-x-axis' true, otherwise set it false. The x values only */ + /* need be tested because the vector has been normalised to a unit */ + /* vector of length 0x4000 = unity. */ + CUR.GS.both_x_axis = (FT_Bool)( CUR.GS.projVector.x == 0x4000 && + CUR.GS.freeVector.x == 0x4000 ); + + /* Throw away projection and freedom vector information */ + /* because the patents don't allow them to be stored. */ + /* The relevant US Patents are 5155805 and 5325479. */ + CUR.GS.projVector.x = 0; + CUR.GS.projVector.y = 0; + CUR.GS.freeVector.x = 0; + CUR.GS.freeVector.y = 0; + + if ( CUR.GS.both_x_axis ) + { + CUR.func_project = Project_x; + CUR.func_move = Direct_Move_X; + CUR.func_move_orig = Direct_Move_Orig_X; + } + else + { + CUR.func_project = Project_y; + CUR.func_move = Direct_Move_Y; + CUR.func_move_orig = Direct_Move_Orig_Y; + } + + if ( CUR.GS.dualVector.x == 0x4000 ) + CUR.func_dualproj = Project_x; + else + { + if ( CUR.GS.dualVector.y == 0x4000 ) + CUR.func_dualproj = Project_y; + else + CUR.func_dualproj = Dual_Project; + } + + /* Force recalculation of cached aspect ratio */ + CUR.tt_metrics.ratio = 0; + + return; + } +#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ + + if ( CUR.GS.freeVector.x == 0x4000 ) + CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L; + else + { + if ( CUR.GS.freeVector.y == 0x4000 ) + CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L; + else + CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 + + (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4; + } + + if ( CUR.GS.projVector.x == 0x4000 ) + CUR.func_project = (TT_Project_Func)Project_x; + else + { + if ( CUR.GS.projVector.y == 0x4000 ) + CUR.func_project = (TT_Project_Func)Project_y; + else + CUR.func_project = (TT_Project_Func)Project; + } + + if ( CUR.GS.dualVector.x == 0x4000 ) + CUR.func_dualproj = (TT_Project_Func)Project_x; + else + { + if ( CUR.GS.dualVector.y == 0x4000 ) + CUR.func_dualproj = (TT_Project_Func)Project_y; + else + CUR.func_dualproj = (TT_Project_Func)Dual_Project; + } + + CUR.func_move = (TT_Move_Func)Direct_Move; + CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig; + + if ( CUR.F_dot_P == 0x40000000L ) + { + if ( CUR.GS.freeVector.x == 0x4000 ) + { + CUR.func_move = (TT_Move_Func)Direct_Move_X; + CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X; + } + else + { + if ( CUR.GS.freeVector.y == 0x4000 ) + { + CUR.func_move = (TT_Move_Func)Direct_Move_Y; + CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y; + } + } + } + + /* at small sizes, F_dot_P can become too small, resulting */ + /* in overflows and `spikes' in a number of glyphs like `w'. */ + + if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L ) + CUR.F_dot_P = 0x40000000L; + + /* Disable cached aspect ratio */ + CUR.tt_metrics.ratio = 0; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Normalize */ + /* */ + /* <Description> */ + /* Norms a vector. */ + /* */ + /* <Input> */ + /* Vx :: The horizontal input vector coordinate. */ + /* Vy :: The vertical input vector coordinate. */ + /* */ + /* <Output> */ + /* R :: The normed unit vector. */ + /* */ + /* <Return> */ + /* Returns FAILURE if a vector parameter is zero. */ + /* */ + /* <Note> */ + /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */ + /* R is undefined. */ + /* */ + + + static FT_Bool + Normalize( EXEC_OP_ FT_F26Dot6 Vx, + FT_F26Dot6 Vy, + FT_UnitVector* R ) + { + FT_F26Dot6 W; + FT_Bool S1, S2; + + FT_UNUSED_EXEC; + + + if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L ) + { + Vx *= 0x100; + Vy *= 0x100; + + W = TT_VecLen( Vx, Vy ); + + if ( W == 0 ) + { + /* XXX: UNDOCUMENTED! It seems that it is possible to try */ + /* to normalize the vector (0,0). Return immediately. */ + return SUCCESS; + } + + R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W ); + R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W ); + + return SUCCESS; + } + + W = TT_VecLen( Vx, Vy ); + + Vx = FT_MulDiv( Vx, 0x4000L, W ); + Vy = FT_MulDiv( Vy, 0x4000L, W ); + + W = Vx * Vx + Vy * Vy; + + /* Now, we want that Sqrt( W ) = 0x4000 */ + /* Or 0x1000000 <= W < 0x1004000 */ + + if ( Vx < 0 ) + { + Vx = -Vx; + S1 = TRUE; + } + else + S1 = FALSE; + + if ( Vy < 0 ) + { + Vy = -Vy; + S2 = TRUE; + } + else + S2 = FALSE; + + while ( W < 0x1000000L ) + { + /* We need to increase W by a minimal amount */ + if ( Vx < Vy ) + Vx++; + else + Vy++; + + W = Vx * Vx + Vy * Vy; + } + + while ( W >= 0x1004000L ) + { + /* We need to decrease W by a minimal amount */ + if ( Vx < Vy ) + Vx--; + else + Vy--; + + W = Vx * Vx + Vy * Vy; + } + + /* Note that in various cases, we can only */ + /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */ + + if ( S1 ) + Vx = -Vx; + + if ( S2 ) + Vy = -Vy; + + R->x = (FT_F2Dot14)Vx; /* Type conversion */ + R->y = (FT_F2Dot14)Vy; /* Type conversion */ + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* Here we start with the implementation of the various opcodes. */ + /* */ + /*************************************************************************/ + + + static FT_Bool + Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1, + FT_UShort aIdx2, + FT_Int aOpc, + FT_UnitVector* Vec ) + { + FT_Long A, B, C; + FT_Vector* p1; + FT_Vector* p2; + + + if ( BOUNDS( aIdx1, CUR.zp2.n_points ) || + BOUNDS( aIdx2, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return FAILURE; + } + + p1 = CUR.zp1.cur + aIdx2; + p2 = CUR.zp2.cur + aIdx1; + + A = p1->x - p2->x; + B = p1->y - p2->y; + + if ( ( aOpc & 1 ) != 0 ) + { + C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, Vec ); + + return SUCCESS; + } + + + /* When not using the big switch statements, the interpreter uses a */ + /* call table defined later below in this source. Each opcode must */ + /* thus have a corresponding function, even trivial ones. */ + /* */ + /* They are all defined there. */ + +#define DO_SVTCA \ + { \ + FT_Short A, B; \ + \ + \ + A = (FT_Short)( CUR.opcode & 1 ) << 14; \ + B = A ^ (FT_Short)0x4000; \ + \ + CUR.GS.freeVector.x = A; \ + CUR.GS.projVector.x = A; \ + CUR.GS.dualVector.x = A; \ + \ + CUR.GS.freeVector.y = B; \ + CUR.GS.projVector.y = B; \ + CUR.GS.dualVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SPVTCA \ + { \ + FT_Short A, B; \ + \ + \ + A = (FT_Short)( CUR.opcode & 1 ) << 14; \ + B = A ^ (FT_Short)0x4000; \ + \ + CUR.GS.projVector.x = A; \ + CUR.GS.dualVector.x = A; \ + \ + CUR.GS.projVector.y = B; \ + CUR.GS.dualVector.y = B; \ + \ + GUESS_VECTOR( freeVector ); \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTCA \ + { \ + FT_Short A, B; \ + \ + \ + A = (FT_Short)( CUR.opcode & 1 ) << 14; \ + B = A ^ (FT_Short)0x4000; \ + \ + CUR.GS.freeVector.x = A; \ + CUR.GS.freeVector.y = B; \ + \ + GUESS_VECTOR( projVector ); \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SPVTL \ + if ( INS_SxVTL( (FT_UShort)args[1], \ + (FT_UShort)args[0], \ + CUR.opcode, \ + &CUR.GS.projVector ) == SUCCESS ) \ + { \ + CUR.GS.dualVector = CUR.GS.projVector; \ + GUESS_VECTOR( freeVector ); \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTL \ + if ( INS_SxVTL( (FT_UShort)args[1], \ + (FT_UShort)args[0], \ + CUR.opcode, \ + &CUR.GS.freeVector ) == SUCCESS ) \ + { \ + GUESS_VECTOR( projVector ); \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTPV \ + GUESS_VECTOR( projVector ); \ + CUR.GS.freeVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); + + +#define DO_SPVFS \ + { \ + FT_Short S; \ + FT_Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (FT_Short)args[1]; \ + Y = (FT_Long)S; \ + S = (FT_Short)args[0]; \ + X = (FT_Long)S; \ + \ + NORMalize( X, Y, &CUR.GS.projVector ); \ + \ + CUR.GS.dualVector = CUR.GS.projVector; \ + GUESS_VECTOR( freeVector ); \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVFS \ + { \ + FT_Short S; \ + FT_Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (FT_Short)args[1]; \ + Y = (FT_Long)S; \ + S = (FT_Short)args[0]; \ + X = S; \ + \ + NORMalize( X, Y, &CUR.GS.freeVector ); \ + GUESS_VECTOR( projVector ); \ + COMPUTE_Funcs(); \ + } + + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING +#define DO_GPV \ + if ( CUR.face->unpatented_hinting ) \ + { \ + args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \ + args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \ + } \ + else \ + { \ + args[0] = CUR.GS.projVector.x; \ + args[1] = CUR.GS.projVector.y; \ + } +#else +#define DO_GPV \ + args[0] = CUR.GS.projVector.x; \ + args[1] = CUR.GS.projVector.y; +#endif + + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING +#define DO_GFV \ + if ( CUR.face->unpatented_hinting ) \ + { \ + args[0] = CUR.GS.both_x_axis ? 0x4000 : 0; \ + args[1] = CUR.GS.both_x_axis ? 0 : 0x4000; \ + } \ + else \ + { \ + args[0] = CUR.GS.freeVector.x; \ + args[1] = CUR.GS.freeVector.y; \ + } +#else +#define DO_GFV \ + args[0] = CUR.GS.freeVector.x; \ + args[1] = CUR.GS.freeVector.y; +#endif + + +#define DO_SRP0 \ + CUR.GS.rp0 = (FT_UShort)args[0]; + + +#define DO_SRP1 \ + CUR.GS.rp1 = (FT_UShort)args[0]; + + +#define DO_SRP2 \ + CUR.GS.rp2 = (FT_UShort)args[0]; + + +#define DO_RTHG \ + CUR.GS.round_state = TT_Round_To_Half_Grid; \ + CUR.func_round = (TT_Round_Func)Round_To_Half_Grid; + + +#define DO_RTG \ + CUR.GS.round_state = TT_Round_To_Grid; \ + CUR.func_round = (TT_Round_Func)Round_To_Grid; + + +#define DO_RTDG \ + CUR.GS.round_state = TT_Round_To_Double_Grid; \ + CUR.func_round = (TT_Round_Func)Round_To_Double_Grid; + + +#define DO_RUTG \ + CUR.GS.round_state = TT_Round_Up_To_Grid; \ + CUR.func_round = (TT_Round_Func)Round_Up_To_Grid; + + +#define DO_RDTG \ + CUR.GS.round_state = TT_Round_Down_To_Grid; \ + CUR.func_round = (TT_Round_Func)Round_Down_To_Grid; + + +#define DO_ROFF \ + CUR.GS.round_state = TT_Round_Off; \ + CUR.func_round = (TT_Round_Func)Round_None; + + +#define DO_SROUND \ + SET_SuperRound( 0x4000, args[0] ); \ + CUR.GS.round_state = TT_Round_Super; \ + CUR.func_round = (TT_Round_Func)Round_Super; + + +#define DO_S45ROUND \ + SET_SuperRound( 0x2D41, args[0] ); \ + CUR.GS.round_state = TT_Round_Super_45; \ + CUR.func_round = (TT_Round_Func)Round_Super_45; + + +#define DO_SLOOP \ + if ( args[0] < 0 ) \ + CUR.error = TT_Err_Bad_Argument; \ + else \ + CUR.GS.loop = args[0]; + + +#define DO_SMD \ + CUR.GS.minimum_distance = args[0]; + + +#define DO_SCVTCI \ + CUR.GS.control_value_cutin = (FT_F26Dot6)args[0]; + + +#define DO_SSWCI \ + CUR.GS.single_width_cutin = (FT_F26Dot6)args[0]; + + + /* XXX: UNDOCUMENTED! or bug in the Windows engine? */ + /* */ + /* It seems that the value that is read here is */ + /* expressed in 16.16 format rather than in font */ + /* units. */ + /* */ +#define DO_SSW \ + CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 ); + + +#define DO_FLIPON \ + CUR.GS.auto_flip = TRUE; + + +#define DO_FLIPOFF \ + CUR.GS.auto_flip = FALSE; + + +#define DO_SDB \ + CUR.GS.delta_base = (FT_Short)args[0]; + + +#define DO_SDS \ + CUR.GS.delta_shift = (FT_Short)args[0]; + + +#define DO_MD /* nothing */ + + +#define DO_MPPEM \ + args[0] = CURRENT_Ppem(); + + + /* Note: The pointSize should be irrelevant in a given font program; */ + /* we thus decide to return only the ppem. */ +#if 0 + +#define DO_MPS \ + args[0] = CUR.metrics.pointSize; + +#else + +#define DO_MPS \ + args[0] = CURRENT_Ppem(); + +#endif /* 0 */ + + +#define DO_DUP \ + args[1] = args[0]; + + +#define DO_CLEAR \ + CUR.new_top = 0; + + +#define DO_SWAP \ + { \ + FT_Long L; \ + \ + \ + L = args[0]; \ + args[0] = args[1]; \ + args[1] = L; \ + } + + +#define DO_DEPTH \ + args[0] = CUR.top; + + +#define DO_CINDEX \ + { \ + FT_Long L; \ + \ + \ + L = args[0]; \ + \ + if ( L <= 0 || L > CUR.args ) \ + CUR.error = TT_Err_Invalid_Reference; \ + else \ + args[0] = CUR.stack[CUR.args - L]; \ + } + + +#define DO_JROT \ + if ( args[1] != 0 ) \ + { \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; \ + } + + +#define DO_JMPR \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; + + +#define DO_JROF \ + if ( args[1] == 0 ) \ + { \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; \ + } + + +#define DO_LT \ + args[0] = ( args[0] < args[1] ); + + +#define DO_LTEQ \ + args[0] = ( args[0] <= args[1] ); + + +#define DO_GT \ + args[0] = ( args[0] > args[1] ); + + +#define DO_GTEQ \ + args[0] = ( args[0] >= args[1] ); + + +#define DO_EQ \ + args[0] = ( args[0] == args[1] ); + + +#define DO_NEQ \ + args[0] = ( args[0] != args[1] ); + + +#define DO_ODD \ + args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 ); + + +#define DO_EVEN \ + args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 ); + + +#define DO_AND \ + args[0] = ( args[0] && args[1] ); + + +#define DO_OR \ + args[0] = ( args[0] || args[1] ); + + +#define DO_NOT \ + args[0] = !args[0]; + + +#define DO_ADD \ + args[0] += args[1]; + + +#define DO_SUB \ + args[0] -= args[1]; + + +#define DO_DIV \ + if ( args[1] == 0 ) \ + CUR.error = TT_Err_Divide_By_Zero; \ + else \ + args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] ); + + +#define DO_MUL \ + args[0] = TT_MULDIV( args[0], args[1], 64L ); + + +#define DO_ABS \ + args[0] = FT_ABS( args[0] ); + + +#define DO_NEG \ + args[0] = -args[0]; + + +#define DO_FLOOR \ + args[0] = FT_PIX_FLOOR( args[0] ); + + +#define DO_CEILING \ + args[0] = FT_PIX_CEIL( args[0] ); + + +#define DO_RS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + else \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR.storage[I]; \ + } + + +#define DO_WS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.storage[I] = args[1]; \ + } + + +#define DO_RCVT \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + else \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR_Func_read_cvt( I ); \ + } + + +#define DO_WCVTP \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR_Func_write_cvt( I, args[1] ); \ + } + + +#define DO_WCVTF \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \ + } + + +#define DO_DEBUG \ + CUR.error = TT_Err_Debug_OpCode; + + +#define DO_ROUND \ + args[0] = CUR_Func_round( \ + args[0], \ + CUR.tt_metrics.compensations[CUR.opcode - 0x68] ); + + +#define DO_NROUND \ + args[0] = ROUND_None( args[0], \ + CUR.tt_metrics.compensations[CUR.opcode - 0x6C] ); + + +#define DO_MAX \ + if ( args[1] > args[0] ) \ + args[0] = args[1]; + + +#define DO_MIN \ + if ( args[1] < args[0] ) \ + args[0] = args[1]; + + +#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +#undef ARRAY_BOUND_ERROR +#define ARRAY_BOUND_ERROR \ + { \ + CUR.error = TT_Err_Invalid_Reference; \ + return; \ + } + + + /*************************************************************************/ + /* */ + /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */ + /* Opcode range: 0x00-0x01 */ + /* Stack: --> */ + /* */ + static void + Ins_SVTCA( INS_ARG ) + { + DO_SVTCA + } + + + /*************************************************************************/ + /* */ + /* SPVTCA[a]: Set PVector to Coordinate Axis */ + /* Opcode range: 0x02-0x03 */ + /* Stack: --> */ + /* */ + static void + Ins_SPVTCA( INS_ARG ) + { + DO_SPVTCA + } + + + /*************************************************************************/ + /* */ + /* SFVTCA[a]: Set FVector to Coordinate Axis */ + /* Opcode range: 0x04-0x05 */ + /* Stack: --> */ + /* */ + static void + Ins_SFVTCA( INS_ARG ) + { + DO_SFVTCA + } + + + /*************************************************************************/ + /* */ + /* SPVTL[a]: Set PVector To Line */ + /* Opcode range: 0x06-0x07 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_SPVTL( INS_ARG ) + { + DO_SPVTL + } + + + /*************************************************************************/ + /* */ + /* SFVTL[a]: Set FVector To Line */ + /* Opcode range: 0x08-0x09 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_SFVTL( INS_ARG ) + { + DO_SFVTL + } + + + /*************************************************************************/ + /* */ + /* SFVTPV[]: Set FVector To PVector */ + /* Opcode range: 0x0E */ + /* Stack: --> */ + /* */ + static void + Ins_SFVTPV( INS_ARG ) + { + DO_SFVTPV + } + + + /*************************************************************************/ + /* */ + /* SPVFS[]: Set PVector From Stack */ + /* Opcode range: 0x0A */ + /* Stack: f2.14 f2.14 --> */ + /* */ + static void + Ins_SPVFS( INS_ARG ) + { + DO_SPVFS + } + + + /*************************************************************************/ + /* */ + /* SFVFS[]: Set FVector From Stack */ + /* Opcode range: 0x0B */ + /* Stack: f2.14 f2.14 --> */ + /* */ + static void + Ins_SFVFS( INS_ARG ) + { + DO_SFVFS + } + + + /*************************************************************************/ + /* */ + /* GPV[]: Get Projection Vector */ + /* Opcode range: 0x0C */ + /* Stack: ef2.14 --> ef2.14 */ + /* */ + static void + Ins_GPV( INS_ARG ) + { + DO_GPV + } + + + /*************************************************************************/ + /* GFV[]: Get Freedom Vector */ + /* Opcode range: 0x0D */ + /* Stack: ef2.14 --> ef2.14 */ + /* */ + static void + Ins_GFV( INS_ARG ) + { + DO_GFV + } + + + /*************************************************************************/ + /* */ + /* SRP0[]: Set Reference Point 0 */ + /* Opcode range: 0x10 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SRP0( INS_ARG ) + { + DO_SRP0 + } + + + /*************************************************************************/ + /* */ + /* SRP1[]: Set Reference Point 1 */ + /* Opcode range: 0x11 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SRP1( INS_ARG ) + { + DO_SRP1 + } + + + /*************************************************************************/ + /* */ + /* SRP2[]: Set Reference Point 2 */ + /* Opcode range: 0x12 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SRP2( INS_ARG ) + { + DO_SRP2 + } + + + /*************************************************************************/ + /* */ + /* RTHG[]: Round To Half Grid */ + /* Opcode range: 0x19 */ + /* Stack: --> */ + /* */ + static void + Ins_RTHG( INS_ARG ) + { + DO_RTHG + } + + + /*************************************************************************/ + /* */ + /* RTG[]: Round To Grid */ + /* Opcode range: 0x18 */ + /* Stack: --> */ + /* */ + static void + Ins_RTG( INS_ARG ) + { + DO_RTG + } + + + /*************************************************************************/ + /* RTDG[]: Round To Double Grid */ + /* Opcode range: 0x3D */ + /* Stack: --> */ + /* */ + static void + Ins_RTDG( INS_ARG ) + { + DO_RTDG + } + + + /*************************************************************************/ + /* RUTG[]: Round Up To Grid */ + /* Opcode range: 0x7C */ + /* Stack: --> */ + /* */ + static void + Ins_RUTG( INS_ARG ) + { + DO_RUTG + } + + + /*************************************************************************/ + /* */ + /* RDTG[]: Round Down To Grid */ + /* Opcode range: 0x7D */ + /* Stack: --> */ + /* */ + static void + Ins_RDTG( INS_ARG ) + { + DO_RDTG + } + + + /*************************************************************************/ + /* */ + /* ROFF[]: Round OFF */ + /* Opcode range: 0x7A */ + /* Stack: --> */ + /* */ + static void + Ins_ROFF( INS_ARG ) + { + DO_ROFF + } + + + /*************************************************************************/ + /* */ + /* SROUND[]: Super ROUND */ + /* Opcode range: 0x76 */ + /* Stack: Eint8 --> */ + /* */ + static void + Ins_SROUND( INS_ARG ) + { + DO_SROUND + } + + + /*************************************************************************/ + /* */ + /* S45ROUND[]: Super ROUND 45 degrees */ + /* Opcode range: 0x77 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_S45ROUND( INS_ARG ) + { + DO_S45ROUND + } + + + /*************************************************************************/ + /* */ + /* SLOOP[]: Set LOOP variable */ + /* Opcode range: 0x17 */ + /* Stack: int32? --> */ + /* */ + static void + Ins_SLOOP( INS_ARG ) + { + DO_SLOOP + } + + + /*************************************************************************/ + /* */ + /* SMD[]: Set Minimum Distance */ + /* Opcode range: 0x1A */ + /* Stack: f26.6 --> */ + /* */ + static void + Ins_SMD( INS_ARG ) + { + DO_SMD + } + + + /*************************************************************************/ + /* */ + /* SCVTCI[]: Set Control Value Table Cut In */ + /* Opcode range: 0x1D */ + /* Stack: f26.6 --> */ + /* */ + static void + Ins_SCVTCI( INS_ARG ) + { + DO_SCVTCI + } + + + /*************************************************************************/ + /* */ + /* SSWCI[]: Set Single Width Cut In */ + /* Opcode range: 0x1E */ + /* Stack: f26.6 --> */ + /* */ + static void + Ins_SSWCI( INS_ARG ) + { + DO_SSWCI + } + + + /*************************************************************************/ + /* */ + /* SSW[]: Set Single Width */ + /* Opcode range: 0x1F */ + /* Stack: int32? --> */ + /* */ + static void + Ins_SSW( INS_ARG ) + { + DO_SSW + } + + + /*************************************************************************/ + /* */ + /* FLIPON[]: Set auto-FLIP to ON */ + /* Opcode range: 0x4D */ + /* Stack: --> */ + /* */ + static void + Ins_FLIPON( INS_ARG ) + { + DO_FLIPON + } + + + /*************************************************************************/ + /* */ + /* FLIPOFF[]: Set auto-FLIP to OFF */ + /* Opcode range: 0x4E */ + /* Stack: --> */ + /* */ + static void + Ins_FLIPOFF( INS_ARG ) + { + DO_FLIPOFF + } + + + /*************************************************************************/ + /* */ + /* SANGW[]: Set ANGle Weight */ + /* Opcode range: 0x7E */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SANGW( INS_ARG ) + { + /* instruction not supported anymore */ + } + + + /*************************************************************************/ + /* */ + /* SDB[]: Set Delta Base */ + /* Opcode range: 0x5E */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SDB( INS_ARG ) + { + DO_SDB + } + + + /*************************************************************************/ + /* */ + /* SDS[]: Set Delta Shift */ + /* Opcode range: 0x5F */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SDS( INS_ARG ) + { + DO_SDS + } + + + /*************************************************************************/ + /* */ + /* MPPEM[]: Measure Pixel Per EM */ + /* Opcode range: 0x4B */ + /* Stack: --> Euint16 */ + /* */ + static void + Ins_MPPEM( INS_ARG ) + { + DO_MPPEM + } + + + /*************************************************************************/ + /* */ + /* MPS[]: Measure Point Size */ + /* Opcode range: 0x4C */ + /* Stack: --> Euint16 */ + /* */ + static void + Ins_MPS( INS_ARG ) + { + DO_MPS + } + + + /*************************************************************************/ + /* */ + /* DUP[]: DUPlicate the top stack's element */ + /* Opcode range: 0x20 */ + /* Stack: StkElt --> StkElt StkElt */ + /* */ + static void + Ins_DUP( INS_ARG ) + { + DO_DUP + } + + + /*************************************************************************/ + /* */ + /* POP[]: POP the stack's top element */ + /* Opcode range: 0x21 */ + /* Stack: StkElt --> */ + /* */ + static void + Ins_POP( INS_ARG ) + { + /* nothing to do */ + } + + + /*************************************************************************/ + /* */ + /* CLEAR[]: CLEAR the entire stack */ + /* Opcode range: 0x22 */ + /* Stack: StkElt... --> */ + /* */ + static void + Ins_CLEAR( INS_ARG ) + { + DO_CLEAR + } + + + /*************************************************************************/ + /* */ + /* SWAP[]: SWAP the stack's top two elements */ + /* Opcode range: 0x23 */ + /* Stack: 2 * StkElt --> 2 * StkElt */ + /* */ + static void + Ins_SWAP( INS_ARG ) + { + DO_SWAP + } + + + /*************************************************************************/ + /* */ + /* DEPTH[]: return the stack DEPTH */ + /* Opcode range: 0x24 */ + /* Stack: --> uint32 */ + /* */ + static void + Ins_DEPTH( INS_ARG ) + { + DO_DEPTH + } + + + /*************************************************************************/ + /* */ + /* CINDEX[]: Copy INDEXed element */ + /* Opcode range: 0x25 */ + /* Stack: int32 --> StkElt */ + /* */ + static void + Ins_CINDEX( INS_ARG ) + { + DO_CINDEX + } + + + /*************************************************************************/ + /* */ + /* EIF[]: End IF */ + /* Opcode range: 0x59 */ + /* Stack: --> */ + /* */ + static void + Ins_EIF( INS_ARG ) + { + /* nothing to do */ + } + + + /*************************************************************************/ + /* */ + /* JROT[]: Jump Relative On True */ + /* Opcode range: 0x78 */ + /* Stack: StkElt int32 --> */ + /* */ + static void + Ins_JROT( INS_ARG ) + { + DO_JROT + } + + + /*************************************************************************/ + /* */ + /* JMPR[]: JuMP Relative */ + /* Opcode range: 0x1C */ + /* Stack: int32 --> */ + /* */ + static void + Ins_JMPR( INS_ARG ) + { + DO_JMPR + } + + + /*************************************************************************/ + /* */ + /* JROF[]: Jump Relative On False */ + /* Opcode range: 0x79 */ + /* Stack: StkElt int32 --> */ + /* */ + static void + Ins_JROF( INS_ARG ) + { + DO_JROF + } + + + /*************************************************************************/ + /* */ + /* LT[]: Less Than */ + /* Opcode range: 0x50 */ + /* Stack: int32? int32? --> bool */ + /* */ + static void + Ins_LT( INS_ARG ) + { + DO_LT + } + + + /*************************************************************************/ + /* */ + /* LTEQ[]: Less Than or EQual */ + /* Opcode range: 0x51 */ + /* Stack: int32? int32? --> bool */ + /* */ + static void + Ins_LTEQ( INS_ARG ) + { + DO_LTEQ + } + + + /*************************************************************************/ + /* */ + /* GT[]: Greater Than */ + /* Opcode range: 0x52 */ + /* Stack: int32? int32? --> bool */ + /* */ + static void + Ins_GT( INS_ARG ) + { + DO_GT + } + + + /*************************************************************************/ + /* */ + /* GTEQ[]: Greater Than or EQual */ + /* Opcode range: 0x53 */ + /* Stack: int32? int32? --> bool */ + /* */ + static void + Ins_GTEQ( INS_ARG ) + { + DO_GTEQ + } + + + /*************************************************************************/ + /* */ + /* EQ[]: EQual */ + /* Opcode range: 0x54 */ + /* Stack: StkElt StkElt --> bool */ + /* */ + static void + Ins_EQ( INS_ARG ) + { + DO_EQ + } + + + /*************************************************************************/ + /* */ + /* NEQ[]: Not EQual */ + /* Opcode range: 0x55 */ + /* Stack: StkElt StkElt --> bool */ + /* */ + static void + Ins_NEQ( INS_ARG ) + { + DO_NEQ + } + + + /*************************************************************************/ + /* */ + /* ODD[]: Is ODD */ + /* Opcode range: 0x56 */ + /* Stack: f26.6 --> bool */ + /* */ + static void + Ins_ODD( INS_ARG ) + { + DO_ODD + } + + + /*************************************************************************/ + /* */ + /* EVEN[]: Is EVEN */ + /* Opcode range: 0x57 */ + /* Stack: f26.6 --> bool */ + /* */ + static void + Ins_EVEN( INS_ARG ) + { + DO_EVEN + } + + + /*************************************************************************/ + /* */ + /* AND[]: logical AND */ + /* Opcode range: 0x5A */ + /* Stack: uint32 uint32 --> uint32 */ + /* */ + static void + Ins_AND( INS_ARG ) + { + DO_AND + } + + + /*************************************************************************/ + /* */ + /* OR[]: logical OR */ + /* Opcode range: 0x5B */ + /* Stack: uint32 uint32 --> uint32 */ + /* */ + static void + Ins_OR( INS_ARG ) + { + DO_OR + } + + + /*************************************************************************/ + /* */ + /* NOT[]: logical NOT */ + /* Opcode range: 0x5C */ + /* Stack: StkElt --> uint32 */ + /* */ + static void + Ins_NOT( INS_ARG ) + { + DO_NOT + } + + + /*************************************************************************/ + /* */ + /* ADD[]: ADD */ + /* Opcode range: 0x60 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static void + Ins_ADD( INS_ARG ) + { + DO_ADD + } + + + /*************************************************************************/ + /* */ + /* SUB[]: SUBtract */ + /* Opcode range: 0x61 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static void + Ins_SUB( INS_ARG ) + { + DO_SUB + } + + + /*************************************************************************/ + /* */ + /* DIV[]: DIVide */ + /* Opcode range: 0x62 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static void + Ins_DIV( INS_ARG ) + { + DO_DIV + } + + + /*************************************************************************/ + /* */ + /* MUL[]: MULtiply */ + /* Opcode range: 0x63 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static void + Ins_MUL( INS_ARG ) + { + DO_MUL + } + + + /*************************************************************************/ + /* */ + /* ABS[]: ABSolute value */ + /* Opcode range: 0x64 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static void + Ins_ABS( INS_ARG ) + { + DO_ABS + } + + + /*************************************************************************/ + /* */ + /* NEG[]: NEGate */ + /* Opcode range: 0x65 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static void + Ins_NEG( INS_ARG ) + { + DO_NEG + } + + + /*************************************************************************/ + /* */ + /* FLOOR[]: FLOOR */ + /* Opcode range: 0x66 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static void + Ins_FLOOR( INS_ARG ) + { + DO_FLOOR + } + + + /*************************************************************************/ + /* */ + /* CEILING[]: CEILING */ + /* Opcode range: 0x67 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static void + Ins_CEILING( INS_ARG ) + { + DO_CEILING + } + + + /*************************************************************************/ + /* */ + /* RS[]: Read Store */ + /* Opcode range: 0x43 */ + /* Stack: uint32 --> uint32 */ + /* */ + static void + Ins_RS( INS_ARG ) + { + DO_RS + } + + + /*************************************************************************/ + /* */ + /* WS[]: Write Store */ + /* Opcode range: 0x42 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_WS( INS_ARG ) + { + DO_WS + } + + + /*************************************************************************/ + /* */ + /* WCVTP[]: Write CVT in Pixel units */ + /* Opcode range: 0x44 */ + /* Stack: f26.6 uint32 --> */ + /* */ + static void + Ins_WCVTP( INS_ARG ) + { + DO_WCVTP + } + + + /*************************************************************************/ + /* */ + /* WCVTF[]: Write CVT in Funits */ + /* Opcode range: 0x70 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_WCVTF( INS_ARG ) + { + DO_WCVTF + } + + + /*************************************************************************/ + /* */ + /* RCVT[]: Read CVT */ + /* Opcode range: 0x45 */ + /* Stack: uint32 --> f26.6 */ + /* */ + static void + Ins_RCVT( INS_ARG ) + { + DO_RCVT + } + + + /*************************************************************************/ + /* */ + /* AA[]: Adjust Angle */ + /* Opcode range: 0x7F */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_AA( INS_ARG ) + { + /* intentionally no longer supported */ + } + + + /*************************************************************************/ + /* */ + /* DEBUG[]: DEBUG. Unsupported. */ + /* Opcode range: 0x4F */ + /* Stack: uint32 --> */ + /* */ + /* Note: The original instruction pops a value from the stack. */ + /* */ + static void + Ins_DEBUG( INS_ARG ) + { + DO_DEBUG + } + + + /*************************************************************************/ + /* */ + /* ROUND[ab]: ROUND value */ + /* Opcode range: 0x68-0x6B */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static void + Ins_ROUND( INS_ARG ) + { + DO_ROUND + } + + + /*************************************************************************/ + /* */ + /* NROUND[ab]: No ROUNDing of value */ + /* Opcode range: 0x6C-0x6F */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static void + Ins_NROUND( INS_ARG ) + { + DO_NROUND + } + + + /*************************************************************************/ + /* */ + /* MAX[]: MAXimum */ + /* Opcode range: 0x68 */ + /* Stack: int32? int32? --> int32 */ + /* */ + static void + Ins_MAX( INS_ARG ) + { + DO_MAX + } + + + /*************************************************************************/ + /* */ + /* MIN[]: MINimum */ + /* Opcode range: 0x69 */ + /* Stack: int32? int32? --> int32 */ + /* */ + static void + Ins_MIN( INS_ARG ) + { + DO_MIN + } + + +#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */ + + + /*************************************************************************/ + /* */ + /* The following functions are called as is within the switch statement. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* MINDEX[]: Move INDEXed element */ + /* Opcode range: 0x26 */ + /* Stack: int32? --> StkElt */ + /* */ + static void + Ins_MINDEX( INS_ARG ) + { + FT_Long L, K; + + + L = args[0]; + + if ( L <= 0 || L > CUR.args ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + K = CUR.stack[CUR.args - L]; + + FT_ARRAY_MOVE( &CUR.stack[CUR.args - L ], + &CUR.stack[CUR.args - L + 1], + ( L - 1 ) ); + + CUR.stack[CUR.args - 1] = K; + } + + + /*************************************************************************/ + /* */ + /* ROLL[]: ROLL top three elements */ + /* Opcode range: 0x8A */ + /* Stack: 3 * StkElt --> 3 * StkElt */ + /* */ + static void + Ins_ROLL( INS_ARG ) + { + FT_Long A, B, C; + + FT_UNUSED_EXEC; + + + A = args[2]; + B = args[1]; + C = args[0]; + + args[2] = C; + args[1] = A; + args[0] = B; + } + + + /*************************************************************************/ + /* */ + /* MANAGING THE FLOW OF CONTROL */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + static FT_Bool + SkipCode( EXEC_OP ) + { + CUR.IP += CUR.length; + + if ( CUR.IP < CUR.codeSize ) + { + CUR.opcode = CUR.code[CUR.IP]; + + CUR.length = opcode_length[CUR.opcode]; + if ( CUR.length < 0 ) + { + if ( CUR.IP + 1 > CUR.codeSize ) + goto Fail_Overflow; + CUR.length = CUR.code[CUR.IP + 1] + 2; + } + + if ( CUR.IP + CUR.length <= CUR.codeSize ) + return SUCCESS; + } + + Fail_Overflow: + CUR.error = TT_Err_Code_Overflow; + return FAILURE; + } + + + /*************************************************************************/ + /* */ + /* IF[]: IF test */ + /* Opcode range: 0x58 */ + /* Stack: StkElt --> */ + /* */ + static void + Ins_IF( INS_ARG ) + { + FT_Int nIfs; + FT_Bool Out; + + + if ( args[0] != 0 ) + return; + + nIfs = 1; + Out = 0; + + do + { + if ( SKIP_Code() == FAILURE ) + return; + + switch ( CUR.opcode ) + { + case 0x58: /* IF */ + nIfs++; + break; + + case 0x1B: /* ELSE */ + Out = FT_BOOL( nIfs == 1 ); + break; + + case 0x59: /* EIF */ + nIfs--; + Out = FT_BOOL( nIfs == 0 ); + break; + } + } while ( Out == 0 ); + } + + + /*************************************************************************/ + /* */ + /* ELSE[]: ELSE */ + /* Opcode range: 0x1B */ + /* Stack: --> */ + /* */ + static void + Ins_ELSE( INS_ARG ) + { + FT_Int nIfs; + + FT_UNUSED_ARG; + + + nIfs = 1; + + do + { + if ( SKIP_Code() == FAILURE ) + return; + + switch ( CUR.opcode ) + { + case 0x58: /* IF */ + nIfs++; + break; + + case 0x59: /* EIF */ + nIfs--; + break; + } + } while ( nIfs != 0 ); + } + + + /*************************************************************************/ + /* */ + /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* FDEF[]: Function DEFinition */ + /* Opcode range: 0x2C */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_FDEF( INS_ARG ) + { + FT_ULong n; + TT_DefRecord* rec; + TT_DefRecord* limit; + + + /* some font programs are broken enough to redefine functions! */ + /* We will then parse the current table. */ + + rec = CUR.FDefs; + limit = rec + CUR.numFDefs; + n = args[0]; + + for ( ; rec < limit; rec++ ) + { + if ( rec->opc == n ) + break; + } + + if ( rec == limit ) + { + /* check that there is enough room for new functions */ + if ( CUR.numFDefs >= CUR.maxFDefs ) + { + CUR.error = TT_Err_Too_Many_Function_Defs; + return; + } + CUR.numFDefs++; + } + + rec->range = CUR.curRange; + rec->opc = n; + rec->start = CUR.IP + 1; + rec->active = TRUE; + + if ( n > CUR.maxFunc ) + CUR.maxFunc = n; + + /* Now skip the whole function definition. */ + /* We don't allow nested IDEFS & FDEFs. */ + + while ( SKIP_Code() == SUCCESS ) + { + switch ( CUR.opcode ) + { + case 0x89: /* IDEF */ + case 0x2C: /* FDEF */ + CUR.error = TT_Err_Nested_DEFS; + return; + + case 0x2D: /* ENDF */ + return; + } + } + } + + + /*************************************************************************/ + /* */ + /* ENDF[]: END Function definition */ + /* Opcode range: 0x2D */ + /* Stack: --> */ + /* */ + static void + Ins_ENDF( INS_ARG ) + { + TT_CallRec* pRec; + + FT_UNUSED_ARG; + + + if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */ + { + CUR.error = TT_Err_ENDF_In_Exec_Stream; + return; + } + + CUR.callTop--; + + pRec = &CUR.callStack[CUR.callTop]; + + pRec->Cur_Count--; + + CUR.step_ins = FALSE; + + if ( pRec->Cur_Count > 0 ) + { + CUR.callTop++; + CUR.IP = pRec->Cur_Restart; + } + else + /* Loop through the current function */ + INS_Goto_CodeRange( pRec->Caller_Range, + pRec->Caller_IP ); + + /* Exit the current call frame. */ + + /* NOTE: If the last intruction of a program is a */ + /* CALL or LOOPCALL, the return address is */ + /* always out of the code range. This is a */ + /* valid address, and it is why we do not test */ + /* the result of Ins_Goto_CodeRange() here! */ + } + + + /*************************************************************************/ + /* */ + /* CALL[]: CALL function */ + /* Opcode range: 0x2B */ + /* Stack: uint32? --> */ + /* */ + static void + Ins_CALL( INS_ARG ) + { + FT_ULong F; + TT_CallRec* pCrec; + TT_DefRecord* def; + + + /* first of all, check the index */ + + F = args[0]; + if ( BOUNDS( F, CUR.maxFunc + 1 ) ) + goto Fail; + + /* Except for some old Apple fonts, all functions in a TrueType */ + /* font are defined in increasing order, starting from 0. This */ + /* means that we normally have */ + /* */ + /* CUR.maxFunc+1 == CUR.numFDefs */ + /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */ + /* */ + /* If this isn't true, we need to look up the function table. */ + + def = CUR.FDefs + F; + if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F ) + { + /* look up the FDefs table */ + TT_DefRecord* limit; + + + def = CUR.FDefs; + limit = def + CUR.numFDefs; + + while ( def < limit && def->opc != F ) + def++; + + if ( def == limit ) + goto Fail; + } + + /* check that the function is active */ + if ( !def->active ) + goto Fail; + + /* check the call stack */ + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + pCrec = CUR.callStack + CUR.callTop; + + pCrec->Caller_Range = CUR.curRange; + pCrec->Caller_IP = CUR.IP + 1; + pCrec->Cur_Count = 1; + pCrec->Cur_Restart = def->start; + + CUR.callTop++; + + INS_Goto_CodeRange( def->range, + def->start ); + + CUR.step_ins = FALSE; + return; + + Fail: + CUR.error = TT_Err_Invalid_Reference; + } + + + /*************************************************************************/ + /* */ + /* LOOPCALL[]: LOOP and CALL function */ + /* Opcode range: 0x2A */ + /* Stack: uint32? Eint16? --> */ + /* */ + static void + Ins_LOOPCALL( INS_ARG ) + { + FT_ULong F; + TT_CallRec* pCrec; + TT_DefRecord* def; + + + /* first of all, check the index */ + F = args[1]; + if ( BOUNDS( F, CUR.maxFunc + 1 ) ) + goto Fail; + + /* Except for some old Apple fonts, all functions in a TrueType */ + /* font are defined in increasing order, starting from 0. This */ + /* means that we normally have */ + /* */ + /* CUR.maxFunc+1 == CUR.numFDefs */ + /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */ + /* */ + /* If this isn't true, we need to look up the function table. */ + + def = CUR.FDefs + F; + if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F ) + { + /* look up the FDefs table */ + TT_DefRecord* limit; + + + def = CUR.FDefs; + limit = def + CUR.numFDefs; + + while ( def < limit && def->opc != F ) + def++; + + if ( def == limit ) + goto Fail; + } + + /* check that the function is active */ + if ( !def->active ) + goto Fail; + + /* check stack */ + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + if ( args[0] > 0 ) + { + pCrec = CUR.callStack + CUR.callTop; + + pCrec->Caller_Range = CUR.curRange; + pCrec->Caller_IP = CUR.IP + 1; + pCrec->Cur_Count = (FT_Int)args[0]; + pCrec->Cur_Restart = def->start; + + CUR.callTop++; + + INS_Goto_CodeRange( def->range, def->start ); + + CUR.step_ins = FALSE; + } + return; + + Fail: + CUR.error = TT_Err_Invalid_Reference; + } + + + /*************************************************************************/ + /* */ + /* IDEF[]: Instruction DEFinition */ + /* Opcode range: 0x89 */ + /* Stack: Eint8 --> */ + /* */ + static void + Ins_IDEF( INS_ARG ) + { + TT_DefRecord* def; + TT_DefRecord* limit; + + + /* First of all, look for the same function in our table */ + + def = CUR.IDefs; + limit = def + CUR.numIDefs; + + for ( ; def < limit; def++ ) + if ( def->opc == (FT_ULong)args[0] ) + break; + + if ( def == limit ) + { + /* check that there is enough room for a new instruction */ + if ( CUR.numIDefs >= CUR.maxIDefs ) + { + CUR.error = TT_Err_Too_Many_Instruction_Defs; + return; + } + CUR.numIDefs++; + } + + def->opc = args[0]; + def->start = CUR.IP+1; + def->range = CUR.curRange; + def->active = TRUE; + + if ( (FT_ULong)args[0] > CUR.maxIns ) + CUR.maxIns = args[0]; + + /* Now skip the whole function definition. */ + /* We don't allow nested IDEFs & FDEFs. */ + + while ( SKIP_Code() == SUCCESS ) + { + switch ( CUR.opcode ) + { + case 0x89: /* IDEF */ + case 0x2C: /* FDEF */ + CUR.error = TT_Err_Nested_DEFS; + return; + case 0x2D: /* ENDF */ + return; + } + } + } + + + /*************************************************************************/ + /* */ + /* PUSHING DATA ONTO THE INTERPRETER STACK */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* NPUSHB[]: PUSH N Bytes */ + /* Opcode range: 0x40 */ + /* Stack: --> uint32... */ + /* */ + static void + Ins_NPUSHB( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)CUR.code[CUR.IP + 1]; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + for ( K = 1; K <= L; K++ ) + args[K - 1] = CUR.code[CUR.IP + K + 1]; + + CUR.new_top += L; + } + + + /*************************************************************************/ + /* */ + /* NPUSHW[]: PUSH N Words */ + /* Opcode range: 0x41 */ + /* Stack: --> int32... */ + /* */ + static void + Ins_NPUSHW( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)CUR.code[CUR.IP + 1]; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + CUR.IP += 2; + + for ( K = 0; K < L; K++ ) + args[K] = GET_ShortIns(); + + CUR.step_ins = FALSE; + CUR.new_top += L; + } + + + /*************************************************************************/ + /* */ + /* PUSHB[abc]: PUSH Bytes */ + /* Opcode range: 0xB0-0xB7 */ + /* Stack: --> uint32... */ + /* */ + static void + Ins_PUSHB( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)(CUR.opcode - 0xB0 + 1); + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + for ( K = 1; K <= L; K++ ) + args[K - 1] = CUR.code[CUR.IP + K]; + } + + + /*************************************************************************/ + /* */ + /* PUSHW[abc]: PUSH Words */ + /* Opcode range: 0xB8-0xBF */ + /* Stack: --> int32... */ + /* */ + static void + Ins_PUSHW( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)(CUR.opcode - 0xB8 + 1); + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + CUR.IP++; + + for ( K = 0; K < L; K++ ) + args[K] = GET_ShortIns(); + + CUR.step_ins = FALSE; + } + + + /*************************************************************************/ + /* */ + /* MANAGING THE GRAPHICS STATE */ + /* */ + /* Instructions appear in the specs' order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* GC[a]: Get Coordinate projected onto */ + /* Opcode range: 0x46-0x47 */ + /* Stack: uint32 --> f26.6 */ + /* */ + /* BULLSHIT: Measures from the original glyph must be taken along the */ + /* dual projection vector! */ + /* */ + static void + Ins_GC( INS_ARG ) + { + FT_ULong L; + FT_F26Dot6 R; + + + L = (FT_ULong)args[0]; + + if ( BOUNDS( L, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + else + R = 0; + } + else + { + if ( CUR.opcode & 1 ) + R = CUR_Func_dualproj( CUR.zp2.org + L, NULL_Vector ); + else + R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); + } + + args[0] = R; + } + + + /*************************************************************************/ + /* */ + /* SCFS[]: Set Coordinate From Stack */ + /* Opcode range: 0x48 */ + /* Stack: f26.6 uint32 --> */ + /* */ + /* Formula: */ + /* */ + /* OA := OA + ( value - OA.p )/( f.p ) * f */ + /* */ + static void + Ins_SCFS( INS_ARG ) + { + FT_Long K; + FT_UShort L; + + + L = (FT_UShort)args[0]; + + if ( BOUNDS( L, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); + + CUR_Func_move( &CUR.zp2, L, args[1] - K ); + + /* not part of the specs, but here for safety */ + + if ( CUR.GS.gep2 == 0 ) + CUR.zp2.org[L] = CUR.zp2.cur[L]; + } + + + /*************************************************************************/ + /* */ + /* MD[a]: Measure Distance */ + /* Opcode range: 0x49-0x4A */ + /* Stack: uint32 uint32 --> f26.6 */ + /* */ + /* BULLSHIT: Measure taken in the original glyph must be along the dual */ + /* projection vector. */ + /* */ + /* Second BULLSHIT: Flag attributes are inverted! */ + /* 0 => measure distance in original outline */ + /* 1 => measure distance in grid-fitted outline */ + /* */ + /* Third one: `zp0 - zp1', and not `zp2 - zp1! */ + /* */ + static void + Ins_MD( INS_ARG ) + { + FT_UShort K, L; + FT_F26Dot6 D; + + + K = (FT_UShort)args[1]; + L = (FT_UShort)args[0]; + + if( BOUNDS( L, CUR.zp0.n_points ) || + BOUNDS( K, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + D = 0; + } + else + { + if ( CUR.opcode & 1 ) + D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K ); + else + D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K ); + } + + args[0] = D; + } + + + /*************************************************************************/ + /* */ + /* SDPVTL[a]: Set Dual PVector to Line */ + /* Opcode range: 0x86-0x87 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_SDPVTL( INS_ARG ) + { + FT_Long A, B, C; + FT_UShort p1, p2; /* was FT_Int in pas type ERROR */ + + + p1 = (FT_UShort)args[1]; + p2 = (FT_UShort)args[0]; + + if ( BOUNDS( p2, CUR.zp1.n_points ) || + BOUNDS( p1, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + { + FT_Vector* v1 = CUR.zp1.org + p2; + FT_Vector* v2 = CUR.zp2.org + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( ( CUR.opcode & 1 ) != 0 ) + { + C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, &CUR.GS.dualVector ); + + { + FT_Vector* v1 = CUR.zp1.cur + p2; + FT_Vector* v2 = CUR.zp2.cur + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( ( CUR.opcode & 1 ) != 0 ) + { + C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, &CUR.GS.projVector ); + + GUESS_VECTOR( freeVector ); + + COMPUTE_Funcs(); + } + + + /*************************************************************************/ + /* */ + /* SZP0[]: Set Zone Pointer 0 */ + /* Opcode range: 0x13 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SZP0( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp0 = CUR.twilight; + break; + + case 1: + CUR.zp0 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep0 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* SZP1[]: Set Zone Pointer 1 */ + /* Opcode range: 0x14 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SZP1( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp1 = CUR.twilight; + break; + + case 1: + CUR.zp1 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep1 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* SZP2[]: Set Zone Pointer 2 */ + /* Opcode range: 0x15 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SZP2( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp2 = CUR.twilight; + break; + + case 1: + CUR.zp2 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep2 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* SZPS[]: Set Zone PointerS */ + /* Opcode range: 0x16 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SZPS( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp0 = CUR.twilight; + break; + + case 1: + CUR.zp0 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.zp1 = CUR.zp0; + CUR.zp2 = CUR.zp0; + + CUR.GS.gep0 = (FT_UShort)args[0]; + CUR.GS.gep1 = (FT_UShort)args[0]; + CUR.GS.gep2 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* INSTCTRL[]: INSTruction ConTRoL */ + /* Opcode range: 0x8e */ + /* Stack: int32 int32 --> */ + /* */ + static void + Ins_INSTCTRL( INS_ARG ) + { + FT_Long K, L; + + + K = args[1]; + L = args[0]; + + if ( K < 1 || K > 2 ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( L != 0 ) + L = K; + + CUR.GS.instruct_control = FT_BOOL( + ( (FT_Byte)CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L ); + } + + + /*************************************************************************/ + /* */ + /* SCANCTRL[]: SCAN ConTRoL */ + /* Opcode range: 0x85 */ + /* Stack: uint32? --> */ + /* */ + static void + Ins_SCANCTRL( INS_ARG ) + { + FT_Int A; + + + /* Get Threshold */ + A = (FT_Int)( args[0] & 0xFF ); + + if ( A == 0xFF ) + { + CUR.GS.scan_control = TRUE; + return; + } + else if ( A == 0 ) + { + CUR.GS.scan_control = FALSE; + return; + } + + A *= 64; + +#if 0 + if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A ) + CUR.GS.scan_control = TRUE; +#endif + + if ( (args[0] & 0x200) != 0 && CUR.tt_metrics.rotated ) + CUR.GS.scan_control = TRUE; + + if ( (args[0] & 0x400) != 0 && CUR.tt_metrics.stretched ) + CUR.GS.scan_control = TRUE; + +#if 0 + if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A ) + CUR.GS.scan_control = FALSE; +#endif + + if ( (args[0] & 0x1000) != 0 && CUR.tt_metrics.rotated ) + CUR.GS.scan_control = FALSE; + + if ( (args[0] & 0x2000) != 0 && CUR.tt_metrics.stretched ) + CUR.GS.scan_control = FALSE; + } + + + /*************************************************************************/ + /* */ + /* SCANTYPE[]: SCAN TYPE */ + /* Opcode range: 0x8D */ + /* Stack: uint32? --> */ + /* */ + static void + Ins_SCANTYPE( INS_ARG ) + { + /* for compatibility with future enhancements, */ + /* we must ignore new modes */ + + if ( args[0] >= 0 && args[0] <= 5 ) + { + if ( args[0] == 3 ) + args[0] = 2; + + CUR.GS.scan_type = (FT_Int)args[0]; + } + } + + + /*************************************************************************/ + /* */ + /* MANAGING OUTLINES */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* FLIPPT[]: FLIP PoinT */ + /* Opcode range: 0x80 */ + /* Stack: uint32... --> */ + /* */ + static void + Ins_FLIPPT( INS_ARG ) + { + FT_UShort point; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + CUR.pts.tags[point] ^= FT_CURVE_TAG_ON; + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* FLIPRGON[]: FLIP RanGe ON */ + /* Opcode range: 0x81 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_FLIPRGON( INS_ARG ) + { + FT_UShort I, K, L; + + + K = (FT_UShort)args[1]; + L = (FT_UShort)args[0]; + + if ( BOUNDS( K, CUR.pts.n_points ) || + BOUNDS( L, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + for ( I = L; I <= K; I++ ) + CUR.pts.tags[I] |= FT_CURVE_TAG_ON; + } + + + /*************************************************************************/ + /* */ + /* FLIPRGOFF: FLIP RanGe OFF */ + /* Opcode range: 0x82 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_FLIPRGOFF( INS_ARG ) + { + FT_UShort I, K, L; + + + K = (FT_UShort)args[1]; + L = (FT_UShort)args[0]; + + if ( BOUNDS( K, CUR.pts.n_points ) || + BOUNDS( L, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + for ( I = L; I <= K; I++ ) + CUR.pts.tags[I] &= ~FT_CURVE_TAG_ON; + } + + + static FT_Bool + Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x, + FT_F26Dot6* y, + TT_GlyphZone zone, + FT_UShort* refp ) + { + TT_GlyphZoneRec zp; + FT_UShort p; + FT_F26Dot6 d; + + + if ( CUR.opcode & 1 ) + { + zp = CUR.zp0; + p = CUR.GS.rp1; + } + else + { + zp = CUR.zp1; + p = CUR.GS.rp2; + } + + if ( BOUNDS( p, zp.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return FAILURE; + } + + *zone = zp; + *refp = p; + + d = CUR_Func_project( zp.cur + p, zp.org + p ); + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + if ( CUR.face->unpatented_hinting ) + { + if ( CUR.GS.both_x_axis ) + { + *x = d; + *y = 0; + } + else + { + *x = 0; + *y = d; + } + } + else +#endif + { + *x = TT_MULDIV( d, + (FT_Long)CUR.GS.freeVector.x * 0x10000L, + CUR.F_dot_P ); + *y = TT_MULDIV( d, + (FT_Long)CUR.GS.freeVector.y * 0x10000L, + CUR.F_dot_P ); + } + + return SUCCESS; + } + + + static void + Move_Zp2_Point( EXEC_OP_ FT_UShort point, + FT_F26Dot6 dx, + FT_F26Dot6 dy, + FT_Bool touch ) + { +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + if ( CUR.face->unpatented_hinting ) + { + if ( CUR.GS.both_x_axis ) + { + CUR.zp2.cur[point].x += dx; + if ( touch ) + CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; + } + else + { + CUR.zp2.cur[point].y += dy; + if ( touch ) + CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; + } + return; + } +#endif + + if ( CUR.GS.freeVector.x != 0 ) + { + CUR.zp2.cur[point].x += dx; + if ( touch ) + CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_X; + } + + if ( CUR.GS.freeVector.y != 0 ) + { + CUR.zp2.cur[point].y += dy; + if ( touch ) + CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_Y; + } + } + + + /*************************************************************************/ + /* */ + /* SHP[a]: SHift Point by the last point */ + /* Opcode range: 0x32-0x33 */ + /* Stack: uint32... --> */ + /* */ + static void + Ins_SHP( INS_ARG ) + { + TT_GlyphZoneRec zp; + FT_UShort refp; + + FT_F26Dot6 dx, + dy; + FT_UShort point; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + /* XXX: UNDOCUMENTED! SHP touches the points */ + MOVE_Zp2_Point( point, dx, dy, TRUE ); + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* SHC[a]: SHift Contour */ + /* Opcode range: 0x34-35 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SHC( INS_ARG ) + { + TT_GlyphZoneRec zp; + FT_UShort refp; + FT_F26Dot6 dx, + dy; + + FT_Short contour; + FT_UShort first_point, last_point, i; + + + contour = (FT_UShort)args[0]; + + if ( BOUNDS( contour, CUR.pts.n_contours ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + if ( contour == 0 ) + first_point = 0; + else + first_point = (FT_UShort)(CUR.pts.contours[contour - 1] + 1); + + last_point = CUR.pts.contours[contour]; + + /* XXX: this is probably wrong... at least it prevents memory */ + /* corruption when zp2 is the twilight zone */ + if ( last_point > CUR.zp2.n_points ) + { + if ( CUR.zp2.n_points > 0 ) + last_point = (FT_UShort)(CUR.zp2.n_points - 1); + else + last_point = 0; + } + + /* XXX: UNDOCUMENTED! SHC does touch the points */ + for ( i = first_point; i <= last_point; i++ ) + { + if ( zp.cur != CUR.zp2.cur || refp != i ) + MOVE_Zp2_Point( i, dx, dy, TRUE ); + } + } + + + /*************************************************************************/ + /* */ + /* SHZ[a]: SHift Zone */ + /* Opcode range: 0x36-37 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_SHZ( INS_ARG ) + { + TT_GlyphZoneRec zp; + FT_UShort refp; + FT_F26Dot6 dx, + dy; + + FT_UShort last_point, i; + + + if ( BOUNDS( args[0], 2 ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + if ( CUR.zp2.n_points > 0 ) + last_point = (FT_UShort)(CUR.zp2.n_points - 1); + else + last_point = 0; + + /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */ + for ( i = 0; i <= last_point; i++ ) + { + if ( zp.cur != CUR.zp2.cur || refp != i ) + MOVE_Zp2_Point( i, dx, dy, FALSE ); + } + } + + + /*************************************************************************/ + /* */ + /* SHPIX[]: SHift points by a PIXel amount */ + /* Opcode range: 0x38 */ + /* Stack: f26.6 uint32... --> */ + /* */ + static void + Ins_SHPIX( INS_ARG ) + { + FT_F26Dot6 dx, dy; + FT_UShort point; + + + if ( CUR.top < CUR.GS.loop + 1 ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + if ( CUR.face->unpatented_hinting ) + { + if ( CUR.GS.both_x_axis ) + { + dx = TT_MulFix14( args[0], 0x4000 ); + dy = 0; + } + else + { + dx = 0; + dy = TT_MulFix14( args[0], 0x4000 ); + } + } + else +#endif + { + dx = TT_MulFix14( args[0], CUR.GS.freeVector.x ); + dy = TT_MulFix14( args[0], CUR.GS.freeVector.y ); + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + MOVE_Zp2_Point( point, dx, dy, TRUE ); + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* MSIRP[a]: Move Stack Indirect Relative Position */ + /* Opcode range: 0x3A-0x3B */ + /* Stack: f26.6 uint32 --> */ + /* */ + static void + Ins_MSIRP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 distance; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: UNDOCUMENTED! behaviour */ + if ( CUR.GS.gep1 == 0 ) /* if the point that is to be moved */ + /* is in twilight zone */ + { + CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0]; + CUR_Func_move_orig( &CUR.zp1, point, args[1] ); + CUR.zp1.cur[point] = CUR.zp1.org[point]; + } + + distance = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, args[1] - distance ); + + CUR.GS.rp1 = CUR.GS.rp0; + CUR.GS.rp2 = point; + + if ( (CUR.opcode & 1) != 0 ) + CUR.GS.rp0 = point; + } + + + /*************************************************************************/ + /* */ + /* MDAP[a]: Move Direct Absolute Point */ + /* Opcode range: 0x2E-0x2F */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_MDAP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 cur_dist, + distance; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: Is there some undocumented feature while in the */ + /* twilight zone? ? */ + if ( ( CUR.opcode & 1 ) != 0 ) + { + cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector ); + distance = CUR_Func_round( cur_dist, + CUR.tt_metrics.compensations[0] ) - cur_dist; + } + else + distance = 0; + + CUR_Func_move( &CUR.zp0, point, distance ); + + CUR.GS.rp0 = point; + CUR.GS.rp1 = point; + } + + + /*************************************************************************/ + /* */ + /* MIAP[a]: Move Indirect Absolute Point */ + /* Opcode range: 0x3E-0x3F */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_MIAP( INS_ARG ) + { + FT_ULong cvtEntry; + FT_UShort point; + FT_F26Dot6 distance, + org_dist; + + + cvtEntry = (FT_ULong)args[1]; + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) || + BOUNDS( cvtEntry, CUR.cvtSize ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* UNDOCUMENTED! */ + /* */ + /* The behaviour of an MIAP instruction is quite */ + /* different when used in the twilight zone. */ + /* */ + /* First, no control value cutin test is performed */ + /* as it would fail anyway. Second, the original */ + /* point, i.e. (org_x,org_y) of zp0.point, is set */ + /* to the absolute, unrounded distance found in */ + /* the CVT. */ + /* */ + /* This is used in the CVT programs of the Microsoft */ + /* fonts Arial, Times, etc., in order to re-adjust */ + /* some key font heights. It allows the use of the */ + /* IP instruction in the twilight zone, which */ + /* otherwise would be `illegal' according to the */ + /* specification. */ + /* */ + /* We implement it with a special sequence for the */ + /* twilight zone. This is a bad hack, but it seems */ + /* to work. */ + + distance = CUR_Func_read_cvt( cvtEntry ); + + if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */ + { + CUR.zp0.org[point].x = TT_MulFix14( distance, CUR.GS.freeVector.x ); + CUR.zp0.org[point].y = TT_MulFix14( distance, CUR.GS.freeVector.y ), + CUR.zp0.cur[point] = CUR.zp0.org[point]; + } + + org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector ); + + if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */ + { + if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin ) + distance = org_dist; + + distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] ); + } + + CUR_Func_move( &CUR.zp0, point, distance - org_dist ); + + CUR.GS.rp0 = point; + CUR.GS.rp1 = point; + } + + + /*************************************************************************/ + /* */ + /* MDRP[abcde]: Move Direct Relative Point */ + /* Opcode range: 0xC0-0xDF */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_MDRP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 org_dist, distance; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: Is there some undocumented feature while in the */ + /* twilight zone? */ + + org_dist = CUR_Func_dualproj( CUR.zp1.org + point, + CUR.zp0.org + CUR.GS.rp0 ); + + /* single width cutin test */ + + if ( FT_ABS( org_dist - CUR.GS.single_width_value ) < + CUR.GS.single_width_cutin ) + { + if ( org_dist >= 0 ) + org_dist = CUR.GS.single_width_value; + else + org_dist = -CUR.GS.single_width_value; + } + + /* round flag */ + + if ( ( CUR.opcode & 4 ) != 0 ) + distance = CUR_Func_round( + org_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + else + distance = ROUND_None( + org_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + + /* minimum distance flag */ + + if ( ( CUR.opcode & 8 ) != 0 ) + { + if ( org_dist >= 0 ) + { + if ( distance < CUR.GS.minimum_distance ) + distance = CUR.GS.minimum_distance; + } + else + { + if ( distance > -CUR.GS.minimum_distance ) + distance = -CUR.GS.minimum_distance; + } + } + + /* now move the point */ + + org_dist = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, distance - org_dist ); + + CUR.GS.rp1 = CUR.GS.rp0; + CUR.GS.rp2 = point; + + if ( ( CUR.opcode & 16 ) != 0 ) + CUR.GS.rp0 = point; + } + + + /*************************************************************************/ + /* */ + /* MIRP[abcde]: Move Indirect Relative Point */ + /* Opcode range: 0xE0-0xFF */ + /* Stack: int32? uint32 --> */ + /* */ + static void + Ins_MIRP( INS_ARG ) + { + FT_UShort point; + FT_ULong cvtEntry; + + FT_F26Dot6 cvt_dist, + distance, + cur_dist, + org_dist; + + + point = (FT_UShort)args[0]; + cvtEntry = (FT_ULong)( args[1] + 1 ); + + /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( cvtEntry, CUR.cvtSize + 1 ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( !cvtEntry ) + cvt_dist = 0; + else + cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 ); + + /* single width test */ + + if ( FT_ABS( cvt_dist - CUR.GS.single_width_value ) < + CUR.GS.single_width_cutin ) + { + if ( cvt_dist >= 0 ) + cvt_dist = CUR.GS.single_width_value; + else + cvt_dist = -CUR.GS.single_width_value; + } + + /* XXX: UNDOCUMENTED! -- twilight zone */ + + if ( CUR.GS.gep1 == 0 ) + { + CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x + + TT_MulFix14( cvt_dist, CUR.GS.freeVector.x ); + + CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y + + TT_MulFix14( cvt_dist, CUR.GS.freeVector.y ); + + CUR.zp1.cur[point] = CUR.zp1.org[point]; + } + + org_dist = CUR_Func_dualproj( CUR.zp1.org + point, + CUR.zp0.org + CUR.GS.rp0 ); + + cur_dist = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + /* auto-flip test */ + + if ( CUR.GS.auto_flip ) + { + if ( ( org_dist ^ cvt_dist ) < 0 ) + cvt_dist = -cvt_dist; + } + + /* control value cutin and round */ + + if ( ( CUR.opcode & 4 ) != 0 ) + { + /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */ + /* refer to the same zone. */ + + if ( CUR.GS.gep0 == CUR.GS.gep1 ) + if ( FT_ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin ) + cvt_dist = org_dist; + + distance = CUR_Func_round( + cvt_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + } + else + distance = ROUND_None( + cvt_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + + /* minimum distance test */ + + if ( ( CUR.opcode & 8 ) != 0 ) + { + if ( org_dist >= 0 ) + { + if ( distance < CUR.GS.minimum_distance ) + distance = CUR.GS.minimum_distance; + } + else + { + if ( distance > -CUR.GS.minimum_distance ) + distance = -CUR.GS.minimum_distance; + } + } + + CUR_Func_move( &CUR.zp1, point, distance - cur_dist ); + + CUR.GS.rp1 = CUR.GS.rp0; + + if ( ( CUR.opcode & 16 ) != 0 ) + CUR.GS.rp0 = point; + + /* XXX: UNDOCUMENTED! */ + + CUR.GS.rp2 = point; + } + + + /*************************************************************************/ + /* */ + /* ALIGNRP[]: ALIGN Relative Point */ + /* Opcode range: 0x3C */ + /* Stack: uint32 uint32... --> */ + /* */ + static void + Ins_ALIGNRP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 distance; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + distance = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, -distance ); + } + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* ISECT[]: moves point to InterSECTion */ + /* Opcode range: 0x0F */ + /* Stack: 5 * uint32 --> */ + /* */ + static void + Ins_ISECT( INS_ARG ) + { + FT_UShort point, + a0, a1, + b0, b1; + + FT_F26Dot6 discriminant; + + FT_F26Dot6 dx, dy, + dax, day, + dbx, dby; + + FT_F26Dot6 val; + + FT_Vector R; + + + point = (FT_UShort)args[0]; + + a0 = (FT_UShort)args[1]; + a1 = (FT_UShort)args[2]; + b0 = (FT_UShort)args[3]; + b1 = (FT_UShort)args[4]; + + if ( BOUNDS( b0, CUR.zp0.n_points ) || + BOUNDS( b1, CUR.zp0.n_points ) || + BOUNDS( a0, CUR.zp1.n_points ) || + BOUNDS( a1, CUR.zp1.n_points ) || + BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x; + dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y; + + dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x; + day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y; + + dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x; + dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y; + + CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH; + + discriminant = TT_MULDIV( dax, -dby, 0x40 ) + + TT_MULDIV( day, dbx, 0x40 ); + + if ( FT_ABS( discriminant ) >= 0x40 ) + { + val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 ); + + R.x = TT_MULDIV( val, dax, discriminant ); + R.y = TT_MULDIV( val, day, discriminant ); + + CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x; + CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y; + } + else + { + /* else, take the middle of the middles of A and B */ + + CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x + + CUR.zp1.cur[a1].x + + CUR.zp0.cur[b0].x + + CUR.zp0.cur[b1].x ) / 4; + CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y + + CUR.zp1.cur[a1].y + + CUR.zp0.cur[b0].y + + CUR.zp0.cur[b1].y ) / 4; + } + } + + + /*************************************************************************/ + /* */ + /* ALIGNPTS[]: ALIGN PoinTS */ + /* Opcode range: 0x27 */ + /* Stack: uint32 uint32 --> */ + /* */ + static void + Ins_ALIGNPTS( INS_ARG ) + { + FT_UShort p1, p2; + FT_F26Dot6 distance; + + + p1 = (FT_UShort)args[0]; + p2 = (FT_UShort)args[1]; + + if ( BOUNDS( args[0], CUR.zp1.n_points ) || + BOUNDS( args[1], CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + distance = CUR_Func_project( CUR.zp0.cur + p2, + CUR.zp1.cur + p1 ) / 2; + + CUR_Func_move( &CUR.zp1, p1, distance ); + CUR_Func_move( &CUR.zp0, p2, -distance ); + } + + + /*************************************************************************/ + /* */ + /* IP[]: Interpolate Point */ + /* Opcode range: 0x39 */ + /* Stack: uint32... --> */ + /* */ + static void + Ins_IP( INS_ARG ) + { + FT_F26Dot6 org_a, org_b, org_x, + cur_a, cur_b, cur_x, + distance; + FT_UShort point; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: There are some glyphs in some braindead but popular */ + /* fonts out there (e.g. [aeu]grave in monotype.ttf) */ + /* calling IP[] with bad values of rp[12]. */ + /* Do something sane when this odd thing happens. */ + + if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) || + BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) ) + { + org_a = cur_a = 0; + org_b = cur_b = 0; + } + else + { + org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector ); + org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector ); + + cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector ); + cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector ); + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector ); + cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector ); + + if ( ( org_a <= org_b && org_x <= org_a ) || + ( org_a > org_b && org_x >= org_a ) ) + + distance = ( cur_a - org_a ) + ( org_x - cur_x ); + + else if ( ( org_a <= org_b && org_x >= org_b ) || + ( org_a > org_b && org_x < org_b ) ) + + distance = ( cur_b - org_b ) + ( org_x - cur_x ); + + else + /* note: it seems that rounding this value isn't a good */ + /* idea (cf. width of capital `S' in Times) */ + + distance = TT_MULDIV( cur_b - cur_a, + org_x - org_a, + org_b - org_a ) + ( cur_a - cur_x ); + + CUR_Func_move( &CUR.zp2, point, distance ); + } + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* UTP[a]: UnTouch Point */ + /* Opcode range: 0x29 */ + /* Stack: uint32 --> */ + /* */ + static void + Ins_UTP( INS_ARG ) + { + FT_UShort point; + FT_Byte mask; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + mask = 0xFF; + + if ( CUR.GS.freeVector.x != 0 ) + mask &= ~FT_CURVE_TAG_TOUCH_X; + + if ( CUR.GS.freeVector.y != 0 ) + mask &= ~FT_CURVE_TAG_TOUCH_Y; + + CUR.zp0.tags[point] &= mask; + } + + + /* Local variables for Ins_IUP: */ + struct LOC_Ins_IUP + { + FT_Vector* orgs; /* original and current coordinate */ + FT_Vector* curs; /* arrays */ + }; + + + static void + Shift( FT_UInt p1, + FT_UInt p2, + FT_UInt p, + struct LOC_Ins_IUP* LINK ) + { + FT_UInt i; + FT_F26Dot6 x; + + + x = LINK->curs[p].x - LINK->orgs[p].x; + + for ( i = p1; i < p; i++ ) + LINK->curs[i].x += x; + + for ( i = p + 1; i <= p2; i++ ) + LINK->curs[i].x += x; + } + + + static void + Interp( FT_UInt p1, + FT_UInt p2, + FT_UInt ref1, + FT_UInt ref2, + struct LOC_Ins_IUP* LINK ) + { + FT_UInt i; + FT_F26Dot6 x, x1, x2, d1, d2; + + + if ( p1 > p2 ) + return; + + x1 = LINK->orgs[ref1].x; + d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x; + x2 = LINK->orgs[ref2].x; + d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x; + + if ( x1 == x2 ) + { + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + + if ( x <= x1 ) + x += d1; + else + x += d2; + + LINK->curs[i].x = x; + } + return; + } + + if ( x1 < x2 ) + { + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + + if ( x <= x1 ) + x += d1; + else + { + if ( x >= x2 ) + x += d2; + else + x = LINK->curs[ref1].x + + TT_MULDIV( x - x1, + LINK->curs[ref2].x - LINK->curs[ref1].x, + x2 - x1 ); + } + LINK->curs[i].x = x; + } + return; + } + + /* x2 < x1 */ + + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + if ( x <= x2 ) + x += d2; + else + { + if ( x >= x1 ) + x += d1; + else + x = LINK->curs[ref1].x + + TT_MULDIV( x - x1, + LINK->curs[ref2].x - LINK->curs[ref1].x, + x2 - x1 ); + } + LINK->curs[i].x = x; + } + } + + + /*************************************************************************/ + /* */ + /* IUP[a]: Interpolate Untouched Points */ + /* Opcode range: 0x30-0x31 */ + /* Stack: --> */ + /* */ + static void + Ins_IUP( INS_ARG ) + { + struct LOC_Ins_IUP V; + FT_Byte mask; + + FT_UInt first_point; /* first point of contour */ + FT_UInt end_point; /* end point (last+1) of contour */ + + FT_UInt first_touched; /* first touched point in contour */ + FT_UInt cur_touched; /* current touched point in contour */ + + FT_UInt point; /* current point */ + FT_Short contour; /* current contour */ + + FT_UNUSED_ARG; + + + if ( CUR.opcode & 1 ) + { + mask = FT_CURVE_TAG_TOUCH_X; + V.orgs = CUR.pts.org; + V.curs = CUR.pts.cur; + } + else + { + mask = FT_CURVE_TAG_TOUCH_Y; + V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 ); + V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 ); + } + + contour = 0; + point = 0; + + do + { + end_point = CUR.pts.contours[contour]; + first_point = point; + + while ( point <= end_point && (CUR.pts.tags[point] & mask) == 0 ) + point++; + + if ( point <= end_point ) + { + first_touched = point; + cur_touched = point; + + point++; + + while ( point <= end_point ) + { + if ( ( CUR.pts.tags[point] & mask ) != 0 ) + { + if ( point > 0 ) + Interp( cur_touched + 1, + point - 1, + cur_touched, + point, + &V ); + cur_touched = point; + } + + point++; + } + + if ( cur_touched == first_touched ) + Shift( first_point, end_point, cur_touched, &V ); + else + { + Interp( (FT_UShort)( cur_touched + 1 ), + end_point, + cur_touched, + first_touched, + &V ); + + if ( first_touched > 0 ) + Interp( first_point, + first_touched - 1, + cur_touched, + first_touched, + &V ); + } + } + contour++; + } while ( contour < CUR.pts.n_contours ); + } + + + /*************************************************************************/ + /* */ + /* DELTAPn[]: DELTA exceptions P1, P2, P3 */ + /* Opcode range: 0x5D,0x71,0x72 */ + /* Stack: uint32 (2 * uint32)... --> */ + /* */ + static void + Ins_DELTAP( INS_ARG ) + { + FT_ULong k, nump; + FT_UShort A; + FT_ULong C; + FT_Long B; + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + /* Delta hinting is covered by US Patent 5159668. */ + if ( CUR.face->unpatented_hinting ) + { + FT_Long n = args[0] * 2; + if ( CUR.args < n ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= n; + CUR.new_top = CUR.args; + return; + } +#endif + + nump = (FT_ULong)args[0]; /* some points theoretically may occur more + than once, thus UShort isn't enough */ + + for ( k = 1; k <= nump; k++ ) + { + if ( CUR.args < 2 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= 2; + + A = (FT_UShort)CUR.stack[CUR.args + 1]; + B = CUR.stack[CUR.args]; + + /* XXX: Because some popular fonts contain some invalid DeltaP */ + /* instructions, we simply ignore them when the stacked */ + /* point reference is off limit, rather than returning an */ + /* error. As a delta instruction doesn't change a glyph */ + /* in great ways, this shouldn't be a problem. */ + + if ( !BOUNDS( A, CUR.zp0.n_points ) ) + { + C = ( (FT_ULong)B & 0xF0 ) >> 4; + + switch ( CUR.opcode ) + { + case 0x5D: + break; + + case 0x71: + C += 16; + break; + + case 0x72: + C += 32; + break; + } + + C += CUR.GS.delta_base; + + if ( CURRENT_Ppem() == (FT_Long)C ) + { + B = ( (FT_ULong)B & 0xF ) - 8; + if ( B >= 0 ) + B++; + B = B * 64 / ( 1L << CUR.GS.delta_shift ); + + CUR_Func_move( &CUR.zp0, A, B ); + } + } + else + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + } + + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* DELTACn[]: DELTA exceptions C1, C2, C3 */ + /* Opcode range: 0x73,0x74,0x75 */ + /* Stack: uint32 (2 * uint32)... --> */ + /* */ + static void + Ins_DELTAC( INS_ARG ) + { + FT_ULong nump, k; + FT_ULong A, C; + FT_Long B; + + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + /* Delta hinting is covered by US Patent 5159668. */ + if ( CUR.face->unpatented_hinting ) + { + FT_Long n = args[0] * 2; + + + if ( CUR.args < n ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= n; + CUR.new_top = CUR.args; + return; + } +#endif + + nump = (FT_ULong)args[0]; + + for ( k = 1; k <= nump; k++ ) + { + if ( CUR.args < 2 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= 2; + + A = (FT_ULong)CUR.stack[CUR.args + 1]; + B = CUR.stack[CUR.args]; + + if ( BOUNDS( A, CUR.cvtSize ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + C = ( (FT_ULong)B & 0xF0 ) >> 4; + + switch ( CUR.opcode ) + { + case 0x73: + break; + + case 0x74: + C += 16; + break; + + case 0x75: + C += 32; + break; + } + + C += CUR.GS.delta_base; + + if ( CURRENT_Ppem() == (FT_Long)C ) + { + B = ( (FT_ULong)B & 0xF ) - 8; + if ( B >= 0 ) + B++; + B = B * 64 / ( 1L << CUR.GS.delta_shift ); + + CUR_Func_move_cvt( A, B ); + } + } + } + + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* MISC. INSTRUCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* GETINFO[]: GET INFOrmation */ + /* Opcode range: 0x88 */ + /* Stack: uint32 --> uint32 */ + /* */ + /* XXX: According to Apple specs, bits 1 & 2 of the argument ought to be */ + /* consulted before rotated/stretched info is returned. */ + static void + Ins_GETINFO( INS_ARG ) + { + FT_Long K; + + + K = 0; + + /* We return then Windows 3.1 version number */ + /* for the font scaler */ + if ( ( args[0] & 1 ) != 0 ) + K = 3; + + /* Has the glyph been rotated ? */ + if ( CUR.tt_metrics.rotated ) + K |= 0x80; + + /* Has the glyph been stretched ? */ + if ( CUR.tt_metrics.stretched ) + K |= 0x100; + + args[0] = K; + } + + + static void + Ins_UNKNOWN( INS_ARG ) + { + TT_DefRecord* def = CUR.IDefs; + TT_DefRecord* limit = def + CUR.numIDefs; + + FT_UNUSED_ARG; + + + for ( ; def < limit; def++ ) + { + if ( (FT_Byte)def->opc == CUR.opcode && def->active ) + { + TT_CallRec* call; + + + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + call = CUR.callStack + CUR.callTop++; + + call->Caller_Range = CUR.curRange; + call->Caller_IP = CUR.IP+1; + call->Cur_Count = 1; + call->Cur_Restart = def->start; + + INS_Goto_CodeRange( def->range, def->start ); + + CUR.step_ins = FALSE; + return; + } + } + + CUR.error = TT_Err_Invalid_Opcode; + } + + +#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + static + TInstruction_Function Instruct_Dispatch[256] = + { + /* Opcodes are gathered in groups of 16. */ + /* Please keep the spaces as they are. */ + + /* SVTCA y */ Ins_SVTCA, + /* SVTCA x */ Ins_SVTCA, + /* SPvTCA y */ Ins_SPVTCA, + /* SPvTCA x */ Ins_SPVTCA, + /* SFvTCA y */ Ins_SFVTCA, + /* SFvTCA x */ Ins_SFVTCA, + /* SPvTL // */ Ins_SPVTL, + /* SPvTL + */ Ins_SPVTL, + /* SFvTL // */ Ins_SFVTL, + /* SFvTL + */ Ins_SFVTL, + /* SPvFS */ Ins_SPVFS, + /* SFvFS */ Ins_SFVFS, + /* GPV */ Ins_GPV, + /* GFV */ Ins_GFV, + /* SFvTPv */ Ins_SFVTPV, + /* ISECT */ Ins_ISECT, + + /* SRP0 */ Ins_SRP0, + /* SRP1 */ Ins_SRP1, + /* SRP2 */ Ins_SRP2, + /* SZP0 */ Ins_SZP0, + /* SZP1 */ Ins_SZP1, + /* SZP2 */ Ins_SZP2, + /* SZPS */ Ins_SZPS, + /* SLOOP */ Ins_SLOOP, + /* RTG */ Ins_RTG, + /* RTHG */ Ins_RTHG, + /* SMD */ Ins_SMD, + /* ELSE */ Ins_ELSE, + /* JMPR */ Ins_JMPR, + /* SCvTCi */ Ins_SCVTCI, + /* SSwCi */ Ins_SSWCI, + /* SSW */ Ins_SSW, + + /* DUP */ Ins_DUP, + /* POP */ Ins_POP, + /* CLEAR */ Ins_CLEAR, + /* SWAP */ Ins_SWAP, + /* DEPTH */ Ins_DEPTH, + /* CINDEX */ Ins_CINDEX, + /* MINDEX */ Ins_MINDEX, + /* AlignPTS */ Ins_ALIGNPTS, + /* INS_0x28 */ Ins_UNKNOWN, + /* UTP */ Ins_UTP, + /* LOOPCALL */ Ins_LOOPCALL, + /* CALL */ Ins_CALL, + /* FDEF */ Ins_FDEF, + /* ENDF */ Ins_ENDF, + /* MDAP[0] */ Ins_MDAP, + /* MDAP[1] */ Ins_MDAP, + + /* IUP[0] */ Ins_IUP, + /* IUP[1] */ Ins_IUP, + /* SHP[0] */ Ins_SHP, + /* SHP[1] */ Ins_SHP, + /* SHC[0] */ Ins_SHC, + /* SHC[1] */ Ins_SHC, + /* SHZ[0] */ Ins_SHZ, + /* SHZ[1] */ Ins_SHZ, + /* SHPIX */ Ins_SHPIX, + /* IP */ Ins_IP, + /* MSIRP[0] */ Ins_MSIRP, + /* MSIRP[1] */ Ins_MSIRP, + /* AlignRP */ Ins_ALIGNRP, + /* RTDG */ Ins_RTDG, + /* MIAP[0] */ Ins_MIAP, + /* MIAP[1] */ Ins_MIAP, + + /* NPushB */ Ins_NPUSHB, + /* NPushW */ Ins_NPUSHW, + /* WS */ Ins_WS, + /* RS */ Ins_RS, + /* WCvtP */ Ins_WCVTP, + /* RCvt */ Ins_RCVT, + /* GC[0] */ Ins_GC, + /* GC[1] */ Ins_GC, + /* SCFS */ Ins_SCFS, + /* MD[0] */ Ins_MD, + /* MD[1] */ Ins_MD, + /* MPPEM */ Ins_MPPEM, + /* MPS */ Ins_MPS, + /* FlipON */ Ins_FLIPON, + /* FlipOFF */ Ins_FLIPOFF, + /* DEBUG */ Ins_DEBUG, + + /* LT */ Ins_LT, + /* LTEQ */ Ins_LTEQ, + /* GT */ Ins_GT, + /* GTEQ */ Ins_GTEQ, + /* EQ */ Ins_EQ, + /* NEQ */ Ins_NEQ, + /* ODD */ Ins_ODD, + /* EVEN */ Ins_EVEN, + /* IF */ Ins_IF, + /* EIF */ Ins_EIF, + /* AND */ Ins_AND, + /* OR */ Ins_OR, + /* NOT */ Ins_NOT, + /* DeltaP1 */ Ins_DELTAP, + /* SDB */ Ins_SDB, + /* SDS */ Ins_SDS, + + /* ADD */ Ins_ADD, + /* SUB */ Ins_SUB, + /* DIV */ Ins_DIV, + /* MUL */ Ins_MUL, + /* ABS */ Ins_ABS, + /* NEG */ Ins_NEG, + /* FLOOR */ Ins_FLOOR, + /* CEILING */ Ins_CEILING, + /* ROUND[0] */ Ins_ROUND, + /* ROUND[1] */ Ins_ROUND, + /* ROUND[2] */ Ins_ROUND, + /* ROUND[3] */ Ins_ROUND, + /* NROUND[0] */ Ins_NROUND, + /* NROUND[1] */ Ins_NROUND, + /* NROUND[2] */ Ins_NROUND, + /* NROUND[3] */ Ins_NROUND, + + /* WCvtF */ Ins_WCVTF, + /* DeltaP2 */ Ins_DELTAP, + /* DeltaP3 */ Ins_DELTAP, + /* DeltaCn[0] */ Ins_DELTAC, + /* DeltaCn[1] */ Ins_DELTAC, + /* DeltaCn[2] */ Ins_DELTAC, + /* SROUND */ Ins_SROUND, + /* S45Round */ Ins_S45ROUND, + /* JROT */ Ins_JROT, + /* JROF */ Ins_JROF, + /* ROFF */ Ins_ROFF, + /* INS_0x7B */ Ins_UNKNOWN, + /* RUTG */ Ins_RUTG, + /* RDTG */ Ins_RDTG, + /* SANGW */ Ins_SANGW, + /* AA */ Ins_AA, + + /* FlipPT */ Ins_FLIPPT, + /* FlipRgON */ Ins_FLIPRGON, + /* FlipRgOFF */ Ins_FLIPRGOFF, + /* INS_0x83 */ Ins_UNKNOWN, + /* INS_0x84 */ Ins_UNKNOWN, + /* ScanCTRL */ Ins_SCANCTRL, + /* SDPVTL[0] */ Ins_SDPVTL, + /* SDPVTL[1] */ Ins_SDPVTL, + /* GetINFO */ Ins_GETINFO, + /* IDEF */ Ins_IDEF, + /* ROLL */ Ins_ROLL, + /* MAX */ Ins_MAX, + /* MIN */ Ins_MIN, + /* ScanTYPE */ Ins_SCANTYPE, + /* InstCTRL */ Ins_INSTCTRL, + /* INS_0x8F */ Ins_UNKNOWN, + + /* INS_0x90 */ Ins_UNKNOWN, + /* INS_0x91 */ Ins_UNKNOWN, + /* INS_0x92 */ Ins_UNKNOWN, + /* INS_0x93 */ Ins_UNKNOWN, + /* INS_0x94 */ Ins_UNKNOWN, + /* INS_0x95 */ Ins_UNKNOWN, + /* INS_0x96 */ Ins_UNKNOWN, + /* INS_0x97 */ Ins_UNKNOWN, + /* INS_0x98 */ Ins_UNKNOWN, + /* INS_0x99 */ Ins_UNKNOWN, + /* INS_0x9A */ Ins_UNKNOWN, + /* INS_0x9B */ Ins_UNKNOWN, + /* INS_0x9C */ Ins_UNKNOWN, + /* INS_0x9D */ Ins_UNKNOWN, + /* INS_0x9E */ Ins_UNKNOWN, + /* INS_0x9F */ Ins_UNKNOWN, + + /* INS_0xA0 */ Ins_UNKNOWN, + /* INS_0xA1 */ Ins_UNKNOWN, + /* INS_0xA2 */ Ins_UNKNOWN, + /* INS_0xA3 */ Ins_UNKNOWN, + /* INS_0xA4 */ Ins_UNKNOWN, + /* INS_0xA5 */ Ins_UNKNOWN, + /* INS_0xA6 */ Ins_UNKNOWN, + /* INS_0xA7 */ Ins_UNKNOWN, + /* INS_0xA8 */ Ins_UNKNOWN, + /* INS_0xA9 */ Ins_UNKNOWN, + /* INS_0xAA */ Ins_UNKNOWN, + /* INS_0xAB */ Ins_UNKNOWN, + /* INS_0xAC */ Ins_UNKNOWN, + /* INS_0xAD */ Ins_UNKNOWN, + /* INS_0xAE */ Ins_UNKNOWN, + /* INS_0xAF */ Ins_UNKNOWN, + + /* PushB[0] */ Ins_PUSHB, + /* PushB[1] */ Ins_PUSHB, + /* PushB[2] */ Ins_PUSHB, + /* PushB[3] */ Ins_PUSHB, + /* PushB[4] */ Ins_PUSHB, + /* PushB[5] */ Ins_PUSHB, + /* PushB[6] */ Ins_PUSHB, + /* PushB[7] */ Ins_PUSHB, + /* PushW[0] */ Ins_PUSHW, + /* PushW[1] */ Ins_PUSHW, + /* PushW[2] */ Ins_PUSHW, + /* PushW[3] */ Ins_PUSHW, + /* PushW[4] */ Ins_PUSHW, + /* PushW[5] */ Ins_PUSHW, + /* PushW[6] */ Ins_PUSHW, + /* PushW[7] */ Ins_PUSHW, + + /* MDRP[00] */ Ins_MDRP, + /* MDRP[01] */ Ins_MDRP, + /* MDRP[02] */ Ins_MDRP, + /* MDRP[03] */ Ins_MDRP, + /* MDRP[04] */ Ins_MDRP, + /* MDRP[05] */ Ins_MDRP, + /* MDRP[06] */ Ins_MDRP, + /* MDRP[07] */ Ins_MDRP, + /* MDRP[08] */ Ins_MDRP, + /* MDRP[09] */ Ins_MDRP, + /* MDRP[10] */ Ins_MDRP, + /* MDRP[11] */ Ins_MDRP, + /* MDRP[12] */ Ins_MDRP, + /* MDRP[13] */ Ins_MDRP, + /* MDRP[14] */ Ins_MDRP, + /* MDRP[15] */ Ins_MDRP, + + /* MDRP[16] */ Ins_MDRP, + /* MDRP[17] */ Ins_MDRP, + /* MDRP[18] */ Ins_MDRP, + /* MDRP[19] */ Ins_MDRP, + /* MDRP[20] */ Ins_MDRP, + /* MDRP[21] */ Ins_MDRP, + /* MDRP[22] */ Ins_MDRP, + /* MDRP[23] */ Ins_MDRP, + /* MDRP[24] */ Ins_MDRP, + /* MDRP[25] */ Ins_MDRP, + /* MDRP[26] */ Ins_MDRP, + /* MDRP[27] */ Ins_MDRP, + /* MDRP[28] */ Ins_MDRP, + /* MDRP[29] */ Ins_MDRP, + /* MDRP[30] */ Ins_MDRP, + /* MDRP[31] */ Ins_MDRP, + + /* MIRP[00] */ Ins_MIRP, + /* MIRP[01] */ Ins_MIRP, + /* MIRP[02] */ Ins_MIRP, + /* MIRP[03] */ Ins_MIRP, + /* MIRP[04] */ Ins_MIRP, + /* MIRP[05] */ Ins_MIRP, + /* MIRP[06] */ Ins_MIRP, + /* MIRP[07] */ Ins_MIRP, + /* MIRP[08] */ Ins_MIRP, + /* MIRP[09] */ Ins_MIRP, + /* MIRP[10] */ Ins_MIRP, + /* MIRP[11] */ Ins_MIRP, + /* MIRP[12] */ Ins_MIRP, + /* MIRP[13] */ Ins_MIRP, + /* MIRP[14] */ Ins_MIRP, + /* MIRP[15] */ Ins_MIRP, + + /* MIRP[16] */ Ins_MIRP, + /* MIRP[17] */ Ins_MIRP, + /* MIRP[18] */ Ins_MIRP, + /* MIRP[19] */ Ins_MIRP, + /* MIRP[20] */ Ins_MIRP, + /* MIRP[21] */ Ins_MIRP, + /* MIRP[22] */ Ins_MIRP, + /* MIRP[23] */ Ins_MIRP, + /* MIRP[24] */ Ins_MIRP, + /* MIRP[25] */ Ins_MIRP, + /* MIRP[26] */ Ins_MIRP, + /* MIRP[27] */ Ins_MIRP, + /* MIRP[28] */ Ins_MIRP, + /* MIRP[29] */ Ins_MIRP, + /* MIRP[30] */ Ins_MIRP, + /* MIRP[31] */ Ins_MIRP + }; + + +#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */ + + + /*************************************************************************/ + /* */ + /* RUN */ + /* */ + /* This function executes a run of opcodes. It will exit in the */ + /* following cases: */ + /* */ + /* - Errors (in which case it returns FALSE). */ + /* */ + /* - Reaching the end of the main code range (returns TRUE). */ + /* Reaching the end of a code range within a function call is an */ + /* error. */ + /* */ + /* - After executing one single opcode, if the flag `Instruction_Trap' */ + /* is set to TRUE (returns TRUE). */ + /* */ + /* On exit whith TRUE, test IP < CodeSize to know wether it comes from */ + /* an instruction trap or a normal termination. */ + /* */ + /* */ + /* Note: The documented DEBUG opcode pops a value from the stack. This */ + /* behaviour is unsupported; here a DEBUG opcode is always an */ + /* error. */ + /* */ + /* */ + /* THIS IS THE INTERPRETER'S MAIN LOOP. */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /* documentation is in ttinterp.h */ + + FT_EXPORT_DEF( FT_Error ) + TT_RunIns( TT_ExecContext exc ) + { + FT_Long ins_counter = 0; /* executed instructions counter */ + + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + cur = *exc; +#endif + + /* set CVT functions */ + CUR.tt_metrics.ratio = 0; + if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem ) + { + /* non-square pixels, use the stretched routines */ + CUR.func_read_cvt = Read_CVT_Stretched; + CUR.func_write_cvt = Write_CVT_Stretched; + CUR.func_move_cvt = Move_CVT_Stretched; + } + else + { + /* square pixels, use normal routines */ + CUR.func_read_cvt = Read_CVT; + CUR.func_write_cvt = Write_CVT; + CUR.func_move_cvt = Move_CVT; + } + + COMPUTE_Funcs(); + COMPUTE_Round( (FT_Byte)exc->GS.round_state ); + + do + { + CUR.opcode = CUR.code[CUR.IP]; + + if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 ) + { + if ( CUR.IP + 1 > CUR.codeSize ) + goto LErrorCodeOverflow_; + + CUR.length = CUR.code[CUR.IP + 1] + 2; + } + + if ( CUR.IP + CUR.length > CUR.codeSize ) + goto LErrorCodeOverflow_; + + /* First, let's check for empty stack and overflow */ + CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 ); + + /* `args' is the top of the stack once arguments have been popped. */ + /* One can also interpret it as the index of the last argument. */ + if ( CUR.args < 0 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + goto LErrorLabel_; + } + + CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 ); + + /* `new_top' is the new top of the stack, after the instruction's */ + /* execution. `top' will be set to `new_top' after the `switch' */ + /* statement. */ + if ( CUR.new_top > CUR.stackSize ) + { + CUR.error = TT_Err_Stack_Overflow; + goto LErrorLabel_; + } + + CUR.step_ins = TRUE; + CUR.error = TT_Err_Ok; + +#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + { + FT_Long* args = CUR.stack + CUR.args; + FT_Byte opcode = CUR.opcode; + + +#undef ARRAY_BOUND_ERROR +#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref + + + switch ( opcode ) + { + case 0x00: /* SVTCA y */ + case 0x01: /* SVTCA x */ + case 0x02: /* SPvTCA y */ + case 0x03: /* SPvTCA x */ + case 0x04: /* SFvTCA y */ + case 0x05: /* SFvTCA x */ + { + FT_Short AA, BB; + + + AA = (FT_Short)( ( opcode & 1 ) << 14 ); + BB = (FT_Short)( AA ^ 0x4000 ); + + if ( opcode < 4 ) + { + CUR.GS.projVector.x = AA; + CUR.GS.projVector.y = BB; + + CUR.GS.dualVector.x = AA; + CUR.GS.dualVector.y = BB; + } + else + { + GUESS_VECTOR( projVector ); + } + + if ( ( opcode & 2 ) == 0 ) + { + CUR.GS.freeVector.x = AA; + CUR.GS.freeVector.y = BB; + } + else + { + GUESS_VECTOR( freeVector ); + } + + COMPUTE_Funcs(); + } + break; + + case 0x06: /* SPvTL // */ + case 0x07: /* SPvTL + */ + DO_SPVTL + break; + + case 0x08: /* SFvTL // */ + case 0x09: /* SFvTL + */ + DO_SFVTL + break; + + case 0x0A: /* SPvFS */ + DO_SPVFS + break; + + case 0x0B: /* SFvFS */ + DO_SFVFS + break; + + case 0x0C: /* GPV */ + DO_GPV + break; + + case 0x0D: /* GFV */ + DO_GFV + break; + + case 0x0E: /* SFvTPv */ + DO_SFVTPV + break; + + case 0x0F: /* ISECT */ + Ins_ISECT( EXEC_ARG_ args ); + break; + + case 0x10: /* SRP0 */ + DO_SRP0 + break; + + case 0x11: /* SRP1 */ + DO_SRP1 + break; + + case 0x12: /* SRP2 */ + DO_SRP2 + break; + + case 0x13: /* SZP0 */ + Ins_SZP0( EXEC_ARG_ args ); + break; + + case 0x14: /* SZP1 */ + Ins_SZP1( EXEC_ARG_ args ); + break; + + case 0x15: /* SZP2 */ + Ins_SZP2( EXEC_ARG_ args ); + break; + + case 0x16: /* SZPS */ + Ins_SZPS( EXEC_ARG_ args ); + break; + + case 0x17: /* SLOOP */ + DO_SLOOP + break; + + case 0x18: /* RTG */ + DO_RTG + break; + + case 0x19: /* RTHG */ + DO_RTHG + break; + + case 0x1A: /* SMD */ + DO_SMD + break; + + case 0x1B: /* ELSE */ + Ins_ELSE( EXEC_ARG_ args ); + break; + + case 0x1C: /* JMPR */ + DO_JMPR + break; + + case 0x1D: /* SCVTCI */ + DO_SCVTCI + break; + + case 0x1E: /* SSWCI */ + DO_SSWCI + break; + + case 0x1F: /* SSW */ + DO_SSW + break; + + case 0x20: /* DUP */ + DO_DUP + break; + + case 0x21: /* POP */ + /* nothing :-) */ + break; + + case 0x22: /* CLEAR */ + DO_CLEAR + break; + + case 0x23: /* SWAP */ + DO_SWAP + break; + + case 0x24: /* DEPTH */ + DO_DEPTH + break; + + case 0x25: /* CINDEX */ + DO_CINDEX + break; + + case 0x26: /* MINDEX */ + Ins_MINDEX( EXEC_ARG_ args ); + break; + + case 0x27: /* ALIGNPTS */ + Ins_ALIGNPTS( EXEC_ARG_ args ); + break; + + case 0x28: /* ???? */ + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + case 0x29: /* UTP */ + Ins_UTP( EXEC_ARG_ args ); + break; + + case 0x2A: /* LOOPCALL */ + Ins_LOOPCALL( EXEC_ARG_ args ); + break; + + case 0x2B: /* CALL */ + Ins_CALL( EXEC_ARG_ args ); + break; + + case 0x2C: /* FDEF */ + Ins_FDEF( EXEC_ARG_ args ); + break; + + case 0x2D: /* ENDF */ + Ins_ENDF( EXEC_ARG_ args ); + break; + + case 0x2E: /* MDAP */ + case 0x2F: /* MDAP */ + Ins_MDAP( EXEC_ARG_ args ); + break; + + + case 0x30: /* IUP */ + case 0x31: /* IUP */ + Ins_IUP( EXEC_ARG_ args ); + break; + + case 0x32: /* SHP */ + case 0x33: /* SHP */ + Ins_SHP( EXEC_ARG_ args ); + break; + + case 0x34: /* SHC */ + case 0x35: /* SHC */ + Ins_SHC( EXEC_ARG_ args ); + break; + + case 0x36: /* SHZ */ + case 0x37: /* SHZ */ + Ins_SHZ( EXEC_ARG_ args ); + break; + + case 0x38: /* SHPIX */ + Ins_SHPIX( EXEC_ARG_ args ); + break; + + case 0x39: /* IP */ + Ins_IP( EXEC_ARG_ args ); + break; + + case 0x3A: /* MSIRP */ + case 0x3B: /* MSIRP */ + Ins_MSIRP( EXEC_ARG_ args ); + break; + + case 0x3C: /* AlignRP */ + Ins_ALIGNRP( EXEC_ARG_ args ); + break; + + case 0x3D: /* RTDG */ + DO_RTDG + break; + + case 0x3E: /* MIAP */ + case 0x3F: /* MIAP */ + Ins_MIAP( EXEC_ARG_ args ); + break; + + case 0x40: /* NPUSHB */ + Ins_NPUSHB( EXEC_ARG_ args ); + break; + + case 0x41: /* NPUSHW */ + Ins_NPUSHW( EXEC_ARG_ args ); + break; + + case 0x42: /* WS */ + DO_WS + break; + + Set_Invalid_Ref: + CUR.error = TT_Err_Invalid_Reference; + break; + + case 0x43: /* RS */ + DO_RS + break; + + case 0x44: /* WCVTP */ + DO_WCVTP + break; + + case 0x45: /* RCVT */ + DO_RCVT + break; + + case 0x46: /* GC */ + case 0x47: /* GC */ + Ins_GC( EXEC_ARG_ args ); + break; + + case 0x48: /* SCFS */ + Ins_SCFS( EXEC_ARG_ args ); + break; + + case 0x49: /* MD */ + case 0x4A: /* MD */ + Ins_MD( EXEC_ARG_ args ); + break; + + case 0x4B: /* MPPEM */ + DO_MPPEM + break; + + case 0x4C: /* MPS */ + DO_MPS + break; + + case 0x4D: /* FLIPON */ + DO_FLIPON + break; + + case 0x4E: /* FLIPOFF */ + DO_FLIPOFF + break; + + case 0x4F: /* DEBUG */ + DO_DEBUG + break; + + case 0x50: /* LT */ + DO_LT + break; + + case 0x51: /* LTEQ */ + DO_LTEQ + break; + + case 0x52: /* GT */ + DO_GT + break; + + case 0x53: /* GTEQ */ + DO_GTEQ + break; + + case 0x54: /* EQ */ + DO_EQ + break; + + case 0x55: /* NEQ */ + DO_NEQ + break; + + case 0x56: /* ODD */ + DO_ODD + break; + + case 0x57: /* EVEN */ + DO_EVEN + break; + + case 0x58: /* IF */ + Ins_IF( EXEC_ARG_ args ); + break; + + case 0x59: /* EIF */ + /* do nothing */ + break; + + case 0x5A: /* AND */ + DO_AND + break; + + case 0x5B: /* OR */ + DO_OR + break; + + case 0x5C: /* NOT */ + DO_NOT + break; + + case 0x5D: /* DELTAP1 */ + Ins_DELTAP( EXEC_ARG_ args ); + break; + + case 0x5E: /* SDB */ + DO_SDB + break; + + case 0x5F: /* SDS */ + DO_SDS + break; + + case 0x60: /* ADD */ + DO_ADD + break; + + case 0x61: /* SUB */ + DO_SUB + break; + + case 0x62: /* DIV */ + DO_DIV + break; + + case 0x63: /* MUL */ + DO_MUL + break; + + case 0x64: /* ABS */ + DO_ABS + break; + + case 0x65: /* NEG */ + DO_NEG + break; + + case 0x66: /* FLOOR */ + DO_FLOOR + break; + + case 0x67: /* CEILING */ + DO_CEILING + break; + + case 0x68: /* ROUND */ + case 0x69: /* ROUND */ + case 0x6A: /* ROUND */ + case 0x6B: /* ROUND */ + DO_ROUND + break; + + case 0x6C: /* NROUND */ + case 0x6D: /* NROUND */ + case 0x6E: /* NRRUND */ + case 0x6F: /* NROUND */ + DO_NROUND + break; + + case 0x70: /* WCVTF */ + DO_WCVTF + break; + + case 0x71: /* DELTAP2 */ + case 0x72: /* DELTAP3 */ + Ins_DELTAP( EXEC_ARG_ args ); + break; + + case 0x73: /* DELTAC0 */ + case 0x74: /* DELTAC1 */ + case 0x75: /* DELTAC2 */ + Ins_DELTAC( EXEC_ARG_ args ); + break; + + case 0x76: /* SROUND */ + DO_SROUND + break; + + case 0x77: /* S45Round */ + DO_S45ROUND + break; + + case 0x78: /* JROT */ + DO_JROT + break; + + case 0x79: /* JROF */ + DO_JROF + break; + + case 0x7A: /* ROFF */ + DO_ROFF + break; + + case 0x7B: /* ???? */ + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + case 0x7C: /* RUTG */ + DO_RUTG + break; + + case 0x7D: /* RDTG */ + DO_RDTG + break; + + case 0x7E: /* SANGW */ + case 0x7F: /* AA */ + /* nothing - obsolete */ + break; + + case 0x80: /* FLIPPT */ + Ins_FLIPPT( EXEC_ARG_ args ); + break; + + case 0x81: /* FLIPRGON */ + Ins_FLIPRGON( EXEC_ARG_ args ); + break; + + case 0x82: /* FLIPRGOFF */ + Ins_FLIPRGOFF( EXEC_ARG_ args ); + break; + + case 0x83: /* UNKNOWN */ + case 0x84: /* UNKNOWN */ + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + case 0x85: /* SCANCTRL */ + Ins_SCANCTRL( EXEC_ARG_ args ); + break; + + case 0x86: /* SDPVTL */ + case 0x87: /* SDPVTL */ + Ins_SDPVTL( EXEC_ARG_ args ); + break; + + case 0x88: /* GETINFO */ + Ins_GETINFO( EXEC_ARG_ args ); + break; + + case 0x89: /* IDEF */ + Ins_IDEF( EXEC_ARG_ args ); + break; + + case 0x8A: /* ROLL */ + Ins_ROLL( EXEC_ARG_ args ); + break; + + case 0x8B: /* MAX */ + DO_MAX + break; + + case 0x8C: /* MIN */ + DO_MIN + break; + + case 0x8D: /* SCANTYPE */ + Ins_SCANTYPE( EXEC_ARG_ args ); + break; + + case 0x8E: /* INSTCTRL */ + Ins_INSTCTRL( EXEC_ARG_ args ); + break; + + case 0x8F: + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + default: + if ( opcode >= 0xE0 ) + Ins_MIRP( EXEC_ARG_ args ); + else if ( opcode >= 0xC0 ) + Ins_MDRP( EXEC_ARG_ args ); + else if ( opcode >= 0xB8 ) + Ins_PUSHW( EXEC_ARG_ args ); + else if ( opcode >= 0xB0 ) + Ins_PUSHB( EXEC_ARG_ args ); + else + Ins_UNKNOWN( EXEC_ARG_ args ); + } + + } + +#else + + Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] ); + +#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */ + + if ( CUR.error != TT_Err_Ok ) + { + switch ( CUR.error ) + { + case TT_Err_Invalid_Opcode: /* looking for redefined instructions */ + { + TT_DefRecord* def = CUR.IDefs; + TT_DefRecord* limit = def + CUR.numIDefs; + + + for ( ; def < limit; def++ ) + { + if ( def->active && CUR.opcode == (FT_Byte)def->opc ) + { + TT_CallRec* callrec; + + + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Invalid_Reference; + goto LErrorLabel_; + } + + callrec = &CUR.callStack[CUR.callTop]; + + callrec->Caller_Range = CUR.curRange; + callrec->Caller_IP = CUR.IP + 1; + callrec->Cur_Count = 1; + callrec->Cur_Restart = def->start; + + if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE ) + goto LErrorLabel_; + + goto LSuiteLabel_; + } + } + } + + CUR.error = TT_Err_Invalid_Opcode; + goto LErrorLabel_; + +#if 0 + break; /* Unreachable code warning suppression. */ + /* Leave to remind in case a later change the editor */ + /* to consider break; */ +#endif + + default: + goto LErrorLabel_; + +#if 0 + break; +#endif + } + } + + CUR.top = CUR.new_top; + + if ( CUR.step_ins ) + CUR.IP += CUR.length; + + /* increment instruction counter and check if we didn't */ + /* run this program for too long (e.g. infinite loops). */ + if ( ++ins_counter > MAX_RUNNABLE_OPCODES ) + return TT_Err_Execution_Too_Long; + + LSuiteLabel_: + if ( CUR.IP >= CUR.codeSize ) + { + if ( CUR.callTop > 0 ) + { + CUR.error = TT_Err_Code_Overflow; + goto LErrorLabel_; + } + else + goto LNo_Error_; + } + } while ( !CUR.instruction_trap ); + + LNo_Error_: + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + *exc = cur; +#endif + + return TT_Err_Ok; + + LErrorCodeOverflow_: + CUR.error = TT_Err_Code_Overflow; + + LErrorLabel_: + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + *exc = cur; +#endif + + return CUR.error; + } + + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttinterp.h b/Utilities/vtkfreetype/src/truetype/ttinterp.h new file mode 100644 index 0000000..eb0bb0b --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttinterp.h @@ -0,0 +1,318 @@ +/***************************************************************************/ +/* */ +/* ttinterp.h */ +/* */ +/* TrueType bytecode interpreter (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTINTERP_H__ +#define __TTINTERP_H__ + + +#include <ft2build.h> +#include "ttobjs.h" + + +FT_BEGIN_HEADER + + +#ifndef TT_CONFIG_OPTION_STATIC_INTEPRETER /* indirect implementation */ + +#define EXEC_OP_ TT_ExecContext exc, +#define EXEC_OP TT_ExecContext exc +#define EXEC_ARG_ exc, +#define EXEC_ARG exc + +#else /* static implementation */ + +#define EXEC_OP_ /* void */ +#define EXEC_OP /* void */ +#define EXEC_ARG_ /* void */ +#define EXEC_ARG /* void */ + +#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */ + + + /*************************************************************************/ + /* */ + /* Rounding mode constants. */ + /* */ +#define TT_Round_Off 5 +#define TT_Round_To_Half_Grid 0 +#define TT_Round_To_Grid 1 +#define TT_Round_To_Double_Grid 2 +#define TT_Round_Up_To_Grid 4 +#define TT_Round_Down_To_Grid 3 +#define TT_Round_Super 6 +#define TT_Round_Super_45 7 + + + /*************************************************************************/ + /* */ + /* Function types used by the interpreter, depending on various modes */ + /* (e.g. the rounding mode, whether to render a vertical or horizontal */ + /* line etc). */ + /* */ + /*************************************************************************/ + + /* Rounding function */ + typedef FT_F26Dot6 + (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ); + + /* Point displacement along the freedom vector routine */ + typedef void + (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone zone, + FT_UShort point, + FT_F26Dot6 distance ); + + /* Distance projection along one of the projection vectors */ + typedef FT_F26Dot6 + (*TT_Project_Func)( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ); + + /* reading a cvt value. Take care of non-square pixels if necessary */ + typedef FT_F26Dot6 + (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong idx ); + + /* setting or moving a cvt value. Take care of non-square pixels */ + /* if necessary */ + typedef void + (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong idx, + FT_F26Dot6 value ); + + + /*************************************************************************/ + /* */ + /* This structure defines a call record, used to manage function calls. */ + /* */ + typedef struct TT_CallRec_ + { + FT_Int Caller_Range; + FT_Long Caller_IP; + FT_Long Cur_Count; + FT_Long Cur_Restart; + + } TT_CallRec, *TT_CallStack; + + + /*************************************************************************/ + /* */ + /* The main structure for the interpreter which collects all necessary */ + /* variables and states. */ + /* */ + typedef struct TT_ExecContextRec_ + { + TT_Face face; + TT_Size size; + FT_Memory memory; + + /* instructions state */ + + FT_Error error; /* last execution error */ + + FT_Long top; /* top of exec. stack */ + + FT_UInt stackSize; /* size of exec. stack */ + FT_Long* stack; /* current exec. stack */ + + FT_Long args; + FT_UInt new_top; /* new top after exec. */ + + TT_GlyphZoneRec zp0, /* zone records */ + zp1, + zp2, + pts, + twilight; + + FT_Size_Metrics metrics; + TT_Size_Metrics tt_metrics; /* size metrics */ + + TT_GraphicsState GS; /* current graphics state */ + + FT_Int curRange; /* current code range number */ + FT_Byte* code; /* current code range */ + FT_Long IP; /* current instruction pointer */ + FT_Long codeSize; /* size of current range */ + + FT_Byte opcode; /* current opcode */ + FT_Int length; /* length of current opcode */ + + FT_Bool step_ins; /* true if the interpreter must */ + /* increment IP after ins. exec */ + FT_Long cvtSize; + FT_Long* cvt; + + FT_UInt glyphSize; /* glyph instructions buffer size */ + FT_Byte* glyphIns; /* glyph instructions buffer */ + + FT_UInt numFDefs; /* number of function defs */ + FT_UInt maxFDefs; /* maximum number of function defs */ + TT_DefArray FDefs; /* table of FDefs entries */ + + FT_UInt numIDefs; /* number of instruction defs */ + FT_UInt maxIDefs; /* maximum number of ins defs */ + TT_DefArray IDefs; /* table of IDefs entries */ + + FT_UInt maxFunc; /* maximum function index */ + FT_UInt maxIns; /* maximum instruction index */ + + FT_Int callTop, /* top of call stack during execution */ + callSize; /* size of call stack */ + TT_CallStack callStack; /* call stack */ + + FT_UShort maxPoints; /* capacity of this context's `pts' */ + FT_Short maxContours; /* record, expressed in points and */ + /* contours. */ + + TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */ + /* useful for the debugger */ + + FT_UShort storeSize; /* size of current storage */ + FT_Long* storage; /* storage area */ + + FT_F26Dot6 period; /* values used for the */ + FT_F26Dot6 phase; /* `SuperRounding' */ + FT_F26Dot6 threshold; + +#if 0 + /* this seems to be unused */ + FT_Int cur_ppem; /* ppem along the current proj vector */ +#endif + + FT_Bool instruction_trap; /* If `True', the interpreter will */ + /* exit after each instruction */ + + TT_GraphicsState default_GS; /* graphics state resulting from */ + /* the prep program */ + FT_Bool is_composite; /* true if the glyph is composite */ + FT_Bool pedantic_hinting; /* true if pedantic interpretation */ + + /* latest interpreter additions */ + + FT_Long F_dot_P; /* dot product of freedom and projection */ + /* vectors */ + TT_Round_Func func_round; /* current rounding function */ + + TT_Project_Func func_project, /* current projection function */ + func_dualproj, /* current dual proj. function */ + func_freeProj; /* current freedom proj. func */ + + TT_Move_Func func_move; /* current point move function */ + TT_Move_Func func_move_orig; /* move original position function */ + + TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */ + TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */ + TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */ + + FT_ULong loadSize; + TT_SubGlyph_Stack loadStack; /* loading subglyph stack */ + + } TT_ExecContextRec; + + + extern const TT_GraphicsState tt_default_graphics_state; + + + FT_LOCAL( FT_Error ) + TT_Goto_CodeRange( TT_ExecContext exec, + FT_Int range, + FT_Long IP ); + + FT_LOCAL( FT_Error ) + TT_Set_CodeRange( TT_ExecContext exec, + FT_Int range, + void* base, + FT_Long length ); + + FT_LOCAL( FT_Error ) + TT_Clear_CodeRange( TT_ExecContext exec, + FT_Int range ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_New_Context */ + /* */ + /* <Description> */ + /* Queries the face context for a given font. Note that there is */ + /* now a _single_ execution context in the TrueType driver which is */ + /* shared among faces. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* <Return> */ + /* A handle to the execution context. Initialized for `face'. */ + /* */ + /* <Note> */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_EXPORT( TT_ExecContext ) + TT_New_Context( TT_Face face ); + + + FT_LOCAL( FT_Error ) + TT_Done_Context( TT_ExecContext exec ); + + FT_LOCAL( FT_Error ) + TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ); + + FT_LOCAL( FT_Error ) + TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ); + + FT_LOCAL( FT_Error ) + TT_Save_Context( TT_ExecContext exec, + TT_Size ins ); + + FT_LOCAL( FT_Error ) + TT_Run_Context( TT_ExecContext exec, + FT_Bool debug ); + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* TT_RunIns */ + /* */ + /* <Description> */ + /* Executes one or more instruction in the execution context. This */ + /* is the main function of the TrueType opcode interpreter. */ + /* */ + /* <Input> */ + /* exec :: A handle to the target execution context. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only the object manager and debugger should call this function. */ + /* */ + /* This function is publicly exported because it is directly */ + /* invoked by the TrueType debugger. */ + /* */ + FT_EXPORT( FT_Error ) + TT_RunIns( TT_ExecContext exec ); + + +FT_END_HEADER + +#endif /* __TTINTERP_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttobjs.c b/Utilities/vtkfreetype/src/truetype/ttobjs.c new file mode 100644 index 0000000..3914ba5 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttobjs.c @@ -0,0 +1,901 @@ +/***************************************************************************/ +/* */ +/* ttobjs.c */ +/* */ +/* Objects manager (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_IDS_H +#include FT_TRUETYPE_TAGS_H +#include FT_INTERNAL_SFNT_H + +#include "ttgload.h" +#include "ttpload.h" + +#include "tterrors.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING +#include FT_TRUETYPE_UNPATENTED_H +#endif + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include "ttgxvar.h" +#endif + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttobjs + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /*************************************************************************/ + /* */ + /* GLYPH ZONE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_glyphzone_done */ + /* */ + /* <Description> */ + /* Deallocates a glyph zone. */ + /* */ + /* <Input> */ + /* zone :: A pointer to the target glyph zone. */ + /* */ + FT_LOCAL_DEF( void ) + tt_glyphzone_done( TT_GlyphZone zone ) + { + FT_Memory memory = zone->memory; + + + if ( memory ) + { + FT_FREE( zone->contours ); + FT_FREE( zone->tags ); + FT_FREE( zone->cur ); + FT_FREE( zone->org ); + + zone->max_points = zone->n_points = 0; + zone->max_contours = zone->n_contours = 0; + zone->memory = NULL; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_glyphzone_new */ + /* */ + /* <Description> */ + /* Allocates a new glyph zone. */ + /* */ + /* <Input> */ + /* memory :: A handle to the current memory object. */ + /* */ + /* maxPoints :: The capacity of glyph zone in points. */ + /* */ + /* maxContours :: The capacity of glyph zone in contours. */ + /* */ + /* <Output> */ + /* zone :: A pointer to the target glyph zone record. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_glyphzone_new( FT_Memory memory, + FT_UShort maxPoints, + FT_Short maxContours, + TT_GlyphZone zone ) + { + FT_Error error; + + + if ( maxPoints > 0 ) + maxPoints += 2; + + FT_MEM_ZERO( zone, sizeof ( *zone ) ); + zone->memory = memory; + + if ( FT_NEW_ARRAY( zone->org, maxPoints * 2 ) || + FT_NEW_ARRAY( zone->cur, maxPoints * 2 ) || + FT_NEW_ARRAY( zone->tags, maxPoints ) || + FT_NEW_ARRAY( zone->contours, maxContours ) ) + { + tt_glyphzone_done( zone ); + } + + return error; + } +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_init */ + /* */ + /* <Description> */ + /* Initializes a given TrueType face object. */ + /* */ + /* <Input> */ + /* stream :: The source font stream. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* <InOut> */ + /* face :: The newly built face object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_init( FT_Stream stream, + FT_Face ttface, /* TT_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Library library; + SFNT_Service sfnt; + TT_Face face = (TT_Face)ttface; + + + library = face->root.driver->root.library; + sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); + if ( !sfnt ) + goto Bad_Format; + + /* create input stream from resource */ + if ( FT_STREAM_SEEK( 0 ) ) + goto Exit; + + /* check that we have a valid TrueType file */ + error = sfnt->init_face( stream, face, face_index, num_params, params ); + if ( error ) + goto Exit; + + /* We must also be able to accept Mac/GX fonts, as well as OT ones */ + if ( face->format_tag != 0x00010000L && /* MS fonts */ + face->format_tag != TTAG_true ) /* Mac fonts */ + { + FT_TRACE2(( "[not a valid TTF font]\n" )); + goto Bad_Format; + } + + /* If we are performing a simple font format check, exit immediately */ + if ( face_index < 0 ) + return TT_Err_Ok; + + /* Load font directory */ + error = sfnt->load_face( stream, face, face_index, num_params, params ); + if ( error ) + goto Exit; + + if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE ) + { + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + if ( !face->root.internal->incremental_interface ) + error = tt_face_load_loca( face, stream ); + if ( !error ) + error = tt_face_load_cvt( face, stream ) || + tt_face_load_fpgm( face, stream ); + +#else + + if ( !error ) + error = tt_face_load_loca( face, stream ) || + tt_face_load_cvt( face, stream ) || + tt_face_load_fpgm( face, stream ); + +#endif + + } + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + + /* Determine whether unpatented hinting is to be used for this face. */ + face->unpatented_hinting = FT_BOOL + ( library->debug_hooks[ FT_DEBUG_HOOK_UNPATENTED_HINTING ] != NULL ); + + { + int i; + + + for ( i = 0; i < num_params && !face->unpatented_hinting; i++ ) + if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING ) + face->unpatented_hinting = TRUE; + } + +#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ + + /* initialize standard glyph loading routines */ + TT_Init_Glyph_Loading( face ); + + Exit: + return error; + + Bad_Format: + error = TT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_done */ + /* */ + /* <Description> */ + /* Finalizes a given face object. */ + /* */ + /* <Input> */ + /* face :: A pointer to the face object to destroy. */ + /* */ + FT_LOCAL_DEF( void ) + tt_face_done( FT_Face ttface ) /* TT_Face */ + { + TT_Face face = (TT_Face)ttface; + FT_Memory memory = face->root.memory; + FT_Stream stream = face->root.stream; + + SFNT_Service sfnt = (SFNT_Service)face->sfnt; + + + /* for `extended TrueType formats' (i.e. compressed versions) */ + if ( face->extra.finalizer ) + face->extra.finalizer( face->extra.data ); + + if ( sfnt ) + sfnt->done_face( face ); + + /* freeing the locations table */ + FT_FREE( face->glyph_locations ); + face->num_locations = 0; + + /* freeing the CVT */ + FT_FREE( face->cvt ); + face->cvt_size = 0; + + /* freeing the programs */ + FT_FRAME_RELEASE( face->font_program ); + FT_FRAME_RELEASE( face->cvt_program ); + face->font_program_size = 0; + face->cvt_program_size = 0; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + tt_done_blend( memory, face->blend ); + face->blend = NULL; +#endif + } + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_size_init */ + /* */ + /* <Description> */ + /* Initializes a new TrueType size object. */ + /* */ + /* <InOut> */ + /* size :: A handle to the size object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_size_init( FT_Size ttsize ) /* TT_Size */ + { + TT_Size size = (TT_Size)ttsize; + FT_Error error = TT_Err_Ok; + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + TT_Face face = (TT_Face)size->root.face; + FT_Memory memory = face->root.memory; + FT_Int i; + + TT_ExecContext exec; + FT_UShort n_twilight; + TT_MaxProfile* maxp = &face->max_profile; + + + size->ttmetrics.valid = FALSE; + + size->max_function_defs = maxp->maxFunctionDefs; + size->max_instruction_defs = maxp->maxInstructionDefs; + + size->num_function_defs = 0; + size->num_instruction_defs = 0; + + size->max_func = 0; + size->max_ins = 0; + + size->cvt_size = face->cvt_size; + size->storage_size = maxp->maxStorage; + + /* Set default metrics */ + { + FT_Size_Metrics* metrics = &size->root.metrics; + TT_Size_Metrics* metrics2 = &size->ttmetrics; + + + metrics->x_ppem = 0; + metrics->y_ppem = 0; + + metrics2->rotated = FALSE; + metrics2->stretched = FALSE; + + /* set default compensation (all 0) */ + for ( i = 0; i < 4; i++ ) + metrics2->compensations[i] = 0; + } + + /* allocate function defs, instruction defs, cvt, and storage area */ + if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || + FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || + FT_NEW_ARRAY( size->cvt, size->cvt_size ) || + FT_NEW_ARRAY( size->storage, size->storage_size ) ) + + goto Fail_Memory; + + /* reserve twilight zone */ + n_twilight = maxp->maxTwilightPoints; + error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); + if ( error ) + goto Fail_Memory; + + size->twilight.n_points = n_twilight; + + /* set `face->interpreter' according to the debug hook present */ + { + FT_Library library = face->root.driver->root.library; + + + face->interpreter = (TT_Interpreter) + library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; + if ( !face->interpreter ) + face->interpreter = (TT_Interpreter)TT_RunIns; + } + + /* Fine, now execute the font program! */ + exec = size->context; + /* size objects used during debugging have their own context */ + if ( !size->debug ) + exec = TT_New_Context( face ); + + if ( !exec ) + { + error = TT_Err_Could_Not_Find_Context; + goto Fail_Memory; + } + + size->GS = tt_default_graphics_state; + TT_Load_Context( exec, face, size ); + + exec->callTop = 0; + exec->top = 0; + + exec->period = 64; + exec->phase = 0; + exec->threshold = 0; + + { + FT_Size_Metrics* metrics = &exec->metrics; + TT_Size_Metrics* tt_metrics = &exec->tt_metrics; + + + metrics->x_ppem = 0; + metrics->y_ppem = 0; + metrics->x_scale = 0; + metrics->y_scale = 0; + + tt_metrics->ppem = 0; + tt_metrics->scale = 0; + tt_metrics->ratio = 0x10000L; + } + + exec->instruction_trap = FALSE; + + exec->cvtSize = size->cvt_size; + exec->cvt = size->cvt; + + exec->F_dot_P = 0x10000L; + + /* allow font program execution */ + TT_Set_CodeRange( exec, + tt_coderange_font, + face->font_program, + face->font_program_size ); + + /* disable CVT and glyph programs coderange */ + TT_Clear_CodeRange( exec, tt_coderange_cvt ); + TT_Clear_CodeRange( exec, tt_coderange_glyph ); + + if ( face->font_program_size > 0 ) + { + error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); + if ( !error ) + error = face->interpreter( exec ); + + if ( error ) + goto Fail_Exec; + } + else + error = TT_Err_Ok; + + TT_Save_Context( exec, size ); + + if ( !size->debug ) + TT_Done_Context( exec ); + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + size->ttmetrics.valid = FALSE; + return error; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + Fail_Exec: + if ( !size->debug ) + TT_Done_Context( exec ); + + Fail_Memory: + + tt_size_done( ttsize ); + return error; + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_size_done */ + /* */ + /* <Description> */ + /* The TrueType size object finalizer. */ + /* */ + /* <Input> */ + /* size :: A handle to the target size object. */ + /* */ + FT_LOCAL_DEF( void ) + tt_size_done( FT_Size ttsize ) /* TT_Size */ + { + TT_Size size = (TT_Size)ttsize; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_Memory memory = size->root.face->memory; + + + if ( size->debug ) + { + /* the debug context must be deleted by the debugger itself */ + size->context = NULL; + size->debug = FALSE; + } + + FT_FREE( size->cvt ); + size->cvt_size = 0; + + /* free storage area */ + FT_FREE( size->storage ); + size->storage_size = 0; + + /* twilight zone */ + tt_glyphzone_done( &size->twilight ); + + FT_FREE( size->function_defs ); + FT_FREE( size->instruction_defs ); + + size->num_function_defs = 0; + size->max_function_defs = 0; + size->num_instruction_defs = 0; + size->max_instruction_defs = 0; + + size->max_func = 0; + size->max_ins = 0; + +#endif + + size->ttmetrics.valid = FALSE; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Reset_Outline_Size */ + /* */ + /* <Description> */ + /* Resets a TrueType outline size when resolutions and character */ + /* dimensions have been changed. */ + /* */ + /* <Input> */ + /* size :: A handle to the target size object. */ + /* */ + static FT_Error + Reset_Outline_Size( TT_Size size ) + { + TT_Face face; + FT_Error error = TT_Err_Ok; + + FT_Size_Metrics* metrics; + + + if ( size->ttmetrics.valid ) + return TT_Err_Ok; + + face = (TT_Face)size->root.face; + + metrics = &size->metrics; + + if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) + return TT_Err_Invalid_PPem; + + /* compute new transformation */ + if ( metrics->x_ppem >= metrics->y_ppem ) + { + size->ttmetrics.scale = metrics->x_scale; + size->ttmetrics.ppem = metrics->x_ppem; + size->ttmetrics.x_ratio = 0x10000L; + size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem, + 0x10000L, + metrics->x_ppem ); + } + else + { + size->ttmetrics.scale = metrics->y_scale; + size->ttmetrics.ppem = metrics->y_ppem; + size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem, + 0x10000L, + metrics->y_ppem ); + size->ttmetrics.y_ratio = 0x10000L; + } + + /* Compute root ascender, descender, text height, and max_advance */ + metrics->ascender = + FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); + metrics->descender = + FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); + metrics->height = + FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); + metrics->max_advance = + FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, + metrics->x_scale ) ); + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + /* set to `invalid' by default */ + size->strike_index = 0xFFFFU; +#endif + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + { + TT_ExecContext exec; + FT_UInt i, j; + + + /* Scale the cvt values to the new ppem. */ + /* We use by default the y ppem to scale the CVT. */ + for ( i = 0; i < size->cvt_size; i++ ) + size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); + + /* All twilight points are originally zero */ + for ( j = 0; j < (FT_UInt)size->twilight.n_points; j++ ) + { + size->twilight.org[j].x = 0; + size->twilight.org[j].y = 0; + size->twilight.cur[j].x = 0; + size->twilight.cur[j].y = 0; + } + + /* clear storage area */ + for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) + size->storage[i] = 0; + + size->GS = tt_default_graphics_state; + + /* get execution context and run prep program */ + if ( size->debug ) + exec = size->context; + else + exec = TT_New_Context( face ); + /* debugging instances have their own context */ + + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + + TT_Load_Context( exec, face, size ); + + TT_Set_CodeRange( exec, + tt_coderange_cvt, + face->cvt_program, + face->cvt_program_size ); + + TT_Clear_CodeRange( exec, tt_coderange_glyph ); + + exec->instruction_trap = FALSE; + + exec->top = 0; + exec->callTop = 0; + + if ( face->cvt_program_size > 0 ) + { + error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); + if ( error ) + goto End; + + if ( !size->debug ) + error = face->interpreter( exec ); + } + else + error = TT_Err_Ok; + + size->GS = exec->GS; + /* save default graphics state */ + + End: + TT_Save_Context( exec, size ); + + if ( !size->debug ) + TT_Done_Context( exec ); + /* debugging instances keep their context */ + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + if ( !error ) + size->ttmetrics.valid = TRUE; + + return error; + } + + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Reset_SBit_Size */ + /* */ + /* <Description> */ + /* Resets a TrueType sbit size when resolutions and character */ + /* dimensions have been changed. */ + /* */ + /* <Input> */ + /* size :: A handle to the target size object. */ + /* */ + static FT_Error + Reset_SBit_Size( TT_Size size ) + { + TT_Face face; + FT_Error error = TT_Err_Ok; + + FT_ULong strike_index; + FT_Size_Metrics* metrics; + FT_Size_Metrics* sbit_metrics; + SFNT_Service sfnt; + + + metrics = &size->metrics; + + if ( size->strike_index != 0xFFFFU ) + return TT_Err_Ok; + + face = (TT_Face)size->root.face; + sfnt = (SFNT_Service)face->sfnt; + + sbit_metrics = &size->strike_metrics; + + error = sfnt->set_sbit_strike( face, + metrics->x_ppem, metrics->y_ppem, + &strike_index ); + + if ( !error ) + { + TT_SBit_Strike strike = face->sbit_strikes + strike_index; + + + sbit_metrics->x_ppem = metrics->x_ppem; + sbit_metrics->y_ppem = metrics->y_ppem; +#if 0 + /* + * sbit_metrics->?_scale + * are not used now. + */ + sbit_metrics->x_scale = 1 << 16; + sbit_metrics->y_scale = 1 << 16; +#endif + + sbit_metrics->ascender = strike->hori.ascender << 6; + sbit_metrics->descender = strike->hori.descender << 6; + + /* XXX: Is this correct? */ + sbit_metrics->height = sbit_metrics->ascender - + sbit_metrics->descender; + + /* XXX: Is this correct? */ + sbit_metrics->max_advance = ( strike->hori.min_origin_SB + + strike->hori.max_width + + strike->hori.min_advance_SB ) << 6; + + size->strike_index = (FT_UInt)strike_index; + } + else + { + size->strike_index = 0xFFFFU; + + sbit_metrics->x_ppem = 0; + sbit_metrics->y_ppem = 0; + sbit_metrics->ascender = 0; + sbit_metrics->descender = 0; + sbit_metrics->height = 0; + sbit_metrics->max_advance = 0; + } + + return error; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_size_reset */ + /* */ + /* <Description> */ + /* Resets a TrueType size when resolutions and character dimensions */ + /* have been changed. */ + /* */ + /* <Input> */ + /* size :: A handle to the target size object. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_size_reset( TT_Size size ) + { + FT_Face face; + FT_Error error = TT_Err_Ok; + + + face = size->root.face; + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + { + if ( !size->ttmetrics.valid ) + error = Reset_Outline_Size( size ); + + if ( error ) + return error; + } + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) + { + if ( size->strike_index == 0xFFFFU ) + error = Reset_SBit_Size( size ); + + if ( !error && !( face->face_flags & FT_FACE_FLAG_SCALABLE ) ) + size->root.metrics = size->strike_metrics; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + return TT_Err_Ok; + else + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_driver_init */ + /* */ + /* <Description> */ + /* Initializes a given TrueType driver object. */ + /* */ + /* <Input> */ + /* driver :: A handle to the target driver object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_driver_init( FT_Module driver ) /* TT_Driver */ + { + FT_Error error; + + + /* set `extra' in glyph loader */ + error = FT_GlyphLoader_CreateExtra( FT_DRIVER( driver )->glyph_loader ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_driver_done */ + /* */ + /* <Description> */ + /* Finalizes a given TrueType driver. */ + /* */ + /* <Input> */ + /* driver :: A handle to the target TrueType driver. */ + /* */ + FT_LOCAL_DEF( void ) + tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ + { +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + TT_Driver driver = (TT_Driver)ttdriver; + + + /* destroy the execution context */ + if ( driver->context ) + { + TT_Destroy_Context( driver->context, driver->root.root.memory ); + driver->context = NULL; + } +#else + FT_UNUSED( ttdriver ); +#endif + + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttobjs.h b/Utilities/vtkfreetype/src/truetype/ttobjs.h new file mode 100644 index 0000000..423d3f0 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttobjs.h @@ -0,0 +1,437 @@ +/***************************************************************************/ +/* */ +/* ttobjs.h */ +/* */ +/* Objects manager (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTOBJS_H__ +#define __TTOBJS_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_TRUETYPE_TYPES_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* TT_Driver */ + /* */ + /* <Description> */ + /* A handle to a TrueType driver object. */ + /* */ + typedef struct TT_DriverRec_* TT_Driver; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* TT_Instance */ + /* */ + /* <Description> */ + /* A handle to a TrueType size object. */ + /* */ + typedef struct TT_SizeRec_* TT_Size; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* TT_GlyphSlot */ + /* */ + /* <Description> */ + /* A handle to a TrueType glyph slot object. */ + /* */ + /* <Note> */ + /* This is a direct typedef of FT_GlyphSlot, as there is nothing */ + /* specific about the TrueType glyph slot. */ + /* */ + typedef FT_GlyphSlot TT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* TT_GraphicsState */ + /* */ + /* <Description> */ + /* The TrueType graphics state used during bytecode interpretation. */ + /* */ + typedef struct TT_GraphicsState_ + { + FT_UShort rp0; + FT_UShort rp1; + FT_UShort rp2; + + FT_UnitVector dualVector; + FT_UnitVector projVector; + FT_UnitVector freeVector; + +#ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING + FT_Bool both_x_axis; +#endif + + FT_Long loop; + FT_F26Dot6 minimum_distance; + FT_Int round_state; + + FT_Bool auto_flip; + FT_F26Dot6 control_value_cutin; + FT_F26Dot6 single_width_cutin; + FT_F26Dot6 single_width_value; + FT_Short delta_base; + FT_Short delta_shift; + + FT_Byte instruct_control; + FT_Bool scan_control; + FT_Int scan_type; + + FT_UShort gep0; + FT_UShort gep1; + FT_UShort gep2; + + } TT_GraphicsState; + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_LOCAL( void ) + tt_glyphzone_done( TT_GlyphZone zone ); + + FT_LOCAL( FT_Error ) + tt_glyphzone_new( FT_Memory memory, + FT_UShort maxPoints, + FT_Short maxContours, + TT_GlyphZone zone ); + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + + + /*************************************************************************/ + /* */ + /* EXECUTION SUBTABLES */ + /* */ + /* These sub-tables relate to instruction execution. */ + /* */ + /*************************************************************************/ + + +#define TT_MAX_CODE_RANGES 3 + + + /*************************************************************************/ + /* */ + /* There can only be 3 active code ranges at once: */ + /* - the Font Program */ + /* - the CVT Program */ + /* - a glyph's instructions set */ + /* */ + typedef enum TT_CodeRange_Tag_ + { + tt_coderange_none = 0, + tt_coderange_font, + tt_coderange_cvt, + tt_coderange_glyph + + } TT_CodeRange_Tag; + + + typedef struct TT_CodeRange_ + { + FT_Byte* base; + FT_ULong size; + + } TT_CodeRange; + + typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES]; + + + /*************************************************************************/ + /* */ + /* Defines a function/instruction definition record. */ + /* */ + typedef struct TT_DefRecord_ + { + FT_Int range; /* in which code range is it located? */ + FT_Long start; /* where does it start? */ + FT_UInt opc; /* function #, or instruction code */ + FT_Bool active; /* is it active? */ + + } TT_DefRecord, *TT_DefArray; + + + /*************************************************************************/ + /* */ + /* Subglyph transformation record. */ + /* */ + typedef struct TT_Transform_ + { + FT_Fixed xx, xy; /* transformation matrix coefficients */ + FT_Fixed yx, yy; + FT_F26Dot6 ox, oy; /* offsets */ + + } TT_Transform; + + + /*************************************************************************/ + /* */ + /* Subglyph loading record. Used to load composite components. */ + /* */ + typedef struct TT_SubglyphRec_ + { + FT_Long index; /* subglyph index; initialized with -1 */ + FT_Bool is_scaled; /* is the subglyph scaled? */ + FT_Bool is_hinted; /* should it be hinted? */ + FT_Bool preserve_pps; /* preserve phantom points? */ + + FT_Long file_offset; + + FT_BBox bbox; + FT_Pos left_bearing; + FT_Pos advance; + + TT_GlyphZoneRec zone; + + FT_Long arg1; /* first argument */ + FT_Long arg2; /* second argument */ + + FT_UShort element_flag; /* current load element flag */ + + TT_Transform transform; /* transformation matrix */ + + FT_Vector pp1, pp2; /* phantom points (horizontal) */ + FT_Vector pp3, pp4; /* phantom points (vertical) */ + + } TT_SubGlyphRec, *TT_SubGlyph_Stack; + + + /*************************************************************************/ + /* */ + /* A note regarding non-squared pixels: */ + /* */ + /* (This text will probably go into some docs at some time; for now, it */ + /* is kept here to explain some definitions in the TIns_Metrics */ + /* record). */ + /* */ + /* The CVT is a one-dimensional array containing values that control */ + /* certain important characteristics in a font, like the height of all */ + /* capitals, all lowercase letter, default spacing or stem width/height. */ + /* */ + /* These values are found in FUnits in the font file, and must be scaled */ + /* to pixel coordinates before being used by the CVT and glyph programs. */ + /* Unfortunately, when using distinct x and y resolutions (or distinct x */ + /* and y pointsizes), there are two possible scalings. */ + /* */ + /* A first try was to implement a `lazy' scheme where all values were */ + /* scaled when first used. However, while some values are always used */ + /* in the same direction, some others are used under many different */ + /* circumstances and orientations. */ + /* */ + /* I have found a simpler way to do the same, and it even seems to work */ + /* in most of the cases: */ + /* */ + /* - All CVT values are scaled to the maximum ppem size. */ + /* */ + /* - When performing a read or write in the CVT, a ratio factor is used */ + /* to perform adequate scaling. Example: */ + /* */ + /* x_ppem = 14 */ + /* y_ppem = 10 */ + /* */ + /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */ + /* entries are scaled to it. */ + /* */ + /* x_ratio = 1.0 */ + /* y_ratio = y_ppem/ppem (< 1.0) */ + /* */ + /* We compute the current ratio like: */ + /* */ + /* - If projVector is horizontal, */ + /* ratio = x_ratio = 1.0 */ + /* */ + /* - if projVector is vertical, */ + /* ratio = y_ratio */ + /* */ + /* - else, */ + /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */ + /* */ + /* Reading a cvt value returns */ + /* ratio * cvt[index] */ + /* */ + /* Writing a cvt value in pixels: */ + /* cvt[index] / ratio */ + /* */ + /* The current ppem is simply */ + /* ratio * ppem */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Metrics used by the TrueType size and context objects. */ + /* */ + typedef struct TT_Size_Metrics_ + { + /* for non-square pixels */ + FT_Long x_ratio; + FT_Long y_ratio; + + FT_UShort ppem; /* maximum ppem size */ + FT_Long ratio; /* current ratio */ + FT_Fixed scale; + + FT_F26Dot6 compensations[4]; /* device-specific compensations */ + + FT_Bool valid; + + FT_Bool rotated; /* `is the glyph rotated?'-flag */ + FT_Bool stretched; /* `is the glyph stretched?'-flag */ + + } TT_Size_Metrics; + + + /*************************************************************************/ + /* */ + /* TrueType size class. */ + /* */ + typedef struct TT_SizeRec_ + { + FT_SizeRec root; + + FT_Size_Metrics metrics; /* slightly different from the root metrics */ + TT_Size_Metrics ttmetrics; + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + FT_UInt strike_index; /* 0xFFFF to indicate invalid */ + FT_Size_Metrics strike_metrics; /* current strike's metrics */ + +#endif + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_UInt num_function_defs; /* number of function definitions */ + FT_UInt max_function_defs; + TT_DefArray function_defs; /* table of function definitions */ + + FT_UInt num_instruction_defs; /* number of ins. definitions */ + FT_UInt max_instruction_defs; + TT_DefArray instruction_defs; /* table of ins. definitions */ + + FT_UInt max_func; + FT_UInt max_ins; + + TT_CodeRangeTable codeRangeTable; + + TT_GraphicsState GS; + + FT_ULong cvt_size; /* the scaled control value table */ + FT_Long* cvt; + + FT_UShort storage_size; /* The storage area is now part of */ + FT_Long* storage; /* the instance */ + + TT_GlyphZoneRec twilight; /* The instance's twilight zone */ + + /* debugging variables */ + + /* When using the debugger, we must keep the */ + /* execution context tied to the instance */ + /* object rather than asking it on demand. */ + + FT_Bool debug; + TT_ExecContext context; + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + } TT_SizeRec; + + + /*************************************************************************/ + /* */ + /* TrueType driver class. */ + /* */ + typedef struct TT_DriverRec_ + { + FT_DriverRec root; + TT_ExecContext context; /* execution context */ + TT_GlyphZoneRec zone; /* glyph loader points zone */ + + void* extension_component; + + } TT_DriverRec; + + + /* Note: All of the functions below (except tt_size_reset()) are used */ + /* as function pointers in a FT_Driver_ClassRec. Therefore their */ + /* parameters are of types FT_Face, FT_Size, etc., rather than TT_Face, */ + /* TT_Size, etc., so that the compiler can confirm that the types and */ + /* number of parameters are correct. In all cases the FT_xxx types are */ + /* cast to their TT_xxx counterparts inside the functions since FreeType */ + /* will always use the TT driver to create them. */ + + + /*************************************************************************/ + /* */ + /* Face functions */ + /* */ + FT_LOCAL( FT_Error ) + tt_face_init( FT_Stream stream, + FT_Face ttface, /* TT_Face */ + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + FT_LOCAL( void ) + tt_face_done( FT_Face ttface ); /* TT_Face */ + + + /*************************************************************************/ + /* */ + /* Size functions */ + /* */ + FT_LOCAL( FT_Error ) + tt_size_init( FT_Size ttsize ); /* TT_Size */ + + FT_LOCAL( void ) + tt_size_done( FT_Size ttsize ); /* TT_Size */ + + FT_LOCAL( FT_Error ) + tt_size_reset( TT_Size size ); + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + FT_LOCAL( FT_Error ) + tt_driver_init( FT_Module ttdriver ); /* TT_Driver */ + + FT_LOCAL( void ) + tt_driver_done( FT_Module ttdriver ); /* TT_Driver */ + + +FT_END_HEADER + +#endif /* __TTOBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttpload.c b/Utilities/vtkfreetype/src/truetype/ttpload.c new file mode 100644 index 0000000..9cae477 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttpload.c @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* ttpload.c */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_TAGS_H + +#include "ttpload.h" + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT +#include "ttgxvar.h" +#endif + +#include "tterrors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttpload + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_loca */ + /* */ + /* <Description> */ + /* Loads the locations table. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Input> */ + /* stream :: The input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_loca( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Short LongOffsets; + FT_ULong table_len; + + + FT_TRACE2(( "Locations " )); + LongOffsets = face->header.Index_To_Loc_Format; + + error = face->goto_table( face, TTAG_loca, stream, &table_len ); + if ( error ) + { + error = TT_Err_Locations_Missing; + goto Exit; + } + + if ( LongOffsets != 0 ) + { + face->num_locations = (FT_UShort)( table_len >> 2 ); + + FT_TRACE2(( "(32bit offsets): %12d ", face->num_locations )); + + if ( FT_NEW_ARRAY( face->glyph_locations, face->num_locations ) ) + goto Exit; + + if ( FT_FRAME_ENTER( face->num_locations * 4L ) ) + goto Exit; + + { + FT_Long* loc = face->glyph_locations; + FT_Long* limit = loc + face->num_locations; + + + for ( ; loc < limit; loc++ ) + *loc = FT_GET_LONG(); + } + + FT_FRAME_EXIT(); + } + else + { + face->num_locations = (FT_UShort)( table_len >> 1 ); + + FT_TRACE2(( "(16bit offsets): %12d ", face->num_locations )); + + if ( FT_NEW_ARRAY( face->glyph_locations, face->num_locations ) ) + goto Exit; + + if ( FT_FRAME_ENTER( face->num_locations * 2L ) ) + goto Exit; + { + FT_Long* loc = face->glyph_locations; + FT_Long* limit = loc + face->num_locations; + + + for ( ; loc < limit; loc++ ) + *loc = (FT_Long)( (FT_ULong)FT_GET_USHORT() * 2 ); + } + FT_FRAME_EXIT(); + } + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_cvt */ + /* */ + /* <Description> */ + /* Loads the control value table into a face object. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Input> */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_cvt( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong table_len; + + + FT_TRACE2(( "CVT " )); + + error = face->goto_table( face, TTAG_cvt, stream, &table_len ); + if ( error ) + { + FT_TRACE2(( "is missing!\n" )); + + face->cvt_size = 0; + face->cvt = NULL; + error = TT_Err_Ok; + + goto Exit; + } + + face->cvt_size = table_len / 2; + + if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) ) + goto Exit; + + if ( FT_FRAME_ENTER( face->cvt_size * 2L ) ) + goto Exit; + + { + FT_Short* cur = face->cvt; + FT_Short* limit = cur + face->cvt_size; + + + for ( ; cur < limit; cur++ ) + *cur = FT_GET_SHORT(); + } + + FT_FRAME_EXIT(); + FT_TRACE2(( "loaded\n" )); + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( face->doblend ) + error = tt_face_vary_cvt( face, stream ); +#endif + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* tt_face_load_fpgm */ + /* */ + /* <Description> */ + /* Loads the font program and the cvt program. */ + /* */ + /* <InOut> */ + /* face :: A handle to the target face object. */ + /* */ + /* <Input> */ + /* stream :: A handle to the input stream. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + tt_face_load_fpgm( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_ULong table_len; + + + FT_TRACE2(( "Font program " )); + + /* The font program is optional */ + error = face->goto_table( face, TTAG_fpgm, stream, &table_len ); + if ( error ) + { + face->font_program = NULL; + face->font_program_size = 0; + + FT_TRACE2(( "is missing!\n" )); + } + else + { + face->font_program_size = table_len; + if ( FT_FRAME_EXTRACT( table_len, face->font_program ) ) + goto Exit; + + FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size )); + } + + FT_TRACE2(( "Prep program " )); + + error = face->goto_table( face, TTAG_prep, stream, &table_len ); + if ( error ) + { + face->cvt_program = NULL; + face->cvt_program_size = 0; + error = TT_Err_Ok; + + FT_TRACE2(( "is missing!\n" )); + } + else + { + face->cvt_program_size = table_len; + if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) ) + goto Exit; + + FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size )); + } + + Exit: + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/truetype/ttpload.h b/Utilities/vtkfreetype/src/truetype/ttpload.h new file mode 100644 index 0000000..3f8cd64 --- /dev/null +++ b/Utilities/vtkfreetype/src/truetype/ttpload.h @@ -0,0 +1,48 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __TTPLOAD_H__ +#define __TTPLOAD_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_TRUETYPE_TYPES_H + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + tt_face_load_loca( TT_Face face, + FT_Stream stream ); + + FT_LOCAL( FT_Error ) + tt_face_load_cvt( TT_Face face, + FT_Stream stream ); + + FT_LOCAL( FT_Error ) + tt_face_load_fpgm( TT_Face face, + FT_Stream stream ); + + +FT_END_HEADER + +#endif /* __TTPLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1afm.c b/Utilities/vtkfreetype/src/type1/t1afm.c new file mode 100644 index 0000000..9945ebd --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1afm.c @@ -0,0 +1,282 @@ +/***************************************************************************/ +/* */ +/* t1afm.c */ +/* */ +/* AFM support for Type 1 fonts (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "t1afm.h" +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_TYPE1_TYPES_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1afm + + + FT_LOCAL_DEF( void ) + T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ) + { + FT_FREE( afm->kern_pairs ); + afm->num_pairs = 0; + FT_FREE( afm ); + } + + +#undef IS_KERN_PAIR +#define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' ) + +#define IS_ALPHANUM( c ) ( ft_isalnum( c ) || \ + c == '_' || \ + c == '.' ) + + + /* read a glyph name and return the equivalent glyph index */ + static FT_UInt + afm_atoindex( FT_Byte** start, + FT_Byte* limit, + T1_Font type1 ) + { + FT_Byte* p = *start; + FT_PtrDist len; + FT_UInt result = 0; + char temp[64]; + + + /* skip whitespace */ + while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) && + p < limit ) + p++; + *start = p; + + /* now, read glyph name */ + while ( IS_ALPHANUM( *p ) && p < limit ) + p++; + + len = p - *start; + + if ( len > 0 && len < 64 ) + { + FT_Int n; + + + /* copy glyph name to intermediate array */ + FT_MEM_COPY( temp, *start, len ); + temp[len] = 0; + + /* lookup glyph name in face array */ + for ( n = 0; n < type1->num_glyphs; n++ ) + { + char* gname = (char*)type1->glyph_names[n]; + + + if ( gname && gname[0] == temp[0] && ft_strcmp( gname, temp ) == 0 ) + { + result = n; + break; + } + } + } + *start = p; + return result; + } + + + /* read an integer */ + static int + afm_atoi( FT_Byte** start, + FT_Byte* limit ) + { + FT_Byte* p = *start; + int sum = 0; + int sign = 1; + + + /* skip everything that is not a number */ + while ( p < limit && !isdigit( *p ) ) + { + sign = 1; + if ( *p == '-' ) + sign = -1; + + p++; + } + + while ( p < limit && isdigit( *p ) ) + { + sum = sum * 10 + ( *p - '0' ); + p++; + } + *start = p; + + return sum * sign; + } + + +#undef KERN_INDEX +#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) + + + /* compare two kerning pairs */ + FT_CALLBACK_DEF( int ) + compare_kern_pairs( const void* a, + const void* b ) + { + T1_Kern_Pair* pair1 = (T1_Kern_Pair*)a; + T1_Kern_Pair* pair2 = (T1_Kern_Pair*)b; + + FT_ULong index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 ); + FT_ULong index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 ); + + + return (int)( index1 - index2 ); + } + + + /* parse an AFM file -- for now, only read the kerning pairs */ + FT_LOCAL_DEF( FT_Error ) + T1_Read_AFM( FT_Face t1_face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Byte* start; + FT_Byte* limit; + FT_Byte* p; + FT_Int count = 0; + T1_Kern_Pair* pair; + T1_Font type1 = &((T1_Face)t1_face)->type1; + T1_AFM* afm = 0; + + + if ( FT_FRAME_ENTER( stream->size ) ) + return error; + + start = (FT_Byte*)stream->cursor; + limit = (FT_Byte*)stream->limit; + p = start; + + /* we are now going to count the occurences of `KP' or `KPX' in */ + /* the AFM file */ + count = 0; + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + count++; + } + + /* Actually, kerning pairs are simply optional! */ + if ( count == 0 ) + goto Exit; + + /* allocate the pairs */ + if ( FT_NEW( afm ) || FT_NEW_ARRAY( afm->kern_pairs, count ) ) + goto Exit; + + /* now, read each kern pair */ + pair = afm->kern_pairs; + afm->num_pairs = count; + + /* save in face object */ + ((T1_Face)t1_face)->afm_data = afm; + + t1_face->face_flags |= FT_FACE_FLAG_KERNING; + + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + { + FT_Byte* q; + + + /* skip keyword (KP or KPX) */ + q = p + 2; + if ( *q == 'X' ) + q++; + + pair->glyph1 = afm_atoindex( &q, limit, type1 ); + pair->glyph2 = afm_atoindex( &q, limit, type1 ); + pair->kerning.x = afm_atoi( &q, limit ); + + pair->kerning.y = 0; + if ( p[2] != 'X' ) + pair->kerning.y = afm_atoi( &q, limit ); + + pair++; + } + } + + /* now, sort the kern pairs according to their glyph indices */ + ft_qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FT_FREE( afm ); + + FT_FRAME_EXIT(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + FT_LOCAL_DEF( void ) + T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + T1_Kern_Pair *min, *mid, *max; + FT_ULong idx = KERN_INDEX( glyph1, glyph2 ); + + + /* simple binary search */ + min = afm->kern_pairs; + max = min + afm->num_pairs - 1; + + while ( min <= max ) + { + FT_ULong midi; + + + mid = min + ( max - min ) / 2; + midi = KERN_INDEX( mid->glyph1, mid->glyph2 ); + + if ( midi == idx ) + { + *kerning = mid->kerning; + return; + } + + if ( midi < idx ) + min = mid + 1; + else + max = mid - 1; + } + + kerning->x = 0; + kerning->y = 0; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1afm.h b/Utilities/vtkfreetype/src/type1/t1afm.h new file mode 100644 index 0000000..77cc6a6 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1afm.h @@ -0,0 +1,66 @@ +/***************************************************************************/ +/* */ +/* t1afm.h */ +/* */ +/* AFM support for Type 1 fonts (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1AFM_H__ +#define __T1AFM_H__ + +#include <ft2build.h> +#include "t1objs.h" + + +FT_BEGIN_HEADER + + + typedef struct T1_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } T1_Kern_Pair; + + + typedef struct T1_AFM_ + { + FT_Int num_pairs; + T1_Kern_Pair* kern_pairs; + + } T1_AFM; + + + FT_LOCAL( FT_Error ) + T1_Read_AFM( FT_Face face, + FT_Stream stream ); + + FT_LOCAL( void ) + T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ); + + FT_LOCAL( void ) + T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +FT_END_HEADER + +#endif /* __T1AFM_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1driver.c b/Utilities/vtkfreetype/src/type1/t1driver.c new file mode 100644 index 0000000..b37ae77 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1driver.c @@ -0,0 +1,303 @@ +/***************************************************************************/ +/* */ +/* t1driver.c */ +/* */ +/* Type 1 driver interface (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "t1driver.h" +#include "t1gload.h" +#include "t1load.h" + +#include "t1errors.h" + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include "t1afm.h" +#endif + +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H + +#include FT_SERVICE_MULTIPLE_MASTERS_H +#include FT_SERVICE_GLYPH_DICT_H +#include FT_SERVICE_XFREE86_NAME_H +#include FT_SERVICE_POSTSCRIPT_NAME_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_SERVICE_POSTSCRIPT_INFO_H + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1driver + + /* + * GLYPH DICT SERVICE + * + */ + + static FT_Error + t1_get_glyph_name( T1_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_String* gname; + + + gname = face->type1.glyph_names[glyph_index]; + + if ( buffer_max > 0 ) + { + FT_UInt len = (FT_UInt)( ft_strlen( gname ) ); + + + if (len >= buffer_max) + len = buffer_max - 1; + + FT_MEM_COPY( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T1_Err_Ok; + } + + + static FT_UInt + t1_get_name_index( T1_Face face, + FT_String* glyph_name ) + { + FT_Int i; + FT_String* gname; + + + for ( i = 0; i < face->type1.num_glyphs; i++ ) + { + gname = face->type1.glyph_names[i]; + + if ( !ft_strcmp( glyph_name, gname ) ) + return (FT_UInt)i; + } + + return 0; + } + + static const FT_Service_GlyphDictRec t1_service_glyph_dict = + { + (FT_GlyphDict_GetNameFunc) t1_get_glyph_name, + (FT_GlyphDict_NameIndexFunc)t1_get_name_index + }; + + + /* + * POSTSCRIPT NAME SERVICE + * + */ + + static const char* + t1_get_ps_name( T1_Face face ) + { + return (const char*) face->type1.font_name; + } + + static const FT_Service_PsFontNameRec t1_service_ps_name = + { + (FT_PsName_GetFunc)t1_get_ps_name + }; + + + /* + * MULTIPLE MASTERS SERVICE + * + */ + +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + static const FT_Service_MultiMastersRec t1_service_multi_masters = + { + (FT_Get_MM_Func) T1_Get_Multi_Master, + (FT_Set_MM_Design_Func) T1_Set_MM_Design, + (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, + (FT_Get_MM_Var_Func) T1_Get_MM_Var, + (FT_Set_Var_Design_Func)T1_Set_Var_Design + }; +#endif + + + /* + * POSTSCRIPT INFO SERVICE + * + */ + + static FT_Error + t1_ps_get_font_info( FT_Face face, + PS_FontInfoRec* afont_info ) + { + *afont_info = ((T1_Face)face)->type1.font_info; + return 0; + } + + + static FT_Int + t1_ps_has_glyph_names( FT_Face face ) + { + FT_UNUSED( face ); + return 1; + } + + + static const FT_Service_PsInfoRec t1_service_ps_info = + { + (PS_GetFontInfoFunc) t1_ps_get_font_info, + (PS_HasGlyphNamesFunc)t1_ps_has_glyph_names + }; + + + /* + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec t1_services[] = + { + { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t1_service_ps_name }, + { FT_SERVICE_ID_GLYPH_DICT, &t1_service_glyph_dict }, + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TYPE_1 }, + { FT_SERVICE_ID_POSTSCRIPT_INFO, &t1_service_ps_info }, + +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + { FT_SERVICE_ID_MULTI_MASTERS, &t1_service_multi_masters }, +#endif + { NULL, NULL } + }; + + + static FT_Module_Interface + Get_Interface( FT_Driver driver, + const FT_String* t1_interface ) + { + FT_UNUSED( driver ); + + return ft_service_list_lookup( t1_services, t1_interface ); + } + + +#ifndef T1_CONFIG_OPTION_NO_AFM + + /*************************************************************************/ + /* */ + /* <Function> */ + /* Get_Kerning */ + /* */ + /* <Description> */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* <Input> */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* <Output> */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + /* <Note> */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + static FT_Error + Get_Kerning( T1_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + T1_AFM* afm; + + + kerning->x = 0; + kerning->y = 0; + + afm = (T1_AFM*)face->afm_data; + if ( afm ) + T1_Get_Kerning( afm, left_glyph, right_glyph, kerning ); + + return T1_Err_Ok; + } + + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec t1_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_SCALABLE | + FT_MODULE_DRIVER_HAS_HINTER, + + sizeof( FT_DriverRec ), + + "type1", + 0x10000L, + 0x20000L, + + 0, /* format interface */ + + (FT_Module_Constructor)T1_Driver_Init, + (FT_Module_Destructor) T1_Driver_Done, + (FT_Module_Requester) Get_Interface, + }, + + sizeof( T1_FaceRec ), + sizeof( T1_SizeRec ), + sizeof( T1_GlyphSlotRec ), + + (FT_Face_InitFunc) T1_Face_Init, + (FT_Face_DoneFunc) T1_Face_Done, + (FT_Size_InitFunc) T1_Size_Init, + (FT_Size_DoneFunc) T1_Size_Done, + (FT_Slot_InitFunc) T1_GlyphSlot_Init, + (FT_Slot_DoneFunc) T1_GlyphSlot_Done, + + (FT_Size_ResetPointsFunc) T1_Size_Reset, + (FT_Size_ResetPixelsFunc) T1_Size_Reset, + (FT_Slot_LoadFunc) T1_Load_Glyph, + +#ifdef T1_CONFIG_OPTION_NO_AFM + (FT_Face_GetKerningFunc) 0, + (FT_Face_AttachFunc) 0, +#else + (FT_Face_GetKerningFunc) Get_Kerning, + (FT_Face_AttachFunc) T1_Read_AFM, +#endif + (FT_Face_GetAdvancesFunc) 0 + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1driver.h b/Utilities/vtkfreetype/src/type1/t1driver.h new file mode 100644 index 0000000..ad42944 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1driver.h @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* t1driver.h */ +/* */ +/* High-level Type 1 driver interface (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1DRIVER_H__ +#define __T1DRIVER_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) t1_driver_class; + + +FT_END_HEADER + +#endif /* __T1DRIVER_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1errors.h b/Utilities/vtkfreetype/src/type1/t1errors.h new file mode 100644 index 0000000..81221c3 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1errors.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* t1errors.h */ +/* */ +/* Type 1 error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the Type 1 error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __T1ERRORS_H__ +#define __T1ERRORS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX T1_Err_ +#define FT_ERR_BASE FT_Mod_Err_Type1 + +#include FT_ERRORS_H + +#endif /* __T1ERRORS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1gload.c b/Utilities/vtkfreetype/src/type1/t1gload.c new file mode 100644 index 0000000..f45a83b --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1gload.c @@ -0,0 +1,431 @@ +/***************************************************************************/ +/* */ +/* t1gload.c */ +/* */ +/* Type 1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include "t1gload.h" +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_OUTLINE_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H + +#include "t1errors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1gload + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder, + FT_UInt glyph_index, + FT_Data* char_string ) + { + T1_Face face = (T1_Face)decoder->builder.face; + T1_Font type1 = &face->type1; + FT_Error error = T1_Err_Ok; + + + decoder->font_matrix = type1->font_matrix; + decoder->font_offset = type1->font_offset; + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* For incremental fonts get the character data using the */ + /* callback function. */ + if ( face->root.internal->incremental_interface ) + error = face->root.internal->incremental_interface->funcs->get_glyph_data( + face->root.internal->incremental_interface->object, + glyph_index, char_string ); + else + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + /* For ordinary fonts get the character data stored in the face record. */ + { + char_string->pointer = type1->charstrings[glyph_index]; + char_string->length = (FT_Int)type1->charstrings_len[glyph_index]; + } + + if ( !error ) + error = decoder->funcs.parse_charstrings( + decoder, (FT_Byte*)char_string->pointer, + char_string->length ); + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + /* Incremental fonts can optionally override the metrics. */ + if ( !error && face->root.internal->incremental_interface && + face->root.internal->incremental_interface->funcs->get_glyph_metrics ) + { + FT_Incremental_MetricsRec metrics; + + + metrics.bearing_x = decoder->builder.left_bearing.x; + metrics.bearing_y = decoder->builder.left_bearing.y; + metrics.advance = decoder->builder.advance.x; + error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( + face->root.internal->incremental_interface->object, + glyph_index, FALSE, &metrics ); + decoder->builder.left_bearing.x = metrics.bearing_x; + decoder->builder.left_bearing.y = metrics.bearing_y; + decoder->builder.advance.x = metrics.advance; + decoder->builder.advance.y = 0; + } + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + return error; + } + + + FT_CALLBACK_DEF( FT_Error ) + T1_Parse_Glyph( T1_Decoder decoder, + FT_UInt glyph_index ) + { + FT_Data glyph_data; + FT_Error error = T1_Parse_Glyph_And_Get_Char_String( + decoder, glyph_index, &glyph_data ); + + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + + if ( !error ) + { + T1_Face face = (T1_Face)decoder->builder.face; + + + if ( face->root.internal->incremental_interface ) + face->root.internal->incremental_interface->funcs->free_glyph_data( + face->root.internal->incremental_interface->object, + &glyph_data ); + } + +#endif /* FT_CONFIG_OPTION_INCREMENTAL */ + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Compute_Max_Advance( T1_Face face, + FT_Pos* max_advance ) + { + FT_Error error; + T1_DecoderRec decoder; + FT_Int glyph_index; + T1_Font type1 = &face->type1; + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + *max_advance = 0; + + /* initialize load decoder */ + error = psaux->t1_decoder_funcs->init( &decoder, + (FT_Face)face, + 0, /* size */ + 0, /* glyph slot */ + (FT_Byte**)type1->glyph_names, + face->blend, + 0, + FT_RENDER_MODE_NORMAL, + T1_Parse_Glyph ); + if ( error ) + return error; + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + decoder.num_subrs = type1->num_subrs; + decoder.subrs = type1->subrs; + decoder.subrs_len = type1->subrs_len; + + *max_advance = 0; + + /* for each glyph, parse the glyph charstring and extract */ + /* the advance width */ + for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) + { + /* now get load the unscaled outline */ + error = T1_Parse_Glyph( &decoder, glyph_index ); + if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance ) + *max_advance = decoder.builder.advance.x; + + /* ignore the error if one occurred - skip to next glyph */ + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** UNHINTED GLYPH LOADER *********/ + /********** *********/ + /********** The following code is in charge of loading a *********/ + /********** single outline. It completely ignores hinting *********/ + /********** and is used when FT_LOAD_NO_HINTING is set. *********/ + /********** *********/ + /********** The Type 1 hinter is located in `t1hint.c' *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + FT_LOCAL_DEF( FT_Error ) + T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + FT_Error error; + T1_DecoderRec decoder; + T1_Face face = (T1_Face)glyph->root.face; + FT_Bool hinting; + T1_Font type1 = &face->type1; + PSAux_Service psaux = (PSAux_Service)face->psaux; + const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; + + FT_Matrix font_matrix; + FT_Vector font_offset; + FT_Data glyph_data; +#ifdef FT_CONFIG_OPTION_INCREMENTAL + FT_Bool glyph_data_loaded = 0; +#endif + + + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + glyph->x_scale = size->root.metrics.x_scale; + glyph->y_scale = size->root.metrics.y_scale; + + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); + + glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; + + error = decoder_funcs->init( &decoder, + (FT_Face)face, + (FT_Size)size, + (FT_GlyphSlot)glyph, + (FT_Byte**)type1->glyph_names, + face->blend, + FT_BOOL( hinting ), + FT_LOAD_TARGET_MODE( load_flags ), + T1_Parse_Glyph ); + if ( error ) + goto Exit; + + decoder.builder.no_recurse = FT_BOOL( + ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); + + decoder.num_subrs = type1->num_subrs; + decoder.subrs = type1->subrs; + decoder.subrs_len = type1->subrs_len; + + /* now load the unscaled outline */ + error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, + &glyph_data ); + if ( error ) + goto Exit; +#ifdef FT_CONFIG_OPTION_INCREMENTAL + glyph_data_loaded = 1; +#endif + + font_matrix = decoder.font_matrix; + font_offset = decoder.font_offset; + + /* save new glyph tables */ + decoder_funcs->done( &decoder ); + + /* now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax */ + if ( !error ) + { + glyph->root.outline.flags &= FT_OUTLINE_OWNER; + glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; + + /* for composite glyphs, return only left side bearing and */ + /* advance width */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + FT_Slot_Internal internal = glyph->root.internal; + + + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + internal->glyph_matrix = font_matrix; + internal->glyph_delta = font_offset; + internal->glyph_transformed = 1; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + FT_Vector advance; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + glyph->root.linearHoriAdvance = decoder.builder.advance.x; + glyph->root.internal->glyph_transformed = 0; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.linearVertAdvance = 0; + + glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; + + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; + +#if 1 + /* apply the font matrix, if any */ + FT_Outline_Transform( &glyph->root.outline, &font_matrix ); + + FT_Outline_Translate( &glyph->root.outline, + font_offset.x, + font_offset.y ); + + advance.x = metrics->horiAdvance; + advance.y = 0; + FT_Vector_Transform( &advance, &font_matrix ); + metrics->horiAdvance = advance.x + font_offset.x; + advance.x = 0; + advance.y = metrics->vertAdvance; + FT_Vector_Transform( &advance, &font_matrix ); + metrics->vertAdvance = advance.y + font_offset.y; +#endif + + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + /* scale the outline and the metrics */ + FT_Int n; + FT_Outline* cur = decoder.builder.base; + FT_Vector* vec = cur->points; + FT_Fixed x_scale = glyph->x_scale; + FT_Fixed y_scale = glyph->y_scale; + + + /* First of all, scale the points, if we are not hinting */ + if ( !hinting ) + for ( n = cur->n_points; n > 0; n--, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* Then scale the metrics */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + + if ( hinting ) + { + metrics->horiAdvance = FT_PIX_ROUND( metrics->horiAdvance ); + metrics->vertAdvance = FT_PIX_ROUND( metrics->vertAdvance ); + + metrics->vertBearingX = FT_PIX_ROUND( metrics->vertBearingX ); + metrics->vertBearingY = FT_PIX_ROUND( metrics->vertBearingY ); + } + } + + /* compute the other metrics */ + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* grid fit the bounding box if necessary */ + if ( hinting ) + { + cbox.xMin = FT_PIX_FLOOR( cbox.xMin ); + cbox.yMin = FT_PIX_FLOOR( cbox.yMin ); + cbox.xMax = FT_PIX_CEIL( cbox.xMax ); + cbox.yMax = FT_PIX_CEIL( cbox.yMax ); + } + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax; + } + + /* Set control data to the glyph charstrings. Note that this is */ + /* _not_ zero-terminated. */ + glyph->root.control_data = (FT_Byte*)glyph_data.pointer; + glyph->root.control_len = glyph_data.length; + } + + + Exit: + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( glyph_data_loaded && face->root.internal->incremental_interface ) + { + face->root.internal->incremental_interface->funcs->free_glyph_data( + face->root.internal->incremental_interface->object, + &glyph_data ); + + /* Set the control data to null - it is no longer available if */ + /* loaded incrementally. */ + glyph->root.control_data = 0; + glyph->root.control_len = 0; + } +#endif + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1gload.h b/Utilities/vtkfreetype/src/type1/t1gload.h new file mode 100644 index 0000000..de87896 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1gload.h @@ -0,0 +1,46 @@ +/***************************************************************************/ +/* */ +/* t1gload.h */ +/* */ +/* Type 1 Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1GLOAD_H__ +#define __T1GLOAD_H__ + + +#include <ft2build.h> +#include "t1objs.h" + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + T1_Compute_Max_Advance( T1_Face face, + FT_Pos* max_advance ); + + FT_LOCAL( FT_Error ) + T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + +FT_END_HEADER + +#endif /* __T1GLOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1load.c b/Utilities/vtkfreetype/src/type1/t1load.c new file mode 100644 index 0000000..7ec163a --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1load.c @@ -0,0 +1,2094 @@ +/***************************************************************************/ +/* */ +/* t1load.c */ +/* */ +/* Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This is the new and improved Type 1 data loader for FreeType 2. The */ + /* old loader has several problems: it is slow, complex, difficult to */ + /* maintain, and contains incredible hacks to make it accept some */ + /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */ + /* the Type 1 fonts on my machine still aren't loaded correctly by it. */ + /* */ + /* This version is much simpler, much faster and also easier to read and */ + /* maintain by a great order of magnitude. The idea behind it is to */ + /* _not_ try to read the Type 1 token stream with a state machine (i.e. */ + /* a Postscript-like interpreter) but rather to perform simple pattern */ + /* matching. */ + /* */ + /* Indeed, nearly all data definitions follow a simple pattern like */ + /* */ + /* ... /Field <data> ... */ + /* */ + /* where <data> can be a number, a boolean, a string, or an array of */ + /* numbers. There are a few exceptions, namely the encoding, font name, */ + /* charstrings, and subrs; they are handled with a special pattern */ + /* matching routine. */ + /* */ + /* All other common cases are handled very simply. The matching rules */ + /* are defined in the file `t1tokens.h' through the use of several */ + /* macros calls PARSE_XXX. This file is included twice here; the first */ + /* time to generate parsing callback functions, the second time to */ + /* generate a table of keywords (with pointers to the associated */ + /* callback functions). */ + /* */ + /* The function `parse_dict' simply scans *linearly* a given dictionary */ + /* (either the top-level or private one) and calls the appropriate */ + /* callback when it encounters an immediate keyword. */ + /* */ + /* This is by far the fastest way one can find to parse and read all */ + /* data. */ + /* */ + /* This led to tremendous code size reduction. Note that later, the */ + /* glyph loader will also be _greatly_ simplified, and the automatic */ + /* hinter will replace the clumsy `t1hinter'. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_CONFIG_CONFIG_H +#include FT_MULTIPLE_MASTERS_H +#include FT_INTERNAL_TYPE1_TYPES_H + +#include "t1load.h" +#include "t1errors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1load + + +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** MULTIPLE MASTERS SUPPORT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static FT_Error + t1_allocate_blend( T1_Face face, + FT_UInt num_designs, + FT_UInt num_axis ) + { + PS_Blend blend; + FT_Memory memory = face->root.memory; + FT_Error error = T1_Err_Ok; + + + blend = face->blend; + if ( !blend ) + { + if ( FT_NEW( blend ) ) + goto Exit; + + face->blend = blend; + } + + /* allocate design data if needed */ + if ( num_designs > 0 ) + { + if ( blend->num_designs == 0 ) + { + FT_UInt nn; + + + /* allocate the blend `private' and `font_info' dictionaries */ + if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) || + FT_NEW_ARRAY( blend->privates[1], num_designs ) || + FT_NEW_ARRAY( blend->bboxes[1], num_designs ) || + FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) ) + goto Exit; + + blend->default_weight_vector = blend->weight_vector + num_designs; + + blend->font_infos[0] = &face->type1.font_info; + blend->privates [0] = &face->type1.private_dict; + blend->bboxes [0] = &face->type1.font_bbox; + + for ( nn = 2; nn <= num_designs; nn++ ) + { + blend->privates[nn] = blend->privates [nn - 1] + 1; + blend->font_infos[nn] = blend->font_infos[nn - 1] + 1; + blend->bboxes[nn] = blend->bboxes [nn - 1] + 1; + } + + blend->num_designs = num_designs; + } + else if ( blend->num_designs != num_designs ) + goto Fail; + } + + /* allocate axis data if needed */ + if ( num_axis > 0 ) + { + if ( blend->num_axis != 0 && blend->num_axis != num_axis ) + goto Fail; + + blend->num_axis = num_axis; + } + + /* allocate the blend design pos table if needed */ + num_designs = blend->num_designs; + num_axis = blend->num_axis; + if ( num_designs && num_axis && blend->design_pos[0] == 0 ) + { + FT_UInt n; + + + if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) ) + goto Exit; + + for ( n = 1; n < num_designs; n++ ) + blend->design_pos[n] = blend->design_pos[0] + num_axis * n; + } + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ) + { + PS_Blend blend = face->blend; + FT_UInt n; + FT_Error error; + + + error = T1_Err_Invalid_Argument; + + if ( blend ) + { + master->num_axis = blend->num_axis; + master->num_designs = blend->num_designs; + + for ( n = 0; n < blend->num_axis; n++ ) + { + FT_MM_Axis* axis = master->axis + n; + PS_DesignMap map = blend->design_map + n; + + + axis->name = blend->axis_names[n]; + axis->minimum = map->design_points[0]; + axis->maximum = map->design_points[map->num_points - 1]; + } + + error = T1_Err_Ok; + } + + return error; + } + + +#define FT_INT_TO_FIXED( a ) ( (a) << 16 ) +#define FT_FIXED_TO_INT( a ) ( FT_RoundFix( a ) >> 16 ) + + + /*************************************************************************/ + /* */ + /* Given a normalized (blend) coordinate, figure out the design */ + /* coordinate appropriate for that value. */ + /* */ + FT_LOCAL_DEF( FT_Fixed ) + mm_axis_unmap( PS_DesignMap axismap, + FT_Fixed ncv ) + { + int j; + + + if ( ncv <= axismap->blend_points[0] ) + return axismap->design_points[0]; + + for ( j = 1; j < axismap->num_points; ++j ) + { + if ( ncv <= axismap->blend_points[j] ) + { + FT_Fixed t = FT_MulDiv( ncv - axismap->blend_points[j - 1], + 0x10000L, + axismap->blend_points[j] - + axismap->blend_points[j - 1] ); + + + return axismap->design_points[j - 1] + + FT_MulDiv( t, + axismap->design_points[j] - + axismap->design_points[j - 1], + 1L ); + } + } + + return axismap->design_points[axismap->num_points - 1]; + } + + + /*************************************************************************/ + /* */ + /* Given a vector of weights, one for each design, figure out the */ + /* normalized axis coordinates which gave rise to those weights. */ + /* */ + FT_LOCAL_DEF( void ) + mm_weights_unmap( FT_Fixed* weights, + FT_Fixed* axiscoords, + FT_UInt axis_count ) + { + FT_ASSERT( axis_count <= T1_MAX_MM_AXIS ); + + if ( axis_count == 1 ) + axiscoords[0] = weights[1]; + + else if ( axis_count == 2 ) + { + axiscoords[0] = weights[3] + weights[1]; + axiscoords[1] = weights[3] + weights[2]; + } + + else if ( axis_count == 3 ) + { + axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1]; + axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2]; + axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4]; + } + + else + { + axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] + + weights[7] + weights[5] + weights[3] + weights[1]; + axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] + + weights[7] + weights[6] + weights[3] + weights[2]; + axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] + + weights[7] + weights[6] + weights[5] + weights[4]; + axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] + + weights[11] + weights[10] + weights[9] + weights[8]; + } + } + + + /*************************************************************************/ + /* */ + /* Just a wrapper around T1_Get_Multi_Master to support the different */ + /* arguments needed by the GX var distortable fonts. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + T1_Get_MM_Var( T1_Face face, + FT_MM_Var* *master ) + { + FT_Memory memory = face->root.memory; + FT_MM_Var *mmvar; + FT_Multi_Master mmaster; + FT_Error error; + FT_UInt i; + FT_Fixed axiscoords[T1_MAX_MM_AXIS]; + PS_Blend blend = face->blend; + + + error = T1_Get_Multi_Master( face, &mmaster ); + if ( error ) + goto Exit; + if ( FT_ALLOC( mmvar, + sizeof ( FT_MM_Var ) + + mmaster.num_axis * sizeof ( FT_Var_Axis ) ) ) + goto Exit; + + mmvar->num_axis = mmaster.num_axis; + mmvar->num_designs = mmaster.num_designs; + mmvar->num_namedstyles = (FT_UInt)-1; /* Does not apply */ + mmvar->axis = (FT_Var_Axis*)&mmvar[1]; + /* Point to axes after MM_Var struct */ + mmvar->namedstyle = NULL; + + for ( i = 0 ; i < mmaster.num_axis; ++i ) + { + mmvar->axis[i].name = mmaster.axis[i].name; + mmvar->axis[i].minimum = FT_INT_TO_FIXED( mmaster.axis[i].minimum); + mmvar->axis[i].maximum = FT_INT_TO_FIXED( mmaster.axis[i].maximum); + mmvar->axis[i].def = ( mmvar->axis[i].minimum + + mmvar->axis[i].maximum ) / 2; + /* Does not apply. But this value is in range */ + mmvar->axis[i].strid = 0xFFFFFFFFLU; /* Does not apply */ + mmvar->axis[i].tag = 0xFFFFFFFFLU; /* Does not apply */ + + if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 ) + mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' ); + else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 ) + mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' ); + else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 ) + mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' ); + } + + if ( blend->num_designs == 1U << blend->num_axis ) + { + mm_weights_unmap( blend->default_weight_vector, + axiscoords, + blend->num_axis ); + + for ( i = 0; i < mmaster.num_axis; ++i ) + mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i], + axiscoords[i] ); + } + + *master = mmvar; + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + PS_Blend blend = face->blend; + FT_Error error; + FT_UInt n, m; + + + error = T1_Err_Invalid_Argument; + + if ( blend && blend->num_axis == num_coords ) + { + /* recompute the weight vector from the blend coordinates */ + error = T1_Err_Ok; + + for ( n = 0; n < blend->num_designs; n++ ) + { + FT_Fixed result = 0x10000L; /* 1.0 fixed */ + + + for ( m = 0; m < blend->num_axis; m++ ) + { + FT_Fixed factor; + + + /* get current blend axis position */ + factor = coords[m]; + if ( factor < 0 ) factor = 0; + if ( factor > 0x10000L ) factor = 0x10000L; + + if ( ( n & ( 1 << m ) ) == 0 ) + factor = 0x10000L - factor; + + result = FT_MulFix( result, factor ); + } + blend->weight_vector[n] = result; + } + + error = T1_Err_Ok; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Set_MM_Design( T1_Face face, + FT_UInt num_coords, + FT_Long* coords ) + { + PS_Blend blend = face->blend; + FT_Error error; + FT_UInt n, p; + + + error = T1_Err_Invalid_Argument; + if ( blend && blend->num_axis == num_coords ) + { + /* compute the blend coordinates through the blend design map */ + FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; + + + for ( n = 0; n < blend->num_axis; n++ ) + { + FT_Long design = coords[n]; + FT_Fixed the_blend; + PS_DesignMap map = blend->design_map + n; + FT_Long* designs = map->design_points; + FT_Fixed* blends = map->blend_points; + FT_Int before = -1, after = -1; + + + for ( p = 0; p < (FT_UInt)map->num_points; p++ ) + { + FT_Long p_design = designs[p]; + + + /* exact match? */ + if ( design == p_design ) + { + the_blend = blends[p]; + goto Found; + } + + if ( design < p_design ) + { + after = p; + break; + } + + before = p; + } + + /* now interpolate if necessary */ + if ( before < 0 ) + the_blend = blends[0]; + + else if ( after < 0 ) + the_blend = blends[map->num_points - 1]; + + else + the_blend = FT_MulDiv( design - designs[before], + blends [after] - blends [before], + designs[after] - designs[before] ); + + Found: + final_blends[n] = the_blend; + } + + error = T1_Set_MM_Blend( face, num_coords, final_blends ); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* Just a wrapper around T1_Set_MM_Design to support the different */ + /* arguments needed by the GX var distortable fonts. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + T1_Set_Var_Design( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Long lcoords[4]; /* maximum axis count is 4 */ + FT_UInt i; + FT_Error error; + + + error = T1_Err_Invalid_Argument; + if ( num_coords <= 4 && num_coords > 0 ) + { + for ( i = 0; i < num_coords; ++i ) + lcoords[i] = FT_FIXED_TO_INT( coords[i] ); + error = T1_Set_MM_Design( face, num_coords, lcoords ); + } + + return error; + } + + + FT_LOCAL_DEF( void ) + T1_Done_Blend( T1_Face face ) + { + FT_Memory memory = face->root.memory; + PS_Blend blend = face->blend; + + + if ( blend ) + { + FT_UInt num_designs = blend->num_designs; + FT_UInt num_axis = blend->num_axis; + FT_UInt n; + + + /* release design pos table */ + FT_FREE( blend->design_pos[0] ); + for ( n = 1; n < num_designs; n++ ) + blend->design_pos[n] = 0; + + /* release blend `private' and `font info' dictionaries */ + FT_FREE( blend->privates[1] ); + FT_FREE( blend->font_infos[1] ); + FT_FREE( blend->bboxes[1] ); + + for ( n = 0; n < num_designs; n++ ) + { + blend->privates [n] = 0; + blend->font_infos[n] = 0; + blend->bboxes [n] = 0; + } + + /* release weight vectors */ + FT_FREE( blend->weight_vector ); + blend->default_weight_vector = 0; + + /* release axis names */ + for ( n = 0; n < num_axis; n++ ) + FT_FREE( blend->axis_names[n] ); + + /* release design map */ + for ( n = 0; n < num_axis; n++ ) + { + PS_DesignMap dmap = blend->design_map + n; + + + FT_FREE( dmap->design_points ); + dmap->num_points = 0; + } + + FT_FREE( face->blend ); + } + } + + + static void + parse_blend_axis_types( T1_Face face, + T1_Loader loader ) + { + T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; + FT_Int n, num_axis; + FT_Error error = T1_Err_Ok; + PS_Blend blend; + FT_Memory memory; + + + /* take an array of objects */ + T1_ToTokenArray( &loader->parser, axis_tokens, + T1_MAX_MM_AXIS, &num_axis ); + if ( num_axis < 0 ) + { + error = T1_Err_Ignore; + goto Exit; + } + if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) + { + FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n", + num_axis )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* allocate blend if necessary */ + error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + if ( error ) + goto Exit; + + blend = face->blend; + memory = face->root.memory; + + /* each token is an immediate containing the name of the axis */ + for ( n = 0; n < num_axis; n++ ) + { + T1_Token token = axis_tokens + n; + FT_Byte* name; + FT_PtrDist len; + + + /* skip first slash, if any */ + if ( token->start[0] == '/' ) + token->start++; + + len = token->limit - token->start; + if ( len == 0 ) + { + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) + goto Exit; + + name = (FT_Byte*)blend->axis_names[n]; + FT_MEM_COPY( name, token->start, len ); + name[len] = 0; + } + + Exit: + loader->parser.root.error = error; + } + + + static void + parse_blend_design_positions( T1_Face face, + T1_Loader loader ) + { + T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; + FT_Int num_designs; + FT_Int num_axis; + T1_Parser parser = &loader->parser; + + FT_Error error = T1_Err_Ok; + PS_Blend blend; + + + /* get the array of design tokens -- compute number of designs */ + T1_ToTokenArray( parser, design_tokens, + T1_MAX_MM_DESIGNS, &num_designs ); + if ( num_designs < 0 ) + { + error = T1_Err_Ignore; + goto Exit; + } + if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) + { + FT_ERROR(( "parse_blend_design_positions:" )); + FT_ERROR(( " incorrect number of designs: %d\n", + num_designs )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + { + FT_Byte* old_cursor = parser->root.cursor; + FT_Byte* old_limit = parser->root.limit; + FT_Int n; + + + blend = face->blend; + num_axis = 0; /* make compiler happy */ + + for ( n = 0; n < num_designs; n++ ) + { + T1_TokenRec axis_tokens[T1_MAX_MM_DESIGNS]; + T1_Token token; + FT_Int axis, n_axis; + + + /* read axis/coordinates tokens */ + token = design_tokens + n; + parser->root.cursor = token->start; + parser->root.limit = token->limit; + T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis ); + + if ( n == 0 ) + { + num_axis = n_axis; + error = t1_allocate_blend( face, num_designs, num_axis ); + if ( error ) + goto Exit; + blend = face->blend; + } + else if ( n_axis != num_axis ) + { + FT_ERROR(( "parse_blend_design_positions: incorrect table\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* now read each axis token into the design position */ + for ( axis = 0; axis < n_axis; axis++ ) + { + T1_Token token2 = axis_tokens + axis; + + + parser->root.cursor = token2->start; + parser->root.limit = token2->limit; + blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); + } + } + + loader->parser.root.cursor = old_cursor; + loader->parser.root.limit = old_limit; + } + + Exit: + loader->parser.root.error = error; + } + + + static void + parse_blend_design_map( T1_Face face, + T1_Loader loader ) + { + FT_Error error = T1_Err_Ok; + T1_Parser parser = &loader->parser; + PS_Blend blend; + T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; + FT_Int n, num_axis; + FT_Byte* old_cursor; + FT_Byte* old_limit; + FT_Memory memory = face->root.memory; + + + T1_ToTokenArray( parser, axis_tokens, + T1_MAX_MM_AXIS, &num_axis ); + if ( num_axis < 0 ) + { + error = T1_Err_Ignore; + goto Exit; + } + if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) + { + FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n", + num_axis )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + old_cursor = parser->root.cursor; + old_limit = parser->root.limit; + + error = t1_allocate_blend( face, 0, num_axis ); + if ( error ) + goto Exit; + blend = face->blend; + + /* now read each axis design map */ + for ( n = 0; n < num_axis; n++ ) + { + PS_DesignMap map = blend->design_map + n; + T1_Token axis_token; + T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS]; + FT_Int p, num_points; + + + axis_token = axis_tokens + n; + + parser->root.cursor = axis_token->start; + parser->root.limit = axis_token->limit; + T1_ToTokenArray( parser, point_tokens, + T1_MAX_MM_MAP_POINTS, &num_points ); + + if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) + { + FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* allocate design map data */ + if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) ) + goto Exit; + map->blend_points = map->design_points + num_points; + map->num_points = (FT_Byte)num_points; + + for ( p = 0; p < num_points; p++ ) + { + T1_Token point_token; + + + point_token = point_tokens + p; + + /* don't include delimiting brackets */ + parser->root.cursor = point_token->start + 1; + parser->root.limit = point_token->limit - 1; + + map->design_points[p] = T1_ToInt( parser ); + map->blend_points [p] = T1_ToFixed( parser, 0 ); + } + } + + parser->root.cursor = old_cursor; + parser->root.limit = old_limit; + + Exit: + parser->root.error = error; + } + + + static void + parse_weight_vector( T1_Face face, + T1_Loader loader ) + { + T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; + FT_Int num_designs; + FT_Error error = T1_Err_Ok; + T1_Parser parser = &loader->parser; + PS_Blend blend = face->blend; + T1_Token token; + FT_Int n; + FT_Byte* old_cursor; + FT_Byte* old_limit; + + + T1_ToTokenArray( parser, design_tokens, + T1_MAX_MM_DESIGNS, &num_designs ); + if ( num_designs < 0 ) + { + error = T1_Err_Ignore; + goto Exit; + } + if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) + { + FT_ERROR(( "parse_weight_vector:" )); + FT_ERROR(( " incorrect number of designs: %d\n", + num_designs )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + if ( !blend || !blend->num_designs ) + { + error = t1_allocate_blend( face, num_designs, 0 ); + if ( error ) + goto Exit; + blend = face->blend; + } + else if ( blend->num_designs != (FT_UInt)num_designs ) + { + FT_ERROR(( "parse_weight_vector:" + " /BlendDesignPosition and /WeightVector have\n" )); + FT_ERROR(( " " + " different number of elements!\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + old_cursor = parser->root.cursor; + old_limit = parser->root.limit; + + for ( n = 0; n < num_designs; n++ ) + { + token = design_tokens + n; + parser->root.cursor = token->start; + parser->root.limit = token->limit; + + blend->default_weight_vector[n] = + blend->weight_vector[n] = T1_ToFixed( parser, 0 ); + } + + parser->root.cursor = old_cursor; + parser->root.limit = old_limit; + + Exit: + parser->root.error = error; + } + + +#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */ + + + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static FT_Error + t1_load_keyword( T1_Face face, + T1_Loader loader, + const T1_Field field ) + { + FT_Error error; + void* dummy_object; + void** objects; + FT_UInt max_objects; + PS_Blend blend = face->blend; + + + /* if the keyword has a dedicated callback, call it */ + if ( field->type == T1_FIELD_TYPE_CALLBACK ) + { + field->reader( (FT_Face)face, loader ); + error = loader->parser.root.error; + goto Exit; + } + + /* now, the keyword is either a simple field, or a table of fields; */ + /* we are now going to take care of it */ + switch ( field->location ) + { + case T1_FIELD_LOCATION_FONT_INFO: + dummy_object = &face->type1.font_info; + objects = &dummy_object; + max_objects = 0; + + if ( blend ) + { + objects = (void**)blend->font_infos; + max_objects = blend->num_designs; + } + break; + + case T1_FIELD_LOCATION_PRIVATE: + dummy_object = &face->type1.private_dict; + objects = &dummy_object; + max_objects = 0; + + if ( blend ) + { + objects = (void**)blend->privates; + max_objects = blend->num_designs; + } + break; + + case T1_FIELD_LOCATION_BBOX: + dummy_object = &face->type1.font_bbox; + objects = &dummy_object; + max_objects = 0; + + if ( blend ) + { + objects = (void**)blend->bboxes; + max_objects = blend->num_designs; + } + break; + + default: + dummy_object = &face->type1; + objects = &dummy_object; + max_objects = 0; + } + + if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || + field->type == T1_FIELD_TYPE_FIXED_ARRAY ) + error = T1_Load_Field_Table( &loader->parser, field, + objects, max_objects, 0 ); + else + error = T1_Load_Field( &loader->parser, field, + objects, max_objects, 0 ); + + Exit: + return error; + } + + + static int + is_space( FT_Byte c ) + { + return ( c == ' ' || c == '\t' || + c == '\r' || c == '\n' || c == '\f' || + c == '\0' ); + } + + + static int + read_binary_data( T1_Parser parser, + FT_Long* size, + FT_Byte** base ) + { + FT_Byte* cur; + FT_Byte* limit = parser->root.limit; + + + /* the binary data has one of the following formats */ + /* */ + /* `size' [white*] RD white ....... ND */ + /* `size' [white*] -| white ....... |- */ + /* */ + + T1_Skip_Spaces( parser ); + + cur = parser->root.cursor; + + if ( cur < limit && ft_isdigit( *cur ) ) + { + *size = T1_ToInt( parser ); + + T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */ + + /* there is only one whitespace char after the */ + /* `RD' or `-|' token */ + *base = parser->root.cursor + 1; + + parser->root.cursor += *size + 1; + return 1; + } + + FT_ERROR(( "read_binary_data: invalid size field\n" )); + parser->root.error = T1_Err_Invalid_File_Format; + return 0; + } + + + /* We now define the routines to handle the `/Encoding', `/Subrs', */ + /* and `/CharStrings' dictionaries. */ + + static void + parse_font_matrix( T1_Face face, + T1_Loader loader ) + { + T1_Parser parser = &loader->parser; + FT_Matrix* matrix = &face->type1.font_matrix; + FT_Vector* offset = &face->type1.font_offset; + FT_Face root = (FT_Face)&face->root; + FT_Fixed temp[6]; + FT_Fixed temp_scale; + + + (void)T1_ToFixedArray( parser, 6, temp, 3 ); + + temp_scale = FT_ABS( temp[3] ); + + /* Set Units per EM based on FontMatrix values. We set the value to */ + /* 1000 / temp_scale, because temp_scale was already multiplied by */ + /* 1000 (in t1_tofixed, from psobjs.c). */ + + root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L, + temp_scale ) >> 16 ); + + /* we need to scale the values by 1.0/temp_scale */ + if ( temp_scale != 0x10000L ) + { + temp[0] = FT_DivFix( temp[0], temp_scale ); + temp[1] = FT_DivFix( temp[1], temp_scale ); + temp[2] = FT_DivFix( temp[2], temp_scale ); + temp[4] = FT_DivFix( temp[4], temp_scale ); + temp[5] = FT_DivFix( temp[5], temp_scale ); + temp[3] = 0x10000L; + } + + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + + /* note that the offsets must be expressed in integer font units */ + offset->x = temp[4] >> 16; + offset->y = temp[5] >> 16; + } + + + static void + parse_encoding( T1_Face face, + T1_Loader loader ) + { + T1_Parser parser = &loader->parser; + FT_Byte* cur; + FT_Byte* limit = parser->root.limit; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + T1_Skip_Spaces( parser ); + cur = parser->root.cursor; + if ( cur >= limit ) + { + FT_ERROR(( "parse_encoding: out of bounds!\n" )); + parser->root.error = T1_Err_Invalid_File_Format; + return; + } + + /* if we have a number or `[', the encoding is an array, */ + /* and we must load it now */ + if ( ft_isdigit( *cur ) || *cur == '[' ) + { + T1_Encoding encode = &face->type1.encoding; + FT_Int count, n; + PS_Table char_table = &loader->encoding_table; + FT_Memory memory = parser->root.memory; + FT_Error error; + FT_Bool only_immediates = 0; + + + /* read the number of entries in the encoding; should be 256 */ + if ( *cur == '[' ) + { + count = 256; + only_immediates = 1; + parser->root.cursor++; + } + else + count = (FT_Int)T1_ToInt( parser ); + + T1_Skip_Spaces( parser ); + if ( parser->root.cursor >= limit ) + return; + + /* we use a T1_Table to store our charnames */ + loader->num_chars = encode->num_chars = count; + if ( FT_NEW_ARRAY( encode->char_index, count ) || + FT_NEW_ARRAY( encode->char_name, count ) || + FT_SET_ERROR( psaux->ps_table_funcs->init( + char_table, count, memory ) ) ) + { + parser->root.error = error; + return; + } + + /* We need to `zero' out encoding_table.elements */ + for ( n = 0; n < count; n++ ) + { + char* notdef = (char *)".notdef"; + + + T1_Add_Table( char_table, n, notdef, 8 ); + } + + /* Now we need to read records of the form */ + /* */ + /* ... charcode /charname ... */ + /* */ + /* for each entry in our table. */ + /* */ + /* We simply look for a number followed by an immediate */ + /* name. Note that this ignores correctly the sequence */ + /* that is often seen in type1 fonts: */ + /* */ + /* 0 1 255 { 1 index exch /.notdef put } for dup */ + /* */ + /* used to clean the encoding array before anything else. */ + /* */ + /* Alternatively, if the array is directly given as */ + /* */ + /* /Encoding [ ... ] */ + /* */ + /* we only read immediates. */ + + n = 0; + T1_Skip_Spaces( parser ); + + while ( parser->root.cursor < limit ) + { + cur = parser->root.cursor; + + /* we stop when we encounter a `def' or `]' */ + if ( *cur == 'd' && cur + 3 < limit ) + { + if ( cur[1] == 'e' && + cur[2] == 'f' && + is_space( cur[3] ) ) + { + FT_TRACE6(( "encoding end\n" )); + cur += 3; + break; + } + } + if ( *cur == ']' ) + { + FT_TRACE6(( "encoding end\n" )); + cur++; + break; + } + + /* check whether we've found an entry */ + if ( ft_isdigit( *cur ) || only_immediates ) + { + FT_Int charcode; + + + if ( only_immediates ) + charcode = n; + else + { + charcode = (FT_Int)T1_ToInt( parser ); + T1_Skip_Spaces( parser ); + } + + cur = parser->root.cursor; + + if ( *cur == '/' && cur + 2 < limit && n < count ) + { + FT_PtrDist len; + + + cur++; + + parser->root.cursor = cur; + T1_Skip_PS_Token( parser ); + + len = parser->root.cursor - cur; + + parser->root.error = T1_Add_Table( char_table, charcode, + cur, len + 1 ); + if ( parser->root.error ) + return; + char_table->elements[charcode][len] = '\0'; + + n++; + } + } + else + T1_Skip_PS_Token( parser ); + + T1_Skip_Spaces( parser ); + } + + face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + parser->root.cursor = cur; + } + + /* Otherwise, we should have either `StandardEncoding', */ + /* `ExpertEncoding', or `ISOLatin1Encoding' */ + else + { + if ( cur + 17 < limit && + ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) + face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + + else if ( cur + 15 < limit && + ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) + face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + + else if ( cur + 18 < limit && + ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) + face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + + else + parser->root.error = T1_Err_Ignore; + } + } + + + static void + parse_subrs( T1_Face face, + T1_Loader loader ) + { + T1_Parser parser = &loader->parser; + PS_Table table = &loader->subrs; + FT_Memory memory = parser->root.memory; + FT_Error error; + FT_Int n, num_subrs; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + T1_Skip_Spaces( parser ); + + /* test for empty array */ + if ( parser->root.cursor < parser->root.limit && + *parser->root.cursor == '[' ) + { + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + if ( parser->root.cursor >= parser->root.limit || + *parser->root.cursor != ']' ) + parser->root.error = T1_Err_Invalid_File_Format; + return; + } + + num_subrs = (FT_Int)T1_ToInt( parser ); + + /* position the parser right before the `dup' of the first subr */ + T1_Skip_PS_Token( parser ); /* `array' */ + T1_Skip_Spaces ( parser ); + + /* initialize subrs array -- with synthetic fonts it is possible */ + /* we get here twice */ + if ( !loader->num_subrs ) + { + error = psaux->ps_table_funcs->init( table, num_subrs, memory ); + if ( error ) + goto Fail; + } + + /* the format is simple: */ + /* */ + /* `index' + binary data */ + /* */ + for ( n = 0; n < num_subrs; n++ ) + { + FT_Long idx, size; + FT_Byte* base; + + + /* If the next token isn't `dup', we are also done. This */ + /* happens when there are `holes' in the Subrs array. */ + if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 ) + break; + + T1_Skip_PS_Token( parser ); /* `dup' */ + + idx = T1_ToInt( parser ); + + if ( !read_binary_data( parser, &size, &base ) ) + return; + + /* The binary string is followed by one token, e.g. `NP' */ + /* (bound to `noaccess put') or by two separate tokens: */ + /* `noaccess' & `put'. We position the parser right */ + /* before the next `dup', if any. */ + T1_Skip_PS_Token( parser ); /* `NP' or `|' or `noaccess' */ + T1_Skip_Spaces ( parser ); + + if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 ) + { + T1_Skip_PS_Token( parser ); /* skip `put' */ + T1_Skip_Spaces ( parser ); + } + + /* with synthetic fonts it is possible we get here twice */ + if ( loader->num_subrs ) + continue; + + /* some fonts use a value of -1 for lenIV to indicate that */ + /* the charstrings are unencoded */ + /* */ + /* thanks to Tom Kacvinsky for pointing this out */ + /* */ + if ( face->type1.private_dict.lenIV >= 0 ) + { + FT_Byte* temp; + + + /* t1_decrypt() shouldn't write to base -- make temporary copy */ + if ( FT_ALLOC( temp, size ) ) + goto Fail; + FT_MEM_COPY( temp, base, size ); + psaux->t1_decrypt( temp, size, 4330 ); + size -= face->type1.private_dict.lenIV; + error = T1_Add_Table( table, (FT_Int)idx, + temp + face->type1.private_dict.lenIV, size ); + FT_FREE( temp ); + } + else + error = T1_Add_Table( table, (FT_Int)idx, base, size ); + if ( error ) + goto Fail; + } + + if ( !loader->num_subrs ) + loader->num_subrs = num_subrs; + + return; + + Fail: + parser->root.error = error; + } + + +#define TABLE_EXTEND 5 + + + static void + parse_charstrings( T1_Face face, + T1_Loader loader ) + { + T1_Parser parser = &loader->parser; + PS_Table code_table = &loader->charstrings; + PS_Table name_table = &loader->glyph_names; + PS_Table swap_table = &loader->swap_table; + FT_Memory memory = parser->root.memory; + FT_Error error; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + FT_Byte* cur; + FT_Byte* limit = parser->root.limit; + FT_Int n, num_glyphs; + FT_UInt notdef_index = 0; + FT_Byte notdef_found = 0; + + + num_glyphs = (FT_Int)T1_ToInt( parser ); + /* some fonts like Optima-Oblique not only define the /CharStrings */ + /* array but access it also */ + if ( num_glyphs == 0 || parser->root.error ) + return; + + /* initialize tables, leaving space for addition of .notdef, */ + /* if necessary, and a few other glyphs to handle buggy */ + /* fonts which have more glyphs than specified. */ + + /* for some non-standard fonts like `Optima' which provides */ + /* different outlines depending on the resolution it is */ + /* possible to get here twice */ + if ( !loader->num_glyphs ) + { + error = psaux->ps_table_funcs->init( + code_table, num_glyphs + 1 + TABLE_EXTEND, memory ); + if ( error ) + goto Fail; + + error = psaux->ps_table_funcs->init( + name_table, num_glyphs + 1 + TABLE_EXTEND, memory ); + if ( error ) + goto Fail; + + /* Initialize table for swapping index notdef_index and */ + /* index 0 names and codes (if necessary). */ + + error = psaux->ps_table_funcs->init( swap_table, 4, memory ); + if ( error ) + goto Fail; + } + + n = 0; + + for (;;) + { + FT_Long size; + FT_Byte* base; + + + /* the format is simple: */ + /* `/glyphname' + binary data */ + + T1_Skip_Spaces( parser ); + + cur = parser->root.cursor; + if ( cur >= limit ) + break; + + /* we stop when we find a `def' or `end' keyword */ + if ( cur + 3 < limit && is_space( cur[3] ) ) + { + if ( cur[0] == 'd' && + cur[1] == 'e' && + cur[2] == 'f' ) + break; + + if ( cur[0] == 'e' && + cur[1] == 'n' && + cur[2] == 'd' ) + break; + } + + T1_Skip_PS_Token( parser ); + + if ( *cur == '/' ) + { + FT_PtrDist len; + + + if ( cur + 1 >= limit ) + { + error = T1_Err_Invalid_File_Format; + goto Fail; + } + + cur++; /* skip `/' */ + len = parser->root.cursor - cur; + + if ( !read_binary_data( parser, &size, &base ) ) + return; + + /* for some non-standard fonts like `Optima' which provides */ + /* different outlines depending on the resolution it is */ + /* possible to get here twice */ + if ( loader->num_glyphs ) + continue; + + error = T1_Add_Table( name_table, n, cur, len + 1 ); + if ( error ) + goto Fail; + + /* add a trailing zero to the name table */ + name_table->elements[n][len] = '\0'; + + /* record index of /.notdef */ + if ( *cur == '.' && + ft_strcmp( ".notdef", + (const char*)(name_table->elements[n]) ) == 0 ) + { + notdef_index = n; + notdef_found = 1; + } + + if ( face->type1.private_dict.lenIV >= 0 && + n < num_glyphs + TABLE_EXTEND ) + { + FT_Byte* temp; + + + /* t1_decrypt() shouldn't write to base -- make temporary copy */ + if ( FT_ALLOC( temp, size ) ) + goto Fail; + FT_MEM_COPY( temp, base, size ); + psaux->t1_decrypt( temp, size, 4330 ); + size -= face->type1.private_dict.lenIV; + error = T1_Add_Table( code_table, n, + temp + face->type1.private_dict.lenIV, size ); + FT_FREE( temp ); + } + else + error = T1_Add_Table( code_table, n, base, size ); + if ( error ) + goto Fail; + + n++; + } + } + + if ( loader->num_glyphs ) + return; + else + loader->num_glyphs = n; + + /* if /.notdef is found but does not occupy index 0, do our magic. */ + if ( ft_strcmp( (const char*)".notdef", + (const char*)name_table->elements[0] ) && + notdef_found ) + { + /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ + /* name and code entries to swap_table. Then place notdef_index */ + /* name and code entries into swap_table. Then swap name and code */ + /* entries at indices notdef_index and 0 using values stored in */ + /* swap_table. */ + + /* Index 0 name */ + error = T1_Add_Table( swap_table, 0, + name_table->elements[0], + name_table->lengths [0] ); + if ( error ) + goto Fail; + + /* Index 0 code */ + error = T1_Add_Table( swap_table, 1, + code_table->elements[0], + code_table->lengths [0] ); + if ( error ) + goto Fail; + + /* Index notdef_index name */ + error = T1_Add_Table( swap_table, 2, + name_table->elements[notdef_index], + name_table->lengths [notdef_index] ); + if ( error ) + goto Fail; + + /* Index notdef_index code */ + error = T1_Add_Table( swap_table, 3, + code_table->elements[notdef_index], + code_table->lengths [notdef_index] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( name_table, notdef_index, + swap_table->elements[0], + swap_table->lengths [0] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( code_table, notdef_index, + swap_table->elements[1], + swap_table->lengths [1] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( name_table, 0, + swap_table->elements[2], + swap_table->lengths [2] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( code_table, 0, + swap_table->elements[3], + swap_table->lengths [3] ); + if ( error ) + goto Fail; + + } + else if ( !notdef_found ) + { + /* notdef_index is already 0, or /.notdef is undefined in */ + /* charstrings dictionary. Worry about /.notdef undefined. */ + /* We take index 0 and add it to the end of the table(s) */ + /* and add our own /.notdef glyph to index 0. */ + + /* 0 333 hsbw endchar */ + FT_Byte notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E}; + char* notdef_name = (char *)".notdef"; + + + error = T1_Add_Table( swap_table, 0, + name_table->elements[0], + name_table->lengths [0] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( swap_table, 1, + code_table->elements[0], + code_table->lengths [0] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( name_table, 0, notdef_name, 8 ); + if ( error ) + goto Fail; + + error = T1_Add_Table( code_table, 0, notdef_glyph, 5 ); + + if ( error ) + goto Fail; + + error = T1_Add_Table( name_table, n, + swap_table->elements[0], + swap_table->lengths [0] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( code_table, n, + swap_table->elements[1], + swap_table->lengths [1] ); + if ( error ) + goto Fail; + + /* we added a glyph. */ + loader->num_glyphs = n + 1; + } + + return; + + Fail: + parser->root.error = error; + } + + + /*************************************************************************/ + /* */ + /* Define the token field static variables. This is a set of */ + /* T1_FieldRec variables. */ + /* */ + /*************************************************************************/ + + + static + const T1_FieldRec t1_keywords[] = + { + +#include "t1tokens.h" + + /* now add the special functions... */ + T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix ) + T1_FIELD_CALLBACK( "Encoding", parse_encoding ) + T1_FIELD_CALLBACK( "Subrs", parse_subrs ) + T1_FIELD_CALLBACK( "CharStrings", parse_charstrings ) + +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ) + T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map ) + T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ) + T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector ) +#endif + + { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 } + }; + + +#define T1_FIELD_COUNT \ + ( sizeof ( t1_keywords ) / sizeof ( t1_keywords[0] ) ) + + + static FT_Error + parse_dict( T1_Face face, + T1_Loader loader, + FT_Byte* base, + FT_Long size, + FT_Byte* keyword_flags ) + { + T1_Parser parser = &loader->parser; + FT_Byte *limit, *start_binary = NULL; + FT_Bool have_integer = 0; + + + parser->root.cursor = base; + parser->root.limit = base + size; + parser->root.error = T1_Err_Ok; + + limit = parser->root.limit; + + T1_Skip_Spaces( parser ); + + while ( parser->root.cursor < limit ) + { + FT_Byte* cur; + + + cur = parser->root.cursor; + + /* look for `FontDirectory' which causes problems for some fonts */ + if ( *cur == 'F' && cur + 25 < limit && + ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 ) + { + FT_Byte* cur2; + + + /* skip the `FontDirectory' keyword */ + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + cur = cur2 = parser->root.cursor; + + /* look up the `known' keyword */ + while ( cur < limit ) + { + if ( *cur == 'k' && cur + 5 < limit && + ft_strncmp( (char*)cur, "known", 5 ) == 0 ) + break; + + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + cur = parser->root.cursor; + } + + if ( cur < limit ) + { + T1_TokenRec token; + + + /* skip the `known' keyword and the token following it */ + T1_Skip_PS_Token( parser ); + T1_ToToken( parser, &token ); + + /* if the last token was an array, skip it! */ + if ( token.type == T1_TOKEN_TYPE_ARRAY ) + cur2 = parser->root.cursor; + } + parser->root.cursor = cur2; + have_integer = 0; + } + + /* look for `eexec' */ + else if ( *cur == 'e' && cur + 5 < limit && + ft_strncmp( (char*)cur, "eexec", 5 ) == 0 ) + break; + + /* look for `closefile' which ends the eexec section */ + else if ( *cur == 'c' && cur + 9 < limit && + ft_strncmp( (char*)cur, "closefile", 9 ) == 0 ) + break; + + /* check whether we have an integer */ + else if ( ft_isdigit( *cur ) ) + { + start_binary = cur; + T1_Skip_PS_Token( parser ); + have_integer = 1; + } + + /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ + /* since those tokens are handled by parse_subrs and */ + /* parse_charstrings */ + else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && + have_integer ) + { + FT_Long s; + FT_Byte* b; + + + parser->root.cursor = start_binary; + if ( !read_binary_data( parser, &s, &b ) ) + return T1_Err_Invalid_File_Format; + have_integer = 0; + } + + else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && + have_integer ) + { + FT_Long s; + FT_Byte* b; + + + parser->root.cursor = start_binary; + if ( !read_binary_data( parser, &s, &b ) ) + return T1_Err_Invalid_File_Format; + have_integer = 0; + } + + /* look for immediates */ + else if ( *cur == '/' && cur + 2 < limit ) + { + FT_PtrDist len; + + + cur++; + + parser->root.cursor = cur; + T1_Skip_PS_Token( parser ); + + len = parser->root.cursor - cur; + + if ( len > 0 && len < 22 && parser->root.cursor < limit ) + { + /* now compare the immediate name to the keyword table */ + T1_Field keyword = (T1_Field)t1_keywords; + FT_Byte* keyword_flag = keyword_flags; + + + for (;;) + { + FT_Byte* name; + + + name = (FT_Byte*)keyword->ident; + if ( !name ) + break; + + if ( cur[0] == name[0] && + len == ft_strlen( (const char *)name ) && + ft_memcmp( cur, name, len ) == 0 ) + { + /* We found it -- run the parsing callback! */ + /* We only record the first instance of any */ + /* field to deal adequately with synthetic */ + /* fonts; /Subrs and /CharStrings are */ + /* handled specially. */ + if ( keyword_flag[0] == 0 || + ft_strcmp( (const char*)name, "Subrs" ) == 0 || + ft_strcmp( (const char*)name, "CharStrings") == 0 ) + { + parser->root.error = t1_load_keyword( face, + loader, + keyword ); + if ( parser->root.error == T1_Err_Ok ) + keyword_flag[0] = 1; + else + { + if ( FT_ERROR_BASE( parser->root.error ) == FT_Err_Ignore ) + parser->root.error = T1_Err_Ok; + else + return parser->root.error; + } + } + break; + } + + keyword++; + keyword_flag++; + } + } + + have_integer = 0; + } + else + { + T1_Skip_PS_Token( parser ); + if ( parser->root.error ) + goto Exit; + have_integer = 0; + } + + T1_Skip_Spaces( parser ); + } + + Exit: + return parser->root.error; + } + + + static void + t1_init_loader( T1_Loader loader, + T1_Face face ) + { + FT_UNUSED( face ); + + FT_MEM_ZERO( loader, sizeof ( *loader ) ); + loader->num_glyphs = 0; + loader->num_chars = 0; + + /* initialize the tables -- simply set their `init' field to 0 */ + loader->encoding_table.init = 0; + loader->charstrings.init = 0; + loader->glyph_names.init = 0; + loader->subrs.init = 0; + loader->swap_table.init = 0; + loader->fontdata = 0; + } + + + static void + t1_done_loader( T1_Loader loader ) + { + T1_Parser parser = &loader->parser; + + + /* finalize tables */ + T1_Release_Table( &loader->encoding_table ); + T1_Release_Table( &loader->charstrings ); + T1_Release_Table( &loader->glyph_names ); + T1_Release_Table( &loader->swap_table ); + T1_Release_Table( &loader->subrs ); + + /* finalize parser */ + T1_Finalize_Parser( parser ); + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Open_Face( T1_Face face ) + { + T1_LoaderRec loader; + T1_Parser parser; + T1_Font type1 = &face->type1; + PS_Private priv = &type1->private_dict; + FT_Error error; + FT_Byte keyword_flags[T1_FIELD_COUNT]; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + t1_init_loader( &loader, face ); + + /* default values */ + priv->blue_shift = 7; + priv->blue_fuzz = 1; + priv->lenIV = 4; + priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); + priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); + + parser = &loader.parser; + error = T1_New_Parser( parser, + face->root.stream, + face->root.memory, + psaux ); + if ( error ) + goto Exit; + + { + FT_UInt n; + + + for ( n = 0; n < T1_FIELD_COUNT; n++ ) + keyword_flags[n] = 0; + } + + error = parse_dict( face, &loader, parser->base_dict, parser->base_len, + keyword_flags ); + if ( error ) + goto Exit; + + error = T1_Get_Private_Dict( parser, psaux ); + if ( error ) + goto Exit; + + error = parse_dict( face, &loader, parser->private_dict, + parser->private_len, + keyword_flags ); + if ( error ) + goto Exit; + +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + + /* the following can happen for MM instances; we then treat the */ + /* font as a normal PS font */ + if ( face->blend && + ( !face->blend->num_designs || !face->blend->num_axis ) ) + T1_Done_Blend( face ); + + /* another safety check */ + if ( face->blend ) + { + FT_UInt i; + + + for ( i = 0; i < face->blend->num_axis; i++ ) + if ( !face->blend->design_map[i].num_points ) + { + T1_Done_Blend( face ); + break; + } + } + +#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */ + + /* now, propagate the subrs, charstrings, and glyphnames tables */ + /* to the Type1 data */ + type1->num_glyphs = loader.num_glyphs; + + if ( loader.subrs.init ) + { + loader.subrs.init = 0; + type1->num_subrs = loader.num_subrs; + type1->subrs_block = loader.subrs.block; + type1->subrs = loader.subrs.elements; + type1->subrs_len = loader.subrs.lengths; + } + +#ifdef FT_CONFIG_OPTION_INCREMENTAL + if ( !face->root.internal->incremental_interface ) +#endif + if ( !loader.charstrings.init ) + { + FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face!\n" )); + error = T1_Err_Invalid_File_Format; + } + + loader.charstrings.init = 0; + type1->charstrings_block = loader.charstrings.block; + type1->charstrings = loader.charstrings.elements; + type1->charstrings_len = loader.charstrings.lengths; + + /* we copy the glyph names `block' and `elements' fields; */ + /* the `lengths' field must be released later */ + type1->glyph_names_block = loader.glyph_names.block; + type1->glyph_names = (FT_String**)loader.glyph_names.elements; + loader.glyph_names.block = 0; + loader.glyph_names.elements = 0; + + /* we must now build type1.encoding when we have a custom array */ + if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) + { + FT_Int charcode, idx, min_char, max_char; + FT_Byte* char_name; + FT_Byte* glyph_name; + + + /* OK, we do the following: for each element in the encoding */ + /* table, look up the index of the glyph having the same name */ + /* the index is then stored in type1.encoding.char_index, and */ + /* a the name to type1.encoding.char_name */ + + min_char = +32000; + max_char = -32000; + + charcode = 0; + for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) + { + type1->encoding.char_index[charcode] = 0; + type1->encoding.char_name [charcode] = (char *)".notdef"; + + char_name = loader.encoding_table.elements[charcode]; + if ( char_name ) + for ( idx = 0; idx < type1->num_glyphs; idx++ ) + { + glyph_name = (FT_Byte*)type1->glyph_names[idx]; + if ( ft_strcmp( (const char*)char_name, + (const char*)glyph_name ) == 0 ) + { + type1->encoding.char_index[charcode] = (FT_UShort)idx; + type1->encoding.char_name [charcode] = (char*)glyph_name; + + /* Change min/max encoded char only if glyph name is */ + /* not /.notdef */ + if ( ft_strcmp( (const char*)".notdef", + (const char*)glyph_name ) != 0 ) + { + if ( charcode < min_char ) + min_char = charcode; + if ( charcode > max_char ) + max_char = charcode; + } + break; + } + } + } + + /* + * Yes, this happens: Certain PDF-embedded fonts have only a + * `.notdef' glyph defined! + */ + + if ( min_char > max_char ) + { + min_char = 0; + max_char = loader.encoding_table.max_elems; + } + + type1->encoding.code_first = min_char; + type1->encoding.code_last = max_char; + type1->encoding.num_chars = loader.num_chars; + } + + Exit: + t1_done_loader( &loader ); + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1load.h b/Utilities/vtkfreetype/src/type1/t1load.h new file mode 100644 index 0000000..9823f53 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1load.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* t1load.h */ +/* */ +/* Type 1 font loader (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1LOAD_H__ +#define __T1LOAD_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H +#include FT_MULTIPLE_MASTERS_H + +#include "t1parse.h" + + +FT_BEGIN_HEADER + + + typedef struct T1_Loader_ + { + T1_ParserRec parser; /* parser used to read the stream */ + + FT_Int num_chars; /* number of characters in encoding */ + PS_TableRec encoding_table; /* PS_Table used to store the */ + /* encoding character names */ + + FT_Int num_glyphs; + PS_TableRec glyph_names; + PS_TableRec charstrings; + PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */ + + FT_Int num_subrs; + PS_TableRec subrs; + FT_Bool fontdata; + + } T1_LoaderRec, *T1_Loader; + + + FT_LOCAL( FT_Error ) + T1_Open_Face( T1_Face face ); + +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + + FT_LOCAL( FT_Error ) + T1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ); + + FT_LOCAL_DEF( FT_Error ) + T1_Get_MM_Var( T1_Face face, + FT_MM_Var* *master ); + + FT_LOCAL( FT_Error ) + T1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + FT_LOCAL( FT_Error ) + T1_Set_MM_Design( T1_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + FT_LOCAL_DEF( FT_Error ) + T1_Set_Var_Design( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + FT_LOCAL( void ) + T1_Done_Blend( T1_Face face ); + +#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ + + +FT_END_HEADER + +#endif /* __T1LOAD_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1objs.c b/Utilities/vtkfreetype/src/type1/t1objs.c new file mode 100644 index 0000000..a832ee0 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1objs.c @@ -0,0 +1,552 @@ +/***************************************************************************/ +/* */ +/* t1objs.c */ +/* */ +/* Type 1 objects manager (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_TRUETYPE_IDS_H + +#include "t1gload.h" +#include "t1load.h" + +#include "t1errors.h" + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include "t1afm.h" +#endif + +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1objs + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /* note that we store the global hints in the size's "internal" root */ + /* field */ + /* */ + /*************************************************************************/ + + + static PSH_Globals_Funcs + T1_Size_Get_Globals_Funcs( T1_Size size ) + { + T1_Face face = (T1_Face)size->root.face; + PSHinter_Service pshinter = (PSHinter_Service)face->pshinter; + FT_Module module; + + + module = FT_Get_Module( size->root.face->driver->root.library, + "pshinter" ); + return ( module && pshinter && pshinter->get_globals_funcs ) + ? pshinter->get_globals_funcs( module ) + : 0 ; + } + + + FT_LOCAL_DEF( void ) + T1_Size_Done( T1_Size size ) + { + if ( size->root.internal ) + { + PSH_Globals_Funcs funcs; + + + funcs = T1_Size_Get_Globals_Funcs( size ); + if ( funcs ) + funcs->destroy( (PSH_Globals)size->root.internal ); + + size->root.internal = 0; + } + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Size_Init( T1_Size size ) + { + FT_Error error = 0; + PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); + + + if ( funcs ) + { + PSH_Globals globals; + T1_Face face = (T1_Face)size->root.face; + + + error = funcs->create( size->root.face->memory, + &face->type1.private_dict, &globals ); + if ( !error ) + size->root.internal = (FT_Size_Internal)(void*)globals; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Size_Reset( T1_Size size ) + { + PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); + FT_Error error = 0; + + + if ( funcs ) + error = funcs->set_scale( (PSH_Globals)size->root.internal, + size->root.metrics.x_scale, + size->root.metrics.y_scale, + 0, 0 ); + return error; + } + + + /*************************************************************************/ + /* */ + /* SLOT FUNCTIONS */ + /* */ + /*************************************************************************/ + + FT_LOCAL_DEF( void ) + T1_GlyphSlot_Done( T1_GlyphSlot slot ) + { + slot->root.internal->glyph_hints = 0; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_GlyphSlot_Init( T1_GlyphSlot slot ) + { + T1_Face face; + PSHinter_Service pshinter; + + + face = (T1_Face)slot->root.face; + pshinter = (PSHinter_Service)face->pshinter; + + if ( pshinter ) + { + FT_Module module; + + + module = FT_Get_Module( slot->root.face->driver->root.library, "pshinter" ); + if (module) + { + T1_Hints_Funcs funcs; + + funcs = pshinter->get_t1_funcs( module ); + slot->root.internal->glyph_hints = (void*)funcs; + } + } + return 0; + } + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* T1_Face_Done */ + /* */ + /* <Description> */ + /* The face object destructor. */ + /* */ + /* <Input> */ + /* face :: A typeless pointer to the face object to destroy. */ + /* */ + FT_LOCAL_DEF( void ) + T1_Face_Done( T1_Face face ) + { + FT_Memory memory; + T1_Font type1 = &face->type1; + + + if ( face ) + { + memory = face->root.memory; + +#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT + /* release multiple masters information */ + T1_Done_Blend( face ); + face->blend = 0; +#endif + + /* release font info strings */ + { + PS_FontInfo info = &type1->font_info; + + + FT_FREE( info->version ); + FT_FREE( info->notice ); + FT_FREE( info->full_name ); + FT_FREE( info->family_name ); + FT_FREE( info->weight ); + } + + /* release top dictionary */ + FT_FREE( type1->charstrings_len ); + FT_FREE( type1->charstrings ); + FT_FREE( type1->glyph_names ); + + FT_FREE( type1->subrs ); + FT_FREE( type1->subrs_len ); + + FT_FREE( type1->subrs_block ); + FT_FREE( type1->charstrings_block ); + FT_FREE( type1->glyph_names_block ); + + FT_FREE( type1->encoding.char_index ); + FT_FREE( type1->encoding.char_name ); + FT_FREE( type1->font_name ); + +#ifndef T1_CONFIG_OPTION_NO_AFM + /* release afm data if present */ + if ( face->afm_data ) + T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); +#endif + + /* release unicode map, if any */ + FT_FREE( face->unicode_map.maps ); + face->unicode_map.num_maps = 0; + + face->root.family_name = 0; + face->root.style_name = 0; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* T1_Face_Init */ + /* */ + /* <Description> */ + /* The face object constructor. */ + /* */ + /* <Input> */ + /* stream :: input stream where to load font data. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* <InOut> */ + /* face :: The face record to build. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + T1_Face_Init( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Service_PsCMaps psnames; + PSAux_Service psaux; + T1_Font type1 = &face->type1; + PS_FontInfo info = &type1->font_info; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + FT_UNUSED( stream ); + + + face->root.num_faces = 1; + + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); + face->psnames = psnames; + + face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), + "psaux" ); + psaux = (PSAux_Service)face->psaux; + + face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), + "pshinter" ); + + /* open the tokenizer; this will also check the font format */ + error = T1_Open_Face( face ); + if ( error ) + goto Exit; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Exit; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "T1_Face_Init: invalid face index\n" )); + error = T1_Err_Invalid_Argument; + goto Exit; + } + + /* now load the font program into the face object */ + + /* initialize the face object fields */ + + /* set up root face fields */ + { + FT_Face root = (FT_Face)&face->root; + + + root->num_glyphs = type1->num_glyphs; + root->face_index = face_index; + + root->face_flags = FT_FACE_FLAG_SCALABLE; + root->face_flags |= FT_FACE_FLAG_HORIZONTAL; + root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; + + if ( info->is_fixed_pitch ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + if ( face->blend ) + root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; + + /* XXX: TODO -- add kerning with .afm support */ + + /* get style name -- be careful, some broken fonts only */ + /* have a `/FontName' dictionary entry! */ + root->family_name = info->family_name; + /* assume "Regular" style if we don't know better */ + root->style_name = (char *)"Regular"; + if ( root->family_name ) + { + char* full = info->full_name; + char* family = root->family_name; + + + if ( full ) + { + while ( *full ) + { + if ( *full == *family ) + { + family++; + full++; + } + else + { + if ( *full == ' ' || *full == '-' ) + full++; + else if ( *family == ' ' || *family == '-' ) + family++; + else + { + if ( !*family ) + root->style_name = full; + break; + } + } + } + } + } + else + { + /* do we have a `/FontName'? */ + if ( type1->font_name ) + root->family_name = type1->font_name; + } + + /* compute style flags */ + root->style_flags = 0; + if ( info->italic_angle ) + root->style_flags |= FT_STYLE_FLAG_ITALIC; + if ( info->weight ) + { + if ( !ft_strcmp( info->weight, "Bold" ) || + !ft_strcmp( info->weight, "Black" ) ) + root->style_flags |= FT_STYLE_FLAG_BOLD; + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox.xMin = type1->font_bbox.xMin >> 16; + root->bbox.yMin = type1->font_bbox.yMin >> 16; + root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFFU ) >> 16; + root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFFU ) >> 16; + + /* Set units_per_EM if we didn't set it in parse_font_matrix. */ + if ( !root->units_per_EM ) + root->units_per_EM = 1000; + + root->ascender = (FT_Short)( root->bbox.yMax ); + root->descender = (FT_Short)( root->bbox.yMin ); + root->height = (FT_Short)( + ( ( root->ascender - root->descender ) * 12 ) / 10 ); + + /* now compute the maximum advance width */ + root->max_advance_width = + (FT_Short)( root->bbox.xMax ); + { + FT_Pos max_advance; + + + error = T1_Compute_Max_Advance( face, &max_advance ); + + /* in case of error, keep the standard width */ + if ( !error ) + root->max_advance_width = (FT_Short)max_advance; + else + error = 0; /* clear error */ + } + + root->max_advance_height = root->height; + + root->underline_position = (FT_Short)info->underline_position; + root->underline_thickness = (FT_Short)info->underline_thickness; + + root->internal->max_points = 0; + root->internal->max_contours = 0; + } + + { + FT_Face root = &face->root; + + + if ( psnames && psaux ) + { + FT_CharMapRec charmap; + T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; + FT_CMap_Class clazz; + + + charmap.face = root; + + /* first of all, try to synthetize a Unicode charmap */ + charmap.platform_id = 3; + charmap.encoding_id = 1; + charmap.encoding = FT_ENCODING_UNICODE; + + FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); + + /* now, generate an Adobe Standard encoding when appropriate */ + charmap.platform_id = 7; + clazz = NULL; + + switch ( type1->encoding_type ) + { + case T1_ENCODING_TYPE_STANDARD: + charmap.encoding = FT_ENCODING_ADOBE_STANDARD; + charmap.encoding_id = TT_ADOBE_ID_STANDARD; + clazz = cmap_classes->standard; + break; + + case T1_ENCODING_TYPE_EXPERT: + charmap.encoding = FT_ENCODING_ADOBE_EXPERT; + charmap.encoding_id = TT_ADOBE_ID_EXPERT; + clazz = cmap_classes->expert; + break; + + case T1_ENCODING_TYPE_ARRAY: + charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; + charmap.encoding_id = TT_ADOBE_ID_CUSTOM; + clazz = cmap_classes->custom; + break; + + case T1_ENCODING_TYPE_ISOLATIN1: + charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; + charmap.encoding_id = TT_ADOBE_ID_LATIN_1; + clazz = cmap_classes->unicode; + break; + + default: + ; + } + + if ( clazz ) + FT_CMap_New( clazz, NULL, &charmap, NULL ); + +#if 0 + /* Select default charmap */ + if (root->num_charmaps) + root->charmap = root->charmaps[0]; +#endif + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* T1_Driver_Init */ + /* */ + /* <Description> */ + /* Initializes a given Type 1 driver object. */ + /* */ + /* <Input> */ + /* driver :: A handle to the target driver object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + T1_Driver_Init( T1_Driver driver ) + { + FT_UNUSED( driver ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* T1_Driver_Done */ + /* */ + /* <Description> */ + /* Finalizes a given Type 1 driver. */ + /* */ + /* <Input> */ + /* driver :: A handle to the target Type 1 driver. */ + /* */ + FT_LOCAL_DEF( void ) + T1_Driver_Done( T1_Driver driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1objs.h b/Utilities/vtkfreetype/src/type1/t1objs.h new file mode 100644 index 0000000..9aeb10d --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1objs.h @@ -0,0 +1,170 @@ +/***************************************************************************/ +/* */ +/* t1objs.h */ +/* */ +/* Type 1 objects manager (specification). */ +/* */ +/* Copyright 1996-2001, 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1OBJS_H__ +#define __T1OBJS_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_OBJECTS_H +#include FT_CONFIG_CONFIG_H +#include FT_INTERNAL_TYPE1_TYPES_H + + +FT_BEGIN_HEADER + + + /* The following structures must be defined by the hinter */ + typedef struct T1_Size_Hints_ T1_Size_Hints; + typedef struct T1_Glyph_Hints_ T1_Glyph_Hints; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* T1_Driver */ + /* */ + /* <Description> */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct T1_DriverRec_ *T1_Driver; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* T1_Size */ + /* */ + /* <Description> */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct T1_SizeRec_* T1_Size; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* T1_GlyphSlot */ + /* */ + /* <Description> */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct T1_GlyphSlotRec_* T1_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* T1_CharMap */ + /* */ + /* <Description> */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* <Note> */ + /* The Type 1 format doesn't use a charmap but an encoding table. */ + /* The driver is responsible for making up charmap objects */ + /* corresponding to these tables. */ + /* */ + typedef struct T1_CharMapRec_* T1_CharMap; + + + /*************************************************************************/ + /* */ + /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* T1_SizeRec */ + /* */ + /* <Description> */ + /* Type 1 size record. */ + /* */ + typedef struct T1_SizeRec_ + { + FT_SizeRec root; + + } T1_SizeRec; + + + FT_LOCAL( void ) + T1_Size_Done( T1_Size size ); + + FT_LOCAL( FT_Error ) + T1_Size_Reset( T1_Size size ); + + FT_LOCAL( FT_Error ) + T1_Size_Init( T1_Size size ); + + + /*************************************************************************/ + /* */ + /* <Type> */ + /* T1_GlyphSlotRec */ + /* */ + /* <Description> */ + /* Type 1 glyph slot record. */ + /* */ + typedef struct T1_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Int max_points; + FT_Int max_contours; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + } T1_GlyphSlotRec; + + + FT_LOCAL( FT_Error ) + T1_Face_Init( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + FT_LOCAL( void ) + T1_Face_Done( T1_Face face ); + + FT_LOCAL( FT_Error ) + T1_GlyphSlot_Init( T1_GlyphSlot slot ); + + FT_LOCAL( void ) + T1_GlyphSlot_Done( T1_GlyphSlot slot ); + + FT_LOCAL( FT_Error ) + T1_Driver_Init( T1_Driver driver ); + + FT_LOCAL( void ) + T1_Driver_Done( T1_Driver driver ); + + +FT_END_HEADER + +#endif /* __T1OBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1parse.c b/Utilities/vtkfreetype/src/type1/t1parse.c new file mode 100644 index 0000000..544aa09 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1parse.c @@ -0,0 +1,443 @@ +/***************************************************************************/ +/* */ +/* t1parse.c */ +/* */ +/* Type 1 parser (body). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The Type 1 parser is in charge of the following: */ + /* */ + /* - provide an implementation of a growing sequence of objects called */ + /* a `T1_Table' (used to build various tables needed by the loader). */ + /* */ + /* - opening .pfb and .pfa files to extract their top-level and private */ + /* dictionaries. */ + /* */ + /* - read numbers, arrays & strings from any dictionary. */ + /* */ + /* See `t1load.c' to see how data is loaded from the font file. */ + /* */ + /*************************************************************************/ + + +#include <ft2build.h> +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H + +#include "t1parse.h" + +#include "t1errors.h" + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1parse + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static FT_Error + read_pfb_tag( FT_Stream stream, + FT_UShort *atag, + FT_Long *asize ) + { + FT_Error error; + FT_UShort tag; + FT_Long size; + + + *atag = 0; + *asize = 0; + + if ( !FT_READ_USHORT( tag ) ) + { + if ( tag == 0x8001U || tag == 0x8002U ) + { + if ( !FT_READ_LONG_LE( size ) ) + *asize = size; + } + + *atag = tag; + } + + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + T1_New_Parser( T1_Parser parser, + FT_Stream stream, + FT_Memory memory, + PSAux_Service psaux ) + { + FT_Error error; + FT_UShort tag; + FT_Long size; + + + psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); + + parser->stream = stream; + parser->base_len = 0; + parser->base_dict = 0; + parser->private_len = 0; + parser->private_dict = 0; + parser->in_pfb = 0; + parser->in_memory = 0; + parser->single_block = 0; + + /******************************************************************/ + /* */ + /* Here a short summary of what is going on: */ + /* */ + /* When creating a new Type 1 parser, we try to locate and load */ + /* the base dictionary if this is possible (i.e. for PFB */ + /* files). Otherwise, we load the whole font into memory. */ + /* */ + /* When `loading' the base dictionary, we only setup pointers */ + /* in the case of a memory-based stream. Otherwise, we */ + /* allocate and load the base dictionary in it. */ + /* */ + /* parser->in_pfb is set if we are in a binary (".pfb") font. */ + /* parser->in_memory is set if we have a memory stream. */ + /* */ + + /* try to compute the size of the base dictionary; */ + /* look for a Postscript binary file tag, i.e 0x8001 */ + if ( FT_STREAM_SEEK( 0L ) ) + goto Exit; + + error = read_pfb_tag( stream, &tag, &size ); + if ( error ) + goto Exit; + + if ( tag != 0x8001U ) + { + /* assume that this is a PFA file for now; an error will */ + /* be produced later when more things are checked */ + if ( FT_STREAM_SEEK( 0L ) ) + goto Exit; + size = stream->size; + } + else + parser->in_pfb = 1; + + /* now, try to load `size' bytes of the `base' dictionary we */ + /* found previously */ + + /* if it is a memory-based resource, set up pointers */ + if ( !stream->read ) + { + parser->base_dict = (FT_Byte*)stream->base + stream->pos; + parser->base_len = size; + parser->in_memory = 1; + + /* check that the `size' field is valid */ + if ( FT_STREAM_SKIP( size ) ) + goto Exit; + } + else + { + /* read segment in memory */ + if ( FT_ALLOC( parser->base_dict, size ) || + FT_STREAM_READ( parser->base_dict, size ) ) + goto Exit; + parser->base_len = size; + } + + /* Now check font format; we must see `%!PS-AdobeFont-1' */ + /* or `%!FontType' */ + { + if ( size <= 16 || + ( ft_strncmp( (const char*)parser->base_dict, + "%!PS-AdobeFont-1", 16 ) && + ft_strncmp( (const char*)parser->base_dict, + "%!FontType", 10 ) ) ) + { + FT_TRACE2(( "[not a Type1 font]\n" )); + error = T1_Err_Unknown_File_Format; + } + else + { + parser->root.base = parser->base_dict; + parser->root.cursor = parser->base_dict; + parser->root.limit = parser->root.cursor + parser->base_len; + } + } + + Exit: + if ( error && !parser->in_memory ) + FT_FREE( parser->base_dict ); + + return error; + } + + + FT_LOCAL_DEF( void ) + T1_Finalize_Parser( T1_Parser parser ) + { + FT_Memory memory = parser->root.memory; + + + /* always free the private dictionary */ + FT_FREE( parser->private_dict ); + + /* free the base dictionary only when we have a disk stream */ + if ( !parser->in_memory ) + FT_FREE( parser->base_dict ); + + parser->root.funcs.done( &parser->root ); + } + + + FT_LOCAL_DEF( FT_Error ) + T1_Get_Private_Dict( T1_Parser parser, + PSAux_Service psaux ) + { + FT_Stream stream = parser->stream; + FT_Memory memory = parser->root.memory; + FT_Error error = T1_Err_Ok; + FT_Long size; + + + if ( parser->in_pfb ) + { + /* in the case of the PFB format, the private dictionary can be */ + /* made of several segments. We thus first read the number of */ + /* segments to compute the total size of the private dictionary */ + /* then re-read them into memory. */ + FT_Long start_pos = FT_STREAM_POS(); + FT_UShort tag; + + + parser->private_len = 0; + for (;;) + { + error = read_pfb_tag( stream, &tag, &size ); + if ( error ) + goto Fail; + + if ( tag != 0x8002U ) + break; + + parser->private_len += size; + + if ( FT_STREAM_SKIP( size ) ) + goto Fail; + } + + /* Check that we have a private dictionary there */ + /* and allocate private dictionary buffer */ + if ( parser->private_len == 0 ) + { + FT_ERROR(( "T1_Get_Private_Dict:" )); + FT_ERROR(( " invalid private dictionary section\n" )); + error = T1_Err_Invalid_File_Format; + goto Fail; + } + + if ( FT_STREAM_SEEK( start_pos ) || + FT_ALLOC( parser->private_dict, parser->private_len ) ) + goto Fail; + + parser->private_len = 0; + for (;;) + { + error = read_pfb_tag( stream, &tag, &size ); + if ( error || tag != 0x8002U ) + { + error = T1_Err_Ok; + break; + } + + if ( FT_STREAM_READ( parser->private_dict + parser->private_len, + size ) ) + goto Fail; + + parser->private_len += size; + } + } + else + { + /* We have already `loaded' the whole PFA font file into memory; */ + /* if this is a memory resource, allocate a new block to hold */ + /* the private dict. Otherwise, simply overwrite into the base */ + /* dictionary block in the heap. */ + + /* first of all, look at the `eexec' keyword */ + FT_Byte* cur = parser->base_dict; + FT_Byte* limit = cur + parser->base_len; + FT_Byte c; + + + Again: + for (;;) + { + c = cur[0]; + if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ + /* newline + 4 chars */ + { + if ( cur[1] == 'e' && + cur[2] == 'x' && + cur[3] == 'e' && + cur[4] == 'c' ) + break; + } + cur++; + if ( cur >= limit ) + { + FT_ERROR(( "T1_Get_Private_Dict:" )); + FT_ERROR(( " could not find `eexec' keyword\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + } + + /* check whether `eexec' was real -- it could be in a comment */ + /* or string (as e.g. in u003043t.gsf from ghostscript) */ + + parser->root.cursor = parser->base_dict; + parser->root.limit = cur + 9; + + cur = parser->root.cursor; + limit = parser->root.limit; + + while ( cur < limit ) + { + if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 ) + goto Found; + + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + cur = parser->root.cursor; + } + + /* we haven't found the correct `eexec'; go back and continue */ + /* searching */ + + cur = limit; + limit = parser->base_dict + parser->base_len; + goto Again; + + /* now determine where to write the _encrypted_ binary private */ + /* dictionary. We overwrite the base dictionary for disk-based */ + /* resources and allocate a new block otherwise */ + + Found: + parser->root.limit = parser->base_dict + parser->base_len; + + T1_Skip_PS_Token( parser ); + cur = parser->root.cursor; + if ( *cur == '\r' ) + { + cur++; + if ( *cur == '\n' ) + cur++; + } + else if ( *cur == '\n' ) + cur++; + else + { + FT_ERROR(( "T1_Get_Private_Dict:" )); + FT_ERROR(( " `eexec' not properly terminated\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) ); + + if ( parser->in_memory ) + { + /* note that we allocate one more byte to put a terminating `0' */ + if ( FT_ALLOC( parser->private_dict, size + 1 ) ) + goto Fail; + parser->private_len = size; + } + else + { + parser->single_block = 1; + parser->private_dict = parser->base_dict; + parser->private_len = size; + parser->base_dict = 0; + parser->base_len = 0; + } + + /* now determine whether the private dictionary is encoded in binary */ + /* or hexadecimal ASCII format -- decode it accordingly */ + + /* we need to access the next 4 bytes (after the final \r following */ + /* the `eexec' keyword); if they all are hexadecimal digits, then */ + /* we have a case of ASCII storage */ + + if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && + ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) + { + /* ASCII hexadecimal encoding */ + FT_Long len; + + + parser->root.cursor = cur; + (void)psaux->ps_parser_funcs->to_bytes( &parser->root, + parser->private_dict, + parser->private_len, + &len, + 0 ); + parser->private_len = len; + + /* put a safeguard */ + parser->private_dict[len] = '\0'; + } + else + /* binary encoding -- copy the private dict */ + FT_MEM_MOVE( parser->private_dict, cur, size ); + } + + /* we now decrypt the encoded binary private dictionary */ + psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U ); + + /* replace the four random bytes at the beginning with whitespace */ + parser->private_dict[0] = ' '; + parser->private_dict[1] = ' '; + parser->private_dict[2] = ' '; + parser->private_dict[3] = ' '; + + parser->root.base = parser->private_dict; + parser->root.cursor = parser->private_dict; + parser->root.limit = parser->root.cursor + parser->private_len; + + Fail: + Exit: + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1parse.h b/Utilities/vtkfreetype/src/type1/t1parse.h new file mode 100644 index 0000000..6fa4ca6 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1parse.h @@ -0,0 +1,135 @@ +/***************************************************************************/ +/* */ +/* t1parse.h */ +/* */ +/* Type 1 parser (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T1PARSE_H__ +#define __T1PARSE_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_TYPE1_TYPES_H +#include FT_INTERNAL_STREAM_H + + +FT_BEGIN_HEADER + + + /*************************************************************************/ + /* */ + /* <Struct> */ + /* T1_ParserRec */ + /* */ + /* <Description> */ + /* A PS_ParserRec is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* <Fields> */ + /* root :: The root parser. */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* base_dict :: A pointer to the top-level dictionary. */ + /* */ + /* base_len :: The length in bytes of the top dictionary. */ + /* */ + /* private_dict :: A pointer to the private dictionary. */ + /* */ + /* private_len :: The length in bytes of the private dictionary. */ + /* */ + /* in_pfb :: A boolean. Indicates that we are handling a PFB */ + /* file. */ + /* */ + /* in_memory :: A boolean. Indicates a memory-based stream. */ + /* */ + /* single_block :: A boolean. Indicates that the private dictionary */ + /* is stored in lieu of the base dictionary. */ + /* */ + typedef struct T1_ParserRec_ + { + PS_ParserRec root; + FT_Stream stream; + + FT_Byte* base_dict; + FT_Long base_len; + + FT_Byte* private_dict; + FT_Long private_len; + + FT_Bool in_pfb; + FT_Bool in_memory; + FT_Bool single_block; + + } T1_ParserRec, *T1_Parser; + + +#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l ) +#define T1_Done_Table( p ) \ + do \ + { \ + if ( (p)->funcs.done ) \ + (p)->funcs.done( p ); \ + } while ( 0 ) +#define T1_Release_Table( p ) \ + do \ + { \ + if ( (p)->funcs.release ) \ + (p)->funcs.release( p ); \ + } while ( 0 ) + + +#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root ) +#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root ) + +#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root ) +#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t ) + +#define T1_ToCoordArray( p, m, c ) \ + (p)->root.funcs.to_coord_array( &(p)->root, m, c ) +#define T1_ToFixedArray( p, m, f, t ) \ + (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t ) +#define T1_ToToken( p, t ) \ + (p)->root.funcs.to_token( &(p)->root, t ) +#define T1_ToTokenArray( p, t, m, c ) \ + (p)->root.funcs.to_token_array( &(p)->root, t, m, c ) + +#define T1_Load_Field( p, f, o, m, pf ) \ + (p)->root.funcs.load_field( &(p)->root, f, o, m, pf ) + +#define T1_Load_Field_Table( p, f, o, m, pf ) \ + (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf ) + + + FT_LOCAL( FT_Error ) + T1_New_Parser( T1_Parser parser, + FT_Stream stream, + FT_Memory memory, + PSAux_Service psaux ); + + FT_LOCAL( FT_Error ) + T1_Get_Private_Dict( T1_Parser parser, + PSAux_Service psaux ); + + FT_LOCAL( void ) + T1_Finalize_Parser( T1_Parser parser ); + + +FT_END_HEADER + +#endif /* __T1PARSE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/t1tokens.h b/Utilities/vtkfreetype/src/type1/t1tokens.h new file mode 100644 index 0000000..a3cc952 --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/t1tokens.h @@ -0,0 +1,84 @@ +/***************************************************************************/ +/* */ +/* t1tokens.h */ +/* */ +/* Type 1 tokenizer (specification). */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#undef FT_STRUCTURE +#define FT_STRUCTURE PS_FontInfoRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_FONT_INFO + + T1_FIELD_STRING( "version", version ) + T1_FIELD_STRING( "Notice", notice ) + T1_FIELD_STRING( "FullName", full_name ) + T1_FIELD_STRING( "FamilyName", family_name ) + T1_FIELD_STRING( "Weight", weight ) + + /* we use pointers to detect modifications made by synthetic fonts */ + T1_FIELD_NUM ( "ItalicAngle", italic_angle ) + T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch ) + T1_FIELD_NUM ( "UnderlinePosition", underline_position ) + T1_FIELD_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef FT_STRUCTURE +#define FT_STRUCTURE PS_PrivateRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_PRIVATE + + T1_FIELD_NUM ( "UniqueID", unique_id ) + T1_FIELD_NUM ( "lenIV", lenIV ) + T1_FIELD_NUM ( "LanguageGroup", language_group ) + T1_FIELD_NUM ( "password", password ) + + T1_FIELD_FIXED_1000( "BlueScale", blue_scale ) + T1_FIELD_NUM ( "BlueShift", blue_shift ) + T1_FIELD_NUM ( "BlueFuzz", blue_fuzz ) + + T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 ) + T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 ) + T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 ) + T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 ) + + T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 ) + T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 ) + T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 ) + T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 ) + + T1_FIELD_FIXED ( "ExpansionFactor", expansion_factor ) + + +#undef FT_STRUCTURE +#define FT_STRUCTURE T1_FontRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_FONT_DICT + + T1_FIELD_KEY ( "FontName", font_name ) + T1_FIELD_NUM ( "PaintType", paint_type ) + T1_FIELD_NUM ( "FontType", font_type ) + T1_FIELD_FIXED( "StrokeWidth", stroke_width ) + +#undef FT_STRUCTURE +#define FT_STRUCTURE FT_BBox +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_BBOX + + T1_FIELD_BBOX("FontBBox", xMin ) + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type1/type1.c b/Utilities/vtkfreetype/src/type1/type1.c new file mode 100644 index 0000000..ccc12be --- /dev/null +++ b/Utilities/vtkfreetype/src/type1/type1.c @@ -0,0 +1,33 @@ +/***************************************************************************/ +/* */ +/* type1.c */ +/* */ +/* FreeType Type 1 driver component (body only). */ +/* */ +/* Copyright 1996-2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "t1parse.c" +#include "t1load.c" +#include "t1objs.c" +#include "t1driver.c" +#include "t1gload.c" + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include "t1afm.c" +#endif + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42drivr.c b/Utilities/vtkfreetype/src/type42/t42drivr.c new file mode 100644 index 0000000..2afe2db --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42drivr.c @@ -0,0 +1,233 @@ +/***************************************************************************/ +/* */ +/* t42drivr.c */ +/* */ +/* High-level Type 42 driver interface (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by Roberto Alameda. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This driver implements Type42 fonts as described in the */ + /* Technical Note #5012 from Adobe, with these limitations: */ + /* */ + /* 1) CID Fonts are not currently supported. */ + /* 2) Incremental fonts making use of the GlyphDirectory keyword */ + /* will be loaded, but the rendering will be using the TrueType */ + /* tables. */ + /* 3) As for Type1 fonts, CDevProc is not supported. */ + /* 4) The Metrics dictionary is not supported. */ + /* 5) AFM metrics are not supported. */ + /* */ + /* In other words, this driver supports Type42 fonts derived from */ + /* TrueType fonts in a non-CID manner, as done by usual conversion */ + /* programs. */ + /* */ + /*************************************************************************/ + + +#include "t42drivr.h" +#include "t42objs.h" +#include "t42error.h" +#include FT_INTERNAL_DEBUG_H + +#include FT_SERVICE_XFREE86_NAME_H +#include FT_SERVICE_GLYPH_DICT_H +#include FT_SERVICE_POSTSCRIPT_NAME_H +#include FT_SERVICE_POSTSCRIPT_INFO_H + +#undef FT_COMPONENT +#define FT_COMPONENT trace_t42 + + + /* + * + * GLYPH DICT SERVICE + * + */ + + static FT_Error + t42_get_glyph_name( T42_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_String* gname; + + + gname = face->type1.glyph_names[glyph_index]; + + if ( buffer_max > 0 ) + { + FT_UInt len = (FT_UInt)( ft_strlen( gname ) ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + FT_MEM_COPY( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T42_Err_Ok; + } + + + static FT_UInt + t42_get_name_index( T42_Face face, + FT_String* glyph_name ) + { + FT_Int i; + FT_String* gname; + + + for ( i = 0; i < face->type1.num_glyphs; i++ ) + { + gname = face->type1.glyph_names[i]; + + if ( !ft_strcmp( glyph_name, gname ) ) + return (FT_UInt)ft_atol( (const char *)face->type1.charstrings[i] ); + } + + return 0; + } + + + static const FT_Service_GlyphDictRec t42_service_glyph_dict = + { + (FT_GlyphDict_GetNameFunc) t42_get_glyph_name, + (FT_GlyphDict_NameIndexFunc)t42_get_name_index + }; + + + /* + * + * POSTSCRIPT NAME SERVICE + * + */ + + static const char* + t42_get_ps_font_name( T42_Face face ) + { + return (const char*)face->type1.font_name; + } + + + static const FT_Service_PsFontNameRec t42_service_ps_font_name = + { + (FT_PsName_GetFunc)t42_get_ps_font_name + }; + + + /* + * + * POSTSCRIPT INFO SERVICE + * + */ + + static FT_Error + t42_ps_get_font_info( FT_Face face, + PS_FontInfoRec* afont_info ) + { + *afont_info = ((T42_Face)face)->type1.font_info; + return 0; + } + + + static FT_Int + t42_ps_has_glyph_names( FT_Face face ) + { + FT_UNUSED( face ); + return 1; + } + + + static const FT_Service_PsInfoRec t42_service_ps_info = + { + (PS_GetFontInfoFunc) t42_ps_get_font_info, + (PS_HasGlyphNamesFunc)t42_ps_has_glyph_names + }; + + + /* + * + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec t42_services[] = + { + { FT_SERVICE_ID_GLYPH_DICT, &t42_service_glyph_dict }, + { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t42_service_ps_font_name }, + { FT_SERVICE_ID_POSTSCRIPT_INFO, &t42_service_ps_info }, + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_TYPE_42 }, + { NULL, NULL } + }; + + + static FT_Module_Interface + T42_Get_Interface( FT_Driver driver, + const FT_String* t42_interface ) + { + FT_UNUSED( driver ); + + return ft_service_list_lookup( t42_services, t42_interface ); + } + + + const FT_Driver_ClassRec t42_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_SCALABLE | +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + FT_MODULE_DRIVER_HAS_HINTER, +#else + 0, +#endif + + sizeof ( T42_DriverRec ), + + "type42", + 0x10000L, + 0x20000L, + + 0, /* format interface */ + + (FT_Module_Constructor)T42_Driver_Init, + (FT_Module_Destructor) T42_Driver_Done, + (FT_Module_Requester) T42_Get_Interface, + }, + + sizeof ( T42_FaceRec ), + sizeof ( T42_SizeRec ), + sizeof ( T42_GlyphSlotRec ), + + (FT_Face_InitFunc) T42_Face_Init, + (FT_Face_DoneFunc) T42_Face_Done, + (FT_Size_InitFunc) T42_Size_Init, + (FT_Size_DoneFunc) T42_Size_Done, + (FT_Slot_InitFunc) T42_GlyphSlot_Init, + (FT_Slot_DoneFunc) T42_GlyphSlot_Done, + + (FT_Size_ResetPointsFunc) T42_Size_SetChars, + (FT_Size_ResetPixelsFunc) T42_Size_SetPixels, + (FT_Slot_LoadFunc) T42_GlyphSlot_Load, + + (FT_Face_GetKerningFunc) 0, + (FT_Face_AttachFunc) 0, + + (FT_Face_GetAdvancesFunc) 0 + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42drivr.h b/Utilities/vtkfreetype/src/type42/t42drivr.h new file mode 100644 index 0000000..98b7410 --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42drivr.h @@ -0,0 +1,38 @@ +/***************************************************************************/ +/* */ +/* t42drivr.h */ +/* */ +/* High-level Type 42 driver interface (specification). */ +/* */ +/* Copyright 2002 by Roberto Alameda. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T42DRIVR_H__ +#define __T42DRIVR_H__ + + +#include <ft2build.h> +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) t42_driver_class; + + +FT_END_HEADER + + +#endif /* __T42DRIVR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42error.h b/Utilities/vtkfreetype/src/type42/t42error.h new file mode 100644 index 0000000..b230910 --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42error.h @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* t42error.h */ +/* */ +/* Type 42 error codes (specification only). */ +/* */ +/* Copyright 2002, 2003 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the Type 42 error enumeration constants. */ + /* */ + /*************************************************************************/ + +#ifndef __T42ERROR_H__ +#define __T42ERROR_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX T42_Err_ +#define FT_ERR_BASE FT_Mod_Err_Type42 + +#include FT_ERRORS_H + +#endif /* __T42ERROR_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42objs.c b/Utilities/vtkfreetype/src/type42/t42objs.c new file mode 100644 index 0000000..8837136 --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42objs.c @@ -0,0 +1,643 @@ +/***************************************************************************/ +/* */ +/* t42objs.c */ +/* */ +/* Type 42 objects manager (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by Roberto Alameda. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "t42objs.h" +#include "t42parse.h" +#include "t42error.h" +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_LIST_H + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_t42 + + + static FT_Error + T42_Open_Face( T42_Face face ) + { + T42_LoaderRec loader; + T42_Parser parser; + T1_Font type1 = &face->type1; + FT_Memory memory = face->root.memory; + FT_Error error; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + t42_loader_init( &loader, face ); + + parser = &loader.parser; + + if ( FT_ALLOC( face->ttf_data, 12 ) ) + goto Exit; + + error = t42_parser_init( parser, + face->root.stream, + memory, + psaux); + if ( error ) + goto Exit; + + error = t42_parse_dict( face, &loader, + parser->base_dict, parser->base_len ); + + if ( type1->font_type != 42 ) + { + error = T42_Err_Unknown_File_Format; + goto Exit; + } + + /* now, propagate the charstrings and glyphnames tables */ + /* to the Type1 data */ + type1->num_glyphs = loader.num_glyphs; + + if ( !loader.charstrings.init ) + { + FT_ERROR(( "T42_Open_Face: no charstrings array in face!\n" )); + error = T42_Err_Invalid_File_Format; + } + + loader.charstrings.init = 0; + type1->charstrings_block = loader.charstrings.block; + type1->charstrings = loader.charstrings.elements; + type1->charstrings_len = loader.charstrings.lengths; + + /* we copy the glyph names `block' and `elements' fields; */ + /* the `lengths' field must be released later */ + type1->glyph_names_block = loader.glyph_names.block; + type1->glyph_names = (FT_String**)loader.glyph_names.elements; + loader.glyph_names.block = 0; + loader.glyph_names.elements = 0; + + /* we must now build type1.encoding when we have a custom array */ + if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) + { + FT_Int charcode, idx, min_char, max_char; + FT_Byte* char_name; + FT_Byte* glyph_name; + + + /* OK, we do the following: for each element in the encoding */ + /* table, look up the index of the glyph having the same name */ + /* as defined in the CharStrings array. */ + /* The index is then stored in type1.encoding.char_index, and */ + /* the name in type1.encoding.char_name */ + + min_char = +32000; + max_char = -32000; + + charcode = 0; + for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) + { + type1->encoding.char_index[charcode] = 0; + type1->encoding.char_name [charcode] = (char *)".notdef"; + + char_name = loader.encoding_table.elements[charcode]; + if ( char_name ) + for ( idx = 0; idx < type1->num_glyphs; idx++ ) + { + glyph_name = (FT_Byte*)type1->glyph_names[idx]; + if ( ft_strcmp( (const char*)char_name, + (const char*)glyph_name ) == 0 ) + { + type1->encoding.char_index[charcode] = (FT_UShort)idx; + type1->encoding.char_name [charcode] = (char*)glyph_name; + + /* Change min/max encoded char only if glyph name is */ + /* not /.notdef */ + if ( ft_strcmp( (const char*)".notdef", + (const char*)glyph_name ) != 0 ) + { + if ( charcode < min_char ) + min_char = charcode; + if ( charcode > max_char ) + max_char = charcode; + } + break; + } + } + } + type1->encoding.code_first = min_char; + type1->encoding.code_last = max_char; + type1->encoding.num_chars = loader.num_chars; + } + + Exit: + t42_loader_done( &loader ); + return error; + } + + + /***************** Driver Functions *************/ + + + FT_LOCAL_DEF( FT_Error ) + T42_Face_Init( FT_Stream stream, + T42_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Service_PsCMaps psnames; + PSAux_Service psaux; + FT_Face root = (FT_Face)&face->root; + T1_Font type1 = &face->type1; + PS_FontInfo info = &type1->font_info; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + FT_UNUSED( stream ); + + + face->ttf_face = NULL; + face->root.num_faces = 1; + + FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); + face->psnames = psnames; + + face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), + "psaux" ); + psaux = (PSAux_Service)face->psaux; + + /* open the tokenizer, this will also check the font format */ + error = T42_Open_Face( face ); + if ( error ) + goto Exit; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Exit; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "T42_Face_Init: invalid face index\n" )); + error = T42_Err_Invalid_Argument; + goto Exit; + } + + /* Now load the font program into the face object */ + + /* Init the face object fields */ + /* Now set up root face fields */ + + root->num_glyphs = type1->num_glyphs; + root->num_charmaps = 0; + root->face_index = face_index; + + root->face_flags = FT_FACE_FLAG_SCALABLE; + root->face_flags |= FT_FACE_FLAG_HORIZONTAL; + root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; + + if ( info->is_fixed_pitch ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX: TODO -- add kerning with .afm support */ + + /* get style name -- be careful, some broken fonts only */ + /* have a `/FontName' dictionary entry! */ + root->family_name = info->family_name; + /* assume "Regular" style if we don't know better */ + root->style_name = (char *)"Regular"; + if ( root->family_name ) + { + char* full = info->full_name; + char* family = root->family_name; + + + if ( full ) + { + while ( *full ) + { + if ( *full == *family ) + { + family++; + full++; + } + else + { + if ( *full == ' ' || *full == '-' ) + full++; + else if ( *family == ' ' || *family == '-' ) + family++; + else + { + if ( !*family ) + root->style_name = full; + break; + } + } + } + } + } + else + { + /* do we have a `/FontName'? */ + if ( type1->font_name ) + root->family_name = type1->font_name; + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + /* Load the TTF font embedded in the T42 font */ + error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ), + face->ttf_data, + face->ttf_size, + 0, + &face->ttf_face ); + if ( error ) + goto Exit; + + FT_Done_Size( face->ttf_face->size ); + + /* Ignore info in FontInfo dictionary and use the info from the */ + /* loaded TTF font. The PostScript interpreter also ignores it. */ + root->bbox = face->ttf_face->bbox; + root->units_per_EM = face->ttf_face->units_per_EM; + + root->ascender = face->ttf_face->ascender; + root->descender = face->ttf_face->descender; + root->height = face->ttf_face->height; + + root->max_advance_width = face->ttf_face->max_advance_width; + root->max_advance_height = face->ttf_face->max_advance_height; + + root->underline_position = (FT_Short)info->underline_position; + root->underline_thickness = (FT_Short)info->underline_thickness; + + root->internal->max_points = 0; + root->internal->max_contours = 0; + + /* compute style flags */ + root->style_flags = 0; + if ( info->italic_angle ) + root->style_flags |= FT_STYLE_FLAG_ITALIC; + + if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) + root->style_flags |= FT_STYLE_FLAG_BOLD; + + if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) + root->face_flags |= FT_FACE_FLAG_VERTICAL; + + { + if ( psnames && psaux ) + { + FT_CharMapRec charmap; + T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; + FT_CMap_Class clazz; + + + charmap.face = root; + + /* first of all, try to synthetize a Unicode charmap */ + charmap.platform_id = 3; + charmap.encoding_id = 1; + charmap.encoding = FT_ENCODING_UNICODE; + + FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); + + /* now, generate an Adobe Standard encoding when appropriate */ + charmap.platform_id = 7; + clazz = NULL; + + switch ( type1->encoding_type ) + { + case T1_ENCODING_TYPE_STANDARD: + charmap.encoding = FT_ENCODING_ADOBE_STANDARD; + charmap.encoding_id = 0; + clazz = cmap_classes->standard; + break; + + case T1_ENCODING_TYPE_EXPERT: + charmap.encoding = FT_ENCODING_ADOBE_EXPERT; + charmap.encoding_id = 1; + clazz = cmap_classes->expert; + break; + + case T1_ENCODING_TYPE_ARRAY: + charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; + charmap.encoding_id = 2; + clazz = cmap_classes->custom; + break; + + case T1_ENCODING_TYPE_ISOLATIN1: + charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; + charmap.encoding_id = 3; + clazz = cmap_classes->unicode; + break; + + default: + ; + } + + if ( clazz ) + FT_CMap_New( clazz, NULL, &charmap, NULL ); + +#if 0 + /* Select default charmap */ + if ( root->num_charmaps ) + root->charmap = root->charmaps[0]; +#endif + } + } + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + T42_Face_Done( T42_Face face ) + { + T1_Font type1; + PS_FontInfo info; + FT_Memory memory; + + + if ( face ) + { + type1 = &face->type1; + info = &type1->font_info; + memory = face->root.memory; + + /* delete internal ttf face prior to freeing face->ttf_data */ + if ( face->ttf_face ) + FT_Done_Face( face->ttf_face ); + + /* release font info strings */ + FT_FREE( info->version ); + FT_FREE( info->notice ); + FT_FREE( info->full_name ); + FT_FREE( info->family_name ); + FT_FREE( info->weight ); + + /* release top dictionary */ + FT_FREE( type1->charstrings_len ); + FT_FREE( type1->charstrings ); + FT_FREE( type1->glyph_names ); + + FT_FREE( type1->charstrings_block ); + FT_FREE( type1->glyph_names_block ); + + FT_FREE( type1->encoding.char_index ); + FT_FREE( type1->encoding.char_name ); + FT_FREE( type1->font_name ); + + FT_FREE( face->ttf_data ); + +#if 0 + /* release afm data if present */ + if ( face->afm_data ) + T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); +#endif + + /* release unicode map, if any */ + FT_FREE( face->unicode_map.maps ); + face->unicode_map.num_maps = 0; + + face->root.family_name = 0; + face->root.style_name = 0; + } + } + + + /*************************************************************************/ + /* */ + /* <Function> */ + /* T42_Driver_Init */ + /* */ + /* <Description> */ + /* Initializes a given Type 42 driver object. */ + /* */ + /* <Input> */ + /* driver :: A handle to the target driver object. */ + /* */ + /* <Return> */ + /* FreeType error code. 0 means success. */ + /* */ + FT_LOCAL_DEF( FT_Error ) + T42_Driver_Init( T42_Driver driver ) + { + FT_Module ttmodule; + + + ttmodule = FT_Get_Module( FT_MODULE(driver)->library, "truetype" ); + driver->ttclazz = (FT_Driver_Class)ttmodule->clazz; + + return T42_Err_Ok; + } + + + FT_LOCAL_DEF( void ) + T42_Driver_Done( T42_Driver driver ) + { + FT_UNUSED( driver ); + } + + + FT_LOCAL_DEF( FT_Error ) + T42_Size_Init( T42_Size size ) + { + FT_Face face = size->root.face; + T42_Face t42face = (T42_Face)face; + FT_Size ttsize; + FT_Error error = T42_Err_Ok; + + + error = FT_New_Size( t42face->ttf_face, &ttsize ); + size->ttsize = ttsize; + + FT_Activate_Size( ttsize ); + + return error; + } + + + FT_LOCAL_DEF( void ) + T42_Size_Done( T42_Size size ) + { + FT_Face face = size->root.face; + T42_Face t42face = (T42_Face)face; + FT_ListNode node; + + + node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize ); + if ( node ) + { + FT_Done_Size( size->ttsize ); + size->ttsize = NULL; + } + } + + + FT_LOCAL_DEF( FT_Error ) + T42_GlyphSlot_Init( T42_GlyphSlot slot ) + { + FT_Face face = slot->root.face; + T42_Face t42face = (T42_Face)face; + FT_GlyphSlot ttslot; + FT_Error error = T42_Err_Ok; + + + if ( face->glyph == NULL ) + { + /* First glyph slot for this face */ + slot->ttslot = t42face->ttf_face->glyph; + } + else + { + error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot ); + slot->ttslot = ttslot; + } + + return error; + } + + + FT_LOCAL_DEF( void ) + T42_GlyphSlot_Done( T42_GlyphSlot slot ) + { + FT_Face face = slot->root.face; + T42_Face t42face = (T42_Face)face; + FT_GlyphSlot cur = t42face->ttf_face->glyph; + + + while ( cur ) + { + if ( cur == slot->ttslot ) + { + FT_Done_GlyphSlot( slot->ttslot ); + break; + } + + cur = cur->next; + } + } + + + + FT_LOCAL_DEF( FT_Error ) + T42_Size_SetChars( T42_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_Face face = size->root.face; + T42_Face t42face = (T42_Face)face; + + + FT_Activate_Size( size->ttsize ); + + return FT_Set_Char_Size( t42face->ttf_face, + char_width, + char_height, + horz_resolution, + vert_resolution ); + } + + + FT_LOCAL_DEF( FT_Error ) + T42_Size_SetPixels( T42_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ) + { + FT_Face face = size->root.face; + T42_Face t42face = (T42_Face)face; + + + FT_Activate_Size( size->ttsize ); + + return FT_Set_Pixel_Sizes( t42face->ttf_face, + pixel_width, + pixel_height ); + } + + + static void + t42_glyphslot_clear( FT_GlyphSlot slot ) + { + /* free bitmap if needed */ + ft_glyphslot_free_bitmap( slot ); + + /* clear all public fields in the glyph slot */ + FT_ZERO( &slot->metrics ); + FT_ZERO( &slot->outline ); + FT_ZERO( &slot->bitmap ); + + slot->bitmap_left = 0; + slot->bitmap_top = 0; + slot->num_subglyphs = 0; + slot->subglyphs = 0; + slot->control_data = 0; + slot->control_len = 0; + slot->other = 0; + slot->format = FT_GLYPH_FORMAT_NONE; + + slot->linearHoriAdvance = 0; + slot->linearVertAdvance = 0; + } + + + FT_LOCAL_DEF( FT_Error ) + T42_GlyphSlot_Load( FT_GlyphSlot glyph, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + FT_Error error; + T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph; + T42_Size t42size = (T42_Size)size; + FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz; + + + t42_glyphslot_clear( t42slot->ttslot ); + error = ttclazz->load_glyph( t42slot->ttslot, + t42size->ttsize, + glyph_index, + load_flags | FT_LOAD_NO_BITMAP ); + + if ( !error ) + { + glyph->metrics = t42slot->ttslot->metrics; + + glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance; + glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance; + + glyph->format = t42slot->ttslot->format; + glyph->outline = t42slot->ttslot->outline; + + glyph->bitmap = t42slot->ttslot->bitmap; + glyph->bitmap_left = t42slot->ttslot->bitmap_left; + glyph->bitmap_top = t42slot->ttslot->bitmap_top; + + glyph->num_subglyphs = t42slot->ttslot->num_subglyphs; + glyph->subglyphs = t42slot->ttslot->subglyphs; + + glyph->control_data = t42slot->ttslot->control_data; + glyph->control_len = t42slot->ttslot->control_len; + } + + return error; + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42objs.h b/Utilities/vtkfreetype/src/type42/t42objs.h new file mode 100644 index 0000000..6238095 --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42objs.h @@ -0,0 +1,126 @@ +/***************************************************************************/ +/* */ +/* t42objs.h */ +/* */ +/* Type 42 objects manager (specification). */ +/* */ +/* Copyright 2002, 2003 by Roberto Alameda. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T42OBJS_H__ +#define __T42OBJS_H__ + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_TYPE1_TABLES_H +#include FT_INTERNAL_TYPE1_TYPES_H +#include "t42types.h" +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DRIVER_H +#include FT_SERVICE_POSTSCRIPT_CMAPS_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H + + +FT_BEGIN_HEADER + + + /* Type42 size */ + typedef struct T42_SizeRec_ + { + FT_SizeRec root; + FT_Size ttsize; + + } T42_SizeRec, *T42_Size; + + + /* Type42 slot */ + typedef struct T42_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + FT_GlyphSlot ttslot; + + } T42_GlyphSlotRec, *T42_GlyphSlot; + + + /* Type 42 driver */ + typedef struct T42_DriverRec_ + { + FT_DriverRec root; + FT_Driver_Class ttclazz; + void* extension_component; + + } T42_DriverRec, *T42_Driver; + + + /* */ + + + FT_LOCAL( FT_Error ) + T42_Face_Init( FT_Stream stream, + T42_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + + FT_LOCAL( void ) + T42_Face_Done( T42_Face face ); + + + FT_LOCAL( FT_Error ) + T42_Size_Init( T42_Size size ); + + + FT_LOCAL( FT_Error ) + T42_Size_SetChars( T42_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + FT_LOCAL( FT_Error ) + T42_Size_SetPixels( T42_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + FT_LOCAL( void ) + T42_Size_Done( T42_Size size ); + + + FT_LOCAL( FT_Error ) + T42_GlyphSlot_Init( T42_GlyphSlot slot ); + + + FT_LOCAL( FT_Error ) + T42_GlyphSlot_Load( FT_GlyphSlot glyph, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ); + + FT_LOCAL( void ) + T42_GlyphSlot_Done( T42_GlyphSlot slot ); + + + FT_LOCAL( FT_Error ) + T42_Driver_Init( T42_Driver driver ); + + FT_LOCAL( void ) + T42_Driver_Done( T42_Driver driver ); + + /* */ + +FT_END_HEADER + + +#endif /* __T42OBJS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42parse.c b/Utilities/vtkfreetype/src/type42/t42parse.c new file mode 100644 index 0000000..ff53a3e --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42parse.c @@ -0,0 +1,1115 @@ +/***************************************************************************/ +/* */ +/* t42parse.c */ +/* */ +/* Type 42 font parser (body). */ +/* */ +/* Copyright 2002, 2003, 2004 by Roberto Alameda. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include "t42parse.h" +#include "t42error.h" +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_LIST_H +#include FT_INTERNAL_POSTSCRIPT_AUX_H + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t42 + + + static void + t42_parse_font_matrix( T42_Face face, + T42_Loader loader ); + static void + t42_parse_encoding( T42_Face face, + T42_Loader loader ); + + static void + t42_parse_charstrings( T42_Face face, + T42_Loader loader ); + + static void + t42_parse_sfnts( T42_Face face, + T42_Loader loader ); + + + static const + T1_FieldRec t42_keywords[] = { + +#undef FT_STRUCTURE +#define FT_STRUCTURE T1_FontInfo +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_FONT_INFO + + T1_FIELD_STRING( "version", version ) + T1_FIELD_STRING( "Notice", notice ) + T1_FIELD_STRING( "FullName", full_name ) + T1_FIELD_STRING( "FamilyName", family_name ) + T1_FIELD_STRING( "Weight", weight ) + T1_FIELD_NUM ( "ItalicAngle", italic_angle ) + T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch ) + T1_FIELD_NUM ( "UnderlinePosition", underline_position ) + T1_FIELD_NUM ( "UnderlineThickness", underline_thickness ) + +#undef FT_STRUCTURE +#define FT_STRUCTURE T1_FontRec +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_FONT_DICT + + T1_FIELD_KEY ( "FontName", font_name ) + T1_FIELD_NUM ( "PaintType", paint_type ) + T1_FIELD_NUM ( "FontType", font_type ) + T1_FIELD_FIXED( "StrokeWidth", stroke_width ) + +#undef FT_STRUCTURE +#define FT_STRUCTURE FT_BBox +#undef T1CODE +#define T1CODE T1_FIELD_LOCATION_BBOX + + T1_FIELD_BBOX("FontBBox", xMin ) + + T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix ) + T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding ) + T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings ) + T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts ) + + { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 } + }; + + +#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l ) +#define T1_Done_Table( p ) \ + do \ + { \ + if ( (p)->funcs.done ) \ + (p)->funcs.done( p ); \ + } while ( 0 ) +#define T1_Release_Table( p ) \ + do \ + { \ + if ( (p)->funcs.release ) \ + (p)->funcs.release( p ); \ + } while ( 0 ) + +#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root ) +#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root ) + +#define T1_ToInt( p ) \ + (p)->root.funcs.to_int( &(p)->root ) +#define T1_ToBytes( p, b, m, n, d ) \ + (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d ) + +#define T1_ToFixedArray( p, m, f, t ) \ + (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t ) +#define T1_ToToken( p, t ) \ + (p)->root.funcs.to_token( &(p)->root, t ) + +#define T1_Load_Field( p, f, o, m, pf ) \ + (p)->root.funcs.load_field( &(p)->root, f, o, m, pf ) +#define T1_Load_Field_Table( p, f, o, m, pf ) \ + (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf ) + + + /********************* Parsing Functions ******************/ + + FT_LOCAL_DEF( FT_Error ) + t42_parser_init( T42_Parser parser, + FT_Stream stream, + FT_Memory memory, + PSAux_Service psaux ) + { + FT_Error error = T42_Err_Ok; + FT_Long size; + + + psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); + + parser->stream = stream; + parser->base_len = 0; + parser->base_dict = 0; + parser->in_memory = 0; + + /*******************************************************************/ + /* */ + /* Here a short summary of what is going on: */ + /* */ + /* When creating a new Type 42 parser, we try to locate and load */ + /* the base dictionary, loading the whole font into memory. */ + /* */ + /* When `loading' the base dictionary, we only set up pointers */ + /* in the case of a memory-based stream. Otherwise, we allocate */ + /* and load the base dictionary in it. */ + /* */ + /* parser->in_memory is set if we have a memory stream. */ + /* */ + + if ( FT_STREAM_SEEK( 0L ) ) + goto Exit; + + size = stream->size; + + /* now, try to load `size' bytes of the `base' dictionary we */ + /* found previously */ + + /* if it is a memory-based resource, set up pointers */ + if ( !stream->read ) + { + parser->base_dict = (FT_Byte*)stream->base + stream->pos; + parser->base_len = size; + parser->in_memory = 1; + + /* check that the `size' field is valid */ + if ( FT_STREAM_SKIP( size ) ) + goto Exit; + } + else + { + /* read segment in memory */ + if ( FT_ALLOC( parser->base_dict, size ) || + FT_STREAM_READ( parser->base_dict, size ) ) + goto Exit; + + parser->base_len = size; + } + + /* Now check font format; we must see `%!PS-TrueTypeFont' */ + if ( size <= 17 || + ( ft_strncmp( (const char*)parser->base_dict, + "%!PS-TrueTypeFont", 17 ) ) ) + error = T42_Err_Unknown_File_Format; + else + { + parser->root.base = parser->base_dict; + parser->root.cursor = parser->base_dict; + parser->root.limit = parser->root.cursor + parser->base_len; + } + + Exit: + if ( error && !parser->in_memory ) + FT_FREE( parser->base_dict ); + + return error; + } + + + FT_LOCAL_DEF( void ) + t42_parser_done( T42_Parser parser ) + { + FT_Memory memory = parser->root.memory; + + + /* free the base dictionary only when we have a disk stream */ + if ( !parser->in_memory ) + FT_FREE( parser->base_dict ); + + parser->root.funcs.done( &parser->root ); + } + + + static int + t42_is_space( FT_Byte c ) + { + return ( c == ' ' || c == '\t' || + c == '\r' || c == '\n' || c == '\f' || + c == '\0' ); + } + + + static void + t42_parse_font_matrix( T42_Face face, + T42_Loader loader ) + { + T42_Parser parser = &loader->parser; + FT_Matrix* matrix = &face->type1.font_matrix; + FT_Vector* offset = &face->type1.font_offset; + FT_Face root = (FT_Face)&face->root; + FT_Fixed temp[6]; + FT_Fixed temp_scale; + + + (void)T1_ToFixedArray( parser, 6, temp, 3 ); + + temp_scale = FT_ABS( temp[3] ); + + /* Set Units per EM based on FontMatrix values. We set the value to */ + /* 1000 / temp_scale, because temp_scale was already multiplied by */ + /* 1000 (in t1_tofixed, from psobjs.c). */ + + root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L, + temp_scale ) >> 16 ); + + /* we need to scale the values by 1.0/temp_scale */ + if ( temp_scale != 0x10000L ) { + temp[0] = FT_DivFix( temp[0], temp_scale ); + temp[1] = FT_DivFix( temp[1], temp_scale ); + temp[2] = FT_DivFix( temp[2], temp_scale ); + temp[4] = FT_DivFix( temp[4], temp_scale ); + temp[5] = FT_DivFix( temp[5], temp_scale ); + temp[3] = 0x10000L; + } + + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + + /* note that the offsets must be expressed in integer font units */ + offset->x = temp[4] >> 16; + offset->y = temp[5] >> 16; + } + + + static void + t42_parse_encoding( T42_Face face, + T42_Loader loader ) + { + T42_Parser parser = &loader->parser; + FT_Byte* cur; + FT_Byte* limit = parser->root.limit; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + + T1_Skip_Spaces( parser ); + cur = parser->root.cursor; + if ( cur >= limit ) + { + FT_ERROR(( "t42_parse_encoding: out of bounds!\n" )); + parser->root.error = T42_Err_Invalid_File_Format; + return; + } + + /* if we have a number or `[', the encoding is an array, */ + /* and we must load it now */ + if ( ft_isdigit( *cur ) || *cur == '[' ) + { + T1_Encoding encode = &face->type1.encoding; + FT_UInt count, n; + PS_Table char_table = &loader->encoding_table; + FT_Memory memory = parser->root.memory; + FT_Error error; + FT_Bool only_immediates = 0; + + + /* read the number of entries in the encoding; should be 256 */ + if ( *cur == '[' ) + { + count = 256; + only_immediates = 1; + parser->root.cursor++; + } + else + count = (FT_UInt)T1_ToInt( parser ); + + T1_Skip_Spaces( parser ); + if ( parser->root.cursor >= limit ) + return; + + /* we use a T1_Table to store our charnames */ + loader->num_chars = encode->num_chars = count; + if ( FT_NEW_ARRAY( encode->char_index, count ) || + FT_NEW_ARRAY( encode->char_name, count ) || + FT_SET_ERROR( psaux->ps_table_funcs->init( + char_table, count, memory ) ) ) + { + parser->root.error = error; + return; + } + + /* We need to `zero' out encoding_table.elements */ + for ( n = 0; n < count; n++ ) + { + char* notdef = (char *)".notdef"; + + + T1_Add_Table( char_table, n, notdef, 8 ); + } + + /* Now we need to read records of the form */ + /* */ + /* ... charcode /charname ... */ + /* */ + /* for each entry in our table. */ + /* */ + /* We simply look for a number followed by an immediate */ + /* name. Note that this ignores correctly the sequence */ + /* that is often seen in type42 fonts: */ + /* */ + /* 0 1 255 { 1 index exch /.notdef put } for dup */ + /* */ + /* used to clean the encoding array before anything else. */ + /* */ + /* Alternatively, if the array is directly given as */ + /* */ + /* /Encoding [ ... ] */ + /* */ + /* we only read immediates. */ + + n = 0; + T1_Skip_Spaces( parser ); + + while ( parser->root.cursor < limit ) + { + cur = parser->root.cursor; + + /* we stop when we encounter `def' or `]' */ + if ( *cur == 'd' && cur + 3 < limit ) + { + if ( cur[1] == 'e' && + cur[2] == 'f' && + t42_is_space( cur[3] ) ) + { + FT_TRACE6(( "encoding end\n" )); + cur += 3; + break; + } + } + if ( *cur == ']' ) + { + FT_TRACE6(( "encoding end\n" )); + cur++; + break; + } + + /* check whether we've found an entry */ + if ( ft_isdigit( *cur ) || only_immediates ) + { + FT_Int charcode; + + + if ( only_immediates ) + charcode = n; + else + { + charcode = (FT_Int)T1_ToInt( parser ); + T1_Skip_Spaces( parser ); + } + + cur = parser->root.cursor; + + if ( *cur == '/' && cur + 2 < limit && n < count ) + { + FT_PtrDist len; + + + cur++; + + parser->root.cursor = cur; + T1_Skip_PS_Token( parser ); + + len = parser->root.cursor - cur; + + parser->root.error = T1_Add_Table( char_table, charcode, + cur, len + 1 ); + char_table->elements[charcode][len] = '\0'; + if ( parser->root.error ) + return; + + n++; + } + } + else + T1_Skip_PS_Token( parser ); + + T1_Skip_Spaces( parser ); + } + + face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; + parser->root.cursor = cur; + } + + /* Otherwise, we should have either `StandardEncoding', */ + /* `ExpertEncoding', or `ISOLatin1Encoding' */ + else + { + if ( cur + 17 < limit && + ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) + face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; + + else if ( cur + 15 < limit && + ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) + face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; + + else if ( cur + 18 < limit && + ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) + face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; + + else + { + FT_ERROR(( "t42_parse_encoding: invalid token!\n" )); + parser->root.error = T42_Err_Invalid_File_Format; + } + } + } + + + typedef enum + { + BEFORE_START, + BEFORE_TABLE_DIR, + OTHER_TABLES + + } T42_Load_Status; + + + static void + t42_parse_sfnts( T42_Face face, + T42_Loader loader ) + { + T42_Parser parser = &loader->parser; + FT_Memory memory = parser->root.memory; + FT_Byte* cur; + FT_Byte* limit = parser->root.limit; + FT_Error error; + FT_Int num_tables = 0; + FT_ULong count, ttf_size = 0; + + FT_Long n, string_size, old_string_size, real_size; + FT_Byte* string_buf = NULL; + FT_Bool alloc = 0; + + T42_Load_Status status; + + + /* The format is */ + /* */ + /* /sfnts [ <hexstring> <hexstring> ... ] def */ + /* */ + /* or */ + /* */ + /* /sfnts [ */ + /* <num_bin_bytes> RD <binary data> */ + /* <num_bin_bytes> RD <binary data> */ + /* ... */ + /* ] def */ + /* */ + /* with exactly one space after the `RD' token. */ + + T1_Skip_Spaces( parser ); + + if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' ) + { + FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + + T1_Skip_Spaces( parser ); + status = BEFORE_START; + string_size = 0; + old_string_size = 0; + count = 0; + + while ( parser->root.cursor < limit ) + { + cur = parser->root.cursor; + + if ( *cur == ']' ) + { + parser->root.cursor++; + goto Exit; + } + + else if ( *cur == '<' ) + { + T1_Skip_PS_Token( parser ); + if ( parser->root.error ) + goto Exit; + + /* don't include delimiters */ + string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 ); + if ( FT_REALLOC( string_buf, old_string_size, string_size ) ) + goto Fail; + + alloc = 1; + + parser->root.cursor = cur; + (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 ); + old_string_size = string_size; + string_size = real_size; + } + + else if ( ft_isdigit( *cur ) ) + { + string_size = T1_ToInt( parser ); + + T1_Skip_PS_Token( parser ); /* `RD' */ + + string_buf = parser->root.cursor + 1; /* one space after `RD' */ + + parser->root.cursor += string_size + 1; + if ( parser->root.cursor >= limit ) + { + FT_ERROR(( "t42_parse_sfnts: too many binary data!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + } + + /* A string can have a trailing zero byte for padding. Ignore it. */ + if ( string_buf[string_size - 1] == 0 && ( string_size % 2 == 1 ) ) + string_size--; + + for ( n = 0; n < string_size; n++ ) + { + switch ( status ) + { + case BEFORE_START: + /* load offset table, 12 bytes */ + if ( count < 12 ) + { + face->ttf_data[count++] = string_buf[n]; + continue; + } + else + { + num_tables = 16 * face->ttf_data[4] + face->ttf_data[5]; + status = BEFORE_TABLE_DIR; + ttf_size = 12 + 16 * num_tables; + + if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) ) + goto Fail; + } + /* fall through */ + + case BEFORE_TABLE_DIR: + /* the offset table is read; read the table directory */ + if ( count < ttf_size ) + { + face->ttf_data[count++] = string_buf[n]; + continue; + } + else + { + int i; + FT_ULong len; + + + for ( i = 0; i < num_tables; i++ ) + { + FT_Byte* p = face->ttf_data + 12 + 16 * i + 12; + + + len = FT_PEEK_ULONG( p ); + + /* Pad to a 4-byte boundary length */ + ttf_size += ( len + 3 ) & ~3; + } + + status = OTHER_TABLES; + face->ttf_size = ttf_size; + + if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables, + ttf_size + 1 ) ) + goto Fail; + } + /* fall through */ + + case OTHER_TABLES: + /* all other tables are just copied */ + if ( count >= ttf_size ) + { + FT_ERROR(( "t42_parse_sfnts: too many binary data!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + face->ttf_data[count++] = string_buf[n]; + } + } + + T1_Skip_Spaces( parser ); + } + + /* if control reaches this point, the format was not valid */ + error = T42_Err_Invalid_File_Format; + + Fail: + parser->root.error = error; + + Exit: + if ( alloc ) + FT_FREE( string_buf ); + } + + + static void + t42_parse_charstrings( T42_Face face, + T42_Loader loader ) + { + T42_Parser parser = &loader->parser; + PS_Table code_table = &loader->charstrings; + PS_Table name_table = &loader->glyph_names; + PS_Table swap_table = &loader->swap_table; + FT_Memory memory = parser->root.memory; + FT_Error error; + + PSAux_Service psaux = (PSAux_Service)face->psaux; + + FT_Byte* cur; + FT_Byte* limit = parser->root.limit; + FT_UInt n; + FT_UInt notdef_index = 0; + FT_Byte notdef_found = 0; + + + T1_Skip_Spaces( parser ); + + if ( parser->root.cursor >= limit ) + { + FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + + if ( ft_isdigit( *parser->root.cursor ) ) + { + loader->num_glyphs = (FT_UInt)T1_ToInt( parser ); + if ( parser->root.error ) + return; + } + else if ( *parser->root.cursor == '<' ) + { + /* We have `<< ... >>'. Count the number of `/' in the dictionary */ + /* to get its size. */ + FT_UInt count = 0; + + + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces( parser ); + cur = parser->root.cursor; + + while ( parser->root.cursor < limit ) + { + if ( *parser->root.cursor == '/' ) + count++; + else if ( *parser->root.cursor == '>' ) + { + loader->num_glyphs = count; + parser->root.cursor = cur; /* rewind */ + break; + } + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces( parser ); + } + } + else + { + FT_ERROR(( "t42_parse_charstrings: invalid token!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + + if ( parser->root.cursor >= limit ) + { + FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + + /* initialize tables */ + + error = psaux->ps_table_funcs->init( code_table, + loader->num_glyphs, + memory ); + if ( error ) + goto Fail; + + error = psaux->ps_table_funcs->init( name_table, + loader->num_glyphs, + memory ); + if ( error ) + goto Fail; + + /* Initialize table for swapping index notdef_index and */ + /* index 0 names and codes (if necessary). */ + + error = psaux->ps_table_funcs->init( swap_table, 4, memory ); + if ( error ) + goto Fail; + + n = 0; + + for (;;) + { + /* The format is simple: */ + /* `/glyphname' + index [+ def] */ + + T1_Skip_Spaces( parser ); + + cur = parser->root.cursor; + if ( cur >= limit ) + break; + + /* We stop when we find an `end' keyword or '>' */ + if ( *cur == 'e' && + cur + 3 < limit && + cur[1] == 'n' && + cur[2] == 'd' && + t42_is_space( cur[3] ) ) + break; + if ( *cur == '>' ) + break; + + T1_Skip_PS_Token( parser ); + + if ( *cur == '/' ) + { + FT_PtrDist len; + + + if ( cur + 1 >= limit ) + { + FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + + cur++; /* skip `/' */ + len = parser->root.cursor - cur; + + error = T1_Add_Table( name_table, n, cur, len + 1 ); + if ( error ) + goto Fail; + + /* add a trailing zero to the name table */ + name_table->elements[n][len] = '\0'; + + /* record index of /.notdef */ + if ( *cur == '.' && + ft_strcmp( ".notdef", + (const char*)(name_table->elements[n]) ) == 0 ) + { + notdef_index = n; + notdef_found = 1; + } + + T1_Skip_Spaces( parser ); + + cur = parser->root.cursor; + + (void)T1_ToInt( parser ); + if ( parser->root.cursor >= limit ) + { + FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + + len = parser->root.cursor - cur; + + error = T1_Add_Table( code_table, n, cur, len + 1 ); + if ( error ) + goto Fail; + + code_table->elements[n][len] = '\0'; + + n++; + if ( n >= loader->num_glyphs ) + break; + } + } + + loader->num_glyphs = n; + + if ( !notdef_found ) + { + FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph!\n" )); + error = T42_Err_Invalid_File_Format; + goto Fail; + } + + /* if /.notdef does not occupy index 0, do our magic. */ + if ( ft_strcmp( (const char*)".notdef", + (const char*)name_table->elements[0] ) ) + { + /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ + /* name and code entries to swap_table. Then place notdef_index */ + /* name and code entries into swap_table. Then swap name and code */ + /* entries at indices notdef_index and 0 using values stored in */ + /* swap_table. */ + + /* Index 0 name */ + error = T1_Add_Table( swap_table, 0, + name_table->elements[0], + name_table->lengths [0] ); + if ( error ) + goto Fail; + + /* Index 0 code */ + error = T1_Add_Table( swap_table, 1, + code_table->elements[0], + code_table->lengths [0] ); + if ( error ) + goto Fail; + + /* Index notdef_index name */ + error = T1_Add_Table( swap_table, 2, + name_table->elements[notdef_index], + name_table->lengths [notdef_index] ); + if ( error ) + goto Fail; + + /* Index notdef_index code */ + error = T1_Add_Table( swap_table, 3, + code_table->elements[notdef_index], + code_table->lengths [notdef_index] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( name_table, notdef_index, + swap_table->elements[0], + swap_table->lengths [0] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( code_table, notdef_index, + swap_table->elements[1], + swap_table->lengths [1] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( name_table, 0, + swap_table->elements[2], + swap_table->lengths [2] ); + if ( error ) + goto Fail; + + error = T1_Add_Table( code_table, 0, + swap_table->elements[3], + swap_table->lengths [3] ); + if ( error ) + goto Fail; + + } + + return; + + Fail: + parser->root.error = error; + } + + + static FT_Error + t42_load_keyword( T42_Face face, + T42_Loader loader, + T1_Field field ) + { + FT_Error error; + void* dummy_object; + void** objects; + FT_UInt max_objects = 0; + + + /* if the keyword has a dedicated callback, call it */ + if ( field->type == T1_FIELD_TYPE_CALLBACK ) + { + field->reader( (FT_Face)face, loader ); + error = loader->parser.root.error; + goto Exit; + } + + /* now the keyword is either a simple field or a table of fields; */ + /* we are now going to take care of it */ + + switch ( field->location ) + { + case T1_FIELD_LOCATION_FONT_INFO: + dummy_object = &face->type1.font_info; + break; + + case T1_FIELD_LOCATION_BBOX: + dummy_object = &face->type1.font_bbox; + break; + + default: + dummy_object = &face->type1; + } + + objects = &dummy_object; + + if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || + field->type == T1_FIELD_TYPE_FIXED_ARRAY ) + error = T1_Load_Field_Table( &loader->parser, field, + objects, max_objects, 0 ); + else + error = T1_Load_Field( &loader->parser, field, + objects, max_objects, 0 ); + + Exit: + return error; + } + + + FT_LOCAL_DEF( FT_Error ) + t42_parse_dict( T42_Face face, + T42_Loader loader, + FT_Byte* base, + FT_Long size ) + { + T42_Parser parser = &loader->parser; + FT_Byte* limit; + FT_Int n_keywords = (FT_Int)( sizeof ( t42_keywords ) / + sizeof ( t42_keywords[0] ) ); + + + parser->root.cursor = base; + parser->root.limit = base + size; + parser->root.error = T42_Err_Ok; + + limit = parser->root.limit; + + T1_Skip_Spaces( parser ); + + while ( parser->root.cursor < limit ) + { + FT_Byte* cur; + + + cur = parser->root.cursor; + + /* look for `FontDirectory' which causes problems for some fonts */ + if ( *cur == 'F' && cur + 25 < limit && + ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 ) + { + FT_Byte* cur2; + + + /* skip the `FontDirectory' keyword */ + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + cur = cur2 = parser->root.cursor; + + /* look up the `known' keyword */ + while ( cur < limit ) + { + if ( *cur == 'k' && cur + 5 < limit && + ft_strncmp( (char*)cur, "known", 5 ) == 0 ) + break; + + T1_Skip_PS_Token( parser ); + T1_Skip_Spaces ( parser ); + cur = parser->root.cursor; + } + + if ( cur < limit ) + { + T1_TokenRec token; + + + /* skip the `known' keyword and the token following it */ + T1_Skip_PS_Token( parser ); + T1_ToToken( parser, &token ); + + /* if the last token was an array, skip it! */ + if ( token.type == T1_TOKEN_TYPE_ARRAY ) + cur2 = parser->root.cursor; + } + parser->root.cursor = cur2; + } + + /* look for immediates */ + else if ( *cur == '/' && cur + 2 < limit ) + { + FT_PtrDist len; + + + cur++; + + parser->root.cursor = cur; + T1_Skip_PS_Token( parser ); + + len = parser->root.cursor - cur; + + if ( len > 0 && len < 22 && parser->root.cursor < limit ) + { + int i; + + + /* now compare the immediate name to the keyword table */ + + /* loop through all known keywords */ + for ( i = 0; i < n_keywords; i++ ) + { + T1_Field keyword = (T1_Field)&t42_keywords[i]; + FT_Byte *name = (FT_Byte*)keyword->ident; + + + if ( !name ) + continue; + + if ( cur[0] == name[0] && + len == ft_strlen( (const char *)name ) && + ft_memcmp( cur, name, len ) == 0 ) + { + /* we found it -- run the parsing callback! */ + parser->root.error = t42_load_keyword( face, + loader, + keyword ); + if ( parser->root.error ) + return parser->root.error; + break; + } + } + } + } + else + T1_Skip_PS_Token( parser ); + + T1_Skip_Spaces( parser ); + } + + return parser->root.error; + } + + + FT_LOCAL_DEF( void ) + t42_loader_init( T42_Loader loader, + T42_Face face ) + { + FT_UNUSED( face ); + + FT_MEM_ZERO( loader, sizeof ( *loader ) ); + loader->num_glyphs = 0; + loader->num_chars = 0; + + /* initialize the tables -- simply set their `init' field to 0 */ + loader->encoding_table.init = 0; + loader->charstrings.init = 0; + loader->glyph_names.init = 0; + } + + + FT_LOCAL_DEF( void ) + t42_loader_done( T42_Loader loader ) + { + T42_Parser parser = &loader->parser; + + + /* finalize tables */ + T1_Release_Table( &loader->encoding_table ); + T1_Release_Table( &loader->charstrings ); + T1_Release_Table( &loader->glyph_names ); + T1_Release_Table( &loader->swap_table ); + + /* finalize parser */ + t42_parser_done( parser ); + } + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42parse.h b/Utilities/vtkfreetype/src/type42/t42parse.h new file mode 100644 index 0000000..f77ec4a --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42parse.h @@ -0,0 +1,90 @@ +/***************************************************************************/ +/* */ +/* t42parse.h */ +/* */ +/* Type 42 font parser (specification). */ +/* */ +/* Copyright 2002, 2003 by Roberto Alameda. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T42PARSE_H__ +#define __T42PARSE_H__ + + +#include "t42objs.h" +#include FT_INTERNAL_POSTSCRIPT_AUX_H + + +FT_BEGIN_HEADER + + typedef struct T42_ParserRec_ + { + PS_ParserRec root; + FT_Stream stream; + + FT_Byte* base_dict; + FT_Long base_len; + + FT_Bool in_memory; + + } T42_ParserRec, *T42_Parser; + + + typedef struct T42_Loader_ + { + T42_ParserRec parser; /* parser used to read the stream */ + + FT_UInt num_chars; /* number of characters in encoding */ + PS_TableRec encoding_table; /* PS_Table used to store the */ + /* encoding character names */ + + FT_UInt num_glyphs; + PS_TableRec glyph_names; + PS_TableRec charstrings; + PS_TableRec swap_table; /* For moving .notdef glyph to index 0. */ + + } T42_LoaderRec, *T42_Loader; + + + FT_LOCAL( FT_Error ) + t42_parser_init( T42_Parser parser, + FT_Stream stream, + FT_Memory memory, + PSAux_Service psaux ); + + FT_LOCAL( void ) + t42_parser_done( T42_Parser parser ); + + + FT_LOCAL( FT_Error ) + t42_parse_dict( T42_Face face, + T42_Loader loader, + FT_Byte* base, + FT_Long size ); + + + FT_LOCAL( void ) + t42_loader_init( T42_Loader loader, + T42_Face face ); + + FT_LOCAL( void ) + t42_loader_done( T42_Loader loader ); + + + /* */ + +FT_END_HEADER + + +#endif /* __T42PARSE_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/t42types.h b/Utilities/vtkfreetype/src/type42/t42types.h new file mode 100644 index 0000000..d44ac4e --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/t42types.h @@ -0,0 +1,54 @@ +/***************************************************************************/ +/* */ +/* t42types.h */ +/* */ +/* Type 42 font data types (specification only). */ +/* */ +/* Copyright 2002, 2003 by Roberto Alameda. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __T42TYPES_H__ +#define __T42TYPES_H__ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_TYPE1_TABLES_H +#include FT_INTERNAL_TYPE1_TYPES_H +#include FT_INTERNAL_POSTSCRIPT_HINTS_H + + +FT_BEGIN_HEADER + + + typedef struct T42_FaceRec_ + { + FT_FaceRec root; + T1_FontRec type1; + const void* psnames; + const void* psaux; + const void* afm_data; + FT_Byte* ttf_data; + FT_ULong ttf_size; + FT_Face ttf_face; + FT_CharMapRec charmaprecs[2]; + FT_CharMap charmaps[2]; + PS_Unicodes unicode_map; + + } T42_FaceRec, *T42_Face; + + +FT_END_HEADER + +#endif /* __T1TYPES_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/type42/type42.c b/Utilities/vtkfreetype/src/type42/type42.c new file mode 100644 index 0000000..d13df56 --- /dev/null +++ b/Utilities/vtkfreetype/src/type42/type42.c @@ -0,0 +1,25 @@ +/***************************************************************************/ +/* */ +/* type42.c */ +/* */ +/* FreeType Type 42 driver component. */ +/* */ +/* Copyright 2002 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include <ft2build.h> +#include "t42objs.c" +#include "t42parse.c" +#include "t42drivr.c" + +/* END */ diff --git a/Utilities/vtkfreetype/src/winfonts/fnterrs.h b/Utilities/vtkfreetype/src/winfonts/fnterrs.h new file mode 100644 index 0000000..ea80909 --- /dev/null +++ b/Utilities/vtkfreetype/src/winfonts/fnterrs.h @@ -0,0 +1,41 @@ +/***************************************************************************/ +/* */ +/* fnterrs.h */ +/* */ +/* Win FNT/FON error codes (specification only). */ +/* */ +/* Copyright 2001 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the Windows FNT/FON error enumeration */ + /* constants. */ + /* */ + /*************************************************************************/ + +#ifndef __FNTERRS_H__ +#define __FNTERRS_H__ + +#include FT_MODULE_ERRORS_H + +#undef __FTERRORS_H__ + +#define FT_ERR_PREFIX FNT_Err_ +#define FT_ERR_BASE FT_Mod_Err_Winfonts + +#include FT_ERRORS_H + +#endif /* __FNTERRS_H__ */ + + +/* END */ diff --git a/Utilities/vtkfreetype/src/winfonts/winfnt.c b/Utilities/vtkfreetype/src/winfonts/winfnt.c new file mode 100644 index 0000000..92174ae --- /dev/null +++ b/Utilities/vtkfreetype/src/winfonts/winfnt.c @@ -0,0 +1,754 @@ +/***************************************************************************/ +/* */ +/* winfnt.c */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_WINFONTS_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H +#include FT_INTERNAL_OBJECTS_H + +#include "winfnt.h" +#include "fnterrs.h" +#include FT_SERVICE_WINFNT_H +#include FT_SERVICE_XFREE86_NAME_H + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_winfnt + + + static const FT_Frame_Field winmz_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinMZ_HeaderRec + + FT_FRAME_START( 64 ), + FT_FRAME_USHORT_LE ( magic ), + FT_FRAME_SKIP_BYTES( 29 * 2 ), + FT_FRAME_ULONG_LE ( lfanew ), + FT_FRAME_END + }; + + static const FT_Frame_Field winne_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WinNE_HeaderRec + + FT_FRAME_START( 40 ), + FT_FRAME_USHORT_LE ( magic ), + FT_FRAME_SKIP_BYTES( 34 ), + FT_FRAME_USHORT_LE ( resource_tab_offset ), + FT_FRAME_USHORT_LE ( rname_tab_offset ), + FT_FRAME_END + }; + + static const FT_Frame_Field winfnt_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE FT_WinFNT_HeaderRec + + FT_FRAME_START( 148 ), + FT_FRAME_USHORT_LE( version ), + FT_FRAME_ULONG_LE ( file_size ), + FT_FRAME_BYTES ( copyright, 60 ), + FT_FRAME_USHORT_LE( file_type ), + FT_FRAME_USHORT_LE( nominal_point_size ), + FT_FRAME_USHORT_LE( vertical_resolution ), + FT_FRAME_USHORT_LE( horizontal_resolution ), + FT_FRAME_USHORT_LE( ascent ), + FT_FRAME_USHORT_LE( internal_leading ), + FT_FRAME_USHORT_LE( external_leading ), + FT_FRAME_BYTE ( italic ), + FT_FRAME_BYTE ( underline ), + FT_FRAME_BYTE ( strike_out ), + FT_FRAME_USHORT_LE( weight ), + FT_FRAME_BYTE ( charset ), + FT_FRAME_USHORT_LE( pixel_width ), + FT_FRAME_USHORT_LE( pixel_height ), + FT_FRAME_BYTE ( pitch_and_family ), + FT_FRAME_USHORT_LE( avg_width ), + FT_FRAME_USHORT_LE( max_width ), + FT_FRAME_BYTE ( first_char ), + FT_FRAME_BYTE ( last_char ), + FT_FRAME_BYTE ( default_char ), + FT_FRAME_BYTE ( break_char ), + FT_FRAME_USHORT_LE( bytes_per_row ), + FT_FRAME_ULONG_LE ( device_offset ), + FT_FRAME_ULONG_LE ( face_name_offset ), + FT_FRAME_ULONG_LE ( bits_pointer ), + FT_FRAME_ULONG_LE ( bits_offset ), + FT_FRAME_BYTE ( reserved ), + FT_FRAME_ULONG_LE ( flags ), + FT_FRAME_USHORT_LE( A_space ), + FT_FRAME_USHORT_LE( B_space ), + FT_FRAME_USHORT_LE( C_space ), + FT_FRAME_ULONG_LE ( color_table_offset ), + FT_FRAME_BYTES ( reserved1, 16 ), + FT_FRAME_END + }; + + + static void + fnt_font_done( FNT_Face face ) + { + FT_Memory memory = FT_FACE( face )->memory; + FT_Stream stream = FT_FACE( face )->stream; + FNT_Font font = face->font; + + + if ( !font ) + return; + + if ( font->fnt_frame ) + FT_FRAME_RELEASE( font->fnt_frame ); + FT_FREE( font->family_name ); + + FT_FREE( font ); + face->font = 0; + } + + + static FT_Error + fnt_font_load( FNT_Font font, + FT_Stream stream ) + { + FT_Error error; + FT_WinFNT_Header header = &font->header; + FT_Bool new_format; + FT_UInt size; + + + /* first of all, read the FNT header */ + if ( FT_STREAM_SEEK( font->offset ) || + FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) ) + goto Exit; + + /* check header */ + if ( header->version != 0x200 && + header->version != 0x300 ) + { + FT_TRACE2(( "[not a valid FNT file]\n" )); + error = FNT_Err_Unknown_File_Format; + goto Exit; + } + + new_format = FT_BOOL( font->header.version == 0x300 ); + size = new_format ? 148 : 118; + + if ( header->file_size < size ) + { + FT_TRACE2(( "[not a valid FNT file]\n" )); + error = FNT_Err_Unknown_File_Format; + goto Exit; + } + + /* Version 2 doesn't have these fields */ + if ( header->version == 0x200 ) + { + header->flags = 0; + header->A_space = 0; + header->B_space = 0; + header->C_space = 0; + + header->color_table_offset = 0; + } + + if ( header->file_type & 1 ) + { + FT_TRACE2(( "[can't handle vector FNT fonts]\n" )); + error = FNT_Err_Unknown_File_Format; + goto Exit; + } + + /* this is a FNT file/table; extract its frame */ + if ( FT_STREAM_SEEK( font->offset ) || + FT_FRAME_EXTRACT( header->file_size, font->fnt_frame ) ) + goto Exit; + + Exit: + return error; + } + + + static FT_Error + fnt_face_get_dll_font( FNT_Face face, + FT_Int face_index ) + { + FT_Error error; + FT_Stream stream = FT_FACE( face )->stream; + FT_Memory memory = FT_FACE( face )->memory; + WinMZ_HeaderRec mz_header; + + + face->font = 0; + + /* does it begin with an MZ header? */ + if ( FT_STREAM_SEEK( 0 ) || + FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) ) + goto Exit; + + error = FNT_Err_Unknown_File_Format; + if ( mz_header.magic == WINFNT_MZ_MAGIC ) + { + /* yes, now look for an NE header in the file */ + WinNE_HeaderRec ne_header; + + + if ( FT_STREAM_SEEK( mz_header.lfanew ) || + FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) ) + goto Exit; + + error = FNT_Err_Unknown_File_Format; + if ( ne_header.magic == WINFNT_NE_MAGIC ) + { + /* good, now look into the resource table for each FNT resource */ + FT_ULong res_offset = mz_header.lfanew + + ne_header.resource_tab_offset; + FT_UShort size_shift; + FT_UShort font_count = 0; + FT_ULong font_offset = 0; + + + if ( FT_STREAM_SEEK( res_offset ) || + FT_FRAME_ENTER( ne_header.rname_tab_offset - + ne_header.resource_tab_offset ) ) + goto Exit; + + size_shift = FT_GET_USHORT_LE(); + + for (;;) + { + FT_UShort type_id, count; + + + type_id = FT_GET_USHORT_LE(); + if ( !type_id ) + break; + + count = FT_GET_USHORT_LE(); + + if ( type_id == 0x8008U ) + { + font_count = count; + font_offset = (FT_ULong)( FT_STREAM_POS() + 4 + + ( stream->cursor - stream->limit ) ); + break; + } + + stream->cursor += 4 + count * 12; + } + + FT_FRAME_EXIT(); + + if ( !font_count || !font_offset ) + { + FT_TRACE2(( "this file doesn't contain any FNT resources!\n" )); + error = FNT_Err_Unknown_File_Format; + goto Exit; + } + + face->root.num_faces = font_count; + + if ( face_index >= font_count ) + { + error = FNT_Err_Bad_Argument; + goto Exit; + } + + if ( FT_NEW( face->font ) ) + goto Exit; + + if ( FT_STREAM_SEEK( font_offset + face_index * 12 ) || + FT_FRAME_ENTER( 12 ) ) + goto Fail; + + face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift; + face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift; + face->font->size_shift = size_shift; + + stream->cursor += 8; + + FT_FRAME_EXIT(); + + error = fnt_font_load( face->font, stream ); + } + } + + Fail: + if ( error ) + fnt_font_done( face ); + + Exit: + return error; + } + + + typedef struct FNT_CMapRec_ + { + FT_CMapRec cmap; + FT_UInt32 first; + FT_UInt32 count; + + } FNT_CMapRec, *FNT_CMap; + + + static FT_Error + fnt_cmap_init( FNT_CMap cmap ) + { + FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); + FNT_Font font = face->font; + + + cmap->first = (FT_UInt32) font->header.first_char; + cmap->count = (FT_UInt32)( font->header.last_char - cmap->first + 1 ); + + return 0; + } + + + static FT_UInt + fnt_cmap_char_index( FNT_CMap cmap, + FT_UInt32 char_code ) + { + FT_UInt gindex = 0; + + + char_code -= cmap->first; + if ( char_code < cmap->count ) + gindex = char_code + 1; /* we artificially increase the glyph index; */ + /* FNT_Load_Glyph reverts to the right one */ + return gindex; + } + + + static FT_UInt + fnt_cmap_char_next( FNT_CMap cmap, + FT_UInt32 *pchar_code ) + { + FT_UInt gindex = 0; + FT_UInt32 result = 0; + FT_UInt32 char_code = *pchar_code + 1; + + + if ( char_code <= cmap->first ) + { + result = cmap->first; + gindex = 1; + } + else + { + char_code -= cmap->first; + if ( char_code < cmap->count ) + { + result = cmap->first + char_code; + gindex = char_code + 1; + } + } + + *pchar_code = result; + return gindex; + } + + + static const FT_CMap_ClassRec fnt_cmap_class_rec = + { + sizeof ( FNT_CMapRec ), + + (FT_CMap_InitFunc) fnt_cmap_init, + (FT_CMap_DoneFunc) NULL, + (FT_CMap_CharIndexFunc)fnt_cmap_char_index, + (FT_CMap_CharNextFunc) fnt_cmap_char_next + }; + + static FT_CMap_Class const fnt_cmap_class = &fnt_cmap_class_rec; + + + static void + FNT_Face_Done( FNT_Face face ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + + + fnt_font_done( face ); + + FT_FREE( face->root.available_sizes ); + face->root.num_fixed_sizes = 0; + } + + + static FT_Error + FNT_Face_Init( FT_Stream stream, + FNT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Memory memory = FT_FACE_MEMORY( face ); + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + /* try to load font from a DLL */ + error = fnt_face_get_dll_font( face, face_index ); + if ( error ) + { + /* this didn't work; try to load a single FNT font */ + FNT_Font font; + + + if ( FT_NEW( face->font ) ) + goto Exit; + + face->root.num_faces = 1; + + font = face->font; + font->offset = 0; + font->fnt_size = stream->size; + + error = fnt_font_load( font, stream ); + if ( error ) + goto Fail; + } + + /* we now need to fill the root FT_Face fields */ + /* with relevant information */ + { + FT_Face root = FT_FACE( face ); + FNT_Font font = face->font; + FT_PtrDist family_size; + + + root->face_flags = FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL; + + if ( font->header.avg_width == font->header.max_width ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + if ( font->header.italic ) + root->style_flags |= FT_STYLE_FLAG_ITALIC; + + if ( font->header.weight >= 800 ) + root->style_flags |= FT_STYLE_FLAG_BOLD; + + /* set up the `fixed_sizes' array */ + if ( FT_NEW_ARRAY( root->available_sizes, 1 ) ) + goto Fail; + + root->num_fixed_sizes = 1; + + { + FT_Bitmap_Size* bsize = root->available_sizes; + + + bsize->width = font->header.avg_width; + bsize->height = (FT_Short)( + font->header.pixel_height + font->header.external_leading ); + bsize->size = font->header.nominal_point_size << 6; + bsize->x_ppem = font->header.pixel_width << 6; + bsize->y_ppem = font->header.pixel_height << 6; + } + + { + FT_CharMapRec charmap; + + + charmap.encoding = FT_ENCODING_NONE; + charmap.platform_id = 0; + charmap.encoding_id = 0; + charmap.face = root; + + if ( font->header.charset == FT_WinFNT_ID_MAC ) + { + charmap.encoding = FT_ENCODING_APPLE_ROMAN; + charmap.platform_id = 1; +/* charmap.encoding_id = 0; */ + } + + error = FT_CMap_New( fnt_cmap_class, + NULL, + &charmap, + NULL ); + if ( error ) + goto Fail; + + /* Select default charmap */ + if ( root->num_charmaps ) + root->charmap = root->charmaps[0]; + } + + /* setup remaining flags */ + + /* reserve one slot for the .notdef glyph at index 0 */ + root->num_glyphs = font->header.last_char - + font->header.first_char + 1 + 1; + + /* Some broken fonts don't delimit the face name with a final */ + /* NULL byte -- the frame is erroneously one byte too small. */ + /* We thus allocate one more byte, setting it explicitly to */ + /* zero. */ + family_size = font->header.file_size - font->header.face_name_offset; + if ( FT_ALLOC( font->family_name, family_size + 1 ) ) + goto Fail; + FT_MEM_COPY( font->family_name, + font->fnt_frame + font->header.face_name_offset, + family_size ); + font->family_name[family_size] = '\0'; + if ( FT_REALLOC( font->family_name, + family_size, + ft_strlen( font->family_name ) + 1 ) ) + goto Fail; + root->family_name = font->family_name; + root->style_name = (char *)"Regular"; + + if ( root->style_flags & FT_STYLE_FLAG_BOLD ) + { + if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = (char *)"Bold Italic"; + else + root->style_name = (char *)"Bold"; + } + else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = (char *)"Italic"; + } + goto Exit; + + Fail: + FNT_Face_Done( face ); + + Exit: + return error; + } + + + static FT_Error + FNT_Size_Set_Pixels( FT_Size size ) + { + FNT_Face face = (FNT_Face)FT_SIZE_FACE( size ); + FT_Face root = FT_FACE( face ); + + + if ( size->metrics.y_ppem == root->available_sizes->y_ppem >> 6 ) + { + FNT_Font font = face->font; + + + size->metrics.ascender = font->header.ascent * 64; + size->metrics.descender = -( font->header.pixel_height - + font->header.ascent ) * 64; + size->metrics.height = font->header.pixel_height * 64; + size->metrics.max_advance = font->header.max_width * 64; + + return FNT_Err_Ok; + } + else + return FNT_Err_Invalid_Pixel_Size; + } + + + static FT_Error + FNT_Load_Glyph( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int32 load_flags ) + { + FNT_Face face = (FNT_Face)FT_SIZE_FACE( size ); + FNT_Font font = face->font; + FT_Error error = FNT_Err_Ok; + FT_Byte* p; + FT_Int len; + FT_Bitmap* bitmap = &slot->bitmap; + FT_ULong offset; + FT_Bool new_format; + + FT_UNUSED( load_flags ); + + + if ( !face || !font ) + { + error = FNT_Err_Invalid_Argument; + goto Exit; + } + + if ( glyph_index > 0 ) + glyph_index--; /* revert to real index */ + else + glyph_index = font->header.default_char; /* the .notdef glyph */ + + new_format = FT_BOOL( font->header.version == 0x300 ); + len = new_format ? 6 : 4; + + /* jump to glyph entry */ + p = font->fnt_frame + ( new_format ? 148 : 118 ) + len * glyph_index; + + bitmap->width = FT_NEXT_SHORT_LE( p ); + + if ( new_format ) + offset = FT_NEXT_ULONG_LE( p ); + else + offset = FT_NEXT_USHORT_LE( p ); + + if ( offset >= font->header.file_size ) + { + FT_TRACE2(( "invalid FNT offset!\n" )); + error = FNT_Err_Invalid_File_Format; + goto Exit; + } + + /* jump to glyph data */ + p = font->fnt_frame + /* font->header.bits_offset */ + offset; + + /* allocate and build bitmap */ + { + FT_Memory memory = FT_FACE_MEMORY( slot->face ); + FT_Int pitch = ( bitmap->width + 7 ) >> 3; + FT_Byte* column; + FT_Byte* write; + + + bitmap->pitch = pitch; + bitmap->rows = font->header.pixel_height; + bitmap->pixel_mode = FT_PIXEL_MODE_MONO; + + /* note: since glyphs are stored in columns and not in rows we */ + /* can't use ft_glyphslot_set_bitmap */ + if ( FT_ALLOC( bitmap->buffer, pitch * bitmap->rows ) ) + goto Exit; + + column = (FT_Byte*)bitmap->buffer; + + for ( ; pitch > 0; pitch--, column++ ) + { + FT_Byte* limit = p + bitmap->rows; + + + for ( write = column; p < limit; p++, write += bitmap->pitch ) + *write = *p; + } + } + + slot->internal->flags = FT_GLYPH_OWN_BITMAP; + slot->bitmap_left = 0; + slot->bitmap_top = font->header.ascent; + slot->format = FT_GLYPH_FORMAT_BITMAP; + + /* now set up metrics */ + slot->metrics.width = bitmap->width << 6; + slot->metrics.height = bitmap->rows << 6; + slot->metrics.horiAdvance = bitmap->width << 6; + slot->metrics.horiBearingX = 0; + slot->metrics.horiBearingY = slot->bitmap_top << 6; + + slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16; + slot->format = FT_GLYPH_FORMAT_BITMAP; + + Exit: + return error; + } + + + static FT_Error + winfnt_get_header( FT_Face face, + FT_WinFNT_HeaderRec *aheader ) + { + FNT_Font font = ((FNT_Face)face)->font; + + + *aheader = font->header; + + return 0; + } + + + static const FT_Service_WinFntRec winfnt_service_rec = + { + winfnt_get_header + }; + + /* + * SERVICE LIST + * + */ + + static const FT_ServiceDescRec winfnt_services[] = + { + { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_WINFNT }, + { FT_SERVICE_ID_WINFNT, &winfnt_service_rec }, + { NULL, NULL } + }; + + + static FT_Module_Interface + winfnt_get_service( FT_Driver driver, + const FT_String* service_id ) + { + FT_UNUSED( driver ); + + return ft_service_list_lookup( winfnt_services, service_id ); + } + + + + + FT_CALLBACK_TABLE_DEF + const FT_Driver_ClassRec winfnt_driver_class = + { + { + FT_MODULE_FONT_DRIVER | + FT_MODULE_DRIVER_NO_OUTLINES, + sizeof ( FT_DriverRec ), + + "winfonts", + 0x10000L, + 0x20000L, + + 0, + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) winfnt_get_service + }, + + sizeof( FNT_FaceRec ), + sizeof( FT_SizeRec ), + sizeof( FT_GlyphSlotRec ), + + (FT_Face_InitFunc) FNT_Face_Init, + (FT_Face_DoneFunc) FNT_Face_Done, + (FT_Size_InitFunc) 0, + (FT_Size_DoneFunc) 0, + (FT_Slot_InitFunc) 0, + (FT_Slot_DoneFunc) 0, + + (FT_Size_ResetPointsFunc) FNT_Size_Set_Pixels, + (FT_Size_ResetPixelsFunc) FNT_Size_Set_Pixels, + (FT_Slot_LoadFunc) FNT_Load_Glyph, + + (FT_Face_GetKerningFunc) 0, + (FT_Face_AttachFunc) 0, + (FT_Face_GetAdvancesFunc) 0 + }; + + +/* END */ diff --git a/Utilities/vtkfreetype/src/winfonts/winfnt.h b/Utilities/vtkfreetype/src/winfonts/winfnt.h new file mode 100644 index 0000000..32ab6da --- /dev/null +++ b/Utilities/vtkfreetype/src/winfonts/winfnt.h @@ -0,0 +1,107 @@ +/***************************************************************************/ +/* */ +/* winfnt.h */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2001, 2002, 2003, 2004 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __WINFNT_H__ +#define __WINFNT_H__ + + +#include <ft2build.h> +#include FT_WINFONTS_H +#include FT_INTERNAL_DRIVER_H + + +FT_BEGIN_HEADER + + typedef struct WinMZ_HeaderRec_ + { + FT_UShort magic; + /* skipped content */ + FT_UShort lfanew; + + } WinMZ_HeaderRec; + + + typedef struct WinNE_HeaderRec_ + { + FT_UShort magic; + /* skipped content */ + FT_UShort resource_tab_offset; + FT_UShort rname_tab_offset; + + } WinNE_HeaderRec; + + + typedef struct WinNameInfoRec_ + { + FT_UShort offset; + FT_UShort length; + FT_UShort flags; + FT_UShort id; + FT_UShort handle; + FT_UShort usage; + + } WinNameInfoRec; + + + typedef struct WinResourceInfoRec_ + { + FT_UShort type_id; + FT_UShort count; + + } WinResourceInfoRec; + + +#define WINFNT_MZ_MAGIC 0x5A4D +#define WINFNT_NE_MAGIC 0x454E + + + typedef struct FNT_FontRec_ + { + FT_ULong offset; + FT_Int size_shift; + + FT_WinFNT_HeaderRec header; + + FT_Byte* fnt_frame; + FT_ULong fnt_size; + FT_String* family_name; + + } FNT_FontRec, *FNT_Font; + + + typedef struct FNT_FaceRec_ + { + FT_FaceRec root; + FNT_Font font; + + FT_CharMap charmap_handle; + FT_CharMapRec charmap; /* a single charmap per face */ + + } FNT_FaceRec, *FNT_Face; + + + FT_EXPORT_VAR( const FT_Driver_ClassRec ) winfnt_driver_class; + + +FT_END_HEADER + + +#endif /* __WINFNT_H__ */ + + +/* END */ diff --git a/Utilities/vtkjpeg/.NoDartCoverage b/Utilities/vtkjpeg/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/vtkjpeg/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/vtkjpeg/CMakeLists.txt b/Utilities/vtkjpeg/CMakeLists.txt new file mode 100644 index 0000000..aecd4c9 --- /dev/null +++ b/Utilities/vtkjpeg/CMakeLists.txt @@ -0,0 +1,61 @@ +PROJECT(VTKJPEG) + +INCLUDE_REGULAR_EXPRESSION("^(jchuff|jconfig|jdct|jdhuff|jerror|jinclude|jmemsys|jmorecfg|jpegint|jpeglib|jversion|jpeg|vtk).*$") + +INCLUDE_DIRECTORIES(${VTKJPEG_SOURCE_DIR}) + +# memmgr back ends: compile only one of these into a working library +# (For now, let's use the mode that requires the image fit into memory. +# This is the recommended mode for Win32 anyway.) +SET(systemdependent_SRCS jmemnobs.c) + +# library object files common to compression and decompression +SET(common_SRCS +jcomapi.c jutils.c jerror.c jmemmgr.c +) + +# compression library object files +SET(compression_SRCS +jcapimin.c jcapistd.c jctrans.c jcparam.c jdatadst.c jcinit.c +jcmaster.c jcmarker.c jcmainct.c jcprepct.c jccoefct.c jccolor.c +jcsample.c jchuff.c jcphuff.c jcdctmgr.c jfdctfst.c jfdctflt.c +jfdctint.c +) + +# decompression library object files +SET(decompression_SRCS +jdapimin.c jdapistd.c jdtrans.c jdatasrc.c jdmaster.c +jdinput.c jdmarker.c jdhuff.c jdphuff.c jdmainct.c jdcoefct.c +jdpostct.c jddctmgr.c jidctfst.c jidctflt.c jidctint.c jidctred.c +jdsample.c jdcolor.c jquant1.c jquant2.c jdmerge.c +) + + +IF (WIN32) + IF (BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DJPEGDLL) + ELSE (BUILD_SHARED_LIBS) + SET(JPEGSTATIC 1) + ENDIF (BUILD_SHARED_LIBS) +ENDIF (WIN32) + + +CONFIGURE_FILE(${VTKJPEG_SOURCE_DIR}/.NoDartCoverage + ${VTKJPEG_BINARY_DIR}/.NoDartCoverage) +CONFIGURE_FILE(${VTKJPEG_SOURCE_DIR}/jpegDllConfig.h.in + ${VTKJPEG_BINARY_DIR}/jpegDllConfig.h) + +ADD_LIBRARY(vtkjpeg ${systemdependent_SRCS} ${common_SRCS} ${compression_SRCS} ${decompression_SRCS}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkjpeg PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkjpeg) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtkjpeg .h + jpegDllConfig jpeglib vtk_jpeg_mangle jconfig jmorecfg jerror) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/vtkjpeg/README b/Utilities/vtkjpeg/README new file mode 100644 index 0000000..86cc206 --- /dev/null +++ b/Utilities/vtkjpeg/README @@ -0,0 +1,385 @@ +The Independent JPEG Group's JPEG software +========================================== + +README for release 6b of 27-Mar-1998 +==================================== + +This distribution contains the sixth public release of the Independent JPEG +Group's free JPEG software. You are welcome to redistribute this software and +to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. + +Serious users of this software (particularly those incorporating it into +larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to +our electronic mailing list. Mailing list members are notified of updates +and have a chance to participate in technical discussions, etc. + +This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, +Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, +Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG +Group. + +IJG is not affiliated with the official ISO JPEG standards committee. + + +DOCUMENTATION ROADMAP +===================== + +This file contains the following sections: + +OVERVIEW General description of JPEG and the IJG software. +LEGAL ISSUES Copyright, lack of warranty, terms of distribution. +REFERENCES Where to learn more about JPEG. +ARCHIVE LOCATIONS Where to find newer versions of this software. +RELATED SOFTWARE Other stuff you should get. +FILE FORMAT WARS Software *not* to get. +TO DO Plans for future IJG releases. + +Other documentation files in the distribution are: + +User documentation: + install.doc How to configure and install the IJG software. + usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + rdjpgcom, and wrjpgcom. + *.1 Unix-style man pages for programs (same info as usage.doc). + wizard.doc Advanced usage instructions for JPEG wizards only. + change.log Version-to-version change highlights. +Programmer and internal documentation: + libjpeg.doc How to use the JPEG library in your own programs. + example.c Sample code for calling the JPEG library. + structure.doc Overview of the JPEG library's internal structure. + filelist.doc Road map of IJG files. + coderules.doc Coding style rules --- please read if you contribute code. + +Please read at least the files install.doc and usage.doc. Useful information +can also be found in the JPEG FAQ (Frequently Asked Questions) article. See +ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. + +If you want to understand how the JPEG code works, we suggest reading one or +more of the REFERENCES, then looking at the documentation files (in roughly +the order listed) before diving into the code. + + +OVERVIEW +======== + +This package contains C software to implement JPEG image compression and +decompression. JPEG (pronounced "jay-peg") is a standardized compression +method for full-color and gray-scale images. JPEG is intended for compressing +"real-world" scenes; line drawings, cartoons and other non-realistic images +are not its strong suit. JPEG is lossy, meaning that the output image is not +exactly identical to the input image. Hence you must not use JPEG if you +have to have identical output bits. However, on typical photographic images, +very good compression levels can be obtained with no visible change, and +remarkably high compression levels are possible if you can tolerate a +low-quality image. For more details, see the references, or just experiment +with various compression settings. + +This software implements JPEG baseline, extended-sequential, and progressive +compression processes. Provision is made for supporting all variants of these +processes, although some uncommon parameter settings aren't implemented yet. +For legal reasons, we are not distributing code for the arithmetic-coding +variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting +the hierarchical or lossless processes defined in the standard. + +We provide a set of library routines for reading and writing JPEG image files, +plus two sample applications "cjpeg" and "djpeg", which use the library to +perform conversion between JPEG and some other popular image file formats. +The library is intended to be reused in other applications. + +In order to support file conversion and viewing software, we have included +considerable functionality beyond the bare JPEG coding/decoding capability; +for example, the color quantization modules are not strictly part of JPEG +decoding, but they are essential for output to colormapped file formats or +colormapped displays. These extra functions can be compiled out of the +library if not required for a particular application. We have also included +"jpegtran", a utility for lossless transcoding between different JPEG +processes, and "rdjpgcom" and "wrjpgcom", two simple applications for +inserting and extracting textual comments in JFIF files. + +The emphasis in designing this software has been on achieving portability and +flexibility, while also making it fast enough to be useful. In particular, +the software is not intended to be read as a tutorial on JPEG. (See the +REFERENCES section for introductory material.) Rather, it is intended to +be reliable, portable, industrial-strength code. We do not claim to have +achieved that goal in every aspect of the software, but we strive for it. + +We welcome the use of this software as a component of commercial products. +No royalty is required, but we do ask for an acknowledgement in product +documentation, as described under LEGAL ISSUES. + + +LEGAL ISSUES +============ + +In plain English: + +1. We don't promise that this software works. (But if you find any bugs, + please let us know!) +2. You can use this software for whatever you want. You don't have to pay us. +3. You may not pretend that you wrote this software. If you use it in a + program, you must acknowledge somewhere in your documentation that + you've used the IJG code. + +In legalese: + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, +sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. +ansi2knr.c is NOT covered by the above copyright and conditions, but instead +by the usual distribution terms of the Free Software Foundation; principally, +that you must include source code if you redistribute it. (See the file +ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part +of any program generated from the IJG code, this does not limit you more than +the foregoing paragraphs do. + +The Unix configuration script "configure" was produced with GNU Autoconf. +It is copyright by the Free Software Foundation but is freely distributable. +The same holds for its supporting scripts (config.guess, config.sub, +ltconfig, ltmain.sh). Another support script, install-sh, is copyright +by M.I.T. but is also freely distributable. + +It appears that the arithmetic coding option of the JPEG spec is covered by +patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot +legally be used without obtaining one or more licenses. For this reason, +support for arithmetic coding has been removed from the free JPEG software. +(Since arithmetic coding provides only a marginal gain over the unpatented +Huffman mode, it is unlikely that very many implementations will support it.) +So far as we are aware, there are no patent restrictions on the remaining +code. + +The IJG distribution formerly included code to read and write GIF files. +To avoid entanglement with the Unisys LZW patent, GIF reading support has +been removed altogether, and the GIF writer has been simplified to produce +"uncompressed GIFs". This technique does not use the LZW algorithm; the +resulting GIF files are larger than usual, but are readable by all standard +GIF decoders. + +We are required to state that + "The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. GIF(sm) is a Service Mark property of + CompuServe Incorporated." + + +REFERENCES +========== + +We highly recommend reading one or more of these references before trying to +understand the innards of the JPEG software. + +The best short technical introduction to the JPEG compression algorithm is + Wallace, Gregory K. "The JPEG Still Picture Compression Standard", + Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. +(Adjacent articles in that issue discuss MPEG motion picture compression, +applications of JPEG, and related topics.) If you don't have the CACM issue +handy, a PostScript file containing a revised version of Wallace's article is +available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually +a preprint for an article that appeared in IEEE Trans. Consumer Electronics) +omits the sample images that appeared in CACM, but it includes corrections +and some added material. Note: the Wallace article is copyright ACM and IEEE, +and it may not be used for commercial purposes. + +A somewhat less technical, more leisurely introduction to JPEG can be found in +"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by +M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides +good explanations and example C code for a multitude of compression methods +including JPEG. It is an excellent source if you are comfortable reading C +code but don't know much about data compression in general. The book's JPEG +sample code is far from industrial-strength, but when you are ready to look +at a full implementation, you've got one here... + +The best full description of JPEG is the textbook "JPEG Still Image Data +Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published +by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. +The book includes the complete text of the ISO JPEG standards (DIS 10918-1 +and draft DIS 10918-2). This is by far the most complete exposition of JPEG +in existence, and we highly recommend it. + +The JPEG standard itself is not available electronically; you must order a +paper copy through ISO or ITU. (Unless you feel a need to own a certified +official copy, we recommend buying the Pennebaker and Mitchell book instead; +it's much cheaper and includes a great deal of useful explanatory material.) +In the USA, copies of the standard may be ordered from ANSI Sales at (212) +642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI +doesn't take credit card orders, but Global does.) It's not cheap: as of +1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% +shipping/handling. The standard is divided into two parts, Part 1 being the +actual specification, while Part 2 covers compliance testing methods. Part 1 +is titled "Digital Compression and Coding of Continuous-tone Still Images, +Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS +10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of +Continuous-tone Still Images, Part 2: Compliance testing" and has document +numbers ISO/IEC IS 10918-2, ITU-T T.83. + +Some extensions to the original JPEG standard are defined in JPEG Part 3, +a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG +currently does not support any Part 3 extensions. + +The JPEG standard does not specify all details of an interchangeable file +format. For the omitted details we follow the "JFIF" conventions, revision +1.02. A copy of the JFIF spec is available from: + Literature Department + C-Cube Microsystems, Inc. + 1778 McCarthy Blvd. + Milpitas, CA 95035 + phone (408) 944-6300, fax (408) 944-6314 +A PostScript version of this document is available by FTP at +ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text +version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing +the figures. + +The TIFF 6.0 file format specification can be obtained by FTP from +ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme +found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. +IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). +Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 +(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or +from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision +of the TIFF spec will replace the 6.0 JPEG design with the Note's design. +Although IJG's own code does not support TIFF/JPEG, the free libtiff library +uses our library to implement TIFF/JPEG per the Note. libtiff is available +from ftp://ftp.sgi.com/graphics/tiff/. + + +ARCHIVE LOCATIONS +================= + +The "official" archive site for this software is ftp.uu.net (Internet +address 192.48.96.9). The most recent released version can always be found +there in directory graphics/jpeg. This particular version will be archived +as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have +direct Internet access, UUNET's archives are also available via UUCP; contact +help@uunet.uu.net for information on retrieving files that way. + +Numerous Internet sites maintain copies of the UUNET files. However, only +ftp.uu.net is guaranteed to have the latest official version. + +You can also obtain this software in DOS-compatible "zip" archive format from +the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or +on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 +"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net +release. + +The JPEG FAQ (Frequently Asked Questions) article is a useful source of +general information about JPEG. It is updated constantly and therefore is +not included in this distribution. The FAQ is posted every two weeks to +Usenet newsgroups comp.graphics.misc, news.answers, and other groups. +It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ +and other news.answers archive sites, including the official news.answers +archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. +If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu +with body + send usenet/news.answers/jpeg-faq/part1 + send usenet/news.answers/jpeg-faq/part2 + + +RELATED SOFTWARE +================ + +Numerous viewing and image manipulation programs now support JPEG. (Quite a +few of them use this library to do so.) The JPEG FAQ described above lists +some of the more popular free and shareware viewers, and tells where to +obtain them on Internet. + +If you are on a Unix machine, we highly recommend Jef Poskanzer's free +PBMPLUS software, which provides many useful operations on PPM-format image +files. In particular, it can convert PPM images to and from a wide range of +other formats, thus making cjpeg/djpeg considerably more useful. The latest +version is distributed by the NetPBM group, and is available from numerous +sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. +Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; +you are likely to have difficulty making it work on any non-Unix machine. + +A different free JPEG implementation, written by the PVRG group at Stanford, +is available from ftp://havefun.stanford.edu/pub/jpeg/. This program +is designed for research and experimentation rather than production use; +it is slower, harder to use, and less portable than the IJG code, but it +is easier to read and modify. Also, the PVRG code supports lossless JPEG, +which we do not. (On the other hand, it doesn't do progressive JPEG.) + + +FILE FORMAT WARS +================ + +Some JPEG programs produce files that are not compatible with our library. +The root of the problem is that the ISO JPEG committee failed to specify a +concrete file format. Some vendors "filled in the blanks" on their own, +creating proprietary formats that no one else could read. (For example, none +of the early commercial JPEG implementations for the Macintosh were able to +exchange compressed files.) + +The file format we have adopted is called JFIF (see REFERENCES). This format +has been agreed to by a number of major commercial JPEG vendors, and it has +become the de facto standard. JFIF is a minimal or "low end" representation. +We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF +Technical Note #2) for "high end" applications that need to record a lot of +additional data about an image. TIFF/JPEG is fairly new and not yet widely +supported, unfortunately. + +The upcoming JPEG Part 3 standard defines a file format called SPIFF. +SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should +be able to read the most common variant of SPIFF. SPIFF has some technical +advantages over JFIF, but its major claim to fame is simply that it is an +official standard rather than an informal one. At this point it is unclear +whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto +standard. IJG intends to support SPIFF once the standard is frozen, but we +have not decided whether it should become our default output format or not. +(In any case, our decoder will remain capable of reading JFIF indefinitely.) + +Various proprietary file formats incorporating JPEG compression also exist. +We have little or no sympathy for the existence of these formats. Indeed, +one of the original reasons for developing this free software was to help +force convergence on common, open format standards for JPEG files. Don't +use a proprietary file format! + + +TO DO +===== + +The major thrust for v7 will probably be improvement of visual quality. +The current method for scaling the quantization tables is known not to be +very good at low Q values. We also intend to investigate block boundary +smoothing, "poor man's variable quantization", and other means of improving +quality-vs-file-size performance without sacrificing compatibility. + +In future versions, we are considering supporting some of the upcoming JPEG +Part 3 extensions --- principally, variable quantization and the SPIFF file +format. + +As always, speeding things up is of great interest. + +Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. diff --git a/Utilities/vtkjpeg/README.VTK.txt b/Utilities/vtkjpeg/README.VTK.txt new file mode 100644 index 0000000..ebe67e2 --- /dev/null +++ b/Utilities/vtkjpeg/README.VTK.txt @@ -0,0 +1,22 @@ +This directory contains a subset of the Independent JPEG Group's (IJG) +libjpeg version 6b. We only include enough of distribution to build +libjpeg. We do not include the standard executables that come with +libjpeg (cjpeg, djpeg, etc.). Furthermore, the standard libjpeg build +process is replaced with a CMake build process. + +We'd like to thank the IJG for distributing a public JPEG IO library. + +Modifications +------------- + +jconfig.h is usually generated by the build process. For this distribution, +we ship a version of jconfig.h to be used across several platforms. + +jmorecfg.h was altered to support Windows DLL generation. We also +changed the typedef INT32 to be an "int" instead of a "long". + + + + + + diff --git a/Utilities/vtkjpeg/change.log b/Utilities/vtkjpeg/change.log new file mode 100644 index 0000000..74102c0 --- /dev/null +++ b/Utilities/vtkjpeg/change.log @@ -0,0 +1,217 @@ +CHANGE LOG for Independent JPEG Group's JPEG software + + +Version 6b 27-Mar-1998 +----------------------- + +jpegtran has new features for lossless image transformations (rotation +and flipping) as well as "lossless" reduction to grayscale. + +jpegtran now copies comments by default; it has a -copy switch to enable +copying all APPn blocks as well, or to suppress comments. (Formerly it +always suppressed comments and APPn blocks.) jpegtran now also preserves +JFIF version and resolution information. + +New decompressor library feature: COM and APPn markers found in the input +file can be saved in memory for later use by the application. (Before, +you had to code this up yourself with a custom marker processor.) + +There is an unused field "void * client_data" now in compress and decompress +parameter structs; this may be useful in some applications. + +JFIF version number information is now saved by the decoder and accepted by +the encoder. jpegtran uses this to copy the source file's version number, +to ensure "jpegtran -copy all" won't create bogus files that contain JFXX +extensions but claim to be version 1.01. Applications that generate their +own JFXX extension markers also (finally) have a supported way to cause the +encoder to emit JFIF version number 1.02. + +djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather +than as unknown APP0 markers. + +In -verbose mode, djpeg and rdjpgcom will try to print the contents of +APP12 markers as text. Some digital cameras store useful text information +in APP12 markers. + +Handling of truncated data streams is more robust: blocks beyond the one in +which the error occurs will be output as uniform gray, or left unchanged +if decoding a progressive JPEG. The appearance no longer depends on the +Huffman tables being used. + +Huffman tables are checked for validity much more carefully than before. + +To avoid the Unisys LZW patent, djpeg's GIF output capability has been +changed to produce "uncompressed GIFs", and cjpeg's GIF input capability +has been removed altogether. We're not happy about it either, but there +seems to be no good alternative. + +The configure script now supports building libjpeg as a shared library +on many flavors of Unix (all the ones that GNU libtool knows how to +build shared libraries for). Use "./configure --enable-shared" to +try this out. + +New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio. +Also, a jconfig file and a build script for Metrowerks CodeWarrior +on Apple Macintosh. makefile.dj has been updated for DJGPP v2, and there +are miscellaneous other minor improvements in the makefiles. + +jmemmac.c now knows how to create temporary files following Mac System 7 +conventions. + +djpeg's -map switch is now able to read raw-format PPM files reliably. + +cjpeg -progressive -restart no longer generates any unnecessary DRI markers. + +Multiple calls to jpeg_simple_progression for a single JPEG object +no longer leak memory. + + +Version 6a 7-Feb-96 +-------------------- + +Library initialization sequence modified to detect version mismatches +and struct field packing mismatches between library and calling application. +This change requires applications to be recompiled, but does not require +any application source code change. + +All routine declarations changed to the style "GLOBAL(type) name ...", +that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the +routine's return type as an argument. This makes it possible to add +Microsoft-style linkage keywords to all the routines by changing just +these macros. Note that any application code that was using these macros +will have to be changed. + +DCT coefficient quantization tables are now stored in normal array order +rather than zigzag order. Application code that calls jpeg_add_quant_table, +or otherwise manipulates quantization tables directly, will need to be +changed. If you need to make such code work with either older or newer +versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is +recommended. + +djpeg's trace capability now dumps DQT tables in natural order, not zigzag +order. This allows the trace output to be made into a "-qtables" file +more easily. + +New system-dependent memory manager module for use on Apple Macintosh. + +Fix bug in cjpeg's -smooth option: last one or two scanlines would be +duplicates of the prior line unless the image height mod 16 was 1 or 2. + +Repair minor problems in VMS, BCC, MC6 makefiles. + +New configure script based on latest GNU Autoconf. + +Correct the list of include files needed by MetroWerks C for ccommand(). + +Numerous small documentation updates. + + +Version 6 2-Aug-95 +------------------- + +Progressive JPEG support: library can read and write full progressive JPEG +files. A "buffered image" mode supports incremental decoding for on-the-fly +display of progressive images. Simply recompiling an existing IJG-v5-based +decoder with v6 should allow it to read progressive files, though of course +without any special progressive display. + +New "jpegtran" application performs lossless transcoding between different +JPEG formats; primarily, it can be used to convert baseline to progressive +JPEG and vice versa. In support of jpegtran, the library now allows lossless +reading and writing of JPEG files as DCT coefficient arrays. This ability +may be of use in other applications. + +Notes for programmers: +* We changed jpeg_start_decompress() to be able to suspend; this makes all +decoding modes available to suspending-input applications. However, +existing applications that use suspending input will need to be changed +to check the return value from jpeg_start_decompress(). You don't need to +do anything if you don't use a suspending data source. +* We changed the interface to the virtual array routines: access_virt_array +routines now take a count of the number of rows to access this time. The +last parameter to request_virt_array routines is now interpreted as the +maximum number of rows that may be accessed at once, but not necessarily +the height of every access. + + +Version 5b 15-Mar-95 +--------------------- + +Correct bugs with grayscale images having v_samp_factor > 1. + +jpeg_write_raw_data() now supports output suspension. + +Correct bugs in "configure" script for case of compiling in +a directory other than the one containing the source files. + +Repair bug in jquant1.c: sometimes didn't use as many colors as it could. + +Borland C makefile and jconfig file work under either MS-DOS or OS/2. + +Miscellaneous improvements to documentation. + + +Version 5a 7-Dec-94 +-------------------- + +Changed color conversion roundoff behavior so that grayscale values are +represented exactly. (This causes test image files to change.) + +Make ordered dither use 16x16 instead of 4x4 pattern for a small quality +improvement. + +New configure script based on latest GNU Autoconf. +Fix configure script to handle CFLAGS correctly. +Rename *.auto files to *.cfg, so that configure script still works if +file names have been truncated for DOS. + +Fix bug in rdbmp.c: didn't allow for extra data between header and image. + +Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data. + +Fix several bugs in rdrle.c. + +NEED_SHORT_EXTERNAL_NAMES option was broken. + +Revise jerror.h/jerror.c for more flexibility in message table. + +Repair oversight in jmemname.c NO_MKTEMP case: file could be there +but unreadable. + + +Version 5 24-Sep-94 +-------------------- + +Version 5 represents a nearly complete redesign and rewrite of the IJG +software. Major user-visible changes include: + * Automatic configuration simplifies installation for most Unix systems. + * A range of speed vs. image quality tradeoffs are supported. + This includes resizing of an image during decompression: scaling down + by a factor of 1/2, 1/4, or 1/8 is handled very efficiently. + * New programs rdjpgcom and wrjpgcom allow insertion and extraction + of text comments in a JPEG file. + +The application programmer's interface to the library has changed completely. +Notable improvements include: + * We have eliminated the use of callback routines for handling the + uncompressed image data. The application now sees the library as a + set of routines that it calls to read or write image data on a + scanline-by-scanline basis. + * The application image data is represented in a conventional interleaved- + pixel format, rather than as a separate array for each color channel. + This can save a copying step in many programs. + * The handling of compressed data has been cleaned up: the application can + supply routines to source or sink the compressed data. It is possible to + suspend processing on source/sink buffer overrun, although this is not + supported in all operating modes. + * All static state has been eliminated from the library, so that multiple + instances of compression or decompression can be active concurrently. + * JPEG abbreviated datastream formats are supported, ie, quantization and + Huffman tables can be stored separately from the image data. + * And not only that, but the documentation of the library has improved + considerably! + + +The last widely used release before the version 5 rewrite was version 4A of +18-Feb-93. Change logs before that point have been discarded, since they +are not of much interest after the rewrite. diff --git a/Utilities/vtkjpeg/filelist.doc b/Utilities/vtkjpeg/filelist.doc new file mode 100644 index 0000000..ad6a82d --- /dev/null +++ b/Utilities/vtkjpeg/filelist.doc @@ -0,0 +1,210 @@ +IJG JPEG LIBRARY: FILE LIST + +Copyright (C) 1994-1998, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +Here is a road map to the files in the IJG JPEG distribution. The +distribution includes the JPEG library proper, plus two application +programs ("cjpeg" and "djpeg") which use the library to convert JPEG +files to and from some other popular image formats. A third application +"jpegtran" uses the library to do lossless conversion between different +variants of JPEG. There are also two stand-alone applications, +"rdjpgcom" and "wrjpgcom". + + +THE JPEG LIBRARY +================ + +Include files: + +jpeglib.h JPEG library's exported data and function declarations. +jconfig.h Configuration declarations. Note: this file is not present + in the distribution; it is generated during installation. +jmorecfg.h Additional configuration declarations; need not be changed + for a standard installation. +jerror.h Declares JPEG library's error and trace message codes. +jinclude.h Central include file used by all IJG .c files to reference + system include files. +jpegint.h JPEG library's internal data structures. +jchuff.h Private declarations for Huffman encoder modules. +jdhuff.h Private declarations for Huffman decoder modules. +jdct.h Private declarations for forward & reverse DCT subsystems. +jmemsys.h Private declarations for memory management subsystem. +jversion.h Version information. + +Applications using the library should include jpeglib.h (which in turn +includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included +if the application needs to reference individual JPEG error codes. The +other include files are intended for internal use and would not normally +be included by an application program. (cjpeg/djpeg/etc do use jinclude.h, +since its function is to improve portability of the whole IJG distribution. +Most other applications will directly include the system include files they +want, and hence won't need jinclude.h.) + + +C source code files: + +These files contain most of the functions intended to be called directly by +an application program: + +jcapimin.c Application program interface: core routines for compression. +jcapistd.c Application program interface: standard compression. +jdapimin.c Application program interface: core routines for decompression. +jdapistd.c Application program interface: standard decompression. +jcomapi.c Application program interface routines common to compression + and decompression. +jcparam.c Compression parameter setting helper routines. +jctrans.c API and library routines for transcoding compression. +jdtrans.c API and library routines for transcoding decompression. + +Compression side of the library: + +jcinit.c Initialization: determines which other modules to use. +jcmaster.c Master control: setup and inter-pass sequencing logic. +jcmainct.c Main buffer controller (preprocessor => JPEG compressor). +jcprepct.c Preprocessor buffer controller. +jccoefct.c Buffer controller for DCT coefficient buffer. +jccolor.c Color space conversion. +jcsample.c Downsampling. +jcdctmgr.c DCT manager (DCT implementation selection & control). +jfdctint.c Forward DCT using slow-but-accurate integer method. +jfdctfst.c Forward DCT using faster, less accurate integer method. +jfdctflt.c Forward DCT using floating-point arithmetic. +jchuff.c Huffman entropy coding for sequential JPEG. +jcphuff.c Huffman entropy coding for progressive JPEG. +jcmarker.c JPEG marker writing. +jdatadst.c Data destination manager for stdio output. + +Decompression side of the library: + +jdmaster.c Master control: determines which other modules to use. +jdinput.c Input controller: controls input processing modules. +jdmainct.c Main buffer controller (JPEG decompressor => postprocessor). +jdcoefct.c Buffer controller for DCT coefficient buffer. +jdpostct.c Postprocessor buffer controller. +jdmarker.c JPEG marker reading. +jdhuff.c Huffman entropy decoding for sequential JPEG. +jdphuff.c Huffman entropy decoding for progressive JPEG. +jddctmgr.c IDCT manager (IDCT implementation selection & control). +jidctint.c Inverse DCT using slow-but-accurate integer method. +jidctfst.c Inverse DCT using faster, less accurate integer method. +jidctflt.c Inverse DCT using floating-point arithmetic. +jidctred.c Inverse DCTs with reduced-size outputs. +jdsample.c Upsampling. +jdcolor.c Color space conversion. +jdmerge.c Merged upsampling/color conversion (faster, lower quality). +jquant1.c One-pass color quantization using a fixed-spacing colormap. +jquant2.c Two-pass color quantization using a custom-generated colormap. + Also handles one-pass quantization to an externally given map. +jdatasrc.c Data source manager for stdio input. + +Support files for both compression and decompression: + +jerror.c Standard error handling routines (application replaceable). +jmemmgr.c System-independent (more or less) memory management code. +jutils.c Miscellaneous utility routines. + +jmemmgr.c relies on a system-dependent memory management module. The IJG +distribution includes the following implementations of the system-dependent +module: + +jmemnobs.c "No backing store": assumes adequate virtual memory exists. +jmemansi.c Makes temporary files with ANSI-standard routine tmpfile(). +jmemname.c Makes temporary files with program-generated file names. +jmemdos.c Custom implementation for MS-DOS (16-bit environment only): + can use extended and expanded memory as well as temp files. +jmemmac.c Custom implementation for Apple Macintosh. + +Exactly one of the system-dependent modules should be configured into an +installed JPEG library (see install.doc for hints about which one to use). +On unusual systems you may find it worthwhile to make a special +system-dependent memory manager. + + +Non-C source code files: + +jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in + MS-DOS-specific configurations of the JPEG library. + + +CJPEG/DJPEG/JPEGTRAN +==================== + +Include files: + +cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules. +cderror.h Additional error and trace message codes for cjpeg et al. +transupp.h Declarations for jpegtran support routines in transupp.c. + +C source code files: + +cjpeg.c Main program for cjpeg. +djpeg.c Main program for djpeg. +jpegtran.c Main program for jpegtran. +cdjpeg.c Utility routines used by all three programs. +rdcolmap.c Code to read a colormap file for djpeg's "-map" switch. +rdswitch.c Code to process some of cjpeg's more complex switches. + Also used by jpegtran. +transupp.c Support code for jpegtran: lossless image manipulations. + +Image file reader modules for cjpeg: + +rdbmp.c BMP file input. +rdgif.c GIF file input (now just a stub). +rdppm.c PPM/PGM file input. +rdrle.c Utah RLE file input. +rdtarga.c Targa file input. + +Image file writer modules for djpeg: + +wrbmp.c BMP file output. +wrgif.c GIF file output (a mere shadow of its former self). +wrppm.c PPM/PGM file output. +wrrle.c Utah RLE file output. +wrtarga.c Targa file output. + + +RDJPGCOM/WRJPGCOM +================= + +C source code files: + +rdjpgcom.c Stand-alone rdjpgcom application. +wrjpgcom.c Stand-alone wrjpgcom application. + +These programs do not depend on the IJG library. They do use +jconfig.h and jinclude.h, only to improve portability. + + +ADDITIONAL FILES +================ + +Documentation (see README for a guide to the documentation files): + +README Master documentation file. +*.doc Other documentation files. +*.1 Documentation in Unix man page format. +change.log Version-to-version change highlights. +example.c Sample code for calling JPEG library. + +Configuration/installation files and programs (see install.doc for more info): + +configure Unix shell script to perform automatic configuration. +ltconfig Support scripts for configure (from GNU libtool). +ltmain.sh +config.guess +config.sub +install-sh Install shell script for those Unix systems lacking one. +ckconfig.c Program to generate jconfig.h on non-Unix systems. +jconfig.doc Template for making jconfig.h by hand. +makefile.* Sample makefiles for particular systems. +jconfig.* Sample jconfig.h for particular systems. +ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of + L. Peter Deutsch and Aladdin Enterprises). + +Test files (see install.doc for test procedure): + +test*.* Source and comparison files for confidence test. + These are binary image files, NOT text files. diff --git a/Utilities/vtkjpeg/install.doc b/Utilities/vtkjpeg/install.doc new file mode 100644 index 0000000..7d72c93 --- /dev/null +++ b/Utilities/vtkjpeg/install.doc @@ -0,0 +1,1063 @@ +INSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software + +Copyright (C) 1991-1998, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file explains how to configure and install the IJG software. We have +tried to make this software extremely portable and flexible, so that it can be +adapted to almost any environment. The downside of this decision is that the +installation process is complicated. We have provided shortcuts to simplify +the task on common systems. But in any case, you will need at least a little +familiarity with C programming and program build procedures for your system. + +If you are only using this software as part of a larger program, the larger +program's installation procedure may take care of configuring the IJG code. +For example, Ghostscript's installation script will configure the IJG code. +You don't need to read this file if you just want to compile Ghostscript. + +If you are on a Unix machine, you may not need to read this file at all. +Try doing + ./configure + make + make test +If that doesn't complain, do + make install +(better do "make -n install" first to see if the makefile will put the files +where you want them). Read further if you run into snags or want to customize +the code for your system. + + +TABLE OF CONTENTS +----------------- + +Before you start +Configuring the software: + using the automatic "configure" script + using one of the supplied jconfig and makefile files + by hand +Building the software +Testing the software +Installing the software +Optional stuff +Optimization +Hints for specific systems + + +BEFORE YOU START +================ + +Before installing the software you must unpack the distributed source code. +Since you are reading this file, you have probably already succeeded in this +task. However, there is a potential for error if you needed to convert the +files to the local standard text file format (for example, if you are on +MS-DOS you may have converted LF end-of-line to CR/LF). You must apply +such conversion to all the files EXCEPT those whose names begin with "test". +The test files contain binary data; if you change them in any way then the +self-test will give bad results. + +Please check the last section of this file to see if there are hints for the +specific machine or compiler you are using. + + +CONFIGURING THE SOFTWARE +======================== + +To configure the IJG code for your system, you need to create two files: + * jconfig.h: contains values for system-dependent #define symbols. + * Makefile: controls the compilation process. +(On a non-Unix machine, you may create "project files" or some other +substitute for a Makefile. jconfig.h is needed in any environment.) + +We provide three different ways to generate these files: + * On a Unix system, you can just run the "configure" script. + * We provide sample jconfig files and makefiles for popular machines; + if your machine matches one of the samples, just copy the right sample + files to jconfig.h and Makefile. + * If all else fails, read the instructions below and make your own files. + + +Configuring the software using the automatic "configure" script +--------------------------------------------------------------- + +If you are on a Unix machine, you can just type + ./configure +and let the configure script construct appropriate configuration files. +If you're using "csh" on an old version of System V, you might need to type + sh configure +instead to prevent csh from trying to execute configure itself. +Expect configure to run for a few minutes, particularly on slower machines; +it works by compiling a series of test programs. + +Configure was created with GNU Autoconf and it follows the usual conventions +for GNU configure scripts. It makes a few assumptions that you may want to +override. You can do this by providing optional switches to configure: + +* If you want to build libjpeg as a shared library, say + ./configure --enable-shared +To get both shared and static libraries, say + ./configure --enable-shared --enable-static +Note that these switches invoke GNU libtool to take care of system-dependent +shared library building methods. If things don't work this way, please try +running configure without either switch; that should build a static library +without using libtool. If that works, your problem is probably with libtool +not with the IJG code. libtool is fairly new and doesn't support all flavors +of Unix yet. (You might be able to find a newer version of libtool than the +one included with libjpeg; see ftp.gnu.org. Report libtool problems to +bug-libtool@gnu.org.) + +* Configure will use gcc (GNU C compiler) if it's available, otherwise cc. +To force a particular compiler to be selected, use the CC option, for example + ./configure CC='cc' +The same method can be used to include any unusual compiler switches. +For example, on HP-UX you probably want to say + ./configure CC='cc -Aa' +to get HP's compiler to run in ANSI mode. + +* The default CFLAGS setting is "-O" for non-gcc compilers, "-O2" for gcc. +You can override this by saying, for example, + ./configure CFLAGS='-g' +if you want to compile with debugging support. + +* Configure will set up the makefile so that "make install" will install files +into /usr/local/bin, /usr/local/man, etc. You can specify an installation +prefix other than "/usr/local" by giving configure the option "--prefix=PATH". + +* If you don't have a lot of swap space, you may need to enable the IJG +software's internal virtual memory mechanism. To do this, give the option +"--enable-maxmem=N" where N is the default maxmemory limit in megabytes. +This is discussed in more detail under "Selecting a memory manager", below. +You probably don't need to worry about this on reasonably-sized Unix machines, +unless you plan to process very large images. + +Configure has some other features that are useful if you are cross-compiling +or working in a network of multiple machine types; but if you need those +features, you probably already know how to use them. + + +Configuring the software using one of the supplied jconfig and makefile files +----------------------------------------------------------------------------- + +If you have one of these systems, you can just use the provided configuration +files: + +Makefile jconfig file System and/or compiler + +makefile.manx jconfig.manx Amiga, Manx Aztec C +makefile.sas jconfig.sas Amiga, SAS C +makeproj.mac jconfig.mac Apple Macintosh, Metrowerks CodeWarrior +mak*jpeg.st jconfig.st Atari ST/STE/TT, Pure C or Turbo C +makefile.bcc jconfig.bcc MS-DOS or OS/2, Borland C +makefile.dj jconfig.dj MS-DOS, DJGPP (Delorie's port of GNU C) +makefile.mc6 jconfig.mc6 MS-DOS, Microsoft C (16-bit only) +makefile.wat jconfig.wat MS-DOS, OS/2, or Windows NT, Watcom C +makefile.vc jconfig.vc Windows NT/95, MS Visual C++ +make*.ds jconfig.vc Windows NT/95, MS Developer Studio +makefile.mms jconfig.vms Digital VMS, with MMS software +makefile.vms jconfig.vms Digital VMS, without MMS software + +Copy the proper jconfig file to jconfig.h and the makefile to Makefile (or +whatever your system uses as the standard makefile name). For more info see +the appropriate system-specific hints section near the end of this file. + + +Configuring the software by hand +-------------------------------- + +First, generate a jconfig.h file. If you are moderately familiar with C, +the comments in jconfig.doc should be enough information to do this; just +copy jconfig.doc to jconfig.h and edit it appropriately. Otherwise, you may +prefer to use the ckconfig.c program. You will need to compile and execute +ckconfig.c by hand --- we hope you know at least enough to do that. +ckconfig.c may not compile the first try (in fact, the whole idea is for it +to fail if anything is going to). If you get compile errors, fix them by +editing ckconfig.c according to the directions given in ckconfig.c. Once +you get it to run, it will write a suitable jconfig.h file, and will also +print out some advice about which makefile to use. + +You may also want to look at the canned jconfig files, if there is one for a +system similar to yours. + +Second, select a makefile and copy it to Makefile (or whatever your system +uses as the standard makefile name). The most generic makefiles we provide +are + makefile.ansi: if your C compiler supports function prototypes + makefile.unix: if not. +(You have function prototypes if ckconfig.c put "#define HAVE_PROTOTYPES" +in jconfig.h.) You may want to start from one of the other makefiles if +there is one for a system similar to yours. + +Look over the selected Makefile and adjust options as needed. In particular +you may want to change the CC and CFLAGS definitions. For instance, if you +are using GCC, set CC=gcc. If you had to use any compiler switches to get +ckconfig.c to work, make sure the same switches are in CFLAGS. + +If you are on a system that doesn't use makefiles, you'll need to set up +project files (or whatever you do use) to compile all the source files and +link them into executable files cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. +See the file lists in any of the makefiles to find out which files go into +each program. Note that the provided makefiles all make a "library" file +libjpeg first, but you don't have to do that if you don't want to; the file +lists identify which source files are actually needed for compression, +decompression, or both. As a last resort, you can make a batch script that +just compiles everything and links it all together; makefile.vms is an example +of this (it's for VMS systems that have no make-like utility). + +Here are comments about some specific configuration decisions you'll +need to make: + +Command line style +------------------ + +These programs can use a Unix-like command line style which supports +redirection and piping, like this: + cjpeg inputfile >outputfile + cjpeg <inputfile >outputfile + source program | cjpeg >outputfile +The simpler "two file" command line style is just + cjpeg inputfile outputfile +You may prefer the two-file style, particularly if you don't have pipes. + +You MUST use two-file style on any system that doesn't cope well with binary +data fed through stdin/stdout; this is true for some MS-DOS compilers, for +example. If you're not on a Unix system, it's safest to assume you need +two-file style. (But if your compiler provides either the Posix-standard +fdopen() library routine or a Microsoft-compatible setmode() routine, you +can safely use the Unix command line style, by defining USE_FDOPEN or +USE_SETMODE respectively.) + +To use the two-file style, make jconfig.h say "#define TWO_FILE_COMMANDLINE". + +Selecting a memory manager +-------------------------- + +The IJG code is capable of working on images that are too big to fit in main +memory; data is swapped out to temporary files as necessary. However, the +code to do this is rather system-dependent. We provide five different +memory managers: + +* jmemansi.c This version uses the ANSI-standard library routine tmpfile(), + which not all non-ANSI systems have. On some systems + tmpfile() may put the temporary file in a non-optimal + location; if you don't like what it does, use jmemname.c. + +* jmemname.c This version creates named temporary files. For anything + except a Unix machine, you'll need to configure the + select_file_name() routine appropriately; see the comments + near the head of jmemname.c. If you use this version, define + NEED_SIGNAL_CATCHER in jconfig.h to make sure the temp files + are removed if the program is aborted. + +* jmemnobs.c (That stands for No Backing Store :-).) This will compile on + almost any system, but it assumes you have enough main memory + or virtual memory to hold the biggest images you work with. + +* jmemdos.c This should be used with most 16-bit MS-DOS compilers. + See the system-specific notes about MS-DOS for more info. + IMPORTANT: if you use this, define USE_MSDOS_MEMMGR in + jconfig.h, and include the assembly file jmemdosa.asm in the + programs. The supplied makefiles and jconfig files for + 16-bit MS-DOS compilers already do both. + +* jmemmac.c Custom version for Apple Macintosh; see the system-specific + notes for Macintosh for more info. + +To use a particular memory manager, change the SYSDEPMEM variable in your +makefile to equal the corresponding object file name (for example, jmemansi.o +or jmemansi.obj for jmemansi.c). + +If you have plenty of (real or virtual) main memory, just use jmemnobs.c. +"Plenty" means about ten bytes for every pixel in the largest images +you plan to process, so a lot of systems don't meet this criterion. +If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have +to use jmemname.c; be sure to adjust select_file_name() for local conditions. +You may also need to change unlink() to remove() in close_backing_store(). + +Except with jmemnobs.c or jmemmac.c, you need to adjust the DEFAULT_MAX_MEM +setting to a reasonable value for your system (either by adding a #define for +DEFAULT_MAX_MEM to jconfig.h, or by adding a -D switch to the Makefile). +This value limits the amount of data space the program will attempt to +allocate. Code and static data space isn't counted, so the actual memory +needs for cjpeg or djpeg are typically 100 to 150Kb more than the max-memory +setting. Larger max-memory settings reduce the amount of I/O needed to +process a large image, but too large a value can result in "insufficient +memory" failures. On most Unix machines (and other systems with virtual +memory), just set DEFAULT_MAX_MEM to several million and forget it. At the +other end of the spectrum, for MS-DOS machines you probably can't go much +above 300K to 400K. (On MS-DOS the value refers to conventional memory only. +Extended/expanded memory is handled separately by jmemdos.c.) + + +BUILDING THE SOFTWARE +===================== + +Now you should be able to compile the software. Just say "make" (or +whatever's necessary to start the compilation). Have a cup of coffee. + +Here are some things that could go wrong: + +If your compiler complains about undefined structures, you should be able to +shut it up by putting "#define INCOMPLETE_TYPES_BROKEN" in jconfig.h. + +If you have trouble with missing system include files or inclusion of the +wrong ones, read jinclude.h. This shouldn't happen if you used configure +or ckconfig.c to set up jconfig.h. + +There are a fair number of routines that do not use all of their parameters; +some compilers will issue warnings about this, which you can ignore. There +are also a few configuration checks that may give "unreachable code" warnings. +Any other warning deserves investigation. + +If you don't have a getenv() library routine, define NO_GETENV. + +Also see the system-specific hints, below. + + +TESTING THE SOFTWARE +==================== + +As a quick test of functionality we've included a small sample image in +several forms: + testorig.jpg Starting point for the djpeg tests. + testimg.ppm The output of djpeg testorig.jpg + testimg.bmp The output of djpeg -bmp -colors 256 testorig.jpg + testimg.jpg The output of cjpeg testimg.ppm + testprog.jpg Progressive-mode equivalent of testorig.jpg. + testimgp.jpg The output of cjpeg -progressive -optimize testimg.ppm +(The first- and second-generation .jpg files aren't identical since JPEG is +lossy.) If you can generate duplicates of the testimg* files then you +probably have working programs. + +With most of the makefiles, "make test" will perform the necessary +comparisons. + +If you're using a makefile that doesn't provide the test option, run djpeg +and cjpeg by hand and compare the output files to testimg* with whatever +binary file comparison tool you have. The files should be bit-for-bit +identical. + +If the programs complain "MAX_ALLOC_CHUNK is wrong, please fix", then you +need to reduce MAX_ALLOC_CHUNK to a value that fits in type size_t. +Try adding "#define MAX_ALLOC_CHUNK 65520L" to jconfig.h. A less likely +configuration error is "ALIGN_TYPE is wrong, please fix": defining ALIGN_TYPE +as long should take care of that one. + +If the cjpeg test run fails with "Missing Huffman code table entry", it's a +good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to the +configuration step and run ckconfig.c. (This is a good plan for any other +test failure, too.) + +If you are using Unix (one-file) command line style on a non-Unix system, +it's a good idea to check that binary I/O through stdin/stdout actually +works. You should get the same results from "djpeg <testorig.jpg >out.ppm" +as from "djpeg -outfile out.ppm testorig.jpg". Note that the makefiles all +use the latter style and therefore do not exercise stdin/stdout! If this +check fails, try recompiling with USE_SETMODE or USE_FDOPEN defined. +If it still doesn't work, better use two-file style. + +If you chose a memory manager other than jmemnobs.c, you should test that +temporary-file usage works. Try "djpeg -bmp -colors 256 -max 0 testorig.jpg" +and make sure its output matches testimg.bmp. If you have any really large +images handy, try compressing them with -optimize and/or decompressing with +-colors 256 to make sure your DEFAULT_MAX_MEM setting is not too large. + +NOTE: this is far from an exhaustive test of the JPEG software; some modules, +such as 1-pass color quantization, are not exercised at all. It's just a +quick test to give you some confidence that you haven't missed something +major. + + +INSTALLING THE SOFTWARE +======================= + +Once you're done with the above steps, you can install the software by +copying the executable files (cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom) +to wherever you normally install programs. On Unix systems, you'll also want +to put the man pages (cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1) +in the man-page directory. The pre-fab makefiles don't support this step +since there's such a wide variety of installation procedures on different +systems. + +If you generated a Makefile with the "configure" script, you can just say + make install +to install the programs and their man pages into the standard places. +(You'll probably need to be root to do this.) We recommend first saying + make -n install +to see where configure thought the files should go. You may need to edit +the Makefile, particularly if your system's conventions for man page +filenames don't match what configure expects. + +If you want to install the IJG library itself, for use in compiling other +programs besides ours, then you need to put the four include files + jpeglib.h jerror.h jconfig.h jmorecfg.h +into your include-file directory, and put the library file libjpeg.a +(extension may vary depending on system) wherever library files go. +If you generated a Makefile with "configure", it will do what it thinks +is the right thing if you say + make install-lib + + +OPTIONAL STUFF +============== + +Progress monitor: + +If you like, you can #define PROGRESS_REPORT (in jconfig.h) to enable display +of percent-done progress reports. The routine provided in cdjpeg.c merely +prints percentages to stderr, but you can customize it to do something +fancier. + +Utah RLE file format support: + +We distribute the software with support for RLE image files (Utah Raster +Toolkit format) disabled, because the RLE support won't compile without the +Utah library. If you have URT version 3.1 or later, you can enable RLE +support as follows: + 1. #define RLE_SUPPORTED in jconfig.h. + 2. Add a -I option to CFLAGS in the Makefile for the directory + containing the URT .h files (typically the "include" + subdirectory of the URT distribution). + 3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies + the directory containing the URT "librle.a" file (typically the + "lib" subdirectory of the URT distribution). + +Support for 12-bit-deep pixel data: + +The JPEG standard allows either 8-bit or 12-bit data precision. (For color, +this means 8 or 12 bits per channel, of course.) If you need to work with +deeper than 8-bit data, you can compile the IJG code for 12-bit operation. +To do so: + 1. In jmorecfg.h, define BITS_IN_JSAMPLE as 12 rather than 8. + 2. In jconfig.h, undefine BMP_SUPPORTED, RLE_SUPPORTED, and TARGA_SUPPORTED, + because the code for those formats doesn't handle 12-bit data and won't + even compile. (The PPM code does work, as explained below. The GIF + code works too; it scales 8-bit GIF data to and from 12-bit depth + automatically.) + 3. Compile. Don't expect "make test" to pass, since the supplied test + files are for 8-bit data. + +Currently, 12-bit support does not work on 16-bit-int machines. + +Note that a 12-bit version will not read 8-bit JPEG files, nor vice versa; +so you'll want to keep around a regular 8-bit compilation as well. +(Run-time selection of data depth, to allow a single copy that does both, +is possible but would probably slow things down considerably; it's very low +on our to-do list.) + +The PPM reader (rdppm.c) can read 12-bit data from either text-format or +binary-format PPM and PGM files. Binary-format PPM/PGM files which have a +maxval greater than 255 are assumed to use 2 bytes per sample, LSB first +(little-endian order). As of early 1995, 2-byte binary format is not +officially supported by the PBMPLUS library, but it is expected that a +future release of PBMPLUS will support it. Note that the PPM reader will +read files of any maxval regardless of the BITS_IN_JSAMPLE setting; incoming +data is automatically rescaled to either maxval=255 or maxval=4095 as +appropriate for the cjpeg bit depth. + +The PPM writer (wrppm.c) will normally write 2-byte binary PPM or PGM +format, maxval 4095, when compiled with BITS_IN_JSAMPLE=12. Since this +format is not yet widely supported, you can disable it by compiling wrppm.c +with PPM_NORAWWORD defined; then the data is scaled down to 8 bits to make a +standard 1-byte/sample PPM or PGM file. (Yes, this means still another copy +of djpeg to keep around. But hopefully you won't need it for very long. +Poskanzer's supposed to get that new PBMPLUS release out Real Soon Now.) + +Of course, if you are working with 12-bit data, you probably have it stored +in some other, nonstandard format. In that case you'll probably want to +write your own I/O modules to read and write your format. + +Note that a 12-bit version of cjpeg always runs in "-optimize" mode, in +order to generate valid Huffman tables. This is necessary because our +default Huffman tables only cover 8-bit data. + +Removing code: + +If you need to make a smaller version of the JPEG software, some optional +functions can be removed at compile time. See the xxx_SUPPORTED #defines in +jconfig.h and jmorecfg.h. If at all possible, we recommend that you leave in +decoder support for all valid JPEG files, to ensure that you can read anyone's +output. Taking out support for image file formats that you don't use is the +most painless way to make the programs smaller. Another possibility is to +remove some of the DCT methods: in particular, the "IFAST" method may not be +enough faster than the others to be worth keeping on your machine. (If you +do remove ISLOW or IFAST, be sure to redefine JDCT_DEFAULT or JDCT_FASTEST +to a supported method, by adding a #define in jconfig.h.) + + +OPTIMIZATION +============ + +Unless you own a Cray, you'll probably be interested in making the JPEG +software go as fast as possible. This section covers some machine-dependent +optimizations you may want to try. We suggest that before trying any of +this, you first get the basic installation to pass the self-test step. +Repeat the self-test after any optimization to make sure that you haven't +broken anything. + +The integer DCT routines perform a lot of multiplications. These +multiplications must yield 32-bit results, but none of their input values +are more than 16 bits wide. On many machines, notably the 680x0 and 80x86 +CPUs, a 16x16=>32 bit multiply instruction is faster than a full 32x32=>32 +bit multiply. Unfortunately there is no portable way to specify such a +multiplication in C, but some compilers can generate one when you use the +right combination of casts. See the MULTIPLYxxx macro definitions in +jdct.h. If your compiler makes "int" be 32 bits and "short" be 16 bits, +defining SHORTxSHORT_32 is fairly likely to work. When experimenting with +alternate definitions, be sure to test not only whether the code still works +(use the self-test), but also whether it is actually faster --- on some +compilers, alternate definitions may compute the right answer, yet be slower +than the default. Timing cjpeg on a large PGM (grayscale) input file is the +best way to check this, as the DCT will be the largest fraction of the runtime +in that mode. (Note: some of the distributed compiler-specific jconfig files +already contain #define switches to select appropriate MULTIPLYxxx +definitions.) + +If your machine has sufficiently fast floating point hardware, you may find +that the float DCT method is faster than the integer DCT methods, even +after tweaking the integer multiply macros. In that case you may want to +make the float DCT be the default method. (The only objection to this is +that float DCT results may vary slightly across machines.) To do that, add +"#define JDCT_DEFAULT JDCT_FLOAT" to jconfig.h. Even if you don't change +the default, you should redefine JDCT_FASTEST, which is the method selected +by djpeg's -fast switch. Don't forget to update the documentation files +(usage.doc and/or cjpeg.1, djpeg.1) to agree with what you've done. + +If access to "short" arrays is slow on your machine, it may be a win to +define type JCOEF as int rather than short. This will cost a good deal of +memory though, particularly in some multi-pass modes, so don't do it unless +you have memory to burn and short is REALLY slow. + +If your compiler can compile function calls in-line, make sure the INLINE +macro in jmorecfg.h is defined as the keyword that marks a function +inline-able. Some compilers have a switch that tells the compiler to inline +any function it thinks is profitable (e.g., -finline-functions for gcc). +Enabling such a switch is likely to make the compiled code bigger but faster. + +In general, it's worth trying the maximum optimization level of your compiler, +and experimenting with any optional optimizations such as loop unrolling. +(Unfortunately, far too many compilers have optimizer bugs ... be prepared to +back off if the code fails self-test.) If you do any experimentation along +these lines, please report the optimal settings to jpeg-info@uunet.uu.net so +we can mention them in future releases. Be sure to specify your machine and +compiler version. + + +HINTS FOR SPECIFIC SYSTEMS +========================== + +We welcome reports on changes needed for systems not mentioned here. Submit +'em to jpeg-info@uunet.uu.net. Also, if configure or ckconfig.c is wrong +about how to configure the JPEG software for your system, please let us know. + + +Acorn RISC OS: + +(Thanks to Simon Middleton for these hints on compiling with Desktop C.) +After renaming the files according to Acorn conventions, take a copy of +makefile.ansi, change all occurrences of 'libjpeg.a' to 'libjpeg.o' and +change these definitions as indicated: + +CFLAGS= -throwback -IC: -Wn +LDLIBS=C:o.Stubs +SYSDEPMEM=jmemansi.o +LN=Link +AR=LibFile -c -o + +Also add a new line '.c.o:; $(cc) $< $(cflags) -c -o $@'. Remove the +lines '$(RM) libjpeg.o' and '$(AR2) libjpeg.o' and the 'jconfig.h' +dependency section. + +Copy jconfig.doc to jconfig.h. Edit jconfig.h to define TWO_FILE_COMMANDLINE +and CHAR_IS_UNSIGNED. + +Run the makefile using !AMU not !Make. If you want to use the 'clean' and +'test' makefile entries then you will have to fiddle with the syntax a bit +and rename the test files. + + +Amiga: + +SAS C 6.50 reportedly is too buggy to compile the IJG code properly. +A patch to update to 6.51 is available from SAS or AmiNet FTP sites. + +The supplied config files are set up to use jmemname.c as the memory +manager, with temporary files being created on the device named by +"JPEGTMP:". + + +Atari ST/STE/TT: + +Copy the project files makcjpeg.st, makdjpeg.st, maktjpeg.st, and makljpeg.st +to cjpeg.prj, djpeg.prj, jpegtran.prj, and libjpeg.prj respectively. The +project files should work as-is with Pure C. For Turbo C, change library +filenames "pc..." to "tc..." in each project file. Note that libjpeg.prj +selects jmemansi.c as the recommended memory manager. You'll probably want to +adjust the DEFAULT_MAX_MEM setting --- you want it to be a couple hundred K +less than your normal free memory. Put "#define DEFAULT_MAX_MEM nnnn" into +jconfig.h to do this. + +To use the 68881/68882 coprocessor for the floating point DCT, add the +compiler option "-8" to the project files and replace pcfltlib.lib with +pc881lib.lib in cjpeg.prj and djpeg.prj. Or if you don't have a +coprocessor, you may prefer to remove the float DCT code by undefining +DCT_FLOAT_SUPPORTED in jmorecfg.h (since without a coprocessor, the float +code will be too slow to be useful). In that case, you can delete +pcfltlib.lib from the project files. + +Note that you must make libjpeg.lib before making cjpeg.ttp, djpeg.ttp, +or jpegtran.ttp. You'll have to perform the self-test by hand. + +We haven't bothered to include project files for rdjpgcom and wrjpgcom. +Those source files should just be compiled by themselves; they don't +depend on the JPEG library. + +There is a bug in some older versions of the Turbo C library which causes the +space used by temporary files created with "tmpfile()" not to be freed after +an abnormal program exit. If you check your disk afterwards, you will find +cluster chains that are allocated but not used by a file. This should not +happen in cjpeg/djpeg/jpegtran, since we enable a signal catcher to explicitly +close temp files before exiting. But if you use the JPEG library with your +own code, be sure to supply a signal catcher, or else use a different +system-dependent memory manager. + + +Cray: + +Should you be so fortunate as to be running JPEG on a Cray YMP, there is a +compiler bug in old versions of Cray's Standard C (prior to 3.1). If you +still have an old compiler, you'll need to insert a line reading +"#pragma novector" just before the loop + for (i = 1; i <= (int) htbl->bits[l]; i++) + huffsize[p++] = (char) l; +in fix_huff_tbl (in V5beta1, line 204 of jchuff.c and line 176 of jdhuff.c). +[This bug may or may not still occur with the current IJG code, but it's +probably a dead issue anyway...] + + +HP-UX: + +If you have HP-UX 7.05 or later with the "software development" C compiler, +you should run the compiler in ANSI mode. If using the configure script, +say + ./configure CC='cc -Aa' +(or -Ae if you prefer). If configuring by hand, use makefile.ansi and add +"-Aa" to the CFLAGS line in the makefile. + +If you have a pre-7.05 system, or if you are using the non-ANSI C compiler +delivered with a minimum HP-UX system, then you must use makefile.unix +(and do NOT add -Aa); or just run configure without the CC option. + +On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior +to A.08.07. If you get complaints about "not a typedef name", you'll have to +use makefile.unix, or run configure without the CC option. + + +Macintosh, generic comments: + +The supplied user-interface files (cjpeg.c, djpeg.c, etc) are set up to +provide a Unix-style command line interface. You can use this interface on +the Mac by means of the ccommand() library routine provided by Metrowerks +CodeWarrior or Think C. This is only appropriate for testing the library, +however; to make a user-friendly equivalent of cjpeg/djpeg you'd really want +to develop a Mac-style user interface. There isn't a complete example +available at the moment, but there are some helpful starting points: +1. Sam Bushell's free "To JPEG" applet provides drag-and-drop conversion to +JPEG under System 7 and later. This only illustrates how to use the +compression half of the library, but it does a very nice job of that part. +The CodeWarrior source code is available from http://www.pobox.com/~jsam. +2. Jim Brunner prepared a Mac-style user interface for both compression and +decompression. Unfortunately, it hasn't been updated since IJG v4, and +the library's API has changed considerably since then. Still it may be of +some help, particularly as a guide to compiling the IJG code under Think C. +Jim's code is available from the Info-Mac archives, at sumex-aim.stanford.edu +or mirrors thereof; see file /info-mac/dev/src/jpeg-convert-c.hqx. + +jmemmac.c is the recommended memory manager back end for Macintosh. It uses +NewPtr/DisposePtr instead of malloc/free, and has a Mac-specific +implementation of jpeg_mem_available(). It also creates temporary files that +follow Mac conventions. (That part of the code relies on System-7-or-later OS +functions. See the comments in jmemmac.c if you need to run it on System 6.) +NOTE that USE_MAC_MEMMGR must be defined in jconfig.h to use jmemmac.c. + +You can also use jmemnobs.c, if you don't care about handling images larger +than available memory. If you use any memory manager back end other than +jmemmac.c, we recommend replacing "malloc" and "free" by "NewPtr" and +"DisposePtr", because Mac C libraries often have peculiar implementations of +malloc/free. (For instance, free() may not return the freed space to the +Mac Memory Manager. This is undesirable for the IJG code because jmemmgr.c +already clumps space requests.) + + +Macintosh, Metrowerks CodeWarrior: + +The Unix-command-line-style interface can be used by defining USE_CCOMMAND. +You'll also need to define TWO_FILE_COMMANDLINE to avoid stdin/stdout. +This means that when using the cjpeg/djpeg programs, you'll have to type the +input and output file names in the "Arguments" text-edit box, rather than +using the file radio buttons. (Perhaps USE_FDOPEN or USE_SETMODE would +eliminate the problem, but I haven't heard from anyone who's tried it.) + +On 680x0 Macs, Metrowerks defines type "double" as a 10-byte IEEE extended +float. jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power +of 2. Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint. + +The supplied configuration file jconfig.mac can be used for your jconfig.h; +it includes all the recommended symbol definitions. If you have AppleScript +installed, you can run the supplied script makeproj.mac to create CodeWarrior +project files for the library and the testbed applications, then build the +library and applications. (Thanks to Dan Sears and Don Agro for this nifty +hack, which saves us from trying to maintain CodeWarrior project files as part +of the IJG distribution...) + + +Macintosh, Think C: + +The documentation in Jim Brunner's "JPEG Convert" source code (see above) +includes detailed build instructions for Think C; it's probably somewhat +out of date for the current release, but may be helpful. + +If you want to build the minimal command line version, proceed as follows. +You'll have to prepare project files for the programs; we don't include any +in the distribution since they are not text files. Use the file lists in +any of the supplied makefiles as a guide. Also add the ANSI and Unix C +libraries in a separate segment. You may need to divide the JPEG files into +more than one segment; we recommend dividing compression and decompression +modules. Define USE_CCOMMAND in jconfig.h so that the ccommand() routine is +called. You must also define TWO_FILE_COMMANDLINE because stdin/stdout +don't handle binary data correctly. + +On 680x0 Macs, Think C defines type "double" as a 12-byte IEEE extended float. +jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power of 2. +Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint. + +jconfig.mac should work as a jconfig.h configuration file for Think C, +but the makeproj.mac AppleScript script is specific to CodeWarrior. Sorry. + + +MIPS R3000: + +MIPS's cc version 1.31 has a rather nasty optimization bug. Don't use -O +if you have that compiler version. (Use "cc -V" to check the version.) +Note that the R3000 chip is found in workstations from DEC and others. + + +MS-DOS, generic comments for 16-bit compilers: + +The IJG code is designed to work well in 80x86 "small" or "medium" memory +models (i.e., data pointers are 16 bits unless explicitly declared "far"; +code pointers can be either size). You may be able to use small model to +compile cjpeg or djpeg by itself, but you will probably have to use medium +model for any larger application. This won't make much difference in +performance. You *will* take a noticeable performance hit if you use a +large-data memory model, and you should avoid "huge" model if at all +possible. Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use +a small-data memory model; be sure it is NOT defined if you use a large-data +model. (The supplied makefiles and jconfig files for Borland and Microsoft C +compile in medium model and define NEED_FAR_POINTERS.) + +The DOS-specific memory manager, jmemdos.c, should be used if possible. +It needs some assembly-code routines which are in jmemdosa.asm; make sure +your makefile assembles that file and includes it in the library. If you +don't have a suitable assembler, you can get pre-assembled object files for +jmemdosa by FTP from ftp.uu.net:/graphics/jpeg/jdosaobj.zip. (DOS-oriented +distributions of the IJG source code often include these object files.) + +When using jmemdos.c, jconfig.h must define USE_MSDOS_MEMMGR and must set +MAX_ALLOC_CHUNK to less than 64K (65520L is a typical value). If your +C library's far-heap malloc() can't allocate blocks that large, reduce +MAX_ALLOC_CHUNK to whatever it can handle. + +If you can't use jmemdos.c for some reason --- for example, because you +don't have an assembler to assemble jmemdosa.asm --- you'll have to fall +back to jmemansi.c or jmemname.c. You'll probably still need to set +MAX_ALLOC_CHUNK in jconfig.h, because most DOS C libraries won't malloc() +more than 64K at a time. IMPORTANT: if you use jmemansi.c or jmemname.c, +you will have to compile in a large-data memory model in order to get the +right stdio library. Too bad. + +wrjpgcom needs to be compiled in large model, because it malloc()s a 64KB +work area to hold the comment text. If your C library's malloc can't +handle that, reduce MAX_COM_LENGTH as necessary in wrjpgcom.c. + +Most MS-DOS compilers treat stdin/stdout as text files, so you must use +two-file command line style. But if your compiler has either fdopen() or +setmode(), you can use one-file style if you like. To do this, define +USE_SETMODE or USE_FDOPEN so that stdin/stdout will be set to binary mode. +(USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You +should test that I/O through stdin/stdout produces the same results as I/O +to explicitly named files... the "make test" procedures in the supplied +makefiles do NOT use stdin/stdout. + + +MS-DOS, generic comments for 32-bit compilers: + +None of the above comments about memory models apply if you are using a +32-bit flat-memory-space environment, such as DJGPP or Watcom C. (And you +should use one if you have it, as performance will be much better than +8086-compatible code!) For flat-memory-space compilers, do NOT define +NEED_FAR_POINTERS, and do NOT use jmemdos.c. Use jmemnobs.c if the +environment supplies adequate virtual memory, otherwise use jmemansi.c or +jmemname.c. + +You'll still need to be careful about binary I/O through stdin/stdout. +See the last paragraph of the previous section. + + +MS-DOS, Borland C: + +Be sure to convert all the source files to DOS text format (CR/LF newlines). +Although Borland C will often work OK with unmodified Unix (LF newlines) +source files, sometimes it will give bogus compile errors. +"Illegal character '#'" is the most common such error. (This is true with +Borland C 3.1, but perhaps is fixed in newer releases.) + +If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. +jconfig.bcc already includes #define USE_SETMODE to make this work. +(fdopen does not work correctly.) + + +MS-DOS, Microsoft C: + +makefile.mc6 works with Microsoft C, DOS Visual C++, etc. It should only +be used if you want to build a 16-bit (small or medium memory model) program. + +If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. +jconfig.mc6 already includes #define USE_SETMODE to make this work. +(fdopen does not work correctly.) + +Note that this makefile assumes that the working copy of itself is called +"makefile". If you want to call it something else, say "makefile.mak", +be sure to adjust the dependency line that reads "$(RFILE) : makefile". +Otherwise the make will fail because it doesn't know how to create "makefile". +Worse, some releases of Microsoft's make utilities give an incorrect error +message in this situation. + +Old versions of MS C fail with an "out of macro expansion space" error +because they can't cope with the macro TRACEMS8 (defined in jerror.h). +If this happens to you, the easiest solution is to change TRACEMS8 to +expand to nothing. You'll lose the ability to dump out JPEG coefficient +tables with djpeg -debug -debug, but at least you can compile. + +Original MS C 6.0 is very buggy; it compiles incorrect code unless you turn +off optimization entirely (remove -O from CFLAGS). 6.00A is better, but it +still generates bad code if you enable loop optimizations (-Ol or -Ox). + +MS C 8.0 crashes when compiling jquant1.c with optimization switch /Oo ... +which is on by default. To work around this bug, compile that one file +with /Oo-. + + +Microsoft Windows (all versions), generic comments: + +Some Windows system include files define typedef boolean as "unsigned char". +The IJG code also defines typedef boolean, but we make it "int" by default. +This doesn't affect the IJG programs because we don't import those Windows +include files. But if you use the JPEG library in your own program, and some +of your program's files import one definition of boolean while some import the +other, you can get all sorts of mysterious problems. A good preventive step +is to make the IJG library use "unsigned char" for boolean. To do that, +add something like this to your jconfig.h file: + /* Define "boolean" as unsigned char, not int, per Windows custom */ + #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ + typedef unsigned char boolean; + #endif + #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +(This is already in jconfig.vc, by the way.) + +windef.h contains the declarations + #define far + #define FAR far +Since jmorecfg.h tries to define FAR as empty, you may get a compiler +warning if you include both jpeglib.h and windef.h (which windows.h +includes). To suppress the warning, you can put "#ifndef FAR"/"#endif" +around the line "#define FAR" in jmorecfg.h. + +When using the library in a Windows application, you will almost certainly +want to modify or replace the error handler module jerror.c, since our +default error handler does a couple of inappropriate things: + 1. it tries to write error and warning messages on stderr; + 2. in event of a fatal error, it exits by calling exit(). + +A simple stopgap solution for problem 1 is to replace the line + fprintf(stderr, "%s\n", buffer); +(in output_message in jerror.c) with + MessageBox(GetActiveWindow(),buffer,"JPEG Error",MB_OK|MB_ICONERROR); +It's highly recommended that you at least do that much, since otherwise +error messages will disappear into nowhere. (Beginning with IJG v6b, this +code is already present in jerror.c; just define USE_WINDOWS_MESSAGEBOX in +jconfig.h to enable it.) + +The proper solution for problem 2 is to return control to your calling +application after a library error. This can be done with the setjmp/longjmp +technique discussed in libjpeg.doc and illustrated in example.c. (NOTE: +some older Windows C compilers provide versions of setjmp/longjmp that +don't actually work under Windows. You may need to use the Windows system +functions Catch and Throw instead.) + +The recommended memory manager under Windows is jmemnobs.c; in other words, +let Windows do any virtual memory management needed. You should NOT use +jmemdos.c nor jmemdosa.asm under Windows. + +For Windows 3.1, we recommend compiling in medium or large memory model; +for newer Windows versions, use a 32-bit flat memory model. (See the MS-DOS +sections above for more info about memory models.) In the 16-bit memory +models only, you'll need to put + #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ +into jconfig.h to limit allocation chunks to 64Kb. (Without that, you'd +have to use huge memory model, which slows things down unnecessarily.) +jmemnobs.c works without modification in large or flat memory models, but to +use medium model, you need to modify its jpeg_get_large and jpeg_free_large +routines to allocate far memory. In any case, you might like to replace +its calls to malloc and free with direct calls on Windows memory allocation +functions. + +You may also want to modify jdatasrc.c and jdatadst.c to use Windows file +operations rather than fread/fwrite. This is only necessary if your C +compiler doesn't provide a competent implementation of C stdio functions. + +You might want to tweak the RGB_xxx macros in jmorecfg.h so that the library +will accept or deliver color pixels in BGR sample order, not RGB; BGR order +is usually more convenient under Windows. Note that this change will break +the sample applications cjpeg/djpeg, but the library itself works fine. + + +Many people want to convert the IJG library into a DLL. This is reasonably +straightforward, but watch out for the following: + + 1. Don't try to compile as a DLL in small or medium memory model; use +large model, or even better, 32-bit flat model. Many places in the IJG code +assume the address of a local variable is an ordinary (not FAR) pointer; +that isn't true in a medium-model DLL. + + 2. Microsoft C cannot pass file pointers between applications and DLLs. +(See Microsoft Knowledge Base, PSS ID Number Q50336.) So jdatasrc.c and +jdatadst.c don't work if you open a file in your application and then pass +the pointer to the DLL. One workaround is to make jdatasrc.c/jdatadst.c +part of your main application rather than part of the DLL. + + 3. You'll probably need to modify the macros GLOBAL() and EXTERN() to +attach suitable linkage keywords to the exported routine names. Similarly, +you'll want to modify METHODDEF() and JMETHOD() to ensure function pointers +are declared in a way that lets application routines be called back through +the function pointers. These macros are in jmorecfg.h. Typical definitions +for a 16-bit DLL are: + #define GLOBAL(type) type _far _pascal _loadds _export + #define EXTERN(type) extern type _far _pascal _loadds + #define METHODDEF(type) static type _far _pascal + #define JMETHOD(type,methodname,arglist) \ + type (_far _pascal *methodname) arglist +For a 32-bit DLL you may want something like + #define GLOBAL(type) __declspec(dllexport) type + #define EXTERN(type) extern __declspec(dllexport) type +Although not all the GLOBAL routines are actually intended to be called by +the application, the performance cost of making them all DLL entry points is +negligible. + +The unmodified IJG library presents a very C-specific application interface, +so the resulting DLL is only usable from C or C++ applications. There has +been some talk of writing wrapper code that would present a simpler interface +usable from other languages, such as Visual Basic. This is on our to-do list +but hasn't been very high priority --- any volunteers out there? + + +Microsoft Windows, Borland C: + +The provided jconfig.bcc should work OK in a 32-bit Windows environment, +but you'll need to tweak it in a 16-bit environment (you'd need to define +NEED_FAR_POINTERS and MAX_ALLOC_CHUNK). Beware that makefile.bcc will need +alteration if you want to use it for Windows --- in particular, you should +use jmemnobs.c not jmemdos.c under Windows. + +Borland C++ 4.5 fails with an internal compiler error when trying to compile +jdmerge.c in 32-bit mode. If enough people complain, perhaps Borland will fix +it. In the meantime, the simplest known workaround is to add a redundant +definition of the variable range_limit in h2v1_merged_upsample(), at the head +of the block that handles odd image width (about line 268 in v6 jdmerge.c): + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + register JSAMPLE * range_limit = cinfo->sample_range_limit; /* ADD THIS */ + cb = GETJSAMPLE(*inptr1); +Pretty bizarre, especially since the very similar routine h2v2_merged_upsample +doesn't trigger the bug. +Recent reports suggest that this bug does not occur with "bcc32a" (the +Pentium-optimized version of the compiler). + +Another report from a user of Borland C 4.5 was that incorrect code (leading +to a color shift in processed images) was produced if any of the following +optimization switch combinations were used: + -Ot -Og + -Ot -Op + -Ot -Om +So try backing off on optimization if you see such a problem. (Are there +several different releases all numbered "4.5"??) + + +Microsoft Windows, Microsoft Visual C++: + +jconfig.vc should work OK with any Microsoft compiler for a 32-bit memory +model. makefile.vc is intended for command-line use. (If you are using +the Developer Studio environment, you may prefer the DevStudio project +files; see below.) + +Some users feel that it's easier to call the library from C++ code if you +force VC++ to treat the library as C++ code, which you can do by renaming +all the *.c files to *.cpp (and adjusting the makefile to match). This +avoids the need to put extern "C" { ... } around #include "jpeglib.h" in +your C++ application. + + +Microsoft Windows, Microsoft Developer Studio: + +We include makefiles that should work as project files in DevStudio 4.2 or +later. There is a library makefile that builds the IJG library as a static +Win32 library, and an application makefile that builds the sample applications +as Win32 console applications. (Even if you only want the library, we +recommend building the applications so that you can run the self-test.) + +To use: +1. Copy jconfig.vc to jconfig.h, makelib.ds to jpeg.mak, and + makeapps.ds to apps.mak. (Note that the renaming is critical!) +2. Click on the .mak files to construct project workspaces. + (If you are using DevStudio more recent than 4.2, you'll probably + get a message saying that the makefiles are being updated.) +3. Build the library project, then the applications project. +4. Move the application .exe files from `app`\Release to an + appropriate location on your path. +5. To perform the self-test, execute the command line + NMAKE /f makefile.vc test + + +OS/2, Borland C++: + +Watch out for optimization bugs in older Borland compilers; you may need +to back off the optimization switch settings. See the comments in +makefile.bcc. + + +SGI: + +On some SGI systems, you may need to set "AR2= ar -ts" in the Makefile. +If you are using configure, you can do this by saying + ./configure RANLIB='ar -ts' +This change is not needed on all SGIs. Use it only if the make fails at the +stage of linking the completed programs. + +On the MIPS R4000 architecture (Indy, etc.), the compiler option "-mips2" +reportedly speeds up the float DCT method substantially, enough to make it +faster than the default int method (but still slower than the fast int +method). If you use -mips2, you may want to alter the default DCT method to +be float. To do this, put "#define JDCT_DEFAULT JDCT_FLOAT" in jconfig.h. + + +VMS: + +On an Alpha/VMS system with MMS, be sure to use the "/Marco=Alpha=1" +qualifier with MMS when building the JPEG package. + +VAX/VMS v5.5-1 may have problems with the test step of the build procedure +reporting differences when it compares the original and test images. If the +error points to the last block of the files, it is most likely bogus and may +be safely ignored. It seems to be because the files are Stream_LF and +Backup/Compare has difficulty with the (presumably) null padded files. +This problem was not observed on VAX/VMS v6.1 or AXP/VMS v6.1. diff --git a/Utilities/vtkjpeg/jcapimin.c b/Utilities/vtkjpeg/jcapimin.c new file mode 100644 index 0000000..54fb8c5 --- /dev/null +++ b/Utilities/vtkjpeg/jcapimin.c @@ -0,0 +1,280 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-compression case or the transcoding-only + * case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jcapistd.c. But also see jcparam.c for + * parameter-setup helper routines, jcomapi.c for routines shared by + * compression and decompression, and jctrans.c for the transcoding case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG compression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_compress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = FALSE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->dest = NULL; + + cinfo->comp_info = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + cinfo->script_space = NULL; + + cinfo->input_gamma = 1.0; /* in case application forgets */ + + /* OK, I'm ready */ + cinfo->global_state = CSTATE_START; +} + + +/* + * Destruction of a JPEG compression object + */ + +GLOBAL(void) +jpeg_destroy_compress (j_compress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG compression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_compress (j_compress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Forcibly suppress or un-suppress all quantization and Huffman tables. + * Marks all currently defined tables as already written (if suppress) + * or not written (if !suppress). This will control whether they get emitted + * by a subsequent jpeg_start_compress call. + * + * This routine is exported for use by applications that want to produce + * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + * since it is called by jpeg_start_compress, we put it here --- otherwise + * jcparam.o would be linked whether the application used it or not. + */ + +GLOBAL(void) +jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) +{ + int i; + JQUANT_TBL * qtbl; + JHUFF_TBL * htbl; + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) + qtbl->sent_table = suppress; + } + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) + htbl->sent_table = suppress; + } +} + + +/* + * Finish JPEG compression. + * + * If a multipass operating mode was selected, this may do a great deal of + * work including most of the actual output. + */ + +GLOBAL(void) +jpeg_finish_compress (j_compress_ptr cinfo) +{ + JDIMENSION iMCU_row; + + if (cinfo->global_state == CSTATE_SCANNING || + cinfo->global_state == CSTATE_RAW_OK) { + /* Terminate first pass */ + if (cinfo->next_scanline < cinfo->image_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_pass) (cinfo); + } else if (cinfo->global_state != CSTATE_WRCOEFS) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any remaining passes */ + while (! cinfo->master->is_last_pass) { + (*cinfo->master->prepare_for_pass) (cinfo); + for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* We bypass the main controller and invoke coef controller directly; + * all work is being done from the coefficient buffer. + */ + if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } + (*cinfo->master->finish_pass) (cinfo); + } + /* Write EOI, do final cleanup */ + (*cinfo->marker->write_file_trailer) (cinfo); + (*cinfo->dest->term_destination) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); +} + + +/* + * Write a special marker. + * This is only recommended for writing COM or APPn markers. + * Must be called after jpeg_start_compress() and before + * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). + */ + +GLOBAL(void) +jpeg_write_marker (j_compress_ptr cinfo, int marker, + const JOCTET *dataptr, unsigned int datalen) +{ + JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); + + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); + write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */ + while (datalen--) { + (*write_marker_byte) (cinfo, *dataptr); + dataptr++; + } +} + +/* Same, but piecemeal. */ + +GLOBAL(void) +jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +{ + if (cinfo->next_scanline != 0 || + (cinfo->global_state != CSTATE_SCANNING && + cinfo->global_state != CSTATE_RAW_OK && + cinfo->global_state != CSTATE_WRCOEFS)) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); +} + +GLOBAL(void) +jpeg_write_m_byte (j_compress_ptr cinfo, int val) +{ + (*cinfo->marker->write_marker_byte) (cinfo, val); +} + + +/* + * Alternate compression function: just write an abbreviated table file. + * Before calling this, all parameters and a data destination must be set up. + * + * To produce a pair of files containing abbreviated tables and abbreviated + * image data, one would proceed as follows: + * + * initialize JPEG object + * set JPEG parameters + * set destination to table file + * jpeg_write_tables(cinfo); + * set destination to image file + * jpeg_start_compress(cinfo, FALSE); + * write data... + * jpeg_finish_compress(cinfo); + * + * jpeg_write_tables has the side effect of marking all tables written + * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + * will not re-emit the tables unless it is passed write_all_tables=TRUE. + */ + +GLOBAL(void) +jpeg_write_tables (j_compress_ptr cinfo) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Initialize the marker writer ... bit of a crock to do it here. */ + jinit_marker_writer(cinfo); + /* Write them tables! */ + (*cinfo->marker->write_tables_only) (cinfo); + /* And clean up. */ + (*cinfo->dest->term_destination) (cinfo); + /* + * In library releases up through v6a, we called jpeg_abort() here to free + * any working memory allocated by the destination manager and marker + * writer. Some applications had a problem with that: they allocated space + * of their own from the library memory manager, and didn't want it to go + * away during write_tables. So now we do nothing. This will cause a + * memory leak if an app calls write_tables repeatedly without doing a full + * compression cycle or otherwise resetting the JPEG object. However, that + * seems less bad than unexpectedly freeing memory in the normal case. + * An app that prefers the old behavior can call jpeg_abort for itself after + * each call to jpeg_write_tables(). + */ +} diff --git a/Utilities/vtkjpeg/jcapistd.c b/Utilities/vtkjpeg/jcapistd.c new file mode 100644 index 0000000..c0320b1 --- /dev/null +++ b/Utilities/vtkjpeg/jcapistd.c @@ -0,0 +1,161 @@ +/* + * jcapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the compression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-compression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_compress, it will end up linking in the entire compressor. + * We thus must separate this file from jcapimin.c to avoid linking the + * whole compression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Compression initialization. + * Before calling this, all parameters and a data destination must be set up. + * + * We require a write_all_tables parameter as a failsafe check when writing + * multiple datastreams from the same compression object. Since prior runs + * will have left all the tables marked sent_table=TRUE, a subsequent run + * would emit an abbreviated stream (no tables) by default. This may be what + * is wanted, but for safety's sake it should not be the default behavior: + * programmers should have to make a deliberate choice to emit abbreviated + * images. Therefore the documentation and examples should encourage people + * to pass write_all_tables=TRUE; then it will take active thought to do the + * wrong thing. + */ + +GLOBAL(void) +jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (write_all_tables) + jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ + + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + jinit_compress_master(cinfo); + /* Set up for the first pass */ + (*cinfo->master->prepare_for_pass) (cinfo); + /* Ready for application to drive first pass through jpeg_write_scanlines + * or jpeg_write_raw_data. + */ + cinfo->next_scanline = 0; + cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); +} + + +/* + * Write some scanlines of data to the JPEG compressor. + * + * The return value will be the number of lines actually written. + * This should be less than the supplied num_lines only in case that + * the data destination module has requested suspension of the compressor, + * or if more than image_height scanlines are passed in. + * + * Note: we warn about excess calls to jpeg_write_scanlines() since + * this likely signals an application programmer error. However, + * excess scanlines passed in the last valid call are *silently* ignored, + * so that the application need not adjust num_lines for end-of-image + * when using a multiple-scanline buffer. + */ + +GLOBAL(JDIMENSION) +jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION num_lines) +{ + JDIMENSION row_ctr, rows_left; + + if (cinfo->global_state != CSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_scanlines. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_scanlines. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Ignore any extra scanlines at bottom of image. */ + rows_left = cinfo->image_height - cinfo->next_scanline; + if (num_lines > rows_left) + num_lines = rows_left; + + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); + cinfo->next_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to write raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION num_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != CSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->next_scanline >= cinfo->image_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->next_scanline; + cinfo->progress->pass_limit = (long) cinfo->image_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Give master control module another chance if this is first call to + * jpeg_write_raw_data. This lets output of the frame/scan headers be + * delayed so that application can write COM, etc, markers between + * jpeg_start_compress and jpeg_write_raw_data. + */ + if (cinfo->master->call_pass_startup) + (*cinfo->master->pass_startup) (cinfo); + + /* Verify that at least one iMCU row has been passed. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; + if (num_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Directly compress the row. */ + if (! (*cinfo->coef->compress_data) (cinfo, data)) { + /* If compressor did not consume the whole row, suspend processing. */ + return 0; + } + + /* OK, we processed one iMCU row. */ + cinfo->next_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} diff --git a/Utilities/vtkjpeg/jccoefct.c b/Utilities/vtkjpeg/jccoefct.c new file mode 100644 index 0000000..6077b67 --- /dev/null +++ b/Utilities/vtkjpeg/jccoefct.c @@ -0,0 +1,450 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for compression. + * This controller is the top level of the JPEG compressor proper. + * The coefficient buffer lies between forward-DCT and entropy encoding steps. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* We use a full-image coefficient buffer when doing Huffman optimization, + * and also for writing multiple-scan JPEG files. In all cases, the DCT + * step is run during the first pass, and subsequent passes need only read + * the buffered coefficients. + */ +#ifdef ENTROPY_OPT_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#else +#ifdef C_MULTISCAN_FILES_SUPPORTED +#define FULL_COEF_BUFFER_SUPPORTED +#endif +#endif + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* For single-pass compression, it's sufficient to buffer just one MCU + * (although this may prove a bit slow in practice). We allocate a + * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each + * MCU constructed and sent. (On 80x86, the workspace is FAR even though + * it's not really very big; this is to keep the module interfaces unchanged + * when a large coefficient buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays. + */ + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +/* Forward declarations */ +METHODDEF(boolean) compress_data + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#ifdef FULL_COEF_BUFFER_SUPPORTED +METHODDEF(boolean) compress_first_pass + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +METHODDEF(boolean) compress_output + JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (coef->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_data; + break; +#ifdef FULL_COEF_BUFFER_SUPPORTED + case JBUF_SAVE_AND_PASS: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_first_pass; + break; + case JBUF_CRANK_DEST: + if (coef->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + coef->pub.compress_data = compress_output; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data in the single-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(boolean) +compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, bi, ci, yindex, yoffset, blockcnt; + JDIMENSION ypos, xpos; + jpeg_component_info *compptr; + + /* Loop to write as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Determine where data comes from in input_buf and do the DCT thing. + * Each call on forward_DCT processes a horizontal row of DCT blocks + * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + * sequentially. Dummy blocks at the right or bottom edge are filled in + * specially. The data in them does not matter for image reconstruction, + * so we fill them with values that will encode to the smallest amount of + * data, viz: all zeroes in the AC entries, DC entries equal to previous + * block's DC value. (Thanks to Thomas Kinsman for this idea.) + */ + blkn = 0; + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * compptr->MCU_sample_width; + ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + jzero_far((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += DCTSIZE; + } + } + /* Try to write the MCU. In event of a suspension failure, we will + * re-DCT the MCU on restart (a bit inefficient, could be fixed...) + */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +#ifdef FULL_COEF_BUFFER_SUPPORTED + +/* + * Process some data in the first pass of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the image. + * This amount of data is read from the source buffer, DCT'd and quantized, + * and saved into the virtual arrays. We also generate suitable dummy blocks + * as needed at the right and lower edges. (The dummy blocks are constructed + * in the virtual arrays, which have been padded appropriately.) This makes + * it possible for subsequent passes not to worry about real vs. dummy blocks. + * + * We must also emit the data to the entropy encoder. This is conveniently + * done by calling compress_output() after we've loaded the current strip + * of the virtual arrays. + * + * NB: input_buf contains a plane for each component in image. All + * components are DCT'd and loaded into the virtual arrays in this pass. + * However, it may be that only a subset of the components are emitted to + * the entropy encoder during this first pass; be careful about looking + * at the scan-dependent variables (MCU dimensions, etc). + */ + +METHODDEF(boolean) +compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION blocks_across, MCUs_across, MCUindex; + int bi, ci, h_samp_factor, block_row, block_rows, ndummy; + JCOEF lastDC; + jpeg_component_info *compptr; + JBLOCKARRAY buffer; + JBLOCKROW thisblockrow, lastblockrow; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (coef->iMCU_row_num < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here, since may not be set! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + blocks_across = compptr->width_in_blocks; + h_samp_factor = compptr->h_samp_factor; + /* Count number of dummy blocks to be added at the right margin. */ + ndummy = (int) (blocks_across % h_samp_factor); + if (ndummy > 0) + ndummy = h_samp_factor - ndummy; + /* Perform DCT for all non-dummy blocks in this iMCU row. Each call + * on forward_DCT processes a complete horizontal row of DCT blocks. + */ + for (block_row = 0; block_row < block_rows; block_row++) { + thisblockrow = buffer[block_row]; + (*cinfo->fdct->forward_DCT) (cinfo, compptr, + input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * DCTSIZE), + (JDIMENSION) 0, blocks_across); + if (ndummy > 0) { + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } + } + } + /* If at end of image, create dummy block rows as needed. + * The tricky part here is that within each MCU, we want the DC values + * of the dummy blocks to match the last real block's DC value. + * This squeezes a few more bytes out of the resulting file... + */ + if (coef->iMCU_row_num == last_iMCU_row) { + blocks_across += ndummy; /* include lower right corner */ + MCUs_across = blocks_across / h_samp_factor; + for (block_row = block_rows; block_row < compptr->v_samp_factor; + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + jzero_far((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } + } + } + } + /* NB: compress_output will increment iMCU_row_num if successful. + * A suspension return will result in redoing all the work above next time. + */ + + /* Emit data to the entropy encoder, sharing code with subsequent passes */ + return compress_output(cinfo, input_buf); +} + + +/* + * Process some data in subsequent passes of a multi-pass case. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + input_buf = 0; + /* Align the virtual buffers for the components used in this scan. + * NB: during first pass, this is safe only because the buffers will + * already be aligned properly, so jmemmgr.c won't need to do any I/O. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + +#endif /* FULL_COEF_BUFFER_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef FULL_COEF_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + int ci; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->whole_image[0] = NULL; /* flag for no virtual arrays */ + } +} diff --git a/Utilities/vtkjpeg/jccolor.c b/Utilities/vtkjpeg/jccolor.c new file mode 100644 index 0000000..ee87aab --- /dev/null +++ b/Utilities/vtkjpeg/jccolor.c @@ -0,0 +1,460 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_converter pub; /* public fields */ + + /* Private state for RGB->YCC conversion */ + INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ +} my_color_converter; + +typedef my_color_converter * my_cconvert_ptr; + + +/**************** RGB -> YCbCr conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + * were not represented exactly. Now we sacrifice exact representation of + * maximum red and maximum blue in order to get exact grayscales. + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times R,G,B for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + * in the tables to save adding them separately in the inner loop. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) + +/* We allocate one big table and divide it up into eight parts, instead of + * doing eight alloc_small requests. This lets us use a single table base + * address, which can be held in a register in the inner loops on many + * machines (more than can hold all eight addresses, anyway). + */ + +#define R_Y_OFF 0 /* offset to R => Y section */ +#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ +#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ +#define R_CB_OFF (3*(MAXJSAMPLE+1)) +#define G_CB_OFF (4*(MAXJSAMPLE+1)) +#define B_CB_OFF (5*(MAXJSAMPLE+1)) +#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ +#define G_CR_OFF (6*(MAXJSAMPLE+1)) +#define B_CR_OFF (7*(MAXJSAMPLE+1)) +#define TABLE_SIZE (8*(MAXJSAMPLE+1)) + + +/* + * Initialize for RGB->YCC colorspace conversion. + */ + +METHODDEF(void) +rgb_ycc_start (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + INT32 * rgb_ycc_tab; + INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + * This ensures that the maximum output will round to MAXJSAMPLE + * not MAXJSAMPLE+1, and thus that we don't have to range-limit. + */ + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +/* B=>Cb and R=>Cr tables are the same + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; +*/ + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * + * Note that we change from the application's interleaved-pixel format + * to our internal noninterleaved, one-plane-per-component format. + * The input buffer is therefore three times as wide as the output buffer. + * + * A starting row offset is provided only for the output buffer. The caller + * can easily adjust the passed input_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +rgb_ycc_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/**************** Cases other than RGB -> YCbCr **************/ + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles RGB->grayscale conversion, which is the same + * as the RGB->Y portion of RGB->YCbCr. + * We assume rgb_ycc_start has been called (we only use the Y tables). + */ + +METHODDEF(void) +rgb_gray_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = GETJSAMPLE(inptr[RGB_RED]); + g = GETJSAMPLE(inptr[RGB_GREEN]); + b = GETJSAMPLE(inptr[RGB_BLUE]); + inptr += RGB_PIXELSIZE; + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles Adobe-style CMYK->YCCK conversion, + * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + * conversion as above, while passing K (black) unchanged. + * We assume rgb_ycc_start has been called. + */ + +METHODDEF(void) +cmyk_ycck_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int r, g, b; + register INT32 * ctab = cconvert->rgb_ycc_tab; + register JSAMPROW inptr; + register JSAMPROW outptr0, outptr1, outptr2, outptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr0 = output_buf[0][output_row]; + outptr1 = output_buf[1][output_row]; + outptr2 = output_buf[2][output_row]; + outptr3 = output_buf[3][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); + g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); + b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); + /* K passes through as-is */ + outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ + inptr += 4; + /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations + * must be too; we do not need an explicit range-limiting operation. + * Hence the value being shifted is never negative, and we don't + * need the general RIGHT_SHIFT macro. + */ + /* Y */ + outptr0[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + /* Cb */ + outptr1[col] = (JSAMPLE) + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); + /* Cr */ + outptr2[col] = (JSAMPLE) + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles grayscale output with no conversion. + * The source can be either plain grayscale or YCbCr (since Y == gray). + */ + +METHODDEF(void) +grayscale_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->image_width; + int instride = cinfo->input_components; + + while (--num_rows >= 0) { + inptr = *input_buf++; + outptr = output_buf[0][output_row]; + output_row++; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ + inptr += instride; + } + } +} + + +/* + * Convert some rows of samples to the JPEG colorspace. + * This version handles multi-component colorspaces without conversion. + * We assume input_components == num_components. + */ + +METHODDEF(void) +null_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + register JSAMPROW inptr; + register JSAMPROW outptr; + register JDIMENSION col; + register int ci; + int nc = cinfo->num_components; + JDIMENSION num_cols = cinfo->image_width; + + while (--num_rows >= 0) { + /* It seems fastest to make a separate pass for each component. */ + for (ci = 0; ci < nc; ci++) { + inptr = *input_buf; + outptr = output_buf[ci][output_row]; + for (col = 0; col < num_cols; col++) { + outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ + inptr += nc; + } + } + input_buf++; + output_row++; + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +null_method (j_compress_ptr cinfo) +{ + cinfo = 0; + /* no work needed */ +} + + +/* + * Module initialization routine for input colorspace conversion. + */ + +GLOBAL(void) +jinit_color_converter (j_compress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_converter)); + cinfo->cconvert = (struct jpeg_color_converter *) cconvert; + /* set start_pass to null method until we find out differently */ + cconvert->pub.start_pass = null_method; + + /* Make sure input_components agrees with in_color_space */ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + if (cinfo->input_components != 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + if (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; +#endif /* else share code with YCbCr */ + + case JCS_YCbCr: + if (cinfo->input_components != 3) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->input_components != 4) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->input_components < 1) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + } + + /* Check num_components, set conversion method based on requested space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_GRAYSCALE) + cconvert->pub.color_convert = grayscale_convert; + else if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_gray_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = grayscale_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_RGB) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + } else if (cinfo->in_color_space == JCS_YCbCr) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + if (cinfo->in_color_space == JCS_CMYK) { + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = cmyk_ycck_convert; + } else if (cinfo->in_color_space == JCS_YCCK) + cconvert->pub.color_convert = null_convert; + else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: /* allow null conversion of JCS_UNKNOWN */ + if (cinfo->jpeg_color_space != cinfo->in_color_space || + cinfo->num_components != cinfo->input_components) + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + cconvert->pub.color_convert = null_convert; + break; + } +} diff --git a/Utilities/vtkjpeg/jcdctmgr.c b/Utilities/vtkjpeg/jcdctmgr.c new file mode 100644 index 0000000..61fa79b --- /dev/null +++ b/Utilities/vtkjpeg/jcdctmgr.c @@ -0,0 +1,387 @@ +/* + * jcdctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the forward-DCT management logic. + * This code selects a particular DCT implementation to be used, + * and it performs related housekeeping chores including coefficient + * quantization. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_forward_dct pub; /* public fields */ + + /* Pointer to the DCT routine actually in use */ + forward_DCT_method_ptr do_dct; + + /* The actual post-DCT divisors --- not identical to the quant table + * entries, because of scaling (especially for an unnormalized DCT). + * Each table is given in normal array order. + */ + DCTELEM * divisors[NUM_QUANT_TBLS]; + +#ifdef DCT_FLOAT_SUPPORTED + /* Same as above for the floating-point case. */ + float_DCT_method_ptr do_float_dct; + FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; +#endif +} my_fdct_controller; + +typedef my_fdct_controller * my_fdct_ptr; + + +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + int ci, qtblno, i; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Perform forward DCT on one or more blocks of a component. + * + * The input samples are taken from the sample_data[] array starting at + * position start_row/start_col, and moving to the right for any additional + * blocks. The quantized coefficients are returned in coef_blocks[]. + */ + +METHODDEF(void) +forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for integer DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + forward_DCT_method_ptr do_dct = fdct->do_dct; + DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register DCTELEM *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register DCTELEM temp, qval; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ +#ifdef FAST_DIVIDE +#define DIVIDE_BY(a,b) a /= b +#else +#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 +#endif + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; + } + } + } +} + + +#ifdef DCT_FLOAT_SUPPORTED + +METHODDEF(void) +forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) +/* This version is used for floating-point DCT implementations. */ +{ + /* This routine is heavily used, so it's worth coding it tightly. */ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + float_DCT_method_ptr do_dct = fdct->do_float_dct; + FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ + JDIMENSION bi; + + sample_data += start_row; /* fold in the vertical offset once */ + + for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { + /* Load data into workspace, applying unsigned->signed conversion */ + { register FAST_FLOAT *workspaceptr; + register JSAMPROW elemptr; + register int elemr; + + workspaceptr = workspace; + for (elemr = 0; elemr < DCTSIZE; elemr++) { + elemptr = sample_data[elemr] + start_col; +#if DCTSIZE == 8 /* unroll the inner loop */ + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); +#else + { register int elemc; + for (elemc = DCTSIZE; elemc > 0; elemc--) { + *workspaceptr++ = (FAST_FLOAT) + (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); + } + } +#endif + } + } + + /* Perform the DCT */ + (*do_dct) (workspace); + + /* Quantize/descale the coefficients, and store into coef_blocks[] */ + { register FAST_FLOAT temp; + register int i; + register JCOEFPTR output_ptr = coef_blocks[bi]; + + for (i = 0; i < DCTSIZE2; i++) { + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + } + } + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ + + +/* + * Initialize FDCT manager. + */ + +GLOBAL(void) +jinit_forward_dct (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct; + int i; + + fdct = (my_fdct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_fdct_controller)); + cinfo->fdct = (struct jpeg_forward_dct *) fdct; + fdct->pub.start_pass = start_pass_fdctmgr; + + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_islow; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + fdct->pub.forward_DCT = forward_DCT; + fdct->do_dct = jpeg_fdct_ifast; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + fdct->pub.forward_DCT = forward_DCT_float; + fdct->do_float_dct = jpeg_fdct_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + + /* Mark divisor tables unallocated */ + for (i = 0; i < NUM_QUANT_TBLS; i++) { + fdct->divisors[i] = NULL; +#ifdef DCT_FLOAT_SUPPORTED + fdct->float_divisors[i] = NULL; +#endif + } +} diff --git a/Utilities/vtkjpeg/jchuff.c b/Utilities/vtkjpeg/jchuff.c new file mode 100644 index 0000000..f235250 --- /dev/null +++ b/Utilities/vtkjpeg/jchuff.c @@ -0,0 +1,909 @@ +/* + * jchuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines. + * + * Much of the complexity here has to do with supporting output suspension. + * If the data destination module demands suspension, we want to be able to + * back up to the start of the current MCU. To do this, we copy state + * variables into local working storage, and update them back to the + * permanent JPEG objects only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jcphuff.c */ + + +/* Expanded entropy encoder object for Huffman encoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + savable_state saved; /* Bit buffer & DC state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + +#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + long * dc_count_ptrs[NUM_HUFF_TBLS]; + long * ac_count_ptrs[NUM_HUFF_TBLS]; +#endif +} huff_entropy_encoder; + +typedef huff_entropy_encoder * huff_entropy_ptr; + +/* Working state while writing an MCU. + * This struct contains all the fields that are needed by subroutines. + */ + +typedef struct { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + savable_state cur; /* Current bit buffer & DC state */ + j_compress_ptr cinfo; /* dump_buffer needs access to this */ +} working_state; + + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); +#ifdef ENTROPY_OPT_SUPPORTED +METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); +#endif + + +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + entropy->pub.encode_mcu = encode_mcu_gather; + entropy->pub.finish_pass = finish_pass_gather; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + entropy->pub.encode_mcu = encode_mcu_huff; + entropy->pub.finish_pass = finish_pass_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (gather_statistics) { +#ifdef ENTROPY_OPT_SUPPORTED + /* Check for invalid table indexes */ + /* (make_c_derived_tbl does this in the other path) */ + if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0 || actbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[dctbl] == NULL) + entropy->dc_count_ptrs[dctbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy->ac_count_ptrs[actbl] == NULL) + entropy->ac_count_ptrs[actbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); +#endif + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jcphuff.c. + */ + +GLOBAL(void) +jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + c_derived_tbl *dtbl; + int p, i, l, lastp, si, maxsymbol; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (c_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(c_derived_tbl)); + dtbl = *pdtbl; + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + lastp = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure C.3: generate encoding tables */ + /* These are code and size indexed by symbol value */ + + /* Set all codeless symbols to have code length 0; + * this lets us detect duplicate VAL entries here, and later + * allows emit_bits to detect any attempt to emit such symbols. + */ + MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); + + /* This is also a convenient place to check for out-of-range + * and duplicated VAL entries. We allow 0..255 for AC symbols + * but only 0..15 for DC. (We could constrain them further + * based on data depth and mode, but this seems enough.) + */ + maxsymbol = isDC ? 15 : 255; + + for (p = 0; p < lastp; p++) { + i = htbl->huffval[p]; + if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + dtbl->ehufco[i] = huffcode[p]; + dtbl->ehufsi[i] = huffsize[p]; + } +} + + +/* Outputting bytes to the file */ + +/* Emit a byte, taking 'action' if must suspend. */ +#define emit_byte(state,val,action) \ + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer(state)) \ + { action; } } + + +LOCAL(boolean) +dump_buffer (working_state * state) +/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ +{ + struct jpeg_destination_mgr * dest = state->cinfo->dest; + + if (! (*dest->empty_output_buffer) (state->cinfo)) + return FALSE; + /* After a successful buffer dump, must reset buffer pointers */ + state->next_output_byte = dest->next_output_byte; + state->free_in_buffer = dest->free_in_buffer; + return TRUE; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(boolean) +emit_bits (working_state * state, unsigned int code, int size) +/* Emit some bits; return TRUE if successful, FALSE if must suspend */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = state->cur.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); + + put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */ + + put_bits += size; /* new number of bits in buffer */ + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(state, c, return FALSE); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(state, 0, return FALSE); + } + put_buffer <<= 8; + put_bits -= 8; + } + + state->cur.put_buffer = put_buffer; /* update state variables */ + state->cur.put_bits = put_bits; + + return TRUE; +} + + +LOCAL(boolean) +flush_bits (working_state * state) +{ + if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + return FALSE; + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_bits = 0; + return TRUE; +} + + +/* Encode a single block's worth of coefficients */ + +LOCAL(boolean) +encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, + c_derived_tbl *dctbl, c_derived_tbl *actbl) +{ + register int temp, temp2; + register int nbits; + register int k, r, i; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = temp2 = block[0] - last_dc_val; + + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit the Huffman-coded symbol for the number of bits */ + if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; + } + + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + + /* Emit Huffman symbol for run length / number of bits */ + i = (r << 4) + nbits; + if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + return FALSE; + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (! emit_bits(state, (unsigned int) temp2, nbits)) + return FALSE; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + return FALSE; + + return TRUE; +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits(state)) + return FALSE; + + emit_byte(state, 0xFF, return FALSE); + emit_byte(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of Huffman-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + int blkn, ci; + jpeg_component_info * compptr; + + /* Load up working state */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! emit_restart(&state, entropy->next_restart_num)) + return FALSE; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + if (! encode_one_block(&state, + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) + return FALSE; + /* Update last_dc_val */ + state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + /* Completed MCU, so update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + working_state state; + + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); +} + + +/* + * Huffman coding optimization. + * + * We first scan the supplied data and count the number of uses of each symbol + * that is to be Huffman-coded. (This process MUST agree with the code above.) + * Then we build a Huffman coding tree for the observed counts. + * Symbols which are not needed at all for the particular image are not + * assigned any code, which saves space in the DHT marker as well as in + * the compressed data. + */ + +#ifdef ENTROPY_OPT_SUPPORTED + + +/* Process a single block's worth of coefficients */ + +LOCAL(void) +htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, + long dc_counts[], long ac_counts[]) +{ + register int temp; + register int nbits; + register int k, r; + + /* Encode the DC coefficient difference per section F.1.2.1 */ + + temp = block[0] - last_dc_val; + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count the Huffman symbol for the number of bits */ + dc_counts[nbits]++; + + /* Encode the AC coefficients per section F.1.2.2 */ + + r = 0; /* r = run length of zeros */ + + for (k = 1; k < DCTSIZE2; k++) { + if ((temp = block[jpeg_natural_order[k]]) == 0) { + r++; + } else { + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + ac_counts[0xF0]++; + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + if (temp < 0) + temp = -temp; + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count Huffman symbol for run length / number of bits */ + ac_counts[(r << 4) + nbits]++; + + r = 0; + } + } + + /* If the last coef(s) were zero, emit an end-of-block code */ + if (r > 0) + ac_counts[0]++; +} + + +/* + * Trial-encode one MCU's worth of Huffman-compressed coefficients. + * No data is actually output, so no suspension return is possible. + */ + +METHODDEF(boolean) +encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn, ci; + jpeg_component_info * compptr; + + /* Take care of restart intervals if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Update restart state */ + entropy->restarts_to_go = cinfo->restart_interval; + } + entropy->restarts_to_go--; + } + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; + } + + return TRUE; +} + + +/* + * Generate the best Huffman code table for the given counts, fill htbl. + * Note this is also used by jcphuff.c. + * + * The JPEG standard requires that no symbol be assigned a codeword of all + * one bits (so that padding bits added at the end of a compressed segment + * can't look like a valid code). Because of the canonical ordering of + * codewords, this just means that there must be an unused slot in the + * longest codeword length category. Section K.2 of the JPEG spec suggests + * reserving such a slot by pretending that symbol 256 is a valid symbol + * with count 1. In theory that's not optimal; giving it count zero but + * including it in the symbol set anyway should give a better Huffman code. + * But the theoretically better code actually seems to come out worse in + * practice, because it produces more all-ones bytes (which incur stuffed + * zero bytes in the final file). In any case the difference is tiny. + * + * The JPEG standard requires Huffman codes to be no more than 16 bits long. + * If some symbols have a very small but nonzero probability, the Huffman tree + * must be adjusted to meet the code length restriction. We currently use + * the adjustment method suggested in JPEG section K.2. This method is *not* + * optimal; it may not choose the best possible limited-length code. But + * typically only very-low-frequency symbols will be given less-than-optimal + * lengths, so the code is almost optimal. Experimental comparisons against + * an optimal limited-length-code algorithm indicate that the difference is + * microscopic --- usually less than a hundredth of a percent of total size. + * So the extra complexity of an optimal algorithm doesn't seem worthwhile. + */ + +GLOBAL(void) +jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) +{ +#define MAX_CLEN 32 /* assumed maximum initial code length */ + UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ + int codesize[257]; /* codesize[k] = code length of symbol k */ + int others[257]; /* next symbol in current branch of tree */ + int c1, c2; + int p, i, j; + long v; + + /* This algorithm is explained in section K.2 of the JPEG standard */ + + MEMZERO(bits, SIZEOF(bits)); + MEMZERO(codesize, SIZEOF(codesize)); + for (i = 0; i < 257; i++) + others[i] = -1; /* init links to empty */ + + freq[256] = 1; /* make sure 256 has a nonzero count */ + /* Including the pseudo-symbol 256 in the Huffman procedure guarantees + * that no real symbol is given code-value of all ones, because 256 + * will be placed last in the largest codeword category. + */ + + /* Huffman's basic algorithm to assign optimal code lengths to symbols */ + + for (;;) { + /* Find the smallest nonzero frequency, set c1 = its symbol */ + /* In case of ties, take the larger symbol number */ + c1 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v) { + v = freq[i]; + c1 = i; + } + } + + /* Find the next smallest nonzero frequency, set c2 = its symbol */ + /* In case of ties, take the larger symbol number */ + c2 = -1; + v = 1000000000L; + for (i = 0; i <= 256; i++) { + if (freq[i] && freq[i] <= v && i != c1) { + v = freq[i]; + c2 = i; + } + } + + /* Done if we've merged everything into one frequency */ + if (c2 < 0) + break; + + /* Else merge the two counts/trees */ + freq[c1] += freq[c2]; + freq[c2] = 0; + + /* Increment the codesize of everything in c1's tree branch */ + codesize[c1]++; + while (others[c1] >= 0) { + c1 = others[c1]; + codesize[c1]++; + } + + others[c1] = c2; /* chain c2 onto c1's tree branch */ + + /* Increment the codesize of everything in c2's tree branch */ + codesize[c2]++; + while (others[c2] >= 0) { + c2 = others[c2]; + codesize[c2]++; + } + } + + /* Now count the number of symbols of each code length */ + for (i = 0; i <= 256; i++) { + if (codesize[i]) { + /* The JPEG standard seems to think that this can't happen, */ + /* but I'm paranoid... */ + if (codesize[i] > MAX_CLEN) + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + + bits[codesize[i]]++; + } + } + + /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + * Huffman procedure assigned any such lengths, we must adjust the coding. + * Here is what the JPEG spec says about how this next bit works: + * Since symbols are paired for the longest Huffman code, the symbols are + * removed from this length category two at a time. The prefix for the pair + * (which is one bit shorter) is allocated to one of the pair; then, + * skipping the BITS entry for that prefix length, a code word from the next + * shortest nonzero BITS entry is converted into a prefix for two code words + * one bit longer. + */ + + for (i = MAX_CLEN; i > 16; i--) { + while (bits[i] > 0) { + j = i - 2; /* find length of new prefix to be used */ + while (bits[j] == 0) + j--; + + bits[i] -= 2; /* remove two symbols */ + bits[i-1]++; /* one goes in this length */ + bits[j+1] += 2; /* two new symbols in this length */ + bits[j]--; /* symbol of this length is now a prefix */ + } + } + + /* Remove the count for the pseudo-symbol 256 from the largest codelength */ + while (bits[i] == 0) /* find largest codelength still in use */ + i--; + bits[i]--; + + /* Return final symbol counts (only for lengths 0..16) */ + MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); + + /* Return a list of the symbols sorted by code length */ + /* It's not real clear to me why we don't need to consider the codelength + * changes made above, but the JPEG spec seems to think this works. + */ + p = 0; + for (i = 1; i <= MAX_CLEN; i++) { + for (j = 0; j <= 255; j++) { + if (codesize[j] == i) { + htbl->huffval[p] = (UINT8) j; + p++; + } + } + } + + /* Set sent_table FALSE so updated table will be written to JPEG file. */ + htbl->sent_table = FALSE; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, dctbl, actbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[NUM_HUFF_TBLS]; + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did_dc, SIZEOF(did_dc)); + MEMZERO(did_ac, SIZEOF(did_ac)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + if (! did_dc[dctbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); + did_dc[dctbl] = TRUE; + } + if (! did_ac[actbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); + did_ac[actbl] = TRUE; + } + } +} + + +#endif /* ENTROPY_OPT_SUPPORTED */ + + +/* + * Module initialization routine for Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_huff_encoder (j_compress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_huff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; +#ifdef ENTROPY_OPT_SUPPORTED + entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; +#endif + } +} diff --git a/Utilities/vtkjpeg/jchuff.h b/Utilities/vtkjpeg/jchuff.h new file mode 100644 index 0000000..a1a5280 --- /dev/null +++ b/Utilities/vtkjpeg/jchuff.h @@ -0,0 +1,47 @@ +/* + * jchuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy encoding routines + * that are shared between the sequential encoder (jchuff.c) and the + * progressive encoder (jcphuff.c). No other modules need to see these. + */ + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_c_derived_tbl jMkCDerived +#define jpeg_gen_optimal_table jGenOptTbl +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_c_derived_tbl + JPP((j_compress_ptr cinfo, boolean isDC, int tblno, + c_derived_tbl ** pdtbl)); + +/* Generate an optimal table definition given the specified counts */ +EXTERN(void) jpeg_gen_optimal_table + JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/Utilities/vtkjpeg/jcinit.c b/Utilities/vtkjpeg/jcinit.c new file mode 100644 index 0000000..5efffe3 --- /dev/null +++ b/Utilities/vtkjpeg/jcinit.c @@ -0,0 +1,72 @@ +/* + * jcinit.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains initialization logic for the JPEG compressor. + * This routine is in charge of selecting the modules to be executed and + * making an initialization call to each one. + * + * Logically, this code belongs in jcmaster.c. It's split out because + * linking this routine implies linking the entire compression library. + * For a transcoding-only application, we want to be able to use jcmaster.c + * without linking in the whole library. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Master selection of compression modules. + * This is done once at the start of processing an image. We determine + * which modules will be used and give them appropriate initialization calls. + */ + +GLOBAL(void) +jinit_compress_master (j_compress_ptr cinfo) +{ + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, FALSE /* full compression */); + + /* Preprocessing */ + if (! cinfo->raw_data_in) { + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); + } + /* Forward DCT */ + jinit_forward_dct(cinfo); + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* Need a full-image coefficient buffer in any multi-pass mode. */ + jinit_c_coef_controller(cinfo, + (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); + jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} diff --git a/Utilities/vtkjpeg/jcmainct.c b/Utilities/vtkjpeg/jcmainct.c new file mode 100644 index 0000000..a23c38e --- /dev/null +++ b/Utilities/vtkjpeg/jcmainct.c @@ -0,0 +1,293 @@ +/* + * jcmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for compression. + * The main buffer lies between the pre-processor and the JPEG + * compressor proper; it holds downsampled data in the JPEG colorspace. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Note: currently, there is no operating mode in which a full-image buffer + * is needed at this step. If there were, that mode could not be used with + * "raw data" input, since this module is bypassed in that case. However, + * we've left the code here for possible use in special applications. + */ +#undef FULL_MAIN_BUFFER_SUPPORTED + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_main_controller pub; /* public fields */ + + JDIMENSION cur_iMCU_row; /* number of current iMCU row */ + JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */ + boolean suspended; /* remember if we suspended output */ + J_BUF_MODE pass_mode; /* current operating mode */ + + /* If using just a strip buffer, this points to the entire set of buffers + * (we allocate one for each component). In the full-image case, this + * points to the currently accessible strips of the virtual arrays. + */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* If using full-image storage, this array holds pointers to virtual-array + * control blocks for each component. Unused if not full-image storage. + */ + jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; +#endif +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#ifdef FULL_MAIN_BUFFER_SUPPORTED +METHODDEF(void) process_data_buffer_main + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + + /* Do nothing in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + mainPtr->cur_iMCU_row = 0; /* initialize counters */ + mainPtr->rowgroup_ctr = 0; + mainPtr->suspended = FALSE; + mainPtr->pass_mode = pass_mode; /* save mode for use by process_data */ + + switch (pass_mode) { + case JBUF_PASS_THRU: +#ifdef FULL_MAIN_BUFFER_SUPPORTED + if (mainPtr->whole_image[0] != NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + mainPtr->pub.process_data = process_data_simple_main; + break; +#ifdef FULL_MAIN_BUFFER_SUPPORTED + case JBUF_SAVE_SOURCE: + case JBUF_CRANK_DEST: + case JBUF_SAVE_AND_PASS: + if (mainPtr->whole_image[0] == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + mainPtr->pub.process_data = process_data_buffer_main; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This routine handles the simple pass-through mode, + * where we have only a strip buffer. + */ + +METHODDEF(void) +process_data_simple_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + + while (mainPtr->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Read input data if we haven't filled the main buffer yet */ + if (mainPtr->rowgroup_ctr < DCTSIZE) + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mainPtr->buffer, &mainPtr->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + + /* If we don't have a full iMCU row buffered, return to application for + * more data. Note that preprocessor will always pad to fill the iMCU row + * at the bottom of the image. + */ + if (mainPtr->rowgroup_ctr != DCTSIZE) + return; + + /* Send the completed row to the compressor */ + if (! (*cinfo->coef->compress_data) (cinfo, mainPtr->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mainPtr->suspended) { + (*in_row_ctr)--; + mainPtr->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mainPtr->suspended) { + (*in_row_ctr)++; + mainPtr->suspended = FALSE; + } + mainPtr->rowgroup_ctr = 0; + mainPtr->cur_iMCU_row++; + } +} + + +#ifdef FULL_MAIN_BUFFER_SUPPORTED + +/* + * Process some data. + * This routine handles all of the modes that use a full-size buffer. + */ + +METHODDEF(void) +process_data_buffer_main (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + int ci; + jpeg_component_info *compptr; + boolean writing = (mainPtr->pass_mode != JBUF_CRANK_DEST); + + while (mainPtr->cur_iMCU_row < cinfo->total_iMCU_rows) { + /* Realign the virtual buffers if at the start of an iMCU row. */ + if (mainPtr->rowgroup_ctr == 0) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mainPtr->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, mainPtr->whole_image[ci], + mainPtr->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); + } + /* In a read pass, pretend we just read some source data. */ + if (! writing) { + *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; + mainPtr->rowgroup_ctr = DCTSIZE; + } + } + + /* If a write pass, read input data until the current iMCU row is full. */ + /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ + if (writing) { + (*cinfo->prep->pre_process_data) (cinfo, + input_buf, in_row_ctr, in_rows_avail, + mainPtr->buffer, &mainPtr->rowgroup_ctr, + (JDIMENSION) DCTSIZE); + /* Return to application if we need more data to fill the iMCU row. */ + if (mainPtr->rowgroup_ctr < DCTSIZE) + return; + } + + /* Emit data, unless this is a sink-only pass. */ + if (mainPtr->pass_mode != JBUF_SAVE_SOURCE) { + if (! (*cinfo->coef->compress_data) (cinfo, mainPtr->buffer)) { + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mainPtr->suspended) { + (*in_row_ctr)--; + mainPtr->suspended = TRUE; + } + return; + } + /* We did finish the row. Undo our little suspension hack if a previous + * call suspended; then mark the main buffer empty. + */ + if (mainPtr->suspended) { + (*in_row_ctr)++; + mainPtr->suspended = FALSE; + } + } + + /* If get here, we are done with this iMCU row. Mark buffer empty. */ + mainPtr->rowgroup_ctr = 0; + mainPtr->cur_iMCU_row++; + } +} + +#endif /* FULL_MAIN_BUFFER_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mainPtr; + int ci; + jpeg_component_info *compptr; + + mainPtr = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_c_main_controller *) mainPtr; + mainPtr->pub.start_pass = start_pass_main; + + /* We don't need to create a buffer in raw-data mode. */ + if (cinfo->raw_data_in) + return; + + /* Create the buffer. It holds downsampled data, so each component + * may be of a different size. + */ + if (need_full_buffer) { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + /* Allocate a full-image virtual array for each component */ + /* Note we pad the bottom to a multiple of the iMCU height */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mainPtr->whole_image[ci] = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor) * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif + } else { +#ifdef FULL_MAIN_BUFFER_SUPPORTED + mainPtr->whole_image[0] = NULL; /* flag for no virtual arrays */ +#endif + /* Allocate a strip buffer for each component */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + mainPtr->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + } + } +} diff --git a/Utilities/vtkjpeg/jcmarker.c b/Utilities/vtkjpeg/jcmarker.c new file mode 100644 index 0000000..4fb6ddd --- /dev/null +++ b/Utilities/vtkjpeg/jcmarker.c @@ -0,0 +1,665 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to write JPEG datastream markers. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_writer pub; /* public fields */ + + unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ +} my_marker_writer; + +typedef my_marker_writer * my_marker_ptr; + + +/* + * Basic output routines. + * + * Note that we do not support suspension while writing a marker. + * Therefore, an application using suspension must ensure that there is + * enough buffer space for the initial markers (typ. 600-700 bytes) before + * calling jpeg_start_compress, and enough space to write the trailing EOI + * (a few bytes) before calling jpeg_finish_compress. Multipass compression + * modes are not supported at all with suspension, so those two are the only + * points where markers will be written. + */ + +LOCAL(void) +emit_byte (j_compress_ptr cinfo, int val) +/* Emit a byte */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *(dest->next_output_byte)++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) { + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + } +} + + +LOCAL(void) +emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) +/* Emit a marker code */ +{ + emit_byte(cinfo, 0xFF); + emit_byte(cinfo, (int) mark); +} + + +LOCAL(void) +emit_2bytes (j_compress_ptr cinfo, int value) +/* Emit a 2-byte integer; these are always MSB first in JPEG files */ +{ + emit_byte(cinfo, (value >> 8) & 0xFF); + emit_byte(cinfo, value & 0xFF); +} + + +/* + * Routines to write specific marker types. + */ + +LOCAL(int) +emit_dqt (j_compress_ptr cinfo, int index) +/* Emit a DQT marker */ +/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ +{ + JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; + int prec; + int i; + + if (qtbl == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); + + prec = 0; + for (i = 0; i < DCTSIZE2; i++) { + if (qtbl->quantval[i] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, index + (prec<<4)); + + for (i = 0; i < DCTSIZE2; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + if (prec) + emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval & 0xFF)); + } + + qtbl->sent_table = TRUE; + } + + return prec; +} + + +LOCAL(void) +emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) +/* Emit a DHT marker */ +{ + JHUFF_TBL * htbl; + int length, i; + + if (is_ac) { + htbl = cinfo->ac_huff_tbl_ptrs[index]; + index += 0x10; /* output index has AC bit set */ + } else { + htbl = cinfo->dc_huff_tbl_ptrs[index]; + } + + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); + + if (! htbl->sent_table) { + emit_marker(cinfo, M_DHT); + + length = 0; + for (i = 1; i <= 16; i++) + length += htbl->bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, index); + + for (i = 1; i <= 16; i++) + emit_byte(cinfo, htbl->bits[i]); + + for (i = 0; i < length; i++) + emit_byte(cinfo, htbl->huffval[i]); + + htbl->sent_table = TRUE; + } +} + + +LOCAL(void) +emit_dac (j_compress_ptr cinfo) +/* Emit a DAC marker */ +/* Since the useful info is so small, we want to emit all the tables in */ +/* one DAC marker. Therefore this routine does its own scan of the table. */ +{ +#ifdef C_ARITH_CODING_SUPPORTED + char dc_in_use[NUM_ARITH_TBLS]; + char ac_in_use[NUM_ARITH_TBLS]; + int length, i; + jpeg_component_info *compptr; + + for (i = 0; i < NUM_ARITH_TBLS; i++) + dc_in_use[i] = ac_in_use[i] = 0; + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + dc_in_use[compptr->dc_tbl_no] = 1; + ac_in_use[compptr->ac_tbl_no] = 1; + } + + length = 0; + for (i = 0; i < NUM_ARITH_TBLS; i++) + length += dc_in_use[i] + ac_in_use[i]; + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + if (dc_in_use[i]) { + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + } + if (ac_in_use[i]) { + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); + } + } +#endif /* C_ARITH_CODING_SUPPORTED */ + cinfo = 0; +} + + +LOCAL(void) +emit_dri (j_compress_ptr cinfo) +/* Emit a DRI marker */ +{ + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); /* fixed length */ + + emit_2bytes(cinfo, (int) cinfo->restart_interval); +} + + +LOCAL(void) +emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) +/* Emit a SOF marker */ +{ + int ci; + jpeg_component_info *compptr; + + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ + + /* Make sure image isn't bigger than SOF field can handle */ + if ((long) cinfo->image_height > 65535L || + (long) cinfo->image_width > 65535L) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); + + emit_byte(cinfo, cinfo->data_precision); + emit_2bytes(cinfo, (int) cinfo->image_height); + emit_2bytes(cinfo, (int) cinfo->image_width); + + emit_byte(cinfo, cinfo->num_components); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + emit_byte(cinfo, compptr->component_id); + emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); + emit_byte(cinfo, compptr->quant_tbl_no); + } +} + + +LOCAL(void) +emit_sos (j_compress_ptr cinfo) +/* Emit a SOS marker */ +{ + int i, td, ta; + jpeg_component_info *compptr; + + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ + + emit_byte(cinfo, cinfo->comps_in_scan); + + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + emit_byte(cinfo, compptr->component_id); + td = compptr->dc_tbl_no; + ta = compptr->ac_tbl_no; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan; + * furthermore, Huffman coding of DC refinement uses no table at all. + * We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + if (cinfo->Ss == 0) { + ta = 0; /* DC scan */ + if (cinfo->Ah != 0 && !cinfo->arith_code) + td = 0; /* no DC table either */ + } else { + td = 0; /* AC scan */ + } + } + emit_byte(cinfo, (td << 4) + ta); + } + + emit_byte(cinfo, cinfo->Ss); + emit_byte(cinfo, cinfo->Se); + emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); +} + + +LOCAL(void) +emit_jfif_app0 (j_compress_ptr cinfo) +/* Emit a JFIF-compliant APP0 marker */ +{ + /* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ + + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + + emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0x49); + emit_byte(cinfo, 0x46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ + emit_byte(cinfo, cinfo->JFIF_minor_version); + emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ + emit_2bytes(cinfo, (int) cinfo->X_density); + emit_2bytes(cinfo, (int) cinfo->Y_density); + emit_byte(cinfo, 0); /* No thumbnail image */ + emit_byte(cinfo, 0); +} + + +LOCAL(void) +emit_adobe_app14 (j_compress_ptr cinfo) +/* Emit an Adobe APP14 marker */ +{ + /* + * Length of APP14 block (2 bytes) + * Block ID (5 bytes - ASCII "Adobe") + * Version Number (2 bytes - currently 100) + * Flags0 (2 bytes - currently 0) + * Flags1 (2 bytes - currently 0) + * Color transform (1 byte) + * + * Although Adobe TN 5116 mentions Version = 101, all the Adobe files + * now in circulation seem to use Version = 100, so that's what we write. + * + * We write the color transform byte as 1 if the JPEG color space is + * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + * whether the encoder performed a transformation, which is pretty useless. + */ + + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ + + emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ + emit_byte(cinfo, 0x64); + emit_byte(cinfo, 0x6F); + emit_byte(cinfo, 0x62); + emit_byte(cinfo, 0x65); + emit_2bytes(cinfo, 100); /* Version */ + emit_2bytes(cinfo, 0); /* Flags0 */ + emit_2bytes(cinfo, 0); /* Flags1 */ + switch (cinfo->jpeg_color_space) { + case JCS_YCbCr: + emit_byte(cinfo, 1); /* Color transform = 1 */ + break; + case JCS_YCCK: + emit_byte(cinfo, 2); /* Color transform = 2 */ + break; + default: + emit_byte(cinfo, 0); /* Color transform = 0 */ + break; + } +} + + +/* + * These routines allow writing an arbitrary marker with parameters. + * The only intended use is to emit COM or APPn markers after calling + * write_file_header and before calling write_frame_header. + * Other uses are not guaranteed to produce desirable results. + * Counting the parameter bytes properly is the caller's responsibility. + */ + +METHODDEF(void) +write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) +/* Emit an arbitrary marker header */ +{ + if (datalen > (unsigned int) 65533) /* safety check */ + ERREXIT(cinfo, JERR_BAD_LENGTH); + + emit_marker(cinfo, (JPEG_MARKER) marker); + + emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ +} + +METHODDEF(void) +write_marker_byte (j_compress_ptr cinfo, int val) +/* Emit one byte of marker parameters following write_marker_header */ +{ + emit_byte(cinfo, val); +} + + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + * We recommend use of the JFIF marker, but not the Adobe marker, + * when using YCbCr or grayscale data. The JFIF marker should NOT + * be used for any other JPEG colorspace. The Adobe marker is helpful + * to distinguish RGB, CMYK, and YCCK colorspaces. + * Note that an application can write additional header markers after + * jpeg_start_compress returns. + */ + +METHODDEF(void) +write_file_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + emit_marker(cinfo, M_SOI); /* first the SOI */ + + /* SOI is defined to reset restart interval to 0 */ + marker->last_restart_interval = 0; + + if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ + emit_jfif_app0(cinfo); + if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ + emit_adobe_app14(cinfo); +} + + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ + +METHODDEF(void) +write_frame_header (j_compress_ptr cinfo) +{ + int ci, prec; + boolean is_baseline; + jpeg_component_info *compptr; + + /* Emit DQT for each quantization table. + * Note that emit_dqt() suppresses any duplicate tables. + */ + prec = 0; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prec += emit_dqt(cinfo, compptr->quant_tbl_no); + } + /* now prec is nonzero iff there are any 16-bit quant tables. */ + + /* Check for a non-baseline specification. + * Note we assume that Huffman table numbers won't be changed later. + */ + if (cinfo->arith_code || cinfo->progressive_mode || + cinfo->data_precision != 8) { + is_baseline = FALSE; + } else { + is_baseline = TRUE; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) + is_baseline = FALSE; + } + if (prec && is_baseline) { + is_baseline = FALSE; + /* If it's baseline except for quantizer size, warn the user */ + TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); + } + } + + /* Emit the proper SOF marker */ + if (cinfo->arith_code) { + emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ + } else { + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ + else if (is_baseline) + emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ + else + emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ + } +} + + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ + +METHODDEF(void) +write_scan_header (j_compress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + int i; + jpeg_component_info *compptr; + + if (cinfo->arith_code) { + /* Emit arith conditioning info. We may have some duplication + * if the file has multiple scans, but it's so small it's hardly + * worth worrying about. + */ + emit_dac(cinfo); + } else { + /* Emit Huffman tables. + * Note that emit_dht() suppresses any duplicate tables. + */ + for (i = 0; i < cinfo->comps_in_scan; i++) { + compptr = cinfo->cur_comp_info[i]; + if (cinfo->progressive_mode) { + /* Progressive mode: only DC or only AC tables are used in one scan */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + } else { + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } else { + /* Sequential mode: need both DC and AC tables */ + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + } + } + } + + /* Emit DRI if required --- note that DRI value could change for each scan. + * We avoid wasting space with unnecessary DRIs, however. + */ + if (cinfo->restart_interval != marker->last_restart_interval) { + emit_dri(cinfo); + marker->last_restart_interval = cinfo->restart_interval; + } + + emit_sos(cinfo); +} + + +/* + * Write datastream trailer. + */ + +METHODDEF(void) +write_file_trailer (j_compress_ptr cinfo) +{ + emit_marker(cinfo, M_EOI); +} + + +/* + * Write an abbreviated table-specification datastream. + * This consists of SOI, DQT and DHT tables, and EOI. + * Any table that is defined and not marked sent_table = TRUE will be + * emitted. Note that all tables will be marked sent_table = TRUE at exit. + */ + +METHODDEF(void) +write_tables_only (j_compress_ptr cinfo) +{ + int i; + + emit_marker(cinfo, M_SOI); + + for (i = 0; i < NUM_QUANT_TBLS; i++) { + if (cinfo->quant_tbl_ptrs[i] != NULL) + (void) emit_dqt(cinfo, i); + } + + if (! cinfo->arith_code) { + for (i = 0; i < NUM_HUFF_TBLS; i++) { + if (cinfo->dc_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, FALSE); + if (cinfo->ac_huff_tbl_ptrs[i] != NULL) + emit_dht(cinfo, i, TRUE); + } + } + + emit_marker(cinfo, M_EOI); +} + + +/* + * Initialize the marker writer module. + */ + +GLOBAL(void) +jinit_marker_writer (j_compress_ptr cinfo) +{ + my_marker_ptr marker; + + /* Create the subobject */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_marker_writer)); + cinfo->marker = (struct jpeg_marker_writer *) marker; + /* Initialize method pointers */ + marker->pub.write_file_header = write_file_header; + marker->pub.write_frame_header = write_frame_header; + marker->pub.write_scan_header = write_scan_header; + marker->pub.write_file_trailer = write_file_trailer; + marker->pub.write_tables_only = write_tables_only; + marker->pub.write_marker_header = write_marker_header; + marker->pub.write_marker_byte = write_marker_byte; + /* Initialize private state */ + marker->last_restart_interval = 0; +} diff --git a/Utilities/vtkjpeg/jcmaster.c b/Utilities/vtkjpeg/jcmaster.c new file mode 100644 index 0000000..aab4020 --- /dev/null +++ b/Utilities/vtkjpeg/jcmaster.c @@ -0,0 +1,590 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG compressor. + * These routines are concerned with parameter validation, initial setup, + * and inter-pass control (determining the number of passes and the work + * to be done in each pass). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef enum { + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ +} c_pass_type; + +typedef struct { + struct jpeg_comp_master pub; /* public fields */ + + c_pass_type pass_type; /* the type of the current pass */ + + int pass_number; /* # of passes completed */ + int total_passes; /* total # of passes needed */ + + int scan_number; /* current index in scan_info[] */ +} my_comp_master; + +typedef my_comp_master * my_master_ptr; + + +/* + * Support routines that do various essential calculations. + */ + +LOCAL(void) +initial_setup (j_compress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ + int ci; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0 || cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Fill in the correct component_index value; don't rely on application */ + compptr->component_index = ci; + /* For compression, we never do DCT scaling. */ + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed (this flag isn't actually used for compression) */ + compptr->component_needed = TRUE; + } + + /* Compute number of fully interleaved MCU rows (number of times that + * main controller will call coefficient controller). + */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); +} + + +#ifdef C_MULTISCAN_FILES_SUPPORTED + +LOCAL(void) +validate_script (j_compress_ptr cinfo) +/* Verify that the scan script in cinfo->scan_info[] is valid; also + * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. + */ +{ + const jpeg_scan_info * scanptr; + int scanno, ncomps, ci, coefi, thisi; + int Ss, Se, Ah, Al; + boolean component_sent[MAX_COMPONENTS]; +#ifdef C_PROGRESSIVE_SUPPORTED + int * last_bitpos_ptr; + int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; + /* -1 until that coefficient has been seen; then last Al for it */ +#endif + + if (cinfo->num_scans <= 0) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); + + /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + * for progressive JPEG, no scan can have this. + */ + scanptr = cinfo->scan_info; + if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { +#ifdef C_PROGRESSIVE_SUPPORTED + cinfo->progressive_mode = TRUE; + last_bitpos_ptr = & last_bitpos[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (coefi = 0; coefi < DCTSIZE2; coefi++) + *last_bitpos_ptr++ = -1; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + for (ci = 0; ci < cinfo->num_components; ci++) + component_sent[ci] = FALSE; + } + + for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { + /* Validate component indexes */ + ncomps = scanptr->comps_in_scan; + if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (thisi < 0 || thisi >= cinfo->num_components) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + /* Components must appear in SOF order within each scan */ + if (ci > 0 && thisi <= scanptr->component_index[ci-1]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + } + /* Validate progression parameters */ + Ss = scanptr->Ss; + Se = scanptr->Se; + Ah = scanptr->Ah; + Al = scanptr->Al; + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + * seems wrong: the upper bound ought to depend on data precision. + * Perhaps they really meant 0..N+1 for N-bit precision. + * Here we allow 0..10 for 8-bit data; Al larger than 10 results in + * out-of-range reconstructed DC values during the first DC scan, + * which might cause problems for some decoders. + */ +#if BITS_IN_JSAMPLE == 8 +#define MAX_AH_AL 10 +#else +#define MAX_AH_AL 13 +#endif + if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Ss == 0) { + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + for (ci = 0; ci < ncomps; ci++) { + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } + } +#endif + } else { + /* For sequential JPEG, all progression parameters must be these: */ + if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + /* Make sure components are not sent twice */ + for (ci = 0; ci < ncomps; ci++) { + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; + } + } + } + + /* Now verify that everything got sent. */ + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + /* For progressive mode, we only check that at least some DC data + * got sent for each component; the spec does not require that all bits + * of all coefficients be transmitted. Would it be wiser to enforce + * transmission of all coefficient bits?? + */ + for (ci = 0; ci < cinfo->num_components; ci++) { + if (last_bitpos[ci][0] < 0) + ERREXIT(cinfo, JERR_MISSING_DATA); + } +#endif + } else { + for (ci = 0; ci < cinfo->num_components; ci++) { + if (! component_sent[ci]) + ERREXIT(cinfo, JERR_MISSING_DATA); + } + } +} + +#endif /* C_MULTISCAN_FILES_SUPPORTED */ + + +LOCAL(void) +select_scan_parameters (j_compress_ptr cinfo) +/* Set up the scan parameters for the current scan */ +{ + int ci; + +#ifdef C_MULTISCAN_FILES_SUPPORTED + if (cinfo->scan_info != NULL) { + /* Prepare for current scan --- the script is already validated */ + my_master_ptr master = (my_master_ptr) cinfo->master; + const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; + + cinfo->comps_in_scan = scanptr->comps_in_scan; + for (ci = 0; ci < scanptr->comps_in_scan; ci++) { + cinfo->cur_comp_info[ci] = + &cinfo->comp_info[scanptr->component_index[ci]]; + } + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + } + else +#endif + { + /* Prepare for single sequential-JPEG scan containing all components */ + if (cinfo->num_components > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPS_IN_SCAN); + cinfo->comps_in_scan = cinfo->num_components; + for (ci = 0; ci < cinfo->num_components; ci++) { + cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; + } + cinfo->Ss = 0; + cinfo->Se = DCTSIZE2-1; + cinfo->Ah = 0; + cinfo->Al = 0; + } +} + + +LOCAL(void) +per_scan_setup (j_compress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = DCTSIZE; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } + + /* Convert restart specified in rows to actual MCU count. */ + /* Note that count must fit in 16 bits, so we provide limiting. */ + if (cinfo->restart_in_rows > 0) { + long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; + cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); + } +} + + +/* + * Per-pass setup. + * This is called at the beginning of each pass. We determine which modules + * will be active during this pass and give them appropriate start_pass calls. + * We also set is_last_pass to indicate whether any more passes will be + * required. + */ + +METHODDEF(void) +prepare_for_pass (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + switch (master->pass_type) { + case main_pass: + /* Initial pass: will collect input data, and do either Huffman + * optimization or data output for the first scan. + */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (! cinfo->raw_data_in) { + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->downsample->start_pass) (cinfo); + (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); + } + (*cinfo->fdct->start_pass) (cinfo); + (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); + (*cinfo->coef->start_pass) (cinfo, + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + if (cinfo->optimize_coding) { + /* No immediate data output; postpone writing frame/scan headers */ + master->pub.call_pass_startup = FALSE; + } else { + /* Will write frame/scan headers at first jpeg_write_scanlines call */ + master->pub.call_pass_startup = TRUE; + } + break; +#ifdef ENTROPY_OPT_SUPPORTED + case huff_opt_pass: + /* Do Huffman optimization for a scan after the first one. */ + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + (*cinfo->entropy->start_pass) (cinfo, TRUE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + master->pub.call_pass_startup = FALSE; + break; + } + /* Special case: Huffman DC refinement scans need no Huffman table + * and therefore we can skip the optimization pass for them. + */ + master->pass_type = output_pass; + master->pass_number++; + /*FALLTHROUGH*/ +#endif + case output_pass: + /* Do a data-output pass. */ + /* We need not repeat per-scan setup if prior optimization pass did it. */ + if (! cinfo->optimize_coding) { + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + } + (*cinfo->entropy->start_pass) (cinfo, FALSE); + (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); + /* We emit frame/scan headers now */ + if (master->scan_number == 0) + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); + master->pub.call_pass_startup = FALSE; + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + } + + master->pub.is_last_pass = (master->pass_number == master->total_passes-1); + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->total_passes; + } +} + + +/* + * Special start-of-pass hook. + * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + * In single-pass processing, we need this hook because we don't want to + * write frame/scan headers during jpeg_start_compress; we want to let the + * application write COM markers etc. between jpeg_start_compress and the + * jpeg_write_scanlines loop. + * In multi-pass processing, this routine is not used. + */ + +METHODDEF(void) +pass_startup (j_compress_ptr cinfo) +{ + cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ + + (*cinfo->marker->write_frame_header) (cinfo); + (*cinfo->marker->write_scan_header) (cinfo); +} + + +/* + * Finish up at end of pass. + */ + +METHODDEF(void) +finish_pass_master (j_compress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* The entropy coder always needs an end-of-pass call, + * either to analyze statistics or to flush its output buffer. + */ + (*cinfo->entropy->finish_pass) (cinfo); + + /* Update state for next pass */ + switch (master->pass_type) { + case main_pass: + /* next pass is either output of scan 0 (after optimization) + * or output of scan 1 (if no optimization). + */ + master->pass_type = output_pass; + if (! cinfo->optimize_coding) + master->scan_number++; + break; + case huff_opt_pass: + /* next pass is always output of current scan */ + master->pass_type = output_pass; + break; + case output_pass: + /* next pass is either optimization or output of next scan */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + master->scan_number++; + break; + } + + master->pass_number++; +} + + +/* + * Initialize master compression control. + */ + +GLOBAL(void) +jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_comp_master)); + cinfo->master = (struct jpeg_comp_master *) master; + master->pub.prepare_for_pass = prepare_for_pass; + master->pub.pass_startup = pass_startup; + master->pub.finish_pass = finish_pass_master; + master->pub.is_last_pass = FALSE; + + /* Validate parameters, determine derived values */ + initial_setup(cinfo); + + if (cinfo->scan_info != NULL) { +#ifdef C_MULTISCAN_FILES_SUPPORTED + validate_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + cinfo->num_scans = 1; + } + + if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ + cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + + /* Initialize my private state */ + if (transcode_only) { + /* no main pass in transcoding */ + if (cinfo->optimize_coding) + master->pass_type = huff_opt_pass; + else + master->pass_type = output_pass; + } else { + /* for normal compression, first pass is always this type: */ + master->pass_type = main_pass; + } + master->scan_number = 0; + master->pass_number = 0; + if (cinfo->optimize_coding) + master->total_passes = cinfo->num_scans * 2; + else + master->total_passes = cinfo->num_scans; +} diff --git a/Utilities/vtkjpeg/jcomapi.c b/Utilities/vtkjpeg/jcomapi.c new file mode 100644 index 0000000..9b1fa75 --- /dev/null +++ b/Utilities/vtkjpeg/jcomapi.c @@ -0,0 +1,106 @@ +/* + * jcomapi.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface routines that are used for both + * compression and decompression. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Abort processing of a JPEG compression or decompression operation, + * but don't destroy the object itself. + * + * For this, we merely clean up all the nonpermanent memory pools. + * Note that temp files (virtual arrays) are not allowed to belong to + * the permanent pool, so we will be able to close all temp files here. + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_abort (j_common_ptr cinfo) +{ + int pool; + + /* Do nothing if called on a not-initialized or destroyed JPEG object. */ + if (cinfo->mem == NULL) + return; + + /* Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { + (*cinfo->mem->free_pool) (cinfo, pool); + } + + /* Reset overall state for possible reuse of object */ + if (cinfo->is_decompressor) { + cinfo->global_state = DSTATE_START; + /* Try to keep application from accessing now-deleted marker list. + * A bit kludgy to do it here, but this is the most central place. + */ + ((j_decompress_ptr) cinfo)->marker_list = NULL; + } else { + cinfo->global_state = CSTATE_START; + } +} + + +/* + * Destruction of a JPEG object. + * + * Everything gets deallocated except the master jpeg_compress_struct itself + * and the error manager struct. Both of these are supplied by the application + * and must be freed, if necessary, by the application. (Often they are on + * the stack and so don't need to be freed anyway.) + * Closing a data source or destination, if necessary, is the application's + * responsibility. + */ + +GLOBAL(void) +jpeg_destroy (j_common_ptr cinfo) +{ + /* We need only tell the memory manager to release everything. */ + /* NB: mem pointer is NULL if memory mgr failed to initialize. */ + if (cinfo->mem != NULL) + (*cinfo->mem->self_destruct) (cinfo); + cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ + cinfo->global_state = 0; /* mark it destroyed */ +} + + +/* + * Convenience routines for allocating quantization and Huffman tables. + * (Would jutils.c be a more reasonable place to put these?) + */ + +GLOBAL(JQUANT_TBL *) +jpeg_alloc_quant_table (j_common_ptr cinfo) +{ + JQUANT_TBL *tbl; + + tbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} + + +GLOBAL(JHUFF_TBL *) +jpeg_alloc_huff_table (j_common_ptr cinfo) +{ + JHUFF_TBL *tbl; + + tbl = (JHUFF_TBL *) + (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); + tbl->sent_table = FALSE; /* make sure this is false in any new table */ + return tbl; +} diff --git a/Utilities/vtkjpeg/jconfig.doc b/Utilities/vtkjpeg/jconfig.doc new file mode 100644 index 0000000..6e2552b --- /dev/null +++ b/Utilities/vtkjpeg/jconfig.doc @@ -0,0 +1,155 @@ +/* + * jconfig.doc + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file documents the configuration options that are required to + * customize the JPEG software for a particular system. + * + * The actual configuration options for a particular installation are stored + * in jconfig.h. On many machines, jconfig.h can be generated automatically + * or copied from one of the "canned" jconfig files that we supply. But if + * you need to generate a jconfig.h file by hand, this file tells you how. + * + * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. + * EDIT A COPY NAMED JCONFIG.H. + */ + + +/* + * These symbols indicate the properties of your machine or compiler. + * #define the symbol if yes, #undef it if no. + */ + +/* Does your compiler support function prototypes? + * (If not, you also need to use ansi2knr, see install.doc) + */ +#define HAVE_PROTOTYPES + +/* Does your compiler support the declaration "unsigned char" ? + * How about "unsigned short" ? + */ +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT + +/* Define "void" as "char" if your compiler doesn't know about type void. + * NOTE: be sure to define void such that "void *" represents the most general + * pointer type, e.g., that returned by malloc(). + */ +/* #define void char */ + +/* Define "const" as empty if your compiler doesn't know the "const" keyword. + */ +/* #define const */ + +/* Define this if an ordinary "char" type is unsigned. + * If you're not sure, leaving it undefined will work at some cost in speed. + * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. + */ +#undef CHAR_IS_UNSIGNED + +/* Define this if your system has an ANSI-conforming <stddef.h> file. + */ +#define HAVE_STDDEF_H + +/* Define this if your system has an ANSI-conforming <stdlib.h> file. + */ +#define HAVE_STDLIB_H + +/* Define this if your system does not have an ANSI/SysV <string.h>, + * but does have a BSD-style <strings.h>. + */ +#undef NEED_BSD_STRINGS + +/* Define this if your system does not provide typedef size_t in any of the + * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in + * <sys/types.h> instead. + */ +#undef NEED_SYS_TYPES_H + +/* For 80x86 machines, you need to define NEED_FAR_POINTERS, + * unless you are using a large-data memory model or 80386 flat-memory mode. + * On less brain-damaged CPUs this symbol must not be defined. + * (Defining this symbol causes large data structures to be referenced through + * "far" pointers and to be allocated with a special version of malloc.) + */ +#undef NEED_FAR_POINTERS + +/* Define this if your linker needs global names to be unique in less + * than the first 15 characters. + */ +#undef NEED_SHORT_EXTERNAL_NAMES + +/* Although a real ANSI C compiler can deal perfectly well with pointers to + * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI + * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, + * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you + * actually get "missing structure definition" warnings or errors while + * compiling the JPEG code. + */ +#undef INCOMPLETE_TYPES_BROKEN + + +/* + * The following options affect code selection within the JPEG library, + * but they don't need to be visible to applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS has been defined. + */ + +#ifdef JPEG_INTERNALS + +/* Define this if your compiler implements ">>" on signed values as a logical + * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, + * which is the normal and rational definition. + */ +#undef RIGHT_SHIFT_IS_UNSIGNED + + +#endif /* JPEG_INTERNALS */ + + +/* + * The remaining options do not affect the JPEG library proper, + * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). + * Other applications can ignore these. + */ + +#ifdef JPEG_CJPEG_DJPEG + +/* These defines indicate which image (non-JPEG) file formats are allowed. */ + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +/* Define this if you want to name both input and output files on the command + * line, rather than using stdout and optionally stdin. You MUST do this if + * your system can't cope with binary I/O to stdin/stdout. See comments at + * head of cjpeg.c or djpeg.c. + */ +#undef TWO_FILE_COMMANDLINE + +/* Define this if your system needs explicit cleanup of temporary files. + * This is crucial under MS-DOS, where the temporary "files" may be areas + * of extended memory; on most other systems it's not as important. + */ +#undef NEED_SIGNAL_CATCHER + +/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). + * This is necessary on systems that distinguish text files from binary files, + * and is harmless on most systems that don't. If you have one of the rare + * systems that complains about the "b" spec, define this symbol. + */ +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. + */ +#undef PROGRESS_REPORT + + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/Utilities/vtkjpeg/jconfig.h b/Utilities/vtkjpeg/jconfig.h new file mode 100644 index 0000000..5789cbf --- /dev/null +++ b/Utilities/vtkjpeg/jconfig.h @@ -0,0 +1,60 @@ +/* jconfig.cfg --- source file edited by configure script */ +/* see jconfig.doc for explanations */ + +#define HAVE_PROTOTYPES +#define HAVE_UNSIGNED_CHAR +#define HAVE_UNSIGNED_SHORT +#undef void +#undef const +#undef CHAR_IS_UNSIGNED +#ifndef HAVE_STDDEF_H +#define HAVE_STDDEF_H +#endif +#ifndef HAVE_STDLIB_H +#define HAVE_STDLIB_H +#endif +#undef NEED_BSD_STRINGS +#undef NEED_SYS_TYPES_H +#undef NEED_FAR_POINTERS +#undef NEED_SHORT_EXTERNAL_NAMES +/* Define this if you get warnings about undefined structures. */ +#undef INCOMPLETE_TYPES_BROKEN + + +#if defined(_WIN32) && !(defined(__CYGWIN__) || defined(__MINGW32__)) +/* Define "boolean" as unsigned char, not int, per Windows custom */ +/* don't conflict if rpcndr.h already read; Note that the w32api headers + used by Cygwin and Mingw do not define "boolean", so jmorecfg.h + handles it later. */ +#ifndef __RPCNDR_H__ +typedef unsigned char boolean; +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif + +#ifdef JPEG_INTERNALS + +#undef RIGHT_SHIFT_IS_UNSIGNED +#define INLINE +/* These are for configuring the JPEG memory manager. */ +#undef DEFAULT_MAX_MEM +#undef NO_MKTEMP + +#endif /* JPEG_INTERNALS */ + +#ifdef JPEG_CJPEG_DJPEG + +#define BMP_SUPPORTED /* BMP image file format */ +#define GIF_SUPPORTED /* GIF image file format */ +#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ +#undef RLE_SUPPORTED /* Utah RLE image file format */ +#define TARGA_SUPPORTED /* Targa image file format */ + +#undef TWO_FILE_COMMANDLINE +#undef NEED_SIGNAL_CATCHER +#undef DONT_USE_B_MODE + +/* Define this if you want percent-done progress reports from cjpeg/djpeg. */ +#undef PROGRESS_REPORT + +#endif /* JPEG_CJPEG_DJPEG */ diff --git a/Utilities/vtkjpeg/jcparam.c b/Utilities/vtkjpeg/jcparam.c new file mode 100644 index 0000000..6fc48f5 --- /dev/null +++ b/Utilities/vtkjpeg/jcparam.c @@ -0,0 +1,610 @@ +/* + * jcparam.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains optional default-setting code for the JPEG compressor. + * Applications do not have to use this file, but those that don't use it + * must know a lot more about the innards of the JPEG code. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Quantization table setup routines + */ + +GLOBAL(void) +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + JQUANT_TBL ** qtblptr; + int i; + long temp; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); + + qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; + + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (force_baseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + (*qtblptr)->quantval[i] = (UINT16) temp; + } + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*qtblptr)->sent_table = FALSE; +} + + +GLOBAL(void) +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and a straight percentage-scaling quality scale. In most cases it's better + * to use jpeg_set_quality (below); this entry point is provided for + * applications that insist on a linear percentage scaling. + */ +{ + /* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ + static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +} + + +GLOBAL(int) +jpeg_quality_scaling (int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality*2; + + return quality; +} + + +GLOBAL(void) +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_set_linear_quality(cinfo, quality, force_baseline); +} + + +/* + * Huffman table setup routines + */ + +LOCAL(void) +add_huff_table (j_compress_ptr cinfo, + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); + + /* Initialize sent_table FALSE so table will be written to JPEG file. */ + (*htblptr)->sent_table = FALSE; +} + + +LOCAL(void) +std_huff_tables (j_compress_ptr cinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }; + + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + +/* + * Default parameter setup for compression. + * + * Applications that don't choose to use this routine must do their + * own setup of all these parameters. Alternately, you can call this + * to establish defaults and then alter parameters selectively. This + * is the recommended approach since, if we add any new parameters, + * your code will still work (they'll be set to reasonable defaults). + */ + +GLOBAL(void) +jpeg_set_defaults (j_compress_ptr cinfo) +{ + int i; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Allocate comp_info array large enough for maximum component count. + * Array is made permanent in case application wants to compress + * multiple images at same param settings. + */ + if (cinfo->comp_info == NULL) + cinfo->comp_info = (jpeg_component_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + + /* Initialize everything not dependent on the color space */ + + cinfo->data_precision = BITS_IN_JSAMPLE; + /* Set up two quantization tables using default quality of 75 */ + jpeg_set_quality(cinfo, 75, TRUE); + /* Set up two Huffman tables */ + std_huff_tables(cinfo); + + /* Initialize default arithmetic coding conditioning */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + + /* Default is no multiple-scan output */ + cinfo->scan_info = NULL; + cinfo->num_scans = 0; + + /* Expect normal source image, not raw downsampled data */ + cinfo->raw_data_in = FALSE; + + /* Use Huffman coding, not arithmetic coding, by default */ + cinfo->arith_code = FALSE; + + /* By default, don't do extra passes to optimize entropy coding */ + cinfo->optimize_coding = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, force optimization on so that usable + * tables will be computed. This test can be removed if default tables + * are supplied that are valid for the desired precision. + */ + if (cinfo->data_precision > 8) + cinfo->optimize_coding = TRUE; + + /* By default, use the simpler non-cosited sampling alignment */ + cinfo->CCIR601_sampling = FALSE; + + /* No input smoothing */ + cinfo->smoothing_factor = 0; + + /* DCT algorithm preference */ + cinfo->dct_method = JDCT_DEFAULT; + + /* No restart markers */ + cinfo->restart_interval = 0; + cinfo->restart_in_rows = 0; + + /* Fill in default JFIF marker parameters. Note that whether the marker + * will actually be written is determined by jpeg_set_colorspace. + * + * By default, the library emits JFIF version code 1.01. + * An application that wants to emit JFIF 1.02 extension markers should set + * JFIF_minor_version to 2. We could probably get away with just defaulting + * to 1.02, but there may still be some decoders in use that will complain + * about that; saying 1.01 should minimize compatibility problems. + */ + cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; /* Pixel size is unknown by default */ + cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ + cinfo->Y_density = 1; + + /* Choose JPEG colorspace based on input space, set defaults accordingly */ + + jpeg_default_colorspace(cinfo); +} + + +/* + * Select an appropriate JPEG colorspace for in_color_space. + */ + +GLOBAL(void) +jpeg_default_colorspace (j_compress_ptr cinfo) +{ + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + break; + case JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + break; + case JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ + break; + case JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + break; + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; + default: + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + } +} + + +/* + * Set the JPEG colorspace, and choose colorspace-dependent default values. + */ + +GLOBAL(void) +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) +{ + jpeg_component_info * compptr; + int ci; + +#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ + (compptr = &cinfo->comp_info[index], \ + compptr->component_id = (id), \ + compptr->h_samp_factor = (hsamp), \ + compptr->v_samp_factor = (vsamp), \ + compptr->quant_tbl_no = (quant), \ + compptr->dc_tbl_no = (dctbl), \ + compptr->ac_tbl_no = (actbl) ) + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* For all colorspaces, we use Q and Huff tables 0 for luminance components, + * tables 1 for chrominance components. + */ + + cinfo->jpeg_color_space = colorspace; + + cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ + cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ + + switch (colorspace) { + case JCS_GRAYSCALE: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 1; + /* JFIF specifies component ID 1 */ + SET_COMP(0, 1, 1,1, 0, 0,0); + break; + case JCS_RGB: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ + cinfo->num_components = 3; + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + break; + case JCS_YCbCr: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->num_components = 3; + /* JFIF specifies component IDs 1,2,3 */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + break; + case JCS_CMYK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ + cinfo->num_components = 4; + SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); + SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); + SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); + SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); + break; + case JCS_YCCK: + cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ + cinfo->num_components = 4; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + break; + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; + default: + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + } +} + + +#ifdef C_PROGRESSIVE_SUPPORTED + +LOCAL(jpeg_scan_info *) +fill_a_scan (jpeg_scan_info * scanptr, int ci, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for specified component */ +{ + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_scans (jpeg_scan_info * scanptr, int ncomps, + int Ss, int Se, int Ah, int Al) +/* Support routine: generate one scan for each component */ +{ + int ci; + + for (ci = 0; ci < ncomps; ci++) { + scanptr->comps_in_scan = 1; + scanptr->component_index[0] = ci; + scanptr->Ss = Ss; + scanptr->Se = Se; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } + return scanptr; +} + +LOCAL(jpeg_scan_info *) +fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) +/* Support routine: generate interleaved DC scan if possible, else N scans */ +{ + int ci; + + if (ncomps <= MAX_COMPS_IN_SCAN) { + /* Single interleaved DC scan */ + scanptr->comps_in_scan = ncomps; + for (ci = 0; ci < ncomps; ci++) + scanptr->component_index[ci] = ci; + scanptr->Ss = scanptr->Se = 0; + scanptr->Ah = Ah; + scanptr->Al = Al; + scanptr++; + } else { + /* Noninterleaved DC scan for each component */ + scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + } + return scanptr; +} + + +/* + * Create a recommended progressive-JPEG script. + * cinfo->num_components and cinfo->jpeg_color_space must be correct. + */ + +GLOBAL(void) +jpeg_simple_progression (j_compress_ptr cinfo) +{ + int ncomps = cinfo->num_components; + int nscans; + jpeg_scan_info * scanptr; + + /* Safety check to ensure start_compress not called yet. */ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + /* Figure space needed for script. Calculation must match code below! */ + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + nscans = 10; + } else { + /* All-purpose script for other color spaces. */ + if (ncomps > MAX_COMPS_IN_SCAN) + nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */ + else + nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */ + } + + /* Allocate space for script. + * We need to put it in the permanent pool in case the application performs + * multiple compressions without changing the settings. To avoid a memory + * leak if jpeg_simple_progression is called repeatedly for the same JPEG + * object, we try to re-use previously allocated space, and we allocate + * enough space to handle YCbCr even if initially asked for grayscale. + */ + if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { + cinfo->script_space_size = MAX(nscans, 10); + cinfo->script_space = (jpeg_scan_info *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + } + scanptr = cinfo->script_space; + cinfo->scan_info = scanptr; + cinfo->num_scans = nscans; + + if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { + /* Custom script for YCbCr color images. */ + /* Initial DC scan */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + /* Initial AC scan: get some luma data out in a hurry */ + scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); + /* Chroma data is too small to be worth expending many scans on */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); + /* Complete spectral selection for luma AC */ + scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); + /* Refine next bit of luma AC */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); + /* Finish DC successive approximation */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + /* Finish AC successive approximation */ + scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); + /* Luma bottom bit comes last since it's usually largest scan */ + scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); + } else { + /* All-purpose script for other color spaces. */ + /* Successive approximation first pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); + /* Successive approximation second pass */ + scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); + /* Successive approximation final pass */ + scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); + } +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jcphuff.c b/Utilities/vtkjpeg/jcphuff.c new file mode 100644 index 0000000..07f9178 --- /dev/null +++ b/Utilities/vtkjpeg/jcphuff.c @@ -0,0 +1,833 @@ +/* + * jcphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy encoding routines for progressive JPEG. + * + * We do not support output suspension in this module, since the library + * currently does not allow multiple-scan files to be written with output + * suspension. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jchuff.h" /* Declarations shared with jchuff.c */ + +#ifdef C_PROGRESSIVE_SUPPORTED + +/* Expanded entropy encoder object for progressive Huffman encoding. */ + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* Bit-level coding status. + * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + INT32 put_buffer; /* current bit-accumulation buffer */ + int put_bits; /* # of bits now in it */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for DC components */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to derived tables (these workspaces have image lifespan). + * Since any one scan codes only DC or only AC, we only need one set + * of tables, not one for DC and one for AC. + */ + c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + /* Statistics tables for optimization; again, one set is enough */ + long * count_ptrs[NUM_HUFF_TBLS]; +} phuff_entropy_encoder; + +typedef phuff_entropy_encoder * phuff_entropy_ptr; + +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. + */ + +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +/* Forward declarations */ +METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); +METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); + + +/* + * Initialize for a Huffman-compressed scan using progressive JPEG. + */ + +METHODDEF(void) +start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + is_DC_band = (cinfo->Ss == 0); + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routines */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + if (gather_statistics) + entropy->pub.finish_pass = finish_pass_gather_phuff; + else + entropy->pub.finish_pass = finish_pass_phuff; + + /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 + * for AC coefficients. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + /* Get table index */ + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; + } + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->count_ptrs[tbl] == NULL) + entropy->count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman table */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + & entropy->derived_tbls[tbl]); + } + } + + /* Initialize AC stuff */ + entropy->EOBRUN = 0; + entropy->BE = 0; + + /* Initialize bit buffer to empty */ + entropy->put_buffer = 0; + entropy->put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ + +/* Emit a byte */ +#define emit_byte(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer(entropy); } + + +LOCAL(void) +dump_buffer (phuff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + +/* Outputting bits to the file */ + +/* Only the right 24 bits of put_buffer are used; the valid bits are + * left-justified in this part. At most 16 bits can be passed to emit_bits + * in one call, and we never retain more than 7 bits in put_buffer + * between calls, so 24 bits are sufficient. + */ + +INLINE +LOCAL(void) +emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ +{ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = entropy->put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */ + + put_bits += size; /* new number of bits in buffer */ + + put_buffer <<= 24 - put_bits; /* align incoming bits */ + + put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */ + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->put_buffer = put_buffer; /* update variables */ + entropy->put_bits = put_bits; +} + + +LOCAL(void) +flush_bits (phuff_entropy_ptr entropy) +{ + emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; + emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (phuff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (phuff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits(entropy); + emit_byte(entropy, 0xFF); + emit_byte(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->last_dc_val[ci]; + entropy->last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + register int r, k; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se = cinfo->Se; + int Al = cinfo->Al; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart(entropy, entropy->next_restart_num); + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[jpeg_natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; + emit_bits(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * Finish up at the end of a Huffman-compressed progressive scan. + */ + +METHODDEF(void) +finish_pass_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; +} + + +/* + * Finish up a statistics-gathering pass and create the new Huffman tables. + */ + +METHODDEF(void) +finish_pass_gather_phuff (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band; + int ci, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did[NUM_HUFF_TBLS]; + + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + + is_DC_band = (cinfo->Ss == 0); + + /* It's important not to apply jpeg_gen_optimal_table more than once + * per table, because it clobbers the input frequency counts! + */ + MEMZERO(did, SIZEOF(did)); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (is_DC_band) { + if (cinfo->Ah != 0) /* DC refinement needs no table */ + continue; + tbl = compptr->dc_tbl_no; + } else { + tbl = compptr->ac_tbl_no; + } + if (! did[tbl]) { + if (is_DC_band) + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + else + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); + did[tbl] = TRUE; + } + } +} + + +/* + * Module initialization routine for progressive Huffman entropy encoding. + */ + +GLOBAL(void) +jinit_phuff_encoder (j_compress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass_phuff; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + entropy->count_ptrs[i] = NULL; + } + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} + +#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jcprepct.c b/Utilities/vtkjpeg/jcprepct.c new file mode 100644 index 0000000..fa93333 --- /dev/null +++ b/Utilities/vtkjpeg/jcprepct.c @@ -0,0 +1,354 @@ +/* + * jcprepct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the compression preprocessing controller. + * This controller manages the color conversion, downsampling, + * and edge expansion steps. + * + * Most of the complexity here is associated with buffering input rows + * as required by the downsampler. See the comments at the head of + * jcsample.c for the downsampler's needs. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* At present, jcsample.c can request context rows only for smoothing. + * In the future, we might also need context rows for CCIR601 sampling + * or other more-complex downsampling procedures. The code to support + * context rows should be compiled only if needed. + */ +#ifdef INPUT_SMOOTHING_SUPPORTED +#define CONTEXT_ROWS_SUPPORTED +#endif + + +/* + * For the simple (no-context-row) case, we just need to buffer one + * row group's worth of pixels for the downsampling step. At the bottom of + * the image, we pad to a full row group by replicating the last pixel row. + * The downsampler's last output row is then replicated if needed to pad + * out to a full iMCU row. + * + * When providing context rows, we must buffer three row groups' worth of + * pixels. Three row groups are physically allocated, but the row pointer + * arrays are made five row groups high, with the extra pointers above and + * below "wrapping around" to point to the last and first real row groups. + * This allows the downsampler to access the proper context rows. + * At the top and bottom of the image, we create dummy context rows by + * copying the first or last real pixel row. This copying could be avoided + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + * trouble on the compression side. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_prep_controller pub; /* public fields */ + + /* Downsampling input buffer. This buffer holds color-converted data + * until we have enough to do a downsample step. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + JDIMENSION rows_to_go; /* counts rows remaining in source image */ + int next_buf_row; /* index of next row to store in color_buf */ + +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ + int this_row_group; /* starting row index of group to process */ + int next_buf_stop; /* downsample when we reach this index */ +#endif +} my_prep_controller; + +typedef my_prep_controller * my_prep_ptr; + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + + if (pass_mode != JBUF_PASS_THRU) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Initialize total-height counter for detecting bottom of image */ + prep->rows_to_go = cinfo->image_height; + /* Mark the conversion buffer empty */ + prep->next_buf_row = 0; +#ifdef CONTEXT_ROWS_SUPPORTED + /* Preset additional state variables for context mode. + * These aren't used in non-context mode, so we needn't test which mode. + */ + prep->this_row_group = 0; + /* Set next_buf_stop to stop after two row groups have been read in. */ + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; +#endif +} + + +/* + * Expand an image vertically from height input_rows to height output_rows, + * by duplicating the bottom row. + */ + +LOCAL(void) +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, + int input_rows, int output_rows) +{ + register int row; + + for (row = input_rows; row < output_rows; row++) { + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + } +} + + +/* + * Process some data in the simple no-context case. + * + * Preprocessor output data is counted in "row groups". A row group + * is defined to be v_samp_factor sample rows of each component. + * Downsampling will produce this much data from each max_v_samp_factor + * input rows. + */ + +METHODDEF(void) +pre_process_data (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + JDIMENSION inrows; + jpeg_component_info * compptr; + + while (*in_row_ctr < in_rows_avail && + *out_row_group_ctr < out_row_groups_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + /* If at bottom of image, pad to fill the conversion buffer. */ + if (prep->rows_to_go == 0 && + prep->next_buf_row < cinfo->max_v_samp_factor) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); + } + prep->next_buf_row = cinfo->max_v_samp_factor; + } + /* If we've filled the conversion buffer, empty it. */ + if (prep->next_buf_row == cinfo->max_v_samp_factor) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); + prep->next_buf_row = 0; + (*out_row_group_ctr)++; + } + /* If at bottom of image, pad the output to a full iMCU height. + * Note we assume the caller is providing a one-iMCU-height output buffer! + */ + if (prep->rows_to_go == 0 && + *out_row_group_ctr < out_row_groups_avail) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * DCTSIZE, + (int) (*out_row_group_ctr * compptr->v_samp_factor), + (int) (out_row_groups_avail * compptr->v_samp_factor)); + } + *out_row_group_ctr = out_row_groups_avail; + break; /* can exit outer loop without test */ + } + } +} + + +#ifdef CONTEXT_ROWS_SUPPORTED + +/* + * Process some data in the context case. + */ + +METHODDEF(void) +pre_process_context (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int numrows, ci; + int buf_height = cinfo->max_v_samp_factor * 3; + JDIMENSION inrows; + + while (*out_row_group_ctr < out_row_groups_avail) { + if (*in_row_ctr < in_rows_avail) { + /* Do color conversion to fill the conversion buffer. */ + inrows = in_rows_avail - *in_row_ctr; + numrows = prep->next_buf_stop - prep->next_buf_row; + numrows = (int) MIN((JDIMENSION) numrows, inrows); + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); + /* Pad at top of image, if first time through */ + if (prep->rows_to_go == cinfo->image_height) { + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } + } + *in_row_ctr += numrows; + prep->next_buf_row += numrows; + prep->rows_to_go -= numrows; + } else { + /* Return for more data, unless we are at the bottom of the image. */ + if (prep->rows_to_go != 0) + break; + /* When at bottom of image, pad to fill the conversion buffer. */ + if (prep->next_buf_row < prep->next_buf_stop) { + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; + } + } + /* If we've gotten enough data, downsample a row group. */ + if (prep->next_buf_row == prep->next_buf_stop) { + (*cinfo->downsample->downsample) (cinfo, + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); + (*out_row_group_ctr)++; + /* Advance pointers with wraparound as necessary. */ + prep->this_row_group += cinfo->max_v_samp_factor; + if (prep->this_row_group >= buf_height) + prep->this_row_group = 0; + if (prep->next_buf_row >= buf_height) + prep->next_buf_row = 0; + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; + } + } +} + + +/* + * Create the wrapped-around downsampling input buffer needed for context mode. + */ + +LOCAL(void) +create_context_buffer (j_compress_ptr cinfo) +{ + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; + int rgroup_height = cinfo->max_v_samp_factor; + int ci, i; + jpeg_component_info * compptr; + JSAMPARRAY true_buffer, fake_buffer; + + /* Grab enough space for fake row pointers for all the components; + * we need five row groups' worth of pointers for each component. + */ + fake_buffer = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate the actual buffer space (3 row groups) for this component. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + true_buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) (3 * rgroup_height)); + /* Copy true buffer row pointers into the middle of the fake row array */ + MEMCOPY(fake_buffer + rgroup_height, true_buffer, + 3 * rgroup_height * SIZEOF(JSAMPROW)); + /* Fill in the above and below wraparound pointers */ + for (i = 0; i < rgroup_height; i++) { + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; + } + prep->color_buf[ci] = fake_buffer + rgroup_height; + fake_buffer += 5 * rgroup_height; /* point to space for next component */ + } +} + +#endif /* CONTEXT_ROWS_SUPPORTED */ + + +/* + * Initialize preprocessing controller. + */ + +GLOBAL(void) +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) +{ + my_prep_ptr prep; + int ci; + jpeg_component_info * compptr; + + if (need_full_buffer) /* safety check */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + prep = (my_prep_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_prep_controller)); + cinfo->prep = (struct jpeg_c_prep_controller *) prep; + prep->pub.start_pass = start_pass_prep; + + /* Allocate the color conversion buffer. + * We make the buffer wide enough to allow the downsampler to edge-expand + * horizontally within the buffer, if it so chooses. + */ + if (cinfo->downsample->need_context_rows) { + /* Set up to provide context rows */ +#ifdef CONTEXT_ROWS_SUPPORTED + prep->pub.pre_process_data = pre_process_context; + create_context_buffer(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* No context, just make it tall enough for one row group */ + prep->pub.pre_process_data = pre_process_data; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/Utilities/vtkjpeg/jcsample.c b/Utilities/vtkjpeg/jcsample.c new file mode 100644 index 0000000..e5e072a --- /dev/null +++ b/Utilities/vtkjpeg/jcsample.c @@ -0,0 +1,520 @@ +/* + * jcsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains downsampling routines. + * + * Downsampling input data is counted in "row groups". A row group + * is defined to be max_v_samp_factor pixel rows of each component, + * from which the downsampler produces v_samp_factor sample rows. + * A single row group is processed in each call to the downsampler module. + * + * The downsampler is responsible for edge-expansion of its output data + * to fill an integral number of DCT blocks horizontally. The source buffer + * may be modified if it is helpful for this purpose (the source buffer is + * allocated wide enough to correspond to the desired output width). + * The caller (the prep controller) is responsible for vertical padding. + * + * The downsampler may request "context rows" by setting need_context_rows + * during startup. In this case, the input arrays will contain at least + * one row group's worth of pixels above and below the passed-in data; + * the caller will create dummy rows at image top and bottom by replicating + * the first or last real pixel row. + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + * + * The downsampling algorithm used here is a simple average of the source + * pixels covered by the output pixel. The hi-falutin sampling literature + * refers to this as a "box filter". In general the characteristics of a box + * filter are not very good, but for the specific cases we normally use (1:1 + * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + * nearly so bad. If you intend to use other sampling ratios, you'd be well + * advised to improve this code. + * + * A simple input-smoothing capability is provided. This is mainly intended + * for cleaning up color-dithered GIF input files (if you find it inadequate, + * we suggest using an external filtering program such as pnmconvol). When + * enabled, each input pixel P is replaced by a weighted sum of itself and its + * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + * where SF = (smoothing_factor / 1024). + * Currently, smoothing is only supported for 2h2v sampling factors. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to downsample a single component */ +typedef JMETHOD(void, downsample1_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); + +/* Private subobject */ + +typedef struct { + struct jpeg_downsampler pub; /* public fields */ + + /* Downsampling method pointers, one per component */ + downsample1_ptr methods[MAX_COMPONENTS]; +} my_downsampler; + +typedef my_downsampler * my_downsample_ptr; + + +/* + * Initialize for a downsampling pass. + */ + +METHODDEF(void) +start_pass_downsample (j_compress_ptr cinfo) +{ + cinfo = 0; + /* no work for now */ +} + + +/* + * Expand a component horizontally from width input_cols to width output_cols, + * by duplicating the rightmost samples. + */ + +LOCAL(void) +expand_right_edge (JSAMPARRAY image_data, int num_rows, + JDIMENSION input_cols, JDIMENSION output_cols) +{ + register JSAMPROW ptr; + register JSAMPLE pixval; + register int count; + int row; + int numcols = (int) (output_cols - input_cols); + + if (numcols > 0) { + for (row = 0; row < num_rows; row++) { + ptr = image_data[row] + input_cols; + pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ + for (count = numcols; count > 0; count--) + *ptr++ = pixval; + } + } +} + + +/* + * Do downsampling for a whole row group (all components). + * + * In this version we simply downsample each component independently. + */ + +METHODDEF(void) +sep_downsample (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) +{ + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; + int ci; + jpeg_component_info * compptr; + JSAMPARRAY in_ptr, out_ptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + in_ptr = input_buf[ci] + in_row_index; + out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); + (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); + } +} + + +/* + * Downsample pixel values of a single component. + * One row group is processed per call. + * This version handles arbitrary integral sampling ratios, without smoothing. + * Note that this version is not actually used for customary sampling ratios. + */ + +METHODDEF(void) +int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; + JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JSAMPROW inptr, outptr; + INT32 outvalue; + + h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; + v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + numpix = h_expand * v_expand; + numpix2 = numpix/2; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * h_expand); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + for (outcol = 0, outcol_h = 0; outcol < output_cols; + outcol++, outcol_h += h_expand) { + outvalue = 0; + for (v = 0; v < v_expand; v++) { + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (INT32) GETJSAMPLE(*inptr++); + } + } + *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); + } + inrow += v_expand; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * without smoothing. + */ + +METHODDEF(void) +fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + /* Copy the data */ + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo->max_v_samp_factor, cinfo->image_width); + /* Edge-expand */ + expand_right_edge(output_data, cinfo->max_v_samp_factor, + cinfo->image_width, compptr->width_in_blocks * DCTSIZE); +} + + +/* + * Downsample pixel values of a single component. + * This version handles the common case of 2:1 horizontal and 1:1 vertical, + * without smoothing. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + bias = 0; /* bias = 0,1,0,1,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + + bias) >> 1); + bias ^= 1; /* 0=>1, 1=>0 */ + inptr += 2; + } + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * without smoothing. + */ + +METHODDEF(void) +h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION outcol; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, outptr; + register int bias; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data, cinfo->max_v_samp_factor, + cinfo->image_width, output_cols * 2); + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + bias = 1; /* bias = 1,2,1,2,... for successive samples */ + for (outcol = 0; outcol < output_cols; outcol++) { + *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); + bias ^= 3; /* 1=>2, 2=>1 */ + inptr0 += 2; inptr1 += 2; + } + inrow += 2; + } +} + + +#ifdef INPUT_SMOOTHING_SUPPORTED + +/* + * Downsample pixel values of a single component. + * This version handles the standard case of 2:1 horizontal and 2:1 vertical, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int inrow, outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols * 2); + + /* We don't bother to form the individual "smoothed" input pixel values; + * we can directly compute the output which is the average of the four + * smoothed values. Each of the four member pixels contributes a fraction + * (1-8*SF) to its own smoothed image and a fraction SF to each of the three + * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + * output. The four corner-adjacent neighbor pixels contribute a fraction + * SF to just one smoothed pixel, or SF/4 to the final output; while the + * eight edge-adjacent neighbors contribute SF to each of two smoothed + * pixels, or SF/2 overall. In order to use integer arithmetic, these + * factors are scaled by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ + neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ + + inrow = 0; + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr0 = input_data[inrow]; + inptr1 = input_data[inrow+1]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+2]; + + /* Special case for first column: pretend column -1 is same as column 0 */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + neighsum += neighsum; + neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + /* sum of pixels directly mapped to this output element */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + /* sum of edge-neighbor pixels */ + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + /* The edge-neighbors count twice as much as corner-neighbors */ + neighsum += neighsum; + /* Add in the corner-neighbors */ + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + /* form final output scaled up by 2^16 */ + membersum = membersum * memberscale + neighsum * neighscale; + /* round, descale and output it */ + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + neighsum += neighsum; + neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + inrow += 2; + } +} + + +/* + * Downsample pixel values of a single component. + * This version handles the special case of a full-size component, + * with smoothing. One row of context is required. + */ + +METHODDEF(void) +fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data) +{ + int outrow; + JDIMENSION colctr; + JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + register JSAMPROW inptr, above_ptr, below_ptr, outptr; + INT32 membersum, neighsum, memberscale, neighscale; + int colsum, lastcolsum, nextcolsum; + + /* Expand input data enough to let all the output samples be generated + * by the standard loop. Special-casing padded output would be more + * efficient. + */ + expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, + cinfo->image_width, output_cols); + + /* Each of the eight neighbor pixels contributes a fraction SF to the + * smoothed pixel, while the main pixel contributes (1-8*SF). In order + * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. + * Also recall that SF = smoothing_factor / 1024. + */ + + memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ + neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ + + for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + outptr = output_data[outrow]; + inptr = input_data[outrow]; + above_ptr = input_data[outrow-1]; + below_ptr = input_data[outrow+1]; + + /* Special case for first column */ + colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + + GETJSAMPLE(*inptr); + membersum = GETJSAMPLE(*inptr++); + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = colsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + + for (colctr = output_cols - 2; colctr > 0; colctr--) { + membersum = GETJSAMPLE(*inptr++); + above_ptr++; below_ptr++; + nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + + GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + nextcolsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); + lastcolsum = colsum; colsum = nextcolsum; + } + + /* Special case for last column */ + membersum = GETJSAMPLE(*inptr); + neighsum = lastcolsum + (colsum - membersum) + colsum; + membersum = membersum * memberscale + neighsum * neighscale; + *outptr = (JSAMPLE) ((membersum + 32768) >> 16); + + } +} + +#endif /* INPUT_SMOOTHING_SUPPORTED */ + + +/* + * Module initialization routine for downsampling. + * Note that we must select a routine for each component. + */ + +GLOBAL(void) +jinit_downsampler (j_compress_ptr cinfo) +{ + my_downsample_ptr downsample; + int ci; + jpeg_component_info * compptr; + boolean smoothok = TRUE; + + downsample = (my_downsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_downsampler)); + cinfo->downsample = (struct jpeg_downsampler *) downsample; + downsample->pub.start_pass = start_pass_downsample; + downsample->pub.downsample = sep_downsample; + downsample->pub.need_context_rows = FALSE; + + if (cinfo->CCIR601_sampling) + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* Verify we can handle the sampling factors, and set up method pointers */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = fullsize_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor == cinfo->max_v_samp_factor) { + smoothok = FALSE; + downsample->methods[ci] = h2v1_downsample; + } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && + compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor) { + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; + } else +#endif + downsample->methods[ci] = h2v2_downsample; + } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && + (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + smoothok = FALSE; + downsample->methods[ci] = int_downsample; + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + } + +#ifdef INPUT_SMOOTHING_SUPPORTED + if (cinfo->smoothing_factor && !smoothok) + TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); +#endif +} diff --git a/Utilities/vtkjpeg/jctrans.c b/Utilities/vtkjpeg/jctrans.c new file mode 100644 index 0000000..f904083 --- /dev/null +++ b/Utilities/vtkjpeg/jctrans.c @@ -0,0 +1,390 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding compression, + * that is, writing raw DCT coefficient arrays to an output JPEG file. + * The routines in jcapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transencode_master_selection + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); +LOCAL(void) transencode_coef_controller + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + + +/* + * Compression initialization for writing raw-coefficient data. + * Before calling this, all parameters and a data destination must be set up. + * Call jpeg_finish_compress() to actually write the data. + * + * The number of passed virtual arrays must match cinfo->num_components. + * Note that the virtual arrays need not be filled or even realized at + * the time write_coefficients is called; indeed, if the virtual arrays + * were requested from this compression object's memory manager, they + * typically will be realized during this routine and filled afterwards. + */ + +GLOBAL(void) +jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) +{ + if (cinfo->global_state != CSTATE_START) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Mark all tables to be written */ + jpeg_suppress_tables(cinfo, FALSE); + /* (Re)initialize error mgr and destination modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->dest->init_destination) (cinfo); + /* Perform master selection of active modules */ + transencode_master_selection(cinfo, coef_arrays); + /* Wait for jpeg_finish_compress() call */ + cinfo->next_scanline = 0; /* so jpeg_write_marker works */ + cinfo->global_state = CSTATE_WRCOEFS; +} + + +/* + * Initialize the compression object with default parameters, + * then copy from the source object all parameters needed for lossless + * transcoding. Parameters that can be varied without loss (such as + * scan script and Huffman optimization) are left in their default states. + */ + +GLOBAL(void) +jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, + j_compress_ptr dstinfo) +{ + JQUANT_TBL ** qtblptr; + jpeg_component_info *incomp, *outcomp; + JQUANT_TBL *c_quant, *slot_quant; + int tblno, ci, coefi; + + /* Safety check to ensure start_compress not called yet. */ + if (dstinfo->global_state != CSTATE_START) + ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); + /* Copy fundamental image dimensions */ + dstinfo->image_width = srcinfo->image_width; + dstinfo->image_height = srcinfo->image_height; + dstinfo->input_components = srcinfo->num_components; + dstinfo->in_color_space = srcinfo->jpeg_color_space; + /* Initialize all parameters to default values */ + jpeg_set_defaults(dstinfo); + /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. + * Fix it to get the right header markers for the image colorspace. + */ + jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); + dstinfo->data_precision = srcinfo->data_precision; + dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; + /* Copy the source's quantization tables. */ + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { + qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; + if (*qtblptr == NULL) + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + MEMCOPY((*qtblptr)->quantval, + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); + (*qtblptr)->sent_table = FALSE; + } + } + /* Copy the source's per-component info. + * Note we assume jpeg_set_defaults has allocated the dest comp_info array. + */ + dstinfo->num_components = srcinfo->num_components; + if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) + ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, + MAX_COMPONENTS); + for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; + ci < dstinfo->num_components; ci++, incomp++, outcomp++) { + outcomp->component_id = incomp->component_id; + outcomp->h_samp_factor = incomp->h_samp_factor; + outcomp->v_samp_factor = incomp->v_samp_factor; + outcomp->quant_tbl_no = incomp->quant_tbl_no; + /* Make sure saved quantization table for component matches the qtable + * slot. If not, the input file re-used this qtable slot. + * IJG encoder currently cannot duplicate this. + */ + tblno = outcomp->quant_tbl_no; + if (tblno < 0 || tblno >= NUM_QUANT_TBLS || + srcinfo->quant_tbl_ptrs[tblno] == NULL) + ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); + slot_quant = srcinfo->quant_tbl_ptrs[tblno]; + c_quant = incomp->quant_table; + if (c_quant != NULL) { + for (coefi = 0; coefi < DCTSIZE2; coefi++) { + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + } + } + /* Note: we do not copy the source's Huffman table assignments; + * instead we rely on jpeg_set_colorspace to have made a suitable choice. + */ + } + /* Also copy JFIF version and resolution information, if available. + * Strictly speaking this isn't "critical" info, but it's nearly + * always appropriate to copy it if available. In particular, + * if the application chooses to copy JFIF 1.02 extension markers from + * the source file, we need to copy the version to make sure we don't + * emit a file that has 1.02 extensions but a claimed version of 1.01. + * We will *not*, however, copy version info from mislabeled "2.01" files. + */ + if (srcinfo->saw_JFIF_marker) { + if (srcinfo->JFIF_major_version == 1) { + dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; + dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; + } + dstinfo->density_unit = srcinfo->density_unit; + dstinfo->X_density = srcinfo->X_density; + dstinfo->Y_density = srcinfo->Y_density; + } +} + + +/* + * Master selection of compression modules for transcoding. + * This substitutes for jcinit.c's initialization of the full compressor. + */ + +LOCAL(void) +transencode_master_selection (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + /* Although we don't actually use input_components for transcoding, + * jcmaster.c's initial_setup will complain if input_components is 0. + */ + cinfo->input_components = 1; + /* Initialize master control (includes parameter checking/processing) */ + jinit_c_master_control(cinfo, TRUE /* transcode only */); + + /* Entropy encoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef C_PROGRESSIVE_SUPPORTED + jinit_phuff_encoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_encoder(cinfo); + } + + /* We need a special coefficient buffer controller. */ + transencode_coef_controller(cinfo, coef_arrays); + + jinit_marker_writer(cinfo); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Write the datastream header (SOI, JFIF) immediately. + * Frame and scan headers are postponed till later. + * This lets application insert special markers after the SOI. + */ + (*cinfo->marker->write_file_header) (cinfo); +} + + +/* + * The rest of this file is a special implementation of the coefficient + * buffer controller. This is similar to jccoefct.c, but it handles only + * output from presupplied virtual arrays. Furthermore, we generate any + * dummy padding blocks on-the-fly rather than expecting them to be present + * in the arrays. + */ + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_c_coef_controller pub; /* public fields */ + + JDIMENSION iMCU_row_num; /* iMCU row # within image */ + JDIMENSION mcu_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* Virtual block array for each component. */ + jvirt_barray_ptr * whole_image; + + /* Workspace for constructing dummy blocks at right/bottom edges. */ + JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + + +LOCAL(void) +start_iMCU_row (j_compress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->mcu_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + if (pass_mode != JBUF_CRANK_DEST) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + coef->iMCU_row_num = 0; + start_iMCU_row(cinfo); +} + + +/* + * Process some data. + * We process the equivalent of one fully interleaved MCU row ("iMCU" row) + * per call, ie, v_samp_factor block rows for each component in the scan. + * The data is obtained from the virtual arrays and fed to the entropy coder. + * Returns TRUE if the iMCU row is completed, FALSE if suspended. + * + * NB: input_buf is ignored; it is likely to be a NULL pointer. + */ + +METHODDEF(boolean) +compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, blockcnt; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + input_buf = 0; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + coef->iMCU_row_num * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } + } + /* Try to write the MCU. */ + if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->mcu_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + coef->iMCU_row_num++; + start_iMCU_row(cinfo); + return TRUE; +} + + +/* + * Initialize coefficient buffer controller. + * + * Each passed coefficient array must be the right size for that + * coefficient: width_in_blocks wide and height_in_blocks high, + * with unitheight at least v_samp_factor. + */ + +LOCAL(void) +transencode_coef_controller (j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays) +{ + my_coef_ptr coef; + JBLOCKROW buffer; + int i; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_c_coef_controller *) coef; + coef->pub.start_pass = start_pass_coef; + coef->pub.compress_data = compress_output; + + /* Save pointer to virtual arrays */ + coef->whole_image = coef_arrays; + + /* Allocate and pre-zero space for dummy DCT blocks. */ + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { + coef->dummy_buffer[i] = buffer + i; + } +} diff --git a/Utilities/vtkjpeg/jdapimin.c b/Utilities/vtkjpeg/jdapimin.c new file mode 100644 index 0000000..cadb59f --- /dev/null +++ b/Utilities/vtkjpeg/jdapimin.c @@ -0,0 +1,395 @@ +/* + * jdapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "minimum" API routines that may be + * needed in either the normal full-decompression case or the + * transcoding-only case. + * + * Most of the routines intended to be called directly by an application + * are in this file or in jdapistd.c. But also see jcomapi.c for routines + * shared by compression and decompression, and jdtrans.c for the transcoding + * case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * Initialization of a JPEG decompression object. + * The error manager must already be set up (in case memory manager fails). + */ + +GLOBAL(void) +jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) +{ + int i; + + /* Guard against version mismatches between library and caller. */ + cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */ + if (version != JPEG_LIB_VERSION) + ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize != SIZEOF(struct jpeg_decompress_struct)) + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + + /* For debugging purposes, we zero the whole master structure. + * But the application has already set the err pointer, and may have set + * client_data, so we have to save and restore those fields. + * Note: if application hasn't set client_data, tools like Purify may + * complain here. + */ + { + struct jpeg_error_mgr * err = cinfo->err; + void * client_data = cinfo->client_data; /* ignore Purify complaint here */ + MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); + cinfo->err = err; + cinfo->client_data = client_data; + } + cinfo->is_decompressor = TRUE; + + /* Initialize a memory manager instance for this object */ + jinit_memory_mgr((j_common_ptr) cinfo); + + /* Zero out pointers to permanent structures. */ + cinfo->progress = NULL; + cinfo->src = NULL; + + for (i = 0; i < NUM_QUANT_TBLS; i++) + cinfo->quant_tbl_ptrs[i] = NULL; + + for (i = 0; i < NUM_HUFF_TBLS; i++) { + cinfo->dc_huff_tbl_ptrs[i] = NULL; + cinfo->ac_huff_tbl_ptrs[i] = NULL; + } + + /* Initialize marker processor so application can override methods + * for COM, APPn markers before calling jpeg_read_header. + */ + cinfo->marker_list = NULL; + jinit_marker_reader(cinfo); + + /* And initialize the overall input controller. */ + jinit_input_controller(cinfo); + + /* OK, I'm ready */ + cinfo->global_state = DSTATE_START; +} + + +/* + * Destruction of a JPEG decompression object + */ + +GLOBAL(void) +jpeg_destroy_decompress (j_decompress_ptr cinfo) +{ + jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Abort processing of a JPEG decompression operation, + * but don't destroy the object itself. + */ + +GLOBAL(void) +jpeg_abort_decompress (j_decompress_ptr cinfo) +{ + jpeg_abort((j_common_ptr) cinfo); /* use common routine */ +} + + +/* + * Set default decompression parameters. + */ + +LOCAL(void) +default_decompress_parms (j_decompress_ptr cinfo) +{ + /* Guess the input colorspace, and set output colorspace accordingly. */ + /* (Wish JPEG committee had provided a real way to specify this...) */ + /* Note application may override our guesses. */ + switch (cinfo->num_components) { + case 1: + cinfo->jpeg_color_space = JCS_GRAYSCALE; + cinfo->out_color_space = JCS_GRAYSCALE; + break; + + case 3: + if (cinfo->saw_JFIF_marker) { + cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ + } else if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_RGB; + break; + case 1: + cinfo->jpeg_color_space = JCS_YCbCr; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; + } + } else { + /* Saw no special markers, try to guess from the component IDs */ + int cid0 = cinfo->comp_info[0].component_id; + int cid1 = cinfo->comp_info[1].component_id; + int cid2 = cinfo->comp_info[2].component_id; + + if (cid0 == 1 && cid1 == 2 && cid2 == 3) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ + else if (cid0 == 82 && cid1 == 71 && cid2 == 66) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else { + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + } + } + /* Always guess RGB is proper output colorspace. */ + cinfo->out_color_space = JCS_RGB; + break; + + case 4: + if (cinfo->saw_Adobe_marker) { + switch (cinfo->Adobe_transform) { + case 0: + cinfo->jpeg_color_space = JCS_CMYK; + break; + case 2: + cinfo->jpeg_color_space = JCS_YCCK; + break; + default: + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; + } + } else { + /* No special markers, assume straight CMYK. */ + cinfo->jpeg_color_space = JCS_CMYK; + } + cinfo->out_color_space = JCS_CMYK; + break; + + default: + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->out_color_space = JCS_UNKNOWN; + break; + } + + /* Set defaults for other decompression parameters. */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; + cinfo->output_gamma = 1.0; + cinfo->buffered_image = FALSE; + cinfo->raw_data_out = FALSE; + cinfo->dct_method = JDCT_DEFAULT; + cinfo->do_fancy_upsampling = TRUE; + cinfo->do_block_smoothing = TRUE; + cinfo->quantize_colors = FALSE; + /* We set these in case application only sets quantize_colors. */ + cinfo->dither_mode = JDITHER_FS; +#ifdef QUANT_2PASS_SUPPORTED + cinfo->two_pass_quantize = TRUE; +#else + cinfo->two_pass_quantize = FALSE; +#endif + cinfo->desired_number_of_colors = 256; + cinfo->colormap = NULL; + /* Initialize for no mode change in buffered-image mode. */ + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; +} + + +/* + * Decompression startup: read start of JPEG datastream to see what's there. + * Need only initialize JPEG object and supply a data source before calling. + * + * This routine will read as far as the first SOS marker (ie, actual start of + * compressed data), and will save all tables and parameters in the JPEG + * object. It will also initialize the decompression parameters to default + * values, and finally return JPEG_HEADER_OK. On return, the application may + * adjust the decompression parameters and then call jpeg_start_decompress. + * (Or, if the application only wanted to determine the image parameters, + * the data need not be decompressed. In that case, call jpeg_abort or + * jpeg_destroy to release any temporary space.) + * If an abbreviated (tables only) datastream is presented, the routine will + * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + * re-use the JPEG object to read the abbreviated image datastream(s). + * It is unnecessary (but OK) to call jpeg_abort in this case. + * The JPEG_SUSPENDED return code only occurs if the data source module + * requests suspension of the decompressor. In this case the application + * should load more source data and then re-call jpeg_read_header to resume + * processing. + * If a non-suspending data source is used and require_image is TRUE, then the + * return code need not be inspected since only JPEG_HEADER_OK is possible. + * + * This routine is now just a front end to jpeg_consume_input, with some + * extra error checking. + */ + +GLOBAL(int) +jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) +{ + int retcode; + + if (cinfo->global_state != DSTATE_START && + cinfo->global_state != DSTATE_INHEADER) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + retcode = jpeg_consume_input(cinfo); + + switch (retcode) { + case JPEG_REACHED_SOS: + retcode = JPEG_HEADER_OK; + break; + case JPEG_REACHED_EOI: + if (require_image) /* Complain if application wanted an image */ + ERREXIT(cinfo, JERR_NO_IMAGE); + /* Reset to start state; it would be safer to require the application to + * call jpeg_abort, but we can't change it now for compatibility reasons. + * A side effect is to free any temporary memory (there shouldn't be any). + */ + jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ + retcode = JPEG_HEADER_TABLES_ONLY; + break; + case JPEG_SUSPENDED: + /* no work */ + break; + } + + return retcode; +} + + +/* + * Consume data in advance of what the decompressor requires. + * This can be called at any time once the decompressor object has + * been created and a data source has been set up. + * + * This routine is essentially a state machine that handles a couple + * of critical state-transition actions, namely initial setup and + * transition from header scanning to ready-for-start_decompress. + * All the actual input is done via the input controller's consume_input + * method. + */ + +GLOBAL(int) +jpeg_consume_input (j_decompress_ptr cinfo) +{ + int retcode = JPEG_SUSPENDED; + + /* NB: every possible DSTATE value should be listed in this switch */ + switch (cinfo->global_state) { + case DSTATE_START: + /* Start-of-datastream actions: reset appropriate modules */ + (*cinfo->inputctl->reset_input_controller) (cinfo); + /* Initialize application's data source module */ + (*cinfo->src->init_source) (cinfo); + cinfo->global_state = DSTATE_INHEADER; + /*FALLTHROUGH*/ + case DSTATE_INHEADER: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ + /* Set up default parameters based on header data */ + default_decompress_parms(cinfo); + /* Set global state: ready for start_decompress */ + cinfo->global_state = DSTATE_READY; + } + break; + case DSTATE_READY: + /* Can't advance past first SOS until start_decompress is called */ + retcode = JPEG_REACHED_SOS; + break; + case DSTATE_PRELOAD: + case DSTATE_PRESCAN: + case DSTATE_SCANNING: + case DSTATE_RAW_OK: + case DSTATE_BUFIMAGE: + case DSTATE_BUFPOST: + case DSTATE_STOPPING: + retcode = (*cinfo->inputctl->consume_input) (cinfo); + break; + default: + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + return retcode; +} + + +/* + * Have we finished reading the input file? + */ + +GLOBAL(boolean) +jpeg_input_complete (j_decompress_ptr cinfo) +{ + /* Check for valid jpeg object */ + if (cinfo->global_state < DSTATE_START || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->eoi_reached; +} + + +/* + * Is there more than one scan? + */ + +GLOBAL(boolean) +jpeg_has_multiple_scans (j_decompress_ptr cinfo) +{ + /* Only valid after jpeg_read_header completes */ + if (cinfo->global_state < DSTATE_READY || + cinfo->global_state > DSTATE_STOPPING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return cinfo->inputctl->has_multiple_scans; +} + + +/* + * Finish JPEG decompression. + * + * This will normally just verify the file trailer and release temp storage. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_decompress (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { + /* Terminate final pass of non-buffered mode */ + if (cinfo->output_scanline < cinfo->output_height) + ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state == DSTATE_BUFIMAGE) { + /* Finishing after a buffered-image operation */ + cinfo->global_state = DSTATE_STOPPING; + } else if (cinfo->global_state != DSTATE_STOPPING) { + /* STOPPING = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read until EOI */ + while (! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + /* Do final cleanup */ + (*cinfo->src->term_source) (cinfo); + /* We can use jpeg_abort to release memory and reset global_state */ + jpeg_abort((j_common_ptr) cinfo); + return TRUE; +} diff --git a/Utilities/vtkjpeg/jdapistd.c b/Utilities/vtkjpeg/jdapistd.c new file mode 100644 index 0000000..c8e3fa0 --- /dev/null +++ b/Utilities/vtkjpeg/jdapistd.c @@ -0,0 +1,275 @@ +/* + * jdapistd.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains application interface code for the decompression half + * of the JPEG library. These are the "standard" API routines that are + * used in the normal full-decompression case. They are not used by a + * transcoding-only application. Note that if an application links in + * jpeg_start_decompress, it will end up linking in the entire decompressor. + * We thus must separate this file from jdapimin.c to avoid linking the + * whole decompression library into a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); + + +/* + * Decompression initialization. + * jpeg_read_header must be completed before calling this. + * + * If a multipass operating mode was selected, this will do all but the + * last pass, and thus may take a great deal of time. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_start_decompress (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize master control, select active modules */ + jinit_master_decompress(cinfo); + if (cinfo->buffered_image) { + /* No more work here; expecting jpeg_start_output next */ + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; + } + cinfo->global_state = DSTATE_PRELOAD; + } + if (cinfo->global_state == DSTATE_PRELOAD) { + /* If file has multiple scans, absorb them all into the coef buffer */ + if (cinfo->inputctl->has_multiple_scans) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + } + cinfo->output_scan_number = cinfo->input_scan_number; + } else if (cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Perform any dummy output passes, and set up for the final pass */ + return output_pass_setup(cinfo); +} + + +/* + * Set up for an output pass, and perform any dummy pass(es) needed. + * Common subroutine for jpeg_start_decompress and jpeg_start_output. + * Entry: global_state = DSTATE_PRESCAN only if previously suspended. + * Exit: If done, returns TRUE and sets global_state for proper output mode. + * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. + */ + +LOCAL(boolean) +output_pass_setup (j_decompress_ptr cinfo) +{ + if (cinfo->global_state != DSTATE_PRESCAN) { + /* First call: do pass setup */ + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; + cinfo->global_state = DSTATE_PRESCAN; + } + /* Loop over any required dummy passes */ + while (cinfo->master->is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Crank through the dummy pass */ + while (cinfo->output_scanline < cinfo->output_height) { + JDIMENSION last_scanline; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + /* Process some data */ + last_scanline = cinfo->output_scanline; + (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, + &cinfo->output_scanline, (JDIMENSION) 0); + if (cinfo->output_scanline == last_scanline) + return FALSE; /* No progress made, must suspend */ + } + /* Finish up dummy pass, and set up for another one */ + (*cinfo->master->finish_output_pass) (cinfo); + (*cinfo->master->prepare_for_output_pass) (cinfo); + cinfo->output_scanline = 0; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } + /* Ready for application to drive output pass through + * jpeg_read_scanlines or jpeg_read_raw_data. + */ + cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; + return TRUE; +} + + +/* + * Read some scanlines of data from the JPEG decompressor. + * + * The return value will be the number of lines actually read. + * This may be less than the number requested in several cases, + * including bottom of image, data source suspension, and operating + * modes that emit multiple scanlines at a time. + * + * Note: we warn about excess calls to jpeg_read_scanlines() since + * this likely signals an application programmer error. However, + * an oversize buffer (max_lines > scanlines remaining) is not an error. + */ + +GLOBAL(JDIMENSION) +jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, + JDIMENSION max_lines) +{ + JDIMENSION row_ctr; + + if (cinfo->global_state != DSTATE_SCANNING) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Process some data */ + row_ctr = 0; + (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); + cinfo->output_scanline += row_ctr; + return row_ctr; +} + + +/* + * Alternate entry point to read raw data. + * Processes exactly one iMCU row per call, unless suspended. + */ + +GLOBAL(JDIMENSION) +jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, + JDIMENSION max_lines) +{ + JDIMENSION lines_per_iMCU_row; + + if (cinfo->global_state != DSTATE_RAW_OK) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + if (cinfo->output_scanline >= cinfo->output_height) { + WARNMS(cinfo, JWRN_TOO_MUCH_DATA); + return 0; + } + + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) { + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + } + + /* Verify that at least one iMCU row can be returned. */ + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; + if (max_lines < lines_per_iMCU_row) + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* Decompress directly into user's buffer. */ + if (! (*cinfo->coef->decompress_data) (cinfo, data)) + return 0; /* suspension forced, can do nothing more */ + + /* OK, we processed one iMCU row. */ + cinfo->output_scanline += lines_per_iMCU_row; + return lines_per_iMCU_row; +} + + +/* Additional entry points for buffered-image mode. */ + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Initialize for an output pass in buffered-image mode. + */ + +GLOBAL(boolean) +jpeg_start_output (j_decompress_ptr cinfo, int scan_number) +{ + if (cinfo->global_state != DSTATE_BUFIMAGE && + cinfo->global_state != DSTATE_PRESCAN) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Limit scan number to valid range */ + if (scan_number <= 0) + scan_number = 1; + if (cinfo->inputctl->eoi_reached && + scan_number > cinfo->input_scan_number) + scan_number = cinfo->input_scan_number; + cinfo->output_scan_number = scan_number; + /* Perform any dummy output passes, and set up for the real pass */ + return output_pass_setup(cinfo); +} + + +/* + * Finish up after an output pass in buffered-image mode. + * + * Returns FALSE if suspended. The return value need be inspected only if + * a suspending data source is used. + */ + +GLOBAL(boolean) +jpeg_finish_output (j_decompress_ptr cinfo) +{ + if ((cinfo->global_state == DSTATE_SCANNING || + cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { + /* Terminate this pass. */ + /* We do not require the whole pass to have been completed. */ + (*cinfo->master->finish_output_pass) (cinfo); + cinfo->global_state = DSTATE_BUFPOST; + } else if (cinfo->global_state != DSTATE_BUFPOST) { + /* BUFPOST = repeat call after a suspension, anything else is error */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + } + /* Read markers looking for SOS or EOI */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) + return FALSE; /* Suspend, come back later */ + } + cinfo->global_state = DSTATE_BUFIMAGE; + return TRUE; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jdatadst.c b/Utilities/vtkjpeg/jdatadst.c new file mode 100644 index 0000000..a8f6fb0 --- /dev/null +++ b/Utilities/vtkjpeg/jdatadst.c @@ -0,0 +1,151 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains compression data destination routines for the case of + * emitting JPEG data to a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * destination manager. + * IMPORTANT: we assume that fwrite() will correctly transcribe an array of + * JOCTETs into 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data destination object for stdio output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + FILE * outfile; /* target stream */ + JOCTET * buffer; /* start of buffer */ +} my_destination_mgr; + +typedef my_destination_mgr * my_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != + (size_t) OUTPUT_BUF_SIZE) + ERREXIT(cinfo, JERR_FILE_WRITE); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + /* Write any data remaining in the buffer */ + if (datacount > 0) { + if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) + ERREXIT(cinfo, JERR_FILE_WRITE); + } + fflush(dest->outfile); + /* Make sure we wrote the output file OK */ + if (ferror(dest->outfile)) + ERREXIT(cinfo, JERR_FILE_WRITE); +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +GLOBAL(void) +jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) +{ + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_destination_mgr)); + } + + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; +} diff --git a/Utilities/vtkjpeg/jdatasrc.c b/Utilities/vtkjpeg/jdatasrc.c new file mode 100644 index 0000000..e1ab975 --- /dev/null +++ b/Utilities/vtkjpeg/jdatasrc.c @@ -0,0 +1,213 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains decompression data source routines for the case of + * reading JPEG data from a file (or any stdio stream). While these routines + * are sufficient for most applications, some will want to use a different + * source manager. + * IMPORTANT: we assume that fread() will correctly transcribe an array of + * JOCTETs from 8-bit-wide elements on external storage. If char is wider + * than 8 bits on your machine, you may need to do some tweaking. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + + +/* Expanded data source object for stdio input */ + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + FILE * infile; /* source stream */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; + +typedef my_source_mgr * my_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes; + + nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + my_src_ptr src = (my_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * An additional method that can be provided by data source modules is the + * resync_to_restart method for error recovery in the presence of RST markers. + * For the moment, this source module just uses the default resync method + * provided by the JPEG library. That method assumes that no backtracking + * is possible. + */ + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + cinfo=cinfo; + /* no work necessary here */ +} + + +/* + * Prepare for input from a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +GLOBAL(void) +jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) +{ + my_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_stdio_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * SIZEOF(JOCTET)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} diff --git a/Utilities/vtkjpeg/jdcoefct.c b/Utilities/vtkjpeg/jdcoefct.c new file mode 100644 index 0000000..0430329 --- /dev/null +++ b/Utilities/vtkjpeg/jdcoefct.c @@ -0,0 +1,737 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the coefficient buffer controller for decompression. + * This controller is the top level of the JPEG decompressor proper. + * The coefficient buffer lies between entropy decoding and inverse-DCT steps. + * + * In buffered-image mode, this controller is the interface between + * input-oriented processing and output-oriented processing. + * Also, the input side (only) is used when reading a file for transcoding. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* Block smoothing is only applicable for progressive JPEG, so: */ +#ifndef D_PROGRESSIVE_SUPPORTED +#undef BLOCK_SMOOTHING_SUPPORTED +#endif + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_coef_controller pub; /* public fields */ + + /* These variables keep track of the current location of the input side. */ + /* cinfo->input_iMCU_row is also used for this. */ + JDIMENSION MCU_ctr; /* counts MCUs processed in current row */ + int MCU_vert_offset; /* counts MCU rows within iMCU row */ + int MCU_rows_per_iMCU_row; /* number of such rows needed */ + + /* The output side's location is represented by cinfo->output_iMCU_row. */ + + /* In single-pass modes, it's sufficient to buffer just one MCU. + * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, + * and let the entropy decoder write into that workspace each time. + * (On 80x86, the workspace is FAR even though it's not really very big; + * this is to keep the module interfaces unchanged when a large coefficient + * buffer is necessary.) + * In multi-pass modes, this array points to the current MCU's blocks + * within the virtual arrays; it is used only by the input side. + */ + JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU]; + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* In multi-pass modes, we need a virtual block array for each component. */ + jvirt_barray_ptr whole_image[MAX_COMPONENTS]; +#endif + +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* When doing block smoothing, we latch coefficient Al values here */ + int * coef_bits_latch; +#define SAVED_COEFS 6 /* we save coef_bits[0..5] */ +#endif +} my_coef_controller; + +typedef my_coef_controller * my_coef_ptr; + +/* Forward declarations */ +METHODDEF(int) decompress_onepass + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#ifdef D_MULTISCAN_FILES_SUPPORTED +METHODDEF(int) decompress_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif +#ifdef BLOCK_SMOOTHING_SUPPORTED +LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); +METHODDEF(int) decompress_smooth_data + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); +#endif + + +LOCAL(void) +start_iMCU_row (j_decompress_ptr cinfo) +/* Reset within-iMCU-row counters for a new row (input side) */ +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* In an interleaved scan, an MCU row is the same as an iMCU row. + * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + * But at the bottom of the image, process only what's left. + */ + if (cinfo->comps_in_scan > 1) { + coef->MCU_rows_per_iMCU_row = 1; + } else { + if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1)) + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; + else + coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; + } + + coef->MCU_ctr = 0; + coef->MCU_vert_offset = 0; +} + + +/* + * Initialize for an input processing pass. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + cinfo->input_iMCU_row = 0; + start_iMCU_row(cinfo); +} + + +/* + * Initialize for an output processing pass. + */ + +METHODDEF(void) +start_output_pass (j_decompress_ptr cinfo) +{ +#ifdef BLOCK_SMOOTHING_SUPPORTED + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + + /* If multipass, check to see whether to use block smoothing on this pass */ + if (coef->pub.coef_arrays != NULL) { + if (cinfo->do_block_smoothing && smoothing_ok(cinfo)) + coef->pub.decompress_data = decompress_smooth_data; + else + coef->pub.decompress_data = decompress_data; + } +#endif + cinfo->output_iMCU_row = 0; +} + + +/* + * Decompress and return some data in the single-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Input and output must run in lockstep since we have only a one-MCU buffer. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image, + * which we index according to the component's SOF position. + */ + +METHODDEF(int) +decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + int blkn, ci, xindex, yindex, yoffset, useful_width; + JSAMPARRAY output_ptr; + JDIMENSION start_col, output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Loop to process as much as one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; + MCU_col_num++) { + /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ + jzero_far((void FAR *) coef->MCU_buffer[0], + (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + /* Determine where data should go in output_buf and do the IDCT thing. + * We skip dummy blocks at the right and bottom edges (but blkn gets + * incremented past them!). Note the inner loop relies on having + * allocated the MCU_buffer[] blocks sequentially. + */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_blocks; + continue; + } + inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->DCT_scaled_size; + start_col = MCU_col_num * compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += compptr->DCT_scaled_size; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->DCT_scaled_size; + } + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + cinfo->output_iMCU_row++; + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Dummy consume-input routine for single-pass operation. + */ + +METHODDEF(int) +dummy_consume_data (j_decompress_ptr cinfo) +{ + cinfo = 0; + return JPEG_SUSPENDED; /* Always indicate nothing was done */ +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Consume input data and store it in the full-image coefficient buffer. + * We read as much as one fully interleaved MCU row ("iMCU" row) per call, + * ie, v_samp_factor block rows for each component in the scan. + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + */ + +METHODDEF(int) +consume_data (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION MCU_col_num; /* index of current MCU within row */ + int blkn, ci, xindex, yindex, yoffset; + JDIMENSION start_col; + JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; + JBLOCKROW buffer_ptr; + jpeg_component_info *compptr; + + /* Align the virtual buffers for the components used in this scan. */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + buffer[ci] = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], + cinfo->input_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, TRUE); + /* Note: entropy decoder expects buffer to be zeroed, + * but this is handled automatically by the memory manager + * because we requested a pre-zeroed array. + */ + } + + /* Loop to process one whole iMCU row */ + for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; + yoffset++) { + for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; + MCU_col_num++) { + /* Construct list of pointers to DCT blocks belonging to this MCU */ + blkn = 0; /* index of current DCT block within MCU */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } + } + /* Try to fetch the MCU. */ + if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; + } + } + /* Completed an MCU row, but perhaps not an iMCU row */ + coef->MCU_ctr = 0; + } + /* Completed the iMCU row, advance counters for next one */ + if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { + start_iMCU_row(cinfo); + return JPEG_ROW_COMPLETED; + } + /* Completed the scan */ + (*cinfo->inputctl->finish_input_pass) (cinfo); + return JPEG_SCAN_COMPLETED; +} + + +/* + * Decompress and return some data in the multi-pass case. + * Always attempts to emit one fully interleaved MCU row ("iMCU" row). + * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + * + * NB: output_buf contains a plane for each component in image. + */ + +METHODDEF(int) +decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num; + int ci, block_row, block_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number < cinfo->output_scan_number || + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Align the virtual buffer for this component. */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + cinfo->output_iMCU_row * compptr->v_samp_factor, + (JDIMENSION) compptr->v_samp_factor, FALSE); + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) + block_rows = compptr->v_samp_factor; + else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + } + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + output_col = 0; + for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += compptr->DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +#ifdef BLOCK_SMOOTHING_SUPPORTED + +/* + * This code applies interblock smoothing as described by section K.8 + * of the JPEG standard: the first 5 AC coefficients are estimated from + * the DC values of a DCT block and its 8 neighboring blocks. + * We apply smoothing only for progressive JPEG decoding, and only if + * the coefficients it can estimate are not yet known to full precision. + */ + +/* Natural-order array positions of the first 5 zigzag-order coefficients */ +#define Q01_POS 1 +#define Q10_POS 8 +#define Q20_POS 16 +#define Q11_POS 9 +#define Q02_POS 2 + +/* + * Determine whether block smoothing is applicable and safe. + * We also latch the current states of the coef_bits[] entries for the + * AC coefficients; otherwise, if the input side of the decompressor + * advances into a new scan, we might think the coefficients are known + * more accurately than they really are. + */ + +LOCAL(boolean) +smoothing_ok (j_decompress_ptr cinfo) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + boolean smoothing_useful = FALSE; + int ci, coefi; + jpeg_component_info *compptr; + JQUANT_TBL * qtable; + int * coef_bits; + int * coef_bits_latch; + + if (! cinfo->progressive_mode || cinfo->coef_bits == NULL) + return FALSE; + + /* Allocate latch area if not already done */ + if (coef->coef_bits_latch == NULL) + coef->coef_bits_latch = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); + coef_bits_latch = coef->coef_bits_latch; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* All components' quantization values must already be latched. */ + if ((qtable = compptr->quant_table) == NULL) + return FALSE; + /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ + if (qtable->quantval[0] == 0 || + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) + return FALSE; + /* DC values must be at least partly known for all components. */ + coef_bits = cinfo->coef_bits[ci]; + if (coef_bits[0] < 0) + return FALSE; + /* Block smoothing is helpful if some AC coefficients remain inaccurate. */ + for (coefi = 1; coefi <= 5; coefi++) { + coef_bits_latch[coefi] = coef_bits[coefi]; + if (coef_bits[coefi] != 0) + smoothing_useful = TRUE; + } + coef_bits_latch += SAVED_COEFS; + } + + return smoothing_useful; +} + + +/* + * Variant of decompress_data for use when doing block smoothing. + */ + +METHODDEF(int) +decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) +{ + my_coef_ptr coef = (my_coef_ptr) cinfo->coef; + JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; + JDIMENSION block_num, last_block_column; + int ci, block_row, block_rows, access_rows; + JBLOCKARRAY buffer; + JBLOCKROW buffer_ptr, prev_block_row, next_block_row; + JSAMPARRAY output_ptr; + JDIMENSION output_col; + jpeg_component_info *compptr; + inverse_DCT_method_ptr inverse_DCT; + boolean first_row, last_row; + JBLOCK workspace; + int *coef_bits; + JQUANT_TBL *quanttbl; + INT32 Q00,Q01,Q02,Q10,Q11,Q20, num; + int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9; + int Al, pred; + + /* Force some input to be done if we are getting ahead of the input. */ + while (cinfo->input_scan_number <= cinfo->output_scan_number && + ! cinfo->inputctl->eoi_reached) { + if (cinfo->input_scan_number == cinfo->output_scan_number) { + /* If input is working on current scan, we ordinarily want it to + * have completed the current row. But if input scan is DC, + * we want it to keep one row ahead so that next block row's DC + * values are up to date. + */ + JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; + if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) + break; + } + if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) + return JPEG_SUSPENDED; + } + + /* OK, output from the virtual arrays. */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) + continue; + /* Count non-dummy DCT block rows in this iMCU row. */ + if (cinfo->output_iMCU_row < last_iMCU_row) { + block_rows = compptr->v_samp_factor; + access_rows = block_rows * 2; /* this and next iMCU row */ + last_row = FALSE; + } else { + /* NB: can't use last_row_height here; it is input-side-dependent! */ + block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (block_rows == 0) block_rows = compptr->v_samp_factor; + access_rows = block_rows; /* this iMCU row only */ + last_row = TRUE; + } + /* Align the virtual buffer for this component. */ + if (cinfo->output_iMCU_row > 0) { + access_rows += compptr->v_samp_factor; /* prior iMCU row too */ + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); + buffer += compptr->v_samp_factor; /* point to current iMCU row */ + first_row = FALSE; + } else { + buffer = (*cinfo->mem->access_virt_barray) + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + first_row = TRUE; + } + /* Fetch component-dependent info */ + coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS); + quanttbl = compptr->quant_table; + Q00 = quanttbl->quantval[0]; + Q01 = quanttbl->quantval[Q01_POS]; + Q10 = quanttbl->quantval[Q10_POS]; + Q20 = quanttbl->quantval[Q20_POS]; + Q11 = quanttbl->quantval[Q11_POS]; + Q02 = quanttbl->quantval[Q02_POS]; + inverse_DCT = cinfo->idct->inverse_DCT[ci]; + output_ptr = output_buf[ci]; + /* Loop over all DCT blocks to be processed. */ + for (block_row = 0; block_row < block_rows; block_row++) { + buffer_ptr = buffer[block_row]; + if (first_row && block_row == 0) + prev_block_row = buffer_ptr; + else + prev_block_row = buffer[block_row-1]; + if (last_row && block_row == block_rows-1) + next_block_row = buffer_ptr; + else + next_block_row = buffer[block_row+1]; + /* We fetch the surrounding DC values using a sliding-register approach. + * Initialize all nine here so as to do the right thing on narrow pics. + */ + DC1 = DC2 = DC3 = (int) prev_block_row[0][0]; + DC4 = DC5 = DC6 = (int) buffer_ptr[0][0]; + DC7 = DC8 = DC9 = (int) next_block_row[0][0]; + output_col = 0; + last_block_column = compptr->width_in_blocks - 1; + for (block_num = 0; block_num <= last_block_column; block_num++) { + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q01<<7) - num) / (Q01<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[1] = (JCOEF) pred; + } + /* AC10 */ + if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) { + num = 36 * Q00 * (DC2 - DC8); + if (num >= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q10<<7) - num) / (Q10<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[8] = (JCOEF) pred; + } + /* AC20 */ + if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) { + num = 9 * Q00 * (DC2 + DC8 - 2*DC5); + if (num >= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q20<<7) - num) / (Q20<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[16] = (JCOEF) pred; + } + /* AC11 */ + if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) { + num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9); + if (num >= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q11<<7) - num) / (Q11<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[9] = (JCOEF) pred; + } + /* AC02 */ + if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) { + num = 9 * Q00 * (DC4 + DC6 - 2*DC5); + if (num >= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + } else { + pred = (int) (((Q02<<7) - num) / (Q02<<8)); + if (Al > 0 && pred >= (1<<Al)) + pred = (1<<Al)-1; + pred = -pred; + } + workspace[2] = (JCOEF) pred; + } + /* OK, do the IDCT */ + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace, + output_ptr, output_col); + /* Advance for next column */ + DC1 = DC2; DC2 = DC3; + DC4 = DC5; DC5 = DC6; + DC7 = DC8; DC8 = DC9; + buffer_ptr++, prev_block_row++, next_block_row++; + output_col += compptr->DCT_scaled_size; + } + output_ptr += compptr->DCT_scaled_size; + } + } + + if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows) + return JPEG_ROW_COMPLETED; + return JPEG_SCAN_COMPLETED; +} + +#endif /* BLOCK_SMOOTHING_SUPPORTED */ + + +/* + * Initialize coefficient buffer controller. + */ + +GLOBAL(void) +jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_coef_ptr coef; + + coef = (my_coef_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_coef_controller)); + cinfo->coef = (struct jpeg_d_coef_controller *) coef; + coef->pub.start_input_pass = start_input_pass; + coef->pub.start_output_pass = start_output_pass; +#ifdef BLOCK_SMOOTHING_SUPPORTED + coef->coef_bits_latch = NULL; +#endif + + /* Create the coefficient buffer. */ + if (need_full_buffer) { +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* Allocate a full-image virtual array for each component, */ + /* padded to a multiple of samp_factor DCT blocks in each direction. */ + /* Note we ask for a pre-zeroed array. */ + int ci, access_rows; + jpeg_component_info *compptr; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + access_rows = compptr->v_samp_factor; +#ifdef BLOCK_SMOOTHING_SUPPORTED + /* If block smoothing could be used, need a bigger window */ + if (cinfo->progressive_mode) + access_rows *= 3; +#endif + coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); + } + coef->pub.consume_data = consume_data; + coef->pub.decompress_data = decompress_data; + coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + /* We only need a single-MCU buffer. */ + JBLOCKROW buffer; + int i; + + buffer = (JBLOCKROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { + coef->MCU_buffer[i] = buffer + i; + } + coef->pub.consume_data = dummy_consume_data; + coef->pub.decompress_data = decompress_onepass; + coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ + } +} diff --git a/Utilities/vtkjpeg/jdcolor.c b/Utilities/vtkjpeg/jdcolor.c new file mode 100644 index 0000000..1a0aa23 --- /dev/null +++ b/Utilities/vtkjpeg/jdcolor.c @@ -0,0 +1,397 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains output colorspace conversion routines. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_deconverter pub; /* public fields */ + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ + +/* + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * where Cb and Cr represent the incoming values less CENTERJSAMPLE. + * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * + * To avoid floating-point arithmetic, we represent the fractional constants + * as integers scaled up by 2^16 (about 4 digits precision); we have to divide + * the products by 2^16, with appropriate rounding, to get the correct answer. + * Notice that Y, being an integral input, does not contribute any fraction + * so it need not participate in the rounding. + * + * For even more speed, we avoid doing any multiplications in the inner loop + * by precalculating the constants times Cb and Cr for all possible values. + * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + * for 12-bit samples it is still acceptable. It's not very reasonable for + * 16-bit samples, but if you want lossless storage you shouldn't be changing + * colorspace anyway. + * The Cr=>R and Cb=>B values can be rounded to integers in advance; the + * values for the G calculation are left scaled up, since we must add them + * together before rounding. + */ + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) + + +/* + * Initialize tables for YCC->RGB colorspace conversion. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + INT32 x; + SHIFT_TEMPS + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + cconvert->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Convert some rows of samples to the output colorspace. + * + * Note that we change from noninterleaved, one-plane-per-component format + * to interleaved-pixel format. The output buffer is therefore three times + * as wide as the input buffer. + * A starting row offset is provided only for the input buffer. The caller + * can easily adjust the passed output_buf value to accommodate any row + * offset required on that side. + */ + +METHODDEF(void) +ycc_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + outptr[RGB_GREEN] = range_limit[y + + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/**************** Cases other than YCbCr -> RGB **************/ + + +/* + * Color conversion for no colorspace change: just copy the data, + * converting from separate-planes to interleaved representation. + */ + +METHODDEF(void) +null_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION count; + register int num_components = cinfo->num_components; + JDIMENSION num_cols = cinfo->output_width; + int ci; + + while (--num_rows >= 0) { + for (ci = 0; ci < num_components; ci++) { + inptr = input_buf[ci][input_row]; + outptr = output_buf[0] + ci; + for (count = num_cols; count > 0; count--) { + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += num_components; + } + } + input_row++; + output_buf++; + } +} + + +/* + * Color conversion for grayscale: just copy the data. + * This also works for YCbCr -> grayscale conversion, in which + * we just copy the Y (luminance) component and ignore chrominance. + */ + +METHODDEF(void) +grayscale_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, + num_rows, cinfo->output_width); +} + + +/* + * Convert grayscale to RGB: just duplicate the graylevel three times. + * This is provided to support applications that don't want to cope + * with grayscale as a separate case. + */ + +METHODDEF(void) +gray_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW inptr, outptr; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + while (--num_rows >= 0) { + inptr = input_buf[0][input_row++]; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * Adobe-style YCCK->CMYK conversion. + * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + * conversion as above, while passing K (black) unchanged. + * We assume build_ycc_rgb_table has been called. + */ + +METHODDEF(void) +ycck_cmyk_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + /* Range-limiting is essential due to noise introduced by DCT losses. */ + outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ + outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; + outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ + /* K passes through unchanged */ + outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ + outptr += 4; + } + } +} + + +/* + * Empty method for start_pass. + */ + +METHODDEF(void) +start_pass_dcolor (j_decompress_ptr cinfo) +{ + cinfo = 0; + /* no work needed */ +} + + +/* + * Module initialization routine for output colorspace conversion. + */ + +GLOBAL(void) +jinit_color_deconverter (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert; + int ci; + + cconvert = (my_cconvert_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_color_deconverter)); + cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; + cconvert->pub.start_pass = start_pass_dcolor; + + /* Make sure num_components agrees with jpeg_color_space */ + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + if (cinfo->num_components != 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_RGB: + case JCS_YCbCr: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + case JCS_CMYK: + case JCS_YCCK: + if (cinfo->num_components != 4) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + + default: /* JCS_UNKNOWN can be anything */ + if (cinfo->num_components < 1) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + break; + } + + /* Set out_color_components and conversion method based on requested space. + * Also clear the component_needed flags for any unused components, + * so that earlier pipeline stages can avoid useless computation. + */ + + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + if (cinfo->jpeg_color_space == JCS_GRAYSCALE || + cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = grayscale_convert; + /* For color->grayscale conversion, only the Y (0) component is needed */ + for (ci = 1; ci < cinfo->num_components; ci++) + cinfo->comp_info[ci].component_needed = FALSE; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_YCbCr) { + cconvert->pub.color_convert = ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { + cconvert->pub.color_convert = gray_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + case JCS_CMYK: + cinfo->out_color_components = 4; + if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = null_convert; + } else + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + + default: + /* Permit null conversion to same output space */ + if (cinfo->out_color_space == cinfo->jpeg_color_space) { + cinfo->out_color_components = cinfo->num_components; + cconvert->pub.color_convert = null_convert; + } else /* unsupported non-null conversion */ + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + break; + } + + if (cinfo->quantize_colors) + cinfo->output_components = 1; /* single colormapped output component */ + else + cinfo->output_components = cinfo->out_color_components; +} diff --git a/Utilities/vtkjpeg/jdct.h b/Utilities/vtkjpeg/jdct.h new file mode 100644 index 0000000..23ce894 --- /dev/null +++ b/Utilities/vtkjpeg/jdct.h @@ -0,0 +1,176 @@ +/* + * jdct.h + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file contains common declarations for the forward and + * inverse DCT modules. These declarations are private to the DCT managers + * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + * The individual DCT algorithms are kept in separate files to ease + * machine-dependent tuning (e.g., assembly coding). + */ + + +/* + * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + * the DCT is to be performed in-place in that buffer. Type DCTELEM is int + * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT + * implementations use an array of type FAST_FLOAT, instead.) + * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * The DCT outputs are returned scaled up by a factor of 8; they therefore + * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + * convention improves accuracy in integer implementations and saves some + * work in floating-point ones. + * Quantization of the output coefficients is done by jcdctmgr.c. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef int DCTELEM; /* 16 or 32 bits is fine */ +#else +typedef INT32 DCTELEM; /* must have 32 bits */ +#endif + +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); + + +/* + * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + * to an output sample array. The routine must dequantize the input data as + * well as perform the IDCT; for dequantization, it uses the multiplier table + * pointed to by compptr->dct_table. The output data is to be placed into the + * sample array starting at a specified column. (Any row offset needed will + * be applied to the array pointer before it is passed to the IDCT code.) + * Note that the number of samples emitted by the IDCT routine is + * DCT_scaled_size * DCT_scaled_size. + */ + +/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ + +/* + * Each IDCT routine has its own ideas about the best dct_table element type. + */ + +typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ +#if BITS_IN_JSAMPLE == 8 +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ +#else +typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ +#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ +#endif +typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ + + +/* + * Each IDCT routine is responsible for range-limiting its results and + * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + * be quite far out of range if the input data is corrupt, so a bulletproof + * range-limiting step is required. We use a mask-and-table-lookup method + * to do the combined operations quickly. See the comments with + * prepare_range_limit_table (in jdmaster.c) for more info. + */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_fdct_islow jFDislow +#define jpeg_fdct_ifast jFDifast +#define jpeg_fdct_float jFDfloat +#define jpeg_idct_islow jRDislow +#define jpeg_idct_ifast jRDifast +#define jpeg_idct_float jRDfloat +#define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_2x2 jRD2x2 +#define jpeg_idct_1x1 jRD1x1 +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + +/* Extern declarations for the forward and inverse DCT routines. */ + +EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); +EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); + +EXTERN(void) jpeg_idct_islow + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_ifast + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_float + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + + +/* + * Macros for handling fixed-point arithmetic; these are used by many + * but not all of the DCT/IDCT modules. + * + * All values are expected to be of type INT32. + * Fractional constants are scaled left by CONST_BITS bits. + * CONST_BITS is defined within each module using these macros, + * and may differ from one module to the next. + */ + +#define ONE ((INT32) 1) +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, + * thus causing a lot of useless floating-point operations at run time. + */ + +#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an INT32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * This macro is used only when the two inputs will actually be no more than + * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a + * full 32x32 multiply. This provides a useful speedup on many machines. + * Unfortunately there is no way to specify a 16x16->32 multiply portably + * in C, but some C compilers will do the right thing if you provide the + * correct combination of casts. + */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) +#endif + +#ifndef MULTIPLY16C16 /* default definition */ +#define MULTIPLY16C16(var,const) ((var) * (const)) +#endif + +/* Same except both inputs are variables. */ + +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) +#endif + +#ifndef MULTIPLY16V16 /* default definition */ +#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) +#endif diff --git a/Utilities/vtkjpeg/jddctmgr.c b/Utilities/vtkjpeg/jddctmgr.c new file mode 100644 index 0000000..bbf8d0e --- /dev/null +++ b/Utilities/vtkjpeg/jddctmgr.c @@ -0,0 +1,269 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the inverse-DCT management logic. + * This code selects a particular IDCT implementation to be used, + * and it performs related housekeeping chores. No code in this file + * is executed per IDCT step, only during output pass setup. + * + * Note that the IDCT routines are responsible for performing coefficient + * dequantization as well as the IDCT proper. This module sets up the + * dequantization multiplier table needed by the IDCT routine. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + + +/* + * The decompressor input side (jdinput.c) saves away the appropriate + * quantization table for each component at the start of the first scan + * involving that component. (This is necessary in order to correctly + * decode files that reuse Q-table slots.) + * When we are ready to make an output pass, the saved Q-table is converted + * to a multiplier table that will actually be used by the IDCT routine. + * The multiplier table contents are IDCT-method-dependent. To support + * application changes in IDCT method between scans, we can remake the + * multiplier tables if necessary. + * In buffered-image mode, the first output pass may occur before any data + * has been seen for some components, and thus before their Q-tables have + * been saved away. To handle this case, multiplier tables are preset + * to zeroes; the result of the IDCT will be a neutral gray level. + */ + + +/* Private subobject for this module */ + +typedef struct { + struct jpeg_inverse_dct pub; /* public fields */ + + /* This array contains the IDCT method code that each multiplier table + * is currently set up for, or -1 if it's not yet set up. + * The actual multiplier tables are pointed to by dct_table in the + * per-component comp_info structures. + */ + int cur_method[MAX_COMPONENTS]; +} my_idct_controller; + +typedef my_idct_controller * my_idct_ptr; + + +/* Allocated multiplier tables: big enough for any supported variant */ + +typedef union { + ISLOW_MULT_TYPE islow_array[DCTSIZE2]; +#ifdef DCT_IFAST_SUPPORTED + IFAST_MULT_TYPE ifast_array[DCTSIZE2]; +#endif +#ifdef DCT_FLOAT_SUPPORTED + FLOAT_MULT_TYPE float_array[DCTSIZE2]; +#endif +} multiplier_table; + + +/* The current scaled-IDCT routines require ISLOW-style multiplier tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. + */ +#ifdef DCT_ISLOW_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#else +#ifdef IDCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES +#endif +#endif + + +/* + * Prepare for an output pass. + * Here we select the proper IDCT routine for each component and build + * a matching multiplier table. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + my_idct_ptr idct = (my_idct_ptr) cinfo->idct; + int ci, i; + jpeg_component_info *compptr; + int method = 0; + inverse_DCT_method_ptr method_ptr = NULL; + JQUANT_TBL * qtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper IDCT routine for this component's scaling */ + switch (compptr->DCT_scaled_size) { +#ifdef IDCT_SCALING_SUPPORTED + case 1: + method_ptr = jpeg_idct_1x1; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 2: + method_ptr = jpeg_idct_2x2; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; + case 4: + method_ptr = jpeg_idct_4x4; + method = JDCT_ISLOW; /* jidctred uses islow-style table */ + break; +#endif + case DCTSIZE: + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); + break; + } + idct->pub.inverse_DCT[ci] = method_ptr; + /* Create multiplier table from quant table. + * However, we can skip this if the component is uninteresting + * or if we already built the table. Also, if no quant table + * has yet been saved for the component, we leave the + * multiplier table all-zero; we'll be reading zeroes from the + * coefficient controller's buffer anyway. + */ + if (! compptr->component_needed || idct->cur_method[ci] == method) + continue; + qtbl = compptr->quant_table; + if (qtbl == NULL) /* happens if no data yet for component */ + continue; + idct->cur_method[ci] = method; + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + { + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } + } + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } + } + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col]); + i++; + } + } + } + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + +/* + * Initialize IDCT manager. + */ + +GLOBAL(void) +jinit_inverse_dct (j_decompress_ptr cinfo) +{ + my_idct_ptr idct; + int ci; + jpeg_component_info *compptr; + + idct = (my_idct_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_idct_controller)); + cinfo->idct = (struct jpeg_inverse_dct *) idct; + idct->pub.start_pass = start_pass; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate and pre-zero a multiplier table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); + /* Mark multiplier table not yet set up for any method */ + idct->cur_method[ci] = -1; + } +} diff --git a/Utilities/vtkjpeg/jdhuff.c b/Utilities/vtkjpeg/jdhuff.c new file mode 100644 index 0000000..b5ba39f --- /dev/null +++ b/Utilities/vtkjpeg/jdhuff.c @@ -0,0 +1,651 @@ +/* + * jdhuff.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdphuff.c */ + + +/* + * Expanded entropy decoder object for Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; + d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; + + /* Precalculated info set up by start_pass for use in decode_mcu: */ + + /* Pointers to derived tables to be used for each block within an MCU */ + d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; + /* Whether we care about the DC and AC coefficient values for each block */ + boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; + boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; +} huff_entropy_decoder; + +typedef huff_entropy_decoder * huff_entropy_ptr; + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, blkn, dctbl, actbl; + jpeg_component_info * compptr; + + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || + cinfo->Ah != 0 || cinfo->Al != 0) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + dctbl = compptr->dc_tbl_no; + actbl = compptr->ac_tbl_no; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + & entropy->dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + & entropy->ac_derived_tbls[actbl]); + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + entropy->dc_needed[blkn] = TRUE; + /* we don't need the ACs if producing a 1/8th-size image */ + entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); + } else { + entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Compute the derived values for a Huffman table. + * This routine also performs some validation checks on the table. + * + * Note this is also used by jdphuff.c. + */ + +GLOBAL(void) +jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl) +{ + JHUFF_TBL *htbl; + d_derived_tbl *dtbl; + int p, i, l, si, numsymbols; + int lookbits, ctr; + char huffsize[257]; + unsigned int huffcode[257]; + unsigned int code; + + /* Note that huffsize[] and huffcode[] are filled in code-length order, + * paralleling the order of the symbols themselves in htbl->huffval[]. + */ + + /* Find the input Huffman table */ + if (tblno < 0 || tblno >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + htbl = + isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; + if (htbl == NULL) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); + + /* Allocate a workspace if we haven't already done so. */ + if (*pdtbl == NULL) + *pdtbl = (d_derived_tbl *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(d_derived_tbl)); + dtbl = *pdtbl; + dtbl->pub = htbl; /* fill in back link */ + + /* Figure C.1: make table of Huffman code length for each symbol */ + + p = 0; + for (l = 1; l <= 16; l++) { + i = (int) htbl->bits[l]; + if (i < 0 || p + i > 256) /* protect against table overrun */ + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + while (i--) + huffsize[p++] = (char) l; + } + huffsize[p] = 0; + numsymbols = p; + + /* Figure C.2: generate the codes themselves */ + /* We also validate that the counts represent a legal Huffman code tree. */ + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p]) { + while (((int) huffsize[p]) == si) { + huffcode[p++] = code; + code++; + } + /* code is now 1 more than the last code used for codelength si; but + * it must still fit in si bits, since no code is allowed to be all ones. + */ + if (((INT32) code) >= (((INT32) 1) << si)) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + code <<= 1; + si++; + } + + /* Figure F.15: generate decoding tables for bit-sequential decoding */ + + p = 0; + for (l = 1; l <= 16; l++) { + if (htbl->bits[l]) { + /* valoffset[l] = huffval[] index of 1st symbol of code length l, + * minus the minimum code of length l + */ + dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; + p += htbl->bits[l]; + dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ + } else { + dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ + } + } + dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ + + /* Compute lookahead tables to speed up decoding. + * First we set all the table entries to 0, indicating "too long"; + * then we iterate through the Huffman codes that are short enough and + * fill in all the entries that correspond to bit sequences starting + * with that code. + */ + + MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); + + p = 0; + for (l = 1; l <= HUFF_LOOKAHEAD; l++) { + for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { + /* l = current code's length, p = its index in huffcode[] & huffval[]. */ + /* Generate left-justified code followed by all possible bit sequences */ + lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); + for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; + } + } + } + + /* Validate symbols as being reasonable. + * For AC tables, we make no check, but accept all byte values 0..255. + * For DC tables, we require the symbols to be in range 0..15. + * (Tighter bounds could be applied depending on the data depth and mode, + * but this is sufficient to ensure safe decoding.) + */ + if (isDC) { + for (i = 0; i < numsymbols; i++) { + int sym = htbl->huffval[i]; + if (sym < 0 || sym > 15) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + } + } +} + + +/* + * Out-of-line code for bit fetching (shared with jdphuff.c). + * See jdhuff.h for info about usage. + * Note: current values of get_buffer and bits_left are passed as parameters, + * but are returned in the corresponding fields of the state struct. + * + * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + * of get_buffer to be used. (On machines with wider words, an even larger + * buffer could be used.) However, on some machines 32-bit shifts are + * quite slow and take time proportional to the number of places shifted. + * (This is true with most PC compilers, for instance.) In this case it may + * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + * average shift distance at the cost of more calls to jpeg_fill_bit_buffer. + */ + +#ifdef SLOW_SHIFT_32 +#define MIN_GET_BITS 15 /* minimum allowable value */ +#else +#define MIN_GET_BITS (BIT_BUF_SIZE-7) +#endif + + +GLOBAL(boolean) +jpeg_fill_bit_buffer (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + int nbits) +/* Load up the bit buffer to a depth of at least nbits */ +{ + /* Copy heavily used state fields into locals (hopefully registers) */ + register const JOCTET * next_input_byte = state->next_input_byte; + register size_t bytes_in_buffer = state->bytes_in_buffer; + j_decompress_ptr cinfo = state->cinfo; + + /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ + /* (It is assumed that no request will be for more than that many bits.) */ + /* We fail to do so only if we hit a marker or are forced to suspend. */ + + if (cinfo->unread_marker == 0) { /* cannot advance past a marker */ + while (bits_left < MIN_GET_BITS) { + register int c; + + /* Attempt to read a byte */ + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + + /* If it's 0xFF, check and discard stuffed zero byte */ + if (c == 0xFF) { + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); + + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } + } + + /* OK, load c into get_buffer */ + get_buffer = (get_buffer << 8) | c; + bits_left += 8; + } /* end while */ + } else { + no_more_bytes: + /* We get here if we've read the marker that terminates the compressed + * data segment. There should be enough bits in the buffer register + * to satisfy the request; if so, no problem. + */ + if (nbits > bits_left) { + /* Uh-oh. Report corrupted data to user and stuff zeroes into + * the data stream, so that we can produce some kind of image. + * We use a nonvolatile flag to ensure that only one warning message + * appears per data segment. + */ + if (! cinfo->entropy->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + cinfo->entropy->insufficient_data = TRUE; + } + /* Fill the buffer with zero bits */ + get_buffer <<= MIN_GET_BITS - bits_left; + bits_left = MIN_GET_BITS; + } + } + + /* Unload the local registers */ + state->next_input_byte = next_input_byte; + state->bytes_in_buffer = bytes_in_buffer; + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + return TRUE; +} + + +/* + * Out-of-line code for Huffman code decoding. + * See jdhuff.h for info about usage. + */ + +GLOBAL(int) +jpeg_huff_decode (bitread_working_state * state, + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) +{ + register int l = min_bits; + register INT32 code; + + /* HUFF_DECODE has determined that the code is at least min_bits */ + /* bits long, so fetch that many bits in one swoop. */ + + CHECK_BIT_BUFFER(*state, l, return -1); + code = GET_BITS(l); + + /* Collect the rest of the Huffman code one bit at a time. */ + /* This is per Figure F.16 in the JPEG spec. */ + + while (code > htbl->maxcode[l]) { + code <<= 1; + CHECK_BIT_BUFFER(*state, 1, return -1); + code |= GET_BITS(1); + l++; + } + + /* Unload the local registers */ + state->get_buffer = get_buffer; + state->bits_left = bits_left; + + /* With garbage input we may reach the sentinel value l = 17. */ + + if (l > 16) { + WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); + return 0; /* fake a zero as the safest result */ + } + + return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ]; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Decode and return one MCU's worth of Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * (Wholesale zeroing is usually a little faster than retail...) + * + * Returns FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * this module, since we'll just re-assign them on the next call.) + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; + d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + register int s, k, r; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + if (entropy->dc_needed[blkn]) { + /* Convert DC difference to actual value, update last_dc_val */ + int ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + (*block)[0] = (JCOEF) s; + } + + if (entropy->ac_needed[blkn]) { + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + break; + k += 15; + } + } + + } else { + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (k = 1; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, actbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + } + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Module initialization routine for Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy; + int i; + + entropy = (huff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(huff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_huff_decoder; + entropy->pub.decode_mcu = decode_mcu; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } +} diff --git a/Utilities/vtkjpeg/jdhuff.h b/Utilities/vtkjpeg/jdhuff.h new file mode 100644 index 0000000..be3ee32 --- /dev/null +++ b/Utilities/vtkjpeg/jdhuff.h @@ -0,0 +1,201 @@ +/* + * jdhuff.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains declarations for Huffman entropy decoding routines + * that are shared between the sequential decoder (jdhuff.c) and the + * progressive decoder (jdphuff.c). No other modules need to see these. + */ + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_make_d_derived_tbl jMkDDerived +#define jpeg_fill_bit_buffer jFilBitBuf +#define jpeg_huff_decode jHufDecode +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */ + UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */ +} d_derived_tbl; + +/* Expand a Huffman table definition into the derived format */ +EXTERN(void) jpeg_make_d_derived_tbl + JPP((j_decompress_ptr cinfo, boolean isDC, int tblno, + d_derived_tbl ** pdtbl)); + + +/* + * Fetching the next N bits from the input stream is a time-critical operation + * for the Huffman decoders. We implement it with a combination of inline + * macros and out-of-line subroutines. Note that N (the number of bits + * demanded at one time) never exceeds 15 for JPEG use. + * + * We read source bytes into get_buffer and dole out bits as needed. + * If get_buffer already contains enough bits, they are fetched in-line + * by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough + * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer + * as full as possible (not just to the number of bits needed; this + * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer). + * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension. + * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains + * at least the requested number of bits --- dummy zeroes are inserted if + * necessary. + */ + +typedef INT32 bit_buf_type; /* type of bit-extraction buffer */ +#define BIT_BUF_SIZE 32 /* size of buffer in bits */ + +/* If long is > 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + +/* Load up the bit buffer to a depth of at least nbits */ +EXTERN(boolean) jpeg_fill_bit_buffer + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, int nbits)); + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} + +/* Out-of-line case for Huffman code fetching */ +EXTERN(int) jpeg_huff_decode + JPP((bitread_working_state * state, register bit_buf_type get_buffer, + register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/Utilities/vtkjpeg/jdinput.c b/Utilities/vtkjpeg/jdinput.c new file mode 100644 index 0000000..0c2ac8f --- /dev/null +++ b/Utilities/vtkjpeg/jdinput.c @@ -0,0 +1,381 @@ +/* + * jdinput.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains input control logic for the JPEG decompressor. + * These routines are concerned with controlling the decompressor's input + * processing (marker reading and coefficient decoding). The actual input + * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_input_controller pub; /* public fields */ + + boolean inheaders; /* TRUE until first SOS is reached */ +} my_input_controller; + +typedef my_input_controller * my_inputctl_ptr; + + +/* Forward declarations */ +METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); + + +/* + * Routines to calculate various quantities related to the size of the image. + */ + +LOCAL(void) +initial_setup (j_decompress_ptr cinfo) +/* Called once, when first SOS marker is reached */ +{ + int ci; + jpeg_component_info *compptr; + + /* Make sure image isn't bigger than I can handle */ + if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Check that number of components won't exceed internal array sizes */ + if (cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + + /* Compute maximum sampling factors; check factor validity */ + cinfo->max_h_samp_factor = 1; + cinfo->max_v_samp_factor = 1; + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + ERREXIT(cinfo, JERR_BAD_SAMPLING); + cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, + compptr->h_samp_factor); + cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, + compptr->v_samp_factor); + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. + * In the full decompressor, this will be overridden by jdmaster.c; + * but in the transcoder, jdmaster.c is not used, so we must do it here. + */ + cinfo->min_DCT_scaled_size = DCTSIZE; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_scaled_size = DCTSIZE; + /* Size in DCT blocks */ + compptr->width_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + /* downsampled_width and downsampled_height will also be overridden by + * jdmaster.c if we are doing full decompression. The transcoder library + * doesn't use these values, but the calling application might. + */ + /* Size in samples */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, + (long) cinfo->max_h_samp_factor); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) cinfo->max_v_samp_factor); + /* Mark component needed, until color conversion says otherwise */ + compptr->component_needed = TRUE; + /* Mark no quantization table yet saved for component */ + compptr->quant_table = NULL; + } + + /* Compute number of fully interleaved MCU rows. */ + cinfo->total_iMCU_rows = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + /* Decide whether file contains multiple scans */ + if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) + cinfo->inputctl->has_multiple_scans = TRUE; + else + cinfo->inputctl->has_multiple_scans = FALSE; +} + + +LOCAL(void) +per_scan_setup (j_decompress_ptr cinfo) +/* Do computations that are needed before processing a JPEG scan */ +/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ +{ + int ci, mcublks, tmp; + jpeg_component_info *compptr; + + if (cinfo->comps_in_scan == 1) { + + /* Noninterleaved (single-component) scan */ + compptr = cinfo->cur_comp_info[0]; + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = compptr->width_in_blocks; + cinfo->MCU_rows_in_scan = compptr->height_in_blocks; + + /* For noninterleaved scan, always one block per MCU */ + compptr->MCU_width = 1; + compptr->MCU_height = 1; + compptr->MCU_blocks = 1; + compptr->MCU_sample_width = compptr->DCT_scaled_size; + compptr->last_col_width = 1; + /* For noninterleaved scans, it is convenient to define last_row_height + * as the number of block rows present in the last iMCU row. + */ + tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); + if (tmp == 0) tmp = compptr->v_samp_factor; + compptr->last_row_height = tmp; + + /* Prepare array describing MCU composition */ + cinfo->blocks_in_MCU = 1; + cinfo->MCU_membership[0] = 0; + + } else { + + /* Interleaved (multi-component) scan */ + if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, + MAX_COMPS_IN_SCAN); + + /* Overall image size in MCUs */ + cinfo->MCUs_per_row = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, + (long) (cinfo->max_h_samp_factor*DCTSIZE)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor*DCTSIZE)); + + cinfo->blocks_in_MCU = 0; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Sampling factors give # of blocks of component in each MCU */ + compptr->MCU_width = compptr->h_samp_factor; + compptr->MCU_height = compptr->v_samp_factor; + compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; + /* Figure number of non-dummy blocks in last MCU column & row */ + tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); + if (tmp == 0) tmp = compptr->MCU_width; + compptr->last_col_width = tmp; + tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); + if (tmp == 0) tmp = compptr->MCU_height; + compptr->last_row_height = tmp; + /* Prepare array describing MCU composition */ + mcublks = compptr->MCU_blocks; + if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + while (mcublks-- > 0) { + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + } + } + + } +} + + +/* + * Save away a copy of the Q-table referenced by each component present + * in the current scan, unless already saved during a prior scan. + * + * In a multiple-scan JPEG file, the encoder could assign different components + * the same Q-table slot number, but change table definitions between scans + * so that each component uses a different Q-table. (The IJG encoder is not + * currently capable of doing this, but other encoders might.) Since we want + * to be able to dequantize all the components at the end of the file, this + * means that we have to save away the table actually used for each component. + * We do this by copying the table at the start of the first scan containing + * the component. + * The JPEG spec prohibits the encoder from changing the contents of a Q-table + * slot between scans of a component using that slot. If the encoder does so + * anyway, this decoder will simply use the Q-table values that were current + * at the start of the first scan for the component. + * + * The decompressor output side looks only at the saved quant tables, + * not at the current Q-table slots. + */ + +LOCAL(void) +latch_quant_tables (j_decompress_ptr cinfo) +{ + int ci, qtblno; + jpeg_component_info *compptr; + JQUANT_TBL * qtbl; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* No work if we already saved Q-table for this component */ + if (compptr->quant_table != NULL) + continue; + /* Make sure specified quantization table is present */ + qtblno = compptr->quant_tbl_no; + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + /* OK, save away the quantization table */ + qtbl = (JQUANT_TBL *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)); + MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr->quant_table = qtbl; + } +} + + +/* + * Initialize the input modules to read a scan of compressed data. + * The first call to this is done by jdmaster.c after initializing + * the entire decompressor (during jpeg_start_decompress). + * Subsequent calls come from consume_markers, below. + */ + +METHODDEF(void) +start_input_pass (j_decompress_ptr cinfo) +{ + per_scan_setup(cinfo); + latch_quant_tables(cinfo); + (*cinfo->entropy->start_pass) (cinfo); + (*cinfo->coef->start_input_pass) (cinfo); + cinfo->inputctl->consume_input = cinfo->coef->consume_data; +} + + +/* + * Finish up after inputting a compressed-data scan. + * This is called by the coefficient controller after it's read all + * the expected data of the scan. + */ + +METHODDEF(void) +finish_input_pass (j_decompress_ptr cinfo) +{ + cinfo->inputctl->consume_input = consume_markers; +} + + +/* + * Read JPEG markers before, between, or after compressed-data scans. + * Change state as necessary when a new scan is reached. + * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * The consume_input method pointer points either here or to the + * coefficient controller's consume_data routine, depending on whether + * we are reading a compressed data segment or inter-segment markers. + */ + +METHODDEF(int) +consume_markers (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + int val; + + if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ + return JPEG_REACHED_EOI; + + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + initial_setup(cinfo); + inputctl->inheaders = FALSE; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + start_input_pass(cinfo); + } + break; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + break; + case JPEG_SUSPENDED: + break; + } + + return val; +} + + +/* + * Reset state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl; + + inputctl->pub.consume_input = consume_markers; + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; + /* Reset other modules */ + (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); + (*cinfo->marker->reset_marker_reader) (cinfo); + /* Reset progression state -- would be cleaner if entropy decoder did this */ + cinfo->coef_bits = NULL; +} + + +/* + * Initialize the input controller module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_input_controller (j_decompress_ptr cinfo) +{ + my_inputctl_ptr inputctl; + + /* Create subobject in permanent pool */ + inputctl = (my_inputctl_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_input_controller)); + cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + /* Initialize method pointers */ + inputctl->pub.consume_input = consume_markers; + inputctl->pub.reset_input_controller = reset_input_controller; + inputctl->pub.start_input_pass = start_input_pass; + inputctl->pub.finish_input_pass = finish_input_pass; + /* Initialize state: can't use reset_input_controller since we don't + * want to try to reset other modules yet. + */ + inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ + inputctl->pub.eoi_reached = FALSE; + inputctl->inheaders = TRUE; +} diff --git a/Utilities/vtkjpeg/jdmainct.c b/Utilities/vtkjpeg/jdmainct.c new file mode 100644 index 0000000..14dbb65 --- /dev/null +++ b/Utilities/vtkjpeg/jdmainct.c @@ -0,0 +1,512 @@ +/* + * jdmainct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the main buffer controller for decompression. + * The main buffer lies between the JPEG decompressor proper and the + * post-processor; it holds downsampled data in the JPEG colorspace. + * + * Note that this code is bypassed in raw-data mode, since the application + * supplies the equivalent of the main buffer in that case. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * In the current system design, the main buffer need never be a full-image + * buffer; any full-height buffers will be found inside the coefficient or + * postprocessing controllers. Nonetheless, the main controller is not + * trivial. Its responsibility is to provide context rows for upsampling/ + * rescaling, and doing this in an efficient fashion is a bit tricky. + * + * Postprocessor input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. (We require DCT_scaled_size values to be + * chosen such that these numbers are integers. In practice DCT_scaled_size + * values will likely be powers of two, so we actually have the stronger + * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) + * Upsampling will typically produce max_v_samp_factor pixel rows from each + * row group (times any additional scale factor that the upsampler is + * applying). + * + * The coefficient controller will deliver data to us one iMCU row at a time; + * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or + * exactly min_DCT_scaled_size row groups. (This amount of data corresponds + * to one row of MCUs when the image is fully interleaved.) Note that the + * number of sample rows varies across components, but the number of row + * groups does not. Some garbage sample rows may be included in the last iMCU + * row at the bottom of the image. + * + * Depending on the vertical scaling algorithm used, the upsampler may need + * access to the sample row(s) above and below its current input row group. + * The upsampler is required to set need_context_rows TRUE at global selection + * time if so. When need_context_rows is FALSE, this controller can simply + * obtain one iMCU row at a time from the coefficient controller and dole it + * out as row groups to the postprocessor. + * + * When need_context_rows is TRUE, this controller guarantees that the buffer + * passed to postprocessing contains at least one row group's worth of samples + * above and below the row group(s) being processed. Note that the context + * rows "above" the first passed row group appear at negative row offsets in + * the passed buffer. At the top and bottom of the image, the required + * context rows are manufactured by duplicating the first or last real sample + * row; this avoids having special cases in the upsampling inner loops. + * + * The amount of context is fixed at one row group just because that's a + * convenient number for this controller to work with. The existing + * upsamplers really only need one sample row of context. An upsampler + * supporting arbitrary output rescaling might wish for more than one row + * group of context when shrinking the image; tough, we don't handle that. + * (This is justified by the assumption that downsizing will be handled mostly + * by adjusting the DCT_scaled_size values, so that the actual scale factor at + * the upsample step needn't be much less than one.) + * + * To provide the desired context, we have to retain the last two row groups + * of one iMCU row while reading in the next iMCU row. (The last row group + * can't be processed until we have another row group for its below-context, + * and so we have to save the next-to-last group too for its above-context.) + * We could do this most simply by copying data around in our buffer, but + * that'd be very slow. We can avoid copying any data by creating a rather + * strange pointer structure. Here's how it works. We allocate a workspace + * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number + * of row groups per iMCU row). We create two sets of redundant pointers to + * the workspace. Labeling the physical row groups 0 to M+1, the synthesized + * pointer lists look like this: + * M+1 M-1 + * master pointer --> 0 master pointer --> 0 + * 1 1 + * ... ... + * M-3 M-3 + * M-2 M + * M-1 M+1 + * M M-2 + * M+1 M-1 + * 0 0 + * We read alternate iMCU rows using each master pointer; thus the last two + * row groups of the previous iMCU row remain un-overwritten in the workspace. + * The pointer lists are set up so that the required context rows appear to + * be adjacent to the proper places when we pass the pointer lists to the + * upsampler. + * + * The above pictures describe the normal state of the pointer lists. + * At top and bottom of the image, we diddle the pointer lists to duplicate + * the first or last sample row as necessary (this is cheaper than copying + * sample rows around). + * + * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that + * situation each iMCU row provides only one row group so the buffering logic + * must be different (eg, we must read two iMCU rows before we can emit the + * first row group). For now, we simply do not support providing context + * rows when min_DCT_scaled_size is 1. That combination seems unlikely to + * be worth providing --- if someone wants a 1/8th-size preview, they probably + * want it quick and dirty, so a context-free upsampler is sufficient. + */ + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_main_controller pub; /* public fields */ + + /* Pointer to allocated workspace (M or M+2 row groups). */ + JSAMPARRAY buffer[MAX_COMPONENTS]; + + boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ + JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ + + /* Remaining fields are only used in the context case. */ + + /* These are the master pointers to the funny-order pointer lists. */ + JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ + + int whichptr; /* indicates which pointer set is now in use */ + int context_state; /* process_data state machine status */ + JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ + JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ +} my_main_controller; + +typedef my_main_controller * my_main_ptr; + +/* context_state values: */ +#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ +#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ +#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ + + +/* Forward declarations */ +METHODDEF(void) process_data_simple_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +METHODDEF(void) process_data_context_main + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) process_data_crank_post + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); +#endif + + +LOCAL(void) +alloc_funny_pointers (j_decompress_ptr cinfo) +/* Allocate space for the funny pointer lists. + * This is done only once, not once per pass. + */ +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + int ci, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + /* Get top-level space for component array pointers. + * We alloc both arrays with one call to save a few cycles. + */ + mainPtr->xbuffer[0] = (JSAMPIMAGE) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + mainPtr->xbuffer[1] = mainPtr->xbuffer[0] + cinfo->num_components; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + /* Get space for pointer lists --- M+4 row groups in each list. + * We alloc both pointer lists with one call to save a few cycles. + */ + xbuf = (JSAMPARRAY) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + xbuf += rgroup; /* want one row group at negative offsets */ + mainPtr->xbuffer[0][ci] = xbuf; + xbuf += rgroup * (M + 4); + mainPtr->xbuffer[1][ci] = xbuf; + } +} + + +LOCAL(void) +make_funny_pointers (j_decompress_ptr cinfo) +/* Create the funny pointer lists discussed in the comments above. + * The actual workspace is already allocated (in mainPtr->buffer), + * and the space for the pointer lists is allocated too. + * This routine just fills in the curiously ordered lists. + * This will be repeated at the beginning of each pass. + */ +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY buf, xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = mainPtr->xbuffer[0][ci]; + xbuf1 = mainPtr->xbuffer[1][ci]; + /* First copy the workspace pointers as-is */ + buf = mainPtr->buffer[ci]; + for (i = 0; i < rgroup * (M + 2); i++) { + xbuf0[i] = xbuf1[i] = buf[i]; + } + /* In the second list, put the last four row groups in swapped order */ + for (i = 0; i < rgroup * 2; i++) { + xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; + xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; + } + /* The wraparound pointers at top and bottom will be filled later + * (see set_wraparound_pointers, below). Initially we want the "above" + * pointers to duplicate the first actual data line. This only needs + * to happen in xbuffer[0]. + */ + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[0]; + } + } +} + + +LOCAL(void) +set_wraparound_pointers (j_decompress_ptr cinfo) +/* Set up the "wraparound" pointers at top and bottom of the pointer lists. + * This changes the pointer list state from top-of-image to the normal state. + */ +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + int ci, i, rgroup; + int M = cinfo->min_DCT_scaled_size; + jpeg_component_info *compptr; + JSAMPARRAY xbuf0, xbuf1; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + xbuf0 = mainPtr->xbuffer[0][ci]; + xbuf1 = mainPtr->xbuffer[1][ci]; + for (i = 0; i < rgroup; i++) { + xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; + xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; + xbuf0[rgroup*(M+2) + i] = xbuf0[i]; + xbuf1[rgroup*(M+2) + i] = xbuf1[i]; + } + } +} + + +LOCAL(void) +set_bottom_pointers (j_decompress_ptr cinfo) +/* Change the pointer lists to duplicate the last sample row at the bottom + * of the image. whichptr indicates which xbuffer holds the final iMCU row. + * Also sets rowgroups_avail to indicate number of nondummy row groups in row. + */ +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + int ci, i, rgroup, iMCUheight, rows_left; + jpeg_component_info *compptr; + JSAMPARRAY xbuf; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Count sample rows in one iMCU row and in one row group */ + iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_scaled_size; + /* Count nondummy sample rows remaining for this component */ + rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); + if (rows_left == 0) rows_left = iMCUheight; + /* Count nondummy row groups. Should get same answer for each component, + * so we need only do it once. + */ + if (ci == 0) { + mainPtr->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); + } + /* Duplicate the last real sample row rgroup*2 times; this pads out the + * last partial rowgroup and ensures at least one full rowgroup of context. + */ + xbuf = mainPtr->xbuffer[mainPtr->whichptr][ci]; + for (i = 0; i < rgroup * 2; i++) { + xbuf[rows_left + i] = xbuf[rows_left-1]; + } + } +} + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->upsample->need_context_rows) { + mainPtr->pub.process_data = process_data_context_main; + make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ + mainPtr->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ + mainPtr->context_state = CTX_PREPARE_FOR_IMCU; + mainPtr->iMCU_row_ctr = 0; + } else { + /* Simple case with no context needed */ + mainPtr->pub.process_data = process_data_simple_main; + } + mainPtr->buffer_full = FALSE; /* Mark buffer empty */ + mainPtr->rowgroup_ctr = 0; + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_CRANK_DEST: + /* For last pass of 2-pass quantization, just crank the postprocessor */ + mainPtr->pub.process_data = process_data_crank_post; + break; +#endif + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } +} + + +/* + * Process some data. + * This handles the simple case where no context is required. + */ + +METHODDEF(void) +process_data_simple_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + JDIMENSION rowgroups_avail; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mainPtr->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, mainPtr->buffer)) + return; /* suspension forced, can do nothing more */ + mainPtr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + } + + /* There are always min_DCT_scaled_size row groups in an iMCU row. */ + rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; + /* Note: at the bottom of the image, we may pass extra garbage row groups + * to the postprocessor. The postprocessor has to check for bottom + * of image anyway (at row resolution), so no point in us doing it too. + */ + + /* Feed the postprocessor */ + (*cinfo->post->post_process_data) (cinfo, mainPtr->buffer, + &mainPtr->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ + if (mainPtr->rowgroup_ctr >= rowgroups_avail) { + mainPtr->buffer_full = FALSE; + mainPtr->rowgroup_ctr = 0; + } +} + + +/* + * Process some data. + * This handles the case where context rows must be provided. + */ + +METHODDEF(void) +process_data_context_main (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_main_ptr mainPtr = (my_main_ptr) cinfo->main; + + /* Read input data if we haven't filled the main buffer yet */ + if (! mainPtr->buffer_full) { + if (! (*cinfo->coef->decompress_data) (cinfo, + mainPtr->xbuffer[mainPtr->whichptr])) + return; /* suspension forced, can do nothing more */ + mainPtr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ + mainPtr->iMCU_row_ctr++; /* count rows received */ + } + + /* Postprocessor typically will not swallow all the input data it is handed + * in one call (due to filling the output buffer first). Must be prepared + * to exit and restart. This switch lets us keep track of how far we got. + * Note that each case falls through to the next on successful completion. + */ + switch (mainPtr->context_state) { + case CTX_POSTPONED_ROW: + /* Call postprocessor using previously set pointers for postponed row */ + (*cinfo->post->post_process_data) (cinfo, mainPtr->xbuffer[mainPtr->whichptr], + &mainPtr->rowgroup_ctr, mainPtr->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mainPtr->rowgroup_ctr < mainPtr->rowgroups_avail) + return; /* Need to suspend */ + mainPtr->context_state = CTX_PREPARE_FOR_IMCU; + if (*out_row_ctr >= out_rows_avail) + return; /* Postprocessor exactly filled output buf */ + /*FALLTHROUGH*/ + case CTX_PREPARE_FOR_IMCU: + /* Prepare to process first M-1 row groups of this iMCU row */ + mainPtr->rowgroup_ctr = 0; + mainPtr->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); + /* Check for bottom of image: if so, tweak pointers to "duplicate" + * the last sample row, and adjust rowgroups_avail to ignore padding rows. + */ + if (mainPtr->iMCU_row_ctr == cinfo->total_iMCU_rows) + set_bottom_pointers(cinfo); + mainPtr->context_state = CTX_PROCESS_IMCU; + /*FALLTHROUGH*/ + case CTX_PROCESS_IMCU: + /* Call postprocessor using previously set pointers */ + (*cinfo->post->post_process_data) (cinfo, mainPtr->xbuffer[mainPtr->whichptr], + &mainPtr->rowgroup_ctr, mainPtr->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (mainPtr->rowgroup_ctr < mainPtr->rowgroups_avail) + return; /* Need to suspend */ + /* After the first iMCU, change wraparound pointers to normal state */ + if (mainPtr->iMCU_row_ctr == 1) + set_wraparound_pointers(cinfo); + /* Prepare to load new iMCU row using other xbuffer list */ + mainPtr->whichptr ^= 1; /* 0=>1 or 1=>0 */ + mainPtr->buffer_full = FALSE; + /* Still need to process last row group of this iMCU row, */ + /* which is saved at index M+1 of the other xbuffer */ + mainPtr->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); + mainPtr->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); + mainPtr->context_state = CTX_POSTPONED_ROW; + } +} + + +/* + * Process some data. + * Final pass of two-pass quantization: just call the postprocessor. + * Source data will be the postprocessor controller's internal buffer. + */ + +#ifdef QUANT_2PASS_SUPPORTED + +METHODDEF(void) +process_data_crank_post (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize main buffer controller. + */ + +GLOBAL(void) +jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_main_ptr mainPtr; + int ci, rgroup, ngroups; + jpeg_component_info *compptr; + + mainPtr = (my_main_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_main_controller)); + cinfo->main = (struct jpeg_d_main_controller *) mainPtr; + mainPtr->pub.start_pass = start_pass_main; + + if (need_full_buffer) /* shouldn't happen */ + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + + /* Allocate the workspace. + * ngroups is the number of row groups we need. + */ + if (cinfo->upsample->need_context_rows) { + if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ + ERREXIT(cinfo, JERR_NOTIMPL); + alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ + ngroups = cinfo->min_DCT_scaled_size + 2; + } else { + ngroups = cinfo->min_DCT_scaled_size; + } + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; /* height of a row group of component */ + mainPtr->buffer[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * compptr->DCT_scaled_size, + (JDIMENSION) (rgroup * ngroups)); + } +} diff --git a/Utilities/vtkjpeg/jdmarker.c b/Utilities/vtkjpeg/jdmarker.c new file mode 100644 index 0000000..f4cca8c --- /dev/null +++ b/Utilities/vtkjpeg/jdmarker.c @@ -0,0 +1,1360 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains routines to decode JPEG datastream markers. + * Most of the complexity arises from our desire to support input + * suspension: if not all of the data for a marker is available, + * we must exit back to the application. On resumption, we reprocess + * the marker. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +/* Private state */ + +typedef struct { + struct jpeg_marker_reader pub; /* public fields */ + + /* Application-overridable marker processing methods */ + jpeg_marker_parser_method process_COM; + jpeg_marker_parser_method process_APPn[16]; + + /* Limit on marker data length to save for each marker type */ + unsigned int length_limit_COM; + unsigned int length_limit_APPn[16]; + + /* Status of COM/APPn marker saving */ + jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */ + unsigned int bytes_read; /* data bytes read so far in marker */ + /* Note: cur_marker is not linked into marker_list until it's all read. */ +} my_marker_reader; + +typedef my_marker_reader * my_marker_ptr; + + +/* + * Macros for fetching data from the data source module. + * + * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect + * the current restart point; we update them only when we have reached a + * suitable place to restart if a suspension occurs. + */ + +/* Declare and initialize local copies of input pointer/count */ +#define INPUT_VARS(cinfo) \ + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer + +/* Unload the local copies --- do this only at a restart boundary */ +#define INPUT_SYNC(cinfo) \ + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) + +/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ +#define INPUT_RELOAD(cinfo) \ + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) + +/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. + * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + * but we must reload the local copies after a successful fill. + */ +#define MAKE_BYTE_AVAIL(cinfo,action) \ + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } + +/* Read a byte into variable V. + * If must suspend, take the specified action (typically "return FALSE"). + */ +#define INPUT_BYTE(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) + +/* As above, but read two bytes interpreted as an unsigned 16-bit integer. + * V should be declared unsigned int or perhaps INT32. + */ +#define INPUT_2BYTES(cinfo,V,action) \ + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) + + +/* + * Routines to process JPEG markers. + * + * Entry condition: JPEG marker itself has been read and its code saved + * in cinfo->unread_marker; input restart point is just after the marker. + * + * Exit: if return TRUE, have read and processed any parameters, and have + * updated the restart point to point after the parameters. + * If return FALSE, was forced to suspend before reaching end of + * marker parameters; restart point has not been moved. Same routine + * will be called again after application supplies more input data. + * + * This approach to suspension assumes that all of a marker's parameters + * can fit into a single input bufferload. This should hold for "normal" + * markers. Some COM/APPn markers might have large parameter segments + * that might not fit. If we are simply dropping such a marker, we use + * skip_input_data to get past it, and thereby put the problem on the + * source manager's shoulders. If we are saving the marker's contents + * into memory, we use a slightly different convention: when forced to + * suspend, the marker processor updates the restart point to the end of + * what it's consumed (ie, the end of the buffer) before returning FALSE. + * On resumption, cinfo->unread_marker still contains the marker code, + * but the data source will point to the next chunk of marker data. + * The marker processor must retain internal state to deal with this. + * + * Note that we don't bother to avoid duplicate trace messages if a + * suspension occurs within marker parameters. Other side effects + * require more care. + */ + + +LOCAL(boolean) +get_soi (j_decompress_ptr cinfo) +/* Process an SOI marker */ +{ + int i; + + TRACEMS(cinfo, 1, JTRC_SOI); + + if (cinfo->marker->saw_SOI) + ERREXIT(cinfo, JERR_SOI_DUPLICATE); + + /* Reset all parameters that are defined to be reset by SOI */ + + for (i = 0; i < NUM_ARITH_TBLS; i++) { + cinfo->arith_dc_L[i] = 0; + cinfo->arith_dc_U[i] = 1; + cinfo->arith_ac_K[i] = 5; + } + cinfo->restart_interval = 0; + + /* Set initial assumptions for colorspace etc */ + + cinfo->jpeg_color_space = JCS_UNKNOWN; + cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ + + cinfo->saw_JFIF_marker = FALSE; + cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */ + cinfo->JFIF_minor_version = 1; + cinfo->density_unit = 0; + cinfo->X_density = 1; + cinfo->Y_density = 1; + cinfo->saw_Adobe_marker = FALSE; + cinfo->Adobe_transform = 0; + + cinfo->marker->saw_SOI = TRUE; + + return TRUE; +} + + +LOCAL(boolean) +get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) +/* Process a SOFn marker */ +{ + INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->progressive_mode = is_prog; + cinfo->arith_code = is_arith; + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); + INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); + INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); + + length -= 8; + + TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); + + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_DUPLICATE); + + /* We don't support files in which the image height is initially specified */ + /* as 0 and is later redefined by DNL. As long as we have to check that, */ + /* might as well have a general sanity check. */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 + || cinfo->num_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + if (length != (cinfo->num_components * 3)) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + if (cinfo->comp_info == NULL) /* do only once, even if suspend */ + cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * SIZEOF(jpeg_component_info)); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->component_index = ci; + INPUT_BYTE(cinfo, compptr->component_id, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + compptr->h_samp_factor = (c >> 4) & 15; + compptr->v_samp_factor = (c ) & 15; + INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); + + TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); + } + + cinfo->marker->saw_SOF = TRUE; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_sos (j_decompress_ptr cinfo) +/* Process a SOS marker */ +{ + INT32 length; + int i, ci, n, c, cc; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + if (! cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOS_NO_SOF); + + INPUT_2BYTES(cinfo, length, return FALSE); + + INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ + + TRACEMS1(cinfo, 1, JTRC_SOS, n); + + if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + cinfo->comps_in_scan = n; + + /* Collect the component-spec parameters */ + + for (i = 0; i < n; i++) { + INPUT_BYTE(cinfo, cc, return FALSE); + INPUT_BYTE(cinfo, c, return FALSE); + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + if (cc == compptr->component_id) + goto id_found; + } + + ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo->cur_comp_info[i] = compptr; + compptr->dc_tbl_no = (c >> 4) & 15; + compptr->ac_tbl_no = (c ) & 15; + + TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, + compptr->dc_tbl_no, compptr->ac_tbl_no); + } + + /* Collect the additional scan parameters Ss, Se, Ah/Al. */ + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ss = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Se = c; + INPUT_BYTE(cinfo, c, return FALSE); + cinfo->Ah = (c >> 4) & 15; + cinfo->Al = (c ) & 15; + + TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, + cinfo->Ah, cinfo->Al); + + /* Prepare to scan data & restart markers */ + cinfo->marker->next_restart_num = 0; + + /* Count another SOS marker */ + cinfo->input_scan_number++; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +#ifdef D_ARITH_CODING_SUPPORTED + +LOCAL(boolean) +get_dac (j_decompress_ptr cinfo) +/* Process a DAC marker */ +{ + INT32 length; + int index, val; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, index, return FALSE); + INPUT_BYTE(cinfo, val, return FALSE); + + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_DAC, index, val); + + if (index < 0 || index >= (2*NUM_ARITH_TBLS)) + ERREXIT1(cinfo, JERR_DAC_INDEX, index); + + if (index >= NUM_ARITH_TBLS) { /* define AC table */ + cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; + } else { /* define DC table */ + cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); + cinfo->arith_dc_U[index] = (UINT8) (val >> 4); + if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) + ERREXIT1(cinfo, JERR_DAC_VALUE, val); + } + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + +#else /* ! D_ARITH_CODING_SUPPORTED */ + +#define get_dac(cinfo) skip_variable(cinfo) + +#endif /* D_ARITH_CODING_SUPPORTED */ + + +LOCAL(boolean) +get_dht (j_decompress_ptr cinfo) +/* Process a DHT marker */ +{ + INT32 length; + UINT8 bits[17]; + UINT8 huffval[256]; + int i, index, count; + JHUFF_TBL **htblptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 16) { + INPUT_BYTE(cinfo, index, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DHT, index); + + bits[0] = 0; + count = 0; + for (i = 1; i <= 16; i++) { + INPUT_BYTE(cinfo, bits[i], return FALSE); + count += bits[i]; + } + + length -= 1 + 16; + + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(cinfo, 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + + /* Here we just do minimal validation of the counts to avoid walking + * off the end of our table space. jdhuff.c will check more carefully. + */ + if (count > 256 || ((INT32) count) > length) + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + + for (i = 0; i < count; i++) + INPUT_BYTE(cinfo, huffval[i], return FALSE); + + length -= count; + + if (index & 0x10) { /* AC table definition */ + index -= 0x10; + htblptr = &cinfo->ac_huff_tbl_ptrs[index]; + } else { /* DC table definition */ + htblptr = &cinfo->dc_huff_tbl_ptrs[index]; + } + + if (index < 0 || index >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_DHT_INDEX, index); + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); + MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dqt (j_decompress_ptr cinfo) +/* Process a DQT marker */ +{ + INT32 length; + int n, i, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + INPUT_BYTE(cinfo, n, return FALSE); + prec = n >> 4; + n &= 0x0F; + + TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); + + if (n >= NUM_QUANT_TBLS) + ERREXIT1(cinfo, JERR_DQT_INDEX, n); + + if (cinfo->quant_tbl_ptrs[n] == NULL) + cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); + quant_ptr = cinfo->quant_tbl_ptrs[n]; + + for (i = 0; i < DCTSIZE2; i++) { + if (prec) + INPUT_2BYTES(cinfo, tmp, return FALSE); + else + INPUT_BYTE(cinfo, tmp, return FALSE); + /* We convert the zigzag-order table to natural array order. */ + quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + } + + if (cinfo->err->trace_level >= 2) { + for (i = 0; i < DCTSIZE2; i += 8) { + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + } + } + + length -= DCTSIZE2+1; + if (prec) length -= DCTSIZE2; + } + + if (length != 0) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +get_dri (j_decompress_ptr cinfo) +/* Process a DRI marker */ +{ + INT32 length; + unsigned int tmp; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + + if (length != 4) + ERREXIT(cinfo, JERR_BAD_LENGTH); + + INPUT_2BYTES(cinfo, tmp, return FALSE); + + TRACEMS1(cinfo, 1, JTRC_DRI, tmp); + + cinfo->restart_interval = tmp; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Routines for processing APPn and COM markers. + * These are either saved in memory or discarded, per application request. + * APP0 and APP14 are specially checked to see if they are + * JFIF and Adobe markers, respectively. + */ + +#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */ +#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */ +#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */ + + +LOCAL(void) +examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP0. + * Take appropriate action if it is a JFIF marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + INT32 totallen = (INT32) datalen + remaining; + + if (datalen >= APP0_DATA_LEN && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x49 && + GETJOCTET(data[3]) == 0x46 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF APP0 marker: save info */ + cinfo->saw_JFIF_marker = TRUE; + cinfo->JFIF_major_version = GETJOCTET(data[5]); + cinfo->JFIF_minor_version = GETJOCTET(data[6]); + cinfo->density_unit = GETJOCTET(data[7]); + cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); + cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); + /* Check version. + * Major version must be 1, anything else signals an incompatible change. + * (We used to treat this as an error, but now it's a nonfatal warning, + * because some bozo at Hijaak couldn't read the spec.) + * Minor version should be 0..2, but process anyway if newer. + */ + if (cinfo->JFIF_major_version != 1) + WARNMS2(cinfo, JWRN_JFIF_MAJOR, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + /* Generate trace messages */ + TRACEMS5(cinfo, 1, JTRC_JFIF, + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + /* Validate thumbnail dimensions and issue appropriate messages */ + if (GETJOCTET(data[12]) | GETJOCTET(data[13])) + TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + totallen -= APP0_DATA_LEN; + if (totallen != + ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) + TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); + } else if (datalen >= 6 && + GETJOCTET(data[0]) == 0x4A && + GETJOCTET(data[1]) == 0x46 && + GETJOCTET(data[2]) == 0x58 && + GETJOCTET(data[3]) == 0x58 && + GETJOCTET(data[4]) == 0) { + /* Found JFIF "JFXX" extension APP0 marker */ + /* The library doesn't actually do anything with these, + * but we try to produce a helpful trace message. + */ + switch (GETJOCTET(data[5])) { + case 0x10: + TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen); + break; + case 0x11: + TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen); + break; + case 0x13: + TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen); + break; + default: + TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), (int) totallen); + break; + } + } else { + /* Start of APP0 does not match "JFIF" or "JFXX", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen); + } +} + + +LOCAL(void) +examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, + unsigned int datalen, INT32 remaining) +/* Examine first few bytes from an APP14. + * Take appropriate action if it is an Adobe marker. + * datalen is # of bytes at data[], remaining is length of rest of marker data. + */ +{ + unsigned int version, flags0, flags1, transform; + + if (datalen >= APP14_DATA_LEN && + GETJOCTET(data[0]) == 0x41 && + GETJOCTET(data[1]) == 0x64 && + GETJOCTET(data[2]) == 0x6F && + GETJOCTET(data[3]) == 0x62 && + GETJOCTET(data[4]) == 0x65) { + /* Found Adobe APP14 marker */ + version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]); + flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]); + flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]); + transform = GETJOCTET(data[11]); + TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); + cinfo->saw_Adobe_marker = TRUE; + cinfo->Adobe_transform = (UINT8) transform; + } else { + /* Start of APP14 does not match "Adobe", or too short */ + TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining)); + } +} + + +METHODDEF(boolean) +get_interesting_appn (j_decompress_ptr cinfo) +/* Process an APP0 or APP14 marker without saving it */ +{ + INT32 length; + JOCTET b[APPN_DATA_LEN]; + unsigned int i, numtoread; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + /* get the interesting part of the marker data */ + if (length >= APPN_DATA_LEN) + numtoread = APPN_DATA_LEN; + else if (length > 0) + numtoread = (unsigned int) length; + else + numtoread = 0; + for (i = 0; i < numtoread; i++) + INPUT_BYTE(cinfo, b[i], return FALSE); + length -= numtoread; + + /* process it */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + case M_APP14: + examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length); + break; + default: + /* can't get here unless jpeg_save_markers chooses wrong processor */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +#ifdef SAVE_MARKERS_SUPPORTED + +METHODDEF(boolean) +save_marker (j_decompress_ptr cinfo) +/* Save an APPn or COM marker into the marker list */ +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + jpeg_saved_marker_ptr cur_marker = marker->cur_marker; + unsigned int bytes_read, data_length; + JOCTET FAR * data; + INT32 length = 0; + INPUT_VARS(cinfo); + + if (cur_marker == NULL) { + /* begin reading a marker */ + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + if (length >= 0) { /* watch out for bogus length word */ + /* figure out how much we want to save */ + unsigned int limit; + if (cinfo->unread_marker == (int) M_COM) + limit = marker->length_limit_COM; + else + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + if ((unsigned int) length < limit) + limit = (unsigned int) length; + /* allocate and initialize the marker item */ + cur_marker = (jpeg_saved_marker_ptr) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); + cur_marker->next = NULL; + cur_marker->marker = (UINT8) cinfo->unread_marker; + cur_marker->original_length = (unsigned int) length; + cur_marker->data_length = limit; + /* data area is just beyond the jpeg_marker_struct */ + data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1); + marker->cur_marker = cur_marker; + marker->bytes_read = 0; + bytes_read = 0; + data_length = limit; + } else { + /* deal with bogus length word */ + bytes_read = data_length = 0; + data = NULL; + } + } else { + /* resume reading a marker */ + bytes_read = marker->bytes_read; + data_length = cur_marker->data_length; + data = cur_marker->data + bytes_read; + } + + while (bytes_read < data_length) { + INPUT_SYNC(cinfo); /* move the restart point to here */ + marker->bytes_read = bytes_read; + /* If there's not at least one byte in buffer, suspend */ + MAKE_BYTE_AVAIL(cinfo, return FALSE); + /* Copy bytes with reasonable rapidity */ + while (bytes_read < data_length && bytes_in_buffer > 0) { + *data++ = *next_input_byte++; + bytes_in_buffer--; + bytes_read++; + } + } + + /* Done reading what we want to read */ + if (cur_marker != NULL) { /* will be NULL if bogus length word */ + /* Add new marker to end of list */ + if (cinfo->marker_list == NULL) { + cinfo->marker_list = cur_marker; + } else { + jpeg_saved_marker_ptr prev = cinfo->marker_list; + while (prev->next != NULL) + prev = prev->next; + prev->next = cur_marker; + } + /* Reset pointer & calc remaining data length */ + data = cur_marker->data; + length = cur_marker->original_length - data_length; + } + /* Reset to initial state for next marker */ + marker->cur_marker = NULL; + + /* Process the marker if interesting; else just make a generic trace msg */ + switch (cinfo->unread_marker) { + case M_APP0: + examine_app0(cinfo, data, data_length, length); + break; + case M_APP14: + examine_app14(cinfo, data, data_length, length); + break; + default: + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, + (int) (data_length + length)); + break; + } + + /* skip any remaining data -- could be lots */ + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +METHODDEF(boolean) +skip_variable (j_decompress_ptr cinfo) +/* Skip over an unknown or uninteresting variable-length marker */ +{ + INT32 length; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); + + INPUT_SYNC(cinfo); /* do before skip_input_data */ + if (length > 0) + (*cinfo->src->skip_input_data) (cinfo, (long) length); + + return TRUE; +} + + +/* + * Find the next JPEG marker, save it in cinfo->unread_marker. + * Returns FALSE if had to suspend before reaching a marker; + * in that case cinfo->unread_marker is unchanged. + * + * Note that the result might not be a valid marker code, + * but it will never be 0 or FF. + */ + +LOCAL(boolean) +next_marker (j_decompress_ptr cinfo) +{ + int c; + INPUT_VARS(cinfo); + + for (;;) { + INPUT_BYTE(cinfo, c, return FALSE); + /* Skip any non-FF bytes. + * This may look a bit inefficient, but it will not occur in a valid file. + * We sync after each discarded byte so that a suspending data source + * can discard the byte from its buffer. + */ + while (c != 0xFF) { + cinfo->marker->discarded_bytes++; + INPUT_SYNC(cinfo); + INPUT_BYTE(cinfo, c, return FALSE); + } + /* This loop swallows any duplicate FF bytes. Extra FFs are legal as + * pad bytes, so don't count them in discarded_bytes. We assume there + * will not be so many consecutive FF bytes as to overflow a suspending + * data source's input buffer. + */ + do { + INPUT_BYTE(cinfo, c, return FALSE); + } while (c == 0xFF); + if (c != 0) + break; /* found a valid marker, exit loop */ + /* Reach here if we found a stuffed-zero data sequence (FF/00). + * Discard it and loop back to try again. + */ + cinfo->marker->discarded_bytes += 2; + INPUT_SYNC(cinfo); + } + + if (cinfo->marker->discarded_bytes != 0) { + WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); + cinfo->marker->discarded_bytes = 0; + } + + cinfo->unread_marker = c; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +LOCAL(boolean) +first_marker (j_decompress_ptr cinfo) +/* Like next_marker, but used to obtain the initial SOI marker. */ +/* For this marker, we do not allow preceding garbage or fill; otherwise, + * we might well scan an entire input file before realizing it ain't JPEG. + * If an application wants to process non-JFIF files, it must seek to the + * SOI before calling the JPEG library. + */ +{ + int c, c2; + INPUT_VARS(cinfo); + + INPUT_BYTE(cinfo, c, return FALSE); + INPUT_BYTE(cinfo, c2, return FALSE); + if (c != 0xFF || c2 != (int) M_SOI) + ERREXIT2(cinfo, JERR_NO_SOI, c, c2); + + cinfo->unread_marker = c2; + + INPUT_SYNC(cinfo); + return TRUE; +} + + +/* + * Read markers until SOS or EOI. + * + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + +METHODDEF(int) +read_markers (j_decompress_ptr cinfo) +{ + /* Outer loop repeats once for each marker. */ + for (;;) { + /* Collect the marker proper, unless we already did. */ + /* NB: first_marker() enforces the requirement that SOI appear first. */ + if (cinfo->unread_marker == 0) { + if (! cinfo->marker->saw_SOI) { + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; + } else { + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; + } + } + /* At this point cinfo->unread_marker contains the marker code and the + * input point is just past the marker proper, but before any parameters. + * A suspension will cause us to return with this state still true. + */ + switch (cinfo->unread_marker) { + case M_SOI: + if (! get_soi(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_SOF0: /* Baseline */ + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, TRUE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, TRUE, TRUE)) + return JPEG_SUSPENDED; + break; + + /* Currently unsupported SOFn types */ + case M_SOF3: /* Lossless, Huffman */ + case M_SOF5: /* Differential sequential, Huffman */ + case M_SOF6: /* Differential progressive, Huffman */ + case M_SOF7: /* Differential lossless, Huffman */ + case M_JPG: /* Reserved for JPEG extensions */ + case M_SOF11: /* Lossless, arithmetic */ + case M_SOF13: /* Differential sequential, arithmetic */ + case M_SOF14: /* Differential progressive, arithmetic */ + case M_SOF15: /* Differential lossless, arithmetic */ + ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); + break; + + case M_SOS: + if (! get_sos(cinfo)) + return JPEG_SUSPENDED; + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_SOS; + + case M_EOI: + TRACEMS(cinfo, 1, JTRC_EOI); + cinfo->unread_marker = 0; /* processed the marker */ + return JPEG_REACHED_EOI; + + case M_DAC: + if (! get_dac(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DHT: + if (! get_dht(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DQT: + if (! get_dqt(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_DRI: + if (! get_dri(cinfo)) + return JPEG_SUSPENDED; + break; + + case M_APP0: + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP14: + case M_APP15: + if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_COM: + if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) + return JPEG_SUSPENDED; + break; + + case M_RST0: /* these are all parameterless */ + case M_RST1: + case M_RST2: + case M_RST3: + case M_RST4: + case M_RST5: + case M_RST6: + case M_RST7: + case M_TEM: + TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); + break; + + case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ + if (! skip_variable(cinfo)) + return JPEG_SUSPENDED; + break; + + default: /* must be DHP, EXP, JPGn, or RESn */ + /* For now, we treat the reserved markers as fatal errors since they are + * likely to be used to signal incompatible JPEG Part 3 extensions. + * Once the JPEG 3 version-number marker is well defined, this code + * ought to change! + */ + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker); + break; + } + /* Successfully processed marker, so reset state variable */ + cinfo->unread_marker = 0; + } /* end loop */ +} + + +/* + * Read a restart marker, which is expected to appear next in the datastream; + * if the marker is not there, take appropriate recovery action. + * Returns FALSE if suspension is required. + * + * This is called by the entropy decoder after it has read an appropriate + * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder + * has already read a marker from the data source. Under normal conditions + * cinfo->unread_marker will be reset to 0 before returning; if not reset, + * it holds a marker which the decoder will be unable to read past. + */ + +METHODDEF(boolean) +read_restart_marker (j_decompress_ptr cinfo) +{ + /* Obtain a marker unless we already did. */ + /* Note that next_marker will complain if it skips any data. */ + if (cinfo->unread_marker == 0) { + if (! next_marker(cinfo)) + return FALSE; + } + + if (cinfo->unread_marker == + ((int) M_RST0 + cinfo->marker->next_restart_num)) { + /* Normal case --- swallow the marker and let entropy decoder continue */ + TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num); + cinfo->unread_marker = 0; + } else { + /* Uh-oh, the restart markers have been messed up. */ + /* Let the data source manager determine how to resync. */ + if (! (*cinfo->src->resync_to_restart) (cinfo, + cinfo->marker->next_restart_num)) + return FALSE; + } + + /* Update next-restart state */ + cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; + + return TRUE; +} + + +/* + * This is the default resync_to_restart method for data source managers + * to use if they don't have any better approach. Some data source managers + * may be able to back up, or may have additional knowledge about the data + * which permits a more intelligent recovery strategy; such managers would + * presumably supply their own resync method. + * + * read_restart_marker calls resync_to_restart if it finds a marker other than + * the restart marker it was expecting. (This code is *not* used unless + * a nonzero restart interval has been declared.) cinfo->unread_marker is + * the marker code actually found (might be anything, except 0 or FF). + * The desired restart marker number (0..7) is passed as a parameter. + * This routine is supposed to apply whatever error recovery strategy seems + * appropriate in order to position the input stream to the next data segment. + * Note that cinfo->unread_marker is treated as a marker appearing before + * the current data-source input point; usually it should be reset to zero + * before returning. + * Returns FALSE if suspension is required. + * + * This implementation is substantially constrained by wanting to treat the + * input as a data stream; this means we can't back up. Therefore, we have + * only the following actions to work with: + * 1. Simply discard the marker and let the entropy decoder resume at next + * byte of file. + * 2. Read forward until we find another marker, discarding intervening + * data. (In theory we could look ahead within the current bufferload, + * without having to discard data if we don't find the desired marker. + * This idea is not implemented here, in part because it makes behavior + * dependent on buffer size and chance buffer-boundary positions.) + * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). + * This will cause the entropy decoder to process an empty data segment, + * inserting dummy zeroes, and then we will reprocess the marker. + * + * #2 is appropriate if we think the desired marker lies ahead, while #3 is + * appropriate if the found marker is a future restart marker (indicating + * that we have missed the desired restart marker, probably because it got + * corrupted). + * We apply #2 or #3 if the found marker is a restart marker no more than + * two counts behind or ahead of the expected one. We also apply #2 if the + * found marker is not a legal JPEG marker code (it's certainly bogus data). + * If the found marker is a restart marker more than 2 counts away, we do #1 + * (too much risk that the marker is erroneous; with luck we will be able to + * resync at some future point). + * For any valid non-restart JPEG marker, we apply #3. This keeps us from + * overrunning the end of a scan. An implementation limited to single-scan + * files might find it better to apply #2 for markers other than EOI, since + * any other marker would have to be bogus data in that case. + */ + +GLOBAL(boolean) +jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) +{ + int marker = cinfo->unread_marker; + int action = 1; + + /* Always put up a warning. */ + WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); + + /* Outer loop handles repeated decision after scanning forward. */ + for (;;) { + if (marker < (int) M_SOF0) + action = 2; /* invalid marker */ + else if (marker < (int) M_RST0 || marker > (int) M_RST7) + action = 3; /* valid non-restart marker */ + else { + if (marker == ((int) M_RST0 + ((desired+1) & 7)) || + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ + else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ + else + action = 1; /* desired restart or too far away */ + } + TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); + switch (action) { + case 1: + /* Discard marker and let entropy decoder resume processing. */ + cinfo->unread_marker = 0; + return TRUE; + case 2: + /* Scan to the next marker, and repeat the decision loop. */ + if (! next_marker(cinfo)) + return FALSE; + marker = cinfo->unread_marker; + break; + case 3: + /* Return without advancing past this marker. */ + /* Entropy decoder will be forced to process an empty segment. */ + return TRUE; + } + } /* end loop */ +} + + +/* + * Reset marker processing state to begin a fresh datastream. + */ + +METHODDEF(void) +reset_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + cinfo->comp_info = NULL; /* until allocated by get_sof */ + cinfo->input_scan_number = 0; /* no SOS seen yet */ + cinfo->unread_marker = 0; /* no pending marker */ + marker->pub.saw_SOI = FALSE; /* set internal state too */ + marker->pub.saw_SOF = FALSE; + marker->pub.discarded_bytes = 0; + marker->cur_marker = NULL; +} + + +/* + * Initialize the marker reader module. + * This is called only once, when the decompression object is created. + */ + +GLOBAL(void) +jinit_marker_reader (j_decompress_ptr cinfo) +{ + my_marker_ptr marker; + int i; + + /* Create subobject in permanent pool */ + marker = (my_marker_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_marker_reader)); + cinfo->marker = (struct jpeg_marker_reader *) marker; + /* Initialize public method pointers */ + marker->pub.reset_marker_reader = reset_marker_reader; + marker->pub.read_markers = read_markers; + marker->pub.read_restart_marker = read_restart_marker; + /* Initialize COM/APPn processing. + * By default, we examine and then discard APP0 and APP14, + * but simply discard COM and all other APPn. + */ + marker->process_COM = skip_variable; + marker->length_limit_COM = 0; + for (i = 0; i < 16; i++) { + marker->process_APPn[i] = skip_variable; + marker->length_limit_APPn[i] = 0; + } + marker->process_APPn[0] = get_interesting_appn; + marker->process_APPn[14] = get_interesting_appn; + /* Reset marker processing state */ + reset_marker_reader(cinfo); +} + + +/* + * Control saving of COM and APPn markers into marker_list. + */ + +#ifdef SAVE_MARKERS_SUPPORTED + +GLOBAL(void) +jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + long maxlength; + jpeg_marker_parser_method processor; + + /* Length limit mustn't be larger than what we can allocate + * (should only be a concern in a 16-bit environment). + */ + maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct); + if (((long) length_limit) > maxlength) + length_limit = (unsigned int) maxlength; + + /* Choose processor routine to use. + * APP0/APP14 have special requirements. + */ + if (length_limit) { + processor = save_marker; + /* If saving APP0/APP14, save at least enough for our internal use. */ + if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN) + length_limit = APP0_DATA_LEN; + else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN) + length_limit = APP14_DATA_LEN; + } else { + processor = skip_variable; + /* If discarding APP0/APP14, use our regular on-the-fly processor. */ + if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14) + processor = get_interesting_appn; + } + + if (marker_code == (int) M_COM) { + marker->process_COM = processor; + marker->length_limit_COM = length_limit; + } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) { + marker->process_APPn[marker_code - (int) M_APP0] = processor; + marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit; + } else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} + +#endif /* SAVE_MARKERS_SUPPORTED */ + + +/* + * Install a special processing method for COM or APPn markers. + */ + +GLOBAL(void) +jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine) +{ + my_marker_ptr marker = (my_marker_ptr) cinfo->marker; + + if (marker_code == (int) M_COM) + marker->process_COM = routine; + else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) + marker->process_APPn[marker_code - (int) M_APP0] = routine; + else + ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code); +} diff --git a/Utilities/vtkjpeg/jdmaster.c b/Utilities/vtkjpeg/jdmaster.c new file mode 100644 index 0000000..2802c5b --- /dev/null +++ b/Utilities/vtkjpeg/jdmaster.c @@ -0,0 +1,557 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains master control logic for the JPEG decompressor. + * These routines are concerned with selecting the modules to be executed + * and with determining the number of passes and the work to be done in each + * pass. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private state */ + +typedef struct { + struct jpeg_decomp_master pub; /* public fields */ + + int pass_number; /* # of passes completed */ + + boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */ + + /* Saved references to initialized quantizer modules, + * in case we need to switch modes. + */ + struct jpeg_color_quantizer * quantizer_1pass; + struct jpeg_color_quantizer * quantizer_2pass; +} my_decomp_master; + +typedef my_decomp_master * my_master_ptr; + + +/* + * Determine whether merged upsample/color conversion should be used. + * CRUCIAL: this must match the actual capabilities of jdmerge.c! + */ + +LOCAL(boolean) +use_merged_upsample (j_decompress_ptr cinfo) +{ +#ifdef UPSAMPLE_MERGING_SUPPORTED + /* Merging is the equivalent of plain box-filter upsampling */ + if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + return FALSE; + /* jdmerge.c only supports YCC=>RGB color conversion */ + if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + cinfo->out_color_space != JCS_RGB || + cinfo->out_color_components != RGB_PIXELSIZE) + return FALSE; + /* and it only handles 2h1v or 2h2v sampling ratios */ + if (cinfo->comp_info[0].h_samp_factor != 2 || + cinfo->comp_info[1].h_samp_factor != 1 || + cinfo->comp_info[2].h_samp_factor != 1 || + cinfo->comp_info[0].v_samp_factor > 2 || + cinfo->comp_info[1].v_samp_factor != 1 || + cinfo->comp_info[2].v_samp_factor != 1) + return FALSE; + /* furthermore, it doesn't work if we've scaled the IDCTs differently */ + if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || + cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) + return FALSE; + /* ??? also need to test for upsample-time rescaling, when & if supported */ + return TRUE; /* by golly, it'll work... */ +#else + return FALSE; +#endif +} + + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + * Also note that it may be called before the master module is initialized! + */ + +GLOBAL(void) +jpeg_calc_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; +#endif + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_READY) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + +#ifdef IDCT_SCALING_SUPPORTED + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * 8 <= cinfo->scale_denom) { + /* Provide 1/8 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 8L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 8L); + cinfo->min_DCT_scaled_size = 1; + } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { + /* Provide 1/4 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 4L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 4L); + cinfo->min_DCT_scaled_size = 2; + } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { + /* Provide 1/2 scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_DCT_scaled_size = 4; + } else { + /* Provide 1/1 scaling */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + cinfo->min_DCT_scaled_size = DCTSIZE; + } + /* In selecting the actual DCT scaling for each component, we try to + * scale up the chroma components via IDCT scaling rather than upsampling. + * This saves time if the upsampler gets to use 1:1 scaling. + * Note this code assumes that the supported DCT scalings are powers of 2. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + int ssize = cinfo->min_DCT_scaled_size; + while (ssize < DCTSIZE && + (compptr->h_samp_factor * ssize * 2 <= + cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && + (compptr->v_samp_factor * ssize * 2 <= + cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { + ssize = ssize * 2; + } + compptr->DCT_scaled_size = ssize; + } + + /* Recompute downsampled dimensions of components; + * application needs to know these if using raw downsampled data. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Size in samples, after IDCT scaling */ + compptr->downsampled_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * + (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_h_samp_factor * DCTSIZE)); + compptr->downsampled_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * + (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), + (long) (cinfo->max_v_samp_factor * DCTSIZE)); + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ + + /* Report number of components in selected colorspace. */ + /* Probably this should be in the color conversion module... */ + switch (cinfo->out_color_space) { + case JCS_GRAYSCALE: + cinfo->out_color_components = 1; + break; + case JCS_RGB: +#if RGB_PIXELSIZE != 3 + cinfo->out_color_components = RGB_PIXELSIZE; + break; +#endif /* else share code with YCbCr */ + case JCS_YCbCr: + cinfo->out_color_components = 3; + break; + case JCS_CMYK: + case JCS_YCCK: + cinfo->out_color_components = 4; + break; + default: /* else must be same colorspace as in file */ + cinfo->out_color_components = cinfo->num_components; + break; + } + cinfo->output_components = (cinfo->quantize_colors ? 1 : + cinfo->out_color_components); + + /* See if upsampler will want to emit more than one row at a time */ + if (use_merged_upsample(cinfo)) + cinfo->rec_outbuf_height = cinfo->max_v_samp_factor; + else + cinfo->rec_outbuf_height = 1; +} + + +/* + * Several decompression processes need to range-limit values to the range + * 0..MAXJSAMPLE; the input value may fall somewhat outside this range + * due to noise introduced by quantization, roundoff error, etc. These + * processes are inner loops and need to be as fast as possible. On most + * machines, particularly CPUs with pipelines or instruction prefetch, + * a (subscript-check-less) C table lookup + * x = sample_range_limit[x]; + * is faster than explicit tests + * if (x < 0) x = 0; + * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; + * These processes all use a common table prepared by the routine below. + * + * For most steps we can mathematically guarantee that the initial value + * of x is within MAXJSAMPLE+1 of the legal range, so a table running from + * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + * limiting step (just after the IDCT), a wildly out-of-range value is + * possible if the input data is corrupt. To avoid any chance of indexing + * off the end of memory and getting a bad-pointer trap, we perform the + * post-IDCT limiting thus: + * x = range_limit[x & MASK]; + * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + * samples. Under normal circumstances this is more than enough range and + * a correct output will be generated; with bogus input data the mask will + * cause wraparound, and we will safely generate a bogus-but-in-range output. + * For the post-IDCT step, we want to convert the data from signed to unsigned + * representation by adding CENTERJSAMPLE at the same time that we limit it. + * So the post-IDCT limiting table ends up looking like this: + * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + * 0,1,...,CENTERJSAMPLE-1 + * Negative inputs select values from the upper half of the table after + * masking. + * + * We can save some space by overlapping the start of the post-IDCT table + * with the simpler range limiting table. The post-IDCT table begins at + * sample_range_limit + CENTERJSAMPLE. + * + * Note that the table is allocated in near data space on PCs; it's small + * enough and used often enough to justify this. + */ + +LOCAL(void) +prepare_range_limit_table (j_decompress_ptr cinfo) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE * table; + int i; + + table = (JSAMPLE *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + cinfo->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE) i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + MEMZERO(table + (2 * (MAXJSAMPLE+1)), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), + cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); +} + + +/* + * Master selection of decompression modules. + * This is done once at jpeg_start_decompress time. We determine + * which modules will be used and give them appropriate initialization calls. + * We also initialize the decompressor input side to begin consuming data. + * + * Since jpeg_read_header has finished, we know what is in the SOF + * and (first) SOS markers. We also have all the application parameter + * settings. + */ + +LOCAL(void) +master_selection (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + boolean use_c_buffer; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* Initialize dimensions and other stuff */ + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + /* Width of an output scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + + /* Initialize my private state */ + master->pass_number = 0; + master->using_merged_upsample = use_merged_upsample(cinfo); + + /* Color quantizer selection */ + master->quantizer_1pass = NULL; + master->quantizer_2pass = NULL; + /* No mode changes if not using buffered-image mode. */ + if (! cinfo->quantize_colors || ! cinfo->buffered_image) { + cinfo->enable_1pass_quant = FALSE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + } + if (cinfo->quantize_colors) { + if (cinfo->raw_data_out) + ERREXIT(cinfo, JERR_NOTIMPL); + /* 2-pass quantizer only works in 3-component color space. */ + if (cinfo->out_color_components != 3) { + cinfo->enable_1pass_quant = TRUE; + cinfo->enable_external_quant = FALSE; + cinfo->enable_2pass_quant = FALSE; + cinfo->colormap = NULL; + } else if (cinfo->colormap != NULL) { + cinfo->enable_external_quant = TRUE; + } else if (cinfo->two_pass_quantize) { + cinfo->enable_2pass_quant = TRUE; + } else { + cinfo->enable_1pass_quant = TRUE; + } + + if (cinfo->enable_1pass_quant) { +#ifdef QUANT_1PASS_SUPPORTED + jinit_1pass_quantizer(cinfo); + master->quantizer_1pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + + /* We use the 2-pass code to map to external colormaps. */ + if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { +#ifdef QUANT_2PASS_SUPPORTED + jinit_2pass_quantizer(cinfo); + master->quantizer_2pass = cinfo->cquantize; +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } + /* If both quantizers are initialized, the 2-pass one is left active; + * this is necessary for starting with quantization to an external map. + */ + } + + /* Post-processing: in particular, color conversion first */ + if (! cinfo->raw_data_out) { + if (master->using_merged_upsample) { +#ifdef UPSAMPLE_MERGING_SUPPORTED + jinit_merged_upsampler(cinfo); /* does color conversion too */ +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + } + jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); + } + /* Inverse DCT */ + jinit_inverse_dct(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Initialize principal buffer controllers. */ + use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + if (! cinfo->raw_data_out) + jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + +#ifdef D_MULTISCAN_FILES_SUPPORTED + /* If jpeg_start_decompress will read the whole file, initialize + * progress monitoring appropriately. The input step is counted + * as one pass. + */ + if (cinfo->progress != NULL && ! cinfo->buffered_image && + cinfo->inputctl->has_multiple_scans) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); + /* Count the input pass as done */ + master->pass_number++; + } +#endif /* D_MULTISCAN_FILES_SUPPORTED */ +} + + +/* + * Per-pass setup. + * This is called at the beginning of each output pass. We determine which + * modules will be active during this pass and give them appropriate + * start_pass calls. We also set is_dummy_pass to indicate whether this + * is a "real" output pass or a dummy pass for color quantization. + * (In the latter case, jdapistd.c will crank the pass to completion.) + */ + +METHODDEF(void) +prepare_for_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (master->pub.is_dummy_pass) { +#ifdef QUANT_2PASS_SUPPORTED + /* Final pass of 2-pass quantization */ + master->pub.is_dummy_pass = FALSE; + (*cinfo->cquantize->start_pass) (cinfo, FALSE); + (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); + (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + if (cinfo->quantize_colors && cinfo->colormap == NULL) { + /* Select new quantization method */ + if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; + } else if (cinfo->enable_1pass_quant) { + cinfo->cquantize = master->quantizer_1pass; + } else { + ERREXIT(cinfo, JERR_MODE_CHANGE); + } + } + (*cinfo->idct->start_pass) (cinfo); + (*cinfo->coef->start_output_pass) (cinfo); + if (! cinfo->raw_data_out) { + if (! master->using_merged_upsample) + (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->upsample->start_pass) (cinfo); + if (cinfo->quantize_colors) + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->post->start_pass) (cinfo, + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); + } + } + + /* Set up progress monitor's pass info if present */ + if (cinfo->progress != NULL) { + cinfo->progress->completed_passes = master->pass_number; + cinfo->progress->total_passes = master->pass_number + + (master->pub.is_dummy_pass ? 2 : 1); + /* In buffered-image mode, we assume one more output pass if EOI not + * yet reached, but no more passes if EOI has been reached. + */ + if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) { + cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1); + } + } +} + + +/* + * Finish up at end of an output pass. + */ + +METHODDEF(void) +finish_output_pass (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + if (cinfo->quantize_colors) + (*cinfo->cquantize->finish_pass) (cinfo); + master->pass_number++; +} + + +#ifdef D_MULTISCAN_FILES_SUPPORTED + +/* + * Switch to a new external colormap between output passes. + */ + +GLOBAL(void) +jpeg_new_colormap (j_decompress_ptr cinfo) +{ + my_master_ptr master = (my_master_ptr) cinfo->master; + + /* Prevent application from calling me at wrong times */ + if (cinfo->global_state != DSTATE_BUFIMAGE) + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + + if (cinfo->quantize_colors && cinfo->enable_external_quant && + cinfo->colormap != NULL) { + /* Select 2-pass quantizer for external colormap use */ + cinfo->cquantize = master->quantizer_2pass; + /* Notify quantizer of colormap change */ + (*cinfo->cquantize->new_color_map) (cinfo); + master->pub.is_dummy_pass = FALSE; /* just in case */ + } else + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + +#endif /* D_MULTISCAN_FILES_SUPPORTED */ + + +/* + * Initialize master decompression control and select active modules. + * This is performed at the start of jpeg_start_decompress. + */ + +GLOBAL(void) +jinit_master_decompress (j_decompress_ptr cinfo) +{ + my_master_ptr master; + + master = (my_master_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_decomp_master)); + cinfo->master = (struct jpeg_decomp_master *) master; + master->pub.prepare_for_output_pass = prepare_for_output_pass; + master->pub.finish_output_pass = finish_output_pass; + + master->pub.is_dummy_pass = FALSE; + + master_selection(cinfo); +} diff --git a/Utilities/vtkjpeg/jdmerge.c b/Utilities/vtkjpeg/jdmerge.c new file mode 100644 index 0000000..e7b6816 --- /dev/null +++ b/Utilities/vtkjpeg/jdmerge.c @@ -0,0 +1,405 @@ +/* + * jdmerge.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains code for merged upsampling/color conversion. + * + * This file combines functions from jdsample.c and jdcolor.c; + * read those files first to understand what's going on. + * + * When the chroma components are to be upsampled by simple replication + * (ie, box filtering), we can save some work in color conversion by + * calculating all the output pixels corresponding to a pair of chroma + * samples at one time. In the conversion equations + * R = Y + K1 * Cr + * G = Y + K2 * Cb + K3 * Cr + * B = Y + K4 * Cb + * only the Y term varies among the group of pixels corresponding to a pair + * of chroma samples, so the rest of the terms can be calculated just once. + * At typical sampling ratios, this eliminates half or three-quarters of the + * multiplications needed for color conversion. + * + * This file currently provides implementations for the following cases: + * YCbCr => RGB color conversion only. + * Sampling ratios of 2h1v or 2h2v. + * No scaling needed at upsample time. + * Corner-aligned (non-CCIR601) sampling alignment. + * Other special cases could be added, but in most applications these are + * the only common cases. (For uncommon cases we fall back on the more + * general code in jdsample.c and jdcolor.c.) + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef UPSAMPLE_MERGING_SUPPORTED + + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Pointer to routine to do actual upsampling/conversion of one row group */ + JMETHOD(void, upmethod, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); + + /* Private state for YCC->RGB conversion */ + int * Cr_r_tab; /* => table for Cr to R conversion */ + int * Cb_b_tab; /* => table for Cb to B conversion */ + INT32 * Cr_g_tab; /* => table for Cr to G conversion */ + INT32 * Cb_g_tab; /* => table for Cb to G conversion */ + + /* For 2:1 vertical sampling, we produce two output rows at a time. + * We need a "spare" row buffer to hold the second output row if the + * application provides just a one-row buffer; we also use the spare + * to discard the dummy last row if the image height is odd. + */ + JSAMPROW spare_row; + boolean spare_full; /* T if spare buffer is occupied */ + + JDIMENSION out_row_width; /* samples per output row */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + +#define SCALEBITS 16 /* speediest right-shift on some machines */ +#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) +#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) + + +/* + * Initialize tables for YCC->RGB colorspace conversion. + * This is taken directly from jdcolor.c; see that file for more info. + */ + +LOCAL(void) +build_ycc_rgb_table (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + upsample->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 1.40200 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.77200 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.71414 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; + /* Cb=>G value is scaled-up -0.34414 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + } +} + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_merged_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the spare buffer empty */ + upsample->spare_full = FALSE; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * The control routine just handles the row buffering considerations. + */ + +METHODDEF(void) +merged_2v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 2:1 vertical sampling case: may need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPROW work_ptrs[2]; + JDIMENSION num_rows; /* number of rows returned to caller */ + + in_row_groups_avail = 0; + + if (upsample->spare_full) { + /* If we have a spare row saved from a previous cycle, just return it. */ + jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, + 1, upsample->out_row_width); + num_rows = 1; + upsample->spare_full = FALSE; + } else { + /* Figure number of rows to return to caller. */ + num_rows = 2; + /* Not more than the distance to the end of the image. */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + /* Create output pointer array for upsampler. */ + work_ptrs[0] = output_buf[*out_row_ctr]; + if (num_rows > 1) { + work_ptrs[1] = output_buf[*out_row_ctr + 1]; + } else { + work_ptrs[1] = upsample->spare_row; + upsample->spare_full = TRUE; + } + /* Now do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); + } + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (! upsample->spare_full) + (*in_row_group_ctr)++; +} + + +METHODDEF(void) +merged_1v_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +/* 1:1 vertical sampling case: much easier, never need a spare row. */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + in_row_groups_avail = 0; + out_rows_avail = 0; + + /* Just do the upsampling. */ + (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, + output_buf + *out_row_ctr); + /* Adjust counts */ + (*out_row_ctr)++; + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by the control routines to do + * the actual upsampling/conversion. One row group is processed per call. + * + * Note: since we may be writing directly into application-supplied buffers, + * we have to be honest about the output width; we can't assume the buffer + * has been rounded up to an even width. + */ + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. + */ + +METHODDEF(void) +h2v1_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr; + JSAMPROW inptr0, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr0 = input_buf[0][in_row_group_ctr]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr = output_buf[0]; + /* Loop for each pair of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 2 Y values and emit 2 pixels */ + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr0++); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr0); + outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_GREEN] = range_limit[y + cgreen]; + outptr[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. + */ + +METHODDEF(void) +h2v2_merged_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + register int y, cred, cgreen, cblue; + int cb, cr; + register JSAMPROW outptr0, outptr1; + JSAMPROW inptr00, inptr01, inptr1, inptr2; + JDIMENSION col; + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + int * Crrtab = upsample->Cr_r_tab; + int * Cbbtab = upsample->Cb_b_tab; + INT32 * Crgtab = upsample->Cr_g_tab; + INT32 * Cbgtab = upsample->Cb_g_tab; + SHIFT_TEMPS + + inptr00 = input_buf[0][in_row_group_ctr*2]; + inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; + inptr1 = input_buf[1][in_row_group_ctr]; + inptr2 = input_buf[2][in_row_group_ctr]; + outptr0 = output_buf[0]; + outptr1 = output_buf[1]; + /* Loop for each group of output pixels */ + for (col = cinfo->output_width >> 1; col > 0; col--) { + /* Do the chroma part of the calculation */ + cb = GETJSAMPLE(*inptr1++); + cr = GETJSAMPLE(*inptr2++); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + /* Fetch 4 Y values and emit 4 pixels */ + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr00++); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + y = GETJSAMPLE(*inptr01++); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1 += RGB_PIXELSIZE; + } + /* If image width is odd, do the last output column separately */ + if (cinfo->output_width & 1) { + cb = GETJSAMPLE(*inptr1); + cr = GETJSAMPLE(*inptr2); + cred = Crrtab[cr]; + cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); + cblue = Cbbtab[cb]; + y = GETJSAMPLE(*inptr00); + outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_GREEN] = range_limit[y + cgreen]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; + y = GETJSAMPLE(*inptr01); + outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_GREEN] = range_limit[y + cgreen]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; + } +} + + +/* + * Module initialization routine for merged upsampling/color conversion. + * + * NB: this is called under the conditions determined by use_merged_upsample() + * in jdmaster.c. That routine MUST correspond to the actual capabilities + * of this module; no safety checks are made here. + */ + +GLOBAL(void) +jinit_merged_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_merged_upsample; + upsample->pub.need_context_rows = FALSE; + + upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; + + if (cinfo->max_v_samp_factor == 2) { + upsample->pub.upsample = merged_2v_upsample; + upsample->upmethod = h2v2_merged_upsample; + /* Allocate a spare row buffer */ + upsample->spare_row = (JSAMPROW) + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + } else { + upsample->pub.upsample = merged_1v_upsample; + upsample->upmethod = h2v1_merged_upsample; + /* No spare row needed */ + upsample->spare_row = NULL; + } + + build_ycc_rgb_table(cinfo); +} + +#endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jdphuff.c b/Utilities/vtkjpeg/jdphuff.c new file mode 100644 index 0000000..2267809 --- /dev/null +++ b/Utilities/vtkjpeg/jdphuff.c @@ -0,0 +1,668 @@ +/* + * jdphuff.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains Huffman entropy decoding routines for progressive JPEG. + * + * Much of the complexity here has to do with supporting input suspension. + * If the data source module demands suspension, we want to be able to back + * up to the start of the current MCU. To do this, we copy state variables + * into local working storage, and update them back to the permanent + * storage only upon successful completion of an MCU. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdhuff.h" /* Declarations shared with jdhuff.c */ + + +#ifdef D_PROGRESSIVE_SUPPORTED + +/* + * Expanded entropy decoder object for progressive Huffman decoding. + * + * The savable_state subrecord contains fields that change within an MCU, + * but must not be updated permanently until we complete the MCU. + */ + +typedef struct { + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ +} savable_state; + +/* This macro is to work around compilers with missing or broken + * structure assignment. You'll need to fix this code if you have + * such a compiler and you change MAX_COMPS_IN_SCAN. + */ + +#ifndef NO_STRUCT_ASSIGN +#define ASSIGN_STATE(dest,src) ((dest) = (src)) +#else +#if MAX_COMPS_IN_SCAN == 4 +#define ASSIGN_STATE(dest,src) \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) +#endif +#endif + + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + /* These fields are loaded into local variables at start of each MCU. + * In case of suspension, we exit WITHOUT updating them. + */ + bitread_perm_state bitstate; /* Bit buffer at start of MCU */ + savable_state saved; /* Other state at start of MCU */ + + /* These fields are NOT loaded into local working state. */ + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ +} phuff_entropy_decoder; + +typedef phuff_entropy_decoder * phuff_entropy_ptr; + +/* Forward declarations */ +METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); +METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + boolean is_DC_band, bad; + int ci, coefi, tbl; + int *coef_bit_ptr; + jpeg_component_info * compptr; + + is_DC_band = (cinfo->Ss == 0); + + /* Validate scan parameters */ + bad = FALSE; + if (is_DC_band) { + if (cinfo->Se != 0) + bad = TRUE; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) + bad = TRUE; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + bad = TRUE; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Al != cinfo->Ah-1) + bad = TRUE; + } + if (cinfo->Al > 13) /* need not check for < 0 */ + bad = TRUE; + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + if (bad) + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int cindex = cinfo->cur_comp_info[ci]->component_index; + coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (is_DC_band) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (is_DC_band) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->pub.insufficient_data = FALSE; + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Figure F.12: extend sign bit. + * On some machines, a shift and add will be faster than a table lookup. + */ + +#ifdef AVOID_TABLES + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +#else + +#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) + +static const int extend_test[16] = /* entry n is 2**(n-1) */ + { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, + 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ + { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, + ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, + ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, + ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + +#endif /* AVOID_TABLES */ + + +/* + * Check for a restart marker & resynchronize decoder. + * Returns FALSE if must suspend. + */ + +LOCAL(boolean) +process_restart (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int ci; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + return FALSE; + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; + + /* Reset out-of-data flag, unless read_restart_marker left us smack up + * against a marker. In that case we will end up treating the next data + * segment as empty, and we can avoid producing bogus output pixels by + * leaving the flag set. + */ + if (cinfo->unread_marker == 0) + entropy->pub.insufficient_data = FALSE; + + return TRUE; +} + + +/* + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + * + * We return FALSE if data source requested suspension. In that case no + * changes have been made to permanent state. (Exception: some output + * coefficients may already have been assigned. This is harmless for + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int Al = cinfo->Al; + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = 1 << r; + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; + int Se = cinfo->Se; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + register int s, k, r; + unsigned int EOBRUN; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->pub.insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = jpeg_natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + jpeg_natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Module initialization routine for progressive Huffman entropy decoding. + */ + +GLOBAL(void) +jinit_phuff_decoder (j_decompress_ptr cinfo) +{ + phuff_entropy_ptr entropy; + int *coef_bit_ptr; + int ci, i; + + entropy = (phuff_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass_phuff_decoder; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + + /* Create progression status table */ + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; +} + +#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jdpostct.c b/Utilities/vtkjpeg/jdpostct.c new file mode 100644 index 0000000..43e4f1f --- /dev/null +++ b/Utilities/vtkjpeg/jdpostct.c @@ -0,0 +1,295 @@ +/* + * jdpostct.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the decompression postprocessing controller. + * This controller manages the upsampling, color conversion, and color + * quantization/reduction steps; specifically, it controls the buffering + * between upsample/color conversion and color quantization/reduction. + * + * If no color quantization/reduction is required, then this module has no + * work to do, and it just hands off to the upsample/color conversion code. + * An integrated upsample/convert/quantize process would replace this module + * entirely. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Private buffer controller object */ + +typedef struct { + struct jpeg_d_post_controller pub; /* public fields */ + + /* Color quantization source buffer: this holds output data from + * the upsample/color conversion step to be passed to the quantizer. + * For two-pass color quantization, we need a full-image buffer; + * for one-pass operation, a strip buffer is sufficient. + */ + jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */ + JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ + JDIMENSION strip_height; /* buffer size in rows */ + /* for two-pass mode only: */ + JDIMENSION starting_row; /* row # of first row in current strip */ + JDIMENSION next_row; /* index of next row to fill/empty in strip */ +} my_post_controller; + +typedef my_post_controller * my_post_ptr; + + +/* Forward declarations */ +METHODDEF(void) post_process_1pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#ifdef QUANT_2PASS_SUPPORTED +METHODDEF(void) post_process_prepass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +METHODDEF(void) post_process_2pass + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +#endif + + +/* + * Initialize for a processing pass. + */ + +METHODDEF(void) +start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + + switch (pass_mode) { + case JBUF_PASS_THRU: + if (cinfo->quantize_colors) { + /* Single-pass processing with color quantization. */ + post->pub.post_process_data = post_process_1pass; + /* We could be doing buffered-image output before starting a 2-pass + * color quantization; in that case, jinit_d_post_controller did not + * allocate a strip buffer. Use the virtual-array buffer as workspace. + */ + if (post->buffer == NULL) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); + } + } else { + /* For single-pass processing without color quantization, + * I have no work to do; just call the upsampler directly. + */ + post->pub.post_process_data = cinfo->upsample->upsample; + } + break; +#ifdef QUANT_2PASS_SUPPORTED + case JBUF_SAVE_AND_PASS: + /* First pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_prepass; + break; + case JBUF_CRANK_DEST: + /* Second pass of 2-pass quantization */ + if (post->whole_image == NULL) + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + post->pub.post_process_data = post_process_2pass; + break; +#endif /* QUANT_2PASS_SUPPORTED */ + default: + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); + break; + } + post->starting_row = post->next_row = 0; +} + + +/* + * Process some data in the one-pass (strip buffer) case. + * This is used for color precision reduction as well as one-pass quantization. + */ + +METHODDEF(void) +post_process_1pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + /* Fill the buffer, but not more than what we can dump out in one go. */ + /* Note we rely on the upsampler to detect bottom of image. */ + max_rows = out_rows_avail - *out_row_ctr; + if (max_rows > post->strip_height) + max_rows = post->strip_height; + num_rows = 0; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer, output_buf + *out_row_ctr, (int) num_rows); + *out_row_ctr += num_rows; +} + + +#ifdef QUANT_2PASS_SUPPORTED + +/* + * Process some data in the first pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_prepass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION old_next_row, num_rows; + output_buf = 0; + out_rows_avail = 0; + + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); + } + + /* Upsample some data (up to a strip height's worth). */ + old_next_row = post->next_row; + (*cinfo->upsample->upsample) (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); + + /* Allow quantizer to scan new data. No data is emitted, */ + /* but we advance out_row_ctr so outer loop can tell when we're done. */ + if (post->next_row > old_next_row) { + num_rows = post->next_row - old_next_row; + (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, + (JSAMPARRAY) NULL, (int) num_rows); + *out_row_ctr += num_rows; + } + + /* Advance if we filled the strip. */ + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + + +/* + * Process some data in the second pass of 2-pass quantization. + */ + +METHODDEF(void) +post_process_2pass (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_post_ptr post = (my_post_ptr) cinfo->post; + JDIMENSION num_rows, max_rows; + + input_buf = 0; + in_row_group_ctr = 0; + in_row_groups_avail = 0; + /* Reposition virtual buffer if at start of strip. */ + if (post->next_row == 0) { + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); + } + + /* Determine number of rows to emit. */ + num_rows = post->strip_height - post->next_row; /* available in strip */ + max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ + if (num_rows > max_rows) + num_rows = max_rows; + /* We have to check bottom of image here, can't depend on upsampler. */ + max_rows = cinfo->output_height - post->starting_row; + if (num_rows > max_rows) + num_rows = max_rows; + + /* Quantize and emit data. */ + (*cinfo->cquantize->color_quantize) (cinfo, + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); + *out_row_ctr += num_rows; + + /* Advance if we filled the strip. */ + post->next_row += num_rows; + if (post->next_row >= post->strip_height) { + post->starting_row += post->strip_height; + post->next_row = 0; + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ + + +/* + * Initialize postprocessing controller. + */ + +GLOBAL(void) +jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) +{ + my_post_ptr post; + + post = (my_post_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_post_controller)); + cinfo->post = (struct jpeg_d_post_controller *) post; + post->pub.start_pass = start_pass_dpost; + post->whole_image = NULL; /* flag for no virtual arrays */ + post->buffer = NULL; /* flag for no strip buffer */ + + /* Create the quantization buffer, if needed */ + if (cinfo->quantize_colors) { + /* The buffer strip height is max_v_samp_factor, which is typically + * an efficient number of rows for upsampling to return. + * (In the presence of output rescaling, we might want to be smarter?) + */ + post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; + if (need_full_buffer) { + /* Two-pass color quantization: need full-image storage. */ + /* We round up the number of rows to a multiple of the strip height. */ +#ifdef QUANT_2PASS_SUPPORTED + post->whole_image = (*cinfo->mem->request_virt_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); +#else + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); +#endif /* QUANT_2PASS_SUPPORTED */ + } else { + /* One-pass color quantization: just make a strip buffer. */ + post->buffer = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->out_color_components, + post->strip_height); + } + } +} diff --git a/Utilities/vtkjpeg/jdsample.c b/Utilities/vtkjpeg/jdsample.c new file mode 100644 index 0000000..e6bb456 --- /dev/null +++ b/Utilities/vtkjpeg/jdsample.c @@ -0,0 +1,486 @@ +/* + * jdsample.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains upsampling routines. + * + * Upsampling input data is counted in "row groups". A row group + * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * sample rows of each component. Upsampling will normally produce + * max_v_samp_factor pixel rows from each row group (but this could vary + * if the upsampler is applying a scale factor of its own). + * + * An excellent reference for image resampling is + * Digital Image Warping, George Wolberg, 1990. + * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Pointer to routine to upsample a single component */ +typedef JMETHOD(void, upsample1_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + +/* Private subobject */ + +typedef struct { + struct jpeg_upsampler pub; /* public fields */ + + /* Color conversion buffer. When using separate upsampling and color + * conversion steps, this buffer holds one upsampled row group until it + * has been color converted and output. + * Note: we do not allocate any storage for component(s) which are full-size, + * ie do not need rescaling. The corresponding entry of color_buf[] is + * simply set to point to the input data array, thereby avoiding copying. + */ + JSAMPARRAY color_buf[MAX_COMPONENTS]; + + /* Per-component upsampling method pointers */ + upsample1_ptr methods[MAX_COMPONENTS]; + + int next_row_out; /* counts rows emitted from color_buf */ + JDIMENSION rows_to_go; /* counts rows remaining in image */ + + /* Height of an input row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_expand need not + * recompute them each time. They are unused for other upsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; +} my_upsampler; + +typedef my_upsampler * my_upsample_ptr; + + +/* + * Initialize for an upsampling pass. + */ + +METHODDEF(void) +start_pass_upsample (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + + /* Mark the conversion buffer empty */ + upsample->next_row_out = cinfo->max_v_samp_factor; + /* Initialize total-height counter for detecting bottom of image */ + upsample->rows_to_go = cinfo->output_height; +} + + +/* + * Control routine to do upsampling (and color conversion). + * + * In this version we upsample each component independently. + * We upsample one row group into the conversion buffer, then apply + * color conversion a row at a time. + */ + +METHODDEF(void) +sep_upsample (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int ci; + jpeg_component_info * compptr; + JDIMENSION num_rows; + + in_row_groups_avail = 0; + /* Fill the conversion buffer, if it's empty */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) { + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Invoke per-component upsample method. Notice we pass a POINTER + * to color_buf[ci], so that fullsize_upsample can change it. + */ + (*upsample->methods[ci]) (cinfo, compptr, + input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), + upsample->color_buf + ci); + } + upsample->next_row_out = 0; + } + + /* Color-convert and emit rows */ + + /* How many we have in the buffer: */ + num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); + /* Not more than the distance to the end of the image. Need this test + * in case the image height is not a multiple of max_v_samp_factor: + */ + if (num_rows > upsample->rows_to_go) + num_rows = upsample->rows_to_go; + /* And not more than what the client can accept: */ + out_rows_avail -= *out_row_ctr; + if (num_rows > out_rows_avail) + num_rows = out_rows_avail; + + (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); + + /* Adjust counts */ + *out_row_ctr += num_rows; + upsample->rows_to_go -= num_rows; + upsample->next_row_out += num_rows; + /* When the buffer is emptied, declare this input row group consumed */ + if (upsample->next_row_out >= cinfo->max_v_samp_factor) + (*in_row_group_ctr)++; +} + + +/* + * These are the routines invoked by sep_upsample to upsample pixel values + * of a single component. One row group is processed per call. + */ + + +/* + * For full-size components, we just make color_buf[ci] point at the + * input buffer, and thus avoid copying any data. Note that this is + * safe only because sep_upsample doesn't declare the input row group + * "consumed" until we are done color converting and emitting it. + */ + +METHODDEF(void) +fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + cinfo = 0; + compptr = 0; + *output_data_ptr = input_data; +} + + +/* + * This is a no-op version used for "uninteresting" components. + * These components will not be referenced by color conversion. + */ + +METHODDEF(void) +noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + cinfo = 0; + compptr = 0; + input_data = 0; + *output_data_ptr = NULL; /* safety check */ +} + + +/* + * This version handles any integral sampling ratios. + * This is not used for typical JPEG files, so it need not be fast. + * Nor, for that matter, is it particularly accurate: the algorithm is + * simple replication of the input pixel onto the corresponding output + * pixels. The hi-falutin sampling literature refers to this as a + * "box filter". A box filter tends to introduce visible artifacts, + * so if you are actually going to use 3:1 or 4:1 sampling ratios + * you would be well advised to improve this code. + */ + +METHODDEF(void) +int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + register int h; + JSAMPROW outend; + int h_expand, v_expand; + int inrow, outrow; + + h_expand = upsample->h_expand[compptr->component_index]; + v_expand = upsample->v_expand[compptr->component_index]; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + /* Generate one output row with proper horizontal expansion */ + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + for (h = h_expand; h > 0; h--) { + *outptr++ = invalue; + } + } + /* Generate any additional output rows by duplicating the first one */ + if (v_expand > 1) { + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo->output_width); + } + inrow++; + outrow += v_expand; + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow; + + compptr = 0; + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + } +} + + +/* + * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + * It's still a box filter. + */ + +METHODDEF(void) +h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register JSAMPLE invalue; + JSAMPROW outend; + int inrow, outrow; + + compptr = 0; + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + inptr = input_data[inrow]; + outptr = output_data[outrow]; + outend = outptr + cinfo->output_width; + while (outptr < outend) { + invalue = *inptr++; /* don't need GETJSAMPLE() here */ + *outptr++ = invalue; + *outptr++ = invalue; + } + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo->output_width); + inrow++; + outrow += 2; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + * + * The upsampling algorithm is linear interpolation between pixel centers, + * also known as a "triangle filter". This is a good compromise between + * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + * of the way between input pixel centers. + * + * A note about the "bias" calculations: when rounding fractional values to + * integer, we do not want to always round 0.5 up to the next integer. + * If we did that, we'd introduce a noticeable bias towards larger values. + * Instead, this code is arranged so that 0.5 will be rounded up or down at + * alternate pixel locations (a simple ordered dither pattern). + */ + +METHODDEF(void) +h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr, outptr; + register int invalue; + register JDIMENSION colctr; + int inrow; + + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + inptr = input_data[inrow]; + outptr = output_data[inrow]; + /* Special case for first column */ + invalue = GETJSAMPLE(*inptr++); + *outptr++ = (JSAMPLE) invalue; + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ + invalue = GETJSAMPLE(*inptr++) * 3; + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); + *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); + } + + /* Special case for last column */ + invalue = GETJSAMPLE(*inptr); + *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); + *outptr++ = (JSAMPLE) invalue; + } +} + + +/* + * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + * Again a triangle filter; see comments for h2v1 case, above. + * + * It is OK for us to reference the adjacent input rows because we demanded + * context from the main buffer controller (see initialization code). + */ + +METHODDEF(void) +h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) +{ + JSAMPARRAY output_data = *output_data_ptr; + register JSAMPROW inptr0, inptr1, outptr; +#if BITS_IN_JSAMPLE == 8 + register int thiscolsum, lastcolsum, nextcolsum; +#else + register INT32 thiscolsum, lastcolsum, nextcolsum; +#endif + register JDIMENSION colctr; + int inrow, outrow, v; + + inrow = outrow = 0; + while (outrow < cinfo->max_v_samp_factor) { + for (v = 0; v < 2; v++) { + /* inptr0 points to nearest input row, inptr1 points to next nearest */ + inptr0 = input_data[inrow]; + if (v == 0) /* next nearest is row above */ + inptr1 = input_data[inrow-1]; + else /* next nearest is row below */ + inptr1 = input_data[inrow+1]; + outptr = output_data[outrow++]; + + /* Special case for first column */ + thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + + for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { + /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ + /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ + nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); + lastcolsum = thiscolsum; thiscolsum = nextcolsum; + } + + /* Special case for last column */ + *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); + *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); + } + inrow++; + } +} + + +/* + * Module initialization routine for upsampling. + */ + +GLOBAL(void) +jinit_upsampler (j_decompress_ptr cinfo) +{ + my_upsample_ptr upsample; + int ci; + jpeg_component_info * compptr; + boolean need_buffer, do_fancy; + int h_in_group, v_in_group, h_out_group, v_out_group; + + upsample = (my_upsample_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_upsampler)); + cinfo->upsample = (struct jpeg_upsampler *) upsample; + upsample->pub.start_pass = start_pass_upsample; + upsample->pub.upsample = sep_upsample; + upsample->pub.need_context_rows = FALSE; /* until we find out differently */ + + if (cinfo->CCIR601_sampling) /* this isn't supported */ + ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); + + /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, + * so don't ask for it. + */ + do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; + + /* Verify we can handle the sampling factors, select per-component methods, + * and create storage as needed. + */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Compute size of an "input group" after IDCT scaling. This many samples + * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. + */ + h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / + cinfo->min_DCT_scaled_size; + h_out_group = cinfo->max_h_samp_factor; + v_out_group = cinfo->max_v_samp_factor; + upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ + need_buffer = TRUE; + if (! compptr->component_needed) { + /* Don't bother to upsample an uninteresting component. */ + upsample->methods[ci] = noop_upsample; + need_buffer = FALSE; + } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + /* Fullsize components can be processed without any work. */ + upsample->methods[ci] = fullsize_upsample; + need_buffer = FALSE; + } else if (h_in_group * 2 == h_out_group && + v_in_group == v_out_group) { + /* Special cases for 2h1v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) + upsample->methods[ci] = h2v1_fancy_upsample; + else + upsample->methods[ci] = h2v1_upsample; + } else if (h_in_group * 2 == h_out_group && + v_in_group * 2 == v_out_group) { + /* Special cases for 2h2v upsampling */ + if (do_fancy && compptr->downsampled_width > 2) { + upsample->methods[ci] = h2v2_fancy_upsample; + upsample->pub.need_context_rows = TRUE; + } else + upsample->methods[ci] = h2v2_upsample; + } else if ((h_out_group % h_in_group) == 0 && + (v_out_group % v_in_group) == 0) { + /* Generic integral-factors upsampling method */ + upsample->methods[ci] = int_upsample; + upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); + upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); + } else + ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) { + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); + } + } +} diff --git a/Utilities/vtkjpeg/jdtrans.c b/Utilities/vtkjpeg/jdtrans.c new file mode 100644 index 0000000..6c0ab71 --- /dev/null +++ b/Utilities/vtkjpeg/jdtrans.c @@ -0,0 +1,143 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains library routines for transcoding decompression, + * that is, reading raw DCT coefficient arrays from an input JPEG file. + * The routines in jdapimin.c will also be needed by a transcoder. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Forward declarations */ +LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo)); + + +/* + * Read the coefficient arrays from a JPEG file. + * jpeg_read_header must be completed before calling this. + * + * The entire image is read into a set of virtual coefficient-block arrays, + * one per component. The return value is a pointer to the array of + * virtual-array descriptors. These can be manipulated directly via the + * JPEG memory manager, or handed off to jpeg_write_coefficients(). + * To release the memory occupied by the virtual arrays, call + * jpeg_finish_decompress() when done with the data. + * + * An alternative usage is to simply obtain access to the coefficient arrays + * during a buffered-image-mode decompression operation. This is allowed + * after any jpeg_finish_output() call. The arrays can be accessed until + * jpeg_finish_decompress() is called. (Note that any call to the library + * may reposition the arrays, so don't rely on access_virt_barray() results + * to stay valid across library calls.) + * + * Returns NULL if suspended. This case need be checked only if + * a suspending data source is used. + */ + +GLOBAL(jvirt_barray_ptr *) +jpeg_read_coefficients (j_decompress_ptr cinfo) +{ + if (cinfo->global_state == DSTATE_READY) { + /* First call: initialize active modules */ + transdecode_master_selection(cinfo); + cinfo->global_state = DSTATE_RDCOEFS; + } + if (cinfo->global_state == DSTATE_RDCOEFS) { + /* Absorb whole file into the coef buffer */ + for (;;) { + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return NULL; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } + } + /* Set state so that jpeg_finish_decompress does the right thing */ + cinfo->global_state = DSTATE_STOPPING; + } + /* At this point we should be in state DSTATE_STOPPING if being used + * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access + * to the coefficients during a full buffered-image-mode decompression. + */ + if ((cinfo->global_state == DSTATE_STOPPING || + cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) { + return cinfo->coef->coef_arrays; + } + /* Oops, improper usage */ + ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + return NULL; /* keep compiler happy */ +} + + +/* + * Master selection of decompression modules for transcoding. + * This substitutes for jdmaster.c's initialization of the full decompressor. + */ + +LOCAL(void) +transdecode_master_selection (j_decompress_ptr cinfo) +{ + /* This is effectively a buffered-image operation. */ + cinfo->buffered_image = TRUE; + + /* Entropy decoding: either Huffman or arithmetic coding. */ + if (cinfo->arith_code) { + ERREXIT(cinfo, JERR_ARITH_NOTIMPL); + } else { + if (cinfo->progressive_mode) { +#ifdef D_PROGRESSIVE_SUPPORTED + jinit_phuff_decoder(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else + jinit_huff_decoder(cinfo); + } + + /* Always get a full-image coefficient buffer. */ + jinit_d_coef_controller(cinfo, TRUE); + + /* We can now tell the memory manager to allocate virtual arrays. */ + (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); + + /* Initialize input side of decompressor to consume first scan. */ + (*cinfo->inputctl->start_input_pass) (cinfo); + + /* Initialize progress monitoring. */ + if (cinfo->progress != NULL) { + int nscans; + /* Estimate number of scans to set pass_limit. */ + if (cinfo->progressive_mode) { + /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ + nscans = 2 + 3 * cinfo->num_components; + } else if (cinfo->inputctl->has_multiple_scans) { + /* For a nonprogressive multiscan file, estimate 1 scan per component. */ + nscans = cinfo->num_components; + } else { + nscans = 1; + } + cinfo->progress->pass_counter = 0L; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; + cinfo->progress->completed_passes = 0; + cinfo->progress->total_passes = 1; + } +} diff --git a/Utilities/vtkjpeg/jerror.c b/Utilities/vtkjpeg/jerror.c new file mode 100644 index 0000000..1477bc4 --- /dev/null +++ b/Utilities/vtkjpeg/jerror.c @@ -0,0 +1,253 @@ +/* + * jerror.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains simple error-reporting and trace-message routines. + * These are suitable for Unix-like systems and others where writing to + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. + * + * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, + * you get a Windows-specific hack to display error messages in a dialog box. + * It ain't much, but it beats dropping error messages into the bit bucket, + * which is what happens to output to stderr under most Windows C compilers. + * + * These routines are used by both the compression and decompression code. + */ + +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jversion.h" +#include "jerror.h" + +#ifdef USE_WINDOWS_MESSAGEBOX +#undef INT32 +#include <windows.h> +#endif + +#ifndef EXIT_FAILURE /* define exit() codes if not provided */ +#define EXIT_FAILURE 1 +#endif + + +/* + * Create the message string table. + * We do this from the master message list in jerror.h by re-reading + * jerror.h with a suitable definition for macro JMESSAGE. + * The message table is made an external symbol just in case any applications + * want to refer to it directly. + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_message_table jMsgTable +#endif + +#define JMESSAGE(code,string) string , + +const char * const jpeg_std_message_table[] = { +#include "jerror.h" + NULL +}; + + +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF(void) +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + * + * On Windows, printing to stderr is generally completely useless, + * so we provide optional code to produce an error-dialog popup. + * Most Windows applications will still prefer to override this routine, + * but if they don't, it'll do something at least marginally useful. + * + * NOTE: to use the library in an environment that doesn't support the + * C stdio library, you may have to delete the call to fprintf() entirely, + * not just not use this routine. + */ + +METHODDEF(void) +output_message (j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + +#ifdef USE_WINDOWS_MESSAGEBOX + /* Display it in a message dialog box */ + MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", + MB_OK | MB_ICONERROR); +#else + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); +#endif +} + + +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + +METHODDEF(void) +emit_message (j_common_ptr cinfo, int msg_level) +{ + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } +} + + +/* + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. + */ + +METHODDEF(void) +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF(void) +reset_error_mgr (j_common_ptr cinfo) +{ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL(struct jpeg_error_mgr *) +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ + + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_std_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; + + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; + + return err; +} diff --git a/Utilities/vtkjpeg/jerror.h b/Utilities/vtkjpeg/jerror.h new file mode 100644 index 0000000..f60c1d4 --- /dev/null +++ b/Utilities/vtkjpeg/jerror.h @@ -0,0 +1,291 @@ +/* + * jerror.h + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the error and message codes for the JPEG library. + * Edit this file to add new codes, or to translate the message strings to + * some other language. + * A set of error-reporting macros are defined too. Some applications using + * the JPEG library may wish to include this file to get the error codes + * and/or the macros. + */ + +/* + * To define the enum list of message codes, include this file without + * defining macro JMESSAGE. To create a message string table, include it + * again with a suitable JMESSAGE definition (see jerror.c for an example). + */ +#ifndef JMESSAGE +#ifndef JERROR_H +/* First time through, define the enum list */ +#define JMAKE_ENUM_LIST +#else +/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ +#define JMESSAGE(code,string) +#endif /* JERROR_H */ +#endif /* JMESSAGE */ + +#ifdef JMAKE_ENUM_LIST + +typedef enum { + +#define JMESSAGE(code,string) code , + +#endif /* JMAKE_ENUM_LIST */ + +JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ + +/* For maintenance convenience, list is alphabetical by message code name */ +JMESSAGE(JERR_ARITH_NOTIMPL, + "Sorry, there are legal restrictions on arithmetic coding") +JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") +JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") +JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") +JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") +JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") +JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") +JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") +JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") +JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") +JMESSAGE(JERR_BAD_LIB_VERSION, + "Wrong JPEG library version: library is %d, caller expects %d") +JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") +JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") +JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") +JMESSAGE(JERR_BAD_PROGRESSION, + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") +JMESSAGE(JERR_BAD_PROG_SCRIPT, + "Invalid progressive parameters at scan script entry %d") +JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") +JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") +JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") +JMESSAGE(JERR_BAD_STRUCT_SIZE, + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") +JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") +JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") +JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") +JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") +JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") +JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") +JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") +JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") +JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") +JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") +JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") +JMESSAGE(JERR_EMS_READ, "Read from EMS failed") +JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") +JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") +JMESSAGE(JERR_FILE_READ, "Input file read error") +JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") +JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") +JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") +JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") +JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") +JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") +JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") +JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, + "Cannot transcode due to multiple use of quantization table %d") +JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") +JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") +JMESSAGE(JERR_NOTIMPL, "Not implemented yet") +JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") +JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") +JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") +JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") +JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") +JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") +JMESSAGE(JERR_QUANT_COMPONENTS, + "Cannot quantize more than %d color components") +JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") +JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") +JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") +JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") +JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") +JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") +JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") +JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") +JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") +JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") +JMESSAGE(JERR_TFILE_WRITE, + "Write failed on temporary file --- out of disk space?") +JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") +JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") +JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") +JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") +JMESSAGE(JERR_XMS_READ, "Read from XMS failed") +JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") +JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) +JMESSAGE(JMSG_VERSION, JVERSION) +JMESSAGE(JTRC_16BIT_TABLES, + "Caution: quantization tables are too coarse for baseline JPEG") +JMESSAGE(JTRC_ADOBE, + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") +JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") +JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") +JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") +JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") +JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") +JMESSAGE(JTRC_DRI, "Define Restart Interval %u") +JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") +JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") +JMESSAGE(JTRC_EOI, "End Of Image") +JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") +JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") +JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, + "Warning: thumbnail image size does not match data length %u") +JMESSAGE(JTRC_JFIF_EXTENSION, + "JFIF extension marker: type 0x%02x, length %u") +JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") +JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") +JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") +JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") +JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") +JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") +JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") +JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") +JMESSAGE(JTRC_RST, "RST%d") +JMESSAGE(JTRC_SMOOTH_NOTIMPL, + "Smoothing not supported with nonstandard sampling ratios") +JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") +JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") +JMESSAGE(JTRC_SOI, "Start of Image") +JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") +JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") +JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") +JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") +JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") +JMESSAGE(JTRC_THUMB_JPEG, + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_PALETTE, + "JFIF extension marker: palette thumbnail image, length %u") +JMESSAGE(JTRC_THUMB_RGB, + "JFIF extension marker: RGB thumbnail image, length %u") +JMESSAGE(JTRC_UNKNOWN_IDS, + "Unrecognized component IDs %d %d %d, assuming YCbCr") +JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") +JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") +JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_BOGUS_PROGRESSION, + "Inconsistent progression sequence for component %d coefficient %d") +JMESSAGE(JWRN_EXTRANEOUS_DATA, + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") +JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") +JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") +JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") +JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") +JMESSAGE(JWRN_MUST_RESYNC, + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") +JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") +JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") + +#ifdef JMAKE_ENUM_LIST + + JMSG_LASTMSGCODE +} J_MESSAGE_CODE; + +#undef JMAKE_ENUM_LIST +#endif /* JMAKE_ENUM_LIST */ + +/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ +#undef JMESSAGE + + +#ifndef JERROR_H +#define JERROR_H + +/* Macros to simplify using the error and trace message stuff */ +/* The first parameter is either type of cinfo pointer */ + +/* Fatal errors (print message and exit) */ +#define ERREXIT(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/Utilities/vtkjpeg/jfdctflt.c b/Utilities/vtkjpeg/jfdctflt.c new file mode 100644 index 0000000..79d7a00 --- /dev/null +++ b/Utilities/vtkjpeg/jfdctflt.c @@ -0,0 +1,168 @@ +/* + * jfdctflt.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * forward DCT (Discrete Cosine Transform). + * + * This implementation should be more accurate than either of the integer + * DCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_float (FAST_FLOAT * data) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; + FAST_FLOAT *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ + z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jfdctfst.c b/Utilities/vtkjpeg/jfdctfst.c new file mode 100644 index 0000000..ccb378a --- /dev/null +++ b/Utilities/vtkjpeg/jfdctfst.c @@ -0,0 +1,224 @@ +/* + * jfdctfst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jfdctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * Again to save a few shifts, the intermediate results between pass 1 and + * pass 2 are not upscaled, but are represented only to integral precision. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#define CONST_BITS 8 + + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */ +#else +#define FIX_0_382683433 FIX(0.382683433) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_707106781 FIX(0.707106781) +#define FIX_1_306562965 FIX(1.306562965) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_ifast (DCTELEM * data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jfdctint.c b/Utilities/vtkjpeg/jfdctint.c new file mode 100644 index 0000000..0a78b64 --- /dev/null +++ b/Utilities/vtkjpeg/jfdctint.c @@ -0,0 +1,283 @@ +/* + * jfdctint.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * forward DCT (Discrete Cosine Transform). + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D DCT step produces outputs which are a factor of sqrt(N) + * larger than the true DCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D DCT, + * because the y0 and y4 outputs need not be divided by sqrt(N). + * In the IJG code, this factor of 8 is removed by the quantization step + * (in jcdctmgr.c), NOT in this module. + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (For 12-bit sample data, the intermediate + * array is INT32 anyway.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + * Perform the forward DCT on one block of samples. + */ + +GLOBAL(void) +jpeg_fdct_islow (DCTELEM * data) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + DCTELEM *dataptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * cK represents cos(K*pi/16). + * i0..i3 in the paper are tmp4..tmp7 here. + */ + + z1 = tmp4 + tmp7; + z2 = tmp5 + tmp6; + z3 = tmp4 + tmp6; + z4 = tmp5 + tmp7; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jidctflt.c b/Utilities/vtkjpeg/jidctflt.c new file mode 100644 index 0000000..0188ce3 --- /dev/null +++ b/Utilities/vtkjpeg/jidctflt.c @@ -0,0 +1,242 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_FLOAT_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a float result. + */ + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + JCOEFPTR inptr; + FLOAT_MULT_TYPE * quantptr; + FAST_FLOAT * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jidctfst.c b/Utilities/vtkjpeg/jidctfst.c new file mode 100644 index 0000000..dba4216 --- /dev/null +++ b/Utilities/vtkjpeg/jidctfst.c @@ -0,0 +1,368 @@ +/* + * jidctfst.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a fast, not so accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with fixed-point math, + * accuracy is lost due to imprecise representation of the scaled + * quantization values. The smaller the quantization table entry, the less + * precise the scaled value, so this implementation does worse with high- + * quality-setting files than with low-quality ones. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_IFAST_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling decisions are generally the same as in the LL&M algorithm; + * see jidctint.c for more details. However, we choose to descale + * (right shift) multiplication products as soon as they are formed, + * rather than carrying additional fractional bits into subsequent additions. + * This compromises accuracy slightly, but it lets us save a few shifts. + * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + * everywhere except in the multiplications proper; this saves a good deal + * of work on 16-bit-int machines. + * + * The dequantized coefficients are not integers because the AA&N scaling + * factors have been incorporated. We represent them scaled up by PASS1_BITS, + * so that the first and second IDCT rounds have the same input scaling. + * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + * avoid a descaling shift; this compromises accuracy rather drastically + * for small quantization table entries, but it saves a lot of shifts. + * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + * so we use a much larger scaling factor to preserve accuracy. + * + * A final compromise is to represent the multiplicative constants to only + * 8 fractional bits, rather than 13. This saves some shifting work on some + * machines, and may also reduce the cost of multiplication (since there + * are fewer one-bits in the constants). + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 8 +#define PASS1_BITS 2 +#else +#define CONST_BITS 8 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 8 +#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */ +#else +#define FIX_1_082392200 FIX(1.082392200) +#define FIX_1_414213562 FIX(1.414213562) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_613125930 FIX(2.613125930) +#endif + + +/* We can gain a little more speed, with a further compromise in accuracy, + * by omitting the addition in a descaling shift. This yields an incorrectly + * rounded result half the time... + */ + +#ifndef USE_ACCURATE_ROUNDING +#undef DESCALE +#define DESCALE(x,n) RIGHT_SHIFT(x, n) +#endif + + +/* Multiply a DCTELEM variable by an INT32 constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS)) + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + * multiplication will do. For 12-bit data, the multiplier table is + * declared INT32, so a 32-bit multiply will be used. + */ + +#if BITS_IN_JSAMPLE == 8 +#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) +#else +#define DEQUANTIZE(coef,quantval) \ + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) +#endif + + +/* Like DESCALE, but applies to a DCTELEM and produces an int. + * We assume that int right shift is unsigned if INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + +#ifdef USE_ACCURATE_ROUNDING +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) +#else +#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) +#endif + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS /* for DESCALE */ + ISHIFT_TEMPS /* for IDESCALE */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (IFAST_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); + wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); + wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6); + wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); + wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); + wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); + wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); + tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + + tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) + - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3]; + z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3]; + z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7]; + z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_IFAST_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jidctint.c b/Utilities/vtkjpeg/jidctint.c new file mode 100644 index 0000000..a72b320 --- /dev/null +++ b/Utilities/vtkjpeg/jidctint.c @@ -0,0 +1,389 @@ +/* + * jidctint.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains a slow-but-accurate integer implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef DCT_ISLOW_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate INT32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ +#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ +#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ +#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ +#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ +#else +#define FIX_0_298631336 FIX(0.298631336) +#define FIX_0_390180644 FIX(0.390180644) +#define FIX_0_541196100 FIX(0.541196100) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_175875602 FIX(1.175875602) +#define FIX_1_501321110 FIX(1.501321110) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_1_961570560 FIX(1.961570560) +#define FIX_2_053119869 FIX(2.053119869) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_072711026 FIX(3.072711026) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +GLOBAL(void) +jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; + tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z1 = tmp0 + tmp3; + z2 = tmp1 + tmp2; + z3 = tmp0 + tmp2; + z4 = tmp1 + tmp3; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_ISLOW_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jidctred.c b/Utilities/vtkjpeg/jidctred.c new file mode 100644 index 0000000..421f3c7 --- /dev/null +++ b/Utilities/vtkjpeg/jidctred.c @@ -0,0 +1,398 @@ +/* + * jidctred.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains inverse-DCT routines that produce reduced-size output: + * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + * + * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + * with an 8-to-4 step that produces the four averages of two adjacent outputs + * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + * These steps were derived by computing the corresponding values at the end + * of the normal LL&M code, then simplifying as much as possible. + * + * 1x1 is trivial: just take the DC coefficient divided by 8. + * + * See jidctint.c for additional comments. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jdct.h" /* Private declarations for DCT subsystem */ + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* Scaling is the same as in jidctint.c. */ + +#if BITS_IN_JSAMPLE == 8 +#define CONST_BITS 13 +#define PASS1_BITS 2 +#else +#define CONST_BITS 13 +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus + * causing a lot of useless floating-point operations at run time. + * To get around this we use the following pre-calculated constants. + * If you change CONST_BITS you may want to add appropriate values. + * (With a reasonable C compiler, you can just rely on the FIX() macro...) + */ + +#if CONST_BITS == 13 +#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ +#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ +#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ +#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ +#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ +#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ +#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ +#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ +#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ +#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ +#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ +#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ +#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ +#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ +#else +#define FIX_0_211164243 FIX(0.211164243) +#define FIX_0_509795579 FIX(0.509795579) +#define FIX_0_601344887 FIX(0.601344887) +#define FIX_0_720959822 FIX(0.720959822) +#define FIX_0_765366865 FIX(0.765366865) +#define FIX_0_850430095 FIX(0.850430095) +#define FIX_0_899976223 FIX(0.899976223) +#define FIX_1_061594337 FIX(1.061594337) +#define FIX_1_272758580 FIX(1.272758580) +#define FIX_1_451774981 FIX(1.451774981) +#define FIX_1_847759065 FIX(1.847759065) +#define FIX_2_172734803 FIX(2.172734803) +#define FIX_2_562915447 FIX(2.562915447) +#define FIX_3_624509785 FIX(3.624509785) +#endif + + +/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + * For 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MULTIPLY(var,const) MULTIPLY16C16(var,const) +#else +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* Dequantize a coefficient by multiplying it by the multiplier-table + * entry; produce an int result. In this module, both inputs and result + * are 16 bits or less, so either int or short multiply will work. + */ + +#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process column 4, because second pass won't use it */ + if (ctr == DCTSIZE-4) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && + inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine term 4 for 4x4 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= (CONST_BITS+1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); + wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); + + tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + /* Odd part */ + + z1 = (INT32) wsptr[7]; + z2 = (INT32) wsptr[5]; + z3 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[1]; + + tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ + + tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10, z1; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[DCTSIZE*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { + /* Don't bother to process columns 2,4,6 */ + if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) + continue; + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { + /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + + continue; + } + + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 = z1 << (CONST_BITS+2); + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); + wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); + } + + /* Pass 2: process 2 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + /* It's not clear whether a zero row test is worthwhile here ... */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); + + /* Odd part */ + + tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jinclude.h b/Utilities/vtkjpeg/jinclude.h new file mode 100644 index 0000000..4e134ea --- /dev/null +++ b/Utilities/vtkjpeg/jinclude.h @@ -0,0 +1,92 @@ +#include "vtk_jpeg_mangle.h" +/* + * jinclude.h + * + * Copyright (C) 1991-1994, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include <stddef.h>. + * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to + * pull in <sys/types.h> as well. + * Note that the core JPEG library does not require <stdio.h>; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without <stdio.h>. + */ + +#ifdef HAVE_STDDEF_H +#include <stddef.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef NEED_SYS_TYPES_H +#include <sys/types.h> +#endif + +#include <stdio.h> + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in <string.h>. + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in <memory.h>. + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include <strings.h> +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include <string.h> +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/Utilities/vtkjpeg/jmemmgr.c b/Utilities/vtkjpeg/jmemmgr.c new file mode 100644 index 0000000..d801b32 --- /dev/null +++ b/Utilities/vtkjpeg/jmemmgr.c @@ -0,0 +1,1118 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the JPEG system-independent memory management + * routines. This code is usable across a wide variety of machines; most + * of the system dependencies have been isolated in a separate file. + * The major functions provided here are: + * * pool-based allocation and freeing of memory; + * * policy decisions about how to divide available memory among the + * virtual arrays; + * * control logic for swapping virtual arrays between main memory and + * backing storage. + * The separate system-dependent file provides the actual backing-storage + * access code, and it contains the policy decision about how much total + * main memory to use. + * This file is system-dependent in the sense that some of its functions + * are unnecessary in some systems. For example, if there is enough virtual + * memory so that backing storage will never be used, much of the virtual + * array control logic could be removed. (Of course, if you have that much + * memory then you shouldn't care about a little bit of unused code...) + */ + +#define JPEG_INTERNALS +#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef NO_GETENV +#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */ +extern char * getenv JPP((const char * name)); +#endif +#endif + + +/* + * Some important notes: + * The allocation routines provided here must never return NULL. + * They should exit to error_exit if unsuccessful. + * + * It's not a good idea to try to merge the sarray and barray routines, + * even though they are textually almost the same, because samples are + * usually stored as bytes while coefficients are shorts or ints. Thus, + * in machines where byte pointers have a different representation from + * word pointers, the resulting machine code could not be the same. + */ + + +/* + * Many machines require storage alignment: longs must start on 4-byte + * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + * always returns pointers that are multiples of the worst-case alignment + * requirement, and we had better do so too. + * There isn't any really portable way to determine the worst-case alignment + * requirement. This module assumes that the alignment requirement is + * multiples of sizeof(ALIGN_TYPE). + * By default, we define ALIGN_TYPE as double. This is necessary on some + * workstations (where doubles really do need 8-byte alignment) and will work + * fine on nearly everything. If your machine has lesser alignment needs, + * you can save a few bytes by making ALIGN_TYPE smaller. + * The only place I know of where this will NOT work is certain Macintosh + * 680x0 compilers that define double as a 10-byte IEEE extended float. + * Doing 10-byte alignment is counterproductive because longwords won't be + * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + * such a compiler. + */ + +#ifndef ALIGN_TYPE /* so can override from jconfig.h */ +#define ALIGN_TYPE double +#endif + + +/* + * We allocate objects from "pools", where each pool is gotten with a single + * request to jpeg_get_small() or jpeg_get_large(). There is no per-object + * overhead within a pool, except for alignment padding. Each pool has a + * header with a link to the next pool of the same class. + * Small and large pool headers are identical except that the latter's + * link pointer must be FAR on 80x86 machines. + * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + * of the alignment requirement of ALIGN_TYPE. + */ + +typedef union small_pool_struct * small_pool_ptr; + +typedef union small_pool_struct { + struct { + small_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} small_pool_hdr; + +typedef union large_pool_struct FAR * large_pool_ptr; + +typedef union large_pool_struct { + struct { + large_pool_ptr next; /* next in list of pools */ + size_t bytes_used; /* how many bytes already used within pool */ + size_t bytes_left; /* bytes still available in this pool */ + } hdr; + ALIGN_TYPE dummy; /* included in union to ensure alignment */ +} large_pool_hdr; + + +/* + * Here is the full definition of a memory manager object. + */ + +typedef struct { + struct jpeg_memory_mgr pub; /* public fields */ + + /* Each pool identifier (lifetime class) names a linked list of pools. */ + small_pool_ptr small_list[JPOOL_NUMPOOLS]; + large_pool_ptr large_list[JPOOL_NUMPOOLS]; + + /* Since we only have one lifetime class of virtual arrays, only one + * linked list is necessary (for each datatype). Note that the virtual + * array control blocks being linked together are actually stored somewhere + * in the small-pool list. + */ + jvirt_sarray_ptr virt_sarray_list; + jvirt_barray_ptr virt_barray_list; + + /* This counts total space obtained from jpeg_get_small/large */ + long total_space_allocated; + + /* alloc_sarray and alloc_barray set this value for use by virtual + * array routines. + */ + JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ +} my_memory_mgr; + +typedef my_memory_mgr * my_mem_ptr; + + +/* + * The control blocks for virtual arrays. + * Note that these blocks are allocated in the "small" pool area. + * System-dependent info for the associated backing store (if any) is hidden + * inside the backing_store_info struct. + */ + +struct jvirt_sarray_control { + JSAMPARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_sarray_ptr next; /* link to next virtual sarray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + +struct jvirt_barray_control { + JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ + JDIMENSION rows_in_array; /* total virtual array height */ + JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ + JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */ + JDIMENSION rows_in_mem; /* height of memory buffer */ + JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ + JDIMENSION cur_start_row; /* first logical row # in the buffer */ + JDIMENSION first_undef_row; /* row # of first uninitialized row */ + boolean pre_zero; /* pre-zero mode requested? */ + boolean dirty; /* do current buffer contents need written? */ + boolean b_s_open; /* is backing-store data valid? */ + jvirt_barray_ptr next; /* link to next virtual barray control block */ + backing_store_info b_s_info; /* System-dependent control info */ +}; + + +#ifdef MEM_STATS /* optional extra stuff for statistics */ + +LOCAL(void) +print_mem_stats (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + + /* Since this is only a debugging stub, we can cheat a little by using + * fprintf directly rather than going through the trace message code. + * This is helpful because message parm array can't handle longs. + */ + fprintf(stderr, "Freeing pool %d, total space = %ld\n", + pool_id, mem->total_space_allocated); + + for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; + lhdr_ptr = lhdr_ptr->hdr.next) { + fprintf(stderr, " Large chunk used %ld\n", + (long) lhdr_ptr->hdr.bytes_used); + } + + for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; + shdr_ptr = shdr_ptr->hdr.next) { + fprintf(stderr, " Small chunk used %ld free %ld\n", + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); + } +} + +#endif /* MEM_STATS */ + + +LOCAL(void) +out_of_memory (j_common_ptr cinfo, int which) +/* Report an out-of-memory error and stop execution */ +/* If we compiled MEM_STATS support, report alloc requests before dying */ +{ +#ifdef MEM_STATS + cinfo->err->trace_level = 2; /* force self_destruct to report stats */ +#endif + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +} + + +/* + * Allocation of "small" objects. + * + * For these, we use pooled storage. When a new pool must be created, + * we try to get enough space for the current request plus a "slop" factor, + * where the slop will be the amount of leftover space in the new pool. + * The speed vs. space tradeoff is largely determined by the slop values. + * A different slop value is provided for each pool class (lifetime), + * and we also distinguish the first pool of a class from later ones. + * NOTE: the values given work fairly well on both 16- and 32-bit-int + * machines, but may be too small if longs are 64 bits or more. + */ + +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +{ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ +}; + +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +{ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ +}; + +#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ + + +METHODDEF(void *) +alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "small" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr hdr_ptr, prev_hdr_ptr; + char * data_ptr; + size_t odd_bytes, min_request, slop; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) + out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* See if space is available in any existing pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + prev_hdr_ptr = NULL; + hdr_ptr = mem->small_list[pool_id]; + while (hdr_ptr != NULL) { + if (hdr_ptr->hdr.bytes_left >= sizeofobject) + break; /* found pool with enough space */ + prev_hdr_ptr = hdr_ptr; + hdr_ptr = hdr_ptr->hdr.next; + } + + /* Time to make a new pool? */ + if (hdr_ptr == NULL) { + /* min_request is what we need now, slop is what will be leftover */ + min_request = sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr == NULL) /* first pool in class? */ + slop = first_pool_slop[pool_id]; + else + slop = extra_pool_slop[pool_id]; + /* Don't ask for more than MAX_ALLOC_CHUNK */ + if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) + slop = (size_t) (MAX_ALLOC_CHUNK-min_request); + /* Try to get space, if fail reduce slop and try again */ + for (;;) { + hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); + if (hdr_ptr != NULL) + break; + slop /= 2; + if (slop < MIN_SLOP) /* give up when it gets real small */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + } + mem->total_space_allocated += min_request + slop; + /* Success, initialize the new pool header and add to end of list */ + hdr_ptr->hdr.next = NULL; + hdr_ptr->hdr.bytes_used = 0; + hdr_ptr->hdr.bytes_left = sizeofobject + slop; + if (prev_hdr_ptr == NULL) /* first pool in class? */ + mem->small_list[pool_id] = hdr_ptr; + else + prev_hdr_ptr->hdr.next = hdr_ptr; + } + + /* OK, allocate the object from the current pool */ + data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ + data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ + hdr_ptr->hdr.bytes_used += sizeofobject; + hdr_ptr->hdr.bytes_left -= sizeofobject; + + return (void *) data_ptr; +} + + +/* + * Allocation of "large" objects. + * + * The external semantics of these are the same as "small" objects, + * except that FAR pointers are used on 80x86. However the pool + * management heuristics are quite different. We assume that each + * request is large enough that it may as well be passed directly to + * jpeg_get_large; the pool management just links everything together + * so that we can free it all on demand. + * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + * structures. The routines that create these structures (see below) + * deliberately bunch rows together to ensure a large request size. + */ + +METHODDEF(void FAR *) +alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) +/* Allocate a "large" object */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + large_pool_ptr hdr_ptr; + size_t odd_bytes; + + /* Check for unsatisfiable request (do now to ensure no overflow below) */ + if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) + out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ + + /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ + odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) + sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes; + + /* Always make a new pool */ + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr)); + if (hdr_ptr == NULL) + out_of_memory(cinfo, 4); /* jpeg_get_large failed */ + mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); + + /* Success, initialize the new pool header and add to list */ + hdr_ptr->hdr.next = mem->large_list[pool_id]; + /* We maintain space counts in each pool header for statistical purposes, + * even though they are not needed for allocation. + */ + hdr_ptr->hdr.bytes_used = sizeofobject; + hdr_ptr->hdr.bytes_left = 0; + mem->large_list[pool_id] = hdr_ptr; + + return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ +} + + +/* + * Creation of 2-D sample arrays. + * The pointers are in near heap, the samples themselves in FAR heap. + * + * To minimize allocation overhead and to allow I/O of large contiguous + * blocks, we allocate the sample rows in groups of as many rows as possible + * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + * NB: the virtual array control routines, later in this file, know about + * this chunking of rows. The rowsperchunk value is left in the mem manager + * object so that it can be saved away if this sarray is the workspace for + * a virtual array. + */ + +METHODDEF(JSAMPARRAY) +alloc_sarray (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +/* Allocate a 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JSAMPARRAY result; + JSAMPROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) samplesperrow * SIZEOF(JSAMPLE)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JSAMPARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JSAMPROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JSAMPROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += samplesperrow; + } + } + + return result; +} + + +/* + * Creation of 2-D coefficient-block arrays. + * This is essentially the same as the code for sample arrays, above. + */ + +METHODDEF(JBLOCKARRAY) +alloc_barray (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, JDIMENSION numrows) +/* Allocate a 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + JBLOCKARRAY result; + JBLOCKROW workspace; + JDIMENSION rowsperchunk, currow, i; + long ltemp; + + /* Calculate max # of rows allowed in one allocation chunk */ + ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / + ((long) blocksperrow * SIZEOF(JBLOCK)); + if (ltemp <= 0) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < (long) numrows) + rowsperchunk = (JDIMENSION) ltemp; + else + rowsperchunk = numrows; + mem->last_rowsperchunk = rowsperchunk; + + /* Get space for row pointers (small object) */ + result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, + (size_t) (numrows * SIZEOF(JBLOCKROW))); + + /* Get the rows themselves (large objects) */ + currow = 0; + while (currow < numrows) { + rowsperchunk = MIN(rowsperchunk, numrows - currow); + workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); + for (i = rowsperchunk; i > 0; i--) { + result[currow++] = workspace; + workspace += blocksperrow; + } + } + + return result; +} + + +/* + * About virtual array management: + * + * The above "normal" array routines are only used to allocate strip buffers + * (as wide as the image, but just a few rows high). Full-image-sized buffers + * are handled as "virtual" arrays. The array is still accessed a strip at a + * time, but the memory manager must save the whole array for repeated + * accesses. The intended implementation is that there is a strip buffer in + * memory (as high as is possible given the desired memory limit), plus a + * backing file that holds the rest of the array. + * + * The request_virt_array routines are told the total size of the image and + * the maximum number of rows that will be accessed at once. The in-memory + * buffer must be at least as large as the maxaccess value. + * + * The request routines create control blocks but not the in-memory buffers. + * That is postponed until realize_virt_arrays is called. At that time the + * total amount of space needed is known (approximately, anyway), so free + * memory can be divided up fairly. + * + * The access_virt_array routines are responsible for making a specific strip + * area accessible (after reading or writing the backing file, if necessary). + * Note that the access routines are told whether the caller intends to modify + * the accessed strip; during a read-only pass this saves having to rewrite + * data to disk. The access routines are also responsible for pre-zeroing + * any newly accessed rows, if pre-zeroing was requested. + * + * In current usage, the access requests are usually for nonoverlapping + * strips; that is, successive access start_row numbers differ by exactly + * num_rows = maxaccess. This means we can get good performance with simple + * buffer dump/reload logic, by making the in-memory buffer be a multiple + * of the access height; then there will never be accesses across bufferload + * boundaries. The code will still work with overlapping access requests, + * but it doesn't handle bufferload overlaps very efficiently. + */ + + +METHODDEF(jvirt_sarray_ptr) +request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D sample array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_sarray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_sarray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->samplesperrow = samplesperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ + mem->virt_sarray_list = result; + + return result; +} + + +METHODDEF(jvirt_barray_ptr) +request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) +/* Request a virtual 2-D coefficient-block array */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + jvirt_barray_ptr result; + + /* Only IMAGE-lifetime virtual arrays are currently supported */ + if (pool_id != JPOOL_IMAGE) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + + /* get control block */ + result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, + SIZEOF(struct jvirt_barray_control)); + + result->mem_buffer = NULL; /* marks array not yet realized */ + result->rows_in_array = numrows; + result->blocksperrow = blocksperrow; + result->maxaccess = maxaccess; + result->pre_zero = pre_zero; + result->b_s_open = FALSE; /* no associated backing-store object */ + result->next = mem->virt_barray_list; /* add to list of virtual arrays */ + mem->virt_barray_list = result; + + return result; +} + + +METHODDEF(void) +realize_virt_arrays (j_common_ptr cinfo) +/* Allocate the in-memory buffers for any unrealized virtual arrays */ +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + long space_per_minheight, maximum_space, avail_mem; + long minheights, max_minheights; + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + /* Compute the minimum space needed (maxaccess rows in each buffer) + * and the maximum space needed (full image height in each buffer). + * These may be of use to the system-dependent jpeg_mem_available routine. + */ + space_per_minheight = 0; + maximum_space = 0; + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) sptr->maxaccess * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + maximum_space += (long) sptr->rows_in_array * + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + } + } + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + space_per_minheight += (long) bptr->maxaccess * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + maximum_space += (long) bptr->rows_in_array * + (long) bptr->blocksperrow * SIZEOF(JBLOCK); + } + } + + if (space_per_minheight <= 0) + return; /* no unrealized arrays, no work */ + + /* Determine amount of memory to actually use; this is system-dependent. */ + avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, + mem->total_space_allocated); + + /* If the maximum space needed is available, make all the buffers full + * height; otherwise parcel it out with the same number of minheights + * in each buffer. + */ + if (avail_mem >= maximum_space) + max_minheights = 1000000000L; + else { + max_minheights = avail_mem / space_per_minheight; + /* If there doesn't seem to be enough space, try to get the minimum + * anyway. This allows a "stub" implementation of jpeg_mem_available(). + */ + if (max_minheights <= 0) + max_minheights = 1; + } + + /* Allocate the in-memory buffers and initialize backing store as needed. */ + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; + } + sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, + sptr->samplesperrow, sptr->rows_in_mem); + sptr->rowsperchunk = mem->last_rowsperchunk; + sptr->cur_start_row = 0; + sptr->first_undef_row = 0; + sptr->dirty = FALSE; + } + } + + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->mem_buffer == NULL) { /* if not realized yet */ + minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; + if (minheights <= max_minheights) { + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; + } else { + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; + } + bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, + bptr->blocksperrow, bptr->rows_in_mem); + bptr->rowsperchunk = mem->last_rowsperchunk; + bptr->cur_start_row = 0; + bptr->first_undef_row = 0; + bptr->dirty = FALSE; + } + } +} + + +LOCAL(void) +do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual sample array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +LOCAL(void) +do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) +/* Do backing store read or write of a virtual coefficient-block array */ +{ + long bytesperrow, file_offset, byte_count, rows, thisrow, i; + + bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); + file_offset = ptr->cur_start_row * bytesperrow; + /* Loop to read or write each allocation chunk in mem_buffer */ + for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { + /* One chunk, but check for short chunk at end of buffer */ + rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); + /* Transfer no more than is currently defined */ + thisrow = (long) ptr->cur_start_row + i; + rows = MIN(rows, (long) ptr->first_undef_row - thisrow); + /* Transfer no more than fits in file */ + rows = MIN(rows, (long) ptr->rows_in_array - thisrow); + if (rows <= 0) /* this chunk might be past end of file! */ + break; + byte_count = rows * bytesperrow; + if (writing) + (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + else + (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); + file_offset += byte_count; + } +} + + +METHODDEF(JSAMPARRAY) +access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual sample array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_sarray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_sarray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +METHODDEF(JBLOCKARRAY) +access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) +/* Access the part of a virtual block array starting at start_row */ +/* and extending for num_rows rows. writable is true if */ +/* caller intends to modify the accessed area. */ +{ + JDIMENSION end_row = start_row + num_rows; + JDIMENSION undef_row; + + /* debugging check */ + if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || + ptr->mem_buffer == NULL) + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + /* Make the desired part of the virtual array accessible */ + if (start_row < ptr->cur_start_row || + end_row > ptr->cur_start_row+ptr->rows_in_mem) { + if (! ptr->b_s_open) + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + /* Flush old buffer contents if necessary */ + if (ptr->dirty) { + do_barray_io(cinfo, ptr, TRUE); + ptr->dirty = FALSE; + } + /* Decide what part of virtual array to access. + * Algorithm: if target address > current window, assume forward scan, + * load starting at target address. If target address < current window, + * assume backward scan, load so that target area is top of window. + * Note that when switching from forward write to forward read, will have + * start_row = 0, so the limiting case applies and we load from 0 anyway. + */ + if (start_row > ptr->cur_start_row) { + ptr->cur_start_row = start_row; + } else { + /* use long arithmetic here to avoid overflow & unsigned problems */ + long ltemp; + + ltemp = (long) end_row - (long) ptr->rows_in_mem; + if (ltemp < 0) + ltemp = 0; /* don't fall off front end of file */ + ptr->cur_start_row = (JDIMENSION) ltemp; + } + /* Read in the selected part of the array. + * During the initial write pass, we will do no actual read + * because the selected part is all undefined. + */ + do_barray_io(cinfo, ptr, FALSE); + } + /* Ensure the accessed part of the array is defined; prezero if needed. + * To improve locality of access, we only prezero the part of the array + * that the caller is about to access, not the entire in-memory array. + */ + if (ptr->first_undef_row < end_row) { + if (ptr->first_undef_row < start_row) { + if (writable) /* writer skipped over a section of array */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row = start_row; /* but reader is allowed to read ahead */ + } else { + undef_row = ptr->first_undef_row; + } + if (writable) + ptr->first_undef_row = end_row; + if (ptr->pre_zero) { + size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK); + undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ + end_row -= ptr->cur_start_row; + while (undef_row < end_row) { + jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; + } + } else { + if (! writable) /* reader looking at undefined data */ + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + } + } + /* Flag the buffer dirty if caller will write in it */ + if (writable) + ptr->dirty = TRUE; + /* Return address of proper part of the buffer */ + return ptr->mem_buffer + (start_row - ptr->cur_start_row); +} + + +/* + * Release all objects belonging to a specified pool. + */ + +METHODDEF(void) +free_pool (j_common_ptr cinfo, int pool_id) +{ + my_mem_ptr mem = (my_mem_ptr) cinfo->mem; + small_pool_ptr shdr_ptr; + large_pool_ptr lhdr_ptr; + size_t space_freed; + + if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ + +#ifdef MEM_STATS + if (cinfo->err->trace_level > 1) + print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ +#endif + + /* If freeing IMAGE pool, close any virtual arrays first */ + if (pool_id == JPOOL_IMAGE) { + jvirt_sarray_ptr sptr; + jvirt_barray_ptr bptr; + + for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { + if (sptr->b_s_open) { /* there may be no backing store */ + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + } + } + mem->virt_sarray_list = NULL; + for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { + if (bptr->b_s_open) { /* there may be no backing store */ + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + } + } + mem->virt_barray_list = NULL; + } + + /* Release large objects */ + lhdr_ptr = mem->large_list[pool_id]; + mem->large_list[pool_id] = NULL; + + while (lhdr_ptr != NULL) { + large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; + space_freed = lhdr_ptr->hdr.bytes_used + + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + lhdr_ptr = next_lhdr_ptr; + } + + /* Release small objects */ + shdr_ptr = mem->small_list[pool_id]; + mem->small_list[pool_id] = NULL; + + while (shdr_ptr != NULL) { + small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; + space_freed = shdr_ptr->hdr.bytes_used + + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); + mem->total_space_allocated -= space_freed; + shdr_ptr = next_shdr_ptr; + } +} + + +/* + * Close up shop entirely. + * Note that this cannot be called unless cinfo->mem is non-NULL. + */ + +METHODDEF(void) +self_destruct (j_common_ptr cinfo) +{ + int pool; + + /* Close all backing store, release all memory. + * Releasing pools in reverse order might help avoid fragmentation + * with some (brain-damaged) malloc libraries. + */ + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + free_pool(cinfo, pool); + } + + /* Release the memory manager control block too. */ + jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); + cinfo->mem = NULL; /* ensures I will be called only once */ + + jpeg_mem_term(cinfo); /* system-dependent cleanup */ +} + + +/* + * Memory manager initialization. + * When this is called, only the error manager pointer is valid in cinfo! + */ + +GLOBAL(void) +jinit_memory_mgr (j_common_ptr cinfo) +{ + my_mem_ptr mem; + long max_to_use; + int pool; + size_t test_mac; + + cinfo->mem = NULL; /* for safety if init fails */ + + /* Check for configuration errors. + * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + * doesn't reflect any real hardware alignment requirement. + * The test is a little tricky: for X>0, X and X-1 have no one-bits + * in common if and only if X is a power of 2, ie has only one one-bit. + * Some compilers may give an "unreachable code" warning here; ignore it. + */ + if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0) + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be + * a multiple of SIZEOF(ALIGN_TYPE). + * Again, an "unreachable code" warning may be ignored here. + * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. + */ + test_mac = (size_t) MAX_ALLOC_CHUNK; + if ((long) test_mac != MAX_ALLOC_CHUNK || + (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0) + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ + + /* Attempt to allocate memory manager's control block */ + mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); + + if (mem == NULL) { + jpeg_mem_term(cinfo); /* system-dependent cleanup */ + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + } + + /* OK, fill in the method pointers */ + mem->pub.alloc_small = alloc_small; + mem->pub.alloc_large = alloc_large; + mem->pub.alloc_sarray = alloc_sarray; + mem->pub.alloc_barray = alloc_barray; + mem->pub.request_virt_sarray = request_virt_sarray; + mem->pub.request_virt_barray = request_virt_barray; + mem->pub.realize_virt_arrays = realize_virt_arrays; + mem->pub.access_virt_sarray = access_virt_sarray; + mem->pub.access_virt_barray = access_virt_barray; + mem->pub.free_pool = free_pool; + mem->pub.self_destruct = self_destruct; + + /* Make MAX_ALLOC_CHUNK accessible to other modules */ + mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK; + + /* Initialize working state */ + mem->pub.max_memory_to_use = max_to_use; + + for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { + mem->small_list[pool] = NULL; + mem->large_list[pool] = NULL; + } + mem->virt_sarray_list = NULL; + mem->virt_barray_list = NULL; + + mem->total_space_allocated = SIZEOF(my_memory_mgr); + + /* Declare ourselves open for business */ + cinfo->mem = & mem->pub; + + /* Check for an environment variable JPEGMEM; if found, override the + * default max_memory setting from jpeg_mem_init. Note that the + * surrounding application may again override this value. + * If your system doesn't support getenv(), define NO_GETENV to disable + * this feature. + */ +#ifndef NO_GETENV + { char * memenv; + + if ((memenv = getenv("JPEGMEM")) != NULL) { + char ch = 'x'; + + if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; + } + } + } +#endif + +} diff --git a/Utilities/vtkjpeg/jmemnobs.c b/Utilities/vtkjpeg/jmemnobs.c new file mode 100644 index 0000000..1967894 --- /dev/null +++ b/Utilities/vtkjpeg/jmemnobs.c @@ -0,0 +1,122 @@ +/* + * jmemnobs.c + * + * Copyright (C) 1992-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides a really simple implementation of the system- + * dependent portion of the JPEG memory manager. This implementation + * assumes that no backing-store files are needed: all required space + * can be obtained from malloc(). + * This is very portable in the sense that it'll compile on almost anything, + * but you'd better have lots of main memory (or virtual memory) if you want + * to process big images. + * Note that the max_memory_to_use option is ignored by this implementation. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" +#include "jmemsys.h" /* import the system-dependent declarations */ + +#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* + * Memory allocation and freeing are controlled by the regular library + * routines malloc() and free(). + */ + +GLOBAL(void *) +jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) +{ + cinfo = 0; + return (void *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) +{ + cinfo = 0; + sizeofobject = 0; + free(object); +} + + +/* + * "Large" objects are treated the same as "small" ones. + * NB: although we include FAR keywords in the routine declarations, + * this file won't actually work in 80x86 small/medium model; at least, + * you probably won't be able to process useful-size images in only 64KB. + */ + +GLOBAL(void FAR *) +jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) +{ + cinfo = 0; + return (void FAR *) malloc(sizeofobject); +} + +GLOBAL(void) +jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) +{ + cinfo = 0; + sizeofobject = 0; + free(object); +} + + +/* + * This routine computes the total memory space available for allocation. + * Here we always say, "we got all you want bud!" + */ + +GLOBAL(long) +jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, + long max_bytes_needed, long already_allocated) +{ + cinfo = 0; + min_bytes_needed = 0; + already_allocated = 0; + return max_bytes_needed; +} + + +/* + * Backing store (temporary file) management. + * Since jpeg_mem_available always promised the moon, + * this should never be called and we can just error out. + */ + +GLOBAL(void) +jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, + long total_bytes_needed) +{ + info = 0; + total_bytes_needed = 0; + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +} + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. Here, there isn't any. + */ + +GLOBAL(long) +jpeg_mem_init (j_common_ptr cinfo) +{ + cinfo = 0; + return 0; /* just set max_memory_to_use to 0 */ +} + +GLOBAL(void) +jpeg_mem_term (j_common_ptr cinfo) +{ + cinfo = 0; + /* no work */ +} diff --git a/Utilities/vtkjpeg/jmemsys.h b/Utilities/vtkjpeg/jmemsys.h new file mode 100644 index 0000000..753569e --- /dev/null +++ b/Utilities/vtkjpeg/jmemsys.h @@ -0,0 +1,198 @@ +/* + * jmemsys.h + * + * Copyright (C) 1992-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This include file defines the interface between the system-independent + * and system-dependent portions of the JPEG memory manager. No other + * modules need include it. (The system-independent portion is jmemmgr.c; + * there are several different versions of the system-dependent portion.) + * + * This file works as-is for the system-dependent memory managers supplied + * in the IJG distribution. You may need to modify it if you write a + * custom memory manager. If system-dependent changes are needed in + * this file, the best method is to #ifdef them based on a configuration + * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR + * and USE_MAC_MEMMGR. + */ + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_get_small jGetSmall +#define jpeg_free_small jFreeSmall +#define jpeg_get_large jGetLarge +#define jpeg_free_large jFreeLarge +#define jpeg_mem_available jMemAvail +#define jpeg_open_backing_store jOpenBackStore +#define jpeg_mem_init jMemInit +#define jpeg_mem_term jMemTerm +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* + * These two functions are used to allocate and release small chunks of + * memory. (Typically the total amount requested through jpeg_get_small is + * no more than 20K or so; this will be requested in chunks of a few K each.) + * Behavior should be the same as for the standard library functions malloc + * and free; in particular, jpeg_get_small must return NULL on failure. + * On most systems, these ARE malloc and free. jpeg_free_small is passed the + * size of the object being freed, just in case it's needed. + * On an 80x86 machine using small-data memory model, these manage near heap. + */ + +EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); +EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, + size_t sizeofobject)); + +/* + * These two functions are used to allocate and release large chunks of + * memory (up to the total free space designated by jpeg_mem_available). + * The interface is the same as above, except that on an 80x86 machine, + * far pointers are used. On most other machines these are identical to + * the jpeg_get/free_small routines; but we keep them separate anyway, + * in case a different allocation strategy is desirable for large chunks. + */ + +EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, + size_t sizeofobject)); +EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, + size_t sizeofobject)); + +/* + * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + * be requested in a single call to jpeg_get_large (and jpeg_get_small for that + * matter, but that case should never come into play). This macro is needed + * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + * On those machines, we expect that jconfig.h will provide a proper value. + * On machines with 32-bit flat address spaces, any large constant may be used. + * + * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + * size_t and will be a multiple of sizeof(align_type). + */ + +#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ +#define MAX_ALLOC_CHUNK 1000000000L +#endif + +/* + * This routine computes the total space still available for allocation by + * jpeg_get_large. If more space than this is needed, backing store will be + * used. NOTE: any memory already allocated must not be counted. + * + * There is a minimum space requirement, corresponding to the minimum + * feasible buffer sizes; jmemmgr.c will request that much space even if + * jpeg_mem_available returns zero. The maximum space needed, enough to hold + * all working storage in memory, is also passed in case it is useful. + * Finally, the total space already allocated is passed. If no better + * method is available, cinfo->mem->max_memory_to_use - already_allocated + * is often a suitable calculation. + * + * It is OK for jpeg_mem_available to underestimate the space available + * (that'll just lead to more backing-store access than is really necessary). + * However, an overestimate will lead to failure. Hence it's wise to subtract + * a slop factor from the true available space. 5% should be enough. + * + * On machines with lots of virtual memory, any large constant may be returned. + * Conversely, zero may be returned to always use the minimum amount of memory. + */ + +EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); + + +/* + * This structure holds whatever state is needed to access a single + * backing-store object. The read/write/close method pointers are called + * by jmemmgr.c to manipulate the backing-store object; all other fields + * are private to the system-dependent backing store routines. + */ + +#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ + + +#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ + +typedef unsigned short XMSH; /* type of extended-memory handles */ +typedef unsigned short EMSH; /* type of expanded-memory handles */ + +typedef union { + short file_handle; /* DOS file handle if it's a temp file */ + XMSH xms_handle; /* handle if it's a chunk of XMS */ + EMSH ems_handle; /* handle if it's a chunk of EMS */ +} handle_union; + +#endif /* USE_MSDOS_MEMMGR */ + +#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ +#include <Files.h> +#endif /* USE_MAC_MEMMGR */ + + +typedef struct backing_store_struct * backing_store_ptr; + +typedef struct backing_store_struct { + /* Methods for reading/writing/closing this backing-store object */ + JMETHOD(void, read_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, write_backing_store, (j_common_ptr cinfo, + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); + JMETHOD(void, close_backing_store, (j_common_ptr cinfo, + backing_store_ptr info)); + + /* Private fields for system-dependent backing-store management */ +#ifdef USE_MSDOS_MEMMGR + /* For the MS-DOS manager (jmemdos.c), we need: */ + handle_union handle; /* reference to backing-store storage object */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else +#ifdef USE_MAC_MEMMGR + /* For the Mac manager (jmemmac.c), we need: */ + short temp_file; /* file reference number to temp file */ + FSSpec tempSpec; /* the FSSpec for the temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ +#else + /* For a typical implementation with temp files, we need: */ + FILE * temp_file; /* stdio reference to temp file */ + char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ +#endif +#endif +} backing_store_info; + + +/* + * Initial opening of a backing-store object. This must fill in the + * read/write/close pointers in the object. The read/write routines + * may take an error exit if the specified maximum file size is exceeded. + * (If jpeg_mem_available always returns a large value, this routine can + * just take an error exit.) + */ + +EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, + backing_store_ptr info, + long total_bytes_needed)); + + +/* + * These routines take care of any system-dependent initialization and + * cleanup required. jpeg_mem_init will be called before anything is + * allocated (and, therefore, nothing in cinfo is of use except the error + * manager pointer). It should return a suitable default value for + * max_memory_to_use; this may subsequently be overridden by the surrounding + * application. (Note that max_memory_to_use is only important if + * jpeg_mem_available chooses to consult it ... no one else will.) + * jpeg_mem_term may assume that all requested memory has been freed and that + * all opened backing-store objects have been closed. + */ + +EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/Utilities/vtkjpeg/jmorecfg.h b/Utilities/vtkjpeg/jmorecfg.h new file mode 100644 index 0000000..cf7838d --- /dev/null +++ b/Utilities/vtkjpeg/jmorecfg.h @@ -0,0 +1,399 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains additional configuration options that customize the + * JPEG software for special applications or support machine-dependent + * optimizations. Most users will not need to touch this file. + */ + +#include <vtkjpeg/jpegDllConfig.h> + +/* + * Define BITS_IN_JSAMPLE as either + * 8 for 8-bit sample values (the usual setting) + * 12 for 12-bit sample values + * Only 8 and 12 are legal data precisions for lossy JPEG according to the + * JPEG standard, and the IJG code does not support anything else! + * We do not support run-time selection of data precision, sorry. + */ + +#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ + + +/* + * Maximum number of components (color channels) allowed in JPEG image. + * To meet the letter of the JPEG spec, set this to 255. However, darn + * few applications need more than 4 channels (maybe 5 for CMYK + alpha + * mask). We recommend 10 as a reasonable compromise; use 4 if you are + * really short on memory. (Each allowed component costs a hundred or so + * bytes of storage, whether actually used in an image or not.) + */ + +#define MAX_COMPONENTS 10 /* maximum number of image components */ + + +/* + * Basic data types. + * You may need to change these if you have a machine with unusual data + * type sizes; for example, "char" not 8 bits, "short" not 16 bits, + * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + * but it had better be at least 16. + */ + +/* Representation of a single sample (pixel element value). + * We frequently allocate large arrays of these, so it's important to keep + * them small. But if you have memory to burn and access to char or short + * arrays is very slow on your hardware, you might want to change these. + */ + +#if BITS_IN_JSAMPLE == 8 +/* JSAMPLE should be the smallest type that will hold the values 0..255. + * You can use a signed char by having GETJSAMPLE mask it with 0xFF. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JSAMPLE; +#ifdef CHAR_IS_UNSIGNED +#define GETJSAMPLE(value) ((int) (value)) +#else +#define GETJSAMPLE(value) ((int) (value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +#endif /* BITS_IN_JSAMPLE == 8 */ + + +#if BITS_IN_JSAMPLE == 12 +/* JSAMPLE should be the smallest type that will hold the values 0..4095. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 4095 +#define CENTERJSAMPLE 2048 + +#endif /* BITS_IN_JSAMPLE == 12 */ + + +/* Representation of a DCT frequency coefficient. + * This should be a signed value of at least 16 bits; "short" is usually OK. + * Again, we allocate large arrays of these, but you can change to int + * if you have memory to burn and "short" is really slow. + */ + +typedef short JCOEF; + + +/* Compressed datastreams are represented as arrays of JOCTET. + * These must be EXACTLY 8 bits wide, at least once they are written to + * external storage. Note that when using the stdio data source/destination + * managers, this is also the data type passed to fread/fwrite. + */ + +#ifdef HAVE_UNSIGNED_CHAR + +typedef unsigned char JOCTET; +#define GETJOCTET(value) (value) + +#else /* not HAVE_UNSIGNED_CHAR */ + +typedef char JOCTET; +#ifdef CHAR_IS_UNSIGNED +#define GETJOCTET(value) (value) +#else +#define GETJOCTET(value) ((value) & 0xFF) +#endif /* CHAR_IS_UNSIGNED */ + +#endif /* HAVE_UNSIGNED_CHAR */ + + +/* These typedefs are used for various table entries and so forth. + * They must be at least as wide as specified; but making them too big + * won't cost a huge amount of memory, so we don't provide special + * extraction code like we did for JSAMPLE. (In other words, these + * typedefs live at a different point on the speed/space tradeoff curve.) + */ + +/* UINT8 must hold at least the values 0..255. */ + +#ifdef HAVE_UNSIGNED_CHAR +typedef unsigned char UINT8; +#else /* not HAVE_UNSIGNED_CHAR */ +#ifdef CHAR_IS_UNSIGNED +typedef char UINT8; +#else /* not CHAR_IS_UNSIGNED */ +typedef short UINT8; +#endif /* CHAR_IS_UNSIGNED */ +#endif /* HAVE_UNSIGNED_CHAR */ + +/* UINT16 must hold at least the values 0..65535. */ + +#ifdef HAVE_UNSIGNED_SHORT +typedef unsigned short UINT16; +#else /* not HAVE_UNSIGNED_SHORT */ +typedef unsigned int UINT16; +#endif /* HAVE_UNSIGNED_SHORT */ + +/* INT16 must hold at least the values -32768..32767. */ + +#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ +typedef short INT16; +#endif + +/* INT32 must hold at least signed 32-bit values. */ + +#if !defined(XMD_H) && !defined(_BASETSD_H_) +#define INT32 int +#endif + +/* Datatype used for image dimensions. The JPEG standard only supports + * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + * "unsigned int" is sufficient on all machines. However, if you need to + * handle larger images and you don't mind deviating from the spec, you + * can change this datatype. + */ + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + + +/* These macros are used in all function definitions and extern declarations. + * You could modify them if you need to change function linkage conventions; + * in particular, you'll need to do that to make the library a Windows DLL. + * Another application is to make all functions global for use with debuggers + * or code profilers that require it. + */ + +/* a function called through method pointers: */ +#define METHODDEF(type) static type +/* a function used only in its module: */ +#define LOCAL(type) static type + + +/* a function referenced thru EXTERNs: */ +#if defined( _WIN32 ) && defined (JPEGDLL) +#define GLOBAL(type) __declspec(dllexport) type +#else +#define GLOBAL(type) type +#endif + +/* a reference to a GLOBAL function: */ +#if defined(_WIN32) && !defined(JPEGSTATIC) +#ifdef JPEGDLL +/* Win32, building a dll */ +#define EXTERN(type) __declspec(dllexport) type +#else +/* Win32, not building a dll but using the dll */ +#define EXTERN(type) __declspec(dllimport) type +#endif +#else +/* not a Win32 system or building a static Win32 lib */ +#define EXTERN(type) extern type +#endif + +/* This macro is used to declare a "method", that is, a function pointer. + * We want to supply prototype parameters if the compiler can cope. + * Note that the arglist parameter must be parenthesized! + * Again, you can customize this if you need special linkage keywords. + */ + +#ifdef HAVE_PROTOTYPES +#define JMETHOD(type,methodname,arglist) type (*methodname) arglist +#else +#define JMETHOD(type,methodname,arglist) type (*methodname) () +#endif + + +/* Here is the pseudo-keyword for declaring pointers that must be "far" + * on 80x86 machines. Most of the specialized coding for 80x86 is handled + * by just saying "FAR *" where such a pointer is needed. In a few places + * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. + */ + +#ifndef FAR +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif +#endif + + +/* + * On a few systems, type boolean and/or its values FALSE, TRUE may appear + * in standard header files. Or you may have conflicts with application- + * specific header files that you want to include together with these files. + * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. + */ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#endif +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* + * The remaining options affect code selection within the JPEG library, + * but they don't need to be visible to most applications using the library. + * To minimize application namespace pollution, the symbols won't be + * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. + */ + +#ifdef JPEG_INTERNALS +#define JPEG_INTERNAL_OPTIONS +#endif + +#ifdef JPEG_INTERNAL_OPTIONS + + +/* + * These defines indicate whether to include various optional functions. + * Undefining some of these symbols will produce a smaller but less capable + * library. Note that you can leave certain source files out of the + * compilation/linking process if you've #undef'd the corresponding symbols. + * (You may HAVE to do that if your compiler doesn't like null source files.) + */ + +/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ + +/* Capability options common to encoder and decoder: */ + +#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ +#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ +#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ + +/* Encoder capability options: */ + +#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ +/* Note: if you selected 12-bit data precision, it is dangerous to turn off + * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + * precision, so jchuff.c normally uses entropy optimization to compute + * usable tables for higher precision. If you don't want to do optimization, + * you'll have to supply different default Huffman tables. + * The exact same statements apply for progressive JPEG: the default tables + * don't work for progressive mode. (This may get fixed, however.) + */ +#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ + +/* Decoder capability options: */ + +#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ +#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ +#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ +#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ +#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ +#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ + +/* more capability options later, no doubt */ + + +/* + * Ordering of RGB data in scanlines passed to or from the application. + * If your application wants to deal with data in the order B,G,R, just + * change these macros. You can also deal with formats such as R,G,B,X + * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + * the offsets will also change the order in which colormap data is organized. + * RESTRICTIONS: + * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + * useful if you are using JPEG color spaces other than YCbCr or grayscale. + * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + * is not 3 (they don't understand about dummy color components!). So you + * can't use color quantization if you change that value. + */ + +#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ +#define RGB_GREEN 1 /* Offset of Green */ +#define RGB_BLUE 2 /* Offset of Blue */ +#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ + + +/* Definitions for speed-related optimizations. */ + + +/* If your compiler supports inline functions, define INLINE + * as the inline keyword; otherwise define it as empty. + */ + +#ifndef INLINE +#ifdef __GNUC__ /* for instance, GNU C knows about inline */ +#define INLINE __inline__ +#endif +#ifndef INLINE +#define INLINE /* default is to define it as empty */ +#endif +#endif + + +/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying + * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + * as short on such a machine. MULTIPLIER must be at least 16 bits wide. + */ + +#ifndef MULTIPLIER +#define MULTIPLIER int /* type for fastest integer multiply */ +#endif + + +/* FAST_FLOAT should be either float or double, whichever is done faster + * by your compiler. (Note that this type is only used in the floating point + * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + * Typically, float is faster in ANSI C compilers, while double is faster in + * pre-ANSI compilers (because they insist on converting to double anyway). + * The code below therefore chooses float if we have ANSI-style prototypes. + */ + +#ifndef FAST_FLOAT +#ifdef HAVE_PROTOTYPES +#define FAST_FLOAT float +#else +#define FAST_FLOAT double +#endif +#endif + +#if defined ( _MSC_VER ) +#pragma warning ( disable : 4100 ) +#pragma warning ( disable : 4115 ) +#pragma warning ( disable : 4127 ) +#pragma warning ( disable : 4244 ) +#pragma warning ( disable : 4251 ) +#pragma warning ( disable : 4267 ) +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4309 ) +#pragma warning ( disable : 4706 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4057 ) +#pragma warning ( disable : 4189 ) +#pragma warning ( disable : 4505 ) +#endif + +#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/Utilities/vtkjpeg/jpegDllConfig.h.in b/Utilities/vtkjpeg/jpegDllConfig.h.in new file mode 100644 index 0000000..0baca64 --- /dev/null +++ b/Utilities/vtkjpeg/jpegDllConfig.h.in @@ -0,0 +1,6 @@ +#ifndef _jpegDllConfig_h +#define _jpegDllConfig_h + +#cmakedefine JPEGSTATIC + +#endif diff --git a/Utilities/vtkjpeg/jpegint.h b/Utilities/vtkjpeg/jpegint.h new file mode 100644 index 0000000..47aa1d2 --- /dev/null +++ b/Utilities/vtkjpeg/jpegint.h @@ -0,0 +1,392 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file provides common declarations for the various JPEG modules. + * These declarations are considered internal to the JPEG library; most + * applications using the library shouldn't need to include this file. + */ + + +/* Declarations for both compression & decompression */ + +typedef enum { /* Operating modes for buffer controllers */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ +} J_BUF_MODE; + +/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ +#define CSTATE_START 100 /* after create_compress */ +#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ +#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ +#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ +#define DSTATE_START 200 /* after create_decompress */ +#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ +#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ +#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ +#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ +#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ +#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ +#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ +#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ +#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ +#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ + + +/* Declarations for compression modules */ + +/* Master control module */ +struct jpeg_comp_master { + JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); + JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean call_pass_startup; /* True if pass_startup must be called */ + boolean is_last_pass; /* True during last pass */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_c_main_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); +}; + +/* Compression preprocessing (downsampling input buffer control) */ +struct jpeg_c_prep_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_c_coef_controller { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf)); +}; + +/* Colorspace conversion */ +struct jpeg_color_converter { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, color_convert, (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); +}; + +/* Downsampling */ +struct jpeg_downsampler { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + JMETHOD(void, downsample, (j_compress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Forward DCT (also controls coefficient quantization) */ +struct jpeg_forward_dct { + JMETHOD(void, start_pass, (j_compress_ptr cinfo)); + /* perhaps this should be an array??? */ + JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, + jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); +}; + +/* Entropy encoding */ +struct jpeg_entropy_encoder { + JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); + JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); +}; + +/* Marker writing */ +struct jpeg_marker_writer { + JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); + JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); + JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); + /* These routines are exported to allow insertion of extra markers */ + /* Probably only COM and APPn markers should be written this way */ + JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, + unsigned int datalen)); + JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); +}; + + +/* Declarations for decompression modules */ + +/* Master control module */ +struct jpeg_decomp_master { + JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ +}; + +/* Input control module */ +struct jpeg_input_controller { + JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); + JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); + + /* State variables made visible to other modules */ + boolean has_multiple_scans; /* True if file has multiple scans */ + boolean eoi_reached; /* True when EOI has been consumed */ +}; + +/* Main buffer control (downsampled-data buffer) */ +struct jpeg_d_main_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, process_data, (j_decompress_ptr cinfo, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Coefficient buffer control */ +struct jpeg_d_coef_controller { + JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); + JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); + JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, + JSAMPIMAGE output_buf)); + /* Pointer to array of coefficient virtual arrays, or NULL if none */ + jvirt_barray_ptr *coef_arrays; +}; + +/* Decompression postprocessing (color quantization buffer control) */ +struct jpeg_d_post_controller { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); + JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); +}; + +/* Marker reading & parsing */ +struct jpeg_marker_reader { + JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); + /* Read markers until SOS or EOI. + * Returns same codes as are defined for jpeg_consume_input: + * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + */ + JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); + /* Read a restart marker --- exported for use by entropy decoder only */ + jpeg_marker_parser_method read_restart_marker; + + /* State of marker reader --- nominally internal, but applications + * supplying COM or APPn handlers might like to know the state. + */ + boolean saw_SOI; /* found SOI? */ + boolean saw_SOF; /* found SOF? */ + int next_restart_num; /* next restart number expected (0-7) */ + unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ +}; + +/* Entropy decoding */ +struct jpeg_entropy_decoder { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, + JBLOCKROW *MCU_data)); + + /* This is here to share code between baseline and progressive decoders; */ + /* other modules probably should not use it */ + boolean insufficient_data; /* set TRUE after emitting warning */ +}; + +/* Inverse DCT (also performs dequantization) */ +typedef JMETHOD(void, inverse_DCT_method_ptr, + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); + +struct jpeg_inverse_dct { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + /* It is useful to allow each component to have a separate IDCT method. */ + inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; +}; + +/* Upsampling (note that upsampler must also call color converter) */ +struct jpeg_upsampler { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, upsample, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); + + boolean need_context_rows; /* TRUE if need rows above & below */ +}; + +/* Colorspace conversion */ +struct jpeg_color_deconverter { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, color_convert, (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); +}; + +/* Color quantization or color precision reduction */ +struct jpeg_color_quantizer { + JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); + JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); + JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); +}; + + +/* Miscellaneous useful macros */ + +#undef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#undef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS INT32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jinit_compress_master jICompress +#define jinit_c_master_control jICMaster +#define jinit_c_main_controller jICMainC +#define jinit_c_prep_controller jICPrepC +#define jinit_c_coef_controller jICCoefC +#define jinit_color_converter jICColor +#define jinit_downsampler jIDownsampler +#define jinit_forward_dct jIFDCT +#define jinit_huff_encoder jIHEncoder +#define jinit_phuff_encoder jIPHEncoder +#define jinit_marker_writer jIMWriter +#define jinit_master_decompress jIDMaster +#define jinit_d_main_controller jIDMainC +#define jinit_d_coef_controller jIDCoefC +#define jinit_d_post_controller jIDPostC +#define jinit_input_controller jIInCtlr +#define jinit_marker_reader jIMReader +#define jinit_huff_decoder jIHDecoder +#define jinit_phuff_decoder jIPHDecoder +#define jinit_inverse_dct jIIDCT +#define jinit_upsampler jIUpsampler +#define jinit_color_deconverter jIDColor +#define jinit_1pass_quantizer jI1Quant +#define jinit_2pass_quantizer jI2Quant +#define jinit_merged_upsampler jIMUpsampler +#define jinit_memory_mgr jIMemMgr +#define jdiv_round_up jDivRound +#define jround_up jRound +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jzero_far jZeroFar +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Compression module initialization routines */ +EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, + boolean transcode_only)); +EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); +/* Decompression module initialization routines */ +EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, + boolean need_full_buffer)); +EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); +/* Memory manager initialization */ +EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); + +/* Utility routines in jutils.c */ +EXTERN(long) jdiv_round_up JPP((long a, long b)); +EXTERN(long) jround_up JPP((long a, long b)); +EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); +EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks)); +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +/* Constant tables in jutils.c */ +#if 0 /* This table is not actually needed in v6a */ +extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ +#endif +extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ + +/* Suppress undefined-structure complaints if necessary. */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +#endif +#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/Utilities/vtkjpeg/jpeglib.h b/Utilities/vtkjpeg/jpeglib.h new file mode 100644 index 0000000..63652b4 --- /dev/null +++ b/Utilities/vtkjpeg/jpeglib.h @@ -0,0 +1,1097 @@ +#include "vtk_jpeg_mangle.h" +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file defines the application interface for the JPEG library. + * Most applications using the library need only include this file, + * and perhaps jerror.h if they want to know the exact error codes. + */ + +#ifndef JPEGLIB_H +#define JPEGLIB_H + +/* + * First we include the configuration files that record how this + * installation of the JPEG library is set up. jconfig.h can be + * generated automatically for many systems. jmorecfg.h contains + * manual configuration options that most people need not worry about. + */ + +#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ +#include "jconfig.h" /* widely used configuration options */ +#endif +#include "jmorecfg.h" /* seldom changed options */ + + +/* Version ID for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + */ + +#define JPEG_LIB_VERSION 62 /* Version 6b */ + + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + * On 80x86 machines, the image arrays are too big for near pointers, + * but the pointer arrays can fit in near memory. + */ + +typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ + + +/* Types for JPEG compression parameters and working tables. */ + + +/* DCT coefficient quantization tables. */ + +typedef struct { + /* This array gives the coefficient quantizers in natural array order + * (not the zigzag order in which they are stored in a JPEG DQT marker). + * CAUTION: IJG versions prior to v6a kept this array in zigzag order. + */ + UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JQUANT_TBL; + + +/* Huffman coding tables. */ + +typedef struct { + /* These two fields directly represent the contents of a JPEG DHT marker */ + UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ + /* length k bits; bits[0] is unused */ + UINT8 huffval[256]; /* The symbols, in order of incr code length */ + /* This field is used only during compression. It's initialized FALSE when + * the table is created, and set TRUE when it's been output to the file. + * You could suppress output of a table by setting this to TRUE. + * (See jpeg_suppress_tables for an example.) + */ + boolean sent_table; /* TRUE when table has been output */ +} JHUFF_TBL; + + +/* Basic info about one component (color channel). */ + +typedef struct { + /* These values are fixed over the whole image. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOF marker. */ + int component_id; /* identifier for this component (0..255) */ + int component_index; /* its index in SOF or cinfo->comp_info[] */ + int h_samp_factor; /* horizontal sampling factor (1..4) */ + int v_samp_factor; /* vertical sampling factor (1..4) */ + int quant_tbl_no; /* quantization table selector (0..3) */ + /* These values may vary between scans. */ + /* For compression, they must be supplied by parameter setup; */ + /* for decompression, they are read from the SOS marker. */ + /* The decompressor output side may not use these variables. */ + int dc_tbl_no; /* DC entropy table selector (0..3) */ + int ac_tbl_no; /* AC entropy table selector (0..3) */ + + /* Remaining fields should be treated as private by applications. */ + + /* These values are computed during compression or decompression startup: */ + /* Component's size in DCT blocks. + * Any dummy blocks added to complete an MCU are not counted; therefore + * these values do not depend on whether a scan is interleaved or not. + */ + JDIMENSION width_in_blocks; + JDIMENSION height_in_blocks; + /* Size of a DCT block in samples. Always DCTSIZE for compression. + * For decompression this is the size of the output from one DCT block, + * reflecting any scaling we choose to apply during the IDCT step. + * Values of 1,2,4,8 are likely to be supported. Note that different + * components may receive different IDCT scalings. + */ + int DCT_scaled_size; + /* The downsampled dimensions are the component's actual, unpadded number + * of samples at the main buffer (preprocessing/compression interface), thus + * downsampled_width = ceil(image_width * Hi/Hmax) + * and similarly for height. For decompression, IDCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + */ + JDIMENSION downsampled_width; /* actual width in samples */ + JDIMENSION downsampled_height; /* actual height in samples */ + /* This flag is used only for decompression. In cases where some of the + * components will be ignored (eg grayscale output from YCbCr image), + * we can skip most computations for the unused components. + */ + boolean component_needed; /* do we need the value of this component? */ + + /* These values are computed before starting a scan of the component. */ + /* The decompressor output side may not use these variables. */ + int MCU_width; /* number of blocks per MCU, horizontally */ + int MCU_height; /* number of blocks per MCU, vertically */ + int MCU_blocks; /* MCU_width * MCU_height */ + int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int last_col_width; /* # of non-dummy blocks across in last MCU */ + int last_row_height; /* # of non-dummy blocks down in last MCU */ + + /* Saved quantization table for component; NULL if none yet saved. + * See jdinput.c comments about the need for this information. + * This field is currently used only for decompression. + */ + JQUANT_TBL * quant_table; + + /* Private per-component storage for DCT or IDCT subsystem. */ + void * dct_table; +} jpeg_component_info; + + +/* The script for encoding a multiple-scan file is an array of these: */ + +typedef struct { + int comps_in_scan; /* number of components encoded in this scan */ + int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ + int Ss, Se; /* progressive JPEG spectral selection parms */ + int Ah, Al; /* progressive JPEG successive approx. parms */ +} jpeg_scan_info; + +/* The decompressor can save APPn and COM markers in a list of these: */ + +typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; + +struct jpeg_marker_struct { + jpeg_saved_marker_ptr next; /* next in list, or NULL */ + UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ + unsigned int original_length; /* # bytes of data in the file */ + unsigned int data_length; /* # bytes of data saved at data[] */ + JOCTET FAR * data; /* the data contained in the marker */ + /* the marker length word is not counted in data_length or original_length */ +}; + +/* Known color spaces. */ + +typedef enum { + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK /* Y/Cb/Cr/K */ +} J_COLOR_SPACE; + +/* DCT/IDCT algorithm options. */ + +typedef enum { + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ +} J_DCT_METHOD; + +#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ +#define JDCT_DEFAULT JDCT_ISLOW +#endif +#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ +#define JDCT_FASTEST JDCT_IFAST +#endif + +/* Dithering options for decompression. */ + +typedef enum { + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ +} J_DITHER_MODE; + + +/* Common fields between JPEG compression and decompression master structs. */ + +#define jpeg_common_fields \ + struct jpeg_error_mgr * err; /* Error handler module */\ + struct jpeg_memory_mgr * mem; /* Memory manager module */\ + struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ + void * client_data; /* Available for use by application */\ + boolean is_decompressor; /* So common code can tell which is which */\ + int global_state /* For checking call sequence validity */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. + */ +struct jpeg_common_struct { + jpeg_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual jpeg_compress_struct or + * jpeg_decompress_struct. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +}; + +typedef struct jpeg_common_struct * j_common_ptr; +typedef struct jpeg_compress_struct * j_compress_ptr; +typedef struct jpeg_decompress_struct * j_decompress_ptr; + + +/* Master record for a compression instance */ + +struct jpeg_compress_struct { + jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ + + /* Destination for compressed data */ + struct jpeg_destination_mgr * dest; + + /* Description of source image --- these fields must be filled in by + * outer application before starting compression. in_color_space must + * be correct before you can even call jpeg_set_defaults(). + */ + + JDIMENSION image_width; /* input image width */ + JDIMENSION image_height; /* input image height */ + int input_components; /* # of color components in input image */ + J_COLOR_SPACE in_color_space; /* colorspace of input image */ + + double input_gamma; /* image gamma of input image */ + + /* Compression parameters --- these fields must be set before calling + * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + * initialize everything to reasonable defaults, then changing anything + * the application specifically wants to change. That way you won't get + * burnt when new parameters are added. Also note that there are several + * helper routines to simplify changing parameters. + */ + + int data_precision; /* bits of precision in image data */ + + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + int num_scans; /* # of entries in scan_info array */ + const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ + /* The default value of scan_info is NULL, which causes a single-scan + * sequential JPEG file to be emitted. To create a multi-scan file, + * set num_scans and scan_info to point to an array of scan definitions. + */ + + boolean raw_data_in; /* TRUE=caller supplies downsampled data */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + int smoothing_factor; /* 1..100, or 0 for no input smoothing */ + J_DCT_METHOD dct_method; /* DCT algorithm selector */ + + /* The restart interval can be specified in absolute MCUs by setting + * restart_interval, or in MCU rows by setting restart_in_rows + * (in which case the correct restart_interval will be figured + * for each scan). + */ + unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ + int restart_in_rows; /* if > 0, MCU rows per restart interval */ + + /* Parameters controlling emission of special markers. */ + + boolean write_JFIF_header; /* should a JFIF marker be written? */ + UINT8 JFIF_major_version; /* What to write for the JFIF version number */ + UINT8 JFIF_minor_version; + /* These three values are not used by the JPEG code, merely copied */ + /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ + /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ + /* ratio is defined by X_density/Y_density even when density_unit=0. */ + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean write_Adobe_marker; /* should an Adobe marker be written? */ + + /* State variable: index of next scanline to be written to + * jpeg_write_scanlines(). Application may use this to control its + * processing loop, e.g., "while (next_scanline < image_height)". + */ + + JDIMENSION next_scanline; /* 0 .. image_height-1 */ + + /* Remaining fields are known throughout compressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during compression startup + */ + boolean progressive_mode; /* TRUE if scan script uses progressive mode */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ + /* The coefficient controller receives data in units of MCU rows as defined + * for fully interleaved scans (whether the JPEG file is interleaved or not). + * There are v_samp_factor * DCTSIZE sample rows of each component in an + * "iMCU" (interleaved MCU) row. + */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[C_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* + * Links to compression subobjects (methods and private variables of modules) + */ + struct jpeg_comp_master * master; + struct jpeg_c_main_controller * main; + struct jpeg_c_prep_controller * prep; + struct jpeg_c_coef_controller * coef; + struct jpeg_marker_writer * marker; + struct jpeg_color_converter * cconvert; + struct jpeg_downsampler * downsample; + struct jpeg_forward_dct * fdct; + struct jpeg_entropy_encoder * entropy; + jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ + int script_space_size; +}; + + +/* Master record for a decompression instance */ + +struct jpeg_decompress_struct { + jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ + + /* Source of compressed data */ + struct jpeg_source_mgr * src; + + /* Basic description of image --- filled in by jpeg_read_header(). */ + /* Application may inspect these values to decide how to process image. */ + + JDIMENSION image_width; /* nominal image width (from SOF marker) */ + JDIMENSION image_height; /* nominal image height */ + int num_components; /* # of color components in JPEG image */ + J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ + + /* Decompression processing parameters --- these fields must be set before + * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes + * them to default values. + */ + + J_COLOR_SPACE out_color_space; /* colorspace for output */ + + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + double output_gamma; /* image gamma wanted in output */ + + boolean buffered_image; /* TRUE=multiple output passes */ + boolean raw_data_out; /* TRUE=downsampled data wanted */ + + J_DCT_METHOD dct_method; /* IDCT algorithm selector */ + boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ + boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ + + boolean quantize_colors; /* TRUE=colormapped output wanted */ + /* the following are ignored if not quantize_colors: */ + J_DITHER_MODE dither_mode; /* type of color dithering to use */ + boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ + int desired_number_of_colors; /* max # colors to use in created colormap */ + /* these are significant only in buffered-image mode: */ + boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ + boolean enable_external_quant;/* enable future use of external colormap */ + boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ + + /* Description of actual output image that will be returned to application. + * These fields are computed by jpeg_start_decompress(). + * You can also use jpeg_calc_output_dimensions() to determine these values + * in advance of calling jpeg_start_decompress(). + */ + + JDIMENSION output_width; /* scaled image width */ + JDIMENSION output_height; /* scaled image height */ + int out_color_components; /* # of color components in out_color_space */ + int output_components; /* # of color components returned */ + /* output_components is 1 (a colormap index) when quantizing colors; + * otherwise it equals out_color_components. + */ + int rec_outbuf_height; /* min recommended height of scanline buffer */ + /* If the buffer passed to jpeg_read_scanlines() is less than this many rows + * high, space and time will be wasted due to unnecessary data copying. + * Usually rec_outbuf_height will be 1 or 2, at most 4. + */ + + /* When quantizing colors, the output colormap is described by these fields. + * The application can supply a colormap by setting colormap non-NULL before + * calling jpeg_start_decompress; otherwise a colormap is created during + * jpeg_start_decompress or jpeg_start_output. + * The map has out_color_components rows and actual_number_of_colors columns. + */ + int actual_number_of_colors; /* number of entries in use */ + JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ + + /* State variables: these variables indicate the progress of decompression. + * The application may examine these but must not modify them. + */ + + /* Row index of next scanline to be read from jpeg_read_scanlines(). + * Application may use this to control its processing loop, e.g., + * "while (output_scanline < output_height)". + */ + JDIMENSION output_scanline; /* 0 .. output_height-1 */ + + /* Current input scan number and number of iMCU rows completed in scan. + * These indicate the progress of the decompressor input side. + */ + int input_scan_number; /* Number of SOS markers seen so far */ + JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ + + /* The "output scan number" is the notional scan being displayed by the + * output side. The decompressor will not allow output scan/row number + * to get ahead of input scan/row, but it can fall arbitrarily far behind. + */ + int output_scan_number; /* Nominal scan number being displayed */ + JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ + + /* Current progression status. coef_bits[c][i] indicates the precision + * with which component c's DCT coefficient i (in zigzag order) is known. + * It is -1 when no data has yet been received, otherwise it is the point + * transform (shift) value for the most recent scan of the coefficient + * (thus, 0 at completion of the progression). + * This pointer is NULL when reading a non-progressive file. + */ + int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ + + /* Internal JPEG parameters --- the application usually need not look at + * these fields. Note that the decompressor output side may not use + * any parameters that can change between scans. + */ + + /* Quantization and Huffman tables are carried forward across input + * datastreams when processing abbreviated JPEG datastreams. + */ + + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined */ + + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; + JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; + /* ptrs to Huffman coding tables, or NULL if not defined */ + + /* These parameters are never carried across datastreams, since they + * are given in SOF/SOS markers or defined to be reset by SOI. + */ + + int data_precision; /* bits of precision in image data */ + + jpeg_component_info * comp_info; + /* comp_info[i] describes component that appears i'th in SOF */ + + boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ + boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ + + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ + UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ + UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ + + unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ + + /* These fields record data obtained from optional markers recognized by + * the JPEG library. + */ + boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ + /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ + UINT8 JFIF_major_version; /* JFIF version number */ + UINT8 JFIF_minor_version; + UINT8 density_unit; /* JFIF code for pixel size units */ + UINT16 X_density; /* Horizontal pixel density */ + UINT16 Y_density; /* Vertical pixel density */ + boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ + UINT8 Adobe_transform; /* Color transform code from Adobe marker */ + + boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + + /* Aside from the specific data retained from APPn markers known to the + * library, the uninterpreted contents of any or all APPn and COM markers + * can be saved in a list for examination by the application. + */ + jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ + + /* Remaining fields are known throughout decompressor, but generally + * should not be touched by a surrounding application. + */ + + /* + * These fields are computed during decompression startup + */ + int max_h_samp_factor; /* largest h_samp_factor */ + int max_v_samp_factor; /* largest v_samp_factor */ + + int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + + JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ + /* The coefficient controller's input and output progress is measured in + * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + * in fully interleaved JPEG scans, but are used whether the scan is + * interleaved or not. We define an iMCU row as v_samp_factor DCT block + * rows of each component. Therefore, the IDCT output contains + * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + */ + + JSAMPLE * sample_range_limit; /* table for fast range-limiting */ + + /* + * These fields are valid during any one scan. + * They describe the components and MCUs actually appearing in the scan. + * Note that the decompressor output side must not use these fields. + */ + int comps_in_scan; /* # of JPEG components in this scan */ + jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; + /* *cur_comp_info[i] describes component that appears i'th in SOS */ + + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ + JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ + + int blocks_in_MCU; /* # of DCT blocks per MCU */ + int MCU_membership[D_MAX_BLOCKS_IN_MCU]; + /* MCU_membership[i] is index in cur_comp_info of component owning */ + /* i'th block in an MCU */ + + int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + + /* This field is shared between entropy decoder and marker parser. + * It is either zero or the code of a JPEG marker that has been + * read from the data source, but has not yet been processed. + */ + int unread_marker; + + /* + * Links to decompression subobjects (methods, private variables of modules) + */ + struct jpeg_decomp_master * master; + struct jpeg_d_main_controller * main; + struct jpeg_d_coef_controller * coef; + struct jpeg_d_post_controller * post; + struct jpeg_input_controller * inputctl; + struct jpeg_marker_reader * marker; + struct jpeg_entropy_decoder * entropy; + struct jpeg_inverse_dct * idct; + struct jpeg_upsampler * upsample; + struct jpeg_color_deconverter * cconvert; + struct jpeg_color_quantizer * cquantize; +}; + + +/* "Object" declarations for JPEG modules that may be supplied or called + * directly by the surrounding application. + * As with all objects in the JPEG library, these structs only define the + * publicly visible methods and state variables of a module. Additional + * private fields may exist after the public ones. + */ + + +/* Error handler object */ + +struct jpeg_error_mgr { + /* Error exit handler: does not return to caller */ + JMETHOD(void, error_exit, (j_common_ptr cinfo)); + /* Conditionally emit a trace or warning message */ + JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); + /* Routine that actually outputs a trace or error message */ + JMETHOD(void, output_message, (j_common_ptr cinfo)); + /* Format a message string for the most recent JPEG error or message */ + JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); +#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ + /* Reset error state variables at start of a new image */ + JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); + + /* The message ID code and any parameters are saved here. + * A message can have one string parameter or up to 8 int parameters. + */ + int msg_code; +#define JMSG_STR_PARM_MAX 80 + union { + int i[8]; + char s[JMSG_STR_PARM_MAX]; + } msg_parm; + + /* Standard state variables for error facility */ + + int trace_level; /* max msg_level that will be displayed */ + + /* For recoverable corrupt-data errors, we emit a warning message, + * but keep going unless emit_message chooses to abort. emit_message + * should count warnings in num_warnings. The surrounding application + * can check for bad data by seeing if num_warnings is nonzero at the + * end of processing. + */ + long num_warnings; /* number of corrupt-data warnings */ + + /* These fields point to the table(s) of error message strings. + * An application can change the table pointer to switch to a different + * message list (typically, to change the language in which errors are + * reported). Some applications may wish to add additional error codes + * that will be handled by the JPEG library error mechanism; the second + * table pointer is used for this purpose. + * + * First table includes all errors generated by JPEG library itself. + * Error code 0 is reserved for a "no such error string" message. + */ + const char * const * jpeg_message_table; /* Library errors */ + int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ + /* Second table can be added by application (see cjpeg/djpeg for example). + * It contains strings numbered first_addon_message..last_addon_message. + */ + const char * const * addon_message_table; /* Non-library errors */ + int first_addon_message; /* code for first string in addon table */ + int last_addon_message; /* code for last string in addon table */ +}; + + +/* Progress monitor object */ + +struct jpeg_progress_mgr { + JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); + + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +}; + + +/* Data destination object for compression */ + +struct jpeg_destination_mgr { + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + + JMETHOD(void, init_destination, (j_compress_ptr cinfo)); + JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); + JMETHOD(void, term_destination, (j_compress_ptr cinfo)); +}; + + +/* Data source object for decompression */ + +struct jpeg_source_mgr { + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + + JMETHOD(void, init_source, (j_decompress_ptr cinfo)); + JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); + JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); + JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); + JMETHOD(void, term_source, (j_decompress_ptr cinfo)); +}; + + +/* Memory manager object. + * Allocates "small" objects (a few K total), "large" objects (tens of K), + * and "really big" objects (virtual arrays with backing store if needed). + * The memory manager does not allow individual objects to be freed; rather, + * each created object is assigned to a pool, and whole pools can be freed + * at once. This is faster and more convenient than remembering exactly what + * to free, especially where malloc()/free() are not too speedy. + * NB: alloc routines never return NULL. They exit to error_exit if not + * successful. + */ + +#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ +#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ +#define JPOOL_NUMPOOLS 2 + +typedef struct jvirt_sarray_control * jvirt_sarray_ptr; +typedef struct jvirt_barray_control * jvirt_barray_ptr; + + +struct jpeg_memory_mgr { + /* Method pointers */ + JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, + size_t sizeofobject)); + JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, + JDIMENSION samplesperrow, + JDIMENSION numrows)); + JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, + JDIMENSION blocksperrow, + JDIMENSION numrows)); + JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); + JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); + JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); + JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); + JMETHOD(void, self_destruct, (j_common_ptr cinfo)); + + /* Limit on memory allocation for this JPEG object. (Note that this is + * merely advisory, not a guaranteed maximum; it only affects the space + * used for virtual-array buffers.) May be changed by outer application + * after creating the JPEG object. + */ + long max_memory_to_use; + + /* Maximum allocation request accepted by alloc_large. */ + long max_alloc_chunk; +}; + + +/* Routine signature for application-supplied marker processing methods. + * Need not pass marker code since it is stored in cinfo->unread_marker. + */ +typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); + + +/* Declarations for routines called by application. + * The JPP macro hides prototype parameters from compilers that can't cope. + * Note JPP requires double parentheses. + */ + +#ifdef HAVE_PROTOTYPES +#define JPP(arglist) arglist +#else +#define JPP(arglist) () +#endif + + +/* Short forms of external names for systems with brain-damaged linkers. + * We shorten external names to be unique in the first six letters, which + * is good enough for all known systems. + * (If your compiler itself needs names to be unique in less than 15 + * characters, you are out of luck. Get a better compiler.) + */ + +#ifdef NEED_SHORT_EXTERNAL_NAMES +#define jpeg_std_error jStdError +#define jpeg_CreateCompress jCreaCompress +#define jpeg_CreateDecompress jCreaDecompress +#define jpeg_destroy_compress jDestCompress +#define jpeg_destroy_decompress jDestDecompress +#define jpeg_stdio_dest jStdDest +#define jpeg_stdio_src jStdSrc +#define jpeg_set_defaults jSetDefaults +#define jpeg_set_colorspace jSetColorspace +#define jpeg_default_colorspace jDefColorspace +#define jpeg_set_quality jSetQuality +#define jpeg_set_linear_quality jSetLQuality +#define jpeg_add_quant_table jAddQuantTable +#define jpeg_quality_scaling jQualityScaling +#define jpeg_simple_progression jSimProgress +#define jpeg_suppress_tables jSuppressTables +#define jpeg_alloc_quant_table jAlcQTable +#define jpeg_alloc_huff_table jAlcHTable +#define jpeg_start_compress jStrtCompress +#define jpeg_write_scanlines jWrtScanlines +#define jpeg_finish_compress jFinCompress +#define jpeg_write_raw_data jWrtRawData +#define jpeg_write_marker jWrtMarker +#define jpeg_write_m_header jWrtMHeader +#define jpeg_write_m_byte jWrtMByte +#define jpeg_write_tables jWrtTables +#define jpeg_read_header jReadHeader +#define jpeg_start_decompress jStrtDecompress +#define jpeg_read_scanlines jReadScanlines +#define jpeg_finish_decompress jFinDecompress +#define jpeg_read_raw_data jReadRawData +#define jpeg_has_multiple_scans jHasMultScn +#define jpeg_start_output jStrtOutput +#define jpeg_finish_output jFinOutput +#define jpeg_input_complete jInComplete +#define jpeg_new_colormap jNewCMap +#define jpeg_consume_input jConsumeInput +#define jpeg_calc_output_dimensions jCalcDimensions +#define jpeg_save_markers jSaveMarkers +#define jpeg_set_marker_processor jSetMarker +#define jpeg_read_coefficients jReadCoefs +#define jpeg_write_coefficients jWrtCoefs +#define jpeg_copy_critical_parameters jCopyCrit +#define jpeg_abort_compress jAbrtCompress +#define jpeg_abort_decompress jAbrtDecompress +#define jpeg_abort jAbort +#define jpeg_destroy jDestroy +#define jpeg_resync_to_restart jResyncRestart +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* Default error-management setup */ +EXTERN(struct jpeg_error_mgr *) jpeg_std_error + JPP((struct jpeg_error_mgr * err)); + +/* Initialization of JPEG compression objects. + * jpeg_create_compress() and jpeg_create_decompress() are the exported + * names that applications should call. These expand to calls on + * jpeg_CreateCompress and jpeg_CreateDecompress with additional information + * passed for version mismatch checking. + * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. + */ +#define jpeg_create_compress(cinfo) \ + jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_compress_struct)) +#define jpeg_create_decompress(cinfo) \ + jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ + (size_t) sizeof(struct jpeg_decompress_struct)) +EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, + int version, size_t structsize)); +EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, + int version, size_t structsize)); +/* Destruction of JPEG compression objects */ +EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); + +/* Standard data source and destination managers: stdio streams. */ +/* Caller is responsible for opening the file before and closing after. */ +EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); +EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); + +/* Default parameter setup for compression */ +EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); +/* Compression parameter setup aids */ +EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, + J_COLOR_SPACE colorspace)); +EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, + boolean force_baseline)); +EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, + int scale_factor, + boolean force_baseline)); +EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); +EXTERN(int) jpeg_quality_scaling JPP((int quality)); +EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, + boolean suppress)); +EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); +EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); + +/* Main entry points for compression */ +EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, + boolean write_all_tables)); +EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION num_lines)); +EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); + +/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION num_lines)); + +/* Write a special marker. See libjpeg.doc concerning safe usage. */ +EXTERN(void) jpeg_write_marker + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); +/* Same, but piecemeal. */ +EXTERN(void) jpeg_write_m_header + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); +EXTERN(void) jpeg_write_m_byte + JPP((j_compress_ptr cinfo, int val)); + +/* Alternate compression function: just write an abbreviated table file */ +EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); + +/* Decompression startup: read start of JPEG datastream to see what's there */ +EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, + boolean require_image)); +/* Return value is one of: */ +#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ +#define JPEG_HEADER_OK 1 /* Found valid image datastream */ +#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ +/* If you pass require_image = TRUE (normal case), you need not check for + * a TABLES_ONLY return code; an abbreviated file will cause an error exit. + * JPEG_SUSPENDED is only possible if you use a data source module that can + * give a suspension return (the stdio source module doesn't). + */ + +/* Main entry points for decompression */ +EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); +EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, + JSAMPARRAY scanlines, + JDIMENSION max_lines)); +EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); + +/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ +EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, + JSAMPIMAGE data, + JDIMENSION max_lines)); + +/* Additional entry points for buffered-image mode. */ +EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, + int scan_number)); +EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); +EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); +EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); +/* Return value is one of: */ +/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ +#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ +#define JPEG_REACHED_EOI 2 /* Reached end of image */ +#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ +#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ + +/* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); + +/* Control saving of COM and APPn markers into marker_list. */ +EXTERN(void) jpeg_save_markers + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); + +/* Install a special processing method for COM or APPn markers. */ +EXTERN(void) jpeg_set_marker_processor + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); + +/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ +EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); +EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, + jvirt_barray_ptr * coef_arrays)); +EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, + j_compress_ptr dstinfo)); + +/* If you choose to abort compression or decompression before completing + * jpeg_finish_(de)compress, then you need to clean up to release memory, + * temporary files, etc. You can just call jpeg_destroy_(de)compress + * if you're done with the JPEG object, but if you want to clean it up and + * reuse it, call this: + */ +EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); +EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); + +/* Generic versions of jpeg_abort and jpeg_destroy that work on either + * flavor of JPEG object. These may be more convenient in some places. + */ +EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); +EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); + +/* Default restart-marker-resync procedure for use by data source modules */ +EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, + int desired)); + + +/* These marker codes are exported since applications and data source modules + * are likely to want to use them. + */ + +#define JPEG_RST0 0xD0 /* RST0 marker code */ +#define JPEG_EOI 0xD9 /* EOI marker code */ +#define JPEG_APP0 0xE0 /* APP0 marker code */ +#define JPEG_COM 0xFE /* COM marker code */ + + +/* If we have a brain-damaged compiler that emits warnings (or worse, errors) + * for structure definitions that are never filled in, keep it quiet by + * supplying dummy definitions for the various substructures. + */ + +#ifdef INCOMPLETE_TYPES_BROKEN +#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ +struct jvirt_sarray_control { long dummy; }; +struct jvirt_barray_control { long dummy; }; +struct jpeg_comp_master { long dummy; }; +struct jpeg_c_main_controller { long dummy; }; +struct jpeg_c_prep_controller { long dummy; }; +struct jpeg_c_coef_controller { long dummy; }; +struct jpeg_marker_writer { long dummy; }; +struct jpeg_color_converter { long dummy; }; +struct jpeg_downsampler { long dummy; }; +struct jpeg_forward_dct { long dummy; }; +struct jpeg_entropy_encoder { long dummy; }; +struct jpeg_decomp_master { long dummy; }; +struct jpeg_d_main_controller { long dummy; }; +struct jpeg_d_coef_controller { long dummy; }; +struct jpeg_d_post_controller { long dummy; }; +struct jpeg_input_controller { long dummy; }; +struct jpeg_marker_reader { long dummy; }; +struct jpeg_entropy_decoder { long dummy; }; +struct jpeg_inverse_dct { long dummy; }; +struct jpeg_upsampler { long dummy; }; +struct jpeg_color_deconverter { long dummy; }; +struct jpeg_color_quantizer { long dummy; }; +#endif /* JPEG_INTERNALS */ +#endif /* INCOMPLETE_TYPES_BROKEN */ + + +/* + * The JPEG library modules define JPEG_INTERNALS before including this file. + * The internal structure declarations are read only when that is true. + * Applications using the library should not include jpegint.h, but may wish + * to include jerror.h. + */ + +#ifdef JPEG_INTERNALS +#include "jpegint.h" /* fetch private declarations */ +#include "jerror.h" /* fetch error codes too */ +#endif + +#endif /* JPEGLIB_H */ diff --git a/Utilities/vtkjpeg/jquant1.c b/Utilities/vtkjpeg/jquant1.c new file mode 100644 index 0000000..c779204 --- /dev/null +++ b/Utilities/vtkjpeg/jquant1.c @@ -0,0 +1,862 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 1-pass color quantization (color mapping) routines. + * These routines provide mapping to a fixed color map using equally spaced + * color values. Optional Floyd-Steinberg or ordered dithering is available. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_1PASS_SUPPORTED + + +/* + * The main purpose of 1-pass quantization is to provide a fast, if not very + * high quality, colormapped output capability. A 2-pass quantizer usually + * gives better visual quality; however, for quantized grayscale output this + * quantizer is perfectly adequate. Dithering is highly recommended with this + * quantizer, though you can turn it off if you really want to. + * + * In 1-pass quantization the colormap must be chosen in advance of seeing the + * image. We use a map consisting of all combinations of Ncolors[i] color + * values for the i'th component. The Ncolors[] values are chosen so that + * their product, the total number of colors, is no more than that requested. + * (In most cases, the product will be somewhat less.) + * + * Since the colormap is orthogonal, the representative value for each color + * component can be determined without considering the other components; + * then these indexes can be combined into a colormap index by a standard + * N-dimensional-array-subscript calculation. Most of the arithmetic involved + * can be precalculated and stored in the lookup table colorindex[]. + * colorindex[i][j] maps pixel value j in component i to the nearest + * representative value (grid plane) for that component; this index is + * multiplied by the array stride for component i, so that the + * index of the colormap entry closest to a given pixel value is just + * sum( colorindex[component-number][pixel-component-value] ) + * Aside from being fast, this scheme allows for variable spacing between + * representative values with no additional lookup cost. + * + * If gamma correction has been applied in color conversion, it might be wise + * to adjust the color grid spacing so that the representative colors are + * equidistant in linear space. At this writing, gamma correction is not + * implemented by jdcolor, so nothing is done here. + */ + + +/* Declarations for ordered dithering. + * + * We use a standard 16x16 ordered dither array. The basic concept of ordered + * dithering is described in many references, for instance Dale Schumacher's + * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + * In place of Schumacher's comparisons against a "threshold" value, we add a + * "dither" value to the input pixel and then round the result to the nearest + * output value. The dither value is equivalent to (0.5 - threshold) times + * the distance between output values. For ordered dithering, we assume that + * the output colors are equally spaced; if not, results will probably be + * worse, since the dither may be too much or too little at a given point. + * + * The normal calculation would be to form pixel value + dither, range-limit + * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + * We can skip the separate range-limiting step by extending the colorindex + * table in both directions. + */ + +#define ODITHER_SIZE 16 /* dimension of dither matrix */ +/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */ +#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */ +#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */ + +typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE]; +typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE]; + +static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = { + /* Bayer's order-4 dither array. Generated by the code given in + * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + * The values in this array must range from 0 to ODITHER_CELLS-1. + */ + { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, + { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, + { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, + { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, + { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, + { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, + { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, + { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, + { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, + { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, + { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, + { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, + { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, + { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, + { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, + { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } +}; + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array is indexed [component#][position]. + * We provide (#columns + 2) entries per component; the extra entry at each + * end saves us from special-casing the first and last pixels. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef INT32 FSERROR; /* may need more than 16 bits */ +typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +#define MAX_Q_COMPS 4 /* max components I can handle */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Initially allocated colormap is saved here */ + JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */ + int sv_actual; /* number of entries in use */ + + JSAMPARRAY colorindex; /* Precomputed mapping for speed */ + /* colorindex[i][j] = index of color closest to pixel value j in component i, + * premultiplied as described above. Since colormap indexes must fit into + * JSAMPLEs, the entries of this array will too. + */ + boolean is_padded; /* is the colorindex padded for odither? */ + + int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ + + /* Variables for ordered dithering */ + int row_index; /* cur row's vertical index in dither matrix */ + ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Policy-making subroutines for create_colormap and create_colorindex. + * These routines determine the colormap to be used. The rest of the module + * only assumes that the colormap is orthogonal. + * + * * select_ncolors decides how to divvy up the available colors + * among the components. + * * output_value defines the set of representative values for a component. + * * largest_input_value defines the mapping from input values to + * representative values for a component. + * Note that the latter two routines may impose different policies for + * different components, though this is not currently done. + */ + + +LOCAL(int) +select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) +/* Determine allocation of desired colors to components, */ +/* and fill in Ncolors[] array to indicate choice. */ +/* Return value is total number of colors (product of Ncolors[] values). */ +{ + int nc = cinfo->out_color_components; /* number of color components */ + int max_colors = cinfo->desired_number_of_colors; + int total_colors, iroot, i, j; + boolean changed; + long temp; + static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE }; + + /* We can allocate at least the nc'th root of max_colors per component. */ + /* Compute floor(nc'th root of max_colors). */ + iroot = 1; + do { + iroot++; + temp = iroot; /* set temp = iroot ** nc */ + for (i = 1; i < nc; i++) + temp *= iroot; + } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ + iroot--; /* now iroot = floor(root) */ + + /* Must have at least 2 color values per component */ + if (iroot < 2) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); + + /* Initialize to iroot color values for each component */ + total_colors = 1; + for (i = 0; i < nc; i++) { + Ncolors[i] = iroot; + total_colors *= iroot; + } + /* We may be able to increment the count for one or more components without + * exceeding max_colors, though we know not all can be incremented. + * Sometimes, the first component can be incremented more than once! + * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + * In RGB colorspace, try to increment G first, then R, then B. + */ + do { + changed = FALSE; + for (i = 0; i < nc; i++) { + j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i); + /* calculate new total_colors if Ncolors[j] is incremented */ + temp = total_colors / Ncolors[j]; + temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ + if (temp > (long) max_colors) + break; /* won't fit, done with this pass */ + Ncolors[j]++; /* OK, apply the increment */ + total_colors = (int) temp; + changed = TRUE; + } + } while (changed); + + return total_colors; +} + + +LOCAL(int) +output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return j'th output value, where j will range from 0 to maxj */ +/* The output values must fall in 0..MAXJSAMPLE in increasing order */ +{ + cinfo = 0; + ci = 0; + /* We always provide values 0 and MAXJSAMPLE for each component; + * any additional values are equally spaced between these limits. + * (Forcing the upper and lower values to the limits ensures that + * dithering can't produce a color outside the selected gamut.) + */ + return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); +} + + +LOCAL(int) +largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) +/* Return largest input value that should map to j'th output value */ +/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ +{ + cinfo = 0; + ci = 0; + /* Breakpoints are halfway between values returned by output_value */ + return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); +} + + +/* + * Create the colormap. + */ + +LOCAL(void) +create_colormap (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colormap; /* Created colormap */ + int total_colors; /* Number of distinct output colors */ + int i,j,k, nci, blksize, blkdist, ptr, val; + + /* Select number of colors for each component */ + total_colors = select_ncolors(cinfo, cquantize->Ncolors); + + /* Report selected color counts */ + if (cinfo->out_color_components == 3) + TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); + else + TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); + + /* Allocate and fill in the colormap. */ + /* The colors are ordered in the map in standard row-major order, */ + /* i.e. rightmost (highest-indexed) color changes most rapidly. */ + + colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + /* blkdist is distance between groups of identical entries for a component */ + blkdist = total_colors; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colormap entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blkdist / nci; + for (j = 0; j < nci; j++) { + /* Compute j'th output value (out of nci) for component */ + val = output_value(cinfo, i, j, nci-1); + /* Fill in all colormap entries that have this value of this component */ + for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; + } + } + blkdist = blksize; /* blksize of this color is blkdist of next */ + } + + /* Save the colormap in private storage, + * where it will survive color quantization mode changes. + */ + cquantize->sv_colormap = colormap; + cquantize->sv_actual = total_colors; +} + + +/* + * Create the color index table. + */ + +LOCAL(void) +create_colorindex (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPROW indexptr; + int i,j,k, nci, blksize, val, pad; + + /* For ordered dither, we pad the color index tables by MAXJSAMPLE in + * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + * This is not necessary in the other dithering modes. However, we + * flag whether it was done in case user changes dithering mode. + */ + if (cinfo->dither_mode == JDITHER_ORDERED) { + pad = MAXJSAMPLE*2; + cquantize->is_padded = TRUE; + } else { + pad = 0; + cquantize->is_padded = FALSE; + } + + cquantize->colorindex = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (MAXJSAMPLE+1 + pad), + (JDIMENSION) cinfo->out_color_components); + + /* blksize is number of adjacent repeated entries for a component */ + blksize = cquantize->sv_actual; + + for (i = 0; i < cinfo->out_color_components; i++) { + /* fill in colorindex entries for i'th color component */ + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + blksize = blksize / nci; + + /* adjust colorindex pointers to provide padding at negative indexes. */ + if (pad) + cquantize->colorindex[i] += MAXJSAMPLE; + + /* in loop, val = index of current output value, */ + /* and k = largest j that maps to current val */ + indexptr = cquantize->colorindex[i]; + val = 0; + k = largest_input_value(cinfo, i, 0, nci-1); + for (j = 0; j <= MAXJSAMPLE; j++) { + while (j > k) /* advance val if past boundary */ + k = largest_input_value(cinfo, i, ++val, nci-1); + /* premultiply so that no multiplication needed in main processing */ + indexptr[j] = (JSAMPLE) (val * blksize); + } + /* Pad at both ends if necessary */ + if (pad) + for (j = 1; j <= MAXJSAMPLE; j++) { + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + } + } +} + + +/* + * Create an ordered-dither array for a component having ncolors + * distinct output values. + */ + +LOCAL(ODITHER_MATRIX_PTR) +make_odither_array (j_decompress_ptr cinfo, int ncolors) +{ + ODITHER_MATRIX_PTR odither; + int j,k; + INT32 num,den; + + odither = (ODITHER_MATRIX_PTR) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX)); + /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + * Hence the dither value for the matrix cell with fill order f + * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + * On 16-bit-int machine, be careful to avoid overflow. + */ + den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1)); + for (j = 0; j < ODITHER_SIZE; j++) { + for (k = 0; k < ODITHER_SIZE; k++) { + num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) + * MAXJSAMPLE; + /* Ensure round towards zero despite C's lack of consistency + * about rounding negative values in integer division... + */ + odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den); + } + } + return odither; +} + + +/* + * Create the ordered-dither tables. + * Components having the same number of representative colors may + * share a dither table. + */ + +LOCAL(void) +create_odither_tables (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + ODITHER_MATRIX_PTR odither; + int i, j, nci; + + for (i = 0; i < cinfo->out_color_components; i++) { + nci = cquantize->Ncolors[i]; /* # of distinct values for this color */ + odither = NULL; /* search for matching prior component */ + for (j = 0; j < i; j++) { + if (nci == cquantize->Ncolors[j]) { + odither = cquantize->odither[j]; + break; + } + } + if (odither == NULL) /* need a new table? */ + odither = make_odither_array(cinfo, nci); + cquantize->odither[i] = odither; + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + JSAMPARRAY colorindex = cquantize->colorindex; + register int pixcode, ci; + register JSAMPROW ptrin, ptrout; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + register int nc = cinfo->out_color_components; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = 0; + for (ci = 0; ci < nc; ci++) { + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + } + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW ptrin, ptrout; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + ptrin = input_buf[row]; + ptrout = output_buf[row]; + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); + *ptrout++ = (JSAMPLE) pixcode; + } + } +} + + +METHODDEF(void) +quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + int * dither; /* points to active row of dither matrix */ + int row_index, col_index; /* current indexes into dither matrix */ + int nc = cinfo->out_color_components; + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + row_index = cquantize->row_index; + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + colorindex_ci = cquantize->colorindex[ci]; + dither = cquantize->odither[ci][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; + } + } + /* Advance row index for next row */ + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* Fast path for out_color_components==3, with ordered dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register int pixcode; + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex0 = cquantize->colorindex[0]; + JSAMPROW colorindex1 = cquantize->colorindex[1]; + JSAMPROW colorindex2 = cquantize->colorindex[2]; + int * dither0; /* points to active row of dither matrix */ + int * dither1; + int * dither2; + int row_index, col_index; /* current indexes into dither matrix */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + row_index = cquantize->row_index; + input_ptr = input_buf[row]; + output_ptr = output_buf[row]; + dither0 = cquantize->odither[0][row_index]; + dither1 = cquantize->odither[1][row_index]; + dither2 = cquantize->odither[2][row_index]; + col_index = 0; + + for (col = width; col > 0; col--) { + pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + + dither0[col_index]]); + pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + + dither1[col_index]]); + pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + + dither2[col_index]]); + *output_ptr++ = (JSAMPLE) pixcode; + col_index = (col_index + 1) & ODITHER_MASK; + } + row_index = (row_index + 1) & ODITHER_MASK; + cquantize->row_index = row_index; + } +} + + +METHODDEF(void) +quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +/* General case, with Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register LOCFSERROR cur; /* current error or pixel value */ + LOCFSERROR belowerr; /* error for pixel below cur */ + LOCFSERROR bpreverr; /* error for below/prev col */ + LOCFSERROR bnexterr; /* error for below/next col */ + LOCFSERROR delta; + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + register JSAMPROW input_ptr; + register JSAMPROW output_ptr; + JSAMPROW colorindex_ci; + JSAMPROW colormap_ci; + int pixcode; + int nc = cinfo->out_color_components; + int dir; /* 1 for left-to-right, -1 for right-to-left */ + int dirnc; /* dir * nc */ + int ci; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + /* Initialize output values to 0 so can process components separately */ + jzero_far((void FAR *) output_buf[row], + (size_t) (width * SIZEOF(JSAMPLE))); + for (ci = 0; ci < nc; ci++) { + input_ptr = input_buf[row] + ci; + output_ptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + input_ptr += (width-1) * nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + } else { + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + } + colorindex_ci = cquantize->colorindex[ci]; + colormap_ci = cquantize->sv_colormap[ci]; + /* Preset error values: no error propagated to first pixel from left */ + cur = 0; + /* and no error propagated to row below yet */ + belowerr = bpreverr = 0; + + for (col = width; col > 0; col--) { + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr += (JSAMPLE) pixcode; + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error value into the + * final fserrors[] entry. Note we need not unload belowerr because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ + } + cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); + } +} + + +/* + * Allocate workspace for Floyd-Steinberg errors. + */ + +LOCAL(void) +alloc_fs_workspace (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) { + cquantize->fserrors[i] = (FSERRPTR) + (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + } +} + + +/* + * Initialize for one-pass color quantization. + */ + +METHODDEF(void) +start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + size_t arraysize; + int i; + + is_pre_scan = 0; + /* Install my colormap. */ + cinfo->colormap = cquantize->sv_colormap; + cinfo->actual_number_of_colors = cquantize->sv_actual; + + /* Initialize for desired dithering mode. */ + switch (cinfo->dither_mode) { + case JDITHER_NONE: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = color_quantize3; + else + cquantize->pub.color_quantize = color_quantize; + break; + case JDITHER_ORDERED: + if (cinfo->out_color_components == 3) + cquantize->pub.color_quantize = quantize3_ord_dither; + else + cquantize->pub.color_quantize = quantize_ord_dither; + cquantize->row_index = 0; /* initialize state for ordered dither */ + /* If user changed to ordered dither from another mode, + * we must recreate the color index table with padding. + * This will cost extra space, but probably isn't very likely. + */ + if (! cquantize->is_padded) + create_colorindex(cinfo); + /* Create ordered-dither tables if we didn't already. */ + if (cquantize->odither[0] == NULL) + create_odither_tables(cinfo); + break; + case JDITHER_FS: + cquantize->pub.color_quantize = quantize_fs_dither; + cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ + /* Allocate Floyd-Steinberg workspace if didn't already. */ + if (cquantize->fserrors[0] == NULL) + alloc_fs_workspace(cinfo); + /* Initialize the propagated errors to zero. */ + arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); + for (i = 0; i < cinfo->out_color_components; i++) + jzero_far((void FAR *) cquantize->fserrors[i], arraysize); + break; + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } +} + + +/* + * Finish up at the end of the pass. + */ + +METHODDEF(void) +finish_pass_1_quant (j_decompress_ptr cinfo) +{ + cinfo = 0; + /* no work in 1-pass case */ +} + + +/* + * Switch to a new external colormap between output passes. + * Shouldn't get to this module! + */ + +METHODDEF(void) +new_color_map_1_quant (j_decompress_ptr cinfo) +{ + ERREXIT(cinfo, JERR_MODE_CHANGE); +} + + +/* + * Module initialization routine for 1-pass color quantization. + */ + +GLOBAL(void) +jinit_1pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_1_quant; + cquantize->pub.finish_pass = finish_pass_1_quant; + cquantize->pub.new_color_map = new_color_map_1_quant; + cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */ + cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */ + + /* Make sure my internal arrays won't overflow */ + if (cinfo->out_color_components > MAX_Q_COMPS) + ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + /* Create the colormap and color index table. */ + create_colormap(cinfo); + create_colorindex(cinfo); + + /* Allocate Floyd-Steinberg workspace now if requested. + * We do this now since it is FAR storage and may affect the memory + * manager's space calculations. If the user changes to FS dither + * mode in a later pass, we will allocate the space then, and will + * possibly overrun the max_memory_to_use setting. + */ + if (cinfo->dither_mode == JDITHER_FS) + alloc_fs_workspace(cinfo); +} + +#endif /* QUANT_1PASS_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jquant2.c b/Utilities/vtkjpeg/jquant2.c new file mode 100644 index 0000000..9bda06d --- /dev/null +++ b/Utilities/vtkjpeg/jquant2.c @@ -0,0 +1,1312 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains 2-pass color quantization (color mapping) routines. + * These routines provide selection of a custom color map for an image, + * followed by mapping of the image to that color map, with optional + * Floyd-Steinberg dithering. + * It is also possible to use just the second pass to map to an arbitrary + * externally-given color map. + * + * Note: ordered dithering is not supported, since there isn't any fast + * way to compute intercolor distances; it's unclear that ordered dither's + * fundamental assumptions even hold with an irregularly spaced color map. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +#ifdef QUANT_2PASS_SUPPORTED + + +/* + * This module implements the well-known Heckbert paradigm for color + * quantization. Most of the ideas used here can be traced back to + * Heckbert's seminal paper + * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + * + * In the first pass over the image, we accumulate a histogram showing the + * usage count of each possible color. To keep the histogram to a reasonable + * size, we reduce the precision of the input; typical practice is to retain + * 5 or 6 bits per color, so that 8 or 4 different input values are counted + * in the same histogram cell. + * + * Next, the color-selection step begins with a box representing the whole + * color space, and repeatedly splits the "largest" remaining box until we + * have as many boxes as desired colors. Then the mean color in each + * remaining box becomes one of the possible output colors. + * + * The second pass over the image maps each input pixel to the closest output + * color (optionally after applying a Floyd-Steinberg dithering correction). + * This mapping is logically trivial, but making it go fast enough requires + * considerable care. + * + * Heckbert-style quantizers vary a good deal in their policies for choosing + * the "largest" box and deciding where to cut it. The particular policies + * used here have proved out well in experimental comparisons, but better ones + * may yet be found. + * + * In earlier versions of the IJG code, this module quantized in YCbCr color + * space, processing the raw upsampled data without a color conversion step. + * This allowed the color conversion math to be done only once per colormap + * entry, not once per pixel. However, that optimization precluded other + * useful optimizations (such as merging color conversion with upsampling) + * and it also interfered with desired capabilities such as quantizing to an + * externally-supplied colormap. We have therefore abandoned that approach. + * The present code works in the post-conversion color space, typically RGB. + * + * To improve the visual quality of the results, we actually work in scaled + * RGB space, giving G distances more weight than R, and R in turn more than + * B. To do everything in integer math, we must use integer scale factors. + * The 2/3/1 scale factors used here correspond loosely to the relative + * weights of the colors in the NTSC grayscale equation. + * If you want to use this code to quantize a non-RGB color space, you'll + * probably need to change these scale factors. + */ + +#define R_SCALE 2 /* scale R distances by this much */ +#define G_SCALE 3 /* scale G distances by this much */ +#define B_SCALE 1 /* and B by this much */ + +/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + * and B,G,R orders. If you define some other weird order in jmorecfg.h, + * you'll get compile errors until you extend this logic. In that case + * you'll probably want to tweak the histogram sizes too. + */ + +#if RGB_RED == 0 +#define C0_SCALE R_SCALE +#endif +#if RGB_BLUE == 0 +#define C0_SCALE B_SCALE +#endif +#if RGB_GREEN == 1 +#define C1_SCALE G_SCALE +#endif +#if RGB_RED == 2 +#define C2_SCALE R_SCALE +#endif +#if RGB_BLUE == 2 +#define C2_SCALE B_SCALE +#endif + + +/* + * First we have the histogram data structure and routines for creating it. + * + * The number of bits of precision can be adjusted by changing these symbols. + * We recommend keeping 6 bits for G and 5 each for R and B. + * If you have plenty of memory and cycles, 6 bits all around gives marginally + * better results; if you are short of memory, 5 bits all around will save + * some space but degrade the results. + * To maintain a fully accurate histogram, we'd need to allocate a "long" + * (preferably unsigned long) for each cell. In practice this is overkill; + * we can get by with 16 bits per cell. Few of the cell counts will overflow, + * and clamping those that do overflow to the maximum value will give close- + * enough results. This reduces the recommended histogram size from 256Kb + * to 128Kb, which is a useful savings on PC-class machines. + * (In the second pass the histogram space is re-used for pixel mapping data; + * in that capacity, each cell must be able to store zero to the number of + * desired colors. 16 bits/cell is plenty for that too.) + * Since the JPEG code is intended to run in small memory model on 80x86 + * machines, we can't just allocate the histogram in one chunk. Instead + * of a true 3-D array, we use a row of pointers to 2-D arrays. Each + * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + * on 80x86 machines, the pointer row is in near memory but the actual + * arrays are in far memory (same arrangement as we use for image arrays). + */ + +#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ + +/* These will do the right thing for either R,G,B or B,G,R color order, + * but you may not like the results for other color orders. + */ +#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1<<HIST_C0_BITS) +#define HIST_C1_ELEMS (1<<HIST_C1_BITS) +#define HIST_C2_ELEMS (1<<HIST_C2_BITS) + +/* These are the amounts to shift an input value to get a histogram index. */ +#define C0_SHIFT (BITS_IN_JSAMPLE-HIST_C0_BITS) +#define C1_SHIFT (BITS_IN_JSAMPLE-HIST_C1_BITS) +#define C2_SHIFT (BITS_IN_JSAMPLE-HIST_C2_BITS) + + +typedef UINT16 histcell; /* histogram cell; prefer an unsigned type */ + +typedef histcell FAR * histptr; /* for pointers to histogram cells */ + +typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */ +typedef hist1d FAR * hist2d; /* type for the 2nd-level pointers */ +typedef hist2d * hist3d; /* type for top-level pointer */ + + +/* Declarations for Floyd-Steinberg dithering. + * + * Errors are accumulated into the array fserrors[], at a resolution of + * 1/16th of a pixel count. The error at a given pixel is propagated + * to its not-yet-processed neighbors using the standard F-S fractions, + * ... (here) 7/16 + * 3/16 5/16 1/16 + * We work left-to-right on even rows, right-to-left on odd rows. + * + * We can get away with a single array (holding one row's worth of errors) + * by using it to store the current row's errors at pixel columns not yet + * processed, but the next row's errors at columns already processed. We + * need only a few extra variables to hold the errors immediately around the + * current column. (If we are lucky, those variables are in registers, but + * even if not, they're probably cheaper to access than array elements are.) + * + * The fserrors[] array has (#columns + 2) entries; the extra entry at + * each end saves us from special-casing the first and last pixels. + * Each entry is three values long, one value for each color component. + * + * Note: on a wide image, we might not have enough room in a PC's near data + * segment to hold the error array; so it is allocated with alloc_large. + */ + +#if BITS_IN_JSAMPLE == 8 +typedef INT16 FSERROR; /* 16 bits should be enough */ +typedef int LOCFSERROR; /* use 'int' for calculation temps */ +#else +typedef INT32 FSERROR; /* may need more than 16 bits */ +typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ +#endif + +typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ + + +/* Private subobject */ + +typedef struct { + struct jpeg_color_quantizer pub; /* public fields */ + + /* Space for the eventually created colormap is stashed here */ + JSAMPARRAY sv_colormap; /* colormap allocated at init time */ + int desired; /* desired # of colors = size of colormap */ + + /* Variables for accumulating image statistics */ + hist3d histogram; /* pointer to the histogram */ + + boolean needs_zeroed; /* TRUE if next pass must zero histogram */ + + /* Variables for Floyd-Steinberg dithering */ + FSERRPTR fserrors; /* accumulated errors */ + boolean on_odd_row; /* flag to remember which row we are on */ + int * error_limiter; /* table for clamping the applied error */ +} my_cquantizer; + +typedef my_cquantizer * my_cquantize_ptr; + + +/* + * Prescan some rows of pixels. + * In this module the prescan simply updates the histogram, which has been + * initialized to zeroes by start_pass. + * An output_buf parameter is required by the method signature, but no data + * is actually output (in fact the buffer controller is probably passing a + * NULL pointer). + */ + +METHODDEF(void) +prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + register JSAMPROW ptr; + register histptr histp; + register hist3d histogram = cquantize->histogram; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + output_buf = 0; + for (row = 0; row < num_rows; row++) { + ptr = input_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the histogram */ + histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + ptr += 3; + } + } +} + + +/* + * Next we have the really interesting routines: selection of a colormap + * given the completed histogram. + * These routines work with a list of "boxes", each representing a rectangular + * subset of the input color space (to histogram precision). + */ + +typedef struct { + /* The bounds of the box (inclusive); expressed as histogram indexes */ + int c0min, c0max; + int c1min, c1max; + int c2min, c2max; + /* The volume (actually 2-norm) of the box */ + INT32 volume; + /* The number of nonzero histogram cells within this box */ + long colorcount; +} box; + +typedef box * boxptr; + + +LOCAL(boxptr) +find_biggest_color_pop (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest color population */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +LOCAL(boxptr) +find_biggest_volume (boxptr boxlist, int numboxes) +/* Find the splittable box with the largest (scaled) volume */ +/* Returns NULL if no splittable boxes remain */ +{ + register boxptr boxp; + register int i; + register INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +LOCAL(void) +update_box (j_decompress_ptr cinfo, boxptr boxp) +/* Shrink the min/max bounds of a box to enclose only nonzero elements, */ +/* and recompute its volume and population */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } + have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } + have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } + have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } + have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } + have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } + have_c2max: + + /* Update box volume. + * We use 2-norm rather than real volume here; this biases the method + * against making long narrow boxes, and it has the side benefit that + * a box is splittable iff norm > 0. + * Since the differences are expressed in histogram-cell units, + * we have to shift back to JSAMPLE units to get consistent distances; + * after which, we scale according to the selected distance scale factors. + */ + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + /* Now scan remaining volume of box and compute population */ + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +LOCAL(int) +median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, + int desired_colors) +/* Repeatedly select and split the largest box until we have enough boxes */ +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + * Current algorithm: longest scaled axis. + * See notes in update_box about scaling distances. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + /* We want to break any ties in favor of green, then red, blue last. + * This code does the right thing for R,G,B or B,G,R color orders only. + */ +#if RGB_RED == 0 + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } +#else + cmax = c1; n = 1; + if (c2 > cmax) { cmax = c2; n = 2; } + if (c0 > cmax) { n = 0; } +#endif + /* Choose split point along selected axis, and update box bounds. + * Current algorithm: split at halfway point. + * (Since the box has been shrunk to minimum volume, + * any split will produce two nonempty subboxes.) + * Note that lb value is max for lower box, so must be < old max. + */ + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(cinfo, b1); + update_box(cinfo, b2); + numboxes++; + } + return numboxes; +} + + +LOCAL(void) +compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) +/* Compute representative color for a box, put it in colormap[icolor] */ +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count; + } + } + } + + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +LOCAL(void) +select_colors (j_decompress_ptr cinfo, int desired_colors) +/* Master routine for color selection */ +{ + boxptr boxlist; + int numboxes; + int i; + + /* Allocate workspace for box list */ + boxlist = (boxptr) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(cinfo, & boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(cinfo, & boxlist[i], i); + cinfo->actual_number_of_colors = numboxes; + TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); +} + + +/* + * These routines are concerned with the time-critical task of mapping input + * colors to the nearest color in the selected colormap. + * + * We re-use the histogram space as an "inverse color map", essentially a + * cache for the results of nearest-color searches. All colors within a + * histogram cell will be mapped to the same colormap entry, namely the one + * closest to the cell's center. This may not be quite the closest entry to + * the actual input color, but it's almost as good. A zero in the cache + * indicates we haven't found the nearest color for that cell yet; the array + * is cleared to zeroes before starting the mapping pass. When we find the + * nearest color for a cell, its colormap index plus one is recorded in the + * cache for future use. The pass2 scanning routines call fill_inverse_cmap + * when they need to use an unfilled entry in the cache. + * + * Our method of efficiently finding nearest colors is based on the "locally + * sorted search" idea described by Heckbert and on the incremental distance + * calculation described by Spencer W. Thomas in chapter III.1 of Graphics + * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + * the distances from a given colormap entry to each cell of the histogram can + * be computed quickly using an incremental method: the differences between + * distances to adjacent cells themselves differ by a constant. This allows a + * fairly fast implementation of the "brute force" approach of computing the + * distance from every colormap entry to every histogram cell. Unfortunately, + * it needs a work array to hold the best-distance-so-far for each histogram + * cell (because the inner loop has to be over cells, not colormap entries). + * The work array elements have to be INT32s, so the work array would need + * 256Kb at our recommended precision. This is not feasible in DOS machines. + * + * To get around these problems, we apply Thomas' method to compute the + * nearest colors for only the cells within a small subbox of the histogram. + * The work array need be only as big as the subbox, so the memory usage + * problem is solved. Furthermore, we need not fill subboxes that are never + * referenced in pass2; many images use only part of the color gamut, so a + * fair amount of work is saved. An additional advantage of this + * approach is that we can apply Heckbert's locality criterion to quickly + * eliminate colormap entries that are far away from the subbox; typically + * three-fourths of the colormap entries are rejected by Heckbert's criterion, + * and we need not compute their distances to individual cells in the subbox. + * The speed of this approach is heavily influenced by the subbox size: too + * small means too much overhead, too big loses because Heckbert's criterion + * can't eliminate as many colormap entries. Empirically the best subbox + * size seems to be about 1/512th of the histogram (1/8th in each direction). + * + * Thomas' article also describes a refined method which is asymptotically + * faster than the brute-force method, but it is also far more complex and + * cannot efficiently be applied to small subboxes. It is therefore not + * useful for programs intended to be portable to DOS machines. On machines + * with plenty of memory, filling the whole histogram in one shot with Thomas' + * refined method might be faster than the present code --- but then again, + * it might not be any faster, and it's certainly more complicated. + */ + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<<BOX_C0_LOG) /* # of hist cells in update box */ +#define BOX_C1_ELEMS (1<<BOX_C1_LOG) +#define BOX_C2_ELEMS (1<<BOX_C2_LOG) + +#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG) +#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG) +#define BOX_C2_SHIFT (C2_SHIFT + BOX_C2_LOG) + + +/* + * The next three routines implement inverse colormap filling. They could + * all be folded into one big routine, but splitting them up this way saves + * some stack space (the mindist[] and bestdist[] arrays need not coexist) + * and may allow some compilers to produce better code by registerizing more + * inner-loop variables. + */ + +LOCAL(int) +find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + JSAMPLE colorlist[]) +/* Locate the colormap entries close enough to an update box to be candidates + * for the nearest entry to some cell(s) in the update box. The update box + * is specified by the center coordinates of its first cell. The number of + * candidate colormap entries is returned, and their colormap indexes are + * placed in colorlist[]. + * This routine uses Heckbert's "locally sorted search" criterion to select + * the colors that need further consideration. + */ +{ + int numcolors = cinfo->actual_number_of_colors; + int maxc0, maxc1, maxc2; + int centerc0, centerc1, centerc2; + int i, x, ncolors; + INT32 minmaxdist, min_dist, max_dist, tdist; + INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ + + /* Compute true coordinates of update box's upper corner and center. + * Actually we compute the coordinates of the center of the upper-corner + * histogram cell, which are the upper bounds of the volume we care about. + * Note that since ">>" rounds down, the "center" values may be closer to + * min than to max; hence comparisons to them must be "<=", not "<". + */ + maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT)); + centerc0 = (minc0 + maxc0) >> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + /* For each color in colormap, find: + * 1. its minimum squared-distance to any point in the update box + * (zero if color is within update box); + * 2. its maximum squared-distance to any point in the update box. + * Both of these can be found by considering only the corners of the box. + * We save the minimum distance for each color in mindist[]; + * only the smallest maximum distance is of interest. + */ + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = GETJSAMPLE(cinfo->colormap[0][i]); + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[1][i]); + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = GETJSAMPLE(cinfo->colormap[2][i]); + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + /* Now we know that no cell in the update box is more than minmaxdist + * away from some colormap entry. Therefore, only colors that are + * within minmaxdist of some part of the box need be considered. + */ + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +LOCAL(void) +find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) +/* Find the closest colormap entry for each cell in the update box, + * given the list of candidate colors prepared by find_nearby_colors. + * Return the indexes of the closest entries in the bestcolor[] array. + * This routine uses Thomas' incremental distance calculation method to + * find the distance from a colormap entry to successive cells in the box. + */ +{ + int ic0, ic1, ic2; + int i, icolor; + register INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ + register INT32 xx2; + INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* For each color selected by find_nearby_colors, + * compute its distance to the center of each cell in the box. + * If that's less than best-so-far, update best distance and color number. + */ + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = GETJSAMPLE(colorlist[i]); + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +LOCAL(void) +fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) +/* Fill the inverse-colormap entries in the update box that contains */ +/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ +/* we can fill as many others as we wish.) */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + /* Compute true coordinates of update box's origin corner. + * Actually we compute the coordinates of the center of the corner + * histogram cell, which are the lower bounds of the volume we care about. + */ + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + /* Determine which colormap entries are close enough to be candidates + * for the nearest entry to some cell in the update box. + */ + numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + } + } + } +} + + +/* + * Map some rows of pixels to the output colormapped representation. + */ + +METHODDEF(void) +pass2_no_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs no dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register JSAMPROW inptr, outptr; + register histptr cachep; + register int c0, c1, c2; + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + for (col = width; col > 0; col--) { + /* get pixel value and index into the cache */ + c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT; + c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT; + c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT; + cachep = & histogram[c0][c1][c2]; + /* If we have not seen this color before, find nearest colormap entry */ + /* and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, c0,c1,c2); + /* Now emit the colormap index for this cell */ + *outptr++ = (JSAMPLE) (*cachep - 1); + } + } +} + + +METHODDEF(void) +pass2_fs_dither (j_decompress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) +/* This version performs Floyd-Steinberg dithering */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing inptr & errorptr */ + int row; + JDIMENSION col; + JDIMENSION width = cinfo->output_width; + JSAMPLE *range_limit = cinfo->sample_range_limit; + int *error_limit = cquantize->error_limiter; + JSAMPROW colormap0 = cinfo->colormap[0]; + JSAMPROW colormap1 = cinfo->colormap[1]; + JSAMPROW colormap2 = cinfo->colormap[2]; + SHIFT_TEMPS + + for (row = 0; row < num_rows; row++) { + inptr = input_buf[row]; + outptr = output_buf[row]; + if (cquantize->on_odd_row) { + /* work right to left in this row */ + inptr += (width-1) * 3; /* so point to rightmost pixel */ + outptr += width-1; + dir = -1; + dir3 = -3; + errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ + cquantize->on_odd_row = FALSE; /* flip for next time */ + } else { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = cquantize->fserrors; /* => entry before first real column */ + cquantize->on_odd_row = TRUE; /* flip for next time */ + } + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) { + /* curN holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); + cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); + cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); + /* Limit the error using transfer function set by init_error_limit. + * See comments with init_error_limit for rationale. + */ + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE (or less with error limiting); + * this sets the required size of the range_limit array. + */ + cur0 += GETJSAMPLE(inptr[0]); + cur1 += GETJSAMPLE(inptr[1]); + cur2 += GETJSAMPLE(inptr[2]); + cur0 = GETJSAMPLE(range_limit[cur0]); + cur1 = GETJSAMPLE(range_limit[cur1]); + cur2 = GETJSAMPLE(range_limit[cur2]); + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); + /* Now emit the colormap index for this cell */ + { register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); + } + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + { register LOCFSERROR bnexterr, delta; + + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inptr += dir3; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* + * Initialize the error-limiting transfer function (lookup table). + * The raw F-S error computation can potentially compute error values of up to + * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + * much less, otherwise obviously wrong pixels will be created. (Typical + * effects include weird fringes at color-area boundaries, isolated bright + * pixels in a dark area, etc.) The standard advice for avoiding this problem + * is to ensure that the "corners" of the color cube are allocated as output + * colors; then repeated errors in the same direction cannot cause cascading + * error buildup. However, that only prevents the error from getting + * completely out of hand; Aaron Giles reports that error limiting improves + * the results even with corner colors allocated. + * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + * well, but the smoother transfer function used below is even better. Thanks + * to Aaron Giles for this idea. + */ + +LOCAL(void) +init_error_limit (j_decompress_ptr cinfo) +/* Allocate and fill in the error_limiter table */ +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + int * table; + int in, out; + + table = (int *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); + table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ + cquantize->error_limiter = table; + +#define STEPSIZE ((MAXJSAMPLE+1)/16) + /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) { + table[in] = out; table[-in] = -out; + } + /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { + table[in] = out; table[-in] = -out; + } + /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ + for (; in <= MAXJSAMPLE; in++) { + table[in] = out; table[-in] = -out; + } +#undef STEPSIZE +} + + +/* + * Finish up at the end of each pass. + */ + +METHODDEF(void) +finish_pass1 (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Select the representative colors and fill in cinfo->colormap */ + cinfo->colormap = cquantize->sv_colormap; + select_colors(cinfo, cquantize->desired); + /* Force next pass to zero the color index table */ + cquantize->needs_zeroed = TRUE; +} + + +METHODDEF(void) +finish_pass2 (j_decompress_ptr cinfo) +{ + cinfo = 0; + /* no work */ +} + + +/* + * Initialize for each processing pass. + */ + +METHODDEF(void) +start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + hist3d histogram = cquantize->histogram; + int i; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + if (is_pre_scan) { + /* Set up method pointers */ + cquantize->pub.color_quantize = prescan_quantize; + cquantize->pub.finish_pass = finish_pass1; + cquantize->needs_zeroed = TRUE; /* Always zero histogram */ + } else { + /* Set up method pointers */ + if (cinfo->dither_mode == JDITHER_FS) + cquantize->pub.color_quantize = pass2_fs_dither; + else + cquantize->pub.color_quantize = pass2_no_dither; + cquantize->pub.finish_pass = finish_pass2; + + /* Make sure color count is acceptable */ + i = cinfo->actual_number_of_colors; + if (i < 1) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo->dither_mode == JDITHER_FS) { + size_t arraysize = (size_t) ((cinfo->output_width + 2) * + (3 * SIZEOF(FSERROR))); + /* Allocate Floyd-Steinberg workspace if we didn't already. */ + if (cquantize->fserrors == NULL) + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + /* Initialize the propagated errors to zero. */ + jzero_far((void FAR *) cquantize->fserrors, arraysize); + /* Make the error-limit table if we didn't already. */ + if (cquantize->error_limiter == NULL) + init_error_limit(cinfo); + cquantize->on_odd_row = FALSE; + } + + } + /* Zero the histogram or inverse color map, if necessary */ + if (cquantize->needs_zeroed) { + for (i = 0; i < HIST_C0_ELEMS; i++) { + jzero_far((void FAR *) histogram[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = FALSE; + } +} + + +/* + * Switch to a new external colormap between output passes. + */ + +METHODDEF(void) +new_color_map_2_quant (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; + + /* Reset the inverse color map */ + cquantize->needs_zeroed = TRUE; +} + + +/* + * Module initialization routine for 2-pass color quantization. + */ + +GLOBAL(void) +jinit_2pass_quantizer (j_decompress_ptr cinfo) +{ + my_cquantize_ptr cquantize; + int i; + + cquantize = (my_cquantize_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(my_cquantizer)); + cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; + cquantize->pub.start_pass = start_pass_2_quant; + cquantize->pub.new_color_map = new_color_map_2_quant; + cquantize->fserrors = NULL; /* flag optional arrays not allocated */ + cquantize->error_limiter = NULL; + + /* Make sure jdmaster didn't give me a case I can't handle */ + if (cinfo->out_color_components != 3) + ERREXIT(cinfo, JERR_NOTIMPL); + + /* Allocate the histogram/inverse colormap storage */ + cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d)); + for (i = 0; i < HIST_C0_ELEMS; i++) { + cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + } + cquantize->needs_zeroed = TRUE; /* histogram is garbage now */ + + /* Allocate storage for the completed colormap, if required. + * We do this now since it is FAR storage and may affect + * the memory manager's space calculations. + */ + if (cinfo->enable_2pass_quant) { + /* Make sure color count is acceptable */ + int desired = cinfo->desired_number_of_colors; + /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ + if (desired < 8) + ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); + /* Make sure colormap indexes can be represented by JSAMPLEs */ + if (desired > MAXNUMCOLORS) + ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize->sv_colormap = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3); + cquantize->desired = desired; + } else + cquantize->sv_colormap = NULL; + + /* Only F-S dithering or no dithering is supported. */ + /* If user asks for ordered dither, give him F-S. */ + if (cinfo->dither_mode != JDITHER_NONE) + cinfo->dither_mode = JDITHER_FS; + + /* Allocate Floyd-Steinberg workspace if necessary. + * This isn't really needed until pass 2, but again it is FAR storage. + * Although we will cope with a later change in dither_mode, + * we do not promise to honor max_memory_to_use if dither_mode changes. + */ + if (cinfo->dither_mode == JDITHER_FS) { + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR)))); + /* Might as well create the error-limiting table too. */ + init_error_limit(cinfo); + } +} + +#endif /* QUANT_2PASS_SUPPORTED */ diff --git a/Utilities/vtkjpeg/jutils.c b/Utilities/vtkjpeg/jutils.c new file mode 100644 index 0000000..d18a955 --- /dev/null +++ b/Utilities/vtkjpeg/jutils.c @@ -0,0 +1,179 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains tables and miscellaneous utility routines needed + * for both compression and decompression. + * Note we prefix all global names with "j" to minimize conflicts with + * a surrounding application. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* + * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + * of a DCT block read in natural order (left to right, top to bottom). + */ + +#if 0 /* This table is not actually needed in v6a */ + +const int jpeg_zigzag_order[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + +#endif + +/* + * jpeg_natural_order[i] is the natural-order position of the i'th element + * of zigzag order. + * + * When reading corrupted data, the Huffman decoders could attempt + * to reference an entry beyond the end of this array (if the decoded + * zero run length reaches past the end of the block). To prevent + * wild stores without adding an inner-loop test, we put some extra + * "63"s after the real entries. This will cause the extra coefficient + * to be stored in location 63 of the block, not somewhere random. + * The worst case would be a run-length of 15, which means we need 16 + * fake entries. + */ + +const int jpeg_natural_order[DCTSIZE2+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + + +/* + * Arithmetic utilities + */ + +GLOBAL(long) +jdiv_round_up (long a, long b) +/* Compute a/b rounded up to next integer, ie, ceil(a/b) */ +/* Assumes a >= 0, b > 0 */ +{ + return (a + b - 1L) / b; +} + + +GLOBAL(long) +jround_up (long a, long b) +/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ +/* Assumes a >= 0, b > 0 */ +{ + a += b - 1L; + return a - (a % b); +} + + +/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + * and coefficient-block arrays. This won't work on 80x86 because the arrays + * are FAR and we're assuming a small-pointer memory model. However, some + * DOS compilers provide far-pointer versions of memcpy() and memset() even + * in the small-model libraries. These will be used if USE_FMEM is defined. + * Otherwise, the routines below do it the hard way. (The performance cost + * is not all that great, because these routines aren't very heavily used.) + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case, define if we can */ +#ifdef USE_FMEM +#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#endif +#endif + + +GLOBAL(void) +jcopy_sample_rows (JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) +/* Copy some rows of samples from one place to another. + * num_rows rows are copied from input_array[source_row++] + * to output_array[dest_row++]; these areas may overlap for duplication. + * The source and destination arrays must be at least as wide as num_cols. + */ +{ + register JSAMPROW inptr, outptr; +#ifdef FMEMCOPY + register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); +#else + register JDIMENSION count; +#endif + register int row; + + input_array += source_row; + output_array += dest_row; + + for (row = num_rows; row > 0; row--) { + inptr = *input_array++; + outptr = *output_array++; +#ifdef FMEMCOPY + FMEMCOPY(outptr, inptr, count); +#else + for (count = num_cols; count > 0; count--) + *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ +#endif + } +} + + +GLOBAL(void) +jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, + JDIMENSION num_blocks) +/* Copy a row of coefficient blocks from one place to another. */ +{ +#ifdef FMEMCOPY + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +#else + register JCOEFPTR inptr, outptr; + register long count; + + inptr = (JCOEFPTR) input_row; + outptr = (JCOEFPTR) output_row; + for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { + *outptr++ = *inptr++; + } +#endif +} + + +GLOBAL(void) +jzero_far (void FAR * target, size_t bytestozero) +/* Zero out a chunk of FAR memory. */ +/* This might be sample-array data, block-array data, or alloc_large data. */ +{ +#ifdef FMEMZERO + FMEMZERO(target, bytestozero); +#else + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +#endif +} diff --git a/Utilities/vtkjpeg/jversion.h b/Utilities/vtkjpeg/jversion.h new file mode 100644 index 0000000..3bb37d8 --- /dev/null +++ b/Utilities/vtkjpeg/jversion.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains software version identification. + */ + + +#define JVERSION "6b 27-Mar-1998" + +#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" diff --git a/Utilities/vtkjpeg/libjpeg.doc b/Utilities/vtkjpeg/libjpeg.doc new file mode 100644 index 0000000..f741051 --- /dev/null +++ b/Utilities/vtkjpeg/libjpeg.doc @@ -0,0 +1,3006 @@ +USING THE IJG JPEG LIBRARY + +Copyright (C) 1994-1998, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file describes how to use the IJG JPEG library within an application +program. Read it if you want to write a program that uses the library. + +The file example.c provides heavily commented skeleton code for calling the +JPEG library. Also see jpeglib.h (the include file to be used by application +programs) for full details about data structures and function parameter lists. +The library source code, of course, is the ultimate reference. + +Note that there have been *major* changes from the application interface +presented by IJG version 4 and earlier versions. The old design had several +inherent limitations, and it had accumulated a lot of cruft as we added +features while trying to minimize application-interface changes. We have +sacrificed backward compatibility in the version 5 rewrite, but we think the +improvements justify this. + + +TABLE OF CONTENTS +----------------- + +Overview: + Functions provided by the library + Outline of typical usage +Basic library usage: + Data formats + Compression details + Decompression details + Mechanics of usage: include files, linking, etc +Advanced features: + Compression parameter selection + Decompression parameter selection + Special color spaces + Error handling + Compressed data handling (source and destination managers) + I/O suspension + Progressive JPEG support + Buffered-image mode + Abbreviated datastreams and multiple images + Special markers + Raw (downsampled) image data + Really raw data: DCT coefficients + Progress monitoring + Memory management + Memory usage + Library compile-time options + Portability considerations + Notes for MS-DOS implementors + +You should read at least the overview and basic usage sections before trying +to program with the library. The sections on advanced features can be read +if and when you need them. + + +OVERVIEW +======== + +Functions provided by the library +--------------------------------- + +The IJG JPEG library provides C code to read and write JPEG-compressed image +files. The surrounding application program receives or supplies image data a +scanline at a time, using a straightforward uncompressed image format. All +details of color conversion and other preprocessing/postprocessing can be +handled by the library. + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. The application indirectly selects use of this code +by specifying the format in which it wishes to supply or receive image data. +For example, if colormapped output is requested, then the decompression +library automatically invokes color quantization. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + +A word about functions *not* provided by the library. We handle a subset of +the ISO JPEG standard; most baseline, extended-sequential, and progressive +JPEG processes are supported. (Our subset includes all features now in common +use.) Unsupported ISO options include: + * Hierarchical storage + * Lossless JPEG + * Arithmetic entropy coding (unsupported for legal reasons) + * DNL marker + * Nonintegral subsampling ratios +We support both 8- and 12-bit data precision, but this is a compile-time +choice rather than a run-time choice; hence it is difficult to use both +precisions in a single application. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, this library is +used by the free LIBTIFF library to support JPEG compression in TIFF.) + + +Outline of typical usage +------------------------ + +The rough outline of a JPEG compression operation is: + + Allocate and initialize a JPEG compression object + Specify the destination for the compressed data (eg, a file) + Set parameters for compression, including image size & colorspace + jpeg_start_compress(...); + while (scan lines remain to be written) + jpeg_write_scanlines(...); + jpeg_finish_compress(...); + Release the JPEG compression object + +A JPEG compression object holds parameters and working state for the JPEG +library. We make creation/destruction of the object separate from starting +or finishing compression of an image; the same object can be re-used for a +series of image compression operations. This makes it easy to re-use the +same parameter settings for a sequence of images. Re-use of a JPEG object +also has important implications for processing abbreviated JPEG datastreams, +as discussed later. + +The image data to be compressed is supplied to jpeg_write_scanlines() from +in-memory buffers. If the application is doing file-to-file compression, +reading image data from the source file is the application's responsibility. +The library emits compressed data by calling a "data destination manager", +which typically will write the data into a file; but the application can +provide its own destination manager to do something else. + +Similarly, the rough outline of a JPEG decompression operation is: + + Allocate and initialize a JPEG decompression object + Specify the source of the compressed data (eg, a file) + Call jpeg_read_header() to obtain image info + Set parameters for decompression + jpeg_start_decompress(...); + while (scan lines remain to be read) + jpeg_read_scanlines(...); + jpeg_finish_decompress(...); + Release the JPEG decompression object + +This is comparable to the compression outline except that reading the +datastream header is a separate step. This is helpful because information +about the image's size, colorspace, etc is available when the application +selects decompression parameters. For example, the application can choose an +output scaling ratio that will fit the image into the available screen size. + +The decompression library obtains compressed data by calling a data source +manager, which typically will read the data from a file; but other behaviors +can be obtained with a custom source manager. Decompressed data is delivered +into in-memory buffers passed to jpeg_read_scanlines(). + +It is possible to abort an incomplete compression or decompression operation +by calling jpeg_abort(); or, if you do not need to retain the JPEG object, +simply release it by calling jpeg_destroy(). + +JPEG compression and decompression objects are two separate struct types. +However, they share some common fields, and certain routines such as +jpeg_destroy() can work on either type of object. + +The JPEG library has no static variables: all state is in the compression +or decompression object. Therefore it is possible to process multiple +compression and decompression operations concurrently, using multiple JPEG +objects. + +Both compression and decompression can be done in an incremental memory-to- +memory fashion, if suitable source/destination managers are used. See the +section on "I/O suspension" for more details. + + +BASIC LIBRARY USAGE +=================== + +Data formats +------------ + +Before diving into procedural details, it is helpful to understand the +image data format that the JPEG library expects or returns. + +The standard input image format is a rectangular array of pixels, with each +pixel having the same number of "component" or "sample" values (color +channels). You must specify how many components there are and the colorspace +interpretation of the components. Most applications will use RGB data +(three components per pixel) or grayscale data (one component per pixel). +PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE. +A remarkable number of people manage to miss this, only to find that their +programs don't work with grayscale JPEG files. + +There is no provision for colormapped input. JPEG files are always full-color +or full grayscale (or sometimes another colorspace such as CMYK). You can +feed in a colormapped image by expanding it to full-color format. However +JPEG often doesn't work very well with source data that has been colormapped, +because of dithering noise. This is discussed in more detail in the JPEG FAQ +and the other references mentioned in the README file. + +Pixels are stored by scanlines, with each scanline running from left to +right. The component values for each pixel are adjacent in the row; for +example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an +array of data type JSAMPLE --- which is typically "unsigned char", unless +you've changed jmorecfg.h. (You can also change the RGB pixel layout, say +to B,G,R order, by modifying jmorecfg.h. But see the restrictions listed in +that file before doing so.) + +A 2-D array of pixels is formed by making a list of pointers to the starts of +scanlines; so the scanlines need not be physically adjacent in memory. Even +if you process just one scanline at a time, you must make a one-element +pointer array to conform to this structure. Pointers to JSAMPLE rows are of +type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY. + +The library accepts or supplies one or more complete scanlines per call. +It is not possible to process part of a row at a time. Scanlines are always +processed top-to-bottom. You can process an entire image in one call if you +have it all in memory, but usually it's simplest to process one scanline at +a time. + +For best results, source data values should have the precision specified by +BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress +data that's only 6 bits/channel, you should left-justify each value in a +byte before passing it to the compressor. If you need to compress data +that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12. +(See "Library compile-time options", later.) + + +The data format returned by the decompressor is the same in all details, +except that colormapped output is supported. (Again, a JPEG file is never +colormapped. But you can ask the decompressor to perform on-the-fly color +quantization to deliver colormapped output.) If you request colormapped +output then the returned data array contains a single JSAMPLE per pixel; +its value is an index into a color map. The color map is represented as +a 2-D JSAMPARRAY in which each row holds the values of one color component, +that is, colormap[i][j] is the value of the i'th color component for pixel +value (map index) j. Note that since the colormap indexes are stored in +JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE +(ie, at most 256 colors for an 8-bit JPEG library). + + +Compression details +------------------- + +Here we revisit the JPEG compression outline given in the overview. + +1. Allocate and initialize a JPEG compression object. + +A JPEG compression object is a "struct jpeg_compress_struct". (It also has +a bunch of subsidiary structures which are allocated via malloc(), but the +application doesn't control those directly.) This struct can be just a local +variable in the calling routine, if a single routine is going to execute the +whole JPEG compression sequence. Otherwise it can be static or allocated +from malloc(). + +You will also need a structure representing a JPEG error handler. The part +of this that the library cares about is a "struct jpeg_error_mgr". If you +are providing your own error handler, you'll typically want to embed the +jpeg_error_mgr struct in a larger structure; this is discussed later under +"Error handling". For now we'll assume you are just using the default error +handler. The default error handler will print JPEG error/warning messages +on stderr, and it will call exit() if a fatal error occurs. + +You must initialize the error handler structure, store a pointer to it into +the JPEG object's "err" field, and then call jpeg_create_compress() to +initialize the rest of the JPEG object. + +Typical code for this step, if you are using the default error handler, is + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + +jpeg_create_compress allocates a small amount of memory, so it could fail +if you are out of memory. In that case it will exit via the error handler; +that's why the error handler must be initialized first. + + +2. Specify the destination for the compressed data (eg, a file). + +As previously mentioned, the JPEG library delivers compressed data to a +"data destination" module. The library includes one data destination +module which knows how to write to a stdio stream. You can use your own +destination module if you want to do something else, as discussed later. + +If you use the standard destination module, you must open the target stdio +stream beforehand. Typical code for this step looks like: + + FILE * outfile; + ... + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + +where the last line invokes the standard destination module. + +WARNING: it is critical that the binary compressed data be delivered to the +output file unchanged. On non-Unix systems the stdio library may perform +newline translation or otherwise corrupt binary data. To suppress this +behavior, you may need to use a "b" option to fopen (as shown above), or use +setmode() or another routine to put the stdio stream in binary mode. See +cjpeg.c and djpeg.c for code that has been found to work on many systems. + +You can select the data destination after setting other parameters (step 3), +if that's more convenient. You may not change the destination between +calling jpeg_start_compress() and jpeg_finish_compress(). + + +3. Set parameters for compression, including image size & colorspace. + +You must supply information about the source image by setting the following +fields in the JPEG object (cinfo structure): + + image_width Width of image, in pixels + image_height Height of image, in pixels + input_components Number of color channels (samples per pixel) + in_color_space Color space of source image + +The image dimensions are, hopefully, obvious. JPEG supports image dimensions +of 1 to 64K pixels in either direction. The input color space is typically +RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special +color spaces", later, for more info.) The in_color_space field must be +assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or +JCS_GRAYSCALE. + +JPEG has a large number of compression parameters that determine how the +image is encoded. Most applications don't need or want to know about all +these parameters. You can set all the parameters to reasonable defaults by +calling jpeg_set_defaults(); then, if there are particular values you want +to change, you can do so after that. The "Compression parameter selection" +section tells about all the parameters. + +You must set in_color_space correctly before calling jpeg_set_defaults(), +because the defaults depend on the source image colorspace. However the +other three source image parameters need not be valid until you call +jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more +than once, if that happens to be convenient. + +Typical code for a 24-bit RGB source image is + + cinfo.image_width = Width; /* image width and height, in pixels */ + cinfo.image_height = Height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + + jpeg_set_defaults(&cinfo); + /* Make optional parameter settings here */ + + +4. jpeg_start_compress(...); + +After you have established the data destination and set all the necessary +source image info and other parameters, call jpeg_start_compress() to begin +a compression cycle. This will initialize internal state, allocate working +storage, and emit the first few bytes of the JPEG datastream header. + +Typical code: + + jpeg_start_compress(&cinfo, TRUE); + +The "TRUE" parameter ensures that a complete JPEG interchange datastream +will be written. This is appropriate in most cases. If you think you might +want to use an abbreviated datastream, read the section on abbreviated +datastreams, below. + +Once you have called jpeg_start_compress(), you may not alter any JPEG +parameters or other fields of the JPEG object until you have completed +the compression cycle. + + +5. while (scan lines remain to be written) + jpeg_write_scanlines(...); + +Now write all the required image data by calling jpeg_write_scanlines() +one or more times. You can pass one or more scanlines in each call, up +to the total image height. In most applications it is convenient to pass +just one or a few scanlines at a time. The expected format for the passed +data is discussed under "Data formats", above. + +Image data should be written in top-to-bottom scanline order. The JPEG spec +contains some weasel wording about how top and bottom are application-defined +terms (a curious interpretation of the English language...) but if you want +your files to be compatible with everyone else's, you WILL use top-to-bottom +order. If the source data must be read in bottom-to-top order, you can use +the JPEG library's virtual array mechanism to invert the data efficiently. +Examples of this can be found in the sample application cjpeg. + +The library maintains a count of the number of scanlines written so far +in the next_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.next_scanline < cinfo.image_height)". + +Code for this step depends heavily on the way that you store the source data. +example.c shows the following code for the case of a full-size 2-D source +array containing 3-byte RGB pixels: + + JSAMPROW row_pointer[1]; /* pointer to a single row */ + int row_stride; /* physical row width in buffer */ + + row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + +jpeg_write_scanlines() returns the number of scanlines actually written. +This will normally be equal to the number passed in, so you can usually +ignore the return value. It is different in just two cases: + * If you try to write more scanlines than the declared image height, + the additional scanlines are ignored. + * If you use a suspending data destination manager, output buffer overrun + will cause the compressor to return before accepting all the passed lines. + This feature is discussed under "I/O suspension", below. The normal + stdio destination manager will NOT cause this to happen. +In any case, the return value is the same as the change in the value of +next_scanline. + + +6. jpeg_finish_compress(...); + +After all the image data has been written, call jpeg_finish_compress() to +complete the compression cycle. This step is ESSENTIAL to ensure that the +last bufferload of data is written to the data destination. +jpeg_finish_compress() also releases working memory associated with the JPEG +object. + +Typical code: + + jpeg_finish_compress(&cinfo); + +If using the stdio destination manager, don't forget to close the output +stdio stream (if necessary) afterwards. + +If you have requested a multi-pass operating mode, such as Huffman code +optimization, jpeg_finish_compress() will perform the additional passes using +data buffered by the first pass. In this case jpeg_finish_compress() may take +quite a while to complete. With the default compression parameters, this will +not happen. + +It is an error to call jpeg_finish_compress() before writing the necessary +total number of scanlines. If you wish to abort compression, call +jpeg_abort() as discussed below. + +After completing a compression cycle, you may dispose of the JPEG object +as discussed next, or you may use it to compress another image. In that case +return to step 2, 3, or 4 as appropriate. If you do not change the +destination manager, the new datastream will be written to the same target. +If you do not change any JPEG parameters, the new datastream will be written +with the same parameters as before. Note that you can change the input image +dimensions freely between cycles, but if you change the input colorspace, you +should call jpeg_set_defaults() to adjust for the new colorspace; and then +you'll need to repeat all of step 3. + + +7. Release the JPEG compression object. + +When you are done with a JPEG compression object, destroy it by calling +jpeg_destroy_compress(). This will free all subsidiary memory (regardless of +the previous state of the object). Or you can call jpeg_destroy(), which +works for either compression or decompression objects --- this may be more +convenient if you are sharing code between compression and decompression +cases. (Actually, these routines are equivalent except for the declared type +of the passed pointer. To avoid gripes from ANSI C compilers, jpeg_destroy() +should be passed a j_common_ptr.) + +If you allocated the jpeg_compress_struct structure from malloc(), freeing +it is your responsibility --- jpeg_destroy() won't. Ditto for the error +handler structure. + +Typical code: + + jpeg_destroy_compress(&cinfo); + + +8. Aborting. + +If you decide to abort a compression cycle before finishing, you can clean up +in either of two ways: + +* If you don't need the JPEG object any more, just call + jpeg_destroy_compress() or jpeg_destroy() to release memory. This is + legitimate at any point after calling jpeg_create_compress() --- in fact, + it's safe even if jpeg_create_compress() fails. + +* If you want to re-use the JPEG object, call jpeg_abort_compress(), or call + jpeg_abort() which works on both compression and decompression objects. + This will return the object to an idle state, releasing any working memory. + jpeg_abort() is allowed at any time after successful object creation. + +Note that cleaning up the data destination, if required, is your +responsibility; neither of these routines will call term_destination(). +(See "Compressed data handling", below, for more about that.) + +jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG +object that has reported an error by calling error_exit (see "Error handling" +for more info). The internal state of such an object is likely to be out of +whack. Either of these two routines will return the object to a known state. + + +Decompression details +--------------------- + +Here we revisit the JPEG decompression outline given in the overview. + +1. Allocate and initialize a JPEG decompression object. + +This is just like initialization for compression, as discussed above, +except that the object is a "struct jpeg_decompress_struct" and you +call jpeg_create_decompress(). Error handling is exactly the same. + +Typical code: + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + ... + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + +(Both here and in the IJG code, we usually use variable name "cinfo" for +both compression and decompression objects.) + + +2. Specify the source of the compressed data (eg, a file). + +As previously mentioned, the JPEG library reads compressed data from a "data +source" module. The library includes one data source module which knows how +to read from a stdio stream. You can use your own source module if you want +to do something else, as discussed later. + +If you use the standard source module, you must open the source stdio stream +beforehand. Typical code for this step looks like: + + FILE * infile; + ... + if ((infile = fopen(filename, "rb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_src(&cinfo, infile); + +where the last line invokes the standard source module. + +WARNING: it is critical that the binary compressed data be read unchanged. +On non-Unix systems the stdio library may perform newline translation or +otherwise corrupt binary data. To suppress this behavior, you may need to use +a "b" option to fopen (as shown above), or use setmode() or another routine to +put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that +has been found to work on many systems. + +You may not change the data source between calling jpeg_read_header() and +jpeg_finish_decompress(). If you wish to read a series of JPEG images from +a single source file, you should repeat the jpeg_read_header() to +jpeg_finish_decompress() sequence without reinitializing either the JPEG +object or the data source module; this prevents buffered input data from +being discarded. + + +3. Call jpeg_read_header() to obtain image info. + +Typical code for this step is just + + jpeg_read_header(&cinfo, TRUE); + +This will read the source datastream header markers, up to the beginning +of the compressed data proper. On return, the image dimensions and other +info have been stored in the JPEG object. The application may wish to +consult this information before selecting decompression parameters. + +More complex code is necessary if + * A suspending data source is used --- in that case jpeg_read_header() + may return before it has read all the header data. See "I/O suspension", + below. The normal stdio source manager will NOT cause this to happen. + * Abbreviated JPEG files are to be processed --- see the section on + abbreviated datastreams. Standard applications that deal only in + interchange JPEG files need not be concerned with this case either. + +It is permissible to stop at this point if you just wanted to find out the +image dimensions and other header info for a JPEG file. In that case, +call jpeg_destroy() when you are done with the JPEG object, or call +jpeg_abort() to return it to an idle state before selecting a new data +source and reading another header. + + +4. Set parameters for decompression. + +jpeg_read_header() sets appropriate default decompression parameters based on +the properties of the image (in particular, its colorspace). However, you +may well want to alter these defaults before beginning the decompression. +For example, the default is to produce full color output from a color file. +If you want colormapped output you must ask for it. Other options allow the +returned image to be scaled and allow various speed/quality tradeoffs to be +selected. "Decompression parameter selection", below, gives details. + +If the defaults are appropriate, nothing need be done at this step. + +Note that all default values are set by each call to jpeg_read_header(). +If you reuse a decompression object, you cannot expect your parameter +settings to be preserved across cycles, as you can for compression. +You must set desired parameter values each time. + + +5. jpeg_start_decompress(...); + +Once the parameter values are satisfactory, call jpeg_start_decompress() to +begin decompression. This will initialize internal state, allocate working +memory, and prepare for returning data. + +Typical code is just + + jpeg_start_decompress(&cinfo); + +If you have requested a multi-pass operating mode, such as 2-pass color +quantization, jpeg_start_decompress() will do everything needed before data +output can begin. In this case jpeg_start_decompress() may take quite a while +to complete. With a single-scan (non progressive) JPEG file and default +decompression parameters, this will not happen; jpeg_start_decompress() will +return quickly. + +After this call, the final output image dimensions, including any requested +scaling, are available in the JPEG object; so is the selected colormap, if +colormapped output has been requested. Useful fields include + + output_width image width and height, as scaled + output_height + out_color_components # of color components in out_color_space + output_components # of color components returned per pixel + colormap the selected colormap, if any + actual_number_of_colors number of entries in colormap + +output_components is 1 (a colormap index) when quantizing colors; otherwise it +equals out_color_components. It is the number of JSAMPLE values that will be +emitted per pixel in the output arrays. + +Typically you will need to allocate data buffers to hold the incoming image. +You will need output_width * output_components JSAMPLEs per scanline in your +output buffer, and a total of output_height scanlines will be returned. + +Note: if you are using the JPEG library's internal memory manager to allocate +data buffers (as djpeg does), then the manager's protocol requires that you +request large buffers *before* calling jpeg_start_decompress(). This is a +little tricky since the output_XXX fields are not normally valid then. You +can make them valid by calling jpeg_calc_output_dimensions() after setting the +relevant parameters (scaling, output color space, and quantization flag). + + +6. while (scan lines remain to be read) + jpeg_read_scanlines(...); + +Now you can read the decompressed image data by calling jpeg_read_scanlines() +one or more times. At each call, you pass in the maximum number of scanlines +to be read (ie, the height of your working buffer); jpeg_read_scanlines() +will return up to that many lines. The return value is the number of lines +actually read. The format of the returned data is discussed under "Data +formats", above. Don't forget that grayscale and color JPEGs will return +different data formats! + +Image data is returned in top-to-bottom scanline order. If you must write +out the image in bottom-to-top order, you can use the JPEG library's virtual +array mechanism to invert the data efficiently. Examples of this can be +found in the sample application djpeg. + +The library maintains a count of the number of scanlines returned so far +in the output_scanline field of the JPEG object. Usually you can just use +this variable as the loop counter, so that the loop test looks like +"while (cinfo.output_scanline < cinfo.output_height)". (Note that the test +should NOT be against image_height, unless you never use scaling. The +image_height field is the height of the original unscaled image.) +The return value always equals the change in the value of output_scanline. + +If you don't use a suspending data source, it is safe to assume that +jpeg_read_scanlines() reads at least one scanline per call, until the +bottom of the image has been reached. + +If you use a buffer larger than one scanline, it is NOT safe to assume that +jpeg_read_scanlines() fills it. (The current implementation returns only a +few scanlines per call, no matter how large a buffer you pass.) So you must +always provide a loop that calls jpeg_read_scanlines() repeatedly until the +whole image has been read. + + +7. jpeg_finish_decompress(...); + +After all the image data has been read, call jpeg_finish_decompress() to +complete the decompression cycle. This causes working memory associated +with the JPEG object to be released. + +Typical code: + + jpeg_finish_decompress(&cinfo); + +If using the stdio source manager, don't forget to close the source stdio +stream if necessary. + +It is an error to call jpeg_finish_decompress() before reading the correct +total number of scanlines. If you wish to abort decompression, call +jpeg_abort() as discussed below. + +After completing a decompression cycle, you may dispose of the JPEG object as +discussed next, or you may use it to decompress another image. In that case +return to step 2 or 3 as appropriate. If you do not change the source +manager, the next image will be read from the same source. + + +8. Release the JPEG decompression object. + +When you are done with a JPEG decompression object, destroy it by calling +jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of +destroying compression objects applies here too. + +Typical code: + + jpeg_destroy_decompress(&cinfo); + + +9. Aborting. + +You can abort a decompression cycle by calling jpeg_destroy_decompress() or +jpeg_destroy() if you don't need the JPEG object any more, or +jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object. +The previous discussion of aborting compression cycles applies here too. + + +Mechanics of usage: include files, linking, etc +----------------------------------------------- + +Applications using the JPEG library should include the header file jpeglib.h +to obtain declarations of data types and routines. Before including +jpeglib.h, include system headers that define at least the typedefs FILE and +size_t. On ANSI-conforming systems, including <stdio.h> is sufficient; on +older Unix systems, you may need <sys/types.h> to define size_t. + +If the application needs to refer to individual JPEG library error codes, also +include jerror.h to define those symbols. + +jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are +installing the JPEG header files in a system directory, you will want to +install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h. + +The most convenient way to include the JPEG code into your executable program +is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix +machines) and reference it at your link step. If you use only half of the +library (only compression or only decompression), only that much code will be +included from the library, unless your linker is hopelessly brain-damaged. +The supplied makefiles build libjpeg.a automatically (see install.doc). + +While you can build the JPEG library as a shared library if the whim strikes +you, we don't really recommend it. The trouble with shared libraries is that +at some point you'll probably try to substitute a new version of the library +without recompiling the calling applications. That generally doesn't work +because the parameter struct declarations usually change with each new +version. In other words, the library's API is *not* guaranteed binary +compatible across versions; we only try to ensure source-code compatibility. +(In hindsight, it might have been smarter to hide the parameter structs from +applications and introduce a ton of access functions instead. Too late now, +however.) + +On some systems your application may need to set up a signal handler to ensure +that temporary files are deleted if the program is interrupted. This is most +critical if you are on MS-DOS and use the jmemdos.c memory manager back end; +it will try to grab extended memory for temp files, and that space will NOT be +freed automatically. See cjpeg.c or djpeg.c for an example signal handler. + +It may be worth pointing out that the core JPEG library does not actually +require the stdio library: only the default source/destination managers and +error handler need it. You can use the library in a stdio-less environment +if you replace those modules and use jmemnobs.c (or another memory manager of +your own devising). More info about the minimum system library requirements +may be found in jinclude.h. + + +ADVANCED FEATURES +================= + +Compression parameter selection +------------------------------- + +This section describes all the optional parameters you can set for JPEG +compression, as well as the "helper" routines provided to assist in this +task. Proper setting of some parameters requires detailed understanding +of the JPEG standard; if you don't know what a parameter is for, it's best +not to mess with it! See REFERENCES in the README file for pointers to +more info about JPEG. + +It's a good idea to call jpeg_set_defaults() first, even if you plan to set +all the parameters; that way your code is more likely to work with future JPEG +libraries that have additional parameters. For the same reason, we recommend +you use a helper routine where one is provided, in preference to twiddling +cinfo fields directly. + +The helper routines are: + +jpeg_set_defaults (j_compress_ptr cinfo) + This routine sets all JPEG parameters to reasonable defaults, using + only the input image's color space (field in_color_space, which must + already be set in cinfo). Many applications will only need to use + this routine and perhaps jpeg_set_quality(). + +jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) + Sets the JPEG file's colorspace (field jpeg_color_space) as specified, + and sets other color-space-dependent parameters appropriately. See + "Special color spaces", below, before using this. A large number of + parameters, including all per-component parameters, are set by this + routine; if you want to twiddle individual parameters you should call + jpeg_set_colorspace() before rather than after. + +jpeg_default_colorspace (j_compress_ptr cinfo) + Selects an appropriate JPEG colorspace based on cinfo->in_color_space, + and calls jpeg_set_colorspace(). This is actually a subroutine of + jpeg_set_defaults(). It's broken out in case you want to change + just the colorspace-dependent JPEG parameters. + +jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) + Constructs JPEG quantization tables appropriate for the indicated + quality setting. The quality value is expressed on the 0..100 scale + recommended by IJG (cjpeg's "-quality" switch uses this routine). + Note that the exact mapping from quality values to tables may change + in future IJG releases as more is learned about DCT quantization. + If the force_baseline parameter is TRUE, then the quantization table + entries are constrained to the range 1..255 for full JPEG baseline + compatibility. In the current implementation, this only makes a + difference for quality settings below 25, and it effectively prevents + very small/low quality files from being generated. The IJG decoder + is capable of reading the non-baseline files generated at low quality + settings when force_baseline is FALSE, but other decoders may not be. + +jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, + boolean force_baseline) + Same as jpeg_set_quality() except that the generated tables are the + sample tables given in the JPEC spec section K.1, multiplied by the + specified scale factor (which is expressed as a percentage; thus + scale_factor = 100 reproduces the spec's tables). Note that larger + scale factors give lower quality. This entry point is useful for + conforming to the Adobe PostScript DCT conventions, but we do not + recommend linear scaling as a user-visible quality scale otherwise. + force_baseline again constrains the computed table entries to 1..255. + +int jpeg_quality_scaling (int quality) + Converts a value on the IJG-recommended quality scale to a linear + scaling percentage. Note that this routine may change or go away + in future releases --- IJG may choose to adopt a scaling method that + can't be expressed as a simple scalar multiplier, in which case the + premise of this routine collapses. Caveat user. + +jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) + Allows an arbitrary quantization table to be created. which_tbl + indicates which table slot to fill. basic_table points to an array + of 64 unsigned ints given in normal array order. These values are + multiplied by scale_factor/100 and then clamped to the range 1..65535 + (or to 1..255 if force_baseline is TRUE). + CAUTION: prior to library version 6a, jpeg_add_quant_table expected + the basic table to be given in JPEG zigzag order. If you need to + write code that works with either older or newer versions of this + routine, you must check the library version number. Something like + "#if JPEG_LIB_VERSION >= 61" is the right test. + +jpeg_simple_progression (j_compress_ptr cinfo) + Generates a default scan script for writing a progressive-JPEG file. + This is the recommended method of creating a progressive file, + unless you want to make a custom scan sequence. You must ensure that + the JPEG color space is set correctly before calling this routine. + + +Compression parameters (cinfo fields) include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are: + JDCT_ISLOW: slow but accurate integer algorithm + JDCT_IFAST: faster, less accurate integer method + JDCT_FLOAT: floating-point method + JDCT_DEFAULT: default method (normally JDCT_ISLOW) + JDCT_FASTEST: fastest method (normally JDCT_IFAST) + The FLOAT method is very slightly more accurate than the ISLOW method, + but may give different results on different machines due to varying + roundoff behavior. The integer methods should give the same results + on all machines. On machines with sufficiently fast FP hardware, the + floating-point method may also be the fastest. The IFAST method is + considerably less accurate than the other two; its use is not + recommended if high quality is a concern. JDCT_DEFAULT and + JDCT_FASTEST are macros configurable by each installation. + +J_COLOR_SPACE jpeg_color_space +int num_components + The JPEG color space and corresponding number of components; see + "Special color spaces", below, for more info. We recommend using + jpeg_set_color_space() if you want to change these. + +boolean optimize_coding + TRUE causes the compressor to compute optimal Huffman coding tables + for the image. This requires an extra pass over the data and + therefore costs a good deal of space and time. The default is + FALSE, which tells the compressor to use the supplied or default + Huffman tables. In most cases optimal tables save only a few percent + of file size compared to the default tables. Note that when this is + TRUE, you need not supply Huffman tables at all, and any you do + supply will be overwritten. + +unsigned int restart_interval +int restart_in_rows + To emit restart markers in the JPEG file, set one of these nonzero. + Set restart_interval to specify the exact interval in MCU blocks. + Set restart_in_rows to specify the interval in MCU rows. (If + restart_in_rows is not 0, then restart_interval is set after the + image width in MCUs is computed.) Defaults are zero (no restarts). + One restart marker per MCU row is often a good choice. + NOTE: the overhead of restart markers is higher in grayscale JPEG + files than in color files, and MUCH higher in progressive JPEGs. + If you use restarts, you may want to use larger intervals in those + cases. + +const jpeg_scan_info * scan_info +int num_scans + By default, scan_info is NULL; this causes the compressor to write a + single-scan sequential JPEG file. If not NULL, scan_info points to + an array of scan definition records of length num_scans. The + compressor will then write a JPEG file having one scan for each scan + definition record. This is used to generate noninterleaved or + progressive JPEG files. The library checks that the scan array + defines a valid JPEG scan sequence. (jpeg_simple_progression creates + a suitable scan definition array for progressive JPEG.) This is + discussed further under "Progressive JPEG support". + +int smoothing_factor + If non-zero, the input image is smoothed; the value should be 1 for + minimal smoothing to 100 for maximum smoothing. Consult jcsample.c + for details of the smoothing algorithm. The default is zero. + +boolean write_JFIF_header + If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space + (ie, YCbCr or grayscale) is selected, otherwise FALSE. + +UINT8 JFIF_major_version +UINT8 JFIF_minor_version + The version number to be written into the JFIF marker. + jpeg_set_defaults() initializes the version to 1.01 (major=minor=1). + You should set it to 1.02 (major=1, minor=2) if you plan to write + any JFIF 1.02 extension markers. + +UINT8 density_unit +UINT16 X_density +UINT16 Y_density + The resolution information to be written into the JFIF marker; + not used otherwise. density_unit may be 0 for unknown, + 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 + indicating square pixels of unknown size. + +boolean write_Adobe_marker + If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and + jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK, + or YCCK is selected, otherwise FALSE. It is generally a bad idea + to set both write_JFIF_header and write_Adobe_marker. In fact, + you probably shouldn't change the default settings at all --- the + default behavior ensures that the JPEG file's color space can be + recognized by the decoder. + +JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS] + Pointers to coefficient quantization tables, one per table slot, + or NULL if no table is defined for a slot. Usually these should + be set via one of the above helper routines; jpeg_add_quant_table() + is general enough to define any quantization table. The other + routines will set up table slot 0 for luminance quality and table + slot 1 for chrominance. + +JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS] +JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS] + Pointers to Huffman coding tables, one per table slot, or NULL if + no table is defined for a slot. Slots 0 and 1 are filled with the + JPEG sample tables by jpeg_set_defaults(). If you need to allocate + more table structures, jpeg_alloc_huff_table() may be used. + Note that optimal Huffman tables can be computed for an image + by setting optimize_coding, as discussed above; there's seldom + any need to mess with providing your own Huffman tables. + +There are some additional cinfo fields which are not documented here +because you currently can't change them; for example, you can't set +arith_code TRUE because arithmetic coding is unsupported. + + +Per-component parameters are stored in the struct cinfo.comp_info[i] for +component number i. Note that components here refer to components of the +JPEG color space, *not* the source image color space. A suitably large +comp_info[] array is allocated by jpeg_set_defaults(); if you choose not +to use that routine, it's up to you to allocate the array. + +int component_id + The one-byte identifier code to be recorded in the JPEG file for + this component. For the standard color spaces, we recommend you + leave the default values alone. + +int h_samp_factor +int v_samp_factor + Horizontal and vertical sampling factors for the component; must + be 1..4 according to the JPEG standard. Note that larger sampling + factors indicate a higher-resolution component; many people find + this behavior quite unintuitive. The default values are 2,2 for + luminance components and 1,1 for chrominance components, except + for grayscale where 1,1 is used. + +int quant_tbl_no + Quantization table number for component. The default value is + 0 for luminance components and 1 for chrominance components. + +int dc_tbl_no +int ac_tbl_no + DC and AC entropy coding table numbers. The default values are + 0 for luminance components and 1 for chrominance components. + +int component_index + Must equal the component's index in comp_info[]. (Beginning in + release v6, the compressor library will fill this in automatically; + you don't have to.) + + +Decompression parameter selection +--------------------------------- + +Decompression parameter selection is somewhat simpler than compression +parameter selection, since all of the JPEG internal parameters are +recorded in the source file and need not be supplied by the application. +(Unless you are working with abbreviated files, in which case see +"Abbreviated datastreams", below.) Decompression parameters control +the postprocessing done on the image to deliver it in a format suitable +for the application's use. Many of the parameters control speed/quality +tradeoffs, in which faster decompression may be obtained at the price of +a poorer-quality image. The defaults select the highest quality (slowest) +processing. + +The following fields in the JPEG object are set by jpeg_read_header() and +may be useful to the application in choosing decompression parameters: + +JDIMENSION image_width Width and height of image +JDIMENSION image_height +int num_components Number of color components +J_COLOR_SPACE jpeg_color_space Colorspace of image +boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen + UINT8 JFIF_major_version Version information from JFIF marker + UINT8 JFIF_minor_version + UINT8 density_unit Resolution data from JFIF marker + UINT16 X_density + UINT16 Y_density +boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen + UINT8 Adobe_transform Color transform code from Adobe marker + +The JPEG color space, unfortunately, is something of a guess since the JPEG +standard proper does not provide a way to record it. In practice most files +adhere to the JFIF or Adobe conventions, and the decoder will recognize these +correctly. See "Special color spaces", below, for more info. + + +The decompression parameters that determine the basic properties of the +returned image are: + +J_COLOR_SPACE out_color_space + Output color space. jpeg_read_header() sets an appropriate default + based on jpeg_color_space; typically it will be RGB or grayscale. + The application can change this field to request output in a different + colorspace. For example, set it to JCS_GRAYSCALE to get grayscale + output from a color file. (This is useful for previewing: grayscale + output is faster than full color since the color components need not + be processed.) Note that not all possible color space transforms are + currently implemented; you may need to extend jdcolor.c if you want an + unusual conversion. + +unsigned int scale_num, scale_denom + Scale the image by the fraction scale_num/scale_denom. Default is + 1/1, or no scaling. Currently, the only supported scaling ratios + are 1/1, 1/2, 1/4, and 1/8. (The library design allows for arbitrary + scaling ratios but this is not likely to be implemented any time soon.) + Smaller scaling ratios permit significantly faster decoding since + fewer pixels need be processed and a simpler IDCT method can be used. + +boolean quantize_colors + If set TRUE, colormapped output will be delivered. Default is FALSE, + meaning that full-color output will be delivered. + +The next three parameters are relevant only if quantize_colors is TRUE. + +int desired_number_of_colors + Maximum number of colors to use in generating a library-supplied color + map (the actual number of colors is returned in a different field). + Default 256. Ignored when the application supplies its own color map. + +boolean two_pass_quantize + If TRUE, an extra pass over the image is made to select a custom color + map for the image. This usually looks a lot better than the one-size- + fits-all colormap that is used otherwise. Default is TRUE. Ignored + when the application supplies its own color map. + +J_DITHER_MODE dither_mode + Selects color dithering method. Supported values are: + JDITHER_NONE no dithering: fast, very low quality + JDITHER_ORDERED ordered dither: moderate speed and quality + JDITHER_FS Floyd-Steinberg dither: slow, high quality + Default is JDITHER_FS. (At present, ordered dither is implemented + only in the single-pass, standard-colormap case. If you ask for + ordered dither when two_pass_quantize is TRUE or when you supply + an external color map, you'll get F-S dithering.) + +When quantize_colors is TRUE, the target color map is described by the next +two fields. colormap is set to NULL by jpeg_read_header(). The application +can supply a color map by setting colormap non-NULL and setting +actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress() +selects a suitable color map and sets these two fields itself. +[Implementation restriction: at present, an externally supplied colormap is +only accepted for 3-component output color spaces.] + +JSAMPARRAY colormap + The color map, represented as a 2-D pixel array of out_color_components + rows and actual_number_of_colors columns. Ignored if not quantizing. + CAUTION: if the JPEG library creates its own colormap, the storage + pointed to by this field is released by jpeg_finish_decompress(). + Copy the colormap somewhere else first, if you want to save it. + +int actual_number_of_colors + The number of colors in the color map. + +Additional decompression parameters that the application may set include: + +J_DCT_METHOD dct_method + Selects the algorithm used for the DCT step. Choices are the same + as described above for compression. + +boolean do_fancy_upsampling + If TRUE, do careful upsampling of chroma components. If FALSE, + a faster but sloppier method is used. Default is TRUE. The visual + impact of the sloppier method is often very small. + +boolean do_block_smoothing + If TRUE, interblock smoothing is applied in early stages of decoding + progressive JPEG files; if FALSE, not. Default is TRUE. Early + progression stages look "fuzzy" with smoothing, "blocky" without. + In any case, block smoothing ceases to be applied after the first few + AC coefficients are known to full accuracy, so it is relevant only + when using buffered-image mode for progressive images. + +boolean enable_1pass_quant +boolean enable_external_quant +boolean enable_2pass_quant + These are significant only in buffered-image mode, which is + described in its own section below. + + +The output image dimensions are given by the following fields. These are +computed from the source image dimensions and the decompression parameters +by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions() +to obtain the values that will result from the current parameter settings. +This can be useful if you are trying to pick a scaling ratio that will get +close to a desired target size. It's also important if you are using the +JPEG library's memory manager to allocate output buffer space, because you +are supposed to request such buffers *before* jpeg_start_decompress(). + +JDIMENSION output_width Actual dimensions of output image. +JDIMENSION output_height +int out_color_components Number of color components in out_color_space. +int output_components Number of color components returned. +int rec_outbuf_height Recommended height of scanline buffer. + +When quantizing colors, output_components is 1, indicating a single color map +index per pixel. Otherwise it equals out_color_components. The output arrays +are required to be output_width * output_components JSAMPLEs wide. + +rec_outbuf_height is the recommended minimum height (in scanlines) of the +buffer passed to jpeg_read_scanlines(). If the buffer is smaller, the +library will still work, but time will be wasted due to unnecessary data +copying. In high-quality modes, rec_outbuf_height is always 1, but some +faster, lower-quality modes set it to larger values (typically 2 to 4). +If you are going to ask for a high-speed processing mode, you may as well +go to the trouble of honoring rec_outbuf_height so as to avoid data copying. +(An output buffer larger than rec_outbuf_height lines is OK, but won't +provide any material speed improvement over that height.) + + +Special color spaces +-------------------- + +The JPEG standard itself is "color blind" and doesn't specify any particular +color space. It is customary to convert color data to a luminance/chrominance +color space before compressing, since this permits greater compression. The +existing de-facto JPEG file format standards specify YCbCr or grayscale data +(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special +applications such as multispectral images, other color spaces can be used, +but it must be understood that such files will be unportable. + +The JPEG library can handle the most common colorspace conversions (namely +RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown +color space, passing it through without conversion. If you deal extensively +with an unusual color space, you can easily extend the library to understand +additional color spaces and perform appropriate conversions. + +For compression, the source data's color space is specified by field +in_color_space. This is transformed to the JPEG file's color space given +by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color +space depending on in_color_space, but you can override this by calling +jpeg_set_colorspace(). Of course you must select a supported transformation. +jccolor.c currently supports the following transformations: + RGB => YCbCr + RGB => GRAYSCALE + YCbCr => GRAYSCALE + CMYK => YCCK +plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB, +YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN. + +The de-facto file format standards (JFIF and Adobe) specify APPn markers that +indicate the color space of the JPEG file. It is important to ensure that +these are written correctly, or omitted if the JPEG file's color space is not +one of the ones supported by the de-facto standards. jpeg_set_colorspace() +will set the compression parameters to include or omit the APPn markers +properly, so long as it is told the truth about the JPEG color space. +For example, if you are writing some random 3-component color space without +conversion, don't try to fake out the library by setting in_color_space and +jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an +APPn marker of your own devising to identify the colorspace --- see "Special +markers", below. + +When told that the color space is UNKNOWN, the library will default to using +luminance-quality compression parameters for all color components. You may +well want to change these parameters. See the source code for +jpeg_set_colorspace(), in jcparam.c, for details. + +For decompression, the JPEG file's color space is given in jpeg_color_space, +and this is transformed to the output color space out_color_space. +jpeg_read_header's setting of jpeg_color_space can be relied on if the file +conforms to JFIF or Adobe conventions, but otherwise it is no better than a +guess. If you know the JPEG file's color space for certain, you can override +jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also +selects a default output color space based on (its guess of) jpeg_color_space; +set out_color_space to override this. Again, you must select a supported +transformation. jdcolor.c currently supports + YCbCr => GRAYSCALE + YCbCr => RGB + GRAYSCALE => RGB + YCCK => CMYK +as well as the null transforms. (Since GRAYSCALE=>RGB is provided, an +application can force grayscale JPEGs to look like color JPEGs if it only +wants to handle one case.) + +The two-pass color quantizer, jquant2.c, is specialized to handle RGB data +(it weights distances appropriately for RGB colors). You'll need to modify +the code if you want to use it for non-RGB output color spaces. Note that +jquant2.c is used to map to an application-supplied colormap as well as for +the normal two-pass colormap selection process. + +CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG +files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect. +This is arguably a bug in Photoshop, but if you need to work with Photoshop +CMYK files, you will have to deal with it in your application. We cannot +"fix" this in the library by inverting the data during the CMYK<=>YCCK +transform, because that would break other applications, notably Ghostscript. +Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK +data in the same inverted-YCCK representation used in bare JPEG files, but +the surrounding PostScript code performs an inversion using the PS image +operator. I am told that Photoshop 3.0 will write uninverted YCCK in +EPS/JPEG files, and will omit the PS-level inversion. (But the data +polarity used in bare JPEG files will not change in 3.0.) In either case, +the JPEG library must not invert the data itself, or else Ghostscript would +read these EPS files incorrectly. + + +Error handling +-------------- + +When the default error handler is used, any error detected inside the JPEG +routines will cause a message to be printed on stderr, followed by exit(). +You can supply your own error handling routines to override this behavior +and to control the treatment of nonfatal warnings and trace/debug messages. +The file example.c illustrates the most common case, which is to have the +application regain control after an error rather than exiting. + +The JPEG library never writes any message directly; it always goes through +the error handling routines. Three classes of messages are recognized: + * Fatal errors: the library cannot continue. + * Warnings: the library can continue, but the data is corrupt, and a + damaged output image is likely to result. + * Trace/informational messages. These come with a trace level indicating + the importance of the message; you can control the verbosity of the + program by adjusting the maximum trace level that will be displayed. + +You may, if you wish, simply replace the entire JPEG error handling module +(jerror.c) with your own code. However, you can avoid code duplication by +only replacing some of the routines depending on the behavior you need. +This is accomplished by calling jpeg_std_error() as usual, but then overriding +some of the method pointers in the jpeg_error_mgr struct, as illustrated by +example.c. + +All of the error handling routines will receive a pointer to the JPEG object +(a j_common_ptr which points to either a jpeg_compress_struct or a +jpeg_decompress_struct; if you need to tell which, test the is_decompressor +field). This struct includes a pointer to the error manager struct in its +"err" field. Frequently, custom error handler routines will need to access +additional data which is not known to the JPEG library or the standard error +handler. The most convenient way to do this is to embed either the JPEG +object or the jpeg_error_mgr struct in a larger structure that contains +additional fields; then casting the passed pointer provides access to the +additional fields. Again, see example.c for one way to do it. (Beginning +with IJG version 6b, there is also a void pointer "client_data" in each +JPEG object, which the application can also use to find related data. +The library does not touch client_data at all.) + +The individual methods that you might wish to override are: + +error_exit (j_common_ptr cinfo) + Receives control for a fatal error. Information sufficient to + generate the error message has been stored in cinfo->err; call + output_message to display it. Control must NOT return to the caller; + generally this routine will exit() or longjmp() somewhere. + Typically you would override this routine to get rid of the exit() + default behavior. Note that if you continue processing, you should + clean up the JPEG object with jpeg_abort() or jpeg_destroy(). + +output_message (j_common_ptr cinfo) + Actual output of any JPEG message. Override this to send messages + somewhere other than stderr. Note that this method does not know + how to generate a message, only where to send it. + +format_message (j_common_ptr cinfo, char * buffer) + Constructs a readable error message string based on the error info + stored in cinfo->err. This method is called by output_message. Few + applications should need to override this method. One possible + reason for doing so is to implement dynamic switching of error message + language. + +emit_message (j_common_ptr cinfo, int msg_level) + Decide whether or not to emit a warning or trace message; if so, + calls output_message. The main reason for overriding this method + would be to abort on warnings. msg_level is -1 for warnings, + 0 and up for trace messages. + +Only error_exit() and emit_message() are called from the rest of the JPEG +library; the other two are internal to the error handler. + +The actual message texts are stored in an array of strings which is pointed to +by the field err->jpeg_message_table. The messages are numbered from 0 to +err->last_jpeg_message, and it is these code numbers that are used in the +JPEG library code. You could replace the message texts (for instance, with +messages in French or German) by changing the message table pointer. See +jerror.h for the default texts. CAUTION: this table will almost certainly +change or grow from one library version to the next. + +It may be useful for an application to add its own message texts that are +handled by the same mechanism. The error handler supports a second "add-on" +message table for this purpose. To define an addon table, set the pointer +err->addon_message_table and the message numbers err->first_addon_message and +err->last_addon_message. If you number the addon messages beginning at 1000 +or so, you won't have to worry about conflicts with the library's built-in +messages. See the sample applications cjpeg/djpeg for an example of using +addon messages (the addon messages are defined in cderror.h). + +Actual invocation of the error handler is done via macros defined in jerror.h: + ERREXITn(...) for fatal errors + WARNMSn(...) for corrupt-data warnings + TRACEMSn(...) for trace and informational messages. +These macros store the message code and any additional parameters into the +error handler struct, then invoke the error_exit() or emit_message() method. +The variants of each macro are for varying numbers of additional parameters. +The additional parameters are inserted into the generated message using +standard printf() format codes. + +See jerror.h and jerror.c for further details. + + +Compressed data handling (source and destination managers) +---------------------------------------------------------- + +The JPEG compression library sends its compressed data to a "destination +manager" module. The default destination manager just writes the data to a +stdio stream, but you can provide your own manager to do something else. +Similarly, the decompression library calls a "source manager" to obtain the +compressed data; you can provide your own source manager if you want the data +to come from somewhere other than a stdio stream. + +In both cases, compressed data is processed a bufferload at a time: the +destination or source manager provides a work buffer, and the library invokes +the manager only when the buffer is filled or emptied. (You could define a +one-character buffer to force the manager to be invoked for each byte, but +that would be rather inefficient.) The buffer's size and location are +controlled by the manager, not by the library. For example, if you desired to +decompress a JPEG datastream that was all in memory, you could just make the +buffer pointer and length point to the original data in memory. Then the +buffer-reload procedure would be invoked only if the decompressor ran off the +end of the datastream, which would indicate an erroneous datastream. + +The work buffer is defined as an array of datatype JOCTET, which is generally +"char" or "unsigned char". On a machine where char is not exactly 8 bits +wide, you must define JOCTET as a wider data type and then modify the data +source and destination modules to transcribe the work arrays into 8-bit units +on external storage. + +A data destination manager struct contains a pointer and count defining the +next byte to write in the work buffer and the remaining free space: + + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is filled. The manager's empty_output_buffer method must reset the pointer +and count. The manager is expected to remember the buffer's starting address +and total size in private fields not visible to the library. + +A data destination manager provides three methods: + +init_destination (j_compress_ptr cinfo) + Initialize destination. This is called by jpeg_start_compress() + before any data is actually written. It must initialize + next_output_byte and free_in_buffer. free_in_buffer must be + initialized to a positive value. + +empty_output_buffer (j_compress_ptr cinfo) + This is called whenever the buffer has filled (free_in_buffer + reaches zero). In typical applications, it should write out the + *entire* buffer (use the saved start address and buffer length; + ignore the current state of next_output_byte and free_in_buffer). + Then reset the pointer & count to the start of the buffer, and + return TRUE indicating that the buffer has been dumped. + free_in_buffer must be set to a positive value when TRUE is + returned. A FALSE return should only be used when I/O suspension is + desired (this operating mode is discussed in the next section). + +term_destination (j_compress_ptr cinfo) + Terminate destination --- called by jpeg_finish_compress() after all + data has been written. In most applications, this must flush any + data remaining in the buffer. Use either next_output_byte or + free_in_buffer to determine how much data is in the buffer. + +term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you +want the destination manager to be cleaned up during an abort, you must do it +yourself. + +You will also need code to create a jpeg_destination_mgr struct, fill in its +method pointers, and insert a pointer to the struct into the "dest" field of +the JPEG compression object. This can be done in-line in your setup code if +you like, but it's probably cleaner to provide a separate routine similar to +the jpeg_stdio_dest() routine of the supplied destination manager. + +Decompression source managers follow a parallel design, but with some +additional frammishes. The source manager struct contains a pointer and count +defining the next byte to read from the work buffer and the number of bytes +remaining: + + const JOCTET * next_input_byte; /* => next byte to read from buffer */ + size_t bytes_in_buffer; /* # of bytes remaining in buffer */ + +The library increments the pointer and decrements the count until the buffer +is emptied. The manager's fill_input_buffer method must reset the pointer and +count. In most applications, the manager must remember the buffer's starting +address and total size in private fields not visible to the library. + +A data source manager provides five methods: + +init_source (j_decompress_ptr cinfo) + Initialize source. This is called by jpeg_read_header() before any + data is actually read. Unlike init_destination(), it may leave + bytes_in_buffer set to 0 (in which case a fill_input_buffer() call + will occur immediately). + +fill_input_buffer (j_decompress_ptr cinfo) + This is called whenever bytes_in_buffer has reached zero and more + data is wanted. In typical applications, it should read fresh data + into the buffer (ignoring the current state of next_input_byte and + bytes_in_buffer), reset the pointer & count to the start of the + buffer, and return TRUE indicating that the buffer has been reloaded. + It is not necessary to fill the buffer entirely, only to obtain at + least one more byte. bytes_in_buffer MUST be set to a positive value + if TRUE is returned. A FALSE return should only be used when I/O + suspension is desired (this mode is discussed in the next section). + +skip_input_data (j_decompress_ptr cinfo, long num_bytes) + Skip num_bytes worth of data. The buffer pointer and count should + be advanced over num_bytes input bytes, refilling the buffer as + needed. This is used to skip over a potentially large amount of + uninteresting data (such as an APPn marker). In some applications + it may be possible to optimize away the reading of the skipped data, + but it's not clear that being smart is worth much trouble; large + skips are uncommon. bytes_in_buffer may be zero on return. + A zero or negative skip count should be treated as a no-op. + +resync_to_restart (j_decompress_ptr cinfo, int desired) + This routine is called only when the decompressor has failed to find + a restart (RSTn) marker where one is expected. Its mission is to + find a suitable point for resuming decompression. For most + applications, we recommend that you just use the default resync + procedure, jpeg_resync_to_restart(). However, if you are able to back + up in the input data stream, or if you have a-priori knowledge about + the likely location of restart markers, you may be able to do better. + Read the read_restart_marker() and jpeg_resync_to_restart() routines + in jdmarker.c if you think you'd like to implement your own resync + procedure. + +term_source (j_decompress_ptr cinfo) + Terminate source --- called by jpeg_finish_decompress() after all + data has been read. Often a no-op. + +For both fill_input_buffer() and skip_input_data(), there is no such thing +as an EOF return. If the end of the file has been reached, the routine has +a choice of exiting via ERREXIT() or inserting fake data into the buffer. +In most cases, generating a warning message and inserting a fake EOI marker +is the best course of action --- this will allow the decompressor to output +however much of the image is there. In pathological cases, the decompressor +may swallow the EOI and again demand data ... just keep feeding it fake EOIs. +jdatasrc.c illustrates the recommended error recovery behavior. + +term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want +the source manager to be cleaned up during an abort, you must do it yourself. + +You will also need code to create a jpeg_source_mgr struct, fill in its method +pointers, and insert a pointer to the struct into the "src" field of the JPEG +decompression object. This can be done in-line in your setup code if you +like, but it's probably cleaner to provide a separate routine similar to the +jpeg_stdio_src() routine of the supplied source manager. + +For more information, consult the stdio source and destination managers +in jdatasrc.c and jdatadst.c. + + +I/O suspension +-------------- + +Some applications need to use the JPEG library as an incremental memory-to- +memory filter: when the compressed data buffer is filled or emptied, they want +control to return to the outer loop, rather than expecting that the buffer can +be emptied or reloaded within the data source/destination manager subroutine. +The library supports this need by providing an "I/O suspension" mode, which we +describe in this section. + +The I/O suspension mode is not a panacea: nothing is guaranteed about the +maximum amount of time spent in any one call to the library, so it will not +eliminate response-time problems in single-threaded applications. If you +need guaranteed response time, we suggest you "bite the bullet" and implement +a real multi-tasking capability. + +To use I/O suspension, cooperation is needed between the calling application +and the data source or destination manager; you will always need a custom +source/destination manager. (Please read the previous section if you haven't +already.) The basic idea is that the empty_output_buffer() or +fill_input_buffer() routine is a no-op, merely returning FALSE to indicate +that it has done nothing. Upon seeing this, the JPEG library suspends +operation and returns to its caller. The surrounding application is +responsible for emptying or refilling the work buffer before calling the +JPEG library again. + +Compression suspension: + +For compression suspension, use an empty_output_buffer() routine that returns +FALSE; typically it will not do anything else. This will cause the +compressor to return to the caller of jpeg_write_scanlines(), with the return +value indicating that not all the supplied scanlines have been accepted. +The application must make more room in the output buffer, adjust the output +buffer pointer/count appropriately, and then call jpeg_write_scanlines() +again, pointing to the first unconsumed scanline. + +When forced to suspend, the compressor will backtrack to a convenient stopping +point (usually the start of the current MCU); it will regenerate some output +data when restarted. Therefore, although empty_output_buffer() is only +called when the buffer is filled, you should NOT write out the entire buffer +after a suspension. Write only the data up to the current position of +next_output_byte/free_in_buffer. The data beyond that point will be +regenerated after resumption. + +Because of the backtracking behavior, a good-size output buffer is essential +for efficiency; you don't want the compressor to suspend often. (In fact, an +overly small buffer could lead to infinite looping, if a single MCU required +more data than would fit in the buffer.) We recommend a buffer of at least +several Kbytes. You may want to insert explicit code to ensure that you don't +call jpeg_write_scanlines() unless there is a reasonable amount of space in +the output buffer; in other words, flush the buffer before trying to compress +more data. + +The compressor does not allow suspension while it is trying to write JPEG +markers at the beginning and end of the file. This means that: + * At the beginning of a compression operation, there must be enough free + space in the output buffer to hold the header markers (typically 600 or + so bytes). The recommended buffer size is bigger than this anyway, so + this is not a problem as long as you start with an empty buffer. However, + this restriction might catch you if you insert large special markers, such + as a JFIF thumbnail image, without flushing the buffer afterwards. + * When you call jpeg_finish_compress(), there must be enough space in the + output buffer to emit any buffered data and the final EOI marker. In the + current implementation, half a dozen bytes should suffice for this, but + for safety's sake we recommend ensuring that at least 100 bytes are free + before calling jpeg_finish_compress(). + +A more significant restriction is that jpeg_finish_compress() cannot suspend. +This means you cannot use suspension with multi-pass operating modes, namely +Huffman code optimization and multiple-scan output. Those modes write the +whole file during jpeg_finish_compress(), which will certainly result in +buffer overrun. (Note that this restriction applies only to compression, +not decompression. The decompressor supports input suspension in all of its +operating modes.) + +Decompression suspension: + +For decompression suspension, use a fill_input_buffer() routine that simply +returns FALSE (except perhaps during error recovery, as discussed below). +This will cause the decompressor to return to its caller with an indication +that suspension has occurred. This can happen at four places: + * jpeg_read_header(): will return JPEG_SUSPENDED. + * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE. + * jpeg_read_scanlines(): will return the number of scanlines already + completed (possibly 0). + * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE. +The surrounding application must recognize these cases, load more data into +the input buffer, and repeat the call. In the case of jpeg_read_scanlines(), +increment the passed pointers past any scanlines successfully read. + +Just as with compression, the decompressor will typically backtrack to a +convenient restart point before suspending. When fill_input_buffer() is +called, next_input_byte/bytes_in_buffer point to the current restart point, +which is where the decompressor will backtrack to if FALSE is returned. +The data beyond that position must NOT be discarded if you suspend; it needs +to be re-read upon resumption. In most implementations, you'll need to shift +this data down to the start of your work buffer and then load more data after +it. Again, this behavior means that a several-Kbyte work buffer is essential +for decent performance; furthermore, you should load a reasonable amount of +new data before resuming decompression. (If you loaded, say, only one new +byte each time around, you could waste a LOT of cycles.) + +The skip_input_data() source manager routine requires special care in a +suspension scenario. This routine is NOT granted the ability to suspend the +decompressor; it can decrement bytes_in_buffer to zero, but no more. If the +requested skip distance exceeds the amount of data currently in the input +buffer, then skip_input_data() must set bytes_in_buffer to zero and record the +additional skip distance somewhere else. The decompressor will immediately +call fill_input_buffer(), which should return FALSE, which will cause a +suspension return. The surrounding application must then arrange to discard +the recorded number of bytes before it resumes loading the input buffer. +(Yes, this design is rather baroque, but it avoids complexity in the far more +common case where a non-suspending source manager is used.) + +If the input data has been exhausted, we recommend that you emit a warning +and insert dummy EOI markers just as a non-suspending data source manager +would do. This can be handled either in the surrounding application logic or +within fill_input_buffer(); the latter is probably more efficient. If +fill_input_buffer() knows that no more data is available, it can set the +pointer/count to point to a dummy EOI marker and then return TRUE just as +though it had read more data in a non-suspending situation. + +The decompressor does not attempt to suspend within standard JPEG markers; +instead it will backtrack to the start of the marker and reprocess the whole +marker next time. Hence the input buffer must be large enough to hold the +longest standard marker in the file. Standard JPEG markers should normally +not exceed a few hundred bytes each (DHT tables are typically the longest). +We recommend at least a 2K buffer for performance reasons, which is much +larger than any correct marker is likely to be. For robustness against +damaged marker length counts, you may wish to insert a test in your +application for the case that the input buffer is completely full and yet +the decoder has suspended without consuming any data --- otherwise, if this +situation did occur, it would lead to an endless loop. (The library can't +provide this test since it has no idea whether "the buffer is full", or +even whether there is a fixed-size input buffer.) + +The input buffer would need to be 64K to allow for arbitrary COM or APPn +markers, but these are handled specially: they are either saved into allocated +memory, or skipped over by calling skip_input_data(). In the former case, +suspension is handled correctly, and in the latter case, the problem of +buffer overrun is placed on skip_input_data's shoulders, as explained above. +Note that if you provide your own marker handling routine for large markers, +you should consider how to deal with buffer overflow. + +Multiple-buffer management: + +In some applications it is desirable to store the compressed data in a linked +list of buffer areas, so as to avoid data copying. This can be handled by +having empty_output_buffer() or fill_input_buffer() set the pointer and count +to reference the next available buffer; FALSE is returned only if no more +buffers are available. Although seemingly straightforward, there is a +pitfall in this approach: the backtrack that occurs when FALSE is returned +could back up into an earlier buffer. For example, when fill_input_buffer() +is called, the current pointer & count indicate the backtrack restart point. +Since fill_input_buffer() will set the pointer and count to refer to a new +buffer, the restart position must be saved somewhere else. Suppose a second +call to fill_input_buffer() occurs in the same library call, and no +additional input data is available, so fill_input_buffer must return FALSE. +If the JPEG library has not moved the pointer/count forward in the current +buffer, then *the correct restart point is the saved position in the prior +buffer*. Prior buffers may be discarded only after the library establishes +a restart point within a later buffer. Similar remarks apply for output into +a chain of buffers. + +The library will never attempt to backtrack over a skip_input_data() call, +so any skipped data can be permanently discarded. You still have to deal +with the case of skipping not-yet-received data, however. + +It's much simpler to use only a single buffer; when fill_input_buffer() is +called, move any unconsumed data (beyond the current pointer/count) down to +the beginning of this buffer and then load new data into the remaining buffer +space. This approach requires a little more data copying but is far easier +to get right. + + +Progressive JPEG support +------------------------ + +Progressive JPEG rearranges the stored data into a series of scans of +increasing quality. In situations where a JPEG file is transmitted across a +slow communications link, a decoder can generate a low-quality image very +quickly from the first scan, then gradually improve the displayed quality as +more scans are received. The final image after all scans are complete is +identical to that of a regular (sequential) JPEG file of the same quality +setting. Progressive JPEG files are often slightly smaller than equivalent +sequential JPEG files, but the possibility of incremental display is the main +reason for using progressive JPEG. + +The IJG encoder library generates progressive JPEG files when given a +suitable "scan script" defining how to divide the data into scans. +Creation of progressive JPEG files is otherwise transparent to the encoder. +Progressive JPEG files can also be read transparently by the decoder library. +If the decoding application simply uses the library as defined above, it +will receive a final decoded image without any indication that the file was +progressive. Of course, this approach does not allow incremental display. +To perform incremental display, an application needs to use the decoder +library's "buffered-image" mode, in which it receives a decoded image +multiple times. + +Each displayed scan requires about as much work to decode as a full JPEG +image of the same size, so the decoder must be fairly fast in relation to the +data transmission rate in order to make incremental display useful. However, +it is possible to skip displaying the image and simply add the incoming bits +to the decoder's coefficient buffer. This is fast because only Huffman +decoding need be done, not IDCT, upsampling, colorspace conversion, etc. +The IJG decoder library allows the application to switch dynamically between +displaying the image and simply absorbing the incoming bits. A properly +coded application can automatically adapt the number of display passes to +suit the time available as the image is received. Also, a final +higher-quality display cycle can be performed from the buffered data after +the end of the file is reached. + +Progressive compression: + +To create a progressive JPEG file (or a multiple-scan sequential JPEG file), +set the scan_info cinfo field to point to an array of scan descriptors, and +perform compression as usual. Instead of constructing your own scan list, +you can call the jpeg_simple_progression() helper routine to create a +recommended progression sequence; this method should be used by all +applications that don't want to get involved in the nitty-gritty of +progressive scan sequence design. (If you want to provide user control of +scan sequences, you may wish to borrow the scan script reading code found +in rdswitch.c, so that you can read scan script files just like cjpeg's.) +When scan_info is not NULL, the compression library will store DCT'd data +into a buffer array as jpeg_write_scanlines() is called, and will emit all +the requested scans during jpeg_finish_compress(). This implies that +multiple-scan output cannot be created with a suspending data destination +manager, since jpeg_finish_compress() does not support suspension. We +should also note that the compressor currently forces Huffman optimization +mode when creating a progressive JPEG file, because the default Huffman +tables are unsuitable for progressive files. + +Progressive decompression: + +When buffered-image mode is not used, the decoder library will read all of +a multi-scan file during jpeg_start_decompress(), so that it can provide a +final decoded image. (Here "multi-scan" means either progressive or +multi-scan sequential.) This makes multi-scan files transparent to the +decoding application. However, existing applications that used suspending +input with version 5 of the IJG library will need to be modified to check +for a suspension return from jpeg_start_decompress(). + +To perform incremental display, an application must use the library's +buffered-image mode. This is described in the next section. + + +Buffered-image mode +------------------- + +In buffered-image mode, the library stores the partially decoded image in a +coefficient buffer, from which it can be read out as many times as desired. +This mode is typically used for incremental display of progressive JPEG files, +but it can be used with any JPEG file. Each scan of a progressive JPEG file +adds more data (more detail) to the buffered image. The application can +display in lockstep with the source file (one display pass per input scan), +or it can allow input processing to outrun display processing. By making +input and display processing run independently, it is possible for the +application to adapt progressive display to a wide range of data transmission +rates. + +The basic control flow for buffered-image decoding is + + jpeg_create_decompress() + set data source + jpeg_read_header() + set overall decompression parameters + cinfo.buffered_image = TRUE; /* select buffered-image mode */ + jpeg_start_decompress() + for (each output pass) { + adjust output decompression parameters if required + jpeg_start_output() /* start a new output pass */ + for (all scanlines in image) { + jpeg_read_scanlines() + display scanlines + } + jpeg_finish_output() /* terminate output pass */ + } + jpeg_finish_decompress() + jpeg_destroy_decompress() + +This differs from ordinary unbuffered decoding in that there is an additional +level of looping. The application can choose how many output passes to make +and how to display each pass. + +The simplest approach to displaying progressive images is to do one display +pass for each scan appearing in the input file. In this case the outer loop +condition is typically + while (! jpeg_input_complete(&cinfo)) +and the start-output call should read + jpeg_start_output(&cinfo, cinfo.input_scan_number); +The second parameter to jpeg_start_output() indicates which scan of the input +file is to be displayed; the scans are numbered starting at 1 for this +purpose. (You can use a loop counter starting at 1 if you like, but using +the library's input scan counter is easier.) The library automatically reads +data as necessary to complete each requested scan, and jpeg_finish_output() +advances to the next scan or end-of-image marker (hence input_scan_number +will be incremented by the time control arrives back at jpeg_start_output()). +With this technique, data is read from the input file only as needed, and +input and output processing run in lockstep. + +After reading the final scan and reaching the end of the input file, the +buffered image remains available; it can be read additional times by +repeating the jpeg_start_output()/jpeg_read_scanlines()/jpeg_finish_output() +sequence. For example, a useful technique is to use fast one-pass color +quantization for display passes made while the image is arriving, followed by +a final display pass using two-pass quantization for highest quality. This +is done by changing the library parameters before the final output pass. +Changing parameters between passes is discussed in detail below. + +In general the last scan of a progressive file cannot be recognized as such +until after it is read, so a post-input display pass is the best approach if +you want special processing in the final pass. + +When done with the image, be sure to call jpeg_finish_decompress() to release +the buffered image (or just use jpeg_destroy_decompress()). + +If input data arrives faster than it can be displayed, the application can +cause the library to decode input data in advance of what's needed to produce +output. This is done by calling the routine jpeg_consume_input(). +The return value is one of the following: + JPEG_REACHED_SOS: reached an SOS marker (the start of a new scan) + JPEG_REACHED_EOI: reached the EOI marker (end of image) + JPEG_ROW_COMPLETED: completed reading one MCU row of compressed data + JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan + JPEG_SUSPENDED: suspended before completing any of the above +(JPEG_SUSPENDED can occur only if a suspending data source is used.) This +routine can be called at any time after initializing the JPEG object. It +reads some additional data and returns when one of the indicated significant +events occurs. (If called after the EOI marker is reached, it will +immediately return JPEG_REACHED_EOI without attempting to read more data.) + +The library's output processing will automatically call jpeg_consume_input() +whenever the output processing overtakes the input; thus, simple lockstep +display requires no direct calls to jpeg_consume_input(). But by adding +calls to jpeg_consume_input(), you can absorb data in advance of what is +being displayed. This has two benefits: + * You can limit buildup of unprocessed data in your input buffer. + * You can eliminate extra display passes by paying attention to the + state of the library's input processing. + +The first of these benefits only requires interspersing calls to +jpeg_consume_input() with your display operations and any other processing +you may be doing. To avoid wasting cycles due to backtracking, it's best to +call jpeg_consume_input() only after a hundred or so new bytes have arrived. +This is discussed further under "I/O suspension", above. (Note: the JPEG +library currently is not thread-safe. You must not call jpeg_consume_input() +from one thread of control if a different library routine is working on the +same JPEG object in another thread.) + +When input arrives fast enough that more than one new scan is available +before you start a new output pass, you may as well skip the output pass +corresponding to the completed scan. This occurs for free if you pass +cinfo.input_scan_number as the target scan number to jpeg_start_output(). +The input_scan_number field is simply the index of the scan currently being +consumed by the input processor. You can ensure that this is up-to-date by +emptying the input buffer just before calling jpeg_start_output(): call +jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or +JPEG_REACHED_EOI. + +The target scan number passed to jpeg_start_output() is saved in the +cinfo.output_scan_number field. The library's output processing calls +jpeg_consume_input() whenever the current input scan number and row within +that scan is less than or equal to the current output scan number and row. +Thus, input processing can "get ahead" of the output processing but is not +allowed to "fall behind". You can achieve several different effects by +manipulating this interlock rule. For example, if you pass a target scan +number greater than the current input scan number, the output processor will +wait until that scan starts to arrive before producing any output. (To avoid +an infinite loop, the target scan number is automatically reset to the last +scan number when the end of image is reached. Thus, if you specify a large +target scan number, the library will just absorb the entire input file and +then perform an output pass. This is effectively the same as what +jpeg_start_decompress() does when you don't select buffered-image mode.) +When you pass a target scan number equal to the current input scan number, +the image is displayed no faster than the current input scan arrives. The +final possibility is to pass a target scan number less than the current input +scan number; this disables the input/output interlock and causes the output +processor to simply display whatever it finds in the image buffer, without +waiting for input. (However, the library will not accept a target scan +number less than one, so you can't avoid waiting for the first scan.) + +When data is arriving faster than the output display processing can advance +through the image, jpeg_consume_input() will store data into the buffered +image beyond the point at which the output processing is reading data out +again. If the input arrives fast enough, it may "wrap around" the buffer to +the point where the input is more than one whole scan ahead of the output. +If the output processing simply proceeds through its display pass without +paying attention to the input, the effect seen on-screen is that the lower +part of the image is one or more scans better in quality than the upper part. +Then, when the next output scan is started, you have a choice of what target +scan number to use. The recommended choice is to use the current input scan +number at that time, which implies that you've skipped the output scans +corresponding to the input scans that were completed while you processed the +previous output scan. In this way, the decoder automatically adapts its +speed to the arriving data, by skipping output scans as necessary to keep up +with the arriving data. + +When using this strategy, you'll want to be sure that you perform a final +output pass after receiving all the data; otherwise your last display may not +be full quality across the whole screen. So the right outer loop logic is +something like this: + do { + absorb any waiting input by calling jpeg_consume_input() + final_pass = jpeg_input_complete(&cinfo); + adjust output decompression parameters if required + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + } while (! final_pass); +rather than quitting as soon as jpeg_input_complete() returns TRUE. This +arrangement makes it simple to use higher-quality decoding parameters +for the final pass. But if you don't want to use special parameters for +the final pass, the right loop logic is like this: + for (;;) { + absorb any waiting input by calling jpeg_consume_input() + jpeg_start_output(&cinfo, cinfo.input_scan_number); + ... + jpeg_finish_output() + if (jpeg_input_complete(&cinfo) && + cinfo.input_scan_number == cinfo.output_scan_number) + break; + } +In this case you don't need to know in advance whether an output pass is to +be the last one, so it's not necessary to have reached EOF before starting +the final output pass; rather, what you want to test is whether the output +pass was performed in sync with the final input scan. This form of the loop +will avoid an extra output pass whenever the decoder is able (or nearly able) +to keep up with the incoming data. + +When the data transmission speed is high, you might begin a display pass, +then find that much or all of the file has arrived before you can complete +the pass. (You can detect this by noting the JPEG_REACHED_EOI return code +from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().) +In this situation you may wish to abort the current display pass and start a +new one using the newly arrived information. To do so, just call +jpeg_finish_output() and then start a new pass with jpeg_start_output(). + +A variant strategy is to abort and restart display if more than one complete +scan arrives during an output pass; this can be detected by noting +JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number. This +idea should be employed with caution, however, since the display process +might never get to the bottom of the image before being aborted, resulting +in the lower part of the screen being several passes worse than the upper. +In most cases it's probably best to abort an output pass only if the whole +file has arrived and you want to begin the final output pass immediately. + +When receiving data across a communication link, we recommend always using +the current input scan number for the output target scan number; if a +higher-quality final pass is to be done, it should be started (aborting any +incomplete output pass) as soon as the end of file is received. However, +many other strategies are possible. For example, the application can examine +the parameters of the current input scan and decide whether to display it or +not. If the scan contains only chroma data, one might choose not to use it +as the target scan, expecting that the scan will be small and will arrive +quickly. To skip to the next scan, call jpeg_consume_input() until it +returns JPEG_REACHED_SOS or JPEG_REACHED_EOI. Or just use the next higher +number as the target scan for jpeg_start_output(); but that method doesn't +let you inspect the next scan's parameters before deciding to display it. + + +In buffered-image mode, jpeg_start_decompress() never performs input and +thus never suspends. An application that uses input suspension with +buffered-image mode must be prepared for suspension returns from these +routines: +* jpeg_start_output() performs input only if you request 2-pass quantization + and the target scan isn't fully read yet. (This is discussed below.) +* jpeg_read_scanlines(), as always, returns the number of scanlines that it + was able to produce before suspending. +* jpeg_finish_output() will read any markers following the target scan, + up to the end of the file or the SOS marker that begins another scan. + (But it reads no input if jpeg_consume_input() has already reached the + end of the file or a SOS marker beyond the target output scan.) +* jpeg_finish_decompress() will read until the end of file, and thus can + suspend if the end hasn't already been reached (as can be tested by + calling jpeg_input_complete()). +jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress() +all return TRUE if they completed their tasks, FALSE if they had to suspend. +In the event of a FALSE return, the application must load more input data +and repeat the call. Applications that use non-suspending data sources need +not check the return values of these three routines. + + +It is possible to change decoding parameters between output passes in the +buffered-image mode. The decoder library currently supports only very +limited changes of parameters. ONLY THE FOLLOWING parameter changes are +allowed after jpeg_start_decompress() is called: +* dct_method can be changed before each call to jpeg_start_output(). + For example, one could use a fast DCT method for early scans, changing + to a higher quality method for the final scan. +* dither_mode can be changed before each call to jpeg_start_output(); + of course this has no impact if not using color quantization. Typically + one would use ordered dither for initial passes, then switch to + Floyd-Steinberg dither for the final pass. Caution: changing dither mode + can cause more memory to be allocated by the library. Although the amount + of memory involved is not large (a scanline or so), it may cause the + initial max_memory_to_use specification to be exceeded, which in the worst + case would result in an out-of-memory failure. +* do_block_smoothing can be changed before each call to jpeg_start_output(). + This setting is relevant only when decoding a progressive JPEG image. + During the first DC-only scan, block smoothing provides a very "fuzzy" look + instead of the very "blocky" look seen without it; which is better seems a + matter of personal taste. But block smoothing is nearly always a win + during later stages, especially when decoding a successive-approximation + image: smoothing helps to hide the slight blockiness that otherwise shows + up on smooth gradients until the lowest coefficient bits are sent. +* Color quantization mode can be changed under the rules described below. + You *cannot* change between full-color and quantized output (because that + would alter the required I/O buffer sizes), but you can change which + quantization method is used. + +When generating color-quantized output, changing quantization method is a +very useful way of switching between high-speed and high-quality display. +The library allows you to change among its three quantization methods: +1. Single-pass quantization to a fixed color cube. + Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL. +2. Single-pass quantization to an application-supplied colormap. + Selected by setting cinfo.colormap to point to the colormap (the value of + two_pass_quantize is ignored); also set cinfo.actual_number_of_colors. +3. Two-pass quantization to a colormap chosen specifically for the image. + Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL. + (This is the default setting selected by jpeg_read_header, but it is + probably NOT what you want for the first pass of progressive display!) +These methods offer successively better quality and lesser speed. However, +only the first method is available for quantizing in non-RGB color spaces. + +IMPORTANT: because the different quantizer methods have very different +working-storage requirements, the library requires you to indicate which +one(s) you intend to use before you call jpeg_start_decompress(). (If we did +not require this, the max_memory_to_use setting would be a complete fiction.) +You do this by setting one or more of these three cinfo fields to TRUE: + enable_1pass_quant Fixed color cube colormap + enable_external_quant Externally-supplied colormap + enable_2pass_quant Two-pass custom colormap +All three are initialized FALSE by jpeg_read_header(). But +jpeg_start_decompress() automatically sets TRUE the one selected by the +current two_pass_quantize and colormap settings, so you only need to set the +enable flags for any other quantization methods you plan to change to later. + +After setting the enable flags correctly at jpeg_start_decompress() time, you +can change to any enabled quantization method by setting two_pass_quantize +and colormap properly just before calling jpeg_start_output(). The following +special rules apply: +1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass + or 2-pass mode from a different mode, or when you want the 2-pass + quantizer to be re-run to generate a new colormap. +2. To switch to an external colormap, or to change to a different external + colormap than was used on the prior pass, you must call + jpeg_new_colormap() after setting cinfo.colormap. +NOTE: if you want to use the same colormap as was used in the prior pass, +you should not do either of these things. This will save some nontrivial +switchover costs. +(These requirements exist because cinfo.colormap will always be non-NULL +after completing a prior output pass, since both the 1-pass and 2-pass +quantizers set it to point to their output colormaps. Thus you have to +do one of these two things to notify the library that something has changed. +Yup, it's a bit klugy, but it's necessary to do it this way for backwards +compatibility.) + +Note that in buffered-image mode, the library generates any requested colormap +during jpeg_start_output(), not during jpeg_start_decompress(). + +When using two-pass quantization, jpeg_start_output() makes a pass over the +buffered image to determine the optimum color map; it therefore may take a +significant amount of time, whereas ordinarily it does little work. The +progress monitor hook is called during this pass, if defined. It is also +important to realize that if the specified target scan number is greater than +or equal to the current input scan number, jpeg_start_output() will attempt +to consume input as it makes this pass. If you use a suspending data source, +you need to check for a FALSE return from jpeg_start_output() under these +conditions. The combination of 2-pass quantization and a not-yet-fully-read +target scan is the only case in which jpeg_start_output() will consume input. + + +Application authors who support buffered-image mode may be tempted to use it +for all JPEG images, even single-scan ones. This will work, but it is +inefficient: there is no need to create an image-sized coefficient buffer for +single-scan images. Requesting buffered-image mode for such an image wastes +memory. Worse, it can cost time on large images, since the buffered data has +to be swapped out or written to a temporary file. If you are concerned about +maximum performance on baseline JPEG files, you should use buffered-image +mode only when the incoming file actually has multiple scans. This can be +tested by calling jpeg_has_multiple_scans(), which will return a correct +result at any time after jpeg_read_header() completes. + +It is also worth noting that when you use jpeg_consume_input() to let input +processing get ahead of output processing, the resulting pattern of access to +the coefficient buffer is quite nonsequential. It's best to use the memory +manager jmemnobs.c if you can (ie, if you have enough real or virtual main +memory). If not, at least make sure that max_memory_to_use is set as high as +possible. If the JPEG memory manager has to use a temporary file, you will +probably see a lot of disk traffic and poor performance. (This could be +improved with additional work on the memory manager, but we haven't gotten +around to it yet.) + +In some applications it may be convenient to use jpeg_consume_input() for all +input processing, including reading the initial markers; that is, you may +wish to call jpeg_consume_input() instead of jpeg_read_header() during +startup. This works, but note that you must check for JPEG_REACHED_SOS and +JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes. +Once the first SOS marker has been reached, you must call +jpeg_start_decompress() before jpeg_consume_input() will consume more input; +it'll just keep returning JPEG_REACHED_SOS until you do. If you read a +tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI +without ever returning JPEG_REACHED_SOS; be sure to check for this case. +If this happens, the decompressor will not read any more input until you call +jpeg_abort() to reset it. It is OK to call jpeg_consume_input() even when not +using buffered-image mode, but in that case it's basically a no-op after the +initial markers have been read: it will just return JPEG_SUSPENDED. + + +Abbreviated datastreams and multiple images +------------------------------------------- + +A JPEG compression or decompression object can be reused to process multiple +images. This saves a small amount of time per image by eliminating the +"create" and "destroy" operations, but that isn't the real purpose of the +feature. Rather, reuse of an object provides support for abbreviated JPEG +datastreams. Object reuse can also simplify processing a series of images in +a single input or output file. This section explains these features. + +A JPEG file normally contains several hundred bytes worth of quantization +and Huffman tables. In a situation where many images will be stored or +transmitted with identical tables, this may represent an annoying overhead. +The JPEG standard therefore permits tables to be omitted. The standard +defines three classes of JPEG datastreams: + * "Interchange" datastreams contain an image and all tables needed to decode + the image. These are the usual kind of JPEG file. + * "Abbreviated image" datastreams contain an image, but are missing some or + all of the tables needed to decode that image. + * "Abbreviated table specification" (henceforth "tables-only") datastreams + contain only table specifications. +To decode an abbreviated image, it is necessary to load the missing table(s) +into the decoder beforehand. This can be accomplished by reading a separate +tables-only file. A variant scheme uses a series of images in which the first +image is an interchange (complete) datastream, while subsequent ones are +abbreviated and rely on the tables loaded by the first image. It is assumed +that once the decoder has read a table, it will remember that table until a +new definition for the same table number is encountered. + +It is the application designer's responsibility to figure out how to associate +the correct tables with an abbreviated image. While abbreviated datastreams +can be useful in a closed environment, their use is strongly discouraged in +any situation where data exchange with other applications might be needed. +Caveat designer. + +The JPEG library provides support for reading and writing any combination of +tables-only datastreams and abbreviated images. In both compression and +decompression objects, a quantization or Huffman table will be retained for +the lifetime of the object, unless it is overwritten by a new table definition. + + +To create abbreviated image datastreams, it is only necessary to tell the +compressor not to emit some or all of the tables it is using. Each +quantization and Huffman table struct contains a boolean field "sent_table", +which normally is initialized to FALSE. For each table used by the image, the +header-writing process emits the table and sets sent_table = TRUE unless it is +already TRUE. (In normal usage, this prevents outputting the same table +definition multiple times, as would otherwise occur because the chroma +components typically share tables.) Thus, setting this field to TRUE before +calling jpeg_start_compress() will prevent the table from being written at +all. + +If you want to create a "pure" abbreviated image file containing no tables, +just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the +tables. If you want to emit some but not all tables, you'll need to set the +individual sent_table fields directly. + +To create an abbreviated image, you must also call jpeg_start_compress() +with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress() +will force all the sent_table fields to FALSE. (This is a safety feature to +prevent abbreviated images from being created accidentally.) + +To create a tables-only file, perform the same parameter setup that you +normally would, but instead of calling jpeg_start_compress() and so on, call +jpeg_write_tables(&cinfo). This will write an abbreviated datastream +containing only SOI, DQT and/or DHT markers, and EOI. All the quantization +and Huffman tables that are currently defined in the compression object will +be emitted unless their sent_tables flag is already TRUE, and then all the +sent_tables flags will be set TRUE. + +A sure-fire way to create matching tables-only and abbreviated image files +is to proceed as follows: + + create JPEG compression object + set JPEG parameters + set destination to tables-only file + jpeg_write_tables(&cinfo); + set destination to image file + jpeg_start_compress(&cinfo, FALSE); + write data... + jpeg_finish_compress(&cinfo); + +Since the JPEG parameters are not altered between writing the table file and +the abbreviated image file, the same tables are sure to be used. Of course, +you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence +many times to produce many abbreviated image files matching the table file. + +You cannot suppress output of the computed Huffman tables when Huffman +optimization is selected. (If you could, there'd be no way to decode the +image...) Generally, you don't want to set optimize_coding = TRUE when +you are trying to produce abbreviated files. + +In some cases you might want to compress an image using tables which are +not stored in the application, but are defined in an interchange or +tables-only file readable by the application. This can be done by setting up +a JPEG decompression object to read the specification file, then copying the +tables into your compression object. See jpeg_copy_critical_parameters() +for an example of copying quantization tables. + + +To read abbreviated image files, you simply need to load the proper tables +into the decompression object before trying to read the abbreviated image. +If the proper tables are stored in the application program, you can just +allocate the table structs and fill in their contents directly. For example, +to load a fixed quantization table into table slot "n": + + if (cinfo.quant_tbl_ptrs[n] == NULL) + cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo); + quant_ptr = cinfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */ + for (i = 0; i < 64; i++) { + /* Qtable[] is desired quantization table, in natural array order */ + quant_ptr->quantval[i] = Qtable[i]; + } + +Code to load a fixed Huffman table is typically (for AC table "n"): + + if (cinfo.ac_huff_tbl_ptrs[n] == NULL) + cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo); + huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */ + for (i = 1; i <= 16; i++) { + /* counts[i] is number of Huffman codes of length i bits, i=1..16 */ + huff_ptr->bits[i] = counts[i]; + } + for (i = 0; i < 256; i++) { + /* symbols[] is the list of Huffman symbols, in code-length order */ + huff_ptr->huffval[i] = symbols[i]; + } + +(Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a +constant JQUANT_TBL object is not safe. If the incoming file happened to +contain a quantization table definition, your master table would get +overwritten! Instead allocate a working table copy and copy the master table +into it, as illustrated above. Ditto for Huffman tables, of course.) + +You might want to read the tables from a tables-only file, rather than +hard-wiring them into your application. The jpeg_read_header() call is +sufficient to read a tables-only file. You must pass a second parameter of +FALSE to indicate that you do not require an image to be present. Thus, the +typical scenario is + + create JPEG decompression object + set source to tables-only file + jpeg_read_header(&cinfo, FALSE); + set source to abbreviated image file + jpeg_read_header(&cinfo, TRUE); + set decompression parameters + jpeg_start_decompress(&cinfo); + read data... + jpeg_finish_decompress(&cinfo); + +In some cases, you may want to read a file without knowing whether it contains +an image or just tables. In that case, pass FALSE and check the return value +from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found, +JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value, +JPEG_SUSPENDED, is possible when using a suspending data source manager.) +Note that jpeg_read_header() will not complain if you read an abbreviated +image for which you haven't loaded the missing tables; the missing-table check +occurs later, in jpeg_start_decompress(). + + +It is possible to read a series of images from a single source file by +repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence, +without releasing/recreating the JPEG object or the data source module. +(If you did reinitialize, any partial bufferload left in the data source +buffer at the end of one image would be discarded, causing you to lose the +start of the next image.) When you use this method, stored tables are +automatically carried forward, so some of the images can be abbreviated images +that depend on tables from earlier images. + +If you intend to write a series of images into a single destination file, +you might want to make a specialized data destination module that doesn't +flush the output buffer at term_destination() time. This would speed things +up by some trifling amount. Of course, you'd need to remember to flush the +buffer after the last image. You can make the later images be abbreviated +ones by passing FALSE to jpeg_start_compress(). + + +Special markers +--------------- + +Some applications may need to insert or extract special data in the JPEG +datastream. The JPEG standard provides marker types "COM" (comment) and +"APP0" through "APP15" (application) to hold application-specific data. +Unfortunately, the use of these markers is not specified by the standard. +COM markers are fairly widely used to hold user-supplied text. The JFIF file +format spec uses APP0 markers with specified initial strings to hold certain +data. Adobe applications use APP14 markers beginning with the string "Adobe" +for miscellaneous data. Other APPn markers are rarely seen, but might +contain almost anything. + +If you wish to store user-supplied text, we recommend you use COM markers +and place readable 7-bit ASCII text in them. Newline conventions are not +standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR +(Mac style). A robust COM reader should be able to cope with random binary +garbage, including nulls, since some applications generate COM markers +containing non-ASCII junk. (But yours should not be one of them.) + +For program-supplied data, use an APPn marker, and be sure to begin it with an +identifying string so that you can tell whether the marker is actually yours. +It's probably best to avoid using APP0 or APP14 for any private markers. +(NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you +not use APP8 markers for any private purposes, either.) + +Keep in mind that at most 65533 bytes can be put into one marker, but you +can have as many markers as you like. + +By default, the IJG compression library will write a JFIF APP0 marker if the +selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if +the selected colorspace is RGB, CMYK, or YCCK. You can disable this, but +we don't recommend it. The decompression library will recognize JFIF and +Adobe markers and will set the JPEG colorspace properly when one is found. + + +You can write special markers immediately following the datastream header by +calling jpeg_write_marker() after jpeg_start_compress() and before the first +call to jpeg_write_scanlines(). When you do this, the markers appear after +the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before +all else. Specify the marker type parameter as "JPEG_COM" for COM or +"JPEG_APP0 + n" for APPn. (Actually, jpeg_write_marker will let you write +any marker type, but we don't recommend writing any other kinds of marker.) +For example, to write a user comment string pointed to by comment_text: + jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text)); + +If it's not convenient to store all the marker data in memory at once, +you can instead call jpeg_write_m_header() followed by multiple calls to +jpeg_write_m_byte(). If you do it this way, it's your responsibility to +call jpeg_write_m_byte() exactly the number of times given in the length +parameter to jpeg_write_m_header(). (This method lets you empty the +output buffer partway through a marker, which might be important when +using a suspending data destination module. In any case, if you are using +a suspending destination, you should flush its buffer after inserting +any special markers. See "I/O suspension".) + +Or, if you prefer to synthesize the marker byte sequence yourself, +you can just cram it straight into the data destination module. + +If you are writing JFIF 1.02 extension markers (thumbnail images), don't +forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the +correct JFIF version number in the JFIF header marker. The library's default +is to write version 1.01, but that's wrong if you insert any 1.02 extension +markers. (We could probably get away with just defaulting to 1.02, but there +used to be broken decoders that would complain about unknown minor version +numbers. To reduce compatibility risks it's safest not to write 1.02 unless +you are actually using 1.02 extensions.) + + +When reading, two methods of handling special markers are available: +1. You can ask the library to save the contents of COM and/or APPn markers +into memory, and then examine them at your leisure afterwards. +2. You can supply your own routine to process COM and/or APPn markers +on-the-fly as they are read. +The first method is simpler to use, especially if you are using a suspending +data source; writing a marker processor that copes with input suspension is +not easy (consider what happens if the marker is longer than your available +input buffer). However, the second method conserves memory since the marker +data need not be kept around after it's been processed. + +For either method, you'd normally set up marker handling after creating a +decompression object and before calling jpeg_read_header(), because the +markers of interest will typically be near the head of the file and so will +be scanned by jpeg_read_header. Once you've established a marker handling +method, it will be used for the life of that decompression object +(potentially many datastreams), unless you change it. Marker handling is +determined separately for COM markers and for each APPn marker code. + + +To save the contents of special markers in memory, call + jpeg_save_markers(cinfo, marker_code, length_limit) +where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n. +(To arrange to save all the special marker types, you need to call this +routine 17 times, for COM and APP0-APP15.) If the incoming marker is longer +than length_limit data bytes, only length_limit bytes will be saved; this +parameter allows you to avoid chewing up memory when you only need to see the +first few bytes of a potentially large marker. If you want to save all the +data, set length_limit to 0xFFFF; that is enough since marker lengths are only +16 bits. As a special case, setting length_limit to 0 prevents that marker +type from being saved at all. (That is the default behavior, in fact.) + +After jpeg_read_header() completes, you can examine the special markers by +following the cinfo->marker_list pointer chain. All the special markers in +the file appear in this list, in order of their occurrence in the file (but +omitting any markers of types you didn't ask for). Both the original data +length and the saved data length are recorded for each list entry; the latter +will not exceed length_limit for the particular marker type. Note that these +lengths exclude the marker length word, whereas the stored representation +within the JPEG file includes it. (Hence the maximum data length is really +only 65533.) + +It is possible that additional special markers appear in the file beyond the +SOS marker at which jpeg_read_header stops; if so, the marker list will be +extended during reading of the rest of the file. This is not expected to be +common, however. If you are short on memory you may want to reset the length +limit to zero for all marker types after finishing jpeg_read_header, to +ensure that the max_memory_to_use setting cannot be exceeded due to addition +of later markers. + +The marker list remains stored until you call jpeg_finish_decompress or +jpeg_abort, at which point the memory is freed and the list is set to empty. +(jpeg_destroy also releases the storage, of course.) + +Note that the library is internally interested in APP0 and APP14 markers; +if you try to set a small nonzero length limit on these types, the library +will silently force the length up to the minimum it wants. (But you can set +a zero length limit to prevent them from being saved at all.) Also, in a +16-bit environment, the maximum length limit may be constrained to less than +65533 by malloc() limitations. It is therefore best not to assume that the +effective length limit is exactly what you set it to be. + + +If you want to supply your own marker-reading routine, you do it by calling +jpeg_set_marker_processor(). A marker processor routine must have the +signature + boolean jpeg_marker_parser_method (j_decompress_ptr cinfo) +Although the marker code is not explicitly passed, the routine can find it +in cinfo->unread_marker. At the time of call, the marker proper has been +read from the data source module. The processor routine is responsible for +reading the marker length word and the remaining parameter bytes, if any. +Return TRUE to indicate success. (FALSE should be returned only if you are +using a suspending data source and it tells you to suspend. See the standard +marker processors in jdmarker.c for appropriate coding methods if you need to +use a suspending data source.) + +If you override the default APP0 or APP14 processors, it is up to you to +recognize JFIF and Adobe markers if you want colorspace recognition to occur +properly. We recommend copying and extending the default processors if you +want to do that. (A better idea is to save these marker types for later +examination by calling jpeg_save_markers(); that method doesn't interfere +with the library's own processing of these markers.) + +jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive +--- if you call one it overrides any previous call to the other, for the +particular marker type specified. + +A simple example of an external COM processor can be found in djpeg.c. +Also, see jpegtran.c for an example of using jpeg_save_markers. + + +Raw (downsampled) image data +---------------------------- + +Some applications need to supply already-downsampled image data to the JPEG +compressor, or to receive raw downsampled data from the decompressor. The +library supports this requirement by allowing the application to write or +read raw data, bypassing the normal preprocessing or postprocessing steps. +The interface is different from the standard one and is somewhat harder to +use. If your interest is merely in bypassing color conversion, we recommend +that you use the standard interface and simply set jpeg_color_space = +in_color_space (or jpeg_color_space = out_color_space for decompression). +The mechanism described in this section is necessary only to supply or +receive downsampled image data, in which not all components have the same +dimensions. + + +To compress raw data, you must supply the data in the colorspace to be used +in the JPEG file (please read the earlier section on Special color spaces) +and downsampled to the sampling factors specified in the JPEG parameters. +You must supply the data in the format used internally by the JPEG library, +namely a JSAMPIMAGE array. This is an array of pointers to two-dimensional +arrays, each of type JSAMPARRAY. Each 2-D array holds the values for one +color component. This structure is necessary since the components are of +different sizes. If the image dimensions are not a multiple of the MCU size, +you must also pad the data correctly (usually, this is done by replicating +the last column and/or row). The data must be padded to a multiple of a DCT +block in each component: that is, each downsampled row must contain a +multiple of 8 valid samples, and there must be a multiple of 8 sample rows +for each component. (For applications such as conversion of digital TV +images, the standard image size is usually a multiple of the DCT block size, +so that no padding need actually be done.) + +The procedure for compression of raw data is basically the same as normal +compression, except that you call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). Before calling jpeg_start_compress(), you must do +the following: + * Set cinfo->raw_data_in to TRUE. (It is set FALSE by jpeg_set_defaults().) + This notifies the library that you will be supplying raw data. + * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace() + call is a good idea. Note that since color conversion is bypassed, + in_color_space is ignored, except that jpeg_set_defaults() uses it to + choose the default jpeg_color_space setting. + * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and + cinfo->comp_info[i].v_samp_factor, are correct. Since these indicate the + dimensions of the data you are supplying, it's wise to set them + explicitly, rather than assuming the library's defaults are what you want. + +To pass raw data to the library, call jpeg_write_raw_data() in place of +jpeg_write_scanlines(). The two routines work similarly except that +jpeg_write_raw_data takes a JSAMPIMAGE data array rather than JSAMPARRAY. +The scanlines count passed to and returned from jpeg_write_raw_data is +measured in terms of the component with the largest v_samp_factor. + +jpeg_write_raw_data() processes one MCU row per call, which is to say +v_samp_factor*DCTSIZE sample rows of each component. The passed num_lines +value must be at least max_v_samp_factor*DCTSIZE, and the return value will +be exactly that amount (or possibly some multiple of that amount, in future +library versions). This is true even on the last call at the bottom of the +image; don't forget to pad your data as necessary. + +The required dimensions of the supplied data can be computed for each +component as + cinfo->comp_info[i].width_in_blocks*DCTSIZE samples per row + cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image +after jpeg_start_compress() has initialized those fields. If the valid data +is smaller than this, it must be padded appropriately. For some sampling +factors and image sizes, additional dummy DCT blocks are inserted to make +the image a multiple of the MCU dimensions. The library creates such dummy +blocks itself; it does not read them from your supplied data. Therefore you +need never pad by more than DCTSIZE samples. An example may help here. +Assume 2h2v downsampling of YCbCr data, that is + cinfo->comp_info[0].h_samp_factor = 2 for Y + cinfo->comp_info[0].v_samp_factor = 2 + cinfo->comp_info[1].h_samp_factor = 1 for Cb + cinfo->comp_info[1].v_samp_factor = 1 + cinfo->comp_info[2].h_samp_factor = 1 for Cr + cinfo->comp_info[2].v_samp_factor = 1 +and suppose that the nominal image dimensions (cinfo->image_width and +cinfo->image_height) are 101x101 pixels. Then jpeg_start_compress() will +compute downsampled_width = 101 and width_in_blocks = 13 for Y, +downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same +for the height fields). You must pad the Y data to at least 13*8 = 104 +columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows. The +MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16 +scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual +sample rows of Y and 8 each of Cb and Cr. A total of 7 MCU rows are needed, +so you must pass a total of 7*16 = 112 "scanlines". The last DCT block row +of Y data is dummy, so it doesn't matter what you pass for it in the data +arrays, but the scanlines count must total up to 112 so that all of the Cb +and Cr data gets passed. + +Output suspension is supported with raw-data compression: if the data +destination module suspends, jpeg_write_raw_data() will return 0. +In this case the same data rows must be passed again on the next call. + + +Decompression with raw data output implies bypassing all postprocessing: +you cannot ask for rescaling or color quantization, for instance. More +seriously, you must deal with the color space and sampling factors present in +the incoming file. If your application only handles, say, 2h1v YCbCr data, +you must check for and fail on other color spaces or other sampling factors. +The library will not convert to a different color space for you. + +To obtain raw data output, set cinfo->raw_data_out = TRUE before +jpeg_start_decompress() (it is set FALSE by jpeg_read_header()). Be sure to +verify that the color space and sampling factors are ones you can handle. +Then call jpeg_read_raw_data() in place of jpeg_read_scanlines(). The +decompression process is otherwise the same as usual. + +jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a +buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is +the same as for raw-data compression). The buffer you pass must be large +enough to hold the actual data plus padding to DCT-block boundaries. As with +compression, any entirely dummy DCT blocks are not processed so you need not +allocate space for them, but the total scanline count includes them. The +above example of computing buffer dimensions for raw-data compression is +equally valid for decompression. + +Input suspension is supported with raw-data decompression: if the data source +module suspends, jpeg_read_raw_data() will return 0. You can also use +buffered-image mode to read raw data in multiple passes. + + +Really raw data: DCT coefficients +--------------------------------- + +It is possible to read or write the contents of a JPEG file as raw DCT +coefficients. This facility is mainly intended for use in lossless +transcoding between different JPEG file formats. Other possible applications +include lossless cropping of a JPEG image, lossless reassembly of a +multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc. + +To read the contents of a JPEG file as DCT coefficients, open the file and do +jpeg_read_header() as usual. But instead of calling jpeg_start_decompress() +and jpeg_read_scanlines(), call jpeg_read_coefficients(). This will read the +entire image into a set of virtual coefficient-block arrays, one array per +component. The return value is a pointer to an array of virtual-array +descriptors. Each virtual array can be accessed directly using the JPEG +memory manager's access_virt_barray method (see Memory management, below, +and also read structure.doc's discussion of virtual array handling). Or, +for simple transcoding to a different JPEG file format, the array list can +just be handed directly to jpeg_write_coefficients(). + +Each block in the block arrays contains quantized coefficient values in +normal array order (not JPEG zigzag order). The block arrays contain only +DCT blocks containing real data; any entirely-dummy blocks added to fill out +interleaved MCUs at the right or bottom edges of the image are discarded +during reading and are not stored in the block arrays. (The size of each +block array can be determined from the width_in_blocks and height_in_blocks +fields of the component's comp_info entry.) This is also the data format +expected by jpeg_write_coefficients(). + +When you are done using the virtual arrays, call jpeg_finish_decompress() +to release the array storage and return the decompression object to an idle +state; or just call jpeg_destroy() if you don't need to reuse the object. + +If you use a suspending data source, jpeg_read_coefficients() will return +NULL if it is forced to suspend; a non-NULL return value indicates successful +completion. You need not test for a NULL return value when using a +non-suspending data source. + +It is also possible to call jpeg_read_coefficients() to obtain access to the +decoder's coefficient arrays during a normal decode cycle in buffered-image +mode. This frammish might be useful for progressively displaying an incoming +image and then re-encoding it without loss. To do this, decode in buffered- +image mode as discussed previously, then call jpeg_read_coefficients() after +the last jpeg_finish_output() call. The arrays will be available for your use +until you call jpeg_finish_decompress(). + + +To write the contents of a JPEG file as DCT coefficients, you must provide +the DCT coefficients stored in virtual block arrays. You can either pass +block arrays read from an input JPEG file by jpeg_read_coefficients(), or +allocate virtual arrays from the JPEG compression object and fill them +yourself. In either case, jpeg_write_coefficients() is substituted for +jpeg_start_compress() and jpeg_write_scanlines(). Thus the sequence is + * Create compression object + * Set all compression parameters as necessary + * Request virtual arrays if needed + * jpeg_write_coefficients() + * jpeg_finish_compress() + * Destroy or re-use compression object +jpeg_write_coefficients() is passed a pointer to an array of virtual block +array descriptors; the number of arrays is equal to cinfo.num_components. + +The virtual arrays need only have been requested, not realized, before +jpeg_write_coefficients() is called. A side-effect of +jpeg_write_coefficients() is to realize any virtual arrays that have been +requested from the compression object's memory manager. Thus, when obtaining +the virtual arrays from the compression object, you should fill the arrays +after calling jpeg_write_coefficients(). The data is actually written out +when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes +the file header. + +When writing raw DCT coefficients, it is crucial that the JPEG quantization +tables and sampling factors match the way the data was encoded, or the +resulting file will be invalid. For transcoding from an existing JPEG file, +we recommend using jpeg_copy_critical_parameters(). This routine initializes +all the compression parameters to default values (like jpeg_set_defaults()), +then copies the critical information from a source decompression object. +The decompression object should have just been used to read the entire +JPEG input file --- that is, it should be awaiting jpeg_finish_decompress(). + +jpeg_write_coefficients() marks all tables stored in the compression object +as needing to be written to the output file (thus, it acts like +jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid +emitting abbreviated JPEG files by accident. If you really want to emit an +abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables' +individual sent_table flags, between calling jpeg_write_coefficients() and +jpeg_finish_compress(). + + +Progress monitoring +------------------- + +Some applications may need to regain control from the JPEG library every so +often. The typical use of this feature is to produce a percent-done bar or +other progress display. (For a simple example, see cjpeg.c or djpeg.c.) +Although you do get control back frequently during the data-transferring pass +(the jpeg_read_scanlines or jpeg_write_scanlines loop), any additional passes +will occur inside jpeg_finish_compress or jpeg_start_decompress; those +routines may take a long time to execute, and you don't get control back +until they are done. + +You can define a progress-monitor routine which will be called periodically +by the library. No guarantees are made about how often this call will occur, +so we don't recommend you use it for mouse tracking or anything like that. +At present, a call will occur once per MCU row, scanline, or sample row +group, whichever unit is convenient for the current processing mode; so the +wider the image, the longer the time between calls. During the data +transferring pass, only one call occurs per call of jpeg_read_scanlines or +jpeg_write_scanlines, so don't pass a large number of scanlines at once if +you want fine resolution in the progress count. (If you really need to use +the callback mechanism for time-critical tasks like mouse tracking, you could +insert additional calls inside some of the library's inner loops.) + +To establish a progress-monitor callback, create a struct jpeg_progress_mgr, +fill in its progress_monitor field with a pointer to your callback routine, +and set cinfo->progress to point to the struct. The callback will be called +whenever cinfo->progress is non-NULL. (This pointer is set to NULL by +jpeg_create_compress or jpeg_create_decompress; the library will not change +it thereafter. So if you allocate dynamic storage for the progress struct, +make sure it will live as long as the JPEG object does. Allocating from the +JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.) You +can use the same callback routine for both compression and decompression. + +The jpeg_progress_mgr struct contains four fields which are set by the library: + long pass_counter; /* work units completed in this pass */ + long pass_limit; /* total number of work units in this pass */ + int completed_passes; /* passes completed so far */ + int total_passes; /* total number of passes expected */ +During any one pass, pass_counter increases from 0 up to (not including) +pass_limit; the step size is usually but not necessarily 1. The pass_limit +value may change from one pass to another. The expected total number of +passes is in total_passes, and the number of passes already completed is in +completed_passes. Thus the fraction of work completed may be estimated as + completed_passes + (pass_counter/pass_limit) + -------------------------------------------- + total_passes +ignoring the fact that the passes may not be equal amounts of work. + +When decompressing, pass_limit can even change within a pass, because it +depends on the number of scans in the JPEG file, which isn't always known in +advance. The computed fraction-of-work-done may jump suddenly (if the library +discovers it has overestimated the number of scans) or even decrease (in the +opposite case). It is not wise to put great faith in the work estimate. + +When using the decompressor's buffered-image mode, the progress monitor work +estimate is likely to be completely unhelpful, because the library has no way +to know how many output passes will be demanded of it. Currently, the library +sets total_passes based on the assumption that there will be one more output +pass if the input file end hasn't yet been read (jpeg_input_complete() isn't +TRUE), but no more output passes if the file end has been reached when the +output pass is started. This means that total_passes will rise as additional +output passes are requested. If you have a way of determining the input file +size, estimating progress based on the fraction of the file that's been read +will probably be more useful than using the library's value. + + +Memory management +----------------- + +This section covers some key facts about the JPEG library's built-in memory +manager. For more info, please read structure.doc's section about the memory +manager, and consult the source code if necessary. + +All memory and temporary file allocation within the library is done via the +memory manager. If necessary, you can replace the "back end" of the memory +manager to control allocation yourself (for example, if you don't want the +library to use malloc() and free() for some reason). + +Some data is allocated "permanently" and will not be freed until the JPEG +object is destroyed. Most data is allocated "per image" and is freed by +jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the +memory manager yourself to allocate structures that will automatically be +freed at these times. Typical code for this is + ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size); +Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object. +Use alloc_large instead of alloc_small for anything bigger than a few Kbytes. +There are also alloc_sarray and alloc_barray routines that automatically +build 2-D sample or block arrays. + +The library's minimum space requirements to process an image depend on the +image's width, but not on its height, because the library ordinarily works +with "strip" buffers that are as wide as the image but just a few rows high. +Some operating modes (eg, two-pass color quantization) require full-image +buffers. Such buffers are treated as "virtual arrays": only the current strip +need be in memory, and the rest can be swapped out to a temporary file. + +If you use the simplest memory manager back end (jmemnobs.c), then no +temporary files are used; virtual arrays are simply malloc()'d. Images bigger +than memory can be processed only if your system supports virtual memory. +The other memory manager back ends support temporary files of various flavors +and thus work in machines without virtual memory. They may also be useful on +Unix machines if you need to process images that exceed available swap space. + +When using temporary files, the library will make the in-memory buffers for +its virtual arrays just big enough to stay within a "maximum memory" setting. +Your application can set this limit by setting cinfo->mem->max_memory_to_use +after creating the JPEG object. (Of course, there is still a minimum size for +the buffers, so the max-memory setting is effective only if it is bigger than +the minimum space needed.) If you allocate any large structures yourself, you +must allocate them before jpeg_start_compress() or jpeg_start_decompress() in +order to have them counted against the max memory limit. Also keep in mind +that space allocated with alloc_small() is ignored, on the assumption that +it's too small to be worth worrying about; so a reasonable safety margin +should be left when setting max_memory_to_use. + +If you use the jmemname.c or jmemdos.c memory manager back end, it is +important to clean up the JPEG object properly to ensure that the temporary +files get deleted. (This is especially crucial with jmemdos.c, where the +"temporary files" may be extended-memory segments; if they are not freed, +DOS will require a reboot to recover the memory.) Thus, with these memory +managers, it's a good idea to provide a signal handler that will trap any +early exit from your program. The handler should call either jpeg_abort() +or jpeg_destroy() for any active JPEG objects. A handler is not needed with +jmemnobs.c, and shouldn't be necessary with jmemansi.c or jmemmac.c either, +since the C library is supposed to take care of deleting files made with +tmpfile(). + + +Memory usage +------------ + +Working memory requirements while performing compression or decompression +depend on image dimensions, image characteristics (such as colorspace and +JPEG process), and operating mode (application-selected options). + +As of v6b, the decompressor requires: + 1. About 24K in more-or-less-fixed-size data. This varies a bit depending + on operating mode and image characteristics (particularly color vs. + grayscale), but it doesn't depend on image dimensions. + 2. Strip buffers (of size proportional to the image width) for IDCT and + upsampling results. The worst case for commonly used sampling factors + is about 34 bytes * width in pixels for a color image. A grayscale image + only needs about 8 bytes per pixel column. + 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG + file (including progressive JPEGs), or whenever you select buffered-image + mode. This takes 2 bytes/coefficient. At typical 2x2 sampling, that's + 3 bytes per pixel for a color image. Worst case (1x1 sampling) requires + 6 bytes/pixel. For grayscale, figure 2 bytes/pixel. + 4. To perform 2-pass color quantization, the decompressor also needs a + 128K color lookup table and a full-image pixel buffer (3 bytes/pixel). +This does not count any memory allocated by the application, such as a +buffer to hold the final output image. + +The above figures are valid for 8-bit JPEG data precision and a machine with +32-bit ints. For 12-bit JPEG data, double the size of the strip buffers and +quantization pixel buffer. The "fixed-size" data will be somewhat smaller +with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual +color spaces will require different amounts of space. + +The full-image coefficient and pixel buffers, if needed at all, do not +have to be fully RAM resident; you can have the library use temporary +files instead when the total memory usage would exceed a limit you set. +(But if your OS supports virtual memory, it's probably better to just use +jmemnobs and let the OS do the swapping.) + +The compressor's memory requirements are similar, except that it has no need +for color quantization. Also, it needs a full-image DCT coefficient buffer +if Huffman-table optimization is asked for, even if progressive mode is not +requested. + +If you need more detailed information about memory usage in a particular +situation, you can enable the MEM_STATS code in jmemmgr.c. + + +Library compile-time options +---------------------------- + +A number of compile-time options are available by modifying jmorecfg.h. + +The JPEG standard provides for both the baseline 8-bit DCT process and +a 12-bit DCT process. The IJG code supports 12-bit lossy JPEG if you define +BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be +larger than a char, so it affects the surrounding application's image data. +The sample applications cjpeg and djpeg can support 12-bit mode only for PPM +and GIF file formats; you must disable the other file formats to compile a +12-bit cjpeg or djpeg. (install.doc has more information about that.) +At present, a 12-bit library can handle *only* 12-bit images, not both +precisions. (If you need to include both 8- and 12-bit libraries in a single +application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES +for just one of the copies. You'd have to access the 8-bit and 12-bit copies +from separate application source files. This is untested ... if you try it, +we'd like to hear whether it works!) + +Note that a 12-bit library always compresses in Huffman optimization mode, +in order to generate valid Huffman tables. This is necessary because our +default Huffman tables only cover 8-bit data. If you need to output 12-bit +files in one pass, you'll have to supply suitable default Huffman tables. +You may also want to supply your own DCT quantization tables; the existing +quality-scaling code has been developed for 8-bit use, and probably doesn't +generate especially good tables for 12-bit. + +The maximum number of components (color channels) in the image is determined +by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we +expect that few applications will need more than four or so. + +On machines with unusual data type sizes, you may be able to improve +performance or reduce memory space by tweaking the various typedefs in +jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s +is quite slow; consider trading memory for speed by making JCOEF, INT16, and +UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int. +You probably don't want to make JSAMPLE be int unless you have lots of memory +to burn. + +You can reduce the size of the library by compiling out various optional +functions. To do this, undefine xxx_SUPPORTED symbols as necessary. + +You can also save a few K by not having text error messages in the library; +the standard error message table occupies about 5Kb. This is particularly +reasonable for embedded applications where there's no good way to display +a message anyway. To do this, remove the creation of the message table +(jpeg_std_message_table[]) from jerror.c, and alter format_message to do +something reasonable without it. You could output the numeric value of the +message code number, for example. If you do this, you can also save a couple +more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing; +you don't need trace capability anyway, right? + + +Portability considerations +-------------------------- + +The JPEG library has been written to be extremely portable; the sample +applications cjpeg and djpeg are slightly less so. This section summarizes +the design goals in this area. (If you encounter any bugs that cause the +library to be less portable than is claimed here, we'd appreciate hearing +about them.) + +The code works fine on ANSI C, C++, and pre-ANSI C compilers, using any of +the popular system include file setups, and some not-so-popular ones too. +See install.doc for configuration procedures. + +The code is not dependent on the exact sizes of the C data types. As +distributed, we make the assumptions that + char is at least 8 bits wide + short is at least 16 bits wide + int is at least 16 bits wide + long is at least 32 bits wide +(These are the minimum requirements of the ANSI C standard.) Wider types will +work fine, although memory may be used inefficiently if char is much larger +than 8 bits or short is much bigger than 16 bits. The code should work +equally well with 16- or 32-bit ints. + +In a system where these assumptions are not met, you may be able to make the +code work by modifying the typedefs in jmorecfg.h. However, you will probably +have difficulty if int is less than 16 bits wide, since references to plain +int abound in the code. + +char can be either signed or unsigned, although the code runs faster if an +unsigned char type is available. If char is wider than 8 bits, you will need +to redefine JOCTET and/or provide custom data source/destination managers so +that JOCTET represents exactly 8 bits of data on external storage. + +The JPEG library proper does not assume ASCII representation of characters. +But some of the image file I/O modules in cjpeg/djpeg do have ASCII +dependencies in file-header manipulation; so does cjpeg's select_file_type() +routine. + +The JPEG library does not rely heavily on the C library. In particular, C +stdio is used only by the data source/destination modules and the error +handler, all of which are application-replaceable. (cjpeg/djpeg are more +heavily dependent on stdio.) malloc and free are called only from the memory +manager "back end" module, so you can use a different memory allocator by +replacing that one file. + +The code generally assumes that C names must be unique in the first 15 +characters. However, global function names can be made unique in the +first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES. + +More info about porting the code may be gleaned by reading jconfig.doc, +jmorecfg.h, and jinclude.h. + + +Notes for MS-DOS implementors +----------------------------- + +The IJG code is designed to work efficiently in 80x86 "small" or "medium" +memory models (i.e., data pointers are 16 bits unless explicitly declared +"far"; code pointers can be either size). You may be able to use small +model to compile cjpeg or djpeg by itself, but you will probably have to use +medium model for any larger application. This won't make much difference in +performance. You *will* take a noticeable performance hit if you use a +large-data memory model (perhaps 10%-25%), and you should avoid "huge" model +if at all possible. + +The JPEG library typically needs 2Kb-3Kb of stack space. It will also +malloc about 20K-30K of near heap space while executing (and lots of far +heap, but that doesn't count in this calculation). This figure will vary +depending on selected operating mode, and to a lesser extent on image size. +There is also about 5Kb-6Kb of constant data which will be allocated in the +near data segment (about 4Kb of this is the error message table). +Thus you have perhaps 20K available for other modules' static data and near +heap space before you need to go to a larger memory model. The C library's +static data will account for several K of this, but that still leaves a good +deal for your needs. (If you are tight on space, you could reduce the sizes +of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to +1K. Another possibility is to move the error message table to far memory; +this should be doable with only localized hacking on jerror.c.) + +About 2K of the near heap space is "permanent" memory that will not be +released until you destroy the JPEG object. This is only an issue if you +save a JPEG object between compression or decompression operations. + +Far data space may also be a tight resource when you are dealing with large +images. The most memory-intensive case is decompression with two-pass color +quantization, or single-pass quantization to an externally supplied color +map. This requires a 128Kb color lookup table plus strip buffers amounting +to about 40 bytes per column for typical sampling ratios (eg, about 25600 +bytes for a 640-pixel-wide image). You may not be able to process wide +images if you have large data structures of your own. + +Of course, all of these concerns vanish if you use a 32-bit flat-memory-model +compiler, such as DJGPP or Watcom C. We highly recommend flat model if you +can use it; the JPEG library is significantly faster in flat model. diff --git a/Utilities/vtkjpeg/structure.doc b/Utilities/vtkjpeg/structure.doc new file mode 100644 index 0000000..4179e48 --- /dev/null +++ b/Utilities/vtkjpeg/structure.doc @@ -0,0 +1,948 @@ +IJG JPEG LIBRARY: SYSTEM ARCHITECTURE + +Copyright (C) 1991-1995, Thomas G. Lane. +This file is part of the Independent JPEG Group's software. +For conditions of distribution and use, see the accompanying README file. + + +This file provides an overview of the architecture of the IJG JPEG software; +that is, the functions of the various modules in the system and the interfaces +between modules. For more precise details about any data structure or calling +convention, see the include files and comments in the source code. + +We assume that the reader is already somewhat familiar with the JPEG standard. +The README file includes references for learning about JPEG. The file +libjpeg.doc describes the library from the viewpoint of an application +programmer using the library; it's best to read that file before this one. +Also, the file coderules.doc describes the coding style conventions we use. + +In this document, JPEG-specific terminology follows the JPEG standard: + A "component" means a color channel, e.g., Red or Luminance. + A "sample" is a single component value (i.e., one number in the image data). + A "coefficient" is a frequency coefficient (a DCT transform output number). + A "block" is an 8x8 group of samples or coefficients. + An "MCU" (minimum coded unit) is an interleaved set of blocks of size + determined by the sampling factors, or a single block in a + noninterleaved scan. +We do not use the terms "pixel" and "sample" interchangeably. When we say +pixel, we mean an element of the full-size image, while a sample is an element +of the downsampled image. Thus the number of samples may vary across +components while the number of pixels does not. (This terminology is not used +rigorously throughout the code, but it is used in places where confusion would +otherwise result.) + + +*** System features *** + +The IJG distribution contains two parts: + * A subroutine library for JPEG compression and decompression. + * cjpeg/djpeg, two sample applications that use the library to transform + JFIF JPEG files to and from several other image formats. +cjpeg/djpeg are of no great intellectual complexity: they merely add a simple +command-line user interface and I/O routines for several uncompressed image +formats. This document concentrates on the library itself. + +We desire the library to be capable of supporting all JPEG baseline, extended +sequential, and progressive DCT processes. Hierarchical processes are not +supported. + +The library does not support the lossless (spatial) JPEG process. Lossless +JPEG shares little or no code with lossy JPEG, and would normally be used +without the extensive pre- and post-processing provided by this library. +We feel that lossless JPEG is better handled by a separate library. + +Within these limits, any set of compression parameters allowed by the JPEG +spec should be readable for decompression. (We can be more restrictive about +what formats we can generate.) Although the system design allows for all +parameter values, some uncommon settings are not yet implemented and may +never be; nonintegral sampling ratios are the prime example. Furthermore, +we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a +run-time option, because most machines can store 8-bit pixels much more +compactly than 12-bit. + +For legal reasons, JPEG arithmetic coding is not currently supported, but +extending the library to include it would be straightforward. + +By itself, the library handles only interchange JPEG datastreams --- in +particular the widely used JFIF file format. The library can be used by +surrounding code to process interchange or abbreviated JPEG datastreams that +are embedded in more complex file formats. (For example, libtiff uses this +library to implement JPEG compression within the TIFF file format.) + +The library includes a substantial amount of code that is not covered by the +JPEG standard but is necessary for typical applications of JPEG. These +functions preprocess the image before JPEG compression or postprocess it after +decompression. They include colorspace conversion, downsampling/upsampling, +and color quantization. This code can be omitted if not needed. + +A wide range of quality vs. speed tradeoffs are possible in JPEG processing, +and even more so in decompression postprocessing. The decompression library +provides multiple implementations that cover most of the useful tradeoffs, +ranging from very-high-quality down to fast-preview operation. On the +compression side we have generally not provided low-quality choices, since +compression is normally less time-critical. It should be understood that the +low-quality modes may not meet the JPEG standard's accuracy requirements; +nonetheless, they are useful for viewers. + + +*** Portability issues *** + +Portability is an essential requirement for the library. The key portability +issues that show up at the level of system architecture are: + +1. Memory usage. We want the code to be able to run on PC-class machines +with limited memory. Images should therefore be processed sequentially (in +strips), to avoid holding the whole image in memory at once. Where a +full-image buffer is necessary, we should be able to use either virtual memory +or temporary files. + +2. Near/far pointer distinction. To run efficiently on 80x86 machines, the +code should distinguish "small" objects (kept in near data space) from +"large" ones (kept in far data space). This is an annoying restriction, but +fortunately it does not impact code quality for less brain-damaged machines, +and the source code clutter turns out to be minimal with sufficient use of +pointer typedefs. + +3. Data precision. We assume that "char" is at least 8 bits, "short" and +"int" at least 16, "long" at least 32. The code will work fine with larger +data sizes, although memory may be used inefficiently in some cases. However, +the JPEG compressed datastream must ultimately appear on external storage as a +sequence of 8-bit bytes if it is to conform to the standard. This may pose a +problem on machines where char is wider than 8 bits. The library represents +compressed data as an array of values of typedef JOCTET. If no data type +exactly 8 bits wide is available, custom data source and data destination +modules must be written to unpack and pack the chosen JOCTET datatype into +8-bit external representation. + + +*** System overview *** + +The compressor and decompressor are each divided into two main sections: +the JPEG compressor or decompressor proper, and the preprocessing or +postprocessing functions. The interface between these two sections is the +image data that the official JPEG spec regards as its input or output: this +data is in the colorspace to be used for compression, and it is downsampled +to the sampling factors to be used. The preprocessing and postprocessing +steps are responsible for converting a normal image representation to or from +this form. (Those few applications that want to deal with YCbCr downsampled +data can skip the preprocessing or postprocessing step.) + +Looking more closely, the compressor library contains the following main +elements: + + Preprocessing: + * Color space conversion (e.g., RGB to YCbCr). + * Edge expansion and downsampling. Optionally, this step can do simple + smoothing --- this is often helpful for low-quality source data. + JPEG proper: + * MCU assembly, DCT, quantization. + * Entropy coding (sequential or progressive, Huffman or arithmetic). + +In addition to these modules we need overall control, marker generation, +and support code (memory management & error handling). There is also a +module responsible for physically writing the output data --- typically +this is just an interface to fwrite(), but some applications may need to +do something else with the data. + +The decompressor library contains the following main elements: + + JPEG proper: + * Entropy decoding (sequential or progressive, Huffman or arithmetic). + * Dequantization, inverse DCT, MCU disassembly. + Postprocessing: + * Upsampling. Optionally, this step may be able to do more general + rescaling of the image. + * Color space conversion (e.g., YCbCr to RGB). This step may also + provide gamma adjustment [ currently it does not ]. + * Optional color quantization (e.g., reduction to 256 colors). + * Optional color precision reduction (e.g., 24-bit to 15-bit color). + [This feature is not currently implemented.] + +We also need overall control, marker parsing, and a data source module. +The support code (memory management & error handling) can be shared with +the compression half of the library. + +There may be several implementations of each of these elements, particularly +in the decompressor, where a wide range of speed/quality tradeoffs is very +useful. It must be understood that some of the best speedups involve +merging adjacent steps in the pipeline. For example, upsampling, color space +conversion, and color quantization might all be done at once when using a +low-quality ordered-dither technique. The system architecture is designed to +allow such merging where appropriate. + + +Note: it is convenient to regard edge expansion (padding to block boundaries) +as a preprocessing/postprocessing function, even though the JPEG spec includes +it in compression/decompression. We do this because downsampling/upsampling +can be simplified a little if they work on padded data: it's not necessary to +have special cases at the right and bottom edges. Therefore the interface +buffer is always an integral number of blocks wide and high, and we expect +compression preprocessing to pad the source data properly. Padding will occur +only to the next block (8-sample) boundary. In an interleaved-scan situation, +additional dummy blocks may be used to fill out MCUs, but the MCU assembly and +disassembly logic will create or discard these blocks internally. (This is +advantageous for speed reasons, since we avoid DCTing the dummy blocks. +It also permits a small reduction in file size, because the compressor can +choose dummy block contents so as to minimize their size in compressed form. +Finally, it makes the interface buffer specification independent of whether +the file is actually interleaved or not.) Applications that wish to deal +directly with the downsampled data must provide similar buffering and padding +for odd-sized images. + + +*** Poor man's object-oriented programming *** + +It should be clear by now that we have a lot of quasi-independent processing +steps, many of which have several possible behaviors. To avoid cluttering the +code with lots of switch statements, we use a simple form of object-style +programming to separate out the different possibilities. + +For example, two different color quantization algorithms could be implemented +as two separate modules that present the same external interface; at runtime, +the calling code will access the proper module indirectly through an "object". + +We can get the limited features we need while staying within portable C. +The basic tool is a function pointer. An "object" is just a struct +containing one or more function pointer fields, each of which corresponds to +a method name in real object-oriented languages. During initialization we +fill in the function pointers with references to whichever module we have +determined we need to use in this run. Then invocation of the module is done +by indirecting through a function pointer; on most machines this is no more +expensive than a switch statement, which would be the only other way of +making the required run-time choice. The really significant benefit, of +course, is keeping the source code clean and well structured. + +We can also arrange to have private storage that varies between different +implementations of the same kind of object. We do this by making all the +module-specific object structs be separately allocated entities, which will +be accessed via pointers in the master compression or decompression struct. +The "public" fields or methods for a given kind of object are specified by +a commonly known struct. But a module's initialization code can allocate +a larger struct that contains the common struct as its first member, plus +additional private fields. With appropriate pointer casting, the module's +internal functions can access these private fields. (For a simple example, +see jdatadst.c, which implements the external interface specified by struct +jpeg_destination_mgr, but adds extra fields.) + +(Of course this would all be a lot easier if we were using C++, but we are +not yet prepared to assume that everyone has a C++ compiler.) + +An important benefit of this scheme is that it is easy to provide multiple +versions of any method, each tuned to a particular case. While a lot of +precalculation might be done to select an optimal implementation of a method, +the cost per invocation is constant. For example, the upsampling step might +have a "generic" method, plus one or more "hardwired" methods for the most +popular sampling factors; the hardwired methods would be faster because they'd +use straight-line code instead of for-loops. The cost to determine which +method to use is paid only once, at startup, and the selection criteria are +hidden from the callers of the method. + +This plan differs a little bit from usual object-oriented structures, in that +only one instance of each object class will exist during execution. The +reason for having the class structure is that on different runs we may create +different instances (choose to execute different modules). You can think of +the term "method" as denoting the common interface presented by a particular +set of interchangeable functions, and "object" as denoting a group of related +methods, or the total shared interface behavior of a group of modules. + + +*** Overall control structure *** + +We previously mentioned the need for overall control logic in the compression +and decompression libraries. In IJG implementations prior to v5, overall +control was mostly provided by "pipeline control" modules, which proved to be +large, unwieldy, and hard to understand. To improve the situation, the +control logic has been subdivided into multiple modules. The control modules +consist of: + +1. Master control for module selection and initialization. This has two +responsibilities: + + 1A. Startup initialization at the beginning of image processing. + The individual processing modules to be used in this run are selected + and given initialization calls. + + 1B. Per-pass control. This determines how many passes will be performed + and calls each active processing module to configure itself + appropriately at the beginning of each pass. End-of-pass processing, + where necessary, is also invoked from the master control module. + + Method selection is partially distributed, in that a particular processing + module may contain several possible implementations of a particular method, + which it will select among when given its initialization call. The master + control code need only be concerned with decisions that affect more than + one module. + +2. Data buffering control. A separate control module exists for each + inter-processing-step data buffer. This module is responsible for + invoking the processing steps that write or read that data buffer. + +Each buffer controller sees the world as follows: + +input data => processing step A => buffer => processing step B => output data + | | | + ------------------ controller ------------------ + +The controller knows the dataflow requirements of steps A and B: how much data +they want to accept in one chunk and how much they output in one chunk. Its +function is to manage its buffer and call A and B at the proper times. + +A data buffer control module may itself be viewed as a processing step by a +higher-level control module; thus the control modules form a binary tree with +elementary processing steps at the leaves of the tree. + +The control modules are objects. A considerable amount of flexibility can +be had by replacing implementations of a control module. For example: +* Merging of adjacent steps in the pipeline is done by replacing a control + module and its pair of processing-step modules with a single processing- + step module. (Hence the possible merges are determined by the tree of + control modules.) +* In some processing modes, a given interstep buffer need only be a "strip" + buffer large enough to accommodate the desired data chunk sizes. In other + modes, a full-image buffer is needed and several passes are required. + The control module determines which kind of buffer is used and manipulates + virtual array buffers as needed. One or both processing steps may be + unaware of the multi-pass behavior. + +In theory, we might be able to make all of the data buffer controllers +interchangeable and provide just one set of implementations for all. In +practice, each one contains considerable special-case processing for its +particular job. The buffer controller concept should be regarded as an +overall system structuring principle, not as a complete description of the +task performed by any one controller. + + +*** Compression object structure *** + +Here is a sketch of the logical structure of the JPEG compression library: + + |-- Colorspace conversion + |-- Preprocessing controller --| + | |-- Downsampling +Main controller --| + | |-- Forward DCT, quantize + |-- Coefficient controller --| + |-- Entropy encoding + +This sketch also describes the flow of control (subroutine calls) during +typical image data processing. Each of the components shown in the diagram is +an "object" which may have several different implementations available. One +or more source code files contain the actual implementation(s) of each object. + +The objects shown above are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the preprocessed input data. This controller invokes preprocessing to + fill the subsampled-data buffer, and JPEG compression to empty it. There is + usually no need for a full-image buffer here; a strip buffer is adequate. + +* Preprocessing controller: buffer controller for the downsampling input data + buffer, which lies between colorspace conversion and downsampling. Note + that a unified conversion/downsampling module would probably replace this + controller entirely. + +* Colorspace conversion: converts application image data into the desired + JPEG color space; also changes the data from pixel-interleaved layout to + separate component planes. Processes one pixel row at a time. + +* Downsampling: performs reduction of chroma components as required. + Optionally may perform pixel-level smoothing as well. Processes a "row + group" at a time, where a row group is defined as Vmax pixel rows of each + component before downsampling, and Vk sample rows afterwards (remember Vk + differs across components). Some downsampling or smoothing algorithms may + require context rows above and below the current row group; the + preprocessing controller is responsible for supplying these rows via proper + buffering. The downsampler is responsible for edge expansion at the right + edge (i.e., extending each sample row to a multiple of 8 samples); but the + preprocessing controller is responsible for vertical edge expansion (i.e., + duplicating the bottom sample row as needed to make a multiple of 8 rows). + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU assembly, including insertion of dummy DCT + blocks when needed at the right or bottom edge. When performing + Huffman-code optimization or emitting a multiscan JPEG file, this + controller is responsible for buffering the full image. The equivalent of + one fully interleaved MCU row of subsampled data is processed per call, + even when the JPEG file is noninterleaved. + +* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients. + Works on one or more DCT blocks at a time. (Note: the coefficients are now + emitted in normal array order, which the entropy encoder is expected to + convert to zigzag order as necessary. Prior versions of the IJG code did + the conversion to zigzag order within the quantization step.) + +* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the + coded data to the data destination module. Works on one MCU per call. + For progressive JPEG, the same DCT blocks are fed to the entropy coder + during each pass, and the coder must emit the appropriate subset of + coefficients. + +In addition to the above objects, the compression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. + +* Marker writing: generates JPEG markers (except for RSTn, which is emitted + by the entropy encoder when needed). + +* Data destination manager: writes the output JPEG datastream to its final + destination (e.g., a file). The destination manager supplied with the + library knows how to write to a stdio stream; for other behaviors, the + surrounding application may provide its own destination manager. + +* Memory manager: allocates and releases memory, controls virtual arrays + (with backing store management, where required). + +* Error handler: performs formatting and output of error and trace messages; + determines handling of nonfatal errors. The surrounding application may + override some or all of this object's methods to change error handling. + +* Progress monitor: supports output of "percent-done" progress reports. + This object represents an optional callback to the surrounding application: + if wanted, it must be supplied by the application. + +The error handler, destination manager, and progress monitor objects are +defined as separate objects in order to simplify application-specific +customization of the JPEG library. A surrounding application may override +individual methods or supply its own all-new implementation of one of these +objects. The object interfaces for these objects are therefore treated as +part of the application interface of the library, whereas the other objects +are internal to the library. + +The error handler and memory manager are shared by JPEG compression and +decompression; the progress monitor, if used, may be shared as well. + + +*** Decompression object structure *** + +Here is a sketch of the logical structure of the JPEG decompression library: + + |-- Entropy decoding + |-- Coefficient controller --| + | |-- Dequantize, Inverse DCT +Main controller --| + | |-- Upsampling + |-- Postprocessing controller --| |-- Colorspace conversion + |-- Color quantization + |-- Color precision reduction + +As before, this diagram also represents typical control flow. The objects +shown are: + +* Main controller: buffer controller for the subsampled-data buffer, which + holds the output of JPEG decompression proper. This controller's primary + task is to feed the postprocessing procedure. Some upsampling algorithms + may require context rows above and below the current row group; when this + is true, the main controller is responsible for managing its buffer so as + to make context rows available. In the current design, the main buffer is + always a strip buffer; a full-image buffer is never required. + +* Coefficient controller: buffer controller for the DCT-coefficient data. + This controller handles MCU disassembly, including deletion of any dummy + DCT blocks at the right or bottom edge. When reading a multiscan JPEG + file, this controller is responsible for buffering the full image. + (Buffering DCT coefficients, rather than samples, is necessary to support + progressive JPEG.) The equivalent of one fully interleaved MCU row of + subsampled data is processed per call, even when the source JPEG file is + noninterleaved. + +* Entropy decoding: Read coded data from the data source module and perform + Huffman or arithmetic entropy decoding. Works on one MCU per call. + For progressive JPEG decoding, the coefficient controller supplies the prior + coefficients of each MCU (initially all zeroes), which the entropy decoder + modifies in each scan. + +* Dequantization and inverse DCT: like it says. Note that the coefficients + buffered by the coefficient controller have NOT been dequantized; we + merge dequantization and inverse DCT into a single step for speed reasons. + When scaled-down output is asked for, simplified DCT algorithms may be used + that emit only 1x1, 2x2, or 4x4 samples per DCT block, not the full 8x8. + Works on one DCT block at a time. + +* Postprocessing controller: buffer controller for the color quantization + input buffer, when quantization is in use. (Without quantization, this + controller just calls the upsampler.) For two-pass quantization, this + controller is responsible for buffering the full-image data. + +* Upsampling: restores chroma components to full size. (May support more + general output rescaling, too. Note that if undersized DCT outputs have + been emitted by the DCT module, this module must adjust so that properly + sized outputs are created.) Works on one row group at a time. This module + also calls the color conversion module, so its top level is effectively a + buffer controller for the upsampling->color conversion buffer. However, in + all but the highest-quality operating modes, upsampling and color + conversion are likely to be merged into a single step. + +* Colorspace conversion: convert from JPEG color space to output color space, + and change data layout from separate component planes to pixel-interleaved. + Works on one pixel row at a time. + +* Color quantization: reduce the data to colormapped form, using either an + externally specified colormap or an internally generated one. This module + is not used for full-color output. Works on one pixel row at a time; may + require two passes to generate a color map. Note that the output will + always be a single component representing colormap indexes. In the current + design, the output values are JSAMPLEs, so an 8-bit compilation cannot + quantize to more than 256 colors. This is unlikely to be a problem in + practice. + +* Color reduction: this module handles color precision reduction, e.g., + generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. + Not quite clear yet how this should be handled... should we merge it with + colorspace conversion??? + +Note that some high-speed operating modes might condense the entire +postprocessing sequence to a single module (upsample, color convert, and +quantize in one step). + +In addition to the above objects, the decompression library includes these +objects: + +* Master control: determines the number of passes required, controls overall + and per-pass initialization of the other modules. This is subdivided into + input and output control: jdinput.c controls only input-side processing, + while jdmaster.c handles overall initialization and output-side control. + +* Marker reading: decodes JPEG markers (except for RSTn). + +* Data source manager: supplies the input JPEG datastream. The source + manager supplied with the library knows how to read from a stdio stream; + for other behaviors, the surrounding application may provide its own source + manager. + +* Memory manager: same as for compression library. + +* Error handler: same as for compression library. + +* Progress monitor: same as for compression library. + +As with compression, the data source manager, error handler, and progress +monitor are candidates for replacement by a surrounding application. + + +*** Decompression input and output separation *** + +To support efficient incremental display of progressive JPEG files, the +decompressor is divided into two sections that can run independently: + +1. Data input includes marker parsing, entropy decoding, and input into the + coefficient controller's DCT coefficient buffer. Note that this + processing is relatively cheap and fast. + +2. Data output reads from the DCT coefficient buffer and performs the IDCT + and all postprocessing steps. + +For a progressive JPEG file, the data input processing is allowed to get +arbitrarily far ahead of the data output processing. (This occurs only +if the application calls jpeg_consume_input(); otherwise input and output +run in lockstep, since the input section is called only when the output +section needs more data.) In this way the application can avoid making +extra display passes when data is arriving faster than the display pass +can run. Furthermore, it is possible to abort an output pass without +losing anything, since the coefficient buffer is read-only as far as the +output section is concerned. See libjpeg.doc for more detail. + +A full-image coefficient array is only created if the JPEG file has multiple +scans (or if the application specifies buffered-image mode anyway). When +reading a single-scan file, the coefficient controller normally creates only +a one-MCU buffer, so input and output processing must run in lockstep in this +case. jpeg_consume_input() is effectively a no-op in this situation. + +The main impact of dividing the decompressor in this fashion is that we must +be very careful with shared variables in the cinfo data structure. Each +variable that can change during the course of decompression must be +classified as belonging to data input or data output, and each section must +look only at its own variables. For example, the data output section may not +depend on any of the variables that describe the current scan in the JPEG +file, because these may change as the data input section advances into a new +scan. + +The progress monitor is (somewhat arbitrarily) defined to treat input of the +file as one pass when buffered-image mode is not used, and to ignore data +input work completely when buffered-image mode is used. Note that the +library has no reliable way to predict the number of passes when dealing +with a progressive JPEG file, nor can it predict the number of output passes +in buffered-image mode. So the work estimate is inherently bogus anyway. + +No comparable division is currently made in the compression library, because +there isn't any real need for it. + + +*** Data formats *** + +Arrays of pixel sample values use the following data structure: + + typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE + typedef JSAMPLE *JSAMPROW; ptr to a row of samples + typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows + typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays + +The basic element type JSAMPLE will typically be one of unsigned char, +(signed) char, or short. Short will be used if samples wider than 8 bits are +to be supported (this is a compile-time option). Otherwise, unsigned char is +used if possible. If the compiler only supports signed chars, then it is +necessary to mask off the value when reading. Thus, all reads of JSAMPLE +values must be coded as "GETJSAMPLE(value)", where the macro will be defined +as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere. + +With these conventions, JSAMPLE values can be assumed to be >= 0. This helps +simplify correct rounding during downsampling, etc. The JPEG standard's +specification that sample values run from -128..127 is accommodated by +subtracting 128 just as the sample value is copied into the source array for +the DCT step (this will be an array of signed ints). Similarly, during +decompression the output of the IDCT step will be immediately shifted back to +0..255. (NB: different values are required when 12-bit samples are in use. +The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be +defined as 255 and 128 respectively in an 8-bit implementation, and as 4095 +and 2048 in a 12-bit implementation.) + +We use a pointer per row, rather than a two-dimensional JSAMPLE array. This +choice costs only a small amount of memory and has several benefits: +* Code using the data structure doesn't need to know the allocated width of + the rows. This simplifies edge expansion/compression, since we can work + in an array that's wider than the logical picture width. +* Indexing doesn't require multiplication; this is a performance win on many + machines. +* Arrays with more than 64K total elements can be supported even on machines + where malloc() cannot allocate chunks larger than 64K. +* The rows forming a component array may be allocated at different times + without extra copying. This trick allows some speedups in smoothing steps + that need access to the previous and next rows. + +Note that each color component is stored in a separate array; we don't use the +traditional layout in which the components of a pixel are stored together. +This simplifies coding of modules that work on each component independently, +because they don't need to know how many components there are. Furthermore, +we can read or write each component to a temporary file independently, which +is helpful when dealing with noninterleaved JPEG files. + +In general, a specific sample value is accessed by code such as + GETJSAMPLE(image[colorcomponent][row][col]) +where col is measured from the image left edge, but row is measured from the +first sample row currently in memory. Either of the first two indexings can +be precomputed by copying the relevant pointer. + + +Since most image-processing applications prefer to work on images in which +the components of a pixel are stored together, the data passed to or from the +surrounding application uses the traditional convention: a single pixel is +represented by N consecutive JSAMPLE values, and an image row is an array of +(# of color components)*(image width) JSAMPLEs. One or more rows of data can +be represented by a pointer of type JSAMPARRAY in this scheme. This scheme is +converted to component-wise storage inside the JPEG library. (Applications +that want to skip JPEG preprocessing or postprocessing will have to contend +with component-wise storage.) + + +Arrays of DCT-coefficient values use the following data structure: + + typedef short JCOEF; a 16-bit signed integer + typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients + typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks + typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows + typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays + +The underlying type is at least a 16-bit signed integer; while "short" is big +enough on all machines of interest, on some machines it is preferable to use +"int" for speed reasons, despite the storage cost. Coefficients are grouped +into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than +"8" and "64"). + +The contents of a coefficient block may be in either "natural" or zigzagged +order, and may be true values or divided by the quantization coefficients, +depending on where the block is in the processing pipeline. In the current +library, coefficient blocks are kept in natural order everywhere; the entropy +codecs zigzag or dezigzag the data as it is written or read. The blocks +contain quantized coefficients everywhere outside the DCT/IDCT subsystems. +(This latter decision may need to be revisited to support variable +quantization a la JPEG Part 3.) + +Notice that the allocation unit is now a row of 8x8 blocks, corresponding to +eight rows of samples. Otherwise the structure is much the same as for +samples, and for the same reasons. + +On machines where malloc() can't handle a request bigger than 64Kb, this data +structure limits us to rows of less than 512 JBLOCKs, or a picture width of +4000+ pixels. This seems an acceptable restriction. + + +On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW) +must be declared as "far" pointers, but the upper levels can be "near" +(implying that the pointer lists are allocated in the DS segment). +We use a #define symbol FAR, which expands to the "far" keyword when +compiling on 80x86 machines and to nothing elsewhere. + + +*** Suspendable processing *** + +In some applications it is desirable to use the JPEG library as an +incremental, memory-to-memory filter. In this situation the data source or +destination may be a limited-size buffer, and we can't rely on being able to +empty or refill the buffer at arbitrary times. Instead the application would +like to have control return from the library at buffer overflow/underrun, and +then resume compression or decompression at a later time. + +This scenario is supported for simple cases. (For anything more complex, we +recommend that the application "bite the bullet" and develop real multitasking +capability.) The libjpeg.doc file goes into more detail about the usage and +limitations of this capability; here we address the implications for library +structure. + +The essence of the problem is that the entropy codec (coder or decoder) must +be prepared to stop at arbitrary times. In turn, the controllers that call +the entropy codec must be able to stop before having produced or consumed all +the data that they normally would handle in one call. That part is reasonably +straightforward: we make the controller call interfaces include "progress +counters" which indicate the number of data chunks successfully processed, and +we require callers to test the counter rather than just assume all of the data +was processed. + +Rather than trying to restart at an arbitrary point, the current Huffman +codecs are designed to restart at the beginning of the current MCU after a +suspension due to buffer overflow/underrun. At the start of each call, the +codec's internal state is loaded from permanent storage (in the JPEG object +structures) into local variables. On successful completion of the MCU, the +permanent state is updated. (This copying is not very expensive, and may even +lead to *improved* performance if the local variables can be registerized.) +If a suspension occurs, the codec simply returns without updating the state, +thus effectively reverting to the start of the MCU. Note that this implies +leaving some data unprocessed in the source/destination buffer (ie, the +compressed partial MCU). The data source/destination module interfaces are +specified so as to make this possible. This also implies that the data buffer +must be large enough to hold a worst-case compressed MCU; a couple thousand +bytes should be enough. + +In a successive-approximation AC refinement scan, the progressive Huffman +decoder has to be able to undo assignments of newly nonzero coefficients if it +suspends before the MCU is complete, since decoding requires distinguishing +previously-zero and previously-nonzero coefficients. This is a bit tedious +but probably won't have much effect on performance. Other variants of Huffman +decoding need not worry about this, since they will just store the same values +again if forced to repeat the MCU. + +This approach would probably not work for an arithmetic codec, since its +modifiable state is quite large and couldn't be copied cheaply. Instead it +would have to suspend and resume exactly at the point of the buffer end. + +The JPEG marker reader is designed to cope with suspension at an arbitrary +point. It does so by backing up to the start of the marker parameter segment, +so the data buffer must be big enough to hold the largest marker of interest. +Again, a couple KB should be adequate. (A special "skip" convention is used +to bypass COM and APPn markers, so these can be larger than the buffer size +without causing problems; otherwise a 64K buffer would be needed in the worst +case.) + +The JPEG marker writer currently does *not* cope with suspension. I feel that +this is not necessary; it is much easier simply to require the application to +ensure there is enough buffer space before starting. (An empty 2K buffer is +more than sufficient for the header markers; and ensuring there are a dozen or +two bytes available before calling jpeg_finish_compress() will suffice for the +trailer.) This would not work for writing multi-scan JPEG files, but +we simply do not intend to support that capability with suspension. + + +*** Memory manager services *** + +The JPEG library's memory manager controls allocation and deallocation of +memory, and it manages large "virtual" data arrays on machines where the +operating system does not provide virtual memory. Note that the same +memory manager serves both compression and decompression operations. + +In all cases, allocated objects are tied to a particular compression or +decompression master record, and they will be released when that master +record is destroyed. + +The memory manager does not provide explicit deallocation of objects. +Instead, objects are created in "pools" of free storage, and a whole pool +can be freed at once. This approach helps prevent storage-leak bugs, and +it speeds up operations whenever malloc/free are slow (as they often are). +The pools can be regarded as lifetime identifiers for objects. Two +pools/lifetimes are defined: + * JPOOL_PERMANENT lasts until master record is destroyed + * JPOOL_IMAGE lasts until done with image (JPEG datastream) +Permanent lifetime is used for parameters and tables that should be carried +across from one datastream to another; this includes all application-visible +parameters. Image lifetime is used for everything else. (A third lifetime, +JPOOL_PASS = one processing pass, was originally planned. However it was +dropped as not being worthwhile. The actual usage patterns are such that the +peak memory usage would be about the same anyway; and having per-pass storage +substantially complicates the virtual memory allocation rules --- see below.) + +The memory manager deals with three kinds of object: +1. "Small" objects. Typically these require no more than 10K-20K total. +2. "Large" objects. These may require tens to hundreds of K depending on + image size. Semantically they behave the same as small objects, but we + distinguish them for two reasons: + * On MS-DOS machines, large objects are referenced by FAR pointers, + small objects by NEAR pointers. + * Pool allocation heuristics may differ for large and small objects. + Note that individual "large" objects cannot exceed the size allowed by + type size_t, which may be 64K or less on some machines. +3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs + (typically large enough for the entire image being processed). The + memory manager provides stripwise access to these arrays. On machines + without virtual memory, the rest of the array may be swapped out to a + temporary file. + +(Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large +objects for the data proper and small objects for the row pointers. For +convenience and speed, the memory manager provides single routines to create +these structures. Similarly, virtual arrays include a small control block +and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.) + +In the present implementation, virtual arrays are only permitted to have image +lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is +not very useful since a virtual array's raison d'etre is to store data for +multiple passes through the image.) We also expect that only "small" objects +will be given permanent lifespan, though this restriction is not required by +the memory manager. + +In a non-virtual-memory machine, some performance benefit can be gained by +making the in-memory buffers for virtual arrays be as large as possible. +(For small images, the buffers might fit entirely in memory, so blind +swapping would be very wasteful.) The memory manager will adjust the height +of the buffers to fit within a prespecified maximum memory usage. In order +to do this in a reasonably optimal fashion, the manager needs to allocate all +of the virtual arrays at once. Therefore, there isn't a one-step allocation +routine for virtual arrays; instead, there is a "request" routine that simply +allocates the control block, and a "realize" routine (called just once) that +determines space allocation and creates all of the actual buffers. The +realize routine must allow for space occupied by non-virtual large objects. +(We don't bother to factor in the space needed for small objects, on the +grounds that it isn't worth the trouble.) + +To support all this, we establish the following protocol for doing business +with the memory manager: + 1. Modules must request virtual arrays (which may have only image lifespan) + during the initial setup phase, i.e., in their jinit_xxx routines. + 2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be + allocated during initial setup. + 3. realize_virt_arrays will be called at the completion of initial setup. + The above conventions ensure that sufficient information is available + for it to choose a good size for virtual array buffers. +Small objects of any lifespan may be allocated at any time. We expect that +the total space used for small objects will be small enough to be negligible +in the realize_virt_arrays computation. + +In a virtual-memory machine, we simply pretend that the available space is +infinite, thus causing realize_virt_arrays to decide that it can allocate all +the virtual arrays as full-size in-memory buffers. The overhead of the +virtual-array access protocol is very small when no swapping occurs. + +A virtual array can be specified to be "pre-zeroed"; when this flag is set, +never-yet-written sections of the array are set to zero before being made +available to the caller. If this flag is not set, never-written sections +of the array contain garbage. (This feature exists primarily because the +equivalent logic would otherwise be needed in jdcoefct.c for progressive +JPEG mode; we may as well make it available for possible other uses.) + +The first write pass on a virtual array is required to occur in top-to-bottom +order; read passes, as well as any write passes after the first one, may +access the array in any order. This restriction exists partly to simplify +the virtual array control logic, and partly because some file systems may not +support seeking beyond the current end-of-file in a temporary file. The main +implication of this restriction is that rearrangement of rows (such as +converting top-to-bottom data order to bottom-to-top) must be handled while +reading data out of the virtual array, not while putting it in. + + +*** Memory manager internal structure *** + +To isolate system dependencies as much as possible, we have broken the +memory manager into two parts. There is a reasonably system-independent +"front end" (jmemmgr.c) and a "back end" that contains only the code +likely to change across systems. All of the memory management methods +outlined above are implemented by the front end. The back end provides +the following routines for use by the front end (none of these routines +are known to the rest of the JPEG code): + +jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown + +jpeg_get_small, jpeg_free_small interface to malloc and free library routines + (or their equivalents) + +jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines; + else usually the same as + jpeg_get_small/jpeg_free_small + +jpeg_mem_available estimate available memory + +jpeg_open_backing_store create a backing-store object + +read_backing_store, manipulate a backing-store object +write_backing_store, +close_backing_store + +On some systems there will be more than one type of backing-store object +(specifically, in MS-DOS a backing store file might be an area of extended +memory as well as a disk file). jpeg_open_backing_store is responsible for +choosing how to implement a given object. The read/write/close routines +are method pointers in the structure that describes a given object; this +lets them be different for different object types. + +It may be necessary to ensure that backing store objects are explicitly +released upon abnormal program termination. For example, MS-DOS won't free +extended memory by itself. To support this, we will expect the main program +or surrounding application to arrange to call self_destruct (typically via +jpeg_destroy) upon abnormal termination. This may require a SIGINT signal +handler or equivalent. We don't want to have the back end module install its +own signal handler, because that would pre-empt the surrounding application's +ability to control signal handling. + +The IJG distribution includes several memory manager back end implementations. +Usually the same back end should be suitable for all applications on a given +system, but it is possible for an application to supply its own back end at +need. + + +*** Implications of DNL marker *** + +Some JPEG files may use a DNL marker to postpone definition of the image +height (this would be useful for a fax-like scanner's output, for instance). +In these files the SOF marker claims the image height is 0, and you only +find out the true image height at the end of the first scan. + +We could read these files as follows: +1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). +2. When the DNL is found, update the image height in the global image + descriptor. +This implies that control modules must avoid making copies of the image +height, and must re-test for termination after each MCU row. This would +be easy enough to do. + +In cases where image-size data structures are allocated, this approach will +result in very inefficient use of virtual memory or much-larger-than-necessary +temporary files. This seems acceptable for something that probably won't be a +mainstream usage. People might have to forgo use of memory-hogging options +(such as two-pass color quantization or noninterleaved JPEG files) if they +want efficient conversion of such files. (One could improve efficiency by +demanding a user-supplied upper bound for the height, less than 65536; in most +cases it could be much less.) + +The standard also permits the SOF marker to overestimate the image height, +with a DNL to give the true, smaller height at the end of the first scan. +This would solve the space problems if the overestimate wasn't too great. +However, it implies that you don't even know whether DNL will be used. + +This leads to a couple of very serious objections: +1. Testing for a DNL marker must occur in the inner loop of the decompressor's + Huffman decoder; this implies a speed penalty whether the feature is used + or not. +2. There is no way to hide the last-minute change in image height from an + application using the decoder. Thus *every* application using the IJG + library would suffer a complexity penalty whether it cared about DNL or + not. +We currently do not support DNL because of these problems. + +A different approach is to insist that DNL-using files be preprocessed by a +separate program that reads ahead to the DNL, then goes back and fixes the SOF +marker. This is a much simpler solution and is probably far more efficient. +Even if one wants piped input, buffering the first scan of the JPEG file needs +a lot smaller temp file than is implied by the maximum-height method. For +this approach we'd simply treat DNL as a no-op in the decompressor (at most, +check that it matches the SOF image height). + +We will not worry about making the compressor capable of outputting DNL. +Something similar to the first scheme above could be applied if anyone ever +wants to make that work. diff --git a/Utilities/vtkjpeg/vtk_jpeg_mangle.h b/Utilities/vtkjpeg/vtk_jpeg_mangle.h new file mode 100644 index 0000000..9b5f4eb --- /dev/null +++ b/Utilities/vtkjpeg/vtk_jpeg_mangle.h @@ -0,0 +1,121 @@ +#ifndef vtk_jpeg_mangle_h +#define vtk_jpeg_mangle_h + +/* + +This header file mangles all symbols exported from the jpeg library. +It is included in all files while building the jpeg library. Due to +namespace pollution, no jpeg headers should be included in .h files in +VTK. + +The following command was used to obtain the symbol list: + +nm libvtkjpeg.a |grep " [TR] " + +*/ + +#define jcopy_block_row vtk_jpeg_jcopy_block_row +#define jcopy_sample_rows vtk_jpeg_jcopy_sample_rows +#define jdiv_round_up vtk_jpeg_jdiv_round_up +#define jinit_1pass_quantizer vtk_jpeg_jinit_1pass_quantizer +#define jinit_2pass_quantizer vtk_jpeg_jinit_2pass_quantizer +#define jinit_c_coef_controller vtk_jpeg_jinit_c_coef_controller +#define jinit_c_main_controller vtk_jpeg_jinit_c_main_controller +#define jinit_c_master_control vtk_jpeg_jinit_c_master_control +#define jinit_c_prep_controller vtk_jpeg_jinit_c_prep_controller +#define jinit_color_converter vtk_jpeg_jinit_color_converter +#define jinit_color_deconverter vtk_jpeg_jinit_color_deconverter +#define jinit_compress_master vtk_jpeg_jinit_compress_master +#define jinit_d_coef_controller vtk_jpeg_jinit_d_coef_controller +#define jinit_d_main_controller vtk_jpeg_jinit_d_main_controller +#define jinit_d_post_controller vtk_jpeg_jinit_d_post_controller +#define jinit_downsampler vtk_jpeg_jinit_downsampler +#define jinit_forward_dct vtk_jpeg_jinit_forward_dct +#define jinit_huff_decoder vtk_jpeg_jinit_huff_decoder +#define jinit_huff_encoder vtk_jpeg_jinit_huff_encoder +#define jinit_input_controller vtk_jpeg_jinit_input_controller +#define jinit_inverse_dct vtk_jpeg_jinit_inverse_dct +#define jinit_marker_reader vtk_jpeg_jinit_marker_reader +#define jinit_marker_writer vtk_jpeg_jinit_marker_writer +#define jinit_master_decompress vtk_jpeg_jinit_master_decompress +#define jinit_memory_mgr vtk_jpeg_jinit_memory_mgr +#define jinit_merged_upsampler vtk_jpeg_jinit_merged_upsampler +#define jinit_phuff_decoder vtk_jpeg_jinit_phuff_decoder +#define jinit_phuff_encoder vtk_jpeg_jinit_phuff_encoder +#define jinit_upsampler vtk_jpeg_jinit_upsampler +#define jpeg_CreateCompress vtk_jpeg_CreateCompress +#define jpeg_CreateDecompress vtk_jpeg_CreateDecompress +#define jpeg_abort vtk_jpeg_abort +#define jpeg_abort_compress vtk_jpeg_abort_compress +#define jpeg_abort_decompress vtk_jpeg_abort_decompress +#define jpeg_add_quant_table vtk_jpeg_add_quant_table +#define jpeg_alloc_huff_table vtk_jpeg_alloc_huff_table +#define jpeg_alloc_quant_table vtk_jpeg_alloc_quant_table +#define jpeg_calc_output_dimensions vtk_jpeg_calc_output_dimensions +#define jpeg_consume_input vtk_jpeg_consume_input +#define jpeg_copy_critical_parameters vtk_jpeg_copy_critical_parameters +#define jpeg_default_colorspace vtk_jpeg_default_colorspace +#define jpeg_destroy vtk_jpeg_destroy +#define jpeg_destroy_compress vtk_jpeg_destroy_compress +#define jpeg_destroy_decompress vtk_jpeg_destroy_decompress +#define jpeg_fdct_float vtk_jpeg_fdct_float +#define jpeg_fdct_ifast vtk_jpeg_fdct_ifast +#define jpeg_fdct_islow vtk_jpeg_fdct_islow +#define jpeg_fill_bit_buffer vtk_jpeg_fill_bit_buffer +#define jpeg_finish_compress vtk_jpeg_finish_compress +#define jpeg_finish_decompress vtk_jpeg_finish_decompress +#define jpeg_finish_output vtk_jpeg_finish_output +#define jpeg_free_large vtk_jpeg_free_large +#define jpeg_free_small vtk_jpeg_free_small +#define jpeg_gen_optimal_table vtk_jpeg_gen_optimal_table +#define jpeg_get_large vtk_jpeg_get_large +#define jpeg_get_small vtk_jpeg_get_small +#define jpeg_has_multiple_scans vtk_jpeg_has_multiple_scans +#define jpeg_huff_decode vtk_jpeg_huff_decode +#define jpeg_idct_1x1 vtk_jpeg_idct_1x1 +#define jpeg_idct_2x2 vtk_jpeg_idct_2x2 +#define jpeg_idct_4x4 vtk_jpeg_idct_4x4 +#define jpeg_idct_float vtk_jpeg_idct_float +#define jpeg_idct_ifast vtk_jpeg_idct_ifast +#define jpeg_idct_islow vtk_jpeg_idct_islow +#define jpeg_input_complete vtk_jpeg_input_complete +#define jpeg_make_c_derived_tbl vtk_jpeg_make_c_derived_tbl +#define jpeg_make_d_derived_tbl vtk_jpeg_make_d_derived_tbl +#define jpeg_mem_available vtk_jpeg_mem_available +#define jpeg_mem_init vtk_jpeg_mem_init +#define jpeg_mem_term vtk_jpeg_mem_term +#define jpeg_natural_order vtk_jpeg_natural_order +#define jpeg_new_colormap vtk_jpeg_new_colormap +#define jpeg_open_backing_store vtk_jpeg_open_backing_store +#define jpeg_quality_scaling vtk_jpeg_quality_scaling +#define jpeg_read_coefficients vtk_jpeg_read_coefficients +#define jpeg_read_header vtk_jpeg_read_header +#define jpeg_read_raw_data vtk_jpeg_read_raw_data +#define jpeg_read_scanlines vtk_jpeg_read_scanlines +#define jpeg_resync_to_restart vtk_jpeg_resync_to_restart +#define jpeg_save_markers vtk_jpeg_save_markers +#define jpeg_set_colorspace vtk_jpeg_set_colorspace +#define jpeg_set_defaults vtk_jpeg_set_defaults +#define jpeg_set_linear_quality vtk_jpeg_set_linear_quality +#define jpeg_set_marker_processor vtk_jpeg_set_marker_processor +#define jpeg_set_quality vtk_jpeg_set_quality +#define jpeg_simple_progression vtk_jpeg_simple_progression +#define jpeg_start_compress vtk_jpeg_start_compress +#define jpeg_start_decompress vtk_jpeg_start_decompress +#define jpeg_start_output vtk_jpeg_start_output +#define jpeg_std_error vtk_jpeg_std_error +#define jpeg_std_message_table vtk_jpeg_std_message_table +#define jpeg_stdio_dest vtk_jpeg_stdio_dest +#define jpeg_stdio_src vtk_jpeg_stdio_src +#define jpeg_suppress_tables vtk_jpeg_suppress_tables +#define jpeg_write_coefficients vtk_jpeg_write_coefficients +#define jpeg_write_m_byte vtk_jpeg_write_m_byte +#define jpeg_write_m_header vtk_jpeg_write_m_header +#define jpeg_write_marker vtk_jpeg_write_marker +#define jpeg_write_raw_data vtk_jpeg_write_raw_data +#define jpeg_write_scanlines vtk_jpeg_write_scanlines +#define jpeg_write_tables vtk_jpeg_write_tables +#define jround_up vtk_jpeg_jround_up +#define jzero_far vtk_jpeg_jzero_far + +#endif diff --git a/Utilities/vtknetcdf/CMakeLists.txt b/Utilities/vtknetcdf/CMakeLists.txt new file mode 100644 index 0000000..27f41ea --- /dev/null +++ b/Utilities/vtknetcdf/CMakeLists.txt @@ -0,0 +1,263 @@ +PROJECT(VTKNETCDF) + +INCLUDE_REGULAR_EXPRESSION(".*") + +SET(netcdf_SRCS + attr.c + dim.c + error.c + libvers.c + nc.c + ncio.c + ncx.c + putget.c + string.c + v1hpg.c + v2i.c + var.c + ) + +IF(APPLE) + SET_SOURCE_FILES_PROPERTIES( + v2i.c + PROPERTIES + COMPILE_FLAGS -fno-common) +ENDIF(APPLE) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ) + +# Include all the necessary files for macros +INCLUDE (CheckIncludeFiles) +INCLUDE (CheckFunctionExists) +INCLUDE (CheckTypeSize) +INCLUDE (CheckSymbolExists) +INCLUDE (TestBigEndian) + +MACRO(MANGLE_VARIABLE_NAME str var prefix) + STRING(TOUPPER "${str}" mangle_variable_name_var) + STRING(REGEX REPLACE "[/. ]" "_" mangle_variable_name_var "${mangle_variable_name_var}") + SET(${var} "${prefix}${mangle_variable_name_var}") +ENDMACRO(MANGLE_VARIABLE_NAME str var) + +# Check if header file exists and add it to the list. +MACRO(CHECK_INCLUDE_FILE_CONCAT FILE) + MANGLE_VARIABLE_NAME("${FILE}" "CHECK_INCLUDE_FILE_CONCAT_VAR" "HAVE_") + CHECK_INCLUDE_FILES("${HEADER_INCLUDES};${FILE}" ${CHECK_INCLUDE_FILE_CONCAT_VAR}) + IF(${CHECK_INCLUDE_FILE_CONCAT_VAR}) + SET(HEADER_INCLUDES ${HEADER_INCLUDES} ${FILE}) + ENDIF(${CHECK_INCLUDE_FILE_CONCAT_VAR}) +ENDMACRO(CHECK_INCLUDE_FILE_CONCAT) + +MACRO(CHECK_FUNCTION_EXISTS_EX FUNC) + MANGLE_VARIABLE_NAME("${FUNC}" "CHECK_FUNCTION_EXISTS_EX_VAR" "HAVE_") + CHECK_FUNCTION_EXISTS("${FUNC}" "${CHECK_FUNCTION_EXISTS_EX_VAR}") +ENDMACRO(CHECK_FUNCTION_EXISTS_EX) + +MACRO(CHECK_SYMBOL_EXISTS_EX SYM) + MANGLE_VARIABLE_NAME("${SYM}" "CHECK_SYMBOL_EXISTS_EX_VAR" "HAVE_") + CHECK_SYMBOL_EXISTS("${SYM}" "${HEADER_INCLUDES}" "${CHECK_SYMBOL_EXISTS_EX_VAR}") +ENDMACRO(CHECK_SYMBOL_EXISTS_EX) + +MACRO(CHECK_TYPE_SIZE_EX type) + MANGLE_VARIABLE_NAME("${type}" "check_type_size_var" "") + CHECK_TYPE_SIZE("${type}" "SIZEOF_${check_type_size_var}") + IF(HAVE_${check_type_size_var}) + SET("HAVE_${check_type_size_var}" 1) + ENDIF(HAVE_${check_type_size_var}) +ENDMACRO(CHECK_TYPE_SIZE_EX) + +MACRO(C_SOURCE_COMPILES SOURCE VAR) + IF("${VAR}" MATCHES "^${VAR}$") + SET(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") + IF(CMAKE_REQUIRED_LIBRARIES) + SET(C_SOURCE_COMPILES_ADD_LIBRARIES + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") + ENDIF(CMAKE_REQUIRED_LIBRARIES) + FILE(WRITE "${CMAKE_BINARY_DIR}/CMakeTmp/src.c" + "${SOURCE}") + + MESSAGE(STATUS "Performing NetCDF Test ${VAR}") + TRY_COMPILE(${VAR} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}/CMakeTmp/src.c + CMAKE_FLAGS + "${C_SOURCE_COMPILES_ADD_LIBRARIES}" + OUTPUT_VARIABLE OUTPUT) + IF(${VAR}) + SET(${VAR} 1 CACHE INTERNAL "NetCDF test ${FUNCTION}") + MESSAGE(STATUS "Performing NetCDF Test ${VAR} - Success") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log + "Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n" APPEND) + ELSE(${VAR}) + MESSAGE(STATUS "Performing NetCDF Test ${VAR} - Failed") + SET(${VAR} "" CACHE INTERNAL "NetCDF test ${FUNCTION}") + WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n" APPEND) + ENDIF(${VAR}) + ENDIF("${VAR}" MATCHES "^${VAR}$") +ENDMACRO(C_SOURCE_COMPILES) + +CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) +FOREACH(file + "alloca.h" + "stdlib.h" + "sys/types.h" + "sys/stat.h" + "unistd.h" + "fcntl.h" + "stdio.h" + "string.h" + "stddef.h" + "stdint.h" + ) + CHECK_INCLUDE_FILE_CONCAT("${file}") +ENDFOREACH(file) +FOREACH(func + alloca + strerror + ) + CHECK_SYMBOL_EXISTS_EX("${func}") +ENDFOREACH(func) +FOREACH(type + "size_t" + "ssize_t" + "ptrdiff_t" + "off_t" + "double" + "float" + "int" + "long" + "short" + "uchar" + ) + CHECK_TYPE_SIZE_EX("${type}") +ENDFOREACH(type) + +SET(testsrc +"#include <sys/stat.h> +int main() { return 0; } +int t() { +struct stat s; s.st_blksize; +; return 0; }") +IF(HAVE_SYS_TYPES_H) + SET(testsrc "#include <sys/types.h>\n${testsrc}") +ENDIF(HAVE_SYS_TYPES_H) + +IF(HAVE_SYS_STAT_H) + C_SOURCE_COMPILES("${testsrc}" HAVE_ST_BLKSIZE) +ENDIF(HAVE_SYS_STAT_H) + +# +SET(testsrc + "main() +{ + char* path = tmpnam(NULL); + int exitStatus = 1; + + if (path != NULL) + { + int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666); + + if (fd != -1) + { + if (write(fd, \"0\", 1) == 1) + { + off_t pos = lseek(fd, 0, SEEK_CUR); + + if (pos != (off_t)-1) + { + if (ftruncate(fd, 512) != -1) + { + if (pos == lseek(fd, 0, SEEK_CUR)) + { + if (lseek(fd, 0, SEEK_SET) == 0) + { + char buf[512]; + + if (read(fd, buf, 512) == 512) + exitStatus = 0; + } + } + } + } + } + close(fd); + unlink(path); + } + } + + return exitStatus; +}") +IF(HAVE_SYS_TYPES_H) + SET(testsrc "#include <sys/types.h>\n${testsrc}") +ENDIF(HAVE_SYS_TYPES_H) +IF(HAVE_SYS_STAT_H) + SET(testsrc "#include <sys/stat.h>\n${testsrc}") +ENDIF(HAVE_SYS_STAT_H) +IF(HAVE_FCNTL_H) + SET(testsrc "#include <fcntl.h>\n${testsrc}") +ENDIF(HAVE_FCNTL_H) +IF(HAVE_STDIO_H) + SET(testsrc "#include <stdio.h>\n${testsrc}") +ENDIF(HAVE_STDIO_H) +IF(HAVE_UNISTD_H) + SET(testsrc "#include <unistd.h>\n${testsrc}") +ENDIF(HAVE_UNISTD_H) +C_SOURCE_COMPILES("${testsrc}" HAVE_FTRUNCATE) + +MACRO(INVERT_VARIABLE var val) + SET(INVERT_VARIABLE_VAR "${val}") + SET(${var} "1") + IF(INVERT_VARIABLE_VAR) + SET(${var} "0") + ENDIF(INVERT_VARIABLE_VAR) +ENDMACRO(INVERT_VARIABLE) + +INVERT_VARIABLE(NO_STDLIB_H "${HAVE_STDLIB_H}") +INVERT_VARIABLE(NO_SYS_TYPES_H "${HAVE_SYS_TYPES_H}") +INVERT_VARIABLE(NO_STRERROR "${HAVE_STRERROR}") + +IF(NOT HAVE_SIZEOF_SIZE_T) + SET(size_t long) +ENDIF(NOT HAVE_SIZEOF_SIZE_T) +IF(NOT HAVE_SIZEOF_OFF_T) + SET(off_t long) +ENDIF(NOT HAVE_SIZEOF_OFF_T) +IF(NOT HAVE_SIZEOF_SSIZE_T) + SET(ssize_t int) +ENDIF(NOT HAVE_SIZEOF_SSIZE_T) +IF(NOT HAVE_SIZEOF_PTRDIFF_T) + SET(ptrdiff_t int) +ENDIF(NOT HAVE_SIZEOF_PTRDIFF_T) +IF(NOT HAVE_SIZEOF_UCHAR) + SET(uchar "unsigned char") +ENDIF(NOT HAVE_SIZEOF_UCHAR) + +TEST_BIG_ENDIAN(WORDS_BIGENDIAN) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ncconfig.h.in + ${CMAKE_CURRENT_BINARY_DIR}/ncconfig.h @ONLY IMMEDIATE) + +ADD_LIBRARY(vtkNetCDF + ${netcdf_SRCS}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkNetCDF PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkNetCDF) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtknetcdf .h + netcdf.h ncconfig.h vtk_netcdf_mangle.h) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/vtknetcdf/attr.c b/Utilities/vtknetcdf/attr.c new file mode 100644 index 0000000..3b6631d --- /dev/null +++ b/Utilities/vtknetcdf/attr.c @@ -0,0 +1,2250 @@ +/* Do not edit this file. It is produced from the corresponding .m4 source */ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: attr.c,v 1.1 2005/07/15 21:56:38 andy Exp $ */ + +#include "nc.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "ncx.h" +#include "fbits.h" +#include "rnd.h" + + +/* + * Free attr + * Formerly +NC_free_attr() + */ +void +free_NC_attr(NC_attr *attrp) +{ + + if(attrp == NULL) + return; + free_NC_string(attrp->name); + free(attrp); +} + + +/* + * How much space will 'nelems' of 'type' take in + * external representation (as the values of an attribute)? + */ +static size_t +ncx_len_NC_attrV(nc_type type, size_t nelems) +{ + switch(type) { + case NC_BYTE: + case NC_CHAR: + return ncx_len_char(nelems); + case NC_SHORT: + return ncx_len_short(nelems); + case NC_INT: + return ncx_len_int(nelems); + case NC_FLOAT: + return ncx_len_float(nelems); + case NC_DOUBLE: + return ncx_len_double(nelems); + } + /* default */ + assert("ncx_len_NC_attr bad type" == 0); + return 0; +} + + +NC_attr * +new_x_NC_attr( + NC_string *strp, + nc_type type, + size_t nelems) +{ + NC_attr *attrp; + const size_t xsz = ncx_len_NC_attrV(type, nelems); + size_t sz = M_RNDUP(sizeof(NC_attr)); + + assert(!(xsz == 0 && nelems != 0)); + + sz += xsz; + + attrp = (NC_attr *) malloc(sz); + if(attrp == NULL ) + return NULL; + + attrp->xsz = xsz; + + attrp->name = strp; + attrp->type = type; + attrp->nelems = nelems; + if(xsz != 0) + attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr)); + else + attrp->xvalue = NULL; + + return(attrp); +} + + +/* + * Formerly +NC_new_attr(name,type,count,value) + */ +static NC_attr * +new_NC_attr( + const char *name, + nc_type type, + size_t nelems) +{ + NC_string *strp; + NC_attr *attrp; + + assert(name != NULL && *name != 0); + + strp = new_NC_string(strlen(name), name); + if(strp == NULL) + return NULL; + + attrp = new_x_NC_attr(strp, type, nelems); + if(attrp == NULL) + { + free_NC_string(strp); + return NULL; + } + + return(attrp); +} + + +static NC_attr * +dup_NC_attr(const NC_attr *rattrp) +{ + NC_attr *attrp = new_NC_attr(rattrp->name->cp, + rattrp->type, rattrp->nelems); + if(attrp == NULL) + return NULL; + (void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz); + return attrp; +} + +/* attrarray */ + +/* + * Free the stuff "in" (referred to by) an NC_attrarray. + * Leaves the array itself allocated. + */ +void +free_NC_attrarrayV0(NC_attrarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return; + + assert(ncap->value != NULL); + + { + NC_attr **app = ncap->value; + NC_attr *const *const end = &app[ncap->nelems]; + for( /*NADA*/; app < end; app++) + { + free_NC_attr(*app); + *app = NULL; + } + } + ncap->nelems = 0; +} + + +/* + * Free NC_attrarray values. + * formerly +NC_free_array() + */ +void +free_NC_attrarrayV(NC_attrarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nalloc == 0) + return; + + assert(ncap->value != NULL); + + free_NC_attrarrayV0(ncap); + + free(ncap->value); + ncap->value = NULL; + ncap->nalloc = 0; +} + + +int +dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref) +{ + int status = NC_NOERR; + + assert(ref != NULL); + assert(ncap != NULL); + + if(ref->nelems != 0) + { + const size_t sz = ref->nelems * sizeof(NC_attr *); + ncap->value = (NC_attr **) malloc(sz); + if(ncap->value == NULL) + return NC_ENOMEM; + + (void) memset(ncap->value, 0, sz); + ncap->nalloc = ref->nelems; + } + + ncap->nelems = 0; + { + NC_attr **app = ncap->value; + const NC_attr **drpp = (const NC_attr **)ref->value; + NC_attr *const *const end = &app[ref->nelems]; + for( /*NADA*/; app < end; drpp++, app++, ncap->nelems++) + { + *app = dup_NC_attr(*drpp); + if(*app == NULL) + { + status = NC_ENOMEM; + break; + } + } + } + + if(status != NC_NOERR) + { + free_NC_attrarrayV(ncap); + return status; + } + + assert(ncap->nelems == ref->nelems); + + return NC_NOERR; +} + + +/* + * Add a new handle on the end of an array of handles + * Formerly +NC_incr_array(array, tail) + */ +static int +incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp) +{ + NC_attr **vp; + + assert(ncap != NULL); + + if(ncap->nalloc == 0) + { + assert(ncap->nelems == 0); + vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *)); + if(vp == NULL) + return NC_ENOMEM; + + ncap->value = vp; + ncap->nalloc = NC_ARRAY_GROWBY; + } + else if(ncap->nelems +1 > ncap->nalloc) + { + vp = (NC_attr **) realloc(ncap->value, + (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *)); + if(vp == NULL) + return NC_ENOMEM; + + ncap->value = vp; + ncap->nalloc += NC_ARRAY_GROWBY; + } + + if(newelemp != NULL) + { + ncap->value[ncap->nelems] = newelemp; + ncap->nelems++; + } + return NC_NOERR; +} + + +NC_attr * +elem_NC_attrarray(const NC_attrarray *ncap, size_t elem) +{ + assert(ncap != NULL); + /* cast needed for braindead systems with signed size_t */ + if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems) + return NULL; + + assert(ncap->value != NULL); + + return ncap->value[elem]; +} + +/* End attarray per se */ + +/* + * Given ncp and varid, return ptr to array of attributes + * else NULL on error + */ +static NC_attrarray * +NC_attrarray0( NC *ncp, int varid) +{ + NC_attrarray *ap; + + if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */ + { + ap = &ncp->attrs; + } + else if(varid >= 0 && (size_t) varid < ncp->vars.nelems) + { + NC_var **vpp; + vpp = (NC_var **)ncp->vars.value; + vpp += varid; + ap = &(*vpp)->attrs; + } else { + ap = NULL; + } + return(ap); +} + + +/* + * Step thru NC_ATTRIBUTE array, seeking match on name. + * return match or NULL if Not Found. + */ +NC_attr ** +NC_findattr(const NC_attrarray *ncap, const char *name) +{ + NC_attr **attrpp; + size_t attrid; + size_t slen; + + assert(ncap != NULL); + + if(ncap->nelems == 0) + return NULL; + + attrpp = (NC_attr **) ncap->value; + + slen = strlen(name); + + for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++) + { + if(strlen((*attrpp)->name->cp) == slen && + strncmp((*attrpp)->name->cp, name, slen) == 0) + { + return(attrpp); /* Normal return */ + } + } + return(NULL); +} + + +/* + * Look up by ncid, varid and name, return NULL if not found + */ +static int +NC_lookupattr(int ncid, + int varid, + const char *name, /* attribute name */ + NC_attr **attrpp) /* modified on return */ +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **tmp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + tmp = NC_findattr(ncap, name); + if(tmp == NULL) + return NC_ENOTATT; + + if(attrpp != NULL) + *attrpp = *tmp; + + return ENOERR; +} + +/* Public */ + +int +nc_inq_attname(int ncid, int varid, int attnum, char *name) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + attrp = elem_NC_attrarray(ncap, (size_t)attnum); + if(attrp == NULL) + return NC_ENOTATT; + + (void) strncpy(name, attrp->name->cp, attrp->name->nchars); + name[attrp->name->nchars] = 0; + + return NC_NOERR; +} + + +int +nc_inq_attid(int ncid, int varid, const char *name, int *attnump) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + + attrpp = NC_findattr(ncap, name); + if(attrpp == NULL) + return NC_ENOTATT; + + if(attnump != NULL) + *attnump = (int)(attrpp - ncap->value); + + return NC_NOERR; +} + +int +nc_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(datatypep != NULL) + *datatypep = attrp->type; + + return NC_NOERR; +} + +int +nc_inq_attlen(int ncid, int varid, const char *name, size_t *lenp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(lenp != NULL) + *lenp = attrp->nelems; + + return NC_NOERR; +} + +int +nc_inq_att(int ncid, + int varid, + const char *name, /* input, attribute name */ + nc_type *datatypep, + size_t *lenp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(datatypep != NULL) + *datatypep = attrp->type; + if(lenp != NULL) + *lenp = attrp->nelems; + + return NC_NOERR; +} + + +int +nc_rename_att( int ncid, int varid, const char *name, const char *newname) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **tmp; + NC_attr *attrp; + NC_string *newStr, *old; + + /* sortof inline clone of NC_lookupattr() */ + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + tmp = NC_findattr(ncap, name); + if(tmp == NULL) + return NC_ENOTATT; + attrp = *tmp; + /* end inline clone NC_lookupattr() */ + + if(NC_findattr(ncap, newname) != NULL) + { + /* name in use */ + return NC_ENAMEINUSE; + } + + old = attrp->name; + if(NC_indef(ncp)) + { + newStr = new_NC_string(strlen(newname), newname); + if( newStr == NULL) + return NC_ENOMEM; + attrp->name = newStr; + free_NC_string(old); + return NC_NOERR; + } + /* else */ + status = set_NC_string(old, newname); + if( status != NC_NOERR) + return status; + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; +} + + +int +nc_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out, int ovarid) +{ + int status; + NC_attr *iattrp; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_lookupattr(ncid_in, varid_in, name, &iattrp); + if(status != NC_NOERR) + return status; + + status = NC_check_id(ncid_out, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, ovarid); + if(ncap == NULL) + return NC_ENOTVAR; + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + attrp = *attrpp; /* convenience */ + + if(iattrp->xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = iattrp->xsz; + attrp->type = iattrp->type; + attrp->nelems = iattrp->nelems; + + (void) memcpy(attrp->xvalue, iattrp->xvalue, + iattrp->xsz); + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + attrp = new_NC_attr(name, iattrp->type, iattrp->nelems); + if(attrp == NULL) + return NC_ENOMEM; + + (void) memcpy(attrp->xvalue, iattrp->xvalue, + iattrp->xsz); + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + status = incr_NC_attrarray(ncap, attrp); + if(status != NC_NOERR) + { + free_NC_attr(attrp); + return status; + } + } + + return NC_NOERR; +} + + +int +nc_del_att(int ncid, int varid, const char *name) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + int attrid; + size_t slen; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + /* sortof inline NC_findattr() */ + slen = strlen(name); + + attrpp = (NC_attr **) ncap->value; + for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++) + { + if( slen == (*attrpp)->name->nchars && + strncmp(name, (*attrpp)->name->cp, slen) == 0) + { + old = *attrpp; + break; + } + } + if( (size_t) attrid == ncap->nelems ) + return NC_ENOTATT; + /* end inline NC_findattr() */ + + /* shuffle down */ + for(attrid++; (size_t) attrid < ncap->nelems; attrid++) + { + *attrpp = *(attrpp + 1); + attrpp++; + } + *attrpp = NULL; + /* decrement count */ + ncap->nelems--; + + free_NC_attr(old); + + return NC_NOERR; +} + + +static int +ncx_pad_putn_Iuchar(void **xpp, size_t nelems, const uchar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_putn_schar_uchar(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_putn_short_uchar(xpp, nelems, tp); + case NC_INT: + return ncx_putn_int_uchar(xpp, nelems, tp); + case NC_FLOAT: + return ncx_putn_float_uchar(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_putn_double_uchar(xpp, nelems, tp); + } + assert("ncx_pad_putn_Iuchar invalid type" == 0); + return NC_EBADTYPE; +} + +static int +ncx_pad_getn_Iuchar(const void **xpp, size_t nelems, uchar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_getn_schar_uchar(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_getn_short_uchar(xpp, nelems, tp); + case NC_INT: + return ncx_getn_int_uchar(xpp, nelems, tp); + case NC_FLOAT: + return ncx_getn_float_uchar(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_getn_double_uchar(xpp, nelems, tp); + } + assert("ncx_pad_getn_Iuchar invalid type" == 0); + return NC_EBADTYPE; +} + + +static int +ncx_pad_putn_Ischar(void **xpp, size_t nelems, const schar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_putn_schar_schar(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_putn_short_schar(xpp, nelems, tp); + case NC_INT: + return ncx_putn_int_schar(xpp, nelems, tp); + case NC_FLOAT: + return ncx_putn_float_schar(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_putn_double_schar(xpp, nelems, tp); + } + assert("ncx_pad_putn_Ischar invalid type" == 0); + return NC_EBADTYPE; +} + +static int +ncx_pad_getn_Ischar(const void **xpp, size_t nelems, schar *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_getn_schar_schar(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_getn_short_schar(xpp, nelems, tp); + case NC_INT: + return ncx_getn_int_schar(xpp, nelems, tp); + case NC_FLOAT: + return ncx_getn_float_schar(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_getn_double_schar(xpp, nelems, tp); + } + assert("ncx_pad_getn_Ischar invalid type" == 0); + return NC_EBADTYPE; +} + + +static int +ncx_pad_putn_Ishort(void **xpp, size_t nelems, const short *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_putn_schar_short(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_putn_short_short(xpp, nelems, tp); + case NC_INT: + return ncx_putn_int_short(xpp, nelems, tp); + case NC_FLOAT: + return ncx_putn_float_short(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_putn_double_short(xpp, nelems, tp); + } + assert("ncx_pad_putn_Ishort invalid type" == 0); + return NC_EBADTYPE; +} + +static int +ncx_pad_getn_Ishort(const void **xpp, size_t nelems, short *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_getn_schar_short(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_getn_short_short(xpp, nelems, tp); + case NC_INT: + return ncx_getn_int_short(xpp, nelems, tp); + case NC_FLOAT: + return ncx_getn_float_short(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_getn_double_short(xpp, nelems, tp); + } + assert("ncx_pad_getn_Ishort invalid type" == 0); + return NC_EBADTYPE; +} + + +static int +ncx_pad_putn_Iint(void **xpp, size_t nelems, const int *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_putn_schar_int(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_putn_short_int(xpp, nelems, tp); + case NC_INT: + return ncx_putn_int_int(xpp, nelems, tp); + case NC_FLOAT: + return ncx_putn_float_int(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_putn_double_int(xpp, nelems, tp); + } + assert("ncx_pad_putn_Iint invalid type" == 0); + return NC_EBADTYPE; +} + +static int +ncx_pad_getn_Iint(const void **xpp, size_t nelems, int *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_getn_schar_int(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_getn_short_int(xpp, nelems, tp); + case NC_INT: + return ncx_getn_int_int(xpp, nelems, tp); + case NC_FLOAT: + return ncx_getn_float_int(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_getn_double_int(xpp, nelems, tp); + } + assert("ncx_pad_getn_Iint invalid type" == 0); + return NC_EBADTYPE; +} + + +static int +ncx_pad_putn_Ilong(void **xpp, size_t nelems, const long *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_putn_schar_long(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_putn_short_long(xpp, nelems, tp); + case NC_INT: + return ncx_putn_int_long(xpp, nelems, tp); + case NC_FLOAT: + return ncx_putn_float_long(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_putn_double_long(xpp, nelems, tp); + } + assert("ncx_pad_putn_Ilong invalid type" == 0); + return NC_EBADTYPE; +} + +static int +ncx_pad_getn_Ilong(const void **xpp, size_t nelems, long *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_getn_schar_long(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_getn_short_long(xpp, nelems, tp); + case NC_INT: + return ncx_getn_int_long(xpp, nelems, tp); + case NC_FLOAT: + return ncx_getn_float_long(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_getn_double_long(xpp, nelems, tp); + } + assert("ncx_pad_getn_Ilong invalid type" == 0); + return NC_EBADTYPE; +} + + +static int +ncx_pad_putn_Ifloat(void **xpp, size_t nelems, const float *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_putn_schar_float(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_putn_short_float(xpp, nelems, tp); + case NC_INT: + return ncx_putn_int_float(xpp, nelems, tp); + case NC_FLOAT: + return ncx_putn_float_float(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_putn_double_float(xpp, nelems, tp); + } + assert("ncx_pad_putn_Ifloat invalid type" == 0); + return NC_EBADTYPE; +} + +static int +ncx_pad_getn_Ifloat(const void **xpp, size_t nelems, float *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_getn_schar_float(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_getn_short_float(xpp, nelems, tp); + case NC_INT: + return ncx_getn_int_float(xpp, nelems, tp); + case NC_FLOAT: + return ncx_getn_float_float(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_getn_double_float(xpp, nelems, tp); + } + assert("ncx_pad_getn_Ifloat invalid type" == 0); + return NC_EBADTYPE; +} + + +static int +ncx_pad_putn_Idouble(void **xpp, size_t nelems, const double *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_putn_schar_double(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_putn_short_double(xpp, nelems, tp); + case NC_INT: + return ncx_putn_int_double(xpp, nelems, tp); + case NC_FLOAT: + return ncx_putn_float_double(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_putn_double_double(xpp, nelems, tp); + } + assert("ncx_pad_putn_Idouble invalid type" == 0); + return NC_EBADTYPE; +} + +static int +ncx_pad_getn_Idouble(const void **xpp, size_t nelems, double *tp, nc_type type) +{ + switch(type) { + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return ncx_pad_getn_schar_double(xpp, nelems, tp); + case NC_SHORT: + return ncx_pad_getn_short_double(xpp, nelems, tp); + case NC_INT: + return ncx_getn_int_double(xpp, nelems, tp); + case NC_FLOAT: + return ncx_getn_float_double(xpp, nelems, tp); + case NC_DOUBLE: + return ncx_getn_double_double(xpp, nelems, tp); + } + assert("ncx_pad_getn_Idouble invalid type" == 0); + return NC_EBADTYPE; +} + + + +int +nc_put_att_text(int ncid, int varid, const char *name, + size_t nelems, const char *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(NC_CHAR, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = NC_CHAR; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_text(&xp, nelems, value); + if(status != NC_NOERR) + return status; + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + attrp = new_NC_attr(name, NC_CHAR, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_text(&xp, nelems, value); + if(status != NC_NOERR) + return status; + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + status = incr_NC_attrarray(ncap, attrp); + if(status != NC_NOERR) + { + free_NC_attr(attrp); + return status; + } + } + + return NC_NOERR; +} + + +int +nc_get_att_text(int ncid, int varid, const char *name, char *str) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type != NC_CHAR) + return NC_ECHAR; + + /* else */ + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_text(&xp, attrp->nelems, str); + } +} + + + + +int +nc_put_att_schar(int ncid, int varid, const char *name, + nc_type type, size_t nelems, const signed char *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ischar(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ischar + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ischar(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ischar + */ + if(lstatus != NC_NOERR) + { + free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +nc_get_att_schar(int ncid, int varid, const char *name, signed char *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_Ischar(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +nc_put_att_uchar(int ncid, int varid, const char *name, + nc_type type, size_t nelems, const unsigned char *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Iuchar(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Iuchar + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Iuchar(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Iuchar + */ + if(lstatus != NC_NOERR) + { + free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +nc_get_att_uchar(int ncid, int varid, const char *name, unsigned char *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_Iuchar(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +nc_put_att_short(int ncid, int varid, const char *name, + nc_type type, size_t nelems, const short *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ishort(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ishort + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ishort(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ishort + */ + if(lstatus != NC_NOERR) + { + free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +nc_get_att_short(int ncid, int varid, const char *name, short *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_Ishort(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +nc_put_att_int(int ncid, int varid, const char *name, + nc_type type, size_t nelems, const int *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Iint(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Iint + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Iint(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Iint + */ + if(lstatus != NC_NOERR) + { + free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +nc_get_att_int(int ncid, int varid, const char *name, int *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_Iint(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +nc_put_att_long(int ncid, int varid, const char *name, + nc_type type, size_t nelems, const long *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ilong(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ilong + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ilong(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ilong + */ + if(lstatus != NC_NOERR) + { + free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +nc_get_att_long(int ncid, int varid, const char *name, long *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_Ilong(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +nc_put_att_float(int ncid, int varid, const char *name, + nc_type type, size_t nelems, const float *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ifloat(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ifloat + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Ifloat(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Ifloat + */ + if(lstatus != NC_NOERR) + { + free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +nc_get_att_float(int ncid, int varid, const char *name, float *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_Ifloat(&xp, attrp->nelems, tp, attrp->type); + } +} + + +int +nc_put_att_double(int ncid, int varid, const char *name, + nc_type type, size_t nelems, const double *value) +{ + int status; + NC *ncp; + NC_attrarray *ncap; + NC_attr **attrpp; + NC_attr *old = NULL; + NC_attr *attrp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + ncap = NC_attrarray0(ncp, varid); + if(ncap == NULL) + return NC_ENOTVAR; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + if(type == NC_CHAR) + return NC_ECHAR; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) nelems > X_INT_MAX) /* backward compat */ + return NC_EINVAL; /* Invalid nelems */ + + if(nelems != 0 && value == NULL) + return NC_EINVAL; /* Null arg */ + + attrpp = NC_findattr(ncap, name); + if(attrpp != NULL) /* name in use */ + { + if(!NC_indef(ncp) ) + { + const size_t xsz = ncx_len_NC_attrV(type, nelems); + attrp = *attrpp; /* convenience */ + + if(xsz > attrp->xsz) + return NC_ENOTINDEFINE; + /* else, we can reuse existing without redef */ + + attrp->xsz = xsz; + attrp->type = type; + attrp->nelems = nelems; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Idouble(&xp, nelems, + value, type); + } + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + const int lstatus = NC_sync(ncp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Idouble + */ + if(lstatus != ENOERR) + return lstatus; + } + + return status; + } + /* else, redefine using existing array slot */ + old = *attrpp; + } + else + { + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + if(ncap->nelems >= NC_MAX_ATTRS) + return NC_EMAXATTS; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + attrp = new_NC_attr(name, type, nelems); + if(attrp == NULL) + return NC_ENOMEM; + + if(nelems != 0) + { + void *xp = attrp->xvalue; + status = ncx_pad_putn_Idouble(&xp, nelems, + value, type); + } + + if(attrpp != NULL) + { + assert(old != NULL); + *attrpp = attrp; + free_NC_attr(old); + } + else + { + const int lstatus = incr_NC_attrarray(ncap, attrp); + /* + * N.B.: potentially overrides NC_ERANGE + * set by ncx_pad_putn_Idouble + */ + if(lstatus != NC_NOERR) + { + free_NC_attr(attrp); + return lstatus; + } + } + + return status; +} + +int +nc_get_att_double(int ncid, int varid, const char *name, double *tp) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + if(attrp->nelems == 0) + return NC_NOERR; + + if(attrp->type == NC_CHAR) + return NC_ECHAR; + + { + const void *xp = attrp->xvalue; + return ncx_pad_getn_Idouble(&xp, attrp->nelems, tp, attrp->type); + } +} + + + +/* deprecated, used to support the 2.x interface */ +int +nc_put_att( + int ncid, + int varid, + const char *name, + nc_type type, + size_t nelems, + const void *value) +{ + switch (type) { + case NC_BYTE: + return nc_put_att_schar(ncid, varid, name, type, nelems, + (schar *)value); + case NC_CHAR: + return nc_put_att_text(ncid, varid, name, nelems, + (char *)value); + case NC_SHORT: + return nc_put_att_short(ncid, varid, name, type, nelems, + (short *)value); + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + return nc_put_att_int(ncid, varid, name, type, nelems, + (int *)value); +#elif SIZEOF_LONG == X_SIZEOF_INT + return nc_put_att_long(ncid, varid, name, type, nelems, + (long *)value); +#endif + case NC_FLOAT: + return nc_put_att_float(ncid, varid, name, type, nelems, + (float *)value); + case NC_DOUBLE: + return nc_put_att_double(ncid, varid, name, type, nelems, + (double *)value); + } + return NC_EBADTYPE; +} + + +/* deprecated, used to support the 2.x interface */ +int +nc_get_att(int ncid, int varid, const char *name, void *value) +{ + int status; + NC_attr *attrp; + + status = NC_lookupattr(ncid, varid, name, &attrp); + if(status != NC_NOERR) + return status; + + switch (attrp->type) { + case NC_BYTE: + return nc_get_att_schar(ncid, varid, name, + (schar *)value); + case NC_CHAR: + return nc_get_att_text(ncid, varid, name, + (char *)value); + case NC_SHORT: + return nc_get_att_short(ncid, varid, name, + (short *)value); + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + return nc_get_att_int(ncid, varid, name, + (int *)value); +#elif SIZEOF_LONG == X_SIZEOF_INT + return nc_get_att_long(ncid, varid, name, + (long *)value); +#endif + case NC_FLOAT: + return nc_get_att_float(ncid, varid, name, + (float *)value); + case NC_DOUBLE: + return nc_get_att_double(ncid, varid, name, + (double *)value); + } + return NC_EBADTYPE; +} diff --git a/Utilities/vtknetcdf/dim.c b/Utilities/vtknetcdf/dim.c new file mode 100644 index 0000000..d0225e7 --- /dev/null +++ b/Utilities/vtknetcdf/dim.c @@ -0,0 +1,520 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: dim.c,v 1.2 2005/07/19 12:31:30 andy Exp $ */ + +#include "nc.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "ncx.h" +#include "fbits.h" + +/* + * Free dim + * Formerly +NC_free_dim(dim) + */ +void +free_NC_dim(NC_dim *dimp) +{ + if(dimp == NULL) + return; + free_NC_string(dimp->name); + free(dimp); +} + + +NC_dim * +new_x_NC_dim(NC_string *name) +{ + NC_dim *dimp; + + dimp = (NC_dim *) malloc(sizeof(NC_dim)); + if(dimp == NULL) + return NULL; + + dimp->name = name; + dimp->size = 0; + + return(dimp); +} + + +/* + * Formerly +NC_new_dim(const char *name, long size) + */ +static NC_dim * +new_NC_dim(const char *name, size_t size) +{ + NC_string *strp; + NC_dim *dimp; + + strp = new_NC_string(strlen(name), name); + if(strp == NULL) + return NULL; + + dimp = new_x_NC_dim(strp); + if(dimp == NULL) + { + free_NC_string(strp); + return NULL; + } + + dimp->size = size; + + return(dimp); +} + + +static NC_dim * +dup_NC_dim(const NC_dim *dimp) +{ + return new_NC_dim(dimp->name->cp, dimp->size); +} + +/* + * Step thru NC_DIMENSION array, seeking the UNLIMITED dimension. + * Return dimid or -1 on not found. + * *dimpp is set to the appropriate NC_dim. + * The loop structure is odd. In order to parallelize, + * we moved a clearer 'break' inside the loop body to the loop test. + */ +int +find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return -1; + + { + int dimid = 0; + NC_dim **loc = ncap->value; + + for(; (size_t) dimid < ncap->nelems + && (*loc)->size != NC_UNLIMITED; dimid++, loc++) + { + /*EMPTY*/ + } + if((size_t)dimid >= ncap->nelems) + return(-1); /* not found */ + /* else, normal return */ + if(dimpp != NULL) + *dimpp = *loc; + return dimid; + } +} + + +/* + * Step thru NC_DIMENSION array, seeking match on name. + * Return dimid or -1 on not found. + * *dimpp is set to the appropriate NC_dim. + * The loop structure is odd. In order to parallelize, + * we moved a clearer 'break' inside the loop body to the loop test. + */ +static int +NC_finddim(const NC_dimarray *ncap, const char *name, NC_dim **dimpp) +{ + + assert(ncap != NULL); + + if(ncap->nelems == 0) + return -1; + + { + size_t slen = strlen(name); + int dimid = 0; + NC_dim **loc = (NC_dim **) ncap->value; + + for(; (size_t) dimid < ncap->nelems + && (strlen((*loc)->name->cp) != slen + || strncmp((*loc)->name->cp, name, slen) != 0); + dimid++, loc++) + { + /*EMPTY*/ + } + if((size_t)dimid >= ncap->nelems) + return(-1); /* not found */ + /* else, normal return */ + if(dimpp != NULL) + *dimpp = *loc; + return(dimid); + } +} + + +/* dimarray */ + + +/* + * Free the stuff "in" (referred to by) an NC_dimarray. + * Leaves the array itself allocated. + */ +void +free_NC_dimarrayV0(NC_dimarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return; + + assert(ncap->value != NULL); + + { + NC_dim **dpp = ncap->value; + NC_dim *const *const end = &dpp[ncap->nelems]; + for( /*NADA*/; dpp < end; dpp++) + { + free_NC_dim(*dpp); + *dpp = NULL; + } + } + ncap->nelems = 0; +} + + +/* + * Free NC_dimarray values. + * formerly +NC_free_array() + */ +void +free_NC_dimarrayV(NC_dimarray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nalloc == 0) + return; + + assert(ncap->value != NULL); + + free_NC_dimarrayV0(ncap); + + free(ncap->value); + ncap->value = NULL; + ncap->nalloc = 0; +} + + +int +dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref) +{ + int status = NC_NOERR; + + assert(ref != NULL); + assert(ncap != NULL); + + if(ref->nelems != 0) + { + const size_t sz = ref->nelems * sizeof(NC_dim *); + ncap->value = (NC_dim **) malloc(sz); + if(ncap->value == NULL) + return NC_ENOMEM; + (void) memset(ncap->value, 0, sz); + ncap->nalloc = ref->nelems; + } + + ncap->nelems = 0; + { + NC_dim **dpp = ncap->value; + const NC_dim **drpp = (const NC_dim **)ref->value; + NC_dim *const *const end = &dpp[ref->nelems]; + for( /*NADA*/; dpp < end; drpp++, dpp++, ncap->nelems++) + { + *dpp = dup_NC_dim(*drpp); + if(*dpp == NULL) + { + status = NC_ENOMEM; + break; + } + } + } + + if(status != NC_NOERR) + { + free_NC_dimarrayV(ncap); + return status; + } + + assert(ncap->nelems == ref->nelems); + + return NC_NOERR; +} + + +/* + * Add a new handle on the end of an array of handles + * Formerly +NC_incr_array(array, tail) + */ +static int +incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp) +{ + NC_dim **vp; + + assert(ncap != NULL); + + if(ncap->nalloc == 0) + { + assert(ncap->nelems == 0); + vp = (NC_dim **) malloc(NC_ARRAY_GROWBY * sizeof(NC_dim *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc = NC_ARRAY_GROWBY; + } + else if(ncap->nelems +1 > ncap->nalloc) + { + vp = (NC_dim **) realloc(ncap->value, + (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_dim *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc += NC_ARRAY_GROWBY; + } + + if(newelemp != NULL) + { + ncap->value[ncap->nelems] = newelemp; + ncap->nelems++; + } + return NC_NOERR; +} + + +NC_dim * +elem_NC_dimarray(const NC_dimarray *ncap, size_t elem) +{ + assert(ncap != NULL); + /* cast needed for braindead systems with signed size_t */ + if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems) + return NULL; + + assert(ncap->value != NULL); + + return ncap->value[elem]; +} + + +/* Public */ + +int +nc_def_dim(int ncid, const char *name, size_t size, int *dimidp) +{ + int status; + NC *ncp; + int dimid; + NC_dim *dimp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + return NC_ENOTINDEFINE; + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) size > X_INT_MAX) /* Backward compat */ + return NC_EINVAL; + + if(size == NC_UNLIMITED) + { + dimid = find_NC_Udim(&ncp->dims, &dimp); + if(dimid != -1) + { + assert(dimid != -1); + return NC_EUNLIMIT; + } + } + + if(ncp->dims.nelems >= NC_MAX_DIMS) + return NC_EMAXDIMS; + + dimid = NC_finddim(&ncp->dims, name, &dimp); + if(dimid != -1) + return NC_ENAMEINUSE; + + dimp = new_NC_dim(name, size); + if(dimp == NULL) + return NC_ENOMEM; + status = incr_NC_dimarray(&ncp->dims, dimp); + if(status != NC_NOERR) + { + free_NC_dim(dimp); + return status; + } + + if(dimidp != NULL) + *dimidp = (int)ncp->dims.nelems -1; + return NC_NOERR; +} + + +int +nc_inq_dimid(int ncid, const char *name, int *dimid_ptr) +{ + int status; + NC *ncp; + int dimid; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimid = NC_finddim(&ncp->dims, name, NULL); + + if(dimid == -1) + return NC_EBADDIM; + + *dimid_ptr = dimid; + return NC_NOERR; +} + + +int +nc_inq_dim(int ncid, int dimid, char *name, size_t *sizep) +{ + int status; + NC *ncp; + NC_dim *dimp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(name != NULL) + { + (void)strncpy(name, dimp->name->cp, + dimp->name->nchars); + name[dimp->name->nchars] = 0; + } + if(sizep != 0) + { + if(dimp->size == NC_UNLIMITED) + *sizep = ncp->numrecs; + else + *sizep = dimp->size; + } + return NC_NOERR; +} + + +int +nc_inq_dimname(int ncid, int dimid, char *name) +{ + int status; + NC *ncp; + NC_dim *dimp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(name != NULL) + { + (void)strncpy(name, dimp->name->cp, + dimp->name->nchars); + name[dimp->name->nchars] = 0; + } + + return NC_NOERR; +} + + +int +nc_inq_dimlen(int ncid, int dimid, size_t *lenp) +{ + int status; + NC *ncp; + NC_dim *dimp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(lenp != 0) + { + if(dimp->size == NC_UNLIMITED) + *lenp = ncp->numrecs; + else + *lenp = dimp->size; + } + return NC_NOERR; +} + + +int +nc_rename_dim( int ncid, int dimid, const char *newname) +{ + int status; + NC *ncp; + int existid; + NC_dim *dimp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + status = NC_check_name(newname); + if(status != NC_NOERR) + return status; + + existid = NC_finddim(&ncp->dims, newname, &dimp); + if(existid != -1) + return NC_ENAMEINUSE; + + dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid); + if(dimp == NULL) + return NC_EBADDIM; + + if(NC_indef(ncp)) + { + NC_string *old = dimp->name; + NC_string *newStr = new_NC_string(strlen(newname), newname); + if(newStr == NULL) + return NC_ENOMEM; + dimp->name = newStr; + free_NC_string(old); + return NC_NOERR; + } + + /* else, not in define mode */ + + status = set_NC_string(dimp->name, newname); + if(status != NC_NOERR) + return status; + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; +} diff --git a/Utilities/vtknetcdf/error.c b/Utilities/vtknetcdf/error.c new file mode 100644 index 0000000..610646c --- /dev/null +++ b/Utilities/vtknetcdf/error.c @@ -0,0 +1,155 @@ +/* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: error.c,v 1.14 90/02/23 16:08:55 davis Exp */ + +/*LINTLIBRARY*/ + +#include "ncconfig.h" +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include "netcdf.h" + + +#ifndef NO_STRERROR +#include <string.h> /* contains prototype for ansi libc function strerror() */ +#else +/* provide a strerror function for older unix systems */ +static char * +strerror(int errnum) +{ + extern int sys_nerr; + extern char *sys_errlist[]; + + if(errnum < 0 || errnum >= sys_nerr) return NULL; + /* else */ + return sys_errlist[errnum]; +} +#endif /* NO_STRERROR */ + + +#ifdef vms +/* UNTESTED */ +/* + * On the vms system, when a system error occurs which is not + * mapped into the unix styled errno values, errno is set EVMSERR + * and a VMS error code is set in vaxc$errno. + * This routine prints the systems message associated with status return + * from a system services call. + */ + +#include <errno.h> +#include <descrip.h> +#include <ssdef.h> + +static const char * +vms_strerror( int status ) +{ + short msglen; + static char msgbuf[256]; + $DESCRIPTOR(message, msgbuf); + register ret; + + msgbuf[0] = 0; + ret = SYS$GETMSG(status, &msglen, &message, 15, 0); + + if(ret != SS$_BUFFEROVF && ret != SS$_NORMAL) { + (void) strcpy(msgbuf, "EVMSERR"); + } + return(msgbuf); +} +#endif /* vms */ + + +static char unknown[] = "Unknown Error"; + + +const char * +nc_strerror(int err) +{ + +#ifdef vms + if(err == EVMSERR) + { + return vms_strerror(err); + } + /* else */ +#endif /* vms */ + + if(NC_ISSYSERR(err)) + { + const char *cp = (const char *) strerror(err); + if(cp == NULL) + return unknown; + /* else */ + return cp; + } + /* else */ + + switch (err) { + case NC_NOERR: + return "No error"; + case NC_EBADID: + return "Not a netCDF id"; + case NC_ENFILE: + return "Too many netCDF files open"; + case NC_EEXIST: + return "netCDF file exists && NC_NOCLOBBER"; + case NC_EINVAL: + return "Invalid argument"; + case NC_EPERM: + return "Write to read only"; + case NC_ENOTINDEFINE: + return "Operation not allowed in data mode"; + case NC_EINDEFINE: + return "Operation not allowed in define mode"; + case NC_EINVALCOORDS: + return "Index exceeds dimension bound"; + case NC_EMAXDIMS: + return "NC_MAX_DIMS exceeded"; + case NC_ENAMEINUSE: + return "String match to name in use"; + case NC_ENOTATT: + return "Attribute not found"; + case NC_EMAXATTS: + return "NC_MAX_ATTRS exceeded"; + case NC_EBADTYPE: + return "Not a netCDF data type or _FillValue type mismatch"; + case NC_EBADDIM: + return "Invalid dimension id or name"; + case NC_EUNLIMPOS: + return "NC_UNLIMITED in the wrong index"; + case NC_EMAXVARS: + return "NC_MAX_VARS exceeded"; + case NC_ENOTVAR: + return "Variable not found"; + case NC_EGLOBAL: + return "Action prohibited on NC_GLOBAL varid"; + case NC_ENOTNC: + return "Not a netCDF file"; + case NC_ESTS: + return "In Fortran, string too short"; + case NC_EMAXNAME: + return "NC_MAX_NAME exceeded"; + case NC_EUNLIMIT: + return "NC_UNLIMITED size already in use"; + case NC_ENORECVARS: + return "nc_rec op when there are no record vars"; + case NC_ECHAR: + return "Attempt to convert between text & numbers"; + case NC_EEDGE: + return "Edge+start exceeds dimension bound"; + case NC_ESTRIDE: + return "Illegal stride"; + case NC_EBADNAME: + return "Attribute or variable name contains illegal characters"; + case NC_ERANGE: + return "Numeric conversion not representable"; + case NC_ENOMEM: + return "Memory allocation (malloc) failure"; + } + /* default */ + return unknown; +} diff --git a/Utilities/vtknetcdf/fbits.h b/Utilities/vtknetcdf/fbits.h new file mode 100644 index 0000000..505c17a --- /dev/null +++ b/Utilities/vtknetcdf/fbits.h @@ -0,0 +1,26 @@ +/* + * Copyright 1995, University Corporation for Atmospheric Research + * See top level COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: fbits.h,v 1.1 2005/07/15 21:56:38 andy Exp $ */ + +#ifndef _FBITS_H_ +#define _FBITS_H_ + +/* + * Macros for dealing with flag bits. + */ +#define fSet(t, f) ((t) |= (f)) +#define fClr(t, f) ((t) &= ~(f)) +#define fIsSet(t, f) ((t) & (f)) +#define fMask(t, f) ((t) & ~(f)) + +/* + * Propositions + */ +/* a implies b */ +#define pIf(a,b) (!(a) || (b)) +/* a if and only if b, use == when it makes sense */ +#define pIff(a,b) (((a) && (b)) || (!(a) && !(b))) + +#endif /*!FBITS_H_*/ diff --git a/Utilities/vtknetcdf/ffio.c b/Utilities/vtknetcdf/ffio.c new file mode 100644 index 0000000..bc01d36 --- /dev/null +++ b/Utilities/vtknetcdf/ffio.c @@ -0,0 +1,625 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: ffio.c,v 1.1 2005/07/15 21:56:38 andy Exp $ */ + +#include "ncconfig.h" +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> /* DEBUG */ +#include <errno.h> +#ifndef ENOERR +#define ENOERR 0 +#endif +#include <fcntl.h> +#include <ffio.h> +#include <unistd.h> +#include <string.h> + +#include "ncio.h" +#include "fbits.h" +#include "rnd.h" + +#if !defined(NDEBUG) && !defined(X_INT_MAX) +#define X_INT_MAX 2147483647 +#endif +#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */ +#define X_ALIGN 4 +#endif + +#define ALWAYS_NC_SHARE 0 /* DEBUG */ + +/* Begin OS */ + +/* + * What is the preferred I/O block size? + * (This becomes the default *sizehint == ncp->chunk in the higher layers.) + * TODO: What is the the best answer here? + */ +static size_t +blksize(int fd) +{ + struct ffc_stat_s sb; + struct ffsw sw; + if (fffcntl(fd, FC_STAT, &sb, &sw) > -1) + { + if(sb.st_oblksize > 0) + return (size_t) sb.st_oblksize; + } + /* else, silent in the face of error */ + return (size_t) 32768; +} + +/* + * Sortof like ftruncate, except won't make the + * file shorter. + */ +static int +fgrow(const int fd, const off_t len) +{ + struct ffc_stat_s sb; + struct ffsw sw; + if (fffcntl(fd, FC_STAT, &sb, &sw) < 0) + return errno; + if (len < sb.st_size) + return ENOERR; + { + const long dumb = 0; + /* cache current position */ + const off_t pos = ffseek(fd, 0, SEEK_CUR); + if(pos < 0) + return errno; + if (ffseek(fd, len-sizeof(dumb), SEEK_SET) < 0) + return errno; + if(ffwrite(fd, (void *)&dumb, sizeof(dumb)) < 0) + return errno; + if (ffseek(fd, pos, SEEK_SET) < 0) + return errno; + } + /* else */ + return ENOERR; +} + +/* End OS */ +/* Begin ffio */ + +static int +ffio_pgout(ncio *const nciop, + off_t const offset, const size_t extent, + const void *const vp, off_t *posp) +{ +#ifdef X_ALIGN + assert(offset % X_ALIGN == 0); + assert(extent % X_ALIGN == 0); +#endif + + if(*posp != offset) + { + if(ffseek(nciop->fd, offset, SEEK_SET) != offset) + { + return errno; + } + *posp = offset; + } + if(ffwrite(nciop->fd, vp, extent) != extent) + { + return errno; + } + *posp += extent; + + return ENOERR; +} + + +static int +ffio_pgin(ncio *const nciop, + off_t const offset, const size_t extent, + void *const vp, size_t *nreadp, off_t *posp) +{ + int status; + ssize_t nread; + +#ifdef X_ALIGN + assert(offset % X_ALIGN == 0); + assert(extent % X_ALIGN == 0); +#endif + + if(*posp != offset) + { + if(ffseek(nciop->fd, offset, SEEK_SET) != offset) + { + status = errno; + return status; + } + *posp = offset; + } + + errno = 0; + nread = ffread(nciop->fd, vp, extent); + if(nread != extent) + { + status = errno; + if(nread == -1 || status != ENOERR) + return status; + /* else it's okay we read 0. */ + } + *nreadp = nread; + *posp += nread; + + return ENOERR; +} + +/* */ + +typedef struct ncio_ffio { + off_t pos; + /* buffer */ + off_t bf_offset; + size_t bf_extent; + size_t bf_cnt; + void *bf_base; +} ncio_ffio; + + +static int +ncio_ffio_rel(ncio *const nciop, off_t offset, int rflags) +{ + ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; + int status = ENOERR; + + assert(ffp->bf_offset <= offset); + assert(ffp->bf_cnt != 0); + assert(ffp->bf_cnt <= ffp->bf_extent); +#ifdef X_ALIGN + assert(offset < ffp->bf_offset + X_ALIGN); + assert(ffp->bf_cnt % X_ALIGN == 0 ); +#endif + + if(fIsSet(rflags, RGN_MODIFIED)) + { + if(!fIsSet(nciop->ioflags, NC_WRITE)) + return EPERM; /* attempt to write readonly file */ + + status = ffio_pgout(nciop, ffp->bf_offset, + ffp->bf_cnt, + ffp->bf_base, &ffp->pos); + /* if error, invalidate buffer anyway */ + } + ffp->bf_offset = OFF_NONE; + ffp->bf_cnt = 0; + return status; +} + + +static int +ncio_ffio_get(ncio *const nciop, + off_t offset, size_t extent, + int rflags, + void **const vpp) +{ + ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; + int status = ENOERR; +#ifdef X_ALIGN + size_t rem; +#endif + + if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE)) + return EPERM; /* attempt to write readonly file */ + + assert(extent != 0); + assert(extent < X_INT_MAX); /* sanity check */ + assert(offset < X_INT_MAX); /* sanity check */ + + assert(ffp->bf_cnt == 0); + +#ifdef X_ALIGN + /* round to seekable boundaries */ + rem = offset % X_ALIGN; + if(rem != 0) + { + offset -= rem; + extent += rem; + } + + { + const size_t rndup = extent % X_ALIGN; + if(rndup != 0) + extent += X_ALIGN - rndup; + } + + assert(offset % X_ALIGN == 0); + assert(extent % X_ALIGN == 0); +#endif + + if(ffp->bf_extent < extent) + { + if(ffp->bf_base != NULL) + { + free(ffp->bf_base); + ffp->bf_base = NULL; + ffp->bf_extent = 0; + } + assert(ffp->bf_extent == 0); + ffp->bf_base = malloc(extent); + if(ffp->bf_base == NULL) + return ENOMEM; + ffp->bf_extent = extent; + } + + status = ffio_pgin(nciop, offset, + extent, + ffp->bf_base, + &ffp->bf_cnt, &ffp->pos); + if(status != ENOERR) + return status; + + ffp->bf_offset = offset; + + if(ffp->bf_cnt < extent) + { + (void) memset((char *)ffp->bf_base + ffp->bf_cnt, 0, + extent - ffp->bf_cnt); + ffp->bf_cnt = extent; + } + + +#ifdef X_ALIGN + *vpp = (char *)ffp->bf_base + rem; +#else + *vpp = (char *)ffp->bf_base; +#endif + return ENOERR; +} + + +static int +ncio_ffio_move(ncio *const nciop, off_t to, off_t from, + size_t nbytes, int rflags) +{ + int status = ENOERR; + off_t lower = from; + off_t upper = to; + char *base; + size_t diff = upper - lower; + size_t extent = diff + nbytes; + + rflags &= RGN_NOLOCK; /* filter unwanted flags */ + + if(to == from) + return ENOERR; /* NOOP */ + + if(to > from) + { + /* growing */ + lower = from; + upper = to; + } + else + { + /* shrinking */ + lower = to; + upper = from; + } + + diff = upper - lower; + extent = diff + nbytes; + + status = ncio_ffio_get(nciop, lower, extent, RGN_WRITE|rflags, + (void **)&base); + + if(status != ENOERR) + return status; + + if(to > from) + (void) memmove(base + diff, base, nbytes); + else + (void) memmove(base, base + diff, nbytes); + + (void) ncio_ffio_rel(nciop, lower, RGN_MODIFIED); + + return status; +} + + +static int +ncio_ffio_sync(ncio *const nciop) +{ + if(ffflush(nciop->fd) < 0) + return errno; + return ENOERR; +} + +static void +ncio_ffio_free(void *const pvt) +{ + ncio_ffio *ffp = (ncio_ffio *)pvt; + if(ffp == NULL) + return; + + if(ffp->bf_base != NULL) + { + free(ffp->bf_base); + ffp->bf_base = NULL; + ffp->bf_offset = OFF_NONE; + ffp->bf_extent = 0; + ffp->bf_cnt = 0; + } +} + + +static int +ncio_ffio_init2(ncio *const nciop, size_t *sizehintp) +{ + ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; + + assert(nciop->fd >= 0); + + ffp->bf_extent = *sizehintp; + + assert(ffp->bf_base == NULL); + + /* this is separate allocation because it may grow */ + ffp->bf_base = malloc(ffp->bf_extent); + if(ffp->bf_base == NULL) + { + ffp->bf_extent = 0; + return ENOMEM; + } + /* else */ + return ENOERR; +} + + +static void +ncio_ffio_init(ncio *const nciop) +{ + ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; + + *((ncio_relfunc **)&nciop->rel) = ncio_ffio_rel; /* cast away const */ + *((ncio_getfunc **)&nciop->get) = ncio_ffio_get; /* cast away const */ + *((ncio_movefunc **)&nciop->move) = ncio_ffio_move; /* cast away const */ + *((ncio_syncfunc **)&nciop->sync) = ncio_ffio_sync; /* cast away const */ + *((ncio_freefunc **)&nciop->free) = ncio_ffio_free; /* cast away const */ + + ffp->pos = -1; + ffp->bf_offset = OFF_NONE; + ffp->bf_extent = 0; + ffp->bf_cnt = 0; + ffp->bf_base = NULL; +} + +/* */ + +static void +ncio_free(ncio *nciop) +{ + if(nciop == NULL) + return; + + if(nciop->free != NULL) + nciop->free(nciop->pvt); + + free(nciop); +} + + +static ncio * +ncio_new(const char *path, int ioflags) +{ + size_t sz_ncio = M_RNDUP(sizeof(ncio)); + size_t sz_path = M_RNDUP(strlen(path) +1); + size_t sz_ncio_pvt; + ncio *nciop; + +#if ALWAYS_NC_SHARE /* DEBUG */ + fSet(ioflags, NC_SHARE); +#endif + + if(fIsSet(ioflags, NC_SHARE)) + fprintf(stderr, "NC_SHARE not implemented for ffio\n"); + + sz_ncio_pvt = sizeof(ncio_ffio); + + nciop = (ncio *) malloc(sz_ncio + sz_path + sz_ncio_pvt); + if(nciop == NULL) + return NULL; + + nciop->ioflags = ioflags; + *((int *)&nciop->fd) = -1; /* cast away const */ + + nciop->path = (char *) ((char *)nciop + sz_ncio); + (void) strcpy((char *)nciop->path, path); /* cast away const */ + + /* cast away const */ + *((void **)&nciop->pvt) = (void *)(nciop->path + sz_path); + + ncio_ffio_init(nciop); + + return nciop; +} + + +/* Public below this point */ + +/* TODO: Is this reasonable for this platform? */ +static const size_t NCIO_MINBLOCKSIZE = 256; +static const size_t NCIO_MAXBLOCKSIZE = 268435456; /* sanity check, about X_SIZE_T_MAX/8 */ + +int +ncio_create(const char *path, int ioflags, + size_t initialsz, + off_t igeto, size_t igetsz, size_t *sizehintp, + ncio **nciopp, void **const igetvpp) +{ + ncio *nciop; + char *ControlString; + int oflags = (O_RDWR|O_CREAT|O_TRUNC); + int fd; + int status; + struct ffsw stat; + + if(initialsz < (size_t)igeto + igetsz) + initialsz = (size_t)igeto + igetsz; + + fSet(ioflags, NC_WRITE); + + if(path == NULL || *path == 0) + return EINVAL; + + nciop = ncio_new(path, ioflags); + if(nciop == NULL) + return ENOMEM; + + /* TODO: use *sizehintp for input? */ + ControlString = getenv("NETCDF_FFIOSPEC"); + if(ControlString == NULL) + { + ControlString="bufa:336:2"; + } + + if(fIsSet(ioflags, NC_NOCLOBBER)) + fSet(oflags, O_EXCL); + + fd = ffopens(path, oflags, 0666, 0, &stat, ControlString); + if(fd < 0) + { + status = errno; + goto unwind_new; + } + *((int *)&nciop->fd) = fd; /* cast away const */ + + if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE) + { + /* Use default */ + *sizehintp = blksize(fd); + } + else + { + *sizehintp = M_RNDUP(*sizehintp); + } + + status = ncio_ffio_init2(nciop, sizehintp); + if(status != ENOERR) + goto unwind_open; + + if(initialsz != 0) + { + status = fgrow(fd, (off_t)initialsz); + if(status != ENOERR) + goto unwind_open; + } + + if(igetsz != 0) + { + status = nciop->get(nciop, + igeto, igetsz, + RGN_WRITE, + igetvpp); + if(status != ENOERR) + goto unwind_open; + } + + *nciopp = nciop; + return ENOERR; + +unwind_open: + (void) ffclose(fd); + /* ?? unlink */ + /*FALLTHRU*/ +unwind_new: + ncio_free(nciop); + return status; +} + + +int +ncio_open(const char *path, + int ioflags, + off_t igeto, size_t igetsz, size_t *sizehintp, + ncio **nciopp, void **const igetvpp) +{ + ncio *nciop; + char *ControlString; + int oflags = fIsSet(ioflags, NC_WRITE) ? O_RDWR : O_RDONLY; + int fd; + int status; + struct ffsw stat; + + if(path == NULL || *path == 0) + return EINVAL; + + nciop = ncio_new(path, ioflags); + if(nciop == NULL) + return ENOMEM; + + /* TODO: use *sizehintp for input? */ + ControlString = getenv("NETCDF_FFIOSPEC"); + if(ControlString == NULL) + { + ControlString="bufa:336:2"; + } + + fd = ffopens(path, oflags, 0, 0, &stat, ControlString); + if(fd < 0) + { + status = errno; + goto unwind_new; + } + *((int *)&nciop->fd) = fd; /* cast away const */ + + if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE) + { + /* Use default */ + *sizehintp = blksize(fd); + } + else + { + *sizehintp = M_RNDUP(*sizehintp); + } + + status = ncio_ffio_init2(nciop, sizehintp); + if(status != ENOERR) + goto unwind_open; + + if(igetsz != 0) + { + status = nciop->get(nciop, + igeto, igetsz, + 0, + igetvpp); + if(status != ENOERR) + goto unwind_open; + } + + *nciopp = nciop; + return ENOERR; + +unwind_open: + (void) ffclose(fd); + /*FALLTHRU*/ +unwind_new: + ncio_free(nciop); + return status; +} + + +int +ncio_close(ncio *nciop, int doUnlink) +{ + int status = ENOERR; + + if(nciop == NULL) + return EINVAL; + + status = nciop->sync(nciop); + + (void) ffclose(nciop->fd); + + if(doUnlink) + (void) unlink(nciop->path); + + ncio_free(nciop); + + return status; +} diff --git a/Utilities/vtknetcdf/libvers.c b/Utilities/vtknetcdf/libvers.c new file mode 100644 index 0000000..5dd2274 --- /dev/null +++ b/Utilities/vtknetcdf/libvers.c @@ -0,0 +1,32 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: libvers.c,v 1.1 2005/07/15 21:56:38 andy Exp $ */ + +#include "netcdf.h" + +/* + * A version string. + */ +#define SKIP_LEADING_GARBAGE 33 /* # of chars prior to the actual version */ +#define XSTRING(x) #x +#define STRING(x) XSTRING(x) +static const char nc_libvers[] = + "\044Id: \100(#) netcdf library version " STRING(VERSION) " of "__DATE__" "__TIME__" $"; + +const char * +nc_inq_libvers(void) +{ + return &nc_libvers[SKIP_LEADING_GARBAGE]; +} + +#if 0 /* TEST JIG */ +#include <stdio.h> + +main() +{ + (void) printf("Version: %s\n", nc_inq_libvers()); + return 0; +} +#endif diff --git a/Utilities/vtknetcdf/nc.c b/Utilities/vtknetcdf/nc.c new file mode 100644 index 0000000..9394e6f --- /dev/null +++ b/Utilities/vtknetcdf/nc.c @@ -0,0 +1,1339 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: nc.c,v 1.3 2005/08/29 17:54:17 andy Exp $ */ + +#include "nc.h" +#include "rnd.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "ncx.h" + + +/* list of open netcdf's */ +static NC *NClist = NULL; + +static void +add_to_NCList(NC *ncp) +{ + assert(ncp != NULL); + + ncp->prev = NULL; + if(NClist != NULL) + NClist->prev = ncp; + ncp->next = NClist; + NClist = ncp; +} + +static void +del_from_NCList(NC *ncp) +{ + assert(ncp != NULL); + + if(NClist == ncp) + { + assert(ncp->prev == NULL); + NClist = ncp->next; + } + else + { + assert(ncp->prev != NULL); + ncp->prev->next = ncp->next; + } + + if(ncp->next != NULL) + ncp->next->prev = ncp->prev; + + ncp->next = NULL; + ncp->prev = NULL; +} + + +int +NC_check_id(int ncid, NC **ncpp) +{ + NC *ncp; + + if(ncid >= 0) + { + for(ncp = NClist; ncp != NULL; ncp = ncp->next) + { + if(ncp->nciop->fd == ncid) + { + *ncpp = ncp; + return NC_NOERR; /* normal return */ + } + } + } + + /* else, not found */ + return NC_EBADID; +} + + +static void +free_NC(NC *ncp) +{ + if(ncp == NULL) + return; + free_NC_dimarrayV(&ncp->dims); + free_NC_attrarrayV(&ncp->attrs); + free_NC_vararrayV(&ncp->vars); + free(ncp); +} + + +static NC * +new_NC(const size_t *chunkp) +{ + NC *ncp; + + ncp = (NC *) malloc(sizeof(NC)); + if(ncp == NULL) + return NULL; + (void) memset(ncp, 0, sizeof(NC)); + + ncp->xsz = MIN_NC_XSZ; + assert(ncp->xsz == ncx_len_NC(ncp,0)); + + ncp->chunk = chunkp != NULL ? *chunkp : NC_SIZEHINT_DEFAULT; + + return ncp; +} + + +static NC * +dup_NC(const NC *ref) +{ + NC *ncp; + + ncp = (NC *) malloc(sizeof(NC)); + if(ncp == NULL) + return NULL; + (void) memset(ncp, 0, sizeof(NC)); + + if(dup_NC_dimarrayV(&ncp->dims, &ref->dims) != NC_NOERR) + goto err; + if(dup_NC_attrarrayV(&ncp->attrs, &ref->attrs) != NC_NOERR) + goto err; + if(dup_NC_vararrayV(&ncp->vars, &ref->vars) != NC_NOERR) + goto err; + + ncp->xsz = ref->xsz; + ncp->begin_var = ref->begin_var; + ncp->begin_rec = ref->begin_rec; + ncp->recsize = ref->recsize; + ncp->numrecs = ref->numrecs; + return ncp; +err: + free_NC(ncp); + return NULL; +} + + +/* + * Verify that this is a user nc_type + * Formerly +NCcktype() + * Sense of the return is changed. + */ +int +nc_cktype(nc_type type) +{ + switch((int)type){ + case NC_BYTE: + case NC_CHAR: + case NC_SHORT: + case NC_INT: + case NC_FLOAT: + case NC_DOUBLE: + return(NC_NOERR); + } + return(NC_EBADTYPE); +} + + +/* + * How many objects of 'type' + * will fit into xbufsize? + */ +size_t +ncx_howmany(nc_type type, size_t xbufsize) +{ + switch(type){ + case NC_BYTE: + case NC_CHAR: + return xbufsize; + case NC_SHORT: + return xbufsize/X_SIZEOF_SHORT; + case NC_INT: + return xbufsize/X_SIZEOF_INT; + case NC_FLOAT: + return xbufsize/X_SIZEOF_FLOAT; + case NC_DOUBLE: + return xbufsize/X_SIZEOF_DOUBLE; + } + assert("ncx_howmany: Bad type" == 0); + return(0); +} + +#define D_RNDUP(x, align) _RNDUP(x, (off_t)(align)) + +/* + * Compute each variable's 'begin' offset, + * update 'begin_rec' as well. + */ +static void +NC_begins(NC *ncp, + size_t h_minfree, size_t v_align, + size_t v_minfree, size_t r_align) +{ + size_t ii; + int sizeof_off_t; + off_t index = 0; + NC_var **vpp; + NC_var *last = NULL; + + if(v_align == NC_ALIGN_CHUNK) + v_align = ncp->chunk; + if(r_align == NC_ALIGN_CHUNK) + r_align = ncp->chunk; + + if (fIsSet(ncp->flags, NC_64BIT_OFFSET)) { + sizeof_off_t = 8; + } else { + sizeof_off_t = 4; + } + + ncp->xsz = ncx_len_NC(ncp,sizeof_off_t); + + if(ncp->vars.nelems == 0) + return; + + index = (off_t) ncp->xsz; + ncp->begin_var = D_RNDUP(index, v_align); + if(ncp->begin_var - index < (off_t)h_minfree) + { + ncp->begin_var = D_RNDUP(index + (off_t)h_minfree, v_align); + } + index = ncp->begin_var; + + /* loop thru vars, first pass is for the 'non-record' vars */ + vpp = ncp->vars.value; + for(ii = 0; ii < ncp->vars.nelems ; ii++, vpp++) + { + if( IS_RECVAR(*vpp) ) + { + /* skip record variables on this pass */ + continue; + } +#if 0 +fprintf(stderr, " VAR %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index); +#endif + (*vpp)->begin = index; + index += (*vpp)->len; + } + + ncp->begin_rec = D_RNDUP(index, r_align); + if(ncp->begin_rec - index < (off_t)v_minfree) + { + ncp->begin_rec = D_RNDUP(index + (off_t)v_minfree, r_align); + } + index = ncp->begin_rec; + + ncp->recsize = 0; + + /* loop thru vars, second pass is for the 'record' vars */ + vpp = (NC_var **)ncp->vars.value; + for(ii = 0; ii < ncp->vars.nelems; ii++, vpp++) + { + if( !IS_RECVAR(*vpp) ) + { + /* skip non-record variables on this pass */ + continue; + } + +#if 0 +fprintf(stderr, " REC %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index); +#endif + (*vpp)->begin = index; + index += (*vpp)->len; + ncp->recsize += (*vpp)->len; + last = (*vpp); + } + + /* + * for special case of exactly one record variable, pack value + */ + if(last != NULL && ncp->recsize == last->len) + ncp->recsize = *last->dsizes * last->xsz; + + if(NC_IsNew(ncp)) + ncp->numrecs = 0; + +} + + +/* + * Read just the numrecs member. + * (A relatively expensive way to do things.) + */ +int +read_numrecs(NC *ncp) +{ + int status = NC_NOERR; + const void *xp; + + assert(!NC_indef(ncp)); + +#define NC_NUMRECS_OFFSET 4 +#define NC_NUMRECS_EXTENT 4 + status = ncp->nciop->get(ncp->nciop, + NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, 0, (void **)&xp); + /* cast away const */ + if(status != NC_NOERR) + return status; + + status = ncx_get_size_t(&xp, &ncp->numrecs); + + { + ncio_relfunc* func = (ncio_relfunc*)(ncp->nciop->rel); + (void) (func(ncp->nciop, NC_NUMRECS_OFFSET, 0)); + } + + if(status == NC_NOERR) + fClr(ncp->flags, NC_NDIRTY); + + return status; +} + + +/* + * Write out just the numrecs member. + * (A relatively expensive way to do things.) + */ +int +write_numrecs(NC *ncp) +{ + int status = NC_NOERR; + void *xp; + + assert(!NC_readonly(ncp)); + assert(!NC_indef(ncp)); + + status = ncp->nciop->get(ncp->nciop, + NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, RGN_WRITE, &xp); + if(status != NC_NOERR) + return status; + + status = ncx_put_size_t(&xp, &ncp->numrecs); + + { + ncio_relfunc* func = (ncio_relfunc*)(ncp->nciop->rel); + (void) (func(ncp->nciop, NC_NUMRECS_OFFSET, RGN_MODIFIED)); + } + + if(status == NC_NOERR) + fClr(ncp->flags, NC_NDIRTY); + + return status; +} + + +/* + * Read in the header + * It is expensive. + */ +static int +read_NC(NC *ncp) +{ + int status = NC_NOERR; + + free_NC_dimarrayV(&ncp->dims); + free_NC_attrarrayV(&ncp->attrs); + free_NC_vararrayV(&ncp->vars); + + status = nc_get_NC(ncp); + + if(status == NC_NOERR) + fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY); + + return status; +} + + +/* + * Write out the header + */ +static int +write_NC(NC *ncp) +{ + int status = NC_NOERR; + + assert(!NC_readonly(ncp)); + + status = ncx_put_NC(ncp, NULL, 0, 0); + + if(status == NC_NOERR) + fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY); + + return status; +} + + +/* + * Write the header or the numrecs if necessary. + */ +int +NC_sync(NC *ncp) +{ + assert(!NC_readonly(ncp)); + + if(NC_hdirty(ncp)) + { + return write_NC(ncp); + } + /* else */ + + if(NC_ndirty(ncp)) + { + return write_numrecs(ncp); + } + /* else */ + + return NC_NOERR; +} + + +/* + * Initialize the 'non-record' variables. + */ +static int +fillerup(NC *ncp) +{ + int status = NC_NOERR; + size_t ii; + NC_var **varpp; + + assert(!NC_readonly(ncp)); + assert(NC_dofill(ncp)); + + /* loop thru vars */ + varpp = ncp->vars.value; + for(ii = 0; ii < ncp->vars.nelems; ii++, varpp++) + { + if(IS_RECVAR(*varpp)) + { + /* skip record variables */ + continue; + } + + status = fill_NC_var(ncp, *varpp, 0); + if(status != NC_NOERR) + break; + } + return status; +} + +/* Begin endef */ + +/* + */ +static int +fill_added_recs(NC *gnu, NC *old) +{ + NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value; + + int recno = 0; + for(; (off_t)recno < (off_t)old->numrecs; recno++) + { + int varid = (int)old->vars.nelems; + for(; varid < (int)gnu->vars.nelems; varid++) + { + const NC_var *const gnu_varp = *(gnu_varpp + varid); + if(!IS_RECVAR(gnu_varp)) + { + /* skip non-record variables */ + continue; + } + /* else */ + { + const int status = fill_NC_var(gnu, gnu_varp, recno); + if(status != NC_NOERR) + return status; + } + } + } + + return NC_NOERR; +} + +/* + */ +static int +fill_added(NC *gnu, NC *old) +{ + NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value; + int varid = (int)old->vars.nelems; + + for(; varid < (int)gnu->vars.nelems; varid++) + { + const NC_var *const gnu_varp = *(gnu_varpp + varid); + if(IS_RECVAR(gnu_varp)) + { + /* skip record variables */ + continue; + } + /* else */ + { + const int status = fill_NC_var(gnu, gnu_varp, 0); + if(status != NC_NOERR) + return status; + } + } + + return NC_NOERR; +} + + +/* + * Move the records "out". + * Fill as needed. + */ +static int +move_recs_r(NC *gnu, NC *old) +{ + int status; + int recno; + int varid; + NC_var **gnu_varpp = (NC_var **)gnu->vars.value; + NC_var **old_varpp = (NC_var **)old->vars.value; + NC_var *gnu_varp; + NC_var *old_varp; + off_t gnu_off; + off_t old_off; + + /* Don't parallelize this loop */ + for(recno = (int)old->numrecs -1; recno >= 0; recno--) + { + /* Don't parallelize this loop */ + for(varid = (int)old->vars.nelems -1; varid >= 0; varid--) + { + gnu_varp = *(gnu_varpp + varid); + if(!IS_RECVAR(gnu_varp)) + { + /* skip non-record variables on this pass */ + continue; + } + /* else */ + + /* else, a pre-existing variable */ + old_varp = *(old_varpp + varid); + gnu_off = gnu_varp->begin + (off_t)(gnu->recsize * recno); + old_off = old_varp->begin + (off_t)(old->recsize * recno); + + if(gnu_off == old_off) + continue; /* nothing to do */ + + assert(gnu_off > old_off); + + status = gnu->nciop->move(gnu->nciop, gnu_off, old_off, + old_varp->len, 0); + + if(status != NC_NOERR) + return status; + + } + } + + gnu->numrecs = old->numrecs; + + return NC_NOERR; +} + + +/* + * Move the "non record" variables "out". + * Fill as needed. + */ +static int +move_vars_r(NC *gnu, NC *old) +{ + int status; + int varid; + NC_var **gnu_varpp = (NC_var **)gnu->vars.value; + NC_var **old_varpp = (NC_var **)old->vars.value; + NC_var *gnu_varp; + NC_var *old_varp; + off_t gnu_off; + off_t old_off; + + /* Don't parallelize this loop */ + for(varid = (int)old->vars.nelems -1; + varid >= 0; varid--) + { + gnu_varp = *(gnu_varpp + varid); + if(IS_RECVAR(gnu_varp)) + { + /* skip record variables on this pass */ + continue; + } + /* else */ + + old_varp = *(old_varpp + varid); + gnu_off = gnu_varp->begin; + old_off = old_varp->begin; + + if(gnu_off == old_off) + continue; /* nothing to do */ + + assert(gnu_off > old_off); + + status = gnu->nciop->move(gnu->nciop, gnu_off, old_off, + old_varp->len, 0); + + if(status != NC_NOERR) + return status; + + } + + return NC_NOERR; +} + + +/* + * Move the "non record" variables "in". + * Fill as needed. + */ +static int +move_vars_f(NC *gnu, NC *old) +{ + int status; + int varid; + NC_var **gnu_varpp = (NC_var **)gnu->vars.value; + NC_var **old_varpp = (NC_var **)old->vars.value; + NC_var *gnu_varp; + NC_var *old_varp; + off_t gnu_off; + off_t old_off; + + + for(varid = 0; (size_t) varid < old->vars.nelems; varid++) + { + gnu_varp = *(gnu_varpp + varid); + if(IS_RECVAR(gnu_varp)) + { + /* skip record variables on this pass */ + continue; + } + /* else */ + + old_varp = *(old_varpp + varid); + gnu_off = gnu_varp->begin; + old_off = old_varp->begin; + + if(gnu_off == old_off) + continue; /* nothing to do */ + + assert(gnu_off < old_off); + + status = gnu->nciop->move(gnu->nciop, gnu_off, old_off, + old_varp->len, 0); + + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; +} + + +/* + * Move the records "in". + * Fill as needed. + */ +static int +move_recs_f(NC *gnu, NC *old) +{ + int status; + size_t recno; + int varid; + NC_var **gnu_varpp = (NC_var **)gnu->vars.value; + NC_var **old_varpp = (NC_var **)old->vars.value; + NC_var *gnu_varp; + NC_var *old_varp; + off_t gnu_off; + off_t old_off; + + + for(recno = 0; recno < old->numrecs; recno++) + { + for(varid = 0; (size_t) varid < gnu->vars.nelems; varid++) + { + gnu_varp = *(gnu_varpp + varid); + if(!IS_RECVAR(gnu_varp)) + { + /* skip non-record variables on this pass */ + continue; + } + /* else */ + + if((size_t) varid < old->vars.nelems) + { + /* a pre-existing variable */ + old_varp = *(old_varpp + varid); + gnu_off = gnu_varp->begin + + (off_t)(gnu->recsize * recno); + old_off = old_varp->begin + + (off_t)(old->recsize * recno); + + if(gnu_off == old_off) + continue; /* nothing to do */ + + assert(gnu_off < old_off); + + status = gnu->nciop->move(gnu->nciop, gnu_off, old_off, + old_varp->len, 0); + + if(status != NC_NOERR) + return status; + continue; + } + + + /* else, a new variable */ + if(NC_dofill(gnu)) + { + status = fill_NC_var(gnu, gnu_varp, recno); + if(status != NC_NOERR) + return status; + } + } + } + + gnu->numrecs = old->numrecs; + + return NC_NOERR; +} + + +/* + * End define mode. + * Common code for ncendef, ncclose(endef) + */ +static int +NC_endef(NC *ncp, + size_t h_minfree, size_t v_align, + size_t v_minfree, size_t r_align) +{ + int status = NC_NOERR; + + assert(!NC_readonly(ncp)); + assert(NC_indef(ncp)); + + NC_begins(ncp, h_minfree, v_align, v_minfree, r_align); + + if(ncp->old != NULL) + { + /* a plain redef, not a create */ + assert(!NC_IsNew(ncp)); + assert(fIsSet(ncp->flags, NC_INDEF)); + + if(ncp->vars.nelems != 0) + { + if(ncp->begin_rec > ncp->old->begin_rec) + { + status = move_recs_r(ncp, ncp->old); + if(status != NC_NOERR) + return status; + if(ncp->begin_var > ncp->old->begin_var) + { + status = move_vars_r(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } + else + { + /* ncp->begin_var <= ncp->old->begin_var */ + /* rare */ + status = move_vars_f(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } + } + else if(ncp->begin_rec < ncp->old->begin_rec) + { + if(ncp->begin_var < ncp->old->begin_var) + { + status = move_vars_f(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } +#ifndef NDEBUG + else + { + assert("Number of non rec vars shrank (<) ???" + == 0); + } +#endif + status = move_recs_f(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } + else + { + /* ncp->begin_rec == ncp->old->begin_rec */ + /* rare and untested */ + if(ncp->begin_var < ncp->old->begin_var) + { + status = move_vars_f(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } +#ifndef NDEBUG + else if(ncp->begin_var > ncp->old->begin_var) + { + assert("Number of non rec vars shrank (==) ???" + == 0); + } +#endif + /* ncp->begin_var == ncp->old->begin_var */ + /* NOOP */ + } + } + } + + status = write_NC(ncp); + if(status != NC_NOERR) + return status; + + if(NC_dofill(ncp)) + { + if(NC_IsNew(ncp)) + { + status = fillerup(ncp); + if(status != NC_NOERR) + return status; + + } + else if(ncp->vars.nelems > ncp->old->vars.nelems) + { + status = fill_added(ncp, ncp->old); + if(status != NC_NOERR) + return status; + status = fill_added_recs(ncp, ncp->old); + if(status != NC_NOERR) + return status; + } + } + + if(ncp->old != NULL) + { + free_NC(ncp->old); + ncp->old = NULL; + } + + fClr(ncp->flags, NC_CREAT | NC_INDEF); + return(status); +} + + +/* Public */ + +int +nc__create(const char * path, int ioflags, size_t initialsz, + size_t *chunksizehintp, int *ncid_ptr) +{ + NC *ncp; + int status; + void *xp = NULL; + int sizeof_off_t = 0; + +#if ALWAYS_NC_SHARE /* DEBUG */ + fSet(ioflags, NC_SHARE); +#endif + + ncp = new_NC(chunksizehintp); + if(ncp == NULL) + return NC_ENOMEM; + assert(ncp->flags == 0); + + if (fIsSet(ioflags, NC_64BIT_OFFSET)) { + fSet(ncp->flags, NC_64BIT_OFFSET); + sizeof_off_t = 8; + } else { + sizeof_off_t = 4; + } + + assert(ncp->xsz == ncx_len_NC(ncp,sizeof_off_t)); + + status = ncio_create(path, ioflags, + initialsz, + 0, ncp->xsz, &ncp->chunk, + &ncp->nciop, &xp); + if(status != NC_NOERR) + { + /* translate error status */ + if(status == EEXIST) + status = NC_EEXIST; + goto unwind_alloc; + } + + fSet(ncp->flags, NC_CREAT); + + if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) + { + /* + * NC_SHARE implies sync up the number of records as well. + * (File format version one.) + * Note that other header changes are not shared + * automatically. Some sort of IPC (external to this package) + * would be used to trigger a call to nc_sync(). + */ + fSet(ncp->flags, NC_NSYNC); + } + + status = ncx_put_NC(ncp, &xp, sizeof_off_t, ncp->xsz); + if(status != NC_NOERR) + goto unwind_ioc; + + add_to_NCList(ncp); + + if(chunksizehintp != NULL) + *chunksizehintp = ncp->chunk; + *ncid_ptr = ncp->nciop->fd; + return NC_NOERR; + +unwind_ioc: + (void) ncio_close(ncp->nciop, 1); /* N.B.: unlink */ + ncp->nciop = NULL; + /*FALLTHRU*/ +unwind_alloc: + free_NC(ncp); + return status; +} + +int +nc_create(const char * path, int ioflags, int *ncid_ptr) +{ + return nc__create(path, ioflags, 0, NULL, ncid_ptr); +} + + +int +nc__open(const char * path, int ioflags, size_t *chunksizehintp, int *ncid_ptr) +{ + NC *ncp; + int status; + +#if ALWAYS_NC_SHARE /* DEBUG */ + fSet(ioflags, NC_SHARE); +#endif + + ncp = new_NC(chunksizehintp); + if(ncp == NULL) + return NC_ENOMEM; + + status = ncio_open(path, ioflags, + 0, 0, &ncp->chunk, + &ncp->nciop, 0); + if(status) + goto unwind_alloc; + + assert(ncp->flags == 0); + + if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) + { + /* + * NC_SHARE implies sync up the number of records as well. + * (File format version one.) + * Note that other header changes are not shared + * automatically. Some sort of IPC (external to this package) + * would be used to trigger a call to nc_sync(). + */ + fSet(ncp->flags, NC_NSYNC); + } + + status = nc_get_NC(ncp); + if(status != NC_NOERR) + goto unwind_ioc; + + add_to_NCList(ncp); + + if(chunksizehintp != NULL) + *chunksizehintp = ncp->chunk; + *ncid_ptr = ncp->nciop->fd; + return NC_NOERR; + +unwind_ioc: + (void) ncio_close(ncp->nciop, 0); + ncp->nciop = NULL; + /*FALLTHRU*/ +unwind_alloc: + free_NC(ncp); + return status; +} + +int +nc_open(const char * path, int ioflags, int *ncid_ptr) +{ + return nc__open(path, ioflags, NULL, ncid_ptr); +} + + +int +nc__enddef(int ncid, + size_t h_minfree, size_t v_align, + size_t v_minfree, size_t r_align) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + return(NC_ENOTINDEFINE); + + return(NC_endef(ncp, h_minfree, v_align, v_minfree, r_align)); +} + +int +nc_enddef(int ncid) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + return(NC_ENOTINDEFINE); + + /* return(NC_endef(ncp, 0, 4096, 0, 4096)); */ + return(NC_endef(ncp, 0, 1, 0, 1)); +} + + +int +nc_close(int ncid) +{ + int status = NC_NOERR; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + { + status = NC_endef(ncp, 0, 1, 0, 1); /* TODO: defaults */ + if(status != NC_NOERR ) + { + (void) nc_abort(ncid); + return status; + } + } + else if(!NC_readonly(ncp)) + { + status = NC_sync(ncp); + } + + (void) ncio_close(ncp->nciop, 0); + ncp->nciop = NULL; + + del_from_NCList(ncp); + + free_NC(ncp); + + return status; +} + + +EXTERNL int +nc_delete(const char * path) +{ + NC *ncp; + int status; + size_t chunk = 512; + + ncp = new_NC(&chunk); + if(ncp == NULL) + return NC_ENOMEM; + + status = ncio_open(path, NC_NOWRITE, + 0, 0, &ncp->chunk, + &ncp->nciop, 0); + if(status) + goto unwind_alloc; + + assert(ncp->flags == 0); + + status = nc_get_NC(ncp); + if(status != NC_NOERR) + { + /* Not a netcdf file, don't delete */ + /* ??? is this the right semantic? what if it was just too big? */ + (void) ncio_close(ncp->nciop, 0); + } + else + { + /* ncio_close does the unlink */ + status = ncio_close(ncp->nciop, 1); /* ncio_close does the unlink */ + } + + ncp->nciop = NULL; +unwind_alloc: + free_NC(ncp); + return status; +} + + +/* + * In data mode, same as ncclose. + * In define mode, restore previous definition. + * In create, remove the file. + */ +int +nc_abort(int ncid) +{ + int status; + NC *ncp; + int doUnlink = 0; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + doUnlink = NC_IsNew(ncp); + + if(ncp->old != NULL) + { + /* a plain redef, not a create */ + assert(!NC_IsNew(ncp)); + assert(fIsSet(ncp->flags, NC_INDEF)); + free_NC(ncp->old); + ncp->old = NULL; + fClr(ncp->flags, NC_INDEF); + } + else if(!NC_readonly(ncp)) + { + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + + (void) ncio_close(ncp->nciop, doUnlink); + ncp->nciop = NULL; + + del_from_NCList(ncp); + + free_NC(ncp); + + return NC_NOERR; +} + + +int +nc_redef(int ncid) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + + if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) + { + /* read in from disk */ + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + ncp->old = dup_NC(ncp); + if(ncp->old == NULL) + return NC_ENOMEM; + + fSet(ncp->flags, NC_INDEF); + + return NC_NOERR; +} + + +int +nc_inq(int ncid, + int *ndimsp, + int *nvarsp, + int *nattsp, + int *xtendimp) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(ndimsp != NULL) + *ndimsp = (int) ncp->dims.nelems; + if(nvarsp != NULL) + *nvarsp = (int) ncp->vars.nelems; + if(nattsp != NULL) + *nattsp = (int) ncp->attrs.nelems; + if(xtendimp != NULL) + *xtendimp = find_NC_Udim(&ncp->dims, NULL); + + return NC_NOERR; +} + +int +nc_inq_ndims(int ncid, int *ndimsp) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(ndimsp != NULL) + *ndimsp = (int) ncp->dims.nelems; + + return NC_NOERR; +} + +int +nc_inq_nvars(int ncid, int *nvarsp) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(nvarsp != NULL) + *nvarsp = (int) ncp->vars.nelems; + + return NC_NOERR; +} + +int +nc_inq_natts(int ncid, int *nattsp) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(nattsp != NULL) + *nattsp = (int) ncp->attrs.nelems; + + return NC_NOERR; +} + +int +nc_inq_unlimdim(int ncid, int *xtendimp) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(xtendimp != NULL) + *xtendimp = find_NC_Udim(&ncp->dims, NULL); + + return NC_NOERR; +} + + +int +nc_sync(int ncid) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + if(NC_readonly(ncp)) + { + return read_NC(ncp); + } + /* else, read/write */ + + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + + return ncp->nciop->sync(ncp->nciop); +} + + +int +nc_set_fill(int ncid, + int fillmode, int *old_mode_ptr) +{ + int status; + NC *ncp; + int oldmode; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + oldmode = fIsSet(ncp->flags, NC_NOFILL) ? NC_NOFILL : NC_FILL; + + if(fillmode == NC_NOFILL) + { + fSet(ncp->flags, NC_NOFILL); + } + else if(fillmode == NC_FILL) + { + if(fIsSet(ncp->flags, NC_NOFILL)) + { + /* + * We are changing back to fill mode + * so do a sync + */ + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + fClr(ncp->flags, NC_NOFILL); + } + else + { + return NC_EINVAL; /* Invalid fillmode */ + } + + if(old_mode_ptr != NULL) + *old_mode_ptr = oldmode; + + return NC_NOERR; +} diff --git a/Utilities/vtknetcdf/nc.h b/Utilities/vtknetcdf/nc.h new file mode 100644 index 0000000..511efcb --- /dev/null +++ b/Utilities/vtknetcdf/nc.h @@ -0,0 +1,388 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: nc.h,v 1.2 2005/07/19 23:37:24 andy Exp $ */ +#ifndef _NC_H_ +#define _NC_H_ + +/* + * netcdf library 'private' data structures, objects and interfaces + */ + +#include "ncconfig.h" +#include <stddef.h> /* size_t */ +#include <sys/types.h> /* off_t */ +#include "netcdf.h" +#include "ncio.h" /* ncio */ +#include "fbits.h" + +#ifdef _MSC_VER +# pragma warning ( disable : 4127 ) +# pragma warning ( disable : 4130 ) +#endif + + +#ifndef NC_ARRAY_GROWBY +#define NC_ARRAY_GROWBY 4 +#endif + +/* + * The extern size of an empty + * netcdf version 1 file. + * The initial value of ncp->xsz. + */ +#define MIN_NC_XSZ 32 + +typedef struct NC NC; /* forward reference */ + +/* + * The internal data types + */ +typedef enum { + NC_UNSPECIFIED = 0, +/* future NC_BITFIELD = 7, */ +/* NC_STRING = 8, */ + NC_DIMENSION = 10, + NC_VARIABLE = 11, + NC_ATTRIBUTE = 12 +} NCtype; + + +/* + * Counted string for names and such + */ +typedef struct { + /* all xdr'd */ + size_t nchars; + char *cp; +} NC_string; + +/* Begin defined in string.c */ +extern void +free_NC_string(NC_string *ncstrp); + +extern int +NC_check_name(const char *name); + +extern NC_string * +new_NC_string(size_t slen, const char *str); + +extern int +set_NC_string(NC_string *ncstrp, const char *str); + +/* End defined in string.c */ + +/* + * NC dimension stucture + */ +typedef struct { + /* all xdr'd */ + NC_string *name; + size_t size; +} NC_dim; + +typedef struct NC_dimarray { + size_t nalloc; /* number allocated >= nelems */ + /* below gets xdr'd */ + /* NCtype type = NC_DIMENSION */ + size_t nelems; /* length of the array */ + NC_dim **value; +} NC_dimarray; + +/* Begin defined in dim.c */ + +extern void +free_NC_dim(NC_dim *dimp); + +extern NC_dim * +new_x_NC_dim(NC_string *name); + +extern int +find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp); + +/* dimarray */ + +extern void +free_NC_dimarrayV0(NC_dimarray *ncap); + +extern void +free_NC_dimarrayV(NC_dimarray *ncap); + +extern int +dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref); + +extern NC_dim * +elem_NC_dimarray(const NC_dimarray *ncap, size_t elem); + +/* End defined in dim.c */ + +/* + * NC attribute + */ +typedef struct { + size_t xsz; /* amount of space at xvalue */ + /* below gets xdr'd */ + NC_string *name; + nc_type type; /* the discriminant */ + size_t nelems; /* length of the array */ + void *xvalue; /* the actual data, in external representation */ +} NC_attr; + +typedef struct NC_attrarray { + size_t nalloc; /* number allocated >= nelems */ + /* below gets xdr'd */ + /* NCtype type = NC_ATTRIBUTE */ + size_t nelems; /* length of the array */ + NC_attr **value; +} NC_attrarray; + +/* Begin defined in attr.c */ + +extern void +free_NC_attr(NC_attr *attrp); + +extern NC_attr * +new_x_NC_attr( + NC_string *strp, + nc_type type, + size_t nelems); + +extern NC_attr ** +NC_findattr(const NC_attrarray *ncap, const char *name); + +/* attrarray */ + +extern void +free_NC_attrarrayV0(NC_attrarray *ncap); + +extern void +free_NC_attrarrayV(NC_attrarray *ncap); + +extern int +dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref); + +extern NC_attr * +elem_NC_attrarray(const NC_attrarray *ncap, size_t elem); + +/* End defined in attr.c */ + + +/* + * NC variable: description and data + */ +typedef struct { + size_t xsz; /* xszof 1 element */ + size_t *shape; /* compiled info: dim->size of each dim */ + size_t *dsizes; /* compiled info: the right to left product of shape */ + /* below gets xdr'd */ + NC_string *name; + /* next two: formerly NC_iarray *assoc */ /* user definition */ + size_t ndims; /* assoc->count */ + int *dimids; /* assoc->value */ + NC_attrarray attrs; + nc_type type; /* the discriminant */ + size_t len; /* the total length originally allocated */ + off_t begin; +} NC_var; + +typedef struct NC_vararray { + size_t nalloc; /* number allocated >= nelems */ + /* below gets xdr'd */ + /* NCtype type = NC_VARIABLE */ + size_t nelems; /* length of the array */ + NC_var **value; +} NC_vararray; + +/* Begin defined in var.c */ + +extern void +free_NC_var(NC_var *varp); + +extern NC_var * +new_x_NC_var( + NC_string *strp, + size_t ndims); + +/* vararray */ + +extern void +free_NC_vararrayV0(NC_vararray *ncap); + +extern void +free_NC_vararrayV(NC_vararray *ncap); + +extern int +dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref); + +extern int +NC_var_shape(NC_var *varp, const NC_dimarray *dims); + +extern int +NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp); + +extern NC_var * +NC_lookupvar(NC *ncp, int varid); + +/* End defined in var.c */ + +#define IS_RECVAR(vp) \ + ((vp)->shape != NULL ? (*(vp)->shape == NC_UNLIMITED) : 0 ) + +struct NC { + /* links to make list of open netcdf's */ + struct NC *next; + struct NC *prev; + /* contains the previous NC during redef. */ + struct NC *old; + /* flags */ +#define NC_CREAT 2 /* in create phase, cleared by ncendef */ +#define NC_INDEF 8 /* in define mode, cleared by ncendef */ +#define NC_NSYNC 0x10 /* synchronise numrecs on change */ +#define NC_HSYNC 0x20 /* synchronise whole header on change */ +#define NC_NDIRTY 0x40 /* numrecs has changed */ +#define NC_HDIRTY 0x80 /* header info has changed */ +/* NC_NOFILL in netcdf.h, historical interface */ + int flags; + ncio *nciop; + size_t chunk; /* largest extent this layer will request from ncio->get() */ + size_t xsz; /* external size of this header, == var[0].begin */ + off_t begin_var; /* postion of the first (non-record) var */ + off_t begin_rec; /* postion of the first 'record' */ + size_t recsize; /* length of 'record' */ + /* below gets xdr'd */ + size_t numrecs; /* number of 'records' allocated */ + NC_dimarray dims; + NC_attrarray attrs; + NC_vararray vars; +}; + +#define NC_readonly(ncp) \ + (!fIsSet(ncp->nciop->ioflags, NC_WRITE)) + +#define NC_IsNew(ncp) \ + fIsSet((ncp)->flags, NC_CREAT) + +#define NC_indef(ncp) \ + (NC_IsNew(ncp) || fIsSet((ncp)->flags, NC_INDEF)) + +#define set_NC_ndirty(ncp) \ + fSet((ncp)->flags, NC_NDIRTY) + +#define NC_ndirty(ncp) \ + fIsSet((ncp)->flags, NC_NDIRTY) + +#define set_NC_hdirty(ncp) \ + fSet((ncp)->flags, NC_HDIRTY) + +#define NC_hdirty(ncp) \ + fIsSet((ncp)->flags, NC_HDIRTY) + +#define NC_dofill(ncp) \ + (!fIsSet((ncp)->flags, NC_NOFILL)) + +#define NC_doHsync(ncp) \ + fIsSet((ncp)->flags, NC_HSYNC) + +#define NC_doNsync(ncp) \ + fIsSet((ncp)->flags, NC_NSYNC) + +/* Begin defined in nc.c */ + +extern int +NC_check_id(int ncid, NC **ncpp); + +extern int +nc_cktype(nc_type datatype); + +extern size_t +ncx_howmany(nc_type type, size_t xbufsize); + +extern int +read_numrecs(NC *ncp); + +extern int +write_numrecs(NC *ncp); + +extern int +NC_sync(NC *ncp); + +/* End defined in nc.c */ +/* Begin defined in v1hpg.c */ + +extern size_t +ncx_len_NC(const NC *ncp, size_t sizeof_off_t); + +extern int +ncx_put_NC(const NC *ncp, void **xpp, off_t offset, size_t extent); + +extern int +nc_get_NC( NC *ncp); + +/* End defined in v1hpg.c */ +/* Begin defined in putget.c */ + +extern int +fill_NC_var(NC *ncp, const NC_var *varp, size_t recno); + +extern int +nc_inq_rec(int ncid, size_t *nrecvars, int *recvarids, size_t *recsizes); + +extern int +nc_get_rec(int ncid, size_t recnum, void **datap); + +extern int +nc_put_rec(int ncid, size_t recnum, void *const *datap); + +/* End defined in putget.c */ + +/* + * These functions are used to support + * interface version 2 backward compatiblity. + * N.B. these are tested in ../nc_test even though they are + * not public. So, be careful to change the declarations in + * ../nc_test/tests.h if you change these. + */ + +extern int +nc_put_att(int ncid, int varid, const char *name, nc_type datatype, + size_t len, const void *value); + +extern int +nc_get_att(int ncid, int varid, const char *name, void *value); + +extern int +nc_put_var1(int ncid, int varid, const size_t *index, const void *value); + +extern int +nc_get_var1(int ncid, int varid, const size_t *index, void *value); + +extern int +nc_put_vara(int ncid, int varid, + const size_t *start, const size_t *count, const void *value); + +extern int +nc_get_vara(int ncid, int varid, + const size_t *start, const size_t *count, void *value); + +extern int +nc_put_vars(int ncid, int varid, + const size_t *start, const size_t *count, const ptrdiff_t *stride, + const void * value); + +extern int +nc_get_vars(int ncid, int varid, + const size_t *start, const size_t *count, const ptrdiff_t *stride, + void * value); + +extern int +nc_put_varm(int ncid, int varid, + const size_t *start, const size_t *count, const ptrdiff_t *stride, + const ptrdiff_t * map, const void *value); + +extern int +nc_get_varm(int ncid, int varid, + const size_t *start, const size_t *count, const ptrdiff_t *stride, + const ptrdiff_t * map, void *value); + +#endif /* _NC_H_ */ diff --git a/Utilities/vtknetcdf/ncconfig.h.in b/Utilities/vtknetcdf/ncconfig.h.in new file mode 100644 index 0000000..957d274 --- /dev/null +++ b/Utilities/vtknetcdf/ncconfig.h.in @@ -0,0 +1,96 @@ +#include "vtk_netcdf_mangle.h" + +/* libsrc/ncconfig.in. Generated automatically from configure.in by autoheader. */ +/* $Id: ncconfig.h.in,v 1.4 2005/07/19 17:04:00 andy Exp $ */ +#ifndef _NCCONFIG_H_ +#define _NCCONFIG_H_ + +/* Define if this is a shared build */ +#cmakedefine BUILD_SHARED_LIBS +#if defined( BUILD_SHARED_LIBS ) && defined( _WIN32 ) +# define DLL_NETCDF +#endif + +#ifdef vtkNetCDF_EXPORTS +# define DLL_EXPORT +#endif + +/* Define if you're on an HP-UX system. */ +#cmakedefine _HPUX_SOURCE + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +#cmakedefine __CHAR_UNSIGNED__ +#endif + +/* Define if your struct stat has st_blksize. */ +#cmakedefine HAVE_ST_BLKSIZE @HAVE_ST_BLKSIZE@ + +/* Define to `long' if <sys/types.h> doesn't define. */ +#cmakedefine off_t @off_t@ + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +#cmakedefine size_t @size_t@ + +/* Define if you have the ANSI C header files. */ +#cmakedefine STDC_HEADERS @STDC_HEADERS@ + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +#cmakedefine WORDS_BIGENDIAN @WORDS_BIGENDIAN@ + +/* Define if you don't have the <stdlib.h>. */ +#cmakedefine NO_STDLIB_H @NO_STDLIB_H@ + +/* Define if you don't have the <sys/types.h>. */ +#cmakedefine NO_SYS_TYPES_H @NO_SYS_TYPES_H@ + +/* Define if you have the ftruncate function */ +#cmakedefine HAVE_FTRUNCATE @HAVE_FTRUNCATE@ + +/* Define if you have alloca, as a function or macro. */ +#cmakedefine HAVE_ALLOCA @HAVE_ALLOCA@ + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +#cmakedefine HAVE_ALLOCA_H @HAVE_ALLOCA_H@ + +/* Define if you have <unistd.h> and it should be used (not on Ultrix). */ +#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@ + +/* Define if you don't have the strerror function */ +#cmakedefine NO_STRERROR @NO_STRERROR@ + +/* The number of bytes in a size_t */ +#cmakedefine SIZEOF_SIZE_T @SIZEOF_SIZE_T@ + +/* The number of bytes in a off_t */ +#cmakedefine SIZEOF_OFF_T @SIZEOF_OFF_T@ + +/* Define to `int' if system doesn't define. */ +#cmakedefine ssize_t @ssize_t@ + +/* Define to `int' if system doesn't define. */ +#cmakedefine ptrdiff_t @ptrdiff_t@ + +/* Define to `unsigned char' if system doesn't define. */ +#cmakedefine uchar @uchar@ + +/* Define if the system does not use IEEE floating point representation */ +#cmakedefine NO_IEEE_FLOAT @NO_IEEE_FLOAT@ + +/* The number of bytes in a double. */ +#cmakedefine SIZEOF_DOUBLE @SIZEOF_DOUBLE@ + +/* The number of bytes in a float. */ +#cmakedefine SIZEOF_FLOAT @SIZEOF_FLOAT@ + +/* The number of bytes in a int. */ +#cmakedefine SIZEOF_INT @SIZEOF_INT@ + +/* The number of bytes in a long. */ +#cmakedefine SIZEOF_LONG @SIZEOF_LONG@ + +/* The number of bytes in a short. */ +#cmakedefine SIZEOF_SHORT @SIZEOF_SHORT@ + +#endif /* !_NCCONFIG_H_ */ diff --git a/Utilities/vtknetcdf/ncconfig_cougarcross.h b/Utilities/vtknetcdf/ncconfig_cougarcross.h new file mode 100644 index 0000000..ca1b8a3 --- /dev/null +++ b/Utilities/vtknetcdf/ncconfig_cougarcross.h @@ -0,0 +1,83 @@ +/* libsrc/ncconfig.h. Generated automatically by configure. */ +/* libsrc/ncconfig.in. Generated automatically from configure.in by autoheader. */ +/* $Id: ncconfig_cougarcross.h,v 1.1 2005/07/15 21:56:39 andy Exp $ */ +#ifndef _NCCONFIG_H_ +#define _NCCONFIG_H_ + +/* Define if you're on an HP-UX system. */ +/* #undef _HPUX_SOURCE */ + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* #undef __CHAR_UNSIGNED__ */ +#endif + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define to `long' if <sys/types.h> doesn't define. */ +/* #undef off_t */ + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if you don't have the <stdlib.h>. */ +/* #undef NO_STDLIB_H */ + +/* Define if you don't have the <sys/types.h>. */ +/* #undef NO_SYS_TYPES_H */ + +/* Define if you have the ftruncate function */ +/* #undef HAVE_FTRUNCATE */ +#define HAVE_FTRUNCATE 1 + +/* Define if you have alloca, as a function or macro. */ +/* #define HAVE_ALLOCA 1 */ + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +/* #define HAVE_ALLOCA_H 1 */ + +/* Define if you don't have the strerror function */ +/* #undef NO_STRERROR */ + +/* The number of bytes in a size_t */ +#define SIZEOF_SIZE_T 4 + +/* The number of bytes in a off_t */ +#define SIZEOF_OFF_T 4 + +/* Define to `int' if system doesn't define. */ +/* #undef ssize_t */ + +/* Define to `int' if system doesn't define. */ +/* #undef ptrdiff_t */ + +/* Define to `unsigned char' if system doesn't define. */ +/* #undef uchar */ + +/* Define if the system does not use IEEE floating point representation */ +/* #undef NO_IEEE_FLOAT */ + +/* The number of bytes in a double. */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in a float. */ +#define SIZEOF_FLOAT 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +#endif /* !_NCCONFIG_H_ */ diff --git a/Utilities/vtknetcdf/ncconfig_linuxcross.h b/Utilities/vtknetcdf/ncconfig_linuxcross.h new file mode 100644 index 0000000..712b694 --- /dev/null +++ b/Utilities/vtknetcdf/ncconfig_linuxcross.h @@ -0,0 +1,82 @@ +/* libsrc/ncconfig.h. Generated automatically by configure. */ +/* libsrc/ncconfig.in. Generated automatically from configure.in by autoheader. */ +/* $Id: ncconfig_linuxcross.h,v 1.1 2005/07/15 21:56:39 andy Exp $ */ +#ifndef _NCCONFIG_H_ +#define _NCCONFIG_H_ + +/* Define if you're on an HP-UX system. */ +/* #undef _HPUX_SOURCE */ + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* #undef __CHAR_UNSIGNED__ */ +#endif + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define to `long' if <sys/types.h> doesn't define. */ +/* #undef off_t */ + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if you don't have the <stdlib.h>. */ +/* #undef NO_STDLIB_H */ + +/* Define if you don't have the <sys/types.h>. */ +/* #undef NO_SYS_TYPES_H */ + +/* Define if you have the ftruncate function */ +#define HAVE_FTRUNCATE 1 + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +#define HAVE_ALLOCA_H 1 + +/* Define if you don't have the strerror function */ +/* #undef NO_STRERROR */ + +/* The number of bytes in a size_t */ +#define SIZEOF_SIZE_T 8 + +/* The number of bytes in a off_t */ +#define SIZEOF_OFF_T 8 + +/* Define to `int' if system doesn't define. */ +/* #undef ssize_t */ + +/* Define to `int' if system doesn't define. */ +/* #undef ptrdiff_t */ + +/* Define to `unsigned char' if system doesn't define. */ +/* #define uchar unsigned char */ + +/* Define if the system does not use IEEE floating point representation */ +/* #undef NO_IEEE_FLOAT */ + +/* The number of bytes in a double. */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in a float. */ +#define SIZEOF_FLOAT 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 8 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +#endif /* !_NCCONFIG_H_ */ diff --git a/Utilities/vtknetcdf/ncconfig_msoft.h b/Utilities/vtknetcdf/ncconfig_msoft.h new file mode 100644 index 0000000..fc68be3 --- /dev/null +++ b/Utilities/vtknetcdf/ncconfig_msoft.h @@ -0,0 +1,76 @@ +/* libsrc/msconfig.h. Generated manually for Wintel (MSC or whatever) */ +/* libsrc/ncconfig.in. Generated automatically from configure.in by autoheader. */ +/* $Id: ncconfig_msoft.h,v 1.1 2005/07/15 21:56:39 andy Exp $ */ +#ifndef _NCCONFIG_H_ +#define _NCCONFIG_H_ + +/* Define if you're on an HP-UX system. */ +/* #undef _INCLUDE_POSIX_SOURCE */ + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* #undef __CHAR_UNSIGNED__ */ +#endif + +/* Define if your struct stat has st_blksize. */ +/* #undef HAVE_ST_BLKSIZE */ + +/* Define to `long' if <sys/types.h> doesn't define. */ +/* #undef off_t */ + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if you don't have the <stdlib.h>. */ +/* #undef NO_STDLIB_H */ + +/* Define if you don't have the <sys/types.h>. */ +/* #undef NO_SYS_TYPES_H */ + +/* Define if you have the ftruncate function */ +/* #undef HAVE_FTRUNCATE */ + +/* Define if you don't have the strerror function */ +/* #undef NO_STRERROR */ + +/* The number of bytes in a size_t */ +#define SIZEOF_SIZE_T 4 + +/* The number of bytes in a off_t */ +#define SIZEOF_OFF_T 4 + +/* Define to `int' if system doesn't define. */ +#define ssize_t int + +/* Define to `int' if system doesn't define. */ +/* #undef ptrdiff_t */ + +/* Define to `unsigned char' if system doesn't define. */ +#define uchar unsigned char + +/* Define if the system does not use IEEE floating point representation */ +/* #undef NO_IEEE_FLOAT */ + +/* The number of bytes in a double. */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in a float. */ +#define SIZEOF_FLOAT 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +#endif /* !_NCCONFIG_H_ */ diff --git a/Utilities/vtknetcdf/ncconfig_tflopcross.h b/Utilities/vtknetcdf/ncconfig_tflopcross.h new file mode 100644 index 0000000..952e726 --- /dev/null +++ b/Utilities/vtknetcdf/ncconfig_tflopcross.h @@ -0,0 +1,83 @@ +/* libsrc/ncconfig.h. Generated automatically by configure. */ +/* libsrc/ncconfig.in. Generated automatically from configure.in by autoheader. */ +/* $Id: ncconfig_tflopcross.h,v 1.1 2005/07/15 21:56:39 andy Exp $ */ +#ifndef _NCCONFIG_H_ +#define _NCCONFIG_H_ + +/* Define if you're on an HP-UX system. */ +/* #undef _HPUX_SOURCE */ + +/* Define if type char is unsigned and you are not using gcc. */ +#ifndef __CHAR_UNSIGNED__ +/* #undef __CHAR_UNSIGNED__ */ +#endif + +/* Define if your struct stat has st_blksize. */ +#define HAVE_ST_BLKSIZE 1 + +/* Define to `long' if <sys/types.h> doesn't define. */ +/* #undef off_t */ + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if you don't have the <stdlib.h>. */ +/* #undef NO_STDLIB_H */ + +/* Define if you don't have the <sys/types.h>. */ +/* #undef NO_SYS_TYPES_H */ + +/* Define if you have the ftruncate function */ +/* #undef HAVE_FTRUNCATE */ +#define HAVE_FTRUNCATE 1 + +/* Define if you have alloca, as a function or macro. */ +/* #define HAVE_ALLOCA 1 */ + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +/* #define HAVE_ALLOCA_H 1 */ + +/* Define if you don't have the strerror function */ +/* #undef NO_STRERROR */ + +/* The number of bytes in a size_t */ +#define SIZEOF_SIZE_T 4 + +/* The number of bytes in a off_t */ +#define SIZEOF_OFF_T 4 + +/* Define to `int' if system doesn't define. */ +/* #undef ssize_t */ + +/* Define to `int' if system doesn't define. */ +/* #undef ptrdiff_t */ + +/* Define to `unsigned char' if system doesn't define. */ +/* #undef uchar */ + +/* Define if the system does not use IEEE floating point representation */ +/* #undef NO_IEEE_FLOAT */ + +/* The number of bytes in a double. */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in a float. */ +#define SIZEOF_FLOAT 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +#endif /* !_NCCONFIG_H_ */ diff --git a/Utilities/vtknetcdf/ncio.c b/Utilities/vtknetcdf/ncio.c new file mode 100644 index 0000000..74d767c --- /dev/null +++ b/Utilities/vtknetcdf/ncio.c @@ -0,0 +1,9 @@ +/* + * $Id: ncio.c,v 1.1 2005/07/15 21:56:39 andy Exp $ + */ + +#if defined(_CRAY) +# include "ffio.c" +#else +# include "posixio.c" +#endif diff --git a/Utilities/vtknetcdf/ncio.h b/Utilities/vtknetcdf/ncio.h new file mode 100644 index 0000000..db5af88 --- /dev/null +++ b/Utilities/vtknetcdf/ncio.h @@ -0,0 +1,144 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: ncio.h,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#ifndef _NCIO_H_ +#define _NCIO_H_ + +#include <stddef.h> /* size_t */ +#include <sys/types.h> /* off_t */ +#include "netcdf.h" + +typedef struct ncio ncio; /* forward reference */ + +/* + * A value which is an invalid off_t + */ +#define OFF_NONE ((off_t)(-1)) + +/* + * Flags used by the region layer, + * 'rflags' argument to ncio.rel() and ncio.get(). + */ +#define RGN_NOLOCK 0x1 /* Don't lock region. + * Used when contention control handled + * elsewhere. + */ +#define RGN_NOWAIT 0x2 /* return immediate if can't lock, else wait */ + +#define RGN_WRITE 0x4 /* we intend to modify, else read only */ + +#define RGN_MODIFIED 0x8 /* we did modify, else, discard */ + + +/* + * The next four typedefs define the signatures + * of function pointers in struct ncio below. + * They are not used outside of this file and ncio.h, + * They just some casts in the ncio.c more readable. + */ + /* + * Indicate that you are done with the region which begins + * at offset. Only reasonable flag value is RGN_MODIFIED. + */ +typedef int ncio_relfunc(ncio *const nciop, + off_t offset, int rflags); + + /* + * Request that the region (offset, extent) + * be made available through *vpp. + */ +typedef int ncio_getfunc(ncio *const nciop, + off_t offset, size_t extent, + int rflags, + void **const vpp); + + /* + * Like memmove(), safely move possibly overlapping data. + * Only reasonable flag value is RGN_NOLOCK. + */ +typedef int ncio_movefunc(ncio *const nciop, off_t to, off_t from, + size_t nbytes, int rflags); + + /* + * Write out any dirty buffers to disk and + * ensure that next read will get data from disk. + */ +typedef int ncio_syncfunc(ncio *const nciop); + + /* + * Don't call this. + * Internal function called at close to + * free up anything hanging off pvt; + */ +typedef void ncio_freefunc(void *const pvt); + +/* Get around cplusplus "const xxx in class ncio without constructor" error */ +#if defined(__cplusplus) +#define NCIO_CONST +#else +#define NCIO_CONST const +#endif + +/* + * netcdf i/o abstraction + */ +struct ncio { + /* + * A copy of the ioflags argument passed in to ncio_open() + * or ncio_create(). + */ + int ioflags; +#ifdef __PARAGON__ + int is_file_pfs; +#endif + + /* + * The file descriptor of the netcdf file. + * This gets handed to the user as the netcdf id. + */ + NCIO_CONST int fd; + + /* member functions do the work */ + + ncio_relfunc *NCIO_CONST rel; + + ncio_getfunc *NCIO_CONST get; + + ncio_movefunc *NCIO_CONST move; + + ncio_syncfunc *NCIO_CONST sync; + + ncio_freefunc *NCIO_CONST free; /* Implementation private */ + + /* + * A copy of the 'path' argument passed in to ncio_open() + * or ncio_create(). Used by ncabort() to remove (unlink) + * the file and by error messages. + */ + const char *path; + + /* implementation private stuff */ + void *NCIO_CONST pvt; +}; + +#undef NCIO_CONST + +extern int +ncio_create(const char *path, int ioflags, + size_t initialsz, + off_t igeto, size_t igetsz, size_t *sizehintp, + ncio **nciopp, void **const igetvpp); + +extern int +ncio_open(const char *path, + int ioflags, + off_t igeto, size_t igetsz, size_t *sizehintp, + ncio **nciopp, void **const igetvpp); + +extern int +ncio_close(ncio *nciop, int doUnlink); + +#endif /* _NCIO_H_ */ diff --git a/Utilities/vtknetcdf/ncx.c b/Utilities/vtknetcdf/ncx.c new file mode 100644 index 0000000..43d82ae --- /dev/null +++ b/Utilities/vtknetcdf/ncx.c @@ -0,0 +1,4213 @@ +/* Do not edit this file. It is produced from the corresponding .m4 source */ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * + * This file contains some routines derived from code + * which is copyrighted by Sun Microsystems, Inc. + * The "#ifdef vax" versions of + * ncx_put_float_float() + * ncx_get_float_float() + * ncx_put_double_double() + * ncx_get_double_double() + * ncx_putn_float_float() + * ncx_getn_float_float() + * ncx_putn_double_double() + * ncx_getn_double_double() + * are derived from xdr_float() and xdr_double() routines + * in the freely available, copyrighted Sun RPCSRC 3.9 + * distribution, xdr_float.c. + * Our "value added" is that these are always memory to memory, + * they handle IEEE subnormals properly, and their "n" versions + * operate speedily on arrays. + */ +/* $Id: ncx.c,v 1.2 2005/07/19 12:31:30 andy Exp $ */ + +/* + * An external data representation interface. + */ + +#include "ncx.h" +#include <stdio.h> +#include <string.h> +#include <limits.h> +/* alias poorly named limits.h macros */ +#define SHORT_MAX SHRT_MAX +#define SHORT_MIN SHRT_MIN +#define USHORT_MAX USHRT_MAX +#include <float.h> +#ifndef FLT_MAX /* This POSIX macro missing on some systems */ +# ifndef NO_IEEE_FLOAT +# define FLT_MAX 3.40282347e+38f +# else +# error "You will need to define FLT_MAX" +# endif +#endif +#include <assert.h> + +/* + * If the machine's float domain is "smaller" than the external one + * use the machine domain + */ +#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128 /* 128 is X_FLT_MAX_EXP */ +#undef X_FLOAT_MAX +# define X_FLOAT_MAX FLT_MAX +#undef X_FLOAT_MIN +# define X_FLOAT_MIN (-X_FLOAT_MAX) +#endif + +#if _SX /* NEC SUPER UX */ +#if _INT64 +#undef INT_MAX /* workaround cpp bug */ +#define INT_MAX X_INT_MAX +#undef INT_MIN /* workaround cpp bug */ +#define INT_MIN X_INT_MIN +#undef LONG_MAX /* workaround cpp bug */ +#define LONG_MAX X_INT_MAX +#undef LONG_MIN /* workaround cpp bug */ +#define LONG_MIN X_INT_MIN +#elif _LONG64 +#undef LONG_MAX /* workaround cpp bug */ +#define LONG_MAX 4294967295L +#undef LONG_MIN /* workaround cpp bug */ +#define LONG_MIN -4294967295L +#endif +#endif /* _SX */ + +static const char nada[X_ALIGN] = {0, 0, 0, 0}; + +#ifndef WORDS_BIGENDIAN +/* LITTLE_ENDIAN: DEC and intel */ +/* + * Routines to convert to BIGENDIAN. + * Optimize the swapn?b() and swap?b() routines aggressivly. + */ + +#define SWAP2(a) ( (((a) & 0xff) << 8) | \ + (((a) >> 8) & 0xff) ) + +#define SWAP4(a) ( ((a) << 24) | \ + (((a) << 8) & 0x00ff0000) | \ + (((a) >> 8) & 0x0000ff00) | \ + (((a) >> 24) & 0x000000ff) ) + +static void +swapn2b(void *dst, const void *src, size_t nn) +{ + char *op = dst; + const char *ip = src; + while(nn-- != 0) + { + *op++ = *(++ip); + *op++ = *(ip++ -1); + } +} + +# ifndef vax +static void +swap4b(void *dst, const void *src) +{ + char *op = dst; + const char *ip = src; + op[0] = ip[3]; + op[1] = ip[2]; + op[2] = ip[1]; + op[3] = ip[0]; +} +# endif /* !vax */ + +static void +swapn4b(void *dst, const void *src, size_t nn) +{ + char *op = dst; + const char *ip = src; + while(nn-- != 0) + { + op[0] = ip[3]; + op[1] = ip[2]; + op[2] = ip[1]; + op[3] = ip[0]; + op += 4; + ip += 4; + } +} + +# ifndef vax +static void +swap8b(void *dst, const void *src) +{ + char *op = dst; + const char *ip = src; + op[0] = ip[7]; + op[1] = ip[6]; + op[2] = ip[5]; + op[3] = ip[4]; + op[4] = ip[3]; + op[5] = ip[2]; + op[6] = ip[1]; + op[7] = ip[0]; +} +# endif /* !vax */ + +# ifndef vax +static void +swapn8b(void *dst, const void *src, size_t nn) +{ + char *op = dst; + const char *ip = src; + while(nn-- != 0) + { + op[0] = ip[7]; + op[1] = ip[6]; + op[2] = ip[5]; + op[3] = ip[4]; + op[4] = ip[3]; + op[5] = ip[2]; + op[6] = ip[1]; + op[7] = ip[0]; + op += 8; + ip += 8; + } +} +# endif /* !vax */ + +#endif /* LITTLE_ENDIAN */ + + +/* + * Primitive numeric conversion functions. + */ + +/* x_schar */ + + /* We don't implement and x_schar primitives. */ + + +/* x_short */ + +#if SHORT_MAX == X_SHORT_MAX +typedef short ix_short; +#define SIZEOF_IX_SHORT SIZEOF_SHORT +#define IX_SHORT_MAX SHORT_MAX +#elif INT_MAX >= X_SHORT_MAX +typedef int ix_short; +#define SIZEOF_IX_SHORT SIZEOF_INT +#define IX_SHORT_MAX INT_MAX +#elif LONG_MAX >= X_SHORT_MAX +typedef long ix_short; +#define SIZEOF_IX_SHORT SIZEOF_LONG +#define IX_SHORT_MAX LONG_MAX +#else +#error "ix_short implementation" +#endif + +static void +get_ix_short(const void *xp, ix_short *ip) +{ + const uchar *cp = (const uchar *) xp; + *ip = *cp++ << 8; +#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT + if(*ip & 0x8000) + { + /* extern is negative */ + *ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */ + } +#endif + *ip |= *cp; +} + +static void +put_ix_short(void *xp, const ix_short *ip) +{ + uchar *cp = (uchar *) xp; + *cp++ = (*ip) >> 8; + *cp = (*ip) & 0xff; +} + + +int +ncx_get_short_schar(const void *xp, schar *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = (schar)xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_short_uchar(const void *xp, uchar *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = (uchar)xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_short_short(const void *xp, short *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_SHORT && IX_SHORT_MAX == SHORT_MAX + get_ix_short(xp, (ix_short *)ip); + return ENOERR; +#else + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; +# if IX_SHORT_MAX > SHORT_MAX + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_get_short_int(const void *xp, int *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_INT && IX_SHORT_MAX == INT_MAX + get_ix_short(xp, (ix_short *)ip); + return ENOERR; +#else + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; +# if IX_SHORT_MAX > INT_MAX + if(xx > INT_MAX || xx < INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_get_short_long(const void *xp, long *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_LONG && IX_SHORT_MAX == LONG_MAX + get_ix_short(xp, (ix_short *)ip); + return ENOERR; +#else + /* assert(LONG_MAX >= X_SHORT_MAX); */ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +#endif +} + +int +ncx_get_short_float(const void *xp, float *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; +#if 0 /* TODO: determine when necessary */ + if(xx > FLT_MAX || xx < (-FLT_MAX)) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_get_short_double(const void *xp, double *ip) +{ + /* assert(DBL_MAX >= X_SHORT_MAX); */ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncx_put_short_schar(void *xp, const schar *ip) +{ + uchar *cp = (uchar *) xp; + if(*ip & 0x80) + *cp++ = 0xff; + else + *cp++ = 0; + *cp = (uchar)*ip; + return ENOERR; +} + +int +ncx_put_short_uchar(void *xp, const uchar *ip) +{ + uchar *cp = (uchar *) xp; + *cp++ = 0; + *cp = *ip; + return ENOERR; +} + +int +ncx_put_short_short(void *xp, const short *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_SHORT && X_SHORT_MAX == SHORT_MAX + put_ix_short(xp, (const ix_short *)ip); + return ENOERR; +#else + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); +# if X_SHORT_MAX < SHORT_MAX + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_put_short_int(void *xp, const int *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_INT && X_SHORT_MAX == INT_MAX + put_ix_short(xp, (const ix_short *)ip); + return ENOERR; +#else + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); +# if X_SHORT_MAX < INT_MAX + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_put_short_long(void *xp, const long *ip) +{ +#if SIZEOF_IX_SHORT == SIZEOF_LONG && X_SHORT_MAX == LONG_MAX + put_ix_short(xp, (const ix_short *)ip); + return ENOERR; +#else + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); +# if X_SHORT_MAX < LONG_MAX + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_put_short_float(void *xp, const float *ip) +{ + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_put_short_double(void *xp, const double *ip) +{ + ix_short xx = (ix_short)*ip; + put_ix_short(xp, &xx); + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +/* x_int */ + +#if SHORT_MAX == X_INT_MAX +typedef short ix_int; +#define SIZEOF_IX_INT SIZEOF_SHORT +#define IX_INT_MAX SHORT_MAX +#elif INT_MAX >= X_INT_MAX +typedef int ix_int; +#define SIZEOF_IX_INT SIZEOF_INT +#define IX_INT_MAX INT_MAX +#elif LONG_MAX >= X_INT_MAX +typedef long ix_int; +#define SIZEOF_IX_INT SIZEOF_LONG +#define IX_INT_MAX LONG_MAX +#else +#error "ix_int implementation" +#endif + + +static void +get_ix_int(const void *xp, ix_int *ip) +{ + const uchar *cp = (const uchar *) xp; + + *ip = *cp++ << 24; +#if SIZEOF_IX_INT > X_SIZEOF_INT + if(*ip & 0x80000000) + { + /* extern is negative */ + *ip |= (~(0xffffffff)); /* N.B. Assumes "twos complement" */ + } +#endif + *ip |= (*cp++ << 16); + *ip |= (*cp++ << 8); + *ip |= *cp; +} + +static void +put_ix_int(void *xp, const ix_int *ip) +{ + uchar *cp = (uchar *) xp; + + *cp++ = (*ip) >> 24; + *cp++ = ((*ip) & 0x00ff0000) >> 16; + *cp++ = ((*ip) & 0x0000ff00) >> 8; + *cp = ((*ip) & 0x000000ff); +} + + +int +ncx_get_int_schar(const void *xp, schar *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_int_uchar(const void *xp, uchar *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_int_short(const void *xp, short *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX + get_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; +# if IX_INT_MAX > SHORT_MAX + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_get_int_int(const void *xp, int *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX + get_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; +# if IX_INT_MAX > INT_MAX + if(xx > INT_MAX || xx < INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_get_int_long(const void *xp, long *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX + get_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; +# if IX_INT_MAX > LONG_MAX /* unlikely */ + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_get_int_float(const void *xp, float *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = (float)xx; +#if 0 /* TODO: determine when necessary */ + if(xx > FLT_MAX || xx < (-FLT_MAX)) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_get_int_double(const void *xp, double *ip) +{ + /* assert((DBL_MAX >= X_INT_MAX); */ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncx_put_int_schar(void *xp, const schar *ip) +{ + uchar *cp = (uchar *) xp; + if(*ip & 0x80) + { + *cp++ = 0xff; + *cp++ = 0xff; + *cp++ = 0xff; + } + else + { + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; + } + *cp = (uchar)*ip; + return ENOERR; +} + +int +ncx_put_int_uchar(void *xp, const uchar *ip) +{ + uchar *cp = (uchar *) xp; + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; + *cp = *ip; + return ENOERR; +} + +int +ncx_put_int_short(void *xp, const short *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX + put_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); +# if IX_INT_MAX < SHORT_MAX + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_put_int_int(void *xp, const int *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX + put_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); +# if IX_INT_MAX < INT_MAX + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_put_int_long(void *xp, const long *ip) +{ +#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX + put_ix_int(xp, (ix_int *)ip); + return ENOERR; +#else + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); +# if IX_INT_MAX < LONG_MAX + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; +# endif + return ENOERR; +#endif +} + +int +ncx_put_int_float(void *xp, const float *ip) +{ + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); + if(*ip > (double)X_INT_MAX || *ip < (double)X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_put_int_double(void *xp, const double *ip) +{ + ix_int xx = (ix_int)(*ip); + put_ix_int(xp, &xx); + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} + + +/* x_float */ + +#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) + +static void +get_ix_float(const void *xp, float *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(ip, xp, sizeof(float)); +#else + swap4b(ip, xp); +#endif +} + +static void +put_ix_float(void *xp, const float *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(xp, ip, X_SIZEOF_FLOAT); +#else + swap4b(xp, ip); +#endif +} + +#elif vax + +/* What IEEE single precision floating point looks like on a Vax */ +struct ieee_single { + unsigned int exp_hi : 7; + unsigned int sign : 1; + unsigned int mant_hi : 7; + unsigned int exp_lo : 1; + unsigned int mant_lo_hi : 8; + unsigned int mant_lo_lo : 8; +}; + +/* Vax single precision floating point */ +struct vax_single { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; +}; + +#define VAX_SNG_BIAS 0x81 +#define IEEE_SNG_BIAS 0x7f + +static struct sgl_limits { + struct vax_single s; + struct ieee_single ieee; +} max = { + { 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ + { 0x7f, 0x0, 0x0, 0x1, 0x0, 0x0 } /* Max IEEE */ +}; +static struct sgl_limits min = { + { 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } /* Min IEEE */ +}; + +static void +get_ix_float(const void *xp, float *ip) +{ + struct vax_single *const vsp = (struct vax_single *) ip; + const struct ieee_single *const isp = + (const struct ieee_single *) xp; + unsigned exp = isp->exp_hi << 1 | isp->exp_lo; + + switch(exp) { + case 0 : + /* ieee subnormal */ + if(isp->mant_hi == min.ieee.mant_hi + && isp->mant_lo_hi == min.ieee.mant_lo_hi + && isp->mant_lo_lo == min.ieee.mant_lo_lo) + { + *vsp = min.s; + } + else + { + unsigned mantissa = (isp->mant_hi << 16) + | isp->mant_lo_hi << 8 + | isp->mant_lo_lo; + unsigned tmp = mantissa >> 20; + if(tmp >= 4) { + vsp->exp = 2; + } else if (tmp >= 2) { + vsp->exp = 1; + } else { + *vsp = min.s; + break; + } /* else */ + tmp = mantissa - (1 << (20 + vsp->exp )); + tmp <<= 3 - vsp->exp; + vsp->mantissa2 = tmp; + vsp->mantissa1 = (tmp >> 16); + } + break; + case 0xfe : + case 0xff : + *vsp = max.s; + break; + default : + vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo; + vsp->mantissa1 = isp->mant_hi; + } + + vsp->sign = isp->sign; + +} + + +static void +put_ix_float(void *xp, const float *ip) +{ + const struct vax_single *const vsp = + (const struct vax_single *)ip; + struct ieee_single *const isp = (struct ieee_single *) xp; + + switch(vsp->exp){ + case 0 : + /* all vax float with zero exponent map to zero */ + *isp = min.ieee; + break; + case 2 : + case 1 : + { + /* These will map to subnormals */ + unsigned mantissa = (vsp->mantissa1 << 16) + | vsp->mantissa2; + mantissa >>= 3 - vsp->exp; + mantissa += (1 << (20 + vsp->exp)); + isp->mant_lo_lo = mantissa; + isp->mant_lo_hi = mantissa >> 8; + isp->mant_hi = mantissa >> 16; + isp->exp_lo = 0; + isp->exp_hi = 0; + } + break; + case 0xff : /* max.s.exp */ + if( vsp->mantissa2 == max.s.mantissa2 + && vsp->mantissa1 == max.s.mantissa1) + { + /* map largest vax float to ieee infinity */ + *isp = max.ieee; + break; + } /* else, fall thru */ + default : + { + unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + isp->exp_hi = exp >> 1; + isp->exp_lo = exp; + isp->mant_lo_lo = vsp->mantissa2; + isp->mant_lo_hi = vsp->mantissa2 >> 8; + isp->mant_hi = vsp->mantissa1; + } + } + + isp->sign = vsp->sign; + +} + + /* vax */ +#elif defined(_CRAY) + +/* + * Return the number of bytes until the next "word" boundary + * N.B. This is based on the very wierd YMP address structure, + * which puts the address within a word in the leftmost 3 bits + * of the address. + */ +static size_t +word_align(const void *vp) +{ + const size_t rem = ((size_t)vp >> (64 - 3)) & 0x7; + return (rem != 0); +} + +struct ieee_single_hi { + unsigned int sign : 1; + unsigned int exp : 8; + unsigned int mant :23; + unsigned int pad :32; +}; +typedef struct ieee_single_hi ieee_single_hi; + +struct ieee_single_lo { + unsigned int pad :32; + unsigned int sign : 1; + unsigned int exp : 8; + unsigned int mant :23; +}; +typedef struct ieee_single_lo ieee_single_lo; + +static const int ieee_single_bias = 0x7f; + +struct ieee_double { + unsigned int sign : 1; + unsigned int exp :11; + unsigned int mant :52; +}; +typedef struct ieee_double ieee_double; + +static const int ieee_double_bias = 0x3ff; + +#if defined(NO_IEEE_FLOAT) + +struct cray_single { + unsigned int sign : 1; + unsigned int exp :15; + unsigned int mant :48; +}; +typedef struct cray_single cray_single; + +static const int cs_ieis_bias = 0x4000 - 0x7f; + +static const int cs_id_bias = 0x4000 - 0x3ff; + + +static void +get_ix_float(const void *xp, float *ip) +{ + + if(word_align(xp) == 0) + { + const ieee_single_hi *isp = (const ieee_single_hi *) xp; + cray_single *csp = (cray_single *) ip; + + if(isp->exp == 0) + { + /* ieee subnormal */ + *ip = (double)isp->mant; + if(isp->mant != 0) + { + csp->exp -= (ieee_single_bias + 22); + } + } + else + { + csp->exp = isp->exp + cs_ieis_bias + 1; + csp->mant = isp->mant << (48 - 1 - 23); + csp->mant |= (1 << (48 - 1)); + } + csp->sign = isp->sign; + + + } + else + { + const ieee_single_lo *isp = (const ieee_single_lo *) xp; + cray_single *csp = (cray_single *) ip; + + if(isp->exp == 0) + { + /* ieee subnormal */ + *ip = (double)isp->mant; + if(isp->mant != 0) + { + csp->exp -= (ieee_single_bias + 22); + } + } + else + { + csp->exp = isp->exp + cs_ieis_bias + 1; + csp->mant = isp->mant << (48 - 1 - 23); + csp->mant |= (1 << (48 - 1)); + } + csp->sign = isp->sign; + + + } +} + +static void +put_ix_float(void *xp, const float *ip) +{ + if(word_align(xp) == 0) + { + ieee_single_hi *isp = (ieee_single_hi*)xp; + const cray_single *csp = (const cray_single *) ip; + int ieee_exp = csp->exp - cs_ieis_bias -1; + + isp->sign = csp->sign; + + if(ieee_exp >= 0xff) + { + /* NC_ERANGE => ieee Inf */ + isp->exp = 0xff; + isp->mant = 0x0; + } + else if(ieee_exp > 0) + { + /* normal ieee representation */ + isp->exp = ieee_exp; + /* assumes cray rep is in normal form */ + assert(csp->mant & 0x800000000000); + isp->mant = (((csp->mant << 1) & + 0xffffffffffff) >> (48 - 23)); + } + else if(ieee_exp > -23) + { + /* ieee subnormal, right */ + const int rshift = (48 - 23 - ieee_exp); + + isp->mant = csp->mant >> rshift; + +#if 0 + if(csp->mant & (1 << (rshift -1))) + { + /* round up */ + isp->mant++; + } +#endif + + isp->exp = 0; + } + else + { + /* smaller than ieee can represent */ + isp->exp = 0; + isp->mant = 0; + } + + } + else + { + ieee_single_lo *isp = (ieee_single_lo*)xp; + const cray_single *csp = (const cray_single *) ip; + int ieee_exp = csp->exp - cs_ieis_bias -1; + + isp->sign = csp->sign; + + if(ieee_exp >= 0xff) + { + /* NC_ERANGE => ieee Inf */ + isp->exp = 0xff; + isp->mant = 0x0; + } + else if(ieee_exp > 0) + { + /* normal ieee representation */ + isp->exp = ieee_exp; + /* assumes cray rep is in normal form */ + assert(csp->mant & 0x800000000000); + isp->mant = (((csp->mant << 1) & + 0xffffffffffff) >> (48 - 23)); + } + else if(ieee_exp > -23) + { + /* ieee subnormal, right */ + const int rshift = (48 - 23 - ieee_exp); + + isp->mant = csp->mant >> rshift; + +#if 0 + if(csp->mant & (1 << (rshift -1))) + { + /* round up */ + isp->mant++; + } +#endif + + isp->exp = 0; + } + else + { + /* smaller than ieee can represent */ + isp->exp = 0; + isp->mant = 0; + } + + } +} + +#else + /* IEEE Cray with only doubles */ +static void +get_ix_float(const void *xp, float *ip) +{ + + ieee_double *idp = (ieee_double *) ip; + + if(word_align(xp) == 0) + { + const ieee_single_hi *isp = (const ieee_single_hi *) xp; + if(isp->exp == 0 && isp->mant == 0) + { + idp->exp = 0; + idp->mant = 0; + } + else + { + idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias); + idp->mant = isp->mant << (52 - 23); + } + idp->sign = isp->sign; + } + else + { + const ieee_single_lo *isp = (const ieee_single_lo *) xp; + if(isp->exp == 0 && isp->mant == 0) + { + idp->exp = 0; + idp->mant = 0; + } + else + { + idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias); + idp->mant = isp->mant << (52 - 23); + } + idp->sign = isp->sign; + } +} + +static void +put_ix_float(void *xp, const float *ip) +{ + const ieee_double *idp = (const ieee_double *) ip; + if(word_align(xp) == 0) + { + ieee_single_hi *isp = (ieee_single_hi*)xp; + if(idp->exp > (ieee_double_bias - ieee_single_bias)) + isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias); + else + isp->exp = 0; + isp->mant = idp->mant >> (52 - 23); + isp->sign = idp->sign; + } + else + { + ieee_single_lo *isp = (ieee_single_lo*)xp; + if(idp->exp > (ieee_double_bias - ieee_single_bias)) + isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias); + else + isp->exp = 0; + isp->mant = idp->mant >> (52 - 23); + isp->sign = idp->sign; + } +} +#endif + +#elif _SX && _FLOAT2 +static void +get_ix_float(const void *xp, float *ip) +{ + const int ncnv = ie3_fl2(xp, ip, 4, 8, 1); +} + +static void +put_ix_float(void *xp, const float *ip) +{ + const int ncnv = fl2_ie3(ip, xp, 8, 4, 1); +} +#else +#error "ix_float implementation" +#endif + + +int +ncx_get_float_schar(const void *xp, schar *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (schar) xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_uchar(const void *xp, uchar *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (uchar) xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_short(const void *xp, short *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (short) xx; + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_int(const void *xp, int *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (int) xx; + if(xx > (double)INT_MAX || xx < (double)INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_long(const void *xp, long *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (long) xx; + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_float(const void *xp, float *ip) +{ + /* TODO */ + get_ix_float(xp, ip); + return ENOERR; +} + +int +ncx_get_float_double(const void *xp, double *ip) +{ + /* TODO */ + float xx; + get_ix_float(xp, &xx); + *ip = xx; + return ENOERR; +} + + +int +ncx_put_float_schar(void *xp, const schar *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); + return ENOERR; +} + +int +ncx_put_float_uchar(void *xp, const uchar *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); + return ENOERR; +} + +int +ncx_put_float_short(void *xp, const short *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); +#if 0 /* TODO: figure this out */ + if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_float_int(void *xp, const int *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); +#if 1 /* TODO: figure this out */ + if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_float_long(void *xp, const long *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); +#if 1 /* TODO: figure this out */ + if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_float_float(void *xp, const float *ip) +{ + put_ix_float(xp, ip); +#ifdef NO_IEEE_FLOAT + if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_float_double(void *xp, const double *ip) +{ + float xx = (float) *ip; + put_ix_float(xp, &xx); + if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + return NC_ERANGE; + return ENOERR; +} + +/* x_double */ + +#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) + +static void +get_ix_double(const void *xp, double *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(ip, xp, sizeof(double)); +#else + swap8b(ip, xp); +#endif +} + +static void +put_ix_double(void *xp, const double *ip) +{ +#ifdef WORDS_BIGENDIAN + (void) memcpy(xp, ip, X_SIZEOF_DOUBLE); +#else + swap8b(xp, ip); +#endif +} + +#elif vax + +/* What IEEE double precision floating point looks like on a Vax */ +struct ieee_double { + unsigned int exp_hi : 7; + unsigned int sign : 1; + unsigned int mant_6 : 4; + unsigned int exp_lo : 4; + unsigned int mant_5 : 8; + unsigned int mant_4 : 8; + + unsigned int mant_lo : 32; +}; + +/* Vax double precision floating point */ +struct vax_double { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; + unsigned int mantissa3 : 16; + unsigned int mantissa4 : 16; +}; + +#define VAX_DBL_BIAS 0x81 +#define IEEE_DBL_BIAS 0x3ff +#define MASK(nbits) ((1 << nbits) - 1) + +static const struct dbl_limits { + struct vax_double d; + struct ieee_double ieee; +} dbl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ + { 0x7f, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0}}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, /* Min IEEE */ +}; + + +static void +get_ix_double(const void *xp, double *ip) +{ + struct vax_double *const vdp = + (struct vax_double *)ip; + const struct ieee_double *const idp = + (const struct ieee_double *) xp; + { + const struct dbl_limits *lim; + int ii; + for (ii = 0, lim = dbl_limits; + ii < sizeof(dbl_limits)/sizeof(struct dbl_limits); + ii++, lim++) + { + if ((idp->mant_lo == lim->ieee.mant_lo) + && (idp->mant_4 == lim->ieee.mant_4) + && (idp->mant_5 == lim->ieee.mant_5) + && (idp->mant_6 == lim->ieee.mant_6) + && (idp->exp_lo == lim->ieee.exp_lo) + && (idp->exp_hi == lim->ieee.exp_hi) + ) + { + *vdp = lim->d; + goto doneit; + } + } + } + { + unsigned exp = idp->exp_hi << 4 | idp->exp_lo; + vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + } + { + unsigned mant_hi = ((idp->mant_6 << 16) + | (idp->mant_5 << 8) + | idp->mant_4); + unsigned mant_lo = SWAP4(idp->mant_lo); + vdp->mantissa1 = (mant_hi >> 13); + vdp->mantissa2 = ((mant_hi & MASK(13)) << 3) + | (mant_lo >> 29); + vdp->mantissa3 = (mant_lo >> 13); + vdp->mantissa4 = (mant_lo << 3); + } + doneit: + vdp->sign = idp->sign; + +} + + +static void +put_ix_double(void *xp, const double *ip) +{ + const struct vax_double *const vdp = + (const struct vax_double *)ip; + struct ieee_double *const idp = + (struct ieee_double *) xp; + + if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) && + (vdp->mantissa3 == dbl_limits[0].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[0].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[0].d.mantissa1) && + (vdp->exp == dbl_limits[0].d.exp)) + { + *idp = dbl_limits[0].ieee; + goto shipit; + } + if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) && + (vdp->mantissa3 == dbl_limits[1].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[1].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[1].d.mantissa1) && + (vdp->exp == dbl_limits[1].d.exp)) + { + *idp = dbl_limits[1].ieee; + goto shipit; + } + + { + unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + + unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) | + (vdp->mantissa3 << 13) | + ((vdp->mantissa4 >> 3) & MASK(13)); + + unsigned mant_hi = (vdp->mantissa1 << 13) + | (vdp->mantissa2 >> 3); + + if((vdp->mantissa4 & 7) > 4) + { + /* round up */ + mant_lo++; + if(mant_lo == 0) + { + mant_hi++; + if(mant_hi > 0xffffff) + { + mant_hi = 0; + exp++; + } + } + } + + idp->mant_lo = SWAP4(mant_lo); + idp->mant_6 = mant_hi >> 16; + idp->mant_5 = (mant_hi & 0xff00) >> 8; + idp->mant_4 = mant_hi; + idp->exp_hi = exp >> 4; + idp->exp_lo = exp; + } + + shipit: + idp->sign = vdp->sign; + +} + + /* vax */ +#elif defined(_CRAY) + +static void +get_ix_double(const void *xp, double *ip) +{ + const ieee_double *idp = (const ieee_double *) xp; + cray_single *csp = (cray_single *) ip; + + if(idp->exp == 0) + { + /* ieee subnormal */ + *ip = (double)idp->mant; + if(idp->mant != 0) + { + csp->exp -= (ieee_double_bias + 51); + } + } + else + { + csp->exp = idp->exp + cs_id_bias + 1; + csp->mant = idp->mant >> (52 - 48 + 1); + csp->mant |= (1 << (48 - 1)); + } + csp->sign = idp->sign; +} + +static void +put_ix_double(void *xp, const double *ip) +{ + ieee_double *idp = (ieee_double *) xp; + const cray_single *csp = (const cray_single *) ip; + + int ieee_exp = csp->exp - cs_id_bias -1; + + idp->sign = csp->sign; + + if(ieee_exp >= 0x7ff) + { + /* NC_ERANGE => ieee Inf */ + idp->exp = 0x7ff; + idp->mant = 0x0; + } + else if(ieee_exp > 0) + { + /* normal ieee representation */ + idp->exp = ieee_exp; + /* assumes cray rep is in normal form */ + assert(csp->mant & 0x800000000000); + idp->mant = (((csp->mant << 1) & + 0xffffffffffff) << (52 - 48)); + } + else if(ieee_exp >= (-(52 -48))) + { + /* ieee subnormal, left */ + const int lshift = (52 - 48) + ieee_exp; + idp->mant = csp->mant << lshift; + idp->exp = 0; + } + else if(ieee_exp >= -52) + { + /* ieee subnormal, right */ + const int rshift = (- (52 - 48) - ieee_exp); + + idp->mant = csp->mant >> rshift; + +#if 0 + if(csp->mant & (1 << (rshift -1))) + { + /* round up */ + idp->mant++; + } +#endif + + idp->exp = 0; + } + else + { + /* smaller than ieee can represent */ + idp->exp = 0; + idp->mant = 0; + } +} +#elif _SX && _FLOAT2 +static void +get_ix_double(const void *xp, double *ip) +{ + const int ncnv = ie3_fl2(xp, ip, 8, 8, 1); +} + +static void +put_ix_double(void *xp, const double *ip) +{ + const int ncnv = fl2_ie3(ip, xp, 8, 8, 1); +} +#else +#error "ix_double implementation" +#endif + +int +ncx_get_double_schar(const void *xp, schar *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (schar) xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_uchar(const void *xp, uchar *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (uchar) xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_short(const void *xp, short *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (short) xx; + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_int(const void *xp, int *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (int) xx; + if(xx > INT_MAX || xx < INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_long(const void *xp, long *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (long) xx; + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_float(const void *xp, float *ip) +{ + double xx; + get_ix_double(xp, &xx); + if(xx > FLT_MAX || xx < (-FLT_MAX)) + { + *ip = FLT_MAX; + return NC_ERANGE; + } + if(xx < (-FLT_MAX)) + { + *ip = (-FLT_MAX); + return NC_ERANGE; + } + *ip = (float) xx; + return ENOERR; +} + +int +ncx_get_double_double(const void *xp, double *ip) +{ + /* TODO */ + get_ix_double(xp, ip); + return ENOERR; +} + + +int +ncx_put_double_schar(void *xp, const schar *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncx_put_double_uchar(void *xp, const uchar *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncx_put_double_short(void *xp, const short *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 0 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_double_int(void *xp, const int *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 0 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_double_long(void *xp, const long *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 1 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_double_float(void *xp, const float *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); +#if 1 /* TODO: figure this out */ + if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + +int +ncx_put_double_double(void *xp, const double *ip) +{ + put_ix_double(xp, ip); +#ifdef NO_IEEE_FLOAT + if(*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN) + return NC_ERANGE; +#endif + return ENOERR; +} + + +/* x_size_t */ +int +ncx_put_size_t(void **xpp, const size_t *ulp) +{ + /* similar to put_ix_int() */ + uchar *cp = (uchar *) *xpp; + /* sizes limited to 2^31 -1 in netcdf */ + assert(*ulp <= X_SIZE_MAX && (long) (*ulp) >= 0); + + *cp++ = (uchar)((*ulp) >> 24); + *cp++ = (uchar)(((*ulp) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*ulp) & 0x0000ff00) >> 8); + *cp = (uchar)((*ulp) & 0x000000ff); + + *xpp = (void *)((char *)(*xpp) + X_SIZEOF_SIZE_T); + return ENOERR; +} + +int +ncx_get_size_t(const void **xpp, size_t *ulp) +{ + /* similar to get_ix_int */ + const uchar *cp = (const uchar *) *xpp; + assert((*cp & 0x80) == 0); /* sizes limited to 2^31 -1 in netcdf */ + + *ulp = *cp++ << 24; + *ulp |= (*cp++ << 16); + *ulp |= (*cp++ << 8); + *ulp |= *cp; + + *xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_SIZE_T); + return ENOERR; +} + +/* x_off_t */ +int +ncx_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t) +{ + /* similar to put_ix_int() */ + uchar *cp = (uchar *) *xpp; + /* No negative offsets stored in netcdf */ + if (*lp < 0) { + /* Assume this is an overflow of a 32-bit int... */ + return ERANGE; + } + + assert(sizeof_off_t == 4 || sizeof_off_t == 8); + + if (sizeof_off_t == 4) { + *cp++ = (uchar) ((*lp) >> 24); + *cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*lp) & 0x0000ff00) >> 8); + *cp = (uchar)( (*lp) & 0x000000ff); + } else { +#if SIZEOF_OFF_T == 4 +/* Write a 64-bit offset on a system with only a 32-bit offset */ + *cp++ = (uchar)0; + *cp++ = (uchar)0; + *cp++ = (uchar)0; + *cp++ = (uchar)0; + + *cp++ = (uchar)(((*lp) & 0xff000000) >> 24); + *cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*lp) & 0x0000ff00) >> 8); + *cp = (uchar)( (*lp) & 0x000000ff); +#else + *cp++ = (uchar) ((*lp) >> 56); + *cp++ = (uchar)(((*lp) & 0x00ff000000000000ULL) >> 48); + *cp++ = (uchar)(((*lp) & 0x0000ff0000000000ULL) >> 40); + *cp++ = (uchar)(((*lp) & 0x000000ff00000000ULL) >> 32); + *cp++ = (uchar)(((*lp) & 0x00000000ff000000ULL) >> 24); + *cp++ = (uchar)(((*lp) & 0x0000000000ff0000ULL) >> 16); + *cp++ = (uchar)(((*lp) & 0x000000000000ff00ULL) >> 8); + *cp = (uchar)( (*lp) & 0x00000000000000ffULL); +#endif + } + *xpp = (void *)((char *)(*xpp) + sizeof_off_t); + return ENOERR; +} + +int +ncx_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t) +{ + /* similar to get_ix_int() */ + const uchar *cp = (const uchar *) *xpp; + + assert((*cp & 0x80) == 0); /* No negative offsets stored in netcdf */ + assert(sizeof_off_t == 4 || sizeof_off_t == 8); + + if (sizeof_off_t == 4) { + *lp = *cp++ << 24; + *lp |= (*cp++ << 16); + *lp |= (*cp++ << 8); + *lp |= *cp; + } else { +#if SIZEOF_OFF_T == 4 +/* Read a 64-bit offset on a system with only a 32-bit offset */ +/* If the offset overflows, set an error code and return */ + *lp = ((off_t)(*cp++) << 24); + *lp |= ((off_t)(*cp++) << 16); + *lp |= ((off_t)(*cp++) << 8); + *lp |= ((off_t)(*cp++)); +/* + * lp now contains the upper 32-bits of the 64-bit offset. if lp is + * not zero, then the dataset is larger than can be represented + * on this system. Set an error code and return. + */ + if (*lp != 0) { + return ERANGE; + } + + *lp = ((off_t)(*cp++) << 24); + *lp |= ((off_t)(*cp++) << 16); + *lp |= ((off_t)(*cp++) << 8); + *lp |= (off_t)*cp; + + if (*lp < 0) { + /* + * If this fails, then the offset is >2^31, but less + * than 2^32 which is not allowed, but is not caught + * by the previous check + */ + return ERANGE; + } +#else + *lp = ((off_t)(*cp++) << 56); + *lp |= ((off_t)(*cp++) << 48); + *lp |= ((off_t)(*cp++) << 40); + *lp |= ((off_t)(*cp++) << 32); + *lp |= ((off_t)(*cp++) << 24); + *lp |= ((off_t)(*cp++) << 16); + *lp |= ((off_t)(*cp++) << 8); + *lp |= (off_t)*cp; +#endif + } + *xpp = (const void *)((const char *)(*xpp) + sizeof_off_t); + return ENOERR; +} + + +/* + * Aggregate numeric conversion functions. + */ + + + +/* schar */ + +int +ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} +int +ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} +int +ncx_getn_schar_short(const void **xpp, size_t nelems, short *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_int(const void **xpp, size_t nelems, int *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_long(const void **xpp, size_t nelems, long *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_float(const void **xpp, size_t nelems, float *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_double(const void **xpp, size_t nelems, double *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + + +int +ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} +int +ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} +int +ncx_pad_getn_schar_short(const void **xpp, size_t nelems, short *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_int(const void **xpp, size_t nelems, int *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_long(const void **xpp, size_t nelems, long *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_float(const void **xpp, size_t nelems, float *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_double(const void **xpp, size_t nelems, double *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + + +int +ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} +int +ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} +int +ncx_putn_schar_short(void **xpp, size_t nelems, const short *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_int(void **xpp, size_t nelems, const int *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_long(void **xpp, size_t nelems, const long *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_float(void **xpp, size_t nelems, const float *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_double(void **xpp, size_t nelems, const double *tp) +{ + int status = ENOERR; + schar *xp = (schar *) *xpp; + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + + +int +ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} +int +ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} +int +ncx_pad_putn_schar_short(void **xpp, size_t nelems, const short *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_int(void **xpp, size_t nelems, const int *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_long(void **xpp, size_t nelems, const long *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_float(void **xpp, size_t nelems, const float *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *) *xpp; + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + + + +/* short */ + +int +ncx_getn_short_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_SHORT == SIZEOF_SHORT +/* optimized version */ +int +ncx_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(short)); +# else + swapn2b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_SHORT); + return ENOERR; +} +#else +int +ncx_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +int +ncx_getn_short_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncx_pad_getn_short_schar(const void **xpp, size_t nelems, schar *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_int(const void **xpp, size_t nelems, int *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_long(const void **xpp, size_t nelems, long *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_float(const void **xpp, size_t nelems, float *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_double(const void **xpp, size_t nelems, double *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + + +int +ncx_putn_short_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_SHORT == SIZEOF_SHORT +/* optimized version */ +int +ncx_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_SHORT); +# else + swapn2b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_SHORT); + return ENOERR; +} +#else +int +ncx_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +int +ncx_putn_short_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + +int +ncx_pad_putn_short_schar(void **xpp, size_t nelems, const schar *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_int(void **xpp, size_t nelems, const int *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_long(void **xpp, size_t nelems, const long *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_float(void **xpp, size_t nelems, const float *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + int lstatus = ncx_put_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + + + +/* int */ + +int +ncx_getn_int_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_int_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_int_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_INT == SIZEOF_INT +/* optimized version */ +int +ncx_getn_int_int(const void **xpp, size_t nelems, int *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(int)); +# else + swapn4b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncx_getn_int_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +#if X_SIZEOF_INT == SIZEOF_LONG +/* optimized version */ +int +ncx_getn_int_long(const void **xpp, size_t nelems, long *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(long)); +# else + swapn4b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncx_getn_int_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +int +ncx_getn_int_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_int_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncx_putn_int_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncx_put_int_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_int_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncx_put_int_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_int_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncx_put_int_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_INT == SIZEOF_INT +/* optimized version */ +int +ncx_putn_int_int(void **xpp, size_t nelems, const int *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT); +# else + swapn4b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncx_putn_int_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncx_put_int_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +#if X_SIZEOF_INT == SIZEOF_LONG +/* optimized version */ +int +ncx_putn_int_long(void **xpp, size_t nelems, const long *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT); +# else + swapn4b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT); + return ENOERR; +} +#else +int +ncx_putn_int_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncx_put_int_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +int +ncx_putn_int_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncx_put_int_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_int_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + int lstatus = ncx_put_int_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + + +/* float */ + +int +ncx_getn_float_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(float)); +# else + swapn4b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_FLOAT); + return ENOERR; +} +#elif vax +int +ncx_getn_float_float(const void **xpp, size_t nfloats, float *ip) +{ + float *const end = ip + nfloats; + + while(ip < end) + { + struct vax_single *const vsp = (struct vax_single *) ip; + const struct ieee_single *const isp = + (const struct ieee_single *) (*xpp); + unsigned exp = isp->exp_hi << 1 | isp->exp_lo; + + switch(exp) { + case 0 : + /* ieee subnormal */ + if(isp->mant_hi == min.ieee.mant_hi + && isp->mant_lo_hi == min.ieee.mant_lo_hi + && isp->mant_lo_lo == min.ieee.mant_lo_lo) + { + *vsp = min.s; + } + else + { + unsigned mantissa = (isp->mant_hi << 16) + | isp->mant_lo_hi << 8 + | isp->mant_lo_lo; + unsigned tmp = mantissa >> 20; + if(tmp >= 4) { + vsp->exp = 2; + } else if (tmp >= 2) { + vsp->exp = 1; + } else { + *vsp = min.s; + break; + } /* else */ + tmp = mantissa - (1 << (20 + vsp->exp )); + tmp <<= 3 - vsp->exp; + vsp->mantissa2 = tmp; + vsp->mantissa1 = (tmp >> 16); + } + break; + case 0xfe : + case 0xff : + *vsp = max.s; + break; + default : + vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo; + vsp->mantissa1 = isp->mant_hi; + } + + vsp->sign = isp->sign; + + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_FLOAT; + } + return ENOERR; +} +#elif _SX && _FLOAT2 +int +ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) +{ + const char *const xp = *xpp; + + const int ncnv = ie3_fl2(xp, tp, 4, 8, nelems); + + *xpp = xp + nelems * X_SIZEOF_FLOAT; + return (nelems == ncnv ? ENOERR : NC_ERANGE); +} +#else +int +ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif +int +ncx_getn_float_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncx_putn_float_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncx_put_float_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncx_put_float_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncx_put_float_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncx_put_float_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncx_put_float_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_FLOAT); +# else + swapn4b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_FLOAT); + return ENOERR; +} +#elif vax +int +ncx_putn_float_float(void **xpp, size_t nfloats, const float *ip) +{ + const float *const end = ip + nfloats; + + while(ip < end) + { + const struct vax_single *const vsp = + (const struct vax_single *)ip; + struct ieee_single *const isp = (struct ieee_single *) (*xpp); + + switch(vsp->exp){ + case 0 : + /* all vax float with zero exponent map to zero */ + *isp = min.ieee; + break; + case 2 : + case 1 : + { + /* These will map to subnormals */ + unsigned mantissa = (vsp->mantissa1 << 16) + | vsp->mantissa2; + mantissa >>= 3 - vsp->exp; + mantissa += (1 << (20 + vsp->exp)); + isp->mant_lo_lo = mantissa; + isp->mant_lo_hi = mantissa >> 8; + isp->mant_hi = mantissa >> 16; + isp->exp_lo = 0; + isp->exp_hi = 0; + } + break; + case 0xff : /* max.s.exp */ + if( vsp->mantissa2 == max.s.mantissa2 + && vsp->mantissa1 == max.s.mantissa1) + { + /* map largest vax float to ieee infinity */ + *isp = max.ieee; + break; + } /* else, fall thru */ + default : + { + unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + isp->exp_hi = exp >> 1; + isp->exp_lo = exp; + isp->mant_lo_lo = vsp->mantissa2; + isp->mant_lo_hi = vsp->mantissa2 >> 8; + isp->mant_hi = vsp->mantissa1; + } + } + + isp->sign = vsp->sign; + + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_FLOAT; + } + return ENOERR; +} +#elif _SX && _FLOAT2 +int +ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) +{ + char *const xp = *xpp; + + const int ncnv = fl2_ie3(tp, xp, 8, 4, nelems); + + *xpp = xp + nelems * X_SIZEOF_FLOAT; + return (nelems == ncnv ? ENOERR : NC_ERANGE); +} +#else +int +ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncx_put_float_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif +int +ncx_putn_float_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + int lstatus = ncx_put_float_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + + +/* double */ + +int +ncx_getn_double_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = (const char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(tp, *xpp, nelems * sizeof(double)); +# else + swapn8b(tp, *xpp, nelems); +# endif + *xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return ENOERR; +} +#elif vax +int +ncx_getn_double_double(const void **xpp, size_t ndoubles, double *ip) +{ + double *const end = ip + ndoubles; + + while(ip < end) + { + struct vax_double *const vdp = + (struct vax_double *)ip; + const struct ieee_double *const idp = + (const struct ieee_double *) (*xpp); + { + const struct dbl_limits *lim; + int ii; + for (ii = 0, lim = dbl_limits; + ii < sizeof(dbl_limits)/sizeof(struct dbl_limits); + ii++, lim++) + { + if ((idp->mant_lo == lim->ieee.mant_lo) + && (idp->mant_4 == lim->ieee.mant_4) + && (idp->mant_5 == lim->ieee.mant_5) + && (idp->mant_6 == lim->ieee.mant_6) + && (idp->exp_lo == lim->ieee.exp_lo) + && (idp->exp_hi == lim->ieee.exp_hi) + ) + { + *vdp = lim->d; + goto doneit; + } + } + } + { + unsigned exp = idp->exp_hi << 4 | idp->exp_lo; + vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + } + { + unsigned mant_hi = ((idp->mant_6 << 16) + | (idp->mant_5 << 8) + | idp->mant_4); + unsigned mant_lo = SWAP4(idp->mant_lo); + vdp->mantissa1 = (mant_hi >> 13); + vdp->mantissa2 = ((mant_hi & MASK(13)) << 3) + | (mant_lo >> 29); + vdp->mantissa3 = (mant_lo >> 13); + vdp->mantissa4 = (mant_lo << 3); + } + doneit: + vdp->sign = idp->sign; + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE; + } + return ENOERR; +} + /* vax */ +#elif _SX && _FLOAT2 +int +ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ + const char *const xp = *xpp; + + const int ncnv = ie3_fl2(xp, tp, 8, 8, nelems); + + *xpp = xp + nelems * X_SIZEOF_DOUBLE; + return (nelems == ncnv ? ENOERR : NC_ERANGE); +} +#else +int +ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#endif + +int +ncx_putn_double_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncx_put_double_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncx_put_double_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncx_put_double_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncx_put_double_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncx_put_double_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = (char *) *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncx_put_double_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) +/* optimized version */ +int +ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ +# if WORDS_BIGENDIAN + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_DOUBLE); +# else + swapn8b(*xpp, tp, nelems); +# endif + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return ENOERR; +} +#elif vax +int +ncx_putn_double_double(void **xpp, size_t ndoubles, const double *ip) +{ + const double *const end = ip + ndoubles; + + while(ip < end) + { + const struct vax_double *const vdp = + (const struct vax_double *)ip; + struct ieee_double *const idp = + (struct ieee_double *) (*xpp); + + if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) && + (vdp->mantissa3 == dbl_limits[0].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[0].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[0].d.mantissa1) && + (vdp->exp == dbl_limits[0].d.exp)) + { + *idp = dbl_limits[0].ieee; + goto shipit; + } + if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) && + (vdp->mantissa3 == dbl_limits[1].d.mantissa3) && + (vdp->mantissa2 == dbl_limits[1].d.mantissa2) && + (vdp->mantissa1 == dbl_limits[1].d.mantissa1) && + (vdp->exp == dbl_limits[1].d.exp)) + { + *idp = dbl_limits[1].ieee; + goto shipit; + } + + { + unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + + unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) | + (vdp->mantissa3 << 13) | + ((vdp->mantissa4 >> 3) & MASK(13)); + + unsigned mant_hi = (vdp->mantissa1 << 13) + | (vdp->mantissa2 >> 3); + + if((vdp->mantissa4 & 7) > 4) + { + /* round up */ + mant_lo++; + if(mant_lo == 0) + { + mant_hi++; + if(mant_hi > 0xffffff) + { + mant_hi = 0; + exp++; + } + } + } + + idp->mant_lo = SWAP4(mant_lo); + idp->mant_6 = mant_hi >> 16; + idp->mant_5 = (mant_hi & 0xff00) >> 8; + idp->mant_4 = mant_hi; + idp->exp_hi = exp >> 4; + idp->exp_lo = exp; + } + + shipit: + idp->sign = vdp->sign; + + ip++; + *xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE; + } + return ENOERR; +} + /* vax */ +#elif _SX && _FLOAT2 +int +ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ + char *const xp = *xpp; + + const int ncnv = fl2_ie3(tp, xp, 8, 8, nelems); + + *xpp = xp + nelems * X_SIZEOF_DOUBLE; + return (nelems == ncnv ? ENOERR : NC_ERANGE); +} +#else +int +ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + int lstatus = ncx_put_double_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#endif + + +/* + * Other aggregate conversion functions. + */ + +/* text */ + +int +ncx_getn_text(const void **xpp, size_t nelems, char *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} + +int +ncx_pad_getn_text(const void **xpp, size_t nelems, char *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} + +int +ncx_putn_text(void **xpp, size_t nelems, const char *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} + +int +ncx_pad_putn_text(void **xpp, size_t nelems, const char *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} + + +/* opaque */ + +int +ncx_getn_void(const void **xpp, size_t nelems, void *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} + +int +ncx_pad_getn_void(const void **xpp, size_t nelems, void *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} + +int +ncx_putn_void(void **xpp, size_t nelems, const void *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} + +int +ncx_pad_putn_void(void **xpp, size_t nelems, const void *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} diff --git a/Utilities/vtknetcdf/ncx.h b/Utilities/vtknetcdf/ncx.h new file mode 100644 index 0000000..5bc89a2 --- /dev/null +++ b/Utilities/vtknetcdf/ncx.h @@ -0,0 +1,663 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* "$Id: ncx.h,v 1.3 2005/07/26 19:48:16 king Exp $" */ + +#ifndef _NCX_H_ +#define _NCX_H_ + +/* + * An external data representation interface. + * + * This started out as a general replacement for ONC XDR, + * specifically, the xdrmem family of functions. + * + * We eventually realized that we could write more portable + * code if we decoupled any association between the 'C' types + * and the external types. (XDR has this association between the 'C' + * types and the external representations, like xdr_int() takes + * an int argument and goes to an external int representation.) + * So, now there is a matrix of functions. + * + */ + +#include "ncconfig.h" /* output of 'configure' */ +#include "rnd.h" +#include <stddef.h> /* size_t */ +#include <errno.h> +#include <sys/types.h> /* off_t */ + +#ifdef _MSC_VER +# pragma warning ( disable : 4244 ) +#endif + + +#if defined(_CRAY) && !defined(_CRAYIEEE) +#define CRAYFLOAT 1 /* CRAY Floating point */ +#elif defined(_SX) && defined(_FLOAT2) /* NEC SUPER-UX in CRAY mode */ +#define CRAYFLOAT 1 /* CRAY Floating point */ +#endif + +/* + * The integer return code for the conversion routines + * is 0 (ENOERR) when no error occured, or NC_ERANGE as appropriate + * for an overflow conversion. + */ +#ifndef ENOERR +#define ENOERR 0 +#endif +#ifndef NC_ERANGE +#define NC_ERANGE (-60) /* N.B. must match value in netcdf.h */ +#endif + + +/* + * External sizes of the primitive elements. + */ +#define X_SIZEOF_CHAR 1 +#define X_SIZEOF_SHORT 2 +#define X_SIZEOF_INT 4 /* xdr_int */ +#if 0 +#define X_SIZEOF_LONG 8 */ /* xdr_long_long */ +#endif +#define X_SIZEOF_FLOAT 4 +#define X_SIZEOF_DOUBLE 8 + +/* + * For now, netcdf is limited to 32 bit offsets and sizes, + * see also X_SIZE_MAX, X_OFF_MAX below + */ +#define X_SIZEOF_OFF_T (sizeof(off_t)) +#define X_SIZEOF_SIZE_T X_SIZEOF_INT + +/* + * limits of the external representation + */ +#define X_SCHAR_MIN (-128) +#define X_SCHAR_MAX 127 +#define X_UCHAR_MAX 255U +#define X_SHORT_MIN (-32768) +#define X_SHRT_MIN X_SHORT_MIN /* alias compatible with limits.h */ +#define X_SHORT_MAX 32767 +#define X_SHRT_MAX X_SHORT_MAX /* alias compatible with limits.h */ +#define X_USHORT_MAX 65535U +#define X_USHRT_MAX X_USHORT_MAX /* alias compatible with limits.h */ +#define X_INT_MIN (-2147483647-1) +#define X_INT_MAX 2147483647 +#define X_UINT_MAX 4294967295U +#if 0 +#define X_LONG_MIN (-2147483647-1) +#define X_LONG_MAX 2147483647 +#define X_ULONG_MAX 4294967295U +#endif +#define X_FLOAT_MAX ((float)3.40282347e+38) +#define X_FLOAT_MIN (-X_FLOAT_MAX) +#define X_FLT_MAX X_FLOAT_MAX /* alias compatible with limits.h */ +#if CRAYFLOAT +/* ldexp(1. - ldexp(.5 , -46), 1024) */ +#define X_DOUBLE_MAX 1.79769313486230e+308 +#else +/* scalb(1. - scalb(.5 , -52), 1024) */ +#define X_DOUBLE_MAX 1.7976931348623157e+308 +#endif +#define X_DOUBLE_MIN (-X_DOUBLE_MAX) +#define X_DBL_MAX X_DOUBLE_MAX /* alias compatible with limits.h */ + +#define X_SIZE_MAX X_INT_MAX /* N.B., just uses the signed range */ +#define X_OFF_MAX X_INT_MAX + + +/* Begin ncx_len */ + +/* + * ncx_len_xxx() interfaces are defined as macros below, + * These give the length of an array of nelems of the type. + * N.B. The 'char' and 'short' interfaces give the X_ALIGNED length. + */ +#define X_ALIGN 4 /* a.k.a. BYTES_PER_XDR_UNIT */ + +#define ncx_len_char(nelems) \ + _RNDUP((nelems), X_ALIGN) + +#define ncx_len_short(nelems) \ + (((nelems) + (nelems)%2) * X_SIZEOF_SHORT) + +#define ncx_len_int(nelems) \ + ((nelems) * X_SIZEOF_INT) + +#define ncx_len_long(nelems) \ + ((nelems) * X_SIZEOF_LONG) + +#define ncx_len_float(nelems) \ + ((nelems) * X_SIZEOF_FLOAT) + +#define ncx_len_double(nelems) \ + ((nelems) * X_SIZEOF_DOUBLE) + +/* End ncx_len */ + +#if __CHAR_UNSIGNED__ + /* 'char' is unsigned, declare ncbyte as 'signed char' */ +typedef signed char schar; + +#else + /* 'char' is signed */ +typedef signed char schar; + +#endif /* __CHAR_UNSIGNED__ */ + +/* + * Primitive numeric conversion functions. + * The `put' functions convert from native internal + * type to the external type, while the `get' functions + * convert from the external to the internal. + * + * These take the form + * int ncx_get_{external_type}_{internal_type}( + * const void *xp, + * internal_type *ip + * ); + * int ncx_put_{external_type}_{internal_type}( + * void *xp, + * const internal_type *ip + * ); + * where + * `external_type' and `internal_type' chosen from + schar + uchar + short + ushort + int + uint + long + ulong + float + double + * + * Not all combinations make sense. + * We may not implement all combinations that make sense. + * The netcdf functions that use this ncx interface don't + * use these primitive conversion functions. They use the + * aggregate conversion functions declared below. + * + * Storage for a single element of external type is at the `void * xp' + * argument. + * + * Storage for a single element of internal type is at `ip' argument. + * + * These functions return 0 (ENOERR) when no error occured, + * or NC_ERANGE when the value being converted is too large. + * When NC_ERANGE occurs, an undefined (implementation dependent) + * conversion may have occured. + * + * Note that loss of precision may occur silently. + * + */ + +#if 0 +extern int +ncx_get_schar_schar(const void *xp, schar *ip); +extern int +ncx_get_schar_uchar(const void *xp, uchar *ip); +extern int +ncx_get_schar_short(const void *xp, short *ip); +extern int +ncx_get_schar_int(const void *xp, int *ip); +extern int +ncx_get_schar_long(const void *xp, long *ip); +extern int +ncx_get_schar_float(const void *xp, float *ip); +extern int +ncx_get_schar_double(const void *xp, double *ip); + +extern int +ncx_put_schar_schar(void *xp, const schar *ip); +extern int +ncx_put_schar_uchar(void *xp, const uchar *ip); +extern int +ncx_put_schar_short(void *xp, const short *ip); +extern int +ncx_put_schar_int(void *xp, const int *ip); +extern int +ncx_put_schar_long(void *xp, const long *ip); +extern int +ncx_put_schar_float(void *xp, const float *ip); +extern int +ncx_put_schar_double(void *xp, const double *ip); +#endif + + +extern int +ncx_get_short_schar(const void *xp, schar *ip); +extern int +ncx_get_short_uchar(const void *xp, uchar *ip); +extern int +ncx_get_short_short(const void *xp, short *ip); +extern int +ncx_get_short_int(const void *xp, int *ip); +extern int +ncx_get_short_long(const void *xp, long *ip); +extern int +ncx_get_short_float(const void *xp, float *ip); +extern int +ncx_get_short_double(const void *xp, double *ip); + +extern int +ncx_put_short_schar(void *xp, const schar *ip); +extern int +ncx_put_short_uchar(void *xp, const uchar *ip); +extern int +ncx_put_short_short(void *xp, const short *ip); +extern int +ncx_put_short_int(void *xp, const int *ip); +extern int +ncx_put_short_long(void *xp, const long *ip); +extern int +ncx_put_short_float(void *xp, const float *ip); +extern int +ncx_put_short_double(void *xp, const double *ip); + + +extern int +ncx_get_int_schar(const void *xp, schar *ip); +extern int +ncx_get_int_uchar(const void *xp, uchar *ip); +extern int +ncx_get_int_short(const void *xp, short *ip); +extern int +ncx_get_int_int(const void *xp, int *ip); +extern int +ncx_get_int_long(const void *xp, long *ip); +extern int +ncx_get_int_float(const void *xp, float *ip); +extern int +ncx_get_int_double(const void *xp, double *ip); + +extern int +ncx_put_int_schar(void *xp, const schar *ip); +extern int +ncx_put_int_uchar(void *xp, const uchar *ip); +extern int +ncx_put_int_short(void *xp, const short *ip); +extern int +ncx_put_int_int(void *xp, const int *ip); +extern int +ncx_put_int_long(void *xp, const long *ip); +extern int +ncx_put_int_float(void *xp, const float *ip); +extern int +ncx_put_int_double(void *xp, const double *ip); + + +extern int +ncx_get_float_schar(const void *xp, schar *ip); +extern int +ncx_get_float_uchar(const void *xp, uchar *ip); +extern int +ncx_get_float_short(const void *xp, short *ip); +extern int +ncx_get_float_int(const void *xp, int *ip); +extern int +ncx_get_float_long(const void *xp, long *ip); +extern int +ncx_get_float_float(const void *xp, float *ip); +extern int +ncx_get_float_double(const void *xp, double *ip); + +extern int +ncx_put_float_schar(void *xp, const schar *ip); +extern int +ncx_put_float_uchar(void *xp, const uchar *ip); +extern int +ncx_put_float_short(void *xp, const short *ip); +extern int +ncx_put_float_int(void *xp, const int *ip); +extern int +ncx_put_float_long(void *xp, const long *ip); +extern int +ncx_put_float_float(void *xp, const float *ip); +extern int +ncx_put_float_double(void *xp, const double *ip); + + +extern int +ncx_get_double_schar(const void *xp, schar *ip); +extern int +ncx_get_double_uchar(const void *xp, uchar *ip); +extern int +ncx_get_double_short(const void *xp, short *ip); +extern int +ncx_get_double_int(const void *xp, int *ip); +extern int +ncx_get_double_long(const void *xp, long *ip); +extern int +ncx_get_double_float(const void *xp, float *ip); +extern int +ncx_get_double_double(const void *xp, double *ip); + +extern int +ncx_put_double_schar(void *xp, const schar *ip); +extern int +ncx_put_double_uchar(void *xp, const uchar *ip); +extern int +ncx_put_double_short(void *xp, const short *ip); +extern int +ncx_put_double_int(void *xp, const int *ip); +extern int +ncx_put_double_long(void *xp, const long *ip); +extern int +ncx_put_double_float(void *xp, const float *ip); +extern int +ncx_put_double_double(void *xp, const double *ip); + + +/* + * Other primitive conversion functions + * N.B. slightly different interface + * Used by netcdf. + */ + +/* ncx_get_int_size_t */ +extern int +ncx_get_size_t(const void **xpp, size_t *ulp); +/* ncx_get_int_off_t */ +extern int +ncx_get_off_t(const void **xpp, off_t *lp, size_t sizeof_off_t); + +/* ncx_put_int_size_t */ +extern int +ncx_put_size_t(void **xpp, const size_t *ulp); +/* ncx_put_int_off_t */ +extern int +ncx_put_off_t(void **xpp, const off_t *lp, size_t sizeof_off_t); + + +/* + * Aggregate numeric conversion functions. + * Convert an array. Replaces xdr_array(...). + * These functions are used by netcdf. Unlike the xdr + * interface, we optimize for aggregate conversions. + * This functions should be implemented to take advantage + * of multiple processor / parallel hardware where available. + * + * These take the form + * int ncx_getn_{external_type}_{internal_type}( + * const void *xpp, + * size_t nelems, + * internal_type *ip + * ); + * int ncx_putn_{external_type}_{internal_type}( + * void **xpp, + * size_t nelems, + * const internal_type *ip + * ); + * Where the types are as in the primitive numeric conversion functions. + * + * The value of the pointer to pointer argument, *xpp, is + * expected to reference storage for `nelems' of the external + * type. On return, it modified to reference just past the last + * converted external element. + * + * The types whose external size is less than X_ALIGN also have `pad' + * interfaces. These round (and zero fill on put) *xpp up to X_ALIGN + * boundaries. (This is the usual xdr behavior.) + * + * The `ip' argument should point to an array of `nelems' of + * internal_type. + * + * Range errors (NC_ERANGE) for a individual values in the array + * DO NOT terminate the array conversion. All elements are converted, + * with some having undefined values. + * If any range error occurs, the function returns NC_ERANGE. + * + */ + +extern int +ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncx_getn_schar_short(const void **xpp, size_t nelems, short *ip); +extern int +ncx_getn_schar_int(const void **xpp, size_t nelems, int *ip); +extern int +ncx_getn_schar_long(const void **xpp, size_t nelems, long *ip); +extern int +ncx_getn_schar_float(const void **xpp, size_t nelems, float *ip); +extern int +ncx_getn_schar_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncx_pad_getn_schar_short(const void **xpp, size_t nelems, short *ip); +extern int +ncx_pad_getn_schar_int(const void **xpp, size_t nelems, int *ip); +extern int +ncx_pad_getn_schar_long(const void **xpp, size_t nelems, long *ip); +extern int +ncx_pad_getn_schar_float(const void **xpp, size_t nelems, float *ip); +extern int +ncx_pad_getn_schar_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncx_putn_schar_short(void **xpp, size_t nelems, const short *ip); +extern int +ncx_putn_schar_int(void **xpp, size_t nelems, const int *ip); +extern int +ncx_putn_schar_long(void **xpp, size_t nelems, const long *ip); +extern int +ncx_putn_schar_float(void **xpp, size_t nelems, const float *ip); +extern int +ncx_putn_schar_double(void **xpp, size_t nelems, const double *ip); + +extern int +ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncx_pad_putn_schar_short(void **xpp, size_t nelems, const short *ip); +extern int +ncx_pad_putn_schar_int(void **xpp, size_t nelems, const int *ip); +extern int +ncx_pad_putn_schar_long(void **xpp, size_t nelems, const long *ip); +extern int +ncx_pad_putn_schar_float(void **xpp, size_t nelems, const float *ip); +extern int +ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncx_getn_short_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncx_getn_short_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncx_getn_short_short(const void **xpp, size_t nelems, short *ip); +extern int +ncx_getn_short_int(const void **xpp, size_t nelems, int *ip); +extern int +ncx_getn_short_long(const void **xpp, size_t nelems, long *ip); +extern int +ncx_getn_short_float(const void **xpp, size_t nelems, float *ip); +extern int +ncx_getn_short_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncx_pad_getn_short_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncx_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncx_pad_getn_short_short(const void **xpp, size_t nelems, short *ip); +extern int +ncx_pad_getn_short_int(const void **xpp, size_t nelems, int *ip); +extern int +ncx_pad_getn_short_long(const void **xpp, size_t nelems, long *ip); +extern int +ncx_pad_getn_short_float(const void **xpp, size_t nelems, float *ip); +extern int +ncx_pad_getn_short_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncx_putn_short_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncx_putn_short_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncx_putn_short_short(void **xpp, size_t nelems, const short *ip); +extern int +ncx_putn_short_int(void **xpp, size_t nelems, const int *ip); +extern int +ncx_putn_short_long(void **xpp, size_t nelems, const long *ip); +extern int +ncx_putn_short_float(void **xpp, size_t nelems, const float *ip); +extern int +ncx_putn_short_double(void **xpp, size_t nelems, const double *ip); + +extern int +ncx_pad_putn_short_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncx_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncx_pad_putn_short_short(void **xpp, size_t nelems, const short *ip); +extern int +ncx_pad_putn_short_int(void **xpp, size_t nelems, const int *ip); +extern int +ncx_pad_putn_short_long(void **xpp, size_t nelems, const long *ip); +extern int +ncx_pad_putn_short_float(void **xpp, size_t nelems, const float *ip); +extern int +ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncx_getn_int_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncx_getn_int_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncx_getn_int_short(const void **xpp, size_t nelems, short *ip); +extern int +ncx_getn_int_int(const void **xpp, size_t nelems, int *ip); +extern int +ncx_getn_int_long(const void **xpp, size_t nelems, long *ip); +extern int +ncx_getn_int_float(const void **xpp, size_t nelems, float *ip); +extern int +ncx_getn_int_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncx_putn_int_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncx_putn_int_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncx_putn_int_short(void **xpp, size_t nelems, const short *ip); +extern int +ncx_putn_int_int(void **xpp, size_t nelems, const int *ip); +extern int +ncx_putn_int_long(void **xpp, size_t nelems, const long *ip); +extern int +ncx_putn_int_float(void **xpp, size_t nelems, const float *ip); +extern int +ncx_putn_int_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncx_getn_float_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncx_getn_float_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncx_getn_float_short(const void **xpp, size_t nelems, short *ip); +extern int +ncx_getn_float_int(const void **xpp, size_t nelems, int *ip); +extern int +ncx_getn_float_long(const void **xpp, size_t nelems, long *ip); +extern int +ncx_getn_float_float(const void **xpp, size_t nelems, float *ip); +extern int +ncx_getn_float_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncx_putn_float_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncx_putn_float_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncx_putn_float_short(void **xpp, size_t nelems, const short *ip); +extern int +ncx_putn_float_int(void **xpp, size_t nelems, const int *ip); +extern int +ncx_putn_float_long(void **xpp, size_t nelems, const long *ip); +extern int +ncx_putn_float_float(void **xpp, size_t nelems, const float *ip); +extern int +ncx_putn_float_double(void **xpp, size_t nelems, const double *ip); + + +extern int +ncx_getn_double_schar(const void **xpp, size_t nelems, schar *ip); +extern int +ncx_getn_double_uchar(const void **xpp, size_t nelems, uchar *ip); +extern int +ncx_getn_double_short(const void **xpp, size_t nelems, short *ip); +extern int +ncx_getn_double_int(const void **xpp, size_t nelems, int *ip); +extern int +ncx_getn_double_long(const void **xpp, size_t nelems, long *ip); +extern int +ncx_getn_double_float(const void **xpp, size_t nelems, float *ip); +extern int +ncx_getn_double_double(const void **xpp, size_t nelems, double *ip); + +extern int +ncx_putn_double_schar(void **xpp, size_t nelems, const schar *ip); +extern int +ncx_putn_double_uchar(void **xpp, size_t nelems, const uchar *ip); +extern int +ncx_putn_double_short(void **xpp, size_t nelems, const short *ip); +extern int +ncx_putn_double_int(void **xpp, size_t nelems, const int *ip); +extern int +ncx_putn_double_long(void **xpp, size_t nelems, const long *ip); +extern int +ncx_putn_double_float(void **xpp, size_t nelems, const float *ip); +extern int +ncx_putn_double_double(void **xpp, size_t nelems, const double *ip); + + +/* + * Other aggregate conversion functions. + */ + +/* read ASCII characters */ +extern int +ncx_getn_text(const void **xpp, size_t nchars, char *cp); +extern int +ncx_pad_getn_text(const void **xpp, size_t nchars, char *cp); + +/* write ASCII characters */ +extern int +ncx_putn_text(void **xpp, size_t nchars, const char *cp); +extern int +ncx_pad_putn_text(void **xpp, size_t nchars, const char *cp); + +/* for symmetry */ +#define ncx_getn_char_char(xpp, nelems, fillp) ncx_getn_text(xpp, nelems, fillp) +#define ncx_putn_char_char(xpp, nelems, fillp) ncx_putn_text(xpp, nelems, fillp) + +/* read opaque data */ +extern int +ncx_getn_void(const void **xpp, size_t nchars, void *vp); +extern int +ncx_pad_getn_void(const void **xpp, size_t nchars, void *vp); + +/* write opaque data */ +extern int +ncx_putn_void(void **xpp, size_t nchars, const void *vp); +extern int +ncx_pad_putn_void(void **xpp, size_t nchars, const void *vp); + +#endif /* _NCX_H_ */ diff --git a/Utilities/vtknetcdf/ncx_cray.c b/Utilities/vtknetcdf/ncx_cray.c new file mode 100644 index 0000000..87223d9 --- /dev/null +++ b/Utilities/vtknetcdf/ncx_cray.c @@ -0,0 +1,3820 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + * + */ +/* $Id: ncx_cray.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ +#ifndef _CRAY +#error "ncx_cray.c is a cray specific implementation" +#endif + +/* + * An external data representation interface. + */ +/* + * TODO: Fix "off diagonal" functions (ncx_{put,get}[n]_t1_t2() s.t. t1 != t2) + * to be use IEG functions when diagonals are. + * + * Whine to cray about IEG function limiting behavior. + */ + +#include <string.h> +#include <limits.h> +/* alias poorly named limits.h macros */ +#define SHORT_MAX SHRT_MAX +#define SHORT_MIN SHRT_MIN +#define USHORT_MAX USHRT_MAX +#include <float.h> +#include <assert.h> +#include "ncx.h" + +/**/ +#if USE_IEG +#define C_SIZE_T size_t + +extern int +CRAY2IEG( + const int *typep, + const C_SIZE_T *nump, + word *foreignp, + const int *bitoffp, + const void *local, + const int *stride +); + +extern int +IEG2CRAY( + const int *typep, + const C_SIZE_T *nump, + const word *foreignp, + const int *bitoffp, + void *local, + const int *stride +); + + +static const int Zero = 0; +static const C_SIZE_T One = 1; +static const int ThirtyTwo = 32; +static const int UnitStride = 1; +static const int Cray2_I32 = 1; /* 32 bit two complement */ +static const int Cray2_F32 = 2; /* IEEE single precision */ +static const int Cray2_I16 = 7; /* 16 bit twos complement */ +static const int Cray2_F64 = 8; /* CRAY float to IEEE double */ + +#define SHORT_USE_IEG 1 +#define INT_USE_IEG 1 +#define FLOAT_USE_IEG 1 +#define DOUBLE_USE_IEG 1 + +#if _CRAY1 +/* + * Return the number of bits "into" a word that (void *) is. + * N.B. This is based on the CRAY1 (PVP) address structure, + * which puts the address within a word in the leftmost 3 bits + * of the address. + */ +static size_t +bitoff(const void *vp) +{ + const size_t bitoffset = ((size_t)vp >> (64 - 6)) & 0x3f; + return bitoffset; +} +# else +#error "Don't use IEG2CRAY, CRAY2IEG except on CRAY1 (MPP) platforms" +#define bitoff(vp) ((size_t)(vp) % 64) /* N.B. Assumes 64 bit word */ +# endif /* _CRAY1 */ + +#endif /* USE_IEG */ + +#if _CRAY1 +/* + * Return the number of bytes "into" a word that (void *) is. + * N.B. This is based on the CRAY1 (PVP) address structure, + * which puts the address within a word in the leftmost 3 bits + * of the address. + */ +static size_t +byteoff(const void *vp) +{ + const size_t byteoffset = ((size_t)vp >> (64 - 3)) & 0x7; + return byteoffset; +} +#else +#define byteoff(vp) ((size_t)(vp) % 8) /* N.B. Assumes 64 bit word */ +#endif /* _CRAY1 */ + +/* + * Return the number of bytes until the next "word" boundary + */ +static size_t +word_align(const void *vp) +{ + const size_t rem = byteoff(vp); + if(rem == 0) + return 0; + return sizeof(word) - rem; +} + + +static const char nada[X_ALIGN] = {0, 0, 0, 0}; + + +/* + * Primitive numeric conversion functions. + */ + +/* x_schar */ + + /* We don't implement and x_schar primitives. */ + + +/* x_short */ + +typedef short ix_short; +#define SIZEOF_IX_SHORT SIZEOF_SHORT +#define IX_SHORT_MAX SHORT_MAX + +static void +cget_short_short(const void *xp, short *ip, int which) +{ + const long *wp = xp; + + switch(which) { + case 0: + *ip = (short)(*wp >> 48); + break; + case 1: + *ip = (short)((*wp >> 32) & 0xffff); + break; + case 2: + *ip = (short)((*wp >> 16) & 0xffff); + break; + case 3: + *ip = (short)(*wp & 0xffff); + break; + } + + if(*ip & 0x8000) + { + /* extern is negative */ + *ip |= (~(0xffff)); + } +} +#define get_ix_short(xp, ip) cget_short_short((xp), (ip), byteoff(xp)/X_SIZEOF_SHORT) + +static int +cput_short_short(void *xp, const short *ip, int which) +{ + word *wp = xp; + + switch(which) { + case 0: + *wp = (*ip << 48) + | (*wp & 0x0000ffffffffffff); + break; + case 1: + *wp = ((*ip << 32) & 0x0000ffff00000000) + | (*wp & 0xffff0000ffffffff); + break; + case 2: + *wp = ((*ip << 16) & 0x00000000ffff0000) + | (*wp & 0xffffffff0000ffff); + break; + case 3: + *wp = (*ip & 0x000000000000ffff) + | (*wp & 0xffffffffffff0000); + break; + } + + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_short_schar(const void *xp, schar *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_short_uchar(const void *xp, uchar *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_short_short(const void *xp, short *ip) +{ + get_ix_short(xp, ip); + return ENOERR; +} + +int +ncx_get_short_int(const void *xp, int *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncx_get_short_long(const void *xp, long *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncx_get_short_float(const void *xp, float *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncx_get_short_double(const void *xp, double *ip) +{ + ix_short xx; + get_ix_short(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncx_put_short_schar(void *xp, const schar *ip) +{ + uchar *cp = xp; + if(*ip & 0x80) + *cp++ = 0xff; + else + *cp++ = 0; + *cp = (uchar)*ip; + return ENOERR; +} + +int +ncx_put_short_uchar(void *xp, const uchar *ip) +{ + uchar *cp = xp; + *cp++ = 0; + *cp = *ip; + return ENOERR; +} + +int +ncx_put_short_short(void *xp, const short *ip) +{ + return cput_short_short(xp, ip, byteoff(xp)/X_SIZEOF_SHORT); +} + +int +ncx_put_short_int(void *xp, const int *ip) +{ + ix_short xx = (ix_short)*ip; + return cput_short_short(xp, &xx, byteoff(xp)/X_SIZEOF_SHORT); +} + +int +ncx_put_short_long(void *xp, const long *ip) +{ + ix_short xx = (ix_short)*ip; + return cput_short_short(xp, &xx, byteoff(xp)/X_SIZEOF_SHORT); +} + +int +ncx_put_short_float(void *xp, const float *ip) +{ + ix_short xx = (ix_short)*ip; + const int status = cput_short_short(xp, &xx, byteoff(xp)/X_SIZEOF_SHORT); + if(status != ENOERR) + return status; + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_put_short_double(void *xp, const double *ip) +{ + ix_short xx = (ix_short)*ip; + const int status = cput_short_short(xp, &xx, byteoff(xp)/X_SIZEOF_SHORT); + if(status != ENOERR) + return status; + if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +/* x_int */ + +typedef int ix_int; +#define SIZEOF_IX_INT SIZEOF_INT +#define IX_INT_MAX INT_MAX + +static void +cget_int_int(const void *xp, int *ip, int which) +{ + const long *wp = xp; + + if(which == 0) + { + *ip = (int)(*wp >> 32); + } + else + { + *ip = (int)(*wp & 0xffffffff); + } + + if(*ip & 0x80000000) + { + /* extern is negative */ + *ip |= (~(0xffffffff)); + } +} +#define get_ix_int(xp, ip) cget_int_int((xp), (ip), byteoff(xp)) + +static int +cput_int_int(void *xp, const int *ip, int which) +{ + word *wp = xp; + + if(which == 0) + { + *wp = (*ip << 32) | (*wp & 0xffffffff); + } + else + { + *wp = (*wp & ~0xffffffff) | (*ip & 0xffffffff); + } + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} +#define put_ix_int(xp, ip) cput_int_int((xp), (ip), byteoff(xp)) + +int +ncx_get_int_schar(const void *xp, schar *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_int_uchar(const void *xp, uchar *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_int_short(const void *xp, short *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_int_int(const void *xp, int *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + return ENOERR; +} + +static void +cget_int_long(const void *xp, long *ip, int which) +{ + const long *wp = xp; + + if(which == 0) + { + *ip = (int)(*wp >> 32); + } + else + { + *ip = (int)(*wp & 0xffffffff); + } + + if(*ip & 0x80000000) + { + /* extern is negative */ + *ip |= (~(0xffffffff)); + } +} + +int +ncx_get_int_long(const void *xp, long *ip) +{ + cget_int_long(xp, ip, byteoff(xp)); + return ENOERR; +} + +int +ncx_get_int_float(const void *xp, float *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + if(xx > FLT_MAX || xx < (-FLT_MAX)) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_int_double(const void *xp, double *ip) +{ + ix_int xx; + get_ix_int(xp, &xx); + *ip = xx; + return ENOERR; +} + +int +ncx_put_int_schar(void *xp, const schar *ip) +{ + uchar *cp = xp; + if(*ip & 0x80) + { + *cp++ = 0xff; + *cp++ = 0xff; + *cp++ = 0xff; + } + else + { + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; + } + *cp = (uchar)*ip; + return ENOERR; +} + +int +ncx_put_int_uchar(void *xp, const uchar *ip) +{ + uchar *cp = xp; + *cp++ = 0x00; + *cp++ = 0x00; + *cp++ = 0x00; + *cp = *ip; + return ENOERR; +} + +int +ncx_put_int_short(void *xp, const short *ip) +{ + ix_int xx = (ix_int)(*ip); + return put_ix_int(xp, &xx); +} + +int +ncx_put_int_int(void *xp, const int *ip) +{ + return put_ix_int(xp, ip); +} + +static int +cput_int_long(void *xp, const long *ip, int which) +{ + long *wp = xp; + + if(which == 0) + { + *wp = (*ip << 32) | (*wp & 0xffffffff); + } + else + { + *wp = (*wp & ~0xffffffff) | (*ip & 0xffffffff); + } + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_put_int_long(void *xp, const long *ip) +{ + return cput_int_long(xp, ip, byteoff(xp)); +} + +int +ncx_put_int_float(void *xp, const float *ip) +{ + ix_int xx = (ix_int)(*ip); + const int status = put_ix_int(xp, &xx); + if(status != ENOERR) + return status; + if(*ip > (double)X_INT_MAX || *ip < (double)X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_put_int_double(void *xp, const double *ip) +{ + ix_int xx = (ix_int)(*ip); + const int status = put_ix_int(xp, &xx); + if(status != ENOERR) + return status; + if(*ip > X_INT_MAX || *ip < X_INT_MIN) + return NC_ERANGE; + return ENOERR; +} + + +/* x_float */ + +#if defined(NO_IEEE_FLOAT) + +struct cray_single { + unsigned int sign : 1; + unsigned int exp :15; + unsigned int mant :48; +}; +typedef struct cray_single cray_single; + +static const int cs_ieis_bias = 0x4000 - 0x7f; + +static const int cs_id_bias = 0x4000 - 0x3ff; + +#endif + +struct ieee_single_hi { + unsigned int sign : 1; + unsigned int exp : 8; + unsigned int mant :23; + unsigned int pad :32; +}; +typedef struct ieee_single_hi ieee_single_hi; + +struct ieee_single_lo { + unsigned int pad :32; + unsigned int sign : 1; + unsigned int exp : 8; + unsigned int mant :23; +}; +typedef struct ieee_single_lo ieee_single_lo; + +static const int ieee_single_bias = 0x7f; + + +struct ieee_double { + unsigned int sign : 1; + unsigned int exp :11; + unsigned int mant :52; +}; +typedef struct ieee_double ieee_double; + +static const int ieee_double_bias = 0x3ff; + +#if FLOAT_USE_IEG + +static void +get_ix_float(const void *xp, float *ip) +{ + const int bo = bitoff(xp); + (void) IEG2CRAY(&Cray2_F32, &One, (word *)xp, &bo, ip, &UnitStride); +} + +static int +put_ix_float(void *xp, const float *ip) +{ + const int bo = bitoff(xp); + int status = CRAY2IEG(&Cray2_F32, &One, (word *)xp, &bo, ip, &UnitStride); + if(status != 0) + status = NC_ERANGE; + /* else, status == 0 == ENOERR */ + return status; +} + +#else + /* !FLOAT_USE_IEG */ + +#if defined(NO_IEEE_FLOAT) + +static void +cget_float_float(const void *xp, float *ip, int which) +{ + + if(which == 0) + { + const ieee_single_hi *isp = (const ieee_single_hi *) xp; + cray_single *csp = (cray_single *) ip; + + if(isp->exp == 0) + { + /* ieee subnormal */ + *ip = (double)isp->mant; + if(isp->mant != 0) + { + csp->exp -= (ieee_single_bias + 22); + } + } + else + { + csp->exp = isp->exp + cs_ieis_bias + 1; + csp->mant = isp->mant << (48 - 1 - 23); + csp->mant |= (1 << (48 - 1)); + } + csp->sign = isp->sign; + + + } + else + { + const ieee_single_lo *isp = (const ieee_single_lo *) xp; + cray_single *csp = (cray_single *) ip; + + if(isp->exp == 0) + { + /* ieee subnormal */ + *ip = (double)isp->mant; + if(isp->mant != 0) + { + csp->exp -= (ieee_single_bias + 22); + } + } + else + { + csp->exp = isp->exp + cs_ieis_bias + 1; + csp->mant = isp->mant << (48 - 1 - 23); + csp->mant |= (1 << (48 - 1)); + } + csp->sign = isp->sign; + + + } +} + +static int +cput_float_float(void *xp, const float *ip, int which) +{ + int status = ENOERR; + if(which == 0) + { + ieee_single_hi *isp = (ieee_single_hi*)xp; + const cray_single *csp = (const cray_single *) ip; + int ieee_exp = csp->exp - cs_ieis_bias -1; + + isp->sign = csp->sign; + + if(ieee_exp >= 0xff + || *ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + { + /* NC_ERANGE => ieee Inf */ + isp->exp = 0xff; + isp->mant = 0x0; + return NC_ERANGE; + } + /* else */ + + if(ieee_exp > 0) + { + /* normal ieee representation */ + isp->exp = ieee_exp; + /* assumes cray rep is in normal form */ + /* assert(csp->mant & 0x800000000000); */ + isp->mant = (((csp->mant << 1) & + 0xffffffffffff) >> (48 - 23)); + } + else if(ieee_exp > -23) + { + /* ieee subnormal, right */ + const int rshift = (48 - 23 - ieee_exp); + + isp->mant = csp->mant >> rshift; + isp->exp = 0; + } + else + { + /* smaller than ieee can represent */ + isp->exp = 0; + isp->mant = 0; + } + + } + else + { + ieee_single_lo *isp = (ieee_single_lo*)xp; + const cray_single *csp = (const cray_single *) ip; + int ieee_exp = csp->exp - cs_ieis_bias -1; + + isp->sign = csp->sign; + + if(ieee_exp >= 0xff + || *ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + { + /* NC_ERANGE => ieee Inf */ + isp->exp = 0xff; + isp->mant = 0x0; + return NC_ERANGE; + } + /* else */ + + if(ieee_exp > 0) + { + /* normal ieee representation */ + isp->exp = ieee_exp; + /* assumes cray rep is in normal form */ + /* assert(csp->mant & 0x800000000000); */ + isp->mant = (((csp->mant << 1) & + 0xffffffffffff) >> (48 - 23)); + } + else if(ieee_exp > -23) + { + /* ieee subnormal, right */ + const int rshift = (48 - 23 - ieee_exp); + + isp->mant = csp->mant >> rshift; + isp->exp = 0; + } + else + { + /* smaller than ieee can represent */ + isp->exp = 0; + isp->mant = 0; + } + + } + return ENOERR; +} + +#define get_ix_float(xp, ip) cget_float_float((xp), (ip), byteoff(xp)) +#define put_ix_float(xp, ip) cput_float_float((xp), (ip), byteoff(xp)) + +#else + /* IEEE Cray with only doubles */ +static void +cget_float_float(const void *xp, float *ip, int which) +{ + + ieee_double *idp = (ieee_double *) ip; + + if(which == 0) + { + const ieee_single_hi *isp = (const ieee_single_hi *) xp; + if(isp->exp == 0 && isp->mant == 0) + { + idp->exp = 0; + idp->mant = 0; + } + else + { + idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias); + idp->mant = isp->mant << (52 - 23); + } + idp->sign = isp->sign; + } + else + { + const ieee_single_lo *isp = (const ieee_single_lo *) xp; + if(isp->exp == 0 && isp->mant == 0) + { + idp->exp = 0; + idp->mant = 0; + } + else + { + idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias); + idp->mant = isp->mant << (52 - 23); + } + idp->sign = isp->sign; + } +} + +static int +cput_float_float(void *xp, const float *ip, int which) +{ + const ieee_double *idp = (const ieee_double *) ip; + if(which == 0) + { + ieee_single_hi *isp = (ieee_single_hi*)xp; + if(idp->exp > (ieee_double_bias - ieee_single_bias)) + isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias); + else + isp->exp = 0; + isp->mant = idp->mant >> (52 - 23); + isp->sign = idp->sign; + } + else + { + ieee_single_lo *isp = (ieee_single_lo*)xp; + if(idp->exp > (ieee_double_bias - ieee_single_bias)) + isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias); + else + isp->exp = 0; + isp->mant = idp->mant >> (52 - 23); + isp->sign = idp->sign; + } + if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + return NC_ERANGE; + return ENOERR; +} + +#define get_ix_float(xp, ip) cget_float_float((xp), (ip), byteoff(xp)) +#define put_ix_float(xp, ip) cput_float_float((xp), (ip), byteoff(xp)) + +#endif /* NO_IEEE_FLOAT */ + +#endif /* FLOAT_USE_IEG */ + + +int +ncx_get_float_schar(const void *xp, schar *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (schar) xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_uchar(const void *xp, uchar *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (uchar) xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_short(const void *xp, short *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (short) xx; + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_int(const void *xp, int *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (int) xx; + if(xx > (double)INT_MAX || xx < (double)INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_long(const void *xp, long *ip) +{ + float xx; + get_ix_float(xp, &xx); + *ip = (long) xx; + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_float_float(const void *xp, float *ip) +{ + get_ix_float(xp, ip); + return ENOERR; +} + +int +ncx_get_float_double(const void *xp, double *ip) +{ +#if SIZEOF_FLOAT == SIZEOF_DOUBLE && FLT_MANT_DIG == DBL_MANT_DIG + return ncx_get_float_float(xp, (float *)ip); +#else + float xx; + get_ix_float(xp, &xx); + *ip = xx; + return ENOERR; +#endif +} + + +int +ncx_put_float_schar(void *xp, const schar *ip) +{ + float xx = (float) *ip; + return put_ix_float(xp, &xx); +} + +int +ncx_put_float_uchar(void *xp, const uchar *ip) +{ + float xx = (float) *ip; + return put_ix_float(xp, &xx); +} + +int +ncx_put_float_short(void *xp, const short *ip) +{ + float xx = (float) *ip; + return put_ix_float(xp, &xx); +} + +int +ncx_put_float_int(void *xp, const int *ip) +{ + float xx = (float) *ip; + return put_ix_float(xp, &xx); +} + +int +ncx_put_float_long(void *xp, const long *ip) +{ + float xx = (float) *ip; + return put_ix_float(xp, &xx); +} + +int +ncx_put_float_float(void *xp, const float *ip) +{ + return put_ix_float(xp, ip); +} + +int +ncx_put_float_double(void *xp, const double *ip) +{ +#if SIZEOF_FLOAT == SIZEOF_DOUBLE && FLT_MANT_DIG == DBL_MANT_DIG + return put_ix_float(xp, (float *)ip); +#else + float xx = (float) *ip; + int status = put_ix_float(xp, &xx); + if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN) + return NC_ERANGE; + return status; +#endif +} + +/* x_double */ + + +#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) + +static void +get_ix_double(const void *xp, double *ip) +{ + (void) memcpy(ip, xp, sizeof(double)); +} + +static int +put_ix_double(void *xp, const double *ip) +{ + (void) memcpy(xp, ip, X_SIZEOF_DOUBLE); + return ENOERR; +} + +#else + +static void +cget_double_double(const void *xp, double *ip) +{ + const ieee_double *idp = (const ieee_double *) xp; + cray_single *csp = (cray_single *) ip; + + if(idp->exp == 0) + { + /* ieee subnormal */ + *ip = (double)idp->mant; + if(idp->mant != 0) + { + csp->exp -= (ieee_double_bias + 51); + } + } + else + { + csp->exp = idp->exp + cs_id_bias + 1; + csp->mant = idp->mant >> (52 - 48 + 1); + csp->mant |= (1 << (48 - 1)); + } + csp->sign = idp->sign; +} + +static int +cput_double_double(void *xp, const double *ip) +{ + ieee_double *idp = (ieee_double *) xp; + const cray_single *csp = (const cray_single *) ip; + + int ieee_exp = csp->exp - cs_id_bias -1; + + idp->sign = csp->sign; + + if(ieee_exp >= 0x7ff) + { + /* NC_ERANGE => ieee Inf */ + idp->exp = 0x7ff; + idp->mant = 0x0; + return NC_ERANGE; + } + /* else */ + + if(ieee_exp > 0) + { + /* normal ieee representation */ + idp->exp = ieee_exp; + /* assumes cray rep is in normal form */ + assert(csp->mant & 0x800000000000); + idp->mant = (((csp->mant << 1) & + 0xffffffffffff) << (52 - 48)); + } + else if(ieee_exp >= (-(52 -48))) + { + /* ieee subnormal, left */ + const int lshift = (52 - 48) + ieee_exp; + idp->mant = csp->mant << lshift; + idp->exp = 0; + } + else if(ieee_exp >= -52) + { + /* ieee subnormal, right */ + const int rshift = (- (52 - 48) - ieee_exp); + + idp->mant = csp->mant >> rshift; + idp->exp = 0; + } + else + { + /* smaller than ieee can represent */ + idp->exp = 0; + idp->mant = 0; + } + return ENOERR; +} + +#define get_ix_double(xp, ip) cget_double_double((xp), (ip)) +#define put_ix_double(xp, ip) cput_double_double((xp), (ip)) + +#endif /* NO_IEEE_FLOAT */ + +int +ncx_get_double_schar(const void *xp, schar *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (schar) xx; + if(xx > SCHAR_MAX || xx < SCHAR_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_uchar(const void *xp, uchar *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (uchar) xx; + if(xx > UCHAR_MAX || xx < 0) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_short(const void *xp, short *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (short) xx; + if(xx > SHORT_MAX || xx < SHORT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_int(const void *xp, int *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (int) xx; + if(xx > INT_MAX || xx < INT_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_long(const void *xp, long *ip) +{ + double xx; + get_ix_double(xp, &xx); + *ip = (long) xx; + if(xx > LONG_MAX || xx < LONG_MIN) + return NC_ERANGE; + return ENOERR; +} + +int +ncx_get_double_float(const void *xp, float *ip) +{ +#if SIZEOF_FLOAT == SIZEOF_DOUBLE && FLT_MANT_DIG == DBL_MANT_DIG + get_ix_double(xp, (double *)ip); + return ENOERR; +#else + double xx; + get_ix_double(xp, &xx); + if(xx > FLT_MAX || xx < (-FLT_MAX)) + { + *ip = FLT_MAX; + return NC_ERANGE; + } + if(xx < (-FLT_MAX)) + { + *ip = (-FLT_MAX); + return NC_ERANGE; + } + *ip = (float) xx; + return ENOERR; +#endif +} + +int +ncx_get_double_double(const void *xp, double *ip) +{ + get_ix_double(xp, ip); + return ENOERR; +} + + +int +ncx_put_double_schar(void *xp, const schar *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncx_put_double_uchar(void *xp, const uchar *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncx_put_double_short(void *xp, const short *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncx_put_double_int(void *xp, const int *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + return ENOERR; +} + +int +ncx_put_double_long(void *xp, const long *ip) +{ + double xx = (double) *ip; + put_ix_double(xp, &xx); + /* TODO: Deal with big guys */ + return ENOERR; +} + +int +ncx_put_double_float(void *xp, const float *ip) +{ +#if SIZEOF_FLOAT == SIZEOF_DOUBLE && FLT_MANT_DIG == DBL_MANT_DIG + put_ix_double(xp, (double *)ip); + return ENOERR; +#else + double xx = (double) *ip; + return put_ix_double(xp, &xx); +#endif +} + +int +ncx_put_double_double(void *xp, const double *ip) +{ +#if !defined(NO_IEEE_FLOAT) + put_ix_double(xp, ip); + return ENOERR; +#else + return put_ix_double(xp, ip); +#endif +} + + +/* x_size_t */ + +int +ncx_put_size_t(void **xpp, const size_t *ulp) +{ + /* similar to put_ix_int() */ + uchar *cp = *xpp; + /* sizes limited to 2^31 -1 in netcdf */ + assert(*ulp <= X_SIZE_MAX && (long) (*ulp) >= 0); + + *cp++ = (uchar)((*ulp) >> 24); + *cp++ = (uchar)(((*ulp) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*ulp) & 0x0000ff00) >> 8); + *cp = (uchar)((*ulp) & 0x000000ff); + + *xpp = (void *)((char *)(*xpp) + X_SIZEOF_SIZE_T); + return ENOERR; +} + +int +ncx_get_size_t(const void **xpp, size_t *ulp) +{ + /* similar to get_ix_int */ + const uchar *cp = *xpp; + assert((*cp & 0x80) == 0); /* sizes limited to 2^31 -1 in netcdf */ + + *ulp = *cp++ << 24; + *ulp |= (*cp++ << 16); + *ulp |= (*cp++ << 8); + *ulp |= *cp; + + *xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_SIZE_T); + return ENOERR; +} + +/* x_off_t */ + +int +ncx_put_off_t(void **xpp, const off_t *lp) +{ + /* similar to put_ix_int() */ + uchar *cp = *xpp; + /* No negative offsets stored in netcdf */ + assert(*lp >= 0 && *lp <= X_OFF_MAX); + + *cp++ = (uchar)((*lp) >> 24); + *cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16); + *cp++ = (uchar)(((*lp) & 0x0000ff00) >> 8); + *cp = (uchar)((*lp) & 0x000000ff); + + *xpp = (void *)((char *)(*xpp) + X_SIZEOF_OFF_T); + return ENOERR; +} + +int +ncx_get_off_t(const void **xpp, off_t *lp) +{ + /* similar to get_ix_int() */ + const uchar *cp = *xpp; + assert((*cp & 0x80) == 0); /* No negative offsets stored in netcdf */ + + *lp = *cp++ << 24; + *lp |= (*cp++ << 16); + *lp |= (*cp++ << 8); + *lp |= *cp; + + *xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_OFF_T); + return ENOERR; +} + + +/* + * Aggregate numeric conversion functions. + */ + + + +/* schar */ + +int +ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} +int +ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} +int +ncx_getn_schar_short(const void **xpp, size_t nelems, short *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_int(const void **xpp, size_t nelems, int *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_long(const void **xpp, size_t nelems, long *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_float(const void **xpp, size_t nelems, float *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + +int +ncx_getn_schar_double(const void **xpp, size_t nelems, double *tp) +{ + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (const void *)xp; + return ENOERR; +} + + +int +ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} +int +ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} +int +ncx_pad_getn_schar_short(const void **xpp, size_t nelems, short *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_int(const void **xpp, size_t nelems, int *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_long(const void **xpp, size_t nelems, long *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_float(const void **xpp, size_t nelems, float *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + +int +ncx_pad_getn_schar_double(const void **xpp, size_t nelems, double *tp) +{ + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + *tp++ = *xp++; + } + + *xpp = (void *)(xp + rndup); + return ENOERR; +} + + +int +ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} +int +ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} +int +ncx_putn_schar_short(void **xpp, size_t nelems, const short *tp) +{ + int status = ENOERR; + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_int(void **xpp, size_t nelems, const int *tp) +{ + int status = ENOERR; + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_long(void **xpp, size_t nelems, const long *tp) +{ + int status = ENOERR; + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_float(void **xpp, size_t nelems, const float *tp) +{ + int status = ENOERR; + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_schar_double(void **xpp, size_t nelems, const double *tp) +{ + int status = ENOERR; + schar *xp = (schar *)(*xpp); + + while(nelems-- != 0) + { + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + *xpp = (void *)xp; + return status; +} + + +int +ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} +int +ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} +int +ncx_pad_putn_schar_short(void **xpp, size_t nelems, const short *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_int(void **xpp, size_t nelems, const int *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_long(void **xpp, size_t nelems, const long *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_float(void **xpp, size_t nelems, const float *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *tp) +{ + int status = ENOERR; + size_t rndup = nelems % X_ALIGN; + schar *xp = (schar *)(*xpp); + + if(rndup) + rndup = X_ALIGN - rndup; + + while(nelems-- != 0) + { + /* N.B. schar as signed */ + if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN) + status = NC_ERANGE; + *xp++ = (schar) *tp++; + } + + + if(rndup) + { + (void) memcpy(xp, nada, rndup); + xp += rndup; + } + + *xpp = (void *)xp; + return status; +} + + + +/* short */ + +int +ncx_getn_short_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if SHORT_USE_IEG +int +ncx_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ + if(nelems > 0) + { + const int bo = bitoff(*xpp); + const word *wp = *xpp; + int ierr; + *xpp = ((const char *) (*xpp) + nelems * X_SIZEOF_SHORT); + ierr = IEG2CRAY(&Cray2_I16, &nelems, wp, + &bo, tp, &UnitStride); + assert(ierr >= 0); + if(ierr > 0) + return NC_ERANGE; + } + return ENOERR; +} +#else +int +ncx_getn_short_short(const void **xpp, const size_t nelems, short *tp) +{ + if(nelems > 0) + { + const word *wp = *xpp; + const short *const last = &tp[nelems -1]; + const int rem = word_align(*xpp)/X_SIZEOF_SHORT; + *xpp = ((const char *) (*xpp) + nelems * X_SIZEOF_SHORT); + + switch(rem) { + case 3: + *tp = (short)((*wp >> 32) & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + if(tp == last) + return ENOERR; + tp++; + /*FALLTHRU*/ + case 2: + *tp = (short)((*wp >> 16) & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + if(tp == last) + return ENOERR; + tp++; + /*FALLTHRU*/ + case 1: + *tp = (short)(*wp & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + if(tp == last) + return ENOERR; + tp++; + wp++; /* Note Bene */ + /*FALLTHRU*/ + } + + assert((nelems - rem) != 0); + { + const int nwords = ((nelems - rem) * X_SIZEOF_SHORT) + / sizeof(word); + const word *const endw = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < endw; wp++) + { + + *tp = (short)(*wp >> 48); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + tp++; + + *tp = (short)((*wp >> 32) & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + tp++; + + *tp = (short)((*wp >> 16) & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + tp++; + + *tp = (short)(*wp & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + tp++; + } + } + + if(tp <= last) + { + *tp = (short)(*wp >> 48); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + tp++; + } + if(tp <= last) + { + *tp = (short)((*wp >> 32) & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + tp++; + } + if(tp <= last) + { + *tp = (short)((*wp >> 16) & 0xffff); + if(*tp & 0x8000) + *tp |= (~(0xffff)); + tp++; + } + + } + return ENOERR; +} +#endif + +int +ncx_getn_short_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_short_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncx_pad_getn_short_schar(const void **xpp, size_t nelems, schar *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_short(const void **xpp, size_t nelems, short *tp) +{ + const size_t rndup = nelems % 2; + + const int status = ncx_getn_short_short(xpp, nelems, tp); + + if(rndup != 0) + { + *xpp = ((char *) (*xpp) + X_SIZEOF_SHORT); + } + + return status; +} + +int +ncx_pad_getn_short_int(const void **xpp, size_t nelems, int *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_long(const void **xpp, size_t nelems, long *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_float(const void **xpp, size_t nelems, float *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_getn_short_double(const void **xpp, size_t nelems, double *tp) +{ + const size_t rndup = nelems % 2; + + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_get_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + xp += X_SIZEOF_SHORT; + + *xpp = (void *)xp; + return status; +} + + +int +ncx_putn_short_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if SHORT_USE_IEG +int +ncx_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ + if(nelems > 0) + { + word *wp = *xpp; + const int bo = bitoff(*xpp); + int ierr; + + *xpp = ((char *) (*xpp) + nelems * X_SIZEOF_SHORT); + + ierr = CRAY2IEG(&Cray2_I16, &nelems, wp, + &bo, tp, &UnitStride); + assert(ierr >= 0); + if(ierr > 0) + return NC_ERANGE; + } + return ENOERR; +} +#else +int +ncx_putn_short_short(void **xpp, const size_t nelems, const short *tp) +{ + int status = ENOERR; + if(nelems == 0) + return status; +{ + word *wp = *xpp; + const short *const last = &tp[nelems -1]; + const int rem = word_align(*xpp)/X_SIZEOF_SHORT; + *xpp = ((char *) (*xpp) + nelems * X_SIZEOF_SHORT); + + switch(rem) { + case 3: + *wp = ((*tp << 32) & 0x0000ffff00000000) + | (*wp & 0xffff0000ffffffff); + if(*tp > X_SHORT_MAX || *tp < X_SHORT_MIN) + status = NC_ERANGE; + if(tp == last) + return status; + tp++; + /*FALLTHRU*/ + case 2: + *wp = ((*tp << 16) & 0x00000000ffff0000) + | (*wp & 0xffffffff0000ffff); + if(*tp > X_SHORT_MAX || *tp < X_SHORT_MIN) + status = NC_ERANGE; + if(tp == last) + return status; + tp++; + /*FALLTHRU*/ + case 1: + *wp = (*tp & 0x000000000000ffff) + | (*wp & 0xffffffffffff0000); + if(*tp > X_SHORT_MAX || *tp < X_SHORT_MIN) + status = NC_ERANGE; + if(tp == last) + return status; + tp++; + wp++; /* Note Bene */ + /*FALLTHRU*/ + } + + assert((nelems - rem) != 0); + { + const int nwords = ((nelems - rem) * X_SIZEOF_SHORT) + / sizeof(word); + const word *const endw = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < endw; wp++) + { + *wp = (*tp << 48) + | ((*(tp +1) << 32) & 0x0000ffff00000000) + | ((*(tp +2) << 16) & 0x00000000ffff0000) + | ((*(tp +3) ) & 0x000000000000ffff); + + { int ii = 0; + for(; ii < 4; ii++, tp++) + if(*tp > X_SHORT_MAX || *tp < X_SHORT_MIN) + status = NC_ERANGE; + } + } + } + + if(tp <= last) + { + *wp = (*tp << 48) + | (*wp & 0x0000ffffffffffff); + if(*tp > X_SHORT_MAX || *tp < X_SHORT_MIN) + status = NC_ERANGE; + tp++; + } + if(tp <= last) + { + *wp = ((*tp << 32) & 0x0000ffff00000000) + | (*wp & 0xffff0000ffffffff); + if(*tp > X_SHORT_MAX || *tp < X_SHORT_MIN) + status = NC_ERANGE; + tp++; + } + if(tp <= last) + { + *wp = ((*tp << 16) & 0x00000000ffff0000) + | (*wp & 0xffffffff0000ffff); + if(*tp > X_SHORT_MAX || *tp < X_SHORT_MIN) + status = NC_ERANGE; + } + + return status; +} +} +#endif + +int +ncx_putn_short_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_short_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + +int +ncx_pad_putn_short_schar(void **xpp, size_t nelems, const schar *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_short(void **xpp, size_t nelems, const short *tp) +{ + const size_t rndup = nelems % 2; + + const int status = ncx_putn_short_short(xpp, nelems, tp); + + if(rndup != 0) + { + *xpp = ((char *) (*xpp) + X_SIZEOF_SHORT); + } + + return status; +} + +int +ncx_pad_putn_short_int(void **xpp, size_t nelems, const int *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_long(void **xpp, size_t nelems, const long *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_float(void **xpp, size_t nelems, const float *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *tp) +{ + const size_t rndup = nelems % 2; + + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++) + { + const int lstatus = ncx_put_short_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + if(rndup != 0) + { + (void) memcpy(xp, nada, X_SIZEOF_SHORT); + xp += X_SIZEOF_SHORT; + } + + *xpp = (void *)xp; + return status; +} + + + +/* int */ + +int +ncx_getn_int_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_int_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_int_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if INT_USE_IEG +int +ncx_getn_int_int(const void **xpp, size_t nelems, int *tp) +{ + if(nelems > 0) + { + const int bo = bitoff(*xpp); + const word *wp = *xpp; + int ierr; + *xpp = ((const char *) (*xpp) + nelems * X_SIZEOF_INT); + ierr = IEG2CRAY(&Cray2_I32, &nelems, wp, + &bo, tp, &UnitStride); + assert(ierr >= 0); + if(ierr > 0) + return NC_ERANGE; + } + return ENOERR; +} +#else +int +ncx_getn_int_int(const void **xpp, size_t nelems, int *tp) +{ + const int bo = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(bo != 0) + { + cget_int_int(*xpp, tp, bo); + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + nelems--; + if(nelems == 0) + return ENOERR; + tp++; + } + + assert(byteoff(*xpp) == 0); + + { + const int nwords = (nelems * X_SIZEOF_INT)/sizeof(word); + const word *wp = *xpp; + const word *const end = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp += 2) + { + cget_int_int(wp, tp, 0); + cget_int_int(wp, tp + 1, 1); + } + + *xpp = ((char *) (*xpp) + nwords * sizeof(word)); + nelems -= (nwords * sizeof(word)/X_SIZEOF_INT); + if(nelems != 0) + { + cget_int_int(wp, tp, 0); + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + } + } + + return ENOERR; +} +#endif + +int +ncx_getn_int_long(const void **xpp, size_t nelems, long *tp) +{ + const int bo = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(bo != 0) + { + cget_int_long(*xpp, tp, bo); + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + nelems--; + if(nelems == 0) + return ENOERR; + tp++; + } + + assert(byteoff(*xpp) == 0); + + { + const int nwords = (nelems * X_SIZEOF_INT)/sizeof(word); + const word *wp = *xpp; + const word *const end = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp += 2) + { + cget_int_long(wp, tp, 0); + cget_int_long(wp, tp + 1, 1); + } + + *xpp = ((char *) (*xpp) + nwords * sizeof(word)); + nelems -= (nwords * sizeof(word)/X_SIZEOF_INT); + if(nelems != 0) + { + cget_int_long(wp, tp, 0); + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + } + } + + return ENOERR; +} + +int +ncx_getn_int_float(const void **xpp, size_t nelems, float *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_int_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_get_int_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncx_putn_int_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_put_int_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_int_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_put_int_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_int_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_put_int_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if INT_USE_IEG +int +ncx_putn_int_int(void **xpp, size_t nelems, const int *tp) +{ + if(nelems > 0) + { + word *wp = *xpp; + const int bo = bitoff(*xpp); + int ierr; + + *xpp = ((char *) (*xpp) + nelems * X_SIZEOF_INT); + + ierr = CRAY2IEG(&Cray2_I32, &nelems, wp, + &bo, tp, &UnitStride); + assert(ierr >= 0); + if(ierr > 0) + return NC_ERANGE; + } + return ENOERR; +} +#else +int +ncx_putn_int_int(void **xpp, size_t nelems, const int *tp) +{ + int status = ENOERR; + const int bo = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(bo != 0) + { + status = cput_int_int(*xpp, tp, bo); + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + nelems--; + if(nelems == 0) + return status; + tp++; + } + + assert(byteoff(*xpp) == 0); + + { + const int nwords = (nelems * X_SIZEOF_INT)/sizeof(word); + word *wp = *xpp; + const word *const end = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp += 2) + { + int lstatus = cput_int_int(wp, tp, 0); + if(lstatus != ENOERR) + status = lstatus; + lstatus = cput_int_int(wp, tp + 1, 1); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = ((char *) (*xpp) + nwords * sizeof(word)); + nelems -= (nwords * sizeof(word)/X_SIZEOF_INT); + if(nelems != 0) + { + const int lstatus = cput_int_int(wp, tp, 0); + if(lstatus != ENOERR) + status = lstatus; + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + } + } + + return status; +} +#endif + +int +ncx_putn_int_long(void **xpp, size_t nelems, const long *tp) +{ + int status = ENOERR; + const int bo = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(bo != 0) + { + status = cput_int_long(*xpp, tp, bo); + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + nelems--; + if(nelems == 0) + return status; + tp++; + } + + assert(byteoff(*xpp) == 0); + + { + const int nwords = (nelems * X_SIZEOF_INT)/sizeof(word); + word *wp = *xpp; + const word *const end = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp += 2) + { + int lstatus = cput_int_long(wp, tp, 0); + if(lstatus != ENOERR) + status = lstatus; + lstatus = cput_int_long(wp, tp + 1, 1); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = ((char *) (*xpp) + nwords * sizeof(word)); + nelems -= (nwords * sizeof(word)/X_SIZEOF_INT); + if(nelems != 0) + { + const int lstatus = cput_int_long(wp, tp, 0); + if(lstatus != ENOERR) + status = lstatus; + *xpp = ((char *) (*xpp) + X_SIZEOF_INT); + } + } + + return status; +} + +int +ncx_putn_int_float(void **xpp, size_t nelems, const float *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_put_int_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_int_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++) + { + const int lstatus = ncx_put_int_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + + +/* float */ + +int +ncx_getn_float_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_float_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if FLOAT_USE_IEG +int +ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) +{ + if(nelems > 0) + { + const int bo = bitoff(*xpp); + const word *wp = *xpp; + int ierr; + *xpp = ((const char *) (*xpp) + nelems * X_SIZEOF_FLOAT); + ierr = IEG2CRAY(&Cray2_F32, &nelems, wp, + &bo, tp, &UnitStride); + assert(ierr >= 0); + if(ierr > 0) + return NC_ERANGE; + } + return ENOERR; + +} +#else +int +ncx_getn_float_float(const void **xpp, size_t nelems, float *tp) +{ + const int bo = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(bo != 0) + { + cget_float_float(*xpp, tp, bo); + *xpp = ((char *) (*xpp) + X_SIZEOF_FLOAT); + nelems--; + if(nelems == 0) + return ENOERR; + tp++; + } + + assert(byteoff(*xpp) == 0); + + { + const int nwords = (nelems * X_SIZEOF_FLOAT)/sizeof(word); + const word *wp = *xpp; + const word *const end = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp += 2) + { + cget_float_float(wp, tp, 0); + cget_float_float(wp, tp + 1, 1); + } + + *xpp = ((char *) (*xpp) + nwords * sizeof(word)); + nelems -= (nwords * sizeof(word)/X_SIZEOF_FLOAT); + if(nelems != 0) + { + cget_float_float(wp, tp, 0); + *xpp = ((char *) (*xpp) + X_SIZEOF_FLOAT); + } + } + + return ENOERR; +} +#endif + +int +ncx_getn_float_double(const void **xpp, size_t nelems, double *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_get_float_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + + +int +ncx_putn_float_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_put_float_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_put_float_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_put_float_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_put_float_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_float_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_put_float_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if FLOAT_USE_IEG +int +ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) +{ + if(nelems > 0) + { + word *wp = *xpp; + const int bo = bitoff(*xpp); + int ierr; + + *xpp = ((char *) (*xpp) + nelems * X_SIZEOF_FLOAT); + + ierr = CRAY2IEG(&Cray2_F32, &nelems, wp, + &bo, tp, &UnitStride); + assert(ierr >= 0); + if(ierr > 0) + return NC_ERANGE; + } + return ENOERR; +} +#else +int +ncx_putn_float_float(void **xpp, size_t nelems, const float *tp) +{ + int status = ENOERR; + const int bo = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(bo != 0) + { + status = cput_float_float(*xpp, tp, bo); + *xpp = ((char *) (*xpp) + X_SIZEOF_FLOAT); + nelems--; + if(nelems == 0) + return status; + tp++; + } + + assert(byteoff(*xpp) == 0); + + { + const int nwords = (nelems * X_SIZEOF_FLOAT)/sizeof(word); + word *wp = *xpp; + const word *const end = &wp[nwords]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp += 2) + { + int lstatus = cput_float_float(wp, tp, 0); + if(lstatus != ENOERR) + status = lstatus; + lstatus = cput_float_float(wp, tp + 1, 1); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = ((char *) (*xpp) + nwords * sizeof(word)); + nelems -= (nwords * sizeof(word)/X_SIZEOF_FLOAT); + if(nelems != 0) + { + const int lstatus = cput_float_float(wp, tp, 0); + if(lstatus != ENOERR) + status = lstatus; + *xpp = ((char *) (*xpp) + X_SIZEOF_FLOAT); + } + } + + return status; +} +#endif + +int +ncx_putn_float_double(void **xpp, size_t nelems, const double *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++) + { + const int lstatus = ncx_put_float_double(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + + + +/* double */ + +int +ncx_getn_double_schar(const void **xpp, size_t nelems, schar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_uchar(const void **xpp, size_t nelems, uchar *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_short(const void **xpp, size_t nelems, short *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_int(const void **xpp, size_t nelems, int *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +int +ncx_getn_double_long(const void **xpp, size_t nelems, long *tp) +{ + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +} + +#if DOUBLE_USE_IEG +int +ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ + const size_t noff = byteoff(*xpp); + int ierr; + + if(nelems == 0) + return ENOERR; + + if(noff != 0) + { + /* (*xpp) not word aligned, forced to make a copy */ + word xbuf[nelems]; + (void) memcpy(xbuf, *xpp, nelems * X_SIZEOF_DOUBLE); + ierr = IEG2CRAY(&Cray2_F64, &nelems, xbuf, + &Zero, tp, &UnitStride); + } + else + { + ierr = IEG2CRAY(&Cray2_F64, &nelems, *xpp, + &Zero, tp, &UnitStride); + } + + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + + assert(ierr >= 0); + + return ierr > 0 ? NC_ERANGE : ENOERR; +} +#elif X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) +int +ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ + (void) memcpy(tp, *xpp, nelems * X_SIZEOF_DOUBLE); + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return ENOERR; +} +#else +int +ncx_getn_double_double(const void **xpp, size_t nelems, double *tp) +{ + const size_t noff = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(noff != 0) + { + /* (*xpp) not word aligned, forced to make a copy */ + word xbuf[nelems]; + const word *wp = xbuf; + const word *const end = &wp[nelems]; + + (void) memcpy(xbuf, *xpp, nelems * X_SIZEOF_DOUBLE); + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp++) + { + cget_double_double(wp, tp); + } + + } + else + { + const word *wp = *xpp; + const word *const end = &wp[nelems]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp++) + { + cget_double_double(wp, tp); + } + + } + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return ENOERR; +} +#endif + +int +ncx_getn_double_float(const void **xpp, size_t nelems, float *tp) +{ +#if SIZEOF_FLOAT == SIZEOF_DOUBLE && FLT_MANT_DIG == DBL_MANT_DIG + return ncx_getn_double_double(xpp, nelems, (double *)tp); +#else + const char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_get_double_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (const void *)xp; + return status; +#endif +} + + +int +ncx_putn_double_schar(void **xpp, size_t nelems, const schar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_put_double_schar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_uchar(void **xpp, size_t nelems, const uchar *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_put_double_uchar(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_short(void **xpp, size_t nelems, const short *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_put_double_short(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_int(void **xpp, size_t nelems, const int *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_put_double_int(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +int +ncx_putn_double_long(void **xpp, size_t nelems, const long *tp) +{ + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_put_double_long(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +} + +#if DOUBLE_USE_IEG +int +ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ + const size_t noff = byteoff(*xpp); + int ierr; + + if(nelems == 0) + return ENOERR; + + if(noff != 0) + { + /* (*xpp) not word aligned, forced to make a copy */ + word xbuf[nelems]; + ierr = CRAY2IEG(&Cray2_F64, &nelems, xbuf, + &Zero, tp, &UnitStride); + assert(ierr >= 0); + (void) memcpy(*xpp, xbuf, nelems * X_SIZEOF_DOUBLE); + } + else + { + ierr = CRAY2IEG(&Cray2_F64, &nelems, *xpp, + &Zero, tp, &UnitStride); + assert(ierr >= 0); + } + + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + + return ierr > 0 ? NC_ERANGE : ENOERR; +} +#elif X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT) +int +ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ + const size_t noff = byteoff(*xpp); + (void) memcpy(*xpp, tp, nelems * X_SIZEOF_DOUBLE); + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return ENOERR; +} +#else +int +ncx_putn_double_double(void **xpp, size_t nelems, const double *tp) +{ + int status = ENOERR; + const size_t noff = byteoff(*xpp); + + if(nelems == 0) + return ENOERR; + + if(noff != 0) + { + /* (*xpp) not word aligned, forced to make a copy */ + word xbuf[nelems]; + word *wp = xbuf; + const word *const end = &wp[nelems]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp++) + { + const int lstatus = cput_double_double(wp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + (void) memcpy(*xpp, xbuf, nelems * X_SIZEOF_DOUBLE); + } + else + { + word *wp = *xpp; + const word *const end = &wp[nelems]; + +#pragma _CRI ivdep + for( ; wp < end; wp++, tp++) + { + const int lstatus = cput_double_double(wp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + } + + *xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE); + return status; +} +#endif + +int +ncx_putn_double_float(void **xpp, size_t nelems, const float *tp) +{ +#if SIZEOF_FLOAT == SIZEOF_DOUBLE && FLT_MANT_DIG == DBL_MANT_DIG + return ncx_putn_double_double(xpp, nelems, (double *)tp); +#else + char *xp = *xpp; + int status = ENOERR; + + for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++) + { + const int lstatus = ncx_put_double_float(xp, tp); + if(lstatus != ENOERR) + status = lstatus; + } + + *xpp = (void *)xp; + return status; +#endif +} + + + +/* + * Other aggregate conversion functions. + */ + +/* text */ + +int +ncx_getn_text(const void **xpp, size_t nelems, char *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} + +int +ncx_pad_getn_text(const void **xpp, size_t nelems, char *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} + +int +ncx_putn_text(void **xpp, size_t nelems, const char *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} + +int +ncx_pad_putn_text(void **xpp, size_t nelems, const char *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} + + +/* opaque */ + +int +ncx_getn_void(const void **xpp, size_t nelems, void *tp) +{ + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + return ENOERR; + +} + +int +ncx_pad_getn_void(const void **xpp, size_t nelems, void *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(tp, *xpp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems + rndup); + + return ENOERR; + +} + +int +ncx_putn_void(void **xpp, size_t nelems, const void *tp) +{ + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + return ENOERR; + +} + +int +ncx_pad_putn_void(void **xpp, size_t nelems, const void *tp) +{ + size_t rndup = nelems % X_ALIGN; + + if(rndup) + rndup = X_ALIGN - rndup; + + (void) memcpy(*xpp, tp, nelems); + *xpp = (void *)((char *)(*xpp) + nelems); + + if(rndup) + { + (void) memcpy(*xpp, nada, rndup); + *xpp = (void *)((char *)(*xpp) + rndup); + } + + return ENOERR; + +} diff --git a/Utilities/vtknetcdf/netcdf.h b/Utilities/vtknetcdf/netcdf.h new file mode 100644 index 0000000..8d932af --- /dev/null +++ b/Utilities/vtknetcdf/netcdf.h @@ -0,0 +1,946 @@ +#include "vtk_netcdf_mangle.h" +/* + * Copyright 1993-1996 University Corporation for Atmospheric Research/Unidata + * + * Portions of this software were developed by the Unidata Program at the + * University Corporation for Atmospheric Research. + * + * Access and use of this software shall impose the following obligations + * and understandings on the user. The user is granted the right, without + * any fee or cost, to use, copy, modify, alter, enhance and distribute + * this software, and any derivative works thereof, and its supporting + * documentation for any purpose whatsoever, provided that this entire + * notice appears in all copies of the software, derivative works and + * supporting documentation. Further, UCAR requests that the user credit + * UCAR/Unidata in any publications that result from the use of this + * software or in any product that includes this software. The names UCAR + * and/or Unidata, however, may not be used in any advertising or publicity + * to endorse or promote any products or commercial entity unless specific + * written permission is obtained from UCAR/Unidata. The user also + * understands that UCAR/Unidata is not obligated to provide the user with + * any support, consulting, training or assistance of any kind with regard + * to the use, operation and performance of this software nor to provide + * the user with any updates, revisions, new versions or "bug fixes." + * + * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* "$Id: netcdf.h,v 1.2 2005/07/15 22:05:43 andy Exp $" */ + +#ifndef _NETCDF_ +#define _NETCDF_ + +#include <stddef.h> /* size_t, ptrdiff_t */ +#include <errno.h> /* netcdf functions sometimes return system errors */ + +#include "ncconfig.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * The netcdf external data types + */ +typedef enum { + NC_BYTE = 1, /* signed 1 byte integer */ + NC_CHAR = 2, /* ISO/ASCII character */ + NC_SHORT = 3, /* signed 2 byte integer */ + NC_INT = 4, /* signed 4 byte integer */ + NC_FLOAT = 5, /* single precision floating point number */ + NC_DOUBLE = 6 /* double precision floating point number */ +} nc_type; + + +/* + * Default fill values, used unless _FillValue attribute is set. + * These values are stuffed into newly allocated space as appropriate. + * The hope is that one might use these to notice that a particular datum + * has not been set. + */ +#define NC_FILL_BYTE ((signed char)-127) +#define NC_FILL_CHAR ((char)0) +#define NC_FILL_SHORT ((short)-32767) +#define NC_FILL_INT (-2147483647L) +#define NC_FILL_FLOAT (9.9692099683868690e+36f) /* near 15 * 2^119 */ +#define NC_FILL_DOUBLE (9.9692099683868690e+36) + + +/* + * The above values are defaults. + * If you wish a variable to use a different value than the above + * defaults, create an attribute with the same type as the variable + * and the following reserved name. The value you give the attribute + * will be used as the fill value for that variable. + */ +#define _FillValue "_FillValue" + + +/* + * 'mode' flags for nccreate and ncopen + */ +#define NC_NOWRITE 0 /* default is read only */ +#define NC_WRITE 0x1 /* read & write */ +#define NC_CLOBBER 0 +#define NC_NOCLOBBER 0x4 /* Don't destroy existing file on create */ +#define NC_FILL 0 /* argument to ncsetfill to clear NC_NOFILL */ +#define NC_NOFILL 0x100 /* Don't fill data section an records */ +#define NC_LOCK 0x0400 /* Use locking if available */ +#define NC_SHARE 0x0800 /* Share updates, limit cacheing */ +#define NC_64BIT_OFFSET 0x0200 /* Use large file offsets */ + +/* + * Let nc__create() or nc__open() figure out + * as suitable chunk size. + */ +#define NC_SIZEHINT_DEFAULT 0 + +/* + * In nc__enddef(), align to the chunk size. + */ +#define NC_ALIGN_CHUNK ((size_t)(-1)) + +/* + * 'size' argument to ncdimdef for an unlimited dimension + */ +#define NC_UNLIMITED 0L + +/* + * attribute id to put/get a global attribute + */ +#define NC_GLOBAL -1 + + +/* + * These maximums are enforced by the interface, to facilitate writing + * applications and utilities. However, nothing is statically allocated to + * these sizes internally. + */ +#define NC_MAX_DIMS 65536 /* max dimensions per file */ +#define NC_MAX_ATTRS 2000 /* max global or per variable attributes */ +#define NC_MAX_VARS 524288 /* max variables per file */ +#define NC_MAX_NAME 128 /* max length of a name */ +#define NC_MAX_VAR_DIMS 8 /* max per variable dimensions */ + + +/* + * The netcdf version 3 functions all return integer error status. + * These are the possible values, in addition to certain + * values from the system errno.h. + */ + +#define NC_ISSYSERR(err) ((err) > 0) + +#define NC_NOERR 0 /* No Error */ + +#define NC_EBADID (-33) /* Not a netcdf id */ +#define NC_ENFILE (-34) /* Too many netcdfs open */ +#define NC_EEXIST (-35) /* netcdf file exists && NC_NOCLOBBER */ +#define NC_EINVAL (-36) /* Invalid Argument */ +#define NC_EPERM (-37) /* Write to read only */ +#define NC_ENOTINDEFINE (-38) /* Operation not allowed in data mode */ +#define NC_EINDEFINE (-39) /* Operation not allowed in define mode */ +#define NC_EINVALCOORDS (-40) /* Index exceeds dimension bound */ +#define NC_EMAXDIMS (-41) /* NC_MAX_DIMS exceeded */ +#define NC_ENAMEINUSE (-42) /* String match to name in use */ +#define NC_ENOTATT (-43) /* Attribute not found */ +#define NC_EMAXATTS (-44) /* NC_MAX_ATTRS exceeded */ +#define NC_EBADTYPE (-45) /* Not a netcdf data type */ +#define NC_EBADDIM (-46) /* Invalid dimension id or name */ +#define NC_EUNLIMPOS (-47) /* NC_UNLIMITED in the wrong index */ +#define NC_EMAXVARS (-48) /* NC_MAX_VARS exceeded */ +#define NC_ENOTVAR (-49) /* Variable not found */ +#define NC_EGLOBAL (-50) /* Action prohibited on NC_GLOBAL varid */ +#define NC_ENOTNC (-51) /* Not a netcdf file */ +#define NC_ESTS (-52) /* In Fortran, string too short */ +#define NC_EMAXNAME (-53) /* NC_MAX_NAME exceeded */ +#define NC_EUNLIMIT (-54) /* NC_UNLIMITED size already in use */ +#define NC_ENORECVARS (-55) /* nc_rec op when there are no record vars */ +#define NC_ECHAR (-56) /* Attempt to convert between text & numbers */ +#define NC_EEDGE (-57) /* Edge+start exceeds dimension bound */ +#define NC_ESTRIDE (-58) /* Illegal stride */ +#define NC_EBADNAME (-59) /* Attribute or variable name + contains illegal characters */ +/* N.B. must match value in ncx.h */ +#define NC_ERANGE (-60) /* Math result not representable */ +#define NC_ENOMEM (-61) /* Memory allocation (malloc) failure */ + +/* + * The Interface + */ + +/* Declaration modifiers for DLL support (MSC et al) */ + +#if defined(DLL_NETCDF) /* define when library is a DLL */ +# if defined(DLL_EXPORT) /* define when building the library */ +# define MSC_EXTRA __declspec(dllexport) +# else +# define MSC_EXTRA __declspec(dllimport) +# endif +#else +#define MSC_EXTRA +#endif /* defined(DLL_NETCDF) */ + +# define EXTERNL extern MSC_EXTRA + +EXTERNL const char * +nc_inq_libvers(void); + +EXTERNL const char * +nc_strerror(int ncerr); + +EXTERNL int +nc__create(const char *path, int cmode, size_t initialsz, + size_t *chunksizehintp, int *ncidp); + +EXTERNL int +nc_create(const char *path, int cmode, int *ncidp); + +EXTERNL int +nc__open(const char *path, int mode, + size_t *chunksizehintp, int *ncidp); + +EXTERNL int +nc_open(const char *path, int mode, int *ncidp); + +EXTERNL int +nc_set_fill(int ncid, int fillmode, int *old_modep); + +EXTERNL int +nc_redef(int ncid); + +EXTERNL int +nc__enddef(int ncid, size_t h_minfree, size_t v_align, + size_t v_minfree, size_t r_align); + +EXTERNL int +nc_enddef(int ncid); + +EXTERNL int +nc_sync(int ncid); + +EXTERNL int +nc_abort(int ncid); + +EXTERNL int +nc_close(int ncid); + +EXTERNL int +nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp); + +EXTERNL int +nc_inq_ndims(int ncid, int *ndimsp); + +EXTERNL int +nc_inq_nvars(int ncid, int *nvarsp); + +EXTERNL int +nc_inq_natts(int ncid, int *nattsp); + +EXTERNL int +nc_inq_unlimdim(int ncid, int *unlimdimidp); + +/* Begin _dim */ + +EXTERNL int +nc_def_dim(int ncid, const char *name, size_t len, int *idp); + +EXTERNL int +nc_inq_dimid(int ncid, const char *name, int *idp); + +EXTERNL int +nc_inq_dim(int ncid, int dimid, char *name, size_t *lenp); + +EXTERNL int +nc_inq_dimname(int ncid, int dimid, char *name); + +EXTERNL int +nc_inq_dimlen(int ncid, int dimid, size_t *lenp); + +EXTERNL int +nc_rename_dim(int ncid, int dimid, const char *name); + +/* End _dim */ +/* Begin _att */ + +EXTERNL int +nc_inq_att(int ncid, int varid, const char *name, + nc_type *xtypep, size_t *lenp); + +EXTERNL int +nc_inq_attid(int ncid, int varid, const char *name, int *idp); + +EXTERNL int +nc_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep); + +EXTERNL int +nc_inq_attlen(int ncid, int varid, const char *name, size_t *lenp); + +EXTERNL int +nc_inq_attname(int ncid, int varid, int attnum, char *name); + +EXTERNL int +nc_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out, int varid_out); + +EXTERNL int +nc_rename_att(int ncid, int varid, const char *name, const char *newname); + +EXTERNL int +nc_del_att(int ncid, int varid, const char *name); + +/* End _att */ +/* Begin {put,get}_att */ + +EXTERNL int +nc_put_att_text(int ncid, int varid, const char *name, + size_t len, const char *op); + +EXTERNL int +nc_get_att_text(int ncid, int varid, const char *name, char *ip); + +EXTERNL int +nc_put_att_uchar(int ncid, int varid, const char *name, nc_type xtype, + size_t len, const unsigned char *op); + +EXTERNL int +nc_get_att_uchar(int ncid, int varid, const char *name, unsigned char *ip); + +EXTERNL int +nc_put_att_schar(int ncid, int varid, const char *name, nc_type xtype, + size_t len, const signed char *op); + +EXTERNL int +nc_get_att_schar(int ncid, int varid, const char *name, signed char *ip); + +EXTERNL int +nc_put_att_short(int ncid, int varid, const char *name, nc_type xtype, + size_t len, const short *op); + +EXTERNL int +nc_get_att_short(int ncid, int varid, const char *name, short *ip); + +EXTERNL int +nc_put_att_int(int ncid, int varid, const char *name, nc_type xtype, + size_t len, const int *op); + +EXTERNL int +nc_get_att_int(int ncid, int varid, const char *name, int *ip); + +EXTERNL int +nc_put_att_long(int ncid, int varid, const char *name, nc_type xtype, + size_t len, const long *op); + +EXTERNL int +nc_get_att_long(int ncid, int varid, const char *name, long *ip); + +EXTERNL int +nc_put_att_float(int ncid, int varid, const char *name, nc_type xtype, + size_t len, const float *op); + +EXTERNL int +nc_get_att_float(int ncid, int varid, const char *name, float *ip); + +EXTERNL int +nc_put_att_double(int ncid, int varid, const char *name, nc_type xtype, + size_t len, const double *op); + +EXTERNL int +nc_get_att_double(int ncid, int varid, const char *name, double *ip); + +/* End {put,get}_att */ +/* Begin _var */ + +EXTERNL int +nc_def_var(int ncid, const char *name, + nc_type xtype, int ndims, const int *dimidsp, int *varidp); + +EXTERNL int +nc_inq_var(int ncid, int varid, char *name, + nc_type *xtypep, int *ndimsp, int *dimidsp, int *nattsp); + +EXTERNL int +nc_inq_varid(int ncid, const char *name, int *varidp); + +EXTERNL int +nc_inq_varname(int ncid, int varid, char *name); + +EXTERNL int +nc_inq_vartype(int ncid, int varid, nc_type *xtypep); + +EXTERNL int +nc_inq_varndims(int ncid, int varid, int *ndimsp); + +EXTERNL int +nc_inq_vardimid(int ncid, int varid, int *dimidsp); + +EXTERNL int +nc_inq_varnatts(int ncid, int varid, int *nattsp); + +EXTERNL int +nc_rename_var(int ncid, int varid, const char *name); + +EXTERNL int +nc_copy_var(int ncid_in, int varid, int ncid_out); +#ifndef ncvarcpy +/* support the old name for now */ +#define ncvarcpy(ncid_in, varid, ncid_out) ncvarcopy((ncid_in), (varid), (ncid_out)) +#endif + +/* End _var */ +/* Begin {put,get}_var1 */ + +EXTERNL int +nc_put_var1_text(int ncid, int varid, const size_t *indexp, const char *op); + +EXTERNL int +nc_get_var1_text(int ncid, int varid, const size_t *indexp, char *ip); + +EXTERNL int +nc_put_var1_uchar(int ncid, int varid, const size_t *indexp, + const unsigned char *op); + +EXTERNL int +nc_get_var1_uchar(int ncid, int varid, const size_t *indexp, + unsigned char *ip); + +EXTERNL int +nc_put_var1_schar(int ncid, int varid, const size_t *indexp, + const signed char *op); + +EXTERNL int +nc_get_var1_schar(int ncid, int varid, const size_t *indexp, + signed char *ip); + +EXTERNL int +nc_put_var1_short(int ncid, int varid, const size_t *indexp, + const short *op); + +EXTERNL int +nc_get_var1_short(int ncid, int varid, const size_t *indexp, + short *ip); + +EXTERNL int +nc_put_var1_int(int ncid, int varid, const size_t *indexp, const int *op); + +EXTERNL int +nc_get_var1_int(int ncid, int varid, const size_t *indexp, int *ip); + +EXTERNL int +nc_put_var1_long(int ncid, int varid, const size_t *indexp, const long *op); + +EXTERNL int +nc_get_var1_long(int ncid, int varid, const size_t *indexp, long *ip); + +EXTERNL int +nc_put_var1_float(int ncid, int varid, const size_t *indexp, const float *op); + +EXTERNL int +nc_get_var1_float(int ncid, int varid, const size_t *indexp, float *ip); + +EXTERNL int +nc_put_var1_double(int ncid, int varid, const size_t *indexp, const double *op); + +EXTERNL int +nc_get_var1_double(int ncid, int varid, const size_t *indexp, double *ip); + +/* End {put,get}_var1 */ +/* Begin {put,get}_vara */ + +EXTERNL int +nc_put_vara_text(int ncid, int varid, + const size_t *startp, const size_t *countp, const char *op); + +EXTERNL int +nc_get_vara_text(int ncid, int varid, + const size_t *startp, const size_t *countp, char *ip); + +EXTERNL int +nc_put_vara_uchar(int ncid, int varid, + const size_t *startp, const size_t *countp, const unsigned char *op); + +EXTERNL int +nc_get_vara_uchar(int ncid, int varid, + const size_t *startp, const size_t *countp, unsigned char *ip); + +EXTERNL int +nc_put_vara_schar(int ncid, int varid, + const size_t *startp, const size_t *countp, const signed char *op); + +EXTERNL int +nc_get_vara_schar(int ncid, int varid, + const size_t *startp, const size_t *countp, signed char *ip); + +EXTERNL int +nc_put_vara_short(int ncid, int varid, + const size_t *startp, const size_t *countp, const short *op); + +EXTERNL int +nc_get_vara_short(int ncid, int varid, + const size_t *startp, const size_t *countp, short *ip); + +EXTERNL int +nc_put_vara_int(int ncid, int varid, + const size_t *startp, const size_t *countp, const int *op); + +EXTERNL int +nc_get_vara_int(int ncid, int varid, + const size_t *startp, const size_t *countp, int *ip); + +EXTERNL int +nc_put_vara_long(int ncid, int varid, + const size_t *startp, const size_t *countp, const long *op); + +EXTERNL int +nc_get_vara_long(int ncid, int varid, + const size_t *startp, const size_t *countp, long *ip); + +EXTERNL int +nc_put_vara_float(int ncid, int varid, + const size_t *startp, const size_t *countp, const float *op); + +EXTERNL int +nc_get_vara_float(int ncid, int varid, + const size_t *startp, const size_t *countp, float *ip); + +EXTERNL int +nc_put_vara_double(int ncid, int varid, + const size_t *startp, const size_t *countp, const double *op); + +EXTERNL int +nc_get_vara_double(int ncid, int varid, + const size_t *startp, const size_t *countp, double *ip); + +/* End {put,get}_vara */ +/* Begin {put,get}_vars */ + +EXTERNL int +nc_put_vars_text(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const char *op); + +EXTERNL int +nc_get_vars_text(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + char *ip); + +EXTERNL int +nc_put_vars_uchar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const unsigned char *op); + +EXTERNL int +nc_get_vars_uchar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + unsigned char *ip); + +EXTERNL int +nc_put_vars_schar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const signed char *op); + +EXTERNL int +nc_get_vars_schar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + signed char *ip); + +EXTERNL int +nc_put_vars_short(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const short *op); + +EXTERNL int +nc_get_vars_short(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + short *ip); + +EXTERNL int +nc_put_vars_int(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const int *op); + +EXTERNL int +nc_get_vars_int(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + int *ip); + +EXTERNL int +nc_put_vars_long(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const long *op); + +EXTERNL int +nc_get_vars_long(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + long *ip); + +EXTERNL int +nc_put_vars_float(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const float *op); + +EXTERNL int +nc_get_vars_float(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + float *ip); + +EXTERNL int +nc_put_vars_double(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const double *op); + +EXTERNL int +nc_get_vars_double(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + double *ip); + +/* End {put,get}_vars */ +/* Begin {put,get}_varm */ + +EXTERNL int +nc_put_varm_text(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const char *op); + +EXTERNL int +nc_get_varm_text(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + char *ip); + +EXTERNL int +nc_put_varm_uchar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const unsigned char *op); + +EXTERNL int +nc_get_varm_uchar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + unsigned char *ip); + +EXTERNL int +nc_put_varm_schar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const signed char *op); + +EXTERNL int +nc_get_varm_schar(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + signed char *ip); + +EXTERNL int +nc_put_varm_short(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const short *op); + +EXTERNL int +nc_get_varm_short(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + short *ip); + +EXTERNL int +nc_put_varm_int(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const int *op); + +EXTERNL int +nc_get_varm_int(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + int *ip); + +EXTERNL int +nc_put_varm_long(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const long *op); + +EXTERNL int +nc_get_varm_long(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + long *ip); + +EXTERNL int +nc_put_varm_float(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const float *op); + +EXTERNL int +nc_get_varm_float(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + float *ip); + +EXTERNL int +nc_put_varm_double(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t *imapp, + const double *op); + +EXTERNL int +nc_get_varm_double(int ncid, int varid, + const size_t *startp, const size_t *countp, const ptrdiff_t *stridep, + const ptrdiff_t * imap, + double *ip); + +/* End {put,get}_varm */ +/* Begin {put,get}_var */ + +EXTERNL int +nc_put_var_text(int ncid, int varid, const char *op); + +EXTERNL int +nc_get_var_text(int ncid, int varid, char *ip); + +EXTERNL int +nc_put_var_uchar(int ncid, int varid, const unsigned char *op); + +EXTERNL int +nc_get_var_uchar(int ncid, int varid, unsigned char *ip); + +EXTERNL int +nc_put_var_schar(int ncid, int varid, const signed char *op); + +EXTERNL int +nc_get_var_schar(int ncid, int varid, signed char *ip); + +EXTERNL int +nc_put_var_short(int ncid, int varid, const short *op); + +EXTERNL int +nc_get_var_short(int ncid, int varid, short *ip); + +EXTERNL int +nc_put_var_int(int ncid, int varid, const int *op); + +EXTERNL int +nc_get_var_int(int ncid, int varid, int *ip); + +EXTERNL int +nc_put_var_long(int ncid, int varid, const long *op); + +EXTERNL int +nc_get_var_long(int ncid, int varid, long *ip); + +EXTERNL int +nc_put_var_float(int ncid, int varid, const float *op); + +EXTERNL int +nc_get_var_float(int ncid, int varid, float *ip); + +EXTERNL int +nc_put_var_double(int ncid, int varid, const double *op); + +EXTERNL int +nc_get_var_double(int ncid, int varid, double *ip); + +/* End {put,get}_var */ + +/* Begin v2.4 backward compatiblity */ +/* + * defining NO_NETCDF_2 to the preprocessor + * turns off backward compatiblity declarations. + */ +#ifndef NO_NETCDF_2 + +/* + * Backward compatible aliases + */ +#define FILL_BYTE NC_FILL_BYTE +#define FILL_CHAR NC_FILL_CHAR +#define FILL_SHORT NC_FILL_SHORT +#define FILL_LONG NC_FILL_INT +#define FILL_FLOAT NC_FILL_FLOAT +#define FILL_DOUBLE NC_FILL_DOUBLE + +#define MAX_NC_DIMS NC_MAX_DIMS +#define MAX_NC_ATTRS NC_MAX_ATTRS +#define MAX_NC_VARS NC_MAX_VARS +#define MAX_NC_NAME NC_MAX_NAME +#define MAX_VAR_DIMS NC_MAX_VAR_DIMS + +/* + * If and when 64 integer types become ubiquitous, + * we would like to use NC_LONG for that. + * For now, define for backward compatibility. + */ +#define NC_LONG NC_INT + +/* + * Global error status + */ +EXTERNL int ncerr; + +#define NC_ENTOOL NC_EMAXNAME /* Backward compatibility */ +#define NC_EXDR (-32) /* */ +#define NC_SYSERR (-31) + +/* + * Avoid use of this meaningless macro + * Use sysconf(_SC_OPEN_MAX). + */ +#ifndef MAX_NC_OPEN +#define MAX_NC_OPEN 32 +#endif + +/* + * Global options variable. + * Used to determine behavior of error handler. + */ +#define NC_FATAL 1 +#define NC_VERBOSE 2 + +EXTERNL int ncopts; /* default is (NC_FATAL | NC_VERBOSE) */ + +EXTERNL void +nc_advise(const char *cdf_routine_name, int err, const char *fmt,...); + +/* + * C data type corresponding to a netCDF NC_LONG argument, + * a signed 32 bit object. + * + * This is the only thing in this file which architecture dependent. + */ +typedef int nclong; + +EXTERNL int +nctypelen(nc_type datatype); + +EXTERNL int +nccreate(const char* path, int cmode); + +EXTERNL int +ncopen(const char* path, int mode); + +EXTERNL int +ncsetfill(int ncid, int fillmode); + +EXTERNL int +ncredef(int ncid); + +EXTERNL int +ncendef(int ncid); + +EXTERNL int +ncsync(int ncid); + +EXTERNL int +ncabort(int ncid); + +EXTERNL int +ncclose(int ncid); + +EXTERNL int +ncinquire(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimp); + +EXTERNL int +ncdimdef(int ncid, const char *name, long len); + +EXTERNL int +ncdimid(int ncid, const char *name); + +EXTERNL int +ncdiminq(int ncid, int dimid, char *name, long *lenp); + +EXTERNL int +ncdimrename(int ncid, int dimid, const char *name); + +EXTERNL int +ncattput(int ncid, int varid, const char *name, nc_type xtype, + int len, const void *op); + +EXTERNL int +ncattinq(int ncid, int varid, const char *name, nc_type *xtypep, int *lenp); + +EXTERNL int +ncattget(int ncid, int varid, const char *name, void *ip); + +EXTERNL int +ncattcopy(int ncid_in, int varid_in, const char *name, int ncid_out, + int varid_out); + +EXTERNL int +ncattname(int ncid, int varid, int attnum, char *name); + +EXTERNL int +ncattrename(int ncid, int varid, const char *name, const char *newname); + +EXTERNL int +ncattdel(int ncid, int varid, const char *name); + +EXTERNL int +ncvardef(int ncid, const char *name, nc_type xtype, + int ndims, const int *dimidsp); + +EXTERNL int +ncvarid(int ncid, const char *name); + +EXTERNL int +ncvarinq(int ncid, int varid, char *name, nc_type *xtypep, + int *ndimsp, int *dimidsp, int *nattsp); + +EXTERNL int +ncvarput1(int ncid, int varid, const long *indexp, const void *op); + +EXTERNL int +ncvarget1(int ncid, int varid, const long *indexp, void *ip); + +EXTERNL int +ncvarput(int ncid, int varid, const long *startp, const long *countp, + const void *op); + +EXTERNL int +ncvarget(int ncid, int varid, const long *startp, const long *countp, + void *ip); + +EXTERNL int +ncvarputs(int ncid, int varid, const long *startp, const long *countp, + const long *stridep, const void *op); + +EXTERNL int +ncvargets(int ncid, int varid, const long *startp, const long *countp, + const long *stridep, void *ip); + +EXTERNL int +ncvarputg(int ncid, int varid, const long *startp, const long *countp, + const long *stridep, const long *imapp, const void *op); + +EXTERNL int +ncvargetg(int ncid, int varid, const long *startp, const long *countp, + const long *stridep, const long *imapp, void *ip); + +EXTERNL int +ncvarrename(int ncid, int varid, const char *name); + +EXTERNL int +ncrecinq(int ncid, int *nrecvarsp, int *recvaridsp, long *recsizesp); + +EXTERNL int +ncrecget(int ncid, long recnum, void **datap); + +EXTERNL int +ncrecput(int ncid, long recnum, void *const *datap); + +/* End v2.4 backward compatiblity */ +#endif /*!NO_NETCDF_2*/ + +#if defined(__cplusplus) +} +#endif + +#endif /* _NETCDF_ */ diff --git a/Utilities/vtknetcdf/onstack.h b/Utilities/vtknetcdf/onstack.h new file mode 100644 index 0000000..a31c48c --- /dev/null +++ b/Utilities/vtknetcdf/onstack.h @@ -0,0 +1,72 @@ +/* + * Copyright 1997, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: onstack.h,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#ifndef _ONSTACK_H_ +#define _ONSTACK_H_ +/* include after ncconfig.h */ +/** + * This file provides definitions which allow us to + * "allocate" arrays on the stack where possible. + * (Where not possible, malloc and free are used.) + * + * The macro ALLOC_ONSTACK(name, type, nelems) is used to declare + * an array of 'type' named 'name' which is 'nelems' long. + * FREE_ONSTACK(name) is placed at the end of the scope of 'name' + * to call 'free' if necessary. + * + * The macro ALLOC_ONSTACK wraps a call to alloca() on most systems. + */ + +#if HAVE_ALLOCA +/* + * Implementation based on alloca() + */ + +#if defined(__GNUC__) +# if !defined(alloca) +# define alloca __builtin_alloca +# endif +#else +# if HAVE_ALLOCA_H +# include <alloca.h> +# elif defined(_AIX) +# pragma alloca +# endif /* HAVE_ALLOCA_H */ +#endif /* __GNUC__ */ + +# if !defined(ALLOCA_ARG_T) +# define ALLOCA_ARG_T int /* the usual type of the alloca argument */ +# endif + +# define ALLOC_ONSTACK(name, type, nelems) \ + type *const name = (type *) alloca((ALLOCA_ARG_T)((nelems) * sizeof(type))) + +# define FREE_ONSTACK(name) + +#elif defined(_CRAYC) && !__cplusplus && __STDC__ > 1 +/* + * Cray C allows sizing of arrays with non-constant values. + */ + +# define ALLOC_ONSTACK(name, type, nelems) \ + type name[nelems] + +# define FREE_ONSTACK(name) + +#else +/* + * Default implementation. When all else fails, use malloc/free. + */ + +# define ALLOC_ONSTACK(name, type, nelems) \ + type *const name = (type *) malloc((nelems) * sizeof(type)) + +# define FREE_ONSTACK(name) \ + free(name) + +#endif + +#endif /* _ONSTACK_H_ */ diff --git a/Utilities/vtknetcdf/posixio.c b/Utilities/vtknetcdf/posixio.c new file mode 100644 index 0000000..22139a2 --- /dev/null +++ b/Utilities/vtknetcdf/posixio.c @@ -0,0 +1,1390 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: posixio.c,v 1.6 2005/08/29 17:54:17 andy Exp $ */ +/*#define USE_CWRITE 1 *//*define to use _cwrite instead of write*/ + +#ifdef SGI64 +#define lseek lseek64 +#endif + +#ifdef __PARAGON__ +#include <nx.h> + static int netcdf_local_is_file_pfs = 0; +#endif + +#include "ncconfig.h" +#include <assert.h> +#include <stdlib.h> +#include <errno.h> +#ifndef ENOERR +#define ENOERR 0 +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#ifdef _MSC_VER /* Microsoft Compilers */ +#include <io.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#include "ncio.h" +#include "fbits.h" +#include "rnd.h" + +/* #define INSTRUMENT 1 */ +#if INSTRUMENT /* debugging */ +#undef NDEBUG +#include <stdio.h> +#include "instr.h" +#endif + +#undef MIN /* system may define MIN somewhere and complain */ +#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn)) + +#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */ +#define X_ALIGN 4 +#else +#undef X_ALIGN +#endif + +/* + * Define the following for debugging. + */ +/* #define ALWAYS_NC_SHARE 1 */ + +/* Begin OS */ +#ifdef __PARAGON__ +/* #define ALIGN32 32 */ +#ifdef __PUMAGON__ +#define POSIXIO_DEFAULT_PAGESIZE (256*1024) +#else +#define POSIXIO_DEFAULT_PAGESIZE (256*1024) +#endif +#ifndef HAVE_ST_BLKSIZE +#define HAVE_ST_BLKSIZE 1 +#endif +#if defined(_SC_PAGE_SIZE) +#undef _SC_PAGE_SIZE +#endif +#endif /* __PARAGON__ */ +#ifndef POSIXIO_DEFAULT_PAGESIZE +#define POSIXIO_DEFAULT_PAGESIZE 4096 +#endif +/* + * What is the system pagesize? + */ +static size_t +pagesize(void) +{ +/* Hmm, aren't standards great? */ +#if defined(_SC_PAGE_SIZE) && !defined(_SC_PAGESIZE) +#define _SC_PAGESIZE _SC_PAGE_SIZE +#endif + +#ifdef _SC_PAGESIZE + { + const long pgsz = sysconf(_SC_PAGESIZE); + if(pgsz > 0) + return (size_t) pgsz; + /* else, silent in the face of error */ + } +#elif defined(HAVE_GETPAGESIZE) + return (size_t) getpagesize(); +#endif + return (size_t) POSIXIO_DEFAULT_PAGESIZE; +} + +/* + * What is the preferred I/O block size? + */ +static size_t +blksize(int fd) +{ +#if defined(HAVE_ST_BLKSIZE) + struct stat sb; + if (fstat(fd, &sb) > -1) + { +#ifdef __PARAGON__ + netcdf_local_is_file_pfs = 0; + if(sb.st_blksize >= 256*1024) + { + netcdf_local_is_file_pfs = 1; + } + if(sb.st_blksize < POSIXIO_DEFAULT_PAGESIZE) + { + return (size_t) POSIXIO_DEFAULT_PAGESIZE; + } + else + { + return (size_t) sb.st_blksize; + } +#else + return (size_t) sb.st_blksize; +#endif + } + /* else, silent in the face of error */ +#endif + (void)fd; + return (size_t) 2 * pagesize(); +} + + +/* + * Sortof like ftruncate, except won't make the + * file shorter. + */ +static int +fgrow(const int fd, const off_t len) +{ + struct stat sb; + if (fstat(fd, &sb) < 0) + return errno; + if (len < sb.st_size) + return ENOERR; +#if defined(HAVE_FTRUNCATE) + if (ftruncate(fd, len) < 0) + return errno; +#else + { + const long dumb = 0; + /* cache current position */ + const off_t pos = lseek(fd, 0, SEEK_CUR); + if(pos < 0) + return errno; + if (lseek(fd, len-sizeof(dumb), SEEK_SET) < 0) + return errno; + + if(write(fd, &dumb, sizeof(dumb)) < 0) + return errno; + if (lseek(fd, pos, SEEK_SET) < 0) + return errno; + } +#endif /* HAVE_FTRUNCATE */ + /* else */ + return ENOERR; +} + +/* End OS */ +/* Begin px */ + +static int +px_pgout(ncio *const nciop, + off_t const offset, const size_t extent, + void *const vp, off_t *posp) +{ +#ifdef X_ALIGN + assert(offset % X_ALIGN == 0); +#endif + + assert(*posp == OFF_NONE || *posp == lseek(nciop->fd, 0, SEEK_CUR)); + + if(*posp != offset) + { + if(lseek(nciop->fd, offset, SEEK_SET) != offset) + { + return errno; + } + *posp = offset; + } +#ifdef __PARAGON__ + if(nciop->is_file_pfs == 1) + { + if(_cwrite(nciop->fd, vp, extent) != (ssize_t) extent) + { + return errno; + } + } + else + { + if(write(nciop->fd, vp, extent) != (ssize_t) extent) + { + return errno; + } + } + +#else + if(write(nciop->fd, vp, extent) != (ssize_t) extent) + { + return errno; + } +#endif + *posp += extent; + + return ENOERR; +} + + +static int +px_pgin(ncio *const nciop, + off_t const offset, const size_t extent, + void *const vp, size_t *nreadp, off_t *posp) +{ + int status; + ssize_t nread; + +#ifdef X_ALIGN + assert(offset % X_ALIGN == 0); + assert(extent % X_ALIGN == 0); +#endif + + assert(*posp == OFF_NONE || *posp == lseek(nciop->fd, 0, SEEK_CUR)); + + if(*posp != offset) + { + if(lseek(nciop->fd, offset, SEEK_SET) != offset) + { + status = errno; + return status; + } + *posp = offset; + } + + errno = 0; +#ifdef __PARAGON__ + if(nciop->is_file_pfs == 1) + { + nread = _cread(nciop->fd, vp, extent); + } + else + { + nread = read(nciop->fd, vp, extent); + } +#else + nread = read(nciop->fd, vp, extent); +#endif + if(nread != (ssize_t) extent) + { + status = errno; +#ifdef __PARAGON__ + if(status == ERDEOF){status=ENOERR;} +#endif + if(nread == -1 || status != ENOERR) + return status; + /* else it's okay we read less than asked for */ + (void) memset((char *)vp + nread, 0, (ssize_t)extent - nread); + } + *nreadp = nread; + *posp += nread; + + return ENOERR; +} + + +typedef struct ncio_px { + size_t blksz; + off_t pos; + /* buffer */ + off_t bf_offset; + size_t bf_extent; + size_t bf_cnt; + void *bf_base; + int bf_rflags; + int bf_refcount; + /* chain for double buffering in px_move */ + struct ncio_px *slave; +} ncio_px; + + +/*ARGSUSED*/ +static int +px_rel(ncio_px *const pxp, off_t offset, int rflags) +{ + assert(pxp->bf_offset <= offset + && offset < pxp->bf_offset + (off_t) pxp->bf_extent); + assert(pIf(fIsSet(rflags, RGN_MODIFIED), + fIsSet(pxp->bf_rflags, RGN_WRITE))); + + (void)offset; + + if(fIsSet(rflags, RGN_MODIFIED)) + { + fSet(pxp->bf_rflags, RGN_MODIFIED); + } + pxp->bf_refcount--; + + return ENOERR; +} + +static int +ncio_px_rel(ncio *const nciop, off_t offset, int rflags) +{ + ncio_px *const pxp = (ncio_px *)nciop->pvt; + + if(fIsSet(rflags, RGN_MODIFIED) && !fIsSet(nciop->ioflags, NC_WRITE)) + return EPERM; /* attempt to write readonly file */ + + return px_rel(pxp, offset, rflags); +} + +static int +px_get(ncio *const nciop, ncio_px *const pxp, + off_t offset, size_t extent, + int rflags, + void **const vpp) +{ + int status = ENOERR; + + const off_t blkoffset = _RNDDOWN(offset, (off_t)pxp->blksz); + size_t diff = (size_t)(offset - blkoffset); + size_t blkextent = _RNDUP(diff + extent, pxp->blksz); + + assert(extent != 0); + assert(offset >= 0); /* sanity check */ + + if(2 * pxp->blksz < blkextent) + return E2BIG; /* TODO: temporary kludge */ + if(pxp->bf_offset == OFF_NONE) + { + /* Uninitialized */ + if(pxp->bf_base == NULL) + { + assert(pxp->bf_extent == 0); + assert(blkextent <= 2 * pxp->blksz); +#ifndef ALIGN32 + pxp->bf_base = malloc(2 * pxp->blksz ); +#else + pxp->bf_base = malloc(2 * pxp->blksz + ALIGN32); + pxp->bf_base = (char *)((uint)((char *)pxp->bf_base + ALIGN32 - 1) & ~(ALIGN32 - 1)); +#endif + if(pxp->bf_base == NULL) + return ENOMEM; + } + goto pgin; + } + /* else */ + assert(blkextent <= 2 * pxp->blksz); + + if(blkoffset == pxp->bf_offset) + { + /* hit */ + if(blkextent > pxp->bf_extent) + { + /* page in upper */ + void *const middle = + (void *)((char *)pxp->bf_base + pxp->blksz); + assert(pxp->bf_extent == pxp->blksz); + status = px_pgin(nciop, + pxp->bf_offset + (off_t)pxp->blksz, + pxp->blksz, + middle, + &pxp->bf_cnt, + &pxp->pos); + if(status != ENOERR) + return status; + pxp->bf_extent = 2 * pxp->blksz; + pxp->bf_cnt += pxp->blksz; + } + goto done; + } + /* else */ + + if(pxp->bf_extent > pxp->blksz + && blkoffset == (off_t)(pxp->bf_offset + pxp->blksz)) + { + /* hit in upper half */ + if(blkextent == pxp->blksz) + { + /* all in upper half, no fault needed */ + diff += pxp->blksz; + goto done; + } + /* else */ + if(pxp->bf_cnt > pxp->blksz) + { + /* data in upper half */ + void *const middle = + (void *)((char *)pxp->bf_base + pxp->blksz); + assert(pxp->bf_extent == 2 * pxp->blksz); + if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) + { + /* page out lower half */ + assert(pxp->bf_refcount <= 0); + status = px_pgout(nciop, + pxp->bf_offset, + pxp->blksz, + pxp->bf_base, + &pxp->pos); + if(status != ENOERR) + return status; + } + pxp->bf_cnt -= pxp->blksz; + /* copy upper half into lower half */ + (void) memcpy(pxp->bf_base, middle, pxp->bf_cnt); + } + pxp->bf_offset = blkoffset; + /* pxp->bf_extent = pxp->blksz; */ + + assert(blkextent == 2 * pxp->blksz); + { + /* page in upper */ + void *const middle = + (void *)((char *)pxp->bf_base + pxp->blksz); + status = px_pgin(nciop, + pxp->bf_offset + (off_t)pxp->blksz, + pxp->blksz, + middle, + &pxp->bf_cnt, + &pxp->pos); + if(status != ENOERR) + return status; + pxp->bf_extent = 2 * pxp->blksz; + pxp->bf_cnt += pxp->blksz; + } + goto done; + } + /* else */ + + if(blkoffset == (off_t)(pxp->bf_offset - pxp->blksz)) + { + /* wants the page below */ + void *const middle = + (void *)((char *)pxp->bf_base + pxp->blksz); + size_t upper_cnt = 0; + if(pxp->bf_cnt > pxp->blksz) + { + /* data in upper half */ + assert(pxp->bf_extent == 2 * pxp->blksz); + if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) + { + /* page out upper half */ + assert(pxp->bf_refcount <= 0); + status = px_pgout(nciop, + pxp->bf_offset + (off_t)pxp->blksz, + pxp->bf_cnt - pxp->blksz, + middle, + &pxp->pos); + if(status != ENOERR) + return status; + } + pxp->bf_cnt = pxp->blksz; + pxp->bf_extent = pxp->blksz; + } + if(pxp->bf_cnt > 0) + { + /* copy lower half into upper half */ + (void) memcpy(middle, pxp->bf_base, pxp->blksz); + upper_cnt = pxp->bf_cnt; + } + /* read page below into lower half */ + status = px_pgin(nciop, + blkoffset, + pxp->blksz, + pxp->bf_base, + &pxp->bf_cnt, + &pxp->pos); + if(status != ENOERR) + return status; + pxp->bf_offset = blkoffset; + if(upper_cnt != 0) + { + pxp->bf_extent = 2 * pxp->blksz; + pxp->bf_cnt = pxp->blksz + upper_cnt; + } + else + { + pxp->bf_extent = pxp->blksz; + } + goto done; + } + /* else */ + + /* no overlap */ + if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) + { + assert(pxp->bf_refcount <= 0); + status = px_pgout(nciop, + pxp->bf_offset, + pxp->bf_cnt, + pxp->bf_base, + &pxp->pos); + if(status != ENOERR) + return status; + pxp->bf_rflags = 0; + } + +pgin: + status = px_pgin(nciop, + blkoffset, + blkextent, + pxp->bf_base, + &pxp->bf_cnt, + &pxp->pos); + if(status != ENOERR) + return status; + pxp->bf_offset = blkoffset; + pxp->bf_extent = blkextent; + +done: + extent += diff; + if(pxp->bf_cnt < extent) + pxp->bf_cnt = extent; + assert(pxp->bf_cnt <= pxp->bf_extent); + + pxp->bf_rflags |= rflags; + pxp->bf_refcount++; + + *vpp = (char *)pxp->bf_base + diff; + return ENOERR; +} + +static int +ncio_px_get(ncio *const nciop, + off_t offset, size_t extent, + int rflags, + void **const vpp) +{ + ncio_px *const pxp = (ncio_px *)nciop->pvt; + + if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE)) + return EPERM; /* attempt to write readonly file */ + + /* reclaim space used in move */ + if(pxp->slave != NULL) + { + if(pxp->slave->bf_base != NULL) + { + free(pxp->slave->bf_base); + pxp->slave->bf_base = NULL; + pxp->slave->bf_extent = 0; + pxp->slave->bf_offset = OFF_NONE; + } + free(pxp->slave); + pxp->slave = NULL; + } + return px_get(nciop, pxp, offset, extent, rflags, vpp); +} + + +/* ARGSUSED */ +static int +px_double_buffer(ncio *const nciop, off_t to, off_t from, + size_t nbytes, int rflags) +{ + ncio_px *const pxp = (ncio_px *)nciop->pvt; + int status = ENOERR; + void *src; + void *dest; + + (void)rflags; + +#if 0 +fprintf(stderr, "double_buffr %ld %ld %ld\n", + (long)to, (long)from, (long)nbytes); +#endif + status = px_get(nciop, pxp, to, nbytes, RGN_WRITE, + &dest); + if(status != ENOERR) + return status; + + if(pxp->slave == NULL) + { + pxp->slave = (ncio_px *) malloc(sizeof(ncio_px)); + if(pxp->slave == NULL) + return ENOMEM; + + pxp->slave->blksz = pxp->blksz; + /* pos done below */ + pxp->slave->bf_offset = pxp->bf_offset; + pxp->slave->bf_extent = pxp->bf_extent; + pxp->slave->bf_cnt = pxp->bf_cnt; +#ifndef ALIGN32 + pxp->slave->bf_base = malloc(2 * pxp->blksz); +#else + pxp->slave->bf_base = malloc(2 * pxp->blksz + ALIGN32); + pxp->slave->bf_base = (char *)((uint)((char *)pxp->slave->bf_base + ALIGN32-1) & ~(ALIGN32 - 1)); +#endif + if(pxp->slave->bf_base == NULL) + return ENOMEM; + (void) memcpy(pxp->slave->bf_base, pxp->bf_base, + pxp->bf_extent); + pxp->slave->bf_rflags = 0; + pxp->slave->bf_refcount = 0; + pxp->slave->slave = NULL; + } + + pxp->slave->pos = pxp->pos; + status = px_get(nciop, pxp->slave, from, nbytes, 0, + &src); + if(status != ENOERR) + return status; + if(pxp->pos != pxp->slave->pos) + { + /* position changed, sync */ + pxp->pos = pxp->slave->pos; + } + + (void) memcpy(dest, src, nbytes); + + (void)px_rel(pxp->slave, from, 0); + (void)px_rel(pxp, to, RGN_MODIFIED); + + return status; +} + +static int +ncio_px_move(ncio *const nciop, off_t to, off_t from, + size_t nbytes, int rflags) +{ + ncio_px *const pxp = (ncio_px *)nciop->pvt; + int status = ENOERR; + off_t lower; + off_t upper; + char *base; + size_t diff; + size_t extent; + + if(to == from) + return ENOERR; /* NOOP */ + + if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE)) + return EPERM; /* attempt to write readonly file */ + + rflags &= RGN_NOLOCK; /* filter unwanted flags */ + + if(to > from) + { + /* growing */ + lower = from; + upper = to; + } + else + { + /* shrinking */ + lower = to; + upper = from; + } + diff = (size_t)(upper - lower); + extent = diff + nbytes; + + if(extent > pxp->blksz) + { + size_t remaining = nbytes; + for(;;) + { + size_t loopextent = MIN(remaining, pxp->blksz); + + status = px_double_buffer(nciop, to, from, + loopextent, rflags) ; + if(status != ENOERR) + return status; + remaining -= loopextent; + + if(remaining == 0) + break; /* normal loop exit */ + to += loopextent; + from += loopextent; + } + return ENOERR; + } + +#if 0 +fprintf(stderr, "ncio_px_move %ld %ld %ld %ld %ld\n", + (long)to, (long)from, (long)nbytes, (long)lower, (long)extent); +#endif + status = px_get(nciop, pxp, lower, extent, RGN_WRITE|rflags, + (void **)&base); + + if(status != ENOERR) + return status; + + if(to > from) + (void) memmove(base + diff, base, nbytes); + else + (void) memmove(base, base + diff, nbytes); + + (void) px_rel(pxp, lower, RGN_MODIFIED); + + return status; +} + + +static int +ncio_px_sync(ncio *const nciop) +{ + ncio_px *const pxp = (ncio_px *)nciop->pvt; + int status = ENOERR; + if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) + { + assert(pxp->bf_refcount <= 0); + status = px_pgout(nciop, pxp->bf_offset, + pxp->bf_cnt, + pxp->bf_base, &pxp->pos); + if(status != ENOERR) + return status; + pxp->bf_rflags = 0; + } + return status; +} + +static void +ncio_px_free(void *const pvt) +{ + ncio_px *const pxp = (ncio_px *)pvt; + if(pxp == NULL) + return; + + if(pxp->slave != NULL) + { + if(pxp->slave->bf_base != NULL) + { + free(pxp->slave->bf_base); + pxp->slave->bf_base = NULL; + pxp->slave->bf_extent = 0; + pxp->slave->bf_offset = OFF_NONE; + } + free(pxp->slave); + pxp->slave = NULL; + } + + if(pxp->bf_base != NULL) + { + free(pxp->bf_base); + pxp->bf_base = NULL; + pxp->bf_extent = 0; + pxp->bf_offset = OFF_NONE; + } +} + + +static int +ncio_px_init2(ncio *const nciop, size_t *sizehintp, int isNew) +{ + ncio_px *const pxp = (ncio_px *)nciop->pvt; + const size_t bufsz = 2 * *sizehintp; + + assert(nciop->fd >= 0); + + pxp->blksz = *sizehintp; + + assert(pxp->bf_base == NULL); + + /* this is separate allocation because it may grow */ +#ifndef ALIGN32 + pxp->bf_base = malloc(bufsz); +#else + pxp->bf_base = malloc(bufsz + ALIGN32); + pxp->bf_base = (char *)((uint)((char *)pxp->bf_base + ALIGN32 - 1) & ~(ALIGN32 - 1)); +#endif + if(pxp->bf_base == NULL) + return ENOMEM; + /* else */ + pxp->bf_cnt = 0; + if(isNew) + { + /* save a read */ + pxp->pos = 0; + pxp->bf_offset = 0; + pxp->bf_extent = bufsz; + (void) memset(pxp->bf_base, 0, pxp->bf_extent); + } + return ENOERR; +} + + +static void +ncio_px_init(ncio *const nciop) +{ + ncio_px *const pxp = (ncio_px *)nciop->pvt; + + *((ncio_relfunc **)&nciop->rel) = ncio_px_rel; /* cast away const */ + *((ncio_getfunc **)&nciop->get) = ncio_px_get; /* cast away const */ + *((ncio_movefunc **)&nciop->move) = ncio_px_move; /* cast away const */ + *((ncio_syncfunc **)&nciop->sync) = ncio_px_sync; /* cast away const */ + *((ncio_freefunc **)&nciop->free) = ncio_px_free; /* cast away const */ + + pxp->blksz = 0; + pxp->pos = -1; + pxp->bf_offset = OFF_NONE; + pxp->bf_extent = 0; + pxp->bf_rflags = 0; + pxp->bf_refcount = 0; + pxp->bf_base = NULL; + pxp->slave = NULL; + +} + +/* Begin spx */ + +typedef struct ncio_spx { + off_t pos; + /* buffer */ + off_t bf_offset; + size_t bf_extent; + size_t bf_cnt; + void *bf_base; +} ncio_spx; + + +/*ARGSUSED*/ +static int +ncio_spx_rel(ncio *const nciop, off_t offset, int rflags) +{ + ncio_spx *const pxp = (ncio_spx *)nciop->pvt; + int status = ENOERR; + + (void)offset; + + assert(pxp->bf_offset <= offset); + assert(pxp->bf_cnt != 0); + assert(pxp->bf_cnt <= pxp->bf_extent); +#ifdef X_ALIGN + assert(offset < pxp->bf_offset + X_ALIGN); + assert(pxp->bf_cnt % X_ALIGN == 0 ); +#endif + + if(fIsSet(rflags, RGN_MODIFIED)) + { + if(!fIsSet(nciop->ioflags, NC_WRITE)) + return EPERM; /* attempt to write readonly file */ + + status = px_pgout(nciop, pxp->bf_offset, + pxp->bf_cnt, + pxp->bf_base, &pxp->pos); + /* if error, invalidate buffer anyway */ + } + pxp->bf_offset = OFF_NONE; + pxp->bf_cnt = 0; + return status; +} + + +static int +ncio_spx_get(ncio *const nciop, + off_t offset, size_t extent, + int rflags, + void **const vpp) +{ + ncio_spx *const pxp = (ncio_spx *)nciop->pvt; + int status = ENOERR; +#ifdef X_ALIGN + size_t rem; +#endif + + if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE)) + return EPERM; /* attempt to write readonly file */ + + assert(extent != 0); + + assert(pxp->bf_cnt == 0); + +#ifdef X_ALIGN + rem = (size_t)(offset % X_ALIGN); + if(rem != 0) + { + offset -= rem; + extent += rem; + } + + { + const size_t rndup = extent % X_ALIGN; + if(rndup != 0) + extent += X_ALIGN - rndup; + } + + assert(offset % X_ALIGN == 0); + assert(extent % X_ALIGN == 0); +#endif + + if(pxp->bf_extent < extent) + { + if(pxp->bf_base != NULL) + { + free(pxp->bf_base); + pxp->bf_base = NULL; + pxp->bf_extent = 0; + } + assert(pxp->bf_extent == 0); + pxp->bf_base = malloc(extent); + if(pxp->bf_base == NULL) + return ENOMEM; + pxp->bf_extent = extent; + } + + status = px_pgin(nciop, offset, + extent, + pxp->bf_base, + &pxp->bf_cnt, &pxp->pos); + if(status != ENOERR) + return status; + + pxp->bf_offset = offset; + + if(pxp->bf_cnt < extent) + pxp->bf_cnt = extent; + +#ifdef X_ALIGN + *vpp = (char *)pxp->bf_base + rem; +#else + *vpp = pxp->bf_base; +#endif + return ENOERR; +} + + +#if 0 +/*ARGSUSED*/ +static int +strategy(ncio *const nciop, off_t to, off_t offset, + size_t extent, int rflags) +{ + static ncio_spx pxp[1]; + int status = ENOERR; +#ifdef X_ALIGN + size_t rem; +#endif + + assert(extent != 0); +#if INSTRUMENT +fprintf(stderr, "strategy %ld at %ld to %ld\n", + (long)extent, (long)offset, (long)to); +#endif + + +#ifdef X_ALIGN + rem = (size_t)(offset % X_ALIGN); + if(rem != 0) + { + offset -= rem; + extent += rem; + } + + { + const size_t rndup = extent % X_ALIGN; + if(rndup != 0) + extent += X_ALIGN - rndup; + } + + assert(offset % X_ALIGN == 0); + assert(extent % X_ALIGN == 0); +#endif + + if(pxp->bf_extent < extent) + { + if(pxp->bf_base != NULL) + { + free(pxp->bf_base); + pxp->bf_base = NULL; + pxp->bf_extent = 0; + } + assert(pxp->bf_extent == 0); + pxp->bf_base = malloc(extent); + if(pxp->bf_base == NULL) + return ENOMEM; + pxp->bf_extent = extent; + } + + status = px_pgin(nciop, offset, + extent, + pxp->bf_base, + &pxp->bf_cnt, &pxp->pos); + if(status != ENOERR) + return status; + + pxp->bf_offset = to; /* TODO: XALIGN */ + + if(pxp->bf_cnt < extent) + pxp->bf_cnt = extent; + + status = px_pgout(nciop, pxp->bf_offset, + pxp->bf_cnt, + pxp->bf_base, &pxp->pos); + /* if error, invalidate buffer anyway */ + pxp->bf_offset = OFF_NONE; + pxp->bf_cnt = 0; + return status; +} +#endif + +static int +ncio_spx_move(ncio *const nciop, off_t to, off_t from, + size_t nbytes, int rflags) +{ + int status = ENOERR; + off_t lower = from; + off_t upper = to; + char *base; + size_t diff = (size_t)(upper - lower); + size_t extent = diff + nbytes; + + rflags &= RGN_NOLOCK; /* filter unwanted flags */ + + if(to == from) + return ENOERR; /* NOOP */ + + if(to > from) + { + /* growing */ + lower = from; + upper = to; + } + else + { + /* shrinking */ + lower = to; + upper = from; + } + + diff = (size_t)(upper - lower); + extent = diff + nbytes; + + status = ncio_spx_get(nciop, lower, extent, RGN_WRITE|rflags, + (void **)&base); + + if(status != ENOERR) + return status; + + if(to > from) + (void) memmove(base + diff, base, nbytes); + else + (void) memmove(base, base + diff, nbytes); + + (void) ncio_spx_rel(nciop, lower, RGN_MODIFIED); + + return status; +} + + +/*ARGSUSED*/ +static int +ncio_spx_sync(ncio *const nciop) +{ + (void)nciop; + /* NOOP */ + return ENOERR; +} + +static void +ncio_spx_free(void *const pvt) +{ + ncio_spx *const pxp = (ncio_spx *)pvt; + if(pxp == NULL) + return; + + if(pxp->bf_base != NULL) + { + free(pxp->bf_base); + pxp->bf_base = NULL; + pxp->bf_offset = OFF_NONE; + pxp->bf_extent = 0; + pxp->bf_cnt = 0; + } +} + + +static int +ncio_spx_init2(ncio *const nciop, const size_t *const sizehintp) +{ + ncio_spx *const pxp = (ncio_spx *)nciop->pvt; + + assert(nciop->fd >= 0); + + pxp->bf_extent = *sizehintp; + + assert(pxp->bf_base == NULL); + + /* this is separate allocation because it may grow */ + pxp->bf_base = malloc(pxp->bf_extent); + if(pxp->bf_base == NULL) + { + pxp->bf_extent = 0; + return ENOMEM; + } + /* else */ + return ENOERR; +} + + +static void +ncio_spx_init(ncio *const nciop) +{ + ncio_spx *const pxp = (ncio_spx *)nciop->pvt; + + *((ncio_relfunc **)&nciop->rel) = ncio_spx_rel; /* cast away const */ + *((ncio_getfunc **)&nciop->get) = ncio_spx_get; /* cast away const */ + *((ncio_movefunc **)&nciop->move) = ncio_spx_move; /* cast away const */ + *((ncio_syncfunc **)&nciop->sync) = ncio_spx_sync; /* cast away const */ + *((ncio_freefunc **)&nciop->free) = ncio_spx_free; /* cast away const */ + + pxp->pos = -1; + pxp->bf_offset = OFF_NONE; + pxp->bf_extent = 0; + pxp->bf_cnt = 0; + pxp->bf_base = NULL; +} + + +/* */ + +static void +ncio_free(ncio *nciop) +{ + if(nciop == NULL) + return; + + if(nciop->free != NULL) + { + ncio_freefunc* func = (ncio_freefunc*)nciop->free; + func(nciop->pvt); + } + + free(nciop); +} + + +static ncio * +ncio_new(const char *path, int ioflags) +{ + size_t sz_ncio = M_RNDUP(sizeof(ncio)); + size_t sz_path = M_RNDUP(strlen(path) +1); + size_t sz_ncio_pvt; + ncio *nciop; + +#if ALWAYS_NC_SHARE /* DEBUG */ + fSet(ioflags, NC_SHARE); +#endif + + if(fIsSet(ioflags, NC_SHARE)) + sz_ncio_pvt = sizeof(ncio_spx); + else + sz_ncio_pvt = sizeof(ncio_px); + + nciop = (ncio *) malloc(sz_ncio + sz_path + sz_ncio_pvt); + if(nciop == NULL) + return NULL; + + nciop->ioflags = ioflags; + *((int *)&nciop->fd) = -1; /* cast away const */ + + nciop->path = (char *) ((char *)nciop + sz_ncio); + (void) strcpy((char *)nciop->path, path); /* cast away const */ + + /* cast away const */ + *((void **)&nciop->pvt) = (void *)(nciop->path + sz_path); + + if(fIsSet(ioflags, NC_SHARE)) + ncio_spx_init(nciop); + else + ncio_px_init(nciop); + + return nciop; +} + + +/* Public below this point */ + +#define NCIO_MINBLOCKSIZE 256 +#define NCIO_MAXBLOCKSIZE 268435456 /* sanity check, about X_SIZE_T_MAX/8 */ + +#if defined( S_IRUSR ) && defined( S_IRGRP ) && defined( S_IWGRP ) && defined( S_IROTH ) && defined( S_IWOTH ) +#define NC_DEFAULT_CREAT_MODE \ + (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) /* 0666 */ + +#else +#define NC_DEFAULT_CREAT_MODE 0666 +#endif + +int +ncio_create(const char *path, int ioflags, + size_t initialsz, + off_t igeto, size_t igetsz, size_t *sizehintp, + ncio **nciopp, void **const igetvpp) +{ + ncio *nciop; + int oflags = (O_RDWR|O_CREAT); + int fd; + int status; + + if(initialsz < (size_t)igeto + igetsz) + initialsz = (size_t)igeto + igetsz; + + fSet(ioflags, NC_WRITE); + + if(path == NULL || *path == 0) + return EINVAL; + + nciop = ncio_new(path, ioflags); + if(nciop == NULL) + return ENOMEM; + + if(fIsSet(ioflags, NC_NOCLOBBER)) + fSet(oflags, O_EXCL); + else + fSet(oflags, O_TRUNC); +#ifdef O_BINARY + fSet(oflags, O_BINARY); +#endif +#ifdef vms + fd = open(path, oflags, NC_DEFAULT_CREAT_MODE, "ctx=stm"); +#else + /* Should we mess with the mode based on NC_SHARE ?? */ + fd = open(path, oflags, NC_DEFAULT_CREAT_MODE); +#endif +#if 0 + (void) fprintf(stderr, "ncio_create(): path=\"%s\"\n", path); + (void) fprintf(stderr, "ncio_create(): oflags=0x%x\n", oflags); +#endif + if(fd < 0) + { + status = errno; + goto unwind_new; + } + *((int *)&nciop->fd) = fd; /* cast away const */ + + if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE) + { + /* Use default */ + *sizehintp = blksize(fd); + } + else + { + *sizehintp = M_RNDUP(*sizehintp); + } +#ifdef __PARAGON__ + *((int *)&nciop->is_file_pfs) = netcdf_local_is_file_pfs; + netcdf_local_is_file_pfs = 0; +#endif + + if(fIsSet(nciop->ioflags, NC_SHARE)) + status = ncio_spx_init2(nciop, sizehintp); + else + status = ncio_px_init2(nciop, sizehintp, 1); + + if(status != ENOERR) + goto unwind_open; + + if(initialsz != 0) + { + status = fgrow(fd, (off_t)initialsz); + if(status != ENOERR) + goto unwind_open; + } + + if(igetsz != 0) + { + status = nciop->get(nciop, + igeto, igetsz, + RGN_WRITE, + igetvpp); + if(status != ENOERR) + goto unwind_open; + } + + *nciopp = nciop; + return ENOERR; + +unwind_open: + (void) close(fd); + /* ?? unlink */ + /*FALLTHRU*/ +unwind_new: + ncio_free(nciop); + return status; +} + + +int +ncio_open(const char *path, + int ioflags, + off_t igeto, size_t igetsz, size_t *sizehintp, + ncio **nciopp, void **const igetvpp) +{ + ncio *nciop; + int oflags = fIsSet(ioflags, NC_WRITE) ? O_RDWR : O_RDONLY; + int fd; + int status; + + if(path == NULL || *path == 0) + return EINVAL; + + nciop = ncio_new(path, ioflags); + if(nciop == NULL) + return ENOMEM; + +#ifdef O_BINARY + fSet(oflags, O_BINARY); +#endif +#ifdef vms + fd = open(path, oflags, 0, "ctx=stm"); +#else + fd = open(path, oflags, 0); +#endif + if(fd < 0) + { + status = errno; + goto unwind_new; + } + *((int *)&nciop->fd) = fd; /* cast away const */ + + if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE) + { + /* Use default */ + *sizehintp = blksize(fd); + } + else + { + *sizehintp = M_RNDUP(*sizehintp); + } + + if(fIsSet(nciop->ioflags, NC_SHARE)) + status = ncio_spx_init2(nciop, sizehintp); + else + status = ncio_px_init2(nciop, sizehintp, 0); + + if(status != ENOERR) + goto unwind_open; + + if(igetsz != 0) + { + status = nciop->get(nciop, + igeto, igetsz, + 0, + igetvpp); + if(status != ENOERR) + goto unwind_open; + } + + *nciopp = nciop; + return ENOERR; + +unwind_open: + (void) close(fd); + /*FALLTHRU*/ +unwind_new: + ncio_free(nciop); + return status; +} + + +int +ncio_close(ncio *nciop, int doUnlink) +{ + int status = ENOERR; + + if(nciop == NULL) + return EINVAL; + + { + ncio_syncfunc* func = (ncio_syncfunc*)(nciop->sync); + status = func(nciop); + } + + (void) close(nciop->fd); + + if(doUnlink) + (void) unlink(nciop->path); + + ncio_free(nciop); + + return status; +} diff --git a/Utilities/vtknetcdf/putget.c b/Utilities/vtknetcdf/putget.c new file mode 100644 index 0000000..b1f837d --- /dev/null +++ b/Utilities/vtknetcdf/putget.c @@ -0,0 +1,11688 @@ +/* Do not edit this file. It is produced from the corresponding .m4 source */ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: putget.c,v 1.3 2005/07/19 23:37:24 andy Exp $ */ + +#include "nc.h" +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include "ncx.h" +#include "fbits.h" +#include "onstack.h" + +#undef MIN /* system may define MIN somewhere and complain */ +#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn)) + +/* #define ODEBUG 1 */ + +#if ODEBUG +#include <stdio.h> +/* + * Print the values of an array of size_t + */ +void +arrayp(const char *label, size_t count, const size_t *array) +{ + (void) fprintf(stderr, "%s", label); + (void) fputc('\t',stderr); + for(; count > 0; count--, array++) + (void) fprintf(stderr," %lu", (unsigned long)*array); + (void) fputc('\n',stderr); +} +#endif /* ODEBUG */ + + +/* Begin fill */ +/* + * This is tunable parameter. + * It essentially controls the tradeoff between the number of times + * memcpy() gets called to copy the external data to fill + * a large buffer vs the number of times its called to + * prepare the external data. + */ +#define NFILL 16 + + + +/* + * Next 6 type specific functions + * Fill a some memory with the default special value. + * Formerly +NC_arrayfill() + */ +static int +NC_fill_schar( + void **xpp, + size_t nelems) /* how many */ +{ + schar fillp[NFILL * sizeof(double)/X_SIZEOF_CHAR]; + + assert(nelems <= sizeof(fillp)/sizeof(fillp[0])); + + { + schar *vp = fillp; /* lower bound of area to be filled */ + const schar *const end = vp + nelems; + while(vp < end) + { + *vp++ = NC_FILL_BYTE; + } + } + return ncx_putn_schar_schar(xpp, nelems, fillp); +} + +static int +NC_fill_char( + void **xpp, + size_t nelems) /* how many */ +{ + char fillp[NFILL * sizeof(double)/X_SIZEOF_CHAR]; + + assert(nelems <= sizeof(fillp)/sizeof(fillp[0])); + + { + char *vp = fillp; /* lower bound of area to be filled */ + const char *const end = vp + nelems; + while(vp < end) + { + *vp++ = NC_FILL_CHAR; + } + } + return ncx_putn_char_char(xpp, nelems, fillp); +} + +static int +NC_fill_short( + void **xpp, + size_t nelems) /* how many */ +{ + short fillp[NFILL * sizeof(double)/X_SIZEOF_SHORT]; + + assert(nelems <= sizeof(fillp)/sizeof(fillp[0])); + + { + short *vp = fillp; /* lower bound of area to be filled */ + const short *const end = vp + nelems; + while(vp < end) + { + *vp++ = NC_FILL_SHORT; + } + } + return ncx_putn_short_short(xpp, nelems, fillp); +} + + +#if (SIZEOF_INT >= X_SIZEOF_INT) +static int +NC_fill_int( + void **xpp, + size_t nelems) /* how many */ +{ + int fillp[NFILL * sizeof(double)/X_SIZEOF_INT]; + + assert(nelems <= sizeof(fillp)/sizeof(fillp[0])); + + { + int *vp = fillp; /* lower bound of area to be filled */ + const int *const end = vp + nelems; + while(vp < end) + { + *vp++ = NC_FILL_INT; + } + } + return ncx_putn_int_int(xpp, nelems, fillp); +} + +#elif SIZEOF_LONG == X_SIZEOF_INT +static int +NC_fill_int( + void **xpp, + size_t nelems) /* how many */ +{ + long fillp[NFILL * sizeof(double)/X_SIZEOF_INT]; + + assert(nelems <= sizeof(fillp)/sizeof(fillp[0])); + + { + long *vp = fillp; /* lower bound of area to be filled */ + const long *const end = vp + nelems; + while(vp < end) + { + *vp++ = NC_FILL_INT; + } + } + return ncx_putn_int_long(xpp, nelems, fillp); +} + +#else +#error "NC_fill_int implementation" +#endif + +static int +NC_fill_float( + void **xpp, + size_t nelems) /* how many */ +{ + float fillp[NFILL * sizeof(double)/X_SIZEOF_FLOAT]; + + assert(nelems <= sizeof(fillp)/sizeof(fillp[0])); + + { + float *vp = fillp; /* lower bound of area to be filled */ + const float *const end = vp + nelems; + while(vp < end) + { + *vp++ = NC_FILL_FLOAT; + } + } + return ncx_putn_float_float(xpp, nelems, fillp); +} + +static int +NC_fill_double( + void **xpp, + size_t nelems) /* how many */ +{ + double fillp[NFILL * sizeof(double)/X_SIZEOF_DOUBLE]; + + assert(nelems <= sizeof(fillp)/sizeof(fillp[0])); + + { + double *vp = fillp; /* lower bound of area to be filled */ + const double *const end = vp + nelems; + while(vp < end) + { + *vp++ = NC_FILL_DOUBLE; + } + } + return ncx_putn_double_double(xpp, nelems, fillp); +} + + + +/* + * Fill the external space for variable 'varp' values at 'recno' + * with the appropriate value. If 'varp' is not a record + * variable, fill the whole thing. + * Formerly +xdr_NC_fill() + */ +int +fill_NC_var(NC *ncp, const NC_var *varp, size_t recno) +{ + char xfillp[NFILL * X_SIZEOF_DOUBLE]; + const size_t step = varp->xsz; + const size_t nelems = sizeof(xfillp)/step; + const size_t xsz = varp->xsz * nelems; + NC_attr **attrpp = NULL; + off_t offset; + size_t remaining = varp->len; + + void *xp; + int status = NC_NOERR; + + /* + * Set up fill value + */ + attrpp = NC_findattr(&varp->attrs, _FillValue); + if( attrpp != NULL ) + { + /* User defined fill value */ + if( (*attrpp)->type != varp->type || (*attrpp)->nelems != 1 ) + { + return NC_EBADTYPE; + } + else + { + /* Use the user defined value */ + char *cp = xfillp; + const char *const end = &xfillp[sizeof(xfillp)]; + + assert(step <= (*attrpp)->xsz); + + for( /*NADA*/; cp < end; cp += step) + { + (void) memcpy(cp, (*attrpp)->xvalue, step); + } + } + } + else + { + /* use the default */ + + assert(xsz % X_ALIGN == 0); + assert(xsz <= sizeof(xfillp)); + + xp = xfillp; + + switch(varp->type){ + case NC_BYTE : + status = NC_fill_schar(&xp, nelems); + break; + case NC_CHAR : + status = NC_fill_char(&xp, nelems); + break; + case NC_SHORT : + status = NC_fill_short(&xp, nelems); + break; + case NC_INT : + status = NC_fill_int(&xp, nelems); + break; + case NC_FLOAT : + status = NC_fill_float(&xp, nelems); + break; + case NC_DOUBLE : + status = NC_fill_double(&xp, nelems); + break; + default : + assert("fill_NC_var invalid type" == 0); + status = NC_EBADTYPE; + break; + } + if(status != NC_NOERR) + return status; + + assert(xp == xfillp + xsz); + } + + /* + * copyout: + * xfillp now contains 'nelems' elements of the fill value + * in external representation. + */ + + /* + * Copy it out. + */ + + offset = varp->begin; + if(IS_RECVAR(varp)) + { + offset += (off_t)ncp->recsize * recno; + } + + assert(remaining > 0); + for(;;) + { + const size_t chunksz = MIN(remaining, ncp->chunk); + size_t ii; + assert(chunksz % X_ALIGN == 0); + + status = ncp->nciop->get(ncp->nciop, offset, chunksz, + RGN_WRITE, &xp); + if(status != NC_NOERR) + { + return status; + } + + /* + * fill the chunksz buffer in units of xsz + */ + for(ii = 0; ii < chunksz/xsz; ii++) + { + (void) memcpy(xp, xfillp, xsz); + xp = (char *)xp + xsz; + } + /* + * Deal with any remainder + */ + { + const size_t rem = chunksz % xsz; + if(rem != 0) + { + (void) memcpy(xp, xfillp, rem); + /* xp = (char *)xp + xsz; */ + } + + } + + status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED); + + if(status != NC_NOERR) + { + break; + } + + remaining -= chunksz; + if(remaining == 0) + break; /* normal loop exit */ + offset += chunksz; + + } + + return status; +} +/* End fill */ + + +/* + * Add a record containing the fill values. + */ +static int +NCfillrecord(NC *ncp, const NC_var *const *varpp, size_t recno) +{ + size_t ii = 0; + for(; ii < ncp->vars.nelems; ii++, varpp++) + { + if( !IS_RECVAR(*varpp) ) + { + continue; /* skip non-record variables */ + } + { + const int status = fill_NC_var(ncp, *varpp, recno); + if(status != NC_NOERR) + return status; + } + } + return NC_NOERR; +} + +/* + * It is advantageous to + * #define TOUCH_LAST + * when using memory mapped io. + */ +#if TOUCH_LAST +/* + * Grow the file to a size which can contain recno + */ +static int +NCtouchlast(NC *ncp, const NC_var *const *varpp, size_t recno) +{ + int status = NC_NOERR; + const NC_var *varp = NULL; + + { + size_t ii = 0; + for(; ii < ncp->vars.nelems; ii++, varpp++) + { + if( !IS_RECVAR(*varpp) ) + { + continue; /* skip non-record variables */ + } + varp = *varpp; + } + } + assert(varp != NULL); + assert( IS_RECVAR(varp) ); + { + const off_t offset = varp->begin + + (off_t)(recno-1) * (off_t)ncp->recsize + + (off_t)(varp->len - varp->xsz); + void *xp; + + + status = ncp->nciop->get(ncp->nciop, offset, varp->xsz, + RGN_WRITE, &xp); + if(status != NC_NOERR) + return status; + (void)memset(xp, 0, varp->xsz); + status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED); + } + return status; +} +#endif /* TOUCH_LAST */ + + +/* + * Ensure that the netcdf file has 'numrecs' records, + * add records and fill as neccessary. + */ +static int +NCvnrecs(NC *ncp, size_t numrecs) +{ + int status = NC_NOERR; + + if(numrecs > ncp->numrecs) + { + + +#if TOUCH_LAST + status = NCtouchlast(ncp, + (const NC_var *const*)ncp->vars.value, + numrecs); + if(status != NC_NOERR) + return status; +#endif /* TOUCH_LAST */ + + set_NC_ndirty(ncp); + + if(!NC_dofill(ncp)) + { + /* Go directly to jail, do not pass go */ + ncp->numrecs = numrecs; + } + else + { + size_t unfilled = numrecs - ncp->numrecs; + size_t ii; + + for(ii = 0; ii < unfilled; ii++, ncp->numrecs++) + { + status = NCfillrecord(ncp, + (const NC_var *const*)ncp->vars.value, + ncp->numrecs); + if(status != NC_NOERR) + { + break; + } + } + if(status != NC_NOERR) + return status; + } + + if(NC_doNsync(ncp)) + { + status = write_numrecs(ncp); + } + + } + return status; +} + + +/* + * Check whether 'coord' values are valid for the variable. + */ +static int +NCcoordck(NC *ncp, const NC_var *varp, const size_t *coord) +{ + const size_t *ip; + size_t *up; + + if(varp->ndims == 0) + return NC_NOERR; /* 'scalar' variable */ + + if(IS_RECVAR(varp)) + { + if(*coord > X_INT_MAX) + return NC_EINVALCOORDS; /* sanity check */ + if(NC_readonly(ncp) && *coord >= ncp->numrecs) + { + if(!NC_doNsync(ncp)) + return NC_EINVALCOORDS; + /* else */ + { + /* Update from disk and check again */ + const int status = read_numrecs(ncp); + if(status != NC_NOERR) + return status; + if(*coord >= ncp->numrecs) + return NC_EINVALCOORDS; + } + } + ip = coord + 1; + up = varp->shape + 1; + } + else + { + ip = coord; + up = varp->shape; + } + +#ifdef CDEBUG +fprintf(stderr," NCcoordck: coord %ld, count %d, ip %ld\n", + coord, varp->ndims, ip ); +#endif /* CDEBUG */ + + for(; ip < coord + varp->ndims; ip++, up++) + { + +#ifdef CDEBUG +fprintf(stderr," NCcoordck: ip %p, *ip %ld, up %p, *up %lu\n", + ip, *ip, up, *up ); +#endif /* CDEBUG */ + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) *ip >= (unsigned long) *up ) + return NC_EINVALCOORDS; + } + + return NC_NOERR; +} + + +/* + * Check whether 'edges' are valid for the variable and 'start' + */ +/*ARGSUSED*/ +static int +NCedgeck(const NC *ncp, const NC_var *varp, + const size_t *start, const size_t *edges) +{ + const size_t *const end = start + varp->ndims; + const size_t *shp = varp->shape; + + (void)ncp; + + if(varp->ndims == 0) + return NC_NOERR; /* 'scalar' variable */ + + if(IS_RECVAR(varp)) + { + start++; + edges++; + shp++; + } + + for(; start < end; start++, edges++, shp++) + { + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) *edges > *shp || + (unsigned long) *start + (unsigned long) *edges > *shp) + { + return(NC_EEDGE); + } + } + return NC_NOERR; +} + + +/* + * Translate the (variable, coord) pair into a seek index + */ +static off_t +NC_varoffset(const NC *ncp, const NC_var *varp, const size_t *coord) +{ + if(varp->ndims == 0) /* 'scalar' variable */ + return varp->begin; + + if(varp->ndims == 1) + { + if(IS_RECVAR(varp)) + return varp->begin + + (off_t)(*coord) * (off_t)ncp->recsize; + /* else */ + return varp->begin + (off_t)(*coord) * (off_t)varp->xsz; + } + /* else */ + { + off_t lcoord = (off_t)coord[varp->ndims -1]; + + size_t *up = varp->dsizes +1; + const size_t *ip = coord; + const size_t *const end = varp->dsizes + varp->ndims; + + if(IS_RECVAR(varp)) + up++, ip++; + + for(; up < end; up++, ip++) + lcoord += *up * *ip; + + lcoord *= varp->xsz; + + if(IS_RECVAR(varp)) + lcoord += (off_t)(*coord) * ncp->recsize; + + lcoord += varp->begin; + return lcoord; + } +} + + + +static int +putNCvx_char_char(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const char *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_char_char(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + + +static int +putNCvx_schar_schar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_schar_schar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_schar_uchar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_schar_uchar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_schar_short(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_schar_short(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_schar_int(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_schar_int(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_schar_long(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_schar_long(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_schar_float(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_schar_float(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_schar_double(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_schar_double(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + + +static int +putNCvx_short_schar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_short_schar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_short_uchar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_short_uchar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_short_short(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_short_short(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_short_int(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_short_int(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_short_long(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_short_long(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_short_float(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_short_float(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_short_double(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_short_double(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + + +static int +putNCvx_int_schar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_int_schar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_int_uchar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_int_uchar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_int_short(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_int_short(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_int_int(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_int_int(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_int_long(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_int_long(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_int_float(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_int_float(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_int_double(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_int_double(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + + +static int +putNCvx_float_schar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_float_schar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_float_uchar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_float_uchar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_float_short(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_float_short(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_float_int(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_float_int(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_float_long(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_float_long(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_float_float(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_float_float(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_float_double(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_float_double(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + + +static int +putNCvx_double_schar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_double_schar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_double_uchar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_double_uchar(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_double_short(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_double_short(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_double_int(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_double_int(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_double_long(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_double_long(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_double_float(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_double_float(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + +static int +putNCvx_double_double(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nput = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + RGN_WRITE, &xp); + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_putn_double_double(&xp, nput, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + { + /* not fatal to the loop */ + status = lstatus; + } + + (void) ncp->nciop->rel(ncp->nciop, offset, + RGN_MODIFIED); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nput; + + } + + return status; +} + + + + +static int +putNCv_text(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const char *value) +{ + if(varp->type != NC_CHAR) + return NC_ECHAR; + return putNCvx_char_char(ncp, varp, start, nelems, value); +} + +static int +putNCv_schar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const schar *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return putNCvx_schar_schar(ncp, varp, start, nelems, + value); + case NC_SHORT: + return putNCvx_short_schar(ncp, varp, start, nelems, + value); + case NC_INT: + return putNCvx_int_schar(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return putNCvx_float_schar(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return putNCvx_double_schar(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +putNCv_uchar(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const uchar *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return putNCvx_schar_uchar(ncp, varp, start, nelems, + value); + case NC_SHORT: + return putNCvx_short_uchar(ncp, varp, start, nelems, + value); + case NC_INT: + return putNCvx_int_uchar(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return putNCvx_float_uchar(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return putNCvx_double_uchar(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +putNCv_short(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const short *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return putNCvx_schar_short(ncp, varp, start, nelems, + value); + case NC_SHORT: + return putNCvx_short_short(ncp, varp, start, nelems, + value); + case NC_INT: + return putNCvx_int_short(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return putNCvx_float_short(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return putNCvx_double_short(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +putNCv_int(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const int *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return putNCvx_schar_int(ncp, varp, start, nelems, + value); + case NC_SHORT: + return putNCvx_short_int(ncp, varp, start, nelems, + value); + case NC_INT: + return putNCvx_int_int(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return putNCvx_float_int(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return putNCvx_double_int(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +putNCv_long(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const long *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return putNCvx_schar_long(ncp, varp, start, nelems, + value); + case NC_SHORT: + return putNCvx_short_long(ncp, varp, start, nelems, + value); + case NC_INT: + return putNCvx_int_long(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return putNCvx_float_long(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return putNCvx_double_long(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +putNCv_float(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const float *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return putNCvx_schar_float(ncp, varp, start, nelems, + value); + case NC_SHORT: + return putNCvx_short_float(ncp, varp, start, nelems, + value); + case NC_INT: + return putNCvx_int_float(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return putNCvx_float_float(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return putNCvx_double_float(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +putNCv_double(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const double *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return putNCvx_schar_double(ncp, varp, start, nelems, + value); + case NC_SHORT: + return putNCvx_short_double(ncp, varp, start, nelems, + value); + case NC_INT: + return putNCvx_int_double(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return putNCvx_float_double(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return putNCvx_double_double(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + + + + +static int +getNCvx_char_char(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, char *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_char_char(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + + +static int +getNCvx_schar_schar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_schar_schar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_schar_uchar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_schar_uchar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_schar_short(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_schar_short(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_schar_int(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_schar_int(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_schar_long(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_schar_long(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_schar_float(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_schar_float(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_schar_double(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_schar_double(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + + +static int +getNCvx_short_schar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_short_schar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_short_uchar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_short_uchar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_short_short(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_short_short(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_short_int(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_short_int(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_short_long(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_short_long(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_short_float(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_short_float(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_short_double(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_short_double(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + + +static int +getNCvx_int_schar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_int_schar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_int_uchar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_int_uchar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_int_short(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_int_short(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_int_int(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_int_int(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_int_long(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_int_long(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_int_float(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_int_float(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_int_double(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_int_double(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + + +static int +getNCvx_float_schar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_float_schar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_float_uchar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_float_uchar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_float_short(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_float_short(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_float_int(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_float_int(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_float_long(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_float_long(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_float_float(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_float_float(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_float_double(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_float_double(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + + +static int +getNCvx_double_schar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, schar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_double_schar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_double_uchar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, uchar *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_double_uchar(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_double_short(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, short *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_double_short(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_double_int(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, int *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_double_int(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_double_long(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, long *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_double_long(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_double_float(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, float *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_double_float(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + +static int +getNCvx_double_double(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, double *value) +{ + off_t offset = NC_varoffset(ncp, varp, start); + size_t remaining = varp->xsz * nelems; + int status = NC_NOERR; + const void *xp; + + if(nelems == 0) + return NC_NOERR; + + assert(value != NULL); + + for(;;) + { + size_t extent = MIN(remaining, ncp->chunk); + size_t nget = ncx_howmany(varp->type, extent); + + int lstatus = ncp->nciop->get(ncp->nciop, offset, extent, + 0, (void **)&xp); /* cast away const */ + if(lstatus != NC_NOERR) + return lstatus; + + lstatus = ncx_getn_double_double(&xp, nget, value); + if(lstatus != NC_NOERR && status == NC_NOERR) + status = lstatus; + + (void) ncp->nciop->rel(ncp->nciop, offset, 0); + + remaining -= extent; + if(remaining == 0) + break; /* normal loop exit */ + offset += extent; + value += nget; + } + + return status; +} + + + + +static int +getNCv_schar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, schar *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return getNCvx_schar_schar(ncp, varp, start, nelems, + value); + case NC_SHORT: + return getNCvx_short_schar(ncp, varp, start, nelems, + value); + case NC_INT: + return getNCvx_int_schar(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return getNCvx_float_schar(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return getNCvx_double_schar(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +getNCv_uchar(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, uchar *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return getNCvx_schar_uchar(ncp, varp, start, nelems, + value); + case NC_SHORT: + return getNCvx_short_uchar(ncp, varp, start, nelems, + value); + case NC_INT: + return getNCvx_int_uchar(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return getNCvx_float_uchar(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return getNCvx_double_uchar(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +getNCv_short(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, short *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return getNCvx_schar_short(ncp, varp, start, nelems, + value); + case NC_SHORT: + return getNCvx_short_short(ncp, varp, start, nelems, + value); + case NC_INT: + return getNCvx_int_short(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return getNCvx_float_short(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return getNCvx_double_short(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +getNCv_int(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, int *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return getNCvx_schar_int(ncp, varp, start, nelems, + value); + case NC_SHORT: + return getNCvx_short_int(ncp, varp, start, nelems, + value); + case NC_INT: + return getNCvx_int_int(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return getNCvx_float_int(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return getNCvx_double_int(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +getNCv_long(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, long *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return getNCvx_schar_long(ncp, varp, start, nelems, + value); + case NC_SHORT: + return getNCvx_short_long(ncp, varp, start, nelems, + value); + case NC_INT: + return getNCvx_int_long(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return getNCvx_float_long(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return getNCvx_double_long(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +getNCv_float(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, float *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return getNCvx_schar_float(ncp, varp, start, nelems, + value); + case NC_SHORT: + return getNCvx_short_float(ncp, varp, start, nelems, + value); + case NC_INT: + return getNCvx_int_float(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return getNCvx_float_float(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return getNCvx_double_float(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + +static int +getNCv_double(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, double *value) +{ + switch(varp->type){ + case NC_CHAR: + return NC_ECHAR; + case NC_BYTE: + return getNCvx_schar_double(ncp, varp, start, nelems, + value); + case NC_SHORT: + return getNCvx_short_double(ncp, varp, start, nelems, + value); + case NC_INT: + return getNCvx_int_double(ncp, varp, start, nelems, + value); + case NC_FLOAT: + return getNCvx_float_double(ncp, varp, start, nelems, + value); + case NC_DOUBLE: + return getNCvx_double_double(ncp, varp, start, nelems, + value); + } + return NC_EBADTYPE; +} + + + +static int +getNCv_text(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, char *value) +{ + if(varp->type != NC_CHAR) + return NC_ECHAR; + return getNCvx_char_char(ncp, varp, start, nelems, value); +} + + +/* + * Copy 'nbytes' contiguous external values + * from ('inncp', invp', inncoord') + * to ('outncp', 'outvp', 'outcoord') + * 'inncp' shouldn't be the same as 'outncp'. + * Used only by ncvarcopy() + */ +static int +NCxvarcpy(NC *inncp, NC_var *invp, size_t *incoord, + NC *outncp, NC_var *outvp, size_t *outcoord, size_t nbytes) +{ + int status; + off_t inoffset = NC_varoffset(inncp, invp, incoord); + off_t outoffset = NC_varoffset(outncp, outvp, outcoord); + void *inxp; + void *outxp; + const size_t chunk = MIN(inncp->chunk, outncp->chunk); + + do { + const size_t extent = MIN(nbytes, chunk); + + status = inncp->nciop->get(inncp->nciop, inoffset, extent, + 0, &inxp); + if(status != NC_NOERR) + return status; + + status = outncp->nciop->get(outncp->nciop, outoffset, extent, + RGN_WRITE, &outxp); + if(status != NC_NOERR) + { + (void) inncp->nciop->rel(inncp->nciop, inoffset, 0); + break; + } + + (void) memcpy(outxp, inxp, extent); + + status = outncp->nciop->rel(outncp->nciop, outoffset, + RGN_MODIFIED); + (void) inncp->nciop->rel(inncp->nciop, inoffset, 0); + + nbytes -= extent; + if(nbytes == 0) + break; /* normal loop exit */ + inoffset += extent; + outoffset += extent; + + } while (status == NC_NOERR); + + return status; +} + + +/* + * For ncvar{put,get}, + * find the largest contiguous block from within 'edges'. + * returns the index to the left of this (which may be -1). + * Compute the number of contiguous elements and return + * that in *iocountp. + * The presence of "record" variables makes this routine + * overly subtle. + */ +static int +NCiocount(const NC *const ncp, const NC_var *const varp, + const size_t *const edges, + size_t *const iocountp) +{ + const size_t *edp0 = edges; + const size_t *edp = edges + varp->ndims; + const size_t *shp = varp->shape + varp->ndims; + + if(IS_RECVAR(varp)) + { + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only 'record' variable */ + *iocountp = *edges; + return(0); + } + /* else */ + edp0++; + } + + assert(edges != NULL); + + /* find max contiguous */ + while(edp > edp0) + { + shp--; edp--; + if(*edp < *shp ) + { + const size_t *zedp = edp; + while(zedp >= edp0) + { + if(*zedp == 0) + { + *iocountp = 0; + goto done; + } + /* Tip of the hat to segmented architectures */ + if(zedp == edp0) + break; + zedp--; + } + break; + } + assert(*edp == *shp); + } + + /* + * edp, shp reference rightmost index s.t. *(edp +1) == *(shp +1) + * + * Or there is only one dimension. + * If there is only one dimension and it is 'non record' dimension, + * edp is &edges[0] and we will return -1. + * If there is only one dimension and and it is a "record dimension", + * edp is &edges[1] (out of bounds) and we will return 0; + */ + assert(shp >= varp->shape + varp->ndims -1 + || *(edp +1) == *(shp +1)); + + /* now accumulate max count for a single io operation */ + for(*iocountp = 1, edp0 = edp; + edp0 < edges + varp->ndims; + edp0++) + { + *iocountp *= *edp0; + } + +done: + return((int)(edp - edges) - 1); +} + + +/* + * Set the elements of the array 'upp' to + * the sum of the corresponding elements of + * 'stp' and 'edp'. 'end' should be &stp[nelems]. + */ +static void +set_upper(size_t *upp, /* modified on return */ + const size_t *stp, + const size_t *edp, + const size_t *const end) +{ + while(upp < end) { + *upp++ = *stp++ + *edp++; + } +} + + +/* + * The infamous and oft-discussed odometer code. + * + * 'start[]' is the starting coordinate. + * 'upper[]' is the upper bound s.t. start[ii] < upper[ii]. + * 'coord[]' is the register, the current coordinate value. + * For some ii, + * upp == &upper[ii] + * cdp == &coord[ii] + * + * Running this routine increments *cdp. + * + * If after the increment, *cdp is equal to *upp + * (and cdp is not the leftmost dimension), + * *cdp is "zeroed" to the starting value and + * we need to "carry", eg, increment one place to + * the left. + * + * TODO: Some architectures hate recursion? + * Reimplement non-recursively. + */ +static void +odo1(const size_t *const start, const size_t *const upper, + size_t *const coord, /* modified on return */ + const size_t *upp, + size_t *cdp) +{ + assert(coord <= cdp && cdp <= coord + NC_MAX_DIMS); + assert(upper <= upp && upp <= upper + NC_MAX_DIMS); + assert(upp - upper == cdp - coord); + + assert(*cdp <= *upp); + + (*cdp)++; + if(cdp != coord && *cdp >= *upp) + { + *cdp = start[cdp - coord]; + odo1(start, upper, coord, upp -1, cdp -1); + } +} +#ifdef _CRAYC +#pragma _CRI noinline odo1 +#endif + + + + +/* Public */ + + +int +nc_put_var1_text(int ncid, int varid, const size_t *coord, + const char *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_text(ncp, varp, coord, 1, value); +} + + +int +nc_put_var1_uchar(int ncid, int varid, const size_t *coord, + const uchar *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_uchar(ncp, varp, coord, 1, value); +} + +int +nc_put_var1_schar(int ncid, int varid, const size_t *coord, + const schar *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_schar(ncp, varp, coord, 1, value); +} + +int +nc_put_var1_short(int ncid, int varid, const size_t *coord, + const short *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_short(ncp, varp, coord, 1, value); +} + +int +nc_put_var1_int(int ncid, int varid, const size_t *coord, + const int *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_int(ncp, varp, coord, 1, value); +} + +int +nc_put_var1_long(int ncid, int varid, const size_t *coord, + const long *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_long(ncp, varp, coord, 1, value); +} + +int +nc_put_var1_float(int ncid, int varid, const size_t *coord, + const float *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_float(ncp, varp, coord, 1, value); +} + +int +nc_put_var1_double(int ncid, int varid, const size_t *coord, + const double *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *coord +1); + if(status != NC_NOERR) + return status; + } + + return putNCv_double(ncp, varp, coord, 1, value); +} + + + +/* deprecated, used to support the 2.x interface */ +int +nc_put_var1(int ncid, int varid, const size_t *coord, const void *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + switch(varp->type){ + case NC_CHAR: + return nc_put_var1_text(ncid, varid, coord, + (const char *) value); + case NC_BYTE: + return nc_put_var1_schar(ncid, varid, coord, + (const schar *) value); + case NC_SHORT: + return nc_put_var1_short(ncid, varid, coord, + (const short *) value); + case NC_INT: + return nc_put_var1_int(ncid, varid, coord, + (const int *) value); + case NC_FLOAT: + return nc_put_var1_float(ncid, varid, coord, + (const float *) value); + case NC_DOUBLE: + return nc_put_var1_double(ncid, varid, coord, + (const double *) value); + } + return NC_EBADTYPE; +} + + + +int +nc_get_var1_text(int ncid, int varid, const size_t *coord, char *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_text(ncp, varp, coord, 1, value); +} + + +int +nc_get_var1_uchar(int ncid, int varid, const size_t *coord, uchar *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_uchar(ncp, varp, coord, 1, value); +} + +int +nc_get_var1_schar(int ncid, int varid, const size_t *coord, schar *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_schar(ncp, varp, coord, 1, value); +} + +int +nc_get_var1_short(int ncid, int varid, const size_t *coord, short *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_short(ncp, varp, coord, 1, value); +} + +int +nc_get_var1_int(int ncid, int varid, const size_t *coord, int *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_int(ncp, varp, coord, 1, value); +} + +int +nc_get_var1_long(int ncid, int varid, const size_t *coord, long *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_long(ncp, varp, coord, 1, value); +} + +int +nc_get_var1_float(int ncid, int varid, const size_t *coord, float *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_float(ncp, varp, coord, 1, value); +} + +int +nc_get_var1_double(int ncid, int varid, const size_t *coord, double *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, coord); + if(status != NC_NOERR) + return status; + + return getNCv_double(ncp, varp, coord, 1, value); +} + + +/* deprecated, used to support the 2.x interface */ +int +nc_get_var1(int ncid, int varid, const size_t *coord, void *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + switch(varp->type){ + case NC_CHAR: + return nc_get_var1_text(ncid, varid, coord, + (char *) value); + case NC_BYTE: + return nc_get_var1_schar(ncid, varid, coord, + (schar *) value); + case NC_SHORT: + return nc_get_var1_short(ncid, varid, coord, + (short *) value); + case NC_INT: + return nc_get_var1_int(ncid, varid, coord, + (int *) value); + case NC_FLOAT: + return nc_get_var1_float(ncid, varid, coord, + (float *) value); + case NC_DOUBLE: + return nc_get_var1_double(ncid, varid, coord, + (double *) value); + } + return NC_EBADTYPE; +} + + + +int +nc_put_vara_text(int ncid, int varid, + const size_t *start, const size_t *edges, const char *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_text(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_text(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_text(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_text(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + + +int +nc_put_vara_uchar(int ncid, int varid, + const size_t *start, const size_t *edges, const uchar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_uchar(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_uchar(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_uchar(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_uchar(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_put_vara_schar(int ncid, int varid, + const size_t *start, const size_t *edges, const schar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_schar(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_schar(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_schar(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_schar(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_put_vara_short(int ncid, int varid, + const size_t *start, const size_t *edges, const short *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_short(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_short(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_short(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_short(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_put_vara_int(int ncid, int varid, + const size_t *start, const size_t *edges, const int *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_int(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_int(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_int(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_int(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_put_vara_long(int ncid, int varid, + const size_t *start, const size_t *edges, const long *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_long(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_long(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_long(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_long(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_put_vara_float(int ncid, int varid, + const size_t *start, const size_t *edges, const float *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_float(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_float(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_float(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_float(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_put_vara_double(int ncid, int varid, + const size_t *start, const size_t *edges, const double *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( putNCv_double(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + status = NCvnrecs(ncp, *start + *edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( putNCv_double(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( putNCv_double(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = putNCv_double(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + + + +/* deprecated, used to support the 2.x interface */ +int +nc_put_vara(int ncid, int varid, + const size_t *start, const size_t *edges, const void *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + switch(varp->type){ + case NC_CHAR: + return nc_put_vara_text(ncid, varid, start, edges, + (const char *) value); + case NC_BYTE: + return nc_put_vara_schar(ncid, varid, start, edges, + (const schar *) value); + case NC_SHORT: + return nc_put_vara_short(ncid, varid, start, edges, + (const short *) value); + case NC_INT: + return nc_put_vara_int(ncid, varid, start, edges, + (const int *) value); + case NC_FLOAT: + return nc_put_vara_float(ncid, varid, start, edges, + (const float *) value); + case NC_DOUBLE: + return nc_put_vara_double(ncid, varid, start, edges, + (const double *) value); + } + return NC_EBADTYPE; +} + + + +int +nc_get_vara_text(int ncid, int varid, + const size_t *start, const size_t *edges, char *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_text(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_text(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_text(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_text(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + + +int +nc_get_vara_uchar(int ncid, int varid, + const size_t *start, const size_t *edges, uchar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_uchar(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_uchar(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_uchar(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_uchar(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_get_vara_schar(int ncid, int varid, + const size_t *start, const size_t *edges, schar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_schar(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_schar(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_schar(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_schar(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_get_vara_short(int ncid, int varid, + const size_t *start, const size_t *edges, short *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_short(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_short(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_short(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_short(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_get_vara_int(int ncid, int varid, + const size_t *start, const size_t *edges, int *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_int(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_int(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_int(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_int(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_get_vara_long(int ncid, int varid, + const size_t *start, const size_t *edges, long *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_long(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_long(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_long(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_long(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_get_vara_float(int ncid, int varid, + const size_t *start, const size_t *edges, float *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_float(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_float(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_float(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_float(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + +int +nc_get_vara_double(int ncid, int varid, + const size_t *start, const size_t *edges, double *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + int ii; + size_t iocount; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + status = NCcoordck(ncp, varp, start); + if(status != NC_NOERR) + return status; + status = NCedgeck(ncp, varp, start, edges); + if(status != NC_NOERR) + return status; + + if(varp->ndims == 0) /* scalar variable */ + { + return( getNCv_double(ncp, varp, start, 1, value) ); + } + + if(IS_RECVAR(varp)) + { + if(*start + *edges > ncp->numrecs) + return NC_EEDGE; + if(varp->ndims == 1 && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return( getNCv_double(ncp, varp, start, *edges, value) ); + } + } + + /* + * find max contiguous + * and accumulate max count for a single io operation + */ + ii = NCiocount(ncp, varp, edges, &iocount); + + if(ii == -1) + { + return( getNCv_double(ncp, varp, start, iocount, value) ); + } + + assert(ii >= 0); + + + { /* inline */ + ALLOC_ONSTACK(coord, size_t, varp->ndims); + ALLOC_ONSTACK(upper, size_t, varp->ndims); + const size_t index = ii; + + /* copy in starting indices */ + (void) memcpy(coord, start, varp->ndims * sizeof(size_t)); + + /* set up in maximum indices */ + set_upper(upper, start, edges, &upper[varp->ndims]); + + /* ripple counter */ + while(*coord < *upper) + { + const int lstatus = getNCv_double(ncp, varp, coord, iocount, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += iocount; + odo1(start, upper, coord, &upper[index], &coord[index]); + } + + FREE_ONSTACK(upper); + FREE_ONSTACK(coord); + } /* end inline */ + + return status; +} + + + +/* deprecated, used to support the 2.x interface */ +int +nc_get_vara(int ncid, int varid, + const size_t *start, const size_t *edges, void *value) +{ + int status; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + switch(varp->type){ + case NC_CHAR: + return nc_get_vara_text(ncid, varid, start, edges, + (char *) value); + case NC_BYTE: + return nc_get_vara_schar(ncid, varid, start, edges, + (schar *) value); + case NC_SHORT: + return nc_get_vara_short(ncid, varid, start, edges, + (short *) value); + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + return nc_get_vara_int(ncid, varid, start, edges, + (int *) value); +#elif SIZEOF_LONG == X_SIZEOF_INT + return nc_get_vara_long(ncid, varid, start, edges, + (long *) value); +#else +#error "nc_get_vara implementation" +#endif + case NC_FLOAT: + return nc_get_vara_float(ncid, varid, start, edges, + (float *) value); + case NC_DOUBLE: + return nc_get_vara_double(ncid, varid, start, edges, + (double *) value); + } + return NC_EBADTYPE; +} + +#if 1 /* defined(__cplusplus) */ +/* C++ consts default to internal linkage and must be initialized */ +static const size_t coord_zero[NC_MAX_VAR_DIMS] = {0}; +#else +static const size_t coord_zero[NC_MAX_VAR_DIMS]; +#endif + + +int +nc_put_var_text(int ncid, int varid, const char *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_text(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_text(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_text(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_text(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + + +int +nc_put_var_uchar(int ncid, int varid, const uchar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_uchar(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_uchar(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_uchar(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_uchar(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_put_var_schar(int ncid, int varid, const schar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_schar(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_schar(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_schar(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_schar(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_put_var_short(int ncid, int varid, const short *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_short(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_short(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_short(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_short(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_put_var_int(int ncid, int varid, const int *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_int(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_int(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_int(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_int(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_put_var_long(int ncid, int varid, const long *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_long(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_long(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_long(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_long(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_put_var_float(int ncid, int varid, const float *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_float(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_float(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_float(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_float(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_put_var_double(int ncid, int varid, const double *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + return NC_EPERM; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( putNCv_double(ncp, varp, &zed, 1, value) ); + } + + if(!IS_RECVAR(varp)) + { + return(putNCv_double(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(putNCv_double(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = putNCv_double(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + + + + +int +nc_get_var_text(int ncid, int varid, char *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_text(ncp, varp, &zed, 1, value) ); + } + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_text(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_text(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_text(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + + +int +nc_get_var_uchar(int ncid, int varid, uchar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_uchar(ncp, varp, &zed, 1, value) ); + } + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_uchar(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_uchar(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_uchar(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_get_var_schar(int ncid, int varid, schar *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_schar(ncp, varp, &zed, 1, value) ); + } + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_schar(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_schar(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_schar(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_get_var_short(int ncid, int varid, short *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_short(ncp, varp, &zed, 1, value) ); + } + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_short(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_short(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_short(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_get_var_int(int ncid, int varid, int *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_int(ncp, varp, &zed, 1, value) ); + } + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_int(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_int(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_int(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_get_var_long(int ncid, int varid, long *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_long(ncp, varp, &zed, 1, value) ); + } + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_long(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_long(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_long(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_get_var_float(int ncid, int varid, float *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_float(ncp, varp, &zed, 1, value) ); + } + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_float(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_float(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_float(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + +int +nc_get_var_double(int ncid, int varid, double *value) +{ + int status = NC_NOERR; + NC *ncp; + const NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + return NC_EINDEFINE; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */ + + if(varp->ndims == 0) /* scalar variable */ + { + const size_t zed = 0; + return( getNCv_double(ncp, varp, &zed, 1, value) ); + } + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + + if(!IS_RECVAR(varp)) + { + return(getNCv_double(ncp, varp, coord_zero, *varp->dsizes, value)); + } + /* else */ + + if(varp->ndims == 1 + && ncp->recsize <= varp->len) + { + /* one dimensional && the only record variable */ + return(getNCv_double(ncp, varp, coord_zero, ncp->numrecs, value)); + } + /* else */ + + { + ALLOC_ONSTACK(coord, size_t, varp->ndims); + size_t elemsPerRec = 1; + (void) memset(coord, 0, varp->ndims * sizeof(size_t)); + /* TODO: fix dsizes to avoid this nonsense */ + if(varp->ndims > 1) + elemsPerRec = varp->dsizes[1]; + while(*coord < ncp->numrecs) + { + const int lstatus = getNCv_double(ncp, varp, coord, elemsPerRec, + value); + if(lstatus != NC_NOERR) + { + if(lstatus != NC_ERANGE) + { + status = lstatus; + /* fatal for the loop */ + break; + } + /* else NC_ERANGE, not fatal for the loop */ + if(status == NC_NOERR) + status = lstatus; + } + value += elemsPerRec; + (*coord)++; + } + FREE_ONSTACK(coord); + } /* elemsPerRec */ + + return status; +} + + + +/* Begin putgetg.c */ + + + +int +nc_get_vars_text ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + char *value) +{ + return nc_get_varm_text (ncid, varid, start, edges, + stride, 0, value); +} + + +int +nc_get_vars_uchar ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + uchar *value) +{ + return nc_get_varm_uchar (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_get_vars_schar ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + schar *value) +{ + return nc_get_varm_schar (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_get_vars_short ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + short *value) +{ + return nc_get_varm_short (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_get_vars_int ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + int *value) +{ + return nc_get_varm_int (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_get_vars_long ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + long *value) +{ + return nc_get_varm_long (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_get_vars_float ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + float *value) +{ + return nc_get_varm_float (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_get_vars_double ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + double *value) +{ + return nc_get_varm_double (ncid, varid, start, edges, + stride, 0, value); +} + + +int +nc_get_vars ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + void *value) +{ + return nc_get_varm (ncid, varid, start, edges, + stride, 0, value); +} + + + +int +nc_put_vars_text ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const char *value) +{ + return nc_put_varm_text (ncid, varid, start, edges, + stride, 0, value); +} + + +int +nc_put_vars_uchar ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const uchar *value) +{ + return nc_put_varm_uchar (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_put_vars_schar ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const schar *value) +{ + return nc_put_varm_schar (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_put_vars_short ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const short *value) +{ + return nc_put_varm_short (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_put_vars_int ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const int *value) +{ + return nc_put_varm_int (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_put_vars_long ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const long *value) +{ + return nc_put_varm_long (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_put_vars_float ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const float *value) +{ + return nc_put_varm_float (ncid, varid, start, edges, + stride, 0, value); +} + +int +nc_put_vars_double ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const double *value) +{ + return nc_put_varm_double (ncid, varid, start, edges, + stride, 0, value); +} + + +int +nc_put_vars ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const void *value) +{ + return nc_put_varm (ncid, varid, start, edges, + stride, 0, value); +} + + +/* + * Generalized hyperslab input. + */ + +int +nc_get_varm_text(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + char *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_text (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_text() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_text (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + + +int +nc_get_varm_uchar(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + uchar *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_uchar (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_uchar() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_uchar (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_get_varm_schar(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + schar *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_schar (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_schar() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_schar (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_get_varm_short(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + short *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_short (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_short() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_short (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_get_varm_int(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + int *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_int (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_int() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_int (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_get_varm_long(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + long *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_long (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_long() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_long (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_get_varm_float(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + float *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_float (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_float() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_float (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_get_varm_double(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, + const ptrdiff_t *map, + double *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return getNCv_double (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = maxidim; idim >= 0; --idim) + { + size_t dimlen = + idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs : varp->shape[idim]; + if (mystart[idim] >= dimlen) + { + status = NC_EINVALCOORDS; + goto done; + } + + if (mystart[idim] + myedges[idim] > dimlen) + { + status = NC_EEDGE; + goto done; + } + + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_get_vara_double() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_get_vara_double (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + + +/* deprecated, used to support the 2.x interface */ +int +nc_get_varm ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const ptrdiff_t * map, + void *value) +{ + int status; + NC *ncp; + const NC_var *varp; + ptrdiff_t *cvtmap = NULL; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(map != NULL && varp->ndims != 0) + { + /* + * convert map units from bytes to units of sizeof(type) + */ + size_t ii; + const ptrdiff_t szof = (ptrdiff_t) nctypelen(varp->type); + cvtmap = (ptrdiff_t *)calloc(varp->ndims, sizeof(ptrdiff_t)); + if(cvtmap == NULL) + return NC_ENOMEM; + for(ii = 0; ii < varp->ndims; ii++) + { + if(map[ii] % szof != 0) + { + free(cvtmap); + return NC_EINVAL; + } + cvtmap[ii] = map[ii] / szof; + } + map = cvtmap; + } + + switch(varp->type){ + case NC_CHAR: + status = nc_get_varm_text(ncid, varid, start, edges, + stride, map, + (char *) value); + break; + case NC_BYTE: + status = nc_get_varm_schar(ncid, varid, start, edges, + stride, map, + (schar *) value); + break; + case NC_SHORT: + status = nc_get_varm_short(ncid, varid, start, edges, + stride, map, + (short *) value); + break; + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + status = nc_get_varm_int(ncid, varid, start, edges, + stride, map, + (int *) value); +#elif SIZEOF_LONG == X_SIZEOF_INT + status = nc_get_varm_long(ncid, varid, start, edges, + stride, map, + (long *) value); +#else +#error "nc_get_varm implementation" +#endif + break; + case NC_FLOAT: + status = nc_get_varm_float(ncid, varid, start, edges, + stride, map, + (float *) value); + break; + case NC_DOUBLE: + status = nc_get_varm_double(ncid, varid, start, edges, + stride, map, + (double *) value); + break; + default: + status = NC_EBADTYPE; + break; + } + + if(cvtmap != NULL) + { + free(cvtmap); + } + return status; +} + + +/* + * Generalized hyperslab output. + */ + +int +nc_put_varm_text(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const char *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type != NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_text (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_text() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_text (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + + +int +nc_put_varm_uchar(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const uchar *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_uchar (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_uchar() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_uchar (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_put_varm_schar(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const schar *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_schar (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_schar() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_schar (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_put_varm_short(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const short *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_short (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_short() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_short (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_put_varm_int(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const int *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_int (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_int() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_int (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_put_varm_long(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const long *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_long (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_long() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_long (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_put_varm_float(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const float *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_float (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_float() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_float (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + +int +nc_put_varm_double(int ncid, int varid, + const size_t *start, const size_t *edges, + const ptrdiff_t *stride, const ptrdiff_t *map, + const double *value) +{ + int status = ENOERR; + NC *ncp; + NC_var *varp; + int maxidim; /* maximum dimensional index */ + + status = NC_check_id (ncid, &ncp); + if (status != NC_NOERR) + return status; + + if (NC_indef (ncp)) + { + return NC_EINDEFINE; + } + + if (NC_readonly (ncp)) + return NC_EPERM; + varp = NC_lookupvar (ncp, varid); + if (varp == NULL) + return NC_ENOTVAR; + + if(varp->type == NC_CHAR) + return NC_ECHAR; + + maxidim = (int) varp->ndims - 1; + + if (maxidim < 0) + { + /* + * The variable is a scalar; consequently, + * there s only one thing to get and only one place to put it. + * (Why was I called?) + */ + return putNCv_double (ncp, varp, start, 1, value); + } + + /* + * else + * The variable is an array. + */ + { + int idim; + size_t *mystart = NULL; + size_t *myedges; + size_t *iocount; /* count vector */ + size_t *stop; /* stop indexes */ + size_t *length; /* edge lengths in bytes */ + ptrdiff_t *mystride; + ptrdiff_t *mymap; + + /* + * Verify stride argument. + */ + for (idim = 0; idim <= maxidim; ++idim) + { + if (stride != NULL + && (stride[idim] == 0 + /* cast needed for braindead systems with signed size_t */ + || (unsigned long) stride[idim] >= X_INT_MAX)) + { + return NC_ESTRIDE; + } + } + + /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */ + mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t)); + if(mystart == NULL) + return NC_ENOMEM; + myedges = mystart + varp->ndims; + iocount = myedges + varp->ndims; + stop = iocount + varp->ndims; + length = stop + varp->ndims; + mystride = (ptrdiff_t *)(length + varp->ndims); + mymap = mystride + varp->ndims; + + /* + * Initialize I/O parameters. + */ + for (idim = maxidim; idim >= 0; --idim) + { + mystart[idim] = start != NULL + ? start[idim] + : 0; + + if (edges[idim] == 0) + { + status = NC_NOERR; /* read/write no data */ + goto done; + } + + myedges[idim] = edges != NULL + ? edges[idim] + : idim == 0 && IS_RECVAR (varp) + ? ncp->numrecs - mystart[idim] + : varp->shape[idim] - mystart[idim]; + mystride[idim] = stride != NULL + ? stride[idim] + : 1; + mymap[idim] = map != NULL + ? map[idim] + : idim == maxidim + ? 1 + : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]; + + iocount[idim] = 1; + length[idim] = mymap[idim] * myedges[idim]; + stop[idim] = mystart[idim] + myedges[idim] * mystride[idim]; + } + + /* + * Check start, edges + */ + for (idim = IS_RECVAR (varp); idim < maxidim; ++idim) + { + if (mystart[idim] >= varp->shape[idim]) + { + status = NC_EINVALCOORDS; + goto done; + } + if (mystart[idim] + myedges[idim] > varp->shape[idim]) + { + status = NC_EEDGE; + goto done; + } + } + /* + * As an optimization, adjust I/O parameters when the fastest + * dimension has unity stride both externally and internally. + * In this case, the user could have called a simpler routine + * (i.e. ncvarnc_put_vara_double() + */ + if (mystride[maxidim] == 1 + && mymap[maxidim] == 1) + { + iocount[maxidim] = myedges[maxidim]; + mystride[maxidim] = (ptrdiff_t) myedges[maxidim]; + mymap[maxidim] = (ptrdiff_t) length[maxidim]; + } + + /* + * Perform I/O. Exit when done. + */ + for (;;) + { + /* TODO: */ + int lstatus = nc_put_vara_double (ncid, varid, mystart, iocount, + value); + if (lstatus != NC_NOERR + && (status == NC_NOERR || lstatus != NC_ERANGE)) + status = lstatus; + + /* + * The following code permutes through the variable s + * external start-index space and it s internal address + * space. At the UPC, this algorithm is commonly + * called "odometer code". + */ + idim = maxidim; + carry: + value += mymap[idim]; + mystart[idim] += mystride[idim]; + if (mystart[idim] == stop[idim]) + { + mystart[idim] = start[idim]; + value -= length[idim]; + if (--idim < 0) + break; /* normal return */ + goto carry; + } + } /* I/O loop */ + done: + free(mystart); + } /* variable is array */ + return status; + +} + + + +/* deprecated, used to support the 2.x interface */ +int +nc_put_varm ( + int ncid, + int varid, + const size_t * start, + const size_t * edges, + const ptrdiff_t * stride, + const ptrdiff_t * map, + const void *value) +{ + int status; + NC *ncp; + const NC_var *varp; + ptrdiff_t *cvtmap = NULL; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(map != NULL && varp->ndims != 0) + { + /* + * convert map units from bytes to units of sizeof(type) + */ + size_t ii; + const ptrdiff_t szof = (ptrdiff_t) nctypelen(varp->type); + cvtmap = (ptrdiff_t *)calloc(varp->ndims, sizeof(ptrdiff_t)); + if(cvtmap == NULL) + return NC_ENOMEM; + for(ii = 0; ii < varp->ndims; ii++) + { + if(map[ii] % szof != 0) + { + free(cvtmap); + return NC_EINVAL; + } + cvtmap[ii] = map[ii] / szof; + } + map = cvtmap; + } + + switch(varp->type){ + case NC_CHAR: + status = nc_put_varm_text(ncid, varid, start, edges, + stride, map, + (const char *) value); + break; + case NC_BYTE: + status = nc_put_varm_schar(ncid, varid, start, edges, + stride, map, + (const schar *) value); + break; + case NC_SHORT: + status = nc_put_varm_short(ncid, varid, start, edges, + stride, map, + (const short *) value); + break; + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + status = nc_put_varm_int(ncid, varid, start, edges, + stride, map, + (const int *) value); +#elif SIZEOF_LONG == X_SIZEOF_INT + status = nc_put_varm_long(ncid, varid, start, edges, + stride, map, + (const long *) value); +#else +#error "nc_put_varm implementation" +#endif + break; + case NC_FLOAT: + status = nc_put_varm_float(ncid, varid, start, edges, + stride, map, + (const float *) value); + break; + case NC_DOUBLE: + status = nc_put_varm_double(ncid, varid, start, edges, + stride, map, + (const double *) value); + break; + default: + status = NC_EBADTYPE; + break; + } + + if(cvtmap != NULL) + { + free(cvtmap); + } + return status; +} + + +/* Begin recio, deprecated */ + +/* + * input 'nelems' items of contiguous data of 'varp' at 'start' + * N.B. this function deprecated. + */ +static int +getNCvdata(const NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, void *value) +{ + switch(varp->type){ + case NC_CHAR: + return getNCvx_char_char(ncp, varp, start, nelems, + (char *) value); + case NC_BYTE: + return getNCvx_schar_schar(ncp, varp, start, nelems, + (schar *) value); + case NC_SHORT: + return getNCvx_short_short(ncp, varp, start, nelems, + (short *) value); + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + return getNCvx_int_int(ncp, varp, start, nelems, + (int *) value); +#elif SIZEOF_LONG == X_SIZEOF_INT + return getNCvx_int_long(ncp, varp, start, nelems, + (long *) value); +#else +#error "getNCvdata implementation" +#endif + case NC_FLOAT: + return getNCvx_float_float(ncp, varp, start, nelems, + (float *) value); + case NC_DOUBLE: + return getNCvx_double_double(ncp, varp, start, nelems, + (double *) value); + } + return NC_EBADTYPE; +} + + +/* + * output 'nelems' items of contiguous data of 'varp' at 'start' + * N.B. this function deprecated. + */ +static int +putNCvdata(NC *ncp, const NC_var *varp, + const size_t *start, size_t nelems, const void *value) +{ + switch(varp->type){ + case NC_CHAR: + return putNCvx_char_char(ncp, varp, start, nelems, + (const char *) value); + case NC_BYTE: + return putNCvx_schar_schar(ncp, varp, start, nelems, + (const schar *) value); + case NC_SHORT: + return putNCvx_short_short(ncp, varp, start, nelems, + (const short *) value); + case NC_INT: +#if (SIZEOF_INT >= X_SIZEOF_INT) + return putNCvx_int_int(ncp, varp, start, nelems, + (const int *) value); +#elif SIZEOF_LONG == X_SIZEOF_INT + return putNCvx_long_int(ncp, varp, start, nelems, + (const long *) value); +#else +#error "putNCvdata implementation" +#endif + case NC_FLOAT: + return putNCvx_float_float(ncp, varp, start, nelems, + (const float *) value); + case NC_DOUBLE: + return putNCvx_double_double(ncp, varp, start, nelems, + (const double *) value); + } + return NC_EBADTYPE; +} + + +static size_t +NCelemsPerRec( + const NC_var *varp) +{ + size_t nelems = 1; + size_t jj; + for(jj = 1; jj < varp->ndims; jj++) + nelems *= varp->shape[jj]; + return nelems; +} + + +/* + * Retrieves the number of record variables, the record variable ids, and the + * record size of each record variable. If any pointer to info to be returned + * is null, the associated information is not returned. Returns -1 on error. + */ +int +nc_inq_rec( + int ncid, + size_t *nrecvars, + int *recvarids, + size_t *recsizes) +{ + NC *ncp; + + { + const int status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + } + + { + size_t nrvars = 0; + size_t ii = 0; + for(; ii < ncp->vars.nelems; ii++) + { + const NC_var *const varp = ncp->vars.value[ii]; + if(!IS_RECVAR(varp)) + continue; + + if(recvarids != NULL) + recvarids[nrvars] = (int) ii; + if(recsizes != NULL) + { + *recsizes++ = nctypelen(varp->type) + * NCelemsPerRec(varp); + } + nrvars++; + } + + if(nrecvars != NULL) + *nrecvars = nrvars; + } + + return NC_NOERR; +} + + +static int +NCrecput( + NC *ncp, + size_t recnum, + void *const *datap) +{ + int status = NC_NOERR; + size_t nrvars = 0; + NC_var *varp; + size_t ii; + size_t iocount; + ALLOC_ONSTACK(coord, size_t, ncp->dims.nelems); + + assert(ncp->dims.nelems != 0); + + (void) memset(coord, 0, ncp->dims.nelems * sizeof(size_t)); + coord[0] = recnum; + for(ii = 0; ii < ncp->vars.nelems; ii++) + { + varp = ncp->vars.value[ii]; + if(!IS_RECVAR(varp)) + continue; + /* else */ + nrvars++; + if(*datap == NULL) + { + datap++; + continue; + } + /* else */ + iocount = NCelemsPerRec(varp); + status = putNCvdata(ncp, varp, coord, iocount, *datap++); + if(status != NC_NOERR) + break; + } + if(nrvars == 0 && status == NC_NOERR) + { + status = NC_ENORECVARS; + } + + FREE_ONSTACK(coord); + return status; +} + + +static int +NCrecget( + NC *ncp, + size_t recnum, + void **datap) +{ + int status = NC_NOERR; + size_t nrvars = 0; + NC_var *varp; + size_t ii; + size_t iocount; + ALLOC_ONSTACK(coord, size_t, ncp->dims.nelems); + + assert(ncp->dims.nelems != 0); + + (void) memset(coord, 0, ncp->dims.nelems * sizeof(size_t)); + coord[0] = recnum; + for(ii = 0; ii < ncp->vars.nelems; ii++) + { + varp = ncp->vars.value[ii]; + if(!IS_RECVAR(varp)) + continue; + /* else */ + nrvars++; + if(*datap == NULL) + { + datap++; + continue; + } + /* else */ + iocount = NCelemsPerRec(varp); + status = getNCvdata(ncp, varp, coord, iocount, *datap++); + if(status != NC_NOERR) + break; + } + if(nrvars == 0 && status == NC_NOERR) + { + status = NC_ENORECVARS; + } + + FREE_ONSTACK(coord); + return status; +} + + +/* + * Write one record's worth of data, except don't write to variables for which + * the address of the data to be written is null. Return -1 on error. + */ +int +nc_put_rec( + int ncid, + size_t recnum, + void * const *datap) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + { + return NC_EPERM; + } + + if(NC_indef(ncp)) + { + return NC_EINDEFINE; + } + + status = NCvnrecs(ncp, recnum +1); + if(status != NC_NOERR) + return status; + + return( NCrecput(ncp, recnum, datap) ); +} + + +/* + * Read one record's worth of data, except don't read from variables for which + * the address of the data to be read is null. Return -1 on error; + */ +int +nc_get_rec( + int ncid, + size_t recnum, + void **datap) +{ + int status; + NC *ncp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_indef(ncp)) + { + return NC_EINDEFINE; + } + + if(recnum >= ncp->numrecs) + { + return NC_EINVALCOORDS; + } + + return( NCrecget(ncp, recnum, datap) ); +} + + +/* + * Copy the values of a variable from an input netCDF to an output netCDF. + * Input and output var assummed to have the same shape. + * return -1 on error. + */ +int +nc_copy_var(int ncid_in, int varid, int ncid_out) +{ + int status = NC_NOERR; + NC *inncp, *outncp; + NC_var *invp, *outvp; + + status = NC_check_id(ncid_in, &inncp); + if(status != NC_NOERR) + return status; + + + if(NC_indef(inncp)) + { + return NC_EINDEFINE; + } + + status = NC_check_id(ncid_out, &outncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(outncp)) + { + /* output file isn't writable */ + return NC_EPERM; + } + + if(NC_indef(outncp)) + { + return NC_EINDEFINE; + } + + /* find the variable in the input cdf */ + invp = NC_lookupvar(inncp, varid); + if(invp == NULL) + { + return NC_ENOTVAR; + } + + /* find the variable in the output cdf */ + if(NC_findvar(&outncp->vars, invp->name->cp, &outvp) == -1) + { + return NC_ENOTVAR; + } + + /* can we even attempt to copy without conversion? */ + if(outvp->type != invp->type) + { + return NC_EINVAL; + } + + if( (invp->ndims == 0 && outvp->ndims != 0) + || (invp->ndims != 0 && outvp->ndims == 0) + || (IS_RECVAR(invp) && !IS_RECVAR(outvp)) + || (!IS_RECVAR(invp) && IS_RECVAR(outvp)) + || (invp->len != outvp->len) + ) + { + return NC_EINVAL; + } + + /* + * Check coordinates + */ + { + ALLOC_ONSTACK(coord, size_t, invp->ndims); + (void) memcpy(coord, invp->shape, invp->ndims * sizeof(size_t)); + if(IS_RECVAR(invp)) + *coord = inncp->numrecs; + + { + size_t ii = 0; + for(; ii < invp->ndims; ii++) + coord[ii] --; + } + /* at this point, coord is the largest valid coord of invp */ + + if(NCcoordck(outncp, outvp, coord) != NC_NOERR) + { + return NC_EINVAL; + } + /* else */ + + (void) memset(coord, 0, invp->ndims * sizeof(size_t)); + + if(!IS_RECVAR(invp)) + { + status = NCxvarcpy(inncp, invp, coord, + outncp, outvp, coord, + invp->len); + goto done; + } + /* else */ + + status = NCvnrecs(outncp, inncp->numrecs); + if(status != NC_NOERR) + goto done; + + for( /*NADA*/; *coord < inncp->numrecs; (*coord)++) + { + status = NCxvarcpy(inncp, invp, coord, + outncp, outvp, coord, + invp->len); + if(status != NC_NOERR) + break; + } +done: + FREE_ONSTACK(coord); + } + return status; +} diff --git a/Utilities/vtknetcdf/rnd.h b/Utilities/vtknetcdf/rnd.h new file mode 100644 index 0000000..a0ff95c --- /dev/null +++ b/Utilities/vtknetcdf/rnd.h @@ -0,0 +1,17 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: rnd.h,v 1.1 2005/07/15 21:56:39 andy Exp $ */ +#ifndef _RNDUP + +/* useful for aligning memory */ +#define _RNDUP(x, unit) ((((x) + (unit) - 1) / (unit)) \ + * (unit)) +#define _RNDDOWN(x, unit) ((x) - ((x)%(unit))) + +#define M_RND_UNIT (sizeof(double)) +#define M_RNDUP(x) _RNDUP(x, M_RND_UNIT) +#define M_RNDDOWN(x) __RNDDOWN(x, M_RND_UNIT) + +#endif diff --git a/Utilities/vtknetcdf/string.c b/Utilities/vtknetcdf/string.c new file mode 100644 index 0000000..0fecb0f --- /dev/null +++ b/Utilities/vtknetcdf/string.c @@ -0,0 +1,120 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: string.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#include "nc.h" +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include "ncx.h" +#include "rnd.h" + + +/* + * Free string, and, if needed, its values. + * Formerly +NC_free_string() + */ +void +free_NC_string(NC_string *ncstrp) +{ + if(ncstrp==NULL) + return; + free(ncstrp); +} + + +/* + * Verify that a name string is valid + * CDL syntax, eg, all the characters are + * alphanumeric, '-', '_', or '.'. + */ +int +NC_check_name(const char *name) +{ + const char *cp = name; + assert(name != NULL); + + if(*name == 0) + return NC_EBADNAME; /* empty names disallowed */ + + for(; *cp != 0; cp++) + { + int ch = *cp; + if(!isalnum(ch)) + { + if(ch != '_' && ch != '-' && ch != '.') + return NC_EBADNAME; + } + } + if(cp - name > NC_MAX_NAME) + return NC_EMAXNAME; + + return NC_NOERR; +} + + +/* + * Allocate a NC_string structure large enough + * to hold slen characters. + * Formerly +NC_new_string(count, str) + */ +NC_string * +new_NC_string(size_t slen, const char *str) +{ + NC_string *ncstrp; + size_t sz = M_RNDUP(sizeof(NC_string)) + slen + 1; + +#if 0 + sz = _RNDUP(sz, X_ALIGN); +#endif + + ncstrp = (NC_string *)malloc(sz); + if( ncstrp == NULL ) + return NULL; + (void) memset(ncstrp, 0, sz); + + ncstrp->nchars = sz - M_RNDUP(sizeof(NC_string)) - 1; + assert(ncstrp->nchars + 1 > slen); + ncstrp->cp = (char *)ncstrp + M_RNDUP(sizeof(NC_string)); + + if(str != NULL && *str != 0) + { + (void) strncpy(ncstrp->cp, str, ncstrp->nchars +1); + ncstrp->cp[ncstrp->nchars] = 0; + } + + return(ncstrp); +} + + +/* + * If possible, change the value of an NC_string to 'str'. + * + * Formerly +NC_re_string() + */ +int +set_NC_string(NC_string *ncstrp, const char *str) +{ + size_t slen; + size_t diff; + + assert(str != NULL && *str != 0); + + slen = strlen(str); + + if(ncstrp->nchars < slen) + return NC_ENOTINDEFINE; + + (void) memcpy(ncstrp->cp, str, slen); + diff = ncstrp->nchars - slen; + if(diff != 0) + (void) memset(ncstrp->cp + slen, 0, diff); + + return NC_NOERR; +} diff --git a/Utilities/vtknetcdf/t_nc.c b/Utilities/vtknetcdf/t_nc.c new file mode 100644 index 0000000..a0f754b --- /dev/null +++ b/Utilities/vtknetcdf/t_nc.c @@ -0,0 +1,661 @@ +/* + * Copyright 1988 University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: t_nc.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +/* + * Program to create a cdf, exercise all cdf functions. + * Creates cdf, stuff it full of numbers, closes it. Then + * reopens it, and checks for consistancy. + * Leaves the file around afterwards. + * + * Based on a program to test the nasa look-alike program, + * so not the most appropropriate test. See ../nctest for a + * complete spec test. + */ + + +#define REDEF +/* #define SYNCDEBUG */ + +#undef NDEBUG /* always active assert() in this file */ + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "netcdf.h" + + +#define MAXSHORT 32767 +#define MAXINT 2147483647 +#define MAXBYTE 127 + + +#define FNAME "test.nc" +#define NUM_DIMS 3 +#define DONT_CARE -1 +/* make these numbers big when you want to give this a real workout */ +#define NUM_RECS 8 +#define SIZE_1 7 +#define SIZE_2 8 + +static struct { + int num_dims; + int num_vars; + int num_attrs; + int xtendim; +} cdesc[1]; + +static struct { + char mnem[NC_MAX_NAME]; + nc_type type; + int ndims; + int dims[NC_MAX_DIMS]; + int num_attrs; +} vdesc[1]; + +static struct { + char mnem[NC_MAX_NAME]; + nc_type type; + size_t len; +} adesc[1]; + +union getret +{ + char by[8]; + short sh[4]; + int in[2]; + float fl[2]; + double dbl; +}; + + +static void +chkgot(nc_type type, union getret got, double check) +{ + switch(type){ + case NC_BYTE : + assert( (char)check == got.by[0] ); + break; + case NC_CHAR : /* TODO */ + assert( (char)check == got.by[0] ); + break; + case NC_SHORT : + assert( (short)check == got.sh[0] ); + break; + case NC_INT : + assert( (int)check == got.in[0] ); + break; + case NC_FLOAT : + assert( (float)check == got.fl[0] ); + break; + case NC_DOUBLE : + assert( check == got.dbl ); + break; + default: + break; + } +} + +static char *fname = FNAME; + + +static size_t num_dims = NUM_DIMS; +static size_t sizes[] = { NC_UNLIMITED, SIZE_1 , SIZE_2 }; +static char *dim_names[] = { "record", "ixx", "iyy"}; + +static void +createtestdims(int cdfid, size_t num_dims, size_t *sizes, char *dim_names[]) +{ + int dimid; + while(num_dims-- != 0) + { + assert( nc_def_dim(cdfid, *dim_names++, *sizes, &dimid) + == NC_NOERR); + sizes++; + } + +} + + +static void +testdims(int cdfid, size_t num_dims, size_t *sizes, char *dim_names[]) +{ + int ii; + size_t size; + char cp[NC_MAX_NAME]; + for(ii=0; (size_t) ii < num_dims; ii++, sizes++) + { + assert( nc_inq_dim(cdfid, ii, cp, &size) == NC_NOERR); + if( size != *sizes) + (void) fprintf(stderr, "%d: %lu != %lu\n", + ii, (unsigned long)size, (unsigned long)*sizes); + assert( size == *sizes); + assert( strcmp(cp, *dim_names++) == 0); + } + +} + + + +static char *reqattr[] = { + "UNITS", + "VALIDMIN", + "VALIDMAX", + "SCALEMIN", + "SCALEMAX", + "FIELDNAM", + _FillValue +}; +#define NUM_RATTRS 6 + +static struct tcdfvar { + char *mnem; + nc_type type; + char *fieldnam; + double validmin; + double validmax; + double scalemin; + double scalemax; + char *units; + int ndims; + int dims[NUM_DIMS]; +} testvars[] = { +#define Byte_id 0 + { "Byte", NC_BYTE, "Byte sized integer variable", + -MAXBYTE, MAXBYTE, -MAXBYTE, MAXBYTE , "ones", + 2, {0,1,DONT_CARE} }, +#define Char_id 1 + { "Char", NC_CHAR, "char (string) variable", + DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, "(unitless)", + 2, {0,2,DONT_CARE} }, +#define Short_id 2 + { "Short", NC_SHORT, "Short variable", + -MAXSHORT, MAXSHORT, -MAXSHORT, MAXSHORT , "ones", + 2, {0, 2, DONT_CARE }}, +#define Long_id 3 + { "Long", NC_INT, "Long Integer variable", /* 2.x backward strings */ + -MAXINT, MAXINT, -MAXINT, MAXINT, "ones", + 2, {1, 2, DONT_CARE}}, +#define Float_id 4 + { "Float", NC_FLOAT, "Single Precision Floating Point variable", + -MAXINT, MAXINT, -MAXINT, MAXINT, "flots", + 3, {0, 1, 2 }}, +#define Double_id 5 + { "Double", NC_DOUBLE, "Double Precision Floating Point variable", + -MAXINT, MAXINT, -MAXINT, MAXINT, "dflots", + 3, {0, 1, 2 }}, +}; +#define NUM_TESTVARS 6 + +static void +createtestvars(int id, struct tcdfvar *testvars, size_t count) +{ + int ii; + int varid; + struct tcdfvar *vp = testvars; + + for(ii = 0; (size_t) ii < count; ii++, vp++ ) + { + assert(nc_def_var(id, vp->mnem, vp->type, vp->ndims, vp->dims, + &varid) + == NC_NOERR ); + + assert( + nc_put_att_text(id,ii,reqattr[0],strlen(vp->units), + vp->units) + == NC_NOERR); + assert( + nc_put_att_double(id,ii,reqattr[1],NC_DOUBLE,1, + &vp->validmin) + == NC_NOERR); + assert( + nc_put_att_double(id,ii,reqattr[2],NC_DOUBLE,1, + &vp->validmax) + == NC_NOERR); + assert( + nc_put_att_double(id,ii,reqattr[3],NC_DOUBLE,1, + &vp->scalemin) + == NC_NOERR); + assert( + nc_put_att_double(id,ii,reqattr[4],NC_DOUBLE,1, + &vp->scalemax) + == NC_NOERR); + assert( + nc_put_att_text(id,ii,reqattr[5],strlen(vp->fieldnam), + vp->fieldnam) + == NC_NOERR); + } +} + +static void +parray(char *label, size_t count, size_t array[]) +{ + (void) fprintf(stdout, "%s", label); + (void) fputc('\t',stdout); + for(; count != 0; count--, array++) + (void) fprintf(stdout," %lu", (unsigned long) *array); +} + + +static void +fill_seq(int id) +{ + float values[NUM_RECS * SIZE_1 * SIZE_2]; + size_t vindices[NUM_DIMS]; + + { + size_t ii = 0; + for(; ii < sizeof(values)/sizeof(values[0]); ii++) + { + values[ii] = (float) ii; + } + } + + /* zero the vindices */ + { + size_t *cc = vindices; + while (cc < &vindices[num_dims]) + *cc++ = 0; + } + + sizes[0] = NUM_RECS; + + assert( nc_put_vara_float(id, Float_id, vindices, sizes, values)== NC_NOERR); + +} + +static void +check_fill_seq(int id) +{ + size_t vindices[NUM_DIMS]; + size_t *cc, *mm; + union getret got; + int ii = 0; + float val; + + sizes[0] = NUM_RECS; + cc = vindices; + while (cc < &vindices[num_dims]) + *cc++ = 0; + + /* ripple counter */ + cc = vindices; + mm = sizes; + while (*vindices < *sizes) + { + while (*cc < *mm) + { + if (mm == &sizes[num_dims - 1]) + { + if(nc_get_var1_float(id, Float_id, vindices, &got.fl[0]) == -1) + goto bad_ret; + val = (float) ii; + if(val != got.fl[0]) + { + parray("indices", NUM_DIMS, vindices); + (void) printf("\t%f != %f\n", val, got.fl[0]); + } + (*cc)++; ii++; + continue; + } + cc++; + mm++; + } + if(cc == vindices) + break; + *cc = 0; + cc--; + mm--; + (*cc)++; + } + return; +bad_ret : + (void) printf("couldn't get a var in check_fill_seq() %d\n", + ii); + return; +} + +static size_t indices[][3] = { + {0, 1, 3}, + {0, 3, 0}, + {1, 2, 3}, + {3, 2, 1}, + {2, 1, 3}, + {1, 0, 0}, + {0, 0, 0}, +}; + +static char chs[] = {'A','B', ((char)0xff) }; +static size_t s_start[] = {0,1}; +static size_t s_edges[] = {NUM_RECS, SIZE_1 - 1}; +static char sentence[NUM_RECS* SIZE_1 -1] = + "The red death had long devastated the country."; +static short shs[] = {97, 99}; +static int birthday = 82555; +#define M_E 2.7182818284590452354 +static float e = (float) M_E; +static double pinot = 3.25; +static double zed = 0.0; + + +/*ARGSUSED*/ +int +main(int ac, char *av[]) +{ + int ret; + int id; + char buf[256]; +#ifdef SYNCDEBUG + char *str = "one"; +#endif + int ii; + size_t ui; + struct tcdfvar *tvp = testvars; + union getret got; + const size_t initialsz = 8192; + size_t chunksz = 8192; + size_t align = 8192/32; + + ret = nc__create(fname,NC_NOCLOBBER, initialsz, &chunksz, &id); + if(ret != NC_NOERR) { + (void) fprintf(stderr, "trying again\n"); + ret = nc__create(fname,NC_CLOBBER, initialsz, &chunksz, &id); + } + if(ret != NC_NOERR) + exit(ret); + + assert( nc_put_att_text(id, NC_GLOBAL, + "TITLE", 12, "another name") == NC_NOERR); + assert( nc_get_att_text(id, NC_GLOBAL, + "TITLE", buf) == NC_NOERR); +/* (void) printf("title 1 \"%s\"\n", buf); */ + assert( nc_put_att_text(id, NC_GLOBAL, + "TITLE", strlen(fname), fname) == NC_NOERR); + assert( nc_get_att_text(id, NC_GLOBAL, + "TITLE", buf) == NC_NOERR); + buf[strlen(fname)] = 0; +/* (void) printf("title 2 \"%s\"\n", buf); */ + assert( strcmp(fname, buf) == 0); + + createtestdims(id, NUM_DIMS, sizes, dim_names); + testdims(id, NUM_DIMS, sizes, dim_names); + + createtestvars(id, testvars, NUM_TESTVARS); + + { + int ifill = -1; double dfill = -9999; + assert( nc_put_att_int(id, Long_id, + _FillValue, NC_INT, 1, &ifill) == NC_NOERR); + assert( nc_put_att_double(id, Double_id, + _FillValue, NC_DOUBLE, 1, &dfill) == NC_NOERR); + } + +#ifdef REDEF + assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR ); + assert( nc_put_var1_int(id, Long_id, indices[3], &birthday) + == NC_NOERR ); + fill_seq(id); + assert( nc_redef(id) == NC_NOERR ); +/* assert( nc_rename_dim(id,2, "a long dim name") == NC_NOERR); */ +#endif + + assert( nc_rename_dim(id,1, "IXX") == NC_NOERR); + assert( nc_inq_dim(id, 1, buf, &ui) == NC_NOERR); + (void) printf("dimrename: %s\n", buf); + assert( nc_rename_dim(id,1, dim_names[1]) == NC_NOERR); + +#ifdef ATTRX + assert( nc_rename_att(id, 1, "UNITS", "units") == NC_NOERR); + assert( nc_del_att(id, 4, "FIELDNAM")== NC_NOERR); + assert( nc_del_att(id, 2, "SCALEMIN")== NC_NOERR); + assert( nc_del_att(id, 2, "SCALEMAX")== NC_NOERR); +#endif /* ATTRX */ + + assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR ); + +#ifndef REDEF + fill_seq(id); + assert( nc_put_var1_int(id, Long_id, indices[3], &birthday)== NC_NOERR ); +#endif + + assert( nc_put_vara_schar(id, Byte_id, s_start, s_edges, + (signed char *)sentence) + == NC_NOERR); + assert( nc_put_var1_schar(id, Byte_id, indices[6], (signed char *)(chs+1)) + == NC_NOERR); + assert( nc_put_var1_schar(id, Byte_id, indices[5], (signed char *)chs) + == NC_NOERR); + + assert( nc_put_vara_text(id, Char_id, s_start, s_edges, sentence) + == NC_NOERR); + assert( nc_put_var1_text(id, Char_id, indices[6], (chs+1)) + == NC_NOERR) ; + assert( nc_put_var1_text(id, Char_id, indices[5], chs) + == NC_NOERR); + + assert( nc_put_var1_short(id, Short_id, indices[4], shs) + == NC_NOERR); + + assert( nc_put_var1_float(id, Float_id, indices[2], &e) + == NC_NOERR); + + assert( nc_put_var1_double(id, Double_id, indices[1], &zed) + == NC_NOERR); + assert( nc_put_var1_double(id, Double_id, indices[0], &pinot) + == NC_NOERR); + + +#ifdef SYNCDEBUG + (void) printf("Hit Return to sync\n"); + gets(str); + nc_sync(id,0); + (void) printf("Sync done. Hit Return to continue\n"); + gets(str); +#endif /* SYNCDEBUG */ + + ret = nc_close(id); + (void) printf("nc_close ret = %d\n\n", ret); + + +/* + * read it + */ + ret = nc__open(fname,NC_NOWRITE, &chunksz, &id); + if(ret != NC_NOERR) + { + (void) printf("Could not open %s: %s\n", fname, + nc_strerror(ret)); + exit(1); + } + (void) printf("reopen id = %d for filename %s\n", + id, fname); + + /* NC */ + (void) printf("NC "); + assert( nc_inq(id, &(cdesc->num_dims), &(cdesc->num_vars), + &(cdesc->num_attrs), &(cdesc->xtendim) ) == NC_NOERR); + assert((size_t) cdesc->num_dims == num_dims); + assert(cdesc->num_attrs == 1); + assert(cdesc->num_vars == NUM_TESTVARS); + (void) printf("done\n"); + + /* GATTR */ + (void) printf("GATTR "); + + assert( nc_inq_attname(id, NC_GLOBAL, 0, adesc->mnem) == 0); + assert(strcmp("TITLE",adesc->mnem) == 0); + assert( nc_inq_att(id, NC_GLOBAL, adesc->mnem, &(adesc->type), &(adesc->len))== NC_NOERR); + assert( adesc->type == NC_CHAR ); + assert( adesc->len == strlen(fname) ); + assert( nc_get_att_text(id, NC_GLOBAL, "TITLE", buf)== NC_NOERR); + buf[adesc->len] = 0; + assert( strcmp(fname, buf) == 0); + + /* VAR */ + (void) printf("VAR "); + assert( cdesc->num_vars == NUM_TESTVARS ); + + for(ii = 0; ii < cdesc->num_vars; ii++, tvp++ ) + { + int jj; + assert( nc_inq_var(id, ii, + vdesc->mnem, + &(vdesc->type), + &(vdesc->ndims), + vdesc->dims, + &(vdesc->num_attrs)) == NC_NOERR); + if(strcmp(tvp->mnem , vdesc->mnem) != 0) + { + (void) printf("attr %d mnem mismatch %s, %s\n", + ii, tvp->mnem, vdesc->mnem); + continue; + } + if(tvp->type != vdesc->type) + { + (void) printf("attr %d type mismatch %d, %d\n", + ii, tvp->type, vdesc->type); + continue; + } + for(jj = 0; jj < vdesc->ndims; jj++ ) + { + if(tvp->dims[jj] != vdesc->dims[jj] ) + { + (void) printf( + "inconsistant dim[%d] for variable %d: %d != %d\n", + jj, ii, tvp->dims[jj], vdesc->dims[jj] ); + continue; + } + } + + /* VATTR */ + (void) printf("VATTR\n"); + for(jj=0; jj<vdesc->num_attrs; jj++ ) + { + assert( nc_inq_attname(id, ii, jj, adesc->mnem) == NC_NOERR); + if( strcmp(adesc->mnem, reqattr[jj]) != 0 ) + { + (void) printf("var %d attr %d mismatch %s != %s\n", + ii, jj, adesc->mnem, reqattr[jj] ); + break; + } + } + + if( nc_inq_att(id, ii, reqattr[0], &(adesc->type), &(adesc->len)) + != -1) { + assert( adesc->type == NC_CHAR ); + assert( adesc->len == strlen(tvp->units) ); + assert( nc_get_att_text(id,ii,reqattr[0],buf)== NC_NOERR); + buf[adesc->len] = 0; + assert( strcmp(tvp->units, buf) == 0); + } + + if( + nc_inq_att(id, ii, reqattr[1], &(adesc->type), &(adesc->len)) + != -1) + { + assert( adesc->type == NC_DOUBLE ); + assert( adesc->len == 1 ); + assert( nc_get_att_double(id, ii, reqattr[1], &got.dbl)== NC_NOERR); + chkgot(adesc->type, got, tvp->validmin); + } + + if( + nc_inq_att(id, ii, reqattr[2], &(adesc->type), &(adesc->len)) + != -1) + { + assert( adesc->type == NC_DOUBLE ); + assert( adesc->len == 1 ); + assert( nc_get_att_double(id, ii, reqattr[2], &got.dbl)== NC_NOERR); + chkgot(adesc->type, got, tvp->validmax); + } + + if( + nc_inq_att(id, ii, reqattr[3], &(adesc->type), &(adesc->len)) + != -1) + { + assert( adesc->type == NC_DOUBLE ); + assert( adesc->len ==1 ); + assert( nc_get_att_double(id, ii, reqattr[3], &got.dbl)== NC_NOERR); + chkgot(adesc->type, got, tvp->scalemin); + } + + if( + nc_inq_att(id, ii, reqattr[4], &(adesc->type), &(adesc->len)) + != -1) + { + assert( adesc->type == NC_DOUBLE ); + assert( adesc->len == 1 ); + assert( nc_get_att_double(id, ii, reqattr[4], &got.dbl)== NC_NOERR); + chkgot(adesc->type, got, tvp->scalemax); + } + + if( nc_inq_att(id, ii, reqattr[5], &(adesc->type), &(adesc->len))== NC_NOERR) + { + assert( adesc->type == NC_CHAR ); + assert( adesc->len == strlen(tvp->fieldnam) ); + assert( nc_get_att_text(id,ii,reqattr[5],buf)== NC_NOERR); + buf[adesc->len] = 0; + assert( strcmp(tvp->fieldnam, buf) == 0); + } + } + + (void) printf("fill_seq "); + check_fill_seq(id); + (void) printf("Done\n"); + + assert( nc_get_var1_double(id, Double_id, indices[0], &got.dbl)== NC_NOERR); + (void) printf("got val = %f\n", got.dbl ); + + assert( nc_get_var1_double(id, Double_id, indices[1], &got.dbl)== NC_NOERR); + (void) printf("got val = %f\n", got.dbl ); + + assert( nc_get_var1_float(id, Float_id, indices[2], &got.fl[0])== NC_NOERR); + (void) printf("got val = %f\n", got.fl[0] ); + + assert( nc_get_var1_int(id, Long_id, indices[3], &got.in[0])== NC_NOERR); + (void) printf("got val = %d\n", got.in[0] ); + + assert( nc_get_var1_short(id, Short_id, indices[4], &got.sh[0])== NC_NOERR); + (void) printf("got val = %d\n", got.sh[0] ); + + assert( nc_get_var1_text(id, Char_id, indices[5], &got.by[0]) == NC_NOERR); + (void) printf("got NC_CHAR val = %c (0x%02x) \n", + got.by[0] , got.by[0]); + + assert( nc_get_var1_text(id, Char_id, indices[6], &got.by[0]) == NC_NOERR); + (void) printf("got NC_CHAR val = %c (0x%02x) \n", + got.by[0], got.by[0] ); + + (void) memset(buf,0,sizeof(buf)); + assert( nc_get_vara_text(id, Char_id, s_start, s_edges, buf) == NC_NOERR); + (void) printf("got NC_CHAR val = \"%s\"\n", buf); + + assert( nc_get_var1_schar(id, Byte_id, indices[5], + (signed char *)&got.by[0])== NC_NOERR); + (void) printf("got val = %c (0x%02x) \n", got.by[0] , got.by[0]); + + assert( nc_get_var1_schar(id, Byte_id, indices[6], + (signed char *)&got.by[0])== NC_NOERR); + (void) printf("got val = %c (0x%02x) \n", got.by[0], got.by[0] ); + + (void) memset(buf,0,sizeof(buf)); + assert( nc_get_vara_schar(id, Byte_id, s_start, s_edges, + (signed char *)buf)== NC_NOERR ); + (void) printf("got val = \"%s\"\n", buf); + + { + double dbuf[NUM_RECS * SIZE_1 * SIZE_2]; + assert(nc_get_var_double(id, Float_id, dbuf) == NC_NOERR); + (void) printf("got vals = %f ... %f\n", dbuf[0], + dbuf[NUM_RECS * SIZE_1 * SIZE_2 -1] ); + } + + ret = nc_close(id); + (void) printf("re nc_close ret = %d\n", ret); + + return 0; +} diff --git a/Utilities/vtknetcdf/t_ncio.c b/Utilities/vtknetcdf/t_ncio.c new file mode 100644 index 0000000..145e831 --- /dev/null +++ b/Utilities/vtknetcdf/t_ncio.c @@ -0,0 +1,372 @@ +/* + * Copyright 1995, University Corporation for Atmospheric Research + * See top level COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: t_ncio.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include "ncio.h" +#ifndef ENOERR +#define ENOERR 0 +#endif + + +static void +usage(const char *av0) +{ + (void)fprintf(stderr, + "Usage: %s [options] fname\t\nOptions:\n", av0); + (void)fprintf(stderr, + "\t-v Verbose\n") ; + (void)fprintf(stderr, + "\t-w Open Read/Write, default is read only\n") ; + (void)fprintf(stderr, + "\t-c Create, clobber existing\n") ; + (void)fprintf(stderr, + "\t-n Create, error if it already exists\n") ; + (void)fprintf(stderr, + "\t-L Use locking if available\n") ; + (void)fprintf(stderr, + "\t-S Share updates (turn off caching)\n") ; + (void)fprintf(stderr, + "\t-U Delete (unlink) on close\n") ; + (void)fprintf(stderr, + "\t-o igeto Initial get offset\n") ; + (void)fprintf(stderr, + "\t-i igetsz Initial get size\n") ; + (void)fprintf(stderr, + "\t-I initialsz Initial file size for create\n") ; + (void)fprintf(stderr, + "\t-s sizehint Buffer size\n") ; + exit(EXIT_FAILURE); +} + + +static long +argscale(const char *arg, const char *tag) +{ + long value = 0; + /* last character */ + const char *cp = arg + strlen(arg) -1; + value = atol(arg); + if(isalpha(*cp)) + { + switch(*cp) { + case 'k': + case 'K': + value *= 1024; + break; + case 'm': + case 'M': + value *= (1024*1024); + break; + default: + value = 0; /* trigger error below */ + break; + } + } + if(value == 0) + { + fprintf(stderr, + "Illegal %s \"%s\", ignored\n", tag, arg); + } + return value; +} + + +static void +modify_ex(off_t offset, size_t extent, void *vp) +{ + unsigned char *obuf = vp; + const unsigned char *const end = &obuf[extent]; + unsigned char *cp = obuf; + + if(cp >= end) return; + *cp++ = (unsigned char)( offset >> 24); + if(cp >= end) return; + *cp++ = (unsigned char)((offset & 0x00ff0000) >> 16); + if(cp >= end) return; + *cp++ = (unsigned char)((offset & 0x0000ff00) >> 8); + if(cp >= end) return; + *cp++ = (unsigned char)( offset & 0x000000ff); + if(cp >= end) return; + *cp++ = (unsigned char)( extent >> 24); + if(cp >= end) return; + *cp++ = (unsigned char)((extent & 0x00ff0000) >> 16); + if(cp >= end) return; + *cp++ = (unsigned char)((extent & 0x0000ff00) >> 8); + if(cp >= end) return; + *cp++ = (unsigned char)( extent & 0x000000ff); + + while(cp < end) + { + *cp++ = (unsigned char) (cp - obuf); + } +} + + +typedef struct riu { + struct riu *next; + struct riu *prev; + off_t offset; + size_t extent; + void *vp; +} riu; + +static void +free_riu(riu *riup) +{ + if(riup == NULL) + return; + free(riup); +} + +static riu * +new_riu(off_t offset, size_t extent, void *vp) +{ + riu *riup = (riu *)malloc(sizeof(riu)); + if(riup == NULL) + { + fprintf(stderr, + "new_riu: malloc failed\n"); + exit(EXIT_FAILURE); + } + riup->next = NULL; + riup->prev = NULL; + riup->offset = offset; + riup->extent = extent; + riup->vp = vp; + return riup; +} + +static riu *stack = NULL; + +static void +riu_push(off_t offset, size_t extent, void *vp) +{ + riu *riup = new_riu(offset, extent, vp); + /* assert(riup != NULL); */ + riup->next = stack; + if(stack != NULL) + stack->prev = riup; + stack = riup; +} + +static int +riu_pop(off_t offset, int modify) +{ + riu *riup = stack; + while(riup != NULL) + { + if(riup->offset == offset) + { + if(modify) + { + modify_ex(riup->offset, riup->extent, riup->vp); + } + if(riup->next != NULL) + { + riup->next->prev = riup->prev; + } + if(riup == stack) + { + stack = riup->next; + } + else + { + assert(riup->prev != NULL); + riup->prev->next = riup->next; + } + free_riu(riup); + return 1; + } + riup = riup->next; + } + /* else, not found */ + return 0; +} + +main(int ac, char *av[]) +{ + char *path = ""; + ncio *nciop; + char linebuf[128]; + off_t offset; + size_t extent; + void *vp; + int status = ENOERR; + int verbose = 0; + int flags = 0; + int create = 0; + off_t igeto = 0; + size_t igetsz = 0; + size_t initialsz = 0; + int doUnlink = 0; + size_t sizehint = NC_SIZEHINT_DEFAULT; + + { + extern int optind; + extern int opterr; + extern char *optarg; + int ch; + + opterr = 1; + + while ((ch = getopt(ac, av, "vwcnLSUo:i:I:s:")) != EOF) + switch (ch) { + case 'v': + verbose = 1; + break; + case 'w': + flags |= NC_WRITE; + break; + case 'c': + create = 1; + break; + case 'n': + create = 1; + flags |= NC_NOCLOBBER; + break; + case 'L': + flags |= NC_LOCK; + break; + case 'S': + flags |= NC_SHARE; + break; + case 'U': + doUnlink = 1; + break; + case 'o': + igeto = argscale(optarg, "igeto"); + break; + case 'i': + igetsz = argscale(optarg, "igetsz"); + break; + case 'I': + initialsz = argscale(optarg, "initialsz"); + break; + case 's': + sizehint = argscale(optarg, "sizehint"); + break; + case '?': + usage(av[0]); + break; + } + + /* last arg, the file name, is required */ + if(ac - optind <= 0) + usage(av[0]) ; + path = av[optind]; + + + } + + if(!create) + { + status = ncio_open(path, flags, + igeto, igetsz, &sizehint, + &nciop, &vp); + if(status != ENOERR) + { + fprintf(stderr, "ncio_open: %s: %s\n", + path, strerror(status)); + return(EXIT_FAILURE); + } + } else { + status = ncio_create(path, flags, initialsz, + igeto, igetsz, &sizehint, + &nciop, &vp); + if(status != ENOERR) + { + fprintf(stderr, "ncio_create: %s: %s\n", + path, strerror(status)); + return(EXIT_FAILURE); + } + } + + while(fgets(linebuf, sizeof(linebuf), stdin) != NULL) + { + offset = 0; + extent = 0; + + if(*linebuf == '#') + continue; /* comment */ + if(sscanf(linebuf, "rel 0x%lx", &offset) == 1 + || sscanf(linebuf, "rel %ld", &offset) == 1) + { + if(verbose) + printf("- rel %8ld\n", offset); + if(!riu_pop(offset, 0)) + continue; + status = nciop->rel(nciop, offset, 0); + if(status) + { + fprintf(stderr, "- rel error: %s\n", + strerror(status)); + continue; + } + } + else if(sscanf(linebuf, "relm 0x%lx", &offset) == 1 + || sscanf(linebuf, "relm %ld", &offset) == 1) + { + if(verbose) + printf("- relm %8ld\n", offset); + if(!riu_pop(offset, 1)) + continue; + status = nciop->rel(nciop, offset, RGN_MODIFIED); + if(status) + { + fprintf(stderr, "- relm %8ld error: %s\n", + offset, strerror(status)); + continue; + } + } + else if(sscanf(linebuf, "get 0x%lx %ld", &offset, &extent) == 2 + || sscanf(linebuf, "get %ld %ld", &offset, &extent) == 2) + { + if(verbose) + printf("- get %10ld %8ld\n", offset, extent); + status = nciop->get(nciop, offset, extent, 0, &vp); + if(status) + { + fprintf(stderr, "- get error: %s\n", + strerror(status)); + continue; + } + riu_push(offset, extent, vp); + } + else if(sscanf(linebuf, "getw 0x%lx %ld", &offset, &extent) == 2 + || sscanf(linebuf, "getw %ld %ld", &offset, &extent) == 2) + { + if(verbose) + printf("- getw %10ld %8ld\n", offset, extent); + status = nciop->get(nciop, offset, extent, RGN_WRITE, &vp); + if(status) + { + fprintf(stderr, "- getw error: %s\n", + strerror(status)); + continue; + } + riu_push(offset, extent, vp); + } + else if(strchr(linebuf, 'q') != NULL) + break; + else + printf("???\n"); + } + + status = ncio_close(nciop, doUnlink); + if(status != ENOERR) + { + fprintf(stderr, "ncio_close(%s): %s: %s\n", + doUnlink ? "doUnlink" : "", + path, strerror(status)); + return(EXIT_FAILURE); + } + + return(EXIT_SUCCESS); +} diff --git a/Utilities/vtknetcdf/t_ncx.c b/Utilities/vtknetcdf/t_ncx.c new file mode 100644 index 0000000..a22b5c2 --- /dev/null +++ b/Utilities/vtknetcdf/t_ncx.c @@ -0,0 +1,1250 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: t_ncx.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#include <stdio.h> +#include <limits.h> +/* alias poorly named limits.h macros */ +#define SHORT_MAX SHRT_MAX +#define SHORT_MIN SHRT_MIN +#define USHORT_MAX USHRT_MAX +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <string.h> +#include "ncx.h" + +#define NO_UNSIGNED +#define NO_UNSIGNED_LONG + +/* + * This program tests the xdr_mem implementation and + * the ncx_ implementation, and compares the two. + * Link like this: + * cc t_ncx.c ncx.o [-lsome_xdr_lib] -o t_nxc + * Successful output is: + xdr_encode ends at byte 640 + xdr_check ends at byte 640 + ncx_encode ends at byte 640 + ncx_check ends at byte 640 + xdr_check ends at byte 640 + ncx_check ends at byte 640 + * with exit status 0; + */ + +#define XBSZ 1024 + +char xdrb[XBSZ]; +char ncxb[XBSZ]; + +#define ArraySize(thang) (sizeof(thang)/sizeof(thang[0])) +#define uiArraySize(thang) ((u_int)ArraySize(thang)) +#define eSizeOf(thang) ((u_int)(sizeof(thang[0]))) + +/* + * Some test data + */ + +static char text[] = { "Hiya sailor. New in town?" }; + +/* + * Some test data + * The ideas is that ncx_putn_type_type(...., types) + * should not return NC_ERANGE. + */ + +#if SCHAR_MAX == X_SCHAR_MAX && SCHAR_MIN == X_SCHAR_MIN +static schar schars[] = { + SCHAR_MIN, SCHAR_MIN +1, + -1, 0, 1, + SCHAR_MAX - 1, SCHAR_MAX +}; +#else +/* The implementation and this test assume 8 bit bytes. */ +#error "Not 8 bit bytes ??" +#endif + +static short shorts[] = { +#if SHORT_MAX <= X_SHORT_MAX + SHORT_MIN, SHORT_MIN + 1, +# if SCHAR_MAX < X_SHORT_MAX + SCHAR_MIN - 1, SCHAR_MIN, SCHAR_MIN + 1, +# endif + -1, 0, 1, +# if SCHAR_MAX < X_SHORT_MAX + SCHAR_MAX - 1, SCHAR_MAX, SCHAR_MAX + 1, +# endif + SHORT_MAX - 1, SHORT_MAX +#else + X_SHORT_MIN, X_SHORT_MIN + 1, +# if SCHAR_MAX < X_SHORT_MAX + SCHAR_MIN - 1, SCHAR_MIN, SCHAR_MIN + 1, +# endif + -1, 0, 1, +# if SCHAR_MAX < X_SHORT_MAX + SCHAR_MAX - 1, SCHAR_MAX, SCHAR_MAX + 1, +# endif + X_SHORT_MAX - 1, X_SHORT_MAX +#endif +}; + +static int ints[] = { +#if INT_MAX <= X_INT_MAX + INT_MIN, INT_MIN +1, +# if SHORT_MAX < X_INT_MAX + SHORT_MIN -1, SHORT_MIN, SHORT_MIN + 1, +# endif +# if SCHAR_MAX < X_INT_MAX + SCHAR_MIN - 1, SCHAR_MIN, SCHAR_MIN + 1, +# endif + -1, 0, 1, +# if SCHAR_MAX < X_INT_MAX + SCHAR_MAX - 1, SCHAR_MAX, SCHAR_MAX + 1, +# endif +# if SHORT_MAX < X_INT_MAX + SHORT_MAX - 1, SHORT_MAX, SHORT_MAX +1, +# endif + INT_MAX - 1, INT_MAX +#else + X_INT_MIN, X_INT_MIN +1, +# if SHORT_MAX < X_INT_MAX + SHORT_MIN -1, SHORT_MIN, SHORT_MIN + 1, +# endif +# if SCHAR_MAX < X_INT_MAX + SCHAR_MIN - 1, SCHAR_MIN, SCHAR_MIN + 1, +# endif + -1, 0, 1, +# if SCHAR_MAX < X_INT_MAX + SCHAR_MAX - 1, SCHAR_MAX, SCHAR_MAX + 1, +# endif +# if SHORT_MAX < X_INT_MAX + SHORT_MAX - 1, SHORT_MAX, SHORT_MAX +1, +# endif + X_INT_MAX - 1, X_INT_MAX +#endif /* INT */ +}; + + +/* N.B. only testing longs over X_INT range for now */ +static long longs[] = { +#if LONG_MAX <= X_INT_MAX + LONG_MIN, LONG_MIN +1, +# if INT_MAX < X_INT_MAX + INT_MIN -1, INT_MIN, INT_MIN + 1, +# endif +# if SHORT_MAX < X_INT_MAX + SHORT_MIN -1, SHORT_MIN, SHORT_MIN + 1, +# endif +# if SCHAR_MAX < X_INT_MAX + SCHAR_MIN - 1, SCHAR_MIN, SCHAR_MIN + 1, +# endif + -1, 0, 1, +# if SCHAR_MAX < X_INT_MAX + SCHAR_MAX - 1, SCHAR_MAX, SCHAR_MAX + 1, +# endif +# if SHORT_MAX < X_INT_MAX + SHORT_MAX - 1, SHORT_MAX, SHORT_MAX +1, +# endif +# if INT_MAX < X_INT_MAX + INT_MAX -1, INT_MAX, INT_MAX + 1, +# endif + LONG_MAX - 1, LONG_MAX +#else + X_INT_MIN, X_INT_MIN +1, +# if SHORT_MAX < X_INT_MAX + SHORT_MIN -1, SHORT_MIN, SHORT_MIN + 1, +# endif +# if SCHAR_MAX < X_INT_MAX + SCHAR_MIN - 1, SCHAR_MIN, SCHAR_MIN + 1, +# endif + -1, 0, 1, +# if SCHAR_MAX < X_INT_MAX + SCHAR_MAX - 1, SCHAR_MAX, SCHAR_MAX + 1, +# endif +# if SHORT_MAX < X_INT_MAX + SHORT_MAX - 1, SHORT_MAX, SHORT_MAX +1, +# endif + X_INT_MAX - 1, X_INT_MAX +#endif +}; + +static float floats[] = { + -100.625, -100.5, -100.375, -100.25, -100.125, + -1.0, -.125, 0., .125, 1., + 100.125, 100.25, 100.375, 100.5, 100.625 +}; + +/* The big numbers require 25 bits: 2^(25-i)+1/2^i, i = 2, 3, ..., 6 */ +static double doubles[] = { + -8388608.25, -4194304.125, -2097152.0625, -1048576.03125, -524288.015625 + -100.625, -100.5, -100.375, -100.25, -100.125, + -1.0, -.125, 0., .125, 1., + 100.125, 100.25, 100.375, 100.5, 100.625, + 524288.015625, 1048576.03125, 2097152.0625, 4194304.125, 8388608.25 +}; + +/* End of test data */ + +/* + * Copyright 1993, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: t_ncx.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +/* putget.c */ +/* + * xdr 1 - 3 bytes, leaving adjoining bytes within the word ok. + * (minimum unit of io is 4 bytes) + */ +static bool_t +xdr_NCvbyte(XDR *xdrs, unsigned rem, unsigned count, char *value) +{ + char buf[4] ; + u_int origin ; + enum xdr_op x_op = xdrs->x_op ; /* save state */ + + if(x_op == XDR_ENCODE) + { + /* + * Since we only read/write multiples of four bytes, + * We will read in the word to change one byte in it. + */ + origin = xdr_getpos( xdrs ) ; + /* next op is a get */ + xdrs->x_op = XDR_DECODE ; + } + + if(!xdr_opaque(xdrs, buf, 4)) + { + /* get failed, assume we are trying to read off the end */ + (void)memset(buf, 0, sizeof(buf)) ; + } + + if(x_op == XDR_ENCODE) /* back to encode */ + xdrs->x_op = x_op ; + + while(count-- != 0) + { + if(x_op == XDR_ENCODE) + buf[rem] = *value ; + else + *value = buf[rem] ; + + rem++ ; + value++ ; + } + + if(x_op == XDR_ENCODE) + { + if( !xdr_setpos(xdrs, origin) ) + return(FALSE) ; + if( !xdr_opaque(xdrs, buf, 4)) + return(FALSE) ; + } + + return(TRUE) ; +} + + +/* xdrshorts.c */ +/* you may wish to tune this: big on a cray, small on a PC? */ +#define NC_SHRT_BUFSIZ 8192 +#define NC_NSHRTS_PER (NC_SHRT_BUFSIZ/2) /* number of netshorts the buffer holds */ + +/* + * xdr a short leaving adjoining short within the word ok. + * (minimum unit of io is 4 bytes) + */ +static bool_t +xdr_NCvshort(XDR *xdrs, unsigned which, short *value) +{ + unsigned char buf[4] ; /* unsigned is important here */ + u_int origin ; + enum xdr_op x_op = xdrs->x_op ; /* save state */ + + if(x_op == XDR_ENCODE) + { + origin = xdr_getpos( xdrs ) ; + /* next op is a get */ + xdrs->x_op = XDR_DECODE ; + } + + if(!xdr_opaque(xdrs, (caddr_t)buf, 4)) + { + /* get failed, assume we are trying to read off the end */ + (void)memset(buf, 0, sizeof(buf)) ; + } + + if(x_op == XDR_ENCODE) /* back to encode */ + xdrs->x_op = x_op ; + + if(which != 0) which = 2 ; + + if(xdrs->x_op == XDR_ENCODE) + { + buf[which +1] = *value % 256 ; + buf[which] = (*value >> 8) ; + + if( !xdr_setpos(xdrs, origin) ) + return(FALSE) ; + if( !xdr_opaque(xdrs, (caddr_t)buf, 4)) + return(FALSE) ; + } + else + { + *value = (((unsigned)buf[which] & 0x7f) << 8) + + (unsigned)buf[which + 1] ; + if((unsigned)buf[which] & 0x80) + { + /* extern is neg */ + *value -= 0x8000 ; + } + } + return(TRUE) ; +} + +/* + * internal function, bulk xdr of an even number of shorts, less than NC_NSHRTS_PER + */ +static +bool_t +NCxdr_shortsb(XDR *xdrs, short *sp, u_int nshorts) +{ + unsigned char buf[NC_SHRT_BUFSIZ] ; + unsigned char *cp ; + unsigned int nbytes = nshorts * 2; + + /* assert(nshorts <= NC_NSHRTS_PER) ; */ + /* assert(nshorts > 0) ; */ + + if(xdrs->x_op == XDR_ENCODE) + { + for(cp = buf ; cp < &buf[nbytes] ; sp++, cp += 2 ) + { + *(cp +1) = *sp % 256 ; + *cp = (*sp >> 8) ; + } + } + + if(!xdr_opaque(xdrs, (caddr_t)buf, nbytes)) + return FALSE ; + + if(xdrs->x_op == XDR_DECODE) + { + for(cp = buf ; cp < &buf[nbytes] ; sp++, cp += 2 ) + { + *sp = (((unsigned)*cp & 0x7f) << 8) + + (unsigned)*(cp +1) ; + if((unsigned)*cp & 0x80) + { + /* extern is neg */ + *sp -= 0x8000 ; + } + } + } + + return TRUE ; +} + + +/* + * Translate an array of cnt short integers at sp. + */ +bool_t +xdr_shorts(XDR *xdrs, short *sp, u_int cnt) +{ + int odd ; /* 1 if cnt is odd, 0 otherwise */ + + if(cnt == 0) + return TRUE ; /* ? */ + + odd = cnt % 2 ; + if(odd) + cnt-- ; + /* cnt is even, odd is set if apropos */ + + while(cnt > NC_NSHRTS_PER) + { + if(!NCxdr_shortsb(xdrs, sp, NC_NSHRTS_PER)) + return FALSE ; + /* else */ + sp += NC_NSHRTS_PER ; + cnt -= NC_NSHRTS_PER ; + } + + /* we know cnt <= NC_NSHRTS_PER at this point */ + + if(cnt != 0) + { + if(!NCxdr_shortsb(xdrs, sp, cnt)) + return FALSE ; + /* else */ + sp += cnt ; + cnt = 0 ; + } + + if(odd) + if(!xdr_NCvshort(xdrs, 0, sp)) + return FALSE ; + + return TRUE ; +} + +/* + * Use standard xdr interface (plus the netcdf xdr_shorts()) + * to encode data to 'buf' + * Returns 0 on success. + */ +static int +xdr_encode(char *buf, u_int sz) +{ + XDR xdrs[1]; + u_int pos; + int ii; + + xdrmem_create(xdrs, buf, sz, XDR_ENCODE); + + if(!xdr_opaque(xdrs, (caddr_t)text, (u_int)sizeof(text))) + return 1; + + if(!xdr_opaque(xdrs, (caddr_t)schars, (u_int)sizeof(schars))) + return 2; + + if(!xdr_shorts(xdrs, shorts, uiArraySize(shorts))) + return 3; + + if(!xdr_vector(xdrs, (char *)ints, + uiArraySize(ints), eSizeOf(ints), + (xdrproc_t)xdr_int)) + return 4; + + /* double the ints to check both ncx_ interfaces */ + if(!xdr_vector(xdrs, (char *)ints, + uiArraySize(ints), eSizeOf(ints), + (xdrproc_t)xdr_int)) + return 5; + +#ifndef NO_UNSIGNED + if(!xdr_vector(xdrs, (char *)u_ints, + uiArraySize(u_ints), eSizeOf(u_ints), + (xdrproc_t)xdr_u_int)) + return 6; +#endif + + if(!xdr_vector(xdrs, (char *)longs, + uiArraySize(longs), eSizeOf(longs), + (xdrproc_t)xdr_long)) + return 7; + +#ifndef NO_UNSIGNED_LONG + if(!xdr_vector(xdrs, (char *)u_longs, + uiArraySize(u_longs), eSizeOf(u_longs), + (xdrproc_t)xdr_u_long)) + return 9; +#endif + + if(!xdr_vector(xdrs, (char *)floats, + uiArraySize(floats), eSizeOf(floats), + (xdrproc_t)xdr_float)) + return 10; + + if(!xdr_vector(xdrs, (char *)doubles, + uiArraySize(doubles), eSizeOf(doubles), + (xdrproc_t)xdr_double)) + return 11; + + /* mix it up */ + for(ii = 1; ii < 5; ii++) + { + if( + !xdr_opaque(xdrs, (caddr_t)text, ii) + || !xdr_shorts(xdrs, shorts, ii) + || !xdr_opaque(xdrs, (caddr_t)schars, ii) + ) + return (11 + ii); + } + + /* + * Test non-aligned unit ops used by netcdf. + */ + + for(ii = 1; ii < 5; ii++) + { + pos = xdr_getpos(xdrs); + if(!xdr_NCvbyte(xdrs, ii, BYTES_PER_XDR_UNIT -ii, &text[ii])) + return (15 + ii); + if(!xdr_setpos(xdrs, pos + BYTES_PER_XDR_UNIT)) + return (15 + ii); + } + + for(ii = 1; ii < 5; ii++) + { + pos = xdr_getpos(xdrs); + if(!xdr_NCvbyte(xdrs, ii, BYTES_PER_XDR_UNIT -ii, + (char *)&schars[ii])) + return (19 + ii); + if(!xdr_setpos(xdrs, pos + BYTES_PER_XDR_UNIT)) + return (18 + ii); + } + + for(ii = 1; ii < 3; ii++) + { + pos = xdr_getpos(xdrs); + if(!xdr_NCvshort(xdrs, ii%2, &shorts[ii])) + return (23 + ii); + if(!xdr_setpos(xdrs, pos + BYTES_PER_XDR_UNIT)) + return (23 + ii); + } + + pos = xdr_getpos(xdrs); + (void) printf("xdr_encode ends at byte %u\n", pos); + + return 0; +} + + +static int +cmp_chars(const char *c1, const char *c2, size_t nchars) +{ + int status = 0; + const char *const end = c1 + nchars; + + while(c1 < end) + { + if(*c1 != *c2) + { + (void) fprintf(stderr, + "%c != %c char\n", + *c1, + *c2); + if(status == 0) + status = *c2 < *c1 ? -1 : 1; + } + c1++, c2++; + } + + return status; +} + +static int +cmp_schars(const schar *b1, const schar *b2, size_t nbytes) +{ + int status = 0; + const schar *const end = b1 + nbytes; + + while(b1 < end) + { + if(*b1 != *b2) + { + (void) fprintf(stderr, + "0x%02x != 0x%02x byte\n", + (unsigned)(*b1), + (unsigned)(*b2)); + + if(status == 0) + status = *b2 < *b1 ? -1 : 1; + } + b1++, b2++; + } + + return status; +} + +static int +cmp_shorts(const short *s1, const short *s2, size_t nshorts) +{ + int status = 0; + const short *const end = s1 + nshorts; + + while(s1 < end) + { + if(*s1 != *s2) + { + (void) fprintf(stderr, + "0x%04x != 0x%04x (%hd) short\n", + (unsigned)(*s1), + (unsigned)(*s2), *s2); + if(status == 0) + status = *s2 < *s1 ? -1 : 1; + } + s1++, s2++; + } + + return status; +} + +static int +cmp_ints(const int *i1, const int *i2, size_t nints) +{ + int status = 0; + const int *const end = i1 + nints; + + while(i1 < end) + { + if(*i1 != *i2) + { + (void) fprintf(stderr, + "0x%08x != 0x%08x int\n", + (unsigned)(*i1), + (unsigned)(*i2)); + if(status == 0) + status = *i2 < *i1 ? -1 : 1; + } + i1++, i2++; + } + + return status; +} + +#ifndef NO_UNSIGNED +static int +cmp_u_ints(const unsigned int *i1, const unsigned int *i2, size_t nints) +{ + int status = 0; + const unsigned int *const end = i1 + nints; + + while(i1 < end) + { + if(*i1 != *i2) + { + (void) fprintf(stderr, + "(%u) 0x%08x != 0x%08x (%u) uint\n", + *i1, *i1, + *i2, *i2); + if(status == 0) + status = *i2 < *i1 ? -1 : 1; + } + i1++, i2++; + } + + return status; +} +#endif + +static int +cmp_longs(const long *l1, const long *l2, size_t nlongs) +{ + int status = 0; + const long *const end = l1 + nlongs; + + while(l1 < end) + { + if(*l1 != *l2) + { + (void) fprintf(stderr, + "0x%016lx != 0x%016lx long\n", + (unsigned long)(*l1), + (unsigned long)(*l2)); + if(status == 0) + status = *l2 < *l1 ? -1 : 1; + } + l1++, l2++; + } + + return status; +} + +#ifndef NO_UNSIGNED_LONG +static int +cmp_u_longs(const unsigned long *l1, const unsigned long *l2, size_t nlongs) +{ + int status = 0; + const unsigned long *const end = l1 + nlongs; + + while(l1 < end) + { + if(*l1 != *l2) + { + (void) fprintf(stderr, + "0x%016lx != 0x%016lx ulong\n", + *l1, + *l2); + if(status == 0) + status = *l2 < *l1 ? -1 : 1; + } + l1++, l2++; + } + + return status; +} +#endif + +static int +cmp_floats(const float *f1, const float *f2, size_t nfloats) +{ +#define F_EPS 1.0e-6 + + int status = 0; + const float *const end = f1 + nfloats; + + while(f1 < end) + { + if(*f1 < *f2 && *f2 - *f1 > F_EPS) + { + (void) fprintf(stderr, + "%.9e != %.9e float (diff %.9e)\n", + *f1, *f2, *f1 - *f2); + if(status == 0) + status = 1; + } + else if( *f2 < *f1 && *f1 - *f2 > F_EPS) + { + (void) fprintf(stderr, + "%.9e != %.9e float (diff %.9e)\n", + *f1, *f2, *f1 - *f2); + if(status == 0) + status = -1; + } + f1++, f2++; + } + + return status; +} + +static int +cmp_doubles(const double *d1, const double *d2, size_t ndoubles) +{ +#define D_EPS 1.0e-15 + + int status = 0; + const double *const end = d1 + ndoubles; + + while(d1 < end) + { + if(*d1 < *d2 && *d2 - *d1 > D_EPS) + { + (void) fprintf(stderr, + "%.17e != %.17e double (diff %.17e)\n", + *d1, *d2, *d1 - *d2); + if(status == 0) + status = 1; + } + else if( *d2 < *d1 && *d1 - *d2 > D_EPS) + { + (void) fprintf(stderr, + "%.17e != %.17e double (diff %.17e)\n", + *d1, *d2, *d1 - *d2); + if(status == 0) + status = -1; + } + d1++, d2++; + } + + return status; +} + +/* + * Verify that data in buf is as encoded + * by xdr_encode() above. + * Returns zero on sucess. + */ +static int +xdr_check(char *buf, u_int sz) +{ + XDR xdrs[1]; + char tbuf[XBSZ]; + u_int pos; + int ii; + int jj; + + xdrmem_create(xdrs, buf, sz, XDR_DECODE); + + (void) memset(tbuf, 0, sizeof(text)+4); + if(!xdr_opaque(xdrs, (caddr_t)tbuf, (u_int)sizeof(text)) + || cmp_chars(tbuf, text, + sizeof(text)) != 0) + return 1; + + (void) memset(tbuf, 0, sizeof(schars)+4); + if(!xdr_opaque(xdrs, (caddr_t)tbuf, (u_int)sizeof(schars)) + || cmp_schars((schar *)tbuf, schars, + sizeof(schars)) != 0) + return 2; + + (void) memset(tbuf, 0, sizeof(shorts)+4); + if(!xdr_shorts(xdrs, (short *)tbuf, uiArraySize(shorts)) + || cmp_shorts((short *)tbuf, shorts, + ArraySize(shorts)) != 0) + return 3; + + (void) memset(tbuf, 0, sizeof(ints)+4); + if(!xdr_vector(xdrs, tbuf, + uiArraySize(ints), eSizeOf(ints), + (xdrproc_t)xdr_int) + || cmp_ints((int *)tbuf, ints, + ArraySize(ints)) != 0) + return 4; + + /* double the ints to check both ncx_ interfaces */ + (void) memset(tbuf, 0, sizeof(ints)+4); + if(!xdr_vector(xdrs, tbuf, + uiArraySize(ints), eSizeOf(ints), + (xdrproc_t)xdr_int) + || cmp_ints((int *)tbuf, ints, + ArraySize(ints)) != 0) + return 5; + +#ifndef NO_UNSIGNED + (void) memset(tbuf, 0, sizeof(u_ints)+4); + if(!xdr_vector(xdrs, tbuf, + uiArraySize(u_ints), eSizeOf(u_ints), + (xdrproc_t)xdr_u_int) + || cmp_u_ints((unsigned int *)tbuf, u_ints, + ArraySize(u_ints)) != 0) + return 6; +#endif + + (void) memset(tbuf, 0, sizeof(longs)+4); + if(!xdr_vector(xdrs, tbuf, + uiArraySize(longs), eSizeOf(longs), (xdrproc_t)xdr_long) + || cmp_longs((long *)tbuf, longs, + ArraySize(longs)) != 0) + return 7; + +#ifndef NO_UNSIGNED_LONG + (void) memset(tbuf, 0, sizeof(u_longs)+4); + if(!xdr_vector(xdrs, tbuf, + uiArraySize(u_longs), eSizeOf(u_longs), (xdrproc_t)xdr_u_long) + || cmp_u_longs((unsigned long *)tbuf, u_longs, + ArraySize(u_longs)) != 0) + return 9; +#endif + + (void) memset(tbuf, 0, sizeof(floats)+4); + if(!xdr_vector(xdrs, tbuf, + uiArraySize(floats), eSizeOf(floats), (xdrproc_t)xdr_float) + || cmp_floats((float *)tbuf, floats, + ArraySize(floats)) != 0) + return 10; + + (void) memset(tbuf, 0, sizeof(doubles)+4); + if(!xdr_vector(xdrs, tbuf, + uiArraySize(doubles), eSizeOf(doubles), (xdrproc_t)xdr_double) + || cmp_doubles((double *)tbuf, doubles, + ArraySize(doubles)) != 0) + return 11; + + for(ii = 1; ii < 5; ii++) + { + char tx[4]; + short sh[4]; + schar by[4]; + if( + !xdr_opaque(xdrs, (caddr_t)tx, ii) + || !xdr_shorts(xdrs, sh, ii) + || !xdr_opaque(xdrs, (caddr_t)by, ii) + ) + return (11 + ii); + for(jj = 0; jj < ii; jj++) + { + if(tx[jj] != text[jj]) + { + (void) fprintf(stderr, "\txdr %c != %c text[%d]\n", + tx[jj], text[jj], jj); + return (11 + ii); + } + /* else */ + if(sh[jj] != shorts[jj]) + { + (void) fprintf(stderr, "\txdr %hd != %hd shorts[%d]\n", + sh[jj], shorts[jj], jj); + return (11 + ii); + } + /* else */ + if(by[jj] != schars[jj]) + { + (void) fprintf(stderr, + "\txdr 0x%02x != 0x%02x schars[%d]\n", + (unsigned) by[jj], + (unsigned) schars[jj], jj); + return (11 + ii); + } + /* else */ + } + } + + /* + * Test non-aligned unit ops used by netcdf. + */ + + for(ii = 1; ii < 5; ii++) + { + pos = xdr_getpos(xdrs); + (void) memset(tbuf, 0, BYTES_PER_XDR_UNIT); + if(!xdr_NCvbyte(xdrs, ii, BYTES_PER_XDR_UNIT -ii, tbuf) + || cmp_chars(&text[ii], tbuf, + BYTES_PER_XDR_UNIT -ii) != 0) + return (15 + ii); + if(!xdr_setpos(xdrs, pos + BYTES_PER_XDR_UNIT)) + return (15 + ii); + } + + for(ii = 1; ii < 5; ii++) + { + pos = xdr_getpos(xdrs); + (void) memset(tbuf, 0, BYTES_PER_XDR_UNIT); + if(!xdr_NCvbyte(xdrs, ii, BYTES_PER_XDR_UNIT -ii, tbuf) + || cmp_schars((schar *)tbuf, &schars[ii], + BYTES_PER_XDR_UNIT -ii) != 0) + return (19 + ii); + if(!xdr_setpos(xdrs, pos + BYTES_PER_XDR_UNIT)) + return (19 + ii); + } + + for(ii = 1; ii < 3; ii++) + { + pos = xdr_getpos(xdrs); + (void) memset(tbuf, 0, BYTES_PER_XDR_UNIT); + if(!xdr_NCvshort(xdrs, ii%2, (short *)tbuf) + || cmp_shorts((short *)tbuf, &shorts[ii], 1)) + return (23 + ii); + if(!xdr_setpos(xdrs, pos + BYTES_PER_XDR_UNIT)) + return (23 + ii); + } + + pos = xdr_getpos(xdrs); + (void) printf("xdr_check ends at byte %u\n", pos); + + return 0; +} + + +/* Poor man's template */ +#define NCX_VEC(xpp, nn, vecp, TYPE, proc, step) \ +{ \ +\ + size_t nelems = (nn); \ + TYPE *elemp = (vecp); \ +\ + while(nelems != 0) \ + { \ + status = (proc)((*(xpp)), elemp); \ + if(status != ENOERR) \ + break; \ + (*(xpp)) = (void *)((char *)(*(xpp)) + (step)); \ + elemp ++; \ + nelems--; \ + } \ +} + + +/* + * Use ncx interface + * to encode data to 'buf' + * Returns zero on success. + */ +static int +ncx_encode(char *buf) +{ + int status = ENOERR; + + void *vp = buf; + int ii; + + if(ncx_pad_putn_text(&vp, sizeof(text), text)) + return 1; + + if(ncx_pad_putn_schar_schar(&vp, sizeof(schars), schars)) + return 2; + + if(ncx_pad_putn_short_short(&vp, ArraySize(shorts), shorts)) + return 3; + + if(ncx_putn_int_int(&vp, ArraySize(ints), ints)) + return 4; + + NCX_VEC(&vp, ArraySize(ints), ints, + int, ncx_put_int_int, X_SIZEOF_INT); + if(status != ENOERR) + return 5; + +#ifndef NO_UNSIGNED + NCX_VEC(&vp, ArraySize(u_ints), u_ints, + unsigned int, ncx_put_uint_uint, X_SIZEOF_INT); + if(status != ENOERR) + return 6; +#endif + + if(ncx_putn_int_long(&vp, ArraySize(longs), longs)) + return 7; + +#ifndef NO_UNSIGNED_LONG + NCX_VEC(&vp, ArraySize(u_longs), u_longs, + unsigned long, ncx_put_ulong_ulong, X_SIZEOF_LONG); + if(status != ENOERR) + return 9; +#endif + + if(ncx_putn_float_float(&vp, ArraySize(floats), floats)) + return 10; + + if(ncx_putn_double_double(&vp, ArraySize(doubles), doubles)) + return 11; + + /* mix it up */ + for(ii = 1; ii < 5; ii++) + { + if( + ncx_pad_putn_text(&vp, ii, text) + || ncx_pad_putn_short_short(&vp, ii, shorts) + || ncx_pad_putn_schar_schar(&vp, ii, schars) + ) + return (11 + ii); + } + + /* + * Test non-aligned unit ops used by netcdf. + */ + + for(ii = 1; ii < 5; ii++) + { + vp = (char *)vp + ii; + if(ncx_putn_text(&vp, X_ALIGN - ii, &text[ii])) + return (15 + ii); + } + + for(ii = 1; ii < 5; ii++) + { + vp = (char *)vp + ii; + if(ncx_putn_schar_schar(&vp, X_ALIGN - ii, &schars[ii])) + return (19 + ii); + } + + for(ii = 1; ii < 3; ii++) + { + char *pos = vp; + vp = (char *)vp + (ii%2) * 2; + if(ncx_putn_short_short(&vp, 1, &shorts[ii])) + return (23 + ii); + vp = pos + X_ALIGN; + } + + (void) printf("ncx_encode ends at byte %u\n", + (unsigned)(((char *)vp) - buf)); + + return 0; +} + +/* + * Verify the ncx_getn_xxx() routines. + * Returns zero on success. + */ +static int +ncx_check(char *buf) +{ + int status = ENOERR; + const void *vp = buf; + char tbuf[XBSZ]; + int ii; + int jj; + + (void) memset(tbuf, 0, sizeof(text)+4); + if(ncx_pad_getn_text(&vp, sizeof(text), tbuf) + || cmp_chars(tbuf, text, + sizeof(text)) != 0) + return 1; + + (void) memset(tbuf, 0, sizeof(schars)+4); + if(ncx_pad_getn_schar_schar(&vp, sizeof(schars), (schar *)tbuf) + || cmp_schars((schar *)tbuf, schars, + sizeof(schars)) != 0) + return 2; + + (void) memset(tbuf, 0, sizeof(shorts)+4); + if(ncx_pad_getn_short_short(&vp, ArraySize(shorts), (short *)tbuf) + || cmp_shorts((short *)tbuf, shorts, + ArraySize(shorts)) != 0) + return 3; + + (void) memset(tbuf, 0, sizeof(ints)+4); + if(ncx_getn_int_int(&vp, ArraySize(ints), (int *)tbuf) + || cmp_ints((int *)tbuf, ints, + ArraySize(ints)) != 0) + return 4; + + (void) memset(tbuf, 0, sizeof(ints)+4); + NCX_VEC(&vp, ArraySize(ints), (int *)tbuf, + int, ncx_get_int_int, X_SIZEOF_INT); + if(status != ENOERR + || cmp_ints((int *)tbuf, ints, + ArraySize(ints)) != 0) + return 5; + +#ifndef NO_UNSIGNED + (void) memset(tbuf, 0, sizeof(u_ints)+4); + NCX_VEC(&vp, ArraySize(u_ints), (unsigned int *)tbuf, + unsigned, ncx_get_uint_uint, X_SIZEOF_INT); + if(status != ENOERR + || cmp_u_ints((unsigned int *)tbuf, u_ints, + ArraySize(u_ints)) != 0) + return 6; +#endif + + (void) memset(tbuf, 0, sizeof(longs)+4); + if(ncx_getn_int_long(&vp, ArraySize(longs), (long *)tbuf) + || cmp_longs((long *)tbuf, longs, + ArraySize(longs)) != 0) + return 7; + +#ifndef NO_UNSIGNED_LONG + (void) memset(tbuf, 0, sizeof(u_longs)+4); + NCX_VEC(&vp, ArraySize(u_longs), (unsigned long *)tbuf, + unsigned long, ncx_get_ulong_ulong, X_SIZEOF_LONG); + if(status != ENOERR + || cmp_u_longs((unsigned long *)tbuf, u_longs, + ArraySize(u_longs)) != 0) + return 9; +#endif + + (void) memset(tbuf, 0, sizeof(floats)+4); + if(ncx_getn_float_float(&vp, ArraySize(floats), (float *)tbuf) + || cmp_floats((float *)tbuf, floats, + ArraySize(floats)) != 0) + return 10; + + (void) memset(tbuf, 0, sizeof(doubles)+4); + if(ncx_getn_double_double(&vp, ArraySize(doubles), (double *)tbuf) + || cmp_doubles((double *)tbuf, doubles, + ArraySize(doubles)) != 0) + return 11; + + for(ii = 1; ii < 5; ii++) + { + char tx[4]; + short sh[4]; + schar by[4]; + if( + ncx_pad_getn_text(&vp, ii, tx) + || ncx_pad_getn_short_short(&vp, ii, sh) + || ncx_pad_getn_schar_schar(&vp, ii, by) + ) + return (11 + ii); + for(jj = 0; jj < ii; jj++) + { + if(tx[jj] != text[jj]) + { + (void) fprintf(stderr, + "\tncx %c != %c text[%d]\n", + tx[jj], text[jj], jj); + return (11 + ii); + } + /* else */ + if(sh[jj] != shorts[jj]) + { + (void) fprintf(stderr, + "\tncx %hd != %hd shorts[%d]\n", + sh[jj], shorts[jj], jj); + return (11 + ii); + } + /* else */ + if((unsigned)by[jj] != (unsigned)schars[jj]) + { + (void) fprintf(stderr, + "\tncx 0x%02x != 0x%02x schars[%d] %d\n", + by[jj], schars[jj], jj, ii); + return (11 + ii); + } + } + } + + /* + * Test non-aligned unit ops used by netcdf. + */ + + for(ii = 1; ii < 5; ii++) + { + (void) memset(tbuf, 0, X_ALIGN); + vp = (char *)vp + ii; + if(ncx_getn_text(&vp, X_ALIGN -ii, tbuf) + || cmp_chars(tbuf, &text[ii], + X_ALIGN -ii) != 0) + return (15 + ii); + } + + for(ii = 1; ii < 5; ii++) + { + (void) memset(tbuf, 0, X_ALIGN); + vp = (char *)vp + ii; + if(ncx_getn_schar_schar(&vp, X_ALIGN -ii, (schar *)tbuf) + || cmp_schars((schar *)tbuf, &schars[ii], + X_ALIGN -ii) != 0) + return (19 + ii); + } + + for(ii = 1; ii < 3; ii++) + { + const char *pos = vp; + (void) memset(tbuf, 0, X_ALIGN); + vp = (char *)vp + (ii%2) *2; + if(ncx_getn_short_short(&vp, 1, (short *)tbuf) + || cmp_shorts((short *)tbuf, &shorts[ii], + 1) != 0) + return (23 + ii); + vp = pos + X_ALIGN; + } + + (void) printf("ncx_check ends at byte %u\n", + (unsigned)(((char *)vp) - buf)); + + + return 0; +} + + +int +main(int ac, char *av[]) +{ + int status; + + status = xdr_encode(xdrb, sizeof(xdrb)); + if(status) + { + (void) fprintf(stderr, + "xdr_encode failed %d\n", status); + return 1; + } + + status = xdr_check(xdrb, sizeof(xdrb)); + if(status) + { + (void) fprintf(stderr, + "xdr_check of xdrb failed %d\n", status); + return 1; + } + + status = ncx_encode(ncxb); + if(status) + { + (void) fprintf(stderr, + "ncx_encode failed %d\n", status); + return 1; + } + + /* cross check */ + status = xdr_check(ncxb, sizeof(ncxb)); + if(status) + { + (void) fprintf(stderr, + "xdr_check of ncxb failed %d\n", status); + return 1; + } + + status = ncx_check(xdrb); + if(status) + { + (void) fprintf(stderr, + "ncx_check of xdrb failed %d\n", status); + return 1; + } + + status = ncx_check(ncxb); + if(status) + { + (void) fprintf(stderr, + "ncx_check of ncxb failed %d\n", status); + return 1; + } + + return 0; +} diff --git a/Utilities/vtknetcdf/v1hpg.c b/Utilities/vtknetcdf/v1hpg.c new file mode 100644 index 0000000..3b1a69a --- /dev/null +++ b/Utilities/vtknetcdf/v1hpg.c @@ -0,0 +1,1348 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: v1hpg.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#include "nc.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "rnd.h" +#include "ncx.h" + +/* + * This module defines the external representation + * of the "header" of a netcdf version one file. + * For each of the components of the NC structure, + * There are (static) ncx_len_XXX(), ncx_put_XXX() + * and v1h_get_XXX() functions. These define the + * external representation of the components. + * The exported entry points for the whole NC structure + * are built up from these. + */ + + +/* + * "magic number" at beginning of file: 0x43444601 (big endian) + * assert(sizeof(ncmagic) % X_ALIGN == 0); + */ +static const schar ncmagic[] = {'C', 'D', 'F', 0x02}; +static const schar ncmagic1[] = {'C', 'D', 'F', 0x01}; + +/* + * v1hs == "Version 1 Header Stream" + * + * The netcdf file version 1 header is + * of unknown and potentially unlimited size. + * So, we don't know how much to get() on + * the initial read. We build a stream, 'v1hs' + * on top of ncio to do the header get. + */ +typedef struct v1hs { + ncio *nciop; + off_t offset; /* argument to nciop->get() */ + size_t extent; /* argument to nciop->get() */ + int flags; /* set to RGN_WRITE for write */ + int version; /* either 1 for normal netcdf or 2 for 8-byte offset version */ + void *base; /* beginning of current buffer */ + void *pos; /* current position in buffer */ + void *end; /* end of current buffer = base + extent */ +} v1hs; + + +/* + * Release the stream, invalidate buffer + */ +static int +rel_v1hs(v1hs *gsp) +{ + int status; + if(gsp->offset == OFF_NONE || gsp->base == NULL) + return ENOERR; + status = gsp->nciop->rel(gsp->nciop, gsp->offset, + gsp->flags == RGN_WRITE ? RGN_MODIFIED : 0); + gsp->end = NULL; + gsp->pos = NULL; + gsp->base = NULL; + return status; +} + + +/* + * Release the current chunk and get the next one. + * Also used for initialization when gsp->base == NULL. + */ +static int +fault_v1hs(v1hs *gsp, size_t extent) +{ + int status; + + if(gsp->base != NULL) + { + const size_t incr = (char *)gsp->pos - (char *)gsp->base; + status = rel_v1hs(gsp); + if(status) + return status; + gsp->offset += incr; + } + + if(extent > gsp->extent) + gsp->extent = extent; + + status = gsp->nciop->get(gsp->nciop, + gsp->offset, gsp->extent, + gsp->flags, &gsp->base); + if(status) + return status; + + gsp->pos = gsp->base; + gsp->end = (char *)gsp->base + gsp->extent; + + return ENOERR; +} + + +/* + * Ensure that 'nextread' bytes are available. + */ +static int +check_v1hs(v1hs *gsp, size_t nextread) +{ + +#if 0 /* DEBUG */ +fprintf(stderr, "nextread %lu, remaining %lu\n", + (unsigned long)nextread, + (unsigned long)((char *)gsp->end - (char *)gsp->pos)); +#endif + + if((char *)gsp->pos + nextread < (char *)gsp->end) + return ENOERR; + return fault_v1hs(gsp, nextread); +} + +/* End v1hs */ + +static int +v1h_put_size_t(v1hs *psp, const size_t *sp) +{ + int status = check_v1hs(psp, psp->version == 1 ? 4 : 8); + if(status != ENOERR) + return status; + return ncx_put_size_t(&psp->pos, sp); +} + + +static int +v1h_get_size_t(v1hs *gsp, size_t *sp) +{ + int status = check_v1hs(gsp, gsp->version == 1 ? 4 : 8); + if(status != ENOERR) + return status; + return ncx_get_size_t((const void **)(&gsp->pos), sp); +} + + +/* Begin nc_type */ + +#define X_SIZEOF_NC_TYPE X_SIZEOF_INT + +static int +v1h_put_nc_type(v1hs *psp, const nc_type *typep) +{ + const int itype = (int) *typep; + int status = check_v1hs(psp, X_SIZEOF_INT); + if(status != ENOERR) + return status; + status = ncx_put_int_int(psp->pos, &itype); + psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT); + return status; +} + + +static int +v1h_get_nc_type(v1hs *gsp, nc_type *typep) +{ + int type = 0; + int status = check_v1hs(gsp, X_SIZEOF_INT); + if(status != ENOERR) + return status; + status = ncx_get_int_int(gsp->pos, &type); + gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT); + if(status != ENOERR) + return status; + + assert(type == NC_BYTE + || type == NC_CHAR + || type == NC_SHORT + || type == NC_INT + || type == NC_FLOAT + || type == NC_DOUBLE); + + /* else */ + *typep = (nc_type) type; + + return ENOERR; +} + +/* End nc_type */ +/* Begin NCtype (internal tags) */ + +#define X_SIZEOF_NCTYPE X_SIZEOF_INT + +static int +v1h_put_NCtype(v1hs *psp, NCtype type) +{ + const int itype = (int) type; + int status = check_v1hs(psp, X_SIZEOF_INT); + if(status != ENOERR) + return status; + status = ncx_put_int_int(psp->pos, &itype); + psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT); + return status; +} + +static int +v1h_get_NCtype(v1hs *gsp, NCtype *typep) +{ + int type = 0; + int status = check_v1hs(gsp, X_SIZEOF_INT); + if(status != ENOERR) + return status; + status = ncx_get_int_int(gsp->pos, &type); + gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT); + if(status != ENOERR) + return status; + /* else */ + *typep = (NCtype) type; + return ENOERR; +} + +/* End NCtype */ +/* Begin NC_string */ + +/* + * How much space will the xdr'd string take. + * Formerly +NC_xlen_string(cdfstr) + */ +static size_t +ncx_len_NC_string(const NC_string *ncstrp) +{ + size_t sz = X_SIZEOF_SIZE_T; /* nchars */ + + assert(ncstrp != NULL); + + if(ncstrp->nchars != 0) + { +#if 0 + assert(ncstrp->nchars % X_ALIGN == 0); + sz += ncstrp->nchars; +#else + sz += _RNDUP(ncstrp->nchars, X_ALIGN); +#endif + } + return sz; +} + + +static int +v1h_put_NC_string(v1hs *psp, const NC_string *ncstrp) +{ + int status; + +#if 0 + assert(ncstrp->nchars % X_ALIGN == 0); +#endif + + status = v1h_put_size_t(psp, &ncstrp->nchars); + if(status != ENOERR) + return status; + status = check_v1hs(psp, _RNDUP(ncstrp->nchars, X_ALIGN)); + if(status != ENOERR) + return status; + status = ncx_pad_putn_text(&psp->pos, ncstrp->nchars, ncstrp->cp); + if(status != ENOERR) + return status; + + return ENOERR; +} + + +static int +v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp) +{ + int status; + size_t nchars = 0; + NC_string *ncstrp; + + status = v1h_get_size_t(gsp, &nchars); + if(status != ENOERR) + return status; + + ncstrp = new_NC_string(nchars, NULL); + if(ncstrp == NULL) + { + return NC_ENOMEM; + } + + +#if 0 +/* assert(ncstrp->nchars == nchars || ncstrp->nchars - nchars < X_ALIGN); */ + assert(ncstrp->nchars % X_ALIGN == 0); + status = check_v1hs(gsp, ncstrp->nchars); +#else + + status = check_v1hs(gsp, _RNDUP(ncstrp->nchars, X_ALIGN)); +#endif + if(status != ENOERR) + goto unwind_alloc; + + status = ncx_pad_getn_text((const void **)(&gsp->pos), + nchars, ncstrp->cp); + if(status != ENOERR) + goto unwind_alloc; + + *ncstrpp = ncstrp; + + return ENOERR; + +unwind_alloc: + free_NC_string(ncstrp); + return status; + +} + +/* End NC_string */ +/* Begin NC_dim */ + +/* + * How much space will the xdr'd dim take. + * Formerly +NC_xlen_dim(dpp) + */ +static size_t +ncx_len_NC_dim(const NC_dim *dimp) +{ + size_t sz; + + assert(dimp != NULL); + + sz = ncx_len_NC_string(dimp->name); + sz += X_SIZEOF_SIZE_T; + + return(sz); +} + + +static int +v1h_put_NC_dim(v1hs *psp, const NC_dim *dimp) +{ + int status; + + status = v1h_put_NC_string(psp, dimp->name); + if(status != ENOERR) + return status; + + status = v1h_put_size_t(psp, &dimp->size); + if(status != ENOERR) + return status; + + return ENOERR; +} + +static int +v1h_get_NC_dim(v1hs *gsp, NC_dim **dimpp) +{ + int status; + NC_string *ncstrp; + NC_dim *dimp; + + status = v1h_get_NC_string(gsp, &ncstrp); + if(status != ENOERR) + return status; + + dimp = new_x_NC_dim(ncstrp); + if(dimp == NULL) + { + status = NC_ENOMEM; + goto unwind_name; + } + + status = v1h_get_size_t(gsp, &dimp->size); + if(status != ENOERR) + { + free_NC_dim(dimp); /* frees name */ + return status; + } + + *dimpp = dimp; + + return ENOERR; + +unwind_name: + free_NC_string(ncstrp); + return status; +} + + +static size_t +ncx_len_NC_dimarray(const NC_dimarray *ncap) +{ + size_t xlen = X_SIZEOF_NCTYPE; /* type */ + xlen += X_SIZEOF_SIZE_T; /* count */ + if(ncap == NULL) + return xlen; + /* else */ + { + const NC_dim **dpp = (const NC_dim **)ncap->value; + const NC_dim *const *const end = &dpp[ncap->nelems]; + for( /*NADA*/; dpp < end; dpp++) + { + xlen += ncx_len_NC_dim(*dpp); + } + } + return xlen; +} + + +static int +v1h_put_NC_dimarray(v1hs *psp, const NC_dimarray *ncap) +{ + int status; + + assert(psp != NULL); + + if(ncap == NULL +#if 1 + /* Backward: + * This clause is for 'byte for byte' + * backward compatibility. + * Strickly speaking, it is 'bug for bug'. + */ + || ncap->nelems == 0 +#endif + ) + { + /* + * Handle empty netcdf + */ + const size_t nosz = 0; + + status = v1h_put_NCtype(psp, NC_UNSPECIFIED); + if(status != ENOERR) + return status; + status = v1h_put_size_t(psp, &nosz); + if(status != ENOERR) + return status; + return ENOERR; + } + /* else */ + + status = v1h_put_NCtype(psp, NC_DIMENSION); + if(status != ENOERR) + return status; + status = v1h_put_size_t(psp, &ncap->nelems); + if(status != ENOERR) + return status; + + { + const NC_dim **dpp = (const NC_dim **)ncap->value; + const NC_dim *const *const end = &dpp[ncap->nelems]; + for( /*NADA*/; dpp < end; dpp++) + { + status = v1h_put_NC_dim(psp, *dpp); + if(status) + return status; + } + } + return ENOERR; +} + + +static int +v1h_get_NC_dimarray(v1hs *gsp, NC_dimarray *ncap) +{ + int status; + NCtype type = NC_UNSPECIFIED; + + assert(gsp != NULL && gsp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = v1h_get_NCtype(gsp, &type); + if(status != ENOERR) + return status; + + status = v1h_get_size_t(gsp, &ncap->nelems); + if(status != ENOERR) + return status; + + if(ncap->nelems == 0) + return ENOERR; + /* else */ + if(type != NC_DIMENSION) + return EINVAL; + + ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + { + NC_dim **dpp = ncap->value; + NC_dim *const *const end = &dpp[ncap->nelems]; + for( /*NADA*/; dpp < end; dpp++) + { + status = v1h_get_NC_dim(gsp, dpp); + if(status) + { + ncap->nelems = dpp - ncap->value; + free_NC_dimarrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + + +/* End NC_dim */ +/* Begin NC_attr */ + + +/* + * How much space will 'attrp' take in external representation? + * Formerly +NC_xlen_attr(app) + */ +static size_t +ncx_len_NC_attr(const NC_attr *attrp) +{ + size_t sz; + + assert(attrp != NULL); + + sz = ncx_len_NC_string(attrp->name); + sz += X_SIZEOF_NC_TYPE; /* type */ + sz += X_SIZEOF_SIZE_T; /* nelems */ + sz += attrp->xsz; + + return(sz); +} + + +#undef MIN +#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn)) + +/* + * Put the values of an attribute + * The loop is necessary since attrp->nelems + * could potentially be quite large. + */ +static int +v1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp) +{ + int status; + const size_t perchunk = psp->extent; + size_t remaining = attrp->xsz; + void *value = attrp->xvalue; + size_t nbytes; + + assert(psp->extent % X_ALIGN == 0); + + do { + nbytes = MIN(perchunk, remaining); + + status = check_v1hs(psp, nbytes); + if(status != ENOERR) + return status; + + (void) memcpy(psp->pos, value, nbytes); + + psp->pos = (void *)((char *)psp->pos + nbytes); + value = (void *)((char *)value + nbytes); + remaining -= nbytes; + + } while(remaining != 0); + + return ENOERR; +} + +static int +v1h_put_NC_attr(v1hs *psp, const NC_attr *attrp) +{ + int status; + + status = v1h_put_NC_string(psp, attrp->name); + if(status != ENOERR) + return status; + + status = v1h_put_nc_type(psp, &attrp->type); + if(status != ENOERR) + return status; + + status = v1h_put_size_t(psp, &attrp->nelems); + if(status != ENOERR) + return status; + + status = v1h_put_NC_attrV(psp, attrp); + if(status != ENOERR) + return status; + + return ENOERR; +} + + +/* + * Get the values of an attribute + * The loop is necessary since attrp->nelems + * could potentially be quite large. + */ +static int +v1h_get_NC_attrV(v1hs *gsp, NC_attr *attrp) +{ + int status; + const size_t perchunk = gsp->extent; + size_t remaining = attrp->xsz; + void *value = attrp->xvalue; + size_t nget; + + assert(gsp->extent % X_ALIGN == 0); + + do { + nget = MIN(perchunk, remaining); + + status = check_v1hs(gsp, nget); + if(status != ENOERR) + return status; + + (void) memcpy(value, gsp->pos, nget); + + gsp->pos = (void *)((char *)gsp->pos + nget); + value = (void *)((char *)value + nget); + remaining -= nget; + + } while(remaining != 0); + + return ENOERR; +} + + +static int +v1h_get_NC_attr(v1hs *gsp, NC_attr **attrpp) +{ + NC_string *strp; + int status; + nc_type type; + size_t nelems; + NC_attr *attrp; + + status = v1h_get_NC_string(gsp, &strp); + if(status != ENOERR) + return status; + + status = v1h_get_nc_type(gsp, &type); + if(status != ENOERR) + goto unwind_name; + + status = v1h_get_size_t(gsp, &nelems); + if(status != ENOERR) + goto unwind_name; + + attrp = new_x_NC_attr(strp, type, nelems); + if(attrp == NULL) + { + status = NC_ENOMEM; + goto unwind_name; + } + + status = v1h_get_NC_attrV(gsp, attrp); + if(status != ENOERR) + { + free_NC_attr(attrp); /* frees strp */ + return status; + } + + *attrpp = attrp; + + return ENOERR; + +unwind_name: + free_NC_string(strp); + return status; +} + + +static size_t +ncx_len_NC_attrarray(const NC_attrarray *ncap) +{ + size_t xlen = X_SIZEOF_NCTYPE; /* type */ + xlen += X_SIZEOF_SIZE_T; /* count */ + if(ncap == NULL) + return xlen; + /* else */ + { + const NC_attr **app = (const NC_attr **)ncap->value; + const NC_attr *const *const end = &app[ncap->nelems]; + for( /*NADA*/; app < end; app++) + { + xlen += ncx_len_NC_attr(*app); + } + } + return xlen; +} + + +static int +v1h_put_NC_attrarray(v1hs *psp, const NC_attrarray *ncap) +{ + int status; + + assert(psp != NULL); + + if(ncap == NULL +#if 1 + /* Backward: + * This clause is for 'byte for byte' + * backward compatibility. + * Strickly speaking, it is 'bug for bug'. + */ + || ncap->nelems == 0 +#endif + ) + { + /* + * Handle empty netcdf + */ + const size_t nosz = 0; + + status = v1h_put_NCtype(psp, NC_UNSPECIFIED); + if(status != ENOERR) + return status; + status = v1h_put_size_t(psp, &nosz); + if(status != ENOERR) + return status; + return ENOERR; + } + /* else */ + + status = v1h_put_NCtype(psp, NC_ATTRIBUTE); + if(status != ENOERR) + return status; + status = v1h_put_size_t(psp, &ncap->nelems); + if(status != ENOERR) + return status; + + { + const NC_attr **app = (const NC_attr **)ncap->value; + const NC_attr *const *const end = &app[ncap->nelems]; + for( /*NADA*/; app < end; app++) + { + status = v1h_put_NC_attr(psp, *app); + if(status) + return status; + } + } + return ENOERR; +} + + +static int +v1h_get_NC_attrarray(v1hs *gsp, NC_attrarray *ncap) +{ + int status; + NCtype type = NC_UNSPECIFIED; + + assert(gsp != NULL && gsp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = v1h_get_NCtype(gsp, &type); + if(status != ENOERR) + return status; + status = v1h_get_size_t(gsp, &ncap->nelems); + if(status != ENOERR) + return status; + + if(ncap->nelems == 0) + return ENOERR; + /* else */ + if(type != NC_ATTRIBUTE) + return EINVAL; + + ncap->value = (NC_attr **) malloc(ncap->nelems * sizeof(NC_attr *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + { + NC_attr **app = ncap->value; + NC_attr *const *const end = &app[ncap->nelems]; + for( /*NADA*/; app < end; app++) + { + status = v1h_get_NC_attr(gsp, app); + if(status) + { + ncap->nelems = app - ncap->value; + free_NC_attrarrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + +/* End NC_attr */ +/* Begin NC_var */ + +/* + * How much space will the xdr'd var take. + * Formerly +NC_xlen_var(vpp) + */ +static size_t +ncx_len_NC_var(const NC_var *varp, size_t sizeof_off_t) +{ + size_t sz; + + assert(varp != NULL); + assert(sizeof_off_t != 0); + + sz = ncx_len_NC_string(varp->name); + sz += X_SIZEOF_SIZE_T; /* ndims */ + sz += ncx_len_int(varp->ndims); /* dimids */ + sz += ncx_len_NC_attrarray(&varp->attrs); + sz += X_SIZEOF_NC_TYPE; /* type */ + sz += X_SIZEOF_SIZE_T; /* len */ + sz += sizeof_off_t; /* begin */ + + return(sz); +} + + +static int +v1h_put_NC_var(v1hs *psp, const NC_var *varp) +{ + int status; + + status = v1h_put_NC_string(psp, varp->name); + if(status != ENOERR) + return status; + + status = v1h_put_size_t(psp, &varp->ndims); + if(status != ENOERR) + return status; + + status = check_v1hs(psp, ncx_len_int(varp->ndims)); + if(status != ENOERR) + return status; + status = ncx_putn_int_int(&psp->pos, + varp->ndims, varp->dimids); + if(status != ENOERR) + return status; + + status = v1h_put_NC_attrarray(psp, &varp->attrs); + if(status != ENOERR) + return status; + + status = v1h_put_nc_type(psp, &varp->type); + if(status != ENOERR) + return status; + + status = v1h_put_size_t(psp, &varp->len); + if(status != ENOERR) + return status; + +#if 0 + fprintf(stderr, "VarWr: %s--%d bytes\n", varp->name->cp, varp->len); +#endif + + status = check_v1hs(psp, psp->version == 1 ? 4 : 8); + if(status != ENOERR) + return status; + status = ncx_put_off_t(&psp->pos, &varp->begin, psp->version == 1 ? 4 : 8); + if(status != ENOERR) + return status; + + return ENOERR; +} + + +static int +v1h_get_NC_var(v1hs *gsp, NC_var **varpp) +{ + NC_string *strp; + int status; + size_t ndims; + NC_var *varp; + + status = v1h_get_NC_string(gsp, &strp); + if(status != ENOERR) + return status; + + status = v1h_get_size_t(gsp, &ndims); + if(status != ENOERR) + goto unwind_name; + + varp = new_x_NC_var(strp, ndims); + if(varp == NULL) + { + status = NC_ENOMEM; + goto unwind_name; + } + + status = check_v1hs(gsp, ncx_len_int(ndims)); + if(status != ENOERR) + goto unwind_alloc; + status = ncx_getn_int_int((const void **)(&gsp->pos), + ndims, varp->dimids); + if(status != ENOERR) + goto unwind_alloc; + + status = v1h_get_NC_attrarray(gsp, &varp->attrs); + if(status != ENOERR) + goto unwind_alloc; + + status = v1h_get_nc_type(gsp, &varp->type); + if(status != ENOERR) + goto unwind_alloc; + + status = v1h_get_size_t(gsp, &varp->len); + if(status != ENOERR) + goto unwind_alloc; + +#if 0 + fprintf(stderr, "VarRd: %s--%d bytes\n", varp->name->cp, varp->len); +#endif + + status = check_v1hs(gsp, gsp->version == 1 ? 4 : 8); + if(status != ENOERR) + goto unwind_alloc; + status = ncx_get_off_t((const void **)&gsp->pos, + &varp->begin, gsp->version == 1 ? 4 : 8); + if(status != ENOERR) + goto unwind_alloc; + + *varpp = varp; + return ENOERR; + +unwind_alloc: + free_NC_var(varp); /* frees name */ + return status; + +unwind_name: + free_NC_string(strp); + return status; +} + + +static size_t +ncx_len_NC_vararray(const NC_vararray *ncap, size_t sizeof_off_t) +{ + size_t xlen = X_SIZEOF_NCTYPE; /* type */ + xlen += X_SIZEOF_SIZE_T; /* count */ + if(ncap == NULL) + return xlen; + /* else */ + { + const NC_var **vpp = (const NC_var **)ncap->value; + const NC_var *const *const end = &vpp[ncap->nelems]; + for( /*NADA*/; vpp < end; vpp++) + { + xlen += ncx_len_NC_var(*vpp, sizeof_off_t); + } + } + return xlen; +} + + +static int +v1h_put_NC_vararray(v1hs *psp, const NC_vararray *ncap) +{ + int status; + + assert(psp != NULL); + + if(ncap == NULL +#if 1 + /* Backward: + * This clause is for 'byte for byte' + * backward compatibility. + * Strickly speaking, it is 'bug for bug'. + */ + || ncap->nelems == 0 +#endif + ) + { + /* + * Handle empty netcdf + */ + const size_t nosz = 0; + + status = v1h_put_NCtype(psp, NC_UNSPECIFIED); + if(status != ENOERR) + return status; + status = v1h_put_size_t(psp, &nosz); + if(status != ENOERR) + return status; + return ENOERR; + } + /* else */ + + status = v1h_put_NCtype(psp, NC_VARIABLE); + if(status != ENOERR) + return status; + status = v1h_put_size_t(psp, &ncap->nelems); + if(status != ENOERR) + return status; + + { + const NC_var **vpp = (const NC_var **)ncap->value; + const NC_var *const *const end = &vpp[ncap->nelems]; + for( /*NADA*/; vpp < end; vpp++) + { + status = v1h_put_NC_var(psp, *vpp); + if(status) + return status; + } + } + return ENOERR; +} + + +static int +v1h_get_NC_vararray(v1hs *gsp, NC_vararray *ncap) +{ + int status; + NCtype type = NC_UNSPECIFIED; + + assert(gsp != NULL && gsp->pos != NULL); + assert(ncap != NULL); + assert(ncap->value == NULL); + + status = v1h_get_NCtype(gsp, &type); + if(status != ENOERR) + return status; + + status = v1h_get_size_t(gsp, &ncap->nelems); + if(status != ENOERR) + return status; + + if(ncap->nelems == 0) + return ENOERR; + /* else */ + if(type != NC_VARIABLE) + return EINVAL; + + ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *)); + if(ncap->value == NULL) + return NC_ENOMEM; + ncap->nalloc = ncap->nelems; + + { + NC_var **vpp = ncap->value; + NC_var *const *const end = &vpp[ncap->nelems]; + for( /*NADA*/; vpp < end; vpp++) + { + status = v1h_get_NC_var(gsp, vpp); + if(status) + { + ncap->nelems = vpp - ncap->value; + free_NC_vararrayV(ncap); + return status; + } + } + } + + return ENOERR; +} + + +/* End NC_var */ +/* Begin NC */ + + +/* + * Recompute the shapes of all variables + * Sets ncp->begin_var to start of first variable. + * Sets ncp->begin_rec to start of first record variable. + * Returns -1 on error. The only possible error is an reference + * to a non existent dimension, which would occur for a corrupt + * netcdf file. + */ +static int +NC_computeshapes(NC *ncp) +{ + NC_var **vpp = (NC_var **)ncp->vars.value; + NC_var *const *const end = &vpp[ncp->vars.nelems]; + NC_var *first_var = NULL; /* first "non-record" var */ + NC_var *first_rec = NULL; /* first "record" var */ + int status; + + ncp->begin_var = (off_t) ncp->xsz; + ncp->begin_rec = (off_t) ncp->xsz; + ncp->recsize = 0; + + if(ncp->vars.nelems == 0) + return(0); + + for( /*NADA*/; vpp < end; vpp++) + { + status = NC_var_shape(*vpp, &ncp->dims); + if(status != ENOERR) + return(status); + + if(IS_RECVAR(*vpp)) + { + if(first_rec == NULL) + first_rec = *vpp; + ncp->recsize += (*vpp)->len; + } + else if(first_var == NULL) + { + first_var = *vpp; + /* + * Overwritten each time thru. + * Usually overwritten in first_rec != NULL clause. + */ + ncp->begin_rec = (*vpp)->begin + (off_t)(*vpp)->len; + } + } + + if(first_rec != NULL) + { + assert(ncp->begin_rec <= first_rec->begin); + ncp->begin_rec = first_rec->begin; + /* + * for special case of exactly one record variable, pack value + */ + if(ncp->recsize == first_rec->len) + ncp->recsize = *first_rec->dsizes * first_rec->xsz; + } + + if(first_var != NULL) + { + ncp->begin_var = first_var->begin; + } + else + { + ncp->begin_var = ncp->begin_rec; + } + + assert(ncp->begin_var > 0); + assert(ncp->xsz <= (size_t)ncp->begin_var); + assert(ncp->begin_rec > 0); + assert(ncp->begin_var <= ncp->begin_rec); + + return(ENOERR); +} + + +size_t +ncx_len_NC(const NC *ncp, size_t sizeof_off_t) +{ + size_t xlen = sizeof(ncmagic); + + assert(ncp != NULL); + + xlen += X_SIZEOF_SIZE_T; /* numrecs */ + xlen += ncx_len_NC_dimarray(&ncp->dims); + xlen += ncx_len_NC_attrarray(&ncp->attrs); + xlen += ncx_len_NC_vararray(&ncp->vars, sizeof_off_t); + + return xlen; +} + + +int +ncx_put_NC(const NC *ncp, void **xpp, off_t offset, size_t extent) +{ + int status = ENOERR; + v1hs ps; /* the get stream */ + + assert(ncp != NULL); + + /* Initialize stream ps */ + + ps.nciop = ncp->nciop; + ps.flags = RGN_WRITE; + + if (ncp->flags & NC_64BIT_OFFSET) + ps.version = 2; + else + ps.version = 1; + + if(xpp == NULL) + { + /* + * Come up with a reasonable stream read size. + */ + extent = ncp->xsz; + if(extent <= MIN_NC_XSZ) + { + /* first time read */ + extent = ncp->chunk; + /* Protection for when ncp->chunk is huge; + * no need to read hugely. */ + if(extent > 4096) + extent = 4096; + } + else if(extent > ncp->chunk) + { + extent = ncp->chunk; + } + + ps.offset = 0; + ps.extent = extent; + ps.base = NULL; + ps.pos = ps.base; + + status = fault_v1hs(&ps, extent); + if(status) + return status; + } + else + { + ps.offset = offset; + ps.extent = extent; + ps.base = *xpp; + ps.pos = ps.base; + ps.end = (char *)ps.base + ps.extent; + } + + if (ps.version == 2) + status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic), ncmagic); + else + status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic1), ncmagic1); + + if(status != ENOERR) + goto release; + + status = ncx_put_size_t(&ps.pos, &ncp->numrecs); + if(status != ENOERR) + goto release; + + assert((char *)ps.pos < (char *)ps.end); + + status = v1h_put_NC_dimarray(&ps, &ncp->dims); + if(status != ENOERR) + goto release; + + status = v1h_put_NC_attrarray(&ps, &ncp->attrs); + if(status != ENOERR) + goto release; + + status = v1h_put_NC_vararray(&ps, &ncp->vars); + if(status != ENOERR) + goto release; + +release: + (void) rel_v1hs(&ps); + + return status; +} + + +int +nc_get_NC(NC *ncp) +{ + int status; + v1hs gs; /* the get stream */ + + assert(ncp != NULL); + + /* Initialize stream gs */ + + gs.nciop = ncp->nciop; + gs.offset = 0; /* beginning of file */ + gs.extent = 0; + gs.flags = 0; + gs.version = 0; + gs.base = NULL; + gs.pos = gs.base; + + { + /* + * Come up with a reasonable stream read size. + */ + size_t extent = ncp->xsz; + if(extent <= MIN_NC_XSZ) + { + /* first time read */ + extent = ncp->chunk; + /* Protection for when ncp->chunk is huge; + * no need to read hugely. */ + if(extent > 4096) + extent = 4096; + } + else if(extent > ncp->chunk) + { + extent = ncp->chunk; + } + + status = fault_v1hs(&gs, extent); + if(status) + return status; + } + + /* get the header from the stream gs */ + + { + /* Get & check magic number */ + schar magic[sizeof(ncmagic)]; + (void) memset(magic, 0, sizeof(magic)); + + status = ncx_getn_schar_schar( + (const void **)(&gs.pos), sizeof(magic), magic); + if(status != ENOERR) + goto unwind_get; + + if(memcmp(magic, ncmagic, sizeof(ncmagic)-1) != 0) + { + status = NC_ENOTNC; + goto unwind_get; + } + /* Check version number in last byte of magic */ + if (magic[sizeof(ncmagic)-1] == 0x1) { + gs.version = 1; + } else if (magic[sizeof(ncmagic)-1] == 0x2) { + gs.version = 2; + if (sizeof(off_t) != 8) { + fprintf(stderr, "NETCDF WARNING: Version 2 database on 32-bit system.\n"); + } + } else { + status = NC_ENOTNC; + goto unwind_get; + } + } + + status = ncx_get_size_t((const void **)(&gs.pos), &ncp->numrecs); + if(status != ENOERR) + goto unwind_get; + + assert((char *)gs.pos < (char *)gs.end); + + status = v1h_get_NC_dimarray(&gs, &ncp->dims); + if(status != ENOERR) + goto unwind_get; + + status = v1h_get_NC_attrarray(&gs, &ncp->attrs); + if(status != ENOERR) + goto unwind_get; + + status = v1h_get_NC_vararray(&gs, &ncp->vars); + if(status != ENOERR) + goto unwind_get; + + ncp->xsz = ncx_len_NC(ncp, (gs.version == 1) ? 4 : 8); + + status = NC_computeshapes(ncp); + +unwind_get: + (void) rel_v1hs(&gs); + return status; +} diff --git a/Utilities/vtknetcdf/v2i.c b/Utilities/vtknetcdf/v2i.c new file mode 100644 index 0000000..468043b --- /dev/null +++ b/Utilities/vtknetcdf/v2i.c @@ -0,0 +1,943 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: v2i.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#include "nc.h" + +#if SIZEOF_LONG == SIZEOF_SIZE_T +/* + * We don't have to copy the arguments to switch from 'long' + * to 'size_t' or 'ptrdiff_t'. Use dummy macros. + */ + +# define NDIMS_DECL +# define A_DECL(name, type, ndims, rhs) \ + const type *const name = ((const type *)(rhs)) + +# define A_FREE(name) + +# define A_INIT(lhs, type, ndims, rhs) + +#else +/* + * We do have to copy the arguments to switch from 'long' + * to 'size_t' or 'ptrdiff_t'. In my tests on an SGI, + * any additional cost was lost in measurement variation. + */ + +# include "onstack.h" + +static size_t +nvdims(int ncid, int varid) +{ + NC *ncp; + if(NC_check_id(ncid, &ncp) != NC_NOERR) + return 0; + { + const NC_var *const varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + return 0; + return varp->ndims; + } +} + +#define NDIMS_DECL const size_t ndims = nvdims(ncid, varid); + +# define A_DECL(name, type, ndims, rhs) \ + ALLOC_ONSTACK(name, type, ndims) + +# define A_FREE(name) \ + FREE_ONSTACK(name) + +# define A_INIT(lhs, type, ndims, rhs) \ + { \ + const long *lp = rhs; \ + type *tp = lhs; \ + type *const end = lhs + ndims; \ + while(tp < end) \ + { \ + *tp++ = (type) *lp++; \ + } \ + } + + +#endif + + +/* Begin globals */ + +/* + * Error code + */ +int ncerr = NC_NOERR ; + + +/* + * The subroutines in error.c emit no messages unless NC_VERBOSE bit is on. + * They call exit() when NC_FATAL bit is on. + */ +int ncopts = (NC_FATAL | NC_VERBOSE) ; + + +/* + * Backward compatibility for the version 2 fortran jackets + */ +const char *cdf_routine_name; + + +/* End globals */ + +/* Begin error handling */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + + +/* + */ +void +nc_advise(const char *routine_name, int err, const char *fmt,...) +{ + va_list args; + + if(NC_ISSYSERR(err)) + ncerr = NC_SYSERR; + else + ncerr = err; + + if( ncopts & NC_VERBOSE ) + { + (void) fprintf(stderr,"%s: ", routine_name); + va_start(args ,fmt); + (void) vfprintf(stderr,fmt,args); + va_end(args); + if(err != NC_NOERR) + { + (void) fprintf(stderr,": %s", + nc_strerror(err)); + } + (void) fputc('\n',stderr); + (void) fflush(stderr); /* to ensure log files are current */ + } + + if( (ncopts & NC_FATAL) && err != NC_NOERR ) + { + exit(ncopts); + } +} + + +/* + * Backward compatibility for the version 2 fortran jackets + */ +void +NCadvise(int err, char *fmt,...) +{ + va_list args; + + va_start(args ,fmt); + nc_advise(cdf_routine_name, err, fmt, args); + va_end(args); +} + +/* End error handling */ + + +int +nccreate(const char* path, int cmode) +{ + int ncid; + const int status = nc_create(path, cmode, &ncid); + if(status != NC_NOERR) + { + nc_advise("nccreate", status, "filename \"%s\"", path); + return -1; + } + return ncid; +} + + +int +ncopen(const char *path, int mode) +{ + int ncid; + const int status = nc_open(path, mode, &ncid); + if(status != NC_NOERR) + { + nc_advise("ncopen", status, "filename \"%s\"", path); + return -1; + } + return ncid; +} + + +int +ncredef(int ncid) +{ + const int status = nc_redef(ncid); + if(status != NC_NOERR) + { + nc_advise("ncredef", status, "ncid %d", ncid); + return -1; + } + return 0; +} + + +int +ncendef(int ncid) +{ + const int status = nc_enddef(ncid); + if(status != NC_NOERR) + { + nc_advise("ncendef", status, "ncid %d", ncid); + return -1; + } + return 0; +} + + +int +ncclose(int ncid) +{ + const int status = nc_close(ncid); + if(status != NC_NOERR) + { + nc_advise("ncclose", status, "ncid %d", ncid); + return -1; + + } + return 0; +} + + +int +ncinquire( + int ncid, + int* ndims, + int* nvars, + int* natts, + int* recdim +) +{ + int nd, nv, na; + const int status = nc_inq(ncid, &nd, &nv, &na, recdim); + + if(status != NC_NOERR) + { + nc_advise("ncinquire", status, "ncid %d", ncid); + return -1; + } + /* else */ + + if(ndims != NULL) + *ndims = (int) nd; + + if(nvars != NULL) + *nvars = (int) nv; + + if(natts != NULL) + *natts = (int) na; + + return ncid; +} + + +int +ncsync(int ncid) +{ + const int status = nc_sync(ncid); + if(status != NC_NOERR) + { + nc_advise("ncsync", status, "ncid %d", ncid); + return -1; + + } + return 0; +} + + +int +ncabort(int ncid) +{ + const int status = nc_abort(ncid); + if(status != NC_NOERR) + { + nc_advise("ncabort", status, "ncid %d", ncid); + return -1; + } + return 0; +} + + +int +ncdimdef( + int ncid, + const char* name, + long length +) +{ + int dimid; + const int status = nc_def_dim(ncid, name, (size_t)length, &dimid); + if(status != NC_NOERR) + { + nc_advise("ncdimdef", status, "ncid %d", ncid); + return -1; + } + return dimid; +} + + +int +ncdimid(int ncid, const char* name) +{ + int dimid; + const int status = nc_inq_dimid(ncid, name, &dimid); + if(status != NC_NOERR) + { + nc_advise("ncdimid", status, "ncid %d", ncid); + return -1; + } + return dimid; +} + + +int +ncdiminq( + int ncid, + int dimid, + char* name, + long* length +) +{ + size_t ll; + const int status = nc_inq_dim(ncid, dimid, name, &ll); + + if(status != NC_NOERR) + { + nc_advise("ncdiminq", status, "ncid %d", ncid); + return -1; + } + /* else */ + + if(length != NULL) + *length = (int) ll; + + return dimid; +} + + +int +ncdimrename( + int ncid, + int dimid, + const char* name +) +{ + const int status = nc_rename_dim(ncid, dimid, name); + if(status != NC_NOERR) + { + nc_advise("ncdimrename", status, "ncid %d", ncid); + return -1; + } + return dimid; +} + + +int +ncvardef( + int ncid, + const char* name, + nc_type datatype, + int ndims, + const int* dim +) +{ + int varid = -1; + const int status = nc_def_var(ncid, name, datatype, ndims, dim, &varid); + if(status != NC_NOERR) + { + nc_advise("ncvardef", status, "ncid %d", ncid); + return -1; + } + return varid; +} + + +int +ncvarid( + int ncid, + const char* name +) +{ + int varid = -1; + const int status = nc_inq_varid(ncid, name, &varid); + if(status != NC_NOERR) + { + nc_advise("ncvarid", status, "ncid %d", ncid); + return -1; + } + return varid; +} + + +int +ncvarinq( + int ncid, + int varid, + char* name, + nc_type* datatype, + int* ndims, + int* dim, + int* natts +) +{ + int nd, na; + const int status = nc_inq_var(ncid, varid, name, datatype, + &nd, dim, &na); + + if(status != NC_NOERR) + { + nc_advise("ncvarinq", status, "ncid %d", ncid); + return -1; + } + /* else */ + + if(ndims != NULL) + *ndims = (int) nd; + + if(natts != NULL) + *natts = (int) na; + + return varid; +} + + +EXTERNL int +ncvarput1( + int ncid, + int varid, + const long* index, + const void* value +) +{ + NDIMS_DECL + A_DECL(coordp, size_t, ndims, index); + A_INIT(coordp, size_t, ndims, index); + { + const int status = nc_put_var1(ncid, varid, coordp, value); + A_FREE(coordp); + if(status != NC_NOERR) + { + nc_advise("ncvarput1", status, "ncid %d", ncid); + return -1; + } + } + return 0; +} + + +int +ncvarget1( + int ncid, + int varid, + const long* index, + void* value +) +{ + NDIMS_DECL + A_DECL(coordp, size_t, ndims, index); + A_INIT(coordp, size_t, ndims, index); + { + const int status = nc_get_var1(ncid, varid, coordp, value); + A_FREE(coordp); + if(status != NC_NOERR) + { + nc_advise("ncdimid", status, "ncid %d", ncid); + return -1; + } + } + return 0; +} + + +int +ncvarput( + int ncid, + int varid, + const long* start, + const long* count, + const void* value +) +{ + NDIMS_DECL + A_DECL(stp, size_t, ndims, start); + A_DECL(cntp, size_t, ndims, count); + A_INIT(stp, size_t, ndims, start); + A_INIT(cntp, size_t, ndims, count); + { + const int status = nc_put_vara(ncid, varid, stp, cntp, value); + A_FREE(cntp); + A_FREE(stp); + if(status != NC_NOERR) + { + nc_advise("ncvarput", status, "ncid %d", ncid); + return -1; + } + } + return 0; +} + + +int +ncvarget( + int ncid, + int varid, + const long* start, + const long* count, + void* value +) +{ + NDIMS_DECL + A_DECL(stp, size_t, ndims, start); + A_DECL(cntp, size_t, ndims, count); + A_INIT(stp, size_t, ndims, start); + A_INIT(cntp, size_t, ndims, count); + { + const int status = nc_get_vara(ncid, varid, stp, cntp, value); + A_FREE(cntp); + A_FREE(stp); + if(status != NC_NOERR) + { + nc_advise("ncvarget", status, "ncid %d", ncid); + return -1; + } + } + return 0; +} + + +int +ncvarputs( + int ncid, + int varid, + const long* start, + const long* count, + const long* stride, + const void* value +) +{ + if(stride == NULL) + return ncvarput(ncid, varid, start, count, value); + /* else */ + { + NDIMS_DECL + A_DECL(stp, size_t, ndims, start); + A_DECL(cntp, size_t, ndims, count); + A_DECL(strdp, ptrdiff_t, ndims, stride); + A_INIT(stp, size_t, ndims, start); + A_INIT(cntp, size_t, ndims, count); + A_INIT(strdp, ptrdiff_t, ndims, stride); + { + const int status = nc_put_vars(ncid, varid, stp, cntp, strdp, value); + A_FREE(strdp); + A_FREE(cntp); + A_FREE(stp); + if(status != NC_NOERR) + { + nc_advise("ncvarputs", status, "ncid %d", ncid); + return -1; + } + } + return 0; + } +} + + +int +ncvargets( + int ncid, + int varid, + const long* start, + const long* count, + const long* stride, + void* value +) +{ + if(stride == NULL) + return ncvarget(ncid, varid, start, count, value); + /* else */ + { + NDIMS_DECL + A_DECL(stp, size_t, ndims, start); + A_DECL(cntp, size_t, ndims, count); + A_DECL(strdp, ptrdiff_t, ndims, stride); + A_INIT(stp, size_t, ndims, start); + A_INIT(cntp, size_t, ndims, count); + A_INIT(strdp, ptrdiff_t, ndims, stride); + { + const int status = nc_get_vars(ncid, varid, stp, cntp, strdp, value); + A_FREE(strdp); + A_FREE(cntp); + A_FREE(stp); + if(status != NC_NOERR) + { + nc_advise("ncvargets", status, "ncid %d", ncid); + return -1; + } + } + return 0; + } +} + + +int +ncvarputg( + int ncid, + int varid, + const long* start, + const long* count, + const long* stride, + const long* map, + const void* value +) +{ + if(map == NULL) + return ncvarputs(ncid, varid, start, count, stride, value); + /* else */ + { + NDIMS_DECL + A_DECL(stp, size_t, ndims, start); + A_DECL(cntp, size_t, ndims, count); + A_DECL(strdp, ptrdiff_t, ndims, stride); + A_DECL(imp, ptrdiff_t, ndims, map); + A_INIT(stp, size_t, ndims, start); + A_INIT(cntp, size_t, ndims, count); + A_INIT(strdp, ptrdiff_t, ndims, stride); + A_INIT(imp, ptrdiff_t, ndims, map); + { + const int status = nc_put_varm(ncid, varid, + stp, cntp, strdp, imp, value); + A_FREE(imp); + A_FREE(strdp); + A_FREE(cntp); + A_FREE(stp); + if(status != NC_NOERR) + { + nc_advise("ncvarputg", status, "ncid %d", ncid); + return -1; + } + } + return 0; + } +} + + +int +ncvargetg( + int ncid, + int varid, + const long* start, + const long* count, + const long* stride, + const long* map, + void* value +) +{ + if(map == NULL) + return ncvargets(ncid, varid, start, count, stride, value); + /* else */ + { + NDIMS_DECL + A_DECL(stp, size_t, ndims, start); + A_DECL(cntp, size_t, ndims, count); + A_DECL(strdp, ptrdiff_t, ndims, stride); + A_DECL(imp, ptrdiff_t, ndims, map); + A_INIT(stp, size_t, ndims, start); + A_INIT(cntp, size_t, ndims, count); + A_INIT(strdp, ptrdiff_t, ndims, stride); + A_INIT(imp, ptrdiff_t, ndims, map); + { + const int status = nc_get_varm(ncid, varid, + stp, cntp, strdp, imp, value); + A_FREE(imp); + A_FREE(strdp); + A_FREE(cntp); + A_FREE(stp); + if(status != NC_NOERR) + { + nc_advise("ncvargetg", status, "ncid %d", ncid); + return -1; + } + } + return 0; + } +} + + +int +ncvarrename( + int ncid, + int varid, + const char* name +) +{ + const int status = nc_rename_var(ncid, varid, name); + if(status != NC_NOERR) + { + nc_advise("ncvarrename", status, "ncid %d", ncid); + return -1; + } + return varid; +} + + +int +ncattput( + int ncid, + int varid, + const char* name, + nc_type datatype, + int len, + const void* value +) +{ + const int status = nc_put_att(ncid, varid, name, datatype, len, value); + if(status != NC_NOERR) + { + nc_advise("ncattput", status, "ncid %d", ncid); + return -1; + } + return 0; +} + + +int +ncattinq( + int ncid, + int varid, + const char* name, + nc_type* datatype, + int* len +) +{ + size_t ll; + const int status = nc_inq_att(ncid, varid, name, datatype, &ll); + if(status != NC_NOERR) + { + nc_advise("ncattinq", status, "ncid %d", ncid); + return -1; + } + + if(len != NULL) + *len = (int) ll; + + return 1; + +} + + +int +ncattget( + int ncid, + int varid, + const char* name, + void* value +) +{ + const int status = nc_get_att(ncid, varid, name, value); + if(status != NC_NOERR) + { + nc_advise("ncattget", status, "ncid %d", ncid); + return -1; + } + return 1; +} + + +int +ncattcopy( + int ncid_in, + int varid_in, + const char* name, + int ncid_out, + int varid_out +) +{ + const int status = nc_copy_att(ncid_in, varid_in, name, ncid_out, varid_out); + if(status != NC_NOERR) + { + nc_advise("ncattcopy", status, "%s", name); + return -1; + } + return 0; +} + + +int +ncattname( + int ncid, + int varid, + int attnum, + char* name +) +{ + const int status = nc_inq_attname(ncid, varid, attnum, name); + if(status != NC_NOERR) + { + nc_advise("ncattname", status, "ncid %d", ncid); + return -1; + } + return attnum; +} + + +int +ncattrename( + int ncid, + int varid, + const char* name, + const char* newname +) +{ + const int status = nc_rename_att(ncid, varid, name, newname); + if(status != NC_NOERR) + { + nc_advise("ncattrename", status, "ncid %d", ncid); + return -1; + } + return 1; +} + + +int +ncattdel( + int ncid, + int varid, + const char* name +) +{ + const int status = nc_del_att(ncid, varid, name); + if(status != NC_NOERR) + { + nc_advise("ncattdel", status, "ncid %d", ncid); + return -1; + } + return 1; +} + + +/* + * This is how much space is required by the user, as in + * + * vals = malloc(nel * nctypelen(var.type)); + * ncvarget(cdfid, varid, cor, edg, vals); + */ +int +nctypelen(nc_type type) +{ + switch(type){ + case NC_BYTE : + case NC_CHAR : + return((int)sizeof(char)); + case NC_SHORT : + return(int)(sizeof(short)); + case NC_INT : + return((int)sizeof(nclong)); + case NC_FLOAT : + return((int)sizeof(float)); + case NC_DOUBLE : + return((int)sizeof(double)); + } + /* else */ + nc_advise("nctypelen", NC_EBADTYPE, "Unknown type %d", + (int)type); + return -1; +} + + +int +ncsetfill( + int ncid, + int fillmode +) +{ + int oldmode = -1; + const int status = nc_set_fill(ncid, fillmode, &oldmode); + if(status != NC_NOERR) + { + nc_advise("ncsetfill", status, "ncid %d", ncid); + return -1; + } + return oldmode; +} + + +int +ncrecinq( + int ncid, + int* nrecvars, + int* recvarids, + long* recsizes +) +{ + size_t nrv = 0; + size_t rs[NC_MAX_VARS]; /* TODO */ + const int status = nc_inq_rec(ncid, &nrv, recvarids, rs); + if(status != NC_NOERR) + { + nc_advise("ncrecinq", status, "ncid %d", ncid); + return -1; + } + + if(nrecvars != NULL) + *nrecvars = (int) nrv; + + if(recsizes != NULL) + { + size_t ii; + for(ii = 0; ii < nrv; ii++) + { + recsizes[ii] = (long) rs[ii]; + } + } + + return (int) nrv; +} + + +int +ncrecget( + int ncid, + long recnum, + void** datap +) +{ + const int status = nc_get_rec(ncid, (size_t)recnum, datap); + if(status != NC_NOERR) + { + nc_advise("ncrecget", status, "ncid %d", ncid); + return -1; + } + return 0; +} + + +int +ncrecput( + int ncid, + long recnum, + void* const* datap +) +{ + const int status = nc_put_rec(ncid, (size_t)recnum, datap); + if(status != NC_NOERR) + { + nc_advise("ncrecput", status, "ncid %d", ncid); + return -1; + } + return 0; +} diff --git a/Utilities/vtknetcdf/var.c b/Utilities/vtknetcdf/var.c new file mode 100644 index 0000000..213392f --- /dev/null +++ b/Utilities/vtknetcdf/var.c @@ -0,0 +1,785 @@ +/* + * Copyright 1996, University Corporation for Atmospheric Research + * See netcdf/COPYRIGHT file for copying and redistribution conditions. + */ +/* $Id: var.c,v 1.1 2005/07/15 21:56:39 andy Exp $ */ + +#include "nc.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "ncx.h" +#include "rnd.h" + + +/* + * Free var + * Formerly +NC_free_var(var) + */ +void +free_NC_var(NC_var *varp) +{ + if(varp == NULL) + return; + free_NC_attrarrayV(&varp->attrs); + free_NC_string(varp->name); + free(varp); +} + + +/* + * Common code for new_NC_var() + * and ncx_get_NC_var() + */ +NC_var * +new_x_NC_var( + NC_string *strp, + size_t ndims) +{ + NC_var *varp; + const size_t o1 = M_RNDUP(ndims * sizeof(int)); + const size_t o2 = M_RNDUP(ndims * sizeof(size_t)); + const size_t sz = M_RNDUP(sizeof(NC_var)) + + o1 + o2 + ndims * sizeof(size_t); + + varp = (NC_var *) malloc(sz); + if(varp == NULL ) + return NULL; + (void) memset(varp, 0, sz); + + varp->name = strp; + varp->ndims = ndims; + + if(ndims != 0) + { + /* + * NOTE: lint may complain about the next 3 lines: + * "pointer cast may result in improper alignment". + * We use the M_RNDUP() macro to get the proper alignment. + */ + varp->dimids = (int *)((char *)varp + M_RNDUP(sizeof(NC_var))); + varp->shape = (size_t *)((char *)varp->dimids + o1); + varp->dsizes = (size_t *)((char *)varp->shape + o2); + } + + varp->xsz = 0; + varp->len = 0; + varp->begin = 0; + + return varp; +} + + +/* + * Formerly +NC_new_var() + */ +static NC_var * +new_NC_var(const char *name, nc_type type, + size_t ndims, const int *dimids) +{ + NC_string *strp; + NC_var *varp; + + strp = new_NC_string(strlen(name), name); + if(strp == NULL) + return NULL; + + varp = new_x_NC_var(strp, ndims); + if(varp == NULL ) + { + free_NC_string(strp); + return NULL; + } + + varp->type = type; + + if( ndims != 0 && dimids != NULL) + (void) memcpy(varp->dimids, dimids, ndims * sizeof(int)); + + return(varp); +} + + +static NC_var * +dup_NC_var(const NC_var *rvarp) +{ + NC_var *varp = new_NC_var(rvarp->name->cp, rvarp->type, + rvarp->ndims, rvarp->dimids); + if(varp == NULL) + return NULL; + + + if(dup_NC_attrarrayV(&varp->attrs, &rvarp->attrs) != NC_NOERR) + { + free_NC_var(varp); + return NULL; + } + + (void) memcpy(varp->shape, rvarp->shape, + rvarp->ndims * sizeof(size_t)); + (void) memcpy(varp->dsizes, rvarp->dsizes, + rvarp->ndims * sizeof(size_t)); + varp->xsz = rvarp->xsz; + varp->len = rvarp->len; + varp->begin = rvarp->begin; + + return varp; +} + + +/* vararray */ + + +/* + * Free the stuff "in" (referred to by) an NC_vararray. + * Leaves the array itself allocated. + */ +void +free_NC_vararrayV0(NC_vararray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nelems == 0) + return; + + assert(ncap->value != NULL); + + { + NC_var **vpp = ncap->value; + NC_var *const *const end = &vpp[ncap->nelems]; + for( /*NADA*/; vpp < end; vpp++) + { + free_NC_var(*vpp); + *vpp = NULL; + } + } + ncap->nelems = 0; +} + + +/* + * Free NC_vararray values. + * formerly +NC_free_array() + */ +void +free_NC_vararrayV(NC_vararray *ncap) +{ + assert(ncap != NULL); + + if(ncap->nalloc == 0) + return; + + assert(ncap->value != NULL); + + free_NC_vararrayV0(ncap); + + free(ncap->value); + ncap->value = NULL; + ncap->nalloc = 0; +} + + +int +dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref) +{ + int status = NC_NOERR; + + assert(ref != NULL); + assert(ncap != NULL); + + if(ref->nelems != 0) + { + const size_t sz = ref->nelems * sizeof(NC_var *); + ncap->value = (NC_var **) malloc(sz); + if(ncap->value == NULL) + return NC_ENOMEM; + (void) memset(ncap->value, 0, sz); + ncap->nalloc = ref->nelems; + } + + ncap->nelems = 0; + { + NC_var **vpp = ncap->value; + const NC_var **drpp = (const NC_var **)ref->value; + NC_var *const *const end = &vpp[ref->nelems]; + for( /*NADA*/; vpp < end; drpp++, vpp++, ncap->nelems++) + { + *vpp = dup_NC_var(*drpp); + if(*vpp == NULL) + { + status = NC_ENOMEM; + break; + } + } + } + + if(status != NC_NOERR) + { + free_NC_vararrayV(ncap); + return status; + } + + assert(ncap->nelems == ref->nelems); + + return NC_NOERR; +} + + +/* + * Add a new handle on the end of an array of handles + * Formerly +NC_incr_array(array, tail) + */ +static int +incr_NC_vararray(NC_vararray *ncap, NC_var *newelemp) +{ + NC_var **vp; + + assert(ncap != NULL); + + if(ncap->nalloc == 0) + { + assert(ncap->nelems == 0); + vp = (NC_var **) malloc(NC_ARRAY_GROWBY * sizeof(NC_var *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc = NC_ARRAY_GROWBY; + } + else if(ncap->nelems +1 > ncap->nalloc) + { + vp = (NC_var **) realloc(ncap->value, + (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_var *)); + if(vp == NULL) + return NC_ENOMEM; + ncap->value = vp; + ncap->nalloc += NC_ARRAY_GROWBY; + } + + if(newelemp != NULL) + { + ncap->value[ncap->nelems] = newelemp; + ncap->nelems++; + } + return NC_NOERR; +} + + +static NC_var * +elem_NC_vararray(const NC_vararray *ncap, size_t elem) +{ + assert(ncap != NULL); + /* cast needed for braindead systems with signed size_t */ + if(ncap->nelems == 0 || (unsigned long)elem >= ncap->nelems) + return NULL; + + assert(ncap->value != NULL); + + return ncap->value[elem]; +} + + +/* End vararray per se */ + + +/* + * Step thru NC_VARIABLE array, seeking match on name. + * Return varid or -1 on not found. + * *varpp is set to the appropriate NC_var. + * Formerly (sort of) +NC_hvarid + */ +int +NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp) +{ + NC_var **loc; + size_t slen; + int varid; + + assert(ncap != NULL); + + if(ncap->nelems == 0) + return -1; + + loc = (NC_var **) ncap->value; + + slen = strlen(name); + + for(varid = 0; (size_t) varid < ncap->nelems; varid++, loc++) + { + if(strlen((*loc)->name->cp) == slen && + strncmp((*loc)->name->cp, name, slen) == 0) + { + if(varpp != NULL) + *varpp = *loc; + return(varid); /* Normal return */ + } + } + return(-1); /* not found */ +} + +/* + * For a netcdf type + * return the size of one element in the external representation. + * Note that arrays get rounded up to X_ALIGN boundaries. + * Formerly +NC_xtypelen + * See also ncx_len() + */ +size_t +ncx_szof(nc_type type) +{ + switch(type){ + case NC_BYTE: + case NC_CHAR: + return(1); + case NC_SHORT : + return(2); + case NC_INT: + return X_SIZEOF_INT; + case NC_FLOAT: + return X_SIZEOF_FLOAT; + case NC_DOUBLE : + return X_SIZEOF_DOUBLE; + } + /* default */ + assert("ncx_szof invalid type" == 0); + return 0; +} + + +/* + * 'compile' the shape and len of a variable + * Formerly +NC_var_shape(var, dims) + */ +int +NC_var_shape(NC_var *varp, const NC_dimarray *dims) +{ + size_t *shp, *dsp, *op; + int *ip; + const NC_dim *dimp; + size_t product = 1; + + varp->xsz = ncx_szof(varp->type); + + if(varp->ndims == 0) + { + goto out; + } + + /* + * use the user supplied dimension indices + * to determine the shape + */ + for(ip = varp->dimids, op = varp->shape + ; ip < &varp->dimids[varp->ndims]; ip++, op++) + { + if(*ip < 0 || (size_t) (*ip) >= ((dims != NULL) ? dims->nelems : 1) ) + return NC_EBADDIM; + + dimp = elem_NC_dimarray(dims, (size_t)*ip); + *op = dimp->size; + if(*op == NC_UNLIMITED && ip != varp->dimids) + return NC_EUNLIMPOS; + } + + /* + * Compute the dsizes + */ + /* ndims is > 0 here */ + for(shp = varp->shape + varp->ndims -1, + dsp = varp->dsizes + varp->ndims -1; + shp >= varp->shape; + shp--, dsp--) + { + if(!(shp == varp->shape && IS_RECVAR(varp))) + product *= *shp; + *dsp = product; + } + + +out : + varp->len = product * varp->xsz; + switch(varp->type) { + case NC_BYTE : + case NC_CHAR : + case NC_SHORT : + if( varp->len%4 != 0 ) + { + varp->len += 4 - varp->len%4; /* round up */ + /* *dsp += 4 - *dsp%4; */ + } + break; + default: + /* already aligned */ + break; + } +#if 0 + arrayp("\tshape", varp->ndims, varp->shape); + arrayp("\tdsizes", varp->ndims, varp->dsizes); +#endif + return NC_NOERR; +} + + +/* + * Given valid ncp and varid, return var + * else NULL on error + * Formerly +NC_hlookupvar() + */ +NC_var * +NC_lookupvar(NC *ncp, int varid) +{ + NC_var *varp; + + if(varid == NC_GLOBAL) + { + /* Global is error in this context */ + return(NULL); + } + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + { + return NULL; + } + + assert(varp != NULL); + + return(varp); +} + + +/* Public */ + +int +nc_def_var( int ncid, const char *name, nc_type type, + int ndims, const int *dimids, int *varidp) +{ + int status; + NC *ncp; + int varid; + NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(!NC_indef(ncp)) + { + return NC_ENOTINDEFINE; + } + + status = NC_check_name(name); + if(status != NC_NOERR) + return status; + + status = nc_cktype(type); + if(status != NC_NOERR) + return status; + + /* cast needed for braindead systems with signed size_t */ + if((unsigned long) ndims > X_INT_MAX) /* Backward compat */ + { + return NC_EINVAL; + } + + if(ncp->vars.nelems >= NC_MAX_VARS) + { + return NC_EMAXVARS; + } + + varid = NC_findvar(&ncp->vars, name, &varp); + if(varid != -1) + { + return NC_ENAMEINUSE; + } + + varp = new_NC_var(name, type, ndims, dimids); + if(varp == NULL) + return NC_ENOMEM; + + status = NC_var_shape(varp, &ncp->dims); + if(status != NC_NOERR) + { + free_NC_var(varp); + return status; + } + + status = incr_NC_vararray(&ncp->vars, varp); + if(status != NC_NOERR) + { + free_NC_var(varp); + return status; + } + + if(varidp != NULL) + *varidp = (int)ncp->vars.nelems -1; /* varid */ + return NC_NOERR; +} + + +int +nc_inq_varid(int ncid, const char *name, int *varid_ptr) +{ + int status; + NC *ncp; + NC_var *varp; + int varid; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varid = NC_findvar(&ncp->vars, name, &varp); + if(varid == -1) + { + return NC_ENOTVAR; + } + + *varid_ptr = varid; + return NC_NOERR; +} + + +int +nc_inq_var(int ncid, + int varid, + char *name, + nc_type *typep, + int *ndimsp, + int *dimids, + int *nattsp) +{ + int status; + NC *ncp; + NC_var *varp; + size_t ii; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(name != NULL) + { + (void) strncpy(name, varp->name->cp, varp->name->nchars); + name[varp->name->nchars] = 0; + } + + if(typep != 0) + *typep = varp->type; + if(ndimsp != 0) + { + *ndimsp = (int) varp->ndims; + } + if(dimids != 0) + { + for(ii = 0; ii < varp->ndims; ii++) + { + dimids[ii] = varp->dimids[ii]; + } + } + if(nattsp != 0) + { + *nattsp = (int) varp->attrs.nelems; + } + + return NC_NOERR; +} + + +int +nc_inq_varname(int ncid, int varid, char *name) +{ + int status; + NC *ncp; + NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(name != NULL) + { + (void) strncpy(name, varp->name->cp, varp->name->nchars); + name[varp->name->nchars] = 0; + } + + return NC_NOERR; +} + +int +nc_inq_vartype(int ncid, int varid, nc_type *typep) +{ + int status; + NC *ncp; + NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; + + if(typep != 0) + *typep = varp->type; + + return NC_NOERR; +} + +int +nc_inq_varndims(int ncid, int varid, int *ndimsp) +{ + int status; + NC *ncp; + NC_var *varp; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: is this the right error code? */ + + if(ndimsp != 0) + { + *ndimsp = (int) varp->ndims; + } + + return NC_NOERR; +} + + +int +nc_inq_vardimid(int ncid, int varid, int *dimids) +{ + int status; + NC *ncp; + NC_var *varp; + size_t ii; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: is this the right error code? */ + + if(dimids != 0) + { + for(ii = 0; ii < varp->ndims; ii++) + { + dimids[ii] = varp->dimids[ii]; + } + } + + return NC_NOERR; +} + + +int +nc_inq_varnatts(int ncid, int varid, int *nattsp) +{ + int status; + NC *ncp; + NC_var *varp; + + if(varid == NC_GLOBAL) + return nc_inq_natts(ncid, nattsp); + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + varp = elem_NC_vararray(&ncp->vars, (size_t)varid); + if(varp == NULL) + return NC_ENOTVAR; /* TODO: is this the right error code? */ + + if(nattsp != 0) + { + *nattsp = (int) varp->attrs.nelems; + } + + return NC_NOERR; +} + +int +nc_rename_var(int ncid, int varid, const char *newname) +{ + int status; + NC *ncp; + NC_var *varp; + NC_string *old, *newStr; + int other; + + status = NC_check_id(ncid, &ncp); + if(status != NC_NOERR) + return status; + + if(NC_readonly(ncp)) + { + return NC_EPERM; + } + + status = NC_check_name(newname); + if(status != NC_NOERR) + return status; + + /* check for name in use */ + other = NC_findvar(&ncp->vars, newname, &varp); + if(other != -1) + { + return NC_ENAMEINUSE; + } + + varp = NC_lookupvar(ncp, varid); + if(varp == NULL) + { + /* invalid varid */ + return NC_ENOTVAR; /* TODO: is this the right error code? */ + } + + old = varp->name; + if(NC_indef(ncp)) + { + newStr = new_NC_string(strlen(newname),newname); + if(newStr == NULL) + return(-1); + varp->name = newStr; + free_NC_string(old); + return NC_NOERR; + } + + /* else, not in define mode */ + status = set_NC_string(varp->name, newname); + if(status != NC_NOERR) + return status; + + set_NC_hdirty(ncp); + + if(NC_doHsync(ncp)) + { + status = NC_sync(ncp); + if(status != NC_NOERR) + return status; + } + + return NC_NOERR; +} diff --git a/Utilities/vtknetcdf/vtk_netcdf_mangle.h b/Utilities/vtknetcdf/vtk_netcdf_mangle.h new file mode 100644 index 0000000..4724320 --- /dev/null +++ b/Utilities/vtknetcdf/vtk_netcdf_mangle.h @@ -0,0 +1,421 @@ +#ifndef vtk_expat_mangle_h +#define vtk_expat_mangle_h + +/* + +This header file mangles all symbols exported from the expat library. +It is included in all files while building the expat library. Due to +namespace pollution, no expat headers should be included in .h files in +VTK. + +The following command was used to obtain the symbol list: + +nm libvtkNetCDF.a |grep " [TR] " + +This is the way to recreate the whole list: + +nm bin/libvtkNetCDF.so |grep " [TR] " | awk '{ print "#define "$3" vtk_netcdf_"$3 }' + +*/ + +#define NC_check_id vtk_netcdf_NC_check_id +#define NC_check_name vtk_netcdf_NC_check_name +#define NC_findattr vtk_netcdf_NC_findattr +#define NC_findvar vtk_netcdf_NC_findvar +#define NC_lookupvar vtk_netcdf_NC_lookupvar +#define NC_sync vtk_netcdf_NC_sync +#define NC_var_shape vtk_netcdf_NC_var_shape +#define NCadvise vtk_netcdf_NCadvise +#define _fini vtk_netcdf__fini +#define _init vtk_netcdf__init +#define dup_NC_attrarrayV vtk_netcdf_dup_NC_attrarrayV +#define dup_NC_dimarrayV vtk_netcdf_dup_NC_dimarrayV +#define dup_NC_vararrayV vtk_netcdf_dup_NC_vararrayV +#define elem_NC_attrarray vtk_netcdf_elem_NC_attrarray +#define elem_NC_dimarray vtk_netcdf_elem_NC_dimarray +#define fill_NC_var vtk_netcdf_fill_NC_var +#define find_NC_Udim vtk_netcdf_find_NC_Udim +#define free_NC_attr vtk_netcdf_free_NC_attr +#define free_NC_attrarrayV vtk_netcdf_free_NC_attrarrayV +#define free_NC_attrarrayV0 vtk_netcdf_free_NC_attrarrayV0 +#define free_NC_dim vtk_netcdf_free_NC_dim +#define free_NC_dimarrayV vtk_netcdf_free_NC_dimarrayV +#define free_NC_dimarrayV0 vtk_netcdf_free_NC_dimarrayV0 +#define free_NC_string vtk_netcdf_free_NC_string +#define free_NC_var vtk_netcdf_free_NC_var +#define free_NC_vararrayV vtk_netcdf_free_NC_vararrayV +#define free_NC_vararrayV0 vtk_netcdf_free_NC_vararrayV0 +#define nc__create vtk_netcdf_nc__create +#define nc__enddef vtk_netcdf_nc__enddef +#define nc__open vtk_netcdf_nc__open +#define nc_abort vtk_netcdf_nc_abort +#define nc_advise vtk_netcdf_nc_advise +#define nc_cktype vtk_netcdf_nc_cktype +#define nc_close vtk_netcdf_nc_close +#define nc_copy_att vtk_netcdf_nc_copy_att +#define nc_copy_var vtk_netcdf_nc_copy_var +#define nc_create vtk_netcdf_nc_create +#define nc_def_dim vtk_netcdf_nc_def_dim +#define nc_def_var vtk_netcdf_nc_def_var +#define nc_del_att vtk_netcdf_nc_del_att +#define nc_delete vtk_netcdf_nc_delete +#define nc_enddef vtk_netcdf_nc_enddef +#define nc_get_NC vtk_netcdf_nc_get_NC +#define nc_get_att vtk_netcdf_nc_get_att +#define nc_get_att_double vtk_netcdf_nc_get_att_double +#define nc_get_att_float vtk_netcdf_nc_get_att_float +#define nc_get_att_int vtk_netcdf_nc_get_att_int +#define nc_get_att_long vtk_netcdf_nc_get_att_long +#define nc_get_att_schar vtk_netcdf_nc_get_att_schar +#define nc_get_att_short vtk_netcdf_nc_get_att_short +#define nc_get_att_text vtk_netcdf_nc_get_att_text +#define nc_get_att_uchar vtk_netcdf_nc_get_att_uchar +#define nc_get_rec vtk_netcdf_nc_get_rec +#define nc_get_var1 vtk_netcdf_nc_get_var1 +#define nc_get_var1_double vtk_netcdf_nc_get_var1_double +#define nc_get_var1_float vtk_netcdf_nc_get_var1_float +#define nc_get_var1_int vtk_netcdf_nc_get_var1_int +#define nc_get_var1_long vtk_netcdf_nc_get_var1_long +#define nc_get_var1_schar vtk_netcdf_nc_get_var1_schar +#define nc_get_var1_short vtk_netcdf_nc_get_var1_short +#define nc_get_var1_text vtk_netcdf_nc_get_var1_text +#define nc_get_var1_uchar vtk_netcdf_nc_get_var1_uchar +#define nc_get_var_double vtk_netcdf_nc_get_var_double +#define nc_get_var_float vtk_netcdf_nc_get_var_float +#define nc_get_var_int vtk_netcdf_nc_get_var_int +#define nc_get_var_long vtk_netcdf_nc_get_var_long +#define nc_get_var_schar vtk_netcdf_nc_get_var_schar +#define nc_get_var_short vtk_netcdf_nc_get_var_short +#define nc_get_var_text vtk_netcdf_nc_get_var_text +#define nc_get_var_uchar vtk_netcdf_nc_get_var_uchar +#define nc_get_vara vtk_netcdf_nc_get_vara +#define nc_get_vara_double vtk_netcdf_nc_get_vara_double +#define nc_get_vara_float vtk_netcdf_nc_get_vara_float +#define nc_get_vara_int vtk_netcdf_nc_get_vara_int +#define nc_get_vara_long vtk_netcdf_nc_get_vara_long +#define nc_get_vara_schar vtk_netcdf_nc_get_vara_schar +#define nc_get_vara_short vtk_netcdf_nc_get_vara_short +#define nc_get_vara_text vtk_netcdf_nc_get_vara_text +#define nc_get_vara_uchar vtk_netcdf_nc_get_vara_uchar +#define nc_get_varm vtk_netcdf_nc_get_varm +#define nc_get_varm_double vtk_netcdf_nc_get_varm_double +#define nc_get_varm_float vtk_netcdf_nc_get_varm_float +#define nc_get_varm_int vtk_netcdf_nc_get_varm_int +#define nc_get_varm_long vtk_netcdf_nc_get_varm_long +#define nc_get_varm_schar vtk_netcdf_nc_get_varm_schar +#define nc_get_varm_short vtk_netcdf_nc_get_varm_short +#define nc_get_varm_text vtk_netcdf_nc_get_varm_text +#define nc_get_varm_uchar vtk_netcdf_nc_get_varm_uchar +#define nc_get_vars vtk_netcdf_nc_get_vars +#define nc_get_vars_double vtk_netcdf_nc_get_vars_double +#define nc_get_vars_float vtk_netcdf_nc_get_vars_float +#define nc_get_vars_int vtk_netcdf_nc_get_vars_int +#define nc_get_vars_long vtk_netcdf_nc_get_vars_long +#define nc_get_vars_schar vtk_netcdf_nc_get_vars_schar +#define nc_get_vars_short vtk_netcdf_nc_get_vars_short +#define nc_get_vars_text vtk_netcdf_nc_get_vars_text +#define nc_get_vars_uchar vtk_netcdf_nc_get_vars_uchar +#define nc_inq vtk_netcdf_nc_inq +#define nc_inq_att vtk_netcdf_nc_inq_att +#define nc_inq_attid vtk_netcdf_nc_inq_attid +#define nc_inq_attlen vtk_netcdf_nc_inq_attlen +#define nc_inq_attname vtk_netcdf_nc_inq_attname +#define nc_inq_atttype vtk_netcdf_nc_inq_atttype +#define nc_inq_dim vtk_netcdf_nc_inq_dim +#define nc_inq_dimid vtk_netcdf_nc_inq_dimid +#define nc_inq_dimlen vtk_netcdf_nc_inq_dimlen +#define nc_inq_dimname vtk_netcdf_nc_inq_dimname +#define nc_inq_libvers vtk_netcdf_nc_inq_libvers +#define nc_inq_natts vtk_netcdf_nc_inq_natts +#define nc_inq_ndims vtk_netcdf_nc_inq_ndims +#define nc_inq_nvars vtk_netcdf_nc_inq_nvars +#define nc_inq_rec vtk_netcdf_nc_inq_rec +#define nc_inq_unlimdim vtk_netcdf_nc_inq_unlimdim +#define nc_inq_var vtk_netcdf_nc_inq_var +#define nc_inq_vardimid vtk_netcdf_nc_inq_vardimid +#define nc_inq_varid vtk_netcdf_nc_inq_varid +#define nc_inq_varname vtk_netcdf_nc_inq_varname +#define nc_inq_varnatts vtk_netcdf_nc_inq_varnatts +#define nc_inq_varndims vtk_netcdf_nc_inq_varndims +#define nc_inq_vartype vtk_netcdf_nc_inq_vartype +#define nc_open vtk_netcdf_nc_open +#define nc_put_att vtk_netcdf_nc_put_att +#define nc_put_att_double vtk_netcdf_nc_put_att_double +#define nc_put_att_float vtk_netcdf_nc_put_att_float +#define nc_put_att_int vtk_netcdf_nc_put_att_int +#define nc_put_att_long vtk_netcdf_nc_put_att_long +#define nc_put_att_schar vtk_netcdf_nc_put_att_schar +#define nc_put_att_short vtk_netcdf_nc_put_att_short +#define nc_put_att_text vtk_netcdf_nc_put_att_text +#define nc_put_att_uchar vtk_netcdf_nc_put_att_uchar +#define nc_put_rec vtk_netcdf_nc_put_rec +#define nc_put_var1 vtk_netcdf_nc_put_var1 +#define nc_put_var1_double vtk_netcdf_nc_put_var1_double +#define nc_put_var1_float vtk_netcdf_nc_put_var1_float +#define nc_put_var1_int vtk_netcdf_nc_put_var1_int +#define nc_put_var1_long vtk_netcdf_nc_put_var1_long +#define nc_put_var1_schar vtk_netcdf_nc_put_var1_schar +#define nc_put_var1_short vtk_netcdf_nc_put_var1_short +#define nc_put_var1_text vtk_netcdf_nc_put_var1_text +#define nc_put_var1_uchar vtk_netcdf_nc_put_var1_uchar +#define nc_put_var_double vtk_netcdf_nc_put_var_double +#define nc_put_var_float vtk_netcdf_nc_put_var_float +#define nc_put_var_int vtk_netcdf_nc_put_var_int +#define nc_put_var_long vtk_netcdf_nc_put_var_long +#define nc_put_var_schar vtk_netcdf_nc_put_var_schar +#define nc_put_var_short vtk_netcdf_nc_put_var_short +#define nc_put_var_text vtk_netcdf_nc_put_var_text +#define nc_put_var_uchar vtk_netcdf_nc_put_var_uchar +#define nc_put_vara vtk_netcdf_nc_put_vara +#define nc_put_vara_double vtk_netcdf_nc_put_vara_double +#define nc_put_vara_float vtk_netcdf_nc_put_vara_float +#define nc_put_vara_int vtk_netcdf_nc_put_vara_int +#define nc_put_vara_long vtk_netcdf_nc_put_vara_long +#define nc_put_vara_schar vtk_netcdf_nc_put_vara_schar +#define nc_put_vara_short vtk_netcdf_nc_put_vara_short +#define nc_put_vara_text vtk_netcdf_nc_put_vara_text +#define nc_put_vara_uchar vtk_netcdf_nc_put_vara_uchar +#define nc_put_varm vtk_netcdf_nc_put_varm +#define nc_put_varm_double vtk_netcdf_nc_put_varm_double +#define nc_put_varm_float vtk_netcdf_nc_put_varm_float +#define nc_put_varm_int vtk_netcdf_nc_put_varm_int +#define nc_put_varm_long vtk_netcdf_nc_put_varm_long +#define nc_put_varm_schar vtk_netcdf_nc_put_varm_schar +#define nc_put_varm_short vtk_netcdf_nc_put_varm_short +#define nc_put_varm_text vtk_netcdf_nc_put_varm_text +#define nc_put_varm_uchar vtk_netcdf_nc_put_varm_uchar +#define nc_put_vars vtk_netcdf_nc_put_vars +#define nc_put_vars_double vtk_netcdf_nc_put_vars_double +#define nc_put_vars_float vtk_netcdf_nc_put_vars_float +#define nc_put_vars_int vtk_netcdf_nc_put_vars_int +#define nc_put_vars_long vtk_netcdf_nc_put_vars_long +#define nc_put_vars_schar vtk_netcdf_nc_put_vars_schar +#define nc_put_vars_short vtk_netcdf_nc_put_vars_short +#define nc_put_vars_text vtk_netcdf_nc_put_vars_text +#define nc_put_vars_uchar vtk_netcdf_nc_put_vars_uchar +#define nc_redef vtk_netcdf_nc_redef +#define nc_rename_att vtk_netcdf_nc_rename_att +#define nc_rename_dim vtk_netcdf_nc_rename_dim +#define nc_rename_var vtk_netcdf_nc_rename_var +#define nc_set_fill vtk_netcdf_nc_set_fill +#define nc_strerror vtk_netcdf_nc_strerror +#define nc_sync vtk_netcdf_nc_sync +#define ncabort vtk_netcdf_ncabort +#define ncattcopy vtk_netcdf_ncattcopy +#define ncattdel vtk_netcdf_ncattdel +#define ncattget vtk_netcdf_ncattget +#define ncattinq vtk_netcdf_ncattinq +#define ncattname vtk_netcdf_ncattname +#define ncattput vtk_netcdf_ncattput +#define ncattrename vtk_netcdf_ncattrename +#define ncclose vtk_netcdf_ncclose +#define nccreate vtk_netcdf_nccreate +#define ncdimdef vtk_netcdf_ncdimdef +#define ncdimid vtk_netcdf_ncdimid +#define ncdiminq vtk_netcdf_ncdiminq +#define ncdimrename vtk_netcdf_ncdimrename +#define ncendef vtk_netcdf_ncendef +#define ncinquire vtk_netcdf_ncinquire +#define ncio_close vtk_netcdf_ncio_close +#define ncio_create vtk_netcdf_ncio_create +#define ncio_open vtk_netcdf_ncio_open +#define ncopen vtk_netcdf_ncopen +#define ncrecget vtk_netcdf_ncrecget +#define ncrecinq vtk_netcdf_ncrecinq +#define ncrecput vtk_netcdf_ncrecput +#define ncredef vtk_netcdf_ncredef +#define ncsetfill vtk_netcdf_ncsetfill +#define ncsync vtk_netcdf_ncsync +#define nctypelen vtk_netcdf_nctypelen +#define ncvardef vtk_netcdf_ncvardef +#define ncvarget vtk_netcdf_ncvarget +#define ncvarget1 vtk_netcdf_ncvarget1 +#define ncvargetg vtk_netcdf_ncvargetg +#define ncvargets vtk_netcdf_ncvargets +#define ncvarid vtk_netcdf_ncvarid +#define ncvarinq vtk_netcdf_ncvarinq +#define ncvarput vtk_netcdf_ncvarput +#define ncvarput1 vtk_netcdf_ncvarput1 +#define ncvarputg vtk_netcdf_ncvarputg +#define ncvarputs vtk_netcdf_ncvarputs +#define ncvarrename vtk_netcdf_ncvarrename +#define ncx_get_double_double vtk_netcdf_ncx_get_double_double +#define ncx_get_double_float vtk_netcdf_ncx_get_double_float +#define ncx_get_double_int vtk_netcdf_ncx_get_double_int +#define ncx_get_double_long vtk_netcdf_ncx_get_double_long +#define ncx_get_double_schar vtk_netcdf_ncx_get_double_schar +#define ncx_get_double_short vtk_netcdf_ncx_get_double_short +#define ncx_get_double_uchar vtk_netcdf_ncx_get_double_uchar +#define ncx_get_float_double vtk_netcdf_ncx_get_float_double +#define ncx_get_float_float vtk_netcdf_ncx_get_float_float +#define ncx_get_float_int vtk_netcdf_ncx_get_float_int +#define ncx_get_float_long vtk_netcdf_ncx_get_float_long +#define ncx_get_float_schar vtk_netcdf_ncx_get_float_schar +#define ncx_get_float_short vtk_netcdf_ncx_get_float_short +#define ncx_get_float_uchar vtk_netcdf_ncx_get_float_uchar +#define ncx_get_int_double vtk_netcdf_ncx_get_int_double +#define ncx_get_int_float vtk_netcdf_ncx_get_int_float +#define ncx_get_int_int vtk_netcdf_ncx_get_int_int +#define ncx_get_int_long vtk_netcdf_ncx_get_int_long +#define ncx_get_int_schar vtk_netcdf_ncx_get_int_schar +#define ncx_get_int_short vtk_netcdf_ncx_get_int_short +#define ncx_get_int_uchar vtk_netcdf_ncx_get_int_uchar +#define ncx_get_off_t vtk_netcdf_ncx_get_off_t +#define ncx_get_short_double vtk_netcdf_ncx_get_short_double +#define ncx_get_short_float vtk_netcdf_ncx_get_short_float +#define ncx_get_short_int vtk_netcdf_ncx_get_short_int +#define ncx_get_short_long vtk_netcdf_ncx_get_short_long +#define ncx_get_short_schar vtk_netcdf_ncx_get_short_schar +#define ncx_get_short_short vtk_netcdf_ncx_get_short_short +#define ncx_get_short_uchar vtk_netcdf_ncx_get_short_uchar +#define ncx_get_size_t vtk_netcdf_ncx_get_size_t +#define ncx_getn_double_double vtk_netcdf_ncx_getn_double_double +#define ncx_getn_double_float vtk_netcdf_ncx_getn_double_float +#define ncx_getn_double_int vtk_netcdf_ncx_getn_double_int +#define ncx_getn_double_long vtk_netcdf_ncx_getn_double_long +#define ncx_getn_double_schar vtk_netcdf_ncx_getn_double_schar +#define ncx_getn_double_short vtk_netcdf_ncx_getn_double_short +#define ncx_getn_double_uchar vtk_netcdf_ncx_getn_double_uchar +#define ncx_getn_float_double vtk_netcdf_ncx_getn_float_double +#define ncx_getn_float_float vtk_netcdf_ncx_getn_float_float +#define ncx_getn_float_int vtk_netcdf_ncx_getn_float_int +#define ncx_getn_float_long vtk_netcdf_ncx_getn_float_long +#define ncx_getn_float_schar vtk_netcdf_ncx_getn_float_schar +#define ncx_getn_float_short vtk_netcdf_ncx_getn_float_short +#define ncx_getn_float_uchar vtk_netcdf_ncx_getn_float_uchar +#define ncx_getn_int_double vtk_netcdf_ncx_getn_int_double +#define ncx_getn_int_float vtk_netcdf_ncx_getn_int_float +#define ncx_getn_int_int vtk_netcdf_ncx_getn_int_int +#define ncx_getn_int_long vtk_netcdf_ncx_getn_int_long +#define ncx_getn_int_schar vtk_netcdf_ncx_getn_int_schar +#define ncx_getn_int_short vtk_netcdf_ncx_getn_int_short +#define ncx_getn_int_uchar vtk_netcdf_ncx_getn_int_uchar +#define ncx_getn_schar_double vtk_netcdf_ncx_getn_schar_double +#define ncx_getn_schar_float vtk_netcdf_ncx_getn_schar_float +#define ncx_getn_schar_int vtk_netcdf_ncx_getn_schar_int +#define ncx_getn_schar_long vtk_netcdf_ncx_getn_schar_long +#define ncx_getn_schar_schar vtk_netcdf_ncx_getn_schar_schar +#define ncx_getn_schar_short vtk_netcdf_ncx_getn_schar_short +#define ncx_getn_schar_uchar vtk_netcdf_ncx_getn_schar_uchar +#define ncx_getn_short_double vtk_netcdf_ncx_getn_short_double +#define ncx_getn_short_float vtk_netcdf_ncx_getn_short_float +#define ncx_getn_short_int vtk_netcdf_ncx_getn_short_int +#define ncx_getn_short_long vtk_netcdf_ncx_getn_short_long +#define ncx_getn_short_schar vtk_netcdf_ncx_getn_short_schar +#define ncx_getn_short_short vtk_netcdf_ncx_getn_short_short +#define ncx_getn_short_uchar vtk_netcdf_ncx_getn_short_uchar +#define ncx_getn_text vtk_netcdf_ncx_getn_text +#define ncx_getn_void vtk_netcdf_ncx_getn_void +#define ncx_howmany vtk_netcdf_ncx_howmany +#define ncx_len_NC vtk_netcdf_ncx_len_NC +#define ncx_pad_getn_schar_double vtk_netcdf_ncx_pad_getn_schar_double +#define ncx_pad_getn_schar_float vtk_netcdf_ncx_pad_getn_schar_float +#define ncx_pad_getn_schar_int vtk_netcdf_ncx_pad_getn_schar_int +#define ncx_pad_getn_schar_long vtk_netcdf_ncx_pad_getn_schar_long +#define ncx_pad_getn_schar_schar vtk_netcdf_ncx_pad_getn_schar_schar +#define ncx_pad_getn_schar_short vtk_netcdf_ncx_pad_getn_schar_short +#define ncx_pad_getn_schar_uchar vtk_netcdf_ncx_pad_getn_schar_uchar +#define ncx_pad_getn_short_double vtk_netcdf_ncx_pad_getn_short_double +#define ncx_pad_getn_short_float vtk_netcdf_ncx_pad_getn_short_float +#define ncx_pad_getn_short_int vtk_netcdf_ncx_pad_getn_short_int +#define ncx_pad_getn_short_long vtk_netcdf_ncx_pad_getn_short_long +#define ncx_pad_getn_short_schar vtk_netcdf_ncx_pad_getn_short_schar +#define ncx_pad_getn_short_short vtk_netcdf_ncx_pad_getn_short_short +#define ncx_pad_getn_short_uchar vtk_netcdf_ncx_pad_getn_short_uchar +#define ncx_pad_getn_text vtk_netcdf_ncx_pad_getn_text +#define ncx_pad_getn_void vtk_netcdf_ncx_pad_getn_void +#define ncx_pad_putn_schar_double vtk_netcdf_ncx_pad_putn_schar_double +#define ncx_pad_putn_schar_float vtk_netcdf_ncx_pad_putn_schar_float +#define ncx_pad_putn_schar_int vtk_netcdf_ncx_pad_putn_schar_int +#define ncx_pad_putn_schar_long vtk_netcdf_ncx_pad_putn_schar_long +#define ncx_pad_putn_schar_schar vtk_netcdf_ncx_pad_putn_schar_schar +#define ncx_pad_putn_schar_short vtk_netcdf_ncx_pad_putn_schar_short +#define ncx_pad_putn_schar_uchar vtk_netcdf_ncx_pad_putn_schar_uchar +#define ncx_pad_putn_short_double vtk_netcdf_ncx_pad_putn_short_double +#define ncx_pad_putn_short_float vtk_netcdf_ncx_pad_putn_short_float +#define ncx_pad_putn_short_int vtk_netcdf_ncx_pad_putn_short_int +#define ncx_pad_putn_short_long vtk_netcdf_ncx_pad_putn_short_long +#define ncx_pad_putn_short_schar vtk_netcdf_ncx_pad_putn_short_schar +#define ncx_pad_putn_short_short vtk_netcdf_ncx_pad_putn_short_short +#define ncx_pad_putn_short_uchar vtk_netcdf_ncx_pad_putn_short_uchar +#define ncx_pad_putn_text vtk_netcdf_ncx_pad_putn_text +#define ncx_pad_putn_void vtk_netcdf_ncx_pad_putn_void +#define ncx_put_NC vtk_netcdf_ncx_put_NC +#define ncx_put_double_double vtk_netcdf_ncx_put_double_double +#define ncx_put_double_float vtk_netcdf_ncx_put_double_float +#define ncx_put_double_int vtk_netcdf_ncx_put_double_int +#define ncx_put_double_long vtk_netcdf_ncx_put_double_long +#define ncx_put_double_schar vtk_netcdf_ncx_put_double_schar +#define ncx_put_double_short vtk_netcdf_ncx_put_double_short +#define ncx_put_double_uchar vtk_netcdf_ncx_put_double_uchar +#define ncx_put_float_double vtk_netcdf_ncx_put_float_double +#define ncx_put_float_float vtk_netcdf_ncx_put_float_float +#define ncx_put_float_int vtk_netcdf_ncx_put_float_int +#define ncx_put_float_long vtk_netcdf_ncx_put_float_long +#define ncx_put_float_schar vtk_netcdf_ncx_put_float_schar +#define ncx_put_float_short vtk_netcdf_ncx_put_float_short +#define ncx_put_float_uchar vtk_netcdf_ncx_put_float_uchar +#define ncx_put_int_double vtk_netcdf_ncx_put_int_double +#define ncx_put_int_float vtk_netcdf_ncx_put_int_float +#define ncx_put_int_int vtk_netcdf_ncx_put_int_int +#define ncx_put_int_long vtk_netcdf_ncx_put_int_long +#define ncx_put_int_schar vtk_netcdf_ncx_put_int_schar +#define ncx_put_int_short vtk_netcdf_ncx_put_int_short +#define ncx_put_int_uchar vtk_netcdf_ncx_put_int_uchar +#define ncx_put_off_t vtk_netcdf_ncx_put_off_t +#define ncx_put_short_double vtk_netcdf_ncx_put_short_double +#define ncx_put_short_float vtk_netcdf_ncx_put_short_float +#define ncx_put_short_int vtk_netcdf_ncx_put_short_int +#define ncx_put_short_long vtk_netcdf_ncx_put_short_long +#define ncx_put_short_schar vtk_netcdf_ncx_put_short_schar +#define ncx_put_short_short vtk_netcdf_ncx_put_short_short +#define ncx_put_short_uchar vtk_netcdf_ncx_put_short_uchar +#define ncx_put_size_t vtk_netcdf_ncx_put_size_t +#define ncx_putn_double_double vtk_netcdf_ncx_putn_double_double +#define ncx_putn_double_float vtk_netcdf_ncx_putn_double_float +#define ncx_putn_double_int vtk_netcdf_ncx_putn_double_int +#define ncx_putn_double_long vtk_netcdf_ncx_putn_double_long +#define ncx_putn_double_schar vtk_netcdf_ncx_putn_double_schar +#define ncx_putn_double_short vtk_netcdf_ncx_putn_double_short +#define ncx_putn_double_uchar vtk_netcdf_ncx_putn_double_uchar +#define ncx_putn_float_double vtk_netcdf_ncx_putn_float_double +#define ncx_putn_float_float vtk_netcdf_ncx_putn_float_float +#define ncx_putn_float_int vtk_netcdf_ncx_putn_float_int +#define ncx_putn_float_long vtk_netcdf_ncx_putn_float_long +#define ncx_putn_float_schar vtk_netcdf_ncx_putn_float_schar +#define ncx_putn_float_short vtk_netcdf_ncx_putn_float_short +#define ncx_putn_float_uchar vtk_netcdf_ncx_putn_float_uchar +#define ncx_putn_int_double vtk_netcdf_ncx_putn_int_double +#define ncx_putn_int_float vtk_netcdf_ncx_putn_int_float +#define ncx_putn_int_int vtk_netcdf_ncx_putn_int_int +#define ncx_putn_int_long vtk_netcdf_ncx_putn_int_long +#define ncx_putn_int_schar vtk_netcdf_ncx_putn_int_schar +#define ncx_putn_int_short vtk_netcdf_ncx_putn_int_short +#define ncx_putn_int_uchar vtk_netcdf_ncx_putn_int_uchar +#define ncx_putn_schar_double vtk_netcdf_ncx_putn_schar_double +#define ncx_putn_schar_float vtk_netcdf_ncx_putn_schar_float +#define ncx_putn_schar_int vtk_netcdf_ncx_putn_schar_int +#define ncx_putn_schar_long vtk_netcdf_ncx_putn_schar_long +#define ncx_putn_schar_schar vtk_netcdf_ncx_putn_schar_schar +#define ncx_putn_schar_short vtk_netcdf_ncx_putn_schar_short +#define ncx_putn_schar_uchar vtk_netcdf_ncx_putn_schar_uchar +#define ncx_putn_short_double vtk_netcdf_ncx_putn_short_double +#define ncx_putn_short_float vtk_netcdf_ncx_putn_short_float +#define ncx_putn_short_int vtk_netcdf_ncx_putn_short_int +#define ncx_putn_short_long vtk_netcdf_ncx_putn_short_long +#define ncx_putn_short_schar vtk_netcdf_ncx_putn_short_schar +#define ncx_putn_short_short vtk_netcdf_ncx_putn_short_short +#define ncx_putn_short_uchar vtk_netcdf_ncx_putn_short_uchar +#define ncx_putn_text vtk_netcdf_ncx_putn_text +#define ncx_putn_void vtk_netcdf_ncx_putn_void +#define ncx_szof vtk_netcdf_ncx_szof +#define new_NC_string vtk_netcdf_new_NC_string +#define new_x_NC_attr vtk_netcdf_new_x_NC_attr +#define new_x_NC_dim vtk_netcdf_new_x_NC_dim +#define new_x_NC_var vtk_netcdf_new_x_NC_var +#define read_numrecs vtk_netcdf_read_numrecs +#define set_NC_string vtk_netcdf_set_NC_string +#define write_numrecs vtk_netcdf_write_numrecs + +#endif + diff --git a/Utilities/vtkpng/.NoDartCoverage b/Utilities/vtkpng/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/vtkpng/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/vtkpng/CMakeLists.txt b/Utilities/vtkpng/CMakeLists.txt new file mode 100644 index 0000000..2285845 --- /dev/null +++ b/Utilities/vtkpng/CMakeLists.txt @@ -0,0 +1,42 @@ +PROJECT(VTKPNG) +INCLUDE_REGULAR_EXPRESSION("^(png|vtk|z).*$") + +INCLUDE_DIRECTORIES(${VTKPNG_SOURCE_DIR}) + +# source files for png +SET(PNG_SRCS +pngget.c pngrio.c pngwrite.c +png.c pngmem.c pngrtran.c pngtrans.c pngwtran.c +pngerror.c pngpread.c pngrutil.c pngvcrd.c pngwutil.c +pnggccrd.c pngread.c pngset.c pngwio.c +) + +IF(WIN32) + IF(BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DPNG_BUILD_DLL) + SET(PNG_NO_MODULEDEF 1) + ELSE(BUILD_SHARED_LIBS) + SET(PNG_STATIC 1) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(WIN32) + +CONFIGURE_FILE(${VTKPNG_SOURCE_DIR}/.NoDartCoverage + ${VTKPNG_BINARY_DIR}/.NoDartCoverage) +CONFIGURE_FILE(${VTKPNG_SOURCE_DIR}/pngDllConfig.h.in + ${VTKPNG_BINARY_DIR}/pngDllConfig.h) + +ADD_LIBRARY(vtkpng ${PNG_SRCS}) +TARGET_LINK_LIBRARIES(vtkpng ${VTK_ZLIB_LIBRARIES}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkpng PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkpng) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtkpng .h + png pngconf pngDllConfig vtk_png_mangle) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/vtkpng/png.c b/Utilities/vtkpng/png.c new file mode 100644 index 0000000..29adb0c --- /dev/null +++ b/Utilities/vtkpng/png.c @@ -0,0 +1,732 @@ + +/* png.c - location for general purpose libpng functions + * + * libpng version 1.0.12 - June 8, 2001 + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + */ + +#define PNG_INTERNAL +#define PNG_NO_EXTERN +#include "png.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_0_12 Your_png_h_is_not_version_1_0_12; + +/* Version information for C files. This had better match the version + * string defined in png.h. */ + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* png_libpng_ver was changed to a function in version 1.0.5c */ +const char png_libpng_ver[18] = "1.0.12"; + +/* png_sig was changed to a function in version 1.0.5c */ +/* Place to hold the signature string for a PNG file. */ +const png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +/* Invoke global declarations for constant strings for known chunk types */ +PNG_IHDR; +PNG_IDAT; +PNG_IEND; +PNG_PLTE; +PNG_bKGD; +PNG_cHRM; +PNG_gAMA; +PNG_hIST; +PNG_iCCP; +PNG_iTXt; +PNG_oFFs; +PNG_pCAL; +PNG_sCAL; +PNG_pHYs; +PNG_sBIT; +PNG_sPLT; +PNG_sRGB; +PNG_tEXt; +PNG_tIME; +PNG_tRNS; +PNG_zTXt; + +/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + +/* start of interlace block */ +const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + +/* offset to next interlace block */ +const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + +/* start of interlace block in the y direction */ +const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + +/* offset to next interlace block in the y direction */ +const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + +/* width of interlace block (used in assembler routines only) */ +#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW +const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; +#endif + +/* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h +const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; +*/ + +/* Mask to determine which pixels are valid in a pass */ +const int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + +/* Mask to determine which pixels to overwrite while displaying */ +const int FARDATA png_pass_dsp_mask[] + = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + +#endif + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes\n"); + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature."); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + if (num_to_check > 8) + num_to_check = 8; + else if (num_to_check < 1) + return (0); + + if (start > 7) + return (0); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +/* (Obsolete) function to check signature bytes. It does not allow one + * to check a partial signature. This function might be removed in the + * future - use png_sig_cmp(). Returns true (nonzero) if the file is a PNG. + */ +int PNGAPI +png_check_sig(png_bytep sig, int num) +{ + return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); +} + +/* Function to allocate memory for zlib and clear it to 0. */ +voidpf /* PRIVATE */ +png_zalloc(voidpf png_ptr, uInt items, uInt size) +{ + png_uint_32 num_bytes = (png_uint_32)items * size; + png_voidp ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + +#ifndef PNG_NO_ZALLOC_ZERO + if (num_bytes > (png_uint_32)0x8000L) + { + png_memset(ptr, 0, (png_size_t)0x8000L); + png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, + (png_size_t)(num_bytes - (png_uint_32)0x8000L)); + } + else + { + png_memset(ptr, 0, (png_size_t)num_bytes); + } +#endif + return ((voidpf)ptr); +} + +/* function to free memory for zlib */ +void /* PRIVATE */ +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +png_infop PNGAPI +png_create_info_struct(png_structp png_ptr) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct\n"); + if(png_ptr == NULL) return (NULL); +#ifdef PNG_USER_MEM_SUPPORTED + if ((info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr)) != NULL) +#else + if ((info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO)) != NULL) +#endif + { + png_info_init_3(&info_ptr, sizeof(png_info)); + } + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct\n"); + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = (png_infop)NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ +#undef png_info_init +void PNGAPI +vtk_png_info_init(png_infop info_ptr) +{ + /* We only come here via pre-1.0.12-compiled applications */ + png_info_init_3(&info_ptr, 0); +} + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3\n"); + + if(sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* set everything to 0 */ + png_memset(info_ptr, 0, sizeof (png_info)); +} + +#ifdef PNG_FREE_ME_SUPPORTED +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer\n"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if(freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + else if(freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer."); +} +#endif + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data\n"); + if (png_ptr == NULL || info_ptr == NULL) + return; + +#if defined(PNG_TEXT_SUPPORTED) +/* free text item num or (if num == -1) all text items */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) +#else +if (mask & PNG_FREE_TEXT) +#endif +{ + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +/* free any tRNS entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) +#endif +{ + png_free(png_ptr, info_ptr->trans); + info_ptr->valid &= ~PNG_INFO_tRNS; + info_ptr->trans = NULL; +} +#endif + +#if defined(PNG_sCAL_SUPPORTED) +/* free any sCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) +#else +if (mask & PNG_FREE_SCAL) +#endif +{ +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; +#endif + info_ptr->valid &= ~PNG_INFO_sCAL; +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +/* free any pCAL entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) +#else +if (mask & PNG_FREE_PCAL) +#endif +{ + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i]=NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; +} +#endif + +#if defined(PNG_iCCP_SUPPORTED) +/* free any iCCP entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) +#else +if (mask & PNG_FREE_ICCP) +#endif +{ + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +/* free a given sPLT entry, or (if num == -1) all sPLT entries */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) +#else +if (mask & PNG_FREE_SPLT) +#endif +{ + if (num != -1) + { + if(info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + else + { + if(info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) +#else +if (mask & PNG_FREE_UNKN) +#endif +{ + if (num != -1) + { + if(info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + else + { + int i; + + if(info_ptr->unknown_chunks_num) + { + for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +/* free any hIST entry */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_HIST) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) +#endif +{ + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; +} +#endif + +/* free any PLTE entry that was internally allocated */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) +#else +if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) +#endif +{ + png_zfree((voidpf)png_ptr, (voidpf)info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* free any image bits attached to the info structure */ +#ifdef PNG_FREE_ME_SUPPORTED +if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) +#else +if (mask & PNG_FREE_ROWS) +#endif +{ + if(info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row]=NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers=NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; +} +#endif + +#ifdef PNG_FREE_ME_SUPPORTED + if(num == -1) + info_ptr->free_me &= ~mask; + else + info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); +#endif +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy\n"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; + } +#endif + + png_info_init_3(&info_ptr, sizeof(png_info)); +} + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + return (png_ptr->io_ptr); +} + +#if !defined(PNG_NO_STDIO) +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io\n"); + png_ptr->io_ptr = (png_voidp)fp; +} +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (png_ptr->time_buffer == NULL) + { + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + sizeof(char))); + } + +#if defined(_WIN32_WCE) + { + wchar_t time_buf[29]; + wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, + NULL, NULL); + } +#else +#ifdef USE_FAR_KEYWORD + { + char near_time_buf[29]; + sprintf(near_time_buf, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*sizeof(char)); + } +#else + sprintf(png_ptr->time_buffer, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); +#endif +#endif /* _WIN32_WCE */ + return ((png_charp)png_ptr->time_buffer); +} +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#if 0 +/* Signature string for a PNG file. */ +png_bytep PNGAPI +png_sig_bytes(void) +{ + return ((png_bytep)"\211\120\116\107\015\012\032\012"); +} +#endif + +#if defined(_MSC_VER) +#pragma warning ( disable : 4702 ) +#endif +png_charp PNGAPI +png_get_copyright(png_structp png_ptr) +{ + if (png_ptr != NULL || png_ptr == NULL) /* silence compiler warning */ + return ((png_charp) "\n libpng version 1.0.12 - June 8, 2001\n\ + Copyright (c) 1998-2001 Glenn Randers-Pehrson\n\ + Copyright (c) 1996, 1997 Andreas Dilger\n\ + Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.\n"); + return ((png_charp) ""); +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files used + * with your application, print out PNG_LIBPNG_VER_STRING, which is defined + * in png.h. + */ + +png_charp PNGAPI +png_get_libpng_ver(png_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */ + return((png_charp) "1.0.12"); + return((png_charp) "1.0.12"); +} + +png_charp PNGAPI +png_get_header_ver(png_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */ + return((png_charp) PNG_LIBPNG_VER_STRING); + return((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_version(png_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + if(png_ptr != NULL) /* silence compiler warning about unused png_ptr */ + return((png_charp) PNG_HEADER_VERSION_STRING); + return((png_charp) PNG_HEADER_VERSION_STRING); +} + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int /* PRIVATE */ +png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) +{ + /* check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if((png_ptr == NULL && chunk_name == NULL) || png_ptr->num_chunk_list<=0) + return 0; + p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5; + for (i = png_ptr->num_chunk_list; i; i--, p-=5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p+4)); + return 0; +} +#endif + +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + return (inflateReset(&png_ptr->zstream)); +} + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32) 10012L); +} + +/* this function was added to libpng 1.2.0 */ +#if !defined(PNG_USE_PNGGCCRD) && \ + !(defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD)) +int PNGAPI +png_mmx_support(void) +{ + return -1; +} +#endif diff --git a/Utilities/vtkpng/png.h b/Utilities/vtkpng/png.h new file mode 100644 index 0000000..f5f23c3 --- /dev/null +++ b/Utilities/vtkpng/png.h @@ -0,0 +1,3093 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.0.12 - June 8, 2001 + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.0.12 - June 8, 2001: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.11beta1-2 + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as RFC 2083 <ftp://ftp.uu.net/graphics/png/documents/> + * and as a W3C Recommendation <http://www.w3.org/TR/REC.png.html> + */ + +/* + * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * + * If you modify libpng you may insert additional notices immediately following + * this sentence. + * + * libpng versions 1.0.7, July 1, 2000, through 1.0.12, June 8, 2001, are + * Copyright (c) 2000, 2001 Glenn Randers-Pehrson, and are + * distributed according to the same disclaimer and license as libpng-1.0.6 + * with the following individuals added to the list of Contributing Authors + * + * Simon-Pierre Cadieux + * Eric S. Raymond + * Gilles Vollant + * + * and with the following additions to the disclaimer: + * + * There is no warranty against interference with your enjoyment of the + * library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is with + * the user. + * + * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are + * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson + * Distributed according to the same disclaimer and license as libpng-0.96, + * with the following individuals added to the list of Contributing Authors: + * + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik + * + * libpng versions 0.89, June 1996, through 0.96, May 1997, are + * Copyright (c) 1996, 1997 Andreas Dilger + * Distributed according to the same disclaimer and license as libpng-0.88, + * with the following individuals added to the list of Contributing Authors: + * + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner + * + * libpng versions 0.5, May 1995, through 0.88, January 1996, are + * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + * + * For the purposes of this copyright and license, "Contributing Authors" + * is defined as the following set of individuals: + * + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing Authors + * and Group 42, Inc. disclaim all warranties, expressed or implied, + * including, without limitation, the warranties of merchantability and of + * fitness for any purpose. The Contributing Authors and Group 42, Inc. + * assume no liability for direct, indirect, incidental, special, exemplary, + * or consequential damages, which may result from the use of the PNG + * Reference Library, even if advised of the possibility of such damage. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * source code, or portions hereof, for any purpose, without fee, subject + * to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented. + * + * 2. Altered versions must be plainly marked as such and + * must not be misrepresented as being the original source. + * + * 3. This Copyright notice may not be removed or altered from + * any source or altered source distribution. + * + * The Contributing Authors and Group 42, Inc. specifically permit, without + * fee, and encourage the use of this source code as a component to + * supporting the PNG file format in commercial products. If you use this + * source code in a product, acknowledgment is not required but would be + * appreciated. + */ + +/* + * A "png_get_copyright" function is available, for convenient use in "about" + * boxes and the like: + * + * printf("%s",png_get_copyright(NULL)); + * + * Also, the PNG logo (in PNG format, of course) is supplied in the + * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + */ + +/* + * Libpng is OSI Certified Open Source Software. OSI Certified is a + * certification mark of the Open Source Initiative. + */ + +/* + * The contributing authors would like to thank all those who helped + * with testing, bug fixes, and patience. This wouldn't have been + * possible without all of you. + * + * Thanks to Frank J. T. Wojcik for helping with the documentation. + */ + +/* + * Y2K compliance in libpng: + * ========================= + * + * June 8, 2001 + * + * Since the PNG Development group is an ad-hoc body, we can't make + * an official declaration. + * + * This is your unofficial assurance that libpng from version 0.71 and + * upward through 1.0.12 are Y2K compliant. It is my belief that earlier + * versions were also Y2K compliant. + * + * Libpng only has three year fields. One is a 2-byte unsigned integer + * that will hold years up to 65535. The other two hold the date in text + * format, and will hold years up to 9999. + * + * The integer is + * "png_uint_16 year" in png_time_struct. + * + * The strings are + * "png_charp time_buffer" in png_struct and + * "near_time_buffer", which is a local character string in png.c. + * + * There are seven time-related functions: + * png.c: png_convert_to_rfc_1123() in png.c + * (formerly png_convert_to_rfc_1152() in error) + * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c + * png_convert_from_time_t() in pngwrite.c + * png_get_tIME() in pngget.c + * png_handle_tIME() in pngrutil.c, called in pngread.c + * png_set_tIME() in pngset.c + * png_write_tIME() in pngwutil.c, called in pngwrite.c + * + * All handle dates properly in a Y2K environment. The + * png_convert_from_time_t() function calls gmtime() to convert from system + * clock time, which returns (year - 1900), which we properly convert to + * the full 4-digit year. There is a possibility that applications using + * libpng are not passing 4-digit years into the png_convert_to_rfc_1123() + * function, or that they are incorrectly passing only a 2-digit year + * instead of "year - 1900" into the png_convert_from_struct_tm() function, + * but this is not under our control. The libpng documentation has always + * stated that it works with 4-digit years, and the APIs have been + * documented as such. + * + * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned + * integer to hold the year, and can hold years as large as 65535. + * + * zlib, upon which libpng depends, is also Y2K compliant. It contains + * no date-related code. + * + * Glenn Randers-Pehrson + * libpng maintainer + * PNG Development Group + */ + +#ifndef PNG_H +#define PNG_H + +/* This is not the place to learn how to use libpng. The file libpng.txt + * describes how to use libpng, and the file example.c summarizes it + * with some code on which to build. This file is useful for looking + * at the actual function definitions and structure components. + */ + +/* Version information for png.h - this should match the version in png.c */ +#define PNG_LIBPNG_VER_STRING "1.0.12" + +#define PNG_LIBPNG_VER_SONUM 2 +#define PNG_LIBPNG_VER_DLLNUM %DLLNUM% + +/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 0 +#define PNG_LIBPNG_VER_RELEASE 12 +/* This should match the numeric part of the final component of + * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ + +#define PNG_LIBPNG_VER_BUILD 0 + +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_TYPEMASK 7 +#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with STABLE only */ +#define PNG_LIBPNG_BUILD_TYPE 4 + +/* Careful here. At one time, Guy wanted to use 082, but that would be octal. + * We must not include leading zeros. + * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only + * version 1.0.0 was mis-numbered 100 instead of 10000). From + * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ +#define PNG_LIBPNG_VER 10012 /* 1.0.12 */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* include the compression library's header */ +#include "vtk_zlib.h" + +/* include all user configurable info, including optional assembler routines */ +#include "pngconf.h" + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* This file is arranged in several sections. The first section contains + * structure and type definitions. The second section contains the external + * library functions, while the third has the internal library functions, + * which applications aren't expected to use directly. + */ + +/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (const char) png_libpng_ver[18]; + /* need room for 99.99.99beta99z*/ +#else +#undef png_libpng_ver +#define png_libpng_ver png_get_header_ver(NULL) +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +/* This was removed in version 1.0.5c */ +/* Structures to facilitate easy interlacing. See png.c for more details */ +PNG_EXPORT_VAR (const int FARDATA) png_pass_start[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_inc[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_ystart[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_yinc[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_mask[7]; +PNG_EXPORT_VAR (const int FARDATA) png_pass_dsp_mask[7]; +#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW +PNG_EXPORT_VAR (const int FARDATA) png_pass_width[7]; +#endif +/* This isn't currently used. If you need it, see png.c for more details. +PNG_EXPORT_VAR (const int FARDATA) png_pass_height[7]; +*/ +#endif + +#endif /* PNG_NO_EXTERN */ + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text", "lang", and + * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. + * However, the * structure returned by png_get_text() will always contain + * regular zero-terminated C strings (possibly empty), never NULL pointers, + * so they can be safely used in printf() and other string-handling functions. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ +#ifdef PNG_iTXt_SUPPORTED + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +#endif +} png_text; +typedef png_text FAR * png_textp; +typedef png_text FAR * FAR * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef png_time FAR * FAR * png_timepp; + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +/* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, then call png_write_info(). + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. + * + * In any case, the order of the parameters in png_info_struct should NOT + * be changed for as long as possible to keep compatibility with applications + * that use the old direct-access method with png_info_struct. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +typedef struct png_info_struct +{ + /* the following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_uint_32 rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4)*/ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + /* The gAMA chunk describes the gamma characteristics of the system + * on which the image was created, normally in the range [1.0, 2.5]. + * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. + */ + float gamma; /* gamma value of image, if (valid & PNG_INFO_gAMA) */ +#endif + +#if defined(PNG_sRGB_SUPPORTED) + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ +#endif + +#if defined(PNG_TEXT_SUPPORTED) + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read/to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read/to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#if defined(PNG_tIME_SUPPORTED) + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; +#endif + +#if defined(PNG_sBIT_SUPPORTED) + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans; /* transparent values for paletted image */ + png_color_16 trans_values; /* transparent color for non-palette image */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; +#endif + +#if defined(PNG_oFFs_SUPPORTED) + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ +#endif + +#if defined(PNG_pHYs_SUPPORTED) + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#if defined(PNG_hIST_SUPPORTED) + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; +#endif + +#ifdef PNG_cHRM_SUPPORTED + /* The cHRM chunk describes the CIE color characteristics of the monitor + * on which the PNG was created. This data allows the viewer to do gamut + * mapping of the input image to ensure that the viewer sees the same + * colors in the image as the creator. Values are in the range + * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float x_white; + float y_white; + float x_red; + float y_red; + float x_green; + float y_green; + float x_blue; + float y_blue; +#endif +#endif + +#if defined(PNG_pCAL_SUPPORTED) + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + png_size_t unknown_chunks_num; +#endif + +#if defined(PNG_iCCP_SUPPORTED) + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_charp iccp_profile; /* International Color Consortium profile data */ + /* Note to maintainer: should be png_bytep */ + png_uint_32 iccp_proflen; /* ICC profile data length */ + png_byte iccp_compression; /* Always zero */ +#endif + +#if defined(PNG_sPLT_SUPPORTED) + /* data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + png_uint_32 splt_palettes_num; +#endif + +#if defined(PNG_sCAL_SUPPORTED) + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. This external representation is converted to double + * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + double scal_pixel_width; /* width of one pixel */ + double scal_pixel_height; /* height of one pixel */ +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#endif +#endif + +#if defined(PNG_INFO_IMAGE_SUPPORTED) + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ +#endif + +#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED) + png_fixed_point int_gamma; /* gamma of image, if (valid & PNG_INFO_gAMA) */ +#endif + +#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED) + png_fixed_point int_x_white; + png_fixed_point int_y_white; + png_fixed_point int_x_red; + png_fixed_point int_y_red; + png_fixed_point int_x_green; + png_fixed_point int_y_green; + png_fixed_point int_x_blue; + png_fixed_point int_y_blue; +#endif + +} png_info; + +typedef png_info FAR * png_infop; +typedef png_info FAR * FAR * png_infopp; + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_MAX_UINT ((png_uint_32)0x7fffffffL) + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_<chunk> defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_uint_32 rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); +#endif +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf; /* used in png_error */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions*/ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + png_size_t zbuf_size; /* size of zbuf */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 rowbytes; /* size of row in bytes */ + png_uint_32 irowbytes; /* size of current interlaced row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +#ifdef PNG_LEGACY_SUPPORTED + png_byte filler; /* filler byte for pixel expansion */ +#else + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif +#endif + +#if defined(PNG_bKGD_SUPPORTED) + png_byte background_gamma_type; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma; +# endif + png_color_16 background; /* background color in screen gamma space */ +# if defined(PNG_READ_GAMMA_SUPPORTED) + png_color_16 background_1; /* background normalized to gamma 1.0 */ +# endif /* PNG_READ_GAMMA && PNG_bKGD_SUPPORTED */ +#endif /* PNG_bKGD_SUPPORTED */ + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_flush_ptr output_flush_fn;/* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma; /* file gamma value */ + float screen_gamma; /* screen gamma value (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans; /* transparency values for paletted files */ + png_color_16 trans_values; /* transparency values for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# if defined(PNG_TEXT_SUPPORTED) + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* for the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + png_bytep palette_lookup; /* lookup table for dithering */ + png_bytep dither_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* changed from png_byte to png_uint_32 at version 1.2.0 */ + png_byte mng_features_permitted; +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_byte filter_type; +#endif + +#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD) +/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ + png_uint_32 row_buf_size; +#endif + +/* New members added in libpng-1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + png_byte mmx_bitdepth_threshold; + png_uint_32 mmx_rowbytes_threshold; + png_uint_32 asm_flags; +#endif + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +}; + + +/* This prevents a compiler error in png_get_copyright() in png.c if png.c + and png.h are both at version 1.0.12 + */ +typedef png_structp version_1_0_12; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first <num_bytes> magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_uint_32 size)); + +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +#endif + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)); + +/* Initialize the info structure (old interface - DEPRECATED) */ +extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); +#undef png_info_init +#define png_info_init(info_ptr) png_info_init_3(&info_ptr, sizeof(png_info)); +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_WRITE_tIME_SUPPORTED */ +#endif /* _WIN32_WCE */ + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Turn on dithering, and reduce the palette to the number of colors available. */ +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ +/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ +extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, + int empty_plte_permitted)); +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* read a one or more rows of image data.*/ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); + +/* read a row of data.*/ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); + +/* read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* writes the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* free all memory used by the read (old method - NOT DLL EXPORTED) */ +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* free any memory used in info_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy_info PNGARG((png_infop info_ptr)); + +/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy PNGARG((png_structp png_ptr)); + +/* set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#if !defined(PNG_NO_STDIO) +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)); + +/* frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +#ifdef PNG_FREE_ME_SUPPORTED +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +#endif +/* assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_uint_32 size)); +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, + png_voidp s1, png_voidp s2, png_uint_32 size)); + +extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, + png_voidp s1, int value, png_uint_32 size)); + +#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error)); + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error)); + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp message)); + +/* The png_set_<chunk> functions are for storing values in the png_info_struct. + * Similarly, the png_get_<chunk> calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_<chunk> functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* Returns row_pointers, which is an array of pointers to scanlines that was +returned from png_read_png(). */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use +by png_write_png(). */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* + * Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#if defined(PNG_TEXT_SUPPORTED) +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans, int *num_trans, + png_color_16p *trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans, int num_trans, + png_color_16p trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +/* provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behavour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + If you need to turn it off for a chunk that your application has freed, + you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include <crtdbg.h> +#if (PNG_DEBUG > 1) +#define png_debug(l,m) _RPT0(_CRT_WARN,m) +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ +#if (PNG_DEBUG > 1) +#define png_debug(l,m) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ +} +#define png_debug1(l,m,p1) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ +} +#define png_debug2(l,m,p1,p2) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ +} +#endif /* (PNG_DEBUG > 1) */ +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +extern PNG_EXPORT(png_bytep,png_sig_bytes) PNGARG((void)); + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* png_mmx_support will be included unconditionally starting in version 1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) || defined(PNG_USE_PNGGCCRD) +/* png.c, pnggccrd.c, or pngvcrd.c */ +extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ + +#define PNG_HEADER_VERSION_STRING \ + " libpng version 1.0.12 - June 8, 2001 (header)\n" + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 - \ + (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L - \ + (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) + +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +/* These next functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +#if defined(PNG_INTERNAL) + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 + +/* flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_DITHER 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + +/* flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_FREE_PLTE 0x1000 +#define PNG_FLAG_FREE_TRNS 0x2000 +#define PNG_FLAG_FREE_HIST 0x4000 +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L + +/* For use in png_set_keep_unknown, png_handle_as_unknown */ +#define HANDLE_CHUNK_AS_DEFAULT 0 +#define HANDLE_CHUNK_NEVER 1 +#define HANDLE_CHUNK_IF_SAFE 2 +#define HANDLE_CHUNK_ALWAYS 3 + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* save typing and make code easier to understand */ +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* place to hold the signature string for a PNG file. */ +#ifdef PNG_USE_GLOBAL_ARRAYS + PNG_EXPORT_VAR (const png_byte FARDATA) png_sig[8]; +#else +#undef png_sig +#define png_sig png_sig_bytes(NULL) +#endif +#endif /* PNG_NO_EXTERN */ + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro in png.c and + * wherever it's needed. + */ +#define PNG_IHDR const png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT const png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND const png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE const png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD const png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM const png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA const png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST const png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP const png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt const png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs const png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL const png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL const png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs const png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT const png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT const png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB const png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_tEXt const png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME const png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS const png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt const png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_PLTE[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_bKGD[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_cHRM[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_gAMA[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_hIST[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iTXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_oFFs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pHYs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sBIT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sPLT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sRGB[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tEXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tIME[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tRNS[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_zTXt[5]; +#endif /* PNG_USE_GLOBAL_ARRAYS */ + + +/* Inline macros to do direct reads of bytes from the input buffer. These + * require that you are using an architecture that uses PNG byte ordering + * (MSB first) and supports unaligned data storage. I think that PowerPC + * in big-endian mode and 680x0 are the only ones that will support this. + * The x86 line of processors definitely do not. The png_get_int_32() + * routine also assumes we are using two's complement format for negative + * values, which is almost certainly true. + */ +#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) +# if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED) +# define png_get_int_32(buf) ( *((png_int_32p) (buf))) +# endif +# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) +# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) +#else +# if defined(PNG_pCAL_SUPPORTED) || defined(PNG_oFFs_SUPPORTED) +PNG_EXTERN png_int_32 png_get_int_32 PNGARG((png_bytep buf)); +# endif +PNG_EXTERN png_uint_32 png_get_uint_32 PNGARG((png_bytep buf)); +PNG_EXTERN png_uint_16 png_get_uint_16 PNGARG((png_bytep buf)); +#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ + +/* Initialize png_ptr struct for reading, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_read_struct instead). + */ +extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); +#undef png_read_init +#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, sizeof(png_struct)); +extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Initialize png_ptr struct for writing, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_write_struct instead). + */ +extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); +#undef png_write_init +#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, sizeof(png_struct)); +extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* Function to allocate memory for zlib. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); + +/* Function to free memory for zlib */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using. */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_length, png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). + * The only currently known PNG chunks that use signed numbers are + * the ancillary extension chunks, oFFs and pCAL. + */ +PNG_EXTERN void png_save_uint_32 PNGARG((png_bytep buf, png_uint_32 i)); + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +PNG_EXTERN void png_save_int_32 PNGARG((png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +PNG_EXTERN void png_save_uint_16 PNGARG((png_bytep buf, unsigned int i)); + +/* simple function to write the signature */ +PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); + +/* write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point + file_gamma)); +#endif +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_uint_32 x_offset, png_uint_32 y_offset, int unit_type)); +#endif + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); +#endif +#endif +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); +#endif + +/* combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) +/* expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* these are the functions that do the transformations */ +#if defined(PNG_READ_FILLER_SUPPORTED) +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); + +# if defined(PNG_CORRECT_PALETTE_SUPPORTED) +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#if defined(PNG_READ_bKGD_SUPPORTED) +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_gAMA_SUPPORTED) +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_iCCP_SUPPORTED) +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sPLT_SUPPORTED) +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_sRGB_SUPPORTED) +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tRNS_SUPPORTED) +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXTERN int png_handle_as_unknown PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); + +/* handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#endif /* PNG_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* do not put anything past this line */ +#endif /* PNG_H */ diff --git a/Utilities/vtkpng/pngDllConfig.h.in b/Utilities/vtkpng/pngDllConfig.h.in new file mode 100644 index 0000000..40b05b3 --- /dev/null +++ b/Utilities/vtkpng/pngDllConfig.h.in @@ -0,0 +1,11 @@ +#ifndef _pngDllConfig_h +#define _pngDllConfig_h + +#cmakedefine PNG_STATIC +#cmakedefine PNG_NO_MODULEDEF + +#if defined(_WIN32) && !defined(PNG_STATIC) && !defined(PNG_BUILD_DLL) +# define PNG_USE_DLL +#endif + +#endif diff --git a/Utilities/vtkpng/pngasmrd.h b/Utilities/vtkpng/pngasmrd.h new file mode 100644 index 0000000..2db1852 --- /dev/null +++ b/Utilities/vtkpng/pngasmrd.h @@ -0,0 +1,11 @@ +/* pngasmrd.h - assembler version of utilities to read a PNG file + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 2001 Glenn Randers-Pehrson + * + */ + +/* This file is obsolete in libpng-1.0.9 and later; its contents now appear + * at the end of pngconf.h. + */ diff --git a/Utilities/vtkpng/pngconf.h b/Utilities/vtkpng/pngconf.h new file mode 100644 index 0000000..9df1346 --- /dev/null +++ b/Utilities/vtkpng/pngconf.h @@ -0,0 +1,1345 @@ +#include "vtk_png_mangle.h" +/* pngconf.h - machine configurable file for libpng + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#include <vtkpng/pngDllConfig.h> + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +/* +#ifndef PNG_NO_MNG_FEATURES +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif +*/ + +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- building the dll + * (no define) -- building an application, linking to the dll + * PNG_STATIC -- building the static lib, or building an application + * that links to the static lib. + * ALL_STATIC -- building various static libs, or building an application + * that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + */ +#if defined(__CYGWIN__) +# if defined(ALL_STATIC) +# if defined(PNG_BUILD_DLL) +# undef PNG_BUILD_DLL +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# if !defined(PNG_STATIC) +# define PNG_STATIC +# endif +# else +# if defined (PNG_BUILD_DLL) +# if defined(PNG_STATIC) +# undef PNG_STATIC +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# else +# if defined(PNG_STATIC) +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# else +# if !defined(PNG_USE_DLL) +# define PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if defined(_WIN32_WCE) +# include <windows.h> + /* Console I/O functions are not supported on WindowsCE */ +# define PNG_NO_CONSOLE_IO +# ifdef PNG_DEBUG +# undef PNG_DEBUG +# endif +#endif + +#ifdef PNG_BUILD_DLL +# ifndef PNG_CONSOLE_IO_SUPPORTED +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include <stdio.h> +# endif +# endif +# else +# if !defined(_WIN32_WCE) +/* "stdio.h" functions are not supported on WindowsCE */ +# include <stdio.h> +# endif +# endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) +# include <sys/types.h> +#endif + +#ifndef PNG_SETJMP_NOT_SUPPORTED +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + */ + +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + __png.h__ already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ +#if defined(__sgi) && !defined(__GNUC__) +# if (_COMPILER_VERSION >= 730) +# pragma set woff 3505 +# endif +#endif + /* include setjmp.h for error handling */ +# include <setjmp.h> + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include <strings.h> +#else +# include <string.h> +#endif + +/* Other defines for things like memory and the like can go here. */ +#ifdef PNG_INTERNAL + +#include <stdlib.h> + +/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it is + * possible to have run-time registry of chunk-handling functions, some of + * these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) +# if defined(MACOS) + /* We need to check that <math.h> hasn't already been included earlier + * as it seems it doesn't agree with <fp.h>, yet we should really use + * <fp.h> if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include <fp.h> +# endif +# else +# include <math.h> +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include <m68881.h> +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* For some reason, Borland C++ defines memcmp, etc. in mem.h, not + * stdlib.h like it should (I think). Or perhaps this is a C++ + * "feature"? + */ +#if 0 +#ifdef __TURBOC__ +# include <mem.h> +# include "alloc.h" +#endif +#endif + +#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ + defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) +# include <malloc.h> +#endif + +/* This controls how fine the dithering gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with dithering quality can decrease some or all of these. + */ +#ifndef PNG_DITHER_RED_BITS +# define PNG_DITHER_RED_BITS 5 +#endif +#ifndef PNG_DITHER_GREEN_BITS +# define PNG_DITHER_GREEN_BITS 5 +#endif +#ifndef PNG_DITHER_BLUE_BITS +# define PNG_DITHER_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +#endif /* PNG_INTERNAL */ + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_NO_CONST +# define PNG_CONST const +#else +# define PNG_CONST +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS + * on the compile line, then pick and choose which ones to define without + * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency) + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt is supported. It is turned off by default, to support old apps + * that malloc the png_text structure instead of calling png_set_text() + * and letting libpng malloc it. It will be turned on by default in + * libpng-1.3.0. + */ + +#ifndef PNG_iTXt_SUPPORTED +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_NO_READ_iTXt +# endif +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_NO_WRITE_iTXt +# endif +#endif + +/* The following support, added after version 1.0.0, can be turned off here en + * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility + * with old applications that require the length of png_struct and png_info + * to remain unchanged. + */ + +#ifdef PNG_LEGACY_SUPPORTED +# define PNG_NO_FREE_ME +# define PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_NO_READ_USER_CHUNKS +# define PNG_NO_READ_iCCP +# define PNG_NO_WRITE_iCCP +# define PNG_NO_READ_iTXt +# define PNG_NO_WRITE_iTXt +# define PNG_NO_READ_sCAL +# define PNG_NO_WRITE_sCAL +# define PNG_NO_READ_sPLT +# define PNG_NO_WRITE_sPLT +# define PNG_NO_INFO_IMAGE +# define PNG_NO_READ_RGB_TO_GRAY +# define PNG_NO_READ_USER_TRANSFORM +# define PNG_NO_WRITE_USER_TRANSFORM +# define PNG_NO_USER_MEM +# define PNG_NO_READ_EMPTY_PLTE +# define PNG_NO_MNG_FEATURES +# define PNG_NO_FIXED_POINT_SUPPORTED +#endif + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifndef PNG_NO_FREE_ME +# define PNG_FREE_ME_SUPPORTED +#endif + +#if defined(PNG_READ_SUPPORTED) + +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_DITHER +# define PNG_READ_DITHER_SUPPORTED +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following line: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +/* Deprecated, will be removed from version 2.0.0. + Use PNG_MNG_FEATURES_SUPPORTED instead. */ +#ifndef PNG_NO_READ_EMPTY_PLTE +# define PNG_READ_EMPTY_PLTE_SUPPORTED +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_WRITE_SUPPORTED) + +# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant + encoders, but can cause trouble + if left undefined */ + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +/* Will be enabled in libpng-1.2.0 */ +/* +#ifndef PNG_NO_ERROR_NUMBERS +#define PNG_ERROR_NUMBERS_SUPPORTED +#endif +*/ + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ +#ifndef PNG_NO_WRITE_EMPTY_PLTE +# define PNG_WRITE_EMPTY_PLTE_SUPPORTED +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef PNG_NO_STDIO +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 + even when PNG_USE_PNGVCRD or PNG_USE_PNGGCCRD is not defined */ +/* +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) +# ifndef PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED +# endif +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_MMX_CODE_SUPPORTED +# endif +#endif +*/ +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) +# if defined(PNG_USE_PNGVCRD) || defined(PNG_USE_PNGGCCRD) +# ifndef PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED +# endif +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) +# define PNG_MMX_CODE_SUPPORTED +# endif +# endif +#endif + +/* This will be enabled by default in libpng-1.2.0 */ +/* +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif +*/ + +/* These are currently experimental features, define them if you want */ + +/* very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +# endif +#endif +*/ + +/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ +/* +#define PNG_NO_POINTER_INDEXING +*/ + +/* These functions are turned off by default, as they will be phased out. */ +/* +#define PNG_USELESS_TESTS_SUPPORTED +#define PNG_CORRECT_PALETTE_SUPPORTED +*/ + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# define PNG_READ_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#if !defined(PNG_NO_READ_USER_CHUNKS) && \ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) +# define PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# ifdef PNG_NO_READ_UNKNOWN_CHUNKS +# undef PNG_NO_READ_UNKNOWN_CHUNKS +# endif +# ifdef PNG_NO_HANDLE_AS_UNKNOWN +# undef PNG_NO_HANDLE_AS_UNKNOWN +# endif +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# define PNG_WRITE_iTXt_SUPPORTED +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* need the time information for reading tIME chunks */ +#if defined(PNG_tIME_SUPPORTED) +# if !defined(_WIN32_WCE) + /* "time.h" functions are not supported on WindowsCE */ +# include <time.h> +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may + * want to have unsigned int for png_uint_32 instead of unsigned long. + */ + +typedef unsigned long png_uint_32; +typedef long png_int_32; +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +/* This is usually size_t. It is typedef'ed just in case you need it to + change (I'm not sure if you will or not, so I thought I'd be safe) */ +typedef size_t png_size_t; + +/* The following is needed for medium model support. It cannot be in the + * PNG_INTERNAL section. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + defines FAR. (SJT) */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#if defined(FAR) +# if defined(M_I86MM) +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include <dos.h> +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +#if defined(_WIN32_WCE) +typedef HANDLE png_FILE_p; +#else +typedef FILE * png_FILE_p; +#endif +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* libpng typedefs for types in zlib. If zlib changes + * or another compression library is used, then change these. + * Eliminates need to change all the source files. + */ +typedef charf * png_zcharp; +typedef charf * FAR * png_zcharpp; +typedef z_stream FAR * png_zstreamp; + +/* + * Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif +/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. + * When building a static lib, default to no GLOBAL ARRAYS, but allow + * command-line override + */ +#if defined(__CYGWIN__) +# if !defined(PNG_STATIC) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +# else +# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# endif +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +#endif + +/* Do not use global arrays (helps with building DLL's) + * They are no longer used in libpng itself, since version 1.0.5c, + * but might be required for some pre-1.0.5c applications. + */ +#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# if defined(PNG_NO_GLOBAL_ARRAYS) || (defined(__GNUC__) && defined(PNG_DLL)) +# define PNG_USE_LOCAL_ARRAYS +# else +# define PNG_USE_GLOBAL_ARRAYS +# endif +#endif + + +#ifndef PNGAPI + +#if defined(__MINGW32__) || defined(__CYGWIN__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + ) && !defined(__CYGWIN__)) + +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# if !defined(PNG_IMPEXP) + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import*/ /* doesn't exist AFAIK in + VC++*/ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# if !defined(PNG_IMPEXP) +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if defined(__CYGWIN__) && !defined(PNG_DLL) +# if !defined(PNG_IMPEXP) +# define PNG_IMPEXP +# endif +# define PNGAPI __cdecl +# else +# if (defined(__IBMC__) || defined(IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# define PNG_IMPEXP +# else +# if 0 /* ... other platforms, with other meanings */ +# else +# define PNGAPI +# define PNG_IMPEXP +# endif +# endif +# endif +#endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type +# endif +#endif + +/* User may want to use these so they are not in PNG_INTERNAL. Any library + * functions that are passed far data must be model independent. + */ + +#ifndef PNG_ABORT +# define PNG_ABORT() abort() +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) +#endif + +#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ +/* use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strcpy _fstrcpy +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else /* use the usual functions */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy strcpy +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +#endif +/* End of memory model independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536 +#endif + +#ifdef PNG_READ_SUPPORTED +/* Prior to libpng-1.0.9, this block was in pngasmrd.h */ +#if defined(PNG_INTERNAL) + +/* These are the default thresholds before the MMX code kicks in; if either + * rowbytes or bitdepth is below the threshold, plain C code is used. These + * can be overridden at runtime via the png_set_mmx_thresholds() call in + * libpng 1.2.0 and later. The values below were chosen by Intel. + */ + +#ifndef PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT +# define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT 128 /* >= */ +#endif +#ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT +# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ +#endif + +/* Set this in the makefile for VC++ on Pentium, not here. */ +/* Platform must be Pentium. Makefile must assemble and load pngvcrd.c . + * MMX will be detected at run time and used if present. + */ +#ifdef PNG_USE_PNGVCRD +# define PNG_HAVE_ASSEMBLER_COMBINE_ROW +# define PNG_HAVE_ASSEMBLER_READ_INTERLACE +# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +#endif + +/* Set this in the makefile for gcc/as on Pentium, not here. */ +/* Platform must be Pentium. Makefile must assemble and load pnggccrd.c . + * MMX will be detected at run time and used if present. + */ +#ifdef PNG_USE_PNGGCCRD +# define PNG_HAVE_ASSEMBLER_COMBINE_ROW +# define PNG_HAVE_ASSEMBLER_READ_INTERLACE +# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +#endif +/* - see pnggccrd.c for info about what is currently enabled */ + +#endif /* PNG_INTERNAL */ +#endif /* PNG_READ_SUPPORTED */ + +#endif /* PNGCONF_H */ + diff --git a/Utilities/vtkpng/pngerror.c b/Utilities/vtkpng/pngerror.c new file mode 100644 index 0000000..c2285ff --- /dev/null +++ b/Utilities/vtkpng/pngerror.c @@ -0,0 +1,290 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#define PNG_INTERNAL +#include "png.h" + +static void /* PRIVATE */ +png_default_error PNGARG((png_structp png_ptr, + png_const_charp message)); +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp message)); + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +void PNGAPI +png_error(png_structp png_ptr, png_const_charp message) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + int offset = 0; + if (*message == '#') + { + for (offset=1; offset<15; offset++) + if (*(message+offset) == ' ') + break; + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i=0; i<offset-1; i++) + msg[i]=message[i+1]; + msg[i]='\0'; + message=msg; + } + else + message+=offset; + } + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0]='0'; + msg[1]='\0'; + message=msg; + } + } + } +#endif + if (png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, message); + + /* if the following returns or doesn't exist, use the default function, + which will not return */ + png_default_error(png_ptr, message); +} + +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp message) +{ + int offset = 0; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags&(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*message == '#') + { + for (offset=1; offset<15; offset++) + if (*(message+offset) == ' ') + break; + } + } + if (png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, (png_const_charp)(message+offset)); + else + png_default_warning(png_ptr, (png_const_charp)(message+offset)); +} + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', + 'F' }; + +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = '['; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = ']'; + } + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (message == NULL) + buffer[iout] = 0; + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_memcpy(buffer+iout, message, 64); + buffer[iout+63] = 0; + } +} + +void PNGAPI +png_chunk_error(png_structp png_ptr, png_const_charp message) +{ + char msg[18+64]; + png_format_buffer(png_ptr, msg, message); + png_error(png_ptr, msg); +} + +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp message) +{ + char msg[18+64]; + png_format_buffer(png_ptr, msg, message); + png_warning(png_ptr, msg); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void /* PRIVATE */ +png_default_error(png_structp png_ptr, png_const_charp message) +{ +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*message == '#') + { + int offset; + char error_number[16]; + for (offset=0; offset<15; offset++) + { + error_number[offset] = *(message+offset+1); + if (*(message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + error_number[offset-1]='\0'; + fprintf(stderr, "libpng error no. %s: %s\n", error_number, message+offset); + } + else + fprintf(stderr, "libpng error: %s, offset=%d\n", message,offset); + } + else +#endif + fprintf(stderr, "libpng error: %s\n", message); +#else + if (message) + /* make compiler happy */ ; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# ifdef USE_FAR_KEYWORD + { + jmp_buf jmpbuf; + png_memcpy(jmpbuf,png_ptr->jmpbuf,sizeof(jmp_buf)); + longjmp(jmpbuf, 1); + } +# else + longjmp(png_ptr->jmpbuf, 1); +# endif +#else + if (png_ptr) + /* make compiler happy */ ; + PNG_ABORT(); +#endif +} + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp message) +{ +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*message == '#') + { + int offset; + char warning_number[16]; + for (offset=0; offset<15; offset++) + { + warning_number[offset]=*(message+offset+1); + if (*(message+offset) == ' ') + break; + } + if((offset > 1) && (offset < 15)) + { + warning_number[offset-1]='\0'; + fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, + message+offset); + } + else + fprintf(stderr, "libpng warning: %s\n", message); + } + else +# endif + fprintf(stderr, "libpng warning: %s\n", message); +#else + if (message) + /* appease compiler */ ; +#endif + if (png_ptr) + return; +} + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_structp png_ptr) +{ + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if(png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif + diff --git a/Utilities/vtkpng/pnggccrd.c b/Utilities/vtkpng/pnggccrd.c new file mode 100644 index 0000000..9b3b1bf --- /dev/null +++ b/Utilities/vtkpng/pnggccrd.c @@ -0,0 +1,5208 @@ +/* pnggccrd.c - mixed C/assembler version of utilities to read a PNG file + * + * For Intel x86 CPU (Pentium-MMX or later) and GNU C compiler. + * + * See http://www.intel.com/drg/pentiumII/appnotes/916/916.htm + * and http://www.intel.com/drg/pentiumII/appnotes/923/923.htm + * for Intel's performance analysis of the MMX vs. non-MMX code. + * + * libpng version 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * Copyright (c) 1998, Intel Corporation + * + * Based on MSVC code contributed by Nirav Chhatrapati, Intel Corp., 1998. + * Interface to libpng contributed by Gilles Vollant, 1999. + * GNU C port by Greg Roelofs, 1999-2001. + * + * Lines 2350-4300 converted in place with intel2gas 1.3.1: + * + * intel2gas -mdI pnggccrd.c.partially-msvc -o pnggccrd.c + * + * and then cleaned up by hand. See http://hermes.terminal.at/intel2gas/ . + * + * NOTE: A sufficiently recent version of GNU as (or as.exe under DOS/Windows) + * is required to assemble the newer MMX instructions such as movq. + * For djgpp, see + * + * ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bnu281b.zip + * + * (or a later version in the same directory). For Linux, check your + * distribution's web site(s) or try these links: + * + * http://rufus.w3.org/linux/RPM/binutils.html + * http://www.debian.org/Packages/stable/devel/binutils.html + * ftp://ftp.slackware.com/pub/linux/slackware/slackware/slakware/d1/ + * binutils.tgz + * + * For other platforms, see the main GNU site: + * + * ftp://ftp.gnu.org/pub/gnu/binutils/ + * + * Version 2.5.2l.15 is definitely too old... + */ + +/* + * TEMPORARY PORTING NOTES AND CHANGELOG (mostly by Greg Roelofs) + * ===================================== + * + * 19991006: + * - fixed sign error in post-MMX cleanup code (16- & 32-bit cases) + * + * 19991007: + * - additional optimizations (possible or definite): + * x [DONE] write MMX code for 64-bit case (pixel_bytes == 8) [not tested] + * - write MMX code for 48-bit case (pixel_bytes == 6) + * - figure out what's up with 24-bit case (pixel_bytes == 3): + * why subtract 8 from width_mmx in the pass 4/5 case? + * (only width_mmx case) (near line 1606) + * x [DONE] replace pixel_bytes within each block with the true + * constant value (or are compilers smart enough to do that?) + * - rewrite all MMX interlacing code so it's aligned with + * the *beginning* of the row buffer, not the end. This + * would not only allow one to eliminate half of the memory + * writes for odd passes (that is, pass == odd), it may also + * eliminate some unaligned-data-access exceptions (assuming + * there's a penalty for not aligning 64-bit accesses on + * 64-bit boundaries). The only catch is that the "leftover" + * pixel(s) at the end of the row would have to be saved, + * but there are enough unused MMX registers in every case, + * so this is not a problem. A further benefit is that the + * post-MMX cleanup code (C code) in at least some of the + * cases could be done within the assembler block. + * x [DONE] the "v3 v2 v1 v0 v7 v6 v5 v4" comments are confusing, + * inconsistent, and don't match the MMX Programmer's Reference + * Manual conventions anyway. They should be changed to + * "b7 b6 b5 b4 b3 b2 b1 b0," where b0 indicates the byte that + * was lowest in memory (e.g., corresponding to a left pixel) + * and b7 is the byte that was highest (e.g., a right pixel). + * + * 19991016: + * - Brennan's Guide notwithstanding, gcc under Linux does *not* + * want globals prefixed by underscores when referencing them-- + * i.e., if the variable is const4, then refer to it as const4, + * not _const4. This seems to be a djgpp-specific requirement. + * Also, such variables apparently *must* be declared outside + * of functions; neither static nor automatic variables work if + * defined within the scope of a single function, but both + * static and truly global (multi-module) variables work fine. + * + * 19991023: + * - fixed png_combine_row() non-MMX replication bug (odd passes only?) + * - switched from string-concatenation-with-macros to cleaner method of + * renaming global variables for djgpp--i.e., always use prefixes in + * inlined assembler code (== strings) and conditionally rename the + * variables, not the other way around. Hence _const4, _mask8_0, etc. + * + * 19991024: + * - fixed mmxsupport()/png_do_read_interlace() first-row bug + * This one was severely weird: even though mmxsupport() doesn't touch + * ebx (where "row" pointer was stored), it nevertheless managed to zero + * the register (even in static/non-fPIC code--see below), which in turn + * caused png_do_read_interlace() to return prematurely on the first row of + * interlaced images (i.e., without expanding the interlaced pixels). + * Inspection of the generated assembly code didn't turn up any clues, + * although it did point at a minor optimization (i.e., get rid of + * mmx_supported_local variable and just use eax). Possibly the CPUID + * instruction is more destructive than it looks? (Not yet checked.) + * - "info gcc" was next to useless, so compared fPIC and non-fPIC assembly + * listings... Apparently register spillage has to do with ebx, since + * it's used to index the global offset table. Commenting it out of the + * input-reg lists in png_combine_row() eliminated compiler barfage, so + * ifdef'd with __PIC__ macro: if defined, use a global for unmask + * + * 19991107: + * - verified CPUID clobberage: 12-char string constant ("GenuineIntel", + * "AuthenticAMD", etc.) placed in ebx:ecx:edx. Still need to polish. + * + * 19991120: + * - made "diff" variable (now "_dif") global to simplify conversion of + * filtering routines (running out of regs, sigh). "diff" is still used + * in interlacing routines, however. + * - fixed up both versions of mmxsupport() (ORIG_THAT_USED_TO_CLOBBER_EBX + * macro determines which is used); original not yet tested. + * + * 20000213: + * - when compiling with gcc, be sure to use -fomit-frame-pointer + * + * 20000319: + * - fixed a register-name typo in png_do_read_interlace(), default (MMX) case, + * pass == 4 or 5, that caused visible corruption of interlaced images + * + * 20000623: + * - Various problems were reported with gcc 2.95.2 in the Cygwin environment, + * many of the form "forbidden register 0 (ax) was spilled for class AREG." + * This is explained at http://gcc.gnu.org/fom_serv/cache/23.html, and + * Chuck Wilson supplied a patch involving dummy output registers. See + * http://sourceforge.net/bugs/?func=detailbug&bug_id=108741&group_id=5624 + * for the original (anonymous) SourceForge bug report. + * + * 20000706: + * - Chuck Wilson passed along these remaining gcc 2.95.2 errors: + * pnggccrd.c: In function `png_combine_row': + * pnggccrd.c:525: more than 10 operands in `asm' + * pnggccrd.c:669: more than 10 operands in `asm' + * pnggccrd.c:828: more than 10 operands in `asm' + * pnggccrd.c:994: more than 10 operands in `asm' + * pnggccrd.c:1177: more than 10 operands in `asm' + * They are all the same problem and can be worked around by using the + * global _unmask variable unconditionally, not just in the -fPIC case. + * Reportedly earlier versions of gcc also have the problem with more than + * 10 operands; they just don't report it. Much strangeness ensues, etc. + * + * 20000729: + * - enabled png_read_filter_row_mmx_up() (shortest remaining unconverted + * MMX routine); began converting png_read_filter_row_mmx_sub() + * - to finish remaining sections: + * - clean up indentation and comments + * - preload local variables + * - add output and input regs (order of former determines numerical + * mapping of latter) + * - avoid all usage of ebx (including bx, bh, bl) register [20000823] + * - remove "$" from addressing of Shift and Mask variables [20000823] + * + * 20000731: + * - global union vars causing segfaults in png_read_filter_row_mmx_sub()? + * + * 20000822: + * - ARGH, stupid png_read_filter_row_mmx_sub() segfault only happens with + * shared-library (-fPIC) version! Code works just fine as part of static + * library. Damn damn damn damn damn, should have tested that sooner. + * ebx is getting clobbered again (explicitly this time); need to save it + * on stack or rewrite asm code to avoid using it altogether. Blargh! + * + * 20000823: + * - first section was trickiest; all remaining sections have ebx -> edx now. + * (-fPIC works again.) Also added missing underscores to various Shift* + * and *Mask* globals and got rid of leading "$" signs. + * + * 20000826: + * - added visual separators to help navigate microscopic printed copies + * (http://pobox.com/~newt/code/gpr-latest.zip, mode 10); started working + * on png_read_filter_row_mmx_avg() + * + * 20000828: + * - finished png_read_filter_row_mmx_avg(): only Paeth left! (930 lines...) + * What the hell, did png_read_filter_row_mmx_paeth(), too. Comments not + * cleaned up/shortened in either routine, but functionality is complete + * and seems to be working fine. + * + * 20000829: + * - ahhh, figured out last(?) bit of gcc/gas asm-fu: if register is listed + * as an input reg (with dummy output variables, etc.), then it *cannot* + * also appear in the clobber list or gcc 2.95.2 will barf. The solution + * is simple enough... + * + * 20000914: + * - bug in png_read_filter_row_mmx_avg(): 16-bit grayscale not handled + * correctly (but 48-bit RGB just fine) + * + * 20000916: + * - fixed bug in png_read_filter_row_mmx_avg(), bpp == 2 case; three errors: + * - "_ShiftBpp.use = 24;" should have been "_ShiftBpp.use = 16;" + * - "_ShiftRem.use = 40;" should have been "_ShiftRem.use = 48;" + * - "psllq _ShiftRem, %%mm2" should have been "psrlq _ShiftRem, %%mm2" + * + * 20010103: + * - renamed mmxsupport() to png_mmx_support(), with auto-set of mmx_supported, + * and made it public + * + * 20010104: + * - removed dependency on png_read_filter_row_c() (C code already duplicated + * within MMX version of png_read_filter_row()) so no longer necessary to + * compile it into pngrutil.o + * + * 20010310: + * - fixed buffer-overrun bug in png_combine_row() C code (non-MMX) + * + * STILL TO DO: + * - test png_do_read_interlace() 64-bit case (pixel_bytes == 8) + * - write MMX code for 48-bit case (pixel_bytes == 6) + * - figure out what's up with 24-bit case (pixel_bytes == 3): + * why subtract 8 from width_mmx in the pass 4/5 case? + * (only width_mmx case) (near line 1606) + * - rewrite all MMX interlacing code so it's aligned with beginning + * of the row buffer, not the end (see 19991007 for details) + * x pick one version of mmxsupport() and get rid of the other + * - add error messages to any remaining bogus default cases + * - enable pixel_depth == 8 cases in png_read_filter_row()? (test speed) + * - add support for runtime enable/disable/query of various MMX routines + */ + +/* +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif +*/ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_USE_PNGGCCRD) + +int PNGAPI png_mmx_support(void); + +#ifdef PNG_USE_LOCAL_ARRAYS +static const int FARDATA png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; +static const int FARDATA png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +static const int FARDATA png_pass_width[7] = {8, 4, 4, 2, 2, 1, 1}; +#endif + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +/* djgpp, Win32, and Cygwin add their own underscores to global variables, + * so define them without: */ +#if defined(__DJGPP__) || defined(WIN32) || defined(__CYGWIN__) +# define _mmx_supported mmx_supported +# define _unmask unmask +# define _const4 const4 +# define _const6 const6 +# define _mask8_0 mask8_0 +# define _mask16_1 mask16_1 +# define _mask16_0 mask16_0 +# define _mask24_2 mask24_2 +# define _mask24_1 mask24_1 +# define _mask24_0 mask24_0 +# define _mask32_3 mask32_3 +# define _mask32_2 mask32_2 +# define _mask32_1 mask32_1 +# define _mask32_0 mask32_0 +# define _mask48_5 mask48_5 +# define _mask48_4 mask48_4 +# define _mask48_3 mask48_3 +# define _mask48_2 mask48_2 +# define _mask48_1 mask48_1 +# define _mask48_0 mask48_0 +# define _FullLength FullLength +# define _MMXLength MMXLength +# define _dif dif +# define _LBCarryMask LBCarryMask +# define _HBClearMask HBClearMask +# define _ActiveMask ActiveMask +# define _ActiveMask2 ActiveMask2 +# define _ActiveMaskEnd ActiveMaskEnd +# define _ShiftBpp ShiftBpp +# define _ShiftRem ShiftRem +# define _patemp patemp +# define _pbtemp pbtemp +# define _pctemp pctemp +#endif + + +/* These constants are used in the inlined MMX assembly code. + Ignore gcc's "At top level: defined but not used" warnings. */ + +/* GRR 20000706: originally _unmask was needed only when compiling with -fPIC, + * since that case uses the %ebx register for indexing the Global Offset Table + * and there were no other registers available. But gcc 2.95 and later emit + * "more than 10 operands in `asm'" errors when %ebx is used to preload unmask + * in the non-PIC case, so we'll just use the global unconditionally now. + */ +static int _unmask; + +static unsigned long long _mask8_0 = 0x0102040810204080LL; + +static unsigned long long _mask16_1 = 0x0101020204040808LL; +static unsigned long long _mask16_0 = 0x1010202040408080LL; + +static unsigned long long _mask24_2 = 0x0101010202020404LL; +static unsigned long long _mask24_1 = 0x0408080810101020LL; +static unsigned long long _mask24_0 = 0x2020404040808080LL; + +static unsigned long long _mask32_3 = 0x0101010102020202LL; +static unsigned long long _mask32_2 = 0x0404040408080808LL; +static unsigned long long _mask32_1 = 0x1010101020202020LL; +static unsigned long long _mask32_0 = 0x4040404080808080LL; + +static unsigned long long _mask48_5 = 0x0101010101010202LL; +static unsigned long long _mask48_4 = 0x0202020204040404LL; +static unsigned long long _mask48_3 = 0x0404080808080808LL; +static unsigned long long _mask48_2 = 0x1010101010102020LL; +static unsigned long long _mask48_1 = 0x2020202040404040LL; +static unsigned long long _mask48_0 = 0x4040808080808080LL; + +static unsigned long long _const4 = 0x0000000000FFFFFFLL; +//static unsigned long long _const5 = 0x000000FFFFFF0000LL; // NOT USED +static unsigned long long _const6 = 0x00000000000000FFLL; + +// These are used in the row-filter routines and should/would be local +// variables if not for gcc addressing limitations. + +static png_uint_32 _FullLength; +static png_uint_32 _MMXLength; +static int _dif; +static int _patemp; // temp variables for Paeth routine +static int _pbtemp; +static int _pctemp; + +static void /* PRIVATE */ +png_squelch_warnings(void) +{ + _dif = _dif; + _patemp = _patemp; + _pbtemp = _pbtemp; + _pctemp = _pctemp; + _const4 = _const4; + _const6 = _const6; + _MMXLength = _MMXLength; + _mask8_0 = _mask8_0; + _mask16_1 = _mask16_1; + _mask16_0 = _mask16_0; + _mask24_2 = _mask24_2; + _mask24_1 = _mask24_1; + _mask24_0 = _mask24_0; + _mask32_3 = _mask32_3; + _mask32_2 = _mask32_2; + _mask32_1 = _mask32_1; + _mask32_0 = _mask32_0; + _mask48_5 = _mask48_5; + _mask48_4 = _mask48_4; + _mask48_3 = _mask48_3; + _mask48_2 = _mask48_2; + _mask48_1 = _mask48_1; + _mask48_0 = _mask48_0; +} +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +static int _mmx_supported = 2; + +/*===========================================================================*/ +/* */ +/* P N G _ C O M B I N E _ R O W */ +/* */ +/*===========================================================================*/ + +#if defined(PNG_HAVE_ASSEMBLER_COMBINE_ROW) + +#define BPP2 2 +#define BPP3 3 /* bytes per pixel (a.k.a. pixel_bytes) */ +#define BPP4 4 +#define BPP6 6 /* (defined only to help avoid cut-and-paste errors) */ +#define BPP8 8 + +/* Combines the row recently read in with the previous row. + This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined; a + zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. + If you want all pixels to be combined, pass 0xff (255) in mask. */ + +/* Use this routine for the x86 platform - it uses a faster MMX routine + if the machine supports MMX. */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1, "in png_combine_row (pnggccrd.c)\n"); + + if (_mmx_supported == 2) { + png_mmx_support(); + } + + if (mask == 0xff) + { + png_debug(2,"mask == 0xff: doing single png_memcpy()\n"); + png_memcpy(row, png_ptr->row_buf + 1, + (png_size_t)((png_ptr->width * png_ptr->row_info.pixel_depth + 7) >> 3)); + } + else /* (png_combine_row() is never called with mask == 0) */ + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: /* png_ptr->row_info.pixel_depth */ + { + png_bytep sp; + png_bytep dp; + int s_inc, s_start, s_end; + int m; + int shift; + png_uint_32 i; + + sp = png_ptr->row_buf + 1; + dp = row; + m = 0x80; +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < png_ptr->width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x1; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + + case 2: /* png_ptr->row_info.pixel_depth */ + { + png_bytep sp; + png_bytep dp; + int s_start, s_end, s_inc; + int m; + int shift; + png_uint_32 i; + int value; + + sp = png_ptr->row_buf + 1; + dp = row; + m = 0x80; +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < png_ptr->width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x3; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + + case 4: /* png_ptr->row_info.pixel_depth */ + { + png_bytep sp; + png_bytep dp; + int s_start, s_end, s_inc; + int m; + int shift; + png_uint_32 i; + int value; + + sp = png_ptr->row_buf + 1; + dp = row; + m = 0x80; +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < png_ptr->width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + + case 8: /* png_ptr->row_info.pixel_depth */ + { + png_bytep srcptr; + png_bytep dstptr; + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported ) + { + png_uint_32 len; + int diff; + int dummy_value_a; // fix 'forbidden register spilled' error + int dummy_value_d; + int dummy_value_c; + int dummy_value_S; + int dummy_value_D; + _unmask = ~mask; // global variable for -fPIC version + srcptr = png_ptr->row_buf + 1; + dstptr = row; + len = png_ptr->width &~7; // reduce to multiple of 8 + diff = (int) (png_ptr->width & 7); // amount lost + + __asm__ __volatile__ ( + "movd _unmask, %%mm7 \n\t" // load bit pattern + "psubb %%mm6, %%mm6 \n\t" // zero mm6 + "punpcklbw %%mm7, %%mm7 \n\t" + "punpcklwd %%mm7, %%mm7 \n\t" + "punpckldq %%mm7, %%mm7 \n\t" // fill reg with 8 masks + + "movq _mask8_0, %%mm0 \n\t" + "pand %%mm7, %%mm0 \n\t" // nonzero if keep byte + "pcmpeqb %%mm6, %%mm0 \n\t" // zeros->1s, v versa + +// preload "movl len, %%ecx \n\t" // load length of line +// preload "movl srcptr, %%esi \n\t" // load source +// preload "movl dstptr, %%edi \n\t" // load dest + + "cmpl $0, %%ecx \n\t" // len == 0 ? + "je mainloop8end \n\t" + + "mainloop8: \n\t" + "movq (%%esi), %%mm4 \n\t" // *srcptr + "pand %%mm0, %%mm4 \n\t" + "movq %%mm0, %%mm6 \n\t" + "pandn (%%edi), %%mm6 \n\t" // *dstptr + "por %%mm6, %%mm4 \n\t" + "movq %%mm4, (%%edi) \n\t" + "addl $8, %%esi \n\t" // inc by 8 bytes processed + "addl $8, %%edi \n\t" + "subl $8, %%ecx \n\t" // dec by 8 pixels processed + "ja mainloop8 \n\t" + + "mainloop8end: \n\t" +// preload "movl diff, %%ecx \n\t" // (diff is in eax) + "movl %%eax, %%ecx \n\t" + "cmpl $0, %%ecx \n\t" + "jz end8 \n\t" +// preload "movl mask, %%edx \n\t" + "sall $24, %%edx \n\t" // make low byte, high byte + + "secondloop8: \n\t" + "sall %%edx \n\t" // move high bit to CF + "jnc skip8 \n\t" // if CF = 0 + "movb (%%esi), %%al \n\t" + "movb %%al, (%%edi) \n\t" + + "skip8: \n\t" + "incl %%esi \n\t" + "incl %%edi \n\t" + "decl %%ecx \n\t" + "jnz secondloop8 \n\t" + + "end8: \n\t" + "EMMS \n\t" // DONE + + : "=a" (dummy_value_a), // output regs (dummy) + "=d" (dummy_value_d), + "=c" (dummy_value_c), + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "3" (srcptr), // esi // input regs + "4" (dstptr), // edi + "0" (diff), // eax +// was (unmask) "b" RESERVED // ebx // Global Offset Table idx + "2" (len), // ecx + "1" (mask) // edx + +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm4", "%mm6", "%mm7" // clobber list +#endif + ); + } + else /* mmx _not supported - Use modified C routine */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + register png_uint_32 i; + png_uint_32 initial_val = png_pass_start[png_ptr->pass]; + /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */ + register int stride = png_pass_inc[png_ptr->pass]; + /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */ + register int rep_bytes = png_pass_width[png_ptr->pass]; + /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */ + png_uint_32 len = png_ptr->width &~7; /* reduce to mult. of 8 */ + int diff = (int) (png_ptr->width & 7); /* amount lost */ + register png_uint_32 final_val = len; /* GRR bugfix */ + + srcptr = png_ptr->row_buf + 1 + initial_val; + dstptr = row + initial_val; + + for (i = initial_val; i < final_val; i += stride) + { + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + if (diff) /* number of leftover pixels: 3 for pngtest */ + { + final_val+=diff /* *BPP1 */ ; + for (; i < final_val; i += stride) + { + if (rep_bytes > (int)(final_val-i)) + rep_bytes = (int)(final_val-i); + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + } + + } /* end of else (_mmx_supported) */ + + break; + } /* end 8 bpp */ + + case 16: /* png_ptr->row_info.pixel_depth */ + { + png_bytep srcptr; + png_bytep dstptr; + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported ) + { + png_uint_32 len; + int diff; + int dummy_value_a; // fix 'forbidden register spilled' error + int dummy_value_d; + int dummy_value_c; + int dummy_value_S; + int dummy_value_D; + _unmask = ~mask; // global variable for -fPIC version + srcptr = png_ptr->row_buf + 1; + dstptr = row; + len = png_ptr->width &~7; // reduce to multiple of 8 + diff = (int) (png_ptr->width & 7); // amount lost // + + __asm__ __volatile__ ( + "movd _unmask, %%mm7 \n\t" // load bit pattern + "psubb %%mm6, %%mm6 \n\t" // zero mm6 + "punpcklbw %%mm7, %%mm7 \n\t" + "punpcklwd %%mm7, %%mm7 \n\t" + "punpckldq %%mm7, %%mm7 \n\t" // fill reg with 8 masks + + "movq _mask16_0, %%mm0 \n\t" + "movq _mask16_1, %%mm1 \n\t" + + "pand %%mm7, %%mm0 \n\t" + "pand %%mm7, %%mm1 \n\t" + + "pcmpeqb %%mm6, %%mm0 \n\t" + "pcmpeqb %%mm6, %%mm1 \n\t" + +// preload "movl len, %%ecx \n\t" // load length of line +// preload "movl srcptr, %%esi \n\t" // load source +// preload "movl dstptr, %%edi \n\t" // load dest + + "cmpl $0, %%ecx \n\t" + "jz mainloop16end \n\t" + + "mainloop16: \n\t" + "movq (%%esi), %%mm4 \n\t" + "pand %%mm0, %%mm4 \n\t" + "movq %%mm0, %%mm6 \n\t" + "movq (%%edi), %%mm7 \n\t" + "pandn %%mm7, %%mm6 \n\t" + "por %%mm6, %%mm4 \n\t" + "movq %%mm4, (%%edi) \n\t" + + "movq 8(%%esi), %%mm5 \n\t" + "pand %%mm1, %%mm5 \n\t" + "movq %%mm1, %%mm7 \n\t" + "movq 8(%%edi), %%mm6 \n\t" + "pandn %%mm6, %%mm7 \n\t" + "por %%mm7, %%mm5 \n\t" + "movq %%mm5, 8(%%edi) \n\t" + + "addl $16, %%esi \n\t" // inc by 16 bytes processed + "addl $16, %%edi \n\t" + "subl $8, %%ecx \n\t" // dec by 8 pixels processed + "ja mainloop16 \n\t" + + "mainloop16end: \n\t" +// preload "movl diff, %%ecx \n\t" // (diff is in eax) + "movl %%eax, %%ecx \n\t" + "cmpl $0, %%ecx \n\t" + "jz end16 \n\t" +// preload "movl mask, %%edx \n\t" + "sall $24, %%edx \n\t" // make low byte, high byte + + "secondloop16: \n\t" + "sall %%edx \n\t" // move high bit to CF + "jnc skip16 \n\t" // if CF = 0 + "movw (%%esi), %%ax \n\t" + "movw %%ax, (%%edi) \n\t" + + "skip16: \n\t" + "addl $2, %%esi \n\t" + "addl $2, %%edi \n\t" + "decl %%ecx \n\t" + "jnz secondloop16 \n\t" + + "end16: \n\t" + "EMMS \n\t" // DONE + + : "=a" (dummy_value_a), // output regs (dummy) + "=c" (dummy_value_c), + "=d" (dummy_value_d), + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "0" (diff), // eax // input regs +// was (unmask) " " RESERVED // ebx // Global Offset Table idx + "1" (len), // ecx + "2" (mask), // edx + "3" (srcptr), // esi + "4" (dstptr) // edi + +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1", "%mm4" // clobber list + , "%mm5", "%mm6", "%mm7" +#endif + ); + } + else /* mmx _not supported - Use modified C routine */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + register png_uint_32 i; + png_uint_32 initial_val = BPP2 * png_pass_start[png_ptr->pass]; + /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */ + register int stride = BPP2 * png_pass_inc[png_ptr->pass]; + /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */ + register int rep_bytes = BPP2 * png_pass_width[png_ptr->pass]; + /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */ + png_uint_32 len = png_ptr->width &~7; /* reduce to mult. of 8 */ + int diff = (int) (png_ptr->width & 7); /* amount lost */ + register png_uint_32 final_val = BPP2 * len; /* GRR bugfix */ + + srcptr = png_ptr->row_buf + 1 + initial_val; + dstptr = row + initial_val; + + for (i = initial_val; i < final_val; i += stride) + { + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + if (diff) /* number of leftover pixels: 3 for pngtest */ + { + final_val+=diff*BPP2; + for (; i < final_val; i += stride) + { + if (rep_bytes > (int)(final_val-i)) + rep_bytes = (int)(final_val-i); + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + } + } /* end of else (_mmx_supported) */ + + break; + } /* end 16 bpp */ + + case 24: /* png_ptr->row_info.pixel_depth */ + { + png_bytep srcptr; + png_bytep dstptr; + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported ) + { + png_uint_32 len; + int diff; + int dummy_value_a; // fix 'forbidden register spilled' error + int dummy_value_d; + int dummy_value_c; + int dummy_value_S; + int dummy_value_D; + _unmask = ~mask; // global variable for -fPIC version + srcptr = png_ptr->row_buf + 1; + dstptr = row; + len = png_ptr->width &~7; // reduce to multiple of 8 + diff = (int) (png_ptr->width & 7); // amount lost // + + __asm__ __volatile__ ( + "movd _unmask, %%mm7 \n\t" // load bit pattern + "psubb %%mm6, %%mm6 \n\t" // zero mm6 + "punpcklbw %%mm7, %%mm7 \n\t" + "punpcklwd %%mm7, %%mm7 \n\t" + "punpckldq %%mm7, %%mm7 \n\t" // fill reg with 8 masks + + "movq _mask24_0, %%mm0 \n\t" + "movq _mask24_1, %%mm1 \n\t" + "movq _mask24_2, %%mm2 \n\t" + + "pand %%mm7, %%mm0 \n\t" + "pand %%mm7, %%mm1 \n\t" + "pand %%mm7, %%mm2 \n\t" + + "pcmpeqb %%mm6, %%mm0 \n\t" + "pcmpeqb %%mm6, %%mm1 \n\t" + "pcmpeqb %%mm6, %%mm2 \n\t" + +// preload "movl len, %%ecx \n\t" // load length of line +// preload "movl srcptr, %%esi \n\t" // load source +// preload "movl dstptr, %%edi \n\t" // load dest + + "cmpl $0, %%ecx \n\t" + "jz mainloop24end \n\t" + + "mainloop24: \n\t" + "movq (%%esi), %%mm4 \n\t" + "pand %%mm0, %%mm4 \n\t" + "movq %%mm0, %%mm6 \n\t" + "movq (%%edi), %%mm7 \n\t" + "pandn %%mm7, %%mm6 \n\t" + "por %%mm6, %%mm4 \n\t" + "movq %%mm4, (%%edi) \n\t" + + "movq 8(%%esi), %%mm5 \n\t" + "pand %%mm1, %%mm5 \n\t" + "movq %%mm1, %%mm7 \n\t" + "movq 8(%%edi), %%mm6 \n\t" + "pandn %%mm6, %%mm7 \n\t" + "por %%mm7, %%mm5 \n\t" + "movq %%mm5, 8(%%edi) \n\t" + + "movq 16(%%esi), %%mm6 \n\t" + "pand %%mm2, %%mm6 \n\t" + "movq %%mm2, %%mm4 \n\t" + "movq 16(%%edi), %%mm7 \n\t" + "pandn %%mm7, %%mm4 \n\t" + "por %%mm4, %%mm6 \n\t" + "movq %%mm6, 16(%%edi) \n\t" + + "addl $24, %%esi \n\t" // inc by 24 bytes processed + "addl $24, %%edi \n\t" + "subl $8, %%ecx \n\t" // dec by 8 pixels processed + + "ja mainloop24 \n\t" + + "mainloop24end: \n\t" +// preload "movl diff, %%ecx \n\t" // (diff is in eax) + "movl %%eax, %%ecx \n\t" + "cmpl $0, %%ecx \n\t" + "jz end24 \n\t" +// preload "movl mask, %%edx \n\t" + "sall $24, %%edx \n\t" // make low byte, high byte + + "secondloop24: \n\t" + "sall %%edx \n\t" // move high bit to CF + "jnc skip24 \n\t" // if CF = 0 + "movw (%%esi), %%ax \n\t" + "movw %%ax, (%%edi) \n\t" + "xorl %%eax, %%eax \n\t" + "movb 2(%%esi), %%al \n\t" + "movb %%al, 2(%%edi) \n\t" + + "skip24: \n\t" + "addl $3, %%esi \n\t" + "addl $3, %%edi \n\t" + "decl %%ecx \n\t" + "jnz secondloop24 \n\t" + + "end24: \n\t" + "EMMS \n\t" // DONE + + : "=a" (dummy_value_a), // output regs (dummy) + "=d" (dummy_value_d), + "=c" (dummy_value_c), + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "3" (srcptr), // esi // input regs + "4" (dstptr), // edi + "0" (diff), // eax +// was (unmask) "b" RESERVED // ebx // Global Offset Table idx + "2" (len), // ecx + "1" (mask) // edx + +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1", "%mm2" // clobber list + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + else /* mmx _not supported - Use modified C routine */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + register png_uint_32 i; + png_uint_32 initial_val = BPP3 * png_pass_start[png_ptr->pass]; + /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */ + register int stride = BPP3 * png_pass_inc[png_ptr->pass]; + /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */ + register int rep_bytes = BPP3 * png_pass_width[png_ptr->pass]; + /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */ + png_uint_32 len = png_ptr->width &~7; /* reduce to mult. of 8 */ + int diff = (int) (png_ptr->width & 7); /* amount lost */ + register png_uint_32 final_val = BPP3 * len; /* GRR bugfix */ + + srcptr = png_ptr->row_buf + 1 + initial_val; + dstptr = row + initial_val; + + for (i = initial_val; i < final_val; i += stride) + { + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + if (diff) /* number of leftover pixels: 3 for pngtest */ + { + final_val+=diff*BPP3; + for (; i < final_val; i += stride) + { + if (rep_bytes > (int)(final_val-i)) + rep_bytes = (int)(final_val-i); + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + } + } /* end of else (_mmx_supported) */ + + break; + } /* end 24 bpp */ + + case 32: /* png_ptr->row_info.pixel_depth */ + { + png_bytep srcptr; + png_bytep dstptr; + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported ) + { + png_uint_32 len; + int diff; + int dummy_value_a; // fix 'forbidden register spilled' error + int dummy_value_d; + int dummy_value_c; + int dummy_value_S; + int dummy_value_D; + _unmask = ~mask; // global variable for -fPIC version + srcptr = png_ptr->row_buf + 1; + dstptr = row; + len = png_ptr->width &~7; // reduce to multiple of 8 + diff = (int) (png_ptr->width & 7); // amount lost // + + __asm__ __volatile__ ( + "movd _unmask, %%mm7 \n\t" // load bit pattern + "psubb %%mm6, %%mm6 \n\t" // zero mm6 + "punpcklbw %%mm7, %%mm7 \n\t" + "punpcklwd %%mm7, %%mm7 \n\t" + "punpckldq %%mm7, %%mm7 \n\t" // fill reg with 8 masks + + "movq _mask32_0, %%mm0 \n\t" + "movq _mask32_1, %%mm1 \n\t" + "movq _mask32_2, %%mm2 \n\t" + "movq _mask32_3, %%mm3 \n\t" + + "pand %%mm7, %%mm0 \n\t" + "pand %%mm7, %%mm1 \n\t" + "pand %%mm7, %%mm2 \n\t" + "pand %%mm7, %%mm3 \n\t" + + "pcmpeqb %%mm6, %%mm0 \n\t" + "pcmpeqb %%mm6, %%mm1 \n\t" + "pcmpeqb %%mm6, %%mm2 \n\t" + "pcmpeqb %%mm6, %%mm3 \n\t" + +// preload "movl len, %%ecx \n\t" // load length of line +// preload "movl srcptr, %%esi \n\t" // load source +// preload "movl dstptr, %%edi \n\t" // load dest + + "cmpl $0, %%ecx \n\t" // lcr + "jz mainloop32end \n\t" + + "mainloop32: \n\t" + "movq (%%esi), %%mm4 \n\t" + "pand %%mm0, %%mm4 \n\t" + "movq %%mm0, %%mm6 \n\t" + "movq (%%edi), %%mm7 \n\t" + "pandn %%mm7, %%mm6 \n\t" + "por %%mm6, %%mm4 \n\t" + "movq %%mm4, (%%edi) \n\t" + + "movq 8(%%esi), %%mm5 \n\t" + "pand %%mm1, %%mm5 \n\t" + "movq %%mm1, %%mm7 \n\t" + "movq 8(%%edi), %%mm6 \n\t" + "pandn %%mm6, %%mm7 \n\t" + "por %%mm7, %%mm5 \n\t" + "movq %%mm5, 8(%%edi) \n\t" + + "movq 16(%%esi), %%mm6 \n\t" + "pand %%mm2, %%mm6 \n\t" + "movq %%mm2, %%mm4 \n\t" + "movq 16(%%edi), %%mm7 \n\t" + "pandn %%mm7, %%mm4 \n\t" + "por %%mm4, %%mm6 \n\t" + "movq %%mm6, 16(%%edi) \n\t" + + "movq 24(%%esi), %%mm7 \n\t" + "pand %%mm3, %%mm7 \n\t" + "movq %%mm3, %%mm5 \n\t" + "movq 24(%%edi), %%mm4 \n\t" + "pandn %%mm4, %%mm5 \n\t" + "por %%mm5, %%mm7 \n\t" + "movq %%mm7, 24(%%edi) \n\t" + + "addl $32, %%esi \n\t" // inc by 32 bytes processed + "addl $32, %%edi \n\t" + "subl $8, %%ecx \n\t" // dec by 8 pixels processed + "ja mainloop32 \n\t" + + "mainloop32end: \n\t" +// preload "movl diff, %%ecx \n\t" // (diff is in eax) + "movl %%eax, %%ecx \n\t" + "cmpl $0, %%ecx \n\t" + "jz end32 \n\t" +// preload "movl mask, %%edx \n\t" + "sall $24, %%edx \n\t" // low byte => high byte + + "secondloop32: \n\t" + "sall %%edx \n\t" // move high bit to CF + "jnc skip32 \n\t" // if CF = 0 + "movl (%%esi), %%eax \n\t" + "movl %%eax, (%%edi) \n\t" + + "skip32: \n\t" + "addl $4, %%esi \n\t" + "addl $4, %%edi \n\t" + "decl %%ecx \n\t" + "jnz secondloop32 \n\t" + + "end32: \n\t" + "EMMS \n\t" // DONE + + : "=a" (dummy_value_a), // output regs (dummy) + "=d" (dummy_value_d), + "=c" (dummy_value_c), + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "3" (srcptr), // esi // input regs + "4" (dstptr), // edi + "0" (diff), // eax +// was (unmask) "b" RESERVED // ebx // Global Offset Table idx + "2" (len), // ecx + "1" (mask) // edx + +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1", "%mm2", "%mm3" // clobber list + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + else /* mmx _not supported - Use modified C routine */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + register png_uint_32 i; + png_uint_32 initial_val = BPP4 * png_pass_start[png_ptr->pass]; + /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */ + register int stride = BPP4 * png_pass_inc[png_ptr->pass]; + /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */ + register int rep_bytes = BPP4 * png_pass_width[png_ptr->pass]; + /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */ + png_uint_32 len = png_ptr->width &~7; /* reduce to mult. of 8 */ + int diff = (int) (png_ptr->width & 7); /* amount lost */ + register png_uint_32 final_val = BPP4 * len; /* GRR bugfix */ + + srcptr = png_ptr->row_buf + 1 + initial_val; + dstptr = row + initial_val; + + for (i = initial_val; i < final_val; i += stride) + { + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + if (diff) /* number of leftover pixels: 3 for pngtest */ + { + final_val+=diff*BPP4; + for (; i < final_val; i += stride) + { + if (rep_bytes > (int)(final_val-i)) + rep_bytes = (int)(final_val-i); + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + } + } /* end of else (_mmx_supported) */ + + break; + } /* end 32 bpp */ + + case 48: /* png_ptr->row_info.pixel_depth */ + { + png_bytep srcptr; + png_bytep dstptr; + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported ) + { + png_uint_32 len; + int diff; + int dummy_value_a; // fix 'forbidden register spilled' error + int dummy_value_d; + int dummy_value_c; + int dummy_value_S; + int dummy_value_D; + _unmask = ~mask; // global variable for -fPIC version + srcptr = png_ptr->row_buf + 1; + dstptr = row; + len = png_ptr->width &~7; // reduce to multiple of 8 + diff = (int) (png_ptr->width & 7); // amount lost // + + __asm__ __volatile__ ( + "movd _unmask, %%mm7 \n\t" // load bit pattern + "psubb %%mm6, %%mm6 \n\t" // zero mm6 + "punpcklbw %%mm7, %%mm7 \n\t" + "punpcklwd %%mm7, %%mm7 \n\t" + "punpckldq %%mm7, %%mm7 \n\t" // fill reg with 8 masks + + "movq _mask48_0, %%mm0 \n\t" + "movq _mask48_1, %%mm1 \n\t" + "movq _mask48_2, %%mm2 \n\t" + "movq _mask48_3, %%mm3 \n\t" + "movq _mask48_4, %%mm4 \n\t" + "movq _mask48_5, %%mm5 \n\t" + + "pand %%mm7, %%mm0 \n\t" + "pand %%mm7, %%mm1 \n\t" + "pand %%mm7, %%mm2 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pand %%mm7, %%mm4 \n\t" + "pand %%mm7, %%mm5 \n\t" + + "pcmpeqb %%mm6, %%mm0 \n\t" + "pcmpeqb %%mm6, %%mm1 \n\t" + "pcmpeqb %%mm6, %%mm2 \n\t" + "pcmpeqb %%mm6, %%mm3 \n\t" + "pcmpeqb %%mm6, %%mm4 \n\t" + "pcmpeqb %%mm6, %%mm5 \n\t" + +// preload "movl len, %%ecx \n\t" // load length of line +// preload "movl srcptr, %%esi \n\t" // load source +// preload "movl dstptr, %%edi \n\t" // load dest + + "cmpl $0, %%ecx \n\t" + "jz mainloop48end \n\t" + + "mainloop48: \n\t" + "movq (%%esi), %%mm7 \n\t" + "pand %%mm0, %%mm7 \n\t" + "movq %%mm0, %%mm6 \n\t" + "pandn (%%edi), %%mm6 \n\t" + "por %%mm6, %%mm7 \n\t" + "movq %%mm7, (%%edi) \n\t" + + "movq 8(%%esi), %%mm6 \n\t" + "pand %%mm1, %%mm6 \n\t" + "movq %%mm1, %%mm7 \n\t" + "pandn 8(%%edi), %%mm7 \n\t" + "por %%mm7, %%mm6 \n\t" + "movq %%mm6, 8(%%edi) \n\t" + + "movq 16(%%esi), %%mm6 \n\t" + "pand %%mm2, %%mm6 \n\t" + "movq %%mm2, %%mm7 \n\t" + "pandn 16(%%edi), %%mm7 \n\t" + "por %%mm7, %%mm6 \n\t" + "movq %%mm6, 16(%%edi) \n\t" + + "movq 24(%%esi), %%mm7 \n\t" + "pand %%mm3, %%mm7 \n\t" + "movq %%mm3, %%mm6 \n\t" + "pandn 24(%%edi), %%mm6 \n\t" + "por %%mm6, %%mm7 \n\t" + "movq %%mm7, 24(%%edi) \n\t" + + "movq 32(%%esi), %%mm6 \n\t" + "pand %%mm4, %%mm6 \n\t" + "movq %%mm4, %%mm7 \n\t" + "pandn 32(%%edi), %%mm7 \n\t" + "por %%mm7, %%mm6 \n\t" + "movq %%mm6, 32(%%edi) \n\t" + + "movq 40(%%esi), %%mm7 \n\t" + "pand %%mm5, %%mm7 \n\t" + "movq %%mm5, %%mm6 \n\t" + "pandn 40(%%edi), %%mm6 \n\t" + "por %%mm6, %%mm7 \n\t" + "movq %%mm7, 40(%%edi) \n\t" + + "addl $48, %%esi \n\t" // inc by 48 bytes processed + "addl $48, %%edi \n\t" + "subl $8, %%ecx \n\t" // dec by 8 pixels processed + + "ja mainloop48 \n\t" + + "mainloop48end: \n\t" +// preload "movl diff, %%ecx \n\t" // (diff is in eax) + "movl %%eax, %%ecx \n\t" + "cmpl $0, %%ecx \n\t" + "jz end48 \n\t" +// preload "movl mask, %%edx \n\t" + "sall $24, %%edx \n\t" // make low byte, high byte + + "secondloop48: \n\t" + "sall %%edx \n\t" // move high bit to CF + "jnc skip48 \n\t" // if CF = 0 + "movl (%%esi), %%eax \n\t" + "movl %%eax, (%%edi) \n\t" + + "skip48: \n\t" + "addl $4, %%esi \n\t" + "addl $4, %%edi \n\t" + "decl %%ecx \n\t" + "jnz secondloop48 \n\t" + + "end48: \n\t" + "EMMS \n\t" // DONE + + : "=a" (dummy_value_a), // output regs (dummy) + "=d" (dummy_value_d), + "=c" (dummy_value_c), + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "3" (srcptr), // esi // input regs + "4" (dstptr), // edi + "0" (diff), // eax +// was (unmask) "b" RESERVED // ebx // Global Offset Table idx + "2" (len), // ecx + "1" (mask) // edx + +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1", "%mm2", "%mm3" // clobber list + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + else /* mmx _not supported - Use modified C routine */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + register png_uint_32 i; + png_uint_32 initial_val = BPP6 * png_pass_start[png_ptr->pass]; + /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */ + register int stride = BPP6 * png_pass_inc[png_ptr->pass]; + /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */ + register int rep_bytes = BPP6 * png_pass_width[png_ptr->pass]; + /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */ + png_uint_32 len = png_ptr->width &~7; /* reduce to mult. of 8 */ + int diff = (int) (png_ptr->width & 7); /* amount lost */ + register png_uint_32 final_val = BPP6 * len; /* GRR bugfix */ + + srcptr = png_ptr->row_buf + 1 + initial_val; + dstptr = row + initial_val; + + for (i = initial_val; i < final_val; i += stride) + { + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + if (diff) /* number of leftover pixels: 3 for pngtest */ + { + final_val+=diff*BPP6; + for (; i < final_val; i += stride) + { + if (rep_bytes > (int)(final_val-i)) + rep_bytes = (int)(final_val-i); + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + } + } /* end of else (_mmx_supported) */ + + break; + } /* end 48 bpp */ + + case 64: /* png_ptr->row_info.pixel_depth */ + { + png_bytep srcptr; + png_bytep dstptr; + register png_uint_32 i; + png_uint_32 initial_val = BPP8 * png_pass_start[png_ptr->pass]; + /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */ + register int stride = BPP8 * png_pass_inc[png_ptr->pass]; + /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */ + register int rep_bytes = BPP8 * png_pass_width[png_ptr->pass]; + /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */ + png_uint_32 len = png_ptr->width &~7; /* reduce to mult. of 8 */ + int diff = (int) (png_ptr->width & 7); /* amount lost */ + register png_uint_32 final_val = BPP8 * len; /* GRR bugfix */ + + srcptr = png_ptr->row_buf + 1 + initial_val; + dstptr = row + initial_val; + + for (i = initial_val; i < final_val; i += stride) + { + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + if (diff) /* number of leftover pixels: 3 for pngtest */ + { + final_val+=diff*BPP8; + for (; i < final_val; i += stride) + { + if (rep_bytes > (int)(final_val-i)) + rep_bytes = (int)(final_val-i); + png_memcpy(dstptr, srcptr, rep_bytes); + srcptr += stride; + dstptr += stride; + } + } + + break; + } /* end 64 bpp */ + + default: /* png_ptr->row_info.pixel_depth != 1,2,4,8,16,24,32,48,64 */ + { + /* this should never happen */ + fprintf(stderr, + "libpng internal error: png_ptr->row_info.pixel_depth = %d\n", + png_ptr->row_info.pixel_depth); + fflush(stderr); + break; + } + } /* end switch (png_ptr->row_info.pixel_depth) */ + + } /* end if (non-trivial mask) */ + +} /* end png_combine_row() */ + +#endif /* PNG_HAVE_ASSEMBLER_COMBINE_ROW */ + + + + +/*===========================================================================*/ +/* */ +/* P N G _ D O _ R E A D _ I N T E R L A C E */ +/* */ +/*===========================================================================*/ + +#if defined(PNG_READ_INTERLACING_SUPPORTED) +#if defined(PNG_HAVE_ASSEMBLER_READ_INTERLACE) + +/* png_do_read_interlace() is called after any 16-bit to 8-bit conversion + * has taken place. [GRR: what other steps come before and/or after?] + */ + +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + png_uint_32 transformations = png_ptr->transformations; +#endif + + png_debug(1, "in png_do_read_interlace (pnggccrd.c)\n"); + + if (_mmx_supported == 2) { + png_mmx_support(); + } + + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp, dp; + int sshift, dshift; + int s_start, s_end, s_inc; + png_byte v; + png_uint_32 i; + int j; + + sp = row + (png_size_t)((row_info->width - 1) >> 3); + dp = row + (png_size_t)((final_width - 1) >> 3); +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 7); + dshift = (int)((final_width + 7) & 7); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 7); + dshift = 7 - (int)((final_width + 7) & 7); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = row_info->width; i; i--) + { + v = (png_byte)((*sp >> sshift) & 0x1); + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + + case 2: + { + png_bytep sp, dp; + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + + sp = row + (png_size_t)((row_info->width - 1) >> 2); + dp = row + (png_size_t)((final_width - 1) >> 2); +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (png_size_t)(((row_info->width + 3) & 3) << 1); + dshift = (png_size_t)(((final_width + 3) & 3) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1); + dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = row_info->width; i; i--) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x3); + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + + case 4: + { + png_bytep sp, dp; + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + + sp = row + (png_size_t)((row_info->width - 1) >> 1); + dp = row + (png_size_t)((final_width - 1) >> 1); +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (png_size_t)(((row_info->width + 1) & 1) << 2); + dshift = (png_size_t)(((final_width + 1) & 1) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2); + dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = row_info->width; i; i--) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0xf); + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + + /*====================================================================*/ + + default: /* 8-bit or larger (this is where the routine is modified) */ + { +#if 0 +// static unsigned long long _const4 = 0x0000000000FFFFFFLL; no good +// static unsigned long long const4 = 0x0000000000FFFFFFLL; no good +// unsigned long long _const4 = 0x0000000000FFFFFFLL; no good +// unsigned long long const4 = 0x0000000000FFFFFFLL; no good +#endif + png_bytep sptr, dp; + png_uint_32 i; + png_size_t pixel_bytes; + int width = (int)row_info->width; + + pixel_bytes = (row_info->pixel_depth >> 3); + + /* point sptr at the last pixel in the pre-expanded row: */ + sptr = row + (width - 1) * pixel_bytes; + + /* point dp at the last pixel position in the expanded row: */ + dp = row + (final_width - 1) * pixel_bytes; + + /* New code by Nirav Chhatrapati - Intel Corporation */ + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported ) + { + //-------------------------------------------------------------- + if (pixel_bytes == 3) + { + if (((pass == 0) || (pass == 1)) && width) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $21, %%edi \n\t" + // (png_pass_inc[pass] - 1)*pixel_bytes + + ".loop3_pass0: \n\t" + "movd (%%esi), %%mm0 \n\t" // x x x x x 2 1 0 + "pand _const4, %%mm0 \n\t" // z z z z z 2 1 0 + "movq %%mm0, %%mm1 \n\t" // z z z z z 2 1 0 + "psllq $16, %%mm0 \n\t" // z z z 2 1 0 z z + "movq %%mm0, %%mm2 \n\t" // z z z 2 1 0 z z + "psllq $24, %%mm0 \n\t" // 2 1 0 z z z z z + "psrlq $8, %%mm1 \n\t" // z z z z z z 2 1 + "por %%mm2, %%mm0 \n\t" // 2 1 0 2 1 0 z z + "por %%mm1, %%mm0 \n\t" // 2 1 0 2 1 0 2 1 + "movq %%mm0, %%mm3 \n\t" // 2 1 0 2 1 0 2 1 + "psllq $16, %%mm0 \n\t" // 0 2 1 0 2 1 z z + "movq %%mm3, %%mm4 \n\t" // 2 1 0 2 1 0 2 1 + "punpckhdq %%mm0, %%mm3 \n\t" // 0 2 1 0 2 1 0 2 + "movq %%mm4, 16(%%edi) \n\t" + "psrlq $32, %%mm0 \n\t" // z z z z 0 2 1 0 + "movq %%mm3, 8(%%edi) \n\t" + "punpckldq %%mm4, %%mm0 \n\t" // 1 0 2 1 0 2 1 0 + "subl $3, %%esi \n\t" + "movq %%mm0, (%%edi) \n\t" + "subl $24, %%edi \n\t" + "decl %%ecx \n\t" + "jnz .loop3_pass0 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width) // ecx +// does not work "i" (0x0000000000FFFFFFLL) // %1 (a.k.a. _const4) + +#if 0 /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1", "%mm2" // clobber list + , "%mm3", "%mm4" +#endif + ); + } + else if (((pass == 2) || (pass == 3)) && width) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $9, %%edi \n\t" + // (png_pass_inc[pass] - 1)*pixel_bytes + + ".loop3_pass2: \n\t" + "movd (%%esi), %%mm0 \n\t" // x x x x x 2 1 0 + "pand _const4, %%mm0 \n\t" // z z z z z 2 1 0 + "movq %%mm0, %%mm1 \n\t" // z z z z z 2 1 0 + "psllq $16, %%mm0 \n\t" // z z z 2 1 0 z z + "movq %%mm0, %%mm2 \n\t" // z z z 2 1 0 z z + "psllq $24, %%mm0 \n\t" // 2 1 0 z z z z z + "psrlq $8, %%mm1 \n\t" // z z z z z z 2 1 + "por %%mm2, %%mm0 \n\t" // 2 1 0 2 1 0 z z + "por %%mm1, %%mm0 \n\t" // 2 1 0 2 1 0 2 1 + "movq %%mm0, 4(%%edi) \n\t" + "psrlq $16, %%mm0 \n\t" // z z 2 1 0 2 1 0 + "subl $3, %%esi \n\t" + "movd %%mm0, (%%edi) \n\t" + "subl $12, %%edi \n\t" + "decl %%ecx \n\t" + "jnz .loop3_pass2 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width) // ecx + +#if 0 /* %mm0, ..., %mm2 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1", "%mm2" // clobber list +#endif + ); + } + else if (width) /* && ((pass == 4) || (pass == 5)) */ + { + int width_mmx = ((width >> 1) << 1) - 8; // GRR: huh? + if (width_mmx < 0) + width_mmx = 0; + width -= width_mmx; // 8 or 9 pix, 24 or 27 bytes + if (width_mmx) + { + // png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + // sptr points at last pixel in pre-expanded row + // dp points at last pixel position in expanded row + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $3, %%esi \n\t" + "subl $9, %%edi \n\t" + // (png_pass_inc[pass] + 1)*pixel_bytes + + ".loop3_pass4: \n\t" + "movq (%%esi), %%mm0 \n\t" // x x 5 4 3 2 1 0 + "movq %%mm0, %%mm1 \n\t" // x x 5 4 3 2 1 0 + "movq %%mm0, %%mm2 \n\t" // x x 5 4 3 2 1 0 + "psllq $24, %%mm0 \n\t" // 4 3 2 1 0 z z z + "pand _const4, %%mm1 \n\t" // z z z z z 2 1 0 + "psrlq $24, %%mm2 \n\t" // z z z x x 5 4 3 + "por %%mm1, %%mm0 \n\t" // 4 3 2 1 0 2 1 0 + "movq %%mm2, %%mm3 \n\t" // z z z x x 5 4 3 + "psllq $8, %%mm2 \n\t" // z z x x 5 4 3 z + "movq %%mm0, (%%edi) \n\t" + "psrlq $16, %%mm3 \n\t" // z z z z z x x 5 + "pand _const6, %%mm3 \n\t" // z z z z z z z 5 + "por %%mm3, %%mm2 \n\t" // z z x x 5 4 3 5 + "subl $6, %%esi \n\t" + "movd %%mm2, 8(%%edi) \n\t" + "subl $12, %%edi \n\t" + "subl $2, %%ecx \n\t" + "jnz .loop3_pass4 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, ..., %mm3 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list + , "%mm2", "%mm3" +#endif + ); + } + + sptr -= width_mmx*3; + dp -= width_mmx*6; + for (i = width; i; i--) + { + png_byte v[8]; + int j; + + png_memcpy(v, sptr, 3); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 3); + dp -= 3; + } + sptr -= 3; + } + } + } /* end of pixel_bytes == 3 */ + + //-------------------------------------------------------------- + else if (pixel_bytes == 1) + { + if (((pass == 0) || (pass == 1)) && width) + { + int width_mmx = ((width >> 2) << 2); + width -= width_mmx; // 0-3 pixels => 0-3 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $3, %%esi \n\t" + "subl $31, %%edi \n\t" + + ".loop1_pass0: \n\t" + "movd (%%esi), %%mm0 \n\t" // x x x x 3 2 1 0 + "movq %%mm0, %%mm1 \n\t" // x x x x 3 2 1 0 + "punpcklbw %%mm0, %%mm0 \n\t" // 3 3 2 2 1 1 0 0 + "movq %%mm0, %%mm2 \n\t" // 3 3 2 2 1 1 0 0 + "punpcklwd %%mm0, %%mm0 \n\t" // 1 1 1 1 0 0 0 0 + "movq %%mm0, %%mm3 \n\t" // 1 1 1 1 0 0 0 0 + "punpckldq %%mm0, %%mm0 \n\t" // 0 0 0 0 0 0 0 0 + "punpckhdq %%mm3, %%mm3 \n\t" // 1 1 1 1 1 1 1 1 + "movq %%mm0, (%%edi) \n\t" + "punpckhwd %%mm2, %%mm2 \n\t" // 3 3 3 3 2 2 2 2 + "movq %%mm3, 8(%%edi) \n\t" + "movq %%mm2, %%mm4 \n\t" // 3 3 3 3 2 2 2 2 + "punpckldq %%mm2, %%mm2 \n\t" // 2 2 2 2 2 2 2 2 + "punpckhdq %%mm4, %%mm4 \n\t" // 3 3 3 3 3 3 3 3 + "movq %%mm2, 16(%%edi) \n\t" + "subl $4, %%esi \n\t" + "movq %%mm4, 24(%%edi) \n\t" + "subl $32, %%edi \n\t" + "subl $4, %%ecx \n\t" + "jnz .loop1_pass0 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, ..., %mm4 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1", "%mm2" // clobber list + , "%mm3", "%mm4" +#endif + ); + } + + sptr -= width_mmx; + dp -= width_mmx*8; + for (i = width; i; i--) + { + int j; + + /* I simplified this part in version 1.0.4e + * here and in several other instances where + * pixel_bytes == 1 -- GR-P + * + * Original code: + * + * png_byte v[8]; + * png_memcpy(v, sptr, pixel_bytes); + * for (j = 0; j < png_pass_inc[pass]; j++) + * { + * png_memcpy(dp, v, pixel_bytes); + * dp -= pixel_bytes; + * } + * sptr -= pixel_bytes; + * + * Replacement code is in the next three lines: + */ + + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp-- = *sptr; + } + --sptr; + } + } + else if (((pass == 2) || (pass == 3)) && width) + { + int width_mmx = ((width >> 2) << 2); + width -= width_mmx; // 0-3 pixels => 0-3 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $3, %%esi \n\t" + "subl $15, %%edi \n\t" + + ".loop1_pass2: \n\t" + "movd (%%esi), %%mm0 \n\t" // x x x x 3 2 1 0 + "punpcklbw %%mm0, %%mm0 \n\t" // 3 3 2 2 1 1 0 0 + "movq %%mm0, %%mm1 \n\t" // 3 3 2 2 1 1 0 0 + "punpcklwd %%mm0, %%mm0 \n\t" // 1 1 1 1 0 0 0 0 + "punpckhwd %%mm1, %%mm1 \n\t" // 3 3 3 3 2 2 2 2 + "movq %%mm0, (%%edi) \n\t" + "subl $4, %%esi \n\t" + "movq %%mm1, 8(%%edi) \n\t" + "subl $16, %%edi \n\t" + "subl $4, %%ecx \n\t" + "jnz .loop1_pass2 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list +#endif + ); + } + + sptr -= width_mmx; + dp -= width_mmx*4; + for (i = width; i; i--) + { + int j; + + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp-- = *sptr; + } + --sptr; + } + } + else if (width) /* && ((pass == 4) || (pass == 5)) */ + { + int width_mmx = ((width >> 3) << 3); + width -= width_mmx; // 0-3 pixels => 0-3 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $7, %%esi \n\t" + "subl $15, %%edi \n\t" + + ".loop1_pass4: \n\t" + "movq (%%esi), %%mm0 \n\t" // 7 6 5 4 3 2 1 0 + "movq %%mm0, %%mm1 \n\t" // 7 6 5 4 3 2 1 0 + "punpcklbw %%mm0, %%mm0 \n\t" // 3 3 2 2 1 1 0 0 + "punpckhbw %%mm1, %%mm1 \n\t" // 7 7 6 6 5 5 4 4 + "movq %%mm1, 8(%%edi) \n\t" + "subl $8, %%esi \n\t" + "movq %%mm0, (%%edi) \n\t" + "subl $16, %%edi \n\t" + "subl $8, %%ecx \n\t" + "jnz .loop1_pass4 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (none) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list +#endif + ); + } + + sptr -= width_mmx; + dp -= width_mmx*2; + for (i = width; i; i--) + { + int j; + + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp-- = *sptr; + } + --sptr; + } + } + } /* end of pixel_bytes == 1 */ + + //-------------------------------------------------------------- + else if (pixel_bytes == 2) + { + if (((pass == 0) || (pass == 1)) && width) + { + int width_mmx = ((width >> 1) << 1); + width -= width_mmx; // 0,1 pixels => 0,2 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $2, %%esi \n\t" + "subl $30, %%edi \n\t" + + ".loop2_pass0: \n\t" + "movd (%%esi), %%mm0 \n\t" // x x x x 3 2 1 0 + "punpcklwd %%mm0, %%mm0 \n\t" // 3 2 3 2 1 0 1 0 + "movq %%mm0, %%mm1 \n\t" // 3 2 3 2 1 0 1 0 + "punpckldq %%mm0, %%mm0 \n\t" // 1 0 1 0 1 0 1 0 + "punpckhdq %%mm1, %%mm1 \n\t" // 3 2 3 2 3 2 3 2 + "movq %%mm0, (%%edi) \n\t" + "movq %%mm0, 8(%%edi) \n\t" + "movq %%mm1, 16(%%edi) \n\t" + "subl $4, %%esi \n\t" + "movq %%mm1, 24(%%edi) \n\t" + "subl $32, %%edi \n\t" + "subl $2, %%ecx \n\t" + "jnz .loop2_pass0 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list +#endif + ); + } + + sptr -= (width_mmx*2 - 2); // sign fixed + dp -= (width_mmx*16 - 2); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 2; + png_memcpy(v, sptr, 2); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 2; + png_memcpy(dp, v, 2); + } + } + } + else if (((pass == 2) || (pass == 3)) && width) + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; // 0,1 pixels => 0,2 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $2, %%esi \n\t" + "subl $14, %%edi \n\t" + + ".loop2_pass2: \n\t" + "movd (%%esi), %%mm0 \n\t" // x x x x 3 2 1 0 + "punpcklwd %%mm0, %%mm0 \n\t" // 3 2 3 2 1 0 1 0 + "movq %%mm0, %%mm1 \n\t" // 3 2 3 2 1 0 1 0 + "punpckldq %%mm0, %%mm0 \n\t" // 1 0 1 0 1 0 1 0 + "punpckhdq %%mm1, %%mm1 \n\t" // 3 2 3 2 3 2 3 2 + "movq %%mm0, (%%edi) \n\t" + "subl $4, %%esi \n\t" + "movq %%mm1, 8(%%edi) \n\t" + "subl $16, %%edi \n\t" + "subl $2, %%ecx \n\t" + "jnz .loop2_pass2 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list +#endif + ); + } + + sptr -= (width_mmx*2 - 2); // sign fixed + dp -= (width_mmx*8 - 2); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 2; + png_memcpy(v, sptr, 2); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 2; + png_memcpy(dp, v, 2); + } + } + } + else if (width) // pass == 4 or 5 + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; // 0,1 pixels => 0,2 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $2, %%esi \n\t" + "subl $6, %%edi \n\t" + + ".loop2_pass4: \n\t" + "movd (%%esi), %%mm0 \n\t" // x x x x 3 2 1 0 + "punpcklwd %%mm0, %%mm0 \n\t" // 3 2 3 2 1 0 1 0 + "subl $4, %%esi \n\t" + "movq %%mm0, (%%edi) \n\t" + "subl $8, %%edi \n\t" + "subl $2, %%ecx \n\t" + "jnz .loop2_pass4 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0" // clobber list +#endif + ); + } + + sptr -= (width_mmx*2 - 2); // sign fixed + dp -= (width_mmx*4 - 2); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 2; + png_memcpy(v, sptr, 2); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 2; + png_memcpy(dp, v, 2); + } + } + } + } /* end of pixel_bytes == 2 */ + + //-------------------------------------------------------------- + else if (pixel_bytes == 4) + { + if (((pass == 0) || (pass == 1)) && width) + { + int width_mmx = ((width >> 1) << 1); + width -= width_mmx; // 0,1 pixels => 0,4 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $4, %%esi \n\t" + "subl $60, %%edi \n\t" + + ".loop4_pass0: \n\t" + "movq (%%esi), %%mm0 \n\t" // 7 6 5 4 3 2 1 0 + "movq %%mm0, %%mm1 \n\t" // 7 6 5 4 3 2 1 0 + "punpckldq %%mm0, %%mm0 \n\t" // 3 2 1 0 3 2 1 0 + "punpckhdq %%mm1, %%mm1 \n\t" // 7 6 5 4 7 6 5 4 + "movq %%mm0, (%%edi) \n\t" + "movq %%mm0, 8(%%edi) \n\t" + "movq %%mm0, 16(%%edi) \n\t" + "movq %%mm0, 24(%%edi) \n\t" + "movq %%mm1, 32(%%edi) \n\t" + "movq %%mm1, 40(%%edi) \n\t" + "movq %%mm1, 48(%%edi) \n\t" + "subl $8, %%esi \n\t" + "movq %%mm1, 56(%%edi) \n\t" + "subl $64, %%edi \n\t" + "subl $2, %%ecx \n\t" + "jnz .loop4_pass0 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list +#endif + ); + } + + sptr -= (width_mmx*4 - 4); // sign fixed + dp -= (width_mmx*32 - 4); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 4; + png_memcpy(v, sptr, 4); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 4; + png_memcpy(dp, v, 4); + } + } + } + else if (((pass == 2) || (pass == 3)) && width) + { + int width_mmx = ((width >> 1) << 1); + width -= width_mmx; // 0,1 pixels => 0,4 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $4, %%esi \n\t" + "subl $28, %%edi \n\t" + + ".loop4_pass2: \n\t" + "movq (%%esi), %%mm0 \n\t" // 7 6 5 4 3 2 1 0 + "movq %%mm0, %%mm1 \n\t" // 7 6 5 4 3 2 1 0 + "punpckldq %%mm0, %%mm0 \n\t" // 3 2 1 0 3 2 1 0 + "punpckhdq %%mm1, %%mm1 \n\t" // 7 6 5 4 7 6 5 4 + "movq %%mm0, (%%edi) \n\t" + "movq %%mm0, 8(%%edi) \n\t" + "movq %%mm1, 16(%%edi) \n\t" + "movq %%mm1, 24(%%edi) \n\t" + "subl $8, %%esi \n\t" + "subl $32, %%edi \n\t" + "subl $2, %%ecx \n\t" + "jnz .loop4_pass2 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list +#endif + ); + } + + sptr -= (width_mmx*4 - 4); // sign fixed + dp -= (width_mmx*16 - 4); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 4; + png_memcpy(v, sptr, 4); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 4; + png_memcpy(dp, v, 4); + } + } + } + else if (width) // pass == 4 or 5 + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; // 0,1 pixels => 0,4 bytes + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $4, %%esi \n\t" + "subl $12, %%edi \n\t" + + ".loop4_pass4: \n\t" + "movq (%%esi), %%mm0 \n\t" // 7 6 5 4 3 2 1 0 + "movq %%mm0, %%mm1 \n\t" // 7 6 5 4 3 2 1 0 + "punpckldq %%mm0, %%mm0 \n\t" // 3 2 1 0 3 2 1 0 + "punpckhdq %%mm1, %%mm1 \n\t" // 7 6 5 4 7 6 5 4 + "movq %%mm0, (%%edi) \n\t" + "subl $8, %%esi \n\t" + "movq %%mm1, 8(%%edi) \n\t" + "subl $16, %%edi \n\t" + "subl $2, %%ecx \n\t" + "jnz .loop4_pass4 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width_mmx) // ecx + +#if 0 /* %mm0, %mm1 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0", "%mm1" // clobber list +#endif + ); + } + + sptr -= (width_mmx*4 - 4); // sign fixed + dp -= (width_mmx*8 - 4); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 4; + png_memcpy(v, sptr, 4); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 4; + png_memcpy(dp, v, 4); + } + } + } + } /* end of pixel_bytes == 4 */ + + //-------------------------------------------------------------- + else if (pixel_bytes == 8) + { +// GRR TEST: should work, but needs testing (special 64-bit version of rpng2?) + // GRR NOTE: no need to combine passes here! + if (((pass == 0) || (pass == 1)) && width) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + // source is 8-byte RRGGBBAA + // dest is 64-byte RRGGBBAA RRGGBBAA RRGGBBAA RRGGBBAA ... + __asm__ __volatile__ ( + "subl $56, %%edi \n\t" // start of last block + + ".loop8_pass0: \n\t" + "movq (%%esi), %%mm0 \n\t" // 7 6 5 4 3 2 1 0 + "movq %%mm0, (%%edi) \n\t" + "movq %%mm0, 8(%%edi) \n\t" + "movq %%mm0, 16(%%edi) \n\t" + "movq %%mm0, 24(%%edi) \n\t" + "movq %%mm0, 32(%%edi) \n\t" + "movq %%mm0, 40(%%edi) \n\t" + "movq %%mm0, 48(%%edi) \n\t" + "subl $8, %%esi \n\t" + "movq %%mm0, 56(%%edi) \n\t" + "subl $64, %%edi \n\t" + "decl %%ecx \n\t" + "jnz .loop8_pass0 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width) // ecx + +#if 0 /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0" // clobber list +#endif + ); + } + else if (((pass == 2) || (pass == 3)) && width) + { + // source is 8-byte RRGGBBAA + // dest is 32-byte RRGGBBAA RRGGBBAA RRGGBBAA RRGGBBAA + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $24, %%edi \n\t" // start of last block + + ".loop8_pass2: \n\t" + "movq (%%esi), %%mm0 \n\t" // 7 6 5 4 3 2 1 0 + "movq %%mm0, (%%edi) \n\t" + "movq %%mm0, 8(%%edi) \n\t" + "movq %%mm0, 16(%%edi) \n\t" + "subl $8, %%esi \n\t" + "movq %%mm0, 24(%%edi) \n\t" + "subl $32, %%edi \n\t" + "decl %%ecx \n\t" + "jnz .loop8_pass2 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width) // ecx + +#if 0 /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0" // clobber list +#endif + ); + } + } + else if (width) // pass == 4 or 5 + { + // source is 8-byte RRGGBBAA + // dest is 16-byte RRGGBBAA RRGGBBAA + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; + if (width_mmx) + { + int dummy_value_c; // fix 'forbidden register spilled' + int dummy_value_S; + int dummy_value_D; + + __asm__ __volatile__ ( + "subl $8, %%edi \n\t" // start of last block + + ".loop8_pass4: \n\t" + "movq (%%esi), %%mm0 \n\t" // 7 6 5 4 3 2 1 0 + "movq %%mm0, (%%edi) \n\t" + "subl $8, %%esi \n\t" + "movq %%mm0, 8(%%edi) \n\t" + "subl $16, %%edi \n\t" + "decl %%ecx \n\t" + "jnz .loop8_pass4 \n\t" + "EMMS \n\t" // DONE + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "1" (sptr), // esi // input regs + "2" (dp), // edi + "0" (width) // ecx + +#if 0 /* %mm0 not supported by gcc 2.7.2.3 or egcs 1.1 */ + : "%mm0" // clobber list +#endif + ); + } + } + + } /* end of pixel_bytes == 8 */ + + //-------------------------------------------------------------- + else if (pixel_bytes == 6) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, 6); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 6); + dp -= 6; + } + sptr -= 6; + } + } /* end of pixel_bytes == 6 */ + + //-------------------------------------------------------------- + else + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr-= pixel_bytes; + } + } + } // end of _mmx_supported ======================================== + + else /* MMX not supported: use modified C code - takes advantage + * of inlining of png_memcpy for a constant */ + /* GRR 19991007: does it? or should pixel_bytes in each + * block be replaced with immediate value (e.g., 1)? */ + /* GRR 19991017: replaced with constants in each case */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + if (pixel_bytes == 1) + { + for (i = width; i; i--) + { + int j; + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp-- = *sptr; + } + --sptr; + } + } + else if (pixel_bytes == 3) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, 3); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 3); + dp -= 3; + } + sptr -= 3; + } + } + else if (pixel_bytes == 2) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, 2); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 2); + dp -= 2; + } + sptr -= 2; + } + } + else if (pixel_bytes == 4) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, 4); + for (j = 0; j < png_pass_inc[pass]; j++) + { +#ifdef PNG_DEBUG + if (dp < row || dp+3 > row+png_ptr->row_buf_size) + { + printf("dp out of bounds: row=%d, dp=%d, rp=%d\n",row, dp, + row+png_ptr->row_buf_size); + printf("row_buf=%d\n",png_ptr->row_buf_size); + } +#endif + png_memcpy(dp, v, 4); + dp -= 4; + } + sptr -= 4; + } + } + else if (pixel_bytes == 6) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, 6); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 6); + dp -= 6; + } + sptr -= 6; + } + } + else if (pixel_bytes == 8) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, 8); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 8); + dp -= 8; + } + sptr -= 8; + } + } + else /* GRR: should never be reached */ + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr -= pixel_bytes; + } + } + + } /* end if (MMX not supported) */ + break; + } + } /* end switch (row_info->pixel_depth) */ + + row_info->width = final_width; + row_info->rowbytes = ((final_width * + (png_uint_32)row_info->pixel_depth + 7) >> 3); + } + +} /* end png_do_read_interlace() */ + +#endif /* PNG_HAVE_ASSEMBLER_READ_INTERLACE */ +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + + + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + +// These variables are utilized in the functions below. They are declared +// globally here to ensure alignment on 8-byte boundaries. + +union uAll { + long long use; + double align; +} _LBCarryMask = {0x0101010101010101LL}, + _HBClearMask = {0x7f7f7f7f7f7f7f7fLL}, + _ActiveMask, _ActiveMask2, _ActiveMaskEnd, _ShiftBpp, _ShiftRem; + + + +//===========================================================================// +// // +// P N G _ R E A D _ F I L T E R _ R O W _ M M X _ A V G // +// // +//===========================================================================// + +// Optimized code for PNG Average filter decoder + +static void /* PRIVATE */ +png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row, + png_bytep prev_row) +{ + int bpp; + int dummy_value_c; // fix 'forbidden register 2 (cx) was spilled' error + int dummy_value_S; + int dummy_value_D; + + bpp = (row_info->pixel_depth + 7) >> 3; // get # bytes per pixel + _FullLength = row_info->rowbytes; // # of bytes to filter + + __asm__ __volatile__ ( + // initialize address pointers and offset +#ifdef __PIC__ + "pushl %%ebx \n\t" // save index to Global Offset Table +#endif +//pre "movl row, %%edi \n\t" // edi: Avg(x) + "xorl %%ebx, %%ebx \n\t" // ebx: x + "movl %%edi, %%edx \n\t" +//pre "movl prev_row, %%esi \n\t" // esi: Prior(x) +//pre "subl bpp, %%edx \n\t" // (bpp is preloaded into ecx) + "subl %%ecx, %%edx \n\t" // edx: Raw(x-bpp) + + "xorl %%eax,%%eax \n\t" + + // Compute the Raw value for the first bpp bytes + // Raw(x) = Avg(x) + (Prior(x)/2) + "avg_rlp: \n\t" + "movb (%%esi,%%ebx,),%%al \n\t" // load al with Prior(x) + "incl %%ebx \n\t" + "shrb %%al \n\t" // divide by 2 + "addb -1(%%edi,%%ebx,),%%al \n\t" // add Avg(x); -1 to offset inc ebx +//pre "cmpl bpp, %%ebx \n\t" // (bpp is preloaded into ecx) + "cmpl %%ecx, %%ebx \n\t" + "movb %%al,-1(%%edi,%%ebx,) \n\t" // write Raw(x); -1 to offset inc ebx + "jb avg_rlp \n\t" // mov does not affect flags + + // get # of bytes to alignment + "movl %%edi, _dif \n\t" // take start of row + "addl %%ebx, _dif \n\t" // add bpp + "addl $0xf, _dif \n\t" // add 7+8 to incr past alignment bdry + "andl $0xfffffff8, _dif \n\t" // mask to alignment boundary + "subl %%edi, _dif \n\t" // subtract from start => value ebx at + "jz avg_go \n\t" // alignment + + // fix alignment + // Compute the Raw value for the bytes up to the alignment boundary + // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) + "xorl %%ecx, %%ecx \n\t" + + "avg_lp1: \n\t" + "xorl %%eax, %%eax \n\t" + "movb (%%esi,%%ebx,), %%cl \n\t" // load cl with Prior(x) + "movb (%%edx,%%ebx,), %%al \n\t" // load al with Raw(x-bpp) + "addw %%cx, %%ax \n\t" + "incl %%ebx \n\t" + "shrw %%ax \n\t" // divide by 2 + "addb -1(%%edi,%%ebx,), %%al \n\t" // add Avg(x); -1 to offset inc ebx + "cmpl _dif, %%ebx \n\t" // check if at alignment boundary + "movb %%al, -1(%%edi,%%ebx,) \n\t" // write Raw(x); -1 to offset inc ebx + "jb avg_lp1 \n\t" // repeat until at alignment boundary + + "avg_go: \n\t" + "movl _FullLength, %%eax \n\t" + "movl %%eax, %%ecx \n\t" + "subl %%ebx, %%eax \n\t" // subtract alignment fix + "andl $0x00000007, %%eax \n\t" // calc bytes over mult of 8 + "subl %%eax, %%ecx \n\t" // drop over bytes from original length + "movl %%ecx, _MMXLength \n\t" +#ifdef __PIC__ + "popl %%ebx \n\t" // restore index to Global Offset Table +#endif + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "0" (bpp), // ecx // input regs + "1" (prev_row), // esi + "2" (row) // edi + + : "%eax", "%edx" // clobber list +#ifndef __PIC__ + , "%ebx" +#endif + // GRR: INCLUDE "memory" as clobbered? (_dif, _MMXLength) + // (seems to work fine without...) + ); + + // now do the math for the rest of the row + switch (bpp) + { + case 3: + { + _ActiveMask.use = 0x0000000000ffffffLL; + _ShiftBpp.use = 24; // == 3 * 8 + _ShiftRem.use = 40; // == 64 - 24 + + __asm__ __volatile__ ( + // re-init address pointers and offset + "movq _ActiveMask, %%mm7 \n\t" + "movl _dif, %%ecx \n\t" // ecx: x = offset to + "movq _LBCarryMask, %%mm5 \n\t" // alignment boundary +// preload "movl row, %%edi \n\t" // edi: Avg(x) + "movq _HBClearMask, %%mm4 \n\t" +// preload "movl prev_row, %%esi \n\t" // esi: Prior(x) + + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes + // (correct pos. in loop below) + "avg_3lp: \n\t" + "movq (%%edi,%%ecx,), %%mm0 \n\t" // load mm0 with Avg(x) + "movq %%mm5, %%mm3 \n\t" + "psrlq _ShiftRem, %%mm2 \n\t" // correct position Raw(x-bpp) data + "movq (%%esi,%%ecx,), %%mm1 \n\t" // load mm1 with Prior(x) + "movq %%mm7, %%mm6 \n\t" + "pand %%mm1, %%mm3 \n\t" // get lsb for each prev_row byte + "psrlq $1, %%mm1 \n\t" // divide prev_row bytes by 2 + "pand %%mm4, %%mm1 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm0 \n\t" // add (Prev_row/2) to Avg for each byte + // add 1st active group (Raw(x-bpp)/2) to average with LBCarry + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 1 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active + // byte + // add 2nd active group (Raw(x-bpp)/2) to average with _LBCarry + "psllq _ShiftBpp, %%mm6 \n\t" // shift the mm6 mask to cover bytes 3-5 + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "psllq _ShiftBpp, %%mm2 \n\t" // shift data to pos. correctly + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 2 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active + // byte + + // add 3rd active group (Raw(x-bpp)/2) to average with _LBCarry + "psllq _ShiftBpp, %%mm6 \n\t" // shift mm6 mask to cover last two + // bytes + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "psllq _ShiftBpp, %%mm2 \n\t" // shift data to pos. correctly + // Data only needs to be shifted once here to + // get the correct x-bpp offset. + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 2 bytes to add to Avg + "addl $8, %%ecx \n\t" + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active + // byte + // now ready to write back to memory + "movq %%mm0, -8(%%edi,%%ecx,) \n\t" + // move updated Raw(x) to use as Raw(x-bpp) for next loop + "cmpl _MMXLength, %%ecx \n\t" + "movq %%mm0, %%mm2 \n\t" // mov updated Raw(x) to mm2 + "jb avg_3lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; // end 3 bpp + + case 6: + case 4: + //case 7: // who wrote this? PNG does not support 5 or 7 bytes/pixel + //case 5: // GRR BOGUS + { + _ActiveMask.use = 0xffffffffffffffffLL; // use shift below to clear + // appropriate inactive bytes + _ShiftBpp.use = bpp << 3; + _ShiftRem.use = 64 - _ShiftBpp.use; + + __asm__ __volatile__ ( + "movq _HBClearMask, %%mm4 \n\t" + + // re-init address pointers and offset + "movl _dif, %%ecx \n\t" // ecx: x = offset to alignment boundary + + // load _ActiveMask and clear all bytes except for 1st active group + "movq _ActiveMask, %%mm7 \n\t" +// preload "movl row, %%edi \n\t" // edi: Avg(x) + "psrlq _ShiftRem, %%mm7 \n\t" +// preload "movl prev_row, %%esi \n\t" // esi: Prior(x) + "movq %%mm7, %%mm6 \n\t" + "movq _LBCarryMask, %%mm5 \n\t" + "psllq _ShiftBpp, %%mm6 \n\t" // create mask for 2nd active group + + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes + // (we correct pos. in loop below) + "avg_4lp: \n\t" + "movq (%%edi,%%ecx,), %%mm0 \n\t" + "psrlq _ShiftRem, %%mm2 \n\t" // shift data to pos. correctly + "movq (%%esi,%%ecx,), %%mm1 \n\t" + // add (Prev_row/2) to average + "movq %%mm5, %%mm3 \n\t" + "pand %%mm1, %%mm3 \n\t" // get lsb for each prev_row byte + "psrlq $1, %%mm1 \n\t" // divide prev_row bytes by 2 + "pand %%mm4, %%mm1 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm0 \n\t" // add (Prev_row/2) to Avg for each byte + // add 1st active group (Raw(x-bpp)/2) to average with _LBCarry + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm7, %%mm2 \n\t" // leave only Active Group 1 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active + // byte + // add 2nd active group (Raw(x-bpp)/2) to average with _LBCarry + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "psllq _ShiftBpp, %%mm2 \n\t" // shift data to pos. correctly + "addl $8, %%ecx \n\t" + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 2 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active + // byte + "cmpl _MMXLength, %%ecx \n\t" + // now ready to write back to memory + "movq %%mm0, -8(%%edi,%%ecx,) \n\t" + // prep Raw(x-bpp) for next loop + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "jb avg_4lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; // end 4,6 bpp + + case 2: + { + _ActiveMask.use = 0x000000000000ffffLL; + _ShiftBpp.use = 16; // == 2 * 8 + _ShiftRem.use = 48; // == 64 - 16 + + __asm__ __volatile__ ( + // load _ActiveMask + "movq _ActiveMask, %%mm7 \n\t" + // re-init address pointers and offset + "movl _dif, %%ecx \n\t" // ecx: x = offset to alignment boundary + "movq _LBCarryMask, %%mm5 \n\t" +// preload "movl row, %%edi \n\t" // edi: Avg(x) + "movq _HBClearMask, %%mm4 \n\t" +// preload "movl prev_row, %%esi \n\t" // esi: Prior(x) + + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes + // (we correct pos. in loop below) + "avg_2lp: \n\t" + "movq (%%edi,%%ecx,), %%mm0 \n\t" + "psrlq _ShiftRem, %%mm2 \n\t" // shift data to pos. correctly + "movq (%%esi,%%ecx,), %%mm1 \n\t" // (GRR BUGFIX: was psllq) + // add (Prev_row/2) to average + "movq %%mm5, %%mm3 \n\t" + "pand %%mm1, %%mm3 \n\t" // get lsb for each prev_row byte + "psrlq $1, %%mm1 \n\t" // divide prev_row bytes by 2 + "pand %%mm4, %%mm1 \n\t" // clear invalid bit 7 of each byte + "movq %%mm7, %%mm6 \n\t" + "paddb %%mm1, %%mm0 \n\t" // add (Prev_row/2) to Avg for each byte + + // add 1st active group (Raw(x-bpp)/2) to average with _LBCarry + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 1 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte + + // add 2nd active group (Raw(x-bpp)/2) to average with _LBCarry + "psllq _ShiftBpp, %%mm6 \n\t" // shift the mm6 mask to cover bytes 2 & 3 + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "psllq _ShiftBpp, %%mm2 \n\t" // shift data to pos. correctly + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 2 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte + + // add 3rd active group (Raw(x-bpp)/2) to average with _LBCarry + "psllq _ShiftBpp, %%mm6 \n\t" // shift the mm6 mask to cover bytes 4 & 5 + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "psllq _ShiftBpp, %%mm2 \n\t" // shift data to pos. correctly + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 2 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte + + // add 4th active group (Raw(x-bpp)/2) to average with _LBCarry + "psllq _ShiftBpp, %%mm6 \n\t" // shift the mm6 mask to cover bytes 6 & 7 + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "psllq _ShiftBpp, %%mm2 \n\t" // shift data to pos. correctly + "addl $8, %%ecx \n\t" + "movq %%mm3, %%mm1 \n\t" // now use mm1 for getting LBCarrys + "pand %%mm2, %%mm1 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 (only valid for active group) + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm2 \n\t" // add LBCarrys to (Raw(x-bpp)/2) for each byte + "pand %%mm6, %%mm2 \n\t" // leave only Active Group 2 bytes to add to Avg + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) + LBCarrys to Avg for each Active byte + + "cmpl _MMXLength, %%ecx \n\t" + // now ready to write back to memory + "movq %%mm0, -8(%%edi,%%ecx,) \n\t" + // prep Raw(x-bpp) for next loop + "movq %%mm0, %%mm2 \n\t" // mov updated Raws to mm2 + "jb avg_2lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; // end 2 bpp + + case 1: + { + __asm__ __volatile__ ( + // re-init address pointers and offset +#ifdef __PIC__ + "pushl %%ebx \n\t" // save Global Offset Table index +#endif + "movl _dif, %%ebx \n\t" // ebx: x = offset to alignment boundary +// preload "movl row, %%edi \n\t" // edi: Avg(x) + "cmpl _FullLength, %%ebx \n\t" // test if offset at end of array + "jnb avg_1end \n\t" + // do Paeth decode for remaining bytes +// preload "movl prev_row, %%esi \n\t" // esi: Prior(x) + "movl %%edi, %%edx \n\t" +// preload "subl bpp, %%edx \n\t" // (bpp is preloaded into ecx) + "subl %%ecx, %%edx \n\t" // edx: Raw(x-bpp) + "xorl %%ecx, %%ecx \n\t" // zero ecx before using cl & cx + // in loop below + "avg_1lp: \n\t" + // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) + "xorl %%eax, %%eax \n\t" + "movb (%%esi,%%ebx,), %%cl \n\t" // load cl with Prior(x) + "movb (%%edx,%%ebx,), %%al \n\t" // load al with Raw(x-bpp) + "addw %%cx, %%ax \n\t" + "incl %%ebx \n\t" + "shrw %%ax \n\t" // divide by 2 + "addb -1(%%edi,%%ebx,), %%al \n\t" // add Avg(x); -1 to offset inc ebx + "cmpl _FullLength, %%ebx \n\t" // check if at end of array + "movb %%al, -1(%%edi,%%ebx,) \n\t" // write back Raw(x); + // mov does not affect flags; -1 to offset inc ebx + "jb avg_1lp \n\t" + + "avg_1end: \n\t" +#ifdef __PIC__ + "popl %%ebx \n\t" // Global Offset Table index +#endif + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "0" (bpp), // ecx // input regs + "1" (prev_row), // esi + "2" (row) // edi + + : "%eax", "%edx" // clobber list +#ifndef __PIC__ + , "%ebx" +#endif + ); + } + return; // end 1 bpp + + case 8: + { + __asm__ __volatile__ ( + // re-init address pointers and offset + "movl _dif, %%ecx \n\t" // ecx: x == offset to alignment + "movq _LBCarryMask, %%mm5 \n\t" // boundary +// preload "movl row, %%edi \n\t" // edi: Avg(x) + "movq _HBClearMask, %%mm4 \n\t" +// preload "movl prev_row, %%esi \n\t" // esi: Prior(x) + + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm2 \n\t" // load previous aligned 8 bytes + // (NO NEED to correct pos. in loop below) + + "avg_8lp: \n\t" + "movq (%%edi,%%ecx,), %%mm0 \n\t" + "movq %%mm5, %%mm3 \n\t" + "movq (%%esi,%%ecx,), %%mm1 \n\t" + "addl $8, %%ecx \n\t" + "pand %%mm1, %%mm3 \n\t" // get lsb for each prev_row byte + "psrlq $1, %%mm1 \n\t" // divide prev_row bytes by 2 + "pand %%mm2, %%mm3 \n\t" // get LBCarrys for each byte + // where both lsbs were == 1 + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm1 \n\t" // clear invalid bit 7, each byte + "paddb %%mm3, %%mm0 \n\t" // add LBCarrys to Avg, each byte + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7, each byte + "paddb %%mm1, %%mm0 \n\t" // add (Prev_row/2) to Avg, each + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) to Avg for each + "cmpl _MMXLength, %%ecx \n\t" + "movq %%mm0, -8(%%edi,%%ecx,) \n\t" + "movq %%mm0, %%mm2 \n\t" // reuse as Raw(x-bpp) + "jb avg_8lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm5 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2" + , "%mm3", "%mm4", "%mm5" +#endif + ); + } + break; // end 8 bpp + + default: // bpp greater than 8 (!= 1,2,3,4,[5],6,[7],8) + { + + // GRR: PRINT ERROR HERE: SHOULD NEVER BE REACHED + fprintf(stderr, + "libpng: internal logic error (png_read_filter_row_mmx_avg())\n"); + +#if 0 + __asm__ __volatile__ ( + "movq _LBCarryMask, %%mm5 \n\t" + // re-init address pointers and offset + "movl _dif, %%ebx \n\t" // ebx: x = offset to alignment boundary + "movl row, %%edi \n\t" // edi: Avg(x) + "movq _HBClearMask, %%mm4 \n\t" + "movl %%edi, %%edx \n\t" + "movl prev_row, %%esi \n\t" // esi: Prior(x) + "subl bpp, %%edx \n\t" // edx: Raw(x-bpp) + "avg_Alp: \n\t" + "movq (%%edi,%%ebx,), %%mm0 \n\t" + "movq %%mm5, %%mm3 \n\t" + "movq (%%esi,%%ebx,), %%mm1 \n\t" + "pand %%mm1, %%mm3 \n\t" // get lsb for each prev_row byte + "movq (%%edx,%%ebx,), %%mm2 \n\t" + "psrlq $1, %%mm1 \n\t" // divide prev_row bytes by 2 + "pand %%mm2, %%mm3 \n\t" // get LBCarrys for each byte where both + // lsbs were == 1 + "psrlq $1, %%mm2 \n\t" // divide raw bytes by 2 + "pand %%mm4, %%mm1 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm3, %%mm0 \n\t" // add LBCarrys to Avg for each byte + "pand %%mm4, %%mm2 \n\t" // clear invalid bit 7 of each byte + "paddb %%mm1, %%mm0 \n\t" // add (Prev_row/2) to Avg for each byte + "addl $8, %%ebx \n\t" + "paddb %%mm2, %%mm0 \n\t" // add (Raw/2) to Avg for each byte + "cmpl _MMXLength, %%ebx \n\t" + "movq %%mm0, -8(%%edi,%%ebx,) \n\t" + "jb avg_Alp \n\t" + + : // FIXASM: output regs/vars go here, e.g.: "=m" (memory_var) + + : // FIXASM: input regs, e.g.: "c" (count), "S" (src), "D" (dest) + + : "%ebx", "%edx", "%edi", "%esi" // CHECKASM: clobber list + ); +#endif /* 0 - NEVER REACHED */ + } + break; + + } // end switch (bpp) + + __asm__ __volatile__ ( + // MMX acceleration complete; now do clean-up + // check if any remaining bytes left to decode +#ifdef __PIC__ + "pushl %%ebx \n\t" // save index to Global Offset Table +#endif + "movl _MMXLength, %%ebx \n\t" // ebx: x == offset bytes after MMX +//pre "movl row, %%edi \n\t" // edi: Avg(x) + "cmpl _FullLength, %%ebx \n\t" // test if offset at end of array + "jnb avg_end \n\t" + + // do Avg decode for remaining bytes +//pre "movl prev_row, %%esi \n\t" // esi: Prior(x) + "movl %%edi, %%edx \n\t" +//pre "subl bpp, %%edx \n\t" // (bpp is preloaded into ecx) + "subl %%ecx, %%edx \n\t" // edx: Raw(x-bpp) + "xorl %%ecx, %%ecx \n\t" // zero ecx before using cl & cx below + + "avg_lp2: \n\t" + // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) + "xorl %%eax, %%eax \n\t" + "movb (%%esi,%%ebx,), %%cl \n\t" // load cl with Prior(x) + "movb (%%edx,%%ebx,), %%al \n\t" // load al with Raw(x-bpp) + "addw %%cx, %%ax \n\t" + "incl %%ebx \n\t" + "shrw %%ax \n\t" // divide by 2 + "addb -1(%%edi,%%ebx,), %%al \n\t" // add Avg(x); -1 to offset inc ebx + "cmpl _FullLength, %%ebx \n\t" // check if at end of array + "movb %%al, -1(%%edi,%%ebx,) \n\t" // write back Raw(x) [mov does not + "jb avg_lp2 \n\t" // affect flags; -1 to offset inc ebx] + + "avg_end: \n\t" + "EMMS \n\t" // end MMX; prep for poss. FP instrs. +#ifdef __PIC__ + "popl %%ebx \n\t" // restore index to Global Offset Table +#endif + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "0" (bpp), // ecx // input regs + "1" (prev_row), // esi + "2" (row) // edi + + : "%eax", "%edx" // clobber list +#ifndef __PIC__ + , "%ebx" +#endif + ); + +} /* end png_read_filter_row_mmx_avg() */ + + + + +//===========================================================================// +// // +// P N G _ R E A D _ F I L T E R _ R O W _ M M X _ P A E T H // +// // +//===========================================================================// + +// Optimized code for PNG Paeth filter decoder + +static void /* PRIVATE */ +png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row, + png_bytep prev_row) +{ + int bpp; + int dummy_value_c; // fix 'forbidden register 2 (cx) was spilled' error + int dummy_value_S; + int dummy_value_D; + + bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel + _FullLength = row_info->rowbytes; // # of bytes to filter + + __asm__ __volatile__ ( +#ifdef __PIC__ + "pushl %%ebx \n\t" // save index to Global Offset Table +#endif + "xorl %%ebx, %%ebx \n\t" // ebx: x offset +//pre "movl row, %%edi \n\t" + "xorl %%edx, %%edx \n\t" // edx: x-bpp offset +//pre "movl prev_row, %%esi \n\t" + "xorl %%eax, %%eax \n\t" + + // Compute the Raw value for the first bpp bytes + // Note: the formula works out to be always + // Paeth(x) = Raw(x) + Prior(x) where x < bpp + "paeth_rlp: \n\t" + "movb (%%edi,%%ebx,), %%al \n\t" + "addb (%%esi,%%ebx,), %%al \n\t" + "incl %%ebx \n\t" +//pre "cmpl bpp, %%ebx \n\t" (bpp is preloaded into ecx) + "cmpl %%ecx, %%ebx \n\t" + "movb %%al, -1(%%edi,%%ebx,) \n\t" + "jb paeth_rlp \n\t" + // get # of bytes to alignment + "movl %%edi, _dif \n\t" // take start of row + "addl %%ebx, _dif \n\t" // add bpp + "xorl %%ecx, %%ecx \n\t" + "addl $0xf, _dif \n\t" // add 7 + 8 to incr past alignment boundary + "andl $0xfffffff8, _dif \n\t" // mask to alignment boundary + "subl %%edi, _dif \n\t" // subtract from start ==> value ebx at alignment + "jz paeth_go \n\t" + // fix alignment + + "paeth_lp1: \n\t" + "xorl %%eax, %%eax \n\t" + // pav = p - a = (a + b - c) - a = b - c + "movb (%%esi,%%ebx,), %%al \n\t" // load Prior(x) into al + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "subl %%ecx, %%eax \n\t" // subtract Prior(x-bpp) + "movl %%eax, _patemp \n\t" // Save pav for later use + "xorl %%eax, %%eax \n\t" + // pbv = p - b = (a + b - c) - b = a - c + "movb (%%edi,%%edx,), %%al \n\t" // load Raw(x-bpp) into al + "subl %%ecx, %%eax \n\t" // subtract Prior(x-bpp) + "movl %%eax, %%ecx \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "addl _patemp, %%eax \n\t" // pcv = pav + pbv + // pc = abs(pcv) + "testl $0x80000000, %%eax \n\t" + "jz paeth_pca \n\t" + "negl %%eax \n\t" // reverse sign of neg values + + "paeth_pca: \n\t" + "movl %%eax, _pctemp \n\t" // save pc for later use + // pb = abs(pbv) + "testl $0x80000000, %%ecx \n\t" + "jz paeth_pba \n\t" + "negl %%ecx \n\t" // reverse sign of neg values + + "paeth_pba: \n\t" + "movl %%ecx, _pbtemp \n\t" // save pb for later use + // pa = abs(pav) + "movl _patemp, %%eax \n\t" + "testl $0x80000000, %%eax \n\t" + "jz paeth_paa \n\t" + "negl %%eax \n\t" // reverse sign of neg values + + "paeth_paa: \n\t" + "movl %%eax, _patemp \n\t" // save pa for later use + // test if pa <= pb + "cmpl %%ecx, %%eax \n\t" + "jna paeth_abb \n\t" + // pa > pb; now test if pb <= pc + "cmpl _pctemp, %%ecx \n\t" + "jna paeth_bbc \n\t" + // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "jmp paeth_paeth \n\t" + + "paeth_bbc: \n\t" + // pb <= pc; Raw(x) = Paeth(x) + Prior(x) + "movb (%%esi,%%ebx,), %%cl \n\t" // load Prior(x) into cl + "jmp paeth_paeth \n\t" + + "paeth_abb: \n\t" + // pa <= pb; now test if pa <= pc + "cmpl _pctemp, %%eax \n\t" + "jna paeth_abc \n\t" + // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "jmp paeth_paeth \n\t" + + "paeth_abc: \n\t" + // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) + "movb (%%edi,%%edx,), %%cl \n\t" // load Raw(x-bpp) into cl + + "paeth_paeth: \n\t" + "incl %%ebx \n\t" + "incl %%edx \n\t" + // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 + "addb %%cl, -1(%%edi,%%ebx,) \n\t" + "cmpl _dif, %%ebx \n\t" + "jb paeth_lp1 \n\t" + + "paeth_go: \n\t" + "movl _FullLength, %%ecx \n\t" + "movl %%ecx, %%eax \n\t" + "subl %%ebx, %%eax \n\t" // subtract alignment fix + "andl $0x00000007, %%eax \n\t" // calc bytes over mult of 8 + "subl %%eax, %%ecx \n\t" // drop over bytes from original length + "movl %%ecx, _MMXLength \n\t" +#ifdef __PIC__ + "popl %%ebx \n\t" // restore index to Global Offset Table +#endif + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "0" (bpp), // ecx // input regs + "1" (prev_row), // esi + "2" (row) // edi + + : "%eax", "%edx" // clobber list +#ifndef __PIC__ + , "%ebx" +#endif + ); + + // now do the math for the rest of the row + switch (bpp) + { + case 3: + { + _ActiveMask.use = 0x0000000000ffffffLL; + _ActiveMaskEnd.use = 0xffff000000000000LL; + _ShiftBpp.use = 24; // == bpp(3) * 8 + _ShiftRem.use = 40; // == 64 - 24 + + __asm__ __volatile__ ( + "movl _dif, %%ecx \n\t" +// preload "movl row, %%edi \n\t" +// preload "movl prev_row, %%esi \n\t" + "pxor %%mm0, %%mm0 \n\t" + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm1 \n\t" + "paeth_3lp: \n\t" + "psrlq _ShiftRem, %%mm1 \n\t" // shift last 3 bytes to 1st 3 bytes + "movq (%%esi,%%ecx,), %%mm2 \n\t" // load b=Prior(x) + "punpcklbw %%mm0, %%mm1 \n\t" // unpack High bytes of a + "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // prep c=Prior(x-bpp) bytes + "punpcklbw %%mm0, %%mm2 \n\t" // unpack High bytes of b + "psrlq _ShiftRem, %%mm3 \n\t" // shift last 3 bytes to 1st 3 bytes + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + "punpcklbw %%mm0, %%mm3 \n\t" // unpack High bytes of c + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "paddw %%mm5, %%mm6 \n\t" + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "psubw %%mm0, %%mm4 \n\t" + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pxor %%mm1, %%mm1 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm7 \n\t" + "movq (%%esi,%%ecx,), %%mm3 \n\t" // load c=Prior(x-bpp) + "pand _ActiveMask, %%mm7 \n\t" + "movq %%mm3, %%mm2 \n\t" // load b=Prior(x) step 1 + "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x) + "punpcklbw %%mm0, %%mm3 \n\t" // unpack High bytes of c + "movq %%mm7, (%%edi,%%ecx,) \n\t" // write back updated value + "movq %%mm7, %%mm1 \n\t" // now mm1 will be used as Raw(x-bpp) + // now do Paeth for 2nd set of bytes (3-5) + "psrlq _ShiftBpp, %%mm2 \n\t" // load b=Prior(x) step 2 + "punpcklbw %%mm0, %%mm1 \n\t" // unpack High bytes of a + "pxor %%mm7, %%mm7 \n\t" + "punpcklbw %%mm0, %%mm2 \n\t" // unpack High bytes of b + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + "psubw %%mm3, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = + // pav + pbv = pbv + pav + "movq %%mm5, %%mm6 \n\t" + "paddw %%mm4, %%mm6 \n\t" + + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm5, %%mm0 \n\t" // create mask pbv bytes < 0 + "pcmpgtw %%mm4, %%mm7 \n\t" // create mask pav bytes < 0 + "pand %%mm5, %%mm0 \n\t" // only pbv bytes < 0 in mm0 + "pand %%mm4, %%mm7 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm0, %%mm5 \n\t" + "psubw %%mm7, %%mm4 \n\t" + "psubw %%mm0, %%mm5 \n\t" + "psubw %%mm7, %%mm4 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "movq (%%esi,%%ecx,), %%mm2 \n\t" // load b=Prior(x) + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm7 \n\t" + "movq %%mm2, %%mm3 \n\t" // load c=Prior(x-bpp) step 1 + "pand _ActiveMask, %%mm7 \n\t" + "punpckhbw %%mm0, %%mm2 \n\t" // unpack High bytes of b + "psllq _ShiftBpp, %%mm7 \n\t" // shift bytes to 2nd group of 3 bytes + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x) + "psllq _ShiftBpp, %%mm3 \n\t" // load c=Prior(x-bpp) step 2 + "movq %%mm7, (%%edi,%%ecx,) \n\t" // write back updated value + "movq %%mm7, %%mm1 \n\t" + "punpckhbw %%mm0, %%mm3 \n\t" // unpack High bytes of c + "psllq _ShiftBpp, %%mm1 \n\t" // shift bytes + // now mm1 will be used as Raw(x-bpp) + // now do Paeth for 3rd, and final, set of bytes (6-7) + "pxor %%mm7, %%mm7 \n\t" + "punpckhbw %%mm0, %%mm1 \n\t" // unpack High bytes of a + "psubw %%mm3, %%mm4 \n\t" + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "paddw %%mm5, %%mm6 \n\t" + + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "packuswb %%mm7, %%mm1 \n\t" + // step ecx to next set of 8 bytes and repeat loop til done + "addl $8, %%ecx \n\t" + "pand _ActiveMaskEnd, %%mm1 \n\t" + "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x) + + "cmpl _MMXLength, %%ecx \n\t" + "pxor %%mm0, %%mm0 \n\t" // pxor does not affect flags + "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + // mm3 ready to be used as Prior(x-bpp) next loop + "jb paeth_3lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; // end 3 bpp + + case 6: + //case 7: // GRR BOGUS + //case 5: // GRR BOGUS + { + _ActiveMask.use = 0x00000000ffffffffLL; + _ActiveMask2.use = 0xffffffff00000000LL; + _ShiftBpp.use = bpp << 3; // == bpp * 8 + _ShiftRem.use = 64 - _ShiftBpp.use; + + __asm__ __volatile__ ( + "movl _dif, %%ecx \n\t" +// preload "movl row, %%edi \n\t" +// preload "movl prev_row, %%esi \n\t" + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm1 \n\t" + "pxor %%mm0, %%mm0 \n\t" + + "paeth_6lp: \n\t" + // must shift to position Raw(x-bpp) data + "psrlq _ShiftRem, %%mm1 \n\t" + // do first set of 4 bytes + "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes + "punpcklbw %%mm0, %%mm1 \n\t" // unpack Low bytes of a + "movq (%%esi,%%ecx,), %%mm2 \n\t" // load b=Prior(x) + "punpcklbw %%mm0, %%mm2 \n\t" // unpack Low bytes of b + // must shift to position Prior(x-bpp) data + "psrlq _ShiftRem, %%mm3 \n\t" + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + "punpcklbw %%mm0, %%mm3 \n\t" // unpack Low bytes of c + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "paddw %%mm5, %%mm6 \n\t" + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "psubw %%mm0, %%mm4 \n\t" + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pxor %%mm1, %%mm1 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm7 \n\t" + "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // load c=Prior(x-bpp) + "pand _ActiveMask, %%mm7 \n\t" + "psrlq _ShiftRem, %%mm3 \n\t" + "movq (%%esi,%%ecx,), %%mm2 \n\t" // load b=Prior(x) step 1 + "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor and Raw(x) + "movq %%mm2, %%mm6 \n\t" + "movq %%mm7, (%%edi,%%ecx,) \n\t" // write back updated value + "movq -8(%%edi,%%ecx,), %%mm1 \n\t" + "psllq _ShiftBpp, %%mm6 \n\t" + "movq %%mm7, %%mm5 \n\t" + "psrlq _ShiftRem, %%mm1 \n\t" + "por %%mm6, %%mm3 \n\t" + "psllq _ShiftBpp, %%mm5 \n\t" + "punpckhbw %%mm0, %%mm3 \n\t" // unpack High bytes of c + "por %%mm5, %%mm1 \n\t" + // do second set of 4 bytes + "punpckhbw %%mm0, %%mm2 \n\t" // unpack High bytes of b + "punpckhbw %%mm0, %%mm1 \n\t" // unpack High bytes of a + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "paddw %%mm5, %%mm6 \n\t" + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "psubw %%mm0, %%mm4 \n\t" + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pxor %%mm1, %%mm1 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + // step ecx to next set of 8 bytes and repeat loop til done + "addl $8, %%ecx \n\t" + "packuswb %%mm7, %%mm1 \n\t" + "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x) + "cmpl _MMXLength, %%ecx \n\t" + "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + "jb paeth_6lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; // end 6 bpp + + case 4: + { + _ActiveMask.use = 0x00000000ffffffffLL; + + __asm__ __volatile__ ( + "movl _dif, %%ecx \n\t" +// preload "movl row, %%edi \n\t" +// preload "movl prev_row, %%esi \n\t" + "pxor %%mm0, %%mm0 \n\t" + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm1 \n\t" // only time should need to read + // a=Raw(x-bpp) bytes + "paeth_4lp: \n\t" + // do first set of 4 bytes + "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes + "punpckhbw %%mm0, %%mm1 \n\t" // unpack Low bytes of a + "movq (%%esi,%%ecx,), %%mm2 \n\t" // load b=Prior(x) + "punpcklbw %%mm0, %%mm2 \n\t" // unpack High bytes of b + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + "punpckhbw %%mm0, %%mm3 \n\t" // unpack High bytes of c + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "paddw %%mm5, %%mm6 \n\t" + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "psubw %%mm0, %%mm4 \n\t" + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pxor %%mm1, %%mm1 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm7 \n\t" + "movq (%%esi,%%ecx,), %%mm3 \n\t" // load c=Prior(x-bpp) + "pand _ActiveMask, %%mm7 \n\t" + "movq %%mm3, %%mm2 \n\t" // load b=Prior(x) step 1 + "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x) + "punpcklbw %%mm0, %%mm3 \n\t" // unpack High bytes of c + "movq %%mm7, (%%edi,%%ecx,) \n\t" // write back updated value + "movq %%mm7, %%mm1 \n\t" // now mm1 will be used as Raw(x-bpp) + // do second set of 4 bytes + "punpckhbw %%mm0, %%mm2 \n\t" // unpack Low bytes of b + "punpcklbw %%mm0, %%mm1 \n\t" // unpack Low bytes of a + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "paddw %%mm5, %%mm6 \n\t" + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "psubw %%mm0, %%mm4 \n\t" + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pxor %%mm1, %%mm1 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + // step ecx to next set of 8 bytes and repeat loop til done + "addl $8, %%ecx \n\t" + "packuswb %%mm7, %%mm1 \n\t" + "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add predictor with Raw(x) + "cmpl _MMXLength, %%ecx \n\t" + "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + "jb paeth_4lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; // end 4 bpp + + case 8: // bpp == 8 + { + _ActiveMask.use = 0x00000000ffffffffLL; + + __asm__ __volatile__ ( + "movl _dif, %%ecx \n\t" +// preload "movl row, %%edi \n\t" +// preload "movl prev_row, %%esi \n\t" + "pxor %%mm0, %%mm0 \n\t" + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%ecx,), %%mm1 \n\t" // only time should need to read + // a=Raw(x-bpp) bytes + "paeth_8lp: \n\t" + // do first set of 4 bytes + "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes + "punpcklbw %%mm0, %%mm1 \n\t" // unpack Low bytes of a + "movq (%%esi,%%ecx,), %%mm2 \n\t" // load b=Prior(x) + "punpcklbw %%mm0, %%mm2 \n\t" // unpack Low bytes of b + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + "punpcklbw %%mm0, %%mm3 \n\t" // unpack Low bytes of c + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "paddw %%mm5, %%mm6 \n\t" + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "psubw %%mm0, %%mm4 \n\t" + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pxor %%mm1, %%mm1 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "packuswb %%mm1, %%mm7 \n\t" + "movq -8(%%esi,%%ecx,), %%mm3 \n\t" // read c=Prior(x-bpp) bytes + "pand _ActiveMask, %%mm7 \n\t" + "movq (%%esi,%%ecx,), %%mm2 \n\t" // load b=Prior(x) + "paddb (%%edi,%%ecx,), %%mm7 \n\t" // add Paeth predictor with Raw(x) + "punpckhbw %%mm0, %%mm3 \n\t" // unpack High bytes of c + "movq %%mm7, (%%edi,%%ecx,) \n\t" // write back updated value + "movq -8(%%edi,%%ecx,), %%mm1 \n\t" // read a=Raw(x-bpp) bytes + + // do second set of 4 bytes + "punpckhbw %%mm0, %%mm2 \n\t" // unpack High bytes of b + "punpckhbw %%mm0, %%mm1 \n\t" // unpack High bytes of a + // pav = p - a = (a + b - c) - a = b - c + "movq %%mm2, %%mm4 \n\t" + // pbv = p - b = (a + b - c) - b = a - c + "movq %%mm1, %%mm5 \n\t" + "psubw %%mm3, %%mm4 \n\t" + "pxor %%mm7, %%mm7 \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "movq %%mm4, %%mm6 \n\t" + "psubw %%mm3, %%mm5 \n\t" + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + "pcmpgtw %%mm4, %%mm0 \n\t" // create mask pav bytes < 0 + "paddw %%mm5, %%mm6 \n\t" + "pand %%mm4, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "pcmpgtw %%mm5, %%mm7 \n\t" // create mask pbv bytes < 0 + "psubw %%mm0, %%mm4 \n\t" + "pand %%mm5, %%mm7 \n\t" // only pbv bytes < 0 in mm0 + "psubw %%mm0, %%mm4 \n\t" + "psubw %%mm7, %%mm5 \n\t" + "pxor %%mm0, %%mm0 \n\t" + "pcmpgtw %%mm6, %%mm0 \n\t" // create mask pcv bytes < 0 + "pand %%mm6, %%mm0 \n\t" // only pav bytes < 0 in mm7 + "psubw %%mm7, %%mm5 \n\t" + "psubw %%mm0, %%mm6 \n\t" + // test pa <= pb + "movq %%mm4, %%mm7 \n\t" + "psubw %%mm0, %%mm6 \n\t" + "pcmpgtw %%mm5, %%mm7 \n\t" // pa > pb? + "movq %%mm7, %%mm0 \n\t" + // use mm7 mask to merge pa & pb + "pand %%mm7, %%mm5 \n\t" + // use mm0 mask copy to merge a & b + "pand %%mm0, %%mm2 \n\t" + "pandn %%mm4, %%mm7 \n\t" + "pandn %%mm1, %%mm0 \n\t" + "paddw %%mm5, %%mm7 \n\t" + "paddw %%mm2, %%mm0 \n\t" + // test ((pa <= pb)? pa:pb) <= pc + "pcmpgtw %%mm6, %%mm7 \n\t" // pab > pc? + "pxor %%mm1, %%mm1 \n\t" + "pand %%mm7, %%mm3 \n\t" + "pandn %%mm0, %%mm7 \n\t" + "pxor %%mm1, %%mm1 \n\t" + "paddw %%mm3, %%mm7 \n\t" + "pxor %%mm0, %%mm0 \n\t" + // step ecx to next set of 8 bytes and repeat loop til done + "addl $8, %%ecx \n\t" + "packuswb %%mm7, %%mm1 \n\t" + "paddb -8(%%edi,%%ecx,), %%mm1 \n\t" // add Paeth predictor with Raw(x) + "cmpl _MMXLength, %%ecx \n\t" + "movq %%mm1, -8(%%edi,%%ecx,) \n\t" // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + "jb paeth_8lp \n\t" + + : "=S" (dummy_value_S), // output regs (dummy) + "=D" (dummy_value_D) + + : "0" (prev_row), // esi // input regs + "1" (row) // edi + + : "%ecx" // clobber list +#if 0 /* %mm0, ..., %mm7 not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; // end 8 bpp + + case 1: // bpp = 1 + case 2: // bpp = 2 + default: // bpp > 8 + { + __asm__ __volatile__ ( +#ifdef __PIC__ + "pushl %%ebx \n\t" // save Global Offset Table index +#endif + "movl _dif, %%ebx \n\t" + "cmpl _FullLength, %%ebx \n\t" + "jnb paeth_dend \n\t" + +// preload "movl row, %%edi \n\t" +// preload "movl prev_row, %%esi \n\t" + // do Paeth decode for remaining bytes + "movl %%ebx, %%edx \n\t" +// preload "subl bpp, %%edx \n\t" // (bpp is preloaded into ecx) + "subl %%ecx, %%edx \n\t" // edx = ebx - bpp + "xorl %%ecx, %%ecx \n\t" // zero ecx before using cl & cx + + "paeth_dlp: \n\t" + "xorl %%eax, %%eax \n\t" + // pav = p - a = (a + b - c) - a = b - c + "movb (%%esi,%%ebx,), %%al \n\t" // load Prior(x) into al + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "subl %%ecx, %%eax \n\t" // subtract Prior(x-bpp) + "movl %%eax, _patemp \n\t" // Save pav for later use + "xorl %%eax, %%eax \n\t" + // pbv = p - b = (a + b - c) - b = a - c + "movb (%%edi,%%edx,), %%al \n\t" // load Raw(x-bpp) into al + "subl %%ecx, %%eax \n\t" // subtract Prior(x-bpp) + "movl %%eax, %%ecx \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "addl _patemp, %%eax \n\t" // pcv = pav + pbv + // pc = abs(pcv) + "testl $0x80000000, %%eax \n\t" + "jz paeth_dpca \n\t" + "negl %%eax \n\t" // reverse sign of neg values + + "paeth_dpca: \n\t" + "movl %%eax, _pctemp \n\t" // save pc for later use + // pb = abs(pbv) + "testl $0x80000000, %%ecx \n\t" + "jz paeth_dpba \n\t" + "negl %%ecx \n\t" // reverse sign of neg values + + "paeth_dpba: \n\t" + "movl %%ecx, _pbtemp \n\t" // save pb for later use + // pa = abs(pav) + "movl _patemp, %%eax \n\t" + "testl $0x80000000, %%eax \n\t" + "jz paeth_dpaa \n\t" + "negl %%eax \n\t" // reverse sign of neg values + + "paeth_dpaa: \n\t" + "movl %%eax, _patemp \n\t" // save pa for later use + // test if pa <= pb + "cmpl %%ecx, %%eax \n\t" + "jna paeth_dabb \n\t" + // pa > pb; now test if pb <= pc + "cmpl _pctemp, %%ecx \n\t" + "jna paeth_dbbc \n\t" + // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "jmp paeth_dpaeth \n\t" + + "paeth_dbbc: \n\t" + // pb <= pc; Raw(x) = Paeth(x) + Prior(x) + "movb (%%esi,%%ebx,), %%cl \n\t" // load Prior(x) into cl + "jmp paeth_dpaeth \n\t" + + "paeth_dabb: \n\t" + // pa <= pb; now test if pa <= pc + "cmpl _pctemp, %%eax \n\t" + "jna paeth_dabc \n\t" + // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "jmp paeth_dpaeth \n\t" + + "paeth_dabc: \n\t" + // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) + "movb (%%edi,%%edx,), %%cl \n\t" // load Raw(x-bpp) into cl + + "paeth_dpaeth: \n\t" + "incl %%ebx \n\t" + "incl %%edx \n\t" + // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 + "addb %%cl, -1(%%edi,%%ebx,) \n\t" + "cmpl _FullLength, %%ebx \n\t" + "jb paeth_dlp \n\t" + + "paeth_dend: \n\t" +#ifdef __PIC__ + "popl %%ebx \n\t" // index to Global Offset Table +#endif + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "0" (bpp), // ecx // input regs + "1" (prev_row), // esi + "2" (row) // edi + + : "%eax", "%edx" // clobber list +#ifndef __PIC__ + , "%ebx" +#endif + ); + } + return; // No need to go further with this one + + } // end switch (bpp) + + __asm__ __volatile__ ( + // MMX acceleration complete; now do clean-up + // check if any remaining bytes left to decode +#ifdef __PIC__ + "pushl %%ebx \n\t" // save index to Global Offset Table +#endif + "movl _MMXLength, %%ebx \n\t" + "cmpl _FullLength, %%ebx \n\t" + "jnb paeth_end \n\t" +//pre "movl row, %%edi \n\t" +//pre "movl prev_row, %%esi \n\t" + // do Paeth decode for remaining bytes + "movl %%ebx, %%edx \n\t" +//pre "subl bpp, %%edx \n\t" // (bpp is preloaded into ecx) + "subl %%ecx, %%edx \n\t" // edx = ebx - bpp + "xorl %%ecx, %%ecx \n\t" // zero ecx before using cl & cx below + + "paeth_lp2: \n\t" + "xorl %%eax, %%eax \n\t" + // pav = p - a = (a + b - c) - a = b - c + "movb (%%esi,%%ebx,), %%al \n\t" // load Prior(x) into al + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "subl %%ecx, %%eax \n\t" // subtract Prior(x-bpp) + "movl %%eax, _patemp \n\t" // Save pav for later use + "xorl %%eax, %%eax \n\t" + // pbv = p - b = (a + b - c) - b = a - c + "movb (%%edi,%%edx,), %%al \n\t" // load Raw(x-bpp) into al + "subl %%ecx, %%eax \n\t" // subtract Prior(x-bpp) + "movl %%eax, %%ecx \n\t" + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + "addl _patemp, %%eax \n\t" // pcv = pav + pbv + // pc = abs(pcv) + "testl $0x80000000, %%eax \n\t" + "jz paeth_pca2 \n\t" + "negl %%eax \n\t" // reverse sign of neg values + + "paeth_pca2: \n\t" + "movl %%eax, _pctemp \n\t" // save pc for later use + // pb = abs(pbv) + "testl $0x80000000, %%ecx \n\t" + "jz paeth_pba2 \n\t" + "negl %%ecx \n\t" // reverse sign of neg values + + "paeth_pba2: \n\t" + "movl %%ecx, _pbtemp \n\t" // save pb for later use + // pa = abs(pav) + "movl _patemp, %%eax \n\t" + "testl $0x80000000, %%eax \n\t" + "jz paeth_paa2 \n\t" + "negl %%eax \n\t" // reverse sign of neg values + + "paeth_paa2: \n\t" + "movl %%eax, _patemp \n\t" // save pa for later use + // test if pa <= pb + "cmpl %%ecx, %%eax \n\t" + "jna paeth_abb2 \n\t" + // pa > pb; now test if pb <= pc + "cmpl _pctemp, %%ecx \n\t" + "jna paeth_bbc2 \n\t" + // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "jmp paeth_paeth2 \n\t" + + "paeth_bbc2: \n\t" + // pb <= pc; Raw(x) = Paeth(x) + Prior(x) + "movb (%%esi,%%ebx,), %%cl \n\t" // load Prior(x) into cl + "jmp paeth_paeth2 \n\t" + + "paeth_abb2: \n\t" + // pa <= pb; now test if pa <= pc + "cmpl _pctemp, %%eax \n\t" + "jna paeth_abc2 \n\t" + // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + "movb (%%esi,%%edx,), %%cl \n\t" // load Prior(x-bpp) into cl + "jmp paeth_paeth2 \n\t" + + "paeth_abc2: \n\t" + // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) + "movb (%%edi,%%edx,), %%cl \n\t" // load Raw(x-bpp) into cl + + "paeth_paeth2: \n\t" + "incl %%ebx \n\t" + "incl %%edx \n\t" + // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 + "addb %%cl, -1(%%edi,%%ebx,) \n\t" + "cmpl _FullLength, %%ebx \n\t" + "jb paeth_lp2 \n\t" + + "paeth_end: \n\t" + "EMMS \n\t" // end MMX; prep for poss. FP instrs. +#ifdef __PIC__ + "popl %%ebx \n\t" // restore index to Global Offset Table +#endif + + : "=c" (dummy_value_c), // output regs (dummy) + "=S" (dummy_value_S), + "=D" (dummy_value_D) + + : "0" (bpp), // ecx // input regs + "1" (prev_row), // esi + "2" (row) // edi + + : "%eax", "%edx" // clobber list (no input regs!) +#ifndef __PIC__ + , "%ebx" +#endif + ); + +} /* end png_read_filter_row_mmx_paeth() */ + + + + +//===========================================================================// +// // +// P N G _ R E A D _ F I L T E R _ R O W _ M M X _ S U B // +// // +//===========================================================================// + +// Optimized code for PNG Sub filter decoder + +static void /* PRIVATE */ +png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row) +{ + int bpp; + int dummy_value_a; + int dummy_value_D; + + bpp = (row_info->pixel_depth + 7) >> 3; // calc number of bytes per pixel + _FullLength = row_info->rowbytes - bpp; // number of bytes to filter + + __asm__ __volatile__ ( +//pre "movl row, %%edi \n\t" + "movl %%edi, %%esi \n\t" // lp = row +//pre "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp +//irr "xorl %%eax, %%eax \n\t" + // get # of bytes to alignment + "movl %%edi, _dif \n\t" // take start of row + "addl $0xf, _dif \n\t" // add 7 + 8 to incr past + // alignment boundary + "xorl %%ecx, %%ecx \n\t" + "andl $0xfffffff8, _dif \n\t" // mask to alignment boundary + "subl %%edi, _dif \n\t" // subtract from start ==> value + "jz sub_go \n\t" // ecx at alignment + + "sub_lp1: \n\t" // fix alignment + "movb (%%esi,%%ecx,), %%al \n\t" + "addb %%al, (%%edi,%%ecx,) \n\t" + "incl %%ecx \n\t" + "cmpl _dif, %%ecx \n\t" + "jb sub_lp1 \n\t" + + "sub_go: \n\t" + "movl _FullLength, %%eax \n\t" + "movl %%eax, %%edx \n\t" + "subl %%ecx, %%edx \n\t" // subtract alignment fix + "andl $0x00000007, %%edx \n\t" // calc bytes over mult of 8 + "subl %%edx, %%eax \n\t" // drop over bytes from length + "movl %%eax, _MMXLength \n\t" + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%ebx", "%ecx", "%edx" // clobber list + , "%esi" + +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + + // now do the math for the rest of the row + switch (bpp) + { + case 3: + { + _ActiveMask.use = 0x0000ffffff000000LL; + _ShiftBpp.use = 24; // == 3 * 8 + _ShiftRem.use = 40; // == 64 - 24 + + __asm__ __volatile__ ( +// preload "movl row, %%edi \n\t" + "movq _ActiveMask, %%mm7 \n\t" // load _ActiveMask for 2nd + // active byte group + "movl %%edi, %%esi \n\t" // lp = row +// preload "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp + "movq %%mm7, %%mm6 \n\t" + "movl _dif, %%edx \n\t" + "psllq _ShiftBpp, %%mm6 \n\t" // move mask in mm6 to cover + // 3rd active byte group + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%edx,), %%mm1 \n\t" + + "sub_3lp: \n\t" // shift data for adding first + "psrlq _ShiftRem, %%mm1 \n\t" // bpp bytes (no need for mask; + // shift clears inactive bytes) + // add 1st active group + "movq (%%edi,%%edx,), %%mm0 \n\t" + "paddb %%mm1, %%mm0 \n\t" + + // add 2nd active group + "movq %%mm0, %%mm1 \n\t" // mov updated Raws to mm1 + "psllq _ShiftBpp, %%mm1 \n\t" // shift data to pos. correctly + "pand %%mm7, %%mm1 \n\t" // mask to use 2nd active group + "paddb %%mm1, %%mm0 \n\t" + + // add 3rd active group + "movq %%mm0, %%mm1 \n\t" // mov updated Raws to mm1 + "psllq _ShiftBpp, %%mm1 \n\t" // shift data to pos. correctly + "pand %%mm6, %%mm1 \n\t" // mask to use 3rd active group + "addl $8, %%edx \n\t" + "paddb %%mm1, %%mm0 \n\t" + + "cmpl _MMXLength, %%edx \n\t" + "movq %%mm0, -8(%%edi,%%edx,) \n\t" // write updated Raws to array + "movq %%mm0, %%mm1 \n\t" // prep 1st add at top of loop + "jb sub_3lp \n\t" + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%edx", "%esi" // clobber list +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm6", "%mm7" +#endif + ); + } + break; + + case 1: + { + __asm__ __volatile__ ( + "movl _dif, %%edx \n\t" +// preload "movl row, %%edi \n\t" + "cmpl _FullLength, %%edx \n\t" + "jnb sub_1end \n\t" + "movl %%edi, %%esi \n\t" // lp = row + "xorl %%eax, %%eax \n\t" +// preload "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp + + "sub_1lp: \n\t" + "movb (%%esi,%%edx,), %%al \n\t" + "addb %%al, (%%edi,%%edx,) \n\t" + "incl %%edx \n\t" + "cmpl _FullLength, %%edx \n\t" + "jb sub_1lp \n\t" + + "sub_1end: \n\t" + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%edx", "%esi" // clobber list + ); + } + return; + + case 6: + case 4: + //case 7: // GRR BOGUS + //case 5: // GRR BOGUS + { + _ShiftBpp.use = bpp << 3; + _ShiftRem.use = 64 - _ShiftBpp.use; + + __asm__ __volatile__ ( +// preload "movl row, %%edi \n\t" + "movl _dif, %%edx \n\t" + "movl %%edi, %%esi \n\t" // lp = row +// preload "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp + + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%edx,), %%mm1 \n\t" + + "sub_4lp: \n\t" // shift data for adding first + "psrlq _ShiftRem, %%mm1 \n\t" // bpp bytes (no need for mask; + // shift clears inactive bytes) + "movq (%%edi,%%edx,), %%mm0 \n\t" + "paddb %%mm1, %%mm0 \n\t" + + // add 2nd active group + "movq %%mm0, %%mm1 \n\t" // mov updated Raws to mm1 + "psllq _ShiftBpp, %%mm1 \n\t" // shift data to pos. correctly + "addl $8, %%edx \n\t" + "paddb %%mm1, %%mm0 \n\t" + + "cmpl _MMXLength, %%edx \n\t" + "movq %%mm0, -8(%%edi,%%edx,) \n\t" + "movq %%mm0, %%mm1 \n\t" // prep 1st add at top of loop + "jb sub_4lp \n\t" + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%edx", "%esi" // clobber list +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1" +#endif + ); + } + break; + + case 2: + { + _ActiveMask.use = 0x00000000ffff0000LL; + _ShiftBpp.use = 16; // == 2 * 8 + _ShiftRem.use = 48; // == 64 - 16 + + __asm__ __volatile__ ( + "movq _ActiveMask, %%mm7 \n\t" // load _ActiveMask for 2nd + // active byte group + "movl _dif, %%edx \n\t" + "movq %%mm7, %%mm6 \n\t" +// preload "movl row, %%edi \n\t" + "psllq _ShiftBpp, %%mm6 \n\t" // move mask in mm6 to cover + // 3rd active byte group + "movl %%edi, %%esi \n\t" // lp = row + "movq %%mm6, %%mm5 \n\t" +// preload "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp + "psllq _ShiftBpp, %%mm5 \n\t" // move mask in mm5 to cover + // 4th active byte group + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%edx,), %%mm1 \n\t" + + "sub_2lp: \n\t" // shift data for adding first + "psrlq _ShiftRem, %%mm1 \n\t" // bpp bytes (no need for mask; + // shift clears inactive bytes) + // add 1st active group + "movq (%%edi,%%edx,), %%mm0 \n\t" + "paddb %%mm1, %%mm0 \n\t" + + // add 2nd active group + "movq %%mm0, %%mm1 \n\t" // mov updated Raws to mm1 + "psllq _ShiftBpp, %%mm1 \n\t" // shift data to pos. correctly + "pand %%mm7, %%mm1 \n\t" // mask to use 2nd active group + "paddb %%mm1, %%mm0 \n\t" + + // add 3rd active group + "movq %%mm0, %%mm1 \n\t" // mov updated Raws to mm1 + "psllq _ShiftBpp, %%mm1 \n\t" // shift data to pos. correctly + "pand %%mm6, %%mm1 \n\t" // mask to use 3rd active group + "paddb %%mm1, %%mm0 \n\t" + + // add 4th active group + "movq %%mm0, %%mm1 \n\t" // mov updated Raws to mm1 + "psllq _ShiftBpp, %%mm1 \n\t" // shift data to pos. correctly + "pand %%mm5, %%mm1 \n\t" // mask to use 4th active group + "addl $8, %%edx \n\t" + "paddb %%mm1, %%mm0 \n\t" + "cmpl _MMXLength, %%edx \n\t" + "movq %%mm0, -8(%%edi,%%edx,) \n\t" // write updated Raws to array + "movq %%mm0, %%mm1 \n\t" // prep 1st add at top of loop + "jb sub_2lp \n\t" + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%edx", "%esi" // clobber list +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; + + case 8: + { + __asm__ __volatile__ ( +// preload "movl row, %%edi \n\t" + "movl _dif, %%edx \n\t" + "movl %%edi, %%esi \n\t" // lp = row +// preload "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp + "movl _MMXLength, %%ecx \n\t" + + // prime the pump: load the first Raw(x-bpp) data set + "movq -8(%%edi,%%edx,), %%mm7 \n\t" + "andl $0x0000003f, %%ecx \n\t" // calc bytes over mult of 64 + + "sub_8lp: \n\t" + "movq (%%edi,%%edx,), %%mm0 \n\t" // load Sub(x) for 1st 8 bytes + "paddb %%mm7, %%mm0 \n\t" + "movq 8(%%edi,%%edx,), %%mm1 \n\t" // load Sub(x) for 2nd 8 bytes + "movq %%mm0, (%%edi,%%edx,) \n\t" // write Raw(x) for 1st 8 bytes + + // Now mm0 will be used as Raw(x-bpp) for the 2nd group of 8 bytes. + // This will be repeated for each group of 8 bytes with the 8th + // group being used as the Raw(x-bpp) for the 1st group of the + // next loop. + + "paddb %%mm0, %%mm1 \n\t" + "movq 16(%%edi,%%edx,), %%mm2 \n\t" // load Sub(x) for 3rd 8 bytes + "movq %%mm1, 8(%%edi,%%edx,) \n\t" // write Raw(x) for 2nd 8 bytes + "paddb %%mm1, %%mm2 \n\t" + "movq 24(%%edi,%%edx,), %%mm3 \n\t" // load Sub(x) for 4th 8 bytes + "movq %%mm2, 16(%%edi,%%edx,) \n\t" // write Raw(x) for 3rd 8 bytes + "paddb %%mm2, %%mm3 \n\t" + "movq 32(%%edi,%%edx,), %%mm4 \n\t" // load Sub(x) for 5th 8 bytes + "movq %%mm3, 24(%%edi,%%edx,) \n\t" // write Raw(x) for 4th 8 bytes + "paddb %%mm3, %%mm4 \n\t" + "movq 40(%%edi,%%edx,), %%mm5 \n\t" // load Sub(x) for 6th 8 bytes + "movq %%mm4, 32(%%edi,%%edx,) \n\t" // write Raw(x) for 5th 8 bytes + "paddb %%mm4, %%mm5 \n\t" + "movq 48(%%edi,%%edx,), %%mm6 \n\t" // load Sub(x) for 7th 8 bytes + "movq %%mm5, 40(%%edi,%%edx,) \n\t" // write Raw(x) for 6th 8 bytes + "paddb %%mm5, %%mm6 \n\t" + "movq 56(%%edi,%%edx,), %%mm7 \n\t" // load Sub(x) for 8th 8 bytes + "movq %%mm6, 48(%%edi,%%edx,) \n\t" // write Raw(x) for 7th 8 bytes + "addl $64, %%edx \n\t" + "paddb %%mm6, %%mm7 \n\t" + "cmpl %%ecx, %%edx \n\t" + "movq %%mm7, -8(%%edi,%%edx,) \n\t" // write Raw(x) for 8th 8 bytes + "jb sub_8lp \n\t" + + "cmpl _MMXLength, %%edx \n\t" + "jnb sub_8lt8 \n\t" + + "sub_8lpA: \n\t" + "movq (%%edi,%%edx,), %%mm0 \n\t" + "addl $8, %%edx \n\t" + "paddb %%mm7, %%mm0 \n\t" + "cmpl _MMXLength, %%edx \n\t" + "movq %%mm0, -8(%%edi,%%edx,) \n\t" // -8 to offset early addl edx + "movq %%mm0, %%mm7 \n\t" // move calculated Raw(x) data + // to mm1 to be new Raw(x-bpp) + // for next loop + "jb sub_8lpA \n\t" + + "sub_8lt8: \n\t" + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%ecx", "%edx", "%esi" // clobber list +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + } + break; + + default: // bpp greater than 8 bytes GRR BOGUS + { + __asm__ __volatile__ ( + "movl _dif, %%edx \n\t" +// preload "movl row, %%edi \n\t" + "movl %%edi, %%esi \n\t" // lp = row +// preload "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp + + "sub_Alp: \n\t" + "movq (%%edi,%%edx,), %%mm0 \n\t" + "movq (%%esi,%%edx,), %%mm1 \n\t" + "addl $8, %%edx \n\t" + "paddb %%mm1, %%mm0 \n\t" + "cmpl _MMXLength, %%edx \n\t" + "movq %%mm0, -8(%%edi,%%edx,) \n\t" // mov does not affect flags; + // -8 to offset addl edx + "jb sub_Alp \n\t" + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%edx", "%esi" // clobber list +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1" +#endif + ); + } + break; + + } // end switch (bpp) + + __asm__ __volatile__ ( + "movl _MMXLength, %%edx \n\t" +//pre "movl row, %%edi \n\t" + "cmpl _FullLength, %%edx \n\t" + "jnb sub_end \n\t" + + "movl %%edi, %%esi \n\t" // lp = row +//pre "movl bpp, %%eax \n\t" + "addl %%eax, %%edi \n\t" // rp = row + bpp + "xorl %%eax, %%eax \n\t" + + "sub_lp2: \n\t" + "movb (%%esi,%%edx,), %%al \n\t" + "addb %%al, (%%edi,%%edx,) \n\t" + "incl %%edx \n\t" + "cmpl _FullLength, %%edx \n\t" + "jb sub_lp2 \n\t" + + "sub_end: \n\t" + "EMMS \n\t" // end MMX instructions + + : "=a" (dummy_value_a), // 0 // output regs (dummy) + "=D" (dummy_value_D) // 1 + + : "0" (bpp), // eax // input regs + "1" (row) // edi + + : "%edx", "%esi" // clobber list + ); + +} // end of png_read_filter_row_mmx_sub() + + + + +//===========================================================================// +// // +// P N G _ R E A D _ F I L T E R _ R O W _ M M X _ U P // +// // +//===========================================================================// + +// Optimized code for PNG Up filter decoder + +static void /* PRIVATE */ +png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row, + png_bytep prev_row) +{ + png_uint_32 len; + int dummy_value_d; // fix 'forbidden register 3 (dx) was spilled' error + int dummy_value_S; + int dummy_value_D; + + len = row_info->rowbytes; // number of bytes to filter + + __asm__ __volatile__ ( +//pre "movl row, %%edi \n\t" + // get # of bytes to alignment + "movl %%edi, %%ecx \n\t" + "xorl %%ebx, %%ebx \n\t" + "addl $0x7, %%ecx \n\t" + "xorl %%eax, %%eax \n\t" + "andl $0xfffffff8, %%ecx \n\t" +//pre "movl prev_row, %%esi \n\t" + "subl %%edi, %%ecx \n\t" + "jz up_go \n\t" + + "up_lp1: \n\t" // fix alignment + "movb (%%edi,%%ebx,), %%al \n\t" + "addb (%%esi,%%ebx,), %%al \n\t" + "incl %%ebx \n\t" + "cmpl %%ecx, %%ebx \n\t" + "movb %%al, -1(%%edi,%%ebx,) \n\t" // mov does not affect flags; -1 to + "jb up_lp1 \n\t" // offset incl ebx + + "up_go: \n\t" +//pre "movl len, %%edx \n\t" + "movl %%edx, %%ecx \n\t" + "subl %%ebx, %%edx \n\t" // subtract alignment fix + "andl $0x0000003f, %%edx \n\t" // calc bytes over mult of 64 + "subl %%edx, %%ecx \n\t" // drop over bytes from length + + // unrolled loop - use all MMX registers and interleave to reduce + // number of branch instructions (loops) and reduce partial stalls + "up_loop: \n\t" + "movq (%%esi,%%ebx,), %%mm1 \n\t" + "movq (%%edi,%%ebx,), %%mm0 \n\t" + "movq 8(%%esi,%%ebx,), %%mm3 \n\t" + "paddb %%mm1, %%mm0 \n\t" + "movq 8(%%edi,%%ebx,), %%mm2 \n\t" + "movq %%mm0, (%%edi,%%ebx,) \n\t" + "paddb %%mm3, %%mm2 \n\t" + "movq 16(%%esi,%%ebx,), %%mm5 \n\t" + "movq %%mm2, 8(%%edi,%%ebx,) \n\t" + "movq 16(%%edi,%%ebx,), %%mm4 \n\t" + "movq 24(%%esi,%%ebx,), %%mm7 \n\t" + "paddb %%mm5, %%mm4 \n\t" + "movq 24(%%edi,%%ebx,), %%mm6 \n\t" + "movq %%mm4, 16(%%edi,%%ebx,) \n\t" + "paddb %%mm7, %%mm6 \n\t" + "movq 32(%%esi,%%ebx,), %%mm1 \n\t" + "movq %%mm6, 24(%%edi,%%ebx,) \n\t" + "movq 32(%%edi,%%ebx,), %%mm0 \n\t" + "movq 40(%%esi,%%ebx,), %%mm3 \n\t" + "paddb %%mm1, %%mm0 \n\t" + "movq 40(%%edi,%%ebx,), %%mm2 \n\t" + "movq %%mm0, 32(%%edi,%%ebx,) \n\t" + "paddb %%mm3, %%mm2 \n\t" + "movq 48(%%esi,%%ebx,), %%mm5 \n\t" + "movq %%mm2, 40(%%edi,%%ebx,) \n\t" + "movq 48(%%edi,%%ebx,), %%mm4 \n\t" + "movq 56(%%esi,%%ebx,), %%mm7 \n\t" + "paddb %%mm5, %%mm4 \n\t" + "movq 56(%%edi,%%ebx,), %%mm6 \n\t" + "movq %%mm4, 48(%%edi,%%ebx,) \n\t" + "addl $64, %%ebx \n\t" + "paddb %%mm7, %%mm6 \n\t" + "cmpl %%ecx, %%ebx \n\t" + "movq %%mm6, -8(%%edi,%%ebx,) \n\t" // (+56)movq does not affect flags; + "jb up_loop \n\t" // -8 to offset addl ebx + + "cmpl $0, %%edx \n\t" // test for bytes over mult of 64 + "jz up_end \n\t" + + "cmpl $8, %%edx \n\t" // test for less than 8 bytes + "jb up_lt8 \n\t" // [added by lcreeve@netins.net] + + "addl %%edx, %%ecx \n\t" + "andl $0x00000007, %%edx \n\t" // calc bytes over mult of 8 + "subl %%edx, %%ecx \n\t" // drop over bytes from length + "jz up_lt8 \n\t" + + "up_lpA: \n\t" // use MMX regs to update 8 bytes sim. + "movq (%%esi,%%ebx,), %%mm1 \n\t" + "movq (%%edi,%%ebx,), %%mm0 \n\t" + "addl $8, %%ebx \n\t" + "paddb %%mm1, %%mm0 \n\t" + "cmpl %%ecx, %%ebx \n\t" + "movq %%mm0, -8(%%edi,%%ebx,) \n\t" // movq does not affect flags; -8 to + "jb up_lpA \n\t" // offset add ebx + "cmpl $0, %%edx \n\t" // test for bytes over mult of 8 + "jz up_end \n\t" + + "up_lt8: \n\t" + "xorl %%eax, %%eax \n\t" + "addl %%edx, %%ecx \n\t" // move over byte count into counter + + "up_lp2: \n\t" // use x86 regs for remaining bytes + "movb (%%edi,%%ebx,), %%al \n\t" + "addb (%%esi,%%ebx,), %%al \n\t" + "incl %%ebx \n\t" + "cmpl %%ecx, %%ebx \n\t" + "movb %%al, -1(%%edi,%%ebx,) \n\t" // mov does not affect flags; -1 to + "jb up_lp2 \n\t" // offset inc ebx + + "up_end: \n\t" + "EMMS \n\t" // conversion of filtered row complete + + : "=d" (dummy_value_d), // 0 // output regs (dummy) + "=S" (dummy_value_S), // 1 + "=D" (dummy_value_D) // 2 + + : "0" (len), // edx // input regs + "1" (prev_row), // esi + "2" (row) // edi + + : "%eax", "%ebx", "%ecx" // clobber list (no input regs!) + +#if 0 /* MMX regs (%mm0, etc.) not supported by gcc 2.7.2.3 or egcs 1.1 */ + , "%mm0", "%mm1", "%mm2", "%mm3" + , "%mm4", "%mm5", "%mm6", "%mm7" +#endif + ); + +} // end of png_read_filter_row_mmx_up() + +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + + + + +/*===========================================================================*/ +/* */ +/* P N G _ R E A D _ F I L T E R _ R O W */ +/* */ +/*===========================================================================*/ + +#if defined(PNG_HAVE_ASSEMBLER_READ_FILTER_ROW) + +/* Optimized png_read_filter_row routines */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep + row, png_bytep prev_row, int filter) +{ +#ifdef PNG_DEBUG + char filnm[10]; +#endif + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +/* GRR: these are superseded by png_ptr->asm_flags: */ +#define UseMMX_sub 1 // GRR: converted 20000730 +#define UseMMX_up 1 // GRR: converted 20000729 +#define UseMMX_avg 1 // GRR: converted 20000828 (+ 16-bit bugfix 20000916) +#define UseMMX_paeth 1 // GRR: converted 20000828 + + if (_mmx_supported == 2) { + png_mmx_support(); + } +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +#ifdef PNG_DEBUG + png_debug(1, "in png_read_filter_row (pnggccrd.c)\n"); + switch (filter) + { + case 0: sprintf(filnm, "none"); + break; + case 1: sprintf(filnm, "sub-%s", "MMX"); + break; + case 2: sprintf(filnm, "up-%s", "MMX"); + break; + case 3: sprintf(filnm, "avg-%s", "MMX"); + break; + case 4: sprintf(filnm, "Paeth-%s", "MMX"); + break; + default: sprintf(filnm, "unknw"); + break; + } + png_debug2(0, "row_number=%5ld, %5s, ", png_ptr->row_number, filnm); + png_debug1(0, "row=0x%08lx, ", (unsigned long)row); + png_debug2(0, "pixdepth=%2d, bytes=%d, ", (int)row_info->pixel_depth, + (int)((row_info->pixel_depth + 7) >> 3)); + png_debug1(0,"rowbytes=%8ld\n", row_info->rowbytes); +#endif /* PNG_DEBUG */ + + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + + case PNG_FILTER_VALUE_SUB: +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported && + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_sub(row_info, row); + } + else +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + } /* end !UseMMX_sub */ + break; + + case PNG_FILTER_VALUE_UP: +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported && + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_up(row_info, row, prev_row); + } + else +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; ++i) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + } /* end !UseMMX_up */ + break; + + case PNG_FILTER_VALUE_AVG: +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported && + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_avg(row_info, row, prev_row); + } + else +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) >> 1)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++ + *lp++) >> 1)) & 0xff); + rp++; + } + } /* end !UseMMX_avg */ + break; + + case PNG_FILTER_VALUE_PAETH: +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) + if ( _mmx_supported && + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_paeth(row_info, row, prev_row); + } + else +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + } /* end !UseMMX_paeth */ + break; + + default: + png_warning(png_ptr, "Ignoring bad row-filter type"); + *row=0; + break; + } +} + +#endif /* PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */ + + +/*===========================================================================*/ +/* */ +/* P N G _ M M X _ S U P P O R T */ +/* */ +/*===========================================================================*/ + +/* GRR NOTES: (1) the following code assumes 386 or better (pushfl/popfl) + * (2) all instructions compile with gcc 2.7.2.3 and later + * (3) the function is moved down here to prevent gcc from + * inlining it in multiple places and then barfing be- + * cause the ".NOT_SUPPORTED" label is multiply defined + * [is there a way to signal that a *single* function should + * not be inlined? is there a way to modify the label for + * each inlined instance, e.g., by appending _1, _2, etc.? + * maybe if don't use leading "." in label name? (nope...sigh)] + */ + +int PNGAPI +png_mmx_support(void) +{ +#if defined(PNG_MMX_CODE_SUPPORTED) + __asm__ __volatile__ ( + "pushl %%ebx \n\t" // ebx gets clobbered by CPUID instruction + "pushl %%ecx \n\t" // so does ecx... + "pushl %%edx \n\t" // ...and edx (but ecx & edx safe on Linux) +// ".byte 0x66 \n\t" // convert 16-bit pushf to 32-bit pushfd +// "pushf \n\t" // 16-bit pushf + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack into eax + "movl %%eax, %%ecx \n\t" // make another copy of Eflag in ecx + "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) + "pushl %%eax \n\t" // save modified Eflag back to stack +// ".byte 0x66 \n\t" // convert 16-bit popf to 32-bit popfd +// "popf \n\t" // 16-bit popf + "popfl \n\t" // restore modified value to Eflag reg + "pushfl \n\t" // save Eflag to stack + "popl %%eax \n\t" // get Eflag from stack + "xorl %%ecx, %%eax \n\t" // compare new Eflag with original Eflag + "jz .NOT_SUPPORTED \n\t" // if same, CPUID instr. is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero +// ".byte 0x0f, 0xa2 \n\t" // CPUID instruction (two-byte opcode) + "cpuid \n\t" // get the CPU identification info + "cmpl $1, %%eax \n\t" // make sure eax return non-zero value + "jl .NOT_SUPPORTED \n\t" // if eax is zero, MMX is not supported + + "xorl %%eax, %%eax \n\t" // set eax to zero and... + "incl %%eax \n\t" // ...increment eax to 1. This pair is + // faster than the instruction "mov eax, 1" + "cpuid \n\t" // get the CPU identification info again + "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23) + "cmpl $0, %%edx \n\t" // 0 = MMX not supported + "jz .NOT_SUPPORTED \n\t" // non-zero = yes, MMX IS supported + + "movl $1, %%eax \n\t" // set return value to 1 + "jmp .RETURN \n\t" // DONE: have MMX support + + ".NOT_SUPPORTED: \n\t" // target label for jump instructions + "movl $0, %%eax \n\t" // set return value to 0 + ".RETURN: \n\t" // target label for jump instructions + "movl %%eax, _mmx_supported \n\t" // save in global static variable, too + "popl %%edx \n\t" // restore edx + "popl %%ecx \n\t" // restore ecx + "popl %%ebx \n\t" // restore ebx + +// "ret \n\t" // DONE: no MMX support + // (fall through to standard C "ret") + + : // output list (none) + + : // any variables used on input (none) + + : "%eax" // clobber list +// , "%ebx", "%ecx", "%edx" // GRR: we handle these manually +// , "memory" // if write to a variable gcc thought was in a reg +// , "cc" // "condition codes" (flag bits) + ); +#else + _mmx_supported = 0; +#endif /* PNG_MMX_CODE_SUPPORTED */ + + return _mmx_supported; +} + +#endif /* PNG_USE_PNGGCCRD */ diff --git a/Utilities/vtkpng/pngget.c b/Utilities/vtkpng/pngget.c new file mode 100644 index 0000000..208918f --- /dev/null +++ b/Utilities/vtkpng/pngget.c @@ -0,0 +1,829 @@ + +/* pngget.c - retrieval of values from info struct + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +png_uint_32 PNGAPI +png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + else + return(0); +} + +png_uint_32 PNGAPI +png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + else + return(0); +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +png_bytepp PNGAPI +png_get_rows(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + else + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->width; + } + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->height; + } + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->bit_depth; + } + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->color_type; + } + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->filter_type; + } + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->interlace_type; + } + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + { + return info_ptr->compression_type; + } + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + else return (info_ptr->y_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter"); + if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER || + info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) + return (0); + else return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) + { + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio"); + if (info_ptr->x_pixels_per_unit == 0) + return ((float)0.0); + else + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + return (0.0); +#endif + return ((float)0.0); +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + else return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#if defined(PNG_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); + if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + else return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +float PNGAPI +png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_x_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +float PNGAPI +png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_y_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + if(*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + else + return (0); +} + +png_bytep PNGAPI +png_get_signature(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + else + return (NULL); +} + +#if defined(PNG_bKGD_SUPPORTED) +png_uint_32 PNGAPI +png_get_bKGD(png_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function\n", "bKGD"); + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + return (0); +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_structp png_ptr, png_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = (double)info_ptr->x_white; + if (white_y != NULL) + *white_y = (double)info_ptr->y_white; + if (red_x != NULL) + *red_x = (double)info_ptr->x_red; + if (red_y != NULL) + *red_y = (double)info_ptr->y_red; + if (green_x != NULL) + *green_x = (double)info_ptr->x_green; + if (green_y != NULL) + *green_y = (double)info_ptr->y_green; + if (blue_x != NULL) + *blue_x = (double)info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = (double)info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function\n", "cHRM"); + if (white_x != NULL) + *white_x = info_ptr->int_x_white; + if (white_y != NULL) + *white_y = info_ptr->int_y_white; + if (red_x != NULL) + *red_x = info_ptr->int_x_red; + if (red_y != NULL) + *red_y = info_ptr->int_y_red; + if (green_x != NULL) + *green_x = info_ptr->int_x_green; + if (green_y != NULL) + *green_y = info_ptr->int_y_green; + if (blue_x != NULL) + *blue_x = info_ptr->int_x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->int_y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *file_gamma = (double)info_ptr->gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *int_file_gamma) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && int_file_gamma != NULL) + { + png_debug1(1, "in %s retrieval function\n", "gAMA"); + *int_file_gamma = info_ptr->int_gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#endif + +#if defined(PNG_sRGB_SUPPORTED) +png_uint_32 PNGAPI +png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + png_debug1(1, "in %s retrieval function\n", "sRGB"); + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + return (0); +} +#endif + +#if defined(PNG_iCCP_SUPPORTED) +png_uint_32 PNGAPI +png_get_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + png_debug1(1, "in %s retrieval function\n", "iCCP"); + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* compression_type is a dummy so the API won't have to change + if we introduce multiple compression types later. */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + return (0); +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sPLT(png_structp png_ptr, png_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +png_uint_32 PNGAPI +png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + png_debug1(1, "in %s retrieval function\n", "hIST"); + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL && + bit_depth != NULL && color_type != NULL) + { + int pixel_depth, channels; + png_uint_32 rowbytes_per_pixel; + + png_debug1(1, "in %s retrieval function\n", "IHDR"); + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* check for potential overflow of rowbytes */ + if (*color_type == PNG_COLOR_TYPE_PALETTE) + channels = 1; + else if (*color_type & PNG_COLOR_MASK_COLOR) + channels = 3; + else + channels = 1; + if (*color_type & PNG_COLOR_MASK_ALPHA) + channels++; + pixel_depth = *bit_depth * channels; + rowbytes_per_pixel = (pixel_depth + 7) >> 3; + if ((*width > PNG_MAX_UINT/rowbytes_per_pixel)) + { + png_warning(png_ptr, + "Width too large for libpng to process image data."); + } + return (1); + } + return (0); +} + +#if defined(PNG_oFFs_SUPPORTED) +png_uint_32 PNGAPI +png_get_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + png_debug1(1, "in %s retrieval function\n", "oFFs"); + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + return (0); +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +png_uint_32 PNGAPI +png_get_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + png_debug1(1, "in %s retrieval function\n", "pCAL"); + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + return (0); +} +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_structp png_ptr, png_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_pixel_width; + *height = info_ptr->scal_pixel_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +png_uint_32 PNGAPI +png_get_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function\n", "pHYs"); + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + return (retval); +} +#endif + +png_uint_32 PNGAPI +png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, + int *num_palette) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + png_debug1(1, "in %s retrieval function\n", "PLTE"); + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d\n", *num_palette); + return (PNG_INFO_PLTE); + } + return (0); +} + +#if defined(PNG_sBIT_SUPPORTED) +png_uint_32 PNGAPI +png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + png_debug1(1, "in %s retrieval function\n", "sBIT"); + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + return (0); +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +png_uint_32 PNGAPI +png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, + int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function\n", + (png_ptr->chunk_name[0] == '\0' ? "text" + : (png_const_charp)png_ptr->chunk_name)); + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + if (num_text != NULL) + *num_text = info_ptr->num_text; + return ((png_uint_32)info_ptr->num_text); + } + if (num_text != NULL) + *num_text = 0; + return(0); +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +png_uint_32 PNGAPI +png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + png_debug1(1, "in %s retrieval function\n", "tIME"); + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + return (0); +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +png_uint_32 PNGAPI +png_get_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep *trans, int *num_trans, png_color_16p *trans_values) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function\n", "tRNS"); + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans != NULL) + { + *trans = info_ptr->trans; + retval |= PNG_INFO_tRNS; + } + if (trans_values != NULL) + *trans_values = &(info_ptr->trans_values); + } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_values != NULL) + { + *trans_values = &(info_ptr->trans_values); + retval |= PNG_INFO_tRNS; + } + if(trans != NULL) + *trans = NULL; + } + if(num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + return (retval); +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +png_uint_32 PNGAPI +png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + *unknowns = info_ptr->unknown_chunks; + return ((png_uint_32)info_ptr->unknown_chunks_num); +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +png_byte PNGAPI +png_get_rgb_to_gray_status (png_structp png_ptr) +{ + return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +png_voidp PNGAPI +png_get_user_chunk_ptr(png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_chunk_ptr : NULL); +} +#endif + + +png_uint_32 PNGAPI +png_get_compression_buffer_size(png_structp png_ptr) +{ + return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L); +} + + diff --git a/Utilities/vtkpng/pngmem.c b/Utilities/vtkpng/pngmem.c new file mode 100644 index 0000000..dd74715 --- /dev/null +++ b/Utilities/vtkpng/pngmem.c @@ -0,0 +1,531 @@ + +/* pngmem.c - stub functions for memory allocation + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* if you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = sizeof(png_struct); + else + return ((png_voidp)NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(malloc_fn != NULL) + { + if (mem_ptr != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + } + else + struct_ptr = (*(malloc_fn))(NULL, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); + } +#endif /* PNG_USER_MEM_SUPPORTED */ + if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL) + { + png_memset(struct_ptr, 0, size); + } + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL, (png_voidp)NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ +#ifndef PNG_USER_MEM_SUPPORTED + png_voidp ret; +#endif + if (png_ptr == NULL || size == 0) + return ((png_voidp)NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(png_ptr->malloc_fn != NULL) + { + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size)); + if (ret == NULL) + png_error(png_ptr, "Out of memory!"); + return (ret); + } + else + return png_malloc_default(png_ptr, size); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + png_error(png_ptr, "Cannot Allocate > 64K"); +#endif + + if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if(png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else + num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { + png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ + } + + if ((png_size_t)table & 0xfff0) + { + png_error(png_ptr, "Farmalloc didn't return normalized pointer"); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + sizeof (png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { + png_error(png_ptr, "Out Of memory."); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + png_error(png_ptr, "Out of Memory."); + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + else + ret = farmalloc(size); + + if (ret == NULL) + { + png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ + } + + return (ret); +} + +/* free a pointer allocated by png_malloc(). In the default + configuration, png_ptr is not used, but is passed in case it + is needed. If ptr is NULL, return without taking any action. */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + { + farfree(ptr); + } +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably.*/ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably.*/ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = sizeof(png_struct); + else + return ((png_voidp)NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(malloc_fn != NULL) + { + if (mem_ptr != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + } + else + struct_ptr = (*(malloc_fn))(NULL, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); + } +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL) +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if ((struct_ptr = (png_voidp)halloc(size,1)) != NULL) +# else + if ((struct_ptr = (png_voidp)malloc(size)) != NULL) +# endif +#endif + { + png_memset(struct_ptr, 0, size); + } + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, (png_free_ptr)NULL, (png_voidp)NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if(free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); +# else + free(struct_ptr); +# endif +#endif + } +} + + +/* Allocate memory. For reasonable files, size should never exceed + 64K. However, zlib may allocate more then 64K if you don't tell + it not to. See zconf.h and png.h for more information. zlib does + need to allocate exactly 64K, so whatever you call here must + have the ability to do that. */ + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; + if (png_ptr == NULL || size == 0) + return ((png_voidp)NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if(png_ptr->malloc_fn != NULL) + { + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size)); + if (ret == NULL) + png_error(png_ptr, "Out of Memory!"); + return (ret); + } + else + return (png_malloc_default(png_ptr, size)); +} +png_voidp /* PRIVATE */ +png_malloc_default(png_structp png_ptr, png_uint_32 size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + png_error(png_ptr, "Cannot Allocate > 64K"); +#endif + +#if defined(__TURBOC__) && !defined(__FLAT__) + ret = farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + ret = halloc(size, 1); +# else + ret = malloc((size_t)size); +# endif +#endif + + if (ret == NULL) + png_error(png_ptr, "Out of Memory"); + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + without taking any action. */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else png_free_default(png_ptr, ptr); +} +void /* PRIVATE */ +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); +# else + free(ptr); +# endif +#endif +} + +#endif /* Not Borland DOS special memory handler */ + +png_voidp /* PRIVATE */ +png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memcpy_check."); + + return(png_memcpy (s1, s2, size)); +} + +png_voidp /* PRIVATE */ +png_memset_check (png_structp png_ptr, png_voidp s1, int value, + png_uint_32 length) +{ + png_size_t size; + + size = (png_size_t)length; + if ((png_uint_32)size != length) + png_error(png_ptr,"Overflow in png_memset_check."); + + return (png_memset (s1, value, size)); + +} + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_structp png_ptr) +{ + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ diff --git a/Utilities/vtkpng/pngpread.c b/Utilities/vtkpng/pngpread.c new file mode 100644 index 0000000..9b4b77a --- /dev/null +++ b/Utilities/vtkpng/pngpread.c @@ -0,0 +1,1504 @@ + +/* pngpread.c - read a png file in push mode + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } +#if defined(PNG_READ_tEXt_SUPPORTED) + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_sCAL; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_sRGB; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_sPLT; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_zTXt; +#endif +#endif /* PNG_USE_LOCAL_ARRAYS */ + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_32(chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + else if (!png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + else + { + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void /* PRIVATE */ +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i,istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, + (png_uint_32)new_max); + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_32(chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + /* check for overflow */ + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + /* check for overflow */ + if((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + int ret; + + if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) + png_error(png_ptr, "Extra compression data"); + + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + for(;;) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK) + { + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_in) + png_error(png_ptr, "Extra compressed data"); + if (!(png_ptr->zstream.avail_out)) + { + png_push_process_row(png_ptr); + } + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + else if (ret == Z_BUF_ERROR) + break; + else + png_error(png_ptr, "Decompression Error"); + } + if (!(png_ptr->zstream.avail_out)) + { + png_push_process_row(png_ptr); + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + png_ptr->zstream.next_out = png_ptr->row_buf; + } + else + break; + } +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = ((png_ptr->row_info.width * + (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ + } + if (png_ptr->pass == 2) /* pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 2) /* skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 2: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 3: + { + int i; + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 4) /* skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + break; + } + case 4: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 5: + { + int i; + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + if (png_ptr->pass == 6) /* skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + if (png_ptr->pass != 6) + break; + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Width of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + const int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; + */ + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + const int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ +#endif + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->irowbytes = ((png_ptr->iwidth * + png_ptr->pixel_depth + 7) >> 3) + 1; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +} + +#if defined(PNG_READ_tEXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place tEXt"); + /* to quiet some compiler warnings */ + if(info_ptr == NULL) return; + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + png_ptr->current_text = 0; + + for (text = key; *text; text++) + /* empty loop */ ; + + if (text != key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = (char *)NULL; + text_ptr->lang_key = (char *)NULL; +#endif + text_ptr->text = text; + + png_set_text(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + } +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place zTXt"); + /* to quiet some compiler warnings */ + if(info_ptr == NULL) return; + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + png_ptr->current_text = 0; + + for (text = key; *text; text++) + /* empty loop */ ; + + /* zTXt can't have zero text */ + if (text == key + png_ptr->current_text_size) + { + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ + { + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep )text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + key_size + 1)); + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_memcpy(text, key, key_size); + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + + 1)); + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = (char *)NULL; + text_ptr->lang_key = (char *)NULL; +#endif + text_ptr->text = text; + + png_set_text(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + } +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place iTXt"); + /* to quiet some compiler warnings */ + if(info_ptr == NULL) return; + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_uint_32)(length+1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + else + text_size = png_ptr->current_text_left; + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#if defined(PNG_MAX_MALLOC_64K) + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + png_ptr->current_text = 0; + + for (lang = key; *lang; lang++) + /* empty loop */ ; + + if (lang != key + png_ptr->current_text_size) + lang++; + + comp_flag = *lang++; + lang++; /* skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* empty loop */ ; + lang_key++; /* skip NUL separator */ + + for (text = lang_key; *text; text++) + /* empty loop */ ; + + if (text != key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text)); + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + png_set_text(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip=0; + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + /* to quiet compiler warnings about unused info_ptr */ + if (info_ptr == NULL) + return; + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { + png_unknown_chunk chunk; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name); + chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, chunk.data, length); + chunk.size = length; +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if(png_ptr->read_user_chunk_fn != NULL) + { + /* callback to user unknown chunk handler */ + if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + } + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + } + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + png_free(png_ptr, chunk.data); + } + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, + png_bytep old_row, png_bytep new_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + const int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; +#endif + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_structp png_ptr) +{ + return png_ptr->io_ptr; +} + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + diff --git a/Utilities/vtkpng/pngread.c b/Utilities/vtkpng/pngread.c new file mode 100644 index 0000000..1ed6b5d --- /dev/null +++ b/Utilities/vtkpng/pngread.c @@ -0,0 +1,1424 @@ + +/* pngread.c - read a PNG file + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Create a PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + png_structp png_ptr; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct\n"); +#ifdef PNG_USER_MEM_SUPPORTED + if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr)) == NULL) +#else + if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL) +#endif + { + return (png_structp)NULL; + } + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; + png_destroy_struct(png_ptr); + return (png_structp)NULL; + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + i=0; + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + + /* Libpng 1.0.6 was not binary compatible, due to insertion of the + info_ptr->free_me member. Libpng-1.0.1 and earlier were not + compatible due to insertion of the user transform function. Note + to maintainer: this test can be removed from version 1.2.0 and + beyond because the previous test would have already rejected it. */ + + if (user_png_ver[0] == '1' && user_png_ver[2] == '0' && + (user_png_ver[4] < '2' || user_png_ver[4] == '6') && + user_png_ver[5] == '\0') + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Application must be recompiled; versions <= 1.0.6 were incompatible"); + } + } + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, NULL, NULL); + + return (png_ptr); +} + +/* Initialize PNG structure for reading, and allocate any memory needed. + This interface is deprecated in favour of the png_create_read_struct(), + and it will eventually disappear. */ +#undef png_read_init +void PNGAPI +vtk_png_read_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if(sizeof(png_struct) > png_struct_size || sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn=(png_error_ptr)NULL; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if(sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn=(png_error_ptr)NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for reading is too small."); + } + if(sizeof(png_info) > png_info_size) + { + png_ptr->error_fn=(png_error_ptr)NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The info struct allocated by application for reading is too small."); + } + png_read_init_3(&png_ptr, user_png_ver, png_struct_size); +} + +void PNGAPI +png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + + int i=0; + + png_structp png_ptr=*ptr_ptr; + + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn=(png_error_ptr)NULL; + png_warning(png_ptr, + "Application uses deprecated png_read_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_read_init_3\n"); + +#ifdef PNG_SETJMP_SUPPORTED + /* save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); +#endif + + if(sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + png_ptr = *ptr_ptr; + } + + /* reset all variables to 0 */ + png_memset(png_ptr, 0, sizeof (png_struct)); + +#ifdef PNG_SETJMP_SUPPORTED + /* restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); +#endif + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; + case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; + default: png_error(png_ptr, "Unknown zlib error"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, NULL, NULL); +} + +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_info\n"); + /* save jump buffer and error functions */ + /* If we haven't checked all of the PNG signature bytes, do so now. */ + if (png_ptr->sig_bytes < 8) + { + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + } + + for(;;) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_zTXt; +#endif +#endif /* PNG_GLOBAL_ARRAYS */ + png_byte chunk_length[4]; + png_uint_32 length; + + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_32(chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + + png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, + length); + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + break; + } + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} + +/* optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info\n"); + /* save jump buffer and error functions */ + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call; row buffer not reallocated"); + png_read_transform_info(png_ptr, info_ptr); +} + +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image\n"); + /* save jump buffer and error functions */ + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); +} + +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; + const int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + const int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; +#endif + int ret; + png_debug2(1, "in png_read_row (row %lu, pass %d)\n", + png_ptr->row_number, png_ptr->pass); + /* save jump buffer and error functions */ + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); +#endif + } + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* if interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_32(chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = ((png_ptr->row_info.width * + (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3); + + if(png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, + png_ptr->rowbytes + 1); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + if (png_ptr->transformations) + png_do_read_transformations(png_ptr); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + /* blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) + png_combine_row(png_ptr, row, + png_pass_mask[png_ptr->pass]); + } + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.12 + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows\n"); + /* save jump buffer and error functions */ + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + else if(rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, NULL); + rp++; + } + else if(dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, NULL, dptr); + dp++; + } +} + +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.12 + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i,image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image\n"); + /* save jump buffer and error functions */ + +#ifdef PNG_READ_INTERLACING_SUPPORTED + pass = png_set_interlace_handling(png_ptr); +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled."); + pass = 1; +#endif + + + image_height=png_ptr->height; + png_ptr->num_rows = image_height; /* Make sure this is set correctly */ + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } +} + +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_byte chunk_length[4]; + png_uint_32 length; + + png_debug(1, "in png_read_end\n"); + /* save jump buffer and error functions */ + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#if defined(PNG_READ_bKGD_SUPPORTED) + PNG_bKGD; +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + PNG_cHRM; +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + PNG_gAMA; +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + PNG_hIST; +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + PNG_iCCP; +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + PNG_iTXt; +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + PNG_oFFs; +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + PNG_pCAL; +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + PNG_pHYs; +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + PNG_sBIT; +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + PNG_sCAL; +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + PNG_sPLT; +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + PNG_sRGB; +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + PNG_tEXt; +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + PNG_tIME; +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + PNG_tRNS; +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + PNG_zTXt; +#endif +#endif /* PNG_GLOBAL_ARRAYS */ + + png_read_data(png_ptr, chunk_length, 4); + length = png_get_uint_32(chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + + png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name); + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + } + else + png_ptr->mode |= PNG_AFTER_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT) + png_error(png_ptr, "Too many IDAT's found"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); +#if defined(PNG_READ_bKGD_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_cHRM_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_gAMA_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_hIST_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_oFFs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sCAL_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_pHYs_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sBIT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sRGB_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iCCP_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_sPLT_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tEXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tIME_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_tRNS_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} + +/* free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_read_struct\n"); + /* save jump buffer and error functions */ + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#if defined(PNG_TEXT_SUPPORTED) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = (png_infop)NULL; + } + + if (end_info_ptr != NULL) + { +#if defined(PNG_READ_TEXT_SUPPORTED) + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = (png_infop)NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = (png_structp)NULL; + } +} + +/* free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy\n"); + /* save jump buffer and error functions */ + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); + png_free(png_ptr, png_ptr->prev_row); +#if defined(PNG_READ_DITHER_SUPPORTED) + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->dither_index); +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_table); +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; +#else + if (png_ptr->flags & PNG_FLAG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; +#endif +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#else + if (png_ptr->flags & PNG_FLAG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans); + png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; +#endif +#endif +#if defined(PNG_READ_hIST_SUPPORTED) +#ifdef PNG_FREE_ME_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#else + if (png_ptr->flags & PNG_FLAG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->flags &= ~PNG_FLAG_FREE_HIST; +#endif +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + + inflateEnd(&png_ptr->zstream); +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, sizeof (png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + png_ptr->read_row_fn = read_row_fn; +} + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* The call to png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + + /* -------------- image transformations start here ------------------- */ + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + /* tell libpng to strip 16 bit/color files down to 8 bits/color */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + /* Strip alpha bytes from the input data without combining with the + * background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or dithering. */ + +#if defined(PNG_READ_INVERT_SUPPORTED) + /* invert monochrome files to have 0 as white and 1 as black */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + /* flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + /* swap bytes of 16 bit files to least significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); +#endif + if(info_ptr->row_pointers == NULL) + { + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * sizeof(png_bytep)); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ROWS; +#endif + for (row = 0; row < (int)info_ptr->height; row++) + { + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + if(transforms == 0 || params == NULL) + /* quiet compiler warnings */ return; + +} +#endif diff --git a/Utilities/vtkpng/pngrio.c b/Utilities/vtkpng/pngrio.c new file mode 100644 index 0000000..707a139 --- /dev/null +++ b/Utilities/vtkpng/pngrio.c @@ -0,0 +1,162 @@ + +/* pngrio.c - functions for data input + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Read the data from whatever input you are using. The default routine + reads from a file pointer. Note that this routine sometimes gets called + with very small lengths, so you should implement some kind of simple + buffering if you are using unbuffered reads. This should never be asked + to read more then 64K on a 16 bit machine. */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4,"reading %d bytes\n", (int)length); + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL read function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual reading of data. If you are + not reading from a standard C stream, you should create a replacement + read_data function and use it at run time with png_set_read_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +static void /* PRIVATE */ +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = (png_size_t)fread(data, (png_size_t)1, length, + (png_FILE_p)png_ptr->io_ptr); +#endif + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void /* PRIVATE */ +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fread(n_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); +#if defined(_WIN32_WCE) + if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) + err = 0; +#else + err = fread(buf, (png_size_t)1, read, io_ptr); +#endif + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if(err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +#endif +#endif + +/* This function allows the application to supply a new input function + for libpng if standard C streams aren't being used. + + This function takes as its arguments: + png_ptr - pointer to a png input data structure + io_ptr - pointer to user supplied structure containing info about + the input functions. May be NULL. + read_data_fn - pointer to a new input function that takes as its + arguments a pointer to a png_struct, a pointer to + a location where input data can be stored, and a 32-bit + unsigned int that is the number of bytes to be read. + To exit and output any fatal error messages the new write + function should call png_error(png_ptr, "Error msg"). */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "It's an error to set both read_data_fn and write_data_fn in the "); + png_warning(png_ptr, + "same structure. Resetting write_data_fn to NULL."); + } + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->output_flush_fn = NULL; +#endif +} + diff --git a/Utilities/vtkpng/pngrtran.c b/Utilities/vtkpng/pngrtran.c new file mode 100644 index 0000000..ef070c8 --- /dev/null +++ b/Utilities/vtkpng/pngrtran.c @@ -0,0 +1,4115 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#define PNG_INTERNAL +#include "png.h" + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action\n"); + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ + png_warning(png_ptr, "Can't discard critical data on CRC error."); + case PNG_CRC_ERROR_QUIT: /* error/quit */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* leave setting as is */ + break; + case PNG_CRC_WARN_USE: /* warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + case PNG_CRC_QUIET_USE: /* quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_ERROR_QUIT: /* error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + case PNG_CRC_WARN_DISCARD: /* warn/discard data */ + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* handle alpha and tRNS via a background color */ +void PNGAPI +png_set_background(png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_debug(1, "in png_set_background\n"); + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + png_memcpy(&(png_ptr->background), background_color, sizeof(png_color_16)); + png_ptr->background_gamma = (float)background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); + + /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA + * (in which case need_expand is superfluous anyway), the background color + * might actually be gray yet not be flagged as such. This is not a problem + * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to + * decide when to do the png_do_gray_to_rgb() transformation. + */ + if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) || + (!need_expand && background_color->red == background_color->green && + background_color->red == background_color->blue)) + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16\n"); + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha\n"); + png_ptr->transformations |= PNG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Dither file to 8 bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_dither" indicates + * whether we need a dithering cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_dither(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_uint_16p histogram, + int full_dither) +{ + png_debug(1, "in png_set_dither\n"); + png_ptr->transformations |= PNG_DITHER; + + if (!full_dither) + { + int i; + + png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * sizeof (png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->dither_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + Perhaps not the best solution, but good enough. */ + + int i; + png_bytep sort; + + /* initialize an array to sort colors */ + sort = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_palette + * sizeof (png_byte))); + + /* initialize the sort array */ + for (i = 0; i < num_palette; i++) + sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + bubble sort, and running it until we have sorted + out enough colors. Note that we don't care about + sorting all the colors, just finding which are + least used. */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* to stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[sort[j]] < histogram[sort[j + 1]]) + { + png_byte t; + + t = sort[j]; + sort[j] = sort[j + 1]; + sort[j + 1] = t; + done = 0; + } + } + if (done) + break; + } + + /* swap the palette around, and set up a table, if necessary */ + if (full_dither) + { + int j = num_palette; + + /* put all the useful colors within the max, but don't + move the others */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)sort[i] >= maximum_colors) + { + do + j--; + while ((int)sort[j] >= maximum_colors); + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* move all the used colors inside the max limit, and + develop a translation table */ + for (i = 0; i < maximum_colors; i++) + { + /* only move the colors we need to */ + if ((int)sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* indicate where the color went */ + png_ptr->dither_index[j] = (png_byte)i; + png_ptr->dither_index[i] = (png_byte)j; + } + } + + /* find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->dither_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* find the closest color to one we threw out */ + d_index = png_ptr->dither_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* point to closest color */ + png_ptr->dither_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, sort); + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + we need to go through a median cut routine, but those + don't always behave themselves with only a few colors + as input. So we will just find the closest two colors, + and throw out one of them (chosen somewhat randomly). + [We don't understand this at all, so if someone wants to + work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortpp hash; + png_bytep index_to_palette; + /* where the original index currently is in the palette */ + png_bytep palette_to_index; + /* which original index points to this palette color */ + + /* initialize palette index arrays */ + index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * sizeof (png_byte))); + palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * sizeof (png_byte))); + + /* initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + index_to_palette[i] = (png_byte)i; + palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * + sizeof (png_dsortp))); + for (i = 0; i < 769; i++) + hash[i] = NULL; +/* png_memset(hash, 0, 769 * sizeof (png_dsortp)); */ + + num_new_palette = num_palette; + + /* initial wild guess at how far apart the farthest pixel + pair we will be eliminating will be. Larger + numbers mean more areas will be allocated, Smaller + numbers run the risk of not saving enough data, and + having to do this all over again. + + I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + png_dsortp t; + + t = (png_dsortp)png_malloc(png_ptr, (png_uint_32)(sizeof + (png_dsort))); + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + } + + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)index_to_palette[p->left] < num_new_palette && + (int)index_to_palette[p->right] < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[index_to_palette[j]] = palette[num_new_palette]; + if (!full_dither) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->dither_index[k] == + index_to_palette[j]) + png_ptr->dither_index[k] = + index_to_palette[next_j]; + if ((int)png_ptr->dither_index[k] == + num_new_palette) + png_ptr->dither_index[k] = + index_to_palette[j]; + } + } + + index_to_palette[palette_to_index[num_new_palette]] = + index_to_palette[j]; + palette_to_index[index_to_palette[j]] = + palette_to_index[num_new_palette]; + + index_to_palette[j] = (png_byte)num_new_palette; + palette_to_index[num_new_palette] = (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + png_dsortp t; + + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, palette_to_index); + png_free(png_ptr, index_to_palette); + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_dither) + { + int i; + png_bytep distance; + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + + PNG_DITHER_BLUE_BITS; + int num_red = (1 << PNG_DITHER_RED_BITS); + int num_green = (1 << PNG_DITHER_GREEN_BITS); + int num_blue = (1 << PNG_DITHER_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, + (png_uint_32)(num_entries * sizeof (png_byte))); + + png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte)); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + sizeof(png_byte))); + + png_memset(distance, 0xff, num_entries * sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + int dr = abs(ir - r); + int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + int dg = abs(ig - g); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + int db = abs(ib - b); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) +/* Transform the image from the file_gamma to the screen_gamma. We + * only do transformations on images where the file_gamma and screen_gamma + * are not close reciprocals, otherwise it slows things down slightly, and + * also needlessly introduces small errors. + */ +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_debug(1, "in png_set_gamma\n"); + if (fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) + png_ptr->transformations |= PNG_GAMMA; + png_ptr->gamma = (float)file_gamma; + png_ptr->screen_gamma = (float)scrn_gamma; +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand\n"); + png_ptr->transformations |= PNG_EXPAND; +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb\n"); + png_ptr->transformations |= PNG_GRAY_TO_RGB; +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + int red_fixed = (int)((float)red*100000.0 + 0.5); + int green_fixed = (int)((float)green*100000.0 + 0.5); + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); +} +#endif + +void PNGAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray\n"); + switch(error_action) + { + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#if defined(PNG_READ_EXPAND_SUPPORTED) + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if(red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + else if(red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); + } +} +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn\n"); +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +#ifdef PNG_LEGACY_SUPPORTED + if(read_user_transform_fn) + png_warning(png_ptr, + "This version of libpng does not support user transforms"); +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if(png_ptr != NULL) +#endif + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ + || defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* expand background chunk. */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green = + png_ptr->background.blue = png_ptr->background.gray; + break; + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green = + png_ptr->background.blue = png_ptr->background.gray; + break; + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green = + png_ptr->background.blue = png_ptr->background.gray; + break; + case 8: + case 16: + png_ptr->background.red = png_ptr->background.green = + png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (!(png_ptr->transformations & PNG_EXPAND)) +#endif + { + /* invert the alpha channel (in tRNS) unless the pixels are + going to be expanded, in which case leave it for later */ + int i,istop; + istop=(int)png_ptr->num_trans; + for (i=0; i<istop; i++) + png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) + { + png_build_gamma_table(png_ptr); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + default: + g = 1.0; /* back_1 */ + gs = 1.0; /* back */ + } + + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + else + { + back.red = (png_byte)(pow( + (double)png_ptr->background.red/255, gs) * 255.0 + .5); + back.green = (png_byte)(pow( + (double)png_ptr->background.green/255, gs) * 255.0 + .5); + back.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, gs) * 255.0 + .5); + } + + back_1.red = (png_byte)(pow( + (double)png_ptr->background.red/255, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( + (double)png_ptr->background.green/255, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255, g) * 255.0 + .5); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + } + + if (color_type & PNG_COLOR_MASK_COLOR) + { + /* RGB or RGBA */ + png_ptr->background_1.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, gs) * m + .5); + } + else + { + /* GRAY or GRAY ALPHA */ + png_ptr->background_1.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, gs) * m + .5); + } + } + } + else + /* transformation does not include PNG_BACKGROUND */ +#endif + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + /* No GAMMA transformation */ + if ((png_ptr->transformations & PNG_BACKGROUND) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (png_ptr->trans[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + if (sg < 0 || sg > 8) + sg = 0; + if (sb < 0 || sb > 8) + sb = 0; + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif + } +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ + && !defined(PNG_READ_BACKGROUND_SUPPORTED) + if(png_ptr) + return; +#endif +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info\n"); +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; + } +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = png_ptr->gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_ptr->int_gamma; +#endif + } +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) + info_ptr->bit_depth = 8; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#if defined(PNG_READ_FILLER_SUPPORTED) + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; +#if 0 /* if adding a true alpha channel not just filler */ + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; +#endif + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if(png_ptr->transformations & PNG_USER_TRANSFORM) + { + if(info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + if(info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3); + +#if !defined(PNG_READ_EXPAND_SUPPORTED) + if(png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations\n"); +#if !defined(PNG_USELESS_TESTS_SUPPORTED) + if (png_ptr->row_buf == NULL) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + + sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); +#else + png_error(png_ptr, "NULL row buffer"); +#endif + } +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values)); + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_STRIP_ALPHA) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); + if(rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* +From Andreas Dilger e-mail to png-implement, 26 March 1998: + + In most cases, the "simple transparency" should be done prior to doing + gray-to-RGB, or you will have to test 3x as many bytes to check if a + pixel is transparent. You would also need to make sure that the + transparency information is upgraded to RGB. + + To summarize, the current flow is: + - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + with background "in place" if transparent, + convert to RGB if necessary + - Gray + alpha -> composite with gray background and remove alpha bytes, + convert to RGB if necessary + + To support RGB backgrounds for gray images we need: + - Gray + simple transparency -> convert to RGB + simple transparency, compare + 3 or 6 bytes and composite with background + "in place" if transparent (3x compare/pixel + compared to doing composite with gray bkgrnd) + - Gray + alpha -> convert to RGB + alpha, composite with background and + remove alpha bytes (3x float operations/pixel + compared with composite on gray background) + + Greg's change will do this. The reason it wasn't done before is for + performance, as this increases the per-pixel operations. If we would check + in advance if the background was gray or RGB, and position the gray-to-RGB + transform appropriately, then it would save a lot of work/time. + */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* if gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if ((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0 ) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_values), &(png_ptr->background), + &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) + if ((png_ptr->transformations & PNG_GAMMA) && +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + if (png_ptr->transformations & PNG_DITHER) + { + png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->dither_index); + if(png_ptr->row_info.rowbytes == (png_uint_32)0) + png_error(png_ptr, "png_do_dither returned rowbytes=0"); + } +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* if gray -> RGB, do so now only if we did not do so above */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if(png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* user read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if(png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if(png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + png_ptr->row_info.rowbytes = (png_ptr->row_info.width * + png_ptr->row_info.pixel_depth+7)>>3; + } +#endif + +} + +#if defined(PNG_READ_PACK_SUPPORTED) +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth < 8) +#else + if (row_info->bit_depth < 8) +#endif + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && sig_bits != NULL && +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + case 2: + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + case 4: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && row_info->bit_depth == 16) +#else + if (row_info->bit_depth == 16) +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i<istop; i++, sp += 2, dp++) + { +#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED) + /* This does a more accurate scaling of the 16-bit color + * value, rather than a simple low-byte truncation. + * + * What the ideal calculation should be: + * *dp = (((((png_uint_32)(*sp) << 8) | + * (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L; + * + * GRR: no, I think this is what it really should be: + * *dp = (((((png_uint_32)(*sp) << 8) | + * (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L; + * + * GRR: here's the exact calculation with shifts: + * temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L; + * *dp = (temp - (temp >> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_invert_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } + } + } +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if(row_info->bit_depth == 8) + { + /* This changes the data from G to GX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from G to XG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + else if(row_info->bit_depth == 16) + { + /* This changes the data from GG to GGXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from GG to XXGG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if(row_info->bit_depth == 8) + { + /* This changes the data from RGB to RGBX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from RGB to XRGB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if(row_info->bit_depth == 16) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + /* This changes the data from RRGGBB to XXRRGGBB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } + } /* COLOR_TYPE == RGB */ +} +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb\n"); + if (row_info->bit_depth >= 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = ((row_width * + row_info->pixel_depth + 7) >> 3); + } +} +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * <http://www.inforamp.net/~poynton/> + * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red+gc*green+bc*blue)>>15]; + } + else + *(dp++) = *(sp-1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); + } + else + *(dp++) = *(sp-1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = (png_byte)((gc*red + gc*green + bc*blue)>>8); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= (png_byte)2; + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = ((row_width * + row_info->pixel_depth + 7) >> 3); + } + return rgb_error; +} +#endif + +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. + */ +void /* PRIVATE */ +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette\n"); + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + case 2: + num_palette = 4; + color_inc = 0x55; + break; + case 4: + num_palette = 16; + color_inc = 0x11; + break; + case 8: + num_palette = 256; + color_inc = 1; + break; + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + +/* This function is currently unused. Do we really need it? */ +#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) +void /* PRIVATE */ +png_correct_palette(png_structp png_ptr, png_colorp palette, + int num_palette) +{ + png_debug(1, "in png_correct_palette\n"); +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) + { + png_color back, back_1; + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g; + + g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); + + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || + fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = png_ptr->background.red; + back.green = png_ptr->background.green; + back.blue = png_ptr->background.blue; + } + else + { + back.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + g = 1.0 / png_ptr->background_gamma; + + back_1.red = + (png_byte)(pow((double)png_ptr->background.red/255, g) * + 255.0 + 0.5); + back_1.green = + (png_byte)(pow((double)png_ptr->background.green/255, g) * + 255.0 + 0.5); + back_1.blue = + (png_byte)(pow((double)png_ptr->background.blue/255, g) * + 255.0 + 0.5); + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_uint_32 i; + + for (i = 0; i < (png_uint_32)num_palette; i++) + { + if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) + { + palette[i] = back; + } + else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) + { + png_byte v, w; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; + png_composite(w, v, png_ptr->trans[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; + png_composite(w, v, png_ptr->trans[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; + png_composite(w, v, png_ptr->trans[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + else + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (palette[i].red == (png_byte)png_ptr->trans_values.gray) + { + palette[i] = back; + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + } + } + else +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + { + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + else +#endif +#endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_color back; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < (int)png_ptr->num_trans; i++) + { + if (png_ptr->trans[i] == 0) + { + palette[i].red = back.red; + palette[i].green = back.green; + palette[i].blue = back.blue; + } + else if (png_ptr->trans[i] != 0xff) + { + png_composite(palette[i].red, png_ptr->palette[i].red, + png_ptr->trans[i], back.red); + png_composite(palette[i].green, png_ptr->palette[i].green, + png_ptr->trans[i], back.green); + png_composite(palette[i].blue, png_ptr->palette[i].blue, + png_ptr->trans[i], back.blue); + } + } + } + else /* assume grayscale palette (what else could it be?) */ + { + int i; + + for (i = 0; i < num_palette; i++) + { + if (i == (png_byte)png_ptr->trans_values.gray) + { + palette[i].red = (png_byte)png_ptr->background.red; + palette[i].green = (png_byte)png_ptr->background.green; + palette[i].blue = (png_byte)png_ptr->background.blue; + } + } + } + } +#endif +} +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_background(png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + int shift; + + png_debug(1, "in png_do_background\n"); + if (background != NULL && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_values->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 7; + sp++; + } + else + shift--; + } + break; + } + case 2: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + break; + } + case 4: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + break; + } + case 8: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + else + { + *sp = gamma_table[*sp]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_values->gray) + { + *sp = (png_byte)background->gray; + } + } + } + break; + } + case 16: + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + /* background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_values->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + } + break; + } + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_values->red && + *(sp + 1) == trans_values->green && + *(sp + 2) == trans_values->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + /* background is already in screen gamma */ + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + + if (r == trans_values->red && g == trans_values->green && + b == trans_values->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); + + if (a == 0xff) + { + *dp = *sp; + } + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_composite(*dp, *sp, a, background_1->gray); + } + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 2); + } + else if (a == 0) + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + /* background is already in screen gamma */ + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v, w, x; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = ((row_width * + row_info->pixel_depth + 7) >> 3); + } + } +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift) +{ + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + ((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + } + } +} +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_colorp palette, png_bytep trans, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift += 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + switch (row_info->bit_depth) + { + case 8: + { + if (trans != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + break; + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the + * transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)(gray*0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + case 2: + { + gray = (png_uint_16)(gray*0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + case 4: + { + gray = (png_uint_16)(gray*0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (((png_uint_16)*(sp) | + ((png_uint_16)*(sp - 1) << 8)) == gray) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = + ((row_width * row_info->pixel_depth) >> 3); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == trans_value->red && + *(sp - 1) == trans_value->green && + *(sp - 0) == trans_value->blue) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if ((((png_uint_16)*(sp - 4) | + ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) && + (((png_uint_16)*(sp - 2) | + ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) && + (((png_uint_16)*(sp - 0) | + ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue)) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = + ((row_width * row_info->pixel_depth) >> 3); + } + } +} +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +void /* PRIVATE */ +png_do_dither(png_row_infop row_info, png_bytep row, + png_bytep palette_lookup, png_bytep dither_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_dither\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + palette_lookup && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* this looks real messy, but the compiler will reduce + it down to a reasonable formula. For example, with + 5 bits per color, we get: + p = (((r >> 3) & 0x1f) << 10) | + (((g >> 3) & 0x1f) << 5) | + ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = + ((row_width * row_info->pixel_depth + 7) >> 3); + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_DITHER_RED_BITS)) & + ((1 << PNG_DITHER_RED_BITS) - 1)) << + (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | + (((g >> (8 - PNG_DITHER_GREEN_BITS)) & + ((1 << PNG_DITHER_GREEN_BITS) - 1)) << + (PNG_DITHER_BLUE_BITS)) | + ((b >> (8 - PNG_DITHER_BLUE_BITS)) & + ((1 << PNG_DITHER_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = + ((row_width * row_info->pixel_depth + 7) >> 3); + } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + dither_lookup && row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + *sp = dither_lookup[*sp]; + } + } + } +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +#if defined(PNG_READ_GAMMA_SUPPORTED) +static int png_gamma_shift[] = + {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0}; + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr) +{ + png_debug(1, "in png_build_gamma_table\n"); + if(png_ptr->gamma != 0.0) + { + if (png_ptr->bit_depth <= 8) + { + int i; + double g; + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + + + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + else + { + double g; + int i, j, shift, num; + int sig_bit; + png_uint_32 ig; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = (int)png_ptr->sig_bit.red; + if ((int)png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + if ((int)png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + { + sig_bit = (int)png_ptr->sig_bit.gray; + } + + if (sig_bit > 0) + shift = 16 - sig_bit; + else + shift = 0; + + if (png_ptr->transformations & PNG_16_TO_8) + { + if (shift < (16 - PNG_MAX_GAMMA_8)) + shift = (16 - PNG_MAX_GAMMA_8); + } + + if (shift > 8) + shift = 8; + if (shift < 0) + shift = 0; + + png_ptr->gamma_shift = (png_byte)shift; + + num = (1 << (8 - shift)); + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * sizeof (png_uint_16p))); + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + { + double fin, fout; + png_uint_32 last, max; + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * sizeof (png_uint_16))); + } + + g = 1.0 / g; + last = 0; + for (i = 0; i < 256; i++) + { + fout = ((double)i + 0.5) / 256.0; + fin = pow(fout, g); + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); + while (last <= max) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)( + (png_uint_16)i | ((png_uint_16)i << 8)); + last++; + } + } + while (last < ((png_uint_32)num << 8)) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; + last++; + } + } + else + { + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * sizeof (png_uint_16))); + + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_table[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * sizeof (png_uint_16p ))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * sizeof (png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_to_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ + + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, + (png_uint_32)(num * sizeof (png_uint_16p))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * sizeof (png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_from_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + } +} +#endif +/* To do: install integer version of png_build_gamma_table here */ +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0=*(rp )<<8 | *(rp+1); + png_uint_32 s1=*(rp+2)<<8 | *(rp+3); + png_uint_32 s2=*(rp+4)<<8 | *(rp+5); + png_uint_32 red=(65536+s0+s1)&0xffff; + png_uint_32 blue=(65536+s2+s1)&0xffff; + *(rp ) = (png_byte)((red>>8)&0xff); + *(rp+1) = (png_byte)(red&0xff); + *(rp+4) = (png_byte)((blue>>8)&0xff); + *(rp+5) = (png_byte)(blue&0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ diff --git a/Utilities/vtkpng/pngrutil.c b/Utilities/vtkpng/pngrutil.c new file mode 100644 index 0000000..ec970ce --- /dev/null +++ b/Utilities/vtkpng/pngrutil.c @@ -0,0 +1,3000 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(_WIN32_WCE) +/* strtod() function is not supported on WindowsCE */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +__inline double strtod(const char *nptr, char **endptr) +{ + double result = 0; + int len; + wchar_t *str, *end; + + len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); + str = (wchar_t *)malloc(len * sizeof(wchar_t)); + if ( NULL != str ) + { + MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); + result = wcstod(str, &end); + len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); + *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); + free(str); + } + return result; +} +# endif +#endif + +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 /* PRIVATE */ +png_get_uint_32(png_bytep buf) +{ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); + + return (i); +} + +#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED) +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format, and it is + * assumed that the machine format for signed integers is the same. */ +png_int_32 /* PRIVATE */ +png_get_int_32(png_bytep buf) +{ + png_int_32 i = ((png_int_32)(*buf) << 24) + + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); + + return (i); +} +#endif /* PNG_READ_pCAL_SUPPORTED */ + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 /* PRIVATE */ +png_get_uint_16(png_bytep buf) +{ + png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + + (png_uint_16)(*(buf + 1))); + + return (i); +} +#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + are reading a ancillary or critical chunk, and how the program has set + things up, we may calculate the CRC on the data and print a message. + Returns '1' if there was a CRC error, '0' otherwise. */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + else + { + png_chunk_error(png_ptr, "CRC error"); + } + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + the data it has read thus far. */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_SUPPORTED) +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +png_charp /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + static char msg[] = "Error decoding compressed text"; + png_charp text = NULL; + png_size_t text_size; + + if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + int ret = Z_OK; + png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); + png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + text_size = 0; + text = NULL; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_warning(png_ptr, png_ptr->zstream.msg); + else + png_warning(png_ptr, msg); + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (text == NULL) + { + text_size = prefix_size + sizeof(msg) + 1; + text = (png_charp)png_malloc(png_ptr, text_size); + png_memcpy(text, chunkdata, prefix_size); + } + + text[text_size - 1] = 0x00; + + /* Copy what we can of the error message into the text chunk */ + text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); + text_size = sizeof(msg) > text_size ? text_size : sizeof(msg); + png_memcpy(text + prefix_size, msg, text_size + 1); + break; + } + if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) + { + if (text == NULL) + { + text_size = prefix_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out; + text = (png_charp)png_malloc(png_ptr, text_size + 1); + png_memcpy(text + prefix_size, png_ptr->zbuf, + text_size - prefix_size); + png_memcpy(text, chunkdata, prefix_size); + *(text + text_size) = 0x00; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, (png_uint_32)(text_size + + png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + png_memcpy(text + text_size, png_ptr->zbuf, + (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = 0x00; + } + if (ret == Z_STREAM_END) + break; + else + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + } + if (ret != Z_STREAM_END) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[50]; + + if (ret == Z_BUF_ERROR) + sprintf(umsg,"Buffer error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else if (ret == Z_DATA_ERROR) + sprintf(umsg,"Data error in compressed datastream in %s chunk", + png_ptr->chunk_name); + else + sprintf(umsg,"Incomplete compressed datastream in %s chunk", + png_ptr->chunk_name); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, + "Incomplete compressed datastream in chunk other than IDAT"); +#endif + text_size=prefix_size; + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, text_size+1); + png_memcpy(text, chunkdata, prefix_size); + } + *(text + text_size) = 0x00; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + png_free(png_ptr, chunkdata); + chunkdata = text; + *newlength=text_size; + } + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char umsg[50]; + + sprintf(umsg, "Unknown zTXt compression type %d", comp_type); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, "Unknown zTXt compression type"); +#endif + + *(chunkdata + prefix_size) = 0x00; + *newlength=prefix_size; + } + + return chunkdata; +} +#endif + +/* read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR\n"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_32(buf); + height = png_get_uint_32(buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + + /* set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + + /* find number of channels */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = ((png_ptr->width * + (png_uint_32)png_ptr->pixel_depth + 7) >> 3); + png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth); + png_debug1(3,"channels = %d\n", png_ptr->channels); + png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifndef PNG_NO_POINTER_INDEXING + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually NEED the PLTE chunk (ie for a paletted image), we do + whatever the normal CRC configuration tells us. However, if we + have an RGB image, the PLTE can be considered ancillary, so + we will act as though it is. */ +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } +#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + we have two options: an error abort, or a warning and we + ignore the data in this chunk (which should be OK, since + it's considered ancillary for a RGB or RGBA image). */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_error(png_ptr, "CRC error"); + } + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#if defined(PNG_READ_tRNS_SUPPORTED) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + + info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */ + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + png_crc_finish(png_ptr, length); +} + +#if defined(PNG_READ_gAMA_SUPPORTED) +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = (png_fixed_point)png_get_uint_32(buf); + /* check for zero gamma */ + if (igamma == 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } + +#if defined(PNG_READ_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + if(igamma < 45000L || igamma > 46000L) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO + fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma); +#endif + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float)igamma / (float)100000.0; +# ifdef PNG_READ_GAMMA_SUPPORTED + png_ptr->gamma = file_gamma; +# endif + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +#endif +} +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT\n"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[4]; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue; + + png_debug(1, "in png_handle_cHRM\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +#if defined(PNG_READ_sRGB_SUPPORTED) + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + int_x_white = (png_fixed_point)png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + int_y_white = (png_fixed_point)png_get_uint_32(buf); + + if (int_x_white > 80000L || int_y_white > 80000L || + int_x_white + int_y_white > 100000L) + { + png_warning(png_ptr, "Invalid cHRM white point"); + png_crc_finish(png_ptr, 24); + return; + } + + png_crc_read(png_ptr, buf, 4); + int_x_red = (png_fixed_point)png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + int_y_red = (png_fixed_point)png_get_uint_32(buf); + + if (int_x_red > 80000L || int_y_red > 80000L || + int_x_red + int_y_red > 100000L) + { + png_warning(png_ptr, "Invalid cHRM red point"); + png_crc_finish(png_ptr, 16); + return; + } + + png_crc_read(png_ptr, buf, 4); + int_x_green = (png_fixed_point)png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + int_y_green = (png_fixed_point)png_get_uint_32(buf); + + if (int_x_green > 80000L || int_y_green > 80000L || + int_x_green + int_y_green > 100000L) + { + png_warning(png_ptr, "Invalid cHRM green point"); + png_crc_finish(png_ptr, 8); + return; + } + + png_crc_read(png_ptr, buf, 4); + int_x_blue = (png_fixed_point)png_get_uint_32(buf); + + png_crc_read(png_ptr, buf, 4); + int_y_blue = (png_fixed_point)png_get_uint_32(buf); + + if (int_x_blue > 80000L || int_y_blue > 80000L || + int_x_blue + int_y_blue > 100000L) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + png_crc_finish(png_ptr, 0); + return; + } +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float)int_x_white / (float)100000.0; + white_y = (float)int_y_white / (float)100000.0; + red_x = (float)int_x_red / (float)100000.0; + red_y = (float)int_y_red / (float)100000.0; + green_x = (float)int_x_green / (float)100000.0; + green_y = (float)int_y_green / (float)100000.0; + blue_x = (float)int_x_blue / (float)100000.0; + blue_y = (float)int_y_blue / (float)100000.0; +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + { + if (abs(int_x_white - 31270L) > 1000 || + abs(int_y_white - 32900L) > 1000 || + abs( int_x_red - 64000L) > 1000 || + abs( int_y_red - 33000L) > 1000 || + abs(int_x_green - 30000L) > 1000 || + abs(int_y_green - 60000L) > 1000 || + abs( int_x_blue - 15000L) > 1000 || + abs( int_y_blue - 6000L) > 1000) + { + + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +#ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); +#else + fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + int_x_white, int_y_white, int_x_red, int_y_red); + fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + int_x_green, int_y_green, int_x_blue, int_y_blue); +#endif +#endif /* PNG_NO_CONSOLE_IO */ + } + png_crc_finish(png_ptr, 0); + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); +#endif + if (png_crc_finish(png_ptr, 0)) + return; +} +#endif + +#if defined(PNG_READ_sRGB_SUPPORTED) +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + /* check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if ((info_ptr->valid & PNG_INFO_gAMA)) + { + int igamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + igamma=(int)info_ptr->int_gamma; +#else +# ifdef PNG_FLOATING_POINT_SUPPORTED + igamma=(int)(info_ptr->gamma * 100000.); +# endif +#endif +#if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED) +/* We need to define these here because they aren't in png.h */ + png_fixed_point int_x_white; + png_fixed_point int_y_white; + png_fixed_point int_x_red; + png_fixed_point int_y_red; + png_fixed_point int_x_green; + png_fixed_point int_y_green; + png_fixed_point int_x_blue; + png_fixed_point int_y_blue; +#endif + if(igamma < 45000L || igamma > 46000L) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifndef PNG_NO_CONSOLE_IO +# ifdef PNG_FIXED_POINT_SUPPORTED + fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma); +# else +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma); +# endif +# endif +#endif + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED +#ifdef PNG_FIXED_POINT_SUPPORTED + if (info_ptr->valid & PNG_INFO_cHRM) + if (abs(info_ptr->int_x_white - 31270L) > 1000 || + abs(info_ptr->int_y_white - 32900L) > 1000 || + abs( info_ptr->int_x_red - 64000L) > 1000 || + abs( info_ptr->int_y_red - 33000L) > 1000 || + abs(info_ptr->int_x_green - 30000L) > 1000 || + abs(info_ptr->int_y_green - 60000L) > 1000 || + abs( info_ptr->int_x_blue - 15000L) > 1000 || + abs( info_ptr->int_y_blue - 6000L) > 1000) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#if defined(PNG_READ_iCCP_SUPPORTED) +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_charp chunkdata; + png_byte compression_type; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size = 0; + png_uint_32 profile_length = 0; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (profile = chunkdata; *profile; profile++) + /* empty loop to find end of name */ ; + + ++profile; + + /* there should be at least one zero (the compression type byte) + following the separator, and we should be on it */ + if ( profile >= chunkdata + slength) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* compression_type should always be zero */ + compression_type = *profile++; + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - chunkdata; + chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if ( profile_length < 4) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + profile_size = ((*(chunkdata+prefix_length))<<24) | + ((*(chunkdata+prefix_length+1))<<16) | + ((*(chunkdata+prefix_length+2))<< 8) | + ((*(chunkdata+prefix_length+3)) ); + + if(profile_size < profile_length) + profile_length = profile_size; + + if(profile_size > profile_length) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "Ignoring truncated iCCP profile.\n"); + return; + } + + png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type, + chunkdata + prefix_length, profile_length); + png_free(png_ptr, chunkdata); +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_sPLT_SUPPORTED) +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep chunkdata; + png_bytep entry_start; + png_sPLT_t new_palette; +#ifdef PNG_NO_POINTER_INDEXING + png_sPLT_entryp pp; +#endif + int data_length, entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + + png_debug(1, "in png_handle_sPLT\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + chunkdata = (png_bytep)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (entry_start = chunkdata; *entry_start; entry_start++) + /* empty loop to find end of name */ ; + ++entry_start; + + /* a sample depth should follow the separator, and we should be on it */ + if (entry_start > chunkdata + slength) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + data_length = (slength - (entry_start - chunkdata)); + + /* integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, chunkdata); + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + new_palette.nentries = data_length / entry_size; + new_palette.entries = (png_sPLT_entryp)png_malloc( + png_ptr, new_palette.nentries * sizeof(png_sPLT_entry)); + +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0; i < new_palette.nentries; i++) + { + png_sPLT_entryp pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* discard all chunk data except the name and stash that */ + new_palette.name = (png_charp)chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, chunkdata); + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_tRNS_SUPPORTED) +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + else if (length > (png_uint_32)png_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_values.red = png_get_uint_16(buf); + png_ptr->trans_values.green = png_get_uint_16(buf + 2); + png_ptr->trans_values.blue = png_get_uint_16(buf + 4); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[6]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_values.gray = png_get_uint_16(buf); + } + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_values)); +} +#endif + +#if defined(PNG_READ_bKGD_SUPPORTED) +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + if(info_ptr->num_palette) + { + if(buf[0] > info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); + } + else + { + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = (int)length / 2 ; + if (num != png_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +/* read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp purpose; + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n", + length + 1); + purpose = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)purpose, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, purpose); + return; + } + + purpose[slength] = 0x00; /* null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string\n"); + for (buf = purpose; *buf; buf++) + /* empty loop */ ; + + endptr = purpose + slength; + + /* We need to have at least 12 bytes after the purpose string + in order to get the parameter information. */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters\n"); + /* Check that we have the right number of parameters for known + equation types. */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, purpose); + return; + } + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array\n"); + params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams + *sizeof(png_charp))) ; + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d\n", i); + for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, purpose); + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, purpose); + png_free(png_ptr, params); +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +/* read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp buffer, ep; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double width, height; + png_charp vp; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp swidth, sheight; +#endif +#endif + png_size_t slength; + + png_debug(1, "in png_handle_sCAL\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n", + length + 1); + buffer = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)buffer, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, buffer); + return; + } + + buffer[slength] = 0x00; /* null terminate the last string */ + + ep = buffer + 1; /* skip unit byte */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + width = strtod(ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed width string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + swidth = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1); + png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + for (ep = buffer; *ep; ep++) + /* empty loop */ ; + ep++; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + height = strtod(ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed height string in sCAL chunk"); + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + sheight = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1); + png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); +#endif +#endif + + if (buffer + slength < ep +#ifdef PNG_FLOATING_POINT_SUPPORTED + || width <= 0. || height <= 0. +#endif + ) + { + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, buffer); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif + return; + } + + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight); +#endif +#endif + + png_free(png_ptr, buffer); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif +} +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + + png_debug(1, "in png_handle_tEXt\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + key = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)key, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, key); + return; + } + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + png_set_text(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); +} +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +/* note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp chunkdata; + png_charp text; + int comp_type; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt\n"); + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr,"zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (text = chunkdata; *text; text++) + /* empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text == chunkdata + slength) + { + comp_type = PNG_TEXT_COMPRESSION_NONE; + png_warning(png_ptr, "Zero length zTXt chunk"); + } + else + { + comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + text++; /* skip the compression_method byte */ + } + prefix_len = text - chunkdata; + + chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text)); + text_ptr->compression = comp_type; + text_ptr->key = chunkdata; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = chunkdata + prefix_len; + text_ptr->text_length = data_len; + + png_set_text(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, chunkdata); +} +#endif + +#if defined(PNG_READ_iTXt_SUPPORTED) +/* note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp chunkdata; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt\n"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr,"iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, chunkdata); + return; + } + + chunkdata[slength] = 0x00; + + for (lang = chunkdata; *lang; lang++) + /* empty loop */ ; + lang++; /* skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + translated keyword (possibly empty), and possibly some text after the + keyword */ + + if (lang >= chunkdata + slength) + { + comp_flag = PNG_TEXT_COMPRESSION_NONE; + png_warning(png_ptr, "Zero length iTXt chunk"); + } + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* empty loop */ ; + lang_key++; /* skip NUL separator */ + + for (text = lang_key; *text; text++) + /* empty loop */ ; + text++; /* skip NUL separator */ + + prefix_len = text - chunkdata; + + key=chunkdata; + if (comp_flag) + chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata, + (size_t)length, prefix_len, &data_len); + else + data_len=png_strlen(chunkdata + prefix_len); + text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text)); + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = chunkdata+(lang_key-key); + text_ptr->lang = chunkdata+(lang-key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = chunkdata; + text_ptr->text = chunkdata + prefix_len; + + png_set_text(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, chunkdata); +} +#endif + +/* This function is called when we haven't found a handler for a + chunk. If there isn't a problem with the chunk itself (ie bad + chunk name, CRC, or a critical chunk), the chunk is silently ignored + -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + case it will be saved away to be written out later. */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown\n"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + HANDLE_CHUNK_ALWAYS +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { + png_unknown_chunk chunk; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name); + chunk.data = (png_bytep)png_malloc(png_ptr, length); + chunk.size = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)chunk.data, length); +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) + if(png_ptr->read_user_chunk_fn != NULL) + { + /* callback to user unknown chunk handler */ + if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + } + } + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); + png_free(png_ptr, chunk.data); + } + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) + info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ + +#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name\n"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + row. This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined, + a zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ +#ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1,"in png_combine_row\n"); + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + (png_size_t)((png_ptr->width * + png_ptr->row_info.pixel_depth + 7) >> 3)); + } + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + } + } +} +#endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */ + +#ifdef PNG_READ_INTERLACING_SUPPORTED +#ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */ +/* OLD pre-1.0.9 interface: +void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations) + */ +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* offset to next interlace block */ + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1,"in png_do_read_interlace (stock C version)\n"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = ((final_width * + (png_uint_32)row_info->pixel_depth + 7) >> 3); + } +#if !defined(PNG_READ_PACKSWAP_SUPPORTED) + transformations = transformations; /* silence compiler warning */ +#endif +} +#endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */ +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +#ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row\n"); + png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + case PNG_FILTER_VALUE_SUB: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row=0; + break; + } +} +#endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */ + +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_debug(1, "in png_read_finish_row\n"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->irowbytes = ((png_ptr->iwidth * + (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; + } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; + } while (png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + for(;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_32(chunk_length); + + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + png_error(png_ptr, "Extra compressed data"); + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_error(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_uint_32 row_bytes; + + png_debug(1, "in png_read_start_row\n"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + row_bytes = ((png_ptr->iwidth * + (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1; + png_ptr->irowbytes = (png_size_t)row_bytes; + if((png_uint_32)png_ptr->irowbytes != row_bytes) + png_error(png_ptr, "Rowbytes overflow in png_read_start_row"); + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + png_ptr->irowbytes = png_ptr->rowbytes + 1; + } + max_pixel_depth = png_ptr->pixel_depth; + +#if defined(PNG_READ_PACK_SUPPORTED) + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + else + max_pixel_depth = 32; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + } +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#if defined(PNG_READ_EXPAND_SUPPORTED) + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#if defined(PNG_READ_FILLER_SUPPORTED) + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if(png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth=png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + if(user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* align the width on the next larger 8 pixels. Mainly used + for interlacing */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* calculate the maximum bytes needed, adding a byte and a pixel + for safety's sake */ + row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) + + 1 + ((max_pixel_depth + 7) >> 3); +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes); +#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD) + png_ptr->row_buf_size = row_bytes; +#endif + +#ifdef PNG_MAX_MALLOC_64K + if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( + png_ptr->rowbytes + 1)); + + png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %lu,\n", png_ptr->width); + png_debug1(3, "height = %lu,\n", png_ptr->height); + png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth); + png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} diff --git a/Utilities/vtkpng/pngset.c b/Utilities/vtkpng/pngset.c new file mode 100644 index 0000000..ddc4d0c --- /dev/null +++ b/Utilities/vtkpng/pngset.c @@ -0,0 +1,972 @@ + +/* pngset.c - storage of image information into info struct + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_bKGD_SUPPORTED) +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) +{ + png_debug1(1, "in %s storage function\n", "bKGD"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_debug1(1, "in %s storage function\n", "cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_white = (float)white_x; + info_ptr->y_white = (float)white_y; + info_ptr->x_red = (float)red_x; + info_ptr->y_red = (float)red_y; + info_ptr->x_green = (float)green_x; + info_ptr->y_green = (float)green_y; + info_ptr->x_blue = (float)blue_x; + info_ptr->y_blue = (float)blue_y; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); + info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); + info_ptr->int_x_red = (png_fixed_point)(red_x*100000.+0.5); + info_ptr->int_y_red = (png_fixed_point)(red_y*100000.+0.5); + info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); + info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); + info_ptr->int_x_blue = (png_fixed_point)(blue_x*100000.+0.5); + info_ptr->int_y_blue = (png_fixed_point)(blue_y*100000.+0.5); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function\n", "cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->int_x_white = white_x; + info_ptr->int_y_white = white_y; + info_ptr->int_x_red = red_x; + info_ptr->int_y_red = red_y; + info_ptr->int_x_green = green_x; + info_ptr->int_y_green = green_y; + info_ptr->int_x_blue = blue_x; + info_ptr->int_y_blue = blue_y; +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->x_white = (float)(white_x/100000.); + info_ptr->y_white = (float)(white_y/100000.); + info_ptr->x_red = (float)(red_x/100000.); + info_ptr->y_red = (float)(red_y/100000.); + info_ptr->x_green = (float)(green_x/100000.); + info_ptr->y_green = (float)(green_y/100000.); + info_ptr->x_blue = (float)(blue_x/100000.); + info_ptr->y_blue = (float)(blue_y/100000.); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + png_debug1(1, "in %s storage function\n", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->gamma = (float)file_gamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = (int)(file_gamma*100000.+.5); +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if(file_gamma == 0.0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif +void PNGAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + int_gamma) +{ + png_debug1(1, "in %s storage function\n", "gAMA"); + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = (float)(int_gamma/100000.); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = int_gamma; +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if(int_gamma == 0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif + +#if defined(PNG_hIST_SUPPORTED) +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function\n", "hIST"); + if (png_ptr == NULL || info_ptr == NULL) + return; + if (info_ptr->num_palette == 0) + { + png_warning(png_ptr, + "Palette size 0, hIST allocation skipped."); + return; + } + +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); +#endif + png_ptr->hist = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(info_ptr->num_palette * sizeof (png_uint_16))); + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_HIST; +#else + png_ptr->flags |= PNG_FLAG_FREE_HIST; +#endif +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int rowbytes_per_pixel; + png_debug1(1, "in %s storage function\n", "IHDR"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* check for width and height valid values */ + if (width == 0 || height == 0) + png_error(png_ptr, "Image width or height is zero in IHDR"); + if (width > PNG_MAX_UINT || height > PNG_MAX_UINT) + png_error(png_ptr, "Invalid image size in IHDR"); + + /* check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth in IHDR"); + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + png_error(png_ptr, "Invalid color type in IHDR"); + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); + + if (interlace_type >= PNG_INTERLACE_LAST) + png_error(png_ptr, "Unknown interlace method in IHDR"); + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_error(png_ptr, "Unknown compression method in IHDR"); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n"); + if(filter_type != PNG_FILTER_TYPE_BASE) + { + if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + png_error(png_ptr, "Unknown filter method in IHDR"); + if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) + png_warning(png_ptr, "Invalid filter method in IHDR"); + } +#else + if(filter_type != PNG_FILTER_TYPE_BASE) + png_error(png_ptr, "Unknown filter method in IHDR"); +#endif + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type =(png_byte) color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* check for overflow */ + rowbytes_per_pixel = (info_ptr->pixel_depth + 7) >> 3; + if (( width > PNG_MAX_UINT/rowbytes_per_pixel)) + { + png_warning(png_ptr, + "Width too large to process image data; rowbytes will overflow."); + info_ptr->rowbytes = (png_size_t)0; + } + else + info_ptr->rowbytes = (info_ptr->width * info_ptr->pixel_depth + 7) >> 3; +} + +#if defined(PNG_oFFs_SUPPORTED) +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function\n", "oFFs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#if defined(PNG_pCAL_SUPPORTED) +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params) +{ + png_uint_32 length; + int i; + + png_debug1(1, "in %s storage function\n", "pCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)\n", length); + info_ptr->pcal_purpose = (png_charp)png_malloc(png_ptr, length); + png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); + + png_debug(3, "storing X0, X1, type, and nparams in info\n"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)\n", length); + info_ptr->pcal_units = (png_charp)png_malloc(png_ptr, length); + png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); + + info_ptr->pcal_params = (png_charpp)png_malloc(png_ptr, + (png_uint_32)((nparams + 1) * sizeof(png_charp))); + + info_ptr->pcal_params[nparams] = NULL; + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length); + info_ptr->pcal_params[i] = (png_charp)png_malloc(png_ptr, length); + png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); + } + + info_ptr->valid |= PNG_INFO_pCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PCAL; +#endif +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height) +{ + png_debug1(1, "in %s storage function\n", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + info_ptr->scal_pixel_width = width; + info_ptr->scal_pixel_height = height; + + info_ptr->valid |= PNG_INFO_sCAL; +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_charp swidth, png_charp sheight) +{ + png_uint_32 length; + + png_debug1(1, "in %s storage function\n", "sCAL"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + + length = png_strlen(swidth) + 1; + png_debug1(3, "allocating unit for info (%d bytes)\n", length); + info_ptr->scal_s_width = (png_charp)png_malloc(png_ptr, length); + png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); + + length = png_strlen(sheight) + 1; + png_debug1(3, "allocating unit for info (%d bytes)\n", length); + info_ptr->scal_s_height = (png_charp)png_malloc(png_ptr, length); + png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); + + info_ptr->valid |= PNG_INFO_sCAL; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SCAL; +#endif +} +#endif +#endif +#endif + +#if defined(PNG_pHYs_SUPPORTED) +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function\n", "pHYs"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function\n", "PLTE"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* + * It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); +#endif + png_ptr->palette = (png_colorp)png_zalloc(png_ptr, (uInt)num_palette, + sizeof (png_color)); + png_memcpy(png_ptr->palette, palette, num_palette * sizeof (png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_PLTE; +#else + png_ptr->flags |= PNG_FLAG_FREE_PLTE; +#endif + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#if defined(PNG_sBIT_SUPPORTED) +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function\n", "sBIT"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, sizeof (png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#if defined(PNG_sRGB_SUPPORTED) +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) +{ + png_debug1(1, "in %s storage function\n", "sRGB"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int intent) +{ +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_file_gamma; +#endif +#endif +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y; +#endif +#endif + png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, intent); + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float).45455; + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + int_file_gamma = 45455L; + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FIXED_POINT_SUPPORTED + int_white_x = 31270L; + int_white_y = 32900L; + int_red_x = 64000L; + int_red_y = 33000L; + int_green_x = 30000L; + int_green_y = 60000L; + int_blue_x = 15000L; + int_blue_y = 6000L; + + png_set_cHRM_fixed(png_ptr, info_ptr, + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, + int_blue_x, int_blue_y); +#endif +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float).3127; + white_y = (float).3290; + red_x = (float).64; + red_y = (float).33; + green_x = (float).30; + green_y = (float).60; + blue_x = (float).15; + blue_y = (float).06; + + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#endif +} +#endif + + +#if defined(PNG_iCCP_SUPPORTED) +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_charp new_iccp_profile; + + png_debug1(1, "in %s storage function\n", "iCCP"); + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + new_iccp_name = (png_charp)png_malloc(png_ptr, png_strlen(name)+1); + png_strcpy(new_iccp_name, name); + new_iccp_profile = (png_charp)png_malloc(png_ptr, proflen); + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types */ + info_ptr->iccp_compression = (png_byte)compression_type; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_ICCP; +#endif + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#if defined(PNG_TEXT_SUPPORTED) +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int i; + + png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return; + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc(png_ptr, + (png_uint_32)(info_ptr->max_text * sizeof (png_text))); + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + sizeof(png_text))); + png_free(png_ptr, old_text); + } + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc(png_ptr, + (png_uint_32)(info_ptr->max_text * sizeof (png_text))); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TEXT; +#endif + } + png_debug1(3, "allocated %d entries for info_ptr->text\n", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length,key_len; + png_size_t lang_len,lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + key_len = png_strlen(text_ptr[i].key); + + if(text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + else +#ifdef PNG_iTXt_SUPPORTED + { + /* set iTXt data */ + if (text_ptr[i].key != NULL) + lang_len = png_strlen(text_ptr[i].lang); + else + lang_len = 0; + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + else + lang_key_len = 0; + } +#else + { + png_warning(png_ptr, "iTXt chunk not supported."); + continue; + } +#endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +#ifdef PNG_iTXt_SUPPORTED + if(text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + else +#endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc(png_ptr, + (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", + (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), + (int)textp->key); + + png_memcpy(textp->key, text_ptr[i].key, + (png_size_t)(key_len)); + *(textp->key+key_len) = '\0'; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + { + textp->lang=textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang+lang_len) = '\0'; + textp->lang_key=textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key+lang_key_len) = '\0'; + textp->text=textp->lang_key + lang_key_len + 1; + } + else +#endif + { +#ifdef PNG_iTXt_SUPPORTED + textp->lang=(png_charp)NULL; + textp->lang_key=(png_charp)NULL; +#endif + textp->text=textp->key + key_len + 1; + } + if(text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + *(textp->text+text_length) = '\0'; + +#ifdef PNG_iTXt_SUPPORTED + if(textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + else +#endif + { + textp->text_length = text_length; +#ifdef PNG_iTXt_SUPPORTED + textp->itxt_length = 0; +#endif + } + info_ptr->text[info_ptr->num_text]= *textp; + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); + } +} +#endif + +#if defined(PNG_tIME_SUPPORTED) +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) +{ + png_debug1(1, "in %s storage function\n", "tIME"); + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, sizeof (png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#if defined(PNG_tRNS_SUPPORTED) +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep trans, int num_trans, png_color_16p trans_values) +{ + png_debug1(1, "in %s storage function\n", "tRNS"); + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans != NULL) + { + /* + * It may not actually be necessary to set png_ptr->trans here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ +#ifdef PNG_FREE_ME_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); +#endif + png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, + num_trans); + png_memcpy(info_ptr->trans, trans, num_trans); +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_TRNS; +#else + png_ptr->flags |= PNG_FLAG_FREE_TRNS; +#endif + } + + if (trans_values != NULL) + { + png_memcpy(&(info_ptr->trans_values), trans_values, + sizeof(png_color_16)); + if (num_trans == 0) + num_trans = 1; + } + info_ptr->num_trans = (png_uint_16)num_trans; + info_ptr->valid |= PNG_INFO_tRNS; +} +#endif + +#if defined(PNG_sPLT_SUPPORTED) +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries) +{ + png_sPLT_tp np; + int i; + + np = (png_sPLT_tp)png_malloc(png_ptr, + (info_ptr->splt_palettes_num + nentries) * sizeof(png_sPLT_t)); + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_sPLT_tp from = entries + i; + + to->name = (png_charp)png_malloc(png_ptr, + png_strlen(from->name) + 1); + png_strcpy(to->name, from->name); + to->entries = (png_sPLT_entryp)png_malloc(png_ptr, + from->nentries * sizeof(png_sPLT_t)); + png_memcpy(to->entries, from->entries, + from->nentries * sizeof(png_sPLT_t)); + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_SPLT; +#endif +} +#endif /* PNG_sPLT_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc(png_ptr, + (info_ptr->unknown_chunks_num + num_unknowns) * + sizeof(png_unknown_chunk)); + + png_memcpy(np, info_ptr->unknown_chunks, + info_ptr->unknown_chunks_num * sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks=NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_unknown_chunkp from = unknowns + i; + + png_strcpy((png_charp)to->name, (png_charp)from->name); + to->data = (png_bytep)png_malloc(png_ptr, from->size); + png_memcpy(to->data, from->data, from->size); + to->size = from->size; + + /* note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; +#ifdef PNG_FREE_ME_SUPPORTED + info_ptr->free_me |= PNG_FREE_UNKN; +#endif +} +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + (int)info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +void PNGAPI +png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) +{ + /* This function is deprecated in favor of png_permit_mng_features() + and will be removed from libpng-2.0.0 */ + png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n"); + if (png_ptr == NULL) + return; + png_ptr->mng_features_permitted = (png_byte) + ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) | + ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); +} +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features\n"); + if (png_ptr == NULL) + return (png_uint_32)0; + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (num_chunks == 0) + { + if(keep == HANDLE_CHUNK_ALWAYS || keep == HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if(keep == HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; + } + if (chunk_list == NULL) + return; + old_num_chunks=png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr,5*(num_chunks+old_num_chunks)); + if(png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + png_memcpy(new_list+5*old_num_chunks, chunk_list, 5*num_chunks); + for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5) + *p=(png_byte)keep; + png_ptr->num_chunk_list=old_num_chunks+num_chunks; + png_ptr->chunk_list=new_list; +#ifdef PNG_FREE_ME_SUPPORTED + png_ptr->free_me |= PNG_FREE_LIST; +#endif +} +#endif + +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn\n"); + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function\n", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + info_ptr->row_pointers = row_pointers; + if(row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size) +{ + if(png_ptr->zbuf) + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf_size = (png_size_t)size; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~(mask); +} + + diff --git a/Utilities/vtkpng/pngtest.c b/Utilities/vtkpng/pngtest.c new file mode 100644 index 0000000..9b954b3 --- /dev/null +++ b/Utilities/vtkpng/pngtest.c @@ -0,0 +1,1514 @@ + +/* pngtest.c - a simple test program to test libpng + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#if defined(_WIN32_WCE) +# if _WIN32_WCE < 211 + __error__ (f|w)printf functions are not supported on old WindowsCE.; +# endif +# include <windows.h> +# include <stdlib.h> +# define READFILE(file, data, length, check) \ + if (ReadFile(file, data, length, &check,NULL)) check = 0 +# define WRITEFILE(file, data, length, check)) \ + if (WriteFile(file, data, length, &check, NULL)) check = 0 +# define FCLOSE(file) CloseHandle(file) +#else +# include <stdio.h> +# include <stdlib.h> +# include <assert.h> +# define READFILE(file, data, length, check) \ + check=(png_size_t)fread(data,(png_size_t)1,length,file) +# define WRITEFILE(file, data, length, check) \ + check=(png_size_t)fwrite(data,(png_size_t)1, length, file) +# define FCLOSE(file) fclose(file) +#endif + +#if defined(PNG_NO_STDIO) +# if defined(_WIN32_WCE) + typedef HANDLE png_FILE_p; +# else + typedef FILE * png_FILE_p; +# endif +#endif + +/* Makes pngtest verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* makes buffer overruns easier to nail */ +#endif + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifdef PNG_NO_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include <time.h> +#endif + +#include "png.h" + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#if !defined(PNG_tIME_SUPPORTED) +#include <time.h> +#endif +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +static int tIME_chunk_present=0; +static char tIME_string[30] = "no tIME chunk present in file"; +#endif + +static int verbose = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include <mem.h> +#endif + +/* defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* for DOS */ + +/* example of using row callbacks to make a simple progress meter */ +static int status_pass=1; +static int status_dots_requested=0; +static int status_dots=1; + +void +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if(png_ptr == NULL || row_number > PNG_MAX_UINT) return; + if(status_pass != pass) + { + fprintf(stdout,"\n Pass %d: ",pass); + status_pass = pass; + status_dots = 31; + } + status_dots--; + if(status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + fprintf(stdout, "r"); +} + +void +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if(png_ptr == NULL || row_number > PNG_MAX_UINT || pass > 7) return; + fprintf(stdout, "w"); +} + + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) +/* Example of using user transform callback (we don't transform anything, + but merely examine the row filters. We set this to 256 rather than + 5 in case illegal filter values are present.) */ +static png_uint_32 filters_used[256]; +void +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if(png_ptr != NULL && row_info != NULL) + ++filters_used[*(data-1)]; +} +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +/* example of using user transform callback (we don't transform anything, + but merely count the zero samples) */ + +static png_uint_32 zero_samples; + +void +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if(png_ptr == NULL)return; + + /* contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + + /* counts the number of zero samples (or zero pixels if color_type is 3 */ + + if(row_info->color_type == 0 || row_info->color_type == 3) + { + int pos=0; + png_uint_32 n, nstop; + for (n=0, nstop=row_info->width; n<nstop; n++) + { + if(row_info->bit_depth == 1) + { + if(((*dp << pos++ ) & 0x80) == 0) zero_samples++; + if(pos == 8) + { + pos = 0; + dp++; + } + } + if(row_info->bit_depth == 2) + { + if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++; + if(pos == 8) + { + pos = 0; + dp++; + } + } + if(row_info->bit_depth == 4) + { + if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++; + if(pos == 8) + { + pos = 0; + dp++; + } + } + if(row_info->bit_depth == 8) + if(*dp++ == 0) zero_samples++; + if(row_info->bit_depth == 16) + { + if((*dp | *(dp+1)) == 0) zero_samples++; + dp+=2; + } + } + } + else /* other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if(row_info->color_type > 3)color_channels--; + + for (n=0, nstop=row_info->width; n<nstop; n++) + { + for (channel = 0; channel < color_channels; channel++) + { + if(row_info->bit_depth == 8) + if(*dp++ == 0) zero_samples++; + if(row_info->bit_depth == 16) + { + if((*dp | *(dp+1)) == 0) zero_samples++; + dp+=2; + } + } + if(row_info->color_type > 3) + { + dp++; + if(row_info->bit_depth == 16)dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +static int wrote_question = 0; + +#if defined(PNG_NO_STDIO) +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and */ +/* pngwio.c. They allow "don't include stdio" testing of the library. */ +/* This is the function that does the actual reading of data. If you are + not reading from a standard C stream, you should create a replacement + read_data function and use it at run time with png_set_read_fn(), rather + than changing the library. */ + +#ifndef USE_FAR_KEYWORD +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); + + if (check != length) + { + png_error(png_ptr, "Read Error!"); + } +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + int check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { + READFILE(io_ptr, n_data, length, check); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + READFILE(io_ptr, buf, 1, err); + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if(err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if (check != length) + { + png_error(png_ptr, "read Error"); + } +} +#endif /* USE_FAR_KEYWORD */ + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +static void +pngtest_flush(png_structp png_ptr) +{ +#if !defined(_WIN32_WCE) + png_FILE_p io_ptr; + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + if (io_ptr != NULL) + fflush(io_ptr); +#endif +} +#endif + +/* This is the function that does the actual writing of data. If you are + not writing to a standard C stream, you should create a replacement + write_data function and use it at run time with png_set_write_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { + WRITEFILE(io_ptr, near_data, length, check); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* copy far buffer to near buffer */ + WRITEFILE(io_ptr, buf, written, err); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} + +#endif /* USE_FAR_KEYWORD */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + if (png_ptr != NULL && png_ptr->error_ptr != NULL) + name = png_ptr->error_ptr; + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. */ +} +#endif /* PNG_NO_STDIO */ +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#ifdef PNG_USER_MEM_SUPPORTED + +/* Allocate memory. For reasonable files, size should never exceed + 64K. However, zlib may allocate more then 64K if you don't tell + it not to. See zconf.h and png.h for more information. zlib does + need to allocate exactly 64K, so whatever you call here must + have the ability to do that. + + This piece of code can be compiled to validate max 64K allocations + by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */ +typedef struct memory_information +{ + png_uint_32 size; + png_voidp pointer; + struct memory_information FAR *next; +} memory_information; +typedef memory_information FAR *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +extern PNG_EXPORT(png_voidp,png_debug_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)); +extern PNG_EXPORT(void,png_debug_free) PNGARG((png_structp png_ptr, + png_voidp ptr)); + +png_voidp +png_debug_malloc(png_structp png_ptr, png_uint_32 size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + png_debug_malloc directly, with png_ptr == NULL which is OK */ + + if (size == 0) + return (png_voidp)(NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + memory_infop pinfo = (memory_infop)png_malloc_default(png_ptr, + sizeof *pinfo); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + pinfo->pointer = (png_voidp)png_malloc_default(png_ptr, size); + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + png_memset(pinfo->pointer, 0xdd, pinfo->size); +#if PNG_DEBUG + if(verbose) + printf("png_malloc %d bytes at %x\n",size,pinfo->pointer); +#endif + assert(pinfo->size != 12345678); + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop FAR *ppinfo = &pinformation; + for (;;) + { + memory_infop pinfo = *ppinfo; + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + png_memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo=NULL; + break; + } + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", ptr); + break; + } + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ +#if PNG_DEBUG + if(verbose) + printf("Freeing %x\n",ptr); +#endif + png_free_default(png_ptr, ptr); + ptr=NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED */ +/* END of code to test memory allocation/deallocation */ + +/* Test one file */ +int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + +#if defined(_WIN32_WCE) + TCHAR path[MAX_PATH]; +#endif + char inbuf[256], outbuf[256]; + + row_buf = (png_bytep)NULL; + +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); + if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpin = fopen(inname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); + if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpout = fopen(outname, "wb")) == NULL) +#endif + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + png_debug(0, "Allocating read and write structures\n"); +#ifdef PNG_USER_MEM_SUPPORTED + read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL, + (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); +#else + read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + (png_error_ptr)NULL, (png_error_ptr)NULL); +#endif +#if defined(PNG_NO_STDIO) + png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_USER_MEM_SUPPORTED + write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + (png_error_ptr)NULL, (png_error_ptr)NULL, (png_voidp)NULL, + (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); +#else + write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + (png_error_ptr)NULL, (png_error_ptr)NULL); +#endif +#if defined(PNG_NO_STDIO) + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#endif + png_debug(0, "Allocating read_info, write_info and end_info structures\n"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_debug(0, "Setting jmpbuf for read struct\n"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(read_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(read_ptr),jmpbuf,sizeof(jmp_buf)); +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "Setting jmpbuf for write struct\n"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(write_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(write_ptr),jmpbuf,sizeof(jmp_buf)); +#endif +#endif +#endif + + png_debug(0, "Initializing input and output streams\n"); +#if !defined(PNG_NO_STDIO) + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# if defined(PNG_WRITE_FLUSH_SUPPORTED) + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + if(status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + { + int i; + for(i=0; i<256; i++) + filters_used[i]=0; + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + zero_samples=0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#define HANDLE_CHUNK_IF_SAFE 2 +#define HANDLE_CHUNK_ALWAYS 3 +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + png_set_keep_unknown_chunks(read_ptr, HANDLE_CHUNK_ALWAYS, NULL, 0); +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + png_set_keep_unknown_chunks(write_ptr, HANDLE_CHUNK_IF_SAFE, NULL, 0); +#endif + + png_debug(0, "Reading info struct\n"); + png_read_info(read_ptr, read_info_ptr); + + png_debug(0, "Transferring info struct\n"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#if defined(PNG_FIXED_POINT_SUPPORTED) +#if defined(PNG_cHRM_SUPPORTED) + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#if defined(PNG_gAMA_SUPPORTED) + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + { + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } + } +#endif +#else /* Use floating point versions */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) +#if defined(PNG_cHRM_SUPPORTED) + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#if defined(PNG_gAMA_SUPPORTED) + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + { + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } + } +#endif +#endif /* floating point */ +#endif /* fixed point */ +#if defined(PNG_iCCP_SUPPORTED) + { + png_charp name; + png_charp profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#if defined(PNG_sRGB_SUPPORTED) + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + { + png_set_sRGB(write_ptr, write_info_ptr, intent); + } + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + { + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } + } +#if defined(PNG_bKGD_SUPPORTED) + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#if defined(PNG_hIST_SUPPORTED) + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + { + png_set_hIST(write_ptr, write_info_ptr, hist); + } + } +#endif +#if defined(PNG_oFFs_SUPPORTED) + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#if defined(PNG_pCAL_SUPPORTED) + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#if defined(PNG_pHYs_SUPPORTED) + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + { + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } + } +#endif +#if defined(PNG_sBIT_SUPPORTED) + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + { + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } + } +#endif +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#endif +#endif +#endif +#if defined(PNG_TEXT_SUPPORTED) + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#if defined(PNG_tIME_SUPPORTED) + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#if defined(PNG_TIME_RFC1123_SUPPORTED) + /* we have to use png_strcpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time)); + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#if defined(PNG_tRNS_SUPPORTED) + { + png_bytep trans; + int num_trans; + png_color_16p trans_values; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, + &trans_values)) + { + png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, + trans_values); + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + { + png_unknown_chunkp unknowns; + int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + /* copy the locations from the read_info_ptr. The automatically + generated locations in write_info_ptr are wrong because we + haven't written anything yet */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "\nWriting info struct\n"); + +/* If we wanted, we could write info in two steps: + png_write_info_before_PLTE(write_ptr, write_info_ptr); + */ + png_write_info(write_ptr, write_info_ptr); +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(0, "\nAllocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(0, "Writing row data\n"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass=1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + png_debug1(0, "Writing row data for pass %d\n",pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, (png_bytepp)NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y); + png_free(read_ptr, row_buf); +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +#endif + + png_debug(0, "Reading and writing end_info data\n"); + + png_read_end(read_ptr, end_info_ptr); +#if defined(PNG_TEXT_SUPPORTED) + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#if defined(PNG_tIME_SUPPORTED) + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#if defined(PNG_TIME_RFC1123_SUPPORTED) + /* we have to use png_strcpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time)); + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + { + png_unknown_chunkp unknowns; + int num_unknowns; + num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + /* copy the locations from the read_info_ptr. The automatically + generated locations in write_end_info_ptr are wrong because we + haven't written the end_info yet */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, + unknowns[i].location); + } + } +#endif +#ifdef PNG_WRITE_SUPPORTED + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if(verbose) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "Image width = %lu, height = %lu\n", + iwidth, iheight); + } +#endif + + png_debug(0, "Destroying data structs\n"); +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(1, "destroying row_buf for read_ptr\n"); + png_free(read_ptr, row_buf); + row_buf=NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_debug(1, "destroying write_end_info_ptr\n"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_debug(1, "destroying write_ptr, write_info_ptr\n"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + png_debug(0, "Destruction complete.\n"); + + FCLOSE(fpin); + FCLOSE(fpout); + + png_debug(0, "Opening files for comparison\n"); +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); + if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpin = fopen(inname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + +#if defined(_WIN32_WCE) + MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); + if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) +#else + if ((fpout = fopen(outname, "rb")) == NULL) +#endif + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for(;;) + { + png_size_t num_in, num_out; + + READFILE(fpin, inbuf, 1, num_in); + READFILE(fpout, outbuf, 1, num_out); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + if(wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname,PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question=1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + + if (!num_in) + break; + + if (png_memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + if(wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname,PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question=1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + } + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR,"%s",png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR," library (%lu):%s", png_access_version_number(), + png_get_header_version(NULL)); + /* Show the version of libpng used in building the application */ + fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + fprintf(STDERR," sizeof(png_struct)=%d, sizeof(png_info)=%d\n", + sizeof(png_struct), sizeof(png_info)); + + /* Do some consistency checking on the memory allocation settings, I'm + not sure this matters, but it is nice to know, the first of these + tests should be impossible because of the way the macros are set + in pngconf.h */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3+verbose) + outname = argv[2+verbose]; + + if ((!multiple && argc > 3+verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#ifdef PNG_USER_MEM_SUPPORTED + int allocation_now = current_allocation; +#endif + for (i=2; i<argc; ++i) + { +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + int k; +#endif + int kerror; + fprintf(STDERR, "Testing %s:",argv[i]); + kerror = test_one_file(argv[i], outname); + if (kerror == 0) + { +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + for (k=0; k<256; k++) + if(filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k,filters_used[k]); +#endif +#if defined(PNG_TIME_RFC1123_SUPPORTED) + if(tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n",tIME_string); + tIME_chunk_present = 0; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + else + { + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#ifdef PNG_USER_MEM_SUPPORTED + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation-allocation_now); + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + while (pinfo != NULL) + { + fprintf(STDERR, " %d bytes at %x\n", pinfo->size, pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#ifdef PNG_USER_MEM_SUPPORTED + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + else + { + int i; + for (i=0; i<3; ++i) + { + int kerror; +#ifdef PNG_USER_MEM_SUPPORTED + int allocation_now = current_allocation; +#endif + if (i == 1) status_dots_requested = 1; + else if(verbose == 0)status_dots_requested = 0; + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "Testing %s:",inname); + kerror = test_one_file(inname, outname); + if(kerror == 0) + { + if(verbose == 1 || i == 2) + { +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + int k; +#endif +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + for (k=0; k<256; k++) + if(filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k,filters_used[k]); +#endif +#if defined(PNG_TIME_RFC1123_SUPPORTED) + if(tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n",tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + else + { + if(verbose == 0 && i != 2) + fprintf(STDERR, "Testing %s:",inname); + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#ifdef PNG_USER_MEM_SUPPORTED + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation-allocation_now); + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + while (pinfo != NULL) + { + fprintf(STDERR," %d bytes at %x\n", + pinfo->size, pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#ifdef PNG_USER_MEM_SUPPORTED + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR," CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR," (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR," encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR," other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, "libpng passes test\n"); + else + fprintf(STDERR, "libpng FAILS test\n"); + return (int)(ierror != 0); +} + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_0_12 your_png_h_is_not_version_1_0_12; diff --git a/Utilities/vtkpng/pngtrans.c b/Utilities/vtkpng/pngtrans.c new file mode 100644 index 0000000..3e757c1 --- /dev/null +++ b/Utilities/vtkpng/pngtrans.c @@ -0,0 +1,611 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr\n"); + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap\n"); + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing\n"); + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap\n"); + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_color_8p true_bits) +{ + png_debug(1, "in png_set_shift\n"); + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling\n"); + if (png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler\n"); + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_byte)filler; + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA? */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha\n"); + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha\n"); + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono\n"); + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert\n"); + if (row_info->bit_depth == 1 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->bit_depth < 8) + { + png_bytep rp, end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + else if (row_info->bit_depth == 2) + table = twobppswaptable; + else if (row_info->bit_depth == 4) + table = fourbppswaptable; + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* remove filler or alpha byte(s) */ +void /* PRIVATE */ +png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +{ + png_debug(1, "in png_do_strip_filler\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { +/* + if (row_info->color_type == PNG_COLOR_TYPE_RGB || + row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) +*/ + png_bytep sp=row; + png_bytep dp=row; + png_uint_32 row_width=row_info->width; + png_uint_32 i; + + if (row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + /* This converts from RGBX or RGBA to RGB */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp+=3; sp+=4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + /* This converts from XRGB or ARGB to RGB */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ + for (i = 0; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + sp+=2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + } +/* + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY || + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) +*/ + else if (row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + /* This converts from GX or GA to G */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + /* This converts from XG or AG to G */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GGXX or GGAA to GG */ + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXGG or AAGG to GG */ + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + } + } +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info\n"); +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +#else + if(user_transform_ptr || user_transform_depth || user_transform_channels) + png_warning(png_ptr, + "This version of libpng does not support user transform info"); +#endif +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +png_voidp PNGAPI +png_get_user_transform_ptr(png_structp png_ptr) +{ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + return ((png_voidp)png_ptr->user_transform_ptr); +#else + if(png_ptr) + return (NULL); + return (NULL); +#endif +} + diff --git a/Utilities/vtkpng/pngvcrd.c b/Utilities/vtkpng/pngvcrd.c new file mode 100644 index 0000000..549db19 --- /dev/null +++ b/Utilities/vtkpng/pngvcrd.c @@ -0,0 +1,3836 @@ +/* pngvcrd.c - mixed C/assembler version of utilities to read a PNG file + * + * For Intel x86 CPU and Microsoft Visual C++ compiler + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * Copyright (c) 1998, Intel Corporation + * + * Contributed by Nirav Chhatrapati, Intel Corporation, 1998 + * Interface to libpng contributed by Gilles Vollant, 1999 + * Debugging and cleanup by Greg Roelofs, 2000, 2001 + * + * In png_do_read_interlace() in libpng versions 1.0.3a through 1.0.4d, + * a sign error in the post-MMX cleanup code for each pixel_depth resulted + * in bad pixels at the beginning of some rows of some images, and also + * (due to out-of-range memory reads and writes) caused heap corruption + * when compiled with MSVC 6.0. The error was fixed in version 1.0.4e. + * + * [png_read_filter_row_mmx_avg() bpp == 2 bugfix, GRR 20000916] + * + */ + +#define PNG_INTERNAL +#include "png.h" + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && defined(PNG_USE_PNGVCRD) + +static int mmx_supported=2; + + +int PNGAPI +png_mmx_support(void) +{ + int mmx_supported_local = 0; + _asm { + push ebx //CPUID will trash these + push ecx + push edx + pushfd //Save Eflag to stack + pop eax //Get Eflag from stack into eax + mov ecx, eax //Make another copy of Eflag in ecx + xor eax, 0x200000 //Toggle ID bit in Eflag [i.e. bit(21)] + push eax //Save modified Eflag back to stack + + popfd //Restored modified value back to Eflag reg + pushfd //Save Eflag to stack + pop eax //Get Eflag from stack + xor eax, ecx //Compare the new Eflag with the original Eflag + jz NOT_SUPPORTED //If the same, CPUID instruction is not supported, + //skip following instructions and jump to + //NOT_SUPPORTED label + + xor eax, eax //Set eax to zero + + _asm _emit 0x0f //CPUID instruction (two bytes opcode) + _asm _emit 0xa2 + + cmp eax, 1 //make sure eax return non-zero value + jl NOT_SUPPORTED //If eax is zero, mmx not supported + + xor eax, eax //set eax to zero + inc eax //Now increment eax to 1. This instruction is + //faster than the instruction "mov eax, 1" + + _asm _emit 0x0f //CPUID instruction + _asm _emit 0xa2 + + and edx, 0x00800000 //mask out all bits but mmx bit(24) + cmp edx, 0 // 0 = mmx not supported + jz NOT_SUPPORTED // non-zero = Yes, mmx IS supported + + mov mmx_supported_local, 1 //set return value to 1 + +NOT_SUPPORTED: + mov eax, mmx_supported_local //move return value to eax + pop edx //CPUID trashed these + pop ecx + pop ebx + } + + //mmx_supported_local=0; // test code for force do not support MMX + //printf("MMX : %u (1=MMX supported)\n",mmx_supported_local); + + mmx_supported = mmx_supported_local; + return mmx_supported_local; +} + +/* Combines the row recently read in with the previous row. + This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined; a + zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ + +/* Use this routine for x86 platform - uses faster MMX routine if machine + supports MMX */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1,"in png_combine_row_asm\n"); + + if (mmx_supported == 2) { + png_mmx_support(); + } + + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + (png_size_t)((png_ptr->width * png_ptr->row_info.pixel_depth + 7) >> 3)); + } + /* GRR: add "else if (mask == 0)" case? + * or does png_combine_row() not even get called in that case? */ + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int s_inc, s_start, s_end; + int m; + int shift; + png_uint_32 i; + + sp = png_ptr->row_buf + 1; + dp = row; + m = 0x80; +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < png_ptr->width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x1; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + + case 2: + { + png_bytep sp; + png_bytep dp; + int s_start, s_end, s_inc; + int m; + int shift; + png_uint_32 i; + int value; + + sp = png_ptr->row_buf + 1; + dp = row; + m = 0x80; +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < png_ptr->width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x3; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + + case 4: + { + png_bytep sp; + png_bytep dp; + int s_start, s_end, s_inc; + int m; + int shift; + png_uint_32 i; + int value; + + sp = png_ptr->row_buf + 1; + dp = row; + m = 0x80; +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < png_ptr->width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + + case 8: + { + png_bytep srcptr; + png_bytep dstptr; + png_uint_32 len; + int m; + int diff, unmask; + + __int64 mask0=0x0102040810204080; + + if ( mmx_supported ) + { + srcptr = png_ptr->row_buf + 1; + dstptr = row; + m = 0x80; + unmask = ~mask; + len = png_ptr->width &~7; //reduce to multiple of 8 + diff = png_ptr->width & 7; //amount lost + + _asm + { + movd mm7, unmask //load bit pattern + psubb mm6,mm6 //zero mm6 + punpcklbw mm7,mm7 + punpcklwd mm7,mm7 + punpckldq mm7,mm7 //fill register with 8 masks + + movq mm0,mask0 + + pand mm0,mm7 //nonzero if keep byte + pcmpeqb mm0,mm6 //zeros->1s, v versa + + mov ecx,len //load length of line (pixels) + mov esi,srcptr //load source + mov ebx,dstptr //load dest + cmp ecx,0 //lcr + je mainloop8end + +mainloop8: + movq mm4,[esi] + pand mm4,mm0 + movq mm6,mm0 + pandn mm6,[ebx] + por mm4,mm6 + movq [ebx],mm4 + + add esi,8 //inc by 8 bytes processed + add ebx,8 + sub ecx,8 //dec by 8 pixels processed + + ja mainloop8 +mainloop8end: + + mov ecx,diff + cmp ecx,0 + jz end8 + + mov edx,mask + sal edx,24 //make low byte the high byte + +secondloop8: + sal edx,1 //move high bit to CF + jnc skip8 //if CF = 0 + mov al,[esi] + mov [ebx],al +skip8: + inc esi + inc ebx + + dec ecx + jnz secondloop8 +end8: + emms + } + } + else /* mmx not supported - use modified C routine */ + { + register unsigned int incr1, initial_val, final_val; + png_size_t pixel_bytes; + png_uint_32 i; + register int disp = png_pass_inc[png_ptr->pass]; + int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; + + pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* + pixel_bytes; + dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; + initial_val = offset_table[png_ptr->pass]*pixel_bytes; + final_val = png_ptr->width*pixel_bytes; + incr1 = (disp)*pixel_bytes; + for (i = initial_val; i < final_val; i += incr1) + { + if (pixel_bytes > (png_size_t)(final_val-i)) + pixel_bytes = (png_size_t)(final_val-i); + png_memcpy(dstptr, srcptr, pixel_bytes); + srcptr += incr1; + dstptr += incr1; + } + } /* end of else */ + + break; + } // end 8 bpp + + case 16: + { + png_bytep srcptr; + png_bytep dstptr; + png_uint_32 len; + int unmask, diff; + __int64 mask1=0x0101020204040808, + mask0=0x1010202040408080; + + if ( mmx_supported ) + { + srcptr = png_ptr->row_buf + 1; + dstptr = row; + + unmask = ~mask; + len = (png_ptr->width)&~7; + diff = (png_ptr->width)&7; + _asm + { + movd mm7, unmask //load bit pattern + psubb mm6,mm6 //zero mm6 + punpcklbw mm7,mm7 + punpcklwd mm7,mm7 + punpckldq mm7,mm7 //fill register with 8 masks + + movq mm0,mask0 + movq mm1,mask1 + + pand mm0,mm7 + pand mm1,mm7 + + pcmpeqb mm0,mm6 + pcmpeqb mm1,mm6 + + mov ecx,len //load length of line + mov esi,srcptr //load source + mov ebx,dstptr //load dest + cmp ecx,0 //lcr + jz mainloop16end + +mainloop16: + movq mm4,[esi] + pand mm4,mm0 + movq mm6,mm0 + movq mm7,[ebx] + pandn mm6,mm7 + por mm4,mm6 + movq [ebx],mm4 + + movq mm5,[esi+8] + pand mm5,mm1 + movq mm7,mm1 + movq mm6,[ebx+8] + pandn mm7,mm6 + por mm5,mm7 + movq [ebx+8],mm5 + + add esi,16 //inc by 16 bytes processed + add ebx,16 + sub ecx,8 //dec by 8 pixels processed + + ja mainloop16 + +mainloop16end: + mov ecx,diff + cmp ecx,0 + jz end16 + + mov edx,mask + sal edx,24 //make low byte the high byte +secondloop16: + sal edx,1 //move high bit to CF + jnc skip16 //if CF = 0 + mov ax,[esi] + mov [ebx],ax +skip16: + add esi,2 + add ebx,2 + + dec ecx + jnz secondloop16 +end16: + emms + } + } + else /* mmx not supported - use modified C routine */ + { + register unsigned int incr1, initial_val, final_val; + png_size_t pixel_bytes; + png_uint_32 i; + register int disp = png_pass_inc[png_ptr->pass]; + int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; + + pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* + pixel_bytes; + dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; + initial_val = offset_table[png_ptr->pass]*pixel_bytes; + final_val = png_ptr->width*pixel_bytes; + incr1 = (disp)*pixel_bytes; + for (i = initial_val; i < final_val; i += incr1) + { + if (pixel_bytes > (png_size_t)(final_val-i)) + pixel_bytes = (png_size_t)(final_val-i); + png_memcpy(dstptr, srcptr, pixel_bytes); + srcptr += incr1; + dstptr += incr1; + } + } /* end of else */ + + break; + } // end 16 bpp + + case 24: + { + png_bytep srcptr; + png_bytep dstptr; + png_uint_32 len; + int unmask, diff; + + __int64 mask2=0x0101010202020404, //24bpp + mask1=0x0408080810101020, + mask0=0x2020404040808080; + + srcptr = png_ptr->row_buf + 1; + dstptr = row; + + unmask = ~mask; + len = (png_ptr->width)&~7; + diff = (png_ptr->width)&7; + + if ( mmx_supported ) + { + _asm + { + movd mm7, unmask //load bit pattern + psubb mm6,mm6 //zero mm6 + punpcklbw mm7,mm7 + punpcklwd mm7,mm7 + punpckldq mm7,mm7 //fill register with 8 masks + + movq mm0,mask0 + movq mm1,mask1 + movq mm2,mask2 + + pand mm0,mm7 + pand mm1,mm7 + pand mm2,mm7 + + pcmpeqb mm0,mm6 + pcmpeqb mm1,mm6 + pcmpeqb mm2,mm6 + + mov ecx,len //load length of line + mov esi,srcptr //load source + mov ebx,dstptr //load dest + cmp ecx,0 + jz mainloop24end + +mainloop24: + movq mm4,[esi] + pand mm4,mm0 + movq mm6,mm0 + movq mm7,[ebx] + pandn mm6,mm7 + por mm4,mm6 + movq [ebx],mm4 + + + movq mm5,[esi+8] + pand mm5,mm1 + movq mm7,mm1 + movq mm6,[ebx+8] + pandn mm7,mm6 + por mm5,mm7 + movq [ebx+8],mm5 + + movq mm6,[esi+16] + pand mm6,mm2 + movq mm4,mm2 + movq mm7,[ebx+16] + pandn mm4,mm7 + por mm6,mm4 + movq [ebx+16],mm6 + + add esi,24 //inc by 24 bytes processed + add ebx,24 + sub ecx,8 //dec by 8 pixels processed + + ja mainloop24 + +mainloop24end: + mov ecx,diff + cmp ecx,0 + jz end24 + + mov edx,mask + sal edx,24 //make low byte the high byte +secondloop24: + sal edx,1 //move high bit to CF + jnc skip24 //if CF = 0 + mov ax,[esi] + mov [ebx],ax + xor eax,eax + mov al,[esi+2] + mov [ebx+2],al +skip24: + add esi,3 + add ebx,3 + + dec ecx + jnz secondloop24 + +end24: + emms + } + } + else /* mmx not supported - use modified C routine */ + { + register unsigned int incr1, initial_val, final_val; + png_size_t pixel_bytes; + png_uint_32 i; + register int disp = png_pass_inc[png_ptr->pass]; + int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; + + pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* + pixel_bytes; + dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; + initial_val = offset_table[png_ptr->pass]*pixel_bytes; + final_val = png_ptr->width*pixel_bytes; + incr1 = (disp)*pixel_bytes; + for (i = initial_val; i < final_val; i += incr1) + { + if (pixel_bytes > (png_size_t)(final_val-i)) + pixel_bytes = (png_size_t)(final_val-i); + png_memcpy(dstptr, srcptr, pixel_bytes); + srcptr += incr1; + dstptr += incr1; + } + } /* end of else */ + + break; + } // end 24 bpp + + case 32: + { + png_bytep srcptr; + png_bytep dstptr; + png_uint_32 len; + int unmask, diff; + + __int64 mask3=0x0101010102020202, //32bpp + mask2=0x0404040408080808, + mask1=0x1010101020202020, + mask0=0x4040404080808080; + + srcptr = png_ptr->row_buf + 1; + dstptr = row; + + unmask = ~mask; + len = (png_ptr->width)&~7; + diff = (png_ptr->width)&7; + + if ( mmx_supported ) + { + _asm + { + movd mm7, unmask //load bit pattern + psubb mm6,mm6 //zero mm6 + punpcklbw mm7,mm7 + punpcklwd mm7,mm7 + punpckldq mm7,mm7 //fill register with 8 masks + + movq mm0,mask0 + movq mm1,mask1 + movq mm2,mask2 + movq mm3,mask3 + + pand mm0,mm7 + pand mm1,mm7 + pand mm2,mm7 + pand mm3,mm7 + + pcmpeqb mm0,mm6 + pcmpeqb mm1,mm6 + pcmpeqb mm2,mm6 + pcmpeqb mm3,mm6 + + mov ecx,len //load length of line + mov esi,srcptr //load source + mov ebx,dstptr //load dest + + cmp ecx,0 //lcr + jz mainloop32end + +mainloop32: + movq mm4,[esi] + pand mm4,mm0 + movq mm6,mm0 + movq mm7,[ebx] + pandn mm6,mm7 + por mm4,mm6 + movq [ebx],mm4 + + movq mm5,[esi+8] + pand mm5,mm1 + movq mm7,mm1 + movq mm6,[ebx+8] + pandn mm7,mm6 + por mm5,mm7 + movq [ebx+8],mm5 + + movq mm6,[esi+16] + pand mm6,mm2 + movq mm4,mm2 + movq mm7,[ebx+16] + pandn mm4,mm7 + por mm6,mm4 + movq [ebx+16],mm6 + + movq mm7,[esi+24] + pand mm7,mm3 + movq mm5,mm3 + movq mm4,[ebx+24] + pandn mm5,mm4 + por mm7,mm5 + movq [ebx+24],mm7 + + add esi,32 //inc by 32 bytes processed + add ebx,32 + sub ecx,8 //dec by 8 pixels processed + + ja mainloop32 + +mainloop32end: + mov ecx,diff + cmp ecx,0 + jz end32 + + mov edx,mask + sal edx,24 //make low byte the high byte +secondloop32: + sal edx,1 //move high bit to CF + jnc skip32 //if CF = 0 + mov eax,[esi] + mov [ebx],eax +skip32: + add esi,4 + add ebx,4 + + dec ecx + jnz secondloop32 + +end32: + emms + } + } + else /* mmx _not supported - Use modified C routine */ + { + register unsigned int incr1, initial_val, final_val; + png_size_t pixel_bytes; + png_uint_32 i; + register int disp = png_pass_inc[png_ptr->pass]; + int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; + + pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* + pixel_bytes; + dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; + initial_val = offset_table[png_ptr->pass]*pixel_bytes; + final_val = png_ptr->width*pixel_bytes; + incr1 = (disp)*pixel_bytes; + for (i = initial_val; i < final_val; i += incr1) + { + if (pixel_bytes > (png_size_t)(final_val-i)) + pixel_bytes = (png_size_t)(final_val-i); + png_memcpy(dstptr, srcptr, pixel_bytes); + srcptr += incr1; + dstptr += incr1; + } + } /* end of else */ + + break; + } // end 32 bpp + + case 48: + { + png_bytep srcptr; + png_bytep dstptr; + png_uint_32 len; + int unmask, diff; + + __int64 mask5=0x0101010101010202, + mask4=0x0202020204040404, + mask3=0x0404080808080808, + mask2=0x1010101010102020, + mask1=0x2020202040404040, + mask0=0x4040808080808080; + + if ( mmx_supported ) + { + srcptr = png_ptr->row_buf + 1; + dstptr = row; + + unmask = ~mask; + len = (png_ptr->width)&~7; + diff = (png_ptr->width)&7; + _asm + { + movd mm7, unmask //load bit pattern + psubb mm6,mm6 //zero mm6 + punpcklbw mm7,mm7 + punpcklwd mm7,mm7 + punpckldq mm7,mm7 //fill register with 8 masks + + movq mm0,mask0 + movq mm1,mask1 + movq mm2,mask2 + movq mm3,mask3 + movq mm4,mask4 + movq mm5,mask5 + + pand mm0,mm7 + pand mm1,mm7 + pand mm2,mm7 + pand mm3,mm7 + pand mm4,mm7 + pand mm5,mm7 + + pcmpeqb mm0,mm6 + pcmpeqb mm1,mm6 + pcmpeqb mm2,mm6 + pcmpeqb mm3,mm6 + pcmpeqb mm4,mm6 + pcmpeqb mm5,mm6 + + mov ecx,len //load length of line + mov esi,srcptr //load source + mov ebx,dstptr //load dest + + cmp ecx,0 + jz mainloop48end + +mainloop48: + movq mm7,[esi] + pand mm7,mm0 + movq mm6,mm0 + pandn mm6,[ebx] + por mm7,mm6 + movq [ebx],mm7 + + movq mm6,[esi+8] + pand mm6,mm1 + movq mm7,mm1 + pandn mm7,[ebx+8] + por mm6,mm7 + movq [ebx+8],mm6 + + movq mm6,[esi+16] + pand mm6,mm2 + movq mm7,mm2 + pandn mm7,[ebx+16] + por mm6,mm7 + movq [ebx+16],mm6 + + movq mm7,[esi+24] + pand mm7,mm3 + movq mm6,mm3 + pandn mm6,[ebx+24] + por mm7,mm6 + movq [ebx+24],mm7 + + movq mm6,[esi+32] + pand mm6,mm4 + movq mm7,mm4 + pandn mm7,[ebx+32] + por mm6,mm7 + movq [ebx+32],mm6 + + movq mm7,[esi+40] + pand mm7,mm5 + movq mm6,mm5 + pandn mm6,[ebx+40] + por mm7,mm6 + movq [ebx+40],mm7 + + add esi,48 //inc by 32 bytes processed + add ebx,48 + sub ecx,8 //dec by 8 pixels processed + + ja mainloop48 +mainloop48end: + + mov ecx,diff + cmp ecx,0 + jz end48 + + mov edx,mask + sal edx,24 //make low byte the high byte + +secondloop48: + sal edx,1 //move high bit to CF + jnc skip48 //if CF = 0 + mov eax,[esi] + mov [ebx],eax +skip48: + add esi,4 + add ebx,4 + + dec ecx + jnz secondloop48 + +end48: + emms + } + } + else /* mmx _not supported - Use modified C routine */ + { + register unsigned int incr1, initial_val, final_val; + png_size_t pixel_bytes; + png_uint_32 i; + register int disp = png_pass_inc[png_ptr->pass]; + int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; + + pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + srcptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* + pixel_bytes; + dstptr = row + offset_table[png_ptr->pass]*pixel_bytes; + initial_val = offset_table[png_ptr->pass]*pixel_bytes; + final_val = png_ptr->width*pixel_bytes; + incr1 = (disp)*pixel_bytes; + for (i = initial_val; i < final_val; i += incr1) + { + if (pixel_bytes > (png_size_t)(final_val-i)) + pixel_bytes = (png_size_t)(final_val-i); + png_memcpy(dstptr, srcptr, pixel_bytes); + srcptr += incr1; + dstptr += incr1; + } + } /* end of else */ + + break; + } // end 48 bpp + + default: + { + png_bytep sptr; + png_bytep dp; + png_size_t pixel_bytes; + int offset_table[7] = {0, 4, 0, 2, 0, 1, 0}; + unsigned int i; + register int disp = png_pass_inc[png_ptr->pass]; // get the offset + register unsigned int incr1, initial_val, final_val; + + pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + sptr = png_ptr->row_buf + 1 + offset_table[png_ptr->pass]* + pixel_bytes; + dp = row + offset_table[png_ptr->pass]*pixel_bytes; + initial_val = offset_table[png_ptr->pass]*pixel_bytes; + final_val = png_ptr->width*pixel_bytes; + incr1 = (disp)*pixel_bytes; + for (i = initial_val; i < final_val; i += incr1) + { + if (pixel_bytes > (png_size_t)(final_val-i)) + pixel_bytes = (png_size_t)(final_val-i); + png_memcpy(dp, sptr, pixel_bytes); + sptr += incr1; + dp += incr1; + } + break; + } + } /* end switch (png_ptr->row_info.pixel_depth) */ + } /* end if (non-trivial mask) */ + +} /* end png_combine_row() */ + + +#if defined(PNG_READ_INTERLACING_SUPPORTED) + +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; +#ifdef PNG_USE_LOCAL_ARRAYS + const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1,"in png_do_read_interlace\n"); + + if (mmx_supported == 2) { + png_mmx_support(); + } + + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp, dp; + int sshift, dshift; + int s_start, s_end, s_inc; + png_byte v; + png_uint_32 i; + int j; + + sp = row + (png_size_t)((row_info->width - 1) >> 3); + dp = row + (png_size_t)((final_width - 1) >> 3); +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 7); + dshift = (int)((final_width + 7) & 7); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 7); + dshift = 7 - (int)((final_width + 7) & 7); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = row_info->width; i; i--) + { + v = (png_byte)((*sp >> sshift) & 0x1); + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + + case 2: + { + png_bytep sp, dp; + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + + sp = row + (png_size_t)((row_info->width - 1) >> 2); + dp = row + (png_size_t)((final_width - 1) >> 2); +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (png_size_t)(((row_info->width + 3) & 3) << 1); + dshift = (png_size_t)(((final_width + 3) & 3) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1); + dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = row_info->width; i; i--) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x3); + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + + case 4: + { + png_bytep sp, dp; + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + + sp = row + (png_size_t)((row_info->width - 1) >> 1); + dp = row + (png_size_t)((final_width - 1) >> 1); +#if defined(PNG_READ_PACKSWAP_SUPPORTED) + if (transformations & PNG_PACKSWAP) + { + sshift = (png_size_t)(((row_info->width + 1) & 1) << 2); + dshift = (png_size_t)(((final_width + 1) & 1) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2); + dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = row_info->width; i; i--) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0xf); + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + + default: // This is the place where the routine is modified + { + __int64 const4 = 0x0000000000FFFFFF; + // __int64 const5 = 0x000000FFFFFF0000; // unused... + __int64 const6 = 0x00000000000000FF; + png_bytep sptr, dp; + png_uint_32 i; + png_size_t pixel_bytes; + int width = row_info->width; + + pixel_bytes = (row_info->pixel_depth >> 3); + + sptr = row + (width - 1) * pixel_bytes; + dp = row + (final_width - 1) * pixel_bytes; + // New code by Nirav Chhatrapati - Intel Corporation + // sign fix by GRR + // NOTE: there is NO MMX code for 48-bit and 64-bit images + + // use MMX routine if machine supports it + if ( mmx_supported ) + { + if (pixel_bytes == 3) + { + if (((pass == 0) || (pass == 1)) && width) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width + sub edi, 21 // (png_pass_inc[pass] - 1)*pixel_bytes +loop_pass0: + movd mm0, [esi] ; X X X X X v2 v1 v0 + pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0 + movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0 + psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0 + movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0 + psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0 + psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1 + por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0 + por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1 + movq mm3, mm0 ; v2 v1 v0 v2 v1 v0 v2 v1 + psllq mm0, 16 ; v0 v2 v1 v0 v2 v1 0 0 + movq mm4, mm3 ; v2 v1 v0 v2 v1 v0 v2 v1 + punpckhdq mm3, mm0 ; v0 v2 v1 v0 v2 v1 v0 v2 + movq [edi+16] , mm4 + psrlq mm0, 32 ; 0 0 0 0 v0 v2 v1 v0 + movq [edi+8] , mm3 + punpckldq mm0, mm4 ; v1 v0 v2 v1 v0 v2 v1 v0 + sub esi, 3 + movq [edi], mm0 + sub edi, 24 + //sub esi, 3 + dec ecx + jnz loop_pass0 + EMMS + } + } + else if (((pass == 2) || (pass == 3)) && width) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width + sub edi, 9 // (png_pass_inc[pass] - 1)*pixel_bytes +loop_pass2: + movd mm0, [esi] ; X X X X X v2 v1 v0 + pand mm0, const4 ; 0 0 0 0 0 v2 v1 v0 + movq mm1, mm0 ; 0 0 0 0 0 v2 v1 v0 + psllq mm0, 16 ; 0 0 0 v2 v1 v0 0 0 + movq mm2, mm0 ; 0 0 0 v2 v1 v0 0 0 + psllq mm0, 24 ; v2 v1 v0 0 0 0 0 0 + psrlq mm1, 8 ; 0 0 0 0 0 0 v2 v1 + por mm0, mm2 ; v2 v1 v0 v2 v1 v0 0 0 + por mm0, mm1 ; v2 v1 v0 v2 v1 v0 v2 v1 + movq [edi+4], mm0 ; move to memory + psrlq mm0, 16 ; 0 0 v2 v1 v0 v2 v1 v0 + movd [edi], mm0 ; move to memory + sub esi, 3 + sub edi, 12 + dec ecx + jnz loop_pass2 + EMMS + } + } + else if (width) /* && ((pass == 4) || (pass == 5)) */ + { + int width_mmx = ((width >> 1) << 1) - 8; + if (width_mmx < 0) + width_mmx = 0; + width -= width_mmx; // 8 or 9 pix, 24 or 27 bytes + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub esi, 3 + sub edi, 9 +loop_pass4: + movq mm0, [esi] ; X X v2 v1 v0 v5 v4 v3 + movq mm7, mm0 ; X X v2 v1 v0 v5 v4 v3 + movq mm6, mm0 ; X X v2 v1 v0 v5 v4 v3 + psllq mm0, 24 ; v1 v0 v5 v4 v3 0 0 0 + pand mm7, const4 ; 0 0 0 0 0 v5 v4 v3 + psrlq mm6, 24 ; 0 0 0 X X v2 v1 v0 + por mm0, mm7 ; v1 v0 v5 v4 v3 v5 v4 v3 + movq mm5, mm6 ; 0 0 0 X X v2 v1 v0 + psllq mm6, 8 ; 0 0 X X v2 v1 v0 0 + movq [edi], mm0 ; move quad to memory + psrlq mm5, 16 ; 0 0 0 0 0 X X v2 + pand mm5, const6 ; 0 0 0 0 0 0 0 v2 + por mm6, mm5 ; 0 0 X X v2 v1 v0 v2 + movd [edi+8], mm6 ; move double to memory + sub esi, 6 + sub edi, 12 + sub ecx, 2 + jnz loop_pass4 + EMMS + } + } + + sptr -= width_mmx*3; + dp -= width_mmx*6; + for (i = width; i; i--) + { + png_byte v[8]; + int j; + + png_memcpy(v, sptr, 3); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 3); + dp -= 3; + } + sptr -= 3; + } + } + } /* end of pixel_bytes == 3 */ + + else if (pixel_bytes == 1) + { + if (((pass == 0) || (pass == 1)) && width) + { + int width_mmx = ((width >> 2) << 2); + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub edi, 31 + sub esi, 3 +loop1_pass0: + movd mm0, [esi] ; X X X X v0 v1 v2 v3 + movq mm1, mm0 ; X X X X v0 v1 v2 v3 + punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 + movq mm2, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 + punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3 + movq mm3, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3 + punpckldq mm0, mm0 ; v3 v3 v3 v3 v3 v3 v3 v3 + punpckhdq mm3, mm3 ; v2 v2 v2 v2 v2 v2 v2 v2 + movq [edi], mm0 ; move to memory v3 + punpckhwd mm2, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1 + movq [edi+8], mm3 ; move to memory v2 + movq mm4, mm2 ; v0 v0 v0 v0 v1 v1 v1 v1 + punpckldq mm2, mm2 ; v1 v1 v1 v1 v1 v1 v1 v1 + punpckhdq mm4, mm4 ; v0 v0 v0 v0 v0 v0 v0 v0 + movq [edi+16], mm2 ; move to memory v1 + movq [edi+24], mm4 ; move to memory v0 + sub esi, 4 + sub edi, 32 + sub ecx, 4 + jnz loop1_pass0 + EMMS + } + } + + sptr -= width_mmx; + dp -= width_mmx*8; + for (i = width; i; i--) + { + int j; + + /* I simplified this part in version 1.0.4e + * here and in several other instances where + * pixel_bytes == 1 -- GR-P + * + * Original code: + * + * png_byte v[8]; + * png_memcpy(v, sptr, pixel_bytes); + * for (j = 0; j < png_pass_inc[pass]; j++) + * { + * png_memcpy(dp, v, pixel_bytes); + * dp -= pixel_bytes; + * } + * sptr -= pixel_bytes; + * + * Replacement code is in the next three lines: + */ + + for (j = 0; j < png_pass_inc[pass]; j++) + *dp-- = *sptr; + sptr--; + } + } + else if (((pass == 2) || (pass == 3)) && width) + { + int width_mmx = ((width >> 2) << 2); + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub edi, 15 + sub esi, 3 +loop1_pass2: + movd mm0, [esi] ; X X X X v0 v1 v2 v3 + punpcklbw mm0, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 + movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 + punpcklwd mm0, mm0 ; v2 v2 v2 v2 v3 v3 v3 v3 + punpckhwd mm1, mm1 ; v0 v0 v0 v0 v1 v1 v1 v1 + movq [edi], mm0 ; move to memory v2 and v3 + sub esi, 4 + movq [edi+8], mm1 ; move to memory v1 and v0 + sub edi, 16 + sub ecx, 4 + jnz loop1_pass2 + EMMS + } + } + + sptr -= width_mmx; + dp -= width_mmx*4; + for (i = width; i; i--) + { + int j; + + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp-- = *sptr; + } + sptr --; + } + } + else if (width) /* && ((pass == 4) || (pass == 5))) */ + { + int width_mmx = ((width >> 3) << 3); + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub edi, 15 + sub esi, 7 +loop1_pass4: + movq mm0, [esi] ; v0 v1 v2 v3 v4 v5 v6 v7 + movq mm1, mm0 ; v0 v1 v2 v3 v4 v5 v6 v7 + punpcklbw mm0, mm0 ; v4 v4 v5 v5 v6 v6 v7 v7 + //movq mm1, mm0 ; v0 v0 v1 v1 v2 v2 v3 v3 + punpckhbw mm1, mm1 ;v0 v0 v1 v1 v2 v2 v3 v3 + movq [edi+8], mm1 ; move to memory v0 v1 v2 and v3 + sub esi, 8 + movq [edi], mm0 ; move to memory v4 v5 v6 and v7 + //sub esi, 4 + sub edi, 16 + sub ecx, 8 + jnz loop1_pass4 + EMMS + } + } + + sptr -= width_mmx; + dp -= width_mmx*2; + for (i = width; i; i--) + { + int j; + + for (j = 0; j < png_pass_inc[pass]; j++) + { + *dp-- = *sptr; + } + sptr --; + } + } + } /* end of pixel_bytes == 1 */ + + else if (pixel_bytes == 2) + { + if (((pass == 0) || (pass == 1)) && width) + { + int width_mmx = ((width >> 1) << 1); + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub esi, 2 + sub edi, 30 +loop2_pass0: + movd mm0, [esi] ; X X X X v1 v0 v3 v2 + punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 + movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 + punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2 + punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0 + movq [edi], mm0 + movq [edi + 8], mm0 + movq [edi + 16], mm1 + movq [edi + 24], mm1 + sub esi, 4 + sub edi, 32 + sub ecx, 2 + jnz loop2_pass0 + EMMS + } + } + + sptr -= (width_mmx*2 - 2); // sign fixed + dp -= (width_mmx*16 - 2); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 2; + png_memcpy(v, sptr, 2); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 2; + png_memcpy(dp, v, 2); + } + } + } + else if (((pass == 2) || (pass == 3)) && width) + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub esi, 2 + sub edi, 14 +loop2_pass2: + movd mm0, [esi] ; X X X X v1 v0 v3 v2 + punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 + movq mm1, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 + punpckldq mm0, mm0 ; v3 v2 v3 v2 v3 v2 v3 v2 + punpckhdq mm1, mm1 ; v1 v0 v1 v0 v1 v0 v1 v0 + movq [edi], mm0 + sub esi, 4 + movq [edi + 8], mm1 + //sub esi, 4 + sub edi, 16 + sub ecx, 2 + jnz loop2_pass2 + EMMS + } + } + + sptr -= (width_mmx*2 - 2); // sign fixed + dp -= (width_mmx*8 - 2); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 2; + png_memcpy(v, sptr, 2); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 2; + png_memcpy(dp, v, 2); + } + } + } + else if (width) // pass == 4 or 5 + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub esi, 2 + sub edi, 6 +loop2_pass4: + movd mm0, [esi] ; X X X X v1 v0 v3 v2 + punpcklwd mm0, mm0 ; v1 v0 v1 v0 v3 v2 v3 v2 + sub esi, 4 + movq [edi], mm0 + sub edi, 8 + sub ecx, 2 + jnz loop2_pass4 + EMMS + } + } + + sptr -= (width_mmx*2 - 2); // sign fixed + dp -= (width_mmx*4 - 2); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 2; + png_memcpy(v, sptr, 2); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 2; + png_memcpy(dp, v, 2); + } + } + } + } /* end of pixel_bytes == 2 */ + + else if (pixel_bytes == 4) + { + if (((pass == 0) || (pass == 1)) && width) + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub esi, 4 + sub edi, 60 +loop4_pass0: + movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4 + movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4 + punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4 + punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0 + movq [edi], mm0 + movq [edi + 8], mm0 + movq [edi + 16], mm0 + movq [edi + 24], mm0 + movq [edi+32], mm1 + movq [edi + 40], mm1 + movq [edi+ 48], mm1 + sub esi, 8 + movq [edi + 56], mm1 + sub edi, 64 + sub ecx, 2 + jnz loop4_pass0 + EMMS + } + } + + sptr -= (width_mmx*4 - 4); // sign fixed + dp -= (width_mmx*32 - 4); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 4; + png_memcpy(v, sptr, 4); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 4; + png_memcpy(dp, v, 4); + } + } + } + else if (((pass == 2) || (pass == 3)) && width) + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub esi, 4 + sub edi, 28 +loop4_pass2: + movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4 + movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4 + punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4 + punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0 + movq [edi], mm0 + movq [edi + 8], mm0 + movq [edi+16], mm1 + movq [edi + 24], mm1 + sub esi, 8 + sub edi, 32 + sub ecx, 2 + jnz loop4_pass2 + EMMS + } + } + + sptr -= (width_mmx*4 - 4); // sign fixed + dp -= (width_mmx*16 - 4); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 4; + png_memcpy(v, sptr, 4); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 4; + png_memcpy(dp, v, 4); + } + } + } + else if (width) // pass == 4 or 5 + { + int width_mmx = ((width >> 1) << 1) ; + width -= width_mmx; + if (width_mmx) + { + _asm + { + mov esi, sptr + mov edi, dp + mov ecx, width_mmx + sub esi, 4 + sub edi, 12 +loop4_pass4: + movq mm0, [esi] ; v3 v2 v1 v0 v7 v6 v5 v4 + movq mm1, mm0 ; v3 v2 v1 v0 v7 v6 v5 v4 + punpckldq mm0, mm0 ; v7 v6 v5 v4 v7 v6 v5 v4 + punpckhdq mm1, mm1 ; v3 v2 v1 v0 v3 v2 v1 v0 + movq [edi], mm0 + sub esi, 8 + movq [edi + 8], mm1 + sub edi, 16 + sub ecx, 2 + jnz loop4_pass4 + EMMS + } + } + + sptr -= (width_mmx*4 - 4); // sign fixed + dp -= (width_mmx*8 - 4); // sign fixed + for (i = width; i; i--) + { + png_byte v[8]; + int j; + sptr -= 4; + png_memcpy(v, sptr, 4); + for (j = 0; j < png_pass_inc[pass]; j++) + { + dp -= 4; + png_memcpy(dp, v, 4); + } + } + } + + } /* end of pixel_bytes == 4 */ + + else if (pixel_bytes == 6) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, 6); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, 6); + dp -= 6; + } + sptr -= 6; + } + } /* end of pixel_bytes == 6 */ + + else + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr-= pixel_bytes; + } + } + } /* end of mmx_supported */ + + else /* MMX not supported: use modified C code - takes advantage + * of inlining of png_memcpy for a constant */ + { + if (pixel_bytes == 1) + { + for (i = width; i; i--) + { + int j; + for (j = 0; j < png_pass_inc[pass]; j++) + *dp-- = *sptr; + sptr--; + } + } + else if (pixel_bytes == 3) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr -= pixel_bytes; + } + } + else if (pixel_bytes == 2) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr -= pixel_bytes; + } + } + else if (pixel_bytes == 4) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr -= pixel_bytes; + } + } + else if (pixel_bytes == 6) + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr -= pixel_bytes; + } + } + else + { + for (i = width; i; i--) + { + png_byte v[8]; + int j; + png_memcpy(v, sptr, pixel_bytes); + for (j = 0; j < png_pass_inc[pass]; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sptr -= pixel_bytes; + } + } + + } /* end of MMX not supported */ + break; + } + } /* end switch (row_info->pixel_depth) */ + + row_info->width = final_width; + row_info->rowbytes = ((final_width * + (png_uint_32)row_info->pixel_depth + 7) >> 3); + } + +} + +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + +// These variables are utilized in the functions below. They are declared +// globally here to ensure alignment on 8-byte boundaries. + +union uAll { + __int64 use; + double align; +} LBCarryMask = {0x0101010101010101}, + HBClearMask = {0x7f7f7f7f7f7f7f7f}, + ActiveMask, ActiveMask2, ActiveMaskEnd, ShiftBpp, ShiftRem; + + +// Optimized code for PNG Average filter decoder +void /* PRIVATE */ +png_read_filter_row_mmx_avg(png_row_infop row_info, png_bytep row + , png_bytep prev_row) +{ + int bpp; + png_uint_32 FullLength; + png_uint_32 MMXLength; + //png_uint_32 len; + int diff; + + bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel + FullLength = row_info->rowbytes; // # of bytes to filter + _asm { + // Init address pointers and offset + mov edi, row // edi ==> Avg(x) + xor ebx, ebx // ebx ==> x + mov edx, edi + mov esi, prev_row // esi ==> Prior(x) + sub edx, bpp // edx ==> Raw(x-bpp) + + xor eax, eax + // Compute the Raw value for the first bpp bytes + // Raw(x) = Avg(x) + (Prior(x)/2) +davgrlp: + mov al, [esi + ebx] // Load al with Prior(x) + inc ebx + shr al, 1 // divide by 2 + add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx + cmp ebx, bpp + mov [edi+ebx-1], al // Write back Raw(x); + // mov does not affect flags; -1 to offset inc ebx + jb davgrlp + // get # of bytes to alignment + mov diff, edi // take start of row + add diff, ebx // add bpp + add diff, 0xf // add 7 + 8 to incr past alignment boundary + and diff, 0xfffffff8 // mask to alignment boundary + sub diff, edi // subtract from start ==> value ebx at alignment + jz davggo + // fix alignment + // Compute the Raw value for the bytes upto the alignment boundary + // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) + xor ecx, ecx +davglp1: + xor eax, eax + mov cl, [esi + ebx] // load cl with Prior(x) + mov al, [edx + ebx] // load al with Raw(x-bpp) + add ax, cx + inc ebx + shr ax, 1 // divide by 2 + add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx + cmp ebx, diff // Check if at alignment boundary + mov [edi+ebx-1], al // Write back Raw(x); + // mov does not affect flags; -1 to offset inc ebx + jb davglp1 // Repeat until at alignment boundary +davggo: + mov eax, FullLength + mov ecx, eax + sub eax, ebx // subtract alignment fix + and eax, 0x00000007 // calc bytes over mult of 8 + sub ecx, eax // drop over bytes from original length + mov MMXLength, ecx + } // end _asm block + // Now do the math for the rest of the row + switch ( bpp ) + { + case 3: + { + ActiveMask.use = 0x0000000000ffffff; + ShiftBpp.use = 24; // == 3 * 8 + ShiftRem.use = 40; // == 64 - 24 + _asm { + // Re-init address pointers and offset + movq mm7, ActiveMask + mov ebx, diff // ebx ==> x = offset to alignment boundary + movq mm5, LBCarryMask + mov edi, row // edi ==> Avg(x) + movq mm4, HBClearMask + mov esi, prev_row // esi ==> Prior(x) + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes + // (we correct position in loop below) +davg3lp: + movq mm0, [edi + ebx] // Load mm0 with Avg(x) + // Add (Prev_row/2) to Average + movq mm3, mm5 + psrlq mm2, ShiftRem // Correct position Raw(x-bpp) data + movq mm1, [esi + ebx] // Load mm1 with Prior(x) + movq mm6, mm7 + pand mm3, mm1 // get lsb for each prev_row byte + psrlq mm1, 1 // divide prev_row bytes by 2 + pand mm1, mm4 // clear invalid bit 7 of each byte + paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte + // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active + // byte + // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry + psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 3-5 + movq mm2, mm0 // mov updated Raws to mm2 + psllq mm2, ShiftBpp // shift data to position correctly + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active + // byte + + // Add 3rd active group (Raw(x-bpp)/2) to Average with LBCarry + psllq mm6, ShiftBpp // shift the mm6 mask to cover the last two + // bytes + movq mm2, mm0 // mov updated Raws to mm2 + psllq mm2, ShiftBpp // shift data to position correctly + // Data only needs to be shifted once here to + // get the correct x-bpp offset. + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg + add ebx, 8 + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active + // byte + + // Now ready to write back to memory + movq [edi + ebx - 8], mm0 + // Move updated Raw(x) to use as Raw(x-bpp) for next loop + cmp ebx, MMXLength + movq mm2, mm0 // mov updated Raw(x) to mm2 + jb davg3lp + } // end _asm block + } + break; + + case 6: + case 4: + case 7: + case 5: + { + ActiveMask.use = 0xffffffffffffffff; // use shift below to clear + // appropriate inactive bytes + ShiftBpp.use = bpp << 3; + ShiftRem.use = 64 - ShiftBpp.use; + _asm { + movq mm4, HBClearMask + // Re-init address pointers and offset + mov ebx, diff // ebx ==> x = offset to alignment boundary + // Load ActiveMask and clear all bytes except for 1st active group + movq mm7, ActiveMask + mov edi, row // edi ==> Avg(x) + psrlq mm7, ShiftRem + mov esi, prev_row // esi ==> Prior(x) + movq mm6, mm7 + movq mm5, LBCarryMask + psllq mm6, ShiftBpp // Create mask for 2nd active group + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes + // (we correct position in loop below) +davg4lp: + movq mm0, [edi + ebx] + psrlq mm2, ShiftRem // shift data to position correctly + movq mm1, [esi + ebx] + // Add (Prev_row/2) to Average + movq mm3, mm5 + pand mm3, mm1 // get lsb for each prev_row byte + psrlq mm1, 1 // divide prev_row bytes by 2 + pand mm1, mm4 // clear invalid bit 7 of each byte + paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte + // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm7 // Leave only Active Group 1 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active + // byte + // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry + movq mm2, mm0 // mov updated Raws to mm2 + psllq mm2, ShiftBpp // shift data to position correctly + add ebx, 8 + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active + // byte + cmp ebx, MMXLength + // Now ready to write back to memory + movq [edi + ebx - 8], mm0 + // Prep Raw(x-bpp) for next loop + movq mm2, mm0 // mov updated Raws to mm2 + jb davg4lp + } // end _asm block + } + break; + case 2: + { + ActiveMask.use = 0x000000000000ffff; + ShiftBpp.use = 16; // == 2 * 8 [BUGFIX] + ShiftRem.use = 48; // == 64 - 16 [BUGFIX] + _asm { + // Load ActiveMask + movq mm7, ActiveMask + // Re-init address pointers and offset + mov ebx, diff // ebx ==> x = offset to alignment boundary + movq mm5, LBCarryMask + mov edi, row // edi ==> Avg(x) + movq mm4, HBClearMask + mov esi, prev_row // esi ==> Prior(x) + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes + // (we correct position in loop below) +davg2lp: + movq mm0, [edi + ebx] + psrlq mm2, ShiftRem // shift data to position correctly [BUGFIX] + movq mm1, [esi + ebx] + // Add (Prev_row/2) to Average + movq mm3, mm5 + pand mm3, mm1 // get lsb for each prev_row byte + psrlq mm1, 1 // divide prev_row bytes by 2 + pand mm1, mm4 // clear invalid bit 7 of each byte + movq mm6, mm7 + paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte + // Add 1st active group (Raw(x-bpp)/2) to Average with LBCarry + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 1 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte + // Add 2nd active group (Raw(x-bpp)/2) to Average with LBCarry + psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 2 & 3 + movq mm2, mm0 // mov updated Raws to mm2 + psllq mm2, ShiftBpp // shift data to position correctly + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte + + // Add rdd active group (Raw(x-bpp)/2) to Average with LBCarry + psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 4 & 5 + movq mm2, mm0 // mov updated Raws to mm2 + psllq mm2, ShiftBpp // shift data to position correctly + // Data only needs to be shifted once here to + // get the correct x-bpp offset. + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte + + // Add 4th active group (Raw(x-bpp)/2) to Average with LBCarry + psllq mm6, ShiftBpp // shift the mm6 mask to cover bytes 6 & 7 + movq mm2, mm0 // mov updated Raws to mm2 + psllq mm2, ShiftBpp // shift data to position correctly + // Data only needs to be shifted once here to + // get the correct x-bpp offset. + add ebx, 8 + movq mm1, mm3 // now use mm1 for getting LBCarrys + pand mm1, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 (Only valid for active group) + psrlq mm2, 1 // divide raw bytes by 2 + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm2, mm1 // add LBCarrys to (Raw(x-bpp)/2) for each byte + pand mm2, mm6 // Leave only Active Group 2 bytes to add to Avg + paddb mm0, mm2 // add (Raw/2) + LBCarrys to Avg for each Active byte + + cmp ebx, MMXLength + // Now ready to write back to memory + movq [edi + ebx - 8], mm0 + // Prep Raw(x-bpp) for next loop + movq mm2, mm0 // mov updated Raws to mm2 + jb davg2lp + } // end _asm block + } + break; + + case 1: // bpp == 1 + { + _asm { + // Re-init address pointers and offset + mov ebx, diff // ebx ==> x = offset to alignment boundary + mov edi, row // edi ==> Avg(x) + cmp ebx, FullLength // Test if offset at end of array + jnb davg1end + // Do Paeth decode for remaining bytes + mov esi, prev_row // esi ==> Prior(x) + mov edx, edi + xor ecx, ecx // zero ecx before using cl & cx in loop below + sub edx, bpp // edx ==> Raw(x-bpp) +davg1lp: + // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) + xor eax, eax + mov cl, [esi + ebx] // load cl with Prior(x) + mov al, [edx + ebx] // load al with Raw(x-bpp) + add ax, cx + inc ebx + shr ax, 1 // divide by 2 + add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx + cmp ebx, FullLength // Check if at end of array + mov [edi+ebx-1], al // Write back Raw(x); + // mov does not affect flags; -1 to offset inc ebx + jb davg1lp +davg1end: + } // end _asm block + } + return; + + case 8: // bpp == 8 + { + _asm { + // Re-init address pointers and offset + mov ebx, diff // ebx ==> x = offset to alignment boundary + movq mm5, LBCarryMask + mov edi, row // edi ==> Avg(x) + movq mm4, HBClearMask + mov esi, prev_row // esi ==> Prior(x) + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm2, [edi + ebx - 8] // Load previous aligned 8 bytes + // (NO NEED to correct position in loop below) +davg8lp: + movq mm0, [edi + ebx] + movq mm3, mm5 + movq mm1, [esi + ebx] + add ebx, 8 + pand mm3, mm1 // get lsb for each prev_row byte + psrlq mm1, 1 // divide prev_row bytes by 2 + pand mm3, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 + psrlq mm2, 1 // divide raw bytes by 2 + pand mm1, mm4 // clear invalid bit 7 of each byte + paddb mm0, mm3 // add LBCarrys to Avg for each byte + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte + paddb mm0, mm2 // add (Raw/2) to Avg for each byte + cmp ebx, MMXLength + movq [edi + ebx - 8], mm0 + movq mm2, mm0 // reuse as Raw(x-bpp) + jb davg8lp + } // end _asm block + } + break; + default: // bpp greater than 8 + { + _asm { + movq mm5, LBCarryMask + // Re-init address pointers and offset + mov ebx, diff // ebx ==> x = offset to alignment boundary + mov edi, row // edi ==> Avg(x) + movq mm4, HBClearMask + mov edx, edi + mov esi, prev_row // esi ==> Prior(x) + sub edx, bpp // edx ==> Raw(x-bpp) +davgAlp: + movq mm0, [edi + ebx] + movq mm3, mm5 + movq mm1, [esi + ebx] + pand mm3, mm1 // get lsb for each prev_row byte + movq mm2, [edx + ebx] + psrlq mm1, 1 // divide prev_row bytes by 2 + pand mm3, mm2 // get LBCarrys for each byte where both + // lsbs were == 1 + psrlq mm2, 1 // divide raw bytes by 2 + pand mm1, mm4 // clear invalid bit 7 of each byte + paddb mm0, mm3 // add LBCarrys to Avg for each byte + pand mm2, mm4 // clear invalid bit 7 of each byte + paddb mm0, mm1 // add (Prev_row/2) to Avg for each byte + add ebx, 8 + paddb mm0, mm2 // add (Raw/2) to Avg for each byte + cmp ebx, MMXLength + movq [edi + ebx - 8], mm0 + jb davgAlp + } // end _asm block + } + break; + } // end switch ( bpp ) + + _asm { + // MMX acceleration complete now do clean-up + // Check if any remaining bytes left to decode + mov ebx, MMXLength // ebx ==> x = offset bytes remaining after MMX + mov edi, row // edi ==> Avg(x) + cmp ebx, FullLength // Test if offset at end of array + jnb davgend + // Do Paeth decode for remaining bytes + mov esi, prev_row // esi ==> Prior(x) + mov edx, edi + xor ecx, ecx // zero ecx before using cl & cx in loop below + sub edx, bpp // edx ==> Raw(x-bpp) +davglp2: + // Raw(x) = Avg(x) + ((Raw(x-bpp) + Prior(x))/2) + xor eax, eax + mov cl, [esi + ebx] // load cl with Prior(x) + mov al, [edx + ebx] // load al with Raw(x-bpp) + add ax, cx + inc ebx + shr ax, 1 // divide by 2 + add al, [edi+ebx-1] // Add Avg(x); -1 to offset inc ebx + cmp ebx, FullLength // Check if at end of array + mov [edi+ebx-1], al // Write back Raw(x); + // mov does not affect flags; -1 to offset inc ebx + jb davglp2 +davgend: + emms // End MMX instructions; prep for possible FP instrs. + } // end _asm block +} + +// Optimized code for PNG Paeth filter decoder +void /* PRIVATE */ +png_read_filter_row_mmx_paeth(png_row_infop row_info, png_bytep row, + png_bytep prev_row) +{ + png_uint_32 FullLength; + png_uint_32 MMXLength; + //png_uint_32 len; + int bpp; + int diff; + //int ptemp; + int patemp, pbtemp, pctemp; + + bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel + FullLength = row_info->rowbytes; // # of bytes to filter + _asm + { + xor ebx, ebx // ebx ==> x offset + mov edi, row + xor edx, edx // edx ==> x-bpp offset + mov esi, prev_row + xor eax, eax + + // Compute the Raw value for the first bpp bytes + // Note: the formula works out to be always + // Paeth(x) = Raw(x) + Prior(x) where x < bpp +dpthrlp: + mov al, [edi + ebx] + add al, [esi + ebx] + inc ebx + cmp ebx, bpp + mov [edi + ebx - 1], al + jb dpthrlp + // get # of bytes to alignment + mov diff, edi // take start of row + add diff, ebx // add bpp + xor ecx, ecx + add diff, 0xf // add 7 + 8 to incr past alignment boundary + and diff, 0xfffffff8 // mask to alignment boundary + sub diff, edi // subtract from start ==> value ebx at alignment + jz dpthgo + // fix alignment +dpthlp1: + xor eax, eax + // pav = p - a = (a + b - c) - a = b - c + mov al, [esi + ebx] // load Prior(x) into al + mov cl, [esi + edx] // load Prior(x-bpp) into cl + sub eax, ecx // subtract Prior(x-bpp) + mov patemp, eax // Save pav for later use + xor eax, eax + // pbv = p - b = (a + b - c) - b = a - c + mov al, [edi + edx] // load Raw(x-bpp) into al + sub eax, ecx // subtract Prior(x-bpp) + mov ecx, eax + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + add eax, patemp // pcv = pav + pbv + // pc = abs(pcv) + test eax, 0x80000000 + jz dpthpca + neg eax // reverse sign of neg values +dpthpca: + mov pctemp, eax // save pc for later use + // pb = abs(pbv) + test ecx, 0x80000000 + jz dpthpba + neg ecx // reverse sign of neg values +dpthpba: + mov pbtemp, ecx // save pb for later use + // pa = abs(pav) + mov eax, patemp + test eax, 0x80000000 + jz dpthpaa + neg eax // reverse sign of neg values +dpthpaa: + mov patemp, eax // save pa for later use + // test if pa <= pb + cmp eax, ecx + jna dpthabb + // pa > pb; now test if pb <= pc + cmp ecx, pctemp + jna dpthbbc + // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + mov cl, [esi + edx] // load Prior(x-bpp) into cl + jmp dpthpaeth +dpthbbc: + // pb <= pc; Raw(x) = Paeth(x) + Prior(x) + mov cl, [esi + ebx] // load Prior(x) into cl + jmp dpthpaeth +dpthabb: + // pa <= pb; now test if pa <= pc + cmp eax, pctemp + jna dpthabc + // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + mov cl, [esi + edx] // load Prior(x-bpp) into cl + jmp dpthpaeth +dpthabc: + // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) + mov cl, [edi + edx] // load Raw(x-bpp) into cl +dpthpaeth: + inc ebx + inc edx + // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 + add [edi + ebx - 1], cl + cmp ebx, diff + jb dpthlp1 +dpthgo: + mov ecx, FullLength + mov eax, ecx + sub eax, ebx // subtract alignment fix + and eax, 0x00000007 // calc bytes over mult of 8 + sub ecx, eax // drop over bytes from original length + mov MMXLength, ecx + } // end _asm block + // Now do the math for the rest of the row + switch ( bpp ) + { + case 3: + { + ActiveMask.use = 0x0000000000ffffff; + ActiveMaskEnd.use = 0xffff000000000000; + ShiftBpp.use = 24; // == bpp(3) * 8 + ShiftRem.use = 40; // == 64 - 24 + _asm + { + mov ebx, diff + mov edi, row + mov esi, prev_row + pxor mm0, mm0 + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm1, [edi+ebx-8] +dpth3lp: + psrlq mm1, ShiftRem // shift last 3 bytes to 1st 3 bytes + movq mm2, [esi + ebx] // load b=Prior(x) + punpcklbw mm1, mm0 // Unpack High bytes of a + movq mm3, [esi+ebx-8] // Prep c=Prior(x-bpp) bytes + punpcklbw mm2, mm0 // Unpack High bytes of b + psrlq mm3, ShiftRem // shift last 3 bytes to 1st 3 bytes + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + punpcklbw mm3, mm0 // Unpack High bytes of c + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + psubw mm4, mm3 + pxor mm7, mm7 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + paddw mm6, mm5 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + psubw mm4, mm0 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm5, mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pxor mm1, mm1 + pand mm3, mm7 + pandn mm7, mm0 + paddw mm7, mm3 + pxor mm0, mm0 + packuswb mm7, mm1 + movq mm3, [esi + ebx] // load c=Prior(x-bpp) + pand mm7, ActiveMask + movq mm2, mm3 // load b=Prior(x) step 1 + paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) + punpcklbw mm3, mm0 // Unpack High bytes of c + movq [edi + ebx], mm7 // write back updated value + movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp) + // Now do Paeth for 2nd set of bytes (3-5) + psrlq mm2, ShiftBpp // load b=Prior(x) step 2 + punpcklbw mm1, mm0 // Unpack High bytes of a + pxor mm7, mm7 + punpcklbw mm2, mm0 // Unpack High bytes of b + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + psubw mm5, mm3 + psubw mm4, mm3 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = + // pav + pbv = pbv + pav + movq mm6, mm5 + paddw mm6, mm4 + + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm5 // Create mask pbv bytes < 0 + pcmpgtw mm7, mm4 // Create mask pav bytes < 0 + pand mm0, mm5 // Only pbv bytes < 0 in mm0 + pand mm7, mm4 // Only pav bytes < 0 in mm7 + psubw mm5, mm0 + psubw mm4, mm7 + psubw mm5, mm0 + psubw mm4, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + movq mm2, [esi + ebx] // load b=Prior(x) + pand mm3, mm7 + pandn mm7, mm0 + pxor mm1, mm1 + paddw mm7, mm3 + pxor mm0, mm0 + packuswb mm7, mm1 + movq mm3, mm2 // load c=Prior(x-bpp) step 1 + pand mm7, ActiveMask + punpckhbw mm2, mm0 // Unpack High bytes of b + psllq mm7, ShiftBpp // Shift bytes to 2nd group of 3 bytes + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) + psllq mm3, ShiftBpp // load c=Prior(x-bpp) step 2 + movq [edi + ebx], mm7 // write back updated value + movq mm1, mm7 + punpckhbw mm3, mm0 // Unpack High bytes of c + psllq mm1, ShiftBpp // Shift bytes + // Now mm1 will be used as Raw(x-bpp) + // Now do Paeth for 3rd, and final, set of bytes (6-7) + pxor mm7, mm7 + punpckhbw mm1, mm0 // Unpack High bytes of a + psubw mm4, mm3 + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + pxor mm0, mm0 + paddw mm6, mm5 + + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + pandn mm0, mm1 + pandn mm7, mm4 + paddw mm0, mm2 + paddw mm7, mm5 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pand mm3, mm7 + pandn mm7, mm0 + paddw mm7, mm3 + pxor mm1, mm1 + packuswb mm1, mm7 + // Step ebx to next set of 8 bytes and repeat loop til done + add ebx, 8 + pand mm1, ActiveMaskEnd + paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) + + cmp ebx, MMXLength + pxor mm0, mm0 // pxor does not affect flags + movq [edi + ebx - 8], mm1 // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + // mm3 ready to be used as Prior(x-bpp) next loop + jb dpth3lp + } // end _asm block + } + break; + + case 6: + case 7: + case 5: + { + ActiveMask.use = 0x00000000ffffffff; + ActiveMask2.use = 0xffffffff00000000; + ShiftBpp.use = bpp << 3; // == bpp * 8 + ShiftRem.use = 64 - ShiftBpp.use; + _asm + { + mov ebx, diff + mov edi, row + mov esi, prev_row + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm1, [edi+ebx-8] + pxor mm0, mm0 +dpth6lp: + // Must shift to position Raw(x-bpp) data + psrlq mm1, ShiftRem + // Do first set of 4 bytes + movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes + punpcklbw mm1, mm0 // Unpack Low bytes of a + movq mm2, [esi + ebx] // load b=Prior(x) + punpcklbw mm2, mm0 // Unpack Low bytes of b + // Must shift to position Prior(x-bpp) data + psrlq mm3, ShiftRem + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + punpcklbw mm3, mm0 // Unpack Low bytes of c + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + psubw mm4, mm3 + pxor mm7, mm7 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + paddw mm6, mm5 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + psubw mm4, mm0 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm5, mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pxor mm1, mm1 + pand mm3, mm7 + pandn mm7, mm0 + paddw mm7, mm3 + pxor mm0, mm0 + packuswb mm7, mm1 + movq mm3, [esi + ebx - 8] // load c=Prior(x-bpp) + pand mm7, ActiveMask + psrlq mm3, ShiftRem + movq mm2, [esi + ebx] // load b=Prior(x) step 1 + paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) + movq mm6, mm2 + movq [edi + ebx], mm7 // write back updated value + movq mm1, [edi+ebx-8] + psllq mm6, ShiftBpp + movq mm5, mm7 + psrlq mm1, ShiftRem + por mm3, mm6 + psllq mm5, ShiftBpp + punpckhbw mm3, mm0 // Unpack High bytes of c + por mm1, mm5 + // Do second set of 4 bytes + punpckhbw mm2, mm0 // Unpack High bytes of b + punpckhbw mm1, mm0 // Unpack High bytes of a + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + psubw mm4, mm3 + pxor mm7, mm7 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + paddw mm6, mm5 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + psubw mm4, mm0 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm5, mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pxor mm1, mm1 + pand mm3, mm7 + pandn mm7, mm0 + pxor mm1, mm1 + paddw mm7, mm3 + pxor mm0, mm0 + // Step ex to next set of 8 bytes and repeat loop til done + add ebx, 8 + packuswb mm1, mm7 + paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) + cmp ebx, MMXLength + movq [edi + ebx - 8], mm1 // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + jb dpth6lp + } // end _asm block + } + break; + + case 4: + { + ActiveMask.use = 0x00000000ffffffff; + _asm { + mov ebx, diff + mov edi, row + mov esi, prev_row + pxor mm0, mm0 + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm1, [edi+ebx-8] // Only time should need to read + // a=Raw(x-bpp) bytes +dpth4lp: + // Do first set of 4 bytes + movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes + punpckhbw mm1, mm0 // Unpack Low bytes of a + movq mm2, [esi + ebx] // load b=Prior(x) + punpcklbw mm2, mm0 // Unpack High bytes of b + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + punpckhbw mm3, mm0 // Unpack High bytes of c + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + psubw mm4, mm3 + pxor mm7, mm7 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + paddw mm6, mm5 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + psubw mm4, mm0 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm5, mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pxor mm1, mm1 + pand mm3, mm7 + pandn mm7, mm0 + paddw mm7, mm3 + pxor mm0, mm0 + packuswb mm7, mm1 + movq mm3, [esi + ebx] // load c=Prior(x-bpp) + pand mm7, ActiveMask + movq mm2, mm3 // load b=Prior(x) step 1 + paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) + punpcklbw mm3, mm0 // Unpack High bytes of c + movq [edi + ebx], mm7 // write back updated value + movq mm1, mm7 // Now mm1 will be used as Raw(x-bpp) + // Do second set of 4 bytes + punpckhbw mm2, mm0 // Unpack Low bytes of b + punpcklbw mm1, mm0 // Unpack Low bytes of a + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + psubw mm4, mm3 + pxor mm7, mm7 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + paddw mm6, mm5 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + psubw mm4, mm0 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm5, mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pxor mm1, mm1 + pand mm3, mm7 + pandn mm7, mm0 + pxor mm1, mm1 + paddw mm7, mm3 + pxor mm0, mm0 + // Step ex to next set of 8 bytes and repeat loop til done + add ebx, 8 + packuswb mm1, mm7 + paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) + cmp ebx, MMXLength + movq [edi + ebx - 8], mm1 // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + jb dpth4lp + } // end _asm block + } + break; + case 8: // bpp == 8 + { + ActiveMask.use = 0x00000000ffffffff; + _asm { + mov ebx, diff + mov edi, row + mov esi, prev_row + pxor mm0, mm0 + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm1, [edi+ebx-8] // Only time should need to read + // a=Raw(x-bpp) bytes +dpth8lp: + // Do first set of 4 bytes + movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes + punpcklbw mm1, mm0 // Unpack Low bytes of a + movq mm2, [esi + ebx] // load b=Prior(x) + punpcklbw mm2, mm0 // Unpack Low bytes of b + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + punpcklbw mm3, mm0 // Unpack Low bytes of c + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + psubw mm4, mm3 + pxor mm7, mm7 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + paddw mm6, mm5 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + psubw mm4, mm0 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm5, mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pxor mm1, mm1 + pand mm3, mm7 + pandn mm7, mm0 + paddw mm7, mm3 + pxor mm0, mm0 + packuswb mm7, mm1 + movq mm3, [esi+ebx-8] // read c=Prior(x-bpp) bytes + pand mm7, ActiveMask + movq mm2, [esi + ebx] // load b=Prior(x) + paddb mm7, [edi + ebx] // add Paeth predictor with Raw(x) + punpckhbw mm3, mm0 // Unpack High bytes of c + movq [edi + ebx], mm7 // write back updated value + movq mm1, [edi+ebx-8] // read a=Raw(x-bpp) bytes + + // Do second set of 4 bytes + punpckhbw mm2, mm0 // Unpack High bytes of b + punpckhbw mm1, mm0 // Unpack High bytes of a + // pav = p - a = (a + b - c) - a = b - c + movq mm4, mm2 + // pbv = p - b = (a + b - c) - b = a - c + movq mm5, mm1 + psubw mm4, mm3 + pxor mm7, mm7 + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + movq mm6, mm4 + psubw mm5, mm3 + // pa = abs(p-a) = abs(pav) + // pb = abs(p-b) = abs(pbv) + // pc = abs(p-c) = abs(pcv) + pcmpgtw mm0, mm4 // Create mask pav bytes < 0 + paddw mm6, mm5 + pand mm0, mm4 // Only pav bytes < 0 in mm7 + pcmpgtw mm7, mm5 // Create mask pbv bytes < 0 + psubw mm4, mm0 + pand mm7, mm5 // Only pbv bytes < 0 in mm0 + psubw mm4, mm0 + psubw mm5, mm7 + pxor mm0, mm0 + pcmpgtw mm0, mm6 // Create mask pcv bytes < 0 + pand mm0, mm6 // Only pav bytes < 0 in mm7 + psubw mm5, mm7 + psubw mm6, mm0 + // test pa <= pb + movq mm7, mm4 + psubw mm6, mm0 + pcmpgtw mm7, mm5 // pa > pb? + movq mm0, mm7 + // use mm7 mask to merge pa & pb + pand mm5, mm7 + // use mm0 mask copy to merge a & b + pand mm2, mm0 + pandn mm7, mm4 + pandn mm0, mm1 + paddw mm7, mm5 + paddw mm0, mm2 + // test ((pa <= pb)? pa:pb) <= pc + pcmpgtw mm7, mm6 // pab > pc? + pxor mm1, mm1 + pand mm3, mm7 + pandn mm7, mm0 + pxor mm1, mm1 + paddw mm7, mm3 + pxor mm0, mm0 + // Step ex to next set of 8 bytes and repeat loop til done + add ebx, 8 + packuswb mm1, mm7 + paddb mm1, [edi + ebx - 8] // add Paeth predictor with Raw(x) + cmp ebx, MMXLength + movq [edi + ebx - 8], mm1 // write back updated value + // mm1 will be used as Raw(x-bpp) next loop + jb dpth8lp + } // end _asm block + } + break; + + case 1: // bpp = 1 + case 2: // bpp = 2 + default: // bpp > 8 + { + _asm { + mov ebx, diff + cmp ebx, FullLength + jnb dpthdend + mov edi, row + mov esi, prev_row + // Do Paeth decode for remaining bytes + mov edx, ebx + xor ecx, ecx // zero ecx before using cl & cx in loop below + sub edx, bpp // Set edx = ebx - bpp +dpthdlp: + xor eax, eax + // pav = p - a = (a + b - c) - a = b - c + mov al, [esi + ebx] // load Prior(x) into al + mov cl, [esi + edx] // load Prior(x-bpp) into cl + sub eax, ecx // subtract Prior(x-bpp) + mov patemp, eax // Save pav for later use + xor eax, eax + // pbv = p - b = (a + b - c) - b = a - c + mov al, [edi + edx] // load Raw(x-bpp) into al + sub eax, ecx // subtract Prior(x-bpp) + mov ecx, eax + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + add eax, patemp // pcv = pav + pbv + // pc = abs(pcv) + test eax, 0x80000000 + jz dpthdpca + neg eax // reverse sign of neg values +dpthdpca: + mov pctemp, eax // save pc for later use + // pb = abs(pbv) + test ecx, 0x80000000 + jz dpthdpba + neg ecx // reverse sign of neg values +dpthdpba: + mov pbtemp, ecx // save pb for later use + // pa = abs(pav) + mov eax, patemp + test eax, 0x80000000 + jz dpthdpaa + neg eax // reverse sign of neg values +dpthdpaa: + mov patemp, eax // save pa for later use + // test if pa <= pb + cmp eax, ecx + jna dpthdabb + // pa > pb; now test if pb <= pc + cmp ecx, pctemp + jna dpthdbbc + // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + mov cl, [esi + edx] // load Prior(x-bpp) into cl + jmp dpthdpaeth +dpthdbbc: + // pb <= pc; Raw(x) = Paeth(x) + Prior(x) + mov cl, [esi + ebx] // load Prior(x) into cl + jmp dpthdpaeth +dpthdabb: + // pa <= pb; now test if pa <= pc + cmp eax, pctemp + jna dpthdabc + // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + mov cl, [esi + edx] // load Prior(x-bpp) into cl + jmp dpthdpaeth +dpthdabc: + // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) + mov cl, [edi + edx] // load Raw(x-bpp) into cl +dpthdpaeth: + inc ebx + inc edx + // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 + add [edi + ebx - 1], cl + cmp ebx, FullLength + jb dpthdlp +dpthdend: + } // end _asm block + } + return; // No need to go further with this one + } // end switch ( bpp ) + _asm + { + // MMX acceleration complete now do clean-up + // Check if any remaining bytes left to decode + mov ebx, MMXLength + cmp ebx, FullLength + jnb dpthend + mov edi, row + mov esi, prev_row + // Do Paeth decode for remaining bytes + mov edx, ebx + xor ecx, ecx // zero ecx before using cl & cx in loop below + sub edx, bpp // Set edx = ebx - bpp +dpthlp2: + xor eax, eax + // pav = p - a = (a + b - c) - a = b - c + mov al, [esi + ebx] // load Prior(x) into al + mov cl, [esi + edx] // load Prior(x-bpp) into cl + sub eax, ecx // subtract Prior(x-bpp) + mov patemp, eax // Save pav for later use + xor eax, eax + // pbv = p - b = (a + b - c) - b = a - c + mov al, [edi + edx] // load Raw(x-bpp) into al + sub eax, ecx // subtract Prior(x-bpp) + mov ecx, eax + // pcv = p - c = (a + b - c) -c = (a - c) + (b - c) = pav + pbv + add eax, patemp // pcv = pav + pbv + // pc = abs(pcv) + test eax, 0x80000000 + jz dpthpca2 + neg eax // reverse sign of neg values +dpthpca2: + mov pctemp, eax // save pc for later use + // pb = abs(pbv) + test ecx, 0x80000000 + jz dpthpba2 + neg ecx // reverse sign of neg values +dpthpba2: + mov pbtemp, ecx // save pb for later use + // pa = abs(pav) + mov eax, patemp + test eax, 0x80000000 + jz dpthpaa2 + neg eax // reverse sign of neg values +dpthpaa2: + mov patemp, eax // save pa for later use + // test if pa <= pb + cmp eax, ecx + jna dpthabb2 + // pa > pb; now test if pb <= pc + cmp ecx, pctemp + jna dpthbbc2 + // pb > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + mov cl, [esi + edx] // load Prior(x-bpp) into cl + jmp dpthpaeth2 +dpthbbc2: + // pb <= pc; Raw(x) = Paeth(x) + Prior(x) + mov cl, [esi + ebx] // load Prior(x) into cl + jmp dpthpaeth2 +dpthabb2: + // pa <= pb; now test if pa <= pc + cmp eax, pctemp + jna dpthabc2 + // pa > pc; Raw(x) = Paeth(x) + Prior(x-bpp) + mov cl, [esi + edx] // load Prior(x-bpp) into cl + jmp dpthpaeth2 +dpthabc2: + // pa <= pc; Raw(x) = Paeth(x) + Raw(x-bpp) + mov cl, [edi + edx] // load Raw(x-bpp) into cl +dpthpaeth2: + inc ebx + inc edx + // Raw(x) = (Paeth(x) + Paeth_Predictor( a, b, c )) mod 256 + add [edi + ebx - 1], cl + cmp ebx, FullLength + jb dpthlp2 +dpthend: + emms // End MMX instructions; prep for possible FP instrs. + } // end _asm block +} + +// Optimized code for PNG Sub filter decoder +void /* PRIVATE */ +png_read_filter_row_mmx_sub(png_row_infop row_info, png_bytep row) +{ + //int test; + int bpp; + png_uint_32 FullLength; + png_uint_32 MMXLength; + int diff; + + bpp = (row_info->pixel_depth + 7) >> 3; // Get # bytes per pixel + FullLength = row_info->rowbytes - bpp; // # of bytes to filter + _asm { + mov edi, row + mov esi, edi // lp = row + add edi, bpp // rp = row + bpp + xor eax, eax + // get # of bytes to alignment + mov diff, edi // take start of row + add diff, 0xf // add 7 + 8 to incr past + // alignment boundary + xor ebx, ebx + and diff, 0xfffffff8 // mask to alignment boundary + sub diff, edi // subtract from start ==> value + // ebx at alignment + jz dsubgo + // fix alignment +dsublp1: + mov al, [esi+ebx] + add [edi+ebx], al + inc ebx + cmp ebx, diff + jb dsublp1 +dsubgo: + mov ecx, FullLength + mov edx, ecx + sub edx, ebx // subtract alignment fix + and edx, 0x00000007 // calc bytes over mult of 8 + sub ecx, edx // drop over bytes from length + mov MMXLength, ecx + } // end _asm block + + // Now do the math for the rest of the row + switch ( bpp ) + { + case 3: + { + ActiveMask.use = 0x0000ffffff000000; + ShiftBpp.use = 24; // == 3 * 8 + ShiftRem.use = 40; // == 64 - 24 + _asm { + mov edi, row + movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group + mov esi, edi // lp = row + add edi, bpp // rp = row + bpp + movq mm6, mm7 + mov ebx, diff + psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active + // byte group + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm1, [edi+ebx-8] +dsub3lp: + psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes + // no need for mask; shift clears inactive bytes + // Add 1st active group + movq mm0, [edi+ebx] + paddb mm0, mm1 + // Add 2nd active group + movq mm1, mm0 // mov updated Raws to mm1 + psllq mm1, ShiftBpp // shift data to position correctly + pand mm1, mm7 // mask to use only 2nd active group + paddb mm0, mm1 + // Add 3rd active group + movq mm1, mm0 // mov updated Raws to mm1 + psllq mm1, ShiftBpp // shift data to position correctly + pand mm1, mm6 // mask to use only 3rd active group + add ebx, 8 + paddb mm0, mm1 + cmp ebx, MMXLength + movq [edi+ebx-8], mm0 // Write updated Raws back to array + // Prep for doing 1st add at top of loop + movq mm1, mm0 + jb dsub3lp + } // end _asm block + } + break; + + case 1: + { + // Placed here just in case this is a duplicate of the + // non-MMX code for the SUB filter in png_read_filter_row below + // + // png_bytep rp; + // png_bytep lp; + // png_uint_32 i; + // bpp = (row_info->pixel_depth + 7) >> 3; + // for (i = (png_uint_32)bpp, rp = row + bpp, lp = row; + // i < row_info->rowbytes; i++, rp++, lp++) + // { + // *rp = (png_byte)(((int)(*rp) + (int)(*lp)) & 0xff); + // } + _asm { + mov ebx, diff + mov edi, row + cmp ebx, FullLength + jnb dsub1end + mov esi, edi // lp = row + xor eax, eax + add edi, bpp // rp = row + bpp +dsub1lp: + mov al, [esi+ebx] + add [edi+ebx], al + inc ebx + cmp ebx, FullLength + jb dsub1lp +dsub1end: + } // end _asm block + } + return; + + case 6: + case 7: + case 4: + case 5: + { + ShiftBpp.use = bpp << 3; + ShiftRem.use = 64 - ShiftBpp.use; + _asm { + mov edi, row + mov ebx, diff + mov esi, edi // lp = row + add edi, bpp // rp = row + bpp + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm1, [edi+ebx-8] +dsub4lp: + psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes + // no need for mask; shift clears inactive bytes + movq mm0, [edi+ebx] + paddb mm0, mm1 + // Add 2nd active group + movq mm1, mm0 // mov updated Raws to mm1 + psllq mm1, ShiftBpp // shift data to position correctly + // there is no need for any mask + // since shift clears inactive bits/bytes + add ebx, 8 + paddb mm0, mm1 + cmp ebx, MMXLength + movq [edi+ebx-8], mm0 + movq mm1, mm0 // Prep for doing 1st add at top of loop + jb dsub4lp + } // end _asm block + } + break; + + case 2: + { + ActiveMask.use = 0x00000000ffff0000; + ShiftBpp.use = 16; // == 2 * 8 + ShiftRem.use = 48; // == 64 - 16 + _asm { + movq mm7, ActiveMask // Load ActiveMask for 2nd active byte group + mov ebx, diff + movq mm6, mm7 + mov edi, row + psllq mm6, ShiftBpp // Move mask in mm6 to cover 3rd active + // byte group + mov esi, edi // lp = row + movq mm5, mm6 + add edi, bpp // rp = row + bpp + psllq mm5, ShiftBpp // Move mask in mm5 to cover 4th active + // byte group + // PRIME the pump (load the first Raw(x-bpp) data set + movq mm1, [edi+ebx-8] +dsub2lp: + // Add 1st active group + psrlq mm1, ShiftRem // Shift data for adding 1st bpp bytes + // no need for mask; shift clears inactive + // bytes + movq mm0, [edi+ebx] + paddb mm0, mm1 + // Add 2nd active group + movq mm1, mm0 // mov updated Raws to mm1 + psllq mm1, ShiftBpp // shift data to position correctly + pand mm1, mm7 // mask to use only 2nd active group + paddb mm0, mm1 + // Add 3rd active group + movq mm1, mm0 // mov updated Raws to mm1 + psllq mm1, ShiftBpp // shift data to position correctly + pand mm1, mm6 // mask to use only 3rd active group + paddb mm0, mm1 + // Add 4th active group + movq mm1, mm0 // mov updated Raws to mm1 + psllq mm1, ShiftBpp // shift data to position correctly + pand mm1, mm5 // mask to use only 4th active group + add ebx, 8 + paddb mm0, mm1 + cmp ebx, MMXLength + movq [edi+ebx-8], mm0 // Write updated Raws back to array + movq mm1, mm0 // Prep for doing 1st add at top of loop + jb dsub2lp + } // end _asm block + } + break; + case 8: + { + _asm { + mov edi, row + mov ebx, diff + mov esi, edi // lp = row + add edi, bpp // rp = row + bpp + mov ecx, MMXLength + movq mm7, [edi+ebx-8] // PRIME the pump (load the first + // Raw(x-bpp) data set + and ecx, 0x0000003f // calc bytes over mult of 64 +dsub8lp: + movq mm0, [edi+ebx] // Load Sub(x) for 1st 8 bytes + paddb mm0, mm7 + movq mm1, [edi+ebx+8] // Load Sub(x) for 2nd 8 bytes + movq [edi+ebx], mm0 // Write Raw(x) for 1st 8 bytes + // Now mm0 will be used as Raw(x-bpp) for + // the 2nd group of 8 bytes. This will be + // repeated for each group of 8 bytes with + // the 8th group being used as the Raw(x-bpp) + // for the 1st group of the next loop. + paddb mm1, mm0 + movq mm2, [edi+ebx+16] // Load Sub(x) for 3rd 8 bytes + movq [edi+ebx+8], mm1 // Write Raw(x) for 2nd 8 bytes + paddb mm2, mm1 + movq mm3, [edi+ebx+24] // Load Sub(x) for 4th 8 bytes + movq [edi+ebx+16], mm2 // Write Raw(x) for 3rd 8 bytes + paddb mm3, mm2 + movq mm4, [edi+ebx+32] // Load Sub(x) for 5th 8 bytes + movq [edi+ebx+24], mm3 // Write Raw(x) for 4th 8 bytes + paddb mm4, mm3 + movq mm5, [edi+ebx+40] // Load Sub(x) for 6th 8 bytes + movq [edi+ebx+32], mm4 // Write Raw(x) for 5th 8 bytes + paddb mm5, mm4 + movq mm6, [edi+ebx+48] // Load Sub(x) for 7th 8 bytes + movq [edi+ebx+40], mm5 // Write Raw(x) for 6th 8 bytes + paddb mm6, mm5 + movq mm7, [edi+ebx+56] // Load Sub(x) for 8th 8 bytes + movq [edi+ebx+48], mm6 // Write Raw(x) for 7th 8 bytes + add ebx, 64 + paddb mm7, mm6 + cmp ebx, ecx + movq [edi+ebx-8], mm7 // Write Raw(x) for 8th 8 bytes + jb dsub8lp + cmp ebx, MMXLength + jnb dsub8lt8 +dsub8lpA: + movq mm0, [edi+ebx] + add ebx, 8 + paddb mm0, mm7 + cmp ebx, MMXLength + movq [edi+ebx-8], mm0 // use -8 to offset early add to ebx + movq mm7, mm0 // Move calculated Raw(x) data to mm1 to + // be the new Raw(x-bpp) for the next loop + jb dsub8lpA +dsub8lt8: + } // end _asm block + } + break; + + default: // bpp greater than 8 bytes + { + _asm { + mov ebx, diff + mov edi, row + mov esi, edi // lp = row + add edi, bpp // rp = row + bpp +dsubAlp: + movq mm0, [edi+ebx] + movq mm1, [esi+ebx] + add ebx, 8 + paddb mm0, mm1 + cmp ebx, MMXLength + movq [edi+ebx-8], mm0 // mov does not affect flags; -8 to offset + // add ebx + jb dsubAlp + } // end _asm block + } + break; + + } // end switch ( bpp ) + + _asm { + mov ebx, MMXLength + mov edi, row + cmp ebx, FullLength + jnb dsubend + mov esi, edi // lp = row + xor eax, eax + add edi, bpp // rp = row + bpp +dsublp2: + mov al, [esi+ebx] + add [edi+ebx], al + inc ebx + cmp ebx, FullLength + jb dsublp2 +dsubend: + emms // End MMX instructions; prep for possible FP instrs. + } // end _asm block +} + +// Optimized code for PNG Up filter decoder +void /* PRIVATE */ +png_read_filter_row_mmx_up(png_row_infop row_info, png_bytep row, + png_bytep prev_row) +{ + png_uint_32 len; + len = row_info->rowbytes; // # of bytes to filter + _asm { + mov edi, row + // get # of bytes to alignment + mov ecx, edi + xor ebx, ebx + add ecx, 0x7 + xor eax, eax + and ecx, 0xfffffff8 + mov esi, prev_row + sub ecx, edi + jz dupgo + // fix alignment +duplp1: + mov al, [edi+ebx] + add al, [esi+ebx] + inc ebx + cmp ebx, ecx + mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx + jb duplp1 +dupgo: + mov ecx, len + mov edx, ecx + sub edx, ebx // subtract alignment fix + and edx, 0x0000003f // calc bytes over mult of 64 + sub ecx, edx // drop over bytes from length + // Unrolled loop - use all MMX registers and interleave to reduce + // number of branch instructions (loops) and reduce partial stalls +duploop: + movq mm1, [esi+ebx] + movq mm0, [edi+ebx] + movq mm3, [esi+ebx+8] + paddb mm0, mm1 + movq mm2, [edi+ebx+8] + movq [edi+ebx], mm0 + paddb mm2, mm3 + movq mm5, [esi+ebx+16] + movq [edi+ebx+8], mm2 + movq mm4, [edi+ebx+16] + movq mm7, [esi+ebx+24] + paddb mm4, mm5 + movq mm6, [edi+ebx+24] + movq [edi+ebx+16], mm4 + paddb mm6, mm7 + movq mm1, [esi+ebx+32] + movq [edi+ebx+24], mm6 + movq mm0, [edi+ebx+32] + movq mm3, [esi+ebx+40] + paddb mm0, mm1 + movq mm2, [edi+ebx+40] + movq [edi+ebx+32], mm0 + paddb mm2, mm3 + movq mm5, [esi+ebx+48] + movq [edi+ebx+40], mm2 + movq mm4, [edi+ebx+48] + movq mm7, [esi+ebx+56] + paddb mm4, mm5 + movq mm6, [edi+ebx+56] + movq [edi+ebx+48], mm4 + add ebx, 64 + paddb mm6, mm7 + cmp ebx, ecx + movq [edi+ebx-8], mm6 // (+56)movq does not affect flags; + // -8 to offset add ebx + jb duploop + + cmp edx, 0 // Test for bytes over mult of 64 + jz dupend + + + // 2 lines added by lcreeve@netins.net + // (mail 11 Jul 98 in png-implement list) + cmp edx, 8 //test for less than 8 bytes + jb duplt8 + + + add ecx, edx + and edx, 0x00000007 // calc bytes over mult of 8 + sub ecx, edx // drop over bytes from length + jz duplt8 + // Loop using MMX registers mm0 & mm1 to update 8 bytes simultaneously +duplpA: + movq mm1, [esi+ebx] + movq mm0, [edi+ebx] + add ebx, 8 + paddb mm0, mm1 + cmp ebx, ecx + movq [edi+ebx-8], mm0 // movq does not affect flags; -8 to offset add ebx + jb duplpA + cmp edx, 0 // Test for bytes over mult of 8 + jz dupend +duplt8: + xor eax, eax + add ecx, edx // move over byte count into counter + // Loop using x86 registers to update remaining bytes +duplp2: + mov al, [edi + ebx] + add al, [esi + ebx] + inc ebx + cmp ebx, ecx + mov [edi + ebx-1], al // mov does not affect flags; -1 to offset inc ebx + jb duplp2 +dupend: + // Conversion of filtered row completed + emms // End MMX instructions; prep for possible FP instrs. + } // end _asm block +} + + +// Optimized png_read_filter_row routines +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep + row, png_bytep prev_row, int filter) +{ +#ifdef PNG_DEBUG + char filnm[10]; +#endif + + if (mmx_supported == 2) { + png_mmx_support(); + } + +#ifdef PNG_DEBUG + png_debug(1, "in png_read_filter_row\n"); + switch (filter) + { + case 0: sprintf(filnm, "none"); + break; + case 1: sprintf(filnm, "sub-%s", "MMX"); + break; + case 2: sprintf(filnm, "up-%s", "MMX"); + break; + case 3: sprintf(filnm, "avg-%s", "MMX"); + break; + case 4: sprintf(filnm, "Paeth-%s", "MMX"); + break; + default: sprintf(filnm, "unknw"); + break; + } + png_debug2(0,"row=%5d, %s, ", png_ptr->row_number, filnm); + png_debug2(0, "pd=%2d, b=%d, ", (int)row_info->pixel_depth, + (int)((row_info->pixel_depth + 7) >> 3)); + png_debug1(0,"len=%8d, ", row_info->rowbytes); +#endif /* PNG_DEBUG */ + + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + + case PNG_FILTER_VALUE_SUB: + { + if ( + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_sub(row_info, row); + } + else + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + } + break; + } + + case PNG_FILTER_VALUE_UP: + { + if ( + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_up(row_info, row, prev_row); + } + else + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; ++i) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + } + break; + } + + case PNG_FILTER_VALUE_AVG: + { + if ( + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_avg(row_info, row, prev_row); + } + else + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) >> 1)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++ + *lp++) >> 1)) & 0xff); + rp++; + } + } + break; + } + + case PNG_FILTER_VALUE_PAETH: + { + if ( + (row_info->pixel_depth >= PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT) && + (row_info->rowbytes >= PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT)) + { + png_read_filter_row_mmx_paeth(row_info, row, prev_row); + } + else + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) // use leftover rp,pp + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + } + break; + } + + default: + png_warning(png_ptr, "Ignoring bad row filter type"); + *row=0; + break; + } +} + +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED && PNG_USE_PNGVCRD */ diff --git a/Utilities/vtkpng/pngwio.c b/Utilities/vtkpng/pngwio.c new file mode 100644 index 0000000..23f881e --- /dev/null +++ b/Utilities/vtkpng/pngwio.c @@ -0,0 +1,228 @@ + +/* pngwio.c - functions for data output + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + writes to a file pointer. Note that this routine sometimes gets called + with very small lengths, so you should implement some kind of simple + buffering if you are using unbuffered writes. This should never be asked + to write more than 64K on a 16 bit machine. */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL write function"); +} + +#if !defined(PNG_NO_STDIO) +/* This is the function that does the actual writing of data. If you are + not writing to a standard C stream, you should create a replacement + write_data function and use it at run time with png_set_write_fn(), rather + than changing the library. */ +#ifndef USE_FAR_KEYWORD +static void /* PRIVATE */ +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + +#if defined(_WIN32_WCE) + if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); +#endif + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* this is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void /* PRIVATE */ +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) + check = 0; +#else + check = fwrite(near_data, 1, length, io_ptr); +#endif + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* copy far buffer to near buffer */ +#if defined(_WIN32_WCE) + if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) + err = 0; +#else + err = fwrite(buf, 1, written, io_ptr); +#endif + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + to disk). After png_flush is called, there should be no data pending + writing in any buffers. */ +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +#if !defined(PNG_NO_STDIO) +static void /* PRIVATE */ +png_default_flush(png_structp png_ptr) +{ +#if !defined(_WIN32_WCE) + png_FILE_p io_ptr; + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + if (io_ptr != NULL) + fflush(io_ptr); +#endif +} +#endif +#endif + +/* This function allows the application to supply new output functions for + libpng if standard C streams aren't being used. + + This function takes as its arguments: + png_ptr - pointer to a png output data structure + io_ptr - pointer to user supplied structure containing info about + the output functions. May be NULL. + write_data_fn - pointer to a new output function that takes as its + arguments a pointer to a png_struct, a pointer to + data to be written, and a 32-bit unsigned int that is + the number of bytes to be written. The new write + function should call png_error(png_ptr, "Error msg") + to exit and output any fatal error messages. + flush_data_fn - pointer to a new flush function that takes as its + arguments a pointer to a png_struct. After a call to + the flush function, there should be no data in any buffers + or pending transmission. If the output method doesn't do + any buffering of ouput, a function prototype must still be + supplied although it doesn't have to do anything. If + PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + time, output_flush_fn will be ignored, although it must be + supplied for compatibility. */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + png_ptr->io_ptr = io_ptr; + +#if !defined(PNG_NO_STDIO) + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + else + png_ptr->output_flush_fn = png_default_flush; +#else + png_ptr->output_flush_fn = output_flush_fn; +#endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + png_warning(png_ptr, + "Attempted to set both read_data_fn and write_data_fn in"); + png_warning(png_ptr, + "the same structure. Resetting read_data_fn to NULL."); + } +} + +#if defined(USE_FAR_KEYWORD) +#if defined(_MSC_VER) +void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + if(check != 0) + if(FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr,"segment lost in conversion"); + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + if(check != 0) + if(far_ptr != ptr) + png_error(png_ptr,"segment lost in conversion"); + return(near_ptr); +} +# endif +# endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/vtkpng/pngwrite.c b/Utilities/vtkpng/pngwrite.c new file mode 100644 index 0000000..3609d87 --- /dev/null +++ b/Utilities/vtkpng/pngwrite.c @@ -0,0 +1,1447 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* get internal access to png.h */ +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE\n"); + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + png_write_sig(png_ptr); /* write PNG signature */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) + { + png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n"); + png_ptr->mng_features_permitted=0; + } +#endif + /* write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + info_ptr->interlace_type); +#else + 0); +#endif + /* the rest of these check to see if the valid field has the appropriate + flag set, and if it does, writes the chunk. */ +#if defined(PNG_WRITE_gAMA_SUPPORTED) + if (info_ptr->valid & PNG_INFO_gAMA) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_gAMA(png_ptr, info_ptr->gamma); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_sRGB_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif +#if defined(PNG_WRITE_iCCP_SUPPORTED) + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#if defined(PNG_WRITE_sBIT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_cHRM_SUPPORTED) + if (info_ptr->valid & PNG_INFO_cHRM) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_cHRM(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#else +# ifdef PNG_FIXED_POINT_SUPPORTED + png_write_cHRM_fixed(png_ptr, + info_ptr->int_x_white, info_ptr->int_y_white, + info_ptr->int_x_red, info_ptr->int_y_red, + info_ptr->int_x_green, info_ptr->int_y_green, + info_ptr->int_x_blue, info_ptr->int_y_blue); +# endif +#endif + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != HANDLE_CHUNK_NEVER && + up->location && (!(up->location & PNG_HAVE_PLTE)) && + ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info\n"); + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images\n"); + +#if defined(PNG_WRITE_tRNS_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tRNS) + { +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j=0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#if defined(PNG_WRITE_bKGD_SUPPORTED) + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif +#if defined(PNG_WRITE_hIST_SUPPORTED) + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif +#if defined(PNG_WRITE_oFFs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif +#if defined(PNG_WRITE_pCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif +#if defined(PNG_WRITE_sCAL_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sCAL) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#else + png_warning(png_ptr, + "png_write_sCAL not supported; sCAL chunk not written.\n"); +#endif +#endif +#endif +#if defined(PNG_WRITE_pHYs_SUPPORTED) + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif +#if defined(PNG_WRITE_tIME_SUPPORTED) + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif +#if defined(PNG_WRITE_sPLT_SUPPORTED) + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + /* an internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end\n"); + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* see if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#if defined(PNG_WRITE_TEXT_SUPPORTED) + int i; /* local index variable */ +#endif +#if defined(PNG_WRITE_tIME_SUPPORTED) + /* check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); +#endif +#if defined(PNG_WRITE_TEXT_SUPPORTED) + /* loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, + info_ptr->text[i].compression); + /* an internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#if defined(PNG_WRITE_iTXt_SUPPORTED) + /* write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#if defined(PNG_WRITE_zTXt_SUPPORTED) + /* write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text\n"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#if defined(PNG_WRITE_tEXt_SUPPORTED) + /* write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text\n"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks\n"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep=png_handle_as_unknown(png_ptr, up->name); + if (keep != HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* write end of PNG file */ + png_write_IEND(png_ptr); +#if 0 +/* This flush, added in libpng-1.0.8, causes some applications to crash + because they do not set png_ptr->output_flush_fn */ + png_flush(png_ptr); +#endif +} + +#if defined(PNG_WRITE_tIME_SUPPORTED) +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm\n"); + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t\n"); + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + int i; + png_debug(1, "in png_create_write_struct\n"); +#ifdef PNG_USER_MEM_SUPPORTED + if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr)) == NULL) +#else + if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL) +#endif /* PNG_USER_MEM_SUPPORTED */ + { + return ((png_structp)NULL); + } + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_ptr->jmpbuf)) +#endif + { + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf=NULL; + png_destroy_struct(png_ptr); + return ((png_structp)NULL); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); +#endif +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + i=0; + do + { + if(user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Incompatible libpng version in application and library"); + } + + /* Libpng 1.0.6 was not binary compatible, due to insertion of the + info_ptr->free_me member. Libpng-1.0.1 and earlier were not + compatible due to insertion of the user transform function. Note + to maintainer: this test can be removed from version 1.2.0 and + beyond because the previous test would have already rejected it. */ + + if (user_png_ver[0] == '1' && user_png_ver[2] == '0' && + (user_png_ver[4] < '2' || user_png_ver[4] == '6') && + user_png_ver[5] == '\0') + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[80]; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "Application must be recompiled; versions <= 1.0.6 were incompatible"); + } + } + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + + png_set_write_fn(png_ptr, NULL, NULL, NULL); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, NULL, NULL); +#endif + + return ((png_structp)png_ptr); +} + +/* Initialize png_ptr structure, and allocate any memory needed */ +#undef png_write_init +void PNGAPI +vtk_png_write_init(png_structp png_ptr) +{ + /* We only come here via pre-1.0.7-compiled applications */ + png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); +} + +void PNGAPI +png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size, png_size_t png_info_size) +{ + /* We only come here via pre-1.0.12-compiled applications */ +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + if(sizeof(png_struct) > png_struct_size || sizeof(png_info) > png_info_size) + { + char msg[80]; + png_ptr->warning_fn=(png_error_ptr)NULL; + if (user_png_ver) + { + sprintf(msg, "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + sprintf(msg, "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); + } +#endif + if(sizeof(png_struct) > png_struct_size) + { + png_ptr->error_fn=(png_error_ptr)NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The png struct allocated by the application for writing is too small."); + } + if(sizeof(png_info) > png_info_size) + { + png_ptr->error_fn=(png_error_ptr)NULL; +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags=0; +#endif + png_error(png_ptr, + "The info struct allocated by the application for writing is too small."); + } + png_write_init_3(&png_ptr, user_png_ver, png_struct_size); +} + + +void PNGAPI +png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, + png_size_t png_struct_size) +{ + png_structp png_ptr=*ptr_ptr; +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* to save current jump buffer */ +#endif + int i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + { +#ifdef PNG_LEGACY_SUPPORTED + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; +#else + png_ptr->warning_fn=(png_error_ptr)NULL; + png_warning(png_ptr, + "Application uses deprecated png_write_init() and should be recompiled."); + break; +#endif + } + } while (png_libpng_ver[i++]); + + png_debug(1, "in png_write_init_3\n"); + +#ifdef PNG_SETJMP_SUPPORTED + /* save jump buffer and error functions */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); +#endif + + if (sizeof(png_struct) > png_struct_size) + { + png_destroy_struct(png_ptr); + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); + *ptr_ptr = png_ptr; + } + + /* reset all variables to 0 */ + png_memset(png_ptr, 0, sizeof (png_struct)); + +#ifdef PNG_SETJMP_SUPPORTED + /* restore jump buffer */ + png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); +#endif + + png_set_write_fn(png_ptr, NULL, NULL, NULL); + + /* initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, NULL, NULL); +#endif +} + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows\n"); + /* loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + png_debug(1, "in png_write_image\n"); +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* intialize interlace handling. If image is not interlaced, + this will set pass to 1 */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_bytep row) +{ + png_debug2(1, "in png_write_row (row %ld, pass %d)\n", + png_ptr->row_number, png_ptr->pass); + /* initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); +#endif +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); +#endif + + png_write_start_row(png_ptr); + } + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* if interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + /* set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = ((png_ptr->row_info.width * + (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3); + + png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, + png_ptr->row_info.rowbytes); + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* this should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#if defined(PNG_MNG_FEATURES_SUPPORTED) + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush\n"); + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush\n"); + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } + } while(wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct\n"); + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + } + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + png_ptr->num_chunk_list=0; + } +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = (png_infop)NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = (png_structp)NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy\n"); + /* free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_free(png_ptr, png_ptr->time_buffer); +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_free(png_ptr, png_ptr->prev_filters); + png_free(png_ptr, png_ptr->filter_weights); + png_free(png_ptr, png_ptr->inv_filter_weights); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* reset structure */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, sizeof (png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter\n"); +#if defined(PNG_MNG_FEATURES_SUPPORTED) + if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); + case PNG_FILTER_VALUE_NONE: png_ptr->do_filter=PNG_FILTER_NONE; break; + case PNG_FILTER_VALUE_SUB: png_ptr->do_filter=PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: png_ptr->do_filter=PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: png_ptr->do_filter=PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break; + default: png_ptr->do_filter = (png_byte)filters; break; + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_UP; + } + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_AVG; + } + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_doublep filter_weights, + png_doublep filter_costs) +{ + int i; + + png_debug(1, "in png_set_filter_heuristics\n"); + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return; + } + + if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) + { + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + } + + if (num_weights < 0 || filter_weights == NULL || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + num_weights = 0; + } + + png_ptr->num_prev_filters = (png_byte)num_weights; + png_ptr->heuristic_method = (png_byte)heuristic_method; + + if (num_weights > 0) + { + if (png_ptr->prev_filters == NULL) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + } + + if (png_ptr->filter_weights == NULL) + { + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + } + + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] < 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); + } + } + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + if (filter_costs == NULL || filter_costs[i] < 0.0) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + else if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); + } + } +} +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level\n"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level\n"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy\n"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); +#ifndef WBITS_8_OK + /* avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits=9; + } +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method\n"); + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + png_ptr->write_row_fn = write_row_fn; +} + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn\n"); + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + /* invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#if defined(PNG_WRITE_INVERT_SUPPORTED) + /* invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) + /* pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + /* swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) + /* flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) + /* swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + /* swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + if(transforms == 0 || params == NULL) + /* quiet compiler warnings */ return; +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/vtkpng/pngwtran.c b/Utilities/vtkpng/pngwtran.c new file mode 100644 index 0000000..3cc6067 --- /dev/null +++ b/Utilities/vtkpng/pngwtran.c @@ -0,0 +1,563 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations\n"); + + if (png_ptr == NULL) + return; + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if(png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* user write transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#if defined(PNG_WRITE_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#if defined(PNG_WRITE_PACK_SUPPORTED) +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack\n"); + if (row_info->bit_depth == 8 && +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + sp++; + if (mask > 1) + mask >>= 1; + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + if (mask != 0x80) + *dp = (png_byte)v; + break; + } + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 2; + sp++; + } + if (shift != 6) + *dp = (png_byte)v; + break; + } + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 4; + + sp++; + } + if (shift != 4) + *dp = (png_byte)v; + break; + } + } + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = + ((row_info->width * row_info->pixel_depth + 7) >> 3); + } +} +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && +#else + if ( +#endif + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* with low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_uint_32 i; + png_byte mask; + png_uint_32 row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from ARGB to RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AARRGGBB to RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from AG to GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AAGG to GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + } +} +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha\n"); +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL) +#endif + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + } +} +#endif + +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp+1))&0xff); + *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0=*(rp )<<8 | *(rp+1); + png_uint_32 s1=*(rp+2)<<8 | *(rp+3); + png_uint_32 s2=*(rp+4)<<8 | *(rp+5); + png_uint_32 red=(s0-s1)&0xffff; + png_uint_32 blue=(s2-s1)&0xffff; + *(rp ) = (png_byte)((red>>8)&0xff); + *(rp+1) = (png_byte)(red&0xff); + *(rp+4) = (png_byte)((blue>>8)&0xff); + *(rp+5) = (png_byte)(blue&0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/vtkpng/pngwutil.c b/Utilities/vtkpng/pngwutil.c new file mode 100644 index 0000000..a1db9c2 --- /dev/null +++ b/Utilities/vtkpng/pngwutil.c @@ -0,0 +1,2646 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * libpng 1.0.12 - June 8, 2001 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2001 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +#define PNG_INTERNAL +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED + +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void /* PRIVATE */ +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. + */ +void /* PRIVATE */ +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void /* PRIVATE */ +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_bytep chunk_name, + png_bytep data, png_size_t length) +{ + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[4]; + png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length); + + /* write the length */ + png_save_uint_32(buf, length); + png_write_data(png_ptr, buf, (png_size_t)4); + + /* write the chunk name */ + png_write_data(png_ptr, chunk_name, (png_size_t)4); + /* reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + /* write the data, and run the CRC over it */ + if (data != NULL && length > 0) + { + png_calculate_crc(png_ptr, data, length); + png_write_data(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + /* write the crc */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void /* PRIVATE */ +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + /* write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)8 - png_ptr->sig_bytes); + if(png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* + * This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + char *input; /* the uncompressed input data */ + int input_len; /* its length */ + int num_output_ptr; /* number of output pointers used */ + int max_output_ptr; /* size of output_ptr */ + png_charpp output_ptr; /* array of pointers to output */ +} compression_state; + +/* compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + + /* we may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = text; + comp->input_len = text_len; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[50]; + sprintf(msg, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown compression type"); +#endif + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* set up the compression buffers */ + png_ptr->zstream.avail_in = (uInt)text_len; + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; + + /* this is the same compression loop as in png_write_row() */ + do + { + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + /* error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + /* check to see if we need more room */ + if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in) + { + /* make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max + * sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charp))); + } + + /* save the data */ + comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* finish the compression */ + do + { + /* tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charp))); + } + + /* save off the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* we got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->input, comp->input_len); + return; + } + + /* write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i], + png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + comp->output_ptr[i]=NULL; + } + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + comp->output_ptr=NULL; + /* write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + /* reset zlib for another zTXt/iTXt or the image data */ + deflateReset(&png_ptr->zstream); + +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IHDR; +#endif + png_byte buf[13]; /* buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR\n"); + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + case 16: png_ptr->channels = 1; break; + default: png_error(png_ptr,"Invalid bit depth for grayscale image"); + } + break; + case PNG_COLOR_TYPE_RGB: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; + break; + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* save off the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = ((width * (png_size_t)png_ptr->pixel_depth + 7) >> 3); + /* set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* write the chunk */ + png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); + + /* initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_PLTE; +#endif + png_uint_32 i; + png_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE\n"); + if (( +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d\n", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, num_pal * 3); +#ifndef PNG_NO_POINTER_INDEXING + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#else + /* This is a little slower but some buggy compilers need to do this instead */ + pal_ptr=palette; + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IDAT; +#endif + png_debug(1, "in png_write_IDAT\n"); + png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_IEND; +#endif + png_debug(1, "in png_write_IEND\n"); + png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +/* write a gAMA chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA(png_structp png_ptr, double file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_uint_32 igamma; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA\n"); + /* file_gamma is saved in 1/100,000ths */ + igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); + png_save_uint_32(buf, igamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA\n"); + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, file_gamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +/* write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sRGB; +#endif + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB\n"); + if(srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); +} +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +/* write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, + png_charp profile, int profile_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iCCP; +#endif + png_size_t name_len; + png_charp new_name; + compression_state comp; + + png_debug(1, "in png_write_iCCP\n"); + if (name == NULL || (name_len = png_check_keyword(png_ptr, name, + &new_name)) == 0) + { + png_warning(png_ptr, "Empty keyword in iCCP chunk"); + return; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len, + PNG_COMPRESSION_TYPE_BASE, &comp); + + /* make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, + (png_uint_32)name_len+profile_len+2); + new_name[name_len+1]=0x00; + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +/* write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sPLT; +#endif + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + int entry_size = (spalette->depth == 8 ? 6 : 10); + int palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifdef PNG_NO_POINTER_INDEXING + int i; +#endif + + png_debug(1, "in png_write_sPLT\n"); + if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr, + spalette->name, &new_name))==0) + { + png_warning(png_ptr, "Empty keyword in sPLT chunk"); + return; + } + + /* make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1); + png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1); + + /* loop through each palette entry, writing appropriately */ +#ifndef PNG_NO_POINTER_INDEXING + for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#else + ep=spalette->entries; + for (i=0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +/* write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sBIT; +#endif + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT\n"); + /* make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); +} +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +/* write the cHRM chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM(png_structp png_ptr, double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + png_uint_32 itemp; + + png_debug(1, "in png_write_cHRM\n"); + /* each value is saved in 1/100,000ths */ + if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 || + white_x + white_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM white point specified"); +#if !defined(PNG_NO_CONSOLE_IO) + fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y); +#endif + return; + } + itemp = (png_uint_32)(white_x * 100000.0 + 0.5); + png_save_uint_32(buf, itemp); + itemp = (png_uint_32)(white_y * 100000.0 + 0.5); + png_save_uint_32(buf + 4, itemp); + + if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 || + red_x + red_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM red point specified"); + return; + } + itemp = (png_uint_32)(red_x * 100000.0 + 0.5); + png_save_uint_32(buf + 8, itemp); + itemp = (png_uint_32)(red_y * 100000.0 + 0.5); + png_save_uint_32(buf + 12, itemp); + + if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 || + green_x + green_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM green point specified"); + return; + } + itemp = (png_uint_32)(green_x * 100000.0 + 0.5); + png_save_uint_32(buf + 16, itemp); + itemp = (png_uint_32)(green_y * 100000.0 + 0.5); + png_save_uint_32(buf + 20, itemp); + + if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 || + blue_x + blue_y > 1.0) + { + png_warning(png_ptr, "Invalid cHRM blue point specified"); + return; + } + itemp = (png_uint_32)(blue_x * 100000.0 + 0.5); + png_save_uint_32(buf + 24, itemp); + itemp = (png_uint_32)(blue_y * 100000.0 + 0.5); + png_save_uint_32(buf + 28, itemp); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM\n"); + /* each value is saved in 1/100,000ths */ + if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM white point specified"); +#if !defined(PNG_NO_CONSOLE_IO) + fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y); +#endif + return; + } + png_save_uint_32(buf, white_x); + png_save_uint_32(buf + 4, white_y); + + if (red_x > 80000L || red_y > 80000L || red_x + red_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM fixed red point specified"); + return; + } + png_save_uint_32(buf + 8, red_x); + png_save_uint_32(buf + 12, red_y); + + if (green_x > 80000L || green_y > 80000L || green_x + green_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM green point specified"); + return; + } + png_save_uint_32(buf + 16, green_x); + png_save_uint_32(buf + 20, green_y); + + if (blue_x > 80000L || blue_y > 80000L || blue_x + blue_y > 100000L) + { + png_warning(png_ptr, "Invalid fixed cHRM blue point specified"); + return; + } + png_save_uint_32(buf + 24, blue_x); + png_save_uint_32(buf + 28, blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); +} +#endif +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +/* write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, + int num_trans, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tRNS; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS\n"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr,"Invalid number of transparent colors specified"); + return; + } + /* write the chunk out as it is */ + png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, (png_size_t)num_trans); + } + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* one 16 bit value */ + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); + } + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); + } + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +/* write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_bKGD; +#endif + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD\n"); + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index > png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + buf[0] = back->index; + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); + } + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); + } + else + { + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +/* write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_hIST; +#endif + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST\n"); + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist, + png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, (png_bytep)png_hIST, (png_uint_32)(num_hist * 2)); + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword\n"); + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'\n", key); + + *new_key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + 2)); + + /* Replace non-printing characters with a blank and print a warning */ + for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) + { + if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1)) + { +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) + char msg[40]; + + sprintf(msg, "invalid keyword character 0x%02X", *kp); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "invalid character in keyword"); +#endif + *dp = ' '; + } + else + { + *dp = *kp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + else if (*kp == ' ') + { + key_len--; + kwarn=1; + } + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if(kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + *new_key=NULL; + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + new_key[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +/* write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tEXt; +#endif + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt\n"); + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in tEXt chunk"); + return; + } + + if (text == NULL || *text == '\0') + text_len = 0; + else + text_len = png_strlen(text); + + /* make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, (png_uint_32)key_len+text_len+1); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + if (text_len) + png_write_chunk_data(png_ptr, (png_bytep)text, text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +/* write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len, int compression) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_zTXt; +#endif + png_size_t key_len; + char buf[1]; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt\n"); + + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in zTXt chunk"); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + png_free(png_ptr, new_key); + + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* write start of chunk */ + png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32) + (key_len+text_len+2)); + /* write key */ + png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1); + buf[0] = (png_byte)compression; + /* write compression */ + png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +/* write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_charp key, + png_charp lang, png_charp lang_key, png_charp text) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iTXt; +#endif + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang, new_key; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt\n"); + + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in iTXt chunk"); + return; + } + if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, + &new_lang))==0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + return; + } + lang_key_len = png_strlen(lang_key); + text_len = png_strlen(text); + + if (text == NULL || *text == '\0') + text_len = 0; + + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression-2, + &comp); + + /* make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts */ + + png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, + (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + + /* set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || \ + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + /* set the compression method */ + cbuf[1] = 0; + png_write_chunk_data(png_ptr, cbuf, 2); + + png_write_chunk_data(png_ptr, (png_bytep)new_lang, lang_len + 1); + png_write_chunk_data(png_ptr, (png_bytep)lang_key, lang_key_len+1); + png_write_chunk_data(png_ptr, '\0', 1); + + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); +} +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +/* write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_uint_32 x_offset, + png_uint_32 y_offset, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_oFFs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs\n"); + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_uint_32(buf, x_offset); + png_save_uint_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); +} +#endif + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +/* write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pCAL; +#endif + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams); + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d\n", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams + *sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + null terminator for the last parameter. */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d\n", (int)total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +/* write the sCAL chunk */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +void /* PRIVATE */ +png_write_sCAL(png_structp png_ptr, int unit, double width,double height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_size_t total_len; + char wbuf[32], hbuf[32]; + + png_debug(1, "in png_write_sCAL\n"); + +#if defined(_WIN32_WCE) +/* sprintf() function is not supported on WindowsCE */ + { + wchar_t wc_buf[32]; + swprintf(wc_buf, TEXT("%12.12e"), width); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, wbuf, 32, NULL, NULL); + swprintf(wc_buf, TEXT("%12.12e"), height); + WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, hbuf, 32, NULL, NULL); + } +#else + sprintf(wbuf, "%12.12e", width); + sprintf(hbuf, "%12.12e", height); +#endif + total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf); + + png_debug1(3, "sCAL total length = %d\n", (int)total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)&unit, 1); + png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1); + png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf)); + + png_write_chunk_end(png_ptr); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, + png_charp height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_size_t total_len; + char wbuf[32], hbuf[32]; + + png_debug(1, "in png_write_sCAL_s\n"); + + png_strcpy(wbuf,(const char *)width); + png_strcpy(hbuf,(const char *)height); + total_len = 1 + png_strlen(wbuf)+1 + png_strlen(hbuf); + + png_debug1(3, "sCAL total length = %d\n", total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)&unit, 1); + png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1); + png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf)); + + png_write_chunk_end(png_ptr); +} +#endif +#endif +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +/* write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_pHYs; +#endif + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs\n"); + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); +} +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_timep mod_time) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_tIME; +#endif + png_byte buf[7]; + + png_debug(1, "in png_write_tIME\n"); + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); +} +#endif + +/* initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row\n"); + buf_size = (png_size_t)(((png_ptr->width * png_ptr->usr_channels * + png_ptr->usr_bit_depth + 7) >> 3) + 1); + + /* set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + + /* set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); + png_memset(png_ptr->prev_row, 0, buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep )png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* if interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int ret; + + png_debug(1, "in png_write_finish_row\n"); + /* next row */ + png_ptr->row_number++; + + /* see if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* if interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + else + { + /* loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) + break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t) (((png_uint_32)png_ptr->usr_channels * + (png_uint_32)png_ptr->usr_bit_depth * + png_ptr->width + 7) >> 3) + 1); + return; + } + } +#endif + + /* if we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + /* check for an error */ + if (ret == Z_OK) + { + /* check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); +} + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +#endif + + png_debug(1, "in png_do_write_interlace\n"); + /* we don't have to do anything on the last pass (6) */ +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if (row != NULL && row_info != NULL && pass < 6) +#else + if (pass < 6) +#endif + { + /* each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + break; + } + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + break; + } + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + break; + } + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* start at the beginning */ + dp = row; + /* find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + /* loop through the row, only looking at the pixels that + matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + /* move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + /* next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + row_info->rowbytes = ((row_info->width * + row_info->pixel_depth + 7) >> 3); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (~((png_uint_32)0) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep prev_row, best_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_uint_32 row_bytes = row_info->rowbytes; +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter\n"); + /* find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) / 8; + + prev_row = png_ptr->prev_row; + best_row = row_buf = png_ptr->row_buf; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && + filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_uint_32 i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* it's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_info->rowbytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } + + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_debug(1, "in png_write_filtered_row\n"); + png_debug1(2, "filter = %d\n", filtered_row[0]); + /* set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; + /* repeat until we have compressed all the data */ + do + { + int ret; /* return of zlib */ + + /* compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + /* check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + /* see if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + /* repeat until all data has been compressed */ + } while (png_ptr->zstream.avail_in); + + /* swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/Utilities/vtkpng/vtk_png_mangle.h b/Utilities/vtkpng/vtk_png_mangle.h new file mode 100644 index 0000000..eb9afe3 --- /dev/null +++ b/Utilities/vtkpng/vtk_png_mangle.h @@ -0,0 +1,350 @@ +#ifndef vtk_png_mangle_h +#define vtk_png_mangle_h + +/* + +This header file mangles all symbols exported from the png library. +It is included in all files while building the png library. Due to +namespace pollution, no png headers should be included in .h files in +VTK. + +The following command was used to obtain the symbol list: + +nm libvtkpng.a |grep " [TR] " + +*/ + +#define png_access_version_number vtk_png_access_version_number +#define png_build_gamma_table vtk_png_build_gamma_table +#define png_build_grayscale_palette vtk_png_build_grayscale_palette +#define png_calculate_crc vtk_png_calculate_crc +#define png_check_chunk_name vtk_png_check_chunk_name +#define png_check_keyword vtk_png_check_keyword +#define png_check_sig vtk_png_check_sig +#define png_chunk_error vtk_png_chunk_error +#define png_chunk_warning vtk_png_chunk_warning +#define png_combine_row vtk_png_combine_row +#define png_convert_from_struct_tm vtk_png_convert_from_struct_tm +#define png_convert_from_time_t vtk_png_convert_from_time_t +#define png_convert_to_rfc1123 vtk_png_convert_to_rfc1123 +#define png_crc_error vtk_png_crc_error +#define png_crc_finish vtk_png_crc_finish +#define png_crc_read vtk_png_crc_read +#define png_create_info_struct vtk_png_create_info_struct +#define png_create_read_struct vtk_png_create_read_struct +#define png_create_struct vtk_png_create_struct +#define png_create_write_struct vtk_png_create_write_struct +#define png_data_freer vtk_png_data_freer +#define png_decompress_chunk vtk_png_decompress_chunk +#define png_destroy_info_struct vtk_png_destroy_info_struct +#define png_destroy_read_struct vtk_png_destroy_read_struct +#define png_destroy_struct vtk_png_destroy_struct +#define png_destroy_write_struct vtk_png_destroy_write_struct +#define png_do_background vtk_png_do_background +#define png_do_bgr vtk_png_do_bgr +#define png_do_chop vtk_png_do_chop +#define png_do_dither vtk_png_do_dither +#define png_do_expand vtk_png_do_expand +#define png_do_expand_palette vtk_png_do_expand_palette +#define png_do_gamma vtk_png_do_gamma +#define png_do_gray_to_rgb vtk_png_do_gray_to_rgb +#define png_do_invert vtk_png_do_invert +#define png_do_pack vtk_png_do_pack +#define png_do_packswap vtk_png_do_packswap +#define png_do_read_filler vtk_png_do_read_filler +#define png_do_read_interlace vtk_png_do_read_interlace +#define png_do_read_invert_alpha vtk_png_do_read_invert_alpha +#define png_do_read_swap_alpha vtk_png_do_read_swap_alpha +#define png_do_read_transformations vtk_png_do_read_transformations +#define png_do_rgb_to_gray vtk_png_do_rgb_to_gray +#define png_do_shift vtk_png_do_shift +#define png_do_strip_filler vtk_png_do_strip_filler +#define png_do_swap vtk_png_do_swap +#define png_do_unpack vtk_png_do_unpack +#define png_do_unshift vtk_png_do_unshift +#define png_do_write_interlace vtk_png_do_write_interlace +#define png_do_write_invert_alpha vtk_png_do_write_invert_alpha +#define png_do_write_swap_alpha vtk_png_do_write_swap_alpha +#define png_do_write_transformations vtk_png_do_write_transformations +#define png_error vtk_png_error +#define png_flush vtk_png_flush +#define png_free vtk_png_free +#define png_free_data vtk_png_free_data +#define png_get_IHDR vtk_png_get_IHDR +#define png_get_PLTE vtk_png_get_PLTE +#define png_get_bKGD vtk_png_get_bKGD +#define png_get_bit_depth vtk_png_get_bit_depth +#define png_get_cHRM vtk_png_get_cHRM +#define png_get_cHRM_fixed vtk_png_get_cHRM_fixed +#define png_get_channels vtk_png_get_channels +#define png_get_color_type vtk_png_get_color_type +#define png_get_compression_buffer_size vtk_png_get_compression_buffer_size +#define png_get_compression_type vtk_png_get_compression_type +#define png_get_copyright vtk_png_get_copyright +#define png_get_error_ptr vtk_png_get_error_ptr +#define png_get_filter_type vtk_png_get_filter_type +#define png_get_gAMA vtk_png_get_gAMA +#define png_get_gAMA_fixed vtk_png_get_gAMA_fixed +#define png_get_hIST vtk_png_get_hIST +#define png_get_header_ver vtk_png_get_header_ver +#define png_get_header_version vtk_png_get_header_version +#define png_get_iCCP vtk_png_get_iCCP +#define png_get_image_height vtk_png_get_image_height +#define png_get_image_width vtk_png_get_image_width +#define png_get_int_32 vtk_png_get_int_32 +#define png_get_interlace_type vtk_png_get_interlace_type +#define png_get_io_ptr vtk_png_get_io_ptr +#define png_get_libpng_ver vtk_png_get_libpng_ver +#define png_get_oFFs vtk_png_get_oFFs +#define png_get_pCAL vtk_png_get_pCAL +#define png_get_pHYs vtk_png_get_pHYs +#define png_get_pixel_aspect_ratio vtk_png_get_pixel_aspect_ratio +#define png_get_pixels_per_meter vtk_png_get_pixels_per_meter +#define png_get_progressive_ptr vtk_png_get_progressive_ptr +#define png_get_rgb_to_gray_status vtk_png_get_rgb_to_gray_status +#define png_get_rowbytes vtk_png_get_rowbytes +#define png_get_rows vtk_png_get_rows +#define png_get_sBIT vtk_png_get_sBIT +#define png_get_sCAL vtk_png_get_sCAL +#define png_get_sPLT vtk_png_get_sPLT +#define png_get_sRGB vtk_png_get_sRGB +#define png_get_signature vtk_png_get_signature +#define png_get_tIME vtk_png_get_tIME +#define png_get_tRNS vtk_png_get_tRNS +#define png_get_text vtk_png_get_text +#define png_get_uint_16 vtk_png_get_uint_16 +#define png_get_uint_32 vtk_png_get_uint_32 +#define png_get_unknown_chunks vtk_png_get_unknown_chunks +#define png_get_user_chunk_ptr vtk_png_get_user_chunk_ptr +#define png_get_user_transform_ptr vtk_png_get_user_transform_ptr +#define png_get_valid vtk_png_get_valid +#define png_get_x_offset_microns vtk_png_get_x_offset_microns +#define png_get_x_offset_pixels vtk_png_get_x_offset_pixels +#define png_get_x_pixels_per_meter vtk_png_get_x_pixels_per_meter +#define png_get_y_offset_microns vtk_png_get_y_offset_microns +#define png_get_y_offset_pixels vtk_png_get_y_offset_pixels +#define png_get_y_pixels_per_meter vtk_png_get_y_pixels_per_meter +#define png_handle_IEND vtk_png_handle_IEND +#define png_handle_IHDR vtk_png_handle_IHDR +#define png_handle_PLTE vtk_png_handle_PLTE +#define png_handle_as_unknown vtk_png_handle_as_unknown +#define png_handle_bKGD vtk_png_handle_bKGD +#define png_handle_cHRM vtk_png_handle_cHRM +#define png_handle_gAMA vtk_png_handle_gAMA +#define png_handle_hIST vtk_png_handle_hIST +#define png_handle_iCCP vtk_png_handle_iCCP +#define png_handle_oFFs vtk_png_handle_oFFs +#define png_handle_pCAL vtk_png_handle_pCAL +#define png_handle_pHYs vtk_png_handle_pHYs +#define png_handle_sBIT vtk_png_handle_sBIT +#define png_handle_sCAL vtk_png_handle_sCAL +#define png_handle_sPLT vtk_png_handle_sPLT +#define png_handle_sRGB vtk_png_handle_sRGB +#define png_handle_tEXt vtk_png_handle_tEXt +#define png_handle_tIME vtk_png_handle_tIME +#define png_handle_tRNS vtk_png_handle_tRNS +#define png_handle_unknown vtk_png_handle_unknown +#define png_handle_zTXt vtk_png_handle_zTXt +#define png_info_destroy vtk_png_info_destroy +#define png_info_init vtk_png_info_init +#define png_info_init_3 vtk_png_info_init_3 +#define png_init_io vtk_png_init_io +#define png_init_read_transformations vtk_png_init_read_transformations +#define png_libpng_ver vtk_png_libpng_ver +#define png_malloc vtk_png_malloc +#define png_memcpy_check vtk_png_memcpy_check +#define png_memset_check vtk_png_memset_check +#define png_mmx_support vtk_png_mmx_support +#define png_pass_dsp_mask vtk_png_pass_dsp_mask +#define png_pass_mask vtk_png_pass_mask +#define png_pass_yinc vtk_png_pass_yinc +#define png_pass_ystart vtk_png_pass_ystart +#define png_pass_inc vtk_png_pass_inc +#define png_pass_start vtk_png_pass_start +#define png_permit_empty_plte vtk_png_permit_empty_plte +#define png_process_IDAT_data vtk_png_process_IDAT_data +#define png_process_data vtk_png_process_data +#define png_process_some_data vtk_png_process_some_data +#define png_progressive_combine_row vtk_png_progressive_combine_row +#define png_push_crc_finish vtk_png_push_crc_finish +#define png_push_crc_skip vtk_png_push_crc_skip +#define png_push_fill_buffer vtk_png_push_fill_buffer +#define png_push_handle_tEXt vtk_png_push_handle_tEXt +#define png_push_handle_unknown vtk_png_push_handle_unknown +#define png_push_handle_zTXt vtk_png_push_handle_zTXt +#define png_push_have_end vtk_png_push_have_end +#define png_push_have_info vtk_png_push_have_info +#define png_push_have_row vtk_png_push_have_row +#define png_push_process_row vtk_png_push_process_row +#define png_push_read_IDAT vtk_png_push_read_IDAT +#define png_push_read_chunk vtk_png_push_read_chunk +#define png_push_read_sig vtk_png_push_read_sig +#define png_push_read_tEXt vtk_png_push_read_tEXt +#define png_push_read_zTXt vtk_png_push_read_zTXt +#define png_push_restore_buffer vtk_png_push_restore_buffer +#define png_push_save_buffer vtk_png_push_save_buffer +#define png_read_data vtk_png_read_data +#define png_read_destroy vtk_png_read_destroy +#define png_read_end vtk_png_read_end +#define png_read_filter_row vtk_png_read_filter_row +#define png_read_finish_row vtk_png_read_finish_row +#define png_read_image vtk_png_read_image +#define png_read_info vtk_png_read_info +#define png_read_init vtk_png_read_init +#define png_read_init_2 vtk_png_read_init_2 +#define png_read_init_3 vtk_png_read_init_3 +#define png_read_png vtk_png_read_png +#define png_read_push_finish_row vtk_png_read_push_finish_row +#define png_read_row vtk_png_read_row +#define png_read_rows vtk_png_read_rows +#define png_read_start_row vtk_png_read_start_row +#define png_read_transform_info vtk_png_read_transform_info +#define png_read_update_info vtk_png_read_update_info +#define png_reset_crc vtk_png_reset_crc +#define png_reset_zstream vtk_png_reset_zstream +#define png_save_int_32 vtk_png_save_int_32 +#define png_save_uint_16 vtk_png_save_uint_16 +#define png_save_uint_32 vtk_png_save_uint_32 +#define png_set_IHDR vtk_png_set_IHDR +#define png_set_PLTE vtk_png_set_PLTE +#define png_set_bKGD vtk_png_set_bKGD +#define png_set_background vtk_png_set_background +#define png_set_bgr vtk_png_set_bgr +#define png_set_cHRM vtk_png_set_cHRM +#define png_set_cHRM_fixed vtk_png_set_cHRM_fixed +#define png_set_compression_buffer_size vtk_png_set_compression_buffer_size +#define png_set_compression_level vtk_png_set_compression_level +#define png_set_compression_mem_level vtk_png_set_compression_mem_level +#define png_set_compression_method vtk_png_set_compression_method +#define png_set_compression_strategy vtk_png_set_compression_strategy +#define png_set_compression_window_bits vtk_png_set_compression_window_bits +#define png_set_crc_action vtk_png_set_crc_action +#define png_set_dither vtk_png_set_dither +#define png_set_error_fn vtk_png_set_error_fn +#define png_set_expand vtk_png_set_expand +#define png_set_filler vtk_png_set_filler +#define png_set_filter vtk_png_set_filter +#define png_set_filter_heuristics vtk_png_set_filter_heuristics +#define png_set_flush vtk_png_set_flush +#define png_set_gAMA vtk_png_set_gAMA +#define png_set_gAMA_fixed vtk_png_set_gAMA_fixed +#define png_set_gamma vtk_png_set_gamma +#define png_set_gray_1_2_4_to_8 vtk_png_set_gray_1_2_4_to_8 +#define png_set_gray_to_rgb vtk_png_set_gray_to_rgb +#define png_set_hIST vtk_png_set_hIST +#define png_set_iCCP vtk_png_set_iCCP +#define png_set_interlace_handling vtk_png_set_interlace_handling +#define png_set_invalid vtk_png_set_invalid +#define png_set_invert_alpha vtk_png_set_invert_alpha +#define png_set_invert_mono vtk_png_set_invert_mono +#define png_set_keep_unknown_chunks vtk_png_set_keep_unknown_chunks +#define png_set_oFFs vtk_png_set_oFFs +#define png_set_pCAL vtk_png_set_pCAL +#define png_set_pHYs vtk_png_set_pHYs +#define png_set_packing vtk_png_set_packing +#define png_set_packswap vtk_png_set_packswap +#define png_set_palette_to_rgb vtk_png_set_palette_to_rgb +#define png_set_progressive_read_fn vtk_png_set_progressive_read_fn +#define png_set_read_fn vtk_png_set_read_fn +#define png_set_read_status_fn vtk_png_set_read_status_fn +#define png_set_read_user_chunk_fn vtk_png_set_read_user_chunk_fn +#define png_set_read_user_transform_fn vtk_png_set_read_user_transform_fn +#define png_set_rgb_to_gray vtk_png_set_rgb_to_gray +#define png_set_rgb_to_gray_fixed vtk_png_set_rgb_to_gray_fixed +#define png_set_rows vtk_png_set_rows +#define png_set_sBIT vtk_png_set_sBIT +#define png_set_sCAL vtk_png_set_sCAL +#define png_set_sPLT vtk_png_set_sPLT +#define png_set_sRGB vtk_png_set_sRGB +#define png_set_sRGB_gAMA_and_cHRM vtk_png_set_sRGB_gAMA_and_cHRM +#define png_set_shift vtk_png_set_shift +#define png_set_sig_bytes vtk_png_set_sig_bytes +#define png_set_strip_16 vtk_png_set_strip_16 +#define png_set_strip_alpha vtk_png_set_strip_alpha +#define png_set_swap vtk_png_set_swap +#define png_set_swap_alpha vtk_png_set_swap_alpha +#define png_set_tIME vtk_png_set_tIME +#define png_set_tRNS vtk_png_set_tRNS +#define png_set_tRNS_to_alpha vtk_png_set_tRNS_to_alpha +#define png_set_text vtk_png_set_text +#define png_set_unknown_chunk_location vtk_png_set_unknown_chunk_location +#define png_set_unknown_chunks vtk_png_set_unknown_chunks +#define png_set_user_transform_info vtk_png_set_user_transform_info +#define png_set_write_fn vtk_png_set_write_fn +#define png_set_write_status_fn vtk_png_set_write_status_fn +#define png_set_write_user_transform_fn vtk_png_set_write_user_transform_fn +#define png_sig_cmp vtk_png_sig_cmp +#define png_start_read_image vtk_png_start_read_image +#define png_warning vtk_png_warning +#define png_write_IDAT vtk_png_write_IDAT +#define png_write_IEND vtk_png_write_IEND +#define png_write_IHDR vtk_png_write_IHDR +#define png_write_PLTE vtk_png_write_PLTE +#define png_write_bKGD vtk_png_write_bKGD +#define png_write_cHRM vtk_png_write_cHRM +#define png_write_cHRM_fixed vtk_png_write_cHRM_fixed +#define png_write_chunk vtk_png_write_chunk +#define png_write_chunk_data vtk_png_write_chunk_data +#define png_write_chunk_end vtk_png_write_chunk_end +#define png_write_chunk_start vtk_png_write_chunk_start +#define png_write_data vtk_png_write_data +#define png_write_destroy vtk_png_write_destroy +#define png_write_end vtk_png_write_end +#define png_write_filtered_row vtk_png_write_filtered_row +#define png_write_find_filter vtk_png_write_find_filter +#define png_write_finish_row vtk_png_write_finish_row +#define png_write_flush vtk_png_write_flush +#define png_write_gAMA vtk_png_write_gAMA +#define png_write_gAMA_fixed vtk_png_write_gAMA_fixed +#define png_write_hIST vtk_png_write_hIST +#define png_write_iCCP vtk_png_write_iCCP +#define png_write_image vtk_png_write_image +#define png_write_info vtk_png_write_info +#define png_write_info_before_PLTE vtk_png_write_info_before_PLTE +#define png_write_init vtk_png_write_init +#define png_write_init_2 vtk_png_write_init_2 +#define png_write_init_3 vtk_png_write_init_3 +#define png_write_oFFs vtk_png_write_oFFs +#define png_write_pCAL vtk_png_write_pCAL +#define png_write_pHYs vtk_png_write_pHYs +#define png_write_png vtk_png_write_png +#define png_write_row vtk_png_write_row +#define png_write_rows vtk_png_write_rows +#define png_write_sBIT vtk_png_write_sBIT +#define png_write_sCAL vtk_png_write_sCAL +#define png_write_sPLT vtk_png_write_sPLT +#define png_write_sRGB vtk_png_write_sRGB +#define png_write_sig vtk_png_write_sig +#define png_write_start_row vtk_png_write_start_row +#define png_write_tEXt vtk_png_write_tEXt +#define png_write_tIME vtk_png_write_tIME +#define png_write_tRNS vtk_png_write_tRNS +#define png_write_zTXt vtk_png_write_zTXt +#define png_zalloc vtk_png_zalloc +#define png_zfree vtk_png_zfree + +#define png_zTXt vtk_png_zTXt +#define png_tRNS vtk_png_tRNS +#define png_tIME vtk_png_tIME +#define png_tEXt vtk_png_tEXt +#define png_sRGB vtk_png_sRGB +#define png_sPLT vtk_png_sPLT +#define png_sBIT vtk_png_sBIT +#define png_pHYs vtk_png_pHYs +#define png_sCAL vtk_png_sCAL +#define png_pCAL vtk_png_pCAL +#define png_oFFs vtk_png_oFFs +#define png_iTXt vtk_png_iTXt +#define png_iCCP vtk_png_iCCP +#define png_hIST vtk_png_hIST +#define png_gAMA vtk_png_gAMA +#define png_cHRM vtk_png_cHRM +#define png_bKGD vtk_png_bKGD +#define png_PLTE vtk_png_PLTE +#define png_IEND vtk_png_IEND +#define png_IDAT vtk_png_IDAT +#define png_IHDR vtk_png_IHDR +#define png_sig vtk_png_sig +#define png_sig_bytes vtk_png_sig_bytes + +#endif diff --git a/Utilities/vtkstd.h.in b/Utilities/vtkstd.h.in new file mode 100644 index 0000000..cde111b --- /dev/null +++ b/Utilities/vtkstd.h.in @@ -0,0 +1,37 @@ +#ifndef __vtkstd_@VTK_STL_HEADER@ +#define __vtkstd_@VTK_STL_HEADER@ + +#include "vtkConfigure.h" + +/* Avoid warnings in MSVC standard headers. */ +#if defined(_MSC_VER) +# pragma warning (push, 1) +# pragma warning (disable: 4702) +# pragma warning (disable: 4786) +#endif + +/* The HP standard library defines the functor "times" instead of + "multiplies" as specified by C++98 20.3.2 for backward + compatibility with earlier specifications. Defining this macro + fixes this behavior. The name "times" also conflicts with the + function declared in sys/times.h on that platform, so we must do + this as a work-around anyway. */ +#if defined(__HP_aCC) && !defined(__HPACC_USING_MULTIPLIES_IN_FUNCTIONAL) +# define __HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +# define VTK_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +#endif + +/* Include the real header. */ +#include <@VTK_STL_HEADER@> + +/* Cleanup. */ +#if defined(VTK_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL) +# undef VTK_DEFINED___HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +# undef __HPACC_USING_MULTIPLIES_IN_FUNCTIONAL +#endif + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif diff --git a/Utilities/vtktiff/.NoDartCoverage b/Utilities/vtktiff/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/vtktiff/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/vtktiff/CMakeLists.txt b/Utilities/vtktiff/CMakeLists.txt new file mode 100644 index 0000000..42d9b2c --- /dev/null +++ b/Utilities/vtktiff/CMakeLists.txt @@ -0,0 +1,68 @@ +PROJECT(VTKTIFF) +INCLUDE_REGULAR_EXPRESSION("^(tif|fax|port|uv|vtk|tconf|t4|mk|z).*$") + +INCLUDE_DIRECTORIES(${VTKTIFF_SOURCE_DIR}) + +# library object files common to compression and decompression +SET(common_SRCS +tif_aux.c tif_close.c +tif_codec.c tif_compress.c tif_dir.c tif_dirinfo.c tif_dirread.c +tif_dirwrite.c tif_dumpmode.c tif_error.c tif_fax3.c tif_flush.c +tif_getimage.c tif_jpeg.c tif_luv.c tif_lzw.c tif_next.c +tif_ojpeg.c tif_open.c tif_packbits.c tif_pixarlog.c tif_predict.c +tif_print.c tif_read.c tif_strip.c tif_swab.c tif_thunder.c tif_tile.c +tif_version.c tif_warning.c +tif_write.c tif_zip.c) + +ADD_DEFINITIONS( -DJPEG_SUPPORT -DZIP_SUPPORT -D_HPUX_SOURCE) + +IF(WIN32) + IF(BUILD_SHARED_LIBS) + SET(TIFFDLL 1) + ELSE(BUILD_SHARED_LIBS) + SET(TIFFSTATIC 1) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(WIN32) + +IF(NOT UNIX) + ADD_DEFINITIONS( -DTIF_PLATFORM_CONSOLE ) + SET(common_SRCS ${common_SRCS} tif_win32.c fax3sm_winnt.c) + IF (NOT BORLAND) + IF(NOT MINGW) + SET(common_SRCS ${common_SRCS} vtktiff.def) + ENDIF(NOT MINGW) + ENDIF(NOT BORLAND) +ELSE (NOT UNIX) + SET(common_SRCS ${common_SRCS} tif_unix.c tif_fax3sm.c) + ADD_EXECUTABLE(mkg3states mkg3states.c) + IF(CYGWIN) + SET(EXE_EXTENSION .exe) + ENDIF(CYGWIN) + ADD_CUSTOM_COMMAND( + OUTPUT ${VTKTIFF_BINARY_DIR}/tif_fax3sm.c + COMMAND ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/mkg3states${EXE_EXTENSION} + ARGS -c const ${VTKTIFF_BINARY_DIR}/tif_fax3sm.c + DEPENDS mkg3states + ) +ENDIF (NOT UNIX) + +CONFIGURE_FILE(${VTKTIFF_SOURCE_DIR}/.NoDartCoverage + ${VTKTIFF_BINARY_DIR}/.NoDartCoverage) +CONFIGURE_FILE(${VTKTIFF_SOURCE_DIR}/tiffDllConfig.h.in + ${VTKTIFF_BINARY_DIR}/tiffDllConfig.h) + +ADD_LIBRARY(vtktiff ${common_SRCS}) +TARGET_LINK_LIBRARIES( vtktiff ${VTK_ZLIB_LIBRARIES} ${VTK_JPEG_LIBRARIES} ) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtktiff PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtktiff) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtktiff .h + tiffDllConfig tiffvers tiff tiffio tconf vtk_tiff_mangle) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/vtktiff/README b/Utilities/vtktiff/README new file mode 100644 index 0000000..ce55e90 --- /dev/null +++ b/Utilities/vtktiff/README @@ -0,0 +1,59 @@ +$Header: /cvsroot/VTK/VTK/Utilities/vtktiff/README,v 1.1 2004/04/28 15:49:22 king Exp $ + + +TIFF Software Distribution +-------------------------- +This file is just a placeholder; all the documentation is now in +HTML in the html directory. To view the documentation point your +favorite WWW viewer at html/index.html; e.g. + + netscape html/index.html + +If you don't have an HTML viewer then you can read the HTML source +or fetch a PostScript version of this documentation from the directory + + ftp://ftp.remotesensing.org/pub/libtiff/ + +If you can't hack either of these options then basically what you +want to do is: + + % ./configure + % make + % su + # make install + +More information, email contacts, and mailing list information can be +found online at http://www.libtiff.org/. + + +Use and Copyright +----------------- +Silicon Graphics has seen fit to allow us to give this work away. It +is free. There is no support or guarantee of any sort as to its +operations, correctness, or whatever. If you do anything useful with +all or parts of it you need to honor the copyright notices. I would +also be interested in knowing about it and, hopefully, be acknowledged. + +The legal way of saying that is: + +Copyright (c) 1988-1997 Sam Leffler +Copyright (c) 1991-1997 Silicon Graphics, Inc. + +Permission to use, copy, modify, distribute, and sell this software and +its documentation for any purpose is hereby granted without fee, provided +that (i) the above copyright notices and this permission notice appear in +all copies of the software and related documentation, and (ii) the names of +Sam Leffler and Silicon Graphics may not be used in any advertising or +publicity relating to the software without the specific, prior written +permission of Sam Leffler and Silicon Graphics. + +THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR +ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF +LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +OF THIS SOFTWARE. diff --git a/Utilities/vtktiff/README.VTK.txt b/Utilities/vtktiff/README.VTK.txt new file mode 100644 index 0000000..235b143 --- /dev/null +++ b/Utilities/vtktiff/README.VTK.txt @@ -0,0 +1,8 @@ +This directory contains a subset of libtiff from www.libtiff.org + +Modifications +------------- + +* It uses CMake + + diff --git a/Utilities/vtktiff/RELEASE-DATE b/Utilities/vtktiff/RELEASE-DATE new file mode 100644 index 0000000..7ac2567 --- /dev/null +++ b/Utilities/vtktiff/RELEASE-DATE @@ -0,0 +1 @@ +11/28/2001 diff --git a/Utilities/vtktiff/VERSION b/Utilities/vtktiff/VERSION new file mode 100644 index 0000000..3cf5751 --- /dev/null +++ b/Utilities/vtktiff/VERSION @@ -0,0 +1 @@ +3.5.7 diff --git a/Utilities/vtktiff/dist/newalpha b/Utilities/vtktiff/dist/newalpha new file mode 100644 index 0000000..7436842 --- /dev/null +++ b/Utilities/vtktiff/dist/newalpha @@ -0,0 +1,8 @@ +#! /bin/sh +# $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/dist/newalpha,v 1.1 2004/04/28 15:49:22 king Exp $ +if test -r tiff.alpha; then + ALPHA=`cat tiff.alpha`; rm -f tiff.alpha + echo "$ALPHA" | awk '{ printf "define ALPHA %1d\n", $3+1}' > tiff.alpha +else + echo "define ALPHA 001" >tiff.alpha +fi diff --git a/Utilities/vtktiff/dist/newversion b/Utilities/vtktiff/dist/newversion new file mode 100644 index 0000000..cad1fa0 --- /dev/null +++ b/Utilities/vtktiff/dist/newversion @@ -0,0 +1,31 @@ +#! /bin/sh +# $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/dist/newversion,v 1.1 2004/04/28 15:49:22 king Exp $ +# +# TIFF Software +# +# Copyright (c) 1994-1996 Sam Leffler +# Copyright (c) 1994-1996 Silicon Graphics, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software and +# its documentation for any purpose is hereby granted without fee, provided +# that (i) the above copyright notices and this permission notice appear in +# all copies of the software and related documentation, and (ii) the names of +# Sam Leffler and Silicon Graphics may not be used in any advertising or +# publicity relating to the software without the specific, prior written +# permission of Sam Leffler and Silicon Graphics. +# +# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, +# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +# +# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR +# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, +# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF +# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# +rm -f tiff.version +awk ' +{ print "define TIFF_VNUM \"" $1 " (" $2 ")\"" } +' ../VERSION > tiff.version diff --git a/Utilities/vtktiff/dist/tiff.alpha b/Utilities/vtktiff/dist/tiff.alpha new file mode 100644 index 0000000..a78fd0b --- /dev/null +++ b/Utilities/vtktiff/dist/tiff.alpha @@ -0,0 +1 @@ +define ALPHA diff --git a/Utilities/vtktiff/dist/tiff.spec b/Utilities/vtktiff/dist/tiff.spec new file mode 100644 index 0000000..07b990c --- /dev/null +++ b/Utilities/vtktiff/dist/tiff.spec @@ -0,0 +1,68 @@ +# $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/dist/tiff.spec,v 1.1 2004/04/28 15:49:22 king Exp $ +# +# TIFF Software +# +# Copyright (c) 1994-1997 Sam Leffler +# Copyright (c) 1994-1997 Silicon Graphics, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software and +# its documentation for any purpose is hereby granted without fee, provided +# that (i) the above copyright notices and this permission notice appear in +# all copies of the software and related documentation, and (ii) the names of +# Sam Leffler and Silicon Graphics may not be used in any advertising or +# publicity relating to the software without the specific, prior written +# permission of Sam Leffler and Silicon Graphics. +# +# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, +# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +# +# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR +# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, +# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF +# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# +define CUR_MAJ_VERS 1006 # Major Version number +define CUR_MIN_VERS 001 # Minor Version number +define CUR_VERS ${CUR_MAJ_VERS}${CUR_MIN_VERS}${ALPHA} +define TIFF_NAME "TIFF" + +include tiff.version +include tiff.alpha + +product tiff + id "${TIFF_NAME} Tools, Version ${TIFF_VNUM}" + inplace + + image sw + id "${TIFF_NAME} Software" + version "${CUR_VERS}" + subsys tools default + id "${TIFF_NAME} Tools & Library DSO" + exp "tiff.sw.tools" + endsubsys + subsys dev + id "${TIFF_NAME} Developement Software" + exp "tiff.sw.dev" + endsubsys + endimage + + image man + id "${TIFF_NAME} Documentation" + version "${CUR_VERS}" + subsys tools default + id "${TIFF_NAME} Tools Manual Pages" + exp "tiff.man.tools" + endsubsys + subsys dev + id "${TIFF_NAME} Library Manual Pages" + exp "tiff.man.dev" + endsubsys + subsys html + id "${TIFF_NAME} HTML Materials" + exp "tiff.man.html" + endsubsys + endimage +endproduct diff --git a/Utilities/vtktiff/dist/tiff.version b/Utilities/vtktiff/dist/tiff.version new file mode 100644 index 0000000..9c5a223 --- /dev/null +++ b/Utilities/vtktiff/dist/tiff.version @@ -0,0 +1 @@ +define TIFF_VNUM "3.5.7 ()" diff --git a/Utilities/vtktiff/fax3sm_winnt.c b/Utilities/vtktiff/fax3sm_winnt.c new file mode 100644 index 0000000..587fff1 --- /dev/null +++ b/Utilities/vtktiff/fax3sm_winnt.c @@ -0,0 +1,1047 @@ +/* WARNING, this file was automatically generated by the + mkg3states program */ +#include "tiff.h" +#include "tif_fax3.h" +#include "tiffconf.h" +const TIFFFaxTabEnt TIFFFaxMainTable[128] = { +12,7,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0, +2,3,0,3,1,0,4,3,1,3,1,0,5,6,2,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0, +1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,5,7,3,3,1,0,5,3,1,3,1,0, +2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0, +4,6,2,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0, +2,3,0,3,1,0,4,3,1,3,1,0,6,7,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0, +1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,5,6,2,3,1,0,5,3,1,3,1,0, +2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0, +4,7,3,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0,1,4,0,3,1,0,5,3,1,3,1,0, +2,3,0,3,1,0,4,3,1,3,1,0,4,6,2,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0, +1,4,0,3,1,0,5,3,1,3,1,0,2,3,0,3,1,0,4,3,1,3,1,0 +}; +const TIFFFaxTabEnt TIFFFaxWhiteTable[4096] = { +12,11,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6, +7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5, +7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5, +7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15, +9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,11,1792,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6, +7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5, +7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14, +7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6, +7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15, +7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7, +7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6, +7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +11,11,1856,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6, +7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5, +7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5, +7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15, +9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6, +7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5, +7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14, +7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6, +7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,11,12,2112,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15, +7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7, +7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6, +7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6, +7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5, +7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5, +7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15, +9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2368,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6, +7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5, +7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14, +7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6, +7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15, +7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7, +7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6, +7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +11,12,1984,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6, +7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5, +7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5, +7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15, +9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6, +7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5, +7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14, +7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6, +7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,11,11,1920,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15, +7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7, +7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6, +7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6, +7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5, +7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5, +7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15, +9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2240,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6, +7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5, +7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14, +7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6, +7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15, +7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7, +7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6, +7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +11,12,2496,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6, +7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5, +7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5, +7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15, +9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,12,11,0,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6, +7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5, +7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14, +7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6, +7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,11,11,1792,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15, +7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7, +7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6, +7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6, +7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5, +7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5, +7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15, +9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,11,1856,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6, +7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5, +7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14, +7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6, +7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15, +7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7, +7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6, +7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +11,12,2176,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6, +7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5, +7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5, +7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15, +9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6, +7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5, +7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14, +7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6, +7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,11,12,2432,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15, +7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7, +7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6, +7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6, +7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5, +7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1472,7,4,5,7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5, +7,8,41,7,6,16,9,9,960,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15, +9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2048,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6, +7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5, +7,8,44,7,6,17,9,9,1344,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14, +7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6, +7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15, +7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7, +7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6, +7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +11,11,1920,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6, +7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5, +7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1728,7,4,5,7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5, +7,8,42,7,6,16,9,9,1152,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15, +9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,0,0,0,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6,7,7,19,7,5,8,7,8,55,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5,7,8,53,7,5,9,9,8,448,7,4,6, +7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1472,7,4,5, +7,8,43,7,6,17,9,9,1216,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,33,9,5,128,7,8,49,7,6,14, +7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5,7,8,41,7,6,16,9,9,960,7,4,6, +7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,9,704,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15,9,8,320,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,11,12,2304,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5, +7,8,40,7,6,16,9,9,832,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6,7,8,36,9,5,128,7,8,52,7,6,15, +7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1600,7,4,5,7,8,44,7,6,17,9,9,1344,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,30,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14,7,8,62,7,4,4,7,4,2,7,4,7, +7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1088,7,4,6,7,8,32,7,5,8,7,8,58,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,8,640,7,4,6, +7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5, +7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +0,0,0,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14, +7,7,28,7,4,4,7,4,2,7,4,7,7,7,23,7,4,3,7,7,27,7,4,5,7,8,39,7,6,16,9,8,576,7,4,6, +7,7,19,7,5,8,7,8,55,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,8,45,7,4,3,7,5,11,7,4,5, +7,8,53,7,5,9,9,8,448,7,4,6,7,8,35,9,5,128,7,8,51,7,6,15,7,8,63,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,9,9,1536,7,4,5,7,8,43,7,6,17,9,9,1280,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,29,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6, +7,8,33,9,5,128,7,8,49,7,6,14,7,8,61,7,4,4,7,4,2,7,4,7,7,8,47,7,4,3,7,8,59,7,4,5, +7,8,41,7,6,16,9,9,1024,7,4,6,7,8,31,7,5,8,7,8,57,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,7,22,7,4,3,7,5,11,7,4,5,7,7,26,7,5,9,9,9,768,7,4,6,7,8,37,9,5,128,7,7,25,7,6,15, +9,8,320,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6, +7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,11,12,2560,7,4,3,7,5,11,7,4,5, +7,6,12,7,5,9,9,6,1664,7,4,6,7,7,20,9,5,128,7,7,24,7,6,14,7,7,28,7,4,4,7,4,2,7,4,7, +7,7,23,7,4,3,7,7,27,7,4,5,7,8,40,7,6,16,9,9,896,7,4,6,7,7,19,7,5,8,7,8,56,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7,7,8,46,7,4,3,7,5,11,7,4,5,7,8,54,7,5,9,9,8,512,7,4,6, +7,8,36,9,5,128,7,8,52,7,6,15,7,8,0,7,4,4,7,4,2,7,4,7,7,6,13,7,4,3,9,9,1728,7,4,5, +7,8,44,7,6,17,9,9,1408,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7, +7,8,30,7,4,3,7,5,11,7,4,5,7,6,12,7,5,9,9,6,1664,7,4,6,7,8,34,9,5,128,7,8,50,7,6,14, +7,8,62,7,4,4,7,4,2,7,4,7,7,8,48,7,4,3,7,8,60,7,4,5,7,8,42,7,6,16,9,9,1152,7,4,6, +7,8,32,7,5,8,7,8,58,9,5,64,7,5,10,7,4,4,7,4,2,7,4,7,7,7,22,7,4,3,7,5,11,7,4,5, +7,7,26,7,5,9,9,8,640,7,4,6,7,8,38,9,5,128,7,7,25,7,6,15,9,8,384,7,4,4,7,4,2,7,4,7, +7,6,13,7,4,3,7,7,18,7,4,5,7,7,21,7,6,17,9,7,256,7,4,6,7,6,1,7,5,8,9,6,192,9,5,64, +7,5,10,7,4,4,7,4,2,7,4,7 +}; +const TIFFFaxTabEnt TIFFFaxBlackTable[8192] = { +12,11,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1792,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,23,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,20,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,25,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,12,128,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,56,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,30,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,11,1856,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,57,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,21,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,54,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,52,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,48,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,12,2112,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,44,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,36,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,384,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,28,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,60,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,40,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2368,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,12,1984,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,50,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,34,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,1664,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,26,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,13,1408,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,32,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,11,1920,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,61,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,42,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1024,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,768,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,62,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2240,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,46,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,38,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,13,512,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,19,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,24,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,22,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,12,2496,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,12,11,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,11,1792,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,23,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,20,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,25,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,12,192,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,1280,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,31,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1856,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,58,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,21,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,13,896,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,640,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,49,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,12,2176,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,45,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,37,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,12,448,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,29,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,13,1536,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,41,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,12,2432,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2048,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,51,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,35,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,12,320,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,27,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,59,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,33,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,11,1920,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,256,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,43,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,1152,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,55,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,63,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,12,2304,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,47,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,39,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,53,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,19,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,24,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,22,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2560,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,12,11,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,11,1792,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,23,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,20,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,25,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,128,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,56,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,30,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,11,1856,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,57,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,21,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,54,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,52,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,48,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2112,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,44,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,36,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,12,384,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,28,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,60,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,40,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,12,2368,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,12,1984,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,50,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,34,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1728,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,26,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,1472,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,32,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1920,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,61,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,42,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,13,1088,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,832,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,62,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,12,2240,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,46,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,38,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,576,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,19,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,24,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,22,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,12,2496,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +12,11,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,11,1792,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,23,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,20,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,25,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,12,192,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1344,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,31,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,11,1856,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,58,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,11,21,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,960,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,13,704,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,49,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,12,2176,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,45,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,37,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,12,448,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,29,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,13,1600,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,41,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2432,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,18,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,10,17,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,12,2048,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,51,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,35,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,12,320,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,27,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,59,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,33,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,11,11,1920,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +10,12,256,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,43,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,10,13,1216,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,13,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,9,15,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,55,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,63,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,11,12,2304,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,12,47,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,12,39,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,12,53,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,8,14,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,0,0,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,13,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,19,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,11,24,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,7,11,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,11,22,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +11,12,2560,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,9,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,10,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,10,16,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,10,0,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,10,10,64,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,6,9,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2,8,7,11,8,2,3,8,3,1,8,2,2, +8,4,6,8,2,3,8,3,4,8,2,2,8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2, +8,8,14,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2,8,6,8,8,2,3,8,3,1,8,2,2, +8,4,5,8,2,3,8,3,4,8,2,2,8,7,12,8,2,3,8,3,1,8,2,2,8,4,6,8,2,3,8,3,4,8,2,2, +8,5,7,8,2,3,8,3,1,8,2,2,8,4,5,8,2,3,8,3,4,8,2,2 +}; diff --git a/Utilities/vtktiff/mkg3states.c b/Utilities/vtktiff/mkg3states.c new file mode 100644 index 0000000..e268f8a --- /dev/null +++ b/Utilities/vtktiff/mkg3states.c @@ -0,0 +1,438 @@ +/* "$Header: /cvsroot/VTK/VTK/Utilities/vtktiff/mkg3states.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* Initialise fax decoder tables + * Decoder support is derived, with permission, from the code + * in Frank Cringle's viewfax program; + * Copyright (C) 1990, 1995 Frank D. Cringle. + */ +#if defined(unix) || defined(__unix) +#include "port.h" +#else +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#endif + +#include <unistd.h> /* getopt */ + +#include "tif_fax3.h" + +#define streq(a,b) (strcmp(a,b) == 0) + +/* NB: can't use names in tif_fax3.h 'cuz they are declared const */ +TIFFFaxTabEnt MainTable[128]; +TIFFFaxTabEnt WhiteTable[4096]; +TIFFFaxTabEnt BlackTable[8192]; + +struct proto { + uint16 code; /* right justified, lsb-first, zero filled */ + uint16 val; /* (pixel count)<<4 + code width */ +}; + +static struct proto Pass[] = { +{ 0x0008, 4 }, +{ 0, 0 } +}; + +static struct proto Horiz[] = { +{ 0x0004, 3 }, +{ 0, 0 } +}; + +static struct proto V0[] = { +{ 0x0001, 1 }, +{ 0, 0 } +}; + +static struct proto VR[] = { +{ 0x0006, (1<<4)+3 }, +{ 0x0030, (2<<4)+6 }, +{ 0x0060, (3<<4)+7 }, +{ 0, 0 } +}; + +static struct proto VL[] = { +{ 0x0002, (1<<4)+3 }, +{ 0x0010, (2<<4)+6 }, +{ 0x0020, (3<<4)+7 }, +{ 0, 0 } +}; + +static struct proto Ext[] = { +{ 0x0040, 7 }, +{ 0, 0 } +}; + +static struct proto EOLV[] = { +{ 0x0000, 7 }, +{ 0, 0 } +}; + +static struct proto MakeUpW[] = { +{ 0x001b, 1029 }, +{ 0x0009, 2053 }, +{ 0x003a, 3078 }, +{ 0x0076, 4103 }, +{ 0x006c, 5128 }, +{ 0x00ec, 6152 }, +{ 0x0026, 7176 }, +{ 0x00a6, 8200 }, +{ 0x0016, 9224 }, +{ 0x00e6, 10248 }, +{ 0x0066, 11273 }, +{ 0x0166, 12297 }, +{ 0x0096, 13321 }, +{ 0x0196, 14345 }, +{ 0x0056, 15369 }, +{ 0x0156, 16393 }, +{ 0x00d6, 17417 }, +{ 0x01d6, 18441 }, +{ 0x0036, 19465 }, +{ 0x0136, 20489 }, +{ 0x00b6, 21513 }, +{ 0x01b6, 22537 }, +{ 0x0032, 23561 }, +{ 0x0132, 24585 }, +{ 0x00b2, 25609 }, +{ 0x0006, 26630 }, +{ 0x01b2, 27657 }, +{ 0, 0 } +}; + +static struct proto MakeUpB[] = { +{ 0x03c0, 1034 }, +{ 0x0130, 2060 }, +{ 0x0930, 3084 }, +{ 0x0da0, 4108 }, +{ 0x0cc0, 5132 }, +{ 0x02c0, 6156 }, +{ 0x0ac0, 7180 }, +{ 0x06c0, 8205 }, +{ 0x16c0, 9229 }, +{ 0x0a40, 10253 }, +{ 0x1a40, 11277 }, +{ 0x0640, 12301 }, +{ 0x1640, 13325 }, +{ 0x09c0, 14349 }, +{ 0x19c0, 15373 }, +{ 0x05c0, 16397 }, +{ 0x15c0, 17421 }, +{ 0x0dc0, 18445 }, +{ 0x1dc0, 19469 }, +{ 0x0940, 20493 }, +{ 0x1940, 21517 }, +{ 0x0540, 22541 }, +{ 0x1540, 23565 }, +{ 0x0b40, 24589 }, +{ 0x1b40, 25613 }, +{ 0x04c0, 26637 }, +{ 0x14c0, 27661 }, +{ 0, 0 } +}; + +static struct proto MakeUp[] = { +{ 0x0080, 28683 }, +{ 0x0180, 29707 }, +{ 0x0580, 30731 }, +{ 0x0480, 31756 }, +{ 0x0c80, 32780 }, +{ 0x0280, 33804 }, +{ 0x0a80, 34828 }, +{ 0x0680, 35852 }, +{ 0x0e80, 36876 }, +{ 0x0380, 37900 }, +{ 0x0b80, 38924 }, +{ 0x0780, 39948 }, +{ 0x0f80, 40972 }, +{ 0, 0 } +}; + +static struct proto TermW[] = { +{ 0x00ac, 8 }, +{ 0x0038, 22 }, +{ 0x000e, 36 }, +{ 0x0001, 52 }, +{ 0x000d, 68 }, +{ 0x0003, 84 }, +{ 0x0007, 100 }, +{ 0x000f, 116 }, +{ 0x0019, 133 }, +{ 0x0005, 149 }, +{ 0x001c, 165 }, +{ 0x0002, 181 }, +{ 0x0004, 198 }, +{ 0x0030, 214 }, +{ 0x000b, 230 }, +{ 0x002b, 246 }, +{ 0x0015, 262 }, +{ 0x0035, 278 }, +{ 0x0072, 295 }, +{ 0x0018, 311 }, +{ 0x0008, 327 }, +{ 0x0074, 343 }, +{ 0x0060, 359 }, +{ 0x0010, 375 }, +{ 0x000a, 391 }, +{ 0x006a, 407 }, +{ 0x0064, 423 }, +{ 0x0012, 439 }, +{ 0x000c, 455 }, +{ 0x0040, 472 }, +{ 0x00c0, 488 }, +{ 0x0058, 504 }, +{ 0x00d8, 520 }, +{ 0x0048, 536 }, +{ 0x00c8, 552 }, +{ 0x0028, 568 }, +{ 0x00a8, 584 }, +{ 0x0068, 600 }, +{ 0x00e8, 616 }, +{ 0x0014, 632 }, +{ 0x0094, 648 }, +{ 0x0054, 664 }, +{ 0x00d4, 680 }, +{ 0x0034, 696 }, +{ 0x00b4, 712 }, +{ 0x0020, 728 }, +{ 0x00a0, 744 }, +{ 0x0050, 760 }, +{ 0x00d0, 776 }, +{ 0x004a, 792 }, +{ 0x00ca, 808 }, +{ 0x002a, 824 }, +{ 0x00aa, 840 }, +{ 0x0024, 856 }, +{ 0x00a4, 872 }, +{ 0x001a, 888 }, +{ 0x009a, 904 }, +{ 0x005a, 920 }, +{ 0x00da, 936 }, +{ 0x0052, 952 }, +{ 0x00d2, 968 }, +{ 0x004c, 984 }, +{ 0x00cc, 1000 }, +{ 0x002c, 1016 }, +{ 0, 0 } +}; + +static struct proto TermB[] = { +{ 0x03b0, 10 }, +{ 0x0002, 19 }, +{ 0x0003, 34 }, +{ 0x0001, 50 }, +{ 0x0006, 67 }, +{ 0x000c, 84 }, +{ 0x0004, 100 }, +{ 0x0018, 117 }, +{ 0x0028, 134 }, +{ 0x0008, 150 }, +{ 0x0010, 167 }, +{ 0x0050, 183 }, +{ 0x0070, 199 }, +{ 0x0020, 216 }, +{ 0x00e0, 232 }, +{ 0x0030, 249 }, +{ 0x03a0, 266 }, +{ 0x0060, 282 }, +{ 0x0040, 298 }, +{ 0x0730, 315 }, +{ 0x00b0, 331 }, +{ 0x01b0, 347 }, +{ 0x0760, 363 }, +{ 0x00a0, 379 }, +{ 0x0740, 395 }, +{ 0x00c0, 411 }, +{ 0x0530, 428 }, +{ 0x0d30, 444 }, +{ 0x0330, 460 }, +{ 0x0b30, 476 }, +{ 0x0160, 492 }, +{ 0x0960, 508 }, +{ 0x0560, 524 }, +{ 0x0d60, 540 }, +{ 0x04b0, 556 }, +{ 0x0cb0, 572 }, +{ 0x02b0, 588 }, +{ 0x0ab0, 604 }, +{ 0x06b0, 620 }, +{ 0x0eb0, 636 }, +{ 0x0360, 652 }, +{ 0x0b60, 668 }, +{ 0x05b0, 684 }, +{ 0x0db0, 700 }, +{ 0x02a0, 716 }, +{ 0x0aa0, 732 }, +{ 0x06a0, 748 }, +{ 0x0ea0, 764 }, +{ 0x0260, 780 }, +{ 0x0a60, 796 }, +{ 0x04a0, 812 }, +{ 0x0ca0, 828 }, +{ 0x0240, 844 }, +{ 0x0ec0, 860 }, +{ 0x01c0, 876 }, +{ 0x0e40, 892 }, +{ 0x0140, 908 }, +{ 0x01a0, 924 }, +{ 0x09a0, 940 }, +{ 0x0d40, 956 }, +{ 0x0340, 972 }, +{ 0x05a0, 988 }, +{ 0x0660, 1004 }, +{ 0x0e60, 1020 }, +{ 0, 0 } +}; + +static struct proto EOLH[] = { +{ 0x0000, 11 }, +{ 0, 0 } +}; + +static void +FillTable(TIFFFaxTabEnt *T, int Size, struct proto *P, int State) +{ + int limit = 1 << Size; + + while (P->val) { + int width = P->val & 15; + int param = P->val >> 4; + int incr = 1 << width; + int code; + for (code = P->code; code < limit; code += incr) { + TIFFFaxTabEnt *E = T+code; + E->State = State; + E->Width = width; + E->Param = param; + } + P++; + } +} + +static char* storage_class = ""; +static char* const_class = ""; +static int packoutput = 1; +static char* prebrace = "{ "; +static char* postbrace = " }"; + +void +WriteTable(FILE* fd, const TIFFFaxTabEnt* T, int Size, const char* name) +{ + int i; + char* sep; + + fprintf(fd, "%s %s TIFFFaxTabEnt %s[%d] = {", + storage_class, const_class, name, Size); + if (packoutput) { + sep = "\n"; + for (i = 0; i < Size; i++) { + fprintf(fd, "%s%s%d,%d,%d%s", + sep, prebrace, T->State, T->Width, (int) T->Param, postbrace); + if (((i+1) % 12) == 0) + sep = ",\n"; + else + sep = ","; + T++; + } + } else { + sep = "\n "; + for (i = 0; i < Size; i++) { + fprintf(fd, "%s%s%3d,%3d,%4d%s", + sep, prebrace, T->State, T->Width, (int) T->Param, postbrace); + if (((i+1) % 6) == 0) + sep = ",\n "; + else + sep = ","; + T++; + } + } + fprintf(fd, "\n};\n"); +} + +/* initialise the huffman code tables */ +int +main(int argc, char* argv[]) +{ + FILE* fd; + char* outputfile; + int c; + extern int optind; + extern char* optarg; + + while ((c = getopt(argc, argv, "c:s:bp")) != -1) + switch (c) { + case 'c': + const_class = optarg; + break; + case 's': + storage_class = optarg; + break; + case 'p': + packoutput = 0; + break; + case 'b': + prebrace = "{"; + postbrace = "}"; + break; + case '?': + fprintf(stderr, + "usage: %s [-c const] [-s storage] [-p] [-b] file\n", + argv[0]); + return (-1); + } + outputfile = optind < argc ? argv[optind] : "g3states.h"; + fd = fopen(outputfile, "w"); + if (fd == NULL) { + fprintf(stderr, "%s: %s: Cannot create output file.\n", + argv[0], outputfile); + return (-2); + } + FillTable(MainTable, 7, Pass, S_Pass); + FillTable(MainTable, 7, Horiz, S_Horiz); + FillTable(MainTable, 7, V0, S_V0); + FillTable(MainTable, 7, VR, S_VR); + FillTable(MainTable, 7, VL, S_VL); + FillTable(MainTable, 7, Ext, S_Ext); + FillTable(MainTable, 7, EOLV, S_EOL); + FillTable(WhiteTable, 12, MakeUpW, S_MakeUpW); + FillTable(WhiteTable, 12, MakeUp, S_MakeUp); + FillTable(WhiteTable, 12, TermW, S_TermW); + FillTable(WhiteTable, 12, EOLH, S_EOL); + FillTable(BlackTable, 13, MakeUpB, S_MakeUpB); + FillTable(BlackTable, 13, MakeUp, S_MakeUp); + FillTable(BlackTable, 13, TermB, S_TermB); + FillTable(BlackTable, 13, EOLH, S_EOL); + + fprintf(fd, "/* WARNING, this file was automatically generated by the\n"); + fprintf(fd, " mkg3states program */\n"); + fprintf(fd, "#include \"tiff.h\"\n"); + fprintf(fd, "#include \"tif_fax3.h\"\n"); + WriteTable(fd, MainTable, 128, "TIFFFaxMainTable"); + WriteTable(fd, WhiteTable, 4096, "TIFFFaxWhiteTable"); + WriteTable(fd, BlackTable, 8192, "TIFFFaxBlackTable"); + fclose(fd); + return (0); +} diff --git a/Utilities/vtktiff/mkspans.c b/Utilities/vtktiff/mkspans.c new file mode 100644 index 0000000..be27166 --- /dev/null +++ b/Utilities/vtktiff/mkspans.c @@ -0,0 +1,72 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/mkspans.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffcomp.h" + +/* + * Hack program to construct tables used to find + * runs of zeros and ones in Group 3 Fax encoding. + */ + +dumparray(name, runs) + char *name; + unsigned char runs[256]; +{ + register int i; + register char *sep; + printf("static u_char %s[256] = {\n", name); + sep = " "; + for (i = 0; i < 256; i++) { + printf("%s%d", sep, runs[i]); + if (((i + 1) % 16) == 0) { + printf(", /* 0x%02x - 0x%02x */\n", i-15, i); + sep = " "; + } else + sep = ", "; + } + printf("\n};\n"); +} + +main() +{ + unsigned char runs[2][256]; + + memset(runs[0], 0, 256*sizeof (char)); + memset(runs[1], 0, 256*sizeof (char)); + { register int run, runlen, i; + runlen = 1; + for (run = 0x80; run != 0xff; run = (run>>1)|0x80) { + for (i = run-1; i >= 0; i--) { + runs[1][run|i] = runlen; + runs[0][(~(run|i)) & 0xff] = runlen; + } + runlen++; + } + runs[1][0xff] = runs[0][0] = 8; + } + dumparray("bruns", runs[0]); + dumparray("wruns", runs[1]); +} diff --git a/Utilities/vtktiff/mkversion.c b/Utilities/vtktiff/mkversion.c new file mode 100644 index 0000000..11beb51 --- /dev/null +++ b/Utilities/vtktiff/mkversion.c @@ -0,0 +1,175 @@ +/* "$Header: /cvsroot/VTK/VTK/Utilities/vtktiff/mkversion.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1995-1997 Sam Leffler + * Copyright (c) 1995-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * Generate a library version string for systems that + * do not have a shell (by default this is done with + * awk and echo from the Makefile). + * + * This was written by Peter Greenham for Acorn systems. + * + * Syntax: mkversion [-v version-file] [-a alpha-file] [<outfile>] + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static void +usage(void) +{ + fprintf(stderr, + "usage: mkversion [-v version-file] [-a alpha-file]\n" + " [-r releasedate-file] [outfile]\n"); + exit(-1); +} + +static FILE* +openFile(char* filename) +{ + FILE* fd = fopen(filename, "r"); + if (fd == NULL) { + fprintf(stderr, "mkversion: %s: Could not open for reading.\n", + filename); + exit(-1); + } + return (fd); +} + +int +main(int argc, char* argv[]) +{ + char* versionFile = "VERSION"; + char* releaseDateFile = "RELEASE-DATE"; + char* alphaFile = "dist/tiff.alpha"; + char version[128]; + char rawReleaseDate[128]; + char tiffLibVersion[128]; + char alpha[128]; + FILE* fd; + char* cp; + + argc--, argv++; + while (argc > 0 && argv[0][0] == '-') { + if (strcmp(argv[0], "-v") == 0) { + if (argc < 1) + usage(); + argc--, argv++; + versionFile = argv[0]; + } else if (strcmp(argv[0], "-a") == 0) { + if (argc < 1) + usage(); + argc--, argv++; + alphaFile = argv[0]; + } else if (strcmp(argv[0], "-r") == 0) { + if (argc < 1) + usage(); + argc--, argv++; + releaseDateFile = argv[0]; + } else + usage(); + argc--, argv++; + } + + /* + * Read the VERSION file. + */ + fd = openFile(versionFile); + if (fgets(version, sizeof (version)-1, fd) == NULL) { + fprintf(stderr, "mkversion: No version information in %s.\n", + versionFile); + exit(-1); + } + cp = strchr(version, '\n'); + if (cp) + *cp = '\0'; + fclose(fd); + fd = openFile(alphaFile); + if (fgets(alpha, sizeof (alpha)-1, fd) == NULL) { + fprintf(stderr, "mkversion: No alpha information in %s.\n", alphaFile); + exit(-1); + } + fclose(fd); + cp = strchr(alpha, ' '); /* skip to 3rd blank-separated field */ + if (cp) + cp = strchr(cp+1, ' '); + if (cp) { /* append alpha to version */ + char* tp; + for (tp = strchr(version, '\0'), cp++; (*tp = *cp) != 0; tp++, cp++) + ; + if (tp[-1] == '\n') + tp[-1] = '\0'; + } else { + fprintf(stderr, "mkversion: Malformed alpha information in %s.\n", + alphaFile); + exit(-1); + } + + /* + * Read the RELEASE-DATE, and translate format to emit TIFFLIB_VERSION. + */ + fd = openFile(releaseDateFile); + if (fgets(rawReleaseDate, sizeof (version)-1, fd) == NULL) { + fprintf(stderr, "mkversion: No release date information in %s.\n", + releaseDateFile); + exit(-1); + } + fclose(fd); + + sprintf( tiffLibVersion, "#define TIFFLIB_VERSION %4.4s%2.2s%2.2s", + rawReleaseDate+6, + rawReleaseDate+0, + rawReleaseDate+3 ); + + /* + * Emit the version.h file. + */ + if (argc > 0) { + fd = fopen(argv[0], "w"); + if (fd == NULL) { + fprintf(stderr, "mkversion: %s: Could not open for writing.\n", + argv[0]); + exit(-1); + } + } else + fd = stdout; + fprintf(fd, "#define TIFFLIB_VERSION_STR \"LIBTIFF, Version %s\\n", version); + fprintf(fd, "Copyright (c) 1988-1996 Sam Leffler\\n"); + fprintf(fd, "Copyright (c) 1991-1996 Silicon Graphics, Inc.\"\n"); + + fprintf( fd, + "/*\n" + " * This define can be used in code that requires\n" + " * compilation-related definitions specific to a\n" + " * version or versions of the library. Runtime\n" + " * version checking should be done based on the\n" + " * string returned by TIFFGetVersion.\n" + " */\n" ); + fprintf(fd, "%s\n", tiffLibVersion ); + + if (fd != stdout) + fclose(fd); + return (0); +} diff --git a/Utilities/vtktiff/port.h b/Utilities/vtktiff/port.h new file mode 100644 index 0000000..e98e400 --- /dev/null +++ b/Utilities/vtktiff/port.h @@ -0,0 +1,36 @@ +/* + * Warning, this file was automatically created by the TIFF configure script + * VERSION: v3.5.7 + * RELEASE: + * DATE: Mon Dec 17 13:18:52 EST 2001 + * TARGET: i686-pc-linux-gnu + * CCOMPILER: /usr/bin/gcc3-3.0.1-3) + */ +#ifndef _PORT_ +#define _PORT_ 1 +#ifdef __cplusplus +extern "C" { +#endif +#include <sys/types.h> +#define HOST_FILLORDER FILLORDER_MSB2LSB +#ifdef VTK_WORDS_BIGENDIAN +#define HOST_BIGENDIAN 1 +#else +#define HOST_BIGENDIAN 0 +#endif +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +typedef double dblparam_t; +#ifdef __STRICT_ANSI__ +#define INLINE __inline__ +#else +#define INLINE inline +#endif +#define GLOBALDATA(TYPE,NAME) extern TYPE NAME +#ifdef __cplusplus +} +#endif +#endif diff --git a/Utilities/vtktiff/t4.h b/Utilities/vtktiff/t4.h new file mode 100644 index 0000000..1b46352 --- /dev/null +++ b/Utilities/vtktiff/t4.h @@ -0,0 +1,285 @@ +/* $Id: t4.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _T4_ +#define _T4_ +/* + * CCITT T.4 1D Huffman runlength codes and + * related definitions. Given the small sizes + * of these tables it does not seem + * worthwhile to make code & length 8 bits. + */ +typedef struct tableentry { + unsigned short length; /* bit length of g3 code */ + unsigned short code; /* g3 code */ + short runlen; /* run length in bits */ +} tableentry; + +#define EOL 0x001 /* EOL code value - 0000 0000 0000 1 */ + +/* status values returned instead of a run length */ +#define G3CODE_EOL -1 /* NB: ACT_EOL - ACT_WRUNT */ +#define G3CODE_INVALID -2 /* NB: ACT_INVALID - ACT_WRUNT */ +#define G3CODE_EOF -3 /* end of input data */ +#define G3CODE_INCOMP -4 /* incomplete run code */ + +/* + * Note that these tables are ordered such that the + * index into the table is known to be either the + * run length, or (run length / 64) + a fixed offset. + * + * NB: The G3CODE_INVALID entries are only used + * during state generation (see mkg3states.c). + */ +#ifdef G3CODES +const tableentry TIFFFaxWhiteCodes[] = { + { 8, 0x35, 0 }, /* 0011 0101 */ + { 6, 0x7, 1 }, /* 0001 11 */ + { 4, 0x7, 2 }, /* 0111 */ + { 4, 0x8, 3 }, /* 1000 */ + { 4, 0xB, 4 }, /* 1011 */ + { 4, 0xC, 5 }, /* 1100 */ + { 4, 0xE, 6 }, /* 1110 */ + { 4, 0xF, 7 }, /* 1111 */ + { 5, 0x13, 8 }, /* 1001 1 */ + { 5, 0x14, 9 }, /* 1010 0 */ + { 5, 0x7, 10 }, /* 0011 1 */ + { 5, 0x8, 11 }, /* 0100 0 */ + { 6, 0x8, 12 }, /* 0010 00 */ + { 6, 0x3, 13 }, /* 0000 11 */ + { 6, 0x34, 14 }, /* 1101 00 */ + { 6, 0x35, 15 }, /* 1101 01 */ + { 6, 0x2A, 16 }, /* 1010 10 */ + { 6, 0x2B, 17 }, /* 1010 11 */ + { 7, 0x27, 18 }, /* 0100 111 */ + { 7, 0xC, 19 }, /* 0001 100 */ + { 7, 0x8, 20 }, /* 0001 000 */ + { 7, 0x17, 21 }, /* 0010 111 */ + { 7, 0x3, 22 }, /* 0000 011 */ + { 7, 0x4, 23 }, /* 0000 100 */ + { 7, 0x28, 24 }, /* 0101 000 */ + { 7, 0x2B, 25 }, /* 0101 011 */ + { 7, 0x13, 26 }, /* 0010 011 */ + { 7, 0x24, 27 }, /* 0100 100 */ + { 7, 0x18, 28 }, /* 0011 000 */ + { 8, 0x2, 29 }, /* 0000 0010 */ + { 8, 0x3, 30 }, /* 0000 0011 */ + { 8, 0x1A, 31 }, /* 0001 1010 */ + { 8, 0x1B, 32 }, /* 0001 1011 */ + { 8, 0x12, 33 }, /* 0001 0010 */ + { 8, 0x13, 34 }, /* 0001 0011 */ + { 8, 0x14, 35 }, /* 0001 0100 */ + { 8, 0x15, 36 }, /* 0001 0101 */ + { 8, 0x16, 37 }, /* 0001 0110 */ + { 8, 0x17, 38 }, /* 0001 0111 */ + { 8, 0x28, 39 }, /* 0010 1000 */ + { 8, 0x29, 40 }, /* 0010 1001 */ + { 8, 0x2A, 41 }, /* 0010 1010 */ + { 8, 0x2B, 42 }, /* 0010 1011 */ + { 8, 0x2C, 43 }, /* 0010 1100 */ + { 8, 0x2D, 44 }, /* 0010 1101 */ + { 8, 0x4, 45 }, /* 0000 0100 */ + { 8, 0x5, 46 }, /* 0000 0101 */ + { 8, 0xA, 47 }, /* 0000 1010 */ + { 8, 0xB, 48 }, /* 0000 1011 */ + { 8, 0x52, 49 }, /* 0101 0010 */ + { 8, 0x53, 50 }, /* 0101 0011 */ + { 8, 0x54, 51 }, /* 0101 0100 */ + { 8, 0x55, 52 }, /* 0101 0101 */ + { 8, 0x24, 53 }, /* 0010 0100 */ + { 8, 0x25, 54 }, /* 0010 0101 */ + { 8, 0x58, 55 }, /* 0101 1000 */ + { 8, 0x59, 56 }, /* 0101 1001 */ + { 8, 0x5A, 57 }, /* 0101 1010 */ + { 8, 0x5B, 58 }, /* 0101 1011 */ + { 8, 0x4A, 59 }, /* 0100 1010 */ + { 8, 0x4B, 60 }, /* 0100 1011 */ + { 8, 0x32, 61 }, /* 0011 0010 */ + { 8, 0x33, 62 }, /* 0011 0011 */ + { 8, 0x34, 63 }, /* 0011 0100 */ + { 5, 0x1B, 64 }, /* 1101 1 */ + { 5, 0x12, 128 }, /* 1001 0 */ + { 6, 0x17, 192 }, /* 0101 11 */ + { 7, 0x37, 256 }, /* 0110 111 */ + { 8, 0x36, 320 }, /* 0011 0110 */ + { 8, 0x37, 384 }, /* 0011 0111 */ + { 8, 0x64, 448 }, /* 0110 0100 */ + { 8, 0x65, 512 }, /* 0110 0101 */ + { 8, 0x68, 576 }, /* 0110 1000 */ + { 8, 0x67, 640 }, /* 0110 0111 */ + { 9, 0xCC, 704 }, /* 0110 0110 0 */ + { 9, 0xCD, 768 }, /* 0110 0110 1 */ + { 9, 0xD2, 832 }, /* 0110 1001 0 */ + { 9, 0xD3, 896 }, /* 0110 1001 1 */ + { 9, 0xD4, 960 }, /* 0110 1010 0 */ + { 9, 0xD5, 1024 }, /* 0110 1010 1 */ + { 9, 0xD6, 1088 }, /* 0110 1011 0 */ + { 9, 0xD7, 1152 }, /* 0110 1011 1 */ + { 9, 0xD8, 1216 }, /* 0110 1100 0 */ + { 9, 0xD9, 1280 }, /* 0110 1100 1 */ + { 9, 0xDA, 1344 }, /* 0110 1101 0 */ + { 9, 0xDB, 1408 }, /* 0110 1101 1 */ + { 9, 0x98, 1472 }, /* 0100 1100 0 */ + { 9, 0x99, 1536 }, /* 0100 1100 1 */ + { 9, 0x9A, 1600 }, /* 0100 1101 0 */ + { 6, 0x18, 1664 }, /* 0110 00 */ + { 9, 0x9B, 1728 }, /* 0100 1101 1 */ + { 11, 0x8, 1792 }, /* 0000 0001 000 */ + { 11, 0xC, 1856 }, /* 0000 0001 100 */ + { 11, 0xD, 1920 }, /* 0000 0001 101 */ + { 12, 0x12, 1984 }, /* 0000 0001 0010 */ + { 12, 0x13, 2048 }, /* 0000 0001 0011 */ + { 12, 0x14, 2112 }, /* 0000 0001 0100 */ + { 12, 0x15, 2176 }, /* 0000 0001 0101 */ + { 12, 0x16, 2240 }, /* 0000 0001 0110 */ + { 12, 0x17, 2304 }, /* 0000 0001 0111 */ + { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ + { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ + { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ + { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ + { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ + { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ + { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ + { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ + { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ +}; + +const tableentry TIFFFaxBlackCodes[] = { + { 10, 0x37, 0 }, /* 0000 1101 11 */ + { 3, 0x2, 1 }, /* 010 */ + { 2, 0x3, 2 }, /* 11 */ + { 2, 0x2, 3 }, /* 10 */ + { 3, 0x3, 4 }, /* 011 */ + { 4, 0x3, 5 }, /* 0011 */ + { 4, 0x2, 6 }, /* 0010 */ + { 5, 0x3, 7 }, /* 0001 1 */ + { 6, 0x5, 8 }, /* 0001 01 */ + { 6, 0x4, 9 }, /* 0001 00 */ + { 7, 0x4, 10 }, /* 0000 100 */ + { 7, 0x5, 11 }, /* 0000 101 */ + { 7, 0x7, 12 }, /* 0000 111 */ + { 8, 0x4, 13 }, /* 0000 0100 */ + { 8, 0x7, 14 }, /* 0000 0111 */ + { 9, 0x18, 15 }, /* 0000 1100 0 */ + { 10, 0x17, 16 }, /* 0000 0101 11 */ + { 10, 0x18, 17 }, /* 0000 0110 00 */ + { 10, 0x8, 18 }, /* 0000 0010 00 */ + { 11, 0x67, 19 }, /* 0000 1100 111 */ + { 11, 0x68, 20 }, /* 0000 1101 000 */ + { 11, 0x6C, 21 }, /* 0000 1101 100 */ + { 11, 0x37, 22 }, /* 0000 0110 111 */ + { 11, 0x28, 23 }, /* 0000 0101 000 */ + { 11, 0x17, 24 }, /* 0000 0010 111 */ + { 11, 0x18, 25 }, /* 0000 0011 000 */ + { 12, 0xCA, 26 }, /* 0000 1100 1010 */ + { 12, 0xCB, 27 }, /* 0000 1100 1011 */ + { 12, 0xCC, 28 }, /* 0000 1100 1100 */ + { 12, 0xCD, 29 }, /* 0000 1100 1101 */ + { 12, 0x68, 30 }, /* 0000 0110 1000 */ + { 12, 0x69, 31 }, /* 0000 0110 1001 */ + { 12, 0x6A, 32 }, /* 0000 0110 1010 */ + { 12, 0x6B, 33 }, /* 0000 0110 1011 */ + { 12, 0xD2, 34 }, /* 0000 1101 0010 */ + { 12, 0xD3, 35 }, /* 0000 1101 0011 */ + { 12, 0xD4, 36 }, /* 0000 1101 0100 */ + { 12, 0xD5, 37 }, /* 0000 1101 0101 */ + { 12, 0xD6, 38 }, /* 0000 1101 0110 */ + { 12, 0xD7, 39 }, /* 0000 1101 0111 */ + { 12, 0x6C, 40 }, /* 0000 0110 1100 */ + { 12, 0x6D, 41 }, /* 0000 0110 1101 */ + { 12, 0xDA, 42 }, /* 0000 1101 1010 */ + { 12, 0xDB, 43 }, /* 0000 1101 1011 */ + { 12, 0x54, 44 }, /* 0000 0101 0100 */ + { 12, 0x55, 45 }, /* 0000 0101 0101 */ + { 12, 0x56, 46 }, /* 0000 0101 0110 */ + { 12, 0x57, 47 }, /* 0000 0101 0111 */ + { 12, 0x64, 48 }, /* 0000 0110 0100 */ + { 12, 0x65, 49 }, /* 0000 0110 0101 */ + { 12, 0x52, 50 }, /* 0000 0101 0010 */ + { 12, 0x53, 51 }, /* 0000 0101 0011 */ + { 12, 0x24, 52 }, /* 0000 0010 0100 */ + { 12, 0x37, 53 }, /* 0000 0011 0111 */ + { 12, 0x38, 54 }, /* 0000 0011 1000 */ + { 12, 0x27, 55 }, /* 0000 0010 0111 */ + { 12, 0x28, 56 }, /* 0000 0010 1000 */ + { 12, 0x58, 57 }, /* 0000 0101 1000 */ + { 12, 0x59, 58 }, /* 0000 0101 1001 */ + { 12, 0x2B, 59 }, /* 0000 0010 1011 */ + { 12, 0x2C, 60 }, /* 0000 0010 1100 */ + { 12, 0x5A, 61 }, /* 0000 0101 1010 */ + { 12, 0x66, 62 }, /* 0000 0110 0110 */ + { 12, 0x67, 63 }, /* 0000 0110 0111 */ + { 10, 0xF, 64 }, /* 0000 0011 11 */ + { 12, 0xC8, 128 }, /* 0000 1100 1000 */ + { 12, 0xC9, 192 }, /* 0000 1100 1001 */ + { 12, 0x5B, 256 }, /* 0000 0101 1011 */ + { 12, 0x33, 320 }, /* 0000 0011 0011 */ + { 12, 0x34, 384 }, /* 0000 0011 0100 */ + { 12, 0x35, 448 }, /* 0000 0011 0101 */ + { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */ + { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */ + { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */ + { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */ + { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */ + { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */ + { 13, 0x72, 896 }, /* 0000 0011 1001 0 */ + { 13, 0x73, 960 }, /* 0000 0011 1001 1 */ + { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */ + { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */ + { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */ + { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */ + { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */ + { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */ + { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */ + { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */ + { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */ + { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */ + { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */ + { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */ + { 11, 0x8, 1792 }, /* 0000 0001 000 */ + { 11, 0xC, 1856 }, /* 0000 0001 100 */ + { 11, 0xD, 1920 }, /* 0000 0001 101 */ + { 12, 0x12, 1984 }, /* 0000 0001 0010 */ + { 12, 0x13, 2048 }, /* 0000 0001 0011 */ + { 12, 0x14, 2112 }, /* 0000 0001 0100 */ + { 12, 0x15, 2176 }, /* 0000 0001 0101 */ + { 12, 0x16, 2240 }, /* 0000 0001 0110 */ + { 12, 0x17, 2304 }, /* 0000 0001 0111 */ + { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ + { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ + { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ + { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ + { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ + { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ + { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ + { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ + { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ +}; +#else +extern const tableentry TIFFFaxWhiteCodes[]; +extern const tableentry TIFFFaxBlackCodes[]; +#endif +#endif /* _T4_ */ diff --git a/Utilities/vtktiff/tconf.h b/Utilities/vtktiff/tconf.h new file mode 100644 index 0000000..8675208 --- /dev/null +++ b/Utilities/vtktiff/tconf.h @@ -0,0 +1,59 @@ +#include <vtktiff/tiffDllConfig.h> + +/* Compile with -DTIFFDLL for Windows DLL support */ +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +#if defined(TIFFDLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include <windows.h> +# define TEXPORT WINAPI +# ifdef WIN32 +# define TEXPORTVA WINAPIV +# else +# define TEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include <windows.h> +/* +# define TEXPORT __declspec(dllexport) WINAPI +# define TEXPORTRVA __declspec(dllexport) WINAPIV +*/ +# define TEXPORT _cdecl _export +# define TEXPORTRVA _cdecl _export +# else +# if defined (_Windows) && defined (__DLL__) +# define TEXPORT _export +# define TEXPORTVA _export +# endif +# endif +# endif +#endif +#ifndef TEXPORT +# define TEXPORT +#endif +#ifndef TEXPORTVA +# define TEXPORTVA +#endif +#ifndef TEXTERN +# define TEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + diff --git a/Utilities/vtktiff/tif_acorn.c b/Utilities/vtktiff/tif_acorn.c new file mode 100644 index 0000000..5dececa --- /dev/null +++ b/Utilities/vtktiff/tif_acorn.c @@ -0,0 +1,519 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_acorn.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library RISC OS specific Routines. + * Developed out of the Unix version. + * Peter Greenham, May 1995 + */ +#include "tiffiop.h" +#include <stdio.h> +#include <stdlib.h> + +/* +Low-level file handling +~~~~~~~~~~~~~~~~~~~~~~~ +The functions in osfcn.h are unavailable when compiling under C, as it's a +C++ header. Therefore they have been implemented here. + +Now, why have I done it this way? + +The definitive API library for RISC OS is Jonathan Coxhead's OSLib, which +uses heavily optimised ARM assembler or even plain inline SWI calls for +maximum performance and minimum runtime size. However, I don't want to make +LIBTIFF need that to survive. Therefore I have also emulated the functions +using macros to _swi() and _swix() defined in the swis.h header, and +borrowing types from kernel.h, which is less efficient but doesn't need any +third-party libraries. + */ + +#ifdef INCLUDE_OSLIB + +#include "osfile.h" +#include "osgbpb.h" +#include "osargs.h" +#include "osfind.h" + +#else + +/* OSLIB EMULATION STARTS */ + +#include "kernel.h" +#include "swis.h" + +/* From oslib:types.h */ +typedef unsigned int bits; +typedef unsigned char byte; +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif +#ifndef SKIP +#define SKIP 0 +#endif + +/* From oslib:os.h */ +typedef _kernel_oserror os_error; +typedef byte os_f; + +/* From oslib:osfile.h */ +#undef OS_File +#define OS_File 0x8 + +/* From oslib:osgbpb.h */ +#undef OS_GBPB +#define OS_GBPB 0xC +#undef OSGBPB_Write +#define OSGBPB_Write 0x2 +#undef OSGBPB_Read +#define OSGBPB_Read 0x4 + +extern os_error *xosgbpb_write (os_f file, + byte *data, + int size, + int *unwritten); +extern int osgbpb_write (os_f file, + byte *data, + int size); + +#define xosgbpb_write(file, data, size, unwritten) \ + (os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_IN(4)|_OUT(3), \ + OSGBPB_WriteAt, \ + file, \ + data, \ + size, \ + unwritten) + +#define osgbpb_write(file, data, size) \ + _swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \ + OSGBPB_Write, \ + file, \ + data, \ + size) + +extern os_error *xosgbpb_read (os_f file, + byte *buffer, + int size, + int *unread); +extern int osgbpb_read (os_f file, + byte *buffer, + int size); + +#define xosgbpb_read(file, buffer, size, unread) \ + (os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_OUT(3), \ + OSGBPB_Read, \ + file, \ + buffer, \ + size, \ + unread) + +#define osgbpb_read(file, buffer, size) \ + _swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \ + OSGBPB_Read, \ + file, \ + buffer, \ + size) + +/* From oslib:osfind.h */ +#undef OS_Find +#define OS_Find 0xD +#undef OSFind_Openin +#define OSFind_Openin 0x40 +#undef OSFind_Openout +#define OSFind_Openout 0x80 +#undef OSFind_Openup +#define OSFind_Openup 0xC0 +#undef OSFind_Close +#define OSFind_Close 0x0 + +#define xosfind_open(reason, file_name, path, file) \ + (os_error*) _swix(OS_Find, _IN(0)|_IN(1)|_IN(2)|_OUT(0), \ + reason, file_name, path, file) + +#define osfind_open(reason, file_name, path) \ + (os_f) _swi(OS_Find, _IN(0)|_IN(1)|_IN(2)|_RETURN(0), \ + reason, file_name, path) + +extern os_error *xosfind_openin (bits flags, + char *file_name, + char *path, + os_f *file); +extern os_f osfind_openin (bits flags, + char *file_name, + char *path); + +#define xosfind_openin(flags, file_name, path, file) \ + xosfind_open(flags | OSFind_Openin, file_name, path, file) + +#define osfind_openin(flags, file_name, path) \ + osfind_open(flags | OSFind_Openin, file_name, path) + +extern os_error *xosfind_openout (bits flags, + char *file_name, + char *path, + os_f *file); +extern os_f osfind_openout (bits flags, + char *file_name, + char *path); + +#define xosfind_openout(flags, file_name, path, file) \ + xosfind_open(flags | OSFind_Openout, file_name, path, file) + +#define osfind_openout(flags, file_name, path) \ + osfind_open(flags | OSFind_Openout, file_name, path) + +extern os_error *xosfind_openup (bits flags, + char *file_name, + char *path, + os_f *file); +extern os_f osfind_openup (bits flags, + char *file_name, + char *path); + +#define xosfind_openup(flags, file_name, path, file) \ + xosfind_open(flags | OSFind_Openup, file_name, path, file) + +#define osfind_openup(flags, file_name, path) \ + osfind_open(flags | OSFind_Openup, file_name, path) + +extern os_error *xosfind_close (os_f file); +extern void osfind_close (os_f file); + +#define xosfind_close(file) \ + (os_error*) _swix(OS_Find, _IN(0)|_IN(1), \ + OSFind_Close, \ + file) + +#define osfind_close(file) \ + (void) _swi(OS_Find, _IN(0)|_IN(1), \ + OSFind_Close, \ + file) + +/* From oslib:osargs.h */ +#undef OS_Args +#define OS_Args 0x9 +#undef OSArgs_ReadPtr +#define OSArgs_ReadPtr 0x0 +#undef OSArgs_SetPtr +#define OSArgs_SetPtr 0x1 +#undef OSArgs_ReadExt +#define OSArgs_ReadExt 0x2 + +extern os_error *xosargs_read_ptr (os_f file, + int *ptr); +extern int osargs_read_ptr (os_f file); + +#define xosargs_read_ptr(file, ptr) \ + (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \ + OSArgs_ReadPtr, \ + file, \ + ptr) + +#define osargs_read_ptr(file) \ + _swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \ + OSArgs_ReadPtr, \ + file) + +extern os_error *xosargs_set_ptr (os_f file, + int ptr); +extern void osargs_set_ptr (os_f file, + int ptr); + +#define xosargs_set_ptr(file, ptr) \ + (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_IN(2), \ + OSArgs_SetPtr, \ + file, \ + ptr) + +#define osargs_set_ptr(file, ptr) \ + (void) _swi(OS_Args, _IN(0)|_IN(1)|_IN(2), \ + OSArgs_SetPtr, \ + file, \ + ptr) + +extern os_error *xosargs_read_ext (os_f file, + int *ext); +extern int osargs_read_ext (os_f file); + +#define xosargs_read_ext(file, ext) \ + (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \ + OSArgs_ReadExt, \ + file, \ + ext) + +#define osargs_read_ext(file) \ + _swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \ + OSArgs_ReadExt, \ + file) + +/* OSLIB EMULATION ENDS */ + +#endif + +#ifndef __osfcn_h +/* Will be set or not during tiffcomp.h */ +/* You get this to compile under C++? Please say how! */ + +extern int open(const char* name, int flags, int mode) +{ + /* From what I can tell, should return <0 for failure */ + os_error* e = (os_error*) 1; /* Cheeky way to use a pointer eh? :-) */ + os_f file = (os_f) -1; + + flags = flags; + + switch(mode) + { + case O_RDONLY: + { + e = xosfind_openin(SKIP, name, SKIP, &file); + break; + } + case O_WRONLY: + case O_RDWR|O_CREAT: + case O_RDWR|O_CREAT|O_TRUNC: + { + e = xosfind_openout(SKIP, name, SKIP, &file); + break; + } + case O_RDWR: + { + e = xosfind_openup(SKIP, name, SKIP, &file); + break; + } + } + if (e) + { + file = (os_f) -1; + } + return (file); +} + +extern int close(int fd) +{ + return ((int) xosfind_close((os_f) fd)); +} + +extern int write(int fd, const char *buf, int nbytes) +{ + /* Returns number of bytes written */ + return (nbytes - osgbpb_write((os_f) fd, (const byte*) buf, nbytes)); +} + +extern int read(int fd, char *buf, int nbytes) +{ + /* Returns number of bytes read */ + return (nbytes - osgbpb_read((os_f) fd, (byte*) buf, nbytes)); +} + +extern off_t lseek(int fd, off_t offset, int whence) +{ + int absolute = 0; + + switch (whence) + { + case SEEK_SET: + { + absolute = (int) offset; + break; + } + case SEEK_CUR: + { + absolute = osargs_read_ptr((os_f) fd) + (int) offset; + break; + } + case SEEK_END: + { + absolute = osargs_read_ext((os_f) fd) + (int) offset; + break; + } + } + + osargs_set_ptr((os_f) fd, absolute); + + return ((off_t) osargs_read_ptr((os_f) fd)); +} +#endif + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return ((tsize_t) read((int) fd, buf, (size_t) size)); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return ((tsize_t) write((int) fd, buf, (size_t) size)); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ + return ((toff_t) lseek((int) fd, (off_t) off, whence)); +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (close((int) fd)); +} + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + return (lseek((int) fd, SEEK_END, SEEK_SET)); +} + +#ifdef HAVE_MMAP +#error "I didn't know Acorn had that!" +#endif + +/* !HAVE_MMAP */ +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + (void) fd; (void) pbase; (void) psize; + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + (void) fd; (void) base; (void) size; +} + +/* + * Open a TIFF file descriptor for read/writing. + */ +TIFF* +TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, + (thandle_t) fd, + _tiffReadProc, _tiffWriteProc, + _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, + _tiffMapProc, _tiffUnmapProc); + if (tif) + { + tif->tif_fd = fd; + } + return (tif); +} + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + int m, fd; + + m = _TIFFgetMode(mode, module); + + if (m == -1) + { + return ((TIFF*) 0); + } + + fd = open(name, 0, m); + + if (fd < 0) + { + TIFFError(module, "%s: Cannot open", name); + return ((TIFF *)0); + } + return (TIFFFdOpen(fd, name, mode)); +} + +void* +_TIFFmalloc(tsize_t s) +{ + return (malloc((size_t) s)); +} + +void +_TIFFfree(tdata_t p) +{ + free(p); +} + +void* +_TIFFrealloc(tdata_t p, tsize_t s) +{ + return (realloc(p, (size_t) s)); +} + +void +_TIFFmemset(tdata_t p, int v, tsize_t c) +{ + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) +{ + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + return (memcmp(p1, p2, (size_t) c)); +} + +static void +acornWarningHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + { + fprintf(stderr, "%s: ", module); + } + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFwarningHandler = acornWarningHandler; + +static void +acornErrorHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + { + fprintf(stderr, "%s: ", module); + } + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFerrorHandler = acornErrorHandler; diff --git a/Utilities/vtktiff/tif_apple.c b/Utilities/vtktiff/tif_apple.c new file mode 100644 index 0000000..ba34f8e --- /dev/null +++ b/Utilities/vtktiff/tif_apple.c @@ -0,0 +1,274 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_apple.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library Macintosh-specific routines. + * + * These routines use only Toolbox and high-level File Manager traps. + * They make no calls to the THINK C "unix" compatibility library. Also, + * malloc is not used directly but it is still referenced internally by + * the ANSI library in rare cases. Heap fragmentation by the malloc ring + * buffer is therefore minimized. + * + * O_RDONLY and O_RDWR are treated identically here. The tif_mode flag is + * checked in TIFFWriteCheck(). + * + * Create below fills in a blank creator signature and sets the file type + * to 'TIFF'. It is much better for the application to do this by Create'ing + * the file first and TIFFOpen'ing it later. + * --------- + * This code has been "Carbonized", and may not work with older MacOS versions. + * If so, grab the tif_apple.c out of an older libtiff distribution, like + * 3.5.5 from www.libtiff.org. + */ + +#include "tiffiop.h" +#include <Errors.h> +#include <Files.h> +#include <Memory.h> +#include <Script.h> + +#if defined(__PPCC__) || defined(__SC__) || defined(__MRC__) || defined(applec) +#define CtoPstr c2pstr +#endif + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (FSRead((short) fd, (long*) &size, (char*) buf) == noErr ? + size : (tsize_t) -1); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (FSWrite((short) fd, (long*) &size, (char*) buf) == noErr ? + size : (tsize_t) -1); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ + long fpos, size; + + if (GetEOF((short) fd, &size) != noErr) + return EOF; + (void) GetFPos((short) fd, &fpos); + + switch (whence) { + case SEEK_CUR: + if (off + fpos > size) + SetEOF((short) fd, off + fpos); + if (SetFPos((short) fd, fsFromMark, off) != noErr) + return EOF; + break; + case SEEK_END: + if (off > 0) + SetEOF((short) fd, off + size); + if (SetFPos((short) fd, fsFromStart, off + size) != noErr) + return EOF; + break; + case SEEK_SET: + if (off > size) + SetEOF((short) fd, off); + if (SetFPos((short) fd, fsFromStart, off) != noErr) + return EOF; + break; + } + + return (toff_t)(GetFPos((short) fd, &fpos) == noErr ? fpos : EOF); +} + +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (FSClose((short) fd)); +} + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + long size; + + if (GetEOF((short) fd, &size) != noErr) { + TIFFError("_tiffSizeProc", "%s: Cannot get file size"); + return (-1L); + } + return ((toff_t) size); +} + +/* + * Open a TIFF file descriptor for read/writing. + */ +TIFF* +TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, (thandle_t) fd, + _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, + _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); + if (tif) + tif->tif_fd = fd; + return (tif); +} + +static void ourc2pstr( char* inString ) +{ + int sLen = strlen( inString ); + BlockMoveData( inString, &inString[1], sLen ); + inString[0] = sLen; +} + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + Str255 pname; + FInfo finfo; + short fref; + OSErr err; + FSSpec fSpec; + + strcpy((char*) pname, name); + ourc2pstr((char*) pname); + + err = FSMakeFSSpec( 0, 0, pname, &fSpec ); + + switch (_TIFFgetMode(mode, module)) { + default: + return ((TIFF*) 0); + case O_RDWR | O_CREAT | O_TRUNC: + if (FSpGetFInfo(&fSpec, &finfo) == noErr) + FSpDelete(&fSpec); + /* fall through */ + case O_RDWR | O_CREAT: + if ((err = FSpGetFInfo(&fSpec, &finfo)) == fnfErr) { + if (FSpCreate(&fSpec, ' ', 'TIFF', smSystemScript) != noErr) + goto badCreate; + if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr) + goto badOpen; + } else if (err == noErr) { + if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr) + goto badOpen; + } else + goto badOpen; + break; + case O_RDONLY: + if (FSpOpenDF(&fSpec, fsRdPerm, &fref) != noErr) + goto badOpen; + break; + case O_RDWR: + if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr) + goto badOpen; + break; + } + return (TIFFFdOpen((int) fref, name, mode)); +badCreate: + TIFFError(module, "%s: Cannot create", name); + return ((TIFF*) 0); +badOpen: + TIFFError(module, "%s: Cannot open", name); + return ((TIFF*) 0); +} + +void +_TIFFmemset(tdata_t p, int v, tsize_t c) +{ + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) +{ + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + return (memcmp(p1, p2, (size_t) c)); +} + +tdata_t +_TIFFmalloc(tsize_t s) +{ + return (NewPtr((size_t) s)); +} + +void +_TIFFfree(tdata_t p) +{ + DisposePtr(p); +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + Ptr n = p; + + SetPtrSize(p, (size_t) s); + if (MemError() && (n = NewPtr((size_t) s)) != NULL) { + BlockMove(p, n, GetPtrSize(p)); + DisposePtr(p); + } + return ((tdata_t) n); +} + +static void +appleWarningHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFwarningHandler = appleWarningHandler; + +static void +appleErrorHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFerrorHandler = appleErrorHandler; diff --git a/Utilities/vtktiff/tif_atari.c b/Utilities/vtktiff/tif_atari.c new file mode 100644 index 0000000..89c9063 --- /dev/null +++ b/Utilities/vtktiff/tif_atari.c @@ -0,0 +1,243 @@ +/* "$Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_atari.c,v 1.1 2004/04/28 15:49:22 king Exp $" */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library ATARI-specific Routines. + */ +#include "tiffiop.h" +#if defined(__TURBOC__) +#include <tos.h> +#include <stdio.h> +#else +#include <osbind.h> +#include <fcntl.h> +#endif + +#ifndef O_ACCMODE +#define O_ACCMODE 3 +#endif + +#include <errno.h> + +#define AEFILNF -33 + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + long r; + + r = Fread((int) fd, size, buf); + if (r < 0) { + errno = (int)-r; + r = -1; + } + return r; +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + long r; + + r = Fwrite((int) fd, size, buf); + if (r < 0) { + errno = (int)-r; + r = -1; + } + return r; +} + +static toff_t +_tiffSeekProc(thandle_t fd, off_t off, int whence) +{ + char buf[256]; + long current_off, expected_off, new_off; + + if (whence == SEEK_END || off <= 0) + return Fseek(off, (int) fd, whence); + current_off = Fseek(0, (int) fd, SEEK_CUR); /* find out where we are */ + if (whence == SEEK_SET) + expected_off = off; + else + expected_off = off + current_off; + new_off = Fseek(off, (int) fd, whence); + if (new_off == expected_off) + return new_off; + /* otherwise extend file -- zero filling the hole */ + if (new_off < 0) /* error? */ + new_off = Fseek(0, (int) fd, SEEK_END); /* go to eof */ + _TIFFmemset(buf, 0, sizeof(buf)); + while (expected_off > new_off) { + off = expected_off - new_off; + if (off > sizeof(buf)) + off = sizeof(buf); + if ((current_off = Fwrite((int) fd, off, buf)) != off) + return (current_off > 0) ? + new_off + current_off : new_off; + new_off += off; + } + return new_off; +} + +static int +_tiffCloseProc(thandle_t fd) +{ + long r; + + r = Fclose((int) fd); + if (r < 0) { + errno = (int)-r; + r = -1; + } + return (int)r; +} + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + long pos, eof; + + pos = Fseek(0, (int) fd, SEEK_CUR); + eof = Fseek(0, (int) fd, SEEK_END); + Fseek(pos, (int) fd, SEEK_SET); + return eof; +} + +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ +} + +/* +* Open a TIFF file descriptor for read/writing. +*/ +TIFF* +TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, + (thandle_t) fd, + _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, + _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); + if (tif) + tif->tif_fd = fd; + return (tif); +} + +/* +* Open a TIFF file for read/writing. +*/ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + int m; + long fd; + + m = _TIFFgetMode(mode, module); + if (m == -1) + return ((TIFF*)0); + if (m & O_TRUNC) { + fd = Fcreate(name, 0); + } else { + fd = Fopen(name, m & O_ACCMODE); + if (fd == AEFILNF && m & O_CREAT) + fd = Fcreate(name, 0); + } + if (fd < 0) + errno = (int)fd; + if (fd < 0) { + TIFFError(module, "%s: Cannot open", name); + return ((TIFF*)0); + } + return (TIFFFdOpen(fd, name, mode)); +} + +#include <stdlib.h> + +tdata_t +_TIFFmalloc(tsize_t s) +{ + return (malloc((size_t) s)); +} + +void +_TIFFfree(tdata_t p) +{ + free(p); +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + return (realloc(p, (size_t) s)); +} + +void +_TIFFmemset(tdata_t p, int v, size_t c) +{ + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, size_t c) +{ + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + return (memcmp(p1, p2, (size_t) c)); +} + +static void +atariWarningHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFwarningHandler = atariWarningHandler; + +static void +atariErrorHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFerrorHandler = atariErrorHandler; diff --git a/Utilities/vtktiff/tif_aux.c b/Utilities/vtktiff/tif_aux.c new file mode 100644 index 0000000..60e9061 --- /dev/null +++ b/Utilities/vtktiff/tif_aux.c @@ -0,0 +1,206 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_aux.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Auxiliary Support Routines. + */ +#include "tiffiop.h" + +#ifdef COLORIMETRY_SUPPORT +#include <math.h> + +static void +TIFFDefaultTransferFunction(TIFFDirectory* td) +{ + uint16 **tf = td->td_transferfunction; + long i, n = 1<<td->td_bitspersample; + + tf[0] = (uint16 *)_TIFFmalloc(n * sizeof (uint16)); + tf[0][0] = 0; + for (i = 1; i < n; i++) { + double t = (double)i/((double) n-1.); + tf[0][i] = (uint16)floor(65535.*pow(t, 2.2) + .5); + } + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + tf[1] = (uint16 *)_TIFFmalloc(n * sizeof (uint16)); + _TIFFmemcpy(tf[1], tf[0], n * sizeof (uint16)); + tf[2] = (uint16 *)_TIFFmalloc(n * sizeof (uint16)); + _TIFFmemcpy(tf[2], tf[0], n * sizeof (uint16)); + } +} + +static void +TIFFDefaultRefBlackWhite(TIFFDirectory* td) +{ + int i; + + td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)); + for (i = 0; i < 3; i++) { + td->td_refblackwhite[2*i+0] = 0; + td->td_refblackwhite[2*i+1] = (float)((1L<<td->td_bitspersample)-1L); + } +} +#endif + +/* + * Like TIFFGetField, but return any default + * value if the tag is not present in the directory. + * + * NB: We use the value in the directory, rather than + * explcit values so that defaults exist only one + * place in the library -- in TIFFDefaultDirectory. + */ +int +TIFFVGetFieldDefaulted(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (TIFFVGetField(tif, tag, ap)) + return (1); + switch (tag) { + case TIFFTAG_SUBFILETYPE: + *va_arg(ap, uint32 *) = td->td_subfiletype; + return (1); + case TIFFTAG_BITSPERSAMPLE: + *va_arg(ap, uint16 *) = td->td_bitspersample; + return (1); + case TIFFTAG_THRESHHOLDING: + *va_arg(ap, uint16 *) = td->td_threshholding; + return (1); + case TIFFTAG_FILLORDER: + *va_arg(ap, uint16 *) = td->td_fillorder; + return (1); + case TIFFTAG_ORIENTATION: + *va_arg(ap, uint16 *) = td->td_orientation; + return (1); + case TIFFTAG_SAMPLESPERPIXEL: + *va_arg(ap, uint16 *) = td->td_samplesperpixel; + return (1); + case TIFFTAG_ROWSPERSTRIP: + *va_arg(ap, uint32 *) = td->td_rowsperstrip; + return (1); + case TIFFTAG_MINSAMPLEVALUE: + *va_arg(ap, uint16 *) = td->td_minsamplevalue; + return (1); + case TIFFTAG_MAXSAMPLEVALUE: + *va_arg(ap, uint16 *) = td->td_maxsamplevalue; + return (1); + case TIFFTAG_PLANARCONFIG: + *va_arg(ap, uint16 *) = td->td_planarconfig; + return (1); + case TIFFTAG_RESOLUTIONUNIT: + *va_arg(ap, uint16 *) = td->td_resolutionunit; + return (1); +#ifdef CMYK_SUPPORT + case TIFFTAG_DOTRANGE: + *va_arg(ap, uint16 *) = 0; + *va_arg(ap, uint16 *) = (1<<td->td_bitspersample)-1; + return (1); + case TIFFTAG_INKSET: + *va_arg(ap, uint16 *) = td->td_inkset; + return (1); + case TIFFTAG_NUMBEROFINKS: + *va_arg(ap, uint16 *) = td->td_ninks; + return (1); +#endif + case TIFFTAG_EXTRASAMPLES: + *va_arg(ap, uint16 *) = td->td_extrasamples; + *va_arg(ap, uint16 **) = td->td_sampleinfo; + return (1); + case TIFFTAG_MATTEING: + *va_arg(ap, uint16 *) = + (td->td_extrasamples == 1 && + td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); + return (1); + case TIFFTAG_TILEDEPTH: + *va_arg(ap, uint32 *) = td->td_tiledepth; + return (1); + case TIFFTAG_DATATYPE: + *va_arg(ap, uint16 *) = td->td_sampleformat-1; + return (1); + case TIFFTAG_SAMPLEFORMAT: + *va_arg(ap, uint16 *) = td->td_sampleformat; + return(1); + case TIFFTAG_IMAGEDEPTH: + *va_arg(ap, uint32 *) = td->td_imagedepth; + return (1); +#ifdef YCBCR_SUPPORT + case TIFFTAG_YCBCRCOEFFICIENTS: + if (!td->td_ycbcrcoeffs) { + td->td_ycbcrcoeffs = (float *) + _TIFFmalloc(3*sizeof (float)); + /* defaults are from CCIR Recommendation 601-1 */ + td->td_ycbcrcoeffs[0] = 0.299f; + td->td_ycbcrcoeffs[1] = 0.587f; + td->td_ycbcrcoeffs[2] = 0.114f; + } + *va_arg(ap, float **) = td->td_ycbcrcoeffs; + return (1); + case TIFFTAG_YCBCRSUBSAMPLING: + *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0]; + *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1]; + return (1); + case TIFFTAG_YCBCRPOSITIONING: + *va_arg(ap, uint16 *) = td->td_ycbcrpositioning; + return (1); +#endif +#ifdef COLORIMETRY_SUPPORT + case TIFFTAG_TRANSFERFUNCTION: + if (!td->td_transferfunction[0]) + TIFFDefaultTransferFunction(td); + *va_arg(ap, uint16 **) = td->td_transferfunction[0]; + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + *va_arg(ap, uint16 **) = td->td_transferfunction[1]; + *va_arg(ap, uint16 **) = td->td_transferfunction[2]; + } + return (1); + case TIFFTAG_REFERENCEBLACKWHITE: + if (!td->td_refblackwhite) + TIFFDefaultRefBlackWhite(td); + *va_arg(ap, float **) = td->td_refblackwhite; + return (1); +#endif + } + return (0); +} + +/* + * Like TIFFGetField, but return any default + * value if the tag is not present in the directory. + */ +int +TIFFGetFieldDefaulted(TIFF* tif, ttag_t tag, ...) +{ + int ok; + va_list ap; + + va_start(ap, tag); + ok = TIFFVGetFieldDefaulted(tif, tag, ap); + va_end(ap); + return (ok); +} diff --git a/Utilities/vtktiff/tif_close.c b/Utilities/vtktiff/tif_close.c new file mode 100644 index 0000000..875f8db --- /dev/null +++ b/Utilities/vtktiff/tif_close.c @@ -0,0 +1,50 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_close.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +void +TEXPORT TIFFClose(TIFF* tif) +{ + if (tif->tif_mode != O_RDONLY) + /* + * Flush buffered data and directory (if dirty). + */ + TIFFFlush(tif); + (*tif->tif_cleanup)(tif); + TIFFFreeDirectory(tif); + if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER)) + _TIFFfree(tif->tif_rawdata); + if (isMapped(tif)) + TIFFUnmapFileContents(tif, tif->tif_base, tif->tif_size); + (void) TIFFCloseFile(tif); + if (tif->tif_fieldinfo) + _TIFFfree(tif->tif_fieldinfo); + _TIFFfree(tif); +} diff --git a/Utilities/vtktiff/tif_codec.c b/Utilities/vtktiff/tif_codec.c new file mode 100644 index 0000000..6bea9c5 --- /dev/null +++ b/Utilities/vtktiff/tif_codec.c @@ -0,0 +1,118 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_codec.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library + * + * Builtin Compression Scheme Configuration Support. + */ +#include "tiffiop.h" + +static int NotConfigured(TIFF*, int); + +#ifndef LZW_SUPPORT +#define TIFFInitLZW NotConfigured +#endif +#ifndef PACKBITS_SUPPORT +#define TIFFInitPackbits NotConfigured +#endif +#ifndef THUNDER_SUPPORT +#define TIFFInitThunderScan NotConfigured +#endif +#ifndef NEXT_SUPPORT +#define TIFFInitNeXT NotConfigured +#endif +#ifndef JPEG_SUPPORT +#define TIFFInitJPEG NotConfigured +#endif +#ifndef OJPEG_SUPPORT +#define TIFFInitOJPEG NotConfigured +#endif +#ifndef CCITT_SUPPORT +#define TIFFInitCCITTRLE NotConfigured +#define TIFFInitCCITTRLEW NotConfigured +#define TIFFInitCCITTFax3 NotConfigured +#define TIFFInitCCITTFax4 NotConfigured +#endif +#ifndef JBIG_SUPPORT +#define TIFFInitJBIG NotConfigured +#endif +#ifndef ZIP_SUPPORT +#define TIFFInitZIP NotConfigured +#endif +#ifndef PIXARLOG_SUPPORT +#define TIFFInitPixarLog NotConfigured +#endif +#ifndef LOGLUV_SUPPORT +#define TIFFInitSGILog NotConfigured +#endif + +/* + * Compression schemes statically built into the library. + */ +#ifdef VMS +const TIFFCodec _TIFFBuiltinCODECS[] = { +#else +TIFFCodec _TIFFBuiltinCODECS[] = { +#endif + { "None", COMPRESSION_NONE, TIFFInitDumpMode }, + { "LZW", COMPRESSION_LZW, TIFFInitLZW }, + { "PackBits", COMPRESSION_PACKBITS, TIFFInitPackBits }, + { "ThunderScan", COMPRESSION_THUNDERSCAN,TIFFInitThunderScan }, + { "NeXT", COMPRESSION_NEXT, TIFFInitNeXT }, + { "JPEG", COMPRESSION_JPEG, TIFFInitJPEG }, + { "Old-style JPEG", COMPRESSION_OJPEG, TIFFInitOJPEG }, + { "CCITT RLE", COMPRESSION_CCITTRLE, TIFFInitCCITTRLE }, + { "CCITT RLE/W", COMPRESSION_CCITTRLEW, TIFFInitCCITTRLEW }, + { "CCITT Group 3", COMPRESSION_CCITTFAX3, TIFFInitCCITTFax3 }, + { "CCITT Group 4", COMPRESSION_CCITTFAX4, TIFFInitCCITTFax4 }, + { "ISO JBIG", COMPRESSION_JBIG, TIFFInitJBIG }, + { "Deflate", COMPRESSION_DEFLATE, TIFFInitZIP }, + { "AdobeDeflate", COMPRESSION_ADOBE_DEFLATE , TIFFInitZIP }, + { "PixarLog", COMPRESSION_PIXARLOG, TIFFInitPixarLog }, + { "SGILog", COMPRESSION_SGILOG, TIFFInitSGILog }, + { "SGILog24", COMPRESSION_SGILOG24, TIFFInitSGILog }, + { NULL, 0, 0 } +}; + +static int +_notConfigured(TIFF* tif) +{ + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + + TIFFError(tif->tif_name, + "%s compression support is not configured", c->name); + return (0); +} + +static int +NotConfigured(TIFF* tif, int scheme) +{ + scheme = 0; + tif->tif_setupdecode = _notConfigured; + tif->tif_setupencode = _notConfigured; + return (1); +} diff --git a/Utilities/vtktiff/tif_compress.c b/Utilities/vtktiff/tif_compress.c new file mode 100644 index 0000000..11d588d --- /dev/null +++ b/Utilities/vtktiff/tif_compress.c @@ -0,0 +1,231 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_compress.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library + * + * Compression Scheme Configuration Support. + */ +#include "tiffiop.h" + +static int +TIFFNoEncode(TIFF* tif, char* method) +{ + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + + if (c) { + if (! strncmp(c->name, "LZW", 3) ){ + TIFFError(tif->tif_name, + "%s %s encoding is no longer implemented due to Unisys patent enforcement", + c->name, method); + } else { + TIFFError(tif->tif_name, "%s %s encoding is not implemented", + c->name, method); + } + } + else { + TIFFError(tif->tif_name, + "Compression scheme %u %s encoding is not implemented", + tif->tif_dir.td_compression, method); + } + return (-1); +} + +int +_TIFFNoRowEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "scanline")); +} + +int +_TIFFNoStripEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "strip")); +} + +int +_TIFFNoTileEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "tile")); +} + +static int +TIFFNoDecode(TIFF* tif, char* method) +{ + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + + if (c) + TIFFError(tif->tif_name, "%s %s decoding is not implemented", + c->name, method); + else + TIFFError(tif->tif_name, + "Compression scheme %u %s decoding is not implemented", + tif->tif_dir.td_compression, method); + return (-1); +} + +int +_TIFFNoRowDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "scanline")); +} + +int +_TIFFNoStripDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "strip")); +} + +int +_TIFFNoTileDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "tile")); +} + +int +_TIFFNoSeek(TIFF* tif, uint32 off) +{ + (void) off; + TIFFError(tif->tif_name, + "Compression algorithm does not support random access"); + return (0); +} + +int +_TIFFNoPreCode(TIFF* tif, tsample_t s) +{ + (void) tif; (void) s; + return (1); +} + +static int _TIFFtrue(TIFF* tif) { (void) tif; return (1); } +static void _TIFFvoid(TIFF* tif) { (void) tif; } + +void +_TIFFSetDefaultCompressionState(TIFF* tif) +{ + tif->tif_setupdecode = _TIFFtrue; + tif->tif_predecode = _TIFFNoPreCode; + tif->tif_decoderow = _TIFFNoRowDecode; + tif->tif_decodestrip = _TIFFNoStripDecode; + tif->tif_decodetile = _TIFFNoTileDecode; + tif->tif_setupencode = _TIFFtrue; + tif->tif_preencode = _TIFFNoPreCode; + tif->tif_postencode = _TIFFtrue; + tif->tif_encoderow = _TIFFNoRowEncode; + tif->tif_encodestrip = _TIFFNoStripEncode; + tif->tif_encodetile = _TIFFNoTileEncode; + tif->tif_close = _TIFFvoid; + tif->tif_seek = _TIFFNoSeek; + tif->tif_cleanup = _TIFFvoid; + tif->tif_defstripsize = _TIFFDefaultStripSize; + tif->tif_deftilesize = _TIFFDefaultTileSize; + tif->tif_flags &= ~TIFF_NOBITREV; +} + +int +TIFFSetCompressionScheme(TIFF* tif, int scheme) +{ + const TIFFCodec *c = TIFFFindCODEC((uint16) scheme); + + _TIFFSetDefaultCompressionState(tif); + /* + * Don't treat an unknown compression scheme as an error. + * This permits applications to open files with data that + * the library does not have builtin support for, but which + * may still be meaningful. + */ + return (c ? (*c->init)(tif, scheme) : 1); +} + +/* + * Other compression schemes may be registered. Registered + * schemes can also override the builtin versions provided + * by this library. + */ +typedef struct _codec { + struct _codec* next; + TIFFCodec* info; +} codec_t; +static codec_t* registeredCODECS = NULL; + +const TIFFCodec* +TIFFFindCODEC(uint16 scheme) +{ + const TIFFCodec* c; + codec_t* cd; + + for (cd = registeredCODECS; cd; cd = cd->next) + if (cd->info->scheme == scheme) + return ((const TIFFCodec*) cd->info); + for (c = _TIFFBuiltinCODECS; c->name; c++) + if (c->scheme == scheme) + return (c); + return ((const TIFFCodec*) 0); +} + +TIFFCodec* +TIFFRegisterCODEC(uint16 scheme, const char* name, TIFFInitMethod init) +{ + codec_t* cd = (codec_t*) + _TIFFmalloc(sizeof (codec_t) + sizeof (TIFFCodec) + strlen(name)+1); + + if (cd != NULL) { + cd->info = (TIFFCodec*) ((tidata_t) cd + sizeof (codec_t)); + cd->info->name = (char*) + ((tidata_t) cd->info + sizeof (TIFFCodec)); + strcpy(cd->info->name, name); + cd->info->scheme = scheme; + cd->info->init = init; + cd->next = registeredCODECS; + registeredCODECS = cd; + } else + TIFFError("TIFFRegisterCODEC", + "No space to register compression scheme %s", name); + return (cd->info); +} + +void +TIFFUnRegisterCODEC(TIFFCodec* c) +{ + codec_t* cd; + codec_t** pcd; + + for (pcd = ®isteredCODECS; (cd = *pcd); pcd = &cd->next) + if (cd->info == c) { + *pcd = cd->next; + _TIFFfree(cd); + return; + } + TIFFError("TIFFUnRegisterCODEC", + "Cannot remove compression scheme %s; not registered", c->name); +} diff --git a/Utilities/vtktiff/tif_dir.c b/Utilities/vtktiff/tif_dir.c new file mode 100644 index 0000000..3605a53 --- /dev/null +++ b/Utilities/vtktiff/tif_dir.c @@ -0,0 +1,1324 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_dir.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Tag Get & Set Routines. + * (and also some miscellaneous stuff) + */ +#include "tiffiop.h" + +/* + * These are used in the backwards compatibility code... + */ +#define DATATYPE_VOID 0 /* !untyped data */ +#define DATATYPE_INT 1 /* !signed integer data */ +#define DATATYPE_UINT 2 /* !unsigned integer data */ +#define DATATYPE_IEEEFP 3 /* !IEEE floating point data */ + +void +_TIFFsetByteArray(void** vpp, void* vp, long n) +{ + if (*vpp) + _TIFFfree(*vpp), *vpp = 0; + if (vp && (*vpp = (void*) _TIFFmalloc(n))) + _TIFFmemcpy(*vpp, vp, n); +} +void _TIFFsetString(char** cpp, char* cp) + { _TIFFsetByteArray((void**) cpp, (void*) cp, (long) (strlen(cp)+1)); } +void _TIFFsetNString(char** cpp, char* cp, long n) + { _TIFFsetByteArray((void**) cpp, (void*) cp, n); } +void _TIFFsetShortArray(uint16** wpp, uint16* wp, long n) + { _TIFFsetByteArray((void**) wpp, (void*) wp, n*sizeof (uint16)); } +void _TIFFsetLongArray(uint32** lpp, uint32* lp, long n) + { _TIFFsetByteArray((void**) lpp, (void*) lp, n*sizeof (uint32)); } +void _TIFFsetFloatArray(float** fpp, float* fp, long n) + { _TIFFsetByteArray((void**) fpp, (void*) fp, n*sizeof (float)); } +void _TIFFsetDoubleArray(double** dpp, double* dp, long n) + { _TIFFsetByteArray((void**) dpp, (void*) dp, n*sizeof (double)); } + +/* + * Install extra samples information. + */ +static int +setExtraSamples(TIFFDirectory* td, va_list ap, int* v) +{ + uint16* va; + int i; + + *v = va_arg(ap, int); + if ((uint16) *v > td->td_samplesperpixel) + return (0); + va = va_arg(ap, uint16*); + if (*v > 0 && va == NULL) /* typically missing param */ + return (0); + for (i = 0; i < *v; i++) + if (va[i] > EXTRASAMPLE_UNASSALPHA) + return (0); + td->td_extrasamples = (uint16) *v; + _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); + return (1); +} + +#ifdef CMYK_SUPPORT +static int +checkInkNamesString(TIFF* tif, int slen, const char* s) +{ + TIFFDirectory* td = &tif->tif_dir; + int i = td->td_samplesperpixel; + + if (slen > 0) { + const char* ep = s+slen; + const char* cp = s; + for (; i > 0; i--) { + for (; *cp != '\0'; cp++) + if (cp >= ep) + goto bad; + cp++; /* skip \0 */ + } + return (cp-s); + } +bad: + TIFFError("TIFFSetField", + "%s: Invalid InkNames value; expecting %d names, found %d", + tif->tif_name, + td->td_samplesperpixel, + td->td_samplesperpixel-i); + return (0); +} +#endif + +static int +_TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFDirectory* td = &tif->tif_dir; + int status = 1; + uint32 v32; + int i, v; + double d; + char* s; + + switch (tag) { + case TIFFTAG_SUBFILETYPE: + td->td_subfiletype = va_arg(ap, uint32); + break; + case TIFFTAG_IMAGEWIDTH: + td->td_imagewidth = va_arg(ap, uint32); + break; + case TIFFTAG_IMAGELENGTH: + td->td_imagelength = va_arg(ap, uint32); + break; + case TIFFTAG_BITSPERSAMPLE: + td->td_bitspersample = (uint16) va_arg(ap, int); + /* + * If the data require post-decoding processing + * to byte-swap samples, set it up here. Note + * that since tags are required to be ordered, + * compression code can override this behaviour + * in the setup method if it wants to roll the + * post decoding work in with its normal work. + */ + if (tif->tif_flags & TIFF_SWAB) { + if (td->td_bitspersample == 16) + tif->tif_postdecode = _TIFFSwab16BitData; + else if (td->td_bitspersample == 32) + tif->tif_postdecode = _TIFFSwab32BitData; + else if (td->td_bitspersample == 64) + tif->tif_postdecode = _TIFFSwab64BitData; + } + break; + case TIFFTAG_COMPRESSION: + v = va_arg(ap, int) & 0xffff; + /* + * If we're changing the compression scheme, + * the notify the previous module so that it + * can cleanup any state it's setup. + */ + if (TIFFFieldSet(tif, FIELD_COMPRESSION)) { + if (td->td_compression == v) + break; + (*tif->tif_cleanup)(tif); + tif->tif_flags &= ~TIFF_CODERSETUP; + } + /* + * Setup new compression routine state. + */ + if( (status = TIFFSetCompressionScheme(tif, v)) != 0 ) + td->td_compression = v; + else + status = 0; + break; + case TIFFTAG_PHOTOMETRIC: + td->td_photometric = (uint16) va_arg(ap, int); + break; + case TIFFTAG_THRESHHOLDING: + td->td_threshholding = (uint16) va_arg(ap, int); + break; + case TIFFTAG_FILLORDER: + v = va_arg(ap, int); + if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB) + goto badvalue; + td->td_fillorder = (uint16) v; + break; + case TIFFTAG_DOCUMENTNAME: + _TIFFsetString(&td->td_documentname, va_arg(ap, char*)); + break; + case TIFFTAG_ARTIST: + _TIFFsetString(&td->td_artist, va_arg(ap, char*)); + break; + case TIFFTAG_DATETIME: + _TIFFsetString(&td->td_datetime, va_arg(ap, char*)); + break; + case TIFFTAG_HOSTCOMPUTER: + _TIFFsetString(&td->td_hostcomputer, va_arg(ap, char*)); + break; + case TIFFTAG_IMAGEDESCRIPTION: + _TIFFsetString(&td->td_imagedescription, va_arg(ap, char*)); + break; + case TIFFTAG_MAKE: + _TIFFsetString(&td->td_make, va_arg(ap, char*)); + break; + case TIFFTAG_MODEL: + _TIFFsetString(&td->td_model, va_arg(ap, char*)); + break; + case TIFFTAG_SOFTWARE: + _TIFFsetString(&td->td_software, va_arg(ap, char*)); + break; + case TIFFTAG_COPYRIGHT: + _TIFFsetString(&td->td_copyright, va_arg(ap, char*)); + break; + case TIFFTAG_ORIENTATION: + v = va_arg(ap, int); + if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v) { + TIFFWarning(tif->tif_name, + "Bad value %ld for \"%s\" tag ignored", + v, _TIFFFieldWithTag(tif, tag)->field_name); + } else + td->td_orientation = (uint16) v; + break; + case TIFFTAG_SAMPLESPERPIXEL: + /* XXX should cross check -- e.g. if pallette, then 1 */ + v = va_arg(ap, int); + if (v == 0) + goto badvalue; + td->td_samplesperpixel = (uint16) v; + break; + case TIFFTAG_ROWSPERSTRIP: + v32 = va_arg(ap, uint32); + if (v32 == 0) + goto badvalue32; + td->td_rowsperstrip = v32; + if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { + td->td_tilelength = v32; + td->td_tilewidth = td->td_imagewidth; + } + break; + case TIFFTAG_MINSAMPLEVALUE: + td->td_minsamplevalue = (uint16) va_arg(ap, int); + break; + case TIFFTAG_MAXSAMPLEVALUE: + td->td_maxsamplevalue = (uint16) va_arg(ap, int); + break; + case TIFFTAG_SMINSAMPLEVALUE: + td->td_sminsamplevalue = (double) va_arg(ap, dblparam_t); + break; + case TIFFTAG_SMAXSAMPLEVALUE: + td->td_smaxsamplevalue = (double) va_arg(ap, dblparam_t); + break; + case TIFFTAG_XRESOLUTION: + td->td_xresolution = (float) va_arg(ap, dblparam_t); + break; + case TIFFTAG_YRESOLUTION: + td->td_yresolution = (float) va_arg(ap, dblparam_t); + break; + case TIFFTAG_PLANARCONFIG: + v = va_arg(ap, int); + if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE) + goto badvalue; + td->td_planarconfig = (uint16) v; + break; + case TIFFTAG_PAGENAME: + _TIFFsetString(&td->td_pagename, va_arg(ap, char*)); + break; + case TIFFTAG_XPOSITION: + td->td_xposition = (float) va_arg(ap, dblparam_t); + break; + case TIFFTAG_YPOSITION: + td->td_yposition = (float) va_arg(ap, dblparam_t); + break; + case TIFFTAG_RESOLUTIONUNIT: + v = va_arg(ap, int); + if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v) + goto badvalue; + td->td_resolutionunit = (uint16) v; + break; + case TIFFTAG_PAGENUMBER: + td->td_pagenumber[0] = (uint16) va_arg(ap, int); + td->td_pagenumber[1] = (uint16) va_arg(ap, int); + break; + case TIFFTAG_HALFTONEHINTS: + td->td_halftonehints[0] = (uint16) va_arg(ap, int); + td->td_halftonehints[1] = (uint16) va_arg(ap, int); + break; + case TIFFTAG_COLORMAP: + v32 = (uint32)(1L<<td->td_bitspersample); + _TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16*), v32); + _TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16*), v32); + _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32); + break; + case TIFFTAG_EXTRASAMPLES: + if (!setExtraSamples(td, ap, &v)) + goto badvalue; + break; + case TIFFTAG_MATTEING: + td->td_extrasamples = (uint16) (va_arg(ap, int) != 0); + if (td->td_extrasamples) { + uint16 sv = EXTRASAMPLE_ASSOCALPHA; + _TIFFsetShortArray(&td->td_sampleinfo, &sv, 1); + } + break; + case TIFFTAG_TILEWIDTH: + v32 = va_arg(ap, uint32); + if (v32 % 16) { + if (tif->tif_mode != O_RDONLY) + goto badvalue32; + TIFFWarning(tif->tif_name, + "Nonstandard tile width %d, convert file", v32); + } + td->td_tilewidth = v32; + tif->tif_flags |= TIFF_ISTILED; + break; + case TIFFTAG_TILELENGTH: + v32 = va_arg(ap, uint32); + if (v32 % 16) { + if (tif->tif_mode != O_RDONLY) + goto badvalue32; + TIFFWarning(tif->tif_name, + "Nonstandard tile length %d, convert file", v32); + } + td->td_tilelength = v32; + tif->tif_flags |= TIFF_ISTILED; + break; + case TIFFTAG_TILEDEPTH: + v32 = va_arg(ap, uint32); + if (v32 == 0) + goto badvalue32; + td->td_tiledepth = v32; + break; + case TIFFTAG_DATATYPE: + v = va_arg(ap, int); + switch (v) { + case DATATYPE_VOID: v = SAMPLEFORMAT_VOID; break; + case DATATYPE_INT: v = SAMPLEFORMAT_INT; break; + case DATATYPE_UINT: v = SAMPLEFORMAT_UINT; break; + case DATATYPE_IEEEFP: v = SAMPLEFORMAT_IEEEFP;break; + default: goto badvalue; + } + td->td_sampleformat = (uint16) v; + break; + case TIFFTAG_SAMPLEFORMAT: + v = va_arg(ap, int); + if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v) + goto badvalue; + td->td_sampleformat = (uint16) v; + break; + case TIFFTAG_IMAGEDEPTH: + td->td_imagedepth = va_arg(ap, uint32); + break; + case TIFFTAG_STONITS: + d = va_arg(ap, dblparam_t); + if (d <= 0.) + goto badvaluedbl; + td->td_stonits = d; + break; + + /* Begin Pixar Tags */ + case TIFFTAG_PIXAR_IMAGEFULLWIDTH: + td->td_imagefullwidth = va_arg(ap, uint32); + break; + case TIFFTAG_PIXAR_IMAGEFULLLENGTH: + td->td_imagefulllength = va_arg(ap, uint32); + break; + case TIFFTAG_PIXAR_TEXTUREFORMAT: + _TIFFsetString(&td->td_textureformat, va_arg(ap, char*)); + break; + case TIFFTAG_PIXAR_WRAPMODES: + _TIFFsetString(&td->td_wrapmodes, va_arg(ap, char*)); + break; + case TIFFTAG_PIXAR_FOVCOT: + td->td_fovcot = (float) va_arg(ap, dblparam_t); + break; + case TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN: + _TIFFsetFloatArray(&td->td_matrixWorldToScreen, + va_arg(ap, float*), 16); + break; + case TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA: + _TIFFsetFloatArray(&td->td_matrixWorldToCamera, + va_arg(ap, float*), 16); + break; + /* End Pixar Tags */ + +#if SUBIFD_SUPPORT + case TIFFTAG_SUBIFD: + if ((tif->tif_flags & TIFF_INSUBIFD) == 0) { + td->td_nsubifd = (uint16) va_arg(ap, int); + _TIFFsetLongArray(&td->td_subifd, va_arg(ap, uint32*), + (long) td->td_nsubifd); + } else { + TIFFError(tif->tif_name, "Sorry, cannot nest SubIFDs"); + status = 0; + } + break; +#endif +#ifdef YCBCR_SUPPORT + case TIFFTAG_YCBCRCOEFFICIENTS: + _TIFFsetFloatArray(&td->td_ycbcrcoeffs, va_arg(ap, float*), 3); + break; + case TIFFTAG_YCBCRPOSITIONING: + td->td_ycbcrpositioning = (uint16) va_arg(ap, int); + break; + case TIFFTAG_YCBCRSUBSAMPLING: + td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, int); + td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, int); + break; +#endif +#ifdef COLORIMETRY_SUPPORT + case TIFFTAG_WHITEPOINT: + _TIFFsetFloatArray(&td->td_whitepoint, va_arg(ap, float*), 2); + break; + case TIFFTAG_PRIMARYCHROMATICITIES: + _TIFFsetFloatArray(&td->td_primarychromas, va_arg(ap, float*), 6); + break; + case TIFFTAG_TRANSFERFUNCTION: + v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1; + for (i = 0; i < v; i++) + _TIFFsetShortArray(&td->td_transferfunction[i], + va_arg(ap, uint16*), 1L<<td->td_bitspersample); + break; + case TIFFTAG_REFERENCEBLACKWHITE: + /* XXX should check for null range */ + _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); + break; +#endif +#ifdef CMYK_SUPPORT + case TIFFTAG_INKSET: + td->td_inkset = (uint16) va_arg(ap, int); + break; + case TIFFTAG_DOTRANGE: + /* XXX should check for null range */ + td->td_dotrange[0] = (uint16) va_arg(ap, int); + td->td_dotrange[1] = (uint16) va_arg(ap, int); + break; + case TIFFTAG_INKNAMES: + i = va_arg(ap, int); + s = va_arg(ap, char*); + i = checkInkNamesString(tif, i, s); + status = i > 0; + if( i > 0 ) { + _TIFFsetNString(&td->td_inknames, s, i); + td->td_inknameslen = i; + } + break; + case TIFFTAG_NUMBEROFINKS: + td->td_ninks = (uint16) va_arg(ap, int); + break; + case TIFFTAG_TARGETPRINTER: + _TIFFsetString(&td->td_targetprinter, va_arg(ap, char*)); + break; +#endif +#ifdef ICC_SUPPORT + case TIFFTAG_ICCPROFILE: + td->td_profileLength = (uint32) va_arg(ap, uint32); + _TIFFsetByteArray(&td->td_profileData, va_arg(ap, void*), + td->td_profileLength); + break; +#endif +#ifdef PHOTOSHOP_SUPPORT + case TIFFTAG_PHOTOSHOP: + td->td_photoshopLength = (uint32) va_arg(ap, uint32); + _TIFFsetByteArray (&td->td_photoshopData, va_arg(ap, void*), + td->td_photoshopLength); + break; +#endif +#ifdef IPTC_SUPPORT + case TIFFTAG_RICHTIFFIPTC: + td->td_richtiffiptcLength = (uint32) va_arg(ap, uint32); +#ifdef PHOTOSHOP_SUPPORT + _TIFFsetLongArray ((uint32**)&td->td_richtiffiptcData, va_arg(ap, uint32*), + td->td_richtiffiptcLength); +#else + _TIFFsetByteArray (&td->td_photoshopData, va_arg(ap, void*), + td->td_photoshopLength); +#endif + break; +#endif + case TIFFTAG_CZ_LSMINFO: + td->td_cz_lsminfoLength = (uint32) va_arg(ap, uint32); + _TIFFsetByteArray (&td->td_cz_lsminfoData, va_arg(ap, void*), + td->td_cz_lsminfoLength); + break; + case TIFFTAG_UIC2TAG: + td->td_uic2tagLength = (uint32) va_arg(ap, uint32); + _TIFFsetLongArray (&td->td_uic2tagData, va_arg(ap, void*), + td->td_uic2tagLength*6); + break; + default: + /* + * This can happen if multiple images are open with + * different codecs which have private tags. The + * global tag information table may then have tags + * that are valid for one file but not the other. + * If the client tries to set a tag that is not valid + * for the image's codec then we'll arrive here. This + * happens, for example, when tiffcp is used to convert + * between compression schemes and codec-specific tags + * are blindly copied. + */ + TIFFError("TIFFSetField", + "%s: Invalid %stag \"%s\" (not supported by codec)", + tif->tif_name, isPseudoTag(tag) ? "pseduo-" : "", + _TIFFFieldWithTag(tif, tag)->field_name); + status = 0; + break; + } + if (status) { + TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit); + tif->tif_flags |= TIFF_DIRTYDIRECT; + } + va_end(ap); + return (status); +badvalue: + TIFFError(tif->tif_name, "%d: Bad value for \"%s\"", v, + _TIFFFieldWithTag(tif, tag)->field_name); + va_end(ap); + return (0); +badvalue32: + TIFFError(tif->tif_name, "%ld: Bad value for \"%s\"", v32, + _TIFFFieldWithTag(tif, tag)->field_name); + va_end(ap); + return (0); +badvaluedbl: + TIFFError(tif->tif_name, "%f: Bad value for \"%s\"", d, + _TIFFFieldWithTag(tif, tag)->field_name); + va_end(ap); + return (0); +} + +/* + * Return 1/0 according to whether or not + * it is permissible to set the tag's value. + * Note that we allow ImageLength to be changed + * so that we can append and extend to images. + * Any other tag may not be altered once writing + * has commenced, unless its value has no effect + * on the format of the data that is written. + */ +static int +OkToChangeTag(TIFF* tif, ttag_t tag) +{ + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + if (!fip) { /* unknown tag */ + TIFFError("TIFFSetField", "%s: Unknown %stag %u", + tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag); + return (0); + } + if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) && + !fip->field_oktochange) { + /* + * Consult info table to see if tag can be changed + * after we've started writing. We only allow changes + * to those tags that don't/shouldn't affect the + * compression and/or format of the data. + */ + TIFFError("TIFFSetField", + "%s: Cannot modify tag \"%s\" while writing", + tif->tif_name, fip->field_name); + return (0); + } + return (1); +} + +/* + * Record the value of a field in the + * internal directory structure. The + * field will be written to the file + * when/if the directory structure is + * updated. + */ +int +TIFFSetField(TIFF* tif, ttag_t tag, ...) +{ + va_list ap; + int status; + + va_start(ap, tag); + status = TIFFVSetField(tif, tag, ap); + va_end(ap); + return (status); +} + +/* + * Like TIFFSetField, but taking a varargs + * parameter list. This routine is useful + * for building higher-level interfaces on + * top of the library. + */ +int +TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + return OkToChangeTag(tif, tag) ? + (*tif->tif_vsetfield)(tif, tag, ap) : 0; +} + +static int +_TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFDirectory* td = &tif->tif_dir; + + switch (tag) { + case TIFFTAG_SUBFILETYPE: + *va_arg(ap, uint32*) = td->td_subfiletype; + break; + case TIFFTAG_IMAGEWIDTH: + *va_arg(ap, uint32*) = td->td_imagewidth; + break; + case TIFFTAG_IMAGELENGTH: + *va_arg(ap, uint32*) = td->td_imagelength; + break; + case TIFFTAG_BITSPERSAMPLE: + *va_arg(ap, uint16*) = td->td_bitspersample; + break; + case TIFFTAG_COMPRESSION: + *va_arg(ap, uint16*) = td->td_compression; + break; + case TIFFTAG_PHOTOMETRIC: + *va_arg(ap, uint16*) = td->td_photometric; + break; + case TIFFTAG_THRESHHOLDING: + *va_arg(ap, uint16*) = td->td_threshholding; + break; + case TIFFTAG_FILLORDER: + *va_arg(ap, uint16*) = td->td_fillorder; + break; + case TIFFTAG_DOCUMENTNAME: + *va_arg(ap, char**) = td->td_documentname; + break; + case TIFFTAG_ARTIST: + *va_arg(ap, char**) = td->td_artist; + break; + case TIFFTAG_DATETIME: + *va_arg(ap, char**) = td->td_datetime; + break; + case TIFFTAG_HOSTCOMPUTER: + *va_arg(ap, char**) = td->td_hostcomputer; + break; + case TIFFTAG_IMAGEDESCRIPTION: + *va_arg(ap, char**) = td->td_imagedescription; + break; + case TIFFTAG_MAKE: + *va_arg(ap, char**) = td->td_make; + break; + case TIFFTAG_MODEL: + *va_arg(ap, char**) = td->td_model; + break; + case TIFFTAG_SOFTWARE: + *va_arg(ap, char**) = td->td_software; + break; + case TIFFTAG_COPYRIGHT: + *va_arg(ap, char**) = td->td_copyright; + break; + case TIFFTAG_ORIENTATION: + *va_arg(ap, uint16*) = td->td_orientation; + break; + case TIFFTAG_SAMPLESPERPIXEL: + *va_arg(ap, uint16*) = td->td_samplesperpixel; + break; + case TIFFTAG_ROWSPERSTRIP: + *va_arg(ap, uint32*) = td->td_rowsperstrip; + break; + case TIFFTAG_MINSAMPLEVALUE: + *va_arg(ap, uint16*) = td->td_minsamplevalue; + break; + case TIFFTAG_MAXSAMPLEVALUE: + *va_arg(ap, uint16*) = td->td_maxsamplevalue; + break; + case TIFFTAG_SMINSAMPLEVALUE: + *va_arg(ap, double*) = td->td_sminsamplevalue; + break; + case TIFFTAG_SMAXSAMPLEVALUE: + *va_arg(ap, double*) = td->td_smaxsamplevalue; + break; + case TIFFTAG_XRESOLUTION: + *va_arg(ap, float*) = td->td_xresolution; + break; + case TIFFTAG_YRESOLUTION: + *va_arg(ap, float*) = td->td_yresolution; + break; + case TIFFTAG_PLANARCONFIG: + *va_arg(ap, uint16*) = td->td_planarconfig; + break; + case TIFFTAG_XPOSITION: + *va_arg(ap, float*) = td->td_xposition; + break; + case TIFFTAG_YPOSITION: + *va_arg(ap, float*) = td->td_yposition; + break; + case TIFFTAG_PAGENAME: + *va_arg(ap, char**) = td->td_pagename; + break; + case TIFFTAG_RESOLUTIONUNIT: + *va_arg(ap, uint16*) = td->td_resolutionunit; + break; + case TIFFTAG_PAGENUMBER: + *va_arg(ap, uint16*) = td->td_pagenumber[0]; + *va_arg(ap, uint16*) = td->td_pagenumber[1]; + break; + case TIFFTAG_HALFTONEHINTS: + *va_arg(ap, uint16*) = td->td_halftonehints[0]; + *va_arg(ap, uint16*) = td->td_halftonehints[1]; + break; + case TIFFTAG_COLORMAP: + *va_arg(ap, uint16**) = td->td_colormap[0]; + *va_arg(ap, uint16**) = td->td_colormap[1]; + *va_arg(ap, uint16**) = td->td_colormap[2]; + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_TILEOFFSETS: + *va_arg(ap, uint32**) = td->td_stripoffset; + break; + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEBYTECOUNTS: + *va_arg(ap, uint32**) = td->td_stripbytecount; + break; + case TIFFTAG_MATTEING: + *va_arg(ap, uint16*) = + (td->td_extrasamples == 1 && + td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); + break; + case TIFFTAG_EXTRASAMPLES: + *va_arg(ap, uint16*) = td->td_extrasamples; + *va_arg(ap, uint16**) = td->td_sampleinfo; + break; + case TIFFTAG_TILEWIDTH: + *va_arg(ap, uint32*) = td->td_tilewidth; + break; + case TIFFTAG_TILELENGTH: + *va_arg(ap, uint32*) = td->td_tilelength; + break; + case TIFFTAG_TILEDEPTH: + *va_arg(ap, uint32*) = td->td_tiledepth; + break; + case TIFFTAG_DATATYPE: + switch (td->td_sampleformat) { + case SAMPLEFORMAT_UINT: + *va_arg(ap, uint16*) = DATATYPE_UINT; + break; + case SAMPLEFORMAT_INT: + *va_arg(ap, uint16*) = DATATYPE_INT; + break; + case SAMPLEFORMAT_IEEEFP: + *va_arg(ap, uint16*) = DATATYPE_IEEEFP; + break; + case SAMPLEFORMAT_VOID: + *va_arg(ap, uint16*) = DATATYPE_VOID; + break; + } + break; + case TIFFTAG_SAMPLEFORMAT: + *va_arg(ap, uint16*) = td->td_sampleformat; + break; + case TIFFTAG_IMAGEDEPTH: + *va_arg(ap, uint32*) = td->td_imagedepth; + break; + case TIFFTAG_STONITS: + *va_arg(ap, double*) = td->td_stonits; + break; +#if SUBIFD_SUPPORT + case TIFFTAG_SUBIFD: + *va_arg(ap, uint16*) = td->td_nsubifd; + *va_arg(ap, uint32**) = td->td_subifd; + break; +#endif +#ifdef YCBCR_SUPPORT + case TIFFTAG_YCBCRCOEFFICIENTS: + *va_arg(ap, float**) = td->td_ycbcrcoeffs; + break; + case TIFFTAG_YCBCRPOSITIONING: + *va_arg(ap, uint16*) = td->td_ycbcrpositioning; + break; + case TIFFTAG_YCBCRSUBSAMPLING: + *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0]; + *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1]; + break; +#endif +#ifdef COLORIMETRY_SUPPORT + case TIFFTAG_WHITEPOINT: + *va_arg(ap, float**) = td->td_whitepoint; + break; + case TIFFTAG_PRIMARYCHROMATICITIES: + *va_arg(ap, float**) = td->td_primarychromas; + break; + case TIFFTAG_TRANSFERFUNCTION: + *va_arg(ap, uint16**) = td->td_transferfunction[0]; + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + *va_arg(ap, uint16**) = td->td_transferfunction[1]; + *va_arg(ap, uint16**) = td->td_transferfunction[2]; + } + break; + case TIFFTAG_REFERENCEBLACKWHITE: + *va_arg(ap, float**) = td->td_refblackwhite; + break; +#endif +#ifdef CMYK_SUPPORT + case TIFFTAG_INKSET: + *va_arg(ap, uint16*) = td->td_inkset; + break; + case TIFFTAG_DOTRANGE: + *va_arg(ap, uint16*) = td->td_dotrange[0]; + *va_arg(ap, uint16*) = td->td_dotrange[1]; + break; + case TIFFTAG_INKNAMES: + *va_arg(ap, char**) = td->td_inknames; + break; + case TIFFTAG_NUMBEROFINKS: + *va_arg(ap, uint16*) = td->td_ninks; + break; + case TIFFTAG_TARGETPRINTER: + *va_arg(ap, char**) = td->td_targetprinter; + break; +#endif +#ifdef ICC_SUPPORT + case TIFFTAG_ICCPROFILE: + *va_arg(ap, uint32*) = td->td_profileLength; + *va_arg(ap, void**) = td->td_profileData; + break; +#endif +#ifdef PHOTOSHOP_SUPPORT + case TIFFTAG_PHOTOSHOP: + *va_arg(ap, uint32*) = td->td_photoshopLength; + *va_arg(ap, void**) = td->td_photoshopData; + break; +#endif +#ifdef IPTC_SUPPORT + case TIFFTAG_RICHTIFFIPTC: + *va_arg(ap, uint32*) = td->td_richtiffiptcLength; + *va_arg(ap, void**) = td->td_richtiffiptcData; + break; +#endif + /* Begin Pixar Tags */ + case TIFFTAG_PIXAR_IMAGEFULLWIDTH: + *va_arg(ap, uint32*) = td->td_imagefullwidth; + break; + case TIFFTAG_PIXAR_IMAGEFULLLENGTH: + *va_arg(ap, uint32*) = td->td_imagefulllength; + break; + case TIFFTAG_PIXAR_TEXTUREFORMAT: + *va_arg(ap, char**) = td->td_textureformat; + break; + case TIFFTAG_PIXAR_WRAPMODES: + *va_arg(ap, char**) = td->td_wrapmodes; + break; + case TIFFTAG_PIXAR_FOVCOT: + *va_arg(ap, float*) = td->td_fovcot; + break; + case TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN: + *va_arg(ap, float**) = td->td_matrixWorldToScreen; + break; + case TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA: + *va_arg(ap, float**) = td->td_matrixWorldToCamera; + break; + /* End Pixar Tags */ + + case TIFFTAG_CZ_LSMINFO: + *va_arg(ap, uint32*) = td->td_cz_lsminfoLength; + *va_arg(ap, void**) = td->td_cz_lsminfoData; + break; + case TIFFTAG_UIC2TAG: + *va_arg(ap, uint32*) = td->td_uic2tagLength; + *va_arg(ap, uint32**) = td->td_uic2tagData; + break; + default: + /* + * This can happen if multiple images are open with + * different codecs which have private tags. The + * global tag information table may then have tags + * that are valid for one file but not the other. + * If the client tries to get a tag that is not valid + * for the image's codec then we'll arrive here. + */ + TIFFError("TIFFGetField", + "%s: Invalid %stag \"%s\" (not supported by codec)", + tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", + _TIFFFieldWithTag(tif, tag)->field_name); + break; + } + return (1); +} + +/* + * Return the value of a field in the + * internal directory structure. + */ +int +TEXPORT TIFFGetField(TIFF* tif, ttag_t tag, ...) +{ + int status; + va_list ap; + + va_start(ap, tag); + status = TIFFVGetField(tif, tag, ap); + va_end(ap); + return (status); +} + +/* + * Like TIFFGetField, but taking a varargs + * parameter list. This routine is useful + * for building higher-level interfaces on + * top of the library. + */ +int +TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ? + (*tif->tif_vgetfield)(tif, tag, ap) : 0); +} + +#define CleanupField(member) { \ + if (td->member) { \ + _TIFFfree(td->member); \ + td->member = 0; \ + } \ +} + +/* + * Release storage associated with a directory. + */ +void +TIFFFreeDirectory(TIFF* tif) +{ + register TIFFDirectory *td = &tif->tif_dir; + + CleanupField(td_colormap[0]); + CleanupField(td_colormap[1]); + CleanupField(td_colormap[2]); + CleanupField(td_documentname); + CleanupField(td_artist); + CleanupField(td_datetime); + CleanupField(td_hostcomputer); + CleanupField(td_imagedescription); + CleanupField(td_make); + CleanupField(td_model); + CleanupField(td_software); + CleanupField(td_copyright); + CleanupField(td_pagename); + CleanupField(td_sampleinfo); +#if SUBIFD_SUPPORT + CleanupField(td_subifd); +#endif +#ifdef YCBCR_SUPPORT + CleanupField(td_ycbcrcoeffs); +#endif +#ifdef CMYK_SUPPORT + CleanupField(td_inknames); + CleanupField(td_targetprinter); +#endif +#ifdef COLORIMETRY_SUPPORT + CleanupField(td_whitepoint); + CleanupField(td_primarychromas); + CleanupField(td_refblackwhite); + CleanupField(td_transferfunction[0]); + CleanupField(td_transferfunction[1]); + CleanupField(td_transferfunction[2]); +#endif +#ifdef ICC_SUPPORT + CleanupField(td_profileData); +#endif +#ifdef PHOTOSHOP_SUPPORT + CleanupField(td_photoshopData); +#endif +#ifdef IPTC_SUPPORT + CleanupField(td_richtiffiptcData); +#endif + CleanupField(td_cz_lsminfoData); + CleanupField(td_uic2tagData); + CleanupField(td_stripoffset); + CleanupField(td_stripbytecount); + /* Begin Pixar Tags */ + CleanupField(td_textureformat); + CleanupField(td_wrapmodes); + CleanupField(td_matrixWorldToScreen); + CleanupField(td_matrixWorldToCamera); + /* End Pixar Tags */ +} +#undef CleanupField + +/* + * Client Tag extension support (from Niles Ritter). + */ +static TIFFExtendProc _TIFFextender = (TIFFExtendProc) NULL; + +TIFFExtendProc +TIFFSetTagExtender(TIFFExtendProc extender) +{ + TIFFExtendProc prev = _TIFFextender; + _TIFFextender = extender; + return (prev); +} + +/* + * Setup for a new directory. Should we automatically call + * TIFFWriteDirectory() if the current one is dirty? + * + * The newly created directory will not exist on the file till + * TIFFWriteDirectory(), TIFFFlush() or TIFFClose() is called. + */ +int +TIFFCreateDirectory(TIFF* tif) +{ + TIFFDefaultDirectory(tif); + tif->tif_diroff = 0; + tif->tif_nextdiroff = 0; + tif->tif_curoff = 0; + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (tstrip_t) -1; + + return 0; +} + +/* + * Setup a default directory structure. + */ +int +TIFFDefaultDirectory(TIFF* tif) +{ + register TIFFDirectory* td = &tif->tif_dir; + + _TIFFSetupFieldInfo(tif); + _TIFFmemset(td, 0, sizeof (*td)); + td->td_fillorder = FILLORDER_MSB2LSB; + td->td_bitspersample = 1; + td->td_threshholding = THRESHHOLD_BILEVEL; + td->td_orientation = ORIENTATION_TOPLEFT; + td->td_samplesperpixel = 1; + td->td_rowsperstrip = (uint32) -1; + td->td_tilewidth = (uint32) -1; + td->td_tilelength = (uint32) -1; + td->td_tiledepth = 1; + td->td_resolutionunit = RESUNIT_INCH; + td->td_sampleformat = SAMPLEFORMAT_UINT; + td->td_imagedepth = 1; +#ifdef YCBCR_SUPPORT + td->td_ycbcrsubsampling[0] = 2; + td->td_ycbcrsubsampling[1] = 2; + td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED; +#endif +#ifdef CMYK_SUPPORT + td->td_inkset = INKSET_CMYK; + td->td_ninks = 4; +#endif + tif->tif_postdecode = _TIFFNoPostDecode; + tif->tif_vsetfield = _TIFFVSetField; + tif->tif_vgetfield = _TIFFVGetField; + tif->tif_printdir = NULL; + /* + * Give client code a chance to install their own + * tag extensions & methods, prior to compression overloads. + */ + if (_TIFFextender) + (*_TIFFextender)(tif); + (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + /* + * NB: The directory is marked dirty as a result of setting + * up the default compression scheme. However, this really + * isn't correct -- we want TIFF_DIRTYDIRECT to be set only + * if the user does something. We could just do the setup + * by hand, but it seems better to use the normal mechanism + * (i.e. TIFFSetField). + */ + tif->tif_flags &= ~TIFF_DIRTYDIRECT; + + /* + * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19 + * we clear the ISTILED flag when setting up a new directory. + * Should we also be clearing stuff like INSUBIFD? + */ + tif->tif_flags &= ~TIFF_ISTILED; + + return (1); +} + +static int +TIFFAdvanceDirectory(TIFF* tif, uint32* nextdir, toff_t* off) +{ + static const char module[] = "TIFFAdvanceDirectory"; + uint16 dircount; + if (isMapped(tif)) + { + toff_t poff=*nextdir; + if (poff+sizeof(uint16) > tif->tif_size) + { + TIFFError(module, "%s: Error fetching directory count", + tif->tif_name); + return (0); + } + _TIFFmemcpy(&dircount, tif->tif_base+poff, sizeof (uint16)); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + poff+=sizeof (uint16)+dircount*sizeof (TIFFDirEntry); + if (off != NULL) + *off = poff; + if (((toff_t) (poff+sizeof (uint32))) > tif->tif_size) + { + TIFFError(module, "%s: Error fetching directory link", + tif->tif_name); + return (0); + } + _TIFFmemcpy(nextdir, tif->tif_base+poff, sizeof (uint32)); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(nextdir); + return (1); + } + else + { + if (!SeekOK(tif, *nextdir) || + !ReadOK(tif, &dircount, sizeof (uint16))) { + TIFFError(module, "%s: Error fetching directory count", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + if (off != NULL) + *off = TIFFSeekFile(tif, + dircount*sizeof (TIFFDirEntry), SEEK_CUR); + else + (void) TIFFSeekFile(tif, + dircount*sizeof (TIFFDirEntry), SEEK_CUR); + if (!ReadOK(tif, nextdir, sizeof (uint32))) { + TIFFError(module, "%s: Error fetching directory link", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(nextdir); + return (1); + } +} + +/* + * Count the number of directories in a file. + */ +tdir_t +TIFFNumberOfDirectories(TIFF* tif) +{ + toff_t nextdir = tif->tif_header.tiff_diroff; + tdir_t n = 0; + + while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL)) + n++; + return (n); +} + +/* + * Set the n-th directory as the current directory. + * NB: Directories are numbered starting at 0. + */ +int +TIFFSetDirectory(TIFF* tif, tdir_t dirn) +{ + toff_t nextdir; + tdir_t n; + + nextdir = tif->tif_header.tiff_diroff; + for (n = dirn; n > 0 && nextdir != 0; n--) + if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) + return (0); + tif->tif_nextdiroff = nextdir; + /* + * Set curdir to the actual directory index. The + * -1 is because TIFFReadDirectory will increment + * tif_curdir after successfully reading the directory. + */ + tif->tif_curdir = (dirn - n) - 1; + return (TIFFReadDirectory(tif)); +} + +/* + * Set the current directory to be the directory + * located at the specified file offset. This interface + * is used mainly to access directories linked with + * the SubIFD tag (e.g. thumbnail images). + */ +int +TIFFSetSubDirectory(TIFF* tif, uint32 diroff) +{ + tif->tif_nextdiroff = diroff; + return (TIFFReadDirectory(tif)); +} + +/* + * Return file offset of the current directory. + */ +uint32 +TIFFCurrentDirOffset(TIFF* tif) +{ + return (tif->tif_diroff); +} + +/* + * Return an indication of whether or not we are + * at the last directory in the file. + */ +int +TIFFLastDirectory(TIFF* tif) +{ + return (tif->tif_nextdiroff == 0); +} + +/* + * Unlink the specified directory from the directory chain. + */ +int +TIFFUnlinkDirectory(TIFF* tif, tdir_t dirn) +{ + static const char module[] = "TIFFUnlinkDirectory"; + toff_t nextdir; + toff_t off; + tdir_t n; + + if (tif->tif_mode == O_RDONLY) { + TIFFError(module, "Can not unlink directory in read-only file"); + return (0); + } + /* + * Go to the directory before the one we want + * to unlink and nab the offset of the link + * field we'll need to patch. + */ + nextdir = tif->tif_header.tiff_diroff; + off = sizeof (uint16) + sizeof (uint16); + for (n = dirn-1; n > 0; n--) { + if (nextdir == 0) { + TIFFError(module, "Directory %d does not exist", dirn); + return (0); + } + if (!TIFFAdvanceDirectory(tif, &nextdir, &off)) + return (0); + } + /* + * Advance to the directory to be unlinked and fetch + * the offset of the directory that follows. + */ + if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) + return (0); + /* + * Go back and patch the link field of the preceding + * directory to point to the offset of the directory + * that follows. + */ + (void) TIFFSeekFile(tif, off, SEEK_SET); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir); + if (!WriteOK(tif, &nextdir, sizeof (uint32))) { + TIFFError(module, "Error writing directory link"); + return (0); + } + /* + * Leave directory state setup safely. We don't have + * facilities for doing inserting and removing directories, + * so it's safest to just invalidate everything. This + * means that the caller can only append to the directory + * chain. + */ + (*tif->tif_cleanup)(tif); + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawcc = 0; + } + tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE); + TIFFFreeDirectory(tif); + TIFFDefaultDirectory(tif); + tif->tif_diroff = 0; /* force link on next write */ + tif->tif_nextdiroff = 0; /* next write must be at end */ + tif->tif_curoff = 0; + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (tstrip_t) -1; + return (1); +} + +/* [BFC] + * + * Author: Bruce Cameron <cameron@petris.com> + * + * Set a table of tags that are to be replaced during directory process by the + * 'IGNORE' state - or return TRUE/FALSE for the requested tag such that + * 'ReadDirectory' can use the stored information. + */ +int +TIFFReassignTagToIgnore (enum TIFFIgnoreSense task, int TIFFtagID) +{ + static int TIFFignoretags [FIELD_LAST]; + static int tagcount = 0 ; + int i; /* Loop index */ + int j; /* Loop index */ + + switch (task) + { + case TIS_STORE: + if ( tagcount < (FIELD_LAST - 1) ) + { + for ( j = 0 ; j < tagcount ; ++j ) + { /* Do not add duplicate tag */ + if ( TIFFignoretags [j] == TIFFtagID ) + return (TRUE) ; + } + TIFFignoretags [tagcount++] = TIFFtagID ; + return (TRUE) ; + } + break ; + + case TIS_EXTRACT: + for ( i = 0 ; i < tagcount ; ++i ) + { + if ( TIFFignoretags [i] == TIFFtagID ) + return (TRUE) ; + } + break; + + case TIS_EMPTY: + tagcount = 0 ; /* Clear the list */ + return (TRUE) ; + + default: + break; + } + + return (FALSE); +} diff --git a/Utilities/vtktiff/tif_dir.h b/Utilities/vtktiff/tif_dir.h new file mode 100644 index 0000000..48897d8 --- /dev/null +++ b/Utilities/vtktiff/tif_dir.h @@ -0,0 +1,282 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_dir.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFDIR_ +#define _TIFFDIR_ +/* + * ``Library-private'' Directory-related Definitions. + */ + + +/* + * Internal format of a TIFF directory entry. + */ +typedef struct { +#define FIELD_SETLONGS 3 + /* bit vector of fields that are set */ + u_long td_fieldsset[FIELD_SETLONGS]; + + uint32 td_imagewidth, td_imagelength, td_imagedepth; + uint32 td_tilewidth, td_tilelength, td_tiledepth; + uint32 td_subfiletype; + uint16 td_bitspersample; + uint16 td_sampleformat; + uint16 td_compression; + uint16 td_photometric; + uint16 td_threshholding; + uint16 td_fillorder; + uint16 td_orientation; + uint16 td_samplesperpixel; + uint32 td_rowsperstrip; + uint16 td_minsamplevalue, td_maxsamplevalue; + double td_sminsamplevalue, td_smaxsamplevalue; + float td_xresolution, td_yresolution; + uint16 td_resolutionunit; + uint16 td_planarconfig; + float td_xposition, td_yposition; + uint16 td_pagenumber[2]; + uint16* td_colormap[3]; + uint16 td_halftonehints[2]; + uint16 td_extrasamples; + uint16* td_sampleinfo; + double td_stonits; + char* td_documentname; + char* td_artist; + char* td_datetime; + char* td_hostcomputer; + char* td_imagedescription; + char* td_make; + char* td_model; + char* td_software; + char* td_copyright; + char* td_pagename; + tstrip_t td_stripsperimage; + tstrip_t td_nstrips; /* size of offset & bytecount arrays */ + uint32* td_stripoffset; + uint32* td_stripbytecount; +#if SUBIFD_SUPPORT + uint16 td_nsubifd; + uint32* td_subifd; +#endif +#ifdef YCBCR_SUPPORT + float* td_ycbcrcoeffs; + uint16 td_ycbcrsubsampling[2]; + uint16 td_ycbcrpositioning; +#endif +#ifdef COLORIMETRY_SUPPORT + float* td_whitepoint; + float* td_primarychromas; + float* td_refblackwhite; + uint16* td_transferfunction[3]; +#endif +#ifdef CMYK_SUPPORT + uint16 td_inkset; + uint16 td_ninks; + uint16 td_dotrange[2]; + int td_inknameslen; + char* td_inknames; + char* td_targetprinter; +#endif +#ifdef ICC_SUPPORT + uint32 td_profileLength; + void *td_profileData; +#endif +#ifdef PHOTOSHOP_SUPPORT + uint32 td_photoshopLength; + void *td_photoshopData; +#endif +#ifdef IPTC_SUPPORT + uint32 td_richtiffiptcLength; + void *td_richtiffiptcData; +#endif + /* Begin Pixar Tag values. */ + uint32 td_imagefullwidth, td_imagefulllength; + char* td_textureformat; + char* td_wrapmodes; + float td_fovcot; + float* td_matrixWorldToScreen; + float* td_matrixWorldToCamera; + /* End Pixar Tag Values. */ + + /* zeiss data */ + uint32 td_cz_lsminfoLength; + void *td_cz_lsminfoData; + + /* uic data */ + uint32 td_uic2tagLength; + uint32 *td_uic2tagData; + +} TIFFDirectory; + +/* + * Field flags used to indicate fields that have + * been set in a directory, and to reference fields + * when manipulating a directory. + */ + +/* + * FIELD_IGNORE is used to signify tags that are to + * be processed but otherwise ignored. This permits + * antiquated tags to be quietly read and discarded. + * Note that a bit *is* allocated for ignored tags; + * this is understood by the directory reading logic + * which uses this fact to avoid special-case handling + */ +#define FIELD_IGNORE 0 + +/* multi-item fields */ +#define FIELD_IMAGEDIMENSIONS 1 +#define FIELD_TILEDIMENSIONS 2 +#define FIELD_RESOLUTION 3 +#define FIELD_POSITION 4 + +/* single-item fields */ +#define FIELD_SUBFILETYPE 5 +#define FIELD_BITSPERSAMPLE 6 +#define FIELD_COMPRESSION 7 +#define FIELD_PHOTOMETRIC 8 +#define FIELD_THRESHHOLDING 9 +#define FIELD_FILLORDER 10 +#define FIELD_DOCUMENTNAME 11 +#define FIELD_IMAGEDESCRIPTION 12 +#define FIELD_MAKE 13 +#define FIELD_MODEL 14 +#define FIELD_ORIENTATION 15 +#define FIELD_SAMPLESPERPIXEL 16 +#define FIELD_ROWSPERSTRIP 17 +#define FIELD_MINSAMPLEVALUE 18 +#define FIELD_MAXSAMPLEVALUE 19 +#define FIELD_PLANARCONFIG 20 +#define FIELD_PAGENAME 21 +#define FIELD_RESOLUTIONUNIT 22 +#define FIELD_PAGENUMBER 23 +#define FIELD_STRIPBYTECOUNTS 24 +#define FIELD_STRIPOFFSETS 25 +#define FIELD_COLORMAP 26 +#define FIELD_ARTIST 27 +#define FIELD_DATETIME 28 +#define FIELD_HOSTCOMPUTER 29 +#define FIELD_SOFTWARE 30 +#define FIELD_EXTRASAMPLES 31 +#define FIELD_SAMPLEFORMAT 32 +#define FIELD_SMINSAMPLEVALUE 33 +#define FIELD_SMAXSAMPLEVALUE 34 +#define FIELD_IMAGEDEPTH 35 +#define FIELD_TILEDEPTH 36 +#define FIELD_HALFTONEHINTS 37 +#define FIELD_YCBCRCOEFFICIENTS 38 +#define FIELD_YCBCRSUBSAMPLING 39 +#define FIELD_YCBCRPOSITIONING 40 +#define FIELD_REFBLACKWHITE 41 +#define FIELD_WHITEPOINT 42 +#define FIELD_PRIMARYCHROMAS 43 +#define FIELD_TRANSFERFUNCTION 44 +#define FIELD_INKSET 45 +#define FIELD_INKNAMES 46 +#define FIELD_DOTRANGE 47 +#define FIELD_TARGETPRINTER 48 +#define FIELD_SUBIFD 49 +#define FIELD_NUMBEROFINKS 50 +#define FIELD_ICCPROFILE 51 +#define FIELD_PHOTOSHOP 52 +#define FIELD_RICHTIFFIPTC 53 +#define FIELD_STONITS 54 +/* Begin PIXAR */ +#define FIELD_IMAGEFULLWIDTH 55 +#define FIELD_IMAGEFULLLENGTH 56 +#define FIELD_TEXTUREFORMAT 57 +#define FIELD_WRAPMODES 58 +#define FIELD_FOVCOT 59 +#define FIELD_MATRIX_WORLDTOSCREEN 60 +#define FIELD_MATRIX_WORLDTOCAMERA 61 +#define FIELD_COPYRIGHT 62 +#define FIELD_CZ_LSMINFO 63 +#define FIELD_UIC2TAG 64 +/* end of support for well-known tags; codec-private tags follow */ +#define FIELD_CODEC 65 /* base of codec-private tags */ +/* + * Pseudo-tags don't normally need field bits since they + * are not written to an output file (by definition). + * The library also has express logic to always query a + * codec for a pseudo-tag so allocating a field bit for + * one is a waste. If codec wants to promote the notion + * of a pseudo-tag being ``set'' or ``unset'' then it can + * do using internal state flags without polluting the + * field bit space defined for real tags. + */ +#define FIELD_PSEUDO 0 + +#define FIELD_LAST (32*FIELD_SETLONGS-1) + +#define TIFFExtractData(tif, type, v) \ + ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ + ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \ + (v) & (tif)->tif_typemask[type])) +#define TIFFInsertData(tif, type, v) \ + ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ + ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \ + (v) & (tif)->tif_typemask[type])) + +typedef struct { + ttag_t field_tag; /* field's tag */ + short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ + short field_writecount; /* write count/TIFF_VARIABLE */ + TIFFDataType field_type; /* type of associated data */ + u_short field_bit; /* bit in fieldsset bit vector */ + u_char field_oktochange; /* if true, can change while writing */ + u_char field_passcount; /* if true, pass dir count on set */ + char *field_name; /* ASCII name */ +} TIFFFieldInfo; + +#define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */ +#define TIFF_VARIABLE -1 /* marker for variable length tags */ +#define TIFF_SPP -2 /* marker for SamplesPerPixel tags */ +#define TIFF_VARIABLE2 -3 /* marker for uint32 var-length tags */ + +extern const int tiffDataWidth[]; /* table of tag datatype widths */ + +#define BITn(n) (((u_long)1L)<<((n)&0x1f)) +#define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n)/32]) +#define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field)) +#define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field)) +#define TIFFClrFieldBit(tif, field) (BITFIELDn(tif, field) &= ~BITn(field)) + +#define FieldSet(fields, f) (fields[(f)/32] & BITn(f)) +#define ResetFieldBit(fields, f) (fields[(f)/32] &= ~BITn(f)) + +#if defined(__cplusplus) +extern "C" { +#endif +extern void _TIFFSetupFieldInfo(TIFF*); +extern void _TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); +extern void _TIFFPrintFieldInfo(TIFF*, FILE*); +extern const TIFFFieldInfo* _TIFFFindFieldInfo(TIFF*, ttag_t, TIFFDataType); +extern const TIFFFieldInfo* _TIFFFieldWithTag(TIFF*, ttag_t); +extern TIFFDataType _TIFFSampleToTagType(TIFF*); +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFDIR_ */ diff --git a/Utilities/vtktiff/tif_dirinfo.c b/Utilities/vtktiff/tif_dirinfo.c new file mode 100644 index 0000000..7c3740b --- /dev/null +++ b/Utilities/vtktiff/tif_dirinfo.c @@ -0,0 +1,419 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_dirinfo.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Core Directory Tag Support. + */ +#include "tiffiop.h" +#include <stdlib.h> + +/* + * NB: NB: THIS ARRAY IS ASSUMED TO BE SORTED BY TAG. + * If a tag can have both LONG and SHORT types + * then the LONG must be placed before the SHORT for + * writing to work properly. + * + * NOTE: The second field (field_readcount) and third field (field_writecount) + * sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3) + * and TIFFTAG_SPP (-2). The macros should be used but would throw off + * the formatting of the code, so please interprete the -1, -2 and -3 + * values accordingly. + */ +#ifndef VMS +static +#endif +const TIFFFieldInfo tiffFieldInfo[] = { + { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, FIELD_SUBFILETYPE, + TRUE, FALSE, "SubfileType" }, +/* XXX SHORT for compatibility w/ old versions of the library */ + { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE, + TRUE, FALSE, "SubfileType" }, + { TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE, + TRUE, FALSE, "OldSubfileType" }, + { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS, + FALSE, FALSE, "ImageWidth" }, + { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS, + FALSE, FALSE, "ImageWidth" }, + { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS, + TRUE, FALSE, "ImageLength" }, + { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS, + TRUE, FALSE, "ImageLength" }, + { TIFFTAG_BITSPERSAMPLE, -1,-1, TIFF_SHORT, FIELD_BITSPERSAMPLE, + FALSE, FALSE, "BitsPerSample" }, + { TIFFTAG_COMPRESSION, -1, 1, TIFF_SHORT, FIELD_COMPRESSION, + FALSE, FALSE, "Compression" }, + { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, FIELD_PHOTOMETRIC, + FALSE, FALSE, "PhotometricInterpretation" }, + { TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, FIELD_THRESHHOLDING, + TRUE, FALSE, "Threshholding" }, + { TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, FIELD_IGNORE, + TRUE, FALSE, "CellWidth" }, + { TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, FIELD_IGNORE, + TRUE, FALSE, "CellLength" }, + { TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, FIELD_FILLORDER, + FALSE, FALSE, "FillOrder" }, + { TIFFTAG_DOCUMENTNAME, -1,-1, TIFF_ASCII, FIELD_DOCUMENTNAME, + TRUE, FALSE, "DocumentName" }, + { TIFFTAG_IMAGEDESCRIPTION, -1,-1, TIFF_ASCII, FIELD_IMAGEDESCRIPTION, + TRUE, FALSE, "ImageDescription" }, + { TIFFTAG_MAKE, -1,-1, TIFF_ASCII, FIELD_MAKE, + TRUE, FALSE, "Make" }, + { TIFFTAG_MODEL, -1,-1, TIFF_ASCII, FIELD_MODEL, + TRUE, FALSE, "Model" }, + { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_LONG, FIELD_STRIPOFFSETS, + FALSE, FALSE, "StripOffsets" }, + { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_SHORT, FIELD_STRIPOFFSETS, + FALSE, FALSE, "StripOffsets" }, + { TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, FIELD_ORIENTATION, + FALSE, FALSE, "Orientation" }, + { TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, FIELD_SAMPLESPERPIXEL, + FALSE, FALSE, "SamplesPerPixel" }, + { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, FIELD_ROWSPERSTRIP, + FALSE, FALSE, "RowsPerStrip" }, + { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_SHORT, FIELD_ROWSPERSTRIP, + FALSE, FALSE, "RowsPerStrip" }, + { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_STRIPBYTECOUNTS, + FALSE, FALSE, "StripByteCounts" }, + { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS, + FALSE, FALSE, "StripByteCounts" }, + { TIFFTAG_MINSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MINSAMPLEVALUE, + TRUE, FALSE, "MinSampleValue" }, + { TIFFTAG_MAXSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MAXSAMPLEVALUE, + TRUE, FALSE, "MaxSampleValue" }, + { TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION, + FALSE, FALSE, "XResolution" }, + { TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION, + FALSE, FALSE, "YResolution" }, + { TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, FIELD_PLANARCONFIG, + FALSE, FALSE, "PlanarConfiguration" }, + { TIFFTAG_PAGENAME, -1,-1, TIFF_ASCII, FIELD_PAGENAME, + TRUE, FALSE, "PageName" }, + { TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION, + TRUE, FALSE, "XPosition" }, + { TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION, + TRUE, FALSE, "YPosition" }, + { TIFFTAG_FREEOFFSETS, -1,-1, TIFF_LONG, FIELD_IGNORE, + FALSE, FALSE, "FreeOffsets" }, + { TIFFTAG_FREEBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_IGNORE, + FALSE, FALSE, "FreeByteCounts" }, + { TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE, + TRUE, FALSE, "GrayResponseUnit" }, + { TIFFTAG_GRAYRESPONSECURVE,-1,-1, TIFF_SHORT, FIELD_IGNORE, + TRUE, FALSE, "GrayResponseCurve" }, + { TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, FIELD_RESOLUTIONUNIT, + FALSE, FALSE, "ResolutionUnit" }, + { TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, FIELD_PAGENUMBER, + TRUE, FALSE, "PageNumber" }, + { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE, + TRUE, FALSE, "ColorResponseUnit" }, +#ifdef COLORIMETRY_SUPPORT + { TIFFTAG_TRANSFERFUNCTION, -1,-1, TIFF_SHORT, FIELD_TRANSFERFUNCTION, + TRUE, FALSE, "TransferFunction" }, +#endif + { TIFFTAG_SOFTWARE, -1,-1, TIFF_ASCII, FIELD_SOFTWARE, + TRUE, FALSE, "Software" }, + { TIFFTAG_DATETIME, 20,20, TIFF_ASCII, FIELD_DATETIME, + TRUE, FALSE, "DateTime" }, + { TIFFTAG_ARTIST, -1,-1, TIFF_ASCII, FIELD_ARTIST, + TRUE, FALSE, "Artist" }, + { TIFFTAG_HOSTCOMPUTER, -1,-1, TIFF_ASCII, FIELD_HOSTCOMPUTER, + TRUE, FALSE, "HostComputer" }, +#ifdef COLORIMETRY_SUPPORT + { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL,FIELD_WHITEPOINT, + TRUE, FALSE, "WhitePoint" }, + { TIFFTAG_PRIMARYCHROMATICITIES,6,6,TIFF_RATIONAL,FIELD_PRIMARYCHROMAS, + TRUE, FALSE, "PrimaryChromaticities" }, +#endif + { TIFFTAG_COLORMAP, -1,-1, TIFF_SHORT, FIELD_COLORMAP, + TRUE, FALSE, "ColorMap" }, + { TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, FIELD_HALFTONEHINTS, + TRUE, FALSE, "HalftoneHints" }, + { TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS, + FALSE, FALSE, "TileWidth" }, + { TIFFTAG_TILEWIDTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS, + FALSE, FALSE, "TileWidth" }, + { TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS, + FALSE, FALSE, "TileLength" }, + { TIFFTAG_TILELENGTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS, + FALSE, FALSE, "TileLength" }, + { TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG, FIELD_STRIPOFFSETS, + FALSE, FALSE, "TileOffsets" }, + { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG, FIELD_STRIPBYTECOUNTS, + FALSE, FALSE, "TileByteCounts" }, + { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS, + FALSE, FALSE, "TileByteCounts" }, +#ifdef TIFFTAG_SUBIFD + { TIFFTAG_SUBIFD, -1,-1, TIFF_LONG, FIELD_SUBIFD, + TRUE, TRUE, "SubIFD" }, +#endif +#ifdef CMYK_SUPPORT /* 6.0 CMYK tags */ + { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, FIELD_INKSET, + FALSE, FALSE, "InkSet" }, + { TIFFTAG_INKNAMES, -1,-1, TIFF_ASCII, FIELD_INKNAMES, + TRUE, TRUE, "InkNames" }, + { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, FIELD_NUMBEROFINKS, + TRUE, FALSE, "NumberOfInks" }, + { TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, FIELD_DOTRANGE, + FALSE, FALSE, "DotRange" }, + { TIFFTAG_DOTRANGE, 2, 2, TIFF_BYTE, FIELD_DOTRANGE, + FALSE, FALSE, "DotRange" }, + { TIFFTAG_TARGETPRINTER, -1,-1, TIFF_ASCII, FIELD_TARGETPRINTER, + TRUE, FALSE, "TargetPrinter" }, +#endif + { TIFFTAG_EXTRASAMPLES, -1,-1, TIFF_SHORT, FIELD_EXTRASAMPLES, + FALSE, FALSE, "ExtraSamples" }, +/* XXX for bogus Adobe Photoshop v2.5 files */ + { TIFFTAG_EXTRASAMPLES, -1,-1, TIFF_BYTE, FIELD_EXTRASAMPLES, + FALSE, FALSE, "ExtraSamples" }, + { TIFFTAG_SAMPLEFORMAT, -1,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT, + FALSE, FALSE, "SampleFormat" }, + { TIFFTAG_SMINSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMINSAMPLEVALUE, + TRUE, FALSE, "SMinSampleValue" }, + { TIFFTAG_SMAXSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMAXSAMPLEVALUE, + TRUE, FALSE, "SMaxSampleValue" }, +#ifdef YCBCR_SUPPORT /* 6.0 YCbCr tags */ + { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, FIELD_YCBCRCOEFFICIENTS, + FALSE, FALSE, "YCbCrCoefficients" }, + { TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, FIELD_YCBCRSUBSAMPLING, + FALSE, FALSE, "YCbCrSubsampling" }, + { TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, FIELD_YCBCRPOSITIONING, + FALSE, FALSE, "YCbCrPositioning" }, +#endif +#ifdef COLORIMETRY_SUPPORT + { TIFFTAG_REFERENCEBLACKWHITE,6,6,TIFF_RATIONAL, FIELD_REFBLACKWHITE, + TRUE, FALSE, "ReferenceBlackWhite" }, +/* XXX temporarily accept LONG for backwards compatibility */ + { TIFFTAG_REFERENCEBLACKWHITE,6,6,TIFF_LONG, FIELD_REFBLACKWHITE, + TRUE, FALSE, "ReferenceBlackWhite" }, +#endif +/* begin SGI tags */ + { TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, FIELD_EXTRASAMPLES, + FALSE, FALSE, "Matteing" }, + { TIFFTAG_DATATYPE, -2,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT, + FALSE, FALSE, "DataType" }, + { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, FIELD_IMAGEDEPTH, + FALSE, FALSE, "ImageDepth" }, + { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDEPTH, + FALSE, FALSE, "ImageDepth" }, + { TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, FIELD_TILEDEPTH, + FALSE, FALSE, "TileDepth" }, + { TIFFTAG_TILEDEPTH, 1, 1, TIFF_SHORT, FIELD_TILEDEPTH, + FALSE, FALSE, "TileDepth" }, +/* end SGI tags */ +/* begin Pixar tags */ + { TIFFTAG_PIXAR_IMAGEFULLWIDTH, 1, 1, TIFF_LONG, FIELD_IMAGEFULLWIDTH, + TRUE, FALSE, "ImageFullWidth" }, + { TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG, FIELD_IMAGEFULLLENGTH, + TRUE, FALSE, "ImageFullLength" }, + { TIFFTAG_PIXAR_TEXTUREFORMAT, -1,-1, TIFF_ASCII, FIELD_TEXTUREFORMAT, + TRUE, FALSE, "TextureFormat" }, + { TIFFTAG_PIXAR_WRAPMODES, -1,-1, TIFF_ASCII, FIELD_WRAPMODES, + TRUE, FALSE, "TextureWrapModes" }, + { TIFFTAG_PIXAR_FOVCOT, 1, 1, TIFF_FLOAT, FIELD_FOVCOT, + TRUE, FALSE, "FieldOfViewCotan" }, + { TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, 16,16, TIFF_FLOAT, + FIELD_MATRIX_WORLDTOSCREEN, TRUE, FALSE, "MatrixWorldToScreen" }, + { TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, 16,16, TIFF_FLOAT, + FIELD_MATRIX_WORLDTOCAMERA, TRUE, FALSE, "MatrixWorldToCamera" }, + { TIFFTAG_COPYRIGHT, -1,-1, TIFF_ASCII, FIELD_COPYRIGHT, + TRUE, FALSE, "Copyright" }, +/* end Pixar tags */ + + { TIFFTAG_UIC2TAG, -1,-3, TIFF_RATIONAL, FIELD_UIC2TAG, + FALSE, TRUE, "UIC2Tag" }, + +#ifdef IPTC_SUPPORT +#ifdef PHOTOSHOP_SUPPORT + { TIFFTAG_RICHTIFFIPTC, -1,-1, TIFF_LONG, FIELD_RICHTIFFIPTC, + FALSE, TRUE, "RichTIFFIPTC" }, +#else + { TIFFTAG_RICHTIFFIPTC, -1,-3, TIFF_UNDEFINED, FIELD_RICHTIFFIPTC, + FALSE, TRUE, "RichTIFFIPTC" }, +#endif +#endif + + { TIFFTAG_CZ_LSMINFO, -1,-3, TIFF_BYTE, FIELD_CZ_LSMINFO, + FALSE, TRUE, "LSM Info" }, + +#ifdef PHOTOSHOP_SUPPORT + { TIFFTAG_PHOTOSHOP, -1,-3, TIFF_BYTE, FIELD_PHOTOSHOP, + FALSE, TRUE, "Photoshop" }, +#endif +#ifdef ICC_SUPPORT + { TIFFTAG_ICCPROFILE, -1,-3, TIFF_UNDEFINED, FIELD_ICCPROFILE, + FALSE, TRUE, "ICC Profile" }, +#endif + { TIFFTAG_STONITS, 1, 1, TIFF_DOUBLE, FIELD_STONITS, + FALSE, FALSE, "StoNits" }, +}; +#define N(a) (sizeof (a) / sizeof (a[0])) + +void +_TIFFSetupFieldInfo(TIFF* tif) +{ + if (tif->tif_fieldinfo) { + _TIFFfree(tif->tif_fieldinfo); + tif->tif_nfields = 0; + } + _TIFFMergeFieldInfo(tif, tiffFieldInfo, N(tiffFieldInfo)); +} + +static int +tagCompare(const void* a, const void* b) +{ + const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a; + const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b; + /* NB: be careful of return values for 16-bit platforms */ + if (ta->field_tag != tb->field_tag) + return (ta->field_tag < tb->field_tag ? -1 : 1); + else + return (tb->field_type < ta->field_type ? -1 : 1); +} + +void +_TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n) +{ + TIFFFieldInfo** tp; + int i; + + if (tif->tif_nfields > 0) { + tif->tif_fieldinfo = (TIFFFieldInfo**) + _TIFFrealloc(tif->tif_fieldinfo, + (tif->tif_nfields+n) * sizeof (TIFFFieldInfo*)); + } else { + tif->tif_fieldinfo = (TIFFFieldInfo**) + _TIFFmalloc(n * sizeof (TIFFFieldInfo*)); + } + tp = &tif->tif_fieldinfo[tif->tif_nfields]; + for (i = 0; i < n; i++) + tp[i] = (TIFFFieldInfo*) &info[i]; /* XXX */ + /* + * NB: the core tags are presumed sorted correctly. + */ + if (tif->tif_nfields > 0) + qsort(tif->tif_fieldinfo, (size_t) (tif->tif_nfields += n), + sizeof (TIFFFieldInfo*), tagCompare); + else + tif->tif_nfields += n; +} + +void +_TIFFPrintFieldInfo(TIFF* tif, FILE* fd) +{ + int i; + + fprintf(fd, "%s: \n", tif->tif_name); + for (i = 0; i < tif->tif_nfields; i++) { + const TIFFFieldInfo* fip = tif->tif_fieldinfo[i]; + fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n" + , i + , (unsigned long) fip->field_tag + , fip->field_readcount, fip->field_writecount + , fip->field_type + , fip->field_bit + , fip->field_oktochange ? "TRUE" : "FALSE" + , fip->field_passcount ? "TRUE" : "FALSE" + , fip->field_name + ); + } +} + +const int tiffDataWidth[] = { + 1, /* nothing */ + 1, /* TIFF_BYTE */ + 1, /* TIFF_ASCII */ + 2, /* TIFF_SHORT */ + 4, /* TIFF_LONG */ + 8, /* TIFF_RATIONAL */ + 1, /* TIFF_SBYTE */ + 1, /* TIFF_UNDEFINED */ + 2, /* TIFF_SSHORT */ + 4, /* TIFF_SLONG */ + 8, /* TIFF_SRATIONAL */ + 4, /* TIFF_FLOAT */ + 8, /* TIFF_DOUBLE */ +}; + +/* + * Return nearest TIFFDataType to the sample type of an image. + */ +TIFFDataType +_TIFFSampleToTagType(TIFF* tif) +{ + int bps = (int) TIFFhowmany(tif->tif_dir.td_bitspersample, 8); + + switch (tif->tif_dir.td_sampleformat) { + case SAMPLEFORMAT_IEEEFP: + return (bps == 4 ? TIFF_FLOAT : TIFF_DOUBLE); + case SAMPLEFORMAT_INT: + return (bps <= 1 ? TIFF_SBYTE : + bps <= 2 ? TIFF_SSHORT : TIFF_SLONG); + case SAMPLEFORMAT_UINT: + return (bps <= 1 ? TIFF_BYTE : + bps <= 2 ? TIFF_SHORT : TIFF_LONG); + case SAMPLEFORMAT_VOID: + return (TIFF_UNDEFINED); + } + /*NOTREACHED*/ + return (TIFF_UNDEFINED); +} + +const TIFFFieldInfo* +_TIFFFindFieldInfo(TIFF* tif, ttag_t tag, TIFFDataType dt) +{ + static const TIFFFieldInfo *last = NULL; + int i, n; + + if (last && last->field_tag == tag && + (dt == TIFF_ANY || dt == last->field_type)) + return (last); + /* NB: if table gets big, use sorted search (e.g. binary search) */ + for (i = 0, n = tif->tif_nfields; i < n; i++) { + const TIFFFieldInfo* fip = tif->tif_fieldinfo[i]; + if (fip->field_tag == tag && + (dt == TIFF_ANY || fip->field_type == dt)) + return (last = fip); + } + return ((const TIFFFieldInfo *)0); +} + +#include <assert.h> +#include <stdio.h> + +const TIFFFieldInfo* +_TIFFFieldWithTag(TIFF* tif, ttag_t tag) +{ + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + if (!fip) { + TIFFError("TIFFFieldWithTag", + "Internal error, unknown tag 0x%x", (u_int) tag); + assert(fip != NULL); + /*NOTREACHED*/ + } + return (fip); +} diff --git a/Utilities/vtktiff/tif_dirread.c b/Utilities/vtktiff/tif_dirread.c new file mode 100644 index 0000000..90b0b59 --- /dev/null +++ b/Utilities/vtktiff/tif_dirread.c @@ -0,0 +1,1379 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_dirread.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Read Support Routines. + */ +#include "tiffiop.h" + +#define IGNORE 0 /* tag placeholder used below */ + +#if HAVE_IEEEFP +#define TIFFCvtIEEEFloatToNative(tif, n, fp) +#define TIFFCvtIEEEDoubleToNative(tif, n, dp) +#else +extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*); +extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*); +#endif + +static void EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16); +static void MissingRequired(TIFF*, const char*); +static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32); +static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*); +static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*); +static float TIFFFetchRational(TIFF*, TIFFDirEntry*); +static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*); +static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, int*); +static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*); +static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*); +static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**); +static int TIFFFetchExtraSamples(TIFF*, TIFFDirEntry*); +static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*); +static float TIFFFetchFloat(TIFF*, TIFFDirEntry*); +static int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*); +static int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*); +static int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*); +static int TIFFFetchShortPair(TIFF*, TIFFDirEntry*); +static void ChopUpSingleUncompressedStrip(TIFF*); + +static char * +CheckMalloc(TIFF* tif, tsize_t n, const char* what) +{ + char *cp = (char*)_TIFFmalloc(n); + if (cp == NULL) + TIFFError(tif->tif_name, "No space %s", what); + return (cp); +} + +/* + * Read the next TIFF directory from a file + * and convert it to the internal format. + * We read directories sequentially. + */ +int +TIFFReadDirectory(TIFF* tif) +{ + register TIFFDirEntry* dp; + register int n; + register TIFFDirectory* td; + TIFFDirEntry* dir; + int iv; + long v; + double dv; + const TIFFFieldInfo* fip; + int fix; + uint16 dircount; + toff_t nextdiroff; + char* cp; + int diroutoforderwarning = 0; + + tif->tif_diroff = tif->tif_nextdiroff; + if (tif->tif_diroff == 0) /* no more directories */ + return (0); + /* + * Cleanup any previous compression state. + */ + (*tif->tif_cleanup)(tif); + tif->tif_curdir++; + nextdiroff = 0; + if (!isMapped(tif)) { + if (!SeekOK(tif, tif->tif_diroff)) { + TIFFError(tif->tif_name, + "Seek error accessing TIFF directory"); + return (0); + } + if (!ReadOK(tif, &dircount, sizeof (uint16))) { + TIFFError(tif->tif_name, + "Can not read TIFF directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + dir = (TIFFDirEntry *)CheckMalloc(tif, + dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); + if (dir == NULL) + return (0); + if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) { + TIFFError(tif->tif_name, "Can not read TIFF directory"); + goto bad; + } + /* + * Read offset to next directory for sequential scans. + */ + (void) ReadOK(tif, &nextdiroff, sizeof (uint32)); + } else { + toff_t off = tif->tif_diroff; + + if (off + sizeof (uint16) > tif->tif_size) { + TIFFError(tif->tif_name, + "Can not read TIFF directory count"); + return (0); + } else + _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16)); + off += sizeof (uint16); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + dir = (TIFFDirEntry *)CheckMalloc(tif, + dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); + if (dir == NULL) + return (0); + if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) { + TIFFError(tif->tif_name, "Can not read TIFF directory"); + goto bad; + } else + _TIFFmemcpy(dir, tif->tif_base + off, + dircount*sizeof (TIFFDirEntry)); + off += dircount* sizeof (TIFFDirEntry); + if (off + sizeof (uint32) <= tif->tif_size) + _TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32)); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdiroff); + tif->tif_nextdiroff = nextdiroff; + + tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ + /* + * Setup default value and then make a pass over + * the fields to check type and tag information, + * and to extract info required to size data + * structures. A second pass is made afterwards + * to read in everthing not taken in the first pass. + */ + td = &tif->tif_dir; + /* free any old stuff and reinit */ + TIFFFreeDirectory(tif); + TIFFDefaultDirectory(tif); + /* + * Electronic Arts writes gray-scale TIFF files + * without a PlanarConfiguration directory entry. + * Thus we setup a default value here, even though + * the TIFF spec says there is no default value. + */ + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + /* + * Sigh, we must make a separate pass through the + * directory for the following reason: + * + * We must process the Compression tag in the first pass + * in order to merge in codec-private tag definitions (otherwise + * we may get complaints about unknown tags). However, the + * Compression tag may be dependent on the SamplesPerPixel + * tag value because older TIFF specs permited Compression + * to be written as a SamplesPerPixel-count tag entry. + * Thus if we don't first figure out the correct SamplesPerPixel + * tag value then we may end up ignoring the Compression tag + * value because it has an incorrect count value (if the + * true value of SamplesPerPixel is not 1). + * + * It sure would have been nice if Aldus had really thought + * this stuff through carefully. + */ + for (dp = dir, n = dircount; n > 0; n--, dp++) { + if (tif->tif_flags & TIFF_SWAB) { + TIFFSwabArrayOfShort(&dp->tdir_tag, 2); + TIFFSwabArrayOfLong(&dp->tdir_count, 2); + } + if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) { + if (!TIFFFetchNormalTag(tif, dp)) + goto bad; + dp->tdir_tag = IGNORE; + } + } + /* + * First real pass over the directory. + */ + fix = 0; + for (dp = dir, n = dircount; n > 0; n--, dp++) { + + /* + * Find the field information entry for this tag. + * Added check for tags to ignore ... [BFC] + */ + if( TIFFReassignTagToIgnore(TIS_EXTRACT, dp->tdir_tag) ) + dp->tdir_tag = IGNORE; + + if (dp->tdir_tag == IGNORE) + continue; + + /* + * Silicon Beach (at least) writes unordered + * directory tags (violating the spec). Handle + * it here, but be obnoxious (maybe they'll fix it?). + */ + if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) { + if (!diroutoforderwarning) { + TIFFWarning(tif->tif_name, + "invalid TIFF directory; tags are not sorted in ascending order"); + diroutoforderwarning = 1; + } + fix = 0; /* O(n^2) */ + } + while (fix < tif->tif_nfields && + tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) + fix++; + if (fix == tif->tif_nfields || + tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) { + TIFFWarning(tif->tif_name, + "unknown field with tag %d (0x%x) ignored", + dp->tdir_tag, dp->tdir_tag); + dp->tdir_tag = IGNORE; + fix = 0; /* restart search */ + continue; + } + /* + * Null out old tags that we ignore. + */ + if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) { + ignore: + dp->tdir_tag = IGNORE; + continue; + } + /* + * Check data type. + */ + fip = tif->tif_fieldinfo[fix]; + while (dp->tdir_type != (u_short) fip->field_type) { + if (fip->field_type == TIFF_ANY) /* wildcard */ + break; + fip++, fix++; + if (fix == tif->tif_nfields || + fip->field_tag != dp->tdir_tag) { + TIFFWarning(tif->tif_name, + "wrong data type %d for \"%s\"; tag ignored", + dp->tdir_type, fip[-1].field_name); + goto ignore; + } + } + /* + * Check count if known in advance. + */ + if (fip->field_readcount != TIFF_VARIABLE) { + uint32 expected = (fip->field_readcount == TIFF_SPP) ? + (uint32) td->td_samplesperpixel : + (uint32) fip->field_readcount; + if (!CheckDirCount(tif, dp, expected)) + goto ignore; + } + + switch (dp->tdir_tag) { + case TIFFTAG_COMPRESSION: + /* + * The 5.0 spec says the Compression tag has + * one value, while earlier specs say it has + * one value per sample. Because of this, we + * accept the tag if one value is supplied. + */ + if (dp->tdir_count == 1) { + v = TIFFExtractData(tif, + dp->tdir_type, dp->tdir_offset); + if (!TIFFSetField(tif, dp->tdir_tag, (int)v)) + goto bad; + break; + } + if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || + !TIFFSetField(tif, dp->tdir_tag, iv)) + goto bad; + dp->tdir_tag = IGNORE; + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEOFFSETS: + case TIFFTAG_TILEBYTECOUNTS: + TIFFSetFieldBit(tif, fip->field_bit); + break; + case TIFFTAG_IMAGEWIDTH: + case TIFFTAG_IMAGELENGTH: + case TIFFTAG_IMAGEDEPTH: + case TIFFTAG_TILELENGTH: + case TIFFTAG_TILEWIDTH: + case TIFFTAG_TILEDEPTH: + case TIFFTAG_PLANARCONFIG: + case TIFFTAG_ROWSPERSTRIP: + if (!TIFFFetchNormalTag(tif, dp)) + goto bad; + dp->tdir_tag = IGNORE; + break; + case TIFFTAG_EXTRASAMPLES: + (void) TIFFFetchExtraSamples(tif, dp); + dp->tdir_tag = IGNORE; + break; + } + } + + /* + * Allocate directory structure and setup defaults. + */ + if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { + MissingRequired(tif, "ImageLength"); + goto bad; + } + if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { + MissingRequired(tif, "PlanarConfiguration"); + goto bad; + } + /* + * Setup appropriate structures (by strip or by tile) + */ + if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { + td->td_nstrips = TIFFNumberOfStrips(tif); + td->td_tilewidth = td->td_imagewidth; + td->td_tilelength = td->td_rowsperstrip; + td->td_tiledepth = td->td_imagedepth; + tif->tif_flags &= ~TIFF_ISTILED; + } else { + td->td_nstrips = TIFFNumberOfTiles(tif); + tif->tif_flags |= TIFF_ISTILED; + } + td->td_stripsperimage = td->td_nstrips; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + td->td_stripsperimage /= td->td_samplesperpixel; + if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { + MissingRequired(tif, + isTiled(tif) ? "TileOffsets" : "StripOffsets"); + goto bad; + } + + /* + * Second pass: extract other information. + */ + for (dp = dir, n = dircount; n > 0; n--, dp++) { + if (dp->tdir_tag == IGNORE) + continue; + switch (dp->tdir_tag) { + case TIFFTAG_MINSAMPLEVALUE: + case TIFFTAG_MAXSAMPLEVALUE: + case TIFFTAG_BITSPERSAMPLE: + /* + * The 5.0 spec says the Compression tag has + * one value, while earlier specs say it has + * one value per sample. Because of this, we + * accept the tag if one value is supplied. + * + * The MinSampleValue, MaxSampleValue and + * BitsPerSample tags are supposed to be written + * as one value/sample, but some vendors incorrectly + * write one value only -- so we accept that + * as well (yech). + */ + if (dp->tdir_count == 1) { + v = TIFFExtractData(tif, + dp->tdir_type, dp->tdir_offset); + if (!TIFFSetField(tif, dp->tdir_tag, (int)v)) + goto bad; + break; + } + /* fall thru... */ + case TIFFTAG_DATATYPE: + case TIFFTAG_SAMPLEFORMAT: + if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || + !TIFFSetField(tif, dp->tdir_tag, iv)) + goto bad; + break; + case TIFFTAG_SMINSAMPLEVALUE: + case TIFFTAG_SMAXSAMPLEVALUE: + if (!TIFFFetchPerSampleAnys(tif, dp, &dv) || + !TIFFSetField(tif, dp->tdir_tag, dv)) + goto bad; + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_TILEOFFSETS: + if (!TIFFFetchStripThing(tif, dp, + td->td_nstrips, &td->td_stripoffset)) + goto bad; + break; + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEBYTECOUNTS: + if (!TIFFFetchStripThing(tif, dp, + td->td_nstrips, &td->td_stripbytecount)) + goto bad; + break; + case TIFFTAG_COLORMAP: + case TIFFTAG_TRANSFERFUNCTION: + /* + * TransferFunction can have either 1x or 3x data + * values; Colormap can have only 3x items. + */ + v = 1L<<td->td_bitspersample; + if (dp->tdir_tag == TIFFTAG_COLORMAP || + dp->tdir_count != (uint32) v) { + if (!CheckDirCount(tif, dp, (uint32)(3*v))) + break; + } + v *= sizeof (uint16); + cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint16), + "to read \"TransferFunction\" tag"); + if (cp != NULL) { + if (TIFFFetchData(tif, dp, cp)) { + /* + * This deals with there being only + * one array to apply to all samples. + */ + uint32 c = + (uint32)1 << td->td_bitspersample; + if (dp->tdir_count == c) + v = 0; + TIFFSetField(tif, dp->tdir_tag, + cp, cp+v, cp+2*v); + } + _TIFFfree(cp); + } + break; + case TIFFTAG_PAGENUMBER: + case TIFFTAG_HALFTONEHINTS: + case TIFFTAG_YCBCRSUBSAMPLING: + case TIFFTAG_DOTRANGE: + (void) TIFFFetchShortPair(tif, dp); + break; +#ifdef COLORIMETRY_SUPPORT + case TIFFTAG_REFERENCEBLACKWHITE: + (void) TIFFFetchRefBlackWhite(tif, dp); + break; +#endif +/* BEGIN REV 4.0 COMPATIBILITY */ + case TIFFTAG_OSUBFILETYPE: + v = 0; + switch (TIFFExtractData(tif, dp->tdir_type, + dp->tdir_offset)) { + case OFILETYPE_REDUCEDIMAGE: + v = FILETYPE_REDUCEDIMAGE; + break; + case OFILETYPE_PAGE: + v = FILETYPE_PAGE; + break; + } + if (v) + (void) TIFFSetField(tif, + TIFFTAG_SUBFILETYPE, (int)v); + break; +/* END REV 4.0 COMPATIBILITY */ + default: + (void) TIFFFetchNormalTag(tif, dp); + break; + } + } + /* + * Verify Palette image has a Colormap. + */ + if (td->td_photometric == PHOTOMETRIC_PALETTE && + !TIFFFieldSet(tif, FIELD_COLORMAP)) { + MissingRequired(tif, "Colormap"); + goto bad; + } + /* + * Attempt to deal with a missing StripByteCounts tag. + */ + if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { + /* + * Some manufacturers violate the spec by not giving + * the size of the strips. In this case, assume there + * is one uncompressed strip of data. + */ + if ((td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_nstrips > 1) || + (td->td_planarconfig == PLANARCONFIG_SEPARATE && + td->td_nstrips != td->td_samplesperpixel)) { + MissingRequired(tif, "StripByteCounts"); + goto bad; + } + TIFFWarning(tif->tif_name, +"TIFF directory is missing required \"%s\" field, calculating from imagelength", + _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); + EstimateStripByteCounts(tif, dir, dircount); +#define BYTECOUNTLOOKSBAD \ + ((td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \ + (td->td_compression == COMPRESSION_NONE && \ + td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0])) + } else if (td->td_nstrips == 1 && BYTECOUNTLOOKSBAD) { + /* + * Plexus (and others) sometimes give a value + * of zero for a tag when they don't know what + * the correct value is! Try and handle the + * simple case of estimating the size of a one + * strip image. + */ + TIFFWarning(tif->tif_name, + "Bogus \"%s\" field, ignoring and calculating from imagelength", + _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); + EstimateStripByteCounts(tif, dir, dircount); + } + if (dir) + _TIFFfree((char *)dir); + if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) + td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1); + /* + * Setup default compression scheme. + */ + if (!TIFFFieldSet(tif, FIELD_COMPRESSION)) + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + /* + * Some manufacturers make life difficult by writing + * large amounts of uncompressed data as a single strip. + * This is contrary to the recommendations of the spec. + * The following makes an attempt at breaking such images + * into strips closer to the recommended 8k bytes. A + * side effect, however, is that the RowsPerStrip tag + * value may be changed. + */ + if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE && + (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP) + ChopUpSingleUncompressedStrip(tif); + /* + * Reinitialize i/o since we are starting on a new directory. + */ + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (tstrip_t) -1; + tif->tif_col = (uint32) -1; + tif->tif_curtile = (ttile_t) -1; + tif->tif_tilesize = TIFFTileSize(tif); + tif->tif_scanlinesize = TIFFScanlineSize(tif); + return (1); +bad: + if (dir) + _TIFFfree(dir); + return (0); +} + +static void +EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) +{ + register TIFFDirEntry *dp; + register TIFFDirectory *td = &tif->tif_dir; + uint16 i; + + if (td->td_stripbytecount) + _TIFFfree(td->td_stripbytecount); + td->td_stripbytecount = (uint32*) + CheckMalloc(tif, td->td_nstrips * sizeof (uint32), + "for \"StripByteCounts\" array"); + if (td->td_compression != COMPRESSION_NONE) { + uint32 space = (uint32)(sizeof (TIFFHeader) + + sizeof (uint16) + + (dircount * sizeof (TIFFDirEntry)) + + sizeof (uint32)); + toff_t filesize = TIFFGetFileSize(tif); + uint16 n; + + /* calculate amount of space used by indirect values */ + for (dp = dir, n = dircount; n > 0; n--, dp++) { + uint32 cc = dp->tdir_count*tiffDataWidth[dp->tdir_type]; + if (cc > sizeof (uint32)) + space += cc; + } + space = filesize - space; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + space /= td->td_samplesperpixel; + for (i = 0; i < td->td_nstrips; i++) + td->td_stripbytecount[i] = space; + /* + * This gross hack handles the case were the offset to + * the last strip is past the place where we think the strip + * should begin. Since a strip of data must be contiguous, + * it's safe to assume that we've overestimated the amount + * of data in the strip and trim this number back accordingly. + */ + i--; + if (((toff_t)(td->td_stripoffset[i]+td->td_stripbytecount[i])) + > filesize) + td->td_stripbytecount[i] = + filesize - td->td_stripoffset[i]; + } else { + uint32 rowbytes = TIFFScanlineSize(tif); + uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage; + for (i = 0; i < td->td_nstrips; i++) + td->td_stripbytecount[i] = rowbytes*rowsperstrip; + } + TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); + if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) + td->td_rowsperstrip = td->td_imagelength; +} + +static void +MissingRequired(TIFF* tif, const char* tagname) +{ + TIFFError(tif->tif_name, + "TIFF directory is missing required \"%s\" field", tagname); +} + +/* + * Check the count field of a directory + * entry against a known value. The caller + * is expected to skip/ignore the tag if + * there is a mismatch. + */ +static int +CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) +{ + if (count > dir->tdir_count) + { + TIFFWarning(tif->tif_name, + "incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, + dir->tdir_count, count); + return (0); + } + return (1); +} + +/* + * Fetch a contiguous directory item. + */ +static tsize_t +TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + int w = tiffDataWidth[dir->tdir_type]; + tsize_t cc = dir->tdir_count * w; + + if (!isMapped(tif)) { + if (!SeekOK(tif, dir->tdir_offset)) + goto bad; + if (!ReadOK(tif, cp, cc)) + goto bad; + } else { + if (dir->tdir_offset + cc > tif->tif_size) + goto bad; + _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc); + } + if (tif->tif_flags & TIFF_SWAB) { + switch (dir->tdir_type) { + case TIFF_SHORT: + case TIFF_SSHORT: + TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); + break; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_FLOAT: + TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); + break; + case TIFF_DOUBLE: + TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); + break; + } + } + return (cc); +bad: + TIFFError(tif->tif_name, "Error fetching data for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + return ((tsize_t) 0); +} + +/* + * Fetch an ASCII item from the file. + */ +static tsize_t +TIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + if (dir->tdir_count <= 4) { + uint32 l = dir->tdir_offset; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&l); + _TIFFmemcpy(cp, &l, dir->tdir_count); + return (1); + } + return (TIFFFetchData(tif, dir, cp)); +} + +/* + * Convert numerator+denominator to float. + */ +static int +cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv) +{ + if (denom == 0) { + TIFFError(tif->tif_name, + "%s: Rational with zero denominator (num = %lu)", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num); + return (0); + } else { + if (dir->tdir_type == TIFF_RATIONAL) + *rv = ((float)num / (float)denom); + else + *rv = ((float)(int32)num / (float)(int32)denom); + return (1); + } +} + +/* + * Fetch a rational item from the file + * at offset off and return the value + * as a floating point number. + */ +static float +TIFFFetchRational(TIFF* tif, TIFFDirEntry* dir) +{ + uint32 l[2]; + float v; + + return (!TIFFFetchData(tif, dir, (char *)l) || + !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v); +} + +/* + * Fetch a single floating point value + * from the offset field and return it + * as a native float. + */ +static float +TIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir) +{ + union { + long l; + float v; + } u; + u.l = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset); + TIFFCvtIEEEFloatToNative(tif, 1, &u.v); + return (u.v); +} + +/* + * Fetch an array of BYTE or SBYTE values. + */ +static int +TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint16* v) +{ + if (dir->tdir_count <= 4) { + /* + * Extract data from offset field. + */ + if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { + switch (dir->tdir_count) { + case 4: v[3] = (uint16)(dir->tdir_offset & 0xff); + case 3: v[2] = (uint16)((dir->tdir_offset >> 8) & 0xff); + case 2: v[1] = (uint16)((dir->tdir_offset >> 16) & 0xff); + case 1: v[0] = (uint16)(dir->tdir_offset >> 24); + } + } else { + switch (dir->tdir_count) { + case 4: v[3] = (uint16)(dir->tdir_offset >> 24); + case 3: v[2] = (uint16)((dir->tdir_offset >> 16) & 0xff); + case 2: v[1] = (uint16)((dir->tdir_offset >> 8) & 0xff); + case 1: v[0] = (uint16)(dir->tdir_offset & 0xff); + } + } + return (1); + } else + return (TIFFFetchData(tif, dir, (char*) v) != 0); /* XXX */ +} + +/* + * Fetch an array of SHORT or SSHORT values. + */ +static int +TIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v) +{ + if (dir->tdir_count <= 2) { + if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { + switch (dir->tdir_count) { + case 2: v[1] = (uint16) (dir->tdir_offset & 0xffff); + case 1: v[0] = (uint16) (dir->tdir_offset >> 16); + } + } else { + switch (dir->tdir_count) { + case 2: v[1] = (uint16) (dir->tdir_offset >> 16); + case 1: v[0] = (uint16) (dir->tdir_offset & 0xffff); + } + } + return (1); + } else + return (TIFFFetchData(tif, dir, (char *)v) != 0); +} + +/* + * Fetch a pair of SHORT or BYTE values. + */ +static int +TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir) +{ + uint16 v[2]; + int ok = 0; + + switch (dir->tdir_type) { + case TIFF_SHORT: + case TIFF_SSHORT: + ok = TIFFFetchShortArray(tif, dir, v); + break; + case TIFF_BYTE: + case TIFF_SBYTE: + ok = TIFFFetchByteArray(tif, dir, v); + break; + } + if (ok) + TIFFSetField(tif, dir->tdir_tag, v[0], v[1]); + return (ok); +} + +/* + * Fetch an array of LONG or SLONG values. + */ +static int +TIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v) +{ + if (dir->tdir_count == 1) { + v[0] = dir->tdir_offset; + return (1); + } else + return (TIFFFetchData(tif, dir, (char*) v) != 0); +} + +/* + * Fetch an array of RATIONAL or SRATIONAL values. + */ +static int +TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v) +{ + int ok = 0; + uint32* l; + + l = (uint32*)CheckMalloc(tif, + dir->tdir_count*tiffDataWidth[dir->tdir_type], + "to fetch array of rationals"); + if (l) { + if (TIFFFetchData(tif, dir, (char *)l)) { + uint32 i; + for (i = 0; i < dir->tdir_count; i++) { + ok = cvtRational(tif, dir, + l[2*i+0], l[2*i+1], &v[i]); + if (!ok) + break; + } + } + _TIFFfree((char *)l); + } + return (ok); +} + +/* + * Fetch an array of FLOAT values. + */ +static int +TIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v) +{ + + if (dir->tdir_count == 1) { + v[0] = *(float*) &dir->tdir_offset; + TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); + return (1); + } else if (TIFFFetchData(tif, dir, (char*) v)) { + TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); + return (1); + } else + return (0); +} + +/* + * Fetch an array of DOUBLE values. + */ +static int +TIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v) +{ + if (TIFFFetchData(tif, dir, (char*) v)) { + TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v); + return (1); + } else + return (0); +} + +/* + * Fetch an array of ANY values. The actual values are + * returned as doubles which should be able hold all the + * types. Yes, there really should be an tany_t to avoid + * this potential non-portability ... Note in particular + * that we assume that the double return value vector is + * large enough to read in any fundamental type. We use + * that vector as a buffer to read in the base type vector + * and then convert it in place to double (from end + * to front of course). + */ +static int +TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v) +{ + int i; + + switch (dir->tdir_type) { + case TIFF_BYTE: + case TIFF_SBYTE: + if (!TIFFFetchByteArray(tif, dir, (uint16*) v)) + return (0); + if (dir->tdir_type == TIFF_BYTE) { + uint16* vp = (uint16*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } else { + int16* vp = (int16*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_SHORT: + case TIFF_SSHORT: + if (!TIFFFetchShortArray(tif, dir, (uint16*) v)) + return (0); + if (dir->tdir_type == TIFF_SHORT) { + uint16* vp = (uint16*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } else { + int16* vp = (int16*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_LONG: + case TIFF_SLONG: + if (!TIFFFetchLongArray(tif, dir, (uint32*) v)) + return (0); + if (dir->tdir_type == TIFF_LONG) { + uint32* vp = (uint32*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } else { + int32* vp = (int32*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + if (!TIFFFetchRationalArray(tif, dir, (float*) v)) + return (0); + { float* vp = (float*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_FLOAT: + if (!TIFFFetchFloatArray(tif, dir, (float*) v)) + return (0); + { float* vp = (float*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_DOUBLE: + return (TIFFFetchDoubleArray(tif, dir, (double*) v)); + default: + /* TIFF_NOTYPE */ + /* TIFF_ASCII */ + /* TIFF_UNDEFINED */ + TIFFError(tif->tif_name, + "Cannot read TIFF_ANY type %d for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + return (0); + } + return (1); +} + +/* + * Fetch a tag that is not handled by special case code. + */ +static int +TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp) +{ + static const char mesg[] = "to fetch tag value"; + int ok = 0; + const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag); + + if (dp->tdir_count > 1) { /* array of values */ + char* cp = NULL; + + switch (dp->tdir_type) { + case TIFF_BYTE: + case TIFF_SBYTE: + /* NB: always expand BYTE values to shorts */ + cp = CheckMalloc(tif, + dp->tdir_count * sizeof (uint16), mesg); + ok = cp && TIFFFetchByteArray(tif, dp, (uint16*) cp); + break; + case TIFF_SHORT: + case TIFF_SSHORT: + cp = CheckMalloc(tif, + dp->tdir_count * sizeof (uint16), mesg); + ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp); + break; + case TIFF_LONG: + case TIFF_SLONG: + cp = CheckMalloc(tif, + dp->tdir_count * sizeof (uint32), mesg); + ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp); + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + cp = CheckMalloc(tif, + dp->tdir_count * sizeof (float), mesg); + ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp); + break; + case TIFF_FLOAT: + cp = CheckMalloc(tif, + dp->tdir_count * sizeof (float), mesg); + ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp); + break; + case TIFF_DOUBLE: + cp = CheckMalloc(tif, + dp->tdir_count * sizeof (double), mesg); + ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp); + break; + case TIFF_ASCII: + case TIFF_UNDEFINED: /* bit of a cheat... */ + /* + * Some vendors write strings w/o the trailing + * NULL byte, so always append one just in case. + */ + cp = CheckMalloc(tif, dp->tdir_count+1, mesg); + if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 ) + cp[dp->tdir_count] = '\0'; /* XXX */ + break; + } + if (ok) { + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, dp->tdir_count, cp) + : TIFFSetField(tif, dp->tdir_tag, cp)); + } + if (cp != NULL) + _TIFFfree(cp); + } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */ + switch (dp->tdir_type) { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + /* + * If the tag is also acceptable as a LONG or SLONG + * then TIFFSetField will expect an uint32 parameter + * passed to it (through varargs). Thus, for machines + * where sizeof (int) != sizeof (uint32) we must do + * a careful check here. It's hard to say if this + * is worth optimizing. + * + * NB: We use TIFFFieldWithTag here knowing that + * it returns us the first entry in the table + * for the tag and that that entry is for the + * widest potential data type the tag may have. + */ + { TIFFDataType type = fip->field_type; + if (type != TIFF_LONG && type != TIFF_SLONG) { + uint16 v = (uint16) + TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v) + : TIFFSetField(tif, dp->tdir_tag, v)); + break; + } + } + /* fall thru... */ + case TIFF_LONG: + case TIFF_SLONG: + { uint32 v32 = + TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v32) + : TIFFSetField(tif, dp->tdir_tag, v32)); + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + { float v = (dp->tdir_type == TIFF_FLOAT ? + TIFFFetchFloat(tif, dp) + : TIFFFetchRational(tif, dp)); + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v) + : TIFFSetField(tif, dp->tdir_tag, v)); + } + break; + case TIFF_DOUBLE: + { double v; + ok = (TIFFFetchDoubleArray(tif, dp, &v) && + (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v) + : TIFFSetField(tif, dp->tdir_tag, v)) + ); + } + break; + case TIFF_ASCII: + case TIFF_UNDEFINED: /* bit of a cheat... */ + { char c[2]; + if( (ok = (TIFFFetchString(tif, dp, c) != 0)) != 0 ){ + c[1] = '\0'; /* XXX paranoid */ + ok = TIFFSetField(tif, dp->tdir_tag, c); + } + } + break; + } + } + return (ok); +} + +#define NITEMS(x) (sizeof (x) / sizeof (x[0])) +/* + * Fetch samples/pixel short values for + * the specified tag and verify that + * all values are the same. + */ +static int +TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, int* pl) +{ + int samples = tif->tif_dir.td_samplesperpixel; + int status = 0; + + if (CheckDirCount(tif, dir, (uint32) samples)) { + uint16 buf[10]; + uint16* v = buf; + + if (samples > (int)NITEMS(buf)) + v = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); + if (TIFFFetchShortArray(tif, dir, v)) { + int i; + for (i = 1; i < samples; i++) + if (v[i] != v[0]) { + TIFFError(tif->tif_name, + "Cannot handle different per-sample values for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + goto bad; + } + *pl = v[0]; + status = 1; + } + bad: + if (v != buf) + _TIFFfree((char*) v); + } + return (status); +} + +/* + * Fetch samples/pixel ANY values for + * the specified tag and verify that + * all values are the same. + */ +static int +TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl) +{ + int samples = (int) tif->tif_dir.td_samplesperpixel; + int status = 0; + + if (CheckDirCount(tif, dir, (uint32) samples)) { + double buf[10]; + double* v = buf; + + if (samples > (int)NITEMS(buf)) + v = (double*) _TIFFmalloc(samples * sizeof (double)); + if (TIFFFetchAnyArray(tif, dir, v)) { + int i; + for (i = 1; i < samples; i++) + if (v[i] != v[0]) { + TIFFError(tif->tif_name, + "Cannot handle different per-sample values for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + goto bad; + } + *pl = v[0]; + status = 1; + } + bad: + if (v != buf) + _TIFFfree(v); + } + return (status); +} +#undef NITEMS + +/* + * Fetch a set of offsets or lengths. + * While this routine says "strips", + * in fact it's also used for tiles. + */ +static int +TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp) +{ + register uint32* lp; + int status; + + if (!CheckDirCount(tif, dir, (uint32) nstrips)) + return (0); + /* + * Allocate space for strip information. + */ + if (*lpp == NULL && + (*lpp = (uint32 *)CheckMalloc(tif, + dir->tdir_count * sizeof (uint32), "for strip array")) == NULL) + return (0); + lp = *lpp; + if (dir->tdir_type == (int)TIFF_SHORT) { + /* + * Handle uint16->uint32 expansion. + */ + uint16* dp = (uint16*) CheckMalloc(tif, + dir->tdir_count* sizeof (uint16), "to fetch strip tag"); + if (dp == NULL) + return (0); + if( (status = TIFFFetchShortArray(tif, dir, dp)) != 0 ) { + register uint16* wp = dp; + while (nstrips-- > 0) + *lp++ = *wp++; + } + _TIFFfree((char*) dp); + } else + status = TIFFFetchLongArray(tif, dir, lp); + return (status); +} + +#define NITEMS(x) (sizeof (x) / sizeof (x[0])) +/* + * Fetch and set the ExtraSamples tag. + */ +static int +TIFFFetchExtraSamples(TIFF* tif, TIFFDirEntry* dir) +{ + uint16 buf[10]; + uint16* v = buf; + int status; + + if (dir->tdir_count > NITEMS(buf)) + v = (uint16*) _TIFFmalloc(dir->tdir_count * sizeof (uint16)); + if (dir->tdir_type == TIFF_BYTE) + status = TIFFFetchByteArray(tif, dir, v); + else + status = TIFFFetchShortArray(tif, dir, v); + if (status) + status = TIFFSetField(tif, dir->tdir_tag, dir->tdir_count, v); + if (v != buf) + _TIFFfree((char*) v); + return (status); +} +#undef NITEMS + +#ifdef COLORIMETRY_SUPPORT +/* + * Fetch and set the RefBlackWhite tag. + */ +static int +TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir) +{ + static const char mesg[] = "for \"ReferenceBlackWhite\" array"; + char* cp; + int ok; + + if (dir->tdir_type == TIFF_RATIONAL) + return (TIFFFetchNormalTag(tif, dir)); + /* + * Handle LONG's for backward compatibility. + */ + cp = CheckMalloc(tif, dir->tdir_count * sizeof (uint32), mesg); + if( (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) != 0) { + float* fp = (float*) + CheckMalloc(tif, dir->tdir_count * sizeof (float), mesg); + if( (ok = (fp != NULL)) != 0 ) { + uint32 i; + for (i = 0; i < dir->tdir_count; i++) + fp[i] = (float)((uint32*) cp)[i]; + ok = TIFFSetField(tif, dir->tdir_tag, fp); + _TIFFfree((char*) fp); + } + } + if (cp) + _TIFFfree(cp); + return (ok); +} +#endif + +/* + * Replace a single strip (tile) of uncompressed data by + * multiple strips (tiles), each approximately 8Kbytes. + * This is useful for dealing with large images or + * for dealing with machines with a limited amount + * memory. + */ +static void +ChopUpSingleUncompressedStrip(TIFF* tif) +{ + register TIFFDirectory *td = &tif->tif_dir; + uint32 bytecount = td->td_stripbytecount[0]; + uint32 offset = td->td_stripoffset[0]; + tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes; + tstrip_t strip, nstrips, rowsperstrip; + uint32* newcounts; + uint32* newoffsets; + + /* + * Make the rows hold at least one + * scanline, but fill 8k if possible. + */ + if (rowbytes > 8192) { + stripbytes = rowbytes; + rowsperstrip = 1; + } else { + rowsperstrip = 8192 / rowbytes; + stripbytes = rowbytes * rowsperstrip; + } + /* never increase the number of strips in an image */ + if (rowsperstrip >= td->td_rowsperstrip) + return; + nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes); + newcounts = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32), + "for chopped \"StripByteCounts\" array"); + newoffsets = (uint32*) CheckMalloc(tif, nstrips * sizeof (uint32), + "for chopped \"StripOffsets\" array"); + if (newcounts == NULL || newoffsets == NULL) { + /* + * Unable to allocate new strip information, give + * up and use the original one strip information. + */ + if (newcounts != NULL) + _TIFFfree(newcounts); + if (newoffsets != NULL) + _TIFFfree(newoffsets); + return; + } + /* + * Fill the strip information arrays with + * new bytecounts and offsets that reflect + * the broken-up format. + */ + for (strip = 0; strip < nstrips; strip++) { + if (stripbytes > (tsize_t) bytecount) + stripbytes = bytecount; + newcounts[strip] = stripbytes; + newoffsets[strip] = offset; + offset += stripbytes; + bytecount -= stripbytes; + } + /* + * Replace old single strip info with multi-strip info. + */ + td->td_stripsperimage = td->td_nstrips = nstrips; + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + + _TIFFfree(td->td_stripbytecount); + _TIFFfree(td->td_stripoffset); + td->td_stripbytecount = newcounts; + td->td_stripoffset = newoffsets; +} diff --git a/Utilities/vtktiff/tif_dirwrite.c b/Utilities/vtktiff/tif_dirwrite.c new file mode 100644 index 0000000..487e2ee --- /dev/null +++ b/Utilities/vtktiff/tif_dirwrite.c @@ -0,0 +1,1101 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_dirwrite.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Write Support Routines. + */ +#include "tiffiop.h" + +#if HAVE_IEEEFP +#define TIFFCvtNativeToIEEEFloat(tif, n, fp) +#define TIFFCvtNativeToIEEEDouble(tif, n, dp) +#else +extern void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*); +extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*); +#endif + +static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*); +static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32); +static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*); +static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*); +static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*); +static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**); +static int TIFFWriteShortArray(TIFF*, + TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint16*); +static int TIFFWriteLongArray(TIFF *, + TIFFDataType, ttag_t, TIFFDirEntry*, uint32, uint32*); +static int TIFFWriteRationalArray(TIFF *, + TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*); +static int TIFFWriteFloatArray(TIFF *, + TIFFDataType, ttag_t, TIFFDirEntry*, uint32, float*); +static int TIFFWriteDoubleArray(TIFF *, + TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); +static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*); +static int TIFFWriteAnyArray(TIFF*, + TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); +#ifdef COLORIMETRY_SUPPORT +static int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*); +#endif +#ifdef CMYK_SUPPORT +static int TIFFWriteInkNames(TIFF*, TIFFDirEntry*); +#endif +static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*); +static int TIFFLinkDirectory(TIFF*); + +#define WriteRationalPair(type, tag1, v1, tag2, v2) { \ + if (!TIFFWriteRational(tif, type, tag1, dir, v1)) \ + goto bad; \ + if (!TIFFWriteRational(tif, type, tag2, dir+1, v2)) \ + goto bad; \ + dir++; \ +} +#define TIFFWriteRational(tif, type, tag, dir, v) \ + TIFFWriteRationalArray((tif), (type), (tag), (dir), 1, &(v)) +#ifndef TIFFWriteRational +static int TIFFWriteRational(TIFF*, + TIFFDataType, ttag_t, TIFFDirEntry*, float); +#endif + +/* + * Write the contents of the current directory + * to the specified file. This routine doesn't + * handle overwriting a directory with auxiliary + * storage that's been changed. + */ +int +TIFFWriteDirectory(TIFF* tif) +{ + uint16 dircount; + toff_t diroff; + ttag_t tag; + uint32 nfields; + tsize_t dirsize; + char* data; + TIFFDirEntry* dir; + TIFFDirectory* td; + u_long b, fields[FIELD_SETLONGS]; + int fi, nfi; + + if (tif->tif_mode == O_RDONLY) + return (1); + /* + * Clear write state so that subsequent images with + * different characteristics get the right buffers + * setup for them. + */ + if (tif->tif_flags & TIFF_POSTENCODE) { + tif->tif_flags &= ~TIFF_POSTENCODE; + if (!(*tif->tif_postencode)(tif)) { + TIFFError(tif->tif_name, + "Error post-encoding before directory write"); + return (0); + } + } + (*tif->tif_close)(tif); /* shutdown encoder */ + /* + * Flush any data that might have been written + * by the compression close+cleanup routines. + */ + if (tif->tif_rawcc > 0 && !TIFFFlushData1(tif)) { + TIFFError(tif->tif_name, + "Error flushing data before directory write"); + return (0); + } + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawcc = 0; + tif->tif_rawdatasize = 0; + } + tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); + + td = &tif->tif_dir; + /* + * Size the directory so that we can calculate + * offsets for the data items that aren't kept + * in-place in each field. + */ + nfields = 0; + for (b = 0; b <= FIELD_LAST; b++) + if (TIFFFieldSet(tif, b)) + nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); + dirsize = nfields * sizeof (TIFFDirEntry); + data = (char*) _TIFFmalloc(dirsize); + if (data == NULL) { + TIFFError(tif->tif_name, + "Cannot write directory, out of space"); + return (0); + } + /* + * Directory hasn't been placed yet, put + * it at the end of the file and link it + * into the existing directory structure. + */ + if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif)) + goto bad; + tif->tif_dataoff = (toff_t)( + tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); + if (tif->tif_dataoff & 1) + tif->tif_dataoff++; + (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); + tif->tif_curdir++; + dir = (TIFFDirEntry*) data; + /* + * Setup external form of directory + * entries and write data items. + */ + _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); + /* + * Write out ExtraSamples tag only if + * extra samples are present in the data. + */ + if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) { + ResetFieldBit(fields, FIELD_EXTRASAMPLES); + nfields--; + dirsize -= sizeof (TIFFDirEntry); + } /*XXX*/ + for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { + const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; + if (!FieldSet(fields, fip->field_bit)) + continue; + switch (fip->field_bit) { + case FIELD_STRIPOFFSETS: + /* + * We use one field bit for both strip and tile + * offsets, and so must be careful in selecting + * the appropriate field descriptor (so that tags + * are written in sorted order). + */ + tag = isTiled(tif) ? + TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS; + if (tag != fip->field_tag) + continue; + if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, + (uint32) td->td_nstrips, td->td_stripoffset)) + goto bad; + break; + case FIELD_STRIPBYTECOUNTS: + /* + * We use one field bit for both strip and tile + * byte counts, and so must be careful in selecting + * the appropriate field descriptor (so that tags + * are written in sorted order). + */ + tag = isTiled(tif) ? + TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS; + if (tag != fip->field_tag) + continue; + if (!TIFFWriteLongArray(tif, TIFF_LONG, tag, dir, + (uint32) td->td_nstrips, td->td_stripbytecount)) + goto bad; + break; + case FIELD_ROWSPERSTRIP: + TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP, + dir, td->td_rowsperstrip); + break; + case FIELD_COLORMAP: + if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir, + 3, td->td_colormap)) + goto bad; + break; + case FIELD_IMAGEDIMENSIONS: + TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH, + dir++, td->td_imagewidth); + TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH, + dir, td->td_imagelength); + break; + case FIELD_TILEDIMENSIONS: + TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH, + dir++, td->td_tilewidth); + TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH, + dir, td->td_tilelength); + break; + case FIELD_POSITION: + WriteRationalPair(TIFF_RATIONAL, + TIFFTAG_XPOSITION, td->td_xposition, + TIFFTAG_YPOSITION, td->td_yposition); + break; + case FIELD_RESOLUTION: + WriteRationalPair(TIFF_RATIONAL, + TIFFTAG_XRESOLUTION, td->td_xresolution, + TIFFTAG_YRESOLUTION, td->td_yresolution); + break; + case FIELD_BITSPERSAMPLE: + case FIELD_MINSAMPLEVALUE: + case FIELD_MAXSAMPLEVALUE: + case FIELD_SAMPLEFORMAT: + if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir)) + goto bad; + break; + case FIELD_SMINSAMPLEVALUE: + case FIELD_SMAXSAMPLEVALUE: + if (!TIFFWritePerSampleAnys(tif, + _TIFFSampleToTagType(tif), fip->field_tag, dir)) + goto bad; + break; + case FIELD_PAGENUMBER: + case FIELD_HALFTONEHINTS: +#ifdef YCBCR_SUPPORT + case FIELD_YCBCRSUBSAMPLING: +#endif +#ifdef CMYK_SUPPORT + case FIELD_DOTRANGE: +#endif + if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) + goto bad; + break; +#ifdef CMYK_SUPPORT + case FIELD_INKNAMES: + if (!TIFFWriteInkNames(tif, dir)) + goto bad; + break; +#endif +#ifdef COLORIMETRY_SUPPORT + case FIELD_TRANSFERFUNCTION: + if (!TIFFWriteTransferFunction(tif, dir)) + goto bad; + break; +#endif +#if SUBIFD_SUPPORT + case FIELD_SUBIFD: + if (!TIFFWriteNormalTag(tif, dir, fip)) + goto bad; + /* + * Total hack: if this directory includes a SubIFD + * tag then force the next <n> directories to be + * written as ``sub directories'' of this one. This + * is used to write things like thumbnails and + * image masks that one wants to keep out of the + * normal directory linkage access mechanism. + */ + if (dir->tdir_count > 0) { + tif->tif_flags |= TIFF_INSUBIFD; + tif->tif_nsubifd = (uint16) dir->tdir_count; + if (dir->tdir_count > 1) + tif->tif_subifdoff = dir->tdir_offset; + else + tif->tif_subifdoff = (uint32)( + tif->tif_diroff + + sizeof (uint16) + + ((char*)&dir->tdir_offset-data)); + } + break; +#endif + default: + if (!TIFFWriteNormalTag(tif, dir, fip)) + goto bad; + break; + } + dir++; + ResetFieldBit(fields, fip->field_bit); + } + /* + * Write directory. + */ + dircount = (uint16) nfields; + diroff = (uint32) tif->tif_nextdiroff; + if (tif->tif_flags & TIFF_SWAB) { + /* + * The file's byte order is opposite to the + * native machine architecture. We overwrite + * the directory information with impunity + * because it'll be released below after we + * write it to the file. Note that all the + * other tag construction routines assume that + * we do this byte-swapping; i.e. they only + * byte-swap indirect data. + */ + for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { + TIFFSwabArrayOfShort(&dir->tdir_tag, 2); + TIFFSwabArrayOfLong(&dir->tdir_count, 2); + } + dircount = (uint16) nfields; + TIFFSwabShort(&dircount); + TIFFSwabLong(&diroff); + } + (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); + if (!WriteOK(tif, &dircount, sizeof (dircount))) { + TIFFError(tif->tif_name, "Error writing directory count"); + goto bad; + } + if (!WriteOK(tif, data, dirsize)) { + TIFFError(tif->tif_name, "Error writing directory contents"); + goto bad; + } + if (!WriteOK(tif, &diroff, sizeof (diroff))) { + TIFFError(tif->tif_name, "Error writing directory link"); + goto bad; + } + TIFFFreeDirectory(tif); + _TIFFfree(data); + tif->tif_flags &= ~TIFF_DIRTYDIRECT; + (*tif->tif_cleanup)(tif); + + /* + * Reset directory-related state for subsequent + * directories. + */ + TIFFCreateDirectory(tif); + return (1); +bad: + _TIFFfree(data); + return (0); +} +#undef WriteRationalPair + +/* + * Process tags that are not special cased. + */ +static int +TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) +{ + u_short wc = (u_short) fip->field_writecount; + uint32 wc2; + + dir->tdir_tag = (uint16) fip->field_tag; + dir->tdir_type = (u_short) fip->field_type; + dir->tdir_count = wc; +#define WRITEF(x,y) x(tif, fip->field_type, fip->field_tag, dir, wc, y) + switch (fip->field_type) { + case TIFF_SHORT: + case TIFF_SSHORT: + if (wc > 1) { + uint16* wp; + if (wc == (u_short) TIFF_VARIABLE) + TIFFGetField(tif, fip->field_tag, &wc, &wp); + else + TIFFGetField(tif, fip->field_tag, &wp); + if (!WRITEF(TIFFWriteShortArray, wp)) + return (0); + } else { + uint16 sv; + TIFFGetField(tif, fip->field_tag, &sv); + dir->tdir_offset = + TIFFInsertData(tif, dir->tdir_type, sv); + } + break; + case TIFF_LONG: + case TIFF_SLONG: + if (wc > 1) { + uint32* lp; + if (wc == (u_short) TIFF_VARIABLE) + TIFFGetField(tif, fip->field_tag, &wc, &lp); + else + TIFFGetField(tif, fip->field_tag, &lp); + if (!WRITEF(TIFFWriteLongArray, lp)) + return (0); + } else { + /* XXX handle LONG->SHORT conversion */ + TIFFGetField(tif, fip->field_tag, &dir->tdir_offset); + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + if (wc > 1) { + float* fp; + if (wc == (u_short) TIFF_VARIABLE) + TIFFGetField(tif, fip->field_tag, &wc, &fp); + else + TIFFGetField(tif, fip->field_tag, &fp); + if (!WRITEF(TIFFWriteRationalArray, fp)) + return (0); + } else { + float fv; + TIFFGetField(tif, fip->field_tag, &fv); + if (!WRITEF(TIFFWriteRationalArray, &fv)) + return (0); + } + break; + case TIFF_FLOAT: + if (wc > 1) { + float* fp; + if (wc == (u_short) TIFF_VARIABLE) + TIFFGetField(tif, fip->field_tag, &wc, &fp); + else + TIFFGetField(tif, fip->field_tag, &fp); + if (!WRITEF(TIFFWriteFloatArray, fp)) + return (0); + } else { + float fv; + TIFFGetField(tif, fip->field_tag, &fv); + if (!WRITEF(TIFFWriteFloatArray, &fv)) + return (0); + } + break; + case TIFF_DOUBLE: + if (wc > 1) { + double* dp; + if (wc == (u_short) TIFF_VARIABLE) + TIFFGetField(tif, fip->field_tag, &wc, &dp); + else + TIFFGetField(tif, fip->field_tag, &dp); + if (!WRITEF(TIFFWriteDoubleArray, dp)) + return (0); + } else { + double dv; + TIFFGetField(tif, fip->field_tag, &dv); + if (!WRITEF(TIFFWriteDoubleArray, &dv)) + return (0); + } + break; + case TIFF_ASCII: + { char* cp; + TIFFGetField(tif, fip->field_tag, &cp); + dir->tdir_count = (uint32) (strlen(cp) + 1); + if (!TIFFWriteByteArray(tif, dir, cp)) + return (0); + } + break; + + /* added based on patch request from MARTIN.MCBRIDE.MM@agfa.co.uk, + correctness not verified (FW, 99/08) */ + case TIFF_BYTE: + case TIFF_SBYTE: + if (wc > 1) { + char* cp; + if (wc == (u_short) TIFF_VARIABLE) { + TIFFGetField(tif, fip->field_tag, &wc, &cp); + dir->tdir_count = wc; + } else if (wc == (u_short) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &cp); + dir->tdir_count = wc2; + } else + TIFFGetField(tif, fip->field_tag, &cp); + if (!TIFFWriteByteArray(tif, dir, cp)) + return (0); + } else { + char cv; + TIFFGetField(tif, fip->field_tag, &cv); + if (!TIFFWriteByteArray(tif, dir, &cv)) + return (0); + } + break; + + case TIFF_UNDEFINED: + { char* cp; + if (wc == (u_short) TIFF_VARIABLE) { + TIFFGetField(tif, fip->field_tag, &wc, &cp); + dir->tdir_count = wc; + } else if (wc == (u_short) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &cp); + dir->tdir_count = wc2; + } else + TIFFGetField(tif, fip->field_tag, &cp); + if (!TIFFWriteByteArray(tif, dir, cp)) + return (0); + } + break; + + case TIFF_NOTYPE: + break; + } + return (1); +} +#undef WRITEF + +/* + * Setup a directory entry with either a SHORT + * or LONG type according to the value. + */ +static void +TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_count = 1; + if (v > 0xffffL) { + dir->tdir_type = (short) TIFF_LONG; + dir->tdir_offset = v; + } else { + dir->tdir_type = (short) TIFF_SHORT; + dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); + } +} +#undef MakeShortDirent + +#ifndef TIFFWriteRational +/* + * Setup a RATIONAL directory entry and + * write the associated indirect value. + */ +static int +TIFFWriteRational(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, float v) +{ + return (TIFFWriteRationalArray(tif, type, tag, dir, 1, &v)); +} +#endif + +#define NITEMS(x) (sizeof (x) / sizeof (x[0])) +/* + * Setup a directory entry that references a + * samples/pixel array of SHORT values and + * (potentially) write the associated indirect + * values. + */ +static int +TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) +{ + uint16 buf[10], v; + uint16* w = buf; + int i, status, samples = tif->tif_dir.td_samplesperpixel; + + if (samples > (int)NITEMS(buf)) + w = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); + TIFFGetField(tif, tag, &v); + for (i = 0; i < samples; i++) + w[i] = v; + status = TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, samples, w); + if (w != buf) + _TIFFfree((char*) w); + return (status); +} + +/* + * Setup a directory entry that references a samples/pixel array of ``type'' + * values and (potentially) write the associated indirect values. The source + * data from TIFFGetField() for the specified tag must be returned as double. + */ +static int +TIFFWritePerSampleAnys(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir) +{ + double buf[10], v; + double* w = buf; + int i, status; + int samples = (int) tif->tif_dir.td_samplesperpixel; + + if (samples > (int)NITEMS(buf)) + w = (double*) _TIFFmalloc(samples * sizeof (double)); + TIFFGetField(tif, tag, &v); + for (i = 0; i < samples; i++) + w[i] = v; + status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w); + if (w != buf) + _TIFFfree(w); + return (status); +} +#undef NITEMS + +/* + * Setup a pair of shorts that are returned by + * value, rather than as a reference to an array. + */ +static int +TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) +{ + uint16 v[2]; + + TIFFGetField(tif, tag, &v[0], &v[1]); + return (TIFFWriteShortArray(tif, TIFF_SHORT, tag, dir, 2, v)); +} + +/* + * Setup a directory entry for an NxM table of shorts, + * where M is known to be 2**bitspersample, and write + * the associated indirect data. + */ +static int +TIFFWriteShortTable(TIFF* tif, + ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table) +{ + uint32 i, off; + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) TIFF_SHORT; + /* XXX -- yech, fool TIFFWriteData */ + dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample); + off = tif->tif_dataoff; + for (i = 0; i < n; i++) + if (!TIFFWriteData(tif, dir, (char *)table[i])) + return (0); + dir->tdir_count *= n; + dir->tdir_offset = off; + return (1); +} + +/* + * Write/copy data associated with an ASCII or opaque tag value. + */ +static int +TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + if (dir->tdir_count > 4) { + if (!TIFFWriteData(tif, dir, cp)) + return (0); + } else + _TIFFmemcpy(&dir->tdir_offset, cp, dir->tdir_count); + return (1); +} + +/* + * Setup a directory entry of an array of SHORT + * or SSHORT and write the associated indirect values. + */ +static int +TIFFWriteShortArray(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16* v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) type; + dir->tdir_count = n; + if (n <= 2) { + if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { + dir->tdir_offset = (uint32) ((long) v[0] << 16); + if (n == 2) + dir->tdir_offset |= v[1] & 0xffff; + } else { + dir->tdir_offset = v[0] & 0xffff; + if (n == 2) + dir->tdir_offset |= (long) v[1] << 16; + } + return (1); + } else + return (TIFFWriteData(tif, dir, (char*) v)); +} + +/* + * Setup a directory entry of an array of LONG + * or SLONG and write the associated indirect values. + */ +static int +TIFFWriteLongArray(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, uint32* v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) type; + dir->tdir_count = n; + if (n == 1) { + dir->tdir_offset = v[0]; + return (1); + } else + return (TIFFWriteData(tif, dir, (char*) v)); +} + +/* + * Setup a directory entry of an array of RATIONAL + * or SRATIONAL and write the associated indirect values. + */ +static int +TIFFWriteRationalArray(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v) +{ + uint32 i; + uint32* t; + int status; + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) type; + dir->tdir_count = n; + t = (uint32*) _TIFFmalloc(2*n * sizeof (uint32)); + for (i = 0; i < n; i++) { + float fv = v[i]; + int sign = 1; + uint32 den; + + if (fv < 0) { + if (type == TIFF_RATIONAL) { + TIFFWarning(tif->tif_name, + "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL", + _TIFFFieldWithTag(tif,tag)->field_name, fv); + fv = 0; + } else + fv = -fv, sign = -1; + } + den = 1L; + if (fv > 0) { + while (fv < 1L<<(31-3) && den < 1L<<(31-3)) + fv *= 1<<3, den *= 1L<<3; + } + t[2*i+0] = (uint32) (sign * (fv + 0.5)); + t[2*i+1] = den; + } + status = TIFFWriteData(tif, dir, (char *)t); + _TIFFfree((char*) t); + return (status); +} + +static int +TIFFWriteFloatArray(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, float* v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) type; + dir->tdir_count = n; + TIFFCvtNativeToIEEEFloat(tif, n, v); + if (n == 1) { + dir->tdir_offset = *(uint32*) &v[0]; + return (1); + } else + return (TIFFWriteData(tif, dir, (char*) v)); +} + +static int +TIFFWriteDoubleArray(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) type; + dir->tdir_count = n; + TIFFCvtNativeToIEEEDouble(tif, n, v); + return (TIFFWriteData(tif, dir, (char*) v)); +} + +/* + * Write an array of ``type'' values for a specified tag (i.e. this is a tag + * which is allowed to have different types, e.g. SMaxSampleType). + * Internally the data values are represented as double since a double can + * hold any of the TIFF tag types (yes, this should really be an abstract + * type tany_t for portability). The data is converted into the specified + * type in a temporary buffer and then handed off to the appropriate array + * writer. + */ +static int +TIFFWriteAnyArray(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) +{ + char buf[10 * sizeof(double)]; + char* w = buf; + int i, status = 0; + + if (n * tiffDataWidth[type] > sizeof buf) + w = (char*) _TIFFmalloc(n * tiffDataWidth[type]); + switch (type) { + case TIFF_BYTE: + { uint8* bp = (uint8*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (uint8) v[i]; + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) type; + dir->tdir_count = n; + if (!TIFFWriteByteArray(tif, dir, (char*) bp)) + goto out; + } + break; + case TIFF_SBYTE: + { int8* bp = (int8*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (int8) v[i]; + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) type; + dir->tdir_count = n; + if (!TIFFWriteByteArray(tif, dir, (char*) bp)) + goto out; + } + break; + case TIFF_SHORT: + { uint16* bp = (uint16*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (uint16) v[i]; + if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) + goto out; + } + break; + case TIFF_SSHORT: + { int16* bp = (int16*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (int16) v[i]; + if (!TIFFWriteShortArray(tif, type, tag, dir, n, (uint16*)bp)) + goto out; + } + break; + case TIFF_LONG: + { uint32* bp = (uint32*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (uint32) v[i]; + if (!TIFFWriteLongArray(tif, type, tag, dir, n, bp)) + goto out; + } + break; + case TIFF_SLONG: + { int32* bp = (int32*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (int32) v[i]; + if (!TIFFWriteLongArray(tif, type, tag, dir, n, (uint32*) bp)) + goto out; + } + break; + case TIFF_FLOAT: + { float* bp = (float*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (float) v[i]; + if (!TIFFWriteFloatArray(tif, type, tag, dir, n, bp)) + goto out; + } + break; + case TIFF_DOUBLE: + return (TIFFWriteDoubleArray(tif, type, tag, dir, n, v)); + default: + /* TIFF_NOTYPE */ + /* TIFF_ASCII */ + /* TIFF_UNDEFINED */ + /* TIFF_RATIONAL */ + /* TIFF_SRATIONAL */ + goto out; + } + status = 1; + out: + if (w != buf) + _TIFFfree(w); + return (status); +} + +#ifdef COLORIMETRY_SUPPORT +static int +TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir) +{ + TIFFDirectory* td = &tif->tif_dir; + tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16); + uint16** tf = td->td_transferfunction; + int ncols; + + /* + * Check if the table can be written as a single column, + * or if it must be written as 3 columns. Note that we + * write a 3-column tag if there are 2 samples/pixel and + * a single column of data won't suffice--hmm. + */ + switch (td->td_samplesperpixel - td->td_extrasamples) { + default: if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; } + case 2: if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; } + case 1: case 0: ncols = 1; + } + return (TIFFWriteShortTable(tif, + TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf)); +} +#endif + +#ifdef CMYK_SUPPORT +static int +TIFFWriteInkNames(TIFF* tif, TIFFDirEntry* dir) +{ + TIFFDirectory* td = &tif->tif_dir; + + dir->tdir_tag = TIFFTAG_INKNAMES; + dir->tdir_type = (short) TIFF_ASCII; + dir->tdir_count = td->td_inknameslen; + return (TIFFWriteByteArray(tif, dir, td->td_inknames)); +} +#endif + +/* + * Write a contiguous directory item. + */ +static int +TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + tsize_t cc; + + if (tif->tif_flags & TIFF_SWAB) { + switch (dir->tdir_type) { + case TIFF_SHORT: + case TIFF_SSHORT: + TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); + break; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_FLOAT: + TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); + break; + case TIFF_DOUBLE: + TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); + break; + } + } + dir->tdir_offset = tif->tif_dataoff; + cc = dir->tdir_count * tiffDataWidth[dir->tdir_type]; + if (SeekOK(tif, dir->tdir_offset) && + WriteOK(tif, cp, cc)) { + tif->tif_dataoff += (cc + 1) & ~1; + return (1); + } + TIFFError(tif->tif_name, "Error writing data for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + return (0); +} + +/* + * Similar to TIFFWriteDirectory(), but if the directory has already + * been written once, it is relocated to the end of the file, in case it + * has changed in size. Note that this will result in the loss of the + * previously used directory space. + */ + +int +TIFFRewriteDirectory( TIFF *tif ) +{ + static const char module[] = "TIFFRewriteDirectory"; + + /* We don't need to do anything special if it hasn't been written. */ + if( tif->tif_diroff == 0 ) + return TIFFWriteDirectory( tif ); + + /* + ** Find and zero the pointer to this directory, so that TIFFLinkDirectory + ** will cause it to be added after this directories current pre-link. + */ + + /* Is it the first directory in the file? */ + if (tif->tif_header.tiff_diroff == tif->tif_diroff) + { + tif->tif_header.tiff_diroff = 0; + tif->tif_diroff = 0; + +#define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) + TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET); + if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), + sizeof (tif->tif_diroff))) + { + TIFFError(tif->tif_name, "Error updating TIFF header"); + return (0); + } + } + else + { + toff_t nextdir, off; + + nextdir = tif->tif_header.tiff_diroff; + do { + uint16 dircount; + + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount, sizeof (dircount))) { + TIFFError(module, "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + (void) TIFFSeekFile(tif, + dircount * sizeof (TIFFDirEntry), SEEK_CUR); + if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { + TIFFError(module, "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir); + } while (nextdir != tif->tif_diroff && nextdir != 0); + off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */ + (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET); + tif->tif_diroff = 0; + if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) { + TIFFError(module, "Error writing directory link"); + return (0); + } + } + + /* + ** Now use TIFFWriteDirectory() normally. + */ + + return TIFFWriteDirectory( tif ); +} + + +/* + * Link the current directory into the + * directory chain for the file. + */ +static int +TIFFLinkDirectory(TIFF* tif) +{ + static const char module[] = "TIFFLinkDirectory"; + toff_t nextdir; + toff_t diroff, off; + + tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; + diroff = tif->tif_diroff; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&diroff); +#if SUBIFD_SUPPORT + if (tif->tif_flags & TIFF_INSUBIFD) { + (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); + if (!WriteOK(tif, &diroff, sizeof (diroff))) { + TIFFError(module, + "%s: Error writing SubIFD directory link", + tif->tif_name); + return (0); + } + /* + * Advance to the next SubIFD or, if this is + * the last one configured, revert back to the + * normal directory linkage. + */ + if (--tif->tif_nsubifd) + tif->tif_subifdoff += sizeof (diroff); + else + tif->tif_flags &= ~TIFF_INSUBIFD; + return (1); + } +#endif + if (tif->tif_header.tiff_diroff == 0) { + /* + * First directory, overwrite offset in header. + */ + tif->tif_header.tiff_diroff = tif->tif_diroff; +#define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) + (void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET); + if (!WriteOK(tif, &diroff, sizeof (diroff))) { + TIFFError(tif->tif_name, "Error writing TIFF header"); + return (0); + } + return (1); + } + /* + * Not the first directory, search to the last and append. + */ + nextdir = tif->tif_header.tiff_diroff; + do { + uint16 dircount; + + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount, sizeof (dircount))) { + TIFFError(module, "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + (void) TIFFSeekFile(tif, + dircount * sizeof (TIFFDirEntry), SEEK_CUR); + if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { + TIFFError(module, "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir); + } while (nextdir != 0); + off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */ + (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET); + if (!WriteOK(tif, &diroff, sizeof (diroff))) { + TIFFError(module, "Error writing directory link"); + return (0); + } + return (1); +} diff --git a/Utilities/vtktiff/tif_dumpmode.c b/Utilities/vtktiff/tif_dumpmode.c new file mode 100644 index 0000000..27a4f21 --- /dev/null +++ b/Utilities/vtktiff/tif_dumpmode.c @@ -0,0 +1,118 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_dumpmode.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * "Null" Compression Algorithm Support. + */ +#include "tiffiop.h" +#include <assert.h> + +/* + * Encode a hunk of pixels. + */ +static int +DumpModeEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) s; + while (cc > 0) { + tsize_t n; + + n = cc; + if (tif->tif_rawcc + n > tif->tif_rawdatasize) + n = tif->tif_rawdatasize - tif->tif_rawcc; + + assert( n > 0 ); + + /* + * Avoid copy if client has setup raw + * data buffer to avoid extra copy. + */ + if (tif->tif_rawcp != pp) + _TIFFmemcpy(tif->tif_rawcp, pp, n); + tif->tif_rawcp += n; + tif->tif_rawcc += n; + pp += n; + cc -= n; + if (tif->tif_rawcc >= tif->tif_rawdatasize && + !TIFFFlushData1(tif)) + return (-1); + } + return (1); +} + +/* + * Decode a hunk of pixels. + */ +static int +DumpModeDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + (void) s; + if (tif->tif_rawcc < cc) { + TIFFError(tif->tif_name, + "DumpModeDecode: Not enough data for scanline %d", + tif->tif_row); + return (0); + } + /* + * Avoid copy if client has setup raw + * data buffer to avoid extra copy. + */ + if (tif->tif_rawcp != buf) + _TIFFmemcpy(buf, tif->tif_rawcp, cc); + tif->tif_rawcp += cc; + tif->tif_rawcc -= cc; + return (1); +} + +/* + * Seek forwards nrows in the current strip. + */ +static int +DumpModeSeek(TIFF* tif, uint32 nrows) +{ + tif->tif_rawcp += nrows * tif->tif_scanlinesize; + tif->tif_rawcc -= nrows * tif->tif_scanlinesize; + return (1); +} + +/* + * Initialize dump mode. + */ +int +TIFFInitDumpMode(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = DumpModeDecode; + tif->tif_decodestrip = DumpModeDecode; + tif->tif_decodetile = DumpModeDecode; + tif->tif_encoderow = DumpModeEncode; + tif->tif_encodestrip = DumpModeEncode; + tif->tif_encodetile = DumpModeEncode; + tif->tif_seek = DumpModeSeek; + return (1); +} diff --git a/Utilities/vtktiff/tif_error.c b/Utilities/vtktiff/tif_error.c new file mode 100644 index 0000000..dd78f13 --- /dev/null +++ b/Utilities/vtktiff/tif_error.c @@ -0,0 +1,49 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_error.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +TIFFErrorHandler +TEXPORT TIFFSetErrorHandler(TIFFErrorHandler handler) +{ + TIFFErrorHandler prev = _TIFFerrorHandler; + _TIFFerrorHandler = handler; + return (prev); +} + +void +TIFFError(const char* module, const char* fmt, ...) +{ + if (_TIFFerrorHandler) { + va_list ap; + va_start(ap, fmt); + (*_TIFFerrorHandler)(module, fmt, ap); + va_end(ap); + } +} diff --git a/Utilities/vtktiff/tif_fax3.c b/Utilities/vtktiff/tif_fax3.c new file mode 100644 index 0000000..e5ac943 --- /dev/null +++ b/Utilities/vtktiff/tif_fax3.c @@ -0,0 +1,1542 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_fax3.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1990-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef CCITT_SUPPORT +/* + * TIFF Library. + * + * CCITT Group 3 (T.4) and Group 4 (T.6) Compression Support. + * + * This file contains support for decoding and encoding TIFF + * compression algorithms 2, 3, 4, and 32771. + * + * Decoder support is derived, with permission, from the code + * in Frank Cringle's viewfax program; + * Copyright (C) 1990, 1995 Frank D. Cringle. + */ +#include "tif_fax3.h" +#define G3CODES +#include "t4.h" +#include <assert.h> +#include <stdio.h> + +/* + * Compression+decompression state blocks are + * derived from this ``base state'' block. + */ +typedef struct { + int rw_mode; /* O_RDONLY for decode, else encode */ + int mode; /* operating mode */ + uint32 rowbytes; /* bytes in a decoded scanline */ + uint32 rowpixels; /* pixels in a scanline */ + + uint16 cleanfaxdata; /* CleanFaxData tag */ + uint32 badfaxrun; /* BadFaxRun tag */ + uint32 badfaxlines; /* BadFaxLines tag */ + uint32 groupoptions; /* Group 3/4 options tag */ + uint32 recvparams; /* encoded Class 2 session params */ + char* subaddress; /* subaddress string */ + uint32 recvtime; /* time spent receiving (secs) */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ +} Fax3BaseState; +#define Fax3State(tif) ((Fax3BaseState*) (tif)->tif_data) + +typedef struct { + Fax3BaseState b; + const u_char* bitmap; /* bit reversal table */ + uint32 data; /* current i/o byte/word */ + int bit; /* current i/o bit in byte */ + int EOLcnt; /* count of EOL codes recognized */ + TIFFFaxFillFunc fill; /* fill routine */ + uint32* runs; /* b&w runs for current/previous row */ + uint32* refruns; /* runs for reference line */ + uint32* curruns; /* runs for current line */ +} Fax3DecodeState; +#define DecoderState(tif) ((Fax3DecodeState*) Fax3State(tif)) + +typedef enum { G3_1D, G3_2D } Ttag; +typedef struct { + Fax3BaseState b; + int data; /* current i/o byte */ + int bit; /* current i/o bit in byte */ + Ttag tag; /* encoding state */ + u_char* refline; /* reference line for 2d decoding */ + int k; /* #rows left that can be 2d encoded */ + int maxk; /* max #rows that can be 2d encoded */ +} Fax3EncodeState; +#define EncoderState(tif) ((Fax3EncodeState*) Fax3State(tif)) + +#define is2DEncoding(sp) \ + (sp->b.groupoptions & GROUP3OPT_2DENCODING) +#define isAligned(p,t) ((((u_long)(p)) & (sizeof (t)-1)) == 0) + +/* + * Group 3 and Group 4 Decoding. + */ + +/* + * These macros glue the TIFF library state to + * the state expected by Frank's decoder. + */ +#define DECLARE_STATE(tif, sp, mod) \ + static const char module[] = mod; \ + Fax3DecodeState* sp = DecoderState(tif); \ + int a0; /* reference element */ \ + int lastx = sp->b.rowpixels; /* last element in row */ \ + uint32 BitAcc; /* bit accumulator */ \ + int BitsAvail; /* # valid bits in BitAcc */ \ + int RunLength; /* length of current run */ \ + u_char* cp; /* next byte of input data */ \ + u_char* ep; /* end of input data */ \ + uint32* pa; /* place to stuff next run */ \ + uint32* thisrun; /* current row's run array */ \ + int EOLcnt; /* # EOL codes recognized */ \ + const u_char* bitmap = sp->bitmap; /* input data bit reverser */ \ + const TIFFFaxTabEnt* TabEnt +#define DECLARE_STATE_2D(tif, sp, mod) \ + DECLARE_STATE(tif, sp, mod); \ + int b1; /* next change on prev line */ \ + uint32* pb /* next run in reference line */\ +/* + * Load any state that may be changed during decoding. + */ +#define CACHE_STATE(tif, sp) do { \ + BitAcc = sp->data; \ + BitsAvail = sp->bit; \ + EOLcnt = sp->EOLcnt; \ + cp = (unsigned char*) tif->tif_rawcp; \ + ep = cp + tif->tif_rawcc; \ +} while (0) +/* + * Save state possibly changed during decoding. + */ +#define UNCACHE_STATE(tif, sp) do { \ + sp->bit = BitsAvail; \ + sp->data = BitAcc; \ + sp->EOLcnt = EOLcnt; \ + tif->tif_rawcc -= (tidata_t) cp - tif->tif_rawcp; \ + tif->tif_rawcp = (tidata_t) cp; \ +} while (0) + +/* + * Setup state for decoding a strip. + */ +static int +Fax3PreDecode(TIFF* tif, tsample_t s) +{ + Fax3DecodeState* sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + sp->bit = 0; /* force initial read */ + sp->data = 0; + sp->EOLcnt = 0; /* force initial scan for EOL */ + /* + * Decoder assumes lsb-to-msb bit order. Note that we select + * this here rather than in Fax3SetupState so that viewers can + * hold the image open, fiddle with the FillOrder tag value, + * and then re-decode the image. Otherwise they'd need to close + * and open the image to get the state reset. + */ + sp->bitmap = + TIFFGetBitRevTable(tif->tif_dir.td_fillorder != FILLORDER_LSB2MSB); + if (sp->refruns) { /* init reference line to white */ + sp->refruns[0] = (uint32) sp->b.rowpixels; + sp->refruns[1] = 0; + } + return (1); +} + +/* + * Routine for handling various errors/conditions. + * Note how they are "glued into the decoder" by + * overriding the definitions used by the decoder. + */ + +static void +Fax3Unexpected(const char* module, TIFF* tif, uint32 a0) +{ + TIFFError(module, "%s: Bad code word at scanline %d (x %lu)", + tif->tif_name, tif->tif_row, (u_long) a0); +} +#define unexpected(table, a0) Fax3Unexpected(module, tif, a0) + +static void +Fax3Extension(const char* module, TIFF* tif, uint32 a0) +{ + TIFFError(module, + "%s: Uncompressed data (not supported) at scanline %d (x %lu)", + tif->tif_name, tif->tif_row, (u_long) a0); +} +#define extension(a0) Fax3Extension(module, tif, a0) + +static void +Fax3BadLength(const char* module, TIFF* tif, uint32 a0, uint32 lastx) +{ + TIFFWarning(module, "%s: %s at scanline %d (got %lu, expected %lu)", + tif->tif_name, + a0 < lastx ? "Premature EOL" : "Line length mismatch", + tif->tif_row, (u_long) a0, (u_long) lastx); +} +#define badlength(a0,lastx) Fax3BadLength(module, tif, a0, lastx) + +static void +Fax3PrematureEOF(const char* module, TIFF* tif, uint32 a0) +{ + TIFFWarning(module, "%s: Premature EOF at scanline %d (x %lu)", + tif->tif_name, tif->tif_row, (u_long) a0); +} +#define prematureEOF(a0) Fax3PrematureEOF(module, tif, a0) + +#define Nop + +/* + * Decode the requested amount of G3 1D-encoded data. + */ +static int +Fax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE(tif, sp, "Fax3Decode1D"); + + (void) s; + CACHE_STATE(tif, sp); + thisrun = sp->curruns; + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); +#endif + SYNC_EOL(EOF1D); + EXPAND1D(EOF1Da); + (*sp->fill)(buf, thisrun, pa, lastx); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + if (occ != 0) + tif->tif_row++; + continue; + EOF1D: /* premature EOF */ + CLEANUP_RUNS(); + EOF1Da: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); +} + +#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; } +/* + * Decode the requested amount of G3 2D-encoded data. + */ +static int +Fax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE_2D(tif, sp, "Fax3Decode2D"); + int is1D; /* current line is 1d/2d-encoded */ + + (void) s; + CACHE_STATE(tif, sp); + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun = sp->curruns; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d EOLcnt = %d", + BitAcc, BitsAvail, EOLcnt); +#endif + SYNC_EOL(EOF2D); + NeedBits8(1, EOF2D); + is1D = GetBits(1); /* 1D/2D-encoding tag bit */ + ClrBits(1); +#ifdef FAX3_DEBUG + printf(" %s\n-------------------- %d\n", + is1D ? "1D" : "2D", tif->tif_row); + fflush(stdout); +#endif + pb = sp->refruns; + b1 = *pb++; + if (is1D) + EXPAND1D(EOF2Da); + else + EXPAND2D(EOF2Da); + (*sp->fill)(buf, thisrun, pa, lastx); + SETVAL(0); /* imaginary change for reference */ + SWAP(uint32*, sp->curruns, sp->refruns); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + if (occ != 0) + tif->tif_row++; + continue; + EOF2D: /* premature EOF */ + CLEANUP_RUNS(); + EOF2Da: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); +} +#undef SWAP + +/* + * The ZERO & FILL macros must handle spans < 2*sizeof(long) bytes. + * For machines with 64-bit longs this is <16 bytes; otherwise + * this is <8 bytes. We optimize the code here to reflect the + * machine characteristics. + */ +#if defined(__alpha) || _MIPS_SZLONG == 64 || defined(__LP64__) +#define FILL(n, cp) \ + switch (n) { \ + case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\ + case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\ + case 9: (cp)[8] = 0xff; case 8: (cp)[7] = 0xff; case 7: (cp)[6] = 0xff;\ + case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; case 4: (cp)[3] = 0xff;\ + case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ + case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + } +#define ZERO(n, cp) \ + switch (n) { \ + case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0; \ + case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0; \ + case 9: (cp)[8] = 0; case 8: (cp)[7] = 0; case 7: (cp)[6] = 0; \ + case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; case 4: (cp)[3] = 0; \ + case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ + case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + } +#else +#define FILL(n, cp) \ + switch (n) { \ + case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \ + case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ + case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + } +#define ZERO(n, cp) \ + switch (n) { \ + case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; \ + case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ + case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + } +#endif + +/* + * Bit-fill a row according to the white/black + * runs generated during G3/G4 decoding. + */ +void +_TIFFFax3fillruns(u_char* buf, uint32* runs, uint32* erun, uint32 lastx) +{ + static const unsigned char _fillmasks[] = + { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + u_char* cp; + uint32 x, bx, run; + int32 n, nw; + long* lp; + + if ((erun-runs)&1) + *erun++ = 0; + x = 0; + for (; runs < erun; runs += 2) { + run = runs[0]; + if (x+run > lastx || run > lastx ) + run = runs[0] = (uint32) (lastx - x); + if (run) { + cp = buf + (x>>3); + bx = x&7; + if (run > 8-bx) { + if (bx) { /* align to byte boundary */ + *cp++ &= 0xff << (8-bx); + run -= 8-bx; + } + if( (n = run >> 3) != 0 ) { /* multiple bytes to fill */ + if ((n/sizeof (long)) > 1) { + /* + * Align to longword boundary and fill. + */ + for (; n && !isAligned(cp, long); n--) + *cp++ = 0x00; + lp = (long*) cp; + nw = (int32)(n / sizeof (long)); + n -= nw * sizeof (long); + do { + *lp++ = 0L; + } while (--nw); + cp = (u_char*) lp; + } + ZERO(n, cp); + run &= 7; + } + if (run) + cp[0] &= 0xff >> run; + } else + cp[0] &= ~(_fillmasks[run]>>bx); + x += runs[0]; + } + run = runs[1]; + if (x+run > lastx || run > lastx ) + run = runs[1] = lastx - x; + if (run) { + cp = buf + (x>>3); + bx = x&7; + if (run > 8-bx) { + if (bx) { /* align to byte boundary */ + *cp++ |= 0xff >> bx; + run -= 8-bx; + } + if( (n = run>>3) != 0 ) { /* multiple bytes to fill */ + if ((n/sizeof (long)) > 1) { + /* + * Align to longword boundary and fill. + */ + for (; n && !isAligned(cp, long); n--) + *cp++ = 0xff; + lp = (long*) cp; + nw = (int32)(n / sizeof (long)); + n -= nw * sizeof (long); + do { + *lp++ = -1L; + } while (--nw); + cp = (u_char*) lp; + } + FILL(n, cp); + run &= 7; + } + if (run) + cp[0] |= 0xff00 >> run; + } else + cp[0] |= _fillmasks[run]>>bx; + x += runs[1]; + } + } + assert(x == lastx); +} +#undef ZERO +#undef FILL + +/* + * Setup G3/G4-related compression/decompression state + * before data is processed. This routine is called once + * per image -- it sets up different state based on whether + * or not decoding or encoding is being done and whether + * 1D- or 2D-encoded data is involved. + */ +static int +Fax3SetupState(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + Fax3BaseState* sp = Fax3State(tif); + long rowbytes, rowpixels; + int needsRefLine; + + if (td->td_bitspersample != 1) { + TIFFError(tif->tif_name, + "Bits/sample must be 1 for Group 3/4 encoding/decoding"); + return (0); + } + /* + * Calculate the scanline/tile widths. + */ + if (isTiled(tif)) { + rowbytes = TIFFTileRowSize(tif); + rowpixels = td->td_tilewidth; + } else { + rowbytes = TIFFScanlineSize(tif); + rowpixels = td->td_imagewidth; + } + sp->rowbytes = (uint32) rowbytes; + sp->rowpixels = (uint32) rowpixels; + /* + * Allocate any additional space required for decoding/encoding. + */ + needsRefLine = ( + (sp->groupoptions & GROUP3OPT_2DENCODING) || + td->td_compression == COMPRESSION_CCITTFAX4 + ); + if (sp->rw_mode == O_RDONLY) { /* 1d/2d decoding */ + Fax3DecodeState* dsp = DecoderState(tif); + uint32 nruns = needsRefLine ? + 2*TIFFroundup(rowpixels,32) : (uint32)rowpixels; + + dsp->runs = (uint32*) _TIFFmalloc((2*nruns+3)*sizeof (uint32)); + if (dsp->runs == NULL) { + TIFFError("Fax3SetupState", + "%s: No space for Group 3/4 run arrays", + tif->tif_name); + return (0); + } + dsp->curruns = dsp->runs; + if (needsRefLine) + dsp->refruns = dsp->runs + (nruns>>1); + else + dsp->refruns = NULL; + if (is2DEncoding(dsp)) { /* NB: default is 1D routine */ + tif->tif_decoderow = Fax3Decode2D; + tif->tif_decodestrip = Fax3Decode2D; + tif->tif_decodetile = Fax3Decode2D; + } + } else if (needsRefLine) { /* 2d encoding */ + Fax3EncodeState* esp = EncoderState(tif); + /* + * 2d encoding requires a scanline + * buffer for the ``reference line''; the + * scanline against which delta encoding + * is referenced. The reference line must + * be initialized to be ``white'' (done elsewhere). + */ + esp->refline = (u_char*) _TIFFmalloc(rowbytes); + if (esp->refline == NULL) { + TIFFError("Fax3SetupState", + "%s: No space for Group 3/4 reference line", + tif->tif_name); + return (0); + } + } else /* 1d encoding */ + EncoderState(tif)->refline = NULL; + return (1); +} + +/* + * CCITT Group 3 FAX Encoding. + */ + +#define Fax3FlushBits(tif, sp) { \ + if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ + (void) TIFFFlushData1(tif); \ + *(tif)->tif_rawcp++ = (sp)->data; \ + (tif)->tif_rawcc++; \ + (sp)->data = 0, (sp)->bit = 8; \ +} +#define _FlushBits(tif) { \ + if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ + (void) TIFFFlushData1(tif); \ + *(tif)->tif_rawcp++ = data; \ + (tif)->tif_rawcc++; \ + data = 0, bit = 8; \ +} +static const int _msbmask[9] = + { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; +#define _PutBits(tif, bits, length) { \ + while (length > bit) { \ + data |= bits >> (length - bit); \ + length -= bit; \ + _FlushBits(tif); \ + } \ + data |= (bits & _msbmask[length]) << (bit - length); \ + bit -= length; \ + if (bit == 0) \ + _FlushBits(tif); \ +} + +/* + * Write a variable-length bit-value to + * the output stream. Values are + * assumed to be at most 16 bits. + */ +static void +Fax3PutBits(TIFF* tif, u_int bits, u_int length) +{ + Fax3EncodeState* sp = EncoderState(tif); + u_int bit = sp->bit; + int data = sp->data; + + _PutBits(tif, bits, length); + + sp->data = data; + sp->bit = bit; +} + +/* + * Write a code to the output stream. + */ +#define putcode(tif, te) Fax3PutBits(tif, (te)->code, (te)->length) + +#ifdef FAX3_DEBUG +#define DEBUG_COLOR(w) (tab == TIFFFaxWhiteCodes ? w "W" : w "B") +#define DEBUG_PRINT(what,len) { \ + int t; \ + printf("%08X/%-2d: %s%5d\t", data, bit, DEBUG_COLOR(what), len); \ + for (t = length-1; t >= 0; t--) \ + putchar(code & (1<<t) ? '1' : '0'); \ + putchar('\n'); \ +} +#endif + +/* + * Write the sequence of codes that describes + * the specified span of zero's or one's. The + * appropriate table that holds the make-up and + * terminating codes is supplied. + */ +static void +putspan(TIFF* tif, int32 span, const tableentry* tab) +{ + Fax3EncodeState* sp = EncoderState(tif); + u_int bit = sp->bit; + int data = sp->data; + u_int code, length; + + while (span >= 2624) { + const tableentry* te = &tab[63 + (2560>>6)]; + code = te->code, length = te->length; +#ifdef FAX3_DEBUG + DEBUG_PRINT("MakeUp", te->runlen); +#endif + _PutBits(tif, code, length); + span -= te->runlen; + } + if (span >= 64) { + const tableentry* te = &tab[63 + (span>>6)]; + assert(te->runlen == 64*(span>>6)); + code = te->code, length = te->length; +#ifdef FAX3_DEBUG + DEBUG_PRINT("MakeUp", te->runlen); +#endif + _PutBits(tif, code, length); + span -= te->runlen; + } + code = tab[span].code, length = tab[span].length; +#ifdef FAX3_DEBUG + DEBUG_PRINT(" Term", tab[span].runlen); +#endif + _PutBits(tif, code, length); + + sp->data = data; + sp->bit = bit; +} + +/* + * Write an EOL code to the output stream. The zero-fill + * logic for byte-aligning encoded scanlines is handled + * here. We also handle writing the tag bit for the next + * scanline when doing 2d encoding. + */ +static void +Fax3PutEOL(TIFF* tif) +{ + Fax3EncodeState* sp = EncoderState(tif); + u_int bit = sp->bit; + int data = sp->data; + u_int code, length, tparm; + + if (sp->b.groupoptions & GROUP3OPT_FILLBITS) { + /* + * Force bit alignment so EOL will terminate on + * a byte boundary. That is, force the bit alignment + * to 16-12 = 4 before putting out the EOL code. + */ + int align = 8 - 4; + if (align != sp->bit) { + if (align > sp->bit) + align = sp->bit + (8 - align); + else + align = sp->bit - align; + code = 0; + tparm=align; + _PutBits(tif, 0, tparm); + } + } + code = EOL, length = 12; + if (is2DEncoding(sp)) + code = (code<<1) | (sp->tag == G3_1D), length++; + _PutBits(tif, code, length); + + sp->data = data; + sp->bit = bit; +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +Fax3PreEncode(TIFF* tif, tsample_t s) +{ + Fax3EncodeState* sp = EncoderState(tif); + + (void) s; + assert(sp != NULL); + sp->bit = 8; + sp->data = 0; + sp->tag = G3_1D; + /* + * This is necessary for Group 4; otherwise it isn't + * needed because the first scanline of each strip ends + * up being copied into the refline. + */ + if (sp->refline) + _TIFFmemset(sp->refline, 0x00, sp->b.rowbytes); + if (is2DEncoding(sp)) { + float res = tif->tif_dir.td_yresolution; + /* + * The CCITT spec says that when doing 2d encoding, you + * should only do it on K consecutive scanlines, where K + * depends on the resolution of the image being encoded + * (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory + * code initializes td_yresolution to 0, this code will + * select a K of 2 unless the YResolution tag is set + * appropriately. (Note also that we fudge a little here + * and use 150 lpi to avoid problems with units conversion.) + */ + if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER) + res *= 2.54f; /* convert to inches */ + sp->maxk = (res > 150 ? 4 : 2); + sp->k = sp->maxk-1; + } else + sp->k = sp->maxk = 0; + return (1); +} + +static const u_char zeroruns[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */ +}; +static const u_char oneruns[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */ + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */ +}; + +/* + * On certain systems it pays to inline + * the routines that find pixel spans. + */ +#ifdef VAXC +static int32 find0span(u_char*, int32, int32); +static int32 find1span(u_char*, int32, int32); +#pragma inline(find0span,find1span) +#endif + +/* + * Find a span of ones or zeros using the supplied + * table. The ``base'' of the bit string is supplied + * along with the start+end bit indices. + */ +static int32 +find0span(u_char* bp, int32 bs, int32 be) +{ + int32 bits = be - bs; + int32 n, span; + + bp += bs>>3; + /* + * Check partial byte on lhs. + */ + if (bits > 0 && (n = (bs & 7))) { + span = zeroruns[(*bp << n) & 0xff]; + if (span > 8-n) /* table value too generous */ + span = 8-n; + if (span > bits) /* constrain span to bit range */ + span = bits; + if (n+span < 8) /* doesn't extend to edge of byte */ + return (span); + bits -= span; + bp++; + } else + span = 0; + if (bits >= (int32)(2*8*sizeof (long))) { + long* lp; + /* + * Align to longword boundary and check longwords. + */ + while (!isAligned(bp, long)) { + if (*bp != 0x00) + return (span + zeroruns[*bp]); + span += 8, bits -= 8; + bp++; + } + lp = (long*) bp; + while (bits >= (int32)(8*sizeof (long)) && *lp == 0) { + span += 8*sizeof (long), bits -= 8*sizeof (long); + lp++; + } + bp = (u_char*) lp; + } + /* + * Scan full bytes for all 0's. + */ + while (bits >= 8) { + if (*bp != 0x00) /* end of run */ + return (span + zeroruns[*bp]); + span += 8, bits -= 8; + bp++; + } + /* + * Check partial byte on rhs. + */ + if (bits > 0) { + n = zeroruns[*bp]; + span += (n > bits ? bits : n); + } + return (span); +} + +static int32 +find1span(u_char* bp, int32 bs, int32 be) +{ + int32 bits = be - bs; + int32 n, span; + + bp += bs>>3; + /* + * Check partial byte on lhs. + */ + if (bits > 0 && (n = (bs & 7))) { + span = oneruns[(*bp << n) & 0xff]; + if (span > 8-n) /* table value too generous */ + span = 8-n; + if (span > bits) /* constrain span to bit range */ + span = bits; + if (n+span < 8) /* doesn't extend to edge of byte */ + return (span); + bits -= span; + bp++; + } else + span = 0; + if (bits >= (int32)(2*8*sizeof (long))) { + long* lp; + /* + * Align to longword boundary and check longwords. + */ + while (!isAligned(bp, long)) { + if (*bp != 0xff) + return (span + oneruns[*bp]); + span += 8, bits -= 8; + bp++; + } + lp = (long*) bp; + while (bits >= (int32)(8*sizeof (long)) && *lp == ~0) { + span += 8*sizeof (long), bits -= 8*sizeof (long); + lp++; + } + bp = (u_char*) lp; + } + /* + * Scan full bytes for all 1's. + */ + while (bits >= 8) { + if (*bp != 0xff) /* end of run */ + return (span + oneruns[*bp]); + span += 8, bits -= 8; + bp++; + } + /* + * Check partial byte on rhs. + */ + if (bits > 0) { + n = oneruns[*bp]; + span += (n > bits ? bits : n); + } + return (span); +} + +/* + * Return the offset of the next bit in the range + * [bs..be] that is different from the specified + * color. The end, be, is returned if no such bit + * exists. + */ +#define finddiff(_cp, _bs, _be, _color) \ + (_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be))) +/* + * Like finddiff, but also check the starting bit + * against the end in case start > end. + */ +#define finddiff2(_cp, _bs, _be, _color) \ + (_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be) + +/* + * 1d-encode a row of pixels. The encoding is + * a sequence of all-white or all-black spans + * of pixels encoded with Huffman codes. + */ +static int +Fax3Encode1DRow(TIFF* tif, u_char* bp, uint32 bits) +{ + Fax3EncodeState* sp = EncoderState(tif); + int32 span; + uint32 bs = 0; + + for (;;) { + span = find0span(bp, bs, bits); /* white span */ + putspan(tif, span, TIFFFaxWhiteCodes); + bs += span; + if (bs >= bits) + break; + span = find1span(bp, bs, bits); /* black span */ + putspan(tif, span, TIFFFaxBlackCodes); + bs += span; + if (bs >= bits) + break; + } + if (sp->b.mode & (FAXMODE_BYTEALIGN|FAXMODE_WORDALIGN)) { + if (sp->bit != 8) /* byte-align */ + Fax3FlushBits(tif, sp); + if ((sp->b.mode&FAXMODE_WORDALIGN) && + !isAligned(tif->tif_rawcp, uint16)) + Fax3FlushBits(tif, sp); + } + return (1); +} + +static const tableentry horizcode = + { 3, 0x1, 0 }; /* 001 */ +static const tableentry passcode = + { 4, 0x1, 0 }; /* 0001 */ +static const tableentry vcodes[7] = { + { 7, 0x03, 0 }, /* 0000 011 */ + { 6, 0x03, 0 }, /* 0000 11 */ + { 3, 0x03, 0 }, /* 011 */ + { 1, 0x1, 0 }, /* 1 */ + { 3, 0x2, 0 }, /* 010 */ + { 6, 0x02, 0 }, /* 0000 10 */ + { 7, 0x02, 0 } /* 0000 010 */ +}; + +/* + * 2d-encode a row of pixels. Consult the CCITT + * documentation for the algorithm. + */ +static int +Fax3Encode2DRow(TIFF* tif, u_char* bp, u_char* rp, uint32 bits) +{ +#define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) + uint32 a0 = 0; + uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0)); + uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0)); + uint32 a2, b2; + + for (;;) { + b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1)); + if (b2 >= a1) { + int32 d = b1 - a1; + if (!(-3 <= d && d <= 3)) { /* horizontal mode */ + a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1)); + putcode(tif, &horizcode); + if (a0+a1 == 0 || PIXEL(bp, a0) == 0) { + putspan(tif, a1-a0, TIFFFaxWhiteCodes); + putspan(tif, a2-a1, TIFFFaxBlackCodes); + } else { + putspan(tif, a1-a0, TIFFFaxBlackCodes); + putspan(tif, a2-a1, TIFFFaxWhiteCodes); + } + a0 = a2; + } else { /* vertical mode */ + putcode(tif, &vcodes[d+3]); + a0 = a1; + } + } else { /* pass mode */ + putcode(tif, &passcode); + a0 = b2; + } + if (a0 >= bits) + break; + a1 = finddiff(bp, a0, bits, PIXEL(bp,a0)); + b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0)); + b1 = finddiff(rp, b1, bits, PIXEL(bp,a0)); + } + return (1); +#undef PIXEL +} + +/* + * Encode a buffer of pixels. + */ +static int +Fax3Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + Fax3EncodeState* sp = EncoderState(tif); + + (void) s; + while ((long)cc > 0) { + if ((sp->b.mode & FAXMODE_NOEOL) == 0) + Fax3PutEOL(tif); + if (is2DEncoding(sp)) { + if (sp->tag == G3_1D) { + if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) + return (0); + sp->tag = G3_2D; + } else { + if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels)) + return (0); + sp->k--; + } + if (sp->k == 0) { + sp->tag = G3_1D; + sp->k = sp->maxk-1; + } else + _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); + } else { + if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) + return (0); + } + bp += sp->b.rowbytes; + cc -= sp->b.rowbytes; + if (cc != 0) + tif->tif_row++; + } + return (1); +} + +static int +Fax3PostEncode(TIFF* tif) +{ + Fax3EncodeState* sp = EncoderState(tif); + + if (sp->bit != 8) + Fax3FlushBits(tif, sp); + return (1); +} + +static void +Fax3Close(TIFF* tif) +{ + if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0) { + Fax3EncodeState* sp = EncoderState(tif); + u_int code = EOL; + u_int length = 12; + int i; + + if (is2DEncoding(sp)) + code = (code<<1) | (sp->tag == G3_1D), length++; + for (i = 0; i < 6; i++) + Fax3PutBits(tif, code, length); + Fax3FlushBits(tif, sp); + } +} + +static void +Fax3Cleanup(TIFF* tif) +{ + if (tif->tif_data) { + if (Fax3State(tif)->rw_mode == O_RDONLY) { + Fax3DecodeState* sp = DecoderState(tif); + if (sp->runs) + _TIFFfree(sp->runs); + } else { + Fax3EncodeState* sp = EncoderState(tif); + if (sp->refline) + _TIFFfree(sp->refline); + } + if (Fax3State(tif)->subaddress) + _TIFFfree(Fax3State(tif)->subaddress); + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; + } +} + +#define FIELD_BADFAXLINES (FIELD_CODEC+0) +#define FIELD_CLEANFAXDATA (FIELD_CODEC+1) +#define FIELD_BADFAXRUN (FIELD_CODEC+2) +#define FIELD_RECVPARAMS (FIELD_CODEC+3) +#define FIELD_SUBADDRESS (FIELD_CODEC+4) +#define FIELD_RECVTIME (FIELD_CODEC+5) + +#define FIELD_OPTIONS (FIELD_CODEC+6) + +static const TIFFFieldInfo faxFieldInfo[] = { + { TIFFTAG_FAXMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "FaxMode" }, + { TIFFTAG_FAXFILLFUNC, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "FaxFillFunc" }, + { TIFFTAG_BADFAXLINES, 1, 1, TIFF_LONG, FIELD_BADFAXLINES, + TRUE, FALSE, "BadFaxLines" }, + { TIFFTAG_BADFAXLINES, 1, 1, TIFF_SHORT, FIELD_BADFAXLINES, + TRUE, FALSE, "BadFaxLines" }, + { TIFFTAG_CLEANFAXDATA, 1, 1, TIFF_SHORT, FIELD_CLEANFAXDATA, + TRUE, FALSE, "CleanFaxData" }, + { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_LONG, FIELD_BADFAXRUN, + TRUE, FALSE, "ConsecutiveBadFaxLines" }, + { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_SHORT, FIELD_BADFAXRUN, + TRUE, FALSE, "ConsecutiveBadFaxLines" }, + { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS, + TRUE, FALSE, "FaxRecvParams" }, + { TIFFTAG_FAXSUBADDRESS, -1,-1, TIFF_ASCII, FIELD_SUBADDRESS, + TRUE, FALSE, "FaxSubAddress" }, + { TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME, + TRUE, FALSE, "FaxRecvTime" }, +}; +static const TIFFFieldInfo fax3FieldInfo[] = { + { TIFFTAG_GROUP3OPTIONS, 1, 1, TIFF_LONG, FIELD_OPTIONS, + FALSE, FALSE, "Group3Options" }, +}; +static const TIFFFieldInfo fax4FieldInfo[] = { + { TIFFTAG_GROUP4OPTIONS, 1, 1, TIFF_LONG, FIELD_OPTIONS, + FALSE, FALSE, "Group4Options" }, +}; +#define N(a) (sizeof (a) / sizeof (a[0])) + +static int +Fax3VSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + Fax3BaseState* sp = Fax3State(tif); + + switch (tag) { + case TIFFTAG_FAXMODE: + sp->mode = va_arg(ap, int); + return (1); /* NB: pseudo tag */ + case TIFFTAG_FAXFILLFUNC: + if (sp->rw_mode == O_RDONLY) + DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc); + return (1); /* NB: pseudo tag */ + case TIFFTAG_GROUP3OPTIONS: + case TIFFTAG_GROUP4OPTIONS: + sp->groupoptions = va_arg(ap, uint32); + break; + case TIFFTAG_BADFAXLINES: + sp->badfaxlines = va_arg(ap, uint32); + break; + case TIFFTAG_CLEANFAXDATA: + sp->cleanfaxdata = (uint16) va_arg(ap, int); + break; + case TIFFTAG_CONSECUTIVEBADFAXLINES: + sp->badfaxrun = va_arg(ap, uint32); + break; + case TIFFTAG_FAXRECVPARAMS: + sp->recvparams = va_arg(ap, uint32); + break; + case TIFFTAG_FAXSUBADDRESS: + _TIFFsetString(&sp->subaddress, va_arg(ap, char*)); + break; + case TIFFTAG_FAXRECVTIME: + sp->recvtime = va_arg(ap, uint32); + break; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit); + tif->tif_flags |= TIFF_DIRTYDIRECT; + return (1); +} + +static int +Fax3VGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + Fax3BaseState* sp = Fax3State(tif); + + switch (tag) { + case TIFFTAG_FAXMODE: + *va_arg(ap, int*) = sp->mode; + break; + case TIFFTAG_FAXFILLFUNC: + if (sp->rw_mode == O_RDONLY) + *va_arg(ap, TIFFFaxFillFunc*) = DecoderState(tif)->fill; + break; + case TIFFTAG_GROUP3OPTIONS: + case TIFFTAG_GROUP4OPTIONS: + *va_arg(ap, uint32*) = sp->groupoptions; + break; + case TIFFTAG_BADFAXLINES: + *va_arg(ap, uint32*) = sp->badfaxlines; + break; + case TIFFTAG_CLEANFAXDATA: + *va_arg(ap, uint16*) = sp->cleanfaxdata; + break; + case TIFFTAG_CONSECUTIVEBADFAXLINES: + *va_arg(ap, uint32*) = sp->badfaxrun; + break; + case TIFFTAG_FAXRECVPARAMS: + *va_arg(ap, uint32*) = sp->recvparams; + break; + case TIFFTAG_FAXSUBADDRESS: + *va_arg(ap, char**) = sp->subaddress; + break; + case TIFFTAG_FAXRECVTIME: + *va_arg(ap, uint32*) = sp->recvtime; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static void +Fax3PrintDir(TIFF* tif, FILE* fd, long flags) +{ + Fax3BaseState* sp = Fax3State(tif); + + (void) flags; + if (TIFFFieldSet(tif,FIELD_OPTIONS)) { + const char* sep = " "; + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) { + fprintf(fd, " Group 4 Options:"); + if (sp->groupoptions & GROUP4OPT_UNCOMPRESSED) + fprintf(fd, "%suncompressed data", sep); + } else { + + fprintf(fd, " Group 3 Options:"); + if (sp->groupoptions & GROUP3OPT_2DENCODING) + fprintf(fd, "%s2-d encoding", sep), sep = "+"; + if (sp->groupoptions & GROUP3OPT_FILLBITS) + fprintf(fd, "%sEOL padding", sep), sep = "+"; + if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED) + fprintf(fd, "%suncompressed data", sep); + } + fprintf(fd, " (%lu = 0x%lx)\n", + (u_long) sp->groupoptions, (u_long) sp->groupoptions); + } + if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) { + fprintf(fd, " Fax Data:"); + switch (sp->cleanfaxdata) { + case CLEANFAXDATA_CLEAN: + fprintf(fd, " clean"); + break; + case CLEANFAXDATA_REGENERATED: + fprintf(fd, " receiver regenerated"); + break; + case CLEANFAXDATA_UNCLEAN: + fprintf(fd, " uncorrected errors"); + break; + } + fprintf(fd, " (%u = 0x%x)\n", + sp->cleanfaxdata, sp->cleanfaxdata); + } + if (TIFFFieldSet(tif,FIELD_BADFAXLINES)) + fprintf(fd, " Bad Fax Lines: %lu\n", (u_long) sp->badfaxlines); + if (TIFFFieldSet(tif,FIELD_BADFAXRUN)) + fprintf(fd, " Consecutive Bad Fax Lines: %lu\n", + (u_long) sp->badfaxrun); + if (TIFFFieldSet(tif,FIELD_RECVPARAMS)) + fprintf(fd, " Fax Receive Parameters: %08lx\n", + (u_long) sp->recvparams); + if (TIFFFieldSet(tif,FIELD_SUBADDRESS)) + fprintf(fd, " Fax SubAddress: %s\n", sp->subaddress); + if (TIFFFieldSet(tif,FIELD_RECVTIME)) + fprintf(fd, " Fax Receive Time: %lu secs\n", + (u_long) sp->recvtime); +} + +static int +InitCCITTFax3(TIFF* tif) +{ + Fax3BaseState* sp; + + /* + * Allocate state block so tag methods have storage to record values. + */ + if (tif->tif_mode == O_RDONLY) + tif->tif_data = (tidata_t) + _TIFFmalloc(sizeof (Fax3DecodeState)); + else + tif->tif_data = (tidata_t) + _TIFFmalloc(sizeof (Fax3EncodeState)); + + if (tif->tif_data == NULL) { + TIFFError("TIFFInitCCITTFax3", + "%s: No space for state block", tif->tif_name); + return (0); + } + + sp = Fax3State(tif); + sp->rw_mode = tif->tif_mode; + + /* + * Merge codec-specific tag information and + * override parent get/set field methods. + */ + _TIFFMergeFieldInfo(tif, faxFieldInfo, N(faxFieldInfo)); + sp->vgetparent = tif->tif_vgetfield; + tif->tif_vgetfield = Fax3VGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_vsetfield; + tif->tif_vsetfield = Fax3VSetField; /* hook for codec tags */ + tif->tif_printdir = Fax3PrintDir; /* hook for codec tags */ + sp->groupoptions = 0; + sp->recvparams = 0; + sp->subaddress = NULL; + + if (sp->rw_mode == O_RDONLY) { + tif->tif_flags |= TIFF_NOBITREV;/* decoder does bit reversal */ + DecoderState(tif)->runs = NULL; + TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, _TIFFFax3fillruns); + } else + EncoderState(tif)->refline = NULL; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = Fax3SetupState; + tif->tif_predecode = Fax3PreDecode; + tif->tif_decoderow = Fax3Decode1D; + tif->tif_decodestrip = Fax3Decode1D; + tif->tif_decodetile = Fax3Decode1D; + tif->tif_setupencode = Fax3SetupState; + tif->tif_preencode = Fax3PreEncode; + tif->tif_postencode = Fax3PostEncode; + tif->tif_encoderow = Fax3Encode; + tif->tif_encodestrip = Fax3Encode; + tif->tif_encodetile = Fax3Encode; + tif->tif_close = Fax3Close; + tif->tif_cleanup = Fax3Cleanup; + + return (1); +} + +int +TIFFInitCCITTFax3(TIFF* tif, int scheme) +{ + scheme = 0; + if (InitCCITTFax3(tif)) { + _TIFFMergeFieldInfo(tif, fax3FieldInfo, N(fax3FieldInfo)); + + /* + * The default format is Class/F-style w/o RTC. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF); + } else + return (0); +} + +/* + * CCITT Group 4 (T.6) Facsimile-compatible + * Compression Scheme Support. + */ + +#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; } +/* + * Decode the requested amount of G4-encoded data. + */ +static int +Fax4Decode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE_2D(tif, sp, "Fax4Decode"); + + (void) s; + CACHE_STATE(tif, sp); + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun = sp->curruns; + pb = sp->refruns; + b1 = *pb++; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); +#endif + EXPAND2D(EOFG4); + if (EOLcnt) + goto EOFG4; + (*sp->fill)(buf, thisrun, pa, lastx); + SETVAL(0); /* imaginary change for reference */ + SWAP(uint32*, sp->curruns, sp->refruns); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + if (occ != 0) + tif->tif_row++; + continue; + EOFG4: + NeedBits16( 13, BADG4 ); + BADG4: +#ifdef FAX3_DEBUG + if( GetBits(13) != 0x1001 ) + fputs( "Bad RTC\n", stderr ); +#endif + ClrBits( 13 ); + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); +} +#undef SWAP + +/* + * Encode the requested amount of data. + */ +static int +Fax4Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + Fax3EncodeState *sp = EncoderState(tif); + + (void) s; + while ((long)cc > 0) { + if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels)) + return (0); + _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); + bp += sp->b.rowbytes; + cc -= sp->b.rowbytes; + if (cc != 0) + tif->tif_row++; + } + return (1); +} + +static int +Fax4PostEncode(TIFF* tif) +{ + Fax3EncodeState *sp = EncoderState(tif); + + /* terminate strip w/ EOFB */ + Fax3PutBits(tif, EOL, 12); + Fax3PutBits(tif, EOL, 12); + if (sp->bit != 8) + Fax3FlushBits(tif, sp); + return (1); +} + +int +TIFFInitCCITTFax4(TIFF* tif, int scheme) +{ + scheme = 0; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + _TIFFMergeFieldInfo(tif, fax4FieldInfo, N(fax4FieldInfo)); + + tif->tif_decoderow = Fax4Decode; + tif->tif_decodestrip = Fax4Decode; + tif->tif_decodetile = Fax4Decode; + tif->tif_encoderow = Fax4Encode; + tif->tif_encodestrip = Fax4Encode; + tif->tif_encodetile = Fax4Encode; + tif->tif_postencode = Fax4PostEncode; + /* + * Suppress RTC at the end of each strip. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_NORTC); + } else + return (0); +} + +/* + * CCITT Group 3 1-D Modified Huffman RLE Compression Support. + * (Compression algorithms 2 and 32771) + */ + +/* + * Decode the requested amount of RLE-encoded data. + */ +static int +Fax3DecodeRLE(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE(tif, sp, "Fax3DecodeRLE"); + int mode = sp->b.mode; + + (void) s; + CACHE_STATE(tif, sp); + thisrun = sp->curruns; + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); +#endif + EXPAND1D(EOFRLE); + (*sp->fill)(buf, thisrun, pa, lastx); + /* + * Cleanup at the end of the row. + */ + if (mode & FAXMODE_BYTEALIGN) { + int n = BitsAvail - (BitsAvail &~ 7); + ClrBits(n); + } else if (mode & FAXMODE_WORDALIGN) { + int n = BitsAvail - (BitsAvail &~ 15); + ClrBits(n); + if (BitsAvail == 0 && !isAligned(cp, uint16)) + cp++; + } + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + if (occ != 0) + tif->tif_row++; + continue; + EOFRLE: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); +} + +int +TIFFInitCCITTRLE(TIFF* tif, int scheme) +{ + scheme = 0; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; + /* + * Suppress RTC+EOLs when encoding and byte-align data. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, + FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_BYTEALIGN); + } else + return (0); +} + +int +TIFFInitCCITTRLEW(TIFF* tif, int scheme) +{ + scheme = 0; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; + /* + * Suppress RTC+EOLs when encoding and word-align data. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, + FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_WORDALIGN); + } else + return (0); +} +#endif /* CCITT_SUPPORT */ diff --git a/Utilities/vtktiff/tif_fax3.h b/Utilities/vtktiff/tif_fax3.h new file mode 100644 index 0000000..4683879 --- /dev/null +++ b/Utilities/vtktiff/tif_fax3.h @@ -0,0 +1,526 @@ +/* $Id: tif_fax3.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1990-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _FAX3_ +#define _FAX3_ +/* + * TIFF Library. + * + * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support. + * + * Decoder support is derived, with permission, from the code + * in Frank Cringle's viewfax program; + * Copyright (C) 1990, 1995 Frank D. Cringle. + */ +#include "tiff.h" + +/* + * To override the default routine used to image decoded + * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC. + * The routine must have the type signature given below; + * for example: + * + * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx) + * + * where buf is place to set the bits, runs is the array of b&w run + * lengths (white then black), erun is the last run in the array, and + * lastx is the width of the row in pixels. Fill routines can assume + * the run array has room for at least lastx runs and can overwrite + * data in the run array as needed (e.g. to append zero runs to bring + * the count up to a nice multiple). + */ +typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32); + +/* + * The default run filler; made external for other decoders. + */ +#if defined(__cplusplus) +extern "C" { +#endif +extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32); +#if defined(__cplusplus) +} +#endif + + +/* finite state machine codes */ +#define S_Null 0 +#define S_Pass 1 +#define S_Horiz 2 +#define S_V0 3 +#define S_VR 4 +#define S_VL 5 +#define S_Ext 6 +#define S_TermW 7 +#define S_TermB 8 +#define S_MakeUpW 9 +#define S_MakeUpB 10 +#define S_MakeUp 11 +#define S_EOL 12 + +typedef struct { /* state table entry */ + unsigned char State; /* see above */ + unsigned char Width; /* width of code in bits */ + uint32 Param; /* unsigned 32-bit run length in bits */ +} TIFFFaxTabEnt; + +extern const TIFFFaxTabEnt TIFFFaxMainTable[]; +extern const TIFFFaxTabEnt TIFFFaxWhiteTable[]; +extern const TIFFFaxTabEnt TIFFFaxBlackTable[]; + +/* + * The following macros define the majority of the G3/G4 decoder + * algorithm using the state tables defined elsewhere. To build + * a decoder you need some setup code and some glue code. Note + * that you may also need/want to change the way the NeedBits* + * macros get input data if, for example, you know the data to be + * decoded is properly aligned and oriented (doing so before running + * the decoder can be a big performance win). + * + * Consult the decoder in the TIFF library for an idea of what you + * need to define and setup to make use of these definitions. + * + * NB: to enable a debugging version of these macros define FAX3_DEBUG + * before including this file. Trace output goes to stdout. + */ + +#ifndef EndOfData +#define EndOfData() (cp >= ep) +#endif +/* + * Need <=8 or <=16 bits of input data. Unlike viewfax we + * cannot use/assume a word-aligned, properly bit swizzled + * input data set because data may come from an arbitrarily + * aligned, read-only source such as a memory-mapped file. + * Note also that the viewfax decoder does not check for + * running off the end of the input data buffer. This is + * possible for G3-encoded data because it prescans the input + * data to count EOL markers, but can cause problems for G4 + * data. In any event, we don't prescan and must watch for + * running out of data since we can't permit the library to + * scan past the end of the input data buffer. + * + * Finally, note that we must handle remaindered data at the end + * of a strip specially. The coder asks for a fixed number of + * bits when scanning for the next code. This may be more bits + * than are actually present in the data stream. If we appear + * to run out of data but still have some number of valid bits + * remaining then we makeup the requested amount with zeros and + * return successfully. If the returned data is incorrect then + * we should be called again and get a premature EOF error; + * otherwise we should get the right answer. + */ +#ifndef NeedBits8 +#define NeedBits8(n,eoflab) do { \ + if (BitsAvail < (n)) { \ + if (EndOfData()) { \ + if (BitsAvail == 0) /* no valid bits */ \ + goto eoflab; \ + BitsAvail = (n); /* pad with zeros */ \ + } else { \ + BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \ + BitsAvail += 8; \ + } \ + } \ +} while (0) +#endif +#ifndef NeedBits16 +#define NeedBits16(n,eoflab) do { \ + if (BitsAvail < (n)) { \ + if (EndOfData()) { \ + if (BitsAvail == 0) /* no valid bits */ \ + goto eoflab; \ + BitsAvail = (n); /* pad with zeros */ \ + } else { \ + BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \ + if ((BitsAvail += 8) < (n)) { \ + if (EndOfData()) { \ + /* NB: we know BitsAvail is non-zero here */ \ + BitsAvail = (n); /* pad with zeros */ \ + } else { \ + BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \ + BitsAvail += 8; \ + } \ + } \ + } \ + } \ +} while (0) +#endif +#define GetBits(n) (BitAcc & ((1<<(n))-1)) +#define ClrBits(n) do { \ + BitsAvail -= (n); \ + BitAcc >>= (n); \ +} while (0) + +#ifdef FAX3_DEBUG +static const char* StateNames[] = { + "Null ", + "Pass ", + "Horiz ", + "V0 ", + "VR ", + "VL ", + "Ext ", + "TermW ", + "TermB ", + "MakeUpW", + "MakeUpB", + "MakeUp ", + "EOL ", +}; +#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0') +#define LOOKUP8(wid,tab,eoflab) do { \ + int t; \ + NeedBits8(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ + StateNames[TabEnt->State], TabEnt->Param); \ + for (t = 0; t < TabEnt->Width; t++) \ + DEBUG_SHOW; \ + putchar('\n'); \ + fflush(stdout); \ + ClrBits(TabEnt->Width); \ +} while (0) +#define LOOKUP16(wid,tab,eoflab) do { \ + int t; \ + NeedBits16(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ + StateNames[TabEnt->State], TabEnt->Param); \ + for (t = 0; t < TabEnt->Width; t++) \ + DEBUG_SHOW; \ + putchar('\n'); \ + fflush(stdout); \ + ClrBits(TabEnt->Width); \ +} while (0) + +#define SETVAL(x) do { \ + *pa++ = RunLength + (x); \ + printf("SETVAL: %d\t%d\n", RunLength + (x), a0); \ + a0 += x; \ + RunLength = 0; \ +} while (0) +#else +#define LOOKUP8(wid,tab,eoflab) do { \ + NeedBits8(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + ClrBits(TabEnt->Width); \ +} while (0) +#define LOOKUP16(wid,tab,eoflab) do { \ + NeedBits16(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + ClrBits(TabEnt->Width); \ +} while (0) + +/* + * Append a run to the run length array for the + * current row and reset decoding state. + */ +#define SETVAL(x) do { \ + *pa++ = RunLength + (x); \ + a0 += (x); \ + RunLength = 0; \ +} while (0) +#endif + +/* + * Synchronize input decoding at the start of each + * row by scanning for an EOL (if appropriate) and + * skipping any trash data that might be present + * after a decoding error. Note that the decoding + * done elsewhere that recognizes an EOL only consumes + * 11 consecutive zero bits. This means that if EOLcnt + * is non-zero then we still need to scan for the final flag + * bit that is part of the EOL code. + */ +#define SYNC_EOL(eoflab) do { \ + if (EOLcnt == 0) { \ + for (;;) { \ + NeedBits16(11,eoflab); \ + if (GetBits(11) == 0) \ + break; \ + ClrBits(1); \ + } \ + } \ + for (;;) { \ + NeedBits8(8,eoflab); \ + if (GetBits(8)) \ + break; \ + ClrBits(8); \ + } \ + while (GetBits(1) == 0) \ + ClrBits(1); \ + ClrBits(1); /* EOL bit */ \ + EOLcnt = 0; /* reset EOL counter/flag */ \ +} while (0) + +/* + * Cleanup the array of runs after decoding a row. + * We adjust final runs to insure the user buffer is not + * overwritten and/or undecoded area is white filled. + */ +#define CLEANUP_RUNS() do { \ + if (RunLength) \ + SETVAL(0); \ + if (a0 != lastx) { \ + badlength(a0, lastx); \ + while (a0 > lastx && pa > thisrun) \ + a0 -= *--pa; \ + if (a0 < lastx) { \ + if (a0 < 0) \ + a0 = 0; \ + if ((pa-thisrun)&1) \ + SETVAL(0); \ + SETVAL(lastx - a0); \ + } else if (a0 > lastx) { \ + SETVAL(lastx); \ + SETVAL(0); \ + } \ + } \ +} while (0) + +/* + * Decode a line of 1D-encoded data. + * + * The line expanders are written as macros so that they can be reused + * but still have direct access to the local variables of the "calling" + * function. + * + * Note that unlike the original version we have to explicitly test for + * a0 >= lastx after each black/white run is decoded. This is because + * the original code depended on the input data being zero-padded to + * insure the decoder recognized an EOL before running out of data. + */ +#define EXPAND1D(eoflab) do { \ + for (;;) { \ + for (;;) { \ + LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermW: \ + SETVAL(TabEnt->Param); \ + goto doneWhite1d; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("WhiteTable", a0); \ + goto done1d; \ + } \ + } \ + doneWhite1d: \ + if (a0 >= lastx) \ + goto done1d; \ + for (;;) { \ + LOOKUP16(13, TIFFFaxBlackTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermB: \ + SETVAL(TabEnt->Param); \ + goto doneBlack1d; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("BlackTable", a0); \ + goto done1d; \ + } \ + } \ + doneBlack1d: \ + if (a0 >= lastx) \ + goto done1d; \ + if( *(pa-1) == 0 && *(pa-2) == 0 ) \ + pa -= 2; \ + } \ +eof1d: \ + prematureEOF(a0); \ + CLEANUP_RUNS(); \ + goto eoflab; \ +done1d: \ + CLEANUP_RUNS(); \ +} while (0) + +/* + * Update the value of b1 using the array + * of runs for the reference line. + */ +#define CHECK_b1 do { \ + if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \ + b1 += pb[0] + pb[1]; \ + pb += 2; \ + } \ +} while (0) + +/* + * Expand a row of 2D-encoded data. + */ +#define EXPAND2D(eoflab) do { \ + while (a0 < lastx) { \ + LOOKUP8(7, TIFFFaxMainTable, eof2d); \ + switch (TabEnt->State) { \ + case S_Pass: \ + CHECK_b1; \ + b1 += *pb++; \ + RunLength += b1 - a0; \ + a0 = b1; \ + b1 += *pb++; \ + break; \ + case S_Horiz: \ + if ((pa-thisrun)&1) { \ + for (;;) { /* black first */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVAL(TabEnt->Param); \ + goto doneWhite2da; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneWhite2da:; \ + for (;;) { /* then white */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVAL(TabEnt->Param); \ + goto doneBlack2da; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneBlack2da:; \ + } else { \ + for (;;) { /* white first */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVAL(TabEnt->Param); \ + goto doneWhite2db; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneWhite2db:; \ + for (;;) { /* then black */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVAL(TabEnt->Param); \ + goto doneBlack2db; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneBlack2db:; \ + } \ + CHECK_b1; \ + break; \ + case S_V0: \ + CHECK_b1; \ + SETVAL(b1 - a0); \ + b1 += *pb++; \ + break; \ + case S_VR: \ + CHECK_b1; \ + SETVAL(b1 - a0 + TabEnt->Param); \ + b1 += *pb++; \ + break; \ + case S_VL: \ + CHECK_b1; \ + SETVAL(b1 - a0 - TabEnt->Param); \ + b1 -= *--pb; \ + break; \ + case S_Ext: \ + *pa++ = lastx - a0; \ + extension(a0); \ + goto eol2d; \ + case S_EOL: \ + *pa++ = lastx - a0; \ + NeedBits8(4,eof2d); \ + if (GetBits(4)) \ + unexpected("EOL", a0); \ + ClrBits(4); \ + EOLcnt = 1; \ + goto eol2d; \ + default: \ + badMain2d: \ + unexpected("MainTable", a0); \ + goto eol2d; \ + badBlack2d: \ + unexpected("BlackTable", a0); \ + goto eol2d; \ + badWhite2d: \ + unexpected("WhiteTable", a0); \ + goto eol2d; \ + eof2d: \ + prematureEOF(a0); \ + CLEANUP_RUNS(); \ + goto eoflab; \ + } \ + } \ + if (RunLength) { \ + if (RunLength + a0 < lastx) { \ + /* expect a final V0 */ \ + NeedBits8(1,eof2d); \ + if (!GetBits(1)) \ + goto badMain2d; \ + ClrBits(1); \ + } \ + SETVAL(0); \ + } \ +eol2d: \ + CLEANUP_RUNS(); \ +} while (0) + +#endif /* _FAX3_ */ diff --git a/Utilities/vtktiff/tif_flush.c b/Utilities/vtktiff/tif_flush.c new file mode 100644 index 0000000..2f5c550 --- /dev/null +++ b/Utilities/vtktiff/tif_flush.c @@ -0,0 +1,67 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_flush.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +int +TIFFFlush(TIFF* tif) +{ + + if (tif->tif_mode != O_RDONLY) { + if (!TIFFFlushData(tif)) + return (0); + if ((tif->tif_flags & TIFF_DIRTYDIRECT) && + !TIFFWriteDirectory(tif)) + return (0); + } + return (1); +} + +/* + * Flush buffered data to the file. + * + * Frank Warmerdam'2000: I modified this to return 1 if TIFF_BEENWRITING + * is not set, so that TIFFFlush() will proceed to write out the directory. + * The documentation says returning 1 is an error indicator, but not having + * been writing isn't exactly a an error. Hopefully this doesn't cause + * problems for other people. + */ +int +TIFFFlushData(TIFF* tif) +{ + if ((tif->tif_flags & TIFF_BEENWRITING) == 0) + return (0); + if (tif->tif_flags & TIFF_POSTENCODE) { + tif->tif_flags &= ~TIFF_POSTENCODE; + if (!(*tif->tif_postencode)(tif)) + return (0); + } + return (TIFFFlushData1(tif)); +} + diff --git a/Utilities/vtktiff/tif_getimage.c b/Utilities/vtktiff/tif_getimage.c new file mode 100644 index 0000000..82af940 --- /dev/null +++ b/Utilities/vtktiff/tif_getimage.c @@ -0,0 +1,2421 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_getimage.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library + * + * Read and return a packed RGBA image. + */ +#include "tiffiop.h" +#include <assert.h> +#include <stdio.h> + +static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32); +static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32); +static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32); +static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32); +static int pickTileContigCase(TIFFRGBAImage*); +static int pickTileSeparateCase(TIFFRGBAImage*); + +static const char photoTag[] = "PhotometricInterpretation"; + +/* + * Check the image to see if TIFFReadRGBAImage can deal with it. + * 1/0 is returned according to whether or not the image can + * be handled. If 0 is returned, emsg contains the reason + * why it is being rejected. + */ +int +TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) +{ + TIFFDirectory* td = &tif->tif_dir; + uint16 photometric; + int colorchannels; + + switch (td->td_bitspersample) { + case 1: case 2: case 4: + case 8: case 16: + break; + default: + sprintf(emsg, "Sorry, can not handle images with %d-bit samples", + td->td_bitspersample); + return (0); + } + colorchannels = td->td_samplesperpixel - td->td_extrasamples; + if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { + switch (colorchannels) { + case 1: + photometric = PHOTOMETRIC_MINISBLACK; + break; + case 3: + photometric = PHOTOMETRIC_RGB; + break; + default: + sprintf(emsg, "Missing needed %s tag", photoTag); + return (0); + } + } + switch (photometric) { + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_PALETTE: + if (td->td_planarconfig == PLANARCONFIG_CONTIG + && td->td_samplesperpixel != 1 + && td->td_bitspersample < 8 ) { + sprintf(emsg, + "Sorry, can not handle contiguous data with %s=%d, " + "and %s=%d and Bits/Sample=%d", + photoTag, photometric, + "Samples/pixel", td->td_samplesperpixel, + td->td_bitspersample); + return (0); + } + /* + ** We should likely validate that any extra samples are either + ** to be ignored, or are alpha, and if alpha we should try to use + ** them. But for now we won't bother with this. + */ + break; + case PHOTOMETRIC_YCBCR: + if (td->td_planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d", + "Planarconfiguration", td->td_planarconfig); + return (0); + } + break; + case PHOTOMETRIC_RGB: + if (colorchannels < 3) { + sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", + "Color channels", colorchannels); + return (0); + } + break; +#ifdef CMYK_SUPPORT + case PHOTOMETRIC_SEPARATED: + if (td->td_inkset != INKSET_CMYK) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "InkSet", td->td_inkset); + return (0); + } + if (td->td_samplesperpixel < 4) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "Samples/pixel", td->td_samplesperpixel); + return (0); + } + break; +#endif + case PHOTOMETRIC_LOGL: + if (td->td_compression != COMPRESSION_SGILOG) { + sprintf(emsg, "Sorry, LogL data must have %s=%d", + "Compression", COMPRESSION_SGILOG); + return (0); + } + break; + case PHOTOMETRIC_LOGLUV: + if (td->td_compression != COMPRESSION_SGILOG && + td->td_compression != COMPRESSION_SGILOG24) { + sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", + "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); + return (0); + } + if (td->td_planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", + "Planarconfiguration", td->td_planarconfig); + return (0); + } + break; + default: + sprintf(emsg, "Sorry, can not handle image with %s=%d", + photoTag, photometric); + return (0); + } + return (1); +} + +void +TIFFRGBAImageEnd(TIFFRGBAImage* img) +{ + if (img->Map) + _TIFFfree(img->Map), img->Map = NULL; + if (img->BWmap) + _TIFFfree(img->BWmap), img->BWmap = NULL; + if (img->PALmap) + _TIFFfree(img->PALmap), img->PALmap = NULL; + if (img->ycbcr) + _TIFFfree(img->ycbcr), img->ycbcr = NULL; + + if( img->redcmap ) { + _TIFFfree( img->redcmap ); + _TIFFfree( img->greencmap ); + _TIFFfree( img->bluecmap ); + } +} + +static int +isCCITTCompression(TIFF* tif) +{ + uint16 compress; + TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); + return (compress == COMPRESSION_CCITTFAX3 || + compress == COMPRESSION_CCITTFAX4 || + compress == COMPRESSION_CCITTRLE || + compress == COMPRESSION_CCITTRLEW); +} + +int +TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) +{ + uint16* sampleinfo; + uint16 extrasamples; + uint16 planarconfig; + uint16 compress; + int colorchannels; + uint16 *red_orig, *green_orig, *blue_orig; + int n_color; + + /* Initialize to normal values */ + img->row_offset = 0; + img->col_offset = 0; + img->redcmap = NULL; + img->greencmap = NULL; + img->bluecmap = NULL; + + img->tif = tif; + img->stoponerr = stop; + TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample); + switch (img->bitspersample) { + case 1: case 2: case 4: + case 8: case 16: + break; + default: + sprintf(emsg, "Sorry, can not image with %d-bit samples", + img->bitspersample); + return (0); + } + img->alpha = 0; + TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel); + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, + &extrasamples, &sampleinfo); + if (extrasamples == 1) + switch (sampleinfo[0]) { + case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */ + case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */ + img->alpha = sampleinfo[0]; + break; + } + colorchannels = img->samplesperpixel - extrasamples; + TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress); + TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); + if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) { + switch (colorchannels) { + case 1: + if (isCCITTCompression(tif)) + img->photometric = PHOTOMETRIC_MINISWHITE; + else + img->photometric = PHOTOMETRIC_MINISBLACK; + break; + case 3: + img->photometric = PHOTOMETRIC_RGB; + break; + default: + sprintf(emsg, "Missing needed %s tag", photoTag); + return (0); + } + } + switch (img->photometric) { + case PHOTOMETRIC_PALETTE: + if (!TIFFGetField(tif, TIFFTAG_COLORMAP, + &red_orig, &green_orig, &blue_orig)) { + TIFFError(TIFFFileName(tif), "Missing required \"Colormap\" tag"); + return (0); + } + + /* copy the colormaps so we can modify them */ + n_color = (1L << img->bitspersample); + img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + if( !img->redcmap || !img->greencmap || !img->bluecmap ) { + TIFFError(TIFFFileName(tif), "Out of memory for colormap copy"); + return (0); + } + + memcpy( img->redcmap, red_orig, n_color * 2 ); + memcpy( img->greencmap, green_orig, n_color * 2 ); + memcpy( img->bluecmap, blue_orig, n_color * 2 ); + + /* fall thru... */ + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + if (planarconfig == PLANARCONFIG_CONTIG + && img->samplesperpixel != 1 + && img->bitspersample < 8 ) { + sprintf(emsg, + "Sorry, can not handle contiguous data with %s=%d, " + "and %s=%d and Bits/Sample=%d", + photoTag, img->photometric, + "Samples/pixel", img->samplesperpixel, + img->bitspersample); + return (0); + } + break; + case PHOTOMETRIC_YCBCR: + if (planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d", + "Planarconfiguration", planarconfig); + return (0); + } + /* It would probably be nice to have a reality check here. */ + if (planarconfig == PLANARCONFIG_CONTIG) + /* can rely on libjpeg to convert to RGB */ + /* XXX should restore current state on exit */ + switch (compress) { + case COMPRESSION_OJPEG: + case COMPRESSION_JPEG: + TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); + img->photometric = PHOTOMETRIC_RGB; + break; + + default: + /* do nothing */; + break; + } + break; + case PHOTOMETRIC_RGB: + if (colorchannels < 3) { + sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", + "Color channels", colorchannels); + return (0); + } + break; + case PHOTOMETRIC_SEPARATED: { + uint16 inkset; + TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); + if (inkset != INKSET_CMYK) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "InkSet", inkset); + return (0); + } + if (img->samplesperpixel < 4) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "Samples/pixel", img->samplesperpixel); + return (0); + } + break; + } + case PHOTOMETRIC_LOGL: + if (compress != COMPRESSION_SGILOG) { + sprintf(emsg, "Sorry, LogL data must have %s=%d", + "Compression", COMPRESSION_SGILOG); + return (0); + } + TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); + img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */ + img->bitspersample = 8; + break; + case PHOTOMETRIC_LOGLUV: + if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) { + sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", + "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); + return (0); + } + if (planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", + "Planarconfiguration", planarconfig); + return (0); + } + TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); + img->photometric = PHOTOMETRIC_RGB; /* little white lie */ + img->bitspersample = 8; + break; + default: + sprintf(emsg, "Sorry, can not handle image with %s=%d", + photoTag, img->photometric); + return (0); + } + img->Map = NULL; + img->BWmap = NULL; + img->PALmap = NULL; + img->ycbcr = NULL; + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height); + TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation); + img->isContig = + !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1); + if (img->isContig) { + img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig; + (void) pickTileContigCase(img); + } else { + img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate; + (void) pickTileSeparateCase(img); + } + return (1); +} + +int +TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + if (img->get == NULL) { + TIFFError(TIFFFileName(img->tif), "No \"get\" routine setup"); + return (0); + } + if (img->put.any == NULL) { + TIFFError(TIFFFileName(img->tif), + "No \"put\" routine setupl; probably can not handle image format"); + return (0); + } + return (*img->get)(img, raster, w, h); +} + +/* + * Read the specified image into an ABGR-format raster. + */ +int +TEXPORT TIFFReadRGBAImage(TIFF* tif, + uint32 rwidth, uint32 rheight, uint32* raster, int stop) +{ + char emsg[1024]; + TIFFRGBAImage img; + int ok; + + if (TIFFRGBAImageBegin(&img, tif, stop, emsg)) { + /* XXX verify rwidth and rheight against width and height */ + ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth, + rwidth, img.height); + TIFFRGBAImageEnd(&img); + } else { + TIFFError(TIFFFileName(tif), emsg); + ok = 0; + } + return (ok); +} + +static uint32 +setorientation(TIFFRGBAImage* img, uint32 h) +{ + TIFF* tif = img->tif; + uint32 y; + + switch (img->orientation) { + case ORIENTATION_BOTRIGHT: + case ORIENTATION_RIGHTBOT: /* XXX */ + case ORIENTATION_LEFTBOT: /* XXX */ + TIFFWarning(TIFFFileName(tif), "using bottom-left orientation"); + img->orientation = ORIENTATION_BOTLEFT; + /* fall thru... */ + case ORIENTATION_BOTLEFT: + y = 0; + break; + case ORIENTATION_TOPRIGHT: + case ORIENTATION_RIGHTTOP: /* XXX */ + case ORIENTATION_LEFTTOP: /* XXX */ + default: + TIFFWarning(TIFFFileName(tif), "using top-left orientation"); + img->orientation = ORIENTATION_TOPLEFT; + /* fall thru... */ + case ORIENTATION_TOPLEFT: + y = h-1; + break; + } + return (y); +} + +/* + * Get an tile-organized image that has + * PlanarConfiguration contiguous if SamplesPerPixel > 1 + * or + * SamplesPerPixel == 1 + */ +static int +gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileContigRoutine put = img->put.contig; + uint16 orientation; + uint32 col, row, y, rowstoread, ret = 1; + uint32 pos; + uint32 tw, th; + u_char* buf; + int32 fromskew, toskew; + uint32 nrow; + + buf = (u_char*) _TIFFmalloc(TIFFTileSize(tif)); + if (buf == 0) { + TIFFError(TIFFFileName(tif), "No space for tile buffer"); + return (0); + } + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + y = setorientation(img, h); + orientation = img->orientation; + toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? tw+w : tw-w); + for (row = 0; row < h; row += nrow) + { + rowstoread = th - (row + img->row_offset) % th; + nrow = (row + rowstoread > h ? h - row : rowstoread); + for (col = 0; col < w; col += tw) + { + if (TIFFReadTile(tif, buf, col+img->col_offset, + row+img->row_offset, 0, 0) < 0 && img->stoponerr) + { + ret = 0; + break; + } + + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); + + if (col + tw > w) + { + /* + * Tile is clipped horizontally. Calculate + * visible portion and skewing factors. + */ + uint32 npix = w - col; + fromskew = tw - npix; + (*put)(img, raster+y*w+col, col, y, + npix, nrow, fromskew, toskew + fromskew, buf + pos); + } + else + { + (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos); + } + } + + y += (orientation == ORIENTATION_TOPLEFT ? -(int32) nrow : (int32) nrow); + } + _TIFFfree(buf); + return (ret); +} + +/* + * Get an tile-organized image that has + * SamplesPerPixel > 1 + * PlanarConfiguration separated + * We assume that all such images are RGB. + */ +static int +gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileSeparateRoutine put = img->put.separate; + uint16 orientation; + uint32 col, row, y, rowstoread; + uint32 pos; + uint32 tw, th; + u_char* buf; + u_char* r; + u_char* g; + u_char* b; + u_char* a; + tsize_t tilesize; + int32 fromskew, toskew; + int alpha = img->alpha; + uint32 nrow; + int ret = 1; + + tilesize = TIFFTileSize(tif); + buf = (u_char*) _TIFFmalloc(4*tilesize); + if (buf == 0) { + TIFFError(TIFFFileName(tif), "No space for tile buffer"); + return (0); + } + r = buf; + g = r + tilesize; + b = g + tilesize; + a = b + tilesize; + if (!alpha) + memset(a, 0xff, tilesize); + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + y = setorientation(img, h); + orientation = img->orientation; + toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? tw+w : tw-w); + for (row = 0; row < h; row += nrow) + { + rowstoread = th - (row + img->row_offset) % th; + nrow = (row + rowstoread > h ? h - row : rowstoread); + for (col = 0; col < w; col += tw) + { + if (TIFFReadTile(tif, r, col+img->col_offset, + row+img->row_offset,0,0) < 0 && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadTile(tif, g, col+img->col_offset, + row+img->row_offset,0,1) < 0 && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadTile(tif, b, col+img->col_offset, + row+img->row_offset,0,2) < 0 && img->stoponerr) + { + ret = 0; + break; + } + if (alpha && TIFFReadTile(tif,a,col+img->col_offset, + row+img->row_offset,0,3) < 0 && img->stoponerr) + { + ret = 0; + break; + } + + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); + + if (col + tw > w) + { + /* + * Tile is clipped horizontally. Calculate + * visible portion and skewing factors. + */ + uint32 npix = w - col; + fromskew = tw - npix; + (*put)(img, raster+y*w+col, col, y, + npix, nrow, fromskew, toskew + fromskew, + r + pos, g + pos, b + pos, a + pos); + } + else + { + (*put)(img, raster+y*w+col, col, y, + tw, nrow, 0, toskew, r + pos, g + pos, b + pos, a + pos); + } + } + + y += (orientation == ORIENTATION_TOPLEFT ?-(int32) nrow : (int32) nrow); + } + _TIFFfree(buf); + return (ret); +} + +/* + * Get a strip-organized image that has + * PlanarConfiguration contiguous if SamplesPerPixel > 1 + * or + * SamplesPerPixel == 1 + */ +static int +gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileContigRoutine put = img->put.contig; + uint16 orientation; + uint32 row, y, nrow, rowstoread; + uint32 pos; + u_char* buf; + uint32 rowsperstrip; + uint32 imagewidth = img->width; + tsize_t scanline; + int32 fromskew, toskew; + int ret = 1; + + buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif)); + if (buf == 0) { + TIFFError(TIFFFileName(tif), "No space for strip buffer"); + return (0); + } + y = setorientation(img, h); + orientation = img->orientation; + toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? w+w : w-w); + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + scanline = TIFFScanlineSize(tif); + fromskew = (w < imagewidth ? imagewidth - w : 0); + for (row = 0; row < h; row += nrow) + { + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + if (TIFFReadEncodedStrip(tif, + TIFFComputeStrip(tif,row+img->row_offset, 0), + buf, + ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + + pos = ((row + img->row_offset) % rowsperstrip) * scanline; + (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos); + y += (orientation == ORIENTATION_TOPLEFT ?-(int32) nrow : (int32) nrow); + } + _TIFFfree(buf); + return (ret); +} + +/* + * Get a strip-organized image with + * SamplesPerPixel > 1 + * PlanarConfiguration separated + * We assume that all such images are RGB. + */ +static int +gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileSeparateRoutine put = img->put.separate; + uint16 orientation; + u_char *buf; + u_char *r, *g, *b, *a; + uint32 row, y, nrow, rowstoread; + uint32 pos; + tsize_t scanline; + uint32 rowsperstrip, offset_row; + uint32 imagewidth = img->width; + tsize_t stripsize; + int32 fromskew, toskew; + int alpha = img->alpha; + int ret = 1; + + stripsize = TIFFStripSize(tif); + r = buf = (u_char *)_TIFFmalloc(4*stripsize); + if (buf == 0) { + TIFFError(TIFFFileName(tif), "No space for tile buffer"); + return (0); + } + g = r + stripsize; + b = g + stripsize; + a = b + stripsize; + if (!alpha) + memset(a, 0xff, stripsize); + y = setorientation(img, h); + orientation = img->orientation; + toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? w+w : w-w); + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + scanline = TIFFScanlineSize(tif); + fromskew = (w < imagewidth ? imagewidth - w : 0); + for (row = 0; row < h; row += nrow) + { + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + offset_row = row + img->row_offset; + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), + r, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), + g, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), + b, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + if (alpha && + (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3), + a, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr)) + { + ret = 0; + break; + } + + pos = ((row + img->row_offset) % rowsperstrip) * scanline; + (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, r + pos, g + pos, + b + pos, a + pos); + y += (orientation == ORIENTATION_TOPLEFT ? -(int32) nrow : (int32) nrow); + } + _TIFFfree(buf); + return (ret); +} + +/* + * The following routines move decoded data returned + * from the TIFF library into rasters filled with packed + * ABGR pixels (i.e. suitable for passing to lrecwrite.) + * + * The routines have been created according to the most + * important cases and optimized. pickTileContigCase and + * pickTileSeparateCase analyze the parameters and select + * the appropriate "put" routine to use. + */ +#define REPEAT8(op) REPEAT4(op); REPEAT4(op) +#define REPEAT4(op) REPEAT2(op); REPEAT2(op) +#define REPEAT2(op) op; op +#define CASE8(x,op) \ + switch (x) { \ + case 7: op; case 6: op; case 5: op; \ + case 4: op; case 3: op; case 2: op; \ + case 1: op; \ + } +#define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } +#define NOP + +#define UNROLL8(w, op1, op2) { \ + uint32 _x; \ + for (_x = w; _x >= 8; _x -= 8) { \ + op1; \ + REPEAT8(op2); \ + } \ + if (_x > 0) { \ + op1; \ + CASE8(_x,op2); \ + } \ +} +#define UNROLL4(w, op1, op2) { \ + uint32 _x; \ + for (_x = w; _x >= 4; _x -= 4) { \ + op1; \ + REPEAT4(op2); \ + } \ + if (_x > 0) { \ + op1; \ + CASE4(_x,op2); \ + } \ +} +#define UNROLL2(w, op1, op2) { \ + uint32 _x; \ + for (_x = w; _x >= 2; _x -= 2) { \ + op1; \ + REPEAT2(op2); \ + } \ + if (_x) { \ + op1; \ + op2; \ + } \ +} + +#define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; } +#define SKEW4(r,g,b,a,skew) { r += skew; g += skew; b += skew; a+= skew; } + +#define A1 ((uint32)(0xff000000)) +#define PACK(r,g,b) \ + ((uint32)(r)|(uint32)((g)<<8)|(uint32)((b)<<16)|A1) +#define PACK4(r,g,b,a) \ + ((uint32)(r)|(uint32)((g)<<8)|(uint32)((b)<<16)|(uint32)((a)<<24)) +#define W2B(v) (((v)>>8)&0xff) +#define PACKW(r,g,b) \ + ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1) +#define PACKW4(r,g,b,a) \ + ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24)) + +#define DECLAREContigPutFunc(name) \ +static void name(\ + TIFFRGBAImage* img, \ + uint32* cp, \ + uint32 x, uint32 y, \ + uint32 w, uint32 h, \ + int32 fromskew, int32 toskew, \ + u_char* pp \ +) + +/* + * 8-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put8bitcmaptile) +{ + uint32** PALmap = img->PALmap; + int samplesperpixel = img->samplesperpixel; + + (void) y; + while (h-- > 0) { + for (x = w; x-- > 0;) + { + *cp++ = PALmap[*pp][0]; + pp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 4-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put4bitcmaptile) +{ + uint32** PALmap = img->PALmap; + + (void) x; (void) y; + fromskew /= 2; + while (h-- > 0) { + uint32* bw; + UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 2-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put2bitcmaptile) +{ + uint32** PALmap = img->PALmap; + + (void) x; (void) y; + fromskew /= 4; + while (h-- > 0) { + uint32* bw; + UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 1-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put1bitcmaptile) +{ + uint32** PALmap = img->PALmap; + + (void) x; (void) y; + fromskew /= 8; + while (h-- > 0) { + uint32* bw; + UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(putgreytile) +{ + int samplesperpixel = img->samplesperpixel; + uint32** BWmap = img->BWmap; + + (void) y; + while (h-- > 0) { + for (x = w; x-- > 0;) + { + *cp++ = BWmap[*pp][0]; + pp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 16-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(put16bitbwtile) +{ + int samplesperpixel = img->samplesperpixel; + uint32** BWmap = img->BWmap; + + (void) y; + while (h-- > 0) { + uint16 *wp = (uint16 *) pp; + + for (x = w; x-- > 0;) + { + /* use high order byte of 16bit value */ + + *cp++ = BWmap[*wp >> 8][0]; + pp += 2 * samplesperpixel; + wp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 1-bit bilevel => colormap/RGB + */ +DECLAREContigPutFunc(put1bitbwtile) +{ + uint32** BWmap = img->BWmap; + + (void) x; (void) y; + fromskew /= 8; + while (h-- > 0) { + uint32* bw; + UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 2-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(put2bitbwtile) +{ + uint32** BWmap = img->BWmap; + + (void) x; (void) y; + fromskew /= 4; + while (h-- > 0) { + uint32* bw; + UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 4-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(put4bitbwtile) +{ + uint32** BWmap = img->BWmap; + + (void) x; (void) y; + fromskew /= 2; + while (h-- > 0) { + uint32* bw; + UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed samples, no Map => RGB + */ +DECLAREContigPutFunc(putRGBcontig8bittile) +{ + int samplesperpixel = img->samplesperpixel; + + (void) x; (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + UNROLL8(w, NOP, + *cp++ = PACK(pp[0], pp[1], pp[2]); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed samples, w/ Map => RGB + */ +DECLAREContigPutFunc(putRGBcontig8bitMaptile) +{ + TIFFRGBValue* Map = img->Map; + int samplesperpixel = img->samplesperpixel; + + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + for (x = w; x-- > 0;) { + *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]); + pp += samplesperpixel; + } + pp += fromskew; + cp += toskew; + } +} + +/* + * 8-bit packed samples => RGBA w/ associated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBAAcontig8bittile) +{ + int samplesperpixel = img->samplesperpixel; + + (void) x; (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + UNROLL8(w, NOP, + *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed samples => RGBA w/ unassociated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBUAcontig8bittile) +{ + int samplesperpixel = img->samplesperpixel; + + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + uint32 r, g, b, a; + for (x = w; x-- > 0;) { + a = pp[3]; + r = (pp[0] * a) / 255; + g = (pp[1] * a) / 255; + b = (pp[2] * a) / 255; + *cp++ = PACK4(r,g,b,a); + pp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 16-bit packed samples => RGB + */ +DECLAREContigPutFunc(putRGBcontig16bittile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + for (x = w; x-- > 0;) { + *cp++ = PACKW(wp[0], wp[1], wp[2]); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } +} + +/* + * 16-bit packed samples => RGBA w/ associated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBAAcontig16bittile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + for (x = w; x-- > 0;) { + *cp++ = PACKW4(wp[0], wp[1], wp[2], wp[3]); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } +} + +/* + * 16-bit packed samples => RGBA w/ unassociated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBUAcontig16bittile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + uint32 r,g,b,a; + /* + * We shift alpha down four bits just in case unsigned + * arithmetic doesn't handle the full range. + * We still have plenty of accuracy, since the output is 8 bits. + * So we have (r * 0xffff) * (a * 0xfff)) = r*a * (0xffff*0xfff) + * Since we want r*a * 0xff for eight bit output, + * we divide by (0xffff * 0xfff) / 0xff == 0x10eff. + */ + for (x = w; x-- > 0;) { + a = wp[3] >> 4; + r = (wp[0] * a) / 0x10eff; + g = (wp[1] * a) / 0x10eff; + b = (wp[2] * a) / 0x10eff; + *cp++ = PACK4(r,g,b,a); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } +} + +/* + * 8-bit packed CMYK samples w/o Map => RGB + * + * NB: The conversion of CMYK->RGB is *very* crude. + */ +DECLAREContigPutFunc(putRGBcontig8bitCMYKtile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 r, g, b, k; + + (void) x; (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + UNROLL8(w, NOP, + k = 255 - pp[3]; + r = (k*(255-pp[0]))/255; + g = (k*(255-pp[1]))/255; + b = (k*(255-pp[2]))/255; + *cp++ = PACK(r, g, b); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed CMYK samples w/Map => RGB + * + * NB: The conversion of CMYK->RGB is *very* crude. + */ +DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile) +{ + int samplesperpixel = img->samplesperpixel; + TIFFRGBValue* Map = img->Map; + uint16 r, g, b, k; + + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + for (x = w; x-- > 0;) { + k = 255 - pp[3]; + r = (k*(255-pp[0]))/255; + g = (k*(255-pp[1]))/255; + b = (k*(255-pp[2]))/255; + *cp++ = PACK(Map[r], Map[g], Map[b]); + pp += samplesperpixel; + } + pp += fromskew; + cp += toskew; + } +} + +#define DECLARESepPutFunc(name) \ +static void name(\ + TIFFRGBAImage* img,\ + uint32* cp,\ + uint32 x, uint32 y, \ + uint32 w, uint32 h,\ + int32 fromskew, int32 toskew,\ + u_char* r, u_char* g, u_char* b, u_char* a\ +) + +/* + * 8-bit unpacked samples => RGB + */ +DECLARESepPutFunc(putRGBseparate8bittile) +{ + (void) img; (void) x; (void) y; (void) a; + while (h-- > 0) { + UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++)); + SKEW(r, g, b, fromskew); + cp += toskew; + } +} + +/* + * 8-bit unpacked samples => RGB + */ +DECLARESepPutFunc(putRGBseparate8bitMaptile) +{ + TIFFRGBValue* Map = img->Map; + + (void) y; (void) a; + while (h-- > 0) { + for (x = w; x > 0; x--) + *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]); + SKEW(r, g, b, fromskew); + cp += toskew; + } +} + +/* + * 8-bit unpacked samples => RGBA w/ associated alpha + */ +DECLARESepPutFunc(putRGBAAseparate8bittile) +{ + (void) img; (void) x; (void) y; + while (h-- > 0) { + UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++)); + SKEW4(r, g, b, a, fromskew); + cp += toskew; + } +} + +/* + * 8-bit unpacked samples => RGBA w/ unassociated alpha + */ +DECLARESepPutFunc(putRGBUAseparate8bittile) +{ + (void) img; (void) y; + while (h-- > 0) { + uint32 rv, gv, bv, av; + for (x = w; x-- > 0;) { + av = *a++; + rv = (*r++ * av) / 255; + gv = (*g++ * av) / 255; + bv = (*b++ * av) / 255; + *cp++ = PACK4(rv,gv,bv,av); + } + SKEW4(r, g, b, a, fromskew); + cp += toskew; + } +} + +/* + * 16-bit unpacked samples => RGB + */ +DECLARESepPutFunc(putRGBseparate16bittile) +{ + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + + (void) img; (void) y; (void) a; + while (h-- > 0) { + for (x = 0; x < w; x++) + *cp++ = PACKW(*wr++, *wg++, *wb++); + SKEW(wr, wg, wb, fromskew); + cp += toskew; + } +} + +/* + * 16-bit unpacked samples => RGBA w/ associated alpha + */ +DECLARESepPutFunc(putRGBAAseparate16bittile) +{ + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + uint16 *wa = (uint16*) a; + + (void) img; (void) y; + while (h-- > 0) { + for (x = 0; x < w; x++) + *cp++ = PACKW4(*wr++, *wg++, *wb++, *wa++); + SKEW4(wr, wg, wb, wa, fromskew); + cp += toskew; + } +} + +/* + * 16-bit unpacked samples => RGBA w/ unassociated alpha + */ +DECLARESepPutFunc(putRGBUAseparate16bittile) +{ + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + uint16 *wa = (uint16*) a; + + (void) img; (void) y; + while (h-- > 0) { + uint32 r,g,b,a; + /* + * We shift alpha down four bits just in case unsigned + * arithmetic doesn't handle the full range. + * We still have plenty of accuracy, since the output is 8 bits. + * So we have (r * 0xffff) * (a * 0xfff)) = r*a * (0xffff*0xfff) + * Since we want r*a * 0xff for eight bit output, + * we divide by (0xffff * 0xfff) / 0xff == 0x10eff. + */ + for (x = w; x-- > 0;) { + a = *wa++ >> 4; + r = (*wr++ * a) / 0x10eff; + g = (*wg++ * a) / 0x10eff; + b = (*wb++ * a) / 0x10eff; + *cp++ = PACK4(r,g,b,a); + } + SKEW4(wr, wg, wb, wa, fromskew); + cp += toskew; + } +} + +/* + * YCbCr -> RGB conversion and packing routines. The colorspace + * conversion algorithm comes from the IJG v5a code; see below + * for more information on how it works. + */ + +#define YCbCrtoRGB(dst, yc) { \ + int Y = (yc); \ + dst = PACK( \ + clamptab[Y+Crrtab[Cr]], \ + clamptab[Y + (int)((Cbgtab[Cb]+Crgtab[Cr])>>16)], \ + clamptab[Y+Cbbtab[Cb]]); \ +} +#define YCbCrSetup \ + TIFFYCbCrToRGB* ycbcr = img->ycbcr; \ + int* Crrtab = ycbcr->Cr_r_tab; \ + int* Cbbtab = ycbcr->Cb_b_tab; \ + int32* Crgtab = ycbcr->Cr_g_tab; \ + int32* Cbgtab = ycbcr->Cb_g_tab; \ + TIFFRGBValue* clamptab = ycbcr->clamptab + +/* + * 8-bit packed YCbCr samples => RGB + * This function is generic for different sampling sizes, + * and can handle blocks sizes that aren't multiples of the + * sampling size. However, it is substantially less optimized + * than the specific sampling cases. It is used as a fallback + * for difficult blocks. + */ +#ifdef notdef +static void putcontig8bitYCbCrGenericTile( + TIFFRGBAImage* img, + uint32* cp, + uint32 x, uint32 y, + uint32 w, uint32 h, + int32 fromskew, int32 toskew, + u_char* pp, + int h_group, + int v_group ) + +{ + YCbCrSetup; + + uint32* cp1 = cp+w+toskew; + uint32* cp2 = cp1+w+toskew; + uint32* cp3 = cp2+w+toskew; + int32 incr = 3*w+4*toskew; + int Cb, Cr; + int group_size = v_group * h_group + 2; + + (void) y; + fromskew = (fromskew * group_size) / h_group; + + for( yy = 0; yy < h; yy++ ) + { + u_char *pp_line; + int y_line_group = yy / v_group; + int y_remainder = yy - y_line_group * v_group; + + pp_line = pp + v_line_group * + + + for( xx = 0; xx < w; xx++ ) + { + Cb = pp + } + } + for (; h >= 4; h -= 4) { + x = w>>2; + do { + Cb = pp[16]; + Cr = pp[17]; + + YCbCrtoRGB(cp [0], pp[ 0]); + YCbCrtoRGB(cp [1], pp[ 1]); + YCbCrtoRGB(cp [2], pp[ 2]); + YCbCrtoRGB(cp [3], pp[ 3]); + YCbCrtoRGB(cp1[0], pp[ 4]); + YCbCrtoRGB(cp1[1], pp[ 5]); + YCbCrtoRGB(cp1[2], pp[ 6]); + YCbCrtoRGB(cp1[3], pp[ 7]); + YCbCrtoRGB(cp2[0], pp[ 8]); + YCbCrtoRGB(cp2[1], pp[ 9]); + YCbCrtoRGB(cp2[2], pp[10]); + YCbCrtoRGB(cp2[3], pp[11]); + YCbCrtoRGB(cp3[0], pp[12]); + YCbCrtoRGB(cp3[1], pp[13]); + YCbCrtoRGB(cp3[2], pp[14]); + YCbCrtoRGB(cp3[3], pp[15]); + + cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; + pp += 18; + } while (--x); + cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + pp += fromskew; + } +} +#endif + +/* + * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr44tile) +{ + YCbCrSetup; + uint32* cp1 = cp+w+toskew; + uint32* cp2 = cp1+w+toskew; + uint32* cp3 = cp2+w+toskew; + int32 incr = 3*w+4*toskew; + + (void) y; + /* adjust fromskew */ + fromskew = (fromskew * 18) / 4; + if ((h & 3) == 0 && (w & 3) == 0) { + for (; h >= 4; h -= 4) { + x = w>>2; + do { + int Cb = pp[16]; + int Cr = pp[17]; + + YCbCrtoRGB(cp [0], pp[ 0]); + YCbCrtoRGB(cp [1], pp[ 1]); + YCbCrtoRGB(cp [2], pp[ 2]); + YCbCrtoRGB(cp [3], pp[ 3]); + YCbCrtoRGB(cp1[0], pp[ 4]); + YCbCrtoRGB(cp1[1], pp[ 5]); + YCbCrtoRGB(cp1[2], pp[ 6]); + YCbCrtoRGB(cp1[3], pp[ 7]); + YCbCrtoRGB(cp2[0], pp[ 8]); + YCbCrtoRGB(cp2[1], pp[ 9]); + YCbCrtoRGB(cp2[2], pp[10]); + YCbCrtoRGB(cp2[3], pp[11]); + YCbCrtoRGB(cp3[0], pp[12]); + YCbCrtoRGB(cp3[1], pp[13]); + YCbCrtoRGB(cp3[2], pp[14]); + YCbCrtoRGB(cp3[3], pp[15]); + + cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; + pp += 18; + } while (--x); + cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + pp += fromskew; + } + } else { + while (h > 0) { + for (x = w; x > 0;) { + int Cb = pp[16]; + int Cr = pp[17]; + switch (x) { + default: + switch (h) { + default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 3: + switch (h) { + default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 2: + switch (h) { + default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 1: + switch (h) { + default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + } + if (x < 4) { + cp += x; cp1 += x; cp2 += x; cp3 += x; + x = 0; + } + else { + cp += 4; cp1 += 4; cp2 += 4; cp3 += 4; + x -= 4; + } + pp += 18; + } + if (h <= 4) + break; + h -= 4; + cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + pp += fromskew; + } + } +} + +/* + * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr42tile) +{ + YCbCrSetup; + uint32* cp1 = cp+w+toskew; + int32 incr = 2*toskew+w; + + (void) y; + fromskew = (fromskew * 10) / 4; + if ((h & 3) == 0 && (w & 1) == 0) { + for (; h >= 2; h -= 2) { + x = w>>2; + do { + int Cb = pp[8]; + int Cr = pp[9]; + + YCbCrtoRGB(cp [0], pp[0]); + YCbCrtoRGB(cp [1], pp[1]); + YCbCrtoRGB(cp [2], pp[2]); + YCbCrtoRGB(cp [3], pp[3]); + YCbCrtoRGB(cp1[0], pp[4]); + YCbCrtoRGB(cp1[1], pp[5]); + YCbCrtoRGB(cp1[2], pp[6]); + YCbCrtoRGB(cp1[3], pp[7]); + + cp += 4, cp1 += 4; + pp += 10; + } while (--x); + cp += incr, cp1 += incr; + pp += fromskew; + } + } else { + while (h > 0) { + for (x = w; x > 0;) { + int Cb = pp[8]; + int Cr = pp[9]; + switch (x) { + default: + switch (h) { + default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 3: + switch (h) { + default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 2: + switch (h) { + default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 1: + switch (h) { + default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + } + if (x < 4) { + cp += x; cp1 += x; + x = 0; + } + else { + cp += 4; cp1 += 4; + x -= 4; + } + pp += 10; + } + if (h <= 2) + break; + h -= 2; + cp += incr, cp1 += incr; + pp += fromskew; + } + } +} + +/* + * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr41tile) +{ + YCbCrSetup; + + (void) y; + /* XXX adjust fromskew */ + do { + x = w>>2; + do { + int Cb = pp[4]; + int Cr = pp[5]; + + YCbCrtoRGB(cp [0], pp[0]); + YCbCrtoRGB(cp [1], pp[1]); + YCbCrtoRGB(cp [2], pp[2]); + YCbCrtoRGB(cp [3], pp[3]); + + cp += 4; + pp += 6; + } while (--x); + + if( (w&3) != 0 ) + { + int Cb = pp[4]; + int Cr = pp[5]; + + switch( (w&3) ) { + case 3: YCbCrtoRGB(cp [2], pp[2]); + case 2: YCbCrtoRGB(cp [1], pp[1]); + case 1: YCbCrtoRGB(cp [0], pp[0]); + case 0: break; + } + + cp += (w&3); + pp += 6; + } + + cp += toskew; + pp += fromskew; + } while (--h); + +} + +/* + * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr22tile) +{ + YCbCrSetup; + uint32* cp1 = cp+w+toskew; + int32 incr = 2*toskew+w; + + (void) y; + fromskew = (fromskew * 6) / 2; + if ((h & 1) == 0 && (w & 1) == 0) { + for (; h >= 2; h -= 2) { + x = w>>1; + do { + int Cb = pp[4]; + int Cr = pp[5]; + + YCbCrtoRGB(cp [0], pp[0]); + YCbCrtoRGB(cp [1], pp[1]); + YCbCrtoRGB(cp1[0], pp[2]); + YCbCrtoRGB(cp1[1], pp[3]); + + cp += 2, cp1 += 2; + pp += 6; + } while (--x); + cp += incr, cp1 += incr; + pp += fromskew; + } + } else { + while (h > 0) { + for (x = w; x > 0;) { + int Cb = pp[4]; + int Cr = pp[5]; + switch (x) { + default: + switch (h) { + default: YCbCrtoRGB(cp1[1], pp[ 3]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 1: + switch (h) { + default: YCbCrtoRGB(cp1[0], pp[ 2]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + } + if (x < 2) { + cp += x; cp1 += x; + x = 0; + } + else { + cp += 2; cp1 += 2; + x -= 2; + } + pp += 6; + } + if (h <= 2) + break; + h -= 2; + cp += incr, cp1 += incr; + pp += fromskew; + } + } +} + +/* + * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr21tile) +{ + YCbCrSetup; + + (void) y; + fromskew = (fromskew * 4) / 2; + do { + x = w>>1; + do { + int Cb = pp[2]; + int Cr = pp[3]; + + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[1], pp[1]); + + cp += 2; + pp += 4; + } while (--x); + + if( (w&1) != 0 ) + { + int Cb = pp[2]; + int Cr = pp[3]; + + YCbCrtoRGB(cp [0], pp[0]); + + cp += 1; + pp += 4; + } + + cp += toskew; + pp += fromskew; + } while (--h); +} + +/* + * 8-bit packed YCbCr samples w/ no subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr11tile) +{ + YCbCrSetup; + + (void) y; + fromskew *= 3; + do { + x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */ + do { + int Cb = pp[1]; + int Cr = pp[2]; + + YCbCrtoRGB(*cp++, pp[0]); + + pp += 3; + } while (--x); + cp += toskew; + pp += fromskew; + } while (--h); +} +#undef YCbCrSetup +#undef YCbCrtoRGB + +#define LumaRed coeffs[0] +#define LumaGreen coeffs[1] +#define LumaBlue coeffs[2] +#define SHIFT 16 +#define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5)) +#define ONE_HALF ((int32)(1<<(SHIFT-1))) + +/* + * Initialize the YCbCr->RGB conversion tables. The conversion + * is done according to the 6.0 spec: + * + * R = Y + Cr*(2 - 2*LumaRed) + * B = Y + Cb*(2 - 2*LumaBlue) + * G = Y + * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen + * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen + * + * To avoid floating point arithmetic the fractional constants that + * come out of the equations are represented as fixed point values + * in the range 0...2^16. We also eliminate multiplications by + * pre-calculating possible values indexed by Cb and Cr (this code + * assumes conversion is being done for 8-bit samples). + */ +static void +TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, TIFF* tif) +{ + TIFFRGBValue* clamptab; + float* coeffs; + int i; + + clamptab = (TIFFRGBValue*)( + (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))); + _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ + ycbcr->clamptab = (clamptab += 256); + for (i = 0; i < 256; i++) + clamptab[i] = i; + _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ + TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs); + _TIFFmemcpy(ycbcr->coeffs, coeffs, 3*sizeof (float)); + { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); + float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); + float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); + float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); + int x; + + ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); + ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; + ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); + ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; + /* + * i is the actual input pixel value in the range 0..255 + * Cb and Cr values are in the range -128..127 (actually + * they are in a range defined by the ReferenceBlackWhite + * tag) so there is some range shifting to do here when + * constructing tables indexed by the raw pixel data. + * + * XXX handle ReferenceBlackWhite correctly to calculate + * Cb/Cr values to use in constructing the tables. + */ + for (i = 0, x = -128; i < 256; i++, x++) { + ycbcr->Cr_r_tab[i] = (int)((D1*x + ONE_HALF)>>SHIFT); + ycbcr->Cb_b_tab[i] = (int)((D3*x + ONE_HALF)>>SHIFT); + ycbcr->Cr_g_tab[i] = D2*x; + ycbcr->Cb_g_tab[i] = D4*x + ONE_HALF; + } + } +} +#undef SHIFT +#undef ONE_HALF +#undef FIX +#undef LumaBlue +#undef LumaGreen +#undef LumaRed + +static tileContigRoutine +initYCbCrConversion(TIFFRGBAImage* img) +{ + uint16 hs, vs; + + if (img->ycbcr == NULL) { + img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( + TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)) + + 4*256*sizeof (TIFFRGBValue) + + 2*256*sizeof (int) + + 2*256*sizeof (int32) + ); + if (img->ycbcr == NULL) { + TIFFError(TIFFFileName(img->tif), + "No space for YCbCr->RGB conversion state"); + return (NULL); + } + TIFFYCbCrToRGBInit(img->ycbcr, img->tif); + } else { + float* coeffs; + + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &coeffs); + if (_TIFFmemcmp(coeffs, img->ycbcr->coeffs, 3*sizeof (float)) != 0) + TIFFYCbCrToRGBInit(img->ycbcr, img->tif); + } + /* + * The 6.0 spec says that subsampling must be + * one of 1, 2, or 4, and that vertical subsampling + * must always be <= horizontal subsampling; so + * there are only a few possibilities and we just + * enumerate the cases. + */ + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); + switch ((hs<<4)|vs) { + case 0x44: return (&putcontig8bitYCbCr44tile); + case 0x42: return (&putcontig8bitYCbCr42tile); + case 0x41: return (&putcontig8bitYCbCr41tile); + case 0x22: return (&putcontig8bitYCbCr22tile); + case 0x21: return (&putcontig8bitYCbCr21tile); + case 0x11: return (&putcontig8bitYCbCr11tile); + } + return (NULL); +} + +/* + * Greyscale images with less than 8 bits/sample are handled + * with a table to avoid lots of shifts and masks. The table + * is setup so that put*bwtile (below) can retrieve 8/bitspersample + * pixel values simply by indexing into the table with one + * number. + */ +static int +makebwmap(TIFFRGBAImage* img) +{ + TIFFRGBValue* Map = img->Map; + int bitspersample = img->bitspersample; + int nsamples = 8 / bitspersample; + int i; + uint32* p; + + if( nsamples == 0 ) + nsamples = 1; + + img->BWmap = (uint32**) _TIFFmalloc( + 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); + if (img->BWmap == NULL) { + TIFFError(TIFFFileName(img->tif), "No space for B&W mapping table"); + return (0); + } + p = (uint32*)(img->BWmap + 256); + for (i = 0; i < 256; i++) { + TIFFRGBValue c; + img->BWmap[i] = p; + switch (bitspersample) { +#define GREY(x) c = Map[x]; *p++ = PACK(c,c,c); + case 1: + GREY(i>>7); + GREY((i>>6)&1); + GREY((i>>5)&1); + GREY((i>>4)&1); + GREY((i>>3)&1); + GREY((i>>2)&1); + GREY((i>>1)&1); + GREY(i&1); + break; + case 2: + GREY(i>>6); + GREY((i>>4)&3); + GREY((i>>2)&3); + GREY(i&3); + break; + case 4: + GREY(i>>4); + GREY(i&0xf); + break; + case 8: + case 16: + GREY(i); + break; + } +#undef GREY + } + return (1); +} + +/* + * Construct a mapping table to convert from the range + * of the data samples to [0,255] --for display. This + * process also handles inverting B&W images when needed. + */ +static int +setupMap(TIFFRGBAImage* img) +{ + int32 x, range; + + range = (int32)((1L<<img->bitspersample)-1); + + /* treat 16 bit the same as eight bit */ + if( img->bitspersample == 16 ) + range = (int32) 255; + + img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue)); + if (img->Map == NULL) { + TIFFError(TIFFFileName(img->tif), + "No space for photometric conversion table"); + return (0); + } + if (img->photometric == PHOTOMETRIC_MINISWHITE) { + for (x = 0; x <= range; x++) + img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range); + } else { + for (x = 0; x <= range; x++) + img->Map[x] = (TIFFRGBValue) ((x * 255) / range); + } + if (img->bitspersample <= 16 && + (img->photometric == PHOTOMETRIC_MINISBLACK || + img->photometric == PHOTOMETRIC_MINISWHITE)) { + /* + * Use photometric mapping table to construct + * unpacking tables for samples <= 8 bits. + */ + if (!makebwmap(img)) + return (0); + /* no longer need Map, free it */ + _TIFFfree(img->Map), img->Map = NULL; + } + return (1); +} + +static int +checkcmap(TIFFRGBAImage* img) +{ + uint16* r = img->redcmap; + uint16* g = img->greencmap; + uint16* b = img->bluecmap; + long n = 1L<<img->bitspersample; + + while (n-- > 0) + if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) + return (16); + return (8); +} + +static void +cvtcmap(TIFFRGBAImage* img) +{ + uint16* r = img->redcmap; + uint16* g = img->greencmap; + uint16* b = img->bluecmap; + long i; + + for (i = (1L<<img->bitspersample)-1; i >= 0; i--) { +#define CVT(x) ((uint16)((x)>>8)) + r[i] = CVT(r[i]); + g[i] = CVT(g[i]); + b[i] = CVT(b[i]); +#undef CVT + } +} + +/* + * Palette images with <= 8 bits/sample are handled + * with a table to avoid lots of shifts and masks. The table + * is setup so that put*cmaptile (below) can retrieve 8/bitspersample + * pixel values simply by indexing into the table with one + * number. + */ +static int +makecmap(TIFFRGBAImage* img) +{ + int bitspersample = img->bitspersample; + int nsamples = 8 / bitspersample; + uint16* r = img->redcmap; + uint16* g = img->greencmap; + uint16* b = img->bluecmap; + uint32 *p; + int i; + + img->PALmap = (uint32**) _TIFFmalloc( + 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); + if (img->PALmap == NULL) { + TIFFError(TIFFFileName(img->tif), "No space for Palette mapping table"); + return (0); + } + p = (uint32*)(img->PALmap + 256); + for (i = 0; i < 256; i++) { + TIFFRGBValue c; + img->PALmap[i] = p; +#define CMAP(x) c = x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff); + switch (bitspersample) { + case 1: + CMAP(i>>7); + CMAP((i>>6)&1); + CMAP((i>>5)&1); + CMAP((i>>4)&1); + CMAP((i>>3)&1); + CMAP((i>>2)&1); + CMAP((i>>1)&1); + CMAP(i&1); + break; + case 2: + CMAP(i>>6); + CMAP((i>>4)&3); + CMAP((i>>2)&3); + CMAP(i&3); + break; + case 4: + CMAP(i>>4); + CMAP(i&0xf); + break; + case 8: + CMAP(i); + break; + } +#undef CMAP + } + return (1); +} + +/* + * Construct any mapping table used + * by the associated put routine. + */ +static int +buildMap(TIFFRGBAImage* img) +{ + switch (img->photometric) { + case PHOTOMETRIC_RGB: + case PHOTOMETRIC_YCBCR: + case PHOTOMETRIC_SEPARATED: + if (img->bitspersample == 8) + break; + /* fall thru... */ + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_MINISWHITE: + if (!setupMap(img)) + return (0); + break; + case PHOTOMETRIC_PALETTE: + /* + * Convert 16-bit colormap to 8-bit (unless it looks + * like an old-style 8-bit colormap). + */ + if (checkcmap(img) == 16) + cvtcmap(img); + else + TIFFWarning(TIFFFileName(img->tif), "Assuming 8-bit colormap"); + /* + * Use mapping table and colormap to construct + * unpacking tables for samples < 8 bits. + */ + if (img->bitspersample <= 8 && !makecmap(img)) + return (0); + break; + } + return (1); +} + +/* + * Select the appropriate conversion routine for packed data. + */ +static int +pickTileContigCase(TIFFRGBAImage* img) +{ + tileContigRoutine put = 0; + + if (buildMap(img)) { + switch (img->photometric) { + case PHOTOMETRIC_RGB: + switch (img->bitspersample) { + case 8: + if (!img->Map) { + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + put = putRGBAAcontig8bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + put = putRGBUAcontig8bittile; + else + put = putRGBcontig8bittile; + } else + put = putRGBcontig8bitMaptile; + break; + case 16: + put = putRGBcontig16bittile; + if (!img->Map) { + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + put = putRGBAAcontig16bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + put = putRGBUAcontig16bittile; + } + break; + } + break; + case PHOTOMETRIC_SEPARATED: + if (img->bitspersample == 8) { + if (!img->Map) + put = putRGBcontig8bitCMYKtile; + else + put = putRGBcontig8bitCMYKMaptile; + } + break; + case PHOTOMETRIC_PALETTE: + switch (img->bitspersample) { + case 8: put = put8bitcmaptile; break; + case 4: put = put4bitcmaptile; break; + case 2: put = put2bitcmaptile; break; + case 1: put = put1bitcmaptile; break; + } + break; + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + switch (img->bitspersample) { + case 16: put = put16bitbwtile; break; + case 8: put = putgreytile; break; + case 4: put = put4bitbwtile; break; + case 2: put = put2bitbwtile; break; + case 1: put = put1bitbwtile; break; + } + break; + case PHOTOMETRIC_YCBCR: + if (img->bitspersample == 8) + put = initYCbCrConversion(img); + break; + } + } + return ((img->put.contig = put) != 0); +} + +/* + * Select the appropriate conversion routine for unpacked data. + * + * NB: we assume that unpacked single channel data is directed + * to the "packed routines. + */ +static int +pickTileSeparateCase(TIFFRGBAImage* img) +{ + tileSeparateRoutine put = 0; + + if (buildMap(img)) { + switch (img->photometric) { + case PHOTOMETRIC_RGB: + switch (img->bitspersample) { + case 8: + if (!img->Map) { + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + put = putRGBAAseparate8bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + put = putRGBUAseparate8bittile; + else + put = putRGBseparate8bittile; + } else + put = putRGBseparate8bitMaptile; + break; + case 16: + put = putRGBseparate16bittile; + if (!img->Map) { + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + put = putRGBAAseparate16bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + put = putRGBUAseparate16bittile; + } + break; + } + break; + } + } + return ((img->put.separate = put) != 0); +} + +/* + * Read a whole strip off data from the file, and convert to RGBA form. + * If this is the last strip, then it will only contain the portion of + * the strip that is actually within the image space. The result is + * organized in bottom to top form. + */ + + +int +TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) + +{ + char emsg[1024]; + TIFFRGBAImage img; + int ok; + uint32 rowsperstrip, rows_to_read; + + if( TIFFIsTiled( tif ) ) + { + TIFFError(TIFFFileName(tif), + "Can't use TIFFReadRGBAStrip() with tiled file."); + return (0); + } + + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + if( (row % rowsperstrip) != 0 ) + { + TIFFError(TIFFFileName(tif), + "Row passed to TIFFReadRGBAStrip() must be first in a strip."); + return (0); + } + + if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + + img.row_offset = row; + img.col_offset = 0; + + if( row + rowsperstrip > img.height ) + rows_to_read = img.height - row; + else + rows_to_read = rowsperstrip; + + ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read ); + + TIFFRGBAImageEnd(&img); + } else { + TIFFError(TIFFFileName(tif), emsg); + ok = 0; + } + + return (ok); +} + +/* + * Read a whole tile off data from the file, and convert to RGBA form. + * The returned RGBA data is organized from bottom to top of tile, + * and may include zeroed areas if the tile extends off the image. + */ + +int +TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) + +{ + char emsg[1024]; + TIFFRGBAImage img; + int ok; + uint32 tile_xsize, tile_ysize; + uint32 read_xsize, read_ysize; + uint32 i_row; + + /* + * Verify that our request is legal - on a tile file, and on a + * tile boundary. + */ + + if( !TIFFIsTiled( tif ) ) + { + TIFFError(TIFFFileName(tif), + "Can't use TIFFReadRGBATile() with stripped file."); + return (0); + } + + TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize); + TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize); + if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 ) + { + TIFFError(TIFFFileName(tif), + "Row/col passed to TIFFReadRGBATile() must be top" + "left corner of a tile."); + return (0); + } + + /* + * Setup the RGBA reader. + */ + + if ( !TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + TIFFError(TIFFFileName(tif), emsg); + return( 0 ); + } + + /* + * The TIFFRGBAImageGet() function doesn't allow us to get off the + * edge of the image, even to fill an otherwise valid tile. So we + * figure out how much we can read, and fix up the tile buffer to + * a full tile configuration afterwards. + */ + + if( row + tile_ysize > img.height ) + read_ysize = img.height - row; + else + read_ysize = tile_ysize; + + if( col + tile_xsize > img.width ) + read_xsize = img.width - col; + else + read_xsize = tile_xsize; + + /* + * Read the chunk of imagery. + */ + + img.row_offset = row; + img.col_offset = col; + + ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize ); + + TIFFRGBAImageEnd(&img); + + /* + * If our read was incomplete we will need to fix up the tile by + * shifting the data around as if a full tile of data is being returned. + * + * This is all the more complicated because the image is organized in + * bottom to top format. + */ + + if( read_xsize == tile_xsize && read_ysize == tile_ysize ) + return( ok ); + + for( i_row = 0; i_row < read_ysize; i_row++ ) + { + memmove( raster + (tile_ysize - i_row - 1) * tile_xsize, + raster + (read_ysize - i_row - 1) * read_xsize, + read_xsize * sizeof(uint32) ); + _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize, + 0, sizeof(uint32) * (tile_xsize - read_xsize) ); + } + + for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) + { + _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize, + 0, sizeof(uint32) * tile_xsize ); + } + + return (ok); +} diff --git a/Utilities/vtktiff/tif_jpeg.c b/Utilities/vtktiff/tif_jpeg.c new file mode 100644 index 0000000..b999471 --- /dev/null +++ b/Utilities/vtktiff/tif_jpeg.c @@ -0,0 +1,1471 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_jpeg.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1994-1997 Sam Leffler + * Copyright (c) 1994-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef JPEG_SUPPORT +/* + * TIFF Library + * + * JPEG Compression support per TIFF Technical Note #2 + * (*not* per the original TIFF 6.0 spec). + * + * This file is simply an interface to the libjpeg library written by + * the Independent JPEG Group. You need release 5 or later of the IJG + * code, which you can find on the Internet at ftp.uu.net:/graphics/jpeg/. + * + * Contributed by Tom Lane <tgl@sss.pgh.pa.us>. + */ +#include <assert.h> +#include <stdio.h> +#include <setjmp.h> + +/* We undefine FAR to avoid conflict with JPEG definition */ + +#ifdef FAR +#undef FAR +#endif + +#define VTK_JPEG_INCLUDE_JERROR +#include "vtk_jpeg.h" + +/* + * On some machines it may be worthwhile to use _setjmp or sigsetjmp + * in place of plain setjmp. These macros will make it easier. + */ +#define SETJMP(jbuf) setjmp(jbuf) +#define LONGJMP(jbuf,code) longjmp(jbuf,code) +#define JMP_BUF jmp_buf + +typedef struct jpeg_destination_mgr jpeg_destination_mgr; +typedef struct jpeg_source_mgr jpeg_source_mgr; +typedef struct jpeg_error_mgr jpeg_error_mgr; + +/* + * State block for each open TIFF file using + * libjpeg to do JPEG compression/decompression. + * + * libjpeg's visible state is either a jpeg_compress_struct + * or jpeg_decompress_struct depending on which way we + * are going. comm can be used to refer to the fields + * which are common to both. + * + * NB: cinfo is required to be the first member of JPEGState, + * so we can safely cast JPEGState* -> jpeg_xxx_struct* + * and vice versa! + */ +typedef struct { + union { + struct jpeg_compress_struct c; + struct jpeg_decompress_struct d; + struct jpeg_common_struct comm; + } cinfo; /* NB: must be first */ + jpeg_error_mgr err; /* libjpeg error manager */ + JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ + /* + * The following two members could be a union, but + * they're small enough that it's not worth the effort. + */ + jpeg_destination_mgr dest; /* data dest for compression */ + jpeg_source_mgr src; /* data source for decompression */ + /* private state */ + TIFF* tif; /* back link needed by some code */ + uint16 photometric; /* copy of PhotometricInterpretation */ + uint16 h_sampling; /* luminance sampling factors */ + uint16 v_sampling; + tsize_t bytesperline; /* decompressed bytes per scanline */ + /* pointers to intermediate buffers when processing downsampled data */ + JSAMPARRAY ds_buffer[MAX_COMPONENTS]; + int scancount; /* number of "scanlines" accumulated */ + int samplesperclump; + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFStripMethod defsparent; /* super-class method */ + TIFFTileMethod deftparent; /* super-class method */ + /* pseudo-tag fields */ + void* jpegtables; /* JPEGTables tag value, or NULL */ + uint32 jpegtables_length; /* number of bytes in same */ + int jpegquality; /* Compression quality level */ + int jpegcolormode; /* Auto RGB<=>YCbCr convert? */ + int jpegtablesmode; /* What to put in JPEGTables */ +} JPEGState; + +#define JState(tif) ((JPEGState*)(tif)->tif_data) + +static int JPEGDecode(TIFF*, tidata_t, tsize_t, tsample_t); +static int JPEGDecodeRaw(TIFF*, tidata_t, tsize_t, tsample_t); +static int JPEGEncode(TIFF*, tidata_t, tsize_t, tsample_t); +static int JPEGEncodeRaw(TIFF*, tidata_t, tsize_t, tsample_t); + +#define FIELD_JPEGTABLES (FIELD_CODEC+0) + +static const TIFFFieldInfo jpegFieldInfo[] = { + { TIFFTAG_JPEGTABLES, -1,-1, TIFF_UNDEFINED, FIELD_JPEGTABLES, + FALSE, TRUE, "JPEGTables" }, + { TIFFTAG_JPEGQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO, + TRUE, FALSE, "" }, + { TIFFTAG_JPEGCOLORMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "" }, + { TIFFTAG_JPEGTABLESMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "" }, +}; +#define N(a) (sizeof (a) / sizeof (a[0])) + +/* + * libjpeg interface layer. + * + * We use setjmp/longjmp to return control to libtiff + * when a fatal error is encountered within the JPEG + * library. We also direct libjpeg error and warning + * messages through the appropriate libtiff handlers. + */ + +/* + * Error handling routines (these replace corresponding + * IJG routines from jerror.c). These are used for both + * compression and decompression. + */ +static void +TIFFjpeg_error_exit(j_common_ptr cinfo) +{ + JPEGState *sp = (JPEGState *) cinfo; /* NB: cinfo assumed first */ + char buffer[JMSG_LENGTH_MAX]; + + (*cinfo->err->format_message) (cinfo, buffer); + TIFFError("JPEGLib", buffer); /* display the error message */ + jpeg_abort(cinfo); /* clean up libjpeg state */ + LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ +} + +/* + * This routine is invoked only for warning messages, + * since error_exit does its own thing and trace_level + * is never set > 0. + */ +static void +TIFFjpeg_output_message(j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + (*cinfo->err->format_message) (cinfo, buffer); + TIFFWarning("JPEGLib", buffer); +} + +/* + * Interface routines. This layer of routines exists + * primarily to limit side-effects from using setjmp. + * Also, normal/error returns are converted into return + * values per libtiff practice. + */ +#define CALLJPEG(sp, fail, op) (SETJMP((sp)->exit_jmpbuf) ? (fail) : (op)) +#define CALLVJPEG(sp, op) CALLJPEG(sp, 0, ((op),1)) + +static int +TIFFjpeg_create_compress(JPEGState* sp) +{ + /* initialize JPEG error handling */ + sp->cinfo.c.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; + + return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c)); +} + +static int +TIFFjpeg_create_decompress(JPEGState* sp) +{ + /* initialize JPEG error handling */ + sp->cinfo.d.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; + + return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d)); +} + +static int +TIFFjpeg_set_defaults(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c)); +} + +static int +TIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace) +{ + return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace)); +} + +static int +TIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline) +{ + return CALLVJPEG(sp, + jpeg_set_quality(&sp->cinfo.c, quality, force_baseline)); +} + +static int +TIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress) +{ + return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress)); +} + +static int +TIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables) +{ + return CALLVJPEG(sp, + jpeg_start_compress(&sp->cinfo.c, write_all_tables)); +} + +static int +TIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c, + scanlines, (JDIMENSION) num_lines)); +} + +static int +TIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c, + data, (JDIMENSION) num_lines)); +} + +static int +TIFFjpeg_finish_compress(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c)); +} + +static int +TIFFjpeg_write_tables(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c)); +} + +static int +TIFFjpeg_read_header(JPEGState* sp, boolean require_image) +{ + return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image)); +} + +static int +TIFFjpeg_start_decompress(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d)); +} + +static int +TIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d, + scanlines, (JDIMENSION) max_lines)); +} + +static int +TIFFjpeg_read_raw_data(JPEGState* sp, JSAMPIMAGE data, int max_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d, + data, (JDIMENSION) max_lines)); +} + +static int +TIFFjpeg_finish_decompress(JPEGState* sp) +{ + return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d)); +} + +static int +TIFFjpeg_abort(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm)); +} + +static int +TIFFjpeg_destroy(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm)); +} + +static JSAMPARRAY +TIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +{ + return CALLJPEG(sp, (JSAMPARRAY) NULL, + (*sp->cinfo.comm.mem->alloc_sarray) + (&sp->cinfo.comm, pool_id, samplesperrow, numrows)); +} + +/* + * JPEG library destination data manager. + * These routines direct compressed data from libjpeg into the + * libtiff output buffer. + */ + +static void +std_init_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; +} + +static boolean +std_empty_output_buffer(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + /* the entire buffer has been filled */ + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; + + return (TRUE); +} + +static void +std_term_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + tif->tif_rawcp = (tidata_t) sp->dest.next_output_byte; + tif->tif_rawcc = + tif->tif_rawdatasize - (tsize_t) sp->dest.free_in_buffer; + /* NB: libtiff does the final buffer flush */ +} + +static void +TIFFjpeg_data_dest(JPEGState* sp, TIFF* tif) +{ + (void) tif; + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = std_init_destination; + sp->dest.empty_output_buffer = std_empty_output_buffer; + sp->dest.term_destination = std_term_destination; +} + +/* + * Alternate destination manager for outputting to JPEGTables field. + */ + +static void +tables_init_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + + /* while building, jpegtables_length is allocated buffer size */ + sp->dest.next_output_byte = (JOCTET*) sp->jpegtables; + sp->dest.free_in_buffer = (size_t) sp->jpegtables_length; +} + +static boolean +tables_empty_output_buffer(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + void* newbuf; + + /* the entire buffer has been filled; enlarge it by 1000 bytes */ + newbuf = _TIFFrealloc((tdata_t) sp->jpegtables, + (tsize_t) (sp->jpegtables_length + 1000)); + if (newbuf == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); + sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length; + sp->dest.free_in_buffer = (size_t) 1000; + sp->jpegtables = newbuf; + sp->jpegtables_length += 1000; + return (TRUE); +} + +static void +tables_term_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + + /* set tables length to number of bytes actually emitted */ + sp->jpegtables_length -= sp->dest.free_in_buffer; +} + +static int +TIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif) +{ + (void) tif; + /* + * Allocate a working buffer for building tables. + * Initial size is 1000 bytes, which is usually adequate. + */ + if (sp->jpegtables) + _TIFFfree(sp->jpegtables); + sp->jpegtables_length = 1000; + sp->jpegtables = (void*) _TIFFmalloc((tsize_t) sp->jpegtables_length); + if (sp->jpegtables == NULL) { + sp->jpegtables_length = 0; + TIFFError("TIFFjpeg_tables_dest", "No space for JPEGTables"); + return (0); + } + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = tables_init_destination; + sp->dest.empty_output_buffer = tables_empty_output_buffer; + sp->dest.term_destination = tables_term_destination; + return (1); +} + +/* + * JPEG library source data manager. + * These routines supply compressed data to libjpeg. + */ + +static void +std_init_source(j_decompress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata; + sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc; +} + +static boolean +std_fill_input_buffer(j_decompress_ptr cinfo) +{ + JPEGState* sp = (JPEGState* ) cinfo; + static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI }; + + /* + * Should never get here since entire strip/tile is + * read into memory before the decompressor is called, + * and thus was supplied by init_source. + */ + WARNMS(cinfo, JWRN_JPEG_EOF); + /* insert a fake EOI marker */ + sp->src.next_input_byte = dummy_EOI; + sp->src.bytes_in_buffer = 2; + return (TRUE); +} + +static void +std_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + JPEGState* sp = (JPEGState*) cinfo; + + if (num_bytes > 0) { + if (num_bytes > (long) sp->src.bytes_in_buffer) { + /* oops, buffer overrun */ + (void) std_fill_input_buffer(cinfo); + } else { + sp->src.next_input_byte += (size_t) num_bytes; + sp->src.bytes_in_buffer -= (size_t) num_bytes; + } + } +} + +static void +std_term_source(j_decompress_ptr cinfo) +{ + /* No work necessary here */ + /* Or must we update tif->tif_rawcp, tif->tif_rawcc ??? */ + /* (if so, need empty tables_term_source!) */ + (void) cinfo; +} + +static void +TIFFjpeg_data_src(JPEGState* sp, TIFF* tif) +{ + (void) tif; + sp->cinfo.d.src = &sp->src; + sp->src.init_source = std_init_source; + sp->src.fill_input_buffer = std_fill_input_buffer; + sp->src.skip_input_data = std_skip_input_data; + sp->src.resync_to_restart = jpeg_resync_to_restart; + sp->src.term_source = std_term_source; + sp->src.bytes_in_buffer = 0; /* for safety */ + sp->src.next_input_byte = NULL; +} + +/* + * Alternate source manager for reading from JPEGTables. + * We can share all the code except for the init routine. + */ + +static void +tables_init_source(j_decompress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + + sp->src.next_input_byte = (const JOCTET*) sp->jpegtables; + sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length; +} + +static void +TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif) +{ + TIFFjpeg_data_src(sp, tif); + sp->src.init_source = tables_init_source; +} + +/* + * Allocate downsampled-data buffers needed for downsampled I/O. + * We use values computed in jpeg_start_compress or jpeg_start_decompress. + * We use libjpeg's allocator so that buffers will be released automatically + * when done with strip/tile. + * This is also a handy place to compute samplesperclump, bytesperline. + */ +static int +alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info, + int num_components) +{ + JPEGState* sp = JState(tif); + int ci; + jpeg_component_info* compptr; + JSAMPARRAY buf; + int samples_per_clump = 0; + + for (ci = 0, compptr = comp_info; ci < num_components; + ci++, compptr++) { + samples_per_clump += compptr->h_samp_factor * + compptr->v_samp_factor; + buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor*DCTSIZE)); + if (buf == NULL) + return (0); + sp->ds_buffer[ci] = buf; + } + sp->samplesperclump = samples_per_clump; + return (1); +} + + +/* + * JPEG Decoding. + */ + +static int +JPEGSetupDecode(TIFF* tif) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + assert(sp != NULL); + assert(sp->cinfo.comm.is_decompressor); + + /* Read JPEGTables if it is present */ + if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) { + TIFFjpeg_tables_src(sp, tif); + if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) { + TIFFError("JPEGSetupDecode", "Bogus JPEGTables field"); + return (0); + } + } + + /* Grab parameters that are same for all strips/tiles */ + sp->photometric = td->td_photometric; + switch (sp->photometric) { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + break; + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Set up for reading normal data */ + TIFFjpeg_data_src(sp, tif); + tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */ + return (1); +} + +/* + * Set up for decoding a strip or tile. + */ +static int +JPEGPreDecode(TIFF* tif, tsample_t s) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreDecode"; + uint32 segment_width, segment_height; + int downsampled_output; + int ci; + + assert(sp != NULL); + assert(sp->cinfo.comm.is_decompressor); + /* + * Reset decoder state from any previous strip/tile, + * in case application didn't read the whole strip. + */ + if (!TIFFjpeg_abort(sp)) + return (0); + /* + * Read the header for this strip/tile. + */ + if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK) + return (0); + /* + * Check image parameters and set decompression parameters. + */ + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (isTiled(tif)) { + if (segment_height > td->td_tilelength) + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } else { + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { + /* + * For PC 2, scale down the expected strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany(segment_width, sp->h_sampling); + segment_height = TIFFhowmany(segment_height, sp->v_sampling); + } + if (sp->cinfo.d.image_width != segment_width || + sp->cinfo.d.image_height != segment_height) { + TIFFError(module, "Improper JPEG strip/tile size"); + return (0); + } + if (sp->cinfo.d.num_components != + (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1)) { + TIFFError(module, "Improper JPEG component count"); + return (0); + } + if (sp->cinfo.d.data_precision != td->td_bitspersample) { + TIFFError(module, "Improper JPEG data precision"); + return (0); + } + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + /* Component 0 should have expected sampling factors */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || + sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) { + TIFFError(module, "Improper JPEG sampling factors"); + return (0); + } + /* Rest should have sampling factors 1,1 */ + for (ci = 1; ci < sp->cinfo.d.num_components; ci++) { + if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 || + sp->cinfo.d.comp_info[ci].v_samp_factor != 1) { + TIFFError(module, "Improper JPEG sampling factors"); + return (0); + } + } + } else { + /* PC 2's single component should have sampling factors 1,1 */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 || + sp->cinfo.d.comp_info[0].v_samp_factor != 1) { + TIFFError(module, "Improper JPEG sampling factors"); + return (0); + } + } + downsampled_output = FALSE; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + sp->photometric == PHOTOMETRIC_YCBCR && + sp->jpegcolormode == JPEGCOLORMODE_RGB) { + /* Convert YCbCr to RGB */ + sp->cinfo.d.jpeg_color_space = JCS_YCbCr; + sp->cinfo.d.out_color_space = JCS_RGB; + } else { + /* Suppress colorspace handling */ + sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN; + sp->cinfo.d.out_color_space = JCS_UNKNOWN; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + (sp->h_sampling != 1 || sp->v_sampling != 1)) + downsampled_output = TRUE; + /* XXX what about up-sampling? */ + } + if (downsampled_output) { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.d.raw_data_out = TRUE; + tif->tif_decoderow = JPEGDecodeRaw; + tif->tif_decodestrip = JPEGDecodeRaw; + tif->tif_decodetile = JPEGDecodeRaw; + } else { + /* Use normal interface to libjpeg */ + sp->cinfo.d.raw_data_out = FALSE; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + } + /* Start JPEG decompressor */ + if (!TIFFjpeg_start_decompress(sp)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_output) { + if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info, + sp->cinfo.d.num_components)) + return (0); + sp->scancount = DCTSIZE; /* mark buffer empty */ + } + return (1); +} + +/* + * Decode a chunk of pixels. + * "Standard" case: returned data is not downsampled. + */ +/*ARGSUSED*/ static int +JPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + tsize_t nrows; + s = 0; + /* data is expected to be read in multiples of a scanline */ + if ((nrows = sp->cinfo.d.image_height)) + do { + JSAMPROW bufptr = (JSAMPROW)buf; + + if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) + return (0); + ++tif->tif_row; + buf += sp->bytesperline; + cc -= sp->bytesperline; + } while (--nrows > 0); + /* Close down the decompressor if we've finished the strip or tile. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFjpeg_finish_decompress(sp); +} + +/* + * Decode a chunk of pixels. + * Returned data is downsampled per sampling factors. + */ +/*ARGSUSED*/ static int +JPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + tsize_t nrows; + s = 0; + /* data is expected to be read in multiples of a scanline */ + if ((nrows = sp->cinfo.d.image_height)) { + /* Cb,Cr both have sampling factors 1, so this is correct */ + JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; + int samples_per_clump = sp->samplesperclump; + + do { + jpeg_component_info *compptr; + int ci, clumpoffset; + + /* Reload downsampled-data buffer if needed */ + if (sp->scancount >= DCTSIZE) { + int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE; + + if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) + != n) + return (0); + sp->scancount = 0; + } + /* + * Fastest way to unseparate data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.d.comp_info; + ci < sp->cinfo.d.num_components; + ci++, compptr++) { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int ypos; + + for (ypos = 0; ypos < vsamp; ypos++) { + JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; + JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; + JDIMENSION nclump; + + if (hsamp == 1) { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + outptr[0] = *inptr++; + outptr += samples_per_clump; + } + } else { + int xpos; + + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + for (xpos = 0; xpos < hsamp; xpos++) + outptr[xpos] = *inptr++; + outptr += samples_per_clump; + } + } + clumpoffset += hsamp; + } + } + ++sp->scancount; + ++tif->tif_row; + buf += sp->bytesperline; + cc -= sp->bytesperline; + } while (--nrows > 0); + } + + /* Close down the decompressor if done. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFjpeg_finish_decompress(sp); +} + + +/* + * JPEG Encoding. + */ + +static void +unsuppress_quant_table (JPEGState* sp, int tblno) +{ + JQUANT_TBL* qtbl; + + if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) + qtbl->sent_table = FALSE; +} + +static void +unsuppress_huff_table (JPEGState* sp, int tblno) +{ + JHUFF_TBL* htbl; + + if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; + if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; +} + +static int +prepare_JPEGTables(TIFF* tif) +{ + JPEGState* sp = JState(tif); + + /* Initialize quant tables for current quality setting */ + if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) + return (0); + /* Mark only the tables we want for output */ + /* NB: chrominance tables are currently used only with YCbCr */ + if (!TIFFjpeg_suppress_tables(sp, TRUE)) + return (0); + if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) { + unsuppress_quant_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_quant_table(sp, 1); + } + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) { + unsuppress_huff_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_huff_table(sp, 1); + } + /* Direct libjpeg output into jpegtables */ + if (!TIFFjpeg_tables_dest(sp, tif)) + return (0); + /* Emit tables-only datastream */ + if (!TIFFjpeg_write_tables(sp)) + return (0); + + return (1); +} + +static int +JPEGSetupEncode(TIFF* tif) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGSetupEncode"; + + assert(sp != NULL); + assert(!sp->cinfo.comm.is_decompressor); + + /* + * Initialize all JPEG parameters to default values. + * Note that jpeg_set_defaults needs legal values for + * in_color_space and input_components. + */ + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + sp->cinfo.c.input_components = 1; + if (!TIFFjpeg_set_defaults(sp)) + return (0); + /* Set per-file parameters */ + sp->photometric = td->td_photometric; + switch (sp->photometric) { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + /* + * A ReferenceBlackWhite field *must* be present since the + * default value is inappropriate for YCbCr. Fill in the + * proper value if application didn't set it. + */ +#ifdef COLORIMETRY_SUPPORT + if (!TIFFFieldSet(tif, FIELD_REFBLACKWHITE)) { + float refbw[6]; + long top = 1L << td->td_bitspersample; + refbw[0] = 0; + refbw[1] = (float)(top-1L); + refbw[2] = (float)(top>>1); + refbw[3] = refbw[1]; + refbw[4] = refbw[2]; + refbw[5] = refbw[1]; + TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refbw); + } +#endif + break; + case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ + case PHOTOMETRIC_MASK: + TIFFError(module, + "PhotometricInterpretation %d not allowed for JPEG", + (int) sp->photometric); + return (0); + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Verify miscellaneous parameters */ + + /* + * This would need work if libtiff ever supports different + * depths for different components, or if libjpeg ever supports + * run-time selection of depth. Neither is imminent. + */ + if (td->td_bitspersample != BITS_IN_JSAMPLE) { + TIFFError(module, "BitsPerSample %d not allowed for JPEG", + (int) td->td_bitspersample); + return (0); + } + sp->cinfo.c.data_precision = td->td_bitspersample; + if (isTiled(tif)) { + if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) { + TIFFError(module, + "JPEG tile height must be multiple of %d", + sp->v_sampling * DCTSIZE); + return (0); + } + if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) { + TIFFError(module, + "JPEG tile width must be multiple of %d", + sp->h_sampling * DCTSIZE); + return (0); + } + } else { + if (td->td_rowsperstrip < td->td_imagelength && + (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) { + TIFFError(module, + "RowsPerStrip must be multiple of %d for JPEG", + sp->v_sampling * DCTSIZE); + return (0); + } + } + + /* Create a JPEGTables field if appropriate */ + if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) { + if (!prepare_JPEGTables(tif)) + return (0); + /* Mark the field present */ + /* Can't use TIFFSetField since BEENWRITING is already set! */ + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + tif->tif_flags |= TIFF_DIRTYDIRECT; + } else { + /* We do not support application-supplied JPEGTables, */ + /* so mark the field not present */ + TIFFClrFieldBit(tif, FIELD_JPEGTABLES); + } + + /* Direct libjpeg output to libtiff's output buffer */ + TIFFjpeg_data_dest(sp, tif); + + return (1); +} + +/* + * Set encoding state at the start of a strip or tile. + */ +static int +JPEGPreEncode(TIFF* tif, tsample_t s) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreEncode"; + uint32 segment_width, segment_height; + int downsampled_input; + + assert(sp != NULL); + assert(!sp->cinfo.comm.is_decompressor); + /* + * Set encoding parameters for this strip/tile. + */ + if (isTiled(tif)) { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } else { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { + /* for PC 2, scale down the strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany(segment_width, sp->h_sampling); + segment_height = TIFFhowmany(segment_height, sp->v_sampling); + } + if (segment_width > 65535 || segment_height > 65535) { + TIFFError(module, "Strip/tile too large for JPEG"); + return (0); + } + sp->cinfo.c.image_width = segment_width; + sp->cinfo.c.image_height = segment_height; + downsampled_input = FALSE; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + sp->cinfo.c.input_components = td->td_samplesperpixel; + if (sp->photometric == PHOTOMETRIC_YCBCR) { + if (sp->jpegcolormode == JPEGCOLORMODE_RGB) { + sp->cinfo.c.in_color_space = JCS_RGB; + } else { + sp->cinfo.c.in_color_space = JCS_YCbCr; + if (sp->h_sampling != 1 || sp->v_sampling != 1) + downsampled_input = TRUE; + } + if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr)) + return (0); + /* + * Set Y sampling factors; + * we assume jpeg_set_colorspace() set the rest to 1 + */ + sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; + sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; + } else { + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) + return (0); + /* jpeg_set_colorspace set all sampling factors to 1 */ + } + } else { + sp->cinfo.c.input_components = 1; + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) + return (0); + sp->cinfo.c.comp_info[0].component_id = s; + /* jpeg_set_colorspace() set sampling factors to 1 */ + if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) { + sp->cinfo.c.comp_info[0].quant_tbl_no = 1; + sp->cinfo.c.comp_info[0].dc_tbl_no = 1; + sp->cinfo.c.comp_info[0].ac_tbl_no = 1; + } + } + /* ensure libjpeg won't write any extraneous markers */ + sp->cinfo.c.write_JFIF_header = FALSE; + sp->cinfo.c.write_Adobe_marker = FALSE; + /* set up table handling correctly */ + if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) { + if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) + return (0); + unsuppress_quant_table(sp, 0); + unsuppress_quant_table(sp, 1); + } + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) + sp->cinfo.c.optimize_coding = FALSE; + else + sp->cinfo.c.optimize_coding = TRUE; + if (downsampled_input) { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.c.raw_data_in = TRUE; + tif->tif_encoderow = JPEGEncodeRaw; + tif->tif_encodestrip = JPEGEncodeRaw; + tif->tif_encodetile = JPEGEncodeRaw; + } else { + /* Use normal interface to libjpeg */ + sp->cinfo.c.raw_data_in = FALSE; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + } + /* Start JPEG compressor */ + if (!TIFFjpeg_start_compress(sp, FALSE)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_input) { + if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info, + sp->cinfo.c.num_components)) + return (0); + } + sp->scancount = 0; + + return (1); +} + +/* + * Encode a chunk of pixels. + * "Standard" case: incoming data is not downsampled. + */ +static int +JPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + tsize_t nrows; + JSAMPROW bufptr[1]; + + (void) s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a scanline */ + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarning(tif->tif_name, "fractional scanline discarded"); + + while (nrows-- > 0) { + bufptr[0] = (JSAMPROW) buf; + if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1) + return (0); + if (nrows > 0) + tif->tif_row++; + buf += sp->bytesperline; + } + return (1); +} + +/* + * Encode a chunk of pixels. + * Incoming data is expected to be downsampled per sampling factors. + */ +static int +JPEGEncodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + JSAMPLE* inptr; + JSAMPLE* outptr; + tsize_t nrows; + JDIMENSION clumps_per_line, nclump; + int clumpoffset, ci, xpos, ypos; + jpeg_component_info* compptr; + int samples_per_clump = sp->samplesperclump; + + (void) s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a scanline */ + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarning(tif->tif_name, "fractional scanline discarded"); + + /* Cb,Cr both have sampling factors 1, so this is correct */ + clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width; + + while (nrows-- > 0) { + /* + * Fastest way to separate the data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; + ci++, compptr++) { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int padding = (int) (compptr->width_in_blocks * DCTSIZE - + clumps_per_line * hsamp); + for (ypos = 0; ypos < vsamp; ypos++) { + inptr = ((JSAMPLE*) buf) + clumpoffset; + outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; + if (hsamp == 1) { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + *outptr++ = inptr[0]; + inptr += samples_per_clump; + } + } else { + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + for (xpos = 0; xpos < hsamp; xpos++) + *outptr++ = inptr[xpos]; + inptr += samples_per_clump; + } + } + /* pad each scanline as needed */ + for (xpos = 0; xpos < padding; xpos++) { + *outptr = outptr[-1]; + outptr++; + } + clumpoffset += hsamp; + } + } + sp->scancount++; + if (sp->scancount >= DCTSIZE) { + int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + sp->scancount = 0; + } + if (nrows > 0) + tif->tif_row++; + buf += sp->bytesperline; + } + return (1); +} + +/* + * Finish up at the end of a strip or tile. + */ +static int +JPEGPostEncode(TIFF* tif) +{ + JPEGState *sp = JState(tif); + + if (sp->scancount > 0) { + /* + * Need to emit a partial bufferload of downsampled data. + * Pad the data vertically. + */ + int ci, ypos, n; + jpeg_component_info* compptr; + + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; + ci++, compptr++) { + int vsamp = compptr->v_samp_factor; + tsize_t row_width = compptr->width_in_blocks * DCTSIZE + * sizeof(JSAMPLE); + for (ypos = sp->scancount * vsamp; + ypos < DCTSIZE * vsamp; ypos++) { + _TIFFmemcpy((tdata_t)sp->ds_buffer[ci][ypos], + (tdata_t)sp->ds_buffer[ci][ypos-1], + row_width); + + } + } + n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + } + + return (TIFFjpeg_finish_compress(JState(tif))); +} + +static void +JPEGCleanup(TIFF* tif) +{ + if (tif->tif_data) { + JPEGState *sp = JState(tif); + TIFFjpeg_destroy(sp); /* release libjpeg resources */ + if (sp->jpegtables) /* tag value */ + _TIFFfree(sp->jpegtables); + _TIFFfree(tif->tif_data); /* release local state */ + tif->tif_data = NULL; + } +} + +static int +JPEGVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + JPEGState* sp = JState(tif); + TIFFDirectory* td = &tif->tif_dir; + uint32 v32; + + switch (tag) { + case TIFFTAG_JPEGTABLES: + v32 = va_arg(ap, uint32); + if (v32 == 0) { + /* XXX */ + return (0); + } + _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*), + (long) v32); + sp->jpegtables_length = v32; + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + break; + case TIFFTAG_JPEGQUALITY: + sp->jpegquality = va_arg(ap, int); + return (1); /* pseudo tag */ + case TIFFTAG_JPEGCOLORMODE: + sp->jpegcolormode = va_arg(ap, int); + /* + * Mark whether returned data is up-sampled or not + * so TIFFStripSize and TIFFTileSize return values + * that reflect the true amount of data. + */ + tif->tif_flags &= ~TIFF_UPSAMPLED; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + if (td->td_photometric == PHOTOMETRIC_YCBCR && + sp->jpegcolormode == JPEGCOLORMODE_RGB) { + tif->tif_flags |= TIFF_UPSAMPLED; + } else { + /*if (td->td_ycbcrsubsampling[0] != 1 || + td->td_ycbcrsubsampling[1] != 1) + ;*/ /* XXX what about up-sampling? */ + } + } + /* + * Must recalculate cached tile size + * in case sampling state changed. + */ + tif->tif_tilesize = TIFFTileSize(tif); + return (1); /* pseudo tag */ + case TIFFTAG_JPEGTABLESMODE: + sp->jpegtablesmode = va_arg(ap, int); + return (1); /* pseudo tag */ + default: + return (*sp->vsetparent)(tif, tag, ap); + } + tif->tif_flags |= TIFF_DIRTYDIRECT; + return (1); +} + +static int +JPEGVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + JPEGState* sp = JState(tif); + + switch (tag) { + case TIFFTAG_JPEGTABLES: + /* u_short is bogus --- should be uint32 ??? */ + /* TIFFWriteNormalTag needs fixed XXX */ + *va_arg(ap, u_short*) = (u_short) sp->jpegtables_length; + *va_arg(ap, void**) = sp->jpegtables; + break; + case TIFFTAG_JPEGQUALITY: + *va_arg(ap, int*) = sp->jpegquality; + break; + case TIFFTAG_JPEGCOLORMODE: + *va_arg(ap, int*) = sp->jpegcolormode; + break; + case TIFFTAG_JPEGTABLESMODE: + *va_arg(ap, int*) = sp->jpegtablesmode; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static void +JPEGPrintDir(TIFF* tif, FILE* fd, long flags) +{ + JPEGState* sp = JState(tif); + + (void) flags; + if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) + fprintf(fd, " JPEG Tables: (%lu bytes)\n", + (u_long) sp->jpegtables_length); +} + +static uint32 +JPEGDefaultStripSize(TIFF* tif, uint32 s) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + s = (*sp->defsparent)(tif, s); + if (s < td->td_imagelength) + s = TIFFroundup(s, td->td_ycbcrsubsampling[1] * DCTSIZE); + return (s); +} + +static void +JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + (*sp->deftparent)(tif, tw, th); + *tw = TIFFroundup(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE); + *th = TIFFroundup(*th, td->td_ycbcrsubsampling[1] * DCTSIZE); +} + +int +TIFFInitJPEG(TIFF* tif, int scheme) +{ + JPEGState* sp; + + assert(scheme == COMPRESSION_JPEG); + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (JPEGState)); + if (tif->tif_data == NULL) { + TIFFError("TIFFInitJPEG", "No space for JPEG state block"); + return (0); + } + sp = JState(tif); + sp->tif = tif; /* back link */ + + /* + * Merge codec-specific tag information and + * override parent get/set field methods. + */ + _TIFFMergeFieldInfo(tif, jpegFieldInfo, N(jpegFieldInfo)); + sp->vgetparent = tif->tif_vgetfield; + tif->tif_vgetfield = JPEGVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_vsetfield; + tif->tif_vsetfield = JPEGVSetField; /* hook for codec tags */ + tif->tif_printdir = JPEGPrintDir; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->jpegtables = NULL; + sp->jpegtables_length = 0; + sp->jpegquality = 75; /* Default IJG quality */ + sp->jpegcolormode = JPEGCOLORMODE_RAW; + sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = JPEGSetupDecode; + tif->tif_predecode = JPEGPreDecode; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + tif->tif_setupencode = JPEGSetupEncode; + tif->tif_preencode = JPEGPreEncode; + tif->tif_postencode = JPEGPostEncode; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + tif->tif_cleanup = JPEGCleanup; + sp->defsparent = tif->tif_defstripsize; + tif->tif_defstripsize = JPEGDefaultStripSize; + sp->deftparent = tif->tif_deftilesize; + tif->tif_deftilesize = JPEGDefaultTileSize; + tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */ + + /* + * Initialize libjpeg. + */ + if (tif->tif_mode == O_RDONLY) { + if (!TIFFjpeg_create_decompress(sp)) + return (0); + } else { + if (!TIFFjpeg_create_compress(sp)) + return (0); + } + + return (1); +} +#endif /* JPEG_SUPPORT */ diff --git a/Utilities/vtktiff/tif_luv.c b/Utilities/vtktiff/tif_luv.c new file mode 100644 index 0000000..79f63c9 --- /dev/null +++ b/Utilities/vtktiff/tif_luv.c @@ -0,0 +1,1586 @@ +/* + * Copyright (c) 1997 Greg Ward Larson + * Copyright (c) 1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any + * advertising or publicity relating to the software without the specific, + * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE + * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef LOGLUV_SUPPORT + +/* + * TIFF Library. + * LogLuv compression support for high dynamic range images. + * + * Contributed by Greg Larson. + * + * LogLuv image support uses the TIFF library to store 16 or 10-bit + * log luminance values with 8 bits each of u and v or a 14-bit index. + * + * The codec can take as input and produce as output 32-bit IEEE float values + * as well as 16-bit integer values. A 16-bit luminance is interpreted + * as a sign bit followed by a 15-bit integer that is converted + * to and from a linear magnitude using the transformation: + * + * L = 2^( (Le+.5)/256 - 64 ) # real from 15-bit + * + * Le = floor( 256*(log2(L) + 64) ) # 15-bit from real + * + * The actual conversion to world luminance units in candelas per sq. meter + * requires an additional multiplier, which is stored in the TIFFTAG_STONITS. + * This value is usually set such that a reasonable exposure comes from + * clamping decoded luminances above 1 to 1 in the displayed image. + * + * The 16-bit values for u and v may be converted to real values by dividing + * each by 32768. (This allows for negative values, which aren't useful as + * far as we know, but are left in case of future improvements in human + * color vision.) + * + * Conversion from (u,v), which is actually the CIE (u',v') system for + * you color scientists, is accomplished by the following transformation: + * + * u = 4*x / (-2*x + 12*y + 3) + * v = 9*y / (-2*x + 12*y + 3) + * + * x = 9*u / (6*u - 16*v + 12) + * y = 4*v / (6*u - 16*v + 12) + * + * This process is greatly simplified by passing 32-bit IEEE floats + * for each of three CIE XYZ coordinates. The codec then takes care + * of conversion to and from LogLuv, though the application is still + * responsible for interpreting the TIFFTAG_STONITS calibration factor. + * + * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white + * point of (x,y)=(1/3,1/3). However, most color systems assume some other + * white point, such as D65, and an absolute color conversion to XYZ then + * to another color space with a different white point may introduce an + * unwanted color cast to the image. It is often desirable, therefore, to + * perform a white point conversion that maps the input white to [1 1 1] + * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT + * tag value. A decoder that demands absolute color calibration may use + * this white point tag to get back the original colors, but usually it + * will be ignored and the new white point will be used instead that + * matches the output color space. + * + * Pixel information is compressed into one of two basic encodings, depending + * on the setting of the compression tag, which is one of COMPRESSION_SGILOG + * or COMPRESSION_SGILOG24. For COMPRESSION_SGILOG, greyscale data is + * stored as: + * + * 1 15 + * |-+---------------| + * + * COMPRESSION_SGILOG color data is stored as: + * + * 1 15 8 8 + * |-+---------------|--------+--------| + * S Le ue ve + * + * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as: + * + * 10 14 + * |----------|--------------| + * Le' Ce + * + * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is + * encoded as an index for optimal color resolution. The 10 log bits are + * defined by the following conversions: + * + * L = 2^((Le'+.5)/64 - 12) # real from 10-bit + * + * Le' = floor( 64*(log2(L) + 12) ) # 10-bit from real + * + * The 10 bits of the smaller format may be converted into the 15 bits of + * the larger format by multiplying by 4 and adding 13314. Obviously, + * a smaller range of magnitudes is covered (about 5 orders of magnitude + * instead of 38), and the lack of a sign bit means that negative luminances + * are not allowed. (Well, they aren't allowed in the real world, either, + * but they are useful for certain types of image processing.) + * + * The desired user format is controlled by the setting the internal + * pseudo tag TIFFTAG_SGILOGDATAFMT to one of: + * SGILOGDATAFMT_FLOAT = IEEE 32-bit float XYZ values + * SGILOGDATAFMT_16BIT = 16-bit integer encodings of logL, u and v + * Raw data i/o is also possible using: + * SGILOGDATAFMT_RAW = 32-bit unsigned integer with encoded pixel + * In addition, the following decoding is provided for ease of display: + * SGILOGDATAFMT_8BIT = 8-bit default RGB gamma-corrected values + * + * For grayscale images, we provide the following data formats: + * SGILOGDATAFMT_FLOAT = IEEE 32-bit float Y values + * SGILOGDATAFMT_16BIT = 16-bit integer w/ encoded luminance + * SGILOGDATAFMT_8BIT = 8-bit gray monitor values + * + * Note that the COMPRESSION_SGILOG applies a simple run-length encoding + * scheme by separating the logL, u and v bytes for each row and applying + * a PackBits type of compression. Since the 24-bit encoding is not + * adaptive, the 32-bit color format takes less space in many cases. + * + * Further control is provided over the conversion from higher-resolution + * formats to final encoded values through the pseudo tag + * TIFFTAG_SGILOGENCODE: + * SGILOGENCODE_NODITHER = do not dither encoded values + * SGILOGENCODE_RANDITHER = apply random dithering during encoding + * + * The default value of this tag is SGILOGENCODE_NODITHER for + * COMPRESSION_SGILOG to maximize run-length encoding and + * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn + * quantization errors into noise. + */ + +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> +#include <math.h> + +/* + * State block for each open TIFF + * file using LogLuv compression/decompression. + */ +typedef struct logLuvState LogLuvState; + +struct logLuvState { + int user_datafmt; /* user data format */ + int encode_meth; /* encoding method */ + int pixel_size; /* bytes per pixel */ + + tidata_t* tbuf; /* translation buffer */ + int tbuflen; /* buffer length */ + void (*tfunc)(LogLuvState*, tidata_t, int); + + TIFFVSetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ +}; + +#define DecoderState(tif) ((LogLuvState*) (tif)->tif_data) +#define EncoderState(tif) ((LogLuvState*) (tif)->tif_data) + +#define N(a) (sizeof(a)/sizeof(a[0])) +#define SGILOGDATAFMT_UNKNOWN -1 + +#define MINRUN 4 /* minimum run length */ + +/* + * Decode a string of 16-bit gray pixels. + */ +static int +LogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + LogLuvState* sp = DecoderState(tif); + int shft, i, npixels; + u_char* bp; + int16* tp; + int16 b; + int cc, rc; + + assert(s == 0); + assert(sp != NULL); + + npixels = occ / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_16BIT) + tp = (int16*) op; + else { + assert(sp->tbuflen >= npixels); + tp = (int16*) sp->tbuf; + } + _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); + + bp = (u_char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + /* get each byte string */ + for (shft = 2*8; (shft -= 8) >= 0; ) { + for (i = 0; i < npixels && cc > 0; ) + if (*bp >= 128) { /* run */ + rc = *bp++ + (2-128); + b = (int16)*bp++ << shft; + cc -= 2; + while (rc--) + tp[i++] |= b; + } else { /* non-run */ + rc = *bp++; /* nul is noop */ + while (--cc && rc--) + tp[i++] |= (int16)*bp++ << shft; + } + if (i != npixels) { + TIFFError(tif->tif_name, + "LogL16Decode: Not enough data at row %d (short %d pixels)", + tif->tif_row, npixels - i); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (0); + } + } + (*sp->tfunc)(sp, op, npixels); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (1); +} + +/* + * Decode a string of 24-bit pixels. + */ +static int +LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + LogLuvState* sp = DecoderState(tif); + int cc, i, npixels; + u_char* bp; + uint32* tp; + + assert(s == 0); + assert(sp != NULL); + + npixels = occ / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32 *)op; + else { + assert(sp->tbuflen >= npixels); + tp = (uint32 *) sp->tbuf; + } + /* copy to array of uint32 */ + bp = (u_char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + for (i = 0; i < npixels && cc > 0; i++) { + tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; + bp += 3; + cc -= 3; + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + if (i != npixels) { + TIFFError(tif->tif_name, + "LogLuvDecode24: Not enough data at row %d (short %d pixels)", + tif->tif_row, npixels - i); + return (0); + } + (*sp->tfunc)(sp, op, npixels); + return (1); +} + +/* + * Decode a string of 32-bit pixels. + */ +static int +LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + LogLuvState* sp; + int shft, i, npixels; + u_char* bp; + uint32* tp; + uint32 b; + int cc, rc; + + assert(s == 0); + sp = DecoderState(tif); + assert(sp != NULL); + + npixels = occ / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) op; + else { + assert(sp->tbuflen >= npixels); + tp = (uint32*) sp->tbuf; + } + _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); + + bp = (u_char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + /* get each byte string */ + for (shft = 4*8; (shft -= 8) >= 0; ) { + for (i = 0; i < npixels && cc > 0; ) + if (*bp >= 128) { /* run */ + rc = *bp++ + (2-128); + b = (uint32)*bp++ << shft; + cc -= 2; + while (rc--) + tp[i++] |= b; + } else { /* non-run */ + rc = *bp++; /* nul is noop */ + while (--cc && rc--) + tp[i++] |= (uint32)*bp++ << shft; + } + if (i != npixels) { + TIFFError(tif->tif_name, + "LogLuvDecode32: Not enough data at row %d (short %d pixels)", + tif->tif_row, npixels - i); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (0); + } + } + (*sp->tfunc)(sp, op, npixels); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (1); +} + +/* + * Decode a strip of pixels. We break it into rows to + * maintain synchrony with the encode algorithm, which + * is row by row. + */ +static int +LogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFScanlineSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Decode a tile of pixels. We break it into rows to + * maintain synchrony with the encode algorithm, which + * is row by row. + */ +static int +LogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFTileRowSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Encode a row of 16-bit pixels. + */ +static int +LogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + LogLuvState* sp = EncoderState(tif); + int shft, i, j, npixels; + tidata_t op; + int16* tp; + int16 b; + int occ, rc=0, mask, beg; + + assert(s == 0); + assert(sp != NULL); + npixels = cc / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_16BIT) + tp = (int16*) bp; + else { + tp = (int16*) sp->tbuf; + assert(sp->tbuflen >= npixels); + (*sp->tfunc)(sp, bp, npixels); + } + /* compress each byte string */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (shft = 2*8; (shft -= 8) >= 0; ) + for (i = 0; i < npixels; i += rc) { + if (occ < 4) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + mask = 0xff << shft; /* find next run */ + for (beg = i; beg < npixels; beg += rc) { + b = tp[beg] & mask; + rc = 1; + while (rc < 127+2 && beg+rc < npixels && + (tp[beg+rc] & mask) == b) + rc++; + if (rc >= MINRUN) + break; /* long enough */ + } + if (beg-i > 1 && beg-i < MINRUN) { + b = tp[i] & mask; /* check short run */ + j = i+1; + while ((tp[j++] & mask) == b) + if (j == beg) { + *op++ = 128-2+j-i; + *op++ = b >> shft; + occ -= 2; + i = beg; + break; + } + } + while (i < beg) { /* write out non-run */ + if ((j = beg-i) > 127) j = 127; + if (occ < j+3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = j; occ--; + while (j--) { + *op++ = tp[i++] >> shft & 0xff; + occ--; + } + } + if (rc >= MINRUN) { /* write out run */ + *op++ = 128-2+rc; + *op++ = tp[beg] >> shft & 0xff; + occ -= 2; + } else + rc = 0; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + + return (0); +} + +/* + * Encode a row of 24-bit pixels. + */ +static int +LogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + LogLuvState* sp = EncoderState(tif); + int i, npixels, occ; + tidata_t op; + uint32* tp; + + assert(s == 0); + assert(sp != NULL); + npixels = cc / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) bp; + else { + tp = (uint32*) sp->tbuf; + assert(sp->tbuflen >= npixels); + (*sp->tfunc)(sp, bp, npixels); + } + /* write out encoded pixels */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (i = npixels; i--; ) { + if (occ < 3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = (tidataval_t)(*tp >> 16); + *op++ = (tidataval_t)(*tp >> 8 & 0xff); + *op++ = (tidataval_t)(*tp++ & 0xff); + occ -= 3; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + + return (0); +} + +/* + * Encode a row of 32-bit pixels. + */ +static int +LogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + LogLuvState* sp = EncoderState(tif); + int shft, i, j, npixels; + tidata_t op; + uint32* tp; + uint32 b; + int occ, rc=0, mask, beg; + + assert(s == 0); + assert(sp != NULL); + + npixels = cc / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) bp; + else { + tp = (uint32*) sp->tbuf; + assert(sp->tbuflen >= npixels); + (*sp->tfunc)(sp, bp, npixels); + } + /* compress each byte string */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (shft = 4*8; (shft -= 8) >= 0; ) + for (i = 0; i < npixels; i += rc) { + if (occ < 4) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + mask = 0xff << shft; /* find next run */ + for (beg = i; beg < npixels; beg += rc) { + b = tp[beg] & mask; + rc = 1; + while (rc < 127+2 && beg+rc < npixels && + (tp[beg+rc] & mask) == b) + rc++; + if (rc >= MINRUN) + break; /* long enough */ + } + if (beg-i > 1 && beg-i < MINRUN) { + b = tp[i] & mask; /* check short run */ + j = i+1; + while ((tp[j++] & mask) == b) + if (j == beg) { + *op++ = (tidataval_t)(128-2+j-i); + *op++ = (tidataval_t)(b >> shft); + occ -= 2; + i = beg; + break; + } + } + while (i < beg) { /* write out non-run */ + if ((j = beg-i) > 127) j = 127; + if (occ < j+3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = j; occ--; + while (j--) { + *op++ = (tidataval_t)(tp[i++] >> shft & 0xff); + occ--; + } + } + if (rc >= MINRUN) { /* write out run */ + *op++ = 128-2+rc; + *op++ = (tidataval_t)(tp[beg] >> shft & 0xff); + occ -= 2; + } else + rc = 0; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + + return (0); +} + +/* + * Encode a strip of pixels. We break it into rows to + * avoid encoding runs across row boundaries. + */ +static int +LogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFScanlineSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Encode a tile of pixels. We break it into rows to + * avoid encoding runs across row boundaries. + */ +static int +LogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFTileRowSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Encode/Decode functions for converting to and from user formats. + */ + +#include "uvcode.h" + +#ifndef UVSCALE +#define U_NEU 0.210526316 +#define V_NEU 0.473684211 +#define UVSCALE 410. +#endif + +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#define tifflog2(x) ((1./M_LN2)*log(x)) +#define exp2(x) exp(M_LN2*(x)) + +#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ + (int)(x) : \ + (int)((x) + rand()*(1./RAND_MAX) - .5)) + +#if !LOGLUV_PUBLIC +static +#endif +double +LogL16toY(int p16) /* compute luminance from 16-bit LogL */ +{ + int Le = p16 & 0x7fff; + double Y; + + if (!Le) + return (0.); + Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.); + return (!(p16 & 0x8000) ? Y : -Y); +} + +#if !LOGLUV_PUBLIC +static +#endif +int +LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */ +{ + if (Y >= 1.8371976e19) + return (0x7fff); + if (Y <= -1.8371976e19) + return (0xffff); + if (Y > 5.4136769e-20) + return itrunc(256.*(tifflog2(Y) + 64.), em); + if (Y < -5.4136769e-20) + return (~0x7fff | itrunc(256.*(tifflog2(-Y) + 64.), em)); + return (0); +} + +static void +L16toY(LogLuvState* sp, tidata_t op, int n) +{ + int16* l16 = (int16*) sp->tbuf; + float* yp = (float*) op; + + while (n-- > 0) + *yp++ = (float)LogL16toY(*l16++); +} + +static void +L16toGry(LogLuvState* sp, tidata_t op, int n) +{ + int16* l16 = (int16*) sp->tbuf; + uint8* gp = (uint8*) op; + + while (n-- > 0) { + double Y = LogL16toY(*l16++); + *gp++ = (Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)); + } +} + +static void +L16fromY(LogLuvState* sp, tidata_t op, int n) +{ + int16* l16 = (int16*) sp->tbuf; + float* yp = (float*) op; + + while (n-- > 0) + *l16++ = LogL16fromY(*yp++, sp->encode_meth); +} + +#if !LOGLUV_PUBLIC +static +#endif +void +XYZtoRGB24(float xyz[3], uint8 rgb[3]) +{ + double r, g, b; + /* assume CCIR-709 primaries */ + r = 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]; + g = -1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]; + b = 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]; + /* assume 2.0 gamma for speed */ + /* could use integer sqrt approx., but this is probably faster */ + rgb[0] = (r <= 0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)); + rgb[1] = (g <= 0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)); + rgb[2] = (b <= 0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)); +} + +#if !LOGLUV_PUBLIC +static +#endif +double +LogL10toY(int p10) /* compute luminance from 10-bit LogL */ +{ + if (p10 == 0) + return (0.); + return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.)); +} + +#if !LOGLUV_PUBLIC +static +#endif +int +LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */ +{ + if (Y >= 15.742) + return (0x3ff); + else if (Y <= .00024283) + return (0); + else + return itrunc(64.*(tifflog2(Y) + 12.), em); +} + +#define NANGLES 100 +#define uv2ang(u, v) ( (NANGLES*.499999999/M_PI) \ + * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES ) + +static int +oog_encode(double u, double v) /* encode out-of-gamut chroma */ +{ + static int oog_table[NANGLES]; + static int initialized = 0; + register int i; + + if (!initialized) { /* set up perimeter table */ + double eps[NANGLES], ua, va, ang, epsa; + int ui, vi, ustep; + for (i = NANGLES; i--; ) + eps[i] = 2.; + for (vi = UV_NVS; vi--; ) { + va = UV_VSTART + (vi+.5)*UV_SQSIZ; + ustep = uv_row[vi].nus-1; + if (vi == UV_NVS-1 || vi == 0 || ustep <= 0) + ustep = 1; + for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) { + ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; + ang = uv2ang(ua, va); + i = (int) ang; + epsa = fabs(ang - (i+.5)); + if (epsa < eps[i]) { + oog_table[i] = uv_row[vi].ncum + ui; + eps[i] = epsa; + } + } + } + for (i = NANGLES; i--; ) /* fill any holes */ + if (eps[i] > 1.5) { + int i1, i2; + for (i1 = 1; i1 < NANGLES/2; i1++) + if (eps[(i+i1)%NANGLES] < 1.5) + break; + for (i2 = 1; i2 < NANGLES/2; i2++) + if (eps[(i+NANGLES-i2)%NANGLES] < 1.5) + break; + if (i1 < i2) + oog_table[i] = + oog_table[(i+i1)%NANGLES]; + else + oog_table[i] = + oog_table[(i+NANGLES-i2)%NANGLES]; + } + initialized = 1; + } + i = (int) uv2ang(u, v); /* look up hue angle */ + return (oog_table[i]); +} + +#undef uv2ang +#undef NANGLES + +#if !LOGLUV_PUBLIC +static +#endif +int +uv_encode(double u, double v, int em) /* encode (u',v') coordinates */ +{ + register int vi, ui; + + if (v < UV_VSTART) + return oog_encode(u, v); + vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em); + if (vi >= UV_NVS) + return oog_encode(u, v); + if (u < uv_row[vi].ustart) + return oog_encode(u, v); + ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em); + if (ui >= uv_row[vi].nus) + return oog_encode(u, v); + + return (uv_row[vi].ncum + ui); +} + +#if !LOGLUV_PUBLIC +static +#endif +int +uv_decode(double *up, double *vp, int c) /* decode (u',v') index */ +{ + int upper, lower; + register int ui, vi; + + if (c < 0 || c >= UV_NDIVS) + return (-1); + lower = 0; /* binary search */ + upper = UV_NVS; + while (upper - lower > 1) { + vi = (lower + upper) >> 1; + ui = c - uv_row[vi].ncum; + if (ui > 0) + lower = vi; + else if (ui < 0) + upper = vi; + else { + lower = vi; + break; + } + } + vi = lower; + ui = c - uv_row[vi].ncum; + *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; + *vp = UV_VSTART + (vi+.5)*UV_SQSIZ; + return (0); +} + +#if !LOGLUV_PUBLIC +static +#endif +void +LogLuv24toXYZ(uint32 p, float XYZ[3]) +{ + int Ce; + double L, u, v, s, x, y; + /* decode luminance */ + L = LogL10toY(p>>14 & 0x3ff); + if (L <= 0.) { + XYZ[0] = XYZ[1] = XYZ[2] = 0.; + return; + } + /* decode color */ + Ce = p & 0x3fff; + if (uv_decode(&u, &v, Ce) < 0) { + u = U_NEU; v = V_NEU; + } + s = 1./(6.*u - 16.*v + 12.); + x = 9.*u * s; + y = 4.*v * s; + /* convert to XYZ */ + XYZ[0] = (float)(x/y * L); + XYZ[1] = (float)L; + XYZ[2] = (float)((1.-x-y)/y * L); +} + +#if !LOGLUV_PUBLIC +static +#endif +uint32 +LogLuv24fromXYZ(float XYZ[3], int em) +{ + int Le, Ce; + double u, v, s; + /* encode luminance */ + Le = LogL10fromY(XYZ[1], em); + /* encode color */ + s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; + if (!Le || s <= 0.) { + u = U_NEU; + v = V_NEU; + } else { + u = 4.*XYZ[0] / s; + v = 9.*XYZ[1] / s; + } + Ce = uv_encode(u, v, em); + if (Ce < 0) /* never happens */ + Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); + /* combine encodings */ + return (Le << 14 | Ce); +} + +static void +Luv24toXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + LogLuv24toXYZ(*luv, xyz); + xyz += 3; + luv++; + } +} + +static void +Luv24toLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + while (n-- > 0) { + double u, v; + + *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314); + if (uv_decode(&u, &v, *luv&0x3fff) < 0) { + u = U_NEU; + v = V_NEU; + } + *luv3++ = (int16)(u * (1L<<15)); + *luv3++ = (int16)(v * (1L<<15)); + luv++; + } +} + +static void +Luv24toRGB(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + uint8* rgb = (uint8*) op; + + while (n-- > 0) { + float xyz[3]; + + LogLuv24toXYZ(*luv++, xyz); + XYZtoRGB24(xyz, rgb); + rgb += 3; + } +} + +static void +Luv24fromXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth); + xyz += 3; + } +} + +static void +Luv24fromLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + while (n-- > 0) { + int Le, Ce; + + if (luv3[0] <= 0) + Le = 0; + else if (luv3[0] >= (1<<12)+3314) + Le = (1<<10) - 1; + else if (sp->encode_meth == SGILOGENCODE_NODITHER) + Le = (luv3[0]-3314) >> 2; + else + Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth); + + Ce = uv_encode((luv[1]+.5)/(1<<15), (luv[2]+.5)/(1<<15), + sp->encode_meth); + if (Ce < 0) /* never happens */ + Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); + *luv++ = (uint32)Le << 14 | Ce; + luv3 += 3; + } +} + +#if !LOGLUV_PUBLIC +static +#endif +void +LogLuv32toXYZ(uint32 p, float XYZ[3]) +{ + double L, u, v, s, x, y; + /* decode luminance */ + L = LogL16toY((int)p >> 16); + if (L <= 0.) { + XYZ[0] = XYZ[1] = XYZ[2] = 0.; + return; + } + /* decode color */ + u = 1./UVSCALE * ((p>>8 & 0xff) + .5); + v = 1./UVSCALE * ((p & 0xff) + .5); + s = 1./(6.*u - 16.*v + 12.); + x = 9.*u * s; + y = 4.*v * s; + /* convert to XYZ */ + XYZ[0] = (float)(x/y * L); + XYZ[1] = (float)L; + XYZ[2] = (float)((1.-x-y)/y * L); +} + +#if !LOGLUV_PUBLIC +static +#endif +uint32 +LogLuv32fromXYZ(float XYZ[3], int em) +{ + unsigned int Le, ue, ve; + double u, v, s; + /* encode luminance */ + Le = (unsigned int)LogL16fromY(XYZ[1], em); + /* encode color */ + s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; + if (!Le || s <= 0.) { + u = U_NEU; + v = V_NEU; + } else { + u = 4.*XYZ[0] / s; + v = 9.*XYZ[1] / s; + } + if (u <= 0.) ue = 0; + else ue = itrunc(UVSCALE*u, em); + if (ue > 255) ue = 255; + if (v <= 0.) ve = 0; + else ve = itrunc(UVSCALE*v, em); + if (ve > 255) ve = 255; + /* combine encodings */ + return (Le << 16 | ue << 8 | ve); +} + +static void +Luv32toXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + LogLuv32toXYZ(*luv++, xyz); + xyz += 3; + } +} + +static void +Luv32toLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + while (n-- > 0) { + double u, v; + + *luv3++ = (int16)(*luv >> 16); + u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5); + v = 1./UVSCALE * ((*luv & 0xff) + .5); + *luv3++ = (int16)(u * (1L<<15)); + *luv3++ = (int16)(v * (1L<<15)); + luv++; + } +} + +static void +Luv32toRGB(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + uint8* rgb = (uint8*) op; + + while (n-- > 0) { + float xyz[3]; + + LogLuv32toXYZ(*luv++, xyz); + XYZtoRGB24(xyz, rgb); + rgb += 3; + } +} + +static void +Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth); + xyz += 3; + } +} + +static void +Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + if (sp->encode_meth == SGILOGENCODE_NODITHER) { + while (n-- > 0) { + *luv++ = (uint32)luv3[0] << 16 | + (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) | + (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff); + luv3 += 3; + } + return; + } + while (n-- > 0) { + *luv++ = (uint32)luv3[0] << 16 | + (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) | + (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff); + luv3 += 3; + } +} + +static void +_logLuvNop(LogLuvState* sp, tidata_t op, int n) +{ + (void) sp; (void) op; (void) n; +} + +static int +LogL16GuessDataFmt(TIFFDirectory *td) +{ +#define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f)) + switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) { + case PACK(1, 32, SAMPLEFORMAT_IEEEFP): + return (SGILOGDATAFMT_FLOAT); + case PACK(1, 16, SAMPLEFORMAT_VOID): + case PACK(1, 16, SAMPLEFORMAT_INT): + case PACK(1, 16, SAMPLEFORMAT_UINT): + return (SGILOGDATAFMT_16BIT); + case PACK(1, 8, SAMPLEFORMAT_VOID): + case PACK(1, 8, SAMPLEFORMAT_UINT): + return (SGILOGDATAFMT_8BIT); + } +#undef PACK + return (SGILOGDATAFMT_UNKNOWN); +} + +static int +LogL16InitState(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + LogLuvState* sp = DecoderState(tif); + static const char module[] = "LogL16InitState"; + + assert(sp != NULL); + assert(td->td_photometric == PHOTOMETRIC_LOGL); + + /* for some reason, we can't do this in TIFFInitLogL16 */ + if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) + sp->user_datafmt = LogL16GuessDataFmt(td); + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->pixel_size = sizeof (float); + break; + case SGILOGDATAFMT_16BIT: + sp->pixel_size = sizeof (int16); + break; + case SGILOGDATAFMT_8BIT: + sp->pixel_size = sizeof (uint8); + break; + default: + TIFFError(tif->tif_name, + "No support for converting user data format to LogL"); + return (0); + } + sp->tbuflen = td->td_imagewidth * td->td_rowsperstrip; + sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16)); + if (sp->tbuf == NULL) { + TIFFError(module, "%s: No space for SGILog translation buffer", + tif->tif_name); + return (0); + } + return (1); +} + +static int +LogLuvGuessDataFmt(TIFFDirectory *td) +{ + int guess; + + /* + * If the user didn't tell us their datafmt, + * take our best guess from the bitspersample. + */ +#define PACK(a,b) (((a)<<3)|(b)) + switch (PACK(td->td_bitspersample, td->td_sampleformat)) { + case PACK(32, SAMPLEFORMAT_IEEEFP): + guess = SGILOGDATAFMT_FLOAT; + break; + case PACK(32, SAMPLEFORMAT_VOID): + case PACK(32, SAMPLEFORMAT_UINT): + case PACK(32, SAMPLEFORMAT_INT): + guess = SGILOGDATAFMT_RAW; + break; + case PACK(16, SAMPLEFORMAT_VOID): + case PACK(16, SAMPLEFORMAT_INT): + case PACK(16, SAMPLEFORMAT_UINT): + guess = SGILOGDATAFMT_16BIT; + break; + case PACK( 8, SAMPLEFORMAT_VOID): + case PACK( 8, SAMPLEFORMAT_UINT): + guess = SGILOGDATAFMT_8BIT; + break; + default: + guess = SGILOGDATAFMT_UNKNOWN; + break; +#undef PACK + } + /* + * Double-check samples per pixel. + */ + switch (td->td_samplesperpixel) { + case 1: + if (guess != SGILOGDATAFMT_RAW) + guess = SGILOGDATAFMT_UNKNOWN; + break; + case 3: + if (guess == SGILOGDATAFMT_RAW) + guess = SGILOGDATAFMT_UNKNOWN; + break; + default: + guess = SGILOGDATAFMT_UNKNOWN; + break; + } + return (guess); +} + +static int +LogLuvInitState(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + LogLuvState* sp = DecoderState(tif); + static const char module[] = "LogLuvInitState"; + + assert(sp != NULL); + assert(td->td_photometric == PHOTOMETRIC_LOGLUV); + + /* for some reason, we can't do this in TIFFInitLogLuv */ + if (td->td_planarconfig != PLANARCONFIG_CONTIG) { + TIFFError(module, + "SGILog compression cannot handle non-contiguous data"); + return (0); + } + if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) + sp->user_datafmt = LogLuvGuessDataFmt(td); + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->pixel_size = 3*sizeof (float); + break; + case SGILOGDATAFMT_16BIT: + sp->pixel_size = 3*sizeof (int16); + break; + case SGILOGDATAFMT_RAW: + sp->pixel_size = sizeof (uint32); + break; + case SGILOGDATAFMT_8BIT: + sp->pixel_size = 3*sizeof (uint8); + break; + default: + TIFFError(tif->tif_name, + "No support for converting user data format to LogLuv"); + return (0); + } + sp->tbuflen = td->td_imagewidth * td->td_rowsperstrip; + sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32)); + if (sp->tbuf == NULL) { + TIFFError(module, "%s: No space for SGILog translation buffer", + tif->tif_name); + return (0); + } + return (1); +} + +static int +LogLuvSetupDecode(TIFF* tif) +{ + LogLuvState* sp = DecoderState(tif); + TIFFDirectory* td = &tif->tif_dir; + + tif->tif_postdecode = _TIFFNoPostDecode; + switch (td->td_photometric) { + case PHOTOMETRIC_LOGLUV: + if (!LogLuvInitState(tif)) + break; + if (td->td_compression == COMPRESSION_SGILOG24) { + tif->tif_decoderow = LogLuvDecode24; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv24toXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv24toLuv48; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = Luv24toRGB; + break; + } + } else { + tif->tif_decoderow = LogLuvDecode32; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv32toXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv32toLuv48; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = Luv32toRGB; + break; + } + } + return (1); + case PHOTOMETRIC_LOGL: + if (!LogL16InitState(tif)) + break; + tif->tif_decoderow = LogL16Decode; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = L16toY; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = L16toGry; + break; + } + return (1); + default: + TIFFError(tif->tif_name, + "Inappropriate photometric interpretation %d for SGILog compression; %s", + td->td_photometric, "must be either LogLUV or LogL"); + break; + } + return (0); +} + +static int +LogLuvSetupEncode(TIFF* tif) +{ + LogLuvState* sp = EncoderState(tif); + TIFFDirectory* td = &tif->tif_dir; + + switch (td->td_photometric) { + case PHOTOMETRIC_LOGLUV: + if (!LogLuvInitState(tif)) + break; + if (td->td_compression == COMPRESSION_SGILOG24) { + tif->tif_encoderow = LogLuvEncode24; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv24fromXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv24fromLuv48; + break; + case SGILOGDATAFMT_RAW: + break; + default: + goto notsupported; + } + } else { + tif->tif_encoderow = LogLuvEncode32; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv32fromXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv32fromLuv48; + break; + case SGILOGDATAFMT_RAW: + break; + default: + goto notsupported; + } + } + break; + case PHOTOMETRIC_LOGL: + if (!LogL16InitState(tif)) + break; + tif->tif_encoderow = LogL16Encode; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = L16fromY; + break; + case SGILOGDATAFMT_16BIT: + break; + default: + goto notsupported; + } + break; + default: + TIFFError(tif->tif_name, + "Inappropriate photometric interpretation %d for SGILog compression; %s", + td->td_photometric, "must be either LogLUV or LogL"); + break; + } + return (1); +notsupported: + TIFFError(tif->tif_name, + "SGILog compression supported only for %s, or raw data", + td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv"); + return (0); +} + +static void +LogLuvClose(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + + /* + * For consistency, we always want to write out the same + * bitspersample and sampleformat for our TIFF file, + * regardless of the data format being used by the application. + * Since this routine is called after tags have been set but + * before they have been recorded in the file, we reset them here. + */ + td->td_samplesperpixel = + (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3; + td->td_bitspersample = 16; + td->td_sampleformat = SAMPLEFORMAT_INT; +} + +static void +LogLuvCleanup(TIFF* tif) +{ + LogLuvState* sp = (LogLuvState *)tif->tif_data; + + if (sp) { + if (sp->tbuf) + _TIFFfree(sp->tbuf); + _TIFFfree(sp); + tif->tif_data = NULL; + } +} + +static int +LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + LogLuvState* sp = DecoderState(tif); + int bps, fmt; + + switch (tag) { + case TIFFTAG_SGILOGDATAFMT: + sp->user_datafmt = va_arg(ap, int); + /* + * Tweak the TIFF header so that the rest of libtiff knows what + * size of data will be passed between app and library, and + * assume that the app knows what it is doing and is not + * confused by these header manipulations... + */ + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + bps = 32, fmt = SAMPLEFORMAT_IEEEFP; + break; + case SGILOGDATAFMT_16BIT: + bps = 16, fmt = SAMPLEFORMAT_INT; + break; + case SGILOGDATAFMT_RAW: + bps = 32, fmt = SAMPLEFORMAT_UINT; + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + break; + case SGILOGDATAFMT_8BIT: + bps = 8, fmt = SAMPLEFORMAT_UINT; + break; + default: + TIFFError(tif->tif_name, + "Unknown data format %d for LogLuv compression", + sp->user_datafmt); + return (0); + } + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt); + /* + * Must recalculate sizes should bits/sample change. + */ + tif->tif_tilesize = TIFFTileSize(tif); + tif->tif_scanlinesize = TIFFScanlineSize(tif); + return (1); + case TIFFTAG_SGILOGENCODE: + sp->encode_meth = va_arg(ap, int); + if (sp->encode_meth != SGILOGENCODE_NODITHER && + sp->encode_meth != SGILOGENCODE_RANDITHER) { + TIFFError(tif->tif_name, + "Unknown encoding %d for LogLuv compression", + sp->encode_meth); + return (0); + } + return (1); + default: + return (*sp->vsetparent)(tif, tag, ap); + } +} + +static int +LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + LogLuvState *sp = (LogLuvState *)tif->tif_data; + + switch (tag) { + case TIFFTAG_SGILOGDATAFMT: + *va_arg(ap, int*) = sp->user_datafmt; + return (1); + default: + return (*sp->vgetparent)(tif, tag, ap); + } +} + +static const TIFFFieldInfo LogLuvFieldInfo[] = { + { TIFFTAG_SGILOGDATAFMT, 0, 0, TIFF_SHORT, FIELD_PSEUDO, + TRUE, FALSE, "SGILogDataFmt"}, + { TIFFTAG_SGILOGENCODE, 0, 0, TIFF_SHORT, FIELD_PSEUDO, + TRUE, FALSE, "SGILogEncode"} +}; + +int +TIFFInitSGILog(TIFF* tif, int scheme) +{ + static const char module[] = "TIFFInitSGILog"; + LogLuvState* sp; + + assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG); + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState)); + if (tif->tif_data == NULL) + goto bad; + sp = (LogLuvState*) tif->tif_data; + _TIFFmemset((tdata_t)sp, 0, sizeof (*sp)); + sp->user_datafmt = SGILOGDATAFMT_UNKNOWN; + sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ? + SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER; + sp->tfunc = _logLuvNop; + + /* + * Install codec methods. + * NB: tif_decoderow & tif_encoderow are filled + * in at setup time. + */ + tif->tif_setupdecode = LogLuvSetupDecode; + tif->tif_decodestrip = LogLuvDecodeStrip; + tif->tif_decodetile = LogLuvDecodeTile; + tif->tif_setupencode = LogLuvSetupEncode; + tif->tif_encodestrip = LogLuvEncodeStrip; + tif->tif_encodetile = LogLuvEncodeTile; + tif->tif_close = LogLuvClose; + tif->tif_cleanup = LogLuvCleanup; + + /* override SetField so we can handle our private pseudo-tag */ + _TIFFMergeFieldInfo(tif, LogLuvFieldInfo, N(LogLuvFieldInfo)); + sp->vgetparent = tif->tif_vgetfield; + tif->tif_vgetfield = LogLuvVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_vsetfield; + tif->tif_vsetfield = LogLuvVSetField; /* hook for codec tags */ + + return (1); +bad: + TIFFError(module, "%s: No space for LogLuv state block", tif->tif_name); + return (0); +} +#endif /* LOGLUV_SUPPORT */ diff --git a/Utilities/vtktiff/tif_lzw.c b/Utilities/vtktiff/tif_lzw.c new file mode 100644 index 0000000..28f314a --- /dev/null +++ b/Utilities/vtktiff/tif_lzw.c @@ -0,0 +1,724 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_lzw.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef LZW_SUPPORT +/* + * TIFF Library. + * Rev 5.0 Lempel-Ziv & Welch Compression Support + * + * This code is derived from the compress program whose code is + * derived from software contributed to Berkeley by James A. Woods, + * derived from original work by Spencer Thomas and Joseph Orost. + * + * The original Berkeley copyright notice appears below in its entirety. + */ +#include "tif_predict.h" + +#include <assert.h> +#include <stdio.h> + +/* + * NB: The 5.0 spec describes a different algorithm than Aldus + * implements. Specifically, Aldus does code length transitions + * one code earlier than should be done (for real LZW). + * Earlier versions of this library implemented the correct + * LZW algorithm, but emitted codes in a bit order opposite + * to the TIFF spec. Thus, to maintain compatibility w/ Aldus + * we interpret MSB-LSB ordered codes to be images written w/ + * old versions of this library, but otherwise adhere to the + * Aldus "off by one" algorithm. + * + * Future revisions to the TIFF spec are expected to "clarify this issue". + */ +#define LZW_COMPAT /* include backwards compatibility code */ +/* + * Each strip of data is supposed to be terminated by a CODE_EOI. + * If the following #define is included, the decoder will also + * check for end-of-strip w/o seeing this code. This makes the + * library more robust, but also slower. + */ +#define LZW_CHECKEOS /* include checks for strips w/o EOI code */ + +#define MAXCODE(n) ((1L<<(n))-1) +/* + * The TIFF spec specifies that encoded bit + * strings range from 9 to 12 bits. + */ +#define BITS_MIN 9 /* start with 9 bits */ +#define BITS_MAX 12 /* max of 12 bit strings */ +/* predefined codes */ +#define CODE_CLEAR 256 /* code to clear string table */ +#define CODE_EOI 257 /* end-of-information code */ +#define CODE_FIRST 258 /* first free code entry */ +#define CODE_MAX MAXCODE(BITS_MAX) +#define HSIZE 9001L /* 91% occupancy */ +#define HSHIFT (13-8) +#ifdef LZW_COMPAT +/* NB: +1024 is for compatibility with old files */ +#define CSIZE (MAXCODE(BITS_MAX)+1024L) +#else +#define CSIZE (MAXCODE(BITS_MAX)+1L) +#endif + +/* + * State block for each open TIFF file using LZW + * compression/decompression. Note that the predictor + * state block must be first in this data structure. + */ +typedef struct { + TIFFPredictorState predict; /* predictor super class */ + + u_short nbits; /* # of bits/code */ + u_short maxcode; /* maximum code for lzw_nbits */ + u_short free_ent; /* next free entry in hash table */ + long nextdata; /* next bits of i/o */ + long nextbits; /* # of valid bits in lzw_nextdata */ +} LZWBaseState; + +#define lzw_nbits base.nbits +#define lzw_maxcode base.maxcode +#define lzw_free_ent base.free_ent +#define lzw_nextdata base.nextdata +#define lzw_nextbits base.nextbits + +/* + * Decoding-specific state. + */ +typedef struct code_ent { + struct code_ent *next; + u_short length; /* string len, including this token */ + u_char value; /* data value */ + u_char firstchar; /* first token of string */ +} code_t; + +typedef int (*decodeFunc)(TIFF*, tidata_t, tsize_t, tsample_t); + +typedef struct { + LZWBaseState base; + long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */ + long dec_restart; /* restart count */ +#ifdef LZW_CHECKEOS + long dec_bitsleft; /* available bits in raw data */ +#endif + decodeFunc dec_decode; /* regular or backwards compatible */ + code_t* dec_codep; /* current recognized code */ + code_t* dec_oldcodep; /* previously recognized code */ + code_t* dec_free_entp; /* next free entry */ + code_t* dec_maxcodep; /* max available entry */ + code_t* dec_codetab; /* kept separate for small machines */ +} LZWDecodeState; + +/* + * Encoding-specific state. + */ +typedef uint16 hcode_t; /* codes fit in 16 bits */ +typedef struct { + long hash; + hcode_t code; +} hash_t; + +typedef struct { + LZWBaseState base; + int enc_oldcode; /* last code encountered */ + long enc_checkpoint; /* point at which to clear table */ +#define CHECK_GAP 10000 /* enc_ratio check interval */ + long enc_ratio; /* current compression ratio */ + long enc_incount; /* (input) data bytes encoded */ + long enc_outcount; /* encoded (output) bytes */ + tidata_t enc_rawlimit; /* bound on tif_rawdata buffer */ + hash_t* enc_hashtab; /* kept separate for small machines */ +} LZWEncodeState; + +#define LZWState(tif) ((LZWBaseState*) (tif)->tif_data) +#define DecoderState(tif) ((LZWDecodeState*) LZWState(tif)) +#define EncoderState(tif) ((LZWEncodeState*) LZWState(tif)) + +static int LZWDecode(TIFF*, tidata_t, tsize_t, tsample_t); +#ifdef LZW_COMPAT +static int LZWDecodeCompat(TIFF*, tidata_t, tsize_t, tsample_t); +#endif +/* This function is never used. + static void cl_hash(LZWEncodeState*); */ + +/* + * LZW Decoder. + */ + +#ifdef LZW_CHECKEOS +/* + * This check shouldn't be necessary because each + * strip is suppose to be terminated with CODE_EOI. + */ +#define NextCode(_tif, _sp, _bp, _code, _get) { \ + if ((_sp)->dec_bitsleft < nbits) { \ + TIFFWarning(_tif->tif_name, \ + "LZWDecode: Strip %d not terminated with EOI code", \ + _tif->tif_curstrip); \ + _code = CODE_EOI; \ + } else { \ + _get(_sp,_bp,_code); \ + (_sp)->dec_bitsleft -= nbits; \ + } \ +} +#else +#define NextCode(tif, sp, bp, code, get) get(sp, bp, code) +#endif + +static int +LZWSetupDecode(TIFF* tif) +{ + LZWDecodeState* sp = DecoderState(tif); + static const char module[] = " LZWSetupDecode"; + int code; + + assert(sp != NULL); + if (sp->dec_codetab == NULL) { + sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t)); + if (sp->dec_codetab == NULL) { + TIFFError(module, "No space for LZW code table"); + return (0); + } + /* + * Pre-load the table. + */ + code = 255; + do { + sp->dec_codetab[code].value = code; + sp->dec_codetab[code].firstchar = code; + sp->dec_codetab[code].length = 1; + sp->dec_codetab[code].next = NULL; + } while (code--); + } + return (1); +} + +/* + * Setup state for decoding a strip. + */ +static int +LZWPreDecode(TIFF* tif, tsample_t s) +{ + LZWDecodeState *sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + /* + * Check for old bit-reversed codes. + */ + if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { +#ifdef LZW_COMPAT + if (!sp->dec_decode) { + TIFFWarning(tif->tif_name, + "Old-style LZW codes, convert file"); + /* + * Override default decoding methods with + * ones that deal with the old coding. + * Otherwise the predictor versions set + * above will call the compatibility routines + * through the dec_decode method. + */ + tif->tif_decoderow = LZWDecodeCompat; + tif->tif_decodestrip = LZWDecodeCompat; + tif->tif_decodetile = LZWDecodeCompat; + /* + * If doing horizontal differencing, must + * re-setup the predictor logic since we + * switched the basic decoder methods... + */ + (*tif->tif_setupdecode)(tif); + sp->dec_decode = LZWDecodeCompat; + } + sp->lzw_maxcode = MAXCODE(BITS_MIN); +#else /* !LZW_COMPAT */ + if (!sp->dec_decode) { + TIFFError(tif->tif_name, + "Old-style LZW codes not supported"); + sp->dec_decode = LZWDecode; + } + return (0); +#endif/* !LZW_COMPAT */ + } else { + sp->lzw_maxcode = MAXCODE(BITS_MIN)-1; + sp->dec_decode = LZWDecode; + } + sp->lzw_nbits = BITS_MIN; + sp->lzw_nextbits = 0; + sp->lzw_nextdata = 0; + + sp->dec_restart = 0; + sp->dec_nbitsmask = MAXCODE(BITS_MIN); +#ifdef LZW_CHECKEOS + sp->dec_bitsleft = tif->tif_rawcc << 3; +#endif + sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; + /* + * Zero entries that are not yet filled in. We do + * this to guard against bogus input data that causes + * us to index into undefined entries. If you can + * come up with a way to safely bounds-check input codes + * while decoding then you can remove this operation. + */ + _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); + sp->dec_oldcodep = &sp->dec_codetab[-1]; + sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1]; + return (1); +} + +/* + * Decode a "hunk of data". + */ +#define GetNextCode(sp, bp, code) { \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + } \ + code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \ + nextbits -= nbits; \ +} + +static void +codeLoop(TIFF* tif) +{ + TIFFError(tif->tif_name, + "LZWDecode: Bogus encoding, loop in the code table; scanline %d", + tif->tif_row); +} + +static int +LZWDecode(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + LZWDecodeState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + u_char *bp; + hcode_t code; + int len; + long nbits, nextbits, nextdata, nbitsmask; + code_t *codep, *free_entp, *maxcodep, *oldcodep; + + (void) s; + assert(sp != NULL); + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; + + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ && codep); + if (codep) { + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + } + return (1); + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue, occ -= residue; + tp = op; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = t; + } while (--residue && codep); + sp->dec_restart = 0; + } + + bp = (u_char *)tif->tif_rawcp; + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0) { + NextCode(tif, sp, bp, code, GetNextCode); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + free_entp = sp->dec_codetab + CODE_FIRST; + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask-1; + NextCode(tif, sp, bp, code, GetNextCode); + if (code == CODE_EOI) + break; + *op++ = (char)code, occ--; + oldcodep = sp->dec_codetab + code; + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + assert(&sp->dec_codetab[0] <= free_entp && free_entp < &sp->dec_codetab[CSIZE]); + free_entp->next = oldcodep; + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask-1; + } + oldcodep = codep; + if (code >= 256) { + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep && codep->length > occ); + if (codep) { + sp->dec_restart = occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + if (codep) + codeLoop(tif); + } + break; + } + len = codep->length; + tp = op + len; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = t; + } while (codep && tp > op); + if (codep) { + codeLoop(tif); + break; + } + op += len, occ -= len; + } else + *op++ = (char)code, occ--; + } + + tif->tif_rawcp = (tidata_t) bp; + sp->lzw_nbits = (u_short) nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + + if (occ > 0) { + TIFFError(tif->tif_name, + "LZWDecode: Not enough data at scanline %d (short %d bytes)", + tif->tif_row, occ); + return (0); + } + return (1); +} + +#ifdef LZW_COMPAT +/* + * Decode a "hunk of data" for old images. + */ +#define GetNextCodeCompat(sp, bp, code) { \ + nextdata |= (u_long) *(bp)++ << nextbits; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata |= (u_long) *(bp)++ << nextbits; \ + nextbits += 8; \ + } \ + code = (hcode_t)(nextdata & nbitsmask); \ + nextdata >>= nbits; \ + nextbits -= nbits; \ +} + +static int +LZWDecodeCompat(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + LZWDecodeState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + u_char *bp; + int code, nbits; + long nextbits, nextdata, nbitsmask; + code_t *codep, *free_entp, *maxcodep, *oldcodep; + + (void) s; + assert(sp != NULL); + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; + + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ); + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + return (1); + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue, occ -= residue; + tp = op; + do { + *--tp = codep->value; + codep = codep->next; + } while (--residue); + sp->dec_restart = 0; + } + + bp = (u_char *)tif->tif_rawcp; + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0) { + NextCode(tif, sp, bp, code, GetNextCodeCompat); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + free_entp = sp->dec_codetab + CODE_FIRST; + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask; + NextCode(tif, sp, bp, code, GetNextCodeCompat); + if (code == CODE_EOI) + break; + *op++ = code, occ--; + oldcodep = sp->dec_codetab + code; + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + assert(&sp->dec_codetab[0] <= free_entp && free_entp < &sp->dec_codetab[CSIZE]); + free_entp->next = oldcodep; + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask; + } + oldcodep = codep; + if (code >= 256) { + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep->length > occ); + sp->dec_restart = occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + break; + } + op += codep->length, occ -= codep->length; + tp = op; + do { + *--tp = codep->value; + } while( (codep = codep->next) != NULL); + } else + *op++ = code, occ--; + } + + tif->tif_rawcp = (tidata_t) bp; + sp->lzw_nbits = nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + + if (occ > 0) { + TIFFError(tif->tif_name, + "LZWDecodeCompat: Not enough data at scanline %d (short %d bytes)", + tif->tif_row, occ); + return (0); + } + return (1); +} +#endif /* LZW_COMPAT */ + + + +static void +LZWCleanup(TIFF* tif) +{ + if (tif->tif_data) { + if (tif->tif_mode == O_RDONLY) { + if (DecoderState(tif)->dec_codetab) + _TIFFfree(DecoderState(tif)->dec_codetab); + } + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; + } +} + +static int +LZWSetupEncode(TIFF* tif) +{ + TIFFError(tif->tif_name, + "LZW compression is not available to due to Unisys patent enforcement"); + return (0); +} + +int +TIFFInitLZW(TIFF* tif, int scheme) +{ + assert(scheme == COMPRESSION_LZW); + /* + * Allocate state block so tag methods have storage to record values. + */ + if (tif->tif_mode == O_RDONLY) + { + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LZWDecodeState)); + if (tif->tif_data == NULL) + goto bad; + DecoderState(tif)->dec_codetab = NULL; + DecoderState(tif)->dec_decode = NULL; + } + + /* + * Install codec methods. + */ + tif->tif_setupencode = LZWSetupEncode; + tif->tif_setupdecode = LZWSetupDecode; + tif->tif_predecode = LZWPreDecode; + tif->tif_decoderow = LZWDecode; + tif->tif_decodestrip = LZWDecode; + tif->tif_decodetile = LZWDecode; + tif->tif_cleanup = LZWCleanup; + + /* + * Setup predictor setup. + */ + if( tif->tif_mode == O_RDONLY ) + (void) TIFFPredictorInit(tif); + + return (1); + +bad: + TIFFError("TIFFInitLZW", "No space for LZW state block"); + return (0); +} + +/* + * Copyright (c) 1985, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James A. Woods, derived from original work by Spencer Thomas + * and Joseph Orost. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#endif /* LZW_SUPPORT */ diff --git a/Utilities/vtktiff/tif_msdos.c b/Utilities/vtktiff/tif_msdos.c new file mode 100644 index 0000000..4073047 --- /dev/null +++ b/Utilities/vtktiff/tif_msdos.c @@ -0,0 +1,179 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_msdos.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library MSDOS-specific Routines. + */ +#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(_MSC_VER) +#include <io.h> /* for open, close, etc. function prototypes */ +#include <stdio.h> +#endif +#include "tiffiop.h" + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (read((int) fd, buf, size)); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (write((int) fd, buf, size)); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ + return (lseek((int) fd, (off_t) off, whence)); +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (close((int) fd)); +} + +#include <sys/stat.h> + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + struct stat sb; + return (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size); +} + +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ +} + +/* + * Open a TIFF file descriptor for read/writing. + */ +TIFF* +TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, + (void*) fd, + _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, + _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); + if (tif) + tif->tif_fd = fd; + return (tif); +} + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + int m, fd; + + m = _TIFFgetMode(mode, module); + if (m == -1) + return ((TIFF*)0); + fd = open(name, m|O_BINARY, 0666); + if (fd < 0) { + TIFFError(module, "%s: Cannot open", name); + return ((TIFF*)0); + } + return (TIFFFdOpen(fd, name, mode)); +} + +#ifdef __GNUC__ +extern char* malloc(); +extern char* realloc(); +#else +#include <malloc.h> +#endif + +tdata_t +_TIFFmalloc(tsize_t s) +{ + return (malloc((size_t) s)); +} + +void +_TIFFfree(tdata_t p) +{ + free(p); +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + return (realloc(p, (size_t) s)); +} + +void +_TIFFmemset(tdata_t p, int v, tsize_t c) +{ + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) +{ + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + return (memcmp(p1, p2, (size_t) c)); +} + +static void +msdosWarningHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFwarningHandler = msdosWarningHandler; + +static void +msdosErrorHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFerrorHandler = msdosErrorHandler; diff --git a/Utilities/vtktiff/tif_next.c b/Utilities/vtktiff/tif_next.c new file mode 100644 index 0000000..12f4d2b --- /dev/null +++ b/Utilities/vtktiff/tif_next.c @@ -0,0 +1,142 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_next.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef NEXT_SUPPORT +/* + * TIFF Library. + * + * NeXT 2-bit Grey Scale Compression Algorithm Support + */ + +#define SETPIXEL(op, v) { \ + switch (npixels++ & 3) { \ + case 0: op[0] = (v) << 6; break; \ + case 1: op[0] |= (v) << 4; break; \ + case 2: op[0] |= (v) << 2; break; \ + case 3: *op++ |= (v); break; \ + } \ +} + +#define LITERALROW 0x00 +#define LITERALSPAN 0x40 +#define WHITE ((1<<2)-1) + +static int +NeXTDecode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + register u_char *bp, *op; + register tsize_t cc; + register int n; + tidata_t row; + tsize_t scanline; + + (void) s; + /* + * Each scanline is assumed to start off as all + * white (we assume a PhotometricInterpretation + * of ``min-is-black''). + */ + for (op = buf, cc = occ; cc-- > 0;) + *op++ = 0xff; + + bp = (u_char *)tif->tif_rawcp; + cc = tif->tif_rawcc; + scanline = tif->tif_scanlinesize; + for (row = buf; (long)occ > 0; occ -= scanline, row += scanline) { + n = *bp++, cc--; + switch (n) { + case LITERALROW: + /* + * The entire scanline is given as literal values. + */ + if (cc < scanline) + goto bad; + _TIFFmemcpy(row, bp, scanline); + bp += scanline; + cc -= scanline; + break; + case LITERALSPAN: { + int off; + /* + * The scanline has a literal span + * that begins at some offset. + */ + off = (bp[0] * 256) + bp[1]; + n = (bp[2] * 256) + bp[3]; + if (cc < 4+n) + goto bad; + _TIFFmemcpy(row+off, bp+4, n); + bp += 4+n; + cc -= 4+n; + break; + } + default: { + register int npixels = 0, grey; + u_long imagewidth = tif->tif_dir.td_imagewidth; + + /* + * The scanline is composed of a sequence + * of constant color ``runs''. We shift + * into ``run mode'' and interpret bytes + * as codes of the form <color><npixels> + * until we've filled the scanline. + */ + op = row; + for (;;) { + grey = (n>>6) & 0x3; + n &= 0x3f; + while (n-- > 0) + SETPIXEL(op, grey); + if (npixels >= (int) imagewidth) + break; + if (cc == 0) + goto bad; + n = *bp++, cc--; + } + break; + } + } + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (1); +bad: + TIFFError(tif->tif_name, "NeXTDecode: Not enough data for scanline %ld", + (long) tif->tif_row); + return (0); +} + +int +TIFFInitNeXT(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = NeXTDecode; + tif->tif_decodestrip = NeXTDecode; + tif->tif_decodetile = NeXTDecode; + return (1); +} +#endif /* NEXT_SUPPORT */ diff --git a/Utilities/vtktiff/tif_ojpeg.c b/Utilities/vtktiff/tif_ojpeg.c new file mode 100644 index 0000000..529e446 --- /dev/null +++ b/Utilities/vtktiff/tif_ojpeg.c @@ -0,0 +1,2042 @@ +#include "tiffiop.h" +#ifdef OJPEG_SUPPORT + +/* JPEG Compression support, as per the original TIFF 6.0 specification. + + WARNING: KLUDGE ALERT! The type of JPEG encapsulation defined by the TIFF + Version 6.0 specification is now totally obsolete and + deprecated for new applications and images. This file is an unsupported hack + that was created solely in order to read (but NOT write!) a few old, + unconverted images still present on some users' computer systems. The code + isn't pretty or robust, and it won't read every "old format" JPEG-in-TIFF + file (see Samuel Leffler's draft "TIFF Technical Note No. 2" for a long and + incomplete list of known problems), but it seems to work well enough in the + few cases of practical interest to the author; so, "caveat emptor"! This + file should NEVER be enhanced to write new images using anything other than + the latest approved JPEG-in-TIFF encapsulation method, implemented by the + "tif_jpeg.c" file elsewhere in this library. + + This file interfaces with Release 6B of the JPEG Library written by theu + Independent JPEG Group, which you can find on the Internet at: + ftp.uu.net:/graphics/jpeg/. + + Contributed by Scott Marovich <marovich@hpl.hp.com> with considerable help + from Charles Auer <Bumble731@msn.com> to unravel the mysteries of image files + created by Microsoft's Wang Imaging application. +*/ +#include <setjmp.h> +#include <stdio.h> +#ifdef FAR +#undef FAR /* Undefine FAR to avoid conflict with JPEG definition */ +#endif +#define JPEG_INTERNALS /* Include "jpegint.h" for "DSTATE_*" symbols */ +#undef INLINE +#include "vtk_jpeg.h" +#undef JPEG_INTERNALS + +/* Hack for Microsoft's Wang Imaging for Windows output files */ +extern void jpeg_reset_huff_decode(j_decompress_ptr,float *); + +/* On some machines, it may be worthwhile to use "_setjmp()" or "sigsetjmp()" + instead of "setjmp()". These macros make it easier: +*/ +#define SETJMP(jbuf)setjmp(jbuf) +#define LONGJMP(jbuf,code)longjmp(jbuf,code) +#define JMP_BUF jmp_buf + +#define TIFFTAG_WANG_PAGECONTROL 32934 + +/* Bit-vector offsets for keeping track of TIFF records that we've parsed. */ + +#define FIELD_JPEGPROC FIELD_CODEC +#define FIELD_JPEGIFOFFSET (FIELD_CODEC+1) +#define FIELD_JPEGIFBYTECOUNT (FIELD_CODEC+2) +#define FIELD_JPEGRESTARTINTERVAL (FIELD_CODEC+3) +#define FIELD_JPEGTABLES (FIELD_CODEC+4) /* New, post-6.0 JPEG-in-TIFF tag! */ +#define FIELD_JPEGLOSSLESSPREDICTORS (FIELD_CODEC+5) +#define FIELD_JPEGPOINTTRANSFORM (FIELD_CODEC+6) +#define FIELD_JPEGQTABLES (FIELD_CODEC+7) +#define FIELD_JPEGDCTABLES (FIELD_CODEC+8) +#define FIELD_JPEGACTABLES (FIELD_CODEC+9) +#define FIELD_WANG_PAGECONTROL (FIELD_CODEC+10) +#define FIELD_JPEGCOLORMODE (FIELD_CODEC+11) + +typedef struct jpeg_destination_mgr jpeg_destination_mgr; +typedef struct jpeg_source_mgr jpeg_source_mgr; +typedef struct jpeg_error_mgr jpeg_error_mgr; + +/* State variable for each open TIFF file that uses "libjpeg" for JPEG + decompression. (Note: This file should NEVER perform JPEG compression + except in the manner implemented by the "tif_jpeg.c" file, elsewhere in this + library; see comments above.) JPEG Library internal state is recorded in a + "jpeg_{de}compress_struct", while a "jpeg_common_struct" records a few items + common to both compression and expansion. The "cinfo" field containing JPEG + Library state MUST be the 1st member of our own state variable, so that we + can safely "cast" pointers back and forth. +*/ +typedef struct /* This module's private, per-image state variable */ + { + union /* JPEG Library state variable; this MUST be our 1st field! */ + { + /* struct jpeg_compress_struct c; */ + struct jpeg_decompress_struct d; + struct jpeg_common_struct comm; + } cinfo; + jpeg_error_mgr err; /* JPEG Library error manager */ + JMP_BUF exit_jmpbuf; /* ...for catching JPEG Library failures */ +# ifdef never + + /* (The following two fields could be a "union", but they're small enough that + it's not worth the effort.) + */ + jpeg_destination_mgr dest; /* Destination for compressed data */ +# endif + jpeg_source_mgr src; /* Source of expanded data */ + JSAMPARRAY ds_buffer[MAX_COMPONENTS]; /* ->Temporary downsampling buffers */ + TIFF *tif; /* Reverse pointer, needed by some code */ + TIFFVGetMethod vgetparent; /* "Super class" methods... */ + TIFFVSetMethod vsetparent; + TIFFStripMethod defsparent; + TIFFTileMethod deftparent; + void *jpegtables; /* ->"New" JPEG tables, if we synthesized any */ + uint32 is_WANG, /* <=> Microsoft Wang Imaging for Windows output file? */ + jpegtables_length; /* Length of "new" JPEG tables, if they exist */ + tsize_t bytesperline; /* No. of decompressed Bytes per scan line */ + int jpegquality, /* Compression quality level */ + jpegtablesmode, /* What to put in JPEGTables */ + samplesperclump, + scancount; /* No. of scan lines accumulated */ + uint16 h_sampling, /* Luminance sampling factors */ + v_sampling, + photometric; /* Copy of "PhotometricInterpretation" tag value */ + u_char jpegcolormode; /* Who performs RGB <-> YCbCr conversion? */ + /* JPEGCOLORMODE_RAW <=> TIFF Library does conversion */ + /* JPEGCOLORMODE_RGB <=> JPEG Library does conversion */ + } OJPEGState; +#define OJState(tif)((OJPEGState*)(tif)->tif_data) + +static const TIFFFieldInfo ojpegFieldInfo[]=/* JPEG-specific TIFF-record tags */ + { + + /* This is the current JPEG-in-TIFF metadata-encapsulation tag, and its + treatment in this file is idiosyncratic. It should never appear in a + "source" image conforming to the TIFF Version 6.0 specification, so we + arrange to report an error if it appears. But in order to support possible + future conversion of "old" JPEG-in-TIFF encapsulations to "new" ones, we + might wish to synthesize an equivalent value to be returned by the TIFF + Library's "getfield" method. So, this table tells the TIFF Library to pass + these records to us in order to filter them below. + */ + { + TIFFTAG_JPEGTABLES ,TIFF_VARIABLE,TIFF_VARIABLE, + TIFF_UNDEFINED,FIELD_JPEGTABLES ,FALSE,TRUE ,"JPEGTables" + }, + + /* These tags are defined by the TIFF Version 6.0 specification and are now + obsolete. This module reads them from an old "source" image, but it never + writes them to a new "destination" image. + */ + { + TIFFTAG_JPEGPROC ,1 ,1 , + TIFF_SHORT ,FIELD_JPEGPROC ,FALSE,FALSE,"JPEGProc" + }, + { + TIFFTAG_JPEGIFOFFSET ,1 ,1 , + TIFF_LONG ,FIELD_JPEGIFOFFSET ,FALSE,FALSE,"JPEGInterchangeFormat" + }, + { + TIFFTAG_JPEGIFBYTECOUNT ,1 ,1 , + TIFF_LONG ,FIELD_JPEGIFBYTECOUNT ,FALSE,FALSE,"JPEGInterchangeFormatLength" + }, + { + TIFFTAG_JPEGRESTARTINTERVAL ,1 ,1 , + TIFF_SHORT ,FIELD_JPEGRESTARTINTERVAL ,FALSE,FALSE,"JPEGRestartInterval" + }, + { + TIFFTAG_JPEGLOSSLESSPREDICTORS,TIFF_VARIABLE,TIFF_VARIABLE, + TIFF_SHORT ,FIELD_JPEGLOSSLESSPREDICTORS,FALSE,TRUE ,"JPEGLosslessPredictors" + }, + { + TIFFTAG_JPEGPOINTTRANSFORM ,TIFF_VARIABLE,TIFF_VARIABLE, + TIFF_SHORT ,FIELD_JPEGPOINTTRANSFORM ,FALSE,TRUE ,"JPEGPointTransforms" + }, + { + TIFFTAG_JPEGQTABLES ,TIFF_VARIABLE,TIFF_VARIABLE, + TIFF_LONG ,FIELD_JPEGQTABLES ,FALSE,TRUE ,"JPEGQTables" + }, + { + TIFFTAG_JPEGDCTABLES ,TIFF_VARIABLE,TIFF_VARIABLE, + TIFF_LONG ,FIELD_JPEGDCTABLES ,FALSE,TRUE ,"JPEGDCTables" + }, + { + TIFFTAG_JPEGACTABLES ,TIFF_VARIABLE,TIFF_VARIABLE, + TIFF_LONG ,FIELD_JPEGACTABLES ,FALSE,TRUE ,"JPEGACTables" + }, + { + TIFFTAG_WANG_PAGECONTROL ,TIFF_VARIABLE,1 , + TIFF_LONG ,FIELD_WANG_PAGECONTROL ,FALSE,FALSE,"WANG PageControl" + }, + + /* This is a pseudo tag intended for internal use only by the TIFF Library and + its clients, which should never appear in an input/output image file. It + specifies whether the TIFF Library will perform YCbCr<->RGB color-space + conversion (JPEGCOLORMODE_RAW <=> 0) or ask the JPEG Library to do it + (JPEGCOLORMODE_RGB <=> 1). + */ + { + TIFFTAG_JPEGCOLORMODE ,0 ,0 , + TIFF_ANY ,FIELD_PSEUDO ,FALSE,FALSE,"JPEGColorMode" + } + }; +static const char JPEGLib_name[]={"JPEG Library"}, + bad_bps[]={"%u BitsPerSample not allowed for JPEG"}, +# ifdef never + no_write_frac[]={"fractional scan line discarded"}, +# endif + no_read_frac[]={"fractional scan line not read"}, + no_jtable_space[]={"No space for JPEGTables"}; + +/* The following diagnostic subroutines interface with and replace default + subroutines in the JPEG Library. Our basic strategy is to use "setjmp()"/ + "longjmp()" in order to return control to the TIFF Library when the JPEG + library detects an error, and to use TIFF Library subroutines for displaying + diagnostic messages to a client application. +*/ +static void +TIFFojpeg_error_exit(register j_common_ptr cinfo) + { char buffer[JMSG_LENGTH_MAX]; + + (*cinfo->err->format_message)(cinfo,buffer); + TIFFError(JPEGLib_name,buffer); /* Display error message */ + jpeg_abort(cinfo); /* Clean up JPEG Library state */ + LONGJMP(((OJPEGState *)cinfo)->exit_jmpbuf,1); /* Return to TIFF client */ + } + +static void +TIFFojpeg_output_message(register j_common_ptr cinfo) + { char buffer[JMSG_LENGTH_MAX]; + + /* This subroutine is invoked only for warning messages, since the JPEG + Library's "error_exit" method does its own thing and "trace_level" is never + set > 0. + */ + (*cinfo->err->format_message)(cinfo,buffer); + TIFFWarning(JPEGLib_name,buffer); + } + +/* The following subroutines, which also interface with the JPEG Library, exist + mainly in limit the side effects of "setjmp()" and convert JPEG normal/error + conditions into TIFF Library return codes. +*/ +#define CALLJPEG(sp,fail,op)(SETJMP((sp)->exit_jmpbuf)?(fail):(op)) +#define CALLVJPEG(sp,op)CALLJPEG(sp,0,((op),1)) +#ifdef never + +static int +TIFFojpeg_create_compress(register OJPEGState *sp) + { + sp->cinfo.c.err = jpeg_std_error(&sp->err); /* Initialize error handling */ + sp->err.error_exit = TIFFojpeg_error_exit; + sp->err.output_message = TIFFojpeg_output_message; + return CALLVJPEG(sp,jpeg_create_compress(&sp->cinfo.c)); + } + +static int +TIFFojpeg_finish_compress(register OJPEGState *sp) + {return CALLVJPEG(sp,jpeg_finish_compress(&sp->cinfo.c));} + +static int +TIFFojpeg_set_colorspace(register OJPEGState *sp,J_COLOR_SPACE colorspace) + {return CALLVJPEG(sp,jpeg_set_colorspace(&sp->cinfo.c,colorspace));} + +static int +TIFFojpeg_set_defaults(register OJPEGState *sp) + {return CALLVJPEG(sp,jpeg_set_defaults(&sp->cinfo.c));} + +static int +TIFFojpeg_set_quality(register OJPEGState *sp,int quality,boolean force_baseline) + {return CALLVJPEG(sp,jpeg_set_quality(&sp->cinfo.c,quality,force_baseline));} + +static int +TIFFojpeg_start_compress(register OJPEGState *sp,boolean write_all_tables) + {return CALLVJPEG(sp,jpeg_start_compress(&sp->cinfo.c,write_all_tables));} + +static int +TIFFojpeg_suppress_tables(register OJPEGState *sp,boolean suppress) + {return CALLVJPEG(sp,jpeg_suppress_tables(&sp->cinfo.c,suppress));} + +static int +TIFFojpeg_write_raw_data(register OJPEGState *sp,JSAMPIMAGE data,int num_lines) + { return + CALLJPEG(sp,-1,(int)jpeg_write_raw_data(&sp->cinfo.c,data,(JDIMENSION)num_lines)); + } + +static int +TIFFojpeg_write_scanlines(register OJPEGState *sp,JSAMPARRAY scanlines, + int num_lines) + { return + CALLJPEG(sp,-1,(int)jpeg_write_scanlines(&sp->cinfo.c,scanlines,(JDIMENSION)num_lines)); + } + +static int +TIFFojpeg_write_tables(register OJPEGState *sp) + {return CALLVJPEG(sp,jpeg_write_tables(&sp->cinfo.c));} +#else /* well, hardly ever */ + +static int +_notSupported(register TIFF *tif) + { const TIFFCodec *c = TIFFFindCODEC(tif->tif_dir.td_compression); + + TIFFError(tif->tif_name,"%s compression is not supported",c->name); + return 0; + } +#endif /* never */ + +static int +TIFFojpeg_abort(register OJPEGState *sp) + {return CALLVJPEG(sp,jpeg_abort(&sp->cinfo.comm));} + +static JSAMPARRAY +TIFFojpeg_alloc_sarray(register OJPEGState *sp,int pool_id, + JDIMENSION samplesperrow,JDIMENSION numrows) + { return + CALLJPEG(sp,0,(*sp->cinfo.comm.mem->alloc_sarray)(&sp->cinfo.comm,pool_id,samplesperrow, numrows)); + } + +static int +TIFFojpeg_create_decompress(register OJPEGState *sp) + { + sp->cinfo.d.err = jpeg_std_error(&sp->err); /* Initialize error handling */ + sp->err.error_exit = TIFFojpeg_error_exit; + sp->err.output_message = TIFFojpeg_output_message; + return CALLVJPEG(sp,jpeg_create_decompress(&sp->cinfo.d)); + } + +static int +TIFFojpeg_destroy(register OJPEGState *sp) + {return CALLVJPEG(sp,jpeg_destroy(&sp->cinfo.comm));} + +static int +TIFFojpeg_finish_decompress(register OJPEGState *sp) + {return CALLJPEG(sp,-1,(int)jpeg_finish_decompress(&sp->cinfo.d));} + +static int +TIFFojpeg_read_header(register OJPEGState *sp,boolean require_image) + {return CALLJPEG(sp,-1,jpeg_read_header(&sp->cinfo.d,require_image));} + +static int +TIFFojpeg_read_raw_data(register OJPEGState *sp,JSAMPIMAGE data,int max_lines) + { + return + CALLJPEG(sp,-1,(int)jpeg_read_raw_data(&sp->cinfo.d,data,(JDIMENSION)max_lines)); + } + +static int +TIFFojpeg_read_scanlines(register OJPEGState *sp,JSAMPARRAY scanlines, + int max_lines) + { return + CALLJPEG(sp,-1,(int)jpeg_read_scanlines(&sp->cinfo.d,scanlines,(JDIMENSION)max_lines)); + } + +static int +TIFFojpeg_start_decompress(register OJPEGState *sp) + {return CALLVJPEG(sp,jpeg_start_decompress(&sp->cinfo.d));} +#ifdef never + +/* The following subroutines comprise a JPEG Library "destination" data manager + by directing compressed data from the JPEG Library to a TIFF Library output + buffer. +*/ +static void +std_init_destination(register j_compress_ptr cinfo){} /* "Dummy" stub */ + +static boolean +std_empty_output_buffer(register j_compress_ptr cinfo) + { +# define sp ((OJPEGState *)cinfo) + register TIFF *tif = sp->tif; + + tif->tif_rawcc = tif->tif_rawdatasize; /* Entire buffer has been filled */ + TIFFFlushData1(tif); + sp->dest.next_output_byte = (JOCTET *)tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t)tif->tif_rawdatasize; + return TRUE; +# undef sp + } + +static void +std_term_destination(register j_compress_ptr cinfo) + { +# define sp ((OJPEGState *)cinfo) + register TIFF *tif = sp->tif; + + /* NB: The TIFF Library does the final buffer flush. */ + tif->tif_rawcp = (tidata_t)sp->dest.next_output_byte; + tif->tif_rawcc = tif->tif_rawdatasize - (tsize_t)sp->dest.free_in_buffer; +# undef sp + } + +/*ARGSUSED*/ static void +TIFFojpeg_data_dest(register OJPEGState *sp,TIFF *tif) + { + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = std_init_destination; + sp->dest.empty_output_buffer = std_empty_output_buffer; + sp->dest.term_destination = std_term_destination; + } + + +/* Alternate destination manager to output JPEGTables field: */ + +static void +tables_init_destination(register j_compress_ptr cinfo) + { +# define sp ((OJPEGState *)cinfo) + /* The "jpegtables_length" field is the allocated buffer size while building */ + sp->dest.next_output_byte = (JOCTET *)sp->jpegtables; + sp->dest.free_in_buffer = (size_t)sp->jpegtables_length; +# undef sp + } + +static boolean +tables_empty_output_buffer(register j_compress_ptr cinfo) + { void *newbuf; +# define sp ((OJPEGState *)cinfo) + + /* The entire buffer has been filled, so enlarge it by 1000 bytes. */ + if (!( newbuf = _TIFFrealloc( (tdata_t)sp->jpegtables + , (tsize_t)(sp->jpegtables_length + 1000) + ) + ) + ) ERREXIT1(cinfo,JERR_OUT_OF_MEMORY,100); + sp->dest.next_output_byte = (JOCTET *)newbuf + sp->jpegtables_length; + sp->dest.free_in_buffer = (size_t)1000; + sp->jpegtables = newbuf; + sp->jpegtables_length += 1000; + return TRUE; +# undef sp + } + +static void +tables_term_destination(register j_compress_ptr cinfo) + { +# define sp ((OJPEGState *)cinfo) + /* Set tables length to no. of Bytes actually emitted. */ + sp->jpegtables_length -= sp->dest.free_in_buffer; +# undef sp + } + +/*ARGSUSED*/ static int +TIFFojpeg_tables_dest(register OJPEGState *sp, TIFF *tif) + { + + /* Allocate a working buffer for building tables. The initial size is 1000 + Bytes, which is usually adequate. + */ + if (sp->jpegtables) _TIFFfree(sp->jpegtables); + if (!(sp->jpegtables = (void*) + _TIFFmalloc((tsize_t)(sp->jpegtables_length = 1000)) + ) + ) + { + sp->jpegtables_length = 0; + TIFFError("TIFFojpeg_tables_dest",no_jtable_space); + return 0; + }; + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = tables_init_destination; + sp->dest.empty_output_buffer = tables_empty_output_buffer; + sp->dest.term_destination = tables_term_destination; + return 1; + } +#endif /* never */ + +/* The following subroutines comprise a JPEG Library "source" data manager by + by directing compressed data to the JPEG Library from a TIFF Library input + buffer. +*/ +static void +std_init_source(register j_decompress_ptr cinfo) + { +# define sp ((OJPEGState *)cinfo) + register TIFF *tif = sp->tif; + + if (sp->src.bytes_in_buffer == 0) + { + sp->src.next_input_byte = (const JOCTET *)tif->tif_rawdata; + sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; + }; +# undef sp + } + +static boolean +std_fill_input_buffer(register j_decompress_ptr cinfo) + { static const JOCTET dummy_EOI[2]={0xFF,JPEG_EOI}; +# define sp ((OJPEGState *)cinfo) + + /* Control should never get here, since an entire strip/tile is read into + memory before the decompressor is called; thus, data should have been + supplied by the "init_source" method. ...But, sometimes things fail. + */ + WARNMS(cinfo,JWRN_JPEG_EOF); + sp->src.next_input_byte = dummy_EOI; /* Insert a fake EOI marker */ + sp->src.bytes_in_buffer = sizeof dummy_EOI; + return TRUE; +# undef sp + } + +static void +std_skip_input_data(register j_decompress_ptr cinfo,long num_bytes) + { +# define sp ((OJPEGState *)cinfo) + + if (num_bytes > 0) + if (num_bytes > (long)sp->src.bytes_in_buffer) /* oops: buffer overrun */ + (void)std_fill_input_buffer(cinfo); + else + { + sp->src.next_input_byte += (size_t)num_bytes; + sp->src.bytes_in_buffer -= (size_t)num_bytes; + } +# undef sp + } + +/*ARGSUSED*/ static void +std_term_source(register j_decompress_ptr cinfo){} /* "Dummy" stub */ + +/* Allocate temporary I/O buffers for downsampled data, using values computed in + "jpeg_start_{de}compress()". We use the JPEG Library's allocator so that + buffers will be released automatically when done with a strip/tile. This is + also a handy place to compute samplesperclump, bytesperline, etc. +*/ +static int +alloc_downsampled_buffers(TIFF *tif,jpeg_component_info *comp_info, + int num_components) + { register OJPEGState *sp = OJState(tif); + + sp->samplesperclump = 0; + if (num_components > 0) + { int ci = 0; + register jpeg_component_info *compptr = comp_info; + + do + { JSAMPARRAY buf; + + sp->samplesperclump += + compptr->h_samp_factor * compptr->v_samp_factor; + if (!(buf = TIFFojpeg_alloc_sarray( sp + , JPOOL_IMAGE + , compptr->width_in_blocks*DCTSIZE + , compptr->v_samp_factor *DCTSIZE + ) + ) + ) return 0; + sp->ds_buffer[ci] = buf; + } + while (++compptr,++ci < num_components); + }; + return 1; + } +#ifdef never + +/* JPEG Encoding begins here. */ + +static void +unsuppress_quant_table(register OJPEGState *sp,int tblno) + { register JQUANT_TBL *qtbl; + + if (qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) qtbl->sent_table = FALSE; + } + +static void +unsuppress_huff_table(register OJPEGState *sp,register int tblno) + { register JHUFF_TBL *htbl; + + if ( (htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) + || (htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) + ) htbl->sent_table = FALSE; + } + +static int +prepare_JPEGTables(register TIFF *tif) + { register OJPEGState *sp = OJState(tif); + + /* Initialize quantization tables for the current quality setting, and mark for + output only the tables that we want. Note that chrominance tables are + currently used only with YCbCr. + */ + if ( !TIFFojpeg_set_quality(sp,sp->jpegquality,FALSE); + || !TIFFojpeg_suppress_tables(sp,TRUE) + ) return 0; + if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) + { + unsuppress_quant_table(sp,0); + if (sp->photometric == PHOTOMETRIC_YCBCR) unsuppress_quant_table(sp,1); + } + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) + { + unsuppress_huff_table(sp,0); + if (sp->photometric == PHOTOMETRIC_YCBCR) unsuppress_huff_table(sp,1); + }; + return TIFFojpeg_tables_dest(sp,tif) && TIFFojpeg_write_tables(sp); + } + +static int +OJPEGSetupEncode(register TIFF *tif) + { static const char module[]={"OJPEGSetupEncode"}; + register OJPEGState *sp = OJState(tif); +# define td (&tif->tif_dir) + + /* Verify miscellaneous parameters. This will need work if the TIFF Library + ever supports different depths for different components, or if the JPEG + Library ever supports run-time depth selection. Neither seems imminent. + */ + if (td->td_bitspersample != BITS_IN_JSAMPLE) + { + TIFFError(module,bad_bps,td->td_bitspersample); + return 0; + }; + + /* Initialize all JPEG parameters to default values. Note that the JPEG + Library's "jpeg_set_defaults()" method needs legal values for the + "in_color_space" and "input_components" fields. + */ + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + sp->cinfo.c.input_components = 1; + if (!TIFFojpeg_set_defaults(sp)) return 0; + switch (sp->photometric = td->td_photometric) /* set per-file parameters */ + { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; +# ifdef COLORIMETRY_SUPPORT + + /* A ReferenceBlackWhite field MUST be present, since the default value + is inapproriate for YCbCr. Fill in the proper value if application + didn't set it. + */ + if (!TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) + { float refbw[6]; + long top = 1L << td->td_bitspersample; + + refbw[0] = 0; + refbw[1] = (float)(top-1L); + refbw[2] = (float)(top>>1); + refbw[3] = refbw[1]; + refbw[4] = refbw[2]; + refbw[5] = refbw[1]; + TIFFSetField(tif,TIFFTAG_REFERENCEBLACKWHITE,refbw); + }; +# endif /* COLORIMETRY_SUPPORT */ + break; + case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ + case PHOTOMETRIC_MASK: + TIFFError(module,"PhotometricInterpretation %d not allowed for JPEG", + (int)sp->photometric); + return 0; + + /* TIFF 6.0 forbids subsampling of all other color spaces */ + + default: sp->h_sampling = sp->v_sampling = 1; + }; + sp->cinfo.c.data_precision = td->td_bitspersample; + if (isTiled(tif)) + { + if (td->td_tilelength % (sp->v_sampling*DCTSIZE)) + { + TIFFError(module,"JPEG tile height must be multiple of %d", + sp->v_sampling*DCTSIZE); + return 0; + }; + if (td->td_tilewidth % (sp->h_sampling*DCTSIZE)) + { + TIFFError(module,"JPEG tile width must be multiple of %d", + sp->h_sampling*DCTSIZE); + return 0; + } + } + else + if ( td->td_rowsperstrip < td->td_imagelength + && (td->td_rowsperstrip % (sp->v_sampling*DCTSIZE)) + ) + { + TIFFError(module,"RowsPerStrip must be multiple of %d for JPEG", + sp->v_sampling*DCTSIZE); + return 0; + }; + if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) + { /* create a JPEGTables field */ + + if (!prepare_JPEGTables(tif)) return 0; + + /* Mark the field "present". We can't use "TIFFSetField()" because + "BEENWRITING" is already set! + */ + TIFFSetFieldBit(tif,FIELD_JPEGTABLES); + tif->tif_flags |= TIFF_DIRTYDIRECT; + } + else + /* We do not support application-supplied JPEG tables, so mark the field + "not present". + */ + TIFFClrFieldBit(tif,FIELD_JPEGTABLES); + TIFFojpeg_data_dest(sp,tif); /* send JPEG output to TIFF Library's buffer */ + return 1; +# undef td + } + +/*ARGSUSED*/ static int +OJPEGEncode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s) + { register OJPEGState *sp = OJState(tif); + + /* Encode a chunk of pixels, where returned data is NOT down-sampled (the + standard case). The data is expected to be written in scan-line multiples. + */ + if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac); + cc /= sp->bytesperline; + while (--cc >= 0) + { JSAMPROW bufptr = (JSAMPROW)buf; + + if (TIFFojpeg_write_scanlines(sp,&bufptr,1) != 1) return 0; + ++tif->tif_row; + buf += sp->bytesperline; + }; + return 1; + } + +/*ARGSUSED*/ static int +OJPEGEncodeRaw(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s) + { register OJPEGState *sp = OJState(tif); + + /* Encode a chunk of pixels, where returned data is down-sampled as per the + sampling factors. The data is expected to be written in scan-line + multiples. + */ + if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac); + cc /= sp->bytesperline; + while (--cc >= 0) + { + if (sp->cinfo.c.num_components > 0) + { int ci = 0, clumpoffset = 0; + register jpeg_component_info *compptr = sp->cinfo.c.comp_info; + + /* The fastest way to separate the data is to make 1 pass over the scan + line for each row of each component. + */ + do + { int ypos = 0; + + do + { int padding; + register JSAMPLE *inptr = (JSAMPLE*)buf + clumpoffset, + *outptr = + sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos]; + /* Cb,Cr both have sampling factors 1, so this is correct */ + register int clumps_per_line = + sp->cinfo.c.comp_info[1].downsampled_width, + xpos; + + padding = (int) + ( compptr->width_in_blocks * DCTSIZE + - clumps_per_line * compptr->h_samp_factor + ); + if (compptr->h_samp_factor == 1) /* Cb & Cr fast path */ + do + { + *outptr++ = inptr[0]; + inptr += sp->samplesperclump; + } + while (--clumps_per_line > 0); + else /* general case */ + do + { + xpos = 0; + do *outptr++ = inptr[xpos]; + while (++xpos < compptr->h_samp_factor); + inptr += sp->samplesperclump; + } + while (--clumps_per_line > 0); + xpos = 0; /* Pad each scan line as needed */ + do outptr[0]=outptr[-1]; while (++outptr,++xpos < padding); + clumpoffset += compptr->h_samp_factor; + } + while (++ypos < compptr->v_samp_factor); + } + while (++compptr,++ci < sp->cinfo.c.num_components); + }; + if (++sp->scancount >= DCTSIZE) + { int n = sp->cinfo.c.max_v_samp_factor*DCTSIZE; + + if (TIFFojpeg_write_raw_data(sp,sp->ds_buffer,n) != n) return 0; + sp->scancount = 0; + }; + ++tif->tif_row++ + buf += sp->bytesperline; + }; + return 1; + } + +static int +OJPEGPreEncode(register TIFF *tif,tsample_t s) + { static const char module[]={"OJPEGPreEncode"}; + uint32 segment_width, segment_height; + int downsampled_input = FALSE; + register OJPEGState *sp = OJState(tif); +# define td (&tif->tif_dir) + + /* Set encoding state at the start of a strip or tile. */ + + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { + sp->cinfo.c.input_components = td->td_samplesperpixel; + if (sp->photometric == PHOTOMETRIC_YCBCR) + { + if (sp->jpegcolormode == JPEGCOLORMODE_RGB) + sp->cinfo.c.in_color_space = JCS_RGB; + else + { + sp->cinfo.c.in_color_space = JCS_YCbCr; + if (sp->h_sampling != 1 || sp->v_sampling != 1) + downsampled_input = TRUE; + }; + if (!TIFFojpeg_set_colorspace(sp,JCS_YCbCr)) return 0; + + /* Set Y sampling factors; we assume "jpeg_set_colorspace()" set the + rest to 1. + */ + sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; + sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; + } + else + { + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + if (!TIFFojpeg_set_colorspace(sp,JCS_UNKNOWN)) return 0; + /* "jpeg_set_colorspace()" set all sampling factors to 1. */ + } + } + else + { + sp->cinfo.c.input_components = 1; + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + if (!TIFFojpeg_set_colorspace(sp,JCS_UNKNOWN)) return 0; + sp->cinfo.c.comp_info[0].component_id = s; + /* "jpeg_set_colorspace()" set all sampling factors to 1. */ + if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) + sp->cinfo.c.comp_info[0].quant_tbl_no = + sp->cinfo.c.comp_info[0].dc_tbl_no = + sp->cinfo.c.comp_info[0].ac_tbl_no = 1; + }; + if (isTiled(tif)) + { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } + else + { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFScanlineSize(tif); + }; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) + { + + /* Scale the expected strip/tile size to match a downsampled component. */ + + segment_width = TIFFhowmany(segment_width,sp->h_sampling); + segment_height = TIFFhowmany(segment_height,sp->v_sampling); + }; + if (segment_width > 65535 || segment_height > 65535) + { + TIFFError(module,"Strip/tile too large for JPEG"); + return 0; + }; + sp->cinfo.c.image_width = segment_width; + sp->cinfo.c.image_height = segment_height; + sp->cinfo.c.write_JFIF_header = /* Don't write extraneous markers */ + sp->cinfo.c.write_Adobe_marker = FALSE; + if (!(sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) /* setup table handling */ + { + if (!TIFFojpeg_set_quality(sp,sp->jpegquality,FALSE)) return 0; + unsuppress_quant_table(sp,0); + unsuppress_quant_table(sp,1); + }; + sp->cinfo.c.optimize_coding = !(sp->jpegtablesmode & JPEGTABLESMODE_HUFF); + tif->tif_encoderow = tif->tif_encodestrip = tif->tif_encodetile = + (sp->cinfo.c.raw_data_in = downsampled_input) + ? OJPEGEncodeRaw : OJPEGEncode; + if ( !TIFFojpeg_start_compress(sp,FALSE) /* start JPEG compressor */ + || downsampled_input /* allocate downsampled-data buffers */ + && !alloc_downsampled_buffers(tif,sp->cinfo.c.comp_info, + sp->cinfo.c.num_components) + ) return 0; + sp->scancount = 0; + return 1; +# undef td + } + +static int +OJPEGPostEncode(register TIFF *tif) + { register OJPEGState *sp = OJState(tif); + + /* Finish up at the end of a strip or tile. */ + + if (sp->scancount > 0) /* emit partial buffer of down-sampled data */ + { + if (sp->scancount < DCTSIZE && sp->cinfo.c.num_components > 0) + { int ci = 0, n; /* Pad the data vertically */ + register jpeg_component_info *compptr = sp->cinfo.c.comp_info; + + do + { tsize_t row_width = + compptr->width_in_blocks*DCTSIZE*sizeof(JSAMPLE); + int ypos = sp->scancount*compptr->v_samp_factor; + + do _TIFFmemcpy( (tdata_t)sp->ds_buffer[ci][ypos] + , (tdata_t)sp->ds_buffer[ci][ypos-1] + , row_width + ); + while (++ypos < compptr->v_samp_factor*DCTSIZE); + } + while (++compptr,++ci < sp->cinfo.c.num_components); + }; + n = sp->cinfo.c.max_v_samp_factor*DCTSIZE; + if (TIFFojpeg_write_raw_data(sp,sp->ds_buffer,n) != n) return 0; + }; + return TIFFojpeg_finish_compress(sp); + } +#endif /* never */ + +/* JPEG Decoding begins here. */ + +static int +OJPEGSetupDecode(register TIFF *tif) + { static const char module[]={"OJPEGSetupDecode"}; + register OJPEGState *sp = OJState(tif); +# define td (&tif->tif_dir) + + /* Verify miscellaneous parameters. This will need work if the TIFF Library + ever supports different depths for different components, or if the JPEG + Library ever supports run-time depth selection. Neither seems imminent. + */ + if (td->td_bitspersample != BITS_IN_JSAMPLE) + { + TIFFError(module,bad_bps,td->td_bitspersample); + return 0; + }; + + /* Almost all old JPEG-in-TIFF encapsulations use 8 bits per sample, but the + following is just a "sanity check", since "OJPEGPreDecode()" actually + depends upon this assumption in certain cases. + */ + if (td->td_bitspersample != 8) + { + TIFFError(module,"Cannot decompress %u bits per sample"); + return 0; + }; + + /* Grab parameters that are same for all strips/tiles. */ + + if ((sp->photometric = td->td_photometric) == PHOTOMETRIC_YCBCR) + { + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + } + else /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = sp->v_sampling = 1; + sp->cinfo.d.src = &sp->src; + sp->src.init_source = std_init_source; + sp->src.fill_input_buffer = std_fill_input_buffer; + sp->src.skip_input_data = std_skip_input_data; + sp->src.resync_to_restart = jpeg_resync_to_restart; + sp->src.term_source = std_term_source; + tif->tif_postdecode = _TIFFNoPostDecode; /* Override Byte-swapping */ + return 1; +# undef td + } + +/*ARGSUSED*/ static int +OJPEGDecode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s) + { static float zeroes[6]; + tsize_t nrows; + register OJPEGState *sp = OJState(tif); + + /* BEWARE OF KLUDGE: If our input file was produced by Microsoft's Wang + Imaging for Windows application, the DC coefficients of + each JPEG image component (Y,Cb,Cr) must be reset at the beginning of each + TIFF "strip", and any JPEG data bits remaining in the decoder's input buffer + must be discarded, up to the next input-Byte storage boundary. To do so, we + create an "ad hoc" interface in the "jdhuff.c" module of IJG JPEG Library + Version 6, and we invoke that interface here before decoding each "strip". + */ + if (sp->is_WANG) jpeg_reset_huff_decode(&sp->cinfo.d,zeroes); + + /* Decode a chunk of pixels, where returned data is NOT down-sampled (the + standard case). The data is expected to be read in scan-line multiples. + */ + if (nrows = sp->cinfo.d.image_height) + { unsigned int bytesperline = isTiled(tif) + ? TIFFTileRowSize(tif) + : TIFFScanlineSize(tif); + + /* WARNING: Unlike "OJPEGDecodeRaw()", below, the no. of Bytes in each + decoded row is calculated here as "bytesperline" instead of + using "sp->bytesperline", which might be a little smaller. This can + occur for an old tiled image whose width isn't a multiple of 8 pixels. + That's illegal according to the TIFF Version 6 specification, but some + test files, like "zackthecat.tif", were built that way. In those cases, + we want to embed the image's true width in our caller's buffer (which is + presumably allocated according to the expected tile width) by + effectively "padding" it with unused Bytes at the end of each row. + */ + do + { JSAMPROW bufptr = (JSAMPROW)buf; + + if (TIFFojpeg_read_scanlines(sp,&bufptr,1) != 1) return 0; + buf += bytesperline; + ++tif->tif_row; + } + while ((cc -= bytesperline) > 0 && --nrows > 0); + }; + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFojpeg_finish_decompress(sp); + } + +/*ARGSUSED*/ static int +OJPEGDecodeRaw(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s) + { static float zeroes[6]; + tsize_t nrows; + register OJPEGState *sp = OJState(tif); + + /* BEWARE OF KLUDGE: If our input file was produced by Microsoft's Wang + Imaging for Windows application, the DC coefficients of + each JPEG image component (Y,Cb,Cr) must be reset at the beginning of each + TIFF "strip", and any JPEG data bits remaining in the decoder's input buffer + must be discarded, up to the next input-Byte storage boundary. To do so, we + create an "ad hoc" interface in the "jdhuff.c" module of IJG JPEG Library + Version 6, and we invoke that interface here before decoding each "strip". + */ + if (sp->is_WANG) jpeg_reset_huff_decode(&sp->cinfo.d,zeroes); + + /* Decode a chunk of pixels, where returned data is down-sampled as per the + sampling factors. The data is expected to be read in scan-line multiples. + */ + if (nrows = sp->cinfo.d.image_height) + do + { + if (sp->scancount >= DCTSIZE) /* reload downsampled-data buffer */ + { int n = sp->cinfo.d.max_v_samp_factor*DCTSIZE; + + if (TIFFojpeg_read_raw_data(sp,sp->ds_buffer,n) != n) return 0; + sp->scancount = 0; + }; + if (sp->cinfo.d.num_components > 0) + { int ci = 0, clumpoffset = 0; + register jpeg_component_info *compptr = sp->cinfo.d.comp_info; + + /* The fastest way to separate the data is: make 1 pass over the scan + line for each row of each component. + */ + do + { int ypos = 0; + + if (compptr->h_samp_factor == 1) /* Cb & Cr fast path */ + do + { register JSAMPLE *inptr = + sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos], + *outptr = (JSAMPLE *)buf + clumpoffset; + /* Cb & Cr have sampling factors = 1, so this is correct */ + register int clumps_per_line = + sp->cinfo.d.comp_info[1].downsampled_width; + + do *outptr = *inptr++; + while ( (outptr += sp->samplesperclump) + , --clumps_per_line > 0 + ); + } + while ( (clumpoffset += compptr->h_samp_factor) + , ++ypos < compptr->v_samp_factor + ); + else /* general case */ + do + { register JSAMPLE *inptr = + sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos], + *outptr = (JSAMPLE *)buf + clumpoffset; + /* Cb & Cr have sampling factors = 1, so this is correct */ + register int clumps_per_line = + sp->cinfo.d.comp_info[1].downsampled_width; + + do + { register int xpos = 0; + + do outptr[xpos] = *inptr++; + while (++xpos < compptr->h_samp_factor); + } + while ( (outptr += sp->samplesperclump) + , --clumps_per_line > 0 + ); + } + while ( (clumpoffset += compptr->h_samp_factor) + , ++ypos < compptr->v_samp_factor + ); + } + while (++compptr,++ci < sp->cinfo.d.num_components); + }; + ++sp->scancount; + buf += sp->bytesperline; + ++tif->tif_row; + } + while ((cc -= sp->bytesperline) > 0 && --nrows > 0); + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFojpeg_finish_decompress(sp); + } + +/* "OJPEGPreDecode()" temporarily forces the JPEG Library to use the following + subroutine as a "dummy" input reader, to fool it into thinking that it has + read the image's 1st "Start of Scan" (SOS) marker and initialize accordingly. +*/ +/*ARGSUSED*/ METHODDEF(int) +fake_SOS_marker(j_decompress_ptr cinfo){return JPEG_REACHED_SOS;} + +/*ARGSUSED*/ METHODDEF(int) +suspend(j_decompress_ptr cinfo){return JPEG_SUSPENDED;} + +/*ARGSUSED*/ static int +OJPEGPreDecode(register TIFF *tif,tsample_t s) + { static const char bad_factors[]={"Improper JPEG sampling factors"}, + module[]={"OJPEGPreDecode"}; + uint32 segment_width, segment_height; + int downsampled_output = FALSE, + is_JFIF; /* <=> JFIF image? */ + J_COLOR_SPACE in_color_space = JCS_UNKNOWN; /* Image's input color space */ + register OJPEGState *sp = OJState(tif); +# define td (&tif->tif_dir) + + tif->tif_predecode = _TIFFNoPreCode; /* Don't call us again */ + + /* BOGOSITY ALERT! MicroSoft's Wang Imaging for Windows application produces + images containing "JPEGInterchangeFormat[Length]" TIFF + records that resemble JFIF-in-TIFF encapsulations but, in fact, violate the + TIFF Version 6 specification in several ways; nevertheless, we try to handle + them gracefully because there are apparently a lot of them around. The + purported "JFIF" data stream in one of these files vaguely resembles a JPEG + "tables only" data stream, except that there's no trailing EOI marker. The + rest of the JPEG data stream lies in a discontiguous file region, identified + by the 0th Strip offset (which is *also* illegal!), where it begins with an + SOS marker and apparently continues to the end of the file. There is no + trailing EOI marker here, either. + */ + is_JFIF = !sp->is_WANG && TIFFFieldSet(tif,FIELD_JPEGIFOFFSET); + + /* Set up to decode a strip or tile. Start by resetting decoder state left + over from any previous strip/tile, in case our client application didn't + read all of that data. Then read the JPEG header data. + */ + if (!TIFFojpeg_abort(sp)) return 0; + + /* Do a preliminary translation of the image's (input) color space from its + TIFF representation to JPEG Library representation. We might have to fix + this up after calling "TIFFojpeg_read_header()", which tries to establish + its own JPEG Library defaults. While we're here, initialize some other + decompression parameters that won't be overridden. + */ + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { + if (sp->h_sampling != 1 || sp->v_sampling != 1) + downsampled_output = TRUE; /* Tentative default */ + switch (sp->photometric) /* default color-space translation */ + { + case PHOTOMETRIC_MINISBLACK: in_color_space = JCS_GRAYSCALE; + break; + case PHOTOMETRIC_RGB : in_color_space = JCS_RGB; + break; + case PHOTOMETRIC_SEPARATED : in_color_space = JCS_CMYK; + break; + case PHOTOMETRIC_YCBCR : in_color_space = JCS_YCbCr; + /* JPEG Library converts YCbCr to RGB? */ + if ( sp->jpegcolormode + == JPEGCOLORMODE_RGB + ) downsampled_output = FALSE; + } + }; + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (isTiled(tif)) + { + if (sp->is_WANG) /* we don't know how to handle it */ + { + TIFFError(module,"Tiled Wang image not supported"); + return 0; + }; + + /* BOGOSITY ALERT! "TIFFTileRowSize()" seems to work fine for modern JPEG- + in-TIFF encapsulations where the image width--like the + tile width--is a multiple of 8 or 16 pixels. But image widths and + heights are aren't restricted to 8- or 16-bit multiples, and we need + the exact Byte count of decompressed scan lines when we call the JPEG + Library. At least one old file ("zackthecat.tif") in the TIFF Library + test suite has widths and heights slightly less than the tile sizes, and + it apparently used the bogus computation below to determine the number + of Bytes per scan line (was this due to an old, broken version of + "TIFFhowmany()"?). Before we get here, "OJPEGSetupDecode()" verified + that our image uses 8-bit samples, so the following check appears to + return the correct answer in all known cases tested to date. + */ + if (is_JFIF || (segment_width & 7) == 0) + sp->bytesperline = TIFFTileRowSize(tif); /* Normal case */ + else + { + /* Was the file-encoder's segment-width calculation bogus? */ + segment_width = (segment_width/sp->h_sampling + 1) * sp->h_sampling; + sp->bytesperline = segment_width * td->td_samplesperpixel; + } + } + else sp->bytesperline = TIFFVStripSize(tif,1); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) + { + + /* Scale the expected strip/tile size to match a downsampled component. */ + + segment_width = TIFFhowmany(segment_width,sp->h_sampling); + segment_height = TIFFhowmany(segment_height,sp->v_sampling); + }; + + /* BEWARE OF KLUDGE: If we have JPEG Interchange File Format (JFIF) image, + then we want to read "metadata" in the bit-stream's + header and validate it against corresponding information in TIFF records. + But if we have a *really old* JPEG file that's not JFIF, then we simply + assign TIFF-record values to JPEG Library variables without checking. + */ + if (is_JFIF) /* JFIF image */ + { unsigned char *end_of_data; + register unsigned char *p; + + /* WARNING: Although the image file contains a JFIF bit stream, it might + also contain some old TIFF records causing "OJPEGVSetField()" + to have allocated quantization or Huffman decoding tables. But when the + JPEG Library reads and parses the JFIF header below, it reallocate these + tables anew without checking for "dangling" pointers, thereby causing a + memory "leak". We have enough information to potentially deallocate the + old tables here, but unfortunately JPEG Library Version 6B uses a "pool" + allocator for small objects, with no deallocation procedure; instead, it + reclaims a whole pool when an image is closed/destroyed, so well-behaved + TIFF client applications (i.e., those which close their JPEG images as + soon as they're no longer needed) will waste memory for a short time but + recover it eventually. But ill-behaved TIFF clients (i.e., those which + keep many JPEG images open gratuitously) can exhaust memory prematurely. + If the JPEG Library ever implements a deallocation procedure, insert + this clean-up code: + */ +# ifdef someday + if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) /* free quant. tables */ + { register int i = 0; + + do + { register JQUANT_TBL *q; + + if (q = sp->cinfo.d.quant_tbl_ptrs[i]) + { + jpeg_free_small(&sp->cinfo.comm,q,sizeof *q); + sp->cinfo.d.quant_tbl_ptrs[i] = 0; + } + } + while (++i < NUM_QUANT_TBLS); + }; + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) /* free Huffman tables */ + { register int i = 0; + + do + { register JHUFF_TBL *h; + + if (h = sp->cinfo.d.dc_huff_tbl_ptrs[i]) + { + jpeg_free_small(&sp->cinfo.comm,h,sizeof *h); + sp->cinfo.d.dc_huff_tbl_ptrs[i] = 0; + }; + if (h = sp->cinfo.d.ac_huff_tbl_ptrs[i]) + { + jpeg_free_small(&sp->cinfo.comm,h,sizeof *h); + sp->cinfo.d.ac_huff_tbl_ptrs[i] = 0; + } + } + while (++i < NUM_HUFF_TBLS); + }; +# endif /* someday */ + + /* Since we might someday wish to try rewriting "old format" JPEG-in-TIFF + encapsulations in "new format" files, try to synthesize the value of a + modern "JPEGTables" TIFF record by scanning the JPEG data from just past + the "Start of Information" (SOI) marker until something other than a + legitimate "table" marker is found, as defined in ISO DIS 10918-1 + Appending B.2.4; namely: + + -- Define Quantization Table (DQT) + -- Define Huffman Table (DHT) + -- Define Arithmetic Coding table (DAC) + -- Define Restart Interval (DRI) + -- Comment (COM) + -- Application data (APPn) + + For convenience, we also accept "Expansion" (EXP) markers, although they + are apparently not a part of normal "table" data. + */ + sp->jpegtables = p = (unsigned char *)sp->src.next_input_byte; + end_of_data = p + sp->src.bytes_in_buffer; + p += 2; + while (p < end_of_data && p[0] == 0xFF) + switch (p[1]) + { + default : goto L; + case 0xC0: /* SOF0 */ + case 0xC1: /* SOF1 */ + case 0xC2: /* SOF2 */ + case 0xC3: /* SOF3 */ + case 0xC4: /* DHT */ + case 0xC5: /* SOF5 */ + case 0xC6: /* SOF6 */ + case 0xC7: /* SOF7 */ + case 0xC9: /* SOF9 */ + case 0xCA: /* SOF10 */ + case 0xCB: /* SOF11 */ + case 0xCC: /* DAC */ + case 0xCD: /* SOF13 */ + case 0xCE: /* SOF14 */ + case 0xCF: /* SOF15 */ + case 0xDB: /* DQT */ + case 0xDD: /* DRI */ + case 0xDF: /* EXP */ + case 0xE0: /* APP0 */ + case 0xE1: /* APP1 */ + case 0xE2: /* APP2 */ + case 0xE3: /* APP3 */ + case 0xE4: /* APP4 */ + case 0xE5: /* APP5 */ + case 0xE6: /* APP6 */ + case 0xE7: /* APP7 */ + case 0xE8: /* APP8 */ + case 0xE9: /* APP9 */ + case 0xEA: /* APP10 */ + case 0xEB: /* APP11 */ + case 0xEC: /* APP12 */ + case 0xED: /* APP13 */ + case 0xEE: /* APP14 */ + case 0xEF: /* APP15 */ + case 0xFE: /* COM */ + p += (p[2] << 8 | p[3]) + 2; + }; + L: if (p - (unsigned char *)sp->jpegtables > 2) /* fake "JPEGTables" */ + { + + /* In case our client application asks, pretend that this image file + contains a modern "JPEGTables" TIFF record by copying to a buffer + the initial part of the JFIF bit-stream that we just scanned, from + the SOI marker through the "metadata" tables, then append an EOI + marker and flag the "JPEGTables" TIFF record as "present". + */ + sp->jpegtables_length = p - (unsigned char*)sp->jpegtables + 2; + p = sp->jpegtables; + if (!(sp->jpegtables = _TIFFmalloc(sp->jpegtables_length))) + { + TIFFError(module,no_jtable_space); + return 0; + }; + _TIFFmemcpy(sp->jpegtables,p,sp->jpegtables_length-2); + p = (unsigned char *)sp->jpegtables + sp->jpegtables_length; + p[-2] = 0xFF; p[-1] = JPEG_EOI; /* Append EOI marker */ + TIFFSetFieldBit(tif,FIELD_JPEGTABLES); + tif->tif_flags |= TIFF_DIRTYDIRECT; + } + else sp->jpegtables = 0; /* Don't simulate "JPEGTables" */ + if (TIFFojpeg_read_header(sp,TRUE) != JPEG_HEADER_OK) return 0; + if ( sp->cinfo.d.image_width != segment_width + || sp->cinfo.d.image_height != segment_height + ) + { + TIFFError(module,"Improper JPEG strip/tile size"); + return 0; + }; + if ( ( td->td_planarconfig == PLANARCONFIG_CONTIG + ? td->td_samplesperpixel + : 1 + ) != sp->cinfo.d.num_components + ) + { + TIFFError(module,"Improper JPEG component count"); + return 0; + }; + if (sp->cinfo.d.data_precision != td->td_bitspersample) + { + TIFFError(module,"Improper JPEG data precision"); + return 0; + }; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { int ci; + + /* Component 0 should have expected sampling factors. */ + + if ( sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling + || sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling + ) + { + TIFFError(module,bad_factors); + return 0; + }; + ci = 1; /* The rest should have sampling factors 1,1 */ + do if ( sp->cinfo.d.comp_info[ci].h_samp_factor != 1 + || sp->cinfo.d.comp_info[ci].v_samp_factor != 1 + ) + { + TIFFError(module,bad_factors); + return 0; + } + while (++ci < sp->cinfo.d.num_components); + } + else + + /* PLANARCONFIG_SEPARATE's single component should have sampling factors + 1,1. + */ + if ( sp->cinfo.d.comp_info[0].h_samp_factor != 1 + || sp->cinfo.d.comp_info[0].v_samp_factor != 1 + ) + { + TIFFError(module,bad_factors); + return 0; + } + } + else /* not JFIF image */ + { int (*save)(j_decompress_ptr cinfo) = sp->cinfo.d.marker->read_markers; + register int i; + + /* We're not assuming that this file's JPEG bit stream has any header + "metadata", so fool the JPEG Library into thinking that we read a + "Start of Input" (SOI) marker and a "Start of Frame" (SOFx) marker, then + force it to read a simulated "Start of Scan" (SOS) marker when we call + "TIFFojpeg_read_header()" below. This should cause the JPEG Library to + establish reasonable defaults. + */ + sp->cinfo.d.marker->saw_SOI = /* Pretend we saw SOI marker */ + sp->cinfo.d.marker->saw_SOF = TRUE; /* Pretend we saw SOF marker */ + sp->cinfo.d.marker->read_markers = + sp->is_WANG ? suspend : fake_SOS_marker; + sp->cinfo.d.global_state = DSTATE_INHEADER; + sp->cinfo.d.Se = DCTSIZE2-1; /* Suppress JPEG Library warning */ + sp->cinfo.d.image_width = segment_width; + sp->cinfo.d.image_height = segment_height; + sp->cinfo.d.data_precision = td->td_bitspersample; + + /* The following color-space initialization, including the complicated + "switch"-statement below, essentially duplicates the logic used by the + JPEG Library's "jpeg_init_colorspace()" subroutine during compression. + */ + sp->cinfo.d.num_components = td->td_planarconfig == PLANARCONFIG_CONTIG + ? td->td_samplesperpixel + : 1; + sp->cinfo.d.comp_info = (jpeg_component_info *) + (*sp->cinfo.d.mem->alloc_small) + ( &sp->cinfo.comm + , JPOOL_IMAGE + , sp->cinfo.d.num_components * sizeof *sp->cinfo.d.comp_info + ); + i = 0; + do + { + sp->cinfo.d.comp_info[i].component_index = i; + sp->cinfo.d.comp_info[i].component_needed = TRUE; + sp->cinfo.d.cur_comp_info[i] = &sp->cinfo.d.comp_info[i]; + } + while (++i < sp->cinfo.d.num_components); + switch (in_color_space) + { + case JCS_UNKNOWN : + i = 0; + do + { + sp->cinfo.d.comp_info[i].component_id = i; + sp->cinfo.d.comp_info[i].h_samp_factor = + sp->cinfo.d.comp_info[i].v_samp_factor = 1; + } + while (++i < sp->cinfo.d.num_components); + break; + case JCS_GRAYSCALE: + sp->cinfo.d.comp_info[0].component_id = + sp->cinfo.d.comp_info[0].h_samp_factor = + sp->cinfo.d.comp_info[0].v_samp_factor = 1; + break; + case JCS_RGB : + sp->cinfo.d.comp_info[0].component_id = 'R'; + sp->cinfo.d.comp_info[1].component_id = 'G'; + sp->cinfo.d.comp_info[2].component_id = 'B'; + i = 0; + do sp->cinfo.d.comp_info[i].h_samp_factor = + sp->cinfo.d.comp_info[i].v_samp_factor = 1; + while (++i < sp->cinfo.d.num_components); + break; + case JCS_CMYK : + sp->cinfo.d.comp_info[0].component_id = 'C'; + sp->cinfo.d.comp_info[1].component_id = 'Y'; + sp->cinfo.d.comp_info[2].component_id = 'M'; + sp->cinfo.d.comp_info[3].component_id = 'K'; + i = 0; + do sp->cinfo.d.comp_info[i].h_samp_factor = + sp->cinfo.d.comp_info[i].v_samp_factor = 1; + while (++i < sp->cinfo.d.num_components); + break; + case JCS_YCbCr : + i = 0; + do + { + sp->cinfo.d.comp_info[i].component_id = i+1; + sp->cinfo.d.comp_info[i].h_samp_factor = + sp->cinfo.d.comp_info[i].v_samp_factor = 1; + sp->cinfo.d.comp_info[i].quant_tbl_no = + sp->cinfo.d.comp_info[i].dc_tbl_no = + sp->cinfo.d.comp_info[i].ac_tbl_no = i > 0; + } + while (++i < sp->cinfo.d.num_components); + sp->cinfo.d.comp_info[0].h_samp_factor = sp->h_sampling; + sp->cinfo.d.comp_info[0].v_samp_factor = sp->v_sampling; + }; + sp->cinfo.d.comps_in_scan = sp->cinfo.d.num_components; + i = TIFFojpeg_read_header(sp,!sp->is_WANG); + sp->cinfo.d.marker->read_markers = save; /* Restore input method */ + if (sp->is_WANG) /* Microsoft Wang Imaging for Windows file */ + { + if (i != JPEG_SUSPENDED) return 0; + + /* BOGOSITY ALERT! Files generated by Microsoft's Wang Imaging + application are a special--and, technically + illegal--case. A JPEG SOS marker and rest of the data stream should + be located at the end of the file, in a position identified by the + 0th Strip offset. + */ + i = td->td_nstrips - 1; + sp->src.next_input_byte = tif->tif_base + td->td_stripoffset[0]; + sp->src.bytes_in_buffer = td->td_stripoffset[i] - + td->td_stripoffset[0] + td->td_stripbytecount[i]; + i = TIFFojpeg_read_header(sp,TRUE); + }; + if (i != JPEG_HEADER_OK) return 0; + }; + + /* The JPEG Library doesn't seem to be as smart as we are about choosing + suitable default input- and output color spaces for decompression, so fix + things up here. + */ + sp->cinfo.d.out_color_space = + ((sp->cinfo.d.jpeg_color_space = in_color_space) == JCS_YCbCr) + ? (sp->jpegcolormode == JPEGCOLORMODE_RGB ? JCS_RGB : JCS_YCbCr) + : JCS_UNKNOWN; /* Suppress color-space handling */ + tif->tif_decoderow = tif->tif_decodestrip = tif->tif_decodetile = + (sp->cinfo.d.raw_data_out = downsampled_output) + ? OJPEGDecodeRaw : OJPEGDecode; + if (!TIFFojpeg_start_decompress(sp)) return 0; /* Start JPEG decompressor */ + if (downsampled_output) /* allocate downsampled-data buffers */ + { + if (!alloc_downsampled_buffers(tif,sp->cinfo.d.comp_info, + sp->cinfo.d.num_components) + ) return 0; + sp->scancount = DCTSIZE; /* mark buffer empty */ + }; + return 1; +# undef td + } + +static int +OJPEGVSetField(register TIFF *tif,ttag_t tag,va_list ap) + { uint32 v32; + register OJPEGState *sp = OJState(tif); +# define td (&tif->tif_dir) + + switch (tag) + { +# ifdef COLORIMETRY_SUPPORT + + /* If a "ReferenceBlackWhite" TIFF tag appears in the file explicitly, undo + any modified default definition that we might have installed below, then + install the real one. + */ + case TIFFTAG_REFERENCEBLACKWHITE : if (td->td_refblackwhite) + { + _TIFFfree(td->td_refblackwhite); + td->td_refblackwhite = 0; + }; +# endif /* COLORIMETRY_SUPPORT */ + default : return + (*sp->vsetparent)(tif,tag,ap); +# ifdef COLORIMETRY_SUPPORT + + /* BEWARE OF KLUDGE: Some old-format JPEG-in-TIFF files, including those + created by Microsoft's Wang Imaging application, + illegally omit a "ReferenceBlackWhite" TIFF tag, even though the TIFF + specification's default is intended for the RGB color space and is in- + appropriate for the YCbCr color space ordinarily used for JPEG images. + Since many TIFF client applications request the value of this tag + immediately after a TIFF image directory is parsed, and before any other + code in this module receives control, we are forced to fix this problem + very early in image-file processing. Fortunately, legal TIFF files are + supposed to store their tags in numeric order, so a mandatory + "PhotometricInterpretation" tag should always appear before an optional + "ReferenceBlackWhite" tag. So, we slyly peek ahead when we discover the + desired photometry, by installing modified black and white reference + levels. + */ + case TIFFTAG_PHOTOMETRIC : + if ( (v32 = (*sp->vsetparent)(tif,tag,ap)) + && td->td_photometric == PHOTOMETRIC_YCBCR + ) + if (td->td_refblackwhite = _TIFFmalloc(6*sizeof(float))) + { register long top = 1 << td->td_bitspersample; + + td->td_refblackwhite[0] = 0; + td->td_refblackwhite[1] = td->td_refblackwhite[3] = + td->td_refblackwhite[5] = top - 1; + td->td_refblackwhite[2] = td->td_refblackwhite[4] = top >> 1; + } + else + { + TIFFError(tif->tif_name,"Cannot define default reference black and white levels"); + v32 = 0; + }; + return v32; +# endif /* COLORIMETRY_SUPPORT */ + + /* BEWARE OF KLUDGE: According to Charles Auer <Bumble731@msn.com>, if our + input is a multi-image (multi-directory) JPEG-in-TIFF + file created by Microsoft's Wang Imaging application, for some reason + the first directory excludes the vendor-specific "WANG PageControl" tag + (32934) that we check below, so the only other way to identify these + directories is apparently to look for a software-identification tag with + the substring, "Wang Labs". Single-image files can apparently pass both + tests, which causes no harm here, but what a mess this is! + */ + case TIFFTAG_SOFTWARE : if ( (v32 = (*sp->vsetparent) + (tif,tag,ap) + ) + && strstr( td->td_software + , "Wang Labs" + ) + ) sp->is_WANG = 1; + return v32; + case TIFFTAG_JPEGPROC : + case TIFFTAG_JPEGIFOFFSET : + case TIFFTAG_JPEGIFBYTECOUNT : + case TIFFTAG_JPEGRESTARTINTERVAL : + case TIFFTAG_JPEGLOSSLESSPREDICTORS: + case TIFFTAG_JPEGPOINTTRANSFORM : + case TIFFTAG_JPEGQTABLES : + case TIFFTAG_JPEGDCTABLES : + case TIFFTAG_JPEGACTABLES : + case TIFFTAG_WANG_PAGECONTROL : + case TIFFTAG_JPEGCOLORMODE : ; + }; + v32 = va_arg(ap,uint32); /* No. of values in this TIFF record */ + + /* BEWARE: The following actions apply only if we are reading a "source" TIFF + image to be decompressed for a client application program. If we + ever enhance this file's CODEC to write "destination" JPEG-in-TIFF images, + we'll need an "if"- and another "switch"-statement below, because we'll + probably want to store these records' values in some different places. Most + of these need not be parsed here in order to decode JPEG bit stream, so we + set boolean flags to note that they have been seen, but we otherwise ignore + them. + */ + switch (tag) + { JHUFF_TBL **h; + float *refbw; + + /* Validate the JPEG-process code. */ + + case TIFFTAG_JPEGPROC : + switch (v32) + { + default: TIFFError(tif->tif_name,"Unknown JPEG process"); + return 0; + case 14: TIFFError(JPEGLib_name, + "Does not support lossless Huffman coding"); + return 0; + case 1: ; + }; + break; + + /* The TIFF Version 6.0 specification says that if the value of a TIFF + "JPEGInterchangeFormat" record is 0, then we are to behave as if this + record were absent; i.e., the data does *not* represent a JPEG Inter- + change Format File (JFIF), so don't even set the boolean "I've been + here" flag below. Otherwise, the field's value represents the file + offset of the JPEG SOI marker. + */ + case TIFFTAG_JPEGIFOFFSET : + if (v32) + { + sp->src.next_input_byte = tif->tif_base + v32; + break; + }; + return 1; + case TIFFTAG_JPEGIFBYTECOUNT : + sp->src.bytes_in_buffer = v32; + break; + + /* The TIFF Version 6.0 specification says that if the JPEG "Restart" + marker interval is 0, then the data has no "Restart" markers; i.e., we + must behave as if this TIFF record were absent. So, don't even set the + boolean "I've been here" flag below. + */ + case TIFFTAG_JPEGRESTARTINTERVAL : + if (v32) + { + sp->cinfo.d.restart_interval = v32; + break; + }; + return 1; + + /* We have a vector of offsets to quantization tables, so load 'em! */ + + case TIFFTAG_JPEGQTABLES : + if (v32) + { uint32 *v; + int i; + + if (v32 > NUM_QUANT_TBLS) + { + TIFFError(tif->tif_name,"Too many quantization tables"); + return 0; + }; + i = 0; + v = va_arg(ap,uint32 *); + do /* read quantization table */ + { register UINT8 *from = tif->tif_base + *v++; + register UINT16 *to = (sp->cinfo.d.quant_tbl_ptrs[i] = + jpeg_alloc_quant_table(&sp->cinfo.comm) + )->quantval; + register int j = DCTSIZE2; + + do *to++ = *from++; while (--j > 0); + } + while (++i < v32); + sp->jpegtablesmode |= JPEGTABLESMODE_QUANT; + }; + break; + + /* We have a vector of offsets to DC Huffman tables, so load 'em! */ + + case TIFFTAG_JPEGDCTABLES : + h = sp->cinfo.d.dc_huff_tbl_ptrs; + goto L; + + /* We have a vector of offsets to AC Huffman tables, so load 'em! */ + + case TIFFTAG_JPEGACTABLES : + h = sp->cinfo.d.ac_huff_tbl_ptrs; + L: if (v32) + { uint32 *v; + int i; + + if (v32 > NUM_HUFF_TBLS) + { + TIFFError(tif->tif_name,"Too many Huffman tables"); + return 0; + }; + v = va_arg(ap,uint32 *); + i = 0; + do /* copy each Huffman table */ + { int size = 0; + register UINT8 *from = tif->tif_base + *v++, + *to = (*h++ = + jpeg_alloc_huff_table(&sp->cinfo.comm) + )->bits; + register int j = sizeof (*h)->bits; + + /* WARNING: This code relies on the fact that an image file not + "memory mapped" was read entirely into a single + buffer by "TIFFInitOJPEG()", so we can do a fast memory-to- + memory copy here. Each table consists of 16 Bytes, which are + suffixed to a 0 Byte when copied, followed by a variable + number of Bytes whose length is the sum of the first 16. + */ + *to++ = 0; + while (--j > 0) size += *to++ = *from++; /* Copy 16 Bytes */ + if (size > sizeof (*h)->huffval/sizeof *(*h)->huffval) + { + TIFFError(tif->tif_name,"Huffman table too big"); + return 0; + }; + if ((j = size) > 0) do *to++ = *from++; while (--j > 0); + while (++size <= sizeof (*h)->huffval/sizeof *(*h)->huffval) + *to++ = 0; /* Zero the rest of the table for cleanliness */ + } + while (++i < v32); + sp->jpegtablesmode |= JPEGTABLESMODE_HUFF; + }; + break; + + /* The following vendor-specific TIFF tag occurs in (highly illegal) files + generated by MicroSoft's Wang Imaging for Windows application. These + can apparently have several "pages", in which case this tag specifies + the offset of a "page control" structure, which we don't currently know + how to handle. 0 indicates a 1-page image with no "page control", which + we make a feeble effort to handle. + */ + case TIFFTAG_WANG_PAGECONTROL : + if (v32 == 0) v32 = -1; + sp->is_WANG = v32; + tag = TIFFTAG_JPEGPROC+FIELD_WANG_PAGECONTROL-FIELD_JPEGPROC; + break; + + /* This pseudo tag indicates whether we think that our caller is supposed + to do YCbCr<->RGB color-space conversion (JPEGCOLORMODE_RAW <=> 0) or + whether we must ask the JPEG Library to do it (JPEGCOLORMODE_RGB <=> 1). + */ + case TIFFTAG_JPEGCOLORMODE : + sp->jpegcolormode = v32; + + /* Mark the image to indicate whether returned data is up-sampled, so + that "TIFF{Strip,Tile}Size()" reflect the true amount of data present. + */ + v32 = tif->tif_flags; /* Save flags temporarily */ + tif->tif_flags &= ~TIFF_UPSAMPLED; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + if ( td->td_photometric == PHOTOMETRIC_YCBCR + && sp->jpegcolormode == JPEGCOLORMODE_RGB + ) tif->tif_flags |= TIFF_UPSAMPLED; + else + if ( (td->td_ycbcrsubsampling[1]<<16|td->td_ycbcrsubsampling[0]) + != (1 << 16 | 1) + ) /* XXX what about up-sampling? */; + + /* If the up-sampling state changed, re-calculate tile size. */ + + if ((tif->tif_flags ^ v32) & TIFF_UPSAMPLED) + { + tif->tif_tilesize = TIFFTileSize(tif); + tif->tif_flags |= TIFF_DIRTYDIRECT; + }; + return 1; + }; + TIFFSetFieldBit(tif,tag-TIFFTAG_JPEGPROC+FIELD_JPEGPROC); + return 1; +# undef td + } + +static int +OJPEGVGetField(register TIFF *tif,ttag_t tag,va_list ap) + { register OJPEGState *sp = OJState(tif); + + switch (tag) + { + + /* If this file has managed to synthesize a set of consolidated "metadata" + tables for the current (post-TIFF Version 6.0 specification) JPEG-in- + TIFF encapsulation strategy, then tell our caller about them; otherwise, + keep mum. + */ + case TIFFTAG_JPEGTABLES : + if (sp->jpegtables_length) /* we have "new"-style JPEG tables */ + { + *va_arg(ap,uint32 *) = sp->jpegtables_length; + *va_arg(ap,char **) = sp->jpegtables; + return 1; + }; + + /* This pseudo tag indicates whether we think that our caller is supposed + to do YCbCr<->RGB color-space conversion (JPEGCOLORMODE_RAW <=> 0) or + whether we must ask the JPEG Library to do it (JPEGCOLORMODE_RGB <=> 1). + */ + case TIFFTAG_JPEGCOLORMODE : + *va_arg(ap,uint32 *) = sp->jpegcolormode; + return 1; + + /* The following tags are defined by the TIFF Version 6.0 specification + and are obsolete. If our caller asks for information about them, do not + return anything, even if we parsed them in an old-format "source" image. + */ + case TIFFTAG_JPEGPROC : + case TIFFTAG_JPEGIFOFFSET : + case TIFFTAG_JPEGIFBYTECOUNT : + case TIFFTAG_JPEGRESTARTINTERVAL : + case TIFFTAG_JPEGLOSSLESSPREDICTORS: + case TIFFTAG_JPEGPOINTTRANSFORM : + case TIFFTAG_JPEGQTABLES : + case TIFFTAG_JPEGDCTABLES : + case TIFFTAG_JPEGACTABLES : return 0; + }; + return (*sp->vgetparent)(tif,tag,ap); + } + +/*ARGSUSED*/ static void +OJPEGPrintDir(register TIFF *tif,FILE *fd,long flags) + { register OJPEGState *sp = OJState(tif); + + if (sp->jpegtables_length) + fprintf(fd," JPEG Table Data: <present>, %lu bytes\n", + sp->jpegtables_length); + } + +static uint32 +OJPEGDefaultStripSize(register TIFF *tif,register uint32 s) + { register OJPEGState *sp = OJState(tif); +# define td (&tif->tif_dir) + + if ((s = (*sp->defsparent)(tif,s)) < td->td_imagelength) + s = TIFFroundup(s,td->td_ycbcrsubsampling[1]*DCTSIZE); + return s; +# undef td + } + +static void +OJPEGDefaultTileSize(register TIFF *tif,register uint32 *tw,register uint32 *th) + { register OJPEGState *sp = OJState(tif); +# define td (&tif->tif_dir) + + (*sp->deftparent)(tif,tw,th); + *tw = TIFFroundup(*tw,td->td_ycbcrsubsampling[0]*DCTSIZE); + *th = TIFFroundup(*th,td->td_ycbcrsubsampling[1]*DCTSIZE); +# undef td + } + +static void +OJPEGCleanUp(register TIFF *tif) + { register OJPEGState *sp; + + if (sp = OJState(tif)) + { + TIFFojpeg_destroy(sp); /* Release JPEG Library variables */ + if (sp->jpegtables) _TIFFfree(sp->jpegtables); + + /* If the image file isn't "memory mapped" and we read it all into a + single, large memory buffer, free the buffer now. + */ + if (!isMapped(tif) && tif->tif_base) /* free whole-file buffer */ + { + _TIFFfree(tif->tif_base); + tif->tif_base = 0; + tif->tif_size = 0; + }; + _TIFFfree(sp); /* Release local variables */ + tif->tif_data = 0; + } + } + +int +TIFFInitOJPEG(register TIFF *tif,int scheme) + { register OJPEGState *sp; +# define td (&tif->tif_dir) +# ifndef never + + /* This module supports a decompression-only CODEC, which is intended strictly + for viewing old image files using the obsolete JPEG-in-TIFF encapsulation + specified by the TIFF Version 6.0 specification. It does not, and never + should, support compression for new images. If a client application asks us + to, refuse and complain loudly! + */ + if (tif->tif_mode != O_RDONLY) return _notSupported(tif); +# endif /* never */ + if (!isMapped(tif)) + { + + /* BEWARE OF KLUDGE: If our host operating-system doesn't let an image + file be "memory mapped", then we want to read the + entire file into a single (possibly large) memory buffer as if it had + been "memory mapped". Although this is likely to waste space, because + analysis of the file's content might cause parts of it to be read into + smaller buffers duplicatively, it appears to be the lesser of several + evils. Very old JPEG-in-TIFF encapsulations aren't guaranteed to be + JFIF bit streams, or to have a TIFF "JPEGTables" record or much other + "metadata" to help us locate the decoding tables and entropy-coded data, + so we're likely do a lot of random-access grokking around, and we must + ultimately tell the JPEG Library to sequentially scan much of the file + anyway. This is all likely to be easier if we use "brute force" to + read the entire file, once, and don't use incremental disc I/O. If our + client application tries to process a file so big that we can't buffer + it entirely, then tough shit: we'll give up and exit! + */ + if (!(tif->tif_base = _TIFFmalloc(tif->tif_size=TIFFGetFileSize(tif)))) + { + TIFFError(tif->tif_name,"Cannot allocate file buffer"); + return 0; + }; + if (!SeekOK(tif,0) || !ReadOK(tif,tif->tif_base,tif->tif_size)) + { + TIFFError(tif->tif_name,"Cannot read file"); + return 0; + } + }; + + /* Allocate storage for this module's per-file variables. */ + + if (!(tif->tif_data = (tidata_t)_TIFFmalloc(sizeof *sp))) + { + TIFFError("TIFFInitOJPEG","No space for JPEG state block"); + return 0; + }; + (sp = OJState(tif))->tif = tif; /* Initialize reverse pointer */ + if (!TIFFojpeg_create_decompress(sp)) return 0; /* Init. JPEG Library */ + + /* If the image file doesn't have "JPEGInterchangeFormat[Length]" TIFF records + to guide us, we have few clues about where its encapsulated JPEG bit stream + is located, so establish intelligent defaults: If the Image File Directory + doesn't immediately follow the TIFF header, assume that the JPEG data lies + in between; otherwise, assume that it follows the Image File Directory. + */ + sp->src.next_input_byte = tif->tif_base + tif->tif_diroff; /* Default */ + if (tif->tif_header.tiff_diroff > sizeof tif->tif_header) + { + sp->src.bytes_in_buffer = tif->tif_header.tiff_diroff + - sizeof tif->tif_header; + sp->src.next_input_byte = sp->src.next_input_byte + - sp->src.bytes_in_buffer; + } + else /* this case is ugly! */ + { uint16 dircount; + + dircount = *(uint16 *)sp->src.next_input_byte; + if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); + sp->src.next_input_byte += dircount * sizeof(TIFFDirEntry) + + sizeof dircount; + sp->src.bytes_in_buffer = tif->tif_base + tif->tif_nextdiroff + - sp->src.next_input_byte; + }; + + /* Install CODEC-specific tag information and override default TIFF Library + "method" subroutines with our own, CODEC-specific methods. Like all good + members of an object-class, we save some of these subroutine pointers for + "fall back" in case our own methods fail. + */ + _TIFFMergeFieldInfo(tif,ojpegFieldInfo, + sizeof ojpegFieldInfo/sizeof *ojpegFieldInfo); + sp->defsparent = tif->tif_defstripsize; + sp->deftparent = tif->tif_deftilesize; + sp->vgetparent = tif->tif_vgetfield; + sp->vsetparent = tif->tif_vsetfield; + tif->tif_defstripsize = OJPEGDefaultStripSize; + tif->tif_deftilesize = OJPEGDefaultTileSize; + tif->tif_vgetfield = OJPEGVGetField; + tif->tif_vsetfield = OJPEGVSetField; + tif->tif_printdir = OJPEGPrintDir; +# ifdef never + tif->tif_setupencode = OJPEGSetupEncode; + tif->tif_preencode = OJPEGPreEncode; + tif->tif_postencode = OJPEGPostEncode; +# else /* well, hardly ever */ + tif->tif_setupencode = tif->tif_postencode = _notSupported; + tif->tif_preencode = (TIFFPreMethod)_notSupported; +# endif /* never */ + tif->tif_setupdecode = OJPEGSetupDecode; + tif->tif_predecode = OJPEGPreDecode; + tif->tif_cleanup = OJPEGCleanUp; + + /* Initialize other CODEC-specific variables requiring default values. */ + + tif->tif_flags |= TIFF_NOBITREV; /* No bit-reversal within data bytes */ + sp->is_WANG = 0; /* Assume not a Microsoft Wang Imaging file by default */ + sp->jpegtables = 0; /* No "new"-style JPEG tables synthesized yet */ + sp->jpegtables_length = 0; + sp->jpegquality = 75; /* Default IJG quality */ + sp->jpegcolormode = JPEGCOLORMODE_RAW; + sp->jpegtablesmode = 0; /* No tables found yet */ + return 1; +# undef td + } +#endif /* OJPEG_SUPPORT */ diff --git a/Utilities/vtktiff/tif_open.c b/Utilities/vtktiff/tif_open.c new file mode 100644 index 0000000..5e58067 --- /dev/null +++ b/Utilities/vtktiff/tif_open.c @@ -0,0 +1,495 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_open.c,v 1.2 2005/02/28 17:19:59 malaterre Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +void _TIFFSetDefaultCompressionState(TIFF* tif); + +static const unsigned long typemask[13] = { + 0L, /* TIFF_NOTYPE */ + 0x000000ffL, /* TIFF_BYTE */ + 0xffffffffL, /* TIFF_ASCII */ + 0x0000ffffL, /* TIFF_SHORT */ + 0xffffffffL, /* TIFF_LONG */ + 0xffffffffL, /* TIFF_RATIONAL */ + 0x000000ffL, /* TIFF_SBYTE */ + 0x000000ffL, /* TIFF_UNDEFINED */ + 0x0000ffffL, /* TIFF_SSHORT */ + 0xffffffffL, /* TIFF_SLONG */ + 0xffffffffL, /* TIFF_SRATIONAL */ + 0xffffffffL, /* TIFF_FLOAT */ + 0xffffffffL, /* TIFF_DOUBLE */ +}; +static const int bigTypeshift[13] = { + 0, /* TIFF_NOTYPE */ + 24, /* TIFF_BYTE */ + 0, /* TIFF_ASCII */ + 16, /* TIFF_SHORT */ + 0, /* TIFF_LONG */ + 0, /* TIFF_RATIONAL */ + 24, /* TIFF_SBYTE */ + 24, /* TIFF_UNDEFINED */ + 16, /* TIFF_SSHORT */ + 0, /* TIFF_SLONG */ + 0, /* TIFF_SRATIONAL */ + 0, /* TIFF_FLOAT */ + 0, /* TIFF_DOUBLE */ +}; +static const int litTypeshift[13] = { + 0, /* TIFF_NOTYPE */ + 0, /* TIFF_BYTE */ + 0, /* TIFF_ASCII */ + 0, /* TIFF_SHORT */ + 0, /* TIFF_LONG */ + 0, /* TIFF_RATIONAL */ + 0, /* TIFF_SBYTE */ + 0, /* TIFF_UNDEFINED */ + 0, /* TIFF_SSHORT */ + 0, /* TIFF_SLONG */ + 0, /* TIFF_SRATIONAL */ + 0, /* TIFF_FLOAT */ + 0, /* TIFF_DOUBLE */ +}; + +/* + * Initialize the shift & mask tables, and the + * byte swapping state according to the file + * contents and the machine architecture. + */ +static void +TIFFInitOrder(TIFF* tif, int magic, int bigendian) +{ + tif->tif_typemask = typemask; + if (magic == TIFF_BIGENDIAN) { + tif->tif_typeshift = bigTypeshift; + if (!bigendian) + tif->tif_flags |= TIFF_SWAB; + } else { + tif->tif_typeshift = litTypeshift; + if (bigendian) + tif->tif_flags |= TIFF_SWAB; + } +} + +int +_TIFFgetMode(const char* mode, const char* module) +{ + int m = -1; + + switch (mode[0]) { + case 'r': + m = O_RDONLY; + if (mode[1] == '+') + m = O_RDWR; + break; + case 'w': + case 'a': + m = O_RDWR|O_CREAT; + if (mode[0] == 'w') + m |= O_TRUNC; + break; + default: + TIFFError(module, "\"%s\": Bad mode", mode); + break; + } + return (m); +} + +TIFF* +TEXPORT TIFFClientOpen( + const char* name, const char* mode, + thandle_t clientdata, + TIFFReadWriteProc readproc, + TIFFReadWriteProc writeproc, + TIFFSeekProc seekproc, + TIFFCloseProc closeproc, + TIFFSizeProc sizeproc, + TIFFMapFileProc mapproc, + TIFFUnmapFileProc unmapproc +) +{ + static const char module[] = "TIFFClientOpen"; + TIFF *tif; + int m, bigendian; + const char* cp; + + m = _TIFFgetMode(mode, module); + if (m == -1) + goto bad2; + tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1); + if (tif == NULL) { + TIFFError(module, "%s: Out of memory (TIFF structure)", name); + goto bad2; + } + _TIFFmemset(tif, 0, sizeof (*tif)); + tif->tif_name = (char *)tif + sizeof (TIFF); + strcpy(tif->tif_name, name); + tif->tif_mode = m &~ (O_CREAT|O_TRUNC); + tif->tif_curdir = (tdir_t) -1; /* non-existent directory */ + tif->tif_curoff = 0; + tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */ + tif->tif_row = (uint32) -1; /* read/write pre-increment */ + tif->tif_clientdata = clientdata; + tif->tif_readproc = readproc; + tif->tif_writeproc = writeproc; + tif->tif_seekproc = seekproc; + tif->tif_closeproc = closeproc; + tif->tif_sizeproc = sizeproc; + tif->tif_mapproc = mapproc; + tif->tif_unmapproc = unmapproc; + _TIFFSetDefaultCompressionState(tif); /* setup default state */ + /* + * Default is to return data MSB2LSB and enable the + * use of memory-mapped files and strip chopping when + * a file is opened read-only. + */ + tif->tif_flags = FILLORDER_MSB2LSB; + if (m == O_RDONLY ) + tif->tif_flags |= TIFF_MAPPED; + +#ifdef STRIPCHOP_DEFAULT + if (m == O_RDONLY || m == O_RDWR) + tif->tif_flags |= STRIPCHOP_DEFAULT; +#endif + + { union { int32 i; char c[4]; } u; u.i = 1; bigendian = u.c[0] == 0; } + /* + * Process library-specific flags in the open mode string. + * The following flags may be used to control intrinsic library + * behaviour that may or may not be desirable (usually for + * compatibility with some application that claims to support + * TIFF but only supports some braindead idea of what the + * vendor thinks TIFF is): + * + * 'l' use little-endian byte order for creating a file + * 'b' use big-endian byte order for creating a file + * 'L' read/write information using LSB2MSB bit order + * 'B' read/write information using MSB2LSB bit order + * 'H' read/write information using host bit order + * 'M' enable use of memory-mapped files when supported + * 'm' disable use of memory-mapped files + * 'C' enable strip chopping support when reading + * 'c' disable strip chopping support + * + * The use of the 'l' and 'b' flags is strongly discouraged. + * These flags are provided solely because numerous vendors, + * typically on the PC, do not correctly support TIFF; they + * only support the Intel little-endian byte order. This + * support is not configured by default because it supports + * the violation of the TIFF spec that says that readers *MUST* + * support both byte orders. It is strongly recommended that + * you not use this feature except to deal with busted apps + * that write invalid TIFF. And even in those cases you should + * bang on the vendors to fix their software. + * + * The 'L', 'B', and 'H' flags are intended for applications + * that can optimize operations on data by using a particular + * bit order. By default the library returns data in MSB2LSB + * bit order for compatibiltiy with older versions of this + * library. Returning data in the bit order of the native cpu + * makes the most sense but also requires applications to check + * the value of the FillOrder tag; something they probabyl do + * not do right now. + * + * The 'M' and 'm' flags are provided because some virtual memory + * systems exhibit poor behaviour when large images are mapped. + * These options permit clients to control the use of memory-mapped + * files on a per-file basis. + * + * The 'C' and 'c' flags are provided because the library support + * for chopping up large strips into multiple smaller strips is not + * application-transparent and as such can cause problems. The 'c' + * option permits applications that only want to look at the tags, + * for example, to get the unadulterated TIFF tag information. + */ + for (cp = mode; *cp; cp++) + switch (*cp) { + case 'b': + if ((m&O_CREAT) && !bigendian) + tif->tif_flags |= TIFF_SWAB; + break; + case 'l': + if ((m&O_CREAT) && bigendian) + tif->tif_flags |= TIFF_SWAB; + break; + case 'B': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + FILLORDER_MSB2LSB; + break; + case 'L': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + FILLORDER_LSB2MSB; + break; + case 'H': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + HOST_FILLORDER; + break; + case 'M': + if (m == O_RDONLY) + tif->tif_flags |= TIFF_MAPPED; + break; + case 'm': + if (m == O_RDONLY) + tif->tif_flags &= ~TIFF_MAPPED; + break; + case 'C': + if (m == O_RDONLY) + tif->tif_flags |= TIFF_STRIPCHOP; + break; + case 'c': + if (m == O_RDONLY) + tif->tif_flags &= ~TIFF_STRIPCHOP; + break; + } + /* + * Read in TIFF header. + */ + if (!ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { + if (tif->tif_mode == O_RDONLY) { + TIFFError(name, "Cannot read TIFF header"); + goto bad; + } + /* + * Setup header and write. + */ + tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB + ? (bigendian ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN) + : (bigendian ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN); + tif->tif_header.tiff_version = TIFF_VERSION; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&tif->tif_header.tiff_version); + tif->tif_header.tiff_diroff = 0; /* filled in later */ + + /* + * This seek shouldn't be necessary, but I have had some + * crazy problems with a failed fseek() on Solaris leaving + * the current file pointer out of whack when an fwrite() + * is done. + */ + TIFFSeekFile( tif, 0, SEEK_SET ); + + if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { + TIFFError(name, "Error writing TIFF header"); + goto bad; + } + /* + * Setup the byte order handling. + */ + TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); + /* + * Setup default directory. + */ + if (!TIFFDefaultDirectory(tif)) + goto bad; + tif->tif_diroff = 0; + return (tif); + } + /* + * Setup the byte order handling. + */ + if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN && + tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN) { + TIFFError(name, "Not a TIFF file, bad magic number %d (0x%x)", + tif->tif_header.tiff_magic, + tif->tif_header.tiff_magic); + goto bad; + } + TIFFInitOrder(tif, tif->tif_header.tiff_magic, bigendian); + /* + * Swap header if required. + */ + if (tif->tif_flags & TIFF_SWAB) { + TIFFSwabShort(&tif->tif_header.tiff_version); + TIFFSwabLong(&tif->tif_header.tiff_diroff); + } + /* + * Now check version (if needed, it's been byte-swapped). + * Note that this isn't actually a version number, it's a + * magic number that doesn't change (stupid). + */ + if (tif->tif_header.tiff_version != TIFF_VERSION) { + TIFFError(name, + "Not a TIFF file, bad version number %d (0x%x)", + tif->tif_header.tiff_version, + tif->tif_header.tiff_version); + goto bad; + } + tif->tif_flags |= TIFF_MYBUFFER; + tif->tif_rawcp = tif->tif_rawdata = 0; + tif->tif_rawdatasize = 0; + /* + * Setup initial directory. + */ + switch (mode[0]) { + case 'r': + tif->tif_nextdiroff = tif->tif_header.tiff_diroff; + /* + * Try to use a memory-mapped file if the client + * has not explicitly suppressed usage with the + * 'm' flag in the open mode (see above). + */ + if ((tif->tif_flags & TIFF_MAPPED) && + !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size)) + tif->tif_flags &= ~TIFF_MAPPED; + if (TIFFReadDirectory(tif)) { + if( m != O_RDONLY + && tif->tif_dir.td_compression != COMPRESSION_NONE ) + { + TIFFError( name, + "Can't open a compressed TIFF file" + " with compression for update." ); + goto bad; + } + tif->tif_rawcc = -1; + tif->tif_flags |= TIFF_BUFFERSETUP; + return (tif); + } + break; + case 'a': + /* + * New directories are automatically append + * to the end of the directory chain when they + * are written out (see TIFFWriteDirectory). + */ + if (!TIFFDefaultDirectory(tif)) + goto bad; + return (tif); + } +bad: + tif->tif_mode = O_RDONLY; /* XXX avoid flush */ + TIFFClose(tif); + return ((TIFF*)0); +bad2: + (void) (*closeproc)(clientdata); + return ((TIFF*)0); +} + +/* + * Query functions to access private data. + */ + +/* + * Return open file's name. + */ +const char * +TIFFFileName(TIFF* tif) +{ + return (tif->tif_name); +} + +/* + * Return open file's I/O descriptor. + */ +int +TIFFFileno(TIFF* tif) +{ + return (tif->tif_fd); +} + +/* + * Return read/write mode. + */ +int +TIFFGetMode(TIFF* tif) +{ + return (tif->tif_mode); +} + +/* + * Return nonzero if file is organized in + * tiles; zero if organized as strips. + */ +int +TEXPORT TIFFIsTiled(TIFF* tif) +{ + return (isTiled(tif)); +} + +/* + * Return current row being read/written. + */ +uint32 +TIFFCurrentRow(TIFF* tif) +{ + return (tif->tif_row); +} + +/* + * Return index of the current directory. + */ +tdir_t +TIFFCurrentDirectory(TIFF* tif) +{ + return (tif->tif_curdir); +} + +/* + * Return current strip. + */ +tstrip_t +TIFFCurrentStrip(TIFF* tif) +{ + return (tif->tif_curstrip); +} + +/* + * Return current tile. + */ +ttile_t +TIFFCurrentTile(TIFF* tif) +{ + return (tif->tif_curtile); +} + +/* + * Return nonzero if the file has byte-swapped data. + */ +int +TIFFIsByteSwapped(TIFF* tif) +{ + return ((tif->tif_flags & TIFF_SWAB) != 0); +} + +/* + * Return nonzero if the data is returned up-sampled. + */ +int +TIFFIsUpSampled(TIFF* tif) +{ + return (isUpSampled(tif)); +} + +/* + * Return nonzero if the data is returned in MSB-to-LSB bit order. + */ +int +TIFFIsMSB2LSB(TIFF* tif) +{ + return (isFillOrder(tif, FILLORDER_MSB2LSB)); +} diff --git a/Utilities/vtktiff/tif_packbits.c b/Utilities/vtktiff/tif_packbits.c new file mode 100644 index 0000000..b49aa6f --- /dev/null +++ b/Utilities/vtktiff/tif_packbits.c @@ -0,0 +1,291 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_packbits.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef PACKBITS_SUPPORT +/* + * TIFF Library. + * + * PackBits Compression Algorithm Support + */ +#include <assert.h> +#include <stdio.h> + +static int +PackBitsPreEncode(TIFF* tif, tsample_t s) +{ + (void) s; + /* + * Calculate the scanline/tile-width size in bytes. + */ + if (isTiled(tif)) + tif->tif_data = (tidata_t)(size_t)TIFFTileRowSize(tif); + else + tif->tif_data = (tidata_t)(size_t)TIFFScanlineSize(tif); + return (1); +} + +/* + * NB: tidata is the type representing *(tidata_t); + * if tidata_t is made signed then this type must + * be adjusted accordingly. + */ +typedef unsigned char tidata; + +/* + * Encode a run of pixels. + */ +static int +PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + u_char* bp = (u_char*) buf; + tidata_t op, ep, lastliteral; + long n, slop; + int b; + enum { BASE, LITERAL, RUN, LITERAL_RUN } state; + + (void) s; + op = tif->tif_rawcp; + ep = tif->tif_rawdata + tif->tif_rawdatasize; + state = BASE; + lastliteral = 0; + while (cc > 0) { + /* + * Find the longest string of identical bytes. + */ + b = *bp++, cc--, n = 1; + for (; cc > 0 && b == *bp; cc--, bp++) + n++; + again: + if (op + 2 >= ep) { /* insure space for new data */ + /* + * Be careful about writing the last + * literal. Must write up to that point + * and then copy the remainder to the + * front of the buffer. + */ + if (state == LITERAL || state == LITERAL_RUN) { + slop = op - lastliteral; + tif->tif_rawcc += lastliteral - tif->tif_rawcp; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + while (slop-- > 0) + *op++ = *lastliteral++; + lastliteral = tif->tif_rawcp; + } else { + tif->tif_rawcc += op - tif->tif_rawcp; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + } + } + switch (state) { + case BASE: /* initial state, set run/literal */ + if (n > 1) { + state = RUN; + if (n > 128) { + *op++ = (tidata) -127; + *op++ = b; + n -= 128; + goto again; + } + *op++ = (tidataval_t)(-(n-1)); + *op++ = b; + } else { + lastliteral = op; + *op++ = 0; + *op++ = b; + state = LITERAL; + } + break; + case LITERAL: /* last object was literal string */ + if (n > 1) { + state = LITERAL_RUN; + if (n > 128) { + *op++ = (tidata) -127; + *op++ = b; + n -= 128; + goto again; + } + *op++ = (tidataval_t)(-(n-1)); /* encode run */ + *op++ = b; + } else { /* extend literal */ + if (++(*lastliteral) == 127) + state = BASE; + *op++ = b; + } + break; + case RUN: /* last object was run */ + if (n > 1) { + if (n > 128) { + *op++ = (tidata) -127; + *op++ = b; + n -= 128; + goto again; + } + *op++ = (tidataval_t)(-(n-1)); + *op++ = b; + } else { + lastliteral = op; + *op++ = 0; + *op++ = b; + state = LITERAL; + } + break; + case LITERAL_RUN: /* literal followed by a run */ + /* + * Check to see if previous run should + * be converted to a literal, in which + * case we convert literal-run-literal + * to a single literal. + */ + if (n == 1 && op[-2] == (tidata) -1 && + *lastliteral < 126) { + state = (((*lastliteral) += 2) == 127 ? + BASE : LITERAL); + op[-2] = op[-1]; /* replicate */ + } else + state = RUN; + goto again; + } + } + tif->tif_rawcc += op - tif->tif_rawcp; + tif->tif_rawcp = op; + return (1); +} + +/* + * Encode a rectangular chunk of pixels. We break it up + * into row-sized pieces to insure that encoded runs do + * not span rows. Otherwise, there can be problems with + * the decoder if data is read, for example, by scanlines + * when it was encoded by strips. + */ +static int +PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowsize = (tsize_t) tif->tif_data; + + assert(rowsize > 0); + +#ifdef YCBCR_SUPPORT + /* + * YCBCR data isn't really separable into rows, so we + * might as well encode the whole tile/strip as one chunk. + */ + if( tif->tif_dir.td_photometric == PHOTOMETRIC_YCBCR ) + rowsize = (tsize_t) tif->tif_data; +#endif + + while ((long)cc > 0) { + int chunk = rowsize; + + if( cc < chunk ) + chunk = cc; + + if (PackBitsEncode(tif, bp, chunk, s) < 0) + return (-1); + bp += chunk; + cc -= chunk; + } + return (1); +} + +static int +PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + char *bp; + tsize_t cc; + long n; + int b; + + (void) s; + bp = (char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + while (cc > 0 && (long)occ > 0) { + n = (long) *bp++, cc--; + /* + * Watch out for compilers that + * don't sign extend chars... + */ + if (n >= 128) + n -= 256; + if (n < 0) { /* replicate next byte -n+1 times */ + if (n == -128) /* nop */ + continue; + n = -n + 1; + if( occ < n ) + { + TIFFWarning(tif->tif_name, + "PackBitsDecode: discarding %d bytes " + "to avoid buffer overrun", + n - occ); + n = occ; + } + occ -= n; + b = *bp++, cc--; + while (n-- > 0) + *op++ = b; + } else { /* copy next n+1 bytes literally */ + if (occ < n + 1) + { + TIFFWarning(tif->tif_name, + "PackBitsDecode: discarding %d bytes " + "to avoid buffer overrun", + n - occ + 1); + n = occ - 1; + } + _TIFFmemcpy(op, bp, ++n); + op += n; occ -= n; + bp += n; cc -= n; + } + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + if (occ > 0) { + TIFFError(tif->tif_name, + "PackBitsDecode: Not enough data for scanline %ld", + (long) tif->tif_row); + return (0); + } + return (1); +} + +int +TIFFInitPackBits(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = PackBitsDecode; + tif->tif_decodestrip = PackBitsDecode; + tif->tif_decodetile = PackBitsDecode; + tif->tif_preencode = PackBitsPreEncode; + tif->tif_encoderow = PackBitsEncode; + tif->tif_encodestrip = PackBitsEncodeChunk; + tif->tif_encodetile = PackBitsEncodeChunk; + return (1); +} +#endif /* PACKBITS_SUPPORT */ diff --git a/Utilities/vtktiff/tif_pixarlog.c b/Utilities/vtktiff/tif_pixarlog.c new file mode 100644 index 0000000..d833147 --- /dev/null +++ b/Utilities/vtktiff/tif_pixarlog.c @@ -0,0 +1,1309 @@ +/* + * Copyright (c) 1996-1997 Sam Leffler + * Copyright (c) 1996 Pixar + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Pixar, Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef PIXARLOG_SUPPORT + +/* + * TIFF Library. + * PixarLog Compression Support + * + * Contributed by Dan McCoy. + * + * PixarLog film support uses the TIFF library to store companded + * 11 bit values into a tiff file, which are compressed using the + * zip compressor. + * + * The codec can take as input and produce as output 32-bit IEEE float values + * as well as 16-bit or 8-bit unsigned integer values. + * + * On writing any of the above are converted into the internal + * 11-bit log format. In the case of 8 and 16 bit values, the + * input is assumed to be unsigned linear color values that represent + * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to + * be the normal linear color range, in addition over 1 values are + * accepted up to a value of about 25.0 to encode "hot" hightlights and such. + * The encoding is lossless for 8-bit values, slightly lossy for the + * other bit depths. The actual color precision should be better + * than the human eye can perceive with extra room to allow for + * error introduced by further image computation. As with any quantized + * color format, it is possible to perform image calculations which + * expose the quantization error. This format should certainly be less + * susceptable to such errors than standard 8-bit encodings, but more + * susceptable than straight 16-bit or 32-bit encodings. + * + * On reading the internal format is converted to the desired output format. + * The program can request which format it desires by setting the internal + * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values: + * PIXARLOGDATAFMT_FLOAT = provide IEEE float values. + * PIXARLOGDATAFMT_16BIT = provide unsigned 16-bit integer values + * PIXARLOGDATAFMT_8BIT = provide unsigned 8-bit integer values + * + * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer + * values with the difference that if there are exactly three or four channels + * (rgb or rgba) it swaps the channel order (bgr or abgr). + * + * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly + * packed in 16-bit values. However no tools are supplied for interpreting + * these values. + * + * "hot" (over 1.0) areas written in floating point get clamped to + * 1.0 in the integer data types. + * + * When the file is closed after writing, the bit depth and sample format + * are set always to appear as if 8-bit data has been written into it. + * That way a naive program unaware of the particulars of the encoding + * gets the format it is most likely able to handle. + * + * The codec does it's own horizontal differencing step on the coded + * values so the libraries predictor stuff should be turned off. + * The codec also handle byte swapping the encoded values as necessary + * since the library does not have the information necessary + * to know the bit depth of the raw unencoded buffer. + * + */ + +#include "tif_predict.h" +#include "zlib.h" +#include "zutil.h" + +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> +#include <math.h> + +/* Tables for converting to/from 11 bit coded values */ + +#define TSIZE 2048 /* decode table size (11-bit tokens) */ +#define TSIZEP1 2049 /* Plus one for slop */ +#define ONE 1250 /* token value of 1.0 exactly */ +#define RATIO 1.004 /* nominal ratio for log part */ + +#define CODE_MASK 0x7ff /* 11 bits. */ + +static float Fltsize; +static float LogK1, LogK2; + +#define REPEAT(n, op) { int i; i=n; do { i--; op; } while (i>0); } + +static void +horizontalAccumulateF(uint16 *wp, int n, int stride, float *op, + float *ToLinearF) +{ + register unsigned int cr, cg, cb, ca, mask; + register float t0, t1, t2, t3; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + t0 = ToLinearF[cr = wp[0]]; + t1 = ToLinearF[cg = wp[1]]; + t2 = ToLinearF[cb = wp[2]]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + t0 = ToLinearF[(cr += wp[0]) & mask]; + t1 = ToLinearF[(cg += wp[1]) & mask]; + t2 = ToLinearF[(cb += wp[2]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + } + } else if (stride == 4) { + t0 = ToLinearF[cr = wp[0]]; + t1 = ToLinearF[cg = wp[1]]; + t2 = ToLinearF[cb = wp[2]]; + t3 = ToLinearF[ca = wp[3]]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + t0 = ToLinearF[(cr += wp[0]) & mask]; + t1 = ToLinearF[(cg += wp[1]) & mask]; + t2 = ToLinearF[(cb += wp[2]) & mask]; + t3 = ToLinearF[(ca += wp[3]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else { + REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + +static void +horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op, + float *ToLinearF) +{ + register unsigned int cr, cg, cb, ca, mask; + register float t0, t1, t2, t3; + +#define SCALE12 2048.0 +#define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071) + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + t0 = ToLinearF[cr = wp[0]] * SCALE12; + t1 = ToLinearF[cg = wp[1]] * SCALE12; + t2 = ToLinearF[cb = wp[2]] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; + t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; + t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + } + } else if (stride == 4) { + t0 = ToLinearF[cr = wp[0]] * SCALE12; + t1 = ToLinearF[cg = wp[1]] * SCALE12; + t2 = ToLinearF[cb = wp[2]] * SCALE12; + t3 = ToLinearF[ca = wp[3]] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + op[3] = CLAMP12(t3); + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; + t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; + t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; + t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + op[3] = CLAMP12(t3); + } + } else { + REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12; + *op = CLAMP12(t0); wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12; + *op = CLAMP12(t0); wp++; op++) + n -= stride; + } + } + } +} + +static void +horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op, + uint16 *ToLinear16) +{ + register unsigned int cr, cg, cb, ca, mask; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = ToLinear16[cr = wp[0]]; + op[1] = ToLinear16[cg = wp[1]]; + op[2] = ToLinear16[cb = wp[2]]; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + op[0] = ToLinear16[(cr += wp[0]) & mask]; + op[1] = ToLinear16[(cg += wp[1]) & mask]; + op[2] = ToLinear16[(cb += wp[2]) & mask]; + } + } else if (stride == 4) { + op[0] = ToLinear16[cr = wp[0]]; + op[1] = ToLinear16[cg = wp[1]]; + op[2] = ToLinear16[cb = wp[2]]; + op[3] = ToLinear16[ca = wp[3]]; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + op[0] = ToLinear16[(cr += wp[0]) & mask]; + op[1] = ToLinear16[(cg += wp[1]) & mask]; + op[2] = ToLinear16[(cb += wp[2]) & mask]; + op[3] = ToLinear16[(ca += wp[3]) & mask]; + } + } else { + REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + +/* + * Returns the log encoded 11-bit values with the horizontal + * differencing undone. + */ +static void +horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op) +{ + register unsigned int cr, cg, cb, ca, mask; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = cr = wp[0]; op[1] = cg = wp[1]; op[2] = cb = wp[2]; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + op[0] = (cr += wp[0]) & mask; + op[1] = (cg += wp[1]) & mask; + op[2] = (cb += wp[2]) & mask; + } + } else if (stride == 4) { + op[0] = cr = wp[0]; op[1] = cg = wp[1]; + op[2] = cb = wp[2]; op[3] = ca = wp[3]; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + op[0] = (cr += wp[0]) & mask; + op[1] = (cg += wp[1]) & mask; + op[2] = (cb += wp[2]) & mask; + op[3] = (ca += wp[3]) & mask; + } + } else { + REPEAT(stride, *op = *wp&mask; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = *wp&mask; wp++; op++) + n -= stride; + } + } + } +} + +static void +horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op, + unsigned char *ToLinear8) +{ + register unsigned int cr, cg, cb, ca, mask; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = ToLinear8[cr = wp[0]]; + op[1] = ToLinear8[cg = wp[1]]; + op[2] = ToLinear8[cb = wp[2]]; + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + op += 3; + op[0] = ToLinear8[(cr += wp[0]) & mask]; + op[1] = ToLinear8[(cg += wp[1]) & mask]; + op[2] = ToLinear8[(cb += wp[2]) & mask]; + } + } else if (stride == 4) { + op[0] = ToLinear8[cr = wp[0]]; + op[1] = ToLinear8[cg = wp[1]]; + op[2] = ToLinear8[cb = wp[2]]; + op[3] = ToLinear8[ca = wp[3]]; + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + op += 4; + op[0] = ToLinear8[(cr += wp[0]) & mask]; + op[1] = ToLinear8[(cg += wp[1]) & mask]; + op[2] = ToLinear8[(cb += wp[2]) & mask]; + op[3] = ToLinear8[(ca += wp[3]) & mask]; + } + } else { + REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + + +static void +horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op, + unsigned char *ToLinear8) +{ + register unsigned int cr, cg, cb, ca, mask; + register unsigned char t0, t1, t2, t3; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = 0; + t1 = ToLinear8[cb = wp[2]]; + t2 = ToLinear8[cg = wp[1]]; + t3 = ToLinear8[cr = wp[0]]; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + op += 4; + op[0] = 0; + t1 = ToLinear8[(cb += wp[2]) & mask]; + t2 = ToLinear8[(cg += wp[1]) & mask]; + t3 = ToLinear8[(cr += wp[0]) & mask]; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else if (stride == 4) { + t0 = ToLinear8[ca = wp[3]]; + t1 = ToLinear8[cb = wp[2]]; + t2 = ToLinear8[cg = wp[1]]; + t3 = ToLinear8[cr = wp[0]]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + op += 4; + t0 = ToLinear8[(ca += wp[3]) & mask]; + t1 = ToLinear8[(cb += wp[2]) & mask]; + t2 = ToLinear8[(cg += wp[1]) & mask]; + t3 = ToLinear8[(cr += wp[0]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else { + REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + +/* + * State block for each open TIFF + * file using PixarLog compression/decompression. + */ +typedef struct { + TIFFPredictorState predict; + z_stream stream; + uint16 *tbuf; + uint16 stride; + int state; + int user_datafmt; + int quality; +#define PLSTATE_INIT 1 + + TIFFVSetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + + float *ToLinearF; + uint16 *ToLinear16; + unsigned char *ToLinear8; + uint16 *FromLT2; + uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ + uint16 *From8; + +} PixarLogState; + +static int +PixarLogMakeTables(PixarLogState *sp) +{ + +/* + * We make several tables here to convert between various external + * representations (float, 16-bit, and 8-bit) and the internal + * 11-bit companded representation. The 11-bit representation has two + * distinct regions. A linear bottom end up through .018316 in steps + * of about .000073, and a region of constant ratio up to about 25. + * These floating point numbers are stored in the main table ToLinearF. + * All other tables are derived from this one. The tables (and the + * ratios) are continuous at the internal seam. + */ + + int nlin, lt2size; + int i, j; + double b, c, linstep, max; + double k, v, dv, r, lr2, r2; + float *ToLinearF; + uint16 *ToLinear16; + unsigned char *ToLinear8; + uint16 *FromLT2; + uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ + uint16 *From8; + + c = log(RATIO); + nlin = 1./c; /* nlin must be an integer */ + c = 1./nlin; + b = exp(-c*ONE); /* multiplicative scale factor [b*exp(c*ONE) = 1] */ + linstep = b*c*exp(1.); + + LogK1 = 1./c; /* if (v >= 2) token = k1*log(v*k2) */ + LogK2 = 1./b; + lt2size = (2./linstep)+1; + FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16)); + From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16)); + From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16)); + ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float)); + ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16)); + ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char)); + if (FromLT2 == NULL || From14 == NULL || From8 == NULL || + ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) { + if (FromLT2) _TIFFfree(FromLT2); + if (From14) _TIFFfree(From14); + if (From8) _TIFFfree(From8); + if (ToLinearF) _TIFFfree(ToLinearF); + if (ToLinear16) _TIFFfree(ToLinear16); + if (ToLinear8) _TIFFfree(ToLinear8); + sp->FromLT2 = NULL; + sp->From14 = NULL; + sp->From8 = NULL; + sp->ToLinearF = NULL; + sp->ToLinear16 = NULL; + sp->ToLinear8 = NULL; + return 0; + } + + j = 0; + + for (i = 0; i < nlin; i++) { + v = i * linstep; + ToLinearF[j++] = v; + } + + for (i = nlin; i < TSIZE; i++) + ToLinearF[j++] = b*exp(c*i); + + ToLinearF[2048] = ToLinearF[2047]; + + for (i = 0; i < TSIZEP1; i++) { + v = ToLinearF[i]*65535.0 + 0.5; + ToLinear16[i] = (v > 65535.0) ? 65535 : v; + v = ToLinearF[i]*255.0 + 0.5; + ToLinear8[i] = (v > 255.0) ? 255 : v; + } + + j = 0; + for (i = 0; i < lt2size; i++) { + if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1]) + j++; + FromLT2[i] = j; + } + + /* + * Since we lose info anyway on 16-bit data, we set up a 14-bit + * table and shift 16-bit values down two bits on input. + * saves a little table space. + */ + j = 0; + for (i = 0; i < 16384; i++) { + while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1]) + j++; + From14[i] = j; + } + + j = 0; + for (i = 0; i < 256; i++) { + while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1]) + j++; + From8[i] = j; + } + + Fltsize = lt2size/2; + + sp->ToLinearF = ToLinearF; + sp->ToLinear16 = ToLinear16; + sp->ToLinear8 = ToLinear8; + sp->FromLT2 = FromLT2; + sp->From14 = From14; + sp->From8 = From8; + + return 1; +} + +#define DecoderState(tif) ((PixarLogState*) (tif)->tif_data) +#define EncoderState(tif) ((PixarLogState*) (tif)->tif_data) + +static int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t); +static int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t); + +#define N(a) (sizeof(a)/sizeof(a[0])) +#define PIXARLOGDATAFMT_UNKNOWN -1 + +static int +PixarLogGuessDataFmt(TIFFDirectory *td) +{ + int guess = PIXARLOGDATAFMT_UNKNOWN; + int format = td->td_sampleformat; + + /* If the user didn't tell us his datafmt, + * take our best guess from the bitspersample. + */ + switch (td->td_bitspersample) { + case 32: + if (format == SAMPLEFORMAT_IEEEFP) + guess = PIXARLOGDATAFMT_FLOAT; + break; + case 16: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_16BIT; + break; + case 12: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT) + guess = PIXARLOGDATAFMT_12BITPICIO; + break; + case 11: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_11BITLOG; + break; + case 8: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_8BIT; + break; + } + + return guess; +} + +static int +PixarLogSetupDecode(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = DecoderState(tif); + static const char module[] = "PixarLogSetupDecode"; + + assert(sp != NULL); + + /* Make sure no byte swapping happens on the data + * after decompression. */ + tif->tif_postdecode = _TIFFNoPostDecode; + + /* for some reason, we can't do this in TIFFInitPixarLog */ + + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + sp->tbuf = (uint16 *) _TIFFmalloc(sp->stride * + td->td_imagewidth * td->td_rowsperstrip * sizeof(uint16)); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) + sp->user_datafmt = PixarLogGuessDataFmt(td); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { + TIFFError(module, + "PixarLog compression can't handle bits depth/data format combination (depth: %d)", + td->td_bitspersample); + return (0); + } + + if (inflateInit(&sp->stream) != Z_OK) { + TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= PLSTATE_INIT; + return (1); + } +} + +/* + * Setup state for decoding a strip. + */ +static int +PixarLogPreDecode(TIFF* tif, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + sp->stream.next_in = tif->tif_rawdata; + sp->stream.avail_in = tif->tif_rawcc; + return (inflateReset(&sp->stream) == Z_OK); +} + +static int +PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = DecoderState(tif); + static const char module[] = "PixarLogDecode"; + int i, nsamples, llen; + uint16 *up; + + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + nsamples = occ / sizeof(float); /* XXX float == 32 bits */ + break; + case PIXARLOGDATAFMT_16BIT: + case PIXARLOGDATAFMT_12BITPICIO: + case PIXARLOGDATAFMT_11BITLOG: + nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */ + break; + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + nsamples = occ; + break; + default: + TIFFError(tif->tif_name, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + + llen = sp->stride * td->td_imagewidth; + + (void) s; + assert(sp != NULL); + sp->stream.next_out = (unsigned char *) sp->tbuf; + sp->stream.avail_out = nsamples * sizeof(uint16); + do { + int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + if (state == Z_STREAM_END) { + break; /* XXX */ + } + if (state == Z_DATA_ERROR) { + TIFFError(module, + "%s: Decoding error at scanline %d, %s", + tif->tif_name, tif->tif_row, sp->stream.msg); + if (inflateSync(&sp->stream) != Z_OK) + return (0); + continue; + } + if (state != Z_OK) { + TIFFError(module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (sp->stream.avail_out > 0); + + /* hopefully, we got all the bytes we needed */ + if (sp->stream.avail_out != 0) { + TIFFError(module, + "%s: Not enough data at scanline %d (short %d bytes)", + tif->tif_name, tif->tif_row, sp->stream.avail_out); + return (0); + } + + up = sp->tbuf; + /* Swap bytes in the data if from a different endian machine. */ + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabArrayOfShort(up, nsamples); + + for (i = 0; i < nsamples; i += llen, up += llen) { + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + horizontalAccumulateF(up, llen, sp->stride, + (float *)op, sp->ToLinearF); + op += llen * sizeof(float); + break; + case PIXARLOGDATAFMT_16BIT: + horizontalAccumulate16(up, llen, sp->stride, + (uint16 *)op, sp->ToLinear16); + op += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_12BITPICIO: + horizontalAccumulate12(up, llen, sp->stride, + (int16 *)op, sp->ToLinearF); + op += llen * sizeof(int16); + break; + case PIXARLOGDATAFMT_11BITLOG: + horizontalAccumulate11(up, llen, sp->stride, + (uint16 *)op); + op += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_8BIT: + horizontalAccumulate8(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); + op += llen * sizeof(unsigned char); + break; + case PIXARLOGDATAFMT_8BITABGR: + horizontalAccumulate8abgr(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); + op += llen * sizeof(unsigned char); + break; + default: + TIFFError(tif->tif_name, + "PixarLogDecode: unsupported bits/sample: %d", + td->td_bitspersample); + return (0); + } + } + + return (1); +} + +static int +PixarLogSetupEncode(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = EncoderState(tif); + static const char module[] = "PixarLogSetupEncode"; + + assert(sp != NULL); + + /* for some reason, we can't do this in TIFFInitPixarLog */ + + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + sp->tbuf = (uint16 *) _TIFFmalloc(sp->stride * + td->td_imagewidth * td->td_rowsperstrip * sizeof(uint16)); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) + sp->user_datafmt = PixarLogGuessDataFmt(td); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { + TIFFError(module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample); + return (0); + } + + if (deflateInit(&sp->stream, sp->quality) != Z_OK) { + TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= PLSTATE_INIT; + return (1); + } +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +PixarLogPreEncode(TIFF* tif, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState *sp = EncoderState(tif); + + (void) s; + assert(sp != NULL); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + return (deflateReset(&sp->stream) == Z_OK); +} + +static void +horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2) +{ + + register int r1, g1, b1, a1, r2, g2, b2, a2, mask; + register float fltsize = Fltsize; + +#define CLAMP(v) ( (v<(float)0.) ? 0 \ + : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \ + : (v>(float)24.2) ? 2047 \ + : LogK1*log(v*LogK2) + 0.5 ) + + mask = CODE_MASK; + if (n >= stride) { + if (stride == 3) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + ip += 3; + r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + } + } else if (stride == 4) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + ip += 4; + r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; + } + } else { + ip += n - 1; /* point to last one */ + wp += n - 1; /* point to last one */ + n -= stride; + while (n > 0) { + REPEAT(stride, wp[0] = CLAMP(ip[0]); + wp[stride] -= wp[0]; + wp[stride] &= mask; + wp--; ip--) + n -= stride; + } + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) + } + } +} + +static void +horizontalDifference16(unsigned short *ip, int n, int stride, + unsigned short *wp, uint16 *From14) +{ + register int r1, g1, b1, a1, r2, g2, b2, a2, mask; + +/* assumption is unsigned pixel values */ +#undef CLAMP +#define CLAMP(v) From14[(v) >> 2] + + mask = CODE_MASK; + if (n >= stride) { + if (stride == 3) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + ip += 3; + r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + } + } else if (stride == 4) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + ip += 4; + r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; + } + } else { + ip += n - 1; /* point to last one */ + wp += n - 1; /* point to last one */ + n -= stride; + while (n > 0) { + REPEAT(stride, wp[0] = CLAMP(ip[0]); + wp[stride] -= wp[0]; + wp[stride] &= mask; + wp--; ip--) + n -= stride; + } + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) + } + } +} + + +static void +horizontalDifference8(unsigned char *ip, int n, int stride, + unsigned short *wp, uint16 *From8) +{ + register int r1, g1, b1, a1, r2, g2, b2, a2, mask; + +#undef CLAMP +#define CLAMP(v) (From8[(v)]) + + mask = CODE_MASK; + if (n >= stride) { + if (stride == 3) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1; + wp += 3; + ip += 3; + } + } else if (stride == 4) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1; + a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1; + wp += 4; + ip += 4; + } + } else { + wp += n + stride - 1; /* point to last one */ + ip += n + stride - 1; /* point to last one */ + n -= stride; + while (n > 0) { + REPEAT(stride, wp[0] = CLAMP(ip[0]); + wp[stride] -= wp[0]; + wp[stride] &= mask; + wp--; ip--) + n -= stride; + } + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) + } + } +} + +/* + * Encode a chunk of pixels. + */ +static int +PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState *sp = EncoderState(tif); + static const char module[] = "PixarLogEncode"; + int i, n, llen; + unsigned short * up; + + (void) s; + + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + n = cc / sizeof(float); /* XXX float == 32 bits */ + break; + case PIXARLOGDATAFMT_16BIT: + case PIXARLOGDATAFMT_12BITPICIO: + case PIXARLOGDATAFMT_11BITLOG: + n = cc / sizeof(uint16); /* XXX uint16 == 16 bits */ + break; + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + n = cc; + break; + default: + TIFFError(tif->tif_name, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + + llen = sp->stride * td->td_imagewidth; + + for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) { + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + horizontalDifferenceF((float *)bp, llen, + sp->stride, up, sp->FromLT2); + bp += llen * sizeof(float); + break; + case PIXARLOGDATAFMT_16BIT: + horizontalDifference16((uint16 *)bp, llen, + sp->stride, up, sp->From14); + bp += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_8BIT: + horizontalDifference8((unsigned char *)bp, llen, + sp->stride, up, sp->From8); + bp += llen * sizeof(unsigned char); + break; + default: + TIFFError(tif->tif_name, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + } + + sp->stream.next_in = (unsigned char *) sp->tbuf; + sp->stream.avail_in = n * sizeof(uint16); + + do { + if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { + TIFFError(module, "%s: Encoder error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + if (sp->stream.avail_out == 0) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + } while (sp->stream.avail_in > 0); + return (1); +} + +/* + * Finish off an encoded strip by flushing the last + * string and tacking on an End Of Information code. + */ + +static int +PixarLogPostEncode(TIFF* tif) +{ + PixarLogState *sp = EncoderState(tif); + static const char module[] = "PixarLogPostEncode"; + int state; + + sp->stream.avail_in = 0; + + do { + state = deflate(&sp->stream, Z_FINISH); + switch (state) { + case Z_STREAM_END: + case Z_OK: + if (sp->stream.avail_out != tif->tif_rawdatasize) { + tif->tif_rawcc = + tif->tif_rawdatasize - sp->stream.avail_out; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + break; + default: + TIFFError(module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (state != Z_STREAM_END); + return (1); +} + +static void +PixarLogClose(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + + /* In a really sneaky maneuver, on close, we covertly modify both + * bitspersample and sampleformat in the directory to indicate + * 8-bit linear. This way, the decode "just works" even for + * readers that don't know about PixarLog, or how to set + * the PIXARLOGDATFMT pseudo-tag. + */ + td->td_bitspersample = 8; + td->td_sampleformat = SAMPLEFORMAT_UINT; +} + +static void +PixarLogCleanup(TIFF* tif) +{ + PixarLogState* sp = (PixarLogState*) tif->tif_data; + + if (sp) { + if (sp->FromLT2) _TIFFfree(sp->FromLT2); + if (sp->From14) _TIFFfree(sp->From14); + if (sp->From8) _TIFFfree(sp->From8); + if (sp->ToLinearF) _TIFFfree(sp->ToLinearF); + if (sp->ToLinear16) _TIFFfree(sp->ToLinear16); + if (sp->ToLinear8) _TIFFfree(sp->ToLinear8); + if (sp->state&PLSTATE_INIT) { + if (tif->tif_mode == O_RDONLY) + inflateEnd(&sp->stream); + else + deflateEnd(&sp->stream); + } + if (sp->tbuf) + _TIFFfree(sp->tbuf); + _TIFFfree(sp); + tif->tif_data = NULL; + } +} + +static int +PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + PixarLogState *sp = (PixarLogState *)tif->tif_data; + int result; + static const char module[] = "PixarLogVSetField"; + + switch (tag) { + case TIFFTAG_PIXARLOGQUALITY: + sp->quality = va_arg(ap, int); + if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) { + if (deflateParams(&sp->stream, + sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) { + TIFFError(module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } + return (1); + case TIFFTAG_PIXARLOGDATAFMT: + sp->user_datafmt = va_arg(ap, int); + /* Tweak the TIFF header so that the rest of libtiff knows what + * size of data will be passed between app and library, and + * assume that the app knows what it is doing and is not + * confused by these header manipulations... + */ + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_11BITLOG: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_12BITPICIO: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); + break; + case PIXARLOGDATAFMT_16BIT: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_FLOAT: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); + break; + } + /* + * Must recalculate sizes should bits/sample change. + */ + tif->tif_tilesize = TIFFTileSize(tif); + tif->tif_scanlinesize = TIFFScanlineSize(tif); + result = 1; /* NB: pseudo tag */ + break; + default: + result = (*sp->vsetparent)(tif, tag, ap); + } + return (result); +} + +static int +PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + PixarLogState *sp = (PixarLogState *)tif->tif_data; + + switch (tag) { + case TIFFTAG_PIXARLOGQUALITY: + *va_arg(ap, int*) = sp->quality; + break; + case TIFFTAG_PIXARLOGDATAFMT: + *va_arg(ap, int*) = sp->user_datafmt; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static const TIFFFieldInfo pixarlogFieldInfo[] = { + {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""}, + {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""} +}; + +int +TIFFInitPixarLog(TIFF* tif, int scheme) +{ + PixarLogState* sp; + + assert(scheme == COMPRESSION_PIXARLOG); + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState)); + if (tif->tif_data == NULL) + goto bad; + sp = (PixarLogState*) tif->tif_data; + memset(sp, 0, sizeof (*sp)); + sp->stream.data_type = Z_BINARY; + sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = PixarLogSetupDecode; + tif->tif_predecode = PixarLogPreDecode; + tif->tif_decoderow = PixarLogDecode; + tif->tif_decodestrip = PixarLogDecode; + tif->tif_decodetile = PixarLogDecode; + tif->tif_setupencode = PixarLogSetupEncode; + tif->tif_preencode = PixarLogPreEncode; + tif->tif_postencode = PixarLogPostEncode; + tif->tif_encoderow = PixarLogEncode; + tif->tif_encodestrip = PixarLogEncode; + tif->tif_encodetile = PixarLogEncode; + tif->tif_close = PixarLogClose; + tif->tif_cleanup = PixarLogCleanup; + + /* Override SetField so we can handle our private pseudo-tag */ + _TIFFMergeFieldInfo(tif, pixarlogFieldInfo, N(pixarlogFieldInfo)); + sp->vgetparent = tif->tif_vgetfield; + tif->tif_vgetfield = PixarLogVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_vsetfield; + tif->tif_vsetfield = PixarLogVSetField; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */ + sp->state = 0; + + /* we don't wish to use the predictor, + * the default is none, which predictor value 1 + */ + (void) TIFFPredictorInit(tif); + + /* + * build the companding tables + */ + PixarLogMakeTables(sp); + + return (1); +bad: + TIFFError("TIFFInitPixarLog", "No space for PixarLog state block"); + return (0); +} +#endif /* PIXARLOG_SUPPORT */ diff --git a/Utilities/vtktiff/tif_predict.c b/Utilities/vtktiff/tif_predict.c new file mode 100644 index 0000000..2798377 --- /dev/null +++ b/Utilities/vtktiff/tif_predict.c @@ -0,0 +1,461 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_predict.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Predictor Tag Support (used by multiple codecs). + */ +#include "tiffiop.h" +#include "tif_predict.h" + +#include <assert.h> + +#define PredictorState(tif) ((TIFFPredictorState*) (tif)->tif_data) + +static void horAcc8(TIFF*, tidata_t, tsize_t); +static void horAcc16(TIFF*, tidata_t, tsize_t); +static void swabHorAcc16(TIFF*, tidata_t, tsize_t); +static void horDiff8(TIFF*, tidata_t, tsize_t); +static void horDiff16(TIFF*, tidata_t, tsize_t); +static int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t); +static int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t); +static int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t); +static int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t); + +static int +PredictorSetup(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; + + if (sp->predictor == 1) /* no differencing */ + return (1); + if (sp->predictor != 2) { + TIFFError(tif->tif_name, "\"Predictor\" value %d not supported", + sp->predictor); + return (0); + } + if (td->td_bitspersample != 8 && td->td_bitspersample != 16) { + TIFFError(tif->tif_name, + "Horizontal differencing \"Predictor\" not supported with %d-bit samples", + td->td_bitspersample); + return (0); + } + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + /* + * Calculate the scanline/tile-width size in bytes. + */ + if (isTiled(tif)) + sp->rowsize = TIFFTileRowSize(tif); + else + sp->rowsize = TIFFScanlineSize(tif); + return (1); +} + +static int +PredictorSetupDecode(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; + + if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif)) + return (0); + if (sp->predictor == 2) { + switch (td->td_bitspersample) { + case 8: sp->pfunc = horAcc8; break; + case 16: sp->pfunc = horAcc16; break; + } + /* + * Override default decoding method with + * one that does the predictor stuff. + */ + sp->coderow = tif->tif_decoderow; + tif->tif_decoderow = PredictorDecodeRow; + sp->codestrip = tif->tif_decodestrip; + tif->tif_decodestrip = PredictorDecodeTile; + sp->codetile = tif->tif_decodetile; + tif->tif_decodetile = PredictorDecodeTile; + /* + * If the data is horizontally differenced + * 16-bit data that requires byte-swapping, + * then it must be byte swapped before the + * accumulation step. We do this with a + * special-purpose routine and override the + * normal post decoding logic that the library + * setup when the directory was read. + */ + if (tif->tif_flags&TIFF_SWAB) { + if (sp->pfunc == horAcc16) { + sp->pfunc = swabHorAcc16; + tif->tif_postdecode = _TIFFNoPostDecode; + } /* else handle 32-bit case... */ + } + } + return (1); +} + +static int +PredictorSetupEncode(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; + + if (!(*sp->setupencode)(tif) || !PredictorSetup(tif)) + return (0); + if (sp->predictor == 2) { + switch (td->td_bitspersample) { + case 8: sp->pfunc = horDiff8; break; + case 16: sp->pfunc = horDiff16; break; + } + /* + * Override default encoding method with + * one that does the predictor stuff. + */ + sp->coderow = tif->tif_encoderow; + tif->tif_encoderow = PredictorEncodeRow; + sp->codestrip = tif->tif_encodestrip; + tif->tif_encodestrip = PredictorEncodeTile; + sp->codetile = tif->tif_encodetile; + tif->tif_encodetile = PredictorEncodeTile; + } + return (1); +} + +#define REPEAT4(n, op) \ + switch (n) { \ + default: { int i; for (i = n-4; i > 0; i--) { op; } } \ + case 4: op; \ + case 3: op; \ + case 2: op; \ + case 1: op; \ + case 0: ; \ + } + +static void +horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + TIFFPredictorState* sp = PredictorState(tif); + tsize_t stride = sp->stride; + + char* cp = (char*) cp0; + if (cc > stride) { + cc -= stride; + /* + * Pipeline the most common cases. + */ + if (stride == 3) { + u_int cr = cp[0]; + u_int cg = cp[1]; + u_int cb = cp[2]; + do { + cc -= 3, cp += 3; + cp[0] = (cr += cp[0]); + cp[1] = (cg += cp[1]); + cp[2] = (cb += cp[2]); + } while ((int32) cc > 0); + } else if (stride == 4) { + u_int cr = cp[0]; + u_int cg = cp[1]; + u_int cb = cp[2]; + u_int ca = cp[3]; + do { + cc -= 4, cp += 4; + cp[0] = (cr += cp[0]); + cp[1] = (cg += cp[1]); + cp[2] = (cb += cp[2]); + cp[3] = (ca += cp[3]); + } while ((int32) cc > 0); + } else { + do { + REPEAT4(stride, cp[stride] += *cp; cp++) + cc -= stride; + } while ((int32) cc > 0); + } + } +} + +static void +swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + TIFFPredictorState* sp = PredictorState(tif); + tsize_t stride = sp->stride; + uint16* wp = (uint16*) cp0; + tsize_t wc = cc / 2; + + if (wc > stride) { + TIFFSwabArrayOfShort(wp, wc); + wc -= stride; + do { + REPEAT4(stride, wp[stride] += wp[0]; wp++) + wc -= stride; + } while ((int32) wc > 0); + } +} + +static void +horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + uint16* wp = (uint16*) cp0; + tsize_t wc = cc / 2; + + if (wc > stride) { + wc -= stride; + do { + REPEAT4(stride, wp[stride] += wp[0]; wp++) + wc -= stride; + } while ((int32) wc > 0); + } +} + +/* + * Decode a scanline and apply the predictor routine. + */ +static int +PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->coderow != NULL); + assert(sp->pfunc != NULL); + if ((*sp->coderow)(tif, op0, occ0, s)) { + (*sp->pfunc)(tif, op0, occ0); + return (1); + } else + return (0); +} + +/* + * Decode a tile/strip and apply the predictor routine. + * Note that horizontal differencing must be done on a + * row-by-row basis. The width of a "row" has already + * been calculated at pre-decode time according to the + * strip/tile dimensions. + */ +static int +PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->codetile != NULL); + if ((*sp->codetile)(tif, op0, occ0, s)) { + tsize_t rowsize = sp->rowsize; + assert(rowsize > 0); + assert(sp->pfunc != NULL); + while ((long)occ0 > 0) { + (*sp->pfunc)(tif, op0, (tsize_t) rowsize); + occ0 -= rowsize; + op0 += rowsize; + } + return (1); + } else + return (0); +} + +static void +horDiff8(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + TIFFPredictorState* sp = PredictorState(tif); + tsize_t stride = sp->stride; + char* cp = (char*) cp0; + + if (cc > stride) { + cc -= stride; + /* + * Pipeline the most common cases. + */ + if (stride == 3) { + int r1, g1, b1; + int r2 = cp[0]; + int g2 = cp[1]; + int b2 = cp[2]; + do { + r1 = cp[3]; cp[3] = r1-r2; r2 = r1; + g1 = cp[4]; cp[4] = g1-g2; g2 = g1; + b1 = cp[5]; cp[5] = b1-b2; b2 = b1; + cp += 3; + } while ((int32)(cc -= 3) > 0); + } else if (stride == 4) { + int r1, g1, b1, a1; + int r2 = cp[0]; + int g2 = cp[1]; + int b2 = cp[2]; + int a2 = cp[3]; + do { + r1 = cp[4]; cp[4] = r1-r2; r2 = r1; + g1 = cp[5]; cp[5] = g1-g2; g2 = g1; + b1 = cp[6]; cp[6] = b1-b2; b2 = b1; + a1 = cp[7]; cp[7] = a1-a2; a2 = a1; + cp += 4; + } while ((int32)(cc -= 4) > 0); + } else { + cp += cc - 1; + do { + REPEAT4(stride, cp[stride] -= cp[0]; cp--) + } while ((int32)(cc -= stride) > 0); + } + } +} + +static void +horDiff16(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + TIFFPredictorState* sp = PredictorState(tif); + tsize_t stride = sp->stride; + int16 *wp = (int16*) cp0; + tsize_t wc = cc/2; + + if (wc > stride) { + wc -= stride; + wp += wc - 1; + do { + REPEAT4(stride, wp[stride] -= wp[0]; wp--) + wc -= stride; + } while ((int32) wc > 0); + } +} + +static int +PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->pfunc != NULL); + assert(sp->coderow != NULL); +/* XXX horizontal differencing alters user's data XXX */ + (*sp->pfunc)(tif, bp, cc); + return ((*sp->coderow)(tif, bp, cc, s)); +} + +static int +PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s) +{ + TIFFPredictorState *sp = PredictorState(tif); + tsize_t cc = cc0, rowsize; + u_char* bp = bp0; + + assert(sp != NULL); + assert(sp->pfunc != NULL); + assert(sp->codetile != NULL); + rowsize = sp->rowsize; + assert(rowsize > 0); + while ((long)cc > 0) { + (*sp->pfunc)(tif, bp, (tsize_t) rowsize); + cc -= rowsize; + bp += rowsize; + } + return ((*sp->codetile)(tif, bp0, cc0, s)); +} + +#define FIELD_PREDICTOR (FIELD_CODEC+0) /* XXX */ + +static const TIFFFieldInfo predictFieldInfo[] = { + { TIFFTAG_PREDICTOR, 1, 1, TIFF_SHORT, FIELD_PREDICTOR, + FALSE, FALSE, "Predictor" }, +}; +#define N(a) (sizeof (a) / sizeof (a[0])) + +static int +PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFPredictorState *sp = PredictorState(tif); + + switch (tag) { + case TIFFTAG_PREDICTOR: + sp->predictor = (uint16) va_arg(ap, int); + TIFFSetFieldBit(tif, FIELD_PREDICTOR); + break; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + tif->tif_flags |= TIFF_DIRTYDIRECT; + return (1); +} + +static int +PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFPredictorState *sp = PredictorState(tif); + + switch (tag) { + case TIFFTAG_PREDICTOR: + *va_arg(ap, uint16*) = sp->predictor; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static void +PredictorPrintDir(TIFF* tif, FILE* fd, long flags) +{ + TIFFPredictorState* sp = PredictorState(tif); + + (void) flags; + if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { + fprintf(fd, " Predictor: "); + switch (sp->predictor) { + case 1: fprintf(fd, "none "); break; + case 2: fprintf(fd, "horizontal differencing "); break; + } + fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor); + } + if (sp->printdir) + (*sp->printdir)(tif, fd, flags); +} + +int +TIFFPredictorInit(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + + /* + * Merge codec-specific tag information and + * override parent get/set field methods. + */ + _TIFFMergeFieldInfo(tif, predictFieldInfo, N(predictFieldInfo)); + sp->vgetparent = tif->tif_vgetfield; + tif->tif_vgetfield = PredictorVGetField;/* hook for predictor tag */ + sp->vsetparent = tif->tif_vsetfield; + tif->tif_vsetfield = PredictorVSetField;/* hook for predictor tag */ + sp->printdir = tif->tif_printdir; + tif->tif_printdir = PredictorPrintDir; /* hook for predictor tag */ + + sp->setupdecode = tif->tif_setupdecode; + tif->tif_setupdecode = PredictorSetupDecode; + sp->setupencode = tif->tif_setupencode; + tif->tif_setupencode = PredictorSetupEncode; + + sp->predictor = 1; /* default value */ + sp->pfunc = NULL; /* no predictor routine */ + return (1); +} diff --git a/Utilities/vtktiff/tif_predict.h b/Utilities/vtktiff/tif_predict.h new file mode 100644 index 0000000..a9b9c78 --- /dev/null +++ b/Utilities/vtktiff/tif_predict.h @@ -0,0 +1,61 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_predict.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1995-1997 Sam Leffler + * Copyright (c) 1995-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFPREDICT_ +#define _TIFFPREDICT_ +/* + * ``Library-private'' Support for the Predictor Tag + */ + +/* + * Codecs that want to support the Predictor tag must place + * this structure first in their private state block so that + * the predictor code can cast tif_data to find its state. + */ +typedef struct { + int predictor; /* predictor tag value */ + int stride; /* sample stride over data */ + tsize_t rowsize; /* tile/strip row size */ + + TIFFPostMethod pfunc; /* horizontal differencer/accumulator */ + TIFFCodeMethod coderow; /* parent codec encode/decode row */ + TIFFCodeMethod codestrip; /* parent codec encode/decode strip */ + TIFFCodeMethod codetile; /* parent codec encode/decode tile */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ + TIFFBoolMethod setupdecode; /* super-class method */ + TIFFBoolMethod setupencode; /* super-class method */ +} TIFFPredictorState; + +#if defined(__cplusplus) +extern "C" { +#endif +extern int TIFFPredictorInit(TIFF*); +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFPREDICT_ */ diff --git a/Utilities/vtktiff/tif_print.c b/Utilities/vtktiff/tif_print.c new file mode 100644 index 0000000..cd8589f --- /dev/null +++ b/Utilities/vtktiff/tif_print.c @@ -0,0 +1,535 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_print.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Printing Support + */ +#include "tiffiop.h" +#include <stdio.h> + +#include <ctype.h> + +static const char *photoNames[] = { + "min-is-white", /* PHOTOMETRIC_MINISWHITE */ + "min-is-black", /* PHOTOMETRIC_MINISBLACK */ + "RGB color", /* PHOTOMETRIC_RGB */ + "palette color (RGB from colormap)", /* PHOTOMETRIC_PALETTE */ + "transparency mask", /* PHOTOMETRIC_MASK */ + "separated", /* PHOTOMETRIC_SEPARATED */ + "YCbCr", /* PHOTOMETRIC_YCBCR */ + "7 (0x7)", + "CIE L*a*b*", /* PHOTOMETRIC_CIELAB */ +}; +#define NPHOTONAMES (sizeof (photoNames) / sizeof (photoNames[0])) + +static const char *orientNames[] = { + "0 (0x0)", + "row 0 top, col 0 lhs", /* ORIENTATION_TOPLEFT */ + "row 0 top, col 0 rhs", /* ORIENTATION_TOPRIGHT */ + "row 0 bottom, col 0 rhs", /* ORIENTATION_BOTRIGHT */ + "row 0 bottom, col 0 lhs", /* ORIENTATION_BOTLEFT */ + "row 0 lhs, col 0 top", /* ORIENTATION_LEFTTOP */ + "row 0 rhs, col 0 top", /* ORIENTATION_RIGHTTOP */ + "row 0 rhs, col 0 bottom", /* ORIENTATION_RIGHTBOT */ + "row 0 lhs, col 0 bottom", /* ORIENTATION_LEFTBOT */ +}; +#define NORIENTNAMES (sizeof (orientNames) / sizeof (orientNames[0])) + +/* + * Print the contents of the current directory + * to the specified stdio file stream. + */ +void +TEXPORT TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) +{ + register TIFFDirectory *td; + char *sep; + uint16 i; + long l, n; + + fprintf(fd, "TIFF Directory at offset 0x%lx\n", tif->tif_diroff); + td = &tif->tif_dir; + if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { + fprintf(fd, " Subfile Type:"); + sep = " "; + if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { + fprintf(fd, "%sreduced-resolution image", sep); + sep = "/"; + } + if (td->td_subfiletype & FILETYPE_PAGE) { + fprintf(fd, "%smulti-page document", sep); + sep = "/"; + } + if (td->td_subfiletype & FILETYPE_MASK) + fprintf(fd, "%stransparency mask", sep); + fprintf(fd, " (%lu = 0x%lx)\n", + (long) td->td_subfiletype, (long) td->td_subfiletype); + } + if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { + fprintf(fd, " Image Width: %lu Image Length: %lu", + (u_long) td->td_imagewidth, (u_long) td->td_imagelength); + if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) + fprintf(fd, " Image Depth: %lu", + (u_long) td->td_imagedepth); + fprintf(fd, "\n"); + } + + /* Begin Pixar */ + if (TIFFFieldSet(tif,FIELD_IMAGEFULLWIDTH) || + TIFFFieldSet(tif,FIELD_IMAGEFULLLENGTH)) { + fprintf(fd, " Pixar Full Image Width: %lu Full Image Length: %lu\n", + (u_long) td->td_imagefullwidth, + (u_long) td->td_imagefulllength); + } + if (TIFFFieldSet(tif,FIELD_TEXTUREFORMAT)) + _TIFFprintAsciiTag(fd, "Texture Format", td->td_textureformat); + if (TIFFFieldSet(tif,FIELD_WRAPMODES)) + _TIFFprintAsciiTag(fd, "Texture Wrap Modes", td->td_wrapmodes); + if (TIFFFieldSet(tif,FIELD_FOVCOT)) + fprintf(fd, " Field of View Cotangent: %g\n", td->td_fovcot); + if (TIFFFieldSet(tif,FIELD_MATRIX_WORLDTOSCREEN)) { + typedef float Matrix[4][4]; + Matrix* m = (Matrix*)td->td_matrixWorldToScreen; + + fprintf(fd, " Matrix NP:\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n", + (*m)[0][0], (*m)[0][1], (*m)[0][2], (*m)[0][3], + (*m)[1][0], (*m)[1][1], (*m)[1][2], (*m)[1][3], + (*m)[2][0], (*m)[2][1], (*m)[2][2], (*m)[2][3], + (*m)[3][0], (*m)[3][1], (*m)[3][2], (*m)[3][3]); + } + if (TIFFFieldSet(tif,FIELD_MATRIX_WORLDTOCAMERA)) { + typedef float Matrix[4][4]; + Matrix* m = (Matrix*)td->td_matrixWorldToCamera; + + fprintf(fd, " Matrix Nl:\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n\t%g %g %g %g\n", + (*m)[0][0], (*m)[0][1], (*m)[0][2], (*m)[0][3], + (*m)[1][0], (*m)[1][1], (*m)[1][2], (*m)[1][3], + (*m)[2][0], (*m)[2][1], (*m)[2][2], (*m)[2][3], + (*m)[3][0], (*m)[3][1], (*m)[3][2], (*m)[3][3]); + } + /* End Pixar */ + + if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { + fprintf(fd, " Tile Width: %lu Tile Length: %lu", + (u_long) td->td_tilewidth, (u_long) td->td_tilelength); + if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) + fprintf(fd, " Tile Depth: %lu", + (u_long) td->td_tiledepth); + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { + fprintf(fd, " Resolution: %g, %g", + td->td_xresolution, td->td_yresolution); + if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { + switch (td->td_resolutionunit) { + case RESUNIT_NONE: + fprintf(fd, " (unitless)"); + break; + case RESUNIT_INCH: + fprintf(fd, " pixels/inch"); + break; + case RESUNIT_CENTIMETER: + fprintf(fd, " pixels/cm"); + break; + default: + fprintf(fd, " (unit %u = 0x%x)", + td->td_resolutionunit, + td->td_resolutionunit); + break; + } + } + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_POSITION)) + fprintf(fd, " Position: %g, %g\n", + td->td_xposition, td->td_yposition); + if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) + fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); + if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { + fprintf(fd, " Sample Format: "); + switch (td->td_sampleformat) { + case SAMPLEFORMAT_VOID: + fprintf(fd, "void\n"); + break; + case SAMPLEFORMAT_INT: + fprintf(fd, "signed integer\n"); + break; + case SAMPLEFORMAT_UINT: + fprintf(fd, "unsigned integer\n"); + break; + case SAMPLEFORMAT_IEEEFP: + fprintf(fd, "IEEE floating point\n"); + break; + case SAMPLEFORMAT_COMPLEXINT: + fprintf(fd, "complex signed integer\n"); + break; + case SAMPLEFORMAT_COMPLEXIEEEFP: + fprintf(fd, "complex IEEE floating point\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_sampleformat, td->td_sampleformat); + break; + } + } + if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { + const TIFFCodec* c = TIFFFindCODEC(td->td_compression); + fprintf(fd, " Compression Scheme: "); + if (c) + fprintf(fd, "%s\n", c->name); + else + fprintf(fd, "%u (0x%x)\n", + td->td_compression, td->td_compression); + } + if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { + fprintf(fd, " Photometric Interpretation: "); + if (td->td_photometric < NPHOTONAMES) + fprintf(fd, "%s\n", photoNames[td->td_photometric]); + else { + switch (td->td_photometric) { + case PHOTOMETRIC_LOGL: + fprintf(fd, "CIE Log2(L)\n"); + break; + case PHOTOMETRIC_LOGLUV: + fprintf(fd, "CIE Log2(L) (u',v')\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_photometric, td->td_photometric); + break; + } + } + } + if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { + fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); + sep = ""; + for (i = 0; i < td->td_extrasamples; i++) { + switch (td->td_sampleinfo[i]) { + case EXTRASAMPLE_UNSPECIFIED: + fprintf(fd, "%sunspecified", sep); + break; + case EXTRASAMPLE_ASSOCALPHA: + fprintf(fd, "%sassoc-alpha", sep); + break; + case EXTRASAMPLE_UNASSALPHA: + fprintf(fd, "%sunassoc-alpha", sep); + break; + default: + fprintf(fd, "%s%u (0x%x)", sep, + td->td_sampleinfo[i], td->td_sampleinfo[i]); + break; + } + sep = ", "; + } + fprintf(fd, ">\n"); + } + if (TIFFFieldSet(tif,FIELD_STONITS)) { + fprintf(fd, " Sample to Nits conversion factor: %.4e\n", + td->td_stonits); + } +#ifdef CMYK_SUPPORT + if (TIFFFieldSet(tif,FIELD_INKSET)) { + fprintf(fd, " Ink Set: "); + switch (td->td_inkset) { + case INKSET_CMYK: + fprintf(fd, "CMYK\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_inkset, td->td_inkset); + break; + } + } + if (TIFFFieldSet(tif,FIELD_INKNAMES)) { + char* cp; + fprintf(fd, " Ink Names: "); + i = td->td_samplesperpixel; + sep = ""; + for (cp = td->td_inknames; i > 0; cp = strchr(cp,'\0')+1, i--) { + fprintf(fd, "%s", sep); + _TIFFprintAscii(fd, cp); + sep = ", "; + } + } + if (TIFFFieldSet(tif,FIELD_NUMBEROFINKS)) + fprintf(fd, " Number of Inks: %u\n", td->td_ninks); + if (TIFFFieldSet(tif,FIELD_DOTRANGE)) + fprintf(fd, " Dot Range: %u-%u\n", + td->td_dotrange[0], td->td_dotrange[1]); + if (TIFFFieldSet(tif,FIELD_TARGETPRINTER)) + _TIFFprintAsciiTag(fd, "Target Printer", td->td_targetprinter); +#endif + if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { + fprintf(fd, " Thresholding: "); + switch (td->td_threshholding) { + case THRESHHOLD_BILEVEL: + fprintf(fd, "bilevel art scan\n"); + break; + case THRESHHOLD_HALFTONE: + fprintf(fd, "halftone or dithered scan\n"); + break; + case THRESHHOLD_ERRORDIFFUSE: + fprintf(fd, "error diffused\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_threshholding, td->td_threshholding); + break; + } + } + if (TIFFFieldSet(tif,FIELD_FILLORDER)) { + fprintf(fd, " FillOrder: "); + switch (td->td_fillorder) { + case FILLORDER_MSB2LSB: + fprintf(fd, "msb-to-lsb\n"); + break; + case FILLORDER_LSB2MSB: + fprintf(fd, "lsb-to-msb\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_fillorder, td->td_fillorder); + break; + } + } +#ifdef YCBCR_SUPPORT + if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) + fprintf(fd, " YCbCr Subsampling: %u, %u\n", + td->td_ycbcrsubsampling[0], td->td_ycbcrsubsampling[1]); + if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { + fprintf(fd, " YCbCr Positioning: "); + switch (td->td_ycbcrpositioning) { + case YCBCRPOSITION_CENTERED: + fprintf(fd, "centered\n"); + break; + case YCBCRPOSITION_COSITED: + fprintf(fd, "cosited\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_ycbcrpositioning, td->td_ycbcrpositioning); + break; + } + } + if (TIFFFieldSet(tif,FIELD_YCBCRCOEFFICIENTS)) + fprintf(fd, " YCbCr Coefficients: %g, %g, %g\n", + td->td_ycbcrcoeffs[0], + td->td_ycbcrcoeffs[1], + td->td_ycbcrcoeffs[2]); +#endif + if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) + fprintf(fd, " Halftone Hints: light %u dark %u\n", + td->td_halftonehints[0], td->td_halftonehints[1]); + if (TIFFFieldSet(tif,FIELD_ARTIST)) + _TIFFprintAsciiTag(fd, "Artist", td->td_artist); + if (TIFFFieldSet(tif,FIELD_DATETIME)) + _TIFFprintAsciiTag(fd, "Date & Time", td->td_datetime); + if (TIFFFieldSet(tif,FIELD_HOSTCOMPUTER)) + _TIFFprintAsciiTag(fd, "Host Computer", td->td_hostcomputer); + if (TIFFFieldSet(tif,FIELD_SOFTWARE)) + _TIFFprintAsciiTag(fd, "Software", td->td_software); + if (TIFFFieldSet(tif,FIELD_COPYRIGHT)) + _TIFFprintAsciiTag(fd, "Copyright", td->td_copyright); + if (TIFFFieldSet(tif,FIELD_DOCUMENTNAME)) + _TIFFprintAsciiTag(fd, "Document Name", td->td_documentname); + if (TIFFFieldSet(tif,FIELD_IMAGEDESCRIPTION)) + _TIFFprintAsciiTag(fd, "Image Description", td->td_imagedescription); + if (TIFFFieldSet(tif,FIELD_MAKE)) + _TIFFprintAsciiTag(fd, "Make", td->td_make); + if (TIFFFieldSet(tif,FIELD_MODEL)) + _TIFFprintAsciiTag(fd, "Model", td->td_model); + if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { + fprintf(fd, " Orientation: "); + if (td->td_orientation < NORIENTNAMES) + fprintf(fd, "%s\n", orientNames[td->td_orientation]); + else + fprintf(fd, "%u (0x%x)\n", + td->td_orientation, td->td_orientation); + } + if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) + fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); + if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { + fprintf(fd, " Rows/Strip: "); + if (td->td_rowsperstrip == (uint32) -1) + fprintf(fd, "(infinite)\n"); + else + fprintf(fd, "%lu\n", (u_long) td->td_rowsperstrip); + } + if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) + fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); + if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) + fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); + if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) + fprintf(fd, " SMin Sample Value: %g\n", + td->td_sminsamplevalue); + if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) + fprintf(fd, " SMax Sample Value: %g\n", + td->td_smaxsamplevalue); + if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { + fprintf(fd, " Planar Configuration: "); + switch (td->td_planarconfig) { + case PLANARCONFIG_CONTIG: + fprintf(fd, "single image plane\n"); + break; + case PLANARCONFIG_SEPARATE: + fprintf(fd, "separate image planes\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_planarconfig, td->td_planarconfig); + break; + } + } + if (TIFFFieldSet(tif,FIELD_PAGENAME)) + _TIFFprintAsciiTag(fd, "Page Name", td->td_pagename); + if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) + fprintf(fd, " Page Number: %u-%u\n", + td->td_pagenumber[0], td->td_pagenumber[1]); + if (TIFFFieldSet(tif,FIELD_COLORMAP)) { + fprintf(fd, " Color Map: "); + if (flags & TIFFPRINT_COLORMAP) { + fprintf(fd, "\n"); + n = 1L<<td->td_bitspersample; + for (l = 0; l < n; l++) + fprintf(fd, " %5lu: %5u %5u %5u\n", + l, + td->td_colormap[0][l], + td->td_colormap[1][l], + td->td_colormap[2][l]); + } else + fprintf(fd, "(present)\n"); + } +#ifdef COLORIMETRY_SUPPORT + if (TIFFFieldSet(tif,FIELD_WHITEPOINT)) + fprintf(fd, " White Point: %g-%g\n", + td->td_whitepoint[0], td->td_whitepoint[1]); + if (TIFFFieldSet(tif,FIELD_PRIMARYCHROMAS)) + fprintf(fd, " Primary Chromaticities: %g,%g %g,%g %g,%g\n", + td->td_primarychromas[0], td->td_primarychromas[1], + td->td_primarychromas[2], td->td_primarychromas[3], + td->td_primarychromas[4], td->td_primarychromas[5]); + if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { + fprintf(fd, " Reference Black/White:\n"); + for (i = 0; i < td->td_samplesperpixel; i++) + fprintf(fd, " %2d: %5g %5g\n", + i, + td->td_refblackwhite[2*i+0], + td->td_refblackwhite[2*i+1]); + } + if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { + fprintf(fd, " Transfer Function: "); + if (flags & TIFFPRINT_CURVES) { + fprintf(fd, "\n"); + n = 1L<<td->td_bitspersample; + for (l = 0; l < n; l++) { + fprintf(fd, " %2lu: %5u", + l, td->td_transferfunction[0][l]); + for (i = 1; i < td->td_samplesperpixel; i++) + fprintf(fd, " %5u", + td->td_transferfunction[i][l]); + fputc('\n', fd); + } + } else + fprintf(fd, "(present)\n"); + } + + if ( 1 ) + { + int colorchannels; + colorchannels = td->td_samplesperpixel - td->td_extrasamples; + fprintf(fd, " Color Channels: %d\n", colorchannels); + } + +#endif +#ifdef ICC_SUPPORT + if (TIFFFieldSet(tif,FIELD_ICCPROFILE)) + fprintf(fd, " ICC Profile: <present>, %lu bytes\n", + (u_long) td->td_profileLength); +#endif +#ifdef PHOTOSHOP_SUPPORT + if (TIFFFieldSet(tif,FIELD_PHOTOSHOP)) + fprintf(fd, " Photoshop Data: <present>, %lu bytes\n", + (u_long) td->td_photoshopLength); +#endif +#ifdef IPTC_SUPPORT + if (TIFFFieldSet(tif,FIELD_RICHTIFFIPTC)) + fprintf(fd, " RichTIFFIPTC Data: <present>, %lu bytes\n", + (u_long) td->td_richtiffiptcLength); +#endif +#if SUBIFD_SUPPORT + if (TIFFFieldSet(tif, FIELD_SUBIFD)) { + fprintf(fd, " SubIFD Offsets:"); + for (i = 0; i < td->td_nsubifd; i++) + fprintf(fd, " %5lu", (long) td->td_subifd[i]); + fputc('\n', fd); + } +#endif + if (tif->tif_printdir) + (*tif->tif_printdir)(tif, fd, flags); + if ((flags & TIFFPRINT_STRIPS) && + TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { + tstrip_t s; + + fprintf(fd, " %lu %s:\n", + (long) td->td_nstrips, + isTiled(tif) ? "Tiles" : "Strips"); + for (s = 0; s < td->td_nstrips; s++) + fprintf(fd, " %3lu: [%8lu, %8lu]\n", + (u_long) s, + (u_long) td->td_stripoffset[s], + (u_long) td->td_stripbytecount[s]); + } +} + +void +_TIFFprintAscii(FILE* fd, const char* cp) +{ + for (; *cp != '\0'; cp++) { + const char* tp; + + if (isprint(*cp)) { + fputc(*cp, fd); + continue; + } + for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++) + if (*tp++ == *cp) + break; + if (*tp) + fprintf(fd, "\\%c", *tp); + else + fprintf(fd, "\\%03o", *cp & 0xff); + } +} + +void +_TIFFprintAsciiTag(FILE* fd, const char* name, const char* value) +{ + fprintf(fd, " %s: \"", name); + _TIFFprintAscii(fd, value); + fprintf(fd, "\"\n"); +} diff --git a/Utilities/vtktiff/tif_read.c b/Utilities/vtktiff/tif_read.c new file mode 100644 index 0000000..4ec3878 --- /dev/null +++ b/Utilities/vtktiff/tif_read.c @@ -0,0 +1,633 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_read.c,v 1.2 2005/02/28 18:49:39 malaterre Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * Scanline-oriented Read Support + */ +#include "tiffiop.h" +#include <stdio.h> +#include <assert.h> + +static int TIFFFillStrip(TIFF*, tstrip_t); +static int TIFFFillTile(TIFF*, ttile_t); +static int TIFFStartStrip(TIFF*, tstrip_t); +static int TIFFStartTile(TIFF*, ttile_t); +static int TIFFCheckRead(TIFF*, int); + +#define NOSTRIP ((tstrip_t) -1) /* undefined state */ +#define NOTILE ((ttile_t) -1) /* undefined state */ + +/* + * Seek to a random row+sample in a file. + */ +static int +TIFFSeek(TIFF* tif, uint32 row, tsample_t sample) +{ + register TIFFDirectory *td = &tif->tif_dir; + tstrip_t strip; + + if (row >= td->td_imagelength) { /* out of range */ + TIFFError(tif->tif_name, "%lu: Row out of range, max %lu", + (u_long) row, (u_long) td->td_imagelength); + return (0); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFError(tif->tif_name, + "%lu: Sample out of range, max %lu", + (u_long) sample, (u_long) td->td_samplesperpixel); + return (0); + } + strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; + } else + strip = row / td->td_rowsperstrip; + if (strip != tif->tif_curstrip) { /* different strip, refill */ + if (!TIFFFillStrip(tif, strip)) + return (0); + } else if (row < tif->tif_row) { + /* + * Moving backwards within the same strip: backup + * to the start and then decode forward (below). + * + * NB: If you're planning on lots of random access within a + * strip, it's better to just read and decode the entire + * strip, and then access the decoded data in a random fashion. + */ + if (!TIFFStartStrip(tif, strip)) + return (0); + } + if (row != tif->tif_row) { + /* + * Seek forward to the desired row. + */ + if (!(*tif->tif_seek)(tif, row - tif->tif_row)) + return (0); + tif->tif_row = row; + } + return (1); +} + +int +TEXPORT TIFFReadScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample) +{ + int e; + + if (!TIFFCheckRead(tif, 0)) + return (-1); + if( (e = TIFFSeek(tif, row, sample)) != 0) { + /* + * Decompress desired row into user buffer. + */ + e = (*tif->tif_decoderow) + (tif, (tidata_t) buf, tif->tif_scanlinesize, sample); + tif->tif_row++; + if (e) + (*tif->tif_postdecode)(tif, (tidata_t) buf, + tif->tif_scanlinesize); + } + return (e > 0 ? 1 : -1); +} + +/* + * Read a strip of data and decompress the specified + * amount into the user-supplied buffer. + */ +tsize_t +TIFFReadEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) +{ + TIFFDirectory *td = &tif->tif_dir; + uint32 nrows; + tsize_t stripsize; + tstrip_t sep_strip, strips_per_sep; + + if (!TIFFCheckRead(tif, 0)) + return (-1); + if (strip >= td->td_nstrips) { + TIFFError(tif->tif_name, "%ld: Strip out of range, max %ld", + (long) strip, (long) td->td_nstrips); + return (-1); + } + /* + * Calculate the strip size according to the number of + * rows in the strip (check for truncated last strip on any + * of the separations). + */ + if( td->td_rowsperstrip >= td->td_imagelength ) + strips_per_sep = 1; + else + strips_per_sep = (td->td_imagelength+td->td_rowsperstrip-1) + / td->td_rowsperstrip; + + sep_strip = strip % strips_per_sep; + + if (sep_strip != strips_per_sep-1 || + (nrows = td->td_imagelength % td->td_rowsperstrip) == 0) + nrows = td->td_rowsperstrip; + + stripsize = TIFFVStripSize(tif, nrows); + if (size == (tsize_t) -1) + size = stripsize; + else if (size > stripsize) + size = stripsize; + if (TIFFFillStrip(tif, strip) && (*tif->tif_decodestrip)(tif, + (tidata_t) buf, size, (tsample_t)(strip / td->td_stripsperimage))) { + (*tif->tif_postdecode)(tif, (tidata_t) buf, size); + return (size); + } else + return ((tsize_t) -1); +} + +static tsize_t +TIFFReadRawStrip1(TIFF* tif, + tstrip_t strip, tdata_t buf, tsize_t size, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (!isMapped(tif)) { + tsize_t cc; + + if (!SeekOK(tif, td->td_stripoffset[strip])) { + TIFFError(module, + "%s: Seek error at scanline %lu, strip %lu", + tif->tif_name, + (u_long) tif->tif_row, (u_long) strip); + return (-1); + } + cc = TIFFReadFile(tif, buf, size); + if (cc != size) { + TIFFError(module, + "%s: Read error at scanline %lu; got %lu bytes, expected %lu", + tif->tif_name, + (u_long) tif->tif_row, + (u_long) cc, + (u_long) size); + return (-1); + } + } else { + if (td->td_stripoffset[strip] + size > tif->tif_size) { + TIFFError(module, + "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu", + tif->tif_name, + (u_long) tif->tif_row, + (u_long) strip, + (u_long) tif->tif_size - td->td_stripoffset[strip], + (u_long) size); + return (-1); + } + _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip], size); + } + return (size); +} + +/* + * Read a strip of data from the file. + */ +tsize_t +TIFFReadRawStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) +{ + static const char module[] = "TIFFReadRawStrip"; + TIFFDirectory *td = &tif->tif_dir; + tsize_t bytecount; + + if (!TIFFCheckRead(tif, 0)) + return ((tsize_t) -1); + if (strip >= td->td_nstrips) { + TIFFError(tif->tif_name, "%lu: Strip out of range, max %lu", + (u_long) strip, (u_long) td->td_nstrips); + return ((tsize_t) -1); + } + bytecount = td->td_stripbytecount[strip]; + if (bytecount <= 0) { + TIFFError(tif->tif_name, + "%lu: Invalid strip byte count, strip %lu", + (u_long) bytecount, (u_long) strip); + return ((tsize_t) -1); + } + if (size != (tsize_t)-1 && size < bytecount) + bytecount = size; + return (TIFFReadRawStrip1(tif, strip, buf, bytecount, module)); +} + +/* + * Read the specified strip and setup for decoding. + * The data buffer is expanded, as necessary, to + * hold the strip's data. + */ +static int +TIFFFillStrip(TIFF* tif, tstrip_t strip) +{ + static const char module[] = "TIFFFillStrip"; + TIFFDirectory *td = &tif->tif_dir; + tsize_t bytecount; + + bytecount = td->td_stripbytecount[strip]; + if (bytecount <= 0) { + TIFFError(tif->tif_name, + "%lu: Invalid strip byte count, strip %lu", + (u_long) bytecount, (u_long) strip); + return (0); + } + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is going + * to handle this operation itself. In this case, avoid + * copying the raw data and instead just reference the + * data from the memory mapped file image. This assumes + * that the decompression routines do not modify the + * contents of the raw data buffer (if they try to, + * the application will get a fault since the file is + * mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + if ( td->td_stripoffset[strip] + bytecount > tif->tif_size) { + /* + * This error message might seem strange, but it's + * what would happen if a read were done instead. + */ + TIFFError(module, + "%s: Read error on strip %lu; got %lu bytes, expected %lu", + tif->tif_name, + (u_long) strip, + (u_long) tif->tif_size - td->td_stripoffset[strip], + (u_long) bytecount); + tif->tif_curstrip = NOSTRIP; + return (0); + } + tif->tif_rawdatasize = bytecount; + tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip]; + } else { + /* + * Expand raw data buffer, if needed, to + * hold data strip coming from file + * (perhaps should set upper bound on + * the size of a buffer we'll use?). + */ + if (bytecount > tif->tif_rawdatasize) { + tif->tif_curstrip = NOSTRIP; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFError(module, + "%s: Data buffer too small to hold strip %lu", + tif->tif_name, (u_long) strip); + return (0); + } + if (!TIFFReadBufferSetup(tif, 0, + TIFFroundup(bytecount, 1024))) + return (0); + } + if (TIFFReadRawStrip1(tif, strip, (u_char *)tif->tif_rawdata, + bytecount, module) != bytecount) + return (0); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, bytecount); + } + return (TIFFStartStrip(tif, strip)); +} + +/* + * Tile-oriented Read Support + * Contributed by Nancy Cam (Silicon Graphics). + */ + +/* + * Read and decompress a tile of data. The + * tile is selected by the (x,y,z,s) coordinates. + */ +tsize_t +TEXPORT TIFFReadTile(TIFF* tif, + tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) + return (-1); + return (TIFFReadEncodedTile(tif, + TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1)); +} + +/* + * Read a tile of data and decompress the specified + * amount into the user-supplied buffer. + */ +tsize_t +TIFFReadEncodedTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t tilesize = tif->tif_tilesize; + + if (!TIFFCheckRead(tif, 1)) + return (-1); + if (tile >= td->td_nstrips) { + TIFFError(tif->tif_name, "%ld: Tile out of range, max %ld", + (long) tile, (u_long) td->td_nstrips); + return (-1); + } + if (size == (tsize_t) -1) + size = tilesize; + else if (size > tilesize) + size = tilesize; + if (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif, + (tidata_t) buf, size, (tsample_t)(tile/td->td_stripsperimage))) { + (*tif->tif_postdecode)(tif, (tidata_t) buf, size); + return (size); + } else + return (-1); +} + +static tsize_t +TIFFReadRawTile1(TIFF* tif, + ttile_t tile, tdata_t buf, tsize_t size, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (!isMapped(tif)) { + tsize_t cc; + + if (!SeekOK(tif, td->td_stripoffset[tile])) { + TIFFError(module, + "%s: Seek error at row %ld, col %ld, tile %ld", + tif->tif_name, + (long) tif->tif_row, + (long) tif->tif_col, + (long) tile); + return ((tsize_t) -1); + } + cc = TIFFReadFile(tif, buf, size); + if (cc != size) { + TIFFError(module, + "%s: Read error at row %ld, col %ld; got %lu bytes, expected %lu", + tif->tif_name, + (long) tif->tif_row, + (long) tif->tif_col, + (u_long) cc, + (u_long) size); + return ((tsize_t) -1); + } + } else { + if (td->td_stripoffset[tile] + size > tif->tif_size) { + TIFFError(module, + "%s: Read error at row %ld, col %ld, tile %ld; got %lu bytes, expected %lu", + tif->tif_name, + (long) tif->tif_row, + (long) tif->tif_col, + (long) tile, + (u_long) tif->tif_size - td->td_stripoffset[tile], + (u_long) size); + return ((tsize_t) -1); + } + _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[tile], size); + } + return (size); +} + +/* + * Read a tile of data from the file. + */ +tsize_t +TIFFReadRawTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size) +{ + static const char module[] = "TIFFReadRawTile"; + TIFFDirectory *td = &tif->tif_dir; + tsize_t bytecount; + + if (!TIFFCheckRead(tif, 1)) + return ((tsize_t) -1); + if (tile >= td->td_nstrips) { + TIFFError(tif->tif_name, "%lu: Tile out of range, max %lu", + (u_long) tile, (u_long) td->td_nstrips); + return ((tsize_t) -1); + } + bytecount = td->td_stripbytecount[tile]; + if (size != (tsize_t) -1 && size < bytecount) + bytecount = size; + return (TIFFReadRawTile1(tif, tile, buf, bytecount, module)); +} + +/* + * Read the specified tile and setup for decoding. + * The data buffer is expanded, as necessary, to + * hold the tile's data. + */ +static int +TIFFFillTile(TIFF* tif, ttile_t tile) +{ + static const char module[] = "TIFFFillTile"; + TIFFDirectory *td = &tif->tif_dir; + tsize_t bytecount; + + bytecount = td->td_stripbytecount[tile]; + if (bytecount <= 0) { + TIFFError(tif->tif_name, + "%lu: Invalid tile byte count, tile %lu", + (u_long) bytecount, (u_long) tile); + return (0); + } + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is going + * to handle this operation itself. In this case, avoid + * copying the raw data and instead just reference the + * data from the memory mapped file image. This assumes + * that the decompression routines do not modify the + * contents of the raw data buffer (if they try to, + * the application will get a fault since the file is + * mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + if ( td->td_stripoffset[tile] + bytecount > tif->tif_size) { + tif->tif_curtile = NOTILE; + return (0); + } + tif->tif_rawdatasize = bytecount; + tif->tif_rawdata = tif->tif_base + td->td_stripoffset[tile]; + } else { + /* + * Expand raw data buffer, if needed, to + * hold data tile coming from file + * (perhaps should set upper bound on + * the size of a buffer we'll use?). + */ + if (bytecount > tif->tif_rawdatasize) { + tif->tif_curtile = NOTILE; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFError(module, + "%s: Data buffer too small to hold tile %ld", + tif->tif_name, (long) tile); + return (0); + } + if (!TIFFReadBufferSetup(tif, 0, + TIFFroundup(bytecount, 1024))) + return (0); + } + if (TIFFReadRawTile1(tif, tile, (u_char *)tif->tif_rawdata, + bytecount, module) != bytecount) + return (0); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, bytecount); + } + return (TIFFStartTile(tif, tile)); +} + +/* + * Setup the raw data buffer in preparation for + * reading a strip of raw data. If the buffer + * is specified as zero, then a buffer of appropriate + * size is allocated by the library. Otherwise, + * the client must guarantee that the buffer is + * large enough to hold any individual strip of + * raw data. + */ +int +TIFFReadBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) +{ + static const char module[] = "TIFFReadBufferSetup"; + + if (tif->tif_rawdata) { + if (tif->tif_flags & TIFF_MYBUFFER) + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + } + if (bp) { + tif->tif_rawdatasize = size; + tif->tif_rawdata = (tidata_t) bp; + tif->tif_flags &= ~TIFF_MYBUFFER; + } else { + tif->tif_rawdatasize = TIFFroundup(size, 1024); + tif->tif_rawdata = (tidata_t) _TIFFmalloc(tif->tif_rawdatasize); + tif->tif_flags |= TIFF_MYBUFFER; + } + if (tif->tif_rawdata == NULL) { + TIFFError(module, + "%s: No space for data buffer at scanline %ld", + tif->tif_name, (long) tif->tif_row); + tif->tif_rawdatasize = 0; + return (0); + } + return (1); +} + +/* + * Set state to appear as if a + * strip has just been read in. + */ +static int +TIFFStartStrip(TIFF* tif, tstrip_t strip) +{ + TIFFDirectory *td = &tif->tif_dir; + + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupdecode)(tif)) + return (0); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_curstrip = strip; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_rawcc = td->td_stripbytecount[strip]; + return ((*tif->tif_predecode)(tif, + (tsample_t)(strip / td->td_stripsperimage))); +} + +/* + * Set state to appear as if a + * tile has just been read in. + */ +static int +TIFFStartTile(TIFF* tif, ttile_t tile) +{ + TIFFDirectory *td = &tif->tif_dir; + + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupdecode)(tif)) + return (0); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_curtile = tile; + tif->tif_row = + (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) * + td->td_tilelength; + tif->tif_col = + (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) * + td->td_tilewidth; + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_rawcc = td->td_stripbytecount[tile]; + return ((*tif->tif_predecode)(tif, + (tsample_t)(tile/td->td_stripsperimage))); +} + +static int +TIFFCheckRead(TIFF* tif, int tiles) +{ + if (tif->tif_mode == O_WRONLY) { + TIFFError(tif->tif_name, "File not open for reading"); + return (0); + } + if (tiles ^ isTiled(tif)) { + TIFFError(tif->tif_name, tiles ? + "Can not read tiles from a stripped image" : + "Can not read scanlines from a tiled image"); + return (0); + } + return (1); +} + +void +_TIFFNoPostDecode(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; (void) buf; (void) cc; +} + +void +_TIFFSwab16BitData(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; + assert((cc & 1) == 0); + TIFFSwabArrayOfShort((uint16*) buf, cc/2); +} + +void +_TIFFSwab32BitData(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; + assert((cc & 3) == 0); + TIFFSwabArrayOfLong((uint32*) buf, cc/4); +} + +void +_TIFFSwab64BitData(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; + assert((cc & 7) == 0); + TIFFSwabArrayOfDouble((double*) buf, cc/8); +} diff --git a/Utilities/vtktiff/tif_strip.c b/Utilities/vtktiff/tif_strip.c new file mode 100644 index 0000000..39631fc --- /dev/null +++ b/Utilities/vtktiff/tif_strip.c @@ -0,0 +1,192 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_strip.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Strip-organized Image Support Routines. + */ +#include "tiffiop.h" + +/* + * Compute which strip a (row,sample) value is in. + */ +tstrip_t +TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample) +{ + TIFFDirectory *td = &tif->tif_dir; + tstrip_t strip; + + strip = row / td->td_rowsperstrip; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFError(tif->tif_name, + "%u: Sample out of range, max %u", + sample, td->td_samplesperpixel); + return ((tstrip_t) 0); + } + strip += sample*td->td_stripsperimage; + } + return (strip); +} + +/* + * Compute how many strips are in an image. + */ +tstrip_t +TIFFNumberOfStrips(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tstrip_t nstrips; + + nstrips = (td->td_rowsperstrip == (uint32) -1 ? + (td->td_imagelength != 0 ? 1 : 0) : + TIFFhowmany(td->td_imagelength, td->td_rowsperstrip)); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + nstrips *= td->td_samplesperpixel; + return (nstrips); +} + +/* + * Compute the # bytes in a variable height, row-aligned strip. + */ +tsize_t +TIFFVStripSize(TIFF* tif, uint32 nrows) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (nrows == (uint32) -1) + nrows = td->td_imagelength; +#ifdef YCBCR_SUPPORT + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_photometric == PHOTOMETRIC_YCBCR && + !isUpSampled(tif)) { + /* + * Packed YCbCr data contain one Cb+Cr for every + * HorizontalSampling*VerticalSampling Y values. + * Must also roundup width and height when calculating + * since images that are not a multiple of the + * horizontal/vertical subsampling area include + * YCbCr data for the extended image. + */ + tsize_t w = + TIFFroundup(td->td_imagewidth, td->td_ycbcrsubsampling[0]); + tsize_t scanline = TIFFhowmany(w*td->td_bitspersample, 8); + tsize_t samplingarea = + td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; + nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]); + /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ + return ((tsize_t) + (nrows*scanline + 2*(nrows*scanline / samplingarea))); + } else +#endif + return ((tsize_t)(nrows * TIFFScanlineSize(tif))); +} + +/* + * Compute the # bytes in a (row-aligned) strip. + * + * Note that if RowsPerStrip is larger than the + * recorded ImageLength, then the strip size is + * truncated to reflect the actual space required + * to hold the strip. + */ +tsize_t +TIFFStripSize(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + uint32 rps = td->td_rowsperstrip; + if (rps > td->td_imagelength) + rps = td->td_imagelength; + return (TIFFVStripSize(tif, rps)); +} + +/* + * Compute a default strip size based on the image + * characteristics and a requested value. If the + * request is <1 then we choose a strip size according + * to certain heuristics. + */ +uint32 +TEXPORT TIFFDefaultStripSize(TIFF* tif, uint32 request) +{ + return (*tif->tif_defstripsize)(tif, request); +} + +uint32 +_TIFFDefaultStripSize(TIFF* tif, uint32 s) +{ + if ((int32) s < 1) { + /* + * If RowsPerStrip is unspecified, try to break the + * image up into strips that are approximately 8Kbytes. + */ + tsize_t scanline = TIFFScanlineSize(tif); + s = (uint32)(8*1024) / (scanline == 0 ? 1 : scanline); + if (s == 0) /* very wide images */ + s = 1; + } + return (s); +} + +/* + * Return the number of bytes to read/write in a call to + * one of the scanline-oriented i/o routines. Note that + * this number may be 1/samples-per-pixel if data is + * stored as separate planes. + */ +tsize_t +TEXPORT TIFFScanlineSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t scanline; + + scanline = td->td_bitspersample * td->td_imagewidth; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + scanline *= td->td_samplesperpixel; + return ((tsize_t) TIFFhowmany(scanline, 8)); +} + +/* + * Return the number of bytes required to store a complete + * decoded and packed raster scanline (as opposed to the + * I/O size returned by TIFFScanlineSize which may be less + * if data is store as separate planes). + */ +tsize_t +TIFFRasterScanlineSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t scanline; + + scanline = td->td_bitspersample * td->td_imagewidth; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + scanline *= td->td_samplesperpixel; + return ((tsize_t) TIFFhowmany(scanline, 8)); + } else + return ((tsize_t) + TIFFhowmany(scanline, 8)*td->td_samplesperpixel); +} diff --git a/Utilities/vtktiff/tif_swab.c b/Utilities/vtktiff/tif_swab.c new file mode 100644 index 0000000..c2628d4 --- /dev/null +++ b/Utilities/vtktiff/tif_swab.c @@ -0,0 +1,217 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_swab.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library Bit & Byte Swapping Support. + * + * XXX We assume short = 16-bits and long = 32-bits XXX + */ +#include "tiffiop.h" + +#ifndef vtk_TIFFSwabShort +void +vtk_TIFFSwabShort(uint16* wp) +{ + register u_char* cp = (u_char*) wp; + int t; + + t = cp[1]; cp[1] = cp[0]; cp[0] = t; +} +#endif + +#ifndef vtk_TIFFSwabLong +void +vtk_TIFFSwabLong(uint32* lp) +{ + register u_char* cp = (u_char*) lp; + int t; + + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; +} +#endif + +#ifndef vtk_TIFFSwabArrayOfShort +void +vtk_TIFFSwabArrayOfShort(uint16* wp, register u_long n) +{ + register u_char* cp; + register int t; + + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (u_char*) wp; + t = cp[1]; cp[1] = cp[0]; cp[0] = t; + wp++; + } +} +#endif + +#ifndef vtk_TIFFSwabArrayOfLong +void +vtk_TIFFSwabArrayOfLong(register uint32* lp, register u_long n) +{ + register unsigned char *cp; + register int t; + + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char *)lp; + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; + lp++; + } +} +#endif + +#ifndef vtk_TIFFSwabDouble +void +vtk_TIFFSwabDouble(double *dp) +{ + register uint32* lp = (uint32*) dp; + uint32 t; + + TIFFSwabArrayOfLong(lp, 2); + t = lp[0]; lp[0] = lp[1]; lp[1] = t; +} +#endif + +#ifndef vtk_TIFFSwabArrayOfDouble +void +vtk_TIFFSwabArrayOfDouble(double* dp, register u_long n) +{ + register uint32* lp = (uint32*) dp; + register uint32 t; + + TIFFSwabArrayOfLong(lp, n + n); + while (n-- > 0) { + t = lp[0]; lp[0] = lp[1]; lp[1] = t; + lp += 2; + } +} +#endif + +/* + * Bit reversal tables. TIFFBitRevTable[<byte>] gives + * the bit reversed value of <byte>. Used in various + * places in the library when the FillOrder requires + * bit reversal of byte values (e.g. CCITT Fax 3 + * encoding/decoding). TIFFNoBitRevTable is provided + * for algorithms that want an equivalent table that + * do not reverse bit values. + */ +static const unsigned char TIFFBitRevTable[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; +static const unsigned char TIFFNoBitRevTable[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + +const unsigned char* +TIFFGetBitRevTable(int reversed) +{ + return (reversed ? TIFFBitRevTable : TIFFNoBitRevTable); +} + +void +TIFFReverseBits(register u_char* cp, register u_long n) +{ + for (; n > 8; n -= 8) { + cp[0] = TIFFBitRevTable[cp[0]]; + cp[1] = TIFFBitRevTable[cp[1]]; + cp[2] = TIFFBitRevTable[cp[2]]; + cp[3] = TIFFBitRevTable[cp[3]]; + cp[4] = TIFFBitRevTable[cp[4]]; + cp[5] = TIFFBitRevTable[cp[5]]; + cp[6] = TIFFBitRevTable[cp[6]]; + cp[7] = TIFFBitRevTable[cp[7]]; + cp += 8; + } + while (n-- > 0) + *cp = TIFFBitRevTable[*cp], cp++; +} diff --git a/Utilities/vtktiff/tif_thunder.c b/Utilities/vtktiff/tif_thunder.c new file mode 100644 index 0000000..5f0dbbb --- /dev/null +++ b/Utilities/vtktiff/tif_thunder.c @@ -0,0 +1,154 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_thunder.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef THUNDER_SUPPORT +/* + * TIFF Library. + * + * ThunderScan 4-bit Compression Algorithm Support + */ + +/* + * ThunderScan uses an encoding scheme designed for + * 4-bit pixel values. Data is encoded in bytes, with + * each byte split into a 2-bit code word and a 6-bit + * data value. The encoding gives raw data, runs of + * pixels, or pixel values encoded as a delta from the + * previous pixel value. For the latter, either 2-bit + * or 3-bit delta values are used, with the deltas packed + * into a single byte. + */ +#define THUNDER_DATA 0x3f /* mask for 6-bit data */ +#define THUNDER_CODE 0xc0 /* mask for 2-bit code word */ +/* code values */ +#define THUNDER_RUN 0x00 /* run of pixels w/ encoded count */ +#define THUNDER_2BITDELTAS 0x40 /* 3 pixels w/ encoded 2-bit deltas */ +#define DELTA2_SKIP 2 /* skip code for 2-bit deltas */ +#define THUNDER_3BITDELTAS 0x80 /* 2 pixels w/ encoded 3-bit deltas */ +#define DELTA3_SKIP 4 /* skip code for 3-bit deltas */ +#define THUNDER_RAW 0xc0 /* raw data encoded */ + +static const int twobitdeltas[4] = { 0, 1, 0, -1 }; +static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 }; + +#define SETPIXEL(op, v) { \ + lastpixel = (v) & 0xf; \ + if (npixels++ & 1) \ + *op++ |= lastpixel; \ + else \ + op[0] = lastpixel << 4; \ +} + +static int +ThunderDecode(TIFF* tif, tidata_t op, tsize_t maxpixels) +{ + register u_char *bp; + register tsize_t cc; + u_int lastpixel; + tsize_t npixels; + + bp = (u_char *)tif->tif_rawcp; + cc = tif->tif_rawcc; + lastpixel = 0; + npixels = 0; + while (cc > 0 && npixels < maxpixels) { + int n, delta; + + n = *bp++, cc--; + switch (n & THUNDER_CODE) { + case THUNDER_RUN: /* pixel run */ + /* + * Replicate the last pixel n times, + * where n is the lower-order 6 bits. + */ + if (npixels & 1) { + op[0] |= lastpixel; + lastpixel = *op++; npixels++; n--; + } else + lastpixel |= lastpixel << 4; + npixels += n; + for (; n > 0; n -= 2) + *op++ = lastpixel; + if (n == -1) + *--op &= 0xf0; + lastpixel &= 0xf; + break; + case THUNDER_2BITDELTAS: /* 2-bit deltas */ + if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + if ((delta = (n & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + break; + case THUNDER_3BITDELTAS: /* 3-bit deltas */ + if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) + SETPIXEL(op, lastpixel + threebitdeltas[delta]); + if ((delta = (n & 7)) != DELTA3_SKIP) + SETPIXEL(op, lastpixel + threebitdeltas[delta]); + break; + case THUNDER_RAW: /* raw data */ + SETPIXEL(op, n); + break; + } + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + if (npixels != maxpixels) { + TIFFError(tif->tif_name, + "ThunderDecode: %s data at scanline %ld (%lu != %lu)", + npixels < maxpixels ? "Not enough" : "Too much", + (long) tif->tif_row, (long) npixels, (long) maxpixels); + return (0); + } + return (1); +} + +static int +ThunderDecodeRow(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + tidata_t row = buf; + + (void) s; + while ((long)occ > 0) { + if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) + return (0); + occ -= tif->tif_scanlinesize; + row += tif->tif_scanlinesize; + } + return (1); +} + +int +TIFFInitThunderScan(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = ThunderDecodeRow; + tif->tif_decodestrip = ThunderDecodeRow; + return (1); +} +#endif /* THUNDER_SUPPORT */ diff --git a/Utilities/vtktiff/tif_tile.c b/Utilities/vtktiff/tif_tile.c new file mode 100644 index 0000000..a1bd727 --- /dev/null +++ b/Utilities/vtktiff/tif_tile.c @@ -0,0 +1,219 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_tile.c,v 1.2 2005/02/28 18:49:39 malaterre Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Tiled Image Support Routines. + */ +#include "tiffiop.h" + +/* + * Compute which tile an (x,y,z,s) value is in. + */ +ttile_t +TIFFComputeTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + uint32 dx = td->td_tilewidth; + uint32 dy = td->td_tilelength; + uint32 dz = td->td_tiledepth; + ttile_t tile = 1; + + if (td->td_imagedepth == 1) + z = 0; + if (dx == (uint32) -1) + dx = td->td_imagewidth; + if (dy == (uint32) -1) + dy = td->td_imagelength; + if (dz == (uint32) -1) + dz = td->td_imagedepth; + if (dx != 0 && dy != 0 && dz != 0) { + uint32 xpt = TIFFhowmany(td->td_imagewidth, dx); + uint32 ypt = TIFFhowmany(td->td_imagelength, dy); + uint32 zpt = TIFFhowmany(td->td_imagedepth, dz); + + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + tile = (xpt*ypt*zpt)*s + + (xpt*ypt)*(z/dz) + + xpt*(y/dy) + + x/dx; + else + tile = (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx + s; + } + return (tile); +} + +/* + * Check an (x,y,z,s) coordinate + * against the image bounds. + */ +int +TIFFCheckTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (x >= td->td_imagewidth) { + TIFFError(tif->tif_name, "Col %ld out of range, max %lu", + (long) x, (u_long) td->td_imagewidth); + return (0); + } + if (y >= td->td_imagelength) { + TIFFError(tif->tif_name, "Row %ld out of range, max %lu", + (long) y, (u_long) td->td_imagelength); + return (0); + } + if (z >= td->td_imagedepth) { + TIFFError(tif->tif_name, "Depth %ld out of range, max %lu", + (long) z, (u_long) td->td_imagedepth); + return (0); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && + s >= td->td_samplesperpixel) { + TIFFError(tif->tif_name, "Sample %d out of range, max %u", + (int) s, td->td_samplesperpixel); + return (0); + } + return (1); +} + +/* + * Compute how many tiles are in an image. + */ +ttile_t +TIFFNumberOfTiles(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + uint32 dx = td->td_tilewidth; + uint32 dy = td->td_tilelength; + uint32 dz = td->td_tiledepth; + ttile_t ntiles; + + if (dx == (uint32) -1) + dx = td->td_imagewidth; + if (dy == (uint32) -1) + dy = td->td_imagelength; + if (dz == (uint32) -1) + dz = td->td_imagedepth; + ntiles = (dx == 0 || dy == 0 || dz == 0) ? 0 : + (TIFFhowmany(td->td_imagewidth, dx) * + TIFFhowmany(td->td_imagelength, dy) * + TIFFhowmany(td->td_imagedepth, dz)); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + ntiles *= td->td_samplesperpixel; + return (ntiles); +} + +/* + * Compute the # bytes in each row of a tile. + */ +tsize_t +TIFFTileRowSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t rowsize; + + if (td->td_tilelength == 0 || td->td_tilewidth == 0) + return ((tsize_t) 0); + rowsize = td->td_bitspersample * td->td_tilewidth; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + rowsize *= td->td_samplesperpixel; + return ((tsize_t) TIFFhowmany(rowsize, 8)); +} + +/* + * Compute the # bytes in a variable length, row-aligned tile. + */ +tsize_t +TIFFVTileSize(TIFF* tif, uint32 nrows) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t tilesize; + + if (td->td_tilelength == 0 || td->td_tilewidth == 0 || + td->td_tiledepth == 0) + return ((tsize_t) 0); +#ifdef YCBCR_SUPPORT + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_photometric == PHOTOMETRIC_YCBCR && + !isUpSampled(tif)) { + /* + * Packed YCbCr data contain one Cb+Cr for every + * HorizontalSampling*VerticalSampling Y values. + * Must also roundup width and height when calculating + * since images that are not a multiple of the + * horizontal/vertical subsampling area include + * YCbCr data for the extended image. + */ + tsize_t w = + TIFFroundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]); + tsize_t rowsize = TIFFhowmany(w*td->td_bitspersample, 8); + tsize_t samplingarea = + td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; + nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]); + /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ + tilesize = nrows*rowsize + 2*(nrows*rowsize / samplingarea); + } else +#endif + tilesize = nrows * TIFFTileRowSize(tif); + return ((tsize_t)(tilesize * td->td_tiledepth)); +} + +/* + * Compute the # bytes in a row-aligned tile. + */ +tsize_t +TEXPORT TIFFTileSize(TIFF* tif) +{ + return (TIFFVTileSize(tif, tif->tif_dir.td_tilelength)); +} + +/* + * Compute a default tile size based on the image + * characteristics and a requested value. If a + * request is <1 then we choose a size according + * to certain heuristics. + */ +void +TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) +{ + (*tif->tif_deftilesize)(tif, tw, th); +} + +void +_TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) +{ + (void) tif; + if (*(int32*) tw < 1) + *tw = 256; + if (*(int32*) th < 1) + *th = 256; + /* roundup to a multiple of 16 per the spec */ + if (*tw & 0xf) + *tw = TIFFroundup(*tw, 16); + if (*th & 0xf) + *th = TIFFroundup(*th, 16); +} diff --git a/Utilities/vtktiff/tif_unix.c b/Utilities/vtktiff/tif_unix.c new file mode 100644 index 0000000..940ece8 --- /dev/null +++ b/Utilities/vtktiff/tif_unix.c @@ -0,0 +1,224 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_unix.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library UNIX-specific Routines. + */ +#include "tiffiop.h" +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return ((tsize_t) read((int) fd, buf, (size_t) size)); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return ((tsize_t) write((int) fd, buf, (size_t) size)); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ +#if USE_64BIT_API == 1 + return ((toff_t) lseek64((int) fd, (off64_t) off, whence)); +#else + return ((toff_t) lseek((int) fd, (off_t) off, whence)); +#endif +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (close((int) fd)); +} + +#include <sys/stat.h> + +static toff_t +_tiffSizeProc(thandle_t fd) +{ +#ifdef _AM29K + long fsize; + return ((fsize = lseek((int) fd, 0, SEEK_END)) < 0 ? 0 : fsize); +#else +#if USE_64BIT_API == 1 + struct stat64 sb; + return (toff_t) (fstat64((int) fd, &sb) < 0 ? 0 : sb.st_size); +#else + struct stat sb; + return (toff_t) (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size); +#endif +#endif +} + +#ifdef HAVE_MMAP +#include <sys/mman.h> + +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + toff_t size = _tiffSizeProc(fd); + if (size != (toff_t) -1) { + *pbase = (tdata_t) + mmap(0, size, PROT_READ, MAP_SHARED, (int) fd, 0); + if (*pbase != (tdata_t) -1) { + *psize = size; + return (1); + } + } + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + (void) fd; + (void) munmap(base, (off_t) size); +} +#else /* !HAVE_MMAP */ +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + (void) fd; (void) pbase; (void) psize; + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + (void) fd; (void) base; (void) size; +} +#endif /* !HAVE_MMAP */ + +/* + * Open a TIFF file descriptor for read/writing. + */ +TIFF* +TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, + (thandle_t) fd, + _tiffReadProc, _tiffWriteProc, + _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, + _tiffMapProc, _tiffUnmapProc); + if (tif) + tif->tif_fd = fd; + return (tif); +} + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + int m, fd; + + m = _TIFFgetMode(mode, module); + if (m == -1) + return ((TIFF*)0); + +/* for cygwin */ +#ifdef O_BINARY + m |= O_BINARY; +#endif + +#ifdef _AM29K + fd = open(name, m); +#else + fd = open(name, m, 0666); +#endif + if (fd < 0) { + TIFFError(module, "%s: Cannot open", name); + return ((TIFF *)0); + } + return (TIFFFdOpen(fd, name, mode)); +} + +void* +_TIFFmalloc(tsize_t s) +{ + return (malloc((size_t) s)); +} + +void +_TIFFfree(tdata_t p) +{ + free(p); +} + +void* +_TIFFrealloc(tdata_t p, tsize_t s) +{ + return (realloc(p, (size_t) s)); +} + +void +_TIFFmemset(tdata_t p, int v, tsize_t c) +{ + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) +{ + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + return (memcmp(p1, p2, (size_t) c)); +} + +static void +unixWarningHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFwarningHandler = unixWarningHandler; + +static void +unixErrorHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} +TIFFErrorHandler _TIFFerrorHandler = unixErrorHandler; diff --git a/Utilities/vtktiff/tif_version.c b/Utilities/vtktiff/tif_version.c new file mode 100644 index 0000000..6777f01 --- /dev/null +++ b/Utilities/vtktiff/tif_version.c @@ -0,0 +1,33 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_version.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ +/* + * Copyright (c) 1992-1997 Sam Leffler + * Copyright (c) 1992-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "tiffiop.h" + +static const char TIFFVersion[] = TIFFLIB_VERSION_STR; + +const char* +TIFFGetVersion(void) +{ + return (TIFFVersion); +} diff --git a/Utilities/vtktiff/tif_vms.c b/Utilities/vtktiff/tif_vms.c new file mode 100644 index 0000000..b70ec31 --- /dev/null +++ b/Utilities/vtktiff/tif_vms.c @@ -0,0 +1,588 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_vms.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library VMS-specific Routines. + */ + +#include <stdlib.h> +#include <unixio.h> +#include "tiffiop.h" +#if !HAVE_IEEEFP +#include <math.h> +#endif + +#ifdef VAXC +#define NOSHARE noshare +#else +#define NOSHARE +#endif + +#ifdef __alpha +/* Dummy entry point for backwards compatibility */ +void TIFFModeCCITTFax3(void){} +#endif + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (read((int) fd, buf, size)); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (write((int) fd, buf, size)); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ + return ((toff_t) lseek((int) fd, (off_t) off, whence)); +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (close((int) fd)); +} + +#include <sys/stat.h> + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + struct stat sb; + return (toff_t) (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size); +} + +#ifdef HAVE_MMAP +#include <starlet.h> +#include <fab.h> +#include <secdef.h> + +/* + * Table for storing information on current open sections. + * (Should really be a linked list) + */ +#define MAX_MAPPED 100 +static int no_mapped = 0; +static struct { + char *base; + char *top; + unsigned short channel; +} map_table[MAX_MAPPED]; + +/* + * This routine maps a file into a private section. Note that this + * method of accessing a file is by far the fastest under VMS. + * The routine may fail (i.e. return 0) for several reasons, for + * example: + * - There is no more room for storing the info on sections. + * - The process is out of open file quota, channels, ... + * - fd does not describe an opened file. + * - The file is already opened for write access by this process + * or another process + * - There is no free "hole" in virtual memory that fits the + * size of the file + */ +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + char name[256]; + struct FAB fab; + unsigned short channel; + char *inadr[2], *retadr[2]; + unsigned long status; + long size; + + if (no_mapped >= MAX_MAPPED) + return(0); + /* + * We cannot use a file descriptor, we + * must open the file once more. + */ + if (getname((int)fd, name, 1) == NULL) + return(0); + /* prepare the FAB for a user file open */ + fab = cc$rms_fab; + fab.fab$l_fop |= FAB$V_UFO; + fab.fab$b_fac = FAB$M_GET; + fab.fab$b_shr = FAB$M_SHRGET; + fab.fab$l_fna = name; + fab.fab$b_fns = strlen(name); + status = sys$open(&fab); /* open file & get channel number */ + if ((status&1) == 0) + return(0); + channel = (unsigned short)fab.fab$l_stv; + inadr[0] = inadr[1] = (char *)0; /* just an address in P0 space */ + /* + * Map the blocks of the file up to + * the EOF block into virtual memory. + */ + size = _tiffSizeProc(fd); + status = sys$crmpsc(inadr, retadr, 0, SEC$M_EXPREG, 0,0,0, channel, + TIFFhowmany(size,512), 0,0,0); + if ((status&1) == 0){ + sys$dassgn(channel); + return(0); + } + *pbase = (tdata_t) retadr[0]; /* starting virtual address */ + /* + * Use the size of the file up to the + * EOF mark for UNIX compatibility. + */ + *psize = (toff_t) size; + /* Record the section in the table */ + map_table[no_mapped].base = retadr[0]; + map_table[no_mapped].top = retadr[1]; + map_table[no_mapped].channel = channel; + no_mapped++; + + return(1); +} + +/* + * This routine unmaps a section from the virtual address space of + * the process, but only if the base was the one returned from a + * call to TIFFMapFileContents. + */ +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + char *inadr[2]; + int i, j; + + /* Find the section in the table */ + for (i = 0;i < no_mapped; i++) { + if (map_table[i].base == (char *) base) { + /* Unmap the section */ + inadr[0] = (char *) base; + inadr[1] = map_table[i].top; + sys$deltva(inadr, 0, 0); + sys$dassgn(map_table[i].channel); + /* Remove this section from the list */ + for (j = i+1; j < no_mapped; j++) + map_table[j-1] = map_table[j]; + no_mapped--; + return; + } + } +} +#else /* !HAVE_MMAP */ +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ +} +#endif /* !HAVE_MMAP */ + +/* + * Open a TIFF file descriptor for read/writing. + */ +TIFF* +TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, + (thandle_t) fd, + _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, + _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); + if (tif) + tif->tif_fd = fd; + return (tif); +} + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + int m, fd; + + m = _TIFFgetMode(mode, module); + if (m == -1) + return ((TIFF*)0); + if (m&O_TRUNC){ + /* + * There is a bug in open in VAXC. If you use + * open w/ m=O_RDWR|O_CREAT|O_TRUNC the + * wrong thing happens. On the other hand + * creat does the right thing. + */ + fd = creat((char *) /* bug in stdio.h */ name, 0666, + "alq = 128", "deq = 64", "mbc = 32", + "fop = tef"); + } else if (m&O_RDWR) { + fd = open(name, m, 0666, + "deq = 64", "mbc = 32", "fop = tef", "ctx = stm"); + } else + fd = open(name, m, 0666, "mbc = 32", "ctx = stm"); + if (fd < 0) { + TIFFError(module, "%s: Cannot open", name); + return ((TIFF*)0); + } + return (TIFFFdOpen(fd, name, mode)); +} + +tdata_t +_TIFFmalloc(tsize_t s) +{ + return (malloc((size_t) s)); +} + +void +_TIFFfree(tdata_t p) +{ + free(p); +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + return (realloc(p, (size_t) s)); +} + +void +_TIFFmemset(tdata_t p, int v, tsize_t c) +{ + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) +{ + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + return (memcmp(p1, p2, (size_t) c)); +} + +/* + * On the VAX, we need to make those global, writable pointers + * non-shareable, otherwise they would be made shareable by default. + * On the AXP, this brain damage has been corrected. + * + * I (Karsten Spang, krs@kampsax.dk) have dug around in the GCC + * manual and the GAS code and have come up with the following + * construct, but I don't have GCC on my VAX, so it is untested. + * Please tell me if it does not work. + */ + +static void +vmsWarningHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} + +NOSHARE TIFFErrorHandler _TIFFwarningHandler = vmsWarningHandler +#if defined(VAX) && defined(__GNUC__) +asm("_$$PsectAttributes_NOSHR$$_TIFFwarningHandler") +#endif +; + +static void +vmsErrorHandler(const char* module, const char* fmt, va_list ap) +{ + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +} + +NOSHARE TIFFErrorHandler _TIFFerrorHandler = vmsErrorHandler +#if defined(VAX) && defined(__GNUC__) +asm("_$$PsectAttributes_NOSHR$$_TIFFerrorHandler") +#endif +; + + +#if !HAVE_IEEEFP +/* IEEE floting point handling */ + +typedef struct ieeedouble { + u_long mant2; /* fix NDR: full 8-byte swap */ + u_long mant : 20, + exp : 11, + sign : 1; +} ieeedouble; +typedef struct ieeefloat { + u_long mant : 23, + exp : 8, + sign : 1; +} ieeefloat; + +/* + * NB: These are D_FLOAT's, not G_FLOAT's. A G_FLOAT is + * simply a reverse-IEEE float/double. + */ + +typedef struct { + u_long mant1 : 7, + exp : 8, + sign : 1, + mant2 : 16, + mant3 : 16, + mant4 : 16; +} nativedouble; +typedef struct { + u_long mant1 : 7, + exp : 8, + sign : 1, + mant2 : 16; +} nativefloat; + +typedef union { + ieeedouble ieee; + nativedouble native; + char b[8]; + uint32 l[2]; + double d; +} double_t; + +typedef union { + ieeefloat ieee; + nativefloat native; + char b[4]; + uint32 l; + float f; +} float_t; + +#if defined(VAXC) || defined(DECC) +#pragma inline(ieeetod,dtoieee) +#endif + +/* + * Convert an IEEE double precision number to native double precision. + * The source is contained in two longwords, the second holding the sign, + * exponent and the higher order bits of the mantissa, and the first + * holding the rest of the mantissa as follows: + * (Note: It is assumed that the number has been eight-byte swapped to + * LSB first.) + * + * First longword: + * 32 least significant bits of mantissa + * Second longword: + * 0-19: 20 most significant bits of mantissa + * 20-30: exponent + * 31: sign + * The exponent is stored as excess 1023. + * The most significant bit of the mantissa is implied 1, and not stored. + * If the exponent and mantissa are zero, the number is zero. + * If the exponent is 0 (i.e. -1023) and the mantissa is non-zero, it is an + * unnormalized number with the most significant bit NOT implied. + * If the exponent is 2047, the number is invalid, in case the mantissa is zero, + * this means overflow (+/- depending of the sign bit), otherwise + * it simply means invalid number. + * + * If the number is too large for the machine or was specified as overflow, + * +/-HUGE_VAL is returned. + */ +INLINE static void +ieeetod(double *dp) +{ + double_t source; + long sign,exp,mant; + double dmant; + + source.ieee = ((double_t*)dp)->ieee; + sign = source.ieee.sign; + exp = source.ieee.exp; + mant = source.ieee.mant; + + if (exp == 2047) { + if (mant) /* Not a Number (NAN) */ + *dp = HUGE_VAL; + else /* +/- infinity */ + *dp = (sign ? -HUGE_VAL : HUGE_VAL); + return; + } + if (!exp) { + if (!(mant || source.ieee.mant2)) { /* zero */ + *dp=0; + return; + } else { /* Unnormalized number */ + /* NB: not -1023, the 1 bit is not implied */ + exp= -1022; + } + } else { + mant |= 1<<20; + exp -= 1023; + } + dmant = (((double) mant) + + ((double) source.ieee.mant2) / (((double) (1<<16)) * + ((double) (1<<16)))) / (double) (1<<20); + dmant = ldexp(dmant, exp); + if (sign) + dmant= -dmant; + *dp = dmant; +} + +INLINE static void +dtoieee(double *dp) +{ + double_t num; + double x; + int exp; + + num.d = *dp; + if (!num.d) { /* Zero is just binary all zeros */ + num.l[0] = num.l[1] = 0; + return; + } + + if (num.d < 0) { /* Sign is encoded separately */ + num.d = -num.d; + num.ieee.sign = 1; + } else { + num.ieee.sign = 0; + } + + /* Now separate the absolute value into mantissa and exponent */ + x = frexp(num.d, &exp); + + /* + * Handle cases where the value is outside the + * range for IEEE floating point numbers. + * (Overflow cannot happen on a VAX, but underflow + * can happen for G float.) + */ + if (exp < -1022) { /* Unnormalized number */ + x = ldexp(x, -1023-exp); + exp = 0; + } else if (exp > 1023) { /* +/- infinity */ + x = 0; + exp = 2047; + } else { /* Get rid of most significant bit */ + x *= 2; + x -= 1; + exp += 1022; /* fix NDR: 1.0 -> x=0.5, exp=1 -> ieee.exp = 1023 */ + } + num.ieee.exp = exp; + + x *= (double) (1<<20); + num.ieee.mant = (long) x; + x -= (double) num.ieee.mant; + num.ieee.mant2 = (long) (x*((double) (1<<16)*(double) (1<<16))); + + if (!(num.ieee.mant || num.ieee.exp || num.ieee.mant2)) { + /* Avoid negative zero */ + num.ieee.sign = 0; + } + ((double_t*)dp)->ieee = num.ieee; +} + +/* + * Beware, these do not handle over/under-flow + * during conversion from ieee to native format. + */ +#define NATIVE2IEEEFLOAT(fp) { \ + float_t t; \ + if (t.ieee.exp = (fp)->native.exp) \ + t.ieee.exp += -129 + 127; \ + t.ieee.sign = (fp)->native.sign; \ + t.ieee.mant = ((fp)->native.mant1<<16)|(fp)->native.mant2; \ + *(fp) = t; \ +} +#define IEEEFLOAT2NATIVE(fp) { \ + float_t t; int v = (fp)->ieee.exp; \ + if (v) v += -127 + 129; /* alter bias of exponent */\ + t.native.exp = v; /* implicit truncation of exponent */\ + t.native.sign = (fp)->ieee.sign; \ + v = (fp)->ieee.mant; \ + t.native.mant1 = v >> 16; \ + t.native.mant2 = v;\ + *(fp) = t; \ +} + +#define IEEEDOUBLE2NATIVE(dp) ieeetod(dp) + +#define NATIVE2IEEEDOUBLE(dp) dtoieee(dp) + + +/* + * These unions are used during floating point + * conversions. The above macros define the + * conversion operations. + */ +void +TIFFCvtIEEEFloatToNative(TIFF* tif, u_int n, float* f) +{ + float_t* fp = (float_t*) f; + + while (n-- > 0) { + IEEEFLOAT2NATIVE(fp); + fp++; + } +} + +void +TIFFCvtNativeToIEEEFloat(TIFF* tif, u_int n, float* f) +{ + float_t* fp = (float_t*) f; + + while (n-- > 0) { + NATIVE2IEEEFLOAT(fp); + fp++; + } +} +void +TIFFCvtIEEEDoubleToNative(TIFF* tif, u_int n, double* f) +{ + double_t* fp = (double_t*) f; + + while (n-- > 0) { + IEEEDOUBLE2NATIVE(fp); + fp++; + } +} + +void +TIFFCvtNativeToIEEEDouble(TIFF* tif, u_int n, double* f) +{ + double_t* fp = (double_t*) f; + + while (n-- > 0) { + NATIVE2IEEEDOUBLE(fp); + fp++; + } +} +#endif diff --git a/Utilities/vtktiff/tif_warning.c b/Utilities/vtktiff/tif_warning.c new file mode 100644 index 0000000..b3245dd --- /dev/null +++ b/Utilities/vtktiff/tif_warning.c @@ -0,0 +1,49 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_warning.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +TIFFErrorHandler +TEXPORT TIFFSetWarningHandler(TIFFErrorHandler handler) +{ + TIFFErrorHandler prev = _TIFFwarningHandler; + _TIFFwarningHandler = handler; + return (prev); +} + +void +TIFFWarning(const char* module, const char* fmt, ...) +{ + if (_TIFFwarningHandler) { + va_list ap; + va_start(ap, fmt); + (*_TIFFwarningHandler)(module, fmt, ap); + va_end(ap); + } +} diff --git a/Utilities/vtktiff/tif_win3.c b/Utilities/vtktiff/tif_win3.c new file mode 100644 index 0000000..c68ac61 --- /dev/null +++ b/Utilities/vtktiff/tif_win3.c @@ -0,0 +1,225 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_win3.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library Windows 3.x-specific Routines. + */ +#include "tiffiop.h" +#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(_MSC_VER) +#include <io.h> /* for open, close, etc. function prototypes */ +#endif + +#include <windows.h> +#include <windowsx.h> +#include <memory.h> + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (_hread(fd, buf, size)); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + return (_hwrite(fd, buf, size)); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ + return (_llseek(fd, (off_t) off, whence)); +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (_lclose(fd)); +} + +#include <sys/stat.h> + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + struct stat sb; + return (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size); +} + +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ +} + +/* + * Open a TIFF file descriptor for read/writing. + */ +TIFF* +TIFFFdOpen(int fd, const char* name, const char* mode) +{ + TIFF* tif; + + tif = TIFFClientOpen(name, mode, + (thandle_t) fd, + _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc, + _tiffSizeProc, _tiffMapProc, _tiffUnmapProc); + if (tif) + tif->tif_fd = fd; + return (tif); +} + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + int m, fd; + OFSTRUCT of; + int mm = 0; + + m = _TIFFgetMode(mode, module); + if (m == -1) + return ((TIFF*)0); + if (m & O_CREAT) { + if ((m & O_TRUNC) || OpenFile(name, &of, OF_EXIST) != HFILE_ERROR) + mm |= OF_CREATE; + } + if (m & O_WRONLY) + mm |= OF_WRITE; + if (m & O_RDWR) + mm |= OF_READWRITE; + fd = OpenFile(name, &of, mm); + if (fd < 0) { + TIFFError(module, "%s: Cannot open", name); + return ((TIFF*)0); + } + return (TIFFFdOpen(fd, name, mode)); +} + +tdata_t +_TIFFmalloc(tsize_t s) +{ + return (tdata_t) GlobalAllocPtr(GHND, (DWORD) s); +} + +void +_TIFFfree(tdata_t p) +{ + GlobalFreePtr(p); +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + return (tdata_t) GlobalReAllocPtr(p, (DWORD) s, GHND); +} + +void +_TIFFmemset(tdata_t p, int v, tsize_t c) +{ + char* pp = (char*) p; + + while (c > 0) { + tsize_t chunk = 0x10000 - ((uint32) pp & 0xffff);/* What's left in segment */ + if (chunk > 0xff00) /* No more than 0xff00 */ + chunk = 0xff00; + if (chunk > c) /* No more than needed */ + chunk = c; + memset(pp, v, chunk); + pp = (char*) (chunk + (char huge*) pp); + c -= chunk; + } +} + +void +_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) +{ + if (c > 0xFFFF) + hmemcpy((void _huge*) d, (void _huge*) s, c); + else + (void) memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const tdata_t d, const tdata_t s, tsize_t c) +{ + char* dd = (char*) d; + char* ss = (char*) s; + tsize_t chunks, chunkd, chunk; + int result; + + while (c > 0) { + chunks = 0x10000 - ((uint32) ss & 0xffff); /* What's left in segment */ + chunkd = 0x10000 - ((uint32) dd & 0xffff); /* What's left in segment */ + chunk = c; /* Get the largest of */ + if (chunk > chunks) /* c, chunks, chunkd, */ + chunk = chunks; /* 0xff00 */ + if (chunk > chunkd) + chunk = chunkd; + if (chunk > 0xff00) + chunk = 0xff00; + result = memcmp(dd, ss, chunk); + if (result != 0) + return (result); + dd = (char*) (chunk + (char huge*) dd); + ss = (char*) (chunk + (char huge*) ss); + c -= chunk; + } + return (0); +} + +static void +win3WarningHandler(const char* module, const char* fmt, va_list ap) +{ + char e[512] = { '\0' }; + if (module != NULL) + strcat(strcpy(e, module), ":"); + vsprintf(e+strlen(e), fmt, ap); + strcat(e, "."); + MessageBox(GetActiveWindow(), e, "LibTIFF Warning", + MB_OK|MB_ICONEXCLAMATION); +} +TIFFErrorHandler _TIFFwarningHandler = win3WarningHandler; + +static void +win3ErrorHandler(const char* module, const char* fmt, va_list ap) +{ + char e[512] = { '\0' }; + if (module != NULL) + strcat(strcpy(e, module), ":"); + vsprintf(e+strlen(e), fmt, ap); + strcat(e, "."); + MessageBox(GetActiveWindow(), e, "LibTIFF Error", MB_OK|MB_ICONSTOP); +} +TIFFErrorHandler _TIFFerrorHandler = win3ErrorHandler; diff --git a/Utilities/vtktiff/tif_win32.c b/Utilities/vtktiff/tif_win32.c new file mode 100644 index 0000000..d1ff46c --- /dev/null +++ b/Utilities/vtktiff/tif_win32.c @@ -0,0 +1,340 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_win32.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library Win32-specific Routines. Adapted from tif_unix.c 4/5/95 by + * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA + */ +#if defined ( _MSC_VER ) +#pragma warning ( disable : 4115 ) +#endif + +#include <windows.h> +#include "tiffiop.h" + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + DWORD dwSizeRead; + if (!ReadFile(fd, buf, size, &dwSizeRead, NULL)) + return(0); + return ((tsize_t) dwSizeRead); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + DWORD dwSizeWritten; + if (!WriteFile(fd, buf, size, &dwSizeWritten, NULL)) + return(0); + return ((tsize_t) dwSizeWritten); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ + DWORD dwMoveMethod, dwMoveHigh; + + /* we use this as a special code, so avoid accepting it */ + if( off == 0xFFFFFFFF ) + return 0xFFFFFFFF; + + switch(whence) + { + case SEEK_SET: + dwMoveMethod = FILE_BEGIN; + break; + case SEEK_CUR: + dwMoveMethod = FILE_CURRENT; + break; + case SEEK_END: + dwMoveMethod = FILE_END; + break; + default: + dwMoveMethod = FILE_BEGIN; + break; + } + dwMoveHigh = 0; + return ((toff_t)SetFilePointer(fd, (LONG) off, (PLONG)&dwMoveHigh, + dwMoveMethod)); +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (CloseHandle(fd) ? 0 : -1); +} + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + return ((toff_t)GetFileSize(fd, NULL)); +} + +#ifdef __BORLANDC__ +#pragma argsused +#endif +static int +_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + return (0); +} + +/* + * From "Hermann Josef Hill" <lhill@rhein-zeitung.de>: + * + * Windows uses both a handle and a pointer for file mapping, + * but according to the SDK documentation and Richter's book + * "Advanced Windows Programming" it is safe to free the handle + * after obtaining the file mapping pointer + * + * This removes a nasty OS dependency and cures a problem + * with Visual C++ 5.0 + */ +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + toff_t size; + HANDLE hMapFile; + + if ((size = _tiffSizeProc(fd)) == 0xFFFFFFFF) + return (0); + hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, size, NULL); + if (hMapFile == NULL) + return (0); + *pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hMapFile); + if (*pbase == NULL) + return (0); + *psize = size; + return(1); +} + +#ifdef __BORLANDC__ +#pragma argsused +#endif +static void +_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + UnmapViewOfFile(base); +} + +/* + * Open a TIFF file descriptor for read/writing. + * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode + * string, which forces the file to be opened unmapped. + */ +TIFF* +TIFFFdOpen(int ifd, const char* name, const char* mode) +{ + TIFF* tif; + BOOL fSuppressMap = (mode[1] == 'u' || (mode[1]!=0 && mode[2] == 'u')); + + tif = TIFFClientOpen(name, mode, + (thandle_t)ifd, + _tiffReadProc, _tiffWriteProc, + _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, + fSuppressMap ? _tiffDummyMapProc : _tiffMapProc, + fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc); + if (tif) + tif->tif_fd = ifd; + return (tif); +} + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TEXPORT TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + thandle_t fd; + int m; + DWORD dwMode; + + m = _TIFFgetMode(mode, module); + + switch(m) + { + case O_RDONLY: + dwMode = OPEN_EXISTING; + break; + case O_RDWR: + dwMode = OPEN_ALWAYS; + break; + case O_RDWR|O_CREAT: + dwMode = OPEN_ALWAYS; + break; + case O_RDWR|O_TRUNC: + dwMode = CREATE_ALWAYS; + break; + case O_RDWR|O_CREAT|O_TRUNC: + dwMode = CREATE_ALWAYS; + break; + default: + return ((TIFF*)0); + } + fd = (thandle_t)CreateFile(name, (m == O_RDONLY) ? GENERIC_READ : + (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ, NULL, dwMode, + (m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL, NULL); + if (fd == INVALID_HANDLE_VALUE) { + TIFFError(module, "%s: Cannot open", name); + return ((TIFF *)0); + } + return (TIFFFdOpen((int)fd, name, mode)); +} + +tdata_t +TEXPORT _TIFFmalloc(tsize_t s) +{ + return ((tdata_t)GlobalAlloc(GMEM_FIXED, s)); +} + +tdata_t +TEXPORT __TIFFmalloc(tsize_t s) +{ + return ((tdata_t)GlobalAlloc(GMEM_FIXED, s)); +} + +void +TEXPORT _TIFFfree(tdata_t p) +{ + GlobalFree(p); + return; +} + +void +TEXPORT __TIFFfree(tdata_t p) +{ + GlobalFree(p); + return; +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + void* pvTmp; + tsize_t old=GlobalSize(p); + if (old>=s) + { + if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) { + CopyMemory(pvTmp, p, s); + GlobalFree(p); + } + } + else + { + if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) { + CopyMemory(pvTmp, p, old); + GlobalFree(p); + } + } + return ((tdata_t)pvTmp); +} + +void +_TIFFmemset(void* p, int v, tsize_t c) +{ + FillMemory(p, c, (BYTE)v); +} + +void +_TIFFmemcpy(void* d, const tdata_t s, tsize_t c) +{ + CopyMemory(d, s, c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + register const BYTE *pb1 = (const BYTE *) p1; + register const BYTE *pb2 = (const BYTE *) p2; + register DWORD dwTmp = c; + register int iTmp; + for (iTmp = 0; dwTmp-- && !iTmp; iTmp = (int)*pb1++ - (int)*pb2++) + ; + return (iTmp); +} + +static void +Win32WarningHandler(const char* module, const char* fmt, va_list ap) +{ +#ifndef TIF_PLATFORM_CONSOLE + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Warning"; + LPCTSTR szDefaultModule = "TIFFLIB"; + szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module; + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) + + lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL) + return; + wsprintf(szTitle, szTitleText, szTmp); + szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR); + wvsprintf(szTmp, fmt, ap); + MessageBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION); + LocalFree(szTitle); + return; +#else + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif +} +TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler; + +static void +Win32ErrorHandler(const char* module, const char* fmt, va_list ap) +{ +#ifndef TIF_PLATFORM_CONSOLE + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Error"; + LPCTSTR szDefaultModule = "TIFFLIB"; + szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module; + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) + + lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL) + return; + wsprintf(szTitle, szTitleText, szTmp); + szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR); + wvsprintf(szTmp, fmt, ap); + MessageBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION); + LocalFree(szTitle); + return; +#else + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif +} +TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler; diff --git a/Utilities/vtktiff/tif_write.c b/Utilities/vtktiff/tif_write.c new file mode 100644 index 0000000..26fb73b --- /dev/null +++ b/Utilities/vtktiff/tif_write.c @@ -0,0 +1,659 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_write.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Scanline-oriented Write Support + */ +#include "tiffiop.h" +#include <assert.h> +#include <stdio.h> + +#define REWRITE_HACK + +#define STRIPINCR 20 /* expansion factor on strip array */ + +#define WRITECHECKSTRIPS(tif, module) \ + (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module)) +#define WRITECHECKTILES(tif, module) \ + (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module)) +#define BUFFERCHECK(tif) \ + ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \ + TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1)) + +static int TIFFGrowStrips(TIFF*, int, const char*); +static int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t); +static int TIFFSetupStrips(TIFF*); + +int +TEXPORT TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample) +{ + static const char module[] = "TIFFWriteScanline"; + register TIFFDirectory *td; + int status, imagegrew = 0; + tstrip_t strip; + + if (!WRITECHECKSTRIPS(tif, module)) + return (-1); + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized more intelligently (using + * directory information). + */ + if (!BUFFERCHECK(tif)) + return (-1); + td = &tif->tif_dir; + /* + * Extend image length if needed + * (but only for PlanarConfig=1). + */ + if (row >= td->td_imagelength) { /* extend image */ + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFError(tif->tif_name, + "Can not change \"ImageLength\" when using separate planes"); + return (-1); + } + td->td_imagelength = row+1; + imagegrew = 1; + } + /* + * Calculate strip and check for crossings. + */ + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFError(tif->tif_name, + "%d: Sample out of range, max %d", + sample, td->td_samplesperpixel); + return (-1); + } + strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; + } else + strip = row / td->td_rowsperstrip; + if (strip != tif->tif_curstrip) { + /* + * Changing strips -- flush any data present. + */ + if (!TIFFFlushData(tif)) + return (-1); + tif->tif_curstrip = strip; + /* + * Watch out for a growing image. The value of + * strips/image will initially be 1 (since it + * can't be deduced until the imagelength is known). + */ + if (strip >= td->td_stripsperimage && imagegrew) + td->td_stripsperimage = + TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); + tif->tif_row = + (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return (-1); + tif->tif_flags |= TIFF_CODERSETUP; + } + if (!(*tif->tif_preencode)(tif, sample)) + return (-1); + tif->tif_flags |= TIFF_POSTENCODE; + } + /* + * Check strip array to make sure there's space. + * We don't support dynamically growing files that + * have data organized in separate bitplanes because + * it's too painful. In that case we require that + * the imagelength be set properly before the first + * write (so that the strips array will be fully + * allocated above). + */ + if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) + return (-1); + /* + * Ensure the write is either sequential or at the + * beginning of a strip (or that we can randomly + * access the data -- i.e. no encoding). + */ + if (row != tif->tif_row) { + if (row < tif->tif_row) { + /* + * Moving backwards within the same strip: + * backup to the start and then decode + * forward (below). + */ + tif->tif_row = (strip % td->td_stripsperimage) * + td->td_rowsperstrip; + tif->tif_rawcp = tif->tif_rawdata; + } + /* + * Seek forward to the desired row. + */ + if (!(*tif->tif_seek)(tif, row - tif->tif_row)) + return (-1); + tif->tif_row = row; + } + status = (*tif->tif_encoderow)(tif, (tidata_t) buf, + tif->tif_scanlinesize, sample); + tif->tif_row++; + return (status); +} + +/* + * Encode the supplied data and write it to the + * specified strip. There must be space for the + * data; we don't check if strips overlap! + * + * NB: Image length must be setup before writing. + */ +tsize_t +TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteEncodedStrip"; + TIFFDirectory *td = &tif->tif_dir; + tsample_t sample; + + if (!WRITECHECKSTRIPS(tif, module)) + return ((tsize_t) -1); + /* + * Check strip array to make sure there's space. + * We don't support dynamically growing files that + * have data organized in separate bitplanes because + * it's too painful. In that case we require that + * the imagelength be set properly before the first + * write (so that the strips array will be fully + * allocated above). + */ + if (strip >= td->td_nstrips) { + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFError(tif->tif_name, + "Can not grow image by strips when using separate planes"); + return ((tsize_t) -1); + } + if (!TIFFGrowStrips(tif, 1, module)) + return ((tsize_t) -1); + td->td_stripsperimage = + TIFFhowmany(td->td_imagelength, td->td_rowsperstrip); + } + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized according to the directory + * info. + */ + if (!BUFFERCHECK(tif)) + return ((tsize_t) -1); + tif->tif_curstrip = strip; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return ((tsize_t) -1); + tif->tif_flags |= TIFF_CODERSETUP; + } + +#ifdef REWRITE_HACK + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + + if( td->td_stripbytecount[strip] > 0 ) + { + /* if we are writing over existing tiles, zero length. */ + td->td_stripbytecount[strip] = 0; + + /* this forces TIFFAppendToStrip() to do a seek */ + tif->tif_curoff = 0; + } +#endif + + tif->tif_flags &= ~TIFF_POSTENCODE; + sample = (tsample_t)(strip / td->td_stripsperimage); + if (!(*tif->tif_preencode)(tif, sample)) + return ((tsize_t) -1); + if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample)) + return ((tsize_t) 0); + if (!(*tif->tif_postencode)(tif)) + return ((tsize_t) -1); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); + if (tif->tif_rawcc > 0 && + !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) + return ((tsize_t) -1); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + return (cc); +} + +/* + * Write the supplied data to the specified strip. + * There must be space for the data; we don't check + * if strips overlap! + * + * NB: Image length must be setup before writing. + */ +tsize_t +TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteRawStrip"; + TIFFDirectory *td = &tif->tif_dir; + + if (!WRITECHECKSTRIPS(tif, module)) + return ((tsize_t) -1); + /* + * Check strip array to make sure there's space. + * We don't support dynamically growing files that + * have data organized in separate bitplanes because + * it's too painful. In that case we require that + * the imagelength be set properly before the first + * write (so that the strips array will be fully + * allocated above). + */ + if (strip >= td->td_nstrips) { + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFError(tif->tif_name, + "Can not grow image by strips when using separate planes"); + return ((tsize_t) -1); + } + /* + * Watch out for a growing image. The value of + * strips/image will initially be 1 (since it + * can't be deduced until the imagelength is known). + */ + if (strip >= td->td_stripsperimage) + td->td_stripsperimage = + TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); + if (!TIFFGrowStrips(tif, 1, module)) + return ((tsize_t) -1); + } + tif->tif_curstrip = strip; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ? + cc : (tsize_t) -1); +} + +/* + * Write and compress a tile of data. The + * tile is selected by the (x,y,z,s) coordinates. + */ +tsize_t +TIFFWriteTile(TIFF* tif, + tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + if (!TIFFCheckTile(tif, x, y, z, s)) + return (-1); + /* + * NB: A tile size of -1 is used instead of tif_tilesize knowing + * that TIFFWriteEncodedTile will clamp this to the tile size. + * This is done because the tile size may not be defined until + * after the output buffer is setup in TIFFWriteBufferSetup. + */ + return (TIFFWriteEncodedTile(tif, + TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1)); +} + +/* + * Encode the supplied data and write it to the + * specified tile. There must be space for the + * data. The function clamps individual writes + * to a tile to the tile size, but does not (and + * can not) check that multiple writes to the same + * tile do not write more than tile size data. + * + * NB: Image length must be setup before writing; this + * interface does not support automatically growing + * the image on each write (as TIFFWriteScanline does). + */ +tsize_t +TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteEncodedTile"; + TIFFDirectory *td; + tsample_t sample; + + if (!WRITECHECKTILES(tif, module)) + return ((tsize_t) -1); + td = &tif->tif_dir; + if (tile >= td->td_nstrips) { + TIFFError(module, "%s: Tile %lu out of range, max %lu", + tif->tif_name, (u_long) tile, (u_long) td->td_nstrips); + return ((tsize_t) -1); + } + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized more intelligently (using + * directory information). + */ + if (!BUFFERCHECK(tif)) + return ((tsize_t) -1); + tif->tif_curtile = tile; + +#ifdef REWRITE_HACK + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + + if( td->td_stripbytecount[tile] > 0 ) + { + /* if we are writing over existing tiles, zero length. */ + td->td_stripbytecount[tile] = 0; + + /* this forces TIFFAppendToStrip() to do a seek */ + tif->tif_curoff = 0; + } +#endif + + /* + * Compute tiles per row & per column to compute + * current row and column + */ + tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) + * td->td_tilelength; + tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) + * td->td_tilewidth; + + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return ((tsize_t) -1); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_flags &= ~TIFF_POSTENCODE; + sample = (tsample_t)(tile/td->td_stripsperimage); + if (!(*tif->tif_preencode)(tif, sample)) + return ((tsize_t) -1); + /* + * Clamp write amount to the tile size. This is mostly + * done so that callers can pass in some large number + * (e.g. -1) and have the tile size used instead. + */ + if ( cc < 1 || cc > tif->tif_tilesize) + cc = tif->tif_tilesize; + if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample)) + return ((tsize_t) 0); + if (!(*tif->tif_postencode)(tif)) + return ((tsize_t) -1); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc); + if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, + tif->tif_rawdata, tif->tif_rawcc)) + return ((tsize_t) -1); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + return (cc); +} + +/* + * Write the supplied data to the specified strip. + * There must be space for the data; we don't check + * if strips overlap! + * + * NB: Image length must be setup before writing; this + * interface does not support automatically growing + * the image on each write (as TIFFWriteScanline does). + */ +tsize_t +TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteRawTile"; + + if (!WRITECHECKTILES(tif, module)) + return ((tsize_t) -1); + if (tile >= tif->tif_dir.td_nstrips) { + TIFFError(module, "%s: Tile %lu out of range, max %lu", + tif->tif_name, (u_long) tile, + (u_long) tif->tif_dir.td_nstrips); + return ((tsize_t) -1); + } + return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ? + cc : (tsize_t) -1); +} + +#define isUnspecified(tif, f) \ + (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0) + +static int +TIFFSetupStrips(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + + if (isTiled(tif)) + td->td_stripsperimage = + isUnspecified(tif, FIELD_TILEDIMENSIONS) ? + td->td_samplesperpixel : TIFFNumberOfTiles(tif); + else + td->td_stripsperimage = + isUnspecified(tif, FIELD_ROWSPERSTRIP) ? + td->td_samplesperpixel : TIFFNumberOfStrips(tif); + td->td_nstrips = td->td_stripsperimage; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + td->td_stripsperimage /= td->td_samplesperpixel; + td->td_stripoffset = (uint32 *) + _TIFFmalloc(td->td_nstrips * sizeof (uint32)); + td->td_stripbytecount = (uint32 *) + _TIFFmalloc(td->td_nstrips * sizeof (uint32)); + if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) + return (0); + /* + * Place data at the end-of-file + * (by setting offsets to zero). + */ + _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32)); + _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32)); + TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); + TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); + return (1); +} +#undef isUnspecified + +/* + * Verify file is writable and that the directory + * information is setup properly. In doing the latter + * we also "freeze" the state of the directory so + * that important information is not changed. + */ +int +TIFFWriteCheck(TIFF* tif, int tiles, const char* module) +{ + if (tif->tif_mode == O_RDONLY) { + TIFFError(module, "%s: File not open for writing", + tif->tif_name); + return (0); + } + if (tiles ^ isTiled(tif)) { + TIFFError(tif->tif_name, tiles ? + "Can not write tiles to a stripped image" : + "Can not write scanlines to a tiled image"); + return (0); + } + /* + * On the first write verify all the required information + * has been setup and initialize any data structures that + * had to wait until directory information was set. + * Note that a lot of our work is assumed to remain valid + * because we disallow any of the important parameters + * from changing after we start writing (i.e. once + * TIFF_BEENWRITING is set, TIFFSetField will only allow + * the image's length to be changed). + */ + if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { + TIFFError(module, + "%s: Must set \"ImageWidth\" before writing data", + tif->tif_name); + return (0); + } + if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { + TIFFError(module, + "%s: Must set \"PlanarConfiguration\" before writing data", + tif->tif_name); + return (0); + } + if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { + tif->tif_dir.td_nstrips = 0; + TIFFError(module, "%s: No space for %s arrays", + tif->tif_name, isTiled(tif) ? "tile" : "strip"); + return (0); + } + tif->tif_tilesize = TIFFTileSize(tif); + tif->tif_scanlinesize = TIFFScanlineSize(tif); + tif->tif_flags |= TIFF_BEENWRITING; + return (1); +} + +/* + * Setup the raw data buffer used for encoding. + */ +int +TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) +{ + static const char module[] = "TIFFWriteBufferSetup"; + + if (tif->tif_rawdata) { + if (tif->tif_flags & TIFF_MYBUFFER) { + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + } + tif->tif_rawdata = NULL; + } + if (size == (tsize_t) -1) { + size = (isTiled(tif) ? + tif->tif_tilesize : tif->tif_scanlinesize); + /* + * Make raw data buffer at least 8K + */ + if (size < 8*1024) + size = 8*1024; + bp = NULL; /* NB: force malloc */ + } + if (bp == NULL) { + bp = _TIFFmalloc(size); + if (bp == NULL) { + TIFFError(module, "%s: No space for output buffer", + tif->tif_name); + return (0); + } + tif->tif_flags |= TIFF_MYBUFFER; + } else + tif->tif_flags &= ~TIFF_MYBUFFER; + tif->tif_rawdata = (tidata_t) bp; + tif->tif_rawdatasize = size; + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_flags |= TIFF_BUFFERSETUP; + return (1); +} + +/* + * Grow the strip data structures by delta strips. + */ +static int +TIFFGrowStrips(TIFF* tif, int delta, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + + assert(td->td_planarconfig == PLANARCONFIG_CONTIG); + td->td_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset, + (td->td_nstrips + delta) * sizeof (uint32)); + td->td_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount, + (td->td_nstrips + delta) * sizeof (uint32)); + if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) { + td->td_nstrips = 0; + TIFFError(module, "%s: No space to expand strip arrays", + tif->tif_name); + return (0); + } + _TIFFmemset(td->td_stripoffset+td->td_nstrips, 0, delta*sizeof (uint32)); + _TIFFmemset(td->td_stripbytecount+td->td_nstrips, 0, delta*sizeof (uint32)); + td->td_nstrips += delta; + return (1); +} + +/* + * Append the data to the specified strip. + * + * NB: We don't check that there's space in the + * file (i.e. that strips do not overlap). + */ +static int +TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) +{ + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "TIFFAppendToStrip"; + + if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { + /* + * No current offset, set the current strip. + */ + if (td->td_stripoffset[strip] != 0) { + if (!SeekOK(tif, td->td_stripoffset[strip])) { + TIFFError(module, + "%s: Seek error at scanline %lu", + tif->tif_name, (u_long) tif->tif_row); + return (0); + } + } else + td->td_stripoffset[strip] = + TIFFSeekFile(tif, (toff_t) 0, SEEK_END); + tif->tif_curoff = td->td_stripoffset[strip]; + } + if (!WriteOK(tif, data, cc)) { + TIFFError(module, "%s: Write error at scanline %lu", + tif->tif_name, (u_long) tif->tif_row); + return (0); + } + tif->tif_curoff += cc; + td->td_stripbytecount[strip] += cc; + return (1); +} + +/* + * Internal version of TIFFFlushData that can be + * called by ``encodestrip routines'' w/o concern + * for infinite recursion. + */ +int +TIFFFlushData1(TIFF* tif) +{ + if (tif->tif_rawcc > 0) { + if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((u_char *)tif->tif_rawdata, + tif->tif_rawcc); + if (!TIFFAppendToStrip(tif, + isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, + tif->tif_rawdata, tif->tif_rawcc)) + return (0); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + } + return (1); +} + +/* + * Set the current write offset. This should only be + * used to set the offset to a known previous location + * (very carefully), or to 0 so that the next write gets + * appended to the end of the file. + */ +void +TIFFSetWriteOffset(TIFF* tif, toff_t off) +{ + tif->tif_curoff = off; +} diff --git a/Utilities/vtktiff/tif_zip.c b/Utilities/vtktiff/tif_zip.c new file mode 100644 index 0000000..7363074 --- /dev/null +++ b/Utilities/vtktiff/tif_zip.c @@ -0,0 +1,371 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tif_zip.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1995-1997 Sam Leffler + * Copyright (c) 1995-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef ZIP_SUPPORT +#include "vtk_zlib.h" +#endif + +#include "tiffiop.h" +#ifdef ZIP_SUPPORT +/* + * TIFF Library. + * + * ZIP (aka Deflate) Compression Support + * + * This file is simply an interface to the zlib library written by + * Jean-loup Gailly and Mark Adler. You must use version 1.0 or later + * of the library: this code assumes the 1.0 API and also depends on + * the ability to write the zlib header multiple times (one per strip) + * which was not possible with versions prior to 0.95. Note also that + * older versions of this codec avoided this bug by supressing the header + * entirely. This means that files written with the old library cannot + * be read; they should be converted to a different compression scheme + * and then reconverted. + * + * The data format used by the zlib library is described in the files + * zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available in the + * directory ftp://ftp.uu.net/pub/archiving/zip/doc. The library was + * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz. + */ +#include "tif_predict.h" + +#include <stdio.h> +#include <assert.h> + +/* + * Sigh, ZLIB_VERSION is defined as a string so there's no + * way to do a proper check here. Instead we guess based + * on the presence of #defines that were added between the + * 0.95 and 1.0 distributions. + */ +#if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED) +#error "Antiquated ZLIB software; you must use version 1.0 or later" +#endif + +/* + * State block for each open TIFF + * file using ZIP compression/decompression. + */ +typedef struct { + TIFFPredictorState predict; + z_stream stream; + int zipquality; /* compression level */ + int state; /* state flags */ +#define ZSTATE_INIT 0x1 /* zlib setup successfully */ + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ +} ZIPState; + +#define ZState(tif) ((ZIPState*) (tif)->tif_data) +#define DecoderState(tif) ZState(tif) +#define EncoderState(tif) ZState(tif) + +static int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t); +static int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t); + +static int +ZIPSetupDecode(TIFF* tif) +{ + ZIPState* sp = DecoderState(tif); + static const char module[] = "ZIPSetupDecode"; + + assert(sp != NULL); + if (inflateInit(&sp->stream) != Z_OK) { + TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= ZSTATE_INIT; + return (1); + } +} + +/* + * Setup state for decoding a strip. + */ +static int +ZIPPreDecode(TIFF* tif, tsample_t s) +{ + ZIPState* sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + sp->stream.next_in = tif->tif_rawdata; + sp->stream.avail_in = tif->tif_rawcc; + return (inflateReset(&sp->stream) == Z_OK); +} + +static int +ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + ZIPState* sp = DecoderState(tif); + static const char module[] = "ZIPDecode"; + + (void) s; + assert(sp != NULL); + sp->stream.next_out = op; + sp->stream.avail_out = occ; + do { + int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + if (state == Z_STREAM_END) + break; + if (state == Z_DATA_ERROR) { + TIFFError(module, + "%s: Decoding error at scanline %d, %s", + tif->tif_name, tif->tif_row, sp->stream.msg); + if (inflateSync(&sp->stream) != Z_OK) + return (0); + continue; + } + if (state != Z_OK) { + TIFFError(module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (sp->stream.avail_out > 0); + if (sp->stream.avail_out != 0) { + TIFFError(module, + "%s: Not enough data at scanline %d (short %d bytes)", + tif->tif_name, tif->tif_row, sp->stream.avail_out); + return (0); + } + return (1); +} + +static int +ZIPSetupEncode(TIFF* tif) +{ + ZIPState* sp = EncoderState(tif); + static const char module[] = "ZIPSetupEncode"; + + assert(sp != NULL); + if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) { + TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= ZSTATE_INIT; + return (1); + } +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +ZIPPreEncode(TIFF* tif, tsample_t s) +{ + ZIPState *sp = EncoderState(tif); + + (void) s; + assert(sp != NULL); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + return (deflateReset(&sp->stream) == Z_OK); +} + +/* + * Encode a chunk of pixels. + */ +static int +ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + ZIPState *sp = EncoderState(tif); + static const char module[] = "ZIPEncode"; + + (void) s; + sp->stream.next_in = bp; + sp->stream.avail_in = cc; + do { + if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { + TIFFError(module, "%s: Encoder error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + if (sp->stream.avail_out == 0) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + } while (sp->stream.avail_in > 0); + return (1); +} + +/* + * Finish off an encoded strip by flushing the last + * string and tacking on an End Of Information code. + */ +static int +ZIPPostEncode(TIFF* tif) +{ + ZIPState *sp = EncoderState(tif); + static const char module[] = "ZIPPostEncode"; + int state; + + sp->stream.avail_in = 0; + do { + state = deflate(&sp->stream, Z_FINISH); + switch (state) { + case Z_STREAM_END: + case Z_OK: + if ((tsize_t)sp->stream.avail_out != + tif->tif_rawdatasize) { + tif->tif_rawcc = + tif->tif_rawdatasize - sp->stream.avail_out; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + break; + default: + TIFFError(module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (state != Z_STREAM_END); + return (1); +} + +static void +ZIPCleanup(TIFF* tif) +{ + ZIPState* sp = ZState(tif); + if (sp) { + if (sp->state&ZSTATE_INIT) { + /* NB: avoid problems in the library */ + if (tif->tif_mode == O_RDONLY) + inflateEnd(&sp->stream); + else + deflateEnd(&sp->stream); + } + _TIFFfree(sp); + tif->tif_data = NULL; + } +} + +static int +ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + ZIPState* sp = ZState(tif); + static const char module[] = "ZIPVSetField"; + + switch (tag) { + case TIFFTAG_ZIPQUALITY: + sp->zipquality = va_arg(ap, int); + if (tif->tif_mode != O_RDONLY && (sp->state&ZSTATE_INIT)) { + if (deflateParams(&sp->stream, + sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) { + TIFFError(module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } + return (1); + default: + return (*sp->vsetparent)(tif, tag, ap); + } + /*NOTREACHED*/ +} + +static int +ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + ZIPState* sp = ZState(tif); + + switch (tag) { + case TIFFTAG_ZIPQUALITY: + *va_arg(ap, int*) = sp->zipquality; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static const TIFFFieldInfo zipFieldInfo[] = { + { TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO, + TRUE, FALSE, "" }, +}; +#define N(a) (sizeof (a) / sizeof (a[0])) + +int +TIFFInitZIP(TIFF* tif, int scheme) +{ + ZIPState* sp; + + assert( (scheme == COMPRESSION_DEFLATE) || (scheme == COMPRESSION_ADOBE_DEFLATE)); + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState)); + if (tif->tif_data == NULL) + goto bad; + sp = ZState(tif); + sp->stream.zalloc = NULL; + sp->stream.zfree = NULL; + sp->stream.opaque = NULL; + sp->stream.data_type = Z_BINARY; + + /* + * Merge codec-specific tag information and + * override parent get/set field methods. + */ + _TIFFMergeFieldInfo(tif, zipFieldInfo, N(zipFieldInfo)); + sp->vgetparent = tif->tif_vgetfield; + tif->tif_vgetfield = ZIPVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_vsetfield; + tif->tif_vsetfield = ZIPVSetField; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */ + sp->state = 0; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = ZIPSetupDecode; + tif->tif_predecode = ZIPPreDecode; + tif->tif_decoderow = ZIPDecode; + tif->tif_decodestrip = ZIPDecode; + tif->tif_decodetile = ZIPDecode; + tif->tif_setupencode = ZIPSetupEncode; + tif->tif_preencode = ZIPPreEncode; + tif->tif_postencode = ZIPPostEncode; + tif->tif_encoderow = ZIPEncode; + tif->tif_encodestrip = ZIPEncode; + tif->tif_encodetile = ZIPEncode; + tif->tif_cleanup = ZIPCleanup; + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + return (1); +bad: + TIFFError("TIFFInitZIP", "No space for ZIP state block"); + return (0); +} +#endif /* ZIP_SUPORT */ diff --git a/Utilities/vtktiff/tiff.h b/Utilities/vtktiff/tiff.h new file mode 100644 index 0000000..47a0e54 --- /dev/null +++ b/Utilities/vtktiff/tiff.h @@ -0,0 +1,477 @@ +#include "vtk_tiff_mangle.h" +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tiff.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFF_ +#define _TIFF_ +/* + * Tag Image File Format (TIFF) + * + * Based on Rev 6.0 from: + * Developer's Desk + * Aldus Corporation + * 411 First Ave. South + * Suite 200 + * Seattle, WA 98104 + * 206-622-5500 + */ +#define TIFF_VERSION 42 + +#define TIFF_BIGENDIAN 0x4d4d +#define TIFF_LITTLEENDIAN 0x4949 + +/* + * The so called TIFF types conflict with definitions from inttypes.h + * included from sys/types.h on AIX (at least using VisualAge compiler). + * We try to work around this by detecting this case. Defining + * _TIFF_DATA_TYPEDEFS_ short circuits the later definitions in tiff.h, and + * we will in the holes not provided for by inttypes.h. + * + * See http://bugzilla.remotesensing.org/show_bug.cgi?id=39 + */ +#if defined(_H_INTTYPES) && defined(_ALL_SOURCE) + +#define _TIFF_DATA_TYPEDEFS_ +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; + +#endif + +/* + * Intrinsic data types required by the file format: + * + * 8-bit quantities int8/uint8 + * 16-bit quantities int16/uint16 + * 32-bit quantities int32/uint32 + * strings unsigned char* + */ +#ifndef _TIFF_DATA_TYPEDEFS_ +#define _TIFF_DATA_TYPEDEFS_ + +#ifdef __STDC__ +typedef signed char int8; /* NB: non-ANSI compilers may not grok */ +#else +typedef char int8; +#endif +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; /* sizeof (uint16) must == 2 */ +#if defined(__alpha) || (defined(_MIPS_SZLONG) && _MIPS_SZLONG == 64) || defined(__LP64__) +typedef int int32; +typedef unsigned int uint32; /* sizeof (uint32) must == 4 */ +#else +typedef long int32; +typedef unsigned long uint32; /* sizeof (uint32) must == 4 */ +#endif +#endif /* _TIFF_DATA_TYPEDEFS_ */ + +/* For TIFFReassignTagToIgnore */ +enum TIFFIgnoreSense /* IGNORE tag table */ +{ + TIS_STORE, + TIS_EXTRACT, + TIS_EMPTY +}; + +typedef struct { + uint16 tiff_magic; /* magic number (defines byte order) */ + uint16 tiff_version; /* TIFF version number */ + uint32 tiff_diroff; /* byte offset to first directory */ +} TIFFHeader; + +/* + * TIFF Image File Directories are comprised of + * a table of field descriptors of the form shown + * below. The table is sorted in ascending order + * by tag. The values associated with each entry + * are disjoint and may appear anywhere in the file + * (so long as they are placed on a word boundary). + * + * If the value is 4 bytes or less, then it is placed + * in the offset field to save space. If the value + * is less than 4 bytes, it is left-justified in the + * offset field. + */ +typedef struct { + uint16 tdir_tag; /* see below */ + uint16 tdir_type; /* data type; see below */ + uint32 tdir_count; /* number of items; length in spec */ + uint32 tdir_offset; /* byte offset to field data */ +} TIFFDirEntry; + +/* + * NB: In the comments below, + * - items marked with a + are obsoleted by revision 5.0, + * - items marked with a ! are introduced in revision 6.0. + * - items marked with a % are introduced post revision 6.0. + * - items marked with a $ are obsoleted by revision 6.0. + */ + +/* + * Tag data type information. + * + * Note: RATIONALs are the ratio of two 32-bit integer values. + */ +typedef enum { + TIFF_NOTYPE = 0, /* placeholder */ + TIFF_BYTE = 1, /* 8-bit unsigned integer */ + TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ + TIFF_SHORT = 3, /* 16-bit unsigned integer */ + TIFF_LONG = 4, /* 32-bit unsigned integer */ + TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ + TIFF_SBYTE = 6, /* !8-bit signed integer */ + TIFF_UNDEFINED = 7, /* !8-bit untyped data */ + TIFF_SSHORT = 8, /* !16-bit signed integer */ + TIFF_SLONG = 9, /* !32-bit signed integer */ + TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ + TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ + TIFF_DOUBLE = 12 /* !64-bit IEEE floating point */ +} TIFFDataType; + +/* + * TIFF Tag Definitions. + */ +#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */ +#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */ +#define FILETYPE_PAGE 0x2 /* one page of many */ +#define FILETYPE_MASK 0x4 /* transparency mask */ +#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */ +#define OFILETYPE_IMAGE 1 /* full resolution image data */ +#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */ +#define OFILETYPE_PAGE 3 /* one page of many */ +#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */ +#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */ +#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */ +#define TIFFTAG_COMPRESSION 259 /* data compression technique */ +#define COMPRESSION_NONE 1 /* dump mode */ +#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ +#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ +#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */ +#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ +#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */ +#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ +#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */ +#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */ +#define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ +#define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ +#define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ +#define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ +/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@etsinc.com) */ +#define COMPRESSION_IT8CTPAD 32895 /* IT8 CT w/padding */ +#define COMPRESSION_IT8LW 32896 /* IT8 Linework RLE */ +#define COMPRESSION_IT8MP 32897 /* IT8 Monochrome picture */ +#define COMPRESSION_IT8BL 32898 /* IT8 Binary line art */ +/* compression codes 32908-32911 are reserved for Pixar */ +#define COMPRESSION_PIXARFILM 32908 /* Pixar companded 10bit LZW */ +#define COMPRESSION_PIXARLOG 32909 /* Pixar companded 11bit ZIP */ +#define COMPRESSION_DEFLATE 32946 /* Deflate compression */ +#define COMPRESSION_ADOBE_DEFLATE 8 /* Deflate compression, as recognized by Adobe */ +/* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */ +#define COMPRESSION_DCS 32947 /* Kodak DCS encoding */ +#define COMPRESSION_JBIG 34661 /* ISO JBIG */ +#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ +#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ +#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ +#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */ +#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */ +#define PHOTOMETRIC_RGB 2 /* RGB color model */ +#define PHOTOMETRIC_PALETTE 3 /* color map indexed */ +#define PHOTOMETRIC_MASK 4 /* $holdout mask */ +#define PHOTOMETRIC_SEPARATED 5 /* !color separations */ +#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */ +#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */ +#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */ +#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */ +#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */ +#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */ +#define THRESHHOLD_BILEVEL 1 /* b&w art scan */ +#define THRESHHOLD_HALFTONE 2 /* or dithered scan */ +#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */ +#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */ +#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */ +#define TIFFTAG_FILLORDER 266 /* data order within a byte */ +#define FILLORDER_MSB2LSB 1 /* most significant -> least */ +#define FILLORDER_LSB2MSB 2 /* least significant -> most */ +#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */ +#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */ +#define TIFFTAG_MAKE 271 /* scanner manufacturer name */ +#define TIFFTAG_MODEL 272 /* scanner model name/number */ +#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */ +#define TIFFTAG_ORIENTATION 274 /* +image orientation */ +#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */ +#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */ +#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */ +#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */ +#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */ +#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */ +#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */ +#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */ +#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */ +#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */ +#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */ +#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */ +#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */ +#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */ +#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */ +#define TIFFTAG_PLANARCONFIG 284 /* storage organization */ +#define PLANARCONFIG_CONTIG 1 /* single image plane */ +#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */ +#define TIFFTAG_PAGENAME 285 /* page name image is from */ +#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */ +#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */ +#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */ +#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */ +#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */ +#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */ +#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */ +#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */ +#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */ +#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */ +#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */ +#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */ +#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */ +#define RESUNIT_NONE 1 /* no meaningful units */ +#define RESUNIT_INCH 2 /* english */ +#define RESUNIT_CENTIMETER 3 /* metric */ +#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */ +#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */ +#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */ +#define TIFFTAG_SOFTWARE 305 /* name & release */ +#define TIFFTAG_DATETIME 306 /* creation date and time */ +#define TIFFTAG_ARTIST 315 /* creator of image */ +#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */ +#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */ +#define TIFFTAG_WHITEPOINT 318 /* image white point */ +#define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ +#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ +#define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ +#define TIFFTAG_TILEWIDTH 322 /* !rows/data tile */ +#define TIFFTAG_TILELENGTH 323 /* !cols/data tile */ +#define TIFFTAG_TILEOFFSETS 324 /* !offsets to data tiles */ +#define TIFFTAG_TILEBYTECOUNTS 325 /* !byte counts for tiles */ +#define TIFFTAG_BADFAXLINES 326 /* lines w/ wrong pixel count */ +#define TIFFTAG_CLEANFAXDATA 327 /* regenerated line info */ +#define CLEANFAXDATA_CLEAN 0 /* no errors detected */ +#define CLEANFAXDATA_REGENERATED 1 /* receiver regenerated lines */ +#define CLEANFAXDATA_UNCLEAN 2 /* uncorrected errors exist */ +#define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */ +#define TIFFTAG_SUBIFD 330 /* subimage descriptors */ +#define TIFFTAG_INKSET 332 /* !inks in separated image */ +#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black */ +#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */ +#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */ +#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */ +#define TIFFTAG_TARGETPRINTER 337 /* !separation target */ +#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */ +#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */ +#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */ +#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */ +#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */ +#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */ +#define SAMPLEFORMAT_INT 2 /* !signed integer data */ +#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */ +#define SAMPLEFORMAT_VOID 4 /* !untyped data */ +#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */ +#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */ +#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */ +#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */ +#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */ +/* + * Tags 512-521 are obsoleted by Technical Note #2 + * which specifies a revised JPEG-in-TIFF scheme. + */ +#define TIFFTAG_JPEGPROC 512 /* !JPEG processing algorithm */ +#define JPEGPROC_BASELINE 1 /* !baseline sequential */ +#define JPEGPROC_LOSSLESS 14 /* !Huffman coded lossless */ +#define TIFFTAG_JPEGIFOFFSET 513 /* !pointer to SOI marker */ +#define TIFFTAG_JPEGIFBYTECOUNT 514 /* !JFIF stream length */ +#define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ +#define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ +#define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ +#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ +#define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ +#define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ +#define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ +#define TIFFTAG_YCBCRSUBSAMPLING 530 /* !YCbCr subsampling factors */ +#define TIFFTAG_YCBCRPOSITIONING 531 /* !subsample positioning */ +#define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */ +#define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */ +#define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */ +/* tags 32952-32956 are private tags registered to Island Graphics */ +#define TIFFTAG_REFPTS 32953 /* image reference points */ +#define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */ +#define TIFFTAG_REGIONWARPCORNERS 32955 /* warp quadrilateral */ +#define TIFFTAG_REGIONAFFINE 32956 /* affine transformation mat */ +/* tags 32995-32999 are private tags registered to SGI */ +#define TIFFTAG_MATTEING 32995 /* $use ExtraSamples */ +#define TIFFTAG_DATATYPE 32996 /* $use SampleFormat */ +#define TIFFTAG_IMAGEDEPTH 32997 /* z depth of image */ +#define TIFFTAG_TILEDEPTH 32998 /* z depth/data tile */ +/* tags 33300-33309 are private tags registered to Pixar */ +/* + * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH + * are set when an image has been cropped out of a larger image. + * They reflect the size of the original uncropped image. + * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used + * to determine the position of the smaller image in the larger one. + */ +#define TIFFTAG_PIXAR_IMAGEFULLWIDTH 33300 /* full image size in x */ +#define TIFFTAG_PIXAR_IMAGEFULLLENGTH 33301 /* full image size in y */ + /* Tags 33302-33306 are used to identify special image modes and data + * used by Pixar's texture formats. + */ +#define TIFFTAG_PIXAR_TEXTUREFORMAT 33302 /* texture map format */ +#define TIFFTAG_PIXAR_WRAPMODES 33303 /* s & t wrap modes */ +#define TIFFTAG_PIXAR_FOVCOT 33304 /* cotan(fov) for env. maps */ +#define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305 +#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306 +/* tag 33405 is a private tag registered to Eastman Kodak */ +#define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */ +/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */ +#define TIFFTAG_COPYRIGHT 33432 /* copyright string */ +/* some UIC tags */ +#define TIFFTAG_UIC1TAG 33628 +#define TIFFTAG_UIC2TAG 33629 +#define TIFFTAG_UIC3TAG 33630 +#define TIFFTAG_UIC4TAG 33631 +/* IPTC TAG from RichTIFF specifications */ +#define TIFFTAG_RICHTIFFIPTC 33723 +/* 34016-34029 are reserved for ANSI IT8 TIFF/IT <dkelly@etsinc.com) */ +#define TIFFTAG_IT8SITE 34016 /* site name */ +#define TIFFTAG_IT8COLORSEQUENCE 34017 /* color seq. [RGB,CMYK,etc] */ +#define TIFFTAG_IT8HEADER 34018 /* DDES Header */ +#define TIFFTAG_IT8RASTERPADDING 34019 /* raster scanline padding */ +#define TIFFTAG_IT8BITSPERRUNLENGTH 34020 /* # of bits in short run */ +#define TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH 34021/* # of bits in long run */ +#define TIFFTAG_IT8COLORTABLE 34022 /* LW colortable */ +#define TIFFTAG_IT8IMAGECOLORINDICATOR 34023 /* BP/BL image color switch */ +#define TIFFTAG_IT8BKGCOLORINDICATOR 34024 /* BP/BL bg color switch */ +#define TIFFTAG_IT8IMAGECOLORVALUE 34025 /* BP/BL image color value */ +#define TIFFTAG_IT8BKGCOLORVALUE 34026 /* BP/BL bg color value */ +#define TIFFTAG_IT8PIXELINTENSITYRANGE 34027 /* MP pixel intensity value */ +#define TIFFTAG_IT8TRANSPARENCYINDICATOR 34028 /* HC transparency switch */ +#define TIFFTAG_IT8COLORCHARACTERIZATION 34029 /* color character. table */ +/* tags 34232-34236 are private tags registered to Texas Instruments */ +#define TIFFTAG_FRAMECOUNT 34232 /* Sequence Frame Count */ +/* tag for zeiss confocal microscopes */ +#define TIFFTAG_CZ_LSMINFO 34412 +/* tag 34750 is a private tag registered to Adobe? */ +#define TIFFTAG_ICCPROFILE 34675 /* ICC profile data */ +/* tag 34377 is private tag registered to Adobe for PhotoShop */ +#define TIFFTAG_PHOTOSHOP 34377 +/* tag 34750 is a private tag registered to Pixel Magic */ +#define TIFFTAG_JBIGOPTIONS 34750 /* JBIG options */ +/* tags 34908-34914 are private tags registered to SGI */ +#define TIFFTAG_FAXRECVPARAMS 34908 /* encoded Class 2 ses. parms */ +#define TIFFTAG_FAXSUBADDRESS 34909 /* received SubAddr string */ +#define TIFFTAG_FAXRECVTIME 34910 /* receive time (secs) */ +/* tags 37439-37443 are registered to SGI <gregl@sgi.com> */ +#define TIFFTAG_STONITS 37439 /* Sample value to Nits */ +/* tag 34929 is a private tag registered to FedEx */ +#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */ +/* tag 65535 is an undefined tag used by Eastman Kodak */ +#define TIFFTAG_DCSHUESHIFTVALUES 65535 /* hue shift correction data */ + +/* + * The following are ``pseudo tags'' that can be + * used to control codec-specific functionality. + * These tags are not written to file. Note that + * these values start at 0xffff+1 so that they'll + * never collide with Aldus-assigned tags. + * + * If you want your private pseudo tags ``registered'' + * (i.e. added to this file), send mail to sam@sgi.com + * with the appropriate C definitions to add. + */ +#define TIFFTAG_FAXMODE 65536 /* Group 3/4 format control */ +#define FAXMODE_CLASSIC 0x0000 /* default, include RTC */ +#define FAXMODE_NORTC 0x0001 /* no RTC at end of data */ +#define FAXMODE_NOEOL 0x0002 /* no EOL code at end of row */ +#define FAXMODE_BYTEALIGN 0x0004 /* byte align row */ +#define FAXMODE_WORDALIGN 0x0008 /* word align row */ +#define FAXMODE_CLASSF FAXMODE_NORTC /* TIFF Class F */ +#define TIFFTAG_JPEGQUALITY 65537 /* Compression quality level */ +/* Note: quality level is on the IJG 0-100 scale. Default value is 75 */ +#define TIFFTAG_JPEGCOLORMODE 65538 /* Auto RGB<=>YCbCr convert? */ +#define JPEGCOLORMODE_RAW 0x0000 /* no conversion (default) */ +#define JPEGCOLORMODE_RGB 0x0001 /* do auto conversion */ +#define TIFFTAG_JPEGTABLESMODE 65539 /* What to put in JPEGTables */ +#define JPEGTABLESMODE_QUANT 0x0001 /* include quantization tbls */ +#define JPEGTABLESMODE_HUFF 0x0002 /* include Huffman tbls */ +/* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */ +#define TIFFTAG_FAXFILLFUNC 65540 /* G3/G4 fill function */ +#define TIFFTAG_PIXARLOGDATAFMT 65549 /* PixarLogCodec I/O data sz */ +#define PIXARLOGDATAFMT_8BIT 0 /* regular u_char samples */ +#define PIXARLOGDATAFMT_8BITABGR 1 /* ABGR-order u_chars */ +#define PIXARLOGDATAFMT_11BITLOG 2 /* 11-bit log-encoded (raw) */ +#define PIXARLOGDATAFMT_12BITPICIO 3 /* as per PICIO (1.0==2048) */ +#define PIXARLOGDATAFMT_16BIT 4 /* signed short samples */ +#define PIXARLOGDATAFMT_FLOAT 5 /* IEEE float samples */ +/* 65550-65556 are allocated to Oceana Matrix <dev@oceana.com> */ +#define TIFFTAG_DCSIMAGERTYPE 65550 /* imager model & filter */ +#define DCSIMAGERMODEL_M3 0 /* M3 chip (1280 x 1024) */ +#define DCSIMAGERMODEL_M5 1 /* M5 chip (1536 x 1024) */ +#define DCSIMAGERMODEL_M6 2 /* M6 chip (3072 x 2048) */ +#define DCSIMAGERFILTER_IR 0 /* infrared filter */ +#define DCSIMAGERFILTER_MONO 1 /* monochrome filter */ +#define DCSIMAGERFILTER_CFA 2 /* color filter array */ +#define DCSIMAGERFILTER_OTHER 3 /* other filter */ +#define TIFFTAG_DCSINTERPMODE 65551 /* interpolation mode */ +#define DCSINTERPMODE_NORMAL 0x0 /* whole image, default */ +#define DCSINTERPMODE_PREVIEW 0x1 /* preview of image (384x256) */ +#define TIFFTAG_DCSBALANCEARRAY 65552 /* color balance values */ +#define TIFFTAG_DCSCORRECTMATRIX 65553 /* color correction values */ +#define TIFFTAG_DCSGAMMA 65554 /* gamma value */ +#define TIFFTAG_DCSTOESHOULDERPTS 65555 /* toe & shoulder points */ +#define TIFFTAG_DCSCALIBRATIONFD 65556 /* calibration file desc */ +/* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */ +#define TIFFTAG_ZIPQUALITY 65557 /* compression quality level */ +#define TIFFTAG_PIXARLOGQUALITY 65558 /* PixarLog uses same scale */ +/* 65559 is allocated to Oceana Matrix <dev@oceana.com> */ +#define TIFFTAG_DCSCLIPRECTANGLE 65559 /* area of image to acquire */ +#define TIFFTAG_SGILOGDATAFMT 65560 /* SGILog user data format */ +#define SGILOGDATAFMT_FLOAT 0 /* IEEE float samples */ +#define SGILOGDATAFMT_16BIT 1 /* 16-bit samples */ +#define SGILOGDATAFMT_RAW 2 /* uninterpreted data */ +#define SGILOGDATAFMT_8BIT 3 /* 8-bit RGB monitor values */ +#define TIFFTAG_SGILOGENCODE 65561 /* SGILog data encoding control*/ +#define SGILOGENCODE_NODITHER 0 /* do not dither encoded values*/ +#define SGILOGENCODE_RANDITHER 1 /* randomly dither encd values */ + +#endif /* _TIFF_ */ diff --git a/Utilities/vtktiff/tiffDllConfig.h.in b/Utilities/vtktiff/tiffDllConfig.h.in new file mode 100644 index 0000000..fd80c1c --- /dev/null +++ b/Utilities/vtktiff/tiffDllConfig.h.in @@ -0,0 +1,7 @@ +#ifndef _tiffDllConfig_h +#define _tiffDllConfig_h + +#cmakedefine TIFFDLL +#cmakedefine TIFFSTATIC + +#endif diff --git a/Utilities/vtktiff/tiffcomp.h b/Utilities/vtktiff/tiffcomp.h new file mode 100644 index 0000000..3797f8d --- /dev/null +++ b/Utilities/vtktiff/tiffcomp.h @@ -0,0 +1,218 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tiffcomp.h,v 1.2 2005/04/13 10:50:59 david.cole Exp $ */ + +/* + * Copyright (c) 1990-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _COMPAT_ +#define _COMPAT_ +/* + * This file contains a hodgepodge of definitions and + * declarations that are needed to provide compatibility + * between the native system and the base implementation + * that the library assumes. + * + * NB: This file is a mess. + */ + +/* + * Setup basic type definitions and function declaratations. + */ + +/* + * Simplify Acorn RISC OS identifier (to avoid confusion with Acorn RISC iX + * and with defunct Unix Risc OS) + * No need to specify __arm - hey, Acorn might port the OS, no problem here! + */ +#ifdef __acornriscos +#undef __acornriscos +#endif +#if defined(__acorn) && defined(__riscos) +#define __acornriscos +#endif + +#if defined(__MWERKS__) || defined(THINK_C) +#include <unix.h> +#include <math.h> +#endif + +#include <stdio.h> + +#if defined(__PPCC__) || defined(__SC__) || defined(__MRC__) +#include <types.h> +#elif !defined(__MWERKS__) && !defined(THINK_C) && !defined(__acornriscos) && !defined(applec) +#include <sys/types.h> +#endif + +#if defined(VMS) +#include <file.h> +#include <unixio.h> +#elif !defined(__acornriscos) +#include <fcntl.h> +#endif + +/* + * This maze of checks controls defines or not the + * target system has BSD-style typdedefs declared in + * an include file and/or whether or not to include + * <unistd.h> to get the SEEK_* definitions. Some + * additional includes are also done to pull in the + * appropriate definitions we're looking for. + */ +#if defined(__MWERKS__) || defined(THINK_C) || defined(__PPCC__) || defined(__SC__) || defined(__MRC__) +#include <stdlib.h> +#define BSDTYPES +#define HAVE_UNISTD_H 0 +#elif (defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) || defined(_WIN32)) && !defined(unix) + // If MINGW has already typedefed u_char, u_short, u_int and u_long in their + // winsock2.h, they also defined _BSDTYPES_DEFINED... + #if !defined(__MINGW32__) || !defined(_BSDTYPES_DEFINED) + #define BSDTYPES + #endif +#elif defined(OS2_16) || defined(OS2_32) +#define BSDTYPES +#elif defined(__acornriscos) +#include <stdlib.h> +#define BSDTYPES +#define HAVE_UNISTD_H 0 +#elif defined(VMS) +#define HAVE_UNISTD_H 0 +#else +#define HAVE_UNISTD_H 1 +#endif + +/* + * The library uses the ANSI C/POSIX SEEK_* + * definitions that should be defined in unistd.h + * (except on system where they are in stdio.h and + * there is no unistd.h). + */ +#if !defined(SEEK_SET) && HAVE_UNISTD_H +#include <unistd.h> +#endif + +/* + * The library uses memset, memcpy, and memcmp. + * ANSI C and System V define these in string.h. + */ +#include <string.h> + +/* + * The BSD typedefs are used throughout the library. + * If your system doesn't have them in <sys/types.h>, + * then define BSDTYPES in your Makefile. + */ +#if defined(BSDTYPES) +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +#endif + +/* + * dblparam_t is the type that a double precision + * floating point value will have on the parameter + * stack (when coerced by the compiler). + */ +/* Note: on MacPowerPC "extended" is undefined. So only use it for 68K-Macs */ +#if defined(__SC__) || defined(THINK_C) +typedef extended dblparam_t; +#else +typedef double dblparam_t; +#endif + +/* + * If your compiler supports inline functions, then + * set INLINE appropriately to get the known hotspots + * in the library expanded inline. + */ +#if defined(__GNUC__) +#if defined(__STRICT_ANSI__) +#define INLINE __inline__ +#else +#define INLINE inline +#endif +#else /* !__GNUC__ */ +#define INLINE +#endif + +/* + * GLOBALDATA is a macro that is used to define global variables + * private to the library. We use this indirection to hide + * brain-damage in VAXC (and GCC) under VAX/VMS. In these + * environments the macro places the variable in a non-shareable + * program section, which ought to be done by default (sigh!) + * + * Apparently DEC are aware of the problem as this behaviour is the + * default under VMS on AXP. + * + * The GNU C variant is untested. + */ +#if defined(VAX) && defined(VMS) +#if defined(VAXC) +#define GLOBALDATA(TYPE,NAME) extern noshare TYPE NAME +#endif +#if defined(__GNUC__) +#define GLOBALDATA(TYPE,NAME) extern TYPE NAME \ + asm("_$$PsectAttributes_NOSHR$$" #NAME) +#endif +#else /* !VAX/VMS */ +#define GLOBALDATA(TYPE,NAME) extern TYPE NAME +#endif + +#if defined(__acornriscos) +/* + * osfcn.h is part of C++Lib on Acorn C/C++, and as such can't be used + * on C alone. For that reason, the relevant functions are + * implemented in tif_acorn.c, and the elements from the header + * file are included here. + */ +#if defined(__cplusplus) +#include <osfcn.h> +#else +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#define O_APPEND 8 +#define O_CREAT 0x200 +#define O_TRUNC 0x400 +typedef long off_t; +extern int open(const char *name, int flags, int mode); +extern int close(int fd); +extern int write(int fd, const char *buf, int nbytes); +extern int read(int fd, char *buf, int nbytes); +extern off_t lseek(int fd, off_t offset, int whence); +extern int creat(const char *path, int mode); +#endif /* __cplusplus */ +#endif /* __acornriscos */ + +/* Bit and byte order, the default is MSB to LSB */ +#ifdef VMS +#undef HOST_FILLORDER +#undef HOST_BIGENDIAN +#define HOST_FILLORDER FILLORDER_LSB2MSB +#define HOST_BIGENDIAN 0 +#endif + + +#endif /* _COMPAT_ */ diff --git a/Utilities/vtktiff/tiffconf.h b/Utilities/vtktiff/tiffconf.h new file mode 100644 index 0000000..b411e8a --- /dev/null +++ b/Utilities/vtktiff/tiffconf.h @@ -0,0 +1,162 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tiffconf.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ +/* + * Library Configuration Definitions. + * + * This file defines the default configuration for the library. + * If the target system does not have make or a way to specify + * #defines on the command line, this file can be edited to + * configure the library. Otherwise, one can override portability + * and configuration-related definitions from a Makefile or command + * line by defining FEATURE_SUPPORT and COMPRESSION_SUPPORT (see below). + */ + +/* + * General portability-related defines: + * + * HAVE_IEEEFP define as 0 or 1 according to the floating point + * format suported by the machine + * BSDTYPES define this if your system does NOT define the + * usual 4BSD typedefs u_int et. al. + * HAVE_MMAP enable support for memory mapping read-only files; + * this is typically deduced by the configure script + * HOST_FILLORDER native cpu bit order: one of FILLORDER_MSB2LSB + * or FILLODER_LSB2MSB; this is typically set by the + * configure script + * HOST_BIGENDIAN native cpu byte order: 1 if big-endian (Motorola) + * or 0 if little-endian (Intel); this may be used + * in codecs to optimize code + * USE_64BIT_API set to 1 if tif_unix.c should use lseek64(), + * fstat64() and stat64 allowing 2-4GB files. + */ +#ifndef HAVE_IEEEFP +#define HAVE_IEEEFP 1 +#endif +#ifndef HOST_FILLORDER +#define HOST_FILLORDER FILLORDER_MSB2LSB +#endif +#ifndef HOST_BIGENDIAN +#define HOST_BIGENDIAN 1 +#endif + +#ifndef USE_64BIT_API +# define USE_64BIT_API 0 +#endif + +#ifndef FEATURE_SUPPORT +/* + * Feature support definitions: + * + * COLORIMETRY_SUPPORT enable support for 6.0 colorimetry tags + * YCBCR_SUPPORT enable support for 6.0 YCbCr tags + * CMYK_SUPPORT enable support for 6.0 CMYK tags + * ICC_SUPPORT enable support for ICC profile tag + * PHOTOSHOP_SUPPORT enable support for PHOTOSHOP resource tag + * IPTC_SUPPORT enable support for RichTIFF IPTC tag + */ +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT +#endif /* FEATURE_SUPPORT */ + +#ifndef COMPRESSION_SUPPORT +/* + * Compression support defines: + * + * CCITT_SUPPORT enable support for CCITT Group 3 & 4 algorithms + * PACKBITS_SUPPORT enable support for Macintosh PackBits algorithm + * LZW_SUPPORT enable support for LZW algorithm + * THUNDER_SUPPORT enable support for ThunderScan 4-bit RLE algorithm + * NEXT_SUPPORT enable support for NeXT 2-bit RLE algorithm + * OJPEG_SUPPORT enable support for 6.0-style JPEG DCT algorithms + * (requires IJG software) + * JPEG_SUPPORT enable support for post-6.0-style JPEG DCT algorithms + * (requires freely available IJG software, see tif_jpeg.c) + * ZIP_SUPPORT enable support for Deflate algorithm + * (requires freely available zlib software, see tif_zip.c) + * PIXARLOG_SUPPORT enable support for Pixar log-format algorithm + * LOGLUV_SUPPORT enable support for LogLuv high dynamic range encoding + */ +#define CCITT_SUPPORT +#define PACKBITS_SUPPORT +#define LZW_SUPPORT +#define THUNDER_SUPPORT +#define NEXT_SUPPORT +#define LOGLUV_SUPPORT +#endif /* COMPRESSION_SUPPORT */ + +/* + * If JPEG compression is enabled then we must also include + * support for the colorimetry and YCbCr-related tags. + */ +#ifdef JPEG_SUPPORT +#ifndef YCBCR_SUPPORT +#define YCBCR_SUPPORT +#endif +#ifndef COLORIMETRY_SUPPORT +#define COLORIMETRY_SUPPORT +#endif +#endif /* JPEG_SUPPORT */ + +/* + * ``Orthogonal Features'' + * + * STRIPCHOP_DEFAULT default handling of strip chopping support (whether + * or not to convert single-strip uncompressed images + * to mutiple strips of ~8Kb--to reduce memory use) + * SUBIFD_SUPPORT enable support for SubIFD tag (thumbnails and such) + */ +#ifndef STRIPCHOP_DEFAULT +#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP /* default is to enable */ +#endif +#ifndef SUBIFD_SUPPORT +#define SUBIFD_SUPPORT 1 /* enable SubIFD tag (330) support */ +#endif + +#if defined ( _MSC_VER ) +#pragma warning ( disable : 4057 ) +#pragma warning ( disable : 4100 ) +#pragma warning ( disable : 4115 ) +#pragma warning ( disable : 4127 ) +#pragma warning ( disable : 4189 ) +#pragma warning ( disable : 4244 ) +#pragma warning ( disable : 4251 ) +#pragma warning ( disable : 4267 ) +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4309 ) +#pragma warning ( disable : 4505 ) +#pragma warning ( disable : 4706 ) +#pragma warning ( disable : 4786 ) +#pragma warning ( disable : 4311 ) +#pragma warning ( disable : 4312 ) +#endif + +#endif /* _TIFFCONF_ */ diff --git a/Utilities/vtktiff/tiffio.h b/Utilities/vtktiff/tiffio.h new file mode 100644 index 0000000..039f8bb --- /dev/null +++ b/Utilities/vtktiff/tiffio.h @@ -0,0 +1,367 @@ +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tiffio.h,v 1.5 2005/02/28 18:49:39 malaterre Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIO_ +#define _TIFFIO_ + +/* + * TIFF I/O Library Definitions. + */ +#include "tiff.h" +#include "tiffvers.h" + +/* + * TIFF is defined as an incomplete type to hide the + * library's internal data structures from clients. + */ +typedef struct tiff TIFF; + +/* + * The following typedefs define the intrinsic size of + * data types used in the *exported* interfaces. These + * definitions depend on the proper definition of types + * in tiff.h. Note also that the varargs interface used + * to pass tag types and values uses the types defined in + * tiff.h directly. + * + * NB: ttag_t is unsigned int and not unsigned short because + * ANSI C requires that the type before the ellipsis be a + * promoted type (i.e. one of int, unsigned int, pointer, + * or double) and because we defined pseudo-tags that are + * outside the range of legal Aldus-assigned tags. + * NB: tsize_t is int32 and not uint32 because some functions + * return -1. + * NB: toff_t is not off_t for many reasons; TIFFs max out at + * 32-bit file offsets being the most important, and to ensure + * that it is unsigned, rather than signed. + */ +typedef uint32 ttag_t; /* directory tag */ +typedef uint16 tdir_t; /* directory index */ +typedef uint16 tsample_t; /* sample number */ +typedef uint32 tstrip_t; /* strip number */ +typedef uint32 ttile_t; /* tile number */ +typedef int32 tsize_t; /* i/o size in bytes */ +typedef void* tdata_t; /* image data ref */ +typedef uint32 toff_t; /* file offset */ + +#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32)) +#define __WIN32__ +#endif + +/* + * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c + * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c). + * + * By default tif_win32.c is assumed on windows if not using the cygwin + * environment. + */ + +#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) +# if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && !defined(USE_WIN32_FILIO) +# define USE_WIN32_FILEIO +# endif +#endif + +#include "tconf.h" + +#if defined(USE_WIN32_FILEIO) +#include <windows.h> +#ifdef __WIN32__ +DECLARE_HANDLE(thandle_t); /* Win32 file handle */ +#else +typedef HFILE thandle_t; /* client data handle */ +#endif +#else +typedef void* thandle_t; /* client data handle */ +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/* + * Flags to pass to TIFFPrintDirectory to control + * printing of data structures that are potentially + * very large. Bit-or these flags to enable printing + * multiple items. + */ +#define TIFFPRINT_NONE 0x0 /* no extra info */ +#define TIFFPRINT_STRIPS 0x1 /* strips/tiles info */ +#define TIFFPRINT_CURVES 0x2 /* color/gray response curves */ +#define TIFFPRINT_COLORMAP 0x4 /* colormap */ +#define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matrices */ +#define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */ +#define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */ + +/* + * RGBA-style image support. + */ +typedef unsigned char TIFFRGBValue; /* 8-bit samples */ +typedef struct _TIFFRGBAImage TIFFRGBAImage; +/* + * The image reading and conversion routines invoke + * ``put routines'' to copy/image/whatever tiles of + * raw image data. A default set of routines are + * provided to convert/copy raw image data to 8-bit + * packed ABGR format rasters. Applications can supply + * alternate routines that unpack the data into a + * different format or, for example, unpack the data + * and draw the unpacked raster on the display. + */ +typedef void (*tileContigRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*); +typedef void (*tileSeparateRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*, unsigned char*, unsigned char*, unsigned char*); +/* + * RGBA-reader state. + */ +typedef struct { /* YCbCr->RGB support */ + TIFFRGBValue* clamptab; /* range clamping table */ + int* Cr_r_tab; + int* Cb_b_tab; + int32* Cr_g_tab; + int32* Cb_g_tab; + float coeffs[3]; /* cached for repeated use */ +} TIFFYCbCrToRGB; + +struct _TIFFRGBAImage { + TIFF* tif; /* image handle */ + int stoponerr; /* stop on read error */ + int isContig; /* data is packed/separate */ + int alpha; /* type of alpha data present */ + uint32 width; /* image width */ + uint32 height; /* image height */ + uint16 bitspersample; /* image bits/sample */ + uint16 samplesperpixel; /* image samples/pixel */ + uint16 orientation; /* image orientation */ + uint16 photometric; /* image photometric interp */ + uint16* redcmap; /* colormap pallete */ + uint16* greencmap; + uint16* bluecmap; + /* get image data routine */ + int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32); + union { + void (*any)(TIFFRGBAImage*); + tileContigRoutine contig; + tileSeparateRoutine separate; + } put; /* put decoded strip/tile */ + TIFFRGBValue* Map; /* sample mapping array */ + uint32** BWmap; /* black&white map */ + uint32** PALmap; /* palette image map */ + TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ + + int row_offset; + int col_offset; +}; + +/* + * Macros for extracting components from the + * packed ABGR form returned by TIFFReadRGBAImage. + */ +#define TIFFGetR(abgr) ((abgr) & 0xff) +#define TIFFGetG(abgr) (((abgr) >> 8) & 0xff) +#define TIFFGetB(abgr) (((abgr) >> 16) & 0xff) +#define TIFFGetA(abgr) (((abgr) >> 24) & 0xff) + +/* + * A CODEC is a software package that implements decoding, + * encoding, or decoding+encoding of a compression algorithm. + * The library provides a collection of builtin codecs. + * More codecs may be registered through calls to the library + * and/or the builtin implementations may be overridden. + */ +typedef int (*TIFFInitMethod)(TIFF*, int); +typedef struct { + char* name; + uint16 scheme; + TIFFInitMethod init; +} TIFFCodec; + +#include <stdio.h> +#include <stdarg.h> + +/* share internal LogLuv conversion routines? */ +#ifndef LOGLUV_PUBLIC +#define LOGLUV_PUBLIC 1 +#endif + +#if defined(__cplusplus) +extern "C" { +#endif +typedef void (*TIFFErrorHandler)(const char*, const char*, va_list); +typedef tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t); +typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int); +typedef int (*TIFFCloseProc)(thandle_t); +typedef toff_t (*TIFFSizeProc)(thandle_t); +typedef int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*); +typedef void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t); +typedef void (*TIFFExtendProc)(TIFF*); + +extern const char* TIFFGetVersion(void); + +extern const TIFFCodec* TIFFFindCODEC(uint16); +extern TIFFCodec* TIFFRegisterCODEC(uint16, const char*, TIFFInitMethod); +extern void TIFFUnRegisterCODEC(TIFFCodec*); + +TEXTERN tdata_t TEXPORT _TIFFmalloc(tsize_t); +extern tdata_t _TIFFrealloc(tdata_t, tsize_t); +extern void _TIFFmemset(tdata_t, int, tsize_t); +extern void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t); +extern int _TIFFmemcmp(const tdata_t, const tdata_t, tsize_t); +TEXTERN void TEXPORT _TIFFfree(tdata_t); + +TEXTERN void TEXPORT TIFFClose(TIFF*); +extern int TIFFFlush(TIFF*); +extern int TIFFFlushData(TIFF*); +TEXTERN int TEXPORT TIFFGetField(TIFF*, ttag_t, ...); +extern int TIFFVGetField(TIFF*, ttag_t, va_list); +extern int TIFFGetFieldDefaulted(TIFF*, ttag_t, ...); +extern int TIFFVGetFieldDefaulted(TIFF*, ttag_t, va_list); +extern int TIFFReadDirectory(TIFF*); +TEXTERN tsize_t TEXPORT TIFFScanlineSize(TIFF*); +extern tsize_t TIFFRasterScanlineSize(TIFF*); +extern tsize_t TIFFStripSize(TIFF*); +extern tsize_t TIFFVStripSize(TIFF*, uint32); +extern tsize_t TIFFTileRowSize(TIFF*); +TEXTERN tsize_t TEXPORT TIFFTileSize(TIFF*); +extern tsize_t TIFFVTileSize(TIFF*, uint32); +TEXTERN uint32 TEXPORT TIFFDefaultStripSize(TIFF*, uint32); +extern void TIFFDefaultTileSize(TIFF*, uint32*, uint32*); +extern int TIFFFileno(TIFF*); +extern int TIFFGetMode(TIFF*); +TEXTERN int TEXPORT TIFFIsTiled(TIFF*); +extern int TIFFIsByteSwapped(TIFF*); +extern int TIFFIsUpSampled(TIFF*); +extern int TIFFIsMSB2LSB(TIFF*); +extern uint32 TIFFCurrentRow(TIFF*); +extern tdir_t TIFFCurrentDirectory(TIFF*); +extern tdir_t TIFFNumberOfDirectories(TIFF*); +extern uint32 TIFFCurrentDirOffset(TIFF*); +extern tstrip_t TIFFCurrentStrip(TIFF*); +extern ttile_t TIFFCurrentTile(TIFF*); +extern int TIFFReadBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFWriteBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFWriteCheck(TIFF*, int, const char *); +extern int TIFFCreateDirectory(TIFF*); +extern int TIFFLastDirectory(TIFF*); +extern int TIFFSetDirectory(TIFF*, tdir_t); +extern int TIFFSetSubDirectory(TIFF*, uint32); +extern int TIFFUnlinkDirectory(TIFF*, tdir_t); +TEXTERN int TEXPORT TIFFSetField(TIFF*, ttag_t, ...); +extern int TIFFVSetField(TIFF*, ttag_t, va_list); +extern int TIFFWriteDirectory(TIFF *); +extern int TIFFRewriteDirectory(TIFF *); +extern int TIFFReassignTagToIgnore(enum TIFFIgnoreSense, int); + +#if defined(c_plusplus) || defined(__cplusplus) +TEXTERN void TEXPORT TIFFPrintDirectory(TIFF*, FILE*, long = 0); +TEXTERN int TEXPORT TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +TEXTERN int TEXPORT TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +TEXTERN int TEXPORT TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int = 0); +#else +TEXTERN void TEXPORT TIFFPrintDirectory(TIFF*, FILE*, long); +TEXTERN int TEXPORT TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t); +TEXTERN int TEXPORT TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t); +TEXTERN int TEXPORT TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int); +#endif + +extern int TIFFReadRGBAStrip(TIFF*, tstrip_t, uint32 * ); +extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * ); +extern int TIFFRGBAImageOK(TIFF*, char [1024]); +extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]); +extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32); +extern void TIFFRGBAImageEnd(TIFFRGBAImage*); +TEXTERN TIFF* TEXPORT TIFFOpen(const char*, const char*); +extern TIFF* TIFFFdOpen(int, const char*, const char*); +TEXTERN TIFF* TEXPORT TIFFClientOpen(const char*, const char*, + thandle_t, + TIFFReadWriteProc, TIFFReadWriteProc, + TIFFSeekProc, TIFFCloseProc, + TIFFSizeProc, + TIFFMapFileProc, TIFFUnmapFileProc); +extern const char* TIFFFileName(TIFF*); +extern void TIFFError(const char*, const char*, ...); +extern void TIFFWarning(const char*, const char*, ...); +TEXTERN TIFFErrorHandler TEXPORT TIFFSetErrorHandler(TIFFErrorHandler); +TEXTERN TIFFErrorHandler TEXPORT TIFFSetWarningHandler(TIFFErrorHandler); +extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc); +extern ttile_t TIFFComputeTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern int TIFFCheckTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern ttile_t TIFFNumberOfTiles(TIFF*); +TEXTERN tsize_t TEXPORT TIFFReadTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tsize_t TIFFWriteTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tstrip_t TIFFComputeStrip(TIFF*, uint32, tsample_t); +extern tstrip_t TIFFNumberOfStrips(TIFF*); +extern tsize_t TIFFReadEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern void TIFFSetWriteOffset(TIFF*, toff_t); +extern void TIFFSwabShort(uint16*); +extern void TIFFSwabLong(uint32*); +extern void TIFFSwabDouble(double*); +extern void TIFFSwabArrayOfShort(uint16*, unsigned long); +extern void TIFFSwabArrayOfLong(uint32*, unsigned long); +extern void TIFFSwabArrayOfDouble(double*, unsigned long); +extern void TIFFReverseBits(unsigned char *, unsigned long); +extern const unsigned char* TIFFGetBitRevTable(int); + +#ifdef LOGLUV_PUBLIC +#define U_NEU 0.210526316 +#define V_NEU 0.473684211 +#define UVSCALE 410. +extern double LogL16toY(int); +extern double LogL10toY(int); +extern void XYZtoRGB24(float*, uint8*); +extern int uv_decode(double*, double*, int); +extern void LogLuv24toXYZ(uint32, float*); +extern void LogLuv32toXYZ(uint32, float*); +#if defined(c_plusplus) || defined(__cplusplus) +extern int LogL16fromY(double, int = SGILOGENCODE_NODITHER); +extern int LogL10fromY(double, int = SGILOGENCODE_NODITHER); +extern int uv_encode(double, double, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv24fromXYZ(float*, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv32fromXYZ(float*, int = SGILOGENCODE_NODITHER); +#else +extern int LogL16fromY(double, int); +extern int LogL10fromY(double, int); +extern int uv_encode(double, double, int); +extern uint32 LogLuv24fromXYZ(float*, int); +extern uint32 LogLuv32fromXYZ(float*, int); +#endif +#endif /* LOGLUV_PUBLIC */ +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFIO_ */ diff --git a/Utilities/vtktiff/tiffiop.h b/Utilities/vtktiff/tiffiop.h new file mode 100644 index 0000000..7f47b9a --- /dev/null +++ b/Utilities/vtktiff/tiffiop.h @@ -0,0 +1,280 @@ +#include "vtk_tiff_mangle.h" +/* $Header: /cvsroot/VTK/VTK/Utilities/vtktiff/tiffiop.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIOP_ +#define _TIFFIOP_ +/* + * ``Library-private'' definitions. + */ +/* + * UNIX systems should run the configure script to generate + * a port.h file that reflects the system capabilities. + * Doing this obviates all the dreck done in tiffcomp.h. + */ +#if defined(unix) || defined(__unix) +#include "port.h" +#include "tiffconf.h" +#else +#include "tiffconf.h" +#include "tiffcomp.h" +#endif +#include "tiffio.h" +#include "tif_dir.h" + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/* + * Typedefs for ``method pointers'' used internally. + */ +typedef unsigned char tidataval_t; /* internal image data value type */ +typedef tidataval_t* tidata_t; /* reference to internal image data */ + +typedef void (*TIFFVoidMethod)(TIFF*); +typedef int (*TIFFBoolMethod)(TIFF*); +typedef int (*TIFFPreMethod)(TIFF*, tsample_t); +typedef int (*TIFFCodeMethod)(TIFF*, tidata_t, tsize_t, tsample_t); +typedef int (*TIFFSeekMethod)(TIFF*, uint32); +typedef void (*TIFFPostMethod)(TIFF*, tidata_t, tsize_t); +typedef int (*TIFFVSetMethod)(TIFF*, ttag_t, va_list); +typedef int (*TIFFVGetMethod)(TIFF*, ttag_t, va_list); +typedef void (*TIFFPrintMethod)(TIFF*, FILE*, long); +typedef uint32 (*TIFFStripMethod)(TIFF*, uint32); +typedef void (*TIFFTileMethod)(TIFF*, uint32*, uint32*); + +struct tiff { + char* tif_name; /* name of open file */ + int tif_fd; /* open file descriptor */ + int tif_mode; /* open mode (O_*) */ + uint32 tif_flags; +#define TIFF_FILLORDER 0x0003 /* natural bit fill order for machine */ +#define TIFF_DIRTYHEADER 0x0004 /* header must be written on close */ +#define TIFF_DIRTYDIRECT 0x0008 /* current directory must be written */ +#define TIFF_BUFFERSETUP 0x0010 /* data buffers setup */ +#define TIFF_CODERSETUP 0x0020 /* encoder/decoder setup done */ +#define TIFF_BEENWRITING 0x0040 /* written 1+ scanlines to file */ +#define TIFF_SWAB 0x0080 /* byte swap file information */ +#define TIFF_NOBITREV 0x0100 /* inhibit bit reversal logic */ +#define TIFF_MYBUFFER 0x0200 /* my raw data buffer; free on close */ +#define TIFF_ISTILED 0x0400 /* file is tile, not strip- based */ +#define TIFF_MAPPED 0x0800 /* file is mapped into memory */ +#define TIFF_POSTENCODE 0x1000 /* need call to postencode routine */ +#define TIFF_INSUBIFD 0x2000 /* currently writing a subifd */ +#define TIFF_UPSAMPLED 0x4000 /* library is doing data up-sampling */ +#define TIFF_STRIPCHOP 0x8000 /* enable strip chopping support */ + toff_t tif_diroff; /* file offset of current directory */ + toff_t tif_nextdiroff; /* file offset of following directory */ + TIFFDirectory tif_dir; /* internal rep of current directory */ + TIFFHeader tif_header; /* file's header block */ + tidata_t tif_clientdir; /* client TIFF directory */ + const int* tif_typeshift; /* data type shift counts */ + const unsigned long* tif_typemask; /* data type masks */ + uint32 tif_row; /* current scanline */ + tdir_t tif_curdir; /* current directory (index) */ + tstrip_t tif_curstrip; /* current strip for read/write */ + toff_t tif_curoff; /* current offset for read/write */ + toff_t tif_dataoff; /* current offset for writing dir */ +#if SUBIFD_SUPPORT + uint16 tif_nsubifd; /* remaining subifds to write */ + toff_t tif_subifdoff; /* offset for patching SubIFD link */ +#endif +/* tiling support */ + uint32 tif_col; /* current column (offset by row too) */ + ttile_t tif_curtile; /* current tile for read/write */ + tsize_t tif_tilesize; /* # of bytes in a tile */ +/* compression scheme hooks */ + TIFFBoolMethod tif_setupdecode;/* called once before predecode */ + TIFFPreMethod tif_predecode; /* pre- row/strip/tile decoding */ + TIFFBoolMethod tif_setupencode;/* called once before preencode */ + TIFFPreMethod tif_preencode; /* pre- row/strip/tile encoding */ + TIFFBoolMethod tif_postencode; /* post- row/strip/tile encoding */ + TIFFCodeMethod tif_decoderow; /* scanline decoding routine */ + TIFFCodeMethod tif_encoderow; /* scanline encoding routine */ + TIFFCodeMethod tif_decodestrip;/* strip decoding routine */ + TIFFCodeMethod tif_encodestrip;/* strip encoding routine */ + TIFFCodeMethod tif_decodetile; /* tile decoding routine */ + TIFFCodeMethod tif_encodetile; /* tile encoding routine */ + TIFFVoidMethod tif_close; /* cleanup-on-close routine */ + TIFFSeekMethod tif_seek; /* position within a strip routine */ + TIFFVoidMethod tif_cleanup; /* cleanup state routine */ + TIFFStripMethod tif_defstripsize;/* calculate/constrain strip size */ + TIFFTileMethod tif_deftilesize;/* calculate/constrain tile size */ + tidata_t tif_data; /* compression scheme private data */ +/* input/output buffering */ + tsize_t tif_scanlinesize;/* # of bytes in a scanline */ + tsize_t tif_scanlineskew;/* scanline skew for reading strips */ + tidata_t tif_rawdata; /* raw data buffer */ + tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */ + tidata_t tif_rawcp; /* current spot in raw buffer */ + tsize_t tif_rawcc; /* bytes unread from raw buffer */ +/* memory-mapped file support */ + tidata_t tif_base; /* base of mapped file */ + toff_t tif_size; /* size of mapped file region (bytes) */ + TIFFMapFileProc tif_mapproc; /* map file method */ + TIFFUnmapFileProc tif_unmapproc;/* unmap file method */ +/* input/output callback methods */ + thandle_t tif_clientdata; /* callback parameter */ + TIFFReadWriteProc tif_readproc; /* read method */ + TIFFReadWriteProc tif_writeproc;/* write method */ + TIFFSeekProc tif_seekproc; /* lseek method */ + TIFFCloseProc tif_closeproc; /* close method */ + TIFFSizeProc tif_sizeproc; /* filesize method */ +/* post-decoding support */ + TIFFPostMethod tif_postdecode; /* post decoding routine */ +/* tag support */ + TIFFFieldInfo** tif_fieldinfo; /* sorted table of registered tags */ + int tif_nfields; /* # entries in registered tag table */ + TIFFVSetMethod tif_vsetfield; /* tag set routine */ + TIFFVGetMethod tif_vgetfield; /* tag get routine */ + TIFFPrintMethod tif_printdir; /* directory print routine */ +}; + +#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */ + +#define isTiled(tif) (((tif)->tif_flags & TIFF_ISTILED) != 0) +#define isMapped(tif) (((tif)->tif_flags & TIFF_MAPPED) != 0) +#define isFillOrder(tif, o) (((tif)->tif_flags & (o)) != 0) +#define isUpSampled(tif) (((tif)->tif_flags & TIFF_UPSAMPLED) != 0) +#define TIFFReadFile(tif, buf, size) \ + ((*(tif)->tif_readproc)((tif)->tif_clientdata,buf,size)) +#define TIFFWriteFile(tif, buf, size) \ + ((*(tif)->tif_writeproc)((tif)->tif_clientdata,buf,size)) +#define TIFFSeekFile(tif, off, whence) \ + ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(toff_t)(off),whence)) +#define TIFFCloseFile(tif) \ + ((*(tif)->tif_closeproc)((tif)->tif_clientdata)) +#define TIFFGetFileSize(tif) \ + ((*(tif)->tif_sizeproc)((tif)->tif_clientdata)) +#define TIFFMapFileContents(tif, paddr, psize) \ + ((*(tif)->tif_mapproc)((tif)->tif_clientdata,paddr,psize)) +#define TIFFUnmapFileContents(tif, addr, size) \ + ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,addr,size)) + +/* + * Default Read/Seek/Write definitions. + */ +#ifndef ReadOK +#define ReadOK(tif, buf, size) \ + (TIFFReadFile(tif, (tdata_t) buf, (tsize_t)(size)) == (tsize_t)(size)) +#endif +#ifndef SeekOK +#define SeekOK(tif, off) \ + (TIFFSeekFile(tif, (toff_t) off, SEEK_SET) == (toff_t) off) +#endif +#ifndef WriteOK +#define WriteOK(tif, buf, size) \ + (TIFFWriteFile(tif, (tdata_t) buf, (tsize_t) size) == (tsize_t) size) +#endif + +/* NB: the uint32 casts are to silence certain ANSI-C compilers */ +#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) +#define TIFFroundup(x, y) (TIFFhowmany(x,y)*((uint32)(y))) + +#if defined(__cplusplus) +extern "C" { +#endif +extern int _TIFFgetMode(const char*, const char*); +extern int _TIFFNoRowEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoStripEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoTileEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoRowDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoStripDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoTileDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern void _TIFFNoPostDecode(TIFF*, tidata_t, tsize_t); +extern int _TIFFNoPreCode (TIFF*, tsample_t); +extern int _TIFFNoSeek(TIFF*, uint32); +extern void _TIFFSwab16BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab32BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab64BitData(TIFF*, tidata_t, tsize_t); +extern int TIFFFlushData1(TIFF*); +extern void TIFFFreeDirectory(TIFF*); +extern int TIFFDefaultDirectory(TIFF*); +extern int TIFFSetCompressionScheme(TIFF*, int); +extern int TIFFSetDefaultCompressionState(TIFF*); +extern uint32 _TIFFDefaultStripSize(TIFF*, uint32); +extern void _TIFFDefaultTileSize(TIFF*, uint32*, uint32*); + +extern void _TIFFsetByteArray(void**, void*, long); +extern void _TIFFsetString(char**, char*); +extern void _TIFFsetShortArray(uint16**, uint16*, long); +extern void _TIFFsetLongArray(uint32**, uint32*, long); +extern void _TIFFsetFloatArray(float**, float*, long); +extern void _TIFFsetDoubleArray(double**, double*, long); + +extern void _TIFFprintAscii(FILE*, const char*); +extern void _TIFFprintAsciiTag(FILE*, const char*, const char*); + +GLOBALDATA(TIFFErrorHandler,_TIFFwarningHandler); +GLOBALDATA(TIFFErrorHandler,_TIFFerrorHandler); + +extern int TIFFInitDumpMode(TIFF*, int); +#ifdef PACKBITS_SUPPORT +extern int TIFFInitPackBits(TIFF*, int); +#endif +#ifdef CCITT_SUPPORT +extern int TIFFInitCCITTRLE(TIFF*, int), TIFFInitCCITTRLEW(TIFF*, int); +extern int TIFFInitCCITTFax3(TIFF*, int), TIFFInitCCITTFax4(TIFF*, int); +#endif +#ifdef THUNDER_SUPPORT +extern int TIFFInitThunderScan(TIFF*, int); +#endif +#ifdef NEXT_SUPPORT +extern int TIFFInitNeXT(TIFF*, int); +#endif +#ifdef LZW_SUPPORT +extern int TIFFInitLZW(TIFF*, int); +#endif +#ifdef OJPEG_SUPPORT +extern int TIFFInitOJPEG(TIFF*, int); +#endif +#ifdef JPEG_SUPPORT +extern int TIFFInitJPEG(TIFF*, int); +#endif +#ifdef JBIG_SUPPORT +extern int TIFFInitJBIG(TIFF*, int); +#endif +#ifdef ZIP_SUPPORT +extern int TIFFInitZIP(TIFF*, int); +#endif +#ifdef PIXARLOG_SUPPORT +extern int TIFFInitPixarLog(TIFF*, int); +#endif +#ifdef LOGLUV_SUPPORT +extern int TIFFInitSGILog(TIFF*, int); +#endif +#ifdef VMS +extern const TIFFCodec _TIFFBuiltinCODECS[]; +#else +extern TIFFCodec _TIFFBuiltinCODECS[]; +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFIOP_ */ diff --git a/Utilities/vtktiff/tiffvers.h b/Utilities/vtktiff/tiffvers.h new file mode 100644 index 0000000..db3f83a --- /dev/null +++ b/Utilities/vtktiff/tiffvers.h @@ -0,0 +1,9 @@ +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.5.7\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +/* + * This define can be used in code that requires + * compilation-related definitions specific to a + * version or versions of the library. Runtime + * version checking should be done based on the + * string returned by TIFFGetVersion. + */ +#define TIFFLIB_VERSION 20011128 diff --git a/Utilities/vtktiff/uvcode.h b/Utilities/vtktiff/uvcode.h new file mode 100644 index 0000000..9866ca3 --- /dev/null +++ b/Utilities/vtktiff/uvcode.h @@ -0,0 +1,173 @@ +/* Version 1.0 generated April 7, 1997 by Greg Ward Larson, SGI */ +#define UV_SQSIZ (float)0.003500 +#define UV_NDIVS 16289 +#define UV_VSTART (float)0.016940 +#define UV_NVS 163 +static struct { + float ustart; + short nus, ncum; +} uv_row[UV_NVS] = { + { (float)0.247663, 4, 0 }, + { (float)0.243779, 6, 4 }, + { (float)0.241684, 7, 10 }, + { (float)0.237874, 9, 17 }, + { (float)0.235906, 10, 26 }, + { (float)0.232153, 12, 36 }, + { (float)0.228352, 14, 48 }, + { (float)0.226259, 15, 62 }, + { (float)0.222371, 17, 77 }, + { (float)0.220410, 18, 94 }, + { (float)0.214710, 21, 112 }, + { (float)0.212714, 22, 133 }, + { (float)0.210721, 23, 155 }, + { (float)0.204976, 26, 178 }, + { (float)0.202986, 27, 204 }, + { (float)0.199245, 29, 231 }, + { (float)0.195525, 31, 260 }, + { (float)0.193560, 32, 291 }, + { (float)0.189878, 34, 323 }, + { (float)0.186216, 36, 357 }, + { (float)0.186216, 36, 393 }, + { (float)0.182592, 38, 429 }, + { (float)0.179003, 40, 467 }, + { (float)0.175466, 42, 507 }, + { (float)0.172001, 44, 549 }, + { (float)0.172001, 44, 593 }, + { (float)0.168612, 46, 637 }, + { (float)0.168612, 46, 683 }, + { (float)0.163575, 49, 729 }, + { (float)0.158642, 52, 778 }, + { (float)0.158642, 52, 830 }, + { (float)0.158642, 52, 882 }, + { (float)0.153815, 55, 934 }, + { (float)0.153815, 55, 989 }, + { (float)0.149097, 58, 1044 }, + { (float)0.149097, 58, 1102 }, + { (float)0.142746, 62, 1160 }, + { (float)0.142746, 62, 1222 }, + { (float)0.142746, 62, 1284 }, + { (float)0.138270, 65, 1346 }, + { (float)0.138270, 65, 1411 }, + { (float)0.138270, 65, 1476 }, + { (float)0.132166, 69, 1541 }, + { (float)0.132166, 69, 1610 }, + { (float)0.126204, 73, 1679 }, + { (float)0.126204, 73, 1752 }, + { (float)0.126204, 73, 1825 }, + { (float)0.120381, 77, 1898 }, + { (float)0.120381, 77, 1975 }, + { (float)0.120381, 77, 2052 }, + { (float)0.120381, 77, 2129 }, + { (float)0.112962, 82, 2206 }, + { (float)0.112962, 82, 2288 }, + { (float)0.112962, 82, 2370 }, + { (float)0.107450, 86, 2452 }, + { (float)0.107450, 86, 2538 }, + { (float)0.107450, 86, 2624 }, + { (float)0.107450, 86, 2710 }, + { (float)0.100343, 91, 2796 }, + { (float)0.100343, 91, 2887 }, + { (float)0.100343, 91, 2978 }, + { (float)0.095126, 95, 3069 }, + { (float)0.095126, 95, 3164 }, + { (float)0.095126, 95, 3259 }, + { (float)0.095126, 95, 3354 }, + { (float)0.088276, 100, 3449 }, + { (float)0.088276, 100, 3549 }, + { (float)0.088276, 100, 3649 }, + { (float)0.088276, 100, 3749 }, + { (float)0.081523, 105, 3849 }, + { (float)0.081523, 105, 3954 }, + { (float)0.081523, 105, 4059 }, + { (float)0.081523, 105, 4164 }, + { (float)0.074861, 110, 4269 }, + { (float)0.074861, 110, 4379 }, + { (float)0.074861, 110, 4489 }, + { (float)0.074861, 110, 4599 }, + { (float)0.068290, 115, 4709 }, + { (float)0.068290, 115, 4824 }, + { (float)0.068290, 115, 4939 }, + { (float)0.068290, 115, 5054 }, + { (float)0.063573, 119, 5169 }, + { (float)0.063573, 119, 5288 }, + { (float)0.063573, 119, 5407 }, + { (float)0.063573, 119, 5526 }, + { (float)0.057219, 124, 5645 }, + { (float)0.057219, 124, 5769 }, + { (float)0.057219, 124, 5893 }, + { (float)0.057219, 124, 6017 }, + { (float)0.050985, 129, 6141 }, + { (float)0.050985, 129, 6270 }, + { (float)0.050985, 129, 6399 }, + { (float)0.050985, 129, 6528 }, + { (float)0.050985, 129, 6657 }, + { (float)0.044859, 134, 6786 }, + { (float)0.044859, 134, 6920 }, + { (float)0.044859, 134, 7054 }, + { (float)0.044859, 134, 7188 }, + { (float)0.040571, 138, 7322 }, + { (float)0.040571, 138, 7460 }, + { (float)0.040571, 138, 7598 }, + { (float)0.040571, 138, 7736 }, + { (float)0.036339, 142, 7874 }, + { (float)0.036339, 142, 8016 }, + { (float)0.036339, 142, 8158 }, + { (float)0.036339, 142, 8300 }, + { (float)0.032139, 146, 8442 }, + { (float)0.032139, 146, 8588 }, + { (float)0.032139, 146, 8734 }, + { (float)0.032139, 146, 8880 }, + { (float)0.027947, 150, 9026 }, + { (float)0.027947, 150, 9176 }, + { (float)0.027947, 150, 9326 }, + { (float)0.023739, 154, 9476 }, + { (float)0.023739, 154, 9630 }, + { (float)0.023739, 154, 9784 }, + { (float)0.023739, 154, 9938 }, + { (float)0.019504, 158, 10092 }, + { (float)0.019504, 158, 10250 }, + { (float)0.019504, 158, 10408 }, + { (float)0.016976, 161, 10566 }, + { (float)0.016976, 161, 10727 }, + { (float)0.016976, 161, 10888 }, + { (float)0.016976, 161, 11049 }, + { (float)0.012639, 165, 11210 }, + { (float)0.012639, 165, 11375 }, + { (float)0.012639, 165, 11540 }, + { (float)0.009991, 168, 11705 }, + { (float)0.009991, 168, 11873 }, + { (float)0.009991, 168, 12041 }, + { (float)0.009016, 170, 12209 }, + { (float)0.009016, 170, 12379 }, + { (float)0.009016, 170, 12549 }, + { (float)0.006217, 173, 12719 }, + { (float)0.006217, 173, 12892 }, + { (float)0.005097, 175, 13065 }, + { (float)0.005097, 175, 13240 }, + { (float)0.005097, 175, 13415 }, + { (float)0.003909, 177, 13590 }, + { (float)0.003909, 177, 13767 }, + { (float)0.002340, 177, 13944 }, + { (float)0.002389, 170, 14121 }, + { (float)0.001068, 164, 14291 }, + { (float)0.001653, 157, 14455 }, + { (float)0.000717, 150, 14612 }, + { (float)0.001614, 143, 14762 }, + { (float)0.000270, 136, 14905 }, + { (float)0.000484, 129, 15041 }, + { (float)0.001103, 123, 15170 }, + { (float)0.001242, 115, 15293 }, + { (float)0.001188, 109, 15408 }, + { (float)0.001011, 103, 15517 }, + { (float)0.000709, 97, 15620 }, + { (float)0.000301, 89, 15717 }, + { (float)0.002416, 82, 15806 }, + { (float)0.003251, 76, 15888 }, + { (float)0.003246, 69, 15964 }, + { (float)0.004141, 62, 16033 }, + { (float)0.005963, 55, 16095 }, + { (float)0.008839, 47, 16150 }, + { (float)0.010490, 40, 16197 }, + { (float)0.016994, 31, 16237 }, + { (float)0.023659, 21, 16268 }, +}; diff --git a/Utilities/vtktiff/vtk_tiff_mangle.h b/Utilities/vtktiff/vtk_tiff_mangle.h new file mode 100644 index 0000000..f413e3d --- /dev/null +++ b/Utilities/vtktiff/vtk_tiff_mangle.h @@ -0,0 +1,183 @@ +#ifndef vtk_tiff_mangle_h +#define vtk_tiff_mangle_h + +/* + +This header file mangles all symbols exported from the tiff library. +It is included in all files while building the tiff library. Due to +namespace pollution, no tiff headers should be included in .h files in +VTK. + +The following command was used to obtain the symbol list: + +nm libvtktiff.a |grep " [TR] " + +*/ + +#define __TIFFmalloc vtk___TIFFmalloc +#define __TIFFfree vtk___TIFFfree +#define _TIFFerrorHandler vtk__TIFFerrorHandler +#define _TIFFwarningHandler vtk__TIFFwarningHandler +#define tiffDataWidth vtk_tiff_DataWidth +#define LogL10fromY vtk_tiff_LogL10fromY +#define LogL10toY vtk_tiff_LogL10toY +#define LogL16fromY vtk_tiff_LogL16fromY +#define LogL16toY vtk_tiff_LogL16toY +#define LogLuv24fromXYZ vtk_tiff_LogLuv24fromXYZ +#define LogLuv24toXYZ vtk_tiff_LogLuv24toXYZ +#define LogLuv32fromXYZ vtk_tiff_LogLuv32fromXYZ +#define LogLuv32toXYZ vtk_tiff_LogLuv32toXYZ +#define TIFFCheckTile vtk_TIFFCheckTile +#define TIFFClientOpen vtk_TIFFClientOpen +#define TIFFClose vtk_TIFFClose +#define TIFFComputeStrip vtk_TIFFComputeStrip +#define TIFFComputeTile vtk_TIFFComputeTile +#define TIFFCreateDirectory vtk_TIFFCreateDirectory +#define TIFFCurrentDirOffset vtk_TIFFCurrentDirOffset +#define TIFFCurrentDirectory vtk_TIFFCurrentDirectory +#define TIFFCurrentRow vtk_TIFFCurrentRow +#define TIFFCurrentStrip vtk_TIFFCurrentStrip +#define TIFFCurrentTile vtk_TIFFCurrentTile +#define TIFFDefaultDirectory vtk_TIFFDefaultDirectory +#define TIFFDefaultStripSize vtk_TIFFDefaultStripSize +#define TIFFDefaultTileSize vtk_TIFFDefaultTileSize +#define TIFFError vtk_TIFFError +#define TIFFFaxBlackCodes vtk_TIFFFaxBlackCodes +#define TIFFFaxBlackTable vtk_TIFFFaxBlackTable +#define TIFFFaxMainTable vtk_TIFFFaxMainTable +#define TIFFFaxWhiteCodes vtk_TIFFFaxWhiteCodes +#define TIFFFaxWhiteTable vtk_TIFFFaxWhiteTable +#define TIFFFdOpen vtk_TIFFFdOpen +#define TIFFFileName vtk_TIFFFileName +#define TIFFFileno vtk_TIFFFileno +#define TIFFFindCODEC vtk_TIFFFindCODEC +#define TIFFFlush vtk_TIFFFlush +#define TIFFFlushData vtk_TIFFFlushData +#define TIFFFlushData1 vtk_TIFFFlushData1 +#define TIFFFreeDirectory vtk_TIFFFreeDirectory +#define TIFFGetBitRevTable vtk_TIFFGetBitRevTable +#define TIFFGetField vtk_TIFFGetField +#define TIFFGetFieldDefaulted vtk_TIFFGetFieldDefaulted +#define TIFFGetMode vtk_TIFFGetMode +#define TIFFGetVersion vtk_TIFFGetVersion +#define TIFFInitCCITTFax3 vtk_TIFFInitCCITTFax3 +#define TIFFInitCCITTFax4 vtk_TIFFInitCCITTFax4 +#define TIFFInitCCITTRLE vtk_TIFFInitCCITTRLE +#define TIFFInitCCITTRLEW vtk_TIFFInitCCITTRLEW +#define TIFFInitDumpMode vtk_TIFFInitDumpMode +#define TIFFInitJPEG vtk_TIFFInitJPEG +#define TIFFInitLZW vtk_TIFFInitLZW +#define TIFFInitNeXT vtk_TIFFInitNeXT +#define TIFFInitPackBits vtk_TIFFInitPackBits +#define TIFFInitSGILog vtk_TIFFInitSGILog +#define TIFFInitThunderScan vtk_TIFFInitThunderScan +#define TIFFInitZIP vtk_TIFFInitZIP +#define TIFFIsByteSwapped vtk_TIFFIsByteSwapped +#define TIFFIsMSB2LSB vtk_TIFFIsMSB2LSB +#define TIFFIsTiled vtk_TIFFIsTiled +#define TIFFIsUpSampled vtk_TIFFIsUpSampled +#define TIFFLastDirectory vtk_TIFFLastDirectory +#define TIFFNumberOfDirectories vtk_TIFFNumberOfDirectories +#define TIFFNumberOfStrips vtk_TIFFNumberOfStrips +#define TIFFNumberOfTiles vtk_TIFFNumberOfTiles +#define TIFFOpen vtk_TIFFOpen +#define TIFFPredictorInit vtk_TIFFPredictorInit +#define TIFFPrintDirectory vtk_TIFFPrintDirectory +#define TIFFRGBAImageBegin vtk_TIFFRGBAImageBegin +#define TIFFRGBAImageEnd vtk_TIFFRGBAImageEnd +#define TIFFRGBAImageGet vtk_TIFFRGBAImageGet +#define TIFFRGBAImageOK vtk_TIFFRGBAImageOK +#define TIFFRasterScanlineSize vtk_TIFFRasterScanlineSize +#define TIFFReadBufferSetup vtk_TIFFReadBufferSetup +#define TIFFReadDirectory vtk_TIFFReadDirectory +#define TIFFReadEncodedStrip vtk_TIFFReadEncodedStrip +#define TIFFReadEncodedTile vtk_TIFFReadEncodedTile +#define TIFFReadRGBAImage vtk_TIFFReadRGBAImage +#define TIFFReadRGBAStrip vtk_TIFFReadRGBAStrip +#define TIFFReadRGBATile vtk_TIFFReadRGBATile +#define TIFFReadRawStrip vtk_TIFFReadRawStrip +#define TIFFReadRawTile vtk_TIFFReadRawTile +#define TIFFReadScanline vtk_TIFFReadScanline +#define TIFFReadTile vtk_TIFFReadTile +#define TIFFReassignTagToIgnore vtk_TIFFReassignTagToIgnore +#define TIFFRegisterCODEC vtk_TIFFRegisterCODEC +#define TIFFReverseBits vtk_TIFFReverseBits +#define TIFFRewriteDirectory vtk_TIFFRewriteDirectory +#define TIFFScanlineSize vtk_TIFFScanlineSize +#define TIFFSetCompressionScheme vtk_TIFFSetCompressionScheme +#define TIFFSetDirectory vtk_TIFFSetDirectory +#define TIFFSetErrorHandler vtk_TIFFSetErrorHandler +#define TIFFSetField vtk_TIFFSetField +#define TIFFSetSubDirectory vtk_TIFFSetSubDirectory +#define TIFFSetTagExtender vtk_TIFFSetTagExtender +#define TIFFSetWarningHandler vtk_TIFFSetWarningHandler +#define TIFFSetWriteOffset vtk_TIFFSetWriteOffset +#define TIFFStripSize vtk_TIFFStripSize +#define TIFFSwabArrayOfDouble vtk_TIFFSwabArrayOfDouble +#define TIFFSwabArrayOfLong vtk_TIFFSwabArrayOfLong +#define TIFFSwabArrayOfShort vtk_TIFFSwabArrayOfShort +#define TIFFSwabDouble vtk_TIFFSwabDouble +#define TIFFSwabLong vtk_TIFFSwabLong +#define TIFFSwabShort vtk_TIFFSwabShort +#define TIFFTileRowSize vtk_TIFFTileRowSize +#define TIFFTileSize vtk_TIFFTileSize +#define TIFFUnRegisterCODEC vtk_TIFFUnRegisterCODEC +#define TIFFUnlinkDirectory vtk_TIFFUnlinkDirectory +#define TIFFVGetField vtk_TIFFVGetField +#define TIFFVGetFieldDefaulted vtk_TIFFVGetFieldDefaulted +#define TIFFVSetField vtk_TIFFVSetField +#define TIFFVStripSize vtk_TIFFVStripSize +#define TIFFVTileSize vtk_TIFFVTileSize +#define TIFFWarning vtk_TIFFWarning +#define TIFFWriteBufferSetup vtk_TIFFWriteBufferSetup +#define TIFFWriteCheck vtk_TIFFWriteCheck +#define TIFFWriteDirectory vtk_TIFFWriteDirectory +#define TIFFWriteEncodedStrip vtk_TIFFWriteEncodedStrip +#define TIFFWriteEncodedTile vtk_TIFFWriteEncodedTile +#define TIFFWriteRawStrip vtk_TIFFWriteRawStrip +#define TIFFWriteRawTile vtk_TIFFWriteRawTile +#define TIFFWriteScanline vtk_TIFFWriteScanline +#define TIFFWriteTile vtk_TIFFWriteTile +#define XYZtoRGB24 vtk_tiff_XYZtoRGB24 +#define _TIFFDefaultStripSize vtk__TIFFDefaultStripSize +#define _TIFFDefaultTileSize vtk__TIFFDefaultTileSize +#define _TIFFFax3fillruns vtk__TIFFFax3fillruns +#define _TIFFFieldWithTag vtk__TIFFFieldWithTag +#define _TIFFFindFieldInfo vtk__TIFFFindFieldInfo +#define _TIFFMergeFieldInfo vtk__TIFFMergeFieldInfo +#define _TIFFNoPostDecode vtk__TIFFNoPostDecode +#define _TIFFNoPreCode vtk__TIFFNoPreCode +#define _TIFFNoRowDecode vtk__TIFFNoRowDecode +#define _TIFFNoRowEncode vtk__TIFFNoRowEncode +#define _TIFFNoSeek vtk__TIFFNoSeek +#define _TIFFNoStripDecode vtk__TIFFNoStripDecode +#define _TIFFNoStripEncode vtk__TIFFNoStripEncode +#define _TIFFNoTileDecode vtk__TIFFNoTileDecode +#define _TIFFNoTileEncode vtk__TIFFNoTileEncode +#define _TIFFPrintFieldInfo vtk__TIFFPrintFieldInfo +#define _TIFFSampleToTagType vtk__TIFFSampleToTagType +#define _TIFFSetDefaultCompressionState vtk__TIFFSetDefaultCompressionState +#define _TIFFSetupFieldInfo vtk__TIFFSetupFieldInfo +#define _TIFFSwab16BitData vtk__TIFFSwab16BitData +#define _TIFFSwab32BitData vtk__TIFFSwab32BitData +#define _TIFFSwab64BitData vtk__TIFFSwab64BitData +#define _TIFFfree vtk__TIFFfree +#define _TIFFgetMode vtk__TIFFgetMode +#define _TIFFmalloc vtk__TIFFmalloc +#define _TIFFmemcmp vtk__TIFFmemcmp +#define _TIFFmemcpy vtk__TIFFmemcpy +#define _TIFFmemset vtk__TIFFmemset +#define _TIFFprintAscii vtk__TIFFprintAscii +#define _TIFFprintAsciiTag vtk__TIFFprintAsciiTag +#define _TIFFrealloc vtk__TIFFrealloc +#define _TIFFsetByteArray vtk__TIFFsetByteArray +#define _TIFFsetDoubleArray vtk__TIFFsetDoubleArray +#define _TIFFsetFloatArray vtk__TIFFsetFloatArray +#define _TIFFsetLongArray vtk__TIFFsetLongArray +#define _TIFFsetNString vtk__TIFFsetNString +#define _TIFFsetShortArray vtk__TIFFsetShortArray +#define _TIFFsetString vtk__TIFFsetString +#define uv_decode vtk_tiff_uv_decode +#define uv_encode vtk_tiff_uv_encode + +#endif diff --git a/Utilities/vtktiff/vtktiff.def b/Utilities/vtktiff/vtktiff.def new file mode 100644 index 0000000..a20d202 --- /dev/null +++ b/Utilities/vtktiff/vtktiff.def @@ -0,0 +1,84 @@ +EXPORTS vtk_TIFFOpen + vtk_TIFFGetVersion + vtk_TIFFClose + vtk_TIFFFlush + vtk_TIFFFlushData + vtk_TIFFGetField + vtk_TIFFVGetField + vtk_TIFFGetFieldDefaulted + vtk_TIFFVGetFieldDefaulted + vtk_TIFFReadDirectory + vtk_TIFFScanlineSize + vtk_TIFFStripSize + vtk_TIFFVStripSize + vtk_TIFFTileRowSize + vtk_TIFFTileSize + vtk_TIFFVTileSize + vtk_TIFFFileno + vtk_TIFFGetMode + vtk_TIFFIsTiled + vtk_TIFFIsByteSwapped + vtk_TIFFCurrentRow + vtk_TIFFCurrentDirectory + vtk_TIFFCurrentStrip + vtk_TIFFCurrentTile + vtk_TIFFReadBufferSetup + vtk_TIFFLastDirectory + vtk_TIFFSetDirectory + vtk_TIFFSetSubDirectory + vtk_TIFFUnlinkDirectory + vtk_TIFFSetField + vtk_TIFFVSetField + vtk_TIFFWriteDirectory + vtk_TIFFRewriteDirectory + vtk_TIFFPrintDirectory + vtk_TIFFReadScanline + vtk_TIFFWriteScanline + vtk_TIFFReadRGBAImage + vtk_TIFFPrintDirectory + vtk_TIFFReadScanline + vtk_TIFFWriteScanline + vtk_TIFFReadRGBAImage + vtk_TIFFFdOpen + vtk_TIFFClientOpen + vtk_TIFFFileName + vtk_TIFFError + vtk_TIFFWarning + vtk_TIFFSetErrorHandler + vtk_TIFFSetWarningHandler + vtk_TIFFComputeTile + vtk_TIFFCheckTile + vtk_TIFFNumberOfTiles + vtk_TIFFReadTile + vtk_TIFFWriteTile + vtk_TIFFComputeStrip + vtk_TIFFNumberOfStrips + vtk_TIFFReadEncodedStrip + vtk_TIFFReadRawStrip + vtk_TIFFReadEncodedTile + vtk_TIFFReadRawTile + vtk_TIFFReadRGBATile + vtk_TIFFReadRGBAStrip + vtk_TIFFWriteEncodedStrip + vtk_TIFFWriteRawStrip + vtk_TIFFWriteEncodedTile + vtk_TIFFWriteRawTile + vtk_TIFFSetWriteOffset + vtk_TIFFSwabShort + vtk_TIFFSwabLong + vtk_TIFFSwabArrayOfShort + vtk_TIFFSwabArrayOfLong + vtk_TIFFSwabArrayOfDouble + vtk_TIFFReverseBits + vtk_TIFFGetBitRevTable + vtk_TIFFDefaultStripSize + vtk_TIFFDefaultTileSize + vtk_TIFFRasterScanlineSize + vtk__TIFFmalloc + vtk__TIFFrealloc + vtk__TIFFfree + vtk__TIFFmemset + vtk__TIFFmemcpy + vtk__TIFFmemcmp + vtk_TIFFCreateDirectory + vtk_TIFFDefaultStripSize diff --git a/Utilities/vtkzlib/.NoDartCoverage b/Utilities/vtkzlib/.NoDartCoverage new file mode 100644 index 0000000..3c99729 --- /dev/null +++ b/Utilities/vtkzlib/.NoDartCoverage @@ -0,0 +1 @@ +# do not do coverage in this directory diff --git a/Utilities/vtkzlib/CMakeLists.txt b/Utilities/vtkzlib/CMakeLists.txt new file mode 100644 index 0000000..cd0befa --- /dev/null +++ b/Utilities/vtkzlib/CMakeLists.txt @@ -0,0 +1,48 @@ +PROJECT(VTKZLIB) +INCLUDE_REGULAR_EXPRESSION("^(vtk|deflate|inf|trees|zconf|zlib|zutil).*$") + +INCLUDE_DIRECTORIES(${VTKZLIB_SOURCE_DIR}) + +# source files for zlib +SET(ZLIB_SRCS + adler32.c gzio.c inftrees.c uncompr.c + compress.c infblock.c infutil.c zutil.c + crc32.c infcodes.c + deflate.c inffast.c + inflate.c trees.c + ) + +# for windows add the .def and .rc files to the source list if building shared libs +IF(WIN32) + IF(BUILD_SHARED_LIBS) + SET(ZLIB_DLL 1) + IF(NOT UNIX) + IF(NOT BORLAND) + IF(NOT MINGW) + SET(ZLIB_SRCS ${ZLIB_SRCS} zlib.def zlib.rc ) + ENDIF(NOT MINGW) + ENDIF(NOT BORLAND) + ENDIF(NOT UNIX) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(WIN32) + +CONFIGURE_FILE(${VTKZLIB_SOURCE_DIR}/.NoDartCoverage + ${VTKZLIB_BINARY_DIR}/.NoDartCoverage) +CONFIGURE_FILE(${VTKZLIB_SOURCE_DIR}/zlibDllConfig.h.in + ${VTKZLIB_BINARY_DIR}/zlibDllConfig.h) + + +ADD_LIBRARY(vtkzlib ${ZLIB_SRCS}) + +# Apply user-defined properties to the library target. +IF(VTK_LIBRARY_PROPERTIES) + SET_TARGET_PROPERTIES(vtkzlib PROPERTIES ${VTK_LIBRARY_PROPERTIES}) +ENDIF(VTK_LIBRARY_PROPERTIES) + +IF(NOT VTK_INSTALL_NO_LIBRARIES) + INSTALL_TARGETS(${VTK_INSTALL_LIB_DIR} vtkzlib) +ENDIF(NOT VTK_INSTALL_NO_LIBRARIES) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_INCLUDE_DIR}/vtkzlib .h + zlib zconf zlibDllConfig vtk_zlib_mangle) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) diff --git a/Utilities/vtkzlib/adler32.c b/Utilities/vtkzlib/adler32.c new file mode 100644 index 0000000..f89d13c --- /dev/null +++ b/Utilities/vtkzlib/adler32.c @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#include "zlib.h" + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/Utilities/vtkzlib/compress.c b/Utilities/vtkzlib/compress.c new file mode 100644 index 0000000..372fa00 --- /dev/null +++ b/Utilities/vtkzlib/compress.c @@ -0,0 +1,71 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#if defined(_MSC_VER) +#pragma warning ( disable : 4702 ) +#endif +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} diff --git a/Utilities/vtkzlib/crc32.c b/Utilities/vtkzlib/crc32.c new file mode 100644 index 0000000..d22907c --- /dev/null +++ b/Utilities/vtkzlib/crc32.c @@ -0,0 +1,162 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: crc32.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#include "zlib.h" + +#define local static + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} diff --git a/Utilities/vtkzlib/deflate.c b/Utilities/vtkzlib/deflate.c new file mode 100644 index 0000000..7512169 --- /dev/null +++ b/Utilities/vtkzlib/deflate.c @@ -0,0 +1,1350 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_slow OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + static const char* my_version = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/Utilities/vtkzlib/deflate.h b/Utilities/vtkzlib/deflate.h new file mode 100644 index 0000000..f68db7b --- /dev/null +++ b/Utilities/vtkzlib/deflate.h @@ -0,0 +1,318 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/Utilities/vtkzlib/example.c b/Utilities/vtkzlib/example.c new file mode 100644 index 0000000..edd332c --- /dev/null +++ b/Utilities/vtkzlib/example.c @@ -0,0 +1,556 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: example.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#include <stdio.h> +#include "zlib.h" + +#ifdef STDC +# include <string.h> +# include <stdlib.h> +#else + extern void exit OF((int)); +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +const char dictionary[] = "hello"; +uLong dictId; /* Adler32 value of the dictionary */ + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *out, const char *in, + Byte *uncompr, int uncomprLen)); +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(out, in, uncompr, uncomprLen) + const char *out; /* compressed output file */ + const char *in; /* compressed input file */ + Byte *uncompr; + int uncomprLen; +{ + int err; + int len = strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(out, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(in, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + } + strcpy((char*)uncompr, "garbage"); + + uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen); + if (uncomprLen != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char *)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, uncomprLen); + uncomprLen = strlen((char*)uncompr); + if (uncomprLen != 6) { /* "hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello+7)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char *)uncompr); + } + + gzclose(file); +} + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + int len = strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + int len = strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (Bytef*)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + (argc > 2 ? argv[2] : TESTFILE), + uncompr, (int)uncomprLen); + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + exit(0); + return 0; /* to avoid warning */ +} diff --git a/Utilities/vtkzlib/gzio.c b/Utilities/vtkzlib/gzio.c new file mode 100644 index 0000000..d80fa97 --- /dev/null +++ b/Utilities/vtkzlib/gzio.c @@ -0,0 +1,875 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_DEFLATE to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#include <stdio.h> + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + long startpos; /* start of compressed data in file (header skipped) */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open return NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->startpos = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * startpos anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->startpos = (ftell(s->file) - s->stream.avail_in); + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "<fd:%d>", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(s); + if (c != gz_magic[len]) { + if (len != 0) s->stream.avail_in++, s->stream.next_in--; + if (c != EOF) { + s->stream.avail_in++, s->stream.next_in--; + s->transparent = 1; + } + s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; + return; + } + } + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->stream.total_in += (uLong)len; + s->stream.total_out += (uLong)len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may + * be different from s->stream.total_out) in case of + * concatenated .gz files. Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + uLong total_in = s->stream.total_in; + uLong total_out = s->stream.total_out; + + inflateReset(&(s->stream)); + s->stream.total_in = total_in; + s->stream.total_out = total_out; + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_DEFLATE +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + const voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include <stdarg.h> + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + va_start(va, format); +#ifdef HAS_vsnprintf + (void)vsnprintf(buf, sizeof(buf), format, va); +#else + (void)vsprintf(buf, format, va); +#endif + va_end(va); + len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + +#ifdef HAS_snprintf + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#else + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#endif + len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->z_err = deflate(&(s->stream), flush); + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_DEFLATE */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->stream.total_in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return (z_off_t)s->stream.total_in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->stream.total_out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->stream.total_in = s->stream.total_out = (uLong)offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if ((uLong)offset >= s->stream.total_out) { + offset -= s->stream.total_out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return (z_off_t)s->stream.total_out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + + if (s->startpos == 0) { /* not a compressed file */ + rewind(s->file); + return 0; + } + + (void) inflateReset(&s->stream); + return fseek(s->file, s->startpos, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, s->stream.total_in); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char* ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} diff --git a/Utilities/vtkzlib/infblock.c b/Utilities/vtkzlib/infblock.c new file mode 100644 index 0000000..dd7a6d4 --- /dev/null +++ b/Utilities/vtkzlib/infblock.c @@ -0,0 +1,403 @@ +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* Table for deflate from PKZIP's appnote.txt. */ +local const uInt border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_streamp z; +uLongf *c; +{ + if (c != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); + Tracev((stderr, "inflate: blocks reset\n")); +} + + +inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_streamp z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) + { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Tracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); + return s; +} + + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + r = t; + if (r == Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + ZFREE(z, s->sub.trees.blens); + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + + +void inflate_set_dictionary(s, d, n) +inflate_blocks_statef *s; +const Bytef *d; +uInt n; +{ + zmemcpy(s->window, d, n); + s->read = s->write = s->window + n; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. + * IN assertion: s != Z_NULL + */ +int inflate_blocks_sync_point(s) +inflate_blocks_statef *s; +{ + return s->mode == LENS; +} diff --git a/Utilities/vtkzlib/infblock.h b/Utilities/vtkzlib/infblock.h new file mode 100644 index 0000000..173b226 --- /dev/null +++ b/Utilities/vtkzlib/infblock.h @@ -0,0 +1,39 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z, + check_func c, /* check function */ + uInt w)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/Utilities/vtkzlib/infcodes.c b/Utilities/vtkzlib/infcodes.c new file mode 100644 index 0000000..9abe541 --- /dev/null +++ b/Utilities/vtkzlib/infcodes.c @@ -0,0 +1,251 @@ +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ +inflate_codes_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + inflate_codes_mode mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +z_streamp z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ + f = q - c->sub.copy.dist; + while (f < s->window) /* modulo window size-"while" instead */ + f += s->end - s->window; /* of "if" handles invalid distances */ + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} diff --git a/Utilities/vtkzlib/infcodes.h b/Utilities/vtkzlib/infcodes.h new file mode 100644 index 0000000..46821a0 --- /dev/null +++ b/Utilities/vtkzlib/infcodes.h @@ -0,0 +1,27 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/Utilities/vtkzlib/inffast.c b/Utilities/vtkzlib/inffast.c new file mode 100644 index 0000000..aa7f1d4 --- /dev/null +++ b/Utilities/vtkzlib/inffast.c @@ -0,0 +1,183 @@ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}} +#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + r = q - d; + if (r < s->window) /* wrap if needed */ + { + do { + r += s->end - s->window; /* force pointer in window */ + } while (r < s->window); /* covers invalid distances */ + e = s->end - r; + if (c > e) + { + c -= e; /* wrapped copy */ + do { + *q++ = *r++; + } while (--e); + r = s->window; + do { + *q++ = *r++; + } while (--c); + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + break; + } + else if ((e & 64) == 0) + { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else + { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} diff --git a/Utilities/vtkzlib/inffast.h b/Utilities/vtkzlib/inffast.h new file mode 100644 index 0000000..a31a4bb --- /dev/null +++ b/Utilities/vtkzlib/inffast.h @@ -0,0 +1,17 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +extern int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_streamp )); diff --git a/Utilities/vtkzlib/inffixed.h b/Utilities/vtkzlib/inffixed.h new file mode 100644 index 0000000..77f7e76 --- /dev/null +++ b/Utilities/vtkzlib/inffixed.h @@ -0,0 +1,151 @@ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by the maketree.c program + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local uInt fixed_bl = 9; +local uInt fixed_bd = 5; +local inflate_huft fixed_tl[] = { + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} + }; +local inflate_huft fixed_td[] = { + {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, + {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, + {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, + {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, + {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, + {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, + {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, + {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} + }; diff --git a/Utilities/vtkzlib/inflate.c b/Utilities/vtkzlib/inflate.c new file mode 100644 index 0000000..dfb2e86 --- /dev/null +++ b/Utilities/vtkzlib/inflate.c @@ -0,0 +1,366 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ + +typedef enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + DICT4, /* four dictionary check bytes to go */ + DICT3, /* three dictionary check bytes to go */ + DICT2, /* two dictionary check bytes to go */ + DICT1, /* one dictionary check byte to go */ + DICT0, /* waiting for inflateSetDictionary */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ +inflate_mode; + +/* inflate private state */ +struct internal_state { + + /* mode */ + inflate_mode mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int ZEXPORT inflateReset(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int ZEXPORT inflateEnd(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + + +int ZEXPORT inflateInit2_(z, w, version, stream_size) +z_streamp z; +int w; +const char *version; +int stream_size; +{ + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != sizeof(z_stream)) + return Z_VERSION_ERROR; + + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) + { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Tracev((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int ZEXPORT inflateInit_(z, version, stream_size) +z_streamp z; +const char *version; +int stream_size; +{ + return inflateInit2_(z, DEF_WBITS, version, stream_size); +} + + +#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int ZEXPORT inflate(z, f) +z_streamp z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) + { + z->state->mode = BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + b = NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) + { + z->state->mode = BLOCKS; + break; + } + z->state->mode = DICT4; + case DICT4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = DICT3; + case DICT3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = DICT2; + case DICT2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = DICT1; + case DICT1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z->state->mode = BAD; + z->msg = (char*)"need dictionary"; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_STREAM_ERROR; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; + r = f; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) +z_streamp z; +const Bytef *dictionary; +uInt dictLength; +{ + uInt length = dictLength; + + if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) + return Z_STREAM_ERROR; + + if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; + z->adler = 1L; + + if (length >= ((uInt)1<<z->state->wbits)) + { + length = (1<<z->state->wbits)-1; + dictionary += dictLength - length; + } + inflate_set_dictionary(z->state->blocks, dictionary, length); + z->state->mode = BLOCKS; + return Z_OK; +} + + +int ZEXPORT inflateSync(z) +z_streamp z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + static const Byte mark[4] = {0, 0, 0xff, 0xff}; + if (*p == mark[m]) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + * but removes the length bytes of the resulting empty stored block. When + * decompressing, PPP checks that at the end of input packet, inflate is + * waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) + return Z_STREAM_ERROR; + return inflate_blocks_sync_point(z->state->blocks); +} diff --git a/Utilities/vtkzlib/inftrees.c b/Utilities/vtkzlib/inftrees.c new file mode 100644 index 0000000..8b5cf5a --- /dev/null +++ b/Utilities/vtkzlib/inftrees.c @@ -0,0 +1,455 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#if !defined(BUILDFIXED) && !defined(STDC) +# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ +#endif + +const char inflate_copyright[] = + " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + const uIntf *, /* list of base values for non-simple codes */ + const uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + inflate_huft *, /* space for trees */ + uInt *, /* hufts used in space */ + uIntf * )); /* space for values */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const uInt cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build(b, n, s, d, e, t, m, hp, hn, v) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= 288) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +const uIntf *d; /* list of base values for non-simple codes */ +const uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +inflate_huft *hp; /* space for trees */ +uInt *hn; /* hufts used in space */ +uIntf *v; /* working area: values in order of bit length */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), or Z_DATA_ERROR if the input is invalid. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_DATA_ERROR; /* overflow of MANY */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + mask = (1 << w) - 1; /* needed on HP, cc -O bug */ + while ((i & mask) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + mask = (1 << w) - 1; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) + { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +} + + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + /* allocate work area */ + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +#endif + } + + /* done */ + ZFREE(z, v); + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +#ifdef BUILDFIXED +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; +#else +#include "inffixed.h" +#endif + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ +#ifdef BUILDFIXED + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + uIntf *c; /* length list for huft_build */ + uIntf *v; /* work area for huft_build */ + + /* allocate memory */ + if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + { + ZFREE(z, c); + return Z_MEM_ERROR; + } + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, + fixed_mem, &f, v); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, + fixed_mem, &f, v); + + /* done */ + ZFREE(z, v); + ZFREE(z, c); + fixed_built = 1; + } +#endif + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + z = 0; + return Z_OK; +} diff --git a/Utilities/vtkzlib/inftrees.h b/Utilities/vtkzlib/inftrees.h new file mode 100644 index 0000000..04b73b7 --- /dev/null +++ b/Utilities/vtkzlib/inftrees.h @@ -0,0 +1,58 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit int's) */ + uInt base; /* literal, length base, distance base, + or table offset */ +}; + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. */ +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_streamp)); /* for memory allocation */ diff --git a/Utilities/vtkzlib/infutil.c b/Utilities/vtkzlib/infutil.c new file mode 100644 index 0000000..9a07622 --- /dev/null +++ b/Utilities/vtkzlib/infutil.c @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/Utilities/vtkzlib/infutil.h b/Utilities/vtkzlib/infutil.h new file mode 100644 index 0000000..4401df8 --- /dev/null +++ b/Utilities/vtkzlib/infutil.h @@ -0,0 +1,98 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft *hufts; /* single malloc for tree space */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}} +#define DUMPBITS(j) {b>>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern uInt inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/Utilities/vtkzlib/maketree.c b/Utilities/vtkzlib/maketree.c new file mode 100644 index 0000000..a16d4b1 --- /dev/null +++ b/Utilities/vtkzlib/maketree.c @@ -0,0 +1,85 @@ +/* maketree.c -- make inffixed.h table for decoding fixed codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* This program is included in the distribution for completeness. + You do not need to compile or run this program since inffixed.h + is already included in the distribution. To use this program + you need to compile zlib with BUILDFIXED defined and then compile + and link this program with the zlib library. Then the output of + this program can be piped to inffixed.h. */ + +#include <stdio.h> +#include <stdlib.h> +#include "zutil.h" +#include "inftrees.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* generate initialization table for an inflate_huft structure array */ +void maketree(uInt b, inflate_huft *t) +{ + int i, e; + + i = 0; + while (1) + { + e = t[i].exop; + if (e && (e & (16+64)) == 0) /* table pointer */ + { + fprintf(stderr, "maketree: cannot initialize sub-tables!\n"); + exit(1); + } + if (i % 4 == 0) + printf("\n "); + printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base); + if (++i == (1<<b)) + break; + putchar(','); + } + puts(""); +} + +/* create the fixed tables in C initialization syntax */ +void main(void) +{ + int r; + uInt bl, bd; + inflate_huft *tl, *td; + z_stream z; + + z.zalloc = zcalloc; + z.opaque = (voidpf)0; + z.zfree = zcfree; + r = inflate_trees_fixed(&bl, &bd, &tl, &td, &z); + if (r) + { + fprintf(stderr, "inflate_trees_fixed error %d\n", r); + return; + } + puts("/* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by the maketree.c program"); + puts(" */"); + puts(""); + puts("/* WARNING: this file should *not* be used by applications. It is"); + puts(" part of the implementation of the compression library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + printf("local uInt fixed_bl = %d;\n", bl); + printf("local uInt fixed_bd = %d;\n", bd); + printf("local inflate_huft fixed_tl[] = {"); + maketree(bl, tl); + puts(" };"); + printf("local inflate_huft fixed_td[] = {"); + maketree(bd, td); + puts(" };"); +} diff --git a/Utilities/vtkzlib/minigzip.c b/Utilities/vtkzlib/minigzip.c new file mode 100644 index 0000000..73af8d6 --- /dev/null +++ b/Utilities/vtkzlib/minigzip.c @@ -0,0 +1,320 @@ +/* minigzip.c -- simulate gzip using the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * minigzip is a minimal implementation of the gzip utility. This is + * only an example of using zlib and isn't meant to replace the + * full-featured gzip. No attempt is made to deal with file systems + * limiting names to 14 or 8+3 characters, etc... Error checking is + * very limited. So use minigzip only for testing; use gzip for the + * real thing. On MSDOS, use only on file names without extension + * or in pipe mode. + */ + +/* @(#) $Id: minigzip.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#include <stdio.h> +#include "zlib.h" + +#ifdef STDC +# include <string.h> +# include <stdlib.h> +#else + extern void exit OF((int)); +#endif + +#ifdef USE_MMAP +# include <sys/types.h> +# include <sys/mman.h> +# include <sys/stat.h> +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) +# include <fcntl.h> +# include <io.h> +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fileno */ +#endif + +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + int len = strlen(file); + + strcpy(buf, file); + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; + strcat(infile, GZ_SUFFIX); + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-d] [-f] [-h] [-1 to -9] [files...] + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int uncompr = 0; + gzFile file; + char outmode[20]; + + strcpy(outmode, "wb6 "); + + prog = argv[0]; + argc--, argv++; + + while (argc > 0) { + if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + do { + if (uncompr) { + file_uncompress(*argv); + } else { + file_compress(*argv, outmode); + } + } while (argv++, --argc); + } + exit(0); + return 0; /* to avoid warning */ +} diff --git a/Utilities/vtkzlib/trees.c b/Utilities/vtkzlib/trees.c new file mode 100644 index 0000000..a6382b1 --- /dev/null +++ b/Utilities/vtkzlib/trees.c @@ -0,0 +1,1214 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include <ctype.h> +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + _length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + _dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/Utilities/vtkzlib/trees.h b/Utilities/vtkzlib/trees.h new file mode 100644 index 0000000..72facf9 --- /dev/null +++ b/Utilities/vtkzlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/Utilities/vtkzlib/uncompr.c b/Utilities/vtkzlib/uncompr.c new file mode 100644 index 0000000..48b7868 --- /dev/null +++ b/Utilities/vtkzlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#if defined(_MSC_VER) +#pragma warning ( disable : 4702 ) +#endif +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/Utilities/vtkzlib/vtk_zlib_mangle.h b/Utilities/vtkzlib/vtk_zlib_mangle.h new file mode 100644 index 0000000..13bb0f1 --- /dev/null +++ b/Utilities/vtkzlib/vtk_zlib_mangle.h @@ -0,0 +1,86 @@ +#ifndef vtk_zlib_mangle_h +#define vtk_zlib_mangle_h + +/* + +This header file mangles all symbols exported from the zlib library. +It is included in all files while building the zlib library. Due to +namespace pollution, no zlib headers should be included in .h files in +VTK. + +The following command was used to obtain the symbol list: + +nm libvtkzlib.a |grep " [TR] " + +*/ + +#define deflate_copyright vtk_zlib_deflate_copyright +#define _length_code vtk_zlib__length_code +#define _dist_code vtk_zlib__dist_code +#define _tr_align vtk_zlib__tr_align +#define _tr_flush_block vtk_zlib__tr_flush_block +#define _tr_init vtk_zlib__tr_init +#define _tr_stored_block vtk_zlib__tr_stored_block +#define _tr_tally vtk_zlib__tr_tally +#define adler32 vtk_zlib_adler32 +#define compress vtk_zlib_compress +#define compress2 vtk_zlib_compress2 +#define crc32 vtk_zlib_crc32 +#define deflate vtk_zlib_deflate +#define deflateCopy vtk_zlib_deflateCopy +#define deflateEnd vtk_zlib_deflateEnd +#define deflateInit2_ vtk_zlib_deflateInit2_ +#define deflateInit_ vtk_zlib_deflateInit_ +#define deflateParams vtk_zlib_deflateParams +#define deflateReset vtk_zlib_deflateReset +#define deflateSetDictionary vtk_zlib_deflateSetDictionary +#define get_crc_table vtk_zlib_get_crc_table +#define gzclose vtk_zlib_gzclose +#define gzdopen vtk_zlib_gzdopen +#define gzeof vtk_zlib_gzeof +#define gzerror vtk_zlib_gzerror +#define gzflush vtk_zlib_gzflush +#define gzgetc vtk_zlib_gzgetc +#define gzgets vtk_zlib_gzgets +#define gzopen vtk_zlib_gzopen +#define gzprintf vtk_zlib_gzprintf +#define gzputc vtk_zlib_gzputc +#define gzputs vtk_zlib_gzputs +#define gzread vtk_zlib_gzread +#define gzrewind vtk_zlib_gzrewind +#define gzseek vtk_zlib_gzseek +#define gzsetparams vtk_zlib_gzsetparams +#define gztell vtk_zlib_gztell +#define gzwrite vtk_zlib_gzwrite +#define inflate vtk_zlib_inflate +#define inflateEnd vtk_zlib_inflateEnd +#define inflateInit2_ vtk_zlib_inflateInit2_ +#define inflateInit_ vtk_zlib_inflateInit_ +#define inflateReset vtk_zlib_inflateReset +#define inflateSetDictionary vtk_zlib_inflateSetDictionary +#define inflateSync vtk_zlib_inflateSync +#define inflateSyncPoint vtk_zlib_inflateSyncPoint +#define inflate_blocks vtk_zlib_inflate_blocks +#define inflate_blocks_free vtk_zlib_inflate_blocks_free +#define inflate_blocks_new vtk_zlib_inflate_blocks_new +#define inflate_blocks_reset vtk_zlib_inflate_blocks_reset +#define inflate_blocks_sync_point vtk_zlib_inflate_blocks_sync_point +#define inflate_codes vtk_zlib_inflate_codes +#define inflate_codes_free vtk_zlib_inflate_codes_free +#define inflate_codes_new vtk_zlib_inflate_codes_new +#define inflate_copyright vtk_zlib_inflate_copyright +#define inflate_fast vtk_zlib_inflate_fast +#define inflate_flush vtk_zlib_inflate_flush +#define inflate_mask vtk_zlib_inflate_mask +#define inflate_set_dictionary vtk_zlib_inflate_set_dictionary +#define inflate_trees_bits vtk_zlib_inflate_trees_bits +#define inflate_trees_dynamic vtk_zlib_inflate_trees_dynamic +#define inflate_trees_fixed vtk_zlib_inflate_trees_fixed +#define uncompress vtk_zlib_uncompress +#define zError vtk_zlib_zError +#define zcalloc vtk_zlib_zcalloc +#define zcfree vtk_zlib_zcfree +#define zlibVersion vtk_zlib_zlibVersion +#define z_errmsg vtk_zlib_z_errmsg + +#endif diff --git a/Utilities/vtkzlib/zconf.h b/Utilities/vtkzlib/zconf.h new file mode 100644 index 0000000..8f687fb --- /dev/null +++ b/Utilities/vtkzlib/zconf.h @@ -0,0 +1,290 @@ +#include "vtk_zlib_mangle.h" +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +#include <vtkzlib/zlibDllConfig.h> + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(NOTUSED_WINDOWS) || defined(NOTUSEDWINDOWS) +# ifdef FAR +# undef FAR +# endif +# include <windows.h> +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include <windows.h> +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include <sys/types.h> /* for off_t */ +# include <unistd.h> /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#if defined(_MSC_VER) +#pragma warning ( disable : 4100 ) /* unreferenced variable */ +#pragma warning ( disable : 4127 ) /* cond expr is constant */ +#pragma warning ( disable : 4131 ) /* Old style declaration */ +#pragma warning ( disable : 4244 ) /* conversion loss of data */ +#pragma warning ( disable : 4267 ) +#endif + +#endif /* _ZCONF_H */ diff --git a/Utilities/vtkzlib/zlib.def b/Utilities/vtkzlib/zlib.def new file mode 100644 index 0000000..dc4e1c7 --- /dev/null +++ b/Utilities/vtkzlib/zlib.def @@ -0,0 +1,47 @@ + +VERSION 1.13 + +HEAPSIZE 1048576,4096 + +EXPORTS + vtk_zlib_adler32 @1 + vtk_zlib_compress @2 + vtk_zlib_crc32 @3 + vtk_zlib_deflate @4 + vtk_zlib_deflateCopy @5 + vtk_zlib_deflateEnd @6 + vtk_zlib_deflateInit2_ @7 + vtk_zlib_deflateInit_ @8 + vtk_zlib_deflateParams @9 + vtk_zlib_deflateReset @10 + vtk_zlib_deflateSetDictionary @11 + vtk_zlib_gzclose @12 + vtk_zlib_gzdopen @13 + vtk_zlib_gzerror @14 + vtk_zlib_gzflush @15 + vtk_zlib_gzopen @16 + vtk_zlib_gzread @17 + vtk_zlib_gzwrite @18 + vtk_zlib_inflate @19 + vtk_zlib_inflateEnd @20 + vtk_zlib_inflateInit2_ @21 + vtk_zlib_inflateInit_ @22 + vtk_zlib_inflateReset @23 + vtk_zlib_inflateSetDictionary @24 + vtk_zlib_inflateSync @25 + vtk_zlib_uncompress @26 + vtk_zlib_zlibVersion @27 + vtk_zlib_gzprintf @28 + vtk_zlib_gzputc @29 + vtk_zlib_gzgetc @30 + vtk_zlib_gzseek @31 + vtk_zlib_gzrewind @32 + vtk_zlib_gztell @33 + vtk_zlib_gzeof @34 + vtk_zlib_gzsetparams @35 + vtk_zlib_zError @36 + vtk_zlib_inflateSyncPoint @37 + vtk_zlib_get_crc_table @38 + vtk_zlib_compress2 @39 + vtk_zlib_gzputs @40 + vtk_zlib_gzgets @41 diff --git a/Utilities/vtkzlib/zlib.h b/Utilities/vtkzlib/zlib.h new file mode 100644 index 0000000..2d7601b --- /dev/null +++ b/Utilities/vtkzlib/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.4, March 11th, 2002 + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.4" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/Utilities/vtkzlib/zlib.rc b/Utilities/vtkzlib/zlib.rc new file mode 100644 index 0000000..556d4ff --- /dev/null +++ b/Utilities/vtkzlib/zlib.rc @@ -0,0 +1,32 @@ +#include <windows.h> + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1,1,3,0 + PRODUCTVERSION 1,1,3,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression library\0" + VALUE "FileVersion", "1.1.3\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlib.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-1998 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/Utilities/vtkzlib/zlibDllConfig.h.in b/Utilities/vtkzlib/zlibDllConfig.h.in new file mode 100644 index 0000000..3dceb8c --- /dev/null +++ b/Utilities/vtkzlib/zlibDllConfig.h.in @@ -0,0 +1,6 @@ +#ifndef _zlibDllConfig_h +#define _zlibDllConfig_h + +#cmakedefine ZLIB_DLL + +#endif diff --git a/Utilities/vtkzlib/zutil.c b/Utilities/vtkzlib/zutil.c new file mode 100644 index 0000000..0231b3e --- /dev/null +++ b/Utilities/vtkzlib/zutil.c @@ -0,0 +1,225 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char *z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifdef __TURBOC__ +#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) +/* Small and medium model in Turbo C are for now limited to near allocation + * with reduced MAX_WBITS and MAX_MEM_LEVEL + */ +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} +#endif +#endif /* __TURBOC__ */ + + +#if defined(M_I86) && !defined(__32BIT__) +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* MSC */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/Utilities/vtkzlib/zutil.h b/Utilities/vtkzlib/zutil.h new file mode 100644 index 0000000..78a074e --- /dev/null +++ b/Utilities/vtkzlib/zutil.h @@ -0,0 +1,220 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2004/04/28 15:49:22 king Exp $ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "zlib.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif +# else /* MSC or DJGPP */ +# include <malloc.h> +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include <stdio.h> + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/VTKConfig.cmake.in b/VTKConfig.cmake.in new file mode 100644 index 0000000..8866d1f --- /dev/null +++ b/VTKConfig.cmake.in @@ -0,0 +1,161 @@ +#----------------------------------------------------------------------------- +# +# VTKConfig.cmake - VTK CMake configuration file for external projects. +# +# This file is configured by VTK and used by the UseVTK.cmake module +# to load VTK's settings for an external project. +@VTK_CONFIG_INSTALL_ONLY@ +# The VTK include file directories. +SET(VTK_INCLUDE_DIRS "@VTK_INCLUDE_DIRS_CONFIG@") + +# The VTK library directories. +SET(VTK_LIBRARY_DIRS "@VTK_LIBRARY_DIRS_CONFIG@") + +# The VTK runtime library directories. Note that if +# VTK_CONFIGURATION_TYPES is set (see below) then these directories +# will be the parent directories under which there will be a directory +# of runtime binaries for each configuration type. +SET(VTK_RUNTIME_LIBRARY_DIRS "@VTK_RUNTIME_LIBRARY_DIRS_CONFIG@") + +# The C and C++ flags added by VTK to the cmake-configured flags. +SET(VTK_REQUIRED_C_FLAGS "@VTK_REQUIRED_C_FLAGS@") +SET(VTK_REQUIRED_CXX_FLAGS "@VTK_REQUIRED_CXX_FLAGS@") +SET(VTK_REQUIRED_EXE_LINKER_FLAGS "@VTK_REQUIRED_EXE_LINKER_FLAGS@") +SET(VTK_REQUIRED_SHARED_LINKER_FLAGS "@VTK_REQUIRED_SHARED_LINKER_FLAGS@") +SET(VTK_REQUIRED_MODULE_LINKER_FLAGS "@VTK_REQUIRED_MODULE_LINKER_FLAGS@") + +# The VTK version number +SET(VTK_MAJOR_VERSION "@VTK_MAJOR_VERSION@") +SET(VTK_MINOR_VERSION "@VTK_MINOR_VERSION@") +SET(VTK_BUILD_VERSION "@VTK_BUILD_VERSION@") + +# The location of the UseVTK.cmake file. +SET(VTK_USE_FILE "@VTK_USE_FILE@") + +# The build settings file. +SET(VTK_BUILD_SETTINGS_FILE "@VTK_BUILD_SETTINGS_FILE@") + +# The directory containing class list files for each kit. +SET(VTK_KITS_DIR "@VTK_KITS_DIR_CONFIG@") + +# The wrapping hints file. +SET(VTK_WRAP_HINTS "@VTK_WRAP_HINTS_CONFIG@") + +# CMake extension module directory and macro file. +SET(VTK_LOAD_CMAKE_EXTENSIONS_MACRO "@VTK_LOAD_CMAKE_EXTENSIONS_MACRO_CONFIG@") +SET(VTK_CMAKE_DIR "@VTK_CMAKE_DIR_CONFIG@") +SET(VTK_CMAKE_EXTENSIONS_DIR "@VTK_CMAKE_EXTENSIONS_DIR_CONFIG@") + +# The list of available kits. +SET(VTK_KITS "@VTK_KITS@") + +# The list of available languages. +SET(VTK_LANGUAGES "@VTK_LANGUAGES@") + +# VTK Configuration options. +SET(VTK_BUILD_SHARED_LIBS "@BUILD_SHARED_LIBS@") +SET(VTK_DEBUG_LEAKS "@VTK_DEBUG_LEAKS@") +SET(VTK_USE_TK "@VTK_USE_TK@") +SET(VTK_HAVE_VP1000 "@VTK_HAVE_VP1000@") +SET(VTK_USE_MANGLED_MESA "@VTK_USE_MANGLED_MESA@") +SET(VTK_MPIRUN_EXE "@VTK_MPIRUN_EXE_CONFIG@") +SET(VTK_MPI_MAX_NUMPROCS "@VTK_MPI_PREFLAGS_CONFIG@") +SET(VTK_MPI_POSTFLAGS "@VTK_MPI_POSTFLAGS_CONFIG@") +SET(VTK_MPI_PREFLAGS "@VTK_MPI_PREFLAGS_CONFIG@") +SET(VTK_MPI_CLIENT_PREFLAGS "@VTK_MPI_CLIENT_PREFLAGS_CONFIG@") +SET(VTK_MPI_SERVER_PREFLAGS "@VTK_MPI_SERVER_PREFLAGS_CONFIG@") +SET(VTK_MPI_CLIENT_POSTFLAGS "@VTK_MPI_CLIENT_POSTFLAGS_CONFIG@") +SET(VTK_MPI_SERVER_POSTFLAGS "@VTK_MPI_SERVER_POSTFLAGS_CONFIG@") +SET(VTK_OPENGL_HAS_OSMESA "@VTK_OPENGL_HAS_OSMESA@") +SET(VTK_USE_64BIT_IDS "@VTK_USE_64BIT_IDS@") +SET(VTK_USE_ANSI_STDLIB "@VTK_USE_ANSI_STDLIB@") +SET(VTK_USE_CARBON "@VTK_USE_CARBON@") +SET(VTK_USE_COCOA "@VTK_USE_COCOA@") +SET(VTK_USE_GUISUPPORT "@VTK_USE_GUISUPPORT@") +SET(VTK_USE_MATROX_IMAGING "@VTK_USE_MATROX_IMAGING@") +SET(VTK_USE_MFC "@VTK_USE_MFC@") +SET(VTK_USE_QVTK "@VTK_USE_QVTK@") +SET(VTK_USE_MPI "@VTK_USE_MPI@") +SET(VTK_USE_PARALLEL "@VTK_USE_PARALLEL@") +SET(VTK_USE_RENDERING "@VTK_USE_RENDERING@") +SET(VTK_USE_VIDEO_FOR_WINDOWS "@VTK_USE_VIDEO_FOR_WINDOWS@") +SET(VTK_USE_GL2PS "@VTK_USE_GL2PS@") +SET(VTK_USE_X "@VTK_USE_X@") +SET(VTK_WRAP_JAVA "@VTK_WRAP_JAVA@") +SET(VTK_WRAP_PYTHON "@VTK_WRAP_PYTHON@") +SET(VTK_WRAP_TCL "@VTK_WRAP_TCL@") +SET(VTK_LEGACY_REMOVE "@VTK_LEGACY_REMOVE@") +SET(VTK_LEGACY_SILENT "@VTK_LEGACY_SILENT@") + +# The Hybrid and VolumeRendering kits are now switched with Rendering. +SET(VTK_USE_HYBRID "@VTK_USE_RENDERING@") +SET(VTK_USE_VOLUMERENDERING "@VTK_USE_RENDERING@") + +# The Tcl/Tk configuration. +SET(VTK_TCL_TK_STATIC "@VTK_TCL_TK_STATIC@") +SET(VTK_TCL_TK_COPY_SUPPORT_LIBRARY "@VTK_TCL_TK_COPY_SUPPORT_LIBRARY@") +SET(VTK_TCL_SUPPORT_LIBRARY_PATH "@VTK_TCL_SUPPORT_LIBRARY_PATH_CONFIG@") +SET(VTK_TK_SUPPORT_LIBRARY_PATH "@VTK_TK_SUPPORT_LIBRARY_PATH_CONFIG@") +SET(VTK_TCL_TK_MACROS_MODULE "@VTK_TCL_TK_MACROS_MODULE_CONFIG@") +SET(VTK_TCL_HOME "@VTK_TCL_HOME_CONFIG@") +SET(VTK_WRAP_TCL_EXE "@VTK_WRAP_TCL_EXE_CONFIG@") +SET(VTK_WRAP_TCL_INIT_EXE "@VTK_WRAP_TCL_INIT_EXE_CONFIG@") +SET(VTK_TK_INTERNAL_DIR "@VTK_TK_INTERNAL_DIR_CONFIG@") +SET(VTK_TK_RESOURCES_DIR "@VTK_TK_RESOURCES_DIR_CONFIG@") + +# The Java configuration. +SET(VTK_JAVA_JAR "@VTK_JAVA_JAR_CONFIG@") +SET(VTK_PARSE_JAVA_EXE "@VTK_PARSE_JAVA_EXE_CONFIG@") +SET(VTK_WRAP_JAVA_EXE "@VTK_WRAP_JAVA_EXE_CONFIG@") + +# The Python configuration. +SET(VTK_WRAP_PYTHON_EXE "@VTK_WRAP_PYTHON_EXE_CONFIG@") +SET(VTK_WRAP_PYTHON_INIT_EXE "@VTK_WRAP_PYTHON_INIT_EXE_CONFIG@") + +# The Doxygen configuration. +SET(VTK_DOXYGEN_HOME "@VTK_DOXYGEN_HOME_CONFIG@") + +# The VTK test script locations. +SET(VTK_HEADER_TESTING_PY "@VTK_HEADER_TESTING_PY_CONFIG@") +SET(VTK_FIND_STRING_TCL "@VTK_FIND_STRING_TCL_CONFIG@") +SET(VTK_PRINT_SELF_CHECK_TCL "@VTK_PRINT_SELF_CHECK_TCL_CONFIG@") +SET(VTK_RT_IMAGE_TEST_TCL "@VTK_RT_IMAGE_TEST_TCL_CONFIG@") +SET(VTK_PRT_IMAGE_TEST_TCL "@VTK_PRT_IMAGE_TEST_TCL_CONFIG@") + +# The names of utility libraries used by VTK. +SET(VTK_PNG_LIBRARIES "@VTK_PNG_LIBRARIES@") +SET(VTK_ZLIB_LIBRARIES "@VTK_ZLIB_LIBRARIES@") +SET(VTK_JPEG_LIBRARIES "@VTK_JPEG_LIBRARIES@") +SET(VTK_TIFF_LIBRARIES "@VTK_TIFF_LIBRARIES@") +SET(VTK_EXPAT_LIBRARIES "@VTK_EXPAT_LIBRARIES@") +SET(VTK_FREETYPE_LIBRARIES "@VTK_FREETYPE_LIBRARIES@") + +# The VTK Qt configuration. +IF(VTK_USE_QVTK) + INCLUDE(${VTK_DIR}/VTKConfigQt.cmake) +ENDIF(VTK_USE_QVTK) + +# A VTK install tree always provides one build configuration. A VTK +# build tree may provide either one or multiple build configurations +# depending on the CMake generator used. Since VTK can be used either +# from a build tree or an install tree it is useful for outside +# projects to know the configurations available. If this +# VTKConfig.cmake is in a VTK install tree VTK_CONFIGURATION_TYPES +# will be empty and VTK_BUILD_TYPE will be set to the value of +# CMAKE_BUILD_TYPE used to build VTK. If VTKConfig.cmake is in a VTK +# build tree then VTK_CONFIGURATION_TYPES and VTK_BUILD_TYPE will have +# values matching CMAKE_CONFIGURATION_TYPES and CMAKE_BUILD_TYPE for +# that build tree (only one will ever be set). +SET(VTK_CONFIGURATION_TYPES @VTK_CONFIGURATION_TYPES_CONFIG@) +SET(VTK_BUILD_TYPE @VTK_BUILD_TYPE_CONFIG@) + +# The VTK library dependencies. +IF(NOT VTK_NO_LIBRARY_DEPENDS AND EXISTS "@VTK_LIBRARY_DEPENDS_FILE@") + INCLUDE("@VTK_LIBRARY_DEPENDS_FILE@") +ENDIF(NOT VTK_NO_LIBRARY_DEPENDS AND EXISTS "@VTK_LIBRARY_DEPENDS_FILE@") + +# The old, less clear name for VTK_RUNTIME_LIBRARY_DIRS. Kept here +# for compatibility. +SET(VTK_RUNTIME_DIRS ${VTK_RUNTIME_LIBRARY_DIRS}) + +@VTK_CONFIG_BACKWARD_COMPATIBILITY_HACK@ diff --git a/VolumeRendering/CMakeLists.txt b/VolumeRendering/CMakeLists.txt new file mode 100644 index 0000000..1028c72 --- /dev/null +++ b/VolumeRendering/CMakeLists.txt @@ -0,0 +1,143 @@ +SET(KIT VolumeRendering) +SET(UKIT VOLUMERENDERING) + +SET(KIT_TCL_LIBS vtkRenderingTCL vtkIOTCL) +SET(KIT_PYTHON_LIBS vtkRenderingPythonD vtkIOPythonD) +SET(KIT_JAVA_LIBS vtkRenderingJava vtkIOJava) +SET(KIT_LIBS vtkRendering vtkIO) +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +SET ( Kit_SRCS +vtkDirectionEncoder.cxx +vtkEncodedGradientEstimator.cxx +vtkEncodedGradientShader.cxx +vtkFiniteDifferenceGradientEstimator.cxx +vtkFixedPointRayCastImage.cxx +vtkFixedPointVolumeRayCastCompositeGOHelper.cxx +vtkFixedPointVolumeRayCastCompositeGOShadeHelper.cxx +vtkFixedPointVolumeRayCastCompositeHelper.cxx +vtkFixedPointVolumeRayCastCompositeShadeHelper.cxx +vtkFixedPointVolumeRayCastHelper.cxx +vtkFixedPointVolumeRayCastMIPHelper.cxx +vtkFixedPointVolumeRayCastMapper.cxx +vtkProjectedTetrahedraMapper.cxx +vtkRayCastImageDisplayHelper.cxx +vtkRecursiveSphereDirectionEncoder.cxx +vtkSphericalDirectionEncoder.cxx +vtkVolumeMapper.cxx +vtkVolumeRayCastCompositeFunction.cxx +vtkVolumeRayCastFunction.cxx +vtkVolumeRayCastIsosurfaceFunction.cxx +vtkVolumeRayCastMIPFunction.cxx +vtkVolumeRayCastMapper.cxx +vtkVolumeRenderingFactory.cxx +vtkVolumeTextureMapper.cxx +vtkVolumeTextureMapper2D.cxx +vtkVolumeTextureMapper3D.cxx +vtkUnstructuredGridBunykRayCastFunction.cxx +vtkUnstructuredGridHomogeneousRayIntegrator.cxx +vtkUnstructuredGridLinearRayIntegrator.cxx +vtkUnstructuredGridPartialPreIntegration.cxx +vtkUnstructuredGridPreIntegration.cxx +vtkUnstructuredGridVolumeMapper.cxx +vtkUnstructuredGridVolumeRayCastFunction.cxx +vtkUnstructuredGridVolumeRayCastIterator.cxx +vtkUnstructuredGridVolumeRayIntegrator.cxx +vtkUnstructuredGridVolumeRayCastMapper.cxx +vtkUnstructuredGridVolumeZSweepMapper.cxx +) + +SET( KitOpenGL_SRCS + vtkOpenGLRayCastImageDisplayHelper.cxx + vtkOpenGLVolumeTextureMapper2D.cxx + vtkOpenGLVolumeTextureMapper3D.cxx +) + +#------------------------------------------------- +# Stuff we need for the vtkVolumeTextureMapper3D +#------------------------------------------------- + +# Create an executable to encode source files into C string literals. +ADD_EXECUTABLE(vtkVREncodeString + ${VTK_SOURCE_DIR}/VolumeRendering/vtkVREncodeString.cxx + ) +GET_TARGET_PROPERTY(ENCODE_EXE vtkVREncodeString LOCATION) + +# The set of source files to be encoded. +SET(asm_files + vtkVolumeTextureMapper3D_FourDependentNoShadeFP + vtkVolumeTextureMapper3D_FourDependentShadeFP + vtkVolumeTextureMapper3D_OneComponentNoShadeFP + vtkVolumeTextureMapper3D_OneComponentShadeFP + vtkVolumeTextureMapper3D_TwoDependentNoShadeFP + vtkVolumeTextureMapper3D_TwoDependentShadeFP + ) + +# Create custom commands to encode each assembly file into a C string +# literal in a header file. +FOREACH(file ${asm_files}) + SET(src ${VTK_SOURCE_DIR}/VolumeRendering/${file}.asm) + SET(res ${VTK_BINARY_DIR}/VolumeRendering/${file}.cxx) + ADD_CUSTOM_COMMAND( + OUTPUT ${res} + DEPENDS ${src} vtkVREncodeString + COMMAND ${ENCODE_EXE} + ARGS ${res} ${src} ${file} + ) + SET(Kit_EXTRA_SRCS ${Kit_EXTRA_SRCS} ${res}) +ENDFOREACH(file) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/vtkVolumeRenderingToolkit.h.in + ${CMAKE_CURRENT_BINARY_DIR}/vtkVolumeRenderingToolkit.h ) + +SET_SOURCE_FILES_PROPERTIES( +vtkDirectionEncoder +vtkEncodedGradientEstimator +vtkFixedPointVolumeRayCastHelper +vtkRayCastImageDisplayHelper +vtkVolumeMapper +vtkVolumeRayCastFunction +vtkVolumeTextureMapper +vtkUnstructuredGridVolumeMapper +vtkUnstructuredGridVolumeRayCastFunction +vtkUnstructuredGridVolumeRayCastIterator +vtkUnstructuredGridVolumeRayIntegrator +ABSTRACT +) + +IF (VTK_USE_MANGLED_MESA) + IF (MANGLED_MESA_LIBRARY) + SET ( KitOpenGL_SRCS ${KitOpenGL_SRCS} + vtkMesaRayCastImageDisplayHelper.cxx + vtkMesaVolumeTextureMapper2D.cxx + ) + SET (KIT_LIBS ${KIT_LIBS} ${MANGLED_MESA_LIBRARY}) + IF(MANGLED_OSMESA_LIBRARY) + SET( KIT_LIBS ${KIT_LIBS} ${MANGLED_OSMESA_LIBRARY} ) + ENDIF(MANGLED_OSMESA_LIBRARY) + ENDIF (MANGLED_MESA_LIBRARY) +ELSE (VTK_USE_MANGLED_MESA) + IF(VTK_OPENGL_HAS_OSMESA) + IF (OSMESA_LIBRARY) + SET(KIT_LIBS ${KIT_LIBS} ${OSMESA_LIBRARY}) + ENDIF (OSMESA_LIBRARY) + ENDIF(VTK_OPENGL_HAS_OSMESA) +ENDIF(VTK_USE_MANGLED_MESA) +SET(Kit_SRCS ${Kit_SRCS} ${KitOpenGL_SRCS}) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- + +# Make sure vtkRendering is built before vtkVolumeRendering builds. +# This will make sure vtkgl.h exists. +ADD_DEPENDENCIES(vtkVolumeRendering vtkRendering) + diff --git a/VolumeRendering/Testing/CMakeLists.txt b/VolumeRendering/Testing/CMakeLists.txt new file mode 100644 index 0000000..ce66986 --- /dev/null +++ b/VolumeRendering/Testing/CMakeLists.txt @@ -0,0 +1,19 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) + SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-VolumeRendering ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/VolumeRendering" + VTK_VOLUMERENDERING_EXPORT + vtkVolumeShearWarpDataStructure.h + vtkVolumeProMapper.h + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/VolumeRendering/Testing/Cxx/CMakeLists.txt b/VolumeRendering/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..18a3bd2 --- /dev/null +++ b/VolumeRendering/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,41 @@ +# if we are using the display add the tests +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + SET(KIT VolumeRendering) + # add tests that do not require data + SET(MyTests) + IF (VTK_DATA_ROOT) + # add tests that require data + SET(MyTests + HomogeneousRayIntegration.cxx + LinearRayIntegration.cxx + PartialPreIntegration.cxx + PreIntegrationIncremental.cxx + PreIntegrationNonIncremental.cxx + TestProjectedTetrahedra.cxx + volProt.cxx + ) + SET(MyTestSupport + ExerciseUnstructuredGridRayCastMapper.cxx + ) + ENDIF (VTK_DATA_ROOT) + CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx ${MyTests} + EXTRA_INCLUDE vtkTestDriver.h) + ADD_EXECUTABLE(${KIT}CxxTests ${Tests} ${MyTestSupport} ) + TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkVolumeRendering) + SET (TestsToRun ${Tests}) + REMOVE (TestsToRun ${KIT}CxxTests.cxx) + + # + # Add all the executables + FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + IF (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName} + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/${KIT}/${TName}.png) + ELSE (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) + ENDIF (VTK_DATA_ROOT) + ENDFOREACH (test) +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) diff --git a/VolumeRendering/Testing/Cxx/ExerciseUnstructuredGridRayCastMapper.cxx b/VolumeRendering/Testing/Cxx/ExerciseUnstructuredGridRayCastMapper.cxx new file mode 100644 index 0000000..c8d81a4 --- /dev/null +++ b/VolumeRendering/Testing/Cxx/ExerciseUnstructuredGridRayCastMapper.cxx @@ -0,0 +1,492 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ExerciseUnstructuredGridRayCastMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "ExerciseUnstructuredGridRayCastMapper.h" + +#include "vtkActor.h" +#include "vtkArrayCalculator.h" +#include "vtkAssignAttribute.h" +#include "vtkCamera.h" +#include "vtkCellData.h" +#include "vtkColorTransferFunction.h" +#include "vtkCubeSource.h" +#include "vtkDataSet.h" +#include "vtkDataSetTriangleFilter.h" +#include "vtkDoubleArray.h" +#include "vtkImageMandelbrotSource.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" +#include "vtkPointData.h" +#include "vtkPointDataToCellData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkUnstructuredGridVolumeRayCastFunction.h" +#include "vtkUnstructuredGridVolumeRayCastMapper.h" +#include "vtkUnstructuredGridVolumeRayIntegrator.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" + +#include "vtkRegressionTestImage.h" + +//============================================================================= + +// A simple filter that will convert an array from independent scalars +// to dependent scalars. +class vtkClassifyVolume : public vtkDataSetAlgorithm +{ +public: + vtkTypeRevisionMacro(vtkClassifyVolume, vtkDataSetAlgorithm); + static vtkClassifyVolume *New(); + + vtkGetObjectMacro(TransferFunction, vtkVolumeProperty); + vtkSetObjectMacro(TransferFunction, vtkVolumeProperty); + +protected: + vtkClassifyVolume(); + ~vtkClassifyVolume(); + + virtual int RequestData(vtkInformation *, vtkInformationVector **, + vtkInformationVector *); + + virtual void Classify(vtkDataSetAttributes *in, vtkDataSetAttributes *out); + + vtkVolumeProperty *TransferFunction; + +private: + vtkClassifyVolume(const vtkClassifyVolume&); // Not implemented + void operator=(const vtkClassifyVolume&); // Not implemented +}; + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkClassifyVolume, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkClassifyVolume); + +vtkClassifyVolume::vtkClassifyVolume() +{ + this->TransferFunction = NULL; +} + +vtkClassifyVolume::~vtkClassifyVolume() +{ + this->SetTransferFunction(NULL); +} + +//----------------------------------------------------------------------------- + +int vtkClassifyVolume::RequestData(vtkInformation *, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) +{ + vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkInformation *outInfo = outputVector->GetInformationObject(0); + vtkDataSet *output = vtkDataSet::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + output->CopyStructure(input); + this->Classify(input->GetPointData(), output->GetPointData()); + this->Classify(input->GetCellData(), output->GetCellData()); + + return 1; +} + +//----------------------------------------------------------------------------- + +void vtkClassifyVolume::Classify(vtkDataSetAttributes *inAttrib, + vtkDataSetAttributes *outAttrib) +{ + vtkDataArray *scalars = inAttrib->GetScalars(); + if (!scalars) return; + + if (scalars->GetNumberOfComponents() != 1) + { + vtkErrorMacro(<< "Only 1-tuple scalars are supported now."); + return; + } + vtkIdType numScalars = scalars->GetNumberOfTuples(); + + vtkDoubleArray *colors = vtkDoubleArray::New(); + colors->SetName(scalars->GetName()); + + if (this->TransferFunction->GetColorChannels() == 3) + { + colors->SetNumberOfComponents(4); + colors->SetNumberOfTuples(numScalars); + + vtkColorTransferFunction *rgb + = this->TransferFunction->GetRGBTransferFunction(); + vtkPiecewiseFunction *alpha = this->TransferFunction->GetScalarOpacity(); + + for (vtkIdType i = 0; i < numScalars; i++) + { + double c[4]; + double x = scalars->GetComponent(i, 0); + rgb->GetColor(x, c); + c[3] = alpha->GetValue(x); + colors->SetTuple(i, c); + } + } + else + { + vtkErrorMacro(<< "Gray values are not supported now."); + } + + outAttrib->SetScalars(colors); + colors->Delete(); +} + +//============================================================================= + +static vtkRenderer *NewTestViewport(RayCastFunctionCreator NewFunction, + RayIntegratorCreator NewIntegrator, + vtkVolumeProperty *volumeProperty, + int UseCellData, int UseDependentComponents, + int UseMultipleTransferFunctions) +{ + // Create the render window. + vtkRenderer *ren = vtkRenderer::New(); + + // Create a small mesh. The coarser and more opaque the mesh, the easier it + // is to see rendering errors. + vtkImageMandelbrotSource *input = vtkImageMandelbrotSource::New(); + input->SetWholeExtent(0, 2, 0, 2, 0, 2); + input->SetSizeCX(2, 2, 2, 2); + input->SetMaximumNumberOfIterations(10); + vtkAlgorithmOutput *outputPort = input->GetOutputPort(0); + + // Make sure we have only tetrahedra. + vtkDataSetTriangleFilter *trifilter = vtkDataSetTriangleFilter::New(); + trifilter->SetInputConnection(0, outputPort); + outputPort = trifilter->GetOutputPort(0); + + // Make multiple scalars if necessary. + vtkArrayCalculator *calc = NULL; + vtkAssignAttribute *assign = NULL; + if (UseMultipleTransferFunctions) + { + calc = vtkArrayCalculator::New(); + calc->AddScalarArrayName("Iterations"); + calc->SetResultArrayName("Result"); + calc->SetFunction("Iterations*iHat + (10-Iterations)*jHat"); + calc->SetInputConnection(0, outputPort); + outputPort = calc->GetOutputPort(0); + + assign = vtkAssignAttribute::New(); + assign->Assign(vtkDataSetAttributes::VECTORS, vtkDataSetAttributes::SCALARS, + vtkAssignAttribute::POINT_DATA); + assign->SetInputConnection(0, outputPort); + outputPort = assign->GetOutputPort(0); + } + + // Convert to cell centered data if requested. + vtkPointDataToCellData *celldata = NULL; + if (UseCellData) + { + celldata = vtkPointDataToCellData::New(); + celldata->SetInputConnection(0, outputPort); + celldata->PassPointDataOff(); + outputPort = celldata->GetOutputPort(0); + } + + // Classify the data if testing dependent components. + vtkClassifyVolume *classify = NULL; + if (UseDependentComponents) + { + classify = vtkClassifyVolume::New(); + classify->SetTransferFunction(volumeProperty); + classify->SetInputConnection(0, outputPort); + outputPort = classify->GetOutputPort(0); + } + + // Set up the mapper. + vtkUnstructuredGridVolumeRayCastMapper *mapper + = vtkUnstructuredGridVolumeRayCastMapper::New(); + mapper->SetInputConnection(0, outputPort); + if (NewFunction) + { + vtkUnstructuredGridVolumeRayCastFunction *function = NewFunction(); + mapper->SetRayCastFunction(function); + function->Delete(); + } + if (NewIntegrator) + { + vtkUnstructuredGridVolumeRayIntegrator *integrator = NewIntegrator(); + mapper->SetRayIntegrator(integrator); + integrator->Delete(); + } + + // The volume holds the mapper and property and can be used to position/orient + // the volume. + vtkVolume *volume = vtkVolume::New(); + volume->SetMapper(mapper); + if (!UseDependentComponents) + { + volume->SetProperty(volumeProperty); + } + else + { + // Set up a volume property that does not have the transfer function. + vtkVolumeProperty *vp = vtkVolumeProperty::New(); + vp->SetShade(volumeProperty->GetShade()); + vp->SetInterpolationType(volumeProperty->GetInterpolationType()); + vp->SetScalarOpacityUnitDistance( + volumeProperty->GetScalarOpacityUnitDistance()); + vp->IndependentComponentsOff(); + volume->SetProperty(vp); + vp->Delete(); + } + + // Add the volume to the renderer. + ren->AddVolume(volume); + + ren->ResetCamera(); + ren->GetActiveCamera()->Azimuth(20.0); + ren->GetActiveCamera()->Elevation(15.0); + ren->GetActiveCamera()->Zoom(1.5); + + // Delete objects. Will not actually be destroyed due to reference counting. + input->Delete(); + trifilter->Delete(); + if (celldata) celldata->Delete(); + if (calc) calc->Delete(); + if (assign) assign->Delete(); + if (classify) classify->Delete(); + mapper->Delete(); + volume->Delete(); + + return ren; +} + +//----------------------------------------------------------------------------- + +static vtkRenderer *NewPlaceholderViewport() +{ + vtkRenderer *ren = vtkRenderer::New(); + + vtkCubeSource *cube = vtkCubeSource::New(); + + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(0, cube->GetOutputPort(0)); + cube->Delete(); + + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + mapper->Delete(); + + ren->AddActor(actor); + ren->ResetCamera(); + actor->Delete(); + + return ren; +} + +//----------------------------------------------------------------------------- + +static vtkVolumeProperty *NewRGBVolumeProperty() +{ + // Create transfer mapping scalar value to opacity. + vtkPiecewiseFunction *opacityTransferFunction = vtkPiecewiseFunction::New(); + opacityTransferFunction->AddPoint( 0.0, 0.0); + opacityTransferFunction->AddPoint(10.0, 1.0); + + // Create transfer mapping scalar value to color. + vtkColorTransferFunction *colorTransferFunction + = vtkColorTransferFunction::New(); + colorTransferFunction->SetColorSpaceToHSV(); + colorTransferFunction->HSVWrapOn(); + colorTransferFunction->AddHSVPoint( 0.0, 4.0/6.0, 1.0, 1.0); + colorTransferFunction->AddHSVPoint( 4.0, 2.0/6.0, 1.0, 1.0); + colorTransferFunction->AddHSVPoint( 6.0, 1.0/6.0, 1.0, 1.0); + colorTransferFunction->AddHSVPoint(10.0, 5.0/6.0, 1.0, 1.0); + + vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New(); + volumeProperty->SetColor(colorTransferFunction); + volumeProperty->SetScalarOpacity(opacityTransferFunction); + volumeProperty->ShadeOff(); + volumeProperty->SetInterpolationTypeToLinear(); + volumeProperty->SetScalarOpacityUnitDistance(0.75); + + // Delete objects. Will not actually be destroyed due to reference counting. + opacityTransferFunction->Delete(); + colorTransferFunction->Delete(); + + return volumeProperty; +} + +//----------------------------------------------------------------------------- + +static vtkVolumeProperty *NewGrayVolumeProperty() +{ + // Create transfer mapping scalar value to opacity. + vtkPiecewiseFunction *opacityTransferFunction = vtkPiecewiseFunction::New(); + opacityTransferFunction->AddPoint( 0.0, 0.0); + opacityTransferFunction->AddPoint(10.0, 1.0); + + // Create transfer mapping scalar value to color. + vtkPiecewiseFunction *grayTransferFunction = vtkPiecewiseFunction::New(); + grayTransferFunction->AddPoint( 0.0, 0.0); + grayTransferFunction->AddPoint(10.0, 1.0); + + vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New(); + volumeProperty->SetColor(grayTransferFunction); + volumeProperty->SetScalarOpacity(opacityTransferFunction); + volumeProperty->ShadeOff(); + volumeProperty->SetInterpolationTypeToLinear(); + volumeProperty->SetScalarOpacityUnitDistance(0.75); + + // Delete objects. Will not actually be destroyed due to reference counting. + opacityTransferFunction->Delete(); + grayTransferFunction->Delete(); + + return volumeProperty; +} + +//----------------------------------------------------------------------------- + +static vtkVolumeProperty *NewMultiTFVolumeProperty() +{ + vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New(); + volumeProperty->ShadeOff(); + volumeProperty->SetInterpolationTypeToLinear(); + volumeProperty->SetScalarOpacityUnitDistance(0.75); + + vtkColorTransferFunction *rgb; + vtkPiecewiseFunction *a; + + // Create first tf. + rgb = vtkColorTransferFunction::New(); + rgb->AddRGBPoint(0.0, 1.0, 0.0, 0.0); + volumeProperty->SetColor(0, rgb); + rgb->Delete(); + + a = vtkPiecewiseFunction::New(); + a->AddPoint(2.9, 0.0); + a->AddPoint(3.0, 1.0); + volumeProperty->SetScalarOpacity(0, a); + a->Delete(); + + // Create second tf. + rgb = vtkColorTransferFunction::New(); + rgb->AddRGBPoint(0.0, 0.0, 1.0, 1.0); + volumeProperty->SetColor(1, rgb); + rgb->Delete(); + + a = vtkPiecewiseFunction::New(); + a->AddPoint(4.9, 0.0); + a->AddPoint(5.0, 0.5); + volumeProperty->SetScalarOpacity(1, a); + a->Delete(); + + // Create third tf. + rgb = vtkColorTransferFunction::New(); + rgb->AddRGBPoint(0.0, 0.0, 0.0, 0.0); + volumeProperty->SetColor(2, rgb); + rgb->Delete(); + + a = vtkPiecewiseFunction::New(); + a->AddPoint(0.0, 0.0); + volumeProperty->SetScalarOpacity(2, a); + a->Delete(); + + return volumeProperty; +} + +//----------------------------------------------------------------------------- + +int ExerciseUnstructuredGridRayCastMapper(int argc, char *argv[], + RayCastFunctionCreator NewFunction, + RayIntegratorCreator NewIntegrator, + int UseCellData, + int TestDependentComponents) +{ + // Create the standard render window and interactor. + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->SetSize(300, 300); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + iren->SetDesiredUpdateRate(3.0); + + // The property describes how the data will look. Establish various + // rendering modes with the property and its transfer functions. + vtkVolumeProperty *volumeProperty; + vtkRenderer *viewport; + + // RGB transfer function. + volumeProperty = NewRGBVolumeProperty(); + viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty, + UseCellData, 0, 0); + if (!viewport) return -1; + viewport->SetViewport(0.0, 0.0, 0.5, 0.5); + renWin->AddRenderer(viewport); + volumeProperty->Delete(); + viewport->Delete(); + + // Gray transfer function. + volumeProperty = NewGrayVolumeProperty(); + viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty, + UseCellData, 0, 0); + if (!viewport) return -1; + viewport->SetViewport(0.5, 0.0, 1.0, 0.5); + renWin->AddRenderer(viewport); + volumeProperty->Delete(); + viewport->Delete(); + + if (TestDependentComponents) + { + // RGBA dependent components. + volumeProperty = NewRGBVolumeProperty(); + viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty, + UseCellData, 1, 0); + volumeProperty->Delete(); + } + else + { + viewport = NewPlaceholderViewport(); + } + if (!viewport) return -1; + viewport->SetViewport(0.0, 0.5, 0.5, 1.0); + renWin->AddRenderer(viewport); + viewport->Delete(); + + // Multiple transfer functions + volumeProperty = NewMultiTFVolumeProperty(); + viewport = NewTestViewport(NewFunction, NewIntegrator, volumeProperty, + UseCellData, 0, 1); + if (!viewport) return -1; + viewport->SetViewport(0.5, 0.5, 1.0, 1.0); + renWin->AddRenderer(viewport); + volumeProperty->Delete(); + viewport->Delete(); + + int retVal = vtkRegressionTestImageThreshold(renWin, 70); + if (retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Delete objects. + renWin->Delete(); + iren->Delete(); + + return !retVal; +} diff --git a/VolumeRendering/Testing/Cxx/ExerciseUnstructuredGridRayCastMapper.h b/VolumeRendering/Testing/Cxx/ExerciseUnstructuredGridRayCastMapper.h new file mode 100644 index 0000000..63e6cdd --- /dev/null +++ b/VolumeRendering/Testing/Cxx/ExerciseUnstructuredGridRayCastMapper.h @@ -0,0 +1,36 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ExerciseUnstructuredGridRayCastMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#ifndef _ExerciseUnstructuredGridRayCastMapper_h +#define _ExerciseUnstructuredGridRayCastMapper_h + +#include "stdlib.h" + +class vtkUnstructuredGridVolumeRayCastFunction; +class vtkUnstructuredGridVolumeRayIntegrator; + +typedef vtkUnstructuredGridVolumeRayCastFunction *(*RayCastFunctionCreator)(void); +typedef vtkUnstructuredGridVolumeRayIntegrator *(*RayIntegratorCreator)(void); + +// Exercises the unstructured grid ray cast mapper with the given function +// and integrator. +int ExerciseUnstructuredGridRayCastMapper( + int argc, char *argv[], + RayCastFunctionCreator NewFunction = NULL, + RayIntegratorCreator NewIntegrator = NULL, + int UseCellData = 0, + int TestDependentComponents = 1); + +#endif diff --git a/VolumeRendering/Testing/Cxx/HomogeneousRayIntegration.cxx b/VolumeRendering/Testing/Cxx/HomogeneousRayIntegration.cxx new file mode 100644 index 0000000..099ae1c --- /dev/null +++ b/VolumeRendering/Testing/Cxx/HomogeneousRayIntegration.cxx @@ -0,0 +1,30 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: HomogeneousRayIntegration.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "ExerciseUnstructuredGridRayCastMapper.h" + +#include "vtkUnstructuredGridHomogeneousRayIntegrator.h" + +static vtkUnstructuredGridVolumeRayIntegrator *CreateHomogeneousRayIntegrator() +{ + return vtkUnstructuredGridHomogeneousRayIntegrator::New(); +} + +int HomogeneousRayIntegration(int argc, char *argv[]) +{ + return ExerciseUnstructuredGridRayCastMapper(argc, argv, NULL, + CreateHomogeneousRayIntegrator, + 1); +} diff --git a/VolumeRendering/Testing/Cxx/LinearRayIntegration.cxx b/VolumeRendering/Testing/Cxx/LinearRayIntegration.cxx new file mode 100644 index 0000000..eb73834 --- /dev/null +++ b/VolumeRendering/Testing/Cxx/LinearRayIntegration.cxx @@ -0,0 +1,29 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: LinearRayIntegration.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "ExerciseUnstructuredGridRayCastMapper.h" + +#include "vtkUnstructuredGridLinearRayIntegrator.h" + +static vtkUnstructuredGridVolumeRayIntegrator *CreateLinearRayIntegrator() +{ + return vtkUnstructuredGridLinearRayIntegrator::New(); +} + +int LinearRayIntegration(int argc, char *argv[]) +{ + return ExerciseUnstructuredGridRayCastMapper(argc, argv, NULL, + CreateLinearRayIntegrator); +} diff --git a/VolumeRendering/Testing/Cxx/PartialPreIntegration.cxx b/VolumeRendering/Testing/Cxx/PartialPreIntegration.cxx new file mode 100644 index 0000000..a74098c --- /dev/null +++ b/VolumeRendering/Testing/Cxx/PartialPreIntegration.cxx @@ -0,0 +1,29 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: PartialPreIntegration.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "ExerciseUnstructuredGridRayCastMapper.h" + +#include "vtkUnstructuredGridPartialPreIntegration.h" + +static vtkUnstructuredGridVolumeRayIntegrator *CreatePartialPreIntegration() +{ + return vtkUnstructuredGridPartialPreIntegration::New(); +} + +int PartialPreIntegration(int argc, char *argv[]) +{ + return ExerciseUnstructuredGridRayCastMapper(argc, argv, NULL, + CreatePartialPreIntegration); +} diff --git a/VolumeRendering/Testing/Cxx/PreIntegrationIncremental.cxx b/VolumeRendering/Testing/Cxx/PreIntegrationIncremental.cxx new file mode 100644 index 0000000..f6880d1 --- /dev/null +++ b/VolumeRendering/Testing/Cxx/PreIntegrationIncremental.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: PreIntegrationIncremental.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "ExerciseUnstructuredGridRayCastMapper.h" + +#include "vtkUnstructuredGridPreIntegration.h" + +static vtkUnstructuredGridVolumeRayIntegrator *CreatePreIntegration() +{ + vtkUnstructuredGridPreIntegration *integrator = + vtkUnstructuredGridPreIntegration::New(); + integrator->IncrementalPreIntegrationOn(); + return integrator; +} + +int PreIntegrationIncremental(int argc, char *argv[]) +{ + return ExerciseUnstructuredGridRayCastMapper(argc, argv, NULL, + CreatePreIntegration, 0, 0); +} diff --git a/VolumeRendering/Testing/Cxx/PreIntegrationNonIncremental.cxx b/VolumeRendering/Testing/Cxx/PreIntegrationNonIncremental.cxx new file mode 100644 index 0000000..f81ff46 --- /dev/null +++ b/VolumeRendering/Testing/Cxx/PreIntegrationNonIncremental.cxx @@ -0,0 +1,39 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: PreIntegrationNonIncremental.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "ExerciseUnstructuredGridRayCastMapper.h" + +#include "vtkUnstructuredGridPreIntegration.h" + +static vtkUnstructuredGridVolumeRayIntegrator *CreatePreIntegration() +{ + vtkUnstructuredGridPreIntegration *integrator = + vtkUnstructuredGridPreIntegration::New(); + + // Turn off incremental building of the table. + integrator->IncrementalPreIntegrationOff(); + + // Make the table much smaller since it takes much longer to build. + integrator->SetIntegrationTableScalarResolution(32); + integrator->SetIntegrationTableLengthResolution(64); + + return integrator; +} + +int PreIntegrationNonIncremental(int argc, char *argv[]) +{ + return ExerciseUnstructuredGridRayCastMapper(argc, argv, NULL, + CreatePreIntegration, 0, 0); +} diff --git a/VolumeRendering/Testing/Cxx/TestProjectedTetrahedra.cxx b/VolumeRendering/Testing/Cxx/TestProjectedTetrahedra.cxx new file mode 100644 index 0000000..0da5ab2 --- /dev/null +++ b/VolumeRendering/Testing/Cxx/TestProjectedTetrahedra.cxx @@ -0,0 +1,192 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestProjectedTetrahedra.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkProjectedTetrahedraMapper.h" + +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkStructuredPointsReader.h" +#include "vtkSLCReader.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" +#include "vtkThreshold.h" +#include "vtkDataSetTriangleFilter.h" +#include "vtkPiecewiseFunction.h" +#include "vtkColorTransferFunction.h" +#include "vtkVolumeProperty.h" +#include "vtkVolume.h" +#include "vtkContourFilter.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkRegressionTestImage.h" +#include "vtkStdString.h" + +int TestProjectedTetrahedra(int argc, char *argv[]) +{ + int i; + // Need to get the data root. + const char *data_root = NULL; + for (i = 0; i < argc-1; i++) + { + if (strcmp("-D", argv[i]) == 0) + { + data_root = argv[i+1]; + break; + } + } + if (!data_root) + { + cout << "Need to specify the directory to VTK_DATA_ROOT with -D <dir>." << endl; + return 1; + } + + // Create the standard renderer, render window, and interactor. + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + iren->SetDesiredUpdateRate(3); + + // Create the reader for the data. + // This is the data that will be volume rendered. + vtkStdString filename; + filename = data_root; + filename += "/Data/ironProt.vtk"; + cout << "Loading " << filename.c_str() << endl; + vtkStructuredPointsReader *reader = vtkStructuredPointsReader::New(); + reader->SetFileName(filename.c_str()); + + // Create a reader for the other data that will be contoured and + // displayed as a polygonal mesh. + filename = data_root; + filename += "/Data/neghip.slc"; + cout << "Loading " << filename.c_str() << endl; + vtkSLCReader *reader2 = vtkSLCReader::New(); + reader2->SetFileName(filename.c_str()); + + // Convert from vtkImageData to vtkUnstructuredGrid. + // Remove any cells where all values are below 80. + vtkThreshold *thresh = vtkThreshold::New(); + thresh->ThresholdByUpper(80); + thresh->AllScalarsOff(); + thresh->SetInputConnection(reader->GetOutputPort()); + + // Make sure we have only tetrahedra. + vtkDataSetTriangleFilter *trifilter = vtkDataSetTriangleFilter::New(); + trifilter->SetInputConnection(thresh->GetOutputPort()); + + // Create transfer mapping scalar value to opacity. + vtkPiecewiseFunction *opacityTransferFunction = vtkPiecewiseFunction::New(); + opacityTransferFunction->AddPoint(80.0, 0.0); + opacityTransferFunction->AddPoint(120.0, 0.2); + opacityTransferFunction->AddPoint(255.0, 0.2); + + // Create transfer mapping scalar value to color. + vtkColorTransferFunction *colorTransferFunction + = vtkColorTransferFunction::New(); + colorTransferFunction->AddRGBPoint(80.0, 0.0, 0.0, 0.0); + colorTransferFunction->AddRGBPoint(120.0, 0.0, 0.0, 1.0); + colorTransferFunction->AddRGBPoint(160.0, 1.0, 0.0, 0.0); + colorTransferFunction->AddRGBPoint(200.0, 0.0, 1.0, 0.0); + colorTransferFunction->AddRGBPoint(255.0, 0.0, 1.0, 1.0); + + // The property describes how the data will look. + vtkVolumeProperty *volumeProperty = vtkVolumeProperty::New(); + volumeProperty->SetColor(colorTransferFunction); + volumeProperty->SetScalarOpacity(opacityTransferFunction); + volumeProperty->ShadeOff(); + volumeProperty->SetInterpolationTypeToLinear(); + + // The mapper that renders the volume data. + vtkProjectedTetrahedraMapper *volumeMapper + = vtkProjectedTetrahedraMapper::New(); + volumeMapper->SetInputConnection(trifilter->GetOutputPort()); + + // The volume holds the mapper and the property and can be used to + // position/orient the volume. + vtkVolume *volume = vtkVolume::New(); + volume->SetMapper(volumeMapper); + volume->SetProperty(volumeProperty); + + // Contour the second dataset. + vtkContourFilter *contour = vtkContourFilter::New(); + contour->SetValue(0, 80); + contour->SetInputConnection(reader2->GetOutputPort()); + + // Create a mapper for the polygonal data. + vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); + mapper->SetInputConnection(contour->GetOutputPort()); + mapper->ScalarVisibilityOff(); + + // Create an actor for the polygonal data. + vtkActor *actor = vtkActor::New(); + actor->SetMapper(mapper); + + ren1->AddViewProp(actor); + ren1->AddVolume(volume); + + renWin->SetSize(300, 300); + + ren1->ResetCamera(); + ren1->GetActiveCamera()->Azimuth(20.0); + ren1->GetActiveCamera()->Elevation(10.0); + ren1->GetActiveCamera()->Zoom(1.5); + + renWin->Render(); + + int retVal = vtkTesting::Test(argc, argv, renWin, 75); + if (retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up. + ren1->Delete(); + renWin->Delete(); + iren->Delete(); + reader->Delete(); + reader2->Delete(); + thresh->Delete(); + trifilter->Delete(); + opacityTransferFunction->Delete(); + colorTransferFunction->Delete(); + volumeProperty->Delete(); + volumeMapper->Delete(); + volume->Delete(); + contour->Delete(); + mapper->Delete(); + actor->Delete(); + + if ((retVal == vtkTesting::PASSED) || (retVal == vtkTesting::DO_INTERACTOR)) + { + return 0; + } + else + { + return 1; + } +} diff --git a/VolumeRendering/Testing/Cxx/volProt.cxx b/VolumeRendering/Testing/Cxx/volProt.cxx new file mode 100644 index 0000000..588499e --- /dev/null +++ b/VolumeRendering/Testing/Cxx/volProt.cxx @@ -0,0 +1,316 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: volProt.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCamera.h" +#include "vtkFiniteDifferenceGradientEstimator.h" +#include "vtkPiecewiseFunction.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkStructuredPoints.h" +#include "vtkStructuredPointsReader.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkVolumeRayCastCompositeFunction.h" +#include "vtkVolumeRayCastIsosurfaceFunction.h" +#include "vtkVolumeRayCastMIPFunction.h" +#include "vtkVolumeRayCastMapper.h" +#include "vtkVolumeTextureMapper2D.h" +#include "vtkColorTransferFunction.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +// Create an 8x7 grid of render windows in a renderer and render a volume +// using various techniques for testing purposes +int volProt( int argc, char *argv[] ) +{ + int i, j, k, l; + + // Create the renderers, render window, and interactor + vtkRenderWindow *renWin = vtkRenderWindow::New(); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + vtkRenderer *ren = vtkRenderer::New(); + renWin->AddRenderer(ren); + + // Read the data from a vtk file + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/ironProt.vtk"); + vtkStructuredPointsReader *reader = vtkStructuredPointsReader::New(); + reader->SetFileName(fname); + reader->Update(); + delete [] fname; + + // Create a transfer function mapping scalar value to opacity + vtkPiecewiseFunction *oTFun = vtkPiecewiseFunction::New(); + oTFun->AddSegment(10, 0.0, 255, 0.3); + + vtkPiecewiseFunction *oTFun2 = vtkPiecewiseFunction::New(); + oTFun2->AddSegment( 0, 0.0, 128, 1.0); + oTFun2->AddSegment(128, 1.0, 255, 0.0); + + // Create a transfer function mapping scalar value to color (grey) + vtkPiecewiseFunction *gTFun = vtkPiecewiseFunction::New(); + gTFun->AddSegment(0, 1.0, 255, 1.0); + + // Create a transfer function mapping scalar value to color (color) + vtkColorTransferFunction *cTFun = vtkColorTransferFunction::New(); + cTFun->AddRGBPoint( 0, 1.0, 0.0, 0.0 ); + cTFun->AddRGBPoint( 64, 1.0, 1.0, 0.0 ); + cTFun->AddRGBPoint( 128, 0.0, 1.0, 0.0 ); + cTFun->AddRGBPoint( 192, 0.0, 1.0, 1.0 ); + cTFun->AddRGBPoint( 255, 0.0, 0.0, 1.0 ); + + // Create a transfer function mapping magnitude of gradient to opacity + vtkPiecewiseFunction *goTFun = vtkPiecewiseFunction::New(); + goTFun->AddPoint( 0, 0.0 ); + goTFun->AddPoint( 30, 0.0 ); + goTFun->AddPoint( 40, 1.0 ); + goTFun->AddPoint( 255, 1.0 ); + + // Create a set of properties with varying options + vtkVolumeProperty *prop[16]; + int index = 0; + for ( l = 0; l < 2; l++ ) + { + for ( k = 0; k < 2; k++ ) + { + for ( j = 0; j < 2; j++ ) + { + for ( i = 0; i < 2; i++ ) + { + prop[index] = vtkVolumeProperty::New(); + prop[index]->SetShade(k); + prop[index]->SetAmbient(0.3); + prop[index]->SetDiffuse(1.0); + prop[index]->SetSpecular(0.2); + prop[index]->SetSpecularPower(50.0); + prop[index]->SetScalarOpacity(oTFun); + + if ( l ) + { + prop[index]->SetGradientOpacity( goTFun ); + } + + if ( j ) + { + prop[index]->SetColor( cTFun ); + } + else + { + prop[index]->SetColor( gTFun ); + } + + if ( i ) + { + prop[index]->SetInterpolationTypeToNearest(); + } + else + { + prop[index]->SetInterpolationTypeToLinear(); + } + + index++; + } + } + } + } + + // Create a set of properties for mip + vtkVolumeProperty *mipprop[4]; + index = 0; + for ( j = 0; j < 2; j++ ) + { + for ( i = 0; i < 2; i++ ) + { + mipprop[index] = vtkVolumeProperty::New(); + mipprop[index]->SetScalarOpacity(oTFun2); + + if ( j ) + { + mipprop[index]->SetColor( cTFun ); + } + else + { + mipprop[index]->SetColor( gTFun ); + } + + if ( i ) + { + mipprop[index]->SetInterpolationTypeToNearest(); + } + else + { + mipprop[index]->SetInterpolationTypeToLinear(); + } + + index++; + } + } + + + + // Create compositing ray functions + vtkVolumeRayCastCompositeFunction *compositeFunction1 = + vtkVolumeRayCastCompositeFunction::New(); + compositeFunction1->SetCompositeMethodToInterpolateFirst(); + + vtkVolumeRayCastCompositeFunction *compositeFunction2 = + vtkVolumeRayCastCompositeFunction::New(); + compositeFunction2->SetCompositeMethodToClassifyFirst(); + + + // Create mip ray functions + vtkVolumeRayCastMIPFunction *MIPFunction1 = + vtkVolumeRayCastMIPFunction::New(); + MIPFunction1->SetMaximizeMethodToScalarValue(); + + vtkVolumeRayCastMIPFunction *MIPFunction2 = + vtkVolumeRayCastMIPFunction::New(); + MIPFunction2->SetMaximizeMethodToOpacity(); + + // Create an isosurface ray function + vtkVolumeRayCastIsosurfaceFunction *isosurfaceFunction = + vtkVolumeRayCastIsosurfaceFunction::New(); + isosurfaceFunction->SetIsoValue(80); + + vtkFiniteDifferenceGradientEstimator *gradest = + vtkFiniteDifferenceGradientEstimator::New(); + + // Create 56 volumes + vtkVolume *volume[56]; + index = 0; + for ( j = 0; j < 7; j++ ) + { + for ( i = 0; i < 8; i++ ) + { + volume[index] = vtkVolume::New(); + volume[index]->AddPosition( i*70, j*70, 0 ); + ren->AddViewProp(volume[index]); + index++; + } + } + + + // Create 48 ray cast mappers - 32 composite, 8 mip, 8 isosurface + vtkVolumeRayCastMapper *raycastMapper[48]; + for ( i = 0; i < 48; i++ ) + { + raycastMapper[i] = vtkVolumeRayCastMapper::New(); + raycastMapper[i]->SetInputConnection(reader->GetOutputPort()); + raycastMapper[i]->SetGradientEstimator(gradest); + volume[i]->SetMapper( raycastMapper[i] ); + + if ( i < 16 ) + { + volume[i]->SetProperty( prop[i] ); + raycastMapper[i]->SetVolumeRayCastFunction( compositeFunction1 ); + } + else if ( i < 32 ) + { + volume[i]->SetProperty( prop[i-16] ); + raycastMapper[i]->SetVolumeRayCastFunction( compositeFunction2 ); + } + else + { + if ( i < 36 ) + { + raycastMapper[i]->SetVolumeRayCastFunction( MIPFunction1 ); + volume[i]->SetProperty( mipprop[i-32] ); + } + else if ( i < 40 ) + { + raycastMapper[i]->SetVolumeRayCastFunction( MIPFunction2 ); + volume[i]->SetProperty( mipprop[i-36] ); + } + else + { + raycastMapper[i]->SetVolumeRayCastFunction( isosurfaceFunction ); + volume[i]->SetProperty( prop[i-40] ); + } + } + } + + // Create 8 texture mappers + vtkVolumeTextureMapper2D *textureMapper[8]; + for ( i = 0; i < 8; i++ ) + { + textureMapper[i] = vtkVolumeTextureMapper2D::New(); + textureMapper[i]->SetInputConnection( reader->GetOutputPort() ); + volume[i+48]->SetMapper( textureMapper[i] ); + volume[i+48]->SetProperty( prop[i*2] ); + } + + + renWin->SetSize(400,350); + + ren->ResetCamera(); + ren->GetActiveCamera()->Zoom(1.5); + + renWin->Render(); + + int retVal = vtkRegressionTestImageThreshold( renWin, 70 ); + + // Interact with the data at 3 frames per second + iren->SetDesiredUpdateRate(3.0); + iren->SetStillUpdateRate(0.001); + + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + reader->Delete(); + oTFun->Delete(); + oTFun2->Delete(); + gTFun->Delete(); + cTFun->Delete(); + goTFun->Delete(); + for ( i = 0; i < 16; i++ ) + { + prop[i]->Delete(); + } + for ( i = 0; i < 4; i++ ) + { + mipprop[i]->Delete(); + } + compositeFunction1->Delete(); + compositeFunction2->Delete(); + isosurfaceFunction->Delete(); + MIPFunction1->Delete(); + MIPFunction2->Delete(); + for ( i = 0; i < 56; i++ ) + { + volume[i]->Delete(); + } + gradest->Delete(); + for ( i = 0; i < 48; i++ ) + { + raycastMapper[i]->Delete(); + } + for ( i = 0; i < 8; i++ ) + { + textureMapper[i]->Delete(); + } + ren->Delete(); + iren->Delete(); + renWin->Delete(); + + return !retVal; +} + + + diff --git a/VolumeRendering/Testing/Python/CMakeLists.txt b/VolumeRendering/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..0be1ba9 --- /dev/null +++ b/VolumeRendering/Testing/Python/CMakeLists.txt @@ -0,0 +1,30 @@ +INCLUDE(${VTK_SOURCE_DIR}/Utilities/vtkTclTest2Py/vtkConvertTclTestToPy.cmake) +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + IF (VTK_PYTHON_EXE) + # Add test converted from Tcl + SET( tests + gaussian + TestBunykRayCastFunction + #TestFixedPointRayCasterLinear -- source file + TestFixedPointRayCasterNearest + #TestFixedPointRayCasterLinearCropped -- source file + #TestFixedPointRayCasterNearestCropped -- source file + TestLODProp3D + TestPTZSweep + volRCClipPlanes + volRCCropRegions + volRCRotateClip + volTM2DCropRegions + volTM2DRotateClip + ) + + CONVERT_TCL_TEST_TO_PY ( + tests + VolumeRendering) + ENDIF (VTK_PYTHON_EXE) + ENDIF (VTK_DATA_ROOT) +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) diff --git a/VolumeRendering/Testing/Tcl/CMakeLists.txt b/VolumeRendering/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..5a76973 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,56 @@ +IF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + FOREACH ( tfile + gaussian + TestBunykRayCastFunction + TestFixedPointRayCasterLinear + TestFixedPointRayCasterNearest + TestFixedPointRayCasterLinearCropped + TestFixedPointRayCasterNearestCropped + TestLODProp3D + TestPTZSweep + volRCClipPlanes + volRCCropRegions + volRCRotateClip + volTM2DCropRegions + volTM2DRotateClip + volTM3DCropRegions + volTM3DRotateClip + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/VolumeRendering/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -V Baseline/VolumeRendering/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + IF(VTK_USE_TK) + ADD_TEST(imageCursor3D-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/VolumeRendering/Testing/Tcl/cursor3D.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/VolumeRendering/cursor3D.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDIF(VTK_USE_TK) + # + # If we do not have the data, still run the tests that we can + # + ELSE (VTK_DATA_ROOT) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING AND VTK_USE_DISPLAY) + +ADD_TEST(PrintSelf-VolumeRendering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/VolumeRendering) + +ADD_TEST(TestSetObjectMacro-VolumeRendering ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/VolumeRendering/vtk\\\\*.h" + "vtkSetObjectMacro" + ) diff --git a/VolumeRendering/Testing/Tcl/TestBunykRayCastFunction.tcl b/VolumeRendering/Testing/Tcl/TestBunykRayCastFunction.tcl new file mode 100644 index 0000000..89abfeb --- /dev/null +++ b/VolumeRendering/Testing/Tcl/TestBunykRayCastFunction.tcl @@ -0,0 +1,104 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create the reader for the data +# This is the data the will be volume rendered +vtkStructuredPointsReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/ironProt.vtk" + +# create a reader for the other data that will +# be contoured and displayed as a polygonal mesh +vtkSLCReader reader2 + reader2 SetFileName "$VTK_DATA_ROOT/Data/neghip.slc" + +# convert from vtkImageData to vtkUnstructuredGrid, remove +# any cells where all values are below 80 +vtkThreshold thresh + thresh ThresholdByUpper 80 + thresh AllScalarsOff + thresh SetInputConnection [reader GetOutputPort] + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [thresh GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 80 0.0 + opacityTransferFunction AddPoint 120 0.2 + opacityTransferFunction AddPoint 255 0.2 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 80.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 120.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 160.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 200.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 1.0 1.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + +# The mapper / ray cast function know how to render the data +vtkUnstructuredGridVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# contour the second dataset +vtkContourFilter contour + contour SetValue 0 80 + contour SetInputConnection [reader2 GetOutputPort] + +# create a mapper for the polygonal data +vtkPolyDataMapper mapper + mapper SetInputConnection [contour GetOutputPort] + mapper ScalarVisibilityOff + +# create an actor for the polygonal data +vtkActor actor + actor SetMapper mapper + +ren1 AddViewProp actor + +ren1 AddVolume volume +renWin SetSize 300 300 + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 10.0 +[ren1 GetActiveCamera] Zoom 1.5 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterLinear.tcl b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterLinear.tcl new file mode 100644 index 0000000..0e73dd1 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterLinear.tcl @@ -0,0 +1,10 @@ +source [file join [file dirname [info script]] TestFixedPointRayCasterNearest.tcl] + +for { set j 0 } { $j < 5 } { incr j } { + for { set i 0 } { $i < 5 } { incr i } { + volumeProperty${i}${j} SetInterpolationTypeToLinear + } +} + +renWin Render + diff --git a/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterLinearCropped.tcl b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterLinearCropped.tcl new file mode 100644 index 0000000..7477046 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterLinearCropped.tcl @@ -0,0 +1,14 @@ +source [file join [file dirname [info script]] TestFixedPointRayCasterNearest.tcl] + +for { set j 0 } { $j < 5 } { incr j } { + for { set i 0 } { $i < 5 } { incr i } { + volumeMapper${i}${j} SetCroppingRegionPlanes 10 20 10 20 10 20 + volumeMapper${i}${j} SetCroppingRegionFlags 253440 + volumeMapper${i}${j} CroppingOn + + volumeProperty${i}${j} SetInterpolationTypeToLinear + } +} + +renWin Render + diff --git a/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterNearest.tcl b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterNearest.tcl new file mode 100644 index 0000000..00d0e0c --- /dev/null +++ b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterNearest.tcl @@ -0,0 +1,349 @@ +package require vtk + +# Create a gaussian +vtkImageGaussianSource gs +gs SetWholeExtent 0 30 0 30 0 30 +gs SetMaximum 255.0 +gs SetStandardDeviation 5 +gs SetCenter 15 15 15 + +# threshold to leave a gap that should show up for +# gradient opacity +vtkImageThreshold t +t SetInputConnection [gs GetOutputPort] +t ReplaceInOn +t SetInValue 0 +t ThresholdBetween 150 200 + +# Use a shift scale to convert to unsigned char +vtkImageShiftScale ss +ss SetInputConnection [t GetOutputPort] +ss SetOutputScalarTypeToUnsignedChar + +# grid will be used for two component dependent +vtkImageGridSource grid0 +grid0 SetDataScalarTypeToUnsignedChar +grid0 SetGridSpacing 10 10 10 +grid0 SetLineValue 200 +grid0 SetFillValue 10 +grid0 SetDataExtent 0 30 0 30 0 30 + +# use dilation to thicken the grid +vtkImageContinuousDilate3D d +d SetInputConnection [grid0 GetOutputPort] +d SetKernelSize 3 3 3 + +# Now make a two component dependent +vtkImageAppendComponents iac +iac AddInput [d GetOutput] +iac AddInput [ss GetOutput] + +# Some more gaussians for the four component indepent case +vtkImageGaussianSource gs1 +gs1 SetWholeExtent 0 30 0 30 0 30 +gs1 SetMaximum 255.0 +gs1 SetStandardDeviation 4 +gs1 SetCenter 5 5 5 + +vtkImageThreshold t1 +t1 SetInputConnection [gs1 GetOutputPort] +t1 ReplaceInOn +t1 SetInValue 0 +t1 ThresholdBetween 150 256 + +vtkImageGaussianSource gs2 +gs2 SetWholeExtent 0 30 0 30 0 30 +gs2 SetMaximum 255.0 +gs2 SetStandardDeviation 4 +gs2 SetCenter 12 12 12 + +vtkImageGaussianSource gs3 +gs3 SetWholeExtent 0 30 0 30 0 30 +gs3 SetMaximum 255.0 +gs3 SetStandardDeviation 4 +gs3 SetCenter 19 19 19 + +vtkImageThreshold t3 +t3 SetInputConnection [gs3 GetOutputPort] +t3 ReplaceInOn +t3 SetInValue 0 +t3 ThresholdBetween 150 256 + +vtkImageGaussianSource gs4 +gs4 SetWholeExtent 0 30 0 30 0 30 +gs4 SetMaximum 255.0 +gs4 SetStandardDeviation 4 +gs4 SetCenter 26 26 26 + +# we need a few append filters ... +vtkImageAppendComponents iac1 +iac1 AddInput [t1 GetOutput] +iac1 AddInput [gs2 GetOutput] + +vtkImageAppendComponents iac2 +iac2 AddInput [iac1 GetOutput] +iac2 AddInput [t3 GetOutput] + +vtkImageAppendComponents iac3 +iac3 AddInput [iac2 GetOutput] +iac3 AddInput [gs4 GetOutput] + +# create the four component dependend - +# use lines in x, y, z for colors +vtkImageGridSource gridR +gridR SetDataScalarTypeToUnsignedChar +gridR SetGridSpacing 10 100 100 +gridR SetLineValue 250 +gridR SetFillValue 100 +gridR SetDataExtent 0 30 0 30 0 30 + +vtkImageContinuousDilate3D dR +dR SetInputConnection [gridR GetOutputPort] +dR SetKernelSize 2 2 2 + +vtkImageGridSource gridG +gridG SetDataScalarTypeToUnsignedChar +gridG SetGridSpacing 100 10 100 +gridG SetLineValue 250 +gridG SetFillValue 100 +gridG SetDataExtent 0 30 0 30 0 30 + +vtkImageContinuousDilate3D dG +dG SetInputConnection [gridG GetOutputPort] +dG SetKernelSize 2 2 2 + +vtkImageGridSource gridB +gridB SetDataScalarTypeToUnsignedChar +gridB SetGridSpacing 100 100 10 +gridB SetLineValue 0 +gridB SetFillValue 250 +gridB SetDataExtent 0 30 0 30 0 30 + +vtkImageContinuousDilate3D dB +dB SetInputConnection [gridB GetOutputPort] +dB SetKernelSize 2 2 2 + +# need some appending +vtkImageAppendComponents iacRG +iacRG AddInput [dR GetOutput] +iacRG AddInput [dG GetOutput] + +vtkImageAppendComponents iacRGB +iacRGB AddInput [iacRG GetOutput] +iacRGB AddInput [dB GetOutput] + +vtkImageAppendComponents iacRGBA +iacRGBA AddInput [iacRGB GetOutput] +iacRGBA AddInput [ss GetOutput] + +# We need a bunch of opacity functions + +# this one is a simple ramp to .2 +vtkPiecewiseFunction rampPoint2 +rampPoint2 AddPoint 0 0.0 +rampPoint2 AddPoint 255 0.2 + +# this one is a simple ramp to 1 +vtkPiecewiseFunction ramp1 +ramp1 AddPoint 0 0.0 +ramp1 AddPoint 255 1.0 + +# this one shows a sharp surface +vtkPiecewiseFunction surface +surface AddPoint 0 0.0 +surface AddPoint 10 0.0 +surface AddPoint 50 1.0 +surface AddPoint 255 1.0 + + +# this one is constant 1 +vtkPiecewiseFunction constant1 +constant1 AddPoint 0 1.0 +constant1 AddPoint 255 1.0 + +# this one is used for gradient opacity +vtkPiecewiseFunction gop +gop AddPoint 0 0.0 +gop AddPoint 20 0.0 +gop AddPoint 60 1.0 +gop AddPoint 255 1.0 + + +# We need a bunch of color functions + +# This one is a simple rainbow +vtkColorTransferFunction rainbow +rainbow SetColorSpaceToHSV +rainbow HSVWrapOff +rainbow AddHSVPoint 0 0.1 1.0 1.0 +rainbow AddHSVPoint 255 0.9 1.0 1.0 + +# this is constant red +vtkColorTransferFunction red +red AddRGBPoint 0 1 0 0 +red AddRGBPoint 255 1 0 0 + +# this is constant green +vtkColorTransferFunction green +green AddRGBPoint 0 0 1 0 +green AddRGBPoint 255 0 1 0 + +# this is constant blue +vtkColorTransferFunction blue +blue AddRGBPoint 0 0 0 1 +blue AddRGBPoint 255 0 0 1 + +# this is constant yellow +vtkColorTransferFunction yellow +yellow AddRGBPoint 0 1 1 0 +yellow AddRGBPoint 255 1 1 0 + + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 500 500 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +# We need 25 mapper / actor pairs which we will render +# in a grid. Going down we will vary the input data +# with the top row unsigned char, then float, then +# two dependent components, then four dependent components +# then four independent components. Going across we +# will vary the rendering method with MIP, Composite, +# Composite Shade, Composite GO, and Composite GO Shade. + +for { set j 0 } { $j < 5 } { incr j } { + for { set i 0 } { $i < 5 } { incr i } { + vtkVolumeProperty volumeProperty${i}${j} + vtkFixedPointVolumeRayCastMapper volumeMapper${i}${j} + volumeMapper${i}${j} SetSampleDistance 0.25 + + vtkVolume volume${i}${j} + volume${i}${j} SetMapper volumeMapper${i}${j} + volume${i}${j} SetProperty volumeProperty${i}${j} + + volume${i}${j} AddPosition [expr $i*30] [expr $j*30] 0 + + ren1 AddVolume volume${i}${j} + } +} + +for { set i 0 } { $i < 5 } { incr i } { + volumeMapper0${i} SetInputConnection [t GetOutputPort] + volumeMapper1${i} SetInputConnection [ss GetOutputPort] + volumeMapper2${i} SetInputConnection [iac GetOutputPort] + volumeMapper3${i} SetInputConnection [iac3 GetOutputPort] + volumeMapper4${i} SetInputConnection [iacRGBA GetOutputPort] + + volumeMapper${i}0 SetBlendModeToMaximumIntensity + volumeMapper${i}1 SetBlendModeToComposite + volumeMapper${i}2 SetBlendModeToComposite + volumeMapper${i}3 SetBlendModeToComposite + volumeMapper${i}4 SetBlendModeToComposite + + volumeProperty0${i} IndependentComponentsOn + volumeProperty1${i} IndependentComponentsOn + volumeProperty2${i} IndependentComponentsOff + volumeProperty3${i} IndependentComponentsOn + volumeProperty4${i} IndependentComponentsOff + + volumeProperty0${i} SetColor rainbow + volumeProperty0${i} SetScalarOpacity rampPoint2 + volumeProperty0${i} SetGradientOpacity constant1 + + volumeProperty1${i} SetColor rainbow + volumeProperty1${i} SetScalarOpacity rampPoint2 + volumeProperty1${i} SetGradientOpacity constant1 + + volumeProperty2${i} SetColor rainbow + volumeProperty2${i} SetScalarOpacity rampPoint2 + volumeProperty2${i} SetGradientOpacity constant1 + + volumeProperty3${i} SetColor 0 red + volumeProperty3${i} SetColor 1 green + volumeProperty3${i} SetColor 2 blue + volumeProperty3${i} SetColor 3 yellow + volumeProperty3${i} SetScalarOpacity 0 rampPoint2 + volumeProperty3${i} SetScalarOpacity 1 rampPoint2 + volumeProperty3${i} SetScalarOpacity 2 rampPoint2 + volumeProperty3${i} SetScalarOpacity 3 rampPoint2 + volumeProperty3${i} SetGradientOpacity 0 constant1 + volumeProperty3${i} SetGradientOpacity 1 constant1 + volumeProperty3${i} SetGradientOpacity 2 constant1 + volumeProperty3${i} SetGradientOpacity 3 constant1 + volumeProperty3${i} SetComponentWeight 0 1 + volumeProperty3${i} SetComponentWeight 1 1 + volumeProperty3${i} SetComponentWeight 2 1 + volumeProperty3${i} SetComponentWeight 3 1 + + volumeProperty4${i} SetColor rainbow + volumeProperty4${i} SetScalarOpacity rampPoint2 + volumeProperty4${i} SetGradientOpacity constant1 + + volumeProperty${i}2 ShadeOn + volumeProperty${i}4 ShadeOn 0 + volumeProperty${i}4 ShadeOn 1 + volumeProperty${i}4 ShadeOn 2 + volumeProperty${i}4 ShadeOn 3 +} + +volumeProperty00 SetScalarOpacity ramp1 +volumeProperty10 SetScalarOpacity ramp1 +volumeProperty20 SetScalarOpacity ramp1 +volumeProperty30 SetScalarOpacity 0 surface +volumeProperty30 SetScalarOpacity 1 surface +volumeProperty30 SetScalarOpacity 2 surface +volumeProperty30 SetScalarOpacity 3 surface +volumeProperty40 SetScalarOpacity ramp1 + +volumeProperty02 SetScalarOpacity surface +volumeProperty12 SetScalarOpacity surface +volumeProperty22 SetScalarOpacity surface +volumeProperty32 SetScalarOpacity 0 surface +volumeProperty32 SetScalarOpacity 1 surface +volumeProperty32 SetScalarOpacity 2 surface +volumeProperty32 SetScalarOpacity 3 surface +volumeProperty42 SetScalarOpacity surface + +volumeProperty04 SetScalarOpacity surface +volumeProperty14 SetScalarOpacity surface +volumeProperty24 SetScalarOpacity surface +volumeProperty34 SetScalarOpacity 0 surface +volumeProperty34 SetScalarOpacity 1 surface +volumeProperty34 SetScalarOpacity 2 surface +volumeProperty34 SetScalarOpacity 3 surface +volumeProperty44 SetScalarOpacity surface + +volumeProperty03 SetGradientOpacity gop +volumeProperty13 SetGradientOpacity gop +volumeProperty23 SetGradientOpacity gop +volumeProperty33 SetGradientOpacity 0 gop +volumeProperty33 SetGradientOpacity 2 gop +volumeProperty43 SetGradientOpacity gop + +volumeProperty33 SetScalarOpacity 0 ramp1 +volumeProperty33 SetScalarOpacity 2 ramp1 + +volumeProperty04 SetGradientOpacity gop +volumeProperty14 SetGradientOpacity gop +volumeProperty24 SetGradientOpacity gop +volumeProperty34 SetGradientOpacity 0 gop +volumeProperty34 SetGradientOpacity 2 gop +volumeProperty44 SetGradientOpacity gop + +renWin Render + +[ren1 GetActiveCamera] Dolly 1.3 +[ren1 GetActiveCamera] Azimuth 15 +[ren1 GetActiveCamera] Elevation 5 +ren1 ResetCameraClippingRange + +wm withdraw . + +iren Initialize diff --git a/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterNearestCropped.tcl b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterNearestCropped.tcl new file mode 100644 index 0000000..ce8710c --- /dev/null +++ b/VolumeRendering/Testing/Tcl/TestFixedPointRayCasterNearestCropped.tcl @@ -0,0 +1,12 @@ +source [file join [file dirname [info script]] TestFixedPointRayCasterNearest.tcl] + +for { set j 0 } { $j < 5 } { incr j } { + for { set i 0 } { $i < 5 } { incr i } { + volumeMapper${i}${j} SetCroppingRegionPlanes 10 20 10 20 10 20 + volumeMapper${i}${j} SetCroppingRegionFlags 253440 + volumeMapper${i}${j} CroppingOn + } +} + +renWin Render + diff --git a/VolumeRendering/Testing/Tcl/TestLODProp3D.tcl b/VolumeRendering/Testing/Tcl/TestLODProp3D.tcl new file mode 100644 index 0000000..03e5fb6 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/TestLODProp3D.tcl @@ -0,0 +1,96 @@ +package require vtk + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +reader Update + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 20 0.0 + opacityTransferFunction AddPoint 255 1.0 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 127.5 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 255.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + + +vtkVolumeTextureMapper2D volumeMapper + volumeMapper SetInputConnection [reader GetOutputPort] + +vtkSphereSource sphereSource + sphereSource SetCenter 25 25 25 + sphereSource SetRadius 30 + sphereSource SetThetaResolution 15 + sphereSource SetPhiResolution 15 + +vtkPolyDataMapper geoMapper + geoMapper SetInputConnection [sphereSource GetOutputPort] + + +vtkLODProp3D lod + set geoID [lod AddLOD geoMapper 0.0] + set volID [lod AddLOD volumeMapper volumeProperty 0.0] + +vtkProperty property + property SetColor 1 0 0 + +lod SetLODProperty $geoID property + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp lod + +# render a few times +renWin Render +renWin Render +renWin Render + +# disable the geometry and render +lod DisableLOD $geoID +renWin Render + +# disable the volume and render +lod EnableLOD $geoID +lod DisableLOD $volID +renWin Render + +# chose the geometry to render +lod EnableLOD $volID +lod AutomaticLODSelectionOff +lod SetSelectedLODID $geoID +renWin Render + +# choose the volume +lod SetSelectedLODID $volID +renWin Render + +# this should be the volID - remove it +set id [lod GetLastRenderedLODID] +lod RemoveLOD $id + +lod AutomaticLODSelectionOn +renWin Render + +wm withdraw . + +iren Initialize diff --git a/VolumeRendering/Testing/Tcl/TestPTZSweep.tcl b/VolumeRendering/Testing/Tcl/TestPTZSweep.tcl new file mode 100644 index 0000000..dccf833 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/TestPTZSweep.tcl @@ -0,0 +1,81 @@ +package require vtk +package require vtkinteraction + +# Create the standard renderer, render window +# and interactor +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren SetDesiredUpdateRate 3 + +# Create a small mesh. The coarser and more opaque the mesh, the easier it +# is to see rendering errors. +vtkImageMandelbrotSource input + input SetWholeExtent 0 2 0 2 0 2 + input SetSizeCX 2 2 2 2 + input SetMaximumNumberOfIterations 10 + +# make sure we have only tetrahedra +vtkDataSetTriangleFilter trifilter + trifilter SetInputConnection [input GetOutputPort] + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 10 1.0 + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0 1.0 0.0 1.0 + colorTransferFunction AddRGBPoint 2 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 4 0.0 1.0 1.0 + colorTransferFunction AddRGBPoint 6 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 8 1.0 1.0 0.0 + colorTransferFunction AddRGBPoint 10 1.0 0.0 0.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty ShadeOff + volumeProperty SetInterpolationTypeToLinear + volumeProperty SetScalarOpacityUnitDistance 0.75 + +# The mapper / ray cast function / ray integrator know how to render the data +vtkUnstructuredGridVolumeZSweepMapper volumeMapper + volumeMapper SetInputConnection [trifilter GetOutputPort] + +#vtkUnstructuredGridLinearRayIntegrator rayIntegrator +# volumeMapper SetRayIntegrator rayIntegrator +vtkUnstructuredGridPreIntegration rayIntegrator + volumeMapper SetRayIntegrator rayIntegrator + +# The volume holds the mapper and the property and +# can be used to position/orient the volume +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +renWin SetSize 300 300 + +ren1 ResetCamera +[ren1 GetActiveCamera] Azimuth 20.0 +[ren1 GetActiveCamera] Elevation 15.0 +[ren1 GetActiveCamera] Zoom 1.5 + +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . diff --git a/VolumeRendering/Testing/Tcl/cursor3D.tcl b/VolumeRendering/Testing/Tcl/cursor3D.tcl new file mode 100644 index 0000000..82635d6 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/cursor3D.tcl @@ -0,0 +1,257 @@ +# This little example shows how a cursor can be created in +# image viewers, and renderers. The standard TkImageViewerWidget and +# TkRenderWidget bindings are used. There is a new binding: +# middle button in the image viewer sets the position of the cursor. + +# First we include the VTK Tcl packages which will make available +# all of the vtk commands to Tcl + +package require vtk +package require vtkinteraction + +# Global values + +set CURSOR_X 20 +set CURSOR_Y 20 +set CURSOR_Z 20 + +set IMAGE_MAG_X 4 +set IMAGE_MAG_Y 4 +set IMAGE_MAG_Z 1 + +# Pipeline stuff + +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/neghip.slc" + +# Cursor stuff + +vtkImageMagnify magnify + magnify SetInputConnection [reader GetOutputPort] + magnify SetMagnificationFactors $IMAGE_MAG_X $IMAGE_MAG_Y $IMAGE_MAG_Z + +vtkImageCursor3D image_cursor + image_cursor SetInputConnection [magnify GetOutputPort] + image_cursor SetCursorPosition \ + [expr $CURSOR_X * $IMAGE_MAG_X] \ + [expr $CURSOR_Y * $IMAGE_MAG_Y] \ + [expr $CURSOR_Z * $IMAGE_MAG_Z] + image_cursor SetCursorValue 255 + image_cursor SetCursorRadius [expr 50 * $IMAGE_MAG_X] + +vtkAxes axes + axes SymmetricOn + axes SetOrigin $CURSOR_X $CURSOR_Y $CURSOR_Z + axes SetScaleFactor 50.0 + +vtkPolyDataMapper axes_mapper + axes_mapper SetInputConnection [axes GetOutputPort] + +vtkActor axesActor + axesActor SetMapper axes_mapper + [axesActor GetProperty] SetAmbient 0.5 + +# Image viewer stuff + +vtkImageViewer viewer + viewer SetInputConnection [image_cursor GetOutputPort] + viewer SetZSlice [expr $CURSOR_Z * $IMAGE_MAG_Z] + viewer SetColorWindow 256 + viewer SetColorLevel 128 + +proc viewer_down {viewer} { + viewer_set_z_slice $viewer [expr [$viewer GetZSlice] - 1] +} + +proc viewer_up {viewer} { + viewer_set_z_slice $viewer [expr [$viewer GetZSlice] + 1] +} + +proc viewer_set_z_slice {viewer z} { + global slice_label + $viewer SetZSlice $z + $slice_label configure -text "slice: $z" + $viewer Render +} + +# Create transfer functions for opacity and color + +vtkPiecewiseFunction opacity_transfer_function + opacity_transfer_function AddPoint 20 0.0 + opacity_transfer_function AddPoint 255 0.2 + +vtkColorTransferFunction color_transfer_function + color_transfer_function AddRGBPoint 0 0 0 0 + color_transfer_function AddRGBPoint 64 1 0 0 + color_transfer_function AddRGBPoint 128 0 0 1 + color_transfer_function AddRGBPoint 192 0 1 0 + color_transfer_function AddRGBPoint 255 0 .2 0 + +# Create properties, mappers, volume actors, and ray cast function + +vtkVolumeProperty volume_property + volume_property SetColor color_transfer_function + volume_property SetScalarOpacity opacity_transfer_function + +vtkVolumeRayCastCompositeFunction composite_function + +vtkVolumeRayCastMapper volume_mapper + volume_mapper SetInputConnection [reader GetOutputPort] + volume_mapper SetVolumeRayCastFunction composite_function + +vtkVolume volume + volume SetMapper volume_mapper + volume SetProperty volume_property + +# Create outline + +vtkOutlineFilter outline + outline SetInputConnection [reader GetOutputPort] + +vtkPolyDataMapper outline_mapper + outline_mapper SetInputConnection [outline GetOutputPort] + +vtkActor outlineActor + outlineActor SetMapper outline_mapper + eval [outlineActor GetProperty] SetColor 1 1 1 + +# Create the renderer + +vtkRenderer ren1 + ren1 AddActor axesActor + ren1 AddVolume volume + ren1 SetBackground 0.1 0.2 0.4 + +vtkRenderWindow renWin2 + renWin2 AddRenderer ren1 + renWin2 SetSize 256 256 + +# Create the GUI: two renderer widgets and a quit button + +wm withdraw . +toplevel .top + +# Set the window manager (wm command) so that it registers a +# command to handle the WM_DELETE_WINDOW protocal request. This +# request is triggered when the widget is closed using the standard +# window manager icons or buttons. In this case the exit callback +# will be called and it will free up any objects we created then exit +# the application. + +wm protocol .top WM_DELETE_WINDOW ::vtk::cb_exit + +# Help label, frame and quit button + +set help_label [label .top.help \ + -text "MiddleMouse (or shift-LeftMouse) in image viewer to place cursor"] + +set display_frame [frame .top.f1] + +set quit_button [button .top.btn \ + -text Quit \ + -command ::vtk::cb_exit] + +# Pack the GUI + +pack $help_label + +pack $display_frame \ + -fill both -expand t + +pack $quit_button \ + -fill x + +# Create the viewer widget + +set viewer_frame [frame $display_frame.vFm] + +pack $viewer_frame \ + -padx 3 -pady 3 \ + -side left -anchor n \ + -fill both -expand f + +set viewer_widget [vtkTkImageViewerWidget $viewer_frame.v \ + -width 264 \ + -height 264 \ + -iv viewer] + +set viewer_controls [frame $viewer_frame.c] + +pack $viewer_widget $viewer_controls \ + -side top -anchor n \ + -fill both -expand f + +set down_button [button $viewer_controls.down \ + -text "Down" \ + -command [list viewer_down viewer]] + +set up_button [button $viewer_controls.up \ + -text "Up" \ + -command [list viewer_up viewer]] + +set slice_label [label $viewer_controls.slice \ + -text "slice: [expr $CURSOR_Z * $IMAGE_MAG_Z]"] + +pack $down_button $up_button $slice_label \ + -side left \ + -expand t -fill both + +# Create the render widget + +set renderer_frame [frame $display_frame.rFm] + +pack $renderer_frame \ + -padx 3 -pady 3 \ + -side left -anchor n \ + -fill both -expand t + +set render_widget [vtkTkRenderWidget $renderer_frame.r \ + -width 264 \ + -height 264 \ + -rw renWin2] + +pack $render_widget \ + -side top -anchor n \ + -expand t -fill both + +# Bindings + +::vtk::bind_tk_imageviewer_widget $viewer_widget +$viewer_widget Render + +::vtk::bind_tk_render_widget $render_widget +[[[$render_widget GetRenderWindow] GetInteractor] GetInteractorStyle] SetCurrentStyleToTrackballCamera +$render_widget Render + +# Lets add an extra binding of the middle button in the image viewer +# to set the cursor location + +bind $viewer_widget <Button-2> {SetCursorFromViewer %x %y} +bind $viewer_widget <Shift-Button-1> {SetCursorFromViewer %x %y} + +# Supporting procedures + +proc SetCursorFromViewer {x y} { + global viewer_widget + global IMAGE_MAG_X IMAGE_MAG_Y IMAGE_MAG_Z + + # we have to flip y axis because tk uses upper right origin. + set height [lindex [$viewer_widget configure -height] 4] + set y [expr $height - $y] + set z [viewer GetZSlice] + SetCursor [expr $x / $IMAGE_MAG_X] [expr $y / $IMAGE_MAG_Y] \ + [expr $z / $IMAGE_MAG_Z] +} + +proc SetCursor {x y z} { + global CURSOR_X CURSOR_Y CURSOR_Z IMAGE_MAG_X IMAGE_MAG_Y IMAGE_MAG_Z + + set CURSOR_X $x + set CURSOR_Y $y + set CURSOR_Z $z + axes SetOrigin $CURSOR_X $CURSOR_Y $CURSOR_Z + image_cursor SetCursorPosition [expr $CURSOR_X * $IMAGE_MAG_X] \ + [expr $CURSOR_Y * $IMAGE_MAG_Y] [expr $CURSOR_Z * $IMAGE_MAG_Z] + viewer Render + renWin2 Render +} diff --git a/VolumeRendering/Testing/Tcl/gaussian.tcl b/VolumeRendering/Testing/Tcl/gaussian.tcl new file mode 100644 index 0000000..6720696 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/gaussian.tcl @@ -0,0 +1,178 @@ +package require vtk +package require vtkinteraction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 300 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +vtkCamera camera + camera ParallelProjectionOn + camera SetViewUp 0 1 0 + camera SetFocalPoint 12 10.5 15 + camera SetPosition -70 15 34 + camera ComputeViewPlaneNormal + ren1 SetActiveCamera camera + +# Create the reader for the data +#vtkStructuredPointsReader reader +vtkGaussianCubeReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/m4_TotalDensity.cube" + reader SetHBScale 1.1 + reader SetBScale 10 + reader Update + +set range [[[[reader GetGridOutput] GetPointData] GetScalars] GetRange] +set min [lindex $range 0] +set max [lindex $range 1] + +vtkImageShiftScale readerSS + readerSS SetInput [reader GetGridOutput] + readerSS SetShift [expr $min * -1] + readerSS SetScale [expr 255 / ($max - $min)] + readerSS SetOutputScalarTypeToUnsignedChar + +vtkOutlineFilter bounds + bounds SetInput [reader GetGridOutput] + +vtkPolyDataMapper boundsMapper + boundsMapper SetInputConnection [bounds GetOutputPort] + +vtkActor boundsActor + boundsActor SetMapper boundsMapper + [boundsActor GetProperty] SetColor 0 0 0 + +vtkContourFilter contour + contour SetInput [reader GetGridOutput] + eval contour GenerateValues 5 0 .05 + + +vtkPolyDataMapper contourMapper + contourMapper SetInputConnection [contour GetOutputPort] + eval contourMapper SetScalarRange 0 .1 + [contourMapper GetLookupTable] SetHueRange 0.32 0 + +vtkActor contourActor + contourActor SetMapper contourMapper + [contourActor GetProperty] SetOpacity .5 + +# Create transfer mapping scalar value to opacity +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.01 + opacityTransferFunction AddPoint 255 0.35 + opacityTransferFunction ClampingOn + +# Create transfer mapping scalar value to color +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddHSVPoint 0.0 0.66 1.0 1.0 + colorTransferFunction AddHSVPoint 50.0 0.33 1.0 1.0 + colorTransferFunction AddHSVPoint 100.0 0.00 1.0 1.0 + +# The property describes how the data will look +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + +# The mapper / ray cast function know how to render the data +vtkVolumeRayCastCompositeFunction compositeFunction + +vtkVolumeRayCastMapper volumeMapper +#vtkVolumeTextureMapper2D volumeMapper + volumeMapper SetVolumeRayCastFunction compositeFunction + volumeMapper SetInputConnection [readerSS GetOutputPort] + +# The volume holds the mapper and the property and +# can be used to position/orient the volume + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +ren1 AddVolume volume +#ren1 AddActor contourActor +ren1 AddActor boundsActor + +###################################################################### +vtkSphereSource Sphere + Sphere SetCenter 0 0 0 + Sphere SetRadius 1 + Sphere SetThetaResolution 16 + Sphere SetStartTheta 0 + Sphere SetEndTheta 360 + Sphere SetPhiResolution 16 + Sphere SetStartPhi 0 + Sphere SetEndPhi 180 + +vtkGlyph3D Glyph + Glyph SetInputConnection [reader GetOutputPort] + Glyph SetOrient 1 + Glyph SetColorMode 1 + #Glyph ScalingOn + Glyph SetScaleMode 2 + Glyph SetScaleFactor .6 + Glyph SetSource [Sphere GetOutput] + +vtkPolyDataMapper AtomsMapper + AtomsMapper SetInputConnection [Glyph GetOutputPort] + AtomsMapper SetImmediateModeRendering 1 + AtomsMapper UseLookupTableScalarRangeOff + AtomsMapper SetScalarVisibility 1 + AtomsMapper SetScalarModeToDefault + +vtkActor Atoms + Atoms SetMapper AtomsMapper + [Atoms GetProperty] SetRepresentationToSurface + [Atoms GetProperty] SetInterpolationToGouraud + [Atoms GetProperty] SetAmbient 0.15 + [Atoms GetProperty] SetDiffuse 0.85 + [Atoms GetProperty] SetSpecular 0.1 + [Atoms GetProperty] SetSpecularPower 100 + [Atoms GetProperty] SetSpecularColor 1 1 1 + [Atoms GetProperty] SetColor 1 1 1 + +vtkTubeFilter Tube + Tube SetInputConnection [reader GetOutputPort] + Tube SetNumberOfSides 16 + Tube SetCapping 0 + Tube SetRadius 0.2 + Tube SetVaryRadius 0 + Tube SetRadiusFactor 10 + +vtkPolyDataMapper BondsMapper + BondsMapper SetInputConnection [Tube GetOutputPort] + BondsMapper SetImmediateModeRendering 1 + BondsMapper UseLookupTableScalarRangeOff + BondsMapper SetScalarVisibility 1 + BondsMapper SetScalarModeToDefault +vtkActor Bonds + Bonds SetMapper BondsMapper + [Bonds GetProperty] SetRepresentationToSurface + [Bonds GetProperty] SetInterpolationToGouraud + [Bonds GetProperty] SetAmbient 0.15 + [Bonds GetProperty] SetDiffuse 0.85 + [Bonds GetProperty] SetSpecular 0.1 + [Bonds GetProperty] SetSpecularPower 100 + [Bonds GetProperty] SetSpecularColor 1 1 1 + [Bonds GetProperty] SetColor 1 1 1 + +ren1 AddActor Bonds +ren1 AddActor Atoms +#################################################### + +ren1 SetBackground 1 1 1 +ren1 ResetCamera +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" {TkCheckAbort} + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . diff --git a/VolumeRendering/Testing/Tcl/volRCClipPlanes.tcl b/VolumeRendering/Testing/Tcl/volRCClipPlanes.tcl new file mode 100644 index 0000000..2b21412 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/volRCClipPlanes.tcl @@ -0,0 +1,123 @@ +package require vtk + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +reader Update + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 20 0.0 + opacityTransferFunction AddPoint 255 1.0 + +vtkColorTransferFunction colorTransferFunction + +# Improve coverage + colorTransferFunction SetColorSpaceToRGB + colorTransferFunction AddRGBPoint 100 1 1 1 + colorTransferFunction AddRGBPoint 0 0 0 0 + colorTransferFunction AddRGBPoint 200 1 0 1 + colorTransferFunction AddRGBPoint 100 0 0 0 + colorTransferFunction RemovePoint 100 + colorTransferFunction RemovePoint 0 + colorTransferFunction RemovePoint 200 + colorTransferFunction AddHSVPoint 100 1 1 1 + colorTransferFunction AddHSVPoint 0 0 0 0 + colorTransferFunction AddHSVPoint 200 1 0 1 + colorTransferFunction AddHSVPoint 100 0 0 0 + colorTransferFunction RemovePoint 0 + colorTransferFunction RemovePoint 200 + colorTransferFunction RemovePoint 100 + colorTransferFunction AddRGBSegment 0 1 1 1 100 0 0 0 + colorTransferFunction AddRGBSegment 50 1 1 1 150 0 0 0 + colorTransferFunction AddRGBSegment 60 1 1 1 90 0 0 0 + colorTransferFunction AddHSVSegment 90 1 1 1 105 0 0 0 + colorTransferFunction AddHSVSegment 40 1 1 1 155 0 0 0 + colorTransferFunction AddHSVSegment 30 1 1 1 95 0 0 0 + + + colorTransferFunction RemoveAllPoints + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 127.5 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 255.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + +vtkVolumeRayCastCompositeFunction compositeFunction + +vtkVolumeRayCastMapper volumeMapper + volumeMapper SetInputConnection [reader GetOutputPort] + volumeMapper SetVolumeRayCastFunction compositeFunction + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# Create geometric sphere +vtkSphereSource sphereSource + sphereSource SetCenter 25 25 25 + sphereSource SetRadius 30 + sphereSource SetThetaResolution 15 + sphereSource SetPhiResolution 15 + +vtkPolyDataMapper sphereMapper + sphereMapper SetInputConnection [sphereSource GetOutputPort] + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Set up the planes +vtkPlane plane1 +plane1 SetOrigin 25 25 20 +plane1 SetNormal 0 0 1 + +vtkPlane plane2 +plane2 SetOrigin 25 25 30 +plane2 SetNormal 0 0 -1 + +vtkPlane plane3 +plane3 SetOrigin 20 25 25 +plane3 SetNormal 1 0 0 + +vtkPlane plane4 +plane4 SetOrigin 30 25 25 +plane4 SetNormal -1 0 0 + +sphereMapper AddClippingPlane plane1 +sphereMapper AddClippingPlane plane2 + +volumeMapper AddClippingPlane plane3 +volumeMapper AddClippingPlane plane4 + + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp sphereActor +ren1 AddViewProp volume +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +[ren1 GetActiveCamera] Azimuth 45 +[ren1 GetActiveCamera] Elevation 15 +[ren1 GetActiveCamera] Roll 45 +[ren1 GetActiveCamera] Zoom 2.0 + +wm withdraw . + +iren Initialize diff --git a/VolumeRendering/Testing/Tcl/volRCCropRegions.tcl b/VolumeRendering/Testing/Tcl/volRCCropRegions.tcl new file mode 100644 index 0000000..73de29b --- /dev/null +++ b/VolumeRendering/Testing/Tcl/volRCCropRegions.tcl @@ -0,0 +1,106 @@ +package require vtk +package require vtkinteraction + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 30 0.0 + opacityTransferFunction AddPoint 80 0.5 + opacityTransferFunction AddPoint 255 0.5 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + volumeProperty ShadeOn + +vtkVolumeRayCastCompositeFunction compositeFunction + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 600 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.1 0.2 0.4 + +for { set i 0 } { $i < 2 } { incr i } { + for { set j 0 } { $j < 4 } { incr j } { + vtkVolumeRayCastMapper volumeMapper_${i}_${j} + volumeMapper_${i}_${j} SetInputConnection [reader GetOutputPort] + volumeMapper_${i}_${j} SetVolumeRayCastFunction compositeFunction + volumeMapper_${i}_${j} SetSampleDistance 0.4 + volumeMapper_${i}_${j} CroppingOn + volumeMapper_${i}_${j} SetCroppingRegionPlanes 17 33 17 33 17 33 + + vtkVolume volume_${i}_${j} + volume_${i}_${j} SetMapper volumeMapper_${i}_${j} + volume_${i}_${j} SetProperty volumeProperty + + vtkTransform userMatrix_${i}_${j} + userMatrix_${i}_${j} PostMultiply + userMatrix_${i}_${j} Identity + userMatrix_${i}_${j} Translate -25 -25 -25 + + if { $i == 0 } { + userMatrix_${i}_${j} RotateX [expr $j*87 + 23] + userMatrix_${i}_${j} RotateY 16 + } else { + userMatrix_${i}_${j} RotateX 27 + userMatrix_${i}_${j} RotateY [expr $j*87 + 19] + } + + userMatrix_${i}_${j} Translate [expr $j*55 + 25] [expr $i*55 + 25] 0 + + volume_${i}_${j} SetUserTransform userMatrix_${i}_${j} + + ren1 AddViewProp volume_${i}_${j} + } +} + +volumeMapper_0_0 SetCroppingRegionFlagsToSubVolume +volumeMapper_0_1 SetCroppingRegionFlagsToCross +volumeMapper_0_2 SetCroppingRegionFlagsToInvertedCross +volumeMapper_0_3 SetCroppingRegionFlags 24600 + +volumeMapper_1_0 SetCroppingRegionFlagsToFence +volumeMapper_1_1 SetCroppingRegionFlagsToInvertedFence +volumeMapper_1_2 SetCroppingRegionFlags 1 +volumeMapper_1_3 SetCroppingRegionFlags 67117057 + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 3.0 +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" {TkCheckAbort} + + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/VolumeRendering/Testing/Tcl/volRCRotateClip.tcl b/VolumeRendering/Testing/Tcl/volRCRotateClip.tcl new file mode 100644 index 0000000..b23fe71 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/volRCRotateClip.tcl @@ -0,0 +1,146 @@ +package require vtk + +# Simple volume rendering example. +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff +reader SetDataSpacing 2 2 1 +reader SetDataScalarTypeToUnsignedShort +reader Update + +set readerOutput [reader GetOutput] +$readerOutput SetOrigin -63 -63 -46 + +# Disconnect the output from its reader. First get an extra reference. +$readerOutput Register {} +$readerOutput SetSource {} + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 600 0.0 + opacityTransferFunction AddPoint 2000 1.0 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction ClampingOff + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 1000.0 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 2000.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + +vtkVolumeRayCastCompositeFunction f +vtkVolumeRayCastMapper volumeMapper + volumeMapper SetInput $readerOutput + volumeMapper SetVolumeRayCastFunction f + volumeMapper SetSampleDistance 0.3 + +# The data object is now referenced by the connection. +$readerOutput UnRegister {} + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# Create geometric sphere +vtkSphereSource sphereSource + sphereSource SetRadius 65 + sphereSource SetThetaResolution 20 + sphereSource SetPhiResolution 40 + + +proc colorCells {} { + vtkMath randomColorGenerator + set input [randomColors GetInput] + set output [randomColors GetOutput] + set numCells [$input GetNumberOfCells] + vtkFloatArray colors + colors SetNumberOfTuples $numCells + + for {set i 0} {$i < $numCells} {incr i} { + colors SetValue $i [randomColorGenerator Random 0 1] + } + + [$output GetCellData] CopyScalarsOff + [$output GetCellData] PassData [$input GetCellData] + [$output GetCellData] SetScalars colors + + colors Delete; #reference counting - it's ok + randomColorGenerator Delete +} + +# Compute random scalars (colors) for each cell +vtkProgrammableAttributeDataFilter randomColors + randomColors SetInputConnection [sphereSource GetOutputPort] + randomColors SetExecuteMethod colorCells + +vtkPolyDataMapper sphereMapper + sphereMapper SetInput [randomColors GetPolyDataOutput] + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Set up the planes +vtkPlane plane1 +plane1 SetOrigin 0 0 -10 +plane1 SetNormal 0 0 1 + +vtkPlane plane2 +plane2 SetOrigin 0 0 10 +plane2 SetNormal 0 0 -1 + +vtkPlane plane3 +plane3 SetOrigin -10 0 0 +plane3 SetNormal 1 0 0 + +vtkPlane plane4 +plane4 SetOrigin 10 0 0 +plane4 SetNormal -1 0 0 + +sphereMapper AddClippingPlane plane1 +sphereMapper AddClippingPlane plane2 + +volumeMapper AddClippingPlane plane3 +volumeMapper AddClippingPlane plane4 + + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp sphereActor +ren1 AddViewProp volume +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +[ren1 GetActiveCamera] Azimuth 45 +[ren1 GetActiveCamera] Elevation 15 +[ren1 GetActiveCamera] Roll 45 +[ren1 GetActiveCamera] Zoom 2.0 + +wm withdraw . + +iren Initialize + +for { set i 0 } { $i < 5 } { incr i } { + volume RotateY 17 + volume RotateZ 13 + sphereActor RotateX 13 + sphereActor RotateY 17 +} +renWin Render + diff --git a/VolumeRendering/Testing/Tcl/volTM2DCropRegions.tcl b/VolumeRendering/Testing/Tcl/volTM2DCropRegions.tcl new file mode 100644 index 0000000..e594c10 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/volTM2DCropRegions.tcl @@ -0,0 +1,103 @@ +package require vtk +package require vtkinteraction + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 30 0.0 + opacityTransferFunction AddPoint 80 0.5 + opacityTransferFunction AddPoint 255 0.5 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + volumeProperty ShadeOn + + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 600 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.1 0.2 0.4 + +for { set i 0 } { $i < 2 } { incr i } { + for { set j 0 } { $j < 4 } { incr j } { + vtkVolumeTextureMapper2D volumeMapper_${i}_${j} + volumeMapper_${i}_${j} SetInputConnection [reader GetOutputPort] + volumeMapper_${i}_${j} CroppingOn + volumeMapper_${i}_${j} SetCroppingRegionPlanes 17 33 17 33 17 33 + + vtkVolume volume_${i}_${j} + volume_${i}_${j} SetMapper volumeMapper_${i}_${j} + volume_${i}_${j} SetProperty volumeProperty + + vtkTransform userMatrix_${i}_${j} + userMatrix_${i}_${j} PostMultiply + userMatrix_${i}_${j} Identity + userMatrix_${i}_${j} Translate -25 -25 -25 + + if { $i == 0 } { + userMatrix_${i}_${j} RotateX [expr $j*90 + 20] + userMatrix_${i}_${j} RotateY 20 + } else { + userMatrix_${i}_${j} RotateX 20 + userMatrix_${i}_${j} RotateY [expr $j*90 + 20] + } + + userMatrix_${i}_${j} Translate [expr $j*55 + 25] [expr $i*55 + 25] 0 + + volume_${i}_${j} SetUserTransform userMatrix_${i}_${j} + + ren1 AddViewProp volume_${i}_${j} + } +} + +volumeMapper_0_0 SetCroppingRegionFlagsToSubVolume +volumeMapper_0_1 SetCroppingRegionFlagsToCross +volumeMapper_0_2 SetCroppingRegionFlagsToInvertedCross +volumeMapper_0_3 SetCroppingRegionFlags 24600 + +volumeMapper_1_0 SetCroppingRegionFlagsToFence +volumeMapper_1_1 SetCroppingRegionFlagsToInvertedFence +volumeMapper_1_2 SetCroppingRegionFlags 1 +volumeMapper_1_3 SetCroppingRegionFlags 67117057 + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 3.0 +renWin Render + + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver "AbortCheckEvent" {TkCheckAbort} + + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/VolumeRendering/Testing/Tcl/volTM2DRotateClip.tcl b/VolumeRendering/Testing/Tcl/volTM2DRotateClip.tcl new file mode 100644 index 0000000..2fa82fa --- /dev/null +++ b/VolumeRendering/Testing/Tcl/volTM2DRotateClip.tcl @@ -0,0 +1,144 @@ +package require vtk + +# Simple volume rendering example. +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff +reader SetDataSpacing 2 2 1 +reader SetDataScalarTypeToUnsignedShort +reader Update + +set readerOutput [reader GetOutput] +$readerOutput SetOrigin -63 -63 -46 + +# Disconnect the output from its reader. First get an extra reference. +$readerOutput Register {} +$readerOutput SetSource {} + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 600 0.0 + opacityTransferFunction AddPoint 2000 1.0 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction ClampingOff + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 1000.0 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 2000.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + +vtkVolumeTextureMapper2D volumeMapper + volumeMapper SetInput $readerOutput + volumeMapper SetMaximumStorageSize 10000000 + +# The data object is now referenced by the connection. +$readerOutput UnRegister {} + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# Create geometric sphere +vtkSphereSource sphereSource + sphereSource SetRadius 65 + sphereSource SetThetaResolution 20 + sphereSource SetPhiResolution 40 + +proc colorCells {} { + vtkMath randomColorGenerator + set input [randomColors GetInput] + set output [randomColors GetOutput] + set numCells [$input GetNumberOfCells] + vtkFloatArray colors + colors SetNumberOfTuples $numCells + + for {set i 0} {$i < $numCells} {incr i} { + colors SetValue $i [randomColorGenerator Random 0 1] + } + + [$output GetCellData] CopyScalarsOff + [$output GetCellData] PassData [$input GetCellData] + [$output GetCellData] SetScalars colors + + colors Delete; #reference counting - it's ok + randomColorGenerator Delete +} + +# Compute random scalars (colors) for each cell +vtkProgrammableAttributeDataFilter randomColors + randomColors SetInputConnection [sphereSource GetOutputPort] + randomColors SetExecuteMethod colorCells + +# This does not need a hierarchical mapper, but hierarchical +# mapper could use a test that has clipping so we use it here +vtkHierarchicalPolyDataMapper sphereMapper + sphereMapper SetInputConnection [randomColors GetOutputPort 0] + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Set up the planes +vtkPlane plane1 +plane1 SetOrigin 0 0 -10 +plane1 SetNormal 0 0 1 + +vtkPlane plane2 +plane2 SetOrigin 0 0 10 +plane2 SetNormal 0 0 -1 + +vtkPlane plane3 +plane3 SetOrigin -10 0 0 +plane3 SetNormal 1 0 0 + +vtkPlane plane4 +plane4 SetOrigin 10 0 0 +plane4 SetNormal -1 0 0 + +sphereMapper AddClippingPlane plane1 +sphereMapper AddClippingPlane plane2 + +volumeMapper AddClippingPlane plane3 +volumeMapper AddClippingPlane plane4 + + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp sphereActor +ren1 AddViewProp volume +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +[ren1 GetActiveCamera] Azimuth 45 +[ren1 GetActiveCamera] Elevation 15 +[ren1 GetActiveCamera] Roll 45 +[ren1 GetActiveCamera] Zoom 2.0 + +wm withdraw . + +iren Initialize + +for { set i 0 } { $i < 5 } { incr i } { + volume RotateY 17 + volume RotateZ 13 + sphereActor RotateX 13 + sphereActor RotateY 17 + renWin Render +} + diff --git a/VolumeRendering/Testing/Tcl/volTM3DCropRegions.tcl b/VolumeRendering/Testing/Tcl/volTM3DCropRegions.tcl new file mode 100644 index 0000000..7fbfb89 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/volTM3DCropRegions.tcl @@ -0,0 +1,115 @@ +package require vtk +package require vtkinteraction + +# Simple volume rendering example. +vtkSLCReader reader + reader SetFileName "$VTK_DATA_ROOT/Data/sphere.slc" + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 0 0.0 + opacityTransferFunction AddPoint 30 0.0 + opacityTransferFunction AddPoint 80 0.5 + opacityTransferFunction AddPoint 255 0.5 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction AddRGBPoint 0.0 0.0 0.0 0.0 + colorTransferFunction AddRGBPoint 64.0 1.0 0.0 0.0 + colorTransferFunction AddRGBPoint 128.0 0.0 0.0 1.0 + colorTransferFunction AddRGBPoint 192.0 0.0 1.0 0.0 + colorTransferFunction AddRGBPoint 255.0 0.0 0.2 0.0 + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + volumeProperty SetInterpolationTypeToLinear + volumeProperty ShadeOn + + +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 600 300 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +for { set i 0 } { $i < 2 } { incr i } { + for { set j 0 } { $j < 4 } { incr j } { + vtkVolumeTextureMapper3D volumeMapper_${i}_${j} + volumeMapper_${i}_${j} SetInputConnection [reader GetOutputPort] + volumeMapper_${i}_${j} SetSampleDistance 0.25 + volumeMapper_${i}_${j} CroppingOn + volumeMapper_${i}_${j} SetCroppingRegionPlanes 17 33 17 33 17 33 + + vtkVolume volume_${i}_${j} + volume_${i}_${j} SetMapper volumeMapper_${i}_${j} + volume_${i}_${j} SetProperty volumeProperty + + vtkTransform userMatrix_${i}_${j} + userMatrix_${i}_${j} PostMultiply + userMatrix_${i}_${j} Identity + userMatrix_${i}_${j} Translate -25 -25 -25 + + if { $i == 0 } { + userMatrix_${i}_${j} RotateX [expr $j*90 + 20] + userMatrix_${i}_${j} RotateY 20 + } else { + userMatrix_${i}_${j} RotateX 20 + userMatrix_${i}_${j} RotateY [expr $j*90 + 20] + } + + userMatrix_${i}_${j} Translate [expr $j*55 + 25] [expr $i*55 + 25] 0 + + volume_${i}_${j} SetUserTransform userMatrix_${i}_${j} + + ren1 AddViewProp volume_${i}_${j} + } +} + +volumeMapper_0_0 SetCroppingRegionFlagsToSubVolume +volumeMapper_0_1 SetCroppingRegionFlagsToCross +volumeMapper_0_2 SetCroppingRegionFlagsToInvertedCross +volumeMapper_0_3 SetCroppingRegionFlags 24600 + +volumeMapper_1_0 SetCroppingRegionFlagsToFence +volumeMapper_1_1 SetCroppingRegionFlagsToInvertedFence +volumeMapper_1_2 SetCroppingRegionFlags 1 +volumeMapper_1_3 SetCroppingRegionFlags 67117057 + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +set valid [volumeMapper_0_0 IsRenderSupported volumeProperty] + +if {!$valid} { + ren1 RemoveAllViewProps + vtkTextActor t + t SetInput "Required Extensions Not Supported" + t SetDisplayPosition 300 150 + [t GetTextProperty] SetJustificationToCentered + ren1 AddViewProp t +} + +ren1 ResetCamera +[ren1 GetActiveCamera] Zoom 3.0 +renWin Render + +proc TkCheckAbort {} { + set foo [renWin GetEventPending] + if {$foo != 0} {renWin SetAbortRender 1} +} +renWin AddObserver AbortCheckEvent {TkCheckAbort} + + +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +wm withdraw . + + + diff --git a/VolumeRendering/Testing/Tcl/volTM3DRotateClip.tcl b/VolumeRendering/Testing/Tcl/volTM3DRotateClip.tcl new file mode 100644 index 0000000..2188f38 --- /dev/null +++ b/VolumeRendering/Testing/Tcl/volTM3DRotateClip.tcl @@ -0,0 +1,149 @@ +package require vtk + +# Simple volume rendering example. +vtkImageReader reader +reader SetDataByteOrderToLittleEndian +reader SetDataExtent 0 63 0 63 1 93 +reader SetFilePrefix "$VTK_DATA_ROOT/Data/headsq/quarter" +reader SetDataMask 0x7fff +reader SetDataSpacing 2 2 1 +reader SetDataScalarTypeToUnsignedShort +reader Update + +vtkImageChangeInformation changeFilter +changeFilter SetInputConnection [reader GetOutputPort] +changeFilter SetOutputOrigin -63 -63 -46 + +# Create transfer functions for opacity and color +vtkPiecewiseFunction opacityTransferFunction + opacityTransferFunction AddPoint 600 0.0 + opacityTransferFunction AddPoint 2000 1.0 + +vtkColorTransferFunction colorTransferFunction + colorTransferFunction ClampingOff + colorTransferFunction AddHSVPoint 0.0 0.01 1.0 1.0 + colorTransferFunction AddHSVPoint 1000.0 0.50 1.0 1.0 + colorTransferFunction AddHSVPoint 2000.0 0.99 1.0 1.0 + colorTransferFunction SetColorSpaceToHSV + +# Create properties, mappers, volume actors, and ray cast function +vtkVolumeProperty volumeProperty + volumeProperty SetColor colorTransferFunction + volumeProperty SetScalarOpacity opacityTransferFunction + +vtkVolumeTextureMapper3D volumeMapper + volumeMapper SetInputConnection [changeFilter GetOutputPort] + volumeMapper SetSampleDistance 0.25 + +vtkVolume volume + volume SetMapper volumeMapper + volume SetProperty volumeProperty + +# Create geometric sphere +vtkSphereSource sphereSource + sphereSource SetRadius 65 + sphereSource SetThetaResolution 20 + sphereSource SetPhiResolution 40 + +# Compute random scalars (colors) for each cell +vtkProgrammableAttributeDataFilter randomColors + randomColors SetInputConnection [sphereSource GetOutputPort] + randomColors SetExecuteMethod colorCells + +proc colorCells {} { + vtkMath randomColorGenerator + set input [randomColors GetInput] + set output [randomColors GetOutput] + set numCells [$input GetNumberOfCells] + vtkFloatArray colors + colors SetNumberOfTuples $numCells + + for {set i 0} {$i < $numCells} {incr i} { + colors SetValue $i [randomColorGenerator Random 0 1] + } + + [$output GetCellData] CopyScalarsOff + [$output GetCellData] PassData [$input GetCellData] + [$output GetCellData] SetScalars colors + + colors Delete; #reference counting - it's ok + randomColorGenerator Delete +} + +# This does not need a hierarchical mapper, but hierarchical +# mapper could use a test that has clipping so we use it here +vtkHierarchicalPolyDataMapper sphereMapper + sphereMapper SetInputConnection [randomColors GetOutputPort 0] + +vtkActor sphereActor + sphereActor SetMapper sphereMapper + +# Set up the planes +vtkPlane plane1 +plane1 SetOrigin 0 0 -10 +plane1 SetNormal 0 0 1 + +vtkPlane plane2 +plane2 SetOrigin 0 0 10 +plane2 SetNormal 0 0 -1 + +vtkPlane plane3 +plane3 SetOrigin -10 0 0 +plane3 SetNormal 1 0 0 + +vtkPlane plane4 +plane4 SetOrigin 10 0 0 +plane4 SetNormal -1 0 0 + +sphereMapper AddClippingPlane plane1 +sphereMapper AddClippingPlane plane2 + +volumeMapper AddClippingPlane plane3 +volumeMapper AddClippingPlane plane4 + + +# Okay now the graphics stuff +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + renWin SetSize 256 256 +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + +[ren1 GetCullers] InitTraversal +set culler [[ren1 GetCullers] GetNextItem] +$culler SetSortingStyleToBackToFront + +ren1 AddViewProp sphereActor +ren1 SetBackground 0.1 0.2 0.4 +renWin Render + +[ren1 GetActiveCamera] Azimuth 45 +[ren1 GetActiveCamera] Elevation 15 +[ren1 GetActiveCamera] Roll 45 +[ren1 GetActiveCamera] Zoom 2.0 + +set valid [volumeMapper IsRenderSupported volumeProperty] + +ren1 AddViewProp volume +if {!$valid} { + ren1 RemoveAllViewProps + vtkTextActor t + t SetInput "Required Extensions Not Supported" + t SetDisplayPosition 128 128 + [t GetTextProperty] SetJustificationToCentered + ren1 AddViewProp t +} + +wm withdraw . + +iren Initialize + +for { set i 0 } { $i < 5 } { incr i } { + volume RotateY 17 + volume RotateZ 13 + sphereActor RotateX 13 + sphereActor RotateY 17 + renWin Render +} + diff --git a/VolumeRendering/vtkDirectionEncoder.cxx b/VolumeRendering/vtkDirectionEncoder.cxx new file mode 100644 index 0000000..fd11e80 --- /dev/null +++ b/VolumeRendering/vtkDirectionEncoder.cxx @@ -0,0 +1,23 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDirectionEncoder.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkDirectionEncoder.h" + +vtkCxxRevisionMacro(vtkDirectionEncoder, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +void vtkDirectionEncoder::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkDirectionEncoder.h b/VolumeRendering/vtkDirectionEncoder.h new file mode 100644 index 0000000..d17c4b9 --- /dev/null +++ b/VolumeRendering/vtkDirectionEncoder.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkDirectionEncoder.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkDirectionEncoder - encode a direction into a one or two byte value +// +// .SECTION Description +// Given a direction, encode it into an integer value. This value should +// be less than 65536, which is the maximum number of encoded directions +// supported by this superclass. A direction encoded is used to encode +// normals in a volume for use during volume rendering, and the +// amount of space that is allocated per normal is 2 bytes. +// This is an abstract superclass - see the subclasses for specific +// implementation details. +// +// .SECTION see also +// vtkRecursiveSphereDirectionEncoder + +#ifndef __vtkDirectionEncoder_h +#define __vtkDirectionEncoder_h + +#include "vtkObject.h" + +class VTK_VOLUMERENDERING_EXPORT vtkDirectionEncoder : public vtkObject +{ +public: + // Description: + // Get the name of this class + vtkTypeRevisionMacro(vtkDirectionEncoder,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Given a normal vector n, return the encoded direction + virtual int GetEncodedDirection( float n[3] )=0; + + // Description: + /// Given an encoded value, return a pointer to the normal vector + virtual float *GetDecodedGradient( int value )=0; + + // Description: + // Return the number of encoded directions + virtual int GetNumberOfEncodedDirections( void )=0; + + // Description: + // Get the decoded gradient table. There are + // this->GetNumberOfEncodedDirections() entries in the table, each + // containing a normal (direction) vector. This is a flat structure - + // 3 times the number of directions floats in an array. + virtual float *GetDecodedGradientTable( void )=0; + +protected: + vtkDirectionEncoder() {}; + ~vtkDirectionEncoder() {}; +private: + vtkDirectionEncoder(const vtkDirectionEncoder&); // Not implemented. + void operator=(const vtkDirectionEncoder&); // Not implemented. +}; + + +#endif + + + + + + + diff --git a/VolumeRendering/vtkEncodedGradientEstimator.cxx b/VolumeRendering/vtkEncodedGradientEstimator.cxx new file mode 100644 index 0000000..8fe372c --- /dev/null +++ b/VolumeRendering/vtkEncodedGradientEstimator.cxx @@ -0,0 +1,379 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEncodedGradientEstimator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEncodedGradientEstimator.h" + +#include "vtkGarbageCollector.h" +#include "vtkImageData.h" +#include "vtkMultiThreader.h" +#include "vtkRecursiveSphereDirectionEncoder.h" +#include "vtkTimerLog.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkEncodedGradientEstimator, "$Revision: 1.1 $"); + +vtkCxxSetObjectMacro(vtkEncodedGradientEstimator, Input, vtkImageData ); + +// Construct a vtkEncodedGradientEstimator with initial values of NULL for +// the Input, EncodedNormal, and GradientMagnitude. Also, +// indicate that the IndexTable has not yet been initialized. The +// GradientMagnitudeRange and the GradientMangitudeTable are +// initialized to default values - these will change in the future +// when magnitude of gradient opacities are included +vtkEncodedGradientEstimator::vtkEncodedGradientEstimator() +{ + this->Input = NULL; + this->EncodedNormals = NULL; + this->EncodedNormalsSize[0] = 0; + this->EncodedNormalsSize[1] = 0; + this->EncodedNormalsSize[2] = 0; + this->GradientMagnitudes = NULL; + this->GradientMagnitudeScale = 1.0; + this->GradientMagnitudeBias = 0.0; + this->Threader = vtkMultiThreader::New(); + this->NumberOfThreads = this->Threader->GetNumberOfThreads(); + this->DirectionEncoder = vtkRecursiveSphereDirectionEncoder::New(); + this->ComputeGradientMagnitudes = 1; + this->CylinderClip = 0; + this->CircleLimits = NULL; + this->CircleLimitsSize = -1; + this->UseCylinderClip = 0; + this->LastUpdateTimeInSeconds = -1.0; + this->LastUpdateTimeInCPUSeconds = -1.0; + this->ZeroNormalThreshold = 0.0; + this->ZeroPad = 1; + this->BoundsClip = 0; + this->Bounds[0] = + this->Bounds[1] = + this->Bounds[2] = + this->Bounds[3] = + this->Bounds[4] = + this->Bounds[5] = 0; + +} + +// Destruct a vtkEncodedGradientEstimator - free up any memory used +vtkEncodedGradientEstimator::~vtkEncodedGradientEstimator() +{ + this->SetInput(NULL); + this->Threader->Delete(); + this->Threader = NULL; + + if ( this->EncodedNormals ) + { + delete [] this->EncodedNormals; + } + + if ( this->GradientMagnitudes ) + { + delete [] this->GradientMagnitudes; + } + + if ( this->DirectionEncoder ) + { + this->DirectionEncoder->UnRegister( this ); + } + + if ( this->CircleLimits ) + { + delete [] this->CircleLimits; + } +} + +void vtkEncodedGradientEstimator::SetZeroNormalThreshold( float v ) +{ + if ( this->ZeroNormalThreshold != v ) + { + if ( v < 0.0 ) + { + vtkErrorMacro( << "The ZeroNormalThreshold must be a value >= 0.0" ); + return; + } + + this->ZeroNormalThreshold = v; + this->Modified(); + } +} + +void +vtkEncodedGradientEstimator::SetDirectionEncoder(vtkDirectionEncoder *direnc) +{ + // If we are setting it to its current value, don't do anything + if ( this->DirectionEncoder == direnc ) + { + return; + } + + // If we already have a direction encoder, unregister it. + if ( this->DirectionEncoder ) + { + this->DirectionEncoder->UnRegister(this); + this->DirectionEncoder = NULL; + } + + // If we are passing in a non-NULL encoder, register it + if ( direnc ) + { + direnc->Register( this ); + } + + // Actually set the encoder, and consider the object Modified + this->DirectionEncoder = direnc; + this->Modified(); +} + +int vtkEncodedGradientEstimator::GetEncodedNormalIndex( int xyzIndex ) +{ + this->Update(); + return *(this->EncodedNormals + xyzIndex); +} + +int vtkEncodedGradientEstimator::GetEncodedNormalIndex( int xIndex, + int yIndex, + int zIndex ) +{ + int ystep, zstep; + + this->Update(); + + // Compute steps through the volume in x, y, and z + ystep = this->InputSize[0]; + zstep = this->InputSize[0] * this->InputSize[1]; + + return *(this->EncodedNormals + zIndex * zstep + yIndex * ystep + xIndex); +} + +unsigned short *vtkEncodedGradientEstimator::GetEncodedNormals() +{ + this->Update(); + + return this->EncodedNormals; +} + +unsigned char *vtkEncodedGradientEstimator::GetGradientMagnitudes() +{ + this->Update(); + + return this->GradientMagnitudes; +} + +void vtkEncodedGradientEstimator::Update( ) +{ + int scalarInputSize[3]; + double scalarInputAspect[3]; + double startSeconds, endSeconds; + double startCPUSeconds, endCPUSeconds; + + if ( !this->Input ) + { + vtkErrorMacro(<< "No input in gradient estimator."); + return; + } + + if ( this->GetMTime() > this->BuildTime || + this->DirectionEncoder->GetMTime() > this->BuildTime || + this->Input->GetMTime() > this->BuildTime || + !this->EncodedNormals ) + { + this->Input->UpdateInformation(); + this->Input->SetUpdateExtentToWholeExtent(); + this->Input->Update(); + + startSeconds = vtkTimerLog::GetUniversalTime(); + startCPUSeconds = vtkTimerLog::GetCPUTime(); + + // Get the dimensions of the data and its aspect ratio + this->Input->GetDimensions( scalarInputSize ); + this->Input->GetSpacing( scalarInputAspect ); + + // If we previously have allocated space for the encoded normals, + // and this space is no longer the right size, delete it + if ( this->EncodedNormalsSize[0] != scalarInputSize[0] || + this->EncodedNormalsSize[1] != scalarInputSize[1] || + this->EncodedNormalsSize[2] != scalarInputSize[2] ) + { + if ( this->EncodedNormals ) + { + delete [] this->EncodedNormals; + this->EncodedNormals = NULL; + } + if ( this->GradientMagnitudes ) + { + delete [] this->GradientMagnitudes; + this->GradientMagnitudes = NULL; + } + } + + // Allocate space for the encoded normals if necessary + if ( !this->EncodedNormals ) + { + this->EncodedNormals = new unsigned short[ scalarInputSize[0] * + scalarInputSize[1] * + scalarInputSize[2] ]; + this->EncodedNormalsSize[0] = scalarInputSize[0]; + this->EncodedNormalsSize[1] = scalarInputSize[1]; + this->EncodedNormalsSize[2] = scalarInputSize[2]; + } + + if ( !this->GradientMagnitudes && this->ComputeGradientMagnitudes ) + { + this->GradientMagnitudes = new unsigned char[ scalarInputSize[0] * + scalarInputSize[1] * + scalarInputSize[2] ]; + } + + // Copy info that multi threaded function will need into temp variables + memcpy( this->InputSize, scalarInputSize, 3 * sizeof(int) ); + // TODO cleanup when double changes are further along + this->InputAspect[0] = static_cast<float>(scalarInputAspect[0]); + this->InputAspect[1] = static_cast<float>(scalarInputAspect[1]); + this->InputAspect[2] = static_cast<float>(scalarInputAspect[2]); + // memcpy( this->InputAspect, scalarInputAspect, 3 * sizeof(float) ); + + if ( this->CylinderClip && + (this->InputSize[0] == this->InputSize[1]) ) + { + this->UseCylinderClip = 1; + this->ComputeCircleLimits( this->InputSize[0] ); + } + else + { + this->UseCylinderClip = 0; + } + this->UpdateNormals(); + + this->BuildTime.Modified(); + + endSeconds = vtkTimerLog::GetUniversalTime(); + endCPUSeconds = vtkTimerLog::GetCPUTime(); + + this->LastUpdateTimeInSeconds = (float)(endSeconds - startSeconds); + this->LastUpdateTimeInCPUSeconds = (float)(endCPUSeconds - startCPUSeconds); + } +} + +void vtkEncodedGradientEstimator::ComputeCircleLimits( int size ) +{ + int *ptr, y; + double w, halfsize, length, start, end; + + if ( this->CircleLimitsSize != size ) + { + if ( this->CircleLimits ) + { + delete [] this->CircleLimits; + } + this->CircleLimits = new int[2*size]; + this->CircleLimitsSize = size; + } + + ptr = this->CircleLimits; + + halfsize = (double)(size-1)/2.0; + + for ( y = 0; y < size; y++ ) + { + w = halfsize - (double)y; + length = (int)( sqrt( (halfsize*halfsize) - (w*w) ) + 0.5 ); + start = halfsize - length - 1; + end = halfsize + length + 1; + start = (start<0)?(0):(start); + end = (end>(size-1))?(size-1):(end); + + *(ptr++) = (int) start; + *(ptr++) = (int) end; + } +} + +// Print the vtkEncodedGradientEstimator +void vtkEncodedGradientEstimator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + if ( this->Input ) + { + os << indent << "Input: (" << this->Input << ")\n"; + } + else + { + os << indent << "Input: (none)\n"; + } + + if ( this->DirectionEncoder ) + { + os << indent << "DirectionEncoder: (" << this->DirectionEncoder << ")\n"; + } + else + { + os << indent << "DirectionEncoder: (none)\n"; + } + + os << indent << "Build Time: " + << this->BuildTime.GetMTime() << endl; + + os << indent << "Gradient Magnitude Scale: " + << this->GradientMagnitudeScale << endl; + + os << indent << "Gradient Magnitude Bias: " + << this->GradientMagnitudeBias << endl; + + os << indent << "Zero Pad: " + << ((this->ZeroPad)?"On":"Off") << endl; + + os << indent << "Bounds Clip: " + << ((this->BoundsClip)?"On":"Off") << endl; + + os << indent << "Bounds: (" + << this->Bounds[0] << ", " << this->Bounds[1] << ", " + << this->Bounds[2] << ", " << this->Bounds[3] << ", " + << this->Bounds[4] << ", " << this->Bounds[5] << ")\n"; + + os << indent << "Zero Normal Threshold: " + << this->ZeroNormalThreshold << endl; + + os << indent << "Compute Gradient Magnitudes: " + << ((this->ComputeGradientMagnitudes)?"On":"Off") << endl; + + os << indent << "Cylinder Clip: " + << ((this->CylinderClip)?"On":"Off") << endl; + + os << indent << "Number Of Threads: " + << this->NumberOfThreads << endl; + + os << indent << "Last Update Time In Seconds: " + << this->LastUpdateTimeInSeconds << endl; + + os << indent << "Last Update Time In CPU Seconds: " + << this->LastUpdateTimeInCPUSeconds << endl; + + // I don't want to print out these variables - they are + // internal and the get methods are included only for access + // within the threaded function + // os << indent << "Use Cylinder Clip: " + // << this->UseCylinderClip << endl; + // os << indent << " Input Size: " + // << this->InputSize << endl; + // os << indent << " Input Aspect Clip: " + // << this->InputAspect << endl; + +} + +//---------------------------------------------------------------------------- +void +vtkEncodedGradientEstimator::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + vtkGarbageCollectorReport(collector, this->Input, "Input"); +} diff --git a/VolumeRendering/vtkEncodedGradientEstimator.h b/VolumeRendering/vtkEncodedGradientEstimator.h new file mode 100644 index 0000000..4bc8851 --- /dev/null +++ b/VolumeRendering/vtkEncodedGradientEstimator.h @@ -0,0 +1,214 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEncodedGradientEstimator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkEncodedGradientEstimator - Superclass for gradient estimation +// .SECTION Description +// vtkEncodedGradientEstimator is an abstract superclass for gradient +// estimation. It takes a scalar input of vtkImageData, computes +// a gradient value for every point, and encodes this value into a +// three byte value (2 for direction, 1 for magnitude) using the +// vtkDirectionEncoder. The direction encoder is defaulted to a +// vtkRecursiveSphereDirectionEncoder, but can be overridden with the +// SetDirectionEncoder method. The scale and the bias values for the gradient +// magnitude are used to convert it into a one byte value according to +// v = m*scale + bias where m is the magnitude and v is the resulting +// one byte value. +// .SECTION see also +// vtkFiniteDifferenceGradientEstimator vtkDirectionEncoder + +#ifndef __vtkEncodedGradientEstimator_h +#define __vtkEncodedGradientEstimator_h + +#include "vtkObject.h" + +class vtkImageData; +class vtkDirectionEncoder; +class vtkMultiThreader; + +class VTK_VOLUMERENDERING_EXPORT vtkEncodedGradientEstimator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkEncodedGradientEstimator,vtkObject); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set/Get the scalar input for which the normals will be + // calculated + virtual void SetInput(vtkImageData*); + vtkGetObjectMacro( Input, vtkImageData ); + + // Description: + // Set/Get the scale and bias for the gradient magnitude + vtkSetMacro( GradientMagnitudeScale, float ); + vtkGetMacro( GradientMagnitudeScale, float ); + vtkSetMacro( GradientMagnitudeBias, float ); + vtkGetMacro( GradientMagnitudeBias, float ); + + // Description: + // Turn on / off the bounding of the normal computation by + // the this->Bounds bounding box + vtkSetClampMacro( BoundsClip, int, 0, 1 ); + vtkGetMacro( BoundsClip, int ); + vtkBooleanMacro( BoundsClip, int ); + + // Description: + // Set / Get the bounds of the computation (used if + // this->ComputationBounds is 1.) The bounds are specified + // xmin, xmax, ymin, ymax, zmin, zmax. + vtkSetVector6Macro( Bounds, int ); + vtkGetVectorMacro( Bounds, int, 6 ); + + // Description: + // Recompute the encoded normals and gradient magnitudes. + void Update( void ); + + // Description: + // Get the encoded normals. + unsigned short *GetEncodedNormals( void ); + + // Description: + // Get the encoded normal at an x,y,z location in the volume + int GetEncodedNormalIndex( int xyz_index ); + int GetEncodedNormalIndex( int x_index, int y_index, int z_index ); + + // Description: + // Get the gradient magnitudes + unsigned char *GetGradientMagnitudes(void); + + // Description: + // Get/Set the number of threads to create when encoding normals + // This defaults to the number of available processors on the machine + vtkSetClampMacro( NumberOfThreads, int, 1, VTK_MAX_THREADS ); + vtkGetMacro( NumberOfThreads, int ); + + // Description: + // Set / Get the direction encoder used to encode normal directions + // to fit within two bytes + void SetDirectionEncoder( vtkDirectionEncoder *direnc ); + vtkGetObjectMacro( DirectionEncoder, vtkDirectionEncoder ); + + // Description: + // If you don't want to compute gradient magnitudes (but you + // do want normals for shading) this can be used. Be careful - if + // if you a non-constant gradient magnitude transfer function and + // you turn this on, it may crash + vtkSetMacro( ComputeGradientMagnitudes, int ); + vtkGetMacro( ComputeGradientMagnitudes, int ); + vtkBooleanMacro( ComputeGradientMagnitudes, int ); + + // Description: + // If the data in each slice is only contained within a circle circumscribed + // within the slice, and the slice is square, then don't compute anything + // outside the circle. This circle through the slices forms a cylinder. + vtkSetMacro( CylinderClip, int ); + vtkGetMacro( CylinderClip, int ); + vtkBooleanMacro( CylinderClip, int ); + + // Description: + // Get the time required for the last update in seconds or cpu seconds + vtkGetMacro( LastUpdateTimeInSeconds, float ); + vtkGetMacro( LastUpdateTimeInCPUSeconds, float ); + + vtkGetMacro( UseCylinderClip, int ); + int *GetCircleLimits() { return this->CircleLimits; }; + + // Description: + // Set / Get the ZeroNormalThreshold - this defines the minimum magnitude + // of a gradient that is considered sufficient to define a + // direction. Gradients with magnitudes at or less than this value are given + // a "zero normal" index. These are handled specially in the shader, + // and you can set the intensity of light for these zero normals in + // the gradient shader. + void SetZeroNormalThreshold( float v ); + vtkGetMacro( ZeroNormalThreshold, float ); + + // Description: + // Assume that the data value outside the volume is zero when + // computing normals. + vtkSetClampMacro( ZeroPad, int, 0, 1 ); + vtkGetMacro( ZeroPad, int ); + vtkBooleanMacro( ZeroPad, int ); + + + // These variables should be protected but are being + // made public to be accessible to the templated function. + // We used to have the templated function as a friend, but + // this does not work with all compilers + + // The input scalar data on which the normals are computed + vtkImageData *Input; + + // The encoded normals (2 bytes) and the size of the encoded normals + unsigned short *EncodedNormals; + int EncodedNormalsSize[3]; + + // The magnitude of the gradient array and the size of this array + unsigned char *GradientMagnitudes; + + // The time at which the normals were last built + vtkTimeStamp BuildTime; + +//BTX + vtkGetVectorMacro( InputSize, int, 3 ); + vtkGetVectorMacro( InputAspect, float, 3 ); +//ETX + +protected: + vtkEncodedGradientEstimator(); + ~vtkEncodedGradientEstimator(); + + virtual void ReportReferences(vtkGarbageCollector*); + + // The number of threads to use when encoding normals + int NumberOfThreads; + + vtkMultiThreader *Threader; + + vtkDirectionEncoder *DirectionEncoder; + + virtual void UpdateNormals( void ) = 0; + + float GradientMagnitudeScale; + float GradientMagnitudeBias; + + float LastUpdateTimeInSeconds; + float LastUpdateTimeInCPUSeconds; + + float ZeroNormalThreshold; + + int CylinderClip; + int *CircleLimits; + int CircleLimitsSize; + int UseCylinderClip; + void ComputeCircleLimits( int size ); + + int BoundsClip; + int Bounds[6]; + + int InputSize[3]; + float InputAspect[3]; + + int ComputeGradientMagnitudes; + + int ZeroPad; + +private: + vtkEncodedGradientEstimator(const vtkEncodedGradientEstimator&); // Not implemented. + void operator=(const vtkEncodedGradientEstimator&); // Not implemented. +}; + + +#endif + diff --git a/VolumeRendering/vtkEncodedGradientShader.cxx b/VolumeRendering/vtkEncodedGradientShader.cxx new file mode 100644 index 0000000..2f93aba --- /dev/null +++ b/VolumeRendering/vtkEncodedGradientShader.cxx @@ -0,0 +1,581 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEncodedGradientShader.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkEncodedGradientShader.h" + +#include "vtkCamera.h" +#include "vtkDirectionEncoder.h" +#include "vtkEncodedGradientEstimator.h" +#include "vtkLight.h" +#include "vtkLightCollection.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkEncodedGradientShader, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkEncodedGradientShader); + +vtkEncodedGradientShader::vtkEncodedGradientShader() +{ + int i, j; + + for ( j = 0; j < VTK_MAX_SHADING_TABLES; j++ ) + { + this->ShadingTableVolume[j] = NULL; + this->ShadingTableSize[j] = 0; + for ( i = 0; i < 6; i++ ) + { + this->ShadingTable[j][i] = NULL; + } + } + + this->ZeroNormalDiffuseIntensity = 0.0; + this->ZeroNormalSpecularIntensity = 0.0; + this->ActiveComponent = 0; +} + +vtkEncodedGradientShader::~vtkEncodedGradientShader() +{ + int i, j; + + for ( j = 0; j < VTK_MAX_SHADING_TABLES; j++ ) + { + for ( i=0; i<6; i++ ) + { + if ( this->ShadingTable[j][i] ) + { + delete [] this->ShadingTable[j][i]; + } + } + } +} + +float *vtkEncodedGradientShader::GetRedDiffuseShadingTable( vtkVolume *vol ) +{ + int index; + + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == vol ) + { + break; + } + } + + if ( index == VTK_MAX_SHADING_TABLES ) + { + vtkErrorMacro( << "No shading table found for that volume!" ); + return NULL; + } + + return this->ShadingTable[index][0]; +} + +float *vtkEncodedGradientShader::GetGreenDiffuseShadingTable( vtkVolume *vol ) +{ + int index; + + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == vol ) + { + break; + } + } + + if ( index == VTK_MAX_SHADING_TABLES ) + { + vtkErrorMacro( << "No shading table found for that volume!" ); + return NULL; + } + + return this->ShadingTable[index][1]; +} + +float *vtkEncodedGradientShader::GetBlueDiffuseShadingTable( vtkVolume *vol ) +{ + int index; + + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == vol ) + { + break; + } + } + + if ( index == VTK_MAX_SHADING_TABLES ) + { + vtkErrorMacro( << "No shading table found for that volume!" ); + return NULL; + } + + return this->ShadingTable[index][2]; +} + +float *vtkEncodedGradientShader::GetRedSpecularShadingTable( vtkVolume *vol ) +{ + int index; + + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == vol ) + { + break; + } + } + + if ( index == VTK_MAX_SHADING_TABLES ) + { + vtkErrorMacro( << "No shading table found for that volume!" ); + return NULL; + } + + return this->ShadingTable[index][3]; +} + +float *vtkEncodedGradientShader::GetGreenSpecularShadingTable( vtkVolume *vol ) +{ + int index; + + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == vol ) + { + break; + } + } + + if ( index == VTK_MAX_SHADING_TABLES ) + { + vtkErrorMacro( << "No shading table found for that volume!" ); + return NULL; + } + + return this->ShadingTable[index][4]; +} + +float *vtkEncodedGradientShader::GetBlueSpecularShadingTable( vtkVolume *vol ) +{ + int index; + + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == vol ) + { + break; + } + } + + if ( index == VTK_MAX_SHADING_TABLES ) + { + vtkErrorMacro( << "No shading table found for that volume!" ); + return NULL; + } + + return this->ShadingTable[index][5]; +} + +void vtkEncodedGradientShader::UpdateShadingTable( + vtkRenderer *ren, vtkVolume *vol, + vtkEncodedGradientEstimator *gradest) +{ + double lightDirection[3], material[4], lightColor[3]; + double lightPosition[3], lightFocalPoint[3]; + double lightIntensity, viewDirection[3]; + double cameraPosition[3], cameraFocalPoint[3], mag; + vtkLightCollection *lightCollection; + vtkLight *light; + double norm; + int update_flag; + vtkVolumeProperty *property; + vtkTransform *transform; + vtkMatrix4x4 *m; + double in[4], out[4], zero[4]; + int index; + + // Figure out which shading table we are working with + // First search through all existing ones, then if one + // is not found, use the first available index + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == vol ) + { + break; + } + } + + if ( index == VTK_MAX_SHADING_TABLES ) + { + for ( index = 0; index < VTK_MAX_SHADING_TABLES; index++ ) + { + if ( this->ShadingTableVolume[index] == NULL ) + { + this->ShadingTableVolume[index] = vol; + break; + } + } + } + if ( index == VTK_MAX_SHADING_TABLES ) + { + vtkErrorMacro( << "Too many shading tables!\n" << + "Increase limit VTK_MAX_SHADING_TABLES and recompile!" ); + return; + } + + transform = vtkTransform::New(); + m = vtkMatrix4x4::New(); + + vol->GetMatrix(m); + transform->SetMatrix(m); + transform->Inverse(); + + property = vol->GetProperty(); + + material[0] = property->GetAmbient(this->ActiveComponent); + material[1] = property->GetDiffuse(this->ActiveComponent); + material[2] = property->GetSpecular(this->ActiveComponent); + material[3] = property->GetSpecularPower(this->ActiveComponent); + + + update_flag = 0; + + ren->GetActiveCamera()->GetPosition( cameraPosition ); + ren->GetActiveCamera()->GetFocalPoint( cameraFocalPoint ); + + viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0]; + viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1]; + viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2]; + + mag = sqrt( (double)( + viewDirection[0] * viewDirection[0] + + viewDirection[1] * viewDirection[1] + + viewDirection[2] * viewDirection[2] ) ); + + if ( mag ) + { + viewDirection[0] /= mag; + viewDirection[1] /= mag; + viewDirection[2] /= mag; + } + + memcpy( in, viewDirection, 3*sizeof(double) ); + in[3] = 1.0; + transform->MultiplyPoint( in, out ); + viewDirection[0] = out[0] / out[3]; + viewDirection[1] = out[1] / out[3]; + viewDirection[2] = out[2] / out[3]; + + in[0] = 0.0; + in[1] = 0.0; + in[2] = 0.0; + transform->MultiplyPoint( in, zero ); + zero[0] /= zero[3]; + zero[1] /= zero[3]; + zero[2] /= zero[3]; + viewDirection[0] -= zero[0]; + viewDirection[1] -= zero[1]; + viewDirection[2] -= zero[2]; + + // Loop through all lights and compute a shading table. For + // the first light, pass in an update_flag of 0, which means + // overwrite the shading table. For each light after that, pass + // in an update flag of 1, which means add to the shading table. + // All lights are forced to be directional light sources + // regardless of what they really are + + // Set up the lights for traversal + lightCollection = ren->GetLights(); + + // In rare cases there are no lights + vtkLight *artificialLight=NULL; + if ( lightCollection->GetNumberOfItems() == 0 ) + { + artificialLight = vtkLight::New(); + artificialLight->SetIntensity(0.0); + lightCollection->AddItem(artificialLight); + } + + vtkCollectionSimpleIterator sit; + lightCollection->InitTraversal(sit); + while ( (light = lightCollection->GetNextLight(sit)) != NULL ) + { + if ( ! light->GetSwitch() ) + { + continue; + } + + // Get the light color, position, focal point, and intensity + light->GetColor( lightColor ); + light->GetTransformedPosition( lightPosition ); + light->GetTransformedFocalPoint( lightFocalPoint ); + lightIntensity = light->GetIntensity( ); + + + // Compute the light direction and normalize it + lightDirection[0] = lightFocalPoint[0] - lightPosition[0]; + lightDirection[1] = lightFocalPoint[1] - lightPosition[1]; + lightDirection[2] = lightFocalPoint[2] - lightPosition[2]; + + norm = sqrt( (double) ( lightDirection[0] * lightDirection[0] + + lightDirection[1] * lightDirection[1] + + lightDirection[2] * lightDirection[2] ) ); + + lightDirection[0] /= -norm; + lightDirection[1] /= -norm; + lightDirection[2] /= -norm; + + memcpy( in, lightDirection, 3*sizeof(double) ); + transform->MultiplyPoint( in, out ); + lightDirection[0] = out[0] / out[3] - zero[0]; + lightDirection[1] = out[1] / out[3] - zero[1]; + lightDirection[2] = out[2] / out[3] - zero[2]; + + // Build / Add to the shading table + this->BuildShadingTable( index, lightDirection, lightColor, + lightIntensity, viewDirection, + material, ren->GetTwoSidedLighting(), + gradest, update_flag ); + + update_flag = 1; + }//while there is a light in the list of lights + + if ( artificialLight ) + { + lightCollection->RemoveItem(artificialLight); + artificialLight->Delete(); + } + + transform->Delete(); + m->Delete(); +} + + +// Build a shading table for a light with the given direction and +// color, for a material of the given type. material[0] = ambient, +// material[1] = diffuse, material[2] = specular, material[3] = +// specular exponent. If the ambient flag is 1, then ambient +// illumination is added. If not, then this means we are calculating +// the "other side" of two sided lighting, so no ambient intensity +// is added in. If update_flag is 0, the table is overwritten +// with the new values. If update_flag is 1, the new intensity values +// are added into the table. This way multiple light sources can +// be handled. There is one shading table per volume, and the index +// value indicates which index table is to be updated +void vtkEncodedGradientShader::BuildShadingTable( int index, + double lightDirection[3], + double lightColor[3], + double lightIntensity, + double viewDirection[3], + double material[4], + int twoSided, + vtkEncodedGradientEstimator *gradest, + int updateFlag ) +{ + double lx, ly, lz; + float n_dot_l; + float n_dot_v; + int i; + float *nptr; + float *sdr_ptr; + float *sdg_ptr; + float *sdb_ptr; + float *ssr_ptr; + float *ssg_ptr; + float *ssb_ptr; + float Ka, Es, Kd_intensity, Ks_intensity; + double half_x, half_y, half_z; + float mag, n_dot_h, specular_value; + int norm_size; + + // Move to local variables + lx = lightDirection[0]; + ly = lightDirection[1]; + lz = lightDirection[2]; + + half_x = lx - viewDirection[0]; + half_y = ly - viewDirection[1]; + half_z = lz - viewDirection[2]; + + mag = sqrt( (double)(half_x*half_x + half_y*half_y + half_z*half_z ) ); + + if( mag != 0.0 ) + { + half_x /= mag; + half_y /= mag; + half_z /= mag; + } + + Ka = material[0] * lightIntensity; + Es = material[3]; + Kd_intensity = material[1] * lightIntensity; + Ks_intensity = material[2] * lightIntensity; + + nptr = gradest->GetDirectionEncoder()->GetDecodedGradientTable(); + + norm_size = gradest->GetDirectionEncoder()->GetNumberOfEncodedDirections(); + + if ( this->ShadingTableSize[index] != norm_size ) + { + for ( i=0; i<6; i++ ) + { + if ( this->ShadingTable[index][i] ) + { + delete [] this->ShadingTable[index][i]; + } + this->ShadingTable[index][i] = new float[norm_size]; + } + this->ShadingTableSize[index] = norm_size; + } + + sdr_ptr = this->ShadingTable[index][0]; + sdg_ptr = this->ShadingTable[index][1]; + sdb_ptr = this->ShadingTable[index][2]; + + ssr_ptr = this->ShadingTable[index][3]; + ssg_ptr = this->ShadingTable[index][4]; + ssb_ptr = this->ShadingTable[index][5]; + + // For each possible normal, compute the intensity of light at + // a location with that normal, and the given lighting and + // material properties + for ( i = 0; i < norm_size; i++ ) + { + // If we have a zero normal, treat it specially + if ( ( *(nptr+0) == 0.0 ) && + ( *(nptr+1) == 0.0 ) && + ( *(nptr+2) == 0.0 ) ) + { + // If we are not updating, initial everything to 0.0 + if ( !updateFlag ) + { + *(sdr_ptr) = 0.0; + *(sdg_ptr) = 0.0; + *(sdb_ptr) = 0.0; + + *(ssr_ptr) = 0.0; + *(ssg_ptr) = 0.0; + *(ssb_ptr) = 0.0; + } + + // Now add in ambient + *(sdr_ptr) += Ka * lightColor[0]; + *(sdg_ptr) += Ka * lightColor[1]; + *(sdb_ptr) += Ka * lightColor[2]; + + // Add in diffuse + *(sdr_ptr) += + (Kd_intensity * this->ZeroNormalDiffuseIntensity * lightColor[0]); + *(sdg_ptr) += + (Kd_intensity * this->ZeroNormalDiffuseIntensity * lightColor[1]); + *(sdb_ptr) += + (Kd_intensity * this->ZeroNormalDiffuseIntensity * lightColor[2]); + + // Add in specular + *(ssr_ptr) += this->ZeroNormalSpecularIntensity * lightColor[0]; + *(ssg_ptr) += this->ZeroNormalSpecularIntensity * lightColor[1]; + *(ssb_ptr) += this->ZeroNormalSpecularIntensity * lightColor[2]; + } + else + { + // The dot product between the normal and the light vector + // used for diffuse illumination + n_dot_l = (*(nptr+0) * lx + *(nptr+1) * ly + *(nptr+2) * lz); + + // The dot product between the normal and the halfway vector + // used for specular illumination + n_dot_h = (*(nptr+0) * half_x + *(nptr+1) * half_y + *(nptr+2) * half_z); + + // Flip the normal if two sided lighting is on and the normal + // is pointing away from the viewer + if ( twoSided ) + { + // The dot product between the normal and the view vector + // used for two sided lighting + n_dot_v = (*(nptr+0) * viewDirection[0] + + *(nptr+1) * viewDirection[1] + + *(nptr+2) * viewDirection[2]); + + if ( n_dot_v > 0.0 ) + { + n_dot_l = -n_dot_l; + n_dot_h = -n_dot_h; + } + } + + // If we are updating, then begin by adding in ambient + if ( updateFlag ) + { + *(sdr_ptr) += Ka * lightColor[0]; + *(sdg_ptr) += Ka * lightColor[1]; + *(sdb_ptr) += Ka * lightColor[2]; + } + // Otherwise begin by setting the value to the ambient contribution + else + { + *(sdr_ptr) = Ka * lightColor[0]; + *(sdg_ptr) = Ka * lightColor[1]; + *(sdb_ptr) = Ka * lightColor[2]; + *(ssr_ptr) = 0.0; + *(ssg_ptr) = 0.0; + *(ssb_ptr) = 0.0; + } + + // If there is some diffuse contribution, add it in + if ( n_dot_l > 0 ) + { + *(sdr_ptr) += (Kd_intensity * n_dot_l * lightColor[0]); + *(sdg_ptr) += (Kd_intensity * n_dot_l * lightColor[1]); + *(sdb_ptr) += (Kd_intensity * n_dot_l * lightColor[2]); + + if ( n_dot_h > 0.001 ) + { + specular_value = Ks_intensity * pow( (double)n_dot_h, (double)Es ); + *(ssr_ptr) += specular_value * lightColor[0]; + *(ssg_ptr) += specular_value * lightColor[1]; + *(ssb_ptr) += specular_value * lightColor[2]; + } + } + } + + // Increment all the pointers + nptr += 3; + sdr_ptr++; + sdg_ptr++; + sdb_ptr++; + ssr_ptr++; + ssg_ptr++; + ssb_ptr++; + } +} + + +// Print the vtkEncodedGradientShader +void vtkEncodedGradientShader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Zero Normal Diffuse Intensity: " << + this->ZeroNormalDiffuseIntensity << endl; + + os << indent << "Zero Normal Specular Intensity: " << + this->ZeroNormalSpecularIntensity << endl; + os << indent << "ActiveComponent: " << this->ActiveComponent << endl; +} + diff --git a/VolumeRendering/vtkEncodedGradientShader.h b/VolumeRendering/vtkEncodedGradientShader.h new file mode 100644 index 0000000..cb6d838 --- /dev/null +++ b/VolumeRendering/vtkEncodedGradientShader.h @@ -0,0 +1,128 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkEncodedGradientShader.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkEncodedGradientShader - Compute shading tables for encoded normals. +// +// .SECTION Description +// vtkEncodedGradientShader computes shading tables for encoded normals +// that indicates the amount of diffuse and specular illumination that is +// received from all light sources at a surface location with that normal. +// For diffuse illumination this is accurate, but for specular illumination +// it is approximate for perspective projections since the center view +// direction is always used as the view direction. Since the shading table is +// dependent on the volume (for the transformation that must be applied to +// the normals to put them into world coordinates) there is a shading table +// per volume. This is necessary because multiple volumes can share a +// volume mapper. + +#ifndef __vtkEncodedGradientShader_h +#define __vtkEncodedGradientShader_h + +#include "vtkObject.h" + +class vtkVolume; +class vtkRenderer; +class vtkEncodedGradientEstimator; + +#define VTK_MAX_SHADING_TABLES 100 + +class VTK_VOLUMERENDERING_EXPORT vtkEncodedGradientShader : public vtkObject +{ +public: + static vtkEncodedGradientShader *New(); + vtkTypeRevisionMacro(vtkEncodedGradientShader,vtkObject); + + // Description: + // Print the vtkEncodedGradientShader + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set / Get the intensity diffuse / specular light used for the + // zero normals. + vtkSetClampMacro( ZeroNormalDiffuseIntensity, float, 0.0, 1.0); + vtkGetMacro( ZeroNormalDiffuseIntensity, float ); + vtkSetClampMacro( ZeroNormalSpecularIntensity, float, 0.0, 1.0); + vtkGetMacro( ZeroNormalSpecularIntensity, float ); + + // Description: + // Cause the shading table to be updated + void UpdateShadingTable( vtkRenderer *ren, vtkVolume *vol, + vtkEncodedGradientEstimator *gradest); + + // Description: + // Get the red/green/blue shading table. + float *GetRedDiffuseShadingTable( vtkVolume *vol ); + float *GetGreenDiffuseShadingTable( vtkVolume *vol ); + float *GetBlueDiffuseShadingTable( vtkVolume *vol ); + float *GetRedSpecularShadingTable( vtkVolume *vol ); + float *GetGreenSpecularShadingTable( vtkVolume *vol ); + float *GetBlueSpecularShadingTable( vtkVolume *vol ); + + // Description: + // Set the active component for shading. This component's + // ambient / diffuse / specular / specular power values will + // be used to create the shading table. The default is 1.0 + vtkSetClampMacro( ActiveComponent, int, 0, 3 ); + vtkGetMacro( ActiveComponent, int ); + +protected: + vtkEncodedGradientShader(); + ~vtkEncodedGradientShader(); + + // Description: + // Build a shading table for a light with the specified direction, + // and color for an object of the specified material properties. + // material[0] = ambient, material[1] = diffuse, material[2] = specular + // and material[3] = specular exponent. If the ambient flag is 1, + // then ambient illumination is added. If not, then this means we + // are calculating the "other side" of two sided lighting, so no + // ambient intensity is added in. If the update flag is 0, + // the shading table is overwritten with these new shading values. + // If the updateFlag is 1, then the computed light contribution is + // added to the current shading table values. There is one shading + // table per volume, and the index value indicated which index table + // should be used. It is computed in the UpdateShadingTable method. + void BuildShadingTable( int index, + double lightDirection[3], + double lightColor[3], + double lightIntensity, + double viewDirection[3], + double material[4], + int twoSided, + vtkEncodedGradientEstimator *gradest, + int updateFlag ); + + // The six shading tables (r diffuse ,g diffuse ,b diffuse, + // r specular, g specular, b specular ) - with an entry for each + // encoded normal plus one entry at the end for the zero normal + // There is one shading table per volume listed in the ShadingTableVolume + // array. A null entry indicates an available slot. + float *ShadingTable[VTK_MAX_SHADING_TABLES][6]; + vtkVolume *ShadingTableVolume[VTK_MAX_SHADING_TABLES]; + int ShadingTableSize[VTK_MAX_SHADING_TABLES]; + + int ActiveComponent; + + // The intensity of light used for the zero normals, since it + // can not be computed from the normal angles. Defaults to 0.0. + float ZeroNormalDiffuseIntensity; + float ZeroNormalSpecularIntensity; +private: + vtkEncodedGradientShader(const vtkEncodedGradientShader&); // Not implemented. + void operator=(const vtkEncodedGradientShader&); // Not implemented. +}; + + +#endif diff --git a/VolumeRendering/vtkFiniteDifferenceGradientEstimator.cxx b/VolumeRendering/vtkFiniteDifferenceGradientEstimator.cxx new file mode 100644 index 0000000..9daa328 --- /dev/null +++ b/VolumeRendering/vtkFiniteDifferenceGradientEstimator.cxx @@ -0,0 +1,380 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFiniteDifferenceGradientEstimator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFiniteDifferenceGradientEstimator.h" + +#include "vtkCharArray.h" +#include "vtkDirectionEncoder.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkImageData.h" +#include "vtkIntArray.h" +#include "vtkLongArray.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkShortArray.h" +#include "vtkUnsignedCharArray.h" +#include "vtkUnsignedIntArray.h" +#include "vtkUnsignedLongArray.h" +#include "vtkUnsignedShortArray.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFiniteDifferenceGradientEstimator, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkFiniteDifferenceGradientEstimator); + +// This is the templated function that actually computes the EncodedNormal +// and the GradientMagnitude +template <class T> +void vtkComputeGradients( + vtkFiniteDifferenceGradientEstimator *estimator, T *data_ptr, + int thread_id, int thread_count ) +{ + int xstep, ystep, zstep; + int x, y, z; + int offset; + int x_start, x_limit; + int y_start, y_limit; + int z_start, z_limit; + int useClip; + int *clip; + T *dptr; + unsigned char *gptr; + unsigned short *nptr; + float n[3], t; + float gvalue; + float zeroNormalThreshold; + int useBounds; + int bounds[6]; + int size[3]; + float aspect[3]; + int xlow, xhigh; + float scale, bias; + int computeGradientMagnitudes; + vtkDirectionEncoder *direction_encoder; + int zeroPad; + + estimator->GetInputSize( size ); + estimator->GetInputAspect( aspect ); + computeGradientMagnitudes = estimator->GetComputeGradientMagnitudes(); + scale = estimator->GetGradientMagnitudeScale(); + bias = estimator->GetGradientMagnitudeBias(); + zeroPad = estimator->GetZeroPad(); + + // adjust the aspect + aspect[0] = aspect[0] * 2.0 * estimator->SampleSpacingInVoxels; + aspect[1] = aspect[1] * 2.0 * estimator->SampleSpacingInVoxels; + aspect[2] = aspect[2] * 2.0 * estimator->SampleSpacingInVoxels; + + // Compute steps through the volume in x, y, and z + xstep = 1; + ystep = size[0]; + zstep = size[0] * size[1]; + + // Multiply by the spacing used for normal estimation + xstep *= estimator->SampleSpacingInVoxels; + ystep *= estimator->SampleSpacingInVoxels; + zstep *= estimator->SampleSpacingInVoxels; + + // Get the length at or below which normals are considered to + // be "zero" + zeroNormalThreshold = estimator->GetZeroNormalThreshold(); + + useBounds = estimator->GetBoundsClip(); + + // Compute an offset based on the thread_id. The volume will + // be broken into large slabs (thread_count slabs). For this thread + // we need to access the correct slab. Also compute the z plane that + // this slab starts on, and the z limit of this slab (one past the + // end of the slab) + if ( useBounds ) + { + estimator->GetBounds( bounds ); + x_start = bounds[0]; + x_limit = bounds[1]+1; + y_start = bounds[2]; + y_limit = bounds[3]+1; + z_start = (int)(( (float)thread_id / (float)thread_count ) * + (float)(bounds[5]-bounds[4]+1) ) + bounds[4]; + z_limit = (int)(( (float)(thread_id + 1) / (float)thread_count ) * + (float)(bounds[5]-bounds[4]+1) ) + bounds[4]; + } + else + { + x_start = 0; + x_limit = size[0]; + y_start = 0; + y_limit = size[1]; + z_start = (int)(( (float)thread_id / (float)thread_count ) * + size[2] ); + z_limit = (int)(( (float)(thread_id + 1) / (float)thread_count ) * + size[2] ); + } + + // Do final error checking on limits - make sure they are all within bounds + // of the scalar input + + x_start = (x_start<0)?(0):(x_start); + y_start = (y_start<0)?(0):(y_start); + z_start = (z_start<0)?(0):(z_start); + + x_limit = (x_limit>size[0])?(size[0]):(x_limit); + y_limit = (y_limit>size[1])?(size[1]):(y_limit); + z_limit = (z_limit>size[2])?(size[2]):(z_limit); + + + direction_encoder = estimator->GetDirectionEncoder(); + + useClip = estimator->GetUseCylinderClip(); + clip = estimator->GetCircleLimits(); + + // Loop through all the data and compute the encoded normal and + // gradient magnitude for each scalar location + for ( z = z_start; z < z_limit; z++ ) + { + for ( y = y_start; y < y_limit; y++ ) + { + if ( useClip ) + { + xlow = ((clip[2*y])>x_start)?(clip[2*y]):(x_start); + xhigh = ((clip[2*y+1]+1)<x_limit)?(clip[2*y+1]+1):(x_limit); + } + else + { + xlow = x_start; + xhigh = x_limit; + } + offset = z * size[0] * size[1] + y * size[0] + xlow; + + // Set some pointers + dptr = data_ptr + offset; + nptr = estimator->EncodedNormals + offset; + gptr = estimator->GradientMagnitudes + offset; + + for ( x = xlow; x < xhigh; x++ ) + { + + // Use a central difference method if possible, + // otherwise use a forward or backward difference if + // we are on the edge + + // Compute the X component + if ( x < estimator->SampleSpacingInVoxels ) + { + if ( zeroPad ) + { + n[0] = -((float)*(dptr+xstep)); + } + else + { + n[0] = 2.0*((float)*(dptr) - (float)*(dptr+xstep)); + } + } + else if ( x >= size[0] - estimator->SampleSpacingInVoxels ) + { + if ( zeroPad ) + { + n[0] = ((float)*(dptr-xstep)); + } + else + { + n[0] = 2.0*((float)*(dptr-xstep) - (float)*(dptr)); + } + } + else + { + n[0] = (float)*(dptr-xstep) - (float)*(dptr+xstep); + } + + // Compute the Y component + if ( y < estimator->SampleSpacingInVoxels ) + { + if ( zeroPad ) + { + n[1] = -((float)*(dptr+ystep)); + } + else + { + n[1] = 2.0*((float)*(dptr) - (float)*(dptr+ystep)); + } + } + else if ( y >= size[1] - estimator->SampleSpacingInVoxels ) + { + if ( zeroPad ) + { + n[1] = ((float)*(dptr-ystep)); + } + else + { + n[1] = 2.0*((float)*(dptr-ystep) - (float)*(dptr)); + } + } + else + { + n[1] = (float)*(dptr-ystep) - (float)*(dptr+ystep); + } + + // Compute the Z component + if ( z < estimator->SampleSpacingInVoxels ) + { + if ( zeroPad ) + { + n[2] = -((float)*(dptr+zstep)); + } + else + { + n[2] = 2.0*((float)*(dptr) - (float)*(dptr+zstep)); + } + } + else if ( z >= size[2] - estimator->SampleSpacingInVoxels ) + { + if ( zeroPad ) + { + n[2] = ((float)*(dptr-zstep)); + } + else + { + n[2] = 2.0*((float)*(dptr-zstep) - (float)*(dptr)); + } + } + else + { + n[2] = (float)*(dptr-zstep) - (float)*(dptr+zstep); + } + + // Take care of the aspect ratio of the data + // Scaling in the vtkVolume is isotropic, so this is the + // only place we have to worry about non-isotropic scaling. + n[0] /= aspect[0]; + n[1] /= aspect[1]; + n[2] /= aspect[2]; + + // Compute the gradient magnitude + t = sqrt( (double)( n[0]*n[0] + + n[1]*n[1] + + n[2]*n[2] ) ); + + if ( computeGradientMagnitudes ) + { + // Encode this into an 8 bit value + gvalue = (t + bias) * scale; + + if ( gvalue < 0.0 ) + { + *gptr = 0; + } + else if ( gvalue > 255.0 ) + { + *gptr = 255; + } + else + { + *gptr = (unsigned char) gvalue; + } + gptr++; + } + + // Normalize the gradient direction + if ( t > zeroNormalThreshold ) + { + n[0] /= t; + n[1] /= t; + n[2] /= t; + } + else + { + n[0] = n[1] = n[2] = 0.0; + } + + // Convert the gradient direction into an encoded index value + *nptr = direction_encoder->GetEncodedDirection( n ); + nptr++; + dptr++; + + } + } + } +} + +// Construct a vtkFiniteDifferenceGradientEstimator +vtkFiniteDifferenceGradientEstimator::vtkFiniteDifferenceGradientEstimator() +{ + this->SampleSpacingInVoxels = 1; +} + +// Destruct a vtkFiniteDifferenceGradientEstimator - free up any memory used +vtkFiniteDifferenceGradientEstimator::~vtkFiniteDifferenceGradientEstimator() +{ +} + +static VTK_THREAD_RETURN_TYPE vtkSwitchOnDataType( void *arg ) +{ + vtkFiniteDifferenceGradientEstimator *estimator; + int thread_count; + int thread_id; + vtkDataArray *scalars; + + thread_id = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + thread_count = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + estimator = (vtkFiniteDifferenceGradientEstimator *) + (((vtkMultiThreader::ThreadInfo *)(arg))->UserData); + scalars = estimator->Input->GetPointData()->GetScalars(); + + if (scalars == NULL) + { + return VTK_THREAD_RETURN_VALUE; + } + + // Find the data type of the Input and call the correct + // templated function to actually compute the normals and magnitudes + + switch ( scalars->GetDataType() ) + { + vtkTemplateMacro( + vtkComputeGradients(estimator, + static_cast<VTK_TT*>(scalars->GetVoidPointer(0)), + thread_id, thread_count) + ); + default: + vtkGenericWarningMacro("unable to encode scalar type!"); + } + + return VTK_THREAD_RETURN_VALUE; +} + + +// This method is used to compute the encoded normal and the +// magnitude of the gradient for each voxel location in the +// Input. +void vtkFiniteDifferenceGradientEstimator::UpdateNormals( ) +{ + vtkDebugMacro( << "Updating Normals!" ); + this->Threader->SetNumberOfThreads( this->NumberOfThreads ); + + this->Threader->SetSingleMethod( vtkSwitchOnDataType, + (vtkObject *)this ); + + this->Threader->SingleMethodExecute(); +} + +// Print the vtkFiniteDifferenceGradientEstimator +void vtkFiniteDifferenceGradientEstimator::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Sample spacing in voxels: " << + this->SampleSpacingInVoxels << endl; +} diff --git a/VolumeRendering/vtkFiniteDifferenceGradientEstimator.h b/VolumeRendering/vtkFiniteDifferenceGradientEstimator.h new file mode 100644 index 0000000..1d39772 --- /dev/null +++ b/VolumeRendering/vtkFiniteDifferenceGradientEstimator.h @@ -0,0 +1,75 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFiniteDifferenceGradientEstimator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkFiniteDifferenceGradientEstimator - Use finite differences to estimate gradient. +// +// .SECTION Description +// vtkFiniteDifferenceGradientEstimator is a concrete subclass of +// vtkEncodedGradientEstimator that uses a central differences technique to +// estimate the gradient. The gradient at some sample location (x,y,z) +// would be estimated by: +// +// nx = (f(x-dx,y,z) - f(x+dx,y,z)) / 2*dx; +// ny = (f(x,y-dy,z) - f(x,y+dy,z)) / 2*dy; +// nz = (f(x,y,z-dz) - f(x,y,z+dz)) / 2*dz; +// +// This value is normalized to determine a unit direction vector and a +// magnitude. The normal is computed in voxel space, and +// dx = dy = dz = SampleSpacingInVoxels. A scaling factor is applied to +// convert this normal from voxel space to world coordinates. +// +// .SECTION see also +// vtkEncodedGradientEstimator + +#ifndef __vtkFiniteDifferenceGradientEstimator_h +#define __vtkFiniteDifferenceGradientEstimator_h + +#include "vtkEncodedGradientEstimator.h" + +class VTK_VOLUMERENDERING_EXPORT vtkFiniteDifferenceGradientEstimator : public vtkEncodedGradientEstimator +{ +public: + vtkTypeRevisionMacro(vtkFiniteDifferenceGradientEstimator,vtkEncodedGradientEstimator); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Construct a vtkFiniteDifferenceGradientEstimator with + // a SampleSpacingInVoxels of 1. + static vtkFiniteDifferenceGradientEstimator *New(); + + // Description: + // Set/Get the spacing between samples for the finite differences + // method used to compute the normal. This spacing is in voxel units. + vtkSetMacro( SampleSpacingInVoxels, int ); + vtkGetMacro( SampleSpacingInVoxels, int ); + + // The sample spacing between samples taken for the normal estimation + int SampleSpacingInVoxels; + +protected: + vtkFiniteDifferenceGradientEstimator(); + ~vtkFiniteDifferenceGradientEstimator(); + + + // Description: + // Recompute the encoded normals and gradient magnitudes. + void UpdateNormals( void ); +private: + vtkFiniteDifferenceGradientEstimator(const vtkFiniteDifferenceGradientEstimator&); // Not implemented. + void operator=(const vtkFiniteDifferenceGradientEstimator&); // Not implemented. +}; + + +#endif diff --git a/VolumeRendering/vtkFixedPointRayCastImage.cxx b/VolumeRendering/vtkFixedPointRayCastImage.cxx new file mode 100644 index 0000000..8eac111 --- /dev/null +++ b/VolumeRendering/vtkFixedPointRayCastImage.cxx @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointRayCastImage.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointRayCastImage.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkFixedPointRayCastImage, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkFixedPointRayCastImage); + +// Construct a new vtkFixedPointRayCastImage with default values +vtkFixedPointRayCastImage::vtkFixedPointRayCastImage() +{ + this->ImageViewportSize[0] = 0; + this->ImageViewportSize[1] = 0; + + this->ImageMemorySize[0] = 0; + this->ImageMemorySize[1] = 0; + + this->ImageInUseSize[0] = 0; + this->ImageInUseSize[1] = 0; + + this->ImageOrigin[0] = 0; + this->ImageOrigin[1] = 0; + + this->ImageSampleDistance = 0; + + this->ZBufferMemorySize = 0; + + this->ZBufferSize[0] = 0; + this->ZBufferSize[1] = 0; + + this->ZBufferOrigin[0] = 0; + this->ZBufferOrigin[1] = 0; + + this->UseZBuffer = 0; + + this->Image = NULL; + this->ZBuffer = NULL; +} + +// Destruct a vtkFixedPointRayCastImage - clean up any memory used +vtkFixedPointRayCastImage::~vtkFixedPointRayCastImage() +{ + delete [] this->Image; + delete [] this->ZBuffer; +} + +// Allocate memory +void vtkFixedPointRayCastImage::AllocateImage() +{ + delete [] this->Image; + this->Image = NULL; + + if ( this->ImageMemorySize[0] > 0 && + this->ImageMemorySize[1] > 0 ) + { + this->Image = new unsigned short [ ( 4 * + this->ImageMemorySize[0] * + this->ImageMemorySize[1] )]; + } +} + +// Clear image to 0 +void vtkFixedPointRayCastImage::ClearImage() +{ + unsigned short *ucptr = this->Image; + + for ( int i = 0; i < this->ImageMemorySize[0]*this->ImageMemorySize[1]; i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } +} + +void vtkFixedPointRayCastImage::AllocateZBuffer() +{ + // If we already have a buffer big enough, don't + // bother to do anything + if ( this->ZBufferSize[0]*this->ZBufferSize[1] > + this->ZBufferMemorySize ) + { + // If our current buffer is not large enough, delete it + delete [] this->ZBuffer; + this->ZBuffer = NULL; + + // Try out a size equal to the viewport in pixels + this->ZBufferMemorySize = + this->ImageViewportSize[0] * this->ImageViewportSize[1]; + + // This shouldn't ever happen, but just in case.... + // If this happens it means that somehow our viewport + // size in pixels is smaller than the zbuffer we are + // requesting - which will probably not make OpenGL + // very happy. + if ( this->ZBufferMemorySize < + this->ZBufferSize[0]*this->ZBufferSize[1] ) + { + this->ZBufferMemorySize = + this->ZBufferSize[0] * this->ZBufferSize[1]; + } + + // Allocate the memory + this->ZBuffer = new float [this->ZBufferMemorySize]; + } +} + +float vtkFixedPointRayCastImage::GetZBufferValue(int x, int y) +{ + if ( !this->UseZBuffer ) + { + return 1.0; + } + + int xPos, yPos; + + xPos = static_cast<int>(static_cast<float>(x) * this->ImageSampleDistance); + yPos = static_cast<int>(static_cast<float>(y) * this->ImageSampleDistance); + + xPos = (xPos >= this->ZBufferSize[0])?(this->ZBufferSize[0]-1):(xPos); + yPos = (yPos >= this->ZBufferSize[1])?(this->ZBufferSize[1]-1):(yPos); + + return *(this->ZBuffer + yPos*this->ZBufferSize[0] + xPos); +} + +void vtkFixedPointRayCastImage::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Image Viewport Size: " + << this->ImageViewportSize[0] << " " + << this->ImageViewportSize[1] << endl; + + os << indent << "Image Memory Size: " + << this->ImageMemorySize[0] << " " + << this->ImageMemorySize[1] << endl; + + os << indent << "Image In Use Size: " + << this->ImageInUseSize[0] << " " + << this->ImageInUseSize[1] << endl; + + os << indent << "Image Origin: " + << this->ImageOrigin[0] << " " + << this->ImageOrigin[1] << endl; + + os << indent << "Image Sample Distance: " + << this->ImageSampleDistance << endl; + + os << indent << "Use ZBuffer: " + << (this->UseZBuffer ? "On" : "Off") << endl; + + os << indent << "ZBuffer Origin: " + << this->ZBufferOrigin[0] << " " + << this->ZBufferOrigin[1] << endl; + + os << indent << "ZBuffer Size: " + << this->ZBufferSize[0] << " " + << this->ZBufferSize[1] << endl; + + +} + diff --git a/VolumeRendering/vtkFixedPointRayCastImage.h b/VolumeRendering/vtkFixedPointRayCastImage.h new file mode 100644 index 0000000..c4e9ef3 --- /dev/null +++ b/VolumeRendering/vtkFixedPointRayCastImage.h @@ -0,0 +1,204 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointRayCastImage.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkFixedPointRayCastImage - helper class for a ray cast image +// .SECTION Description +// This is a helper class for storing the ray cast image including the +// underlying data and the size of the image. This class is not intended +// to be used directly - just as an internal class in the +// vtkFixedPointVolumeRayCastMapper so that multiple mappers can share +// the same image. This class also stored the ZBuffer (if necessary due +// to intermixed geometry). Perhaps this class could be generalized +// in the future to be used for other ray cast methods other than the +// fixed point method. + +// .SECTION see also +// vtkFixedPointVolumeRayCastMapper + +#ifndef __vtkFixedPointRayCastImage_h +#define __vtkFixedPointRayCastImage_h + +#include "vtkObject.h" + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointRayCastImage : public vtkObject +{ +public: + static vtkFixedPointRayCastImage *New(); + vtkTypeRevisionMacro(vtkFixedPointRayCastImage,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the internal storage for the image. It is a pointer to + // unsigned short with four components (RGBA) per pixel. This + // memory is allocated when the AllocateImage method is called. + unsigned short *GetImage() {return this->Image;} + + // Description: + // Set / Get the ImageViewportSize. This is the size of the + // whole viewport in pixels. + vtkSetVector2Macro( ImageViewportSize, int ); + vtkGetVectorMacro( ImageViewportSize, int, 2 ); + + // Description: + // Set / Get the ImageMemorySize. This is the size in pixels + // of the Image ivar. This will be a power of two in order + // to ensure that the texture can be rendered by graphics + // hardware that requires power of two textures. + vtkSetVector2Macro( ImageMemorySize, int ); + vtkGetVectorMacro( ImageMemorySize, int, 2 ); + + // Description: + // Set / Get the size of the image we are actually using. As + // long as the memory size is big enough, but not too big, + // we won't bother deleting and re-allocated, we'll just + // continue to use the memory size we have. This size will + // always be equal to or less than the ImageMemorySize. + vtkSetVector2Macro( ImageInUseSize, int ); + vtkGetVectorMacro( ImageInUseSize, int, 2 ); + + // Description: + // Set / Get the origin of the image. This is the starting + // pixel within the whole viewport that our Image starts on. + // That is, we could be generating just a subregion of the + // whole viewport due to the fact that our volume occupies + // only a portion of the viewport. The Image pixels will + // start from this location. + vtkSetVector2Macro( ImageOrigin, int ); + vtkGetVectorMacro( ImageOrigin, int, 2 ); + + // Description: + // Set / Get the ImageSampleDistance that will be used for + // rendering. This is a copy of the value stored in the + // mapper. It is stored here for sharing between all mappers + // that are participating in the creation of this image. + vtkSetMacro( ImageSampleDistance, float ); + vtkGetMacro( ImageSampleDistance, float ); + + // Description: + // Call this method once the ImageMemorySize has been set + // the allocate the image. If an image already exists, + // it will be deleted first. + void AllocateImage(); + + // Description: + // Clear the image to (0,0,0,0) for each pixel. + void ClearImage(); + + // Description: + // Set / Get the size of the ZBuffer in pixels. The zbuffer will + // be captured for the region of the screen covered by the + // ImageInUseSize image. However, due to subsampling, the size + // of the ImageInUseSize image may be smaller than this ZBuffer + // image which will be captured at screen resolution. + vtkSetVector2Macro( ZBufferSize, int ); + vtkGetVectorMacro( ZBufferSize, int, 2 ); + + // Description: + // Set / Get the origin of the ZBuffer. This is the distance + // from the lower left corner of the viewport where the ZBuffer + // started (multiply the ImageOrigin by the ImageSampleDistance) + // This is the pixel location on the full resolution viewport + // where the ZBuffer capture will start. These values are used + // to convert the (x,y) pixel location within the ImageInUseSize + // image into a ZBuffer location. + vtkSetVector2Macro( ZBufferOrigin, int ); + vtkGetVectorMacro( ZBufferOrigin, int, 2 ); + + // Description: + // The UseZBuffer flag indicates whether the ZBuffer is in use. + // The ZBuffer is captured and used when IntermixIntersectingGeometry + // is on in the mapper, and when there are props that have been + // rendered before the current volume. + vtkSetClampMacro( UseZBuffer, int, 0, 1 ); + vtkGetMacro( UseZBuffer, int ); + vtkBooleanMacro( UseZBuffer, int ); + + // Description: + // Get the ZBuffer value corresponding to location (x,y) where (x,y) + // are indexing into the ImageInUse image. This must be converted to + // the zbuffer image coordinates. Nearest neighbor value is returned. + // If UseZBuffer is off, then 1.0 is always returned. + float GetZBufferValue( int x, int y ); + + // Description: + // Get the ZBuffer. The size of the ZBuffer should be specific + // with SetZBufferSize, and AllocateZBuffer method should be called + // before getting the ZBuffer. + float *GetZBuffer() {return this->ZBuffer;} + + // Descipriotn: + // Allocate the space for the ZBuffer according to the size. + void AllocateZBuffer(); + +protected: + vtkFixedPointRayCastImage(); + ~vtkFixedPointRayCastImage(); + + // This is how big the image would be if it covered the entire viewport + int ImageViewportSize[2]; + + // This is how big the allocated memory for image is. This may be bigger + // or smaller than ImageFullSize - it will be bigger if necessary to + // ensure a power of 2, it will be smaller if the volume only covers a + // small region of the viewport + int ImageMemorySize[2]; + + // This is the size of subregion in ImageSize image that we are using for + // the current image. Since ImageSize is a power of 2, there is likely + // wasted space in it. This number will be used for things such as clearing + // the image if necessary. + int ImageInUseSize[2]; + + // This is the location in ImageFullSize image where our ImageSize image + // is located. + int ImageOrigin[2]; + + // This is a copy of the ImageSampleDistance from the mapper - copied here + // in order to share among all mappers contributing to this image + float ImageSampleDistance; + + // This is the allocated image + unsigned short *Image; + + // This is the size of the zbuffer in pixels + int ZBufferSize[2]; + + // This is the size of the memory for the zbuffer - this can be + // bigger than the size of the zbuffer since we will allocate enough + // space for the whole viewport to avoid re-allocating over and over + int ZBufferMemorySize; + + // This is the distance from the lower left corner of the viewport + // where the ZBuffer starts + int ZBufferOrigin[2]; + + // This is the flag that indicate whether the ZBuffer is in use + int UseZBuffer; + + // This is the actual ZBuffer data in floats + float *ZBuffer; + + +private: + vtkFixedPointRayCastImage(const vtkFixedPointRayCastImage&); // Not implemented. + void operator=(const vtkFixedPointRayCastImage&); // Not implemented. +}; + +#endif + + + + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOHelper.cxx b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOHelper.cxx new file mode 100644 index 0000000..7d52067 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOHelper.cxx @@ -0,0 +1,916 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeGOHelper.cxx,v $ + Language: C++ + Date: $Date: 2005/08/19 19:24:59 $ + Version: $Revision: 1.5 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointVolumeRayCastCompositeGOHelper.h" + +#include "vtkImageData.h" +#include "vtkCommand.h" +#include "vtkFixedPointVolumeRayCastMapper.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkFixedPointRayCastImage.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFixedPointVolumeRayCastCompositeGOHelper, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkFixedPointVolumeRayCastCompositeGOHelper); + +// Construct a new vtkFixedPointVolumeRayCastCompositeGOHelper with default values +vtkFixedPointVolumeRayCastCompositeGOHelper::vtkFixedPointVolumeRayCastCompositeGOHelper() +{ +} + +// Destruct a vtkFixedPointVolumeRayCastCompositeGOHelper - clean up any memory used +vtkFixedPointVolumeRayCastCompositeGOHelper::~vtkFixedPointVolumeRayCastCompositeGOHelper() +{ +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component and scale == 1.0 and shift == 0.0. In the inner +// loop we get the data value as an unsigned short, and use this index to +// lookup a color and opacity for this sample. We then composite this into +// the color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageOneSimpleNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGONN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGONN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val = static_cast<unsigned short>(((*dptr))); + unsigned char mag = *magPtr; + + VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0], + gradientOpacityTable[0], val, mag, tmp ); + + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component. In the inner loop we get the data value as +// an unsigned short using the scale/shift, and use this index to lookup +// a color and opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageOneNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGONN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGONN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]); + unsigned char mag = *magPtr; + + VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0], + gradientOpacityTable[0], val, mag, tmp ); + + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has two components which are not considered independent. In the +// inner loop we compute the two unsigned short index values from the data +// values (using the scale/shift). We use the first index to lookup a color, +// and we use the second index to look up the opacity. We then composite +// the color into the color computed so far along this ray, and check to +// see if we can terminate here (if the opacity accumulated exceed some +// threshold). Finally we move to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageTwoDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGONN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGONN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val[2]; + val[0] = static_cast<unsigned short>(((*(dptr )) + shift[0])*scale[0]); + val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]); + unsigned char mag = *magPtr; + + tmp[3] = (scalarOpacityTable[0][val[1]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT); + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has four components which are not considered independent . This +// means that the first three components directly represent color, and this +// data must be of unsigned char type. In the inner loop we directly access +// the four data values (no scale/shift is needed). The first three are the +// color of this sample and the fourth is used to look up an opacity in the +// scalar opacity transfer function. We then composite this color into the +// color we have accumulated so far along the ray, and check if we can +// terminate here (if our accumulated opacity has exceed some threshold). +// Finally we move onto the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageFourDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGONN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGONN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val[4]; + val[0] = *(dptr ); + val[1] = *(dptr+1); + val[2] = *(dptr+2); + val[3] = *(dptr+3); + + unsigned char mag = *magPtr; + + tmp[3] = (scalarOpacityTable[0][val[3]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT); + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = (val[0]*tmp[3]+0x7f)>>(8); + tmp[1] = (val[1]*tmp[3]+0x7f)>>(8); + tmp[2] = (val[2]*tmp[3]+0x7f)>>(8); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has more than one component and the components are considered to +// be independent. In the inner loop we access each component value, using +// the scale/shift to turn the data value into an unsigned short index. We +// then lookup the color/opacity for each component and combine them according +// to the weighting value for each component. We composite this resulting +// color into the color already accumulated for this ray, and we check +// wether we can terminate here (if the accumulated opacity exceeds some +// threshold). Finally we increment to the next sample on the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageIndependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartGONN(); + VTKKWRCHelper_InitializeCompositeMultiNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGONN(); + } + + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned char mag[4]; + for ( c = 0; c < components; c++ ) + { + val[c] = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]); + mag[c] = static_cast<unsigned short>(*(magPtr+c)); + } + + VTKKWRCHelper_LookupAndCombineIndependentColorsGOUS( colorTable, scalarOpacityTable, + gradientOpacityTable, + val, mag, weights, components, tmp ); + + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale = 1.0 and shift = 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (the range must be right and we don't need the +// scale/shift). We compute our weights within the cell according to our +// fractional position within the cell, apply trilinear interpolation to +// compute the index, and use this index to lookup a color and opacity for +// this sample. We then composite this into the color computed so far along +// the ray, and check if we can terminate at this point (if the accumulated +// opacity is higher than some threshold). Finally we move on to the next +// sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageOneSimpleTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleGO = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValuesSimple( dptr ); + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleGO = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + tmp[3] = scalarOpacityTable[0][val]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleGO ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleGO = 0; + } + + VTKKWRCHelper_InterpolateMagnitude(mag); + tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT; + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale != 1.0 or shift != 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (we use the scale/shift to ensure the correct range). +// We compute our weights within the cell according to our fractional position +// within the cell, apply trilinear interpolation to compute the index, and use +// this index to lookup a color and opacity for this sample. We then composite +// this into the color computed so far along the ray, and check if we can +// terminate at this point (if the accumulated opacity is higher than some +// threshold). Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageOneTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleGO = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] ); + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleGO = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + tmp[3] = scalarOpacityTable[0][val]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleGO ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleGO = 0; + } + VTKKWRCHelper_InterpolateMagnitude(mag); + + tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT; + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is linear, the data has +// two components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for both components as an unsigned shorts (we use the +// scale/shift to ensure the correct range). We compute our weights within +// the cell according to our fractional position within the cell, and apply +// trilinear interpolation to compute the two index value. We use the first +// index to lookup a color and the second to look up an opacity for this sample. +// We then composite this into the color computed so far along the ray, and +// check if we can terminate at this point (if the accumulated opacity is +// higher than some threshold). Finally we move on to the next sample along +// the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageTwoDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleGO = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleGO = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 ); + + tmp[3] = scalarOpacityTable[0][val[1]]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleGO ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleGO = 0; + } + + VTKKWRCHelper_InterpolateMagnitude(mag); + tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT; + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + + +// This method is used when the interpolation type is linear, the data has +// four components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we don't have to +// use the scale/shift because only unsigned char data is supported for four +// component data when the components are not independent). We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// use the first three directly as the color of the sample, and the fourth is +// used to look up an opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageFourDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleGO = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleGO = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, 4 ); + + tmp[3] = scalarOpacityTable[0][val[3]]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleGO ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleGO = 0; + } + + VTKKWRCHelper_InterpolateMagnitude(mag); + tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT; + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = (val[0]*tmp[3]+0x7f)>>8; + tmp[1] = (val[1]*tmp[3]+0x7f)>>8; + tmp[2] = (val[2]*tmp[3]+0x7f)>>8; + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear, the data has +// more than one component and the components are considered independent. In +// the inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we have to use the +// scale/shift to ensure that we obtained unsigned short indices) We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// look up a color/opacity for each component and blend them according to the +// component weights. We then composite this resulting color into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOHelperGenerateImageIndependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartGOTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeMultiGOTrilin(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + if ( components > 2 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + if ( components > 3 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + } + } + + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 0 ); + + magPtrABCD++; + magPtrEFGH++; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 1 ); + + if ( components > 2 ) + { + magPtrABCD++; + magPtrEFGH++; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 2 ); + if ( components > 3 ) + { + magPtrABCD++; + magPtrEFGH++; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 3 ); + } + } + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + VTKKWRCHelper_InterpolateMagnitudeComponent( mag, c, components ); + + VTKKWRCHelper_LookupAndCombineIndependentColorsGOUS( colorTable, scalarOpacityTable, + gradientOpacityTable, val, mag, + weights, components, tmp ); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +void vtkFixedPointVolumeRayCastCompositeGOHelper::GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper ) +{ + void *data = mapper->GetInput()->GetScalarPointer(); + int scalarType = mapper->GetInput()->GetScalarType(); + + // Nearest Neighbor interpolate + if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) ) + { + // One component data + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageOneSimpleNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageOneNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // More that one independent components + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageIndependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent (color) components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageTwoDependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeGOHelperGenerateImageFourDependentNN( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent must be unsigned char!"); + } + } + } + } + // Trilinear Interpolation + else + { + // One component + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageOneSimpleTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageOneTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // Indepedent components (more than one) + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageIndependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOHelperGenerateImageTwoDependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeGOHelperGenerateImageFourDependentTrilin( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent must be unsigned char!"); + } + } + } + } +} + +// Print method for vtkFixedPointVolumeRayCastCompositeGOHelper +void vtkFixedPointVolumeRayCastCompositeGOHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOHelper.h b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOHelper.h new file mode 100644 index 0000000..004923f --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOHelper.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeGOHelper.h,v $ + Language: C++ + Date: $Date: 2005/05/04 14:13:58 $ + Version: $Revision: 1.1 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkFixedPointVolumeRayCastCompositeGOHelper - A helper that generates composite images for the volume ray cast mapper +// .SECTION Description +// This is one of the helper classes for the vtkFixedPointVolumeRayCastMapper. +// It will generate composite images using an alpha blending operation. +// This class should not be used directly, it is a helper class for +// the mapper and has no user-level API. +// +// .SECTION see also +// vtkFixedPointVolumeRayCastMapper + +#ifndef __vtkFixedPointVolumeRayCastCompositeGOHelper_h +#define __vtkFixedPointVolumeRayCastCompositeGOHelper_h + +#include "vtkFixedPointVolumeRayCastHelper.h" + +class vtkFixedPointVolumeRayCastMapper; +class vtkVolume; + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointVolumeRayCastCompositeGOHelper : public vtkFixedPointVolumeRayCastHelper +{ +public: + static vtkFixedPointVolumeRayCastCompositeGOHelper *New(); + vtkTypeRevisionMacro(vtkFixedPointVolumeRayCastCompositeGOHelper,vtkFixedPointVolumeRayCastHelper); + void PrintSelf( ostream& os, vtkIndent indent ); + + virtual void GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper); + +protected: + vtkFixedPointVolumeRayCastCompositeGOHelper(); + ~vtkFixedPointVolumeRayCastCompositeGOHelper(); + +private: + vtkFixedPointVolumeRayCastCompositeGOHelper(const vtkFixedPointVolumeRayCastCompositeGOHelper&); // Not implemented. + void operator=(const vtkFixedPointVolumeRayCastCompositeGOHelper&); // Not implemented. +}; + +#endif + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOShadeHelper.cxx b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOShadeHelper.cxx new file mode 100644 index 0000000..2772c8f --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOShadeHelper.cxx @@ -0,0 +1,1007 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeGOShadeHelper.cxx,v $ + Language: C++ + Date: $Date: 2005/08/19 19:24:59 $ + Version: $Revision: 1.5 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointVolumeRayCastCompositeGOShadeHelper.h" + +#include "vtkImageData.h" +#include "vtkCommand.h" +#include "vtkFixedPointVolumeRayCastMapper.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkFixedPointRayCastImage.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFixedPointVolumeRayCastCompositeGOShadeHelper, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkFixedPointVolumeRayCastCompositeGOShadeHelper); + +// Construct a new vtkFixedPointVolumeRayCastCompositeGOShadeHelper with default values +vtkFixedPointVolumeRayCastCompositeGOShadeHelper::vtkFixedPointVolumeRayCastCompositeGOShadeHelper() +{ +} + +// Destruct a vtkFixedPointVolumeRayCastCompositeGOShadeHelper - clean up any memory used +vtkFixedPointVolumeRayCastCompositeGOShadeHelper::~vtkFixedPointVolumeRayCastCompositeGOShadeHelper() +{ +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component and scale == 1.0 and shift == 0.0. In the inner +// loop we get the data value as an unsigned short, and use this index to +// lookup a color and opacity for this sample. We then composite this into +// the color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGOShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + unsigned short val = static_cast<unsigned short>(((*dptr))); + unsigned char mag = *magPtr; + + + VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0], + gradientOpacityTable[0], val, mag, tmp ); + + if ( tmp[3] ) + { + unsigned short normal = *dirPtr; + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component. In the inner loop we get the data value as +// an unsigned short using the scale/shift, and use this index to lookup +// a color and opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageOneNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGOShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]); + unsigned char mag = *magPtr; + + VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0], + gradientOpacityTable[0], val, mag, tmp ); + + if ( tmp[3] ) + { + unsigned short normal = *dirPtr; + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has two components which are not considered independent. In the +// inner loop we compute the two unsigned short index values from the data +// values (using the scale/shift). We use the first index to lookup a color, +// and we use the second index to look up the opacity. We then composite +// the color into the color computed so far along this ray, and check to +// see if we can terminate here (if the opacity accumulated exceed some +// threshold). Finally we move to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGOShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + unsigned short val[2]; + + val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]); + unsigned char mag = *magPtr; + + tmp[3] = (scalarOpacityTable[0][val[1]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT); + if ( !tmp[3] ) + { + continue; + } + + val[0] = static_cast<unsigned short>(((*(dptr )) + shift[0])*scale[0]); + unsigned short normal = *dirPtr; + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has four components which are not considered independent . This +// means that the first three components directly represent color, and this +// data must be of unsigned char type. In the inner loop we directly access +// the four data values (no scale/shift is needed). The first three are the +// color of this sample and the fourth is used to look up an opacity in the +// scalar opacity transfer function. We then composite this color into the +// color we have accumulated so far along the ray, and check if we can +// terminate here (if our accumulated opacity has exceed some threshold). +// Finally we move onto the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGOShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + unsigned short val[4]; + + val[3] = *(dptr+3); + unsigned char mag = *magPtr; + + tmp[3] = (scalarOpacityTable[0][val[3]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT); + if ( !tmp[3] ) + { + continue; + } + + val[0] = *(dptr ); + val[1] = *(dptr+1); + val[2] = *(dptr+2); + unsigned short normal = *dirPtr; + + tmp[0] = (val[0]*tmp[3]+0x7f)>>(8); + tmp[1] = (val[1]*tmp[3]+0x7f)>>(8); + tmp[2] = (val[2]*tmp[3]+0x7f)>>(8); + + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has more than one component and the components are considered to +// be independent. In the inner loop we access each component value, using +// the scale/shift to turn the data value into an unsigned short index. We +// then lookup the color/opacity for each component and combine them according +// to the weighting value for each component. We composite this resulting +// color into the color already accumulated for this ray, and we check +// wether we can terminate here (if the accumulated opacity exceeds some +// threshold). Finally we increment to the next sample on the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartGOShadeNN(); + VTKKWRCHelper_InitializeCompositeMultiNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_InitializeCompositeGONN(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleGOShadeNN(); + } + + VTKKWRCHelper_CroppingCheckNN( pos ); + unsigned short normal[4]; + unsigned char mag[4]; + for ( c = 0; c < components; c++ ) + { + val[c] = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]); + mag[c] = static_cast<unsigned short>(*(magPtr+c)); + normal[c] = *(dirPtr+c); + } + + VTKKWRCHelper_LookupAndCombineIndependentColorsGOShadeUS( colorTable, scalarOpacityTable, + gradientOpacityTable, + diffuseShadingTable, + specularShadingTable, + val, mag, normal, weights, + components, tmp ); + + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale = 1.0 and shift = 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (the range must be right and we don't need the +// scale/shift). We compute our weights within the cell according to our +// fractional position within the cell, apply trilinear interpolation to +// compute the index, and use this index to lookup a color and opacity for +// this sample. We then composite this into the color computed so far along +// the ray, and check if we can terminate at this point (if the accumulated +// opacity is higher than some threshold). Finally we move on to the next +// sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + int needToSampleMagnitude = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValuesSimple( dptr ); + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleMagnitude = 1; + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + tmp[3] = scalarOpacityTable[0][val]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleMagnitude ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleMagnitude = 0; + } + VTKKWRCHelper_InterpolateMagnitude(mag); + tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT; + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale != 1.0 or shift != 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (we use the scale/shift to ensure the correct range). +// We compute our weights within the cell according to our fractional position +// within the cell, apply trilinear interpolation to compute the index, and use +// this index to lookup a color and opacity for this sample. We then composite +// this into the color computed so far along the ray, and check if we can +// terminate at this point (if the accumulated opacity is higher than some +// threshold). Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageOneTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + int needToSampleMagnitude = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] ); + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleMagnitude = 1; + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + tmp[3] = scalarOpacityTable[0][val]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleMagnitude ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleMagnitude = 0; + } + VTKKWRCHelper_InterpolateMagnitude(mag); + tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is linear, the data has +// two components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for both components as an unsigned shorts (we use the +// scale/shift to ensure the correct range). We compute our weights within +// the cell according to our fractional position within the cell, and apply +// trilinear interpolation to compute the two index value. We use the first +// index to lookup a color and the second to look up an opacity for this sample. +// We then composite this into the color computed so far along the ray, and +// check if we can terminate at this point (if the accumulated opacity is +// higher than some threshold). Finally we move on to the next sample along +// the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + int needToSampleMagnitude = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleMagnitude = 1; + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 ); + + tmp[3] = scalarOpacityTable[0][val[1]]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleMagnitude ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleMagnitude = 0; + } + VTKKWRCHelper_InterpolateMagnitude(mag); + tmp[3] = (0x7fff + tmp[3]*gradientOpacityTable[0][mag])>>(VTKKW_FP_SHIFT); + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + + +// This method is used when the interpolation type is linear, the data has +// four components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we don't have to +// use the scale/shift because only unsigned char data is supported for four +// component data when the components are not independent). We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// use the first three directly as the color of the sample, and the fourth is +// used to look up an opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneGOTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + int needToSampleMagnitude = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + needToSampleMagnitude = 1; + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + + tmp[3] = scalarOpacityTable[0][val[3]]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleMagnitude ) + { + VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH ); + needToSampleMagnitude = 0; + } + VTKKWRCHelper_InterpolateMagnitude(mag); + tmp[3] = (0x7fff + tmp[3]*gradientOpacityTable[0][mag])>>(VTKKW_FP_SHIFT); + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + + tmp[0] = (val[0]*tmp[3]+0x7f)>>8; + tmp[1] = (val[1]*tmp[3]+0x7f)>>8; + tmp[2] = (val[2]*tmp[3]+0x7f)>>8; + + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear, the data has +// more than one component and the components are considered independent. In +// the inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we have to use the +// scale/shift to ensure that we obtained unsigned short indices) We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// look up a color/opacity for each component and blend them according to the +// component weights. We then composite this resulting color into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeMultiShadeTrilin(); + VTKKWRCHelper_InitializeCompositeMultiGOTrilin(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + if ( components > 2 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + if ( components > 3 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + } + } + + magPtrABCD = gradientMag[spos[2] ] + spos[0]*mInc[0] + spos[1]*mInc[1]; + magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1]; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 0 ); + + magPtrABCD++; + magPtrEFGH++; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 1 ); + + if ( components > 2 ) + { + magPtrABCD++; + magPtrEFGH++; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 2 ); + if ( components > 3 ) + { + magPtrABCD++; + magPtrEFGH++; + VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 3 ); + } + } + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 0 ); + + dirPtrABCD++; + dirPtrEFGH++; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 1 ); + + if ( components > 2 ) + { + dirPtrABCD++; + dirPtrEFGH++; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 2 ); + if ( components > 3 ) + { + dirPtrABCD++; + dirPtrEFGH++; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 3 ); + } + } + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + VTKKWRCHelper_InterpolateMagnitudeComponent( mag, c, components ); + + VTKKWRCHelper_LookupAndCombineIndependentColorsGOInterpolateShadeUS( + colorTable, scalarOpacityTable, gradientOpacityTable, + diffuseShadingTable, specularShadingTable, + val, mag, weights, components, tmp ); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +void vtkFixedPointVolumeRayCastCompositeGOShadeHelper::GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper ) +{ + void *data = mapper->GetInput()->GetScalarPointer(); + int scalarType = mapper->GetInput()->GetScalarType(); + + // Nearest Neighbor interpolate + if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) ) + { + // One component data + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageOneNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // More that one independent components + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent (color) components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentNN( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent data must be unsigned char"); + } + } + } + } + // Trilinear Interpolation + else + { + // One component + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageOneSimpleTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageOneTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // Indepedent components (more than one) + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageIndependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeGOShadeHelperGenerateImageTwoDependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeGOShadeHelperGenerateImageFourDependentTrilin( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent data must be unsigned char"); + } + } + } + } +} + +// Print method for vtkFixedPointVolumeRayCastCompositeGOShadeHelper +void vtkFixedPointVolumeRayCastCompositeGOShadeHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOShadeHelper.h b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOShadeHelper.h new file mode 100644 index 0000000..447832b --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeGOShadeHelper.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeGOShadeHelper.h,v $ + Language: C++ + Date: $Date: 2005/05/04 14:13:58 $ + Version: $Revision: 1.1 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkFixedPointVolumeRayCastCompositeGOShadeHelper - A helper that generates composite images for the volume ray cast mapper +// .SECTION Description +// This is one of the helper classes for the vtkFixedPointVolumeRayCastMapper. +// It will generate composite images using an alpha blending operation. +// This class should not be used directly, it is a helper class for +// the mapper and has no user-level API. +// +// .SECTION see also +// vtkFixedPointVolumeRayCastMapper + +#ifndef __vtkFixedPointVolumeRayCastCompositeGOShadeHelper_h +#define __vtkFixedPointVolumeRayCastCompositeGOShadeHelper_h + +#include "vtkFixedPointVolumeRayCastHelper.h" + +class vtkFixedPointVolumeRayCastMapper; +class vtkVolume; + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointVolumeRayCastCompositeGOShadeHelper : public vtkFixedPointVolumeRayCastHelper +{ +public: + static vtkFixedPointVolumeRayCastCompositeGOShadeHelper *New(); + vtkTypeRevisionMacro(vtkFixedPointVolumeRayCastCompositeGOShadeHelper,vtkFixedPointVolumeRayCastHelper); + void PrintSelf( ostream& os, vtkIndent indent ); + + virtual void GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper); + +protected: + vtkFixedPointVolumeRayCastCompositeGOShadeHelper(); + ~vtkFixedPointVolumeRayCastCompositeGOShadeHelper(); + +private: + vtkFixedPointVolumeRayCastCompositeGOShadeHelper(const vtkFixedPointVolumeRayCastCompositeGOShadeHelper&); // Not implemented. + void operator=(const vtkFixedPointVolumeRayCastCompositeGOShadeHelper&); // Not implemented. +}; + +#endif + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeHelper.cxx b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeHelper.cxx new file mode 100644 index 0000000..9842c40 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeHelper.cxx @@ -0,0 +1,786 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeHelper.cxx,v $ + Language: C++ + Date: $Date: 2005/08/19 19:24:59 $ + Version: $Revision: 1.5 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointVolumeRayCastCompositeHelper.h" + +#include "vtkImageData.h" +#include "vtkCommand.h" +#include "vtkFixedPointVolumeRayCastMapper.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkFixedPointRayCastImage.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFixedPointVolumeRayCastCompositeHelper, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkFixedPointVolumeRayCastCompositeHelper); + +// Construct a new vtkFixedPointVolumeRayCastCompositeHelper with default values +vtkFixedPointVolumeRayCastCompositeHelper::vtkFixedPointVolumeRayCastCompositeHelper() +{ +} + +// Destruct a vtkFixedPointVolumeRayCastCompositeHelper - clean up any memory used +vtkFixedPointVolumeRayCastCompositeHelper::~vtkFixedPointVolumeRayCastCompositeHelper() +{ +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component and scale == 1.0 and shift == 0.0. In the inner +// loop we get the data value as an unsigned short, and use this index to +// lookup a color and opacity for this sample. We then composite this into +// the color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageOneSimpleNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val = static_cast<unsigned short>(((*dptr))); + + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component. In the inner loop we get the data value as +// an unsigned short using the scale/shift, and use this index to lookup +// a color and opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageOneNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]); + + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has two components which are not considered independent. In the +// inner loop we compute the two unsigned short index values from the data +// values (using the scale/shift). We use the first index to lookup a color, +// and we use the second index to look up the opacity. We then composite +// the color into the color computed so far along this ray, and check to +// see if we can terminate here (if the opacity accumulated exceed some +// threshold). Finally we move to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageTwoDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val[2]; + val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]); + + tmp[3] = scalarOpacityTable[0][val[1]]; + if ( !tmp[3] ) + { + continue; + } + + val[0] = static_cast<unsigned short>(((*(dptr )) + shift[0])*scale[0]); + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has four components which are not considered independent . This +// means that the first three components directly represent color, and this +// data must be of unsigned char type. In the inner loop we directly access +// the four data values (no scale/shift is needed). The first three are the +// color of this sample and the fourth is used to look up an opacity in the +// scalar opacity transfer function. We then composite this color into the +// color we have accumulated so far along the ray, and check if we can +// terminate here (if our accumulated opacity has exceed some threshold). +// Finally we move onto the next sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageFourDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val[4]; + val[3] = *(dptr+3); + + tmp[3] = scalarOpacityTable[0][val[3]]; + if ( !tmp[3] ) + { + continue; + } + + val[0] = *(dptr ); + val[1] = *(dptr+1); + val[2] = *(dptr+2); + + tmp[0] = (val[0]*tmp[3]+0x7f)>>(8); + tmp[1] = (val[1]*tmp[3]+0x7f)>>(8); + tmp[2] = (val[2]*tmp[3]+0x7f)>>(8); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has more than one component and the components are considered to +// be independent. In the inner loop we access each component value, using +// the scale/shift to turn the data value into an unsigned short index. We +// then lookup the color/opacity for each component and combine them according +// to the weighting value for each component. We composite this resulting +// color into the color already accumulated for this ray, and we check +// wether we can terminate here (if the accumulated opacity exceeds some +// threshold). Finally we increment to the next sample on the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageIndependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeCompositeMultiNN(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleNN(); + } + + VTKKWRCHelper_CroppingCheckNN( pos ); + + for ( c = 0; c < components; c++ ) + { + val[c] = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]); + } + + + VTKKWRCHelper_LookupAndCombineIndependentColorsUS( colorTable, scalarOpacityTable, + val, weights, components, tmp ); + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale = 1.0 and shift = 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (the range must be right and we don't need the +// scale/shift). We compute our weights within the cell according to our +// fractional position within the cell, apply trilinear interpolation to +// compute the index, and use this index to lookup a color and opacity for +// this sample. We then composite this into the color computed so far along +// the ray, and check if we can terminate at this point (if the accumulated +// opacity is higher than some threshold). Finally we move on to the next +// sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageOneSimpleTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValuesSimple( dptr ); + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale != 1.0 or shift != 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (we use the scale/shift to ensure the correct range). +// We compute our weights within the cell according to our fractional position +// within the cell, apply trilinear interpolation to compute the index, and use +// this index to lookup a color and opacity for this sample. We then composite +// this into the color computed so far along the ray, and check if we can +// terminate at this point (if the accumulated opacity is higher than some +// threshold). Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageOneTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] ); + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is linear, the data has +// two components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for both components as an unsigned shorts (we use the +// scale/shift to ensure the correct range). We compute our weights within +// the cell according to our fractional position within the cell, and apply +// trilinear interpolation to compute the two index value. We use the first +// index to lookup a color and the second to look up an opacity for this sample. +// We then composite this into the color computed so far along the ray, and +// check if we can terminate at this point (if the accumulated opacity is +// higher than some threshold). Finally we move on to the next sample along +// the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageTwoDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 ); + + tmp[3] = scalarOpacityTable[0][val[1]]; + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + + + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + + +// This method is used when the interpolation type is linear, the data has +// four components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we don't have to +// use the scale/shift because only unsigned char data is supported for four +// component data when the components are not independent). We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// use the first three directly as the color of the sample, and the fourth is +// used to look up an opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageFourDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + + tmp[3] = scalarOpacityTable[0][val[3]]; + if ( !tmp[3] ) + { + continue; + } + + tmp[0] = (val[0]*tmp[3]+0x7f)>>8; + tmp[1] = (val[1]*tmp[3]+0x7f)>>8; + tmp[2] = (val[2]*tmp[3]+0x7f)>>8; + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear, the data has +// more than one component and the components are considered independent. In +// the inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we have to use the +// scale/shift to ensure that we obtained unsigned short indices) We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// look up a color/opacity for each component and blend them according to the +// component weights. We then composite this resulting color into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeHelperGenerateImageIndependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + if ( components > 2 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + } + + if ( components > 3 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + } + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + + VTKKWRCHelper_LookupAndCombineIndependentColorsUS( colorTable, scalarOpacityTable, + val, weights, components, tmp ); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +void vtkFixedPointVolumeRayCastCompositeHelper::GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper ) +{ + void *data = mapper->GetInput()->GetScalarPointer(); + int scalarType = mapper->GetInput()->GetScalarType(); + + // Nearest Neighbor interpolate + if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) ) + { + // One component data + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageOneSimpleNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageOneNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // More that one independent components + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageIndependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent (color) components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageTwoDependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeHelperGenerateImageFourDependentNN( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent data must be unsigned char!"); + } + } + } + } + // Trilinear Interpolation + else + { + // One component + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageOneSimpleTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageOneTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // Indepedent components (more than one) + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageIndependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeHelperGenerateImageTwoDependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeHelperGenerateImageFourDependentTrilin( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent data must be unsigned char!"); + } + } + } + } +} + +// Print method for vtkFixedPointVolumeRayCastCompositeHelper +void vtkFixedPointVolumeRayCastCompositeHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeHelper.h b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeHelper.h new file mode 100644 index 0000000..410cfd3 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeHelper.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeHelper.h,v $ + Language: C++ + Date: $Date: 2005/05/04 14:13:58 $ + Version: $Revision: 1.1 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkFixedPointVolumeRayCastCompositeHelper - A helper that generates composite images for the volume ray cast mapper +// .SECTION Description +// This is one of the helper classes for the vtkFixedPointVolumeRayCastMapper. +// It will generate composite images using an alpha blending operation. +// This class should not be used directly, it is a helper class for +// the mapper and has no user-level API. +// +// .SECTION see also +// vtkFixedPointVolumeRayCastMapper + +#ifndef __vtkFixedPointVolumeRayCastCompositeHelper_h +#define __vtkFixedPointVolumeRayCastCompositeHelper_h + +#include "vtkFixedPointVolumeRayCastHelper.h" + +class vtkFixedPointVolumeRayCastMapper; +class vtkVolume; + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointVolumeRayCastCompositeHelper : public vtkFixedPointVolumeRayCastHelper +{ +public: + static vtkFixedPointVolumeRayCastCompositeHelper *New(); + vtkTypeRevisionMacro(vtkFixedPointVolumeRayCastCompositeHelper,vtkFixedPointVolumeRayCastHelper); + void PrintSelf( ostream& os, vtkIndent indent ); + + virtual void GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper); + +protected: + vtkFixedPointVolumeRayCastCompositeHelper(); + ~vtkFixedPointVolumeRayCastCompositeHelper(); + +private: + vtkFixedPointVolumeRayCastCompositeHelper(const vtkFixedPointVolumeRayCastCompositeHelper&); // Not implemented. + void operator=(const vtkFixedPointVolumeRayCastCompositeHelper&); // Not implemented. +}; + +#endif + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeShadeHelper.cxx b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeShadeHelper.cxx new file mode 100644 index 0000000..b5c58d1 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeShadeHelper.cxx @@ -0,0 +1,862 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeShadeHelper.cxx,v $ + Language: C++ + Date: $Date: 2005/08/19 19:24:59 $ + Version: $Revision: 1.5 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointVolumeRayCastCompositeShadeHelper.h" + +#include "vtkImageData.h" +#include "vtkCommand.h" +#include "vtkFixedPointVolumeRayCastMapper.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkFixedPointRayCastImage.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFixedPointVolumeRayCastCompositeShadeHelper, "$Revision: 1.5 $"); +vtkStandardNewMacro(vtkFixedPointVolumeRayCastCompositeShadeHelper); + +// Construct a new vtkFixedPointVolumeRayCastCompositeShadeHelper with default values +vtkFixedPointVolumeRayCastCompositeShadeHelper::vtkFixedPointVolumeRayCastCompositeShadeHelper() +{ +} + +// Destruct a vtkFixedPointVolumeRayCastCompositeShadeHelper - clean up any memory used +vtkFixedPointVolumeRayCastCompositeShadeHelper::~vtkFixedPointVolumeRayCastCompositeShadeHelper() +{ +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component and scale == 1.0 and shift == 0.0. In the inner +// loop we get the data value as an unsigned short, and use this index to +// lookup a color and opacity for this sample. We then composite this into +// the color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val = static_cast<unsigned short>(((*dptr))); + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + if (tmp[3]) + { + unsigned short normal = *dirPtr; + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has one component. In the inner loop we get the data value as +// an unsigned short using the scale/shift, and use this index to lookup +// a color and opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at +// this point (if the accumulated opacity is higher than some threshold). +// Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageOneNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]); + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + if (tmp[3]) + { + unsigned short normal = *dirPtr; + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is nearest neighbor and +// the data has two components which are not considered independent. In the +// inner loop we compute the two unsigned short index values from the data +// values (using the scale/shift). We use the first index to lookup a color, +// and we use the second index to look up the opacity. We then composite +// the color into the color computed so far along this ray, and check to +// see if we can terminate here (if the opacity accumulated exceed some +// threshold). Finally we move to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val[2]; + val[0] = static_cast<unsigned short>(((*(dptr )) + shift[0])*scale[0]); + val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]); + + tmp[3] = scalarOpacityTable[0][val[1]]; + if (tmp[3]) + { + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + unsigned short normal = *dirPtr; + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has four components which are not considered independent . This +// means that the first three components directly represent color, and this +// data must be of unsigned char type. In the inner loop we directly access +// the four data values (no scale/shift is needed). The first three are the +// color of this sample and the fourth is used to look up an opacity in the +// scalar opacity transfer function. We then composite this color into the +// color we have accumulated so far along the ray, and check if we can +// terminate here (if our accumulated opacity has exceed some threshold). +// Finally we move onto the next sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageFourDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeNN(); + VTKKWRCHelper_InitializeCompositeOneNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleShadeNN(); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short val[4]; + val[0] = *(dptr ); + val[1] = *(dptr+1); + val[2] = *(dptr+2); + val[3] = *(dptr+3); + + tmp[3] = scalarOpacityTable[0][val[3]]; + if ( tmp[3] ) + { + tmp[0] = (val[0]*tmp[3]+0x7f)>>(8); + tmp[1] = (val[1]*tmp[3]+0x7f)>>(8); + tmp[2] = (val[2]*tmp[3]+0x7f)>>(8); + + unsigned short normal = *dirPtr; + VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is nearest neighbor and +// the data has more than one component and the components are considered to +// be independent. In the inner loop we access each component value, using +// the scale/shift to turn the data value into an unsigned short index. We +// then lookup the color/opacity for each component and combine them according +// to the weighting value for each component. We composite this resulting +// color into the color already accumulated for this ray, and we check +// wether we can terminate here (if the accumulated opacity exceeds some +// threshold). Finally we increment to the next sample on the ray. +// +// TODO: short circuit calculations when opacity is 0 +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageIndependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartShadeNN(); + VTKKWRCHelper_InitializeCompositeMultiNN(); + VTKKWRCHelper_InitializeCompositeShadeNN(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + VTKKWRCHelper_MoveToNextSampleShadeNN(); + } + + VTKKWRCHelper_CroppingCheckNN( pos ); + + unsigned short normal[4]; + for ( c = 0; c < components; c++ ) + { + val[c] = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]); + normal[c] = *(dirPtr+c); + } + + VTKKWRCHelper_LookupAndCombineIndependentColorsShadeUS( colorTable, scalarOpacityTable, + diffuseShadingTable, + specularShadingTable, + val, normal, weights, + components, tmp ); + + if ( tmp[3] ) + { + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale = 1.0 and shift = 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (the range must be right and we don't need the +// scale/shift). We compute our weights within the cell according to our +// fractional position within the cell, apply trilinear interpolation to +// compute the index, and use this index to lookup a color and opacity for +// this sample. We then composite this into the color computed so far along +// the ray, and check if we can terminate at this point (if the accumulated +// opacity is higher than some threshold). Finally we move on to the next +// sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValuesSimple( dptr ); + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear and the data +// has one component and scale != 1.0 or shift != 0.0. In the inner loop we +// get the data value for the eight cell corners (if we have changed cells) +// as an unsigned short (we use the scale/shift to ensure the correct range). +// We compute our weights within the cell according to our fractional position +// within the cell, apply trilinear interpolation to compute the index, and use +// this index to lookup a color and opacity for this sample. We then composite +// this into the color computed so far along the ray, and check if we can +// terminate at this point (if the accumulated opacity is higher than some +// threshold). Finally we move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageOneTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeTrilin(); + VTKKWRCHelper_InitializeCompositeOneTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] ); + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp ); + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is used when the interpolation type is linear, the data has +// two components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for both components as an unsigned shorts (we use the +// scale/shift to ensure the correct range). We compute our weights within +// the cell according to our fractional position within the cell, and apply +// trilinear interpolation to compute the two index value. We use the first +// index to lookup a color and the second to look up an opacity for this sample. +// We then composite this into the color computed so far along the ray, and +// check if we can terminate at this point (if the accumulated opacity is +// higher than some threshold). Finally we move on to the next sample along +// the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 ); + + tmp[3] = scalarOpacityTable[0][val[1]]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + + tmp[0] = static_cast<unsigned short> + ((colorTable[0][3*val[0] ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[1] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + tmp[2] = static_cast<unsigned short> + ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); + + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + + +// This method is used when the interpolation type is linear, the data has +// four components and the components are not considered independent. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we don't have to +// use the scale/shift because only unsigned char data is supported for four +// component data when the components are not independent). We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// use the first three directly as the color of the sample, and the fourth is +// used to look up an opacity for this sample. We then composite this into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageFourDependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializationAndLoopStartShadeTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeOneShadeTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int needToSampleDirection = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_SpaceLeapCheck(); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + needToSampleDirection = 1; + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + + tmp[3] = scalarOpacityTable[0][val[3]]; + if ( !tmp[3] ) + { + continue; + } + + if ( needToSampleDirection ) + { + VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH ); + needToSampleDirection = 0; + } + + tmp[0] = (val[0]*tmp[3]+0x7f)>>8; + tmp[1] = (val[1]*tmp[3]+0x7f)>>8; + tmp[2] = (val[2]*tmp[3]+0x7f)>>8; + + VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp ); + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear, the data has +// more than one component and the components are considered independent. In +// the inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we have to use the +// scale/shift to ensure that we obtained unsigned short indices) We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We +// look up a color/opacity for each component and blend them according to the +// component weights. We then composite this resulting color into the +// color computed so far along the ray, and check if we can terminate at this +// point (if the accumulated opacity is higher than some threshold). Finally we +// move on to the next sample along the ray. +template <class T> +void vtkFixedPointCompositeShadeHelperGenerateImageIndependentTrilin( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartShadeTrilin(); + VTKKWRCHelper_InitializeCompositeMultiTrilin(); + VTKKWRCHelper_InitializeCompositeMultiShadeTrilin(); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] ); + + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] ); + + if ( components > 2 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] ); + if ( components > 3 ) + { + dptr++; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] ); + } + } + + + dirPtrABCD = gradientDir[spos[2] ] + spos[0]*dInc[0] + spos[1]*dInc[1]; + dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1]; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 0 ); + + dirPtrABCD++; + dirPtrEFGH++; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 1 ); + + if ( components > 2 ) + { + dirPtrABCD++; + dirPtrEFGH++; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 2 ); + if ( components > 3 ) + { + dirPtrABCD++; + dirPtrEFGH++; + VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 3 ); + } + } + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + + VTKKWRCHelper_LookupAndCombineIndependentColorsInterpolateShadeUS( + colorTable, scalarOpacityTable, diffuseShadingTable, + specularShadingTable, val, weights, components, tmp ); + + VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity ); + } + + VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity ); + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +void vtkFixedPointVolumeRayCastCompositeShadeHelper::GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper ) +{ + void *data = mapper->GetInput()->GetScalarPointer(); + int scalarType = mapper->GetInput()->GetScalarType(); + + // Nearest Neighbor interpolate + if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) ) + { + // One component data + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageOneNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // More that one independent components + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageIndependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent (color) components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentNN( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeShadeHelperGenerateImageFourDependentNN( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent data must be unsigned char"); + } + } + } + } + // Trilinear Interpolation + else + { + // One component + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageOneSimpleTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageOneTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + } + // Indepedent components (more than one) + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageIndependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent components + else + { + // Two components - the first specifies color (through a lookup table) and + // the second specified opacity (through a lookup table) + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 2 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointCompositeShadeHelperGenerateImageTwoDependentTrilin( + (VTK_TT *)(data), + threadID, threadCount, mapper, vol) ); + } + } + // Four components - they must be unsigned char, the first three directly + // specify color and the fourth specifies opacity (through a lookup table) + else + { + if ( scalarType == VTK_UNSIGNED_CHAR ) + { + vtkFixedPointCompositeShadeHelperGenerateImageFourDependentTrilin( + static_cast<unsigned char *>(data), threadID, threadCount, mapper, vol ); + } + else + { + vtkErrorMacro("Four component dependent data must be unsigned char"); + } + } + } + } +} + +// Print method for vtkFixedPointVolumeRayCastCompositeShadeHelper +void vtkFixedPointVolumeRayCastCompositeShadeHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastCompositeShadeHelper.h b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeShadeHelper.h new file mode 100644 index 0000000..4b78fa5 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastCompositeShadeHelper.h @@ -0,0 +1,60 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastCompositeShadeHelper.h,v $ + Language: C++ + Date: $Date: 2005/05/04 14:13:58 $ + Version: $Revision: 1.1 $ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkFixedPointVolumeRayCastCompositeShadeHelper - A helper that generates composite images for the volume ray cast mapper +// .SECTION Description +// This is one of the helper classes for the vtkFixedPointVolumeRayCastMapper. +// It will generate composite images using an alpha blending operation. +// This class should not be used directly, it is a helper class for +// the mapper and has no user-level API. +// +// .SECTION see also +// vtkFixedPointVolumeRayCastMapper + +#ifndef __vtkFixedPointVolumeRayCastCompositeShadeHelper_h +#define __vtkFixedPointVolumeRayCastCompositeShadeHelper_h + +#include "vtkFixedPointVolumeRayCastHelper.h" + +class vtkFixedPointVolumeRayCastMapper; +class vtkVolume; + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointVolumeRayCastCompositeShadeHelper : public vtkFixedPointVolumeRayCastHelper +{ +public: + static vtkFixedPointVolumeRayCastCompositeShadeHelper *New(); + vtkTypeRevisionMacro(vtkFixedPointVolumeRayCastCompositeShadeHelper,vtkFixedPointVolumeRayCastHelper); + void PrintSelf( ostream& os, vtkIndent indent ); + + virtual void GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper); + +protected: + vtkFixedPointVolumeRayCastCompositeShadeHelper(); + ~vtkFixedPointVolumeRayCastCompositeShadeHelper(); + +private: + vtkFixedPointVolumeRayCastCompositeShadeHelper(const vtkFixedPointVolumeRayCastCompositeShadeHelper&); // Not implemented. + void operator=(const vtkFixedPointVolumeRayCastCompositeShadeHelper&); // Not implemented. +}; + +#endif + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastHelper.cxx b/VolumeRendering/vtkFixedPointVolumeRayCastHelper.cxx new file mode 100644 index 0000000..84c5f68 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastHelper.cxx @@ -0,0 +1,36 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastHelper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointVolumeRayCastHelper.h" +#include "vtkObjectFactory.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFixedPointVolumeRayCastHelper, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkFixedPointVolumeRayCastHelper); + +vtkFixedPointVolumeRayCastHelper::vtkFixedPointVolumeRayCastHelper() +{ +} + +vtkFixedPointVolumeRayCastHelper::~vtkFixedPointVolumeRayCastHelper() +{ +} + +void vtkFixedPointVolumeRayCastHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastHelper.h b/VolumeRendering/vtkFixedPointVolumeRayCastHelper.h new file mode 100644 index 0000000..a149eb5 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastHelper.h @@ -0,0 +1,1317 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastHelper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFixedPointVolumeRayCastHelper - An abstract helper that generates images for the volume ray cast mapper +// .SECTION Description +// This is the abstract superclass of all helper classes for the +// vtkFixedPointVolumeRayCastMapper. This class should not be used directly. +// +// .SECTION see also +// vtkFixedPointVolumeRayCastMapper + +#ifndef __vtkFixedPointVolumeRayCastHelper_h +#define __vtkFixedPointVolumeRayCastHelper_h + +//BTX +#define VTKKWRCHelper_GetCellScalarValues( DATA, SCALE, SHIFT ) \ + A = static_cast<unsigned int >(SCALE*(*(DATA ) + SHIFT)); \ + B = static_cast<unsigned int >(SCALE*(*(DATA+Binc) + SHIFT)); \ + C = static_cast<unsigned int >(SCALE*(*(DATA+Cinc) + SHIFT)); \ + D = static_cast<unsigned int >(SCALE*(*(DATA+Dinc) + SHIFT)); \ + E = static_cast<unsigned int >(SCALE*(*(DATA+Einc) + SHIFT)); \ + F = static_cast<unsigned int >(SCALE*(*(DATA+Finc) + SHIFT)); \ + G = static_cast<unsigned int >(SCALE*(*(DATA+Ginc) + SHIFT)); \ + H = static_cast<unsigned int >(SCALE*(*(DATA+Hinc) + SHIFT)) +//ETX + +//BTX +#define VTKKWRCHelper_GetCellScalarValuesSimple( DATA ) \ + A = static_cast<unsigned int >(*(DATA )); \ + B = static_cast<unsigned int >(*(DATA+Binc)); \ + C = static_cast<unsigned int >(*(DATA+Cinc)); \ + D = static_cast<unsigned int >(*(DATA+Dinc)); \ + E = static_cast<unsigned int >(*(DATA+Einc)); \ + F = static_cast<unsigned int >(*(DATA+Finc)); \ + G = static_cast<unsigned int >(*(DATA+Ginc)); \ + H = static_cast<unsigned int >(*(DATA+Hinc)) +//ETX + +//BTX +#define VTKKWRCHelper_GetCellMagnitudeValues( ABCD, EFGH ) \ + mA = static_cast<unsigned int >(*(ABCD )); \ + mB = static_cast<unsigned int >(*(ABCD+mBFinc)); \ + mC = static_cast<unsigned int >(*(ABCD+mCGinc)); \ + mD = static_cast<unsigned int >(*(ABCD+mDHinc)); \ + mE = static_cast<unsigned int >(*(EFGH )); \ + mF = static_cast<unsigned int >(*(EFGH+mBFinc)); \ + mG = static_cast<unsigned int >(*(EFGH+mCGinc)); \ + mH = static_cast<unsigned int >(*(EFGH+mDHinc)) +//ETX + +//BTX +#define VTKKWRCHelper_GetCellDirectionValues( ABCD, EFGH ) \ + normalA = static_cast<unsigned int >(*(ABCD )); \ + normalB = static_cast<unsigned int >(*(ABCD+dBFinc)); \ + normalC = static_cast<unsigned int >(*(ABCD+dCGinc)); \ + normalD = static_cast<unsigned int >(*(ABCD+dDHinc)); \ + normalE = static_cast<unsigned int >(*(EFGH )); \ + normalF = static_cast<unsigned int >(*(EFGH+dBFinc)); \ + normalG = static_cast<unsigned int >(*(EFGH+dCGinc)); \ + normalH = static_cast<unsigned int >(*(EFGH+dDHinc)); +//ETX + +//BTX +#define VTKKWRCHelper_GetCellComponentScalarValues( DATA, CIDX, SCALE, SHIFT ) \ + A[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA ) + SHIFT)); \ + B[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA+Binc) + SHIFT)); \ + C[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA+Cinc) + SHIFT)); \ + D[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA+Dinc) + SHIFT)); \ + E[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA+Einc) + SHIFT)); \ + F[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA+Finc) + SHIFT)); \ + G[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA+Ginc) + SHIFT)); \ + H[CIDX] = static_cast<unsigned int >(SCALE*(*(DATA+Hinc) + SHIFT)) +//ETX + +//BTX +#define VTKKWRCHelper_GetCellComponentMagnitudeValues( ABCD, EFGH, CIDX ) \ + mA[CIDX] = static_cast<unsigned int >(*(ABCD )); \ + mB[CIDX] = static_cast<unsigned int >(*(ABCD+mBFinc)); \ + mC[CIDX] = static_cast<unsigned int >(*(ABCD+mCGinc)); \ + mD[CIDX] = static_cast<unsigned int >(*(ABCD+mDHinc)); \ + mE[CIDX] = static_cast<unsigned int >(*(EFGH )); \ + mF[CIDX] = static_cast<unsigned int >(*(EFGH+mBFinc)); \ + mG[CIDX] = static_cast<unsigned int >(*(EFGH+mCGinc)); \ + mH[CIDX] = static_cast<unsigned int >(*(EFGH+mDHinc)) +//ETX + +//BTX +#define VTKKWRCHelper_GetCellComponentDirectionValues( ABCD, EFGH, CIDX ) \ + normalA[CIDX] = static_cast<unsigned int >(*(ABCD )); \ + normalB[CIDX] = static_cast<unsigned int >(*(ABCD+dBFinc)); \ + normalC[CIDX] = static_cast<unsigned int >(*(ABCD+dCGinc)); \ + normalD[CIDX] = static_cast<unsigned int >(*(ABCD+dDHinc)); \ + normalE[CIDX] = static_cast<unsigned int >(*(EFGH )); \ + normalF[CIDX] = static_cast<unsigned int >(*(EFGH+dBFinc)); \ + normalG[CIDX] = static_cast<unsigned int >(*(EFGH+dCGinc)); \ + normalH[CIDX] = static_cast<unsigned int >(*(EFGH+dDHinc)); +//ETX + + +//BTX +#define VTKKWRCHelper_ComputeWeights( POS ) \ + w2X = (POS[0]&VTKKW_FP_MASK); \ + w2Y = (POS[1]&VTKKW_FP_MASK); \ + w2Z = (POS[2]&VTKKW_FP_MASK); \ + \ + w1X = ((~w2X)&VTKKW_FP_MASK); \ + w1Y = ((~w2Y)&VTKKW_FP_MASK); \ + w1Z = ((~w2Z)&VTKKW_FP_MASK); \ + \ + w1Xw1Y = (0x4000+(w1X*w1Y))>>VTKKW_FP_SHIFT; \ + w2Xw1Y = (0x4000+(w2X*w1Y))>>VTKKW_FP_SHIFT; \ + w1Xw2Y = (0x4000+(w1X*w2Y))>>VTKKW_FP_SHIFT; \ + w2Xw2Y = (0x4000+(w2X*w2Y))>>VTKKW_FP_SHIFT; \ +//ETX + + +//BTX +#define VTKKWRCHelper_InterpolateScalar( VAL ) \ + VAL = \ + (0x7fff + ((A*((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (B*((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (C*((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (D*((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (E*((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (F*((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (G*((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (H*((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; +//ETX + +//BTX +#define VTKKWRCHelper_InterpolateMagnitude( VAL ) \ + VAL = \ + (0x7fff + ((mA*((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mB*((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mC*((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mD*((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mE*((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (mF*((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (mG*((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (mH*((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; +//ETX + +//BTX +#define VTKKWRCHelper_InterpolateScalarComponent( VAL, CIDX, COMPONENTS ) \ + for ( CIDX = 0; CIDX < COMPONENTS; CIDX++ ) \ + { \ + VAL[CIDX] = \ + (0x7fff + ((A[CIDX]*((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (B[CIDX]*((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (C[CIDX]*((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (D[CIDX]*((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (E[CIDX]*((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (F[CIDX]*((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (G[CIDX]*((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (H[CIDX]*((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + } \ +//ETX + +//BTX +#define VTKKWRCHelper_InterpolateMagnitudeComponent( VAL, CIDX, COMPONENTS ) \ + for ( CIDX = 0; CIDX < COMPONENTS; CIDX++ ) \ + { \ + VAL[CIDX] = \ + (0x7fff + ((mA[CIDX]*((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mB[CIDX]*((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mC[CIDX]*((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mD[CIDX]*((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (mE[CIDX]*((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (mF[CIDX]*((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (mG[CIDX]*((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (mH[CIDX]*((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_InterpolateShading( DTABLE, STABLE, COLOR ) \ + unsigned int _tmpDColor[3]; \ + unsigned int _tmpSColor[3]; \ + \ + _tmpDColor[0] = \ + (0x7fff + ((DTABLE[3*normalA] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalB] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalC] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalD] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalE] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalF] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalG] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalH] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpDColor[1] = \ + (0x7fff + ((DTABLE[3*normalA+1] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalB+1] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalC+1] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalD+1] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalE+1] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalF+1] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalG+1] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalH+1] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpDColor[2] = \ + (0x7fff + ((DTABLE[3*normalA+2] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalB+2] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalC+2] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalD+2] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalE+2] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalF+2] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalG+2] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[3*normalH+2] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpSColor[0] = \ + (0x7fff + ((STABLE[3*normalA] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalB] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalC] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalD] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalE] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalF] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalG] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalH] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpSColor[1] = \ + (0x7fff + ((STABLE[3*normalA+1] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalB+1] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalC+1] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalD+1] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalE+1] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalF+1] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalG+1] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalH+1] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpSColor[2] = \ + (0x7fff + ((STABLE[3*normalA+2] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalB+2] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalC+2] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalD+2] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalE+2] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalF+2] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalG+2] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[3*normalH+2] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + \ + COLOR[0] = static_cast<unsigned short>((_tmpDColor[0]*COLOR[0]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[1] = static_cast<unsigned short>((_tmpDColor[1]*COLOR[1]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[2] = static_cast<unsigned short>((_tmpDColor[2]*COLOR[2]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[0] += (_tmpSColor[0]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[1] += (_tmpSColor[1]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[2] += (_tmpSColor[2]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; +//ETX + + +//BTX +#define VTKKWRCHelper_InterpolateShadingComponent( DTABLE, STABLE, COLOR, CIDX ) \ + unsigned int _tmpDColor[3]; \ + unsigned int _tmpSColor[3]; \ + \ + _tmpDColor[0] = \ + (0x7fff + ((DTABLE[CIDX][3*normalA[CIDX]] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalB[CIDX]] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalC[CIDX]] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalD[CIDX]] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalE[CIDX]] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalF[CIDX]] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalG[CIDX]] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalH[CIDX]] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpDColor[1] = \ + (0x7fff + ((DTABLE[CIDX][3*normalA[CIDX]+1] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalB[CIDX]+1] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalC[CIDX]+1] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalD[CIDX]+1] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalE[CIDX]+1] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalF[CIDX]+1] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalG[CIDX]+1] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalH[CIDX]+1] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpDColor[2] = \ + (0x7fff + ((DTABLE[CIDX][3*normalA[CIDX]+2] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalB[CIDX]+2] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalC[CIDX]+2] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalD[CIDX]+2] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalE[CIDX]+2] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalF[CIDX]+2] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalG[CIDX]+2] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (DTABLE[CIDX][3*normalH[CIDX]+2] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpSColor[0] = \ + (0x7fff + ((STABLE[CIDX][3*normalA[CIDX]] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalB[CIDX]] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalC[CIDX]] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalD[CIDX]] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalE[CIDX]] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalF[CIDX]] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalG[CIDX]] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalH[CIDX]] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpSColor[1] = \ + (0x7fff + ((STABLE[CIDX][3*normalA[CIDX]+1] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalB[CIDX]+1] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalC[CIDX]+1] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalD[CIDX]+1] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalE[CIDX]+1] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalF[CIDX]+1] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalG[CIDX]+1] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalH[CIDX]+1] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + _tmpSColor[2] = \ + (0x7fff + ((STABLE[CIDX][3*normalA[CIDX]+2] * ((0x4000 + w1Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalB[CIDX]+2] * ((0x4000 + w2Xw1Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalC[CIDX]+2] * ((0x4000 + w1Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalD[CIDX]+2] * ((0x4000 + w2Xw2Y*w1Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalE[CIDX]+2] * ((0x4000 + w1Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalF[CIDX]+2] * ((0x4000 + w2Xw1Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalG[CIDX]+2] * ((0x4000 + w1Xw2Y*w2Z)>>VTKKW_FP_SHIFT)) + \ + (STABLE[CIDX][3*normalH[CIDX]+2] * ((0x4000 + w2Xw2Y*w2Z)>>VTKKW_FP_SHIFT)))) >> VTKKW_FP_SHIFT; \ + \ + \ + COLOR[0] = static_cast<unsigned short>((_tmpDColor[0]*COLOR[0]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[1] = static_cast<unsigned short>((_tmpDColor[1]*COLOR[1]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[2] = static_cast<unsigned short>((_tmpDColor[2]*COLOR[2]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[0] += (_tmpSColor[0]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[1] += (_tmpSColor[1]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[2] += (_tmpSColor[2]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; +//ETX + +//BTX +#define VTKKWRCHelper_LookupColorUS( COLORTABLE, SCALAROPACITYTABLE, IDX, COLOR ) \ + COLOR[3] = SCALAROPACITYTABLE[IDX]; \ + if ( !COLOR[3] ) {continue;} \ + COLOR[0] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX ]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[1] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX+1]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[2] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX+2]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); +//ETX + +//BTX +#define VTKKWRCHelper_LookupColorMax( COLORTABLE, SCALAROPACITYTABLE, IDX, COLOR ) \ + COLOR[3] = SCALAROPACITYTABLE[IDX]; \ + COLOR[0] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX ]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[1] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX+1]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[2] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX+2]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); +//ETX + +//BTX +#define VTKKWRCHelper_LookupDependentColorUS( COLORTABLE, SCALAROPACITYTABLE, IDX, CMPS, COLOR ) \ + { \ + unsigned short _alpha; \ + switch ( CMPS ) \ + { \ + case 2: \ + _alpha = SCALAROPACITYTABLE[IDX[1]]; \ + COLOR[0] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX[0] ]*_alpha + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[1] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX[0]+1]*_alpha + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[2] = static_cast<unsigned short> \ + ((COLORTABLE[3*IDX[0]+2]*_alpha + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[3] = _alpha; \ + break; \ + case 4: \ + _alpha = SCALAROPACITYTABLE[IDX[3]]; \ + COLOR[0] = static_cast<unsigned short>((IDX[0]*_alpha + 0x7f)>>8 ); \ + COLOR[1] = static_cast<unsigned short>((IDX[1]*_alpha + 0x7f)>>8 ); \ + COLOR[2] = static_cast<unsigned short>((IDX[2]*_alpha + 0x7f)>>8 ); \ + COLOR[3] = _alpha; \ + break; \ + } \ + } +//ETX + +//BTX +#define VTKKWRCHelper_LookupColorGOUS( CTABLE, SOTABLE, GOTABLE, IDX, IDX2, COLOR ) \ + COLOR[3] = (SOTABLE[IDX] * GOTABLE[IDX2] + 0x7fff)>>VTKKW_FP_SHIFT; \ + if ( !COLOR[3] ) {continue;} \ + COLOR[0] = static_cast<unsigned short> \ + ((CTABLE[3*IDX ]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[1] = static_cast<unsigned short> \ + ((CTABLE[3*IDX+1]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + COLOR[2] = static_cast<unsigned short> \ + ((CTABLE[3*IDX+2]*COLOR[3] + 0x7fff)>>(VTKKW_FP_SHIFT)); +//ETX + +//BTX +#define VTKKWRCHelper_LookupShading( DTABLE, STABLE, NORMAL, COLOR ) \ + COLOR[0] = static_cast<unsigned short>((DTABLE[3*NORMAL ]*COLOR[0]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[1] = static_cast<unsigned short>((DTABLE[3*NORMAL+1]*COLOR[1]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[2] = static_cast<unsigned short>((DTABLE[3*NORMAL+2]*COLOR[2]+0x7fff)>>VTKKW_FP_SHIFT); \ + COLOR[0] += (STABLE[3*NORMAL ]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[1] += (STABLE[3*NORMAL+1]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[2] += (STABLE[3*NORMAL+2]*COLOR[3] + 0x7fff)>>VTKKW_FP_SHIFT; +//ETX + + +//BTX +#define VTKKWRCHelper_LookupAndCombineIndependentColorsUS( COLORTABLE, SOTABLE, \ + SCALAR, WEIGHTS, \ + COMPONENTS, COLOR ) \ + unsigned int _tmp[4] = {0,0,0,0}; \ + unsigned short _alpha[4] = {0,0,0,0}; \ + unsigned int _totalAlpha = 0; \ + \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>(SOTABLE[_idx][SCALAR[_idx]]*WEIGHTS[_idx]); \ + _totalAlpha += _alpha[_idx]; \ + }} \ + \ + if ( !_totalAlpha ) {continue;} \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + if ( _alpha[_idx] ) \ + { \ + _tmp[0] += static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx] ])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[1] += static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+1])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[2] += static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+2])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[3] += ((_alpha[_idx]*_alpha[_idx])/_totalAlpha); \ + } \ + }} \ + if ( !_tmp[3] ) {continue;} \ + COLOR[0] = (_tmp[0]>32767)?(32767):(_tmp[0]); \ + COLOR[1] = (_tmp[1]>32767)?(32767):(_tmp[1]); \ + COLOR[2] = (_tmp[2]>32767)?(32767):(_tmp[2]); \ + COLOR[3] = (_tmp[3]>32767)?(32767):(_tmp[3]); +//ETX + +//BTX +#define VTKKWRCHelper_LookupAndCombineIndependentColorsMax( COLORTABLE, SCALAROPACITYTABLE, \ + IDX, WEIGHTS, CMPS, COLOR ) \ + { \ + unsigned int _tmp[4] = {0,0,0,0}; \ + for ( int _idx = 0; _idx < CMPS; _idx++ ) \ + { \ + unsigned short _alpha = static_cast<unsigned short>(SCALAROPACITYTABLE[_idx][IDX[_idx]]*WEIGHTS[_idx]); \ + _tmp[0] += static_cast<unsigned short>(((COLORTABLE[_idx][3*IDX[_idx] ])*_alpha + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[1] += static_cast<unsigned short>(((COLORTABLE[_idx][3*IDX[_idx]+1])*_alpha + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[2] += static_cast<unsigned short>(((COLORTABLE[_idx][3*IDX[_idx]+2])*_alpha + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[3] += _alpha; \ + } \ + COLOR[0] = (_tmp[0]>32767)?(32767):(_tmp[0]); \ + COLOR[1] = (_tmp[1]>32767)?(32767):(_tmp[1]); \ + COLOR[2] = (_tmp[2]>32767)?(32767):(_tmp[2]); \ + COLOR[3] = (_tmp[3]>32767)?(32767):(_tmp[3]); \ + } +//ETX + +//BTX +#define VTKKWRCHelper_LookupAndCombineIndependentColorsGOUS( COLORTABLE, SOTABLE, \ + GOTABLE, \ + SCALAR, MAG, WEIGHTS, \ + COMPONENTS, COLOR ) \ + unsigned int _tmp[4] = {0,0,0,0}; \ + unsigned short _alpha[4] = {0,0,0,0}; \ + unsigned int _totalAlpha = 0; \ + \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>(SOTABLE[_idx][SCALAR[_idx]]*WEIGHTS[_idx]); \ + if ( _alpha[_idx] ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>((_alpha[_idx]*GOTABLE[_idx][MAG[_idx]] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _totalAlpha += _alpha[_idx]; \ + } \ + }} \ + \ + if ( !_totalAlpha ) {continue;} \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + if ( _alpha[_idx] ) \ + { \ + _tmp[0] += static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx] ])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[1] += static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+1])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[2] += static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+2])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmp[3] += ((_alpha[_idx]*_alpha[_idx])/_totalAlpha); \ + } \ + }} \ + if ( !_tmp[3] ) {continue;}; \ + COLOR[0] = (_tmp[0]>32767)?(32767):(_tmp[0]); \ + COLOR[1] = (_tmp[1]>32767)?(32767):(_tmp[1]); \ + COLOR[2] = (_tmp[2]>32767)?(32767):(_tmp[2]); \ + COLOR[3] = (_tmp[3]>32767)?(32767):(_tmp[3]); +//ETX + +//BTX +#define VTKKWRCHelper_LookupAndCombineIndependentColorsShadeUS( COLORTABLE, SOTABLE, \ + DTABLE, STABLE, \ + SCALAR, NORMAL, WEIGHTS, \ + COMPONENTS, COLOR ) \ + unsigned int _tmp[4] = {0,0,0,0}; \ + unsigned int _tmpC[3]; \ + unsigned short _alpha[4] = {0,0,0,0}; \ + unsigned int _totalAlpha = 0; \ + \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>(SOTABLE[_idx][SCALAR[_idx]]*WEIGHTS[_idx]); \ + _totalAlpha += _alpha[_idx]; \ + }} \ + \ + if ( !_totalAlpha ) {continue;} \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + if ( _alpha[_idx] ) \ + { \ + _tmpC[0] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx] ])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[1] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+1])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[2] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+2])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[0] = static_cast<unsigned short>((DTABLE[_idx][3*NORMAL[_idx] ]*_tmpC[0]+0x7fff)>>VTKKW_FP_SHIFT); \ + _tmpC[1] = static_cast<unsigned short>((DTABLE[_idx][3*NORMAL[_idx]+1]*_tmpC[1]+0x7fff)>>VTKKW_FP_SHIFT); \ + _tmpC[2] = static_cast<unsigned short>((DTABLE[_idx][3*NORMAL[_idx]+2]*_tmpC[2]+0x7fff)>>VTKKW_FP_SHIFT); \ + _tmpC[0] += (STABLE[_idx][3*NORMAL[_idx] ]*_alpha[_idx] + 0x7fff)>>VTKKW_FP_SHIFT; \ + _tmpC[1] += (STABLE[_idx][3*NORMAL[_idx]+1]*_alpha[_idx] + 0x7fff)>>VTKKW_FP_SHIFT; \ + _tmpC[2] += (STABLE[_idx][3*NORMAL[_idx]+2]*_alpha[_idx] + 0x7fff)>>VTKKW_FP_SHIFT; \ + _tmp[0] += _tmpC[0]; \ + _tmp[1] += _tmpC[1]; \ + _tmp[2] += _tmpC[2]; \ + _tmp[3] += ((_alpha[_idx]*_alpha[_idx])/_totalAlpha); \ + } \ + }} \ + if ( !_tmp[3] ) {continue;} \ + \ + COLOR[0] = (_tmp[0]>32767)?(32767):(_tmp[0]); \ + COLOR[1] = (_tmp[1]>32767)?(32767):(_tmp[1]); \ + COLOR[2] = (_tmp[2]>32767)?(32767):(_tmp[2]); \ + COLOR[3] = (_tmp[3]>32767)?(32767):(_tmp[3]); +//ETX + +//BTX +#define VTKKWRCHelper_LookupAndCombineIndependentColorsInterpolateShadeUS( COLORTABLE, SOTABLE, \ + DTABLE, STABLE, \ + SCALAR, WEIGHTS, \ + COMPONENTS, COLOR ) \ + unsigned int _tmp[4] = {0,0,0,0}; \ + unsigned int _tmpC[4]; \ + unsigned short _alpha[4] = {0,0,0,0}; \ + unsigned int _totalAlpha = 0; \ + \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>(SOTABLE[_idx][SCALAR[_idx]]*WEIGHTS[_idx]); \ + _totalAlpha += _alpha[_idx]; \ + }} \ + \ + if ( !_totalAlpha ) {continue;} \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + if ( _alpha[_idx] ) \ + { \ + _tmpC[0] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx] ])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[1] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+1])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[2] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+2])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[3] = _alpha[_idx]; \ + VTKKWRCHelper_InterpolateShadingComponent( DTABLE, STABLE, _tmpC, _idx ); \ + _tmp[0] += _tmpC[0]; \ + _tmp[1] += _tmpC[1]; \ + _tmp[2] += _tmpC[2]; \ + _tmp[3] += ((_alpha[_idx]*_alpha[_idx])/_totalAlpha); \ + } \ + }} \ + if (!_tmp[3]) {continue;} \ + COLOR[0] = (_tmp[0]>32767)?(32767):(_tmp[0]); \ + COLOR[1] = (_tmp[1]>32767)?(32767):(_tmp[1]); \ + COLOR[2] = (_tmp[2]>32767)?(32767):(_tmp[2]); \ + COLOR[3] = (_tmp[3]>32767)?(32767):(_tmp[3]); +//ETX + +//BTX +#define VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( COLOR, TMP, REMAININGOPACITY ) \ + COLOR[0] += (TMP[0]*REMAININGOPACITY+0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[1] += (TMP[1]*REMAININGOPACITY+0x7fff)>>VTKKW_FP_SHIFT; \ + COLOR[2] += (TMP[2]*REMAININGOPACITY+0x7fff)>>VTKKW_FP_SHIFT; \ + REMAININGOPACITY = (REMAININGOPACITY*((~(TMP[3])&VTKKW_FP_MASK))+0x7fff)>>VTKKW_FP_SHIFT; \ + if ( REMAININGOPACITY < 0xff ) \ + { \ + break; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_LookupAndCombineIndependentColorsGOShadeUS( COLORTABLE, SOTABLE, GOTABLE, \ + DTABLE, STABLE, \ + SCALAR, MAG, NORMAL, WEIGHTS, \ + COMPONENTS, COLOR ) \ + unsigned int _tmp[4] = {0,0,0,0}; \ + unsigned int _tmpC[3]; \ + unsigned short _alpha[4] = {0,0,0,0}; \ + unsigned int _totalAlpha = 0; \ + \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>(SOTABLE[_idx][SCALAR[_idx]]*WEIGHTS[_idx]); \ + if ( _alpha[_idx] ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>((_alpha[_idx]*GOTABLE[_idx][MAG[_idx]] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _totalAlpha += _alpha[_idx]; \ + } \ + }} \ + \ + if ( !_totalAlpha ) {continue;} \ + \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + if ( _alpha[_idx] ) \ + { \ + _tmpC[0] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx] ])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[1] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+1])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[2] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+2])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[0] = static_cast<unsigned short>((DTABLE[_idx][3*NORMAL[_idx] ]*_tmpC[0]+0x7fff)>>VTKKW_FP_SHIFT); \ + _tmpC[1] = static_cast<unsigned short>((DTABLE[_idx][3*NORMAL[_idx]+1]*_tmpC[1]+0x7fff)>>VTKKW_FP_SHIFT); \ + _tmpC[2] = static_cast<unsigned short>((DTABLE[_idx][3*NORMAL[_idx]+2]*_tmpC[2]+0x7fff)>>VTKKW_FP_SHIFT); \ + _tmpC[0] += (STABLE[_idx][3*NORMAL[_idx] ]*_alpha[_idx] + 0x7fff)>>VTKKW_FP_SHIFT; \ + _tmpC[1] += (STABLE[_idx][3*NORMAL[_idx]+1]*_alpha[_idx] + 0x7fff)>>VTKKW_FP_SHIFT; \ + _tmpC[2] += (STABLE[_idx][3*NORMAL[_idx]+2]*_alpha[_idx] + 0x7fff)>>VTKKW_FP_SHIFT; \ + _tmp[0] += _tmpC[0]; \ + _tmp[1] += _tmpC[1]; \ + _tmp[2] += _tmpC[2]; \ + _tmp[3] += ((_alpha[_idx]*_alpha[_idx])/_totalAlpha); \ + } \ + }} \ + if ( !_tmp[3] ) {continue;} \ + COLOR[0] = (_tmp[0]>32767)?(32767):(_tmp[0]); \ + COLOR[1] = (_tmp[1]>32767)?(32767):(_tmp[1]); \ + COLOR[2] = (_tmp[2]>32767)?(32767):(_tmp[2]); \ + COLOR[3] = (_tmp[3]>32767)?(32767):(_tmp[3]); +//ETX + +//BTX +#define VTKKWRCHelper_LookupAndCombineIndependentColorsGOInterpolateShadeUS( COLORTABLE, SOTABLE, GOTABLE, \ + DTABLE, STABLE, \ + SCALAR, MAG, WEIGHTS, \ + COMPONENTS, COLOR ) \ + unsigned int _tmp[4] = {0,0,0,0}; \ + unsigned int _tmpC[4]; \ + unsigned short _alpha[4] = {0,0,0,0}; \ + unsigned int _totalAlpha = 0; \ + \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>(SOTABLE[_idx][SCALAR[_idx]]*WEIGHTS[_idx]); \ + if ( _alpha[_idx] ) \ + { \ + _alpha[_idx] = static_cast<unsigned short>((_alpha[_idx]*GOTABLE[_idx][MAG[_idx]] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _totalAlpha += _alpha[_idx]; \ + } \ + }} \ + \ + if ( !_totalAlpha ) {continue;} \ + {for ( int _idx = 0; _idx < COMPONENTS; _idx++ ) \ + { \ + if ( _alpha[_idx] ) \ + { \ + _tmpC[0] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx] ])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[1] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+1])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[2] = static_cast<unsigned short>(((COLORTABLE[_idx][3*SCALAR[_idx]+2])*_alpha[_idx] + 0x7fff)>>(VTKKW_FP_SHIFT)); \ + _tmpC[3] = _alpha[_idx]; \ + VTKKWRCHelper_InterpolateShadingComponent( DTABLE, STABLE, _tmpC, _idx ); \ + _tmp[0] += _tmpC[0]; \ + _tmp[1] += _tmpC[1]; \ + _tmp[2] += _tmpC[2]; \ + _tmp[3] += ((_alpha[_idx]*_alpha[_idx])/_totalAlpha); \ + } \ + }} \ + if ( !_tmp[3] ) {continue;} \ + COLOR[0] = (_tmp[0]>32767)?(32767):(_tmp[0]); \ + COLOR[1] = (_tmp[1]>32767)?(32767):(_tmp[1]); \ + COLOR[2] = (_tmp[2]>32767)?(32767):(_tmp[2]); \ + COLOR[3] = (_tmp[3]>32767)?(32767):(_tmp[3]); +//ETX + + +//BTX +#define VTKKWRCHelper_SetPixelColor( IMAGEPTR, COLOR, REMAININGOPACITY ) \ + IMAGEPTR[0] = (COLOR[0]>32767)?(32767):(COLOR[0]); \ + IMAGEPTR[1] = (COLOR[1]>32767)?(32767):(COLOR[1]); \ + IMAGEPTR[2] = (COLOR[2]>32767)?(32767):(COLOR[2]); \ + unsigned int tmpAlpha = (~REMAININGOPACITY)&VTKKW_FP_MASK; \ + IMAGEPTR[3] = (tmpAlpha>32767)?(32767):(tmpAlpha); +//ETX + +//BTX +#define VTKKWRCHelper_MoveToNextSampleNN() \ + if ( k < numSteps-1 ) \ + { \ + mapper->FixedPointIncrement( pos, dir ); \ + mapper->ShiftVectorDown( pos, spos ); \ + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_MoveToNextSampleGONN() \ + if ( k < numSteps-1 ) \ + { \ + mapper->FixedPointIncrement( pos, dir ); \ + mapper->ShiftVectorDown( pos, spos ); \ + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + magPtr = gradientMag[spos[2]] + spos[0]*mInc[0] + spos[1]*mInc[1]; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_MoveToNextSampleShadeNN() \ + if ( k < numSteps-1 ) \ + { \ + mapper->FixedPointIncrement( pos, dir ); \ + mapper->ShiftVectorDown( pos, spos ); \ + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + dirPtr = gradientDir[spos[2]] + spos[0]*dInc[0] + spos[1]*dInc[1]; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_MoveToNextSampleGOShadeNN() \ + if ( k < numSteps-1 ) \ + { \ + mapper->FixedPointIncrement( pos, dir ); \ + mapper->ShiftVectorDown( pos, spos ); \ + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + magPtr = gradientMag[spos[2]] + spos[0]*mInc[0] + spos[1]*mInc[1]; \ + dirPtr = gradientDir[spos[2]] + spos[0]*dInc[0] + spos[1]*dInc[1]; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_InitializeVariables() \ + int i, j; \ + unsigned short *imagePtr; \ + \ + int imageInUseSize[2]; \ + int imageMemorySize[2]; \ + int imageViewportSize[2]; \ + int imageOrigin[2]; \ + int dim[3]; \ + float shift[4]; \ + float scale[4]; \ + \ + mapper->GetRayCastImage()->GetImageInUseSize(imageInUseSize); \ + mapper->GetRayCastImage()->GetImageMemorySize(imageMemorySize); \ + mapper->GetRayCastImage()->GetImageViewportSize(imageViewportSize); \ + mapper->GetRayCastImage()->GetImageOrigin(imageOrigin); \ + mapper->GetInput()->GetDimensions(dim); \ + mapper->GetTableShift( shift ); \ + mapper->GetTableScale( scale ); \ + \ + int *rowBounds = mapper->GetRowBounds(); \ + unsigned short *image = mapper->GetRayCastImage()->GetImage(); \ + vtkRenderWindow *renWin = mapper->GetRenderWindow(); \ + int components = mapper->GetInput()->GetNumberOfScalarComponents(); \ + int cropping = (mapper->GetCropping() && \ + mapper->GetCroppingRegionFlags() != 0x2000 ); \ + \ + unsigned short *colorTable[4]; \ + unsigned short *scalarOpacityTable[4]; \ + \ + int c; \ + for ( c = 0; c < 4; c++ ) \ + { \ + colorTable[c] = mapper->GetColorTable(c); \ + (void)(colorTable[c]); \ + scalarOpacityTable[c] = mapper->GetScalarOpacityTable(c); \ + } \ + \ + unsigned int inc[3]; \ + inc[0] = components; \ + inc[1] = dim[0]*components; \ + inc[2] = dim[0]*dim[1]*components; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeWeights() \ + float weights[4]; \ + weights[0] = vol->GetProperty()->GetComponentWeight(0); \ + weights[1] = vol->GetProperty()->GetComponentWeight(1); \ + weights[2] = vol->GetProperty()->GetComponentWeight(2); \ + weights[3] = vol->GetProperty()->GetComponentWeight(3); +//ETX + +//BTX +#define VTKKWRCHelper_InitializeVariablesGO() \ + unsigned short *gradientOpacityTable[4]; \ + for ( c = 0; c < 4; c++ ) \ + { \ + gradientOpacityTable[c] = mapper->GetGradientOpacityTable(c); \ + } \ + unsigned char **gradientMag = mapper->GetGradientMagnitude(); \ + \ + unsigned int mInc[3]; \ + if ( vol->GetProperty()->GetIndependentComponents() ) \ + { \ + mInc[0] = inc[0]; \ + mInc[1] = inc[1]; \ + mInc[2] = inc[2]; \ + } \ + else \ + { \ + mInc[0] = 1; \ + mInc[1] = dim[0]; \ + mInc[2] = dim[0]*dim[1]; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_InitializeVariablesShade() \ + unsigned short *diffuseShadingTable[4]; \ + unsigned short *specularShadingTable[4]; \ + for ( c = 0; c < 4; c++ ) \ + { \ + diffuseShadingTable[c] = mapper->GetDiffuseShadingTable(c); \ + specularShadingTable[c] = mapper->GetSpecularShadingTable(c); \ + } \ + unsigned short **gradientDir = mapper->GetGradientNormal(); \ + unsigned int dInc[3]; \ + if ( vol->GetProperty()->GetIndependentComponents() ) \ + { \ + dInc[0] = inc[0]; \ + dInc[1] = inc[1]; \ + dInc[2] = inc[2]; \ + } \ + else \ + { \ + dInc[0] = 1; \ + dInc[1] = dim[0]; \ + dInc[2] = dim[0]*dim[1]; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_InitializeTrilinVariables() \ + unsigned int Binc = components; \ + unsigned int Cinc = dim[0]*components; \ + unsigned int Dinc = dim[0]*components + components; \ + unsigned int Einc = dim[0]*dim[1]*components; \ + unsigned int Finc = dim[0]*dim[1]*components + components; \ + unsigned int Ginc = dim[0]*dim[1]*components + dim[0]*components; \ + unsigned int Hinc = dim[0]*dim[1]*components + dim[0]*components + components; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeTrilinVariablesGO() \ + int magOffset; \ + if ( vol->GetProperty()->GetIndependentComponents() ) \ + { \ + magOffset = components; \ + } \ + else \ + { \ + magOffset = 1; \ + } \ + \ + unsigned int mBFinc = magOffset; \ + unsigned int mCGinc = dim[0]*magOffset; \ + unsigned int mDHinc = dim[0]*magOffset + magOffset; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeTrilinVariablesShade() \ + int dirOffset; \ + if ( vol->GetProperty()->GetIndependentComponents() ) \ + { \ + dirOffset = components; \ + } \ + else \ + { \ + dirOffset = 1; \ + } \ + \ + unsigned int dBFinc = dirOffset; \ + unsigned int dCGinc = dim[0]*dirOffset; \ + unsigned int dDHinc = dim[0]*dirOffset + dirOffset; +//ETX + +//BTX +#define VTKKWRCHelper_OuterInitialization() \ + if ( j%threadCount != threadID ) \ + { \ + continue; \ + } \ + if ( !threadID ) \ + { \ + if ( renWin->CheckAbortStatus() ) \ + { \ + break; \ + } \ + } \ + else if ( renWin->GetAbortRender() ) \ + { \ + break; \ + } \ + imagePtr = image + 4*(j*imageMemorySize[0] + rowBounds[j*2]); + +//ETX + +//BTX +#define VTKKWRCHelper_InnerInitialization() \ + unsigned int numSteps; \ + unsigned int pos[3]; \ + unsigned int dir[3]; \ + mapper->ComputeRayInfo( i, j, pos, dir, &numSteps ); \ + if ( numSteps == 0 ) \ + { \ + *(imagePtr ) = 0; \ + *(imagePtr+1) = 0; \ + *(imagePtr+2) = 0; \ + *(imagePtr+3) = 0; \ + imagePtr += 4; \ + continue; \ + } \ + unsigned int spos[3]; \ + unsigned int k; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeMIPOneNN() \ + mapper->ShiftVectorDown( pos, spos ); \ + T *dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + T maxValue = *(dptr); +//ETX + +//BTX +#define VTKKWRCHelper_InitializeMIPMultiNN() \ + mapper->ShiftVectorDown( pos, spos ); \ + T *dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + T maxValue[4]; \ + for ( c = 0; c < components; c++ ) \ + { \ + maxValue[c] = *(dptr+c); \ + } +//ETX + +//BTX +#define VTKKWRCHelper_InitializeMIPOneTrilin() \ + T *dptr; \ + unsigned int oldSPos[3]; \ + \ + oldSPos[0] = (pos[0] >> VTKKW_FP_SHIFT) + 1; \ + \ + unsigned int w1X, w1Y, w1Z; \ + unsigned int w2X, w2Y, w2Z; \ + unsigned int w1Xw1Y, w2Xw1Y, w1Xw2Y, w2Xw2Y; \ + \ + unsigned short maxValue=0; \ + unsigned short val; \ + unsigned int A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeMIPMultiTrilin() \ + T *dptr; \ + unsigned int oldSPos[3]; \ + \ + oldSPos[0] = (pos[0] >> VTKKW_FP_SHIFT) + 1; \ + \ + unsigned int w1X, w1Y, w1Z; \ + unsigned int w2X, w2Y, w2Z; \ + unsigned int w1Xw1Y, w2Xw1Y, w1Xw2Y, w2Xw2Y; \ + \ + unsigned short maxValue[4]; \ + unsigned short val[4]; \ + unsigned int A[4],B[4],C[4],D[4],E[4],F[4],G[4],H[4]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeGONN() \ + unsigned char *magPtr = gradientMag[spos[2]] + spos[0]*mInc[0] + spos[1]*mInc[1]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeShadeNN() \ + unsigned short *dirPtr = gradientDir[spos[2]] + spos[0]*dInc[0] + spos[1]*dInc[1]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeOneNN() \ + mapper->ShiftVectorDown( pos, spos ); \ + T *dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + unsigned int color[3] = {0,0,0}; \ + unsigned short remainingOpacity = 0x7fff; \ + unsigned short tmp[4]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeMultiNN() \ + mapper->ShiftVectorDown( pos, spos ); \ + T *dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; \ + unsigned int color[3] = {0,0,0}; \ + unsigned int remainingOpacity = 0x7fff; \ + unsigned short tmp[4]; \ + unsigned short val[4]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeOneTrilin() \ + T *dptr; \ + unsigned int oldSPos[3]; \ + \ + oldSPos[0] = (pos[0] >> VTKKW_FP_SHIFT) + 1; \ + \ + unsigned int w1X, w1Y, w1Z; \ + unsigned int w2X, w2Y, w2Z; \ + unsigned int w1Xw1Y, w2Xw1Y, w1Xw2Y, w2Xw2Y; \ + \ + unsigned short val; \ + unsigned int A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0; \ + \ + unsigned int color[3] = {0,0,0}; \ + unsigned short remainingOpacity = 0x7fff; \ + unsigned short tmp[4]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeOneGOTrilin() \ + unsigned char *magPtrABCD = 0, *magPtrEFGH = 0; \ + unsigned short mag; \ + unsigned int mA=0,mB=0,mC=0,mD=0,mE=0,mF=0,mG=0,mH=0; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeOneShadeTrilin() \ + unsigned short *dirPtrABCD = 0, *dirPtrEFGH = 0; \ + unsigned int normalA=0,normalB=0,normalC=0,normalD=0; \ + unsigned int normalE=0,normalF=0,normalG=0,normalH=0; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeMultiTrilin() \ + T *dptr; \ + unsigned int oldSPos[3]; \ + \ + oldSPos[0] = (pos[0] >> VTKKW_FP_SHIFT) + 1; \ + \ + unsigned int w1X, w1Y, w1Z; \ + unsigned int w2X, w2Y, w2Z; \ + unsigned int w1Xw1Y, w2Xw1Y, w1Xw2Y, w2Xw2Y; \ + \ + unsigned short val[4]; \ + unsigned int A[4],B[4],C[4],D[4],E[4],F[4],G[4],H[4]; \ + \ + unsigned int color[3] = {0,0,0}; \ + unsigned short remainingOpacity = 0x7fff; \ + unsigned short tmp[4]; + +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeMultiGOTrilin() \ + unsigned char *magPtrABCD = 0, *magPtrEFGH = 0; \ + unsigned short mag[4]; \ + unsigned int mA[4],mB[4],mC[4],mD[4],mE[4],mF[4],mG[4],mH[4]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializeCompositeMultiShadeTrilin() \ + unsigned short *dirPtrABCD = 0, *dirPtrEFGH = 0; \ + unsigned int normalA[4],normalB[4],normalC[4],normalD[4]; \ + unsigned int normalE[4],normalF[4],normalG[4],normalH[4]; +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartNN() \ + VTKKWRCHelper_InitializeVariables(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartGONN() \ + VTKKWRCHelper_InitializeVariables(); \ + VTKKWRCHelper_InitializeVariablesGO(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartShadeNN() \ + VTKKWRCHelper_InitializeVariables(); \ + VTKKWRCHelper_InitializeVariablesShade(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartGOShadeNN() \ + VTKKWRCHelper_InitializeVariables(); \ + VTKKWRCHelper_InitializeVariablesGO(); \ + VTKKWRCHelper_InitializeVariablesShade(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartTrilin() \ + VTKKWRCHelper_InitializeVariables(); \ + VTKKWRCHelper_InitializeTrilinVariables(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartGOTrilin() \ + VTKKWRCHelper_InitializeVariables(); \ + VTKKWRCHelper_InitializeVariablesGO(); \ + VTKKWRCHelper_InitializeTrilinVariables(); \ + VTKKWRCHelper_InitializeTrilinVariablesGO(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartShadeTrilin() \ + VTKKWRCHelper_InitializeVariables(); \ + VTKKWRCHelper_InitializeVariablesShade(); \ + VTKKWRCHelper_InitializeTrilinVariables(); \ + VTKKWRCHelper_InitializeTrilinVariablesShade(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin() \ + VTKKWRCHelper_InitializeVariables(); \ + VTKKWRCHelper_InitializeVariablesShade(); \ + VTKKWRCHelper_InitializeVariablesGO(); \ + VTKKWRCHelper_InitializeTrilinVariables(); \ + VTKKWRCHelper_InitializeTrilinVariablesShade(); \ + VTKKWRCHelper_InitializeTrilinVariablesGO(); \ + for ( j = 0; j < imageInUseSize[1]; j++ ) \ + { \ + VTKKWRCHelper_OuterInitialization(); \ + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) \ + { \ + VTKKWRCHelper_InnerInitialization(); +//ETX + +//BTX +#define VTKKWRCHelper_IncrementAndLoopEnd() \ + imagePtr+=4; \ + } \ + if ( j%32 == 31 ) \ + { \ + float fargs[1]; \ + fargs[0] = static_cast<float>(j)/static_cast<float>(imageInUseSize[1]-1); \ + mapper->InvokeEvent( vtkCommand::ProgressEvent, fargs ); \ + } \ + } +//ETX + +//BTX +#define VTKKWRCHelper_CroppingCheckTrilin( POS ) \ + if ( cropping ) \ + { \ + if ( mapper->CheckIfCropped( POS ) ) \ + { \ + continue; \ + } \ + } +//ETX + +//BTX +#define VTKKWRCHelper_CroppingCheckNN( POS ) \ + if ( cropping ) \ + { \ + if ( mapper->CheckIfCropped( POS ) ) \ + { \ + continue; \ + } \ + } +//ETX + +//BTX +#define VTKKWRCHelper_SpaceLeapSetup() \ + unsigned int mmpos[3]; \ + mmpos[0] = (pos[0] >> VTKKW_FPMM_SHIFT) + 1; \ + mmpos[1] = 0; \ + mmpos[2] = 0; \ + int mmvalid = 0; +//ETX + +//BTX +#define VTKKWRCHelper_SpaceLeapSetupMulti() \ + unsigned int mmpos[3]; \ + mmpos[0] = (pos[0] >> VTKKW_FPMM_SHIFT) + 1; \ + mmpos[1] = 0; \ + mmpos[2] = 0; \ + int mmvalid[4] = {0,0,0,0}; +//ETX + + +//BTX +#define VTKKWRCHelper_SpaceLeapCheck() \ + if ( pos[0] >> VTKKW_FPMM_SHIFT != mmpos[0] || \ + pos[1] >> VTKKW_FPMM_SHIFT != mmpos[1] || \ + pos[2] >> VTKKW_FPMM_SHIFT != mmpos[2] ) \ + { \ + mmpos[0] = pos[0] >> VTKKW_FPMM_SHIFT; \ + mmpos[1] = pos[1] >> VTKKW_FPMM_SHIFT; \ + mmpos[2] = pos[2] >> VTKKW_FPMM_SHIFT; \ + mmvalid = mapper->CheckMinMaxVolumeFlag( mmpos, 0 ); \ + } \ + \ + if ( !mmvalid ) \ + { \ + continue; \ + } +//ETX + +//BTX +#define VTKKWRCHelper_MIPSpaceLeapCheck( MAXIDX, MAXIDXDEF ) \ + if ( pos[0] >> VTKKW_FPMM_SHIFT != mmpos[0] || \ + pos[1] >> VTKKW_FPMM_SHIFT != mmpos[1] || \ + pos[2] >> VTKKW_FPMM_SHIFT != mmpos[2] ) \ + { \ + mmpos[0] = pos[0] >> VTKKW_FPMM_SHIFT; \ + mmpos[1] = pos[1] >> VTKKW_FPMM_SHIFT; \ + mmpos[2] = pos[2] >> VTKKW_FPMM_SHIFT; \ + mmvalid = (MAXIDXDEF)? \ + (mapper->CheckMIPMinMaxVolumeFlag( mmpos, 0, MAXIDX )):(1); \ + } \ + \ + if ( !mmvalid ) \ + { \ + continue; \ + } +//ETX + + +//BTX +#define VTKKWRCHelper_MIPSpaceLeapPopulateMulti( MAXIDX ) \ + if ( pos[0] >> VTKKW_FPMM_SHIFT != mmpos[0] || \ + pos[1] >> VTKKW_FPMM_SHIFT != mmpos[1] || \ + pos[2] >> VTKKW_FPMM_SHIFT != mmpos[2] ) \ + { \ + mmpos[0] = pos[0] >> VTKKW_FPMM_SHIFT; \ + mmpos[1] = pos[1] >> VTKKW_FPMM_SHIFT; \ + mmpos[2] = pos[2] >> VTKKW_FPMM_SHIFT; \ + for ( c = 0; c < components; c++ ) \ + { \ + mmvalid[c] = mapper->CheckMIPMinMaxVolumeFlag( mmpos, c, MAXIDX[c] ); \ + } \ + } +//ETX + +//BTX +#define VTKKWRCHelper_MIPSpaceLeapCheckMulti( COMP ) mmvalid[COMP] +//ETX + +#include "vtkObject.h" + +class vtkFixedPointVolumeRayCastMapper; +class vtkVolume; + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointVolumeRayCastHelper : public vtkObject +{ +public: + static vtkFixedPointVolumeRayCastHelper *New(); + vtkTypeRevisionMacro(vtkFixedPointVolumeRayCastHelper,vtkObject); + void PrintSelf( ostream& os, vtkIndent indent ); + + virtual void GenerateImage( int, + int, + vtkVolume *, + vtkFixedPointVolumeRayCastMapper *) {} + +protected: + vtkFixedPointVolumeRayCastHelper(); + ~vtkFixedPointVolumeRayCastHelper(); + + +private: + vtkFixedPointVolumeRayCastHelper(const vtkFixedPointVolumeRayCastHelper&); // Not implemented. + void operator=(const vtkFixedPointVolumeRayCastHelper&); // Not implemented. +}; + +#endif + + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastMIPHelper.cxx b/VolumeRendering/vtkFixedPointVolumeRayCastMIPHelper.cxx new file mode 100644 index 0000000..f14b943 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastMIPHelper.cxx @@ -0,0 +1,665 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastMIPHelper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointVolumeRayCastMIPHelper.h" + +#include "vtkImageData.h" +#include "vtkCommand.h" +#include "vtkFixedPointVolumeRayCastMapper.h" +#include "vtkObjectFactory.h" +#include "vtkRenderWindow.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkFixedPointRayCastImage.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFixedPointVolumeRayCastMIPHelper, "$Revision: 1.6 $"); +vtkStandardNewMacro(vtkFixedPointVolumeRayCastMIPHelper); + +// Construct a new vtkFixedPointVolumeRayCastMIPHelper with default values +vtkFixedPointVolumeRayCastMIPHelper::vtkFixedPointVolumeRayCastMIPHelper() +{ +} + +// Destruct a vtkFixedPointVolumeRayCastMIPHelper - clean up any memory used +vtkFixedPointVolumeRayCastMIPHelper::~vtkFixedPointVolumeRayCastMIPHelper() +{ +} + +// This method is called when the interpolation type is nearest neighbor and +// the data contains one component. In the inner loop we will compute the +// maximum value (in native type). After we have a maximum value for the ray +// we will convert it to unsigned short using the scale/shift, then use this +// index to lookup the final color/opacity. +template <class T> +void vtkFixedPointMIPHelperGenerateImageOneNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeMIPOneNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + if ( cropping ) + { + int maxValueDefined = 0; + unsigned short maxIdx = 0; + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_MIPSpaceLeapCheck( maxIdx, maxValueDefined ); + + if ( !mapper->CheckIfCropped( pos ) ) + { + mapper->ShiftVectorDown( pos, spos ); + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + if ( !maxValueDefined || *dptr > maxValue ) + { + maxValue = *dptr; + maxIdx = static_cast<unsigned short>((maxValue + shift[0])*scale[0]); + maxValueDefined = 1; + } + } + } + + if ( maxValueDefined ) + { + VTKKWRCHelper_LookupColorMax( colorTable[0], scalarOpacityTable[0], maxIdx, imagePtr ); + } + else + { + imagePtr[0] = imagePtr[1] = imagePtr[2] = imagePtr[3] = 0; + } + } + else + { + unsigned short maxIdx = + static_cast<unsigned short>((maxValue + shift[0])*scale[0]); + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_MIPSpaceLeapCheck( maxIdx, 1 ); + + mapper->ShiftVectorDown( pos, spos ); + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + maxValue = ( *dptr > maxValue )?(*dptr):(maxValue); + maxIdx = static_cast<unsigned short>((maxValue + shift[0])*scale[0]); + } + + VTKKWRCHelper_LookupColorMax( colorTable[0], scalarOpacityTable[0], maxIdx, imagePtr ); + } + + VTKKWRCHelper_IncrementAndLoopEnd(); + +} + +// This method is called when the interpolation type is nearest neighbor and +// the data has two or four dependent components. If it is four, they must be +// unsigned char components. Compute max of last components in native type, +// then use first component to look up a color (2 component data) or first three +// as the color directly (four component data). Lookup alpha off the last component. +template <class T> +void vtkFixedPointMIPHelperGenerateImageDependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeMIPMultiNN(); + VTKKWRCHelper_SpaceLeapSetup(); + + int maxValueDefined = 0; + unsigned short maxIdxS = 0; + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_MIPSpaceLeapCheck( maxIdxS, maxValueDefined ); + VTKKWRCHelper_CroppingCheckNN( pos ); + + mapper->ShiftVectorDown( pos, spos ); + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + if ( !maxValueDefined || *(dptr + components - 1) > maxValue[components-1] ) + { + for ( c = 0; c < components; c++ ) + { + maxValue[c] = *(dptr+c); + } + maxIdxS = (unsigned short)((maxValue[components-1] + + shift[components-1])*scale[components-1]); + maxValueDefined = 1; + } + } + + if ( maxValueDefined ) + { + unsigned short maxIdx[4]; + for ( c = 0; c < components; c++ ) + { + maxIdx[c] = (unsigned short)((maxValue[c] + shift[c])*scale[c]); + } + VTKKWRCHelper_LookupDependentColorUS( colorTable[0], scalarOpacityTable[0], + maxIdx, components, imagePtr ); + } + else + { + imagePtr[0] = imagePtr[1] = imagePtr[2] = imagePtr[3] = 0; + } + + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is called when the interpolation type is nearest neighbor and +// the data has more than one independent components. We compute the max of +// each component along the ray in native type, then use the scale/shift to +// convert this into an unsigned short index value. We use the index values +// to lookup the color/opacity per component, then use the component weights to +// blend these into one final color. +template <class T> +void vtkFixedPointMIPHelperGenerateImageIndependentNN( T *data, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartNN(); + VTKKWRCHelper_InitializeMIPMultiNN(); + VTKKWRCHelper_SpaceLeapSetupMulti(); + + int maxValueDefined = 0; + unsigned short maxIdx[4]; + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + VTKKWRCHelper_CroppingCheckNN( pos ); + VTKKWRCHelper_MIPSpaceLeapPopulateMulti( maxIdx ) + + mapper->ShiftVectorDown( pos, spos ); + dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + + if ( !maxValueDefined ) + { + for ( c = 0; c < components; c++ ) + { + maxValue[c] = *(dptr+c); + maxIdx[c] = (unsigned short)((maxValue[c] + shift[c])*scale[c]); + } + maxValueDefined = 1; + } + else + { + for ( c = 0; c < components; c++ ) + { + if ( VTKKWRCHelper_MIPSpaceLeapCheckMulti( c ) && + *(dptr + c) > maxValue[c] ) + { + maxValue[c] = *(dptr+c); + maxIdx[c] = (unsigned short)((maxValue[c] + shift[c])*scale[c]); + } + } + } + } + + imagePtr[0] = imagePtr[1] = imagePtr[2] = imagePtr[3] = 0; + if ( maxValueDefined ) + { + VTKKWRCHelper_LookupAndCombineIndependentColorsMax( colorTable, + scalarOpacityTable, + maxIdx, weights, + components, imagePtr ); + } + + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is called when the interpolation type is linear, the +// data contains one component and scale = 1.0 and shift = 0.0. This is +// the simple case were we do not need to apply scale/shift in the +// inner loop. In the inner loop we compute the eight cell vertex values +// (if we have changed cells). We compute our weights within the cell +// according to our fractional position within the cell, and apply trilinear +// interpolation to compute the index. We find the maximum index along +// the ray, and then use this to look up a final color. +template <class T> +void vtkFixedPointMIPHelperGenerateImageOneSimpleTrilin( T *dataPtr, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeMIPOneTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int maxValueDefined = 0; + unsigned short maxIdx=0; + unsigned short maxScalar = 0; + + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_MIPSpaceLeapCheck( maxIdx, maxValueDefined ); + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + dptr = dataPtr + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValuesSimple( dptr ); + maxScalar = (A>B)?(A):(B); + maxScalar = (C>maxScalar)?(C):(maxScalar); + maxScalar = (D>maxScalar)?(D):(maxScalar); + maxScalar = (E>maxScalar)?(E):(maxScalar); + maxScalar = (F>maxScalar)?(F):(maxScalar); + maxScalar = (G>maxScalar)?(G):(maxScalar); + maxScalar = (H>maxScalar)?(H):(maxScalar); + } + + if ( !maxValueDefined || maxScalar > maxValue ) + { + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + if ( !maxValueDefined || val > maxValue ) + { + maxValue = val; + maxIdx = static_cast<unsigned short>(maxValue); + maxValueDefined = 1; + } + } + } + + if ( maxValueDefined ) + { + VTKKWRCHelper_LookupColorMax( colorTable[0], scalarOpacityTable[0], maxIdx, imagePtr ); + } + else + { + imagePtr[0] = imagePtr[1] = imagePtr[2] = imagePtr[3] = 0; + } + + VTKKWRCHelper_IncrementAndLoopEnd(); +} + + +// This method is called when the interpolation type is linear, the +// data contains one component and scale != 1.0 or shift != 0.0. This +// means that we need to apply scale/shift in the inner loop to compute +// an unsigned short index value. In the inner loop we compute the eight cell +// vertex values (as unsigned short indices, if we have changed cells). We +// compute our weights within the cell according to our fractional position +// within the cell, and apply trilinear interpolation to compute the index. +// We find the maximum index along the ray, and then use this to look up a +// final color. +template <class T> +void vtkFixedPointMIPHelperGenerateImageOneTrilin( T *dataPtr, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeMIPOneTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int maxValueDefined = 0; + unsigned short maxIdx = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_CroppingCheckTrilin( pos ); + VTKKWRCHelper_MIPSpaceLeapCheck( maxIdx, maxValueDefined ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + + dptr = dataPtr + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2]; + VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] ); + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalar(val); + + if ( !maxValueDefined || val > maxValue ) + { + maxValue = val; + maxIdx = static_cast<unsigned short>(maxValue); + maxValueDefined = 1; + } + } + + if ( maxValueDefined ) + { + VTKKWRCHelper_LookupColorMax( colorTable[0], scalarOpacityTable[0], maxIdx, imagePtr ); + } + else + { + imagePtr[0] = imagePtr[1] = imagePtr[2] = imagePtr[3] = 0; + } + + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear, the data has +// two or four components and the components are not considered independent. +// For four component d>>(VTKKW_FP_SHIFT - 8));ata, the data must be unsigned char in type. In the +// inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as unsigned shorts (we use the +// scale/shift to ensure the correct range). We compute our weights within +// the cell according to our fractional position within the cell, and apply +// trilinear interpolation to compute the index values. For two component data, +// We use the first index to lookup a color and the second to look up an opacity +// for this sample. For four component data we use the first three components +// directly as a color, then we look up the opacity using the fourth component. +// We then composite this into the color computed so far along the ray, and +// check if we can terminate at this point (if the accumulated opacity is +// higher than some threshold). +template <class T> +void vtkFixedPointMIPHelperGenerateImageDependentTrilin( T *dataPtr, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vtkNotUsed(vol)) +{ + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeMIPMultiTrilin(); + VTKKWRCHelper_SpaceLeapSetup(); + + int maxValueDefined = 0; + unsigned short maxIdx = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_CroppingCheckTrilin( pos ); + VTKKWRCHelper_MIPSpaceLeapCheck( maxIdx, maxValueDefined ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + for ( c= 0; c < components; c++ ) + { + dptr = dataPtr + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2] + c; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, c, scale[c], shift[c] ); + } + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + + if ( !maxValueDefined || (val[components-1] > maxValue[components-1]) ) + { + for ( c= 0; c < components; c++ ) + { + maxValue[c] = val[c]; + } + maxIdx = static_cast<unsigned short>((maxValue[components-1] + + shift[components-1])*scale[components-1]); + maxValueDefined = 1; + } + } + + if ( maxValueDefined ) + { + VTKKWRCHelper_LookupDependentColorUS( colorTable[0], + scalarOpacityTable[0], + maxValue, components, imagePtr ); + } + else + { + imagePtr[0] = imagePtr[1] = imagePtr[2] = imagePtr[3] = 0; + } + + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +// This method is used when the interpolation type is linear, the data has +// more than one component and the components are considered independent. In +// the inner loop we get the data value for the eight cell corners (if we have +// changed cells) for all components as an unsigned shorts (we have to use the +// scale/shift to ensure that we obtained unsigned short indices) We compute our +// weights within the cell according to our fractional position within the cell, +// and apply trilinear interpolation to compute a value for each component. We do +// this for each sample along the ray to find a maximum value per component, then +// we look up a color/opacity for each component and blend them according to the +// component weights. +template <class T> +void vtkFixedPointMIPHelperGenerateImageIndependentTrilin( T *dataPtr, + int threadID, + int threadCount, + vtkFixedPointVolumeRayCastMapper *mapper, + vtkVolume *vol) +{ + VTKKWRCHelper_InitializeWeights(); + VTKKWRCHelper_InitializationAndLoopStartTrilin(); + VTKKWRCHelper_InitializeMIPMultiTrilin(); + + int maxValueDefined = 0; + for ( k = 0; k < numSteps; k++ ) + { + if ( k ) + { + mapper->FixedPointIncrement( pos, dir ); + } + + VTKKWRCHelper_CroppingCheckTrilin( pos ); + + mapper->ShiftVectorDown( pos, spos ); + if ( spos[0] != oldSPos[0] || + spos[1] != oldSPos[1] || + spos[2] != oldSPos[2] ) + { + oldSPos[0] = spos[0]; + oldSPos[1] = spos[1]; + oldSPos[2] = spos[2]; + + for ( c= 0; c < components; c++ ) + { + dptr = dataPtr + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2] + c; + VTKKWRCHelper_GetCellComponentScalarValues( dptr, c, scale[c], shift[c] ); + } + } + + VTKKWRCHelper_ComputeWeights(pos); + VTKKWRCHelper_InterpolateScalarComponent( val, c, components ); + + if ( !maxValueDefined ) + { + for ( c= 0; c < components; c++ ) + { + maxValue[c] = val[c]; + } + maxValueDefined = 1; + } + else + { + for ( c= 0; c < components; c++ ) + { + if ( (val[c] > maxValue[c]) ) + { + maxValue[c] = val[c]; + } + } + } + } + + imagePtr[0] = imagePtr[1] = imagePtr[2] = imagePtr[3] = 0; + if ( maxValueDefined ) + { + VTKKWRCHelper_LookupAndCombineIndependentColorsMax( colorTable, scalarOpacityTable, + maxValue, weights, components, imagePtr ); + } + + VTKKWRCHelper_IncrementAndLoopEnd(); +} + +void vtkFixedPointVolumeRayCastMIPHelper::GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper ) +{ + void *dataPtr = mapper->GetInput()->GetScalarPointer(); + int scalarType = mapper->GetInput()->GetScalarType(); + + // Nearest Neighbor interpolate + if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) ) + { + // One component data + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointMIPHelperGenerateImageOneNN( + (VTK_TT *)(dataPtr), + threadID, threadCount, mapper, vol) ); + } + } + // More that one independent components + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointMIPHelperGenerateImageIndependentNN( + (VTK_TT *)(dataPtr), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent (color) components + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointMIPHelperGenerateImageDependentNN( + (VTK_TT *)(dataPtr), + threadID, threadCount, mapper, vol) ); + } + } + } + // Trilinear Interpolation + else + { + // One component + if ( mapper->GetInput()->GetNumberOfScalarComponents() == 1 ) + { + // Scale == 1.0 and shift == 0.0 - simple case (faster) + if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointMIPHelperGenerateImageOneSimpleTrilin( + (VTK_TT *)(dataPtr), + threadID, threadCount, mapper, vol) ); + } + } + // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointMIPHelperGenerateImageOneTrilin( + (VTK_TT *)(dataPtr), + threadID, threadCount, mapper, vol) ); + } + } + } + // Indepedent components (more than one) + else if ( vol->GetProperty()->GetIndependentComponents() ) + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointMIPHelperGenerateImageIndependentTrilin( + (VTK_TT *)(dataPtr), + threadID, threadCount, mapper, vol) ); + } + } + // Dependent components + else + { + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointMIPHelperGenerateImageDependentTrilin( + (VTK_TT *)(dataPtr), + threadID, threadCount, mapper, vol) ); + } + } + } +} + +// Print method for vtkFixedPointVolumeRayCastMIPHelper +void vtkFixedPointVolumeRayCastMIPHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastMIPHelper.h b/VolumeRendering/vtkFixedPointVolumeRayCastMIPHelper.h new file mode 100644 index 0000000..4dba923 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastMIPHelper.h @@ -0,0 +1,57 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastMIPHelper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFixedPointVolumeRayCastMIPHelper - A helper that generates MIP images for the volume ray cast mapper +// .SECTION Description +// This is one of the helper classes for the vtkFixedPointVolumeRayCastMapper. +// It will generate maximum intensity images. +// This class should not be used directly, it is a helper class for +// the mapper and has no user-level API. +// +// .SECTION see also +// vtkFixedPointVolumeRayCastMapper + +#ifndef __vtkFixedPointVolumeRayCastMIPHelper_h +#define __vtkFixedPointVolumeRayCastMIPHelper_h + +#include "vtkFixedPointVolumeRayCastHelper.h" + +class vtkFixedPointVolumeRayCastMapper; +class vtkVolume; + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointVolumeRayCastMIPHelper : public vtkFixedPointVolumeRayCastHelper +{ +public: + static vtkFixedPointVolumeRayCastMIPHelper *New(); + vtkTypeRevisionMacro(vtkFixedPointVolumeRayCastMIPHelper,vtkFixedPointVolumeRayCastHelper); + void PrintSelf( ostream& os, vtkIndent indent ); + + virtual void GenerateImage( int threadID, + int threadCount, + vtkVolume *vol, + vtkFixedPointVolumeRayCastMapper *mapper); + +protected: + vtkFixedPointVolumeRayCastMIPHelper(); + ~vtkFixedPointVolumeRayCastMIPHelper(); + +private: + vtkFixedPointVolumeRayCastMIPHelper(const vtkFixedPointVolumeRayCastMIPHelper&); // Not implemented. + void operator=(const vtkFixedPointVolumeRayCastMIPHelper&); // Not implemented. +}; + +#endif + + + diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastMapper.cxx b/VolumeRendering/vtkFixedPointVolumeRayCastMapper.cxx new file mode 100644 index 0000000..47a446b --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastMapper.cxx @@ -0,0 +1,3066 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkFixedPointVolumeRayCastMapper.h" + +#include "vtkCamera.h" +#include "vtkColorTransferFunction.h" +#include "vtkEncodedGradientShader.h" +#include "vtkFiniteDifferenceGradientEstimator.h" +#include "vtkImageData.h" +#include "vtkCommand.h" +#include "vtkGraphicsFactory.h" +#include "vtkSphericalDirectionEncoder.h" +#include "vtkFixedPointVolumeRayCastCompositeGOHelper.h" +#include "vtkFixedPointVolumeRayCastCompositeGOShadeHelper.h" +#include "vtkFixedPointVolumeRayCastCompositeHelper.h" +#include "vtkFixedPointVolumeRayCastCompositeShadeHelper.h" +#include "vtkFixedPointVolumeRayCastMIPHelper.h" +#include "vtkMath.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" +#include "vtkPlaneCollection.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTimerLog.h" +#include "vtkTransform.h" +#include "vtkVolumeProperty.h" +#include "vtkRayCastImageDisplayHelper.h" +#include "vtkFixedPointRayCastImage.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkFixedPointVolumeRayCastMapper, "$Revision: 1.20.4.1 $"); +vtkStandardNewMacro(vtkFixedPointVolumeRayCastMapper); +vtkCxxSetObjectMacro(vtkFixedPointVolumeRayCastMapper, RayCastImage, vtkFixedPointRayCastImage); + +// Macro for tri-linear interpolation - do four linear interpolations on +// edges, two linear interpolations between pairs of edges, then a final +// interpolation between faces +#define vtkTrilinFuncMacro(v,x,y,z,a,b,c,d,e,f,g,h) \ + t00 = a + (x)*(b-a); \ + t01 = c + (x)*(d-c); \ + t10 = e + (x)*(f-e); \ + t11 = g + (x)*(h-g); \ + t0 = t00 + (y)*(t01-t00); \ + t1 = t10 + (y)*(t11-t10); \ + v = t0 + (z)*(t1-t0); + + +#define vtkVRCMultiplyPointMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[1] + A[2]*M[2] + M[3]; \ + B[1] = A[0]*M[4] + A[1]*M[5] + A[2]*M[6] + M[7]; \ + B[2] = A[0]*M[8] + A[1]*M[9] + A[2]*M[10] + M[11]; \ + B[3] = A[0]*M[12] + A[1]*M[13] + A[2]*M[14] + M[15]; \ + if ( B[3] != 1.0 ) { B[0] /= B[3]; B[1] /= B[3]; B[2] /= B[3]; } + +#define vtkVRCMultiplyViewPointMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[1] + A[2]*M[2] + M[3]; \ + B[1] = A[0]*M[4] + A[1]*M[5] + A[2]*M[6] + M[7]; \ + B[3] = A[0]*M[12] + A[1]*M[13] + A[2]*M[14] + M[15]; \ + if ( B[3] != 1.0 ) { B[0] /= B[3]; B[1] /= B[3]; } + +#define vtkVRCMultiplyNormalMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[4] + A[2]*M[8]; \ + B[1] = A[0]*M[1] + A[1]*M[5] + A[2]*M[9]; \ + B[2] = A[0]*M[2] + A[1]*M[6] + A[2]*M[10] + + +template <class T> +void vtkFixedPointVolumeRayCastMapperFillInMinMaxVolume( T *dataPtr, unsigned short *minMaxVolume, + int fullDim[3], int smallDim[4], + int independent, int components, + float *shift, float *scale ) +{ + int i, j, k, c; + int sx1, sx2, sy1, sy2, sz1, sz2; + int x, y, z; + + T *dptr = dataPtr; + + for ( k = 0; k < fullDim[2]; k++ ) + { + sz1 = (k < 1)?(0):(static_cast<int>((k-1)/4)); + sz2 = static_cast<int>((k )/4); + sz2 = ( k == fullDim[2]-1 )?(sz1):(sz2); + for ( j = 0; j < fullDim[1]; j++ ) + { + sy1 = (j < 1)?(0):(static_cast<int>((j-1)/4)); + sy2 = static_cast<int>((j )/4); + sy2 = ( j == fullDim[1]-1 )?(sy1):(sy2); + for ( i = 0; i < fullDim[0]; i++ ) + { + sx1 = (i < 1)?(0):(static_cast<int>((i-1)/4)); + sx2 = static_cast<int>((i )/4); + sx2 = ( i == fullDim[0]-1 )?(sx1):(sx2); + + for ( c = 0; c < smallDim[3]; c++ ) + { + unsigned short val; + if ( independent ) + { + val = static_cast<unsigned short>((*dptr + shift[c]) * scale[c]); + dptr++; + } + else + { + val = static_cast<unsigned short>((*(dptr+components-1) + + shift[components-1]) * scale[components-1]); + dptr += components; + } + + for ( z = sz1; z <= sz2; z++ ) + { + for ( y = sy1; y <= sy2; y++ ) + { + for ( x = sx1; x <= sx2; x++ ) + { + unsigned short *tmpPtr = minMaxVolume + + 3*( z*smallDim[0]*smallDim[1]*smallDim[3] + + y*smallDim[0]*smallDim[3] + + x*smallDim[3] + c); + + tmpPtr[0] = (val<tmpPtr[0])?(val):(tmpPtr[0]); + tmpPtr[1] = (val>tmpPtr[1])?(val):(tmpPtr[1]); + } + } + } + } + } + } + } +} + +template <class T> +void vtkFixedPointVolumeRayCastMapperComputeGradients( T *dataPtr, + int dim[3], + double spacing[3], + int components, + int independent, + double scalarRange[4][2], + unsigned short **gradientNormal, + unsigned char **gradientMagnitude, + vtkDirectionEncoder *directionEncoder, + vtkFixedPointVolumeRayCastMapper *me ) +{ + int x, y, z, c; + int x_start, x_limit; + int y_start, y_limit; + int z_start, z_limit; + T *dptr, *cdptr; + float n[3], t; + float gvalue=0; + int xlow, xhigh; + double aspect[3]; + int xstep, ystep, zstep; + float scale[4]; + unsigned short *dirPtr, *cdirPtr; + unsigned char *magPtr, *cmagPtr; + + + me->InvokeEvent( vtkCommand::StartEvent, NULL ); + + double avgSpacing = (spacing[0]+spacing[1]+spacing[2])/3.0; + + // adjust the aspect + aspect[0] = spacing[0] * 2.0 / avgSpacing; + aspect[1] = spacing[1] * 2.0 / avgSpacing; + aspect[2] = spacing[2] * 2.0 / avgSpacing; + + // Compute steps through the volume in x, y, and z + xstep = components; + ystep = components*dim[0]; + zstep = components*dim[0] * dim[1]; + + if ( !independent ) + { + if ( scalarRange[components-1][1] - scalarRange[components-1][0] ) + { + scale[0] = 255.0 / (0.25*(scalarRange[components-1][1] - scalarRange[components-1][0])); + } + else + { + scale[0] = 0.0; + } + } + else + { + for (c = 0; c < components; c++ ) + { + if ( scalarRange[c][1] - scalarRange[c][0] ) + { + scale[c] = 255.0 / (0.25*(scalarRange[c][1] - scalarRange[c][0])); + } + else + { + scale[c] = 1.0; + } + } + } + + + int thread_id = 0; + int thread_count = 1; + + x_start = 0; + x_limit = dim[0]; + y_start = 0; + y_limit = dim[1]; + z_start = (int)(( (float)thread_id / (float)thread_count ) * + dim[2] ); + z_limit = (int)(( (float)(thread_id + 1) / (float)thread_count ) * + dim[2] ); + + // Do final error checking on limits - make sure they are all within bounds + // of the scalar input + + x_start = (x_start<0)?(0):(x_start); + y_start = (y_start<0)?(0):(y_start); + z_start = (z_start<0)?(0):(z_start); + + x_limit = (x_limit>dim[0])?(dim[0]):(x_limit); + y_limit = (y_limit>dim[1])?(dim[1]):(y_limit); + z_limit = (z_limit>dim[2])?(dim[2]):(z_limit); + + + int increment = (independent)?(components):(1); + + float tolerance[4]; + for ( c = 0; c < components; c++ ) + { + tolerance[c] = .00001 * (scalarRange[c][1] - scalarRange[c][0]); + } + + // Loop through all the data and compute the encoded normal and + // gradient magnitude for each scalar location + for ( z = z_start; z < z_limit; z++ ) + { + unsigned short *gradientDirPtr = gradientNormal[z]; + unsigned char *gradientMagPtr = gradientMagnitude[z]; + + for ( y = y_start; y < y_limit; y++ ) + { + xlow = x_start; + xhigh = x_limit; + + dptr = dataPtr + components*(z * dim[0] * dim[1] + y * dim[0] + xlow); + + dirPtr = gradientDirPtr + (y * dim[0] + xlow)*increment; + magPtr = gradientMagPtr + (y * dim[0] + xlow)*increment; + + for ( x = xlow; x < xhigh; x++ ) + { + for ( c = 0; ( independent && c < components ) || c == 0; c++ ) + { + cdptr = dptr + ((independent)?(c):(components-1)); + cdirPtr = dirPtr + ((independent)?(c):(0)); + cmagPtr = magPtr + ((independent)?(c):(0)); + + // Allow up to 3 tries to find the gadient - looking out at a distance of + // 1, 2, and 3 units. + int foundGradient = 0; + for ( int d = 1; d <= 3 && !foundGradient; d++ ) + { + // Use a central difference method if possible, + // otherwise use a forward or backward difference if + // we are on the edge + // Compute the X component + if ( x < d ) + { + n[0] = 2.0*((float)*(cdptr) - (float)*(cdptr+d*xstep)); + } + else if ( x >= dim[0] - d ) + { + n[0] = 2.0*((float)*(cdptr-d*xstep) - (float)*(cdptr)); + } + else + { + n[0] = (float)*(cdptr-d*xstep) - (float)*(cdptr+d*xstep); + } + + // Compute the Y component + if ( y < d ) + { + n[1] = 2.0*((float)*(cdptr) - (float)*(cdptr+d*ystep)); + } + else if ( y >= dim[1] - d ) + { + n[1] = 2.0*((float)*(cdptr-d*ystep) - (float)*(cdptr)); + } + else + { + n[1] = (float)*(cdptr-d*ystep) - (float)*(cdptr+d*ystep); + } + + // Compute the Z component + if ( z < d ) + { + n[2] = 2.0*((float)*(cdptr) - (float)*(cdptr+d*zstep)); + } + else if ( z >= dim[2] - d ) + { + n[2] = 2.0*((float)*(cdptr-d*zstep) - (float)*(cdptr)); + } + else + { + n[2] = (float)*(cdptr-d*zstep) - (float)*(cdptr+d*zstep); + } + + // Take care of the aspect ratio of the data + // Scaling in the vtkVolume is isotropic, so this is the + // only place we have to worry about non-isotropic scaling. + n[0] /= d*aspect[0]; + n[1] /= d*aspect[1]; + n[2] /= d*aspect[2]; + + // Compute the gradient magnitude + t = sqrt( (double)( n[0]*n[0] + + n[1]*n[1] + + n[2]*n[2] ) ); + + + // Encode this into an 8 bit value + gvalue = t * scale[c]; + + if ( d > 1 ) + { + gvalue = 0; + } + + gvalue = (gvalue<0.0)?(0.0):(gvalue); + gvalue = (gvalue>255.0)?(255.0):(gvalue); + + // Normalize the gradient direction + if ( t > tolerance[c] ) + { + n[0] /= t; + n[1] /= t; + n[2] /= t; + foundGradient = 1; + } + else + { + n[0] = n[1] = n[2] = 0.0; + } + } + + + *cmagPtr = static_cast<unsigned char>(gvalue + 0.5); + *cdirPtr = directionEncoder->GetEncodedDirection( n ); + } + + dptr += components; + dirPtr += increment; + magPtr += increment; + } + } + if ( z%8 == 7 ) + { + float args[1]; + args[0] = + static_cast<float>(z - z_start) / + static_cast<float>(z_limit - z_start - 1); + me->InvokeEvent( vtkCommand::ProgressEvent, args ); + } + } + + me->InvokeEvent( vtkCommand::EndEvent, NULL ); +} + +// Construct a new vtkFixedPointVolumeRayCastMapper with default values +vtkFixedPointVolumeRayCastMapper::vtkFixedPointVolumeRayCastMapper() +{ + this->SampleDistance = 1.0; + this->InteractiveSampleDistance = 2.0; + this->ImageSampleDistance = 1.0; + this->MinimumImageSampleDistance = 1.0; + this->MaximumImageSampleDistance = 10.0; + this->AutoAdjustSampleDistances = 1; + + // Should never be used without initialization, but + // set here to avoid compiler warnings + this->OldSampleDistance = 1.0; + this->OldImageSampleDistance = 1.0; + + this->PerspectiveMatrix = vtkMatrix4x4::New(); + this->ViewToWorldMatrix = vtkMatrix4x4::New(); + this->ViewToVoxelsMatrix = vtkMatrix4x4::New(); + this->VoxelsToViewMatrix = vtkMatrix4x4::New(); + this->WorldToVoxelsMatrix = vtkMatrix4x4::New(); + this->VoxelsToWorldMatrix = vtkMatrix4x4::New(); + + this->VolumeMatrix = vtkMatrix4x4::New(); + + this->PerspectiveTransform = vtkTransform::New(); + this->VoxelsTransform = vtkTransform::New(); + this->VoxelsToViewTransform = vtkTransform::New(); + + this->Threader = vtkMultiThreader::New(); + + this->RayCastImage = vtkFixedPointRayCastImage::New(); + + this->RowBounds = NULL; + this->OldRowBounds = NULL; + + this->RenderTimeTable = NULL; + this->RenderVolumeTable = NULL; + this->RenderRendererTable = NULL; + this->RenderTableSize = 0; + this->RenderTableEntries = 0; + + this->RenderWindow = NULL; + + this->MIPHelper = vtkFixedPointVolumeRayCastMIPHelper::New(); + this->CompositeHelper = vtkFixedPointVolumeRayCastCompositeHelper::New(); + this->CompositeGOHelper = vtkFixedPointVolumeRayCastCompositeGOHelper::New(); + this->CompositeShadeHelper = vtkFixedPointVolumeRayCastCompositeShadeHelper::New(); + this->CompositeGOShadeHelper = vtkFixedPointVolumeRayCastCompositeGOShadeHelper::New(); + + this->IntermixIntersectingGeometry = 1; + + int i; + for ( i = 0; i < 4; i++ ) + { + this->SavedRGBFunction[i] = NULL; + this->SavedGrayFunction[i] = NULL; + this->SavedScalarOpacityFunction[i] = NULL; + this->SavedGradientOpacityFunction[i] = NULL; + this->SavedColorChannels[i] = 0; + this->SavedScalarOpacityDistance[i] = 0; + } + + this->SavedSampleDistance = 0; + this->SavedBlendMode = -1; + + this->SavedGradientsInput = NULL; + this->SavedParametersInput = NULL; + + this->NumberOfGradientSlices = 0; + this->GradientNormal = NULL; + this->GradientMagnitude = NULL; + this->ContiguousGradientNormal = NULL; + this->ContiguousGradientMagnitude = NULL; + + this->DirectionEncoder = vtkSphericalDirectionEncoder::New(); + this->GradientShader = vtkEncodedGradientShader::New(); + this->GradientEstimator = vtkFiniteDifferenceGradientEstimator::New(); + + this->GradientEstimator->SetDirectionEncoder( this->DirectionEncoder ); + + this->ShadingRequired = 0; + this->GradientOpacityRequired = 0; + + this->CroppingRegionMask[0] = 1; + for ( i = 1; i < 27; i++ ) + { + this->CroppingRegionMask[i] = this->CroppingRegionMask[i-1]*2; + } + + this->NumTransformedClippingPlanes = 0; + this->TransformedClippingPlanes = NULL; + + this->ImageDisplayHelper = vtkRayCastImageDisplayHelper::New(); + this->ImageDisplayHelper->PreMultipliedColorsOn(); + this->ImageDisplayHelper->SetPixelScale( 2.0 ); + + // This is the min max volume used for space leaping. Each 4x4x4 cell from + // the original input volume has three values per component - a minimum scalar + // index, maximum scalar index, and a values used for both the maximum gradient + // magnitude and a flag. The flag is used to indicate for the + // current transfer function whether any non-zero opacity exists between the + // minimum and maximum scalar values and up to the maximum gradient magnitude + this->MinMaxVolume = NULL; + this->MinMaxVolumeSize[0] = 0; + this->MinMaxVolumeSize[1] = 0; + this->MinMaxVolumeSize[2] = 0; + this->MinMaxVolumeSize[3] = 0; + this->SavedMinMaxInput = NULL; + + this->Volume = NULL; + + +} + +// Destruct a vtkFixedPointVolumeRayCastMapper - clean up any memory used +vtkFixedPointVolumeRayCastMapper::~vtkFixedPointVolumeRayCastMapper() +{ + this->PerspectiveMatrix->Delete(); + this->ViewToWorldMatrix->Delete(); + this->ViewToVoxelsMatrix->Delete(); + this->VoxelsToViewMatrix->Delete(); + this->WorldToVoxelsMatrix->Delete(); + this->VoxelsToWorldMatrix->Delete(); + + this->VolumeMatrix->Delete(); + + this->VoxelsTransform->Delete(); + this->VoxelsToViewTransform->Delete(); + this->PerspectiveTransform->Delete(); + + this->Threader->Delete(); + + this->MIPHelper->Delete(); + this->CompositeHelper->Delete(); + this->CompositeGOHelper->Delete(); + this->CompositeShadeHelper->Delete(); + this->CompositeGOShadeHelper->Delete(); + + if ( this->RayCastImage ) + { + this->RayCastImage->Delete(); + this->RayCastImage = NULL; + } + + delete [] this->RenderTimeTable; + delete [] this->RenderVolumeTable; + delete [] this->RenderRendererTable; + + delete [] this->RowBounds; + delete [] this->OldRowBounds; + + int i; + if ( this->GradientNormal ) + { + // Contiguous? Delete in one chunk otherwise delete slice by slice + if ( this->ContiguousGradientNormal ) + { + delete [] this->ContiguousGradientNormal; + this->ContiguousGradientNormal = NULL; + } + else + { + for ( i = 0; i < this->NumberOfGradientSlices; i++ ) + { + delete [] this->GradientNormal[i]; + } + } + delete [] this->GradientNormal; + this->GradientNormal = NULL; + } + + if ( this->GradientMagnitude ) + { + // Contiguous? Delete in one chunk otherwise delete slice by slice + if ( this->ContiguousGradientMagnitude ) + { + delete [] this->ContiguousGradientMagnitude; + this->ContiguousGradientMagnitude = NULL; + } + else + { + for ( i = 0; i < this->NumberOfGradientSlices; i++ ) + { + delete [] this->GradientMagnitude[i]; + } + } + delete [] this->GradientMagnitude; + this->GradientMagnitude = NULL; + } + + this->DirectionEncoder->Delete(); + this->GradientShader->Delete(); + this->GradientEstimator->Delete(); + + delete [] this->TransformedClippingPlanes; + + this->ImageDisplayHelper->Delete(); + + // Delete storage used by min/max volume + delete [] this->MinMaxVolume; +} + +float vtkFixedPointVolumeRayCastMapper::ComputeRequiredImageSampleDistance( float desiredTime, + vtkRenderer *ren ) +{ + return this->ComputeRequiredImageSampleDistance( desiredTime, ren, NULL ); +} + +float vtkFixedPointVolumeRayCastMapper::ComputeRequiredImageSampleDistance( float desiredTime, + vtkRenderer *ren, + vtkVolume *vol ) +{ + float result; + + float oldTime; + + if ( vol ) + { + oldTime = this->RetrieveRenderTime( ren, vol ); + } + else + { + oldTime = this->RetrieveRenderTime( ren ); + } + + float newTime = desiredTime; + + if ( oldTime == 0.0 ) + { + if ( newTime > 10 ) + { + result = this->MinimumImageSampleDistance; + } + else + { + result = this->MaximumImageSampleDistance / 2.0; + } + } + else + { + oldTime /= (this->ImageSampleDistance * this->ImageSampleDistance); + result = this->ImageSampleDistance * sqrt(oldTime / newTime); + result = (result > this->MaximumImageSampleDistance)? + (this->MaximumImageSampleDistance):(result); + result = + (result<this->MinimumImageSampleDistance)? + (this->MinimumImageSampleDistance):(result); + } + + return result; +} + +float vtkFixedPointVolumeRayCastMapper::RetrieveRenderTime( vtkRenderer *ren, + vtkVolume *vol ) +{ + int i; + + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + return this->RenderTimeTable[i]; + } + } + + return 0.0; +} + +float vtkFixedPointVolumeRayCastMapper::RetrieveRenderTime( vtkRenderer *ren ) +{ + int i; + + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderRendererTable[i] == ren ) + { + return this->RenderTimeTable[i]; + } + } + + return 0.0; +} + +void vtkFixedPointVolumeRayCastMapper::StoreRenderTime( vtkRenderer *ren, + vtkVolume *vol, + float time ) +{ + int i; + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + this->RenderTimeTable[i] = time; + return; + } + } + + + // Need to increase size + if ( this->RenderTableEntries >= this->RenderTableSize ) + { + if ( this->RenderTableSize == 0 ) + { + this->RenderTableSize = 10; + } + else + { + this->RenderTableSize *= 2; + } + + float *oldTimePtr = this->RenderTimeTable; + vtkVolume **oldVolumePtr = this->RenderVolumeTable; + vtkRenderer **oldRendererPtr = this->RenderRendererTable; + + this->RenderTimeTable = new float [this->RenderTableSize]; + this->RenderVolumeTable = new vtkVolume *[this->RenderTableSize]; + this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize]; + + for (i = 0; i < this->RenderTableEntries; i++ ) + { + this->RenderTimeTable[i] = oldTimePtr[i]; + this->RenderVolumeTable[i] = oldVolumePtr[i]; + this->RenderRendererTable[i] = oldRendererPtr[i]; + } + + delete [] oldTimePtr; + delete [] oldVolumePtr; + delete [] oldRendererPtr; + } + + this->RenderTimeTable[this->RenderTableEntries] = time; + this->RenderVolumeTable[this->RenderTableEntries] = vol; + this->RenderRendererTable[this->RenderTableEntries] = ren; + + this->RenderTableEntries++; +} + +void vtkFixedPointVolumeRayCastMapper::SetNumberOfThreads( int num ) +{ + this->Threader->SetNumberOfThreads( num ); +} + +int vtkFixedPointVolumeRayCastMapper::GetNumberOfThreads() +{ + if (this->Threader) + { + return this->Threader->GetNumberOfThreads(); + } + return 0; +} + +void vtkFixedPointVolumeRayCastMapper::FillInMaxGradientMagnitudes( int fullDim[3], + int smallDim[4] ) +{ + int i, j, k, c; + int sx1, sx2, sy1, sy2, sz1, sz2; + int x, y, z; + + + for ( k = 0; k < fullDim[2]; k++ ) + { + sz1 = (k < 1)?(0):(static_cast<int>((k-1)/4)); + sz2 = static_cast<int>((k )/4); + sz2 = ( k == fullDim[2]-1 )?(sz1):(sz2); + + unsigned char *dptr = this->GradientMagnitude[k]; + + for ( j = 0; j < fullDim[1]; j++ ) + { + sy1 = (j < 1)?(0):(static_cast<int>((j-1)/4)); + sy2 = static_cast<int>((j )/4); + sy2 = ( j == fullDim[1]-1 )?(sy1):(sy2); + + for ( i = 0; i < fullDim[0]; i++ ) + { + sx1 = (i < 1)?(0):(static_cast<int>((i-1)/4)); + sx2 = static_cast<int>((i )/4); + sx2 = ( i == fullDim[0]-1 )?(sx1):(sx2); + + for ( c = 0; c < smallDim[3]; c++ ) + { + unsigned char val; + val = *dptr; + dptr++; + + for ( z = sz1; z <= sz2; z++ ) + { + for ( y = sy1; y <= sy2; y++ ) + { + for ( x = sx1; x <= sx2; x++ ) + { + unsigned short *tmpPtr = this->MinMaxVolume + + 3*( z*smallDim[0]*smallDim[1]*smallDim[3] + + y*smallDim[0]*smallDim[3] + + x*smallDim[3] + c); + + // Need to keep track of max gradient magnitude in upper + // eight bits. No need to preserve lower eight (the flag) + // since we will be recomputing this. + tmpPtr[2] = (val>(tmpPtr[2]>>8))?(val<<8):(tmpPtr[2]); + } + } + } + } + } + } + } +} + +// This method should be called after UpdateColorTables since it +// relies on some information (shift and scale) computed in that method, +// as well as the last built time for the color tables. +void vtkFixedPointVolumeRayCastMapper::UpdateMinMaxVolume( vtkVolume *vol ) +{ + int i, j, k, c; + + // A three bit variable: + // first bit indicates need to update flags + // second bit indicates need to update scalars + // third bit indicates need to update gradient magnitudes + int needToUpdate = 0; + + // Get the image data + vtkImageData *input = this->GetInput(); + + // We'll need this info later + int components = input->GetPointData()->GetScalars()->GetNumberOfComponents(); + int independent = vol->GetProperty()->GetIndependentComponents(); + int dim[3]; + input->GetDimensions( dim ); + + // Has the data itself changed? + if ( input != this->SavedMinMaxInput || + input->GetMTime() > this->SavedMinMaxBuildTime.GetMTime() ) + { + needToUpdate |= 0x03; + } + + // Do the gradient magnitudes need to be filled in? + if ( this->GradientOpacityRequired && + ( needToUpdate&0x02 || + this->SavedGradientsMTime.GetMTime() > + this->SavedMinMaxBuildTime.GetMTime() ) ) + { + needToUpdate |= 0x05; + } + + // Have the parameters changed which means the flags need + // to be recomputed. Actually, we could be checking just + // a subset of these parameters (we don't need to recompute + // the flags if the colors change, but unless these seems + // like a significant performance problem, I'd rather not + // complicate the code) + if ( !(needToUpdate&0x01) && + this->SavedParametersMTime.GetMTime() > + this->SavedMinMaxFlagTime.GetMTime() ) + { + needToUpdate |= 0x01; + } + + + if ( !needToUpdate ) + { + return; + } + + // Regenerate the min max values if necessary + if ( needToUpdate&0x02 ) + { + // How big should the min/max volume be? + int targetSize[4]; + + for ( i = 0; i < 3; i++ ) + { + // We group four cells (which require 5 samples) into one element in the min/max tree + targetSize[i] = + (dim[i] < 2) ? (1) : ( 1 + static_cast<int>((dim[i] - 2)/4)); + } + + // This fourth dimension is the number of independent components for which we + // need to keep track of min/max + targetSize[3] = (independent)?(components):(1); + + if ( this->MinMaxVolumeSize[0] != targetSize[0] || + this->MinMaxVolumeSize[1] != targetSize[1] || + this->MinMaxVolumeSize[2] != targetSize[2] || + this->MinMaxVolumeSize[3] != targetSize[3] ) + { + delete [] this->MinMaxVolume; + + // One entry for min, one for max, one shared by max gradient + // magnitude, and a flag set based on opacity transfer functions + this->MinMaxVolume = new unsigned short [3 * ( targetSize[0] * + targetSize[1] * + targetSize[2] * + targetSize[3] ) ]; + + // Don't really do anything about it - but reporting this error may + // save some debugging time later... + if ( !this->MinMaxVolume ) + { + vtkErrorMacro( "Problem allocating min/max volume" ); + this->MinMaxVolumeSize[0] = 0; + this->MinMaxVolumeSize[1] = 0; + this->MinMaxVolumeSize[2] = 0; + this->MinMaxVolumeSize[3] = 0; + return; + } + + this->MinMaxVolumeSize[0] = targetSize[0]; + this->MinMaxVolumeSize[1] = targetSize[1]; + this->MinMaxVolumeSize[2] = targetSize[2]; + this->MinMaxVolumeSize[3] = targetSize[3]; + + // Initialize the structure + unsigned short *tmpPtr = this->MinMaxVolume; + for ( i = 0; i < targetSize[0] * targetSize[1] * targetSize[2]; i++ ) + { + for ( j = 0; j < targetSize[3]; j++ ) + { + *(tmpPtr++) = 0xffff; // Min Scalar + *(tmpPtr++) = 0; // Max Scalar + *(tmpPtr++) = 0; // Max Gradient Magnitude and + } // Flag computed from transfer functions + } + + // Now put the scalar data values into the structure + int scalarType = input->GetScalarType(); + void *dataPtr = input->GetScalarPointer(); + + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointVolumeRayCastMapperFillInMinMaxVolume( + (VTK_TT *)(dataPtr), this->MinMaxVolume, dim, targetSize, + independent, components, this->TableShift, this->TableScale) ); + } + } + + this->SavedMinMaxInput = input; + this->SavedMinMaxBuildTime.Modified(); + } + + if ( needToUpdate&0x04 ) + { + // Now put the gradient magnitude values into the structure + this->FillInMaxGradientMagnitudes( dim, this->MinMaxVolumeSize ); + + // It is OK to use this same variable for scalars and gradient magnitudes - either + // we just rebuilt the min max volume from the scalars, or the MTime on the input + // is already less than this build time so updating it again won't matter for + // future checks + this->SavedMinMaxBuildTime.Modified(); + } + + // Update the flags now + unsigned short *minNonZeroScalarIndex = new unsigned short [this->MinMaxVolumeSize[3]]; + for ( c = 0; c < this->MinMaxVolumeSize[3]; c++ ) + { + for ( i = 0; i < this->TableSize[c]; i++ ) + { + if ( this->ScalarOpacityTable[c][i] ) + { + break; + } + } + minNonZeroScalarIndex[c] = i; + } + + unsigned char *minNonZeroGradientMagnitudeIndex = new unsigned char [this->MinMaxVolumeSize[3]]; + for ( c = 0; c < this->MinMaxVolumeSize[3]; c++ ) + { + for ( i = 0; i < 256; i++ ) + { + if ( this->GradientOpacityTable[c][i] ) + { + break; + } + } + minNonZeroGradientMagnitudeIndex[c] = i; + } + + unsigned short *tmpPtr = this->MinMaxVolume; + int zero = 0; + int nonZero = 0; + + for ( k = 0; k < this->MinMaxVolumeSize[2]; k++ ) + { + for ( j = 0; j < this->MinMaxVolumeSize[1]; j++ ) + { + for ( i = 0; i < this->MinMaxVolumeSize[0]; i++ ) + { + for ( c = 0; c < this->MinMaxVolumeSize[3]; c++ ) + { + // We definite have 0 opacity because our maximum scalar value in + // this region is below the minimum scalar value with non-zero opacity + // for this component + if ( tmpPtr[1] < minNonZeroScalarIndex[c] ) + { + tmpPtr[2] &= 0xff00; + zero++; + } + // We have 0 opacity because we are using gradient magnitudes and + // the maximum gradient magnitude in this area is below the minimum + // gradient magnitude with non-zero opacity for this component + else if ( this->GradientOpacityRequired && + (tmpPtr[2]>>8) < minNonZeroGradientMagnitudeIndex[c] ) + { + tmpPtr[2] &= 0xff00; + zero++; + } + // We definitely have non-zero opacity because our minimum scalar + // value is lower than our first scalar with non-zero opacity, and + // the maximum scalar value is greater than this threshold - so + // we must encounter scalars with opacity in between + else if ( tmpPtr[0] < minNonZeroScalarIndex[c] ) + { + tmpPtr[2] &= 0xff00; + tmpPtr[2] |= 0x0001; + nonZero++; + } + // We have to search between min scalar value and the + // max scalar stored in the minmax volume to look for non-zero + // opacity since both values must be above our first non-zero + // threshold so we don't have information in this area + else + { + int loop; + for ( loop = tmpPtr[0]; loop <= tmpPtr[1]; loop++ ) + { + if ( this->ScalarOpacityTable[c][loop] ) + { + break; + } + } + if ( loop <= tmpPtr[1] ) + { + tmpPtr[2] &= 0xff00; + tmpPtr[2] |= 0x0001; + nonZero++; + } + else + { + tmpPtr[2] &= 0xff00; + zero++; + } + } + tmpPtr += 3; + } + } + } + } + + this->SavedMinMaxFlagTime.Modified(); + +} + +void vtkFixedPointVolumeRayCastMapper::UpdateCroppingRegions() +{ + this->ConvertCroppingRegionPlanesToVoxels(); + + int i; + for ( i = 0; i < 6; i++ ) + { + this->FixedPointCroppingRegionPlanes[i] = + this->ToFixedPointPosition( this->VoxelCroppingRegionPlanes[i] ); + } + +} + +// This is the initialization that should be done once per image +// The render has been broken into several parts to support AMR +// volume rendering. Basically, this is done by having the AMR +// mapper call the PerImageInitialization once, then the +// PerVolumeInitialization once for each volume in the hierarchical +// structure. Finally, the AMR mapper divides all the volumes +// into subvolumes in order to render everything in a back-to-front +// order. The PerSubVolumeInitialization is called for each subvolume, +// then the RenderSubVolume is called. Finally, the DisplayImage method +// is called to map the image onto the screen. When this class is used +// directly as the mapper, the Render method calls these initialization +// methods and the RenderSubVolumeMethod. The AMR mapper will set the +// multiRender flag to 1 indicating that the PerImageInitialization +// should fully polulate the RayCastImage class based on the +// origin, spacing, and extent passed in. This will result in computing +// some things twice - once for the "full" volume (the extent bounding +// all volumes in the hierarchy), then once for each volume in the +// hierarchy. This does not make sense when rendering just a single +// volume so the multiRender flag indicates whether to do this +// computation here or skip it for later. +int vtkFixedPointVolumeRayCastMapper::PerImageInitialization( vtkRenderer *ren, + vtkVolume *vol, + int multiRender, + double inputOrigin[3], + double inputSpacing[3], + int inputExtent[6] ) +{ + // Save this so that we can restore it if the image is cancelled + this->OldImageSampleDistance = this->ImageSampleDistance; + this->OldSampleDistance = this->SampleDistance; + + // If we are automatically adjusting the size to achieve a desired frame + // rate, then do that adjustment here. Base the new image sample distance + // on the previous one and the previous render time. Don't let + // the adjusted image sample distance be less than the minimum image sample + // distance or more than the maximum image sample distance. + if ( this->AutoAdjustSampleDistances ) + { + this->ImageSampleDistance = + this->ComputeRequiredImageSampleDistance( vol->GetAllocatedRenderTime(), ren, vol ); + + // If this is an interactive render (faster than 1 frame per second) then we'll + // increase the sample distance along the ray to improve performance + if ( vol->GetAllocatedRenderTime() < 1.0 ) + { + this->SampleDistance = this->InteractiveSampleDistance; + } + } + + // Pass the ImageSampleDistance on the RayCastImage + this->RayCastImage->SetImageSampleDistance( this->ImageSampleDistance ); + + // The full image fills the viewport. First, compute the actual viewport + // size, then divide by the ImageSampleDistance to find the full image + // size in pixels + int width, height; + ren->GetTiledSize(&width, &height); + this->RayCastImage->SetImageViewportSize( + static_cast<int>(width/this->ImageSampleDistance), + static_cast<int>(height/this->ImageSampleDistance) ); + + if ( multiRender ) + { + this->UpdateCroppingRegions(); + this->ComputeMatrices( inputOrigin, + inputSpacing, + inputExtent, + ren, vol ); + + if ( !this->ComputeRowBounds( ren, 1, 0, inputExtent ) ) + { + return 0; + } + } + + return 1; +} + +// This is the initialization that should be done once per volume +void vtkFixedPointVolumeRayCastMapper::PerVolumeInitialization( vtkRenderer *ren, vtkVolume *vol ) +{ + // This is the input of this mapper + vtkImageData *input = this->GetInput(); + + // make sure that we have scalar input and update the scalar input + if ( input == NULL ) + { + vtkErrorMacro(<< "No Input!"); + return; + } + else + { + input->UpdateInformation(); + input->SetUpdateExtentToWholeExtent(); + input->Update(); + } + + // Compute some matrices from voxels to view and vice versa based + // on the whole input + double inputSpacing[3]; + double inputOrigin[3]; + int inputExtent[6]; + input->GetSpacing( inputSpacing ); + input->GetOrigin( inputOrigin ); + input->GetExtent( inputExtent ); + + this->ComputeMatrices( inputOrigin, + inputSpacing, + inputExtent, + ren, vol ); + + this->RenderWindow = ren->GetRenderWindow(); + this->Volume = vol; + + this->UpdateColorTable( vol ); + this->UpdateGradients( vol ); + this->UpdateShadingTable( ren, vol ); + this->UpdateMinMaxVolume( vol ); +} + +// This is the initialization that should be done once per subvolume +void vtkFixedPointVolumeRayCastMapper::PerSubVolumeInitialization( vtkRenderer *ren, vtkVolume *vol, int multiRender ) +{ + this->UpdateCroppingRegions(); + + // Compute row bounds. This will also compute the size of the image to + // render, allocate the space if necessary, and clear the image where + // required. If no rays need to be cast, restore the old image sample + // distance and return + int inputExtent[6]; + vtkImageData *input = this->GetInput(); + input->GetExtent( inputExtent ); + + // If this is part of a multirender (AMR volume rendering) then + // the image parameters have already been computed and we can skip + // that. In all cases we need to compute the row bounds so pass in + // a 1 for that flag + int imageFlag = (multiRender)?(0):(1); + if ( !this->ComputeRowBounds( ren, imageFlag, 1, inputExtent ) ) + { + this->AbortRender(); + return; + } + + // If this is part of a multiRender, then we've already captured the z buffer, + // otherwise we need to do it here + if ( !multiRender ) + { + this->CaptureZBuffer( ren ); + } + + this->InitializeRayInfo( vol ); +} + +// This is the render method for the subvolume +void vtkFixedPointVolumeRayCastMapper::RenderSubVolume() +{ + // Set the number of threads to use for ray casting, + // then set the execution method and do it. + this->Threader->SetSingleMethod( FixedPointVolumeRayCastMapper_CastRays, + (void *)this); + this->Threader->SingleMethodExecute(); +} + +// This method displays the image that has been created +void vtkFixedPointVolumeRayCastMapper::DisplayRenderedImage( vtkRenderer *ren, + vtkVolume *vol ) +{ + float depth; + if ( this->IntermixIntersectingGeometry ) + { + depth = this->MinimumViewDistance; + } + else + { + depth = -1; + } + + this->ImageDisplayHelper-> + RenderTexture( vol, ren, + this->RayCastImage, + depth ); +} + +// This method should be called when the render is aborted to restore previous values. +// Otherwise, the old time is still stored, with the newly computed sample distances, +// and that will cause problems on the next render. +void vtkFixedPointVolumeRayCastMapper::AbortRender() +{ + // Restore values + this->ImageSampleDistance = this->OldImageSampleDistance; + this->SampleDistance = this->OldSampleDistance; +} + +// Capture the ZBuffer to use for intermixing with opaque geometry +// that has already been rendered +void vtkFixedPointVolumeRayCastMapper::CaptureZBuffer( vtkRenderer *ren ) +{ + // How big is the viewport in pixels? + double *viewport = ren->GetViewport(); + int *renWinSize = ren->GetRenderWindow()->GetSize(); + + // Do we need to capture the z buffer to intermix intersecting + // geometry? If so, do it here + if ( this->IntermixIntersectingGeometry && + ren->GetNumberOfPropsRendered() ) + { + int x1, x2, y1, y2; + + // turn ImageOrigin into (x1,y1) in window (not viewport!) + // coordinates. + int imageOrigin[2]; + int imageInUseSize[2]; + this->RayCastImage->GetImageOrigin( imageOrigin ); + this->RayCastImage->GetImageInUseSize( imageInUseSize ); + + x1 = static_cast<int> ( + viewport[0] * static_cast<float>(renWinSize[0]) + + static_cast<float>(imageOrigin[0]) * this->ImageSampleDistance ); + y1 = static_cast<int> ( + viewport[1] * static_cast<float>(renWinSize[1]) + + static_cast<float>(imageOrigin[1]) * this->ImageSampleDistance); + + int zbufferSize[2]; + int zbufferOrigin[2]; + + // compute z buffer size + zbufferSize[0] = static_cast<int>( + static_cast<float>(imageInUseSize[0]) * this->ImageSampleDistance); + zbufferSize[1] = static_cast<int>( + static_cast<float>(imageInUseSize[1]) * this->ImageSampleDistance); + + // Use the size to compute (x2,y2) in window coordinates + x2 = x1 + zbufferSize[0] - 1; + y2 = y1 + zbufferSize[1] - 1; + + // This is the z buffer origin (in viewport coordinates) + zbufferOrigin[0] = static_cast<int>( + static_cast<float>(imageOrigin[0]) * this->ImageSampleDistance); + zbufferOrigin[1] = static_cast<int>( + static_cast<float>(imageOrigin[1]) * this->ImageSampleDistance); + + this->RayCastImage->SetZBufferSize( zbufferSize ); + this->RayCastImage->SetZBufferOrigin( zbufferOrigin ); + this->RayCastImage->AllocateZBuffer(); + + // Capture the z buffer + ren->GetRenderWindow()->GetZbufferData( x1, y1, x2, y2, + this->RayCastImage->GetZBuffer() ); + + this->RayCastImage->UseZBufferOn(); + } + else + { + this->RayCastImage->UseZBufferOff(); + } +} + + +void vtkFixedPointVolumeRayCastMapper::Render( vtkRenderer *ren, vtkVolume *vol ) +{ + this->Timer->StartTimer(); + + // Since we are passing in a value of 0 for the multiRender flag + // (this is a single render pass - not part of a multipass AMR render) + // then we know the origin, spacing, and extent values will not + // be used so just initialize everything to 0. No need to check + // the return value of the PerImageInitialization method - since this + // is not a multirender it will always return 1. + double dummyOrigin[3] = {0.0, 0.0, 0.0}; + double dummySpacing[3] = {0.0, 0.0, 0.0}; + int dummyExtent[6] = {0, 0, 0, 0, 0, 0}; + this->PerImageInitialization( ren, vol, 0, + dummyOrigin, + dummySpacing, + dummyExtent ); + + this->PerVolumeInitialization( ren, vol ); + if ( this->RenderWindow->CheckAbortStatus() ) + { + this->AbortRender(); + return; + } + + this->PerSubVolumeInitialization( ren, vol, 0 ); + if ( this->RenderWindow->CheckAbortStatus() ) + { + this->AbortRender(); + return; + } + + this->RenderSubVolume(); + + if ( this->RenderWindow->CheckAbortStatus() ) + { + this->AbortRender(); + return; + } + + this->DisplayRenderedImage( ren, vol ); + + this->Timer->StopTimer(); + this->TimeToDraw = this->Timer->GetElapsedTime(); + // If we've increased the sample distance, account for that in the stored time. Since we + // don't get linear performance improvement, use a factor of .66 + this->StoreRenderTime( ren, vol, + this->TimeToDraw * + this->ImageSampleDistance * + this->ImageSampleDistance * + ( 1.0 + 0.66* + (this->SampleDistance - this->OldSampleDistance) / + this->OldSampleDistance ) ); + + this->SampleDistance = this->OldSampleDistance; +} + +VTK_THREAD_RETURN_TYPE FixedPointVolumeRayCastMapper_CastRays( void *arg ) +{ + // Get the info out of the input structure + int threadID = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + int threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + + vtkFixedPointVolumeRayCastMapper *me = (vtkFixedPointVolumeRayCastMapper *)(((vtkMultiThreader::ThreadInfo *)arg)->UserData); + + if ( !me ) + { + vtkGenericWarningMacro("Irrecoverable error: no mapper specified"); + return VTK_THREAD_RETURN_VALUE; + } + + vtkVolume *vol = me->GetVolume(); + if ( me->GetBlendMode() == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND ) + { + me->GetMIPHelper()->GenerateImage( threadID, threadCount, vol, me ); + } + else + { + if ( me->GetShadingRequired() == 0 ) + { + if ( me->GetGradientOpacityRequired() == 0 ) + { + me->GetCompositeHelper()->GenerateImage( threadID, threadCount, vol, me ); + } + else + { + me->GetCompositeGOHelper()->GenerateImage( threadID, threadCount, vol, me ); + } + } + else + { + if ( me->GetGradientOpacityRequired() == 0 ) + { + me->GetCompositeShadeHelper()->GenerateImage( threadID, threadCount, vol, me ); + } + else + { + me->GetCompositeGOShadeHelper()->GenerateImage( threadID, threadCount, vol, me ); + } + } + } + + return VTK_THREAD_RETURN_VALUE; +} + +void vtkFixedPointVolumeRayCastMapper::ComputeRayInfo( int x, int y, unsigned int pos[3], + unsigned int dir[3], + unsigned int *numSteps ) +{ + float viewRay[3]; + float rayDirection[3]; + float rayStart[4], rayEnd[4]; + + int imageViewportSize[2]; + int imageOrigin[2]; + this->RayCastImage->GetImageViewportSize( imageViewportSize ); + this->RayCastImage->GetImageOrigin( imageOrigin ); + + float offsetX = 1.0 / static_cast<float>(imageViewportSize[0]); + float offsetY = 1.0 / static_cast<float>(imageViewportSize[1]); + + + // compute the view point y value for this row. Do this by + // taking our pixel position, adding the image origin then dividing + // by the full image size to get a number from 0 to 1-1/fullSize. Then, + // multiply by two and subtract one to get a number from + // -1 to 1 - 2/fullSize. Then add offsetX (which is 1/fullSize) to + // center it. + viewRay[1] = ((static_cast<float>(y) + + static_cast<float>(imageOrigin[1])) / + imageViewportSize[1]) * 2.0 - 1.0 + offsetY; + + // compute the view point x value for this pixel. Do this by + // taking our pixel position, adding the image origin then dividing + // by the full image size to get a number from 0 to 1-1/fullSize. Then, + // multiply by two and subtract one to get a number from + // -1 to 1 - 2/fullSize. Then add offsetX (which is 1/fullSize) to + // center it. + viewRay[0] = ((static_cast<float>(x) + + static_cast<float>(imageOrigin[0])) / + imageViewportSize[0]) * 2.0 - 1.0 + offsetX; + + // Now transform this point with a z value of 0 for the ray start, and + // a z value of 1 for the ray end. This corresponds to the near and far + // plane locations. If IntermixIntersectingGeometry is on, then use + // the zbuffer value instead of 1.0 + viewRay[2] = 0.0; + vtkVRCMultiplyPointMacro( viewRay, rayStart, + this->ViewToVoxelsArray ); + + viewRay[2] = this->RayCastImage->GetZBufferValue(x,y); + + vtkVRCMultiplyPointMacro( viewRay, rayEnd, + this->ViewToVoxelsArray ); + + rayDirection[0] = rayEnd[0] - rayStart[0]; + rayDirection[1] = rayEnd[1] - rayStart[1]; + rayDirection[2] = rayEnd[2] - rayStart[2]; + + float originalRayStart[3]; + originalRayStart[0] = rayStart[0]; + originalRayStart[1] = rayStart[1]; + originalRayStart[2] = rayStart[2]; + + + // Initialize with 0, fill in with actual number of steps + // if necessary + *numSteps = 0; + + if ( this->ClipRayAgainstVolume( rayStart, + rayEnd, + rayDirection, + this->CroppingBounds ) && + ( this->NumTransformedClippingPlanes == 0 || + this->ClipRayAgainstClippingPlanes( rayStart, + rayEnd, + this->NumTransformedClippingPlanes, + this->TransformedClippingPlanes ) ) ) + { + double worldRayDirection[3]; + worldRayDirection[0] = rayDirection[0]*this->SavedSpacing[0]; + worldRayDirection[1] = rayDirection[1]*this->SavedSpacing[1]; + worldRayDirection[2] = rayDirection[2]*this->SavedSpacing[2]; + double worldLength = + vtkMath::Normalize( worldRayDirection ) / this->SampleDistance; + + rayDirection[0] /= worldLength; + rayDirection[1] /= worldLength; + rayDirection[2] /= worldLength; + + float diff[3]; + diff[0] = (rayStart[0] - originalRayStart[0])*((rayDirection[0]<0)?(-1):(1)); + diff[1] = (rayStart[1] - originalRayStart[1])*((rayDirection[1]<0)?(-1):(1)); + diff[2] = (rayStart[2] - originalRayStart[2])*((rayDirection[2]<0)?(-1):(1)); + + int steps = -1; + + if ( diff[0] >= diff[1] && diff[0] >= diff[2] && rayDirection[0]) + { + steps = 1 + static_cast<int>( diff[0] / + ((rayDirection[0]<0)?(-rayDirection[0]):(rayDirection[0])) ); + } + + if ( diff[1] >= diff[0] && diff[1] >= diff[2] && rayDirection[2]) + { + steps = 1 + static_cast<int>( diff[1] / + ((rayDirection[1]<0)?(-rayDirection[1]):(rayDirection[1])) ); + } + + if ( diff[2] >= diff[0] && diff[2] >= diff[1] && rayDirection[2]) + { + steps = 1 + static_cast<int>( diff[2] / + ((rayDirection[2]<0)?(-rayDirection[2]):(rayDirection[2])) ); + } + + if ( steps > 0 ) + { + rayStart[0] = originalRayStart[0] + steps*rayDirection[0]; + rayStart[1] = originalRayStart[1] + steps*rayDirection[1]; + rayStart[2] = originalRayStart[2] + steps*rayDirection[2]; + } + + if ( rayStart[0] > 0.0 && rayStart[1] > 0.0 && rayStart[2] > 0.0 ) + { + pos[0] = this->ToFixedPointPosition(rayStart[0]); + pos[1] = this->ToFixedPointPosition(rayStart[1]); + pos[2] = this->ToFixedPointPosition(rayStart[2]); + dir[0] = this->ToFixedPointDirection(rayDirection[0]); + dir[1] = this->ToFixedPointDirection(rayDirection[1]); + dir[2] = this->ToFixedPointDirection(rayDirection[2]); + + int stepLoop; + int stepsValid = 0; + unsigned int currSteps; + for ( stepLoop = 0; stepLoop < 3; stepLoop++ ) + { + if ( !( dir[stepLoop]&0x7fffffff ) ) + { + continue; + } + + unsigned int endVal = this->ToFixedPointPosition(rayEnd[stepLoop]); + + if ( dir[stepLoop]&0x80000000 ) + { + if ( endVal > pos[stepLoop] ) + { + currSteps = static_cast<unsigned int>( + 1 + (endVal - pos[stepLoop])/(dir[stepLoop]&0x7fffffff)); + } + else + { + currSteps = 0; + } + } + else + { + if ( pos[stepLoop] > endVal ) + { + currSteps = 1 + (pos[stepLoop]- endVal)/dir[stepLoop]; + } + else + { + currSteps = 0; + } + } + + if ( !stepsValid || currSteps < *numSteps ) + { + *numSteps = currSteps; + stepsValid = 1; + } + } + } + } +} + +void vtkFixedPointVolumeRayCastMapper::InitializeRayInfo( vtkVolume *vol ) +{ + if ( !vol ) + { + return; + } + + // Copy the viewToVoxels matrix to 16 floats + int i, j; + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + this->ViewToVoxelsArray[j*4+i] = + static_cast<float>(this->ViewToVoxelsMatrix->GetElement(j,i)); + } + } + + // Copy the worldToVoxels matrix to 16 floats + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + this->WorldToVoxelsArray[j*4+i] = + static_cast<float>(this->WorldToVoxelsMatrix->GetElement(j,i)); + } + } + + // Copy the voxelsToWorld matrix to 16 floats + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + this->VoxelsToWorldArray[j*4+i] = + static_cast<float>(this->VoxelsToWorldMatrix->GetElement(j,i)); + } + } + + int dim[3]; + this->GetInput()->GetDimensions(dim); + this->CroppingBounds[0] = this->CroppingBounds[2] = this->CroppingBounds[4] = 0.0; + this->CroppingBounds[1] = dim[0]-1; + this->CroppingBounds[3] = dim[1]-1; + this->CroppingBounds[5] = dim[2]-1; + + + // Do some initialization of the clipping planes + this->NumTransformedClippingPlanes = (this->ClippingPlanes)?(this->ClippingPlanes->GetNumberOfItems()):(0); + + // Clear out old clipping planes + delete [] this->TransformedClippingPlanes; + this->TransformedClippingPlanes = NULL; + + // Do we have any clipping planes + if ( this->NumTransformedClippingPlanes > 0 ) + { + // Allocate some space to store the plane equations + this->TransformedClippingPlanes = new float [4*this->NumTransformedClippingPlanes]; + + // loop through all the clipping planes + for ( i = 0; i < this->NumTransformedClippingPlanes; i++ ) + { + // Convert plane into voxel coordinate system + double worldNormal[3], worldOrigin[3]; + double inputOrigin[4]; + vtkPlane *onePlane = (vtkPlane *)this->ClippingPlanes->GetItemAsObject(i); + onePlane->GetNormal(worldNormal); + onePlane->GetOrigin(worldOrigin); + float *planePtr = this->TransformedClippingPlanes + 4*i; + vtkVRCMultiplyNormalMacro( worldNormal, + planePtr, + this->VoxelsToWorldArray ); + vtkVRCMultiplyPointMacro( worldOrigin, inputOrigin, + this->WorldToVoxelsArray ); + + float t = sqrt( planePtr[0]*planePtr[0] + + planePtr[1]*planePtr[1] + + planePtr[2]*planePtr[2] ); + if ( t ) + { + planePtr[0] /= t; + planePtr[1] /= t; + planePtr[2] /= t; + } + + planePtr[3] = -(planePtr[0]*inputOrigin[0] + + planePtr[1]*inputOrigin[1] + + planePtr[2]*inputOrigin[2]); + } + } + + // If we have a simple crop box then we can tighten the bounds + if ( this->Cropping && this->CroppingRegionFlags == 0x2000 ) + { + this->CroppingBounds[0] = this->VoxelCroppingRegionPlanes[0]; + this->CroppingBounds[1] = this->VoxelCroppingRegionPlanes[1]; + this->CroppingBounds[2] = this->VoxelCroppingRegionPlanes[2]; + this->CroppingBounds[3] = this->VoxelCroppingRegionPlanes[3]; + this->CroppingBounds[4] = this->VoxelCroppingRegionPlanes[4]; + this->CroppingBounds[5] = this->VoxelCroppingRegionPlanes[5]; + } + + this->CroppingBounds[0] = (this->CroppingBounds[0] < 0)?(0):(this->CroppingBounds[0]); + this->CroppingBounds[0] = (this->CroppingBounds[0] > dim[0]-1)?(dim[0]-1):(this->CroppingBounds[0]); + this->CroppingBounds[1] = (this->CroppingBounds[1] < 0)?(0):(this->CroppingBounds[1]); + this->CroppingBounds[1] = (this->CroppingBounds[1] > dim[0]-1)?(dim[0]-1):(this->CroppingBounds[1]); + this->CroppingBounds[2] = (this->CroppingBounds[2] < 0)?(0):(this->CroppingBounds[2]); + this->CroppingBounds[2] = (this->CroppingBounds[2] > dim[1]-1)?(dim[1]-1):(this->CroppingBounds[2]); + this->CroppingBounds[3] = (this->CroppingBounds[3] < 0)?(0):(this->CroppingBounds[3]); + this->CroppingBounds[3] = (this->CroppingBounds[3] > dim[1]-1)?(dim[1]-1):(this->CroppingBounds[3]); + this->CroppingBounds[4] = (this->CroppingBounds[4] < 0)?(0):(this->CroppingBounds[4]); + this->CroppingBounds[4] = (this->CroppingBounds[4] > dim[2]-1)?(dim[2]-1):(this->CroppingBounds[4]); + this->CroppingBounds[5] = (this->CroppingBounds[5] < 0)?(0):(this->CroppingBounds[5]); + this->CroppingBounds[5] = (this->CroppingBounds[5] > dim[2]-1)?(dim[2]-1):(this->CroppingBounds[5]); + + // Save spacing because for some reason this call is really really slow! + this->GetInput()->GetSpacing(this->SavedSpacing); +} + +// Return 0 if our volume is outside the view frustum, 1 if it +// is in the view frustum. +int vtkFixedPointVolumeRayCastMapper::ComputeRowBounds(vtkRenderer *ren, + int imageFlag, + int rowBoundsFlag, + int inputExtent[6] ) +{ + float voxelPoint[3]; + float viewPoint[8][4]; + int i, j, k; + unsigned short *ucptr; + float minX, minY, maxX, maxY, minZ, maxZ; + + minX = 1.0; + minY = 1.0; + maxX = -1.0; + maxY = -1.0; + minZ = 1.0; + maxZ = 0.0; + + float bounds[6]; + int dim[3]; + dim[0] = inputExtent[1] - inputExtent[0] + 1; + dim[1] = inputExtent[3] - inputExtent[2] + 1; + dim[2] = inputExtent[5] - inputExtent[4] + 1; + + + bounds[0] = bounds[2] = bounds[4] = 0.0; + bounds[1] = static_cast<float>(dim[0]-1); + bounds[3] = static_cast<float>(dim[1]-1); + bounds[5] = static_cast<float>(dim[2]-1); + + int insideFlag = 0; + double camPos[4]; + ren->GetActiveCamera()->GetPosition( camPos ); + camPos[3] = 1.0; + this->WorldToVoxelsMatrix->MultiplyPoint( camPos, camPos ); + if ( camPos[3] ) + { + camPos[0] /= camPos[3]; + camPos[1] /= camPos[3]; + camPos[2] /= camPos[3]; + } + + + // If we have a simple crop box then we can tighten the bounds + if ( this->Cropping && this->CroppingRegionFlags == 0x2000 ) + { + bounds[0] = this->VoxelCroppingRegionPlanes[0]; + bounds[1] = this->VoxelCroppingRegionPlanes[1]; + bounds[2] = this->VoxelCroppingRegionPlanes[2]; + bounds[3] = this->VoxelCroppingRegionPlanes[3]; + bounds[4] = this->VoxelCroppingRegionPlanes[4]; + bounds[5] = this->VoxelCroppingRegionPlanes[5]; + } + + + if ( camPos[0] >= bounds[0] && + camPos[0] <= bounds[1] && + camPos[1] >= bounds[2] && + camPos[1] <= bounds[3] && + camPos[2] >= bounds[4] && + camPos[2] <= bounds[5] ) + { + insideFlag = 1; + } + + // Copy the voxelsToView matrix to 16 floats + float voxelsToViewMatrix[16]; + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + voxelsToViewMatrix[j*4+i] = + static_cast<float>(this->VoxelsToViewMatrix->GetElement(j,i)); + } + } + + // Convert the voxel bounds to view coordinates to find out the + // size and location of the image we need to generate. + int idx = 0; + if ( insideFlag ) + { + minX = -1.0; + maxX = 1.0; + minY = -1.0; + maxY = 1.0; + minZ = 0.001; + maxZ = 0.001; + } + else + { + for ( k = 0; k < 2; k++ ) + { + voxelPoint[2] = bounds[4+k]; + for ( j = 0; j < 2; j++ ) + { + voxelPoint[1] = bounds[2+j]; + for ( i = 0; i < 2; i++ ) + { + voxelPoint[0] = bounds[i]; + vtkVRCMultiplyPointMacro( voxelPoint, viewPoint[idx], + voxelsToViewMatrix ); + + minX = (viewPoint[idx][0]<minX)?(viewPoint[idx][0]):(minX); + minY = (viewPoint[idx][1]<minY)?(viewPoint[idx][1]):(minY); + maxX = (viewPoint[idx][0]>maxX)?(viewPoint[idx][0]):(maxX); + maxY = (viewPoint[idx][1]>maxY)?(viewPoint[idx][1]):(maxY); + minZ = (viewPoint[idx][2]<minZ)?(viewPoint[idx][2]):(minZ); + maxZ = (viewPoint[idx][2]>maxZ)?(viewPoint[idx][2]):(maxZ); + idx++; + } + } + } + } + + if ( minZ < 0.001 || maxZ > 0.9999 ) + { + minX = -1.0; + maxX = 1.0; + minY = -1.0; + maxY = 1.0; + insideFlag = 1; + } + + this->MinimumViewDistance = + (minZ<0.001)?(0.001):((minZ>0.999)?(0.999):(minZ)); + + int imageViewportSize[2]; + int imageOrigin[2]; + int imageMemorySize[2]; + int imageInUseSize[2]; + this->RayCastImage->GetImageViewportSize( imageViewportSize ); + this->RayCastImage->GetImageOrigin( imageOrigin ); + this->RayCastImage->GetImageMemorySize( imageMemorySize ); + + // We have min/max values from -1.0 to 1.0 now - we want to convert + // these to pixel locations. Give a couple of pixels of breathing room + // on each side if possible + minX = ( minX + 1.0 ) * 0.5 * imageViewportSize[0] - 2; + minY = ( minY + 1.0 ) * 0.5 * imageViewportSize[1] - 2; + maxX = ( maxX + 1.0 ) * 0.5 * imageViewportSize[0] + 2; + maxY = ( maxY + 1.0 ) * 0.5 * imageViewportSize[1] + 2; + + // If we are outside the view frustum return 0 - there is no need + // to render anything + if ( ( minX < 0 && maxX < 0 ) || + ( minY < 0 && maxY < 0 ) || + ( minX > imageViewportSize[0]-1 && + maxX > imageViewportSize[0]-1 ) || + ( minX > imageViewportSize[0]-1 && + maxX > imageViewportSize[0]-1 ) ) + { + return 0; + } + + int oldImageMemorySize[2]; + oldImageMemorySize[0] = imageMemorySize[0]; + oldImageMemorySize[1] = imageMemorySize[1]; + + // Check the bounds - the volume might project outside of the + // viewing box / frustum so clip it if necessary + minX = (minX<0)?(0):(minX); + minY = (minY<0)?(0):(minY); + maxX = (maxX>imageViewportSize[0]-1)? + (imageViewportSize[0]-1):(maxX); + maxY = (maxY>imageViewportSize[1]-1)? + (imageViewportSize[1]-1):(maxY); + + // Create the new image, and set its size and position + imageInUseSize[0] = static_cast<int>(maxX - minX + 1.0); + imageInUseSize[1] = static_cast<int>(maxY - minY + 1.0); + + // What is a power of 2 size big enough to fit this image? + imageMemorySize[0] = 32; + imageMemorySize[1] = 32; + while ( imageMemorySize[0] < imageInUseSize[0] ) + { + imageMemorySize[0] *= 2; + } + while ( imageMemorySize[1] < imageInUseSize[1] ) + { + imageMemorySize[1] *= 2; + } + + imageOrigin[0] = static_cast<int>(minX); + imageOrigin[1] = static_cast<int>(minY); + + // If the old image size is much too big (more than twice in + // either direction) then set the old width to 0 which will + // cause the image to be recreated + if ( oldImageMemorySize[0] > 4*imageMemorySize[0] || + oldImageMemorySize[1] > 4*imageMemorySize[1] ) + { + oldImageMemorySize[0] = 0; + } + + // If the old image is big enough (but not too big - we handled + // that above) then we'll bump up our required size to the + // previous one. This will keep us from thrashing. + if ( oldImageMemorySize[0] >= imageMemorySize[0] && + oldImageMemorySize[1] >= imageMemorySize[1] ) + { + imageMemorySize[0] = oldImageMemorySize[0]; + imageMemorySize[1] = oldImageMemorySize[1]; + } + + if ( imageFlag ) + { + this->RayCastImage->SetImageOrigin( imageOrigin ); + this->RayCastImage->SetImageMemorySize( imageMemorySize ); + this->RayCastImage->SetImageInUseSize( imageInUseSize ); + + // Do we already have a texture big enough? If not, create a new one and + // clear it. + if ( imageMemorySize[0] > oldImageMemorySize[0] || + imageMemorySize[1] > oldImageMemorySize[1] ) + { + this->RayCastImage->AllocateImage(); + delete [] this->RowBounds; + delete [] this->OldRowBounds; + + this->RayCastImage->ClearImage(); + + if ( rowBoundsFlag ) + { + // Create the row bounds array. This will store the start / stop pixel + // for each row. This helps eleminate work in areas outside the bounding + // hexahedron since a bounding box is not very tight. We keep the old ones + // too to help with only clearing where required + this->RowBounds = new int [2*imageMemorySize[1]]; + this->OldRowBounds = new int [2*imageMemorySize[1]]; + + for ( i = 0; i < imageMemorySize[1]; i++ ) + { + this->RowBounds[i*2] = imageMemorySize[0]; + this->RowBounds[i*2+1] = -1; + this->OldRowBounds[i*2] = imageMemorySize[0]; + this->OldRowBounds[i*2+1] = -1; + } + } + } + } + + if ( !rowBoundsFlag ) + { + return 1; + } + + + // Swap the row bounds + int *tmpptr; + tmpptr = this->RowBounds; + this->RowBounds = this->OldRowBounds; + this->OldRowBounds = tmpptr; + + // If we are inside the volume our row bounds indicate every ray must be + // cast - we don't need to intersect with the 12 lines + if ( insideFlag ) + { + for ( j = 0; j < imageInUseSize[1]; j++ ) + { + this->RowBounds[j*2] = 0; + this->RowBounds[j*2+1] = imageInUseSize[0] - 1; + } + } + else + { + // create an array of lines where the y value of the first vertex is less + // than or equal to the y value of the second vertex. There are 12 lines, + // each containing x1, y1, x2, y2 values. + float lines[12][4]; + float x1, y1, x2, y2; + int xlow, xhigh; + int lineIndex[12][2] = {{0,1}, {2,3}, {4,5}, {6,7}, + {0,2}, {1,3} ,{4,6}, {5,7}, + {0,4}, {1,5}, {2,6}, {3,7}}; + + for ( i = 0; i < 12; i++ ) + { + x1 = (viewPoint[lineIndex[i][0]][0]+1.0) * + 0.5*imageViewportSize[0] - imageOrigin[0]; + + y1 = (viewPoint[lineIndex[i][0]][1]+1.0) * + 0.5*imageViewportSize[1] - imageOrigin[1]; + + x2 = (viewPoint[lineIndex[i][1]][0]+1.0) * + 0.5*imageViewportSize[0] - imageOrigin[0]; + + y2 = (viewPoint[lineIndex[i][1]][1]+1.0) * + 0.5*imageViewportSize[1] - imageOrigin[1]; + + if ( y1 < y2 ) + { + lines[i][0] = x1; + lines[i][1] = y1; + lines[i][2] = x2; + lines[i][3] = y2; + } + else + { + lines[i][0] = x2; + lines[i][1] = y2; + lines[i][2] = x1; + lines[i][3] = y1; + } + } + + // Now for each row in the image, find out the start / stop pixel + // If min > max, then no intersection occurred + for ( j = 0; j < imageInUseSize[1]; j++ ) + { + this->RowBounds[j*2] = imageMemorySize[0]; + this->RowBounds[j*2+1] = -1; + for ( i = 0; i < 12; i++ ) + { + if ( j >= lines[i][1] && j <= lines[i][3] && + ( lines[i][1] != lines[i][3] ) ) + { + x1 = lines[i][0] + + (static_cast<float>(j) - lines[i][1])/(lines[i][3] - lines[i][1]) * + (lines[i][2] - lines[i][0] ); + + xlow = static_cast<int>(x1 + 1.5); + xhigh = static_cast<int>(x1 - 1.0); + + xlow = (xlow<0)?(0):(xlow); + xlow = (xlow>imageInUseSize[0]-1)? + (imageInUseSize[0]-1):(xlow); + + xhigh = (xhigh<0)?(0):(xhigh); + xhigh = (xhigh>imageInUseSize[0]-1)?( + imageInUseSize[0]-1):(xhigh); + + if ( xlow < this->RowBounds[j*2] ) + { + this->RowBounds[j*2] = xlow; + } + if ( xhigh > this->RowBounds[j*2+1] ) + { + this->RowBounds[j*2+1] = xhigh; + } + } + } + // If they are the same this is either a point on the cube or + // all lines were out of bounds (all on one side or the other) + // It is safe to ignore the point (since the ray isn't likely + // to travel through it enough to actually take a sample) and it + // must be ignored in the case where all lines are out of range + if ( this->RowBounds[j*2] == this->RowBounds[j*2+1] ) + { + this->RowBounds[j*2] = imageMemorySize[0]; + this->RowBounds[j*2+1] = -1; + } + } + } + + for ( j = imageInUseSize[1]; j < imageMemorySize[1]; j++ ) + { + this->RowBounds[j*2] = imageMemorySize[0]; + this->RowBounds[j*2+1] = -1; + } + + unsigned short *image = this->RayCastImage->GetImage(); + + for ( j = 0; j < imageMemorySize[1]; j++ ) + { + if ( j%64 == 1 && this->RenderWindow->CheckAbortStatus() ) + { + return 0; + } + + // New bounds are not overlapping with old bounds - clear between + // old bounds only + if ( this->RowBounds[j*2+1] < this->OldRowBounds[j*2] || + this->RowBounds[j*2] > this->OldRowBounds[j*2+1] ) + { + ucptr = image + 4*( j*imageMemorySize[0] + + this->OldRowBounds[j*2] ); + for ( i = 0; + i <= (this->OldRowBounds[j*2+1] - this->OldRowBounds[j*2]); + i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + } + // New bounds do overlap with old bounds + else + { + // Clear from old min to new min + ucptr = image + 4*( j*imageMemorySize[0] + + this->OldRowBounds[j*2] ); + for ( i = 0; + i < (this->RowBounds[j*2] - this->OldRowBounds[j*2]); + i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + + // Clear from new max to old max + ucptr = image + 4*( j*imageMemorySize[0] + + this->RowBounds[j*2+1]+1 ); + for ( i = 0; + i < (this->OldRowBounds[j*2+1] - this->RowBounds[j*2+1]); + i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + + } + } + + return 1; +} + + +void vtkFixedPointVolumeRayCastMapper::ComputeMatrices( double inputOrigin[3], + double inputSpacing[3], + int inputExtent[6], + vtkRenderer *ren, + vtkVolume *vol ) +{ + // Get the camera from the renderer + vtkCamera *cam = ren->GetActiveCamera(); + + // Get the aspect ratio from the renderer. This is needed for the + // computation of the perspective matrix + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + // Keep track of the projection matrix - we'll need it in a couple of places + // Get the projection matrix. The method is called perspective, but + // the matrix is valid for perspective and parallel viewing transforms. + // Don't replace this with the GetCompositePerspectiveTransformMatrix + // because that turns off stereo rendering!!! + this->PerspectiveTransform->Identity(); + this->PerspectiveTransform-> + Concatenate(cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], + 0.0, 1.0 )); + this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix()); + + + // Compute the origin of the extent the volume origin is at voxel (0,0,0) + // but we want to consider (0,0,0) in voxels to be at + // (inputExtent[0], inputExtent[2], inputExtent[4]). + double extentOrigin[3]; + extentOrigin[0] = inputOrigin[0] + inputExtent[0]*inputSpacing[0]; + extentOrigin[1] = inputOrigin[1] + inputExtent[2]*inputSpacing[1]; + extentOrigin[2] = inputOrigin[2] + inputExtent[4]*inputSpacing[2]; + + // Get the volume matrix. This is a volume to world matrix right now. + // We'll need to invert it, translate by the origin and scale by the + // spacing to change it to a world to voxels matrix. + this->VolumeMatrix->DeepCopy( vol->GetMatrix() ); + + this->VoxelsToViewTransform->SetMatrix( this->VolumeMatrix ); + + // Create a transform that will account for the scaling and translation of + // the scalar data. The is the volume to voxels matrix. + this->VoxelsTransform->Identity(); + this->VoxelsTransform->Translate(extentOrigin[0], + extentOrigin[1], + extentOrigin[2] ); + + this->VoxelsTransform->Scale( inputSpacing[0], + inputSpacing[1], + inputSpacing[2] ); + + // Now concatenate the volume's matrix with this scalar data matrix + this->VoxelsToViewTransform->PreMultiply(); + this->VoxelsToViewTransform->Concatenate( this->VoxelsTransform->GetMatrix() ); + + // Now we actually have the world to voxels matrix - copy it out + this->WorldToVoxelsMatrix->DeepCopy( this->VoxelsToViewTransform->GetMatrix() ); + this->WorldToVoxelsMatrix->Invert(); + + // We also want to invert this to get voxels to world + this->VoxelsToWorldMatrix->DeepCopy( this->VoxelsToViewTransform->GetMatrix() ); + + // Compute the voxels to view transform by concatenating the + // voxels to world matrix with the projection matrix (world to view) + this->VoxelsToViewTransform->PostMultiply(); + this->VoxelsToViewTransform->Concatenate( this->PerspectiveMatrix ); + + this->VoxelsToViewMatrix->DeepCopy( this->VoxelsToViewTransform->GetMatrix() ); + + this->ViewToVoxelsMatrix->DeepCopy( this->VoxelsToViewMatrix ); + this->ViewToVoxelsMatrix->Invert(); +} + +int vtkFixedPointVolumeRayCastMapper::ClipRayAgainstClippingPlanes( float rayStart[3], + float rayEnd[3], + int numClippingPlanes, + float *clippingPlanes ) +{ + + float *planePtr; + int i; + float t, point[3], dp; + float rayDir[3]; + + rayDir[0] = rayEnd[0] - rayStart[0]; + rayDir[1] = rayEnd[1] - rayStart[1]; + rayDir[2] = rayEnd[2] - rayStart[2]; + + // loop through all the clipping planes + for ( i = 0; i < numClippingPlanes; i++ ) + { + planePtr = clippingPlanes + 4*i; + + dp = + planePtr[0]*rayDir[0] + + planePtr[1]*rayDir[1] + + planePtr[2]*rayDir[2]; + + if ( dp != 0.0 ) + { + t = + -( planePtr[0]*rayStart[0] + + planePtr[1]*rayStart[1] + + planePtr[2]*rayStart[2] + planePtr[3]) / dp; + + if ( t > 0.0 && t < 1.0 ) + { + point[0] = rayStart[0] + t*rayDir[0]; + point[1] = rayStart[1] + t*rayDir[1]; + point[2] = rayStart[2] + t*rayDir[2]; + + if ( dp > 0.0 ) + { + rayStart[0] = point[0]; + rayStart[1] = point[1]; + rayStart[2] = point[2]; + } + else + { + rayEnd[0] = point[0]; + rayEnd[1] = point[1]; + rayEnd[2] = point[2]; + } + + rayDir[0] = rayEnd[0] - rayStart[0]; + rayDir[1] = rayEnd[1] - rayStart[1]; + rayDir[2] = rayEnd[2] - rayStart[2]; + + } + // If the clipping plane is outside the ray segment, then + // figure out if that means the ray segment goes to zero (if so + // return 0) or doesn't affect it (if so do nothing) + else + { + if ( dp >= 0.0 && t >= 1.0 ) + { + return 0; + } + if ( dp <= 0.0 && t <= 0.0 ) + { + return 0; + } + } + } + } + + return 1; +} + + +int vtkFixedPointVolumeRayCastMapper::ClipRayAgainstVolume( float rayStart[3], + float rayEnd[3], + float rayDirection[3], + double bounds[6] ) +{ + int loop; + float diff; + float t; + + if ( rayStart[0] >= bounds[1] || + rayStart[1] >= bounds[3] || + rayStart[2] >= bounds[5] || + rayStart[0] < bounds[0] || + rayStart[1] < bounds[2] || + rayStart[2] < bounds[4] ) + { + for ( loop = 0; loop < 3; loop++ ) + { + diff = 0; + + if ( rayStart[loop] < (bounds[2*loop]+0.01) ) + { + diff = (bounds[2*loop]+0.01) - rayStart[loop]; + } + else if ( rayStart[loop] > (bounds[2*loop+1]-0.01) ) + { + diff = (bounds[2*loop+1]-0.01) - rayStart[loop]; + } + + if ( diff ) + { + if ( rayDirection[loop] != 0.0 ) + { + t = diff / rayDirection[loop]; + } + else + { + t = -1.0; + } + + if ( t > 0.0 ) + { + rayStart[0] += rayDirection[0] * t; + rayStart[1] += rayDirection[1] * t; + rayStart[2] += rayDirection[2] * t; + } + } + } + } + + // If the voxel still isn't inside the volume, then this ray + // doesn't really intersect the volume + + if ( rayStart[0] >= bounds[1] || + rayStart[1] >= bounds[3] || + rayStart[2] >= bounds[5] || + rayStart[0] < bounds[0] || + rayStart[1] < bounds[2] || + rayStart[2] < bounds[4] ) + { + return 0; + } + + // The ray does intersect the volume, and we have a starting + // position that is inside the volume + if ( rayEnd[0] >= bounds[1] || + rayEnd[1] >= bounds[3] || + rayEnd[2] >= bounds[5] || + rayEnd[0] < bounds[0] || + rayEnd[1] < bounds[2] || + rayEnd[2] < bounds[4] ) + { + for ( loop = 0; loop < 3; loop++ ) + { + diff = 0; + + if ( rayEnd[loop] < (bounds[2*loop]+0.01) ) + { + diff = (bounds[2*loop]+0.01) - rayEnd[loop]; + } + else if ( rayEnd[loop] > (bounds[2*loop+1]-0.01) ) + { + diff = (bounds[2*loop+1]-0.01) - rayEnd[loop]; + } + + if ( diff ) + { + if ( rayDirection[loop] != 0.0 ) + { + t = diff / rayDirection[loop]; + } + else + { + t = 1.0; + } + + if ( t < 0.0 ) + { + rayEnd[0] += rayDirection[0] * t; + rayEnd[1] += rayDirection[1] * t; + rayEnd[2] += rayDirection[2] * t; + } + } + } + } + + // To be absolutely certain our ray remains inside the volume, + // recompute the ray direction (since it has changed - it is not + // normalized and therefore changes when start/end change) and move + // the start/end points in by 1/1000th of the distance. + float offset; + offset = (rayEnd[0] - rayStart[0])*0.001; + rayStart[0] += offset; + rayEnd[0] -= offset; + + offset = (rayEnd[1] - rayStart[1])*0.001; + rayStart[1] += offset; + rayEnd[1] -= offset; + + offset = (rayEnd[2] - rayStart[2])*0.001; + rayStart[2] += offset; + rayEnd[2] -= offset; + + if ( rayEnd[0] >= bounds[1] || + rayEnd[1] >= bounds[3] || + rayEnd[2] >= bounds[5] || + rayEnd[0] < bounds[0] || + rayEnd[1] < bounds[2] || + rayEnd[2] < bounds[4] ) + { + return 0; + } + + if ( (rayEnd[0]-rayStart[0])*rayDirection[0] < 0.0 || + (rayEnd[1]-rayStart[1])*rayDirection[1] < 0.0 || + (rayEnd[2]-rayStart[2])*rayDirection[2] < 0.0 ) + { + return 0; + } + + return 1; +} + + +void vtkFixedPointVolumeRayCastMapper::ComputeGradients( vtkVolume *vol ) +{ + vtkImageData *input = this->GetInput(); + + void *dataPtr = input->GetScalarPointer(); + + int scalarType = input->GetScalarType(); + int components = input->GetPointData()->GetScalars()->GetNumberOfComponents(); + int independent = vol->GetProperty()->GetIndependentComponents(); + + int dim[3]; + double spacing[3]; + input->GetDimensions(dim); + input->GetSpacing(spacing); + + // Find the scalar range + double scalarRange[4][2]; + int c; + for ( c = 0; c < components; c++ ) + { + input->GetPointData()->GetScalars()->GetRange(scalarRange[c], c); + } + + int sliceSize = dim[0]*dim[1]*((independent)?(components):(1)); + int numSlices = dim[2]; + + int i; + + // Delete the prior gradient normal information + if ( this->GradientNormal ) + { + // Contiguous? Delete in one chunk otherwise delete slice by slice + if ( this->ContiguousGradientNormal ) + { + delete [] this->ContiguousGradientNormal; + this->ContiguousGradientNormal = NULL; + } + else + { + for ( i = 0; i < this->NumberOfGradientSlices; i++ ) + { + delete [] this->GradientNormal[i]; + } + } + delete [] this->GradientNormal; + this->GradientNormal = NULL; + } + + // Delete the prior gradient magnitude information + if ( this->GradientMagnitude ) + { + // Contiguous? Delete in one chunk otherwise delete slice by slice + if ( this->ContiguousGradientMagnitude ) + { + delete [] this->ContiguousGradientMagnitude; + this->ContiguousGradientMagnitude = NULL; + } + else + { + for ( i = 0; i < this->NumberOfGradientSlices; i++ ) + { + delete [] this->GradientMagnitude[i]; + } + } + delete [] this->GradientMagnitude; + this->GradientMagnitude = NULL; + } + + this->NumberOfGradientSlices = numSlices; + this->GradientNormal = new unsigned short *[numSlices]; + this->GradientMagnitude = new unsigned char *[numSlices]; + + // first, attempt contiguous memory. If this fails, then go + // for non-contiguous + this->ContiguousGradientNormal = new unsigned short [numSlices * sliceSize]; + this->ContiguousGradientMagnitude = new unsigned char [numSlices * sliceSize]; + + if ( this->ContiguousGradientNormal ) + { + // We were able to allocate contiguous space - we just need to set the + // slice pointers here + for ( i = 0; i < numSlices; i++ ) + { + this->GradientNormal[i] = this->ContiguousGradientNormal + i*sliceSize; + } + } + else + { + // We were not able to allocate contigous space - allocate it slice by slice + for ( i = 0; i < numSlices; i++ ) + { + this->GradientNormal[i] = new unsigned short [sliceSize]; + } + } + + if ( this->ContiguousGradientMagnitude ) + { + // We were able to allocate contiguous space - we just need to set the + // slice pointers here + for ( i = 0; i < numSlices; i++ ) + { + this->GradientMagnitude[i] = this->ContiguousGradientMagnitude + i*sliceSize; + } + } + else + { + // We were not able to allocate contigous space - allocate it slice by slice + for ( i = 0; i < numSlices; i++ ) + { + this->GradientMagnitude[i] = new unsigned char [sliceSize]; + } + } + + + + switch ( scalarType ) + { + vtkTemplateMacro( + vtkFixedPointVolumeRayCastMapperComputeGradients( + (VTK_TT *)(dataPtr), dim, spacing, components, + independent, scalarRange, + this->GradientNormal, + this->GradientMagnitude, + this->DirectionEncoder, + this) ); + } +} + +int vtkFixedPointVolumeRayCastMapper::UpdateShadingTable( vtkRenderer *ren, + vtkVolume *vol ) +{ + if ( this->ShadingRequired == 0 ) + { + return 0; + } + + // How many components? + int components = this->GetInput()->GetPointData()->GetScalars()->GetNumberOfComponents(); + + int c; + for ( c = 0; c < ((vol->GetProperty()->GetIndependentComponents())?(components):(1)); c++ ) + { + this->GradientShader->SetActiveComponent( c ); + this->GradientShader->UpdateShadingTable( ren, vol, this->GradientEstimator ); + + float *r = this->GradientShader->GetRedDiffuseShadingTable(vol); + float *g = this->GradientShader->GetGreenDiffuseShadingTable(vol); + float *b = this->GradientShader->GetBlueDiffuseShadingTable(vol); + + float *rptr = r; + float *gptr = g; + float *bptr = b; + + unsigned short *tablePtr = this->DiffuseShadingTable[c]; + + int i; + for ( i = 0; i < this->DirectionEncoder->GetNumberOfEncodedDirections(); i++ ) + { + *(tablePtr++) = static_cast<unsigned short>((*(rptr++))*VTKKW_FP_SCALE + 0.5); + *(tablePtr++) = static_cast<unsigned short>((*(gptr++))*VTKKW_FP_SCALE + 0.5); + *(tablePtr++) = static_cast<unsigned short>((*(bptr++))*VTKKW_FP_SCALE + 0.5); + } + + r = this->GradientShader->GetRedSpecularShadingTable(vol); + g = this->GradientShader->GetGreenSpecularShadingTable(vol); + b = this->GradientShader->GetBlueSpecularShadingTable(vol); + + rptr = r; + gptr = g; + bptr = b; + + tablePtr = this->SpecularShadingTable[c]; + + + for ( i = 0; i < this->DirectionEncoder->GetNumberOfEncodedDirections(); i++ ) + { + *(tablePtr++) = static_cast<unsigned short>((*(rptr++))*VTKKW_FP_SCALE + 0.5); + *(tablePtr++) = static_cast<unsigned short>((*(gptr++))*VTKKW_FP_SCALE + 0.5); + *(tablePtr++) = static_cast<unsigned short>((*(bptr++))*VTKKW_FP_SCALE + 0.5); + } + } + + return 1; +} + +int vtkFixedPointVolumeRayCastMapper::UpdateGradients( vtkVolume *vol ) +{ + int needToUpdate = 0; + + this->GradientOpacityRequired = 0; + this->ShadingRequired = 0; + + // Get the image data + vtkImageData *input = this->GetInput(); + + if ( vol->GetProperty()->GetShade() ) + { + needToUpdate = 1; + this->ShadingRequired = 1; + } + + for ( int c = 0; c < input->GetPointData()->GetScalars()->GetNumberOfComponents(); c++ ) + { + vtkPiecewiseFunction *f = vol->GetProperty()->GetGradientOpacity(c); + if ( strcmp(f->GetType(), "Constant") || f->GetValue(0.0) != 1.0 ) + { + needToUpdate = 1; + this->GradientOpacityRequired = 1; + } + } + + if ( !needToUpdate ) + { + return 0; + } + + // Check if the input has changed + if ( input == this->SavedGradientsInput && + input->GetMTime() < this->SavedGradientsMTime.GetMTime() ) + { + return 0; + } + + this->ComputeGradients( vol ); + + // Time to save the input used to update the tabes + this->SavedGradientsInput = this->GetInput(); + this->SavedGradientsMTime.Modified(); + + return 1; +} + +int vtkFixedPointVolumeRayCastMapper::UpdateColorTable( vtkVolume *vol ) +{ + int needToUpdate = 0; + + // Get the image data + vtkImageData *input = this->GetInput(); + + // Has the data itself changed? + if ( input != this->SavedParametersInput || + input->GetMTime() > this->SavedParametersMTime.GetMTime() ) + { + needToUpdate = 1; + } + + // What is the blending mode? + int blendMode = this->GetBlendMode(); + if ( blendMode != this->SavedBlendMode ) + { + needToUpdate = 1; + } + + // How many components? + int components = input->GetPointData()->GetScalars()->GetNumberOfComponents(); + + // Has the sample distance changed? + if ( this->SavedSampleDistance != this->SampleDistance ) + { + needToUpdate = 1; + } + + vtkColorTransferFunction *rgbFunc[4]; + vtkPiecewiseFunction *grayFunc[4]; + vtkPiecewiseFunction *scalarOpacityFunc[4]; + vtkPiecewiseFunction *gradientOpacityFunc[4]; + int colorChannels[4]; + float scalarOpacityDistance[4]; + + int c; + + for ( c = 0; c < ((vol->GetProperty()->GetIndependentComponents())?(components):(1)); c++ ) + { + colorChannels[c] = vol->GetProperty()->GetColorChannels(c); + if ( colorChannels[c] == 1 ) + { + rgbFunc[c] = NULL; + grayFunc[c] = vol->GetProperty()->GetGrayTransferFunction(c); + } + else + { + rgbFunc[c] = vol->GetProperty()->GetRGBTransferFunction(c); + grayFunc[c] = NULL; + } + scalarOpacityFunc[c] = vol->GetProperty()->GetScalarOpacity(c); + gradientOpacityFunc[c] = vol->GetProperty()->GetGradientOpacity(c); + scalarOpacityDistance[c] = vol->GetProperty()->GetScalarOpacityUnitDistance(c); + + // Has the number of color channels changed? + if ( this->SavedColorChannels[c] != colorChannels[c] ) + { + needToUpdate = 1; + } + + // Has the color transfer function changed in some way, + // and we are using it? + if ( colorChannels[c] == 3 ) + { + if ( this->SavedRGBFunction[c] != rgbFunc[c] || + this->SavedParametersMTime.GetMTime() < rgbFunc[c]->GetMTime() ) + { + needToUpdate = 1; + } + } + + // Has the gray transfer function changed in some way, + // and we are using it? + if ( colorChannels[c] == 1 ) + { + if ( this->SavedGrayFunction[c] != grayFunc[c] || + this->SavedParametersMTime.GetMTime() < grayFunc[c]->GetMTime() ) + { + needToUpdate = 1; + } + } + + // Has the scalar opacity transfer function changed in some way? + if ( this->SavedScalarOpacityFunction[c] != scalarOpacityFunc[c] || + this->SavedParametersMTime.GetMTime() < scalarOpacityFunc[c]->GetMTime() ) + { + needToUpdate = 1; + } + + // Has the gradient opacity transfer function changed in some way? + if ( this->SavedGradientOpacityFunction[c] != gradientOpacityFunc[c] || + this->SavedParametersMTime.GetMTime() < gradientOpacityFunc[c]->GetMTime() ) + { + needToUpdate = 1; + } + + // Has the distance over which the scalar opacity function is defined changed? + if ( this->SavedScalarOpacityDistance[c] != scalarOpacityDistance[c] ) + { + needToUpdate = 1; + } + } + + // If we have not found any need to update, return now + if ( !needToUpdate ) + { + return 0; + } + + + for ( c = 0; c < ((vol->GetProperty()->GetIndependentComponents())?(components):(1)); c++ ) + { + this->SavedRGBFunction[c] = rgbFunc[c]; + this->SavedGrayFunction[c] = grayFunc[c]; + this->SavedScalarOpacityFunction[c] = scalarOpacityFunc[c]; + this->SavedGradientOpacityFunction[c] = gradientOpacityFunc[c]; + this->SavedColorChannels[c] = colorChannels[c]; + this->SavedScalarOpacityDistance[c] = scalarOpacityDistance[c]; + } + + this->SavedSampleDistance = this->SampleDistance; + this->SavedBlendMode = blendMode; + this->SavedParametersInput = input; + + this->SavedParametersMTime.Modified(); + + int scalarType = input->GetScalarType(); + + int i; + float tmpArray[3*32768]; + + // Find the scalar range + double scalarRange[4][2]; + for ( c = 0; c < components; c++ ) + { + input->GetPointData()->GetScalars()->GetRange(scalarRange[c], c); + + // Is the difference between max and min less than 32768? If so, and if + // the data is not of float or double type, use a simple offset mapping. + // If the difference between max and min is 32768 or greater, or the data + // is of type float or double, we must use an offset / scaling mapping. + // In this case, the array size will be 32768 - we need to figure out the + // offset and scale factor. + float offset; + float scale; + + int arraySizeNeeded; + + if ( scalarType == VTK_FLOAT || + scalarType == VTK_DOUBLE || + scalarRange[c][1] - scalarRange[c][0] > 32767 ) + { + arraySizeNeeded = 32768; + offset = -scalarRange[c][0]; + + if ( scalarRange[c][1] - scalarRange[c][0] ) + { + scale = 32767.0 / (scalarRange[c][1] - scalarRange[c][0]); + } + else + { + scale = 1.0; + } + } + else + { + arraySizeNeeded = (int)(scalarRange[c][1] - scalarRange[c][0] + 1); + offset = -scalarRange[c][0]; + scale = 1.0; + } + + this->TableSize[c] = arraySizeNeeded; + this->TableShift[c] = offset; + this->TableScale[c] = scale; + } + + if ( vol->GetProperty()->GetIndependentComponents() ) + { + for ( c = 0; c < components; c++ ) + { + // Sample the transfer functions between the min and max. + if ( colorChannels[c] == 1 ) + { + float tmpArray2[32768]; + grayFunc[c]->GetTable( scalarRange[c][0], scalarRange[c][1], + this->TableSize[c], tmpArray2 ); + for ( int index = 0; index < this->TableSize[c]; index++ ) + { + tmpArray[3*index ] = tmpArray2[index]; + tmpArray[3*index+1] = tmpArray2[index]; + tmpArray[3*index+2] = tmpArray2[index]; + } + } + else + { + rgbFunc[c]->GetTable( scalarRange[c][0], scalarRange[c][1], + this->TableSize[c], tmpArray ); + } + // Convert color to short format + for ( i = 0; i < this->TableSize[c]; i++ ) + { + this->ColorTable[c][3*i ] = + static_cast<unsigned short>(tmpArray[3*i ]*VTKKW_FP_SCALE + 0.5); + this->ColorTable[c][3*i+1] = + static_cast<unsigned short>(tmpArray[3*i+1]*VTKKW_FP_SCALE + 0.5); + this->ColorTable[c][3*i+2] = + static_cast<unsigned short>(tmpArray[3*i+2]*VTKKW_FP_SCALE + 0.5); + } + + scalarOpacityFunc[c]->GetTable( scalarRange[c][0], scalarRange[c][1], + this->TableSize[c], tmpArray ); + + // Correct the opacity array for the spacing between the planes if we are + // using a composite blending operation + if ( this->BlendMode == vtkVolumeMapper::COMPOSITE_BLEND ) + { + float *ptr = tmpArray; + double factor = this->SampleDistance / vol->GetProperty()->GetScalarOpacityUnitDistance(c); + for ( i = 0; i < this->TableSize[c]; i++ ) + { + if ( *ptr > 0.0001 ) + { + *ptr = 1.0-pow((double)(1.0-(*ptr)),factor); + } + ptr++; + } + } + + // Convert tables to short format + for ( i = 0; i < this->TableSize[c]; i++ ) + { + this->ScalarOpacityTable[c][i] = + static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5); + } + + if ( scalarRange[c][1] - scalarRange[c][0] ) + { + gradientOpacityFunc[c]->GetTable( 0, + (scalarRange[c][1] - scalarRange[c][0])*0.25, + 256, tmpArray ); + + for ( i = 0; i < 256; i++ ) + { + this->GradientOpacityTable[c][i] = + static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5); + } + } + else + { + for ( i = 0; i < 256; i++ ) + { + this->GradientOpacityTable[c][i] = 0x0000; + } + } + } + } + else + { + if ( components == 2 ) + { + // Sample the transfer functions between the min and max. + if ( colorChannels[0] == 1 ) + { + float tmpArray2[32768]; + grayFunc[0]->GetTable( scalarRange[0][0], scalarRange[0][1], + this->TableSize[0], tmpArray2 ); + for ( int index = 0; index < this->TableSize[0]; index++ ) + { + tmpArray[3*index ] = tmpArray2[index]; + tmpArray[3*index+1] = tmpArray2[index]; + tmpArray[3*index+2] = tmpArray2[index]; + } + } + else + { + rgbFunc[0]->GetTable( scalarRange[0][0], scalarRange[0][1], + this->TableSize[0], tmpArray ); + } + + // Convert color to short format + for ( i = 0; i < this->TableSize[0]; i++ ) + { + this->ColorTable[0][3*i ] = + static_cast<unsigned short>(tmpArray[3*i ]*VTKKW_FP_SCALE + 0.5); + this->ColorTable[0][3*i+1] = + static_cast<unsigned short>(tmpArray[3*i+1]*VTKKW_FP_SCALE + 0.5); + this->ColorTable[0][3*i+2] = + static_cast<unsigned short>(tmpArray[3*i+2]*VTKKW_FP_SCALE + 0.5); + } + } + + // The opacity table is indexed with the last component + scalarOpacityFunc[0]->GetTable( scalarRange[components-1][0], scalarRange[components-1][1], + this->TableSize[components-1], tmpArray ); + + // Correct the opacity array for the spacing between the planes if we are + // using a composite blending operation + if ( this->BlendMode == vtkVolumeMapper::COMPOSITE_BLEND ) + { + float *ptr = tmpArray; + double factor = + this->SampleDistance / vol->GetProperty()->GetScalarOpacityUnitDistance(); + for ( i = 0; i < this->TableSize[components-1]; i++ ) + { + if ( *ptr > 0.0001 ) + { + *ptr = 1.0-pow((double)(1.0-(*ptr)),factor); + } + ptr++; + } + } + + // Convert tables to short format + for ( i = 0; i < this->TableSize[components-1]; i++ ) + { + this->ScalarOpacityTable[0][i] = + static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5); + } + + if ( scalarRange[components-1][1] - scalarRange[components-1][0] ) + { + gradientOpacityFunc[0]->GetTable( 0, + (scalarRange[components-1][1] - + scalarRange[components-1][0])*0.25, + 256, tmpArray ); + + for ( i = 0; i < 256; i++ ) + { + this->GradientOpacityTable[0][i] = + static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5); + } + } + else + { + for ( i = 0; i < 256; i++ ) + { + this->GradientOpacityTable[0][i] = 0x0000; + } + } + } + + return 1; +} + + +int vtkFixedPointVolumeRayCastMapper::ShouldUseNearestNeighborInterpolation( vtkVolume *vol ) +{ +// return ( this->UseShortCuts || +// vol->GetProperty()->GetInterpolationType() == VTK_NEAREST_INTERPOLATION ); + return ( vol->GetProperty()->GetInterpolationType() == VTK_NEAREST_INTERPOLATION ); +} + +// Print method for vtkFixedPointVolumeRayCastMapper +void vtkFixedPointVolumeRayCastMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Sample Distance: " << this->SampleDistance << endl; + os << indent << "Interactive Sample Distance: " + << this->InteractiveSampleDistance << endl; + os << indent << "Image Sample Distance: " + << this->ImageSampleDistance << endl; + os << indent << "Minimum Image Sample Distance: " + << this->MinimumImageSampleDistance << endl; + os << indent << "Maximum Image Sample Distance: " + << this->MaximumImageSampleDistance << endl; + os << indent << "Auto Adjust Sample Distances: " + << this->AutoAdjustSampleDistances << endl; + os << indent << "Intermix Intersecting Geometry: " + << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n"); + + os << indent << "ShadingRequired: " << this->ShadingRequired << endl; + os << indent << "GradientOpacityRequired: " << this->GradientOpacityRequired + << endl; + + if ( this->RayCastImage ) + { + os << indent << "Ray Cast Image:\n"; + this->RayCastImage->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Ray Cast Image: (none)\n"; + } + + os << indent << "RenderWindow: " << this->RenderWindow << endl; + + os << indent << "CompositeHelper: " << this->CompositeHelper << endl; + os << indent << "CompositeShadeHelper: " << this->CompositeShadeHelper + << endl; + os << indent << "CompositeGOHelper: " << this->CompositeGOHelper << endl; + os << indent << "CompositeGOShadeHelper: " << this->CompositeGOShadeHelper + << endl; + os << indent << "MIPHelper: " << this->MIPHelper << endl; + + os << indent << "TableShift: " << this->TableShift[0] << " " + << this->TableShift[1] << " " << this->TableShift[2] << " " + << this->TableShift[3] << endl; + os << indent << "TableScale: " << this->TableScale[0] << " " + << this->TableScale[1] << " " << this->TableScale[2] << " " + << this->TableScale[3] << endl; +} diff --git a/VolumeRendering/vtkFixedPointVolumeRayCastMapper.h b/VolumeRendering/vtkFixedPointVolumeRayCastMapper.h new file mode 100644 index 0000000..1fcb8d4 --- /dev/null +++ b/VolumeRendering/vtkFixedPointVolumeRayCastMapper.h @@ -0,0 +1,664 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkFixedPointVolumeRayCastMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkFixedPointVolumeRayCastMapper - A fixed point mapper for volumes +// .SECTION Description +// This is a software ray caster for rendering volumes in vtkImageData. +// It works with all input data types and up to four components. It performs +// composite or MIP rendering, and can be intermixed with geometric data. +// Space leaping is used to speed up the rendering process. In addition, +// calculation are performed in 15 bit fixed point precision. This mapper +// is threaded, and will interleave scan lines across processors. +// +// This mapper is a good replacement for vtkVolumeRayCastMapper EXCEPT: +// - it does not do isosurface ray casting +// - it does only interpolate before classify compositing +// - it does only maximum scalar value MIP +// +// The vtkVolumeRayCastMapper CANNOT be used in these instances when a +// vtkFixedPointVolumeRayCastMapper can be used: +// - if the data is not unsigned char or unsigned short +// - if the data has more than one component +// +// This mapper handles all data type from unsigned char through double. +// However, some of the internal calcultions are performed in float and +// therefore even the full float range may cause problems for this mapper +// (both in scalar data values and in spacing between samples). +// +// Space leaping is performed by creating a sub-sampled volume. 4x4x4 +// cells in the original volume are represented by a min, max, and +// combined gradient and flag value. The min max volume has three +// unsigned shorts per 4x4x4 group of cells from the original volume - +// one reprenting the minumum scalar index (the scalar value adjusted +// to fit in the 15 bit range), the maximum scalar index, and a +// third unsigned short which is both the maximum gradient opacity in +// the neighborhood (an unsigned char) and the flag that is filled +// in for the current lookup tables to indicate whether this region +// can be skipped. + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkFixedPointVolumeRayCastMapper_h +#define __vtkFixedPointVolumeRayCastMapper_h + +#include "vtkVolumeMapper.h" + +#define VTKKW_FP_SHIFT 15 +#define VTKKW_FPMM_SHIFT 17 +#define VTKKW_FP_MASK 0x7fff +#define VTKKW_FP_SCALE 32767.0 + +class vtkMatrix4x4; +class vtkMultiThreader; +class vtkPlaneCollection; +class vtkRenderer; +class vtkTimerLog; +class vtkVolume; +class vtkTransform; +class vtkRenderWindow; +class vtkColorTransferFunction; +class vtkPiecewiseFunction; +class vtkFixedPointVolumeRayCastMIPHelper; +class vtkFixedPointVolumeRayCastCompositeHelper; +class vtkFixedPointVolumeRayCastCompositeGOHelper; +class vtkFixedPointVolumeRayCastCompositeGOShadeHelper; +class vtkFixedPointVolumeRayCastCompositeShadeHelper; +class vtkDirectionEncoder; +class vtkEncodedGradientShader; +class vtkFiniteDifferenceGradientEstimator; +class vtkRayCastImageDisplayHelper; +class vtkFixedPointRayCastImage; + +// Forward declaration needed for use by friend declaration below. +VTK_THREAD_RETURN_TYPE FixedPointVolumeRayCastMapper_CastRays( void *arg ); + +class VTK_VOLUMERENDERING_EXPORT vtkFixedPointVolumeRayCastMapper : public vtkVolumeMapper +{ +public: + static vtkFixedPointVolumeRayCastMapper *New(); + vtkTypeRevisionMacro(vtkFixedPointVolumeRayCastMapper,vtkVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set/Get the distance between samples used for rendering + // when AutoAdjustSampleDistances is off, or when this mapper + // has more than 1 second allocated to it for rendering. + vtkSetMacro( SampleDistance, float ); + vtkGetMacro( SampleDistance, float ); + + // Description: + // Set/Get the distance between samples when interactive rendering is happening. + // In this case, interactive is defined as this volume mapper having less than 1 + // second allocated for rendering. When AutoAdjustSampleDistance is On, and the + // allocated render time is less than 1 second, then this InteractiveSampleDistance + // will be used instead of the SampleDistance above. + vtkSetMacro( InteractiveSampleDistance, float ); + vtkGetMacro( InteractiveSampleDistance, float ); + + // Description: + // Sampling distance in the XY image dimensions. Default value of 1 meaning + // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If + // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. This value + // will be adjusted to meet a desired frame rate when AutoAdjustSampleDistances + // is on. + vtkSetClampMacro( ImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( ImageSampleDistance, float ); + + // Description: + // This is the minimum image sample distance allow when the image + // sample distance is being automatically adjusted. + vtkSetClampMacro( MinimumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MinimumImageSampleDistance, float ); + + // Description: + // This is the maximum image sample distance allow when the image + // sample distance is being automatically adjusted. + vtkSetClampMacro( MaximumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MaximumImageSampleDistance, float ); + + // Description: + // If AutoAdjustSampleDistances is on, the the ImageSampleDistance + // and the SampleDistance will be varied to achieve the allocated + // render time of this prop (controlled by the desired update rate + // and any culling in use). If this is an interactive render (more + // than 1 frame per second) the SampleDistance will be increased, + // otherwise it will not be altered (a binary decision, as opposed + // to the ImageSampleDistance which will vary continuously). + vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 ); + vtkGetMacro( AutoAdjustSampleDistances, int ); + vtkBooleanMacro( AutoAdjustSampleDistances, int ); + + // Description: + // Set/Get the number of threads to use. This by default is equal to + // the number of available processors detected. + void SetNumberOfThreads( int num ); + int GetNumberOfThreads(); + + // Description: + // If IntermixIntersectingGeometry is turned on, the zbuffer will be + // captured and used to limit the traversal of the rays. + vtkSetClampMacro( IntermixIntersectingGeometry, int, 0, 1 ); + vtkGetMacro( IntermixIntersectingGeometry, int ); + vtkBooleanMacro( IntermixIntersectingGeometry, int ); + + // Description: + // What is the image sample distance required to achieve the desired time? + // A version of this method is provided that does not require the volume + // argument since if you are using an LODProp3D you may not know this information. + // If you use this version you must be certain that the ray cast mapper is + // only used for one volume (and not shared among multiple volumes) + float ComputeRequiredImageSampleDistance( float desiredTime, + vtkRenderer *ren ); + float ComputeRequiredImageSampleDistance( float desiredTime, + vtkRenderer *ren, + vtkVolume *vol ); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Initialize rendering for this volume. + void Render( vtkRenderer *, vtkVolume * ); + + unsigned int ToFixedPointPosition( float val ); + void ToFixedPointPosition( float in[3], unsigned int out[3] ); + unsigned int ToFixedPointDirection( float dir ); + void ToFixedPointDirection( float in[3], unsigned int out[3] ); + void FixedPointIncrement( unsigned int position[3], unsigned int increment[3] ); + void GetFloatTripleFromPointer( float v[3], float *ptr ); + void GetUIntTripleFromPointer( unsigned int v[3], unsigned int *ptr ); + void ShiftVectorDown( unsigned int in[3], unsigned int out[3] ); + int CheckMinMaxVolumeFlag( unsigned int pos[3], int c ); + int CheckMIPMinMaxVolumeFlag( unsigned int pos[3], int c, unsigned short maxIdx ); + + void LookupColorUC( unsigned short *colorTable, + unsigned short *scalarOpacityTable, + unsigned short index, + unsigned char color[4] ); + void LookupDependentColorUC( unsigned short *colorTable, + unsigned short *scalarOpacityTable, + unsigned short index[4], + int components, + unsigned char color[4] ); + void LookupAndCombineIndependentColorsUC( + unsigned short *colorTable[4], + unsigned short *scalarOpacityTable[4], + unsigned short index[4], + float weights[4], + int components, + unsigned char color[4] ); + int CheckIfCropped( unsigned int pos[3] ); + +//ETX + + vtkGetObjectMacro( RenderWindow, vtkRenderWindow ); + vtkGetObjectMacro( MIPHelper, vtkFixedPointVolumeRayCastMIPHelper ); + vtkGetObjectMacro( CompositeHelper, vtkFixedPointVolumeRayCastCompositeHelper ); + vtkGetObjectMacro( CompositeGOHelper, vtkFixedPointVolumeRayCastCompositeGOHelper ); + vtkGetObjectMacro( CompositeGOShadeHelper, vtkFixedPointVolumeRayCastCompositeGOShadeHelper ); + vtkGetObjectMacro( CompositeShadeHelper, vtkFixedPointVolumeRayCastCompositeShadeHelper ); + vtkGetVectorMacro( TableShift, float, 4 ); + vtkGetVectorMacro( TableScale, float, 4 ); + vtkGetMacro( ShadingRequired, int ); + vtkGetMacro( GradientOpacityRequired, int ); + + int *GetRowBounds() {return this->RowBounds;} + unsigned short *GetColorTable(int c) {return this->ColorTable[c];} + unsigned short *GetScalarOpacityTable(int c) {return this->ScalarOpacityTable[c];} + unsigned short *GetGradientOpacityTable(int c) {return this->GradientOpacityTable[c];} + vtkVolume *GetVolume() {return this->Volume;} + unsigned short **GetGradientNormal() {return this->GradientNormal;} + unsigned char **GetGradientMagnitude() {return this->GradientMagnitude;} + unsigned short *GetDiffuseShadingTable(int c) {return this->DiffuseShadingTable[c];} + unsigned short *GetSpecularShadingTable(int c) {return this->SpecularShadingTable[c];} + + void ComputeRayInfo( int x, int y, + unsigned int pos[3], + unsigned int dir[3], + unsigned int *numSteps ); + + void InitializeRayInfo( vtkVolume *vol ); + + int ShouldUseNearestNeighborInterpolation( vtkVolume *vol ); + + // Description: + // Set / Get the underlying image object. One will be automatically + // created - only need to set it when using from an AMR mapper which + // renders multiple times into the same image. + void SetRayCastImage( vtkFixedPointRayCastImage * ); + vtkGetObjectMacro( RayCastImage, vtkFixedPointRayCastImage ); + + int PerImageInitialization( vtkRenderer *, vtkVolume *, int, + double *, double *, int * ); + void PerVolumeInitialization( vtkRenderer *, vtkVolume * ); + void PerSubVolumeInitialization( vtkRenderer *, vtkVolume *, int ); + void RenderSubVolume(); + void DisplayRenderedImage( vtkRenderer *, vtkVolume * ); + void AbortRender(); + + +protected: + vtkFixedPointVolumeRayCastMapper(); + ~vtkFixedPointVolumeRayCastMapper(); + + // The helper class that displays the image + vtkRayCastImageDisplayHelper *ImageDisplayHelper; + + // The distance between sample points along the ray + float SampleDistance; + float InteractiveSampleDistance; + + // The distance between rays in the image + float ImageSampleDistance; + float MinimumImageSampleDistance; + float MaximumImageSampleDistance; + int AutoAdjustSampleDistances; + + // Saved values used to restore + float OldSampleDistance; + float OldImageSampleDistance; + + // Internal method for computing matrices needed during + // ray casting + void ComputeMatrices( double volumeOrigin[3], + double volumeSpacing[3], + int volumeExtent[6], + vtkRenderer *ren, + vtkVolume *vol ); + + int ComputeRowBounds( vtkRenderer *ren, + int imageFlag, int rowBoundsFlag, + int volumeExtent[6]); + + void CaptureZBuffer( vtkRenderer *ren ); + + friend VTK_THREAD_RETURN_TYPE FixedPointVolumeRayCastMapper_CastRays( void *arg ); + + vtkMultiThreader *Threader; + + vtkMatrix4x4 *PerspectiveMatrix; + vtkMatrix4x4 *ViewToWorldMatrix; + vtkMatrix4x4 *ViewToVoxelsMatrix; + vtkMatrix4x4 *VoxelsToViewMatrix; + vtkMatrix4x4 *WorldToVoxelsMatrix; + vtkMatrix4x4 *VoxelsToWorldMatrix; + + vtkMatrix4x4 *VolumeMatrix; + + vtkTransform *PerspectiveTransform; + vtkTransform *VoxelsTransform; + vtkTransform *VoxelsToViewTransform; + + // This object encapsulated the image and all related information + vtkFixedPointRayCastImage *RayCastImage; + + int *RowBounds; + int *OldRowBounds; + + float *RenderTimeTable; + vtkVolume **RenderVolumeTable; + vtkRenderer **RenderRendererTable; + int RenderTableSize; + int RenderTableEntries; + + void StoreRenderTime( vtkRenderer *ren, vtkVolume *vol, float t ); + float RetrieveRenderTime( vtkRenderer *ren, vtkVolume *vol ); + float RetrieveRenderTime( vtkRenderer *ren ); + + int IntermixIntersectingGeometry; + + float MinimumViewDistance; + + vtkColorTransferFunction *SavedRGBFunction[4]; + vtkPiecewiseFunction *SavedGrayFunction[4]; + vtkPiecewiseFunction *SavedScalarOpacityFunction[4]; + vtkPiecewiseFunction *SavedGradientOpacityFunction[4]; + int SavedColorChannels[4]; + float SavedScalarOpacityDistance[4]; + int SavedBlendMode; + vtkImageData *SavedParametersInput; + vtkTimeStamp SavedParametersMTime; + + vtkImageData *SavedGradientsInput; + vtkTimeStamp SavedGradientsMTime; + + float SavedSampleDistance; + + + unsigned short ColorTable[4][32768*3]; + unsigned short ScalarOpacityTable[4][32768]; + unsigned short GradientOpacityTable[4][256]; + int TableSize[4]; + float TableScale[4]; + float TableShift[4]; + + float GradientMagnitudeScale[4]; + float GradientMagnitudeShift[4]; + + unsigned short **GradientNormal; + unsigned char **GradientMagnitude; + unsigned short *ContiguousGradientNormal; + unsigned char *ContiguousGradientMagnitude; + + int NumberOfGradientSlices; + + vtkDirectionEncoder *DirectionEncoder; + + vtkEncodedGradientShader *GradientShader; + + vtkFiniteDifferenceGradientEstimator *GradientEstimator; + + unsigned short DiffuseShadingTable [4][65536*3]; + unsigned short SpecularShadingTable[4][65536*3]; + + int ShadingRequired; + int GradientOpacityRequired; + + vtkRenderWindow *RenderWindow; + vtkVolume *Volume; + + int ClipRayAgainstVolume( float rayStart[3], + float rayEnd[3], + float rayDirection[3], + double bounds[6] ); + + int UpdateColorTable( vtkVolume *vol ); + int UpdateGradients( vtkVolume *vol ); + int UpdateShadingTable( vtkRenderer *ren, + vtkVolume *vol ); + void UpdateCroppingRegions(); + + void ComputeGradients( vtkVolume *vol ); + + int ClipRayAgainstClippingPlanes( float rayStart[3], + float rayEnd[3], + int numClippingPlanes, + float *clippingPlanes ); + + unsigned int FixedPointCroppingRegionPlanes[6]; + unsigned int CroppingRegionMask[27]; + + // Get the ZBuffer value corresponding to location (x,y) where (x,y) + // are indexing into the ImageInUse image. This must be converted to + // the zbuffer image coordinates. Nearest neighbor value is returned. + float GetZBufferValue( int x, int y ); + + vtkFixedPointVolumeRayCastMIPHelper *MIPHelper; + vtkFixedPointVolumeRayCastCompositeHelper *CompositeHelper; + vtkFixedPointVolumeRayCastCompositeGOHelper *CompositeGOHelper; + vtkFixedPointVolumeRayCastCompositeShadeHelper *CompositeShadeHelper; + vtkFixedPointVolumeRayCastCompositeGOShadeHelper *CompositeGOShadeHelper; + + // Some variables used for ray computation + float ViewToVoxelsArray[16]; + float WorldToVoxelsArray[16]; + float VoxelsToWorldArray[16]; + + double CroppingBounds[6]; + + int NumTransformedClippingPlanes; + float *TransformedClippingPlanes; + + double SavedSpacing[3]; + + + // Min Max structured used to do space leaping + unsigned short *MinMaxVolume; + int MinMaxVolumeSize[4]; + vtkImageData *SavedMinMaxInput; + vtkTimeStamp SavedMinMaxBuildTime; + vtkTimeStamp SavedMinMaxGradientTime; + vtkTimeStamp SavedMinMaxFlagTime; + + void UpdateMinMaxVolume( vtkVolume *vol ); + void FillInMaxGradientMagnitudes( int fullDim[3], + int smallDim[3] ); + +private: + vtkFixedPointVolumeRayCastMapper(const vtkFixedPointVolumeRayCastMapper&); // Not implemented. + void operator=(const vtkFixedPointVolumeRayCastMapper&); // Not implemented. +}; + + +inline unsigned int vtkFixedPointVolumeRayCastMapper::ToFixedPointPosition( float val ) +{ + return static_cast<unsigned int>(val * VTKKW_FP_SCALE + 0.5); +} + +inline void vtkFixedPointVolumeRayCastMapper::ToFixedPointPosition( float in[3], unsigned int out[3] ) +{ + out[0] = static_cast<unsigned int>(in[0] * VTKKW_FP_SCALE + 0.5); + out[1] = static_cast<unsigned int>(in[1] * VTKKW_FP_SCALE + 0.5); + out[2] = static_cast<unsigned int>(in[2] * VTKKW_FP_SCALE + 0.5); +} + +inline unsigned int vtkFixedPointVolumeRayCastMapper::ToFixedPointDirection( float dir ) +{ + return ((dir<0.0)? + (static_cast<unsigned int>(-dir * VTKKW_FP_SCALE + 0.5)): + (0x80000000+static_cast<unsigned int>(dir*VTKKW_FP_SCALE + 0.5))); +} + +inline void vtkFixedPointVolumeRayCastMapper::ToFixedPointDirection( float in[3], unsigned int out[3] ) +{ + out[0] = ((in[0]<0.0)? + (static_cast<unsigned int>(-in[0] * VTKKW_FP_SCALE + 0.5)): + (0x80000000+ + static_cast<unsigned int>(in[0]*VTKKW_FP_SCALE + 0.5))); + out[1] = ((in[1]<0.0)? + (static_cast<unsigned int>(-in[1] * VTKKW_FP_SCALE + 0.5)): + (0x80000000+ + static_cast<unsigned int>(in[1]*VTKKW_FP_SCALE + 0.5))); + out[2] = ((in[2]<0.0)? + (static_cast<unsigned int>(-in[2] * VTKKW_FP_SCALE + 0.5)): + (0x80000000+ + static_cast<unsigned int>(in[2]*VTKKW_FP_SCALE + 0.5))); +} + +inline void vtkFixedPointVolumeRayCastMapper::FixedPointIncrement( unsigned int position[3], unsigned int increment[3] ) +{ + if ( increment[0]&0x80000000 ) + { + position[0] += (increment[0]&0x7fffffff); + } + else + { + position[0] -= increment[0]; + } + if ( increment[1]&0x80000000 ) + { + position[1] += (increment[1]&0x7fffffff); + } + else + { + position[1] -= increment[1]; + } + if ( increment[2]&0x80000000 ) + { + position[2] += (increment[2]&0x7fffffff); + } + else + { + position[2] -= increment[2]; + } +} + + +inline void vtkFixedPointVolumeRayCastMapper::GetFloatTripleFromPointer( float v[3], float *ptr ) +{ + v[0] = *(ptr); + v[1] = *(ptr+1); + v[2] = *(ptr+2); +} + +inline void vtkFixedPointVolumeRayCastMapper::GetUIntTripleFromPointer( unsigned int v[3], unsigned int *ptr ) +{ + v[0] = *(ptr); + v[1] = *(ptr+1); + v[2] = *(ptr+2); +} + +inline void vtkFixedPointVolumeRayCastMapper::ShiftVectorDown( unsigned int in[3], + unsigned int out[3] ) +{ + out[0] = in[0] >> VTKKW_FP_SHIFT; + out[1] = in[1] >> VTKKW_FP_SHIFT; + out[2] = in[2] >> VTKKW_FP_SHIFT; +} + +inline int vtkFixedPointVolumeRayCastMapper::CheckMinMaxVolumeFlag( unsigned int mmpos[3], int c ) +{ + unsigned int offset = + this->MinMaxVolumeSize[3] * + ( mmpos[2]*this->MinMaxVolumeSize[0]*this->MinMaxVolumeSize[1] + + mmpos[1]*this->MinMaxVolumeSize[0] + + mmpos[0] ) + c; + + return ((*(this->MinMaxVolume + 3*offset + 2))&0x00ff); +} + +inline int vtkFixedPointVolumeRayCastMapper::CheckMIPMinMaxVolumeFlag( unsigned int mmpos[3], int c, + unsigned short maxIdx ) +{ + unsigned int offset = + this->MinMaxVolumeSize[3] * + ( mmpos[2]*this->MinMaxVolumeSize[0]*this->MinMaxVolumeSize[1] + + mmpos[1]*this->MinMaxVolumeSize[0] + + mmpos[0] ) + c; + + if ( (*(this->MinMaxVolume + 3*offset + 2)&0x00ff) ) + { + return ( *(this->MinMaxVolume + 3*offset + 1) > maxIdx ); + } + else + { + return 0; + } +} + +inline void vtkFixedPointVolumeRayCastMapper::LookupColorUC( unsigned short *colorTable, + unsigned short *scalarOpacityTable, + unsigned short index, + unsigned char color[4] ) +{ + unsigned short alpha = scalarOpacityTable[index]; + color[0] = static_cast<unsigned char> + ((colorTable[3*index ]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + color[1] = static_cast<unsigned char> + ((colorTable[3*index+1]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + color[2] = static_cast<unsigned char> + ((colorTable[3*index+2]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + color[3] = static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8)); +} + +inline void vtkFixedPointVolumeRayCastMapper::LookupDependentColorUC( unsigned short *colorTable, + unsigned short *scalarOpacityTable, + unsigned short index[4], + int components, + unsigned char color[4] ) +{ + unsigned short alpha; + switch ( components ) + { + case 2: + alpha = scalarOpacityTable[index[1]]; + color[0] = static_cast<unsigned char> + ((colorTable[3*index[0] ]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + color[1] = static_cast<unsigned char> + ((colorTable[3*index[0]+1]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + color[2] = static_cast<unsigned char> + ((colorTable[3*index[0]+2]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + color[3] = static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8)); + break; + case 4: + alpha = scalarOpacityTable[index[3]]; + color[0] = static_cast<unsigned char>((index[0]*alpha + 0x7fff)>>VTKKW_FP_SHIFT ); + color[1] = static_cast<unsigned char>((index[1]*alpha + 0x7fff)>>VTKKW_FP_SHIFT ); + color[2] = static_cast<unsigned char>((index[2]*alpha + 0x7fff)>>VTKKW_FP_SHIFT ); + color[3] = static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8)); + break; + } +} + + +inline void vtkFixedPointVolumeRayCastMapper::LookupAndCombineIndependentColorsUC( unsigned short *colorTable[4], + unsigned short *scalarOpacityTable[4], + unsigned short index[4], + float weights[4], + int components, + unsigned char color[4] ) +{ + unsigned int tmp[4] = {0,0,0,0}; + + for ( int i = 0; i < components; i++ ) + { + unsigned short alpha = static_cast<unsigned short>(scalarOpacityTable[i][index[i]]*weights[i]); + tmp[0] += static_cast<unsigned char>(((colorTable[i][3*index[i] ])*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + tmp[1] += static_cast<unsigned char>(((colorTable[i][3*index[i]+1])*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + tmp[2] += static_cast<unsigned char>(((colorTable[i][3*index[i]+2])*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8)); + tmp[3] += static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8)); + } + + color[0] = (tmp[0]>255)?(255):(tmp[0]); + color[1] = (tmp[1]>255)?(255):(tmp[1]); + color[2] = (tmp[2]>255)?(255):(tmp[2]); + color[3] = (tmp[3]>255)?(255):(tmp[3]); + +} + +inline int vtkFixedPointVolumeRayCastMapper::CheckIfCropped( unsigned int pos[3] ) +{ + int idx; + + if ( pos[2] < this->FixedPointCroppingRegionPlanes[4] ) + { + idx = 0; + } + else if ( pos[2] > this->FixedPointCroppingRegionPlanes[5] ) + { + idx = 18; + } + else + { + idx = 9; + } + + if ( pos[1] >= this->FixedPointCroppingRegionPlanes[2] ) + { + if ( pos[1] > this->FixedPointCroppingRegionPlanes[3] ) + { + idx += 6; + } + else + { + idx += 3; + } + } + + if ( pos[0] >= this->FixedPointCroppingRegionPlanes[0] ) + { + if ( pos[0] > this->FixedPointCroppingRegionPlanes[1] ) + { + idx += 2; + } + else + { + idx += 1; + } + } + + return !(this->CroppingRegionFlags&this->CroppingRegionMask[idx]); +} + +#endif diff --git a/VolumeRendering/vtkMesaRayCastImageDisplayHelper.cxx b/VolumeRendering/vtkMesaRayCastImageDisplayHelper.cxx new file mode 100644 index 0000000..4b3de01 --- /dev/null +++ b/VolumeRendering/vtkMesaRayCastImageDisplayHelper.cxx @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaRayCastImageDisplayHelper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include <math.h> +#include "vtkMesaRayCastImageDisplayHelper.h" + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaRayCastImageDisplayHelper classes defined. +#include "vtkOpenGLRayCastImageDisplayHelper.h" +#include "vtkMesaRayCastImageDisplayHelper.h" + +// Make sure vtkMesaRayCastImageDisplayHelper is a copy of +// vtkOpenGLRayCastImageDisplayHelper with vtkOpenGLRayCastImageDisplayHelper +// replaced with vtkMesaRayCastImageDisplayHelper +#define vtkOpenGLRayCastImageDisplayHelper vtkMesaRayCastImageDisplayHelper +#include "vtkOpenGLRayCastImageDisplayHelper.cxx" +#undef vtkOpenGLRayCastImageDisplayHelper + +vtkCxxRevisionMacro(vtkMesaRayCastImageDisplayHelper, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkMesaRayCastImageDisplayHelper); diff --git a/VolumeRendering/vtkMesaRayCastImageDisplayHelper.h b/VolumeRendering/vtkMesaRayCastImageDisplayHelper.h new file mode 100644 index 0000000..e41d82e --- /dev/null +++ b/VolumeRendering/vtkMesaRayCastImageDisplayHelper.h @@ -0,0 +1,78 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaRayCastImageDisplayHelper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkMesaRayCastImageDisplayHelper - Mesa subclass that draws the image to the screen +// .SECTION Description +// This is the concrete implementation of a ray cast image display helper - +// a helper class responsible for drawing the image to the screen. + +// .SECTION see also +// vtkRayCastImageDisplayHelper + +#ifndef __vtkMesaRayCastImageDisplayHelper_h +#define __vtkMesaRayCastImageDisplayHelper_h + +#include "vtkRayCastImageDisplayHelper.h" + +class vtkVolume; +class vtkRenderer; +class vtkFixedPointRayCastImage; + +class VTK_VOLUMERENDERING_EXPORT vtkMesaRayCastImageDisplayHelper : public vtkRayCastImageDisplayHelper +{ +public: + static vtkMesaRayCastImageDisplayHelper *New(); + vtkTypeRevisionMacro(vtkMesaRayCastImageDisplayHelper,vtkRayCastImageDisplayHelper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned char *image ); + + void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned short *image ); + + void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + vtkFixedPointRayCastImage *image, + float requestedDepth ); + +protected: + vtkMesaRayCastImageDisplayHelper(); + ~vtkMesaRayCastImageDisplayHelper(); + + void RenderTextureInternal( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + int imageScalarType, + void *image ); +private: + vtkMesaRayCastImageDisplayHelper(const vtkMesaRayCastImageDisplayHelper&); // Not implemented. + void operator=(const vtkMesaRayCastImageDisplayHelper&); // Not implemented. +}; + +#endif + diff --git a/VolumeRendering/vtkMesaVolumeTextureMapper2D.cxx b/VolumeRendering/vtkMesaVolumeTextureMapper2D.cxx new file mode 100644 index 0000000..51581ef --- /dev/null +++ b/VolumeRendering/vtkMesaVolumeTextureMapper2D.cxx @@ -0,0 +1,42 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaVolumeTextureMapper2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// Make sure this is first, so any includes of gl.h can be stoped if needed +#define VTK_IMPLEMENT_MESA_CXX + +#include "MangleMesaInclude/gl_mangle.h" +#include "MangleMesaInclude/gl.h" + +#include <math.h> +#include "vtkToolkits.h" +#include "vtkMesaVolumeTextureMapper2D.h" +#include "vtkRenderWindow.h" +#include "vtkMesaProperty.h" +#include "vtkMesaCamera.h" +#include "vtkMesaLight.h" +#include "vtkCuller.h" + +// make sure this file is included before the #define takes place +// so we don't get two vtkMesaVolumeTextureMapper2D classes defined. +#include "vtkOpenGLVolumeTextureMapper2D.h" +#include "vtkMesaVolumeTextureMapper2D.h" + +// Make sure vtkMesaVolumeTextureMapper2D is a copy of vtkOpenGLVolumeTextureMapper2D +// with vtkOpenGLVolumeTextureMapper2D replaced with vtkMesaVolumeTextureMapper2D +#define vtkOpenGLVolumeTextureMapper2D vtkMesaVolumeTextureMapper2D +#include "vtkOpenGLVolumeTextureMapper2D.cxx" +#undef vtkOpenGLVolumeTextureMapper2D + +vtkCxxRevisionMacro(vtkMesaVolumeTextureMapper2D, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkMesaVolumeTextureMapper2D); diff --git a/VolumeRendering/vtkMesaVolumeTextureMapper2D.h b/VolumeRendering/vtkMesaVolumeTextureMapper2D.h new file mode 100644 index 0000000..e0ce149 --- /dev/null +++ b/VolumeRendering/vtkMesaVolumeTextureMapper2D.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkMesaVolumeTextureMapper2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkMesaVolumeTextureMapper2D - Abstract class for a volume mapper + +// .SECTION Description +// vtkMesaVolumeTextureMapper2D renders a volume using 2D texture mapping. + + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkMesaVolumeTextureMapper2D_h +#define __vtkMesaVolumeTextureMapper2D_h + +#include "vtkVolumeTextureMapper2D.h" + +class VTK_VOLUMERENDERING_EXPORT vtkMesaVolumeTextureMapper2D : public vtkVolumeTextureMapper2D +{ +public: + vtkTypeRevisionMacro(vtkMesaVolumeTextureMapper2D,vtkVolumeTextureMapper2D); + void PrintSelf( ostream& os, vtkIndent indent ); + + static vtkMesaVolumeTextureMapper2D *New(); + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol); + + void RenderQuads( int count, float *v, float *t, + unsigned char *texture, int size[2], int reverseFlag); + +//ETX + +protected: + vtkMesaVolumeTextureMapper2D(); + ~vtkMesaVolumeTextureMapper2D(); + +private: + vtkMesaVolumeTextureMapper2D(const vtkMesaVolumeTextureMapper2D&); // Not implemented. + void operator=(const vtkMesaVolumeTextureMapper2D&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkOpenGLRayCastImageDisplayHelper.cxx b/VolumeRendering/vtkOpenGLRayCastImageDisplayHelper.cxx new file mode 100644 index 0000000..68bab3c --- /dev/null +++ b/VolumeRendering/vtkOpenGLRayCastImageDisplayHelper.cxx @@ -0,0 +1,555 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLRayCastImageDisplayHelper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLRayCastImageDisplayHelper.h" + +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkVolume.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkCamera.h" +#include "vtkFixedPointRayCastImage.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif + +#include <math.h> + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLRayCastImageDisplayHelper, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkOpenGLRayCastImageDisplayHelper); +#endif + +// Construct a new vtkOpenGLRayCastImageDisplayHelper with default values +vtkOpenGLRayCastImageDisplayHelper::vtkOpenGLRayCastImageDisplayHelper() +{ +} + +// Destruct a vtkOpenGLRayCastImageDisplayHelper - clean up any memory used +vtkOpenGLRayCastImageDisplayHelper::~vtkOpenGLRayCastImageDisplayHelper() +{ +} + +// imageMemorySize is how big the texture is - this is always a power of two +// +// imageViewportSize is how big the renderer viewport is in pixels +// +// imageInUseSize is the rendered image - equal or smaller than imageMemorySize +// and imageViewportSize +// +// imageOrigin is the starting pixel of the imageInUseSize image on the +// the imageViewportSize viewport +// +void vtkOpenGLRayCastImageDisplayHelper::RenderTexture( vtkVolume *vol, + vtkRenderer *ren, + vtkFixedPointRayCastImage *image, + float requestedDepth ) +{ + this->RenderTextureInternal( vol, ren, image->GetImageMemorySize(), image->GetImageViewportSize(), + image->GetImageInUseSize(), image->GetImageOrigin(), + requestedDepth, VTK_UNSIGNED_SHORT, image->GetImage() ); +} + +void vtkOpenGLRayCastImageDisplayHelper::RenderTexture( vtkVolume *vol, + vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned char *image ) +{ + this->RenderTextureInternal( vol, ren, imageMemorySize, imageViewportSize, + imageInUseSize, imageOrigin, requestedDepth, + VTK_UNSIGNED_CHAR, static_cast<void *>(image) ); +} + +void vtkOpenGLRayCastImageDisplayHelper::RenderTexture( vtkVolume *vol, + vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned short *image ) +{ + this->RenderTextureInternal( vol, ren, imageMemorySize, imageViewportSize, + imageInUseSize, imageOrigin, requestedDepth, + VTK_UNSIGNED_SHORT, static_cast<void *>(image) ); +} + +void vtkOpenGLRayCastImageDisplayHelper::RenderTextureInternal( vtkVolume *vol, + vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + int imageScalarType, + void *image ) +{ + int i; + float offsetX, offsetY; + float xMinOffset, xMaxOffset, yMinOffset, yMaxOffset; + float tcoords[8]; + + float depth; + if ( requestedDepth > 0.0 && requestedDepth <= 1.0 ) + { + depth = requestedDepth; + } + else + { + // Pass the center of the volume through the world to view function + // of the renderer to get the z view coordinate to use for the + // view to world transformation of the image bounds. This way we + // will draw the image at the depth of the center of the volume + ren->SetWorldPoint( vol->GetCenter()[0], + vol->GetCenter()[1], + vol->GetCenter()[2], + 1.0 ); + ren->WorldToView(); + depth = ren->GetViewPoint()[2]; + } + + // Convert the four corners of the image into world coordinates + float verts[12]; + vtkMatrix4x4 *viewToWorldMatrix = vtkMatrix4x4::New(); + float in[4], out[4]; + + vtkCamera *cam = ren->GetActiveCamera(); + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + vtkTransform *perspectiveTransform = vtkTransform::New(); + perspectiveTransform->Identity(); + perspectiveTransform->Concatenate( + cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], + 0.0, 1.0 )); + perspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + + // get the perspective transformation from the active camera + viewToWorldMatrix->DeepCopy( perspectiveTransform->GetMatrix() ); + perspectiveTransform->Delete(); + + // use the inverse matrix + viewToWorldMatrix->Invert(); + + // These two values never change + in[2] = depth; + in[3] = 1.0; + + // This is the lower left corner + in[0] = (float)imageOrigin[0]/imageViewportSize[0] * 2.0 - 1.0; + in[1] = (float)imageOrigin[1]/imageViewportSize[1] * 2.0 - 1.0; + + viewToWorldMatrix->MultiplyPoint( in, out ); + verts[0] = out[0] / out[3]; + verts[1] = out[1] / out[3]; + verts[2] = out[2] / out[3]; + + // This is the lower right corner + in[0] = (float)(imageOrigin[0]+imageInUseSize[0]) / + imageViewportSize[0] * 2.0 - 1.0; + in[1] = (float)imageOrigin[1]/imageViewportSize[1] * 2.0 - 1.0; + + viewToWorldMatrix->MultiplyPoint( in, out ); + verts[3] = out[0] / out[3]; + verts[4] = out[1] / out[3]; + verts[5] = out[2] / out[3]; + + // This is the upper right corner + in[0] = (float)(imageOrigin[0]+imageInUseSize[0]) / + imageViewportSize[0] * 2.0 - 1.0; + in[1] = (float)(imageOrigin[1]+imageInUseSize[1]) / + imageViewportSize[1] * 2.0 - 1.0; + + viewToWorldMatrix->MultiplyPoint( in, out ); + verts[6] = out[0] / out[3]; + verts[7] = out[1] / out[3]; + verts[8] = out[2] / out[3]; + + // This is the upper left corner + in[0] = (float)imageOrigin[0]/imageViewportSize[0] * 2.0 - 1.0; + in[1] = (float)(imageOrigin[1]+imageInUseSize[1]) / + imageViewportSize[1] * 2.0 - 1.0; + + viewToWorldMatrix->MultiplyPoint( in, out ); + verts[9] = out[0] / out[3]; + verts[10] = out[1] / out[3]; + verts[11] = out[2] / out[3]; + + viewToWorldMatrix->Delete(); + + // Save state + glPushAttrib(GL_ENABLE_BIT | + GL_COLOR_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_POLYGON_BIT | + GL_PIXEL_MODE_BIT | + GL_TEXTURE_BIT); + + glPixelTransferf( GL_RED_SCALE, this->PixelScale ); + glPixelTransferf( GL_GREEN_SCALE, this->PixelScale ); + glPixelTransferf( GL_BLUE_SCALE, this->PixelScale ); + glPixelTransferf( GL_ALPHA_SCALE, this->PixelScale ); + + if ( this->PreMultipliedColors ) + { + // Values in the texture map have already been pre-multiplied by alpha + glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); + } + else + { + // Values in the texture map have not been pre-multiplied by alpha + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + } + + // Turn lighting off - the texture already has illumination in it + glDisable( GL_LIGHTING ); + + // Turn texturing on so that we can draw the textured hexagon + glEnable( GL_TEXTURE_2D ); + +#ifdef GL_VERSION_1_1 + GLuint tempIndex; + glGenTextures(1, &tempIndex); + glBindTexture(GL_TEXTURE_2D, tempIndex); +#endif + + // Don't write into the Zbuffer - just use it for comparisons + glDepthMask( 0 ); + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + // Specify the texture + glColor3f(1.0,1.0,1.0); + int newTextureSize[2]; + +#ifdef GL_VERSION_1_1 + if ( imageScalarType == VTK_UNSIGNED_CHAR ) + { + // Test the texture to see if it fits in memory + glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, + imageMemorySize[0], imageMemorySize[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, + static_cast<unsigned char *>(image) ); + } + else + { + // Test the texture to see if it fits in memory + glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, + imageMemorySize[0], imageMemorySize[1], + 0, GL_RGBA, GL_UNSIGNED_SHORT, + static_cast<unsigned short *>(image) ); + } + + GLint params[1]; + glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D, 0, + GL_TEXTURE_WIDTH, params ); + + // if it does, we will render it later. define the texture here + if ( params[0] != 0 ) + { + if ( imageScalarType == VTK_UNSIGNED_CHAR ) + { + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, + imageMemorySize[0], imageMemorySize[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, + static_cast<unsigned char *>(image) ); + } + else + { + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, + imageMemorySize[0], imageMemorySize[1], + 0, GL_RGBA, GL_UNSIGNED_SHORT, + static_cast<unsigned short *>(image) ); + } + } + // if it doesn't, we are going to break it up now and render it. + // That's because we want this in the ifdef because this only works in + // 1.1 and later. + else + { + // Figure out our new texture size. Keep dividing the big one in half until + // OpenGL says this texture is OK + newTextureSize[0] = imageMemorySize[0]; + newTextureSize[1] = imageMemorySize[1]; + + while ( params[0] == 0 && newTextureSize[0] >= 32 && + newTextureSize[1] >= 32 ) + { + if ( newTextureSize[0] > newTextureSize[1] ) + { + newTextureSize[0] /= 2; + } + else + { + newTextureSize[1] /= 2; + } + + if ( imageScalarType == VTK_UNSIGNED_CHAR ) + { + glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, + newTextureSize[0], newTextureSize[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, + static_cast<unsigned char *>(image) ); + } + else + { + glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, + newTextureSize[0], newTextureSize[1], + 0, GL_RGBA, GL_UNSIGNED_SHORT, + static_cast<unsigned short *>(image) ); + } + glGetTexLevelParameteriv ( GL_PROXY_TEXTURE_2D, 0, + GL_TEXTURE_WIDTH, params ); + } + + // If we got down to 32 by 32 and OpenGL still doesn't like it, something + // must be seriously wrong and we will ignore it. Otherwise, we have our + // new texture size and let's start chopping up the image + if ( newTextureSize[0] >= 32 && newTextureSize[1] >= 32 ) + { + // How many tiles in x? + int xLimit = 1 + static_cast<int>( + static_cast<float>(imageInUseSize[0]) / + static_cast<float>((newTextureSize[0]-2))); + + // How many tiles in y? + int yLimit = 1 + static_cast<int>( + static_cast<float>(imageInUseSize[1]) / + static_cast<float>((newTextureSize[1]-2))); + + // Create memory for the new texture + unsigned char *newTextureChar = NULL; + unsigned short *newTextureShort = NULL; + + if ( imageScalarType == VTK_UNSIGNED_CHAR ) + { + newTextureChar = + new unsigned char [newTextureSize[0] * newTextureSize[1] * 4]; + } + else + { + newTextureShort = + new unsigned short [newTextureSize[0] * newTextureSize[1] * 4]; + } + + + // This is the 1/2 pixel offset for texture coordinates + offsetX = .5 / static_cast<float>(newTextureSize[0]); + offsetY = .5 / static_cast<float>(newTextureSize[1]); + + int ii, jj; + float newVerts[12]; + float vx1, vx2, vy1, vy2; + int px1, py1, pxSize, pySize; + + + // loop through the tiles in y + for ( jj = 0; jj < yLimit; jj++ ) + { + vy1 = static_cast<float>(jj) / static_cast<float>(yLimit); + vy2 = static_cast<float>(jj+1) / static_cast<float>(yLimit); + + py1 = static_cast<int>(vy1 * static_cast<float>( + imageInUseSize[1])); + pySize = static_cast<int>(2 - py1 + vy2 * static_cast<float>( + imageInUseSize[1]-1)); + if ( py1 + pySize > imageInUseSize[1] ) + { + pySize = imageInUseSize[1] - py1; + } + + yMinOffset = 2.0 * offsetY * + (vy1*static_cast<float>(imageInUseSize[1]-1)-static_cast<float>(py1)); + + yMaxOffset = 2.0 * offsetY * + (static_cast<float>(py1+pySize-1)-vy2*static_cast<float>(imageInUseSize[1]-1)); + + // loop through the tiles in x + for ( ii = 0; ii < xLimit; ii++ ) + { + vx1 = static_cast<float>(ii) / static_cast<float>(xLimit); + vx2 = static_cast<float>(ii+1) / static_cast<float>(xLimit); + + px1 = static_cast<int>(vx1 * static_cast<float>( + imageInUseSize[0])); + pxSize = static_cast<int>(2 - px1 + vx2 * static_cast<float>( + imageInUseSize[0]-1)); + if ( px1 + pxSize > imageInUseSize[0] ) + { + pxSize = imageInUseSize[0] - px1; + } + + xMinOffset = 2.0 * offsetX * + (vx1*static_cast<float>(imageInUseSize[0]-1) - + static_cast<float>(px1)); + + xMaxOffset = 2.0 * offsetX * + (static_cast<float>(px1+pxSize-1) - + vx2*static_cast<float>(imageInUseSize[0]-1)); + + if ( px1 + pxSize > imageInUseSize[0] ) + { + pxSize = imageInUseSize[0] - px1; + } + + // copy subtexture of image into newTexture + int loop; + for ( loop = 0; loop < pySize; loop++ ) + { + if ( imageScalarType == VTK_UNSIGNED_CHAR ) + { + memcpy( newTextureChar + 4*loop*newTextureSize[0], + static_cast<unsigned char *>(image) + + 4*(py1+loop)*imageMemorySize[0] + 4*px1, + pxSize * sizeof(unsigned char) * 4 ); + } + else + { + memcpy( newTextureShort + 4*loop*newTextureSize[0], + static_cast<unsigned short *>(image) + + 4*(py1+loop)*imageMemorySize[0] + 4*px1, + pxSize * sizeof(unsigned short) * 4 ); + } + } + + newVerts[ 0] = verts[0] + vx1*(verts[3]-verts[0]) + vy1*(verts[ 9]-verts[0]); + newVerts[ 1] = verts[1] + vx1*(verts[4]-verts[1]) + vy1*(verts[10]-verts[1]); + newVerts[ 2] = verts[2] + vx1*(verts[5]-verts[2]) + vy1*(verts[11]-verts[2]); + + newVerts[ 3] = verts[0] + vx2*(verts[3]-verts[0]) + vy1*(verts[ 9]-verts[0]); + newVerts[ 4] = verts[1] + vx2*(verts[4]-verts[1]) + vy1*(verts[10]-verts[1]); + newVerts[ 5] = verts[2] + vx2*(verts[5]-verts[2]) + vy1*(verts[11]-verts[2]); + + newVerts[ 6] = verts[0] + vx2*(verts[3]-verts[0]) + vy2*(verts[ 9]-verts[0]); + newVerts[ 7] = verts[1] + vx2*(verts[4]-verts[1]) + vy2*(verts[10]-verts[1]); + newVerts[ 8] = verts[2] + vx2*(verts[5]-verts[2]) + vy2*(verts[11]-verts[2]); + + newVerts[ 9] = verts[0] + vx1*(verts[3]-verts[0]) + vy2*(verts[ 9]-verts[0]); + newVerts[10] = verts[1] + vx1*(verts[4]-verts[1]) + vy2*(verts[10]-verts[1]); + newVerts[11] = verts[2] + vx1*(verts[5]-verts[2]) + vy2*(verts[11]-verts[2]); + + tcoords[0] = offsetX + xMinOffset; + tcoords[1] = offsetY + yMinOffset; + tcoords[2] = (float)pxSize/(float)newTextureSize[0] - offsetX - xMaxOffset; + tcoords[3] = offsetY + yMinOffset; + tcoords[4] = (float)pxSize/(float)newTextureSize[0] - offsetX - xMaxOffset; + tcoords[5] = (float)pySize/(float)newTextureSize[1] - offsetY - yMaxOffset; + tcoords[6] = offsetX + xMaxOffset; + tcoords[7] = (float)pySize/(float)newTextureSize[1] - offsetY - yMaxOffset; + + if ( imageScalarType == VTK_UNSIGNED_CHAR ) + { + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, + newTextureSize[0], newTextureSize[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, newTextureChar ); + } + else + { + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, + newTextureSize[0], newTextureSize[1], + 0, GL_RGBA, GL_UNSIGNED_SHORT, newTextureShort ); + } + + // Render the polygon + glBegin( GL_POLYGON ); + + for ( i = 0; i < 4; i++ ) + { + glTexCoord2fv( tcoords+i*2 ); + glVertex3fv( newVerts+i*3 ); + } + + glEnd(); + } + } + + // Delete the memory we created + delete [] newTextureChar; + delete [] newTextureShort; + } + + glFlush(); + glDeleteTextures(1, &tempIndex); + + // Restore state + glPopAttrib(); + + return; + } + +#else + if ( imageScalarType == VTK_UNSIGNED_CHAR ) + { + glTexImage2D( GL_TEXTURE_2D, 0, 4, + imageMemorySize[0], imageMemorySize[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, + static_cast<unsigned char *>(image) ); + } + else + { + glTexImage2D( GL_TEXTURE_2D, 0, 4, + imageMemorySize[0], imageMemorySize[1], + 0, GL_RGBA, GL_UNSIGNED_SHORT, + static_cast<unsigned short *>(image) ); + } + +#endif + offsetX = .5 / static_cast<float>(imageMemorySize[0]); + offsetY = .5 / static_cast<float>(imageMemorySize[1]); + + tcoords[0] = 0.0 + offsetX; + tcoords[1] = 0.0 + offsetY; + tcoords[2] = + (float)imageInUseSize[0]/(float)imageMemorySize[0] - offsetX; + tcoords[3] = offsetY; + tcoords[4] = + (float)imageInUseSize[0]/(float)imageMemorySize[0] - offsetX; + tcoords[5] = + (float)imageInUseSize[1]/(float)imageMemorySize[1] - offsetY; + tcoords[6] = offsetX; + tcoords[7] = + (float)imageInUseSize[1]/(float)imageMemorySize[1] - offsetY; + + // Render the polygon + glBegin( GL_POLYGON ); + + for ( i = 0; i < 4; i++ ) + { + glTexCoord2fv( tcoords+i*2 ); + glVertex3fv( verts+i*3 ); + } + glEnd(); + + +#ifdef GL_VERSION_1_1 + glFlush(); + glDeleteTextures(1, &tempIndex); +#endif + + // Restore state + glPopAttrib(); +} + +void vtkOpenGLRayCastImageDisplayHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkOpenGLRayCastImageDisplayHelper.h b/VolumeRendering/vtkOpenGLRayCastImageDisplayHelper.h new file mode 100644 index 0000000..3b90f54 --- /dev/null +++ b/VolumeRendering/vtkOpenGLRayCastImageDisplayHelper.h @@ -0,0 +1,79 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLRayCastImageDisplayHelper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkOpenGLRayCastImageDisplayHelper - OpenGL subclass that draws the image to the screen +// .SECTION Description +// This is the concrete implementation of a ray cast image display helper - +// a helper class responsible for drawing the image to the screen. + +// .SECTION see also +// vtkRayCastImageDisplayHelper + +#ifndef __vtkOpenGLRayCastImageDisplayHelper_h +#define __vtkOpenGLRayCastImageDisplayHelper_h + +#include "vtkRayCastImageDisplayHelper.h" + +class vtkVolume; +class vtkRenderer; +class vtkFixedPointRayCastImage; + +class VTK_VOLUMERENDERING_EXPORT vtkOpenGLRayCastImageDisplayHelper : public vtkRayCastImageDisplayHelper +{ +public: + static vtkOpenGLRayCastImageDisplayHelper *New(); + vtkTypeRevisionMacro(vtkOpenGLRayCastImageDisplayHelper,vtkRayCastImageDisplayHelper); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned char *image ); + + void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned short *image ); + + void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + vtkFixedPointRayCastImage *image, + float requestedDepth ); + +protected: + vtkOpenGLRayCastImageDisplayHelper(); + ~vtkOpenGLRayCastImageDisplayHelper(); + + void RenderTextureInternal( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + int imageScalarType, + void *image ); + +private: + vtkOpenGLRayCastImageDisplayHelper(const vtkOpenGLRayCastImageDisplayHelper&); // Not implemented. + void operator=(const vtkOpenGLRayCastImageDisplayHelper&); // Not implemented. +}; + +#endif + diff --git a/VolumeRendering/vtkOpenGLVolumeProVP1000Mapper.cxx b/VolumeRendering/vtkOpenGLVolumeProVP1000Mapper.cxx new file mode 100644 index 0000000..1c293e3 --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeProVP1000Mapper.cxx @@ -0,0 +1,255 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeProVP1000Mapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkOpenGLVolumeProVP1000Mapper.h" + +#include "vtkCamera.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderWindow.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkVolume.h" + +#include "vtkOpenGL.h" + +vtkCxxRevisionMacro(vtkOpenGLVolumeProVP1000Mapper, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkOpenGLVolumeProVP1000Mapper); + +void vtkOpenGLVolumeProVP1000Mapper::RenderImageBuffer(vtkRenderer *ren, + vtkVolume *vol, + int size[2], + unsigned int *outData) +{ + float depthVal, nearestPt[3], testZ, minZ; + double planeCoords[4][4]; + float tCoords[4][2]; + int i, j, k; + int textureSize[2]; + unsigned int *textureData; + double bounds[6]; + + textureSize[0] = textureSize[1] = 32; + while (textureSize[0] < size[0]) + { + textureSize[0] *= 2; + } + while (textureSize[1] < size[1]) + { + textureSize[1] *= 2; + } + + textureData = new unsigned int[textureSize[0]*textureSize[1]]; + for (j = 0; j < textureSize[1]; j++) + { + for (i = 0; i < textureSize[0]; i++) + { + if (i < size[0] && j < size[1]) + { + textureData[j*textureSize[0] + i] = outData[j*size[0] + i]; + } + else + { + textureData[j*textureSize[0] + i] = 0; + } + } + } + + if ( ! this->IntermixIntersectingGeometry ) + { + ren->SetWorldPoint(vol->GetCenter()[0], + vol->GetCenter()[1], + vol->GetCenter()[2], + 1.0); + } + else + { + minZ = 1; + vol->GetBounds(bounds); + + for (k = 0; k < 2; k++) + { + for (j = 0; j < 2; j++) + { + for (i = 0; i < 2; i++) + { + ren->SetWorldPoint(bounds[i+0], bounds[j+2], bounds[k+4], 1.0); + ren->WorldToDisplay(); + testZ = ren->GetDisplayPoint()[2]; + if (testZ < minZ) + { + minZ = testZ; + nearestPt[0] = bounds[i+0]; + nearestPt[1] = bounds[j+2]; + nearestPt[2] = bounds[k+4]; + } + } + } + } + ren->SetWorldPoint(nearestPt[0], nearestPt[1], nearestPt[2], 1.0); + } + + ren->WorldToView(); + depthVal = ren->GetViewPoint()[2]; + + double aspect[2]; + ren->GetAspect(aspect); + + ren->SetViewPoint(-aspect[0], -aspect[1], depthVal); + ren->ViewToWorld(); + ren->GetWorldPoint(planeCoords[0]); + + ren->SetViewPoint(aspect[0], -aspect[1], depthVal); + ren->ViewToWorld(); + ren->GetWorldPoint(planeCoords[1]); + + ren->SetViewPoint(aspect[0], aspect[1], depthVal); + ren->ViewToWorld(); + ren->GetWorldPoint(planeCoords[2]); + + ren->SetViewPoint(-aspect[0], aspect[1], depthVal); + ren->ViewToWorld(); + ren->GetWorldPoint(planeCoords[3]); + + // OpenGL stuff + glDisable( GL_LIGHTING ); + + glEnable( GL_TEXTURE_2D ); + glDepthMask( 0 ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Specify the texture + glColor3f(1.0,1.0,1.0); +#ifdef GL_VERSION_1_1 + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, + textureSize[0], textureSize[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData ); +#else + glTexImage2D( GL_TEXTURE_2D, 0, 4, + textureSize[0], textureSize[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData ); +#endif + + tCoords[0][0] = 0.0; + tCoords[0][1] = 0.0; + tCoords[1][0] = (float)size[0]/(float)textureSize[0]; + tCoords[1][1] = 0.0; + tCoords[2][0] = (float)size[0]/(float)textureSize[0]; + tCoords[2][1] = (float)size[1]/(float)textureSize[1]; + tCoords[3][0] = 0.0; + tCoords[3][1] = (float)size[1]/(float)textureSize[1]; + + glBegin( GL_POLYGON ); + for (i = 0; i < 4; i++) + { + glTexCoord2fv(tCoords[i]); + glVertex3dv(planeCoords[i]); + } + glEnd(); + glDisable( GL_TEXTURE_2D); + glDepthMask( 1 ); + glEnable( GL_LIGHTING ); + + glFlush(); + + delete [] textureData; +} + +void vtkOpenGLVolumeProVP1000Mapper::GetDepthBufferValues(vtkRenderer *ren, + int size[2], + unsigned int *outData) +{ + float *zData; + int i, length, rescale; + + zData = ren->GetRenderWindow()->GetZbufferData(0, 0, size[0]-1, size[1]-1); + if ( ! zData ) + { + vtkErrorMacro("could not get Z buffer data"); + return; + } + + length = size[0]*size[1]; + + rescale = 16777215; // 2^24 - 1 + + for (i = 0; i < length; i++) + { + outData[i] = (unsigned int)(zData[i] * rescale); + } + + // The render window allocated this memory, so it should release it. +#if ((VTK_MAJOR_VERSION == 3)&&(VTK_MINOR_VERSION == 2)) + delete [] zData; +#else + vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow())->ReleaseRGBAPixelData(zData); +#endif +} + + +void vtkOpenGLVolumeProVP1000Mapper::RenderBoundingBox(vtkRenderer *ren, + vtkVolume *vol) +{ + double bounds[6], background[3], color[3]; + ren->GetBackground(background); + if (background[0] > 0.5 && background[1] > 0.5 && background[2] > 0.5) + { + // black + color[0] = color[1] = color[2] = 0.0; + } + else + { + // white + color[0] = color[1] = color[2] = 1.0; + } + + vol->GetBounds(bounds); + + glColor3dv(color); + glDisable( GL_LIGHTING ); + + glBegin( GL_LINE_LOOP ); + glVertex3d(bounds[0], bounds[2], bounds[4]); + glVertex3d(bounds[1], bounds[2], bounds[4]); + glVertex3d(bounds[1], bounds[2], bounds[5]); + glVertex3d(bounds[0], bounds[2], bounds[5]); + glEnd(); + glBegin( GL_LINE_LOOP ); + glVertex3d(bounds[0], bounds[3], bounds[4]); + glVertex3d(bounds[1], bounds[3], bounds[4]); + glVertex3d(bounds[1], bounds[3], bounds[5]); + glVertex3d(bounds[0], bounds[3], bounds[5]); + glEnd(); + glBegin( GL_LINES ); + glVertex3d(bounds[0], bounds[2], bounds[4]); + glVertex3d(bounds[0], bounds[3], bounds[4]); + glVertex3d(bounds[1], bounds[2], bounds[4]); + glVertex3d(bounds[1], bounds[3], bounds[4]); + glVertex3d(bounds[1], bounds[2], bounds[5]); + glVertex3d(bounds[1], bounds[3], bounds[5]); + glVertex3d(bounds[0], bounds[2], bounds[5]); + glVertex3d(bounds[0], bounds[3], bounds[5]); + glEnd(); + + glEnable( GL_LIGHTING ); + glFlush(); +} + +//---------------------------------------------------------------------------- +void vtkOpenGLVolumeProVP1000Mapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkOpenGLVolumeProVP1000Mapper.h b/VolumeRendering/vtkOpenGLVolumeProVP1000Mapper.h new file mode 100644 index 0000000..914b0bc --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeProVP1000Mapper.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeProVP1000Mapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLVolumeProVP1000Mapper - Concrete class for VolumePRO mapper +// +// .SECTION Description +// vtkOpenGLVolumeProVP1000Mapper is the concrete implementation of a +// vtkVolumeProMapper based on the VP1000 chip running with OpenGL. +// Users should not create this class directly - a vtkVolumeProMapper will +// automatically create the object of the right type. +// +// This class is not included in the Rendering CMakeLists by default. If you +// want to add this class to your vtk build, you need to have the vli header +// and library files. Please see the vtkVolumeProVP1000Mapper.h file for +// instructions on how to use the vli library with vtk. +// +// For more information on the VolumePRO hardware, please see: +// +// http://www.terarecon.com/products/volumepro_prod.html +// +// If you encounter any problems with this class, please inform Kitware, Inc. +// at kitware@kitware.com. +// +// +// .SECTION See Also +// vtkVolumeMapper vtkVolumeProMapper vtkVolumeProVP1000Mapper +// + +#ifndef __vtkOpenGLVolumeProVP1000Mapper_h +#define __vtkOpenGLVolumeProVP1000Mapper_h + +#include "vtkVolumeProVP1000Mapper.h" + +class VTK_VOLUMERENDERING_EXPORT vtkOpenGLVolumeProVP1000Mapper : public vtkVolumeProVP1000Mapper +{ +public: + vtkTypeRevisionMacro(vtkOpenGLVolumeProVP1000Mapper,vtkVolumeProVP1000Mapper); + static vtkOpenGLVolumeProVP1000Mapper *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +protected: + vtkOpenGLVolumeProVP1000Mapper() {} + ~vtkOpenGLVolumeProVP1000Mapper() {} + + // Render the hexagon returned by the hardware to the screen. + void RenderImageBuffer( vtkRenderer *ren, + vtkVolume *vol, + int size[2], + unsigned int *outData ); + + // Get the OpenGL depth buffer values in a the form needed for the + // VolumePro board + virtual void GetDepthBufferValues( vtkRenderer *ren, int size[2], + unsigned int *outData); + + // Render a bounding box of the volume because the texture map would be + // too large + virtual void RenderBoundingBox(vtkRenderer *ren, vtkVolume *vol); + +private: + vtkOpenGLVolumeProVP1000Mapper(const vtkOpenGLVolumeProVP1000Mapper&); // Not implemented + void operator=(const vtkOpenGLVolumeProVP1000Mapper&); // Not implemented +}; + + +#endif + + + diff --git a/VolumeRendering/vtkOpenGLVolumeShearWarpMapper.cxx b/VolumeRendering/vtkOpenGLVolumeShearWarpMapper.cxx new file mode 100644 index 0000000..198b831 --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeShearWarpMapper.cxx @@ -0,0 +1,434 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeShearWarpMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLVolumeShearWarpMapper.h" +#include "vtkMatrix4x4.h" +#include "vtkVolume.h" +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif +#include "vtkObjectFactory.h" + +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLVolumeShearWarpMapper, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkOpenGLVolumeShearWarpMapper); +#endif + +#ifndef VTK_IMPLEMENT_MESA_CXX +/* +//------------------------------------------------------------------------------ +vtkOpenGLVolumeShearWarpMapper* vtkOpenGLVolumeShearWarpMapper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkObjectFactory::CreateInstance("vtkOpenGLVolumeShearWarpMapper"); + if(ret) + { + return (vtkOpenGLVolumeShearWarpMapper*)ret; + } + // If the factory was unable to create the object, then create it here. + return new vtkOpenGLVolumeShearWarpMapper; +} +*/ +#endif + + + +vtkOpenGLVolumeShearWarpMapper::vtkOpenGLVolumeShearWarpMapper() +{ +} + +vtkOpenGLVolumeShearWarpMapper::~vtkOpenGLVolumeShearWarpMapper() +{ +} + +//#define SEPP +#ifdef SEPP +void vtkOpenGLVolumeShearWarpMapper::RenderTexture(vtkRenderer *ren, vtkVolume *vol) +{ + + if (this->vtkVolumeShearWarpMapper::IntermixIntersectingGeometry) + glDisable(GL_DEPTH_TEST); + + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); +// glLoadIdentity(); + + float warp[16]; + int row, col, i=0; + + for (col=0; col<4; ++col) + for (row=0; row<4; ++row) + warp[i++] = this->WarpMatrix->Element[row][col]; + + glLoadMatrixf(warp); + + + glDisable( GL_LIGHTING ); + glEnable( GL_TEXTURE_2D ); + + GLuint tempIndex; + glGenTextures(1, &tempIndex); + glBindTexture(GL_TEXTURE_2D, tempIndex); + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, this->ImageWidth, this->ImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->ImageData ); + glColor3f( 1.0, 1.0, 1.0 ); + + glDepthMask(0); + const float ZPOS = 0.0f; // texture z position. TODO: make zPos changeable and adjust warp matrix accordingly + + float scaleFactor = 1.0; + +// if (this->ReverseOrder) + scaleFactor = 1.0f / (1.0f - (this->CountK-1) * this->Scale); + + + float px = (float) this->vtkVolumeShearWarpMapper::IntermediateWidth / (float) this->vtkVolumeShearWarpMapper::ImageWidth; + float py = (float) this->vtkVolumeShearWarpMapper::IntermediateHeight / (float) this->vtkVolumeShearWarpMapper::ImageHeight; + + float center[4] = {vol->GetCenter()[0],vol->GetCenter()[1],vol->GetCenter()[2],1.0}; + float ts[4]; + float ws[4]; + + this->ShearMatrix->MultiplyPoint(center,ts); + ts[0] /= ts[3]; + ts[1] /= ts[3]; + ts[2] /= ts[3]; + ts[3] /= ts[3]; + + vtkMatrix4x4 *view = vtkMatrix4x4::New(); + vtkMatrix4x4::Multiply4x4(this->WarpMatrix,this->ViewportMatrix,view); + view->MultiplyPoint(ts,ws); + view->Delete(); + ws[0] /= ws[3]; + ws[1] /= ws[3]; + ws[2] /= ws[3]; + ws[3] /= ws[3]; + /* + b[0] /= b[3]; + b[1] /= b[3]; + b[2] /= b[3]; + b[3] /= b[3]; + */ + float position[4][2]; + + cout << "ts: " << ts[0] << " ... " << ts[1] << "\n"; + cout << "ws: " << ws[0] << " ... " << ws[1] << "\n"; + + position[0][0] = 0;//-b[0]; + position[0][1] = 0;//-b[1]; + + position[1][0] = position[0][0] + this->ImageWidth; + position[1][1] = position[0][1]; + + position[2][0] = position[0][0] + this->ImageWidth; + position[2][1] = position[0][1] + this->ImageHeight; + + position[3][0] = position[0][0]; + position[3][1] = position[0][1] + this->ImageHeight; + + glBegin(GL_QUADS); + + glTexCoord2f(0.0f, 0.0f); + glVertex2fv(position[0]); // bottom left +// glVertex3f(0.0f,0.0f,0.0f); + + glTexCoord2f(1.0, 0.0f); + glVertex2fv(position[1]); // bottom left +// glVertex3f(this->IntermediateWidth,0.0f,0.0f); + + glTexCoord2f(1.0, 1.0); + glVertex2fv(position[2]); // bottom left +// glVertex3f(this->IntermediateWidth,this->IntermediateHeight,0.0f); + + glTexCoord2f(0.0f, 1.0); + glVertex2fv(position[3]); // bottom left +// glVertex3f(0.0f,this->IntermediateHeight,0.0f); + + glEnd(); + +// glDrawPixels(this->ImageWidth,this->ImageHeight,GL_RGBA,GL_UNSIGNED_BYTE,this->ImageData); + + if (this->vtkVolumeShearWarpMapper::IntermixIntersectingGeometry == 1) + { + if (this->IntermediateZBuffer) + { + // glDrawPixels(maxx - minx + 1,maxy - miny + 1,GL_LUMINANCE,GL_FLOAT,this->ZBuffer); + glDrawPixels(this->IntermediateWidth,this->IntermediateHeight,GL_LUMINANCE,GL_FLOAT,this->IntermediateZBuffer); +// glDrawPixels(this->ImageWidth,this->ImageHeight,GL_RGBA,GL_UNSIGNED_BYTE,this->ImageData); + delete [] this->ZBuffer; + delete [] this->IntermediateZBuffer; + } + } + + glDepthMask(1); + + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + + glDisable( GL_TEXTURE_2D ); + glEnable( GL_LIGHTING ); + + if (this->vtkVolumeShearWarpMapper::IntermixIntersectingGeometry) + glEnable(GL_DEPTH_TEST); + +} +#endif + + +#define FRANZ +#ifdef FRANZ +void vtkOpenGLVolumeShearWarpMapper::RenderTexture(vtkRenderer *ren, vtkVolume *vol) +{ + float position[4][4]; + float translation[4]; + + float px,py,sx,sy; +/* float w00,w01,w10,w11; + float w03,w30,w31,w13,w33; + float pc; + float depthVal; + + ren->SetWorldPoint( vol->GetCenter()[0], + vol->GetCenter()[1], + vol->GetCenter()[2], + 1.0 ); + depthVal = ren->GetViewPoint()[2]; + + int *renWinSize = ren->GetRenderWindow()->GetSize(); + float *viewport = ren->GetViewport(); + + // The coefficients of the 2D warp matrix + w00 = WarpMatrix->Element[0][0]; + w01 = WarpMatrix->Element[0][1]; + w10 = WarpMatrix->Element[1][0]; + w11 = WarpMatrix->Element[1][1]; + + w03 = 0.0f;//WarpMatrix->Element[0][3]; + w13 = 0.0f;//WarpMatrix->Element[1][3]; + w30 = WarpMatrix->Element[3][0]; + w31 = WarpMatrix->Element[3][1]; + w33 = WarpMatrix->Element[3][3]; +*/ + float scaleFactor = 1.0f / (1.0f - (this->CountK-1) * this->Scale); + + px = (float) this->vtkVolumeShearWarpMapper::IntermediateWidth / (float) this->vtkVolumeShearWarpMapper::ImageWidth; + py = (float) this->vtkVolumeShearWarpMapper::IntermediateHeight / (float) this->vtkVolumeShearWarpMapper::ImageHeight; +/* + // Warp the edges of the polygon + pc = 1.0f;//0.0f * w30 + 0.0f * w31 + w33; + position[0][0] = (0.0f * w00 + 0.0f * w01 + w03) / pc; + position[0][1] = (0.0f * w10 + 0.0f * w11 + w13) / pc; + + pc = 1.0f;//px * w30 + 0.0f * w31 + w33; + position[1][0] = (px * w00 + 0.0f * w01 + w03) / pc; + position[1][1] = (px * w10 + 0.0f * w11 + w13) / pc; + + pc = 1.0f;//px * w30 + py * w31 + w33; + position[2][0] = (px * w00 + py * w01 + w03) / pc; + position[2][1] = (px * w10 + py * w11 + w13) / pc; + + pc = 1.0f;//0.0f * w30 + py * w31 + w33; + position[3][0] = (0.0f * w00 + py * w01 + w03) / pc; + position[3][1] = (0.0f * w10 + py * w11 + w13) / pc; + + // Compute the translation of the polygon + pc = 1.0f;//px * 0.5f * w30 + py * 0.5f * w31 + w33; + translation[0] = (px * 0.5f * w00 + py * 0.5f * w01 + w03) / pc; + translation[1] = (px * 0.5f * w10 + py * 0.5f * w11 + w13) / pc; + */ + + position[0][0] = 0.0f; + position[0][1] = 0.0f; + position[0][2] = 0.0f; + position[0][3] = 1.0f; + + position[1][0] = px; + position[1][1] = 0.0f; + position[1][2] = 0.0f; + position[1][3] = 1.0f; + + position[2][0] = px; + position[2][1] = py; + position[2][2] = 0.0f; + position[2][3] = 1.0f; + + position[3][0] = 0.0f; + position[3][1] = py; + position[3][2] = 0.0f; + position[3][3] = 1.0f; + + translation[0] = 0.5f*px; + translation[1] = 0.5f*py; + translation[2] = 0.0; + translation[3] = 1.0; + + this->WarpMatrix->MultiplyPoint(position[0],position[0]); + this->WarpMatrix->MultiplyPoint(position[1],position[1]); + this->WarpMatrix->MultiplyPoint(position[2],position[2]); + this->WarpMatrix->MultiplyPoint(position[3],position[3]); + this->WarpMatrix->MultiplyPoint(translation,translation); + + /* + position[0][0] /= position[0][3]; + position[0][1] /= position[0][3]; + position[0][2] /= position[0][3]; + position[0][3] /= position[0][3]; + + position[1][0] /= position[1][3]; + position[1][1] /= position[1][3]; + position[1][2] /= position[1][3]; + position[1][3] /= position[1][3]; + + position[2][0] /= position[2][3]; + position[2][1] /= position[2][3]; + position[2][2] /= position[2][3]; + position[2][3] /= position[2][3]; + + position[3][0] /= position[3][3]; + position[3][1] /= position[3][3]; + position[3][2] /= position[3][3]; + position[3][3] /= position[3][3]; + + translation[0] /= translation[3]; + translation[1] /= translation[3]; + translation[2] /= translation[3]; + translation[3] /= translation[3]; + */ + + + sx = (float) this->vtkVolumeShearWarpMapper::ImageSampleDistance * + (float) this->vtkVolumeShearWarpMapper::ImageWidth / + (float) this->vtkVolumeShearWarpMapper::ImageViewportSize[0] * 2.0f; + sy = (float) this->vtkVolumeShearWarpMapper::ImageSampleDistance * + (float) this->vtkVolumeShearWarpMapper::ImageHeight / + (float) this->vtkVolumeShearWarpMapper::ImageViewportSize[1] * 2.0f; + + float a[4] = {vol->GetCenter()[0],vol->GetCenter()[1],vol->GetCenter()[2],1.0f}; + float b[4]; + this->PerspectiveMatrix->MultiplyPoint(a,b); + + /* + b[0] /= b[3]; + b[1] /= b[3]; + b[2] /= b[3]; + b[3] /= b[3]; + */ + + if (this->vtkVolumeShearWarpMapper::IntermixIntersectingGeometry) + glDisable(GL_DEPTH_TEST); + + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + + glDisable( GL_LIGHTING ); + glEnable( GL_TEXTURE_2D ); + + GLuint tempIndex; + glGenTextures(1, &tempIndex); + glBindTexture(GL_TEXTURE_2D, tempIndex); + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, this->ImageWidth, this->ImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->ImageData ); + glColor3f( 1.0, 1.0, 1.0 ); + + glDepthMask(0); + + // Draw the polygin + glBegin(GL_QUADS); + + glTexCoord2f(0.0f,0.0f); + glVertex4f(b[0] + sx*(position[0][0]-translation[0]),b[1] + sy*(position[0][1]-translation[1]),b[2] + (position[0][2] - translation[2]),b[3] + (position[0][3] - translation[3])); + + glTexCoord2f(px,0.0f); +// glTexCoord2f(1.0f,0.0f); + glVertex4f(b[0] + sx*(position[1][0]-translation[0]),b[1] + sy*(position[1][1]-translation[1]),b[2] + (position[1][2] - translation[2]),b[3] + (position[1][3] - translation[3])); + + glTexCoord2f(px,py); +// glTexCoord2f(1.0f,1.0f); + glVertex4f(b[0] + sx*(position[2][0]-translation[0]),b[1] + sy*(position[2][1]-translation[1]),b[2] + (position[2][2] - translation[2]),b[3] + (position[2][3] - translation[3])); + + glTexCoord2f(0.0f,py); +// glTexCoord2f(0.0f,1.0f); + glVertex4f(b[0] + sx*(position[3][0]-translation[0]),b[1] + sy*(position[3][1]-translation[1]),b[2] + (position[3][2] - translation[2]),b[3] + (position[3][3] - translation[3])); + + glEnd(); + + if (this->Debug == 1) + glDrawPixels(this->ImageWidth,this->ImageHeight,GL_RGBA,GL_UNSIGNED_BYTE,this->ImageData); + + if (this->vtkVolumeShearWarpMapper::IntermixIntersectingGeometry == 1) + { + if (this->IntermediateZBuffer) + { + if (this->Debug == 2) + glDrawPixels(this->ZBufferSize[0],this->ZBufferSize[1],GL_LUMINANCE,GL_FLOAT,this->ZBuffer); + else if (this->Debug == 3) + glDrawPixels(this->ImageSampleDistance*this->IntermediateWidth,this->ImageSampleDistance*this->IntermediateHeight,GL_LUMINANCE,GL_FLOAT,this->IntermediateZBuffer); + + delete [] this->ZBuffer; + delete [] this->IntermediateZBuffer; + } + } + + glDepthMask(1); + + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + + glDisable( GL_TEXTURE_2D ); + glEnable( GL_LIGHTING ); + + if (this->vtkVolumeShearWarpMapper::IntermixIntersectingGeometry) + glEnable(GL_DEPTH_TEST); + +} +#endif + +// Print the vtkOpenGLVolumeShearWarpMapper +void vtkOpenGLVolumeShearWarpMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/VolumeRendering/vtkOpenGLVolumeShearWarpMapper.h b/VolumeRendering/vtkOpenGLVolumeShearWarpMapper.h new file mode 100644 index 0000000..dda2cd3 --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeShearWarpMapper.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeShearWarpMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLVolumeShearWarpMapper - Class for a Shear Warp Volume Mapper +// +// .SECTION Description +// vtkVolumeShearWarpMapper is a base class for volume mappers using +// the shear-warp factorization algorithm. +// +// .SECTION see also +// vtkVolumeMapper vtkVolumeShearWarpMapper +// +// .SECTION Thanks +// Thanks to Stefan Bruckner for developing and contributing this code +// and to Namkug Kim for some fixing and tidying of the code +// +// .SECTION References +// P. Lacroute. "Fast Volume Rendering Using a Shear- +// Warp Factorization of the Viewing Transformation" +// PhD thesis, Stanford University, 1995. +// +// P. Lacroute and M. Levoy. "Fast volume rendering using +// a shear-warp factorization of the viewing transformation" +// Proceedings of the 21st annual conference +// on Computer graphics and interactive techniques, +// pages 451-458, 1994. +// +// "The InverseWarp: Non-Invasive Integration of Shear-Warp +// Volume Rendering into Polygon Rendering Pipelines" +// Stefan Bruckner, Dieter Schmalstiegy, Helwig Hauserz, +// M. Eduard Groller + +#ifndef __vtkOpenGLVolumeShearWarpMapper_h +#define __vtkOpenGLVolumeShearWarpMapper_h + +#include "vtkVolumeShearWarpMapper.h" + +class VTK_VOLUMERENDERING_EXPORT vtkOpenGLVolumeShearWarpMapper : public vtkVolumeShearWarpMapper +{ +public: +// vtkTypeMacro(vtkOpenGLVolumeShearWarpMapper,vtkVolumeShearWarpMapper); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkOpenGLVolumeShearWarpMapper *New(); + vtkTypeRevisionMacro(vtkOpenGLVolumeShearWarpMapper,vtkVolumeShearWarpMapper); + +protected: + vtkOpenGLVolumeShearWarpMapper(); + ~vtkOpenGLVolumeShearWarpMapper(); + + virtual void RenderTexture(vtkRenderer *ren, vtkVolume *vol); + +private: + vtkOpenGLVolumeShearWarpMapper(const vtkOpenGLVolumeShearWarpMapper&); // Not implemented. + void operator=(const vtkOpenGLVolumeShearWarpMapper&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkOpenGLVolumeTextureMapper2D.cxx b/VolumeRendering/vtkOpenGLVolumeTextureMapper2D.cxx new file mode 100644 index 0000000..288cb60 --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeTextureMapper2D.cxx @@ -0,0 +1,203 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeTextureMapper2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOpenGLVolumeTextureMapper2D.h" + +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPlaneCollection.h" +#include "vtkTimerLog.h" +#include "vtkVolume.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" +#endif + + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLVolumeTextureMapper2D, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkOpenGLVolumeTextureMapper2D); +#endif + + + +vtkOpenGLVolumeTextureMapper2D::vtkOpenGLVolumeTextureMapper2D() +{ +} + +vtkOpenGLVolumeTextureMapper2D::~vtkOpenGLVolumeTextureMapper2D() +{ +} + +void vtkOpenGLVolumeTextureMapper2D::Render(vtkRenderer *ren, vtkVolume *vol) +{ + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + vtkPlaneCollection *clipPlanes; + vtkPlane *plane; + int i, numClipPlanes = 0; + double planeEquation[4]; + + this->Timer->StartTimer(); + + // Let the superclass take care of some initialization + this->vtkVolumeTextureMapper2D::InitializeRender( ren, vol ); + + // build transformation + vol->GetMatrix(matrix); + matrix->Transpose(); + + // Use the OpenGL clip planes + clipPlanes = this->ClippingPlanes; + if ( clipPlanes ) + { + numClipPlanes = clipPlanes->GetNumberOfItems(); + if (numClipPlanes > 6) + { + vtkErrorMacro(<< "OpenGL guarantees only 6 additional clipping planes"); + } + + for (i = 0; i < numClipPlanes; i++) + { + glEnable((GLenum)(GL_CLIP_PLANE0+i)); + + plane = (vtkPlane *)clipPlanes->GetItemAsObject(i); + + planeEquation[0] = plane->GetNormal()[0]; + planeEquation[1] = plane->GetNormal()[1]; + planeEquation[2] = plane->GetNormal()[2]; + planeEquation[3] = -(planeEquation[0]*plane->GetOrigin()[0]+ + planeEquation[1]*plane->GetOrigin()[1]+ + planeEquation[2]*plane->GetOrigin()[2]); + glClipPlane((GLenum)(GL_CLIP_PLANE0+i),planeEquation); + } + } + + + // insert model transformation + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glMultMatrixd(matrix->Element[0]); + + // Turn lighting off - the polygon textures already have illumination + glDisable( GL_LIGHTING ); + + // Turn texturing on so that we can draw the textured polygons + glEnable( GL_TEXTURE_2D ); + +#ifdef GL_VERSION_1_1 + GLuint tempIndex; + glGenTextures(1, &tempIndex); + glBindTexture(GL_TEXTURE_2D, tempIndex); +#endif + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + glColor3f( 1.0, 1.0, 1.0 ); + + this->GenerateTexturesAndRenderQuads( ren, vol ); + + // pop transformation matrix + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + matrix->Delete(); + + glDisable( GL_TEXTURE_2D ); + +#ifdef GL_VERSION_1_1 + glFlush(); + glDeleteTextures(1, &tempIndex); +#endif + + // Turn lighting back on + glEnable( GL_LIGHTING ); + + if ( clipPlanes ) + { + for (i = 0; i < numClipPlanes; i++) + { + glDisable((GLenum)(GL_CLIP_PLANE0+i)); + } + } + + this->Timer->StopTimer(); + + this->TimeToDraw = (float)this->Timer->GetElapsedTime(); + + // If the timer is not accurate enough, set it to a small + // time so that it is not zero + if ( this->TimeToDraw == 0.0 ) + { + this->TimeToDraw = 0.0001; + } +} + +void vtkOpenGLVolumeTextureMapper2D::RenderQuads( int numQuads, + float *v, + float *t, + unsigned char *texture, + int size[2], int reverseFlag ) +{ +#ifdef GL_VERSION_1_1 + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, size[0], size[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, texture ); +#else + glTexImage2D( GL_TEXTURE_2D, 0, 4, size[0], size[1], + 0, GL_RGBA, GL_UNSIGNED_BYTE, texture ); +#endif + + glBegin( GL_QUADS ); + + float *tptr, *vptr; + int i, j; + + if ( reverseFlag ) + { + for ( i = 0; i < numQuads; i++ ) + { + tptr = t+2*4*(numQuads-i-1); + vptr = v+3*4*(numQuads-i-1); + for ( j = 0; j < 4; j++ ) + { + glTexCoord2fv( tptr ); + glVertex3fv( vptr ); + tptr += 2; + vptr += 3; + } + } + } + else + { + tptr = t; + vptr = v; + for ( i = 0; i < numQuads*4; i++ ) + { + glTexCoord2fv( tptr ); + glVertex3fv( vptr ); + tptr += 2; + vptr += 3; + } + } + + glEnd(); +} + +// Print the vtkOpenGLVolumeTextureMapper2D +void vtkOpenGLVolumeTextureMapper2D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} + diff --git a/VolumeRendering/vtkOpenGLVolumeTextureMapper2D.h b/VolumeRendering/vtkOpenGLVolumeTextureMapper2D.h new file mode 100644 index 0000000..f9e5a22 --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeTextureMapper2D.h @@ -0,0 +1,62 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeTextureMapper2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLVolumeTextureMapper2D - Abstract class for a volume mapper + +// .SECTION Description +// vtkOpenGLVolumeTextureMapper2D renders a volume using 2D texture mapping. + + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkOpenGLVolumeTextureMapper2D_h +#define __vtkOpenGLVolumeTextureMapper2D_h + +#include "vtkVolumeTextureMapper2D.h" + +class VTK_VOLUMERENDERING_EXPORT vtkOpenGLVolumeTextureMapper2D : public vtkVolumeTextureMapper2D +{ +public: + vtkTypeRevisionMacro(vtkOpenGLVolumeTextureMapper2D,vtkVolumeTextureMapper2D); + void PrintSelf( ostream& os, vtkIndent indent ); + + static vtkOpenGLVolumeTextureMapper2D *New(); + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol); + + void RenderQuads( int count, float *v, float *t, + unsigned char *texture, int size[2], int reverseFlag); + +//ETX + +protected: + vtkOpenGLVolumeTextureMapper2D(); + ~vtkOpenGLVolumeTextureMapper2D(); + +private: + vtkOpenGLVolumeTextureMapper2D(const vtkOpenGLVolumeTextureMapper2D&); // Not implemented. + void operator=(const vtkOpenGLVolumeTextureMapper2D&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkOpenGLVolumeTextureMapper3D.cxx b/VolumeRendering/vtkOpenGLVolumeTextureMapper3D.cxx new file mode 100644 index 0000000..659360c --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeTextureMapper3D.cxx @@ -0,0 +1,1943 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeTextureMapper3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkWindows.h" +#include "vtkOpenGLVolumeTextureMapper3D.h" + +#include "vtkImageData.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPlaneCollection.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTimerLog.h" +#include "vtkVolumeProperty.h" +#include "vtkTransform.h" +#include "vtkLightCollection.h" +#include "vtkLight.h" +#include "vtkCamera.h" +#include "vtkMath.h" +#include "vtkOpenGLExtensionManager.h" +#include "vtkgl.h" + +extern const char* vtkVolumeTextureMapper3D_OneComponentShadeFP; +extern const char* vtkVolumeTextureMapper3D_OneComponentNoShadeFP; +extern const char* vtkVolumeTextureMapper3D_TwoDependentNoShadeFP; +extern const char* vtkVolumeTextureMapper3D_TwoDependentShadeFP; +extern const char* vtkVolumeTextureMapper3D_FourDependentNoShadeFP; +extern const char* vtkVolumeTextureMapper3D_FourDependentShadeFP; + +// Apple OS X doesn't have glTexImage3DEXT, but it does have glTexImage3D +#if defined(__APPLE__) && defined(GL_VERSION_1_4) +#ifdef TexImage3DEXT +#undef TexImage3DEXT +#endif +#define TexImage3DEXT TexImage3D +#ifdef TEXTURE_3D_EXT +#undef TEXTURE_3D_EXT +#endif +#define TEXTURE_3D_EXT TEXTURE_3D +#endif /* defined(__APPLE__) && defined(GL_VERSION_1_4) */ + +//extern "C" void (*glXGetProcAddressARB(const GLubyte *procName))( void ); + +//#ifdef _WIN32 + +//#endif + +#define PrintError(S) \ + { \ + GLenum errorCode; \ + if ( (errorCode = glGetError()) != GL_NO_ERROR ) \ + { \ + cout << S << endl; \ + cout << "ERROR" << endl; \ + switch (errorCode) \ + { \ + case GL_INVALID_ENUM: cout << "invalid enum" << endl; break; \ + case GL_INVALID_VALUE: cout << "invalid value" << endl; break; \ + case GL_INVALID_OPERATION: cout << "invalid operation" << endl; break; \ + case GL_STACK_OVERFLOW: cout << "stack overflow" << endl; break; \ + case GL_STACK_UNDERFLOW: cout << "stack underflow" << endl; break; \ + case GL_OUT_OF_MEMORY: cout << "out of memory" << endl; break; \ + default: cout << "unknown error" << endl; \ + } \ + }} + +//#ifndef VTK_IMPLEMENT_MESA_CXX +vtkCxxRevisionMacro(vtkOpenGLVolumeTextureMapper3D, "$Revision: 1.7.2.1 $"); +vtkStandardNewMacro(vtkOpenGLVolumeTextureMapper3D); +//#endif + + + +vtkOpenGLVolumeTextureMapper3D::vtkOpenGLVolumeTextureMapper3D() +{ + this->Initialized = 0; + this->Volume1Index = 0; + this->Volume2Index = 0; + this->Volume3Index = 0; + this->ColorLookupIndex = 0; + this->RenderWindow = NULL; +} + +vtkOpenGLVolumeTextureMapper3D::~vtkOpenGLVolumeTextureMapper3D() +{ +} + +// Release the graphics resources used by this texture. +void vtkOpenGLVolumeTextureMapper3D::ReleaseGraphicsResources(vtkWindow + *renWin) +{ + if (( this->Volume1Index || this->Volume2Index || + this->Volume3Index || this->ColorLookupIndex) && renWin) + { + ((vtkRenderWindow *) renWin)->MakeCurrent(); +#ifdef GL_VERSION_1_1 + // free any textures + this->DeleteTextureIndex( &this->Volume1Index ); + this->DeleteTextureIndex( &this->Volume2Index ); + this->DeleteTextureIndex( &this->Volume3Index ); + this->DeleteTextureIndex( &this->ColorLookupIndex ); + this->DeleteTextureIndex( &this->AlphaLookupIndex ); +#endif + } + this->Volume1Index = 0; + this->Volume2Index = 0; + this->Volume3Index = 0; + this->ColorLookupIndex = 0; + this->RenderWindow = NULL; + this->Modified(); +} + +void vtkOpenGLVolumeTextureMapper3D::Render(vtkRenderer *ren, vtkVolume *vol) +{ + ren->GetRenderWindow()->MakeCurrent(); + + if ( !this->Initialized ) + { + this->Initialize(); + } + + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NO_METHOD ) + { + vtkErrorMacro( "required extensions not supported" ); + return; + } + + + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + vtkPlaneCollection *clipPlanes; + vtkPlane *plane; + int numClipPlanes = 0; + double planeEquation[4]; + + + // build transformation + vol->GetMatrix(matrix); + matrix->Transpose(); + + glPushAttrib(GL_ENABLE_BIT | + GL_COLOR_BUFFER_BIT | + GL_STENCIL_BUFFER_BIT | + GL_DEPTH_BUFFER_BIT | + GL_POLYGON_BIT | + GL_TEXTURE_BIT); + + int i; + + // Use the OpenGL clip planes + clipPlanes = this->ClippingPlanes; + if ( clipPlanes ) + { + numClipPlanes = clipPlanes->GetNumberOfItems(); + if (numClipPlanes > 6) + { + vtkErrorMacro(<< "OpenGL guarantees only 6 additional clipping planes"); + } + + for (i = 0; i < numClipPlanes; i++) + { + glEnable((GLenum)(GL_CLIP_PLANE0+i)); + + plane = (vtkPlane *)clipPlanes->GetItemAsObject(i); + + planeEquation[0] = plane->GetNormal()[0]; + planeEquation[1] = plane->GetNormal()[1]; + planeEquation[2] = plane->GetNormal()[2]; + planeEquation[3] = -(planeEquation[0]*plane->GetOrigin()[0]+ + planeEquation[1]*plane->GetOrigin()[1]+ + planeEquation[2]*plane->GetOrigin()[2]); + glClipPlane((GLenum)(GL_CLIP_PLANE0+i),planeEquation); + } + } + + + + // insert model transformation + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glMultMatrixd(matrix->Element[0]); + + glColor4f( 1.0, 1.0, 1.0, 1.0 ); + + // Turn lighting off - the polygon textures already have illumination + glDisable( GL_LIGHTING ); + + switch ( this->RenderMethod ) + { + case vtkVolumeTextureMapper3D::NVIDIA_METHOD: + this->RenderNV(ren,vol); + break; + case vtkVolumeTextureMapper3D::FRAGMENT_PROGRAM_METHOD: + this->RenderFP(ren,vol); + break; + } + + // pop transformation matrix + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + + matrix->Delete(); + glPopAttrib(); + + + glFlush(); + glFinish(); + + + this->Timer->StopTimer(); + + this->TimeToDraw = (float)this->Timer->GetElapsedTime(); + + // If the timer is not accurate enough, set it to a small + // time so that it is not zero + if ( this->TimeToDraw == 0.0 ) + { + this->TimeToDraw = 0.0001; + } +} + +void vtkOpenGLVolumeTextureMapper3D::RenderFP( vtkRenderer *ren, vtkVolume *vol ) +{ + glAlphaFunc (GL_GREATER, (GLclampf) 0); + glEnable (GL_ALPHA_TEST); + + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + int components = this->GetInput()->GetNumberOfScalarComponents(); + switch ( components ) + { + case 1: + if ( !vol->GetProperty()->GetShade() ) + { + this->RenderOneIndependentNoShadeFP(ren,vol); + } + else + { + this->RenderOneIndependentShadeFP(ren,vol); + } + break; + + case 2: + if ( !vol->GetProperty()->GetShade() ) + { + this->RenderTwoDependentNoShadeFP(ren,vol); + } + else + { + this->RenderTwoDependentShadeFP(ren,vol); + } + break; + + case 3: + case 4: + if ( !vol->GetProperty()->GetShade() ) + { + this->RenderFourDependentNoShadeFP(ren,vol); + } + else + { + this->RenderFourDependentShadeFP(ren,vol); + } + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glDisable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glDisable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glDisable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderNV( vtkRenderer *ren, vtkVolume *vol ) +{ + glAlphaFunc (GL_GREATER, (GLclampf) 0); + glEnable (GL_ALPHA_TEST); + + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + int components = this->GetInput()->GetNumberOfScalarComponents(); + switch ( components ) + { + case 1: + if ( !vol->GetProperty()->GetShade() ) + { + this->RenderOneIndependentNoShadeNV(ren,vol); + } + else + { + this->RenderOneIndependentShadeNV(ren,vol); + } + break; + + case 2: + if ( !vol->GetProperty()->GetShade() ) + { + this->RenderTwoDependentNoShadeNV(ren,vol); + } + else + { + this->RenderTwoDependentShadeNV(ren,vol); + } + break; + + case 3: + case 4: + if ( !vol->GetProperty()->GetShade() ) + { + this->RenderFourDependentNoShadeNV(ren,vol); + } + else + { + this->RenderFourDependentShadeNV(ren,vol); + } + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glDisable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glDisable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glDisable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + + glDisable( vtkgl::TEXTURE_SHADER_NV ); + + glDisable(vtkgl::REGISTER_COMBINERS_NV); +} + +void vtkOpenGLVolumeTextureMapper3D::DeleteTextureIndex( GLuint *index ) +{ + if (glIsTexture(*index)) + { + GLuint tempIndex; + tempIndex = *index; + glDeleteTextures(1, &tempIndex); + *index = 0; + } +} + +void vtkOpenGLVolumeTextureMapper3D::CreateTextureIndex( GLuint *index ) +{ + GLuint tempIndex=0; + glGenTextures(1, &tempIndex); + *index = (long) tempIndex; +} + +void vtkOpenGLVolumeTextureMapper3D::RenderPolygons( vtkRenderer *ren, + vtkVolume *vol, + int stages[4] ) +{ + vtkRenderWindow *renWin = ren->GetRenderWindow(); + + if ( renWin->CheckAbortStatus() ) + { + return; + } + + double bounds[27][6]; + float distance2[27]; + + int numIterations; + int i, j, k; + + // No cropping case - render the whole thing + if ( !this->Cropping ) + { + // Use the input data bounds - we'll take care of the volume's + // matrix during rendering + this->GetInput()->GetBounds(bounds[0]); + numIterations = 1; + } + // Simple cropping case - render the subvolume + else if ( this->CroppingRegionFlags == 0x2000 ) + { + this->GetCroppingRegionPlanes(bounds[0]); + numIterations = 1; + } + // Complex cropping case - render each region in back-to-front order + else + { + // Get the camera position + double camPos[4]; + ren->GetActiveCamera()->GetPosition(camPos); + + double volBounds[6]; + this->GetInput()->GetBounds(volBounds); + + // Pass camera through inverse volume matrix + // so that we are in the same coordinate system + vtkMatrix4x4 *volMatrix = vtkMatrix4x4::New(); + vol->GetMatrix( volMatrix ); + camPos[3] = 1.0; + volMatrix->Invert(); + volMatrix->MultiplyPoint( camPos, camPos ); + volMatrix->Delete(); + if ( camPos[3] ) + { + camPos[0] /= camPos[3]; + camPos[1] /= camPos[3]; + camPos[2] /= camPos[3]; + } + + // These are the region limits for x (first four), y (next four) and + // z (last four). The first region limit is the lower bound for + // that axis, the next two are the region planes along that axis, and + // the final one in the upper bound for that axis. + float limit[12]; + for ( i = 0; i < 3; i++ ) + { + limit[i*4 ] = volBounds[i*2]; + limit[i*4+1] = this->CroppingRegionPlanes[i*2]; + limit[i*4+2] = this->CroppingRegionPlanes[i*2+1]; + limit[i*4+3] = volBounds[i*2+1]; + } + + // For each of the 27 possible regions, find out if it is enabled, + // and if so, compute the bounds and the distance from the camera + // to the center of the region. + int numRegions = 0; + int region; + for ( region = 0; region < 27; region++ ) + { + int regionFlag = 1<<region; + + if ( this->CroppingRegionFlags & regionFlag ) + { + // what is the coordinate in the 3x3x3 grid + int loc[3]; + loc[0] = region%3; + loc[1] = (region/3)%3; + loc[2] = (region/9)%3; + + // compute the bounds and center + float center[3]; + for ( i = 0; i < 3; i++ ) + { + bounds[numRegions][i*2 ] = limit[4*i+loc[i]]; + bounds[numRegions][i*2+1] = limit[4*i+loc[i]+1]; + center[i] = + (bounds[numRegions][i*2 ] + + bounds[numRegions][i*2+1])/2.0; + } + + // compute the distance squared to the center + distance2[numRegions] = + (camPos[0]-center[0])*(camPos[0]-center[0]) + + (camPos[1]-center[1])*(camPos[1]-center[1]) + + (camPos[2]-center[2])*(camPos[2]-center[2]); + + // we've added one region + numRegions++; + } + } + + // Do a quick bubble sort on distance + for ( i = 1; i < numRegions; i++ ) + { + for ( j = i; j > 0 && distance2[j] > distance2[j-1]; j-- ) + { + float tmpBounds[6]; + float tmpDistance2; + + for ( k = 0; k < 6; k++ ) + { + tmpBounds[k] = bounds[j][k]; + } + tmpDistance2 = distance2[j]; + + for ( k = 0; k < 6; k++ ) + { + bounds[j][k] = bounds[j-1][k]; + } + distance2[j] = distance2[j-1]; + + for ( k = 0; k < 6; k++ ) + { + bounds[j-1][k] = tmpBounds[k]; + } + distance2[j-1] = tmpDistance2; + + } + } + + numIterations = numRegions; + } + + // loop over all regions we need to render + for ( int loop = 0; + loop < numIterations; + loop++ ) + { + // Compute the set of polygons for this region + // according to the bounds + this->ComputePolygons( ren, vol, bounds[loop] ); + + // Loop over the polygons + for ( i = 0; i < this->NumberOfPolygons; i++ ) + { + if ( i%64 == 1 ) + { + glFlush(); + glFinish(); + } + + if ( renWin->CheckAbortStatus() ) + { + return; + } + + float *ptr = this->PolygonBuffer + 36*i; + + glBegin( GL_TRIANGLE_FAN ); + + for ( j = 0; j < 6; j++ ) + { + if ( ptr[0] < 0.0 ) + { + break; + } + + for ( k = 0; k < 4; k++ ) + { + if ( stages[k] ) + { + vtkgl::MultiTexCoord3fvARB( vtkgl::TEXTURE0_ARB + k, ptr ); + } + } + glVertex3fv( ptr+3 ); + + ptr += 6; + } + glEnd(); + } + } +} + +void vtkOpenGLVolumeTextureMapper3D::Setup3DTextureParameters( vtkVolumeProperty *property ) +{ + if ( property->GetInterpolationType() == VTK_NEAREST_INTERPOLATION ) + { + glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + } + else + { + glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + } + glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameterf( vtkgl::TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP ); +} + +void vtkOpenGLVolumeTextureMapper3D::SetupOneIndependentTextures( vtkRenderer *vtkNotUsed(ren), + vtkVolume *vol ) +{ + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glDisable( GL_TEXTURE_2D ); + glEnable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glEnable( vtkgl::TEXTURE_SHADER_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glDisable( GL_TEXTURE_2D ); + glEnable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glEnable( vtkgl::TEXTURE_SHADER_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT); + } + + // Update the volume containing the 2 byte scalar / gradient magnitude + if ( this->UpdateVolumes( vol ) || !this->Volume1Index || !this->Volume2Index ) + { + int dim[3]; + this->GetVolumeDimensions(dim); + this->DeleteTextureIndex(&this->Volume3Index); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL); + this->DeleteTextureIndex(&this->Volume1Index); + this->CreateTextureIndex(&this->Volume1Index); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index); + vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume1 ); + + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL); + this->DeleteTextureIndex(&this->Volume2Index); + this->CreateTextureIndex(&this->Volume2Index); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index); + vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGBA8, dim[0], dim[1], dim[2], 0, + GL_RGB, GL_UNSIGNED_BYTE, this->Volume2 ); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index); + this->Setup3DTextureParameters( vol->GetProperty() ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index); + this->Setup3DTextureParameters( vol->GetProperty() ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glEnable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, + vtkgl::DEPENDENT_AR_TEXTURE_2D_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE0_ARB); + } + + // Update the dependent 2D color table mapping scalar value and + // gradient magnitude to RGBA + if ( this->UpdateColorLookup( vol ) || !this->ColorLookupIndex ) + { + this->DeleteTextureIndex( &this->ColorLookupIndex ); + this->DeleteTextureIndex( &this->AlphaLookupIndex ); + + this->CreateTextureIndex( &this->ColorLookupIndex ); + glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, + GL_RGBA, GL_UNSIGNED_BYTE, this->ColorLookup ); + } + + glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); +} + +void vtkOpenGLVolumeTextureMapper3D::SetupRegisterCombinersNoShadeNV( vtkRenderer *vtkNotUsed(ren), + vtkVolume *vtkNotUsed(vol), + int components ) +{ + if ( components < 3 ) + { + vtkgl::ActiveTextureARB(vtkgl::TEXTURE2_ARB); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, GL_NONE); + + if ( components == 1 ) + { + vtkgl::ActiveTextureARB(vtkgl::TEXTURE3_ARB); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, GL_NONE); + } + } + + + glEnable(vtkgl::REGISTER_COMBINERS_NV); + vtkgl::CombinerParameteriNV(vtkgl::NUM_GENERAL_COMBINERS_NV, 1); + vtkgl::CombinerParameteriNV(vtkgl::COLOR_SUM_CLAMP_NV, GL_TRUE); + + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_A_NV, GL_ZERO, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_B_NV, GL_ZERO, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_C_NV, GL_ZERO, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + if ( components < 3 ) + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_D_NV, vtkgl::TEXTURE1_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + else + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_D_NV, vtkgl::TEXTURE0_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + + if ( components == 1 ) + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE1_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA); + } + else + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE3_ARB, vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA); + } +} + +void vtkOpenGLVolumeTextureMapper3D::SetupRegisterCombinersShadeNV( vtkRenderer *ren, + vtkVolume *vol, + int components ) +{ + if ( components == 1 ) + { + vtkgl::ActiveTextureARB(vtkgl::TEXTURE3_ARB); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, GL_NONE); + } + + GLfloat white[4] = {1,1,1,1}; + + GLfloat lightDirection[2][4]; + GLfloat lightDiffuseColor[2][4]; + GLfloat lightSpecularColor[2][4]; + GLfloat halfwayVector[2][4]; + GLfloat ambientColor[4]; + + // Gather information about the light sources. Although we gather info for multiple light sources, + // in this case we will only use the first one, and will duplicate it (in opposite direction) to + // approximate two-sided lighting. + this->GetLightInformation( ren, vol, lightDirection, lightDiffuseColor, + lightSpecularColor, halfwayVector, ambientColor ); + + float specularPower = vol->GetProperty()->GetSpecularPower(); + + glEnable(vtkgl::REGISTER_COMBINERS_NV); + glEnable( vtkgl::PER_STAGE_CONSTANTS_NV ); + vtkgl::CombinerParameteriNV(vtkgl::NUM_GENERAL_COMBINERS_NV, 8); + vtkgl::CombinerParameteriNV(vtkgl::COLOR_SUM_CLAMP_NV, GL_TRUE); + + // Stage 0 + // + // N dot L is computed into vtkgl::SPARE0_NV + // -N dot L is computed into vtkgl::SPARE1_NV + // + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER0_NV, vtkgl::CONSTANT_COLOR0_NV, lightDirection[0] ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NORMAL_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NEGATE_NV, GL_RGB ); + + vtkgl::CombinerOutputNV( vtkgl::COMBINER0_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, vtkgl::DISCARD_NV, + GL_NONE, GL_NONE, GL_TRUE, GL_TRUE, GL_FALSE ); + + // Stage 1 + // + // lightColor * max( 0, (N dot L)) + lightColor * max( 0, (-N dot L)) is computed into vtkgl::SPARE0_NV + // + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER1_NV, vtkgl::CONSTANT_COLOR0_NV, lightDiffuseColor[0] ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + + vtkgl::CombinerOutputNV( vtkgl::COMBINER1_NV, GL_RGB, vtkgl::DISCARD_NV, vtkgl::DISCARD_NV, + vtkgl::SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE ); + + // Stage 2 + // + // result from Stage 1 is added to the ambient color and stored in vtkgl::PRIMARY_COLOR_NV + // + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER2_NV, vtkgl::CONSTANT_COLOR0_NV, white ); + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER2_NV, vtkgl::CONSTANT_COLOR1_NV, ambientColor ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::CONSTANT_COLOR1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + + vtkgl::CombinerOutputNV( vtkgl::COMBINER2_NV, GL_RGB, vtkgl::DISCARD_NV, vtkgl::DISCARD_NV, + vtkgl::PRIMARY_COLOR_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE ); + + // Stage 3 + // + // N dot H is computed into vtkgl::SPARE0_NV + // -N dot H is computed into vtkgl::SPARE1_NV + // + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER3_NV, vtkgl::CONSTANT_COLOR0_NV, halfwayVector[0] ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NORMAL_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::EXPAND_NORMAL_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::TEXTURE2_ARB, vtkgl::EXPAND_NEGATE_NV, GL_RGB ); + + vtkgl::CombinerOutputNV( vtkgl::COMBINER3_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, + vtkgl::DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_TRUE, GL_FALSE ); + + // Stage 4 + // + // if the specular power is greater than 1, then + // + // N dot H squared is computed into vtkgl::SPARE0_NV + // -N dot H squared is computed into vtkgl::SPARE1_NV + // + // otherwise these registers are simply multiplied by white + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER4_NV, vtkgl::CONSTANT_COLOR0_NV, white ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + if ( specularPower > 1.0 ) + { + vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + else + { + vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + + vtkgl::CombinerOutputNV( vtkgl::COMBINER4_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, vtkgl::DISCARD_NV, + GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE ); + + // Stage 5 + // + // if the specular power is greater than 3, then + // + // N dot H to the fourth is computed into vtkgl::SPARE0_NV + // -N dot H to the fourth is computed into vtkgl::SPARE1_NV + // + // otherwise these registers are simply multiplied by white + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER5_NV, vtkgl::CONSTANT_COLOR0_NV, white ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + if ( specularPower > 3.0 ) + { + vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + else + { + vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + + vtkgl::CombinerOutputNV( vtkgl::COMBINER5_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, vtkgl::DISCARD_NV, + GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE ); + + // Stage 6 + // + // if the specular power is greater than 6, then + // + // N dot H to the eighth is computed into vtkgl::SPARE0_NV + // -N dot H to the eighth is computed into vtkgl::SPARE1_NV + // + // otherwise these registers are simply multiplied by white + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER6_NV, vtkgl::CONSTANT_COLOR0_NV, white ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + + if ( specularPower > 6.0 ) + { + vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + else + { + vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + + vtkgl::CombinerOutputNV( vtkgl::COMBINER6_NV, GL_RGB, vtkgl::SPARE0_NV, vtkgl::SPARE1_NV, + vtkgl::DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE ); + + + // Stage 7 + // + // Add the two specular contributions and multiply each by the specular color. + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER7_NV, vtkgl::CONSTANT_COLOR0_NV, lightSpecularColor[0] ); + vtkgl::CombinerStageParameterfvNV( vtkgl::COMBINER7_NV, vtkgl::CONSTANT_COLOR1_NV, lightSpecularColor[1] ); + + vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_A_NV, + vtkgl::SPARE0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_B_NV, + vtkgl::CONSTANT_COLOR0_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_C_NV, + vtkgl::SPARE1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::CombinerInputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::VARIABLE_D_NV, + vtkgl::CONSTANT_COLOR1_NV, vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + + vtkgl::CombinerOutputNV( vtkgl::COMBINER7_NV, GL_RGB, vtkgl::DISCARD_NV, + vtkgl::DISCARD_NV, vtkgl::SPARE0_NV, + GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE ); + + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_A_NV, vtkgl::PRIMARY_COLOR_NV, + vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + if ( components < 3 ) + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_B_NV, vtkgl::TEXTURE1_ARB, + vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + else + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_B_NV, vtkgl::TEXTURE0_ARB, + vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + } + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_C_NV, GL_ZERO, + vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_D_NV, vtkgl::SPARE0_NV, + vtkgl::UNSIGNED_IDENTITY_NV, GL_RGB ); + + if ( components == 1 ) + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE1_ARB, + vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA); + } + else + { + vtkgl::FinalCombinerInputNV(vtkgl::VARIABLE_G_NV, vtkgl::TEXTURE3_ARB, + vtkgl::UNSIGNED_IDENTITY_NV, GL_ALPHA); + } + +} + +void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentNoShadeNV( vtkRenderer *ren, + vtkVolume *vol ) +{ + this->SetupOneIndependentTextures( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + this->SetupRegisterCombinersNoShadeNV( ren, vol, 1 ); + + int stages[4] = {1,0,0,0}; + this->RenderPolygons( ren, vol, stages ); +} + + +void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentShadeNV( vtkRenderer *ren, + vtkVolume *vol ) +{ + this->SetupOneIndependentTextures( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + this->SetupRegisterCombinersShadeNV( ren, vol, 1 ); + + int stages[4] = {1,0,1,0}; + this->RenderPolygons( ren, vol, stages ); +} + + +void vtkOpenGLVolumeTextureMapper3D::SetupTwoDependentTextures( vtkRenderer *vtkNotUsed(ren), + vtkVolume *vol ) +{ + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glDisable( GL_TEXTURE_2D ); + glEnable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glEnable( vtkgl::TEXTURE_SHADER_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glDisable( GL_TEXTURE_2D ); + glEnable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glEnable( vtkgl::TEXTURE_SHADER_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT); + } + + // Update the volume containing the 3 byte scalars / gradient magnitude + if ( this->UpdateVolumes( vol ) || !this->Volume1Index || !this->Volume2Index ) + { + int dim[3]; + this->GetVolumeDimensions(dim); + this->DeleteTextureIndex(&this->Volume3Index); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL); + this->DeleteTextureIndex(&this->Volume1Index); + this->CreateTextureIndex(&this->Volume1Index); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index); + vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGB8, dim[0], dim[1], dim[2], 0, + GL_RGB, GL_UNSIGNED_BYTE, this->Volume1 ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL); + this->DeleteTextureIndex(&this->Volume2Index); + this->CreateTextureIndex(&this->Volume2Index); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index); + vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGBA8, dim[0], dim[1], dim[2], 0, + GL_RGB, GL_UNSIGNED_BYTE, this->Volume2 ); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index); + this->Setup3DTextureParameters( vol->GetProperty() ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index); + this->Setup3DTextureParameters( vol->GetProperty() ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glEnable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, + vtkgl::DEPENDENT_AR_TEXTURE_2D_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE0_ARB); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB ); + glEnable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, + vtkgl::DEPENDENT_GB_TEXTURE_2D_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE0_ARB); + } + + // Update the dependent 2D color table mapping scalar value and + // gradient magnitude to RGBA + if ( this->UpdateColorLookup( vol ) || + !this->ColorLookupIndex || !this->AlphaLookupIndex ) + { + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glBindTexture(GL_TEXTURE_2D, (GLuint)NULL); + this->DeleteTextureIndex(&this->ColorLookupIndex); + this->CreateTextureIndex(&this->ColorLookupIndex); + glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, this->ColorLookup ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB ); + glBindTexture(GL_TEXTURE_2D, (GLuint)NULL); + this->DeleteTextureIndex(&this->AlphaLookupIndex); + this->CreateTextureIndex(&this->AlphaLookupIndex); + glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA8, 256, 256, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, this->AlphaLookup ); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB ); + glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentNoShadeNV( vtkRenderer *ren, + vtkVolume *vol ) +{ + this->SetupTwoDependentTextures(ren, vol); + + // Start the timer now + this->Timer->StartTimer(); + + this->SetupRegisterCombinersNoShadeNV( ren, vol, 2 ); + + int stages[4] = {1,0,0,0}; + this->RenderPolygons( ren, vol, stages ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentShadeNV( vtkRenderer *ren, + vtkVolume *vol ) +{ + this->SetupTwoDependentTextures( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + this->SetupRegisterCombinersShadeNV( ren, vol, 2 ); + + int stages[4] = {1,0,1,0}; + this->RenderPolygons( ren, vol, stages ); +} + +void vtkOpenGLVolumeTextureMapper3D::SetupFourDependentTextures( vtkRenderer *vtkNotUsed(ren), + vtkVolume *vol ) +{ + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glDisable( GL_TEXTURE_2D ); + glEnable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glEnable( vtkgl::TEXTURE_SHADER_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glDisable( GL_TEXTURE_2D ); + glEnable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glEnable( vtkgl::TEXTURE_SHADER_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glDisable( GL_TEXTURE_2D ); + glEnable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glEnable( vtkgl::TEXTURE_SHADER_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, vtkgl::TEXTURE_3D_EXT); + } + + // Update the volume containing the 3 byte scalars / gradient magnitude + if ( this->UpdateVolumes( vol ) || !this->Volume1Index || + !this->Volume2Index || !this->Volume3Index ) + { + int dim[3]; + this->GetVolumeDimensions(dim); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL); + this->DeleteTextureIndex(&this->Volume1Index); + this->CreateTextureIndex(&this->Volume1Index); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index); + vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGB8, dim[0], dim[1], dim[2], 0, + GL_RGB, GL_UNSIGNED_BYTE, this->Volume1 ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL); + this->DeleteTextureIndex(&this->Volume2Index); + this->CreateTextureIndex(&this->Volume2Index); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index); + vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0, + GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume2 ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, (GLuint)NULL); + this->DeleteTextureIndex(&this->Volume3Index); + this->CreateTextureIndex(&this->Volume3Index); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume3Index); + vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_RGB8, dim[0], dim[1], dim[2], 0, + GL_RGB, GL_UNSIGNED_BYTE, this->Volume3 ); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE0_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume1Index); + this->Setup3DTextureParameters( vol->GetProperty() ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE1_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume2Index); + this->Setup3DTextureParameters( vol->GetProperty() ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE2_ARB ); + glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume3Index); + this->Setup3DTextureParameters( vol->GetProperty() ); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB ); + glEnable( GL_TEXTURE_2D ); + glDisable( vtkgl::TEXTURE_3D_EXT ); + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NVIDIA_METHOD ) + { + glTexEnvf ( vtkgl::TEXTURE_SHADER_NV, vtkgl::SHADER_OPERATION_NV, + vtkgl::DEPENDENT_AR_TEXTURE_2D_NV ); + glTexEnvi(vtkgl::TEXTURE_SHADER_NV, vtkgl::PREVIOUS_TEXTURE_INPUT_NV, vtkgl::TEXTURE1_ARB); + } + + // Update the dependent 2D table mapping scalar value and + // gradient magnitude to opacity + if ( this->UpdateColorLookup( vol ) || !this->AlphaLookupIndex ) + { + this->DeleteTextureIndex(&this->ColorLookupIndex); + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB ); + glBindTexture(GL_TEXTURE_2D, (GLuint)NULL); + this->DeleteTextureIndex(&this->AlphaLookupIndex); + this->CreateTextureIndex(&this->AlphaLookupIndex); + glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); + + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA8, 256, 256, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, this->AlphaLookup ); + } + + vtkgl::ActiveTextureARB( vtkgl::TEXTURE3_ARB ); + glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentNoShadeNV( vtkRenderer *ren, + vtkVolume *vol ) +{ + this->SetupFourDependentTextures(ren, vol); + + // Start the timer now + this->Timer->StartTimer(); + + this->SetupRegisterCombinersNoShadeNV( ren, vol, 4 ); + + int stages[4] = {1,1,0,0}; + this->RenderPolygons( ren, vol, stages ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentShadeNV( vtkRenderer *ren, + vtkVolume *vol ) +{ + this->SetupFourDependentTextures( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + this->SetupRegisterCombinersShadeNV( ren, vol, 4 ); + + int stages[4] = {1,1,1,0}; + this->RenderPolygons( ren, vol, stages ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentNoShadeFP( vtkRenderer *ren, + vtkVolume *vol ) +{ + glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + GLuint fragmentProgram; + vtkgl::GenProgramsARB( 1, &fragmentProgram ); + + + vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram ); + + vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, + vtkgl::PROGRAM_FORMAT_ASCII_ARB, + strlen(vtkVolumeTextureMapper3D_OneComponentNoShadeFP), + vtkVolumeTextureMapper3D_OneComponentNoShadeFP ); + + this->SetupOneIndependentTextures( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + int stages[4] = {1,0,0,0}; + this->RenderPolygons( ren, vol, stages ); + + glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + vtkgl::DeleteProgramsARB( 1, &fragmentProgram ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderOneIndependentShadeFP( vtkRenderer *ren, + vtkVolume *vol ) +{ + glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + GLuint fragmentProgram; + vtkgl::GenProgramsARB( 1, &fragmentProgram ); + + + vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram ); + + vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, + vtkgl::PROGRAM_FORMAT_ASCII_ARB, + strlen(vtkVolumeTextureMapper3D_OneComponentShadeFP), + vtkVolumeTextureMapper3D_OneComponentShadeFP ); + + this->SetupOneIndependentTextures( ren, vol ); + this->SetupProgramLocalsForShadingFP( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + int stages[4] = {1,1,1,0}; + this->RenderPolygons( ren, vol, stages ); + + glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + vtkgl::DeleteProgramsARB( 1, &fragmentProgram ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentNoShadeFP( vtkRenderer *ren, + vtkVolume *vol ) +{ + glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + GLuint fragmentProgram; + vtkgl::GenProgramsARB( 1, &fragmentProgram ); + + vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram ); + + vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, + vtkgl::PROGRAM_FORMAT_ASCII_ARB, + strlen(vtkVolumeTextureMapper3D_TwoDependentNoShadeFP), + vtkVolumeTextureMapper3D_TwoDependentNoShadeFP ); + + this->SetupTwoDependentTextures(ren, vol); + + // Start the timer now + this->Timer->StartTimer(); + + int stages[4] = {1,0,0,0}; + this->RenderPolygons( ren, vol, stages ); + + glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + vtkgl::DeleteProgramsARB( 1, &fragmentProgram ); +} + + +void vtkOpenGLVolumeTextureMapper3D::RenderTwoDependentShadeFP( vtkRenderer *ren, + vtkVolume *vol ) +{ + glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + GLuint fragmentProgram; + vtkgl::GenProgramsARB( 1, &fragmentProgram ); + + vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram ); + + vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, + vtkgl::PROGRAM_FORMAT_ASCII_ARB, + strlen(vtkVolumeTextureMapper3D_TwoDependentShadeFP), + vtkVolumeTextureMapper3D_TwoDependentShadeFP ); + + this->SetupTwoDependentTextures(ren, vol); + this->SetupProgramLocalsForShadingFP( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + int stages[4] = {1,0,1,0}; + this->RenderPolygons( ren, vol, stages ); + + glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + vtkgl::DeleteProgramsARB( 1, &fragmentProgram ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentNoShadeFP( vtkRenderer *ren, + vtkVolume *vol ) +{ + glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + GLuint fragmentProgram; + vtkgl::GenProgramsARB( 1, &fragmentProgram ); + + vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram ); + + vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, + vtkgl::PROGRAM_FORMAT_ASCII_ARB, + strlen(vtkVolumeTextureMapper3D_FourDependentNoShadeFP), + vtkVolumeTextureMapper3D_FourDependentNoShadeFP ); + + this->SetupFourDependentTextures(ren, vol); + + // Start the timer now + this->Timer->StartTimer(); + + int stages[4] = {1,1,0,0}; + this->RenderPolygons( ren, vol, stages ); + + glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + vtkgl::DeleteProgramsARB( 1, &fragmentProgram ); +} + +void vtkOpenGLVolumeTextureMapper3D::RenderFourDependentShadeFP( vtkRenderer *ren, + vtkVolume *vol ) +{ + glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + GLuint fragmentProgram; + vtkgl::GenProgramsARB( 1, &fragmentProgram ); + + vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, fragmentProgram ); + + vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, + vtkgl::PROGRAM_FORMAT_ASCII_ARB, + strlen(vtkVolumeTextureMapper3D_FourDependentShadeFP), + vtkVolumeTextureMapper3D_FourDependentShadeFP ); + + this->SetupFourDependentTextures(ren, vol); + this->SetupProgramLocalsForShadingFP( ren, vol ); + + // Start the timer now + this->Timer->StartTimer(); + + int stages[4] = {1,1,1,0}; + this->RenderPolygons( ren, vol, stages ); + + glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); + + vtkgl::DeleteProgramsARB( 1, &fragmentProgram ); +} + + +void vtkOpenGLVolumeTextureMapper3D::GetLightInformation( vtkRenderer *ren, + vtkVolume *vol, + GLfloat lightDirection[2][4], + GLfloat lightDiffuseColor[2][4], + GLfloat lightSpecularColor[2][4], + GLfloat halfwayVector[2][4], + GLfloat ambientColor[4] ) +{ + float ambient = vol->GetProperty()->GetAmbient(); + float diffuse = vol->GetProperty()->GetDiffuse(); + float specular = vol->GetProperty()->GetSpecular(); + + vtkTransform *volumeTransform = vtkTransform::New(); + + volumeTransform->SetMatrix( vol->GetMatrix() ); + volumeTransform->Inverse(); + + vtkLightCollection *lights = ren->GetLights(); + lights->InitTraversal(); + + vtkLight *light[2]; + light[0] = lights->GetNextItem(); + light[1] = lights->GetNextItem(); + + int lightIndex = 0; + + double cameraPosition[3]; + double cameraFocalPoint[3]; + + ren->GetActiveCamera()->GetPosition( cameraPosition ); + ren->GetActiveCamera()->GetFocalPoint( cameraFocalPoint ); + + double viewDirection[3]; + + volumeTransform->TransformPoint( cameraPosition, cameraPosition ); + volumeTransform->TransformPoint( cameraFocalPoint, cameraFocalPoint ); + + viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0]; + viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1]; + viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2]; + + vtkMath::Normalize( viewDirection ); + + + ambientColor[0] = 0.0; + ambientColor[1] = 0.0; + ambientColor[2] = 0.0; + ambientColor[3] = 0.0; + + for ( lightIndex = 0; lightIndex < 2; lightIndex++ ) + { + float dir[3] = {0,0,0}; + float half[3] = {0,0,0}; + + if ( light[lightIndex] == NULL || + light[lightIndex]->GetSwitch() == 0 ) + { + lightDiffuseColor[lightIndex][0] = 0.0; + lightDiffuseColor[lightIndex][1] = 0.0; + lightDiffuseColor[lightIndex][2] = 0.0; + lightDiffuseColor[lightIndex][3] = 0.0; + + lightSpecularColor[lightIndex][0] = 0.0; + lightSpecularColor[lightIndex][1] = 0.0; + lightSpecularColor[lightIndex][2] = 0.0; + lightSpecularColor[lightIndex][3] = 0.0; + } + else + { + float lightIntensity = light[lightIndex]->GetIntensity(); + double lightColor[3]; + + light[lightIndex]->GetColor( lightColor ); + + double lightPosition[3]; + double lightFocalPoint[3]; + light[lightIndex]->GetTransformedPosition( lightPosition ); + light[lightIndex]->GetTransformedFocalPoint( lightFocalPoint ); + + volumeTransform->TransformPoint( lightPosition, lightPosition ); + volumeTransform->TransformPoint( lightFocalPoint, lightFocalPoint ); + + dir[0] = lightPosition[0] - lightFocalPoint[0]; + dir[1] = lightPosition[1] - lightFocalPoint[1]; + dir[2] = lightPosition[2] - lightFocalPoint[2]; + + vtkMath::Normalize( dir ); + + lightDiffuseColor[lightIndex][0] = lightColor[0]*diffuse*lightIntensity; + lightDiffuseColor[lightIndex][1] = lightColor[1]*diffuse*lightIntensity; + lightDiffuseColor[lightIndex][2] = lightColor[2]*diffuse*lightIntensity; + lightDiffuseColor[lightIndex][3] = 1.0; + + lightSpecularColor[lightIndex][0] = lightColor[0]*specular*lightIntensity; + lightSpecularColor[lightIndex][1] = lightColor[1]*specular*lightIntensity; + lightSpecularColor[lightIndex][2] = lightColor[2]*specular*lightIntensity; + lightSpecularColor[lightIndex][3] = 0.0; + + half[0] = dir[0] - viewDirection[0]; + half[1] = dir[1] - viewDirection[1]; + half[2] = dir[2] - viewDirection[2]; + + vtkMath::Normalize( half ); + + ambientColor[0] += ambient*lightColor[0]; + ambientColor[1] += ambient*lightColor[1]; + ambientColor[2] += ambient*lightColor[2]; + } + + lightDirection[lightIndex][0] = (dir[0]+1.0)/2.0; + lightDirection[lightIndex][1] = (dir[1]+1.0)/2.0; + lightDirection[lightIndex][2] = (dir[2]+1.0)/2.0; + lightDirection[lightIndex][3] = 0.0; + + halfwayVector[lightIndex][0] = (half[0]+1.0)/2.0; + halfwayVector[lightIndex][1] = (half[1]+1.0)/2.0; + halfwayVector[lightIndex][2] = (half[2]+1.0)/2.0; + halfwayVector[lightIndex][3] = 0.0; + } + + volumeTransform->Delete(); + +} + +void vtkOpenGLVolumeTextureMapper3D::SetupProgramLocalsForShadingFP( vtkRenderer *ren, + vtkVolume *vol ) +{ + GLfloat lightDirection[2][4]; + GLfloat lightDiffuseColor[2][4]; + GLfloat lightSpecularColor[2][4]; + GLfloat halfwayVector[2][4]; + GLfloat ambientColor[4]; + + float ambient = vol->GetProperty()->GetAmbient(); + float diffuse = vol->GetProperty()->GetDiffuse(); + float specular = vol->GetProperty()->GetSpecular(); + float specularPower = vol->GetProperty()->GetSpecularPower(); + + vtkTransform *volumeTransform = vtkTransform::New(); + + volumeTransform->SetMatrix( vol->GetMatrix() ); + volumeTransform->Inverse(); + + vtkLightCollection *lights = ren->GetLights(); + lights->InitTraversal(); + + vtkLight *light[2]; + light[0] = lights->GetNextItem(); + light[1] = lights->GetNextItem(); + + int lightIndex = 0; + + double cameraPosition[3]; + double cameraFocalPoint[3]; + + ren->GetActiveCamera()->GetPosition( cameraPosition ); + ren->GetActiveCamera()->GetFocalPoint( cameraFocalPoint ); + + volumeTransform->TransformPoint( cameraPosition, cameraPosition ); + volumeTransform->TransformPoint( cameraFocalPoint, cameraFocalPoint ); + + double viewDirection[4]; + + viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0]; + viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1]; + viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2]; + viewDirection[3] = 0.0; + + vtkMath::Normalize( viewDirection ); + + ambientColor[0] = 0.0; + ambientColor[1] = 0.0; + ambientColor[2] = 0.0; + ambientColor[3] = 0.0; + + for ( lightIndex = 0; lightIndex < 2; lightIndex++ ) + { + float dir[3] = {0,0,0}; + float half[3] = {0,0,0}; + + if ( light[lightIndex] == NULL || + light[lightIndex]->GetSwitch() == 0 ) + { + lightDiffuseColor[lightIndex][0] = 0.0; + lightDiffuseColor[lightIndex][1] = 0.0; + lightDiffuseColor[lightIndex][2] = 0.0; + lightDiffuseColor[lightIndex][3] = 0.0; + + lightSpecularColor[lightIndex][0] = 0.0; + lightSpecularColor[lightIndex][1] = 0.0; + lightSpecularColor[lightIndex][2] = 0.0; + lightSpecularColor[lightIndex][3] = 0.0; + } + else + { + float lightIntensity = light[lightIndex]->GetIntensity(); + double lightColor[3]; + + light[lightIndex]->GetColor( lightColor ); + + double lightPosition[3]; + double lightFocalPoint[3]; + light[lightIndex]->GetTransformedPosition( lightPosition ); + light[lightIndex]->GetTransformedFocalPoint( lightFocalPoint ); + + volumeTransform->TransformPoint( lightPosition, lightPosition ); + volumeTransform->TransformPoint( lightFocalPoint, lightFocalPoint ); + + dir[0] = lightPosition[0] - lightFocalPoint[0]; + dir[1] = lightPosition[1] - lightFocalPoint[1]; + dir[2] = lightPosition[2] - lightFocalPoint[2]; + + vtkMath::Normalize( dir ); + + lightDiffuseColor[lightIndex][0] = lightColor[0]*diffuse*lightIntensity; + lightDiffuseColor[lightIndex][1] = lightColor[1]*diffuse*lightIntensity; + lightDiffuseColor[lightIndex][2] = lightColor[2]*diffuse*lightIntensity; + lightDiffuseColor[lightIndex][3] = 0.0; + + lightSpecularColor[lightIndex][0] = lightColor[0]*specular*lightIntensity; + lightSpecularColor[lightIndex][1] = lightColor[1]*specular*lightIntensity; + lightSpecularColor[lightIndex][2] = lightColor[2]*specular*lightIntensity; + lightSpecularColor[lightIndex][3] = 0.0; + + half[0] = dir[0] - viewDirection[0]; + half[1] = dir[1] - viewDirection[1]; + half[2] = dir[2] - viewDirection[2]; + + vtkMath::Normalize( half ); + + ambientColor[0] += ambient*lightColor[0]; + ambientColor[1] += ambient*lightColor[1]; + ambientColor[2] += ambient*lightColor[2]; + } + + lightDirection[lightIndex][0] = dir[0]; + lightDirection[lightIndex][1] = dir[1]; + lightDirection[lightIndex][2] = dir[2]; + lightDirection[lightIndex][3] = 0.0; + + halfwayVector[lightIndex][0] = half[0]; + halfwayVector[lightIndex][1] = half[1]; + halfwayVector[lightIndex][2] = half[2]; + halfwayVector[lightIndex][3] = 0.0; + } + + volumeTransform->Delete(); + + vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 0, + lightDirection[0][0], + lightDirection[0][1], + lightDirection[0][2], + lightDirection[0][3] ); + + vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 1, + halfwayVector[0][0], + halfwayVector[0][1], + halfwayVector[0][2], + halfwayVector[0][3] ); + + vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 2, + ambient, diffuse, specular, specularPower ); + + vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 3, + lightDiffuseColor[0][0], + lightDiffuseColor[0][1], + lightDiffuseColor[0][2], + lightDiffuseColor[0][3] ); + + vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 4, + lightSpecularColor[0][0], + lightSpecularColor[0][1], + lightSpecularColor[0][2], + lightSpecularColor[0][3] ); + + vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 5, + viewDirection[0], + viewDirection[1], + viewDirection[2], + viewDirection[3] ); + + vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 6, 2.0, -1.0, 0.0, 0.0 ); +} + +int vtkOpenGLVolumeTextureMapper3D::IsRenderSupported( vtkVolumeProperty *property ) +{ + if ( !this->Initialized ) + { + this->Initialize(); + } + + if ( this->RenderMethod == vtkVolumeTextureMapper3D::NO_METHOD ) + { + return 0; + } + + if ( !this->GetInput() ) + { + return 0; + } + + if ( this->GetInput()->GetNumberOfScalarComponents() > 1 && + property->GetIndependentComponents() ) + { + return 0; + } + + return 1; +} + +void vtkOpenGLVolumeTextureMapper3D::Initialize() +{ + this->Initialized = 1; + vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New(); + extensions->SetRenderWindow(NULL); // set render window to current render window + + int supports_GL_EXT_texture3D = extensions->ExtensionSupported( "GL_EXT_texture3D" ); + int supports_GL_ARB_multitexture = extensions->ExtensionSupported( "GL_ARB_multitexture" ); + int supports_GL_NV_texture_shader2 = extensions->ExtensionSupported( "GL_NV_texture_shader2" ); + int supports_GL_NV_register_combiners2 = extensions->ExtensionSupported( "GL_NV_register_combiners2" ); + int supports_GL_ATI_fragment_shader = extensions->ExtensionSupported( "GL_ATI_fragment_shader" ); + int supports_GL_ARB_fragment_program = extensions->ExtensionSupported( "GL_ARB_fragment_program" ); + int supports_GL_ARB_vertex_program = extensions->ExtensionSupported( "GL_ARB_vertex_program" ); + int supports_GL_NV_register_combiners = extensions->ExtensionSupported( "GL_NV_register_combiners" ); + + if(supports_GL_EXT_texture3D) + { + extensions->LoadExtension("GL_EXT_texture3D"); + } + + if(supports_GL_ARB_multitexture) + { + extensions->LoadExtension("GL_ARB_multitexture" ); + } + + if(supports_GL_NV_texture_shader2) + { + extensions->LoadExtension("GL_NV_texture_shader2" ); + } + + if(supports_GL_NV_register_combiners2) + { + extensions->LoadExtension( "GL_NV_register_combiners2" ); + } + + if(supports_GL_ATI_fragment_shader) + { + extensions->LoadExtension( "GL_ATI_fragment_shader" ); + } + + if(supports_GL_ARB_fragment_program) + { + extensions->LoadExtension( "GL_ARB_fragment_program" ); + } + + if(supports_GL_ARB_vertex_program) + { + extensions->LoadExtension( "GL_ARB_vertex_program" ); + } + + if(supports_GL_NV_register_combiners) + { + extensions->LoadExtension( "GL_NV_register_combiners" ); + } + + extensions->Delete(); + +#if defined(__APPLE__) && defined(GL_VERSION_1_4) + // Apple doesn't have glTexImage3D_EXT, but it does have + // OpenGL 1.4 which supports glTexImage3D directly + supports_GL_EXT_texture3D = 1; +#endif + + int canDoFP = 0; + int canDoNV = 0; + + if ( supports_GL_EXT_texture3D && + supports_GL_ARB_multitexture && + supports_GL_ARB_fragment_program && + supports_GL_ARB_vertex_program && + vtkgl::TexImage3DEXT && + vtkgl::ActiveTextureARB && + vtkgl::MultiTexCoord3fvARB && + vtkgl::GenProgramsARB && + vtkgl::DeleteProgramsARB && + vtkgl::BindProgramARB && + vtkgl::ProgramStringARB && + vtkgl::ProgramLocalParameter4fARB ) + { + canDoFP = 1; + } + else if ( supports_GL_EXT_texture3D && + supports_GL_ARB_multitexture && + supports_GL_NV_texture_shader2 && + supports_GL_NV_register_combiners2 && + supports_GL_NV_register_combiners && + vtkgl::TexImage3DEXT && + vtkgl::ActiveTextureARB && + vtkgl::MultiTexCoord3fvARB && + vtkgl::CombinerParameteriNV && + vtkgl::CombinerStageParameterfvNV && + vtkgl::CombinerInputNV && + vtkgl::CombinerOutputNV && + vtkgl::FinalCombinerInputNV ) + { + canDoNV = 1; + } + + // can't do either + if ( !canDoFP && !canDoNV ) + { + this->RenderMethod = vtkVolumeTextureMapper3D::NO_METHOD; + } + // can only do FragmentProgram + else if ( canDoFP && !canDoNV ) + { + this->RenderMethod = vtkVolumeTextureMapper3D::FRAGMENT_PROGRAM_METHOD; + } + // can only do NVidia method + else if ( !canDoFP && canDoNV ) + { + this->RenderMethod = vtkVolumeTextureMapper3D::NVIDIA_METHOD; + } + // can do both - pick the preferred one + else + { + this->RenderMethod = this->PreferredRenderMethod; + } + + + +} + +int vtkOpenGLVolumeTextureMapper3D::IsTextureSizeSupported( int size[3] ) +{ + if ( this->GetInput()->GetNumberOfScalarComponents() < 4 ) + { + if ( size[0]*size[1]*size[2] > 128*256*256 ) + { + return 0; + } + + vtkgl::TexImage3DEXT( vtkgl::PROXY_TEXTURE_3D_EXT, 0, GL_RGBA8, size[0]*2, + size[1]*2, size[2], 0, GL_RGBA, GL_UNSIGNED_BYTE, this->Volume2 ); + } + else + { + if ( size[0]*size[1]*size[2] > 128*128*128 ) + { + return 0; + } + + vtkgl::TexImage3DEXT( vtkgl::PROXY_TEXTURE_3D_EXT, 0, GL_RGBA8, size[0]*2, + size[1]*2, size[2]*2, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->Volume2 ); + } + + + GLint params[1]; + glGetTexLevelParameteriv ( vtkgl::PROXY_TEXTURE_3D_EXT, 0, GL_TEXTURE_WIDTH, params ); + + if ( params[0] != 0 ) + { + return 1; + } + else + { + return 0; + } +} + +// Print the vtkOpenGLVolumeTextureMapper3D +void vtkOpenGLVolumeTextureMapper3D::PrintSelf(ostream& os, vtkIndent indent) +{ + + vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New(); + extensions->SetRenderWindow(NULL); // set render window to current render window + + os << indent << "Initialized " << this->Initialized << endl; + if ( this->Initialized ) + { + os << indent << "Supports GL_EXT_texture3D:" + << extensions->ExtensionSupported( "GL_EXT_texture3D" ) << endl; + os << indent << "Supports GL_ARB_multitexture: " + << extensions->ExtensionSupported( "GL_ARB_multitexture" ) << endl; + os << indent << "Supports GL_NV_texture_shader2: " + << extensions->ExtensionSupported( "GL_NV_texture_shader2" ) << endl; + os << indent << "Supports GL_NV_register_combiners2: " + << extensions->ExtensionSupported( "GL_NV_register_combiners2" ) << endl; + os << indent << "Supports GL_ATI_fragment_shader: " + << extensions->ExtensionSupported( "GL_ATI_fragment_shader" ) << endl; + os << indent << "Supports GL_ARB_fragment_program: " + << extensions->ExtensionSupported( "GL_ARB_fragment_program" ) << endl; + } + extensions->Delete(); + + this->Superclass::PrintSelf(os,indent); +} + + + diff --git a/VolumeRendering/vtkOpenGLVolumeTextureMapper3D.h b/VolumeRendering/vtkOpenGLVolumeTextureMapper3D.h new file mode 100644 index 0000000..7847c9b --- /dev/null +++ b/VolumeRendering/vtkOpenGLVolumeTextureMapper3D.h @@ -0,0 +1,154 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOpenGLVolumeTextureMapper3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOpenGLVolumeTextureMapper3D - concrete implementation of 3D volume texture mapping + +// .SECTION Description +// vtkOpenGLVolumeTextureMapper3D renders a volume using 3D texture mapping. +// See vtkVolumeTextureMapper3D for full description. + +// .SECTION see also +// vtkVolumeTextureMapper3D vtkVolumeMapper + +#ifndef __vtkOpenGLVolumeTextureMapper3D_h +#define __vtkOpenGLVolumeTextureMapper3D_h + +#include "vtkVolumeTextureMapper3D.h" + +#ifndef VTK_IMPLEMENT_MESA_CXX +# include "vtkOpenGL.h" // GLfloat type is used in some method signatures. +#endif + + +class vtkRenderWindow; +class vtkVolumeProperty; + +class VTK_VOLUMERENDERING_EXPORT vtkOpenGLVolumeTextureMapper3D : public vtkVolumeTextureMapper3D +{ +public: + vtkTypeRevisionMacro(vtkOpenGLVolumeTextureMapper3D,vtkVolumeTextureMapper3D); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkOpenGLVolumeTextureMapper3D *New(); + + // Description: + // Is hardware rendering supported? No if the input data is + // more than one independent component, or if the hardware does + // not support the required extensions + int IsRenderSupported(vtkVolumeProperty *); + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol); + +//ETX + + // Desciption: + // Initialize when we go to render, or go to answer the + // IsRenderSupported question. Don't call unless we have + // a valid OpenGL context! + vtkGetMacro( Initialized, int ); + + // Description: + // Release any graphics resources that are being consumed by this texture. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + +protected: + vtkOpenGLVolumeTextureMapper3D(); + ~vtkOpenGLVolumeTextureMapper3D(); + +//BTX + + void GetLightInformation(vtkRenderer *ren, + vtkVolume *vol, + GLfloat lightDirection[2][4], + GLfloat lightDiffuseColor[2][4], + GLfloat lightSpecularColor[2][4], + GLfloat halfwayVector[2][4], + GLfloat *ambient ); +//ETX + + int Initialized; + GLuint Volume1Index; + GLuint Volume2Index; + GLuint Volume3Index; + GLuint ColorLookupIndex; + GLuint AlphaLookupIndex; + vtkRenderWindow *RenderWindow; + + void Initialize(); + + virtual void RenderNV(vtkRenderer *ren, vtkVolume *vol); + virtual void RenderFP(vtkRenderer *ren, vtkVolume *vol); + + void RenderOneIndependentNoShadeFP( vtkRenderer *ren, + vtkVolume *vol ); + void RenderOneIndependentShadeFP( vtkRenderer *ren, vtkVolume *vol ); + void RenderTwoDependentNoShadeFP( vtkRenderer *ren, vtkVolume *vol ); + void RenderTwoDependentShadeFP( vtkRenderer *ren, vtkVolume *vol ); + void RenderFourDependentNoShadeFP( vtkRenderer *ren, vtkVolume *vol ); + void RenderFourDependentShadeFP( vtkRenderer *ren, vtkVolume *vol ); + + void RenderOneIndependentNoShadeNV( vtkRenderer *ren, vtkVolume *vol ); + void RenderOneIndependentShadeNV( vtkRenderer *ren, vtkVolume *vol ); + void RenderTwoDependentNoShadeNV( vtkRenderer *ren, vtkVolume *vol ); + void RenderTwoDependentShadeNV( vtkRenderer *ren, vtkVolume *vol ); + void RenderFourDependentNoShadeNV( vtkRenderer *ren, vtkVolume *vol ); + void RenderFourDependentShadeNV( vtkRenderer *ren, vtkVolume *vol ); + + void SetupOneIndependentTextures( vtkRenderer *ren, vtkVolume *vol ); + void SetupTwoDependentTextures( vtkRenderer *ren, vtkVolume *vol ); + void SetupFourDependentTextures( vtkRenderer *ren, vtkVolume *vol ); + + void SetupRegisterCombinersNoShadeNV( vtkRenderer *ren, + vtkVolume *vol, + int components ); + + void SetupRegisterCombinersShadeNV( vtkRenderer *ren, + vtkVolume *vol, + int components ); + + void DeleteTextureIndex( GLuint *index ); + void CreateTextureIndex( GLuint *index ); + + void RenderPolygons( vtkRenderer *ren, + vtkVolume *vol, + int stages[4] ); + + void SetupProgramLocalsForShadingFP( vtkRenderer *ren, vtkVolume *vol ); + + // Description: + // Check if we can support this texture size. + int IsTextureSizeSupported( int size[3] ); + + // Description: + // Common code for setting up interpolation / clamping on 3D textures + void Setup3DTextureParameters( vtkVolumeProperty *property ); + +private: + vtkOpenGLVolumeTextureMapper3D(const vtkOpenGLVolumeTextureMapper3D&); // Not implemented. + void operator=(const vtkOpenGLVolumeTextureMapper3D&); // Not implemented. +}; + + +#endif + + + diff --git a/VolumeRendering/vtkProjectedTetrahedraMapper.cxx b/VolumeRendering/vtkProjectedTetrahedraMapper.cxx new file mode 100644 index 0000000..d1385ca --- /dev/null +++ b/VolumeRendering/vtkProjectedTetrahedraMapper.cxx @@ -0,0 +1,1077 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProjectedTetrahedraMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkProjectedTetrahedraMapper.h" + +#include "vtkObjectFactory.h" +#include "vtkVisibilitySort.h" +#include "vtkUnsignedCharArray.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkIdTypeArray.h" +#include "vtkCellCenterDepthSort.h" +#include "vtkUnstructuredGrid.h" +#include "vtkCellArray.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkPointData.h" +#include "vtkCellData.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkCamera.h" +#include "vtkMath.h" +#include "vtkTimerLog.h" +#include "vtkMatrix4x4.h" +#include "vtkPiecewiseFunction.h" +#include "vtkColorTransferFunction.h" +#include "vtkGarbageCollector.h" + +#include "vtkOpenGL.h" + +#include <math.h> +#include <vtkstd/algorithm> + +//----------------------------------------------------------------------------- + +// static int tet_faces[4][3] = { {1,2,3}, {2,0,3}, {0,1,3}, {0,2,1} }; +static int tet_edges[6][2] = { {0,1}, {1,2}, {2,0}, + {0,3}, {1,3}, {2,3} }; + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkProjectedTetrahedraMapper, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkProjectedTetrahedraMapper); + +vtkCxxSetObjectMacro(vtkProjectedTetrahedraMapper, + VisibilitySort, vtkVisibilitySort); + +vtkProjectedTetrahedraMapper::vtkProjectedTetrahedraMapper() +{ + this->TransformedPoints = vtkFloatArray::New(); + this->Colors = vtkUnsignedCharArray::New(); + this->VisibilitySort = vtkCellCenterDepthSort::New(); + + this->ScalarMode = VTK_SCALAR_MODE_DEFAULT; + this->ArrayName = new char[1]; + this->ArrayName[0] = '\0'; + this->ArrayId = -1; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; + + this->LastVolume = NULL; + + this->OpacityTexture = 0; + this->MaxCellSize = 0; + + this->GaveError = 0; +} + +vtkProjectedTetrahedraMapper::~vtkProjectedTetrahedraMapper() +{ + this->ReleaseGraphicsResources(NULL); + this->TransformedPoints->Delete(); + this->Colors->Delete(); + if (this->VisibilitySort) this->VisibilitySort->UnRegister(this); + + delete[] this->ArrayName; +} + +void vtkProjectedTetrahedraMapper::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "VisibilitySort: " << this->VisibilitySort << endl; + + os << indent << "ScalarMode: " << this->GetScalarModeAsString() << endl; + if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + os << indent << "ArrayId: " << this->ArrayId << endl; + } + else + { + os << indent << "ArrayName: " << this->ArrayName << endl; + } +} + +//----------------------------------------------------------------------------- + +void vtkProjectedTetrahedraMapper::ReleaseGraphicsResources(vtkWindow *win) +{ + if (this->OpacityTexture) + { + GLuint texid = this->OpacityTexture; + glDeleteTextures(1, &texid); + this->OpacityTexture = 0; + } + this->Superclass::ReleaseGraphicsResources(win); +} + +//----------------------------------------------------------------------------- + +void vtkProjectedTetrahedraMapper::ReportReferences(vtkGarbageCollector *collector) +{ + this->Superclass::ReportReferences(collector); + + vtkGarbageCollectorReport(collector, this->VisibilitySort, "VisibilitySort"); +} + +//----------------------------------------------------------------------------- + +void vtkProjectedTetrahedraMapper::SelectScalarArray(int arrayNum) +{ + if ( (this->ArrayId == arrayNum) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) + { + return; + } + this->Modified(); + + this->ArrayId = arrayNum; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +void vtkProjectedTetrahedraMapper::SelectScalarArray(const char *arrayName) +{ + if ( !arrayName + || ( (strcmp(this->ArrayName, arrayName) == 0) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) ) + { + return; + } + this->Modified(); + + delete[] this->ArrayName; + this->ArrayName = new char[strlen(arrayName) + 1]; + strcpy(this->ArrayName, arrayName); + this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME; +} + +//----------------------------------------------------------------------------- + +// Return the method for obtaining scalar data. +const char *vtkProjectedTetrahedraMapper::GetScalarModeAsString(void) +{ + if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ) + { + return "UseCellData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA ) + { + return "UsePointFieldData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + return "UseCellFieldData"; + } + else + { + return "Default"; + } +} + +//----------------------------------------------------------------------------- + +// Given a unit opacity, converts it to an opacity for the given depth. +// Note that opacity is not the same as the attenuation. Specifically, +// opacity = 1 - exp(-attenuation) +// attenuation = -ln(1 - opacity) +// The correction for opacity is simply depth * attenuation. Therefore, +// the correction for opacity is: +// 1 - exp(-depth * (-ln(1 - opacity))) +// which resolves to +// 1 - (1 - opacity)^depth +// static inline float CorrectOpacityForDepth(float opacity, float depth) +// { +// return (1 - (float)pow(1 - opacity, depth)); +// } + +void vtkProjectedTetrahedraMapper::Render(vtkRenderer *renderer, + vtkVolume *volume) +{ + vtkUnstructuredGrid *input = this->GetInput(); + + float last_max_cell_size = this->MaxCellSize; + + // Check to see if input changed. + if ( (this->InputAnalyzedTime < this->MTime) + || (this->InputAnalyzedTime < input->GetMTime()) ) + { + this->GaveError = 0; + float max_cell_size2 = 0; + + vtkCellArray *cells = input->GetCells(); + if (!cells) + { + // Apparently, the input has no cells. Just do nothing. + return; + } + + vtkIdType npts, *pts; + cells->InitTraversal(); + for (vtkIdType i = 0; cells->GetNextCell(npts, pts); i++) + { + int j; + if (npts != 4) + { + if (!this->GaveError) + { + vtkErrorMacro("Encountered non-tetrahedra cell!"); + this->GaveError = 1; + } + continue; + } + for (j = 0; j < 6; j++) + { + double p1[3], p2[3]; + input->GetPoint(pts[tet_edges[j][0]], p1); + input->GetPoint(pts[tet_edges[j][1]], p2); + float size2 = (float)vtkMath::Distance2BetweenPoints(p1, p2); + if (size2 > max_cell_size2) max_cell_size2 = size2; + } + } + + this->MaxCellSize = (float)sqrt(max_cell_size2); + + this->InputAnalyzedTime.Modified(); + } + + if (renderer->GetRenderWindow()->CheckAbortStatus() || this->GaveError) + { + return; + } + + // Check to see if we need to rebuild opacity texture. + if ( !this->OpacityTexture + || (last_max_cell_size != this->MaxCellSize) + || (this->LastVolume != volume) + || (this->OpacityTextureTime < volume->GetMTime()) + || (this->OpacityTextureTime < volume->GetProperty()->GetMTime()) ) + { + if (!this->OpacityTexture) + { + GLuint texid; + glGenTextures(1, &texid); + this->OpacityTexture = texid; + } + glBindTexture(GL_TEXTURE_2D, this->OpacityTexture); + + float unit_distance = volume->GetProperty()->GetScalarOpacityUnitDistance(); + +#define TEXRES 258 + float *texture = new float[TEXRES*TEXRES]; + for (int depthi = 0; depthi < TEXRES; depthi++) + { + if (renderer->GetRenderWindow()->CheckAbortStatus()) + { + delete[] texture; + return; + } + float depth = depthi*this->MaxCellSize/(TEXRES); +// for (int opacityi = 0; opacityi < TEXRES; opacityi++) +// { +// float opacity = (float)opacityi/(TEXRES-1); +// float alpha = CorrectOpacityForDepth(opacity, depth/unit_distance); +// texture[(depthi*TEXRES + opacityi)] = alpha; +// } + for (int attenuationi = 0; attenuationi < TEXRES; attenuationi++) + { + float attenuation = (float)attenuationi/(TEXRES); + float alpha = 1 - (float)exp(-attenuation*depth/unit_distance); + texture[(depthi*TEXRES + attenuationi)] = alpha; + } + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, TEXRES, TEXRES, 1, GL_RED, + GL_FLOAT, texture); + delete[] texture; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + + glBindTexture(GL_TEXTURE_2D, 0); + + this->OpacityTextureTime.Modified(); + } + if (renderer->GetRenderWindow()->CheckAbortStatus()) + { + return; + } + + // Check to see if we need to remap colors. + if ( (this->ColorsMappedTime < this->MTime) + || (this->ColorsMappedTime < input->GetMTime()) + || (this->LastVolume != volume) + || (this->ColorsMappedTime < volume->GetMTime()) + || (this->ColorsMappedTime < volume->GetProperty()->GetMTime()) ) + { + vtkDataArray *scalars = this->GetScalars(input, this->ScalarMode, + this->ArrayAccessMode, + this->ArrayId, this->ArrayName, + this->UsingCellColors); + if (!scalars) + { + vtkErrorMacro(<< "Can't use projected tetrahedra without scalars!"); + return; + } + + vtkProjectedTetrahedraMapper::MapScalarsToColors(this->Colors, volume, + scalars); + + this->ColorsMappedTime.Modified(); + this->LastVolume = volume; + } + if (renderer->GetRenderWindow()->CheckAbortStatus()) + { + return; + } + + this->Timer->StartTimer(); + + this->ProjectTetrahedra(renderer, volume); + + this->Timer->StopTimer(); + this->TimeToDraw = this->Timer->GetElapsedTime(); +} + +//----------------------------------------------------------------------------- + +template<class point_type> +void vtkProjectedTetrahedraMapperTransformPoints(const point_type *in_points, + vtkIdType num_points, + const float projection_mat[16], + const float modelview_mat[16], + float *out_points); + +static inline float GetCorrectedDepth(float x, float y, float z1, float z2, + const float inverse_projection_mat[16], + int use_linear_depth_correction, + float linear_depth_correction) +{ + if (use_linear_depth_correction) + { + float depth = linear_depth_correction*(z1 - z2); + if (depth < 0) depth = -depth; + return depth; + } + else + { + float eye1[3], eye2[3], invw; + + invw = 1/( inverse_projection_mat[ 3]*x + + inverse_projection_mat[ 7]*y + + inverse_projection_mat[11]*z1 + + inverse_projection_mat[15] ); + eye1[0] = invw*( inverse_projection_mat[ 0]*x + + inverse_projection_mat[ 4]*y + + inverse_projection_mat[ 8]*z1 + + inverse_projection_mat[12] ); + eye1[1] = invw*( inverse_projection_mat[ 1]*x + + inverse_projection_mat[ 5]*y + + inverse_projection_mat[ 9]*z1 + + inverse_projection_mat[13] ); + eye1[2] = invw*( inverse_projection_mat[ 2]*x + + inverse_projection_mat[ 6]*y + + inverse_projection_mat[10]*z1 + + inverse_projection_mat[14] ); + + invw = 1/( inverse_projection_mat[ 3]*x + + inverse_projection_mat[ 7]*y + + inverse_projection_mat[11]*z2 + + inverse_projection_mat[15] ); + eye2[0] = invw*( inverse_projection_mat[ 0]*x + + inverse_projection_mat[ 4]*y + + inverse_projection_mat[ 8]*z2 + + inverse_projection_mat[12] ); + eye2[1] = invw*( inverse_projection_mat[ 1]*x + + inverse_projection_mat[ 5]*y + + inverse_projection_mat[ 9]*z2 + + inverse_projection_mat[13] ); + eye2[2] = invw*( inverse_projection_mat[ 2]*x + + inverse_projection_mat[ 6]*y + + inverse_projection_mat[10]*z2 + + inverse_projection_mat[14] ); + + return (float)sqrt(vtkMath::Distance2BetweenPoints(eye1, eye2)); + } +} + +void vtkProjectedTetrahedraMapper::ProjectTetrahedra(vtkRenderer *renderer, + vtkVolume *volume) +{ + vtkUnstructuredGrid *input = this->GetInput(); + + this->VisibilitySort->SetInput(input); + this->VisibilitySort->SetDirectionToBackToFront(); + this->VisibilitySort->SetModelTransform(volume->GetMatrix()); + this->VisibilitySort->SetCamera(renderer->GetActiveCamera()); + this->VisibilitySort->SetMaxCellsReturned(1000); + + this->VisibilitySort->InitTraversal(); + + if (renderer->GetRenderWindow()->CheckAbortStatus()) + { + return; + } + + float projection_mat[16]; + float modelview_mat[16]; + glGetFloatv(GL_PROJECTION_MATRIX, projection_mat); + glGetFloatv(GL_MODELVIEW_MATRIX, modelview_mat); + + // Get the inverse projection matrix so that we can convert distances in + // clipping space to distances in world or eye space. + float inverse_projection_mat[16]; + float linear_depth_correction = 1; + int use_linear_depth_correction; + double tmp_mat[16]; + + // VTK's matrix functions use doubles. + vtkstd::copy(projection_mat, projection_mat+16, tmp_mat); + // VTK and OpenGL store their matrices differently. Correct. + vtkMatrix4x4::Transpose(tmp_mat, tmp_mat); + // Take the inverse. + vtkMatrix4x4::Invert(tmp_mat, tmp_mat); + // Restore back to OpenGL form. + vtkMatrix4x4::Transpose(tmp_mat, tmp_mat); + // Copy back to float for faster computation. + vtkstd::copy(tmp_mat, tmp_mat+16, inverse_projection_mat); + + // Check to see if we can just do a linear depth correction from clipping + // space to eye space. + use_linear_depth_correction = ( (projection_mat[ 3] == 0.0) + && (projection_mat[ 7] == 0.0) + && (projection_mat[11] == 0.0) + && (projection_mat[15] == 1.0) ); + if (use_linear_depth_correction) + { + float pos1[3], *pos2; + + pos1[0] = inverse_projection_mat[8] + inverse_projection_mat[12]; + pos1[1] = inverse_projection_mat[9] + inverse_projection_mat[13]; + pos1[2] = inverse_projection_mat[10] + inverse_projection_mat[14]; + + pos2 = inverse_projection_mat + 12; + + linear_depth_correction = sqrt(vtkMath::Distance2BetweenPoints(pos1, pos2)); + } + + // Transform all the points. + vtkIdType num_points = input->GetNumberOfPoints(); + this->TransformedPoints->SetNumberOfComponents(3); + this->TransformedPoints->SetNumberOfTuples(num_points); + float *points = this->TransformedPoints->GetPointer(0); + switch (input->GetPoints()->GetDataType()) + { + vtkTemplateMacro + (vtkProjectedTetrahedraMapperTransformPoints( + (const VTK_TT *)input->GetPoints()->GetVoidPointer(0), + num_points, + projection_mat, modelview_mat, + points)); + } + + if (renderer->GetRenderWindow()->CheckAbortStatus()) + { + return; + } + + glDisable(GL_LIGHTING); + glDepthMask(GL_FALSE); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, this->OpacityTexture); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + // Establish vertex arrays. + float tet_points[5*3]; + glVertexPointer(3, GL_FLOAT, 0, tet_points); + glEnableClientState(GL_VERTEX_ARRAY); + + unsigned char tet_colors[5*3]; + glColorPointer(3, GL_UNSIGNED_BYTE, 0, tet_colors); + glEnableClientState(GL_COLOR_ARRAY); + + float tet_texcoords[5*2]; + glTexCoordPointer(2, GL_FLOAT, 0, tet_texcoords); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + // Since we had to transform the points on the CPU, replace the OpenGL + // transforms with the identity matrix. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + unsigned char *colors = this->Colors->GetPointer(0); + vtkIdType *cells = input->GetCells()->GetPointer(); + vtkIdType totalnumcells = input->GetNumberOfCells(); + vtkIdType numcellsrendered = 0; + + // Let's do it! + for (vtkIdTypeArray *sorted_cell_ids = this->VisibilitySort->GetNextCells(); + sorted_cell_ids != NULL; + sorted_cell_ids = this->VisibilitySort->GetNextCells()) + { + this->UpdateProgress((double)numcellsrendered/totalnumcells); + if (renderer->GetRenderWindow()->CheckAbortStatus()) + { + break; + } + vtkIdType *cell_ids = sorted_cell_ids->GetPointer(0); + vtkIdType num_cell_ids = sorted_cell_ids->GetNumberOfTuples(); + for (vtkIdType i = 0; i < num_cell_ids; i++) + { + vtkIdType cell = cell_ids[i]; + int j; + + // Get the data for the tetrahedra. + for (j = 0; j < 4; j++) + { + // Assuming we only have tetrahedra, each entry in cells has 5 + // components. + const float *p = points + 3*cells[5*cell + j + 1]; + tet_points[j*3 + 0] = p[0]; + tet_points[j*3 + 1] = p[1]; + tet_points[j*3 + 2] = p[2]; + + const unsigned char *c; + if (this->UsingCellColors) + { + c = colors + 4*cell; + } + else + { + c = colors + 4*cells[5*cell + j + 1]; + } + tet_colors[j*3 + 0] = c[0]; + tet_colors[j*3 + 1] = c[1]; + tet_colors[j*3 + 2] = c[2]; + + tet_texcoords[j*2 + 0] = (float)c[3]/255; + tet_texcoords[j*2 + 1] = 0; + } + + // The classic PT algorithm uses face normals to determine the + // projection class and then do calculations individually. However, + // Wylie 2002 shows how to use the intersection of two segments to + // calculate the depth of the thick part for any case. Here, we use + // face normals to determine which segments to use. One segment + // should be between two faces that are either both front facing or + // back facing. Obviously, we only need to test three faces to find + // two such faces. We test the three faces connected to point 0. + vtkIdType segment1[2]; + vtkIdType segment2[2]; + + float v1[2], v2[2], v3[3]; + v1[0] = tet_points[1*3 + 0] - tet_points[0*3 + 0]; + v1[1] = tet_points[1*3 + 1] - tet_points[0*3 + 1]; + v2[0] = tet_points[2*3 + 0] - tet_points[0*3 + 0]; + v2[1] = tet_points[2*3 + 1] - tet_points[0*3 + 1]; + v3[0] = tet_points[3*3 + 0] - tet_points[0*3 + 0]; + v3[1] = tet_points[3*3 + 1] - tet_points[0*3 + 1]; + + float face_dir1 = v3[0]*v2[1] - v3[1]*v2[0]; + float face_dir2 = v1[0]*v3[1] - v1[1]*v3[0]; + float face_dir3 = v2[0]*v1[1] - v2[1]*v1[0]; + + if ( (face_dir1 * face_dir2 >= 0) + && ( (face_dir1 != 0) // Handle a special case where 2 faces + || (face_dir2 != 0) ) ) // are perpendicular to the view plane. + { + segment1[0] = 0; segment1[1] = 3; + segment2[0] = 1; segment2[1] = 2; + } + else if (face_dir1 * face_dir3 >= 0) + { + segment1[0] = 0; segment1[1] = 2; + segment2[0] = 1; segment2[1] = 3; + } + else // Unless the tet is degenerate, face_dir2*face_dir3 >= 0 + { + segment1[0] = 0; segment1[1] = 1; + segment2[0] = 2; segment2[1] = 3; + } + +#define VEC3SUB(Z,X,Y) \ + (Z)[0] = (X)[0] - (Y)[0]; \ + (Z)[1] = (X)[1] - (Y)[1]; \ + (Z)[2] = (X)[2] - (Y)[2]; +#define P1 (tet_points + 3*segment1[0]) +#define P2 (tet_points + 3*segment1[1]) +#define P3 (tet_points + 3*segment2[0]) +#define P4 (tet_points + 3*segment2[1]) +#define C1 (tet_colors + 3*segment1[0]) +#define C2 (tet_colors + 3*segment1[1]) +#define C3 (tet_colors + 3*segment2[0]) +#define C4 (tet_colors + 3*segment2[1]) +#define T1 (tet_texcoords + 2*segment1[0]) +#define T2 (tet_texcoords + 2*segment1[1]) +#define T3 (tet_texcoords + 2*segment2[0]) +#define T4 (tet_texcoords + 2*segment2[1]) + // Find the intersection of the projection of the two segments in the + // XY plane. This algorithm is based on that given in Graphics Gems + // III, pg. 199-202. + float A[3], B[3], C[3]; + // We can define the two lines parametrically as: + // P1 + alpha(A) + // P3 + beta(B) + // where A = P2 - P1 + // and B = P4 - P3. + // alpha and beta are in the range [0,1] within the line segment. + VEC3SUB(A, P2, P1); + VEC3SUB(B, P4, P3); + // The lines intersect when the values of the two parameteric equations + // are equal. Setting them equal and moving everything to one side: + // 0 = C + beta(B) - alpha(A) + // where C = P3 - P1. + VEC3SUB(C, P3, P1); + // When we project the lines to the xy plane (which we do by throwing + // away the z value), we have two equations and two unkowns. The + // following are the solutions for alpha and beta. + float alpha = (B[1]*C[0]-B[0]*C[1])/(A[0]*B[1]-A[1]*B[0]); + float beta = (A[1]*C[0]-A[0]*C[1])/(A[0]*B[1]-A[1]*B[0]); + + if ((alpha >= 0) && (alpha <= 1)) + { + // The two segments intersect. This corresponds to class 2 in + // Shirley and Tuchman (or one of the degenerate cases). + + // Make new point at intersection. + tet_points[3*4 + 0] = P1[0] + alpha*A[0]; + tet_points[3*4 + 1] = P1[1] + alpha*A[1]; + tet_points[3*4 + 2] = P1[2] + alpha*A[2]; + + // Find depth at intersection. + float depth = GetCorrectedDepth(tet_points[3*4 + 0], + tet_points[3*4 + 1], + tet_points[3*4 + 2], + P3[2] + beta*B[2], + inverse_projection_mat, + use_linear_depth_correction, + linear_depth_correction); + + // Find color at intersection. + tet_colors[3*4 + 0] = + (unsigned char)(0.5f*( C1[0] + alpha*(C2[0]-C1[0]) + + C3[0] + beta*(C4[0]-C3[0]) )); + tet_colors[3*4 + 1] = + (unsigned char)(0.5f*( C1[1] + alpha*(C2[1]-C1[1]) + + C3[1] + beta*(C4[1]-C3[1]) )); + tet_colors[3*4 + 2] = + (unsigned char)(0.5f*( C1[2] + alpha*(C2[2]-C1[2]) + + C3[2] + beta*(C4[2]-C3[2]) )); + +// tet_colors[3*0 + 0] = 255; +// tet_colors[3*0 + 1] = 0; +// tet_colors[3*0 + 2] = 0; +// tet_colors[3*1 + 0] = 255; +// tet_colors[3*1 + 1] = 0; +// tet_colors[3*1 + 2] = 0; +// tet_colors[3*2 + 0] = 255; +// tet_colors[3*2 + 1] = 0; +// tet_colors[3*2 + 2] = 0; +// tet_colors[3*3 + 0] = 255; +// tet_colors[3*3 + 1] = 0; +// tet_colors[3*3 + 2] = 0; +// tet_colors[3*4 + 0] = 255; +// tet_colors[3*4 + 1] = 0; +// tet_colors[3*4 + 2] = 0; + + // Find the opacity at intersection. + tet_texcoords[2*4 + 0] = 0.5f*( T1[0] + alpha*(T2[0]-T1[0]) + + T3[0] + alpha*(T4[0]-T3[0])); + + // Record the depth at the intersection. + tet_texcoords[2*4 + 1] = depth/this->MaxCellSize; + + // Establish the order in which the points should be rendered. + unsigned char gl_indices[6]; + gl_indices[0] = 4; + gl_indices[1] = segment1[0]; + gl_indices[2] = segment2[0]; + gl_indices[3] = segment1[1]; + gl_indices[4] = segment2[1]; + gl_indices[5] = segment1[0]; + + // Render + glDrawElements(GL_TRIANGLE_FAN, 6, GL_UNSIGNED_BYTE, gl_indices); + } + else + { + // The two segments do not intersect. This corresponds to class 1 + // in Shirley and Tuchman. + if (alpha <= 0) + { + // Flip segment1 so that alpha is >= 1. P1 and P2 are also + // flipped as are C1-C2 and T1-T2. Note that this will + // invalidate A. B and beta are unaffected. + vtkstd::swap(segment1[0], segment1[1]); + alpha = 1 - alpha; + } + // From here on, we can assume P2 is the "thick" point. + + // Find the depth under the thick point. Use the alpha and beta + // from intersection to determine location of face under thick + // point. + float edgez = P3[2] + beta*B[2]; + float pointz = P1[2]; + float facez = (edgez + (alpha-1)*pointz)/alpha; + float depth = GetCorrectedDepth(P2[0], P2[1], P2[2], facez, + inverse_projection_mat, + use_linear_depth_correction, + linear_depth_correction); + + // Fix color at thick point. Average color with color of opposite + // face. + for (j = 0; j < 3; j++) + { + float edgec = C3[j] + beta*(C4[j]-C3[j]); + float pointc = C1[j]; + float facec = (edgec + (alpha-1)*pointc)/alpha; + C2[j] = (unsigned char)(0.5f*(facec + C2[j])); + } + +// tet_colors[3*segment1[0] + 0] = 0; +// tet_colors[3*segment1[0] + 1] = 255; +// tet_colors[3*segment1[0] + 2] = 0; +// tet_colors[3*segment1[1] + 0] = 0; +// tet_colors[3*segment1[1] + 1] = 255; +// tet_colors[3*segment1[1] + 2] = 0; +// tet_colors[3*segment2[0] + 0] = 0; +// tet_colors[3*segment2[0] + 1] = 255; +// tet_colors[3*segment2[0] + 2] = 0; +// tet_colors[3*segment2[1] + 0] = 0; +// tet_colors[3*segment2[1] + 1] = 255; +// tet_colors[3*segment2[1] + 2] = 0; + + // Fix opacity at thick point. Average opacity with opacity of + // opposite face. + float edgea = T3[0] + beta*(T4[0]-T3[0]); + float pointa = T1[0]; + float facea = (edgea + (alpha-1)*pointa)/alpha; + T2[0] = 0.5f*(facea + T2[0]); + + // Record thickness at thick point. + T2[1] = depth/this->MaxCellSize; + + // Establish the order in which the points should be rendered. + unsigned char gl_indices[5]; + gl_indices[0] = segment1[1]; + gl_indices[1] = segment1[0]; + gl_indices[2] = segment2[0]; + gl_indices[3] = segment2[1]; + gl_indices[4] = segment1[0]; + + // Render + glDrawElements(GL_TRIANGLE_FAN, 5, GL_UNSIGNED_BYTE, gl_indices); + } + } + numcellsrendered += num_cell_ids; + } + + // Restore OpenGL state. + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(projection_mat); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(modelview_mat); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + glDepthMask(GL_TRUE); + glEnable(GL_LIGHTING); + + this->UpdateProgress(1.0); +} + +//----------------------------------------------------------------------------- + +template<class point_type> +void vtkProjectedTetrahedraMapperTransformPoints(const point_type *in_points, + vtkIdType num_points, + const float projection_mat[16], + const float modelview_mat[16], + float *out_points) +{ + float mat[16]; + int row, col; + vtkIdType i; + const point_type *in_p; + float *out_p; + + // Combine two transforms into one transform. + for (col = 0; col < 4; col++) + { + for (row = 0; row < 4; row++) + { + mat[col*4+row] = ( projection_mat[0*4+row]*modelview_mat[col*4+0] + + projection_mat[1*4+row]*modelview_mat[col*4+1] + + projection_mat[2*4+row]*modelview_mat[col*4+2] + + projection_mat[3*4+row]*modelview_mat[col*4+3]); + } + } + + // Transform all points. + for (i = 0, in_p = in_points, out_p = out_points; i < num_points; + i++, in_p += 3, out_p += 3) + { + for (row = 0; row < 3; row++) + { + out_p[row] = ( mat[0*4+row]*in_p[0] + mat[1*4+row]*in_p[1] + + mat[2*4+row]*in_p[2] + mat[3*4+row]); + } + } + + // Check to see if we need to divide by w. + if ( (mat[0*4+3] != 0) || (mat[1*4+3] != 0) + || (mat[0*4+3] != 0) || (mat[1*4+3] != 1) ) + { + for (i = 0, in_p = in_points, out_p = out_points; i < num_points; + i++, in_p += 3, out_p += 3) + { + float w = ( mat[0*4+3]*in_p[0] + mat[1*4+3]*in_p[1] + + mat[2*4+3]*in_p[2] + mat[3*4+3]); + out_p[0] /= w; + out_p[1] /= w; + out_p[2] /= w; + } + } +} + +//----------------------------------------------------------------------------- + +namespace vtkProjectedTetrahedraMapperNamespace +{ + template<class ColorType> + void MapScalarsToColors1(ColorType *colors, vtkVolumeProperty *property, + vtkDataArray *scalars); + template<class ColorType, class ScalarType> + void MapScalarsToColors2(ColorType *colors, vtkVolumeProperty *property, + ScalarType *scalars, + int num_scalar_components, + vtkIdType num_scalars); + template<class ColorType, class ScalarType> + void MapIndependentComponents(ColorType *colors, + vtkVolumeProperty *property, + ScalarType *scalars, + int num_scalar_components, + vtkIdType num_scalars); + template<class ColorType, class ScalarType> + void Map2DependentComponents(ColorType *colors, ScalarType *scalars, + vtkIdType num_scalars); + template<class ColorType, class ScalarType> + void Map4DependentComponents(ColorType *colors, ScalarType *scalars, + vtkIdType num_scalars); +} + +void vtkProjectedTetrahedraMapper::MapScalarsToColors(vtkDataArray *colors, + vtkVolume *volume, + vtkDataArray *scalars) +{ + using namespace vtkProjectedTetrahedraMapperNamespace; + + vtkDataArray *tmpColors; + int castColors; + + if ( (colors->GetDataType() == VTK_UNSIGNED_CHAR) + && ( (scalars->GetDataType() != VTK_UNSIGNED_CHAR) + || (volume->GetProperty()->GetIndependentComponents()) ) ) + { + // Special case. Need to convert from range [0,1] to [0,255]. + tmpColors = vtkDoubleArray::New(); + castColors = 1; + } + else + { + tmpColors = colors; + castColors = 0; + } + + vtkIdType numscalars = scalars->GetNumberOfTuples(); + + tmpColors->Initialize(); + tmpColors->SetNumberOfComponents(4); + tmpColors->SetNumberOfTuples(numscalars); + + void *colorpointer = tmpColors->GetVoidPointer(0); + switch (tmpColors->GetDataType()) + { + vtkTemplateMacro(MapScalarsToColors1(static_cast<VTK_TT *>(colorpointer), + volume->GetProperty(), scalars)); + } + + if (castColors) + { + // Special case. Need to convert from range [0,1] to [0,255]. + colors->Initialize(); + colors->SetNumberOfComponents(4); + colors->SetNumberOfTuples(scalars->GetNumberOfTuples()); + + unsigned char *c + = static_cast<vtkUnsignedCharArray *>(colors)->GetPointer(0); + + for (vtkIdType i = 0; i < numscalars; i++, c+= 4) + { + double *dc = tmpColors->GetTuple(i); + c[0] = static_cast<unsigned char>(dc[0]*255.9999); + c[1] = static_cast<unsigned char>(dc[1]*255.9999); + c[2] = static_cast<unsigned char>(dc[2]*255.9999); + c[3] = static_cast<unsigned char>(dc[3]*255.9999); + } + + tmpColors->Delete(); + } +} + +namespace vtkProjectedTetrahedraMapperNamespace +{ + + template<class ColorType> + void MapScalarsToColors1(ColorType *colors, vtkVolumeProperty *property, + vtkDataArray *scalars) + { + void *scalarpointer = scalars->GetVoidPointer(0); + switch(scalars->GetDataType()) + { + vtkTemplateMacro(MapScalarsToColors2(colors, property, + static_cast<VTK_TT *>(scalarpointer), + scalars->GetNumberOfComponents(), + scalars->GetNumberOfTuples())); + } + } + + template<class ColorType, class ScalarType> + void MapScalarsToColors2(ColorType *colors, vtkVolumeProperty *property, + ScalarType *scalars, + int num_scalar_components, vtkIdType num_scalars) + { + if (property->GetIndependentComponents()) + { + MapIndependentComponents(colors, property, + scalars, num_scalar_components, num_scalars); + } + else + { + switch (num_scalar_components) + { + case 2: + Map2DependentComponents(colors, scalars, num_scalars); + break; + case 4: + Map4DependentComponents(colors, scalars, num_scalars); + break; + default: + vtkGenericWarningMacro("Attempted to map scalar with " + << num_scalar_components + << " with dependent components"); + break; + } + } + } + + template<class ColorType, class ScalarType> + void MapIndependentComponents(ColorType *colors, + vtkVolumeProperty *property, + ScalarType *scalars, + int num_scalar_components, + vtkIdType num_scalars) + { + // I don't really know what to do if there is more than one component. + // How am I supposed to mix the resulting colors? Since I don't know + // what to do, and the whole thing seems kinda pointless anyway, I'm just + // going to punt and copy over the first scalar. + ColorType *c = colors; + ScalarType *s = scalars; + vtkIdType i; + + if (property->GetColorChannels() == 1) + { + vtkPiecewiseFunction *gray = property->GetGrayTransferFunction(); + vtkPiecewiseFunction *alpha = property->GetScalarOpacity(); + + for (i = 0; i < num_scalars; i++, c += 4, s += num_scalar_components) + { + c[0] = c[1] = c[2] = static_cast<ColorType>(gray->GetValue(s[0])); + c[3] = static_cast<ColorType>(alpha->GetValue(s[0])); + } + } + else + { + vtkColorTransferFunction *rgb = property->GetRGBTransferFunction(); + vtkPiecewiseFunction *alpha = property->GetScalarOpacity(); + + for (i = 0; i < num_scalars; i++, c += 4, s += num_scalar_components) + { + double trgb[3]; + rgb->GetColor(s[0], trgb); + c[0] = static_cast<ColorType>(trgb[0]); + c[1] = static_cast<ColorType>(trgb[1]); + c[2] = static_cast<ColorType>(trgb[2]); + c[3] = static_cast<ColorType>(alpha->GetValue(s[0])); + } + } + } + + template<class ColorType, class ScalarType> + void Map2DependentComponents(ColorType *colors, ScalarType *scalars, + vtkIdType num_scalars) + { + for (vtkIdType i = 0; i < num_scalars; i++) + { + colors[0] = colors[1] = colors[2] = static_cast<ColorType>(scalars[0]); + colors[3] = static_cast<ColorType>(scalars[3]); + + colors += 4; + scalars += 2; + } + } + + template<class ColorType, class ScalarType> + void Map4DependentComponents(ColorType *colors, ScalarType *scalars, + vtkIdType num_scalars) + { + for (vtkIdType i = 0; i < num_scalars; i++) + { + colors[0] = static_cast<ColorType>(scalars[0]); + colors[1] = static_cast<ColorType>(scalars[1]); + colors[2] = static_cast<ColorType>(scalars[2]); + colors[3] = static_cast<ColorType>(scalars[3]); + + colors += 4; + scalars += 4; + } + } + +} diff --git a/VolumeRendering/vtkProjectedTetrahedraMapper.h b/VolumeRendering/vtkProjectedTetrahedraMapper.h new file mode 100644 index 0000000..c596be8 --- /dev/null +++ b/VolumeRendering/vtkProjectedTetrahedraMapper.h @@ -0,0 +1,147 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkProjectedTetrahedraMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2003 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkProjectedTetrahedraMapper - Unstructured grid volume renderer. +// +// .SECTION Description +// vtkProjectedTetrahedraMapper is an implementation of the classic +// Projected Tetrahedra algorithm presented by Shirley and Tuchman in "A +// Polygonal Approximation to Direct Scalar Volume Rendering" in Computer +// Graphics, December 1990. +// +// .SECTION Bugs +// This mapper relies highly on the implementation of the OpenGL pipeline. +// A typically hardware driver has lots of options and some settings can +// cause this mapper to produce artifacts. +// + +#ifndef __vtkProjectedTetrahedraMapper_h +#define __vtkProjectedTetrahedraMapper_h + +#include "vtkUnstructuredGridVolumeMapper.h" + +class vtkVisibilitySort; +class vtkUnsignedCharArray; +class vtkFloatArray; + +class VTK_VOLUMERENDERING_EXPORT vtkProjectedTetrahedraMapper : public vtkUnstructuredGridVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkProjectedTetrahedraMapper, + vtkUnstructuredGridVolumeMapper); + static vtkProjectedTetrahedraMapper *New(); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + virtual void SetVisibilitySort(vtkVisibilitySort *sort); + vtkGetObjectMacro(VisibilitySort, vtkVisibilitySort); + + // Description: + // Control how the filter works with scalar point data and cell attribute + // data. By default (ScalarModeToDefault), the filter will use point data, + // and if no point data is available, then cell data is used. Alternatively + // you can explicitly set the filter to use point data + // (ScalarModeToUsePointData) or cell data (ScalarModeToUseCellData). + // You can also choose to get the scalars from an array in point field + // data (ScalarModeToUsePointFieldData) or cell field data + // (ScalarModeToUseCellFieldData). If scalars are coming from a field + // data array, you must call SelectColorArray before you call + // GetColors. + vtkSetMacro(ScalarMode,int); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToDefault() { + this->SetScalarMode(VTK_SCALAR_MODE_DEFAULT);}; + void SetScalarModeToUsePointData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA);}; + void SetScalarModeToUseCellData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_DATA);}; + void SetScalarModeToUsePointFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA);}; + void SetScalarModeToUseCellFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA);}; + + // Description: + // When ScalarMode is set to UsePointFileData or UseCellFieldData, + // you can specify which array to use for coloring using these methods. + // The transfer function in the vtkVolumeProperty (attached to the calling + // vtkVolume) will decide how to convert vectors to colors. + virtual void SelectScalarArray(int arrayNum); + virtual void SelectScalarArray(const char* arrayName); + + // Description: + // Get the array name or number and component to color by. + virtual char* GetArrayName() { return this->ArrayName; } + virtual int GetArrayId() { return this->ArrayId; } + virtual int GetArrayAccessMode() { return this->ArrayAccessMode; } + + // Description: + // Return the method for obtaining scalar data. + const char *GetScalarModeAsString(); + + virtual void Render(vtkRenderer *renderer, vtkVolume *volume); + + virtual void ReleaseGraphicsResources(vtkWindow *window); + + static void MapScalarsToColors(vtkDataArray *colors, vtkVolume *volume, + vtkDataArray *scalars); + +protected: + vtkProjectedTetrahedraMapper(); + ~vtkProjectedTetrahedraMapper(); + + vtkUnsignedCharArray *Colors; + int UsingCellColors; + + vtkFloatArray *TransformedPoints; + + float MaxCellSize; + vtkTimeStamp InputAnalyzedTime; + vtkTimeStamp OpacityTextureTime; + vtkTimeStamp ColorsMappedTime; + + unsigned int OpacityTexture; + + vtkVisibilitySort *VisibilitySort; + + int ScalarMode; + char *ArrayName; + int ArrayId; + int ArrayAccessMode; + + int GaveError; + + vtkVolume *LastVolume; + + virtual void ProjectTetrahedra(vtkRenderer *renderer, vtkVolume *volume); + + // Description: + // The visibility sort will probably make a reference loop by holding a + // reference to the input. + virtual void ReportReferences(vtkGarbageCollector *collector); + +private: + vtkProjectedTetrahedraMapper(const vtkProjectedTetrahedraMapper &); // Not Implemented. + void operator=(const vtkProjectedTetrahedraMapper &); // Not Implemented. +}; + +#endif //__vtkProjectedTetrahedraMapper_h diff --git a/VolumeRendering/vtkRayCastImageDisplayHelper.cxx b/VolumeRendering/vtkRayCastImageDisplayHelper.cxx new file mode 100644 index 0000000..3709e69 --- /dev/null +++ b/VolumeRendering/vtkRayCastImageDisplayHelper.cxx @@ -0,0 +1,54 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRayCastImageDisplayHelper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRayCastImageDisplayHelper.h" +#include "vtkVolumeRenderingFactory.h" + +vtkCxxRevisionMacro(vtkRayCastImageDisplayHelper, "$Revision: 1.4 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkRayCastImageDisplayHelper); +//---------------------------------------------------------------------------- + +vtkRayCastImageDisplayHelper* vtkRayCastImageDisplayHelper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret=vtkVolumeRenderingFactory::CreateInstance("vtkRayCastImageDisplayHelper"); + return (vtkRayCastImageDisplayHelper*)ret; +} + + +// Construct a new vtkRayCastImageDisplayHelper with default values +vtkRayCastImageDisplayHelper::vtkRayCastImageDisplayHelper() +{ + this->PreMultipliedColors = 0; + this->PixelScale = 1.0; +} + +// Destruct a vtkRayCastImageDisplayHelper - clean up any memory used +vtkRayCastImageDisplayHelper::~vtkRayCastImageDisplayHelper() +{ +} + +void vtkRayCastImageDisplayHelper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "PreMultiplied Colors: " + << (this->PreMultipliedColors ? "On" : "Off") << endl; + + os << indent << "Pixel Scale: " << this->PixelScale << endl; +} + diff --git a/VolumeRendering/vtkRayCastImageDisplayHelper.h b/VolumeRendering/vtkRayCastImageDisplayHelper.h new file mode 100644 index 0000000..808e7ee --- /dev/null +++ b/VolumeRendering/vtkRayCastImageDisplayHelper.h @@ -0,0 +1,90 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRayCastImageDisplayHelper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkRayCastImageDisplayHelper - helper class that draws the image to the screen +// .SECTION Description +// This is a helper class for drawing images created from ray casting on the screen. +// This is the abstract device-independent superclass. + +// .SECTION see also +// vtkVolumeRayCastMapper vtkUnstructuredGridVolumeRayCastMapper +// vtkOpenGLRayCastImageDisplayHelper + +#ifndef __vtkRayCastImageDisplayHelper_h +#define __vtkRayCastImageDisplayHelper_h + +#include "vtkObject.h" + +class vtkVolume; +class vtkRenderer; +class vtkFixedPointRayCastImage; + +class VTK_VOLUMERENDERING_EXPORT vtkRayCastImageDisplayHelper : public vtkObject +{ +public: + static vtkRayCastImageDisplayHelper *New(); + vtkTypeRevisionMacro(vtkRayCastImageDisplayHelper,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + virtual void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned char *image ) = 0; + + virtual void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + int imageMemorySize[2], + int imageViewportSize[2], + int imageInUseSize[2], + int imageOrigin[2], + float requestedDepth, + unsigned short *image ) = 0; + + virtual void RenderTexture( vtkVolume *vol, vtkRenderer *ren, + vtkFixedPointRayCastImage *image, + float requestedDepth ) = 0; + + vtkSetClampMacro( PreMultipliedColors, int, 0, 1 ); + vtkGetMacro( PreMultipliedColors, int ); + vtkBooleanMacro( PreMultipliedColors, int ); + + + // Description: + // Set / Get the pixel scale to be applied to the image before display. + // Can be set to scale the incoming pixel values - for example the + // fixed point mapper uses the unsigned short API but with 15 bit + // values so needs a scale of 2.0. + vtkSetMacro( PixelScale, float ); + vtkGetMacro( PixelScale, float ); + +protected: + vtkRayCastImageDisplayHelper(); + ~vtkRayCastImageDisplayHelper(); + + // Description: + // Have the colors already been multiplied by alpha? + int PreMultipliedColors; + + float PixelScale; + +private: + vtkRayCastImageDisplayHelper(const vtkRayCastImageDisplayHelper&); // Not implemented. + void operator=(const vtkRayCastImageDisplayHelper&); // Not implemented. +}; + +#endif + diff --git a/VolumeRendering/vtkRecursiveSphereDirectionEncoder.cxx b/VolumeRendering/vtkRecursiveSphereDirectionEncoder.cxx new file mode 100644 index 0000000..74803dc --- /dev/null +++ b/VolumeRendering/vtkRecursiveSphereDirectionEncoder.cxx @@ -0,0 +1,382 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRecursiveSphereDirectionEncoder.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkRecursiveSphereDirectionEncoder.h" +#include "vtkObjectFactory.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkRecursiveSphereDirectionEncoder, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkRecursiveSphereDirectionEncoder); + +// Construct the object. Initialize the index table which will be +// used to map the normal into a patch on the recursively subdivided +// sphere. +vtkRecursiveSphereDirectionEncoder::vtkRecursiveSphereDirectionEncoder() +{ + this->RecursionDepth = 6; + this->IndexTable = NULL; + this->DecodedNormal = NULL; + this->InitializeIndexTable(); +} + +// Destruct a vtkRecursiveSphereDirectionEncoder - free up any memory used +vtkRecursiveSphereDirectionEncoder::~vtkRecursiveSphereDirectionEncoder() +{ + if ( this->IndexTable ) + { + delete [] this->IndexTable; + } + if ( this->DecodedNormal ) + { + delete [] this->DecodedNormal; + } +} + + +int vtkRecursiveSphereDirectionEncoder::GetEncodedDirection( float n[3] ) +{ + float t; + int value; + int xindex, yindex; + float x, y; + + if ( this->IndexTableRecursionDepth != this->RecursionDepth ) + { + this->InitializeIndexTable(); + } + + // Convert the gradient direction into an encoded index value + // This is done by computing the (x,y) grid position of this + // normal in the 2*NORM_SQR_SIZE - 1 grid, then passing this + // through the IndexTable to look up the 16 bit index value + + // Don't use fabs because it is slow - just convert to absolute + // using a simple conditional. + t = + ((n[0]>=0.0)?(n[0]):(-n[0])) + + ((n[1]>=0.0)?(n[1]):(-n[1])) + + ((n[2]>=0.0)?(n[2]):(-n[2])); + + if ( t ) + { + + t = 1.0 / t; + + x = n[0] * t; + y = n[1] * t; + + xindex = (int)((x+1.0)*(float)(this->InnerSize) + 0.5); + yindex = (int)((y+1.0)*(float)(this->InnerSize) + 0.5); + + if ( xindex > 2*this->InnerSize ) + { + xindex = 2*this->InnerSize; + } + if ( yindex > 2*this->InnerSize ) + { + yindex = 2*this->InnerSize; + } + + value = this->IndexTable[xindex*(this->OuterSize+this->InnerSize) + yindex]; + + // If the z component is less than 0.0, add this->GridSize to the + // index + if ( n[2] < 0.0 ) + { + value += this->GridSize; + } + } + else + { + value = 2*this->GridSize; + } + + return value; +} + +float *vtkRecursiveSphereDirectionEncoder::GetDecodedGradient( int value ) +{ + if ( this->IndexTableRecursionDepth != this->RecursionDepth ) + { + this->InitializeIndexTable(); + } + + return (this->DecodedNormal + value*3); +} + +int vtkRecursiveSphereDirectionEncoder::GetNumberOfEncodedDirections( void ) +{ + int outer_size, inner_size; + int norm_size; + + outer_size = (int)(pow( 2.0, (double) this->RecursionDepth ) + 1); + inner_size = outer_size - 1; + + norm_size = outer_size * outer_size + inner_size * inner_size; + + return (norm_size*2 + 1); +} + +float *vtkRecursiveSphereDirectionEncoder::GetDecodedGradientTable( void ) +{ + if ( this->IndexTableRecursionDepth != this->RecursionDepth ) + { + this->InitializeIndexTable(); + } + + return this->DecodedNormal; +} + +// Initialize the index table. This is a 2*NORM_SQR_SIZE - 1 by +// 2*NORM_SQR_SIZE - 1 entry table that maps (x,y) grid position to +// encoded normal index. The grid position is obtained by starting +// with an octahedron (comprised of 8 triangles forming a double +// pyramid). Each triangle is then replaced by 4 triangles by joining +// edge midpoints. This is done recursively until NORM_SQR_SIZE +// vertices exist on each original edge. If you "squish" this octahedron, +// it will look like a diamond. Then rotate it 45 degrees, it will +// look like a square. Then look at the pattern of vertices - there +// is a NORM_SQR_SIZE by NORM_SQR_SIZE grid, with a (NORM_SQR_SIZE-1) by +// NORM_SQR_SIZE - 1 grid inside of it. The vertices all fall on +// (x,y) locatiions in a grid that is 2*NORM_SQR_SIZE - 1 by +// 2*NORM_SQR_SIZE - 1, although not every (x,y) location has a vertex. +void vtkRecursiveSphereDirectionEncoder::InitializeIndexTable( void ) +{ + int i, j, index, max_index; + int xindex, yindex; + float x, y, z, tmp_x, tmp_y; + float norm; + int limit; + + // Free up any memory previously used + if ( this->IndexTable ) + { + delete [] this->IndexTable; + } + if ( this->DecodedNormal ) + { + delete [] this->DecodedNormal; + } + + this->OuterSize = (int)(pow( 2.0, (double) this->RecursionDepth ) + 1); + this->InnerSize = this->OuterSize - 1; + this->GridSize = + this->OuterSize * this->OuterSize + + this->InnerSize * this->InnerSize; + + + // Create space for the tables + this->IndexTable = new int [(this->OuterSize + this->InnerSize) * + (this->OuterSize + this->InnerSize)]; + + // Initialize the table to -1 -- we'll use this later to determine which + // entries are still not filled in + for ( i = 0; i < ( (this->OuterSize + this->InnerSize) * + (this->OuterSize + this->InnerSize) ); i ++ ) + { + this->IndexTable[i] = -1; + } + + this->DecodedNormal = + new float [ 3 * ( 1 + + 2 * this->OuterSize * this->OuterSize + + 2 * this->InnerSize * this->InnerSize ) ]; + + // Initialize the index + index = 0; + + // max_index indicates the largest index we will get - the number + // of vertices in the two-grid square. This represents half the + // normals, and max_index is used to offset from one half into the + // other. One half of the normals have z components >= 0, and the + // second half (all with indices above max_index) have z components + // that are <= 0. + max_index = this->GridSize; + + // The last normal (max_index*2) is the zero normal + this->DecodedNormal[3*(max_index*2) + 0] = 0.0; + this->DecodedNormal[3*(max_index*2) + 1] = 0.0; + this->DecodedNormal[3*(max_index*2) + 2] = 0.0; + + // The outer loop is for this->OuterSize + this->InnerSize rows + for ( i = 0; i < this->OuterSize + this->InnerSize; i++ ) + { + // Compute the y component for this row + tmp_y = (float)(2*i)/(float)(this->InnerSize*2) - 1.0; + + // On the odd rows, we are doing the small grid which has + // this->InnerSize elements in it + limit = ( i%2 )?(this->InnerSize):(this->OuterSize); + + for ( j = 0; j < limit; j++ ) + { + // compute the x component for this column + if ( i%2 ) + { + tmp_x = (float)(2*j)/(float)(this->InnerSize) - + 1.0 + (1.0/(float)(this->InnerSize)); + } + else + { + tmp_x = (float)(2*j)/(float)(this->InnerSize) - 1.0; + } + + // rotate by 45 degrees + // This rotation intentionally does not preserve length - + // we could have tmp_x = 1.0 and tmp_y = 1.0, we want this + // to lie within [-1.0,1.0] after rotation. + x = 0.5 * tmp_x - 0.5 * tmp_y; + y = 0.5 * tmp_x + 0.5 * tmp_y; + + // compute the z based on the x and y values + if ( x >= 0 && y >= 0 ) + { + z = 1.0 - x - y; + } + else if ( x >= 0 && y < 0 ) + { + z = 1.0 - x + y; + } + else if ( x < 0 && y < 0 ) + { + z = 1.0 + x + y; + } + else + { + z = 1.0 + x - y; + } + + // Normalize this direction and set the DecodedNormal table for + // this index to this normal. Also set the corresponding + // entry for this normal with a negative z component + norm = sqrt( (double)( x*x + y*y + z*z ) ); + this->DecodedNormal[3*index + 0] = x / norm; + this->DecodedNormal[3*index + 1] = y / norm; + this->DecodedNormal[3*index + 2] = z / norm; + this->DecodedNormal[3*(index+max_index) + 0] = x / norm; + this->DecodedNormal[3*(index+max_index) + 1] = y / norm; + this->DecodedNormal[3*(index+max_index) + 2] = -(z / norm); + + // Figure out the location in the IndexTable. Be careful with + // boundary conditions. + xindex = (int)((x+1.0)*(float)(this->InnerSize) + 0.5); + yindex = (int)((y+1.0)*(float)(this->InnerSize) + 0.5); + if ( xindex > 2*this->InnerSize ) + { + xindex = 2*this->InnerSize; + } + if ( yindex > 2*this->InnerSize ) + { + yindex = 2*this->InnerSize; + } + this->IndexTable[xindex*(this->OuterSize+this->InnerSize) + yindex] = index; + + // Do the grid location to the left - unless we are at the left + // border of the grid. We are computing indices only for the + // actual vertices of the subdivided octahedron, but we'll + // convert these into the IndexTable coordinates and fill in + // the index for the intermediate points on the grid as well. + // This way we can't get bitten by a scan-conversion problem + // where we skip over some table index due to precision, and + // therefore it doesn't have a valid value in it. + if ( tmp_x > 0 ) + { + x = 0.5 * (tmp_x - (1.0/(float)this->InnerSize)) - 0.5 * tmp_y; + y = 0.5 * (tmp_x - (1.0/(float)this->InnerSize)) + 0.5 * tmp_y; + xindex = (int)((x+1.0)*(float)(this->InnerSize) + 0.5); + yindex = (int)((y+1.0)*(float)(this->InnerSize) + 0.5); + if ( xindex > 2*this->InnerSize ) + { + xindex = 2*this->InnerSize; + } + if ( yindex > 2*this->InnerSize ) + { + yindex = 2*this->InnerSize; + } + this->IndexTable[xindex*(this->OuterSize+this->InnerSize) + yindex] = index; + } + + // On the odd rows we also need to do the last grid location on + // the right. + if ( (i%2) && (j == limit - 1) ) + { + x = 0.5 * (tmp_x + (1.0/(float)this->InnerSize)) - 0.5 * tmp_y; + y = 0.5 * (tmp_x + (1.0/(float)this->InnerSize)) + 0.5 * tmp_y; + xindex = (int)((x+1.0)*(float)(this->InnerSize) + 0.5); + yindex = (int)((y+1.0)*(float)(this->InnerSize) + 0.5); + if ( xindex > 2*this->InnerSize ) + { + xindex = 2*this->InnerSize; + } + if ( yindex > 2*this->InnerSize ) + { + yindex = 2*this->InnerSize; + } + this->IndexTable[xindex*(this->OuterSize+this->InnerSize) + yindex] = index; + } + + // Increment the index + index++; + } + } + + + // The index table has been initialized for the current recursion + // depth + this->IndexTableRecursionDepth = this->RecursionDepth; + + + // Spread the first index value in each row to the left, and the last to the right. + // This is because we have only filled in a diamond of index values within the square + // grid, and we need to be careful at the edges due to precision problems. This way + // we won't be able to access a table location that does not have a valid index in it. + for ( j = 0; j < this->OuterSize + this->InnerSize; j++ ) + { + // Start from the middle going right, copy the value from the left if + // this entry is not initialized + for ( i = (this->OuterSize+this->InnerSize)/2; + i < this->OuterSize + this->InnerSize; i++ ) + { + if ( this->IndexTable[j*(this->OuterSize+this->InnerSize)+i] == -1 ) + { + this->IndexTable[j*(this->OuterSize+this->InnerSize)+i] = + this->IndexTable[j*(this->OuterSize+this->InnerSize)+i-1]; + } + } + + // Start from the middle going left, copy the value from the right if + // this entry is not initialized + for ( i = (this->OuterSize+this->InnerSize)/2; i >= 0; i-- ) + { + if ( this->IndexTable[j*(this->OuterSize+this->InnerSize)+i] == -1 ) + { + this->IndexTable[j*(this->OuterSize+this->InnerSize)+i] = + this->IndexTable[j*(this->OuterSize+this->InnerSize)+i+1]; + } + } + } +} + + +// Print the vtkRecursiveSphereDirectionEncoder +void vtkRecursiveSphereDirectionEncoder::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of encoded directions: " << + this->GetNumberOfEncodedDirections() << endl; + + os << indent << "Recursion depth: " << this->RecursionDepth << endl; +} diff --git a/VolumeRendering/vtkRecursiveSphereDirectionEncoder.h b/VolumeRendering/vtkRecursiveSphereDirectionEncoder.h new file mode 100644 index 0000000..6a41501 --- /dev/null +++ b/VolumeRendering/vtkRecursiveSphereDirectionEncoder.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkRecursiveSphereDirectionEncoder.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkRecursiveSphereDirectionEncoder - A direction encoder based on the recursive subdivision of an octahedron +// .SECTION Description +// vtkRecursiveSphereDirectionEncoder is a direction encoder which uses the +// vertices of a recursive subdivision of an octahedron (with the vertices +// pushed out onto the surface of an enclosing sphere) to encode directions +// into a two byte value. +// +// .SECTION see also +// vtkDirectionEncoder + +#ifndef __vtkRecursiveSphereDirectionEncoder_h +#define __vtkRecursiveSphereDirectionEncoder_h + +#include "vtkDirectionEncoder.h" + +class VTK_VOLUMERENDERING_EXPORT vtkRecursiveSphereDirectionEncoder : public vtkDirectionEncoder +{ +public: + vtkTypeRevisionMacro(vtkRecursiveSphereDirectionEncoder,vtkDirectionEncoder); + void PrintSelf( ostream& os, vtkIndent indent ); + +// Description: +// Construct the object. Initialize the index table which will be +// used to map the normal into a patch on the recursively subdivided +// sphere. + static vtkRecursiveSphereDirectionEncoder *New(); + + + // Description: + // Given a normal vector n, return the encoded direction + int GetEncodedDirection( float n[3] ); + + // Description: + /// Given an encoded value, return a pointer to the normal vector + float *GetDecodedGradient( int value ); + + // Description: + // Return the number of encoded directions + int GetNumberOfEncodedDirections( void ); + + // Description: + // Get the decoded gradient table. There are + // this->GetNumberOfEncodedDirections() entries in the table, each + // containing a normal (direction) vector. This is a flat structure - + // 3 times the number of directions floats in an array. + float *GetDecodedGradientTable( void ); + + // Description: + // Set / Get the recursion depth for the subdivision. This + // indicates how many time one triangle on the initial 8-sided + // sphere model is replaced by four triangles formed by connecting + // triangle edge midpoints. A recursion level of 0 yields 8 triangles + // with 6 unique vertices. The normals are the vectors from the + // sphere center through the vertices. The number of directions + // will be 11 since the four normals with 0 z values will be + // duplicated in the table - once with +0 values and the other + // time with -0 values, and an addition index will be used to + // represent the (0,0,0) normal. If we instead choose a recursion + // level of 6 (the maximum that can fit within 2 bytes) the number + // of directions is 16643, with 16386 unique directions and a + // zero normal. + vtkSetClampMacro( RecursionDepth, int, 0, 6 ); + vtkGetMacro( RecursionDepth, int ); + +protected: + vtkRecursiveSphereDirectionEncoder(); + ~vtkRecursiveSphereDirectionEncoder(); + + // How far to recursively divide the sphere + int RecursionDepth; + + // The index table which maps (x,y) position in the rotated grid + // to an encoded normal + //int IndexTable[2*NORM_SQR_SIZE - 1][2*NORM_SQR_SIZE -1]; + int *IndexTable; + + // This is a table that maps encoded normal (2 byte value) to a + // normal (dx, dy, dz) + //float DecodedNormal[3*(1 + 2*(NORM_SQR_SIZE*NORM_SQR_SIZE+ + // (NORM_SQR_SIZE-1)*(NORM_SQR_SIZE-1)))]; + float *DecodedNormal; + + // Method to initialize the index table and variable that + // stored the recursion depth the last time the table was + // built + void InitializeIndexTable( void ); + int IndexTableRecursionDepth; + + int OuterSize; + int InnerSize; + int GridSize; +private: + vtkRecursiveSphereDirectionEncoder(const vtkRecursiveSphereDirectionEncoder&); // Not implemented. + void operator=(const vtkRecursiveSphereDirectionEncoder&); // Not implemented. +}; + + +#endif + diff --git a/VolumeRendering/vtkSphericalDirectionEncoder.cxx b/VolumeRendering/vtkSphericalDirectionEncoder.cxx new file mode 100644 index 0000000..78ffc28 --- /dev/null +++ b/VolumeRendering/vtkSphericalDirectionEncoder.cxx @@ -0,0 +1,153 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphericalDirectionEncoder.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSphericalDirectionEncoder.h" +#include "vtkObjectFactory.h" + +#include "vtkMath.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkSphericalDirectionEncoder, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkSphericalDirectionEncoder); + +float vtkSphericalDirectionEncoder::DecodedGradientTable[65536*3]; +int vtkSphericalDirectionEncoder::DecodedGradientTableInitialized = 0; + +// Construct the object. Initialize the index table which will be +// used to map the normal into a patch on the recursively subdivided +// sphere. +vtkSphericalDirectionEncoder::vtkSphericalDirectionEncoder() +{ + this->InitializeDecodedGradientTable(); +} + +// Destruct a vtkSphericalDirectionEncoder - free up any memory used +vtkSphericalDirectionEncoder::~vtkSphericalDirectionEncoder() +{ +} + +// Encode n into a 2 byte value. The first byte will be theta - the +// rotation angle around the z axis. The second (high order) byte is +// phi - the elevation of the vector. 256 values are used for theta, +// but only 255 values for phi, leaving room for a "zero normal" code +int vtkSphericalDirectionEncoder::GetEncodedDirection( float n[3] ) +{ + if ( n[0] == 0.0 && n[1] == 0.0 && n[2] == 0.0 ) + { + return ( 255*256 ); + } + + float theta, phi; + + // Need to handle this separately since some atan2 implementations + // don't handle a zero denominator + if ( n[0] == 0 ) + { + theta = (n[1]>0)?(90.0):(270.0); + } + else + { + theta = (vtkMath::RadiansToDegrees())*atan2( n[1], n[0] ); + theta = (theta<0.0)?(theta+360.0):(theta); + theta = (theta>=360.0)?(theta-360.0):(theta); + } + + phi = (vtkMath::RadiansToDegrees())*asin( n[2] ); + phi = (phi > 90.5)?(phi-360):(phi); + + int lowByte, highByte; + + lowByte = static_cast<int>(theta * 255.0 / 359.0 + 0.5); + highByte = static_cast<int>((phi+90.0) * 254.0 / 180.0 + 0.5); + + lowByte = (lowByte<0)?(0):(lowByte); + lowByte = (lowByte>255)?(255):(lowByte); + + highByte = (highByte<0)?(0):(highByte); + highByte = (highByte>254)?(254):(highByte); + + return (lowByte + highByte*256); +} + +float *vtkSphericalDirectionEncoder::GetDecodedGradient( int value ) +{ + return &(vtkSphericalDirectionEncoder::DecodedGradientTable[value*3]); +} + +// This is the table that maps the encoded gradient back into +// a float triple. +void vtkSphericalDirectionEncoder::InitializeDecodedGradientTable() +{ + if ( vtkSphericalDirectionEncoder::DecodedGradientTableInitialized ) + { + return; + } + + float theta, phi; + int i, j; + + vtkTransform *transformPhi = vtkTransform::New(); + vtkTransform *transformTheta = vtkTransform::New(); + + float v1[3] = {1,0,0}; + float v2[3], v3[3]; + + float *ptr = vtkSphericalDirectionEncoder::DecodedGradientTable; + + for ( j = 0; j < 256; j++ ) + { + phi = -89.5 + j * (179.0 / 254.0 ); + + transformPhi->Identity(); + transformPhi->RotateY( -phi ); + transformPhi->TransformPoint( v1, v2 ); + + for ( i = 0; i < 256; i++ ) + { + if ( j < 255 ) + { + theta = i * (359.0 / 255.0); + + transformTheta->Identity(); + transformTheta->RotateZ( theta ); + transformTheta->TransformPoint( v2, v3 ); + } + else + { + v3[0] = 0.0; + v3[1] = 0.0; + v3[2] = 0.0; + } + + *(ptr++) = v3[0]; + *(ptr++) = v3[1]; + *(ptr++) = v3[2]; + } + } + + transformPhi->Delete(); + transformTheta->Delete(); + + vtkSphericalDirectionEncoder::DecodedGradientTableInitialized = 1; +} + +// Print the vtkSphericalDirectionEncoder +void vtkSphericalDirectionEncoder::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Number of encoded directions: " << + this->GetNumberOfEncodedDirections() << endl; +} + diff --git a/VolumeRendering/vtkSphericalDirectionEncoder.h b/VolumeRendering/vtkSphericalDirectionEncoder.h new file mode 100644 index 0000000..b617d6b --- /dev/null +++ b/VolumeRendering/vtkSphericalDirectionEncoder.h @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphericalDirectionEncoder.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSphericalDirectionEncoder - A direction encoder based on spherical coordinates +// .SECTION Description +// vtkSphericalDirectionEncoder is a direction encoder which uses spherical +// coordinates for mapping (nx, ny, nz) into an azimuth, elevation pair. +// +// .SECTION see also +// vtkDirectionEncoder + +#ifndef __vtkSphericalDirectionEncoder_h +#define __vtkSphericalDirectionEncoder_h + +#include "vtkDirectionEncoder.h" + +class VTK_VOLUMERENDERING_EXPORT vtkSphericalDirectionEncoder : public vtkDirectionEncoder +{ +public: + vtkTypeRevisionMacro(vtkSphericalDirectionEncoder,vtkDirectionEncoder); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Construct the object. Initialize the index table which will be + // used to map the normal into a patch on the recursively subdivided + // sphere. + static vtkSphericalDirectionEncoder *New(); + + + // Description: + // Given a normal vector n, return the encoded direction + int GetEncodedDirection( float n[3] ); + + // Description: + /// Given an encoded value, return a pointer to the normal vector + float *GetDecodedGradient( int value ); + + // Description: + // Return the number of encoded directions + int GetNumberOfEncodedDirections( void ) { return 65536; } + + // Description: + // Get the decoded gradient table. There are + // this->GetNumberOfEncodedDirections() entries in the table, each + // containing a normal (direction) vector. This is a flat structure - + // 3 times the number of directions floats in an array. + float *GetDecodedGradientTable( void ) + { + return &(this->DecodedGradientTable[0]); + } + + +protected: + vtkSphericalDirectionEncoder(); + ~vtkSphericalDirectionEncoder(); + + static float DecodedGradientTable[65536*3]; + + // Description: + // Initialize the table at startup + static void InitializeDecodedGradientTable(); + static int DecodedGradientTableInitialized; + +private: + vtkSphericalDirectionEncoder(const vtkSphericalDirectionEncoder&); // Not implemented. + void operator=(const vtkSphericalDirectionEncoder&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkUnstructuredGridBunykRayCastFunction.cxx b/VolumeRendering/vtkUnstructuredGridBunykRayCastFunction.cxx new file mode 100644 index 0000000..92fb5eb --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridBunykRayCastFunction.cxx @@ -0,0 +1,1167 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridBunykRayCastFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridBunykRayCastFunction.h" +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" +#include "vtkUnstructuredGridVolumeRayCastMapper.h" +#include "vtkVolume.h" +#include "vtkRenderer.h" +#include "vtkCamera.h" +#include "vtkMatrix4x4.h" +#include "vtkTransform.h" +#include "vtkCell.h" +#include "vtkCellType.h" +#include "vtkMath.h" +#include "vtkPointData.h" +#include "vtkCellArray.h" +#include "vtkDoubleArray.h" +#include "vtkIdList.h" +#include "vtkPiecewiseFunction.h" +#include "vtkColorTransferFunction.h" +#include "vtkVolumeProperty.h" +#include "vtkUnstructuredGridVolumeRayCastIterator.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridBunykRayCastFunction, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkUnstructuredGridBunykRayCastFunction); + +#define VTK_BUNYKRCF_NUMLISTS 100000 + +#define VTK_BUNYKRCF_MAX_COMPONENTS 4 + +template <class T> +vtkIdType TemplateCastRay( + const T *scalars, + vtkUnstructuredGridBunykRayCastFunction *self, + int numComponents, + int x, int y, + double farClipZ, + vtkUnstructuredGridBunykRayCastFunction::Intersection *&intersectionPtr, + vtkUnstructuredGridBunykRayCastFunction::Triangle *¤tTriangle, + vtkIdType ¤tTetra, + vtkIdType *intersectedCells, + double *intersectionLengths, + T *nearIntersections, + T *farIntersections, + int maxNumIntersections); + +//----------------------------------------------------------------------------- + +// This is an internal hidden class. + +class vtkUnstructuredGridBunykRayCastIterator + : public vtkUnstructuredGridVolumeRayCastIterator +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridBunykRayCastIterator, + vtkUnstructuredGridVolumeRayCastIterator); + static vtkUnstructuredGridBunykRayCastIterator *New(); + + void Initialize(int x, int y); + + vtkIdType GetNextIntersections(vtkIdList *intersectedCells, + vtkDoubleArray *intersectionLengths, + vtkDataArray *scalars, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections); + + vtkSetObjectMacro(RayCastFunction, vtkUnstructuredGridBunykRayCastFunction); + vtkGetObjectMacro(RayCastFunction, vtkUnstructuredGridBunykRayCastFunction); + +protected: + vtkUnstructuredGridBunykRayCastIterator(); + ~vtkUnstructuredGridBunykRayCastIterator(); + + int RayPosition[2]; + + vtkUnstructuredGridBunykRayCastFunction *RayCastFunction; + + vtkUnstructuredGridBunykRayCastFunction::Intersection *IntersectionPtr; + vtkUnstructuredGridBunykRayCastFunction::Triangle *CurrentTriangle; + vtkIdType CurrentTetra; + +private: + vtkUnstructuredGridBunykRayCastIterator(const vtkUnstructuredGridBunykRayCastIterator&); // Not implemented + void operator=(const vtkUnstructuredGridBunykRayCastIterator&); // Not implemented +}; + +vtkCxxRevisionMacro(vtkUnstructuredGridBunykRayCastIterator, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkUnstructuredGridBunykRayCastIterator); + +vtkUnstructuredGridBunykRayCastIterator::vtkUnstructuredGridBunykRayCastIterator() +{ + this->RayCastFunction = NULL; +} + +vtkUnstructuredGridBunykRayCastIterator::~vtkUnstructuredGridBunykRayCastIterator() +{ + this->SetRayCastFunction(NULL); +} + +void vtkUnstructuredGridBunykRayCastIterator::Initialize(int x, int y) +{ + this->RayPosition[0] = x; this->RayPosition[1] = y; + + this->IntersectionPtr + = this->RayCastFunction->GetIntersectionList(this->RayPosition[0], + this->RayPosition[1]); + this->CurrentTriangle = NULL; + this->CurrentTetra = -1; + + // Intersect cells until we get to Bounds[0] (the near clip plane). + while(TemplateCastRay((const float *)NULL, + this->RayCastFunction, 0, + this->RayPosition[0], this->RayPosition[1], + this->Bounds[0], + this->IntersectionPtr, + this->CurrentTriangle, + this->CurrentTetra, + (vtkIdType *)NULL, + (double *)NULL, + (float *)NULL, + (float *)NULL, + this->MaxNumberOfIntersections) > 0); +} + +vtkIdType vtkUnstructuredGridBunykRayCastIterator::GetNextIntersections( + vtkIdList *intersectedCells, + vtkDoubleArray *intersectionLengths, + vtkDataArray *scalars, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections) +{ + if (intersectedCells) + { + intersectedCells->SetNumberOfIds(this->MaxNumberOfIntersections); + } + if (intersectionLengths) + { + intersectionLengths->SetNumberOfComponents(1); + intersectionLengths->SetNumberOfTuples(this->MaxNumberOfIntersections); + } + + vtkIdType numIntersections = 0; + + if (!scalars) + { + numIntersections = TemplateCastRay + ((const float *)NULL, this->RayCastFunction, 0, + this->RayPosition[0], this->RayPosition[1], this->Bounds[1], + this->IntersectionPtr, this->CurrentTriangle, this->CurrentTetra, + (intersectedCells ? intersectedCells->GetPointer(0) : NULL), + (intersectionLengths ? intersectionLengths->GetPointer(0) : NULL), + (float *)NULL, (float *)NULL, this->MaxNumberOfIntersections); + } + else + { + if ( (scalars->GetDataType() != nearIntersections->GetDataType()) + || (scalars->GetDataType() != farIntersections->GetDataType()) ) + { + vtkErrorMacro(<< "Data types for scalars do not match up."); + } + + nearIntersections->SetNumberOfComponents(scalars->GetNumberOfComponents()); + nearIntersections->SetNumberOfTuples(this->MaxNumberOfIntersections); + farIntersections->SetNumberOfComponents(scalars->GetNumberOfComponents()); + farIntersections->SetNumberOfTuples(this->MaxNumberOfIntersections); + + switch (scalars->GetDataType()) + { + vtkTemplateMacro + (numIntersections = TemplateCastRay + ((const VTK_TT *)scalars->GetVoidPointer(0), + this->RayCastFunction, scalars->GetNumberOfComponents(), + this->RayPosition[0], this->RayPosition[1], this->Bounds[1], + this->IntersectionPtr, this->CurrentTriangle, this->CurrentTetra, + (intersectedCells ? intersectedCells->GetPointer(0) : NULL), + (intersectionLengths ? intersectionLengths->GetPointer(0) : NULL), + (VTK_TT *)nearIntersections->GetVoidPointer(0), + (VTK_TT *)farIntersections->GetVoidPointer(0), + this->MaxNumberOfIntersections)); + } + + nearIntersections->SetNumberOfTuples(numIntersections); + farIntersections->SetNumberOfTuples(numIntersections); + } + + if (intersectedCells) + { + intersectedCells->SetNumberOfIds(numIntersections); + } + if (intersectionLengths) + { + intersectionLengths->SetNumberOfTuples(numIntersections); + } + + return numIntersections; +} + +//----------------------------------------------------------------------------- + +// Constructor - initially everything to null, and create a matrix for use later +vtkUnstructuredGridBunykRayCastFunction::vtkUnstructuredGridBunykRayCastFunction() +{ + this->Renderer = NULL; + this->Volume = NULL; + this->Mapper = NULL; + this->Valid = 0; + this->Points = NULL; + this->Image = NULL; + this->TriangleList = NULL; + this->TetraTriangles = NULL; + this->NumberOfPoints = 0; + this->ImageSize[0] = 0; + this->ImageSize[1] = 0; + this->ViewToWorldMatrix = vtkMatrix4x4::New(); + + for (int i = 0; i < VTK_BUNYKRCF_MAX_ARRAYS; i++ ) + { + this->IntersectionBuffer[i] = NULL; + this->IntersectionBufferCount[i] = 0; + } + + this->SavedTriangleListInput = NULL; +} + +// Destructor - release all memory +vtkUnstructuredGridBunykRayCastFunction::~vtkUnstructuredGridBunykRayCastFunction() +{ + delete [] this->Points; + + this->ClearImage(); + delete [] this->Image; + this->Image = NULL; + + delete [] this->TetraTriangles; + + int i; + for (i = 0; i < 20; i++ ) + { + delete [] this->IntersectionBuffer[i]; + } + + while ( this->TriangleList ) + { + Triangle *tmp; + tmp = this->TriangleList->Next; + delete this->TriangleList; + this->TriangleList = tmp; + } + + this->ViewToWorldMatrix->Delete(); +} + +// Clear the intersection image. This does NOT release memory - +// it just sets the link pointers to NULL. The memory is +// contained in the IntersectionBuffer arrays. +void vtkUnstructuredGridBunykRayCastFunction::ClearImage() +{ + int i; + if ( this->Image ) + { + for ( i = 0; i < this->ImageSize[0]*this->ImageSize[1]; i++ ) + { + this->Image[i] = NULL; + } + } + + for ( i = 0; i < VTK_BUNYKRCF_MAX_ARRAYS; i++ ) + { + this->IntersectionBufferCount[i] = 0; + } +} + +// Since we are managing the memory ourself for these intersections, +// we need a new method. In this method we return an unused +// intersection element from our storage arrays. If we don't +// have one, we create a new storage array (unless we have run +// out of memory). The memory can never shrink, and will only be +// deleted when the class is destructed. +void *vtkUnstructuredGridBunykRayCastFunction::NewIntersection() +{ + // Look for the first buffer that has enough space, or the + // first one that has not yet been allocated + int i; + for ( i = 0; i < VTK_BUNYKRCF_MAX_ARRAYS; i++ ) + { + if ( !this->IntersectionBuffer[i] || + this->IntersectionBufferCount[i] < VTK_BUNYKRCF_ARRAY_SIZE ) + { + break; + } + } + + // We have run out of space - return NULL + if ( i == VTK_BUNYKRCF_MAX_ARRAYS ) + { + vtkErrorMacro("Out of space for intersections!"); + return NULL; + } + + // We need another array - allocate it and set its count to 0 indicating + // that we have not used any elements yet + if ( !this->IntersectionBuffer[i] ) + { + this->IntersectionBuffer[i] = new Intersection[VTK_BUNYKRCF_ARRAY_SIZE]; + this->IntersectionBufferCount[i] = 0; + } + + // Return the first unused element + return (this->IntersectionBuffer[i] + (this->IntersectionBufferCount[i]++)); + +} + +// The Intialize method is called from the ray caster at the start of +// rendering. In this method we check if the render is valid (there is +// a renderer, a volume, a mapper, input, etc). We build the basic +// structured if necessary. Then we compute the view dependent information +// such as plane equations and barycentric coordinates per triangle, +// tranfromed points in view space, and the intersection list per pixel. +void vtkUnstructuredGridBunykRayCastFunction::Initialize( vtkRenderer *ren, + vtkVolume *vol ) +{ + // Check if this is a valid render - we have all the required info + // such as the volume, renderer, mapper, input, etc. + this->Valid = this->CheckValidity( ren, vol ); + if ( !this->Valid ) + { + return; + } + + // Cache some objects for later use during rendering + this->Mapper = vtkUnstructuredGridVolumeRayCastMapper::SafeDownCast( vol->GetMapper() ); + this->Renderer = ren; + this->Volume = vol; + + + vtkUnstructuredGrid *input = this->Mapper->GetInput(); + int numPoints = input->GetNumberOfPoints(); + + // If the number of points have changed, recreate the structure + if ( numPoints != this->NumberOfPoints ) + { + delete [] this->Points; + this->Points = new double[3*numPoints]; + this->NumberOfPoints = numPoints; + } + + // Get the image size from the ray cast mapper. The ImageViewportSize is + // the size of the whole viewport (this does not necessary equal pixel + // size since we may be over / undersampling on the image plane). The size + // (which will be stored in ImageSize) and the ImageOrigin represent the + // subregion of the whole image that we will be considering. + int size[2]; + this->Mapper->GetImageInUseSize( size ); + this->Mapper->GetImageOrigin( this->ImageOrigin ); + this->Mapper->GetImageViewportSize( this->ImageViewportSize ); + + // If our intersection image is not the right size, recreate it. + // Clear out any old intersections + this->ClearImage(); + if ( this->ImageSize[0]*this->ImageSize[1] != size[0]*size[1] ) + { + delete [] this->Image; + this->Image = new Intersection *[size[0]*size[1]]; + this->ImageSize[0] = size[0]; + this->ImageSize[1] = size[1]; + this->ClearImage(); + } + + // Tranform the points. As a by product, compute the ViewToWorldMatrix + // that will be used later + this->TransformPoints(); + + // If it has not yet been built, or the data has changed in + // some way, we will need to recreate the triangle list. This is + // view independent - although we will leave space in the structure + // for the view dependent info + this->UpdateTriangleList(); + + // For each triangle store the plane equation and barycentric + // coefficients to be used to speed up rendering + this->ComputeViewDependentInfo(); + + // Project each boundary triangle onto the image and store intersections + // sorted by depth + this->ComputePixelIntersections(); +} + +int vtkUnstructuredGridBunykRayCastFunction::CheckValidity( vtkRenderer *ren, + vtkVolume *vol ) +{ + // We must have a renderer + if ( !ren ) + { + vtkErrorMacro("No Renderer"); + return 0; + } + + // We must have a volume + if ( !vol ) + { + vtkErrorMacro("No Volume"); + return 0; + } + + // We must have a mapper of the correct type + vtkUnstructuredGridVolumeRayCastMapper *mapper = + vtkUnstructuredGridVolumeRayCastMapper::SafeDownCast( vol->GetMapper() ); + if ( !mapper ) + { + vtkErrorMacro("No mapper or wrong type"); + return 0; + } + + // The mapper must have input + vtkUnstructuredGrid *input = mapper->GetInput(); + if ( !input ) + { + vtkErrorMacro("No input to mapper"); + return 0; + } + + // The input must have some points. This is a silent + // error - just render nothing if it occurs. + int numPoints = input->GetNumberOfPoints(); + if ( numPoints == 0 ) + { + this->Valid = 0; + return 0; + } + + return 1; +} + + +// This is done once per render - transform the points into view coordinate. +// We also compute the ViewToWorldMatrix here (by inverting the matrix +// we use to project to view coordinates) so that later on in the +// rendering process we can convert points back to world coordinates. +void vtkUnstructuredGridBunykRayCastFunction::TransformPoints() +{ + vtkRenderer *ren = this->Renderer; + vtkVolume *vol = this->Volume; + + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + vtkTransform *perspectiveTransform = vtkTransform::New(); + vtkMatrix4x4 *perspectiveMatrix = vtkMatrix4x4::New(); + + // Get the view matrix in two steps - there is a one step method in camera + // but it turns off stereo so we do not want to use that one + vtkCamera *cam = ren->GetActiveCamera(); + perspectiveTransform->Identity(); + perspectiveTransform-> + Concatenate(cam->GetPerspectiveTransformMatrix(aspect[0]/ + aspect[1], 0.0, 1.0 )); + perspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + perspectiveTransform->Concatenate(vol->GetMatrix()); + perspectiveMatrix->DeepCopy(perspectiveTransform->GetMatrix()); + + // Invert this project matrix and store for later use + this->ViewToWorldMatrix->DeepCopy(perspectiveTransform->GetMatrix()); + this->ViewToWorldMatrix->Invert(); + + double *origPtr; + double *transformedPtr = this->Points; + double in[4], out[4]; + in[3] = 1.0; + vtkUnstructuredGrid *input = this->Mapper->GetInput(); + int numPoints = input->GetNumberOfPoints(); + + // Loop through all the points and transform them + for ( int i = 0; i < numPoints; i++ ) + { + origPtr = input->GetPoint( i ); + in[0] = origPtr[0]; + in[1] = origPtr[1]; + in[2] = origPtr[2]; + perspectiveMatrix->MultiplyPoint( in, out ); + transformedPtr[0] = (out[0]/out[3] + 1.0)/2.0 * + (double)this->ImageViewportSize[0] - this->ImageOrigin[0]; + transformedPtr[1] = (out[1]/out[3] + 1.0)/2.0 * + (double)this->ImageViewportSize[1] - this->ImageOrigin[1]; + transformedPtr[2] = out[2]/out[3]; + + transformedPtr += 3; + } + + perspectiveTransform->Delete(); + perspectiveMatrix->Delete(); + +} + +// This is done once per change in the data - build a list of +// enumerated triangles (up to four per tetra). Don't store +// duplicates, so we'll have to search for them. +void vtkUnstructuredGridBunykRayCastFunction::UpdateTriangleList() +{ + int needsUpdate = 0; + + // If we have never created the list, we need updating + if ( !this->TriangleList ) + { + needsUpdate = 1; + } + + // If the data has changed in some way then we need to update + vtkUnstructuredGrid *input = this->Mapper->GetInput(); + if ( this->SavedTriangleListInput != input || + input->GetMTime() > this->SavedTriangleListMTime.GetMTime() ) + { + needsUpdate = 1; + } + + + // If we don't need updating, return + if ( !needsUpdate ) + { + return; + } + + + // Clear out the old triangle list + while ( this->TriangleList ) + { + Triangle *tmp; + tmp = this->TriangleList->Next; + delete this->TriangleList; + this->TriangleList = tmp; + } + this->TriangleList = NULL; + + // A temporary structure to reduce search time - VTK_BUNYKRCF_NUMLISTS small + // lists instead of one big one + Triangle *tmpList[VTK_BUNYKRCF_NUMLISTS]; + + vtkIdType i; + for ( i = 0; i < VTK_BUNYKRCF_NUMLISTS; i++ ) + { + tmpList[i] = NULL; + } + + int numCells = input->GetNumberOfCells(); + + // Provide a warning if we find anything other than tetra + int warningNeeded = 0; + + // Create a set of links from each tetra to the four triangles + // This is redundant information, but saves time during rendering + this->TetraTriangles = new Triangle *[4 * numCells]; + + // Loop through all the cells + for ( i = 0; i < numCells; i++ ) + { + // We only handle tetra + if ( input->GetCellType(i) != VTK_TETRA ) + { + warningNeeded = 1; + continue; + } + + // Get the cell + vtkCell *cell = input->GetCell(i); + + // Get the four points + vtkIdType pts[4]; + pts[0] = cell->GetPointId(0); + pts[1] = cell->GetPointId(1); + pts[2] = cell->GetPointId(2); + pts[3] = cell->GetPointId(3); + + // Build each of the four triangles + int ii, jj; + for ( jj = 0; jj < 4; jj++ ) + { + vtkIdType tri[3]; + int idx = 0; + for ( ii = 0; ii < 4; ii++ ) + { + if ( ii != jj ) + { + tri[idx++] = pts[ii]; + } + } + + if ( tri[0] > tri[1] ) + { + vtkIdType tmptri = tri[0]; + tri[0] = tri[1]; + tri[1] = tmptri; + } + if ( tri[1] > tri[2] ) + { + vtkIdType tmptri = tri[1]; + tri[1] = tri[2]; + tri[2] = tmptri; + } + if ( tri[0] > tri[1] ) + { + vtkIdType tmptri = tri[0]; + tri[0] = tri[1]; + tri[1] = tmptri; + } + + // Do we have this triangle already? + Triangle *triPtr = tmpList[tri[0]%VTK_BUNYKRCF_NUMLISTS]; + while ( triPtr ) + { + if ( triPtr->PointIndex[0] == tri[0] && + triPtr->PointIndex[1] == tri[1] && + triPtr->PointIndex[2] == tri[2] ) + { + break; + } + triPtr = triPtr->Next; + } + + if ( triPtr ) + { + if ( triPtr->ReferredByTetra[1] != -1 ) + { + vtkErrorMacro("Degenerate topology - cell face used more than twice"); + } + triPtr->ReferredByTetra[1] = i; + this->TetraTriangles[i*4+jj] = triPtr; + } + else + { + Triangle *next = new Triangle; + next->PointIndex[0] = tri[0]; + next->PointIndex[1] = tri[1]; + next->PointIndex[2] = tri[2]; + next->ReferredByTetra[0] = i; + next->ReferredByTetra[1] = -1; + + next->Next = tmpList[tri[0]%VTK_BUNYKRCF_NUMLISTS]; + tmpList[tri[0]%VTK_BUNYKRCF_NUMLISTS] = next; + this->TetraTriangles[i*4+jj] = next; + } + } + } + + if ( warningNeeded ) + { + vtkWarningMacro("Input contains more than tetrahedra - only tetrahedra are supported"); + } + + // Put the list together + for ( i = 0; i < VTK_BUNYKRCF_NUMLISTS; i++ ) + { + if ( tmpList[i] ) + { + Triangle *last = tmpList[i]; + while ( last->Next ) + { + last = last->Next; + } + last->Next = this->TriangleList; + this->TriangleList = tmpList[i]; + } + } + + this->SavedTriangleListInput = input; + this->SavedTriangleListMTime.Modified(); +} + +void vtkUnstructuredGridBunykRayCastFunction::ComputeViewDependentInfo() +{ + Triangle *triPtr = this->TriangleList; + while ( triPtr ) + { + double P1[3], P2[3]; + double A[3], B[3], C[3]; + + A[0] = this->Points[3*triPtr->PointIndex[0]]; + A[1] = this->Points[3*triPtr->PointIndex[0]+1]; + A[2] = this->Points[3*triPtr->PointIndex[0]+2]; + B[0] = this->Points[3*triPtr->PointIndex[1]]; + B[1] = this->Points[3*triPtr->PointIndex[1]+1]; + B[2] = this->Points[3*triPtr->PointIndex[1]+2]; + C[0] = this->Points[3*triPtr->PointIndex[2]]; + C[1] = this->Points[3*triPtr->PointIndex[2]+1]; + C[2] = this->Points[3*triPtr->PointIndex[2]+2]; + + P1[0] = B[0] - A[0]; + P1[1] = B[1] - A[1]; + P1[2] = B[2] - A[2]; + + P2[0] = C[0] - A[0]; + P2[1] = C[1] - A[1]; + P2[2] = C[2] - A[2]; + + triPtr->Denominator = P1[0]*P2[1] - P2[0]*P1[1]; + + if ( triPtr->Denominator < 0 ) + { + double T[3]; + triPtr->Denominator = -triPtr->Denominator; + T[0] = P1[0]; + T[1] = P1[1]; + T[2] = P1[2]; + P1[0] = P2[0]; + P1[1] = P2[1]; + P1[2] = P2[2]; + P2[0] = T[0]; + P2[1] = T[1]; + P2[2] = T[2]; + vtkIdType tmpIndex = triPtr->PointIndex[1]; + triPtr->PointIndex[1] = triPtr->PointIndex[2]; + triPtr->PointIndex[2] = tmpIndex; + } + + triPtr->P1X = P1[0]; + triPtr->P1Y = P1[1]; + triPtr->P2X = P2[0]; + triPtr->P2Y = P2[1]; + + double result[3]; + vtkMath::Cross( P1, P2, result ); + triPtr->A = result[0]; + triPtr->B = result[1]; + triPtr->C = result[2]; + triPtr->D = -(A[0]*result[0] + A[1]*result[1] + A[2]*result[2]); + + triPtr = triPtr->Next; + } +} + +void vtkUnstructuredGridBunykRayCastFunction::ComputePixelIntersections() +{ + Triangle *triPtr = this->TriangleList; + while ( triPtr ) + { + if ( triPtr->ReferredByTetra[1] == -1 ) + { + if ( this->IsTriangleFrontFacing( triPtr, triPtr->ReferredByTetra[0] ) ) + { + int minX = static_cast<int>(this->Points[3*triPtr->PointIndex[0]]); + int maxX = minX+1; + int minY = static_cast<int>(this->Points[3*triPtr->PointIndex[0]+1]); + int maxY = minY+1; + + int tmp; + + tmp = static_cast<int>(this->Points[3*triPtr->PointIndex[1]]); + minX = (tmp<minX)?(tmp):(minX); + maxX = ((tmp+1)>maxX)?(tmp+1):(maxX); + + tmp = static_cast<int>(this->Points[3*triPtr->PointIndex[1]+1]); + minY = (tmp<minY)?(tmp):(minY); + maxY = ((tmp+1)>maxY)?(tmp+1):(maxY); + + tmp = static_cast<int>(this->Points[3*triPtr->PointIndex[2]]); + minX = (tmp<minX)?(tmp):(minX); + maxX = ((tmp+1)>maxX)?(tmp+1):(maxX); + + tmp = static_cast<int>(this->Points[3*triPtr->PointIndex[2]+1]); + minY = (tmp<minY)?(tmp):(minY); + maxY = ((tmp+1)>maxY)?(tmp+1):(maxY); + + double minZ = this->Points[3*triPtr->PointIndex[0]+2]; + double ftmp; + + ftmp = this->Points[3*triPtr->PointIndex[1]+2]; + minZ = (ftmp<minZ)?(ftmp):(minZ); + + ftmp = this->Points[3*triPtr->PointIndex[2]+2]; + minZ = (ftmp<minZ)?(ftmp):(minZ); + + if ( minX < this->ImageSize[0] - 1 && + minY < this->ImageSize[1] - 1 && + maxX >= 0 && maxY >= 0 && minZ > 0.0 ) + { + minX = (minX<0)?(0):(minX); + maxX = (maxX>(this->ImageSize[0]-1))?(this->ImageSize[0]-1):(maxX); + + minY = (minY<0)?(0):(minY); + maxY = (maxY>(this->ImageSize[1]-1))?(this->ImageSize[1]-1):(maxY); + + int x, y; + double ax, ay, az; + ax = this->Points[3*triPtr->PointIndex[0]]; + ay = this->Points[3*triPtr->PointIndex[0]+1]; + az = this->Points[3*triPtr->PointIndex[0]+2]; + + for ( y = minY; y <= maxY; y++ ) + { + double qy = (double)y - ay; + for ( x = minX; x <= maxX; x++ ) + { + double qx = (double)x - ax; + if ( this->InTriangle( qx, qy, triPtr ) ) + { + Intersection *intersect = (Intersection *)this->NewIntersection(); + if ( intersect ) + { + intersect->TriPtr = triPtr; + intersect->Z = az; + intersect->Next = NULL; + + if ( !this->Image[y*this->ImageSize[0] + x] || + intersect->Z < this->Image[y*this->ImageSize[0] + x]->Z ) + { + intersect->Next = this->Image[y*this->ImageSize[0] + x]; + this->Image[y*this->ImageSize[0] + x] = intersect; + } + else + { + Intersection *test = this->Image[y*this->ImageSize[0] + x]; + while ( test->Next && intersect->Z > test->Next->Z ) + { + test = test->Next; + } + Intersection *tmpNext = test->Next; + test->Next = intersect; + intersect->Next = tmpNext; + } + } + } + } + } + } + } + } + triPtr = triPtr->Next; + } +} + +// Taken from equation on bottom of left column of page 3 - but note that the +// equation in the paper has a mistake: (q1+q2) must be less than 1 (not denom as +// stated in the paper). +int vtkUnstructuredGridBunykRayCastFunction::InTriangle( double x, double y, Triangle *triPtr ) +{ + double q1, q2; + + q1 = (x*triPtr->P2Y - y*triPtr->P2X) / triPtr->Denominator; + q2 = (y*triPtr->P1X - x*triPtr->P1Y) / triPtr->Denominator; + + if ( q1 >= 0 && q2 >= 0 && (q1+q2) <= 1.0 ) + { + return 1; + } + else + { + return 0; + } +} + +int vtkUnstructuredGridBunykRayCastFunction::IsTriangleFrontFacing( Triangle *triPtr, vtkIdType tetraIndex ) +{ + vtkCell *cell = this->Mapper->GetInput()->GetCell(tetraIndex); + + vtkIdType pts[4]; + pts[0] = cell->GetPointId(0); + pts[1] = cell->GetPointId(1); + pts[2] = cell->GetPointId(2); + pts[3] = cell->GetPointId(3); + + int i; + for( i = 0; i < 4; i++ ) + { + if ( pts[i] != triPtr->PointIndex[0] && + pts[i] != triPtr->PointIndex[1] && + pts[i] != triPtr->PointIndex[2] ) + { + break; + } + } + + double d = + triPtr->A*this->Points[3*pts[i]] + + triPtr->B*this->Points[3*pts[i]+1] + + triPtr->C*this->Points[3*pts[i]+2] + + triPtr->D; + + return (d>0); +} + +template <class T> +vtkIdType TemplateCastRay( + const T *scalars, + vtkUnstructuredGridBunykRayCastFunction *self, + int numComponents, + int x, int y, + double farClipZ, + vtkUnstructuredGridBunykRayCastFunction::Intersection *&intersectionPtr, + vtkUnstructuredGridBunykRayCastFunction::Triangle *¤tTriangle, + vtkIdType ¤tTetra, + vtkIdType *intersectedCells, + double *intersectionLengths, + T *nearIntersections, + T *farIntersections, + int maxNumIntersections) +{ + int imageViewportSize[2]; + self->GetImageViewportSize( imageViewportSize ); + + int origin[2]; + self->GetImageOrigin( origin ); + float fx = x - origin[0]; + float fy = y - origin[1]; + + double *points = self->GetPoints(); + vtkUnstructuredGridBunykRayCastFunction::Triangle + **triangles = self->GetTetraTriangles(); + + vtkMatrix4x4 *viewToWorld = self->GetViewToWorldMatrix(); + + vtkUnstructuredGridBunykRayCastFunction::Triangle *nextTriangle; + vtkIdType nextTetra; + + vtkIdType numIntersections = 0; + + double nearZ = VTK_FLOAT_MIN; + double nearPoint[4]; + double viewCoords[4]; + viewCoords[0] = ((float)x / (float)(imageViewportSize[0]-1)) * 2.0 - 1.0; + viewCoords[1] = ((float)y / (float)(imageViewportSize[1]-1)) * 2.0 - 1.0; + // viewCoords[2] set when an intersection is found. + viewCoords[3] = 1.0; + if (currentTriangle) + { + // Find intersection in currentTriangle (the entry point). + nearZ = -( fx*currentTriangle->A + fy*currentTriangle->B + + currentTriangle->D) / currentTriangle->C; + + viewCoords[2] = nearZ; + + viewToWorld->MultiplyPoint( viewCoords, nearPoint ); + nearPoint[0] /= nearPoint[3]; + nearPoint[1] /= nearPoint[3]; + nearPoint[2] /= nearPoint[3]; + } + + while (numIntersections < maxNumIntersections) + { + // If we have exited the mesh (or are entering it for the first time, + // find the next intersection with an external face (which has already + // been found with rasterization). + if (!currentTriangle) + { + if (!intersectionPtr) + { + break; // No more intersections. + } + currentTriangle = intersectionPtr->TriPtr; + currentTetra = intersectionPtr->TriPtr->ReferredByTetra[0]; + intersectionPtr = intersectionPtr->Next; + + // Find intersection in currentTriangle (the entry point). + nearZ = -( fx*currentTriangle->A + fy*currentTriangle->B + + currentTriangle->D) / currentTriangle->C; + + viewCoords[2] = nearZ; + + viewToWorld->MultiplyPoint( viewCoords, nearPoint ); + nearPoint[0] /= nearPoint[3]; + nearPoint[1] /= nearPoint[3]; + nearPoint[2] /= nearPoint[3]; + } + + // Find all triangles that the ray may exit. + vtkUnstructuredGridBunykRayCastFunction::Triangle *candidate[3]; + + int index = 0; + int i; + for ( i = 0; i < 4; i++ ) + { + if ( triangles[currentTetra*4+i] != currentTriangle ) + { + if ( index == 3 ) + { + vtkGenericWarningMacro( "Ugh - found too many triangles!" ); + } + else + { + candidate[index++] = triangles[currentTetra*4+i]; + } + } + } + + double farZ = VTK_FLOAT_MAX; + int minIdx = -1; + + // Determine which face the ray exits the cell from. + for ( i = 0; i < 3; i++ ) + { + // Far intersection is the nearest intersectation that is farther + // than nearZ. + double tmpZ = 1.0; + if (candidate[i]->C != 0.0) + { + tmpZ = + -( fx*candidate[i]->A + + fy*candidate[i]->B + + candidate[i]->D) / candidate[i]->C; + } + if (tmpZ > nearZ && tmpZ < farZ) + { + farZ = tmpZ; + minIdx = i; + } + } + + if (farZ > farClipZ) + { + // Exit happened after point of interest. Bail out now (in case + // we wish to restart). + return numIntersections; + } + + if (minIdx == -1) + { + // The ray never exited the cell? Perhaps numerical inaccuracies + // got us here. Just bail out as if we exited the mesh. + nextTriangle = NULL; + nextTetra = -1; + } + else + { + if (intersectedCells) + { + intersectedCells[numIntersections] = currentTetra; + } + + nextTriangle = candidate[minIdx]; + + // Compute intersection with exiting face. + double farPoint[4]; + viewCoords[2] = farZ; + viewToWorld->MultiplyPoint( viewCoords, farPoint ); + farPoint[0] /= farPoint[3]; + farPoint[1] /= farPoint[3]; + farPoint[2] /= farPoint[3]; + double dist + = sqrt( (nearPoint[0]-farPoint[0])*(nearPoint[0]-farPoint[0]) + + (nearPoint[1]-farPoint[1])*(nearPoint[1]-farPoint[1]) + + (nearPoint[2]-farPoint[2])*(nearPoint[2]-farPoint[2]) ); + + if (intersectionLengths) + { + intersectionLengths[numIntersections] = dist; + } + + // compute the barycentric weights + float ax, ay; + double a1, b1, c1; + ax = points[3*currentTriangle->PointIndex[0]]; + ay = points[3*currentTriangle->PointIndex[0]+1]; + b1 = ((fx-ax)*currentTriangle->P2Y - (fy-ay)*currentTriangle->P2X) / currentTriangle->Denominator; + c1 = ((fy-ay)*currentTriangle->P1X - (fx-ax)*currentTriangle->P1Y) / currentTriangle->Denominator; + a1 = 1.0 - b1 - c1; + + double a2, b2, c2; + ax = points[3*nextTriangle->PointIndex[0]]; + ay = points[3*nextTriangle->PointIndex[0]+1]; + b2 = ((fx-ax)*nextTriangle->P2Y - (fy-ay)*nextTriangle->P2X) / nextTriangle->Denominator; + c2 = ((fy-ay)*nextTriangle->P1X - (fx-ax)*nextTriangle->P1Y) / nextTriangle->Denominator; + a2 = 1.0 - b2 - c2; + + if (nearIntersections) + { + for (int c = 0; c < numComponents; c++) + { + double A, B, C; + A = *(scalars + numComponents*currentTriangle->PointIndex[0] + c); + B = *(scalars + numComponents*currentTriangle->PointIndex[1] + c); + C = *(scalars + numComponents*currentTriangle->PointIndex[2] + c); + nearIntersections[numComponents*numIntersections + c] + = static_cast<T>(a1 * A + b1 * B + c1 * C); + } + } + + if (farIntersections) + { + for (int c = 0; c < numComponents; c++) + { + double A, B, C; + A = *(scalars + numComponents*nextTriangle->PointIndex[0] + c); + B = *(scalars + numComponents*nextTriangle->PointIndex[1] + c); + C = *(scalars + numComponents*nextTriangle->PointIndex[2] + c); + farIntersections[numComponents*numIntersections + c] + = static_cast<T>(a2 * A + b2 * B + c2 * C); + } + } + + numIntersections++; + + // The far triangle has one or two tetras in its referred list. + // If one, return -1 for next tetra and NULL for next triangle + // since we are exiting. If two, return the one that isn't the + // current one. + if ( (nextTriangle)->ReferredByTetra[1] == -1 ) + { + nextTetra = -1; + nextTriangle = NULL; + } + else + { + if ( nextTriangle->ReferredByTetra[0] == currentTetra ) + { + nextTetra = nextTriangle->ReferredByTetra[1]; + } + else + { + nextTetra = nextTriangle->ReferredByTetra[0]; + } + } + + nearZ = farZ; + nearPoint[0] = farPoint[0]; + nearPoint[1] = farPoint[1]; + nearPoint[2] = farPoint[2]; + nearPoint[3] = farPoint[3]; + } + + currentTriangle = nextTriangle; + currentTetra = nextTetra; + } + + return numIntersections; +} + +vtkUnstructuredGridVolumeRayCastIterator + *vtkUnstructuredGridBunykRayCastFunction::NewIterator() +{ + if (!this->Valid) return NULL; + + vtkUnstructuredGridBunykRayCastIterator *iterator + = vtkUnstructuredGridBunykRayCastIterator::New(); + iterator->SetRayCastFunction(this); + + return iterator; +} + +void vtkUnstructuredGridBunykRayCastFunction::Finalize( ) +{ + this->Renderer = NULL; + this->Volume = NULL; + this->Mapper = NULL; + + this->Valid = 0; +} + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridBunykRayCastFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + // Do not want to print this->ViewToWorldMatrix , this->ImageViewportSize + // this->ScalarOpacityUnitDistance , or this->ImageOrigin - these are + // internal ivar and not part of the public API for this class +} + + diff --git a/VolumeRendering/vtkUnstructuredGridBunykRayCastFunction.h b/VolumeRendering/vtkUnstructuredGridBunykRayCastFunction.h new file mode 100644 index 0000000..ed56816 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridBunykRayCastFunction.h @@ -0,0 +1,268 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridBunykRayCastFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkUnstructuredGridBunykRayCastFunction - a superclass for ray casting functions + +// .SECTION Description +// vtkUnstructuredGridBunykRayCastFunction is a concrete implementation of a +// ray cast function for unstructured grid data. This class was based on the +// paper "Simple, Fast, Robust Ray Casting of Irregular Grids" by Paul Bunyk, +// Arie Kaufmna, and Claudio Silva. This method is quite memory intensive +// (with extra explicit copies of the data) and therefore should not be used +// for very large data. This method assumes that the input data is composed +// entirely of tetras - use vtkDataSetTriangleFilter before setting the input +// on the mapper. +// +// The basic idea of this method is as follows: +// +// 1) Enumerate the triangles. At each triangle have space for some +// information that will be used during rendering. This includes +// which tetra the triangles belong to, the plane equation and the +// Barycentric coefficients. +// +// 2) Keep a reference to all four triangles for each tetra. +// +// 3) At the beginning of each render, do the precomputation. This +// includes creating an array of transformed points (in view +// coordinates) and computing the view dependent info per triangle +// (plane equations and barycentric coords in view space) +// +// 4) Find all front facing boundary triangles (a triangle is on the +// boundary if it belongs to only one tetra). For each triangle, +// find all pixels in the image that intersect the triangle, and +// add this to the sorted (by depth) intersection list at each +// pixel. +// +// 5) For each ray cast, traverse the intersection list. At each +// intersection, accumulate opacity and color contribution +// per tetra along the ray until you reach an exiting triangle +// (on the boundary). +// + +// .SECTION See Also +// vtkUnstructuredGridVolumeRayCastMapper + +#ifndef __vtkUnstructuredGridBunykRayCastFunction_h +#define __vtkUnstructuredGridBunykRayCastFunction_h + +#include "vtkUnstructuredGridVolumeRayCastFunction.h" + +class vtkRenderer; +class vtkVolume; +class vtkUnstructuredGridVolumeRayCastMapper; +class vtkMatrix4x4; +class vtkPiecewiseFunction; +class vtkColorTransferFunction; +class vtkUnstructuredGrid; +class vtkIdList; +class vtkDoubleArray; +class vtkDataArray; + +// We manage the memory for the list of intersections ourself - this is the +// storage used. We keep 10,000 elements in each array, and we can have up to +// 1,000 arrays. +#define VTK_BUNYKRCF_MAX_ARRAYS 10000 +#define VTK_BUNYKRCF_ARRAY_SIZE 10000 + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridBunykRayCastFunction : public vtkUnstructuredGridVolumeRayCastFunction +{ +public: + static vtkUnstructuredGridBunykRayCastFunction *New(); + vtkTypeRevisionMacro(vtkUnstructuredGridBunykRayCastFunction,vtkUnstructuredGridVolumeRayCastFunction); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +//BTX + // Description: + // Called by the ray cast mapper at the start of rendering + virtual void Initialize( vtkRenderer *ren, vtkVolume *vol ); + + // Description: + // Called by the ray cast mapper at the end of rendering + virtual void Finalize(); + + virtual vtkUnstructuredGridVolumeRayCastIterator *NewIterator(); + + // Used to store each triangle - made public because of the + // templated function + class Triangle { + public: + vtkIdType PointIndex[3]; + vtkIdType ReferredByTetra[2]; + double P1X, P1Y; + double P2X, P2Y; + double Denominator; + double A, B, C, D; + Triangle *Next; + }; + + // Used to store each intersection for the pixel rays - made + // public because of the templated function + class Intersection { + public: + Triangle *TriPtr; + double Z; + Intersection *Next; + }; + + // Description: + // Is the point x, y, in the given triangle? Public for + // access from the templated function. + int InTriangle( double x, double y, + Triangle *triPtr ); + + + // Description: + // Access to an internal structure for the templated method. + double *GetPoints() {return this->Points;} + + // Description: + // Access to an internal structure for the templated method. + vtkGetObjectMacro( ViewToWorldMatrix, vtkMatrix4x4 ); + + // Description: + // Access to an internal structure for the templated method. + vtkGetVectorMacro( ImageOrigin, int, 2 ); + + // Description: + // Access to an internal structure for the templated method. + vtkGetVectorMacro( ImageViewportSize, int, 2 ); + + // Description: + // Access to an internal structure for the templated method. + Triangle **GetTetraTriangles () {return this->TetraTriangles;} + + // Description: + // Access to an internal structure for the templated method. + Intersection *GetIntersectionList( int x, int y ) { return this->Image[y*this->ImageSize[0] + x]; } + +//ETX + +protected: + vtkUnstructuredGridBunykRayCastFunction(); + ~vtkUnstructuredGridBunykRayCastFunction(); + + // These are cached during the initialize method so that they do not + // need to be passed into subsequent CastRay calls. + vtkRenderer *Renderer; + vtkVolume *Volume; + vtkUnstructuredGridVolumeRayCastMapper *Mapper; + + // Computed during the initialize method - if something is + // wrong (no mapper, no volume, no input, etc.) then no rendering + // will actually be performed. + int Valid; + + // These are the transformed points + int NumberOfPoints; + double *Points; + + // This is the matrix that will take a transformed point back + // to world coordinates + vtkMatrix4x4 *ViewToWorldMatrix; + + + // This is the intersection list per pixel in the image + Intersection **Image; + + // This is the size of the image we are computing (which does + // not need to match the screen size) + int ImageSize[2]; + + // Since we may only be computing a subregion of the "full" image, + // this is the origin of the region we are computing. We must + // subtract this origin from any pixel (x,y) locations before + // accessing the pixel in this->Image (which represents only the + // subregion) + int ImageOrigin[2]; + + // This is the full size of the image + int ImageViewportSize[2]; + + // These are values saved for the building of the TriangleList. Basically + // we need to check if the data has changed in some way. + vtkUnstructuredGrid *SavedTriangleListInput; + vtkTimeStamp SavedTriangleListMTime; + +//BTX + // This is a memory intensive algorithm! For each tetra in the + // input data we create up to 4 triangles (we don't create duplicates) + // This is the TriangleList. Then, for each tetra we keep track of + // the pointer to each of its four triangles - this is the + // TetraTriangles. We also keep a duplicate list of points + // (transformed into view space) - these are the Points. + Triangle **TetraTriangles; + Triangle *TriangleList; + + // Compute whether a boundary triangle is front facing by + // looking at the fourth point in the tetra to see if it is + // in front (triangle is backfacing) or behind (triangle is + // front facing) the plane containing the triangle. + int IsTriangleFrontFacing( Triangle *triPtr, vtkIdType tetraIndex ); + + // The image contains lists of intersections per pixel - we + // need to clear this during the initialization phase for each + // render. + void ClearImage(); + + // This is the memory buffer used to build the intersection + // lists. We do our own memory management here because allocating + // a bunch of small elements during rendering is too slow. + Intersection *IntersectionBuffer[VTK_BUNYKRCF_MAX_ARRAYS]; + int IntersectionBufferCount[VTK_BUNYKRCF_MAX_ARRAYS]; + + // This method replaces new for creating a new element - it + // returns one from the big block already allocated (it + // allocates another big block if necessary) + void *NewIntersection(); + + // This method is used during the initialization process to + // check the validity of the objects - missing information + // such as the volume, renderer, mapper, etc. will be flagged + // and reported. + int CheckValidity(vtkRenderer *ren, + vtkVolume *vol); + + // This method is used during the initialization process to + // transform the points to view coordinates + void TransformPoints(); + + // This method is used during the initialization process to + // create the list of triangles if the data has changed + void UpdateTriangleList(); + + // This method is used during the initialization process to + // update the view dependent information in the triangle list + void ComputeViewDependentInfo(); + + // This method is used during the initialization process to + // compute the intersections for each pixel with the boundary + // triangles. + void ComputePixelIntersections(); + +//ETX + +private: + vtkUnstructuredGridBunykRayCastFunction(const vtkUnstructuredGridBunykRayCastFunction&); // Not implemented. + void operator=(const vtkUnstructuredGridBunykRayCastFunction&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/VolumeRendering/vtkUnstructuredGridHomogeneousRayIntegrator.cxx b/VolumeRendering/vtkUnstructuredGridHomogeneousRayIntegrator.cxx new file mode 100644 index 0000000..997a8e0 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridHomogeneousRayIntegrator.cxx @@ -0,0 +1,306 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridHomogeneousRayIntegrator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkUnstructuredGridHomogeneousRayIntegrator.h" + +#include "vtkObjectFactory.h" +#include "vtkVolumeProperty.h" +#include "vtkVolume.h" +#include "vtkAbstractVolumeMapper.h" +#include "vtkUnstructuredGrid.h" +#include "vtkDoubleArray.h" +#include "vtkColorTransferFunction.h" +#include "vtkPiecewiseFunction.h" + +#include <math.h> + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkUnstructuredGridHomogeneousRayIntegrator, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkUnstructuredGridHomogeneousRayIntegrator); + +//----------------------------------------------------------------------------- + +vtkUnstructuredGridHomogeneousRayIntegrator::vtkUnstructuredGridHomogeneousRayIntegrator() +{ + this->Property = NULL; + + this->NumComponents = 0; + this->ColorTable = NULL; + this->AttenuationTable = NULL; + this->TableShift = NULL; + this->TableScale = NULL; + + this->UseAverageColor = 0; + this->TransferFunctionTableSize = 1024; +} + +vtkUnstructuredGridHomogeneousRayIntegrator::~vtkUnstructuredGridHomogeneousRayIntegrator() +{ + for (int i = 0; i < this->NumComponents; i++) + { + delete[] this->ColorTable[i]; + delete[] this->AttenuationTable[i]; + } + delete[] this->ColorTable; + delete[] this->AttenuationTable; + delete[] this->TableShift; + delete[] this->TableScale; +} + +void vtkUnstructuredGridHomogeneousRayIntegrator::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "UseAverageColor: " << this->UseAverageColor << endl; + os << indent << "TransferFunctionTableSize: " + << this->TransferFunctionTableSize << endl; +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridHomogeneousRayIntegrator::GetTransferFunctionTables(vtkDataArray *scalars) +{ + for (int i = 0; i < this->NumComponents; i++) + { + delete[] this->ColorTable[i]; + delete[] this->AttenuationTable[i]; + } + delete[] this->ColorTable; + delete[] this->AttenuationTable; + delete[] this->TableShift; + delete[] this->TableScale; + + this->NumComponents = scalars->GetNumberOfComponents(); + + this->ColorTable = new float*[this->NumComponents]; + this->AttenuationTable = new float*[this->NumComponents]; + this->TableShift = new double[this->NumComponents]; + this->TableScale = new double[this->NumComponents]; + + for (int c = 0; c < this->NumComponents; c++) + { + double range[2]; + scalars->GetRange(range, c); + if (range[0] >= range[1]) + { + range[1] = range[0] + 1; + } + this->TableScale[c] = this->TransferFunctionTableSize/(range[1]-range[0]); + this->TableShift[c] + = -range[0]*this->TransferFunctionTableSize/(range[1]-range[0]); + + this->ColorTable[c] = new float[3*this->TransferFunctionTableSize]; + if (this->Property->GetColorChannels(c) == 1) + { + // Get gray values. Store temporarily in allocated RGB array. + this->Property->GetGrayTransferFunction(c) + ->GetTable(range[0], range[1], this->TransferFunctionTableSize, + this->ColorTable[c]); + // Convert gray into RGB. Copy backward so that we can use the same + // array. + for (int i = this->TransferFunctionTableSize-1; i >= 0; i--) + { + this->ColorTable[c][3*i + 0] + = this->ColorTable[c][3*i + 1] + = this->ColorTable[c][3*i + 2] = this->ColorTable[c][i]; + } + } + else + { + this->Property->GetRGBTransferFunction(c) + ->GetTable(range[0], range[1], this->TransferFunctionTableSize, + this->ColorTable[c]); + } + + this->AttenuationTable[c] = new float[this->TransferFunctionTableSize]; + this->Property->GetScalarOpacity(c) + ->GetTable(range[0], range[1], this->TransferFunctionTableSize, + this->AttenuationTable[c]); + + // Adjust attenuation by scalar unit length. This will make the unit + // lenth the same as the model. + float unitlength = this->Property->GetScalarOpacityUnitDistance(c); + for (int i = 0; i < this->TransferFunctionTableSize; i++) + { + this->AttenuationTable[c][i] /= unitlength; + } + } + + this->TablesBuilt.Modified(); +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridHomogeneousRayIntegrator::Initialize(vtkVolume *volume, + vtkDataArray *scalars) +{ + vtkVolumeProperty *property = volume->GetProperty(); + + if ( (property == this->Property) + && (this->TablesBuilt > property->GetMTime()) + && (this->TablesBuilt > this->MTime) ) + { + // Nothing changed from the last time Initialize was run. + return; + } + + this->Property = property; + this->Volume = volume; + + if (property->GetIndependentComponents()) + { + this->GetTransferFunctionTables(scalars); + } +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridHomogeneousRayIntegrator::Integrate( + vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *vtkNotUsed(farIntersections), + float color[4]) +{ + vtkIdType numIntersections = intersectionLengths->GetNumberOfTuples(); + + if (this->Property->GetIndependentComponents()) + { + if (this->NumComponents == 1) + { + // Optimize for what I think is one of the most common uses. + for (vtkIdType i = 0; i < numIntersections; i++) + { + int table_index + = (int)( this->TableScale[0]*nearIntersections->GetComponent(i, 0) + + this->TableShift[0] ); + if (table_index < 0) + { + table_index = 0; + } + if (table_index >= this->TransferFunctionTableSize) + { + table_index = this->TransferFunctionTableSize-1; + } + float *c = this->ColorTable[0] + 3*table_index; + float tau = this->AttenuationTable[0][table_index]; + float alpha = 1-(float)exp(-intersectionLengths->GetComponent(i,0)*tau); + color[0] += c[0]*alpha*(1-color[3]); + color[1] += c[1]*alpha*(1-color[3]); + color[2] += c[2]*alpha*(1-color[3]); + color[3] += alpha*(1-color[3]); + } + } + else + { + // Generic case. + for (vtkIdType i = 0; i < numIntersections; i++) + { + float newcolor[4]; + int table_index + = (int)( this->TableScale[0]*nearIntersections->GetComponent(i, 0) + + this->TableShift[0] ); + if (table_index < 0) + { + table_index = 0; + } + if (table_index >= this->TransferFunctionTableSize) + { + table_index = this->TransferFunctionTableSize-1; + } + float *c = this->ColorTable[0] + 3*table_index; + float tau = this->AttenuationTable[0][table_index]; + newcolor[0] = c[0]; newcolor[1] = c[1]; + newcolor[2] = c[2]; newcolor[3] = tau; + for (int component = 1; component < this->NumComponents; component++) + { + table_index + = (int)( this->TableScale[component] + *nearIntersections->GetComponent(i, component) + + this->TableShift[component] ); + if (table_index < 0) + { + table_index = 0; + } + if (table_index >= this->TransferFunctionTableSize) + { + table_index = this->TransferFunctionTableSize-1; + } + c = this->ColorTable[component] + 3*table_index; + tau = this->AttenuationTable[component][table_index]; + // Here we handle the mixing of material properties. This never + // seems to be defined very clearly. I handle this by assuming + // that each scalar represents a cloud of particles of a certian + // color and a certain density. We mix the scalars in the same + // way as mixing these particles together. By necessity, the + // density becomes greater. The "opacity" parameter is really + // interpreted as the attenuation coefficient (which is + // proportional to density) and can therefore easily be greater + // than one. The opacity of the resulting color will, however, + // always be scaled between 0 and 1. + if (tau + newcolor[3] > 1.0e-8f) + { + newcolor[0] *= newcolor[3]/(tau + newcolor[3]); + newcolor[1] *= newcolor[3]/(tau + newcolor[3]); + newcolor[2] *= newcolor[3]/(tau + newcolor[3]); + newcolor[0] += c[0]*tau/(tau + newcolor[3]); + newcolor[1] += c[1]*tau/(tau + newcolor[3]); + newcolor[2] += c[2]*tau/(tau + newcolor[3]); + newcolor[3] += tau; + } + } + float alpha = 1 - (float)exp(-intersectionLengths->GetComponent(i,0) + *newcolor[3]); + color[0] += newcolor[0]*alpha*(1-color[3]); + color[1] += newcolor[1]*alpha*(1-color[3]); + color[2] += newcolor[2]*alpha*(1-color[3]); + color[3] += alpha*(1-color[3]); + } + } + } + else + { + int numComponents = nearIntersections->GetNumberOfComponents(); + for (vtkIdType i = 0; i < numIntersections; i++) + { + double c[4]; + if (numComponents == 4) + { + nearIntersections->GetTuple(i, c); + } + else + { + double *lt = nearIntersections->GetTuple(i); + c[0] = c[1] = c[2] = lt[0]; + c[3] = lt[1]; + } + float alpha = 1-(float)exp(-intersectionLengths->GetComponent(i,0)*c[3]); + color[0] += (float)c[0]*alpha*(1-color[3]); + color[1] += (float)c[1]*alpha*(1-color[3]); + color[2] += (float)c[2]*alpha*(1-color[3]); + color[3] += alpha*(1-color[3]); + } + } +} + diff --git a/VolumeRendering/vtkUnstructuredGridHomogeneousRayIntegrator.h b/VolumeRendering/vtkUnstructuredGridHomogeneousRayIntegrator.h new file mode 100644 index 0000000..d1174fe --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridHomogeneousRayIntegrator.h @@ -0,0 +1,87 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridHomogeneousRayIntegrator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkUnstructuredGridHomogeneousRayIntegrator - performs peicewise constant ray integration. +// +// .SECTION Description +// +// vtkUnstructuredGridHomogeneousRayIntegrator performs homogeneous ray +// integration. This is a good method to use when volume rendering scalars +// that are defined on cells. +// + +#ifndef __vtkUnstructuredGridHomogeneousRayIntegrator_h +#define __vtkUnstructuredGridHomogeneousRayIntegrator_h + +#include "vtkUnstructuredGridVolumeRayIntegrator.h" + +class vtkVolumeProperty; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridHomogeneousRayIntegrator : public vtkUnstructuredGridVolumeRayIntegrator +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridHomogeneousRayIntegrator, + vtkUnstructuredGridVolumeRayIntegrator); + static vtkUnstructuredGridHomogeneousRayIntegrator *New(); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + virtual void Initialize(vtkVolume *volume, vtkDataArray *scalars); + + virtual void Integrate(vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]); + + // Description: + // For quick lookup, the transfer function is sampled into a table. + // This parameter sets how big of a table to use. By default, 1024 + // entries are used. + vtkSetMacro(TransferFunctionTableSize, int); + vtkGetMacro(TransferFunctionTableSize, int); + +protected: + vtkUnstructuredGridHomogeneousRayIntegrator(); + ~vtkUnstructuredGridHomogeneousRayIntegrator(); + + vtkVolume *Volume; + vtkVolumeProperty *Property; + + int NumComponents; + float **ColorTable; + float **AttenuationTable; + double *TableShift; + double *TableScale; + vtkTimeStamp TablesBuilt; + + int UseAverageColor; + int TransferFunctionTableSize; + + virtual void GetTransferFunctionTables(vtkDataArray *scalars); + +private: + vtkUnstructuredGridHomogeneousRayIntegrator(const vtkUnstructuredGridHomogeneousRayIntegrator&); // Not implemented. + void operator=(const vtkUnstructuredGridHomogeneousRayIntegrator&); // Not implemented +}; + +#endif //__vtkUnstructuredGridHomogeneousRayIntegrator_h diff --git a/VolumeRendering/vtkUnstructuredGridLinearRayIntegrator.cxx b/VolumeRendering/vtkUnstructuredGridLinearRayIntegrator.cxx new file mode 100644 index 0000000..aaff781 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridLinearRayIntegrator.cxx @@ -0,0 +1,707 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridLinearRayIntegrator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkUnstructuredGridLinearRayIntegrator.h" + +#include "vtkObjectFactory.h" +#include "vtkVolumeProperty.h" +#include "vtkVolume.h" +#include "vtkDoubleArray.h" +#include "vtkPiecewiseFunction.h" +#include "vtkColorTransferFunction.h" +#include "vtkMath.h" + +#include <vtkstd/vector> +#include <vtkstd/set> +#include <vtkstd/algorithm> + +#include <math.h> + +#ifndef M_SQRTPI +#define M_SQRTPI 1.77245385090551602792981 +#endif +#ifndef M_2_SQRTPI +#define M_2_SQRTPI 1.12837916709551257390 +#endif +#ifndef M_1_SQRTPI +#define M_1_SQRTPI (0.5*M_2_SQRTPI) +#endif + +//----------------------------------------------------------------------------- + +// VTK's native classes for defining transfer functions is actually slow to +// access, so we have to cache it somehow. This class is straightforward +// copy of the transfer function. +class vtkLinearRayIntegratorTransferFunction +{ +public: + vtkLinearRayIntegratorTransferFunction(); + ~vtkLinearRayIntegratorTransferFunction(); + + void GetTransferFunction(vtkColorTransferFunction *color, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]); + void GetTransferFunction(vtkPiecewiseFunction *intensity, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]); + + inline void GetColor(double x, double c[4]); + + struct acolor { + double c[4]; + }; + double *ControlPoints; + int NumControlPoints; + acolor *Colors; + +private: + vtkLinearRayIntegratorTransferFunction(const vtkLinearRayIntegratorTransferFunction&); // Not implemented. + void operator=(const vtkLinearRayIntegratorTransferFunction &); // Not implemented. +}; + +vtkLinearRayIntegratorTransferFunction::vtkLinearRayIntegratorTransferFunction() +{ + this->ControlPoints = NULL; + this->Colors = NULL; + + this->NumControlPoints = 0; +} + +vtkLinearRayIntegratorTransferFunction::~vtkLinearRayIntegratorTransferFunction() +{ + if (this->ControlPoints) delete[] this->ControlPoints; + if (this->Colors) delete[] this->Colors; +} + +static const double huebends[6] = { + 1.0/6.0, 1.0/3.0, 0.5, 2.0/3.0, 5.0/6.0, 1.0 +}; + +void vtkLinearRayIntegratorTransferFunction::GetTransferFunction( + vtkColorTransferFunction *color, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]) +{ + vtkstd::set<double> cpset; + + double *function_range = color->GetRange(); + double *function = color->GetDataPointer(); + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[1]) break; + function += 4; + } + + if (color->GetColorSpace() != VTK_CTF_RGB) + { + // If we are in an HSV color space, we must insert control points + // in places where the RGB bends. + double rgb[3], hsv[3]; + double hue1, hue2; + double x1, x2; + vtkstd::set<double>::iterator i = cpset.begin(); + x1 = *i; + color->GetColor(x1, rgb); + vtkMath::RGBToHSV(rgb, hsv); + hue1 = hsv[0]; + for (i++; i != cpset.end(); i++) + { + x2 = *i; + color->GetColor(x2, rgb); + vtkMath::RGBToHSV(rgb, hsv); + hue2 = hsv[0]; + + // Are we crossing the 0/1 boundary? + if ( (color->GetColorSpace() == VTK_CTF_HSV && color->GetHSVWrap() ) + && ((hue1 - hue2 > 0.5) || (hue2 - hue1 > 0.5)) ) + { + // Yes, we are crossing the boundary. + if (hue1 > hue2) + { + int j; + for (j = 0; huebends[j] <= hue2; j++) + { + double interp = (1-hue1+huebends[j])/(1-hue1+hue2); + cpset.insert((x2-x1)*interp + x1); + } + while (huebends[j] < hue1) j++; + for ( ; j < 6; j++) + { + double interp = (huebends[j]-hue1)/(1-hue1+hue2); + cpset.insert((x2-x1)*interp + x1); + } + } + else + { + int j; + for (j = 0; huebends[j] <= hue1; j++) + { + double interp = (hue1-huebends[j])/(1-hue2+hue1); + cpset.insert((x2-x1)*interp + x1); + } + while (huebends[j] < hue2) j++; + for ( ; j < 6; j++) + { + double interp = (1-huebends[j]+hue1)/(1-hue2+hue1); + cpset.insert((x2-x1)*interp + x1); + } + } + } + else + { + // No, we are not crossing the boundary. + int j = 0; + double minh, maxh; + if (hue1 < hue2) + { + minh = hue1; maxh = hue2; + } + else + { + minh = hue2; maxh = hue1; + } + while (huebends[j] < minh) j++; + for (j = 0; huebends[j] < maxh; j++) + { + double interp = (huebends[j]-hue1)/(hue2-hue1); + cpset.insert((x2-x1)*interp + x1); + } + } + + x1 = x2; + hue1 = hue2; + } + } + + function_range = opacity->GetRange(); + function = opacity->GetDataPointer(); + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[0]) break; + function += 2; + } + + // Add the scalar at the beginning and end of the range so the interpolation + // is correct there. + cpset.insert(scalar_range[0]); + cpset.insert(scalar_range[1]); + // Make extra sure there are at least two entries in cpset. + if (cpset.size() < 2) + { + cpset.insert(0.0); + cpset.insert(1.0); + } + + // Now record control points and colors. + if (this->ControlPoints) delete[] this->ControlPoints; + if (this->Colors) delete[] this->Colors; + this->NumControlPoints = cpset.size(); + this->ControlPoints = new double[this->NumControlPoints]; + this->Colors = new acolor[this->NumControlPoints]; + + vtkstd::copy(cpset.begin(), cpset.end(), this->ControlPoints); + for (int i = 0; i < this->NumControlPoints; i++) + { + color->GetColor(this->ControlPoints[i], this->Colors[i].c); + this->Colors[i].c[3] = ( opacity->GetValue(this->ControlPoints[i]) + / unit_distance); + } +} + +void vtkLinearRayIntegratorTransferFunction::GetTransferFunction( + vtkPiecewiseFunction *intensity, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]) +{ + vtkstd::set<double> cpset; + + double *function_range = intensity->GetRange(); + double *function = intensity->GetDataPointer(); + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[1]) break; + function += 2; + } + + function_range = opacity->GetRange(); + function = opacity->GetDataPointer(); + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[0]) break; + function += 2; + } + + // Add the scalar at the beginning and end of the range so the interpolation + // is correct there. + cpset.insert(scalar_range[0]); + cpset.insert(scalar_range[1]); + // Make extra sure there are at least two entries in cpset. + if (cpset.size() < 2) + { + cpset.insert(0.0); + cpset.insert(1.0); + } + + // Now record control points and colors. + if (this->ControlPoints) delete[] this->ControlPoints; + if (this->Colors) delete[] this->Colors; + this->NumControlPoints = cpset.size(); + this->ControlPoints = new double[this->NumControlPoints]; + this->Colors = new acolor[this->NumControlPoints]; + + vtkstd::copy(cpset.begin(), cpset.end(), this->ControlPoints); + for (int i = 0; i < this->NumControlPoints; i++) + { + // Is setting all the colors to the same value the right thing to do? + this->Colors[i].c[0] = this->Colors[i].c[1] = this->Colors[i].c[2] + = intensity->GetValue(this->ControlPoints[i]); + this->Colors[i].c[3] = ( opacity->GetValue(this->ControlPoints[i]) + / unit_distance); + } +} + +inline void vtkLinearRayIntegratorTransferFunction::GetColor(double x, + double c[4]) +{ + int i = 1; + while ((this->ControlPoints[i] < x) && (i < this->NumControlPoints-1)) i++; + + double before = this->ControlPoints[i-1]; + double after = this->ControlPoints[i]; + + double interp = (x-before)/(after-before); + + double *beforec = this->Colors[i-1].c; + double *afterc = this->Colors[i].c; + c[0] = (1-interp)*beforec[0] + interp*afterc[0]; + c[1] = (1-interp)*beforec[1] + interp*afterc[1]; + c[2] = (1-interp)*beforec[2] + interp*afterc[2]; + c[3] = (1-interp)*beforec[3] + interp*afterc[3]; +} + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkUnstructuredGridLinearRayIntegrator, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkUnstructuredGridLinearRayIntegrator); + +vtkUnstructuredGridLinearRayIntegrator::vtkUnstructuredGridLinearRayIntegrator() +{ + this->Property = NULL; + this->TransferFunctions = NULL; + this->NumIndependentComponents = 0; +} + +//----------------------------------------------------------------------------- + +vtkUnstructuredGridLinearRayIntegrator::~vtkUnstructuredGridLinearRayIntegrator() +{ + delete[] this->TransferFunctions; +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridLinearRayIntegrator::PrintSelf(ostream &os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridLinearRayIntegrator::Initialize( + vtkVolume *volume, + vtkDataArray *scalars) +{ + vtkVolumeProperty *property = volume->GetProperty(); + + if ( (property == this->Property) + && (this->TransferFunctionsModified > property->GetMTime()) ) + { + // Nothing has changed from the last time Initialize was run. + return; + } + + int numcomponents = scalars->GetNumberOfComponents(); + + this->Property = property; + this->TransferFunctionsModified.Modified(); + + if (!property->GetIndependentComponents()) + { + // The scalars actually hold material properties. + if ((numcomponents != 4) && (numcomponents != 2) ) + { + vtkErrorMacro("Only 2-tuples and 4-tuples allowed for dependent components."); + } + return; + } + + delete[] this->TransferFunctions; + + this->NumIndependentComponents = numcomponents; + this->TransferFunctions + = new vtkLinearRayIntegratorTransferFunction[numcomponents]; + + for (int component = 0; component < numcomponents; component++) + { + if (property->GetColorChannels(component) == 1) + { + this->TransferFunctions[component] + .GetTransferFunction(property->GetGrayTransferFunction(component), + property->GetScalarOpacity(component), + property->GetScalarOpacityUnitDistance(component), + scalars->GetRange(component)); + } + else + { + this->TransferFunctions[component] + .GetTransferFunction(property->GetRGBTransferFunction(component), + property->GetScalarOpacity(component), + property->GetScalarOpacityUnitDistance(component), + scalars->GetRange(component)); + } + } +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridLinearRayIntegrator::Integrate( + vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]) +{ + int numintersections = intersectionLengths->GetNumberOfTuples(); + if (this->Property->GetIndependentComponents()) + { + int numscalars = nearIntersections->GetNumberOfComponents(); + double *nearScalars = new double[numscalars]; + double *farScalars = new double[numscalars]; + vtkstd::set<double> segments; + for (vtkIdType i = 0; i < numintersections; i++) + { + double total_length = intersectionLengths->GetValue(i); + nearIntersections->GetTuple(i, nearScalars); + farIntersections->GetTuple(i, farScalars); + + // Split up segment on control points, because it is nonlinear in + // these regions. + segments.erase(segments.begin(), segments.end()); + segments.insert(0.0); + segments.insert(1.0); + for (int j = 0; j < numscalars; j++) + { + double *cp = this->TransferFunctions[j].ControlPoints; + vtkIdType numcp = this->TransferFunctions[j].NumControlPoints; + double minscalar, maxscalar; + if (nearScalars[j] < farScalars[j]) + { + minscalar = nearScalars[j]; maxscalar = farScalars[j]; + } + else + { + minscalar = farScalars[j]; maxscalar = nearScalars[j]; + } + for (int k = 0; k < numcp; k++) + { + if (cp[k] <= minscalar) continue; + if (cp[k] >= maxscalar) break; + // If we are here, we need to break the segment at the given scalar. + // Find the fraction between the near and far segment points. + segments.insert( (cp[k]-nearScalars[j]) + / (farScalars[j]-nearScalars[j])); + } + } + + // Iterate over all the segment pieces (from front to back) and + // integrate each piece. + vtkstd::set<double>::iterator segi = segments.begin(); + double nearInterpolant = *segi; + for (segi++; segi != segments.end(); segi++) + { + double farInterpolant = *segi; + double nearcolor[4] = {0.0, 0.0, 0.0, 0.0}; + double farcolor[4] = {0.0, 0.0, 0.0, 0.0}; + double length = total_length*(farInterpolant-nearInterpolant); + // Here we handle the mixing of material properties. This never + // seems to be defined very clearly. I handle this by assuming + // that each scalar represents a cloud of particles of a certian + // color and a certain density. We mix the scalars in the same way + // as mixing these particles together. By necessity, the density + // becomes greater. The "opacity" parameter is really interpreted + // as the attenuation coefficient (which is proportional to + // density) and can therefore easily be greater than one. The + // opacity of the resulting color will, however, always be scaled + // between 0 and 1. + for (int j = 0; j < numscalars; j++) + { + double scalar + = (farScalars[j]-nearScalars[j])*nearInterpolant + nearScalars[j]; + if (j == 0) + { + this->TransferFunctions[j].GetColor(scalar, nearcolor); + } + else + { + double c[4]; + this->TransferFunctions[j].GetColor(scalar, c); + if (c[3] + nearcolor[3] > 1.0e-8f) + { + nearcolor[0] *= nearcolor[3]/(c[3] + nearcolor[3]); + nearcolor[1] *= nearcolor[3]/(c[3] + nearcolor[3]); + nearcolor[2] *= nearcolor[3]/(c[3] + nearcolor[3]); + nearcolor[0] += c[0]*c[3]/(c[3] + nearcolor[3]); + nearcolor[1] += c[1]*c[3]/(c[3] + nearcolor[3]); + nearcolor[2] += c[2]*c[3]/(c[3] + nearcolor[3]); + nearcolor[3] += c[3]; + } + } + + scalar + = (farScalars[j]-nearScalars[j])*farInterpolant + nearScalars[j]; + if (j == 0) + { + this->TransferFunctions[j].GetColor(scalar, farcolor); + } + else + { + double c[4]; + this->TransferFunctions[j].GetColor(scalar, c); + if (c[3] + farcolor[3] > 1.0e-8f) + { + farcolor[0] *= farcolor[3]/(c[3] + farcolor[3]); + farcolor[1] *= farcolor[3]/(c[3] + farcolor[3]); + farcolor[2] *= farcolor[3]/(c[3] + farcolor[3]); + farcolor[0] += c[0]*c[3]/(c[3] + farcolor[3]); + farcolor[1] += c[1]*c[3]/(c[3] + farcolor[3]); + farcolor[2] += c[2]*c[3]/(c[3] + farcolor[3]); + farcolor[3] += c[3]; + } + } + } + this->IntegrateRay(length, nearcolor, nearcolor[3], + farcolor, farcolor[3], color); + + nearInterpolant = farInterpolant; + } + } + delete[] nearScalars; + delete[] farScalars; + } + else + { + double unitdistance = this->Property->GetScalarOpacityUnitDistance(); + if (nearIntersections->GetNumberOfComponents() == 4) + { + for (vtkIdType i = 0; i < numintersections; i++) + { + double length = intersectionLengths->GetValue(i); + double *nearcolor = nearIntersections->GetTuple(i); + double *farcolor = farIntersections->GetTuple(i); + this->IntegrateRay(length, nearcolor, nearcolor[3]/unitdistance, + farcolor, farcolor[3]/unitdistance, color); + } + } + else // Two components. + { + for (vtkIdType i = 0; i < numintersections; i++) + { + double length = intersectionLengths->GetValue(i); + double *nearcolor = nearIntersections->GetTuple(i); + double *farcolor = farIntersections->GetTuple(i); + this->IntegrateRay(length, nearcolor[0], nearcolor[1]/unitdistance, + farcolor[0], farcolor[1]/unitdistance, color); + } + } + } +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridLinearRayIntegrator::IntegrateRay( + double length, + double intensity_front, + double attenuation_front, + double intensity_back, + double attenuation_back, + float color[4]) +{ + float Psi = vtkUnstructuredGridLinearRayIntegrator::Psi(length, + attenuation_front, + attenuation_back); + float zeta = (float)exp(-0.5*length*(attenuation_front+attenuation_back)); + float alpha = 1-zeta; + + float newintensity = (1-color[3])*( intensity_front*(1-Psi) + + intensity_back*(Psi-zeta) ); + // Is setting the RGB values the same the right thing to do? + color[0] += newintensity; + color[1] += newintensity; + color[2] += newintensity; + color[3] += (1-color[3])*alpha; +} + +void vtkUnstructuredGridLinearRayIntegrator::IntegrateRay( + double length, + const double color_front[3], + double attenuation_front, + const double color_back[3], + double attenuation_back, + float color[4]) +{ + float Psi = vtkUnstructuredGridLinearRayIntegrator::Psi(length, + attenuation_front, + attenuation_back); + float zeta = (float)exp(-0.5*length*(attenuation_front+attenuation_back)); + float alpha = 1-zeta; + + color[0] += (1-color[3])*(color_front[0]*(1-Psi) + color_back[0]*(Psi-zeta)); + color[1] += (1-color[3])*(color_front[1]*(1-Psi) + color_back[1]*(Psi-zeta)); + color[2] += (1-color[3])*(color_front[2]*(1-Psi) + color_back[2]*(Psi-zeta)); + color[3] += (1-color[3])*alpha; +} + +//----------------------------------------------------------------------------- + +static inline float erf_fitting_function(float u) +{ + return + - 1.26551223 + u*(1.00002368 + u*(0.37409196 + u*(0.09678418 + + u*(-0.18628806 + u*(0.27886807 + u*(-1.13520398 + u*(1.48851587 + + u*(-0.82215223 + u*0.17087277)))))))); +} + +#if 0 +// This function is not used directly. It is here for reference. +static inline float erf(float x) +{ + /* Compute as described in Numerical Recipes in C++ by Press, et al. */ +/* x = abs(x); In this application, x should always be >= 0. */ + float u = 1/(1 + 0.5*x); + float ans = u*exp(-x*x + erf_fitting_function(u)); +/* return (x >= 0 ? 1 - ans : ans - 1); x should always be >= 0. */ + return 1 - ans; +} +#endif + +/* Compute Dawson's integral as described in Numerical Recipes in C++ by + Press, et al. */ +#define H 0.4 +#define NMAX 6 +static const float dawson_constant0 = 0.852144; +static const float dawson_constant1 = 0.236928; +static const float dawson_constant2 = 0.0183156; +static const float dawson_constant3 = 0.000393669; +static const float dawson_constant4 = 2.35258e-6; +static const float dawson_constant5 = 3.90894e-9; +static inline float dawson(float x) +{ + if (x > 0.2) + { +/* x = abs(x); In this application, x should always be >= 0. */ + int n0 = 2*(int)((0.5/H)*x + 0.5); + float xp = x - (float)n0*H; + float e1 = exp((2*H)*xp); + float e2 = e1*e1; + float d1 = n0 + 1; + float d2 = d1 - 2; + float sum = 0; + sum = dawson_constant0*(e1/d1 + 1/(d2*e1)); + d1 += 2; d2 -= 2; e1 *= e2; + sum += dawson_constant1*(e1/d1 + 1/(d2*e1)); + d1 += 2; d2 -= 2; e1 *= e2; + sum += dawson_constant2*(e1/d1 + 1/(d2*e1)); + d1 += 2; d2 -= 2; e1 *= e2; + sum += dawson_constant3*(e1/d1 + 1/(d2*e1)); + d1 += 2; d2 -= 2; e1 *= e2; + sum += dawson_constant4*(e1/d1 + 1/(d2*e1)); + d1 += 2; d2 -= 2; e1 *= e2; + sum += dawson_constant5*(e1/d1 + 1/(d2*e1)); + return M_1_SQRTPI*exp(-xp*xp)*sum; + } + else + { + float x2 = x*x; + return x*(1 - (2.0/3.0)*x2*(1 - .4*x2*(1 - (2.0/7.0)*x2))); + } +} + +#if 0 +// This function is not used directly. It is here for reference. +inline float erfi(float x) +{ + return M_2_SQRTPI*exp(x*x)*dawson(x); +} +#endif + +float vtkUnstructuredGridLinearRayIntegrator::Psi(float length, + float attenuation_front, + float attenuation_back) +{ + float difftauD = length*fabs(attenuation_back - attenuation_front); + + if (difftauD < 1.0e-8f) + { + // Volume is homogeneous (with respect to attenuation). + float tauD = length * attenuation_front; + if (tauD < 1.0e-8f) + { + return 1; + } + else + { + return (1 - (float)exp(-tauD))/tauD; + } + } + else + { + float invsqrt2difftauD = 1/(float)sqrt(2*difftauD); + float frontterm = length*invsqrt2difftauD*attenuation_front; + float backterm = length*invsqrt2difftauD*attenuation_back; + if (attenuation_back > attenuation_front) + { + float u, Y; + u = 1/(1+0.5f*frontterm); + Y = u*(float)exp(erf_fitting_function(u)); + u = 1/(1+0.5f*backterm); + Y += -u*exp( frontterm*frontterm-backterm*backterm + + erf_fitting_function(u)); + Y *= M_SQRTPI*invsqrt2difftauD; + return Y; + } + else + { + float expterm = (float)exp(backterm*backterm-frontterm*frontterm); + return 2*invsqrt2difftauD*(dawson(frontterm) - expterm*dawson(backterm)); + } + } +} diff --git a/VolumeRendering/vtkUnstructuredGridLinearRayIntegrator.h b/VolumeRendering/vtkUnstructuredGridLinearRayIntegrator.h new file mode 100644 index 0000000..fae620c --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridLinearRayIntegrator.h @@ -0,0 +1,98 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridLinearRayIntegrator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkUnstructuredGridLinearRayIntegrator - performs piecewise linear ray integration. +// +// .SECTION Description +// +// vtkUnstructuredGridLinearRayIntegrator performs piecewise linear ray +// integration. Considering that transfer functions in VTK are piecewise +// linear, this class should give the "correct" integration under most +// circumstances. However, the computations performed are fairly hefty and +// should, for the most part, only be used as a benchmark for other, faster +// methods. +// +// .SECTION See Also +// vtkUnstructuredGridPartialPreIntegration +// + +#ifndef __vtkUnstructuredGridLinearRayIntegrator_h +#define __vtkUnstructuredGridLinearRayIntegrator_h + +#include "vtkUnstructuredGridVolumeRayIntegrator.h" + +class vtkLinearRayIntegratorTransferFunction; +class vtkVolumeProperty; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridLinearRayIntegrator : public vtkUnstructuredGridVolumeRayIntegrator +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridLinearRayIntegrator, + vtkUnstructuredGridVolumeRayIntegrator); + static vtkUnstructuredGridLinearRayIntegrator *New(); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + virtual void Initialize(vtkVolume *volume, vtkDataArray *scalars); + + virtual void Integrate(vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]); + + // Description: + // Integrates a single ray segment. \c color is blended with the result + // (with \c color in front). The result is written back into \c color. + static void IntegrateRay(double length, + double intensity_front, double attenuation_front, + double intensity_back, double attenuation_back, + float color[4]); + static void IntegrateRay(double length, + const double color_front[3], + double attenuation_front, + const double color_back[3], + double attenuation_back, + float color[4]); + + // Description: + // Computes Psi (as defined by Moreland and Angel, "A Fast High Accuracy + // Volume Renderer for Unstructured Data"). + static float Psi(float length, + float attenuation_front, float attenuation_back); + +protected: + vtkUnstructuredGridLinearRayIntegrator(); + ~vtkUnstructuredGridLinearRayIntegrator(); + + vtkVolumeProperty *Property; + + vtkLinearRayIntegratorTransferFunction *TransferFunctions; + vtkTimeStamp TransferFunctionsModified; + int NumIndependentComponents; + +private: + vtkUnstructuredGridLinearRayIntegrator(const vtkUnstructuredGridLinearRayIntegrator&); // Not implemented. + void operator=(const vtkUnstructuredGridLinearRayIntegrator&); // Not implemented. +}; + +#endif //__vtkUnstructuredGridLinearRayIntegrator_h diff --git a/VolumeRendering/vtkUnstructuredGridPartialPreIntegration.cxx b/VolumeRendering/vtkUnstructuredGridPartialPreIntegration.cxx new file mode 100644 index 0000000..9851061 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridPartialPreIntegration.cxx @@ -0,0 +1,562 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridPartialPreIntegration.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkUnstructuredGridPartialPreIntegration.h" + +#include "vtkObjectFactory.h" +#include "vtkVolumeProperty.h" +#include "vtkVolume.h" +#include "vtkDoubleArray.h" +#include "vtkPiecewiseFunction.h" +#include "vtkColorTransferFunction.h" +#include "vtkUnstructuredGridLinearRayIntegrator.h" +#include "vtkMath.h" + +#include <vtkstd/vector> +#include <vtkstd/set> +#include <vtkstd/algorithm> + +//----------------------------------------------------------------------------- + +// VTK's native classes for defining transfer functions is actually slow to +// access, so we have to cache it somehow. This class is straightforward +// copy of the transfer function. +class vtkPartialPreIntegrationTransferFunction +{ +public: + void GetTransferFunction(vtkColorTransferFunction *color, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]); + void GetTransferFunction(vtkPiecewiseFunction *intensity, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]); + + inline void GetColor(double x, double c[4]); + + struct acolor { + double c[4]; + }; + vtkstd::vector<double> ControlPoints; + vtkstd::vector<acolor> Colors; +}; + +static const double huebends[6] = { + 1.0/6.0, 1.0/3.0, 0.5, 2.0/3.0, 5.0/6.0, 1.0 +}; + +void vtkPartialPreIntegrationTransferFunction::GetTransferFunction( + vtkColorTransferFunction *color, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]) +{ + vtkstd::set<double> cpset; + + double *function_range = color->GetRange(); + double *function = color->GetDataPointer(); + if( !function ) + { + return; + } + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[1]) break; + function += 4; + } + + if (color->GetColorSpace() != VTK_CTF_RGB) + { + // If we are in an HSV color space, we must insert control points + // in places where the RGB bends. + double rgb[3], hsv[3]; + double hue1, hue2; + double x1, x2; + vtkstd::set<double>::iterator i = cpset.begin(); + x1 = *i; + color->GetColor(x1, rgb); + vtkMath::RGBToHSV(rgb, hsv); + hue1 = hsv[0]; + for (i++; i != cpset.end(); i++) + { + x2 = *i; + color->GetColor(x2, rgb); + vtkMath::RGBToHSV(rgb, hsv); + hue2 = hsv[0]; + + // Are we crossing the 0/1 boundary? + if ( (color->GetColorSpace() == VTK_CTF_HSV && color->GetHSVWrap() ) + && ((hue1 - hue2 > 0.5) || (hue2 - hue1 > 0.5)) ) + { + // Yes, we are crossing the boundary. + if (hue1 > hue2) + { + int j; + for (j = 0; huebends[j] <= hue2; j++) + { + double interp = (1-hue1+huebends[j])/(1-hue1+hue2); + cpset.insert((x2-x1)*interp + x1); + } + while (huebends[j] < hue1) j++; + for ( ; j < 6; j++) + { + double interp = (huebends[j]-hue1)/(1-hue1+hue2); + cpset.insert((x2-x1)*interp + x1); + } + } + else + { + int j; + for (j = 0; huebends[j] <= hue1; j++) + { + double interp = (hue1-huebends[j])/(1-hue2+hue1); + cpset.insert((x2-x1)*interp + x1); + } + while (huebends[j] < hue2) j++; + for ( ; j < 6; j++) + { + double interp = (1-huebends[j]+hue1)/(1-hue2+hue1); + cpset.insert((x2-x1)*interp + x1); + } + } + } + else + { + // No, we are not crossing the boundary. + int j = 0; + double minh, maxh; + if (hue1 < hue2) + { + minh = hue1; maxh = hue2; + } + else + { + minh = hue2; maxh = hue1; + } + while (huebends[j] < minh) j++; + for ( ; huebends[j] < maxh; j++) + { + double interp = (huebends[j]-hue1)/(hue2-hue1); + cpset.insert((x2-x1)*interp + x1); + } + } + + x1 = x2; + hue1 = hue2; + } + } + + function_range = opacity->GetRange(); + function = opacity->GetDataPointer(); + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[0]) break; + function += 2; + } + + // Add the scalar at the beginning and end of the range so the interpolation + // is correct there. + cpset.insert(scalar_range[0]); + cpset.insert(scalar_range[1]); + // Make extra sure there are at least two entries in cpset. + if (cpset.size() < 2) + { + cpset.insert(0.0); + cpset.insert(1.0); + } + + // Now record control points and colors. + this->ControlPoints.erase(this->ControlPoints.begin(), + this->ControlPoints.end()); + this->ControlPoints.resize(cpset.size()); + this->Colors.erase(this->Colors.begin(), this->Colors.end()); + this->Colors.resize(cpset.size()); + + vtkstd::copy(cpset.begin(), cpset.end(), this->ControlPoints.begin()); + for (unsigned int i = 0; i < this->ControlPoints.size(); i++) + { + color->GetColor(this->ControlPoints[i], this->Colors[i].c); + this->Colors[i].c[3] = ( opacity->GetValue(this->ControlPoints[i]) + / unit_distance); + } +} + +void vtkPartialPreIntegrationTransferFunction::GetTransferFunction( + vtkPiecewiseFunction *intensity, + vtkPiecewiseFunction *opacity, + double unit_distance, + double scalar_range[2]) +{ + vtkstd::set<double> cpset; + + double *function_range = intensity->GetRange(); + double *function = intensity->GetDataPointer(); + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[1]) break; + function += 2; + } + + function_range = opacity->GetRange(); + function = opacity->GetDataPointer(); + while (1) + { + cpset.insert(function[0]); + if (function[0] == function_range[0]) break; + function += 2; + } + + // Add the scalar at the beginning and end of the range so the interpolation + // is correct there. + cpset.insert(scalar_range[0]); + cpset.insert(scalar_range[1]); + // Make extra sure there are at least two entries in cpset. + if (cpset.size() < 2) + { + cpset.insert(0.0); + cpset.insert(1.0); + } + + // Now record control points and colors. + this->ControlPoints.erase(this->ControlPoints.begin(), + this->ControlPoints.end()); + this->ControlPoints.resize(cpset.size()); + this->Colors.erase(this->Colors.begin(), this->Colors.end()); + this->Colors.resize(cpset.size()); + + vtkstd::copy(cpset.begin(), cpset.end(), this->ControlPoints.begin()); + for (unsigned int i = 0; i < this->ControlPoints.size(); i++) + { + // Is setting all the colors to the same value the right thing to do? + this->Colors[i].c[0] = this->Colors[i].c[1] = this->Colors[i].c[2] + = intensity->GetValue(this->ControlPoints[i]); + this->Colors[i].c[3] = ( opacity->GetValue(this->ControlPoints[i]) + / unit_distance); + } +} + +inline void vtkPartialPreIntegrationTransferFunction::GetColor(double x, + double c[4]) +{ + unsigned int i = 1; + unsigned int size = this->ControlPoints.size(); + if( !size ) + { + return; + } + while (this->ControlPoints[i] < x && i < size-1) + { + i++; + } + + double before = this->ControlPoints[i-1]; + double after = this->ControlPoints[i]; + + double interp = (x-before)/(after-before); + + double *beforec = this->Colors[i-1].c; + double *afterc = this->Colors[i].c; + c[0] = (1-interp)*beforec[0] + interp*afterc[0]; + c[1] = (1-interp)*beforec[1] + interp*afterc[1]; + c[2] = (1-interp)*beforec[2] + interp*afterc[2]; + c[3] = (1-interp)*beforec[3] + interp*afterc[3]; +} + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkUnstructuredGridPartialPreIntegration, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkUnstructuredGridPartialPreIntegration); + +float vtkUnstructuredGridPartialPreIntegration::PsiTable[PSI_TABLE_SIZE*PSI_TABLE_SIZE]; +int vtkUnstructuredGridPartialPreIntegration::PsiTableBuilt = 0; + +//----------------------------------------------------------------------------- + +vtkUnstructuredGridPartialPreIntegration::vtkUnstructuredGridPartialPreIntegration() +{ + this->Property = NULL; + this->TransferFunctions = NULL; + this->NumIndependentComponents = 0; +} + +//----------------------------------------------------------------------------- +vtkUnstructuredGridPartialPreIntegration::~vtkUnstructuredGridPartialPreIntegration() +{ + if (this->TransferFunctions) + { + delete[] this->TransferFunctions; + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridPartialPreIntegration::PrintSelf(ostream &os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridPartialPreIntegration::Initialize( + vtkVolume *volume, + vtkDataArray *scalars) +{ + vtkVolumeProperty *property = volume->GetProperty(); + + if ( (property == this->Property) + && (this->TransferFunctionsModified > property->GetMTime()) ) + { + // Nothing has changed from the last time Initialize was run. + return; + } + + this->BuildPsiTable(); + + int numcomponents = scalars->GetNumberOfComponents(); + + this->Property = property; + this->TransferFunctionsModified.Modified(); + + if (!property->GetIndependentComponents()) + { + // The scalars actually hold material properties. + if ((numcomponents != 4) && (numcomponents != 2) ) + { + vtkErrorMacro("Only 2-tuples and 4-tuples allowed for dependent components."); + } + return; + } + + if (this->TransferFunctions) + { + delete[] this->TransferFunctions; + } + + this->NumIndependentComponents = numcomponents; + this->TransferFunctions + = new vtkPartialPreIntegrationTransferFunction[numcomponents]; + + for (int component = 0; component < numcomponents; component++) + { + if (property->GetColorChannels(component) == 1) + { + this->TransferFunctions[component] + .GetTransferFunction(property->GetGrayTransferFunction(component), + property->GetScalarOpacity(component), + property->GetScalarOpacityUnitDistance(component), + scalars->GetRange(component)); + } + else + { + this->TransferFunctions[component] + .GetTransferFunction(property->GetRGBTransferFunction(component), + property->GetScalarOpacity(component), + property->GetScalarOpacityUnitDistance(component), + scalars->GetRange(component)); + } + } +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridPartialPreIntegration::Integrate( + vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]) +{ + int numintersections = intersectionLengths->GetNumberOfTuples(); + if (this->Property->GetIndependentComponents()) + { + int numscalars = nearIntersections->GetNumberOfComponents(); + double *nearScalars = new double[numscalars]; + double *farScalars = new double[numscalars]; + vtkstd::set<double> segments; + for (vtkIdType i = 0; i < numintersections; i++) + { + double total_length = intersectionLengths->GetValue(i); + nearIntersections->GetTuple(i, nearScalars); + farIntersections->GetTuple(i, farScalars); + + // Split up segment on control points, because it is nonlinear in + // these regions. + segments.erase(segments.begin(), segments.end()); + segments.insert(0.0); + segments.insert(1.0); + for (int j = 0; j < numscalars; j++) + { + vtkstd::vector<double> &cp = this->TransferFunctions[j].ControlPoints; + vtkIdType numcp = cp.size(); + double minscalar, maxscalar; + if (nearScalars[j] < farScalars[j]) + { + minscalar = nearScalars[j]; maxscalar = farScalars[j]; + } + else + { + minscalar = farScalars[j]; maxscalar = nearScalars[j]; + } + for (int k = 0; k < numcp; k++) + { + if (cp[k] <= minscalar) continue; + if (cp[k] >= maxscalar) break; + // If we are here, we need to break the segment at the given scalar. + // Find the fraction between the near and far segment points. + segments.insert( (cp[k]-nearScalars[j]) + / (farScalars[j]-nearScalars[j])); + } + } + + // Iterate over all the segment pieces (from front to back) and + // integrate each piece. + vtkstd::set<double>::iterator segi = segments.begin(); + double nearInterpolant = *segi; + for (segi++; segi != segments.end(); segi++) + { + double farInterpolant = *segi; + double nearcolor[4] = {0.0, 0.0, 0.0, 0.0}; + double farcolor[4] = {0.0, 0.0, 0.0, 0.0}; + double length = total_length*(farInterpolant-nearInterpolant); + // Here we handle the mixing of material properties. This never + // seems to be defined very clearly. I handle this by assuming + // that each scalar represents a cloud of particles of a certian + // color and a certain density. We mix the scalars in the same way + // as mixing these particles together. By necessity, the density + // becomes greater. The "opacity" parameter is really interpreted + // as the attenuation coefficient (which is proportional to + // density) and can therefore easily be greater than one. The + // opacity of the resulting color will, however, always be scaled + // between 0 and 1. + for (int j = 0; j < numscalars; j++) + { + double scalar + = (farScalars[j]-nearScalars[j])*nearInterpolant + nearScalars[j]; + if (j == 0) + { + this->TransferFunctions[j].GetColor(scalar, nearcolor); + } + else + { + double c[4]; + this->TransferFunctions[j].GetColor(scalar, c); + if (c[3] + nearcolor[3] > 1.0e-8f) + { + nearcolor[0] *= nearcolor[3]/(c[3] + nearcolor[3]); + nearcolor[1] *= nearcolor[3]/(c[3] + nearcolor[3]); + nearcolor[2] *= nearcolor[3]/(c[3] + nearcolor[3]); + nearcolor[0] += c[0]*c[3]/(c[3] + nearcolor[3]); + nearcolor[1] += c[1]*c[3]/(c[3] + nearcolor[3]); + nearcolor[2] += c[2]*c[3]/(c[3] + nearcolor[3]); + nearcolor[3] += c[3]; + } + } + + scalar + = (farScalars[j]-nearScalars[j])*farInterpolant + nearScalars[j]; + if (j == 0) + { + this->TransferFunctions[j].GetColor(scalar, farcolor); + } + else + { + double c[4]; + this->TransferFunctions[j].GetColor(scalar, c); + if (c[3] + farcolor[3] > 1.0e-8f) + { + farcolor[0] *= farcolor[3]/(c[3] + farcolor[3]); + farcolor[1] *= farcolor[3]/(c[3] + farcolor[3]); + farcolor[2] *= farcolor[3]/(c[3] + farcolor[3]); + farcolor[0] += c[0]*c[3]/(c[3] + farcolor[3]); + farcolor[1] += c[1]*c[3]/(c[3] + farcolor[3]); + farcolor[2] += c[2]*c[3]/(c[3] + farcolor[3]); + farcolor[3] += c[3]; + } + } + } + this->IntegrateRay(length, nearcolor, nearcolor[3], + farcolor, farcolor[3], color); + + nearInterpolant = farInterpolant; + } + } + delete[] nearScalars; + delete[] farScalars; + } + else + { + double unitdistance = this->Property->GetScalarOpacityUnitDistance(); + if (nearIntersections->GetNumberOfComponents() == 4) + { + for (vtkIdType i = 0; i < numintersections; i++) + { + double length = intersectionLengths->GetValue(i); + double *nearcolor = nearIntersections->GetTuple(i); + double *farcolor = farIntersections->GetTuple(i); + this->IntegrateRay(length, nearcolor, nearcolor[3]/unitdistance, + farcolor, farcolor[3]/unitdistance, color); + } + } + else // Two components. + { + for (vtkIdType i = 0; i < numintersections; i++) + { + double length = intersectionLengths->GetValue(i); + double *nearcolor = nearIntersections->GetTuple(i); + double *farcolor = farIntersections->GetTuple(i); + this->IntegrateRay(length, nearcolor[0], nearcolor[1]/unitdistance, + farcolor[0], farcolor[1]/unitdistance, color); + } + } + } +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridPartialPreIntegration::BuildPsiTable() +{ + if (vtkUnstructuredGridPartialPreIntegration::PsiTableBuilt) + { + return; + } + + for (int gammafi = 0; gammafi < PSI_TABLE_SIZE; gammafi++) + { + float gammaf = ((float)gammafi+0.0f)/PSI_TABLE_SIZE; + float taufD = gammaf/(1-gammaf); + for (int gammabi = 0; gammabi < PSI_TABLE_SIZE; gammabi++) + { + float gammab = ((float)gammabi+0.0f)/PSI_TABLE_SIZE; + float taubD = gammab/(1-gammab); + + PsiTable[gammafi*PSI_TABLE_SIZE + gammabi] + = vtkUnstructuredGridLinearRayIntegrator::Psi(1, taufD, taubD); + } + } + + vtkUnstructuredGridPartialPreIntegration::PsiTableBuilt = 1; +} diff --git a/VolumeRendering/vtkUnstructuredGridPartialPreIntegration.h b/VolumeRendering/vtkUnstructuredGridPartialPreIntegration.h new file mode 100644 index 0000000..4fe5b22 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridPartialPreIntegration.h @@ -0,0 +1,160 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridPartialPreIntegration.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkUnstructuredGridPartialPreIntegration - performs piecewise linear ray integration. +// +// .SECTION Description +// +// vtkUnstructuredGridPartialPreIntegration performs piecewise linear ray +// integration. This will give the same results as +// vtkUnstructuredGridLinearRayIntegration (with potentially a error due to +// table lookup quantization), but should be notably faster. The algorithm +// used is given by Moreland and Angel, "A Fast High Accuracy Volume +// Renderer for Unstructured Data." +// +// This class is thread safe only after the first instance is created. +// + +#ifndef __vtkUnstructuredGridPartialPreIntegration_h +#define __vtkUnstructuredGridPartialPreIntegration_h + +#include "vtkUnstructuredGridVolumeRayIntegrator.h" +#include "vtkMath.h" // For all the inline methods + +class vtkPartialPreIntegrationTransferFunction; +class vtkVolumeProperty; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridPartialPreIntegration : public vtkUnstructuredGridVolumeRayIntegrator +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridPartialPreIntegration, + vtkUnstructuredGridVolumeRayIntegrator); + static vtkUnstructuredGridPartialPreIntegration *New(); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + virtual void Initialize(vtkVolume *volume, vtkDataArray *scalars); + + virtual void Integrate(vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]); + + // Description: + // Integrates a single ray segment. \c color is blended with the result + // (with \c color in front). The result is written back into \c color. + static void IntegrateRay(double length, + double intensity_front, double attenuation_front, + double intensity_back, double attenuation_back, + float color[4]); + static void IntegrateRay(double length, + const double color_front[3], + double attenuation_front, + const double color_back[3], + double attenuation_back, + float color[4]); + + // Description: + // Looks up Psi (as defined by Moreland and Angel, "A Fast High Accuracy + // Volume Renderer for Unstructured Data") in a table. The table must be + // created first, which happens on the first instantiation of this class + // or when BuildPsiTable is first called. + static float Psi(float taufD, float taubD); + + static void BuildPsiTable(); + +protected: + vtkUnstructuredGridPartialPreIntegration(); + ~vtkUnstructuredGridPartialPreIntegration(); + + vtkVolumeProperty *Property; + + vtkPartialPreIntegrationTransferFunction *TransferFunctions; + vtkTimeStamp TransferFunctionsModified; + int NumIndependentComponents; + +//BTX + enum {PSI_TABLE_SIZE = 512}; +//ETX + static float PsiTable[PSI_TABLE_SIZE*PSI_TABLE_SIZE]; + static int PsiTableBuilt; + +private: + vtkUnstructuredGridPartialPreIntegration(const vtkUnstructuredGridPartialPreIntegration&); // Not implemented. + void operator=(const vtkUnstructuredGridPartialPreIntegration&); // Not implemented. +}; + +inline float vtkUnstructuredGridPartialPreIntegration::Psi(float taufD, + float taubD) +{ + float gammaf = taufD/(taufD+1); + float gammab = taubD/(taubD+1); + int gammafi = vtkMath::Floor(gammaf*PSI_TABLE_SIZE); + int gammabi = vtkMath::Floor(gammab*PSI_TABLE_SIZE); + return PsiTable[gammafi*PSI_TABLE_SIZE + gammabi]; +} + +inline void vtkUnstructuredGridPartialPreIntegration::IntegrateRay( + double length, + double intensity_front, + double attenuation_front, + double intensity_back, + double attenuation_back, + float color[4]) +{ + float taufD = length*attenuation_front; + float taubD = length*attenuation_back; + float Psi = vtkUnstructuredGridPartialPreIntegration::Psi(taufD, taubD); + float zeta = (float)exp(-0.5*(taufD+taubD)); + float alpha = 1-zeta; + + float newintensity = (1-color[3])*( intensity_front*(1-Psi) + + intensity_back*(Psi-zeta) ); + // Is setting the RGB values the same the right thing to do? + color[0] += newintensity; + color[1] += newintensity; + color[2] += newintensity; + color[3] += (1-color[3])*alpha; +} + +inline void vtkUnstructuredGridPartialPreIntegration::IntegrateRay( + double length, + const double color_front[3], + double attenuation_front, + const double color_back[3], + double attenuation_back, + float color[4]) +{ + float taufD = length*attenuation_front; + float taubD = length*attenuation_back; + float Psi = vtkUnstructuredGridPartialPreIntegration::Psi(taufD, taubD); + float zeta = (float)exp(-0.5*(taufD+taubD)); + float alpha = 1-zeta; + + color[0] += (1-color[3])*(color_front[0]*(1-Psi) + color_back[0]*(Psi-zeta)); + color[1] += (1-color[3])*(color_front[1]*(1-Psi) + color_back[1]*(Psi-zeta)); + color[2] += (1-color[3])*(color_front[2]*(1-Psi) + color_back[2]*(Psi-zeta)); + color[3] += (1-color[3])*alpha; +} + +#endif //__vtkUnstructuredGridPartialPreIntegration_h diff --git a/VolumeRendering/vtkUnstructuredGridPreIntegration.cxx b/VolumeRendering/vtkUnstructuredGridPreIntegration.cxx new file mode 100644 index 0000000..2eeeb62 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridPreIntegration.cxx @@ -0,0 +1,470 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridPreIntegration.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +#include "vtkUnstructuredGridPreIntegration.h" + +#include "vtkObjectFactory.h" +#include "vtkVolumeProperty.h" +#include "vtkVolume.h" +#include "vtkAbstractVolumeMapper.h" +#include "vtkUnstructuredGrid.h" +#include "vtkDoubleArray.h" +#include "vtkUnstructuredGridPartialPreIntegration.h" + +#include <vtkstd/algorithm> +#include <math.h> + +//----------------------------------------------------------------------------- + +vtkCxxRevisionMacro(vtkUnstructuredGridPreIntegration, "$Revision: 1.4 $"); +vtkStandardNewMacro(vtkUnstructuredGridPreIntegration); + +vtkCxxSetObjectMacro(vtkUnstructuredGridPreIntegration, Integrator, + vtkUnstructuredGridVolumeRayIntegrator); + +//----------------------------------------------------------------------------- + +vtkUnstructuredGridPreIntegration::vtkUnstructuredGridPreIntegration() +{ + this->Integrator = vtkUnstructuredGridPartialPreIntegration::New(); + this->Property = NULL; + + this->NumComponents = 0; + this->IntegrationTable = NULL; + this->IntegrationTableScalarShift = NULL; + this->IntegrationTableScalarScale = NULL; + + this->IntegrationTableScalarResolution = 128; + this->IntegrationTableLengthResolution = 256; + + this->IncrementalPreIntegration = 1; +} + +vtkUnstructuredGridPreIntegration::~vtkUnstructuredGridPreIntegration() +{ + this->SetIntegrator(NULL); + + if (this->IntegrationTable) + { + for (int i = 0; i < this->NumComponents; i++) + { + delete[] this->IntegrationTable[i]; + } + delete[] this->IntegrationTable; + } + if (this->IntegrationTableScalarShift) + { + delete[] this->IntegrationTableScalarShift; + } + if (this->IntegrationTableScalarScale) + { + delete[] this->IntegrationTableScalarScale; + } +} + +void vtkUnstructuredGridPreIntegration::PrintSelf(ostream &os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "Integrator: " << this->Integrator << endl; + + os << indent << "IntegrationTableScalarResolution: " + << this->IntegrationTableScalarResolution << endl; + os << indent << "IntegrationTableLengthResolution: " + << this->IntegrationTableLengthResolution << endl; + + os << indent << "IncrementalPreIntegration: " + << this->IncrementalPreIntegration << endl; +} + +//----------------------------------------------------------------------------- + +double vtkUnstructuredGridPreIntegration::GetIntegrationTableScalarShift(int component) +{ + return this->IntegrationTableScalarShift[component]; +} + +double vtkUnstructuredGridPreIntegration::GetIntegrationTableScalarScale(int component) +{ + return this->IntegrationTableScalarScale[component]; +} + +double vtkUnstructuredGridPreIntegration::GetIntegrationTableLengthScale() +{ + return this->IntegrationTableLengthScale; +} + +float *vtkUnstructuredGridPreIntegration::GetPreIntegrationTable(int component) +{ + return this->IntegrationTable[component]; +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridPreIntegration::BuildPreIntegrationTables(vtkDataArray *scalars) +{ + // Delete old tables. + if (this->IntegrationTable) + { + for (int i = 0; i < this->NumComponents; i++) + { + delete[] this->IntegrationTable[i]; + } + delete[] this->IntegrationTable; + } + if (this->IntegrationTableScalarShift) + { + delete[] this->IntegrationTableScalarShift; + } + if (this->IntegrationTableScalarScale) + { + delete[] this->IntegrationTableScalarScale; + } + + // Establish temporary inputs to integrator. + vtkVolume *tmpVolume = vtkVolume::New(); + vtkVolumeProperty *tmpProperty = vtkVolumeProperty::New(); + vtkDataArray *tmpScalars + = vtkDataArray::CreateDataArray(scalars->GetDataType()); + + tmpVolume->SetMapper(this->Volume->GetMapper()); + tmpVolume->SetProperty(tmpProperty); + + tmpProperty->IndependentComponentsOn(); + tmpProperty->SetInterpolationType(this->Property->GetInterpolationType()); + + tmpScalars->SetNumberOfComponents(1); + tmpScalars->SetNumberOfTuples(2); + + vtkDoubleArray *tmpIntersectionLengths = vtkDoubleArray::New(); + vtkDataArray *tmpNearIntersections + = vtkDataArray::CreateDataArray(scalars->GetDataType()); + vtkDataArray *tmpFarIntersections + = vtkDataArray::CreateDataArray(scalars->GetDataType()); + + tmpIntersectionLengths->SetNumberOfComponents(1); + tmpIntersectionLengths->SetNumberOfTuples(1); + tmpNearIntersections->SetNumberOfComponents(1); + tmpNearIntersections->SetNumberOfTuples(1); + tmpFarIntersections->SetNumberOfComponents(1); + tmpFarIntersections->SetNumberOfTuples(1); + + this->IntegrationTable = new float*[this->NumComponents]; + this->IntegrationTableScalarShift = new double[this->NumComponents]; + this->IntegrationTableScalarScale = new double[this->NumComponents]; + // Note that the scale set up such that a length of (this->MaxLength + + // epsilon + 0.5) will scale to this->IntegrationTableLengthResolution-1. + // Similar scaling is performed for the other dimensions of the + // pre-integration table. + this->IntegrationTableLengthScale + = (this->IntegrationTableLengthResolution-2)/this->MaxLength; + + // We only do computations at one length. + float d_length = (float)(1/this->IntegrationTableLengthScale); + + for (int component = 0; component < this->NumComponents; component++) + { + int d_idx, sb_idx, sf_idx; + float *c; + + // Allocate table. + try + { + this->IntegrationTable[component] + = new float[4*this->IntegrationTableScalarResolution + *this->IntegrationTableScalarResolution + *this->IntegrationTableLengthResolution]; + } + catch (...) + { + this->IntegrationTable[component] = NULL; + } + + if (this->IntegrationTable[component] == NULL) + { + // Could not allocate memory for table. + if ( (this->IntegrationTableScalarResolution > 32) + || (this->IntegrationTableLengthResolution > 64) ) + { + vtkWarningMacro("Could not allocate integration table.\n" + "Reducing the table size and trying again."); + for (int i = 0; i < component; i++) + { + delete[] this->IntegrationTable[i]; + } + delete[] this->IntegrationTable; + this->IntegrationTable = NULL; + + this->IntegrationTableScalarResolution = 32; + this->IntegrationTableLengthResolution = 64; + this->BuildPreIntegrationTables(scalars); + } + else + { + vtkErrorMacro("Could not allocate integration table."); + } + break; + } + + // Determine scale and shift. + double *range = scalars->GetRange(component); + if (range[0] == range[1]) + { + // Unusual case where the scalars are all the same. + this->IntegrationTableScalarScale[component] = 1.0; + } + else + { + this->IntegrationTableScalarScale[component] + = (this->IntegrationTableScalarResolution-2)/(range[1]-range[0]); + } + this->IntegrationTableScalarShift[component] + = -range[0]*this->IntegrationTableScalarScale[component]; + + // Set values for d=0 (they are all zero). + c = this->IntegrationTable[component]; + for (sb_idx = 0; sb_idx < this->IntegrationTableScalarResolution; sb_idx++) + { + for (sf_idx = 0; sf_idx < this->IntegrationTableScalarResolution; + sf_idx++) + { + c[0] = c[1] = c[2] = c[3] = 0.0f; + c += 4; + } + } + + // Initialize integrator. + if (this->Property->GetColorChannels(component) == 3) + { + tmpProperty->SetColor(this->Property->GetRGBTransferFunction(component)); + } + else + { + tmpProperty->SetColor(this->Property->GetGrayTransferFunction(component)); + } + tmpProperty->SetScalarOpacity(this->Property->GetScalarOpacity(component)); + tmpProperty->SetScalarOpacityUnitDistance + (this->Property->GetScalarOpacityUnitDistance(component)); + tmpProperty->SetShade(this->Property->GetShade(component)); + tmpProperty->SetAmbient(this->Property->GetAmbient(component)); + tmpProperty->SetDiffuse(this->Property->GetDiffuse(component)); + tmpProperty->SetSpecular(this->Property->GetSpecular(component)); + tmpProperty->SetSpecularPower(this->Property->GetSpecularPower(component)); + tmpScalars->SetTuple1(0, range[0]); + tmpScalars->SetTuple1(1, range[1]); + this->Integrator->Initialize(tmpVolume, tmpScalars); + + // Set values for next smallest d (the base values). + tmpIntersectionLengths->SetTuple1(0, d_length); + for (sb_idx = 0; sb_idx < this->IntegrationTableScalarResolution; sb_idx++) + { + tmpFarIntersections + ->SetTuple1(0, + ( (sb_idx - this->IntegrationTableScalarShift[component]) + / (this->IntegrationTableScalarScale[component]) )); + for (sf_idx = 0; sf_idx < this->IntegrationTableScalarResolution; + sf_idx++) + { + tmpNearIntersections + ->SetTuple1(0, + ( (sf_idx - this->IntegrationTableScalarShift[component]) + / (this->IntegrationTableScalarScale[component]) )); + c[0] = c[1] = c[2] = c[3] = 0; + this->Integrator->Integrate(tmpIntersectionLengths, + tmpNearIntersections, tmpFarIntersections, + c); + c += 4; + } + } + + // Set rest of values using other values in table. + if (this->IncrementalPreIntegration) + { + for (d_idx = 2; d_idx < this->IntegrationTableLengthResolution; d_idx++) + { + for (sb_idx = 0; sb_idx < this->IntegrationTableScalarResolution; + sb_idx++) + { + for (sf_idx = 0; sf_idx < this->IntegrationTableScalarResolution; + sf_idx++) + { + // We are going to perform incremental pre-integration. To do + // this, we compute the integration of a ray from sf to sb of + // length d by combining two entries in the table. The first + // entry will be from sf to sm of length delta d (the smallest + // non-zero length stored in the table). The second entry will + // be from sm to sb of length d - delta d. See Weiler, et + // al. "Hardware-Based Ray Casting for Tetrahedral Meshes" for + // more details. + int sm_idx = ((d_idx-1)*sf_idx + sb_idx + d_idx/2)/d_idx; + + float *colorf = this->GetIndexedTableEntry(sf_idx, sm_idx, 1, + component); + float *colorb = this->GetIndexedTableEntry(sm_idx, sb_idx, d_idx-1, + component); + + c[0] = colorf[0] + colorb[0]*(1-colorf[3]); + c[1] = colorf[1] + colorb[1]*(1-colorf[3]); + c[2] = colorf[2] + colorb[2]*(1-colorf[3]); + c[3] = colorf[3] + colorb[3]*(1-colorf[3]); + c += 4; + } + } + } + } + else + { + for (d_idx = 2; d_idx < this->IntegrationTableLengthResolution; d_idx++) + { + for (sb_idx = 0; sb_idx < this->IntegrationTableScalarResolution; + sb_idx++) + { + for (sf_idx = 0; sf_idx < this->IntegrationTableScalarResolution; + sf_idx++) + { + // Compute the integration table the old-fashioned slow way. + float length = d_idx*d_length; + float sb = (float) + ( (sb_idx - this->IntegrationTableScalarShift[component]) + / (this->IntegrationTableScalarScale[component]) ); + float sf = (float) + ( (sf_idx - this->IntegrationTableScalarShift[component]) + / (this->IntegrationTableScalarScale[component]) ); + tmpIntersectionLengths->SetTuple1(0, length); + tmpFarIntersections->SetTuple1(0, sb); + tmpNearIntersections->SetTuple1(0, sf); + c[0] = c[1] = c[2] = c[3] = 0; + this->Integrator->Integrate(tmpIntersectionLengths, + tmpNearIntersections, + tmpFarIntersections, + c); + c += 4; + } + } + } + } + } + + // Get rid of temporary data. + tmpVolume->Delete(); + tmpProperty->Delete(); + tmpScalars->Delete(); + + tmpIntersectionLengths->Delete(); + tmpNearIntersections->Delete(); + tmpFarIntersections->Delete(); +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridPreIntegration::Initialize(vtkVolume *volume, + vtkDataArray *scalars) +{ + vtkIdType i; + vtkVolumeProperty *property = volume->GetProperty(); + + if ( (property == this->Property) + && (this->IntegrationTableBuilt > property->GetMTime()) + && (this->IntegrationTableBuilt > this->MTime) ) + { + // Nothing changed from the last time Initialize was run. + return; + } + + this->NumComponents = scalars->GetNumberOfComponents(); + this->Property = property; + this->Volume = volume; + this->IntegrationTableBuilt.Modified(); + + if (!property->GetIndependentComponents()) + { + vtkErrorMacro("Cannot store dependent components in pre-integration table."); + return; + } + + // Determine the maximum possible length of a ray segment. + vtkDataSet *input = volume->GetMapper()->GetDataSetInput(); + vtkIdType numcells = input->GetNumberOfCells(); + this->MaxLength = 0; + for (i = 0; i < numcells; i++) + { + double cellbounds[6]; + input->GetCellBounds(i, cellbounds); +#define SQR(x) ((x)*(x)) + double diagonal_length = sqrt( SQR(cellbounds[1]-cellbounds[0]) + + SQR(cellbounds[3]-cellbounds[2]) + + SQR(cellbounds[5]-cellbounds[4]) ); +#undef SQR + if (diagonal_length > this->MaxLength) + { + this->MaxLength = diagonal_length; + } + } + + this->BuildPreIntegrationTables(scalars); +} + +//----------------------------------------------------------------------------- + +void vtkUnstructuredGridPreIntegration::Integrate( + vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]) +{ + vtkIdType numIntersections = intersectionLengths->GetNumberOfTuples(); + + for (vtkIdType i = 0; i < numIntersections; i++) + { + float newcolor[4]; + float *c; + c = this->GetTableEntry(nearIntersections->GetComponent(i, 0), + farIntersections->GetComponent(i, 0), + intersectionLengths->GetComponent(i, 0), 0); + newcolor[0] = c[0]; newcolor[1] = c[1]; + newcolor[2] = c[2]; newcolor[3] = c[3]; + for (int component = 1; component < this->NumComponents; component++) + { + c = this->GetTableEntry(nearIntersections->GetComponent(i, component), + farIntersections->GetComponent(i, component), + intersectionLengths->GetComponent(i, 0), + component); + // The blending I'm using is a combination of porter and duff xors + // and ins. + float coef1=1-0.5f*c[3]; + float coef2=1-0.5f*newcolor[3]; + newcolor[0] = newcolor[0]*coef1 + c[0]*coef2; + newcolor[1] = newcolor[1]*coef1 + c[1]*coef2; + newcolor[2] = newcolor[2]*coef1 + c[2]*coef2; + newcolor[3] = newcolor[3]*coef1 + c[3]*coef2; + } + + float coef=1-color[3]; + color[0] += newcolor[0]*coef; + color[1] += newcolor[1]*coef; + color[2] += newcolor[2]*coef; + color[3] += newcolor[3]*coef; + } +} + diff --git a/VolumeRendering/vtkUnstructuredGridPreIntegration.h b/VolumeRendering/vtkUnstructuredGridPreIntegration.h new file mode 100644 index 0000000..fef0182 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridPreIntegration.h @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridPreIntegration.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* + * Copyright 2004 Sandia Corporation. + * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive + * license for use of this work by or on behalf of the + * U.S. Government. Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that this Notice and any + * statement of authorship are reproduced on all copies. + */ + +// .NAME vtkUnstructuredGridPreIntegration - performs ray integration with pre-integration tables. +// +// .SECTION Description +// +// vtkUnstructuredGridPreIntegration performs ray integration by looking +// into a precomputed table. The result should be equivalent to that +// computed by vtkUnstructuredGridLinearRayIntegrator and +// vtkUnstructuredGridPartialPreIntegration, but faster than either one. +// The pre-integration algorithm was first introduced by Roettger, Kraus, +// and Ertl in "Hardware-Accelerated Volume And Isosurface Rendering Based +// On Cell-Projection." +// +// Due to table size limitations, a table can only be indexed by +// independent scalars. Thus, dependent scalars are not supported. +// + +#ifndef __vtkUnstructuredGridPreIntegration_h +#define __vtkUnstructuredGridPreIntegration_h + +#include "vtkUnstructuredGridVolumeRayIntegrator.h" + +class vtkVolumeProperty; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridPreIntegration : public vtkUnstructuredGridVolumeRayIntegrator +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridPreIntegration, + vtkUnstructuredGridVolumeRayIntegrator); + static vtkUnstructuredGridPreIntegration *New(); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + virtual void Initialize(vtkVolume *volume, vtkDataArray *scalars); + + virtual void Integrate(vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]); + + // Description: + // The class used to fill the pre integration table. By default, a + // vtkUnstructuredGridPartialPreIntegration is built. + vtkGetObjectMacro(Integrator, vtkUnstructuredGridVolumeRayIntegrator); + virtual void SetIntegrator(vtkUnstructuredGridVolumeRayIntegrator *); + + // Description: + // Set/Get the size of the integration table built. + vtkSetMacro(IntegrationTableScalarResolution, int); + vtkGetMacro(IntegrationTableScalarResolution, int); + vtkSetMacro(IntegrationTableLengthResolution, int); + vtkGetMacro(IntegrationTableLengthResolution, int); + + // Description:: + // Get how an integration table is indexed. + virtual double GetIntegrationTableScalarShift(int component = 0); + virtual double GetIntegrationTableScalarScale(int component = 0); + virtual double GetIntegrationTableLengthScale(); + + // Description: + // Get/set whether to use incremental pre-integration (by default it's + // on). Incremental pre-integration is much faster but can introduce + // error due to numerical imprecision. Under most circumstances, the + // error is not noticable. + vtkGetMacro(IncrementalPreIntegration, int); + vtkSetMacro(IncrementalPreIntegration, int); + vtkBooleanMacro(IncrementalPreIntegration, int); + + // Description: + // Get the partial pre-integration table for the given scalar component. + // The tables are built when Initialize is called. A segment of length d + // with a front scalar of sf and a back scalar of sb is referenced in the + // resulting table as 4 * ((l * \c IntegrationTableLengthScale) * \c + // IntegrationTableScalarResolution * \c IntegrationTableScalarResolution + // + (sb * \c IntegrationTableScalarScale + \c + // IntegrationTableScalarShift) * \c IntegrationTableScalarResolution + // + (sf * \c IntegrationTableScalarScale + \c + // IntegrationTableScalarShift)). + virtual float *GetPreIntegrationTable(int component = 0); + + // Description: + // Get an entry (RGBA) in one of the pre-integration tables. The tables + // are built when Intialize is called. + float *GetTableEntry(double scalar_front, double scalar_back, double lenth, + int component = 0); + + // Description: + // Like GetTableEntry, except the inputs are scaled indices into the table + // rather than than the actual scalar and length values. Use GetTableEntry + // unless you are really sure you know what you are doing. + float *GetIndexedTableEntry(int scalar_front_index, int scalar_back_index, + int length_index, int component = 0); + +protected: + vtkUnstructuredGridPreIntegration(); + ~vtkUnstructuredGridPreIntegration(); + + vtkUnstructuredGridVolumeRayIntegrator *Integrator; + + vtkVolume *Volume; + vtkVolumeProperty *Property; + double MaxLength; + + int NumComponents; + float **IntegrationTable; + double *IntegrationTableScalarShift; + double *IntegrationTableScalarScale; + double IntegrationTableLengthScale; + vtkTimeStamp IntegrationTableBuilt; + + int IntegrationTableScalarResolution; + int IntegrationTableLengthResolution; + + int IncrementalPreIntegration; + + virtual void BuildPreIntegrationTables(vtkDataArray *scalars); + +private: + vtkUnstructuredGridPreIntegration(const vtkUnstructuredGridPreIntegration&); // Not implemented. + void operator=(const vtkUnstructuredGridPreIntegration&); // Not implemented +}; + +inline float *vtkUnstructuredGridPreIntegration::GetIndexedTableEntry( + int scalar_front_index, + int scalar_back_index, + int length_index, + int component) +{ + // Snap entries to bounds. I don't really want to spend cycles doing + // this, but I've had the ray caster give me values that are noticeably + // out of bounds. + if (scalar_front_index < 0) scalar_front_index = 0; + if (scalar_front_index >= this->IntegrationTableScalarResolution) + scalar_front_index = this->IntegrationTableScalarResolution - 1; + if (scalar_back_index < 0) scalar_back_index = 0; + if (scalar_back_index >= this->IntegrationTableScalarResolution) + scalar_back_index = this->IntegrationTableScalarResolution - 1; + if (length_index < 0) length_index = 0; + if (length_index >= this->IntegrationTableLengthResolution) + length_index = this->IntegrationTableLengthResolution - 1; + + return ( this->IntegrationTable[component] + + 4*( ( ( length_index*this->IntegrationTableScalarResolution + + scalar_back_index) + * this->IntegrationTableScalarResolution) + + scalar_front_index)); +} + +inline float *vtkUnstructuredGridPreIntegration::GetTableEntry( + double scalar_front, double scalar_back, double length, int component) +{ + int sfi = (int)( scalar_front + *this->IntegrationTableScalarScale[component] + + this->IntegrationTableScalarShift[component] + 0.5); + int sbi = (int)( scalar_back*this->IntegrationTableScalarScale[component] + + this->IntegrationTableScalarShift[component] + 0.5); + int li = (int)(length*this->IntegrationTableLengthScale + 0.5); + return this->GetIndexedTableEntry(sfi, sbi, li, component); +} + +#endif //__vtkUnstructuredGridPreIntegration_h diff --git a/VolumeRendering/vtkUnstructuredGridVolumeMapper.cxx b/VolumeRendering/vtkUnstructuredGridVolumeMapper.cxx new file mode 100644 index 0000000..ee4eac6 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeMapper.cxx @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridVolumeMapper.h" + +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkInformation.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridVolumeMapper, "$Revision: 1.1 $"); + +// Construct a vtkUnstructuredGridVolumeMapper with empty scalar input and +// clipping off. +vtkUnstructuredGridVolumeMapper::vtkUnstructuredGridVolumeMapper() +{ + this->BlendMode = vtkUnstructuredGridVolumeMapper::COMPOSITE_BLEND; +} + +vtkUnstructuredGridVolumeMapper::~vtkUnstructuredGridVolumeMapper() +{ +} + +void vtkUnstructuredGridVolumeMapper::SetInput( vtkDataSet *genericInput ) +{ + vtkUnstructuredGrid *input = + vtkUnstructuredGrid::SafeDownCast( genericInput ); + + if ( input ) + { + this->SetInput( input ); + } + else + { + vtkErrorMacro("The SetInput method of this mapper requires vtkUnstructuredGrid as input"); + } +} + +void vtkUnstructuredGridVolumeMapper::SetInput( vtkUnstructuredGrid *input ) +{ + if(input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(0, 0); + } +} + +vtkUnstructuredGrid *vtkUnstructuredGridVolumeMapper::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkUnstructuredGrid::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + + +// Print the vtkUnstructuredGridVolumeMapper +void vtkUnstructuredGridVolumeMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Blend Mode: " << this->BlendMode << endl; +} + +//---------------------------------------------------------------------------- +int vtkUnstructuredGridVolumeMapper::FillInputPortInformation( + int vtkNotUsed( port ), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); + return 1; +} + diff --git a/VolumeRendering/vtkUnstructuredGridVolumeMapper.h b/VolumeRendering/vtkUnstructuredGridVolumeMapper.h new file mode 100644 index 0000000..dc8c2cc --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeMapper.h @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridVolumeMapper - Abstract class for a unstructured grid volume mapper + +// .SECTION Description +// vtkUnstructuredGridVolumeMapper is the abstract definition of a volume mapper for +// unstructured data (vtkUnstructuredGrid). Several basic types of volume mappers +// are supported as subclasses + +// .SECTION see also +// vtkUnstructuredGridVolumeRayCastMapper + +#ifndef __vtkUnstructuredGridVolumeMapper_h +#define __vtkUnstructuredGridVolumeMapper_h + +#include "vtkAbstractVolumeMapper.h" + +class vtkRenderer; +class vtkVolume; +class vtkUnstructuredGrid; +class vtkWindow; + + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridVolumeMapper : public vtkAbstractVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridVolumeMapper,vtkAbstractVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set/Get the input data + virtual void SetInput( vtkUnstructuredGrid * ); + virtual void SetInput( vtkDataSet * ); + vtkUnstructuredGrid *GetInput(); + + vtkSetMacro( BlendMode, int ); + void SetBlendModeToComposite() + { this->SetBlendMode( vtkUnstructuredGridVolumeMapper::COMPOSITE_BLEND ); } + void SetBlendModeToMaximumIntensity() + { this->SetBlendMode( vtkUnstructuredGridVolumeMapper::MAXIMUM_INTENSITY_BLEND ); } + vtkGetMacro( BlendMode, int ); + + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol)=0; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *) {}; + + enum + { + COMPOSITE_BLEND, + MAXIMUM_INTENSITY_BLEND + }; + +//ETX + +protected: + vtkUnstructuredGridVolumeMapper(); + ~vtkUnstructuredGridVolumeMapper(); + + int BlendMode; + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkUnstructuredGridVolumeMapper(const vtkUnstructuredGridVolumeMapper&); // Not implemented. + void operator=(const vtkUnstructuredGridVolumeMapper&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayCastFunction.cxx b/VolumeRendering/vtkUnstructuredGridVolumeRayCastFunction.cxx new file mode 100644 index 0000000..c6fcd0e --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayCastFunction.cxx @@ -0,0 +1,23 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayCastFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridVolumeRayCastFunction.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridVolumeRayCastFunction, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeRayCastFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayCastFunction.h b/VolumeRendering/vtkUnstructuredGridVolumeRayCastFunction.h new file mode 100644 index 0000000..1a1bcf8 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayCastFunction.h @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayCastFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkUnstructuredGridVolumeRayCastFunction - a superclass for ray casting functions + +// .SECTION Description +// vtkUnstructuredGridVolumeRayCastFunction is a superclass for ray casting functions that +// can be used within a vtkUnstructuredGridVolumeRayCastMapper. + +// .SECTION See Also +// vtkUnstructuredGridVolumeRayCastMapper vtkUnstructuredGridVolumeRayIntegrator + +#ifndef __vtkUnstructuredGridVolumeRayCastFunction_h +#define __vtkUnstructuredGridVolumeRayCastFunction_h + +#include "vtkObject.h" + +class vtkRenderer; +class vtkVolume; +class vtkUnstructuredGridVolumeRayCastIterator; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridVolumeRayCastFunction : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridVolumeRayCastFunction,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + +//BTX + virtual void Initialize( vtkRenderer *ren, vtkVolume *vol )=0; + + virtual void Finalize( )=0; + + // Description: + // Returns a new object that will iterate over all the intersections of a + // ray with the cells of the input. The calling code is responsible for + // deleting the returned object. + virtual vtkUnstructuredGridVolumeRayCastIterator *NewIterator() = 0; +//ETX + + +protected: + vtkUnstructuredGridVolumeRayCastFunction() {}; + ~vtkUnstructuredGridVolumeRayCastFunction() {}; + +private: + vtkUnstructuredGridVolumeRayCastFunction(const vtkUnstructuredGridVolumeRayCastFunction&); // Not implemented. + void operator=(const vtkUnstructuredGridVolumeRayCastFunction&); // Not implemented. +}; + +#endif + + + + + + + diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayCastIterator.cxx b/VolumeRendering/vtkUnstructuredGridVolumeRayCastIterator.cxx new file mode 100644 index 0000000..97b159a --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayCastIterator.cxx @@ -0,0 +1,43 @@ +// -*- c++ -*- + +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayCastIterator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridVolumeRayCastIterator.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridVolumeRayCastIterator, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- + +vtkUnstructuredGridVolumeRayCastIterator::vtkUnstructuredGridVolumeRayCastIterator() +{ + this->Bounds[0] = 0.0; + this->Bounds[1] = 1.0; + + this->MaxNumberOfIntersections = 32; +} + +vtkUnstructuredGridVolumeRayCastIterator::~vtkUnstructuredGridVolumeRayCastIterator() +{ +} + +void vtkUnstructuredGridVolumeRayCastIterator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Bounds: [" << this->Bounds[0] << ", " << this->Bounds[1] + << "]" << endl; + os << indent << "MaxNumberOfIntersections: " + << this->MaxNumberOfIntersections << endl; +} diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayCastIterator.h b/VolumeRendering/vtkUnstructuredGridVolumeRayCastIterator.h new file mode 100644 index 0000000..ab98ad9 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayCastIterator.h @@ -0,0 +1,93 @@ +// -*- c++ -*- + +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayCastIterator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkUnstructuredGridVolumeRayCastIterator +// +// .SECTION Description +// +// vtkUnstructuredGridVolumeRayCastIterator is a superclass for iterating +// over the intersections of a viewing ray with a group of unstructured +// cells. These iterators are created with a +// vtkUnstructuredGridVolumeRayCastFunction. +// +// .SECTION See Also +// vtkUnstructuredGridVolumeRayCastFunction +// + +#ifndef __vtkUnstructuredGridRayCastIterator_h +#define __vtkUnstructuredGridRayCastIterator_h + +#include "vtkObject.h" + +class vtkIdList; +class vtkDoubleArray; +class vtkDataArray; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridVolumeRayCastIterator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridVolumeRayCastIterator, vtkObject); + virtual void PrintSelf(ostream &os, vtkIndent indent); + + // Description: + // Initializes the iteration to the start of the ray at the given screen + // coordinates. + virtual void Initialize(int x, int y) = 0; + + // Description: + // Get the intersections of the next several cells. The cell ids are + // stored in \c intersectedCells and the length of each ray segment + // within the cell is stored in \c intersectionLengths. The point + // scalars \c scalars are interpolated and stored in \c nearIntersections + // and \c farIntersections. \c intersectedCells, \c intersectionLengths, + // or \c scalars may be \c NULL to supress passing the associated + // information. The number of intersections actually encountered is + // returned. 0 is returned if and only if no more intersections are to + // be found. + virtual vtkIdType GetNextIntersections(vtkIdList *intersectedCells, + vtkDoubleArray *intersectionLengths, + vtkDataArray *scalars, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections) = 0; + + // Description: + // Set/get the bounds of the cast ray (in viewing coordinates). By + // default the range is [0,1]. + vtkSetVector2Macro(Bounds, double); + vtkGetVector2Macro(Bounds, double); + + // Descrption: + // Set/get the maximum number of intersections returned with a call to + // GetNextIntersections. Set to 32 by default. + vtkSetMacro(MaxNumberOfIntersections, vtkIdType); + vtkGetMacro(MaxNumberOfIntersections, vtkIdType); + +protected: + vtkUnstructuredGridVolumeRayCastIterator(); + ~vtkUnstructuredGridVolumeRayCastIterator(); + + double Bounds[2]; + + vtkIdType MaxNumberOfIntersections; + +private: + vtkUnstructuredGridVolumeRayCastIterator(const vtkUnstructuredGridVolumeRayCastIterator&); // Not implemented. + void operator=(const vtkUnstructuredGridVolumeRayCastIterator&); // Not implemented. +}; + +#endif //__vtkUnstructuredGridRayCastIterator_h + diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayCastMapper.cxx b/VolumeRendering/vtkUnstructuredGridVolumeRayCastMapper.cxx new file mode 100644 index 0000000..9631dcf --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayCastMapper.cxx @@ -0,0 +1,832 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayCastMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridVolumeRayCastMapper.h" + +#include "vtkCamera.h" +#include "vtkEncodedGradientEstimator.h" +#include "vtkEncodedGradientShader.h" +#include "vtkFiniteDifferenceGradientEstimator.h" +#include "vtkUnstructuredGrid.h" +#include "vtkMath.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkPlaneCollection.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTimerLog.h" +#include "vtkTransform.h" +#include "vtkVolumeProperty.h" +#include "vtkUnstructuredGridBunykRayCastFunction.h" +#include "vtkUnstructuredGridVolumeRayCastIterator.h" +#include "vtkUnstructuredGridPreIntegration.h" +#include "vtkUnstructuredGridPartialPreIntegration.h" +#include "vtkUnstructuredGridHomogeneousRayIntegrator.h" +#include "vtkRayCastImageDisplayHelper.h" +#include "vtkDoubleArray.h" +#include "vtkIdList.h" + +#include <math.h> + +VTK_THREAD_RETURN_TYPE UnstructuredGridVolumeRayCastMapper_CastRays( void *arg ); + + +vtkCxxRevisionMacro(vtkUnstructuredGridVolumeRayCastMapper, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkUnstructuredGridVolumeRayCastMapper); + +vtkCxxSetObjectMacro(vtkUnstructuredGridVolumeRayCastMapper, RayCastFunction, + vtkUnstructuredGridVolumeRayCastFunction); +vtkCxxSetObjectMacro(vtkUnstructuredGridVolumeRayCastMapper, RayIntegrator, + vtkUnstructuredGridVolumeRayIntegrator); + +// Construct a new vtkUnstructuredGridVolumeRayCastMapper with default values +vtkUnstructuredGridVolumeRayCastMapper::vtkUnstructuredGridVolumeRayCastMapper() +{ + this->ImageSampleDistance = 1.0; + this->MinimumImageSampleDistance = 1.0; + this->MaximumImageSampleDistance = 10.0; + this->AutoAdjustSampleDistances = 1; + + this->ImageMemorySize[0] = 0; + this->ImageMemorySize[1] = 0; + + this->Threader = vtkMultiThreader::New(); + this->NumberOfThreads = this->Threader->GetNumberOfThreads(); + + this->Image = NULL; + + this->RenderTimeTable = NULL; + this->RenderVolumeTable = NULL; + this->RenderRendererTable = NULL; + this->RenderTableSize = 0; + this->RenderTableEntries = 0; + + this->ZBuffer = NULL; + this->ZBufferSize[0] = 0; + this->ZBufferSize[1] = 0; + this->ZBufferOrigin[0] = 0; + this->ZBufferOrigin[1] = 0; + + this->IntermixIntersectingGeometry = 1; + + this->ImageDisplayHelper = vtkRayCastImageDisplayHelper::New(); + + this->RayCastFunction = vtkUnstructuredGridBunykRayCastFunction::New(); + this->RayIntegrator = NULL; + this->RealRayIntegrator = NULL; + + this->ScalarMode = VTK_SCALAR_MODE_DEFAULT; + this->ArrayName = new char[1]; + this->ArrayName[0] = '\0'; + this->ArrayId = -1; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +// Destruct a vtkUnstructuredGridVolumeRayCastMapper - clean up any memory used +vtkUnstructuredGridVolumeRayCastMapper::~vtkUnstructuredGridVolumeRayCastMapper() +{ + this->Threader->Delete(); + + if ( this->Image ) + { + delete [] this->Image; + } + + if ( this->RenderTableSize ) + { + delete [] this->RenderTimeTable; + delete [] this->RenderVolumeTable; + delete [] this->RenderRendererTable; + } + + this->ImageDisplayHelper->Delete(); + + this->SetRayCastFunction(NULL); + this->SetRayIntegrator(NULL); + if (this->RealRayIntegrator) + { + this->RealRayIntegrator->UnRegister(this); + } + + delete[] this->ArrayName; +} + +float vtkUnstructuredGridVolumeRayCastMapper::RetrieveRenderTime( vtkRenderer *ren, + vtkVolume *vol ) +{ + int i; + + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + return this->RenderTimeTable[i]; + } + } + + return 0.0; +} + +void vtkUnstructuredGridVolumeRayCastMapper::StoreRenderTime( vtkRenderer *ren, + vtkVolume *vol, + float time ) +{ + int i; + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + this->RenderTimeTable[i] = time; + return; + } + } + + + // Need to increase size + if ( this->RenderTableEntries >= this->RenderTableSize ) + { + if ( this->RenderTableSize == 0 ) + { + this->RenderTableSize = 10; + } + else + { + this->RenderTableSize *= 2; + } + + float *oldTimePtr = this->RenderTimeTable; + vtkVolume **oldVolumePtr = this->RenderVolumeTable; + vtkRenderer **oldRendererPtr = this->RenderRendererTable; + + this->RenderTimeTable = new float [this->RenderTableSize]; + this->RenderVolumeTable = new vtkVolume *[this->RenderTableSize]; + this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize]; + + for (i = 0; i < this->RenderTableEntries; i++ ) + { + this->RenderTimeTable[i] = oldTimePtr[i]; + this->RenderVolumeTable[i] = oldVolumePtr[i]; + this->RenderRendererTable[i] = oldRendererPtr[i]; + } + + delete [] oldTimePtr; + delete [] oldVolumePtr; + delete [] oldRendererPtr; + } + + this->RenderTimeTable[this->RenderTableEntries] = time; + this->RenderVolumeTable[this->RenderTableEntries] = vol; + this->RenderRendererTable[this->RenderTableEntries] = ren; + + this->RenderTableEntries++; +} + +void vtkUnstructuredGridVolumeRayCastMapper::SelectScalarArray(int arrayNum) +{ + if ( (this->ArrayId == arrayNum) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) + { + return; + } + this->Modified(); + + this->ArrayId = arrayNum; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +void vtkUnstructuredGridVolumeRayCastMapper::SelectScalarArray(const char *arrayName) +{ + if ( !arrayName + || ( (strcmp(this->ArrayName, arrayName) == 0) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) ) + { + return; + } + this->Modified(); + + delete[] this->ArrayName; + this->ArrayName = new char[strlen(arrayName) + 1]; + strcpy(this->ArrayName, arrayName); + this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME; +} + +// Return the method for obtaining scalar data. +const char *vtkUnstructuredGridVolumeRayCastMapper::GetScalarModeAsString(void) +{ + if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ) + { + return "UseCellData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA ) + { + return "UsePointFieldData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + return "UseCellFieldData"; + } + else + { + return "Default"; + } +} + +void vtkUnstructuredGridVolumeRayCastMapper::ReleaseGraphicsResources(vtkWindow *) +{ +} + +void vtkUnstructuredGridVolumeRayCastMapper::Render( vtkRenderer *ren, vtkVolume *vol ) +{ + int i; + + // Check for input + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<< "No Input!"); + return; + } + + this->Scalars = this->GetScalars(this->GetInput(), this->ScalarMode, + this->ArrayAccessMode, + this->ArrayId, this->ArrayName, + this->CellScalars); + + if (this->Scalars == NULL) + { + vtkErrorMacro("Can't use the ray cast mapper without scalars!"); + return; + } + + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + + // Check to make sure we have an appropriate integrator. + if (this->RayIntegrator) + { + if (this->RealRayIntegrator != this->RayIntegrator) + { + if (this->RealRayIntegrator) + { + this->RealRayIntegrator->UnRegister(this); + } + this->RealRayIntegrator = this->RayIntegrator; + this->RealRayIntegrator->Register(this); + } + } + else + { + +#define ESTABLISH_INTEGRATOR(classname) \ + if ( !this->RealRayIntegrator \ + || (!this->RealRayIntegrator->IsA(#classname)) ) \ + { \ + if (this->RealRayIntegrator) this->RealRayIntegrator->UnRegister(this); \ + this->RealRayIntegrator = classname::New(); \ + this->RealRayIntegrator->Register(this); \ + this->RealRayIntegrator->Delete(); \ + } \ + + if (this->CellScalars) + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridHomogeneousRayIntegrator); + } + else + { + if (vol->GetProperty()->GetIndependentComponents()) + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridPreIntegration); + } + else + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridPartialPreIntegration); + } + } + } + +#undef ESTABLISH_INTEGRATOR + + // Start timing now. We didn't want to capture the update of the + // input data in the times + this->Timer->StartTimer(); + + int oldImageMemorySize[2]; + oldImageMemorySize[0] = this->ImageMemorySize[0]; + oldImageMemorySize[1] = this->ImageMemorySize[1]; + + // If we are automatically adjusting the size to achieve a desired frame + // rate, then do that adjustment here. Base the new image sample distance + // on the previous one and the previous render time. Don't let + // the adjusted image sample distance be less than the minimum image sample + // distance or more than the maximum image sample distance. + float oldImageSampleDistance = this->ImageSampleDistance; + if ( this->AutoAdjustSampleDistances ) + { + float oldTime = this->RetrieveRenderTime( ren, vol ); + float newTime = vol->GetAllocatedRenderTime(); + this->ImageSampleDistance *= sqrt(oldTime / newTime); + this->ImageSampleDistance = + (this->ImageSampleDistance>this->MaximumImageSampleDistance)? + (this->MaximumImageSampleDistance):(this->ImageSampleDistance); + this->ImageSampleDistance = + (this->ImageSampleDistance<this->MinimumImageSampleDistance)? + (this->MinimumImageSampleDistance):(this->ImageSampleDistance); + } + + // The full image fills the viewport. First, compute the actual viewport + // size, then divide by the ImageSampleDistance to find the full image + // size in pixels + int width, height; + ren->GetTiledSize(&width, &height); + this->ImageViewportSize[0] = + static_cast<int>(width/this->ImageSampleDistance); + this->ImageViewportSize[1] = + static_cast<int>(height/this->ImageSampleDistance); + + this->ImageInUseSize[0] = this->ImageViewportSize[0]; + this->ImageInUseSize[1] = this->ImageViewportSize[1]; + this->ImageOrigin[0] = 0; + this->ImageOrigin[1] = 0; + + // What is a power of 2 size big enough to fit this image? + this->ImageMemorySize[0] = 32; + this->ImageMemorySize[1] = 32; + while ( this->ImageMemorySize[0] < this->ImageInUseSize[0] ) + { + this->ImageMemorySize[0] *= 2; + } + while ( this->ImageMemorySize[1] < this->ImageInUseSize[1] ) + { + this->ImageMemorySize[1] *= 2; + } + + // If the old image size is much too big (more than twice in + // either direction) then set the old width to 0 which will + // cause the image to be recreated + if ( oldImageMemorySize[0] > 2*this->ImageMemorySize[0] || + oldImageMemorySize[1] > 2*this->ImageMemorySize[1] ) + { + oldImageMemorySize[0] = 0; + } + + // If the old image is big enough (but not too big - we handled + // that above) then we'll bump up our required size to the + // previous one. This will keep us from thrashing. + if ( oldImageMemorySize[0] >= this->ImageMemorySize[0] && + oldImageMemorySize[1] >= this->ImageMemorySize[1] ) + { + this->ImageMemorySize[0] = oldImageMemorySize[0]; + this->ImageMemorySize[1] = oldImageMemorySize[1]; + } + + // Do we already have a texture big enough? If not, create a new one and + // clear it. + if ( !this->Image || + this->ImageMemorySize[0] > oldImageMemorySize[0] || + this->ImageMemorySize[1] > oldImageMemorySize[1] ) + { + // If there is an image there must be row bounds + if ( this->Image ) + { + delete [] this->Image; + } + + this->Image = new unsigned char[(this->ImageMemorySize[0] * + this->ImageMemorySize[1] * 4)]; + + unsigned char *ucptr = this->Image; + + for ( i = 0; i < this->ImageMemorySize[0]*this->ImageMemorySize[1]; i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + } + + // Capture the zbuffer if necessary + if ( this->IntermixIntersectingGeometry && + ren->GetNumberOfPropsRendered() ) + { + int x1, x2, y1, y2; + double *viewport = ren->GetViewport(); + int *renWinSize = ren->GetRenderWindow()->GetSize(); + + // turn this->ImageOrigin into (x1,y1) in window (not viewport!) + // coordinates. + x1 = static_cast<int> ( + viewport[0] * static_cast<float>(renWinSize[0]) + + static_cast<float>(this->ImageOrigin[0]) * this->ImageSampleDistance ); + y1 = static_cast<int> ( + viewport[1] * static_cast<float>(renWinSize[1]) + + static_cast<float>(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // compute z buffer size + this->ZBufferSize[0] = static_cast<int>( + static_cast<float>(this->ImageInUseSize[0]) * this->ImageSampleDistance); + this->ZBufferSize[1] = static_cast<int>( + static_cast<float>(this->ImageInUseSize[1]) * this->ImageSampleDistance); + + // Use the size to compute (x2,y2) in window coordinates + x2 = x1 + this->ZBufferSize[0] - 1; + y2 = y1 + this->ZBufferSize[1] - 1; + + // This is the z buffer origin (in viewport coordinates) + this->ZBufferOrigin[0] = static_cast<int>( + static_cast<float>(this->ImageOrigin[0]) * this->ImageSampleDistance); + this->ZBufferOrigin[1] = static_cast<int>( + static_cast<float>(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // Capture the z buffer + this->ZBuffer = ren->GetRenderWindow()->GetZbufferData(x1,y1,x2,y2); + } + + this->RayCastFunction->Initialize( ren, vol ); + + this->RealRayIntegrator->Initialize(vol, this->Scalars); + + // Save the volume and mapper temporarily so that they can be accessed later + this->CurrentVolume = vol; + this->CurrentRenderer = ren; + + // Create iterators here to prevent race conditions. + this->RayCastIterators + = new vtkUnstructuredGridVolumeRayCastIterator*[this->NumberOfThreads]; + for (i = 0; i < this->NumberOfThreads; i++) + { + this->RayCastIterators[i] = this->RayCastFunction->NewIterator(); + } + + // Set the number of threads to use for ray casting, + // then set the execution method and do it. + this->Threader->SetNumberOfThreads( this->NumberOfThreads ); + this->Threader->SetSingleMethod( UnstructuredGridVolumeRayCastMapper_CastRays, + (void *)this); + this->Threader->SingleMethodExecute(); + + // We don't need these anymore + this->CurrentVolume = NULL; + this->CurrentRenderer = NULL; + for (i = 0; i < this->NumberOfThreads; i++) + { + this->RayCastIterators[i]->Delete(); + } + delete[] this->RayCastIterators; + + if ( !ren->GetRenderWindow()->GetAbortRender() ) + { + float depth; + if ( this->IntermixIntersectingGeometry ) + { + depth = this->GetMinimumBoundsDepth( ren, vol ); + } + else + { + depth = -1; + } + + this->ImageDisplayHelper-> + RenderTexture( vol, ren, + this->ImageMemorySize, + this->ImageViewportSize, + this->ImageInUseSize, + this->ImageOrigin, + depth, + this->Image ); + + this->Timer->StopTimer(); + this->TimeToDraw = this->Timer->GetElapsedTime(); + this->StoreRenderTime( ren, vol, this->TimeToDraw ); + } + else + { + this->ImageSampleDistance = oldImageSampleDistance; + } + + + if ( this->ZBuffer ) + { + delete [] this->ZBuffer; + this->ZBuffer = NULL; + } + + this->UpdateProgress(1.0); +} + +VTK_THREAD_RETURN_TYPE UnstructuredGridVolumeRayCastMapper_CastRays( void *arg ) +{ + // Get the info out of the input structure + int threadID = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + int threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + vtkUnstructuredGridVolumeRayCastMapper *me = + (vtkUnstructuredGridVolumeRayCastMapper *)((vtkMultiThreader::ThreadInfo *)arg)->UserData; + + if ( !me ) + { + vtkGenericWarningMacro("The volume does not have a ray cast mapper!"); + return VTK_THREAD_RETURN_VALUE; + } + + me->CastRays( threadID, threadCount ); + + return VTK_THREAD_RETURN_VALUE; +} + +template<class T> +inline void vtkUGVRCMLookupCopy(const T *src, T *dest, vtkIdType *lookup, + int numcomponents, int numtuples) +{ + for (vtkIdType i = 0; i < numtuples; i++) + { + const T *srctuple = src + lookup[i] * numcomponents; + for (int j = 0; j < numcomponents; j++) + { + *dest = *srctuple; + dest++; srctuple++; + } + } +} + +void vtkUnstructuredGridVolumeRayCastMapper::CastRays( int threadID, int threadCount ) +{ + int i, j; + unsigned char *ucptr; + + vtkRenderWindow *renWin = this->CurrentRenderer->GetRenderWindow(); + vtkUnstructuredGridVolumeRayCastIterator *iterator + = this->RayCastIterators[threadID]; + + vtkDoubleArray *intersectionLengths = vtkDoubleArray::New(); + vtkDataArray *nearIntersections + = vtkDataArray::CreateDataArray(this->Scalars->GetDataType()); + vtkDataArray *farIntersections; + vtkIdList *intersectedCells; + if (this->CellScalars) + { + intersectedCells = vtkIdList::New(); + farIntersections = nearIntersections; + } + else + { + farIntersections + = vtkDataArray::CreateDataArray(this->Scalars->GetDataType()); + intersectedCells = NULL; + } + + for ( j = 0; j < this->ImageInUseSize[1]; j++ ) + { + if ( j%threadCount != threadID ) + { + continue; + } + + if ( !threadID ) + { + this->UpdateProgress((double)j/this->ImageInUseSize[1]); + if ( renWin->CheckAbortStatus() ) + { + break; + } + } + else if ( renWin->GetAbortRender() ) + { + break; + } + + ucptr = this->Image + 4*j*this->ImageMemorySize[0]; + + for ( i = 0; i < this->ImageInUseSize[0]; i++ ) + { + int x = i + this->ImageOrigin[0]; + int y = j + this->ImageOrigin[1]; + + double bounds[2] = {0.0,1.0}; + float color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + if ( this->ZBuffer ) + { + bounds[1] = this->GetZBufferValue( x, y ); + } + + iterator->SetBounds(bounds); + iterator->Initialize(x, y); + + vtkIdType numIntersections; + do + { + if (this->CellScalars) + { + numIntersections = iterator->GetNextIntersections(intersectedCells, + intersectionLengths, + NULL, + NULL, NULL); + nearIntersections + ->SetNumberOfComponents(this->Scalars->GetNumberOfComponents()); + nearIntersections->SetNumberOfTuples(numIntersections); + switch (this->Scalars->GetDataType()) + { + vtkTemplateMacro(vtkUGVRCMLookupCopy + ((const VTK_TT*)this->Scalars->GetVoidPointer(0), + (VTK_TT*)nearIntersections->GetVoidPointer(0), + intersectedCells->GetPointer(0), + this->Scalars->GetNumberOfComponents(), + numIntersections)); + } + } + else + { + numIntersections = iterator->GetNextIntersections(NULL, + intersectionLengths, + this->Scalars, + nearIntersections, + farIntersections); + } + if (numIntersections < 1) break; + this->RealRayIntegrator->Integrate(intersectionLengths, + nearIntersections, + farIntersections, + color); + } while (color[3] < 0.99); + + if ( color[3] > 0.0 ) + { + int val; + val = static_cast<int>((color[0]/color[3])*255.0); + val = (val > 255)?(255):(val); + val = (val < 0)?( 0):(val); + ucptr[0] = static_cast<unsigned char>(val); + + val = static_cast<int>((color[1]/color[3])*255.0); + val = (val > 255)?(255):(val); + val = (val < 0)?( 0):(val); + ucptr[1] = static_cast<unsigned char>(val); + + val = static_cast<int>((color[2]/color[3])*255.0); + val = (val > 255)?(255):(val); + val = (val < 0)?( 0):(val); + ucptr[2] = static_cast<unsigned char>(val); + + val = static_cast<int>(color[3]*255.0); + val = (val > 255)?(255):(val); + val = (val < 0)?( 0):(val); + ucptr[3] = static_cast<unsigned char>(val); + } + else + { + ucptr[0] = 0; + ucptr[1] = 0; + ucptr[2] = 0; + ucptr[3] = 0; + } + ucptr+=4; + } + } + + intersectionLengths->Delete(); + nearIntersections->Delete(); + if (!this->CellScalars) + { + farIntersections->Delete(); + } + else + { + intersectedCells->Delete(); + } +} + +double vtkUnstructuredGridVolumeRayCastMapper:: +GetMinimumBoundsDepth( vtkRenderer *ren, vtkVolume *vol ) +{ + double bounds[6]; + vol->GetBounds( bounds ); + + vtkTransform *perspectiveTransform = vtkTransform::New(); + vtkMatrix4x4 *perspectiveMatrix = vtkMatrix4x4::New(); + + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + // Get the view matrix in two steps - there is a one step method in camera + // but it turns off stereo so we do not want to use that one + vtkCamera *cam = ren->GetActiveCamera(); + perspectiveTransform->Identity(); + perspectiveTransform->Concatenate( + cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], 0.0, 1.0 )); + perspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + perspectiveMatrix->DeepCopy(perspectiveTransform->GetMatrix()); + + double minZ = 1.0; + + for ( int k = 0; k < 2; k++ ) + { + for ( int j = 0; j < 2; j++ ) + { + for ( int i = 0; i < 2; i++ ) + { + double inPoint[4]; + inPoint[0] = bounds[ i]; + inPoint[1] = bounds[2+j]; + inPoint[2] = bounds[4+k]; + inPoint[3] = 1.0; + + double outPoint[4]; + perspectiveMatrix->MultiplyPoint( inPoint, outPoint ); + double testZ = outPoint[2] / outPoint[3]; + minZ = ( testZ < minZ ) ? (testZ) : (minZ); + } + } + } + + perspectiveTransform->Delete(); + perspectiveMatrix->Delete(); + + return minZ; +} + +double vtkUnstructuredGridVolumeRayCastMapper::GetZBufferValue(int x, int y) +{ + int xPos, yPos; + + xPos = static_cast<int>(static_cast<float>(x) * this->ImageSampleDistance); + yPos = static_cast<int>(static_cast<float>(y) * this->ImageSampleDistance); + + xPos = (xPos >= this->ZBufferSize[0])?(this->ZBufferSize[0]-1):(xPos); + yPos = (yPos >= this->ZBufferSize[1])?(this->ZBufferSize[1]-1):(yPos); + + return *(this->ZBuffer + yPos*this->ZBufferSize[0] + xPos); +} + +// Print method for vtkUnstructuredGridVolumeRayCastMapper +void vtkUnstructuredGridVolumeRayCastMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + + os << indent << "ScalarMode: " << this->GetScalarModeAsString() << endl; + if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) + { + os << indent << "ArrayId: " << this->ArrayId << endl; + } + else + { + os << indent << "ArrayName: " << this->ArrayName << endl; + } + + os << indent << "Image Sample Distance: " + << this->ImageSampleDistance << "\n"; + os << indent << "Minimum Image Sample Distance: " + << this->MinimumImageSampleDistance << "\n"; + os << indent << "Maximum Image Sample Distance: " + << this->MaximumImageSampleDistance << "\n"; + os << indent << "Auto Adjust Sample Distances: " + << this->AutoAdjustSampleDistances << "\n"; + os << indent << "Intermix Intersecting Geometry: " + << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n"); + + os << indent << "Number Of Threads: " << this->NumberOfThreads << "\n"; + + if (this->RayCastFunction) + { + os << indent << "RayCastFunction: " << + this->RayCastFunction->GetClassName() << "\n"; + } + else + { + os << indent << "RayCastFunction: (none)\n"; + } + + if (this->RayIntegrator) + { + os << indent << "RayIntegrator: " + << this->RayIntegrator->GetClassName() << endl; + } + else + { + os << indent << "RayIntegrator: (automatic)" << endl; + } + + // Do not want to print this->ImageOrigin, this->ImageViewportSize or + // this->ImageInUseSize since these are just internal variables with Get + // methods for access from the ray cast function (not part of the public + // API) +} + diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayCastMapper.h b/VolumeRendering/vtkUnstructuredGridVolumeRayCastMapper.h new file mode 100644 index 0000000..f130e8e --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayCastMapper.h @@ -0,0 +1,240 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayCastMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkUnstructuredGridVolumeRayCastMapper - A software mapper for unstructured volumes +// .SECTION Description +// This is a software ray caster for rendering volumes in vtkUnstructuredGrid. + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkUnstructuredGridVolumeRayCastMapper_h +#define __vtkUnstructuredGridVolumeRayCastMapper_h + +#include "vtkUnstructuredGridVolumeMapper.h" + +class vtkMultiThreader; +class vtkRenderer; +class vtkTimerLog; +class vtkVolume; +class vtkUnstructuredGridVolumeRayCastFunction; +class vtkUnstructuredGridVolumeRayCastIterator; +class vtkUnstructuredGridVolumeRayIntegrator; +class vtkRayCastImageDisplayHelper; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridVolumeRayCastMapper : public vtkUnstructuredGridVolumeMapper +{ +public: + static vtkUnstructuredGridVolumeRayCastMapper *New(); + vtkTypeRevisionMacro(vtkUnstructuredGridVolumeRayCastMapper,vtkUnstructuredGridVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Control how the filter works with scalar point data and cell attribute + // data. By default (ScalarModeToDefault), the filter will use point data, + // and if no point data is available, then cell data is used. Alternatively + // you can explicitly set the filter to use point data + // (ScalarModeToUsePointData) or cell data (ScalarModeToUseCellData). + // You can also choose to get the scalars from an array in point field + // data (ScalarModeToUsePointFieldData) or cell field data + // (ScalarModeToUseCellFieldData). If scalars are coming from a field + // data array, you must call SelectColorArray before you call + // GetColors. + vtkSetMacro(ScalarMode,int); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToDefault() { + this->SetScalarMode(VTK_SCALAR_MODE_DEFAULT);}; + void SetScalarModeToUsePointData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA);}; + void SetScalarModeToUseCellData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_DATA);}; + void SetScalarModeToUsePointFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA);}; + void SetScalarModeToUseCellFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA);}; + + // Description: + // When ScalarMode is set to UsePointFileData or UseCellFieldData, + // you can specify which array to use for coloring using these methods. + // The transfer function in the vtkVolumeProperty (attached to the calling + // vtkVolume) will decide how to convert vectors to colors. + virtual void SelectScalarArray(int arrayNum); + virtual void SelectScalarArray(const char* arrayName); + + // Description: + // Get the array name or number and component to color by. + virtual char* GetArrayName() { return this->ArrayName; } + virtual int GetArrayId() { return this->ArrayId; } + virtual int GetArrayAccessMode() { return this->ArrayAccessMode; } + + // Description: + // Return the method for obtaining scalar data. + const char *GetScalarModeAsString(); + + // Description: + // Sampling distance in the XY image dimensions. Default value of 1 meaning + // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If + // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. + vtkSetClampMacro( ImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( ImageSampleDistance, float ); + + // Description: + // This is the minimum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MinimumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MinimumImageSampleDistance, float ); + + // Description: + // This is the maximum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MaximumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MaximumImageSampleDistance, float ); + + // Description: + // If AutoAdjustSampleDistances is on, the the ImageSampleDistance + // will be varied to achieve the allocated render time of this + // prop (controlled by the desired update rate and any culling in + // use). + vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 ); + vtkGetMacro( AutoAdjustSampleDistances, int ); + vtkBooleanMacro( AutoAdjustSampleDistances, int ); + + // Description: + // Set/Get the number of threads to use. This by default is equal to + // the number of available processors detected. + vtkSetMacro( NumberOfThreads, int ); + vtkGetMacro( NumberOfThreads, int ); + + // Description: + // If IntermixIntersectingGeometry is turned on, the zbuffer will be + // captured and used to limit the traversal of the rays. + vtkSetClampMacro( IntermixIntersectingGeometry, int, 0, 1 ); + vtkGetMacro( IntermixIntersectingGeometry, int ); + vtkBooleanMacro( IntermixIntersectingGeometry, int ); + + // Description: + // Set/Get the helper class for casting rays. + virtual void SetRayCastFunction(vtkUnstructuredGridVolumeRayCastFunction *f); + vtkGetObjectMacro(RayCastFunction, vtkUnstructuredGridVolumeRayCastFunction); + + // Description: + // Set/Get the helper class for integrating rays. If set to NULL, a + // default integrator will be assigned. + virtual void SetRayIntegrator(vtkUnstructuredGridVolumeRayIntegrator *ri); + vtkGetObjectMacro(RayIntegrator, vtkUnstructuredGridVolumeRayIntegrator); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Initialize rendering for this volume. + void Render( vtkRenderer *, vtkVolume * ); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + vtkGetVectorMacro( ImageInUseSize, int, 2 ); + vtkGetVectorMacro( ImageOrigin, int, 2 ); + vtkGetVectorMacro( ImageViewportSize, int , 2 ); + +//ETX + + void CastRays( int threadID, int threadCount ); + +protected: + vtkUnstructuredGridVolumeRayCastMapper(); + ~vtkUnstructuredGridVolumeRayCastMapper(); + + float ImageSampleDistance; + float MinimumImageSampleDistance; + float MaximumImageSampleDistance; + int AutoAdjustSampleDistances; + + vtkMultiThreader *Threader; + int NumberOfThreads; + + vtkRayCastImageDisplayHelper *ImageDisplayHelper; + + // This is how big the image would be if it covered the entire viewport + int ImageViewportSize[2]; + + // This is how big the allocated memory for image is. This may be bigger + // or smaller than ImageFullSize - it will be bigger if necessary to + // ensure a power of 2, it will be smaller if the volume only covers a + // small region of the viewport + int ImageMemorySize[2]; + + // This is the size of subregion in ImageSize image that we are using for + // the current image. Since ImageSize is a power of 2, there is likely + // wasted space in it. This number will be used for things such as clearing + // the image if necessary. + int ImageInUseSize[2]; + + // This is the location in ImageFullSize image where our ImageSize image + // is located. + int ImageOrigin[2]; + + // This is the allocated image + unsigned char *Image; + + float *RenderTimeTable; + vtkVolume **RenderVolumeTable; + vtkRenderer **RenderRendererTable; + int RenderTableSize; + int RenderTableEntries; + + void StoreRenderTime( vtkRenderer *ren, vtkVolume *vol, float t ); + float RetrieveRenderTime( vtkRenderer *ren, vtkVolume *vol ); + + int IntermixIntersectingGeometry; + + float *ZBuffer; + int ZBufferSize[2]; + int ZBufferOrigin[2]; + + // Get the ZBuffer value corresponding to location (x,y) where (x,y) + // are indexing into the ImageInUse image. This must be converted to + // the zbuffer image coordinates. Nearest neighbor value is returned. + double GetZBufferValue( int x, int y ); + + double GetMinimumBoundsDepth( vtkRenderer *ren, + vtkVolume *vol ); + + vtkUnstructuredGridVolumeRayCastFunction *RayCastFunction; + vtkUnstructuredGridVolumeRayCastIterator **RayCastIterators; + vtkUnstructuredGridVolumeRayIntegrator *RayIntegrator; + vtkUnstructuredGridVolumeRayIntegrator *RealRayIntegrator; + + vtkVolume *CurrentVolume; + vtkRenderer *CurrentRenderer; + + int ScalarMode; + char *ArrayName; + int ArrayId; + int ArrayAccessMode; + + vtkDataArray *Scalars; + int CellScalars; + +private: + vtkUnstructuredGridVolumeRayCastMapper(const vtkUnstructuredGridVolumeRayCastMapper&); // Not implemented. + void operator=(const vtkUnstructuredGridVolumeRayCastMapper&); // Not implemented. +}; + +#endif + diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayIntegrator.cxx b/VolumeRendering/vtkUnstructuredGridVolumeRayIntegrator.cxx new file mode 100644 index 0000000..e535842 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayIntegrator.cxx @@ -0,0 +1,31 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayIntegrator.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridVolumeRayIntegrator.h" + +vtkCxxRevisionMacro(vtkUnstructuredGridVolumeRayIntegrator, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +vtkUnstructuredGridVolumeRayIntegrator::vtkUnstructuredGridVolumeRayIntegrator() +{ +} + +vtkUnstructuredGridVolumeRayIntegrator::~vtkUnstructuredGridVolumeRayIntegrator() +{ +} + +void vtkUnstructuredGridVolumeRayIntegrator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkUnstructuredGridVolumeRayIntegrator.h b/VolumeRendering/vtkUnstructuredGridVolumeRayIntegrator.h new file mode 100644 index 0000000..34aae19 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeRayIntegrator.h @@ -0,0 +1,71 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeRayIntegrator.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkUnstructuredGridVolumeRayIntegrator - a superclass for volume ray integration functions + +// .SECTION Description +// +// vtkUnstructuredGridVolumeRayIntegrator is a superclass for ray +// integration functions that can be used within a +// vtkUnstructuredGridVolumeRayCastMapper. +// +// .SECTION See Also +// vtkUnstructuredGridVolumeRayCastMapper +// vtkUnstructuredGridVolumeRayCastFunction + +#ifndef __vtkUnstructuredGridVolumeRayIntegrator_h +#define __vtkUnstructuredGridVolumeRayIntegrator_h + +#include "vtkObject.h" + +class vtkVolume; +class vtkDoubleArray; +class vtkDataArray; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridVolumeRayIntegrator : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridVolumeRayIntegrator,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set up the integrator with the given properties and scalars. + virtual void Initialize(vtkVolume *volume, + vtkDataArray* scalars) = 0; + + // Description: + // Given a set of intersections (defined by the three arrays), compute + // the peicewise integration of the array in front to back order. + // /c intersectionLengths holds the lengths of each peicewise segment. + // /c nearIntersections and /c farIntersections hold the scalar values at + // the front and back of each segment. /c color should contain the RGBA + // value of the volume in front of the segments passed in, and the result + // will be placed back into /c color. + virtual void Integrate(vtkDoubleArray *intersectionLengths, + vtkDataArray *nearIntersections, + vtkDataArray *farIntersections, + float color[4]) = 0; + +protected: + vtkUnstructuredGridVolumeRayIntegrator(); + ~vtkUnstructuredGridVolumeRayIntegrator(); + +private: + vtkUnstructuredGridVolumeRayIntegrator(const vtkUnstructuredGridVolumeRayIntegrator&); // Not implemented. + void operator=(const vtkUnstructuredGridVolumeRayIntegrator&); // Not implemented. +}; + +#endif + diff --git a/VolumeRendering/vtkUnstructuredGridVolumeZSweepMapper.cxx b/VolumeRendering/vtkUnstructuredGridVolumeZSweepMapper.cxx new file mode 100644 index 0000000..d1c1da0 --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeZSweepMapper.cxx @@ -0,0 +1,4217 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeZSweepMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkUnstructuredGridVolumeZSweepMapper.h" + +#include "vtkObjectFactory.h" +#include "vtkUnstructuredGrid.h" +#include "vtkTimerLog.h" +#include "vtkVolume.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRayCastImageDisplayHelper.h" +#include "vtkTransform.h" +#include "vtkCamera.h" +#include "vtkGenericCell.h" +#include "vtkPriorityQueue.h" +#include "vtkIdList.h" +#include "vtkVolumeProperty.h" +#include "vtkColorTransferFunction.h" +#include "vtkPiecewiseFunction.h" +#include "vtkUnstructuredGridPreIntegration.h" +#include "vtkUnstructuredGridPartialPreIntegration.h" +#include "vtkUnstructuredGridHomogeneousRayIntegrator.h" +#include "vtkDoubleArray.h" +#include "vtkDataArray.h" + +#include "vtkPolyData.h" +#include "vtkCellArray.h" +#include "vtkXMLPolyDataWriter.h" +#include "vtkPointData.h" + +#include <assert.h> +#include <string.h> // memset() +#include <vtkstd/vector> +#include <vtkstd/list> + +// do not remove the following line: +//#define BACK_TO_FRONT + +enum +{ + VTK_VALUES_X_INDEX=0, // world coordinate + VTK_VALUES_Y_INDEX, // world coordinate + VTK_VALUES_Z_INDEX, // world coordinate + VTK_VALUES_SCALAR_INDEX, + VTK_VALUES_SIZE // size of a value array +}; + +// Internal classes +//----------------------------------------------------------------------------- +// Store the result of the scan conversion at some pixel. +class vtkPixelListEntry +{ +public: + vtkPixelListEntry() + { + } + + void Init(double values[VTK_VALUES_SIZE], + double zView) + { + this->Zview=zView; + int i=0; + while(i<VTK_VALUES_SIZE) + { + this->Values[i]=values[i]; + ++i; + } + } + + + // Return the interpolated values at this pixel. + double *GetValues() { return this->Values; } + // Return the interpolated z coordinate in view space at this pixel. + double GetZview() const { return this->Zview; } + + vtkPixelListEntry *GetPrevious() { return this->Previous; } + vtkPixelListEntry *GetNext() { return this->Next; } + + void SetPrevious(vtkPixelListEntry *e) { this->Previous=e; } + void SetNext(vtkPixelListEntry *e) { this->Next=e; } + +protected: + double Values[VTK_VALUES_SIZE]; + double Zview; + + // List structure: both for the free block list (one-way) and any + // pixel list (two-way) + vtkPixelListEntry *Next; + // List structure: only for the pixel list (two-way) + vtkPixelListEntry *Previous; +private: + vtkPixelListEntry(const vtkPixelListEntry &other); + vtkPixelListEntry &operator=(const vtkPixelListEntry &other); +}; + +//----------------------------------------------------------------------------- +// Cache the projection of a vertex +class vtkVertexEntry +{ +public: + vtkVertexEntry() {} + + vtkVertexEntry(int screenX, + int screenY, + double xWorld, + double yWorld, + double zWorld, + double zView, + double scalar, + double invW) + :ScreenX(screenX),ScreenY(screenY),Zview(zView),InvW(invW) + { + this->Values[VTK_VALUES_X_INDEX]=xWorld; + this->Values[VTK_VALUES_Y_INDEX]=yWorld; + this->Values[VTK_VALUES_Z_INDEX]=zWorld; + this->Values[VTK_VALUES_SCALAR_INDEX]=scalar; + } + + void Set(int screenX, + int screenY, + double xWorld, + double yWorld, + double zWorld, + double zView, + double scalar, + double invW) + { + this->ScreenX=screenX; + this->ScreenY=screenY; + this->Zview=zView; + this->Values[VTK_VALUES_X_INDEX]=xWorld; + this->Values[VTK_VALUES_Y_INDEX]=yWorld; + this->Values[VTK_VALUES_Z_INDEX]=zWorld; + this->Values[VTK_VALUES_SCALAR_INDEX]=scalar; + this->InvW=invW; + } + + int GetScreenX() + { + return this->ScreenX; + } + int GetScreenY() + { + return this->ScreenY; + } + double *GetValues() + { + return this->Values; + } + double GetZview() + { + return this->Zview; + } + double GetInvW() + { + return this->InvW; + } + + vtkVertexEntry(const vtkVertexEntry &vtkNotUsed(other)) {} + +protected: + int ScreenX; + int ScreenY; + double Values[VTK_VALUES_SIZE]; + double Zview; + double InvW; + +private: + vtkVertexEntry &operator=(const vtkVertexEntry &other); +}; + + +//----------------------------------------------------------------------------- +// Abstract interface for an edge of a triangle in the screen space. +// Used during scan-conversion. +class vtkScreenEdge +{ +public: + // If the edge is a composite edge (top+bottom) switch to the bottom edge. + // Otherwise, do nothing. + virtual void OnBottom(int skipped, int y) + { + if(!skipped) + { + this->NextLine(y); + } + } + // Increment edge state to the next line. + virtual void NextLine(int y)=0; + // Increment edge state to the next deltaY line. + virtual void SkipLines(int deltaY, + int y)=0; + // Return the abscissa for the current line. + virtual int GetX()=0; + // Return the projected values for the current line. They are linearly + // incrementally interpolated in view space. The actual values are + // given by projectedValue/InvW. This is the way the values in world space + // are incrementally (not linearly) interpolated in view space. + virtual double *GetPValues()=0; + // Return 1/W, linearly interpolated in view space. + virtual double GetInvW()=0; + // Return Z in view coordinates, linearly interpolated in view space. + virtual double GetZview()=0; +protected: + // Destructor. + virtual ~vtkScreenEdge() {} +}; + +//----------------------------------------------------------------------------- +// Do an incremental traversing of an edge based on an Y increment. +enum +{ + VTK_CASE_VERTICAL=0, + VTK_CASE_MOSTLY_VERTICAL, + VTK_CASE_DIAGONAL, + VTK_CASE_HORIZONTAL_BEGIN, + VTK_CASE_HORIZONTAL_END, + VTK_CASE_HORIZONTAL_MS, // most significant pixel + VTK_CASE_VERTICAL_IN_TO_OUT, // with edge equation + VTK_CASE_VERTICAL_OUT_TO_IN, + VTK_CASE_HORIZONTAL_IN_TO_OUT, + VTK_CASE_HORIZONTAL_OUT_TO_IN +}; + +// We use an edge equation as described in: +// Juan Pineda +// A Parallel Algorithm for Polygon Rasterization +// In Computer Graphics, Volume 22, Number 4, August 1988 +// SIGGRAPH'88, Atlanta, August 1-5, 1988. +// pages 17--20. + +// or in: + +// Marc Olano and Trey Greer +// Triangle Scan Conversion using 2D Homogeneous Coordinates +// In 1997 SIGGRAPH/Eurographics Workshop +// pages 89--95. +// http://www.cs.unc.edu/~olano/papers/2dh-tri/2dh-tri.pdf + +#define MOST_SIGNIFICANT +#define EDGE_EQUATION +#define HORI_EDGE_EQUATION +//#define STRICTLY_INSIDE + +class vtkSimpleScreenEdge + : public vtkScreenEdge +{ +public: + // Initialize the edge by the vertices v0 and v2 (ordered in y) + // `onRight' is true if the edge in on the right side of the triangle. + void Init(vtkVertexEntry *v0, + vtkVertexEntry *v2, + int dx20, + int dy20, + int onRight) + { + double z0=v0->GetZview(); + double z2=v2->GetZview(); + + double invW0=v0->GetInvW(); + double invW2=v2->GetInvW(); + + double pv0[VTK_VALUES_SIZE]; + double pv2[VTK_VALUES_SIZE]; + int i=0; + while(i<VTK_VALUES_SIZE) + { + pv0[i]=v0->GetValues()[i]*invW0; + this->PValues[i]=pv0[i]; + pv2[i]=v2->GetValues()[i]*invW2; + ++i; + } + + this->InvW=invW0; + this->Zview=z0; + + int x0=v0->GetScreenX(); + int x2=v2->GetScreenX(); + + this->X0=x0; + this->X2=x2; + + this->V2=v2; + + this->X=x0; + + if(dx20==0) + { + this->Case=VTK_CASE_VERTICAL; + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; + } + else + { + if(dx20>0) + { + this->IncX=1; + if(dx20>dy20) + { + // Mostly horizontal +#ifdef HORI_EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_HORIZONTAL_IN_TO_OUT; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_OUT_TO_IN; + } + this->Error=0; + this->SDy=dy20; + this->XStep=dx20/dy20; // integral division + this->Dx=dx20-this->XStep*this->SDy; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else +#ifdef MOST_SIGNIFICANT + this->Case=VTK_CASE_HORIZONTAL_MS; + this->XStep=dx20/dy20; // integral division + this->Dy=dy20; + this->Dy2=dy20<<1; // *2 + this->Error=0; + this->ErrorStep=(dx20-this->XStep*dy20)<<1; // 2*r, dx=q*dy+r, r<dy + double invDx20=1.0/dx20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=this->DinvW*this->XStep; + this->ZStep=this->Dz*this->XStep; + +#else + if(!onRight) + { + this->Case=VTK_CASE_HORIZONTAL_BEGIN; + this->First=1; + this->Dy2=dy20<<1; // *2 + this->Dx2=dx20<<1; // *2 + this->Error=dx20; + + this->XStep=dx20/dy20; // integral division + + this->ErrorStep=this->XStep*this->Dy2; + + double invDx20=1.0/dx20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=this->DinvW*this->XStep; + this->ZStep=this->Dz*this->XStep; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_END; + + this->InvW2=invW2; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues2[i]=pv2[i]; + ++i; + } + + this->Zview2=z2; + + this->Dy2=dy20<<1; // *2 + this->Dx2=dx20<<1; // *2 + this->Error=dx20; + this->XStep=dx20/dy20; + this->ErrorStep=this->XStep*this->Dy2; + + double invDx20=1.0/dx20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=this->DinvW*this->XStep; + this->ZStep=this->Dz*this->XStep; + + while(this->Error<this->Dx2) + { + this->X+=this->IncX; + this->InvW+= this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + this->X-=this->IncX; + this->InvW-= this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]-=this->Dpv[i]; + ++i; + } + this->Zview-=this->Dz; + } +#endif +#endif // EDGE_EQUATION + } + else + { + if(dx20==dy20) + { + this->Case=VTK_CASE_DIAGONAL; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; + } + else + { +#ifdef EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_VERTICAL_IN_TO_OUT; + } + else + { + this->Case=VTK_CASE_VERTICAL_OUT_TO_IN; + } + this->Error=0; + this->SDy=dy20; + this->Dx=dx20; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else + this->Case=VTK_CASE_MOSTLY_VERTICAL; + this->Dx2=dx20<<1; // *2 + this->Dy2=dy20<<1; // *2 + this->Error=dy20; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#endif + } + } + } + else + { + this->IncX=-1; + if(-dx20>dy20) + { + // Mostly horizontal +#ifdef HORI_EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_HORIZONTAL_OUT_TO_IN; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_IN_TO_OUT; + } + this->Error=0; + this->SDy=-dy20; + this->XStep=dx20/dy20; // integral division + this->Dx=dx20+this->XStep*this->SDy; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else +#ifdef MOST_SIGNIFICANT + this->Case=VTK_CASE_HORIZONTAL_MS; + this->XStep=dx20/dy20; // integral division + this->Dy=dy20; + this->Dy2=dy20<<1; // *2 + this->Error=0; + this->ErrorStep=(dx20+this->XStep*dy20)<<1; // 2*r, dx=q*dy+r, r<dy + double invDx20=-1.0/dx20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=-this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=-this->DinvW*this->XStep; + this->ZStep=-this->Dz*this->XStep; + + +#else + if(onRight) + { + this->Case=VTK_CASE_HORIZONTAL_BEGIN; + this->First=1; + this->Dy2=dy20<<1; // *2 + this->Dx2=(-dx20)<<1; // *2 + this->Error=-dx20; + this->XStep=dx20/dy20; + this->ErrorStep=-this->XStep*this->Dy2; + + double invDx20=-1.0/dx20; + + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=-this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=-this->DinvW*this->XStep; + this->ZStep=-this->Dz*this->XStep; + } + else + { + this->Case=VTK_CASE_HORIZONTAL_END; + + this->InvW2=invW2; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues2[i]=pv2[i]; + ++i; + } + this->Zview2=z2; + + this->Dy2=dy20<<1; // *2 + this->Dx2=(-dx20)<<1; // *2 + this->Error=-dx20; + this->XStep=dx20/dy20; + this->ErrorStep=-this->XStep*this->Dy2; + + double invDx20=-1.0/dx20; + + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDx20; + this->PValuesStep[i]=-this->Dpv[i]*this->XStep; + ++i; + } + this->DinvW=(invW2-invW0)*invDx20; + this->Dz=(z2-z0)*invDx20; + this->InvWStep=-this->DinvW*this->XStep; + this->ZStep=-this->Dz*this->XStep; + + while(this->Error<this->Dx2) + { + this->X+=this->IncX; + this->InvW+= this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + this->X-=this->IncX; + + this->InvW-= this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]-=this->Dpv[i]; + ++i; + } + this->Zview-=this->Dz; + } +#endif +#endif // EDGE_EQUATION + } + else + { + if(dx20==-dy20) + { + this->Case=VTK_CASE_DIAGONAL; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; + } + else + { +#ifdef EDGE_EQUATION + if(onRight) + { + this->Case=VTK_CASE_VERTICAL_OUT_TO_IN; + } + else + { + this->Case=VTK_CASE_VERTICAL_IN_TO_OUT; + } + this->Error=0; + this->SDy=-dy20; + this->Dx=dx20; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#else + this->Case=VTK_CASE_MOSTLY_VERTICAL; + this->Dx2=(-dx20)<<1; // *2 + this->Dy2=dy20<<1; // *2 + this->Error=dy20; + + double invDy20=1.0/dy20; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pv2[i]-pv0[i])*invDy20; + ++i; + } + this->DinvW=(invW2-invW0)*invDy20; + this->Dz=(z2-z0)*invDy20; +#endif + } + } + } + } + } + + // Check that the current abscissa is in the range given by the vertices. + int ValidXRange() + { + if(this->X0<=this->X2) + { + return (this->X>=this->X0) && (this->X<=this->X2); + } + else + { + return (this->X>=this->X2) && (this->X<=this->X0); + } + } + int GetX() + { + // assert("pre: valid_range" && ValidXRange() ); + return this->X; + } + double GetInvW() { return this->InvW; } + double *GetPValues() { return this->PValues; } + double GetZview() { return this->Zview; } + + void NextLine(int y) + { + int i; + switch(this->Case) + { + case VTK_CASE_VERTICAL: + // nothing to do with X + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_DIAGONAL: + // X + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_MOSTLY_VERTICAL: + // X + this->Error+=this->Dx2; + if(this->Error>=this->Dy2) + { + this->Error-=this->Dy2; + this->X+=this->IncX; + } + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_VERTICAL_OUT_TO_IN: + this->Error-=this->Dx; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) +#else + if(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // we are no more on the left side +#else + if(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE +// assert("check: negative_equation" && this->Error>0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + case VTK_CASE_VERTICAL_IN_TO_OUT: + this->Error+=this->SDy-this->Dx; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) // out: too far on left +#else + if(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // out: too far on right +#else + if(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: negative_equation" && this->Error<0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + + case VTK_CASE_HORIZONTAL_OUT_TO_IN: + this->Error-=this->Dx; + this->X+=this->XStep; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) // we are no more on the right side +#else + if(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // we are no more on the left side +#else + if(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; +#ifdef STRICTLY_INSIDE + assert("check: negative_equation" && this->Error<0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + + case VTK_CASE_HORIZONTAL_IN_TO_OUT: + this->Error+=this->SDy-this->Dx; + this->X+=this->XStep; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + if(this->Error<=0) // out: too far on left +#else + if(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE +// assert("check: positive_equation" && this->Error>0); +#else + assert("check: positive_equation" && this->Error>=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + if(this->Error>=0) // out: too far on right +#else + if(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; +#ifdef STRICTLY_INSIDE +// assert("check: negative_equation" && this->Error<0); +#else + assert("check: negative_equation" && this->Error<=0); +#endif + } + else + { + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + break; + + case VTK_CASE_HORIZONTAL_BEGIN: + if(this->First) + { + this->First=0; + } + else + { + this->X+=this->XStep; + + this->InvW+=this->InvWStep; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->PValuesStep[i]; + ++i; + } + this->Zview+=this->ZStep; + this->Error+=this->ErrorStep; + } + while(this->Error<this->Dx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + break; + case VTK_CASE_HORIZONTAL_END: + if(y==this->V2->GetScreenY()) + { + this->X=this->V2->GetScreenX(); + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]=this->PValues2[i]; + ++i; + } + this->Zview=this->Zview2; + this->InvW=this->InvW2; + } + else + { + this->X+=this->XStep; + + this->InvW+=this->InvWStep; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->PValuesStep[i]; + ++i; + } + this->Zview+=this->ZStep; + + this->Error+=this->ErrorStep; + + while(this->Error<this->Dx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + } + break; + case VTK_CASE_HORIZONTAL_MS: + this->Error+=this->ErrorStep; + if(this->Error>=this->Dy) + { + this->Error-=this->Dy2; + this->X+=this->XStep+this->IncX; + this->InvW+=this->InvWStep+this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->PValuesStep[i]+this->Dpv[i]; + ++i; + } + this->Zview+=this->ZStep+this->Dz; + } + else + { + this->X+=this->XStep; + this->InvW+=this->InvWStep; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->PValuesStep[i]; + ++i; + } + this->Zview+=this->ZStep; + } + break; + } + } + + void SkipLines(int deltaY, + int y) + { + if(deltaY==1) + { + this->NextLine(0); + return; + } + + int firstDeltaY; + int i; + switch(this->Case) + { + case VTK_CASE_VERTICAL: + // nothing to do with X + this->InvW+=this->DinvW*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_DIAGONAL: + // X + this->X+=this->IncX*deltaY; + this->InvW+=this->DinvW*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_MOSTLY_VERTICAL: + // X + this->Error+=this->Dx2*deltaY; + while(this->Error>=this->Dy2) + { + this->Error-=this->Dy2; + this->X+=this->IncX; + } + this->InvW+=this->DinvW*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_VERTICAL_OUT_TO_IN: + this->Error-=this->Dx*deltaY; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // we are no more on the right side +#else + while(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // we are no more on the left side +#else + while(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_VERTICAL_IN_TO_OUT: + this->Error+=(this->SDy-this->Dx)*deltaY; + this->X+=this->IncX*deltaY; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // out: too far on left +#else + while(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // out: too far on right +#else + while(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + + case VTK_CASE_HORIZONTAL_OUT_TO_IN: + this->Error-=this->Dx*deltaY; + this->X+=this->XStep*deltaY; + if(this->SDy>0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // we are no more on the right side +#else + while(this->Error<0) // we are no more on the right side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // we are no more on the left side +#else + while(this->Error>0) // we are no more on the left side +#endif + { + this->Error+=this->SDy; + this->X+=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + case VTK_CASE_HORIZONTAL_IN_TO_OUT: + this->Error+=(this->SDy-this->Dx)*deltaY; + this->X+=(this->XStep+this->IncX)*deltaY; +// this->X+=this->IncX*deltaY; + if(this->SDy<0) + { +#ifdef STRICTLY_INSIDE + while(this->Error<=0) // out: too far on left +#else + while(this->Error<0) // out: too far on left +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + else + { +#ifdef STRICTLY_INSIDE + while(this->Error>=0) // out: too far on right +#else + while(this->Error>0) // out: too far on right +#endif + { + this->Error-=this->SDy; + this->X-=this->IncX; + } + } + // Interpolate the values on inc y + this->InvW+=this->DinvW*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]*deltaY; + ++i; + } + this->Zview+=this->Dz*deltaY; + break; + + case VTK_CASE_HORIZONTAL_BEGIN: + + if(this->First) + { + this->First=0; + firstDeltaY=deltaY-1; + } + else + { + firstDeltaY=deltaY; + } + + this->X+=this->XStep*firstDeltaY; + + this->InvW+=this->InvWStep*firstDeltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->PValuesStep[i]*firstDeltaY; + ++i; + } + this->Zview+=this->ZStep*firstDeltaY; + this->Error+=this->ErrorStep*firstDeltaY; + + while(this->Error<this->Dx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + break; + case VTK_CASE_HORIZONTAL_END: + if(y==this->V2->GetScreenY()) + { + this->X=this->V2->GetScreenX(); + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]=this->PValues2[i]; + ++i; + } + this->Zview=this->Zview2; + this->InvW=this->InvW2; + } + else + { + this->X+=this->XStep*deltaY; + + this->InvW+=this->InvWStep*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->PValuesStep[i]*deltaY; + ++i; + } + this->Zview+=this->ZStep*deltaY; + + this->Error+=this->ErrorStep*deltaY; + + while(this->Error<this->Dx2) + { + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + + this->Error+=this->Dy2; + } + this->Error-=this->Dx2; + } + break; + case VTK_CASE_HORIZONTAL_MS: + this->Error+=this->ErrorStep*deltaY; + this->X+=this->XStep*deltaY; + this->InvW+=this->InvWStep*deltaY; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->PValuesStep[i]*deltaY; + ++i; + } + this->Zview+=this->ZStep*deltaY; + + while(this->Error>=this->Dy) + { + this->Error-=this->Dy2; + this->X+=this->IncX; + this->InvW+=this->DinvW; + i=0; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + ++i; + } + this->Zview+=this->Dz; + } + break; + } + } + +protected: + int Case; + int Error; // error to the mid-point + int Dx2; // 2*dx + int Dy2; // 2*dy + int First; // use only with VTK_CASE_HORIZONTAL_BEGIN case + int XStep; // dx/dy + int ErrorStep; // XStep*Dy2 + + vtkVertexEntry *V2; + + int IncX; // -1 or 1 + + int X; // Current abscissa + + int X0; // for debugging + int X2; // for debugging + + // Slope of 1/w + double DinvW; + // Current 1/W + double InvW; + // DinvW*XStep + double InvWStep; + // 1/W at the end vertex + double InvW2; + + // Slope of the z coordinate in view space + double Dz; + // current z in view space + double Zview; + // Dz*XStep + double ZStep; + // z coordinate in view space at the end vertex + double Zview2; + + // Slope of each projected values on the edge + double Dpv[VTK_VALUES_SIZE]; + + + // Current projected values + double PValues[VTK_VALUES_SIZE]; + // Dpv*XStep + double PValuesStep[VTK_VALUES_SIZE]; + // Values at the end vertex. + double PValues2[VTK_VALUES_SIZE]; + + int Dy; // VTK_HORIZONTAL_MS + int SDy; // VTK_VERTICAL_LEFT/RIGHT + int Dx; // VTK_VERTICAL_LEFT/RIGHT +}; + +//----------------------------------------------------------------------------- +// During rasterization of a triangle, there is always one side with two +// edges and the other side with a single edge. +// This class manages the side with the two edges called top and bottom edges. +class vtkDoubleScreenEdge + :public vtkScreenEdge +{ +public: + void Init(vtkVertexEntry *v0, + vtkVertexEntry *v1, + vtkVertexEntry *v2, + int dx10, + int dy10, + int onRight) + { + this->Current=0; + if(dy10!=0) + { + this->Top.Init(v0,v1,dx10,dy10,onRight); + this->Current=&this->Top; + } + + int dx21=v2->GetScreenX()-v1->GetScreenX(); + int dy21=v2->GetScreenY()-v1->GetScreenY(); + + if(dy21!=0) + { + this->Bottom.Init(v1,v2,dx21,dy21,onRight); + if(this->Current==0) + { + this->Current=&this->Bottom; + } + } + } + + int GetX() { return this->Current->GetX(); } + double GetInvW() { return this->Current->GetInvW(); } + double GetZview() { return this->Current->GetZview(); } + double *GetPValues() { return this->Current->GetPValues(); } + + void OnBottom(int skipped, int y) + { + this->Current=&this->Bottom; + this->Current->OnBottom(skipped,y); + } + + void NextLine(int y) + { + this->Current->NextLine(y); + } + void SkipLines(int deltaY, + int y) + { + this->Current->SkipLines(deltaY,y); + } + +protected: + vtkSimpleScreenEdge Top; + vtkSimpleScreenEdge Bottom; + vtkScreenEdge *Current; +}; + +//----------------------------------------------------------------------------- +// Horizontal span between two points of two edges. +// Used during scan-conversion. +// It interpolates the values along the span. + +class vtkSpan +{ +public: + // Initialize the span from the left abcissa x0 and the right absissa x1 and + // from 1/W, the projected values and the z coordinate in view space at + // thoses points. Set the current state to the left point. + void Init(int x0, + double invW0, + double pValues0[VTK_VALUES_SIZE], // projected values + double zView0, + int x1, + double invW1, + double pValues1[VTK_VALUES_SIZE], // projected values + double zView1) + { +// assert("pre: dx>=0" && x1-x0>=0); + // x0=x1: the span is just a point + + int i; + if(x0!=x1) + { + + double invDx10=1.0/(x1-x0); + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=(pValues1[i]-pValues0[i])*invDx10; + ++i; + } + this->DinvW=(invW1-invW0)*invDx10; + this->Dz=(zView1-zView0)*invDx10; + } + else + { + i=0; + while(i<VTK_VALUES_SIZE) + { + this->Dpv[i]=0; + ++i; + } + this->DinvW=0; + this->Dz=0; + } + + this->Zview=zView0; + this->InvW=invW0; + i=0; + double w=1/this->InvW; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]=pValues0[i]; + this->Values[i]=this->PValues[i]*w; + ++i; + } + this->X=x0; + this->X1=x1; + } + + // Is the current state after the right point? + int IsAtEnd() + { + return this->X>this->X1; + } + + // Current abscissa. + int GetX() { return this->X; } + // Current values. + double *GetValues() { return this->Values; } + // Current z coordinate in view space. + double GetZview() { return this->Zview; } + + // Go the next abscissa from left to right. + void NextPixel() + { + ++this->X; + + this->InvW+=this->DinvW; + int i=0; + double w=1/this->InvW; + while(i<VTK_VALUES_SIZE) + { + this->PValues[i]+=this->Dpv[i]; + this->Values[i]=this->PValues[i]*w; + ++i; + } + this->Zview+=this->Dz; + } + +protected: + int X1; // abscissa at the right point. + + int X; // current abscissa + + // Slope of 1/w + double DinvW; + // current 1/W + double InvW; + + // Slope of the z coordinate in view space + double Dz; + // current z coordinate in view space + double Zview; + + // Slope of each projected values on the span + double Dpv[VTK_VALUES_SIZE]; + // Current projected values + double PValues[VTK_VALUES_SIZE]; + + // Current values: Values=PValues/InvW + double Values[VTK_VALUES_SIZE]; +}; + + +// Pimpl (i.e. private implementation) idiom + +//typedef vtkstd::list<vtkPixelListEntry *> vtkPixelList; + +class vtkPixelListEntryBlock +{ +public: + vtkPixelListEntryBlock(vtkIdType size) + { + assert("pre: positive_size" && size>0); + this->Size=size; + this->Next=0; + this->Array=new vtkPixelListEntry[size]; + this->Last=this->Array+size-1; + // link each entry to the next one + vtkPixelListEntry *p; + vtkPixelListEntry *q; + p=this->Array; + q=p+1; + vtkIdType i=1; + while(i<size) + { + p->SetNext(q); + ++i; + p=q; + ++q; + } + p->SetNext(0); + } + ~vtkPixelListEntryBlock() + { + delete[] this->Array; + } + vtkIdType GetSize() { return this->Size; } + vtkPixelListEntryBlock *GetNext() { return this->Next; } + vtkPixelListEntry *GetFirst() { return this->Array; } + vtkPixelListEntry *GetLast() { return this->Last; } + void SetNext(vtkPixelListEntryBlock *other) { this->Next=other; } + +protected: + vtkIdType Size; + vtkPixelListEntryBlock *Next; + vtkPixelListEntry *Array; + vtkPixelListEntry *Last; +}; + +const vtkIdType VTK_PIXEL_BLOCK_SIZE=64; + +class vtkPixelListEntryMemory +{ +public: + vtkPixelListEntryMemory() + { + this->FirstBlock=new vtkPixelListEntryBlock(VTK_PIXEL_BLOCK_SIZE); + this->FirstFreeElement=this->FirstBlock->GetFirst(); + this->Size=VTK_PIXEL_BLOCK_SIZE; + } + ~vtkPixelListEntryMemory() + { + vtkPixelListEntryBlock *p=this->FirstBlock; + vtkPixelListEntryBlock *q; + while(p!=0) + { + q=p->GetNext(); + delete p; + p=q; + } + } + vtkPixelListEntry *AllocateEntry() + { + if(this->FirstFreeElement==0) + { + this->AllocateBlock(this->Size<<1); +// this->AllocateBlock(BLOCK_SIZE); + } + vtkPixelListEntry *result=this->FirstFreeElement; + this->FirstFreeElement=result->GetNext(); + assert("post: result_exists" && result!=0); + return result; + } + void FreeEntry(vtkPixelListEntry *e) + { + assert("pre: e_exists" && e!=0); + + // the following line works even if this->FirstFreeElement==0 + e->SetNext(this->FirstFreeElement); + this->FirstFreeElement=e; + } + void FreeSubList(vtkPixelListEntry *first, + vtkPixelListEntry *last) + { + assert("pre: first_exists" && first!=0); + assert("pre: last_exists" && last!=0); + // pre: first==last can be true + // the following line works even if this->FirstFreeElement==0 + last->SetNext(this->FirstFreeElement); + this->FirstFreeElement=first; + } +protected: + + void AllocateBlock(vtkIdType size) + { + assert("pre: positive_size" && size>0); + vtkPixelListEntryBlock *b=new vtkPixelListEntryBlock(size); + this->Size+=size; + // Update the block linked list: starts with the new block + b->SetNext(this->FirstBlock); + this->FirstBlock=b; + + // Update the free element linked list. + // It works even if this->FirstFreeElement==0 + b->GetLast()->SetNext(this->FirstFreeElement); + this->FirstFreeElement=b->GetFirst(); + } + + vtkPixelListEntryBlock *FirstBlock; + vtkPixelListEntry *FirstFreeElement; + vtkIdType Size; // overall size, in number of elements, not in bytes +}; + + +class vtkPixelList +{ +public: + vtkPixelList() + { + this->Size=0; + } + vtkPixelListEntry *GetFirst() + { + assert("pre: not_empty" && this->Size>0); + return this->First; + } + vtkIdType GetSize() { return this->Size; } + + void AddAndSort(vtkPixelListEntry *p) + { + assert("pre: p_exists" && p!=0); + if(this->Size==0) + { + p->SetPrevious(0); + p->SetNext(0); + this->First=p; + this->Last=p; + } + else + { + vtkPixelListEntry *it=this->Last; + int sorted=0; + double z=p->GetZview(); + while(!sorted && it!=0) + { +#ifdef BACK_TO_FRONT + sorted=it->GetZview()>=z; +#else + sorted=it->GetZview()<=z; +#endif + if(!sorted) + { + it=it->GetPrevious(); + } + } + if(it==0) // first element + { + p->SetPrevious(0); + p->SetNext(this->First); + // this->First==0 is handled by case size==0 + this->First->SetPrevious(p); + this->First=p; + } + else + { + if(it->GetNext()==0) // last element + { + it->SetNext(p); + p->SetPrevious(it); + p->SetNext(0); + this->Last=p; + } + else // general case + { + vtkPixelListEntry *q=it->GetNext(); + q->SetPrevious(p); + p->SetNext(q); + p->SetPrevious(it); + it->SetNext(p); + } + } + } + ++this->Size; + } + + // the return pointer is used by the memory manager. + void RemoveFirst(vtkPixelListEntryMemory *mm) + { + assert("pre: not_empty" && this->Size>0); + assert("pre: mm_exists" && mm!=0); + + vtkPixelListEntry *p=this->First; + if(this->Size>1) + { + this->First=p->GetNext(); + this->First->SetPrevious(0); + } + --this->Size; + mm->FreeEntry(p); + } + + // the return pointer on the first element is used by the memory manager. + void Clear(vtkPixelListEntryMemory *mm) + { + assert("pre: mm_exists" && mm!=0); + if(this->Size>0) + { + // it works even if first==last + mm->FreeSubList(this->First,this->Last); + this->Size=0; + } + } + +protected: + vtkIdType Size; + vtkPixelListEntry *First; + vtkPixelListEntry *Last; +}; + +//----------------------------------------------------------------------------- +// Store the pixel lists for all the frame. +class vtkPixelListFrame +{ +public: + typedef vtkstd::vector<vtkPixelList> VectorType; + + vtkPixelListFrame(int size) + :Vector(size) + { + } + + // Return width*height + vtkIdType GetSize() { return this->Vector.size(); } + + // Return the size of the list at pixel `i'. + vtkIdType GetListSize(int i) + { + assert("pre: valid_i" && i>=0 && i<this->GetSize()); + return this->Vector[i].GetSize(); + } + + // Add a value the pixel list of pixel `i' and sort it in the list. + void AddAndSort(int i, + vtkPixelListEntry *pixelEntry) + { + assert("pre: valid_i" && i>=0 && i<this->GetSize()); + assert("pre: pixelEntry_exists" && pixelEntry!=0); + + this->Vector[i].AddAndSort(pixelEntry); + } + + // Return the first entry for pixel `i'. + vtkPixelListEntry *GetFront(int i) + { + assert("pre: valid_i" && i>=0 && i<this->GetSize()); + assert("pre: not_empty" && this->GetListSize(i)>0); + return this->Vector[i].GetFirst(); + } + + // Remove the first entry for pixel `i'. + void PopFront(int i, + vtkPixelListEntryMemory *mm) + { + assert("pre: valid_i" && i>=0 && i<this->GetSize()); + assert("pre: not_empty" && this->GetListSize(i)>0); + assert("pre: mm_exists" && mm!=0); + this->Vector[i].RemoveFirst(mm); + } + + // Return the begin iterator for pixel `i'. + vtkPixelListEntry *GetFirst(int i) + { + assert("pre: valid_i" && i>=0 && i<this->GetSize()); + return this->Vector[i].GetFirst(); + } +#if 0 + // Return the end iterator for pixel `i'. + vtkstd::list<vtkPixelListEntry *>::iterator GetEndIterator(int i) + { + assert("pre: valid_i" && i>=0 && i<this->GetSize()); + return this->Vector[i].end(); + } +#endif + // Clear the list of each pixel of the frame. + void Clean(vtkPixelListEntryMemory *mm) + { + assert("pre: mm_exists" && mm!=0); + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(i<c) + { + vtkPixelList *l=&(Vector[i]); + l->Clear(mm); + ++i; + } + } + + // Destructor. + ~vtkPixelListFrame() + { +#if 0 + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(i<c) + { + vtkPixelList *l=&(Vector[i]); + while(!l->empty()) + { + delete l->front(); + l->pop_front(); + } + ++i; + } +#endif + } + + vtkPixelList *GetList(int i) + { + assert("pre: valid_i" && i>=0 && i<this->GetSize()); + return &(this->Vector[i]); + } + +protected: + VectorType Vector; + + // the STL specification claims that + // size() on a std: :list is permitted to be O(n)!!!! +// vtkstd::vector<vtkIdType> Sizes; + +// vtkstd::list<vtkPixelListEntry *>::iterator It; +// vtkstd::list<vtkPixelListEntry *>::iterator PreviousIt; +// vtkstd::list<vtkPixelListEntry *>::iterator ItEnd; +}; + +//----------------------------------------------------------------------------- +// Store a triangle face. Ids are in increasing order. Orientation does not +// matter for the algorithm. +class vtkFace +{ +public: + // Initialization from face ids in increasing order. + vtkFace(vtkIdType faceIds[3]) + { + assert("pre: ordered ids" && faceIds[0]<faceIds[1] + && faceIds[1]<faceIds[2]); + this->FaceIds[0]=faceIds[0]; + this->FaceIds[1]=faceIds[1]; + this->FaceIds[2]=faceIds[2]; + this->Count=0; + } + + // Return the 3 face ids. + vtkIdType *GetFaceIds() { return this->FaceIds; } + + // Are `this' and faceIds equal? + int IsEqual(vtkIdType faceIds[3]) + { + return (this->FaceIds[0]==faceIds[0])&&(this->FaceIds[1]==faceIds[1]) + &&(this->FaceIds[2]==faceIds[2]); + } + + void Ref() { ++this->Count; } + void Unref() + { + --this->Count; + if(this->Count==0) + { + delete this; + } + } + + int GetRendered() { return this->Rendered; } + void SetRendered(int value) { this->Rendered=value; } + +protected: + vtkIdType FaceIds[3]; + int Count; + int Rendered; + +private: + vtkFace(); // not implemented + vtkFace(const vtkFace &other); // not implemented + vtkFace &operator=(const vtkFace &other); // not implemented +}; + +//----------------------------------------------------------------------------- +// For each vertex, store the list of faces incident on this vertex. +// It is view independent. +class vtkUseSet +{ +public: + typedef vtkstd::vector<vtkstd::list<vtkFace *> *> VectorType; + VectorType Vector; + + vtkstd::list<vtkFace *> AllFaces; // to set up rendering to false. + + // Initialize with the number of vertices. + vtkUseSet(int size) + :Vector(size) + { + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(i<c) + { + this->Vector[i]=0; + ++i; + } + } + + // Destructor. + ~vtkUseSet() + { + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(i<c) + { + if(this->Vector[i]!=0) + { + while(!this->Vector[i]->empty()) + { + (*this->Vector[i]->begin())->Unref(); + this->Vector[i]->pop_front(); + } + delete this->Vector[i]; + } + ++i; + } + while(!this->AllFaces.empty()) + { + (*this->AllFaces.begin())->Unref(); + this->AllFaces.pop_front(); + } + } + + // For each vertex, clear the list of faces incident to it. + void Clear() + { + vtkIdType i=0; + vtkIdType c=this->Vector.size(); + while(i<c) + { + if(this->Vector[i]!=0) + { + while(!this->Vector[i]->empty()) + { + (*this->Vector[i]->begin())->Unref(); + this->Vector[i]->pop_front(); + } + delete this->Vector[i]; + this->Vector[i]=0; + } + ++i; + } + while(!this->AllFaces.empty()) + { + (*this->AllFaces.begin())->Unref(); + this->AllFaces.pop_front(); + } + } + + // Add face to each vertex only if the useset does not have the face yet. + void AddFace(vtkIdType faceIds[3]) + { + assert("pre: ordered ids" && faceIds[0]<faceIds[1] + && faceIds[1]<faceIds[2]); + if(!this->HasFace(faceIds)) + { + vtkFace *f=new vtkFace(faceIds); + this->AllFaces.push_back(f); + f->Ref(); + // All the vertices of this face need to be fed + int i=0; + while(i<3) + { + vtkstd::list<vtkFace *> *p=this->Vector[faceIds[i]]; + if(p==0) + { + p=new vtkstd::list<vtkFace *>; + this->Vector[faceIds[i]]=p; + } + p->push_back(f); + f->Ref(); + ++i; + } + } + } + + void SetNotRendered() + { + vtkstd::list<vtkFace *>::iterator it; + vtkstd::list<vtkFace *>::iterator end; + it=this->AllFaces.begin(); + end=this->AllFaces.end(); + while(it!=end) + { + (*it)->SetRendered(0); + ++it; + } + } +protected: + // Does the use set of vertex faceIds[0] have face faceIds? + int HasFace(vtkIdType faceIds[3]) + { + vtkstd::list<vtkFace *> *useSet=this->Vector[faceIds[0]]; + int result=0; + + if(useSet!=0) + { + this->It=(*useSet).begin(); + this->ItEnd=(*useSet).end(); + while(!result && this->It!=this->ItEnd) + { + result=(*this->It)->IsEqual(faceIds); + ++this->It; + } + } + return result; + } + + + // Used in HasFace() + vtkstd::list<vtkFace *>::iterator It; + vtkstd::list<vtkFace *>::iterator ItEnd; +}; + +// For each vertex, store its projection. It is view-dependent. +class vtkVertices +{ +public: + typedef vtkstd::vector<vtkVertexEntry> VectorType; + VectorType Vector; + + // Initialize with the number of vertices. + vtkVertices(int size) + :Vector(size) + { + } +}; + +//----------------------------------------------------------------------------- +// Implementation of the public class. + +vtkCxxRevisionMacro(vtkUnstructuredGridVolumeZSweepMapper, "$Revision: 1.3 $"); +vtkStandardNewMacro(vtkUnstructuredGridVolumeZSweepMapper); + +vtkCxxSetObjectMacro(vtkUnstructuredGridVolumeZSweepMapper, RayIntegrator, + vtkUnstructuredGridVolumeRayIntegrator); + + +//----------------------------------------------------------------------------- +// Description: +// Set MaxPixelListSize to 32. +vtkUnstructuredGridVolumeZSweepMapper::vtkUnstructuredGridVolumeZSweepMapper() +{ + this->MaxPixelListSize=64; // default value. + + this->ImageSampleDistance = 1.0; + this->MinimumImageSampleDistance = 1.0; + this->MaximumImageSampleDistance = 10.0; + this->AutoAdjustSampleDistances = 1; + + this->ImageMemorySize[0] = 0; + this->ImageMemorySize[1] = 0; + + this->Image = NULL; + this->RealRGBAImage=0; + + this->RenderTimeTable = NULL; + this->RenderVolumeTable = NULL; + this->RenderRendererTable = NULL; + this->RenderTableSize = 0; + this->RenderTableEntries = 0; + + this->ZBuffer = NULL; + this->ZBufferSize[0] = 0; + this->ZBufferSize[1] = 0; + this->ZBufferOrigin[0] = 0; + this->ZBufferOrigin[1] = 0; + + this->IntermixIntersectingGeometry = 1; + + this->ImageDisplayHelper = vtkRayCastImageDisplayHelper::New(); + + this->ScalarMode = VTK_SCALAR_MODE_DEFAULT; + this->ArrayName = new char[1]; + this->ArrayName[0] = '\0'; + this->ArrayId = -1; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; + + this->PixelListFrame=0; + + this->Cell=vtkGenericCell::New(); + + this->EventList=vtkPriorityQueue::New(); + + this->UseSet=0; + this->Vertices=0; + + this->PerspectiveTransform = vtkTransform::New(); + this->PerspectiveMatrix = vtkMatrix4x4::New(); + + this->SimpleEdge=new vtkSimpleScreenEdge; + this->DoubleEdge=new vtkDoubleScreenEdge; + + this->Span=new vtkSpan; + + this->RayIntegrator = NULL; + this->RealRayIntegrator = NULL; + + this->IntersectionLengths=vtkDoubleArray::New(); + this->IntersectionLengths->SetNumberOfValues(1); + this->NearIntersections=vtkDoubleArray::New(); + this->NearIntersections->SetNumberOfValues(1); + this->FarIntersections=vtkDoubleArray::New(); + this->FarIntersections->SetNumberOfValues(1); + + this->MemoryManager=0; +} + +//----------------------------------------------------------------------------- +vtkUnstructuredGridVolumeZSweepMapper::~vtkUnstructuredGridVolumeZSweepMapper() +{ + if(this->MemoryManager!=0) + { + delete this->MemoryManager; + } + if(this->PixelListFrame!=0) + { + delete this->PixelListFrame; + } + this->Cell->Delete(); + this->EventList->Delete(); + + this->ImageDisplayHelper->Delete(); + + delete[] this->ArrayName; + + if(this->UseSet!=0) + { + delete this->UseSet; + } + + if(this->Vertices!=0) + { + delete this->Vertices; + } + + this->PerspectiveTransform->Delete(); + this->PerspectiveMatrix->Delete(); + + delete this->SimpleEdge; + delete this->DoubleEdge; + delete this->Span; + + if ( this->Image ) + { + delete [] this->Image; + delete [] this->RealRGBAImage; + } + + if ( this->RenderTableSize ) + { + delete [] this->RenderTimeTable; + delete [] this->RenderVolumeTable; + delete [] this->RenderRendererTable; + } + + this->SetRayIntegrator(NULL); + if (this->RealRayIntegrator) + { + this->RealRayIntegrator->UnRegister(this); + } + + this->IntersectionLengths->Delete(); + this->NearIntersections->Delete(); + this->FarIntersections->Delete(); +} + +//----------------------------------------------------------------------------- +float vtkUnstructuredGridVolumeZSweepMapper::RetrieveRenderTime( + vtkRenderer *ren, + vtkVolume *vol ) +{ + int i; + + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + return this->RenderTimeTable[i]; + } + } + + return 0.0; +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::StoreRenderTime( + vtkRenderer *ren, + vtkVolume *vol, + float time ) +{ + int i; + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + this->RenderTimeTable[i] = time; + return; + } + } + + + // Need to increase size + if ( this->RenderTableEntries >= this->RenderTableSize ) + { + if ( this->RenderTableSize == 0 ) + { + this->RenderTableSize = 10; + } + else + { + this->RenderTableSize *= 2; + } + + float *oldTimePtr = this->RenderTimeTable; + vtkVolume **oldVolumePtr = this->RenderVolumeTable; + vtkRenderer **oldRendererPtr = this->RenderRendererTable; + + this->RenderTimeTable = new float [this->RenderTableSize]; + this->RenderVolumeTable = new vtkVolume *[this->RenderTableSize]; + this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize]; + + for (i = 0; i < this->RenderTableEntries; i++ ) + { + this->RenderTimeTable[i] = oldTimePtr[i]; + this->RenderVolumeTable[i] = oldVolumePtr[i]; + this->RenderRendererTable[i] = oldRendererPtr[i]; + } + + delete [] oldTimePtr; + delete [] oldVolumePtr; + delete [] oldRendererPtr; + } + + this->RenderTimeTable[this->RenderTableEntries] = time; + this->RenderVolumeTable[this->RenderTableEntries] = vol; + this->RenderRendererTable[this->RenderTableEntries] = ren; + + this->RenderTableEntries++; +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::SelectScalarArray(int arrayNum) +{ + if ( (this->ArrayId == arrayNum) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) + { + return; + } + this->Modified(); + + this->ArrayId = arrayNum; + this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID; +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::SelectScalarArray( + const char *arrayName) +{ + if ( !arrayName + || ( (strcmp(this->ArrayName, arrayName) == 0) + && (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) ) ) + { + return; + } + this->Modified(); + + delete[] this->ArrayName; + this->ArrayName = new char[strlen(arrayName) + 1]; + strcpy(this->ArrayName, arrayName); + this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME; +} + +//----------------------------------------------------------------------------- +// Return the method for obtaining scalar data. +const char *vtkUnstructuredGridVolumeZSweepMapper::GetScalarModeAsString(void) +{ + if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ) + { + return "UseCellData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA ) + { + return "UsePointData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA ) + { + return "UsePointFieldData"; + } + else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) + { + return "UseCellFieldData"; + } + else + { + return "Default"; + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::PrintSelf(ostream& os, + vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Max Pixel List Size: " << this->MaxPixelListSize << "\n"; + + os << indent << "ScalarMode: " << this->GetScalarModeAsString() << endl; + + os << indent << "Image Sample Distance: " + << this->ImageSampleDistance << "\n"; + os << indent << "Minimum Image Sample Distance: " + << this->MinimumImageSampleDistance << "\n"; + os << indent << "Maximum Image Sample Distance: " + << this->MaximumImageSampleDistance << "\n"; + os << indent << "Auto Adjust Sample Distances: " + << this->AutoAdjustSampleDistances << "\n"; + os << indent << "Intermix Intersecting Geometry: " + << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n"); + + // The PrintSelf test just search for words in the PrintSelf function + // We add here the internal variable we don't want to display: + // this->ImageViewportSize this->ImageOrigin this->ImageInUseSize + + os << indent << "ImageOrigin="<<ImageOrigin[0]<<", "<<ImageOrigin[1]<<"\n"; + os << indent << "ImageInUseSize="<<ImageInUseSize[0]<<", "<<ImageInUseSize[1]<<"\n"; + os << indent << "ImageMemorySize="<<ImageMemorySize[0]<<", "<<ImageMemorySize[1]<<"\n"; + + if (this->RayIntegrator) + { + os << indent << "RayIntegrator: " + << this->RayIntegrator->GetClassName() << endl; + } + else + { + os << indent << "RayIntegrator: (automatic)" << endl; + } +} + +//----------------------------------------------------------------------------- +// Description: +// Maximum size allowed for a pixel list. Default is 32. +// During the rendering, if a list of pixel is full, incremental compositing +// is performed. Even if it is a user setting, it is an advanced parameter. +// You have to understand how the algorithm works to change this value. +int vtkUnstructuredGridVolumeZSweepMapper::GetMaxPixelListSize() +{ + return this->MaxPixelListSize; +} + +//----------------------------------------------------------------------------- +// Description: +// Change the maximum size allowed for a pixel list. It is an advanced +// parameter. +void vtkUnstructuredGridVolumeZSweepMapper::SetMaxPixelListSize(int size) +{ + assert("pre: positive_size" && size>0); + this->MaxPixelListSize=size; +} + +//----------------------------------------------------------------------------- +#define ESTABLISH_INTEGRATOR(classname) \ + if ( !this->RealRayIntegrator \ + || (!this->RealRayIntegrator->IsA(#classname)) ) \ + { \ + if (this->RealRayIntegrator) this->RealRayIntegrator->UnRegister(this); \ + this->RealRayIntegrator = classname::New(); \ + this->RealRayIntegrator->Register(this); \ + this->RealRayIntegrator->Delete(); \ + } \ + +//----------------------------------------------------------------------------- +// Description: +// WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE +// DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS +// Render the volume +void vtkUnstructuredGridVolumeZSweepMapper::Render(vtkRenderer *ren, + vtkVolume *vol) +{ + vtkDebugMacro(<<"Render"); + + // Check for input + if(this->GetInput()==0) + { + vtkErrorMacro(<< "No Input!"); + return; + } + + this->Scalars = this->GetScalars(this->GetInput(), this->ScalarMode, + this->ArrayAccessMode, + this->ArrayId, this->ArrayName, + this->CellScalars); + + if(this->Scalars==0) + { + vtkErrorMacro("Can't use the ZSweep mapper without scalars!"); + return; + } + + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + + // Check to make sure we have an appropriate integrator. + if (this->RayIntegrator) + { + if (this->RealRayIntegrator != this->RayIntegrator) + { + if (this->RealRayIntegrator) + { + this->RealRayIntegrator->UnRegister(this); + } + this->RealRayIntegrator = this->RayIntegrator; + this->RealRayIntegrator->Register(this); + } + } + else + { + if (this->CellScalars) + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridHomogeneousRayIntegrator); + } + else + { + if (vol->GetProperty()->GetIndependentComponents()) + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridPreIntegration); + } + else + { + ESTABLISH_INTEGRATOR(vtkUnstructuredGridPartialPreIntegration); + } + } + } + // Start timing now. We didn't want to capture the update of the + // input data in the times + this->Timer->StartTimer(); + + int oldImageMemorySize[2]; + oldImageMemorySize[0] = this->ImageMemorySize[0]; + oldImageMemorySize[1] = this->ImageMemorySize[1]; + + // If we are automatically adjusting the size to achieve a desired frame + // rate, then do that adjustment here. Base the new image sample distance + // on the previous one and the previous render time. Don't let + // the adjusted image sample distance be less than the minimum image sample + // distance or more than the maximum image sample distance. + float oldImageSampleDistance = this->ImageSampleDistance; + if ( this->AutoAdjustSampleDistances ) + { + float oldTime = this->RetrieveRenderTime( ren, vol ); + float newTime = vol->GetAllocatedRenderTime(); + this->ImageSampleDistance *= sqrt(oldTime / newTime); + this->ImageSampleDistance = + (this->ImageSampleDistance>this->MaximumImageSampleDistance)? + (this->MaximumImageSampleDistance):(this->ImageSampleDistance); + this->ImageSampleDistance = + (this->ImageSampleDistance<this->MinimumImageSampleDistance)? + (this->MinimumImageSampleDistance):(this->ImageSampleDistance); + } + + // The full image fills the viewport. First, compute the actual viewport + // size, then divide by the ImageSampleDistance to find the full image + // size in pixels + int width, height; + ren->GetTiledSize(&width, &height); + this->ImageViewportSize[0] = + static_cast<int>(width/this->ImageSampleDistance); + this->ImageViewportSize[1] = + static_cast<int>(height/this->ImageSampleDistance); + + this->ImageInUseSize[0] = this->ImageViewportSize[0]; + this->ImageInUseSize[1] = this->ImageViewportSize[1]; + this->ImageOrigin[0] = 0; + this->ImageOrigin[1] = 0; + + // What is a power of 2 size big enough to fit this image? + this->ImageMemorySize[0] = 32; + this->ImageMemorySize[1] = 32; + while ( this->ImageMemorySize[0] < this->ImageInUseSize[0] ) + { + this->ImageMemorySize[0] *= 2; + } + while ( this->ImageMemorySize[1] < this->ImageInUseSize[1] ) + { + this->ImageMemorySize[1] *= 2; + } + + // If the old image size is much too big (more than twice in + // either direction) then set the old width to 0 which will + // cause the image to be recreated + if ( oldImageMemorySize[0] > 2*this->ImageMemorySize[0] || + oldImageMemorySize[1] > 2*this->ImageMemorySize[1] ) + { + oldImageMemorySize[0] = 0; + } + + // If the old image is big enough (but not too big - we handled + // that above) then we'll bump up our required size to the + // previous one. This will keep us from thrashing. + if ( oldImageMemorySize[0] >= this->ImageMemorySize[0] && + oldImageMemorySize[1] >= this->ImageMemorySize[1] ) + { + this->ImageMemorySize[0] = oldImageMemorySize[0]; + this->ImageMemorySize[1] = oldImageMemorySize[1]; + } + + int bufferSize=this->ImageMemorySize[0] * this->ImageMemorySize[1] * 4; + + // Do we already have a texture big enough? If not, create a new one and + // clear it. + if ( !this->Image || + this->ImageMemorySize[0] > oldImageMemorySize[0] || + this->ImageMemorySize[1] > oldImageMemorySize[1] ) + { + // If there is an image there must be row bounds + if ( this->Image ) + { + delete [] this->Image; + delete [] this->RealRGBAImage; + } + this->Image = new unsigned char[bufferSize]; + this->RealRGBAImage=new float[bufferSize]; + } + + // We have to clear the image, each time: + memset(this->Image,0,bufferSize); + + vtkIdType j=0; + while(j<bufferSize) + { + this->RealRGBAImage[j]=0; + this->RealRGBAImage[j+1]=0; + this->RealRGBAImage[j+2]=0; + this->RealRGBAImage[j+3]=0; + j+=4; + } + + // Capture the zbuffer if necessary + if ( this->IntermixIntersectingGeometry && + ren->GetNumberOfPropsRendered() ) + { + int x1, x2, y1, y2; + double *viewport = ren->GetViewport(); + int *renWinSize = ren->GetRenderWindow()->GetSize(); + + // turn this->ImageOrigin into (x1,y1) in window (not viewport!) + // coordinates. + x1 = static_cast<int> ( + viewport[0] * static_cast<float>(renWinSize[0]) + + static_cast<float>(this->ImageOrigin[0]) * this->ImageSampleDistance ); + y1 = static_cast<int> ( + viewport[1] * static_cast<float>(renWinSize[1]) + + static_cast<float>(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // compute z buffer size + this->ZBufferSize[0] = static_cast<int>( + static_cast<float>(this->ImageInUseSize[0]) * this->ImageSampleDistance); + this->ZBufferSize[1] = static_cast<int>( + static_cast<float>(this->ImageInUseSize[1]) * this->ImageSampleDistance); + + // Use the size to compute (x2,y2) in window coordinates + x2 = x1 + this->ZBufferSize[0] - 1; + y2 = y1 + this->ZBufferSize[1] - 1; + + // This is the z buffer origin (in viewport coordinates) + this->ZBufferOrigin[0] = static_cast<int>( + static_cast<float>(this->ImageOrigin[0]) * this->ImageSampleDistance); + this->ZBufferOrigin[1] = static_cast<int>( + static_cast<float>(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // Capture the z buffer + this->ZBuffer = ren->GetRenderWindow()->GetZbufferData(x1,y1,x2,y2); + } + + this->RealRayIntegrator->Initialize(vol, this->Scalars); + + // Here is the Zsweep algorithm: + + // 1. For each vertex, find the list of incident faces (the "use set") (3.1) + // In the original paper, it deals with incident cells but the chapter about + // the parallel version in the dissertation deals with faces, which makes + // more sense. Hence, there is no need for the sparsification step (3.5.1) + // It is view-independent, so it can be reused for the next call to Render() + // if the dataset did not change. + vtkDebugMacro(<<"BuildUseSets: start"); + this->BuildUseSets(); + vtkDebugMacro(<<"BuildUseSets: done"); + + // 2. Sort the vertices by z-coordinates (view-dependent) in view space. + // For each vertex, compute its camera coordinates and sort it + // by z in an heap. The heap is called the "event list". + // The heap stores the Id of the vertices. + // It is view-dependent. + vtkDebugMacro(<<"ProjectAndSortVertices: start"); + this->ProjectAndSortVertices(ren,vol); + vtkDebugMacro(<<"ProjectAndSortVertices: done"); + + // 3. Create an empty "pixel list" (two way linked list) for each pixel of + // the screen. + vtkDebugMacro(<<"CreateAndCleanPixelList: start"); + this->CreateAndCleanPixelList(); + vtkDebugMacro(<<"CreateAndCleanPixelList: done"); + + // 4. Main loop + // (section 2 paragraph 11) + vtkDebugMacro(<<"MainLoop: start"); + this->MainLoop(ren->GetRenderWindow()); + vtkDebugMacro(<<"MainLoop: done"); + + // The algorithm is done: send to result to the final image. + if ( !ren->GetRenderWindow()->GetAbortRender() ) + { + float depth; + if ( this->IntermixIntersectingGeometry ) + { + depth = this->GetMinimumBoundsDepth( ren, vol ); + } + else + { + depth = -1; + } + + // copy the double image into the unsigned char image: + + j=0; + while(j<bufferSize) + { + float alpha=this->RealRGBAImage[j+3]; + if(alpha!=0) + { + this->Image[j]=this->ColorComponentRealToByte(this->RealRGBAImage[j]/alpha); + this->Image[j+1]=this->ColorComponentRealToByte(this->RealRGBAImage[j+1]/alpha); + this->Image[j+2]=this->ColorComponentRealToByte(this->RealRGBAImage[j+2]/alpha); + this->Image[j+3]=this->ColorComponentRealToByte(alpha); + } + else + { + this->Image[j]=0; + this->Image[j+1]=0; + this->Image[j+2]=0; + this->Image[j+3]=0; + } + j+=4; + } + this->ImageDisplayHelper-> + RenderTexture( vol, ren, + this->ImageMemorySize, + this->ImageViewportSize, + this->ImageInUseSize, + this->ImageOrigin, + depth, + this->Image ); + + this->Timer->StopTimer(); + this->TimeToDraw = this->Timer->GetElapsedTime(); + this->StoreRenderTime( ren, vol, this->TimeToDraw ); + } + else + { + this->ImageSampleDistance = oldImageSampleDistance; + } + + if ( this->ZBuffer ) + { + delete [] this->ZBuffer; + this->ZBuffer = NULL; + } + + this->UpdateProgress(1.0); +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::AllocateUseSet(vtkIdType size) +{ + if(this->UseSet!=0) + { + if(size>static_cast<vtkIdType>(this->UseSet->Vector.size())) + { + delete this->UseSet; + this->UseSet=new vtkUseSet(size); + } + else + { + this->UseSet->Clear(); + } + } + else + { + this->UseSet=new vtkUseSet(size); + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::AllocateVertices(vtkIdType size) +{ + if(this->Vertices!=0) + { + if(size>static_cast<vtkIdType>(this->Vertices->Vector.size())) + { + delete this->Vertices; + this->Vertices=new vtkVertices(size); + } + } + else + { + this->Vertices=new vtkVertices(size); + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::BuildUseSets() +{ + int needsUpdate = 0; + + // If we have never created the list, we need updating + if (this->UseSet==0 ) + { + needsUpdate = 1; + } + + // If the data has changed in some way then we need to update + vtkUnstructuredGrid *input = this->GetInput(); + if ( input->GetMTime() > this->SavedTriangleListMTime.GetMTime() ) + { + needsUpdate = 1; + } + + + // If we don't need updating, return + if ( !needsUpdate ) + { + return; + } + + vtkIdType numberOfCells=input->GetNumberOfCells(); + vtkIdType numberOfPoints=input->GetNumberOfPoints(); + + // init the use set of each vertex + this->AllocateUseSet(numberOfPoints); + + // for each cell + vtkIdType cellIdx=0; + while(cellIdx<numberOfCells) + { + input->GetCell(cellIdx,this->Cell); + + vtkIdType faces=this->Cell->GetNumberOfFaces(); + vtkIdType faceidx=0; + vtkCell *face; + vtkIdType faceIds[3]; + vtkIdType orderedFaceIds[3]; + // for each face + while(faceidx<faces) + { + face=this->Cell->GetFace(faceidx); + faceIds[0]=face->GetPointId(0); + faceIds[1]=face->GetPointId(1); + faceIds[2]=face->GetPointId(2); + this->ReorderTriangle(faceIds,orderedFaceIds); + + // Add face only if it is not already in the useset. + this->UseSet->AddFace(orderedFaceIds); + ++faceidx; + } + ++cellIdx; + } + this->SavedTriangleListMTime.Modified(); +} + +//----------------------------------------------------------------------------- +// Description: +// Reorder vertices `v' in increasing order in `w'. Orientation does not +// matter for the algorithm. +void vtkUnstructuredGridVolumeZSweepMapper::ReorderTriangle(vtkIdType v[3], + vtkIdType w[3]) +{ + if(v[0]>v[1]) + { + if(v[1]>v[2]) + { + // v[2] is the min + w[0]=v[2]; + w[1]=v[0]; + w[2]=v[1]; + } + else + { + // v[1] is the min + w[0]=v[1]; + w[1]=v[2]; + w[2]=v[0]; + } + } + else + { + if(v[0]>v[2]) + { + // v[2] is the min + w[0]=v[2]; + w[1]=v[0]; + w[2]=v[1]; + } + else + { + // v[0] is the min + w[0]=v[0]; + w[1]=v[1]; + w[2]=v[2]; + } + } + // At this point the triangle start with the min id and the + // order did not change + // Now, ensure that the two last id are in increasing order + if(w[1]>w[2]) + { + vtkIdType tmp=w[1]; + w[1]=w[2]; + w[2]=tmp; + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::ProjectAndSortVertices( + vtkRenderer *ren, + vtkVolume *vol) +{ + assert("pre: empty list" && this->EventList->GetNumberOfItems()==0); + + vtkUnstructuredGrid *input = this->GetInput(); + vtkIdType numberOfPoints=input->GetNumberOfPoints(); + + vtkIdType pointId=0; + vtkVertexEntry *vertex=0; + // Pre-computation for the projection. + + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + // Get the view matrix in two steps - there is a one step method in camera + // but it turns off stereo so we do not want to use that one + vtkCamera *cam = ren->GetActiveCamera(); + this->PerspectiveTransform->Identity(); + this->PerspectiveTransform->Concatenate( + cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], 0.0, 1.0 )); + this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + this->PerspectiveTransform->Concatenate(vol->GetMatrix()); + this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix()); + + this->AllocateVertices(numberOfPoints); + + while(pointId<numberOfPoints) + { + vertex=&(this->Vertices->Vector[pointId]); + + // Projection + // + double inPoint[4]; + input->GetPoint(pointId,inPoint); + inPoint[3] = 1.0; + + double outPoint[4]; + this->PerspectiveMatrix->MultiplyPoint( inPoint, outPoint ); + assert("outPoint[3]" && outPoint[3]!=0.0); + + double invW=1/outPoint[3]; + double zView = outPoint[2]*invW; + + int xScreen=static_cast<int>((outPoint[0]*invW+1)*0.5*this->ImageViewportSize[0]-this->ImageOrigin[0]); + int yScreen=static_cast<int>((outPoint[1]*invW+1)*0.5*this->ImageViewportSize[1]-this->ImageOrigin[1]); + + double outWorldPoint[4]; + + vol->GetMatrix()->MultiplyPoint( inPoint, outWorldPoint ); + + assert("check: vol no projection" && outWorldPoint[3]==1); + + double scalar; + if(this->CellScalars) // cell attribute + { + assert(0); + // scalar=this->Scalars->GetComponent(cellIdx,0); + scalar=0; + } + else // point attribute + { + scalar=this->Scalars->GetComponent(pointId,0); + } + + vertex->Set(xScreen,yScreen,outWorldPoint[0]/outWorldPoint[3], + outWorldPoint[1]/outWorldPoint[3], + outWorldPoint[2]/outWorldPoint[3],zView,scalar,invW); + + // Sorting + // + // we store -z because the top of the priority list is the + // smallest value +#ifdef BACK_TO_FRONT + this->EventList->Insert(-zView,pointId); +#else + this->EventList->Insert(zView,pointId); +#endif + ++pointId; + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::CreateAndCleanPixelList() +{ + // paper: a "pixel list" is a double linked list. We put that in a queue. + vtkIdType size=this->ImageInUseSize[0]*this->ImageInUseSize[1]; + if(this->PixelListFrame!=0) + { + if(this->PixelListFrame->GetSize()<size) + { + delete this->PixelListFrame; + this->PixelListFrame=0; + } + } + + if(this->PixelListFrame==0) + { + this->PixelListFrame=new vtkPixelListFrame(size); + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::MainLoop(vtkRenderWindow *renWin) +{ + double previousZTarget=0.0; + double zTarget; + vtkIdType vertex; + +// used to know if the next vertex is on the same plane + double currentZ; // than the previous one. If so, the z-target has to be + // updated (without calling the compositing function) + if(this->EventList->GetNumberOfItems()==0) + { + return; // we are done. + } + + // initialize the "previous z-target" to the z-coordinate of the first + // vertex. + vertex=this->EventList->Peek(0,previousZTarget); + +#ifdef BACK_TO_FRONT + previousZTarget=-previousZTarget; // because the EventList store -z +#endif + + // (section 2 paragraph 11) + // initialize the "z-target" with the maximum z-coordinate of the adjacent + // vertices to the first vertex. The adjacent vertices can be found + // indirectly by using the "use set" of the first vertex (cells), and + // by taking the vertices of all those cells. + // + zTarget=previousZTarget; + vtkstd::list<vtkFace *>::iterator it; + vtkstd::list<vtkFace *>::iterator itEnd; + +// this->MaxRecordedPixelListSize=0; + this->MaxPixelListSizeReached=0; + this->XBounds[0]=this->ImageInUseSize[0]; + this->XBounds[1]=0; + this->YBounds[0]=this->ImageInUseSize[1]; + this->YBounds[1]=0; + + vtkIdType progressCount=0; + vtkIdType sum=this->EventList->GetNumberOfItems(); + + if(this->MemoryManager==0) + { + this->MemoryManager=new vtkPixelListEntryMemory; + } + + this->UseSet->SetNotRendered(); + + int aborded=0; + // for each vertex of the "event list" + while(this->EventList->GetNumberOfItems()>0) + { + this->UpdateProgress(static_cast<double>(progressCount)/sum); + + aborded=renWin->CheckAbortStatus(); + if(aborded) + { + break; + } + ++progressCount; + // the z coordinate of the current vertex defines the "sweep plane". + vertex=this->EventList->Pop(0,currentZ); + + if(this->UseSet->Vector[vertex]!=0) + { // otherwise the vertex is not useful, basically this is the + // end we reached the last ztarget + +#ifdef BACK_TO_FRONT + currentZ=-currentZ; // because the EventList store -z +#endif + + if(previousZTarget==currentZ) + { + // the new vertex is on the same sweep plane than the previous vertex + // that defined a z target + // => the z target has to be updated accordingly + // This is also the case for the first vertex. + it=this->UseSet->Vector[vertex]->begin(); + itEnd=this->UseSet->Vector[vertex]->end(); + + // for each face incident with the vertex + while(it!=itEnd) + { + vtkFace *face=(*it); + // for each point of the face, get the closest z + vtkIdType *vids=face->GetFaceIds(); + vtkIdType i=0; + while(i<3) + { + double z=this->Vertices->Vector[vids[i]].GetZview(); +#ifdef BACK_TO_FRONT + if(z<zTarget) +#else + if(z>zTarget) +#endif + { + zTarget=z; + } + ++i; + } + ++it; + } + } + + // Time to call the composite function? +#ifdef BACK_TO_FRONT + if(currentZ<zTarget) +#else + if(currentZ>zTarget) +#endif + { + this->CompositeFunction(zTarget); + + // Update the zTarget + previousZTarget=zTarget; + + it=this->UseSet->Vector[vertex]->begin(); + itEnd=this->UseSet->Vector[vertex]->end(); + // for each cell incident with the vertex + while(it!=itEnd) + { + vtkFace *face=(*it); + // for each point of the face, get the closest z + vtkIdType *vids=face->GetFaceIds(); + vtkIdType i=0; + while(i<3) + { + double z=this->Vertices->Vector[vids[i]].GetZview(); +#ifdef BACK_TO_FRONT + if(z<zTarget) +#else + if(z>zTarget) +#endif + { + zTarget=z; + } + ++i; + } + ++it; + } + } + else + { + if(this->MaxPixelListSizeReached) + { + this->CompositeFunction(currentZ); + // We do not update the zTarget in this case. + } + } + + // use the "use set" (cells) of the vertex to get the cells that are + // incident on the vertex, and that have this vertex as + // minimal z-coordinate, + + it=this->UseSet->Vector[vertex]->begin(); + itEnd=this->UseSet->Vector[vertex]->end(); + + while(it!=itEnd) + { + vtkFace *face=(*it); + if(!face->GetRendered()) + { + vtkIdType *vids=face->GetFaceIds(); + this->RasterizeFace(vids); + face->SetRendered(1); + } +#if 0 // face search + // for each point of the face, get the closest z + vtkIdType *vids=face->GetFaceIds(); + vtkIdType minVertex=vids[0]; + double farestZ=this->Vertices->Vector[vids[0]].GetZview(); + + vtkIdType i=1; + while(i<3) + { + double z=this->Vertices->Vector[vids[i]].GetZview(); +#ifdef BACK_TO_FRONT + if(z>farestZ) +#else + if(z<farestZ) +#endif + { + farestZ=z; + minVertex=vids[i]; + } + ++i; + } + if(minVertex==vertex) + { +// if(face->GetRendered()) +// { +// cout<<"FACE ALREADY RENDERED!!!!"<<endl; +// } + this->RasterizeFace(vids); +// face->SetRendered(1); + } +#endif // face search + ++it; + } + } // if useset of vertex is not null + } // while(eventList->GetNumberOfItems()>0) + + if(!aborded) + { + // Here a final compositing + vtkDebugMacro(<<"Flush Compositing"); +// this->SavePixelListFrame(); +#ifdef BACK_TO_FRONT + this->CompositeFunction(-2); +#else + this->CompositeFunction(2); +#endif + } + else + { + this->EventList->Reset(); + } + this->PixelListFrame->Clean(this->MemoryManager); +// vtkDebugMacro(<<"MaxRecordedPixelListSize="<<this->MaxRecordedPixelListSize); + + assert("post: empty_list" && this->EventList->GetNumberOfItems()==0); +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::SavePixelListFrame() +{ + vtkPolyData *dataset=vtkPolyData::New(); + + vtkIdType height=this->ImageInUseSize[1]; + vtkIdType width=this->ImageInUseSize[0]; + vtkPixelListEntry *current; + vtkIdType i; + + vtkPoints *pts=vtkPoints::New(); + pts->SetDataTypeToDouble(); + + vtkDoubleArray *dataArray=vtkDoubleArray::New(); + vtkCellArray *vertices=vtkCellArray::New(); + vtkIdType pointId=0; + +// height=151; +// width=151; + + vtkIdType y=0; //150; + while(y<height) + { + vtkIdType x=0; //150; + while(x<width) + { + i=y*this->ImageInUseSize[0]+x; + current=this->PixelListFrame->GetFirst(i); + while(current!=0) + { + double *values=current->GetValues(); + + double point[3]; + point[0]=x; + point[1]=y; + point[2]=values[2]; // zWorld + + pts->InsertNextPoint(point); + dataArray->InsertNextValue(values[3]); + vertices->InsertNextCell(1,&pointId); + current=current->GetNext(); + ++pointId; + } + ++x; + } + ++y; + } + dataset->SetPoints(pts); + pts->Delete(); + dataset->SetVerts(vertices); + vertices->Delete(); + dataset->GetPointData()->SetScalars(dataArray); + dataArray->Delete(); + + vtkXMLPolyDataWriter *writer=vtkXMLPolyDataWriter::New(); + writer->SetFileName("pixellistframe.vtp"); + writer->SetInput(dataset); + writer->SetIdTypeToInt32(); + dataset->Delete(); + writer->Write(); + writer->Delete(); +} + +//----------------------------------------------------------------------------- +// Description: +// Perform a scan conversion of a triangle, interpolating z and the scalar. +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeFace(vtkIdType faceIds[3]) +{ + // The triangle is splitted by an horizontal line passing through the + // second vertex v1 (y-order) + // Hence, on one side there one edge (v0v2), on the other side there are two + // edges (v0v1 and v1v2). + + vtkVertexEntry *v0=&(this->Vertices->Vector[faceIds[0]]); + vtkVertexEntry *v1=&(this->Vertices->Vector[faceIds[1]]); + vtkVertexEntry *v2=&(this->Vertices->Vector[faceIds[2]]); + + this->RasterizeTriangle(v0,v1,v2); +} + +//----------------------------------------------------------------------------- +// Description: +// Perform a scan conversion of a triangle, interpolating z and the scalar. +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeTriangle( + vtkVertexEntry *ve0, + vtkVertexEntry *ve1, + vtkVertexEntry *ve2 + ) +{ + assert("pre: ve0_exists" && ve0!=0); + assert("pre: ve1_exists" && ve1!=0); + assert("pre: ve2_exists" && ve2!=0); + + vtkVertexEntry *v0=ve0; + vtkVertexEntry *v1=ve1; + vtkVertexEntry *v2=ve2; + + // The triangle is splitted by an horizontal line passing through the + // second vertex v1 (y-order) + // Hence, on one side there one edge (v0v2), on the other side there are two + // edges (v0v1 and v1v2). + + // Order vertices by y screen. + + vtkVertexEntry *tmp; + + if(v0->GetScreenY()>v1->GetScreenY()) + { + tmp=v0; + v0=v1; + v1=tmp; + } + if(v0->GetScreenY()>v2->GetScreenY()) + { + tmp=v1; + v1=v0; + v0=v2; + v2=tmp; + } + else + { + if(v1->GetScreenY()>v2->GetScreenY()) + { + tmp=v1; + v1=v2; + v2=tmp; + } + } + + if(v0->GetScreenY()<this->YBounds[0]) + { + if(v0->GetScreenY()>=0) + { + this->YBounds[0]=v0->GetScreenY(); + } + else + { + this->YBounds[0]=0; + } + } + if(v2->GetScreenY()>this->YBounds[1]) + { + if(v2->GetScreenY()<this->ImageInUseSize[1]) + { + this->YBounds[1]=v2->GetScreenY(); + } + else + { + this->YBounds[1]=this->ImageInUseSize[1]-1; + } + } + + int x=v0->GetScreenX(); + + if(x<this->XBounds[0]) + { + if(x>=0) + { + this->XBounds[0]=x; + } + else + { + this->XBounds[0]=0; + } + } + else + { + if(x>this->XBounds[1]) + { + if(x<this->ImageInUseSize[0]) + { + this->XBounds[1]=x; + } + else + { + this->XBounds[1]=this->ImageInUseSize[0]-1; + } + } + } + x=v1->GetScreenX(); + + if(x<this->XBounds[0]) + { + if(x>=0) + { + this->XBounds[0]=x; + } + else + { + this->XBounds[0]=0; + } + } + else + { + if(x>this->XBounds[1]) + { + if(x<this->ImageInUseSize[0]) + { + this->XBounds[1]=x; + } + else + { + this->XBounds[1]=this->ImageInUseSize[0]-1; + } + } + } + + x=v2->GetScreenX(); + + if(x<this->XBounds[0]) + { + if(x>=0) + { + this->XBounds[0]=x; + } + else + { + this->XBounds[0]=0; + } + } + else + { + if(x>this->XBounds[1]) + { + if(x<this->ImageInUseSize[0]) + { + this->XBounds[1]=x; + } + else + { + this->XBounds[1]=this->ImageInUseSize[0]-1; + } + } + } + + int dy20=v2->GetScreenY()-v0->GetScreenY(); + int dx10=v1->GetScreenX()-v0->GetScreenX(); + int dx20=v2->GetScreenX()-v0->GetScreenX(); + int dy10=v1->GetScreenY()-v0->GetScreenY(); + + int det=dy20*dx10-dx20*dy10; + + vtkScreenEdge *leftEdge=0; + vtkScreenEdge *rightEdge=0; + + if(det==0) //v0v1v2 aligned or v0=v1=v2 + { + // easy case: v0=v1=v2 render the 3 points + if(v0->GetScreenX()==v1->GetScreenX() && v0->GetScreenX()==v2->GetScreenX() + && v0->GetScreenY()==v1->GetScreenY() + && v0->GetScreenY()==v2->GetScreenY()) + { + x=v0->GetScreenX(); + int y=v0->GetScreenY(); + if(x>=0 && x<this->ImageInUseSize[0] && y>=0 && + y<this->ImageInUseSize[1]) + { + vtkIdType i=y*this->ImageInUseSize[0]+x; + // Write the pixel + vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry(); + p0->Init(v0->GetValues(),v0->GetZview()); + this->PixelListFrame->AddAndSort(i,p0); + + vtkPixelListEntry *p1=this->MemoryManager->AllocateEntry(); + p1->Init(v1->GetValues(),v1->GetZview()); + this->PixelListFrame->AddAndSort(i,p1); + + vtkPixelListEntry *p2=this->MemoryManager->AllocateEntry(); + p2->Init(v2->GetValues(),v2->GetZview()); + this->PixelListFrame->AddAndSort(i,p2); + +// if(this->PixelListFrame->GetListSize(i)>this->MaxRecordedPixelListSize) +// { +// this->MaxRecordedPixelListSize=this->PixelListFrame->GetListSize(i); +// } + + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(i)> + this->MaxPixelListSize; + } + } + } + else // line + { + this->RasterizeLine(v0,v1); + this->RasterizeLine(v1,v2); + this->RasterizeLine(v0,v2); + } + return; + } + else + { + if(det>0) //v0v1 on right + { + this->DoubleEdge->Init(v0,v1,v2,dx10,dy10,1); // true=on right + rightEdge=this->DoubleEdge; + this->SimpleEdge->Init(v0,v2,dx20,dy20,0); + leftEdge=this->SimpleEdge; + } + else + { + // v0v1 on left + this->DoubleEdge->Init(v0,v1,v2,dx10,dy10,0); // true=on right + leftEdge=this->DoubleEdge; + this->SimpleEdge->Init(v0,v2,dx20,dy20,1); + rightEdge=this->SimpleEdge; + } + } + + int y=v0->GetScreenY(); + int y1=v1->GetScreenY(); + int y2=v2->GetScreenY(); + + int skipped=0; + + if(y1>=0) // clipping + { + + if(y1>=this->ImageInUseSize[1]) // clipping + { + y1=this->ImageInUseSize[1]-1; + } + + while(y<=y1) + { + if(y>=0 && y<this->ImageInUseSize[1]) // clipping + { + this->RasterizeSpan(y,leftEdge,rightEdge); + } + ++y; + if(y<=y1) + { + leftEdge->NextLine(y); + rightEdge->NextLine(y); + } + } + } + else + { + leftEdge->SkipLines(y1-y,y1); + rightEdge->SkipLines(y1-y,y1); + y=y1; + skipped=1; + } + + if(y<this->ImageInUseSize[1]) // clipping + { + leftEdge->OnBottom(skipped,y); + rightEdge->OnBottom(skipped,y); + + if(y2>=this->ImageInUseSize[1]) // clipping + { + y2=this->ImageInUseSize[1]-1; + } + + while(y<=y2) + { + if(y>=0) // clipping, needed in case of no top + { + this->RasterizeSpan(y,leftEdge,rightEdge); + } + ++y; + leftEdge->NextLine(y); + rightEdge->NextLine(y); + } + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeSpan(int y, + vtkScreenEdge *left, + vtkScreenEdge *right) +{ + assert("pre: left_exists" && left!=0); + assert("pre: right_exists" && right!=0); + + vtkIdType i=y*this->ImageInUseSize[0]; + + this->Span->Init(left->GetX(), + left->GetInvW(), + left->GetPValues(), + left->GetZview(), + right->GetX(), + right->GetInvW(), + right->GetPValues(), + right->GetZview()); + + while(!this->Span->IsAtEnd()) + { + int x=this->Span->GetX(); + if(x>=0 && x<this->ImageInUseSize[0]) // clipping + { + vtkIdType j=i+x; + // Write the pixel + vtkPixelListEntry *p=this->MemoryManager->AllocateEntry(); + p->Init(this->Span->GetValues(),this->Span->GetZview()); + this->PixelListFrame->AddAndSort(j,p); + + +// if(this->PixelListFrame->GetListSize(j)>this->MaxRecordedPixelListSize) +// { +// this->MaxRecordedPixelListSize=this->PixelListFrame->GetListSize(j); +// } + + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)> + this->MaxPixelListSize; + } + } + this->Span->NextPixel(); + } +} + +enum +{ + VTK_LINE_CONSTANT=0, + VTK_LINE_BRESENHAM, + VTK_LINE_DIAGONAL +}; + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::RasterizeLine(vtkVertexEntry *v0, + vtkVertexEntry *v1) +{ + assert("pre: v0_exists" && v0!=0); + assert("pre: v1_exists" && v1!=0); + assert("pre: y_ordered" && v0->GetScreenY()<=v1->GetScreenY()); + + int lineCase; + int xIncrement; // if true increment x, if false increment y + int dx; + int dy; + int xSign; + + // initialization is not useful, it is just to remove compiler warnings + int dx2=0; + int dy2=0; + int e=0; + + double values[VTK_VALUES_SIZE]; + double pValues[VTK_VALUES_SIZE]; + + double dPv[VTK_VALUES_SIZE]; + double dInvW; + double dZ; + + double zView; + double invW; + + int i; + + int x=v0->GetScreenX(); + int y=v0->GetScreenY(); + + // 1. Find the case + dx=v1->GetScreenX()-v0->GetScreenX(); + if(dx<0) + { + dx=-dx; + xSign=-1; + } + else + { + xSign=1; + } + dy=v1->GetScreenY()-v0->GetScreenY(); + xIncrement=dx>dy; + if(xIncrement) + { + if(dy==0) + { + lineCase=VTK_LINE_CONSTANT; + } + else + { + lineCase=VTK_LINE_BRESENHAM; + dx2=dx<<1; + dy2=dy<<1; + e=dx; + } + + double invDx=1.0/dx; + i=0; + invW=v0->GetInvW(); + double invW1=v1->GetInvW(); + double *val0=v0->GetValues(); + double *val1=v1->GetValues(); + while(i<VTK_VALUES_SIZE) + { + values[i]=val0[i]; + pValues[i]=values[i]*invW; + dPv[i]=(val1[i]*invW1-pValues[i])*invDx; + ++i; + } + dInvW=(invW1-invW)*invDx; + zView=v0->GetZview(); + dZ=(v1->GetZview()-zView)*invDx; + } + else + { + if(dx==0) + { + if(dy==0) + { + // render both points and return + // write pixel + if(x>=0 && x<this->ImageInUseSize[0] && y>=0 && + y<this->ImageInUseSize[1]) // clipping + { + vtkIdType j=y*this->ImageInUseSize[0]+x; // mult==bad!! + // Write the pixel + vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry(); + p0->Init(v0->GetValues(),v0->GetZview()); + this->PixelListFrame->AddAndSort(j,p0); + + // Write the pixel + vtkPixelListEntry *p1=this->MemoryManager->AllocateEntry(); + p1->Init(v1->GetValues(),v1->GetZview()); + this->PixelListFrame->AddAndSort(j,p1); + + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)> + this->MaxPixelListSize; + } + } + return; + } + else + { + lineCase=VTK_LINE_CONSTANT; + } + } + else + { + if(dy==dx) + { + lineCase=VTK_LINE_DIAGONAL; + } + else + { + lineCase=VTK_LINE_BRESENHAM; + dx2=dx<<1; + dy2=dy<<1; + e=dy; + } + } + double invDy=1.0/dy; + i=0; + invW=v0->GetInvW(); + double invW1=v1->GetInvW(); + double *val0=v0->GetValues(); + double *val1=v1->GetValues(); + while(i<VTK_VALUES_SIZE) + { + values[i]=val0[i]; + pValues[i]=values[i]*invW; + dPv[i]=(val1[i]*invW1-pValues[i])*invDy; + ++i; + } + dInvW=(invW1-invW)*invDy; + zView=v0->GetZview(); + dZ=(v1->GetZview()-zView)*invDy; + } + + // 2. Iterate over each pixel of the straight line. + int done=0; + while(!done) + { + // write pixel + if(x>=0 && x<this->ImageInUseSize[0] && y>=0 && + y<this->ImageInUseSize[1]) // clipping + { + vtkIdType j=y*this->ImageInUseSize[0]+x; // mult==bad!! + // Write the pixel + vtkPixelListEntry *p0=this->MemoryManager->AllocateEntry(); + p0->Init(values,zView); + this->PixelListFrame->AddAndSort(j,p0); + if(!this->MaxPixelListSizeReached) + { + this->MaxPixelListSizeReached=this->PixelListFrame->GetListSize(j)> + this->MaxPixelListSize; + } + } + + // next pixel + switch(lineCase) + { + case VTK_LINE_CONSTANT: + if(xIncrement) + { + x+=xSign; + if(xSign>0) + { + done=x>v1->GetScreenX(); + } + else + { + done=x<v1->GetScreenX(); + } + } + else + { + ++y; + done=y>v1->GetScreenY(); + } + // values, invw, zview + break; + case VTK_LINE_DIAGONAL: + ++y; + x+=xSign; + done=y>v1->GetScreenY(); + // values, invw, zview + break; + case VTK_LINE_BRESENHAM: + if(xIncrement) + { + x+=xSign; + e+=dy2; + if(e>=dx2) + { + e-=dx2; + ++y; + } + if(xSign>0) + { + done=x>v1->GetScreenX(); + } + else + { + done=x<v1->GetScreenX(); + } + } + else + { + ++y; + e+=dx2; + if(e>=dy2) + { + e-=dy2; + x+=xSign; + } + done=y>v1->GetScreenY(); + } + // values, invw, zview + break; + } + if(!done) + { + invW+=dInvW; + i=0; + double w=1.0/invW; + while(i<VTK_VALUES_SIZE) + { + pValues[i]+=dPv[i]; + values[i]=pValues[i]*w; + ++i; + } + zView+=dZ; + } + } +} + +//----------------------------------------------------------------------------- +void vtkUnstructuredGridVolumeZSweepMapper::CompositeFunction(double zTarget) +{ + int y=this->YBounds[0]; + vtkIdType i=y*this->ImageInUseSize[0]+this->XBounds[0]; + + vtkIdType index=(y*this->ImageMemorySize[0]+this->XBounds[0])<< 2; // *4 + vtkIdType indexStep=this->ImageMemorySize[0]<<2; // *4 + + vtkPixelListEntry *current; + vtkPixelListEntry *next; + double zBuffer=0; + + int newXBounds[2]; + int newYBounds[2]; + + newXBounds[0]=this->ImageInUseSize[0]; + newXBounds[1]=0; + newYBounds[0]=this->ImageInUseSize[1]; + newYBounds[1]=0; + + int xMin=this->XBounds[0]; + int xMax=this->XBounds[1]; + int yMax=this->YBounds[1]; + + vtkPixelList *pixel; + int x; + vtkIdType j; + vtkIdType index2; + int done; + int doIntegration; + double length; + float *color; + + // for each pixel in the bounding box + while(y<=yMax) + { + x=xMin; + j=i; + index2=index; + while(x<=xMax) + { + pixel=this->PixelListFrame->GetList(j); + // we need at least two entries per pixel to perform compositing + if(pixel->GetSize()>=2) + { + current=pixel->GetFirst(); + next=current->GetNext(); +#ifdef BACK_TO_FRONT + done=current->GetZview()<=zTarget || next->GetZview()<=zTarget; +#else + done=current->GetZview()>=zTarget || next->GetZview()>=zTarget; +#endif + + if(!done && this->ZBuffer!=0) + { + // value of the z buffer at the current pixel. + zBuffer=this->GetZBufferValue(x,y); + } + + while(!done) + { + if(this->ZBuffer!=0) + { + // check that current and next are in front of the z-buffer value + doIntegration=current->GetZview()<zBuffer + && next->GetZview()<zBuffer; + } + else + { + doIntegration=1; + } + + if(doIntegration) + { + if(current->GetZview()!=next->GetZview()) + { + // length in world coordinates + length=sqrt(vtkMath::Distance2BetweenPoints( + current->GetValues(),next->GetValues())); + if(length!=0) +// if(length>=0.4) + { + color=this->RealRGBAImage+index2; + this->IntersectionLengths->SetValue(0,length); + this->NearIntersections->SetValue(0,current->GetValues()[VTK_VALUES_SCALAR_INDEX]); + this->FarIntersections->SetValue(0,next->GetValues()[VTK_VALUES_SCALAR_INDEX]); +#ifdef BACK_TO_FRONT + this->RealRayIntegrator->Integrate(this->IntersectionLengths, + this->FarIntersections, + this->NearIntersections, + color); +#else + this->RealRayIntegrator->Integrate(this->IntersectionLengths, + this->NearIntersections, + this->FarIntersections, + color); +#endif + } // length!=0 + } // current->GetZview()!=next->GetZview() + } // doIntegration + + // Next entry + pixel->RemoveFirst(this->MemoryManager); // remove current + + done=pixel->GetSize()<2; // empty queue? + if(!done) + { + current=next; + next=current->GetNext(); +#ifdef BACK_TO_FRONT + done=next->GetZview()<=zTarget; +#else + done=next->GetZview()>=zTarget; +#endif + } + } // while(!done) + } + if(pixel->GetSize()>=2) + { + if(x<newXBounds[0]) + { + newXBounds[0]=x; + } + else + { + if(x>newXBounds[1]) + { + newXBounds[1]=x; + } + } + if(y<newYBounds[0]) + { + newYBounds[0]=y; + } + else + { + if(y>newYBounds[1]) + { + newYBounds[1]=y; + } + } + } + + // next abscissa + ++j; + index2+=4; + ++x; + } + // next ordinate + i=i+this->ImageInUseSize[0]; + index+=indexStep; + ++y; + } + + // Update the bounding box. Useful for the delayed compositing + + this->XBounds[0]=newXBounds[0]; + this->XBounds[1]=newXBounds[1]; + this->YBounds[0]=newYBounds[0]; + this->YBounds[1]=newYBounds[1]; + + this->MaxPixelListSizeReached=0; +} + +//----------------------------------------------------------------------------- +// Description: +// Convert and clamp a float color component into a unsigned char. +unsigned char vtkUnstructuredGridVolumeZSweepMapper::ColorComponentRealToByte( + float color) +{ + int val=static_cast<int>(color*255.0); + if(val>255) + { + val=255; + } + else + { + if(val<0) + { + val=0; + } + } + return static_cast<unsigned char>(val); +} + +//----------------------------------------------------------------------------- +double vtkUnstructuredGridVolumeZSweepMapper::GetZBufferValue(int x, + int y) +{ + int xPos, yPos; + + xPos = static_cast<int>(static_cast<float>(x) * this->ImageSampleDistance); + yPos = static_cast<int>(static_cast<float>(y) * this->ImageSampleDistance); + + xPos = (xPos >= this->ZBufferSize[0])?(this->ZBufferSize[0]-1):(xPos); + yPos = (yPos >= this->ZBufferSize[1])?(this->ZBufferSize[1]-1):(yPos); + + return *(this->ZBuffer + yPos*this->ZBufferSize[0] + xPos); +} + +//----------------------------------------------------------------------------- +double vtkUnstructuredGridVolumeZSweepMapper::GetMinimumBoundsDepth( + vtkRenderer *ren, + vtkVolume *vol ) +{ + double bounds[6]; + vol->GetBounds( bounds ); + + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + // Get the view matrix in two steps - there is a one step method in camera + // but it turns off stereo so we do not want to use that one + vtkCamera *cam = ren->GetActiveCamera(); + this->PerspectiveTransform->Identity(); + this->PerspectiveTransform->Concatenate( + cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], 0.0, 1.0 )); + this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix()); + + double minZ = 1.0; + + for ( int k = 0; k < 2; k++ ) + { + for ( int j = 0; j < 2; j++ ) + { + for ( int i = 0; i < 2; i++ ) + { + double inPoint[4]; + inPoint[0] = bounds[ i]; + inPoint[1] = bounds[2+j]; + inPoint[2] = bounds[4+k]; + inPoint[3] = 1.0; + + double outPoint[4]; + this->PerspectiveMatrix->MultiplyPoint( inPoint, outPoint ); + double testZ = outPoint[2] / outPoint[3]; + minZ = ( testZ < minZ ) ? (testZ) : (minZ); + } + } + } + + return minZ; +} diff --git a/VolumeRendering/vtkUnstructuredGridVolumeZSweepMapper.h b/VolumeRendering/vtkUnstructuredGridVolumeZSweepMapper.h new file mode 100644 index 0000000..253dc7f --- /dev/null +++ b/VolumeRendering/vtkUnstructuredGridVolumeZSweepMapper.h @@ -0,0 +1,374 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkUnstructuredGridVolumeZSweepMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkUnstructuredGridVolumeZSweepMapper - Unstructured grid volume mapper based the ZSweep Algorithm + +// .SECTION Description +// This is a volume mapper for unstructured grid implemented with the ZSweep +// algorithm. This is a software projective method. + +// .SECTION see also +// vtkVolumetMapper + +// .SECTION Background +// The algorithm is described in the following paper: +// Ricardo Farias, Joseph S. B. Mitchell and Claudio T. Silva. +// ZSWEEP: An Efficient and Exact Projection Algorithm for Unstructured Volume +// Rendering. In 2000 Volume Visualization Symposium, pages 91--99. +// October 2000. +// http://www.cse.ogi.edu/~csilva/papers/volvis2000.pdf + +#ifndef __vtkUnstructuredGridVolumeZSweepMapper_h +#define __vtkUnstructuredGridVolumeZSweepMapper_h + +#include "vtkUnstructuredGridVolumeMapper.h" + +class vtkRenderer; +class vtkVolume; +class vtkRayCastImageDisplayHelper; +class vtkCell; +class vtkGenericCell; +class vtkIdList; +class vtkPriorityQueue; +class vtkTransform; +class vtkMatrix4x4; +class vtkVolumeProperty; +class vtkDoubleArray; +class vtkUnstructuredGridVolumeRayIntegrator; +class vtkRenderWindow; + +// Internal classes +class vtkScreenEdge; +class vtkSpan; +class vtkPixelListFrame; +class vtkUseSet; +class vtkVertices; +class vtkSimpleScreenEdge; +class vtkDoubleScreenEdge; +class vtkVertexEntry; +class vtkPixelListEntryMemory; + +class VTK_VOLUMERENDERING_EXPORT vtkUnstructuredGridVolumeZSweepMapper : public vtkUnstructuredGridVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkUnstructuredGridVolumeZSweepMapper,vtkUnstructuredGridVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set MaxPixelListSize to 32. + static vtkUnstructuredGridVolumeZSweepMapper *New(); + + // Description: + // Control how the filter works with scalar point data and cell attribute + // data. By default (ScalarModeToDefault), the filter will use point data, + // and if no point data is available, then cell data is used. Alternatively + // you can explicitly set the filter to use point data + // (ScalarModeToUsePointData) or cell data (ScalarModeToUseCellData). + // You can also choose to get the scalars from an array in point field + // data (ScalarModeToUsePointFieldData) or cell field data + // (ScalarModeToUseCellFieldData). If scalars are coming from a field + // data array, you must call SelectColorArray before you call + // GetColors. + vtkSetMacro(ScalarMode,int); + vtkGetMacro(ScalarMode,int); + void SetScalarModeToDefault() { + this->SetScalarMode(VTK_SCALAR_MODE_DEFAULT);}; + void SetScalarModeToUsePointData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_DATA);}; + void SetScalarModeToUseCellData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_DATA);}; + void SetScalarModeToUsePointFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA);}; + void SetScalarModeToUseCellFieldData() { + this->SetScalarMode(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA);}; + + // Description: + // When ScalarMode is set to UsePointFileData or UseCellFieldData, + // you can specify which array to use for coloring using these methods. + // The transfer function in the vtkVolumeProperty (attached to the calling + // vtkVolume) will decide how to convert vectors to colors. + virtual void SelectScalarArray(int arrayNum); + virtual void SelectScalarArray(const char* arrayName); + + // Description: + // Get the array name or number and component to color by. + virtual char* GetArrayName() { return this->ArrayName; } + virtual int GetArrayId() { return this->ArrayId; } + virtual int GetArrayAccessMode() { return this->ArrayAccessMode; } + + // Description: + // Return the method for obtaining scalar data. + const char *GetScalarModeAsString(); + + // Description: + // Sampling distance in the XY image dimensions. Default value of 1 meaning + // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If + // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. + vtkSetClampMacro( ImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( ImageSampleDistance, float ); + + // Description: + // This is the minimum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MinimumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MinimumImageSampleDistance, float ); + + // Description: + // This is the maximum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MaximumImageSampleDistance, float, 0.1f, 100.0f ); + vtkGetMacro( MaximumImageSampleDistance, float ); + + // Description: + // If AutoAdjustSampleDistances is on, the the ImageSampleDistance + // will be varied to achieve the allocated render time of this + // prop (controlled by the desired update rate and any culling in + // use). + vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 ); + vtkGetMacro( AutoAdjustSampleDistances, int ); + vtkBooleanMacro( AutoAdjustSampleDistances, int ); + + // Description: + // If IntermixIntersectingGeometry is turned on, the zbuffer will be + // captured and used to limit the traversal of the rays. + vtkSetClampMacro( IntermixIntersectingGeometry, int, 0, 1 ); + vtkGetMacro( IntermixIntersectingGeometry, int ); + vtkBooleanMacro( IntermixIntersectingGeometry, int ); + + // Description: + // Maximum size allowed for a pixel list. Default is 32. + // During the rendering, if a list of pixel is full, incremental compositing + // is performed. Even if it is a user setting, it is an advanced parameter. + // You have to understand how the algorithm works to change this value. + int GetMaxPixelListSize(); + + // Description: + // Change the maximum size allowed for a pixel list. It is an advanced + // parameter. + // \pre positive_size: size>0 + void SetMaxPixelListSize(int size); + + // Description: + // Set/Get the helper class for integrating rays. If set to NULL, a + // default integrator will be assigned. + virtual void SetRayIntegrator(vtkUnstructuredGridVolumeRayIntegrator *ri); + vtkGetObjectMacro(RayIntegrator, vtkUnstructuredGridVolumeRayIntegrator); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + void Render(vtkRenderer *ren, + vtkVolume *vol); + + vtkGetVectorMacro( ImageInUseSize, int, 2 ); + vtkGetVectorMacro( ImageOrigin, int, 2 ); + vtkGetVectorMacro( ImageViewportSize, int , 2 ); +//ETX + +protected: + vtkUnstructuredGridVolumeZSweepMapper(); + ~vtkUnstructuredGridVolumeZSweepMapper(); + + // Description: + // For each vertex, find the list of incident faces. + void BuildUseSets(); + + // Description: + // Reorder vertices `v' in increasing order in `w'. Orientation does not + // matter for the algorithm. + void ReorderTriangle(vtkIdType v[3], + vtkIdType w[3]); + + // Description: + // Project and sort the vertices by z-coordinates in view space in the + // "event list" (an heap). + // \pre empty_list: this->EventList->GetNumberOfItems()==0 + void ProjectAndSortVertices(vtkRenderer *ren, + vtkVolume *vol); + + // Description: + // Create an empty "pixel list" for each pixel of the screen. + void CreateAndCleanPixelList(); + + // Description: + // MainLoop of the Zsweep algorithm. + // \post empty_list: this->EventList->GetNumberOfItems()==0 + void MainLoop(vtkRenderWindow *renWin); + + // Description: + // Do delayed compositing from back to front, stopping at zTarget for each + // pixel inside the bounding box. + void CompositeFunction(double zTarget); + + // Description: + // Convert and clamp a float color component into a unsigned char. + unsigned char ColorComponentRealToByte(float color); + + // Description: + // Perform scan conversion of a triangle face. + void RasterizeFace(vtkIdType faceIds[3]); + + // Description: + // Perform scan conversion of a triangle defined by its vertices. + // \pre ve0_exists: ve0!=0 + // \pre ve1_exists: ve1!=0 + // \pre ve2_exists: ve2!=0 + void RasterizeTriangle(vtkVertexEntry *ve0,vtkVertexEntry *ve1, + vtkVertexEntry *ve2); + + // Description: + // Perform scan conversion of an horizontal span from left ro right at line + // y. + // \pre left_exists: left!=0 + // \pre right_exists: right!=0 + void RasterizeSpan(int y, + vtkScreenEdge *left, + vtkScreenEdge *right); + + // Description: + // Scan conversion of a straight line defined by endpoints v0 and v1. + // \pre v0_exists: v0!=0 + // \pre v1_exists: v1!=0 + // \pre y_ordered v0->GetScreenY()<=v1->GetScreenY() + void RasterizeLine(vtkVertexEntry *v0, + vtkVertexEntry *v1); + + void StoreRenderTime(vtkRenderer *ren, + vtkVolume *vol, + float t); + + float RetrieveRenderTime(vtkRenderer *ren, + vtkVolume *vol); + + // Description: + // Return the value of the z-buffer at screen coordinates (x,y). + double GetZBufferValue(int x, + int y); + + double GetMinimumBoundsDepth(vtkRenderer *ren, + vtkVolume *vol); + + // Description: + // Allocate an array of usesets of size `size' only if the current one is not + // large enough. Otherwise clear each use set of each vertex. + void AllocateUseSet(vtkIdType size); + + // Description: + // Allocate a vertex array of size `size' only if the current one is not + // large enough. + void AllocateVertices(vtkIdType size); + + // Description: + // For debugging purpose, save the pixel list frame as a dataset. + void SavePixelListFrame(); + + int MaxPixelListSize; + + float ImageSampleDistance; + float MinimumImageSampleDistance; + float MaximumImageSampleDistance; + int AutoAdjustSampleDistances; + + vtkRayCastImageDisplayHelper *ImageDisplayHelper; + + // This is how big the image would be if it covered the entire viewport + int ImageViewportSize[2]; + + // This is how big the allocated memory for image is. This may be bigger + // or smaller than ImageFullSize - it will be bigger if necessary to + // ensure a power of 2, it will be smaller if the volume only covers a + // small region of the viewport + int ImageMemorySize[2]; + + // This is the size of subregion in ImageSize image that we are using for + // the current image. Since ImageSize is a power of 2, there is likely + // wasted space in it. This number will be used for things such as clearing + // the image if necessary. + int ImageInUseSize[2]; + + // This is the location in ImageFullSize image where our ImageSize image + // is located. + int ImageOrigin[2]; + + // This is the allocated image + unsigned char *Image; + + // This is the accumulating double RGBA image + float *RealRGBAImage; + + float *RenderTimeTable; + vtkVolume **RenderVolumeTable; + vtkRenderer **RenderRendererTable; + int RenderTableSize; + int RenderTableEntries; + + int IntermixIntersectingGeometry; + + float *ZBuffer; + int ZBufferSize[2]; + int ZBufferOrigin[2]; + + int ScalarMode; + char *ArrayName; + int ArrayId; + int ArrayAccessMode; + + vtkDataArray *Scalars; + int CellScalars; + + vtkSpan *Span; + vtkPixelListFrame *PixelListFrame; + + // Used by BuildUseSets(). + vtkGenericCell *Cell; + + vtkUseSet *UseSet; + + vtkPriorityQueue *EventList; + vtkVertices *Vertices; + + vtkTransform *PerspectiveTransform; + vtkMatrix4x4 *PerspectiveMatrix; + + // Used by the main loop + int MaxPixelListSizeReached; + int XBounds[2]; + int YBounds[2]; + + vtkSimpleScreenEdge *SimpleEdge; + vtkDoubleScreenEdge *DoubleEdge; + + vtkUnstructuredGridVolumeRayIntegrator *RayIntegrator; + vtkUnstructuredGridVolumeRayIntegrator *RealRayIntegrator; + + vtkTimeStamp SavedTriangleListMTime; + + // Used during compositing + vtkDoubleArray *IntersectionLengths; + vtkDoubleArray *NearIntersections; + vtkDoubleArray *FarIntersections; + + // Benchmark + vtkIdType MaxRecordedPixelListSize; + + + vtkPixelListEntryMemory *MemoryManager; +private: + vtkUnstructuredGridVolumeZSweepMapper(const vtkUnstructuredGridVolumeZSweepMapper&); // Not implemented. + void operator=(const vtkUnstructuredGridVolumeZSweepMapper&); // Not implemented. +}; + +#endif diff --git a/VolumeRendering/vtkVREncodeString.cxx b/VolumeRendering/vtkVREncodeString.cxx new file mode 100644 index 0000000..f3ce21b --- /dev/null +++ b/VolumeRendering/vtkVREncodeString.cxx @@ -0,0 +1,95 @@ +#include "vtkObject.h" + +#include <vtkstd/string> + +class Output +{ +public: + Output() + { + } + Output(const Output&); + void operator=(const Output&); + ~Output() + { + this->Stream.rdbuf()->freeze(0); + } + ostrstream Stream; + + int ProcessFile(const char* file, const char* title) + { + FILE* fp = fopen(file, "r"); + if ( !fp ) + { + cout << "Canot open file: " << file << endl; + return VTK_ERROR; + } + int ch; + this->Stream << "// Define the " << title << " interfaces." << endl + << "//" << endl + << "// Generated from file: " << file << endl + << "//" << endl + << "const char* " << title << " =" + << endl << "\""; + while ( ( ch = fgetc(fp) ) != EOF ) + { + if ( ch == '\n' ) + { + this->Stream << "\\n\"" << endl << "\""; + } + else if ( ch == '\\' ) + { + this->Stream << "\\\\"; + } + else if ( ch == '\"' ) + { + this->Stream << "\\\""; + } + else if ( ch != '\r' ) + { + this->Stream << (unsigned char)ch; + } + } + this->Stream << "\\n\";" << endl; + fclose(fp); + return VTK_OK; + } +}; + +int main(int argc, char* argv[]) +{ + if ( argc < 4 ) + { + cout << "Usage: " << argv[0] << " <output-file> <input-path> <title>" << endl; + return 1; + } + Output ot; + ot.Stream << "// Loadable modules" << endl + << "//" << endl + << "// Generated by " << argv[0] << endl + << "//" << endl + << "#ifndef __vtkKWCommonPro" << argv[3] << "_h" << endl + << "#define __vtkKWCommonPro" << argv[3] << "_h" << endl + << "" << endl; + + vtkstd::string output = argv[1]; + vtkstd::string input = argv[2]; + + if ( ot.ProcessFile(input.c_str(), argv[3]) != VTK_OK ) + { + cout << "Problem generating header file from XML file: " << input.c_str() << endl; + return 1; + } + ot.Stream << "" << endl + << "#endif" << endl; + ot.Stream << ends; + FILE* fp = fopen(output.c_str(), "w"); + if ( !fp ) + { + cout << "Cannot open output file: " << output.c_str() << endl; + return 1; + } + fprintf(fp, "%s", ot.Stream.str()); + fclose(fp); + return 0; +} diff --git a/VolumeRendering/vtkVolumeMapper.cxx b/VolumeRendering/vtkVolumeMapper.cxx new file mode 100644 index 0000000..3c7e1e6 --- /dev/null +++ b/VolumeRendering/vtkVolumeMapper.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeMapper.h" + +#include "vtkDataSet.h" +#include "vtkExecutive.h" +#include "vtkGarbageCollector.h" +#include "vtkImageData.h" +#include "vtkInformation.h" + +vtkCxxRevisionMacro(vtkVolumeMapper, "$Revision: 1.2 $"); + +// Construct a vtkVolumeMapper with empty scalar input and clipping off. +vtkVolumeMapper::vtkVolumeMapper() +{ + int i; + + this->BlendMode = vtkVolumeMapper::COMPOSITE_BLEND; + + this->Cropping = 0; + for ( i = 0; i < 3; i++ ) + { + this->CroppingRegionPlanes[2*i ] = 0; + this->CroppingRegionPlanes[2*i + 1] = 1; + this->VoxelCroppingRegionPlanes[2*i] = 0; + this->VoxelCroppingRegionPlanes[2*i + 1] = 1; + } + this->CroppingRegionFlags = VTK_CROP_SUBVOLUME; +} + +vtkVolumeMapper::~vtkVolumeMapper() +{ +} + +void vtkVolumeMapper::ConvertCroppingRegionPlanesToVoxels() +{ + double *spacing = this->GetInput()->GetSpacing(); + int *dimensions = this->GetInput()->GetDimensions(); + double origin[3]; + double *bds = this->GetInput()->GetBounds(); + origin[0] = bds[0]; + origin[1] = bds[2]; + origin[2] = bds[4]; + + for ( int i = 0; i < 6; i++ ) + { + this->VoxelCroppingRegionPlanes[i] = + (this->CroppingRegionPlanes[i] - origin[i/2]) / spacing[i/2]; + + this->VoxelCroppingRegionPlanes[i] = + ( this->VoxelCroppingRegionPlanes[i] < 0 ) ? + ( 0 ) : ( this->VoxelCroppingRegionPlanes[i] ); + + this->VoxelCroppingRegionPlanes[i] = + ( this->VoxelCroppingRegionPlanes[i] > dimensions[i/2]-1 ) ? + ( dimensions[i/2]-1 ) : ( this->VoxelCroppingRegionPlanes[i] ); + } +} + +void vtkVolumeMapper::SetInput( vtkDataSet *genericInput ) +{ + vtkImageData *input = + vtkImageData::SafeDownCast( genericInput ); + + if ( input ) + { + this->SetInput( input ); + } + else + { + vtkErrorMacro("The SetInput method of this mapper requires vtkImageData as input"); + } +} + +void vtkVolumeMapper::SetInput( vtkImageData *input ) +{ + if(input) + { + this->SetInputConnection(0, input->GetProducerPort()); + } + else + { + // Setting a NULL input removes the connection. + this->SetInputConnection(0, 0); + } +} + +vtkImageData *vtkVolumeMapper::GetInput() +{ + if (this->GetNumberOfInputConnections(0) < 1) + { + return 0; + } + return vtkImageData::SafeDownCast( + this->GetExecutive()->GetInputData(0, 0)); +} + + +// Print the vtkVolumeMapper +void vtkVolumeMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Cropping: " << (this->Cropping ? "On\n" : "Off\n"); + + os << indent << "Cropping Region Planes: " << endl + << indent << " In X: " << this->CroppingRegionPlanes[0] + << " to " << this->CroppingRegionPlanes[1] << endl + << indent << " In Y: " << this->CroppingRegionPlanes[2] + << " to " << this->CroppingRegionPlanes[3] << endl + << indent << " In Z: " << this->CroppingRegionPlanes[4] + << " to " << this->CroppingRegionPlanes[5] << endl; + + os << indent << "Cropping Region Flags: " + << this->CroppingRegionFlags << endl; + + os << indent << "BlendMode: " << this->BlendMode << endl; + + // Don't print this->VoxelCroppingRegionPlanes +} + +//---------------------------------------------------------------------------- +int vtkVolumeMapper::FillInputPortInformation(int port, vtkInformation* info) +{ + if(!this->Superclass::FillInputPortInformation(port, info)) + { + return 0; + } + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData"); + return 1; +} diff --git a/VolumeRendering/vtkVolumeMapper.h b/VolumeRendering/vtkVolumeMapper.h new file mode 100644 index 0000000..9a48d39 --- /dev/null +++ b/VolumeRendering/vtkVolumeMapper.h @@ -0,0 +1,155 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeMapper - Abstract class for a volume mapper + +// .SECTION Description +// vtkVolumeMapper is the abstract definition of a volume mapper for regular +// rectilinear data (vtkImageData). Several basic types of volume mappers +// are supported. + +// .SECTION see also +// vtkVolumeRayCastMapper vtkVolumeTextureMapper2D + +#ifndef __vtkVolumeMapper_h +#define __vtkVolumeMapper_h + +#include "vtkAbstractVolumeMapper.h" + +class vtkRenderer; +class vtkVolume; +class vtkImageData; + +#define VTK_CROP_SUBVOLUME 0x0002000 +#define VTK_CROP_FENCE 0x2ebfeba +#define VTK_CROP_INVERTED_FENCE 0x5140145 +#define VTK_CROP_CROSS 0x0417410 +#define VTK_CROP_INVERTED_CROSS 0x7be8bef + +class vtkWindow; + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeMapper : public vtkAbstractVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkVolumeMapper,vtkAbstractVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set/Get the input data + virtual void SetInput( vtkImageData * ); + virtual void SetInput( vtkDataSet * ); + vtkImageData *GetInput(); + + // Description: + // Set/Get the blend mode. Currently this is only supported + // by the vtkFixedPointVolumeRayCastMapper - other mappers + // have different ways to set this (supplying a function + // to a vtkVolumeRayCastMapper) or don't have any options + // (vtkVolumeTextureMapper2D supports only compositing) + vtkSetMacro( BlendMode, int ); + void SetBlendModeToComposite() + { this->SetBlendMode( vtkVolumeMapper::COMPOSITE_BLEND ); } + void SetBlendModeToMaximumIntensity() + { this->SetBlendMode( vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND ); } + vtkGetMacro( BlendMode, int ); + + // Description: + // Turn On/Off orthogonal cropping. (Clipping planes are + // perpendicular to the coordinate axes.) + vtkSetClampMacro(Cropping,int,0,1); + vtkGetMacro(Cropping,int); + vtkBooleanMacro(Cropping,int); + + // Description: + // Set/Get the Cropping Region Planes ( xmin, xmax, ymin, ymax, zmin, zmax ) + // These planes are defined in volume coordinates - spacing and origin are + // considered. + vtkSetVector6Macro( CroppingRegionPlanes, double ); + vtkGetVectorMacro( CroppingRegionPlanes, double, 6 ); + + // Description: + // Get the cropping region planes in voxels. Only valid during the + // rendering process + vtkGetVectorMacro( VoxelCroppingRegionPlanes, double, 6 ); + + // Description: + // Set the flags for the cropping regions. The clipping planes divide the + // volume into 27 regions - there is one bit for each region. The regions + // start from the one containing voxel (0,0,0), moving along the x axis + // fastest, the y axis next, and the z axis slowest. These are represented + // from the lowest bit to bit number 27 in the integer containing the + // flags. There are several convenience functions to set some common + // configurations - subvolume (the default), fence (between any of the + // clip plane pairs), inverted fence, cross (between any two of the + // clip plane pairs) and inverted cross. + vtkSetClampMacro( CroppingRegionFlags, int, 0x0, 0x7ffffff ); + vtkGetMacro( CroppingRegionFlags, int ); + void SetCroppingRegionFlagsToSubVolume() + {this->SetCroppingRegionFlags( VTK_CROP_SUBVOLUME );}; + void SetCroppingRegionFlagsToFence() + {this->SetCroppingRegionFlags( VTK_CROP_FENCE );}; + void SetCroppingRegionFlagsToInvertedFence() + {this->SetCroppingRegionFlags( VTK_CROP_INVERTED_FENCE );}; + void SetCroppingRegionFlagsToCross() + {this->SetCroppingRegionFlags( VTK_CROP_CROSS );}; + void SetCroppingRegionFlagsToInvertedCross() + {this->SetCroppingRegionFlags( VTK_CROP_INVERTED_CROSS );}; + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol)=0; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + virtual void ReleaseGraphicsResources(vtkWindow *) {}; + + enum + { + COMPOSITE_BLEND, + MAXIMUM_INTENSITY_BLEND + }; +//ETX + +protected: + vtkVolumeMapper(); + ~vtkVolumeMapper(); + + int BlendMode; + + // Cropping variables, and a method for converting the world + // coordinate cropping region planes to voxel coordinates + int Cropping; + double CroppingRegionPlanes[6]; + double VoxelCroppingRegionPlanes[6]; + int CroppingRegionFlags; + void ConvertCroppingRegionPlanesToVoxels(); + + virtual int FillInputPortInformation(int, vtkInformation*); + +private: + vtkVolumeMapper(const vtkVolumeMapper&); // Not implemented. + void operator=(const vtkVolumeMapper&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkVolumeProMapper.cxx b/VolumeRendering/vtkVolumeProMapper.cxx new file mode 100644 index 0000000..7f9a027 --- /dev/null +++ b/VolumeRendering/vtkVolumeProMapper.cxx @@ -0,0 +1,264 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeProMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkVolumeProMapper.h" +#include "vtkRenderer.h" +#include "vtkToolkits.h" + +#if defined (VTK_HAVE_VP1000) || defined (VTK_FORCE_COMPILE_VP1000) +#include "vtkVolumeProVP1000Mapper.h" +#endif + +#include "vtkDebugLeaks.h" + + +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkVolumeProMapper, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkVolumeProMapper); +//---------------------------------------------------------------------------- + +// Create the mapper. No context has been created, no volume has +// been created yet. +vtkVolumeProMapper::vtkVolumeProMapper() +{ + int i; + + this->Context = NULL; + this->Volume = NULL; + this->VolumeInput = NULL; + this->VolumeBuildTime = vtkTimeStamp::New(); + this->Lights = NULL; + this->NumberOfLights = 0; + this->BlendMode = VTK_BLEND_MODE_COMPOSITE; + + // Disable the subvolume + for ( i = 0; i < 6; i++ ) + { + this->SubVolume[i] = -1; + } + + this->GradientOpacityModulation = 0; + this->GradientDiffuseModulation = 0; + this->GradientSpecularModulation = 0; + + this->Cursor = 0; + this->CursorType = VTK_CURSOR_TYPE_CROSSHAIR; + this->CursorPosition[0] = 0.0; + this->CursorPosition[1] = 0.0; + this->CursorPosition[2] = 0.0; + + this->CursorXAxisColor[0] = 1.0; + this->CursorXAxisColor[1] = 0.0; + this->CursorXAxisColor[2] = 0.0; + + this->CursorYAxisColor[0] = 0.0; + this->CursorYAxisColor[1] = 1.0; + this->CursorYAxisColor[2] = 0.0; + + this->CursorZAxisColor[0] = 0.0; + this->CursorZAxisColor[1] = 0.0; + this->CursorZAxisColor[2] = 1.0; + + this->CutPlane = 0; + this->CutPlaneEquation[0] = 1.0; + this->CutPlaneEquation[1] = 0.0; + this->CutPlaneEquation[2] = 0.0; + this->CutPlaneEquation[3] = 0.0; + this->CutPlaneThickness = 0.0; + this->CutPlaneFallOffDistance = 0; + + this->SuperSampling = 0; + this->SuperSamplingFactor[0] = 1.0; + this->SuperSamplingFactor[1] = 1.0; + this->SuperSamplingFactor[2] = 1.0; + + this->NumberOfBoards = 0; + this->MajorBoardVersion = 0; + this->MinorBoardVersion = 0; + + this->NoHardware = 0; + this->WrongVLIVersion = 0; + this->DisplayedMessage = 0; + + this->Cut = NULL; + + this->IntermixIntersectingGeometry = 0; +} + +// Destroy the mapper. Delete the context, volume build time, and the +// volume if necessary +vtkVolumeProMapper::~vtkVolumeProMapper() +{ + this->VolumeBuildTime->Delete(); +} + +// Simplified version - just assume the mapper type +vtkVolumeProMapper *vtkVolumeProMapper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkObjectFactory::CreateInstance("vtkVolumeProMapper"); + if(ret) + { + return (vtkVolumeProMapper*)ret; + } + +#if defined (VTK_HAVE_VP1000) || defined (VTK_FORCE_COMPILE_VP1000) + vtkDebugLeaks::DestructClass("vtkVolumeProMapper"); + return vtkVolumeProVP1000Mapper::New(); +#else + // if not using vli, then return the stub class, which will render + // nothing.... + return new vtkVolumeProMapper; +#endif +} + +int vtkVolumeProMapper::StatusOK() +{ + if ( this->NoHardware ) + { + if ( !this->DisplayedMessage ) + { + vtkErrorMacro( << "No Hardware Found!" ); + this->DisplayedMessage = 1; + } + return 0; + } + + if ( this->WrongVLIVersion ) + { + if ( !this->DisplayedMessage ) + { + vtkErrorMacro( << "Wrong VLI Version found!" ); + this->DisplayedMessage = 1; + } + return 0; + } + + if ( this->Context == NULL ) + { + return 0; + } + + if ( this->LookupTable == NULL ) + { + return 0; + } + + if ( this->Cut == NULL ) + { + return 0; + } + + return 1; +} + +void vtkVolumeProMapper::SetSuperSamplingFactor( double x, double y, double z ) +{ + if ( x < 0.0 || x > 1.0 || + y < 0.0 || y > 1.0 || + z < 0.0 || z > 1.0 ) + { + vtkErrorMacro( << "Invalid supersampling factor" << endl << + "Each component must be between 0 and 1" ); + return; + } + + this->SuperSamplingFactor[0] = x; + this->SuperSamplingFactor[1] = y; + this->SuperSamplingFactor[2] = z; + + this->Modified(); +} + +void vtkVolumeProMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + // don't print this->SubVolume + os << indent << "Number Of Boards: " << this->NumberOfBoards << endl; + + os << indent << "Major Board Version: " << this->MajorBoardVersion << endl; + + os << indent << "Minor Board Version: " << this->MinorBoardVersion << endl; + + os << indent << "Hardware Available: " << + (this->NoHardware ? "No\n" : "Yes\n"); + + os << indent << "Correct vli Version: " << + (this->WrongVLIVersion ? "No\n" : "Yes\n"); + + os << indent << "Super Sampling: " << + (this->SuperSampling ? "On\n" : "Off\n"); + + os << indent << "Super Sampling Factor: " << + this->SuperSamplingFactor[0] << " by " << + this->SuperSamplingFactor[1] << " by " << + this->SuperSamplingFactor[2] << endl; + + os << indent << "Intermix Intersecting Geometry: " + << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n"); + + os << indent << "Cursor: " << (this->Cursor ? "On\n" : "Off\n"); + + os << indent << "Cursor Position: (" << + this->CursorPosition[0] << ", " << + this->CursorPosition[1] << ", " << + this->CursorPosition[0] << ")\n"; + + os << indent << "Cursor X Axis Color: (" << + this->CursorXAxisColor[0] << ", " << + this->CursorXAxisColor[1] << ", " << + this->CursorXAxisColor[0] << ")\n"; + + os << indent << "Cursor Y Axis Color: (" << + this->CursorYAxisColor[0] << ", " << + this->CursorYAxisColor[1] << ", " << + this->CursorYAxisColor[0] << ")\n"; + + os << indent << "Cursor Z Axis Color: (" << + this->CursorZAxisColor[0] << ", " << + this->CursorZAxisColor[1] << ", " << + this->CursorZAxisColor[0] << ")\n"; + + os << indent << "Cursor Type: " << this->GetCursorTypeAsString() << endl; + + os << indent << "Blend Mode: " << this->GetBlendModeAsString() << endl; + + os << indent << "Cut Plane: " << (this->CutPlane ? "On\n" : "Off\n"); + + os << indent << "Cut Plane Equation: \n" << indent << " (" << + this->CutPlaneEquation[0] << ")X + (" << + this->CutPlaneEquation[1] << ")Y + (" << + this->CutPlaneEquation[2] << ")Z + (" << + this->CutPlaneEquation[3] << ") = 0\n"; + + os << indent << "Cut Plane Thickness " << this->CutPlaneThickness << endl; + + os << indent << "Cut Plane FallOff Distance " << + this->CutPlaneFallOffDistance << endl; + + os << indent << "Gradient Opacity Modulation: " << + (this->GradientOpacityModulation ? "On\n" : "Off\n"); + + os << indent << "Gradient Specular Modulation: " << + (this->GradientSpecularModulation ? "On\n" : "Off\n"); + + os << indent << "Gradient Diffuse Modulation: " << + (this->GradientDiffuseModulation ? "On\n" : "Off\n"); +} diff --git a/VolumeRendering/vtkVolumeProMapper.h b/VolumeRendering/vtkVolumeProMapper.h new file mode 100644 index 0000000..b78bd7d --- /dev/null +++ b/VolumeRendering/vtkVolumeProMapper.h @@ -0,0 +1,338 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeProMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeProMapper - Superclass for VolumePRO volume rendering mappers +// +// .SECTION Description +// vtkVolumeProMapper is the superclass for VolumePRO volume rendering mappers. +// Any functionality that is general across all VolumePRO implementations is +// placed here in this class. Subclasses of this class are for the specific +// board implementations. Subclasses of that are for underlying graphics +// languages. Users should not create subclasses directly - +// a vtkVolumeProMapper will automatically create the object of the right +// type. +// +// If you do not have the VolumePRO libraries when building this object, then +// the New method will create a default renderer that will not render. +// You can check the NumberOfBoards ivar to see if it is a real rendering class. +// To build with the VolumePRO board see vtkVolumeProVP1000Mapper.h +// for instructions. +// +// For more information on the VolumePRO hardware, please see: +// +// http://www.terarecon.com/products/volumepro_prod.html +// +// If you encounter any problems with this class, please inform Kitware, Inc. +// at kitware@kitware.com. +// +// +// .SECTION See Also +// vtkVolumeMapper vtkVolumeProVP1000Mapper vtkOpenGLVolumeProVP1000Mapper +// + + +#ifndef __vtkVolumeProMapper_h +#define __vtkVolumeProMapper_h + +#include "vtkVolumeMapper.h" +#include "vtkToolkits.h" // Needed for VTK_HAVE_VP1000 +#include "vtkVersion.h" // Needed for VTK_*_VERSION + +//BTX +#if defined (VTK_HAVE_VP1000) || defined (VTK_FORCE_COMPILE_VP1000) +namespace vli3 { +#endif +class VLIContext; +class VLIVolume; +class VLILookupTable; +class VLILight; +class VLICutPlane; +#if defined (VTK_HAVE_VP1000) || defined (VTK_FORCE_COMPILE_VP1000) +} +using namespace vli3; +#endif +//ETX + +#define VTK_BLEND_MODE_COMPOSITE 0 +#define VTK_BLEND_MODE_MAX_INTENSITY 1 +#define VTK_BLEND_MODE_MIN_INTENSITY 2 + +#define VTK_CURSOR_TYPE_CROSSHAIR 0 +#define VTK_CURSOR_TYPE_PLANE 1 + +#define VTK_VOLUME_8BIT 0 +#define VTK_VOLUME_12BIT_UPPER 1 +#define VTK_VOLUME_12BIT_LOWER 2 +//BTX +#if ((VTK_MAJOR_VERSION == 3)&&(VTK_MINOR_VERSION == 2)) +#define VTK_VOLUME_PRO_MAPPER_EXPORT VTK_EXPORT +#else +#define VTK_VOLUME_PRO_MAPPER_EXPORT VTK_VOLUMERENDERING_EXPORT +#endif +//ETX + +class VTK_VOLUME_PRO_MAPPER_EXPORT vtkVolumeProMapper : public vtkVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkVolumeProMapper,vtkVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Automatically create the proper subclass + static vtkVolumeProMapper *New(); + + // Description: + // Render the image using the hardware and place it in the frame buffer + virtual void Render( vtkRenderer *, vtkVolume * ) {} + + // Description: + // Set the blend mode + vtkSetClampMacro( BlendMode, int, + VTK_BLEND_MODE_COMPOSITE, VTK_BLEND_MODE_MIN_INTENSITY ); + vtkGetMacro(BlendMode,int); + void SetBlendModeToComposite() + {this->SetBlendMode(VTK_BLEND_MODE_COMPOSITE);}; + void SetBlendModeToMaximumIntensity() + {this->SetBlendMode(VTK_BLEND_MODE_MAX_INTENSITY);}; + void SetBlendModeToMinimumIntensity() + {this->SetBlendMode(VTK_BLEND_MODE_MIN_INTENSITY);}; + const char *GetBlendModeAsString(void); + + // Description: + // Set the subvolume + vtkSetVector6Macro( SubVolume, int ); + vtkGetVectorMacro( SubVolume, int, 6 ); + + // Description: + // Turn the cursor on / off + vtkSetClampMacro( Cursor, int, 0, 1 ); + vtkGetMacro( Cursor, int ); + vtkBooleanMacro( Cursor, int ); + + // Description: + // Set the type of the cursor + vtkSetClampMacro( CursorType, int, + VTK_CURSOR_TYPE_CROSSHAIR, VTK_CURSOR_TYPE_PLANE ); + vtkGetMacro( CursorType, int ); + void SetCursorTypeToCrossHair() + { this->SetCursorType( VTK_CURSOR_TYPE_CROSSHAIR ); }; + void SetCursorTypeToPlane() + { this->SetCursorType( VTK_CURSOR_TYPE_PLANE ); }; + const char *GetCursorTypeAsString( void ); + + // Description: + // Set/Get the cursor position + vtkSetVector3Macro( CursorPosition, double ); + vtkGetVectorMacro( CursorPosition, double, 3 ); + + // Description: + // Set/Get the cursor color + vtkSetVector3Macro( CursorXAxisColor, double ); + vtkGetVectorMacro( CursorXAxisColor, double, 3 ); + vtkSetVector3Macro( CursorYAxisColor, double ); + vtkGetVectorMacro( CursorYAxisColor, double, 3 ); + vtkSetVector3Macro( CursorZAxisColor, double ); + vtkGetVectorMacro( CursorZAxisColor, double, 3 ); + + // Description: + // Turn supersampling on/off + vtkSetClampMacro( SuperSampling, int, 0, 1 ); + vtkGetMacro( SuperSampling, int ); + vtkBooleanMacro( SuperSampling, int ); + + // Description: + // Set the supersampling factors + void SetSuperSamplingFactor( double x, double y, double z ); + void SetSuperSamplingFactor( double f[3] ) + { this->SetSuperSamplingFactor( f[0], f[1], f[2] ); }; + vtkGetVectorMacro( SuperSamplingFactor, double, 3 ); + + // Description: + // Turn on / off the cut plane + vtkSetClampMacro( CutPlane, int, 0, 1 ); + vtkGetMacro( CutPlane, int ); + vtkBooleanMacro( CutPlane, int ); + + // Description: + // Set/Get the cut plane equation + vtkSetVector4Macro( CutPlaneEquation, double ); + vtkGetVectorMacro( CutPlaneEquation, double, 4 ); + + // Description: + // Set / Get the cut plane thickness + vtkSetClampMacro( CutPlaneThickness, double, 0.0, 9.99e10 ); + vtkGetMacro( CutPlaneThickness, double ); + + // Description: + // Set / Get the cut plane falloff value for intensities + vtkSetClampMacro( CutPlaneFallOffDistance, int, 0, 16 ); + vtkGetMacro( CutPlaneFallOffDistance, int ); + + // Description: + // Set/Get the gradient magnitude opacity modulation + vtkSetClampMacro( GradientOpacityModulation, int, 0, 1 ); + vtkGetMacro( GradientOpacityModulation, int ); + vtkBooleanMacro( GradientOpacityModulation, int ); + + // Description: + // Set/Get the gradient magnitude diffuse modulation + vtkSetClampMacro( GradientDiffuseModulation, int, 0, 1 ); + vtkGetMacro( GradientDiffuseModulation, int ); + vtkBooleanMacro( GradientDiffuseModulation, int ); + + // Description: + // Set/Get the gradient magnitude specular modulation + vtkSetClampMacro( GradientSpecularModulation, int, 0, 1 ); + vtkGetMacro( GradientSpecularModulation, int ); + vtkBooleanMacro( GradientSpecularModulation, int ); + + // Description: + // Conveniece methods for debugging + vtkGetMacro( NoHardware, int ); + vtkGetMacro( WrongVLIVersion, int ); + + // Description: + // Access methods for some board info + vtkGetMacro( NumberOfBoards, int ); + vtkGetMacro( MajorBoardVersion, int ); + vtkGetMacro( MinorBoardVersion, int ); + virtual int GetAvailableBoardMemory() { return 0; } + virtual void GetLockSizesForBoardMemory( unsigned int vtkNotUsed(type), + unsigned int * vtkNotUsed(xSize), + unsigned int * vtkNotUsed(ySize), + unsigned int * vtkNotUsed(zSize)) {}; + + // Description: + // Specify whether any geometry intersects the volume. + vtkSetClampMacro(IntermixIntersectingGeometry, int, 0, 1); + vtkGetMacro(IntermixIntersectingGeometry, int); + vtkBooleanMacro(IntermixIntersectingGeometry, int); + +protected: + vtkVolumeProMapper(); + ~vtkVolumeProMapper(); + // Make sure everything is OK for rendering + int StatusOK(); + + // The volume context - create it once and keep it around + VLIContext *Context; + + // The Volume, and the Input that was used to build the volume + // and the time at which it was last built. + VLIVolume *Volume; + vtkImageData *VolumeInput; + vtkTimeStamp *VolumeBuildTime; + + // The type of data in the volume - 8bit, 12bit upper, or 12bit lower + int VolumeDataType; + + // The lookup table for RGBA - create it once then modify it as + // necessary + VLILookupTable *LookupTable; + + // The blending mode to use + int BlendMode; + + // The lights, and how many of them there are. Not all of them + // are turned on or used. + VLILight **Lights; + int NumberOfLights; + + // The subvolume extent (xmin, xmax, ymin, ymax, zmin, zmax) + int SubVolume[6]; + + // The cursor parameters + int Cursor; + int CursorType; + double CursorPosition[3]; + double CursorXAxisColor[3]; + double CursorYAxisColor[3]; + double CursorZAxisColor[3]; + + // The cut plane parameters + int CutPlane; + VLICutPlane *Cut; + double CutPlaneEquation[4]; + double CutPlaneThickness; + int CutPlaneFallOffDistance; + + // The supersampling parameters + int SuperSampling; + double SuperSamplingFactor[3]; + + // The gradient modulation flags + int GradientOpacityModulation; + int GradientDiffuseModulation; + int GradientSpecularModulation; + + // Some board properties + int NumberOfBoards; + int MajorBoardVersion; + int MinorBoardVersion; + int GradientTableSize; + + // Some error conditions that may occur during initialization + int NoHardware; + int WrongVLIVersion; + int DisplayedMessage; + + // The embedded geometry flag + int IntermixIntersectingGeometry; + +//BTX +#if ((VTK_MAJOR_VERSION == 3)&&(VTK_MINOR_VERSION == 2)) + // WARNING: INTERNAL METHOD - NOT FOR GENERAL USE + virtual int GetMapperType() {return VTK_FRAMEBUFFER_VOLUME_MAPPER;}; +#endif +//ETX + +private: + vtkVolumeProMapper(const vtkVolumeProMapper&); // Not implemented. + void operator=(const vtkVolumeProMapper&); // Not implemented. +}; + +// Description: +// Get the blending mode as a descriptive string +inline const char *vtkVolumeProMapper::GetBlendModeAsString() +{ + switch ( this->BlendMode ) + { + case VTK_BLEND_MODE_COMPOSITE: + return "Composite"; + case VTK_BLEND_MODE_MAX_INTENSITY: + return "Maximum Intensity"; + case VTK_BLEND_MODE_MIN_INTENSITY: + return "Minimum Intensity"; + default: + return "Unknown Blend Mode"; + } +} + +// Description: +// Get the cursor type as a descriptive string +inline const char *vtkVolumeProMapper::GetCursorTypeAsString() +{ + switch ( this->CursorType ) + { + case VTK_CURSOR_TYPE_CROSSHAIR: + return "Crosshair"; + case VTK_CURSOR_TYPE_PLANE: + return "Plane"; + default: + return "Unknown Cursor Type"; + } +} + +#endif + diff --git a/VolumeRendering/vtkVolumeProVP1000Mapper.cxx b/VolumeRendering/vtkVolumeProVP1000Mapper.cxx new file mode 100644 index 0000000..59324df --- /dev/null +++ b/VolumeRendering/vtkVolumeProVP1000Mapper.cxx @@ -0,0 +1,1396 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeProVP1000Mapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeProVP1000Mapper.h" + +#include "vtkCamera.h" +#include "vtkColorTransferFunction.h" +#include "vtkDebugLeaks.h" +#include "vtkGraphicsFactory.h" +#include "vtkImageData.h" +#include "vtkLight.h" +#include "vtkLightCollection.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLVolumeProVP1000Mapper.h" +#include "vtkPiecewiseFunction.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkToolkits.h" +#include "vtkTransform.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" + +#include <stdio.h> +#include <math.h> + +vtkCxxRevisionMacro(vtkVolumeProVP1000Mapper, "$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkVolumeProVP1000Mapper); +//---------------------------------------------------------------------------- + +vtkVolumeProVP1000Mapper::vtkVolumeProVP1000Mapper() +{ + VLIStatus status; + VLIConfiguration *config; + + this->ImageBuffer = NULL; + this->DepthBuffer = NULL; + + // Establish a connection with vli + status = VLIOpen(); + + if ( status != kVLIOK ) + { + vtkDebugMacro( << "VLIOpen failed!" ); + this->Context = NULL; + this->LookupTable = NULL; + + if ( status == kVLIErrNoHardware ) + { + this->NoHardware = 1; + } + else if ( status == kVLIErrVersion ) + { + this->WrongVLIVersion = 1; + } + return; + } + + // Gather some useful information + config = new VLIConfiguration; + this->NumberOfBoards = config->GetNumberOfBoards(); + this->MajorBoardVersion = config->GetBoardMajorVersion(); + this->MinorBoardVersion = config->GetBoardMinorVersion(); + this->GradientTableSize = config->GetGradientTableLength(); + delete config; + + // Create the context + this->Context = VLIContext::Create(); + if (!this->Context) + { + vtkErrorMacro( << "Context could not be created!" ); + return; + } + + this->LookupTable = VLILookupTable::Create(VLILookupTable::kSize4096); + + if ( !this->LookupTable ) + { + vtkErrorMacro( << "Lookup table could not be created!" ); + return; + } + + this->Context->GetClassifier().SetLookupTable(kVLITable0, this->LookupTable); + + this->Cut = VLICutPlane::Create( 1.0, 0.0, 0.0, 0.0, 0.0, 0.0 ); + + if ( !this->Cut ) + { + vtkErrorMacro( << "Cut plane could not be created!" ); + return; + } + + this->DrawBoundingBox = 0; +} + + + +vtkVolumeProVP1000Mapper::~vtkVolumeProVP1000Mapper() +{ + int i; + + // free the lights + if (this->NumberOfLights > 0) + { + for ( i = 0; i < this->NumberOfLights; i++ ) + { + this->Context->RemoveLight( this->Lights[i] ); + this->Lights[i]->Release(); + } + if ( this->Lights ) + { + delete [] this->Lights; + } + } + + if (this->Cut) + { + this->Cut->Release(); + } + + // Free the lookup table if it was created + if ( this->LookupTable ) + { + this->LookupTable->Release(); + } + + // Free the volume if necessary + if ( this->Volume ) + { + if (this->Volume->IsLocked() == VLItrue) + { + this->Volume->UnlockVolume(); + } + this->Volume->Release(); + } + + if (this->ImageBuffer) + { + this->ImageBuffer->Release(); + this->ImageBuffer = NULL; + } + + if (this->DepthBuffer) + { + this->DepthBuffer->Release(); + this->DepthBuffer = NULL; + } + + // Free the context if necessary + if (this->Context) + { + this->Context->Release(); + } + + // Terminate connection to the hardware + VLIClose(); +} + +vtkVolumeProVP1000Mapper *vtkVolumeProVP1000Mapper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = vtkObjectFactory::CreateInstance("vtkVolumeProVP1000Mapper"); + if(ret) + { + return (vtkVolumeProVP1000Mapper*)ret; + } + // If the factory was unable to create the object, then create it here. + const char *temp = vtkGraphicsFactory::GetRenderLibrary(); + +#ifdef VTK_USE_OGLR + if (!strcmp("OpenGL",temp)) + { +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass("vtkVolumeProVP1000Mapper"); +#endif + return vtkOpenGLVolumeProVP1000Mapper::New(); + } +#endif +#ifdef _WIN32 + if (!strcmp("Win32OpenGL",temp)) + { +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass("vtkVolumeProVP1000Mapper"); +#endif + return vtkOpenGLVolumeProVP1000Mapper::New(); + } +#endif + + return new vtkVolumeProVP1000Mapper; +} + + + +void vtkVolumeProVP1000Mapper::UpdateCamera( vtkRenderer *ren, vtkVolume * vtkNotUsed(vol) ) +{ + double positionVTK[3]; + double focalPointVTK[3]; + double viewUpVTK[3]; + VLIStatus status; + + // Get the necessary information from the vtk camera + ren->GetActiveCamera()->GetPosition( positionVTK ); + ren->GetActiveCamera()->GetFocalPoint( focalPointVTK ); + ren->GetActiveCamera()->GetViewUp( viewUpVTK ); + + // make sure we are in parallel mode + if (!ren->GetActiveCamera()->GetParallelProjection()) + { + vtkWarningMacro("The Volume Pro VP1000 does not support perspective projection and the camera is currently not in ParallelProjection mode."); + } + + // Create the three vectors we need to do the lookat + VLIVector3D positionVLI ( positionVTK ); + VLIVector3D focalPointVLI ( focalPointVTK ); + VLIVector3D viewUpVLI ( viewUpVTK ); + + // Create a camera from this matrix + VLIMatrix viewMatrixVLI = VLIMatrix::LookAt(positionVLI, focalPointVLI, + viewUpVLI ); + status = this->Context->GetCamera().SetViewMatrix( viewMatrixVLI ); + + double clippingRange[2], parallelScale; + double aspect[2]; + ren->GetActiveCamera()->GetClippingRange(clippingRange); + ren->GetAspect(aspect); + parallelScale = ren->GetActiveCamera()->GetParallelScale(); + + VLIMatrix projectionMatrixVLI = VLIMatrix::Ortho(-parallelScale*aspect[0], + parallelScale*aspect[0], + -parallelScale, + parallelScale, + clippingRange[0], + clippingRange[1]); + + status = this->Context->GetCamera().SetProjectionMatrix( projectionMatrixVLI ); + + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Camera matrix not set!" ); + } + + if ( this->SuperSampling ) + { + if (this->SuperSamplingFactor[2] == 0.0) + { + status = this->Context->SetSamplingFactor(1.0); + } + else + { + status = + this->Context->SetSamplingFactor(1/this->SuperSamplingFactor[2]); + } + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Could not set the sampling factor!" ); + } + } + else + { + this->Context->SetSamplingFactor( 1.0 ); + } +} + + + +void vtkVolumeProVP1000Mapper::UpdateLights( vtkRenderer *ren, vtkVolume *vol ) +{ + vtkLight *light; + float status; + int count; + int index; + double position[3], focalPoint[3]; + float intensity; + VLIVector3D direction; + int i; + + // How many lights do we have? + count = 0; + for( ren->GetLights()->InitTraversal(); + (light = ren->GetLights()->GetNextItem()); ) + { + status = light->GetSwitch(); + if ( status > 0.0 ) + { + count++; + } + } + + if ( count > this->NumberOfLights ) + { + for ( i = 0; i < this->NumberOfLights; i++ ) + { + this->Context->RemoveLight( this->Lights[i] ); + this->Lights[i]->Release(); + } + if ( this->Lights ) + { + delete [] this->Lights; + } + + this->NumberOfLights = count; + this->Lights = new VLILight* [count]; + + for ( i = 0; i < this->NumberOfLights; i++ ) + { + this->Lights[i] = VLILight::CreateDirectional( ); + this->Context->AddLight( this->Lights[i] ); + } + } + + index = 0; + if ( vol->GetProperty()->GetShade() ) + { + for(ren->GetLights()->InitTraversal(); + (light = ren->GetLights()->GetNextItem()); ) + { + status = light->GetSwitch(); + if ( status > 0.0 ) + { + light->GetPosition( position ); + light->GetFocalPoint( focalPoint ); + intensity = light->GetIntensity(); + direction.Assign( (focalPoint[0] - position[0]), + (focalPoint[1] - position[1]), + (focalPoint[2] - position[2]) ); + direction.Normalize(); + this->Lights[index]->SetDirection( direction ); + this->Lights[index]->SetIntensity( intensity ); + index++; + } + } + } + + for ( i = index; i < this->NumberOfLights; i++ ) + { + this->Lights[i]->SetIntensity( 0.0 ); + } +} + +void vtkVolumeProVP1000Mapper::UpdateProperties( vtkRenderer *vtkNotUsed(ren), + vtkVolume *vol ) +{ + vtkPiecewiseFunction *grayFunc; + vtkPiecewiseFunction *goFunc; + vtkPiecewiseFunction *soFunc; + vtkColorTransferFunction *rgbFunc; + VLIuint8 rgbTable[4096][3]; + VLIuint16 aTable[4096]; + int i; + float scale = 1.0; + double *gradientTable; + float val; + + switch ( this->VolumeDataType ) + { + case VTK_VOLUME_8BIT: + scale = 255.0 / 4095.0; + break; + case VTK_VOLUME_12BIT_LOWER: + scale = 1.0; + break; + case VTK_VOLUME_16BIT: + scale = 65535.0 / 4095.0; + break; + } + + soFunc = vol->GetProperty()->GetScalarOpacity(); + + switch ( vol->GetProperty()->GetColorChannels() ) + { + case 1: + grayFunc = vol->GetProperty()->GetGrayTransferFunction(); + for ( i= 0; i< 4096; i++) + { + val = 0.5 + grayFunc->GetValue(static_cast<float>(i)*scale)*255.0; + val = (val < 0)?(0):(val); + val = (val > 255)?(255):(val); + rgbTable[i][0] = rgbTable[i][1] = rgbTable[i][2] + = static_cast<unsigned char>( val ); + + val = 0.5 + 4095.0 * soFunc->GetValue(static_cast<float>(i)*scale); + val = (val < 0)?(0):(val); + val = (val > 4095)?(4095):(val); + aTable[i] = static_cast<unsigned short>( val ); + } + break; + case 3: + rgbFunc = vol->GetProperty()->GetRGBTransferFunction(); + for ( i= 0; i< 4096; i++) + { + val = 0.5 + rgbFunc->GetRedValue(static_cast<float>(i)*scale)*255.0; + val = (val < 0)?(0):(val); + val = (val > 255)?(255):(val); + rgbTable[i][0] = static_cast<unsigned char>( val ); + + val = 0.5 + rgbFunc->GetGreenValue(static_cast<float>(i)*scale)*255.0; + val = (val < 0)?(0):(val); + val = (val > 255)?(255):(val); + rgbTable[i][1] = static_cast<unsigned char>( val ); + + val = 0.5 + rgbFunc->GetBlueValue(static_cast<float>(i)*scale)*255.0; + val = (val < 0)?(0):(val); + val = (val > 255)?(255):(val); + rgbTable[i][2] = static_cast<unsigned char>( val ); + + val = 0.5 + 4095.0 * soFunc->GetValue(static_cast<float>(i)*scale); + val = (val < 0)?(0):(val); + val = (val > 4095)?(4095):(val); + aTable[i] = static_cast<unsigned short>( val ); + } + break; + } + + this->LookupTable->SetColorEntries( 0, 4096, rgbTable ); + this->LookupTable->SetAlphaEntries( 0, 4096, aTable ); + + // Set up the gradient magnitude opacity modulation + goFunc = vol->GetProperty()->GetGradientOpacity(); + + if ( !this->GradientOpacityModulation || !goFunc || + ( !strcmp(goFunc->GetType(), "Constant") && + goFunc->GetValue(0) == 1.0 )) + { + this->Context->SetGradientOpacityModulation( VLIfalse ); + } + else + { + switch ( this->VolumeDataType ) + { + case VTK_VOLUME_8BIT: + scale = sqrt(3.0)*256.0; + break; + case VTK_VOLUME_12BIT_LOWER: + scale = sqrt(3.0)*4096; + break; + case VTK_VOLUME_16BIT: + scale = sqrt(3.0)*65536; + break; + } + + gradientTable = new double [this->GradientTableSize]; + double *spacing = this->GetInput()->GetSpacing(); + double avgSpacing = 0.333*(spacing[0] + spacing[1] + spacing[2]); + scale = scale/(avgSpacing*(this->GradientTableSize-1)); + + for ( i = 0; i < this->GradientTableSize; i++ ) + { + // Take an average of five values in the region + gradientTable[i] = 0.2 * ( + goFunc->GetValue(scale*(static_cast<float>(i - 0.4))) + + goFunc->GetValue(scale*(static_cast<float>(i-0.2))) + + goFunc->GetValue(scale*(static_cast<float>(i))) + + goFunc->GetValue(scale*(static_cast<float>(i+0.2))) + + goFunc->GetValue(scale*(static_cast<float>(i+0.4)))); + } + + this->Context->SetGradientOpacityModulation( VLItrue ); + this->Context->SetGradientTable( gradientTable ); + delete [] gradientTable; + } + + if ( vol->GetProperty()->GetShade() ) + { + this->Context-> + SetReflectionProperties( vol->GetProperty()->GetDiffuse(), + vol->GetProperty()->GetSpecular(), + vol->GetProperty()->GetAmbient(), + vol->GetProperty()->GetSpecularPower() ); + } + else + { + this->Context->SetReflectionProperties( 0.0, 0.0, 1.0, 1.0 ); + } + + this->Context->GetClassifier().SetLookupTable(kVLITable0, this->LookupTable); +} + +void vtkVolumeProVP1000Mapper::UpdateCropping( vtkRenderer * vtkNotUsed(ren), vtkVolume * vtkNotUsed(vol) ) +{ + VLICrop *crop; + + crop = new VLICrop; + + crop->SetSlabs( this->VoxelCroppingRegionPlanes[0], + this->VoxelCroppingRegionPlanes[1], + this->VoxelCroppingRegionPlanes[2], + this->VoxelCroppingRegionPlanes[3], + this->VoxelCroppingRegionPlanes[4], + this->VoxelCroppingRegionPlanes[5] ); + + if ( !this->Cropping ) + { + crop->SetFlags( VLICrop::kDisable ); + } + else + { + switch ( this->CroppingRegionFlags ) + { + case VTK_CROP_SUBVOLUME: + crop->SetFlags( VLICrop::kSubVolume ); + break; + case VTK_CROP_FENCE: + crop->SetFlags( VLICrop::k3DFence ); + break; + case VTK_CROP_INVERTED_FENCE: + crop->SetFlags( VLICrop::k3DFenceInvert ); + break; + case VTK_CROP_CROSS: + crop->SetFlags( VLICrop::k3DCross ); + break; + case VTK_CROP_INVERTED_CROSS: + crop->SetFlags( VLICrop::k3DCrossInvert ); + break; + default: + crop->SetFlags( VLICrop::kDisable ); + vtkErrorMacro( << "Unsupported crop option!" ); + break; + } + } + + this->Context->SetCrop( *crop ); + + delete crop; +} + +void vtkVolumeProVP1000Mapper::UpdateCutPlane( vtkRenderer * vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol) ) +{ + VLIStatus status; + + // If the cut plane is turned off, but the context has a cut plane, + // then we need to remove it + if ( !this->CutPlane ) + { + // Remove it if necessary + if ( this->Context->GetCutPlaneCount() > 0 ) + { + status = this->Context->RemoveCutPlane( this->Cut ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Could not remove cut plane from context" ); + } + } + } + // If the cut plane is turned on, and the context does not have a cut + // plane, then we need to add it. Also, update the position/orientation + // and thickness of the plane + else + { + // Update the position/orientation + status = this->Cut->SetPlane( this->CutPlaneEquation[0], + this->CutPlaneEquation[1], + this->CutPlaneEquation[2], + this->CutPlaneEquation[3] ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Could not set cut plane equation" ); + } + + // Update the thickness + status = this->Cut->SetThickness( this->CutPlaneThickness ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Could not set cut plane thickness" ); + } + + // Update the falloff distance + status = this->Cut->SetFallOff( this->CutPlaneFallOffDistance ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Could not set cut plane fall off distance" ); + } + + // Add it if necessary + if ( this->Context->GetCutPlaneCount() == 0 ) + { + status = this->Context->AddCutPlane( this->Cut ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Could not remove cut plane from context" ); + } + } + } +} + +void vtkVolumeProVP1000Mapper::UpdateCursor( vtkRenderer *vtkNotUsed(ren), vtkVolume *vtkNotUsed(vol) ) +{ +} + +void vtkVolumeProVP1000Mapper::UpdateVolume( vtkRenderer * vtkNotUsed(ren), vtkVolume * vol ) +{ + int dataSize[3]; + int dataType; + unsigned char *uc_data_ptr; + unsigned short *us_data_ptr; + void *data_ptr; + vtkImageData *input = this->GetInput(); + vtkTransform *correctionTransform; + vtkTransform *modelTransform; + int i, j; + double dataOrigin[3]; + double dataSpacing[3]; + VLIStatus status; + double range[2]; + + // We need the size to create the volume and check the subvolume + input->GetDimensions( dataSize ); + VLIVolumeRange volumeRange (dataSize[0], dataSize[1], dataSize[2]); + + // If we have a volume, the size still matches, but our data has + // been modified, call UpdateVolume() to change the content + if ( this->Volume && + input == this->VolumeInput && + input->GetMTime() >= this->VolumeBuildTime->GetMTime() && + this->LoadedDataSize[0] == dataSize[0] && + this->LoadedDataSize[1] == dataSize[1] && + this->LoadedDataSize[2] == dataSize[2] ) + { + int volumeUpdated = 0; + + // Get the data type and a void * pointer to the data + dataType = input->GetPointData()->GetScalars()->GetDataType(); + data_ptr = input->GetPointData()->GetScalars()->GetVoidPointer(0); + + // Switch on data type and update the volume + switch ( dataType ) + { + case VTK_UNSIGNED_CHAR: + if ( this->VolumeDataType == VTK_VOLUME_8BIT ) + { + uc_data_ptr = static_cast<unsigned char *>(data_ptr); + this->Volume->Update( uc_data_ptr, volumeRange ); + volumeUpdated = 1; + } + + break; + + case VTK_UNSIGNED_SHORT: + if ( this->VolumeDataType == VTK_VOLUME_16BIT || + this->VolumeDataType == VTK_VOLUME_12BIT_LOWER) + { + us_data_ptr = static_cast<unsigned short *>(data_ptr); + this->Volume->Update(us_data_ptr, volumeRange); + volumeUpdated = 1; + } + break; + + default: + vtkErrorMacro( "You must convert your data to unsigned char or " << + "unsigned short for a VolumePro mapper" ); + break; + } + + if ( volumeUpdated ) + { + this->VolumeBuildTime->Modified(); + } + } + + // If we have a volume, it is the one we last built with, and it + // has not been modified since then, then we don't need to rebuilt + if ( !this->Volume || + input != this->VolumeInput || + input->GetMTime() >= this->VolumeBuildTime->GetMTime() ) + { + // Otherwise, we need to build the volume + this->VolumeInput = input; + this->VolumeBuildTime->Modified(); + + // If we already have one, get rid of it + if ( this->Volume ) + { + this->Volume->Release(); + this->Volume = NULL; + } + + // Get the data type and a void * pointer to the data + dataType = input->GetPointData()->GetScalars()->GetDataType(); + data_ptr = input->GetPointData()->GetScalars()->GetVoidPointer(0); + + // Switch on data type and create the volume + switch ( dataType ) + { + case VTK_UNSIGNED_CHAR: + uc_data_ptr = static_cast<unsigned char *>(data_ptr); + this->Volume = VLIVolume::Create( 8, dataSize[0], dataSize[1], + dataSize[2], 0, 0, uc_data_ptr ); + this->Volume->SetFieldDescriptor(kVLIField0, + VLIFieldDescriptor(0, 8, kVLIUnsignedFraction)); + + this->VolumeDataType = VTK_VOLUME_8BIT; + + break; + + case VTK_UNSIGNED_SHORT: + us_data_ptr = static_cast<unsigned short *>(data_ptr); + this->Volume = VLIVolume::Create( 16, dataSize[0], dataSize[1], + dataSize[2], 0, 0, us_data_ptr ); + + input->GetPointData()->GetScalars()->GetRange( range ); + if ( range[1] > 4095 ) + { + this->Volume->SetFieldDescriptor(kVLIField0, + VLIFieldDescriptor(0, 16, kVLIUnsignedFraction)); + + this->VolumeDataType = VTK_VOLUME_16BIT; + } + else + { + this->Volume->SetFieldDescriptor(kVLIField0, + VLIFieldDescriptor(0, 12, kVLIUnsignedFraction)); + this->VolumeDataType = VTK_VOLUME_12BIT_LOWER; + } + + break; + + default: + vtkErrorMacro( << "You must convert your data to unsigned char or " + << "unsigned short for a VolumePro mapper" ); + break; + } + } + + // Keep the data size for our check next time + this->LoadedDataSize[0] = dataSize[0]; + this->LoadedDataSize[1] = dataSize[1]; + this->LoadedDataSize[2] = dataSize[2]; + + // Store the matrix of the volume in a temporary transformation matrix + modelTransform = vtkTransform::New(); + modelTransform->SetMatrix( vol->vtkProp3D::GetMatrix() ); + + // Get the origin of the data. This translation is not accounted for in + // the volume's matrix, so we must add it in. + input->GetOrigin( dataOrigin ); + + // Get the data spacing. This scaling is not accounted for in + // the volume's matrix, so we must add it in. + input->GetSpacing( dataSpacing ); + + // Create a transform that will account for the scaling and translation of + // the scalar data + correctionTransform = vtkTransform::New(); + correctionTransform->Identity(); + correctionTransform->Translate(dataOrigin[0], dataOrigin[1], dataOrigin[2]); + correctionTransform->Scale( dataSpacing[0], dataSpacing[1], dataSpacing[2] ); + + VLIMatrix correctionMatrixVLI; + VLIMatrix modelMatrixVLI; + + // Now copy the matrix out (inverted) into an array of doubles + for ( j = 0; j < 4; j++ ) + for ( i = 0; i < 4; i++ ) + { + modelMatrixVLI[i][j] = modelTransform->GetMatrix()->GetElement( i, j ); + correctionMatrixVLI[i][j] = correctionTransform->GetMatrix()->GetElement( i, j ); + } + + if( this->Volume ) + { + status = this->Volume->SetCorrectionMatrix( correctionMatrixVLI ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Error setting the correction matrix: " << status ); + } + } + + status = this->Context->GetCamera().SetModelMatrix( modelMatrixVLI ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Error setting the model matrix: " << status ); + } + + // Delete the objects we created + correctionTransform->Delete(); + modelTransform->Delete(); + + // Update the subvolume if it is reasonable + if ( this->Volume && + this->SubVolume[0] >= 0 && + this->SubVolume[2] >= 0 && + this->SubVolume[4] >= 0 && + this->SubVolume[0] < dataSize[0] && + this->SubVolume[2] < dataSize[1] && + this->SubVolume[4] < dataSize[2] && + this->SubVolume[1] >= this->SubVolume[0] && + this->SubVolume[3] >= this->SubVolume[2] && + this->SubVolume[5] >= this->SubVolume[4] && + this->SubVolume[1] < dataSize[0] && + this->SubVolume[3] < dataSize[1] && + this->SubVolume[5] < dataSize[2] ) + { + VLIVolumeRange volRange ((this->SubVolume[1]-this->SubVolume[0]) + 1, + (this->SubVolume[3]-this->SubVolume[2]) + 1, + (this->SubVolume[5]-this->SubVolume[4]) + 1, + this->SubVolume[0], this->SubVolume[2], + this->SubVolume[4] ); + status = + this->Volume->SetActiveSubVolume( volRange ); + if ( status != kVLIOK ) + { + vtkErrorMacro( << "Could not set the active subvolume" ); + } + } +} + +int vtkVolumeProVP1000Mapper::GetAvailableBoardMemory() +{ + int memory; + VLIConfiguration *config; + + config = new VLIConfiguration; + memory = config->GetAvailableMemory( 0 ); + delete config; + + return memory; +} + +void vtkVolumeProVP1000Mapper::GetLockSizesForBoardMemory( unsigned int type, + unsigned int *xSize, + unsigned int *ySize, + unsigned int *zSize ) +{ + VLIConfiguration *config; + + config = new VLIConfiguration; + config->GetMaxLockedSize( type, *xSize, *ySize, *zSize ); + delete config; +} + +void vtkVolumeProVP1000Mapper::Render( vtkRenderer *ren, vtkVolume *vol ) +{ + int size[2]; + VLIStatus status; + //return; + + if ( !this->StatusOK() ) + { + return; + } + + // make sure that we have scalar input and update the scalar input + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<< "No Input!"); + return; + } + else + { + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + } + + this->ConvertCroppingRegionPlanesToVoxels(); + + this->UpdateCamera( ren, vol ); + + this->UpdateLights( ren, vol); + + this->UpdateVolume( ren, vol ); + + this->UpdateProperties( ren, vol ); + + if ( !this->Volume ) + { + return; + } + + this->UpdateCropping( ren, vol ); + + this->UpdateCutPlane( ren, vol ); + + this->UpdateCursor( ren, vol ); + + this->Context->SetCorrectGradient (VLItrue); + + switch ( this->BlendMode ) + { + case VTK_BLEND_MODE_COMPOSITE: + this->Context->SetBlendMode( kVLIBlendFTB ); + break; + case VTK_BLEND_MODE_MAX_INTENSITY: + this->Context->SetBlendMode( kVLIBlendMIP ); + break; + case VTK_BLEND_MODE_MIN_INTENSITY: + this->Context->SetBlendMode( kVLIBlendMINIP ); + break; + default: + vtkErrorMacro( << "Unknown blending mode: " << this->BlendMode ); + break; + } + + int *windowSize; + windowSize = ren->GetRenderWindow()->GetSize(); + + status = this->Volume->LockVolume(); + + if ( this->ImageBuffer ) + { + unsigned int width, height; + this->ImageBuffer->GetSize(width, height); + if (static_cast<int>(width) != windowSize[0] || + static_cast<int>(height) != windowSize[1]) + { + this->ImageBuffer->Release(); + this->ImageBuffer = NULL; + } + } + if ( ! this->ImageBuffer ) + { + static VLIFieldDescriptor sImageBufferFields[4] = + { + VLIFieldDescriptor(0, 8, kVLIUnsignedFraction), + VLIFieldDescriptor(8, 8, kVLIUnsignedFraction), + VLIFieldDescriptor(16, 8, kVLIUnsignedFraction), + VLIFieldDescriptor(24, 8, kVLIUnsignedFraction) + }; + + this->ImageBuffer = VLIImageBuffer::Create(kVLIBoard0, windowSize[0], + windowSize[1], 32, 4, + sImageBufferFields); + this->ImageBuffer->SetBorderValue(0, 0, 0, 0); + } + + this->Context->SetRayTermination(1.0, VLIfalse); + + int width = 0, height = 0; + + this->CheckSubSampling(this->Volume, this->Context, width, height); + + int imageWidth, imageHeight; + imageWidth = this->ImageBuffer->GetWidth(); + imageHeight = this->ImageBuffer->GetHeight(); + + this->DrawBoundingBox = 0; + + if (width > imageWidth || height > imageHeight) + { + if (width < 2000 && height < 2000) + { + float aspectRatio = (float)imageWidth / (float)imageHeight; + int widthDiff, heightDiff, newWidth, newHeight; + float increase; + + widthDiff = width - imageWidth; + heightDiff = height - imageHeight; + if (widthDiff > heightDiff) + { + increase = (float)width / (float)imageWidth; + newWidth = width; + newHeight = ceil(imageHeight*increase); + } + else + { + increase = (float)height / (float)imageHeight; + newWidth = ceil(imageWidth*increase); + newHeight = height; + } + this->ImageBuffer->Release(); + static VLIFieldDescriptor sImageBufferFields[4] = + { + VLIFieldDescriptor(0, 8, kVLIUnsignedFraction), + VLIFieldDescriptor(8, 8, kVLIUnsignedFraction), + VLIFieldDescriptor(16, 8, kVLIUnsignedFraction), + VLIFieldDescriptor(24, 8, kVLIUnsignedFraction) + }; + + this->ImageBuffer = VLIImageBuffer::Create(kVLIBoard0, newWidth, + newHeight, 32, 4, + sImageBufferFields); + this->ImageBuffer->SetBorderValue(0, 0, 0, 0); + } + else + { + this->DrawBoundingBox = 1; + } + } + + if ( ! this->DrawBoundingBox) + { + if ( ! this->IntermixIntersectingGeometry ) + { + status = this->Volume->Render(this->Context, this->ImageBuffer); + } + else + { + VLIImageRange iRange = VLIImageRange(windowSize[0], windowSize[1]); + if ( this->DepthBuffer ) + { + unsigned int width, height; + this->DepthBuffer->GetSize(width, height); + if (static_cast<int>(width) != windowSize[0] || + static_cast<int>(height) != windowSize[1]) + { + this->DepthBuffer->Release(); + this->DepthBuffer = NULL; + } + } + if ( ! this->DepthBuffer ) + { + this->DepthBuffer = VLIDepthBuffer::Create(kVLIBoard0, windowSize[0], + windowSize[1]); + this->DepthBuffer->SetBorderValue(0); + this->DepthBuffer->SetInputLimits(iRange); + status = this->Context->SetDepthTest(VLIContext::kDepthBuffer1, + VLIContext::kDepthTestLess); + } + unsigned int *depthData = new unsigned int[windowSize[0]*windowSize[1]]; + this->GetDepthBufferValues(ren, windowSize, depthData); + + status = this->DepthBuffer->Update(depthData, + VLIImageRange(windowSize[0], + windowSize[1])); + if ( status != kVLIOK ) + { + switch ( status ) + { + case kVLIErrArgument: + vtkErrorMacro( << "Invalid argument for updating depth buffer!" ); + break; + case kVLIErrAlloc: + vtkErrorMacro( << "Not enough resources to update depth buffer!" ); + break; + default: + // Don't know what the error is, but can't update the depth buffer. + // Shouldn't get to this error message. + vtkErrorMacro( << "Unknown error updating depth buffer!" ); + break; + } + return; + } + this->ImageBuffer->Clear(iRange, 0); + status = this->Volume->Render(this->Context, this->ImageBuffer, 0, 0, + this->DepthBuffer); + + delete [] depthData; + } + + if ( status != kVLIOK ) + { + switch ( status ) + { + case kVLIErrArgument: + vtkErrorMacro( << "Volume could not be rendered - bad argument!" ); + break; + case kVLIErrCantSubsample: + vtkErrorMacro( << "Volume could not be rendered - volume too large for viewport!"); + break; + case kVLIErrClassifier: + vtkErrorMacro( << "Volume could not be rendered - invalid classifier!"); + break; + case kVLIErrTransform: + vtkErrorMacro( << "Volume could not be rendered - invalid transform state!"); + break; + case kVLIErrAccess: + vtkErrorMacro( << "Volume could not be rendered - could not access volume!" ); + break; + case kVLIErrPermission: + vtkErrorMacro( << "Volume could not be rendered - do not have permission to perform render!"); + break; + case kVLIErrVolume: + vtkErrorMacro( << "Volume could not be rendered - no attached buffer!"); + break; + case kVLIErrAlloc: + vtkErrorMacro( << "Volume could not be rendered - not enough resources!" ); + break; + default: + // Don't report the error - this volume just won't render + vtkErrorMacro( << "Volume could not be rendered - unkown error!" ); + break; + } + + return; + } + + size[0] = this->ImageBuffer->GetWidth(); + size[1] = this->ImageBuffer->GetHeight(); + + unsigned int *outData = new unsigned int[size[0]*size[1]]; + + status = this->ImageBuffer->Unload(outData, + this->ImageBuffer->GetOutputLimits()); + + if ( status != kVLIOK ) + { + switch (status) + { + case kVLIErrArgument: + vtkErrorMacro("Image buffer could not be unloaded - invalid argument!"); + break; + case kVLIErrAlloc: + vtkErrorMacro("Image buffer could not be unloaded - not enough resources!"); + break; + case kVLIErrInternal: + vtkErrorMacro("Image buffer could not be unloaded - internal VLI error!"); + break; + default: + vtkErrorMacro("Image buffer could not be unloaded - unknown error!"); + } + } + + // Render the image buffer we've been returned. + this->RenderImageBuffer(ren, vol, size, outData); + + delete [] outData; + } + else + { + this->RenderBoundingBox(ren, vol); + } +} + +#if ((VTK_MAJOR_VERSION == 3)&&(VTK_MINOR_VERSION == 2)) +void vtkVolumeProVP1000Mapper::ConvertCroppingRegionPlanesToVoxels() +{ + memcpy( this->VoxelCroppingRegionPlanes, this->CroppingRegionPlanes, + sizeof ( this->VoxelCroppingRegionPlanes ) ); +} +#endif + +VLIStatus vtkVolumeProVP1000Mapper::CheckSubSampling(const VLIVolume *inVolume, + const VLIContext *inContext, + int &outMinImageWidth, + int &outMinImageHeight) +{ + enum VGAxis + { + kU = 0, + kV = 1, + kW = 2 + }; + + enum VGNeg + { + kNotNeg = 0, + kIsNeg = 1 + }; + + const double kEpsilonSubSample = 1.999; + + + ////////////////////////////////////////////////////////////////////////// + // + // 1) Initialize and calculate matrices: + // + ////////////////////////////////////////////////////////////////////////// + + VLIStatus status = kVLIOK; + + double depthNear, depthFar; + int viewportMinX, viewportMinY, viewportWidth, viewportHeight; + inContext->GetCamera().GetViewport(viewportMinX, viewportMinY, + viewportWidth, viewportHeight); + inContext->GetCamera().GetDepthRange(depthNear, depthFar); + + if (viewportWidth <=0 || viewportHeight <=0) + { + viewportWidth = 3; + viewportHeight = 3; + viewportMinX = 0; + viewportMinY = 0; + status = kVLIErrCantSubsample; + } + + //------------------------------------------------------ + // Calculate viewport matrix from viewport paramteres + //------------------------------------------------------ + + VLIMatrix viewportMatrix; + viewportMatrix.Assign( + (viewportWidth -1)/2.0, 0, 0, (viewportWidth -1)/2.0 + viewportMinX, + 0, (viewportHeight-1)/2.0, 0, (viewportHeight-1)/2.0 + viewportMinY, + 0, 0, (depthFar-depthNear)/2.0, (depthFar+depthNear)/2.0, + 0, 0, 0, 1.0); + + //------------------------------------------------------ + // Calculate viewport-viewmapping(projection)-CorrectedModelView matrix + //------------------------------------------------------- + + VLIMatrix projection = inContext->GetCamera().GetProjectionMatrix(); + VLIMatrix viewMatrix = inContext->GetCamera().GetViewMatrix(); + VLIMatrix model = inContext->GetCamera().GetModelMatrix(); + VLIMatrix correction = inVolume->GetCorrectionMatrix(); + + VLIMatrix VP_VM_CRMVMatrix = + viewportMatrix * + inContext->GetCamera().GetProjectionMatrix() * + inContext->GetCamera().GetViewMatrix() * + inContext->GetCamera().GetModelMatrix() * + inVolume->GetCorrectionMatrix(); + + if (VP_VM_CRMVMatrix.IsSingular()) + { + return kVLIErrTransform; + } + + + ////////////////////////////////////////////////////////////////////////// + // + // 2) Calculate permutation matrix + // a) Choose primary axis to permuted space + // b) Decide the select and neg values in transform + // c) Construct permutation matrix considering min block + ////////////////////////////////////////////////////////////////////////// + + //------------------------------------------------------ + // a) Choose primary axis to permuted space, + // + // The Z axis of the permuted space + // is one axis of object space that is + // closest to the casting ray direction + //------------------------------------------------------ + + + VLIVector4D view(0.0, 0.0, 1.0, 0.0); // view vector in image space + + VLIMatrix VP_VM_CRMVInverse = VP_VM_CRMVMatrix.Inverse(); + + VLIVector4D viewVectorInObjectSpace = (VP_VM_CRMVInverse * view).Normalize(); + + double max = fabs (viewVectorInObjectSpace[0]); + VGAxis primaryAxis = kU; + + if (fabs (viewVectorInObjectSpace[1]) > max) + { + primaryAxis = kV; + max = fabs(viewVectorInObjectSpace[1]); + } + + if (fabs (viewVectorInObjectSpace[2]) > max) + { + primaryAxis = kW; + max = fabs(viewVectorInObjectSpace[2]); + } + + //------------------------------------------------------ + // b) Decide the select and neg values in transform + // + // selectZ is the primary axis, negZ as its direction + // + // selectX, selectY is chosen + // to keep the coordinate system order + //------------------------------------------------------ + + int dirSignOfViewVector[3]; // sign of du, dv, dw direction + int i; + for ( i = 0; i < 3 ; i++) + { + dirSignOfViewVector[i] =(viewVectorInObjectSpace[i] < 0 )? -1:1; + } + + // even: 1, odd -1 + int even = dirSignOfViewVector[0] * dirSignOfViewVector[1]* + dirSignOfViewVector[2]; + + + int axisObj = primaryAxis; // axis of Object Space + int negSign[3]; + + // SelectZ, negZ + VGAxis select[3]; + VGNeg neg[3]; + select[2] = primaryAxis; + neg[2] = (dirSignOfViewVector[axisObj] == 1)?kNotNeg:kIsNeg; + negSign[2] = dirSignOfViewVector[axisObj]; + + // SelectX, SelectY, negX, negY + int axisP; // Axis of Permuted Space + + // The permuted axes are chosen to keep the same coordinate order + // (right or left) as object space + for ( i = 1; i < 3; i++) + { + axisP = (2+ i* even)%3; + axisObj = (primaryAxis +i) %3; + + select[axisP] = (VGAxis)(axisObj); + neg[axisP] = (dirSignOfViewVector[axisObj] == 1)?kNotNeg:kIsNeg; + negSign[axisP] = dirSignOfViewVector[axisObj]; + } + + //----------------------------------------------------------- + // c) Construct permutation matrix considering mini block + //------------------------------------------------------------ + +#define SELECT_AXIS(select, axisObj) ((select == axisObj)?1:0) +#define PERMUTE(axisP,axisObj) negSign[axisP] * SELECT_AXIS(select[axisP], axisObj) + + // shift -1 if du, dv, dw < 0 +#define SHIFT(index) ((negSign[index]==1)? 0:-1) + VLIMatrix permutation; + permutation.Assign( + PERMUTE(0,kU), PERMUTE(0,kV),PERMUTE(0,kW), SHIFT(0), + PERMUTE(1,kU), PERMUTE(1,kV),PERMUTE(1,kW), SHIFT(1), + PERMUTE(2,kU), PERMUTE(2,kV),PERMUTE(2,kW), SHIFT(2), + 0, 0, 0, 1); + + ////////////////////////////////////////////////////////////////////////// + // 3) Calculate sample space increment registers using matrices + ////////////////////////////////////////////////////////////////////////// + + VLIMatrix VP_VM_CRMVPermuted = VP_VM_CRMVMatrix * permutation.Inverse(); + + // 3.a) The 2x2 upper part of dI_DV Matrix is same in dS_dV Matrix + + VLIMatrix dS_dVsubMatrix = VLIMatrix::Identity(); + + dS_dVsubMatrix[0][0] = VP_VM_CRMVPermuted[0][0]; + dS_dVsubMatrix[0][1] = VP_VM_CRMVPermuted[0][1]; + dS_dVsubMatrix[1][0] = VP_VM_CRMVPermuted[1][0]; + dS_dVsubMatrix[1][1] = VP_VM_CRMVPermuted[1][1]; + + VLIMatrix dV_dSsubMatrix = dS_dVsubMatrix.Inverse(); + + dV_dSsubMatrix[0][0] = fabs(dV_dSsubMatrix[0][0]); + dV_dSsubMatrix[0][1] = fabs(dV_dSsubMatrix[0][1]); + dV_dSsubMatrix[1][0] = fabs(dV_dSsubMatrix[1][0]); + dV_dSsubMatrix[1][1] = fabs(dV_dSsubMatrix[1][1]); + + ////////////////////////////////////////////////////////// + // A Scaling method that will + // + // 1) Change only the image size, (viewport) + // + // 2) keep the same permutation matrix + // + // 3) keep valid DepthWarp Matrix + // + // 4) avoid sub sampling, so that + // + // VLIAbs(dXv_dXs) + VLIAbs(dXv_dYs) <=2 + // VLIAbs(dYv_dXs) + VLIAbs(dYv_dYs) <=2 + // + // To conclude, get a scaleX, scaleY in imageSize + // so that + // VLIAbs(dXv_dXs)/ScaleX+ VLIAbs(dXv_dYs)/ScaleY <=2 + // VLIAbs(dXv_dYs)/ScaleX+ VLIAbs(dYv_dYs)/ScaleY <=2 + // + // Different ways to choose ScaleX, ScaleY to avoid sub Sampling + // We choose here when ScaleX == ScaleY, and most close to + // ScaleX =1 , ScaleY =1 + // + + double dXvSampleMax= dV_dSsubMatrix[0][0] + dV_dSsubMatrix[0][1]; + double dYvSampleMax= dV_dSsubMatrix[1][0] + dV_dSsubMatrix[1][1]; + + if (dXvSampleMax > 2.0 || dYvSampleMax > 2.0) + { + status = kVLIErrCantSubsample; + } + + double viewportScale = dXvSampleMax > dYvSampleMax? dXvSampleMax:dYvSampleMax; + + viewportScale /= kEpsilonSubSample; + //************************************************* + //Solution I: + //double dXvSampleMax= dV_dSsubMatrix[0][0] > dV_dSsubMatrix[1][0]? dV_dSsubMatrix[0][0]:dV_dSsubMatrix[1][0]; + //double dYvSampleMax= dV_dSsubMatrix[0][1] > dV_dSsubMatrix[1][1]? dV_dSsubMatrix[0][1]:dV_dSsubMatrix[1][1]; + //************************************** + + //******************************* + //Solution II: + /*Not proper to choose the interesection of the two equation!!!! + VLIVector4D imageScale(2,2,0,0); + dS_dVsubMatrix = dV_dSsubMatrix.Inverse(); + imageScale = dS_dVsubMatrix * imageScale; + + outMinImageWidth = (int)ceil( (viewportWidth -1)/imageScale[0] +1); + outMinImageHeight = (int)ceil( (viewportHeight-1)/imageScale[1] +1);*/ + + // Instead of using scaling dXvSampleMax/2.0, using dZvSampleMax/kEpsionSubSample + outMinImageWidth = (int)ceil( double (viewportWidth -1)*viewportScale +1); + outMinImageHeight = (int)ceil( double (viewportHeight-1)*viewportScale +1); + + return status; +} + +//---------------------------------------------------------------------------- +void vtkVolumeProVP1000Mapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkVolumeProVP1000Mapper.h b/VolumeRendering/vtkVolumeProVP1000Mapper.h new file mode 100644 index 0000000..b712a06 --- /dev/null +++ b/VolumeRendering/vtkVolumeProVP1000Mapper.h @@ -0,0 +1,155 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeProVP1000Mapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeProVP1000Mapper - Superclass for VP1000 board +// +// .SECTION Description +// vtkVolumeProVP1000Mapper is the superclass for VolumePRO volume rendering +// mappers based on the VP1000 chip. Subclasses are for underlying graphics +// languages. Users should not create subclasses directly - +// a vtkVolumeProMapper will automatically create the object of the right +// type. +// +// This class is not included in the Rendering CMakeLists by default. If you +// want to add this class to your vtk build, you need to have the vli header +// and library files, and you will need to perform the following steps: +// +// 1. Run cmake, and set the VTK_USE_VOLUMEPRO flag to true. +// 2. If the libary file (VLI_LIBRARY_FOR_VP1000) is not found by cmake, set +// the path to that file, and rerun cmake. +// 3. If the header file (VLI_INCLUDE_PATH_FOR_VP1000) is not found by cmake, +// set the path to that file, and rerun cmake. +// 4. Rebuild VTK. +// +// For more information on the VolumePRO hardware, please see: +// +// http://www.terarecon.com/products/volumepro_prod.html +// +// If you encounter any problems with this class, please inform Kitware, Inc. +// at kitware@kitware.com. +// +// +// .SECTION See Also +// vtkVolumeMapper vtkVolumeProMapper vtkOpenGLVolumeProVP1000Mapper +// + +#ifndef __vtkVolumeProVP1000Mapper_h +#define __vtkVolumeProVP1000Mapper_h + +#include "vtkVolumeProMapper.h" + +#ifdef _WIN32 +#include "VolumePro1000/inc/vli.h" // Needed for VLI internal types +#else +#include "vli3/include/vli.h" // Needed for VLI internal types +#endif + +#define VTK_VOLUME_16BIT 3 +#define VTK_VOLUME_32BIT 4 + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeProVP1000Mapper : public vtkVolumeProMapper +{ +public: + vtkTypeRevisionMacro(vtkVolumeProVP1000Mapper,vtkVolumeProMapper); + static vtkVolumeProVP1000Mapper *New(); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Render the image using the hardware and place it in the frame buffer + virtual void Render( vtkRenderer *, vtkVolume * ); + virtual int GetAvailableBoardMemory(); + virtual void GetLockSizesForBoardMemory(unsigned int type, + unsigned int *xSize, + unsigned int *ySize, + unsigned int *zSize); + +protected: + vtkVolumeProVP1000Mapper(); + ~vtkVolumeProVP1000Mapper(); + + // Update the camera - set the camera matrix + void UpdateCamera( vtkRenderer *, vtkVolume * ); + + // Update the lights + void UpdateLights( vtkRenderer *, vtkVolume * ); + + // Update the properties of the volume including transfer functions + // and material properties + void UpdateProperties( vtkRenderer *, vtkVolume * ); + + // Update the volume - create it if necessary + // Set the volume matrix. + void UpdateVolume( vtkRenderer *, vtkVolume * ); + + // Set the crop box (as defined in the vtkVolumeMapper superclass) + void UpdateCropping( vtkRenderer *, vtkVolume * ); + + // Set the cursor + void UpdateCursor( vtkRenderer *, vtkVolume * ); + + // Update the cut plane + void UpdateCutPlane( vtkRenderer *, vtkVolume * ); + + // Render the image buffer to the screen + // Defined in the specific graphics implementation. + virtual void RenderImageBuffer( vtkRenderer * vtkNotUsed(ren), + vtkVolume * vol, + int size[2], + unsigned int * outData ) + {(void)vol; (void)size; (void)outData;} + + // Render a bounding box of the volume because the texture map would + // be too large. + virtual void RenderBoundingBox( vtkRenderer * vtkNotUsed(ren), + vtkVolume * vol ) + {(void)vol;} + + // Get the depth buffer values + virtual void GetDepthBufferValues( vtkRenderer *vtkNotUsed(ren), + int size[2], + unsigned int *outData ) + { (void)outData; } + +#if ((VTK_MAJOR_VERSION == 3)&&(VTK_MINOR_VERSION == 2)) + vtkGetVectorMacro( VoxelCroppingRegionPlanes, float, 6 ); + void ConvertCroppingRegionPlanesToVoxels(); + float VoxelCroppingRegionPlanes[6]; +#endif + + + // Keep track of the size of the data loaded so we know if we can + // simply update when a change occurs or if we need to release and + // create again + int LoadedDataSize[3]; + + VLIImageBuffer *ImageBuffer; + VLIDepthBuffer *DepthBuffer; + + VLIStatus CheckSubSampling(const VLIVolume *inVolume, + const VLIContext *inContext, + int &outImageWidth, int &outImageHeight); + + int DrawBoundingBox; + +private: + vtkVolumeProVP1000Mapper(const vtkVolumeProVP1000Mapper&); // Not implemented + void operator=(const vtkVolumeProVP1000Mapper&); // Not implemented +}; + + + +#endif + + + diff --git a/VolumeRendering/vtkVolumeRayCastCompositeFunction.cxx b/VolumeRendering/vtkVolumeRayCastCompositeFunction.cxx new file mode 100644 index 0000000..6c96c0d --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastCompositeFunction.cxx @@ -0,0 +1,2536 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastCompositeFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeRayCastCompositeFunction.h" + +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkVolumeRayCastMapper.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkVolumeRayCastCompositeFunction, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkVolumeRayCastCompositeFunction); + +#define VTK_REMAINING_OPACITY 0.02 + +// This is the templated function that actually casts a ray and computes +// The composite value. This version uses nearest neighbor interpolation +// and does not perform shading. +template <class T> +void vtkCastRay_NN_Unshaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + int value=0; + unsigned char *grad_mag_ptr = NULL; + float accum_red_intensity; + float accum_green_intensity; + float accum_blue_intensity; + float remaining_opacity; + float opacity=0.0; + float gradient_opacity; + int loop; + int xinc, yinc, zinc; + int voxel[3]; + float ray_position[3]; + int prev_voxel[3]; + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + int offset; + int steps_this_ray = 0; + int grad_op_is_constant; + float gradient_opacity_constant; + int num_steps; + float *ray_start, *ray_increment; + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray(); + CTF = staticInfo->Volume->GetRGBArray(); + GTF = staticInfo->Volume->GetGrayArray(); + GOTF = staticInfo->Volume->GetGradientOpacityArray(); + + // Get the gradient opacity constant. If this number is greater than + // or equal to 0.0, then the gradient opacity transfer function is + // a constant at that value, otherwise it is not a constant function + gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant(); + grad_op_is_constant = ( gradient_opacity_constant >= 0.0 ); + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position[0] = ray_start[0]; + ray_position[1] = ray_start[1]; + ray_position[2] = ray_start[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + + // So far we haven't accumulated anything + accum_red_intensity = 0.0; + accum_green_intensity = 0.0; + accum_blue_intensity = 0.0; + remaining_opacity = 1.0; + + // Get a pointer to the gradient magnitudes for this volume + if ( !grad_op_is_constant ) + { + grad_mag_ptr = staticInfo->GradientMagnitudes; + } + + + // Keep track of previous voxel to know when we step into a new one + // set it to something invalid to start with so that everything is + // computed first time through + prev_voxel[0] = voxel[0]-1; + prev_voxel[1] = voxel[1]-1; + prev_voxel[2] = voxel[2]-1; + + // Two cases - we are working with a gray or RGB transfer + // function - break them up to make it more efficient + if ( staticInfo->ColorChannels == 1 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Access the value at this voxel location + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc; + value = *(data_ptr + offset); + opacity = SOTF[value]; + + if ( opacity ) + { + if ( grad_op_is_constant ) + { + gradient_opacity = gradient_opacity_constant; + } + else + { + gradient_opacity = GOTF[*(grad_mag_ptr + offset)]; + } + opacity *= gradient_opacity; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + // Accumulate some light intensity and opacity + accum_red_intensity += ( opacity * remaining_opacity * + GTF[(value)] ); + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + } + accum_green_intensity = accum_red_intensity; + accum_blue_intensity = accum_red_intensity; + } + else if ( staticInfo->ColorChannels == 3 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Access the value at this voxel location + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc; + value = *(data_ptr + offset); + opacity = SOTF[value]; + + if ( opacity ) + { + if ( grad_op_is_constant ) + { + gradient_opacity = gradient_opacity_constant; + } + else + { + gradient_opacity = GOTF[*(grad_mag_ptr + offset)]; + } + opacity *= gradient_opacity; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + + // Accumulate some light intensity and opacity + accum_red_intensity += ( opacity * remaining_opacity * + CTF[(value)*3] ); + accum_green_intensity += ( opacity * remaining_opacity * + CTF[(value)*3 + 1] ); + accum_blue_intensity += ( opacity * remaining_opacity * + CTF[(value)*3 + 2] ); + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + } + } + + // Cap the intensity value at 1.0 + if ( accum_red_intensity > 1.0 ) + { + accum_red_intensity = 1.0; + } + if ( accum_green_intensity > 1.0 ) + { + accum_green_intensity = 1.0; + } + if ( accum_blue_intensity > 1.0 ) + { + accum_blue_intensity = 1.0; + } + + if( remaining_opacity < VTK_REMAINING_OPACITY ) + { + remaining_opacity = 0.0; + } + + // Set the return pixel value. The depth value is the distance to the + // center of the volume. + dynamicInfo->Color[0] = accum_red_intensity; + dynamicInfo->Color[1] = accum_green_intensity; + dynamicInfo->Color[2] = accum_blue_intensity; + dynamicInfo->Color[3] = 1.0 - remaining_opacity; + dynamicInfo->NumberOfStepsTaken = steps_this_ray; + +} + + +// This is the templated function that actually casts a ray and computes +// the composite value. This version uses nearest neighbor and does +// perform shading. +template <class T> +void vtkCastRay_NN_Shaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + int value; + unsigned char *grad_mag_ptr = NULL; + float accum_red_intensity; + float accum_green_intensity; + float accum_blue_intensity; + float remaining_opacity; + float opacity = 0.0; + float gradient_opacity; + int loop; + int xinc, yinc, zinc; + int voxel[3]; + float ray_position[3]; + int prev_voxel[3]; + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float *red_d_shade, *green_d_shade, *blue_d_shade; + float *red_s_shade, *green_s_shade, *blue_s_shade; + unsigned short *encoded_normals; + float red_shaded_value = 0.0; + float green_shaded_value = 0.0; + float blue_shaded_value = 0.0; + int offset; + int steps_this_ray = 0; + int grad_op_is_constant; + float gradient_opacity_constant; + int num_steps; + float *ray_start, *ray_increment; + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + // Get diffuse shading table pointers + red_d_shade = staticInfo->RedDiffuseShadingTable; + green_d_shade = staticInfo->GreenDiffuseShadingTable; + blue_d_shade = staticInfo->BlueDiffuseShadingTable; + + // Get specular shading table pointers + red_s_shade = staticInfo->RedSpecularShadingTable; + green_s_shade = staticInfo->GreenSpecularShadingTable; + blue_s_shade = staticInfo->BlueSpecularShadingTable; + + // Get a pointer to the encoded normals for this volume + encoded_normals = staticInfo->EncodedNormals; + + // Get the scalar opacity transfer function for this volume (which maps + // scalar input values to opacities) + SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray(); + + // Get the color transfer function for this volume (which maps + // scalar input values to RGB values) + CTF = staticInfo->Volume->GetRGBArray(); + GTF = staticInfo->Volume->GetGrayArray(); + + // Get the gradient opacity transfer function for this volume (which maps + // gradient magnitudes to opacities) + GOTF = staticInfo->Volume->GetGradientOpacityArray(); + + // Get the gradient opacity constant. If this number is greater than + // or equal to 0.0, then the gradient opacity transfer function is + // a constant at that value, otherwise it is not a constant function + gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant(); + grad_op_is_constant = ( gradient_opacity_constant >= 0.0 ); + + // Get a pointer to the gradient magnitudes for this volume + if ( !grad_op_is_constant ) + { + grad_mag_ptr = staticInfo->GradientMagnitudes; + } + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position[0] = ray_start[0]; + ray_position[1] = ray_start[1]; + ray_position[2] = ray_start[2]; + + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + + // So far we haven't accumulated anything + accum_red_intensity = 0.0; + accum_green_intensity = 0.0; + accum_blue_intensity = 0.0; + remaining_opacity = 1.0; + + // Keep track of previous voxel to know when we step into a new one + prev_voxel[0] = voxel[0]-1; + prev_voxel[1] = voxel[1]-1; + prev_voxel[2] = voxel[2]-1; + + // Two cases - we are working with a gray or RGB transfer + // function - break them up to make it more efficient + if ( staticInfo->ColorChannels == 1 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Access the value at this voxel location and compute + // opacity and shaded value + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc; + value = *(data_ptr + offset); + + // Get the opacity contributed by the scalar opacity transfer function + opacity = SOTF[value]; + + // Multiply by the opacity contributed by the gradient magnitude + // transfer function (don't both if opacity is already 0) + if ( opacity ) + { + if ( grad_op_is_constant ) + { + gradient_opacity = gradient_opacity_constant; + } + else + { + gradient_opacity = GOTF[*(grad_mag_ptr + offset)]; + } + + opacity *= gradient_opacity; + + } + + // Compute the red shaded value (only if there is some opacity) + // This is grey-scale so green and blue are the same as red + if ( opacity ) + { + red_shaded_value = opacity * remaining_opacity * + ( red_d_shade[*(encoded_normals + offset)] * GTF[value] + + red_s_shade[*(encoded_normals + offset)] ); + } + else + { + red_shaded_value = 0.0; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + + // Accumulate the shaded intensity and opacity of this sample + accum_red_intensity += red_shaded_value; + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + } + accum_green_intensity = accum_red_intensity; + accum_blue_intensity = accum_red_intensity; + } + else if ( staticInfo->ColorChannels == 3 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Access the value at this voxel location and compute + // opacity and shaded value + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0] * xinc; + value = *(data_ptr + offset); + + // Get the opacity contributed by the scalar opacity transfer function + opacity = SOTF[value]; + + // Multiply by the opacity contributed by the gradient magnitude + // transfer function (don't both if opacity is already 0) + if ( opacity ) + { + if ( grad_op_is_constant ) + { + gradient_opacity = gradient_opacity_constant; + } + else + { + gradient_opacity = GOTF[*(grad_mag_ptr + offset)]; + } + + opacity *= gradient_opacity; + } + + // Compute the red, green, and blue shaded value (only if there + // is some opacity) + if ( opacity ) + { + red_shaded_value = opacity * remaining_opacity * + ( red_d_shade[*(encoded_normals + offset)] * CTF[value*3] + + red_s_shade[*(encoded_normals + offset)] ); + green_shaded_value = opacity * remaining_opacity * + ( green_d_shade[*(encoded_normals + offset)] * CTF[value*3 + 1] + + green_s_shade[*(encoded_normals + offset)] ); + blue_shaded_value = opacity * remaining_opacity * + ( blue_d_shade[*(encoded_normals + offset)] * CTF[value*3 + 2] + + blue_s_shade[*(encoded_normals + offset)] ); + } + else + { + red_shaded_value = 0.0; + green_shaded_value = 0.0; + blue_shaded_value = 0.0; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + + // Accumulate the shaded intensity and opacity of this sample + accum_red_intensity += red_shaded_value; + accum_green_intensity += green_shaded_value; + accum_blue_intensity += blue_shaded_value; + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + } + } + + // Cap the intensities at 1.0 + if ( accum_red_intensity > 1.0 ) + { + accum_red_intensity = 1.0; + } + if ( accum_green_intensity > 1.0 ) + { + accum_green_intensity = 1.0; + } + if ( accum_blue_intensity > 1.0 ) + { + accum_blue_intensity = 1.0; + } + + if( remaining_opacity < VTK_REMAINING_OPACITY ) + { + remaining_opacity = 0.0; + } + + // Set the return pixel value. The depth value is the distance to the + // center of the volume. + dynamicInfo->Color[0] = accum_red_intensity; + dynamicInfo->Color[1] = accum_green_intensity; + dynamicInfo->Color[2] = accum_blue_intensity; + dynamicInfo->Color[3] = 1.0 - remaining_opacity; + dynamicInfo->NumberOfStepsTaken = steps_this_ray; + +} + +// This is the templated function that actually casts a ray and computes +// the composite value. This version uses trilinear interpolation and +// does not compute shading +template <class T> +void vtkCastRay_TrilinSample_Unshaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + unsigned char *grad_mag_ptr = NULL; + unsigned char *gmptr; + float accum_red_intensity; + float accum_green_intensity; + float accum_blue_intensity; + float remaining_opacity; + float red_value, green_value, blue_value; + float opacity; + int loop; + int xinc, yinc, zinc; + int voxel[3]; + float ray_position[3]; + float A, B, C, D, E, F, G, H; + int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc; + T *dptr; + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float x, y, z, t1, t2, t3; + int offset; + int steps_this_ray = 0; + float gradient_value; + float scalar_value; + int grad_op_is_constant; + float gradient_opacity_constant; + int num_steps; + float *ray_start, *ray_increment; + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + // Get the scalar opacity transfer function which maps scalar input values + // to opacities + SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray(); + + // Get the color transfer function which maps scalar input values + // to RGB colors + CTF = staticInfo->Volume->GetRGBArray(); + GTF = staticInfo->Volume->GetGrayArray(); + + // Get the gradient opacity transfer function for this volume (which maps + // gradient magnitudes to opacities) + GOTF = staticInfo->Volume->GetGradientOpacityArray(); + + // Get the gradient opacity constant. If this number is greater than + // or equal to 0.0, then the gradient opacity transfer function is + // a constant at that value, otherwise it is not a constant function + gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant(); + grad_op_is_constant = ( gradient_opacity_constant >= 0.0 ); + + // Get a pointer to the gradient magnitudes for this volume + if ( !grad_op_is_constant ) + { + grad_mag_ptr = staticInfo->GradientMagnitudes; + } + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position[0] = ray_start[0]; + ray_position[1] = ray_start[1]; + ray_position[2] = ray_start[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + + // So far we have not accumulated anything + accum_red_intensity = 0.0; + accum_green_intensity = 0.0; + accum_blue_intensity = 0.0; + remaining_opacity = 1.0; + + // Compute the increments to get to the other 7 voxel vertices from A + Binc = xinc; + Cinc = yinc; + Dinc = xinc + yinc; + Einc = zinc; + Finc = zinc + xinc; + Ginc = zinc + yinc; + Hinc = zinc + xinc + yinc; + + // Two cases - we are working with a gray or RGB transfer + // function - break them up to make it more efficient + if ( staticInfo->ColorChannels == 1 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate the value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + scalar_value = + A * t1 * t2 * t3 + + B * x * t2 * t3 + + C * t1 * y * t3 + + D * x * y * t3 + + E * t1 * t2 * z + + F * x * t2 * z + + G * t1 * y * z + + H * x * y * z; + + if ( scalar_value < 0.0 ) + { + scalar_value = 0.0; + } + else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 ) + { + scalar_value = staticInfo->Volume->GetArraySize() - 1; + } + + opacity = SOTF[(int)(scalar_value)]; + + if ( opacity ) + { + if ( !grad_op_is_constant ) + { + gmptr = grad_mag_ptr + offset; + + A = *(gmptr); + B = *(gmptr + Binc); + C = *(gmptr + Cinc); + D = *(gmptr + Dinc); + E = *(gmptr + Einc); + F = *(gmptr + Finc); + G = *(gmptr + Ginc); + H = *(gmptr + Hinc); + + gradient_value = + A * t1 * t2 * t3 + + B * x * t2 * t3 + + C * t1 * y * t3 + + D * x * y * t3 + + E * t1 * t2 * z + + F * x * t2 * z + + G * t1 * y * z + + H * x * y * z; + + if ( gradient_value < 0.0 ) + { + gradient_value = 0.0; + } + else if ( gradient_value > 255.0 ) + { + gradient_value = 255.0; + } + + opacity *= GOTF[(int)(gradient_value)]; + } + else + { + opacity *= gradient_opacity_constant; + } + red_value = opacity * GTF[(int)(scalar_value)]; + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += remaining_opacity * red_value; + remaining_opacity *= (1.0 - opacity); + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + accum_green_intensity = accum_red_intensity; + accum_blue_intensity = accum_red_intensity; + } + else if ( staticInfo->ColorChannels == 3 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate the value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + scalar_value = + A * t1 * t2 * t3 + + B * x * t2 * t3 + + C * t1 * y * t3 + + D * x * y * t3 + + E * t1 * t2 * z + + F * x * t2 * z + + G * t1 * y * z + + H * x * y * z; + + if ( scalar_value < 0.0 ) + { + scalar_value = 0.0; + } + else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 ) + { + scalar_value = staticInfo->Volume->GetArraySize() - 1; + } + + opacity = SOTF[(int)(scalar_value)]; + + if ( opacity ) + { + if ( !grad_op_is_constant ) + { + gmptr = grad_mag_ptr + offset; + + A = *(gmptr); + B = *(gmptr + Binc); + C = *(gmptr + Cinc); + D = *(gmptr + Dinc); + E = *(gmptr + Einc); + F = *(gmptr + Finc); + G = *(gmptr + Ginc); + H = *(gmptr + Hinc); + + gradient_value = + A * t1 * t2 * t3 + + B * x * t2 * t3 + + C * t1 * y * t3 + + D * x * y * t3 + + E * t1 * t2 * z + + F * x * t2 * z + + G * t1 * y * z + + H * x * y * z; + + if ( gradient_value < 0.0 ) + { + gradient_value = 0.0; + } + else if ( gradient_value > 255.0 ) + { + gradient_value = 255.0; + } + + opacity *= GOTF[(int)(gradient_value)]; + } + else + { + opacity *= gradient_opacity_constant; + } + + red_value = opacity * CTF[(int)(scalar_value) * 3 ]; + green_value = opacity * CTF[(int)(scalar_value) * 3 + 1]; + blue_value = opacity * CTF[(int)(scalar_value) * 3 + 2]; + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += remaining_opacity * red_value; + accum_green_intensity += remaining_opacity * green_value; + accum_blue_intensity += remaining_opacity * blue_value; + remaining_opacity *= (1.0 - opacity); + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + } + + // Cap the intensity value at 1.0 + if ( accum_red_intensity > 1.0 ) + { + accum_red_intensity = 1.0; + } + if ( accum_green_intensity > 1.0 ) + { + accum_green_intensity = 1.0; + } + if ( accum_blue_intensity > 1.0 ) + { + accum_blue_intensity = 1.0; + } + + if( remaining_opacity < VTK_REMAINING_OPACITY ) + { + remaining_opacity = 0.0; + } + + // Set the return pixel value. The depth value is the distance to the + // center of the volume. + dynamicInfo->Color[0] = accum_red_intensity; + dynamicInfo->Color[1] = accum_green_intensity; + dynamicInfo->Color[2] = accum_blue_intensity; + dynamicInfo->Color[3] = 1.0 - remaining_opacity; + dynamicInfo->NumberOfStepsTaken = steps_this_ray; + + +} + +// This is the templated function that actually casts a ray and computes +// the composite value. This version uses trilinear interpolation, and +// does perform shading. +template <class T> +void vtkCastRay_TrilinSample_Shaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + unsigned char *grad_mag_ptr = NULL; + unsigned char *gmptr; + float accum_red_intensity; + float accum_green_intensity; + float accum_blue_intensity; + float remaining_opacity; + float opacity; + int loop; + int xinc, yinc, zinc; + int voxel[3]; + float ray_position[3]; + float A, B, C, D, E, F, G, H; + int A_n, B_n, C_n, D_n, E_n, F_n, G_n, H_n; + float final_rd, final_gd, final_bd; + float final_rs, final_gs, final_bs; + int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc; + T *dptr; + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float x, y, z, t1, t2, t3; + float tA, tB, tC, tD, tE, tF, tG, tH; + float *red_d_shade, *green_d_shade, *blue_d_shade; + float *red_s_shade, *green_s_shade, *blue_s_shade; + unsigned short *encoded_normals, *nptr; + float red_shaded_value, green_shaded_value, blue_shaded_value; + int offset; + int steps_this_ray = 0; + int gradient_value; + int scalar_value; + float r, g, b; + int grad_op_is_constant; + float gradient_opacity_constant; + int num_steps; + float *ray_start, *ray_increment; + + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + // Get diffuse shading table pointers + red_d_shade = staticInfo->RedDiffuseShadingTable; + green_d_shade = staticInfo->GreenDiffuseShadingTable; + blue_d_shade = staticInfo->BlueDiffuseShadingTable; + + + // Get diffuse shading table pointers + red_s_shade = staticInfo->RedSpecularShadingTable; + green_s_shade = staticInfo->GreenSpecularShadingTable; + blue_s_shade = staticInfo->BlueSpecularShadingTable; + + // Get a pointer to the encoded normals for this volume + encoded_normals = staticInfo->EncodedNormals; + + // Get the scalar opacity transfer function which maps scalar input values + // to opacities + SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray(); + + // Get the color transfer function which maps scalar input values + // to RGB values + CTF = staticInfo->Volume->GetRGBArray(); + GTF = staticInfo->Volume->GetGrayArray(); + + // Get the gradient opacity transfer function for this volume (which maps + // gradient magnitudes to opacities) + GOTF = staticInfo->Volume->GetGradientOpacityArray(); + + // Get the gradient opacity constant. If this number is greater than + // or equal to 0.0, then the gradient opacity transfer function is + // a constant at that value, otherwise it is not a constant function + gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant(); + grad_op_is_constant = ( gradient_opacity_constant >= 0.0 ); + + // Get a pointer to the gradient magnitudes for this volume + if ( !grad_op_is_constant ) + { + grad_mag_ptr = staticInfo->GradientMagnitudes; + } + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position[0] = ray_start[0]; + ray_position[1] = ray_start[1]; + ray_position[2] = ray_start[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + + // So far we haven't accumulated anything + accum_red_intensity = 0.0; + accum_green_intensity = 0.0; + accum_blue_intensity = 0.0; + remaining_opacity = 1.0; + + // Compute the increments to get to the other 7 voxel vertices from A + Binc = xinc; + Cinc = yinc; + Dinc = xinc + yinc; + Einc = zinc; + Finc = zinc + xinc; + Ginc = zinc + yinc; + Hinc = zinc + xinc + yinc; + + // Two cases - we are working with a gray or RGB transfer + // function - break them up to make it more efficient + if ( staticInfo->ColorChannels == 1 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + nptr = encoded_normals + offset; + + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + tA = t1 * t2 * t3; + tB = x * t2 * t3; + tC = t1 * y * t3; + tD = x * y * t3; + tE = t1 * t2 * z; + tF = x * t2 * z; + tG = t1 * y * z; + tH = x * y * z; + + scalar_value = (int) ( + A * tA + B * tB + C * tC + D * tD + + E * tE + F * tF + G * tG + H * tH ); + + if ( scalar_value < 0 ) + { + scalar_value = 0; + } + else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 ) + { + scalar_value = (int)(staticInfo->Volume->GetArraySize() - 1); + } + + opacity = SOTF[scalar_value]; + + // If we have some opacity based on the scalar value transfer function, + // then multiply by the opacity from the gradient magnitude transfer + // function + if ( opacity ) + { + if ( !grad_op_is_constant ) + { + gmptr = grad_mag_ptr + offset; + + A = *(gmptr); + B = *(gmptr + Binc); + C = *(gmptr + Cinc); + D = *(gmptr + Dinc); + E = *(gmptr + Einc); + F = *(gmptr + Finc); + G = *(gmptr + Ginc); + H = *(gmptr + Hinc); + + gradient_value = (int) ( + A * tA + B * tB + C * tC + D * tD + + E * tE + F * tF + G * tG + H * tH ); + if ( gradient_value < 0 ) + { + gradient_value = 0; + } + else if ( gradient_value > 255 ) + { + gradient_value = 255; + } + + opacity *= GOTF[gradient_value]; + } + else + { + opacity *= gradient_opacity_constant; + } + } + + // If we have a combined opacity value, then compute the shading + if ( opacity ) + { + A_n = *(nptr); + B_n = *(nptr + Binc); + C_n = *(nptr + Cinc); + D_n = *(nptr + Dinc); + E_n = *(nptr + Einc); + F_n = *(nptr + Finc); + G_n = *(nptr + Ginc); + H_n = *(nptr + Hinc); + + final_rd = + red_d_shade[ A_n ] * tA + red_d_shade[ B_n ] * tB + + red_d_shade[ C_n ] * tC + red_d_shade[ D_n ] * tD + + red_d_shade[ E_n ] * tE + red_d_shade[ F_n ] * tF + + red_d_shade[ G_n ] * tG + red_d_shade[ H_n ] * tH; + + final_rs = + red_s_shade[ A_n ] * tA + red_s_shade[ B_n ] * tB + + red_s_shade[ C_n ] * tC + red_s_shade[ D_n ] * tD + + red_s_shade[ E_n ] * tE + red_s_shade[ F_n ] * tF + + red_s_shade[ G_n ] * tG + red_s_shade[ H_n ] * tH; + + r = GTF[(scalar_value)]; + + // For this sample we have do not yet have any opacity or + // shaded intensity yet + red_shaded_value = opacity * ( final_rd * r + final_rs ); + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += red_shaded_value * remaining_opacity; + remaining_opacity *= (1.0 - opacity); + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + accum_green_intensity = accum_red_intensity; + accum_blue_intensity = accum_red_intensity; + } + else if ( staticInfo->ColorChannels == 3 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + nptr = encoded_normals + offset; + + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + tA = t1 * t2 * t3; + tB = x * t2 * t3; + tC = t1 * y * t3; + tD = x * y * t3; + tE = t1 * t2 * z; + tF = x * t2 * z; + tG = t1 * y * z; + tH = x * y * z; + + scalar_value = (int) ( + A * tA + B * tB + C * tC + D * tD + + E * tE + F * tF + G * tG + H * tH ); + + if ( scalar_value < 0 ) + { + scalar_value = 0; + } + else if ( scalar_value > staticInfo->Volume->GetArraySize() - 1 ) + { + scalar_value = (int)(staticInfo->Volume->GetArraySize() - 1); + } + + opacity = SOTF[scalar_value]; + + if ( opacity ) + { + if ( !grad_op_is_constant ) + { + gmptr = grad_mag_ptr + offset; + + A = *(gmptr); + B = *(gmptr + Binc); + C = *(gmptr + Cinc); + D = *(gmptr + Dinc); + E = *(gmptr + Einc); + F = *(gmptr + Finc); + G = *(gmptr + Ginc); + H = *(gmptr + Hinc); + + gradient_value = (int) ( + A * tA + B * tB + C * tC + D * tD + + E * tE + F * tF + G * tG + H * tH ); + if ( gradient_value < 0 ) + { + gradient_value = 0; + } + else if ( gradient_value > 255 ) + { + gradient_value = 255; + } + + opacity *= GOTF[gradient_value]; + } + else + { + opacity *= gradient_opacity_constant; + } + } + + // If we have a combined opacity value, then compute the shading + if ( opacity ) + { + A_n = *(nptr); + B_n = *(nptr + Binc); + C_n = *(nptr + Cinc); + D_n = *(nptr + Dinc); + E_n = *(nptr + Einc); + F_n = *(nptr + Finc); + G_n = *(nptr + Ginc); + H_n = *(nptr + Hinc); + + final_rd = + red_d_shade[ A_n ] * tA + red_d_shade[ B_n ] * tB + + red_d_shade[ C_n ] * tC + red_d_shade[ D_n ] * tD + + red_d_shade[ E_n ] * tE + red_d_shade[ F_n ] * tF + + red_d_shade[ G_n ] * tG + red_d_shade[ H_n ] * tH; + + final_gd = + green_d_shade[ A_n ] * tA + green_d_shade[ B_n ] * tB + + green_d_shade[ C_n ] * tC + green_d_shade[ D_n ] * tD + + green_d_shade[ E_n ] * tE + green_d_shade[ F_n ] * tF + + green_d_shade[ G_n ] * tG + green_d_shade[ H_n ] * tH; + + final_bd = + blue_d_shade[ A_n ] * tA + blue_d_shade[ B_n ] * tB + + blue_d_shade[ C_n ] * tC + blue_d_shade[ D_n ] * tD + + blue_d_shade[ E_n ] * tE + blue_d_shade[ F_n ] * tF + + blue_d_shade[ G_n ] * tG + blue_d_shade[ H_n ] * tH; + + final_rs = + red_s_shade[ A_n ] * tA + red_s_shade[ B_n ] * tB + + red_s_shade[ C_n ] * tC + red_s_shade[ D_n ] * tD + + red_s_shade[ E_n ] * tE + red_s_shade[ F_n ] * tF + + red_s_shade[ G_n ] * tG + red_s_shade[ H_n ] * tH; + + final_gs = + green_s_shade[ A_n ] * tA + green_s_shade[ B_n ] * tB + + green_s_shade[ C_n ] * tC + green_s_shade[ D_n ] * tD + + green_s_shade[ E_n ] * tE + green_s_shade[ F_n ] * tF + + green_s_shade[ G_n ] * tG + green_s_shade[ H_n ] * tH; + + final_bs = + blue_s_shade[ A_n ] * tA + blue_s_shade[ B_n ] * tB + + blue_s_shade[ C_n ] * tC + blue_s_shade[ D_n ] * tD + + blue_s_shade[ E_n ] * tE + blue_s_shade[ F_n ] * tF + + blue_s_shade[ G_n ] * tG + blue_s_shade[ H_n ] * tH; + + r = CTF[(scalar_value) * 3 ]; + g = CTF[(scalar_value) * 3 + 1]; + b = CTF[(scalar_value) * 3 + 2]; + + // For this sample we have do not yet have any opacity or + // shaded intensity yet + red_shaded_value = opacity * ( final_rd * r + final_rs ); + green_shaded_value = opacity * ( final_gd * g + final_gs ); + blue_shaded_value = opacity * ( final_bd * b + final_bs ); + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += red_shaded_value * remaining_opacity; + accum_green_intensity += green_shaded_value * remaining_opacity; + accum_blue_intensity += blue_shaded_value * remaining_opacity; + remaining_opacity *= (1.0 - opacity); + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + } + + // Cap the accumulated intensity at 1.0 + if ( accum_red_intensity > 1.0 ) + { + accum_red_intensity = 1.0; + } + if ( accum_green_intensity > 1.0 ) + { + accum_green_intensity = 1.0; + } + if ( accum_blue_intensity > 1.0 ) + { + accum_blue_intensity = 1.0; + } + + if( remaining_opacity < VTK_REMAINING_OPACITY ) + { + remaining_opacity = 0.0; + } + + // Set the return pixel value. The depth value is the distance to the + // center of the volume. + dynamicInfo->Color[0] = accum_red_intensity; + dynamicInfo->Color[1] = accum_green_intensity; + dynamicInfo->Color[2] = accum_blue_intensity; + dynamicInfo->Color[3] = 1.0 - remaining_opacity; + dynamicInfo->NumberOfStepsTaken = steps_this_ray; + + +} + +// Description: +// This is the templated function that actually casts a ray and computes +// the composite value. This version uses trilinear interpolation and +// does not compute shading +template <class T> +void vtkCastRay_TrilinVertices_Unshaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + unsigned char *grad_mag_ptr = NULL; + unsigned char *goptr; + float accum_red_intensity; + float accum_green_intensity; + float accum_blue_intensity; + float remaining_opacity; + float red_value, green_value, blue_value; + float opacity; + int loop; + int xinc, yinc, zinc; + int voxel[3]; + float ray_position[3]; + int prev_voxel[3]; + float A, B, C, D, E, F, G, H; + float Ago, Bgo, Cgo, Dgo, Ego, Fgo, Ggo, Hgo; + int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc; + T *dptr; + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float x, y, z, t1, t2, t3; + float weight; + int offset; + int steps_this_ray = 0; + int num_steps; + float *ray_start, *ray_increment; + int grad_op_is_constant; + float gradient_opacity_constant; + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + // Get the scalar opacity transfer function which maps scalar input values + // to opacities + SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray(); + + // Get the color transfer function which maps scalar input values + // to RGB colors + CTF = staticInfo->Volume->GetRGBArray(); + GTF = staticInfo->Volume->GetGrayArray(); + + // Get the gradient opacity transfer function for this volume (which maps + // gradient magnitudes to opacities) + GOTF = staticInfo->Volume->GetGradientOpacityArray(); + + // Get the gradient opacity constant. If this number is greater than + // or equal to 0.0, then the gradient opacity transfer function is + // a constant at that value, otherwise it is not a constant function + gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant(); + grad_op_is_constant = ( gradient_opacity_constant >= 0.0 ); + + // Get a pointer to the gradient magnitudes for this volume + if ( !grad_op_is_constant ) + { + grad_mag_ptr = staticInfo->GradientMagnitudes; + } + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position[0] = ray_start[0]; + ray_position[1] = ray_start[1]; + ray_position[2] = ray_start[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + + // So far we have not accumulated anything + accum_red_intensity = 0.0; + accum_green_intensity = 0.0; + accum_blue_intensity = 0.0; + remaining_opacity = 1.0; + + // Compute the increments to get to the other 7 voxel vertices from A + Binc = xinc; + Cinc = yinc; + Dinc = xinc + yinc; + Einc = zinc; + Finc = zinc + xinc; + Ginc = zinc + yinc; + Hinc = zinc + xinc + yinc; + + // Compute the values for the first pass through the loop + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + + A = SOTF[(*(dptr))]; + B = SOTF[(*(dptr + Binc))]; + C = SOTF[(*(dptr + Cinc))]; + D = SOTF[(*(dptr + Dinc))]; + E = SOTF[(*(dptr + Einc))]; + F = SOTF[(*(dptr + Finc))]; + G = SOTF[(*(dptr + Ginc))]; + H = SOTF[(*(dptr + Hinc))]; + + if ( !grad_op_is_constant ) + { + goptr = grad_mag_ptr + offset; + Ago = GOTF[(*(goptr))]; + Bgo = GOTF[(*(goptr + Binc))]; + Cgo = GOTF[(*(goptr + Cinc))]; + Dgo = GOTF[(*(goptr + Dinc))]; + Ego = GOTF[(*(goptr + Einc))]; + Fgo = GOTF[(*(goptr + Finc))]; + Ggo = GOTF[(*(goptr + Ginc))]; + Hgo = GOTF[(*(goptr + Hinc))]; + } + else + { + Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0; + } + + // Keep track of previous voxel to know when we step into a new one + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + + // Two cases - we are working with a gray or RGB transfer + // function - break them up to make it more efficient + if ( staticInfo->ColorChannels == 1 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Have we moved into a new voxel? If so we need to recompute A-H + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + + A = SOTF[(*(dptr))]; + B = SOTF[(*(dptr + Binc))]; + C = SOTF[(*(dptr + Cinc))]; + D = SOTF[(*(dptr + Dinc))]; + E = SOTF[(*(dptr + Einc))]; + F = SOTF[(*(dptr + Finc))]; + G = SOTF[(*(dptr + Ginc))]; + H = SOTF[(*(dptr + Hinc))]; + + if ( !grad_op_is_constant ) + { + goptr = grad_mag_ptr + offset; + Ago = GOTF[(*(goptr))]; + Bgo = GOTF[(*(goptr + Binc))]; + Cgo = GOTF[(*(goptr + Cinc))]; + Dgo = GOTF[(*(goptr + Dinc))]; + Ego = GOTF[(*(goptr + Einc))]; + Fgo = GOTF[(*(goptr + Finc))]; + Ggo = GOTF[(*(goptr + Ginc))]; + Hgo = GOTF[(*(goptr + Hinc))]; + } + else + { + Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate the value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + // For this sample we have do not yet have any opacity + opacity = 0.0; + red_value = 0.0; + + // Now add the opacity in vertex by vertex. If any of the A-H + // have a non-transparent opacity value, then add its contribution + // to the opacity + if ( A && Ago ) + { + weight = t1*t2*t3 * A * Ago; + opacity += weight; + red_value += weight * GTF[((*dptr))]; + } + + if ( B && Bgo ) + { + weight = x*t2*t3 * B * Bgo; + opacity += weight; + red_value += weight * GTF[((*(dptr + Binc)))]; + } + + if ( C && Cgo ) + { + weight = t1*y*t3 * C * Cgo; + opacity += weight; + red_value += weight * GTF[((*(dptr + Cinc)))]; + } + + if ( D && Dgo ) + { + weight = x*y*t3 * D * Dgo; + opacity += weight; + red_value += weight * GTF[((*(dptr + Dinc)))]; + } + + if ( E && Ego ) + { + weight = t1*t2*z * E * Ego; + opacity += weight; + red_value += weight * GTF[((*(dptr + Einc)))]; + } + + if ( F && Fgo ) + { + weight = x*t2*z * F * Fgo; + opacity += weight; + red_value += weight * GTF[((*(dptr + Finc)))]; + } + + if ( G && Ggo ) + { + weight = t1*y*z * G * Ggo; + opacity += weight; + red_value += weight * GTF[((*(dptr + Ginc)))]; + } + + if ( H && Hgo ) + { + weight = x*z*y * H * Hgo; + opacity += weight; + red_value += weight * GTF[((*(dptr + Hinc)))]; + } + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += remaining_opacity * red_value; + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + accum_green_intensity = accum_red_intensity; + accum_blue_intensity = accum_red_intensity; + } + else if ( staticInfo->ColorChannels == 3 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Have we moved into a new voxel? If so we need to recompute A-H + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + + A = SOTF[(*(dptr))]; + B = SOTF[(*(dptr + Binc))]; + C = SOTF[(*(dptr + Cinc))]; + D = SOTF[(*(dptr + Dinc))]; + E = SOTF[(*(dptr + Einc))]; + F = SOTF[(*(dptr + Finc))]; + G = SOTF[(*(dptr + Ginc))]; + H = SOTF[(*(dptr + Hinc))]; + + if ( !grad_op_is_constant ) + { + goptr = grad_mag_ptr + offset; + Ago = GOTF[(*(goptr))]; + Bgo = GOTF[(*(goptr + Binc))]; + Cgo = GOTF[(*(goptr + Cinc))]; + Dgo = GOTF[(*(goptr + Dinc))]; + Ego = GOTF[(*(goptr + Einc))]; + Fgo = GOTF[(*(goptr + Finc))]; + Ggo = GOTF[(*(goptr + Ginc))]; + Hgo = GOTF[(*(goptr + Hinc))]; + } + else + { + Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate the value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + // For this sample we have do not yet have any opacity + opacity = 0.0; + red_value = 0.0; + green_value = 0.0; + blue_value = 0.0; + + // Now add the opacity in vertex by vertex. If any of the A-H + // have a non-transparent opacity value, then add its contribution + // to the opacity + if ( A && Ago ) + { + weight = t1*t2*t3 * A * Ago; + opacity += weight; + red_value += weight * CTF[((*dptr)) * 3 ]; + green_value += weight * CTF[((*dptr)) * 3 + 1]; + blue_value += weight * CTF[((*dptr)) * 3 + 2]; + } + + if ( B && Bgo ) + { + weight = x*t2*t3 * B * Bgo; + opacity += weight; + red_value += weight * CTF[((*(dptr + Binc))) * 3 ]; + green_value += weight * CTF[((*(dptr + Binc))) * 3 + 1]; + blue_value += weight * CTF[((*(dptr + Binc))) * 3 + 2]; + } + + if ( C && Cgo ) + { + weight = t1*y*t3 * C * Cgo; + opacity += weight; + red_value += weight * CTF[((*(dptr + Cinc))) * 3 ]; + green_value += weight * CTF[((*(dptr + Cinc))) * 3 + 1]; + blue_value += weight * CTF[((*(dptr + Cinc))) * 3 + 2]; + } + + if ( D && Dgo ) + { + weight = x*y*t3 * D * Dgo; + opacity += weight; + red_value += weight * CTF[((*(dptr + Dinc))) * 3 ]; + green_value += weight * CTF[((*(dptr + Dinc))) * 3 + 1]; + blue_value += weight * CTF[((*(dptr + Dinc))) * 3 + 2]; + } + + if ( E && Ego ) + { + weight = t1*t2*z * E * Ego; + opacity += weight; + red_value += weight * CTF[((*(dptr + Einc))) * 3 ]; + green_value += weight * CTF[((*(dptr + Einc))) * 3 + 1]; + blue_value += weight * CTF[((*(dptr + Einc))) * 3 + 2]; + } + + if ( F && Fgo ) + { + weight = x*t2*z * F * Fgo; + opacity += weight; + red_value += weight * CTF[((*(dptr + Finc))) * 3 ]; + green_value += weight * CTF[((*(dptr + Finc))) * 3 + 1]; + blue_value += weight * CTF[((*(dptr + Finc))) * 3 + 2]; + } + + if ( G && Ggo ) + { + weight = t1*y*z * G * Ggo; + opacity += weight; + red_value += weight * CTF[((*(dptr + Ginc))) * 3 ]; + green_value += weight * CTF[((*(dptr + Ginc))) * 3 + 1]; + blue_value += weight * CTF[((*(dptr + Ginc))) * 3 + 2]; + } + + if ( H && Hgo ) + { + weight = x*z*y * H * Hgo; + opacity += weight; + red_value += weight * CTF[((*(dptr + Hinc))) * 3 ]; + green_value += weight * CTF[((*(dptr + Hinc))) * 3 + 1]; + blue_value += weight * CTF[((*(dptr + Hinc))) * 3 + 2]; + } + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += remaining_opacity * red_value; + accum_green_intensity += remaining_opacity * green_value; + accum_blue_intensity += remaining_opacity * blue_value; + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + } + + // Cap the accumulated intensity at 1.0 + if ( accum_red_intensity > 1.0 ) + { + accum_red_intensity = 1.0; + } + if ( accum_green_intensity > 1.0 ) + { + accum_green_intensity = 1.0; + } + if ( accum_blue_intensity > 1.0 ) + { + accum_blue_intensity = 1.0; + } + + if( remaining_opacity < VTK_REMAINING_OPACITY ) + { + remaining_opacity = 0.0; + } + + // Set the return pixel value. The depth value is the distance to the + // center of the volume. + dynamicInfo->Color[0] = accum_red_intensity; + dynamicInfo->Color[1] = accum_green_intensity; + dynamicInfo->Color[2] = accum_blue_intensity; + dynamicInfo->Color[3] = 1.0 - remaining_opacity; + dynamicInfo->NumberOfStepsTaken = steps_this_ray; + + +} + + +// Description: +// This is the templated function that actually casts a ray and computes +// the composite value. This version uses trilinear interpolation, and +// does perform shading. +template <class T> +void vtkCastRay_TrilinVertices_Shaded( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + unsigned char *grad_mag_ptr = NULL; + unsigned char *goptr; + float accum_red_intensity; + float accum_green_intensity; + float accum_blue_intensity; + float remaining_opacity; + float opacity; + int loop; + int xinc, yinc, zinc; + int voxel[3]; + float ray_position[3]; + int prev_voxel[3]; + float A, B, C, D, E, F, G, H; + float Ago, Bgo, Cgo, Dgo, Ego, Fgo, Ggo, Hgo; + int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc; + T *dptr; + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float x, y, z, t1, t2, t3; + float weight; + float *red_d_shade, *green_d_shade, *blue_d_shade; + float *red_s_shade, *green_s_shade, *blue_s_shade; + unsigned short *encoded_normals, *nptr; + float red_shaded_value, green_shaded_value, blue_shaded_value; + int offset; + int steps_this_ray = 0; + int grad_op_is_constant; + float gradient_opacity_constant; + int num_steps; + float *ray_start, *ray_increment; + + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + // Get diffuse shading table pointers + red_d_shade = staticInfo->RedDiffuseShadingTable; + green_d_shade = staticInfo->GreenDiffuseShadingTable; + blue_d_shade = staticInfo->BlueDiffuseShadingTable; + + + // Get diffuse shading table pointers + red_s_shade = staticInfo->RedSpecularShadingTable; + green_s_shade = staticInfo->GreenSpecularShadingTable; + blue_s_shade = staticInfo->BlueSpecularShadingTable; + + // Get a pointer to the encoded normals for this volume + encoded_normals = staticInfo->EncodedNormals; + + // Get the scalar opacity transfer function which maps scalar input values + // to opacities + SOTF = staticInfo->Volume->GetCorrectedScalarOpacityArray(); + + // Get the color transfer function which maps scalar input values + // to RGB values + CTF = staticInfo->Volume->GetRGBArray(); + GTF = staticInfo->Volume->GetGrayArray(); + + // Get the gradient opacity transfer function for this volume (which maps + // gradient magnitudes to opacities) + GOTF = staticInfo->Volume->GetGradientOpacityArray(); + + // Get the gradient opacity constant. If this number is greater than + // or equal to 0.0, then the gradient opacity transfer function is + // a constant at that value, otherwise it is not a constant function + gradient_opacity_constant = staticInfo->Volume->GetGradientOpacityConstant(); + grad_op_is_constant = ( gradient_opacity_constant >= 0.0 ); + + // Get a pointer to the gradient magnitudes for this volume + if ( !grad_op_is_constant ) + { + grad_mag_ptr = staticInfo->GradientMagnitudes; + } + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position[0] = ray_start[0]; + ray_position[1] = ray_start[1]; + ray_position[2] = ray_start[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + + // So far we haven't accumulated anything + accum_red_intensity = 0.0; + accum_green_intensity = 0.0; + accum_blue_intensity = 0.0; + remaining_opacity = 1.0; + + // Compute the increments to get to the other 7 voxel vertices from A + Binc = xinc; + Cinc = yinc; + Dinc = xinc + yinc; + Einc = zinc; + Finc = zinc + xinc; + Ginc = zinc + yinc; + Hinc = zinc + xinc + yinc; + + // Compute the values for the first pass through the loop + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + nptr = encoded_normals + offset; + + A = SOTF[(*(dptr))]; + B = SOTF[(*(dptr + Binc))]; + C = SOTF[(*(dptr + Cinc))]; + D = SOTF[(*(dptr + Dinc))]; + E = SOTF[(*(dptr + Einc))]; + F = SOTF[(*(dptr + Finc))]; + G = SOTF[(*(dptr + Ginc))]; + H = SOTF[(*(dptr + Hinc))]; + + if ( !grad_op_is_constant ) + { + goptr = grad_mag_ptr + offset; + Ago = GOTF[(*(goptr))]; + Bgo = GOTF[(*(goptr + Binc))]; + Cgo = GOTF[(*(goptr + Cinc))]; + Dgo = GOTF[(*(goptr + Dinc))]; + Ego = GOTF[(*(goptr + Einc))]; + Fgo = GOTF[(*(goptr + Finc))]; + Ggo = GOTF[(*(goptr + Ginc))]; + Hgo = GOTF[(*(goptr + Hinc))]; + } + else + { + Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0; + } + + + // Keep track of previous voxel to know when we step into a new one + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + + // Two cases - we are working with a single color or a color transfer + // function - break them up to make it more efficient + if ( staticInfo->ColorChannels == 1 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Have we moved into a new voxel? If so we need to recompute A-H + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + nptr = encoded_normals + offset; + //goptr = grad_mag_ptr + offset; + + A = SOTF[(*(dptr))]; + B = SOTF[(*(dptr + Binc))]; + C = SOTF[(*(dptr + Cinc))]; + D = SOTF[(*(dptr + Dinc))]; + E = SOTF[(*(dptr + Einc))]; + F = SOTF[(*(dptr + Finc))]; + G = SOTF[(*(dptr + Ginc))]; + H = SOTF[(*(dptr + Hinc))]; + + if ( !grad_op_is_constant ) + { + goptr = grad_mag_ptr + offset; + Ago = GOTF[(*(goptr))]; + Bgo = GOTF[(*(goptr + Binc))]; + Cgo = GOTF[(*(goptr + Cinc))]; + Dgo = GOTF[(*(goptr + Dinc))]; + Ego = GOTF[(*(goptr + Einc))]; + Fgo = GOTF[(*(goptr + Finc))]; + Ggo = GOTF[(*(goptr + Ginc))]; + Hgo = GOTF[(*(goptr + Hinc))]; + } + else + { + Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + // For this sample we have do not yet have any opacity or + // shaded intensity yet + opacity = 0.0; + red_shaded_value = 0.0; + + // Now add the opacity and shaded intensity value in vertex by + // vertex. If any of the A-H have a non-transparent opacity value, + // then add its contribution to the opacity + if ( A && Ago ) + { + weight = t1*t2*t3 * A * Ago; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr) ] * + GTF[*(dptr)] + + red_s_shade[ *(nptr) ] ); + } + + if ( B && Bgo ) + { + weight = x*t2*t3 * B * Bgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Binc) ] * + GTF[*(dptr+Binc)] + + red_s_shade[ *(nptr + Binc) ] ); + } + + if ( C && Cgo ) + { + weight = t1*y*t3 * C * Cgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Cinc) ] * + GTF[*(dptr+Cinc)] + + red_s_shade[ *(nptr + Cinc) ] ); + } + + if ( D && Dgo ) + { + weight = x*y*t3 * D * Dgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Dinc) ] * + GTF[*(dptr+Dinc)] + + red_s_shade[ *(nptr + Dinc) ] ); + } + + if ( E && Ego ) + { + weight = t1*t2*z * E * Ego; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Einc) ] * + GTF[*(dptr+Einc)] + + red_s_shade[ *(nptr + Einc) ] ); + } + + if ( F && Fgo ) + { + weight = x*z*t2 * F * Fgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Finc) ] * + GTF[*(dptr+Finc)] + + red_s_shade[ *(nptr + Finc) ] ); + } + + if ( G && Ggo ) + { + weight = t1*y*z * G * Ggo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Ginc) ] * + GTF[*(dptr+Ginc)] + + red_s_shade[ *(nptr + Ginc) ] ); + } + + if ( H && Hgo ) + { + weight = x*z*y * H * Hgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Hinc) ] * + GTF[*(dptr+Hinc)] + + red_s_shade[ *(nptr + Hinc) ] ); + } + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += red_shaded_value * remaining_opacity; + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + accum_green_intensity = accum_red_intensity; + accum_blue_intensity = accum_red_intensity; + } + else if ( staticInfo->ColorChannels == 3 ) + { + // For each step along the ray + for ( loop = 0; + loop < num_steps && remaining_opacity > VTK_REMAINING_OPACITY; + loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Have we moved into a new voxel? If so we need to recompute A-H + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + offset = voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + dptr = data_ptr + offset; + nptr = encoded_normals + offset; + + A = SOTF[(*(dptr))]; + B = SOTF[(*(dptr + Binc))]; + C = SOTF[(*(dptr + Cinc))]; + D = SOTF[(*(dptr + Dinc))]; + E = SOTF[(*(dptr + Einc))]; + F = SOTF[(*(dptr + Finc))]; + G = SOTF[(*(dptr + Ginc))]; + H = SOTF[(*(dptr + Hinc))]; + + if ( !grad_op_is_constant ) + { + goptr = grad_mag_ptr + offset; + Ago = GOTF[(*(goptr))]; + Bgo = GOTF[(*(goptr + Binc))]; + Cgo = GOTF[(*(goptr + Cinc))]; + Dgo = GOTF[(*(goptr + Dinc))]; + Ego = GOTF[(*(goptr + Einc))]; + Fgo = GOTF[(*(goptr + Finc))]; + Ggo = GOTF[(*(goptr + Ginc))]; + Hgo = GOTF[(*(goptr + Hinc))]; + } + else + { + Ago = Bgo = Cgo = Dgo = Ego = Fgo = Ggo = Hgo = 1.0; + } + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + x = ray_position[0] - (float) voxel[0]; + y = ray_position[1] - (float) voxel[1]; + z = ray_position[2] - (float) voxel[2]; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + // For this sample we have do not yet have any opacity or + // shaded intensity yet + opacity = 0.0; + red_shaded_value = 0.0; + green_shaded_value = 0.0; + blue_shaded_value = 0.0; + + // Now add the opacity and shaded intensity value in vertex by + // vertex. If any of the A-H have a non-transparent opacity value, + // then add its contribution to the opacity + if ( A ) + { + weight = t1*t2*t3 * A * Ago; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr) ] * + CTF[*(dptr) * 3] + + red_s_shade[ *(nptr) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr) ] * + CTF[*(dptr) * 3 + 1] + + + green_s_shade[ *(nptr) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr) ] * + CTF[*(dptr) * 3 + 2] + + blue_s_shade[ *(nptr) ] ); + } + + if ( B ) + { + weight = x*t2*t3 * B * Bgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Binc) ] * + CTF[*(dptr+Binc) * 3] + + red_s_shade[ *(nptr + Binc) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr + Binc) ] * + CTF[*(dptr+Binc) * 3 + 1] + + green_s_shade[ *(nptr + Binc) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Binc) ] * + CTF[*(dptr+Binc) * 3 + 2] + + blue_s_shade[ *(nptr + Binc) ] ); + } + + if ( C ) + { + weight = t1*y*t3 * C * Cgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Cinc) ] * + CTF[*(dptr+Cinc) * 3] + + red_s_shade[ *(nptr + Cinc) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr + Cinc) ] * + CTF[*(dptr+Cinc) * 3 + 1] + + green_s_shade[ *(nptr + Cinc) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Cinc) ] * + CTF[*(dptr+Cinc) * 3 + 2] + + blue_s_shade[ *(nptr + Cinc) ] ); + } + + if ( D ) + { + weight = x*y*t3 * D * Dgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Dinc) ] * + CTF[*(dptr+Dinc) * 3] + + red_s_shade[ *(nptr + Dinc) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr + Dinc) ] * + CTF[*(dptr+Dinc) * 3 + 1] + + green_s_shade[ *(nptr + Dinc) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Dinc) ] * + CTF[*(dptr+Dinc) * 3 + 2] + + blue_s_shade[ *(nptr + Dinc) ] ); + } + + if ( E ) + { + weight = t1*t2*z * E * Ego; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Einc) ] * + CTF[*(dptr+Einc) * 3] + + red_s_shade[ *(nptr + Einc) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr + Einc) ] * + CTF[*(dptr+Einc) * 3 + 1] + + green_s_shade[ *(nptr + Einc) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Einc) ] * + CTF[*(dptr+Einc) * 3 + 2] + + blue_s_shade[ *(nptr + Einc) ] ); + } + + if ( F ) + { + weight = x*z*t2 * F * Fgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Finc) ] * + CTF[*(dptr+Finc) * 3] + + red_s_shade[ *(nptr + Finc) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr + Finc) ] * + CTF[*(dptr+Finc) * 3 + 1] + + green_s_shade[ *(nptr + Finc) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Finc) ] * + CTF[*(dptr+Finc) * 3 + 2] + + blue_s_shade[ *(nptr + Finc) ] ); + } + + if ( G ) + { + weight = t1*y*z * G * Ggo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Ginc) ] * + CTF[*(dptr+Ginc) * 3] + + red_s_shade[ *(nptr + Ginc) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr + Ginc) ] * + CTF[*(dptr+Ginc) * 3 + 1] + + green_s_shade[ *(nptr + Ginc) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Ginc) ] * + CTF[*(dptr+Ginc) * 3 + 2] + + blue_s_shade[ *(nptr + Ginc) ] ); + } + + if ( H ) + { + weight = x*z*y * H * Hgo; + opacity += weight; + red_shaded_value += weight * ( red_d_shade[ *(nptr + Hinc) ] * + CTF[*(dptr+Hinc) * 3] + + red_s_shade[ *(nptr + Hinc) ] ); + green_shaded_value += weight * ( green_d_shade[ *(nptr + Hinc) ] * + CTF[*(dptr+Hinc) * 3 + 1] + + green_s_shade[ *(nptr + Hinc) ] ); + blue_shaded_value += weight * ( blue_d_shade[ *(nptr + Hinc) ] * + CTF[*(dptr+Hinc) * 3 + 2] + + blue_s_shade[ *(nptr + Hinc) ] ); + } + + // Accumulate intensity and opacity for this sample location + accum_red_intensity += red_shaded_value * remaining_opacity; + accum_green_intensity += green_shaded_value * remaining_opacity; + accum_blue_intensity += blue_shaded_value * remaining_opacity; + remaining_opacity *= (1.0 - opacity); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + } + + // Cap the accumulated intensity at 1.0 + if ( accum_red_intensity > 1.0 ) + { + accum_red_intensity = 1.0; + } + if ( accum_green_intensity > 1.0 ) + { + accum_green_intensity = 1.0; + } + if ( accum_blue_intensity > 1.0 ) + { + accum_blue_intensity = 1.0; + } + + if( remaining_opacity < VTK_REMAINING_OPACITY ) + { + remaining_opacity = 0.0; + } + + // Set the return pixel value. The depth value is the distance to the + // center of the volume. + dynamicInfo->Color[0] = accum_red_intensity; + dynamicInfo->Color[1] = accum_green_intensity; + dynamicInfo->Color[2] = accum_blue_intensity; + dynamicInfo->Color[3] = 1.0 - remaining_opacity; + dynamicInfo->NumberOfStepsTaken = steps_this_ray; + + +} + +// Constructor for the vtkVolumeRayCastCompositeFunction class +vtkVolumeRayCastCompositeFunction::vtkVolumeRayCastCompositeFunction() +{ + this->CompositeMethod = VTK_COMPOSITE_INTERPOLATE_FIRST; +} + +// Destruct the vtkVolumeRayCastCompositeFunction +vtkVolumeRayCastCompositeFunction::~vtkVolumeRayCastCompositeFunction() +{ +} + +// This is called from RenderAnImage (in vtkDepthPARCMapper.cxx) +// It uses the integer data type flag that is passed in to +// determine what type of ray needs to be cast (which is handled +// by a templated function. It also uses the shading and +// interpolation types to determine which templated function +// to call. +void vtkVolumeRayCastCompositeFunction::CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + void *data_ptr; + + data_ptr = staticInfo->ScalarDataPointer; + + // Cast the ray for the data type and shading/interpolation type + if ( staticInfo->InterpolationType == VTK_NEAREST_INTERPOLATION ) + { + if ( staticInfo->Shading == 0 ) + { + // Nearest neighbor and no shading + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_NN_Unshaded( (unsigned char *)data_ptr, dynamicInfo, + staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_NN_Unshaded( (unsigned short *)data_ptr, dynamicInfo, + staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + else + { + // Nearest neighbor and shading + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_NN_Shaded( (unsigned char *)data_ptr, dynamicInfo, staticInfo); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_NN_Shaded( (unsigned short *)data_ptr, dynamicInfo, staticInfo); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + } + else + { + // Trilinear interpolation and no shading + if ( staticInfo->Shading == 0 ) + { + if ( this->CompositeMethod == VTK_COMPOSITE_INTERPOLATE_FIRST ) + { + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_TrilinSample_Unshaded( (unsigned char *)data_ptr, + dynamicInfo, staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_TrilinSample_Unshaded( (unsigned short *)data_ptr, + dynamicInfo, staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + else + { + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_TrilinVertices_Unshaded( (unsigned char *)data_ptr, + dynamicInfo, staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_TrilinVertices_Unshaded( (unsigned short *)data_ptr, + dynamicInfo, staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + } + else + { + // Trilinear interpolation and shading + if ( this->CompositeMethod == VTK_COMPOSITE_INTERPOLATE_FIRST ) + { + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_TrilinSample_Shaded( (unsigned char *)data_ptr, + dynamicInfo, staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_TrilinSample_Shaded( (unsigned short *)data_ptr, + dynamicInfo, staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + else + { + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_TrilinVertices_Shaded( (unsigned char *)data_ptr, + dynamicInfo, staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_TrilinVertices_Shaded( (unsigned short *)data_ptr, + dynamicInfo, staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + } + } +} + +float vtkVolumeRayCastCompositeFunction::GetZeroOpacityThreshold( vtkVolume + *vol ) +{ + return vol->GetProperty()->GetScalarOpacity()->GetFirstNonZeroValue(); +} + +// We don't need to do any specific initialization here... +void vtkVolumeRayCastCompositeFunction::SpecificFunctionInitialize( + vtkRenderer *vtkNotUsed(ren), + vtkVolume *vtkNotUsed(vol), + vtkVolumeRayCastStaticInfo *vtkNotUsed(staticInfo), + vtkVolumeRayCastMapper *vtkNotUsed(mapper) ) +{ +} + +// Description: +// Return the composite method as a descriptive character string. +const char *vtkVolumeRayCastCompositeFunction::GetCompositeMethodAsString(void) +{ + if( this->CompositeMethod == VTK_COMPOSITE_INTERPOLATE_FIRST ) + { + return "Interpolate First"; + } + if( this->CompositeMethod == VTK_COMPOSITE_CLASSIFY_FIRST ) + { + return "Classify First"; + } + else + { + return "Unknown"; + } +} + +// Print method for vtkVolumeRayCastCompositeFunction +// Since there is nothing local to print, just print the object stuff. +void vtkVolumeRayCastCompositeFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Composite Method: " << this->GetCompositeMethodAsString() + << "\n"; + +} + + + + + diff --git a/VolumeRendering/vtkVolumeRayCastCompositeFunction.h b/VolumeRendering/vtkVolumeRayCastCompositeFunction.h new file mode 100644 index 0000000..8d292fe --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastCompositeFunction.h @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastCompositeFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeRayCastCompositeFunction - a ray function for compositing + +// .SECTION Description +// vtkVolumeRayCastCompositeFunction is a ray function that can be used +// within a vtkVolumeRayCastMapper. This function performs compositing along +// the ray according to the properties stored in the vtkVolumeProperty for +// the volume. + +// .SECTION See Also +// vtkVolumeRayCastMapper vtkVolumeProperty vtkVolume + +#ifndef __vtkVolumeRayCastCompositeFunction_h +#define __vtkVolumeRayCastCompositeFunction_h + +#include "vtkVolumeRayCastFunction.h" + +#define VTK_COMPOSITE_CLASSIFY_FIRST 0 +#define VTK_COMPOSITE_INTERPOLATE_FIRST 1 + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeRayCastCompositeFunction : public vtkVolumeRayCastFunction +{ +public: + static vtkVolumeRayCastCompositeFunction *New(); + vtkTypeRevisionMacro(vtkVolumeRayCastCompositeFunction,vtkVolumeRayCastFunction); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set the CompositeMethod to either Classify First or Interpolate First + vtkSetClampMacro( CompositeMethod, int, + VTK_COMPOSITE_CLASSIFY_FIRST, VTK_COMPOSITE_INTERPOLATE_FIRST ); + vtkGetMacro(CompositeMethod,int); + void SetCompositeMethodToInterpolateFirst() + {this->SetCompositeMethod(VTK_COMPOSITE_INTERPOLATE_FIRST);} + void SetCompositeMethodToClassifyFirst() + {this->SetCompositeMethod(VTK_COMPOSITE_CLASSIFY_FIRST);} + const char *GetCompositeMethodAsString(void); + +//BTX + void CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo); + + float GetZeroOpacityThreshold( vtkVolume *vol ); +//ETX + +protected: + vtkVolumeRayCastCompositeFunction(); + ~vtkVolumeRayCastCompositeFunction(); + +//BTX + void SpecificFunctionInitialize( vtkRenderer *ren, + vtkVolume *vol, + vtkVolumeRayCastStaticInfo *staticInfo, + vtkVolumeRayCastMapper *mapper ); +//ETX + + int CompositeMethod; +private: + vtkVolumeRayCastCompositeFunction(const vtkVolumeRayCastCompositeFunction&); // Not implemented. + void operator=(const vtkVolumeRayCastCompositeFunction&); // Not implemented. +}; + + +#endif diff --git a/VolumeRendering/vtkVolumeRayCastFunction.cxx b/VolumeRendering/vtkVolumeRayCastFunction.cxx new file mode 100644 index 0000000..afabd9c --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastFunction.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeRayCastFunction.h" + +#include "vtkEncodedGradientEstimator.h" +#include "vtkEncodedGradientShader.h" +#include "vtkImageData.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkVolumeRayCastMapper.h" + +vtkCxxRevisionMacro(vtkVolumeRayCastFunction, "$Revision: 1.1 $"); + +// Grab everything we need for rendering now. This procedure will be called +// during the initialization phase of ray casting. It is called once per +// image. All Gets are done here for both performance and multithreading +// reentrant requirements reasons. At the end, the SpecificFunctionInitialize +// is called to give the subclass a chance to do its thing. +void vtkVolumeRayCastFunction::FunctionInitialize( + vtkRenderer *ren, + vtkVolume *vol, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + vtkVolumeRayCastMapper *mapper = + vtkVolumeRayCastMapper::SafeDownCast( vol->GetMapper() ); + + if ( !mapper ) + { + vtkErrorMacro( + "Function initialized called with a volume that does not use ray casting"); + return; + } + + // Is shading on? + staticInfo->Shading = vol->GetProperty()->GetShade(); + + // How many color channels? Either 1 or 3. 1 means we have + // to use the GrayTransferFunction, 3 means we use the + // RGBTransferFunction + staticInfo->ColorChannels = vol->GetProperty()->GetColorChannels(); + + // What is the interpolation type? Nearest or linear. + staticInfo->InterpolationType = vol->GetProperty()->GetInterpolationType(); + + // Get the size, spacing and origin of the scalar data + mapper->GetInput()->GetDimensions( staticInfo->DataSize ); + mapper->GetInput()->GetSpacing( staticInfo->DataSpacing ); + mapper->GetInput()->GetOrigin( staticInfo->DataOrigin ); + + // What are the data increments? + // (One voxel, one row, and one slice offsets) + staticInfo->DataIncrement[0] = 1; + staticInfo->DataIncrement[1] = staticInfo->DataSize[0]; + staticInfo->DataIncrement[2] = staticInfo->DataSize[0] * staticInfo->DataSize[1]; + + + // Get the encoded normals from the normal encoder in the + // volume ray cast mapper. We need to do this if shading is on + // or if we are classifying scalar value into opacity based + // on the magnitude of the gradient (since if we need to + // calculate the magnitude we might as well just keep the + // direction as well. + if ( staticInfo->Shading ) + { + staticInfo->EncodedNormals = + mapper->GetGradientEstimator()->GetEncodedNormals(); + + // Get the diffuse shading tables from the normal encoder + // in the volume ray cast mapper + staticInfo->RedDiffuseShadingTable = + mapper->GetGradientShader()->GetRedDiffuseShadingTable(vol); + staticInfo->GreenDiffuseShadingTable = + mapper->GetGradientShader()->GetGreenDiffuseShadingTable(vol); + staticInfo->BlueDiffuseShadingTable = + mapper->GetGradientShader()->GetBlueDiffuseShadingTable(vol); + + // Get the specular shading tables from the normal encoder + // in the volume ray cast mapper + staticInfo->RedSpecularShadingTable = + mapper->GetGradientShader()->GetRedSpecularShadingTable(vol); + staticInfo->GreenSpecularShadingTable = + mapper->GetGradientShader()->GetGreenSpecularShadingTable(vol); + staticInfo->BlueSpecularShadingTable = + mapper->GetGradientShader()->GetBlueSpecularShadingTable(vol); + } + else + { + staticInfo->EncodedNormals = NULL; + staticInfo->RedDiffuseShadingTable = NULL; + staticInfo->GreenDiffuseShadingTable = NULL; + staticInfo->BlueDiffuseShadingTable = NULL; + staticInfo->RedSpecularShadingTable = NULL; + staticInfo->GreenSpecularShadingTable = NULL; + staticInfo->BlueSpecularShadingTable = NULL; + } + + // We need the gradient magnitudes only if we are classifying opacity + // based on them. Otherwise we can just leave them NULL + if ( vol->GetGradientOpacityArray() && + vol->GetGradientOpacityConstant() == -1.0 ) + { + staticInfo->GradientMagnitudes = + mapper->GetGradientEstimator()->GetGradientMagnitudes(); + } + else + { + staticInfo->GradientMagnitudes = NULL; + } + + // By default the blending is not MIP - the MIP function will turn this + // on + staticInfo->MIPFunction = 0; + + // Give the subclass a chance to do any initialization it needs + // to do + this->SpecificFunctionInitialize( ren, vol, staticInfo, mapper ); +} + +//---------------------------------------------------------------------------- +void vtkVolumeRayCastFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkVolumeRayCastFunction.h b/VolumeRendering/vtkVolumeRayCastFunction.h new file mode 100644 index 0000000..a3ff05c --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastFunction.h @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkVolumeRayCastFunction - a superclass for ray casting functions + +// .SECTION Description +// vtkVolumeRayCastFunction is a superclass for ray casting functions that +// can be used within a vtkVolumeRayCastMapper. This includes for example, +// vtkVolumeRayCastCompositeFunction, vtkVolumeRayCastMIPFunction, and +// vtkVolumeRayCastIsosurfaceFunction. + +// .SECTION See Also +// vtkVolumeRayCastCompositeFunction vtkVolumeRayCastMIPFunction +// vtkVolumeRayCastIsosurfaceFunction vtkVolumeRayCastMapper + +#ifndef __vtkVolumeRayCastFunction_h +#define __vtkVolumeRayCastFunction_h + +#include "vtkObject.h" + +class vtkRenderer; +class vtkVolume; +class vtkVolumeRayCastMapper; + +// Define a couple of structures we need to hold all the important information +// This first structure hold the dynamic information - stuff that changes per +// ray +typedef struct +{ + // These are the return values - RGBA + float Color[4]; + float ScalarValue; + + // Ray information transformed into local coordinates + float TransformedStart[4]; + float TransformedEnd[4]; + float TransformedDirection[4]; + float TransformedIncrement[3]; + + // The number of steps we want to take if this is + // a ray caster that takes steps + int NumberOfStepsToTake; + + // The number of steps we actually take if this is + // a ray caster that takes steps + int NumberOfStepsTaken; + +} vtkVolumeRayCastDynamicInfo; + +// This second structure hold the static information - things that don't +// change over the whole image +typedef struct +{ + // A pointer to the volume + vtkVolume *Volume; + + // A pointer to the renderer + vtkRenderer *Renderer; + + // Matrices for switching from view to volume coordinate, and back + float WorldToVoxelsMatrix[16]; + float VoxelsToWorldMatrix[16]; + float ViewToVoxelsMatrix[16]; + + float *ClippingPlane; + int NumberOfClippingPlanes; + + // The camera thickness (distance between near and far) is necessary + // for computing sampling distance + float CameraThickness; + + // The type of the data and a pointer to it, and the information + // about its size, spacing, origin and precomputed increment + int ScalarDataType; + void *ScalarDataPointer; + int DataIncrement[3]; + int DataSize[3]; + double DataSpacing[3]; + double DataOrigin[3]; + + // Information from the vtkVolumeProperty + int Shading; + int ColorChannels; + float Color[3]; + int InterpolationType; + + // The shading tables from the vtkEncodedGradientShader + // that will be used for shading the volume. + float *RedDiffuseShadingTable; + float *GreenDiffuseShadingTable; + float *BlueDiffuseShadingTable; + float *RedSpecularShadingTable; + float *GreenSpecularShadingTable; + float *BlueSpecularShadingTable; + + // Info needed from the gradient estimator + unsigned short *EncodedNormals; + unsigned char *GradientMagnitudes; + + // Image information + int ImageInUseSize[2]; + int ImageMemorySize[2]; + int ImageViewportSize[2]; + int ImageOrigin[2]; + unsigned char *Image; + + int *RowBounds; + + // Is a MIP ray cast function in use? This will control + // how subsegments of the ray are combined when non-subvolume + // cropping is used. If maximize opacity is used, the color[3] + // value is used to find the max othersize the dynamicInfo->ScalarValue + // value is used + int MIPFunction; + int MaximizeOpacity; +} vtkVolumeRayCastStaticInfo; + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeRayCastFunction : public vtkObject +{ +public: + vtkTypeRevisionMacro(vtkVolumeRayCastFunction,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Do the basic initialization. This includes saving the parameters + // passed in into local variables, as well as grabbing some useful + // info from the volume property and normal encoder. This initialize + // routine is called once per render. It also calls the + // SpecificFunctionInitialize of the subclass function. +//BTX + void FunctionInitialize( vtkRenderer *ren, + vtkVolume *vol, + vtkVolumeRayCastStaticInfo *staticInfo ); + + virtual void CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo )=0; +//ETX + + // Description: + // Get the value below which all scalar values are considered to + // have 0 opacity. + virtual float GetZeroOpacityThreshold( vtkVolume *vol )=0; + +protected: + vtkVolumeRayCastFunction() {}; + ~vtkVolumeRayCastFunction() {}; + + // Description: + // This method gives the subclass a chance to do any special + // initialization that it may need to do +//BTX + virtual void SpecificFunctionInitialize( vtkRenderer *ren, + vtkVolume *vol, + vtkVolumeRayCastStaticInfo *staticInfo, + vtkVolumeRayCastMapper *mapper )=0; +//ETX +private: + vtkVolumeRayCastFunction(const vtkVolumeRayCastFunction&); // Not implemented. + void operator=(const vtkVolumeRayCastFunction&); // Not implemented. +}; + +#endif diff --git a/VolumeRendering/vtkVolumeRayCastIsosurfaceFunction.cxx b/VolumeRendering/vtkVolumeRayCastIsosurfaceFunction.cxx new file mode 100644 index 0000000..a123aaf --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastIsosurfaceFunction.cxx @@ -0,0 +1,1142 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastIsosurfaceFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeRayCastIsosurfaceFunction.h" + +#include "vtkCamera.h" +#include "vtkColorTransferFunction.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPiecewiseFunction.h" +#include "vtkRenderWindow.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" +#include "vtkVolumeRayCastMapper.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkVolumeRayCastIsosurfaceFunction, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkVolumeRayCastIsosurfaceFunction); + +/* Is x between y and z? */ +#define VTK_In_Range(x,y,z) ((x) >= (y) && (x) <= (z)) +#define VTK_Sign(x) (((x) < 0.0)?(-1):(1)) + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef struct +{ + int num_intersections; + float local_position[3][3]; + float local_distance[3]; +} LineIntersectInfo; + +/************************************************************************/ +/* This routine computes the intersection(s) of a vector and an */ +/* isosurface within the trilinear interpolation function. The starting */ +/* position of the vector is given in variable "start" and the direction*/ +/* of the vector is given in the variable "vec". The scalar values at */ +/* the vertices of the [0.0 <-> 1.0] cube are supplied within variables */ +/* "A"-"H" (See macro Trilin()). */ +/* */ +/* Scalar Field: */ +/* */ +/* Trilin( x, y, z, A, B, C, D, E, F, G, H ) */ +/* */ +/* Parametric Line Equation: */ +/* */ +/* x = x0 + at */ +/* y = y0 + bt */ +/* z = z0 + ct */ +/* */ +/* Isosurface Threshold Value: */ +/* */ +/* iso */ +/* */ +/* Intermediate Calculations: */ +/* */ +/* P = A - B - C + D */ +/* Q = A - C - E + G */ +/* R = A - B - E + F */ +/* S = -A + B + C - D + E - F - G + H */ +/* T = a * b * c * S */ +/* */ +/* Trilinear Interpolation With Parametric Substitutions: */ +/* */ +/* c0*t^3 + c1*t^2 + c2*t + c3 = 0 */ +/* */ +/* Where: */ +/* */ +/* c0 = a*b*c*S */ +/* */ +/* c1 = a*b*P + b*c*Q + a*c*R + (x0*b*c + a*(y0*c + z0*b))*S */ +/* */ +/* c2 = (x0*b + y0*a)*P + (y0*c + z0*b)*Q + (x0*c + z0*a)*R + */ +/* (a*y0*z0 + x0*(y0*c + z0*b))*S + */ +/* (B - A)*a + (C - A)*b + (E - A)*c */ +/* */ +/* c3 = (1.0-x0-y0-z0)*A + B*x0 + C*y0 + E*z0 + */ +/* x0*y0*P + y0*z0*Q + x0*z0*R + x0*y0*z0*S - iso */ +/* */ +/************************************************************************/ + +void trilin_line_intersection( float start[3], float vec[3], + double A, double B, double C, double D, + double E, double F, double G, double H, + double iso, LineIntersectInfo *solution ) +{ + double c0, c1, c2, c3; /* Coefficients Of Cubic Equation */ + double r1, r2, r3; /* Roots Of Equation */ + double temp; /* Swap Variable */ + int num_roots; /* Number Of Unique Roots To Equation */ + int root; /* Loops Through Roots */ + int pos_dist_num; /* Number Of Positive Distance Roots */ + + double x0, y0, z0; + double a, b, c; + double P, Q, R, S, T; + double x, y, z; + double dist = 0; + // This are used for alternative approach that is commented now + // double ab, bc, ac; + // double x0y0, y0z0, x0z0; + // double z0S; + + x0 = start[0]; + y0 = start[1]; + z0 = start[2]; + + a = vec[0]; + b = vec[1]; + c = vec[2]; + + /* Precision problem - this quantizes the ray direction */ + /* which keeps c0 from becoming too small */ + a = (float)((int)(a * 100000.0))/100000.0; + b = (float)((int)(b * 100000.0))/100000.0; + c = (float)((int)(c * 100000.0))/100000.0; + + P = A - B - C + D; + Q = A - C - E + G; + R = A - B - E + F; + S = -A + B + C - D + E - F - G + H; + T = a * b * c * S; + + /* Initialize the Number Of Intersections To Zero */ + solution->num_intersections = 0; + + /* 41 mults & 30 adds */ + c0 = T; + + c1 = (a*b*P + b*c*Q + a*c*R + (x0*b*c + a*(y0*c + z0*b))*S); + + c2 = ( (x0*b + y0*a)*P + (y0*c + z0*b)*Q + (x0*c + z0*a)*R + + (a*y0*z0 + x0*(y0*c + z0*b))*S + + (B - A)*a + (C - A)*b + (E - A)*c + ); + + c3 = ( (1.0-x0-y0-z0)*A + B*x0 + C*y0 + E*z0 + + x0*y0*P + y0*z0*Q + x0*z0*R + x0*y0*z0*S - iso + ); + + /* 36 mults & 28 adds */ + /*** + ab = a * b; + bc = b * c; + ac = a * c; + + x0y0 = x0 * y0; + y0z0 = y0 * z0; + x0z0 = x0 * z0; + + z0S = z0 * S; + + c0 = T; + + c1 = (ab*P + bc*Q + ac*R + (x0*bc + y0*ac)*S + z0S*ab); + + c2 = ( (x0*b + y0*a)*P + (y0*c + z0*b)*Q + (x0*c + z0*a)*R + + (a*y0z0 + x0y0*c + x0z0*b)*S + + (B - A)*a + (C - A)*b + (E - A)*c + ); + + c3 = ( (1.0-x0-y0-z0)*A + B*x0 + C*y0 + E*z0 + + x0y0*P + y0z0*Q + x0z0*R + x0y0*z0S - iso + ); + + ****/ + if ( (c0 >= 0.0 && c1 >= 0.0 && c2 >= 0.0 && c3 >= 0.0) + || (c0 <= 0.0 && c1 <= 0.0 && c2 <= 0.0 && c3 <= 0.0)) + { + return; + } + + vtkMath::SolveCubic( c0, c1, c2, c3, &r1, &r2, &r3, &num_roots ); + + /* Remove Negative Solutions And Store In Distance Array */ + pos_dist_num = 0; + for( root=0; root < num_roots; root++ ) + { + switch( root ) + { + case 0: + dist = r1; + break; + case 1: + dist = r2; + break; + case 2: + dist = r3; + } + + if( dist >= 0.0 ) + { + solution->local_distance[pos_dist_num] = dist; + pos_dist_num += 1; + } + } + + solution->num_intersections = pos_dist_num; + + /* Sort The Solutions Based On Distance */ + if( pos_dist_num == 2 ) + { + if( solution->local_distance[0] > solution->local_distance[1] ) + { + temp = solution->local_distance[0]; + solution->local_distance[0] = solution->local_distance[1]; + solution->local_distance[1] = temp; + } + } + else if( pos_dist_num == 3 ) + { + if( solution->local_distance[0] > solution->local_distance[1] ) + { + temp = solution->local_distance[0]; + solution->local_distance[0] = solution->local_distance[1]; + solution->local_distance[1] = temp; + } + if( solution->local_distance[1] > solution->local_distance[2] ) + { + temp = solution->local_distance[1]; + solution->local_distance[1] = solution->local_distance[2]; + solution->local_distance[2] = temp; + } + if( solution->local_distance[0] > solution->local_distance[1] ) + { + temp = solution->local_distance[0]; + solution->local_distance[0] = solution->local_distance[1]; + solution->local_distance[1] = temp; + } + } + + for( root=0; root < solution->num_intersections; root++ ) + { + /**********************************************/ + /* Determine The (x,y,z) Position Of Solution */ + /**********************************************/ + x = x0 + a * solution->local_distance[root]; + y = y0 + b * solution->local_distance[root]; + z = z0 + c * solution->local_distance[root]; + + solution->local_position[root][0] = x; + solution->local_position[root][1] = y; + solution->local_position[root][2] = z; + } +} + +// This is the templated function that actually casts a ray and computes +// the pixel_value for isosurface-ray intersection. It is valid for +// unsigned char, unsigned short, short, int and float data. +template <class T> +void vtkCastRay_NN ( vtkVolumeRayCastIsosurfaceFunction *cast_function, + T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + + unsigned short *encoded_normals; + int xinc, yinc, zinc; + int voxel_x, voxel_y, voxel_z; + int end_voxel_x, end_voxel_y, end_voxel_z; + int x_voxels, y_voxels, z_voxels; + int found_intersection; + int tstep_x, tstep_y, tstep_z; + int offset; + int steps_this_ray = 0; + T A; + T *dptr; + float ray_position_x, ray_position_y, ray_position_z; + float ray_end[3]; + float ray_direction_x, ray_direction_y, ray_direction_z; + float tmax_x, tmax_y, tmax_z, + tdelta_x, tdelta_y, tdelta_z; + float isovalue; + float *red_d_shade, *green_d_shade, *blue_d_shade; + float *red_s_shade, *green_s_shade, *blue_s_shade; + int num_steps; + float *ray_start, *ray_increment; + float r, g, b; + float volumeRed, volumeGreen, volumeBlue; + + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + dynamicInfo->Color[0] = 0.0; + dynamicInfo->Color[1] = 0.0; + dynamicInfo->Color[2] = 0.0; + dynamicInfo->Color[3] = 0.0; + dynamicInfo->NumberOfStepsTaken = 0; + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position_x = ray_start[0]; + ray_position_y = ray_start[1]; + ray_position_z = ray_start[2]; + + voxel_x = vtkFloorFuncMacro( ray_position_x ); + voxel_y = vtkFloorFuncMacro( ray_position_y ); + voxel_z = vtkFloorFuncMacro( ray_position_z ); + + ray_end[0] = ray_start[0] + num_steps*ray_increment[0]; + ray_end[1] = ray_start[1] + num_steps*ray_increment[1]; + ray_end[2] = ray_start[2] + num_steps*ray_increment[2]; + + ray_direction_x = ray_increment[0]; + ray_direction_y = ray_increment[1]; + ray_direction_z = ray_increment[2]; + + x_voxels = staticInfo->DataSize[0]; + y_voxels = staticInfo->DataSize[1]; + z_voxels = staticInfo->DataSize[2]; + + if ( voxel_x >= x_voxels - 1 || + voxel_y >= y_voxels - 1 || + voxel_z >= z_voxels - 1 || + voxel_x < 0 || voxel_y < 0 || voxel_z < 0 ) + { + return; + } + + // Set the local variable to be isovalue for the surface + isovalue = cast_function->IsoValue; + + tstep_x = VTK_Sign( ray_direction_x ); + tstep_y = VTK_Sign( ray_direction_y ); + tstep_z = VTK_Sign( ray_direction_z ); + + end_voxel_x = (int)ray_end[0] + tstep_x; + end_voxel_y = (int)ray_end[1] + tstep_y; + end_voxel_z = (int)ray_end[2] + tstep_z; + + if (ray_direction_x != 0.0) + { + tmax_x = fabs((float)((voxel_x+(tstep_x==1)) - ray_position_x) / + ray_direction_x); + tdelta_x = fabs(1.0 / ray_direction_x); + } + else + { + tmax_x = VTK_LARGE_FLOAT; + tdelta_x = VTK_LARGE_FLOAT; + } + + if (ray_direction_y != 0.0) + { + tmax_y = fabs((float)((voxel_y+(tstep_y==1)) - ray_position_y) / + ray_direction_y); + tdelta_y = fabs(1.0 / ray_direction_y); + } + else + { + tmax_y = VTK_LARGE_FLOAT; + tdelta_y = VTK_LARGE_FLOAT; + } + + if (ray_direction_z != 0.0) + { + tmax_z = fabs((float)((voxel_z+(tstep_z==1)) - ray_position_z) / + ray_direction_z); + tdelta_z = fabs(1.0 / ray_direction_z); + } + else + { + tmax_z = VTK_LARGE_FLOAT; + tdelta_z = VTK_LARGE_FLOAT; + } + + dptr = data_ptr + + voxel_x * xinc + + voxel_y * yinc + + voxel_z * zinc; + + A = *(dptr); + + found_intersection = FALSE; + + while ( found_intersection == FALSE ) + { + // We've taken another step + steps_this_ray++; + + if ( A >= isovalue ) + { + found_intersection = TRUE; + + volumeRed = staticInfo->Color[0]; + volumeGreen = staticInfo->Color[1]; + volumeBlue = staticInfo->Color[2]; + + if ( staticInfo->Shading ) + { + // Get diffuse shading table pointers + red_d_shade = staticInfo->RedDiffuseShadingTable; + green_d_shade = staticInfo->GreenDiffuseShadingTable; + blue_d_shade = staticInfo->BlueDiffuseShadingTable; + + // Get specular shading table pointers + red_s_shade = staticInfo->RedSpecularShadingTable; + green_s_shade = staticInfo->GreenSpecularShadingTable; + blue_s_shade = staticInfo->BlueSpecularShadingTable; + + // Get a pointer to the encoded normals for this volume + encoded_normals = staticInfo->EncodedNormals; + + + // Set up the offset into the normal array + offset = voxel_z * zinc + voxel_y * yinc + voxel_x; + + // Set the return pixel value. This should be corrected later; + // + r = red_d_shade[*(encoded_normals + offset)] + * volumeRed + red_s_shade[*(encoded_normals + offset)]; + g = green_d_shade[*(encoded_normals + offset)] + * volumeGreen + green_s_shade[*(encoded_normals + offset)]; + b = blue_d_shade[*(encoded_normals + offset)] + * volumeBlue + blue_s_shade[*(encoded_normals + offset)]; + + dynamicInfo->Color[0] = ( r > 1.0 ) ? 1.0 : r; + dynamicInfo->Color[1] = ( g > 1.0 ) ? 1.0 : g; + dynamicInfo->Color[2] = ( b > 1.0 ) ? 1.0 : b; + dynamicInfo->Color[3] = 1.0; + } + else + { + // No shading + dynamicInfo->Color[0] = volumeRed; + dynamicInfo->Color[1] = volumeGreen; + dynamicInfo->Color[2] = volumeBlue; + dynamicInfo->Color[3] = 1.0; + } + } + + if ( found_intersection == FALSE ) + { + if (tmax_x < tmax_y) + { + if (tmax_x < tmax_z) + { + voxel_x += tstep_x; + + if (voxel_x < 0 || voxel_x >= x_voxels-1 + || voxel_x == end_voxel_x ) + { + found_intersection = TRUE; + } + else + { + tmax_x += tdelta_x; + dptr += tstep_x * xinc; + A = *dptr; + } + } + else + { + voxel_z += tstep_z; + + if (voxel_z < 0 || voxel_z >= z_voxels-1 + || voxel_z == end_voxel_z ) + { + found_intersection = TRUE; + } + else + { + tmax_z += tdelta_z; + dptr += tstep_z * zinc; + A = *dptr; + } + } + } + else + { + if (tmax_y < tmax_z) + { + voxel_y += tstep_y; + + if (voxel_y < 0 || voxel_y >= y_voxels-1 + || voxel_y == end_voxel_y ) + { + found_intersection = TRUE; + } + else + { + tmax_y += tdelta_y; + dptr += tstep_y * yinc; + A = *dptr; + } + } + else + { + voxel_z += tstep_z; + + if (voxel_z < 0 || voxel_z >= z_voxels-1 + || voxel_z == end_voxel_z ) + { + found_intersection = TRUE; + } + else + { + tmax_z += tdelta_z; + dptr += tstep_z * zinc; + A = *dptr; + } + } + } + } + } + + dynamicInfo->NumberOfStepsTaken = steps_this_ray; + +} +// This is the templated function that actually casts a ray and computes +// the pixel_value for isosurface-ray intersection. It is valid for +// unsigned char, unsigned short, short, int and float data. +template <class T> +void vtkCastRay_Trilin ( vtkVolumeRayCastIsosurfaceFunction *cast_function, + T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + LineIntersectInfo line_info; + unsigned short *encoded_normals, *nptr; + int loop; + int xinc, yinc, zinc; + int voxel_x, voxel_y, voxel_z; + int end_voxel_x, end_voxel_y, end_voxel_z; + int x_voxels, y_voxels, z_voxels; + int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc; + int found_intersection; + int tstep_x, tstep_y, tstep_z; + int offset; + int steps_this_ray = 0; + T A, B, C, D, E, F, G, H; + T *dptr; + float ray_position_x, ray_position_y, ray_position_z; + float ray_end[3]; + float ray_direction_x, ray_direction_y, ray_direction_z; + float tmax_x, tmax_y, tmax_z, + tdelta_x, tdelta_y, tdelta_z; + float isovalue; + float trilin_origin[3]; + float point_x = 0, point_y = 0, point_z = 0; + float *red_d_shade, *green_d_shade, *blue_d_shade; + float *red_s_shade, *green_s_shade, *blue_s_shade; + float x, y, z, t1, t2, t3; + float tA, tB, tC, tD, tE, tF, tG, tH; + float red_shaded_value, green_shaded_value, blue_shaded_value; + int num_steps; + float *ray_start, *ray_increment; + float volumeRed, volumeGreen, volumeBlue; + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + dynamicInfo->Color[0] = 0.0; + dynamicInfo->Color[1] = 0.0; + dynamicInfo->Color[2] = 0.0; + dynamicInfo->Color[3] = 0.0; + dynamicInfo->NumberOfStepsTaken = 0; + + // Move the increments into local variables + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position_x = ray_start[0]; + ray_position_y = ray_start[1]; + ray_position_z = ray_start[2]; + + voxel_x = vtkFloorFuncMacro( ray_position_x ); + voxel_y = vtkFloorFuncMacro( ray_position_y ); + voxel_z = vtkFloorFuncMacro( ray_position_z ); + + ray_end[0] = ray_start[0] + num_steps*ray_increment[0]; + ray_end[1] = ray_start[1] + num_steps*ray_increment[1]; + ray_end[2] = ray_start[2] + num_steps*ray_increment[2]; + + ray_direction_x = ray_increment[0]; + ray_direction_y = ray_increment[1]; + ray_direction_z = ray_increment[2]; + + x_voxels = staticInfo->DataSize[0]; + y_voxels = staticInfo->DataSize[1]; + z_voxels = staticInfo->DataSize[2]; + + if ( voxel_x >= x_voxels - 1 || + voxel_y >= y_voxels - 1 || + voxel_z >= z_voxels - 1 || + voxel_x < 0 || voxel_y < 0 || voxel_z < 0 ) + { + return; + } + + // Set the local variable to be isovalue for the surface + isovalue = cast_function->IsoValue; + + tstep_x = VTK_Sign( ray_direction_x ); + tstep_y = VTK_Sign( ray_direction_y ); + tstep_z = VTK_Sign( ray_direction_z ); + + end_voxel_x = (int)ray_end[0] + tstep_x; + end_voxel_y = (int)ray_end[1] + tstep_y; + end_voxel_z = (int)ray_end[2] + tstep_z; + + if (ray_direction_x != 0.0) + { + tmax_x = fabs((float)((voxel_x+(tstep_x==1)) - ray_position_x) / + ray_direction_x); + tdelta_x = fabs(1.0 / ray_direction_x); + } + else + { + tmax_x = VTK_LARGE_FLOAT; + tdelta_x = VTK_LARGE_FLOAT; + } + + if (ray_direction_y != 0.0) + { + tmax_y = fabs((float)((voxel_y+(tstep_y==1)) - ray_position_y) / + ray_direction_y); + tdelta_y = fabs(1.0 / ray_direction_y); + } + else + { + tmax_y = VTK_LARGE_FLOAT; + tdelta_y = VTK_LARGE_FLOAT; + } + + if (ray_direction_z != 0.0) + { + tmax_z = fabs((float)((voxel_z+(tstep_z==1)) - ray_position_z) / + ray_direction_z); + tdelta_z = fabs(1.0 / ray_direction_z); + } + else + { + tmax_z = VTK_LARGE_FLOAT; + tdelta_z = VTK_LARGE_FLOAT; + } + + dptr = data_ptr + + voxel_x * xinc + + voxel_y * yinc + + voxel_z * zinc; + + // Compute the increments to get to the other 7 voxel vertices from A + Binc = xinc; + Cinc = yinc; + Dinc = xinc + yinc; + Einc = zinc; + Finc = zinc + xinc; + Ginc = zinc + yinc; + Hinc = zinc + xinc + yinc; + + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + found_intersection = FALSE; + + while ( found_intersection == FALSE ) + { + + // We've taken another step + steps_this_ray++; + + if ( ( A >= isovalue || B >= isovalue || C >= isovalue || + D >= isovalue || E >= isovalue || F >= isovalue || + G >= isovalue || H >= isovalue) + && ( A <= isovalue || B <= isovalue || C <= isovalue || + D <= isovalue || E <= isovalue || F <= isovalue || + G <= isovalue || H <= isovalue ) ) + { + trilin_origin[0] = ray_start[0] - voxel_x; + trilin_origin[1] = ray_start[1] - voxel_y; + trilin_origin[2] = ray_start[2] - voxel_z; + + trilin_line_intersection + ( trilin_origin, ray_increment, + (double) A, (double) B, (double) C, (double) D, + (double) E, (double) F, (double) G, (double) H, + (double) isovalue, &line_info ); + + if ( line_info.num_intersections > 0 ) + { + + for (loop=0; loop<line_info.num_intersections; + loop++) + { + point_x = line_info.local_position[loop][0] + voxel_x; + point_y = line_info.local_position[loop][1] + voxel_y; + point_z = line_info.local_position[loop][2] + voxel_z; + + if ((VTK_In_Range(point_x, ((float)(voxel_x) - 0.001 ), ((float)(voxel_x) + 1.001))) && + (VTK_In_Range(point_y, ((float)(voxel_y) - 0.001 ), ((float)(voxel_y) + 1.001))) && + (VTK_In_Range(point_z, ((float)(voxel_z) - 0.001 ), ((float)(voxel_z) + 1.001)))) + { + break; + } + } + + if ( loop < line_info.num_intersections ) + { + found_intersection = TRUE; + + volumeRed = staticInfo->Color[0]; + volumeGreen = staticInfo->Color[1]; + volumeBlue = staticInfo->Color[2]; + + if ( staticInfo->Shading ) + { + // Get diffuse shading table pointers + red_d_shade = staticInfo->RedDiffuseShadingTable; + green_d_shade = staticInfo->GreenDiffuseShadingTable; + blue_d_shade = staticInfo->BlueDiffuseShadingTable; + + + // Get diffuse shading table pointers + red_s_shade = staticInfo->RedSpecularShadingTable; + green_s_shade = staticInfo->GreenSpecularShadingTable; + blue_s_shade = staticInfo->BlueSpecularShadingTable; + + // Get a pointer to the encoded normals for this volume + encoded_normals = staticInfo->EncodedNormals; + + // Get the opacity transfer function which maps scalar input values + + // Compute the values for the first pass through the loop + offset = voxel_z * zinc + voxel_y * yinc + voxel_x; + dptr = data_ptr + offset; + nptr = encoded_normals + offset; + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + x = point_x - voxel_x; + y = point_y - voxel_y; + z = point_z - voxel_z; + + t1 = 1.0 - x; + t2 = 1.0 - y; + t3 = 1.0 - z; + + tA = t1*t2*t3; + tB = x*t2*t3; + tC = t1*y*t3; + tD = x*y*t3; + tE = t1*t2*z; + tF = x*z*t2; + tG = t1*y*z; + tH = x*z*y; + + // Compute pixel_value; + // Do trilinear interpolation of shadings of pixel corners + // Do it for red, green, and blue components + red_shaded_value = + tA * ( red_d_shade[ *(nptr) ] * volumeRed + + red_s_shade[ *(nptr) ] ); + red_shaded_value += + tB * ( red_d_shade[ *(nptr + Binc) ] * volumeRed + + red_s_shade[ *(nptr + Binc) ] ); + red_shaded_value += + tC * ( red_d_shade[ *(nptr + Cinc) ] * volumeRed + + red_s_shade[ *(nptr + Cinc) ] ); + red_shaded_value += + tD * ( red_d_shade[ *(nptr + Dinc) ] * volumeRed + + red_s_shade[ *(nptr + Dinc) ] ); + red_shaded_value += + tE * ( red_d_shade[ *(nptr + Einc) ] * volumeRed + + red_s_shade[ *(nptr + Einc) ] ); + red_shaded_value += + tF * ( red_d_shade[ *(nptr + Finc) ] * volumeRed + + red_s_shade[ *(nptr + Finc) ] ); + red_shaded_value += + tG * ( red_d_shade[ *(nptr + Ginc) ] * volumeRed + + red_s_shade[ *(nptr + Ginc) ] ); + red_shaded_value += + tH * ( red_d_shade[ *(nptr + Hinc) ] * volumeRed + + red_s_shade[ *(nptr + Hinc) ] ); + + green_shaded_value = + tA * ( green_d_shade[ *(nptr) ] * volumeGreen + + green_s_shade[ *(nptr) ] ); + green_shaded_value += + tB * ( green_d_shade[ *(nptr + Binc) ] * volumeGreen + + green_s_shade[ *(nptr + Binc) ] ); + green_shaded_value += + tC * ( green_d_shade[ *(nptr + Cinc) ] * volumeGreen + + green_s_shade[ *(nptr + Cinc) ] ); + green_shaded_value += + tD * ( green_d_shade[ *(nptr + Dinc) ] * volumeGreen + + green_s_shade[ *(nptr + Dinc) ] ); + green_shaded_value += + tE * ( green_d_shade[ *(nptr + Einc) ] * volumeGreen + + green_s_shade[ *(nptr + Einc) ] ); + green_shaded_value += + tF * ( green_d_shade[ *(nptr + Finc) ] * volumeGreen + + green_s_shade[ *(nptr + Finc) ] ); + green_shaded_value += + tG * ( green_d_shade[ *(nptr + Ginc) ] * volumeGreen + + green_s_shade[ *(nptr + Ginc) ] ); + green_shaded_value += + tH * ( green_d_shade[ *(nptr + Hinc) ] * volumeGreen + + green_s_shade[ *(nptr + Hinc) ] ); + + blue_shaded_value = + tA * ( blue_d_shade[ *(nptr) ] * volumeBlue + + blue_s_shade[ *(nptr) ] ); + blue_shaded_value += + tB * ( blue_d_shade[ *(nptr + Binc) ] * volumeBlue + + blue_s_shade[ *(nptr + Binc) ] ); + blue_shaded_value += + tC * ( blue_d_shade[ *(nptr + Cinc) ] * volumeBlue + + blue_s_shade[ *(nptr + Cinc) ] ); + blue_shaded_value += + tD * ( blue_d_shade[ *(nptr + Dinc) ] * volumeBlue + + blue_s_shade[ *(nptr + Dinc) ] ); + blue_shaded_value += + tE * ( blue_d_shade[ *(nptr + Einc) ] * volumeBlue + + blue_s_shade[ *(nptr + Einc) ] ); + blue_shaded_value += + tF * ( blue_d_shade[ *(nptr + Finc) ] * volumeBlue + + blue_s_shade[ *(nptr + Finc) ] ); + blue_shaded_value += + tG * ( blue_d_shade[ *(nptr + Ginc) ] * volumeBlue + + blue_s_shade[ *(nptr + Ginc) ] ); + blue_shaded_value += + tH * ( blue_d_shade[ *(nptr + Hinc) ] * volumeBlue + + blue_s_shade[ *(nptr + Hinc) ] ); + + dynamicInfo->Color[0] = + ( red_shaded_value > 1.0 ) ? 1.0 : red_shaded_value; + dynamicInfo->Color[1] = + ( green_shaded_value > 1.0 ) ? 1.0 : green_shaded_value; + dynamicInfo->Color[2] = + ( blue_shaded_value > 1.0 ) ? 1.0 : blue_shaded_value; + dynamicInfo->Color[3] = 1.0; + } + else + { + // No shading + dynamicInfo->Color[0] = volumeRed; + dynamicInfo->Color[1] = volumeGreen; + dynamicInfo->Color[2] = volumeBlue; + dynamicInfo->Color[3] = 1.0; + } + } + } + } + if ( found_intersection == FALSE ) + { + if (tmax_x < tmax_y) + { + if (tmax_x < tmax_z) + { + voxel_x += tstep_x; + + if (voxel_x < 0 || voxel_x >= x_voxels-1 + || voxel_x == end_voxel_x ) + { + found_intersection = TRUE; + } + else + { + tmax_x += tdelta_x; + dptr += tstep_x * xinc; + if (tstep_x > 0) + { + A = B; + C = D; + E = F; + G = H; + B = *(dptr + Binc); + D = *(dptr + Dinc); + F = *(dptr + Finc); + H = *(dptr + Hinc); + } + else + { + B = A; + D = C; + F = E; + H = G; + A = *(dptr); + C = *(dptr + Cinc); + E = *(dptr + Einc); + G = *(dptr + Ginc); + } + } + } + else + { + voxel_z += tstep_z; + + if (voxel_z < 0 || voxel_z >= z_voxels-1 + || voxel_z == end_voxel_z ) + { + found_intersection = TRUE; + } + else + { + tmax_z += tdelta_z; + dptr += tstep_z * zinc; + if (tstep_z > 0) + { + A = E; + B = F; + C = G; + D = H; + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + } + else + { + E = A; + F = B; + G = C; + H = D; + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + } + } + } + } + else + { + if (tmax_y < tmax_z) + { + voxel_y += tstep_y; + + if (voxel_y < 0 || voxel_y >= y_voxels-1 + || voxel_y == end_voxel_y ) + { + found_intersection = TRUE; + } + else + { + tmax_y += tdelta_y; + dptr += tstep_y * yinc; + if (tstep_y > 0) + { + A = C; + B = D; + E = G; + F = H; + C = *(dptr + Cinc); + D = *(dptr + Dinc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + } + else + { + C = A; + D = B; + G = E; + H = F; + A = *(dptr); + B = *(dptr + Binc); + E = *(dptr + Einc); + F = *(dptr + Finc); + } + } + } + else + { + voxel_z += tstep_z; + + if (voxel_z < 0 || voxel_z >= z_voxels-1 + || voxel_z == end_voxel_z ) + { + found_intersection = TRUE; + } + else + { + tmax_z += tdelta_z; + dptr += tstep_z * zinc; + if (tstep_z > 0) + { + A = E; + B = F; + C = G; + D = H; + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + } + else + { + E = A; + F = B; + G = C; + H = D; + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + } + } + } + } + } + } + + dynamicInfo->NumberOfStepsTaken = steps_this_ray; +} + +// Construct a new vtkVolumeRayCastIsosurfaceFunction with a default ramp. +// This ramp is best suited for unsigned char data and should +// probably be modified before rendering any other data type. +// The ParcBuildValue is set to LinearRampRange[0] + 1, ensuring +// that the Parc structure will be built during the first render. +vtkVolumeRayCastIsosurfaceFunction::vtkVolumeRayCastIsosurfaceFunction() +{ + this->IsoValue = 0; +} + +// Destruct the vtkVolumeRayCastIsosurfaceFunction +vtkVolumeRayCastIsosurfaceFunction::~vtkVolumeRayCastIsosurfaceFunction() +{ +} + +// This is called from RenderAnImage (in vtkDepthPARCMapper.cxx) +// It uses the integer data type flag that is passed in to +// determine what type of ray needs to be cast (which is handled +// by a templated function. +void vtkVolumeRayCastIsosurfaceFunction::CastRay( + vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + void *data_ptr; + + data_ptr = staticInfo->ScalarDataPointer; + + // Cast the ray for the data type and shading/interpolation type + if ( staticInfo->InterpolationType == VTK_NEAREST_INTERPOLATION ) + { + // Nearest neighbor + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_NN + ( this, (unsigned char *)data_ptr, dynamicInfo, staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_NN + ( this, (unsigned short *)data_ptr, dynamicInfo, staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + else if ( staticInfo->InterpolationType == VTK_LINEAR_INTERPOLATION ) + { + // Trilinear interpolation + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastRay_Trilin + ( this, (unsigned char *)data_ptr, dynamicInfo, staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastRay_Trilin + ( this, (unsigned short *)data_ptr, dynamicInfo, staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } +} + +float vtkVolumeRayCastIsosurfaceFunction::GetZeroOpacityThreshold(vtkVolume *) +{ + return( this->IsoValue ); +} + +void vtkVolumeRayCastIsosurfaceFunction::SpecificFunctionInitialize( + vtkRenderer *vtkNotUsed(ren), + vtkVolume *vol, + vtkVolumeRayCastStaticInfo *staticInfo, + vtkVolumeRayCastMapper *vtkNotUsed(mapper) ) +{ + vtkVolumeProperty *volume_property; + + volume_property = vol->GetProperty(); + + if ( volume_property->GetColorChannels() == 1 ) + { + staticInfo->Color[0] = + volume_property->GetGrayTransferFunction()->GetValue( this->IsoValue ); + staticInfo->Color[1] = staticInfo->Color[0]; + staticInfo->Color[2] = staticInfo->Color[0]; + } + else if ( volume_property->GetColorChannels() == 3 ) + { + staticInfo->Color[0] = + volume_property->GetRGBTransferFunction()->GetRedValue( this->IsoValue ); + staticInfo->Color[1] = + volume_property->GetRGBTransferFunction()->GetGreenValue( this->IsoValue ); + staticInfo->Color[2] = + volume_property->GetRGBTransferFunction()->GetBlueValue( this->IsoValue ); + } +} + +// Print method for vtkVolumeRayCastIsosurfaceFunction +void vtkVolumeRayCastIsosurfaceFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Isosurface Value: " << this->IsoValue << "\n"; +} + + diff --git a/VolumeRendering/vtkVolumeRayCastIsosurfaceFunction.h b/VolumeRendering/vtkVolumeRayCastIsosurfaceFunction.h new file mode 100644 index 0000000..4d15315 --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastIsosurfaceFunction.h @@ -0,0 +1,82 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastIsosurfaceFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeRayCastIsosurfaceFunction - An isosurface ray caster for volumes +// +// .SECTION Description +// vtkVolumeRayCastIsosurfaceFunction is a volume ray cast function that +// intersects a ray with an analytic isosurface in a scalar field. The color +// and shading parameters are defined in the vtkVolumeProperty of the +// vtkVolume, as well as the interpolation type to use when locating the +// surface (either a nearest neighbor approach or a tri-linear interpolation +// approach) +// +// .SECTION See Also +// vtkVolumeRayCastFunction vtkVolumeRayCastMapper vtkVolumeProperty +// vtkVolumeRayCastCompositeFunction vtkVolumeRayCastMIPFunction +// vtkVolume vtkVolumeProperty + +#ifndef __vtkVolumeRayCastIsosurfaceFunction_h +#define __vtkVolumeRayCastIsosurfaceFunction_h + +#include "vtkVolumeRayCastFunction.h" + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeRayCastIsosurfaceFunction : public vtkVolumeRayCastFunction +{ +public: + vtkTypeRevisionMacro(vtkVolumeRayCastIsosurfaceFunction,vtkVolumeRayCastFunction); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Construct a new vtkVolumeRayCastIsosurfaceFunction + static vtkVolumeRayCastIsosurfaceFunction *New(); + + // Description: + // Get the scalar value below which all scalar values have 0 opacity + float GetZeroOpacityThreshold( vtkVolume *vol ); + + // Description: + // Set/Get the value of IsoValue. + vtkSetMacro( IsoValue, double ); + vtkGetMacro( IsoValue, double ); + + + // Description: + // This is the isovalue at which to view a surface + double IsoValue; + + // Description: + // These variables are filled in by SpecificFunctionInitialize + float Color[3]; + +//BTX + void CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo); +//ETX + +protected: + vtkVolumeRayCastIsosurfaceFunction(); + ~vtkVolumeRayCastIsosurfaceFunction(); + +//BTX + void SpecificFunctionInitialize( vtkRenderer *ren, + vtkVolume *vol, + vtkVolumeRayCastStaticInfo *staticInfo, + vtkVolumeRayCastMapper *mapper ); +//ETX +private: + vtkVolumeRayCastIsosurfaceFunction(const vtkVolumeRayCastIsosurfaceFunction&); // Not implemented. + void operator=(const vtkVolumeRayCastIsosurfaceFunction&); // Not implemented. +}; +#endif diff --git a/VolumeRendering/vtkVolumeRayCastMIPFunction.cxx b/VolumeRendering/vtkVolumeRayCastMIPFunction.cxx new file mode 100644 index 0000000..9416d32 --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastMIPFunction.cxx @@ -0,0 +1,539 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastMIPFunction.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeRayCastMIPFunction.h" +#include "vtkVolumeRayCastMapper.h" +#include "vtkVolume.h" +#include "vtkObjectFactory.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkVolumeRayCastMIPFunction, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkVolumeRayCastMIPFunction); + +// This is the templated function that actually casts a ray and computes +// the maximum value. It is valid for unsigned char and unsigned short, +template <class T> +void vtkCastMaxScalarValueRay( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + float triMax, triValue; + int max = 0;; + float max_opacity; + int loop; + int xinc, yinc, zinc; + int voxel[3], prev_voxel[3]; + float ray_position[3]; + T A, B, C, D, E, F, G, H; + float t00, t01, t10, t11, t0, t1; + int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc; + float xoff, yoff, zoff; + T *dptr; + int num_steps; + float *ray_increment; + float *grayArray, *RGBArray; + float *scalarArray; + T nnValue, nnMax; + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_increment = dynamicInfo->TransformedIncrement; + + grayArray = staticInfo->Volume->GetGrayArray(); + RGBArray = staticInfo->Volume->GetRGBArray(); + scalarArray = staticInfo->Volume->GetScalarOpacityArray(); + + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + memcpy( ray_position, dynamicInfo->TransformedStart, 3*sizeof(float) ); + + // If we have nearest neighbor interpolation + if ( staticInfo->InterpolationType == VTK_NEAREST_INTERPOLATION ) + { + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + + // Access the value at this voxel location + nnMax = *(data_ptr + voxel[2] * zinc + + voxel[1] * yinc + voxel[0] ); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + + // For each step along the ray + for ( loop = 1; loop < num_steps; loop++ ) + { + // Access the value at this voxel location + nnValue = *(data_ptr + voxel[2] * zinc + + voxel[1] * yinc + voxel[0] ); + + // If this is greater than the max, this is the new max. + if ( nnValue > nnMax ) + { + nnMax = nnValue; + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + } + max = (int)nnMax; + } + // We are using trilinear interpolation + else if ( staticInfo->InterpolationType == VTK_LINEAR_INTERPOLATION ) + { + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + + // Compute the increments to get to the other 7 voxel vertices from A + Binc = xinc; + Cinc = yinc; + Dinc = xinc + yinc; + Einc = zinc; + Finc = zinc + xinc; + Ginc = zinc + yinc; + Hinc = zinc + xinc + yinc; + + // Set values for the first pass through the loop + dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + xoff = ray_position[0] - (float) voxel[0]; + yoff = ray_position[1] - (float) voxel[1]; + zoff = ray_position[2] - (float) voxel[2]; + vtkTrilinFuncMacro( triMax, xoff, yoff, zoff, A, B, C, D, E, F, G, H ); + + // Keep the voxel location so that we know when we've moved into a + // new voxel + memcpy( prev_voxel, voxel, 3*sizeof(int) ); + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + + // For each step along the ray + for ( loop = 1; loop < num_steps; loop++ ) + { + // Have we moved into a new voxel? If so we need to recompute A-H + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + memcpy( prev_voxel, voxel, 3*sizeof(int) ); + } + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + xoff = ray_position[0] - (float) voxel[0]; + yoff = ray_position[1] - (float) voxel[1]; + zoff = ray_position[2] - (float) voxel[2]; + vtkTrilinFuncMacro( triValue, xoff, yoff, zoff, A, B, C, D, E, F, G, H ); + + // If this value is greater than max, it is the new max + if ( triValue > triMax ) + { + triMax = triValue; + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + max = (int)triMax; + } + + if ( max < 0 ) + { + max = 0; + } + else if ( max > staticInfo->Volume->GetArraySize() - 1 ) + { + max = (int)(staticInfo->Volume->GetArraySize() - 1); + } + + dynamicInfo->ScalarValue = max; + max_opacity = scalarArray[max]; + + // Set the return pixel value. + if( staticInfo->ColorChannels == 1 ) + { + dynamicInfo->Color[0] = max_opacity * grayArray[max]; + dynamicInfo->Color[1] = max_opacity * grayArray[max]; + dynamicInfo->Color[2] = max_opacity * grayArray[max]; + dynamicInfo->Color[3] = max_opacity; + } + else if ( staticInfo->ColorChannels == 3 ) + { + dynamicInfo->Color[0] = max_opacity * RGBArray[max*3]; + dynamicInfo->Color[1] = max_opacity * RGBArray[max*3+1]; + dynamicInfo->Color[2] = max_opacity * RGBArray[max*3+2]; + dynamicInfo->Color[3] = max_opacity; + } + + dynamicInfo->NumberOfStepsTaken = num_steps; +} + + +// This is the templated function that actually casts a ray and computes +// the maximum value. It is valid for unsigned char and unsigned short, +template <class T> +void vtkCastMaxOpacityRay( T *data_ptr, vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + float max; + float opacity; + float value; + int max_value = 0; + int loop; + int xinc, yinc, zinc; + int voxel[3]; + int prev_voxel[3]; + float ray_position[3]; + T A, B, C, D, E, F, G, H; + float t00, t01, t10, t11, t0, t1; + int Binc, Cinc, Dinc, Einc, Finc, Ginc, Hinc; + float xoff, yoff, zoff; + T *dptr; + int steps_this_ray = 0; + float *SOTF; + int num_steps; + float *ray_start, *ray_increment; + float *grayArray, *RGBArray; + + num_steps = dynamicInfo->NumberOfStepsToTake; + ray_start = dynamicInfo->TransformedStart; + ray_increment = dynamicInfo->TransformedIncrement; + + + SOTF = staticInfo->Volume->GetScalarOpacityArray(); + grayArray = staticInfo->Volume->GetGrayArray(); + RGBArray = staticInfo->Volume->GetRGBArray(); + + // Set the max value. This will not always be correct and should be fixed + max = -999999.0; + + xinc = staticInfo->DataIncrement[0]; + yinc = staticInfo->DataIncrement[1]; + zinc = staticInfo->DataIncrement[2]; + + // Initialize the ray position and voxel location + ray_position[0] = ray_start[0]; + ray_position[1] = ray_start[1]; + ray_position[2] = ray_start[2]; + + // If we have nearest neighbor interpolation + if ( staticInfo->InterpolationType == VTK_NEAREST_INTERPOLATION ) + { + + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + + // For each step along the ray + for ( loop = 0; loop < num_steps; loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Access the value at this voxel location + value = *(data_ptr + voxel[2] * zinc + + voxel[1] * yinc + voxel[0] ); + + if ( value < 0 ) + { + value = 0; + } + else if ( value > staticInfo->Volume->GetArraySize() - 1 ) + { + value = staticInfo->Volume->GetArraySize() - 1; + } + + opacity = SOTF[(int)value]; + + // If this is greater than the max, this is the new max. + if ( opacity > max ) + { + max = opacity; + max_value = (int) value; + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkRoundFuncMacro( ray_position[0] ); + voxel[1] = vtkRoundFuncMacro( ray_position[1] ); + voxel[2] = vtkRoundFuncMacro( ray_position[2] ); + } + } + // We are using trilinear interpolation + else if ( staticInfo->InterpolationType == VTK_LINEAR_INTERPOLATION ) + { + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + + // Compute the increments to get to the other 7 voxel vertices from A + Binc = xinc; + Cinc = yinc; + Dinc = xinc + yinc; + Einc = zinc; + Finc = zinc + xinc; + Ginc = zinc + yinc; + Hinc = zinc + xinc + yinc; + + // Set values for the first pass through the loop + dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + // Keep the voxel location so that we know when we've moved into a + // new voxel + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + + // For each step along the ray + for ( loop = 0; loop < num_steps; loop++ ) + { + // We've taken another step + steps_this_ray++; + + // Have we moved into a new voxel? If so we need to recompute A-H + if ( prev_voxel[0] != voxel[0] || + prev_voxel[1] != voxel[1] || + prev_voxel[2] != voxel[2] ) + { + dptr = data_ptr + voxel[2] * zinc + voxel[1] * yinc + voxel[0]; + + A = *(dptr); + B = *(dptr + Binc); + C = *(dptr + Cinc); + D = *(dptr + Dinc); + E = *(dptr + Einc); + F = *(dptr + Finc); + G = *(dptr + Ginc); + H = *(dptr + Hinc); + + prev_voxel[0] = voxel[0]; + prev_voxel[1] = voxel[1]; + prev_voxel[2] = voxel[2]; + } + + // Compute our offset in the voxel, and use that to trilinearly + // interpolate a value + xoff = ray_position[0] - (float) voxel[0]; + yoff = ray_position[1] - (float) voxel[1]; + zoff = ray_position[2] - (float) voxel[2]; + vtkTrilinFuncMacro( value, xoff, yoff, zoff, A, B, C, D, E, F, G, H ); + + if ( value < 0 ) + { + value = 0; + } + else if ( value > staticInfo->Volume->GetArraySize() - 1 ) + { + value = staticInfo->Volume->GetArraySize() - 1; + } + + opacity = SOTF[(int)value]; + + // If this is greater than the max, this is the new max. + if ( opacity > max ) + { + max = opacity; + max_value = (int) value; + } + + // Increment our position and compute our voxel location + ray_position[0] += ray_increment[0]; + ray_position[1] += ray_increment[1]; + ray_position[2] += ray_increment[2]; + voxel[0] = vtkFloorFuncMacro( ray_position[0] ); + voxel[1] = vtkFloorFuncMacro( ray_position[1] ); + voxel[2] = vtkFloorFuncMacro( ray_position[2] ); + } + } + + dynamicInfo->ScalarValue = max; + + // Set the return pixel value. The depth value is currently useless and + // should be fixed. + if( staticInfo->ColorChannels == 1 ) + { + dynamicInfo->Color[0] = max * grayArray[max_value]; + dynamicInfo->Color[1] = max * grayArray[max_value]; + dynamicInfo->Color[2] = max * grayArray[max_value]; + dynamicInfo->Color[3] = max; + } + else if ( staticInfo->ColorChannels == 3 ) + { + dynamicInfo->Color[0] = max * RGBArray[max_value*3]; + dynamicInfo->Color[1] = max * RGBArray[max_value*3+1]; + dynamicInfo->Color[2] = max * RGBArray[max_value*3+2]; + dynamicInfo->Color[3] = max; + } + + + dynamicInfo->NumberOfStepsTaken = steps_this_ray; +} + +// Construct a new vtkVolumeRayCastMIPFunction +vtkVolumeRayCastMIPFunction::vtkVolumeRayCastMIPFunction() +{ + this->MaximizeMethod = VTK_MAXIMIZE_SCALAR_VALUE; +} + +// Destruct the vtkVolumeRayCastMIPFunction +vtkVolumeRayCastMIPFunction::~vtkVolumeRayCastMIPFunction() +{ +} + +// This is called from RenderAnImage (in vtkDepthPARCMapper.cxx) +// It uses the integer data type flag that is passed in to +// determine what type of ray needs to be cast (which is handled +// by a templated function. +void vtkVolumeRayCastMIPFunction::CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo) +{ + void *data_ptr; + + data_ptr = staticInfo->ScalarDataPointer; + + if ( this->MaximizeMethod == VTK_MAXIMIZE_SCALAR_VALUE ) + { + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastMaxScalarValueRay( (unsigned char *)data_ptr, dynamicInfo, + staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastMaxScalarValueRay( (unsigned short *)data_ptr, dynamicInfo, + staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } + else + { + switch ( staticInfo->ScalarDataType ) + { + case VTK_UNSIGNED_CHAR: + vtkCastMaxOpacityRay( (unsigned char *)data_ptr, dynamicInfo, staticInfo ); + break; + case VTK_UNSIGNED_SHORT: + vtkCastMaxOpacityRay( (unsigned short *)data_ptr, dynamicInfo, staticInfo ); + break; + default: + vtkWarningMacro ( << "Unsigned char and unsigned short are the only supported datatypes for rendering" ); + break; + } + } +} + +float vtkVolumeRayCastMIPFunction::GetZeroOpacityThreshold( vtkVolume *vtkNotUsed(vol) ) +{ + return ( 1.0 ); +} + +// This is an update method that is called from Render (in +// vtkDepthPARCMapper.cxx). It allows the specific mapper type to +// update any local caster variables. In this case, nothing needs +// to be done here +void vtkVolumeRayCastMIPFunction::SpecificFunctionInitialize( + vtkRenderer *vtkNotUsed(ren), + vtkVolume *vtkNotUsed(vol), + vtkVolumeRayCastStaticInfo *staticInfo, + vtkVolumeRayCastMapper *vtkNotUsed(mapper) ) +{ + staticInfo->MIPFunction = 1; + staticInfo->MaximizeOpacity = (this->MaximizeMethod == VTK_MAXIMIZE_OPACITY); +} + +// Description: +// Return the maximize method as a descriptive character string. +const char *vtkVolumeRayCastMIPFunction::GetMaximizeMethodAsString(void) +{ + if( this->MaximizeMethod == VTK_MAXIMIZE_SCALAR_VALUE ) + { + return "Maximize Scalar Value"; + } + if( this->MaximizeMethod == VTK_MAXIMIZE_OPACITY ) + { + return "Maximize Opacity"; + } + else + { + return "Unknown"; + } +} + +// Print method for vtkVolumeRayCastMIPFunction +void vtkVolumeRayCastMIPFunction::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Maximize Method: " << this->GetMaximizeMethodAsString() + << "\n"; +} diff --git a/VolumeRendering/vtkVolumeRayCastMIPFunction.h b/VolumeRendering/vtkVolumeRayCastMIPFunction.h new file mode 100644 index 0000000..61681dc --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastMIPFunction.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastMIPFunction.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeRayCastMIPFunction - A maximum intensity projection ray caster for volumes +// +// .SECTION Description +// vtkVolumeRayCastMIPFunction is a volume ray cast function that +// computes the maximum value encountered along the ray. This is +// either the maximum scalar value, or the maximum opacity, as +// defined by the MaximizeMethod. The color and opacity returned +// by this function is based on the color, scalar opacity, and +// gradient opacity transfer functions defined in the vtkVolumeProperty +// of the vtkVolume. +// +// .SECTION See Also +// vtkVolumeRayCastFunction vtkVolumeRayCastMapper vtkVolumeProperty +// vtkVolumeRayCastCompositeFunction vtkVolumeRayCastIsosurfaceFunction +// vtkVolume vtkVolumeProperty + +#ifndef __vtkVolumeRayCastMIPFunction_h +#define __vtkVolumeRayCastMIPFunction_h + +#include "vtkVolumeRayCastFunction.h" + +#define VTK_MAXIMIZE_SCALAR_VALUE 0 +#define VTK_MAXIMIZE_OPACITY 1 + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeRayCastMIPFunction : public vtkVolumeRayCastFunction +{ +public: + static vtkVolumeRayCastMIPFunction *New(); + vtkTypeRevisionMacro(vtkVolumeRayCastMIPFunction,vtkVolumeRayCastFunction); + void PrintSelf( ostream& os, vtkIndent indent ); + + + // Description: + // Get the scalar value below which all scalar values have zero opacity. + float GetZeroOpacityThreshold( vtkVolume *vol ); + + + // Description: + // Set the MaximizeMethod to either ScalarValue or Opacity. + vtkSetClampMacro( MaximizeMethod, int, + VTK_MAXIMIZE_SCALAR_VALUE, VTK_MAXIMIZE_OPACITY ); + vtkGetMacro(MaximizeMethod,int); + void SetMaximizeMethodToScalarValue() + {this->SetMaximizeMethod(VTK_MAXIMIZE_SCALAR_VALUE);} + void SetMaximizeMethodToOpacity() + {this->SetMaximizeMethod(VTK_MAXIMIZE_OPACITY);} + const char *GetMaximizeMethodAsString(void); + +//BTX + void CastRay( vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ); +//ETX + + +protected: + vtkVolumeRayCastMIPFunction(); + ~vtkVolumeRayCastMIPFunction(); + + int MaximizeMethod; + +//BTX + void SpecificFunctionInitialize( vtkRenderer *ren, + vtkVolume *vol, + vtkVolumeRayCastStaticInfo *staticInfo, + vtkVolumeRayCastMapper *mapper ); + +//ETX +private: + vtkVolumeRayCastMIPFunction(const vtkVolumeRayCastMIPFunction&); // Not implemented. + void operator=(const vtkVolumeRayCastMIPFunction&); // Not implemented. +}; + + + +#endif diff --git a/VolumeRendering/vtkVolumeRayCastMapper.cxx b/VolumeRendering/vtkVolumeRayCastMapper.cxx new file mode 100644 index 0000000..c6a3333 --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastMapper.cxx @@ -0,0 +1,2029 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeRayCastMapper.h" + +#include "vtkCamera.h" +#include "vtkEncodedGradientEstimator.h" +#include "vtkEncodedGradientShader.h" +#include "vtkFiniteDifferenceGradientEstimator.h" +#include "vtkGarbageCollector.h" +#include "vtkGraphicsFactory.h" +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkMultiThreader.h" +#include "vtkObjectFactory.h" +#include "vtkPlaneCollection.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTimerLog.h" +#include "vtkTransform.h" +#include "vtkVolumeProperty.h" +#include "vtkVolumeRayCastFunction.h" +#include "vtkRayCastImageDisplayHelper.h" + +#include <math.h> + +vtkCxxRevisionMacro(vtkVolumeRayCastMapper, "$Revision: 1.1.6.1 $"); +vtkStandardNewMacro(vtkVolumeRayCastMapper); + +vtkCxxSetObjectMacro(vtkVolumeRayCastMapper,VolumeRayCastFunction, + vtkVolumeRayCastFunction ); + +#define vtkVRCMultiplyPointMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[1] + A[2]*M[2] + M[3]; \ + B[1] = A[0]*M[4] + A[1]*M[5] + A[2]*M[6] + M[7]; \ + B[2] = A[0]*M[8] + A[1]*M[9] + A[2]*M[10] + M[11]; \ + B[3] = A[0]*M[12] + A[1]*M[13] + A[2]*M[14] + M[15]; \ + if ( B[3] != 1.0 ) { B[0] /= B[3]; B[1] /= B[3]; B[2] /= B[3]; } + +#define vtkVRCMultiplyViewPointMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[1] + A[2]*M[2] + M[3]; \ + B[1] = A[0]*M[4] + A[1]*M[5] + A[2]*M[6] + M[7]; \ + B[3] = A[0]*M[12] + A[1]*M[13] + A[2]*M[14] + M[15]; \ + if ( B[3] != 1.0 ) { B[0] /= B[3]; B[1] /= B[3]; } + +#define vtkVRCMultiplyNormalMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[4] + A[2]*M[8]; \ + B[1] = A[0]*M[1] + A[1]*M[5] + A[2]*M[9]; \ + B[2] = A[0]*M[2] + A[1]*M[6] + A[2]*M[10] + +// Construct a new vtkVolumeRayCastMapper with default values +vtkVolumeRayCastMapper::vtkVolumeRayCastMapper() +{ + this->SampleDistance = 1.0; + this->ImageSampleDistance = 1.0; + this->MinimumImageSampleDistance = 1.0; + this->MaximumImageSampleDistance = 10.0; + this->AutoAdjustSampleDistances = 1; + this->VolumeRayCastFunction = NULL; + + this->GradientEstimator = vtkFiniteDifferenceGradientEstimator::New(); + this->GradientShader = vtkEncodedGradientShader::New(); + + this->PerspectiveMatrix = vtkMatrix4x4::New(); + this->ViewToWorldMatrix = vtkMatrix4x4::New(); + this->ViewToVoxelsMatrix = vtkMatrix4x4::New(); + this->VoxelsToViewMatrix = vtkMatrix4x4::New(); + this->WorldToVoxelsMatrix = vtkMatrix4x4::New(); + this->VoxelsToWorldMatrix = vtkMatrix4x4::New(); + + this->VolumeMatrix = vtkMatrix4x4::New(); + + this->PerspectiveTransform = vtkTransform::New(); + this->VoxelsTransform = vtkTransform::New(); + this->VoxelsToViewTransform = vtkTransform::New(); + + + this->ImageMemorySize[0] = 0; + this->ImageMemorySize[1] = 0; + + this->Threader = vtkMultiThreader::New(); + + this->Image = NULL; + this->RowBounds = NULL; + this->OldRowBounds = NULL; + + this->RenderTimeTable = NULL; + this->RenderVolumeTable = NULL; + this->RenderRendererTable = NULL; + this->RenderTableSize = 0; + this->RenderTableEntries = 0; + + this->ZBuffer = NULL; + this->ZBufferSize[0] = 0; + this->ZBufferSize[1] = 0; + this->ZBufferOrigin[0] = 0; + this->ZBufferOrigin[1] = 0; + + this->ImageDisplayHelper = vtkRayCastImageDisplayHelper::New(); + + this->IntermixIntersectingGeometry = 1; +} + +// Destruct a vtkVolumeRayCastMapper - clean up any memory used +vtkVolumeRayCastMapper::~vtkVolumeRayCastMapper() +{ + if ( this->GradientEstimator ) + { + this->GradientEstimator->UnRegister(this); + this->GradientEstimator = NULL; + } + + this->GradientShader->Delete(); + + this->SetVolumeRayCastFunction(NULL); + + this->PerspectiveMatrix->Delete(); + this->ViewToWorldMatrix->Delete(); + this->ViewToVoxelsMatrix->Delete(); + this->VoxelsToViewMatrix->Delete(); + this->WorldToVoxelsMatrix->Delete(); + this->VoxelsToWorldMatrix->Delete(); + + this->VolumeMatrix->Delete(); + + this->VoxelsTransform->Delete(); + this->VoxelsToViewTransform->Delete(); + this->PerspectiveTransform->Delete(); + + this->ImageDisplayHelper->Delete(); + + this->Threader->Delete(); + + if ( this->Image ) + { + delete [] this->Image; + } + + if ( this->RenderTableSize ) + { + delete [] this->RenderTimeTable; + delete [] this->RenderVolumeTable; + delete [] this->RenderRendererTable; + } + + if ( this->RowBounds ) + { + delete [] this->RowBounds; + delete [] this->OldRowBounds; + } +} + +float vtkVolumeRayCastMapper::RetrieveRenderTime( vtkRenderer *ren, + vtkVolume *vol ) +{ + int i; + + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + return this->RenderTimeTable[i]; + } + } + + return 0.0; +} + +void vtkVolumeRayCastMapper::StoreRenderTime( vtkRenderer *ren, + vtkVolume *vol, + float time ) +{ + int i; + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + this->RenderTimeTable[i] = time; + return; + } + } + + + // Need to increase size + if ( this->RenderTableEntries >= this->RenderTableSize ) + { + if ( this->RenderTableSize == 0 ) + { + this->RenderTableSize = 10; + } + else + { + this->RenderTableSize *= 2; + } + + float *oldTimePtr = this->RenderTimeTable; + vtkVolume **oldVolumePtr = this->RenderVolumeTable; + vtkRenderer **oldRendererPtr = this->RenderRendererTable; + + this->RenderTimeTable = new float [this->RenderTableSize]; + this->RenderVolumeTable = new vtkVolume *[this->RenderTableSize]; + this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize]; + + for (i = 0; i < this->RenderTableEntries; i++ ) + { + this->RenderTimeTable[i] = oldTimePtr[i]; + this->RenderVolumeTable[i] = oldVolumePtr[i]; + this->RenderRendererTable[i] = oldRendererPtr[i]; + } + + delete [] oldTimePtr; + delete [] oldVolumePtr; + delete [] oldRendererPtr; + } + + this->RenderTimeTable[this->RenderTableEntries] = time; + this->RenderVolumeTable[this->RenderTableEntries] = vol; + this->RenderRendererTable[this->RenderTableEntries] = ren; + + this->RenderTableEntries++; +} + +void vtkVolumeRayCastMapper::SetNumberOfThreads( int num ) +{ + this->Threader->SetNumberOfThreads( num ); +} + +int vtkVolumeRayCastMapper::GetNumberOfThreads() +{ + if (this->Threader) + { + return this->Threader->GetNumberOfThreads(); + } + return 0; +} + +void vtkVolumeRayCastMapper::SetGradientEstimator( + vtkEncodedGradientEstimator *gradest ) +{ + + // If we are setting it to its current value, don't do anything + if ( this->GradientEstimator == gradest ) + { + return; + } + + // If we already have a gradient estimator, unregister it. + if ( this->GradientEstimator ) + { + this->GradientEstimator->UnRegister(this); + this->GradientEstimator = NULL; + } + + // If we are passing in a non-NULL estimator, register it + if ( gradest ) + { + gradest->Register( this ); + } + + // Actually set the estimator, and consider the object Modified + this->GradientEstimator = gradest; + this->Modified(); +} + +float vtkVolumeRayCastMapper::GetGradientMagnitudeScale() +{ + if ( !this->GradientEstimator ) + { + vtkErrorMacro( "You must have a gradient estimator set to get the scale" ); + return 1.0; + } + + return this->GradientEstimator->GetGradientMagnitudeScale(); +} + +float vtkVolumeRayCastMapper::GetGradientMagnitudeBias() +{ + if ( !this->GradientEstimator ) + { + vtkErrorMacro( "You must have a gradient estimator set to get the bias" ); + return 1.0; + } + + return this->GradientEstimator->GetGradientMagnitudeBias(); +} + +void vtkVolumeRayCastMapper::ReleaseGraphicsResources(vtkWindow *) +{ +} + +void vtkVolumeRayCastMapper::Render( vtkRenderer *ren, vtkVolume *vol ) +{ + // make sure that we have scalar input and update the scalar input + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<< "No Input!"); + return; + } + else + { + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + } + + + int scalarType = this->GetInput()->GetPointData()->GetScalars()->GetDataType(); + if (scalarType != VTK_UNSIGNED_SHORT && scalarType != VTK_UNSIGNED_CHAR) + { + vtkErrorMacro ("Cannot volume render data of type " + << vtkImageScalarTypeNameMacro(scalarType) + << ", only unsigned char or unsigned short."); + return; + } + // Start timing now. We didn't want to capture the update of the + // input data in the times + this->Timer->StartTimer(); + + this->ConvertCroppingRegionPlanesToVoxels(); + + this->UpdateShadingTables( ren, vol ); + + // This is the input of this mapper + vtkImageData *input = this->GetInput(); + + // Get the camera from the renderer + vtkCamera *cam = ren->GetActiveCamera(); + + // Get the aspect ratio from the renderer. This is needed for the + // computation of the perspective matrix + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + + // Keep track of the projection matrix - we'll need it in a couple of + // places Get the projection matrix. The method is called perspective, but + // the matrix is valid for perspective and parallel viewing transforms. + // Don't replace this with the GetCompositePerspectiveTransformMatrix + // because that turns off stereo rendering!!! + this->PerspectiveTransform->Identity(); + this->PerspectiveTransform->Concatenate( + cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1],0.0, 1.0 )); + this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix()); + + // Compute some matrices from voxels to view and vice versa based + // on the whole input + this->ComputeMatrices( input, vol ); + + + // How big is the viewport in pixels? + double *viewport = ren->GetViewport(); + int *renWinSize = ren->GetRenderWindow()->GetSize(); + + // Save this so that we can restore it if the image is cancelled + double oldImageSampleDistance = this->ImageSampleDistance; + + // If we are automatically adjusting the size to achieve a desired frame + // rate, then do that adjustment here. Base the new image sample distance + // on the previous one and the previous render time. Don't let + // the adjusted image sample distance be less than the minimum image sample + // distance or more than the maximum image sample distance. + if ( this->AutoAdjustSampleDistances ) + { + float oldTime = this->RetrieveRenderTime( ren, vol ); + float newTime = vol->GetAllocatedRenderTime(); + this->ImageSampleDistance *= sqrt(oldTime / newTime); + this->ImageSampleDistance = + (this->ImageSampleDistance>this->MaximumImageSampleDistance)? + (this->MaximumImageSampleDistance):(this->ImageSampleDistance); + this->ImageSampleDistance = + (this->ImageSampleDistance<this->MinimumImageSampleDistance)? + (this->MinimumImageSampleDistance):(this->ImageSampleDistance); + } + + // The full image fills the viewport. First, compute the actual viewport + // size, then divide by the ImageSampleDistance to find the full image + // size in pixels + int width, height; + ren->GetTiledSize(&width, &height); + this->ImageViewportSize[0] = + static_cast<int>(width/this->ImageSampleDistance); + this->ImageViewportSize[1] = + static_cast<int>(height/this->ImageSampleDistance); + + // Compute row bounds. This will also compute the size of the image to + // render, allocate the space if necessary, and clear the image where + // required + if ( this->ComputeRowBounds( vol, ren ) ) + { + vtkVolumeRayCastStaticInfo *staticInfo = new vtkVolumeRayCastStaticInfo; + staticInfo->ClippingPlane = NULL; + staticInfo->Volume = vol; + staticInfo->Renderer = ren; + staticInfo->ScalarDataPointer = + this->GetInput()->GetPointData()->GetScalars()->GetVoidPointer(0); + staticInfo->ScalarDataType = + this->GetInput()->GetPointData()->GetScalars()->GetDataType(); + + // Do we need to capture the z buffer to intermix intersecting + // geometry? If so, do it here + if ( this->IntermixIntersectingGeometry && + ren->GetNumberOfPropsRendered() ) + { + int x1, x2, y1, y2; + + // turn this->ImageOrigin into (x1,y1) in window (not viewport!) + // coordinates. + x1 = static_cast<int> ( + viewport[0] * static_cast<double>(renWinSize[0]) + + static_cast<double>(this->ImageOrigin[0]) * this->ImageSampleDistance ); + y1 = static_cast<int> ( + viewport[1] * static_cast<double>(renWinSize[1]) + + static_cast<double>(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // compute z buffer size + this->ZBufferSize[0] = static_cast<int>( + static_cast<double>(this->ImageInUseSize[0]) * this->ImageSampleDistance); + this->ZBufferSize[1] = static_cast<int>( + static_cast<double>(this->ImageInUseSize[1]) * this->ImageSampleDistance); + + // Use the size to compute (x2,y2) in window coordinates + x2 = x1 + this->ZBufferSize[0] - 1; + y2 = y1 + this->ZBufferSize[1] - 1; + + // This is the z buffer origin (in viewport coordinates) + this->ZBufferOrigin[0] = static_cast<int>( + static_cast<double>(this->ImageOrigin[0]) * this->ImageSampleDistance); + this->ZBufferOrigin[1] = static_cast<int>( + static_cast<double>(this->ImageOrigin[1]) * this->ImageSampleDistance); + + // Capture the z buffer + this->ZBuffer = ren->GetRenderWindow()->GetZbufferData(x1,y1,x2,y2); + } + + // This must be done before FunctionInitialize since FunctionInitialize + // depends on the gradient opacity constant (computed in here) to + // determine whether to save the gradient magnitudes + vol->UpdateTransferFunctions( ren ); + + // Requires UpdateTransferFunctions to have been called first + this->VolumeRayCastFunction->FunctionInitialize( ren, vol, + staticInfo ); + + vol->UpdateScalarOpacityforSampleSize( ren, this->SampleDistance ); + + staticInfo->CameraThickness = + static_cast<float>(ren->GetActiveCamera()->GetThickness()); + + // Copy the viewToVoxels matrix to 16 floats + int i, j; + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + staticInfo->ViewToVoxelsMatrix[j*4+i] = + static_cast<float>(this->ViewToVoxelsMatrix->GetElement(j,i)); + } + } + + // Copy the worldToVoxels matrix to 16 floats + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + staticInfo->WorldToVoxelsMatrix[j*4+i] = + static_cast<float>(this->WorldToVoxelsMatrix->GetElement(j,i)); + } + } + + // Copy the voxelsToWorld matrix to 16 floats + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + staticInfo->VoxelsToWorldMatrix[j*4+i] = + static_cast<float>(this->VoxelsToWorldMatrix->GetElement(j,i)); + } + } + + if ( this->ClippingPlanes ) + { + this->InitializeClippingPlanes( staticInfo, this->ClippingPlanes ); + } + else + { + staticInfo->NumberOfClippingPlanes = 0; + } + + + // Copy in the image info + staticInfo->ImageInUseSize[0] = this->ImageInUseSize[0]; + staticInfo->ImageInUseSize[1] = this->ImageInUseSize[1]; + staticInfo->ImageMemorySize[0] = this->ImageMemorySize[0]; + staticInfo->ImageMemorySize[1] = this->ImageMemorySize[1]; + staticInfo->ImageViewportSize[0] = this->ImageViewportSize[0]; + staticInfo->ImageViewportSize[1] = this->ImageViewportSize[1]; + + staticInfo->ImageOrigin[0] = this->ImageOrigin[0]; + staticInfo->ImageOrigin[1] = this->ImageOrigin[1]; + + staticInfo->Image = this->Image; + staticInfo->RowBounds = this->RowBounds; + + // Set the number of threads to use for ray casting, + // then set the execution method and do it. + this->Threader->SetSingleMethod( VolumeRayCastMapper_CastRays, + (void *)staticInfo); + this->Threader->SingleMethodExecute(); + + if ( !ren->GetRenderWindow()->GetAbortRender() ) + { + float depth; + if ( this->IntermixIntersectingGeometry ) + { + depth = this->MinimumViewDistance; + } + else + { + depth = -1; + } + + this->ImageDisplayHelper-> + RenderTexture( vol, ren, + this->ImageMemorySize, + this->ImageViewportSize, + this->ImageInUseSize, + this->ImageOrigin, + depth, + this->Image ); + + this->Timer->StopTimer(); + this->TimeToDraw = this->Timer->GetElapsedTime(); + this->StoreRenderTime( ren, vol, this->TimeToDraw ); + } + // Restore the image sample distance so that automatic adjustment + // will work correctly + else + { + this->ImageSampleDistance = oldImageSampleDistance; + } + + if ( staticInfo->ClippingPlane ) + { + delete [] staticInfo->ClippingPlane; + } + delete staticInfo; + + if ( this->ZBuffer ) + { + delete [] this->ZBuffer; + this->ZBuffer = NULL; + } + + } +} +VTK_THREAD_RETURN_TYPE VolumeRayCastMapper_CastRays( void *arg ) +{ + // Get the info out of the input structure + int threadID = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID; + int threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads; + vtkVolumeRayCastStaticInfo *staticInfo = + (vtkVolumeRayCastStaticInfo *)((vtkMultiThreader::ThreadInfo *)arg)->UserData; + + int i, j, k; + unsigned char *ucptr; + + vtkVolumeRayCastMapper *me = + vtkVolumeRayCastMapper::SafeDownCast( staticInfo->Volume->GetMapper() ); + + if ( !me ) + { + vtkGenericWarningMacro("The volume does not have a ray cast mapper!"); + return VTK_THREAD_RETURN_VALUE; + } + + vtkVolumeRayCastDynamicInfo *dynamicInfo = new vtkVolumeRayCastDynamicInfo; + + // Initialize this to avoid purify problems + dynamicInfo->ScalarValue = 0; + + float *rayStart = dynamicInfo->TransformedStart; + float *rayEnd = dynamicInfo->TransformedEnd; + float *rayDirection = dynamicInfo->TransformedDirection; + float *rayStep = dynamicInfo->TransformedIncrement; + + float norm; + float viewRay[3]; + float rayCenter[3]; + float absStep[3]; + float voxelPoint[4]; + + // We need to know what the center ray is (in voxel coordinates) to + // compute sampling distance later on. Save it in an instance variable. + + // This is tbe near end of the center ray in view coordinates + // Convert it to voxel coordinates + viewRay[0] = viewRay[1] = viewRay[2] = 0.0; + vtkVRCMultiplyPointMacro( viewRay, rayStart, + staticInfo->ViewToVoxelsMatrix ); + + // This is the far end of the center ray in view coordinates + // Convert it to voxel coordiantes + viewRay[2] = 1.0; + vtkVRCMultiplyPointMacro( viewRay, voxelPoint, + staticInfo->ViewToVoxelsMatrix ); + + // Turn these two points into a vector + rayCenter[0] = voxelPoint[0] - rayStart[0]; + rayCenter[1] = voxelPoint[1] - rayStart[1]; + rayCenter[2] = voxelPoint[2] - rayStart[2]; + + // normalize the vector based on world coordinate distance + // This way we can scale by sample distance and it will work + // out even though we are in voxel coordinates + rayCenter[0] /= staticInfo->CameraThickness; + rayCenter[1] /= staticInfo->CameraThickness; + rayCenter[2] /= staticInfo->CameraThickness; + + float centerScale = sqrt( (rayCenter[0] * rayCenter[0]) + + (rayCenter[1] * rayCenter[1]) + + (rayCenter[2] * rayCenter[2]) ); + + rayCenter[0] /= centerScale; + rayCenter[1] /= centerScale; + rayCenter[2] /= centerScale; + + float bounds[6]; + int dim[3]; + + me->GetInput()->GetDimensions(dim); + bounds[0] = bounds[2] = bounds[4] = 0.0; + bounds[1] = dim[0]-1; + bounds[3] = dim[1]-1; + bounds[5] = dim[2]-1; + + // If we have a simple crop box then we can tighten the bounds + if ( me->Cropping && me->CroppingRegionFlags == 0x2000 ) + { + bounds[0] = me->VoxelCroppingRegionPlanes[0]; + bounds[1] = me->VoxelCroppingRegionPlanes[1]; + bounds[2] = me->VoxelCroppingRegionPlanes[2]; + bounds[3] = me->VoxelCroppingRegionPlanes[3]; + bounds[4] = me->VoxelCroppingRegionPlanes[4]; + bounds[5] = me->VoxelCroppingRegionPlanes[5]; + } + + bounds[0] = (bounds[0] < 0)?(0):(bounds[0]); + bounds[0] = (bounds[0] > dim[0]-1)?(dim[0]-1):(bounds[0]); + bounds[1] = (bounds[1] < 0)?(0):(bounds[1]); + bounds[1] = (bounds[1] > dim[0]-1)?(dim[0]-1):(bounds[1]); + bounds[2] = (bounds[2] < 0)?(0):(bounds[2]); + bounds[2] = (bounds[2] > dim[1]-1)?(dim[1]-1):(bounds[2]); + bounds[3] = (bounds[3] < 0)?(0):(bounds[3]); + bounds[3] = (bounds[3] > dim[1]-1)?(dim[1]-1):(bounds[3]); + bounds[4] = (bounds[4] < 0)?(0):(bounds[4]); + bounds[4] = (bounds[4] > dim[2]-1)?(dim[2]-1):(bounds[4]); + bounds[5] = (bounds[5] < 0)?(0):(bounds[5]); + bounds[5] = (bounds[5] > dim[2]-1)?(dim[2]-1):(bounds[5]); + + // The rounding tie-breaker is used to protect against a very small rounding error + // introduced in the QuickFloor function, which is used by the vtkFloorFuncMacro macro. + bounds[1] -= vtkFastNumericConversion::RoundingTieBreaker(); + bounds[3] -= vtkFastNumericConversion::RoundingTieBreaker(); + bounds[5] -= vtkFastNumericConversion::RoundingTieBreaker(); + + int *imageInUseSize = staticInfo->ImageInUseSize; + int *imageMemorySize = staticInfo->ImageMemorySize; + int *imageViewportSize = staticInfo->ImageViewportSize; + int *imageOrigin = staticInfo->ImageOrigin; + int *rowBounds = staticInfo->RowBounds; + + unsigned char *imagePtr = staticInfo->Image; + + float sampleDistance = me->GetSampleDistance(); + + float val; + + vtkRenderWindow *renWin = staticInfo->Renderer->GetRenderWindow(); + + // Compute the offset valuex for viewing rays - this is the 1 / fullSize + // value to add to the computed location so that they falls between + // -1 + 1/fullSize and 1 - 1/fullSize and are each 2/fullSize apart. + // fullSize is the viewport size along the corresponding direction (in + // pixels) + float offsetX = 1.0 / static_cast<float>(imageViewportSize[0]); + float offsetY = 1.0 / static_cast<float>(imageViewportSize[1]); + + // Some variables needed for non-subvolume cropping + float fullRayStart[3]; + float fullRayEnd[3]; + float fullRayDirection[3]; + int bitLoop, bitFlag; + float rgbaArray[40], distanceArray[10], scalarArray[10]; + float tmp, tmpArray[4]; + int arrayCount; + + for ( j = 0; j < imageInUseSize[1]; j++ ) + { + if ( j%threadCount != threadID ) + { + continue; + } + + if ( !threadID ) + { + if ( renWin->CheckAbortStatus() ) + { + break; + } + } + else if ( renWin->GetAbortRender() ) + { + break; + } + + ucptr = imagePtr + 4*(j*imageMemorySize[0] + + rowBounds[j*2]); + + // compute the view point y value for this row. Do this by + // taking our pixel position, adding the image origin then dividing + // by the full image size to get a number from 0 to 1-1/fullSize. Then, + // multiply by two and subtract one to get a number from + // -1 to 1 - 2/fullSize. Then ass offsetX (which is 1/fullSize) to + // center it. + viewRay[1] = ((static_cast<float>(j) + static_cast<float>(imageOrigin[1])) / + imageViewportSize[1]) * 2.0 - 1.0 + offsetY; + + for ( i = rowBounds[j*2]; i <= rowBounds[j*2+1]; i++ ) + { + // Initialize for the cases where the ray doesn't intersect anything + ucptr[0] = 0; + ucptr[1] = 0; + ucptr[2] = 0; + ucptr[3] = 0; + + // Convert the view coordinates for the start and end of the + // ray into voxel coordinates, then compute the origin and direction. + + // compute the view point x value for this pixel. Do this by + // taking our pixel position, adding the image origin then dividing + // by the full image size to get a number from 0 to 1-1/fullSize. Then, + // multiply by two and subtract one to get a number from + // -1 to 1 - 2/fullSize. Then ass offsetX (which is 1/fullSize) to + // center it. + viewRay[0] = ((static_cast<float>(i) + static_cast<float>(imageOrigin[0])) / + imageViewportSize[0]) * 2.0 - 1.0 + offsetX; + + // Now transform this point with a z value of 0 for the ray start, and + // a z value of 1 for the ray end. This corresponds to the near and far + // plane locations. If IntermixIntersectingGeometry is on, then use + // the zbuffer value instead of 1.0 + viewRay[2] = 0.0; + vtkVRCMultiplyPointMacro( viewRay, rayStart, + staticInfo->ViewToVoxelsMatrix ); + + viewRay[2] = + (me->ZBuffer)?(me->GetZBufferValue(i,j)):(1.0); + vtkVRCMultiplyPointMacro( viewRay, rayEnd, + staticInfo->ViewToVoxelsMatrix ); + + rayDirection[0] = rayEnd[0] - rayStart[0]; + rayDirection[1] = rayEnd[1] - rayStart[1]; + rayDirection[2] = rayEnd[2] - rayStart[2]; + + // If cropping is off, or we are just doing a subvolume, we can + // do the easy thing here + if ( !me->Cropping || me->CroppingRegionFlags == 0x2000 ) + { + if ( me->ClipRayAgainstVolume( dynamicInfo, bounds ) && + ( staticInfo->NumberOfClippingPlanes == 0 || + me->ClipRayAgainstClippingPlanes( dynamicInfo, staticInfo ) ) ) + { + rayDirection[0] = rayEnd[0] - rayStart[0]; + rayDirection[1] = rayEnd[1] - rayStart[1]; + rayDirection[2] = rayEnd[2] - rayStart[2]; + + // Find the length of the input ray. It is not normalized + norm = sqrt( rayDirection[0] * rayDirection[0] + + rayDirection[1] * rayDirection[1] + + rayDirection[2] * rayDirection[2] ); + + // Normalize this ray into rayStep + rayStep[0] = rayDirection[0] / norm; + rayStep[1] = rayDirection[1] / norm; + rayStep[2] = rayDirection[2] / norm; + + // Correct for perspective in the sample distance. 1.0 over the + // dot product between this ray and the center ray is the + // correction factor to allow samples to be taken on parallel + // planes rather than concentric hemispheres. This factor will + // compute to be 1.0 for parallel. + val = ( rayStep[0] * rayCenter[0] + + rayStep[1] * rayCenter[1] + + rayStep[2] * rayCenter[2] ); + norm = (val != 0)?(1.0/val):(1.0); + + // Now multiple the normalized step by the sample distance and this + // correction factor to find the actual step + rayStep[0] *= norm * sampleDistance * centerScale; + rayStep[1] *= norm * sampleDistance * centerScale; + rayStep[2] *= norm * sampleDistance * centerScale; + + absStep[0] = ( rayStep[0] < 0.0 )?(-rayStep[0]):(rayStep[0]); + absStep[1] = ( rayStep[1] < 0.0 )?(-rayStep[1]):(rayStep[1]); + absStep[2] = ( rayStep[2] < 0.0 )?(-rayStep[2]):(rayStep[2]); + + if ( absStep[0] >= absStep[1] && absStep[0] >= absStep[2] ) + { + dynamicInfo->NumberOfStepsToTake = static_cast<int> + ((rayEnd[0]-rayStart[0]) / rayStep[0]); + } + else if ( absStep[1] >= absStep[2] && absStep[1] >= absStep[0] ) + { + dynamicInfo->NumberOfStepsToTake = static_cast<int> + ((rayEnd[1]-rayStart[1]) / rayStep[1]); + } + else + { + dynamicInfo->NumberOfStepsToTake = static_cast<int> + ((rayEnd[2]-rayStart[2]) / rayStep[2]); + } + + me->VolumeRayCastFunction->CastRay( dynamicInfo, staticInfo ); + if ( dynamicInfo->Color[3] > 0.0 ) + { + val = (dynamicInfo->Color[0]/dynamicInfo->Color[3])*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[0] = static_cast<unsigned char>(val); + + val = (dynamicInfo->Color[1]/dynamicInfo->Color[3])*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[1] = static_cast<unsigned char>(val); + + val = (dynamicInfo->Color[2]/dynamicInfo->Color[3])*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[2] = static_cast<unsigned char>(val); + + val = dynamicInfo->Color[3]*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[3] = static_cast<unsigned char>(val); + } + } + } + // Otherwise, cropping is on and we don't have a simple subvolume. + // We'll have to cast a ray for each of the 27 regions that is on + // and composite the results. + else + { + // We'll keep an array of regions that we intersect, the arrayCount + // variable will count how many of them we have + arrayCount = 0; + + // Save the ray start, end, and direction. We will modify this + // during each iteration of the loop for the current cropping region. + fullRayStart[0] = rayStart[0]; + fullRayStart[1] = rayStart[1]; + fullRayStart[2] = rayStart[2]; + + fullRayEnd[0] = rayEnd[0]; + fullRayEnd[1] = rayEnd[1]; + fullRayEnd[2] = rayEnd[2]; + + fullRayDirection[0] = rayDirection[0]; + fullRayDirection[1] = rayDirection[1]; + fullRayDirection[2] = rayDirection[2]; + + // Loop through the twenty seven cropping regions + bitFlag = 1; + for ( bitLoop = 0; bitLoop < 27; bitLoop++ ) + { + // Check if this cropping region is on + if ( !(me->CroppingRegionFlags & bitFlag) ) + { + bitFlag = bitFlag << 1; + continue; + } + + // Restore the ray information + rayStart[0] = fullRayStart[0]; + rayStart[1] = fullRayStart[1]; + rayStart[2] = fullRayStart[2]; + + rayEnd[0] = fullRayEnd[0]; + rayEnd[1] = fullRayEnd[1]; + rayEnd[2] = fullRayEnd[2]; + + rayDirection[0] = fullRayDirection[0]; + rayDirection[1] = fullRayDirection[1]; + rayDirection[2] = fullRayDirection[2]; + + // Figure out the bounds of the cropping region + // along the X axis + switch ( bitLoop % 3 ) + { + case 0: + bounds[0] = 0; + bounds[1] = me->VoxelCroppingRegionPlanes[0]; + break; + case 1: + bounds[0] = me->VoxelCroppingRegionPlanes[0]; + bounds[1] = me->VoxelCroppingRegionPlanes[1]; + break; + case 2: + bounds[0] = me->VoxelCroppingRegionPlanes[1]; + bounds[1] = (staticInfo->DataSize[0] - 1) - vtkFastNumericConversion::RoundingTieBreaker(); + break; + } + + // Figure out the bounds of the cropping region + // along the Y axis + switch ( (bitLoop % 9) / 3 ) + { + case 0: + bounds[2] = 0; + bounds[3] = me->VoxelCroppingRegionPlanes[2]; + break; + case 1: + bounds[2] = me->VoxelCroppingRegionPlanes[2]; + bounds[3] = me->VoxelCroppingRegionPlanes[3]; + break; + case 2: + bounds[2] = me->VoxelCroppingRegionPlanes[3]; + bounds[3] = (staticInfo->DataSize[1] - 1) - vtkFastNumericConversion::RoundingTieBreaker(); + break; + } + + // Figure out the bounds of the cropping region + // along the Z axis + switch ( bitLoop / 9 ) + { + case 0: + bounds[4] = 0; + bounds[5] = me->VoxelCroppingRegionPlanes[4]; + break; + case 1: + bounds[4] = me->VoxelCroppingRegionPlanes[4]; + bounds[5] = me->VoxelCroppingRegionPlanes[5]; + break; + case 2: + bounds[4] = me->VoxelCroppingRegionPlanes[5]; + bounds[5] = (staticInfo->DataSize[2] - 1) - vtkFastNumericConversion::RoundingTieBreaker(); + break; + } + + // Check against the bounds of the volume + for ( k = 0; k < 3; k++ ) + { + if ( bounds[2*k] < 0 ) + { + bounds[2*k] = 0; + } + if ( bounds[2*k + 1] > ((staticInfo->DataSize[k]-1) - vtkFastNumericConversion::RoundingTieBreaker()) ) + { + bounds[2*k + 1] = ((staticInfo->DataSize[k] - 1) - vtkFastNumericConversion::RoundingTieBreaker()); + } + } + + // Clip against the volume and the clipping planes + if ( me->ClipRayAgainstVolume( dynamicInfo, bounds ) && + ( staticInfo->NumberOfClippingPlanes == 0 || + me->ClipRayAgainstClippingPlanes( dynamicInfo, + staticInfo ) ) ) + { + // The ray start and end may have changed - recompute + // the direction + rayDirection[0] = rayEnd[0] - rayStart[0]; + rayDirection[1] = rayEnd[1] - rayStart[1]; + rayDirection[2] = rayEnd[2] - rayStart[2]; + + // Find the length of the ray. It is not normalized yet + norm = sqrt( rayDirection[0] * rayDirection[0] + + rayDirection[1] * rayDirection[1] + + rayDirection[2] * rayDirection[2] ); + + // Normalize this ray into rayStep + rayStep[0] = rayDirection[0] / norm; + rayStep[1] = rayDirection[1] / norm; + rayStep[2] = rayDirection[2] / norm; + + // Correct for perspective in the sample distance. 1.0 over the + // dot product between this ray and the center ray is the + // correction factor to allow samples to be taken on parallel + // planes rather than concentric hemispheres. This factor will + // compute to be 1.0 for parallel. + val = ( rayStep[0] * rayCenter[0] + + rayStep[1] * rayCenter[1] + + rayStep[2] * rayCenter[2] ); + norm = (val != 0)?(1.0/val):(1.0); + + // Now multiple the normalized step by the sample distance and this + // correction factor to find the actual step + rayStep[0] *= norm * sampleDistance * centerScale; + rayStep[1] *= norm * sampleDistance * centerScale; + rayStep[2] *= norm * sampleDistance * centerScale; + + // Find the major direction to determine the number of + // steps to take + absStep[0] = ( rayStep[0] < 0.0 )?(-rayStep[0]):(rayStep[0]); + absStep[1] = ( rayStep[1] < 0.0 )?(-rayStep[1]):(rayStep[1]); + absStep[2] = ( rayStep[2] < 0.0 )?(-rayStep[2]):(rayStep[2]); + if ( absStep[0] >= absStep[1] && absStep[0] >= absStep[2] ) + { + dynamicInfo->NumberOfStepsToTake = static_cast<int> + ((rayEnd[0]-rayStart[0]) / rayStep[0]); + } + else if ( absStep[1] >= absStep[2] && absStep[1] >= absStep[0] ) + { + dynamicInfo->NumberOfStepsToTake = static_cast<int> + ((rayEnd[1]-rayStart[1]) / rayStep[1]); + } + else + { + dynamicInfo->NumberOfStepsToTake = static_cast<int> + ((rayEnd[2]-rayStart[2]) / rayStep[2]); + } + + // Cast the ray + me->VolumeRayCastFunction->CastRay( dynamicInfo, staticInfo ); + + // If the ray returns a non-transparent color, store this + // in our arrays of distances and colors + if ( dynamicInfo->Color[3] > 0.0 ) + { + // Figure out the distance from this ray start to the full ray + // start and use this to sort the ray segments + for ( k = 0; k < 3; k++ ) + { + if ( absStep[k] >= absStep[(k+1)%3] && + absStep[k] >= absStep[(k+2)%3] ) + { + distanceArray[arrayCount] = + (rayStart[k] - fullRayStart[k]) / rayStep[k]; + break; + } + } + + // Store the ray color + rgbaArray[4*arrayCount ] = dynamicInfo->Color[0]; + rgbaArray[4*arrayCount+1] = dynamicInfo->Color[1]; + rgbaArray[4*arrayCount+2] = dynamicInfo->Color[2]; + rgbaArray[4*arrayCount+3] = dynamicInfo->Color[3]; + scalarArray[arrayCount] = dynamicInfo->ScalarValue; + + if ( !staticInfo->MIPFunction ) + { + // Do a sort pass (one iteration of bubble sort each time an + // element is added. The array stores element from farthest + // to closest + for ( k = arrayCount; + k > 0 && distanceArray[k] > distanceArray[k-1]; k-- ) + { + tmp = distanceArray[k]; + distanceArray[k] = distanceArray[k-1]; + distanceArray[k-1] = tmp; + + tmpArray[0] = rgbaArray[4*k ]; + tmpArray[1] = rgbaArray[4*k+1]; + tmpArray[2] = rgbaArray[4*k+2]; + tmpArray[3] = rgbaArray[4*k+3]; + + rgbaArray[4*k ] = rgbaArray[4*(k-1) ]; + rgbaArray[4*k+1] = rgbaArray[4*(k-1)+1]; + rgbaArray[4*k+2] = rgbaArray[4*(k-1)+2]; + rgbaArray[4*k+3] = rgbaArray[4*(k-1)+3]; + + rgbaArray[4*(k-1) ] = tmpArray[0]; + rgbaArray[4*(k-1)+1] = tmpArray[1]; + rgbaArray[4*(k-1)+2] = tmpArray[2]; + rgbaArray[4*(k-1)+3] = tmpArray[3]; + } + } + + arrayCount++; + } + } + + // Move the bit over by one + bitFlag = bitFlag << 1; + } + + // We have encountered something in at least one crop region - + // merge all results into one RGBA value + if ( arrayCount ) + { + // Is this MIP compositing? We need to treat this differently + if ( staticInfo->MIPFunction ) + { + dynamicInfo->Color[0] = 0.0; + dynamicInfo->Color[1] = 0.0; + dynamicInfo->Color[2] = 0.0; + dynamicInfo->Color[3] = 0.0; + dynamicInfo->ScalarValue = 0.0; + + // If we are maximizing the opacity, find the max Color[3] + if ( staticInfo->MaximizeOpacity ) + { + for ( k = 0; k < arrayCount; k++ ) + { + if ( rgbaArray[k*4+3] > dynamicInfo->Color[3] ) + { + dynamicInfo->Color[0] = rgbaArray[k*4 ]; + dynamicInfo->Color[1] = rgbaArray[k*4+1]; + dynamicInfo->Color[2] = rgbaArray[k*4+2]; + dynamicInfo->Color[3] = rgbaArray[k*4+3]; + } + } + } + // Otherwise we are maximizing scalar value + else + { + for ( k = 0; k < arrayCount; k++ ) + { + if ( scalarArray[k] > dynamicInfo->ScalarValue ) + { + dynamicInfo->Color[0] = rgbaArray[k*4 ]; + dynamicInfo->Color[1] = rgbaArray[k*4+1]; + dynamicInfo->Color[2] = rgbaArray[k*4+2]; + dynamicInfo->Color[3] = rgbaArray[k*4+3]; + dynamicInfo->ScalarValue = scalarArray[k]; + } + } + } + } + else + { + // Now we have the sorted distances / colors, put them together + // in a back-to-front order. First, initialize the color to black + // and the remaining opacity (color[3]) to 1.0 + dynamicInfo->Color[0] = 0.0; + dynamicInfo->Color[1] = 0.0; + dynamicInfo->Color[2] = 0.0; + dynamicInfo->Color[3] = 1.0; + + // Now do alpha blending, keeping remaining opacity in color[3] + for ( k = 0; k < arrayCount; k++ ) + { + dynamicInfo->Color[0] = dynamicInfo->Color[0] * + (1.0 - rgbaArray[k*4 + 3]) + rgbaArray[k*4 + 0]; + dynamicInfo->Color[1] = dynamicInfo->Color[1] * + (1.0 - rgbaArray[k*4 + 3]) + rgbaArray[k*4 + 1]; + dynamicInfo->Color[2] = dynamicInfo->Color[2] * + (1.0 - rgbaArray[k*4 + 3]) + rgbaArray[k*4 + 2]; + dynamicInfo->Color[3] *= 1.0 - rgbaArray[k*4 + 3]; + } + + // Take 1.0 - color[3] to convert from remaining opacity to alpha. + dynamicInfo->Color[3] = 1.0 - dynamicInfo->Color[3]; + } + + val = (dynamicInfo->Color[0]/dynamicInfo->Color[3])*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[0] = static_cast<unsigned char>(val); + + val = (dynamicInfo->Color[1]/dynamicInfo->Color[3])*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[1] = static_cast<unsigned char>(val); + + val = (dynamicInfo->Color[2]/dynamicInfo->Color[3])*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[2] = static_cast<unsigned char>(val); + + val = dynamicInfo->Color[3]*255.0; + val = (val > 255.0)?(255.0):(val); + val = (val < 0.0)?( 0.0):(val); + ucptr[3] = static_cast<unsigned char>(val); + } + } + + // Increment the image pointer + ucptr+=4; + } + } + + delete dynamicInfo; + + return VTK_THREAD_RETURN_VALUE; +} + +double vtkVolumeRayCastMapper::GetZBufferValue(int x, int y) +{ + int xPos, yPos; + + xPos = static_cast<int>(static_cast<float>(x) * this->ImageSampleDistance); + yPos = static_cast<int>(static_cast<float>(y) * this->ImageSampleDistance); + + xPos = (xPos >= this->ZBufferSize[0])?(this->ZBufferSize[0]-1):(xPos); + yPos = (yPos >= this->ZBufferSize[1])?(this->ZBufferSize[1]-1):(yPos); + + return *(this->ZBuffer + yPos*this->ZBufferSize[0] + xPos); +} + +int vtkVolumeRayCastMapper::ComputeRowBounds(vtkVolume *vol, + vtkRenderer *ren) +{ + float voxelPoint[3]; + float viewPoint[8][4]; + int i, j, k; + unsigned char *ucptr; + float minX, minY, maxX, maxY, minZ, maxZ; + + minX = 1.0; + minY = 1.0; + maxX = -1.0; + maxY = -1.0; + minZ = 1.0; + maxZ = 0.0; + + float bounds[6]; + int dim[3]; + + this->GetInput()->GetDimensions(dim); + bounds[0] = bounds[2] = bounds[4] = 0.0; + // The rounding tie-breaker is used to protect against a very small rounding error + // introduced in the QuickFloor function, which is used by the vtkFloorFuncMacro macro. + bounds[1] = static_cast<float>(dim[0]-1) - vtkFastNumericConversion::RoundingTieBreaker(); + bounds[3] = static_cast<float>(dim[1]-1) - vtkFastNumericConversion::RoundingTieBreaker(); + bounds[5] = static_cast<float>(dim[2]-1) - vtkFastNumericConversion::RoundingTieBreaker(); + + double camPos[3]; + double worldBounds[6]; + vol->GetBounds( worldBounds ); + int insideFlag = 0; + ren->GetActiveCamera()->GetPosition( camPos ); + if ( camPos[0] >= worldBounds[0] && + camPos[0] <= worldBounds[1] && + camPos[1] >= worldBounds[2] && + camPos[1] <= worldBounds[3] && + camPos[2] >= worldBounds[4] && + camPos[2] <= worldBounds[5] ) + { + insideFlag = 1; + } + + + // If we have a simple crop box then we can tighten the bounds + // See prior explanation of RoundingTieBreaker + if ( this->Cropping && this->CroppingRegionFlags == 0x2000 ) + { + bounds[0] = this->VoxelCroppingRegionPlanes[0]; + bounds[1] = this->VoxelCroppingRegionPlanes[1] - vtkFastNumericConversion::RoundingTieBreaker(); + bounds[2] = this->VoxelCroppingRegionPlanes[2]; + bounds[3] = this->VoxelCroppingRegionPlanes[3] - vtkFastNumericConversion::RoundingTieBreaker(); + bounds[4] = this->VoxelCroppingRegionPlanes[4]; + bounds[5] = this->VoxelCroppingRegionPlanes[5] - vtkFastNumericConversion::RoundingTieBreaker(); + } + + + // Copy the voxelsToView matrix to 16 floats + float voxelsToViewMatrix[16]; + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + voxelsToViewMatrix[j*4+i] = + static_cast<float>(this->VoxelsToViewMatrix->GetElement(j,i)); + } + } + + // Convert the voxel bounds to view coordinates to find out the + // size and location of the image we need to generate. + int idx = 0; + if ( insideFlag ) + { + minX = -1.0; + maxX = 1.0; + minY = -1.0; + maxY = 1.0; + minZ = 0.001; + maxZ = 0.001; + } + else + { + for ( k = 0; k < 2; k++ ) + { + voxelPoint[2] = bounds[4+k]; + for ( j = 0; j < 2; j++ ) + { + voxelPoint[1] = bounds[2+j]; + for ( i = 0; i < 2; i++ ) + { + voxelPoint[0] = bounds[i]; + vtkVRCMultiplyPointMacro( voxelPoint, viewPoint[idx], + voxelsToViewMatrix ); + + minX = (viewPoint[idx][0]<minX)?(viewPoint[idx][0]):(minX); + minY = (viewPoint[idx][1]<minY)?(viewPoint[idx][1]):(minY); + maxX = (viewPoint[idx][0]>maxX)?(viewPoint[idx][0]):(maxX); + maxY = (viewPoint[idx][1]>maxY)?(viewPoint[idx][1]):(maxY); + minZ = (viewPoint[idx][2]<minZ)?(viewPoint[idx][2]):(minZ); + maxZ = (viewPoint[idx][2]>maxZ)?(viewPoint[idx][2]):(maxZ); + idx++; + } + } + } + } + + if ( minZ < 0.001 || maxZ > 0.9999 ) + { + minX = -1.0; + maxX = 1.0; + minY = -1.0; + maxY = 1.0; + insideFlag = 1; + } + + this->MinimumViewDistance = + (minZ<0.001)?(0.001):((minZ>0.999)?(0.999):(minZ)); + + // We have min/max values from -1.0 to 1.0 now - we want to convert + // these to pixel locations. Give a couple of pixels of breathing room + // on each side if possible + minX = ( minX + 1.0 ) * 0.5 * this->ImageViewportSize[0] - 2; + minY = ( minY + 1.0 ) * 0.5 * this->ImageViewportSize[1] - 2; + maxX = ( maxX + 1.0 ) * 0.5 * this->ImageViewportSize[0] + 2; + maxY = ( maxY + 1.0 ) * 0.5 * this->ImageViewportSize[1] + 2; + + // If we are outside the view frustum return 0 - there is no need + // to render anything + if ( ( minX < 0 && maxX < 0 ) || + ( minY < 0 && maxY < 0 ) || + ( minX > this->ImageViewportSize[0]-1 && + maxX > this->ImageViewportSize[0]-1 ) || + ( minY > this->ImageViewportSize[1]-1 && + maxY > this->ImageViewportSize[1]-1 ) ) + { + return 0; + } + + int oldImageMemorySize[2]; + oldImageMemorySize[0] = this->ImageMemorySize[0]; + oldImageMemorySize[1] = this->ImageMemorySize[1]; + + // Swap the row bounds + int *tmpptr; + tmpptr = this->RowBounds; + this->RowBounds = this->OldRowBounds; + this->OldRowBounds = tmpptr; + + + // Check the bounds - the volume might project outside of the + // viewing box / frustum so clip it if necessary + minX = (minX<0)?(0):(minX); + minY = (minY<0)?(0):(minY); + maxX = (maxX>this->ImageViewportSize[0]-1)? + (this->ImageViewportSize[0]-1):(maxX); + maxY = (maxY>this->ImageViewportSize[1]-1)? + (this->ImageViewportSize[1]-1):(maxY); + + // Create the new image, and set its size and position + this->ImageInUseSize[0] = static_cast<int>(maxX - minX + 1.0); + this->ImageInUseSize[1] = static_cast<int>(maxY - minY + 1.0); + + // What is a power of 2 size big enough to fit this image? + this->ImageMemorySize[0] = 32; + this->ImageMemorySize[1] = 32; + while ( this->ImageMemorySize[0] < this->ImageInUseSize[0] ) + { + this->ImageMemorySize[0] *= 2; + } + while ( this->ImageMemorySize[1] < this->ImageInUseSize[1] ) + { + this->ImageMemorySize[1] *= 2; + } + + this->ImageOrigin[0] = static_cast<int>(minX); + this->ImageOrigin[1] = static_cast<int>(minY); + + // If the old image size is much too big (more than twice in + // either direction) then set the old width to 0 which will + // cause the image to be recreated + if ( oldImageMemorySize[0] > 2*this->ImageMemorySize[0] || + oldImageMemorySize[1] > 2*this->ImageMemorySize[1] ) + { + oldImageMemorySize[0] = 0; + } + + // If the old image is big enough (but not too big - we handled + // that above) then we'll bump up our required size to the + // previous one. This will keep us from thrashing. + if ( oldImageMemorySize[0] >= this->ImageMemorySize[0] && + oldImageMemorySize[1] >= this->ImageMemorySize[1] ) + { + this->ImageMemorySize[0] = oldImageMemorySize[0]; + this->ImageMemorySize[1] = oldImageMemorySize[1]; + } + + // Do we already have a texture big enough? If not, create a new one and + // clear it. + if ( !this->Image || + this->ImageMemorySize[0] > oldImageMemorySize[0] || + this->ImageMemorySize[1] > oldImageMemorySize[1] ) + { + // If there is an image there must be row bounds + if ( this->Image ) + { + delete [] this->Image; + delete [] this->RowBounds; + delete [] this->OldRowBounds; + } + + this->Image = new unsigned char[(this->ImageMemorySize[0] * + this->ImageMemorySize[1] * 4)]; + + // Create the row bounds array. This will store the start / stop pixel + // for each row. This helps eleminate work in areas outside the bounding + // hexahedron since a bounding box is not very tight. We keep the old ones + // too to help with only clearing where required + this->RowBounds = new int [2*this->ImageMemorySize[1]]; + this->OldRowBounds = new int [2*this->ImageMemorySize[1]]; + + for ( i = 0; i < this->ImageMemorySize[1]; i++ ) + { + this->RowBounds[i*2] = this->ImageMemorySize[0]; + this->RowBounds[i*2+1] = -1; + this->OldRowBounds[i*2] = this->ImageMemorySize[0]; + this->OldRowBounds[i*2+1] = -1; + } + + ucptr = this->Image; + + for ( i = 0; i < this->ImageMemorySize[0]*this->ImageMemorySize[1]; i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + } + + // If we are inside the volume our row bounds indicate every ray must be + // cast - we don't need to intersect with the 12 lines + if ( insideFlag ) + { + for ( j = 0; j < this->ImageInUseSize[1]; j++ ) + { + this->RowBounds[j*2] = 0; + this->RowBounds[j*2+1] = this->ImageInUseSize[0] - 1; + } + } + else + { + // create an array of lines where the y value of the first vertex is less + // than or equal to the y value of the second vertex. There are 12 lines, + // each containing x1, y1, x2, y2 values. + float lines[12][4]; + float x1, y1, x2, y2; + int xlow, xhigh; + int lineIndex[12][2] = {{0,1}, {2,3}, {4,5}, {6,7}, + {0,2}, {1,3} ,{4,6}, {5,7}, + {0,4}, {1,5}, {2,6}, {3,7}}; + + for ( i = 0; i < 12; i++ ) + { + x1 = (viewPoint[lineIndex[i][0]][0]+1.0) * + 0.5*this->ImageViewportSize[0] - this->ImageOrigin[0]; + + y1 = (viewPoint[lineIndex[i][0]][1]+1.0) * + 0.5*this->ImageViewportSize[1] - this->ImageOrigin[1]; + + x2 = (viewPoint[lineIndex[i][1]][0]+1.0) * + 0.5*this->ImageViewportSize[0] - this->ImageOrigin[0]; + + y2 = (viewPoint[lineIndex[i][1]][1]+1.0) * + 0.5*this->ImageViewportSize[1] - this->ImageOrigin[1]; + + if ( y1 < y2 ) + { + lines[i][0] = x1; + lines[i][1] = y1; + lines[i][2] = x2; + lines[i][3] = y2; + } + else + { + lines[i][0] = x2; + lines[i][1] = y2; + lines[i][2] = x1; + lines[i][3] = y1; + } + } + + // Now for each row in the image, find out the start / stop pixel + // If min > max, then no intersection occurred + for ( j = 0; j < this->ImageInUseSize[1]; j++ ) + { + this->RowBounds[j*2] = this->ImageMemorySize[0]; + this->RowBounds[j*2+1] = -1; + for ( i = 0; i < 12; i++ ) + { + if ( j >= lines[i][1] && j <= lines[i][3] && + ( lines[i][1] != lines[i][3] ) ) + { + x1 = lines[i][0] + + (static_cast<float>(j) - lines[i][1])/(lines[i][3] - lines[i][1]) * + (lines[i][2] - lines[i][0] ); + + xlow = static_cast<int>(x1 + 1.5); + xhigh = static_cast<int>(x1 - 1.0); + + xlow = (xlow<0)?(0):(xlow); + xlow = (xlow>this->ImageInUseSize[0]-1)? + (this->ImageInUseSize[0]-1):(xlow); + + xhigh = (xhigh<0)?(0):(xhigh); + xhigh = (xhigh>this->ImageInUseSize[0]-1)?( + this->ImageInUseSize[0]-1):(xhigh); + + if ( xlow < this->RowBounds[j*2] ) + { + this->RowBounds[j*2] = xlow; + } + if ( xhigh > this->RowBounds[j*2+1] ) + { + this->RowBounds[j*2+1] = xhigh; + } + } + } + // If they are the same this is either a point on the cube or + // all lines were out of bounds (all on one side or the other) + // It is safe to ignore the point (since the ray isn't likely + // to travel through it enough to actually take a sample) and it + // must be ignored in the case where all lines are out of range + if ( this->RowBounds[j*2] == this->RowBounds[j*2+1] ) + { + this->RowBounds[j*2] = this->ImageMemorySize[0]; + this->RowBounds[j*2+1] = -1; + } + } + } + + for ( j = this->ImageInUseSize[1]; j < this->ImageMemorySize[1]; j++ ) + { + this->RowBounds[j*2] = this->ImageMemorySize[0]; + this->RowBounds[j*2+1] = -1; + } + + for ( j = 0; j < this->ImageMemorySize[1]; j++ ) + { + // New bounds are not overlapping with old bounds - clear between + // old bounds only + if ( this->RowBounds[j*2+1] < this->OldRowBounds[j*2] || + this->RowBounds[j*2] > this->OldRowBounds[j*2+1] ) + { + ucptr = this->Image + 4*( j*this->ImageMemorySize[0] + + this->OldRowBounds[j*2] ); + for ( i = 0; + i <= (this->OldRowBounds[j*2+1] - this->OldRowBounds[j*2]); + i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + } + // New bounds do overlap with old bounds + else + { + // Clear from old min to new min + ucptr = this->Image + 4*( j*this->ImageMemorySize[0] + + this->OldRowBounds[j*2] ); + for ( i = 0; + i < (this->RowBounds[j*2] - this->OldRowBounds[j*2]); + i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + + // Clear from new max to old max + ucptr = this->Image + 4*( j*this->ImageMemorySize[0] + + this->RowBounds[j*2+1]+1 ); + for ( i = 0; + i < (this->OldRowBounds[j*2+1] - this->RowBounds[j*2+1]); + i++ ) + { + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + *(ucptr++) = 0; + } + + } + } + + return 1; +} + + +void vtkVolumeRayCastMapper::ComputeMatrices( vtkImageData *data, + vtkVolume *vol ) +{ + // Get the data spacing. This scaling is not accounted for in + // the volume's matrix, so we must add it in. + double volumeSpacing[3]; + data->GetSpacing( volumeSpacing ); + + // Get the origin of the data. This translation is not accounted for in + // the volume's matrix, so we must add it in. + float volumeOrigin[3]; + double *bds = data->GetBounds(); + volumeOrigin[0] = bds[0]; + volumeOrigin[1] = bds[2]; + volumeOrigin[2] = bds[4]; + + // Get the dimensions of the data. + int volumeDimensions[3]; + data->GetDimensions( volumeDimensions ); + + vtkTransform *voxelsTransform = this->VoxelsTransform; + vtkTransform *voxelsToViewTransform = this->VoxelsToViewTransform; + + // Get the volume matrix. This is a volume to world matrix right now. + // We'll need to invert it, translate by the origin and scale by the + // spacing to change it to a world to voxels matrix. + this->VolumeMatrix->DeepCopy( vol->GetMatrix() ); + voxelsToViewTransform->SetMatrix( VolumeMatrix ); + + // Create a transform that will account for the scaling and translation of + // the scalar data. The is the volume to voxels matrix. + voxelsTransform->Identity(); + voxelsTransform->Translate(volumeOrigin[0], + volumeOrigin[1], + volumeOrigin[2] ); + + voxelsTransform->Scale( volumeSpacing[0], + volumeSpacing[1], + volumeSpacing[2] ); + + // Now concatenate the volume's matrix with this scalar data matrix + voxelsToViewTransform->PreMultiply(); + voxelsToViewTransform->Concatenate( voxelsTransform->GetMatrix() ); + + // Now we actually have the world to voxels matrix - copy it out + this->WorldToVoxelsMatrix->DeepCopy( voxelsToViewTransform->GetMatrix() ); + this->WorldToVoxelsMatrix->Invert(); + + // We also want to invert this to get voxels to world + this->VoxelsToWorldMatrix->DeepCopy( voxelsToViewTransform->GetMatrix() ); + + // Compute the voxels to view transform by concatenating the + // voxels to world matrix with the projection matrix (world to view) + voxelsToViewTransform->PostMultiply(); + voxelsToViewTransform->Concatenate( this->PerspectiveMatrix ); + + this->VoxelsToViewMatrix->DeepCopy( voxelsToViewTransform->GetMatrix() ); + + this->ViewToVoxelsMatrix->DeepCopy( this->VoxelsToViewMatrix ); + this->ViewToVoxelsMatrix->Invert(); +} + +void vtkVolumeRayCastMapper::InitializeClippingPlanes( + vtkVolumeRayCastStaticInfo *staticInfo, + vtkPlaneCollection *planes ) +{ + vtkPlane *onePlane; + double worldNormal[3], worldOrigin[3]; + double volumeOrigin[4]; + int i; + float *worldToVoxelsMatrix; + float *voxelsToWorldMatrix; + int count; + float *clippingPlane; + float t; + + count = planes->GetNumberOfItems(); + staticInfo->NumberOfClippingPlanes = count; + + if ( !count ) + { + return; + } + + worldToVoxelsMatrix = staticInfo->WorldToVoxelsMatrix; + voxelsToWorldMatrix = staticInfo->VoxelsToWorldMatrix; + + staticInfo->ClippingPlane = new float [4*count]; + + // loop through all the clipping planes + for ( i = 0; i < count; i++ ) + { + onePlane = (vtkPlane *)planes->GetItemAsObject(i); + onePlane->GetNormal(worldNormal); + onePlane->GetOrigin(worldOrigin); + clippingPlane = staticInfo->ClippingPlane + 4*i; + vtkVRCMultiplyNormalMacro( worldNormal, + clippingPlane, + voxelsToWorldMatrix ); + vtkVRCMultiplyPointMacro( worldOrigin, volumeOrigin, + worldToVoxelsMatrix ); + + t = sqrt( clippingPlane[0]*clippingPlane[0] + + clippingPlane[1]*clippingPlane[1] + + clippingPlane[2]*clippingPlane[2] ); + if ( t ) + { + clippingPlane[0] /= t; + clippingPlane[1] /= t; + clippingPlane[2] /= t; + } + + clippingPlane[3] = -(clippingPlane[0]*volumeOrigin[0] + + clippingPlane[1]*volumeOrigin[1] + + clippingPlane[2]*volumeOrigin[2]); + } +} + + +int vtkVolumeRayCastMapper::ClipRayAgainstClippingPlanes( + vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo ) +{ + float *clippingPlane; + int i; + float rayDir[3]; + float t, point[3], dp; + float *rayStart, *rayEnd; + + rayStart = dynamicInfo->TransformedStart; + rayEnd = dynamicInfo->TransformedEnd; + + rayDir[0] = rayEnd[0] - rayStart[0]; + rayDir[1] = rayEnd[1] - rayStart[1]; + rayDir[2] = rayEnd[2] - rayStart[2]; + + // loop through all the clipping planes + for ( i = 0; i < staticInfo->NumberOfClippingPlanes; i++ ) + { + clippingPlane = staticInfo->ClippingPlane + 4*i; + + dp = + clippingPlane[0]*rayDir[0] + + clippingPlane[1]*rayDir[1] + + clippingPlane[2]*rayDir[2]; + + if ( dp != 0.0 ) + { + t = + -( clippingPlane[0]*rayStart[0] + + clippingPlane[1]*rayStart[1] + + clippingPlane[2]*rayStart[2] + clippingPlane[3]) / dp; + + if ( t > 0.0 && t < 1.0 ) + { + point[0] = rayStart[0] + t*rayDir[0]; + point[1] = rayStart[1] + t*rayDir[1]; + point[2] = rayStart[2] + t*rayDir[2]; + + if ( dp > 0.0 ) + { + rayStart[0] = point[0]; + rayStart[1] = point[1]; + rayStart[2] = point[2]; + } + else + { + rayEnd[0] = point[0]; + rayEnd[1] = point[1]; + rayEnd[2] = point[2]; + } + + rayDir[0] = rayEnd[0] - rayStart[0]; + rayDir[1] = rayEnd[1] - rayStart[1]; + rayDir[2] = rayEnd[2] - rayStart[2]; + + } + // If the clipping plane is outside the ray segment, then + // figure out if that means the ray segment goes to zero (if so + // return 0) or doesn't affect it (if so do nothing) + else + { + if ( dp >= 0.0 && t >= 1.0 ) + { + return 0; + } + if ( dp <= 0.0 && t <= 0.0 ) + { + return 0; + } + } + } + } + + return 1; +} + +int vtkVolumeRayCastMapper::ClipRayAgainstVolume( + vtkVolumeRayCastDynamicInfo *dynamicInfo, + float bounds[6] ) +{ + int loop; + float diff; + float t; + float *rayStart, *rayEnd, *rayDirection; + + rayStart = dynamicInfo->TransformedStart; + rayEnd = dynamicInfo->TransformedEnd; + rayDirection = dynamicInfo->TransformedDirection; + + if ( rayStart[0] >= bounds[1] || + rayStart[1] >= bounds[3] || + rayStart[2] >= bounds[5] || + rayStart[0] < bounds[0] || + rayStart[1] < bounds[2] || + rayStart[2] < bounds[4] ) + { + for ( loop = 0; loop < 3; loop++ ) + { + diff = 0; + + if ( rayStart[loop] < (bounds[2*loop]+0.01) ) + { + diff = (bounds[2*loop]+0.01) - rayStart[loop]; + } + else if ( rayStart[loop] > (bounds[2*loop+1]-0.01) ) + { + diff = (bounds[2*loop+1]-0.01) - rayStart[loop]; + } + + if ( diff ) + { + if ( rayDirection[loop] != 0.0 ) + { + t = diff / rayDirection[loop]; + } + else + { + t = -1.0; + } + + if ( t > 0.0 ) + { + rayStart[0] += rayDirection[0] * t; + rayStart[1] += rayDirection[1] * t; + rayStart[2] += rayDirection[2] * t; + } + } + } + } + + // If the voxel still isn't inside the volume, then this ray + // doesn't really intersect the volume + + if ( rayStart[0] >= bounds[1] || + rayStart[1] >= bounds[3] || + rayStart[2] >= bounds[5] || + rayStart[0] < bounds[0] || + rayStart[1] < bounds[2] || + rayStart[2] < bounds[4] ) + { + return 0; + } + + // The ray does intersect the volume, and we have a starting + // position that is inside the volume + if ( rayEnd[0] >= bounds[1] || + rayEnd[1] >= bounds[3] || + rayEnd[2] >= bounds[5] || + rayEnd[0] < bounds[0] || + rayEnd[1] < bounds[2] || + rayEnd[2] < bounds[4] ) + { + for ( loop = 0; loop < 3; loop++ ) + { + diff = 0; + + if ( rayEnd[loop] < (bounds[2*loop]+0.01) ) + { + diff = (bounds[2*loop]+0.01) - rayEnd[loop]; + } + else if ( rayEnd[loop] > (bounds[2*loop+1]-0.01) ) + { + diff = (bounds[2*loop+1]-0.01) - rayEnd[loop]; + } + + if ( diff ) + { + if ( rayDirection[loop] != 0.0 ) + { + t = diff / rayDirection[loop]; + } + else + { + t = 1.0; + } + + if ( t < 0.0 ) + { + rayEnd[0] += rayDirection[0] * t; + rayEnd[1] += rayDirection[1] * t; + rayEnd[2] += rayDirection[2] * t; + } + } + } + } + + // To be absolutely certain our ray remains inside the volume, + // recompute the ray direction (since it has changed - it is not + // normalized and therefore changes when start/end change) and move + // the start/end points in by 1/1000th of the distance. + float offset; + offset = (rayEnd[0] - rayStart[0])*0.001; + rayStart[0] += offset; + rayEnd[0] -= offset; + + offset = (rayEnd[1] - rayStart[1])*0.001; + rayStart[1] += offset; + rayEnd[1] -= offset; + + offset = (rayEnd[2] - rayStart[2])*0.001; + rayStart[2] += offset; + rayEnd[2] -= offset; + + if ( rayEnd[0] >= bounds[1] || + rayEnd[1] >= bounds[3] || + rayEnd[2] >= bounds[5] || + rayEnd[0] < bounds[0] || + rayEnd[1] < bounds[2] || + rayEnd[2] < bounds[4] ) + { + return 0; + } + + return 1; +} + +void vtkVolumeRayCastMapper::UpdateShadingTables( vtkRenderer *ren, + vtkVolume *vol ) +{ + int shading; + vtkVolumeProperty *volume_property; + + volume_property = vol->GetProperty(); + + shading = volume_property->GetShade(); + + this->GradientEstimator->SetInput( this->GetInput() ); + + if ( shading ) + { + this->GradientShader->UpdateShadingTable( ren, vol, + this->GradientEstimator ); + } +} + +float vtkVolumeRayCastMapper::GetZeroOpacityThreshold( vtkVolume *vol ) +{ + return( this->VolumeRayCastFunction->GetZeroOpacityThreshold( vol ) ); +} + +// Print method for vtkVolumeRayCastMapper +void vtkVolumeRayCastMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Sample Distance: " << this->SampleDistance << "\n"; + os << indent << "Image Sample Distance: " + << this->ImageSampleDistance << "\n"; + os << indent << "Minimum Image Sample Distance: " + << this->MinimumImageSampleDistance << "\n"; + os << indent << "Maximum Image Sample Distance: " + << this->MaximumImageSampleDistance << "\n"; + os << indent << "Auto Adjust Sample Distances: " + << this->AutoAdjustSampleDistances << "\n"; + os << indent << "Intermix Intersecting Geometry: " + << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n"); + + if ( this->VolumeRayCastFunction ) + { + os << indent << "Ray Cast Function: " << this->VolumeRayCastFunction<<"\n"; + } + else + { + os << indent << "Ray Cast Function: (none)\n"; + } + + if ( this->GradientEstimator ) + { + os << indent << "Gradient Estimator: " << (this->GradientEstimator) << + endl; + } + else + { + os << indent << "Gradient Estimator: (none)" << endl; + } + + if ( this->GradientShader ) + { + os << indent << "Gradient Shader: " << (this->GradientShader) << endl; + } + else + { + os << indent << "Gradient Shader: (none)" << endl; + } + +} + +//---------------------------------------------------------------------------- +void vtkVolumeRayCastMapper::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->GradientEstimator, + "GradientEstimator"); +} diff --git a/VolumeRendering/vtkVolumeRayCastMapper.h b/VolumeRendering/vtkVolumeRayCastMapper.h new file mode 100644 index 0000000..ff840a8 --- /dev/null +++ b/VolumeRendering/vtkVolumeRayCastMapper.h @@ -0,0 +1,283 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRayCastMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// .NAME vtkVolumeRayCastMapper - A slow but accurate mapper for rendering volumes +// .SECTION Description +// This is a software ray caster for rendering volumes in vtkImageData. + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkVolumeRayCastMapper_h +#define __vtkVolumeRayCastMapper_h + +#include "vtkVolumeMapper.h" +#include "vtkVolumeRayCastFunction.h" // For vtkVolumeRayCastStaticInfo + // and vtkVolumeRayCastDynamicInfo +#include "vtkFastNumericConversion.h" // for fast rounding and floor + +class vtkEncodedGradientEstimator; +class vtkEncodedGradientShader; +class vtkMatrix4x4; +class vtkMultiThreader; +class vtkPlaneCollection; +class vtkRenderer; +class vtkTimerLog; +class vtkVolume; +class vtkVolumeRayCastFunction; +class vtkVolumeTransform; +class vtkTransform; +class vtkRayCastImageDisplayHelper; + +//BTX +// Macro for floor of x + +inline int vtkFloorFuncMacro(double x) +{ + return vtkFastNumericConversion::QuickFloor(x); +} + + +// Macro for rounding x (for x >= 0) +inline int vtkRoundFuncMacro(double x) +{ + return vtkFastNumericConversion::Round(x); +} +//ETX + +// Macro for tri-linear interpolation - do four linear interpolations on +// edges, two linear interpolations between pairs of edges, then a final +// interpolation between faces +#define vtkTrilinFuncMacro(v,x,y,z,a,b,c,d,e,f,g,h) \ + t00 = a + (x)*(b-a); \ + t01 = c + (x)*(d-c); \ + t10 = e + (x)*(f-e); \ + t11 = g + (x)*(h-g); \ + t0 = t00 + (y)*(t01-t00); \ + t1 = t10 + (y)*(t11-t10); \ + v = t0 + (z)*(t1-t0); + +// Forward declaration needed for use by friend declaration below. +VTK_THREAD_RETURN_TYPE VolumeRayCastMapper_CastRays( void *arg ); + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeRayCastMapper : public vtkVolumeMapper +{ +public: + static vtkVolumeRayCastMapper *New(); + vtkTypeRevisionMacro(vtkVolumeRayCastMapper,vtkVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Set/Get the distance between samples. This variable is only + // used for sampling ray casting methods. Methods that compute + // a ray value by stepping cell-by-cell are not affected by this + // value. + vtkSetMacro( SampleDistance, double ); + vtkGetMacro( SampleDistance, double ); + + // Description: + // Get / Set the volume ray cast function. This is used to process + // values found along the ray to compute a final pixel value. + virtual void SetVolumeRayCastFunction(vtkVolumeRayCastFunction*); + vtkGetObjectMacro( VolumeRayCastFunction, vtkVolumeRayCastFunction ); + + // Description: + // Set / Get the gradient estimator used to estimate normals + virtual void SetGradientEstimator(vtkEncodedGradientEstimator *gradest); + vtkGetObjectMacro( GradientEstimator, vtkEncodedGradientEstimator ); + + // Description: + // Get the gradient shader. + vtkGetObjectMacro( GradientShader, vtkEncodedGradientShader ); + + // Description: + // Sampling distance in the XY image dimensions. Default value of 1 meaning + // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If + // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. + vtkSetClampMacro( ImageSampleDistance, double, 0.1, 100.0 ); + vtkGetMacro( ImageSampleDistance, double ); + + // Description: + // This is the minimum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MinimumImageSampleDistance, double, 0.1, 100.0 ); + vtkGetMacro( MinimumImageSampleDistance, double ); + + // Description: + // This is the maximum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MaximumImageSampleDistance, double, 0.1, 100.0 ); + vtkGetMacro( MaximumImageSampleDistance, double ); + + // Description: + // If AutoAdjustSampleDistances is on, the the ImageSampleDistance + // will be varied to achieve the allocated render time of this + // prop (controlled by the desired update rate and any culling in + // use). + vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 ); + vtkGetMacro( AutoAdjustSampleDistances, int ); + vtkBooleanMacro( AutoAdjustSampleDistances, int ); + + // Description: + // Set/Get the number of threads to use. This by default is equal to + // the number of available processors detected. + void SetNumberOfThreads( int num ); + int GetNumberOfThreads(); + + // Description: + // If IntermixIntersectingGeometry is turned on, the zbuffer will be + // captured and used to limit the traversal of the rays. + vtkSetClampMacro( IntermixIntersectingGeometry, int, 0, 1 ); + vtkGetMacro( IntermixIntersectingGeometry, int ); + vtkBooleanMacro( IntermixIntersectingGeometry, int ); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Initialize rendering for this volume. + void Render( vtkRenderer *, vtkVolume * ); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Release any graphics resources that are being consumed by this mapper. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Return the scalar value below which all opacities are zero + float GetZeroOpacityThreshold( vtkVolume *vol ); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Values needed by the volume + virtual float GetGradientMagnitudeScale(); + virtual float GetGradientMagnitudeBias(); + virtual float GetGradientMagnitudeScale(int) + {return this->GetGradientMagnitudeScale();}; + virtual float GetGradientMagnitudeBias(int) + {return this->GetGradientMagnitudeBias();}; + +//ETX + +protected: + vtkVolumeRayCastMapper(); + ~vtkVolumeRayCastMapper(); + + vtkVolumeRayCastFunction *VolumeRayCastFunction; + vtkEncodedGradientEstimator *GradientEstimator; + vtkEncodedGradientShader *GradientShader; + vtkRayCastImageDisplayHelper *ImageDisplayHelper; + + virtual void ReportReferences(vtkGarbageCollector*); + + // The distance between sample points along the ray + double SampleDistance; + double ImageSampleDistance; + double MinimumImageSampleDistance; + double MaximumImageSampleDistance; + int AutoAdjustSampleDistances; + + double WorldSampleDistance; + int ScalarDataType; + void *ScalarDataPointer; + + void UpdateShadingTables( vtkRenderer *ren, + vtkVolume *vol ); + + void ComputeMatrices( vtkImageData *data, vtkVolume *vol ); + int ComputeRowBounds( vtkVolume *vol, vtkRenderer *ren ); + + friend VTK_THREAD_RETURN_TYPE VolumeRayCastMapper_CastRays( void *arg ); + + vtkMultiThreader *Threader; + + vtkMatrix4x4 *PerspectiveMatrix; + vtkMatrix4x4 *ViewToWorldMatrix; + vtkMatrix4x4 *ViewToVoxelsMatrix; + vtkMatrix4x4 *VoxelsToViewMatrix; + vtkMatrix4x4 *WorldToVoxelsMatrix; + vtkMatrix4x4 *VoxelsToWorldMatrix; + + vtkMatrix4x4 *VolumeMatrix; + + vtkTransform *PerspectiveTransform; + vtkTransform *VoxelsTransform; + vtkTransform *VoxelsToViewTransform; + + // This is how big the image would be if it covered the entire viewport + int ImageViewportSize[2]; + + // This is how big the allocated memory for image is. This may be bigger + // or smaller than ImageFullSize - it will be bigger if necessary to + // ensure a power of 2, it will be smaller if the volume only covers a + // small region of the viewport + int ImageMemorySize[2]; + + // This is the size of subregion in ImageSize image that we are using for + // the current image. Since ImageSize is a power of 2, there is likely + // wasted space in it. This number will be used for things such as clearing + // the image if necessary. + int ImageInUseSize[2]; + + // This is the location in ImageFullSize image where our ImageSize image + // is located. + int ImageOrigin[2]; + + // This is the allocated image + unsigned char *Image; + + int *RowBounds; + int *OldRowBounds; + + float *RenderTimeTable; + vtkVolume **RenderVolumeTable; + vtkRenderer **RenderRendererTable; + int RenderTableSize; + int RenderTableEntries; + + void StoreRenderTime( vtkRenderer *ren, vtkVolume *vol, float t ); + float RetrieveRenderTime( vtkRenderer *ren, vtkVolume *vol ); + + int IntermixIntersectingGeometry; + + float *ZBuffer; + int ZBufferSize[2]; + int ZBufferOrigin[2]; + + float MinimumViewDistance; + + int ClipRayAgainstVolume( vtkVolumeRayCastDynamicInfo *dynamicInfo, + float bounds[6] ); + + void InitializeClippingPlanes( vtkVolumeRayCastStaticInfo *staticInfo, + vtkPlaneCollection *planes ); + + int ClipRayAgainstClippingPlanes( vtkVolumeRayCastDynamicInfo *dynamicInfo, + vtkVolumeRayCastStaticInfo *staticInfo); + + // Get the ZBuffer value corresponding to location (x,y) where (x,y) + // are indexing into the ImageInUse image. This must be converted to + // the zbuffer image coordinates. Nearest neighbor value is returned. + double GetZBufferValue( int x, int y ); + +private: + vtkVolumeRayCastMapper(const vtkVolumeRayCastMapper&); // Not implemented. + void operator=(const vtkVolumeRayCastMapper&); // Not implemented. +}; + +#endif + diff --git a/VolumeRendering/vtkVolumeRenderingFactory.cxx b/VolumeRendering/vtkVolumeRenderingFactory.cxx new file mode 100644 index 0000000..4eb1732 --- /dev/null +++ b/VolumeRendering/vtkVolumeRenderingFactory.cxx @@ -0,0 +1,109 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRenderingFactory.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkObjectFactory.h" + +#include "vtkVolumeRenderingFactory.h" +#include "vtkToolkits.h" +#include "vtkVolumeRenderingToolkit.h" +#include "vtkDebugLeaks.h" +#include "vtkGraphicsFactory.h" + +// if using some sort of opengl, then include these files +#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON) +#include "vtkOpenGLRayCastImageDisplayHelper.h" +#include "vtkOpenGLVolumeTextureMapper2D.h" +#include "vtkOpenGLVolumeTextureMapper3D.h" +#endif + +#if defined(VTK_USE_MANGLED_MESA) +#include "vtkMesaRayCastImageDisplayHelper.h" +#include "vtkMesaVolumeTextureMapper2D.h" +#endif + +#include "vtkCriticalSection.h" + +#include "stdlib.h" + +vtkCxxRevisionMacro(vtkVolumeRenderingFactory, "$Revision: 1.7 $"); +vtkStandardNewMacro(vtkVolumeRenderingFactory); + + +vtkObject* vtkVolumeRenderingFactory::CreateInstance(const char* vtkclassname ) +{ + // first check the object factory + vtkObject *ret = vtkObjectFactory::CreateInstance(vtkclassname); + if (ret) + { + return ret; + } + // if the factory failed to create the object, + // then destroy it now, as vtkDebugLeaks::ConstructClass was called + // with vtkclassname, and not the real name of the class +#ifdef VTK_DEBUG_LEAKS + vtkDebugLeaks::DestructClass(vtkclassname); +#endif + const char *rl = vtkGraphicsFactory::GetRenderLibrary(); + + +#if defined(VTK_USE_OGLR) || defined(_WIN32) || defined(VTK_USE_COCOA) || defined(VTK_USE_CARBON) + if (!strcmp("OpenGL",rl) || !strcmp("Win32OpenGL",rl) || !strcmp("CarbonOpenGL",rl) || !strcmp("CocoaOpenGL",rl)) + { + // 2D Volume Texture Mapper + if(strcmp(vtkclassname, "vtkVolumeTextureMapper2D") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::GetUseMesaClasses() ) + { + return vtkMesaVolumeTextureMapper2D::New(); + } +#endif + return vtkOpenGLVolumeTextureMapper2D::New(); + } + + // 3D Volume Texture Mapper + if(strcmp(vtkclassname, "vtkVolumeTextureMapper3D") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::GetUseMesaClasses() ) + { + vtkGenericWarningMacro("No support for mesa in vtkVolumeTextureMapper3D"); + return 0; + } +#endif + return vtkOpenGLVolumeTextureMapper3D::New(); + } + + // Ray Cast Image Display Helper + if(strcmp(vtkclassname, "vtkRayCastImageDisplayHelper") == 0) + { +#if defined(VTK_USE_MANGLED_MESA) + if ( vtkGraphicsFactory::GetUseMesaClasses() ) + { + return vtkMesaRayCastImageDisplayHelper::New(); + } +#endif + return vtkOpenGLRayCastImageDisplayHelper::New(); + } + } +#endif + + return 0; +} + +//---------------------------------------------------------------------------- +void vtkVolumeRenderingFactory::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/VolumeRendering/vtkVolumeRenderingFactory.h b/VolumeRendering/vtkVolumeRenderingFactory.h new file mode 100644 index 0000000..0220ea1 --- /dev/null +++ b/VolumeRendering/vtkVolumeRenderingFactory.h @@ -0,0 +1,44 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRenderingFactory.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeRenderingFactory - +// .SECTION Description + +#ifndef __vtkVolumeRenderingFactory_h +#define __vtkVolumeRenderingFactory_h + +#include "vtkObject.h" + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeRenderingFactory : public vtkObject +{ +public: + static vtkVolumeRenderingFactory *New(); + vtkTypeRevisionMacro(vtkVolumeRenderingFactory,vtkObject); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Create and return an instance of the named vtk object. + // This method first checks the vtkObjectFactory to support + // dynamic loading. + static vtkObject* CreateInstance(const char* vtkclassname); + +protected: + vtkVolumeRenderingFactory() {}; + +private: + vtkVolumeRenderingFactory(const vtkVolumeRenderingFactory&); // Not implemented. + void operator=(const vtkVolumeRenderingFactory&); // Not implemented. +}; + +#endif diff --git a/VolumeRendering/vtkVolumeRenderingToolkit.h.in b/VolumeRendering/vtkVolumeRenderingToolkit.h.in new file mode 100644 index 0000000..89a958b --- /dev/null +++ b/VolumeRendering/vtkVolumeRenderingToolkit.h.in @@ -0,0 +1,21 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeRenderingToolkit.h.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkVolumeRenderingToolkit_h +#define __vtkVolumeRenderingToolkit_h + +/* This header is configured by VTK's build process. */ +/* Nothing in here right now - keep for future use */ + +#endif diff --git a/VolumeRendering/vtkVolumeShearWarpDataStructure.h b/VolumeRendering/vtkVolumeShearWarpDataStructure.h new file mode 100644 index 0000000..99b7fbd --- /dev/null +++ b/VolumeRendering/vtkVolumeShearWarpDataStructure.h @@ -0,0 +1,1076 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeShearWarpDataStructure.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +//#include "vtkShearWarpBase.h" + +#define VTK_X_AXIS 0 +#define VTK_Y_AXIS 1 +#define VTK_Z_AXIS 2 +#define VTK_SHEAR_WARP_COMPOSITE_FUNCTION 0 +#define VTK_SHEAR_WARP_MIP_FUNCTION 1 +#define VTK_SHEAR_WARP_ISOSURFACE_FUNCTION 2 + +#define VTK_SHEAR_WARP_OCTREE_TRANSPARENT 0 +#define VTK_SHEAR_WARP_OCTREE_NONTRANSPARENT 1 +#define VTK_SHEAR_WARP_OCTREE_COMBINATION 2 +#define VTK_SHEAR_WARP_OCTREE_MINIMUM_SIZE 16 + +// Intermediate image pixel data for early ray termination +class vtkShearWarpPixelData +{ +public: + float Red; + float Green; + float Blue; + float Opacity; + float Value; + int Offset; +}; + + +// Runlength encoded intermediate image +class vtkShearWarpRLEImage +{ +public: + vtkShearWarpRLEImage(int size) + { + this->PixelData = new vtkShearWarpPixelData[size]; + this->ImageSize = size; + this->Clear(); + }; + + ~vtkShearWarpRLEImage() + { + if (this->PixelData != NULL) + delete[] this->PixelData; + }; + + // Reset all pixels to default values + void Clear() + { + for (int i = 0; i < this->ImageSize; i++) + { + this->PixelData[i].Red = 0.0f; + this->PixelData[i].Green = 0.0f; + this->PixelData[i].Blue = 0.0f; + this->PixelData[i].Opacity = 0.0f; + this->PixelData[i].Value = 0.0f; + this->PixelData[i].Offset = 0; + } + }; + + // Reset the current pixel pointer to the first pixel + void First(vtkShearWarpPixelData * &ptr) + { + ptr = this->PixelData; + }; + + // Sets the current pixel pointer to the specified position + void Position (vtkShearWarpPixelData * &ptr, int position) + { + ptr = this->PixelData + position; + }; + + // Advances the current pixel pointer by the specified increment + void Advance(vtkShearWarpPixelData * &ptr, int count) + { + ptr = ptr + count; + }; + + // Skip over transparent voxels and returns the count of skipped voxels + int Skip(vtkShearWarpPixelData * &ptr) + { + vtkShearWarpPixelData *data = ptr; + int runLength = 0; + int pathLength = 0; + int offset = 0; + + while (ptr->Offset > 0) + { + runLength += ptr->Offset; + ptr += ptr->Offset; + } + + data->Offset = runLength; + + while (data->Offset > 0) + { + offset = data->Offset; + data->Offset = runLength - pathLength; + pathLength += offset; + data += offset; + } + + return runLength; + }; + + // Retrieves a pointer to the first pixel + vtkShearWarpPixelData * GetPixelData() + { + return this->PixelData; + }; + + // Retrieves the allocated image size + int GetSize() + { + return this->ImageSize; + }; + +private: + // the pixel data + vtkShearWarpPixelData *PixelData; + + // the allocated image size + int ImageSize; + +}; + + +// Voxel data for runlength encoding, contains the scalar value and shading information +template <class T> +struct vtkShearWarpVoxelData +{ +public: + T Value; + unsigned short EncodedNormal; + unsigned char GradientMagnitude; +}; + + + +// An RLE run. It has a length and a pointer to the first voxel. +template <class T> +class vtkShearWarpRLERun +{ +public: + unsigned char Length; + vtkShearWarpVoxelData<T> *VoxelData; +}; + + +// A runlength encoded voxel slice which provides scanline-wise access to the data +template <class T> +class vtkShearWarpRLESlice +{ +public: + vtkShearWarpRLESlice() + { + this->SliceRuns = NULL; + this->VoxelData = NULL; + this->LineRuns = NULL; + }; + + ~vtkShearWarpRLESlice() + { + if (this->LineRuns != NULL) + delete[] this->LineRuns; + + if (this->SliceRuns != NULL) + delete[] this->SliceRuns; + + if (this->VoxelData != NULL) + delete[] this->VoxelData; + }; + + + // Encodes the data by opacity (for alpha compositing) + void encodeOpacity (vtkImageData* data, vtkVolume *volume, vtkEncodedGradientEstimator *gradest, int axis, int k, float opacityThreshold) + { + if (data == NULL || volume == NULL) + return; + + T voxelScalar = 0; + float voxelOpacity = 0.0f; + unsigned char currentIndex = 0; + int currentRun = 0; + int location = 0; + bool transparentRun = false; + + float *SOTF = volume->GetCorrectedScalarOpacityArray(); + + T *dptr = (T*) data->GetScalarPointer(); + unsigned short *nptr = gradest->GetEncodedNormals(); + unsigned char *gptr = gradest->GetGradientMagnitudes(); + + int i,j; + + int jCount = 0; + int iCount = 0; + int voxelIndex = 0; + + int *dimensions = data->GetDimensions(); + int plane = dimensions[0] * dimensions[1]; + int iIncrement,jIncrement; + int vi,vj,vk; + + switch (axis) + { + case VTK_X_AXIS: + iCount = dimensions[1]; + jCount = dimensions[2]; + vk = k; + iIncrement = dimensions[0]; + jIncrement = plane; + break; + + case VTK_Y_AXIS: + iCount = dimensions[2]; + jCount = dimensions[0]; + vk = k*dimensions[0]; + iIncrement = plane; + jIncrement = 1; + break; + + case VTK_Z_AXIS: + default: + iCount = dimensions[0]; + jCount = dimensions[1]; + vk = k*plane; + iIncrement = 1; + jIncrement = dimensions[0]; + break; + } + + // First we determine the number of runs in the slice + for (j=0,vj=0; j<jCount;j++, vj += jIncrement) + { + for (i=0,vi=0; i<iCount;i++, vi += iIncrement) + { + location = vi + vj + vk; + voxelScalar = dptr[location]; + voxelOpacity = SOTF[voxelScalar]; + + if (voxelOpacity > opacityThreshold) + { + if (!transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + currentIndex = 0; + currentRun++; + transparentRun = false; + } + + voxelIndex++; + + } + else + { + if (transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + currentIndex = 0; + currentRun++; + transparentRun = true; + } + } + } + } + + this->LineRuns = new vtkShearWarpRLERun<T>*[jCount]; + this->SliceRuns = new vtkShearWarpRLERun<T>[currentRun]; + this->VoxelData = new vtkShearWarpVoxelData<T>[voxelIndex]; + + vtkShearWarpRLERun<T> *activeRun = &this->SliceRuns[0]; + + voxelIndex = 0; + currentRun = 0; + + // Now we run-length-encode the slice + for (j=0,vj=0; j<jCount;j++, vj += jIncrement) + { + this->LineRuns[j] = activeRun; + currentIndex = 0; + + for (i=0,vi=0; i<iCount;i++, vi += iIncrement) + { + location = vi + vj + vk; + voxelScalar = dptr[location]; + voxelOpacity = SOTF[voxelScalar]; + + if (voxelOpacity > opacityThreshold) + { + + if (!transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + if (i > 0) + { + activeRun->Length = currentIndex + 1; + activeRun++; + currentRun++; + currentIndex = 0; + } + + activeRun->VoxelData = &this->VoxelData[voxelIndex]; + transparentRun = false; + } + + // Set voxel data + this->VoxelData[voxelIndex].Value = voxelScalar; + this->VoxelData[voxelIndex].EncodedNormal = nptr[location]; + this->VoxelData[voxelIndex].GradientMagnitude = gptr[location]; + + voxelIndex++; + } + else + { + if (transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + if (i > 0) + { + activeRun->Length = currentIndex + 1; + activeRun++; + currentRun++; + currentIndex = 0; + } + + activeRun->VoxelData = NULL; + transparentRun = true; + } + } + } + + activeRun->Length = currentIndex + 1; + activeRun++; + currentRun++; + + } + }; + + // Encodes the data by scalar value (for isosurface display) + void encodeScalar (vtkImageData* data, vtkVolume *volume, vtkEncodedGradientEstimator *gradest, int axis, int k, float isoValue) + { + if (data == NULL || volume == NULL) + return; + + T voxelScalar = 0; + unsigned char currentIndex = 0; + int currentRun = 0; + int location = 0; + bool transparentRun = false; + + T *dptr = (T*) data->GetScalarPointer(); + unsigned short *nptr = gradest->GetEncodedNormals(); + unsigned char *gptr = gradest->GetGradientMagnitudes(); + + int i,j; + + int jCount = 0; + int iCount = 0; + int voxelIndex = 0; + + int *dimensions = data->GetDimensions(); + int plane = dimensions[0] * dimensions[1]; + int iIncrement,jIncrement; + int vi,vj,vk; + + switch (axis) + { + case VTK_X_AXIS: + iCount = dimensions[1]; + jCount = dimensions[2]; + vk = k; + iIncrement = dimensions[0]; + jIncrement = plane; + break; + + case VTK_Y_AXIS: + iCount = dimensions[2]; + jCount = dimensions[0]; + vk = k*dimensions[0]; + iIncrement = plane; + jIncrement = 1; + break; + + case VTK_Z_AXIS: + default: + iCount = dimensions[0]; + jCount = dimensions[1]; + vk = k*plane; + iIncrement = 1; + jIncrement = dimensions[0]; + break; + } + + // First we determine the number of runs in the slice + for (j=0,vj=0; j<jCount;j++, vj += jIncrement) + { + for (i=0,vi=0; i<iCount;i++, vi += iIncrement) + { + location = vi + vj + vk; + voxelScalar = dptr[location]; + + if (voxelScalar >= isoValue) + { + if (!transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + currentIndex = 0; + currentRun++; + transparentRun = false; + } + + voxelIndex++; + + } + else + { + if (transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + currentIndex = 0; + currentRun++; + transparentRun = true; + } + } + } + } + + this->LineRuns = new vtkShearWarpRLERun<T>*[jCount]; + this->SliceRuns = new vtkShearWarpRLERun<T>[currentRun]; + this->VoxelData = new vtkShearWarpVoxelData<T>[voxelIndex]; + + vtkShearWarpRLERun<T> *activeRun = this->SliceRuns; + + voxelIndex = 0; + currentRun = 0; + + // Now we run-length-encode the slice + for (j=0,vj=0; j<jCount;j++, vj += jIncrement) + { + this->LineRuns[j] = activeRun; + currentIndex = 0; + + for (i=0,vi=0; i<iCount;i++, vi += iIncrement) + { + location = vi + vj + vk; + voxelScalar = dptr[location]; + + if (voxelScalar >= isoValue) + { + if (!transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + if (i > 0) + { + activeRun->Length = currentIndex + 1; + activeRun++; + currentRun++; + currentIndex = 0; + } + + activeRun->VoxelData = &this->VoxelData[voxelIndex]; + transparentRun = false; + } + + // Set voxel data + this->VoxelData[voxelIndex].Value = voxelScalar; + this->VoxelData[voxelIndex].EncodedNormal = nptr[location]; + this->VoxelData[voxelIndex].GradientMagnitude = gptr[location]; + + voxelIndex++; + } + else + { + if (transparentRun && i > 0 && currentIndex < 254) + { + currentIndex++; + } + else + { + if (i > 0) + { + activeRun->Length = currentIndex + 1; + activeRun++; + currentRun++; + currentIndex = 0; + } + + activeRun->VoxelData = NULL; + transparentRun = true; + } + } + } + + activeRun->Length = currentIndex + 1; + activeRun++; + currentRun++; + } + }; + + // Returns a pointer to the first run of a specified scanline + vtkShearWarpRLERun<T> * GetLineRuns(int line) + { + return this->LineRuns[line]; + } + +private: + // pointers to the first run for every scanline + vtkShearWarpRLERun<T> **LineRuns; + + // all runs of the slice + vtkShearWarpRLERun<T> *SliceRuns; + + // the voxel data of the slice + vtkShearWarpVoxelData<T> *VoxelData; + +}; + +// Base class for encoded volume +class vtkShearWarpBase : public vtkObjectBase +{ +public: + vtkShearWarpBase() + { + this->VolumeDimensions[0] = 0; + this->VolumeDimensions[1] = 0; + this->VolumeDimensions[2] = 0; + }; + + virtual ~vtkShearWarpBase() + { + }; + vtkTypeRevisionMacro(vtkShearWarpBase,vtkObjectBase); + + // Returns the volume dimensions + int * GetDimensions() + { + return this->VolumeDimensions; + }; + + // Returns the encoded isovalue, if the volume is scalar encoded + float GetIsoValue() + { + return this->IsoValue; + }; + + // Returns true if the volume is opacity encoded + bool IsOpacityEncoded() + { + return (this->OpacityEncoded == 1); + }; + + // Returns true if the volume is scalar encoded + bool IsScalarEncoded() + { + return (!this->OpacityEncoded && this->IsoValue >= 0.0); + } + +protected: + // the volume dimensions + int VolumeDimensions[3]; + + // the encoded isovalue + float IsoValue; + + // encoding type flag + int OpacityEncoded; +}; + + +// A runlength encoded volume. It contains voxel data encoded for each major viewing direction. +template <class T> +class VTK_VOLUMERENDERING_EXPORT vtkShearWarpRLEVolume : public vtkShearWarpBase +{ +public: + vtkShearWarpRLEVolume() + { + for (int l=0;l<3;l++) + this->EncodedSlices[l] = NULL; + + this->OpacityEncoded = 0; + this->IsoValue = -1.0f; + }; + + virtual ~vtkShearWarpRLEVolume() + { + for (int l=0;l<3;l++) + if (this->EncodedSlices[l] != NULL) + delete[] this->EncodedSlices[l]; + }; + + // Encodes the volume by opacity (for alpha-compositing) + void encodeOpacity(vtkImageData *data, vtkVolume *volume, vtkEncodedGradientEstimator* gradest, float opacityThreshold) + { + int l; + this->IsoValue = -1.0f; + this->OpacityEncoded = 1; + + for (l=0;l<3;l++) + { + if (this->EncodedSlices[l] != NULL) + { + delete[] this->EncodedSlices[l]; + } + } + + int *dimensions = data->GetDimensions(); + this->Volume = volume; + this->VolumeDimensions[0] = dimensions[0]; + this->VolumeDimensions[1] = dimensions[1]; + this->VolumeDimensions[2] = dimensions[2]; + + for (l=0; l<3; l++) + { + this->EncodedSlices[l] = new vtkShearWarpRLESlice<T>[dimensions[l]]; + + for (int k = 0; k < dimensions[l]; k++) + { + this->EncodedSlices[l][k].encodeOpacity(data,volume,gradest,l,k,opacityThreshold); + } + } + }; + + // Encodes the volume by scalar (for isosurface display) + void encodeScalar(vtkImageData *data, vtkVolume *volume, vtkEncodedGradientEstimator* gradest, float isoValue) + { + int l; + this->IsoValue = isoValue; + this->OpacityEncoded = 0; + + for (l=0;l<3;l++) + { + if (this->EncodedSlices[l] != NULL) + { + delete[] this->EncodedSlices[l]; + } + } + + int *dimensions = data->GetDimensions(); + this->Volume = volume; + this->VolumeDimensions[0] = dimensions[0]; + this->VolumeDimensions[1] = dimensions[1]; + this->VolumeDimensions[2] = dimensions[2]; + + for (l=0; l<3; l++) + { + this->EncodedSlices[l] = new vtkShearWarpRLESlice<T>[dimensions[l]]; + + for (int k = 0; k < dimensions[l]; k++) + { + this->EncodedSlices[l][k].encodeScalar(data,volume,gradest,l,k,isoValue); + } + } + }; + + // Returns the slice + vtkShearWarpRLESlice<T> * GetSlice(int axis, int slice) + { + return &this->EncodedSlices[axis][slice]; + }; + + // Returns a pointer to the source volume + vtkVolume * GetVolume() + { + return this->Volume; + }; + + +private: + // the encoded slices for all three principal axes + vtkShearWarpRLESlice<T> *EncodedSlices[3]; + + // the source volume + vtkVolume *Volume; + +}; + +template <class T> +class vtkShearWarpSummedAreaTable +{ +public: + vtkShearWarpSummedAreaTable() + { + this->Table = new float[2 << ((sizeof(T)*8)-1)]; + this->Opacity = NULL; + }; + + ~vtkShearWarpSummedAreaTable() + { + if (this->Table) + delete[] this->Table; + }; + + void build(float *SOTF, T upper) + { + this->Table[0] = SOTF[0]; + this->Opacity = SOTF; + + for (int i=1;i<=upper;i++) + { + this->Table[i] = this->Table[i-1] + SOTF[i]; + } + }; + + float integrate(T min, T max) + { + if (min != max) + return this->Table[max] - this->Table[min]; + else + return this->Opacity[min]; + + }; + +private: + float *Table; + float *Opacity; +}; + +struct vtkShearWarpOctreeRun +{ + unsigned short Length; + unsigned char Type; +}; + +template <class T> +class vtkShearWarpOctreeNode +{ +public: + vtkShearWarpOctreeNode() + { + this->Children = NULL; + }; + + ~vtkShearWarpOctreeNode() + { + if (this->Children != NULL) + delete[] this->Children; + }; + + T GetMinimum() + { + return this->Minimum; + }; + + T GetMaximum() + { + return this->Maximum; + }; + + void build(vtkImageData *data, int min[3], int max[3], int level) + { +// cout << "minX: " << min[0] << " - minY: " << min[1] << " - minZ: " << min[2] << "\n"; +// cout << "maxX: " << max[0] << " - maxY: " << max[1] << " - maxZ: " << max[2] << "\n\n"; + + if (this->Children != NULL) + { + delete[] this->Children; + this->Children = NULL; + } + + if (max[0] <= min[0] && max[1] <= min[1] && max[2] <= min[2]) + { + this->Minimum = *((T*) data->GetScalarPointer(max[0],max[1],max[2])); + this->Maximum = this->Minimum; + } + else + { + int center[3] = {(max[0]+min[0]) / 2, (max[1]+min[1]) / 2, (max[2]+min[2]) / 2}; + int newMin[3]; + int newMax[3]; + this->Children = new vtkShearWarpOctreeNode<T>[8]; + + newMin[0] = min[0]; + newMin[1] = min[1]; + newMin[2] = min[2]; + newMax[0] = center[0]; + newMax[1] = center[1]; + newMax[2] = center[2]; + this->Children[0].build(data,newMin,newMax,level+1); + + newMin[0] = center[0]+1; + newMin[1] = min[1]; + newMin[2] = min[2]; + newMax[0] = max[0]; + newMax[1] = center[1]; + newMax[2] = center[2]; + this->Children[1].build(data,newMin,newMax,level+1); + + newMin[0] = min[0]; + newMin[1] = center[1]+1; + newMin[2] = min[2]; + newMax[0] = center[0]; + newMax[1] = max[1]; + newMax[2] = center[2]; + this->Children[2].build(data,newMin,newMax,level+1); + + newMin[0] = center[0]+1; + newMin[1] = center[1]+1; + newMin[2] = min[2]; + newMax[0] = max[0]; + newMax[1] = max[1]; + newMax[2] = center[2]; + this->Children[3].build(data,newMin,newMax,level+1); + + newMin[0] = min[0]; + newMin[1] = min[1]; + newMin[2] = center[2]+1; + newMax[0] = center[0]; + newMax[1] = center[1]; + newMax[2] = max[2]; + this->Children[4].build(data,newMin,newMax,level+1); + + newMin[0] = center[0]+1; + newMin[1] = min[1]; + newMin[2] = center[2]+1; + newMax[0] = max[0]; + newMax[1] = center[1]; + newMax[2] = max[2]; + this->Children[5].build(data,newMin,newMax,level+1); + + newMin[0] = min[0]; + newMin[1] = center[1]+1; + newMin[2] = center[2]+1; + newMax[0] = center[0]; + newMax[1] = max[1]; + newMax[2] = max[2]; + this->Children[6].build(data,newMin,newMax,level+1); + + newMin[0] = center[0]+1; + newMin[1] = center[1]+1; + newMin[2] = center[2]+1; + newMax[0] = max[0]; + newMax[1] = max[1]; + newMax[2] = max[2]; + this->Children[7].build(data,newMin,newMax,level+1); + + this->Minimum = this->Children[0].Minimum; + this->Maximum = this->Children[0].Maximum; + + bool equalMinimum = true; + bool equalMaximum = true; + + for (int i=1; i < 8; i++) + { + if (this->Minimum != this->Children[i].Minimum) + { + if (this->Children[i].Minimum < this->Minimum) + this->Minimum = this->Children[i].Minimum; + + equalMinimum = false; + } + + if (this->Maximum != this->Children[i].Maximum) + { + if (this->Children[i].Maximum > this->Maximum) + this->Maximum = this->Children[i].Maximum; + + equalMaximum = false; + } + } + + // If minimum and maximum of all children are equal, we can remove them + if (equalMinimum && equalMaximum) + { + delete[] this->Children; + this->Children = NULL; + } + else + { + // Remove children if node already is at the lowest level +/* if ((max[0] - min[0] + 1) <= VTK_SHEAR_WARP_OCTREE_MINIMUM_SIZE && + (max[1] - min[1] + 1) <= VTK_SHEAR_WARP_OCTREE_MINIMUM_SIZE && + (max[2] - min[2] + 1) <= VTK_SHEAR_WARP_OCTREE_MINIMUM_SIZE)*/ + if (level >= 4) + { + delete[] this->Children; + this->Children = NULL; + } + } + } + }; + + void classifyOpacity(vtkShearWarpSummedAreaTable<T> *table) + { + float integral = table->integrate(this->Minimum,this->Maximum); + + if (integral == 0.0f) + { + this->Status = VTK_SHEAR_WARP_OCTREE_TRANSPARENT; + } + else if (this->Children == NULL) + { + this->Status = VTK_SHEAR_WARP_OCTREE_NONTRANSPARENT; + } + else + { + this->Status = VTK_SHEAR_WARP_OCTREE_COMBINATION; + + for (int i = 0; i < 8; i++) + this->Children[i].classifyOpacity(table); + } + }; + + void classifyScalar(T value) + { + if (this->Minimum >= value || this->Maximum >= value) + { + if (this->Children == NULL) + { + this->Status = VTK_SHEAR_WARP_OCTREE_NONTRANSPARENT; + } + else + { + this->Status = VTK_SHEAR_WARP_OCTREE_COMBINATION; + + for (int i = 0; i < 8; i++) + this->Children[i].classifyScalar(value); + } + } + else + { + this->Status = VTK_SHEAR_WARP_OCTREE_TRANSPARENT; + } + }; + + int computeRuns(vtkShearWarpOctreeRun *& runs, int axis, int slices, int lines, int voxels, int slice, int line) + { + static const int increments[3][3] = {{2,4,1},{4,1,2},{1,2,4}}; + + if (this->Status == VTK_SHEAR_WARP_OCTREE_COMBINATION) + { + int child = 0; +// int half = size / 2; + int halfSlices = slices / 2; + int halfLines = lines / 2; + int halfVoxels = voxels / 2; + + if (slice > halfSlices) + { + child += increments[axis][2]; + slice -= halfSlices; + + halfSlices = slices - halfSlices; + } + + if (line > halfLines) + { + child += increments[axis][1]; + line -= halfLines; + + halfLines = lines - halfLines; + } + + int a = this->Children[child].computeRuns(runs, axis, halfSlices, halfLines, halfVoxels, slice,line); + int b = this->Children[child + increments[axis][0]].computeRuns(runs, axis, halfSlices, halfLines, voxels-halfVoxels, slice,line); + + if (a < b) + return a; + else + return b; + } + else + { + if (runs->Type == this->Status) + { + runs->Length += voxels;//size; + } + else + { + if (runs[0].Type != 255) + runs++; + + runs->Type = this->Status; + runs->Length = voxels;//size; + } + + return voxels;//size; + + } + } + +private: + vtkShearWarpOctreeNode<T> *Children; + unsigned char Status; + T Minimum; + T Maximum; +}; + +template <class T> +class VTK_VOLUMERENDERING_EXPORT vtkShearWarpOctree : public vtkShearWarpBase +{ +public: + vtkTypeRevisionMacro(vtkShearWarpOctree,vtkShearWarpBase); + + vtkShearWarpOctree() + { + }; + + virtual ~vtkShearWarpOctree() + { + + }; + + void build(vtkImageData* data) + { + int min[3],max[3]; + data->GetDimensions(this->Dimensions); + data->GetExtent(min[0],max[0],min[1],max[1],min[2],max[2]); + this->Root.build(data,min,max,0); + }; + + void classifyOpacity(vtkVolume* volume) + { + this->Table.build(volume->GetCorrectedScalarOpacityArray(),this->Root.GetMaximum()); + this->Root.classifyOpacity(&this->Table); + this->OpacityEncoded = 1; + }; + + void classifyScalar(T value) + { + this->Root.classifyScalar(value); + this->OpacityEncoded = 0; + }; + + int GetLineRuns(vtkShearWarpOctreeRun *runs, int axis, int slice, int line) + { + static const int sizes[3][3] = {{this->Dimensions[1],this->Dimensions[2],this->Dimensions[0]}, + {this->Dimensions[2],this->Dimensions[0],this->Dimensions[1]}, + {this->Dimensions[0],this->Dimensions[1],this->Dimensions[2]}}; + + runs[0].Type = 255; + runs[0].Length = 0; + return this->Root.computeRuns(runs,axis,/*this->Dimensions[axis],*/sizes[axis][2],sizes[axis][1],sizes[axis][0],slice,line); + }; + +private: + vtkShearWarpOctreeNode<T> Root; + vtkShearWarpSummedAreaTable<T> Table; + int Dimensions[3]; + + vtkShearWarpOctree(const vtkShearWarpOctree&); // Not implemented. + void operator=(const vtkShearWarpOctree&); // Not implemented. +}; diff --git a/VolumeRendering/vtkVolumeShearWarpMapper.cxx b/VolumeRendering/vtkVolumeShearWarpMapper.cxx new file mode 100644 index 0000000..3385e98 --- /dev/null +++ b/VolumeRendering/vtkVolumeShearWarpMapper.cxx @@ -0,0 +1,5327 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeShearWarpMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeShearWarpMapper.h" +#include "vtkVolumeShearWarpDataStructure.h" + +#include "vtkVolume.h" +#include "vtkRenderer.h" +#include "vtkFiniteDifferenceGradientEstimator.h" +#include "vtkRenderWindow.h" +#include "vtkGraphicsFactory.h" +#include "vtkMatrix4x4.h" +#include "vtkTransform.h" +#include "vtkTimerLog.h" +#include "vtkPlaneCollection.h" + +#include "vtkEncodedGradientShader.h" +#include "vtkEncodedGradientEstimator.h" +#include "vtkStructuredPoints.h" +#include "vtkCamera.h" +#include "vtkImageData.h" +#include "vtkVolumeProperty.h" +#include "vtkPiecewiseFunction.h" + +#include "vtkOpenGLVolumeShearWarpMapper.h" + +#define vtkVSWMultiplyPointMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[1] + A[2]*M[2] + M[3]; \ + B[1] = A[0]*M[4] + A[1]*M[5] + A[2]*M[6] + M[7]; \ + B[2] = A[0]*M[8] + A[1]*M[9] + A[2]*M[10] + M[11]; \ + B[3] = A[0]*M[12] + A[1]*M[13] + A[2]*M[14] + M[15]; \ + if ( B[3] != 1.0 ) { B[0] /= B[3]; B[1] /= B[3]; B[2] /= B[3]; } + +#define vtkVSWMultiplyNormalMacro( A, B, M ) \ + B[0] = A[0]*M[0] + A[1]*M[4] + A[2]*M[8]; \ + B[1] = A[0]*M[1] + A[1]*M[5] + A[2]*M[9]; \ + B[2] = A[0]*M[2] + A[1]*M[6] + A[2]*M[10] + +vtkCxxRevisionMacro(vtkVolumeShearWarpMapper, "$Revision: 1.1 $"); +vtkCxxRevisionMacro(vtkShearWarpBase,"$Revision: 1.1 $"); +vtkCxxRevisionMacro(vtkShearWarpOctree<unsigned char>,"$Revision: 1.1 $"); +vtkCxxRevisionMacro(vtkShearWarpOctree<unsigned short>,"$Revision: 1.1 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkVolumeShearWarpMapper); +//---------------------------------------------------------------------------- + +// Factor the view matrix into shear and warp +void vtkVolumeShearWarpMapper::FactorViewMatrix() +{ + + ComputeViewportMatrix(); + ComputeViewMatrix(); + + if (this->ParallelProjection) + ComputePrincipalAxisParallel(); + else if (this->MyPerspectiveProjection) + ComputePrincipalAxisParallel(); + else +// ComputePrincipalAxisParallel(); + ComputePrincipalAxisPerspective(); + + + ComputePermutationMatrix(); + + if (this->ParallelProjection) + ComputeShearMatrixParallel(); + else if (this->MyPerspectiveProjection) + ComputeShearMatrixParallel(); + else +// ComputeShearMatrixParallel(); + ComputeShearMatrixPerspective(); + + ComputeWarpMatrix(); +} + + +// Compute the view matrix for parallel projection +void vtkVolumeShearWarpMapper::ComputeViewMatrix() +{ + vtkTransform *view = vtkTransform::New(); + view->SetMatrix(VoxelsToViewMatrix); + view->Inverse(); + + WorldViewingDirection[0] = 0.0; + WorldViewingDirection[1] = 0.0; + WorldViewingDirection[2] = 1.0; + WorldViewingDirection[3] = 0.0; + + WorldEyePosition[0] = 0.0; + WorldEyePosition[1] = 0.0; + WorldEyePosition[2] = -1.0; + WorldEyePosition[3] = 0.0; + + // Compute viewing direction in object space (for parallel projection) + view->MultiplyPoint(WorldViewingDirection,ObjectViewingDirection); + + // Compute eye position in object space (for perspective projection) + view->MultiplyPoint(WorldEyePosition,ObjectEyePosition); + +} + +// Compute the viewport matrix +void vtkVolumeShearWarpMapper::ComputeViewportMatrix() +{ + ViewportMatrix->Identity(); + ViewportMatrix->Element[0][0] = 0.5 * (double) ImageViewportSize[0]; + ViewportMatrix->Element[0][3] = 0.5 * (double) ImageViewportSize[0]; + ViewportMatrix->Element[1][1] = 0.5 * (double) ImageViewportSize[1]; + ViewportMatrix->Element[1][3] = 0.5 * (double) ImageViewportSize[1]; +} + + +// Compute the principal viewing axis for parallel projection +void vtkVolumeShearWarpMapper::ComputePrincipalAxisParallel() +{ + double x = fabs(ObjectViewingDirection[0]); + double y = fabs(ObjectViewingDirection[1]); + double z = fabs(ObjectViewingDirection[2]); + + if (x >= y) + { + if (x >= z) + this->MajorAxis = VTK_X_AXIS; + else + this->MajorAxis = VTK_Z_AXIS; + } + else + { + if (y >= z) + this->MajorAxis = VTK_Y_AXIS; + else + this->MajorAxis = VTK_Z_AXIS; + + } + + if (ObjectViewingDirection[this->MajorAxis] > 0) + this->ReverseOrder = 0; + else + this->ReverseOrder = 1; +} + +// Compute the principal viewing axis for perspective projection +void vtkVolumeShearWarpMapper::ComputePrincipalAxisPerspective() +{ + double vertex[3]; + double distance[3]; + double eye[3]; + double ax, ay, az; + double maximumDistance; + int maximumCount; + int count[3]; + int order[3]; + int axis[8]; + int i; + + eye[0] = ObjectEyePosition[0] / ObjectEyePosition[3]; + eye[1] = ObjectEyePosition[1] / ObjectEyePosition[3]; + eye[2] = ObjectEyePosition[2] / ObjectEyePosition[3]; + + // Find principal axes: + for (i=0; i<8; i++) + { + // Generate volume corners: + vertex[0] = -0.5 + (double)(i % 2); + vertex[1] = -0.5 + (double)((i/2) % 2); + vertex[2] = -0.5 + (double)((i/4) % 2); + + vertex[0] *= this->GetInput()->GetDimensions()[0]; + vertex[1] *= this->GetInput()->GetDimensions()[1]; + vertex[2] *= this->GetInput()->GetDimensions()[2]; + + distance[0] = vertex[0] - eye[0]; + distance[1] = vertex[1] - eye[1]; + distance[2] = vertex[2] - eye[2]; + + // Determine the principal viewing axis and the stacking order: + ax = fabs(distance[0]); + + ay = fabs(distance[1]); + az = fabs(distance[2]); + + maximumDistance = ax; + + if (ay > maximumDistance) + maximumDistance = ay; + + if (az > maximumDistance) + maximumDistance = az; + + if (maximumDistance == ax) + { + axis[i] = VTK_X_AXIS; + order[0] = (distance[0] < 0.0) ? 1 : 0; + } + else if (maximumDistance == ay) + { + axis[i] = VTK_Y_AXIS; + order[1] = (distance[1] < 0.0) ? 1 : 0; + } + else + { + axis[i] = VTK_Z_AXIS; + order[2] = (distance[2] < 0.0) ? 1 : 0; + } + } + + // Find the dominating principal axis: + for (i=0; i<3; i++) + count[i] = 0; + + for (i=0; i<8; i++) + { + switch (axis[i]) + { + case VTK_X_AXIS: + count[0]++; + break; + + case VTK_Y_AXIS: + count[1]++; + break; + + case VTK_Z_AXIS: + count[2]++; + break; + + default: + break; + } + } + + // Assign the dominant axis for the principal axis (favor the Z axis for ties): + maximumCount = count[0]; + + if (count[1] > maximumCount) + maximumCount = count[1]; + + if (count[2] > maximumCount) + maximumCount = count[2]; + + if (maximumCount == count[2]) + { + this->MajorAxis = VTK_Z_AXIS; + this->ReverseOrder = order[2]; + } + else if (maximumCount==count[1]) + { + this->MajorAxis = VTK_Y_AXIS; + this->ReverseOrder = order[1]; + } + else + { + this->MajorAxis = VTK_X_AXIS; + this->ReverseOrder = order[0]; + } +} + + +// Compute the permutation matrix (transformation from object space to standard object space) +void vtkVolumeShearWarpMapper::ComputePermutationMatrix() +{ + PermutationMatrix->Zero(); + + int size[3]; + GetInput()->GetDimensions(size); + + switch (this->MajorAxis) + + { + case VTK_X_AXIS: + PermutationMatrix->Element[0][1] = 1.0f; + PermutationMatrix->Element[1][2] = 1.0f; + PermutationMatrix->Element[2][0] = 1.0f; + PermutationMatrix->Element[3][3] = 1.0f; + + this->CountI = int(float(size[1]) / this->ImageSampleDistance); + this->CountJ = int(float(size[2]) / this->ImageSampleDistance); + this->CountK = int(float(size[0]) / this->ImageSampleDistance); + break; + + case VTK_Y_AXIS: + PermutationMatrix->Element[0][2] = 1.0f; + + PermutationMatrix->Element[1][0] = 1.0f; + PermutationMatrix->Element[2][1] = 1.0f; + PermutationMatrix->Element[3][3] = 1.0f; + + this->CountI = int(float(size[2]) / this->ImageSampleDistance); + this->CountJ = int(float(size[0]) / this->ImageSampleDistance); + this->CountK = int(float(size[1]) / this->ImageSampleDistance); + break; + + case VTK_Z_AXIS: + default: + PermutationMatrix->Element[0][0] = 1.0f; + PermutationMatrix->Element[1][1] = 1.0f; + PermutationMatrix->Element[2][2] = 1.0f; + PermutationMatrix->Element[3][3] = 1.0f; + + this->CountI = int(float(size[0]) / this->ImageSampleDistance); + this->CountJ = int(float(size[1]) / this->ImageSampleDistance); + this->CountK = int(float(size[2]) / this->ImageSampleDistance); + break; + } + + this->MaximumIntermediateDimension = size[0]; + + if (size[1] > this->MaximumIntermediateDimension) + this->MaximumIntermediateDimension = size[1]; + + if (size[2] > this->MaximumIntermediateDimension) + this->MaximumIntermediateDimension = size[2]; + + this->MaximumIntermediateDimension *= 2; + + // Compute the viewing direction in standard object space (for parallel projection) + this->PermutationMatrix->MultiplyPoint(ObjectViewingDirection,StandardViewingDirection); + + // Compute the eye position in standard object space (for perspective projection) + this->PermutationMatrix->MultiplyPoint(ObjectEyePosition,StandardEyePosition); + + // Compute the permuted view to voxel matrix + vtkMatrix4x4::Multiply4x4(this->PermutationMatrix,this->ViewToVoxelsMatrix,this->PermutedViewToVoxelsMatrix); + + // Compute the permuted voxel to view matrix + vtkMatrix4x4::Multiply4x4(this->PermutationMatrix,this->VoxelsToViewMatrix,this->PermutedVoxelsToViewMatrix); + + + // Get depth cueing factors + /* + this->DepthI = this->PermutedVoxelsToViewMatrix->Element[2][0]; + this->DepthJ = this->PermutedVoxelsToViewMatrix->Element[2][1]; + this->DepthK = this->PermutedVoxelsToViewMatrix->Element[2][2]; + this->Depth0 = this->PermutedVoxelsToViewMatrix->Element[2][3]; + */ + +} + +// Compute the shear matrix (transformation from object to intermediate image space) +void vtkVolumeShearWarpMapper::ComputeShearMatrixParallel() +{ + vtkMatrix4x4 *conv = vtkMatrix4x4::New(); // conversion to intermediate image coordinate system + vtkMatrix4x4 *shear = vtkMatrix4x4::New(); // shear standard object space to intermediate image space + + // Compute shear factors: + this->ShearI = - StandardViewingDirection[0] / StandardViewingDirection[2]; + this->ShearJ = - StandardViewingDirection[1] / StandardViewingDirection[2]; + this->Scale = 1.0f; + + /* compute the intermediate image size */ + this->IntermediateWidth = this->CountI + 1 + (int) ceil((this->CountK-1)*fabs(this->ShearI)); + this->IntermediateHeight = this->CountJ + 1 + (int) ceil((this->CountK-1)*fabs(this->ShearJ)); + + /* compute the translation coefficients */ + if (this->ShearI >= 0.0) + this->TranslationI = 1.0; + else + + this->TranslationI = 1.0 - this->ShearI * (double) (this->CountK - 1); + + if (this->ShearJ >= 0.0) + this->TranslationJ = 1.0; + else + this->TranslationJ = 1.0 - this->ShearJ * (double) (this->CountK - 1); + + // Assemble standard object space shear matrix from shear factors + shear->Identity(); + shear->Element[0][2] = this->ShearI; + shear->Element[1][2] = this->ShearJ; + + // Add scale factor depending on object size: +// shear->Scale((double) size[0] / (double) this->CountI, (double) size[1] / (double) this->CountJ, (double) size[2] / (double) this->CountK); + + // Create conversion matrix for intermediate image coordinates + conv->Identity(); + conv->Element[0][3] = 0.5 * (double) this->IntermediateWidth; + conv->Element[1][3] = 0.5 * (double) this->IntermediateHeight; + + vtkTransform *shearTransform = vtkTransform::New(); + shearTransform->SetMatrix(this->PermutationMatrix); + shearTransform->PostMultiply(); + shearTransform->Concatenate(shear); + shearTransform->Concatenate(conv); + this->ShearMatrix->DeepCopy(shearTransform->GetMatrix()); + shearTransform->Delete(); + + shear->Delete(); + conv->Delete(); + +} + +// Compute the shear matrix (transformation from object to intermediate image space) +void vtkVolumeShearWarpMapper::ComputeShearMatrixPerspective() +{ + + vtkMatrix4x4 *conv = vtkMatrix4x4::New(); // conversion to intermediate image coordinate system + vtkMatrix4x4 *shear = vtkMatrix4x4::New(); // shear standard object space to intermediate image space + vtkMatrix4x4 *scale = vtkMatrix4x4::New(); + + // Compute shear factors: fabs + this->ShearI = - StandardEyePosition[0] / StandardEyePosition[2]; + this->ShearJ = - StandardEyePosition[1] / StandardEyePosition[2]; + this->Scale = - StandardEyePosition[3] / StandardEyePosition[2]; + + float scaleFactor = 1.0; + +// if(this->Scale < 0.0) +// this->Scale = - this->Scale; + + + if (this->ReverseOrder==1) + scaleFactor = 1.0f / (1.0f - (this->CountK-1) * this->Scale); + + /* compute the intermediate image size */ + this->IntermediateWidth = this->CountI + 1 + (int) ceil((this->CountK-1)*fabs(this->ShearI));// - (int)(this->CountI - 1 - scaleFactor*(this->CountI-1)); + this->IntermediateHeight = this->CountJ + 1 + (int) ceil((this->CountK-1)*fabs(this->ShearJ));// - (int)(this->CountJ - 1 - scaleFactor*(this->CountJ-1)); + + /* compute the translation coefficients */ + + if (this->ShearI >= 0.0) + this->TranslationI = 1.0; + else + this->TranslationI = 1.0 - this->ShearI * (double) (this->CountK - 1); + + if (this->ShearJ >= 0.0) + this->TranslationJ = 1.0; + else + this->TranslationJ = 1.0 - this->ShearJ * (double) (this->CountK - 1); + + // Assemble standard object space shear matrix from shear factors + shear->Identity(); + shear->Element[0][2] = this->ShearI; + shear->Element[1][2] = this->ShearJ; + shear->Element[3][2] = this->Scale; + + // Add scale factor depending on object size: +// shear->Scale((double) size[0] / (double) this->CountI, (double) size[1] / (double) this->CountJ, (double) size[2] / (double) this->CountK); + + double sf; + + if (this->ReverseOrder) + sf = 1.0 + this->Scale * (double)(this->CountK - 1);// - shear->Element[3][2]; + else + sf = 1.0;//shear->Element[3][2] + 1; + +/* + double sf; + + if (this->ReverseOrder==1) + sf = 1.0 - shear->Element[3][2]; + else + sf = shear->Element[3][2] + 1.0; + + sf = 1.0 / sf; // invert scale factor +*/ + scale->Identity(); + scale->Element[0][0] = sf; + scale->Element[1][1] = sf; + + // Create conversion matrix for intermediate image coordinates + conv->Identity(); + conv->Element[0][3] = 0.5 * (double) this->IntermediateWidth; + conv->Element[1][3] = 0.5 * (double) this->IntermediateHeight; + + vtkTransform *shearTransform = vtkTransform::New(); + shearTransform->SetMatrix(this->PermutationMatrix); + shearTransform->PostMultiply(); +// shearTransform->Concatenate(scale); + shearTransform->Concatenate(shear); + shearTransform->Concatenate(conv); + this->ShearMatrix->DeepCopy(shearTransform->GetMatrix()); + shearTransform->Delete(); + + shear->Delete(); + scale->Delete(); + conv->Delete(); + + + + +/* + double lb[4] = { 0, 0, this->CountK, 1.0 }; + double rb[4] = { this->CountI, this->CountJ, this->CountK, 1.0 }; + double tlt[4],tlb[4],trb[4]; + shearTransform->MultiplyPoint(lb,tlb); + shearTransform->MultiplyPoint(rb,trb); + tlb[0] /= tlb[3]; + tlb[1] /= tlb[3]; + trb[0] /= trb[3]; + trb[1] /= trb[3]; + this->IntermediateWidth = trb[0] - tlb[0]; + this->IntermediateHeight = trb[1] - tlb[1]; + conv->Identity(); + conv->Element[0][3] = 0.5 * (double) this->IntermediateWidth; + conv->Element[1][3] = 0.5 * (double) this->IntermediateHeight; +*/ + + +} + +// Compute a the two-dimensional warp matrix +void vtkVolumeShearWarpMapper::ComputeWarpMatrix() +{ + + vtkTransform *warp = vtkTransform::New(); +/* + vtkTransform *inverse = vtkTransform::New(); + inverse->SetMatrix(this->ShearMatrix); + inverse->Inverse(); + + // Invert shear matrix + warp->SetMatrix(VoxelsToViewMatrix); + + // Compute warp matrix + warp->PreMultiply(); + warp->Concatenate(inverse); + + + warp->PreMultiply(); + warp->Concatenate(ViewportMatrix); + */ + + // Compute inverse of shear matrix: + warp->SetMatrix(ShearMatrix); + warp->Inverse(); + + // Compute warp matrices: + warp->PostMultiply(); + warp->Concatenate(VoxelsToViewMatrix); + warp->Concatenate(ViewportMatrix); + + WarpMatrix->DeepCopy(warp->GetMatrix()); + warp->Delete(); +} + +/* +// Compute a lookup table used for depth cueing +void vtkVolumeShearWarpMapper::ComputeDepthTable(int first, int last) +{ + for (int i = first; i <= last; i++) + this->DepthTable[i] = this->FrontDepth * exp(-this->DepthDensity*(1.0 - i*this->DeltaDepth)); + + this->DepthTableSize = last - first; +} + + +// Perfrom second step for fast depth cueing (multiply intermediate image by second depth factor) +void vtkVolumeShearWarpMapper::DepthCueImage (vtkShearWarpPixelData *im, int slice) +{ + + double depthQuant = 1.0 / this->DeltaDepth; + + float pixelDepth; + int pixelDepthInteger; + + float uSlice = this->ShearI * slice + this->TranslationI; + float vSlice = this->ShearJ * slice + this->TranslationJ; + float leftDepth = this->Depth0 + this->DepthK*slice - uSlice*this->DepthI - vSlice*this->DepthJ; + + if (this->DepthI > 0) + { + if (this->DepthJ > 0) + max_depth = left_depth + this->DepthI * width + this->DepthJ * height; + else + max_depth = left_depth + this->DepthI * width; + } + else + { + if (depth_dj > 0) + max_depth = left_depth + this->DepthJ * height; + else + max_depth = left_depth; + } + + max_depth_int = max_depth * depth_quant; + + if (max_depth_int >= vpc->dc_table_len) + { + // Resize table + } + + float di = this->DepthI * depthQuant; + float dj = this->DepthJ * depthQuant; + + leftDepth *= depthQuant; + + for (int j = this->IntermediateHeight; j > 0; j--) + { + pixelDepth = leftDepth; + leftDepth += dj; + + for (int i = this->IntermediateWidth; i > 0; i--) + { + pixelDepthInteger = pixelDepth; + pixelDepth += di; + + if (pixelDepthInteger < 0) + pixelDepthInteger = 0; + + if (pixelDepthInteger >= this->DepthTableSize) + { + // This shouldn't happen + pixelDepthInteger = this->DepthTableSize - 1; + } + + im->Red *= this->DepthTable[pixelDepthInteger]; + im->Green *= this->DepthTable[pixelDepthInteger]; + im->Blue *= this->DepthTable[pixelDepthInteger]; + im++; + } + } +} +*/ + +// Simple parallel projection shear-warp without runlength encoded volume using bilinear interpolation +template <class T> + +void CompositeIntermediateNearestSimple(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis) +{ + vtkShearWarpPixelData *pixels; + + float sampledRed,sampledGreen,sampledBlue,sampledOpacity; + float sampledValue; + float sampledGradientMagnitude; + float oldRed,oldGreen,oldBlue,oldOpacity; + float newRed,newGreen,newBlue,newOpacity; + float redDiffuse,greenDiffuse,blueDiffuse; + float redSpecular,greenSpecular,blueSpecular; + float gradientOpacity; + float isoRed; + float isoGreen; + float isoBlue; + + int skipped; + int i,j,k; + int vi,vj,vk; + + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float gradientOpacityConstant; + int gradientOpacityIsConstant; + unsigned short encodedNormal; + unsigned char gradientMagnitude; + + float uSlice; + float vSlice; + + int uSliceInteger; + int vSliceInteger; + + T value; + + int kStart; + int kEnd; + int kIncrement; + int vkStart; + int viIncrement; + int vjIncrement; + int vkIncrement; + + T *dptr = (T*) myThis->GetInput()->GetScalarPointer(); + + unsigned short *nptr = myThis->GradientEstimator->GetEncodedNormals(); + unsigned char *gptr = myThis->GradientEstimator->GetGradientMagnitudes(); + + int *dimensions = myThis->GetInput()->GetDimensions(); + int location; + int plane = dimensions[0]*dimensions[1]; + int halfDistance = myThis->ImageSampleDistance / 2; + + //float depthCueFactor; + //float depthCueRatio; + + if (myThis->ReverseOrder) + { + kStart = myThis->CountK - 1; + kEnd = -1 + halfDistance; + kIncrement = -1; + } + else + { + kStart = 0; + kEnd = myThis->CountK - halfDistance; + kIncrement = 1; + } + + SOTF = myThis->Volume->GetCorrectedScalarOpacityArray(); + CTF = myThis->Volume->GetRGBArray(); + GTF = myThis->Volume->GetGrayArray(); + GOTF = myThis->Volume->GetGradientOpacityArray(); + gradientOpacityConstant = myThis->Volume->GetGradientOpacityConstant(); + + if (gradientOpacityConstant > 0.0f) + gradientOpacityIsConstant = 1; + else + gradientOpacityIsConstant = 0; + + + if (myThis->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + isoRed = CTF[int(myThis->IsoValue)*3 + 0]; + isoGreen = CTF[int(myThis->IsoValue)*3 + 1]; + isoBlue = CTF[int(myThis->IsoValue)*3 + 2]; + } + + switch (myThis->MajorAxis) + { + case VTK_X_AXIS: + viIncrement = dimensions[0] * myThis->ImageSampleDistance; + vjIncrement = plane * myThis->ImageSampleDistance; + vkIncrement = kIncrement * myThis->ImageSampleDistance; + vkStart = kStart * myThis->ImageSampleDistance; + break; + + case VTK_Y_AXIS: + viIncrement = plane * myThis->ImageSampleDistance; + vjIncrement = myThis->ImageSampleDistance; + vkIncrement = kIncrement * dimensions[0] * myThis->ImageSampleDistance; + vkStart = kStart * dimensions[0] * myThis->ImageSampleDistance; + + break; + + + + case VTK_Z_AXIS: + default: + viIncrement = myThis->ImageSampleDistance; + vjIncrement = dimensions[0] * myThis->ImageSampleDistance; + vkIncrement = kIncrement * plane * myThis->ImageSampleDistance; + vkStart = kStart * plane * myThis->ImageSampleDistance; + + break; + } + + /* + float delta = myThis->DepthK - myThis->DepthI * myThis->ShearI - myThis->DepthJ * myThis->ShearJ; + + cout << "\n\nDELTA: " << delta << "\n\n"; + + if (myThis->ReverseOrder == 1) + delta = -delta; + + depthCueRatio = exp (myThis->DepthDensity * delta); + depthCueFactor = 1.0f; + */ + for (k = kStart, vk = vkStart; k != kEnd; k += kIncrement, vk += vkIncrement) + { + uSlice = k*myThis->ShearI + myThis->TranslationI; + vSlice = k*myThis->ShearJ + myThis->TranslationJ; + + uSliceInteger = (int) ceil(uSlice) - 1; + vSliceInteger = (int) ceil(vSlice) - 1; + + // Composite one slice into the intermediate image + for (j=0, vj = halfDistance; j < myThis->CountJ-halfDistance; j++, vj += vjIncrement) + { + image->Position(pixels,uSliceInteger + (vSliceInteger+j)*myThis->IntermediateWidth); + + for (i=0, vi = halfDistance; i < myThis->CountI-halfDistance; ) + { + // Skip opaque pixels in intermediate image + skipped = image->Skip(pixels); + + // Update both runs if to be aligned with intermediate pixels + if (skipped > 0) + { + i += skipped; + vi += viIncrement * skipped; + } + else + { + if (myThis->IntermixIntersectingGeometry) + { + float depth = myThis->IntermediateZBuffer[myThis->ImageSampleDistance * (uSliceInteger + i) + myThis->ImageSampleDistance * (vSliceInteger + j) * myThis->IntermediateWidth * myThis->ImageSampleDistance]; + + if (myThis->ReverseOrder) + { + if (k*myThis->ImageSampleDistance <= depth) + pixels->Offset = 1; + } + else + { + if (k*myThis->ImageSampleDistance >= depth) + pixels->Offset = 1; + } + + } + + // Only process non-opaque pixels + if (pixels->Offset == 0) + { + if (myThis->IsVoxelClipped(i*myThis->ImageSampleDistance,j*myThis->ImageSampleDistance,k*myThis->ImageSampleDistance) == 1) + { + image->Advance(pixels,1); + i++; + vi += viIncrement; + continue; + } + + + oldOpacity = pixels->Opacity; + oldRed = pixels->Red; + oldGreen = pixels->Green; + oldBlue = pixels->Blue; + + location = vi + vj + vk; + + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + sampledOpacity = 0.0f; + sampledRed = 0.0f; + sampledGreen = 0.0f; + sampledBlue = 0.0f; + + value = dptr[location]; + sampledOpacity += SOTF[value]; + sampledRed += CTF[value*3 + 0]; + sampledGreen += CTF[value*3 + 1]; + sampledBlue += CTF[value*3 + 2]; + + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + sampledGradientMagnitude = 0.0f; + gradientOpacity = gradientOpacityConstant; + + encodedNormal = nptr[location]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal]; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal]; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal]; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal]; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal]; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal]; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[location]; + sampledGradientMagnitude += float(gradientMagnitude); + + if (sampledGradientMagnitude > 255.0f) + gradientOpacity = GOTF[255]; + else if (sampledGradientMagnitude < 0.0f) + gradientOpacity = GOTF[0]; + else + gradientOpacity = GOTF[(unsigned char) sampledGradientMagnitude]; + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + sampledOpacity *= gradientOpacity; + } + + /* + if (1) + { + sampledRed *= depthCueFactor; + sampledGreen *= depthCueFactor; + sampledBlue *= depthCueFactor; + } + */ + + // Alpha Compositing + newRed = oldRed + sampledOpacity * sampledRed * (1.0f - oldOpacity); + newGreen = oldGreen + sampledOpacity * sampledGreen * (1.0f - oldOpacity); + newBlue = oldBlue + sampledOpacity * sampledBlue * (1.0f - oldOpacity); + newOpacity = oldOpacity + sampledOpacity * (1.0f - oldOpacity); + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + sampledValue = 0.0f; + + value = dptr[location]; + sampledValue += float(value); + + // Maximum Intensity Projection + if (sampledValue > pixels->Value) + { + + newRed = CTF[int(sampledValue)*3+0]; + newGreen = CTF[int(sampledValue)*3+1]; + newBlue = CTF[int(sampledValue)*3+2]; + newOpacity = SOTF[int(sampledValue)]; + pixels->Value = sampledValue; + } + else + + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + else + { + sampledValue = 0.0f; + + value = dptr[location]; + sampledValue += float(value); + + if (sampledValue >= myThis->IsoValue) + { + sampledRed = isoRed; + sampledGreen = isoGreen; + + sampledBlue = isoBlue; + + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + + encodedNormal = nptr[location]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal]; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal]; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal]; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal]; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal]; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal]; + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + } + + newRed = sampledRed; + newGreen = sampledGreen; + newBlue = sampledBlue; + newOpacity = 1.0f; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + + pixels->Red = newRed; + pixels->Green = newGreen; + pixels->Blue = newBlue; + pixels->Opacity = newOpacity; + + if (newOpacity >= 1.0f) + { + // The current intermediate pixel is opaque, so exit + // loop and skip opaque pixels + pixels->Offset = 1; + } + else + { + image->Advance(pixels,1); + i++; + vi += viIncrement; + } + + } + } + } + } + /* + depthCueFactor *= (pow(depthCueRatio,myThis->ImageSampleDistance)); + cout << depthCueFactor << ", "; + */ + } + + //myThis->DepthCueImage(image->GetPixelData(),(kEnd-kIncrement) * myThis->ImageSampleDistance); +} + + +// Simple parallel projection shear-warp without runlength encoded volume using bilinear interpolation +template <class T> +void CompositeIntermediateLinearSimple(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis) +{ + vtkShearWarpPixelData *pixels = 0; + + float sampledRed,sampledGreen,sampledBlue,sampledOpacity; + float sampledValue; + float sampledGradientMagnitude; + float oldRed,oldGreen,oldBlue,oldOpacity; + float newRed,newGreen,newBlue,newOpacity; + float redDiffuse,greenDiffuse,blueDiffuse; + float redSpecular,greenSpecular,blueSpecular; + float gradientOpacity; + + + float isoRed; + float isoGreen; + float isoBlue; + + int skipped; + + int i,j,k; + int vi,vj,vk; + + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float gradientOpacityConstant; + int gradientOpacityIsConstant; + unsigned short encodedNormal; + unsigned char gradientMagnitude; + + float uSlice; + float vSlice; + + int uSliceInteger; + int vSliceInteger; + + float uSliceFractional; + float vSliceFractional; + + + float weightTopLeft; + float weightBottomLeft; + float weightTopRight; + float weightBottomRight; + + float adjustedTL; + float adjustedTR; + float adjustedBL; + float adjustedBR; + + T value; + + int kStart; + int vkStart; + int kEnd; + int kIncrement; + int viIncrement; + int vjIncrement; + int vkIncrement; + + T *dptr = (T*) myThis->GetInput()->GetScalarPointer(); + + unsigned short *nptr = myThis->GradientEstimator->GetEncodedNormals(); + unsigned char *gptr = myThis->GradientEstimator->GetGradientMagnitudes(); + + int *dimensions = myThis->GetInput()->GetDimensions(); + int locationTL,locationTR,locationBL,locationBR; + int plane = dimensions[0]*dimensions[1]; + + if (myThis->ReverseOrder) + { + kStart = myThis->CountK - 1; + kEnd = -1; + kIncrement = -1; + } + else + { + kStart = 0; + kEnd = myThis->CountK; + kIncrement = 1; + } + + SOTF = myThis->Volume->GetCorrectedScalarOpacityArray(); + CTF = myThis->Volume->GetRGBArray(); + GTF = myThis->Volume->GetGrayArray(); + GOTF = myThis->Volume->GetGradientOpacityArray(); + gradientOpacityConstant = myThis->Volume->GetGradientOpacityConstant(); + + if (gradientOpacityConstant > 0.0f) + + gradientOpacityIsConstant = 1; + else + gradientOpacityIsConstant = 0; + + + if (myThis->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + isoRed = CTF[int(myThis->IsoValue)*3 + 0]; + isoGreen = CTF[int(myThis->IsoValue)*3 + 1]; + isoBlue = CTF[int(myThis->IsoValue)*3 + 2]; + } + + switch (myThis->MajorAxis) + { + case VTK_X_AXIS: + viIncrement = dimensions[0] * myThis->ImageSampleDistance; + vjIncrement = plane * myThis->ImageSampleDistance; + vkIncrement = kIncrement * myThis->ImageSampleDistance; + vkStart = kStart * myThis->ImageSampleDistance; + break; + + case VTK_Y_AXIS: + viIncrement = plane * myThis->ImageSampleDistance; + vjIncrement = myThis->ImageSampleDistance; + vkIncrement = kIncrement * dimensions[0] * myThis->ImageSampleDistance; + vkStart = kStart * dimensions[0] * myThis->ImageSampleDistance; + break; + + + case VTK_Z_AXIS: + default: + viIncrement = myThis->ImageSampleDistance; + vjIncrement = dimensions[0] * myThis->ImageSampleDistance; + vkIncrement = kIncrement * plane * myThis->ImageSampleDistance; + vkStart = kStart * plane * myThis->ImageSampleDistance; + break; + } + + + + for (k = kStart, vk = vkStart; k != kEnd; k += kIncrement, vk += vkIncrement) + { + uSlice = k*myThis->ShearI + myThis->TranslationI; + vSlice = k*myThis->ShearJ + myThis->TranslationJ; + + uSliceInteger = (int)ceil(uSlice) - 1; + vSliceInteger = (int)ceil(vSlice) - 1; + + uSliceFractional = uSlice - uSliceInteger; + vSliceFractional = vSlice - vSliceInteger; + + weightTopLeft = uSliceFractional * vSliceFractional; + weightBottomLeft = uSliceFractional * (1.0f - vSliceFractional); + + weightTopRight = (1.0f - uSliceFractional) * vSliceFractional; + weightBottomRight = (1.0f - uSliceFractional) * (1.0f - vSliceFractional); + + // Composite one slice into the intermediate image + for (j=0, vj = 0; j < myThis->CountJ; j++, vj += vjIncrement) + { + image->Position(pixels,uSliceInteger + (vSliceInteger+j)*myThis->IntermediateWidth); + + for (i=0, vi = 0; i < myThis->CountI; ) + { + // Skip opaque pixels in intermediate image + skipped = image->Skip(pixels); + + // Update both runs if to be aligned with intermediate pixels + if (skipped > 0) + { + i += skipped; + vi += viIncrement/*myThis->ImageSampleDistance*/ * skipped; + } + else + { + if (myThis->IntermixIntersectingGeometry) + { + float depth = myThis->IntermediateZBuffer[myThis->ImageSampleDistance * (uSliceInteger + i) + myThis->ImageSampleDistance * (vSliceInteger + j) * myThis->IntermediateWidth * myThis->ImageSampleDistance]; + + + if (myThis->ReverseOrder) + { + if (k*myThis->ImageSampleDistance <= depth) + pixels->Offset = 1; + } + else + { + + if (k*myThis->ImageSampleDistance >= depth) + pixels->Offset = 1; + } + } + + // Only process non-opaque pixels + if (pixels->Offset == 0) + { + if (myThis->IsVoxelClipped(i*myThis->ImageSampleDistance,j*myThis->ImageSampleDistance,k*myThis->ImageSampleDistance) == 1) + { + image->Advance(pixels,1); + i++; + + vi += viIncrement; + continue; + } + + + + oldOpacity = pixels->Opacity; + oldRed = pixels->Red; + oldGreen = pixels->Green; + oldBlue = pixels->Blue; + + locationTL = vi + vj + vk; + locationTR = locationTL + viIncrement; + locationBL = locationTL + vjIncrement; + locationBR = locationBL + viIncrement; + +/* switch (myThis->MajorAxis) + { + case VTK_X_AXIS: + locationTL = vj * plane + vi *dimensions[0] + vk; + + + locationTR = vj * plane + (vi+myThis->ImageSampleDistance) *dimensions[0] + vk; + locationBL = (vj+myThis->ImageSampleDistance) * plane + vi *dimensions[0] + vk; + locationBR = (vj+myThis->ImageSampleDistance) * plane + vi *dimensions[0] + vk; + + break; + + case VTK_Y_AXIS: + locationTL = vi * plane + vk *dimensions[0] + vj; + locationTR = (vi+myThis->ImageSampleDistance) * plane + vk *dimensions[0] + vj; + locationBL = vi * plane + vk *dimensions[0] + (vj+myThis->ImageSampleDistance); + locationBR = (vi+myThis->ImageSampleDistance) * plane + vk *dimensions[0] + (vj+myThis->ImageSampleDistance); + break; + + case VTK_Z_AXIS: + default: + locationTL = vk * plane + vj *dimensions[0] + vi; + locationTR = vk * plane + vj *dimensions[0] + (vi+myThis->ImageSampleDistance); + locationBL = vk * plane + (vj+myThis->ImageSampleDistance) *dimensions[0] + vi; + locationBR = vk * plane + (vj+myThis->ImageSampleDistance) *dimensions[0] + (vi+myThis->ImageSampleDistance); + break; + }*/ + + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + + sampledOpacity = 0.0f; + sampledRed = 0.0f; + sampledGreen = 0.0f; + sampledBlue = 0.0f; + + value = dptr[locationTL]; + sampledOpacity += SOTF[value] * weightTopLeft; + sampledRed += CTF[value*3 + 0] * weightTopLeft; + sampledGreen += CTF[value*3 + 1] * weightTopLeft; + sampledBlue += CTF[value*3 + 2] * weightTopLeft; + + + if (i + 1 < myThis->CountI) + { + value = dptr[locationTR]; + sampledOpacity += SOTF[value] * weightTopRight; + sampledRed += CTF[value*3 + 0] * weightTopRight; + sampledGreen += CTF[value*3 + 1] * weightTopRight; + sampledBlue += CTF[value*3 + 2] * weightTopRight; + } + + if (j + 1 < myThis->CountJ) + { + value = dptr[locationBL]; + sampledOpacity += SOTF[value] * weightBottomLeft; + sampledRed += CTF[value*3 + 0] * weightBottomLeft; + sampledGreen += CTF[value*3 + 1] * weightBottomLeft; + sampledBlue += CTF[value*3 + 2] * weightBottomLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationBR]; + sampledOpacity += SOTF[value] * weightBottomRight; + sampledRed += CTF[value*3 + 0] * weightBottomRight; + sampledGreen += CTF[value*3 + 1] * weightBottomRight; + sampledBlue += CTF[value*3 + 2] * weightBottomRight; + } + } + + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + sampledGradientMagnitude = 0.0f; + + gradientOpacity = gradientOpacityConstant; + + encodedNormal = nptr[locationTL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightTopLeft; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightTopLeft; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightTopLeft; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightTopLeft; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightTopLeft; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightTopLeft; + + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[locationTL]; + sampledGradientMagnitude += float(gradientMagnitude) * weightTopLeft; + } + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationTR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightTopRight; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightTopRight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightTopRight; + + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightTopRight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightTopRight; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightTopRight; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[locationTR]; + sampledGradientMagnitude += float(gradientMagnitude) * weightTopRight; + } + } + + if (j + 1 < myThis->CountJ) + { + encodedNormal = nptr[locationBL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightBottomLeft; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightBottomLeft; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightBottomLeft; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightBottomLeft; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightBottomLeft; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightBottomLeft; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[locationBL]; + sampledGradientMagnitude += float(gradientMagnitude) * weightBottomLeft; + } + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationBR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightBottomRight; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightBottomRight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightBottomRight; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightBottomRight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightBottomRight; + + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightBottomRight; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[locationBR]; + sampledGradientMagnitude += float(gradientMagnitude) * weightBottomRight; + } + } + } + + if (!gradientOpacityIsConstant) + { + if (sampledGradientMagnitude > 255.0f) + gradientOpacity = GOTF[255]; + else if (sampledGradientMagnitude < 0.0f) + gradientOpacity = GOTF[0]; + else + gradientOpacity = GOTF[(unsigned char) sampledGradientMagnitude]; + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + sampledOpacity *= gradientOpacity; + } + + // Alpha Compositing + newRed = oldRed + sampledOpacity * sampledRed * (1.0f - oldOpacity); + newGreen = oldGreen + sampledOpacity * sampledGreen * (1.0f - oldOpacity); + newBlue = oldBlue + sampledOpacity * sampledBlue * (1.0f - oldOpacity); + newOpacity = oldOpacity + sampledOpacity * (1.0f - oldOpacity); + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + sampledValue = 0.0f; + + value = dptr[locationTL]; + sampledValue += float(value) * weightTopLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationTR]; + sampledValue += float(value) * weightTopRight; + } + + if (j + 1 < myThis->CountJ) + { + value = dptr[locationBL]; + sampledValue += float(value) * weightBottomLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationBR]; + sampledValue += float(value) * weightBottomRight; + } + } + + // Maximum Intensity Projection + if (sampledValue > pixels->Value) + { + newRed = CTF[int(sampledValue)*3+0]; + newGreen = CTF[int(sampledValue)*3+1]; + newBlue = CTF[int(sampledValue)*3+2]; + newOpacity = SOTF[int(sampledValue)]; + + pixels->Value = sampledValue; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + else + { + sampledRed = isoRed; + sampledGreen = isoGreen; + sampledBlue = isoBlue; + + sampledValue = 0.0f; + + value = dptr[locationTL]; + sampledValue += float(value) * weightTopLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationTR]; + sampledValue += float(value) * weightTopRight; + } + + if (j + 1 < myThis->CountJ) + { + value = dptr[locationBL]; + sampledValue += float(value) * weightBottomLeft; + + if (i + 1 < myThis->CountI) + + { + value = dptr[locationBR]; + sampledValue += float(value) * weightBottomRight; + } + } + + // Maximum Intensity Projection + if (sampledValue >= myThis->IsoValue) + { + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + + adjustedTL = weightTopLeft; + adjustedBL = weightBottomLeft; + adjustedTR = weightTopRight; + adjustedBR = weightBottomRight; + + if (i + 1 >= myThis->CountI) + { + adjustedTL += adjustedTR; + adjustedBL += adjustedBR; + } + + if (j + 1 >= myThis->CountJ) + { + adjustedTL += adjustedBL; + adjustedTR += adjustedBR; + } + + encodedNormal = nptr[locationTL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedTL; + + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedTL; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedTL; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedTL; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedTL; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedTL; + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationTR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedTR; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedTR; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedTR; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedTR; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedTR; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedTR; + } + + if (j + 1 < myThis->CountJ) + { + encodedNormal = nptr[locationBL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedBL; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedBL; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedBL; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedBL; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedBL; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedBL; + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationBR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedBR; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedBR; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedBR; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedBR; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedBR; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedBR; + + } + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + + } + + + newRed = sampledRed; + newGreen = sampledGreen; + newBlue = sampledBlue; + newOpacity = 1.0f; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + + + pixels->Red = newRed; + pixels->Green = newGreen; + pixels->Blue = newBlue; + pixels->Opacity = newOpacity; + + if (newOpacity >= 1.0f) + { + // The current intermediate pixel is opaque, so exit + + // loop and skip opaque pixels + pixels->Offset = 1; + + } + else + { + image->Advance(pixels,1); + i++; + vi += viIncrement; + } + } + } + } + + } + } +} + +// Lacroute's parallel projection shear-warp algorithm with runlength encoded volume using nearest neighbour interpolation +template <class T> +void CompositeIntermediateNearestRLE(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis) +{ + vtkShearWarpRLESlice<T> *slice; + vtkShearWarpRLERun<T> *top; + vtkShearWarpPixelData *pixels; + + float sampledRed,sampledGreen,sampledBlue,sampledOpacity; + float sampledValue; + float sampledGradientMagnitude; + float oldRed,oldGreen,oldBlue,oldOpacity; + + float newRed,newGreen,newBlue,newOpacity; + float redDiffuse,greenDiffuse,blueDiffuse; + float redSpecular,greenSpecular,blueSpecular; + float gradientOpacity; + + float isoRed; + float isoGreen; + float isoBlue; + + int topIndex; + + int skipped; + int runLength; + + int i,j,k; + int vj,vk; + + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float gradientOpacityConstant; + int gradientOpacityIsConstant; + unsigned short encodedNormal; + unsigned char gradientMagnitude; + + float uSlice; + float vSlice; + + int uSliceInteger; + int vSliceInteger; + + T value; + + int kStart; + int kEnd; + int kIncrement; + int vkStart; + int vkIncrement; + + int halfDistance = myThis->ImageSampleDistance / 2; + + vtkShearWarpRLEVolume<T> *encodedVolume = dynamic_cast< vtkShearWarpRLEVolume<T> * > (myThis->EncodedVolume); + + if (myThis->ReverseOrder) + { + kStart = myThis->CountK - 1; + kEnd = -1 + halfDistance; + + kIncrement = -1; + + vkStart = (myThis->CountK - 1) * myThis->ImageSampleDistance - halfDistance; + vkIncrement = -myThis->ImageSampleDistance; + } + else + { + kStart = 0; + kEnd = myThis->CountK - halfDistance; + kIncrement = 1; + + vkStart = halfDistance; + vkIncrement = myThis->ImageSampleDistance; + } + + SOTF = myThis->Volume->GetCorrectedScalarOpacityArray(); + CTF = myThis->Volume->GetRGBArray(); + GTF = myThis->Volume->GetGrayArray(); + GOTF = myThis->Volume->GetGradientOpacityArray(); + gradientOpacityConstant = myThis->Volume->GetGradientOpacityConstant(); + + if (gradientOpacityConstant > 0.0f) + gradientOpacityIsConstant = 1; + else + gradientOpacityIsConstant = 0; + + + if (myThis->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + isoRed = CTF[int(myThis->IsoValue)*3 + 0]; + isoGreen = CTF[int(myThis->IsoValue)*3 + 1]; + isoBlue = CTF[int(myThis->IsoValue)*3 + 2]; + } + + for (k = kStart, vk = vkStart; k != kEnd; k += kIncrement, vk += vkIncrement) + { + uSlice = k*myThis->ShearI + myThis->TranslationI; + vSlice = k*myThis->ShearJ + myThis->TranslationJ; + + uSliceInteger = (int)ceil(uSlice) - 1; + vSliceInteger = (int)ceil(vSlice) - 1; + + slice = encodedVolume->GetSlice(myThis->MajorAxis,vk); + + // Composite one slice into the intermediate image + for (j=0, vj = halfDistance; j < myThis->CountJ-halfDistance; j++, vj += myThis->ImageSampleDistance) + { + top = slice->GetLineRuns(vj); + topIndex = halfDistance; + + while (topIndex >= top->Length) + + { + topIndex -= top->Length; + top++; + } + + image->Position(pixels,uSliceInteger + (vSliceInteger+j)*myThis->IntermediateWidth); + + + for (i=0; i < myThis->CountI; ) + { + // Update run + while (topIndex >= top->Length) + { + + topIndex -= top->Length; + top++; + } + + // Skip opaque pixels in intermediate image + skipped = image->Skip(pixels); + + // Update both runs if to be aligned with intermediate pixels + if (skipped > 0) + { + i += skipped; + topIndex += skipped * myThis->ImageSampleDistance; + } + else + { + runLength = top->Length - topIndex; + + // Skip transparent voxels + + + if (top->VoxelData == NULL) + { + while (topIndex < top->Length) + { + image->Advance(pixels,1); + i++; + topIndex += myThis->ImageSampleDistance; + } + + } + else + { + + // This loops samples voxels, performs shading and performs + // compositing into the intermediate image + while (topIndex < top->Length)//h=0; h < runLength; h+=myThis->ImageSampleDistance) + { + if (myThis->IntermixIntersectingGeometry) + { + float depth = myThis->IntermediateZBuffer[myThis->ImageSampleDistance * (uSliceInteger + i) + myThis->ImageSampleDistance * (vSliceInteger + j) * myThis->IntermediateWidth * myThis->ImageSampleDistance]; + + if (myThis->ReverseOrder) + { + if (vk <= depth) + pixels->Offset = 1; + } + else + { + + if (vk >= depth) + pixels->Offset = 1; + } + } + + // Only process non-opaque pixels + if (pixels->Offset == 0) + { + if (myThis->IsVoxelClipped(i*myThis->ImageSampleDistance,vj,vk) == 1) + { + image->Advance(pixels,1); + i++; + topIndex+=myThis->ImageSampleDistance; + continue; + } + + oldOpacity = pixels->Opacity; + oldRed = pixels->Red; + oldGreen = pixels->Green; + oldBlue = pixels->Blue; + + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + value = top->VoxelData[topIndex].Value; + sampledOpacity = SOTF[value]; + sampledRed = CTF[value*3 + 0]; + sampledGreen = CTF[value*3 + 1]; + sampledBlue = CTF[value*3 + 2]; + + if (myThis->Shade) + { + encodedNormal = top->VoxelData[topIndex].EncodedNormal; + + redDiffuse = myThis->RedDiffuseShadingTable[encodedNormal]; + redSpecular = myThis->RedSpecularShadingTable[encodedNormal]; + greenDiffuse = myThis->GreenDiffuseShadingTable[encodedNormal]; + greenSpecular = myThis->GreenSpecularShadingTable[encodedNormal]; + blueDiffuse = myThis->BlueDiffuseShadingTable[encodedNormal]; + blueSpecular = myThis->BlueSpecularShadingTable[encodedNormal]; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = top->VoxelData[topIndex].GradientMagnitude; + sampledGradientMagnitude = float(gradientMagnitude); + } + + + if (!gradientOpacityIsConstant) + { + if (sampledGradientMagnitude > 255.0f) + gradientOpacity = GOTF[255]; + else if (sampledGradientMagnitude < 0.0f) + gradientOpacity = GOTF[0]; + else + gradientOpacity = GOTF[(unsigned char) sampledGradientMagnitude]; + } + else + gradientOpacity = gradientOpacityConstant; + + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + sampledOpacity *= gradientOpacity; + } + + // Alpha Compositing + newRed = oldRed + sampledOpacity * sampledRed * (1.0f - oldOpacity); + newGreen = oldGreen + sampledOpacity * sampledGreen * (1.0f - oldOpacity); + newBlue = oldBlue + sampledOpacity * sampledBlue * (1.0f - oldOpacity); + newOpacity = oldOpacity + sampledOpacity * (1.0f - oldOpacity); + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + value = top->VoxelData[topIndex].Value; + sampledValue = value; + + // Maximum Intensity Projection + if (sampledValue > pixels->Value) + { + newRed = CTF[int(sampledValue)*3+0]; + newGreen = CTF[int(sampledValue)*3+1]; + newBlue = CTF[int(sampledValue)*3+2]; + newOpacity = SOTF[int(sampledValue)]; + pixels->Value = sampledValue; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + else + { + sampledRed = isoRed; + sampledGreen = isoGreen; + sampledBlue = isoBlue; + sampledOpacity = 1.0f; + + if (myThis->Shade) + + { + encodedNormal = top->VoxelData[topIndex].EncodedNormal; + + redDiffuse = myThis->RedDiffuseShadingTable[encodedNormal]; + redSpecular = myThis->RedSpecularShadingTable[encodedNormal]; + greenDiffuse = myThis->GreenDiffuseShadingTable[encodedNormal]; + greenSpecular = myThis->GreenSpecularShadingTable[encodedNormal]; + blueDiffuse = myThis->BlueDiffuseShadingTable[encodedNormal]; + blueSpecular = myThis->BlueSpecularShadingTable[encodedNormal]; + + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + } + + newRed = sampledRed; + newGreen = sampledGreen; + newBlue = sampledBlue; + newOpacity = 1.0f; + + + } + + pixels->Red = newRed; + pixels->Green = newGreen; + pixels->Blue = newBlue; + pixels->Opacity = newOpacity; + + if (newOpacity >= 1.0f) + { + // The current intermediate pixel is opaque, so exit + // loop and skip opaque pixels + pixels->Offset = 1; + break; + } + + image->Advance(pixels,1); + i++; + topIndex+=myThis->ImageSampleDistance; + } + else + { + // The current pixel has an offset greater than zero, so + // we exit the loop and skip all opaque pixels + break; + } + } + } + } + } + } + } +} + + +// Lacroute's parallel projection shear-warp algorithm with runlength encoded volume using bilinear interpolation +template <class T> +void CompositeIntermediateLinearRLE(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis) +{ + vtkShearWarpRLESlice<T> *slice; + vtkShearWarpRLERun<T> *top; + vtkShearWarpRLERun<T> *bottom; + vtkShearWarpPixelData *pixels; + + float sampledRed,sampledGreen,sampledBlue,sampledOpacity; + float sampledValue; + float sampledGradientMagnitude; + float oldRed,oldGreen,oldBlue,oldOpacity; + float newRed,newGreen,newBlue,newOpacity; + float redDiffuse,greenDiffuse,blueDiffuse; + float redSpecular,greenSpecular,blueSpecular; + float gradientOpacity; + + float isoRed; + float isoGreen; + float isoBlue; + + int topIndex; + int bottomIndex; + int topStart; + int bottomStart; + + int skipped; + int runLength; + + int i,j,k,h; + int vj,vk; + + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + + float gradientOpacityConstant; + int gradientOpacityIsConstant; + unsigned short encodedNormal; + unsigned char gradientMagnitude; + + float uSlice; + float vSlice; + + int uSliceInteger; + int vSliceInteger; + + + float uSliceFractional; + float vSliceFractional; + + float weightTopLeft; + float weightBottomLeft; + float weightTopRight; + float weightBottomRight; + + + float adjustedTL; + float adjustedTR; + float adjustedBL; + float adjustedBR; + + T value; + + int kStart; + int kEnd; + int kIncrement; + int vkIncrement; + + vtkShearWarpRLEVolume<T> *encodedVolume = dynamic_cast< vtkShearWarpRLEVolume<T> * > (myThis->EncodedVolume); + + if (myThis->ReverseOrder) + { + kStart = myThis->CountK - 1; + kEnd = -1; + kIncrement = -1; + vkIncrement = -myThis->ImageSampleDistance; + } + else + { + kStart = 0; + kEnd = myThis->CountK; + kIncrement = 1; + vkIncrement = myThis->ImageSampleDistance; + } + + SOTF = myThis->Volume->GetCorrectedScalarOpacityArray(); + CTF = myThis->Volume->GetRGBArray(); + GTF = myThis->Volume->GetGrayArray(); + GOTF = myThis->Volume->GetGradientOpacityArray(); + gradientOpacityConstant = myThis->Volume->GetGradientOpacityConstant(); + + if (gradientOpacityConstant > 0.0f) + gradientOpacityIsConstant = 1; + else + gradientOpacityIsConstant = 0; + + + if (myThis->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + isoRed = CTF[int(myThis->IsoValue)*3 + 0]; + isoGreen = CTF[int(myThis->IsoValue)*3 + 1]; + isoBlue = CTF[int(myThis->IsoValue)*3 + 2]; + } + + for (k = kStart, vk = kStart*myThis->ImageSampleDistance; k != kEnd; k += kIncrement, vk += vkIncrement) + { + topIndex = 0; + bottomIndex = 0; + topStart = 0; + bottomStart = 0; + + uSlice = k*myThis->ShearI + myThis->TranslationI; + vSlice = k*myThis->ShearJ + myThis->TranslationJ; + + uSliceInteger = (int)ceil(uSlice) - 1; + vSliceInteger = (int)ceil(vSlice) - 1; + + uSliceFractional = uSlice - uSliceInteger; + vSliceFractional = vSlice - vSliceInteger; + + weightTopLeft = uSliceFractional * vSliceFractional; + weightBottomLeft = uSliceFractional * (1.0f - vSliceFractional); + weightTopRight = (1.0f - uSliceFractional) * vSliceFractional; + weightBottomRight = (1.0f - uSliceFractional) * (1.0f - vSliceFractional); + + slice = encodedVolume->GetSlice(myThis->MajorAxis,vk); + + // Composite one slice into the intermediate image + for (j=0, vj = 0; j < myThis->CountJ; j++, vj += myThis->ImageSampleDistance) + { + top = slice->GetLineRuns(vj); + + if ((j + 1) < myThis->CountJ) + bottom = slice->GetLineRuns(vj+myThis->ImageSampleDistance); + else + bottom = NULL; + + topStart = 0; + bottomStart = 0; + + topIndex = 0; + bottomIndex = 0; + + image->Position(pixels,uSliceInteger + (vSliceInteger+j)*myThis->IntermediateWidth); + + for (i=0; i < myThis->CountI; ) + { + // Update runs + while (topIndex >= top->Length) + { + topIndex -= top->Length; + topStart += top->Length; + top++; + } + + if (bottom != NULL) + { + while (bottomIndex >= bottom->Length) + { + bottomIndex -= bottom->Length; + bottomStart += bottom->Length; + bottom++; + } + } + + // Skip opaque pixels in intermediate image + skipped = image->Skip(pixels); + + // Update both runs if to be aligned with intermediate pixels + if (skipped > 0) + { + i += skipped; + + topIndex += skipped * myThis->ImageSampleDistance; + bottomIndex += skipped * myThis->ImageSampleDistance; + } + else + { + if (bottom != NULL) + { + if ( ((topStart + top->Length) - (topStart + topIndex)) < ((bottomStart + bottom->Length) - (bottomStart + bottomIndex)) ) + runLength = ((topStart + top->Length) - (topStart + topIndex)); + else + runLength = ((bottomStart + bottom->Length) - (bottomStart + bottomIndex)); + } + else + runLength = top->Length - topIndex; + + // Skip transparent voxels in both runs + + if (top->VoxelData == NULL && (((bottom != NULL) ? bottom->VoxelData : NULL) == NULL)) + + { + for (h = 0; h < runLength; h+=myThis->ImageSampleDistance) + + { + image->Advance(pixels,1); + i++; + topIndex += myThis->ImageSampleDistance; + bottomIndex += myThis->ImageSampleDistance; + } + } + else + { + + // This loops samples voxels from both runs, + // interpolates, performs shading and performs + // compositing into the intermediate image + for (h=0; h < runLength; h+= myThis->ImageSampleDistance) + { + if (myThis->IntermixIntersectingGeometry) + { + float depth = myThis->IntermediateZBuffer[myThis->ImageSampleDistance * (uSliceInteger + i) + myThis->ImageSampleDistance * (vSliceInteger + j) * myThis->IntermediateWidth * myThis->ImageSampleDistance]; + + if (myThis->ReverseOrder) + { + if (vk <= depth) + pixels->Offset = 1; + } + else + { + if (vk >= depth) + pixels->Offset = 1; + } + } + + // Only process non-opaque pixels + if (pixels->Offset == 0) + { + + if (myThis->IsVoxelClipped(i*myThis->ImageSampleDistance,vj,vk) == 1) + { + image->Advance(pixels,1); + i++; + topIndex += myThis->ImageSampleDistance; + bottomIndex += myThis->ImageSampleDistance; + continue; + } + + + oldOpacity = pixels->Opacity; + oldRed = pixels->Red; + oldGreen = pixels->Green; + oldBlue = pixels->Blue; + + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + sampledOpacity = 0.0f; + sampledRed = 0.0f; + sampledGreen = 0.0f; + sampledBlue = 0.0f; + + if (top->VoxelData != NULL) + { + value = top->VoxelData[topIndex].Value; + sampledOpacity += SOTF[value] * weightTopLeft; + sampledRed += CTF[value*3 + 0] * weightTopLeft; + sampledGreen += CTF[value*3 + 1] * weightTopLeft; + sampledBlue += CTF[value*3 + 2] * weightTopLeft; + + if (h + myThis->ImageSampleDistance < runLength) + { + value = top->VoxelData[topIndex+myThis->ImageSampleDistance].Value; + sampledOpacity += SOTF[value] * weightTopRight; + sampledRed += CTF[value*3 + 0] * weightTopRight; + sampledGreen += CTF[value*3 + 1] * weightTopRight; + sampledBlue += CTF[value*3 + 2] * weightTopRight; + } + } + + if (bottom != NULL) + { + if (bottom->VoxelData != NULL) + { + value = bottom->VoxelData[bottomIndex].Value; + sampledOpacity += SOTF[value] * weightBottomLeft; + sampledRed += CTF[value*3 + 0] * weightBottomLeft; + sampledGreen += CTF[value*3 + 1] * weightBottomLeft; + sampledBlue += CTF[value*3 + 2] * weightBottomLeft; + + + if (h + myThis->ImageSampleDistance < runLength) + { + value = bottom->VoxelData[bottomIndex+myThis->ImageSampleDistance].Value; + sampledOpacity += SOTF[value] * weightBottomRight; + sampledRed += CTF[value*3 + 0] * weightBottomRight; + sampledGreen += CTF[value*3 + 1] * weightBottomRight; + sampledBlue += CTF[value*3 + 2] * weightBottomRight; + } + } + + } + + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + sampledGradientMagnitude = 0.0f; + gradientOpacity = gradientOpacityConstant; + + if (top->VoxelData != NULL) + { + encodedNormal = top->VoxelData[topIndex].EncodedNormal; + + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightTopLeft; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightTopLeft; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightTopLeft; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightTopLeft; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightTopLeft; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightTopLeft; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = top->VoxelData[topIndex].GradientMagnitude; + sampledGradientMagnitude += float(gradientMagnitude) * weightTopLeft; + } + + if (h + myThis->ImageSampleDistance < runLength) + { + encodedNormal = top->VoxelData[topIndex+myThis->ImageSampleDistance].EncodedNormal; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightTopRight; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightTopRight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightTopRight; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightTopRight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightTopRight; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightTopRight; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = top->VoxelData[topIndex+myThis->ImageSampleDistance].GradientMagnitude; + sampledGradientMagnitude += float(gradientMagnitude) * weightTopRight; + } + } + } + + if (bottom != NULL) + { + if (bottom->VoxelData != NULL) + { + encodedNormal = bottom->VoxelData[bottomIndex].EncodedNormal; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightBottomLeft; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightBottomLeft; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightBottomLeft; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightBottomLeft; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightBottomLeft; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightBottomLeft; + + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = bottom->VoxelData[bottomIndex].GradientMagnitude; + sampledGradientMagnitude += float(gradientMagnitude) * weightBottomLeft; + } + + if (h + myThis->ImageSampleDistance < runLength) + { + encodedNormal = bottom->VoxelData[bottomIndex+myThis->ImageSampleDistance].EncodedNormal; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightBottomRight; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightBottomRight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightBottomRight; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightBottomRight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightBottomRight; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightBottomRight; + + if (!gradientOpacityIsConstant) + { + + gradientMagnitude = bottom->VoxelData[bottomIndex+myThis->ImageSampleDistance].GradientMagnitude; + sampledGradientMagnitude += float(gradientMagnitude) * weightBottomRight; + } + } + } + } + + if (!gradientOpacityIsConstant) + { + if (sampledGradientMagnitude > 255.0f) + gradientOpacity = GOTF[255]; + else if (sampledGradientMagnitude < 0.0f) + gradientOpacity = GOTF[0]; + else + gradientOpacity = GOTF[(unsigned char) sampledGradientMagnitude]; + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + sampledOpacity *= gradientOpacity; + } + + // Alpha Compositing + newRed = oldRed + sampledOpacity * sampledRed * (1.0f - oldOpacity); + newGreen = oldGreen + sampledOpacity * sampledGreen * (1.0f - oldOpacity); + newBlue = oldBlue + sampledOpacity * sampledBlue * (1.0f - oldOpacity); + newOpacity = oldOpacity + sampledOpacity * (1.0f - oldOpacity); + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + sampledValue = 0.0f; + + if (top->VoxelData != NULL) + { + value = top->VoxelData[topIndex].Value; + sampledValue += float(value) * weightTopLeft; + + if (h + myThis->ImageSampleDistance < runLength) + { + value = top->VoxelData[topIndex+myThis->ImageSampleDistance].Value; + sampledValue += float(value) * weightTopRight; + } + } + + if (bottom != NULL) + { + if (bottom->VoxelData != NULL) + { + value = bottom->VoxelData[bottomIndex].Value; + sampledValue += float(value) * weightBottomLeft; + + if (h + myThis->ImageSampleDistance < runLength) + { + + value = bottom->VoxelData[bottomIndex+myThis->ImageSampleDistance].Value; + sampledValue += float(value) * weightBottomRight; + } + } + } + + // Maximum Intensity Projection + if (sampledValue > pixels->Value) + { + newRed = CTF[int(sampledValue)*3+0]; + newGreen = CTF[int(sampledValue)*3+1]; + newBlue = CTF[int(sampledValue)*3+2]; + newOpacity = SOTF[int(sampledValue)]; + pixels->Value = sampledValue; + } + else + { + + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + else + { + sampledRed = isoRed; + sampledGreen = isoGreen; + + sampledBlue = isoBlue; + + if (myThis->Shade) + { + redDiffuse = 0.0f; + + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + + adjustedTL = weightTopLeft; + adjustedBL = weightBottomLeft; + adjustedTR = weightTopRight; + adjustedBR = weightBottomRight; + + + if (h + myThis->ImageSampleDistance >= runLength) + { + adjustedTL += adjustedTR; + + adjustedBL += adjustedBR; + } + + if (top->VoxelData == NULL) + { + adjustedBL += adjustedTL; + adjustedBR += adjustedTR; + } + else if ((((bottom != NULL) ? bottom->VoxelData : NULL) == NULL)) + { + adjustedTL += adjustedBL; + adjustedTR += adjustedBR; + } + + if (top->VoxelData != NULL) + { + encodedNormal = top->VoxelData[topIndex].EncodedNormal; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedTL; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedTL; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedTL; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedTL; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedTL; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedTL; + + if (h + myThis->ImageSampleDistance < runLength) + { + encodedNormal = top->VoxelData[topIndex+myThis->ImageSampleDistance].EncodedNormal; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedTR; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedTR; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedTR; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedTR; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedTR; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedTR; + } + } + + if (bottom != NULL) + { + if (bottom->VoxelData != NULL) + { + encodedNormal = bottom->VoxelData[bottomIndex].EncodedNormal; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedBL; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedBL; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedBL; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedBL; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedBL; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedBL; + + if (h + myThis->ImageSampleDistance < runLength) + { + + encodedNormal = bottom->VoxelData[bottomIndex+myThis->ImageSampleDistance].EncodedNormal; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedBR; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedBR; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedBR; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedBR; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedBR; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedBR; + + } + } + + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + + + } + + newRed = sampledRed; + newGreen = sampledGreen; + newBlue = sampledBlue; + newOpacity = 1.0f; + } + + pixels->Red = newRed; + pixels->Green = newGreen; + pixels->Blue = newBlue; + pixels->Opacity = newOpacity; + + + if (newOpacity >= 1.0f) + { + // The current intermediate pixel is opaque, so exit + // loop and skip opaque pixels + pixels->Offset = 1; + break; + } + + image->Advance(pixels,1); + + i++; + topIndex += myThis->ImageSampleDistance; + bottomIndex += myThis->ImageSampleDistance; + } + else + { + // The current pixel has an offset greater than zero, so + // we exit the loop and skip all opaque pixels + break; + } + } + } + } + } + } + } +} + +// Lacroute's perspective projection shear-warp algorithm with runlength encoded volume using bilinear interpolation +template <class T> +void CompositeIntermediateLinearRLEPerspective(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis) +{ + vtkShearWarpRLERun<T> **line; + float *lineIndex; + vtkShearWarpRLERun<T> *currentLine; + + + int currentLineIndex; + vtkShearWarpRLESlice<T> *slice; + vtkShearWarpPixelData *pixels; + int voxels; + int footprint; + int left; + + float sampledRed,sampledGreen,sampledBlue,sampledOpacity; + float sampledValue; + float sampledGradientMagnitude; + float oldRed,oldGreen,oldBlue,oldOpacity; + float newRed,newGreen,newBlue,newOpacity; + + float redDiffuse,greenDiffuse,blueDiffuse; + float redSpecular,greenSpecular,blueSpecular; + float gradientOpacity; + + float isoRed; + float isoGreen; + + float isoBlue; + + int skipped; + int runLength; + + int i,j,k,h,g; + int vk; + float vj; + + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float gradientOpacityConstant; + int gradientOpacityIsConstant; + unsigned short encodedNormal; + unsigned char gradientMagnitude; + + float uSlice; + float vSlice; + + int uSliceInteger; + int vSliceInteger; + + float scaleFactor; + float weight; + + T value; + + + int kStart; + int kEnd; + int kIncrement; + int vkIncrement; + + vtkShearWarpRLEVolume<T> *encodedVolume = dynamic_cast< vtkShearWarpRLEVolume<T> * > (myThis->EncodedVolume); + + if (myThis->ReverseOrder) + { + kStart = myThis->CountK - 1; + kEnd = -1; + kIncrement = -1; + vkIncrement = -myThis->ImageSampleDistance; + + } + else + { + kStart = 0; + kEnd = myThis->CountK; + kIncrement = 1; + vkIncrement = myThis->ImageSampleDistance; + } + + SOTF = myThis->Volume->GetCorrectedScalarOpacityArray(); + CTF = myThis->Volume->GetRGBArray(); + + GTF = myThis->Volume->GetGrayArray(); + GOTF = myThis->Volume->GetGradientOpacityArray(); + gradientOpacityConstant = myThis->Volume->GetGradientOpacityConstant(); + + if (gradientOpacityConstant > 0.0f) + gradientOpacityIsConstant = 1; + else + gradientOpacityIsConstant = 0; + + + if (myThis->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + + { + isoRed = CTF[int(myThis->IsoValue)*3 + 0]; + isoGreen = CTF[int(myThis->IsoValue)*3 + 1]; + isoBlue = CTF[int(myThis->IsoValue)*3 + 2]; + } + + float vjIncrement; + float viIncrement; + + + for (k = kStart, vk = kStart*myThis->ImageSampleDistance; k != kEnd; k += kIncrement, vk += vkIncrement) + { + if (myThis->ReverseOrder) + scaleFactor = 1.0f / (1.0 - float(kStart*myThis->ImageSampleDistance-vk) * myThis->Scale); + else + scaleFactor = 1.0f / (1.0 + float(vk) * myThis->Scale); + + footprint = (int) (1.0f + ceil ( 1.0f / scaleFactor)); + + vjIncrement = myThis->ImageSampleDistance / scaleFactor; + viIncrement = myThis->ImageSampleDistance / scaleFactor; + + + line = new vtkShearWarpRLERun<T>*[footprint]; + lineIndex = new float[footprint]; + + uSlice = k*myThis->ShearI + myThis->TranslationI; + vSlice = k*myThis->ShearJ + myThis->TranslationJ; + + uSliceInteger = (int)ceil(uSlice) - 1; + vSliceInteger = (int)ceil(vSlice) - 1; + + + + slice = encodedVolume->GetSlice(myThis->MajorAxis,vk); + + // Composite one slice into the intermediate image + for (j=0, vj = 0; j < myThis->CountJ*scaleFactor; j++, vj += vjIncrement) + { + for (g = 0; g < footprint; g++) + { + if (j+g < (myThis->CountJ*scaleFactor)) + line[g] = slice->GetLineRuns(int(vj+g*myThis->ImageSampleDistance)); + else + line[g] = NULL; + + lineIndex[g] = 0; + } + + image->Position(pixels,uSliceInteger + (vSliceInteger+j)*myThis->IntermediateWidth); + + for (i=0; i < myThis->CountI*scaleFactor; ) + { + // Skip opaque pixels in intermediate image + skipped = image->Skip(pixels); + + // Update both runs if to be aligned with intermediate pixels + if (skipped > 0) + { + i += skipped; + + for (g = 0; g < footprint; g++) + { + if (line[g] == NULL) + break; + + + lineIndex[g] += skipped * viIncrement; + + while (lineIndex[g] >= line[g]->Length) + + { + lineIndex[g] -= line[g]->Length; + line[g]++; + } + } + + } + else + { + sampledOpacity = 0.0f; + sampledRed = 0.0f; + sampledGreen = 0.0f; + sampledBlue = 0.0f; + sampledValue = 0.0f; + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + sampledGradientMagnitude = 0.0f; + gradientOpacity = gradientOpacityConstant; + + oldOpacity = pixels->Opacity; + oldRed = pixels->Red; + oldGreen = pixels->Green; + oldBlue = pixels->Blue; + + voxels = 0; + + // This loops samples voxels from both runs, + // interpolates, performs shading and performs + // compositing into the intermediate image + for (g = 0; g < footprint; g++) + { + + weight = 1.0; + + if (line[g] == NULL) + break; + + left = footprint * myThis->ImageSampleDistance; + + if (i + left >= myThis->CountI*scaleFactor) + left = (int)(myThis->CountI*scaleFactor - i) * myThis->ImageSampleDistance; + + currentLine = line[g]; + currentLineIndex = (int) lineIndex[g]; + + while (left > 0) + { + if (currentLineIndex >= currentLine->Length) + { + currentLineIndex -= currentLine->Length; + currentLine++; + } + + runLength = (left < currentLine->Length) ? left : currentLine->Length; + left -= runLength; + + if (currentLine->VoxelData == NULL) + { + currentLineIndex += runLength; + } + else + { + for (h = 0; h < runLength; h+= myThis->ImageSampleDistance) + { + voxels++; + + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + value = currentLine->VoxelData[(int)currentLineIndex].Value; + if(value > 16000) + continue; + sampledOpacity += SOTF[value] * weight; + sampledRed += CTF[value*3 + 0] * weight; + sampledGreen += CTF[value*3 + 1] * weight; + sampledBlue += CTF[value*3 + 2] * weight; + + if (myThis->Shade) + { + encodedNormal = currentLine->VoxelData[(int)currentLineIndex].EncodedNormal; + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weight; + + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weight; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weight; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weight; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = currentLine->VoxelData[(int)currentLineIndex].GradientMagnitude; + sampledGradientMagnitude += float(gradientMagnitude) * weight; + } + } + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + value = currentLine->VoxelData[(int)currentLineIndex].Value; + sampledValue += float(value) * weight; + + } + else + { + value = currentLine->VoxelData[(int)currentLineIndex].Value; + sampledValue += float(value) * weight; + + if (myThis->Shade) + { + + encodedNormal = currentLine->VoxelData[(int)currentLineIndex].EncodedNormal; + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weight; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weight; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weight; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weight; + } + } + + currentLineIndex += myThis->ImageSampleDistance; + } + } + } + + lineIndex[g] += viIncrement; + + if (lineIndex[g] >= line[g]->Length) + { + lineIndex[g] -= line[g]->Length; + + line[g]++; + } + + } + + if (voxels > 0) + { + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + sampledRed /= (float)voxels; + sampledGreen /= (float)voxels; + sampledBlue /= (float)voxels; + sampledOpacity /= (float)voxels; + + // Alpha Compositing + if (myThis->Shade) + + { + sampledGradientMagnitude /= voxels; + + if (sampledGradientMagnitude > 255.0f) + gradientOpacity = GOTF[255]; + + else if (sampledGradientMagnitude < 0.0f) + gradientOpacity = GOTF[0]; + else + gradientOpacity = GOTF[(unsigned char) sampledGradientMagnitude]; + + redDiffuse /= (float)voxels; + redSpecular /= (float)voxels; + greenDiffuse /= (float)voxels; + greenSpecular /= (float)voxels; + blueDiffuse /= (float)voxels; + blueSpecular /= (float)voxels; + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + sampledOpacity *= gradientOpacity; + + } + + newRed = oldRed + sampledOpacity * sampledRed * (1.0f - oldOpacity); + newGreen = oldGreen + sampledOpacity * sampledGreen * (1.0f - oldOpacity); + newBlue = oldBlue + sampledOpacity * sampledBlue * (1.0f - oldOpacity); + newOpacity = oldOpacity + sampledOpacity * (1.0f - oldOpacity); + + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + sampledValue /= (float)voxels; + + // Maximum Intensity Projection + if (sampledValue > pixels->Value) + { + newRed = CTF[int(sampledValue)*3+0]; + newGreen = CTF[int(sampledValue)*3+1]; + newBlue = CTF[int(sampledValue)*3+2]; + newOpacity = SOTF[int(sampledValue)]; + pixels->Value = sampledValue; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + else + { + sampledValue /= (float)voxels; + + // Isosurface + if (sampledValue > myThis->IsoValue) + { + sampledRed = isoRed; + sampledGreen = isoGreen; + sampledBlue = isoBlue; + + if (myThis->Shade) + { + redDiffuse /= (float)voxels; + redSpecular /= (float)voxels; + greenDiffuse /= (float)voxels; + greenSpecular /= (float)voxels; + blueDiffuse /= (float)voxels; + blueSpecular /= (float)voxels; + + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + } + + newRed = sampledRed; + newGreen = sampledGreen; + newBlue = sampledBlue; + newOpacity = 1.0f; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + + pixels->Red = newRed; + pixels->Green = newGreen; + pixels->Blue = newBlue; + pixels->Opacity = newOpacity; + + if (newOpacity >= 1.0f) + { + // The current intermediate pixel is opaque, so exit + // loop and skip opaque pixels + pixels->Offset = 1; + } + } + + + + image->Advance(pixels,1); + i++; + } + } + } + + delete[] lineIndex; + delete[] line; + } +} + + + +// Parallel projection shear-warp fast classification algorithm using nearest neighbour interpolation +template <class T> +void CompositeIntermediateNearestUnclassified(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis) +{ + vtkShearWarpPixelData *pixels = 0; + vtkShearWarpOctreeRun *runs = new vtkShearWarpOctreeRun[myThis->CountJ]; + vtkShearWarpOctreeRun *top; + + int topIndex; + float sampledRed,sampledGreen,sampledBlue,sampledOpacity; + float sampledValue; + float sampledGradientMagnitude; + float oldRed,oldGreen,oldBlue,oldOpacity; + float newRed,newGreen,newBlue,newOpacity; + float redDiffuse,greenDiffuse,blueDiffuse; + float redSpecular,greenSpecular,blueSpecular; + float gradientOpacity; + + float isoRed; + float isoGreen; + float isoBlue; + + int skipped; + + int i,j,k; + int vi,vj,vk; + + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float gradientOpacityConstant; + int gradientOpacityIsConstant; + unsigned short encodedNormal; + unsigned char gradientMagnitude; + + float uSlice; + float vSlice; + + int uSliceInteger; + int vSliceInteger; + + T value; + + int kStart; + int vkStart; + int kEnd; + int kIncrement; + int viIncrement; + int vjIncrement; + int vkIncrement; + int size; + + T *dptr = (T*) myThis->GetInput()->GetScalarPointer(); + + unsigned short *nptr = myThis->GradientEstimator->GetEncodedNormals(); + unsigned char *gptr = myThis->GradientEstimator->GetGradientMagnitudes(); + + int *dimensions = myThis->GetInput()->GetDimensions(); + int location; + int plane = dimensions[0]*dimensions[1]; + + vtkShearWarpOctree<T> *octree = dynamic_cast< vtkShearWarpOctree<T> * > (myThis->Octree); + + if (myThis->ReverseOrder) + { + kStart = myThis->CountK - 1; + kEnd = -1; + kIncrement = -1; + } + else + { + kStart = 0; + kEnd = myThis->CountK; + kIncrement = 1; + } + + SOTF = myThis->Volume->GetCorrectedScalarOpacityArray(); + CTF = myThis->Volume->GetRGBArray(); + GTF = myThis->Volume->GetGrayArray(); + GOTF = myThis->Volume->GetGradientOpacityArray(); + gradientOpacityConstant = myThis->Volume->GetGradientOpacityConstant(); + + if (gradientOpacityConstant > 0.0f) + gradientOpacityIsConstant = 1; + else + gradientOpacityIsConstant = 0; + + + if (myThis->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + isoRed = CTF[int(myThis->IsoValue)*3 + 0]; + isoGreen = CTF[int(myThis->IsoValue)*3 + 1]; + isoBlue = CTF[int(myThis->IsoValue)*3 + 2]; + } + + switch (myThis->MajorAxis) + { + case VTK_X_AXIS: + viIncrement = dimensions[0] * myThis->ImageSampleDistance; + vjIncrement = plane * myThis->ImageSampleDistance; + vkIncrement = kIncrement * myThis->ImageSampleDistance; + vkStart = kStart * myThis->ImageSampleDistance; + break; + + case VTK_Y_AXIS: + viIncrement = plane * myThis->ImageSampleDistance; + vjIncrement = myThis->ImageSampleDistance; + vkIncrement = kIncrement * dimensions[0] * myThis->ImageSampleDistance; + vkStart = kStart * dimensions[0] * myThis->ImageSampleDistance; + break; + + case VTK_Z_AXIS: + default: + viIncrement = myThis->ImageSampleDistance; + vjIncrement = dimensions[0] * myThis->ImageSampleDistance; + vkIncrement = kIncrement * plane * myThis->ImageSampleDistance; + vkStart = kStart * plane * myThis->ImageSampleDistance; + break; + } + + + for (k = kStart, vk = vkStart; k != kEnd; k += kIncrement, vk += vkIncrement) + { + uSlice = k*myThis->ShearI + myThis->TranslationI; + vSlice = k*myThis->ShearJ + myThis->TranslationJ; + + + uSliceInteger = (int)ceil(uSlice) - 1; + vSliceInteger = (int)ceil(vSlice) - 1; + + + size = 0; + + // Composite one slice into the intermediate image + for (j=0, vj = 0; j < myThis->CountJ; j++, vj += vjIncrement) + { + size -= 2 * myThis->ImageSampleDistance; + + if (size <= 0) + size = octree->GetLineRuns(runs,myThis->MajorAxis, k*myThis->ImageSampleDistance, j*myThis->ImageSampleDistance); + + top = runs; + topIndex = 0; + + image->Position(pixels,uSliceInteger + (vSliceInteger+j)*myThis->IntermediateWidth); + + for (i=0, vi = 0; i < myThis->CountI; ) + { + // Update runs + while (topIndex >= top->Length) + { + topIndex -= top->Length; + top++; + } + + // Skip opaque pixels in intermediate image + skipped = image->Skip(pixels); + + // Update both runs if to be aligned with intermediate pixels + if (skipped > 0) + { + i += skipped; + vi += skipped * viIncrement; + topIndex += skipped * myThis->ImageSampleDistance; + } + + else + { + // Skip transparent voxels + + + if (top->Type == VTK_SHEAR_WARP_OCTREE_TRANSPARENT) + { + while (topIndex < top->Length) + { + image->Advance(pixels,1); + i++; + vi += viIncrement; + topIndex += myThis->ImageSampleDistance; + } + } + else + { + + // This loops samples voxels, performs shading and performs + // compositing into the intermediate image + while (topIndex < top->Length) + { + if (myThis->IntermixIntersectingGeometry) + { + float depth = myThis->IntermediateZBuffer[myThis->ImageSampleDistance * (uSliceInteger + i) + myThis->ImageSampleDistance * (vSliceInteger + j) * myThis->IntermediateWidth * myThis->ImageSampleDistance]; + + if (myThis->ReverseOrder) + { + if (k*myThis->ImageSampleDistance <= depth) + pixels->Offset = 1; + } + else + { + if (k*myThis->ImageSampleDistance >= depth) + pixels->Offset = 1; + } + } + + // Only process non-opaque pixels + if (pixels->Offset == 0) + { + if (myThis->IsVoxelClipped(i*myThis->ImageSampleDistance,j*myThis->ImageSampleDistance,k*myThis->ImageSampleDistance) == 1) + { + image->Advance(pixels,1); + i++; + vi += viIncrement; + topIndex += myThis->ImageSampleDistance; + continue; + } + + oldOpacity = pixels->Opacity; + oldRed = pixels->Red; + oldGreen = pixels->Green; + oldBlue = pixels->Blue; + + location = vi + vj + vk; + + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + sampledOpacity = 0.0f; + sampledRed = 0.0f; + sampledGreen = 0.0f; + sampledBlue = 0.0f; + + value = dptr[location]; + sampledOpacity += SOTF[value]; + sampledRed += CTF[value*3 + 0]; + + + sampledGreen += CTF[value*3 + 1]; + sampledBlue += CTF[value*3 + 2]; + + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + sampledGradientMagnitude = 0.0f; + gradientOpacity = gradientOpacityConstant; + + encodedNormal = nptr[location]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal]; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal]; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal]; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal]; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal]; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal]; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[location]; + sampledGradientMagnitude += float(gradientMagnitude); + + if (sampledGradientMagnitude > 255.0f) + gradientOpacity = GOTF[255]; + else if (sampledGradientMagnitude < 0.0f) + gradientOpacity = GOTF[0]; + else + gradientOpacity = GOTF[(unsigned char) sampledGradientMagnitude]; + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + sampledOpacity *= gradientOpacity; + + } + + // Alpha Compositing + newRed = oldRed + sampledOpacity * sampledRed * (1.0f - oldOpacity); + newGreen = oldGreen + sampledOpacity * sampledGreen * (1.0f - oldOpacity); + newBlue = oldBlue + sampledOpacity * sampledBlue * (1.0f - oldOpacity); + newOpacity = oldOpacity + sampledOpacity * (1.0f - oldOpacity); + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + sampledValue = 0.0f; + + value = dptr[location]; + sampledValue += float(value); + + // Maximum Intensity Projection + if (sampledValue > pixels->Value) + { + + newRed = CTF[int(sampledValue)*3+0]; + newGreen = CTF[int(sampledValue)*3+1]; + newBlue = CTF[int(sampledValue)*3+2]; + newOpacity = SOTF[int(sampledValue)]; + pixels->Value = sampledValue; + } + else + + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + else + { + sampledValue = 0.0f; + + value = dptr[location]; + sampledValue += float(value); + + + if (sampledValue >= myThis->IsoValue) + { + sampledRed = isoRed; + + sampledGreen = isoGreen; + sampledBlue = isoBlue; + + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + + encodedNormal = nptr[location]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal]; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal]; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal]; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal]; + + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal]; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal]; + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + } + + newRed = sampledRed; + newGreen = sampledGreen; + newBlue = sampledBlue; + newOpacity = 1.0f; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + + pixels->Red = newRed; + + pixels->Green = newGreen; + pixels->Blue = newBlue; + pixels->Opacity = newOpacity; + + if (newOpacity >= 1.0f) + { + // The current intermediate pixel is opaque, so exit + // loop and skip opaque pixels + pixels->Offset = 1; + break; + } + + image->Advance(pixels,1); + i++; + vi += viIncrement; + topIndex += myThis->ImageSampleDistance; + } + else + { + // The current pixel has an offset greater than zero, so + // we exit the loop and skip all opaque pixels + break; + } + } + } + } + } + + } + } + + delete[] runs; +} + + +// Parallel projection shear-warp fast classification algorithm using bilinear interpolation +template <class T> +void CompositeIntermediateLinearUnclassified(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis) +{ + vtkShearWarpPixelData *pixels = 0; + vtkShearWarpOctreeRun *runs = new vtkShearWarpOctreeRun[myThis->CountJ]; + vtkShearWarpOctreeRun *top,*bottom; + + int topIndex, bottomIndex, topStart, bottomStart; + + float sampledRed,sampledGreen,sampledBlue,sampledOpacity; + float sampledValue; + float sampledGradientMagnitude; + float oldRed,oldGreen,oldBlue,oldOpacity; + float newRed,newGreen,newBlue,newOpacity; + float redDiffuse,greenDiffuse,blueDiffuse; + float redSpecular,greenSpecular,blueSpecular; + float gradientOpacity; + + float isoRed; + float isoGreen; + + float isoBlue; + + int skipped; + int runLength; + + int i,j,k,h; + int vi,vj,vk; + + float *SOTF; + float *CTF; + float *GTF; + float *GOTF; + float gradientOpacityConstant; + int gradientOpacityIsConstant; + unsigned short encodedNormal; + unsigned char gradientMagnitude; + + float uSlice; + float vSlice; + + int uSliceInteger; + int vSliceInteger; + + float uSliceFractional; + float vSliceFractional; + + float weightTopLeft; + float weightBottomLeft; + float weightTopRight; + float weightBottomRight; + + float adjustedTL; + float adjustedTR; + float adjustedBL; + float adjustedBR; + + T value; + + int kStart; + int vkStart; + int kEnd; + int kIncrement; + int viIncrement; + int vjIncrement; + int vkIncrement; + int size; + + T *dptr = (T*) myThis->GetInput()->GetScalarPointer(); + + unsigned short *nptr = myThis->GradientEstimator->GetEncodedNormals(); + unsigned char *gptr = myThis->GradientEstimator->GetGradientMagnitudes(); + + int *dimensions = myThis->GetInput()->GetDimensions(); + int locationTL,locationTR,locationBL,locationBR; + int plane = dimensions[0]*dimensions[1]; + + vtkShearWarpOctree<T> *octree = dynamic_cast< vtkShearWarpOctree<T> * > (myThis->Octree); + + if (myThis->ReverseOrder) + { + kStart = myThis->CountK - 1; + kEnd = -1; + kIncrement = -1; + } + else + { + kStart = 0; + kEnd = myThis->CountK; + kIncrement = 1; + } + + SOTF = myThis->Volume->GetCorrectedScalarOpacityArray(); + CTF = myThis->Volume->GetRGBArray(); + GTF = myThis->Volume->GetGrayArray(); + GOTF = myThis->Volume->GetGradientOpacityArray(); + gradientOpacityConstant = myThis->Volume->GetGradientOpacityConstant(); + + if (gradientOpacityConstant > 0.0f) + gradientOpacityIsConstant = 1; + else + gradientOpacityIsConstant = 0; + + + if (myThis->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + isoRed = CTF[int(myThis->IsoValue)*3 + 0]; + isoGreen = CTF[int(myThis->IsoValue)*3 + 1]; + isoBlue = CTF[int(myThis->IsoValue)*3 + 2]; + } + + switch (myThis->MajorAxis) + { + case VTK_X_AXIS: + viIncrement = dimensions[0] * myThis->ImageSampleDistance; + vjIncrement = plane * myThis->ImageSampleDistance; + vkIncrement = kIncrement * myThis->ImageSampleDistance; + vkStart = kStart * myThis->ImageSampleDistance; + break; + + case VTK_Y_AXIS: + viIncrement = plane * myThis->ImageSampleDistance; + vjIncrement = myThis->ImageSampleDistance; + vkIncrement = kIncrement * dimensions[0] * myThis->ImageSampleDistance; + vkStart = kStart * dimensions[0] * myThis->ImageSampleDistance; + break; + + case VTK_Z_AXIS: + default: + viIncrement = myThis->ImageSampleDistance; + vjIncrement = dimensions[0] * myThis->ImageSampleDistance; + vkIncrement = kIncrement * plane * myThis->ImageSampleDistance; + vkStart = kStart * plane * myThis->ImageSampleDistance; + break; + } + + + for (k = kStart, vk = vkStart; k != kEnd; k += kIncrement, vk += vkIncrement) + { + uSlice = k*myThis->ShearI + myThis->TranslationI; + vSlice = k*myThis->ShearJ + myThis->TranslationJ; + + uSliceInteger = (int)ceil(uSlice) - 1; + vSliceInteger = (int)ceil(vSlice) - 1; + + uSliceFractional = uSlice - uSliceInteger; + vSliceFractional = vSlice - vSliceInteger; + + weightTopLeft = uSliceFractional * vSliceFractional; + weightBottomLeft = uSliceFractional * (1.0f - vSliceFractional); + weightTopRight = (1.0f - uSliceFractional) * vSliceFractional; + weightBottomRight = (1.0f - uSliceFractional) * (1.0f - vSliceFractional); + + size = 0; + + // Composite one slice into the intermediate image + for (j=0, vj = 0; j < myThis->CountJ; j++, vj += vjIncrement) + { + size -= myThis->ImageSampleDistance; + + if (size <= 0) + { + size = octree->GetLineRuns(runs,myThis->MajorAxis, k*myThis->ImageSampleDistance, j*myThis->ImageSampleDistance); + size -= myThis->ImageSampleDistance; + } + + top = runs; + + if ((j + 1) < myThis->CountJ) + { + size -= myThis->ImageSampleDistance; + + if (size <= 0) + { + size = octree->GetLineRuns(runs, myThis->MajorAxis, k*myThis->ImageSampleDistance, (j+1)*myThis->ImageSampleDistance); + size -= myThis->ImageSampleDistance; + } + + bottom = runs; + } + else + bottom = NULL; + + topStart = 0; + bottomStart = 0; + + topIndex = 0; + bottomIndex = 0; + + image->Position(pixels,uSliceInteger + (vSliceInteger+j)*myThis->IntermediateWidth); + + for (i=0, vi = 0; i < myThis->CountI; ) + { + // Update runs + while (topIndex >= top->Length) + { + topIndex -= top->Length; + topStart += top->Length; + top++; + } + + if (bottom != NULL) + { + while (bottomIndex >= bottom->Length) + { + bottomIndex -= bottom->Length; + bottomStart += bottom->Length; + bottom++; + } + } + + // Skip opaque pixels in intermediate image + + skipped = image->Skip(pixels); + + // Update both runs if to be aligned with intermediate pixels + if (skipped > 0) + { + i += skipped; + vi += skipped * viIncrement; + topIndex += skipped * myThis->ImageSampleDistance; + bottomIndex += skipped * myThis->ImageSampleDistance; + } + else + { + if (bottom != NULL) + { + if ( ((topStart + top->Length) - (topStart + topIndex)) < ((bottomStart + bottom->Length) - (bottomStart + bottomIndex)) ) + runLength = ((topStart + top->Length) - (topStart + topIndex)); + else + runLength = ((bottomStart + bottom->Length) - (bottomStart + bottomIndex)); + } + else + runLength = top->Length - topIndex; + + // Skip transp1arent voxels in both runs + + if (top->Type == VTK_SHEAR_WARP_OCTREE_TRANSPARENT && (((bottom != NULL) ? bottom->Type : VTK_SHEAR_WARP_OCTREE_TRANSPARENT) == VTK_SHEAR_WARP_OCTREE_TRANSPARENT)) + { + for (h = 0; h < runLength; h+=myThis->ImageSampleDistance) + { + image->Advance(pixels,1); + i++; + vi += viIncrement; + topIndex += myThis->ImageSampleDistance; + bottomIndex += myThis->ImageSampleDistance; + } + } + else + { + // This loops samples voxels from both runs, + // interpolates, performs shading and performs + // compositing into the intermediate image + for (h=0; h < runLength; h+= myThis->ImageSampleDistance) + { + if (myThis->IntermixIntersectingGeometry) + { + float depth = myThis->IntermediateZBuffer[myThis->ImageSampleDistance * (uSliceInteger + i) + myThis->ImageSampleDistance * (vSliceInteger + j) * myThis->IntermediateWidth * myThis->ImageSampleDistance]; + + if (myThis->ReverseOrder) + { + if (k*myThis->ImageSampleDistance <= depth) + pixels->Offset = 1; + } + else + { + if (k*myThis->ImageSampleDistance >= depth) + pixels->Offset = 1; + } + + } + + // Only process non-opaque pixels + if (pixels->Offset == 0) + { + if (myThis->IsVoxelClipped(i*myThis->ImageSampleDistance,j*myThis->ImageSampleDistance,k*myThis->ImageSampleDistance) == 1) + { + image->Advance(pixels,1); + i++; + vi += viIncrement; + + topIndex += myThis->ImageSampleDistance; + bottomIndex += myThis->ImageSampleDistance; + continue; + } + + oldOpacity = pixels->Opacity; + oldRed = pixels->Red; + oldGreen = pixels->Green; + oldBlue = pixels->Blue; + + locationTL = vi + vj + vk; + locationTR = locationTL + viIncrement; + locationBL = locationTL + vjIncrement; + locationBR = locationBL + viIncrement; + + if (myThis->FunctionType == VTK_SHEAR_WARP_COMPOSITE_FUNCTION) + { + sampledOpacity = 0.0f; + sampledRed = 0.0f; + sampledGreen = 0.0f; + sampledBlue = 0.0f; + + value = dptr[locationTL]; + sampledOpacity += SOTF[value] * weightTopLeft; + sampledRed += CTF[value*3 + 0] * weightTopLeft; + sampledGreen += CTF[value*3 + 1] * weightTopLeft; + sampledBlue += CTF[value*3 + 2] * weightTopLeft; + + + if (i + 1 < myThis->CountI) + { + value = dptr[locationTR]; + sampledOpacity += SOTF[value] * weightTopRight; + sampledRed += CTF[value*3 + 0] * weightTopRight; + sampledGreen += CTF[value*3 + 1] * weightTopRight; + sampledBlue += CTF[value*3 + 2] * weightTopRight; + } + + if (j + 1 < myThis->CountJ) + { + + value = dptr[locationBL]; + sampledOpacity += SOTF[value] * weightBottomLeft; + sampledRed += CTF[value*3 + 0] * weightBottomLeft; + sampledGreen += CTF[value*3 + 1] * weightBottomLeft; + sampledBlue += CTF[value*3 + 2] * weightBottomLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationBR]; + sampledOpacity += SOTF[value] * weightBottomRight; + + sampledRed += CTF[value*3 + 0] * weightBottomRight; + sampledGreen += CTF[value*3 + 1] * weightBottomRight; + sampledBlue += CTF[value*3 + 2] * weightBottomRight; + } + } + + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + sampledGradientMagnitude = 0.0f; + gradientOpacity = gradientOpacityConstant; + + encodedNormal = nptr[locationTL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightTopLeft; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightTopLeft; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightTopLeft; + + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightTopLeft; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightTopLeft; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightTopLeft; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[locationTL]; + sampledGradientMagnitude += float(gradientMagnitude) * weightTopLeft; + } + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationTR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightTopRight; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightTopRight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightTopRight; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightTopRight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightTopRight; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightTopRight; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[locationTR]; + sampledGradientMagnitude += float(gradientMagnitude) * weightTopRight; + } + } + + if (j + 1 < myThis->CountJ) + { + encodedNormal = nptr[locationBL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightBottomLeft; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightBottomLeft; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightBottomLeft; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightBottomLeft; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightBottomLeft; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightBottomLeft; + + if (!gradientOpacityIsConstant) + { + gradientMagnitude = gptr[locationBL]; + sampledGradientMagnitude += float(gradientMagnitude) * weightBottomLeft; + } + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationBR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * weightBottomRight; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * weightBottomRight; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * weightBottomRight; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * weightBottomRight; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * weightBottomRight; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * weightBottomRight; + + if (!gradientOpacityIsConstant) + { + + gradientMagnitude = gptr[locationBR]; + sampledGradientMagnitude += float(gradientMagnitude) * weightBottomRight; + } + } + } + + if (!gradientOpacityIsConstant) + { + if (sampledGradientMagnitude > 255.0f) + gradientOpacity = GOTF[255]; + else if (sampledGradientMagnitude < 0.0f) + gradientOpacity = GOTF[0]; + else + gradientOpacity = GOTF[(unsigned char) sampledGradientMagnitude]; + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + sampledOpacity *= gradientOpacity; + } + + // Alpha Compositing + newRed = oldRed + sampledOpacity * sampledRed * (1.0f - oldOpacity); + newGreen = oldGreen + sampledOpacity * sampledGreen * (1.0f - oldOpacity); + newBlue = oldBlue + sampledOpacity * sampledBlue * (1.0f - oldOpacity); + newOpacity = oldOpacity + sampledOpacity * (1.0f - oldOpacity); + } + else if (myThis->FunctionType == VTK_SHEAR_WARP_MIP_FUNCTION) + { + sampledValue = 0.0f; + + value = dptr[locationTL]; + sampledValue += float(value) * weightTopLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationTR]; + sampledValue += float(value) * weightTopRight; + } + + if (j + 1 < myThis->CountJ) + { + value = dptr[locationBL]; + sampledValue += float(value) * weightBottomLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationBR]; + sampledValue += float(value) * weightBottomRight; + + } + } + + // Maximum Intensity Projection + if (sampledValue > pixels->Value) + { + newRed = CTF[int(sampledValue)*3+0]; + + newGreen = CTF[int(sampledValue)*3+1]; + newBlue = CTF[int(sampledValue)*3+2]; + newOpacity = SOTF[int(sampledValue)]; + pixels->Value = sampledValue; + + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + } + else + { + + sampledRed = isoRed; + sampledGreen = isoGreen; + sampledBlue = isoBlue; + + sampledValue = 0.0f; + + value = dptr[locationTL]; + sampledValue += float(value) * weightTopLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationTR]; + sampledValue += float(value) * weightTopRight; + } + + if (j + 1 < myThis->CountJ) + { + value = dptr[locationBL]; + sampledValue += float(value) * weightBottomLeft; + + if (i + 1 < myThis->CountI) + { + value = dptr[locationBR]; + sampledValue += float(value) * weightBottomRight; + } + } + + + // Isosurface + if (sampledValue >= myThis->IsoValue) + { + if (myThis->Shade) + { + redDiffuse = 0.0f; + redSpecular = 0.0f; + blueDiffuse = 0.0f; + blueSpecular = 0.0f; + greenDiffuse = 0.0f; + greenSpecular = 0.0f; + + adjustedTL = weightTopLeft; + adjustedBL = weightBottomLeft; + adjustedTR = weightTopRight; + adjustedBR = weightBottomRight; + + if (i + 1 >= myThis->CountI) + { + adjustedTL += adjustedTR; + adjustedBL += adjustedBR; + } + + if (j + 1 >= myThis->CountJ) + { + adjustedTL += adjustedBL; + adjustedTR += adjustedBR; + + } + + + encodedNormal = nptr[locationTL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedTL; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedTL; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedTL; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedTL; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedTL; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedTL; + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationTR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedTR; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedTR; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedTR; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedTR; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedTR; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedTR; + } + + if (j + 1 < myThis->CountJ) + { + encodedNormal = nptr[locationBL]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedBL; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedBL; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedBL; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedBL; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedBL; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedBL; + + + if (i + 1 < myThis->CountI) + { + encodedNormal = nptr[locationBR]; + + redDiffuse += myThis->RedDiffuseShadingTable[encodedNormal] * adjustedBR; + redSpecular += myThis->RedSpecularShadingTable[encodedNormal] * adjustedBR; + greenDiffuse += myThis->GreenDiffuseShadingTable[encodedNormal] * adjustedBR; + greenSpecular += myThis->GreenSpecularShadingTable[encodedNormal] * adjustedBR; + blueDiffuse += myThis->BlueDiffuseShadingTable[encodedNormal] * adjustedBR; + blueSpecular += myThis->BlueSpecularShadingTable[encodedNormal] * adjustedBR; + + } + } + + sampledRed *= redDiffuse + redSpecular; + sampledGreen *= greenDiffuse + greenSpecular; + sampledBlue *= blueDiffuse + blueSpecular; + + + } + + + newRed = sampledRed; + newGreen = sampledGreen; + newBlue = sampledBlue; + newOpacity = 1.0f; + } + else + { + newRed = oldRed; + newGreen = oldGreen; + newBlue = oldBlue; + newOpacity = oldOpacity; + } + + } + + pixels->Red = newRed; + pixels->Green = newGreen; + pixels->Blue = newBlue; + pixels->Opacity = newOpacity; + + if (newOpacity >= 1.0f) + { + // The current intermediate pixel is opaque, so exit + // loop and skip opaque pixels + pixels->Offset = 1; + break; + } + + + image->Advance(pixels,1); + i++; + vi += viIncrement; + topIndex += myThis->ImageSampleDistance; + bottomIndex += myThis->ImageSampleDistance; + } + else + { + // The current pixel has an offset greater than zero, so + // we exit the loop and skip all opaque pixels + break; + } + } + } + } + } + } + } + + delete[] runs; +} + + +vtkVolumeShearWarpMapper* vtkVolumeShearWarpMapper::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret=vtkGraphicsFactory::CreateInstance("vtkVolumeShearWarpMapper"); + return (vtkVolumeShearWarpMapper*)ret; +} + + +vtkVolumeShearWarpMapper::vtkVolumeShearWarpMapper() +{ + this->ImageSampleDistance = 1; + this->MinimumImageSampleDistance = 1; + this->MaximumImageSampleDistance = 4; + this->AutoAdjustSampleDistances = 1; + + this->PerspectiveMatrix = vtkMatrix4x4::New(); + this->ViewToWorldMatrix = vtkMatrix4x4::New(); + this->ViewToVoxelsMatrix = vtkMatrix4x4::New(); + this->VoxelsToViewMatrix = vtkMatrix4x4::New(); + this->WorldToVoxelsMatrix = vtkMatrix4x4::New(); + + this->VoxelsToWorldMatrix = vtkMatrix4x4::New(); + this->VoxelTransformMatrix = vtkMatrix4x4::New(); + this->ViewportMatrix = vtkMatrix4x4::New(); + this->ShearMatrix = vtkMatrix4x4::New(); + this->WarpMatrix = vtkMatrix4x4::New(); + this->PermutationMatrix = vtkMatrix4x4::New(); + this->PermutedViewToVoxelsMatrix = vtkMatrix4x4::New(); + this->PermutedVoxelsToViewMatrix = vtkMatrix4x4::New(); + this->PerspectiveTransform = vtkTransform::New(); + + this->EncodedVolume = NULL; + this->Octree = NULL; + + this->ImageData = NULL; + this->ImageWidth = 0; + this->ImageHeight = 0; + this->AllocatedSize = 0; + + this->IntemediateImage = NULL; + this->IntermediateWidth = 0; + this->IntermediateHeight = 0; + this->ScalarOpacityMTime = 0; + + this->RenderTimeTable = NULL; + this->RenderVolumeTable = NULL; + this->RenderRendererTable = NULL; + this->RenderTableSize = 0; + this->RenderTableEntries = 0; + + this->GradientEstimator = vtkFiniteDifferenceGradientEstimator::New(); + this->GradientShader = vtkEncodedGradientShader::New(); + + this->IsoValue = 0.0f; + + + this->RunlengthEncoding = 0; + this->FastClassification = 0; + this->Shade = 0; + this->ParallelProjection = 0; + this->MyPerspectiveProjection = 0; + + this->ZBuffer = NULL; + this->IntermediateZBuffer = NULL; + this->IntermixIntersectingGeometry = 0; + + /* + this->FrontDepth = 1.0; + this->DepthDensity = 2.0; + this->DeltaDepth = 1.0 / 255.0; + this->DepthTableSize = 0; + + ComputeDepthTable(0,511); + */ + this->Debug = 0; +} + +void vtkVolumeShearWarpMapper::SetGradientEstimator( + vtkEncodedGradientEstimator *gradest ) +{ + + // If we are setting it to its current value, don't do anything + if ( this->GradientEstimator == gradest ) + { + return; + } + + // If we already have a gradient estimator, unregister it. + if ( this->GradientEstimator ) + { + this->GradientEstimator->UnRegister(this); + this->GradientEstimator = NULL; + } + + // If we are passing in a non-NULL estimator, register it + if ( gradest ) + { + gradest->Register( this ); + } + + // Actually set the estimator, and consider the object Modified + this->GradientEstimator = gradest; + this->Modified(); +} + +vtkVolumeShearWarpMapper::~vtkVolumeShearWarpMapper() +{ + + this->PerspectiveMatrix->Delete(); + this->ViewToWorldMatrix->Delete(); + this->ViewToVoxelsMatrix->Delete(); + this->VoxelsToViewMatrix->Delete(); + this->WorldToVoxelsMatrix->Delete(); + this->VoxelsToWorldMatrix->Delete(); + this->VoxelTransformMatrix->Delete(); + this->ViewportMatrix->Delete(); + this->ShearMatrix->Delete(); + this->WarpMatrix->Delete(); + this->PermutationMatrix->Delete(); + this->PermutedViewToVoxelsMatrix->Delete(); + this->PerspectiveTransform->Delete(); + + this->SetGradientEstimator( NULL ); + this->GradientShader->Delete(); + + if (this->EncodedVolume != NULL) + + delete this->EncodedVolume; + + if (this->IntemediateImage != NULL) + delete this->IntemediateImage; + + if (this->ImageData != NULL) + delete[] this->ImageData; + + if (this->Octree != NULL) + delete this->Octree; +} + +void vtkVolumeShearWarpMapper::Update() +{ + if ( this->GetInput() ) + { + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + } + +} + +void vtkVolumeShearWarpMapper::Render( vtkRenderer *ren, + vtkVolume *vol ) +{ + + this->Volume = vol; + + // make sure that we have scalar input and update the scalar input + if ( this->GetInput() == NULL ) + { + vtkErrorMacro(<< "No Input!"); + + return; + } + else + { + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + } + + // Start timing now. We didn't want to capture the update of the + // input data in the times + this->Timer->StartTimer(); + + vol->UpdateTransferFunctions( ren ); + + ren->ComputeAspect(); + double *aspect = ren->GetAspect(); + vtkCamera *cam = ren->GetActiveCamera(); + + // Keep track of the projection matrix - we'll need it in a couple of places + // Get the projection matrix. The method is called perspective, but + // the matrix is valid for perspective and parallel viewing transforms. + // Don't replace this with the GetCompositePerspectiveTransformMatrix because that + + // turns off stereo rendering!!! + this->PerspectiveTransform->SetMatrix(cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1], + 0.0, 1.0 )); + this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix()); + this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix()); + + + // Compute some matrices from voxels to view and vice versa based + // on the whole input + + this->VoxelTransformMatrix->DeepCopy( vol->GetMatrix() ); + + + + this->ComputeMatrices( this->GetInput(), vol ); + this->ParallelProjection = cam->GetParallelProjection(); + + // How big is the viewport in pixels? + double *viewport = ren->GetViewport(); + + int *renWinSize = ren->GetRenderWindow()->GetSize(); + + // Save this so that we can restore it if the image is cancelled + int oldImageSampleDistance = this->ImageSampleDistance; + + // If we are automatically adjusting the size to achieve a desired frame + // rate, then do that adjustment here. Base the new image sample distance + // on the previous one and the previous render time. Don't let + // the adjusted image sample distance be less than the minimum image sample + // distance or more than the maximum image sample distance. + if ( this->AutoAdjustSampleDistances ) + { + float oldTime = this->RetrieveRenderTime( ren, vol ); + float newTime = vol->GetAllocatedRenderTime(); + this->ImageSampleDistance = (this->ImageSampleDistance * int(0.5+(sqrt(oldTime / newTime))));//int(rint(sqrt(oldTime / newTime)))); + this->ImageSampleDistance = + (this->ImageSampleDistance>this->MaximumImageSampleDistance)? + (this->MaximumImageSampleDistance):(this->ImageSampleDistance); + this->ImageSampleDistance = + (this->ImageSampleDistance<this->MinimumImageSampleDistance)? + + (this->MinimumImageSampleDistance):(this->ImageSampleDistance); + } + + vol->UpdateScalarOpacityforSampleSize( ren, this->ImageSampleDistance ); + + // The full image fills the viewport. First, compute the actual viewport + // size, then divide by the ImageSampleDistance to find the full image + // size in pixels + this->ImageViewportSize[0] = static_cast<int> + (static_cast<float>(renWinSize[0]) * (viewport[2]-viewport[0])); + this->ImageViewportSize[1] = static_cast<int> + (static_cast<float>(renWinSize[1]) * (viewport[3]-viewport[1])); + + this->ImageViewportSize[0] = + static_cast<int>( static_cast<float>(this->ImageViewportSize[0]) ); + this->ImageViewportSize[1] = + static_cast<int>( static_cast<float>(this->ImageViewportSize[1]) ); + +/* + this->ImageViewportSize[0] = + static_cast<int>( static_cast<float>(this->ImageViewportSize[0]) / + static_cast<float>(this->ImageSampleDistance) ); + this->ImageViewportSize[1] = + static_cast<int>( static_cast<float>(this->ImageViewportSize[1]) / + static_cast<float>(this->ImageSampleDistance) ); +*/ + vol->UpdateTransferFunctions( ren ); + + vol->UpdateScalarOpacityforSampleSize( ren, this->ImageSampleDistance ); + + this->Shade = vol->GetProperty()->GetShade(); + + this->GradientEstimator->SetInput( this->GetInput() ); + + if ( this->Shade ) + { + this->GradientShader->UpdateShadingTable( ren, vol, + this->GradientEstimator ); + this->EncodedNormals = + this->GradientEstimator->GetEncodedNormals(); + + this->RedDiffuseShadingTable = + this->GradientShader->GetRedDiffuseShadingTable(vol); + this->GreenDiffuseShadingTable = + this->GradientShader->GetGreenDiffuseShadingTable(vol); + this->BlueDiffuseShadingTable = + this->GradientShader->GetBlueDiffuseShadingTable(vol); + + this->RedSpecularShadingTable = + this->GradientShader->GetRedSpecularShadingTable(vol); + this->GreenSpecularShadingTable = + this->GradientShader->GetGreenSpecularShadingTable(vol); + this->BlueSpecularShadingTable = + this->GradientShader->GetBlueSpecularShadingTable(vol); + } + else + { + + this->EncodedNormals = NULL; + this->RedDiffuseShadingTable = NULL; + this->GreenDiffuseShadingTable = NULL; + this->BlueDiffuseShadingTable = NULL; + this->RedSpecularShadingTable = NULL; + this->GreenSpecularShadingTable = NULL; + this->BlueSpecularShadingTable = NULL; + } + + // If we have non-constant opacity on the gradient magnitudes, + // we need to use the gradient magnitudes to look up the opacity + if ( vol->GetGradientOpacityConstant() == -1.0 ) + { + this->GradientMagnitudes = + this->GradientEstimator->GetGradientMagnitudes(); + } + else + { + this->GradientMagnitudes = NULL; + } + + float bounds[6]; + int dim[3]; + + + this->GetInput()->GetDimensions(dim); + bounds[0] = bounds[2] = bounds[4] = 0.0; + bounds[1] = static_cast<float>(dim[0]-1); + bounds[3] = static_cast<float>(dim[1]-1); + bounds[5] = static_cast<float>(dim[2]-1); + + float voxelPoint[3]; + float viewPoint[8][4]; + int i, j, k; +// unsigned char *ucptr; + float minX, minY, maxX, maxY, minZ, maxZ; + + minX = 1.0; + minY = 1.0; + maxX = -1.0; + maxY = -1.0; + minZ = 1.0; + maxZ = 0.0; + + double camPos[3]; + double worldBounds[6]; + vol->GetBounds( worldBounds ); + int insideFlag = 0; + ren->GetActiveCamera()->GetPosition( camPos ); + if ( camPos[0] >= worldBounds[0] && + camPos[0] <= worldBounds[1] && + camPos[1] >= worldBounds[2] && + camPos[1] <= worldBounds[3] && + camPos[2] >= worldBounds[4] && + camPos[2] <= worldBounds[5] ) + { + insideFlag = 1; + } + + + + // Copy the voxelsToView matrix to 16 floats + float voxelsToViewMatrix[16]; + for ( j = 0; j < 4; j++ ) + { + for ( i = 0; i < 4; i++ ) + { + voxelsToViewMatrix[j*4+i] = + static_cast<float>(this->VoxelsToViewMatrix->GetElement(j,i)); + } + } + + // Convert the voxel bounds to view coordinates to find out the + // size and location of the image we need to generate. + int idx = 0; + if ( insideFlag ) + { + minX = -1.0; + maxX = 1.0; + minY = -1.0; + maxY = 1.0; + minZ = 0.001; + maxZ = 0.001; + } + else + + { + for ( k = 0; k < 2; k++ ) + { + voxelPoint[2] = bounds[4+k]; + for ( j = 0; j < 2; j++ ) + { + voxelPoint[1] = bounds[2+j]; + for ( i = 0; i < 2; i++ ) + { + voxelPoint[0] = bounds[i]; + vtkVSWMultiplyPointMacro( voxelPoint, viewPoint[idx], + voxelsToViewMatrix ); + + minX = (viewPoint[idx][0]<minX)?(viewPoint[idx][0]):(minX); + minY = (viewPoint[idx][1]<minY)?(viewPoint[idx][1]):(minY); + maxX = (viewPoint[idx][0]>maxX)?(viewPoint[idx][0]):(maxX); + maxY = (viewPoint[idx][1]>maxY)?(viewPoint[idx][1]):(maxY); + minZ = (viewPoint[idx][2]<minZ)?(viewPoint[idx][2]):(minZ); + maxZ = (viewPoint[idx][2]>maxZ)?(viewPoint[idx][2]):(maxZ); + idx++; + } + } + } + } + + if ( minZ < 0.001 || maxZ > 0.9999 ) + { + minX = -1.0; + maxX = 1.0; + minY = -1.0; + maxY = 1.0; + insideFlag = 1; + } + + this->MinimumViewDistance = + (minZ<0.001)?(0.001):((minZ>0.999)?(0.999):(minZ)); + + if ( !ren->GetRenderWindow()->GetAbortRender() ) + this->FactorViewMatrix(); + + if ( this->ClippingPlanes ) + this->InitializeClippingPlanes( this->ClippingPlanes ); + + if (this->IntermixIntersectingGeometry == 1) + { + if ( !ren->GetRenderWindow()->GetAbortRender() ) + this->ExtractZBuffer(ren,vol); + } + + + if ( !ren->GetRenderWindow()->GetAbortRender() ) + this->CompositeIntermediate(); + + if ( !ren->GetRenderWindow()->GetAbortRender() ) + this->RenderTexture(ren,vol); + + if ( !ren->GetRenderWindow()->GetAbortRender() ) + { + this->Timer->StopTimer(); + this->TimeToDraw = this->Timer->GetElapsedTime(); + this->StoreRenderTime( ren, vol, this->TimeToDraw ); + } + // Restore the image sample distance so that automatic adjustment + // will work correctly + else + { + this->ImageSampleDistance = oldImageSampleDistance; + } + +} + + +#if 0 +vtkVolumeShearWarpMapper *vtkVolumeShearWarpMapper::New() +{ + + // First try to create the object from the vtkObjectFactory + vtkObject* ret = + vtkGraphicsFactory::CreateInstance("vtkVolumeShearWarpMapper"); + + if (ret != NULL) + return (vtkVolumeShearWarpMapper*)ret; + + return vtkOpenGLVolumeShearWarpMapper::New(); +} +#endif + +void vtkVolumeShearWarpMapper::ComputeMatrices( vtkImageData *data, + vtkVolume *vol ) +{ + // Get the data spacing. This scaling is not accounted for in + // the volume's matrix, so we must add it in. + double volumeSpacing[3]; + data->GetSpacing( volumeSpacing ); + + // Get the origin of the data. This translation is not accounted for in + // the volume's matrix, so we must add it in. + double volumeOrigin[3]; + data->GetOrigin( volumeOrigin ); + + // Get the dimensions of the data. + int volumeDimensions[3]; + data->GetDimensions( volumeDimensions ); + + // Create some transform objects that we will need later + vtkTransform *voxelsTransform = vtkTransform::New(); + vtkTransform *voxelsToViewTransform = vtkTransform::New(); + + // Get the volume matrix. This is a volume to world matrix right now. + // We'll need to invert it, translate by the origin and scale by the + // spacing to change it to a world to voxels matrix. + vtkMatrix4x4 *volMatrix = vtkMatrix4x4::New(); + volMatrix->DeepCopy( vol->GetMatrix() ); + + voxelsToViewTransform->SetMatrix( volMatrix ); + + // Create a transform that will account for the scaling and translation of + // the scalar data. The is the volume to voxels matrix. + voxelsTransform->Identity(); + voxelsTransform->Translate(volumeOrigin[0], + volumeOrigin[1], + volumeOrigin[2] ); + + voxelsTransform->Scale( volumeSpacing[0], + + volumeSpacing[1], + volumeSpacing[2] ); + + + + // Now concatenate the volume's matrix with this scalar data matrix + voxelsToViewTransform->PreMultiply(); + voxelsToViewTransform->Concatenate( voxelsTransform->GetMatrix() ); + + // Now we actually have the world to voxels matrix - copy it out + this->WorldToVoxelsMatrix->DeepCopy( voxelsToViewTransform->GetMatrix() ); + this->WorldToVoxelsMatrix->Invert(); + + // We also want to invert this to get voxels to world + this->VoxelsToWorldMatrix->DeepCopy( voxelsToViewTransform->GetMatrix() ); + + + // Compute the voxels to view transform by concatenating the + // voxels to world matrix with the projection matrix (world to view) + + voxelsToViewTransform->PostMultiply(); + voxelsToViewTransform->Concatenate( this->PerspectiveMatrix ); + + + + this->VoxelsToViewMatrix->DeepCopy( voxelsToViewTransform->GetMatrix() ); + + this->ViewToVoxelsMatrix->DeepCopy( this->VoxelsToViewMatrix ); + this->ViewToVoxelsMatrix->Invert(); + + voxelsToViewTransform->Delete(); + voxelsTransform->Delete(); + volMatrix->Delete(); +} + +float vtkVolumeShearWarpMapper::RetrieveRenderTime( vtkRenderer *ren, + vtkVolume *vol ) +{ + int i; + + for ( i = 0; i < this->RenderTableEntries; i++ ) + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + return this->RenderTimeTable[i]; + } + } + + return 0.0; +} + +void vtkVolumeShearWarpMapper::StoreRenderTime( vtkRenderer *ren, + vtkVolume *vol, + float time ) +{ + int i; + for ( i = 0; i < this->RenderTableEntries; i++ ) + + { + if ( this->RenderVolumeTable[i] == vol && + this->RenderRendererTable[i] == ren ) + { + this->RenderTimeTable[i] = time; + return; + } + } + + + // Need to increase size + if ( this->RenderTableEntries >= this->RenderTableSize ) + { + if ( this->RenderTableSize == 0 ) + { + this->RenderTableSize = 10; + } + else + { + this->RenderTableSize *= 2; + } + + float *oldTimePtr = this->RenderTimeTable; + vtkVolume **oldVolumePtr = this->RenderVolumeTable; + + vtkRenderer **oldRendererPtr = this->RenderRendererTable; + + this->RenderTimeTable = new float [this->RenderTableSize]; + this->RenderVolumeTable = new vtkVolume *[this->RenderTableSize]; + this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize]; + + for (i = 0; i < this->RenderTableEntries; i++ ) + { + this->RenderTimeTable[i] = oldTimePtr[i]; + this->RenderVolumeTable[i] = oldVolumePtr[i]; + this->RenderRendererTable[i] = oldRendererPtr[i]; + } + + delete [] oldTimePtr; + delete [] oldVolumePtr; + delete [] oldRendererPtr; + } + + this->RenderTimeTable[this->RenderTableEntries] = time; + this->RenderVolumeTable[this->RenderTableEntries] = vol; + this->RenderRendererTable[this->RenderTableEntries] = ren; + + this->RenderTableEntries++; +} + +void vtkVolumeShearWarpMapper::CompositeIntermediate() +{ + int scalarType = this->GetInput()->GetScalarType(); + int interpolationType = this->Volume->GetProperty()->GetInterpolationType(); + + + this->ImageWidth = 32; + this->ImageHeight = 32; + + while (this->ImageWidth < this->MaximumIntermediateDimension) + this->ImageWidth = this->ImageWidth << 1; + + while (this->ImageHeight < this->MaximumIntermediateDimension) + this->ImageHeight = this->ImageHeight << 1; + + int imageSize = this->ImageWidth * this->ImageHeight; + + if (imageSize > this->AllocatedSize) + { + this->AllocatedSize = imageSize; + + if (this->ImageData != NULL) + delete[] this->ImageData; + + this->ImageData = new unsigned char[imageSize*4]; + + if (this->IntemediateImage != NULL) + delete this->IntemediateImage; + + this->IntemediateImage = new vtkShearWarpRLEImage(imageSize); + } + else + this->IntemediateImage->Clear(); + + if (this->RunlengthEncoding == 1) + { + if (this->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + if (this->EncodedVolume != NULL) + { + if (this->EncodedVolume->IsScalarEncoded()) + { + if (this->EncodedVolume->GetIsoValue() != this->IsoValue) + { + delete this->EncodedVolume; + this->EncodedVolume = NULL; + } + } + else + { + delete this->EncodedVolume; + this->EncodedVolume = NULL; + } + } + + + if (this->EncodedVolume == NULL) + { + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + { + vtkShearWarpRLEVolume<unsigned char> *encodedVolume = new vtkShearWarpRLEVolume<unsigned char>(); + encodedVolume->encodeScalar(this->GetInput(),this->Volume,this->GradientEstimator,this->IsoValue); + this->EncodedVolume = encodedVolume; + break; + } + case VTK_UNSIGNED_SHORT: + { + vtkShearWarpRLEVolume<unsigned short> *encodedVolume = new vtkShearWarpRLEVolume<unsigned short>(); + encodedVolume->encodeScalar(this->GetInput(),this->Volume,this->GradientEstimator,this->IsoValue); + this->EncodedVolume = encodedVolume; + break; + } + } + } + + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + if ( interpolationType == VTK_NEAREST_INTERPOLATION ) + CompositeIntermediateNearestRLE<unsigned char>(this->IntemediateImage,this); + else + CompositeIntermediateLinearRLE<unsigned char>(this->IntemediateImage,this); + + break; + + case VTK_UNSIGNED_SHORT: + if ( interpolationType == VTK_NEAREST_INTERPOLATION ) + + CompositeIntermediateNearestRLE<unsigned short>(this->IntemediateImage,this); + else +// if(ParallelProjection) + CompositeIntermediateLinearRLE<unsigned short>(this->IntemediateImage,this); +// else +// CompositeIntermediateLinearRLEPerspective<unsigned short>(this->IntemediateImage,this); + + break; + } + } + else + { + // If the scalar opacity transfer function has been modified + // the runlength encoding has to be redone + unsigned long scalarOpacityMTime = this->Volume->GetProperty()->GetScalarOpacity()->GetMTime(); + + if (this->EncodedVolume != NULL) + { + if ( scalarOpacityMTime > this->ScalarOpacityMTime) + { + delete this->EncodedVolume; + this->EncodedVolume = NULL; + } + } + + if (this->EncodedVolume == NULL) + { + this->ScalarOpacityMTime = scalarOpacityMTime; + + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + { + vtkShearWarpRLEVolume<unsigned char> *encodedVolume = new vtkShearWarpRLEVolume<unsigned char>(); + encodedVolume->encodeOpacity(this->GetInput(),this->Volume,this->GradientEstimator,0.0f); + this->EncodedVolume = encodedVolume; + break; + } + + + case VTK_UNSIGNED_SHORT: + { + vtkShearWarpRLEVolume<unsigned short> *encodedVolume = new vtkShearWarpRLEVolume<unsigned short>(); + + encodedVolume->encodeOpacity(this->GetInput(),this->Volume,this->GradientEstimator,0.0f); + this->EncodedVolume = encodedVolume; + break; + } + } + } + + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + if ( interpolationType == VTK_NEAREST_INTERPOLATION ) + CompositeIntermediateNearestRLE<unsigned char>(this->IntemediateImage,this); + else + CompositeIntermediateLinearRLE<unsigned char>(this->IntemediateImage,this); + + break; + + case VTK_UNSIGNED_SHORT: + if ( interpolationType == VTK_NEAREST_INTERPOLATION ) + CompositeIntermediateNearestRLE<unsigned short>(this->IntemediateImage,this); + else +// if(ParallelProjection) + CompositeIntermediateLinearRLE<unsigned short>(this->IntemediateImage,this); +// else +// CompositeIntermediateLinearRLEPerspective<unsigned short>(this->IntemediateImage,this); + + break; + } + } + } + else if (this->FastClassification == 1) + { + if (this->EncodedVolume != NULL) + { + delete this->EncodedVolume; + this->EncodedVolume = NULL; + } + + if (this->Octree == NULL) + { + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + this->Octree = new vtkShearWarpOctree<unsigned char>(); + dynamic_cast< vtkShearWarpOctree<unsigned char> *>(this->Octree)->build(this->GetInput()); + break; + case VTK_UNSIGNED_SHORT: + this->Octree = new vtkShearWarpOctree<unsigned short>(); + dynamic_cast< vtkShearWarpOctree<unsigned short> *>(this->Octree)->build(this->GetInput()); + break; + } + } + + if (this->FunctionType == VTK_SHEAR_WARP_ISOSURFACE_FUNCTION) + { + if (!this->Octree->IsScalarEncoded() || this->Octree->GetIsoValue() != this->IsoValue) + { + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + dynamic_cast< vtkShearWarpOctree<unsigned char> *>(this->Octree)->classifyScalar((unsigned char)this->IsoValue); + break; + case VTK_UNSIGNED_SHORT: + dynamic_cast< vtkShearWarpOctree<unsigned short> *>(this->Octree)->classifyScalar((unsigned short)this->IsoValue); + break; + } + } + } + else + { + unsigned long scalarOpacityMTime = this->Volume->GetProperty()->GetScalarOpacity()->GetMTime(); + + if ( scalarOpacityMTime > this->ScalarOpacityMTime) + { + this->ScalarOpacityMTime = scalarOpacityMTime; + + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + dynamic_cast< vtkShearWarpOctree<unsigned char> *>(this->Octree)->classifyOpacity(this->Volume); + break; + case VTK_UNSIGNED_SHORT: + dynamic_cast< vtkShearWarpOctree<unsigned short> *>(this->Octree)->classifyOpacity(this->Volume); + break; + } + } + } + + if ( interpolationType == VTK_NEAREST_INTERPOLATION ) + { + // Nearest neighbor + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + CompositeIntermediateNearestUnclassified<unsigned char>(this->IntemediateImage,this); + break; + case VTK_UNSIGNED_SHORT: + CompositeIntermediateNearestUnclassified<unsigned short>(this->IntemediateImage,this); + break; + } + } + else + { + // Linear interpolation + switch ( scalarType ) + { + + case VTK_UNSIGNED_CHAR: + CompositeIntermediateLinearUnclassified<unsigned char>(this->IntemediateImage,this); + break; + case VTK_UNSIGNED_SHORT: + CompositeIntermediateLinearUnclassified<unsigned short>(this->IntemediateImage,this); + break; + } + } + } + else + { + if ( interpolationType == VTK_NEAREST_INTERPOLATION ) + { + // Nearest neighbor + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + CompositeIntermediateNearestSimple<unsigned char>(this->IntemediateImage,this); + break; + case VTK_UNSIGNED_SHORT: + CompositeIntermediateNearestSimple<unsigned short>(this->IntemediateImage,this); + break; + } + } + else + { + // Linear interpolation + switch ( scalarType ) + { + case VTK_UNSIGNED_CHAR: + CompositeIntermediateLinearSimple<unsigned char>(this->IntemediateImage,this); + break; + case VTK_UNSIGNED_SHORT: + + CompositeIntermediateLinearSimple<unsigned short>(this->IntemediateImage,this); + break; + } + } + } + + BuildImage(this->ImageData,this->IntemediateImage->GetPixelData()); + + bool Debug_IntermediateImage = true; + if(Debug_IntermediateImage) + { + FILE *fp; + fp = fopen("c:\\temp\\output.raw", "wb+"); + fwrite(this->ImageData, 4, this->ImageWidth * this->ImageHeight, fp); + fclose(fp); + } + +} + + +void vtkVolumeShearWarpMapper::BuildImage(unsigned char *id, vtkShearWarpPixelData *im) +{ + int i,j; + float red,green,blue,opacity; + + int startX = 0;//int(float(this->ImageWidth) * 0.5f - float(this->IntermediateWidth) * 0.5f); + int startY = 0;//int(float(this->ImageHeight) * 0.5f - float(this->IntermediateHeight) * 0.5f); + + for (j = 0; j < this->ImageHeight; j++) + + { + for (i = 0; i < this->ImageWidth; i++) + { + red = 0.0f; + + green = 0.0f; + blue = 0.0f; + opacity = 0.0f; + + if (/*i >= startX && j >= startY && */i < startX+this->IntermediateWidth && j < startY+this->IntermediateHeight) + { + red = im->Red; + green = im->Green; + blue = im->Blue; + opacity = im->Opacity; + + if (red > 1.0f) + red = 1.0f; + else if (red < 0.0f) + red = 0.0f; + + if (green > 1.0f) + + green = 1.0f; + else if (green < 0.0f) + green = 0.0f; + + if (blue > 1.0f) + blue = 1.0f; + else if (blue < 0.0f) + blue = 0.0f; + + if (opacity > 1.0f) + opacity = 1.0f; + else if (opacity < 0.0f) + opacity = 0.0f; + + im++; + } + /* + else + { + red = 1.0f; + green = 0.0f; + blue = 0.0f; + opacity = 1.0f; + } + */ + id[0] = (unsigned char) (255.0f * red); + id[1] = (unsigned char) (255.0f * green); + id[2] = (unsigned char) (255.0f * blue); + id[3] = (unsigned char) (255.0f * opacity); + + id += 4; + } + } +} + +void vtkVolumeShearWarpMapper::ExtractZBuffer(vtkRenderer *ren, vtkVolume *vol) +{ + float iposition[4][2]; + float itranslation[2]; + float isx, isy; + float ix,iy; + float w00,w01,w10,w11; + + int *renWinSize = ren->GetRenderWindow()->GetSize(); + +// float *viewport = ren->GetViewport(); + + // The coefficients of the 2D warp matrix + w00 = WarpMatrix->Element[0][0]; + w01 = WarpMatrix->Element[0][1]; + w10 = WarpMatrix->Element[1][0]; + w11 = WarpMatrix->Element[1][1]; + + ix = (float) this->vtkVolumeShearWarpMapper::IntermediateWidth * this->ImageSampleDistance; + iy = (float) this->vtkVolumeShearWarpMapper::IntermediateHeight * this->ImageSampleDistance; + + + // Intermediate + iposition[0][0] = 0.0f * w00 + 0.0f * w01; + iposition[0][1] = 0.0f * w10 + 0.0f * w11; + + iposition[1][0] = ix * w00 + 0.0f * w01; + iposition[1][1] = ix * w10 + 0.0f * w11; + + iposition[2][0] = ix * w00 + iy * w01; + iposition[2][1] = ix * w10 + iy * w11; + + iposition[3][0] = 0.0f * w00 + iy * w01; + iposition[3][1] = 0.0f * w10 + iy * w11; + + // Intermediate + itranslation[0] = ix * 0.5f * w00 + iy * 0.5f * w01; + itranslation[1] = ix * 0.5f * w10 + iy * 0.5f * w11; + + // Intermediate + isx = 1;//(float) this->vtkVolumeShearWarpMapper::ImageSampleDistance; + isy = 1;//(float) this->vtkVolumeShearWarpMapper::ImageSampleDistance; + + double *t = vol->GetCenter(); + float a[4] = {t[0],t[1],t[2],1.0f}; + float b[4]; + + + this->PerspectiveMatrix->MultiplyPoint(a,b); + b[2] = 0.0f; + + float x1 = isx*(iposition[0][0]-itranslation[0]) + b[0] * (float) renWinSize[0] * 0.5f; + float x2 = isx*(iposition[1][0]-itranslation[0]) + b[0] * (float) renWinSize[0] * 0.5f; + float x3 = isx*(iposition[2][0]-itranslation[0]) + b[0] * (float) renWinSize[0] * 0.5f; + float x4 = isx*(iposition[3][0]-itranslation[0]) + b[0] * (float) renWinSize[0] * 0.5f; + + float y1 = isy*(iposition[0][1]-itranslation[1]) + b[1] * (float) renWinSize[1] * 0.5f; + float y2 = isy*(iposition[1][1]-itranslation[1]) + b[1] * (float) renWinSize[1] * 0.5f; + float y3 = isy*(iposition[2][1]-itranslation[1]) + b[1] * (float) renWinSize[1] * 0.5f; + float y4 = isy*(iposition[3][1]-itranslation[1]) + b[1] * (float) renWinSize[1] * 0.5f; + + + + x1 = x1 + renWinSize[0] * 0.5f; + y1 = y1 + renWinSize[1] * 0.5f; + + + x2 = x2 + renWinSize[0] * 0.5f; + y2 = y2 + renWinSize[1] * 0.5f; + + x3 = x3 + renWinSize[0] * 0.5f; + y3 = y3 + renWinSize[1] * 0.5f; + + + x4 = x4 + renWinSize[0] * 0.5f; + y4 = y4 + renWinSize[1] * 0.5f; + + float minx = x1; + float miny = y1; + float maxx = x1; + float maxy = y1; + + if (x2 < minx) + minx = x2; + + if (y2 < miny) + miny = y2; + + if (x3 < minx) + minx = x3; + + if (y3 < miny) + miny = y3; + + if (x4 < minx) + minx = x4; + + if (y4 < miny) + miny = y4; + + + if (x2 > maxx) + + maxx = x2; + + if (y2 > maxy) + maxy = y2; + + if (x3 > maxx) + maxx = x3; + + if (y3 > maxy) + maxy = y3; + + if (x4 > maxx) + maxx = x4; + + if (y4 > maxy) + maxy = y4; + + int left = 0; + int top = 0; + + if (minx < 0) + { + left = (int) -minx; + minx = 0; + } + + if (miny < 0) + { + top = (int) -miny; + miny = 0; + } + + if (maxx > renWinSize[0] - 1) + maxx = renWinSize[0] - 1; + + if (maxy > renWinSize[1] - 1) + maxy = renWinSize[1] - 1; + + int zx1 = int(minx + 0.5f); + int zy1 = int(miny + 0.5f); + int zx2 = int(maxx - 0.5f); + int zy2 = int(maxy - 0.5f); + + + this->ZBuffer = ren->GetRenderWindow()->GetZbufferData(zx1,zy1,zx2,zy2); + this->ZBufferSize[0] = zx2 - zx1 + 1; + this->ZBufferSize[1] = zy2 - zy1 + 1; + + this->IntermediateZBuffer = new float[(this->ImageSampleDistance*this->IntermediateWidth) * (this->ImageSampleDistance*this->IntermediateHeight)]; + +// this->Unwarp(this->IntermediateZBuffer,this->IntermediateWidth,this->IntermediateHeight,this->ZBuffer,this->ZBufferSize[0],this->ZBufferSize[1],this->WarpMatrix); + this->Unwarp(this->IntermediateZBuffer, this->ImageSampleDistance*this->IntermediateWidth, this->ImageSampleDistance*this->IntermediateHeight, this->ZBuffer, left, top, this->ZBufferSize[0],this->ZBufferSize[1],this->WarpMatrix); + +} + +void vtkVolumeShearWarpMapper::Unwarp(float *destination, int dWidth, int dHeight, float *source, int left, int top, int sWidth, int sHeight, vtkMatrix4x4* w) + +{ + float xs, ys; // source image coordinates + float xsMin,ysMin; + int i, j; // counters + float xd, yd; // precomputed destination values + float pc; // perspective correction + float inv00, inv01, inv03; // elements of 1st row of inverted warp matrix + float inv10, inv11, inv13; // elements of 2nd row of inverted warp matrix + float inv30, inv31, inv33; // elements of 3rd row of inverted warp matrix + + inv00 = w->Element[0][0]; + inv01 = w->Element[0][1]; + inv03 = w->Element[0][3]; + inv10 = w->Element[1][0]; + inv11 = w->Element[1][1]; + inv13 = w->Element[1][3]; + inv30 = w->Element[3][0]; + inv31 = w->Element[3][1]; + inv33 = w->Element[3][3]; + + xsMin = 4096; + ysMin = 4096; + + for (j=0; j < dHeight; j++) + { + yd = (float)j; + for (i=0; i < dWidth; i++) + { + xd = (float)i; + pc = xd * inv30 + yd * inv31 + inv33; + xs = ((xd * inv00 + yd * inv01 + inv03)) / pc; + ys = ((xd * inv10 + yd * inv11 + inv13)) / pc; + + if (xs < xsMin) + xsMin = xs; + + + if (ys < ysMin) + ysMin = ys; + } + } + + for (j=0; j < dHeight; j++) + { + yd = (float)j; + for (i=0; i < dWidth; i++) + { + xd = (float)i; + pc = xd * inv30 + yd * inv31 + inv33; + + xs = ((xd * inv00 + yd * inv01 + inv03)) / pc; + ys = ((xd * inv10 + yd * inv11 + inv13)) / pc; + + xs -= xsMin; + ys -= ysMin; + + + xs -= left; + ys -= top; + + float depth; + + // Check if pixel is inside image + if (xs > sWidth - 1 || ys > sHeight - 1 || xs < 0 || ys < 0) + destination[i + j * dWidth] = 0.0f; + else + { + depth = source[int(xs) + int(ys) * sWidth]; +// memcpy(destination + (i + j * dWidth), source + (int(xs) + int(ys) * sWidth), sizeof(float)); +// memcpy(destination + (i + j * dWidth), source + (int(xs) + int(ys) * sWidth), sizeof(float)); + depth = depth * this->PermutedViewToVoxelsMatrix->Element[2][2] + this->PermutedViewToVoxelsMatrix->Element[2][3]; + destination[i + j * dWidth] = depth; + } + } + } +} + +void vtkVolumeShearWarpMapper::InitializeClippingPlanes( vtkPlaneCollection *planes ) +{ + vtkPlane *onePlane; + double planePoint[4]; + double normalPoint[4]; + float *clippingPlane; + float d; + int i; + + this->ClippingPlaneCount = planes->GetNumberOfItems(); + + if (this->ClippingPlaneCount == 0) + return; + + // loop through all the clipping planes + for ( i = 0; i < this->ClippingPlaneCount; i++ ) + { + onePlane = (vtkPlane *)planes->GetItemAsObject(i); + + onePlane->GetOrigin(planePoint); + onePlane->GetNormal(normalPoint); + normalPoint[0] += planePoint[0]; + normalPoint[1] += planePoint[1]; + normalPoint[2] += planePoint[2]; + planePoint[3] = 1.0; + normalPoint[3] = 1.0; + + this->WorldToVoxelsMatrix->MultiplyPoint(planePoint,planePoint); + this->WorldToVoxelsMatrix->MultiplyPoint(normalPoint,normalPoint); + + this->PermutationMatrix->MultiplyPoint(planePoint,planePoint); + this->PermutationMatrix->MultiplyPoint(normalPoint,normalPoint); + + clippingPlane = this->ClippingPlane + 4*i; + clippingPlane[0] = normalPoint[0] - planePoint[0]; + clippingPlane[1] = normalPoint[1] - planePoint[1]; + clippingPlane[2] = normalPoint[2] - planePoint[2]; + + d = sqrt(clippingPlane[0] * clippingPlane[0] + clippingPlane[1] * clippingPlane[1] + clippingPlane[2] * clippingPlane[2]); + clippingPlane[0] /= d; + clippingPlane[1] /= d; + clippingPlane[2] /= d; + + clippingPlane[3] = clippingPlane[0] * planePoint[0] + clippingPlane[1] * planePoint[1] + clippingPlane[2] * planePoint[2]; + } +} + +int vtkVolumeShearWarpMapper::IsVoxelClipped(int x, int y, int z) +{ + float *clippingPlane; + + for (int i=0; i<this->ClippingPlaneCount; i++) + { + clippingPlane = this->ClippingPlane + 4*i; + + if (clippingPlane[0] * (float)x + + clippingPlane[1] * (float)y + + clippingPlane[2] * (float)z < clippingPlane[3]) + return 1; + } + + return 0; +} + + +// Print the vtkVolumeShearWarpMapper +void vtkVolumeShearWarpMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + if( this->GradientShader ) + { + os << indent << "GradientShader:\n"; + this->GradientShader->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "GradientShader: (none)\n"; + } + os << indent << "FunctionType: " << this->FunctionType << "\n"; + os << indent << "MinimumImageSampleDistance: " << + this->MinimumImageSampleDistance << "\n"; + if( this->GradientEstimator ) + { + os << indent << "GradientEstimator:\n"; + this->GradientEstimator->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "GradientEstimator: (none)\n"; + } + os << indent << "AutoAdjustSampleDistances: " << + this->AutoAdjustSampleDistances << "\n"; + os << indent << "ParallelProjection: " << this->ParallelProjection << + "\n"; + os << indent << "MaximumImageSampleDistance: " << + this->MaximumImageSampleDistance << "\n"; + os << indent << "IntermixIntersectingGeometry: " << + this->IntermixIntersectingGeometry << "\n"; + os << indent << "IsoValue: " << this->IsoValue << "\n"; + os << indent << "MyPerspectiveProjection: " << + this->MyPerspectiveProjection << "\n"; + os << indent << "FastClassification: " << this->FastClassification << + "\n"; + os << indent << "RunlengthEncoding: " << this->RunlengthEncoding << "\n"; + os << indent << "ImageSampleDistance: " << this->ImageSampleDistance + << "\n"; +} diff --git a/VolumeRendering/vtkVolumeShearWarpMapper.h b/VolumeRendering/vtkVolumeShearWarpMapper.h new file mode 100644 index 0000000..cf21456 --- /dev/null +++ b/VolumeRendering/vtkVolumeShearWarpMapper.h @@ -0,0 +1,371 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeShearWarpMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeShearWarpMapper - Abstract class for a Shear Warp Volume Mapper + +// .SECTION Description +// vtkVolumeShearWarpMapper is a base class for volume mappers using +// the shear-warp factorization algorithm. + +// .SECTION see also +// vtkVolumeMapper vtkOpenGLVolumeShearWarpMapper + +// .SECTION Thanks +// Thanks to Stefan Bruckner for developing and contributing this code +// and to Namkug Kim for some fixing and tidying of the code + +// .SECTION References +// P. Lacroute. "Fast Volume Rendering Using a Shear- +// Warp Factorization of the Viewing Transformation" +// PhD thesis, Stanford University, 1995. +// +// P. Lacroute and M. Levoy. "Fast volume rendering using +// a shear-warp factorization of the viewing transformation" +// Proceedings of the 21st annual conference +// on Computer graphics and interactive techniques, +// pages 451–458, 1994. +// +// "The InverseWarp: Non-Invasive Integration of Shear-Warp +// Volume Rendering into Polygon Rendering Pipelines" +// Stefan Bruckner, Dieter Schmalstiegy, Helwig Hauserz, +// M. Eduard Groller + +#ifndef __vtkVolumeShearWarpMapper_h +#define __vtkVolumeShearWarpMapper_h + +#include "vtkVolumeMapper.h" + +class vtkEncodedGradientShader; +class vtkEncodedGradientEstimator; + +class vtkStructuredPoints; +class vtkCamera; +class vtkVolume; +class vtkImageData; +class vtkVolumeProperty; +class vtkPiecewiseFunction; +class vtkTransform; +class vtkMatrix4x4; + +class vtkRenderer; +class vtkRenderWindow; + +//#include "vtkVolumeShearWarpDataStructure.h" + +class vtkShearWarpPixelData; +class vtkShearWarpRLEImage; +template <class T> struct vtkShearWarpVoxelData; +template <class T> class vtkShearWarpRLERun; +template <class T> class vtkShearWarpRLESlice; +class vtkShearWarpBase; +template <class T> class vtkShearWarpRLEVolume; +template <class T> class vtkShearWarpSummedAreaTable; +struct vtkShearWarpOctreeRun; +template <class T> class vtkShearWarpOctreeNode; +template <class T> class vtkShearWarpOctree; + +#define VTK_X_AXIS 0 +#define VTK_Y_AXIS 1 +#define VTK_Z_AXIS 2 + +#define VTK_SHEAR_WARP_COMPOSITE_FUNCTION 0 +#define VTK_SHEAR_WARP_MIP_FUNCTION 1 +#define VTK_SHEAR_WARP_ISOSURFACE_FUNCTION 2 + +#define VTK_SHEAR_WARP_OCTREE_TRANSPARENT 0 +#define VTK_SHEAR_WARP_OCTREE_NONTRANSPARENT 1 +#define VTK_SHEAR_WARP_OCTREE_COMBINATION 2 +#define VTK_SHEAR_WARP_OCTREE_MINIMUM_SIZE 16 + + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeShearWarpMapper : public vtkVolumeMapper +{ +//BTX + template <class T> + friend void CompositeIntermediateNearestSimple(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis); + + template <class T> + friend void CompositeIntermediateLinearSimple(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis); + + template <class T> + friend void CompositeIntermediateNearestRLE(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis); + + template <class T> + friend void CompositeIntermediateLinearRLE(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis); + + template <class T> + friend void CompositeIntermediateNearestUnclassified(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis); + + template <class T> + friend void CompositeIntermediateLinearUnclassified(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis); + + template <class T> + friend void CompositeIntermediateLinearRLEPerspective(vtkShearWarpRLEImage *image, vtkVolumeShearWarpMapper *myThis); +//ETX + +public: + static vtkVolumeShearWarpMapper *New(); + vtkTypeRevisionMacro(vtkVolumeShearWarpMapper,vtkVolumeMapper); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Update the volume rendering pipeline by updating the scalar input + virtual void Update(); + + // Description: + // Set / Get the gradient estimator used to estimate normals + void SetGradientEstimator( vtkEncodedGradientEstimator *gradest ); + vtkGetObjectMacro( GradientEstimator, vtkEncodedGradientEstimator ); + + // Description: + // Get the gradient shader. + vtkGetObjectMacro( GradientShader, vtkEncodedGradientShader ); + + // Description: + // Set/Get the value of IsoValue. + vtkSetMacro( IsoValue, float ); + vtkGetMacro( IsoValue, float ); + + // Description: + // Enable/Disable runlength encoding + vtkSetMacro(RunlengthEncoding,int); + vtkGetMacro(RunlengthEncoding,int); + vtkBooleanMacro(RunlengthEncoding,int); + + // Description: + // Enable/Disable classification optimization (fast classification) + vtkSetMacro(FastClassification,int); + vtkGetMacro(FastClassification,int); + vtkBooleanMacro(FastClassification,int); + + // Description: + // Enable/Disable ParallelProjection or PerspectiveProjection + vtkSetMacro(ParallelProjection,int); + vtkGetMacro(ParallelProjection,int); + vtkBooleanMacro(ParallelProjection, int); + + vtkSetMacro(MyPerspectiveProjection,int); + vtkGetMacro(MyPerspectiveProjection,int); + vtkBooleanMacro(MyPerspectiveProjection, int); + + // Description: + // Set the compositing function type. + vtkSetClampMacro( FunctionType, int, + VTK_SHEAR_WARP_COMPOSITE_FUNCTION, VTK_SHEAR_WARP_ISOSURFACE_FUNCTION); + vtkGetMacro(FunctionType,int); + void SetFunctionTypeToComposite() + {this->SetFunctionType(VTK_SHEAR_WARP_COMPOSITE_FUNCTION);}; + void SetFunctionTypeToMIP() + {this->SetFunctionType(VTK_SHEAR_WARP_MIP_FUNCTION);}; + void SetFunctionTypeToIsosurface() + {this->SetFunctionType(VTK_SHEAR_WARP_ISOSURFACE_FUNCTION);}; + + int Debug; + + // Description: + // Sampling distance. Default value of 1 meaning that every voxel is being + // processed, 2 causes every second voxel to be processed, etc. + vtkSetClampMacro( ImageSampleDistance, int, 1, 32 ); + vtkGetMacro( ImageSampleDistance, int ); + + // Description: + // This is the minimum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MinimumImageSampleDistance, int, 1, 32 ); + vtkGetMacro( MinimumImageSampleDistance, int ); + + // Description: + // This is the maximum image sample distance allow when the image + // sample distance is being automatically adjusted + vtkSetClampMacro( MaximumImageSampleDistance, int, 1, 32 ); + vtkGetMacro( MaximumImageSampleDistance, int ); + + // Description: + // If AutoAdjustSampleDistances is on, the the ImageSampleDistance + // will be varied to achieve the allocated render time of this + // prop (controlled by the desired update rate and any culling in + // use). + vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 ); + vtkGetMacro( AutoAdjustSampleDistances, int ); + vtkBooleanMacro( AutoAdjustSampleDistances, int ); + + // Description: + // If IntermixIntersectingGeometry is turned on, the zbuffer will be + // captured and used to limit the traversal of the rays. + vtkSetClampMacro( IntermixIntersectingGeometry, int, 0, 1 ); + vtkGetMacro( IntermixIntersectingGeometry, int ); + vtkBooleanMacro( IntermixIntersectingGeometry, int ); + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol); + +//ETX + +protected: + vtkVolumeShearWarpMapper(); + ~vtkVolumeShearWarpMapper(); + + // Objects / variables needed for shading / gradient magnitude opacity + vtkEncodedGradientEstimator *GradientEstimator; + vtkEncodedGradientShader *GradientShader; + int Shade; + + float *RedDiffuseShadingTable; + float *GreenDiffuseShadingTable; + float *BlueDiffuseShadingTable; + float *RedSpecularShadingTable; + float *GreenSpecularShadingTable; + float *BlueSpecularShadingTable; + + unsigned short *EncodedNormals; + unsigned char *GradientMagnitudes; + + vtkTransform *PerspectiveTransform; + vtkMatrix4x4 *PerspectiveMatrix; + vtkMatrix4x4 *ViewToWorldMatrix; + vtkMatrix4x4 *ViewToVoxelsMatrix; + vtkMatrix4x4 *VoxelsToViewMatrix; + vtkMatrix4x4 *WorldToVoxelsMatrix; + vtkMatrix4x4 *VoxelsToWorldMatrix; + vtkMatrix4x4 *VoxelTransformMatrix; + vtkMatrix4x4 *ViewportMatrix; + vtkMatrix4x4 *ShearMatrix; + vtkMatrix4x4 *WarpMatrix; + vtkMatrix4x4 *PermutationMatrix; + vtkMatrix4x4 *PermutedViewToVoxelsMatrix; + vtkMatrix4x4 *PermutedVoxelsToViewMatrix; + + int IntermixIntersectingGeometry; + float *ZBuffer; + float *IntermediateZBuffer; + int ZBufferSize[2]; + int ZBufferOrigin[2]; + float MinimumViewDistance; + + + vtkVolume *Volume; + vtkShearWarpBase *EncodedVolume; + vtkShearWarpBase *Octree; + vtkShearWarpRLEImage *IntemediateImage; + unsigned char *ImageData; + + int ImageWidth; + int ImageHeight; + int AllocatedSize; + + unsigned long ScalarOpacityMTime; + int FunctionType; + float IsoValue; + int RunlengthEncoding; + int FastClassification; + + int CountI; + int CountJ; + int CountK; + + int ReverseOrder; + int MajorAxis; + int ParallelProjection; + int MyPerspectiveProjection; + + int IntermediateWidth; + int IntermediateHeight; + int MaximumIntermediateDimension; + + float ShearI; + float ShearJ; + float TranslationI; + float TranslationJ; + float Scale; + + // Depth cueing stuff + /* + float DepthI; + float DepthJ; + float DepthK; + float Depth0; + float DeltaDepth; + float FrontDepth; + float DepthDensity; + float DepthTable[512]; + int DepthTableSize; + */ + float ClippingPlane[4*6]; + int ClippingPlaneCount; + + // This is how big the image would be if it covered the entire viewport + int ImageViewportSize[2]; + + double WorldViewingDirection[4]; + double ObjectViewingDirection[4]; + double StandardViewingDirection[4]; + + double WorldEyePosition[4]; + double ObjectEyePosition[4]; + double StandardEyePosition[4]; + + // The distance between sample points along the ray + int ImageSampleDistance; + int MinimumImageSampleDistance; + int MaximumImageSampleDistance; + int AutoAdjustSampleDistances; + + float *RenderTimeTable; + vtkVolume **RenderVolumeTable; + vtkRenderer **RenderRendererTable; + int RenderTableSize; + int RenderTableEntries; + + void StoreRenderTime( vtkRenderer *ren, vtkVolume *vol, float t ); + float RetrieveRenderTime( vtkRenderer *ren, vtkVolume *vol ); + + void ComputeMatrices( vtkImageData *data, vtkVolume *vol ); + void FactorViewMatrix(); + void ComputeViewMatrix(); + void ComputeViewportMatrix(); + void ComputePrincipalAxisParallel(); + void ComputePrincipalAxisPerspective(); + void ComputePermutationMatrix(); + void ComputeShearMatrixParallel(); + void ComputeShearMatrixPerspective(); + void ComputeWarpMatrix(); + void CompositeIntermediate(); + void BuildImage(unsigned char *id, vtkShearWarpPixelData *im); + + void Unwarp(float *destination, int dWidth, int dHeight, float *source, int left, int top, int sWidth, int sHeight, vtkMatrix4x4* w); + void ExtractZBuffer(vtkRenderer *ren, vtkVolume *vol); + + void InitializeClippingPlanes( vtkPlaneCollection *planes ); + int IsVoxelClipped(int x, int y, int z); + + // void ComputeDepthTable(int first, int last); + //void DepthCueImage (vtkShearWarpPixelData *im, int slice); + + virtual void RenderTexture(vtkRenderer *ren, vtkVolume *vol) = 0; + +private: + vtkVolumeShearWarpMapper(const vtkVolumeShearWarpMapper&); // Not implemented. + void operator=(const vtkVolumeShearWarpMapper&); // Not implemented. +}; + + + +#endif + + diff --git a/VolumeRendering/vtkVolumeTextureMapper.cxx b/VolumeRendering/vtkVolumeTextureMapper.cxx new file mode 100644 index 0000000..d9462b9 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper.cxx @@ -0,0 +1,304 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeTextureMapper.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeTextureMapper.h" + +#include "vtkEncodedGradientShader.h" +#include "vtkFiniteDifferenceGradientEstimator.h" +#include "vtkGarbageCollector.h" +#include "vtkImageData.h" +#include "vtkPointData.h" +#include "vtkRenderer.h" +#include "vtkVolume.h" +#include "vtkVolumeProperty.h" + +vtkCxxRevisionMacro(vtkVolumeTextureMapper, "$Revision: 1.2 $"); + +vtkVolumeTextureMapper::vtkVolumeTextureMapper() +{ + this->GradientOpacityArray = NULL; + this->RGBAArray = NULL; + this->ArraySize = -1; + this->SampleDistance = 1.0; + this->GradientEstimator = vtkFiniteDifferenceGradientEstimator::New(); + this->GradientShader = vtkEncodedGradientShader::New(); + this->NumberOfComponents = 1; +} + +vtkVolumeTextureMapper::~vtkVolumeTextureMapper() +{ + this->SetGradientEstimator( NULL ); + this->GradientShader->Delete(); + + if ( this->RGBAArray ) + { + delete [] this->RGBAArray; + } + + if ( this->GradientOpacityArray ) + { + delete [] this->GradientOpacityArray; + } +} + +void vtkVolumeTextureMapper::SetGradientEstimator( + vtkEncodedGradientEstimator *gradest ) +{ + + // If we are setting it to its current value, don't do anything + if ( this->GradientEstimator == gradest ) + { + return; + } + + // If we already have a gradient estimator, unregister it. + if ( this->GradientEstimator ) + { + this->GradientEstimator->UnRegister(this); + this->GradientEstimator = NULL; + } + + // If we are passing in a non-NULL estimator, register it + if ( gradest ) + { + gradest->Register( this ); + } + + // Actually set the estimator, and consider the object Modified + this->GradientEstimator = gradest; + this->Modified(); +} + +void vtkVolumeTextureMapper::Update() +{ + if ( this->GetInput() ) + { + this->GetInput()->UpdateInformation(); + this->GetInput()->SetUpdateExtentToWholeExtent(); + this->GetInput()->Update(); + } +} + +void vtkVolumeTextureMapper::InitializeRender( vtkRenderer *ren, + vtkVolume *vol ) +{ + int size, i, j, k; + float *AArray; + float *RGBArray; + float *GArray; + int colorChannels; + float gradientOpacityConstant; + + // Hang on to the render window - we'll need it to test for abort + this->RenderWindow = ren->GetRenderWindow(); + + vol->UpdateTransferFunctions( ren ); + + vol->UpdateScalarOpacityforSampleSize( ren, this->SampleDistance ); + + size = (int) vol->GetArraySize(); + + int numComponents = this->GetInput()-> + GetPointData()->GetScalars()->GetNumberOfComponents(); + + if ( this->ArraySize != size || + this->NumberOfComponents != numComponents ) + { + if ( this->RGBAArray ) + { + delete [] this->RGBAArray; + } + if ( this->GradientOpacityArray ) + { + delete [] this->GradientOpacityArray; + } + + this->RGBAArray = new unsigned char [4*size*numComponents]; + this->GradientOpacityArray = new float [256*numComponents]; + this->ArraySize = size; + this->NumberOfComponents = numComponents; + } + + float *goPtr; + float *goArray; + + for ( int c = 0; c < numComponents; c++ ) + { + goPtr = vol->GetGradientOpacityArray(c); + goArray = this->GradientOpacityArray + c; + + for ( i = 0; i < 256; i++ ) + { + *(goArray) = *(goPtr++); + goArray += numComponents; + } + + AArray = vol->GetCorrectedScalarOpacityArray(c); + colorChannels = vol->GetProperty()->GetColorChannels(c); + + + // Being less than 0.0 implies a transfer function, so just multiply by + // 1.0 here since the transfer function will supply the true opacity + // modulation value + gradientOpacityConstant = vol->GetGradientOpacityConstant(c); + if ( gradientOpacityConstant <= 0.0 ) + { + gradientOpacityConstant = 1.0; + } + + if ( colorChannels == 3 ) + { + RGBArray = vol->GetRGBArray(c); + for ( i=0, j=(c*4), k=0; i < size; i++ ) + { + this->RGBAArray[j++] = (unsigned char) (0.5 + (RGBArray[k++]*255.0)); + this->RGBAArray[j++] = (unsigned char) (0.5 + (RGBArray[k++]*255.0)); + this->RGBAArray[j++] = (unsigned char) (0.5 + (RGBArray[k++]*255.0)); + this->RGBAArray[j++] = + (unsigned char) (0.5 + AArray[i]*255.0*gradientOpacityConstant); + + j += 4*(numComponents-1); + } + } + else if ( colorChannels == 1 ) + { + GArray = vol->GetGrayArray(c); + for ( i=0, j=(c*4); i < size; i++ ) + { + this->RGBAArray[j++] = (unsigned char) (0.5 + (GArray[i]*255.0)); + this->RGBAArray[j++] = (unsigned char) (0.5 + (GArray[i]*255.0)); + this->RGBAArray[j++] = (unsigned char) (0.5 + (GArray[i]*255.0)); + this->RGBAArray[j++] = + (unsigned char) (0.5 + AArray[i]*255.0*gradientOpacityConstant); + + j += 4*(numComponents-1); + } + } + } + + this->Shade = vol->GetProperty()->GetShade(); + + this->GradientEstimator->SetInput( this->GetInput() ); + + if ( this->Shade ) + { + this->GradientShader->UpdateShadingTable( ren, vol, + this->GradientEstimator ); + this->EncodedNormals = + this->GradientEstimator->GetEncodedNormals(); + + this->RedDiffuseShadingTable = + this->GradientShader->GetRedDiffuseShadingTable(vol); + this->GreenDiffuseShadingTable = + this->GradientShader->GetGreenDiffuseShadingTable(vol); + this->BlueDiffuseShadingTable = + this->GradientShader->GetBlueDiffuseShadingTable(vol); + + this->RedSpecularShadingTable = + this->GradientShader->GetRedSpecularShadingTable(vol); + this->GreenSpecularShadingTable = + this->GradientShader->GetGreenSpecularShadingTable(vol); + this->BlueSpecularShadingTable = + this->GradientShader->GetBlueSpecularShadingTable(vol); + } + else + { + this->EncodedNormals = NULL; + this->RedDiffuseShadingTable = NULL; + this->GreenDiffuseShadingTable = NULL; + this->BlueDiffuseShadingTable = NULL; + this->RedSpecularShadingTable = NULL; + this->GreenSpecularShadingTable = NULL; + this->BlueSpecularShadingTable = NULL; + } + + // If we have non-constant opacity on the gradient magnitudes, + // we need to use the gradient magnitudes to look up the opacity + if ( vol->GetGradientOpacityConstant() == -1.0 ) + { + this->GradientMagnitudes = + this->GradientEstimator->GetGradientMagnitudes(); + } + else + { + this->GradientMagnitudes = NULL; + } + + this->GetInput()->GetOrigin( this->DataOrigin ); + this->GetInput()->GetSpacing( this->DataSpacing ); + + this->ConvertCroppingRegionPlanesToVoxels(); +} + +float vtkVolumeTextureMapper::GetGradientMagnitudeScale() +{ + if ( !this->GradientEstimator ) + { + vtkErrorMacro( "You must have a gradient estimator set to get the scale" ); + return 1.0; + } + + return this->GradientEstimator->GetGradientMagnitudeScale(); +} + +float vtkVolumeTextureMapper::GetGradientMagnitudeBias() +{ + if ( !this->GradientEstimator ) + { + vtkErrorMacro( "You must have a gradient estimator set to get the bias" ); + return 1.0; + } + + return this->GradientEstimator->GetGradientMagnitudeBias(); +} + +// Print the vtkVolumeTextureMapper +void vtkVolumeTextureMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->GradientEstimator ) + { + os << indent << "Gradient Estimator: " << (this->GradientEstimator) << + endl; + } + else + { + os << indent << "Gradient Estimator: (none)" << endl; + } + + if ( this->GradientShader ) + { + os << indent << "Gradient Shader: " << (this->GradientShader) << endl; + } + else + { + os << indent << "Gradient Shader: (none)" << endl; + } + + // this->Shade is a temporary variable that should not be printed + // this->RenderWindow is a temporary variable that should not be printed + // this->DataSpacing is a temporary variable that should not be printed + // this->DataOrigin is a temporary variable that should not be printed +} + +//---------------------------------------------------------------------------- +void vtkVolumeTextureMapper::ReportReferences(vtkGarbageCollector* collector) +{ + this->Superclass::ReportReferences(collector); + // These filters share our input and are therefore involved in a + // reference loop. + vtkGarbageCollectorReport(collector, this->GradientEstimator, + "GradientEstimator"); +} diff --git a/VolumeRendering/vtkVolumeTextureMapper.h b/VolumeRendering/vtkVolumeTextureMapper.h new file mode 100644 index 0000000..81fd71d --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper.h @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeTextureMapper.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeTextureMapper - Abstract class for a volume mapper + +// .SECTION Description +// vtkVolumeTextureMapper is the abstract definition of a volume mapper +// that uses a texture mapping approach. + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkVolumeTextureMapper_h +#define __vtkVolumeTextureMapper_h + +#include "vtkVolumeMapper.h" + +class vtkEncodedGradientEstimator; +class vtkEncodedGradientShader; +class vtkRenderWindow; +class vtkRenderer; +class vtkVolume; + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeTextureMapper : public vtkVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkVolumeTextureMapper,vtkVolumeMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + // Description: + // Update the volume rendering pipeline by updating the scalar input + virtual void Update(); + + // Description: + // Set / Get the gradient estimator used to estimate normals + virtual void SetGradientEstimator( vtkEncodedGradientEstimator *gradest ); + vtkGetObjectMacro( GradientEstimator, vtkEncodedGradientEstimator ); + + // Description: + // Get the gradient shader. + vtkGetObjectMacro( GradientShader, vtkEncodedGradientShader ); + +//BTX + // Description: + // Allow access to the arrays / variables from the templated functions in the + // subclasses. + float *GetGradientOpacityArray(){return this->GradientOpacityArray;}; + unsigned char *GetRGBAArray(){return this->RGBAArray;}; + float *GetRedDiffuseShadingTable(){return this->RedDiffuseShadingTable;}; + float *GetGreenDiffuseShadingTable(){return this->GreenDiffuseShadingTable;}; + float *GetBlueDiffuseShadingTable(){return this->BlueDiffuseShadingTable;}; + float *GetRedSpecularShadingTable(){return this->RedSpecularShadingTable;}; + float *GetGreenSpecularShadingTable(){return this->GreenSpecularShadingTable;}; + float *GetBlueSpecularShadingTable(){return this->BlueSpecularShadingTable;}; + unsigned short *GetEncodedNormals(){return this->EncodedNormals;}; + unsigned char *GetGradientMagnitudes(){return this->GradientMagnitudes;}; + vtkGetMacro( Shade, int ); + vtkGetObjectMacro( RenderWindow, vtkRenderWindow ); + vtkGetVectorMacro( DataOrigin, double, 3 ); + vtkGetVectorMacro( DataSpacing, double, 3 ); + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *ren, vtkVolume *vol)=0; + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // Values needed by the volume + virtual float GetGradientMagnitudeScale(); + virtual float GetGradientMagnitudeBias(); + virtual float GetGradientMagnitudeScale(int) + { return this->GetGradientMagnitudeScale(); }; + virtual float GetGradientMagnitudeBias(int) + { return this->GetGradientMagnitudeBias(); }; + +//ETX + + + +protected: + vtkVolumeTextureMapper(); + ~vtkVolumeTextureMapper(); + + void InitializeRender( vtkRenderer *ren, vtkVolume *vol ); + + virtual void ReportReferences(vtkGarbageCollector*); + + // Objects / variables needed for shading / gradient magnitude opacity + vtkEncodedGradientEstimator *GradientEstimator; + vtkEncodedGradientShader *GradientShader; + int Shade; + + float *GradientOpacityArray; + unsigned char *RGBAArray; + int ArraySize; + int NumberOfComponents; + + float *RedDiffuseShadingTable; + float *GreenDiffuseShadingTable; + float *BlueDiffuseShadingTable; + float *RedSpecularShadingTable; + float *GreenSpecularShadingTable; + float *BlueSpecularShadingTable; + + double DataOrigin[3]; + double DataSpacing[3]; + + unsigned short *EncodedNormals; + unsigned char *GradientMagnitudes; + + float SampleDistance; + + vtkRenderWindow *RenderWindow; +private: + vtkVolumeTextureMapper(const vtkVolumeTextureMapper&); // Not implemented. + void operator=(const vtkVolumeTextureMapper&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkVolumeTextureMapper2D.cxx b/VolumeRendering/vtkVolumeTextureMapper2D.cxx new file mode 100644 index 0000000..4860277 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper2D.cxx @@ -0,0 +1,1177 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeTextureMapper2D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeTextureMapper2D.h" + +#include "vtkCamera.h" +#include "vtkVolumeRenderingFactory.h" +#include "vtkImageData.h" +#include "vtkLargeInteger.h" +#include "vtkMatrix4x4.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkTransform.h" +#include "vtkVolumeProperty.h" + +#define VTK_PLUS_X_MAJOR_DIRECTION 0 +#define VTK_MINUS_X_MAJOR_DIRECTION 1 +#define VTK_PLUS_Y_MAJOR_DIRECTION 2 +#define VTK_MINUS_Y_MAJOR_DIRECTION 3 +#define VTK_PLUS_Z_MAJOR_DIRECTION 4 +#define VTK_MINUS_Z_MAJOR_DIRECTION 5 + +template <class T> +void vtkVolumeTextureMapper2D_TraverseVolume( T *data_ptr, + int size[3], + int axis, + int directionFlag, + vtkVolumeTextureMapper2D *me ) +{ + int i, j, k; + int kstart, kend, kinc; + unsigned char *tptr; + T *dptr; + unsigned short *nptr; + unsigned char *gptr = NULL; + float *v, *t; + unsigned char *rgbaArray = me->GetRGBAArray(); + float *gradientOpacityArray; + unsigned char *gradientMagnitudes; + unsigned short *encodedNormals = NULL; + float *redDiffuseShadingTable = NULL; + float *greenDiffuseShadingTable = NULL; + float *blueDiffuseShadingTable = NULL; + float *redSpecularShadingTable = NULL; + float *greenSpecularShadingTable = NULL; + float *blueSpecularShadingTable = NULL; + int shade; + float tmpval; + int cropping, croppingFlags; + double *croppingBounds; + int flag[3], tmpFlag, index; + int clipLow = 0, clipHigh = 0; + vtkRenderWindow *renWin = me->GetRenderWindow(); + double spacing[3], origin[3]; + unsigned char zero[4]; + unsigned char *texture; + int textureSize[2]; + int xTile, yTile, xTotal, yTotal, tile, numTiles; + int *zAxis=0, *yAxis=0, *xAxis=0; + int loc, inc=0; + int saveTextures = me->GetSaveTextures(); + int textureOffset=0; + + int a0=0, a1=0, a2=0; + + switch ( axis ) + { + case 0: + a0 = 1; + a1 = 2; + a2 = 0; + xAxis = &k; + yAxis = &i; + zAxis = &j; + inc = size[0]; + break; + case 1: + a0 = 0; + a1 = 2; + a2 = 1; + xAxis = &i; + yAxis = &k; + zAxis = &j; + inc = 1; + break; + case 2: + a0 = 0; + a1 = 1; + a2 = 2; + xAxis = &i; + yAxis = &j; + zAxis = &k; + inc = 1; + break; + } + + int *axisTextureSize = me->GetAxisTextureSize(); + textureSize[0] = axisTextureSize[a2*3+0]; + textureSize[1] = axisTextureSize[a2*3+1]; + + if ( saveTextures ) + { + texture = me->GetTexture(); + switch ( axis ) + { + case 0: + textureOffset = 0; + break; + case 1: + textureOffset = + 4*axisTextureSize[0]*axisTextureSize[1]*axisTextureSize[2]; + break; + case 2: + textureOffset = + 4*axisTextureSize[0]*axisTextureSize[1]*axisTextureSize[2] + + 4*axisTextureSize[3]*axisTextureSize[4]*axisTextureSize[5]; + break; + } + } + else + { + // Create space for the texture + texture = new unsigned char[4*textureSize[0]*textureSize[1]]; + textureOffset = 0; + } + + // How many tiles are there in X? in Y? total? + xTotal = textureSize[0] / size[a0]; + yTotal = textureSize[1] / size[a1]; + numTiles = xTotal * yTotal; + + // Create space for the vertices and texture coordinates. You need four vertices + // with three components each for each tile, and four texture coordinates with + // three components each for each texture coordinate + v = new float [12*numTiles]; + t = new float [ 8*numTiles]; + + // Convenient for filling in the empty regions (due to clipping) + zero[0] = 0; + zero[1] = 0; + zero[2] = 0; + zero[3] = 0; + + // We need to know the spacing and origin of the data to set up the coordinates + // correctly + me->GetDataSpacing( spacing ); + me->GetDataOrigin( origin ); + + // What is the first plane, the increment to move to the next plane, and the plane + // that is just past the end? + if ( directionFlag ) + { + kstart = 0; + kend = ((int)( (size[a2]-1) / + me->GetInternalSkipFactor())+1)*me->GetInternalSkipFactor(); + + // Offset the slices so that if we take just one it is in the middle + kstart += (size[a2]-1-kend+me->GetInternalSkipFactor())/2; + kend += (size[a2]-1-kend+me->GetInternalSkipFactor())/2; + + kinc = me->GetInternalSkipFactor(); + } + else + { + kstart = (int)((size[a2]-1) / + me->GetInternalSkipFactor()) * me->GetInternalSkipFactor(); + kend = -me->GetInternalSkipFactor(); + + // Offset the slices so that if we take just one it is in the middle + kend += (size[a2]-1-kstart)/2; + kstart += (size[a2]-1-kstart)/2; + + kinc = -me->GetInternalSkipFactor(); + } + + // Fill in the texture coordinates and most of the vertex information in advance + float offset[2]; + offset[0] = 0.5 / (float)textureSize[0]; + offset[1] = 0.5 / (float)textureSize[1]; + + for ( i = 0; i < numTiles; i++ ) + { + yTile = i / xTotal; + xTile = i % xTotal; + + t[i*8 + 0] = (float)((size[a0]*(xTile )) )/(float)textureSize[0] + offset[0]; + t[i*8 + 1] = (float)((size[a1]*(yTile )) )/(float)textureSize[1] + offset[1]; + t[i*8 + 2] = (float)((size[a0]*(xTile )) )/(float)textureSize[0] + offset[0]; + t[i*8 + 3] = (float)((size[a1]*(yTile+1)) )/(float)textureSize[1] - offset[1]; + t[i*8 + 4] = (float)((size[a0]*(xTile+1)) )/(float)textureSize[0] - offset[0]; + t[i*8 + 5] = (float)((size[a1]*(yTile+1)) )/(float)textureSize[1] - offset[1]; + t[i*8 + 6] = (float)((size[a0]*(xTile+1)) )/(float)textureSize[0] - offset[0]; + t[i*8 + 7] = (float)((size[a1]*(yTile )) )/(float)textureSize[1] + offset[1]; + + v[i*12 + a0] = origin[a0]; + v[i*12 + a1] = origin[a1]; + + v[i*12 + 3+a0] = origin[a0]; + v[i*12 + 3+a1] = spacing[a1] * (float)(size[a1]-1) + origin[a1]; + + v[i*12 + 6+a0] = spacing[a0] * (float)(size[a0]-1) + origin[a0]; + v[i*12 + 6+a1] = spacing[a1] * (float)(size[a1]-1) + origin[a1]; + + v[i*12 + 9+a0] = spacing[a0] * (float)(size[a0]-1) + origin[a0]; + v[i*12 + 9+a1] = origin[a1]; + } + + cropping = me->GetCropping(); + croppingFlags = me->GetCroppingRegionFlags(); + croppingBounds = me->GetVoxelCroppingRegionPlanes(); + + if ( !cropping ) + { + clipLow = 0; + clipHigh = size[a0]; + flag[0] = 1; + flag[1] = 1; + flag[2] = 1; + } + + shade = me->GetShade(); + if ( shade ) + { + encodedNormals = me->GetEncodedNormals(); + + redDiffuseShadingTable = me->GetRedDiffuseShadingTable(); + greenDiffuseShadingTable = me->GetGreenDiffuseShadingTable(); + blueDiffuseShadingTable = me->GetBlueDiffuseShadingTable(); + + redSpecularShadingTable = me->GetRedSpecularShadingTable(); + greenSpecularShadingTable = me->GetGreenSpecularShadingTable(); + blueSpecularShadingTable = me->GetBlueSpecularShadingTable(); + } + + gradientMagnitudes = me->GetGradientMagnitudes(); + gradientOpacityArray = me->GetGradientOpacityArray(); + + tile = 0; + for ( k = kstart; k != kend; k+=kinc ) + { + yTile = tile / xTotal; + xTile = tile % xTotal; + + for ( j = 0; j < size[a1]; j++ ) + { + i = 0; + + tptr = texture + textureOffset + + 4 * ( yTile*size[a1]*textureSize[0]+ + j*textureSize[0] + + xTile*size[a0] ); + + loc = (*zAxis)*size[0]*size[1] + (*yAxis)*size[0] + (*xAxis); + dptr = data_ptr + loc; + + // Given a Y and Z value, what are the cropping bounds + // on X. + if ( cropping ) + { + switch ( axis ) + { + case 0: + clipLow = (int) croppingBounds[2]; + clipHigh = (int) croppingBounds[3]; + tmpFlag = (*xAxis<croppingBounds[0])?(0):(1+(*xAxis>=croppingBounds[1])); + tmpFlag+= 9*((*zAxis<croppingBounds[4])?(0):(1+(*zAxis>=croppingBounds[5]))); + flag[0] = croppingFlags&(1<<(tmpFlag)); + flag[1] = croppingFlags&(1<<(tmpFlag+3)); + flag[2] = croppingFlags&(1<<(tmpFlag+6)); + break; + case 1: + clipLow = (int)croppingBounds[0]; + clipHigh = (int)croppingBounds[1]; + tmpFlag = 3*((*yAxis<croppingBounds[2])?(0):(1+(*yAxis>=croppingBounds[3]))); + tmpFlag+= 9*((*zAxis<croppingBounds[4])?(0):(1+(*zAxis>=croppingBounds[5]))); + flag[0] = croppingFlags&(1<<(tmpFlag)); + flag[1] = croppingFlags&(1<<(tmpFlag+1)); + flag[2] = croppingFlags&(1<<(tmpFlag+2)); + break; + case 2: + clipLow = (int)croppingBounds[0]; + clipHigh = (int)croppingBounds[1]; + tmpFlag = 3*((*yAxis<croppingBounds[2])?(0):(1+(*yAxis>=croppingBounds[3]))); + tmpFlag+= 9*((*zAxis<croppingBounds[4])?(0):(1+(*zAxis>=croppingBounds[5]))); + flag[0] = croppingFlags&(1<<(tmpFlag)); + flag[1] = croppingFlags&(1<<(tmpFlag+1)); + flag[2] = croppingFlags&(1<<(tmpFlag+2)); + break; + } + } + + if ( shade ) + { + nptr = encodedNormals + loc; + + if ( gradientMagnitudes ) + { + gptr = gradientMagnitudes + loc; + } + for ( i = 0; i < size[a0]; i++ ) + { + index = 0; + index += ( i >= clipLow ); + index += ( i >= clipHigh ); + if ( flag[index] ) + { + tmpval = rgbaArray[(*dptr)*4]; + tmpval = tmpval * redDiffuseShadingTable[*nptr] + + redSpecularShadingTable[*nptr]*255.0; + if ( tmpval > 255.0 ) + { + tmpval = 255.0; + } + *(tptr++) = (unsigned char) tmpval; + + tmpval = rgbaArray[(*dptr)*4 + 1]; + tmpval = tmpval * greenDiffuseShadingTable[*nptr] + + greenSpecularShadingTable[*nptr]*255.0; + if ( tmpval > 255.0 ) + { + tmpval = 255.0; + } + *(tptr++) = (unsigned char) tmpval; + + tmpval = rgbaArray[(*dptr)*4 + 2]; + tmpval = tmpval * blueDiffuseShadingTable[*nptr] + + blueSpecularShadingTable[*nptr]*255.0; + if ( tmpval > 255.0 ) + { + tmpval = 255.0; + } + *(tptr++) = (unsigned char) tmpval; + + tmpval = rgbaArray[(*dptr)*4 + 3]; + if ( gradientMagnitudes ) + { + tmpval *= gradientOpacityArray[*gptr]; + gptr += inc; + } + *(tptr++) = (unsigned char) tmpval; + + } + else + { + memcpy( tptr, zero, 4 ); + tptr += 4; + if ( gradientMagnitudes ) + { + gptr += inc; + } + } + nptr += inc; + dptr += inc; + } + } + else + { + if ( gradientMagnitudes ) + { + gptr = gradientMagnitudes + loc; + } + + if ( cropping ) + { + for ( i = 0; i < size[a0]; i++ ) + { + index = 0; + index += ( i >= clipLow ); + index += ( i >= clipHigh ); + if ( flag[index] ) + { + memcpy( tptr, rgbaArray + (*dptr)*4, 4 ); + if ( gradientMagnitudes ) + { + *(tptr+3) = (unsigned char) + ((float)(*(tptr+3)) * gradientOpacityArray[*gptr]); + gptr += inc; + } + } + else + { + memcpy( tptr, zero, 4 ); + if ( gradientMagnitudes ) + { + gptr += inc; + } + } + tptr += 4; + dptr += inc; + } + } + else + { + if ( gradientMagnitudes ) + { + for ( i = 0; i < size[a0]; i++ ) + { + memcpy( tptr, rgbaArray + (*dptr)*4, 4 ); + *(tptr+3) = (unsigned char) + ((float)(*(tptr+3)) * gradientOpacityArray[*gptr]); + gptr += inc; + dptr += inc; + tptr += 4; + } + } + else + { + for ( i = 0; i < size[a0]; i++ ) + { + memcpy( tptr, rgbaArray + (*dptr)*4, 4 ); + tptr += 4; + dptr += inc; + } + } + } + } + } + + if ( renWin->CheckAbortStatus() ) + { + break; + } + + v[12*tile + a2] = + v[12*tile + 3+a2] = + v[12*tile + 6+a2] = + v[12*tile + 9+a2] = spacing[a2] * (float)k + origin[a2]; + + tile++; + + if ( tile == numTiles || (k+kinc == kend) ) + { + if ( saveTextures ) + { + textureOffset += 4*axisTextureSize[a2*3] * axisTextureSize[a2*3+1]; + } + else + { + me->RenderQuads( tile, v, t, texture, textureSize, 0); + } + tile = 0; + } + + } + + + if ( !saveTextures ) + { + delete [] texture; + } + + delete [] v; + delete [] t; + +} + +vtkCxxRevisionMacro(vtkVolumeTextureMapper2D, "$Revision: 1.2 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkVolumeTextureMapper2D); +//---------------------------------------------------------------------------- + +vtkVolumeTextureMapper2D::vtkVolumeTextureMapper2D() +{ + this->TargetTextureSize[0] = 512; + this->TargetTextureSize[1] = 512; + this->MaximumNumberOfPlanes = 0; + this->MaximumStorageSize = 0; + this->Texture = NULL; + this->TextureSize = 0; +} + +vtkVolumeTextureMapper2D::~vtkVolumeTextureMapper2D() +{ + if ( this->Texture ) + { + delete [] this->Texture; + } +} + + +vtkVolumeTextureMapper2D *vtkVolumeTextureMapper2D::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = + vtkVolumeRenderingFactory::CreateInstance("vtkVolumeTextureMapper2D"); + return (vtkVolumeTextureMapper2D*)ret; +} + +void vtkVolumeTextureMapper2D::RenderSavedTexture() +{ + int i, k; + int kstart, kend, kinc; + unsigned char *tptr; + float *v, *t; + vtkRenderWindow *renWin = this->GetRenderWindow(); + double spacing[3], origin[3]; + unsigned char *texture; + int textureSize[2]; + int xTile, yTile, xTotal, yTotal, tile, numTiles; + int textureOffset=0; + int axis=0, directionFlag=0; + int size[3]; + + int a0=0, a1=0, a2=0; + + this->GetInput()->GetDimensions( size ); + + switch ( this->MajorDirection ) + { + case VTK_PLUS_X_MAJOR_DIRECTION: + axis = 0; + directionFlag = 1; + break; + case VTK_MINUS_X_MAJOR_DIRECTION: + axis = 0; + directionFlag = 0; + break; + case VTK_PLUS_Y_MAJOR_DIRECTION: + axis = 1; + directionFlag = 1; + break; + case VTK_MINUS_Y_MAJOR_DIRECTION: + axis = 1; + directionFlag = 0; + break; + case VTK_PLUS_Z_MAJOR_DIRECTION: + axis = 2; + directionFlag = 1; + break; + case VTK_MINUS_Z_MAJOR_DIRECTION: + axis = 2; + directionFlag = 0; + break; + } + + switch ( axis ) + { + case 0: + a0 = 1; + a1 = 2; + a2 = 0; + break; + case 1: + a0 = 0; + a1 = 2; + a2 = 1; + break; + case 2: + a0 = 0; + a1 = 1; + a2 = 2; + break; + } + + textureSize[0] = this->AxisTextureSize[a2][0]; + textureSize[1] = this->AxisTextureSize[a2][1]; + + texture = this->Texture; + switch ( axis ) + { + case 0: + textureOffset = 0; + break; + case 1: + textureOffset = + 4*(this->AxisTextureSize[0][0]* + this->AxisTextureSize[0][1]* + this->AxisTextureSize[0][2]); + break; + case 2: + textureOffset = + 4*(this->AxisTextureSize[0][0]* + this->AxisTextureSize[0][1]* + this->AxisTextureSize[0][2]) + + 4*(this->AxisTextureSize[1][0]* + this->AxisTextureSize[1][1]* + this->AxisTextureSize[1][2]); + break; + } + + if ( directionFlag == 0 ) + { + textureOffset += + 4*(this->AxisTextureSize[a2][0]* + this->AxisTextureSize[a2][1]* + (this->AxisTextureSize[a2][2]-1)); + } + + // How many tiles are there in X? in Y? total? + xTotal = textureSize[0] / size[a0]; + yTotal = textureSize[1] / size[a1]; + numTiles = xTotal * yTotal; + + // Create space for the vertices and texture coordinates. You need four vertices + // with three components each for each tile, and four texture coordinates with + // three components each for each texture coordinate + v = new float [12*numTiles]; + t = new float [ 8*numTiles]; + + // We need to know the spacing and origin of the data to set up the coordinates + // correctly + this->GetDataSpacing( spacing ); + this->GetDataOrigin( origin ); + + // What is the first plane, the increment to move to the next plane, and the plane + // that is just past the end? + if ( directionFlag ) + { + kstart = 0; + kend = ((int)( (size[a2]-1) / + this->InternalSkipFactor)+1)*this->InternalSkipFactor; + + // Offset the slices so that if we take just one it is in the middle + kstart += (size[a2]-1-kend+this->InternalSkipFactor)/2; + kend += (size[a2]-1-kend+this->InternalSkipFactor)/2; + + kinc = this->InternalSkipFactor; + } + else + { + kstart = (int)((size[a2]-1) / + this->InternalSkipFactor) * this->InternalSkipFactor; + kend = -this->InternalSkipFactor; + + // Offset the slices so that if we take just one it is in the middle + kend += (size[a2]-1-kstart)/2; + kstart += (size[a2]-1-kstart)/2; + + kinc = -this->InternalSkipFactor; + } + + // Fill in the texture coordinates and most of the vertex information in advance + float offset[2]; + offset[0] = 0.5 / (float)textureSize[0]; + offset[1] = 0.5 / (float)textureSize[1]; + + int idx; + for ( idx = 0; idx < numTiles; idx++ ) + { + i = ( directionFlag == 1 )?(idx):(numTiles-idx-1); + + yTile = i / xTotal; + xTile = i % xTotal; + + t[i*8 + 0] = (float)((size[a0]*(xTile )) )/(float)textureSize[0] + offset[0]; + t[i*8 + 1] = (float)((size[a1]*(yTile )) )/(float)textureSize[1] + offset[1]; + t[i*8 + 2] = (float)((size[a0]*(xTile )) )/(float)textureSize[0] + offset[0]; + t[i*8 + 3] = (float)((size[a1]*(yTile+1)) )/(float)textureSize[1] - offset[1]; + t[i*8 + 4] = (float)((size[a0]*(xTile+1)) )/(float)textureSize[0] - offset[0]; + t[i*8 + 5] = (float)((size[a1]*(yTile+1)) )/(float)textureSize[1] - offset[1]; + t[i*8 + 6] = (float)((size[a0]*(xTile+1)) )/(float)textureSize[0] - offset[0]; + t[i*8 + 7] = (float)((size[a1]*(yTile )) )/(float)textureSize[1] + offset[1]; + + v[i*12 + a0] = origin[a0]; + v[i*12 + a1] = origin[a1]; + + v[i*12 + 3+a0] = origin[a0]; + v[i*12 + 3+a1] = spacing[a1] * (float)(size[a1]-1) + origin[a1]; + + v[i*12 + 6+a0] = spacing[a0] * (float)(size[a0]-1) + origin[a0]; + v[i*12 + 6+a1] = spacing[a1] * (float)(size[a1]-1) + origin[a1]; + + v[i*12 + 9+a0] = spacing[a0] * (float)(size[a0]-1) + origin[a0]; + v[i*12 + 9+a1] = origin[a1]; + } + + if ( directionFlag == 1 ) + { + tile = 0; + } + else + { + tile = (((kend - kstart)/kinc)-1)%numTiles; + } + + int tileCount = 0; + + for ( k = kstart; k != kend; k+=kinc ) + { + if ( renWin->CheckAbortStatus() ) + { + break; + } + + v[12*tile + a2] = + v[12*tile + 3+a2] = + v[12*tile + 6+a2] = + v[12*tile + 9+a2] = spacing[a2] * (float)k + origin[a2]; + + tileCount++; + + if ( directionFlag == 1 ) + { + tile++; + } + else + { + tile--; + } + + if ( (directionFlag == 1 && tile == numTiles ) || + (directionFlag == 0 && tile == -1) || (k+kinc == kend) ) + { + tptr = texture + textureOffset; + if ( directionFlag == 1 ) + { + textureOffset += + 4*this->AxisTextureSize[a2][0] * this->AxisTextureSize[a2][1]; + } + else + { + textureOffset -= + 4*this->AxisTextureSize[a2][0] * this->AxisTextureSize[a2][1]; + } + + this->RenderQuads( tileCount, v, t, tptr, textureSize, !directionFlag ); + tile = (directionFlag == 1)?(0):(numTiles-1); + tileCount = 0; + } + } + + delete [] v; + delete [] t; + +} + +void vtkVolumeTextureMapper2D::GenerateTexturesAndRenderQuads( vtkRenderer *ren, vtkVolume *vol ) +{ + vtkImageData *input = this->GetInput(); + int size[3]; + void *inputPointer; + int inputType; + + inputPointer = + input->GetPointData()->GetScalars()->GetVoidPointer(0); + inputType = + input->GetPointData()->GetScalars()->GetDataType(); + + input->GetDimensions( size ); + + // Do we have a texture already, and nothing has changed? If so + // just render it. + if ( this->Texture && !this->Shade && + this->GetMTime() < this->TextureMTime && + this->GetInput()->GetMTime() < this->TextureMTime && + vol->GetProperty()->GetMTime() < this->TextureMTime ) + { + this->RenderSavedTexture(); + return; + } + + // Otherwise, we need to generate textures. We can throw away any + // saved textures + if ( this->Texture ) + { + delete [] this->Texture; + this->Texture = NULL; + } + this->TextureSize = 0; + + // Will all the textures fit in the allotted storage? + this->ComputeAxisTextureSize( 0, this->AxisTextureSize[0] ); + this->ComputeAxisTextureSize( 1, this->AxisTextureSize[1] ); + this->ComputeAxisTextureSize( 2, this->AxisTextureSize[2] ); + + vtkLargeInteger neededSize; + vtkLargeInteger tmpInt; + + + neededSize = + this->AxisTextureSize[0][0]; + neededSize = neededSize * + this->AxisTextureSize[0][1] * + this->AxisTextureSize[0][2] ; + + tmpInt = + this->AxisTextureSize[1][0]; + tmpInt = tmpInt * + this->AxisTextureSize[1][1] * + this->AxisTextureSize[1][2]; + neededSize = neededSize + tmpInt; + + tmpInt = + this->AxisTextureSize[2][0]; + tmpInt = tmpInt * + this->AxisTextureSize[2][1] * + this->AxisTextureSize[2][2]; + neededSize = neededSize + tmpInt; + + neededSize *= 4; + + if ( neededSize.GetLength() > 31 ) + { + this->SaveTextures = 0; + } + else + { + this->SaveTextures = + ( neededSize.CastToLong() <= this->MaximumStorageSize && + !this->Shade ); + } + + if ( this->SaveTextures ) + { + this->Texture = new unsigned char [neededSize.CastToLong()]; + this->TextureSize = neededSize.CastToLong(); + + int savedDirection = this->MajorDirection; + + switch ( inputType ) + { + case VTK_UNSIGNED_CHAR: + this->InitializeRender( ren, vol, VTK_PLUS_X_MAJOR_DIRECTION ); + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 0, 1, this ); + + this->InitializeRender( ren, vol, VTK_PLUS_Y_MAJOR_DIRECTION ); + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 1, 1, this ); + + this->InitializeRender( ren, vol, VTK_PLUS_Z_MAJOR_DIRECTION ); + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 2, 1, this ); + break; + case VTK_UNSIGNED_SHORT: + this->InitializeRender( ren, vol, VTK_PLUS_X_MAJOR_DIRECTION ); + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 0, 1, this ); + + this->InitializeRender( ren, vol, VTK_PLUS_Y_MAJOR_DIRECTION ); + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 1, 1, this ); + + this->InitializeRender( ren, vol, VTK_PLUS_Z_MAJOR_DIRECTION ); + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 2, 1, this ); + break; + } + + this->MajorDirection = savedDirection; + if ( !ren->GetRenderWindow()->GetAbortRender() ) + { + this->RenderSavedTexture(); + this->TextureMTime.Modified(); + } + } + else + { + + switch ( inputType ) + { + case VTK_UNSIGNED_CHAR: + switch ( this->MajorDirection ) + { + case VTK_PLUS_X_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 0, 1, this ); + break; + + case VTK_MINUS_X_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 0, 0, this ); + break; + + case VTK_PLUS_Y_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 1, 1, this ); + break; + + case VTK_MINUS_Y_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 1, 0, this ); + break; + + case VTK_PLUS_Z_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 2, 1, this ); + break; + + case VTK_MINUS_Z_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned char *)inputPointer, size, 2, 0, this ); + break; + } + break; + case VTK_UNSIGNED_SHORT: + switch ( this->MajorDirection ) + { + case VTK_PLUS_X_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 0, 1, this ); + break; + + case VTK_MINUS_X_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 0, 0, this ); + break; + + case VTK_PLUS_Y_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 1, 1, this ); + break; + + case VTK_MINUS_Y_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 1, 0, this ); + break; + + case VTK_PLUS_Z_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 2, 1, this ); + break; + + case VTK_MINUS_Z_MAJOR_DIRECTION: + vtkVolumeTextureMapper2D_TraverseVolume + ( (unsigned short *)inputPointer, size, 2, 0, this ); + break; + } + break; + default: + vtkErrorMacro( + "vtkVolumeTextureMapper2D only works with unsigned short and unsigned char data.\n" << + "Input type: " << inputType << " given."); + } + } +} + +void vtkVolumeTextureMapper2D::InitializeRender( vtkRenderer *ren, + vtkVolume *vol, + int majorDirection ) +{ + if ( majorDirection >= 0) + { + this->MajorDirection = majorDirection; + } + else + { + double vpn[3]; + + // Take the vpn, convert it to volume coordinates, and find the + // major direction + vtkMatrix4x4 *volMatrix = vtkMatrix4x4::New(); + volMatrix->DeepCopy( vol->GetMatrix() ); + vtkTransform *worldToVolumeTransform = vtkTransform::New(); + worldToVolumeTransform->SetMatrix( volMatrix ); + + // Create a transform that will account for the translation of + // the scalar data. + vtkTransform *volumeTransform = vtkTransform::New(); + + volumeTransform->Identity(); + volumeTransform->Translate(this->GetInput()->GetOrigin()); + + // Now concatenate the volume's matrix with this scalar data matrix + worldToVolumeTransform->PreMultiply(); + worldToVolumeTransform->Concatenate( volumeTransform->GetMatrix() ); + worldToVolumeTransform->Inverse(); + + ren->GetActiveCamera()->GetViewPlaneNormal(vpn); + worldToVolumeTransform->TransformVector( vpn, vpn ); + + volMatrix->Delete(); + volumeTransform->Delete(); + worldToVolumeTransform->Delete(); + + if ( fabs(vpn[0]) >= fabs(vpn[1]) && fabs(vpn[0]) >= fabs(vpn[2]) ) + { + this->MajorDirection = (vpn[0]<0.0)? + (VTK_MINUS_X_MAJOR_DIRECTION):(VTK_PLUS_X_MAJOR_DIRECTION); + } + else if ( fabs(vpn[1]) >= fabs(vpn[0]) && fabs(vpn[1]) >= fabs(vpn[2]) ) + { + this->MajorDirection = (vpn[1]<0.0)? + (VTK_MINUS_Y_MAJOR_DIRECTION):(VTK_PLUS_Y_MAJOR_DIRECTION); + } + else + { + this->MajorDirection = (vpn[2]<0.0)? + (VTK_MINUS_Z_MAJOR_DIRECTION):(VTK_PLUS_Z_MAJOR_DIRECTION); + } + } + + // Determine the internal skip factor - if there is a limit on the number + // of planes we can have (the MaximumNumberOfPlanes value is greater than + // 0) then increase this skip factor until we ensure the maximum condition. + this->InternalSkipFactor = 1; + if ( this->MaximumNumberOfPlanes > 0 ) + { + int size[3]; + this->GetInput()->GetDimensions( size ); + while ( (float)size[this->MajorDirection/2] / + (float)this->InternalSkipFactor > + (float)this->MaximumNumberOfPlanes ) + { + this->InternalSkipFactor++; + } + } + // Assume that the spacing between samples is 1/2 of the maximum - this + // could be computed accurately for parallel (but isn't right now). For + // perspective, this spacing changes across the image so no one number will + // be accurate. 1/2 the maximum is (1 + sqrt(2)) / 2 = 1.2071 + + // TODO: DataSpacing should be converted to double at some point + double *dspacing; + dspacing = this->GetInput()->GetSpacing(); + this->DataSpacing[0] = (float)dspacing[0]; + this->DataSpacing[1] = (float)dspacing[1]; + this->DataSpacing[2] = (float)dspacing[2]; + this->SampleDistance = + this->DataSpacing[this->MajorDirection/2]*this->InternalSkipFactor*1.2071; + this->vtkVolumeTextureMapper::InitializeRender( ren, vol ); +} + +void vtkVolumeTextureMapper2D::ComputeAxisTextureSize( int axis, int *textureSize ) +{ + int targetSize[2]; + int a0=0, a1=0, a2=0; + + switch ( axis ) + { + case 0: + a0 = 1; + a1 = 2; + a2 = 0; + break; + case 1: + a0 = 0; + a1 = 2; + a2 = 1; + break; + case 2: + a0 = 0; + a1 = 1; + a2 = 2; + break; + } + + + // How big should the texture be? + // Start with the target size + targetSize[0] = this->TargetTextureSize[0]; + targetSize[1] = this->TargetTextureSize[1]; + + int size[3]; + this->GetInput()->GetDimensions( size ); + + // Increase the x dimension of the texture if the x dimension of the data + // is bigger than it (because these are x by y textures) + if ( size[a0] > targetSize[0] ) + { + targetSize[0] = size[a0]; + } + + // Increase the y dimension of the texture if the y dimension of the data + // is bigger than it (because these are x by y textures) + if ( size[a1] > targetSize[1] ) + { + targetSize[1] = size[a1]; + } + + // Make sure the x dimension of the texture is a power of 2 + textureSize[0] = 32; + while( textureSize[0] < targetSize[0] ) + { + textureSize[0] *= 2; + } + + // Make sure the y dimension of the texture is a power of 2 + textureSize[1] = 32; + while( textureSize[1] < targetSize[1] ) + { + textureSize[1] *= 2; + } + + // Our texture might be too big - shrink it carefully making + // sure that it is still big enough in the right dimensions to + // handle oddly shaped volumes + int volSize = size[0]*size[1]*size[2]; + int done = (volSize > textureSize[0]*textureSize[1]); + int minSize[2]; + + // What is the minumum size the texture could be in X (along the X + // axis of the volume)? + minSize[0] = 32; + while ( minSize[0] < size[a0] ) + { + minSize[0] *= 2; + } + + // What is the minumum size the texture could be in Y (along the Y + // axis of the volume)? + minSize[1] = 32; + while ( minSize[1] < size[a1] ) + { + minSize[1] *= 2; + } + + // Keep reducing the texture size until it is just big enough + while (!done) + { + // Set done to 1. Reset to 0 if we make any changes. + done = 1; + + // If the texture is bigger in some dimension that it needs to be + // and chopping that dimension in half would still fit the whole + // volume, then chop it in half. + if ( textureSize[0] > minSize[0] && + ( ((textureSize[0]/2) / size[a0]) * + (textureSize[1] / size[a1]) >= size[a2] ) ) + { + textureSize[0] /= 2; + done = 0; + } + if ( textureSize[1] > minSize[1] && + ( (textureSize[0] / size[a0]) * + ((textureSize[1]/2) / size[a1]) >= size[a2] ) ) + { + textureSize[1] /= 2; + done = 0; + } + } + + // This is how many texture planes would be necessary if one slice fit on a + // texture (taking into account the user defined maximum) + textureSize[2] = + (size[a2]<this->MaximumNumberOfPlanes||this->MaximumNumberOfPlanes<=0) ? + (size[a2]) : (this->MaximumNumberOfPlanes); + + // How many slices can fit on a texture in X and Y? + int xTotal = textureSize[0] / size[a0]; + int yTotal = textureSize[1] / size[a1]; + + // The number of textures we need is the number computed above divided by + // how many fit on a texture (plus one if they don't fit evenly) + textureSize[2] = (textureSize[2] / (xTotal*yTotal)) + + ((textureSize[2] % (xTotal*yTotal))!=0); +} + + +// Print the vtkVolumeTextureMapper2D +void vtkVolumeTextureMapper2D::PrintSelf(ostream& os, vtkIndent indent) +{ + os << indent << "Target Texture Size: " + << this->TargetTextureSize[0] << ", " + << this->TargetTextureSize[1] << endl; + + os << indent << "Maximum Number Of Planes: "; + if ( this->MaximumNumberOfPlanes > 0 ) + { + os << this->MaximumNumberOfPlanes << endl; + } + else + { + os << "<unlimited>" << endl; + } + + os << indent << "Maximum Storage Size: " + << this->MaximumStorageSize << endl; + + this->Superclass::PrintSelf(os,indent); +} + + diff --git a/VolumeRendering/vtkVolumeTextureMapper2D.h b/VolumeRendering/vtkVolumeTextureMapper2D.h new file mode 100644 index 0000000..1df5b79 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper2D.h @@ -0,0 +1,127 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeTextureMapper2D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeTextureMapper2D - Abstract class for a volume mapper + +// .SECTION Description +// vtkVolumeTextureMapper2D renders a volume using 2D texture mapping. + + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkVolumeTextureMapper2D_h +#define __vtkVolumeTextureMapper2D_h + +#include "vtkVolumeTextureMapper.h" + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeTextureMapper2D : public vtkVolumeTextureMapper +{ +public: + vtkTypeRevisionMacro(vtkVolumeTextureMapper2D,vtkVolumeTextureMapper); + void PrintSelf( ostream& os, vtkIndent indent ); + + static vtkVolumeTextureMapper2D *New(); + + // Description: + // Target size in pixels of each size of the texture for downloading. Default is + // 512x512 - so a 512x512 texture will be tiled with as many slices of the volume + // as possible, then all the quads will be rendered. This can be set to optimize + // for a particular architecture. This must be set with numbers that are a power + // of two. + vtkSetVector2Macro( TargetTextureSize, int ); + vtkGetVector2Macro( TargetTextureSize, int ); + + // Description: + // This is the maximum number of planes that will be created for texture mapping + // the volume. If the volume has more voxels than this along the viewing direction, + // then planes of the volume will be skipped to ensure that this maximum is not + // violated. A skip factor is used, and is incremented until the maximum condition + // is satisfied. + vtkSetMacro( MaximumNumberOfPlanes, int ); + vtkGetMacro( MaximumNumberOfPlanes, int ); + + // Description: + // This is the maximum size of saved textures in bytes. If this size is large + // enough to hold the RGBA textures for all three directions (XxYxZx3x4 is + // the approximate value - it is actually a bit larger due to wasted space in + // the textures) then the textures will be saved. + vtkSetMacro( MaximumStorageSize, int ); + vtkGetMacro( MaximumStorageSize, int ); + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *, vtkVolume *) {}; + + virtual void RenderQuads( int vtkNotUsed(count), + float *vtkNotUsed(v), float *vtkNotUsed(t), + unsigned char *vtkNotUsed(texture), + int vtkNotUsed(size)[2], + int vtkNotUsed(reverseFlag)) {}; + + // Description: + // Made public only for access from the templated method. Not a vtkGetMacro + // to avoid the PrintSelf defect. + int GetInternalSkipFactor() {return this->InternalSkipFactor;}; + + int *GetAxisTextureSize() {return &(this->AxisTextureSize[0][0]);}; + + int GetSaveTextures() {return this->SaveTextures;}; + + unsigned char *GetTexture() {return this->Texture;}; + +//ETX + + +protected: + vtkVolumeTextureMapper2D(); + ~vtkVolumeTextureMapper2D(); + + void InitializeRender( vtkRenderer *ren, vtkVolume *vol ) + {this->InitializeRender( ren, vol, -1 );} + + void InitializeRender( vtkRenderer *ren, vtkVolume *vol, int majorDirection ); + + void GenerateTexturesAndRenderQuads( vtkRenderer *ren, vtkVolume *vol ); + + int MajorDirection; + int TargetTextureSize[2]; + + int MaximumNumberOfPlanes; + int InternalSkipFactor; + int MaximumStorageSize; + + unsigned char *Texture; + int TextureSize; + int SaveTextures; + vtkTimeStamp TextureMTime; + + int AxisTextureSize[3][3]; + void ComputeAxisTextureSize( int axis, int *size ); + + void RenderSavedTexture(); + +private: + vtkVolumeTextureMapper2D(const vtkVolumeTextureMapper2D&); // Not implemented. + void operator=(const vtkVolumeTextureMapper2D&); // Not implemented. +}; + + +#endif + + diff --git a/VolumeRendering/vtkVolumeTextureMapper3D.cxx b/VolumeRendering/vtkVolumeTextureMapper3D.cxx new file mode 100644 index 0000000..9ac40fe --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D.cxx @@ -0,0 +1,1486 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeTextureMapper3D.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkVolumeTextureMapper3D.h" +#include "vtkVolumeRenderingFactory.h" + +#include "vtkRenderer.h" +#include "vtkVolume.h" +#include "vtkCamera.h" +#include "vtkMath.h" +#include "vtkPointData.h" +#include "vtkImageData.h" +#include "vtkColorTransferFunction.h" +#include "vtkPiecewiseFunction.h" +#include "vtkVolumeProperty.h" +#include "vtkMatrix4x4.h" + +vtkCxxRevisionMacro(vtkVolumeTextureMapper3D, "$Revision: 1.6 $"); + +//---------------------------------------------------------------------------- +// Needed when we don't use the vtkStandardNewMacro. +vtkInstantiatorNewMacro(vtkVolumeTextureMapper3D); +//---------------------------------------------------------------------------- + +// This method moves the scalars from the input volume into volume1 (and +// possibly volume2) which are the 3D texture maps used for rendering. +// +// In the case where our volume is a power of two, the copy is done +// directly. If we need to resample, then trilinear interpolation is used. +// +// A shift/scale is applied to the input scalar value to produce an 8 bit +// value for the texture volume. +// +// When the input data is one component, the scalar value is placed in the +// second component of the two component volume1. The first component is +// filled in later with the gradient magnitude. +// +// When the input data is two component non-independent, the first component +// of the input data is placed in the first component of volume1, and the +// second component of the input data is placed in the third component of +// volume1. Volume1 has three components - the second is filled in later with +// the gradient magnitude. +// +// When the input data is four component non-independent, the first three +// components of the input data are placed in volume1 (which has three +// components), and the fourth component is placed in the second component +// of volume2. The first component of volume2 is later filled in with the +// gradient magnitude. + +template <class T> +void vtkVolumeTextureMapper3DComputeScalars( T *dataPtr, + vtkVolumeTextureMapper3D *me, + float offset, float scale, + unsigned char *volume1, + unsigned char *volume2) +{ + T *inPtr; + unsigned char *outPtr, *outPtr2; + int i, j, k; + int idx; + + int inputDimensions[3]; + double inputSpacing[3]; + me->GetInput()->GetDimensions( inputDimensions ); + me->GetInput()->GetSpacing( inputSpacing ); + + int outputDimensions[3]; + float outputSpacing[3]; + me->GetVolumeDimensions( outputDimensions ); + me->GetVolumeSpacing( outputSpacing ); + + int components = me->GetInput()->GetNumberOfScalarComponents(); + + double wx, wy, wz; + double fx, fy, fz; + int x, y, z; + + double sampleRate[3]; + sampleRate[0] = (double)outputSpacing[0] / (double)inputSpacing[0]; + sampleRate[1] = (double)outputSpacing[1] / (double)inputSpacing[1]; + sampleRate[2] = (double)outputSpacing[2] / (double)inputSpacing[2]; + + // This is the case where no interpolation is needed + if ( inputDimensions[0] == outputDimensions[0] && + inputDimensions[1] == outputDimensions[1] && + inputDimensions[2] == outputDimensions[2] ) + { + int size = outputDimensions[0] * outputDimensions[1] * outputDimensions[2]; + + inPtr = dataPtr; + if ( components == 1 ) + { + outPtr = volume1; + if ( scale == 1.0 ) + { + for ( i = 0; i < size; i++ ) + { + idx = static_cast<int>(*(inPtr++) + offset); + *(outPtr++) = 0; + *(outPtr++) = idx; + } + } + else + { + for ( i = 0; i < size; i++ ) + { + idx = static_cast<int>((*(inPtr++) + offset) * scale); + *(outPtr++) = 0; + *(outPtr++) = idx; + } + } + } + else if ( components == 2 ) + { + outPtr = volume1; + if ( scale == 1.0 ) + { + for ( i = 0; i < size; i++ ) + { + idx = static_cast<int>(*(inPtr++) + offset); + *(outPtr++) = idx; + + *(outPtr++) = 0; + + idx = static_cast<int>(*(inPtr++) + offset); + *(outPtr++) = idx; + } + } + else + { + for ( i = 0; i < size; i++ ) + { + idx = static_cast<int>((*(inPtr++) + offset) * scale); + *(outPtr++) = idx; + + *(outPtr++) = 0; + + idx = static_cast<int>((*(inPtr++) + offset) * scale); + *(outPtr++) = idx; + } + } + } + else if ( components == 4 ) + { + outPtr = volume1; + outPtr2 = volume2; + if ( scale == 1.0 ) + { + for ( i = 0; i < size; i++ ) + { + idx = static_cast<int>(*(inPtr++) + offset); + *(outPtr++) = idx; + idx = static_cast<int>(*(inPtr++) + offset); + *(outPtr++) = idx; + idx = static_cast<int>(*(inPtr++) + offset); + *(outPtr++) = idx; + + *(outPtr2++) = 0; + idx = static_cast<int>(*(inPtr++) + offset); + *(outPtr2++) = idx; + } + } + else + { + for ( i = 0; i < size; i++ ) + { + idx = static_cast<int>((*(inPtr++) + offset) * scale); + *(outPtr++) = idx; + idx = static_cast<int>((*(inPtr++) + offset) * scale); + *(outPtr++) = idx; + idx = static_cast<int>((*(inPtr++) + offset) * scale); + *(outPtr++) = idx; + + *(outPtr2++) = 0; + idx = static_cast<int>((*(inPtr++) + offset) * scale); + *(outPtr2++) = idx; + } + } + } + } + // The sizes are different and interpolation is required + else + { + outPtr = volume1; + outPtr2 = volume2; + + for ( k = 0; k < outputDimensions[2]; k++ ) + { + fz = k * sampleRate[2]; + fz = (fz >= inputDimensions[2]-1)?(inputDimensions[2]-1.001):(fz); + z = vtkMath::Floor( fz ); + wz = fz - z; + for ( j = 0; j < outputDimensions[1]; j++ ) + { + fy = j * sampleRate[1]; + fy = (fy >= inputDimensions[1]-1)?(inputDimensions[1]-1.001):(fy); + y = vtkMath::Floor( fy ); + wy = fy - y; + for ( i = 0; i < outputDimensions[0]; i++ ) + { + fx = i * sampleRate[0]; + fx = (fx >= inputDimensions[0]-1)?(inputDimensions[0]-1.001):(fx); + x = vtkMath::Floor( fx ); + wx = fx - x; + + inPtr = + dataPtr + components * ( z*inputDimensions[0]*inputDimensions[1] + + y*inputDimensions[0] + + x ); + + if ( components == 1 ) + { + float A, B, C, D, E, F, G, H; + A = static_cast<float>(*(inPtr)); + B = static_cast<float>(*(inPtr+1)); + C = static_cast<float>(*(inPtr+inputDimensions[0])); + D = static_cast<float>(*(inPtr+inputDimensions[0]+1)); + E = static_cast<float>(*(inPtr+inputDimensions[0]*inputDimensions[1])); + F = static_cast<float>(*(inPtr+inputDimensions[0]*inputDimensions[1]+1)); + G = static_cast<float>(*(inPtr+inputDimensions[0]*inputDimensions[1]+inputDimensions[0])); + H = static_cast<float>(*(inPtr+inputDimensions[0]*inputDimensions[1]+inputDimensions[0]+1)); + + float val = + (1.0-wx)*(1.0-wy)*(1.0-wz)*A + + ( wx)*(1.0-wy)*(1.0-wz)*B + + (1.0-wx)*( wy)*(1.0-wz)*C + + ( wx)*( wy)*(1.0-wz)*D + + (1.0-wx)*(1.0-wy)*( wz)*E + + ( wx)*(1.0-wy)*( wz)*F + + (1.0-wx)*( wy)*( wz)*G + + ( wx)*( wy)*( wz)*H; + + idx = static_cast<int>((val + offset)*scale); + *(outPtr++) = 0; + *(outPtr++) = idx; + } + else if ( components == 2 ) + { + float A1, B1, C1, D1, E1, F1, G1, H1; + float A2, B2, C2, D2, E2, F2, G2, H2; + A1 = static_cast<float>(*(inPtr)); + A2 = static_cast<float>(*(inPtr+1)); + B1 = static_cast<float>(*(inPtr+2)); + B2 = static_cast<float>(*(inPtr+3)); + C1 = static_cast<float>(*(inPtr+2*inputDimensions[0])); + C2 = static_cast<float>(*(inPtr+2*inputDimensions[0]+1)); + D1 = static_cast<float>(*(inPtr+2*inputDimensions[0]+2)); + D2 = static_cast<float>(*(inPtr+2*inputDimensions[0]+3)); + E1 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1])); + E2 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1]+1)); + F1 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1]+2)); + F2 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1]+3)); + G1 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1]+2*inputDimensions[0])); + G2 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1]+2*inputDimensions[0]+1)); + H1 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1]+2*inputDimensions[0]+2)); + H2 = static_cast<float>(*(inPtr+2*inputDimensions[0]*inputDimensions[1]+2*inputDimensions[0]+3)); + + float val1 = + (1.0-wx)*(1.0-wy)*(1.0-wz)*A1 + + ( wx)*(1.0-wy)*(1.0-wz)*B1 + + (1.0-wx)*( wy)*(1.0-wz)*C1 + + ( wx)*( wy)*(1.0-wz)*D1 + + (1.0-wx)*(1.0-wy)*( wz)*E1 + + ( wx)*(1.0-wy)*( wz)*F1 + + (1.0-wx)*( wy)*( wz)*G1 + + ( wx)*( wy)*( wz)*H1; + + + float val2 = + (1.0-wx)*(1.0-wy)*(1.0-wz)*A2 + + ( wx)*(1.0-wy)*(1.0-wz)*B2 + + (1.0-wx)*( wy)*(1.0-wz)*C2 + + ( wx)*( wy)*(1.0-wz)*D2 + + (1.0-wx)*(1.0-wy)*( wz)*E2 + + ( wx)*(1.0-wy)*( wz)*F2 + + (1.0-wx)*( wy)*( wz)*G2 + + ( wx)*( wy)*( wz)*H2; + + idx = static_cast<int>((val1 + offset) * scale); + *(outPtr++) = idx; + + *(outPtr++) = 0; + + idx = static_cast<int>((val2 + offset) * scale); + *(outPtr++) = idx; + } + else + { + float Ar, Br, Cr, Dr, Er, Fr, Gr, Hr; + float Ag, Bg, Cg, Dg, Eg, Fg, Gg, Hg; + float Ab, Bb, Cb, Db, Eb, Fb, Gb, Hb; + float Aa, Ba, Ca, Da, Ea, Fa, Ga, Ha; + Ar = static_cast<float>(*(inPtr)); + Ag = static_cast<float>(*(inPtr+1)); + Ab = static_cast<float>(*(inPtr+2)); + Aa = static_cast<float>(*(inPtr+3)); + Br = static_cast<float>(*(inPtr+4)); + Bg = static_cast<float>(*(inPtr+5)); + Bb = static_cast<float>(*(inPtr+6)); + Ba = static_cast<float>(*(inPtr+7)); + Cr = static_cast<float>(*(inPtr+4*inputDimensions[0])); + Cg = static_cast<float>(*(inPtr+4*inputDimensions[0]+1)); + Cb = static_cast<float>(*(inPtr+4*inputDimensions[0]+2)); + Ca = static_cast<float>(*(inPtr+4*inputDimensions[0]+3)); + Dr = static_cast<float>(*(inPtr+4*inputDimensions[0]+4)); + Dg = static_cast<float>(*(inPtr+4*inputDimensions[0]+5)); + Db = static_cast<float>(*(inPtr+4*inputDimensions[0]+6)); + Da = static_cast<float>(*(inPtr+4*inputDimensions[0]+7)); + Er = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1])); + Eg = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+1)); + Eb = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+2)); + Ea = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+3)); + Fr = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4)); + Fg = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+5)); + Fb = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+6)); + Fa = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+7)); + Gr = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0])); + Gg = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0]+1)); + Gb = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0]+2)); + Ga = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0]+3)); + Hr = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0]+4)); + Hg = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0]+5)); + Hb = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0]+6)); + Ha = static_cast<float>(*(inPtr+4*inputDimensions[0]*inputDimensions[1]+4*inputDimensions[0]+7)); + + float valr = + (1.0-wx)*(1.0-wy)*(1.0-wz)*Ar + + ( wx)*(1.0-wy)*(1.0-wz)*Br + + (1.0-wx)*( wy)*(1.0-wz)*Cr + + ( wx)*( wy)*(1.0-wz)*Dr + + (1.0-wx)*(1.0-wy)*( wz)*Er + + ( wx)*(1.0-wy)*( wz)*Fr + + (1.0-wx)*( wy)*( wz)*Gr + + ( wx)*( wy)*( wz)*Hr; + + float valg = + (1.0-wx)*(1.0-wy)*(1.0-wz)*Ag + + ( wx)*(1.0-wy)*(1.0-wz)*Bg + + (1.0-wx)*( wy)*(1.0-wz)*Cg + + ( wx)*( wy)*(1.0-wz)*Dg + + (1.0-wx)*(1.0-wy)*( wz)*Eg + + ( wx)*(1.0-wy)*( wz)*Fg + + (1.0-wx)*( wy)*( wz)*Gg + + ( wx)*( wy)*( wz)*Hg; + + float valb = + (1.0-wx)*(1.0-wy)*(1.0-wz)*Ab + + ( wx)*(1.0-wy)*(1.0-wz)*Bb + + (1.0-wx)*( wy)*(1.0-wz)*Cb + + ( wx)*( wy)*(1.0-wz)*Db + + (1.0-wx)*(1.0-wy)*( wz)*Eb + + ( wx)*(1.0-wy)*( wz)*Fb + + (1.0-wx)*( wy)*( wz)*Gb + + ( wx)*( wy)*( wz)*Hb; + + float vala = + (1.0-wx)*(1.0-wy)*(1.0-wz)*Aa + + ( wx)*(1.0-wy)*(1.0-wz)*Ba + + (1.0-wx)*( wy)*(1.0-wz)*Ca + + ( wx)*( wy)*(1.0-wz)*Da + + (1.0-wx)*(1.0-wy)*( wz)*Ea + + ( wx)*(1.0-wy)*( wz)*Fa + + (1.0-wx)*( wy)*( wz)*Ga + + ( wx)*( wy)*( wz)*Ha; + + idx = static_cast<int>((valr + offset) * scale); + *(outPtr++) = idx; + idx = static_cast<int>((valg + offset) * scale); + *(outPtr++) = idx; + idx = static_cast<int>((valb + offset) * scale); + *(outPtr++) = idx; + + *(outPtr2++) = 0; + idx = static_cast<int>((vala + offset) * scale); + *(outPtr2++) = idx; + } + } + } + } + } +} + + +template <class T> +void vtkVolumeTextureMapper3DComputeGradients( T *dataPtr, + vtkVolumeTextureMapper3D *me, + double scalarRange[2], + unsigned char *volume1, + unsigned char *volume2, + unsigned char *volume3) +{ + int x, y, z; + int offset, outputOffset; + int x_start, x_limit; + int y_start, y_limit; + int z_start, z_limit; + T *dptr; + float n[3], t; + float gvalue; + float zeroNormalThreshold; + int xlow, xhigh; + double aspect[3]; + unsigned char *outPtr1, *outPtr2; + unsigned char *normals, *gradmags; + int gradmagIncrement; + int gradmagOffset; + double floc[3]; + int loc[3]; + +// me->InvokeEvent( vtkEvent::VolumeMapperComputeGradientsStartEvent, NULL ); + + float outputSpacing[3]; + me->GetVolumeSpacing( outputSpacing ); + + double spacing[3]; + me->GetInput()->GetSpacing( spacing ); + + double sampleRate[3]; + sampleRate[0] = (double)outputSpacing[0] / (double)spacing[0]; + sampleRate[1] = (double)outputSpacing[1] / (double)spacing[1]; + sampleRate[2] = (double)outputSpacing[2] / (double)spacing[2]; + + int components = me->GetInput()->GetNumberOfScalarComponents(); + + int dim[3]; + me->GetInput()->GetDimensions(dim); + + int outputDim[3]; + me->GetVolumeDimensions( outputDim ); + + double avgSpacing = ((double)spacing[0] + + (double)spacing[1] + + (double)spacing[2]) / 3.0; + + // adjust the aspect + aspect[0] = (double)spacing[0] * 2.0 / avgSpacing; + aspect[1] = (double)spacing[1] * 2.0 / avgSpacing; + aspect[2] = (double)spacing[2] * 2.0 / avgSpacing; + + float scale; + scale = 255.0 / (0.25*(scalarRange[1] - scalarRange[0])); + + // Get the length at or below which normals are considered to + // be "zero" + zeroNormalThreshold =.001 * (scalarRange[1] - scalarRange[0]); + + int thread_id = 0; + int thread_count = 1; + + x_start = 0; + x_limit = outputDim[0]; + y_start = 0; + y_limit = outputDim[1]; + z_start = (int)(( (float)thread_id / (float)thread_count ) * + outputDim[2] ); + z_limit = (int)(( (float)(thread_id + 1) / (float)thread_count ) * + outputDim[2] ); + + // Do final error checking on limits - make sure they are all within bounds + // of the scalar input + + x_start = (x_start<0)?(0):(x_start); + y_start = (y_start<0)?(0):(y_start); + z_start = (z_start<0)?(0):(z_start); + + x_limit = (x_limit>dim[0])?(outputDim[0]):(x_limit); + y_limit = (y_limit>dim[1])?(outputDim[1]):(y_limit); + z_limit = (z_limit>dim[2])?(outputDim[2]):(z_limit); + + + if ( components == 1 || components == 2 ) + { + normals = volume2; + gradmags = volume1; + gradmagIncrement = components+1; + gradmagOffset = components-1; + } + else + { + normals = volume3; + gradmags = volume2; + gradmagIncrement = 2; + gradmagOffset = 0; + } + + double wx, wy, wz; + + // Loop through all the data and compute the encoded normal and + // gradient magnitude for each scalar location + for ( z = z_start; z < z_limit; z++ ) + { + floc[2] = z*sampleRate[2]; + floc[2] = (floc[2]>=(dim[2]-1))?(dim[2]-1.001):(floc[2]); + loc[2] = vtkMath::Floor(floc[2]); + wz = floc[2] - loc[2]; + + for ( y = y_start; y < y_limit; y++ ) + { + floc[1] = y*sampleRate[1]; + floc[1] = (floc[1]>=(dim[1]-1))?(dim[1]-1.001):(floc[1]); + loc[1] = vtkMath::Floor(floc[1]); + wy = floc[1] - loc[1]; + + xlow = x_start; + xhigh = x_limit; + outputOffset = z * outputDim[0] * outputDim[1] + y * outputDim[0] + xlow; + + // Set some pointers + outPtr1 = gradmags + gradmagIncrement*outputOffset; + outPtr2 = normals + 3*outputOffset; + + for ( x = xlow; x < xhigh; x++ ) + { + floc[0] = x*sampleRate[0]; + floc[0] = (floc[0]>=(dim[0]-1))?(dim[0]-1.001):(floc[0]); + loc[0] = vtkMath::Floor(floc[0]); + wx = floc[0] - loc[0]; + + offset = loc[2] * dim[0] * dim[1] + loc[1] * dim[0] + loc[0]; + + dptr = dataPtr + components*offset + components - 1; + + // Use a central difference method if possible, + // otherwise use a forward or backward difference if + // we are on the edge + int sampleOffset[6]; + sampleOffset[0] = (loc[0]<1) ?(0):(-components); + sampleOffset[1] = (loc[0]>=dim[0]-2)?(0):( components); + sampleOffset[2] = (loc[1]<1) ?(0):(-components*dim[0]); + sampleOffset[3] = (loc[1]>=dim[1]-2)?(0):( components*dim[0]); + sampleOffset[4] = (loc[2]<1) ?(0):(-components*dim[0]*dim[1]); + sampleOffset[5] = (loc[2]>=dim[2]-2)?(0):( components*dim[0]*dim[1]); + + float sample[6]; + for ( int i = 0; i < 6; i++ ) + { + float A, B, C, D, E, F, G, H; + T *samplePtr = dptr + sampleOffset[i]; + + A = static_cast<float>(*(samplePtr)); + B = static_cast<float>(*(samplePtr+components)); + C = static_cast<float>(*(samplePtr+components*dim[0])); + D = static_cast<float>(*(samplePtr+components*dim[0]+components)); + E = static_cast<float>(*(samplePtr+components*dim[0]*dim[1])); + F = static_cast<float>(*(samplePtr+components*dim[0]*dim[1]+components)); + G = static_cast<float>(*(samplePtr+components*dim[0]*dim[1]+components*dim[0])); + H = static_cast<float>(*(samplePtr+components*dim[0]*dim[1]+components*dim[0]+components)); + + sample[i] = + (1.0-wx)*(1.0-wy)*(1.0-wz)*A + + ( wx)*(1.0-wy)*(1.0-wz)*B + + (1.0-wx)*( wy)*(1.0-wz)*C + + ( wx)*( wy)*(1.0-wz)*D + + (1.0-wx)*(1.0-wy)*( wz)*E + + ( wx)*(1.0-wy)*( wz)*F + + (1.0-wx)*( wy)*( wz)*G + + ( wx)*( wy)*( wz)*H; + } + + n[0] = ((sampleOffset[0]==0 || sampleOffset[1]==0)?(2.0):(1.0))*(sample[0] -sample[1]); + n[1] = ((sampleOffset[2]==0 || sampleOffset[3]==0)?(2.0):(1.0))*(sample[2] -sample[3]); + n[2] = ((sampleOffset[4]==0 || sampleOffset[5]==0)?(2.0):(1.0))*(sample[4] -sample[5]); + + // Take care of the aspect ratio of the data + // Scaling in the vtkVolume is isotropic, so this is the + // only place we have to worry about non-isotropic scaling. + n[0] /= aspect[0]; + n[1] /= aspect[1]; + n[2] /= aspect[2]; + + // Compute the gradient magnitude + t = sqrt( (double)( n[0]*n[0] + + n[1]*n[1] + + n[2]*n[2] ) ); + + // Encode this into an 4 bit value + gvalue = t * scale; + + gvalue = (gvalue<0.0)?(0.0):(gvalue); + gvalue = (gvalue>255.0)?(255.0):(gvalue); + + + *(outPtr1+gradmagOffset) = static_cast<unsigned char>(gvalue + 0.5); + + // Normalize the gradient direction + if ( t > zeroNormalThreshold ) + { + n[0] /= t; + n[1] /= t; + n[2] /= t; + } + else + { + n[0] = n[1] = n[2] = 0.0; + } + + int nx = static_cast<int>((n[0] / 2.0 + 0.5)*255.0 + 0.5); + int ny = static_cast<int>((n[1] / 2.0 + 0.5)*255.0 + 0.5); + int nz = static_cast<int>((n[2] / 2.0 + 0.5)*255.0 + 0.5); + + nx = (nx<0)?(0):(nx); + ny = (ny<0)?(0):(ny); + nz = (nz<0)?(0):(nz); + + nx = (nx>255)?(255):(nx); + ny = (ny>255)?(255):(ny); + nz = (nz>255)?(255):(nz); + + *(outPtr2 ) = nx; + *(outPtr2+1) = ny; + *(outPtr2+2) = nz; + + outPtr1 += gradmagIncrement; + outPtr2 += 3; + } + } +// if ( z%8 == 7 ) +// { +// float args[1]; +// args[0] = +// static_cast<float>(z - z_start) / +// static_cast<float>(z_limit - z_start - 1); +// me->InvokeEvent( vtkEvent::VolumeMapperComputeGradientsProgressEvent, args ); +// } + } +// me->InvokeEvent( vtkEvent::VolumeMapperComputeGradientsEndEvent, NULL ); +} + + +vtkVolumeTextureMapper3D::vtkVolumeTextureMapper3D() +{ + this->PolygonBuffer = NULL; + this->IntersectionBuffer = NULL; + this->NumberOfPolygons = 0; + this->BufferSize = 0; + + // The input used when creating the textures + this->SavedTextureInput = NULL; + + // The input used when creating the color tables + this->SavedParametersInput = NULL; + + this->SavedRGBFunction = NULL; + this->SavedGrayFunction = NULL; + this->SavedScalarOpacityFunction = NULL; + this->SavedColorChannels = 0; + this->SavedSampleDistance = 0; + this->SavedScalarOpacityDistance = 0; + + this->Volume1 = NULL; + this->Volume2 = NULL; + this->Volume3 = NULL; + this->VolumeSize = 0; + this->VolumeComponents = 0; + + this->SampleDistance = 1.0; + this->ActualSampleDistance = 1.0; + + this->RenderMethod = vtkVolumeTextureMapper3D::NO_METHOD; + this->PreferredRenderMethod = vtkVolumeTextureMapper3D::FRAGMENT_PROGRAM_METHOD; +} + +vtkVolumeTextureMapper3D::~vtkVolumeTextureMapper3D() +{ + delete [] this->PolygonBuffer; + delete [] this->IntersectionBuffer; + delete [] this->Volume1; + delete [] this->Volume2; + delete [] this->Volume3; +} + + +vtkVolumeTextureMapper3D *vtkVolumeTextureMapper3D::New() +{ + // First try to create the object from the vtkObjectFactory + vtkObject* ret = + vtkVolumeRenderingFactory::CreateInstance("vtkVolumeTextureMapper3D"); + return (vtkVolumeTextureMapper3D*)ret; +} + +void vtkVolumeTextureMapper3D::ComputePolygons( vtkRenderer *ren, + vtkVolume *vol, + double inBounds[6] ) +{ + // Get the camera position and focal point + double focalPoint[4], position[4]; + double plane[4]; + vtkCamera *camera = ren->GetActiveCamera(); + + camera->GetPosition( position ); + camera->GetFocalPoint( focalPoint ); + + position[3] = 1.0; + focalPoint[3] = 1.0; + + // Pass the focal point and position through the inverse of the + // volume's matrix to map back into the data coordinates. We + // are going to compute these polygons in the coordinate system + // of the input data - this is easiest since this data must be + // axis aligned. Then we'll use OpenGL to transform these polygons + // into the world coordinate system through the use of the + // volume's matrix. + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + vol->GetMatrix( matrix ); + matrix->Invert(); + matrix->MultiplyPoint( position, position ); + matrix->MultiplyPoint( focalPoint, focalPoint ); + matrix->Delete(); + + if ( position[3] ) + { + position[0] /= position[3]; + position[1] /= position[3]; + position[2] /= position[3]; + } + + if ( focalPoint[3] ) + { + focalPoint[0] /= focalPoint[3]; + focalPoint[1] /= focalPoint[3]; + focalPoint[2] /= focalPoint[3]; + } + + // Create a plane equation using the direction and position of the camera + plane[0] = (double)focalPoint[0] - (double)position[0]; + plane[1] = (double)focalPoint[1] - (double)position[1]; + plane[2] = (double)focalPoint[2] - (double)position[2]; + + vtkMath::Normalize( plane ); + + plane[3] = -(plane[0] * (double)position[0] + + plane[1] * (double)position[1] + + plane[2] * (double)position[2]); + + // Find the min and max distances of the boundary points of the volume + double minDistance = VTK_FLOAT_MAX; + double maxDistance = -VTK_FLOAT_MAX; + + // The inBounds parameter is the bounds we are using for clipping the + // texture planes against. First we need to clip these against the bounds + // of the volume to make sure they don't exceed it. + double volBounds[6]; + this->GetInput()->GetBounds( volBounds ); + + double bounds[6]; + bounds[0] = (inBounds[0]>volBounds[0])?(inBounds[0]):(volBounds[0]); + bounds[1] = (inBounds[1]<volBounds[1])?(inBounds[1]):(volBounds[1]); + bounds[2] = (inBounds[2]>volBounds[2])?(inBounds[2]):(volBounds[2]); + bounds[3] = (inBounds[3]<volBounds[3])?(inBounds[3]):(volBounds[3]); + bounds[4] = (inBounds[4]>volBounds[4])?(inBounds[4]):(volBounds[4]); + bounds[5] = (inBounds[5]<volBounds[5])?(inBounds[5]):(volBounds[5]); + + // Create 8 vertices for the bounding box we are rendering + int i, j, k; + double vertices[8][3]; + + int idx = 0; + + for ( k = 0; k < 2; k++ ) + { + for ( j = 0; j < 2; j++ ) + { + for ( i = 0; i < 2; i++ ) + { + vertices[idx][2] = bounds[4+k]; + vertices[idx][1] = bounds[2+j]; + vertices[idx][0] = bounds[i]; + + double d = + plane[0] * vertices[idx][0] + + plane[1] * vertices[idx][1] + + plane[2] * vertices[idx][2] + + plane[3]; + + idx++; + + // Keep track of closest and farthest point + minDistance = (d<minDistance)?(d):(minDistance); + maxDistance = (d>maxDistance)?(d):(maxDistance); + + } + } + } + + int dim[6]; + this->GetVolumeDimensions(dim); + + float tCoordOffset[3], tCoordScale[3]; + + tCoordOffset[0] = 0.5 / static_cast<float>( dim[0] ); + tCoordOffset[1] = 0.5 / static_cast<float>( dim[1] ); + tCoordOffset[2] = 0.5 / static_cast<float>( dim[2] ); + + tCoordScale[0] = + static_cast<float>( dim[0]-1 ) / + static_cast<float>( dim[0] ); + tCoordScale[1] = + static_cast<float>( dim[1]-1 ) / + static_cast<float>( dim[1] ); + tCoordScale[2] = + static_cast<float>( dim[2]-1 ) / + static_cast<float>( dim[2] ); + + float spacing[3]; + this->GetVolumeSpacing( spacing ); + + double offset = + 0.333 * 0.5 * (spacing[0] + spacing[1] + spacing[2]); + + minDistance += 0.1*offset; + maxDistance -= 0.1*offset; + + minDistance = (minDistance < offset)?(offset):(minDistance); + + double stepSize = this->ActualSampleDistance; + + // Determine the number of polygons + int numPolys = (int)((maxDistance - minDistance)/(double)stepSize); + + // Check if we have space, free old space only if it is too small + if ( this->BufferSize < numPolys ) + { + delete [] this->PolygonBuffer; + delete [] this->IntersectionBuffer; + + this->BufferSize = numPolys; + + this->PolygonBuffer = new float [36*this->BufferSize]; + this->IntersectionBuffer = new float [12*this->BufferSize]; + } + + this->NumberOfPolygons = numPolys; + + // Compute the intersection points for each edge of the volume + int lines[12][2] = { {0,1}, {1,3}, {2,3}, {0,2}, + {4,5}, {5,7}, {6,7}, {4,6}, + {0,4}, {1,5}, {3,7}, {2,6} }; + + float *iptr, *pptr; + + for ( i = 0; i < 12; i++ ) + { + double line[3]; + + line[0] = vertices[lines[i][1]][0] - vertices[lines[i][0]][0]; + line[1] = vertices[lines[i][1]][1] - vertices[lines[i][0]][1]; + line[2] = vertices[lines[i][1]][2] - vertices[lines[i][0]][2]; + + double d = maxDistance; + + iptr = this->IntersectionBuffer + i; + + double planeDotLineOrigin = vtkMath::Dot( plane, vertices[lines[i][0]] ); + double planeDotLine = vtkMath::Dot( plane, line ); + + double t, increment; + + if ( planeDotLine != 0.0 ) + { + t = (d - planeDotLineOrigin - plane[3] ) / planeDotLine; + increment = -stepSize / planeDotLine; + } + else + { + t = -1.0; + increment = 0.0; + } + + for ( j = 0; j < numPolys; j++ ) + { + *iptr = (t > 0.0 && t < 1.0)?(t):(-1.0); + + t += increment; + iptr += 12; + } + } + + // Compute the polgons by determining which edges were intersected + int neighborLines[12][6] = + { { 1, 2, 3, 4, 8, 9}, { 0, 2, 3, 5, 9, 10}, + { 0, 1, 3, 6, 10, 11}, { 0, 1, 2, 7, 8, 11}, + { 0, 5, 6, 7, 8, 9}, { 1, 4, 6, 7, 9, 10}, + { 2, 4, 5, 7, 10, 11}, { 3, 4, 5, 6, 8, 11}, + { 0, 3, 4, 7, 9, 11}, { 0, 1, 4, 5, 8, 10}, + { 1, 2, 5, 6, 9, 11}, { 2, 3, 6, 7, 8, 10} }; + + float tCoord[12][4] = + {{0,0,0,0}, {1,0,0,1}, {0,1,0,0}, {0,0,0,1}, + {0,0,1,0}, {1,0,1,1}, {0,1,1,0}, {0,0,1,1}, + {0,0,0,2}, {1,0,0,2}, {1,1,0,2}, {0,1,0,2}}; + + double low[3]; + double high[3]; + + low[0] = (bounds[0] - (double)volBounds[0]) / + ((double)volBounds[1] - (double)volBounds[0]); + high[0] = (bounds[1] - (double)volBounds[0]) / + ((double)volBounds[1] - (double)volBounds[0]); + low[1] = (bounds[2] - (double)volBounds[2]) / + ((double)volBounds[3] - (double)volBounds[2]); + high[1] = (bounds[3] - (double)volBounds[2]) / + ((double)volBounds[3] - (double)volBounds[2]); + low[2] = (bounds[4] - (double)volBounds[4]) / + ((double)volBounds[5] - (double)volBounds[4]); + high[2] = (bounds[5] - (double)volBounds[4]) / + ((double)volBounds[5] - (double)volBounds[4]); + + for ( i = 0; i < 12; i++ ) + { + tCoord[i][0] = (tCoord[i][0])?(high[0]):(low[0]); + tCoord[i][1] = (tCoord[i][1])?(high[1]):(low[1]); + tCoord[i][2] = (tCoord[i][2])?(high[2]):(low[2]); + } + + iptr = this->IntersectionBuffer; + pptr = this->PolygonBuffer; + + for ( i = 0; i < numPolys; i++ ) + { + // Look for a starting point + int start = 0; + + while ( start < 12 && iptr[start] == -1.0 ) + { + start++; + } + + if ( start == 12 ) + { + pptr[0] = -1.0; + } + else + { + int current = start; + int previous = -1; + int errFlag = 0; + + idx = 0; + + while ( idx < 6 && !errFlag && ( idx == 0 || current != start) ) + { + double t = iptr[current]; + + *(pptr + idx*6) = + tCoord[current][0] * tCoordScale[0] + tCoordOffset[0]; + *(pptr + idx*6 + 1) = + tCoord[current][1] * tCoordScale[1] + tCoordOffset[1]; + *(pptr + idx*6 + 2) = + tCoord[current][2] * tCoordScale[2] + tCoordOffset[2]; + + int coord = static_cast<int>(tCoord[current][3]); + *(pptr + idx*6 + coord) = + (low[coord] + t*(high[coord]-low[coord]))*tCoordScale[coord] + tCoordOffset[coord]; + + *(pptr + idx*6 + 3) = (float)( + vertices[lines[current][0]][0] + + t*(vertices[lines[current][1]][0] - vertices[lines[current][0]][0])); + + *(pptr + idx*6 + 4) = (float)( + vertices[lines[current][0]][1] + + t*(vertices[lines[current][1]][1] - vertices[lines[current][0]][1])); + + *(pptr + idx*6 + 5) = (float)( + vertices[lines[current][0]][2] + + t*(vertices[lines[current][1]][2] - vertices[lines[current][0]][2])); + + idx++; + + j = 0; + + while ( j < 6 && + (*(this->IntersectionBuffer + i*12 + + neighborLines[current][j]) < 0 || + neighborLines[current][j] == previous) ) + { + j++; + } + + if ( j >= 6 ) + { + errFlag = 1; + } + else + { + previous = current; + current = neighborLines[current][j]; + } + } + + if ( idx < 6 ) + { + *(pptr + idx*6) = -1; + } + } + + iptr += 12; + pptr += 36; + } +} + +int vtkVolumeTextureMapper3D::UpdateVolumes(vtkVolume *vtkNotUsed(vol)) +{ + int needToUpdate = 0; + + // Get the image data + vtkImageData *input = this->GetInput(); + input->Update(); + + // Has the volume changed in some way? + if ( this->SavedTextureInput != input || + this->SavedTextureMTime.GetMTime() < input->GetMTime() ) + { + needToUpdate = 1; + } + + if ( !needToUpdate ) + { + return 0; + } + + this->SavedTextureInput = input; + this->SavedTextureMTime.Modified(); + + // How big does the Volume need to be? + int dim[3]; + input->GetDimensions(dim); + + int powerOfTwoDim[3]; + + for ( int i = 0; i < 3; i++ ) + { + powerOfTwoDim[i] = 32; + while ( powerOfTwoDim[i] < dim[i] ) + { + powerOfTwoDim[i] *= 2; + } + } + + while ( ! this->IsTextureSizeSupported( powerOfTwoDim ) ) + { + if ( powerOfTwoDim[0] >= powerOfTwoDim[1] && + powerOfTwoDim[0] >= powerOfTwoDim[2] ) + { + powerOfTwoDim[0] /= 2; + } + else if ( powerOfTwoDim[1] >= powerOfTwoDim[0] && + powerOfTwoDim[1] >= powerOfTwoDim[2] ) + { + powerOfTwoDim[1] /= 2; + } + else + { + powerOfTwoDim[2] /= 2; + } + } + + int neededSize = powerOfTwoDim[0] * powerOfTwoDim[1] * powerOfTwoDim[2]; + + int components = input->GetNumberOfScalarComponents(); + + // What is the spacing? + double spacing[3]; + input->GetSpacing(spacing); + + // Is it the right size? If not, allocate it. + if ( this->VolumeSize != neededSize || + this->VolumeComponents != components ) + { + delete [] this->Volume1; + delete [] this->Volume2; + delete [] this->Volume3; + switch (components) + { + case 1: + this->Volume1 = new unsigned char [2*neededSize]; + this->Volume2 = new unsigned char [3*neededSize]; + this->Volume3 = NULL; + break; + case 2: + this->Volume1 = new unsigned char [3*neededSize]; + this->Volume2 = new unsigned char [3*neededSize]; + this->Volume3 = NULL; + break; + case 3: + case 4: + this->Volume1 = new unsigned char [3*neededSize]; + this->Volume2 = new unsigned char [2*neededSize]; + this->Volume3 = new unsigned char [3*neededSize]; + break; + } + + this->VolumeSize = neededSize; + this->VolumeComponents = components; + } + + // Find the scalar range + double scalarRange[2]; + input->GetPointData()->GetScalars()->GetRange(scalarRange, components-1); + + // Is the difference between max and min less than 4096? If so, and if + // the data is not of float or double type, use a simple offset mapping. + // If the difference between max and min is 4096 or greater, or the data + // is of type float or double, we must use an offset / scaling mapping. + // In this case, the array size will be 4096 - we need to figure out the + // offset and scale factor. + float offset; + float scale; + + int arraySizeNeeded; + + int scalarType = input->GetScalarType(); + + if ( scalarType == VTK_FLOAT || + scalarType == VTK_DOUBLE || + scalarRange[1] - scalarRange[0] > 255 ) + { + arraySizeNeeded = 256; + offset = -scalarRange[0]; + scale = 255.0 / (scalarRange[1] - scalarRange[0]); + } + else + { + arraySizeNeeded = (int)(scalarRange[1] - scalarRange[0] + 1); + offset = -scalarRange[0]; + scale = 1.0; + } + + this->ColorTableSize = arraySizeNeeded; + this->ColorTableOffset = offset; + this->ColorTableScale = scale; + + // Save the volume size + this->VolumeDimensions[0] = powerOfTwoDim[0]; + this->VolumeDimensions[1] = powerOfTwoDim[1]; + this->VolumeDimensions[2] = powerOfTwoDim[2]; + + // Compute the new spacing + this->VolumeSpacing[0] = + (static_cast<double>(dim[0])-1.01)*(double)spacing[0] / static_cast<double>(this->VolumeDimensions[0]-1); + this->VolumeSpacing[1] = + (static_cast<double>(dim[1])-1.01)*(double)spacing[1] / static_cast<double>(this->VolumeDimensions[1]-1); + this->VolumeSpacing[2] = + (static_cast<double>(dim[2])-1.01)*(double)spacing[2] / static_cast<double>(this->VolumeDimensions[2]-1); + + + // Transfer the input volume to the RGBA volume + void *dataPtr = input->GetScalarPointer(); + + + switch ( scalarType ) + { + vtkTemplateMacro( + vtkVolumeTextureMapper3DComputeScalars( + (VTK_TT *)(dataPtr), this, + offset, scale, + this->Volume1, + this->Volume2)); + } + + switch ( scalarType ) + { + vtkTemplateMacro( + vtkVolumeTextureMapper3DComputeGradients( + (VTK_TT *)(dataPtr), this, + scalarRange, + this->Volume1, + this->Volume2, + this->Volume3)); + } + + return 1; +} + + +int vtkVolumeTextureMapper3D::UpdateColorLookup( vtkVolume *vol ) +{ + int needToUpdate = 0; + + // Get the image data + vtkImageData *input = this->GetInput(); + input->Update(); + + // Has the volume changed in some way? + if ( this->SavedParametersInput != input || + this->SavedParametersMTime.GetMTime() < input->GetMTime() ) + { + needToUpdate = 1; + } + + // What sample distance are we going to use for rendering? If we + // have to render quickly according to our allocated render time, + // don't necessary obey the sample distance requested by the user. + // Instead set the sample distance to the average spacing. + this->ActualSampleDistance = this->SampleDistance; + if ( vol->GetAllocatedRenderTime() < 1.0 ) + { + float spacing[3]; + this->GetVolumeSpacing(spacing); + this->ActualSampleDistance = + 0.333 * ((double)spacing[0] + (double)spacing[1] + (double)spacing[2]); + } + + // How many components? + int components = input->GetNumberOfScalarComponents(); + + // Has the sample distance changed? + if ( this->SavedSampleDistance != this->ActualSampleDistance ) + { + needToUpdate = 1; + } + + vtkColorTransferFunction *rgbFunc = NULL; + vtkPiecewiseFunction *grayFunc = NULL; + + // How many color channels for this component? + int colorChannels = vol->GetProperty()->GetColorChannels(0); + + if ( components < 3 ) + { + // Has the number of color channels changed? + if ( this->SavedColorChannels != colorChannels ) + { + needToUpdate = 1; + } + + // Has the color transfer function changed in some way, + // and we are using it? + if ( colorChannels == 3 ) + { + rgbFunc = vol->GetProperty()->GetRGBTransferFunction(0); + if ( this->SavedRGBFunction != rgbFunc || + this->SavedParametersMTime.GetMTime() < rgbFunc->GetMTime() ) + { + needToUpdate = 1; + } + } + + // Has the gray transfer function changed in some way, + // and we are using it? + if ( colorChannels == 1 ) + { + grayFunc = vol->GetProperty()->GetGrayTransferFunction(0); + if ( this->SavedGrayFunction != grayFunc || + this->SavedParametersMTime.GetMTime() < grayFunc->GetMTime() ) + { + needToUpdate = 1; + } + } + } + + // Has the scalar opacity transfer function changed in some way? + vtkPiecewiseFunction *scalarOpacityFunc = + vol->GetProperty()->GetScalarOpacity(0); + if ( this->SavedScalarOpacityFunction != scalarOpacityFunc || + this->SavedParametersMTime.GetMTime() < + scalarOpacityFunc->GetMTime() ) + { + needToUpdate = 1; + } + + // Has the gradient opacity transfer function changed in some way? + vtkPiecewiseFunction *gradientOpacityFunc = + vol->GetProperty()->GetGradientOpacity(0); + if ( this->SavedGradientOpacityFunction != gradientOpacityFunc || + this->SavedParametersMTime.GetMTime() < + gradientOpacityFunc->GetMTime() ) + { + needToUpdate = 1; + } + + + double scalarOpacityDistance = + vol->GetProperty()->GetScalarOpacityUnitDistance(0); + if ( this->SavedScalarOpacityDistance != scalarOpacityDistance ) + { + needToUpdate = 1; + } + + // If we have not found any need to update, return now + if ( !needToUpdate ) + { + return 0; + } + + this->SavedRGBFunction = rgbFunc; + this->SavedGrayFunction = grayFunc; + this->SavedScalarOpacityFunction = scalarOpacityFunc; + this->SavedGradientOpacityFunction = gradientOpacityFunc; + this->SavedColorChannels = colorChannels; + this->SavedSampleDistance = this->ActualSampleDistance; + this->SavedScalarOpacityDistance = scalarOpacityDistance; + this->SavedParametersInput = input; + + this->SavedParametersMTime.Modified(); + + // Find the scalar range + double scalarRange[2]; + input->GetPointData()->GetScalars()->GetRange(scalarRange, components-1); + + int arraySizeNeeded = this->ColorTableSize; + + if ( components < 3 ) + { + // Sample the transfer functions between the min and max. + if ( colorChannels == 1 ) + { + grayFunc->GetTable( scalarRange[0], scalarRange[1], + arraySizeNeeded, this->TempArray1 ); + } + else + { + rgbFunc->GetTable( scalarRange[0], scalarRange[1], + arraySizeNeeded, this->TempArray1 ); + } + } + + scalarOpacityFunc->GetTable( scalarRange[0], scalarRange[1], + arraySizeNeeded, this->TempArray2 ); + + float goArray[256]; + gradientOpacityFunc->GetTable( 0, (scalarRange[1] - scalarRange[0])*0.25, + 256, goArray ); + + // Correct the opacity array for the spacing between the planes. + int i; + + float *fptr2 = this->TempArray2; + double factor = (double)this->ActualSampleDistance / scalarOpacityDistance; + for ( i = 0; i < arraySizeNeeded; i++ ) + { + if ( *fptr2 > 0.0001 ) + { + *fptr2 = 1.0-pow((double)(1.0-(*fptr2)),factor); + } + fptr2++; + } + + int goLoop; + unsigned char *ptr, *rgbptr, *aptr; + float *fptr1; + + switch (components) + { + case 1: + // Move the two temp float arrays into one RGBA unsigned char array + ptr = this->ColorLookup; + for ( goLoop = 0; goLoop < 256; goLoop++ ) + { + fptr1 = this->TempArray1; + fptr2 = this->TempArray2; + if ( colorChannels == 1 ) + { + for ( i = 0; i < arraySizeNeeded; i++ ) + { + *(ptr++) = static_cast<unsigned char>(*(fptr1)*255.0 + 0.5); + *(ptr++) = static_cast<unsigned char>(*(fptr1)*255.0 + 0.5); + *(ptr++) = static_cast<unsigned char>(*(fptr1++)*255.0 + 0.5); + *(ptr++) = static_cast<unsigned char>(*(fptr2++)*goArray[goLoop]*255.0 + 0.5); + } + } + else + { + for ( i = 0; i < arraySizeNeeded; i++ ) + { + *(ptr++) = static_cast<unsigned char>(*(fptr1++)*255.0 + 0.5); + *(ptr++) = static_cast<unsigned char>(*(fptr1++)*255.0 + 0.5); + *(ptr++) = static_cast<unsigned char>(*(fptr1++)*255.0 + 0.5); + *(ptr++) = static_cast<unsigned char>(*(fptr2++)*goArray[goLoop]*255.0 + 0.5); + } + } + + for ( ; i < 256; i++ ) + { + *(ptr++) = 0; + *(ptr++) = 0; + *(ptr++) = 0; + *(ptr++) = 0; + } + } + break; + + case 2: + // Move the two temp float arrays into one RGB unsigned char array and + // one alpha array. + rgbptr = this->ColorLookup; + aptr = this->AlphaLookup; + + if ( colorChannels == 1 ) + { + for ( i = 0; i < arraySizeNeeded; i++ ) + { + fptr1 = this->TempArray1; + fptr2 = this->TempArray2; + for ( goLoop = 0; goLoop < 256; goLoop++ ) + { + *(rgbptr++) = static_cast<unsigned char>(*(fptr1)*255.0 + 0.5); + *(rgbptr++) = static_cast<unsigned char>(*(fptr1)*255.0 + 0.5); + *(rgbptr++) = static_cast<unsigned char>(*(fptr1++)*255.0 + 0.5); + *(aptr++) = static_cast<unsigned char>(*(fptr2++)*goArray[goLoop]*255.0 + 0.5); + } + } + } + else + { + fptr1 = this->TempArray1; + fptr2 = this->TempArray2; + for ( i = 0; i < arraySizeNeeded; i++ ) + { + for ( goLoop = 0; goLoop < 256; goLoop++ ) + { + *(rgbptr++) = static_cast<unsigned char>(*(fptr1)*255.0 + 0.5); + *(rgbptr++) = static_cast<unsigned char>(*(fptr1+1)*255.0 + 0.5); + *(rgbptr++) = static_cast<unsigned char>(*(fptr1+2)*255.0 + 0.5); + *(aptr++) = static_cast<unsigned char>(*(fptr2)*goArray[goLoop]*255.0 + 0.5); + } + fptr1+=3; + fptr2++; + } + } + + for ( ; i < 256; i++ ) + { + for ( goLoop = 0; goLoop < 256; goLoop++ ) + { + *(rgbptr++) = 0; + *(rgbptr++) = 0; + *(rgbptr++) = 0; + *(aptr++) = 0; + } + } + break; + + case 3: + case 4: + // Move the two temp float arrays into one alpha array + aptr = this->AlphaLookup; + + for ( goLoop = 0; goLoop < 256; goLoop++ ) + { + fptr2 = this->TempArray2; + for ( i = 0; i < arraySizeNeeded; i++ ) + { + *(aptr++) = static_cast<unsigned char>(*(fptr2++)*goArray[goLoop]*255.0 + 0.5); + } + for ( ; i < 256; i++ ) + { + *(aptr++) = 0; + } + } + + break; + } + return 1; +} + + +// Print the vtkVolumeTextureMapper3D +void vtkVolumeTextureMapper3D::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Sample Distance: " << this->SampleDistance << endl; + os << indent << "Render Method: " << this->RenderMethod << endl; + os << indent << "Preferred Render Method: " << this->PreferredRenderMethod << endl; + os << indent << "NumberOfPolygons: " << this->NumberOfPolygons << endl; + os << indent << "ActualSampleDistance: " + << this->ActualSampleDistance << endl; + os << indent << "VolumeDimensions: " << this->VolumeDimensions[0] << " " + << this->VolumeDimensions[1] << " " << this->VolumeDimensions[2] << endl; + os << indent << "VolumeSpacing: " << this->VolumeSpacing[0] << " " + << this->VolumeSpacing[1] << " " << this->VolumeSpacing[2] << endl; +} + + + diff --git a/VolumeRendering/vtkVolumeTextureMapper3D.h b/VolumeRendering/vtkVolumeTextureMapper3D.h new file mode 100644 index 0000000..4924ac2 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D.h @@ -0,0 +1,227 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkVolumeTextureMapper3D.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkVolumeTextureMapper3D - volume render with 3D texture mapping + +// .SECTION Description +// vtkVolumeTextureMapper3D renders a volume using 3D texture mapping. +// This class is actually an abstract superclass - with all the actual +// work done by vtkOpenGLVolumeTextureMapper3D. +// +// This mappers currently supports: +// +// - any data type as input +// - one component, or two or four non-independent components +// - composite blending +// - intermixed opaque geometry +// - multiple volumes can be rendered if they can +// be sorted into back-to-front order (use the vtkFrustumCoverageCuller) +// +// This mapper does not support: +// - more than one independent component +// - maximum intensity projection +// +// Internally, this mapper will potentially change the resolution of the +// input data. The data will be resampled to be a power of two in each +// direction, and also no greater than 128*256*256 voxels (any aspect) +// for one or two component data, or 128*128*256 voxels (any aspect) +// for four component data. The limits are currently hardcoded after +// a check using the GL_PROXY_TEXTURE3D because some graphics drivers +// were always responding "yes" to the proxy call despite not being +// able to allocate that much texture memory. +// +// Currently, calculations are computed using 8 bits per RGBA channel. +// In the future this should be expanded to handle newer boards that +// can support 15 bit float compositing. +// +// This mapper supports two main families of graphics hardware: +// nvidia and ATI. There are two different implementations of +// 3D texture mapping used - one based on nvidia's GL_NV_texture_shader2 +// and GL_NV_register_combiners2 extension, and one based on +// ATI's GL_ATI_fragment_shader (supported also by some nvidia boards) +// To use this class in an application that will run on various +// hardware configurations, you should have a back-up volume rendering +// method. You should create a vtkVolumeTextureMapper3D, assign its +// input, make sure you have a current OpenGL context (you've rendered +// at least once), then call IsRenderSupported with a vtkVolumeProperty +// as an argument. This method will return 0 if the input has more than +// one independent component, or if the graphics hardware does not +// support the set of required extensions for using at least one of +// the two implemented methods (nvidia or ati) +// + +// .SECTION see also +// vtkVolumeMapper + +#ifndef __vtkVolumeTextureMapper3D_h +#define __vtkVolumeTextureMapper3D_h + +#include "vtkVolumeMapper.h" + +class vtkImageData; +class vtkColorTransferFunction; +class vtkPiecewiseFunction; +class vtkVolumeProperty; + +class VTK_VOLUMERENDERING_EXPORT vtkVolumeTextureMapper3D : public vtkVolumeMapper +{ +public: + vtkTypeRevisionMacro(vtkVolumeTextureMapper3D,vtkVolumeMapper); + void PrintSelf(ostream& os, vtkIndent indent); + + static vtkVolumeTextureMapper3D *New(); + + // Description: + // The distance at which to space sampling planes. This + // may not be honored for interactive renders. An interactive + // render is defined as one that has less than 1 second of + // allocated render time. + vtkSetMacro( SampleDistance, float ); + vtkGetMacro( SampleDistance, float ); + + // Description: + // These are the dimensions of the 3D texture + vtkGetVectorMacro( VolumeDimensions, int, 3 ); + + // Description: + // This is the spacing of the 3D texture + vtkGetVectorMacro( VolumeSpacing, float, 3 ); + + // Description: + // Based on hardware and properties, we may or may not be able to + // render using 3D texture mapping. This indicates if 3D texture + // mapping is supported by the hardware, and if the other extensions + // necessary to support the specific properties are available. + virtual int IsRenderSupported( vtkVolumeProperty * ) {return 0;}; + + // Description: + // Allow access to the number of polygons used for the + // rendering. + vtkGetMacro( NumberOfPolygons, int ); + + // Description: + // Allow access to the actual sample distance used to render + // the image. + vtkGetMacro( ActualSampleDistance, float ); + +//BTX + + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS + // Render the volume + virtual void Render(vtkRenderer *, vtkVolume *) {}; + + // Description: + // What rendering method is supported? + enum + { + FRAGMENT_PROGRAM_METHOD=0, + NVIDIA_METHOD=1, + ATI_METHOD=2, + NO_METHOD=3 + }; +//ETX + + // Description: + // Set the preferred render method. If it is supported, this + // one will be used. Don't allow ATI_METHOD - it is not actually + // supported. + vtkSetClampMacro( PreferredRenderMethod, int, + vtkVolumeTextureMapper3D::FRAGMENT_PROGRAM_METHOD, + vtkVolumeTextureMapper3D::NVIDIA_METHOD ); + void SetPreferredMethodToFragmentProgram() + { this->SetPreferredRenderMethod( vtkVolumeTextureMapper3D::FRAGMENT_PROGRAM_METHOD ); } + void SetPreferredMethodToNVidia() + { this->SetPreferredRenderMethod( vtkVolumeTextureMapper3D::NVIDIA_METHOD ); } + + + +protected: + vtkVolumeTextureMapper3D(); + ~vtkVolumeTextureMapper3D(); + + float *PolygonBuffer; + float *IntersectionBuffer; + int NumberOfPolygons; + int BufferSize; + + unsigned char *Volume1; + unsigned char *Volume2; + unsigned char *Volume3; + int VolumeSize; + int VolumeComponents; + int VolumeDimensions[3]; + float VolumeSpacing[3]; + + float SampleDistance; + float ActualSampleDistance; + + vtkImageData *SavedTextureInput; + vtkImageData *SavedParametersInput; + + vtkColorTransferFunction *SavedRGBFunction; + vtkPiecewiseFunction *SavedGrayFunction; + vtkPiecewiseFunction *SavedScalarOpacityFunction; + vtkPiecewiseFunction *SavedGradientOpacityFunction; + int SavedColorChannels; + float SavedSampleDistance; + float SavedScalarOpacityDistance; + + unsigned char ColorLookup[65536*4]; + unsigned char AlphaLookup[65536]; + float TempArray1[3*4096]; + float TempArray2[4096]; + int ColorTableSize; + float ColorTableScale; + float ColorTableOffset; + + unsigned char DiffuseLookup[65536*4]; + unsigned char SpecularLookup[65536*4]; + + vtkTimeStamp SavedTextureMTime; + vtkTimeStamp SavedParametersMTime; + + int RenderMethod; + int PreferredRenderMethod; + + // Description: + // For the given viewing direction, compute the set of polygons. + void ComputePolygons( vtkRenderer *ren, vtkVolume *vol, double bounds[6] ); + + // Description: + // Update the internal RGBA representation of the volume. Return 1 if + // anything change, 0 if nothing changed. + int UpdateVolumes( vtkVolume * ); + int UpdateColorLookup( vtkVolume * ); + + // Description: + // Impemented in subclass - check is texture size is OK. + //BTX + virtual int IsTextureSizeSupported( int [3] ) {return 0;}; + //ETX + +private: + vtkVolumeTextureMapper3D(const vtkVolumeTextureMapper3D&); // Not implemented. + void operator=(const vtkVolumeTextureMapper3D&); // Not implemented. +}; + + +#endif + + + + + + diff --git a/VolumeRendering/vtkVolumeTextureMapper3D_FourDependentNoShadeFP.asm b/VolumeRendering/vtkVolumeTextureMapper3D_FourDependentNoShadeFP.asm new file mode 100644 index 0000000..67c5427 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D_FourDependentNoShadeFP.asm @@ -0,0 +1,43 @@ +!!ARBfp1.0 + +# This is the fragment program for four +# component dependent data with no shading + +# We need some temporary variables +TEMP temp1, temp2; +TEMP finalColor, finalOpacity; + +# We are going to use the first +# texture coordinate +ATTRIB tex0 = fragment.texcoord[0]; + +# This is our output color +OUTPUT out = result.color; + +# Look up the color in the first volume +TEX finalColor, tex0, texture[0], 3D; + +# Look up the fourth scalar / gradient +# magnitude in the second volume +TEX temp1, tex0, texture[1], 3D; + +# Swizzle this to use (a,r) as texture +# coordinates for color, and (g,b) for +# opacity +SWZ temp2, temp1, a, r, 1, 1; + +# Use the (a,r) coordinate to look up a +# final opacity in the fourth texture +# (this is a 2D texture) +TEX finalOpacity, temp2, texture[3], 2D; + +# Combine these into the result +MOV out, finalColor; +MOV out.w, finalOpacity.w; +END + + + + + + \ No newline at end of file diff --git a/VolumeRendering/vtkVolumeTextureMapper3D_FourDependentShadeFP.asm b/VolumeRendering/vtkVolumeTextureMapper3D_FourDependentShadeFP.asm new file mode 100644 index 0000000..b5ca008 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D_FourDependentShadeFP.asm @@ -0,0 +1,98 @@ +!!ARBfp1.0 + +# This is the fragment program for two +# component dependent data with shading + +# We need some temporary variables +TEMP index1, index2, normal, finalColor; +TEMP temp1, temp2, temp3; +TEMP sampleColor, sampleOpacity; +TEMP ndotl, ndoth, ndotv; +TEMP lightInfo, lightResult; + +# We are going to use the first +# texture coordinate +ATTRIB tex0 = fragment.texcoord[0]; + +# This is the lighting information +PARAM lightDirection = program.local[0]; +PARAM halfwayVector = program.local[1]; +PARAM coefficient = program.local[2]; +PARAM lightDiffColor = program.local[3]; +PARAM lightSpecColor = program.local[4]; +PARAM viewVector = program.local[5]; +PARAM constants = program.local[6]; + +# This is our output color +OUTPUT out = result.color; + +# Look up color in the first volume +TEX sampleColor, tex0, texture[0], 3D; + +# Look up the fourth scalar value / gradient +# magnitude in the second volume +TEX temp1, tex0, texture[1], 3D; + +# Look up the gradient direction +# in the third volume +TEX temp2, tex0, texture[2], 3D; + +# This normal is stored 0 to 1, change to -1 to 1 +# by multiplying by 2.0 then adding -1.0. +MAD normal, temp2, constants.x, constants.y; + +# Swizzle this to use (a,r) as texture +# coordinates for opacity +SWZ index1, temp1, a, r, 1, 1; + +# Use this coordinate to look up a +# final opacity in the fourth texture +TEX sampleOpacity, index1, texture[3], 2D; + +# Take the dot product of the light +# direction and the normal +DP3 ndotl, normal, lightDirection; + +# Take the dot product of the halfway +# vector and the normal +DP3 ndoth, normal, halfwayVector; + +DP3 ndotv, normal, viewVector; + +# flip if necessary for two sided lighting +MUL temp3, ndotl, constants.y; +CMP ndotl, ndotv, ndotl, temp3; +MUL temp3, ndoth, constants.y; +CMP ndoth, ndotv, ndoth, temp3; + +# put the pieces together for a LIT operation +MOV lightInfo.x, ndotl.x; +MOV lightInfo.y, ndoth.x; +MOV lightInfo.w, coefficient.w; + +# compute the lighting +LIT lightResult, lightInfo; + +# This is the ambient contribution +MUL finalColor, coefficient.x, sampleColor; + +# This is the diffuse contribution +MUL temp3, lightDiffColor, sampleColor; +MUL temp3, temp3, lightResult.y; +ADD finalColor, finalColor, temp3; + +# This is th specular contribution +MUL temp3, lightSpecColor, lightResult.z; + +# Add specular into result so far, and replace +# with the original alpha. +ADD out, finalColor, temp3; +MOV out.w, sampleOpacity.w; + +END + + + + + + \ No newline at end of file diff --git a/VolumeRendering/vtkVolumeTextureMapper3D_OneComponentNoShadeFP.asm b/VolumeRendering/vtkVolumeTextureMapper3D_OneComponentNoShadeFP.asm new file mode 100644 index 0000000..d04bdc6 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D_OneComponentNoShadeFP.asm @@ -0,0 +1,37 @@ +!!ARBfp1.0 + +# This is the fragment program for one +# component data with no shading + +# We need some temporary variables +TEMP temp1, temp2, temp3; + +# We are going to use the first +# texture coordinate +ATTRIB tex0 = fragment.texcoord[0]; + +# This is our output color +OUTPUT out = result.color; + +# Look up the scalar value / gradient +# magnitude in the first volume +TEX temp1, tex0, texture[0], 3D; + +# Swizzle this to use (a,r) as texture +# coordinates +SWZ temp2, temp1, a, r, 1, 1; + +# Use this coordinate to look up a +# final color in the second texture +# (this is a 2D texture) +TEX temp3, temp2, texture[1], 2D; + +# That's our result and we are done +MOV out, temp3; +END + + + + + + \ No newline at end of file diff --git a/VolumeRendering/vtkVolumeTextureMapper3D_OneComponentShadeFP.asm b/VolumeRendering/vtkVolumeTextureMapper3D_OneComponentShadeFP.asm new file mode 100644 index 0000000..cf1ab9f --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D_OneComponentShadeFP.asm @@ -0,0 +1,96 @@ +!!ARBfp1.0 + +# This is the fragment program for one +# component data with shading + +# We need some temporary variables +TEMP index, normal, finalColor; +TEMP temp1, temp2, temp3; +TEMP sampleColor; +TEMP ndotl, ndoth, ndotv; +TEMP lightInfo, lightResult; + +# We are going to use the first +# texture coordinate +ATTRIB tex0 = fragment.texcoord[0]; + +# This is the lighting information +PARAM lightDirection = program.local[0]; +PARAM halfwayVector = program.local[1]; +PARAM coefficient = program.local[2]; +PARAM lightDiffColor = program.local[3]; +PARAM lightSpecColor = program.local[4]; +PARAM viewVector = program.local[5]; +PARAM constants = program.local[6]; + +# This is our output color +OUTPUT out = result.color; + +# Look up the scalar value / gradient +# magnitude in the first volume +TEX temp1, tex0, texture[0], 3D; + +# Look up the gradient direction +# in the third volume +TEX temp2, tex0, texture[2], 3D; + +# This normal is stored 0 to 1, change to -1 to 1 +# by multiplying by 2.0 then adding -1.0. +MAD normal, temp2, constants.x, constants.y; + +# Swizzle this to use (a,r) as texture +# coordinates +SWZ index, temp1, a, r, 1, 1; + +# Use this coordinate to look up a +# final color in the third texture +# (this is a 2D texture) +TEX sampleColor, index, texture[1], 2D; + +# Take the dot product of the light +# direction and the normal +DP3 ndotl, normal, lightDirection; + +# Take the dot product of the halfway +# vector and the normal +DP3 ndoth, normal, halfwayVector; + +DP3 ndotv, normal, viewVector; + +# flip if necessary for two sided lighting +MUL temp3, ndotl, constants.y; +CMP ndotl, ndotv, ndotl, temp3; +MUL temp3, ndoth, constants.y; +CMP ndoth, ndotv, ndoth, temp3; + +# put the pieces together for a LIT operation +MOV lightInfo.x, ndotl.x; +MOV lightInfo.y, ndoth.x; +MOV lightInfo.w, coefficient.w; + +# compute the lighting +LIT lightResult, lightInfo; + +# This is the ambient contribution +MUL finalColor, coefficient.x, sampleColor; + +# This is the diffuse contribution +MUL temp3, lightDiffColor, sampleColor; +MUL temp3, temp3, lightResult.y; +ADD finalColor, finalColor, temp3; + +# This is th specular contribution +MUL temp3, lightSpecColor, lightResult.z; + +# Add specular into result so far, and replace +# with the original alpha. +ADD out, finalColor, temp3; +MOV out.w, sampleColor.w; + +END + + + + + + \ No newline at end of file diff --git a/VolumeRendering/vtkVolumeTextureMapper3D_TwoDependentNoShadeFP.asm b/VolumeRendering/vtkVolumeTextureMapper3D_TwoDependentNoShadeFP.asm new file mode 100644 index 0000000..aa15a14 --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D_TwoDependentNoShadeFP.asm @@ -0,0 +1,46 @@ +!!ARBfp1.0 + +# This is the fragment program for two +# component dependent data with no shading + +# We need some temporary variables +TEMP temp1, temp2, temp3; +TEMP finalColor, finalOpacity; + +# We are going to use the first +# texture coordinate +ATTRIB tex0 = fragment.texcoord[0]; + +# This is our output color +OUTPUT out = result.color; + +# Look up the scalar values / gradient +# magnitude in the first volume +TEX temp1, tex0, texture[0], 3D; + +# Swizzle this to use (a,r) as texture +# coordinates for color, and (g,b) for +# opacity +SWZ temp2, temp1, a, r, 1, 1; +SWZ temp3, temp1, g, b, 1, 1; + +# Use the (a,r) coordinate to look up a +# final color in the second texture +# (this is a 2D texture) +TEX finalColor, temp2, texture[1], 2D; + +# Use the (g,b) coordinate to look up a +# final opacity in the fourth texture +# (this is a 2D texture) +TEX finalOpacity, temp3, texture[3], 2D; + +# Combine these into the result +MOV out, finalColor; +MOV out.w, finalOpacity.w; +END + + + + + + \ No newline at end of file diff --git a/VolumeRendering/vtkVolumeTextureMapper3D_TwoDependentShadeFP.asm b/VolumeRendering/vtkVolumeTextureMapper3D_TwoDependentShadeFP.asm new file mode 100644 index 0000000..a5c1c4d --- /dev/null +++ b/VolumeRendering/vtkVolumeTextureMapper3D_TwoDependentShadeFP.asm @@ -0,0 +1,100 @@ +!!ARBfp1.0 + +# This is the fragment program for two +# component dependent data with shading + +# We need some temporary variables +TEMP index1, index2, normal, finalColor; +TEMP temp1, temp2, temp3; +TEMP sampleColor, sampleOpacity; +TEMP ndotl, ndoth, ndotv; +TEMP lightInfo, lightResult; + +# We are going to use the first +# texture coordinate +ATTRIB tex0 = fragment.texcoord[0]; + +# This is the lighting information +PARAM lightDirection = program.local[0]; +PARAM halfwayVector = program.local[1]; +PARAM coefficient = program.local[2]; +PARAM lightDiffColor = program.local[3]; +PARAM lightSpecColor = program.local[4]; +PARAM viewVector = program.local[5]; +PARAM constants = program.local[6]; + +# This is our output color +OUTPUT out = result.color; + +# Look up the scalar values / gradient +# magnitude in the first volume +TEX temp1, tex0, texture[0], 3D; + +# Look up the gradient direction +# in the third volume +TEX temp2, tex0, texture[2], 3D; + +# This normal is stored 0 to 1, change to -1 to 1 +# by multiplying by 2.0 then adding -1.0. +MAD normal, temp2, constants.x, constants.y; + +# Swizzle this to use (a,r) as texture +# coordinates for color, and (g,b) for +# opacity +SWZ index1, temp1, a, r, 1, 1; +SWZ index2, temp1, g, b, 1, 1; + +# Use this coordinate to look up a +# final color in the second texture +# (this is a 2D texture) and the final +# opacity in the fourth texture. +TEX sampleColor, index1, texture[1], 2D; +TEX sampleOpacity, index2, texture[3], 2D; + +# Take the dot product of the light +# direction and the normal +DP3 ndotl, normal, lightDirection; + +# Take the dot product of the halfway +# vector and the normal +DP3 ndoth, normal, halfwayVector; + +DP3 ndotv, normal, viewVector; + +# flip if necessary for two sided lighting +MUL temp3, ndotl, constants.y; +CMP ndotl, ndotv, ndotl, temp3; +MUL temp3, ndoth, constants.y; +CMP ndoth, ndotv, ndoth, temp3; + +# put the pieces together for a LIT operation +MOV lightInfo.x, ndotl.x; +MOV lightInfo.y, ndoth.x; +MOV lightInfo.w, coefficient.w; + +# compute the lighting +LIT lightResult, lightInfo; + +# This is the ambient contribution +MUL finalColor, coefficient.x, sampleColor; + +# This is the diffuse contribution +MUL temp3, lightDiffColor, sampleColor; +MUL temp3, temp3, lightResult.y; +ADD finalColor, finalColor, temp3; + +# This is th specular contribution +MUL temp3, lightSpecColor, lightResult.z; + +# Add specular into result so far, and replace +# with the original alpha. +ADD out, finalColor, temp3; +MOV out.w, sampleOpacity.w; + +END + + + + + + \ No newline at end of file diff --git a/Widgets/CMakeLists.txt b/Widgets/CMakeLists.txt new file mode 100644 index 0000000..7afbda8 --- /dev/null +++ b/Widgets/CMakeLists.txt @@ -0,0 +1,44 @@ +SET(KIT Widgets) +SET(UKIT WIDGETS) + +SET(KIT_TCL_LIBS vtkRenderingTCL vtkHybridTCL) +SET(KIT_PYTHON_LIBS vtkRenderingPythonD vtkHybridPythonD) +SET(KIT_JAVA_LIBS vtkRenderingJava vtkHybridJava) +SET(KIT_LIBS vtkRendering vtkHybrid) + +SET ( Kit_SRCS +vtk3DWidget.cxx +vtkBoxWidget.cxx +vtkImagePlaneWidget.cxx +vtkImageTracerWidget.cxx +vtkImplicitPlaneWidget.cxx +vtkLineWidget.cxx +vtkOrientationMarkerWidget.cxx +vtkPlaneWidget.cxx +vtkPointWidget.cxx +vtkPolyDataSourceWidget.cxx +vtkScalarBarWidget.cxx +vtkSphereWidget.cxx +vtkSplineWidget.cxx +vtkXYPlotWidget.cxx +) + +SET_SOURCE_FILES_PROPERTIES( +vtk3DWidget +vtkPolyDataSourceWidget +ABSTRACT +) + +SET(Kit_EXTRA_SRCS) +SET(Kit_EXTRA_CMDS) +SET(Kit_TCL_EXTRA_SRCS) +SET(Kit_PYTHON_EXTRA_SRCS) +SET(Kit_JAVA_EXTRA_SRCS) +SET(KIT_TCL_DEPS) +SET(KIT_PYTHON_DEPS) +SET(KIT_JAVA_DEPS) + +#----------------------------------------------------------------------------- +# Include CMake code common to all kits. +INCLUDE(${VTK_SOURCE_DIR}/CMake/KitCommonBlock.cmake) +#----------------------------------------------------------------------------- diff --git a/Widgets/Testing/CMakeLists.txt b/Widgets/Testing/CMakeLists.txt new file mode 100644 index 0000000..d0999ee --- /dev/null +++ b/Widgets/Testing/CMakeLists.txt @@ -0,0 +1,17 @@ +SUBDIRS(Cxx) + +IF (VTK_WRAP_TCL) +# SUBDIRS(Tcl) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + SUBDIRS(Python) +ENDIF (VTK_WRAP_PYTHON) + +IF(PYTHON_EXECUTABLE) + ADD_TEST(HeaderTesting-Widgets ${PYTHON_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py + "${VTK_SOURCE_DIR}/Widgets" + VTK_WIDGETS_EXPORT + ) +ENDIF(PYTHON_EXECUTABLE) diff --git a/Widgets/Testing/Cxx/BoxWidget.cxx b/Widgets/Testing/Cxx/BoxWidget.cxx new file mode 100644 index 0000000..cfbb40f --- /dev/null +++ b/Widgets/Testing/Cxx/BoxWidget.cxx @@ -0,0 +1,546 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: BoxWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkAppendPolyData.h" +#include "vtkBoxWidget.h" +#include "vtkCommand.h" +#include "vtkConeSource.h" +#include "vtkGlyph3D.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" + +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +// Callback for the interaction +class vtkBWCallback : public vtkCommand +{ +public: + static vtkBWCallback *New() + { return new vtkBWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkBoxWidget *boxWidget = reinterpret_cast<vtkBoxWidget*>(caller); + boxWidget->GetTransform(this->Transform); + this->Actor->SetUserTransform(this->Transform); + } + vtkBWCallback():Transform(0),Actor(0) {} + vtkTransform *Transform; + vtkActor *Actor; +}; + +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char BoxWidgetEventLog[] = +"# StreamVersion 1\n" +"CharEvent 187 242 0 0 105 1 i\n" +"KeyReleaseEvent 187 242 0 0 105 1 i\n" +"MouseMoveEvent 187 241 0 0 0 0 i\n" +"MouseMoveEvent 186 241 0 0 0 0 i\n" +"MouseMoveEvent 184 241 0 0 0 0 i\n" +"MouseMoveEvent 182 242 0 0 0 0 i\n" +"MouseMoveEvent 178 242 0 0 0 0 i\n" +"MouseMoveEvent 177 243 0 0 0 0 i\n" +"MouseMoveEvent 175 244 0 0 0 0 i\n" +"MouseMoveEvent 174 244 0 0 0 0 i\n" +"MouseMoveEvent 173 245 0 0 0 0 i\n" +"MouseMoveEvent 172 245 0 0 0 0 i\n" +"MouseMoveEvent 171 245 0 0 0 0 i\n" +"MouseMoveEvent 170 246 0 0 0 0 i\n" +"MouseMoveEvent 169 246 0 0 0 0 i\n" +"MouseMoveEvent 168 246 0 0 0 0 i\n" +"MouseMoveEvent 167 246 0 0 0 0 i\n" +"MouseMoveEvent 166 246 0 0 0 0 i\n" +"MouseMoveEvent 165 246 0 0 0 0 i\n" +"MouseMoveEvent 164 246 0 0 0 0 i\n" +"MouseMoveEvent 163 246 0 0 0 0 i\n" +"MouseMoveEvent 162 246 0 0 0 0 i\n" +"MouseMoveEvent 161 246 0 0 0 0 i\n" +"MouseMoveEvent 160 247 0 0 0 0 i\n" +"MouseMoveEvent 159 248 0 0 0 0 i\n" +"MouseMoveEvent 158 248 0 0 0 0 i\n" +"MouseMoveEvent 156 248 0 0 0 0 i\n" +"MouseMoveEvent 155 249 0 0 0 0 i\n" +"MouseMoveEvent 155 250 0 0 0 0 i\n" +"MouseMoveEvent 155 251 0 0 0 0 i\n" +"MouseMoveEvent 155 252 0 0 0 0 i\n" +"MouseMoveEvent 154 252 0 0 0 0 i\n" +"MouseMoveEvent 153 252 0 0 0 0 i\n" +"MouseMoveEvent 153 253 0 0 0 0 i\n" +"LeftButtonPressEvent 153 253 0 0 0 0 i\n" +"MouseMoveEvent 153 252 0 0 0 0 i\n" +"MouseMoveEvent 154 252 0 0 0 0 i\n" +"MouseMoveEvent 155 251 0 0 0 0 i\n" +"MouseMoveEvent 155 250 0 0 0 0 i\n" +"MouseMoveEvent 155 249 0 0 0 0 i\n" +"MouseMoveEvent 155 248 0 0 0 0 i\n" +"MouseMoveEvent 155 247 0 0 0 0 i\n" +"MouseMoveEvent 155 246 0 0 0 0 i\n" +"MouseMoveEvent 155 245 0 0 0 0 i\n" +"MouseMoveEvent 155 244 0 0 0 0 i\n" +"MouseMoveEvent 155 243 0 0 0 0 i\n" +"MouseMoveEvent 155 242 0 0 0 0 i\n" +"MouseMoveEvent 155 241 0 0 0 0 i\n" +"MouseMoveEvent 155 240 0 0 0 0 i\n" +"MouseMoveEvent 155 239 0 0 0 0 i\n" +"MouseMoveEvent 155 238 0 0 0 0 i\n" +"MouseMoveEvent 155 237 0 0 0 0 i\n" +"MouseMoveEvent 155 236 0 0 0 0 i\n" +"MouseMoveEvent 155 235 0 0 0 0 i\n" +"MouseMoveEvent 155 234 0 0 0 0 i\n" +"MouseMoveEvent 155 232 0 0 0 0 i\n" +"MouseMoveEvent 155 231 0 0 0 0 i\n" +"MouseMoveEvent 155 230 0 0 0 0 i\n" +"MouseMoveEvent 155 229 0 0 0 0 i\n" +"MouseMoveEvent 155 228 0 0 0 0 i\n" +"MouseMoveEvent 154 228 0 0 0 0 i\n" +"LeftButtonReleaseEvent 154 228 0 0 0 0 i\n" +"MouseMoveEvent 154 228 0 0 0 0 i\n" +"MouseMoveEvent 154 227 0 0 0 0 i\n" +"MouseMoveEvent 153 226 0 0 0 0 i\n" +"MouseMoveEvent 151 226 0 0 0 0 i\n" +"MouseMoveEvent 150 225 0 0 0 0 i\n" +"MouseMoveEvent 148 223 0 0 0 0 i\n" +"MouseMoveEvent 146 223 0 0 0 0 i\n" +"MouseMoveEvent 144 222 0 0 0 0 i\n" +"MouseMoveEvent 143 222 0 0 0 0 i\n" +"MouseMoveEvent 143 221 0 0 0 0 i\n" +"MouseMoveEvent 141 221 0 0 0 0 i\n" +"MouseMoveEvent 137 219 0 0 0 0 i\n" +"MouseMoveEvent 130 216 0 0 0 0 i\n" +"MouseMoveEvent 120 212 0 0 0 0 i\n" +"MouseMoveEvent 111 209 0 0 0 0 i\n" +"MouseMoveEvent 100 204 0 0 0 0 i\n" +"MouseMoveEvent 97 204 0 0 0 0 i\n" +"MouseMoveEvent 96 202 0 0 0 0 i\n" +"MouseMoveEvent 96 201 0 0 0 0 i\n" +"MouseMoveEvent 96 200 0 0 0 0 i\n" +"MouseMoveEvent 96 199 0 0 0 0 i\n" +"MouseMoveEvent 96 198 0 0 0 0 i\n" +"MouseMoveEvent 96 197 0 0 0 0 i\n" +"MouseMoveEvent 96 196 0 0 0 0 i\n" +"LeftButtonPressEvent 96 196 0 0 0 0 i\n" +"MouseMoveEvent 96 195 0 0 0 0 i\n" +"MouseMoveEvent 96 194 0 0 0 0 i\n" +"MouseMoveEvent 96 193 0 0 0 0 i\n" +"MouseMoveEvent 96 192 0 0 0 0 i\n" +"MouseMoveEvent 96 191 0 0 0 0 i\n" +"MouseMoveEvent 96 190 0 0 0 0 i\n" +"MouseMoveEvent 96 189 0 0 0 0 i\n" +"MouseMoveEvent 96 188 0 0 0 0 i\n" +"MouseMoveEvent 97 188 0 0 0 0 i\n" +"MouseMoveEvent 97 187 0 0 0 0 i\n" +"MouseMoveEvent 98 186 0 0 0 0 i\n" +"MouseMoveEvent 98 185 0 0 0 0 i\n" +"MouseMoveEvent 99 185 0 0 0 0 i\n" +"MouseMoveEvent 99 184 0 0 0 0 i\n" +"MouseMoveEvent 99 182 0 0 0 0 i\n" +"MouseMoveEvent 100 182 0 0 0 0 i\n" +"MouseMoveEvent 101 179 0 0 0 0 i\n" +"MouseMoveEvent 103 178 0 0 0 0 i\n" +"MouseMoveEvent 106 177 0 0 0 0 i\n" +"MouseMoveEvent 109 177 0 0 0 0 i\n" +"MouseMoveEvent 112 176 0 0 0 0 i\n" +"MouseMoveEvent 115 175 0 0 0 0 i\n" +"MouseMoveEvent 117 174 0 0 0 0 i\n" +"MouseMoveEvent 118 174 0 0 0 0 i\n" +"MouseMoveEvent 119 174 0 0 0 0 i\n" +"MouseMoveEvent 119 173 0 0 0 0 i\n" +"MouseMoveEvent 120 173 0 0 0 0 i\n" +"MouseMoveEvent 121 172 0 0 0 0 i\n" +"MouseMoveEvent 121 171 0 0 0 0 i\n" +"MouseMoveEvent 122 171 0 0 0 0 i\n" +"MouseMoveEvent 123 171 0 0 0 0 i\n" +"MouseMoveEvent 123 170 0 0 0 0 i\n" +"MouseMoveEvent 124 170 0 0 0 0 i\n" +"MouseMoveEvent 125 170 0 0 0 0 i\n" +"MouseMoveEvent 125 169 0 0 0 0 i\n" +"MouseMoveEvent 128 169 0 0 0 0 i\n" +"MouseMoveEvent 129 168 0 0 0 0 i\n" +"MouseMoveEvent 130 168 0 0 0 0 i\n" +"MouseMoveEvent 132 168 0 0 0 0 i\n" +"MouseMoveEvent 133 168 0 0 0 0 i\n" +"MouseMoveEvent 135 167 0 0 0 0 i\n" +"MouseMoveEvent 136 167 0 0 0 0 i\n" +"MouseMoveEvent 137 167 0 0 0 0 i\n" +"MouseMoveEvent 138 167 0 0 0 0 i\n" +"MouseMoveEvent 140 168 0 0 0 0 i\n" +"MouseMoveEvent 141 168 0 0 0 0 i\n" +"MouseMoveEvent 142 168 0 0 0 0 i\n" +"MouseMoveEvent 142 167 0 0 0 0 i\n" +"MouseMoveEvent 143 167 0 0 0 0 i\n" +"MouseMoveEvent 144 167 0 0 0 0 i\n" +"MouseMoveEvent 145 166 0 0 0 0 i\n" +"MouseMoveEvent 146 166 0 0 0 0 i\n" +"MouseMoveEvent 147 166 0 0 0 0 i\n" +"MouseMoveEvent 148 166 0 0 0 0 i\n" +"MouseMoveEvent 149 166 0 0 0 0 i\n" +"MouseMoveEvent 150 167 0 0 0 0 i\n" +"MouseMoveEvent 151 167 0 0 0 0 i\n" +"MouseMoveEvent 152 167 0 0 0 0 i\n" +"MouseMoveEvent 152 168 0 0 0 0 i\n" +"MouseMoveEvent 153 168 0 0 0 0 i\n" +"MouseMoveEvent 153 167 0 0 0 0 i\n" +"MouseMoveEvent 154 167 0 0 0 0 i\n" +"MouseMoveEvent 155 167 0 0 0 0 i\n" +"LeftButtonReleaseEvent 155 167 0 0 0 0 i\n" +"MouseMoveEvent 155 167 0 0 0 0 i\n" +"MouseMoveEvent 155 166 0 0 0 0 i\n" +"MouseMoveEvent 156 166 0 0 0 0 i\n" +"MouseMoveEvent 158 166 0 0 0 0 i\n" +"MouseMoveEvent 159 167 0 0 0 0 i\n" +"MouseMoveEvent 159 168 0 0 0 0 i\n" +"MouseMoveEvent 159 169 0 0 0 0 i\n" +"MouseMoveEvent 158 169 0 0 0 0 i\n" +"MouseMoveEvent 158 170 0 0 0 0 i\n" +"MouseMoveEvent 157 170 0 0 0 0 i\n" +"MouseMoveEvent 157 171 0 0 0 0 i\n" +"MouseMoveEvent 156 172 0 0 0 0 i\n" +"RightButtonPressEvent 156 172 0 0 0 0 i\n" +"MouseMoveEvent 156 173 0 0 0 0 i\n" +"MouseMoveEvent 155 173 0 0 0 0 i\n" +"MouseMoveEvent 153 173 0 0 0 0 i\n" +"MouseMoveEvent 150 174 0 0 0 0 i\n" +"MouseMoveEvent 150 176 0 0 0 0 i\n" +"MouseMoveEvent 149 177 0 0 0 0 i\n" +"MouseMoveEvent 148 178 0 0 0 0 i\n" +"MouseMoveEvent 148 181 0 0 0 0 i\n" +"MouseMoveEvent 147 184 0 0 0 0 i\n" +"MouseMoveEvent 147 186 0 0 0 0 i\n" +"MouseMoveEvent 147 187 0 0 0 0 i\n" +"MouseMoveEvent 146 187 0 0 0 0 i\n" +"MouseMoveEvent 146 188 0 0 0 0 i\n" +"MouseMoveEvent 146 189 0 0 0 0 i\n" +"MouseMoveEvent 145 190 0 0 0 0 i\n" +"MouseMoveEvent 144 190 0 0 0 0 i\n" +"MouseMoveEvent 143 192 0 0 0 0 i\n" +"MouseMoveEvent 141 194 0 0 0 0 i\n" +"MouseMoveEvent 140 194 0 0 0 0 i\n" +"MouseMoveEvent 140 195 0 0 0 0 i\n" +"MouseMoveEvent 139 195 0 0 0 0 i\n" +"MouseMoveEvent 138 195 0 0 0 0 i\n" +"MouseMoveEvent 137 196 0 0 0 0 i\n" +"MouseMoveEvent 137 197 0 0 0 0 i\n" +"MouseMoveEvent 137 198 0 0 0 0 i\n" +"MouseMoveEvent 137 199 0 0 0 0 i\n" +"MouseMoveEvent 137 200 0 0 0 0 i\n" +"MouseMoveEvent 137 201 0 0 0 0 i\n" +"MouseMoveEvent 138 202 0 0 0 0 i\n" +"MouseMoveEvent 138 203 0 0 0 0 i\n" +"MouseMoveEvent 139 203 0 0 0 0 i\n" +"MouseMoveEvent 140 203 0 0 0 0 i\n" +"MouseMoveEvent 141 202 0 0 0 0 i\n" +"MouseMoveEvent 142 202 0 0 0 0 i\n" +"MouseMoveEvent 145 203 0 0 0 0 i\n" +"MouseMoveEvent 149 204 0 0 0 0 i\n" +"MouseMoveEvent 150 205 0 0 0 0 i\n" +"MouseMoveEvent 151 205 0 0 0 0 i\n" +"RightButtonReleaseEvent 151 205 0 0 0 0 i\n" +"MouseMoveEvent 151 205 0 0 0 0 i\n" +"MouseMoveEvent 151 204 0 0 0 0 i\n" +"MouseMoveEvent 150 204 0 0 0 0 i\n" +"RightButtonPressEvent 150 204 0 0 0 0 i\n" +"MouseMoveEvent 150 203 0 0 0 0 i\n" +"MouseMoveEvent 150 202 0 0 0 0 i\n" +"MouseMoveEvent 151 201 0 0 0 0 i\n" +"MouseMoveEvent 152 201 0 0 0 0 i\n" +"MouseMoveEvent 152 200 0 0 0 0 i\n" +"MouseMoveEvent 153 200 0 0 0 0 i\n" +"MouseMoveEvent 153 199 0 0 0 0 i\n" +"MouseMoveEvent 153 198 0 0 0 0 i\n" +"MouseMoveEvent 153 196 0 0 0 0 i\n" +"MouseMoveEvent 153 195 0 0 0 0 i\n" +"MouseMoveEvent 153 194 0 0 0 0 i\n" +"MouseMoveEvent 153 191 0 0 0 0 i\n" +"MouseMoveEvent 153 190 0 0 0 0 i\n" +"MouseMoveEvent 153 189 0 0 0 0 i\n" +"MouseMoveEvent 153 188 0 0 0 0 i\n" +"MouseMoveEvent 153 187 0 0 0 0 i\n" +"MouseMoveEvent 153 186 0 0 0 0 i\n" +"MouseMoveEvent 153 185 0 0 0 0 i\n" +"MouseMoveEvent 153 183 0 0 0 0 i\n" +"MouseMoveEvent 153 182 0 0 0 0 i\n" +"MouseMoveEvent 153 181 0 0 0 0 i\n" +"MouseMoveEvent 153 180 0 0 0 0 i\n" +"MouseMoveEvent 153 179 0 0 0 0 i\n" +"MouseMoveEvent 153 178 0 0 0 0 i\n" +"MouseMoveEvent 153 177 0 0 0 0 i\n" +"MouseMoveEvent 153 176 0 0 0 0 i\n" +"MouseMoveEvent 153 175 0 0 0 0 i\n" +"MouseMoveEvent 153 176 0 0 0 0 i\n" +"RightButtonReleaseEvent 153 176 0 0 0 0 i\n" +"MouseMoveEvent 153 176 0 0 0 0 i\n" +"MouseMoveEvent 154 176 0 0 0 0 i\n" +"MouseMoveEvent 156 177 0 0 0 0 i\n" +"MouseMoveEvent 156 178 0 0 0 0 i\n" +"MouseMoveEvent 156 179 0 0 0 0 i\n" +"MouseMoveEvent 156 180 0 0 0 0 i\n" +"MouseMoveEvent 155 180 0 0 0 0 i\n" +"MiddleButtonPressEvent 155 180 0 0 0 0 i\n" +"MouseMoveEvent 154 180 0 0 0 0 i\n" +"MouseMoveEvent 154 181 0 0 0 0 i\n" +"MouseMoveEvent 153 181 0 0 0 0 i\n" +"MouseMoveEvent 152 181 0 0 0 0 i\n" +"MouseMoveEvent 151 181 0 0 0 0 i\n" +"MouseMoveEvent 148 181 0 0 0 0 i\n" +"MouseMoveEvent 141 182 0 0 0 0 i\n" +"MouseMoveEvent 139 181 0 0 0 0 i\n" +"MouseMoveEvent 139 182 0 0 0 0 i\n" +"MouseMoveEvent 138 183 0 0 0 0 i\n" +"MouseMoveEvent 138 184 0 0 0 0 i\n" +"MouseMoveEvent 139 185 0 0 0 0 i\n" +"MouseMoveEvent 140 186 0 0 0 0 i\n" +"MouseMoveEvent 141 186 0 0 0 0 i\n" +"MouseMoveEvent 143 186 0 0 0 0 i\n" +"MouseMoveEvent 147 189 0 0 0 0 i\n" +"MouseMoveEvent 151 189 0 0 0 0 i\n" +"MouseMoveEvent 153 190 0 0 0 0 i\n" +"MouseMoveEvent 154 190 0 0 0 0 i\n" +"MouseMoveEvent 155 191 0 0 0 0 i\n" +"MouseMoveEvent 156 192 0 0 0 0 i\n" +"MouseMoveEvent 157 192 0 0 0 0 i\n" +"MouseMoveEvent 157 193 0 0 0 0 i\n" +"MouseMoveEvent 158 194 0 0 0 0 i\n" +"MouseMoveEvent 159 194 0 0 0 0 i\n" +"MouseMoveEvent 159 195 0 0 0 0 i\n" +"MouseMoveEvent 160 195 0 0 0 0 i\n" +"MouseMoveEvent 160 197 0 0 0 0 i\n" +"MouseMoveEvent 162 198 0 0 0 0 i\n" +"MouseMoveEvent 166 199 0 0 0 0 i\n" +"MouseMoveEvent 167 200 0 0 0 0 i\n" +"MouseMoveEvent 168 200 0 0 0 0 i\n" +"MouseMoveEvent 168 201 0 0 0 0 i\n" +"MouseMoveEvent 168 202 0 0 0 0 i\n" +"MouseMoveEvent 168 203 0 0 0 0 i\n" +"MouseMoveEvent 168 204 0 0 0 0 i\n" +"MouseMoveEvent 168 205 0 0 0 0 i\n" +"MouseMoveEvent 167 205 0 0 0 0 i\n" +"MouseMoveEvent 167 206 0 0 0 0 i\n" +"MouseMoveEvent 166 208 0 0 0 0 i\n" +"MouseMoveEvent 165 209 0 0 0 0 i\n" +"MouseMoveEvent 165 210 0 0 0 0 i\n" +"MouseMoveEvent 164 210 0 0 0 0 i\n" +"MouseMoveEvent 164 211 0 0 0 0 i\n" +"MouseMoveEvent 165 211 0 0 0 0 i\n" +"MouseMoveEvent 165 212 0 0 0 0 i\n" +"MouseMoveEvent 166 212 0 0 0 0 i\n" +"MouseMoveEvent 166 213 0 0 0 0 i\n" +"MouseMoveEvent 166 214 0 0 0 0 i\n" +"MouseMoveEvent 166 215 0 0 0 0 i\n" +"MouseMoveEvent 166 216 0 0 0 0 i\n" +"MouseMoveEvent 166 217 0 0 0 0 i\n" +"MouseMoveEvent 167 218 0 0 0 0 i\n" +"MouseMoveEvent 168 218 0 0 0 0 i\n" +"MouseMoveEvent 168 219 0 0 0 0 i\n" +"MouseMoveEvent 169 220 0 0 0 0 i\n" +"MouseMoveEvent 169 221 0 0 0 0 i\n" +"MouseMoveEvent 169 222 0 0 0 0 i\n" +"MouseMoveEvent 169 223 0 0 0 0 i\n" +"MouseMoveEvent 169 224 0 0 0 0 i\n" +"MouseMoveEvent 169 223 0 0 0 0 i\n" +"MouseMoveEvent 170 222 0 0 0 0 i\n" +"MouseMoveEvent 170 221 0 0 0 0 i\n" +"MiddleButtonReleaseEvent 170 221 0 0 0 0 i\n" +"MouseMoveEvent 170 221 0 0 0 0 i\n" +"MouseMoveEvent 170 220 0 0 0 0 i\n" +"MouseMoveEvent 170 219 0 0 0 0 i\n" +"MouseMoveEvent 170 218 0 0 0 0 i\n" +"MouseMoveEvent 170 217 0 0 0 0 i\n" +"MouseMoveEvent 169 216 0 0 0 0 i\n" +"MouseMoveEvent 168 216 0 0 0 0 i\n" +"MouseMoveEvent 168 215 0 0 0 0 i\n" +"MouseMoveEvent 167 214 0 0 0 0 i\n" +"MouseMoveEvent 164 214 0 0 0 0 i\n" +"MouseMoveEvent 163 213 0 0 0 0 i\n" +"MouseMoveEvent 163 212 0 0 0 0 i\n" +"MouseMoveEvent 162 210 0 0 0 0 i\n" +"MouseMoveEvent 162 209 0 0 0 0 i\n" +"MouseMoveEvent 162 206 0 0 0 0 i\n" +"MouseMoveEvent 161 202 0 0 0 0 i\n" +"MouseMoveEvent 160 197 0 0 0 0 i\n" +"MouseMoveEvent 160 192 0 0 0 0 i\n" +"MouseMoveEvent 160 187 0 0 0 0 i\n" +"MouseMoveEvent 158 182 0 0 0 0 i\n" +"MouseMoveEvent 157 174 0 0 0 0 i\n" +"MouseMoveEvent 156 169 0 0 0 0 i\n" +"MouseMoveEvent 156 164 0 0 0 0 i\n" +"MouseMoveEvent 156 157 0 0 0 0 i\n" +"MouseMoveEvent 156 156 0 0 0 0 i\n" +"MouseMoveEvent 156 152 0 0 0 0 i\n" +"MouseMoveEvent 156 151 0 0 0 0 i\n" +"MouseMoveEvent 156 148 0 0 0 0 i\n" +"MouseMoveEvent 156 146 0 0 0 0 i\n" +"MouseMoveEvent 156 145 0 0 0 0 i\n" +"MouseMoveEvent 156 143 0 0 0 0 i\n" +"MouseMoveEvent 156 142 0 0 0 0 i\n" +"MouseMoveEvent 156 141 0 0 0 0 i\n" +"MouseMoveEvent 155 140 0 0 0 0 i\n" +"MouseMoveEvent 154 140 0 0 0 0 i\n" +"MouseMoveEvent 154 139 0 0 0 0 i\n" +"MouseMoveEvent 151 137 0 0 0 0 i\n" +"MouseMoveEvent 149 136 0 0 0 0 i\n" +"MouseMoveEvent 147 135 0 0 0 0 i\n" +"MouseMoveEvent 144 132 0 0 0 0 i\n" +"MouseMoveEvent 143 132 0 0 0 0 i\n" +"MouseMoveEvent 143 131 0 0 0 0 i\n" +"MouseMoveEvent 143 130 0 0 0 0 i\n" +"LeftButtonPressEvent 143 130 0 0 0 0 i\n" +"MouseMoveEvent 143 129 0 0 0 0 i\n" +"MouseMoveEvent 143 126 0 0 0 0 i\n" +"MouseMoveEvent 143 125 0 0 0 0 i\n" +"MouseMoveEvent 143 123 0 0 0 0 i\n" +"MouseMoveEvent 143 120 0 0 0 0 i\n" +"MouseMoveEvent 143 118 0 0 0 0 i\n" +"MouseMoveEvent 143 116 0 0 0 0 i\n" +"MouseMoveEvent 143 115 0 0 0 0 i\n" +"MouseMoveEvent 142 115 0 0 0 0 i\n" +"MouseMoveEvent 142 114 0 0 0 0 i\n" +"MouseMoveEvent 142 113 0 0 0 0 i\n" +"MouseMoveEvent 141 113 0 0 0 0 i\n" +"MouseMoveEvent 141 112 0 0 0 0 i\n" +"MouseMoveEvent 141 111 0 0 0 0 i\n" +"MouseMoveEvent 141 110 0 0 0 0 i\n" +"MouseMoveEvent 140 109 0 0 0 0 i\n" +"MouseMoveEvent 140 108 0 0 0 0 i\n" +"MouseMoveEvent 139 108 0 0 0 0 i\n" +"MouseMoveEvent 138 107 0 0 0 0 i\n" +"MouseMoveEvent 137 104 0 0 0 0 i\n" +"MouseMoveEvent 137 103 0 0 0 0 i\n" +"MouseMoveEvent 137 102 0 0 0 0 i\n" +"MouseMoveEvent 137 101 0 0 0 0 i\n" +"MouseMoveEvent 137 100 0 0 0 0 i\n" +"MouseMoveEvent 137 99 0 0 0 0 i\n" +"MouseMoveEvent 137 98 0 0 0 0 i\n" +"MouseMoveEvent 137 97 0 0 0 0 i\n" +"MouseMoveEvent 137 96 0 0 0 0 i\n" +"MouseMoveEvent 137 95 0 0 0 0 i\n" +"MouseMoveEvent 137 94 0 0 0 0 i\n" +"MouseMoveEvent 137 93 0 0 0 0 i\n" +"MouseMoveEvent 137 92 0 0 0 0 i\n" +"MouseMoveEvent 137 91 0 0 0 0 i\n" +"MouseMoveEvent 137 90 0 0 0 0 i\n" +"MouseMoveEvent 136 89 0 0 0 0 i\n" +"MouseMoveEvent 136 88 0 0 0 0 i\n" +"LeftButtonReleaseEvent 136 88 0 0 0 0 i\n" +"MouseMoveEvent 136 88 0 0 0 0 i\n" +"MouseMoveEvent 136 89 0 0 0 0 i\n" +"MouseMoveEvent 136 91 0 0 0 0 i\n" +"MouseMoveEvent 136 92 0 0 0 0 i\n" +"MouseMoveEvent 136 91 0 0 0 0 i\n" +"MouseMoveEvent 136 90 0 0 0 0 i\n" +"MouseMoveEvent 136 89 0 0 0 0 i\n" +"MouseMoveEvent 136 90 0 0 0 0 i\n" +"MouseMoveEvent 136 91 0 0 0 0 i\n" +"MouseMoveEvent 136 92 0 0 0 0 i\n" +"MouseMoveEvent 135 93 0 0 0 0 i\n" +; + +int BoxWidget( int argc, char *argv[] ) +{ + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkBoxWidget *boxWidget = vtkBoxWidget::New(); + boxWidget->SetInteractor( iren ); + boxWidget->SetPlaceFactor( 1.25 ); + + vtkConeSource *cone = vtkConeSource::New(); + cone->SetResolution(6); + vtkSphereSource *sphere = vtkSphereSource::New(); + sphere->SetThetaResolution(8); sphere->SetPhiResolution(8); + vtkGlyph3D *glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(sphere->GetOutputPort()); + glyph->SetSource(cone->GetOutput()); + glyph->SetVectorModeToUseNormal(); + glyph->SetScaleModeToScaleByVector(); + glyph->SetScaleFactor(0.25); + + vtkAppendPolyData *append = vtkAppendPolyData::New(); + append->AddInput(glyph->GetOutput()); + append->AddInput(sphere->GetOutput()); + + vtkPolyDataMapper *maceMapper = vtkPolyDataMapper::New(); + maceMapper->SetInputConnection(append->GetOutputPort()); + + vtkActor *maceActor = vtkActor::New(); + maceActor->SetMapper(maceMapper); + + renderer->AddActor(maceActor); + renderer->SetBackground(0,0,0); + renWin->SetSize(300,300); + + // Configure the box widget including callbacks + vtkTransform *t = vtkTransform::New(); + boxWidget->SetProp3D(maceActor); + boxWidget->PlaceWidget(); + + vtkBWCallback *myCallback = vtkBWCallback::New(); + myCallback->Transform = t; + myCallback->Actor = maceActor; + boxWidget->AddObserver(vtkCommand::InteractionEvent,myCallback); + + // record events + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); +// recorder->SetFileName("c:/record.log"); +// recorder->Record(); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(BoxWidgetEventLog); + + // interact with data + // render the image + // + iren->Initialize(); + renWin->Render(); + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + recorder->Off(); + recorder->Delete(); + t->Delete(); + myCallback->Delete(); + boxWidget->Delete(); + sphere->Delete(); + cone->Delete(); + glyph->Delete(); + append->Delete(); + maceMapper->Delete(); + maceActor->Delete(); + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/CMakeLists.txt b/Widgets/Testing/Cxx/CMakeLists.txt new file mode 100644 index 0000000..43b447b --- /dev/null +++ b/Widgets/Testing/Cxx/CMakeLists.txt @@ -0,0 +1,56 @@ +SET(KIT Widgets) +# add tests that do not require data +SET(MyTests + BoxWidget.cxx + TestImplicitPlaneWidget.cxx + TestOrientationMarkerWidget.cxx + ) +IF (VTK_DATA_ROOT) + # add tests that require data + SET(MyTests ${MyTests} + ImagePlaneWidget.cxx + TestSplineWidget.cxx + TestScalarBarWidget.cxx + TestLineWidget.cxx + TestPlaneWidget.cxx + TestPointWidget.cxx + TestImageTracerWidget.cxx + ) +ENDIF (VTK_DATA_ROOT) + +# remove some tests if there is no display +IF(NOT VTK_USE_DISPLAY) + REMOVE(MyTests + BoxWidget.cxx + TestImplicitPlaneWidget.cxx + TestOrientationMarkerWidget.cxx + ImagePlaneWidget.cxx + TestSplineWidget.cxx + TestScalarBarWidget.cxx + TestLineWidget.cxx + TestPlaneWidget.cxx + TestPointWidget.cxx + TestImageTracerWidget.cxx + ) +ENDIF(NOT VTK_USE_DISPLAY) + +CREATE_TEST_SOURCELIST(Tests ${KIT}CxxTests.cxx ${MyTests} + EXTRA_INCLUDE vtkTestDriver.h) + +ADD_EXECUTABLE(${KIT}CxxTests ${Tests}) +TARGET_LINK_LIBRARIES(${KIT}CxxTests vtkWidgets) +SET (TestsToRun ${Tests}) +REMOVE (TestsToRun ${KIT}CxxTests.cxx) + +# +# Add all the executables +FOREACH (test ${TestsToRun}) + GET_FILENAME_COMPONENT(TName ${test} NAME_WE) + IF (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName} + -D ${VTK_DATA_ROOT} + -V Baseline/${KIT}/${TName}.png) + ELSE (VTK_DATA_ROOT) + ADD_TEST(${TName} ${CXX_TEST_PATH}/${KIT}CxxTests ${TName}) + ENDIF (VTK_DATA_ROOT) +ENDFOREACH (test) diff --git a/Widgets/Testing/Cxx/ImagePlaneWidget.cxx b/Widgets/Testing/Cxx/ImagePlaneWidget.cxx new file mode 100644 index 0000000..b13bc3f --- /dev/null +++ b/Widgets/Testing/Cxx/ImagePlaneWidget.cxx @@ -0,0 +1,529 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: ImagePlaneWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCellPicker.h" +#include "vtkCommand.h" +#include "vtkImageActor.h" +#include "vtkImageMapToColors.h" +#include "vtkImagePlaneWidget.h" +#include "vtkImageReader.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkLookupTable.h" +#include "vtkOutlineFilter.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkVolume16Reader.h" +#include "vtkImageData.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char IPWeventLog[] = +"# StreamVersion 1\n" +"CharEvent 179 195 0 0 98 1 i\n" +"MiddleButtonPressEvent 179 195 0 0 0 0 i\n" +"MouseMoveEvent 179 190 0 0 0 0 i\n" +"MouseMoveEvent 179 185 0 0 0 0 i\n" +"MouseMoveEvent 179 180 0 0 0 0 i\n" +"MouseMoveEvent 179 175 0 0 0 0 i\n" +"MouseMoveEvent 179 170 0 0 0 0 i\n" +"MouseMoveEvent 179 165 0 0 0 0 i\n" +"MouseMoveEvent 179 160 0 0 0 0 i\n" +"MouseMoveEvent 179 155 0 0 0 0 i\n" +"MouseMoveEvent 179 150 0 0 0 0 i\n" +"MouseMoveEvent 179 145 0 0 0 0 i\n" +"MouseMoveEvent 179 140 0 0 0 0 i\n" +"MouseMoveEvent 179 135 0 0 0 0 i\n" +"MiddleButtonReleaseEvent 179 135 0 0 0 0 i\n" +"RightButtonPressEvent 179 135 0 0 0 0 i\n" +"MouseMoveEvent 180 135 0 0 0 0 i\n" +"MouseMoveEvent 180 140 0 0 0 0 i\n" +"MouseMoveEvent 180 145 0 0 0 0 i\n" +"MouseMoveEvent 180 150 0 0 0 0 i\n" +"MouseMoveEvent 180 155 0 0 0 0 i\n" +"MouseMoveEvent 181 160 0 0 0 0 i\n" +"MouseMoveEvent 181 165 0 0 0 0 i\n" +"MouseMoveEvent 181 170 0 0 0 0 i\n" +"MouseMoveEvent 181 175 0 0 0 0 i\n" +"MouseMoveEvent 181 180 0 0 0 0 i\n" +"MouseMoveEvent 181 185 0 0 0 0 i\n" +"MouseMoveEvent 181 190 0 0 0 0 i\n" +"MouseMoveEvent 181 195 0 0 0 0 i\n" +"MouseMoveEvent 181 200 0 0 0 0 i\n" +"MouseMoveEvent 180 207 0 0 0 0 i\n" +"MouseMoveEvent 175 207 0 0 0 0 i\n" +"MouseMoveEvent 170 207 0 0 0 0 i\n" +"MouseMoveEvent 165 207 0 0 0 0 i\n" +"MouseMoveEvent 160 207 0 0 0 0 i\n" +"MouseMoveEvent 155 209 0 0 0 0 i\n" +"MouseMoveEvent 150 209 0 0 0 0 i\n" +"MouseMoveEvent 145 210 0 0 0 0 i\n" +"MouseMoveEvent 140 211 0 0 0 0 i\n" +"MouseMoveEvent 135 213 0 0 0 0 i\n" +"MouseMoveEvent 130 214 0 0 0 0 i\n" +"MouseMoveEvent 125 215 0 0 0 0 i\n" +"MouseMoveEvent 120 216 0 0 0 0 i\n" +"MouseMoveEvent 115 216 0 0 0 0 i\n" +"MouseMoveEvent 110 217 0 0 0 0 i\n" +"MouseMoveEvent 106 218 0 0 0 0 i\n" +"RightButtonReleaseEvent 106 218 0 0 0 0 i\n" +"LeftButtonPressEvent 106 218 0 0 0 0 i\n" +"MouseMoveEvent 107 219 0 0 0 0 i\n" +"MouseMoveEvent 110 218 0 0 0 0 i\n" +"MouseMoveEvent 114 216 0 0 0 0 i\n" +"MouseMoveEvent 118 214 0 0 0 0 i\n" +"MouseMoveEvent 123 213 0 0 0 0 i\n" +"MouseMoveEvent 128 212 0 0 0 0 i\n" +"MouseMoveEvent 132 210 0 0 0 0 i\n" +"MouseMoveEvent 138 207 0 0 0 0 i\n" +"MouseMoveEvent 144 205 0 0 0 0 i\n" +"MouseMoveEvent 150 203 0 0 0 0 i\n" +"MouseMoveEvent 157 201 0 0 0 0 i\n" +"MouseMoveEvent 164 200 0 0 0 0 i\n" +"MouseMoveEvent 168 198 0 0 0 0 i\n" +"MouseMoveEvent 176 196 0 0 0 0 i\n" +"MouseMoveEvent 183 194 0 0 0 0 i\n" +"MouseMoveEvent 190 192 0 0 0 0 i\n" +"MouseMoveEvent 197 190 0 0 0 0 i\n" +"MouseMoveEvent 199 189 0 0 0 0 i\n" +"MouseMoveEvent 204 189 0 0 0 0 i\n" +"MouseMoveEvent 206 189 0 0 0 0 i\n" +"MouseMoveEvent 209 188 0 0 0 0 i\n" +"MouseMoveEvent 211 187 0 0 0 0 i\n" +"LeftButtonReleaseEvent 211 187 0 0 0 0 i\n" +"MouseMoveEvent 259 183 0 0 0 0 i\n" +"KeyPressEvent 259 183 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 259 183 8 0 0 0 Control_L\n" +"MouseMoveEvent 261 183 8 0 0 0 Control_L\n" +"MouseMoveEvent 263 182 8 0 0 0 Control_L\n" +"MouseMoveEvent 266 181 8 0 0 0 Control_L\n" +"MouseMoveEvent 268 180 8 0 0 0 Control_L\n" +"MouseMoveEvent 270 179 8 0 0 0 Control_L\n" +"MouseMoveEvent 273 178 8 0 0 0 Control_L\n" +"MouseMoveEvent 276 177 8 0 0 0 Control_L\n" +"MouseMoveEvent 279 176 8 0 0 0 Control_L\n" +"MouseMoveEvent 282 175 8 0 0 0 Control_L\n" +"MouseMoveEvent 287 174 8 0 0 0 Control_L\n" +"MouseMoveEvent 286 173 8 0 0 0 Control_L\n" +"MouseMoveEvent 284 173 8 0 0 0 Control_L\n" +"MouseMoveEvent 281 174 8 0 0 0 Control_L\n" +"MouseMoveEvent 277 175 8 0 0 0 Control_L\n" +"MouseMoveEvent 274 176 8 0 0 0 Control_L\n" +"MouseMoveEvent 269 177 8 0 0 0 Control_L\n" +"MouseMoveEvent 267 177 8 0 0 0 Control_L\n" +"KeyReleaseEvent 267 177 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 267 177 0 0 0 0 Control_L\n" +"MouseMoveEvent 240 229 0 0 0 0 Control_L\n" +"KeyPressEvent 240 229 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 240 229 8 0 0 0 Control_L\n" +"MouseMoveEvent 240 230 8 0 0 0 Control_L\n" +"MouseMoveEvent 240 235 8 0 0 0 Control_L\n" +"MouseMoveEvent 240 240 8 0 0 0 Control_L\n" +"MouseMoveEvent 240 245 8 0 0 0 Control_L\n" +"MouseMoveEvent 240 250 8 0 0 0 Control_L\n" +"MouseMoveEvent 241 255 8 0 0 0 Control_L\n" +"MouseMoveEvent 242 260 8 0 0 0 Control_L\n" +"MouseMoveEvent 242 265 8 0 0 0 Control_L\n" +"MouseMoveEvent 242 260 8 0 0 0 Control_L\n" +"MouseMoveEvent 242 255 8 0 0 0 Control_L\n" +"MouseMoveEvent 242 250 8 0 0 0 Control_L\n" +"MouseMoveEvent 242 245 8 0 0 0 Control_L\n" +"MouseMoveEvent 242 240 8 0 0 0 Control_L\n" +"MouseMoveEvent 241 238 8 0 0 0 Control_L\n" +"KeyReleaseEvent 241 238 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 241 238 0 0 0 0 Control_L\n" +"MouseMoveEvent 103 250 0 0 0 0 Control_L\n" +"KeyPressEvent 103 250 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 103 250 8 0 0 0 Control_L\n" +"MouseMoveEvent 100 250 8 0 0 0 Control_L\n" +"MouseMoveEvent 97 251 8 0 0 0 Control_L\n" +"MouseMoveEvent 94 251 8 0 0 0 Control_L\n" +"MouseMoveEvent 91 252 8 0 0 0 Control_L\n" +"MouseMoveEvent 90 253 8 0 0 0 Control_L\n" +"MouseMoveEvent 85 253 8 0 0 0 Control_L\n" +"MouseMoveEvent 80 253 8 0 0 0 Control_L\n" +"MouseMoveEvent 85 253 8 0 0 0 Control_L\n" +"KeyReleaseEvent 85 253 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 85 253 0 0 0 0 Control_L\n" +"MouseMoveEvent 228 88 0 0 0 0 Control_L\n" +"KeyPressEvent 228 88 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 228 88 8 0 0 0 Control_L\n" +"MouseMoveEvent 228 86 8 0 0 0 Control_L\n" +"MouseMoveEvent 227 83 8 0 0 0 Control_L\n" +"MouseMoveEvent 226 83 8 0 0 0 Control_L\n" +"MouseMoveEvent 225 80 8 0 0 0 Control_L\n" +"MouseMoveEvent 225 75 8 0 0 0 Control_L\n" +"MouseMoveEvent 224 70 8 0 0 0 Control_L\n" +"MouseMoveEvent 223 70 8 0 0 0 Control_L\n" +"MouseMoveEvent 223 75 8 0 0 0 Control_L\n" +"MouseMoveEvent 222 80 8 0 0 0 Control_L\n" +"MouseMoveEvent 222 85 8 0 0 0 Control_L\n" +"MouseMoveEvent 222 90 8 0 0 0 Control_L\n" +"KeyReleaseEvent 222 93 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 222 93 0 0 0 0 Control_L\n" +"MouseMoveEvent 260 76 0 0 0 0 Control_L\n" +"KeyPressEvent 260 76 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 260 76 8 0 0 0 Control_L\n" +"MouseMoveEvent 260 75 8 0 0 0 Control_L\n" +"MouseMoveEvent 261 72 8 0 0 0 Control_L\n" +"MouseMoveEvent 262 69 8 0 0 0 Control_L\n" +"MouseMoveEvent 263 67 8 0 0 0 Control_L\n" +"MouseMoveEvent 263 65 8 0 0 0 Control_L\n" +"MouseMoveEvent 264 63 8 0 0 0 Control_L\n" +"MouseMoveEvent 265 61 8 0 0 0 Control_L\n" +"MouseMoveEvent 266 60 8 0 0 0 Control_L\n" +"MouseMoveEvent 266 55 8 0 0 0 Control_L\n" +"MouseMoveEvent 267 53 8 0 0 0 Control_L\n" +"KeyReleaseEvent 267 53 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 267 53 0 0 0 0 Control_L\n" +"MouseMoveEvent 278 226 0 0 0 0 Control_L\n" +"KeyPressEvent 278 226 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 278 226 8 0 0 0 Control_L\n" +"MouseMoveEvent 278 227 8 0 0 0 Control_L\n" +"MouseMoveEvent 278 230 8 0 0 0 Control_L\n" +"MouseMoveEvent 280 232 8 0 0 0 Control_L\n" +"MouseMoveEvent 282 234 8 0 0 0 Control_L\n" +"MouseMoveEvent 284 237 8 0 0 0 Control_L\n" +"MouseMoveEvent 286 239 8 0 0 0 Control_L\n" +"MouseMoveEvent 287 242 8 0 0 0 Control_L\n" +"MouseMoveEvent 290 245 8 0 0 0 Control_L\n" +"MouseMoveEvent 292 247 8 0 0 0 Control_L\n" +"MouseMoveEvent 293 249 8 0 0 0 Control_L\n" +"KeyReleaseEvent 283 249 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 293 249 0 0 0 0 Control_L\n" +"MouseMoveEvent 93 286 0 0 0 0 Control_L\n" +"KeyPressEvent 93 286 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 93 286 8 0 0 0 Control_L\n" +"MouseMoveEvent 92 288 8 0 0 0 Control_L\n" +"MouseMoveEvent 90 290 8 0 0 0 Control_L\n" +"MouseMoveEvent 87 292 8 0 0 0 Control_L\n" +"MouseMoveEvent 84 295 8 0 0 0 Control_L\n" +"MouseMoveEvent 82 297 8 0 0 0 Control_L\n" +"MouseMoveEvent 80 298 8 0 0 0 Control_L\n" +"MouseMoveEvent 78 300 8 0 0 0 Control_L\n" +"KeyReleaseEvent 78 300 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 78 300 0 0 0 0 Control_L\n" +"MouseMoveEvent 198 194 0 0 0 0 Control_L\n" +"KeyPressEvent 198 194 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 198 194 8 0 0 0 Control_L\n" +"MouseMoveEvent 196 194 8 0 0 0 Control_L\n" +"MouseMoveEvent 191 192 8 0 0 0 Control_L\n" +"MouseMoveEvent 185 189 8 0 0 0 Control_L\n" +"MouseMoveEvent 182 187 8 0 0 0 Control_L\n" +"MouseMoveEvent 180 186 8 0 0 0 Control_L\n" +"MouseMoveEvent 178 185 8 0 0 0 Control_L\n" +"MouseMoveEvent 177 180 8 0 0 0 Control_L\n" +"MouseMoveEvent 178 179 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 178 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 177 8 0 0 0 Control_L\n" +"MouseMoveEvent 182 176 8 0 0 0 Control_L\n" +"MouseMoveEvent 187 175 8 0 0 0 Control_L\n" +"MouseMoveEvent 190 177 8 0 0 0 Control_L\n" +"MouseMoveEvent 190 179 8 0 0 0 Control_L\n" +"KeyReleaseEvent 190 179 0 0 0 1 Control_L\n" +"MiddleButtonReleaseEvent 190 179 0 0 0 0 Control_L\n" +"KeyPressEvent 190 179 0 -128 0 1 Shift_L\n" +"MiddleButtonPressEvent 190 179 0 4 0 0 Shift_L\n" +"MouseMoveEvent 190 180 0 4 0 0 Shift_L\n" +"MouseMoveEvent 190 185 0 4 0 0 Shift_L\n" +"MouseMoveEvent 190 190 0 4 0 0 Shift_L\n" +"MouseMoveEvent 191 194 0 4 0 0 Shift_L\n" +"MouseMoveEvent 192 200 0 4 0 0 Shift_L\n" +"MouseMoveEvent 192 206 0 4 0 0 Shift_L\n" +"MouseMoveEvent 193 213 0 4 0 0 Shift_L\n" +"MouseMoveEvent 193 209 0 4 0 0 Shift_L\n" +"MouseMoveEvent 193 206 0 4 0 0 Shift_L\n" +"MouseMoveEvent 193 200 0 4 0 0 Shift_L\n" +"MouseMoveEvent 193 196 0 4 0 0 Shift_L\n" +"MouseMoveEvent 193 190 0 4 0 0 Shift_L\n" +"MouseMoveEvent 194 185 0 4 0 0 Shift_L\n" +"MouseMoveEvent 196 180 0 4 0 0 Shift_L\n" +"MouseMoveEvent 197 175 0 4 0 0 Shift_L\n" +"MouseMoveEvent 198 172 0 4 0 0 Shift_L\n" +"KeyReleaseEvent 198 172 0 0 0 1 Shift_L\n" +"MiddleButtonReleaseEvent 198 172 0 0 0 0 Shift_L\n" +"MouseMoveEvent 267 172 0 0 0 0 Shift_L\n" +"MiddleButtonPressEvent 267 172 0 0 0 0 Shift_L\n" +"MouseMoveEvent 264 171 0 0 0 0 Shift_L\n" +"MouseMoveEvent 260 171 0 0 0 0 Shift_L\n" +"MouseMoveEvent 255 171 0 0 0 0 Shift_L\n" +"MouseMoveEvent 250 171 0 0 0 0 Shift_L\n" +"MouseMoveEvent 245 172 0 0 0 0 Shift_L\n" +"MiddleButtonReleaseEvent 245 172 0 0 0 0 Shift_L\n" +"MouseMoveEvent 203 65 0 0 0 0 Shift_L\n" +"MiddleButtonPressEvent 203 65 0 0 0 0 Shift_L\n" +"MouseMoveEvent 200 65 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 66 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 67 0 0 0 0 Shift_L\n" +"MouseMoveEvent 190 68 0 0 0 0 Shift_L\n" +"MouseMoveEvent 184 71 0 0 0 0 Shift_L\n" +"MouseMoveEvent 180 73 0 0 0 0 Shift_L\n" +"MouseMoveEvent 178 74 0 0 0 0 Shift_L\n" +"MouseMoveEvent 176 75 0 0 0 0 Shift_L\n" +"MouseMoveEvent 175 76 0 0 0 0 Shift_L\n" +"MouseMoveEvent 174 77 0 0 0 0 Shift_L\n" +"MouseMoveEvent 173 78 0 0 0 0 Shift_L\n" +"MouseMoveEvent 172 79 0 0 0 0 Shift_L\n" +"MouseMoveEvent 170 80 0 0 0 0 Shift_L\n" +"MouseMoveEvent 169 81 0 0 0 0 Shift_L\n" +"MouseMoveEvent 168 82 0 0 0 0 Shift_L\n" +"MouseMoveEvent 167 83 0 0 0 0 Shift_L\n" +"MouseMoveEvent 166 84 0 0 0 0 Shift_L\n" +"MouseMoveEvent 164 84 0 0 0 0 Shift_L\n" +"MouseMoveEvent 163 85 0 0 0 0 Shift_L\n" +"MouseMoveEvent 162 86 0 0 0 0 Shift_L\n" +"MouseMoveEvent 160 86 0 0 0 0 Shift_L\n" +"MouseMoveEvent 158 87 0 0 0 0 Shift_L\n" +"MiddleButtonReleaseEvent 158 87 0 0 0 0 Shift_L\n" +"MouseMoveEvent 95 251 0 0 0 0 Shift_L\n" +"MiddleButtonPressEvent 95 251 0 0 0 0 Shift_L\n" +"MouseMoveEvent 90 251 0 0 0 0 Shift_L\n" +"MouseMoveEvent 85 252 0 0 0 0 Shift_L\n" +"MouseMoveEvent 80 252 0 0 0 0 Shift_L\n" +"MouseMoveEvent 75 252 0 0 0 0 Shift_L\n" +"MouseMoveEvent 70 252 0 0 0 0 Shift_L\n" +"MouseMoveEvent 65 251 0 0 0 0 Shift_L\n" +"MiddleButtonReleaseEvent 65 251 0 0 0 0 Shift_L\n" +"MouseMoveEvent 133 281 0 0 0 0 Shift_L\n" +"MiddleButtonPressEvent 133 281 0 0 0 0 Shift_L\n" +"MouseMoveEvent 130 280 0 0 0 0 Shift_L\n" +"MouseMoveEvent 125 277 0 0 0 0 Shift_L\n" +"MouseMoveEvent 120 274 0 0 0 0 Shift_L\n" +"MouseMoveEvent 115 270 0 0 0 0 Shift_L\n" +"MouseMoveEvent 113 267 0 0 0 0 Shift_L\n" +"MouseMoveEvent 110 265 0 0 0 0 Shift_L\n" +"MiddleButtonReleaseEvent 110 265 0 0 0 0 Shift_L\n" +"MouseMoveEvent 99 286 0 0 0 0 Shift_L\n" +"MiddleButtonPressEvent 99 286 0 0 0 0 Shift_L\n" +"MouseMoveEvent 100 287 0 0 0 0 Shift_L\n" +"MouseMoveEvent 105 289 0 0 0 0 Shift_L\n" +"MouseMoveEvent 110 290 0 0 0 0 Shift_L\n" +"MouseMoveEvent 115 290 0 0 0 0 Shift_L\n" +"MouseMoveEvent 120 290 0 0 0 0 Shift_L\n" +"MouseMoveEvent 125 285 0 0 0 0 Shift_L\n" +"MouseMoveEvent 129 281 0 0 0 0 Shift_L\n" +"MouseMoveEvent 130 279 0 0 0 0 Shift_L\n" +"MouseMoveEvent 128 281 0 0 0 0 Shift_L\n" +"MouseMoveEvent 126 282 0 0 0 0 Shift_L\n" +"MouseMoveEvent 123 283 0 0 0 0 Shift_L\n" +"MouseMoveEvent 120 284 0 0 0 0 Shift_L\n" +"MouseMoveEvent 115 285 0 0 0 0 Shift_L\n" +"MouseMoveEvent 110 286 0 0 0 0 Shift_L\n" +"MouseMoveEvent 106 286 0 0 0 0 Shift_L\n" +"MouseMoveEvent 102 286 0 0 0 0 Shift_L\n" +"MouseMoveEvent 99 285 0 0 0 0 Shift_L\n" +"MouseMoveEvent 95 283 0 0 0 0 Shift_L\n" +"MouseMoveEvent 92 281 0 0 0 0 Shift_L\n" +"MouseMoveEvent 89 279 0 0 0 0 Shift_L\n" +"MouseMoveEvent 88 276 0 0 0 0 Shift_L\n" +"MouseMoveEvent 86 274 0 0 0 0 Shift_L\n" +"MiddleButtonReleaseEvent 86 274 0 0 0 0 Shift_L\n" +; + +int ImagePlaneWidget( int argc, char *argv[] ) +{ + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter"); + + vtkVolume16Reader* v16 = vtkVolume16Reader::New(); + v16->SetDataDimensions( 64, 64); + v16->SetDataByteOrderToLittleEndian(); + v16->SetImageRange( 1, 93); + v16->SetDataSpacing( 3.2, 3.2, 1.5); + v16->SetFilePrefix( fname ); + v16->SetDataMask( 0x7fff); + v16->Update(); + + delete[] fname; + + vtkOutlineFilter* outline = vtkOutlineFilter::New(); + outline->SetInputConnection(v16->GetOutputPort()); + + vtkPolyDataMapper* outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + + vtkActor* outlineActor = vtkActor::New(); + outlineActor->SetMapper( outlineMapper); + + vtkRenderer* ren1 = vtkRenderer::New(); + vtkRenderer* ren2 = vtkRenderer::New(); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren2); + renWin->AddRenderer(ren1); + + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkCellPicker* picker = vtkCellPicker::New(); + picker->SetTolerance(0.005); + + vtkProperty* ipwProp = vtkProperty::New(); + //assign default props to the ipw's texture plane actor + + vtkImagePlaneWidget* planeWidgetX = vtkImagePlaneWidget::New(); + planeWidgetX->SetInteractor( iren); + planeWidgetX->SetKeyPressActivationValue('x'); + planeWidgetX->SetPicker(picker); + planeWidgetX->RestrictPlaneToVolumeOn(); + planeWidgetX->GetPlaneProperty()->SetColor(1,0,0); + planeWidgetX->SetTexturePlaneProperty(ipwProp); + planeWidgetX->TextureInterpolateOff(); + planeWidgetX->SetResliceInterpolateToNearestNeighbour(); + planeWidgetX->SetInput(v16->GetOutput()); + planeWidgetX->SetPlaneOrientationToXAxes(); + planeWidgetX->SetSliceIndex(32); + planeWidgetX->DisplayTextOn(); + planeWidgetX->On(); + planeWidgetX->InteractionOff(); + planeWidgetX->InteractionOn(); + + vtkImagePlaneWidget* planeWidgetY = vtkImagePlaneWidget::New(); + planeWidgetY->SetInteractor( iren); + planeWidgetY->SetKeyPressActivationValue('y'); + planeWidgetY->SetPicker(picker); + planeWidgetY->GetPlaneProperty()->SetColor(1,1,0); + planeWidgetY->SetTexturePlaneProperty(ipwProp); + planeWidgetY->TextureInterpolateOn(); + planeWidgetY->SetResliceInterpolateToLinear(); + planeWidgetY->SetInput(v16->GetOutput()); + planeWidgetY->SetPlaneOrientationToYAxes(); + planeWidgetY->SetSlicePosition(102.4); + planeWidgetY->SetLookupTable( planeWidgetX->GetLookupTable()); + planeWidgetY->DisplayTextOff(); + planeWidgetY->UpdatePlacement(); + planeWidgetY->On(); + + vtkImagePlaneWidget* planeWidgetZ = vtkImagePlaneWidget::New(); + planeWidgetZ->SetInteractor( iren); + planeWidgetZ->SetKeyPressActivationValue('z'); + planeWidgetZ->SetPicker(picker); + planeWidgetZ->GetPlaneProperty()->SetColor(0,0,1); + planeWidgetZ->SetTexturePlaneProperty(ipwProp); + planeWidgetZ->TextureInterpolateOn(); + planeWidgetZ->SetResliceInterpolateToCubic(); + planeWidgetZ->SetInput(v16->GetOutput()); + planeWidgetZ->SetPlaneOrientationToZAxes(); + planeWidgetZ->SetSliceIndex(25); + planeWidgetZ->SetLookupTable( planeWidgetX->GetLookupTable()); + planeWidgetZ->DisplayTextOn(); + planeWidgetZ->On(); + + double wl[2]; + planeWidgetZ->GetWindowLevel(wl); + + // Add a 2D image to test the GetReslice method + // + vtkImageMapToColors* colorMap = vtkImageMapToColors::New(); + colorMap->PassAlphaToOutputOff(); + colorMap->SetActiveComponent(0); + colorMap->SetOutputFormatToLuminance(); + colorMap->SetInput(planeWidgetZ->GetResliceOutput()); + colorMap->SetLookupTable(planeWidgetX->GetLookupTable()); + + vtkImageActor* imageActor = vtkImageActor::New(); + imageActor->PickableOff(); + imageActor->SetInput(colorMap->GetOutput()); + + // Add the actors + // + ren1->AddActor( outlineActor); + ren2->AddActor( imageActor); + + ren1->SetBackground( 0.1, 0.1, 0.2); + ren2->SetBackground( 0.2, 0.1, 0.2); + + renWin->SetSize( 600, 350); + + ren1->SetViewport(0,0,0.58333,1); + ren2->SetViewport(0.58333,0,1,1); + + // Set the actors' postions + // + renWin->Render(); + iren->SetEventPosition( 175,175); + iren->SetKeyCode('r'); + iren->InvokeEvent(vtkCommand::CharEvent,NULL); + iren->SetEventPosition( 475,175); + iren->SetKeyCode('r'); + iren->InvokeEvent(vtkCommand::CharEvent,NULL); + renWin->Render(); + + ren1->GetActiveCamera()->Elevation(110); + ren1->GetActiveCamera()->SetViewUp(0, 0, -1); + ren1->GetActiveCamera()->Azimuth(45); + ren1->GetActiveCamera()->Dolly(1.15); + ren1->ResetCameraClippingRange(); + + // Playback recorded events + // + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(IPWeventLog); + + // Interact with data + // Render the image + // + iren->Initialize(); + renWin->Render(); + + // Test SetKeyPressActivationValue for one of the widgets + // + iren->SetKeyCode('z'); + iren->InvokeEvent(vtkCommand::CharEvent,NULL); + iren->SetKeyCode('z'); + iren->InvokeEvent(vtkCommand::CharEvent,NULL); + + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + // + recorder->Off(); + recorder->Delete(); + + ipwProp->Delete(); + planeWidgetX->Delete(); + planeWidgetY->Delete(); + planeWidgetZ->Delete(); + colorMap->Delete(); + imageActor->Delete(); + picker->Delete(); + outlineActor->Delete(); + outlineMapper->Delete(); + outline->Delete(); + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + ren2->Delete(); + v16->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestImageTracerWidget.cxx b/Widgets/Testing/Cxx/TestImageTracerWidget.cxx new file mode 100644 index 0000000..44003ee --- /dev/null +++ b/Widgets/Testing/Cxx/TestImageTracerWidget.cxx @@ -0,0 +1,566 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestImageTracerWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkExtractVOI.h" +#include "vtkGlyphSource2D.h" +#include "vtkImageActor.h" +#include "vtkImageData.h" +#include "vtkImageShiftScale.h" +#include "vtkImageStencil.h" +#include "vtkImageTracerWidget.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkInteractorStyleImage.h" +#include "vtkLinearExtrusionFilter.h" +#include "vtkMapper.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataToImageStencil.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkSplineWidget.h" +#include "vtkVolume16Reader.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char ImageTracerWidgetEventLog[] = +"# StreamVersion 1\n" +"MouseMoveEvent 322 145 0 0 0 0 b\n" +"LeftButtonPressEvent 322 145 0 0 0 0 b\n" +"LeftButtonReleaseEvent 322 145 0 0 0 0 b\n" +"MouseMoveEvent 146 166 0 0 0 0 b\n" +"LeftButtonPressEvent 146 166 0 0 0 0 b\n" +"MouseMoveEvent 154 161 0 0 0 0 b\n" +"MouseMoveEvent 162 148 0 0 0 0 b\n" +"MouseMoveEvent 169 129 0 0 0 0 b\n" +"MouseMoveEvent 168 100 0 0 0 0 b\n" +"MouseMoveEvent 161 95 0 0 0 0 b\n" +"MouseMoveEvent 131 90 0 0 0 0 b\n" +"MouseMoveEvent 113 95 0 0 0 0 b\n" +"MouseMoveEvent 77 116 0 0 0 0 b\n" +"MouseMoveEvent 68 132 0 0 0 0 b\n" +"MouseMoveEvent 67 151 0 0 0 0 b\n" +"MouseMoveEvent 73 165 0 0 0 0 b\n" +"MouseMoveEvent 89 179 0 0 0 0 b\n" +"MouseMoveEvent 98 182 0 0 0 0 b\n" +"MouseMoveEvent 111 182 0 0 0 0 b\n" +"MouseMoveEvent 118 182 0 0 0 0 b\n" +"MouseMoveEvent 130 177 0 0 0 0 b\n" +"MouseMoveEvent 134 175 0 0 0 0 b\n" +"MouseMoveEvent 144 170 0 0 0 0 b\n" +"MouseMoveEvent 146 167 0 0 0 0 b\n" +"LeftButtonReleaseEvent 146 167 0 0 0 0 b\n" +"MouseMoveEvent 132 164 0 0 0 0 b\n" +"MiddleButtonPressEvent 132 164 0 0 0 0 b\n" +"MiddleButtonReleaseEvent 132 164 0 0 0 0 b\n" +"MouseMoveEvent 131 163 0 0 0 0 b\n" +"MouseMoveEvent 127 161 0 0 0 0 b\n" +"MouseMoveEvent 120 153 0 0 0 0 b\n" +"MouseMoveEvent 110 146 0 0 0 0 b\n" +"MouseMoveEvent 104 140 0 0 0 0 b\n" +"MouseMoveEvent 101 132 0 0 0 0 b\n" +"MouseMoveEvent 99 128 0 0 0 0 b\n" +"MouseMoveEvent 95 123 0 0 0 0 b\n" +"MouseMoveEvent 91 116 0 0 0 0 b\n" +"MiddleButtonPressEvent 91 116 0 0 0 0 b\n" +"MiddleButtonReleaseEvent 91 116 0 0 0 0 b\n" +"MouseMoveEvent 95 116 0 0 0 0 b\n" +"MouseMoveEvent 105 118 0 0 0 0 b\n" +"MouseMoveEvent 115 121 0 0 0 0 b\n" +"MouseMoveEvent 124 124 0 0 0 0 b\n" +"MouseMoveEvent 136 127 0 0 0 0 b\n" +"MouseMoveEvent 144 128 0 0 0 0 b\n" +"MouseMoveEvent 150 130 0 0 0 0 b\n" +"MouseMoveEvent 154 132 0 0 0 0 b\n" +"MouseMoveEvent 157 133 0 0 0 0 b\n" +"MouseMoveEvent 161 133 0 0 0 0 b\n" +"MouseMoveEvent 164 134 0 0 0 0 b\n" +"MouseMoveEvent 167 135 0 0 0 0 b\n" +"MouseMoveEvent 169 136 0 0 0 0 b\n" +"KeyPressEvent 169 136 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 169 136 8 0 0 0 Control_L\n" +"MiddleButtonReleaseEvent 169 136 8 0 0 0 Control_L\n" +"KeyReleaseEvent 169 136 0 0 0 1 Control_L\n" +"RightButtonPressEvent 169 136 0 0 0 0 Control_L\n" +"MouseMoveEvent 167 142 0 0 0 0 Control_L\n" +"MouseMoveEvent 164 146 0 0 0 0 Control_L\n" +"MouseMoveEvent 162 149 0 0 0 0 Control_L\n" +"MouseMoveEvent 159 152 0 0 0 0 Control_L\n" +"MouseMoveEvent 155 155 0 0 0 0 Control_L\n" +"MouseMoveEvent 152 157 0 0 0 0 Control_L\n" +"MouseMoveEvent 148 159 0 0 0 0 Control_L\n" +"MouseMoveEvent 143 163 0 0 0 0 Control_L\n" +"MouseMoveEvent 137 165 0 0 0 0 Control_L\n" +"MouseMoveEvent 133 166 0 0 0 0 Control_L\n" +"MouseMoveEvent 132 164 0 0 0 0 Control_L\n" +"RightButtonReleaseEvent 132 164 0 0 0 0 Control_L\n" +"MouseMoveEvent 133 164 0 0 0 0 Control_L\n" +"KeyPressEvent 133 164 -128 0 0 1 Control_L\n" +"RightButtonPressEvent 133 164 8 0 0 0 Control_L\n" +"RightButtonReleaseEvent 133 164 8 0 0 0 Control_L\n" +"KeyReleaseEvent 133 164 0 0 0 1 Control_L\n" +"MouseMoveEvent 133 164 0 0 0 0 Control_L\n" +"MouseMoveEvent 129 162 0 0 0 0 Control_L\n" +"MouseMoveEvent 125 160 0 0 0 0 Control_L\n" +"MouseMoveEvent 125 156 0 0 0 0 Control_L\n" +"MouseMoveEvent 122 154 0 0 0 0 Control_L\n" +"MouseMoveEvent 121 152 0 0 0 0 Control_L\n" +"KeyPressEvent 121 152 0 -128 0 1 Shift_L\n" +"RightButtonPressEvent 121 152 0 4 0 0 Shift_L\n" +"RightButtonReleaseEvent 121 152 0 4 0 0 Shift_L\n" +"KeyReleaseEvent 121 152 0 0 0 1 Shift_L\n" +"MouseMoveEvent 108 137 0 0 0 0 Shift_L\n" +"KeyPressEvent 108 137 0 -128 0 1 Shift_L\n" +"RightButtonPressEvent 108 137 0 4 0 0 Shift_L\n" +"RightButtonReleaseEvent 108 137 0 4 0 0 Shift_L\n" +"KeyReleaseEvent 108 137 0 0 0 1 Shift_L\n" +"RightButtonPressEvent 108 137 0 0 0 0 Shift_L\n" +"MouseMoveEvent 112 127 0 0 0 0 Shift_L\n" +"MouseMoveEvent 118 116 0 0 0 0 Shift_L\n" +"MouseMoveEvent 121 109 0 0 0 0 Shift_L\n" +"MouseMoveEvent 128 97 0 0 0 0 Shift_L\n" +"MouseMoveEvent 134 88 0 0 0 0 Shift_L\n" +"MouseMoveEvent 136 86 0 0 0 0 Shift_L\n" +"RightButtonReleaseEvent 136 86 0 0 0 0 Shift_L\n" +"MouseMoveEvent 122 152 0 0 0 0 Shift_L\n" +"RightButtonPressEvent 122 152 0 0 0 0 Shift_L\n" +"MouseMoveEvent 125 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 156 143 0 0 0 0 Shift_L\n" +"MouseMoveEvent 164 141 0 0 0 0 Shift_L\n" +"MouseMoveEvent 168 140 0 0 0 0 Shift_L\n" +"MouseMoveEvent 170 140 0 0 0 0 Shift_L\n" +"RightButtonReleaseEvent 170 140 0 0 0 0 Shift_L\n" +"MouseMoveEvent 129 166 0 0 0 0 Shift_L\n" +"RightButtonPressEvent 129 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 127 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 115 152 0 0 0 0 Shift_L\n" +"MouseMoveEvent 104 140 0 0 0 0 Shift_L\n" +"MouseMoveEvent 95 130 0 0 0 0 Shift_L\n" +"MouseMoveEvent 89 124 0 0 0 0 Shift_L\n" +"MouseMoveEvent 88 118 0 0 0 0 Shift_L\n" +"RightButtonReleaseEvent 88 118 0 0 0 0 Shift_L\n" +"MouseMoveEvent 168 140 0 0 0 0 Shift_L\n" +"RightButtonPressEvent 168 140 0 0 0 0 Shift_L\n" +"MouseMoveEvent 165 140 0 0 0 0 Shift_L\n" +"MouseMoveEvent 162 142 0 0 0 0 Shift_L\n" +"MouseMoveEvent 159 145 0 0 0 0 Shift_L\n" +"MouseMoveEvent 156 146 0 0 0 0 Shift_L\n" +"MouseMoveEvent 153 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 150 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 147 153 0 0 0 0 Shift_L\n" +"RightButtonReleaseEvent 147 153 0 0 0 0 Shift_L\n" +"MouseMoveEvent 137 84 0 0 0 0 Shift_L\n" +"RightButtonPressEvent 137 84 0 0 0 0 Shift_L\n" +"MouseMoveEvent 133 94 0 0 0 0 Shift_L\n" +"MouseMoveEvent 130 107 0 0 0 0 Shift_L\n" +"MouseMoveEvent 123 124 0 0 0 0 Shift_L\n" +"MouseMoveEvent 110 147 0 0 0 0 Shift_L\n" +"MouseMoveEvent 99 160 0 0 0 0 Shift_L\n" +"RightButtonReleaseEvent 99 160 0 0 0 0 Shift_L\n" +"MouseMoveEvent 337 163 0 0 0 0 Shift_L\n" +"RightButtonPressEvent 337 163 0 0 0 0 Shift_L\n" +"MouseMoveEvent 337 162 0 0 0 0 Shift_L\n" +"MouseMoveEvent 337 160 0 0 0 0 Shift_L\n" +"MouseMoveEvent 338 158 0 0 0 0 Shift_L\n" +"MouseMoveEvent 342 153 0 0 0 0 Shift_L\n" +"MouseMoveEvent 346 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 349 147 0 0 0 0 Shift_L\n" +"MouseMoveEvent 352 144 0 0 0 0 Shift_L\n" +"MouseMoveEvent 354 141 0 0 0 0 Shift_L\n" +"MouseMoveEvent 356 139 0 0 0 0 Shift_L\n" +"MouseMoveEvent 358 136 0 0 0 0 Shift_L\n" +"MouseMoveEvent 359 135 0 0 0 0 Shift_L\n" +"MouseMoveEvent 360 133 0 0 0 0 Shift_L\n" +"MouseMoveEvent 360 131 0 0 0 0 Shift_L\n" +"MouseMoveEvent 361 130 0 0 0 0 Shift_L\n" +"MouseMoveEvent 362 128 0 0 0 0 Shift_L\n" +"MouseMoveEvent 364 124 0 0 0 0 Shift_L\n" +"MouseMoveEvent 365 122 0 0 0 0 Shift_L\n" +"MouseMoveEvent 367 119 0 0 0 0 Shift_L\n" +"MouseMoveEvent 368 117 0 0 0 0 Shift_L\n" +"MouseMoveEvent 369 114 0 0 0 0 Shift_L\n" +"MouseMoveEvent 370 113 0 0 0 0 Shift_L\n" +"MouseMoveEvent 370 112 0 0 0 0 Shift_L\n" +"MouseMoveEvent 370 113 0 0 0 0 Shift_L\n" +"MouseMoveEvent 368 114 0 0 0 0 Shift_L\n" +"MouseMoveEvent 367 115 0 0 0 0 Shift_L\n" +"MouseMoveEvent 366 116 0 0 0 0 Shift_L\n" +"MouseMoveEvent 366 118 0 0 0 0 Shift_L\n" +"MouseMoveEvent 365 118 0 0 0 0 Shift_L\n" +"MouseMoveEvent 365 120 0 0 0 0 Shift_L\n" +"MouseMoveEvent 364 121 0 0 0 0 Shift_L\n" +"MouseMoveEvent 363 123 0 0 0 0 Shift_L\n" +"MouseMoveEvent 362 125 0 0 0 0 Shift_L\n" +"MouseMoveEvent 362 127 0 0 0 0 Shift_L\n" +"MouseMoveEvent 361 128 0 0 0 0 Shift_L\n" +"MouseMoveEvent 360 130 0 0 0 0 Shift_L\n" +"MouseMoveEvent 360 131 0 0 0 0 Shift_L\n" +"MouseMoveEvent 359 133 0 0 0 0 Shift_L\n" +"MouseMoveEvent 358 134 0 0 0 0 Shift_L\n" +"MouseMoveEvent 357 136 0 0 0 0 Shift_L\n" +"MouseMoveEvent 356 139 0 0 0 0 Shift_L\n" +"MouseMoveEvent 355 141 0 0 0 0 Shift_L\n" +"MouseMoveEvent 354 143 0 0 0 0 Shift_L\n" +"MouseMoveEvent 353 145 0 0 0 0 Shift_L\n" +"MouseMoveEvent 352 147 0 0 0 0 Shift_L\n" +"MouseMoveEvent 352 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 352 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 351 152 0 0 0 0 Shift_L\n" +"MouseMoveEvent 350 156 0 0 0 0 Shift_L\n" +"MouseMoveEvent 349 158 0 0 0 0 Shift_L\n" +"RightButtonReleaseEvent 349 158 0 0 0 0 Shift_L\n" +"MouseMoveEvent 381 179 0 0 0 0 Shift_L\n" +"LeftButtonPressEvent 381 179 0 0 0 0 Shift_L\n" +"MouseMoveEvent 382 179 0 0 0 0 Shift_L\n" +"MouseMoveEvent 379 179 0 0 0 0 Shift_L\n" +"MouseMoveEvent 376 177 0 0 0 0 Shift_L\n" +"MouseMoveEvent 371 174 0 0 0 0 Shift_L\n" +"MouseMoveEvent 364 167 0 0 0 0 Shift_L\n" +"MouseMoveEvent 353 156 0 0 0 0 Shift_L\n" +"MouseMoveEvent 348 146 0 0 0 0 Shift_L\n" +"MouseMoveEvent 345 139 0 0 0 0 Shift_L\n" +"MouseMoveEvent 342 129 0 0 0 0 Shift_L\n" +"MouseMoveEvent 340 121 0 0 0 0 Shift_L\n" +"MouseMoveEvent 337 111 0 0 0 0 Shift_L\n" +"MouseMoveEvent 336 101 0 0 0 0 Shift_L\n" +"MouseMoveEvent 336 98 0 0 0 0 Shift_L\n" +"MouseMoveEvent 335 95 0 0 0 0 Shift_L\n" +"MouseMoveEvent 335 93 0 0 0 0 Shift_L\n" +"MouseMoveEvent 333 91 0 0 0 0 Shift_L\n" +"MouseMoveEvent 331 87 0 0 0 0 Shift_L\n" +"MouseMoveEvent 329 85 0 0 0 0 Shift_L\n" +"MouseMoveEvent 329 84 0 0 0 0 Shift_L\n" +"MouseMoveEvent 328 84 0 0 0 0 Shift_L\n" +"LeftButtonReleaseEvent 328 84 0 0 0 0 Shift_L\n" +; + +// Callback for the tracer interaction +class vtkITWCallback : public vtkCommand +{ +public: + static vtkITWCallback *New() + { return new vtkITWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkImageTracerWidget *tracerWidget = + reinterpret_cast<vtkImageTracerWidget*>(caller); + if(!tracerWidget) { return; } + + int closed = tracerWidget->IsClosed(); + SplineWidget->SetClosed(closed); + + if (!closed) + { + Actor->SetInput(Extract->GetOutput()); + } + + int npts = tracerWidget->GetNumberOfHandles(); + if (npts < 2) { return; } + + tracerWidget->GetPath(PathPoly); + vtkPoints* points = PathPoly->GetPoints(); + if (!points){ return; } + + SplineWidget->InitializeHandles(points); + + if (closed) + { + SplineWidget->GetPolyData(SplinePoly); + Stencil->Update(); + Actor->SetInput(Stencil->GetOutput()); + } + } + + vtkITWCallback():SplineWidget(0),Actor(0),Stencil(0),Extract(0), + PathPoly(0),SplinePoly(0){} + + vtkSplineWidget *SplineWidget; + vtkImageActor *Actor; + vtkImageStencil *Stencil; + vtkExtractVOI *Extract; + vtkPolyData *PathPoly; + vtkPolyData *SplinePoly; +}; + +// Callback for the spline interaction. +// Note: this callback has to have a name different from that already +// used in another test: see TestSplineWidget.cxx! +class vtkSW2Callback : public vtkCommand +{ +public: + static vtkSW2Callback *New() + { return new vtkSW2Callback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkSplineWidget *splineWidget = + reinterpret_cast<vtkSplineWidget*>(caller); + if(!splineWidget) { return; } + + int npts = splineWidget->GetNumberOfHandles(); + int closed = splineWidget->IsClosed(); + + Points->Reset(); + for (int i = 0; i < npts; ++i) + { + Points->InsertNextPoint(splineWidget->GetHandlePosition(i)); + } + + if (closed) + { + if (TracerWidget->GetAutoClose()) + { + Points->InsertNextPoint(splineWidget->GetHandlePosition(0)); + } + splineWidget->GetPolyData(SplinePoly); + Stencil->Update(); + Actor->SetInput(Stencil->GetOutput()); + } + + TracerWidget->InitializeHandles(Points); + } + + vtkSW2Callback():Points(0),TracerWidget(0),Actor(0),Stencil(0),SplinePoly(0){} + + vtkPoints *Points; + vtkImageTracerWidget *TracerWidget; + vtkImageActor *Actor; + vtkImageStencil *Stencil; + vtkPolyData *SplinePoly; +}; + +int TestImageTracerWidget( int argc, char *argv[] ) +{ + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter"); + + // Increase polygon offsets to support some OpenGL drivers + vtkMapper::SetResolveCoincidentTopologyToPolygonOffset(); + vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(10,10); + +// Start by loading some data. +// + vtkVolume16Reader* v16 = vtkVolume16Reader::New(); + v16->SetDataDimensions(64, 64); + v16->SetDataByteOrderToLittleEndian(); + v16->SetImageRange(1, 93); + v16->SetDataSpacing(3.2, 3.2, 1.5); + v16->SetFilePrefix(fname); + v16->ReleaseDataFlagOn(); + v16->SetDataMask(0x7fff); + v16->Update(); + + delete[] fname; + + vtkRenderer* ren1 = vtkRenderer::New(); + vtkRenderer* ren2 = vtkRenderer::New(); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + renWin->AddRenderer(ren2); + + vtkInteractorStyleImage* interactorStyle = vtkInteractorStyleImage::New(); + + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetInteractorStyle(interactorStyle); + iren->SetRenderWindow(renWin); + + double range[2]; + v16->GetOutput()->GetScalarRange(range); + + vtkImageShiftScale* shifter = vtkImageShiftScale::New(); + shifter->SetShift(-1.0*range[0]); + shifter->SetScale(255.0/(range[1]-range[0])); + shifter->SetOutputScalarTypeToUnsignedChar(); + shifter->SetInputConnection(v16->GetOutputPort()); + shifter->ReleaseDataFlagOff(); + shifter->Update(); + +// Display a y-z plane. +// + vtkImageActor* imageActor1 = vtkImageActor::New(); + imageActor1->SetInput(shifter->GetOutput()); + imageActor1->VisibilityOn(); + imageActor1->SetDisplayExtent(31, 31, 0, 63, 0, 92); + imageActor1->InterpolateOff(); + + vtkExtractVOI* extract = vtkExtractVOI::New(); + extract->SetVOI(imageActor1->GetDisplayExtent()); + extract->SetSampleRate(1, 1, 1); + extract->SetInputConnection(shifter->GetOutputPort()); + extract->ReleaseDataFlagOff(); + + vtkImageActor* imageActor2 = vtkImageActor::New(); + imageActor2->SetInput(extract->GetOutput()); + imageActor2->VisibilityOn(); + imageActor2->SetDisplayExtent(extract->GetVOI()); + imageActor2->InterpolateOff(); + +// Set up the image tracer widget +// + vtkImageTracerWidget* imageTracerWidget = vtkImageTracerWidget::New(); + imageTracerWidget->SetDefaultRenderer(ren1); + imageTracerWidget->SetCaptureRadius(1.5); + imageTracerWidget->GetGlyphSource()->SetColor(1, 0, 0); + imageTracerWidget->GetGlyphSource()->SetScale(3.0); + imageTracerWidget->GetGlyphSource()->SetRotationAngle(45.0); + imageTracerWidget->GetGlyphSource()->Modified(); + imageTracerWidget->ProjectToPlaneOn(); + imageTracerWidget->SetProjectionNormalToXAxes(); + imageTracerWidget->SetProjectionPosition(imageActor1->GetBounds()[0]); + imageTracerWidget->SetViewProp(imageActor1); + imageTracerWidget->SetInput(shifter->GetOutput()); + imageTracerWidget->SetInteractor(iren); + imageTracerWidget->PlaceWidget(); + imageTracerWidget->SnapToImageOff(); + imageTracerWidget->AutoCloseOn(); + +// Set up a vtkSplineWidget in the second renderer and have +// its handles set by the tracer widget. +// + vtkSplineWidget* splineWidget = vtkSplineWidget::New(); + splineWidget->SetCurrentRenderer(ren2); + splineWidget->SetDefaultRenderer(ren2); + splineWidget->SetInput(extract->GetOutput()); + splineWidget->SetInteractor(iren); + splineWidget->PlaceWidget(imageActor2->GetBounds()); + splineWidget->ProjectToPlaneOn(); + splineWidget->SetProjectionNormalToXAxes(); + splineWidget->SetProjectionPosition(imageActor2->GetBounds()[0]); + + vtkPolyData* pathPoly = vtkPolyData::New(); + vtkPoints* points = vtkPoints::New(); + vtkPolyData* splinePoly = vtkPolyData::New(); + +// Set up a pipleline to demonstrate extraction of a 2D +// region of interest. +// + vtkLinearExtrusionFilter* extrude = vtkLinearExtrusionFilter::New(); + extrude->SetInput(splinePoly); + extrude->SetScaleFactor(1); + extrude->SetExtrusionTypeToNormalExtrusion(); + extrude->SetVector(1, 0, 0); + + vtkPolyDataToImageStencil* dataToStencil = vtkPolyDataToImageStencil::New(); + dataToStencil->SetInputConnection(extrude->GetOutputPort()); + + vtkImageStencil* stencil = vtkImageStencil::New(); + stencil->SetInputConnection(extract->GetOutputPort()); + stencil->SetStencil(dataToStencil->GetOutput()); + stencil->ReverseStencilOff(); + stencil->SetBackgroundValue(128); + +// Set up callbacks for widget interactions. +// + vtkITWCallback* itwCallback = vtkITWCallback::New(); + itwCallback->SplineWidget = splineWidget; + itwCallback->Actor = imageActor2; + itwCallback->Stencil = stencil; + itwCallback->Extract = extract; + itwCallback->PathPoly = pathPoly; + itwCallback->SplinePoly = splinePoly; + + imageTracerWidget->AddObserver(vtkCommand::EndInteractionEvent,itwCallback); + + vtkSW2Callback* swCallback = vtkSW2Callback::New(); + swCallback->Points = points; + swCallback->TracerWidget = imageTracerWidget; + swCallback->Actor = imageActor2; + swCallback->Stencil = stencil; + swCallback->SplinePoly = splinePoly; + + splineWidget->AddObserver(vtkCommand::EndInteractionEvent,swCallback); + + ren1->SetBackground(0.4, 0.4, 0.5); + ren1->SetViewport(0, 0, 0.5, 1); + ren1->AddViewProp(imageActor1); + ren2->SetBackground(0.5, 0.4, 0.4); + ren2->SetViewport(0.5, 0, 1, 1); + ren2->AddViewProp(imageActor2); + + ren1->ResetCamera(); + ren2->ResetCamera(); + renWin->SetSize(480, 240); + + imageTracerWidget->On(); + splineWidget->On(); + + vtkCamera* cam = ren1->GetActiveCamera(); + cam->SetViewUp(0, 1, 0); + cam->Azimuth(270); + cam->Roll(270); + cam->Dolly(1.7); + ren1->ResetCameraClippingRange(); + + cam = ren2->GetActiveCamera(); + cam->SetViewUp(0, 1, 0); + cam->Azimuth(270); + cam->Roll(270); + cam->Dolly(1.7); + ren2->ResetCameraClippingRange(); + + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(ImageTracerWidgetEventLog); + + iren->Initialize(); + + renWin->Render(); + + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + // + recorder->Off(); + recorder->Delete(); + + v16->Delete(); + shifter->Delete(); + extract->Delete(); + extrude->Delete(); + dataToStencil->Delete(); + stencil->Delete(); + imageActor1->Delete(); + imageActor2->Delete(); + pathPoly->Delete(); + points->Delete(); + splinePoly->Delete(); + imageTracerWidget->RemoveObserver(itwCallback); + imageTracerWidget->Delete(); + itwCallback->Delete(); + splineWidget->RemoveObserver(swCallback); + splineWidget->Delete(); + swCallback->Delete(); + interactorStyle->Delete(); + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + ren2->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestImplicitPlaneWidget.cxx b/Widgets/Testing/Cxx/TestImplicitPlaneWidget.cxx new file mode 100644 index 0000000..414f242 --- /dev/null +++ b/Widgets/Testing/Cxx/TestImplicitPlaneWidget.cxx @@ -0,0 +1,554 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestImplicitPlaneWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkAppendPolyData.h" +#include "vtkClipPolyData.h" +#include "vtkCommand.h" +#include "vtkConeSource.h" +#include "vtkGlyph3D.h" +#include "vtkImplicitPlaneWidget.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkLODActor.h" +#include "vtkPlane.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" + +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char eventLog[] = +"# StreamVersion 1\n" +"CharEvent 108 202 0 0 105 1 i\n" +"KeyReleaseEvent 108 202 0 0 105 1 i\n" +"MouseMoveEvent 255 120 0 0 0 0 i\n" +"MouseMoveEvent 255 121 0 0 0 0 i\n" +"MouseMoveEvent 255 122 0 0 0 0 i\n" +"MouseMoveEvent 255 123 0 0 0 0 i\n" +"MouseMoveEvent 255 125 0 0 0 0 i\n" +"MouseMoveEvent 255 126 0 0 0 0 i\n" +"MouseMoveEvent 253 129 0 0 0 0 i\n" +"MouseMoveEvent 253 133 0 0 0 0 i\n" +"MouseMoveEvent 253 138 0 0 0 0 i\n" +"MouseMoveEvent 253 141 0 0 0 0 i\n" +"MouseMoveEvent 251 147 0 0 0 0 i\n" +"MouseMoveEvent 251 146 0 0 0 0 i\n" +"MouseMoveEvent 251 147 0 0 0 0 i\n" +"MouseMoveEvent 251 148 0 0 0 0 i\n" +"LeftButtonPressEvent 251 148 0 0 0 0 i\n" +"MouseMoveEvent 251 149 0 0 0 0 i\n" +"MouseMoveEvent 251 150 0 0 0 0 i\n" +"MouseMoveEvent 251 151 0 0 0 0 i\n" +"MouseMoveEvent 251 152 0 0 0 0 i\n" +"MouseMoveEvent 251 153 0 0 0 0 i\n" +"MouseMoveEvent 251 154 0 0 0 0 i\n" +"MouseMoveEvent 250 154 0 0 0 0 i\n" +"MouseMoveEvent 250 155 0 0 0 0 i\n" +"MouseMoveEvent 250 157 0 0 0 0 i\n" +"MouseMoveEvent 250 158 0 0 0 0 i\n" +"MouseMoveEvent 250 159 0 0 0 0 i\n" +"MouseMoveEvent 249 160 0 0 0 0 i\n" +"MouseMoveEvent 249 161 0 0 0 0 i\n" +"MouseMoveEvent 249 163 0 0 0 0 i\n" +"MouseMoveEvent 249 166 0 0 0 0 i\n" +"MouseMoveEvent 249 167 0 0 0 0 i\n" +"MouseMoveEvent 249 169 0 0 0 0 i\n" +"MouseMoveEvent 249 170 0 0 0 0 i\n" +"MouseMoveEvent 249 171 0 0 0 0 i\n" +"MouseMoveEvent 248 172 0 0 0 0 i\n" +"MouseMoveEvent 248 174 0 0 0 0 i\n" +"MouseMoveEvent 247 174 0 0 0 0 i\n" +"MouseMoveEvent 247 175 0 0 0 0 i\n" +"MouseMoveEvent 247 174 0 0 0 0 i\n" +"MouseMoveEvent 247 172 0 0 0 0 i\n" +"MouseMoveEvent 246 170 0 0 0 0 i\n" +"MouseMoveEvent 245 170 0 0 0 0 i\n" +"MouseMoveEvent 244 170 0 0 0 0 i\n" +"MouseMoveEvent 239 168 0 0 0 0 i\n" +"MouseMoveEvent 235 166 0 0 0 0 i\n" +"MouseMoveEvent 232 166 0 0 0 0 i\n" +"MouseMoveEvent 232 167 0 0 0 0 i\n" +"MouseMoveEvent 231 167 0 0 0 0 i\n" +"MouseMoveEvent 230 168 0 0 0 0 i\n" +"MouseMoveEvent 229 170 0 0 0 0 i\n" +"MouseMoveEvent 227 173 0 0 0 0 i\n" +"MouseMoveEvent 227 174 0 0 0 0 i\n" +"MouseMoveEvent 226 176 0 0 0 0 i\n" +"MouseMoveEvent 224 180 0 0 0 0 i\n" +"MouseMoveEvent 224 182 0 0 0 0 i\n" +"MouseMoveEvent 224 184 0 0 0 0 i\n" +"MouseMoveEvent 224 186 0 0 0 0 i\n" +"MouseMoveEvent 221 190 0 0 0 0 i\n" +"MouseMoveEvent 218 191 0 0 0 0 i\n" +"MouseMoveEvent 218 192 0 0 0 0 i\n" +"MouseMoveEvent 218 195 0 0 0 0 i\n" +"MouseMoveEvent 217 200 0 0 0 0 i\n" +"MouseMoveEvent 217 203 0 0 0 0 i\n" +"MouseMoveEvent 217 207 0 0 0 0 i\n" +"MouseMoveEvent 217 208 0 0 0 0 i\n" +"MouseMoveEvent 217 210 0 0 0 0 i\n" +"MouseMoveEvent 217 211 0 0 0 0 i\n" +"MouseMoveEvent 217 214 0 0 0 0 i\n" +"MouseMoveEvent 217 216 0 0 0 0 i\n" +"MouseMoveEvent 217 217 0 0 0 0 i\n" +"MouseMoveEvent 219 218 0 0 0 0 i\n" +"MouseMoveEvent 220 219 0 0 0 0 i\n" +"MouseMoveEvent 220 222 0 0 0 0 i\n" +"MouseMoveEvent 220 225 0 0 0 0 i\n" +"MouseMoveEvent 220 227 0 0 0 0 i\n" +"MouseMoveEvent 220 228 0 0 0 0 i\n" +"MouseMoveEvent 220 230 0 0 0 0 i\n" +"MouseMoveEvent 220 232 0 0 0 0 i\n" +"MouseMoveEvent 220 236 0 0 0 0 i\n" +"MouseMoveEvent 220 237 0 0 0 0 i\n" +"MouseMoveEvent 220 238 0 0 0 0 i\n" +"MouseMoveEvent 220 239 0 0 0 0 i\n" +"MouseMoveEvent 219 239 0 0 0 0 i\n" +"MouseMoveEvent 218 239 0 0 0 0 i\n" +"MouseMoveEvent 217 239 0 0 0 0 i\n" +"MouseMoveEvent 217 238 0 0 0 0 i\n" +"MouseMoveEvent 217 237 0 0 0 0 i\n" +"LeftButtonReleaseEvent 217 237 0 0 0 0 i\n" +"MouseMoveEvent 213 233 0 0 0 0 i\n" +"MouseMoveEvent 212 231 0 0 0 0 i\n" +"MouseMoveEvent 212 227 0 0 0 0 i\n" +"MouseMoveEvent 211 225 0 0 0 0 i\n" +"MouseMoveEvent 211 221 0 0 0 0 i\n" +"MouseMoveEvent 208 216 0 0 0 0 i\n" +"MouseMoveEvent 206 214 0 0 0 0 i\n" +"MouseMoveEvent 206 210 0 0 0 0 i\n" +"MouseMoveEvent 206 206 0 0 0 0 i\n" +"MouseMoveEvent 206 201 0 0 0 0 i\n" +"MouseMoveEvent 206 198 0 0 0 0 i\n" +"MouseMoveEvent 206 194 0 0 0 0 i\n" +"MouseMoveEvent 206 189 0 0 0 0 i\n" +"MouseMoveEvent 206 185 0 0 0 0 i\n" +"MouseMoveEvent 206 180 0 0 0 0 i\n" +"MouseMoveEvent 205 175 0 0 0 0 i\n" +"MouseMoveEvent 203 171 0 0 0 0 i\n" +"MouseMoveEvent 202 168 0 0 0 0 i\n" +"MouseMoveEvent 202 161 0 0 0 0 i\n" +"MouseMoveEvent 201 156 0 0 0 0 i\n" +"MouseMoveEvent 200 150 0 0 0 0 i\n" +"MouseMoveEvent 198 147 0 0 0 0 i\n" +"MouseMoveEvent 198 143 0 0 0 0 i\n" +"MouseMoveEvent 196 140 0 0 0 0 i\n" +"MouseMoveEvent 196 136 0 0 0 0 i\n" +"MouseMoveEvent 193 131 0 0 0 0 i\n" +"MouseMoveEvent 192 121 0 0 0 0 i\n" +"MouseMoveEvent 192 114 0 0 0 0 i\n" +"MouseMoveEvent 192 109 0 0 0 0 i\n" +"MouseMoveEvent 192 104 0 0 0 0 i\n" +"MouseMoveEvent 192 100 0 0 0 0 i\n" +"MouseMoveEvent 192 97 0 0 0 0 i\n" +"MouseMoveEvent 189 93 0 0 0 0 i\n" +"MouseMoveEvent 188 92 0 0 0 0 i\n" +"MouseMoveEvent 187 90 0 0 0 0 i\n" +"MouseMoveEvent 186 89 0 0 0 0 i\n" +"MouseMoveEvent 185 88 0 0 0 0 i\n" +"MouseMoveEvent 184 86 0 0 0 0 i\n" +"MouseMoveEvent 184 85 0 0 0 0 i\n" +"MouseMoveEvent 183 85 0 0 0 0 i\n" +"MouseMoveEvent 182 84 0 0 0 0 i\n" +"MouseMoveEvent 180 83 0 0 0 0 i\n" +"MouseMoveEvent 179 83 0 0 0 0 i\n" +"MouseMoveEvent 178 83 0 0 0 0 i\n" +"MouseMoveEvent 175 82 0 0 0 0 i\n" +"MouseMoveEvent 173 81 0 0 0 0 i\n" +"MouseMoveEvent 169 79 0 0 0 0 i\n" +"MouseMoveEvent 168 78 0 0 0 0 i\n" +"MouseMoveEvent 167 78 0 0 0 0 i\n" +"MouseMoveEvent 167 79 0 0 0 0 i\n" +"LeftButtonPressEvent 167 79 0 0 0 0 i\n" +"MouseMoveEvent 167 80 0 0 0 0 i\n" +"MouseMoveEvent 167 81 0 0 0 0 i\n" +"MouseMoveEvent 169 82 0 0 0 0 i\n" +"MouseMoveEvent 170 83 0 0 0 0 i\n" +"MouseMoveEvent 171 84 0 0 0 0 i\n" +"MouseMoveEvent 172 84 0 0 0 0 i\n" +"MouseMoveEvent 174 85 0 0 0 0 i\n" +"MouseMoveEvent 174 86 0 0 0 0 i\n" +"MouseMoveEvent 175 86 0 0 0 0 i\n" +"MouseMoveEvent 176 88 0 0 0 0 i\n" +"MouseMoveEvent 177 90 0 0 0 0 i\n" +"MouseMoveEvent 177 91 0 0 0 0 i\n" +"MouseMoveEvent 177 92 0 0 0 0 i\n" +"MouseMoveEvent 177 93 0 0 0 0 i\n" +"MouseMoveEvent 177 94 0 0 0 0 i\n" +"MouseMoveEvent 178 96 0 0 0 0 i\n" +"MouseMoveEvent 178 97 0 0 0 0 i\n" +"MouseMoveEvent 180 99 0 0 0 0 i\n" +"MouseMoveEvent 181 99 0 0 0 0 i\n" +"MouseMoveEvent 181 100 0 0 0 0 i\n" +"MouseMoveEvent 181 101 0 0 0 0 i\n" +"MouseMoveEvent 181 102 0 0 0 0 i\n" +"MouseMoveEvent 181 103 0 0 0 0 i\n" +"LeftButtonReleaseEvent 181 103 0 0 0 0 i\n" +"MouseMoveEvent 181 103 0 0 0 0 i\n" +"MouseMoveEvent 181 102 0 0 0 0 i\n" +"MouseMoveEvent 181 102 0 0 0 0 i\n" +"MouseMoveEvent 181 102 0 0 0 0 i\n" +"MouseMoveEvent 182 102 0 0 0 0 i\n" +"MouseMoveEvent 183 103 0 0 0 0 i\n" +"MouseMoveEvent 183 102 0 0 0 0 i\n" +"MouseMoveEvent 184 102 0 0 0 0 i\n" +"MouseMoveEvent 185 102 0 0 0 0 i\n" +"MouseMoveEvent 185 101 0 0 0 0 i\n" +"MouseMoveEvent 185 100 0 0 0 0 i\n" +"MouseMoveEvent 185 99 0 0 0 0 i\n" +"MiddleButtonPressEvent 185 99 0 0 0 0 i\n" +"MouseMoveEvent 185 100 0 0 0 0 i\n" +"MouseMoveEvent 182 101 0 0 0 0 i\n" +"MouseMoveEvent 181 102 0 0 0 0 i\n" +"MouseMoveEvent 180 103 0 0 0 0 i\n" +"MouseMoveEvent 179 105 0 0 0 0 i\n" +"MouseMoveEvent 176 107 0 0 0 0 i\n" +"MouseMoveEvent 173 105 0 0 0 0 i\n" +"MouseMoveEvent 173 106 0 0 0 0 i\n" +"MouseMoveEvent 173 107 0 0 0 0 i\n" +"MouseMoveEvent 173 108 0 0 0 0 i\n" +"MouseMoveEvent 173 110 0 0 0 0 i\n" +"MouseMoveEvent 172 112 0 0 0 0 i\n" +"MouseMoveEvent 172 113 0 0 0 0 i\n" +"MouseMoveEvent 172 114 0 0 0 0 i\n" +"MouseMoveEvent 172 115 0 0 0 0 i\n" +"MouseMoveEvent 173 116 0 0 0 0 i\n" +"MouseMoveEvent 173 117 0 0 0 0 i\n" +"MouseMoveEvent 174 118 0 0 0 0 i\n" +"MouseMoveEvent 174 119 0 0 0 0 i\n" +"MouseMoveEvent 174 120 0 0 0 0 i\n" +"MouseMoveEvent 174 121 0 0 0 0 i\n" +"MouseMoveEvent 174 122 0 0 0 0 i\n" +"MouseMoveEvent 175 122 0 0 0 0 i\n" +"MiddleButtonReleaseEvent 175 122 0 0 0 0 i\n" +"MouseMoveEvent 175 122 0 0 0 0 i\n" +"MouseMoveEvent 175 121 0 0 0 0 i\n" +"MouseMoveEvent 174 120 0 0 0 0 i\n" +"MouseMoveEvent 173 120 0 0 0 0 i\n" +"MouseMoveEvent 173 119 0 0 0 0 i\n" +"MouseMoveEvent 173 118 0 0 0 0 i\n" +"MouseMoveEvent 172 117 0 0 0 0 i\n" +"MouseMoveEvent 171 117 0 0 0 0 i\n" +"MouseMoveEvent 171 116 0 0 0 0 i\n" +"MouseMoveEvent 171 115 0 0 0 0 i\n" +"MouseMoveEvent 171 114 0 0 0 0 i\n" +"MouseMoveEvent 171 112 0 0 0 0 i\n" +"MouseMoveEvent 171 109 0 0 0 0 i\n" +"MouseMoveEvent 172 107 0 0 0 0 i\n" +"MouseMoveEvent 172 105 0 0 0 0 i\n" +"MouseMoveEvent 175 103 0 0 0 0 i\n" +"MouseMoveEvent 176 100 0 0 0 0 i\n" +"MouseMoveEvent 178 99 0 0 0 0 i\n" +"MouseMoveEvent 179 97 0 0 0 0 i\n" +"MouseMoveEvent 182 94 0 0 0 0 i\n" +"MouseMoveEvent 183 92 0 0 0 0 i\n" +"MouseMoveEvent 185 90 0 0 0 0 i\n" +"MouseMoveEvent 186 87 0 0 0 0 i\n" +"MouseMoveEvent 188 84 0 0 0 0 i\n" +"MouseMoveEvent 190 81 0 0 0 0 i\n" +"MouseMoveEvent 193 79 0 0 0 0 i\n" +"MouseMoveEvent 195 78 0 0 0 0 i\n" +"MouseMoveEvent 197 76 0 0 0 0 i\n" +"MouseMoveEvent 201 75 0 0 0 0 i\n" +"MouseMoveEvent 205 71 0 0 0 0 i\n" +"MouseMoveEvent 209 67 0 0 0 0 i\n" +"MouseMoveEvent 215 63 0 0 0 0 i\n" +"MouseMoveEvent 221 58 0 0 0 0 i\n" +"MouseMoveEvent 226 56 0 0 0 0 i\n" +"MouseMoveEvent 228 54 0 0 0 0 i\n" +"MouseMoveEvent 231 50 0 0 0 0 i\n" +"MouseMoveEvent 235 47 0 0 0 0 i\n" +"MouseMoveEvent 237 45 0 0 0 0 i\n" +"MouseMoveEvent 239 42 0 0 0 0 i\n" +"MouseMoveEvent 243 42 0 0 0 0 i\n" +"MouseMoveEvent 245 41 0 0 0 0 i\n" +"MouseMoveEvent 246 40 0 0 0 0 i\n" +"MouseMoveEvent 246 39 0 0 0 0 i\n" +"MouseMoveEvent 247 39 0 0 0 0 i\n" +"MouseMoveEvent 248 38 0 0 0 0 i\n" +"MouseMoveEvent 249 38 0 0 0 0 i\n" +"MouseMoveEvent 250 38 0 0 0 0 i\n" +"MouseMoveEvent 250 37 0 0 0 0 i\n" +"MouseMoveEvent 252 36 0 0 0 0 i\n" +"MouseMoveEvent 253 36 0 0 0 0 i\n" +"MouseMoveEvent 254 36 0 0 0 0 i\n" +"MouseMoveEvent 254 37 0 0 0 0 i\n" +"MouseMoveEvent 255 37 0 0 0 0 i\n" +"MouseMoveEvent 256 37 0 0 0 0 i\n" +"MouseMoveEvent 257 37 0 0 0 0 i\n" +"MouseMoveEvent 258 37 0 0 0 0 i\n" +"MouseMoveEvent 259 38 0 0 0 0 i\n" +"MouseMoveEvent 260 39 0 0 0 0 i\n" +"MouseMoveEvent 260 40 0 0 0 0 i\n" +"MouseMoveEvent 259 40 0 0 0 0 i\n" +"MouseMoveEvent 258 40 0 0 0 0 i\n" +"MouseMoveEvent 257 40 0 0 0 0 i\n" +"MouseMoveEvent 257 41 0 0 0 0 i\n" +"MouseMoveEvent 257 42 0 0 0 0 i\n" +"MouseMoveEvent 257 43 0 0 0 0 i\n" +"MouseMoveEvent 257 44 0 0 0 0 i\n" +"MouseMoveEvent 258 44 0 0 0 0 i\n" +"LeftButtonPressEvent 258 44 0 0 0 0 i\n" +"MouseMoveEvent 258 45 0 0 0 0 i\n" +"MouseMoveEvent 259 45 0 0 0 0 i\n" +"MouseMoveEvent 259 46 0 0 0 0 i\n" +"MouseMoveEvent 259 47 0 0 0 0 i\n" +"MouseMoveEvent 259 49 0 0 0 0 i\n" +"MouseMoveEvent 259 50 0 0 0 0 i\n" +"MouseMoveEvent 259 51 0 0 0 0 i\n" +"MouseMoveEvent 259 52 0 0 0 0 i\n" +"MouseMoveEvent 260 53 0 0 0 0 i\n" +"MouseMoveEvent 260 54 0 0 0 0 i\n" +"MouseMoveEvent 260 55 0 0 0 0 i\n" +"MouseMoveEvent 260 56 0 0 0 0 i\n" +"MouseMoveEvent 260 57 0 0 0 0 i\n" +"MouseMoveEvent 261 58 0 0 0 0 i\n" +"MouseMoveEvent 261 59 0 0 0 0 i\n" +"MouseMoveEvent 261 60 0 0 0 0 i\n" +"MouseMoveEvent 261 61 0 0 0 0 i\n" +"MouseMoveEvent 261 60 0 0 0 0 i\n" +"MouseMoveEvent 260 59 0 0 0 0 i\n" +"MouseMoveEvent 258 58 0 0 0 0 i\n" +"MouseMoveEvent 255 57 0 0 0 0 i\n" +"MouseMoveEvent 252 55 0 0 0 0 i\n" +"MouseMoveEvent 251 54 0 0 0 0 i\n" +"MouseMoveEvent 251 53 0 0 0 0 i\n" +"MouseMoveEvent 249 51 0 0 0 0 i\n" +"MouseMoveEvent 246 50 0 0 0 0 i\n" +"MouseMoveEvent 245 50 0 0 0 0 i\n" +"MouseMoveEvent 245 49 0 0 0 0 i\n" +"MouseMoveEvent 244 48 0 0 0 0 i\n" +"MouseMoveEvent 242 45 0 0 0 0 i\n" +"MouseMoveEvent 241 44 0 0 0 0 i\n" +"MouseMoveEvent 240 44 0 0 0 0 i\n" +"MouseMoveEvent 239 44 0 0 0 0 i\n" +"MouseMoveEvent 238 42 0 0 0 0 i\n" +"MouseMoveEvent 237 42 0 0 0 0 i\n" +"MouseMoveEvent 236 42 0 0 0 0 i\n" +"MouseMoveEvent 236 41 0 0 0 0 i\n" +"LeftButtonReleaseEvent 236 41 0 0 0 0 i\n" +"MouseMoveEvent 236 40 0 0 0 0 i\n" +"MouseMoveEvent 235 40 0 0 0 0 i\n" +"MouseMoveEvent 234 40 0 0 0 0 i\n" +"MouseMoveEvent 233 40 0 0 0 0 i\n" +"MouseMoveEvent 233 41 0 0 0 0 i\n" +"MouseMoveEvent 233 42 0 0 0 0 i\n" +"MouseMoveEvent 232 42 0 0 0 0 i\n" +"MouseMoveEvent 231 42 0 0 0 0 i\n" +"MouseMoveEvent 231 43 0 0 0 0 i\n" +"RightButtonPressEvent 231 43 0 0 0 0 i\n" +"MouseMoveEvent 231 42 0 0 0 0 i\n" +"MouseMoveEvent 231 41 0 0 0 0 i\n" +"MouseMoveEvent 231 40 0 0 0 0 i\n" +"MouseMoveEvent 230 40 0 0 0 0 i\n" +"MouseMoveEvent 229 38 0 0 0 0 i\n" +"MouseMoveEvent 227 33 0 0 0 0 i\n" +"MouseMoveEvent 226 27 0 0 0 0 i\n" +"MouseMoveEvent 222 23 0 0 0 0 i\n" +"MouseMoveEvent 214 19 0 0 0 0 i\n" +"MouseMoveEvent 208 14 0 0 0 0 i\n" +"MouseMoveEvent 208 15 0 0 0 0 i\n" +"MouseMoveEvent 208 14 0 0 0 0 i\n" +"MouseMoveEvent 208 13 0 0 0 0 i\n" +"MouseMoveEvent 210 11 0 0 0 0 i\n" +"MouseMoveEvent 213 9 0 0 0 0 i\n" +"MouseMoveEvent 214 8 0 0 0 0 i\n" +"MouseMoveEvent 214 7 0 0 0 0 i\n" +"MouseMoveEvent 215 7 0 0 0 0 i\n" +"MouseMoveEvent 215 6 0 0 0 0 i\n" +"MouseMoveEvent 215 5 0 0 0 0 i\n" +"MouseMoveEvent 216 2 0 0 0 0 i\n" +"MouseMoveEvent 218 1 0 0 0 0 i\n" +"LeaveEvent 220 -1 0 0 0 0 i\n" +"MouseMoveEvent 220 -1 0 0 0 0 i\n" +"MouseMoveEvent 221 -1 0 0 0 0 i\n" +"MouseMoveEvent 221 -2 0 0 0 0 i\n" +"MouseMoveEvent 220 -2 0 0 0 0 i\n" +"MouseMoveEvent 220 -3 0 0 0 0 i\n" +"MouseMoveEvent 220 -4 0 0 0 0 i\n" +"MouseMoveEvent 220 -5 0 0 0 0 i\n" +"MouseMoveEvent 220 -6 0 0 0 0 i\n" +"MouseMoveEvent 220 -7 0 0 0 0 i\n" +"MouseMoveEvent 220 -8 0 0 0 0 i\n" +"MouseMoveEvent 220 -9 0 0 0 0 i\n" +"MouseMoveEvent 220 -11 0 0 0 0 i\n" +"MouseMoveEvent 220 -12 0 0 0 0 i\n" +"MouseMoveEvent 220 -13 0 0 0 0 i\n" +"MouseMoveEvent 220 -12 0 0 0 0 i\n" +"MouseMoveEvent 220 -11 0 0 0 0 i\n" +"RightButtonReleaseEvent 220 -11 0 0 0 0 i\n" +"EnterEvent 218 0 0 0 0 0 i\n" +"MouseMoveEvent 218 0 0 0 0 0 i\n" +"MouseMoveEvent 218 1 0 0 0 0 i\n" +"MouseMoveEvent 218 2 0 0 0 0 i\n" +"MouseMoveEvent 217 2 0 0 0 0 i\n" +"MouseMoveEvent 217 4 0 0 0 0 i\n" +"MouseMoveEvent 217 5 0 0 0 0 i\n" +"MouseMoveEvent 217 6 0 0 0 0 i\n" +"MouseMoveEvent 217 7 0 0 0 0 i\n" +"MouseMoveEvent 217 8 0 0 0 0 i\n" +"MouseMoveEvent 217 9 0 0 0 0 i\n" +"MouseMoveEvent 216 11 0 0 0 0 i\n" +"MouseMoveEvent 216 12 0 0 0 0 i\n" +"MouseMoveEvent 215 12 0 0 0 0 i\n" +"MouseMoveEvent 215 11 0 0 0 0 i\n" +"MouseMoveEvent 215 12 0 0 0 0 i\n" +"MouseMoveEvent 215 13 0 0 0 0 i\n" +"MouseMoveEvent 215 14 0 0 0 0 i\n" +; + +// This does the actual work: updates the vtkPlane implicit function. +// This in turn causes the pipeline to update and clip the object. +// Callback for the interaction +class vtkTIPWCallback : public vtkCommand +{ +public: + static vtkTIPWCallback *New() + { return new vtkTIPWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkImplicitPlaneWidget *planeWidget = + reinterpret_cast<vtkImplicitPlaneWidget*>(caller); + planeWidget->GetPlane(this->Plane); + this->Actor->VisibilityOn(); + } + vtkTIPWCallback():Plane(0),Actor(0) {} + vtkPlane *Plane; + vtkActor *Actor; + +}; + +int TestImplicitPlaneWidget( int argc, char *argv[] ) +{ + // Create a mace out of filters. + // + vtkSphereSource *sphere = vtkSphereSource::New(); + vtkConeSource *cone = vtkConeSource::New(); + vtkGlyph3D *glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(sphere->GetOutputPort()); + glyph->SetSource(cone->GetOutput()); + glyph->SetVectorModeToUseNormal(); + glyph->SetScaleModeToScaleByVector(); + glyph->SetScaleFactor(0.25); + + // The sphere and spikes are appended into a single polydata. + // This just makes things simpler to manage. + vtkAppendPolyData *apd = vtkAppendPolyData::New(); + apd->AddInput(glyph->GetOutput()); + apd->AddInput(sphere->GetOutput()); + + vtkPolyDataMapper *maceMapper = vtkPolyDataMapper::New(); + maceMapper->SetInputConnection(apd->GetOutputPort()); + + vtkLODActor *maceActor = vtkLODActor::New(); + maceActor->SetMapper(maceMapper); + maceActor->VisibilityOn(); + + // This portion of the code clips the mace with the vtkPlanes + // implicit function. The clipped region is colored green. + vtkPlane *plane = vtkPlane::New(); + vtkClipPolyData *clipper = vtkClipPolyData::New(); + clipper->SetInputConnection(apd->GetOutputPort()); + clipper->SetClipFunction(plane); + clipper->InsideOutOn(); + + vtkPolyDataMapper *selectMapper = vtkPolyDataMapper::New(); + selectMapper->SetInputConnection(clipper->GetOutputPort()); + + vtkLODActor *selectActor = vtkLODActor::New(); + selectActor->SetMapper(selectMapper); + selectActor->GetProperty()->SetColor(0,1,0); + selectActor->VisibilityOff(); + selectActor->SetScale(1.01, 1.01, 1.01); + + // Create the RenderWindow, Renderer and both Actors + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The SetInteractor method is how 3D widgets are associated with the render + // window interactor. Internally, SetInteractor sets up a bunch of callbacks + // using the Command/Observer mechanism (AddObserver()). + vtkTIPWCallback *myCallback = vtkTIPWCallback::New(); + myCallback->Plane = plane; + myCallback->Actor = selectActor; + + vtkImplicitPlaneWidget *planeWidget = vtkImplicitPlaneWidget::New(); + planeWidget->SetInteractor(iren); + planeWidget->SetPlaceFactor(1.25); + planeWidget->SetInput(glyph->GetOutput()); + planeWidget->PlaceWidget(); + planeWidget->AddObserver(vtkCommand::InteractionEvent,myCallback); + + ren1->AddActor(maceActor); + ren1->AddActor(selectActor); + + // Add the actors to the renderer, set the background and size + // + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(300, 300); + + // record events + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); +// recorder->SetFileName("c:/record.log"); +// recorder->Record(); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(eventLog); + + // render the image + // + iren->Initialize(); + renWin->Render(); + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + recorder->Off(); + recorder->Delete(); + myCallback->Delete(); + sphere->Delete(); + cone->Delete(); + glyph->Delete(); + apd->Delete(); + maceMapper->Delete(); + maceActor->Delete(); + plane->Delete(); + clipper->Delete(); + selectMapper->Delete(); + selectActor->Delete(); + planeWidget->Delete(); + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestLineWidget.cxx b/Widgets/Testing/Cxx/TestLineWidget.cxx new file mode 100644 index 0000000..c5ccca4 --- /dev/null +++ b/Widgets/Testing/Cxx/TestLineWidget.cxx @@ -0,0 +1,384 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestLineWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCommand.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkLineWidget.h" +#include "vtkPLOT3DReader.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkRibbonFilter.h" +#include "vtkRungeKutta4.h" +#include "vtkStreamLine.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridOutlineFilter.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char TestLineWidgetEventLog[] = +"# StreamVersion 1\n" +"CharEvent 185 179 0 0 105 1 i\n" +"KeyReleaseEvent 185 179 0 0 105 1 i\n" +"MouseMoveEvent 185 178 0 0 0 0 i\n" +"MouseMoveEvent 184 178 0 0 0 0 i\n" +"MouseMoveEvent 183 178 0 0 0 0 i\n" +"MouseMoveEvent 182 177 0 0 0 0 i\n" +"MouseMoveEvent 179 174 0 0 0 0 i\n" +"MouseMoveEvent 178 172 0 0 0 0 i\n" +"MouseMoveEvent 175 171 0 0 0 0 i\n" +"MouseMoveEvent 173 169 0 0 0 0 i\n" +"MouseMoveEvent 170 166 0 0 0 0 i\n" +"MouseMoveEvent 167 165 0 0 0 0 i\n" +"MouseMoveEvent 161 162 0 0 0 0 i\n" +"MouseMoveEvent 159 160 0 0 0 0 i\n" +"MouseMoveEvent 157 159 0 0 0 0 i\n" +"MouseMoveEvent 156 158 0 0 0 0 i\n" +"MouseMoveEvent 156 157 0 0 0 0 i\n" +"MouseMoveEvent 156 156 0 0 0 0 i\n" +"MouseMoveEvent 156 155 0 0 0 0 i\n" +"MouseMoveEvent 155 155 0 0 0 0 i\n" +"MouseMoveEvent 155 154 0 0 0 0 i\n" +"MouseMoveEvent 155 153 0 0 0 0 i\n" +"MouseMoveEvent 154 153 0 0 0 0 i\n" +"MouseMoveEvent 152 152 0 0 0 0 i\n" +"MouseMoveEvent 151 150 0 0 0 0 i\n" +"MouseMoveEvent 148 150 0 0 0 0 i\n" +"MouseMoveEvent 148 149 0 0 0 0 i\n" +"MouseMoveEvent 148 150 0 0 0 0 i\n" +"LeftButtonPressEvent 148 150 0 0 0 0 i\n" +"MouseMoveEvent 148 151 0 0 0 0 i\n" +"MouseMoveEvent 146 151 0 0 0 0 i\n" +"MouseMoveEvent 143 151 0 0 0 0 i\n" +"MouseMoveEvent 142 151 0 0 0 0 i\n" +"MouseMoveEvent 142 152 0 0 0 0 i\n" +"MouseMoveEvent 141 151 0 0 0 0 i\n" +"MouseMoveEvent 136 149 0 0 0 0 i\n" +"MouseMoveEvent 134 149 0 0 0 0 i\n" +"MouseMoveEvent 133 149 0 0 0 0 i\n" +"MouseMoveEvent 132 149 0 0 0 0 i\n" +"MouseMoveEvent 131 149 0 0 0 0 i\n" +"MouseMoveEvent 131 150 0 0 0 0 i\n" +"MouseMoveEvent 130 150 0 0 0 0 i\n" +"MouseMoveEvent 131 150 0 0 0 0 i\n" +"MouseMoveEvent 136 150 0 0 0 0 i\n" +"LeftButtonReleaseEvent 136 150 0 0 0 0 i\n" +"MouseMoveEvent 136 150 0 0 0 0 i\n" +"MouseMoveEvent 136 151 0 0 0 0 i\n" +"MouseMoveEvent 137 151 0 0 0 0 i\n" +"MouseMoveEvent 138 151 0 0 0 0 i\n" +"MouseMoveEvent 138 152 0 0 0 0 i\n" +"MouseMoveEvent 139 152 0 0 0 0 i\n" +"RightButtonPressEvent 139 152 0 0 0 0 i\n" +"MouseMoveEvent 138 152 0 0 0 0 i\n" +"MouseMoveEvent 137 152 0 0 0 0 i\n" +"MouseMoveEvent 137 153 0 0 0 0 i\n" +"MouseMoveEvent 136 154 0 0 0 0 i\n" +"MouseMoveEvent 136 156 0 0 0 0 i\n" +"MouseMoveEvent 136 157 0 0 0 0 i\n" +"MouseMoveEvent 136 158 0 0 0 0 i\n" +"MouseMoveEvent 137 159 0 0 0 0 i\n" +"MouseMoveEvent 136 159 0 0 0 0 i\n" +"MouseMoveEvent 136 160 0 0 0 0 i\n" +"MouseMoveEvent 136 161 0 0 0 0 i\n" +"MouseMoveEvent 136 160 0 0 0 0 i\n" +"MouseMoveEvent 136 158 0 0 0 0 i\n" +"MouseMoveEvent 136 157 0 0 0 0 i\n" +"MouseMoveEvent 136 155 0 0 0 0 i\n" +"MouseMoveEvent 135 152 0 0 0 0 i\n" +"MouseMoveEvent 135 149 0 0 0 0 i\n" +"MouseMoveEvent 136 147 0 0 0 0 i\n" +"MouseMoveEvent 136 146 0 0 0 0 i\n" +"MouseMoveEvent 136 144 0 0 0 0 i\n" +"MouseMoveEvent 136 143 0 0 0 0 i\n" +"MouseMoveEvent 136 141 0 0 0 0 i\n" +"MouseMoveEvent 136 140 0 0 0 0 i\n" +"MouseMoveEvent 136 139 0 0 0 0 i\n" +"MouseMoveEvent 135 139 0 0 0 0 i\n" +"MouseMoveEvent 135 137 0 0 0 0 i\n" +"MouseMoveEvent 135 136 0 0 0 0 i\n" +"MouseMoveEvent 134 136 0 0 0 0 i\n" +"MouseMoveEvent 135 136 0 0 0 0 i\n" +"RightButtonReleaseEvent 135 136 0 0 0 0 i\n" +"MouseMoveEvent 135 136 0 0 0 0 i\n" +"MouseMoveEvent 135 137 0 0 0 0 i\n" +"MouseMoveEvent 135 138 0 0 0 0 i\n" +"MouseMoveEvent 135 137 0 0 0 0 i\n" +"MouseMoveEvent 134 136 0 0 0 0 i\n" +"MouseMoveEvent 134 135 0 0 0 0 i\n" +"MouseMoveEvent 134 134 0 0 0 0 i\n" +"MouseMoveEvent 134 133 0 0 0 0 i\n" +"MouseMoveEvent 134 132 0 0 0 0 i\n" +"MouseMoveEvent 134 131 0 0 0 0 i\n" +"MouseMoveEvent 134 130 0 0 0 0 i\n" +"MouseMoveEvent 135 130 0 0 0 0 i\n" +"MouseMoveEvent 135 129 0 0 0 0 i\n" +"MouseMoveEvent 136 129 0 0 0 0 i\n" +"MouseMoveEvent 137 129 0 0 0 0 i\n" +"MouseMoveEvent 137 128 0 0 0 0 i\n" +"MouseMoveEvent 138 128 0 0 0 0 i\n" +"MouseMoveEvent 138 129 0 0 0 0 i\n" +"MouseMoveEvent 137 130 0 0 0 0 i\n" +"MouseMoveEvent 137 131 0 0 0 0 i\n" +"MouseMoveEvent 137 132 0 0 0 0 i\n" +"MouseMoveEvent 137 131 0 0 0 0 i\n" +"LeftButtonPressEvent 137 131 0 0 0 0 i\n" +"MouseMoveEvent 137 130 0 0 0 0 i\n" +"MouseMoveEvent 137 128 0 0 0 0 i\n" +"MouseMoveEvent 137 127 0 0 0 0 i\n" +"MouseMoveEvent 138 127 0 0 0 0 i\n" +"MouseMoveEvent 140 127 0 0 0 0 i\n" +"MouseMoveEvent 141 126 0 0 0 0 i\n" +"MouseMoveEvent 143 126 0 0 0 0 i\n" +"MouseMoveEvent 148 123 0 0 0 0 i\n" +"MouseMoveEvent 149 123 0 0 0 0 i\n" +"MouseMoveEvent 149 122 0 0 0 0 i\n" +"MouseMoveEvent 150 122 0 0 0 0 i\n" +"MouseMoveEvent 151 122 0 0 0 0 i\n" +"MouseMoveEvent 152 122 0 0 0 0 i\n" +"MouseMoveEvent 153 121 0 0 0 0 i\n" +"MouseMoveEvent 155 121 0 0 0 0 i\n" +"LeftButtonReleaseEvent 155 121 0 0 0 0 i\n" +"MouseMoveEvent 155 121 0 0 0 0 i\n" +"MouseMoveEvent 155 122 0 0 0 0 i\n" +"MouseMoveEvent 155 123 0 0 0 0 i\n" +"MouseMoveEvent 155 124 0 0 0 0 i\n" +"MouseMoveEvent 155 126 0 0 0 0 i\n" +"MouseMoveEvent 155 127 0 0 0 0 i\n" +"MouseMoveEvent 155 129 0 0 0 0 i\n" +"MouseMoveEvent 153 132 0 0 0 0 i\n" +"MouseMoveEvent 153 135 0 0 0 0 i\n" +"MouseMoveEvent 152 139 0 0 0 0 i\n" +"MouseMoveEvent 152 140 0 0 0 0 i\n" +"MouseMoveEvent 151 142 0 0 0 0 i\n" +"MouseMoveEvent 151 143 0 0 0 0 i\n" +"MouseMoveEvent 151 145 0 0 0 0 i\n" +"MouseMoveEvent 150 146 0 0 0 0 i\n" +"MouseMoveEvent 149 147 0 0 0 0 i\n" +"MouseMoveEvent 149 149 0 0 0 0 i\n" +"MouseMoveEvent 148 151 0 0 0 0 i\n" +"MouseMoveEvent 146 152 0 0 0 0 i\n" +"MouseMoveEvent 143 154 0 0 0 0 i\n" +"MouseMoveEvent 142 155 0 0 0 0 i\n" +"MouseMoveEvent 141 155 0 0 0 0 i\n" +"MouseMoveEvent 141 156 0 0 0 0 i\n" +"MouseMoveEvent 141 157 0 0 0 0 i\n" +"MouseMoveEvent 141 158 0 0 0 0 i\n" +"MouseMoveEvent 141 159 0 0 0 0 i\n" +"MouseMoveEvent 142 160 0 0 0 0 i\n" +"MouseMoveEvent 142 161 0 0 0 0 i\n" +"MouseMoveEvent 142 162 0 0 0 0 i\n" +"MouseMoveEvent 141 162 0 0 0 0 i\n" +"MouseMoveEvent 140 162 0 0 0 0 i\n" +"MouseMoveEvent 138 162 0 0 0 0 i\n" +"MouseMoveEvent 137 163 0 0 0 0 i\n" +"MouseMoveEvent 137 164 0 0 0 0 i\n" +"MouseMoveEvent 137 165 0 0 0 0 i\n" +"MouseMoveEvent 137 166 0 0 0 0 i\n" +"MouseMoveEvent 137 167 0 0 0 0 i\n" +"LeftButtonPressEvent 137 167 0 0 0 0 i\n" +"MouseMoveEvent 138 167 0 0 0 0 i\n" +"MouseMoveEvent 139 168 0 0 0 0 i\n" +"MouseMoveEvent 140 168 0 0 0 0 i\n" +"MouseMoveEvent 141 168 0 0 0 0 i\n" +"MouseMoveEvent 142 168 0 0 0 0 i\n" +"MouseMoveEvent 143 168 0 0 0 0 i\n" +"MouseMoveEvent 144 169 0 0 0 0 i\n" +"MouseMoveEvent 145 169 0 0 0 0 i\n" +"MouseMoveEvent 146 169 0 0 0 0 i\n" +"MouseMoveEvent 146 170 0 0 0 0 i\n" +"MouseMoveEvent 146 171 0 0 0 0 i\n" +"MouseMoveEvent 147 171 0 0 0 0 i\n" +"MouseMoveEvent 148 171 0 0 0 0 i\n" +"MouseMoveEvent 149 172 0 0 0 0 i\n" +"MouseMoveEvent 150 172 0 0 0 0 i\n" +"MouseMoveEvent 151 172 0 0 0 0 i\n" +"MouseMoveEvent 152 172 0 0 0 0 i\n" +"MouseMoveEvent 154 172 0 0 0 0 i\n" +"MouseMoveEvent 155 172 0 0 0 0 i\n" +"MouseMoveEvent 156 172 0 0 0 0 i\n" +"MouseMoveEvent 157 172 0 0 0 0 i\n" +"MouseMoveEvent 158 171 0 0 0 0 i\n" +"MouseMoveEvent 160 171 0 0 0 0 i\n" +"MouseMoveEvent 162 170 0 0 0 0 i\n" +"MouseMoveEvent 163 170 0 0 0 0 i\n" +"MouseMoveEvent 164 170 0 0 0 0 i\n" +"MouseMoveEvent 165 170 0 0 0 0 i\n" +"LeftButtonReleaseEvent 165 170 0 0 0 0 i\n" +"MouseMoveEvent 165 170 0 0 0 0 i\n" +; + +// This does the actual work: updates the probe. +// Callback for the interaction +class vtkLWCallback : public vtkCommand +{ +public: + static vtkLWCallback *New() + { return new vtkLWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkLineWidget *lineWidget = reinterpret_cast<vtkLineWidget*>(caller); + lineWidget->GetPolyData(this->PolyData); + this->Actor->VisibilityOn(); + } + vtkLWCallback():PolyData(0),Actor(0) {} + vtkPolyData *PolyData; + vtkActor *Actor; +}; + +int TestLineWidget( int argc, char *argv[] ) +{ + char* fname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combxyz.bin"); + char* fname2 = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combq.bin"); + + // Start by loading some data. + // + vtkPLOT3DReader *pl3d = vtkPLOT3DReader::New(); + pl3d->SetXYZFileName(fname); + pl3d->SetQFileName(fname2); + pl3d->SetScalarFunctionNumber(100); + pl3d->SetVectorFunctionNumber(202); + pl3d->Update(); + + delete [] fname; + delete [] fname2; + + vtkPolyData *seeds = vtkPolyData::New(); + + // Create streamtues + vtkRungeKutta4 *rk4 = vtkRungeKutta4::New(); + + vtkStreamLine *streamer = vtkStreamLine::New(); + streamer->SetInputConnection(pl3d->GetOutputPort()); + streamer->SetSource(seeds); + streamer->SetMaximumPropagationTime(100); + streamer->SetIntegrationStepLength(.2); + streamer->SetStepLength(.001); + streamer->SetNumberOfThreads(1); + streamer->SetIntegrationDirectionToForward(); + streamer->VorticityOn(); + streamer->SetIntegrator(rk4); + + vtkRibbonFilter *rf = vtkRibbonFilter::New(); + rf->SetInputConnection(streamer->GetOutputPort()); + rf->SetWidth(0.1); + rf->SetWidthFactor(5); + + vtkPolyDataMapper *streamMapper = vtkPolyDataMapper::New(); + streamMapper->SetInputConnection(rf->GetOutputPort()); + double tmp[2]; + pl3d->GetOutput()->GetScalarRange(tmp); + streamMapper->SetScalarRange(tmp[0], tmp[1]); + + vtkActor *streamline =vtkActor::New(); + streamline->SetMapper(streamMapper); + streamline->VisibilityOff(); + + // An outline is shown for context. + vtkStructuredGridOutlineFilter *outline = + vtkStructuredGridOutlineFilter::New(); + outline->SetInputConnection(pl3d->GetOutputPort()); + + vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + + vtkActor *outlineActor = vtkActor::New(); + outlineActor->SetMapper(outlineMapper); + + // Create the RenderWindow, Renderer and both Actors + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The SetInteractor method is how 3D widgets are associated with the render + // window interactor. Internally, SetInteractor sets up a bunch of callbacks + // using the Command/Observer mechanism (AddObserver()). + vtkLWCallback *myCallback = vtkLWCallback::New(); + myCallback->PolyData = seeds; + myCallback->Actor = streamline; + + // The plane widget is used probe the dataset. + // + vtkLineWidget *lineWidget = vtkLineWidget::New(); + lineWidget->SetInteractor(iren); + lineWidget->SetInput(pl3d->GetOutput()); + lineWidget->SetAlignToYAxis(); + lineWidget->PlaceWidget(); + lineWidget->GetPolyData(seeds); + lineWidget->AddObserver(vtkCommand::InteractionEvent,myCallback); + + ren1->AddActor(streamline); + ren1->AddActor(outlineActor); + + // Add the actors to the renderer, set the background and size + // + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(300, 300); + + // record events + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); +// recorder->SetFileName("c:/record.log"); +// recorder->Record(); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(TestLineWidgetEventLog); + + // render the image + // + iren->Initialize(); + renWin->Render(); + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + recorder->Off(); + recorder->Delete(); + myCallback->Delete(); + seeds->Delete(); + lineWidget->Delete(); + pl3d->Delete(); + rk4->Delete(); + streamer->Delete(); + rf->Delete(); + streamMapper->Delete(); + streamline->Delete(); + outline->Delete(); + outlineMapper->Delete(); + outlineActor->Delete(); + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestOrientationMarkerWidget.cxx b/Widgets/Testing/Cxx/TestOrientationMarkerWidget.cxx new file mode 100644 index 0000000..fcbdf0e --- /dev/null +++ b/Widgets/Testing/Cxx/TestOrientationMarkerWidget.cxx @@ -0,0 +1,594 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestOrientationMarkerWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkActor.h" +#include "vtkAnnotatedCubeActor.h" +#include "vtkAppendPolyData.h" +#include "vtkAxesActor.h" +#include "vtkCamera.h" +#include "vtkCaptionActor2D.h" +#include "vtkCellArray.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkMath.h" +#include "vtkOrientationMarkerWidget.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPropAssembly.h" +#include "vtkPropCollection.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkTextProperty.h" +#include "vtkTransform.h" +#include "vtkTransformPolyDataFilter.h" +#include "vtkTubeFilter.h" + +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char TestOMWidgetEventLog[] = +"# StreamVersion 1\n" +"CharEvent 215 191 0 0 98 1 b\n" +"KeyReleaseEvent 215 191 0 0 98 1 b\n" +"RightButtonPressEvent 215 191 0 0 0 0 b\n" +"TimerEvent 215 191 0 0 0 0 b\n" +"MouseMoveEvent 216 191 0 0 0 0 b\n" +"TimerEvent 216 191 0 0 0 0 b\n" +"MouseMoveEvent 216 192 0 0 0 0 b\n" +"TimerEvent 216 192 0 0 0 0 b\n" +"MouseMoveEvent 216 193 0 0 0 0 b\n" +"TimerEvent 216 193 0 0 0 0 b\n" +"MouseMoveEvent 216 194 0 0 0 0 b\n" +"TimerEvent 216 194 0 0 0 0 b\n" +"MouseMoveEvent 216 195 0 0 0 0 b\n" +"TimerEvent 216 195 0 0 0 0 b\n" +"MouseMoveEvent 216 196 0 0 0 0 b\n" +"TimerEvent 216 196 0 0 0 0 b\n" +"MouseMoveEvent 216 197 0 0 0 0 b\n" +"TimerEvent 216 197 0 0 0 0 b\n" +"MouseMoveEvent 216 198 0 0 0 0 b\n" +"TimerEvent 216 198 0 0 0 0 b\n" +"MouseMoveEvent 216 199 0 0 0 0 b\n" +"TimerEvent 216 199 0 0 0 0 b\n" +"RightButtonReleaseEvent 216 199 0 0 0 0 b\n" +"MouseMoveEvent 216 199 0 0 0 0 b\n" +"KeyPressEvent 216 199 0 0 116 1 t\n" +"CharEvent 216 199 0 0 116 1 t\n" +"KeyReleaseEvent 216 199 0 0 116 1 t\n" +"RightButtonPressEvent 216 199 0 0 0 0 t\n" +"MouseMoveEvent 216 200 0 0 0 0 t\n" +"MouseMoveEvent 219 240 0 0 0 0 t\n" +"RightButtonReleaseEvent 219 240 0 0 0 0 t\n" +"MouseMoveEvent 185 139 0 0 0 0 t\n" +"LeftButtonPressEvent 185 139 0 0 0 0 t\n" +"MouseMoveEvent 187 139 0 0 0 0 t\n" +"MouseMoveEvent 199 139 0 0 0 0 t\n" +"MouseMoveEvent 237 138 0 0 0 0 t\n" +"MouseMoveEvent 250 137 0 0 0 0 t\n" +"MouseMoveEvent 259 133 0 0 0 0 t\n" +"MouseMoveEvent 276 119 0 0 0 0 t\n" +"MouseMoveEvent 282 119 0 0 0 0 t\n" +"MouseMoveEvent 269 136 0 0 0 0 t\n" +"MouseMoveEvent 241 166 0 0 0 0 t\n" +"MouseMoveEvent 218 199 0 0 0 0 t\n" +"MouseMoveEvent 173 220 0 0 0 0 t\n" +"MouseMoveEvent 152 230 0 0 0 0 t\n" +"MouseMoveEvent 135 232 0 0 0 0 t\n" +"MouseMoveEvent 124 233 0 0 0 0 t\n" +"MouseMoveEvent 111 227 0 0 0 0 t\n" +"MouseMoveEvent 96 218 0 0 0 0 t\n" +"MouseMoveEvent 87 213 0 0 0 0 t\n" +"MouseMoveEvent 81 212 0 0 0 0 t\n" +"MouseMoveEvent 60 215 0 0 0 0 t\n" +"MouseMoveEvent 51 226 0 0 0 0 t\n" +"MouseMoveEvent 44 246 0 0 0 0 t\n" +"MouseMoveEvent 40 263 0 0 0 0 t\n" +"MouseMoveEvent 39 277 0 0 0 0 t\n" +"MouseMoveEvent 39 299 0 0 0 0 t\n" +"MouseMoveEvent 44 313 0 0 0 0 t\n" +"MouseMoveEvent 52 324 0 0 0 0 t\n" +"MouseMoveEvent 59 330 0 0 0 0 t\n" +"MouseMoveEvent 67 332 0 0 0 0 t\n" +"MouseMoveEvent 77 332 0 0 0 0 t\n" +"MouseMoveEvent 99 331 0 0 0 0 t\n" +"MouseMoveEvent 123 331 0 0 0 0 t\n" +"MouseMoveEvent 138 335 0 0 0 0 t\n" +"MouseMoveEvent 156 340 0 0 0 0 t\n" +"MouseMoveEvent 175 345 0 0 0 0 t\n" +"MouseMoveEvent 188 349 0 0 0 0 t\n" +"MouseMoveEvent 199 352 0 0 0 0 t\n" +"MouseMoveEvent 222 354 0 0 0 0 t\n" +"MouseMoveEvent 237 356 0 0 0 0 t\n" +"MouseMoveEvent 253 356 0 0 0 0 t\n" +"MouseMoveEvent 259 356 0 0 0 0 t\n" +"MouseMoveEvent 274 352 0 0 0 0 t\n" +"MouseMoveEvent 278 350 0 0 0 0 t\n" +"MouseMoveEvent 285 347 0 0 0 0 t\n" +"MouseMoveEvent 289 343 0 0 0 0 t\n" +"MouseMoveEvent 296 335 0 0 0 0 t\n" +"MouseMoveEvent 306 325 0 0 0 0 t\n" +"MouseMoveEvent 313 316 0 0 0 0 t\n" +"MouseMoveEvent 322 304 0 0 0 0 t\n" +"MouseMoveEvent 328 291 0 0 0 0 t\n" +"MouseMoveEvent 331 285 0 0 0 0 t\n" +"MouseMoveEvent 333 277 0 0 0 0 t\n" +"MouseMoveEvent 335 267 0 0 0 0 t\n" +"MouseMoveEvent 337 262 0 0 0 0 t\n" +"LeftButtonReleaseEvent 337 262 0 0 0 0 t\n" +"MouseMoveEvent 133 119 0 0 0 0 t\n" +"LeftButtonPressEvent 133 119 0 0 0 0 t\n" +"MouseMoveEvent 134 119 0 0 0 0 t\n" +"MouseMoveEvent 139 125 0 0 0 0 t\n" +"MouseMoveEvent 145 131 0 0 0 0 t\n" +"MouseMoveEvent 156 141 0 0 0 0 t\n" +"MouseMoveEvent 168 146 0 0 0 0 t\n" +"MouseMoveEvent 211 158 0 0 0 0 t\n" +"MouseMoveEvent 253 163 0 0 0 0 t\n" +"MouseMoveEvent 300 167 0 0 0 0 t\n" +"MouseMoveEvent 345 172 0 0 0 0 t\n" +"MouseMoveEvent 370 179 0 0 0 0 t\n" +"MouseMoveEvent 384 180 0 0 0 0 t\n" +"MouseMoveEvent 396 182 0 0 0 0 t\n" +"LeaveEvent 402 183 0 0 0 0 t\n" +"MouseMoveEvent 402 183 0 0 0 0 t\n" +"MouseMoveEvent 408 182 0 0 0 0 t\n" +"EnterEvent 388 182 0 0 0 0 t\n" +"MouseMoveEvent 388 182 0 0 0 0 t\n" +"MouseMoveEvent 358 193 0 0 0 0 t\n" +"MouseMoveEvent 327 227 0 0 0 0 t\n" +"MouseMoveEvent 307 265 0 0 0 0 t\n" +"MouseMoveEvent 290 325 0 0 0 0 t\n" +"MouseMoveEvent 281 367 0 0 0 0 t\n" +"MouseMoveEvent 280 396 0 0 0 0 t\n" +"LeaveEvent 280 400 0 0 0 0 t\n" +"MouseMoveEvent 280 400 0 0 0 0 t\n" +"MouseMoveEvent 240 401 0 0 0 0 t\n" +"EnterEvent 230 396 0 0 0 0 t\n" +"MouseMoveEvent 230 396 0 0 0 0 t\n" +"MouseMoveEvent 178 371 0 0 0 0 t\n" +"MouseMoveEvent 120 351 0 0 0 0 t\n" +"MouseMoveEvent 94 341 0 0 0 0 t\n" +"MouseMoveEvent 68 337 0 0 0 0 t\n" +"MouseMoveEvent 58 332 0 0 0 0 t\n" +"MouseMoveEvent 47 319 0 0 0 0 t\n" +"MouseMoveEvent 42 296 0 0 0 0 t\n" +"MouseMoveEvent 44 255 0 0 0 0 t\n" +"MouseMoveEvent 64 223 0 0 0 0 t\n" +"MouseMoveEvent 86 195 0 0 0 0 t\n" +"MouseMoveEvent 102 172 0 0 0 0 t\n" +"MouseMoveEvent 111 159 0 0 0 0 t\n" +"MouseMoveEvent 115 153 0 0 0 0 t\n" +"MouseMoveEvent 116 138 0 0 0 0 t\n" +"MouseMoveEvent 110 124 0 0 0 0 t\n" +"MouseMoveEvent 99 111 0 0 0 0 t\n" +"MouseMoveEvent 93 104 0 0 0 0 t\n" +"MouseMoveEvent 92 102 0 0 0 0 t\n" +"LeftButtonReleaseEvent 92 102 0 0 0 0 t\n" +"MouseMoveEvent 92 102 0 0 0 0 t\n" +"MouseMoveEvent 168 179 0 0 0 0 t\n" +"LeftButtonPressEvent 168 179 0 0 0 0 t\n" +"MouseMoveEvent 167 178 0 0 0 0 t\n" +"MouseMoveEvent 162 172 0 0 0 0 t\n" +"MouseMoveEvent 153 164 0 0 0 0 t\n" +"MouseMoveEvent 148 158 0 0 0 0 t\n" +"MouseMoveEvent 140 150 0 0 0 0 t\n" +"MouseMoveEvent 135 145 0 0 0 0 t\n" +"MouseMoveEvent 131 141 0 0 0 0 t\n" +"MouseMoveEvent 125 135 0 0 0 0 t\n" +"MouseMoveEvent 123 132 0 0 0 0 t\n" +"MouseMoveEvent 121 131 0 0 0 0 t\n" +"MouseMoveEvent 120 129 0 0 0 0 t\n" +"LeftButtonReleaseEvent 120 129 0 0 0 0 t\n" +"MouseMoveEvent 120 129 0 0 0 0 t\n" +"MouseMoveEvent 116 22 0 0 0 0 t\n" +"LeftButtonPressEvent 116 22 0 0 0 0 t\n" +"MouseMoveEvent 117 22 0 0 0 0 t\n" +"MouseMoveEvent 119 20 0 0 0 0 t\n" +"MouseMoveEvent 130 10 0 0 0 0 t\n" +"MouseMoveEvent 143 2 0 0 0 0 t\n" +"MouseMoveEvent 145 0 0 0 0 0 t\n" +"LeaveEvent 146 -1 0 0 0 0 t\n" +"MouseMoveEvent 146 -1 0 0 0 0 t\n" +"MouseMoveEvent 159 -9 0 0 0 0 t\n" +"MouseMoveEvent 162 -11 0 0 0 0 t\n" +"MouseMoveEvent 166 -14 0 0 0 0 t\n" +"MouseMoveEvent 169 -17 0 0 0 0 t\n" +"MouseMoveEvent 173 -22 0 0 0 0 t\n" +"MouseMoveEvent 176 -25 0 0 0 0 t\n" +"MouseMoveEvent 177 -25 0 0 0 0 t\n" +"LeftButtonReleaseEvent 177 -25 0 0 0 0 t\n" +"EnterEvent 156 2 0 0 0 0 t\n" +"MouseMoveEvent 156 2 0 0 0 0 t\n" +"MouseMoveEvent 140 25 0 0 0 0 t\n" +"MouseMoveEvent 113 53 0 0 0 0 t\n" +"MouseMoveEvent 92 74 0 0 0 0 t\n" +"MouseMoveEvent 76 89 0 0 0 0 t\n" +"MouseMoveEvent 67 96 0 0 0 0 t\n" +"MouseMoveEvent 61 105 0 0 0 0 t\n" +"MouseMoveEvent 57 111 0 0 0 0 t\n" +"MouseMoveEvent 55 115 0 0 0 0 t\n" +"MouseMoveEvent 53 121 0 0 0 0 t\n" +"MouseMoveEvent 51 126 0 0 0 0 t\n" +"MouseMoveEvent 50 128 0 0 0 0 t\n" +"LeftButtonPressEvent 50 128 0 0 0 0 t\n" +"MouseMoveEvent 50 129 0 0 0 0 t\n" +"MouseMoveEvent 49 133 0 0 0 0 t\n" +"MouseMoveEvent 46 137 0 0 0 0 t\n" +"MouseMoveEvent 42 144 0 0 0 0 t\n" +"MouseMoveEvent 40 149 0 0 0 0 t\n" +"MouseMoveEvent 38 154 0 0 0 0 t\n" +"MouseMoveEvent 35 158 0 0 0 0 t\n" +"MouseMoveEvent 33 161 0 0 0 0 t\n" +"MouseMoveEvent 29 166 0 0 0 0 t\n" +"MouseMoveEvent 27 168 0 0 0 0 t\n" +"MouseMoveEvent 24 168 0 0 0 0 t\n" +"MouseMoveEvent 22 169 0 0 0 0 t\n" +"MouseMoveEvent 20 170 0 0 0 0 t\n" +"MouseMoveEvent 18 170 0 0 0 0 t\n" +"LeftButtonReleaseEvent 18 170 0 0 0 0 t\n" +"MouseMoveEvent 18 170 0 0 0 0 t\n" +"MouseMoveEvent 20 15 0 0 0 0 t\n" +"LeftButtonPressEvent 20 15 0 0 0 0 t\n" +"MouseMoveEvent 19 15 0 0 0 0 t\n" +"MouseMoveEvent 18 13 0 0 0 0 t\n" +"MouseMoveEvent 16 11 0 0 0 0 t\n" +"MouseMoveEvent 15 9 0 0 0 0 t\n" +"MouseMoveEvent 13 7 0 0 0 0 t\n" +"MouseMoveEvent 10 5 0 0 0 0 t\n" +"MouseMoveEvent 9 4 0 0 0 0 t\n" +"LeftButtonReleaseEvent 9 4 0 0 0 0 t\n" +"MouseMoveEvent 9 4 0 0 0 0 t\n" +"MouseMoveEvent 119 82 0 0 0 0 t\n" +"LeftButtonPressEvent 119 82 0 0 0 0 t\n" +"MouseMoveEvent 120 82 0 0 0 0 t\n" +"MouseMoveEvent 126 79 0 0 0 0 t\n" +"MouseMoveEvent 130 75 0 0 0 0 t\n" +"MouseMoveEvent 131 73 0 0 0 0 t\n" +"MouseMoveEvent 133 72 0 0 0 0 t\n" +"MouseMoveEvent 134 72 0 0 0 0 t\n" +"LeftButtonReleaseEvent 134 72 0 0 0 0 t\n" +"MouseMoveEvent 134 72 0 0 0 0 t\n" +"MouseMoveEvent 132 184 0 0 0 0 t\n" +"LeftButtonPressEvent 132 184 0 0 0 0 t\n" +"MouseMoveEvent 130 184 0 0 0 0 t\n" +"MouseMoveEvent 99 179 0 0 0 0 t\n" +"MouseMoveEvent 94 176 0 0 0 0 t\n" +"MouseMoveEvent 83 174 0 0 0 0 t\n" +"MouseMoveEvent 77 186 0 0 0 0 t\n" +"MouseMoveEvent 67 212 0 0 0 0 t\n" +"MouseMoveEvent 65 233 0 0 0 0 t\n" +"MouseMoveEvent 66 244 0 0 0 0 t\n" +"MouseMoveEvent 72 253 0 0 0 0 t\n" +"MouseMoveEvent 86 259 0 0 0 0 t\n" +"MouseMoveEvent 106 266 0 0 0 0 t\n" +"MouseMoveEvent 132 271 0 0 0 0 t\n" +"MouseMoveEvent 145 272 0 0 0 0 t\n" +"MouseMoveEvent 154 264 0 0 0 0 t\n" +"MouseMoveEvent 163 240 0 0 0 0 t\n" +"MouseMoveEvent 169 212 0 0 0 0 t\n" +"MouseMoveEvent 171 199 0 0 0 0 t\n" +"MouseMoveEvent 170 189 0 0 0 0 t\n" +"MouseMoveEvent 146 185 0 0 0 0 t\n" +"MouseMoveEvent 136 188 0 0 0 0 t\n" +"MouseMoveEvent 127 189 0 0 0 0 t\n" +"MouseMoveEvent 123 188 0 0 0 0 t\n" +"LeftButtonReleaseEvent 123 188 0 0 0 0 t\n" +"MouseMoveEvent 123 188 0 0 0 0 t\n" +; + +int TestOrientationMarkerWidget( int argc, char *argv[] ) +{ + // create an actor out of parts of vtkAxesActor and vtkAnnotatedCubeActor + // to have the widget follow. + // part 1 is a helical spring to test vtkAxesActor SetUserDefinedShaft + // + double dt = vtkMath::DoublePi() / 20.0; + double t = 0.0; + double x = 0.0; + int nPoints = 120; + double dx = 0.8 / nPoints; + + vtkPoints* points = vtkPoints::New(VTK_DOUBLE); + vtkCellArray* line = vtkCellArray::New(); + line->InsertNextCell( nPoints + 80 ); + + int i = 0; + do + { + points->InsertPoint( i, 0.1*cos(t), x, 0.1*sin(t) ); + line->InsertCellPoint( i ); + t += dt; + }while( ++i < 40 ); + + do + { + points->InsertPoint( i, 0.1*cos(t), x, 0.1*sin(t) ); + line->InsertCellPoint(i); + t += dt; + x += dx; + }while( ++i < nPoints + 40 ); + + do + { + points->InsertPoint( i, 0.1*cos(t), x, 0.1*sin(t) ); + line->InsertCellPoint( i ); + t += dt; + }while( ++i < nPoints + 80 ); + + vtkPolyData* wiggle = vtkPolyData::New(); + wiggle->SetPoints( points ); + wiggle->SetLines( line ); + + vtkTubeFilter* tube = vtkTubeFilter::New(); + tube->SetInput( wiggle ); + tube->SetGenerateTCoordsToOff(); + tube->CappingOff(); + tube->SetVaryRadiusToVaryRadiusOff(); + tube->SetRadius( 0.02 ); + tube->SetNumberOfSides( 5 ); + + // part 2 is generated from vtkAnnotatedCubeActor to test + // vtkAxesActor SetUserDefinedTip + // + vtkAnnotatedCubeActor* cube = vtkAnnotatedCubeActor::New(); + cube->SetXPlusFaceText ( "V" ); + cube->SetXMinusFaceText( "K" ); + cube->SetYPlusFaceText ( "T" ); + cube->SetZPlusFaceText ( "" ); + cube->SetZMinusFaceText( "" ); + cube->SetYMinusFaceText( "" ); + cube->SetFaceTextScale( 0.666667 ); + + vtkPropCollection* props = vtkPropCollection::New(); + cube->GetActors( props ); + + vtkAppendPolyData* append = vtkAppendPolyData::New(); + + vtkTransformPolyDataFilter* transformFilter = vtkTransformPolyDataFilter::New(); + vtkTransform* transform = vtkTransform::New(); + transformFilter->SetTransform( transform ); + + vtkCollectionSimpleIterator sit; + props->InitTraversal( sit ); + int nprops = props->GetNumberOfItems(); + + for ( i = 0; i < nprops; i++ ) + { + vtkActor *node = vtkActor::SafeDownCast( props->GetNextProp( sit ) ); + + // the first prop in the collection will be the cube outline, the last + // will be the text outlines + // + if ( node && i == 0 || i == (nprops - 1) ) + { + vtkPolyData* poly = vtkPolyData::SafeDownCast(node->GetMapper()->GetInput()); + if ( poly ) + { + transformFilter->SetInput( poly ); + transform->Identity(); + transform->SetMatrix( node->GetMatrix() ); + transform->Scale( 2.0, 2.0, 2.0 ); + transformFilter->Update(); + + vtkPolyData* newpoly = vtkPolyData::New(); + newpoly->DeepCopy( transformFilter->GetOutput() ); + append->AddInput( newpoly ); + newpoly->Delete(); + } + } + } + + // the final actor the widget will follow + // + vtkAxesActor* axes = vtkAxesActor::New(); + + axes->SetTotalLength( 1.2, 1.2 , 1.2 ); + axes->SetUserDefinedTip( append->GetOutput() ); + axes->SetTipTypeToUserDefined(); + axes->SetNormalizedShaftLength( 0.85, 0.85, 0.85 ); + axes->SetNormalizedTipLength( 0.15, 0.15, 0.15 ); + axes->AxisLabelsOff(); + axes->SetUserDefinedShaft( tube->GetOutput() ); + axes->SetShaftTypeToUserDefined(); + + vtkProperty* property = axes->GetXAxisTipProperty(); + property->SetRepresentationToWireframe(); + property->SetDiffuse(0); + property->SetAmbient(1); + property->SetColor( 1, 0, 1 ); + + property = axes->GetYAxisTipProperty(); + property->SetRepresentationToWireframe(); + property->SetDiffuse(0); + property->SetAmbient(1); + property->SetColor( 1, 1, 0 ); + + property = axes->GetZAxisTipProperty(); + property->SetRepresentationToWireframe(); + property->SetDiffuse(0); + property->SetAmbient(1); + property->SetColor( 0, 1, 1 ); + + // set up the renderer, window, and interactor + // + vtkRenderer* renderer = vtkRenderer::New(); + renderer->SetBackground( 0.0980, 0.0980, 0.4392 ); + + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer( renderer ); + renWin->SetSize( 400, 400 ); + + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow( renWin ); + + renderer->AddViewProp( axes ); + + // set up an interesting view + // + vtkCamera* camera = renderer->GetActiveCamera(); + camera->SetViewUp( 0, 0, 1 ); + camera->SetFocalPoint( 0, 0, 0 ); + camera->SetPosition( 4.5, 4.5, 2.5 ); + renderer->ResetCameraClippingRange(); + + // the orientation marker passed to the widget will be composed of two + // actors: vtkAxesActor and a vtkAnnotatedCubeActor + // + cube->SetFaceTextScale( 0.65 ); + property = cube->GetCubeProperty(); + property->SetColor( 0.5, 1, 1 ); + + property = cube->GetTextEdgesProperty(); + property->SetLineWidth( 1 ); + property->SetDiffuse( 0 ); + property->SetAmbient( 1 ); + property->SetColor( 0.1800, 0.2800, 0.2300 ); + + // this static function improves the appearance of the text edges + // since they are overlaid on a surface rendering of the cube's faces + // + vtkMapper::SetResolveCoincidentTopologyToPolygonOffset(); + + // just for coverage + // + cube->TextEdgesOff(); + cube->TextEdgesOn(); + cube->CubeOff(); + cube->CubeOn(); + cube->FaceTextOff(); + cube->FaceTextOn(); + + // anatomic labelling + // + cube->SetXPlusFaceText ( "A" ); + cube->SetXMinusFaceText( "P" ); + cube->SetYPlusFaceText ( "L" ); + cube->SetYMinusFaceText( "R" ); + cube->SetZPlusFaceText ( "S" ); + cube->SetZMinusFaceText( "I" ); + + // change the vector text colors + // + property = cube->GetXPlusFaceProperty(); + property->SetColor(0, 0, 1); + property->SetInterpolationToFlat(); + property = cube->GetXMinusFaceProperty(); + property->SetColor(0, 0, 1); + property->SetInterpolationToFlat(); + property = cube->GetYPlusFaceProperty(); + property->SetColor(0, 1, 0); + property->SetInterpolationToFlat(); + property = cube->GetYMinusFaceProperty(); + property->SetColor(0, 1, 0); + property->SetInterpolationToFlat(); + property = cube->GetZPlusFaceProperty(); + property->SetColor(1, 0, 0); + property->SetInterpolationToFlat(); + property = cube->GetZMinusFaceProperty(); + property->SetColor(1, 0, 0); + property->SetInterpolationToFlat(); + + vtkAxesActor* axes2 = vtkAxesActor::New(); + + // simulate a left-handed coordinate system + // + transform->Identity(); + transform->RotateY(90); + axes2->SetShaftTypeToCylinder(); + axes2->SetUserTransform( transform ); + axes2->SetXAxisLabelText( "w" ); + axes2->SetYAxisLabelText( "v" ); + axes2->SetZAxisLabelText( "u" ); + + axes2->SetTotalLength( 1.5, 1.5, 1.5 ); + axes2->SetCylinderRadius( 0.500 * axes2->GetCylinderRadius() ); + axes2->SetConeRadius ( 1.025 * axes2->GetConeRadius() ); + axes2->SetSphereRadius ( 1.500 * axes2->GetSphereRadius() ); + + vtkTextProperty* tprop = axes2->GetXAxisCaptionActor2D()-> + GetCaptionTextProperty(); + tprop->ItalicOn(); + tprop->ShadowOn(); + tprop->SetFontFamilyToTimes(); + + axes2->GetYAxisCaptionActor2D()->GetCaptionTextProperty()->ShallowCopy( tprop ); + axes2->GetZAxisCaptionActor2D()->GetCaptionTextProperty()->ShallowCopy( tprop ); + + // combine orientation markers into one with an assembly + // + vtkPropAssembly* assembly = vtkPropAssembly::New(); + assembly->AddPart( axes2 ); + assembly->AddPart( cube ); + + // set up the widget + // + vtkOrientationMarkerWidget* widget = vtkOrientationMarkerWidget::New(); + widget->SetOutlineColor( 0.9300, 0.5700, 0.1300 ); + widget->SetOrientationMarker( assembly ); + widget->SetInteractor( iren ); + widget->SetViewport( 0.0, 0.0, 0.4, 0.4 ); + widget->SetEnabled( 1 ); + widget->InteractiveOff(); + widget->InteractiveOn(); + + // recorder to play back previously events + // + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); +// recorder->SetFileName("record.log"); +// recorder->SetKeyPressActivationValue('b'); + + recorder->ReadFromInputStringOn(); + recorder->SetInputString(TestOMWidgetEventLog); + + iren->Initialize(); + renWin->Render(); + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // clean up + // + recorder->Off(); + recorder->Delete(); + renderer->Delete(); + renWin->Delete(); + iren->Delete(); + props->Delete(); + transformFilter->Delete(); + transform->Delete(); + points->Delete(); + line->Delete(); + wiggle->Delete(); + tube->Delete(); + append->Delete(); + axes->Delete(); + cube->Delete(); + axes2->Delete(); + assembly->Delete(); + widget->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestPlaneWidget.cxx b/Widgets/Testing/Cxx/TestPlaneWidget.cxx new file mode 100644 index 0000000..91ea427 --- /dev/null +++ b/Widgets/Testing/Cxx/TestPlaneWidget.cxx @@ -0,0 +1,530 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestPlaneWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCommand.h" +#include "vtkConeSource.h" +#include "vtkGlyph3D.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkPLOT3DReader.h" +#include "vtkPlaneWidget.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProbeFilter.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridOutlineFilter.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char TPWeventLog[] = +"# StreamVersion 1\n" +"CharEvent 192 232 0 0 105 1 i\n" +"KeyReleaseEvent 192 230 0 0 105 1 i\n" +"MouseMoveEvent 192 229 0 0 0 0 i\n" +"MouseMoveEvent 192 228 0 0 0 0 i\n" +"MouseMoveEvent 193 228 0 0 0 0 i\n" +"MouseMoveEvent 194 227 0 0 0 0 i\n" +"MouseMoveEvent 195 225 0 0 0 0 i\n" +"MouseMoveEvent 196 220 0 0 0 0 i\n" +"MouseMoveEvent 196 215 0 0 0 0 i\n" +"MouseMoveEvent 196 206 0 0 0 0 i\n" +"MouseMoveEvent 198 197 0 0 0 0 i\n" +"MouseMoveEvent 198 190 0 0 0 0 i\n" +"MouseMoveEvent 198 185 0 0 0 0 i\n" +"MouseMoveEvent 199 178 0 0 0 0 i\n" +"MouseMoveEvent 199 173 0 0 0 0 i\n" +"MouseMoveEvent 198 168 0 0 0 0 i\n" +"MouseMoveEvent 196 163 0 0 0 0 i\n" +"MouseMoveEvent 196 159 0 0 0 0 i\n" +"MouseMoveEvent 196 156 0 0 0 0 i\n" +"MouseMoveEvent 195 151 0 0 0 0 i\n" +"MouseMoveEvent 192 145 0 0 0 0 i\n" +"MouseMoveEvent 187 142 0 0 0 0 i\n" +"MouseMoveEvent 185 141 0 0 0 0 i\n" +"MouseMoveEvent 181 139 0 0 0 0 i\n" +"MouseMoveEvent 179 139 0 0 0 0 i\n" +"MouseMoveEvent 177 138 0 0 0 0 i\n" +"MouseMoveEvent 173 138 0 0 0 0 i\n" +"MouseMoveEvent 171 138 0 0 0 0 i\n" +"MouseMoveEvent 170 137 0 0 0 0 i\n" +"MouseMoveEvent 170 138 0 0 0 0 i\n" +"MouseMoveEvent 170 139 0 0 0 0 i\n" +"MouseMoveEvent 170 142 0 0 0 0 i\n" +"MouseMoveEvent 170 144 0 0 0 0 i\n" +"MouseMoveEvent 163 147 0 0 0 0 i\n" +"MouseMoveEvent 159 149 0 0 0 0 i\n" +"MouseMoveEvent 155 149 0 0 0 0 i\n" +"MouseMoveEvent 151 153 0 0 0 0 i\n" +"MouseMoveEvent 150 154 0 0 0 0 i\n" +"MouseMoveEvent 147 155 0 0 0 0 i\n" +"MouseMoveEvent 146 158 0 0 0 0 i\n" +"MouseMoveEvent 146 160 0 0 0 0 i\n" +"MouseMoveEvent 146 161 0 0 0 0 i\n" +"MouseMoveEvent 146 163 0 0 0 0 i\n" +"MouseMoveEvent 146 164 0 0 0 0 i\n" +"MouseMoveEvent 146 167 0 0 0 0 i\n" +"MouseMoveEvent 146 171 0 0 0 0 i\n" +"MouseMoveEvent 146 172 0 0 0 0 i\n" +"MouseMoveEvent 146 173 0 0 0 0 i\n" +"MouseMoveEvent 147 173 0 0 0 0 i\n" +"MouseMoveEvent 147 172 0 0 0 0 i\n" +"MouseMoveEvent 148 169 0 0 0 0 i\n" +"MouseMoveEvent 149 167 0 0 0 0 i\n" +"MouseMoveEvent 151 163 0 0 0 0 i\n" +"MouseMoveEvent 153 158 0 0 0 0 i\n" +"MouseMoveEvent 156 154 0 0 0 0 i\n" +"MouseMoveEvent 161 150 0 0 0 0 i\n" +"MouseMoveEvent 162 148 0 0 0 0 i\n" +"MouseMoveEvent 163 147 0 0 0 0 i\n" +"MouseMoveEvent 164 146 0 0 0 0 i\n" +"MouseMoveEvent 165 145 0 0 0 0 i\n" +"MouseMoveEvent 166 145 0 0 0 0 i\n" +"MouseMoveEvent 167 146 0 0 0 0 i\n" +"MouseMoveEvent 168 146 0 0 0 0 i\n" +"MouseMoveEvent 169 146 0 0 0 0 i\n" +"MouseMoveEvent 169 147 0 0 0 0 i\n" +"MouseMoveEvent 170 147 0 0 0 0 i\n" +"MouseMoveEvent 170 148 0 0 0 0 i\n" +"MouseMoveEvent 170 149 0 0 0 0 i\n" +"MouseMoveEvent 171 149 0 0 0 0 i\n" +"MouseMoveEvent 171 150 0 0 0 0 i\n" +"MouseMoveEvent 172 150 0 0 0 0 i\n" +"MouseMoveEvent 172 151 0 0 0 0 i\n" +"MouseMoveEvent 173 151 0 0 0 0 i\n" +"MouseMoveEvent 174 151 0 0 0 0 i\n" +"MouseMoveEvent 175 151 0 0 0 0 i\n" +"MouseMoveEvent 177 151 0 0 0 0 i\n" +"MouseMoveEvent 178 151 0 0 0 0 i\n" +"MouseMoveEvent 179 151 0 0 0 0 i\n" +"LeftButtonPressEvent 179 151 0 0 0 0 i\n" +"MouseMoveEvent 179 152 0 0 0 0 i\n" +"MouseMoveEvent 178 153 0 0 0 0 i\n" +"MouseMoveEvent 177 154 0 0 0 0 i\n" +"MouseMoveEvent 176 155 0 0 0 0 i\n" +"MouseMoveEvent 175 156 0 0 0 0 i\n" +"MouseMoveEvent 172 156 0 0 0 0 i\n" +"MouseMoveEvent 167 157 0 0 0 0 i\n" +"MouseMoveEvent 163 157 0 0 0 0 i\n" +"MouseMoveEvent 160 158 0 0 0 0 i\n" +"MouseMoveEvent 159 158 0 0 0 0 i\n" +"MouseMoveEvent 158 159 0 0 0 0 i\n" +"MouseMoveEvent 155 162 0 0 0 0 i\n" +"MouseMoveEvent 153 165 0 0 0 0 i\n" +"MouseMoveEvent 153 167 0 0 0 0 i\n" +"MouseMoveEvent 151 168 0 0 0 0 i\n" +"MouseMoveEvent 148 170 0 0 0 0 i\n" +"MouseMoveEvent 146 170 0 0 0 0 i\n" +"MouseMoveEvent 142 172 0 0 0 0 i\n" +"MouseMoveEvent 140 172 0 0 0 0 i\n" +"MouseMoveEvent 139 173 0 0 0 0 i\n" +"MouseMoveEvent 138 174 0 0 0 0 i\n" +"MouseMoveEvent 137 176 0 0 0 0 i\n" +"MouseMoveEvent 133 177 0 0 0 0 i\n" +"MouseMoveEvent 129 178 0 0 0 0 i\n" +"MouseMoveEvent 128 179 0 0 0 0 i\n" +"MouseMoveEvent 127 179 0 0 0 0 i\n" +"MouseMoveEvent 122 179 0 0 0 0 i\n" +"MouseMoveEvent 115 179 0 0 0 0 i\n" +"MouseMoveEvent 114 179 0 0 0 0 i\n" +"MouseMoveEvent 113 179 0 0 0 0 i\n" +"LeftButtonReleaseEvent 113 179 0 0 0 0 i\n" +"MouseMoveEvent 113 179 0 0 0 0 i\n" +"MouseMoveEvent 113 178 0 0 0 0 i\n" +"MouseMoveEvent 114 178 0 0 0 0 i\n" +"MouseMoveEvent 115 178 0 0 0 0 i\n" +"MouseMoveEvent 116 177 0 0 0 0 i\n" +"MouseMoveEvent 117 177 0 0 0 0 i\n" +"MouseMoveEvent 118 177 0 0 0 0 i\n" +"MouseMoveEvent 120 176 0 0 0 0 i\n" +"MouseMoveEvent 121 176 0 0 0 0 i\n" +"MouseMoveEvent 124 174 0 0 0 0 i\n" +"MouseMoveEvent 128 174 0 0 0 0 i\n" +"MouseMoveEvent 133 174 0 0 0 0 i\n" +"MouseMoveEvent 138 173 0 0 0 0 i\n" +"MouseMoveEvent 141 173 0 0 0 0 i\n" +"MouseMoveEvent 144 171 0 0 0 0 i\n" +"MouseMoveEvent 147 169 0 0 0 0 i\n" +"MouseMoveEvent 153 168 0 0 0 0 i\n" +"MouseMoveEvent 156 168 0 0 0 0 i\n" +"MouseMoveEvent 159 168 0 0 0 0 i\n" +"MouseMoveEvent 160 168 0 0 0 0 i\n" +"MouseMoveEvent 160 169 0 0 0 0 i\n" +"MouseMoveEvent 159 169 0 0 0 0 i\n" +"MouseMoveEvent 157 171 0 0 0 0 i\n" +"MouseMoveEvent 153 173 0 0 0 0 i\n" +"MouseMoveEvent 152 174 0 0 0 0 i\n" +"MouseMoveEvent 151 174 0 0 0 0 i\n" +"MouseMoveEvent 150 175 0 0 0 0 i\n" +"MouseMoveEvent 149 175 0 0 0 0 i\n" +"MouseMoveEvent 149 176 0 0 0 0 i\n" +"MouseMoveEvent 148 176 0 0 0 0 i\n" +"MouseMoveEvent 148 177 0 0 0 0 i\n" +"MouseMoveEvent 147 177 0 0 0 0 i\n" +"MouseMoveEvent 147 178 0 0 0 0 i\n" +"MouseMoveEvent 146 179 0 0 0 0 i\n" +"MouseMoveEvent 144 180 0 0 0 0 i\n" +"MouseMoveEvent 141 180 0 0 0 0 i\n" +"MouseMoveEvent 139 182 0 0 0 0 i\n" +"MouseMoveEvent 138 183 0 0 0 0 i\n" +"MouseMoveEvent 137 183 0 0 0 0 i\n" +"MouseMoveEvent 137 184 0 0 0 0 i\n" +"MouseMoveEvent 136 184 0 0 0 0 i\n" +"MouseMoveEvent 136 185 0 0 0 0 i\n" +"MouseMoveEvent 136 186 0 0 0 0 i\n" +"MouseMoveEvent 135 186 0 0 0 0 i\n" +"MouseMoveEvent 135 187 0 0 0 0 i\n" +"MouseMoveEvent 135 188 0 0 0 0 i\n" +"MouseMoveEvent 134 189 0 0 0 0 i\n" +"MouseMoveEvent 133 189 0 0 0 0 i\n" +"MouseMoveEvent 132 189 0 0 0 0 i\n" +"LeftButtonPressEvent 132 189 0 0 0 0 i\n" +"MouseMoveEvent 132 188 0 0 0 0 i\n" +"MouseMoveEvent 132 186 0 0 0 0 i\n" +"MouseMoveEvent 132 184 0 0 0 0 i\n" +"MouseMoveEvent 132 182 0 0 0 0 i\n" +"MouseMoveEvent 132 181 0 0 0 0 i\n" +"MouseMoveEvent 132 179 0 0 0 0 i\n" +"MouseMoveEvent 132 176 0 0 0 0 i\n" +"MouseMoveEvent 133 175 0 0 0 0 i\n" +"MouseMoveEvent 134 174 0 0 0 0 i\n" +"MouseMoveEvent 134 172 0 0 0 0 i\n" +"MouseMoveEvent 134 171 0 0 0 0 i\n" +"MouseMoveEvent 135 168 0 0 0 0 i\n" +"MouseMoveEvent 135 167 0 0 0 0 i\n" +"LeftButtonReleaseEvent 135 167 0 0 0 0 i\n" +"MouseMoveEvent 135 167 0 0 0 0 i\n" +"MouseMoveEvent 136 166 0 0 0 0 i\n" +"MouseMoveEvent 136 165 0 0 0 0 i\n" +"MouseMoveEvent 136 164 0 0 0 0 i\n" +"MouseMoveEvent 136 163 0 0 0 0 i\n" +"MouseMoveEvent 136 162 0 0 0 0 i\n" +"MouseMoveEvent 135 162 0 0 0 0 i\n" +"MouseMoveEvent 134 162 0 0 0 0 i\n" +"MouseMoveEvent 133 161 0 0 0 0 i\n" +"RightButtonPressEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"TimerEvent 133 161 0 0 0 0 i\n" +"MouseMoveEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"TimerEvent 133 160 0 0 0 0 i\n" +"MouseMoveEvent 132 160 0 0 0 0 i\n" +"TimerEvent 132 160 0 0 0 0 i\n" +"MouseMoveEvent 132 159 0 0 0 0 i\n" +"TimerEvent 132 159 0 0 0 0 i\n" +"MouseMoveEvent 131 159 0 0 0 0 i\n" +"RightButtonReleaseEvent 131 159 0 0 0 0 i\n" +"MouseMoveEvent 131 159 0 0 0 0 i\n" +"MouseMoveEvent 131 158 0 0 0 0 i\n" +"MouseMoveEvent 131 155 0 0 0 0 i\n" +"MouseMoveEvent 132 154 0 0 0 0 i\n" +"MouseMoveEvent 132 152 0 0 0 0 i\n" +"MouseMoveEvent 132 151 0 0 0 0 i\n" +"MouseMoveEvent 133 150 0 0 0 0 i\n" +"MouseMoveEvent 134 150 0 0 0 0 i\n" +"RightButtonPressEvent 134 150 0 0 0 0 i\n" +"MouseMoveEvent 134 149 0 0 0 0 i\n" +"MouseMoveEvent 134 148 0 0 0 0 i\n" +"MouseMoveEvent 134 149 0 0 0 0 i\n" +"MouseMoveEvent 133 150 0 0 0 0 i\n" +"MouseMoveEvent 131 151 0 0 0 0 i\n" +"MouseMoveEvent 131 152 0 0 0 0 i\n" +"MouseMoveEvent 131 153 0 0 0 0 i\n" +"MouseMoveEvent 131 154 0 0 0 0 i\n" +"MouseMoveEvent 130 157 0 0 0 0 i\n" +"MouseMoveEvent 129 160 0 0 0 0 i\n" +"MouseMoveEvent 129 161 0 0 0 0 i\n" +"MouseMoveEvent 128 164 0 0 0 0 i\n" +"MouseMoveEvent 125 167 0 0 0 0 i\n" +"MouseMoveEvent 122 171 0 0 0 0 i\n" +"MouseMoveEvent 122 173 0 0 0 0 i\n" +"MouseMoveEvent 121 173 0 0 0 0 i\n" +"MouseMoveEvent 121 175 0 0 0 0 i\n" +"MouseMoveEvent 121 178 0 0 0 0 i\n" +"MouseMoveEvent 121 179 0 0 0 0 i\n" +"MouseMoveEvent 120 179 0 0 0 0 i\n" +"MouseMoveEvent 120 181 0 0 0 0 i\n" +"MouseMoveEvent 119 183 0 0 0 0 i\n" +"MouseMoveEvent 118 185 0 0 0 0 i\n" +"MouseMoveEvent 118 186 0 0 0 0 i\n" +"MouseMoveEvent 117 187 0 0 0 0 i\n" +"MouseMoveEvent 116 189 0 0 0 0 i\n" +"MouseMoveEvent 113 190 0 0 0 0 i\n" +"MouseMoveEvent 113 191 0 0 0 0 i\n" +"MouseMoveEvent 113 190 0 0 0 0 i\n" +"MouseMoveEvent 113 189 0 0 0 0 i\n" +"RightButtonReleaseEvent 113 189 0 0 0 0 i\n" +"MouseMoveEvent 112 189 0 0 0 0 i\n" +"MouseMoveEvent 112 188 0 0 0 0 i\n" +"MouseMoveEvent 112 187 0 0 0 0 i\n" +"MouseMoveEvent 113 186 0 0 0 0 i\n" +"MouseMoveEvent 114 185 0 0 0 0 i\n" +"MouseMoveEvent 115 184 0 0 0 0 i\n" +"MouseMoveEvent 116 183 0 0 0 0 i\n" +"MouseMoveEvent 116 182 0 0 0 0 i\n" +"MouseMoveEvent 117 181 0 0 0 0 i\n" +"MouseMoveEvent 117 180 0 0 0 0 i\n" +"MouseMoveEvent 118 179 0 0 0 0 i\n" +"MouseMoveEvent 119 179 0 0 0 0 i\n" +"MouseMoveEvent 120 178 0 0 0 0 i\n" +"MouseMoveEvent 120 176 0 0 0 0 i\n" +"MouseMoveEvent 120 174 0 0 0 0 i\n" +"MouseMoveEvent 120 173 0 0 0 0 i\n" +"MouseMoveEvent 120 172 0 0 0 0 i\n" +"MiddleButtonPressEvent 120 172 0 0 0 0 i\n" +"MouseMoveEvent 120 171 0 0 0 0 i\n" +"MouseMoveEvent 121 166 0 0 0 0 i\n" +"MouseMoveEvent 123 165 0 0 0 0 i\n" +"MouseMoveEvent 125 165 0 0 0 0 i\n" +"MouseMoveEvent 126 166 0 0 0 0 i\n" +"MouseMoveEvent 129 167 0 0 0 0 i\n" +"MouseMoveEvent 130 167 0 0 0 0 i\n" +"MouseMoveEvent 133 169 0 0 0 0 i\n" +"MouseMoveEvent 135 169 0 0 0 0 i\n" +"MouseMoveEvent 136 169 0 0 0 0 i\n" +"MouseMoveEvent 137 168 0 0 0 0 i\n" +"MouseMoveEvent 139 169 0 0 0 0 i\n" +"MouseMoveEvent 148 168 0 0 0 0 i\n" +"MouseMoveEvent 158 165 0 0 0 0 i\n" +"MouseMoveEvent 159 165 0 0 0 0 i\n" +"MouseMoveEvent 163 165 0 0 0 0 i\n" +"MouseMoveEvent 164 164 0 0 0 0 i\n" +"MouseMoveEvent 165 164 0 0 0 0 i\n" +"MouseMoveEvent 167 163 0 0 0 0 i\n" +"MouseMoveEvent 168 163 0 0 0 0 i\n" +"MouseMoveEvent 174 162 0 0 0 0 i\n" +"MouseMoveEvent 178 161 0 0 0 0 i\n" +"MouseMoveEvent 179 161 0 0 0 0 i\n" +"MouseMoveEvent 180 161 0 0 0 0 i\n" +"MouseMoveEvent 181 161 0 0 0 0 i\n" +"MouseMoveEvent 183 161 0 0 0 0 i\n" +"MouseMoveEvent 183 160 0 0 0 0 i\n" +"MouseMoveEvent 182 159 0 0 0 0 i\n" +"MiddleButtonReleaseEvent 182 159 0 0 0 0 i\n" +"MouseMoveEvent 181 158 0 0 0 0 i\n" +"MouseMoveEvent 180 158 0 0 0 0 i\n" +"MouseMoveEvent 179 158 0 0 0 0 i\n" +; + +// This does the actual work: updates the probe. +// Callback for the interaction +class vtkTPWCallback : public vtkCommand +{ +public: + static vtkTPWCallback *New() + { return new vtkTPWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkPlaneWidget *planeWidget = reinterpret_cast<vtkPlaneWidget*>(caller); + planeWidget->GetPolyData(this->PolyData); + this->Actor->VisibilityOn(); + } + vtkTPWCallback():PolyData(0),Actor(0) {} + vtkPolyData *PolyData; + vtkActor *Actor; +}; + +int TestPlaneWidget( int argc, char *argv[] ) +{ + char* fname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combxyz.bin"); + char* fname2 = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combq.bin"); + + // Start by loading some data. + // + vtkPLOT3DReader *pl3d = vtkPLOT3DReader::New(); + pl3d->SetXYZFileName(fname); + pl3d->SetQFileName(fname2); + pl3d->SetScalarFunctionNumber(100); + pl3d->SetVectorFunctionNumber(202); + pl3d->Update(); + + delete [] fname; + delete [] fname2; + + vtkPolyData *plane = vtkPolyData::New(); + + vtkProbeFilter *probe = vtkProbeFilter::New(); + probe->SetInput(plane); + probe->SetSource(pl3d->GetOutput()); + + vtkPolyDataMapper *probeMapper = vtkPolyDataMapper::New(); + probeMapper->SetInput(probe->GetPolyDataOutput()); + double tmp[2]; + pl3d->GetOutput()->GetScalarRange(tmp); + probeMapper->SetScalarRange(tmp[0], tmp[1]); + + vtkActor *probeActor = vtkActor::New(); + probeActor->SetMapper(probeMapper); + probeActor->VisibilityOff(); + + // An outline is shown for context. + vtkStructuredGridOutlineFilter *outline = + vtkStructuredGridOutlineFilter::New(); + outline->SetInputConnection(pl3d->GetOutputPort()); + + vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + + vtkActor *outlineActor = vtkActor::New(); + outlineActor->SetMapper(outlineMapper); + + // Create the RenderWindow, Renderer and both Actors + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The SetInteractor method is how 3D widgets are associated with the render + // window interactor. Internally, SetInteractor sets up a bunch of callbacks + // using the Command/Observer mechanism (AddObserver()). + vtkTPWCallback *myCallback = vtkTPWCallback::New(); + myCallback->PolyData = plane; + myCallback->Actor = probeActor; + + // The plane widget is used probe the dataset. + // + vtkPlaneWidget *planeWidget = vtkPlaneWidget::New(); + planeWidget->SetInteractor(iren); + planeWidget->SetInput(pl3d->GetOutput()); + planeWidget->NormalToXAxisOn(); + planeWidget->SetResolution(20); + planeWidget->SetRepresentationToOutline(); + planeWidget->PlaceWidget(); + planeWidget->AddObserver(vtkCommand::InteractionEvent,myCallback); + + ren1->AddActor(probeActor); + ren1->AddActor(outlineActor); + + // Add the actors to the renderer, set the background and size + // + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(300, 300); + + // record events + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); +// recorder->SetFileName("c:/record.log"); +// recorder->Record(); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(TPWeventLog); + + // render the image + // + iren->Initialize(); + renWin->Render(); + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + recorder->Off(); + recorder->Delete(); + myCallback->Delete(); + planeWidget->Delete(); + pl3d->Delete(); + plane->Delete(); + probe->Delete(); + probeMapper->Delete(); + probeActor->Delete(); + outline->Delete(); + outlineMapper->Delete(); + outlineActor->Delete(); + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestPointWidget.cxx b/Widgets/Testing/Cxx/TestPointWidget.cxx new file mode 100644 index 0000000..997a638 --- /dev/null +++ b/Widgets/Testing/Cxx/TestPointWidget.cxx @@ -0,0 +1,672 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestPointWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkActor.h" +#include "vtkCommand.h" +#include "vtkConeSource.h" +#include "vtkGlyph3D.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkPLOT3DReader.h" +#include "vtkPointWidget.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProbeFilter.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredGridOutlineFilter.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char PointWidgetEventLog[] = +"# StreamVersion 1\n" +"CharEvent 204 169 0 0 105 1 i\n" +"KeyReleaseEvent 204 169 0 0 105 1 i\n" +"KeyPressEvent 204 169 0 0 116 1 t\n" +"CharEvent 204 169 0 0 116 1 t\n" +"KeyReleaseEvent 204 169 0 0 116 1 t\n" +"MouseMoveEvent 204 168 0 0 0 0 t\n" +"MouseMoveEvent 204 167 0 0 0 0 t\n" +"MouseMoveEvent 202 165 0 0 0 0 t\n" +"MouseMoveEvent 196 164 0 0 0 0 t\n" +"MouseMoveEvent 196 163 0 0 0 0 t\n" +"MouseMoveEvent 193 162 0 0 0 0 t\n" +"MouseMoveEvent 192 161 0 0 0 0 t\n" +"MouseMoveEvent 190 160 0 0 0 0 t\n" +"MouseMoveEvent 190 159 0 0 0 0 t\n" +"MouseMoveEvent 189 158 0 0 0 0 t\n" +"MouseMoveEvent 187 156 0 0 0 0 t\n" +"MouseMoveEvent 184 154 0 0 0 0 t\n" +"MouseMoveEvent 178 150 0 0 0 0 t\n" +"MouseMoveEvent 176 148 0 0 0 0 t\n" +"MouseMoveEvent 175 147 0 0 0 0 t\n" +"MouseMoveEvent 175 146 0 0 0 0 t\n" +"MouseMoveEvent 175 147 0 0 0 0 t\n" +"MouseMoveEvent 175 146 0 0 0 0 t\n" +"MouseMoveEvent 176 146 0 0 0 0 t\n" +"MouseMoveEvent 178 146 0 0 0 0 t\n" +"MouseMoveEvent 179 147 0 0 0 0 t\n" +"MouseMoveEvent 179 148 0 0 0 0 t\n" +"MouseMoveEvent 178 148 0 0 0 0 t\n" +"MouseMoveEvent 177 148 0 0 0 0 t\n" +"MouseMoveEvent 177 149 0 0 0 0 t\n" +"MouseMoveEvent 177 150 0 0 0 0 t\n" +"MouseMoveEvent 177 151 0 0 0 0 t\n" +"LeftButtonPressEvent 177 151 0 0 0 0 t\n" +"MouseMoveEvent 177 152 0 0 0 0 t\n" +"MouseMoveEvent 177 154 0 0 0 0 t\n" +"MouseMoveEvent 177 155 0 0 0 0 t\n" +"MouseMoveEvent 177 156 0 0 0 0 t\n" +"MouseMoveEvent 177 157 0 0 0 0 t\n" +"MouseMoveEvent 177 158 0 0 0 0 t\n" +"MouseMoveEvent 177 159 0 0 0 0 t\n" +"MouseMoveEvent 177 160 0 0 0 0 t\n" +"MouseMoveEvent 177 161 0 0 0 0 t\n" +"MouseMoveEvent 177 162 0 0 0 0 t\n" +"MouseMoveEvent 176 162 0 0 0 0 t\n" +"MouseMoveEvent 176 163 0 0 0 0 t\n" +"MouseMoveEvent 176 164 0 0 0 0 t\n" +"MouseMoveEvent 176 165 0 0 0 0 t\n" +"MouseMoveEvent 176 166 0 0 0 0 t\n" +"MouseMoveEvent 176 167 0 0 0 0 t\n" +"MouseMoveEvent 176 168 0 0 0 0 t\n" +"MouseMoveEvent 176 169 0 0 0 0 t\n" +"MouseMoveEvent 176 170 0 0 0 0 t\n" +"MouseMoveEvent 176 169 0 0 0 0 t\n" +"MouseMoveEvent 176 168 0 0 0 0 t\n" +"MouseMoveEvent 176 166 0 0 0 0 t\n" +"MouseMoveEvent 176 165 0 0 0 0 t\n" +"MouseMoveEvent 176 164 0 0 0 0 t\n" +"MouseMoveEvent 176 163 0 0 0 0 t\n" +"MouseMoveEvent 176 162 0 0 0 0 t\n" +"MouseMoveEvent 176 161 0 0 0 0 t\n" +"MouseMoveEvent 176 160 0 0 0 0 t\n" +"MouseMoveEvent 176 159 0 0 0 0 t\n" +"MouseMoveEvent 176 158 0 0 0 0 t\n" +"MouseMoveEvent 176 157 0 0 0 0 t\n" +"MouseMoveEvent 176 156 0 0 0 0 t\n" +"MouseMoveEvent 176 155 0 0 0 0 t\n" +"MouseMoveEvent 176 154 0 0 0 0 t\n" +"MouseMoveEvent 176 153 0 0 0 0 t\n" +"MouseMoveEvent 176 152 0 0 0 0 t\n" +"MouseMoveEvent 176 151 0 0 0 0 t\n" +"MouseMoveEvent 176 150 0 0 0 0 t\n" +"MouseMoveEvent 176 149 0 0 0 0 t\n" +"MouseMoveEvent 176 148 0 0 0 0 t\n" +"LeftButtonReleaseEvent 176 148 0 0 0 0 t\n" +"MouseMoveEvent 176 148 0 0 0 0 t\n" +"MouseMoveEvent 176 147 0 0 0 0 t\n" +"MouseMoveEvent 176 146 0 0 0 0 t\n" +"MouseMoveEvent 176 145 0 0 0 0 t\n" +"MouseMoveEvent 175 145 0 0 0 0 t\n" +"MouseMoveEvent 173 145 0 0 0 0 t\n" +"MouseMoveEvent 168 145 0 0 0 0 t\n" +"MouseMoveEvent 164 145 0 0 0 0 t\n" +"MouseMoveEvent 162 145 0 0 0 0 t\n" +"MouseMoveEvent 161 145 0 0 0 0 t\n" +"MouseMoveEvent 160 145 0 0 0 0 t\n" +"MouseMoveEvent 158 145 0 0 0 0 t\n" +"KeyPressEvent 158 145 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 157 146 0 4 0 0 Shift_L\n" +"MouseMoveEvent 157 147 0 4 0 0 Shift_L\n" +"MouseMoveEvent 157 148 0 4 0 0 Shift_L\n" +"MouseMoveEvent 157 147 0 4 0 0 Shift_L\n" +"MouseMoveEvent 158 144 0 4 0 0 Shift_L\n" +"MouseMoveEvent 159 144 0 4 0 0 Shift_L\n" +"LeftButtonPressEvent 159 144 0 4 0 0 Shift_L\n" +"MouseMoveEvent 160 144 0 4 0 0 Shift_L\n" +"MouseMoveEvent 160 145 0 4 0 0 Shift_L\n" +"MouseMoveEvent 160 146 0 4 0 0 Shift_L\n" +"MouseMoveEvent 160 147 0 4 0 0 Shift_L\n" +"MouseMoveEvent 162 148 0 4 0 0 Shift_L\n" +"MouseMoveEvent 163 148 0 4 0 0 Shift_L\n" +"MouseMoveEvent 164 149 0 4 0 0 Shift_L\n" +"KeyPressEvent 164 149 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 166 149 0 4 0 0 Shift_L\n" +"KeyPressEvent 166 149 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 166 150 0 4 0 0 Shift_L\n" +"KeyPressEvent 166 150 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 166 149 0 4 0 0 Shift_L\n" +"KeyPressEvent 166 149 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 167 149 0 4 0 0 Shift_L\n" +"KeyPressEvent 167 149 0 -128 0 1 Shift_L\n" +"KeyPressEvent 167 149 0 -128 0 1 Shift_L\n" +"KeyPressEvent 167 149 0 -128 0 1 Shift_L\n" +"KeyPressEvent 167 149 0 -128 0 1 Shift_L\n" +"KeyPressEvent 167 149 0 -128 0 1 Shift_L\n" +"KeyPressEvent 167 149 0 -128 0 1 Shift_L\n" +"KeyPressEvent 167 149 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 168 149 0 4 0 0 Shift_L\n" +"KeyPressEvent 168 149 0 -128 0 1 Shift_L\n" +"LeftButtonReleaseEvent 168 149 0 4 0 0 Shift_L\n" +"MouseMoveEvent 168 149 0 4 0 0 Shift_L\n" +"KeyPressEvent 168 149 0 -128 0 1 Shift_L\n" +"KeyPressEvent 168 149 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 169 149 0 4 0 0 Shift_L\n" +"KeyPressEvent 169 149 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 169 150 0 4 0 0 Shift_L\n" +"MouseMoveEvent 170 150 0 4 0 0 Shift_L\n" +"KeyPressEvent 170 150 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 170 151 0 4 0 0 Shift_L\n" +"MouseMoveEvent 171 151 0 4 0 0 Shift_L\n" +"KeyPressEvent 171 151 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 171 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 172 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 172 153 0 4 0 0 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"LeftButtonPressEvent 172 153 0 4 0 0 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"KeyPressEvent 172 153 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 173 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 173 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 174 153 0 4 0 0 Shift_L\n" +"MouseMoveEvent 175 153 0 4 0 0 Shift_L\n" +"KeyPressEvent 175 153 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 176 153 0 4 0 0 Shift_L\n" +"MouseMoveEvent 177 153 0 4 0 0 Shift_L\n" +"KeyPressEvent 177 153 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 180 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 181 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 181 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 183 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 183 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 184 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 184 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 185 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 185 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 186 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 187 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 188 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 188 152 0 -128 0 1 Shift_L\n" +"KeyPressEvent 188 152 0 -128 0 1 Shift_L\n" +"KeyPressEvent 188 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 189 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 190 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 190 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 191 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 192 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 192 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 193 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 194 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 195 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 195 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 196 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 196 152 0 -128 0 1 Shift_L\n" +"KeyPressEvent 196 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 197 152 0 4 0 0 Shift_L\n" +"KeyPressEvent 197 152 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 197 151 0 4 0 0 Shift_L\n" +"KeyPressEvent 197 151 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 198 151 0 4 0 0 Shift_L\n" +"MouseMoveEvent 199 151 0 4 0 0 Shift_L\n" +"KeyPressEvent 199 151 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 200 151 0 4 0 0 Shift_L\n" +"MouseMoveEvent 201 151 0 4 0 0 Shift_L\n" +"MouseMoveEvent 203 151 0 4 0 0 Shift_L\n" +"KeyPressEvent 203 151 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 204 151 0 4 0 0 Shift_L\n" +"KeyPressEvent 204 151 0 -128 0 1 Shift_L\n" +"KeyPressEvent 204 151 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 205 151 0 4 0 0 Shift_L\n" +"MouseMoveEvent 206 151 0 4 0 0 Shift_L\n" +"KeyPressEvent 206 151 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 207 151 0 4 0 0 Shift_L\n" +"KeyPressEvent 207 151 0 -128 0 1 Shift_L\n" +"KeyPressEvent 207 151 0 -128 0 1 Shift_L\n" +"KeyPressEvent 207 151 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 207 152 0 4 0 0 Shift_L\n" +"MouseMoveEvent 206 153 0 4 0 0 Shift_L\n" +"MouseMoveEvent 205 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 205 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 203 154 0 4 0 0 Shift_L\n" +"MouseMoveEvent 200 154 0 4 0 0 Shift_L\n" +"MouseMoveEvent 199 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 199 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 197 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 197 154 0 -128 0 1 Shift_L\n" +"KeyPressEvent 197 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 196 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 196 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 195 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 195 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 194 154 0 4 0 0 Shift_L\n" +"MouseMoveEvent 193 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 193 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 189 154 0 4 0 0 Shift_L\n" +"MouseMoveEvent 187 154 0 4 0 0 Shift_L\n" +"MouseMoveEvent 186 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 186 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 185 153 0 4 0 0 Shift_L\n" +"KeyPressEvent 185 153 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 185 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 185 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 184 154 0 4 0 0 Shift_L\n" +"KeyPressEvent 184 154 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 184 155 0 4 0 0 Shift_L\n" +"KeyPressEvent 184 155 0 -128 0 1 Shift_L\n" +"KeyPressEvent 184 155 0 -128 0 1 Shift_L\n" +"KeyPressEvent 184 155 0 -128 0 1 Shift_L\n" +"KeyPressEvent 184 155 0 -128 0 1 Shift_L\n" +"KeyPressEvent 184 155 0 -128 0 1 Shift_L\n" +"KeyPressEvent 184 155 0 -128 0 1 Shift_L\n" +"KeyPressEvent 184 155 0 -128 0 1 Shift_L\n" +"MouseMoveEvent 184 154 0 4 0 0 Shift_L\n" +"LeftButtonReleaseEvent 184 154 0 4 0 0 Shift_L\n" +"MouseMoveEvent 184 154 0 4 0 0 Shift_L\n" +"KeyReleaseEvent 184 154 0 0 0 1 Shift_L\n" +"MouseMoveEvent 185 154 0 0 0 0 Shift_L\n" +"MouseMoveEvent 185 155 0 0 0 0 Shift_L\n" +"MouseMoveEvent 186 155 0 0 0 0 Shift_L\n" +"MouseMoveEvent 187 156 0 0 0 0 Shift_L\n" +"MouseMoveEvent 188 156 0 0 0 0 Shift_L\n" +"MouseMoveEvent 189 156 0 0 0 0 Shift_L\n" +"MouseMoveEvent 190 157 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 159 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 161 0 0 0 0 Shift_L\n" +"MouseMoveEvent 192 162 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 194 167 0 0 0 0 Shift_L\n" +"MouseMoveEvent 194 168 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 168 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 168 0 0 0 0 Shift_L\n" +"LeftButtonPressEvent 196 168 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 169 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 170 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 171 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 172 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 173 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 174 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 175 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 176 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 177 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 178 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 179 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 180 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 181 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 182 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 183 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 184 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 185 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 187 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 188 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 189 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 190 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 191 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 192 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 194 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 195 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 196 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 197 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 198 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 199 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 200 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 201 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 202 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 203 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 204 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 205 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 206 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 208 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 210 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 212 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 213 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 214 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 215 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 216 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 217 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 218 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 219 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 220 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 221 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 222 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 223 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 224 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 223 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 222 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 221 0 0 0 0 Shift_L\n" +"LeftButtonReleaseEvent 196 221 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 221 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 220 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 219 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 217 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 216 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 214 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 213 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 210 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 206 0 0 0 0 Shift_L\n" +"MouseMoveEvent 190 200 0 0 0 0 Shift_L\n" +"MouseMoveEvent 189 197 0 0 0 0 Shift_L\n" +"MouseMoveEvent 189 193 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 189 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 186 0 0 0 0 Shift_L\n" +"MouseMoveEvent 197 182 0 0 0 0 Shift_L\n" +"MouseMoveEvent 198 178 0 0 0 0 Shift_L\n" +"MouseMoveEvent 198 175 0 0 0 0 Shift_L\n" +"MouseMoveEvent 198 171 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 167 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 162 0 0 0 0 Shift_L\n" +"MouseMoveEvent 194 158 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 157 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 156 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 155 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 153 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 147 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 146 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 147 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 197 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 198 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 198 151 0 0 0 0 Shift_L\n" +"MouseMoveEvent 198 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 197 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 197 151 0 0 0 0 Shift_L\n" +"MiddleButtonPressEvent 197 151 0 0 0 0 Shift_L\n" +"MouseMoveEvent 197 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 197 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 200 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 205 151 0 0 0 0 Shift_L\n" +"MouseMoveEvent 206 151 0 0 0 0 Shift_L\n" +"MouseMoveEvent 207 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 208 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 210 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 211 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 212 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 212 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 212 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 213 148 0 0 0 0 Shift_L\n" +"MouseMoveEvent 213 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 214 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 216 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 218 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 220 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 221 149 0 0 0 0 Shift_L\n" +"MouseMoveEvent 221 150 0 0 0 0 Shift_L\n" +"MouseMoveEvent 221 151 0 0 0 0 Shift_L\n" +"MouseMoveEvent 221 152 0 0 0 0 Shift_L\n" +"MouseMoveEvent 220 153 0 0 0 0 Shift_L\n" +"MouseMoveEvent 219 155 0 0 0 0 Shift_L\n" +"MouseMoveEvent 216 157 0 0 0 0 Shift_L\n" +"MouseMoveEvent 215 158 0 0 0 0 Shift_L\n" +"MouseMoveEvent 215 159 0 0 0 0 Shift_L\n" +"MouseMoveEvent 215 160 0 0 0 0 Shift_L\n" +"MouseMoveEvent 215 161 0 0 0 0 Shift_L\n" +"MouseMoveEvent 214 161 0 0 0 0 Shift_L\n" +"MouseMoveEvent 213 161 0 0 0 0 Shift_L\n" +"MouseMoveEvent 211 161 0 0 0 0 Shift_L\n" +"MouseMoveEvent 210 162 0 0 0 0 Shift_L\n" +"MouseMoveEvent 209 162 0 0 0 0 Shift_L\n" +"MouseMoveEvent 208 162 0 0 0 0 Shift_L\n" +"MouseMoveEvent 207 163 0 0 0 0 Shift_L\n" +"MouseMoveEvent 205 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 204 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 204 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 203 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 201 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 200 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 198 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 197 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 196 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 195 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 194 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 192 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 190 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 189 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 188 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 188 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 189 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 190 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 163 0 0 0 0 Shift_L\n" +"MouseMoveEvent 192 163 0 0 0 0 Shift_L\n" +"MiddleButtonReleaseEvent 192 163 0 0 0 0 Shift_L\n" +"MouseMoveEvent 192 163 0 0 0 0 Shift_L\n" +"MouseMoveEvent 193 163 0 0 0 0 Shift_L\n" +"MouseMoveEvent 194 163 0 0 0 0 Shift_L\n" +"RightButtonPressEvent 194 163 0 0 0 0 Shift_L\n" +"MouseMoveEvent 194 164 0 0 0 0 Shift_L\n" +"MouseMoveEvent 192 165 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 166 0 0 0 0 Shift_L\n" +"MouseMoveEvent 191 168 0 0 0 0 Shift_L\n" +"MouseMoveEvent 188 171 0 0 0 0 Shift_L\n" +"MouseMoveEvent 186 173 0 0 0 0 Shift_L\n" +"MouseMoveEvent 185 175 0 0 0 0 Shift_L\n" +"MouseMoveEvent 185 176 0 0 0 0 Shift_L\n" +"MouseMoveEvent 185 178 0 0 0 0 Shift_L\n" +"MouseMoveEvent 184 181 0 0 0 0 Shift_L\n" +"MouseMoveEvent 184 183 0 0 0 0 Shift_L\n" +"MouseMoveEvent 182 185 0 0 0 0 Shift_L\n" +"MouseMoveEvent 181 186 0 0 0 0 Shift_L\n" +"MouseMoveEvent 181 187 0 0 0 0 Shift_L\n" +"MouseMoveEvent 181 188 0 0 0 0 Shift_L\n" +"MouseMoveEvent 181 189 0 0 0 0 Shift_L\n" +"MouseMoveEvent 181 190 0 0 0 0 Shift_L\n" +"MouseMoveEvent 182 191 0 0 0 0 Shift_L\n" +"MouseMoveEvent 182 192 0 0 0 0 Shift_L\n" +"MouseMoveEvent 182 193 0 0 0 0 Shift_L\n" +"MouseMoveEvent 182 194 0 0 0 0 Shift_L\n" +"MouseMoveEvent 182 195 0 0 0 0 Shift_L\n" +"MouseMoveEvent 181 197 0 0 0 0 Shift_L\n" +"MouseMoveEvent 180 202 0 0 0 0 Shift_L\n" +"MouseMoveEvent 179 204 0 0 0 0 Shift_L\n" +"MouseMoveEvent 177 206 0 0 0 0 Shift_L\n" +"MouseMoveEvent 176 209 0 0 0 0 Shift_L\n" +"MouseMoveEvent 175 210 0 0 0 0 Shift_L\n" +"MouseMoveEvent 175 211 0 0 0 0 Shift_L\n" +"MouseMoveEvent 175 212 0 0 0 0 Shift_L\n" +"MouseMoveEvent 175 213 0 0 0 0 Shift_L\n" +"MouseMoveEvent 175 216 0 0 0 0 Shift_L\n" +"MouseMoveEvent 174 216 0 0 0 0 Shift_L\n" +"MouseMoveEvent 174 217 0 0 0 0 Shift_L\n" +"MouseMoveEvent 173 220 0 0 0 0 Shift_L\n" +"MouseMoveEvent 170 222 0 0 0 0 Shift_L\n" +"MouseMoveEvent 169 224 0 0 0 0 Shift_L\n" +"MouseMoveEvent 167 227 0 0 0 0 Shift_L\n" +"MouseMoveEvent 164 229 0 0 0 0 Shift_L\n" +"MouseMoveEvent 162 232 0 0 0 0 Shift_L\n" +"MouseMoveEvent 162 233 0 0 0 0 Shift_L\n" +"MouseMoveEvent 162 234 0 0 0 0 Shift_L\n" +"MouseMoveEvent 161 235 0 0 0 0 Shift_L\n" +"MouseMoveEvent 161 236 0 0 0 0 Shift_L\n" +"MouseMoveEvent 161 237 0 0 0 0 Shift_L\n" +"MouseMoveEvent 161 238 0 0 0 0 Shift_L\n" +"MouseMoveEvent 161 239 0 0 0 0 Shift_L\n" +"MouseMoveEvent 161 240 0 0 0 0 Shift_L\n" +"MouseMoveEvent 160 242 0 0 0 0 Shift_L\n" +"MouseMoveEvent 160 243 0 0 0 0 Shift_L\n" +"MouseMoveEvent 160 244 0 0 0 0 Shift_L\n" +"MouseMoveEvent 160 243 0 0 0 0 Shift_L\n" +"MouseMoveEvent 160 242 0 0 0 0 Shift_L\n" +"MouseMoveEvent 162 242 0 0 0 0 Shift_L\n" +"MouseMoveEvent 163 241 0 0 0 0 Shift_L\n" +"MouseMoveEvent 163 240 0 0 0 0 Shift_L\n" +"RightButtonReleaseEvent 163 240 0 0 0 0 Shift_L\n" +"MouseMoveEvent 163 240 0 0 0 0 Shift_L\n" +"MouseMoveEvent 163 241 0 0 0 0 Shift_L\n" +"MouseMoveEvent 163 242 0 0 0 0 Shift_L\n" +; + +// This does the actual work: updates the probe. +// Callback for the interaction +class vtkmyPWCallback : public vtkCommand +{ +public: + static vtkmyPWCallback *New() + { return new vtkmyPWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkPointWidget *pointWidget = reinterpret_cast<vtkPointWidget*>(caller); + pointWidget->GetPolyData(this->PolyData); + pointWidget->GetPolyData(this->PolyData); + this->Actor->VisibilityOn(); + } + vtkmyPWCallback():PolyData(0),Actor(0) {} + vtkPolyData *PolyData; + vtkActor *Actor; +}; + +int TestPointWidget( int argc, char *argv[] ) +{ + char* fname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combxyz.bin"); + char* fname2 = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combq.bin"); + + // Start by loading some data. + // + vtkPLOT3DReader *pl3d = vtkPLOT3DReader::New(); + pl3d->SetXYZFileName(fname); + pl3d->SetQFileName(fname2); + pl3d->SetScalarFunctionNumber(100); + pl3d->SetVectorFunctionNumber(202); + pl3d->Update(); + + delete [] fname; + delete [] fname2; + + vtkPolyData *point = vtkPolyData::New(); + + vtkProbeFilter *probe = vtkProbeFilter::New(); + probe->SetInput(point); + probe->SetSource(pl3d->GetOutput()); + + // create glyph + vtkConeSource *cone = vtkConeSource::New(); + cone->SetResolution(16); + + vtkGlyph3D *glyph = vtkGlyph3D::New(); + glyph->SetInputConnection(probe->GetOutputPort()); + glyph->SetSource(cone->GetOutput()); + glyph->SetVectorModeToUseVector(); + glyph->SetScaleModeToDataScalingOff(); + glyph->SetScaleFactor(pl3d->GetOutput()->GetLength() * 0.1); + + vtkPolyDataMapper *glyphMapper = vtkPolyDataMapper::New(); + glyphMapper->SetInputConnection(glyph->GetOutputPort()); + + vtkActor *glyphActor = vtkActor::New(); + glyphActor->SetMapper(glyphMapper); + glyphActor->VisibilityOff(); + + // An outline is shown for context. + vtkStructuredGridOutlineFilter *outline = + vtkStructuredGridOutlineFilter::New(); + outline->SetInputConnection(pl3d->GetOutputPort()); + + vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + + vtkActor *outlineActor = vtkActor::New(); + outlineActor->SetMapper(outlineMapper); + + // Create the RenderWindow, Renderer and both Actors + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + // The SetInteractor method is how 3D widgets are associated with the render + // window interactor. Internally, SetInteractor sets up a bunch of callbacks + // using the Command/Observer mechanism (AddObserver()). + vtkmyPWCallback *myCallback = vtkmyPWCallback::New(); + myCallback->PolyData = point; + myCallback->Actor = glyphActor; + + // The plane widget is used probe the dataset. + // + vtkPointWidget *pointWidget = vtkPointWidget::New(); + pointWidget->SetInteractor(iren); + pointWidget->SetInput(pl3d->GetOutput()); + pointWidget->AllOff(); + pointWidget->PlaceWidget(); + pointWidget->AddObserver(vtkCommand::InteractionEvent,myCallback); + + ren1->AddActor(outlineActor); + ren1->AddActor(glyphActor); + + // Add the actors to the renderer, set the background and size + // + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(300, 300); + + // record events + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); +// recorder->SetFileName("c:/record.log"); +// recorder->Record(); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(PointWidgetEventLog); + + // render the image + // + iren->Initialize(); + renWin->Render(); + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + recorder->Off(); + recorder->Delete(); + myCallback->Delete(); + pointWidget->Delete(); + pl3d->Delete(); + point->Delete(); + probe->Delete(); + cone->Delete(); + glyph->Delete(); + glyphMapper->Delete(); + glyphActor->Delete(); + outline->Delete(); + outlineMapper->Delete(); + outlineActor->Delete(); + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestScalarBarWidget.cxx b/Widgets/Testing/Cxx/TestScalarBarWidget.cxx new file mode 100644 index 0000000..dc2cb2f --- /dev/null +++ b/Widgets/Testing/Cxx/TestScalarBarWidget.cxx @@ -0,0 +1,458 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: TestScalarBarWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPLOT3DReader.h" +#include "vtkScalarBarWidget.h" +#include "vtkStructuredGridGeometryFilter.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkScalarBarActor.h" +#include "vtkStructuredGrid.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char TSBWeventLog[] = +"# StreamVersion 1\n" +"CharEvent 153 168 0 0 105 1 i\n" +"KeyReleaseEvent 153 168 0 0 105 1 i\n" +"MouseMoveEvent 153 167 0 0 0 0 i\n" +"MouseMoveEvent 154 166 0 0 0 0 i\n" +"MouseMoveEvent 156 165 0 0 0 0 i\n" +"MouseMoveEvent 159 163 0 0 0 0 i\n" +"MouseMoveEvent 163 162 0 0 0 0 i\n" +"MouseMoveEvent 167 161 0 0 0 0 i\n" +"MouseMoveEvent 170 161 0 0 0 0 i\n" +"MouseMoveEvent 172 161 0 0 0 0 i\n" +"MouseMoveEvent 173 161 0 0 0 0 i\n" +"MouseMoveEvent 176 161 0 0 0 0 i\n" +"MouseMoveEvent 179 161 0 0 0 0 i\n" +"MouseMoveEvent 181 161 0 0 0 0 i\n" +"MouseMoveEvent 185 160 0 0 0 0 i\n" +"MouseMoveEvent 188 159 0 0 0 0 i\n" +"MouseMoveEvent 191 159 0 0 0 0 i\n" +"MouseMoveEvent 195 158 0 0 0 0 i\n" +"MouseMoveEvent 198 157 0 0 0 0 i\n" +"MouseMoveEvent 201 157 0 0 0 0 i\n" +"MouseMoveEvent 203 157 0 0 0 0 i\n" +"MouseMoveEvent 205 157 0 0 0 0 i\n" +"MouseMoveEvent 208 156 0 0 0 0 i\n" +"MouseMoveEvent 212 156 0 0 0 0 i\n" +"MouseMoveEvent 217 155 0 0 0 0 i\n" +"MouseMoveEvent 220 155 0 0 0 0 i\n" +"MouseMoveEvent 222 155 0 0 0 0 i\n" +"MouseMoveEvent 224 154 0 0 0 0 i\n" +"MouseMoveEvent 227 154 0 0 0 0 i\n" +"MouseMoveEvent 230 154 0 0 0 0 i\n" +"MouseMoveEvent 234 153 0 0 0 0 i\n" +"MouseMoveEvent 237 153 0 0 0 0 i\n" +"MouseMoveEvent 239 153 0 0 0 0 i\n" +"MouseMoveEvent 240 153 0 0 0 0 i\n" +"MouseMoveEvent 242 153 0 0 0 0 i\n" +"MouseMoveEvent 243 153 0 0 0 0 i\n" +"MouseMoveEvent 245 153 0 0 0 0 i\n" +"MouseMoveEvent 246 153 0 0 0 0 i\n" +"MouseMoveEvent 247 152 0 0 0 0 i\n" +"MouseMoveEvent 248 152 0 0 0 0 i\n" +"MouseMoveEvent 249 152 0 0 0 0 i\n" +"MouseMoveEvent 250 152 0 0 0 0 i\n" +"MouseMoveEvent 251 152 0 0 0 0 i\n" +"MouseMoveEvent 252 152 0 0 0 0 i\n" +"MouseMoveEvent 253 152 0 0 0 0 i\n" +"MouseMoveEvent 253 151 0 0 0 0 i\n" +"MouseMoveEvent 254 151 0 0 0 0 i\n" +"LeftButtonPressEvent 254 151 0 0 0 0 i\n" +"MouseMoveEvent 253 150 0 0 0 0 i\n" +"MouseMoveEvent 251 148 0 0 0 0 i\n" +"MouseMoveEvent 248 145 0 0 0 0 i\n" +"MouseMoveEvent 243 141 0 0 0 0 i\n" +"MouseMoveEvent 240 137 0 0 0 0 i\n" +"MouseMoveEvent 236 133 0 0 0 0 i\n" +"MouseMoveEvent 234 130 0 0 0 0 i\n" +"MouseMoveEvent 232 128 0 0 0 0 i\n" +"MouseMoveEvent 229 125 0 0 0 0 i\n" +"MouseMoveEvent 226 122 0 0 0 0 i\n" +"MouseMoveEvent 222 118 0 0 0 0 i\n" +"MouseMoveEvent 219 115 0 0 0 0 i\n" +"MouseMoveEvent 217 112 0 0 0 0 i\n" +"MouseMoveEvent 215 110 0 0 0 0 i\n" +"MouseMoveEvent 212 107 0 0 0 0 i\n" +"MouseMoveEvent 210 103 0 0 0 0 i\n" +"MouseMoveEvent 207 100 0 0 0 0 i\n" +"MouseMoveEvent 203 96 0 0 0 0 i\n" +"MouseMoveEvent 199 94 0 0 0 0 i\n" +"MouseMoveEvent 196 91 0 0 0 0 i\n" +"MouseMoveEvent 193 88 0 0 0 0 i\n" +"MouseMoveEvent 191 86 0 0 0 0 i\n" +"MouseMoveEvent 188 83 0 0 0 0 i\n" +"MouseMoveEvent 186 80 0 0 0 0 i\n" +"MouseMoveEvent 182 78 0 0 0 0 i\n" +"MouseMoveEvent 179 75 0 0 0 0 i\n" +"MouseMoveEvent 175 73 0 0 0 0 i\n" +"MouseMoveEvent 172 70 0 0 0 0 i\n" +"MouseMoveEvent 169 68 0 0 0 0 i\n" +"MouseMoveEvent 167 65 0 0 0 0 i\n" +"MouseMoveEvent 164 63 0 0 0 0 i\n" +"MouseMoveEvent 162 60 0 0 0 0 i\n" +"MouseMoveEvent 160 58 0 0 0 0 i\n" +"MouseMoveEvent 157 56 0 0 0 0 i\n" +"MouseMoveEvent 155 55 0 0 0 0 i\n" +"MouseMoveEvent 153 53 0 0 0 0 i\n" +"MouseMoveEvent 151 51 0 0 0 0 i\n" +"MouseMoveEvent 149 49 0 0 0 0 i\n" +"MouseMoveEvent 148 47 0 0 0 0 i\n" +"MouseMoveEvent 147 46 0 0 0 0 i\n" +"MouseMoveEvent 145 44 0 0 0 0 i\n" +"MouseMoveEvent 143 41 0 0 0 0 i\n" +"MouseMoveEvent 142 40 0 0 0 0 i\n" +"MouseMoveEvent 141 40 0 0 0 0 i\n" +"MouseMoveEvent 140 39 0 0 0 0 i\n" +"MouseMoveEvent 139 37 0 0 0 0 i\n" +"MouseMoveEvent 138 36 0 0 0 0 i\n" +"MouseMoveEvent 138 35 0 0 0 0 i\n" +"MouseMoveEvent 137 35 0 0 0 0 i\n" +"MouseMoveEvent 136 34 0 0 0 0 i\n" +"MouseMoveEvent 135 32 0 0 0 0 i\n" +"MouseMoveEvent 134 32 0 0 0 0 i\n" +"MouseMoveEvent 134 33 0 0 0 0 i\n" +"MouseMoveEvent 132 34 0 0 0 0 i\n" +"MouseMoveEvent 131 37 0 0 0 0 i\n" +"MouseMoveEvent 129 40 0 0 0 0 i\n" +"MouseMoveEvent 127 44 0 0 0 0 i\n" +"MouseMoveEvent 126 49 0 0 0 0 i\n" +"MouseMoveEvent 123 53 0 0 0 0 i\n" +"MouseMoveEvent 121 56 0 0 0 0 i\n" +"MouseMoveEvent 118 60 0 0 0 0 i\n" +"MouseMoveEvent 115 63 0 0 0 0 i\n" +"MouseMoveEvent 112 66 0 0 0 0 i\n" +"MouseMoveEvent 110 68 0 0 0 0 i\n" +"MouseMoveEvent 108 71 0 0 0 0 i\n" +"MouseMoveEvent 105 73 0 0 0 0 i\n" +"MouseMoveEvent 102 75 0 0 0 0 i\n" +"MouseMoveEvent 99 78 0 0 0 0 i\n" +"MouseMoveEvent 96 80 0 0 0 0 i\n" +"MouseMoveEvent 93 83 0 0 0 0 i\n" +"MouseMoveEvent 91 85 0 0 0 0 i\n" +"MouseMoveEvent 88 87 0 0 0 0 i\n" +"MouseMoveEvent 85 90 0 0 0 0 i\n" +"MouseMoveEvent 82 93 0 0 0 0 i\n" +"MouseMoveEvent 79 95 0 0 0 0 i\n" +"MouseMoveEvent 76 96 0 0 0 0 i\n" +"MouseMoveEvent 73 97 0 0 0 0 i\n" +"MouseMoveEvent 70 99 0 0 0 0 i\n" +"MouseMoveEvent 67 101 0 0 0 0 i\n" +"MouseMoveEvent 64 102 0 0 0 0 i\n" +"MouseMoveEvent 62 104 0 0 0 0 i\n" +"MouseMoveEvent 58 105 0 0 0 0 i\n" +"MouseMoveEvent 54 105 0 0 0 0 i\n" +"MouseMoveEvent 51 106 0 0 0 0 i\n" +"MouseMoveEvent 47 107 0 0 0 0 i\n" +"MouseMoveEvent 45 109 0 0 0 0 i\n" +"MouseMoveEvent 44 110 0 0 0 0 i\n" +"MouseMoveEvent 43 112 0 0 0 0 i\n" +"MouseMoveEvent 41 113 0 0 0 0 i\n" +"MouseMoveEvent 40 115 0 0 0 0 i\n" +"MouseMoveEvent 39 117 0 0 0 0 i\n" +"MouseMoveEvent 38 119 0 0 0 0 i\n" +"MouseMoveEvent 38 120 0 0 0 0 i\n" +"MouseMoveEvent 38 123 0 0 0 0 i\n" +"MouseMoveEvent 38 125 0 0 0 0 i\n" +"MouseMoveEvent 38 128 0 0 0 0 i\n" +"MouseMoveEvent 38 129 0 0 0 0 i\n" +"MouseMoveEvent 37 131 0 0 0 0 i\n" +"MouseMoveEvent 36 132 0 0 0 0 i\n" +"MouseMoveEvent 35 133 0 0 0 0 i\n" +"MouseMoveEvent 34 134 0 0 0 0 i\n" +"MouseMoveEvent 33 134 0 0 0 0 i\n" +"MouseMoveEvent 31 134 0 0 0 0 i\n" +"MouseMoveEvent 30 134 0 0 0 0 i\n" +"MouseMoveEvent 29 134 0 0 0 0 i\n" +"MouseMoveEvent 28 135 0 0 0 0 i\n" +"MouseMoveEvent 26 136 0 0 0 0 i\n" +"MouseMoveEvent 24 137 0 0 0 0 i\n" +"MouseMoveEvent 23 140 0 0 0 0 i\n" +"MouseMoveEvent 22 141 0 0 0 0 i\n" +"MouseMoveEvent 21 142 0 0 0 0 i\n" +"MouseMoveEvent 21 143 0 0 0 0 i\n" +"MouseMoveEvent 21 144 0 0 0 0 i\n" +"MouseMoveEvent 20 145 0 0 0 0 i\n" +"MouseMoveEvent 19 146 0 0 0 0 i\n" +"MouseMoveEvent 19 148 0 0 0 0 i\n" +"MouseMoveEvent 19 149 0 0 0 0 i\n" +"MouseMoveEvent 19 150 0 0 0 0 i\n" +"MouseMoveEvent 19 151 0 0 0 0 i\n" +"MouseMoveEvent 19 152 0 0 0 0 i\n" +"MouseMoveEvent 19 153 0 0 0 0 i\n" +"MouseMoveEvent 18 154 0 0 0 0 i\n" +"MouseMoveEvent 18 155 0 0 0 0 i\n" +"MouseMoveEvent 18 156 0 0 0 0 i\n" +"MouseMoveEvent 18 157 0 0 0 0 i\n" +"MouseMoveEvent 18 158 0 0 0 0 i\n" +"MouseMoveEvent 18 159 0 0 0 0 i\n" +"MouseMoveEvent 19 160 0 0 0 0 i\n" +"MouseMoveEvent 19 161 0 0 0 0 i\n" +"MouseMoveEvent 19 162 0 0 0 0 i\n" +"MouseMoveEvent 19 163 0 0 0 0 i\n" +"MouseMoveEvent 24 165 0 0 0 0 i\n" +"MouseMoveEvent 40 168 0 0 0 0 i\n" +"MouseMoveEvent 58 170 0 0 0 0 i\n" +"MouseMoveEvent 62 171 0 0 0 0 i\n" +"MouseMoveEvent 76 174 0 0 0 0 i\n" +"MouseMoveEvent 80 176 0 0 0 0 i\n" +"MouseMoveEvent 84 178 0 0 0 0 i\n" +"MouseMoveEvent 88 179 0 0 0 0 i\n" +"MouseMoveEvent 90 181 0 0 0 0 i\n" +"MouseMoveEvent 92 182 0 0 0 0 i\n" +"MouseMoveEvent 95 183 0 0 0 0 i\n" +"MouseMoveEvent 100 186 0 0 0 0 i\n" +"MouseMoveEvent 103 188 0 0 0 0 i\n" +"MouseMoveEvent 106 190 0 0 0 0 i\n" +"MouseMoveEvent 109 192 0 0 0 0 i\n" +"MouseMoveEvent 112 194 0 0 0 0 i\n" +"MouseMoveEvent 114 196 0 0 0 0 i\n" +"MouseMoveEvent 118 199 0 0 0 0 i\n" +"MouseMoveEvent 122 202 0 0 0 0 i\n" +"MouseMoveEvent 125 206 0 0 0 0 i\n" +"MouseMoveEvent 127 208 0 0 0 0 i\n" +"MouseMoveEvent 128 210 0 0 0 0 i\n" +"MouseMoveEvent 129 212 0 0 0 0 i\n" +"MouseMoveEvent 131 214 0 0 0 0 i\n" +"MouseMoveEvent 133 217 0 0 0 0 i\n" +"MouseMoveEvent 134 219 0 0 0 0 i\n" +"MouseMoveEvent 135 221 0 0 0 0 i\n" +"MouseMoveEvent 136 223 0 0 0 0 i\n" +"MouseMoveEvent 137 225 0 0 0 0 i\n" +"MouseMoveEvent 137 227 0 0 0 0 i\n" +"MouseMoveEvent 137 230 0 0 0 0 i\n" +"MouseMoveEvent 137 231 0 0 0 0 i\n" +"MouseMoveEvent 138 233 0 0 0 0 i\n" +"MouseMoveEvent 138 234 0 0 0 0 i\n" +"MouseMoveEvent 138 235 0 0 0 0 i\n" +"MouseMoveEvent 138 236 0 0 0 0 i\n" +"MouseMoveEvent 138 238 0 0 0 0 i\n" +"MouseMoveEvent 138 239 0 0 0 0 i\n" +"MouseMoveEvent 138 241 0 0 0 0 i\n" +"MouseMoveEvent 138 243 0 0 0 0 i\n" +"MouseMoveEvent 139 245 0 0 0 0 i\n" +"MouseMoveEvent 138 247 0 0 0 0 i\n" +"MouseMoveEvent 138 248 0 0 0 0 i\n" +"MouseMoveEvent 138 249 0 0 0 0 i\n" +"MouseMoveEvent 138 250 0 0 0 0 i\n" +"MouseMoveEvent 137 252 0 0 0 0 i\n" +"MouseMoveEvent 136 254 0 0 0 0 i\n" +"MouseMoveEvent 136 255 0 0 0 0 i\n" +"MouseMoveEvent 135 256 0 0 0 0 i\n" +"MouseMoveEvent 135 257 0 0 0 0 i\n" +"MouseMoveEvent 135 258 0 0 0 0 i\n" +"MouseMoveEvent 135 259 0 0 0 0 i\n" +"MouseMoveEvent 135 260 0 0 0 0 i\n" +"MouseMoveEvent 136 262 0 0 0 0 i\n" +"MouseMoveEvent 136 263 0 0 0 0 i\n" +"MouseMoveEvent 136 264 0 0 0 0 i\n" +"MouseMoveEvent 136 265 0 0 0 0 i\n" +"MouseMoveEvent 137 266 0 0 0 0 i\n" +"MouseMoveEvent 138 267 0 0 0 0 i\n" +"MouseMoveEvent 139 267 0 0 0 0 i\n" +"MouseMoveEvent 140 268 0 0 0 0 i\n" +"MouseMoveEvent 140 269 0 0 0 0 i\n" +"LeftButtonReleaseEvent 140 269 0 0 0 0 i\n" +"MouseMoveEvent 140 269 0 0 0 0 i\n" +"MouseMoveEvent 139 269 0 0 0 0 i\n" +"MouseMoveEvent 136 268 0 0 0 0 i\n" +"MouseMoveEvent 131 268 0 0 0 0 i\n" +"MouseMoveEvent 127 267 0 0 0 0 i\n" +"MouseMoveEvent 113 266 0 0 0 0 i\n" +"MouseMoveEvent 97 263 0 0 0 0 i\n" +"MouseMoveEvent 79 260 0 0 0 0 i\n" +"MouseMoveEvent 65 258 0 0 0 0 i\n" +"MouseMoveEvent 63 258 0 0 0 0 i\n" +"MouseMoveEvent 60 257 0 0 0 0 i\n" +"MouseMoveEvent 58 257 0 0 0 0 i\n" +"MouseMoveEvent 56 256 0 0 0 0 i\n" +"MouseMoveEvent 53 255 0 0 0 0 i\n" +"MouseMoveEvent 49 254 0 0 0 0 i\n" +"MouseMoveEvent 45 252 0 0 0 0 i\n" +"MouseMoveEvent 41 251 0 0 0 0 i\n" +"MouseMoveEvent 38 250 0 0 0 0 i\n" +"MouseMoveEvent 36 250 0 0 0 0 i\n" +"MouseMoveEvent 34 250 0 0 0 0 i\n" +"MouseMoveEvent 33 249 0 0 0 0 i\n" +"MouseMoveEvent 31 249 0 0 0 0 i\n" +"MouseMoveEvent 30 249 0 0 0 0 i\n" +"MouseMoveEvent 30 248 0 0 0 0 i\n" +"MouseMoveEvent 29 248 0 0 0 0 i\n" +"MouseMoveEvent 28 248 0 0 0 0 i\n" +"MouseMoveEvent 27 248 0 0 0 0 i\n" +"MouseMoveEvent 27 249 0 0 0 0 i\n" +"MouseMoveEvent 28 250 0 0 0 0 i\n" +"MouseMoveEvent 29 250 0 0 0 0 i\n" +"MouseMoveEvent 30 250 0 0 0 0 i\n" +"MouseMoveEvent 30 251 0 0 0 0 i\n" +"MouseMoveEvent 30 252 0 0 0 0 i\n" +"MouseMoveEvent 31 252 0 0 0 0 i\n" +"MouseMoveEvent 32 252 0 0 0 0 i\n" +"MouseMoveEvent 33 253 0 0 0 0 i\n" +"MouseMoveEvent 34 253 0 0 0 0 i\n" +"MouseMoveEvent 35 253 0 0 0 0 i\n" +"MouseMoveEvent 36 253 0 0 0 0 i\n" +"MouseMoveEvent 37 253 0 0 0 0 i\n" +"MouseMoveEvent 38 253 0 0 0 0 i\n" +"LeftButtonPressEvent 38 253 0 0 0 0 i\n" +"MouseMoveEvent 41 254 0 0 0 0 i\n" +"MouseMoveEvent 55 255 0 0 0 0 i\n" +"MouseMoveEvent 75 257 0 0 0 0 i\n" +"MouseMoveEvent 91 259 0 0 0 0 i\n" +"MouseMoveEvent 96 260 0 0 0 0 i\n" +"MouseMoveEvent 97 260 0 0 0 0 i\n" +"MouseMoveEvent 98 260 0 0 0 0 i\n" +"MouseMoveEvent 99 260 0 0 0 0 i\n" +"MouseMoveEvent 101 260 0 0 0 0 i\n" +"MouseMoveEvent 102 260 0 0 0 0 i\n" +"MouseMoveEvent 104 260 0 0 0 0 i\n" +"MouseMoveEvent 107 260 0 0 0 0 i\n" +"MouseMoveEvent 111 260 0 0 0 0 i\n" +"MouseMoveEvent 114 261 0 0 0 0 i\n" +"MouseMoveEvent 116 261 0 0 0 0 i\n" +"MouseMoveEvent 118 260 0 0 0 0 i\n" +"MouseMoveEvent 120 259 0 0 0 0 i\n" +"MouseMoveEvent 122 259 0 0 0 0 i\n" +"MouseMoveEvent 124 259 0 0 0 0 i\n" +"MouseMoveEvent 126 259 0 0 0 0 i\n" +"MouseMoveEvent 127 259 0 0 0 0 i\n" +"MouseMoveEvent 128 258 0 0 0 0 i\n" +"MouseMoveEvent 130 258 0 0 0 0 i\n" +"MouseMoveEvent 132 258 0 0 0 0 i\n" +"MouseMoveEvent 133 258 0 0 0 0 i\n" +"MouseMoveEvent 134 258 0 0 0 0 i\n" +"MouseMoveEvent 135 258 0 0 0 0 i\n" +"MouseMoveEvent 136 258 0 0 0 0 i\n" +"MouseMoveEvent 137 258 0 0 0 0 i\n" +"MouseMoveEvent 138 258 0 0 0 0 i\n" +"MouseMoveEvent 139 258 0 0 0 0 i\n" +"LeftButtonReleaseEvent 139 258 0 0 0 0 i\n" +"MouseMoveEvent 139 258 0 0 0 0 i\n" +"MouseMoveEvent 138 258 0 0 0 0 i\n" +"MouseMoveEvent 136 256 0 0 0 0 i\n" +"MouseMoveEvent 135 255 0 0 0 0 i\n" +"MouseMoveEvent 134 255 0 0 0 0 i\n" +"MouseMoveEvent 134 253 0 0 0 0 i\n" +"MouseMoveEvent 133 253 0 0 0 0 i\n" +"MouseMoveEvent 132 252 0 0 0 0 i\n" +"MouseMoveEvent 130 251 0 0 0 0 i\n" +"MouseMoveEvent 128 250 0 0 0 0 i\n" +"MouseMoveEvent 126 249 0 0 0 0 i\n" +"MouseMoveEvent 124 249 0 0 0 0 i\n" +"MouseMoveEvent 124 248 0 0 0 0 i\n" +"MouseMoveEvent 123 248 0 0 0 0 i\n" +"MouseMoveEvent 122 247 0 0 0 0 i\n" +"MouseMoveEvent 121 246 0 0 0 0 i\n" +"MouseMoveEvent 121 245 0 0 0 0 i\n" +"MouseMoveEvent 120 244 0 0 0 0 i\n" +"KeyPressEvent 120 244 0 0 105 1 i\n" +; + +int TestScalarBarWidget( int argc, char *argv[] ) +{ + char* fname = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combxyz.bin"); + char* fname2 = + vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/combq.bin"); + + // Start by loading some data. + vtkPLOT3DReader *pl3d = vtkPLOT3DReader::New(); + pl3d->SetXYZFileName(fname); + pl3d->SetQFileName(fname2); + pl3d->SetScalarFunctionNumber(100); + pl3d->SetVectorFunctionNumber(202); + pl3d->Update(); + + delete [] fname; + delete [] fname2; + + // An outline is shown for context. + vtkStructuredGridGeometryFilter *outline = + vtkStructuredGridGeometryFilter::New(); + outline->SetInputConnection(pl3d->GetOutputPort()); + outline->SetExtent(0,100,0,100,9,9); + + vtkPolyDataMapper *outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + + vtkActor *outlineActor = vtkActor::New(); + outlineActor->SetMapper(outlineMapper); + + // Create the RenderWindow, Renderer and both Actors + // + vtkRenderer *ren1 = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(ren1); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + vtkScalarBarWidget *scalarWidget = vtkScalarBarWidget::New(); + scalarWidget->SetInteractor(iren); + scalarWidget->GetScalarBarActor()->SetTitle("Temperature"); + scalarWidget->GetScalarBarActor()->SetLookupTable(outlineMapper->GetLookupTable()); + + ren1->AddActor(outlineActor); + + // Add the actors to the renderer, set the background and size + // + ren1->SetBackground(0.1, 0.2, 0.4); + renWin->SetSize(300, 300); + + // record events + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); +// recorder->SetFileName("c:/record.log"); +// recorder->Record(); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(TSBWeventLog); + + // render the image + iren->Initialize(); + renWin->Render(); + //scalarWidget->EnabledOn(); + recorder->Play(); + //recorder->EnabledOn(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + recorder->Off(); + recorder->Delete(); + scalarWidget->Delete(); + pl3d->Delete(); + outline->Delete(); + outlineMapper->Delete(); + outlineActor->Delete(); + iren->Delete(); + renWin->Delete(); + ren1->Delete(); + + return !retVal; +} diff --git a/Widgets/Testing/Cxx/TestSplineWidget.cxx b/Widgets/Testing/Cxx/TestSplineWidget.cxx new file mode 100644 index 0000000..daa1140 --- /dev/null +++ b/Widgets/Testing/Cxx/TestSplineWidget.cxx @@ -0,0 +1,398 @@ +#include "vtkActor.h" +#include "vtkCamera.h" +#include "vtkCommand.h" +#include "vtkImageData.h" +#include "vtkImagePlaneWidget.h" +#include "vtkInteractorEventRecorder.h" +#include "vtkKochanekSpline.h" +#include "vtkOutlineFilter.h" +#include "vtkParametricSpline.h" +#include "vtkPlaneSource.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProbeFilter.h" +#include "vtkProperty.h" +#include "vtkProperty2D.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSplineWidget.h" +#include "vtkTextProperty.h" +#include "vtkVolume16Reader.h" +#include "vtkXYPlotActor.h" + +#include "vtkTestUtilities.h" +#include "vtkRegressionTestImage.h" +#include "vtkDebugLeaks.h" + +char TSWeventLog[] = +"# StreamVersion 1\n" +"CharEvent 133 125 0 0 98 1 i\n" +"KeyReleaseEvent 133 125 0 0 98 1 i\n" +"MouseMoveEvent 133 125 0 0 0 0 i\n" +"RightButtonPressEvent 133 125 0 0 0 0 i\n" +"MouseMoveEvent 133 123 0 0 0 0 i\n" +"MouseMoveEvent 133 119 0 0 0 0 i\n" +"MouseMoveEvent 132 115 0 0 0 0 i\n" +"MouseMoveEvent 132 111 0 0 0 0 i\n" +"MouseMoveEvent 132 107 0 0 0 0 i\n" +"RightButtonReleaseEvent 132 107 0 0 0 0 i\n" +"MouseMoveEvent 132 129 0 0 0 0 i\n" +"LeftButtonPressEvent 132 129 0 0 0 0 i\n" +"MouseMoveEvent 132 130 0 0 0 0 i\n" +"MouseMoveEvent 132 135 0 0 0 0 i\n" +"MouseMoveEvent 132 143 0 0 0 0 i\n" +"MouseMoveEvent 131 152 0 0 0 0 i\n" +"MouseMoveEvent 130 159 0 0 0 0 i\n" +"MouseMoveEvent 129 165 0 0 0 0 i\n" +"MouseMoveEvent 127 170 0 0 0 0 i\n" +"MouseMoveEvent 125 176 0 0 0 0 i\n" +"MouseMoveEvent 124 181 0 0 0 0 i\n" +"MouseMoveEvent 122 183 0 0 0 0 i\n" +"LeftButtonReleaseEvent 122 183 0 0 0 0 i\n" +"MouseMoveEvent 133 163 0 0 0 0 i\n" +"MiddleButtonPressEvent 133 163 0 0 0 0 i\n" +"MouseMoveEvent 132 161 0 0 0 0 i\n" +"MouseMoveEvent 128 158 0 0 0 0 i\n" +"MouseMoveEvent 124 155 0 0 0 0 i\n" +"MouseMoveEvent 120 151 0 0 0 0 i\n" +"MouseMoveEvent 116 147 0 0 0 0 i\n" +"MouseMoveEvent 118 146 0 0 0 0 i\n" +"MouseMoveEvent 121 148 0 0 0 0 i\n" +"MouseMoveEvent 123 150 0 0 0 0 i\n" +"MouseMoveEvent 125 154 0 0 0 0 i\n" +"MouseMoveEvent 129 158 0 0 0 0 i\n" +"MouseMoveEvent 132 161 0 0 0 0 i\n" +"MouseMoveEvent 134 165 0 0 0 0 i\n" +"MouseMoveEvent 136 168 0 0 0 0 i\n" +"MiddleButtonReleaseEvent 136 168 0 0 0 0 i\n" +"MouseMoveEvent 178 186 0 0 0 0 i\n" +"KeyPressEvent 178 186 -128 0 0 1 Control_L\n" +"MiddleButtonPressEvent 178 186 8 0 0 0 Control_L\n" +"MouseMoveEvent 178 185 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 183 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 181 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 179 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 177 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 175 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 173 8 0 0 0 Control_L\n" +"MouseMoveEvent 179 171 8 0 0 0 Control_L\n" +"MouseMoveEvent 177 169 8 0 0 0 Control_L\n" +"MouseMoveEvent 176 167 8 0 0 0 Control_L\n" +"MouseMoveEvent 174 165 8 0 0 0 Control_L\n" +"MouseMoveEvent 172 164 8 0 0 0 Control_L\n" +"MouseMoveEvent 171 163 8 0 0 0 Control_L\n" +"MiddleButtonReleaseEvent 171 163 8 0 0 0 Control_L\n" +"KeyReleaseEvent 171 163 0 0 0 1 Control_L\n" +"MouseMoveEvent 170 167 0 0 0 0 Control_L\n" +"MiddleButtonPressEvent 170 167 0 0 0 0 Control_L\n" +"MouseMoveEvent 172 167 0 0 0 0 Control_L\n" +"MouseMoveEvent 176 167 0 0 0 0 Control_L\n" +"MouseMoveEvent 181 167 0 0 0 0 Control_L\n" +"MouseMoveEvent 188 167 0 0 0 0 Control_L\n" +"MouseMoveEvent 198 165 0 0 0 0 Control_L\n" +"MouseMoveEvent 205 163 0 0 0 0 Control_L\n" +"MouseMoveEvent 211 161 0 0 0 0 Control_L\n" +"MouseMoveEvent 216 160 0 0 0 0 Control_L\n" +"MouseMoveEvent 222 158 0 0 0 0 Control_L\n" +"MiddleButtonReleaseEvent 222 158 0 0 0 0 Control_L\n" +"MouseMoveEvent 230 158 0 0 0 0 Control_L\n" +"MiddleButtonPressEvent 230 158 0 0 0 0 Control_L\n" +"MouseMoveEvent 229 156 0 0 0 0 Control_L\n" +"MouseMoveEvent 228 153 0 0 0 0 Control_L\n" +"MouseMoveEvent 226 150 0 0 0 0 Control_L\n" +"MouseMoveEvent 224 148 0 0 0 0 Control_L\n" +"MouseMoveEvent 222 145 0 0 0 0 Control_L\n" +"MouseMoveEvent 220 141 0 0 0 0 Control_L\n" +"MouseMoveEvent 216 135 0 0 0 0 Control_L\n" +"MouseMoveEvent 214 129 0 0 0 0 Control_L\n" +"MouseMoveEvent 212 123 0 0 0 0 Control_L\n" +"MouseMoveEvent 209 118 0 0 0 0 Control_L\n" +"MouseMoveEvent 207 113 0 0 0 0 Control_L\n" +"MouseMoveEvent 204 109 0 0 0 0 Control_L\n" +"MouseMoveEvent 202 105 0 0 0 0 Control_L\n" +"MouseMoveEvent 200 103 0 0 0 0 Control_L\n" +"MouseMoveEvent 198 99 0 0 0 0 Control_L\n" +"MouseMoveEvent 196 97 0 0 0 0 Control_L\n" +"MouseMoveEvent 194 93 0 0 0 0 Control_L\n" +"MiddleButtonReleaseEvent 194 93 0 0 0 0 Control_L\n" +"MouseMoveEvent 254 98 0 0 0 0 Control_L\n" +"MiddleButtonPressEvent 254 98 0 0 0 0 Control_L\n" +"MouseMoveEvent 254 100 0 0 0 0 Control_L\n" +"MouseMoveEvent 254 104 0 0 0 0 Control_L\n" +"MouseMoveEvent 255 108 0 0 0 0 Control_L\n" +"MouseMoveEvent 255 112 0 0 0 0 Control_L\n" +"MouseMoveEvent 255 116 0 0 0 0 Control_L\n" +"MouseMoveEvent 255 120 0 0 0 0 Control_L\n" +"MouseMoveEvent 256 124 0 0 0 0 Control_L\n" +"MouseMoveEvent 257 128 0 0 0 0 Control_L\n" +"MouseMoveEvent 257 132 0 0 0 0 Control_L\n" +"MouseMoveEvent 257 136 0 0 0 0 Control_L\n" +"MouseMoveEvent 258 141 0 0 0 0 Control_L\n" +"MouseMoveEvent 258 146 0 0 0 0 Control_L\n" +"MouseMoveEvent 258 151 0 0 0 0 Control_L\n" +"MouseMoveEvent 258 157 0 0 0 0 Control_L\n" +"MouseMoveEvent 258 159 0 0 0 0 Control_L\n" +"MiddleButtonReleaseEvent 80 206 0 0 0 0 Control_L\n" +; + +// Callback for the image plane widget interaction +class vtkIPWCallback : public vtkCommand +{ +public: + static vtkIPWCallback *New() + { return new vtkIPWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkImagePlaneWidget *planeWidget = reinterpret_cast<vtkImagePlaneWidget*>(caller); + if(planeWidget->GetPlaneOrientation() == 3) + { + Spline->SetProjectionPosition(0); + } + else + { + Spline->SetProjectionPosition(planeWidget->GetSlicePosition()); + } + Spline->GetPolyData(Poly); + } + vtkIPWCallback():Spline(0),Poly(0){}; + vtkSplineWidget* Spline; + vtkPolyData* Poly; +}; + +// Callback for the spline widget interaction +class vtkSWCallback : public vtkCommand +{ +public: + static vtkSWCallback *New() + { return new vtkSWCallback; } + virtual void Execute(vtkObject *caller, unsigned long, void*) + { + vtkSplineWidget *spline = reinterpret_cast<vtkSplineWidget*>(caller); + spline->GetPolyData(Poly); + } + vtkSWCallback():Poly(0){}; + vtkPolyData* Poly; +}; + +int TestSplineWidget( int argc, char *argv[] ) +{ + char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter"); + + vtkVolume16Reader* v16 = vtkVolume16Reader::New(); + v16->SetDataDimensions( 64, 64); + v16->SetDataByteOrderToLittleEndian(); + v16->SetImageRange( 1, 93); + v16->SetDataSpacing( 3.2, 3.2, 1.5); + v16->SetFilePrefix( fname); + v16->SetDataMask( 0x7fff); + v16->Update(); + + delete[] fname; + + vtkRenderer* ren1 = vtkRenderer::New(); + vtkRenderer* ren2 = vtkRenderer::New(); + vtkRenderWindow* renWin = vtkRenderWindow::New(); + renWin->AddRenderer( ren1); + renWin->AddRenderer( ren2); + vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow( renWin); + + vtkOutlineFilter* outline = vtkOutlineFilter::New(); + outline->SetInputConnection(v16->GetOutputPort()); + + vtkPolyDataMapper* outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInputConnection(outline->GetOutputPort()); + + vtkActor* outlineActor = vtkActor::New(); + outlineActor->SetMapper(outlineMapper); + + vtkImagePlaneWidget* ipw = vtkImagePlaneWidget::New(); + ipw->DisplayTextOn(); + ipw->TextureInterpolateOff(); + ipw->UserControlledLookupTableOff(); + ipw->SetInput(v16->GetOutput()); + ipw->KeyPressActivationOn(); + ipw->SetKeyPressActivationValue('x'); + ipw->SetResliceInterpolateToNearestNeighbour(); + ipw->SetInteractor(iren); + ipw->SetPlaneOrientationToXAxes(); + ipw->SetSliceIndex(32); + ipw->GetPlaneProperty()->SetColor(1,0,0); + + vtkSplineWidget* spline = vtkSplineWidget::New(); + spline->SetInteractor( iren); + spline->SetInput(v16->GetOutput()); + spline->SetPriority(1.0); + spline->KeyPressActivationOff(); + spline->PlaceWidget(); + spline->ProjectToPlaneOn(); + spline->SetProjectionNormal(0); + spline->SetProjectionPosition(102.4); //initial plane oriented position + spline->SetProjectionNormal(3); //allow arbitrary oblique orientations + spline->SetPlaneSource((vtkPlaneSource*)ipw->GetPolyDataAlgorithm()); + + + // Specify the type of spline (change from default vtkCardinalSpline) + vtkKochanekSpline* xspline = vtkKochanekSpline::New(); + vtkKochanekSpline* yspline = vtkKochanekSpline::New(); + vtkKochanekSpline* zspline = vtkKochanekSpline::New(); + + vtkParametricSpline* para = spline->GetParametricSpline(); + + para->SetXSpline(xspline); + para->SetYSpline(yspline); + para->SetZSpline(zspline); + + xspline->Delete(); + yspline->Delete(); + zspline->Delete(); + + vtkPolyData* poly = vtkPolyData::New(); + spline->GetPolyData(poly); + + vtkProbeFilter* probe = vtkProbeFilter::New(); + probe->SetInput(poly); + probe->SetSource(v16->GetOutput()); + + vtkIPWCallback* ipwcb = vtkIPWCallback::New(); + ipwcb->Spline = spline; + ipwcb->Poly = poly; + + ipw->AddObserver(vtkCommand::InteractionEvent,ipwcb); + + vtkSWCallback* swcb = vtkSWCallback::New(); + swcb->Poly = poly; + + spline->AddObserver(vtkCommand::InteractionEvent,swcb); + + vtkImageData* data = v16->GetOutput(); + double* range = data->GetPointData()->GetScalars()->GetRange(); + + vtkXYPlotActor* profile = vtkXYPlotActor::New(); + profile->AddInput(probe->GetOutput()); + profile->GetPositionCoordinate()->SetValue( 0.05, 0.05, 0); + profile->GetPosition2Coordinate()->SetValue( 0.95, 0.95, 0); + profile->SetXValuesToNormalizedArcLength(); + profile->SetNumberOfXLabels( 6); + profile->SetTitle( "Profile Data "); + profile->SetXTitle( "s"); + profile->SetYTitle( "I(s)"); + profile->SetXRange( 0, 1); + profile->SetYRange( range[0], range[1]); + profile->GetProperty()->SetColor( 0, 0, 0); + profile->GetProperty()->SetLineWidth( 2); + profile->SetLabelFormat("%g"); + vtkTextProperty* tprop = profile->GetTitleTextProperty(); + tprop->SetColor(0.02,0.06,0.62); + tprop->SetFontFamilyToArial(); + profile->SetAxisTitleTextProperty(tprop); + profile->SetAxisLabelTextProperty(tprop); + profile->SetTitleTextProperty(tprop); + + ren1->SetBackground( 0.1, 0.2, 0.4); + ren1->SetViewport( 0, 0, 0.5, 1); + ren1->AddActor(outlineActor); + + ren2->SetBackground( 1, 1, 1); + ren2->SetViewport( 0.5, 0, 1, 1); + ren2->AddActor2D( profile); + + renWin->SetSize( 600, 300); + + ipw->On(); + ipw->SetInteraction(0); + ipw->SetInteraction(1); + spline->On(); + spline->SetNumberOfHandles(4); + spline->SetNumberOfHandles(5); + spline->SetResolution(399); + + // Set up an interesting viewpoint + vtkCamera* camera = ren1->GetActiveCamera(); + camera->Elevation(110); + camera->SetViewUp(0, 0, -1); + camera->Azimuth(45); + camera->SetFocalPoint(100.8,100.8,69); + camera->SetPosition(560.949, 560.949, -167.853); + ren1->ResetCameraClippingRange(); + + // Position the actors +// renWin->Render(); +// iren->SetEventPosition(200,200); +// iren->SetKeyCode('r'); +// iren->InvokeEvent(vtkCommand::CharEvent,NULL); +// ren1->ResetCameraClippingRange(); +// renWin->Render(); +// iren->SetKeyCode('t'); +// iren->InvokeEvent(vtkCommand::CharEvent,NULL); + + // Playback recorded events + vtkInteractorEventRecorder *recorder = vtkInteractorEventRecorder::New(); + recorder->SetInteractor(iren); + recorder->ReadFromInputStringOn(); + recorder->SetInputString(TSWeventLog); + + // Test On Off mechanism + ipw->SetEnabled(0); + spline->EnabledOff(); + ipw->SetEnabled(1); + spline->EnabledOn(); + + // Test Set Get handle positions + double pos[3]; + int i; + for(i=0;i<spline->GetNumberOfHandles();i++) + { + spline->GetHandlePosition(i,pos); + spline->SetHandlePosition(i,pos); + } + + // Test Closed On Off + spline->ClosedOn(); + spline->ClosedOff(); + + // Render the image + iren->Initialize(); + renWin->Render(); + //ren1->ResetCamera(); + recorder->Play(); + + // Remove the observers so we can go interactive. Without this the "-I" + // testing option fails. + recorder->Off(); + + int retVal = vtkRegressionTestImage( renWin ); + if ( retVal == vtkRegressionTester::DO_INTERACTOR) + { + iren->Start(); + } + + // Clean up + recorder->Off(); + recorder->Delete(); + + outlineActor->Delete(); + outlineMapper->Delete(); + outline->Delete(); + renWin->Delete(); + ren1->Delete(); + ren2->Delete(); + iren->Delete(); + + ipw->RemoveObserver(ipwcb); + ipw->Delete(); + ipwcb->Delete(); + spline->RemoveObserver(swcb); + spline->Delete(); + swcb->Delete(); + poly->Delete(); + probe->Delete(); + profile->Delete(); + v16->Delete(); + + return !retVal; +} + + diff --git a/Widgets/Testing/Python/CMakeLists.txt b/Widgets/Testing/Python/CMakeLists.txt new file mode 100644 index 0000000..a4b2063 --- /dev/null +++ b/Widgets/Testing/Python/CMakeLists.txt @@ -0,0 +1,16 @@ +# +# Add tests, with the data +# +IF (VTK_PYTHON_EXE AND VTK_USE_RENDERING AND VTK_DATA_ROOT AND + VTK_USE_DISPLAY) + FOREACH ( tfile + TestImagePlaneWidget + ) + ADD_TEST(${tfile}Python-image ${VTK_PYTHON_EXE} + ${VTK_SOURCE_DIR}/Widgets/Testing/Python/${tfile}.py + -D ${VTK_DATA_ROOT} + -B ${VTK_DATA_ROOT}/Baseline/Widgets + ) + ENDFOREACH( tfile ) +ENDIF (VTK_PYTHON_EXE AND VTK_USE_RENDERING AND VTK_DATA_ROOT AND + VTK_USE_DISPLAY) diff --git a/Widgets/Testing/Python/TestImagePlaneWidget.py b/Widgets/Testing/Python/TestImagePlaneWidget.py new file mode 100644 index 0000000..4db9106 --- /dev/null +++ b/Widgets/Testing/Python/TestImagePlaneWidget.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python + +# Run this test like so: +# $ vtkpython TestImagePlaneWidget.py -D $VTK_DATA_ROOT \ +# -B $VTK_DATA_ROOT/Baseline/Widgets/ +# +# $ vtkpython TestImagePlaneWidget.py --help +# provides more details on other options. + +import os +import os.path +import vtk +from vtk.test import Testing + +class TestImagePlaneWidget(Testing.vtkTest): + def testBug(self): + # Uncomment the next line if you want to run this via + # `gdb python`. + #raw_input('Hit Ctrl-C') + + # Load some data. + v16 = vtk.vtkVolume16Reader() + v16.SetDataDimensions(64, 64) + v16.SetDataByteOrderToLittleEndian() + v16.SetFilePrefix(os.path.join(Testing.VTK_DATA_ROOT, + "Data", "headsq", "quarter")) + v16.SetImageRange(1, 93) + v16.SetDataSpacing(3.2, 3.2, 1.5) + v16.Update() + + xMin, xMax, yMin, yMax, zMin, zMax = v16.GetOutput().GetWholeExtent() + img_data = v16.GetOutput() + + # ************************************************** + # Look here for wierdness. + + # Lets create this data using the data from the reader. + my_img_data = vtk.vtkImageData() + my_img_data.SetDimensions(img_data.GetDimensions()) + my_img_data.SetWholeExtent(img_data.GetWholeExtent()) + my_img_data.SetExtent(img_data.GetExtent()) + my_img_data.SetUpdateExtent(img_data.GetUpdateExtent()) + my_img_data.SetSpacing(img_data.GetSpacing()) + my_img_data.SetOrigin(img_data.GetOrigin()) + my_img_data.SetScalarType(img_data.GetScalarType()) + my_img_data.GetPointData().SetScalars(img_data.GetPointData().GetScalars()) + my_img_data.Update() + # hang on to original image data. + orig_img_data = img_data + + # hijack img_data with our own. If you comment this out everything is + # fine. + img_data = my_img_data + # ************************************************** + + spacing = img_data.GetSpacing() + sx, sy, sz = spacing + + origin = img_data.GetOrigin() + ox, oy, oz = origin + + # An outline is shown for context. + outline = vtk.vtkOutlineFilter() + outline.SetInput(img_data) + + outlineMapper = vtk.vtkPolyDataMapper() + outlineMapper.SetInputConnection(outline.GetOutputPort()) + + outlineActor = vtk.vtkActor() + outlineActor.SetMapper(outlineMapper) + + # The shared picker enables us to use 3 planes at one time + # and gets the picking order right + picker = vtk.vtkCellPicker() + picker.SetTolerance(0.005) + + # The 3 image plane widgets are used to probe the dataset. + planeWidgetX = vtk.vtkImagePlaneWidget() + planeWidgetX.DisplayTextOn() + planeWidgetX.SetInput(img_data) + planeWidgetX.SetPlaneOrientationToXAxes() + planeWidgetX.SetSliceIndex(32) + planeWidgetX.SetPicker(picker) + planeWidgetX.SetKeyPressActivationValue("x") + prop1 = planeWidgetX.GetPlaneProperty() + prop1.SetColor(1, 0, 0) + + planeWidgetY = vtk.vtkImagePlaneWidget() + planeWidgetY.DisplayTextOn() + planeWidgetY.SetInput(img_data) + planeWidgetY.SetPlaneOrientationToYAxes() + planeWidgetY.SetSliceIndex(32) + planeWidgetY.SetPicker(picker) + planeWidgetY.SetKeyPressActivationValue("y") + prop2 = planeWidgetY.GetPlaneProperty() + prop2.SetColor(1, 1, 0) + planeWidgetY.SetLookupTable(planeWidgetX.GetLookupTable()) + + # for the z-slice, turn off texture interpolation: + # interpolation is now nearest neighbour, to demonstrate + # cross-hair cursor snapping to pixel centers + planeWidgetZ = vtk.vtkImagePlaneWidget() + planeWidgetZ.DisplayTextOn() + planeWidgetZ.SetInput(img_data) + planeWidgetZ.SetPlaneOrientationToZAxes() + planeWidgetZ.SetSliceIndex(46) + planeWidgetZ.SetPicker(picker) + planeWidgetZ.SetKeyPressActivationValue("z") + prop3 = planeWidgetZ.GetPlaneProperty() + prop3.SetColor(0, 0, 1) + planeWidgetZ.SetLookupTable(planeWidgetX.GetLookupTable()) + + # Create the RenderWindow and Renderer + ren = vtk.vtkRenderer() + renWin = vtk.vtkRenderWindow() + renWin.AddRenderer(ren) + + # Add the outline actor to the renderer, set the background + # color and size + ren.AddActor(outlineActor) + renWin.SetSize(600, 600) + ren.SetBackground(0.1, 0.1, 0.2) + + current_widget = planeWidgetZ + mode_widget = planeWidgetZ + + # Set the interactor for the widgets + iact = vtk.vtkRenderWindowInteractor() + iact.SetRenderWindow(renWin) + planeWidgetX.SetInteractor(iact) + planeWidgetX.On() + planeWidgetY.SetInteractor(iact) + planeWidgetY.On() + planeWidgetZ.SetInteractor(iact) + planeWidgetZ.On() + + # Create an initial interesting view + ren.ResetCamera(); + cam1 = ren.GetActiveCamera() + cam1.Elevation(110) + cam1.SetViewUp(0, 0, -1) + cam1.Azimuth(45) + ren.ResetCameraClippingRange() + + iact.Initialize() + renWin.Render() + + # Compare the images and test. + img_file = "TestImagePlaneWidget.png" + Testing.compareImage(renWin, Testing.getAbsImagePath(img_file)) + # Interact if necessary. + if Testing.isInteractive(): + iact.Start() + +if __name__ == "__main__": + Testing.main([(TestImagePlaneWidget, 'test')]) diff --git a/Widgets/Testing/Tcl/CMakeLists.txt b/Widgets/Testing/Tcl/CMakeLists.txt new file mode 100644 index 0000000..6a3ab40 --- /dev/null +++ b/Widgets/Testing/Tcl/CMakeLists.txt @@ -0,0 +1,42 @@ +IF (VTK_USE_RENDERING) + + # + # Add tests, with the data + # + IF (VTK_DATA_ROOT) + FOREACH ( tfile + TestInteractorEventRecorder + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Widgets/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -V Baseline/Widgets/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + # + # If we do not have the data, still run the tests that we can + # + ELSE (VTK_DATA_ROOT) + FOREACH ( tfile + ) + ADD_TEST(${tfile}-image ${VTK_EXECUTABLE} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl + ${VTK_SOURCE_DIR}/Widgets/Testing/Tcl/${tfile}.tcl + -D ${VTK_DATA_ROOT} + -T ${VTK_BINARY_DIR}/Testing/Temporary + -V Baseline/Widgets/${tfile}.png + -A ${VTK_SOURCE_DIR}/Wrapping/Tcl) + ENDFOREACH( tfile ) + ENDIF (VTK_DATA_ROOT) + +ENDIF (VTK_USE_RENDERING) + +ADD_TEST(PrintSelf-Widgets ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl + ${VTK_SOURCE_DIR}/Widgets) + +ADD_TEST(TestSetObjectMacro-Widgets ${TCL_TCLSH} + ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl + "${VTK_SOURCE_DIR}/Widgets/vtk\\\\*.h" + "vtkSetObjectMacro") diff --git a/Widgets/Testing/Tcl/TestBoxWidget.tcl b/Widgets/Testing/Tcl/TestBoxWidget.tcl new file mode 100644 index 0000000..48df7f9 --- /dev/null +++ b/Widgets/Testing/Tcl/TestBoxWidget.tcl @@ -0,0 +1,75 @@ +package require vtk +package require vtkinteraction + +# Demonstrate how to use the vtkBoxWidget. +# This script uses a 3D box widget to define a "clipping box" to clip some +# simple geometry (a mace). Make sure that you hit the "W" key to activate the widget. + +# create a sphere source +# +vtkSphereSource sphere +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 +vtkAppendPolyData apd + apd AddInput [glyph GetOutput] + apd AddInput [sphere GetOutput] +vtkPolyDataMapper maceMapper + maceMapper SetInputConnection [apd GetOutputPort] +vtkLODActor maceActor + maceActor SetMapper maceMapper + maceActor VisibilityOn + +vtkPlanes planes +vtkClipPolyData clipper + clipper SetInputConnection [apd GetOutputPort] + clipper SetClipFunction planes + clipper InsideOutOn +vtkPolyDataMapper selectMapper + selectMapper SetInputConnection [clipper GetOutputPort] +vtkLODActor selectActor + selectActor SetMapper selectMapper + [selectActor GetProperty] SetColor 0 1 0 + selectActor VisibilityOff + selectActor SetScale 1.01 1.01 1.01 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin +vtkBoxWidget boxWidget + boxWidget SetInteractor iren + +ren1 AddActor maceActor +ren1 AddActor selectActor + +# Add the actors to the renderer, set the background and size +# +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# place the interactor initially +boxWidget SetInputConnection [glyph GetOutputPort] +boxWidget PlaceWidget +boxWidget AddObserver EndInteractionEvent SelectPolygons + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +proc SelectPolygons {} { + boxWidget GetPlanes planes + selectActor VisibilityOn +} diff --git a/Widgets/Testing/Tcl/TestInteractorEventRecorder.tcl b/Widgets/Testing/Tcl/TestInteractorEventRecorder.tcl new file mode 100644 index 0000000..94083b1 --- /dev/null +++ b/Widgets/Testing/Tcl/TestInteractorEventRecorder.tcl @@ -0,0 +1,99 @@ +package require vtk +package require vtkinteraction + +# Demonstrate how to use the vtkInteractorEventRecorder to play back some +# events. + +# Create a mace out of filters. +# +vtkSphereSource sphere +vtkConeSource cone +vtkGlyph3D glyph + glyph SetInputConnection [sphere GetOutputPort] + glyph SetSource [cone GetOutput] + glyph SetVectorModeToUseNormal + glyph SetScaleModeToScaleByVector + glyph SetScaleFactor 0.25 + +# The sphere and spikes are appended into a single polydata. This just makes things +# simpler to manage. +vtkAppendPolyData apd + apd AddInput [glyph GetOutput] + apd AddInput [sphere GetOutput] +vtkPolyDataMapper maceMapper + maceMapper SetInputConnection [apd GetOutputPort] +vtkLODActor maceActor + maceActor SetMapper maceMapper + maceActor VisibilityOn + +# This portion of the code clips the mace with the vtkPlanes implicit function. +# The clipped region is colored green. +vtkPlanes planes +vtkClipPolyData clipper + clipper SetInputConnection [apd GetOutputPort] + clipper SetClipFunction planes + clipper InsideOutOn +vtkPolyDataMapper selectMapper + selectMapper SetInputConnection [clipper GetOutputPort] +vtkLODActor selectActor + selectActor SetMapper selectMapper + [selectActor GetProperty] SetColor 0 1 0 + selectActor VisibilityOff + selectActor SetScale 1.01 1.01 1.01 + +# Create the RenderWindow, Renderer and both Actors +# +vtkRenderer ren1 +vtkRenderWindow renWin + renWin AddRenderer ren1 + +vtkRenderWindowInteractor iren + iren SetRenderWindow renWin + iren AddObserver ExitEvent {exit} + +# The SetInteractor method is how 3D widgets are associated with the render +# window interactor. Internally, SetInteractor sets up a bunch of callbacks +# using the Command/Observer mechanism (AddObserver()). +vtkBoxWidget boxWidget + boxWidget SetInteractor iren + boxWidget SetPlaceFactor 1.25 + +ren1 AddActor maceActor +ren1 AddActor selectActor + +# Add the actors to the renderer, set the background and size +# +ren1 SetBackground 0.1 0.2 0.4 +renWin SetSize 300 300 + +# Place the interactor initially. The input to a 3D widget is used to +# initially position and scale the widget. The EndInteractionEvent is +# observed which invokes the SelectPolygons callback. +boxWidget SetInputConnection [glyph GetOutputPort] +boxWidget PlaceWidget +boxWidget AddObserver EndInteractionEvent SelectPolygons + +# record events +vtkInteractorEventRecorder recorder +recorder SetInteractor iren +recorder SetFileName "$VTK_DATA_ROOT/Data/EventRecording.log" + +# render the image +# +iren AddObserver UserEvent {wm deiconify .vtkInteract} +iren Initialize +#recorder Record + +# prevent the tk window from showing up then start the event loop +wm withdraw . + +# This does the actual work: updates the vtkPlanes implicit function. +# This in turn causes the pipeline to update. +proc SelectPolygons {} { + boxWidget GetPlanes planes + selectActor VisibilityOn +} + +recorder Play +recorder Off +set threshold 15 diff --git a/Widgets/vtk3DWidget.cxx b/Widgets/vtk3DWidget.cxx new file mode 100644 index 0000000..efbfd5f --- /dev/null +++ b/Widgets/vtk3DWidget.cxx @@ -0,0 +1,169 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk3DWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtk3DWidget.h" + +#include "vtkCallbackCommand.h" +#include "vtkObjectFactory.h" +#include "vtkProp3D.h" +#include "vtkDataSet.h" +#include "vtkCamera.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" + +vtkCxxRevisionMacro(vtk3DWidget, "$Revision: 1.1 $"); + +vtkCxxSetObjectMacro(vtk3DWidget,Prop3D,vtkProp3D); +vtkCxxSetObjectMacro(vtk3DWidget,Input,vtkDataSet); +vtk3DWidget::vtk3DWidget() +{ + this->Placed = 0; + this->Prop3D = NULL; + this->Input = NULL; + this->PlaceFactor = 0.5; + + this->Priority = 0.5; + + this->HandleSize = 0.01; + this->ValidPick = 0; +} + +vtk3DWidget::~vtk3DWidget() +{ + if ( this->Input ) + { + this->Input->Delete(); + this->Input = NULL; + } + if ( this->Prop3D ) + { + this->Prop3D->Delete(); + this->Prop3D = NULL; + } +} + +void vtk3DWidget::PlaceWidget() +{ + double bounds[6]; + + if ( this->Prop3D ) + { + this->Prop3D->GetBounds(bounds); + } + else if ( this->Input ) + { + this->Input->Update(); + this->Input->GetBounds(bounds); + } + else + { + vtkErrorMacro(<<"No input or prop defined for widget placement"); + bounds[0] = -1.0; + bounds[1] = 1.0; + bounds[2] = -1.0; + bounds[3] = 1.0; + bounds[4] = -1.0; + bounds[5] = 1.0; + } + + this->PlaceWidget(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]); +} + +void vtk3DWidget::PlaceWidget(double xmin, double xmax, + double ymin, double ymax, + double zmin, double zmax) +{ + double bounds[6]; + + bounds[0] = xmin; + bounds[1] = xmax; + bounds[2] = ymin; + bounds[3] = ymax; + bounds[4] = zmin; + bounds[5] = zmax; + + this->PlaceWidget(bounds); + this->InvokeEvent(vtkCommand::PlaceWidgetEvent,NULL); + this->Placed = 1; +} + +void vtk3DWidget::AdjustBounds(double bounds[6], + double newBounds[6], double center[3]) +{ + center[0] = (bounds[0] + bounds[1])/2.0; + center[1] = (bounds[2] + bounds[3])/2.0; + center[2] = (bounds[4] + bounds[5])/2.0; + + newBounds[0] = center[0] + this->PlaceFactor*(bounds[0]-center[0]); + newBounds[1] = center[0] + this->PlaceFactor*(bounds[1]-center[0]); + newBounds[2] = center[1] + this->PlaceFactor*(bounds[2]-center[1]); + newBounds[3] = center[1] + this->PlaceFactor*(bounds[3]-center[1]); + newBounds[4] = center[2] + this->PlaceFactor*(bounds[4]-center[2]); + newBounds[5] = center[2] + this->PlaceFactor*(bounds[5]-center[2]); +} + +double vtk3DWidget::SizeHandles(double factor) +{ + int i; + vtkRenderer *renderer; + + if ( !this->ValidPick || !(renderer=this->CurrentRenderer) || + !renderer->GetActiveCamera() ) + { + return (this->HandleSize * factor * this->InitialLength); + } + else + { + double radius, z; + double windowLowerLeft[4], windowUpperRight[4]; + double *viewport = renderer->GetViewport(); + int *winSize = renderer->GetRenderWindow()->GetSize(); + double focalPoint[4]; + + this->ComputeWorldToDisplay(this->LastPickPosition[0], + this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + + double x = winSize[0] * viewport[0]; + double y = winSize[1] * viewport[1]; + this->ComputeDisplayToWorld(x,y,z,windowLowerLeft); + + x = winSize[0] * viewport[2]; + y = winSize[1] * viewport[3]; + this->ComputeDisplayToWorld(x,y,z,windowUpperRight); + + for (radius=0.0, i=0; i<3; i++) + { + radius += (windowUpperRight[i] - windowLowerLeft[i]) * + (windowUpperRight[i] - windowLowerLeft[i]); + } + + return (sqrt(radius) * factor * this->HandleSize); + } +} + + +void vtk3DWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Prop3D: " << this->Prop3D << "\n"; + os << indent << "Input: " << this->Input << "\n"; + os << indent << "Handle Size: " << this->HandleSize << "\n"; + os << indent << "Place Factor: " << this->PlaceFactor << "\n"; + +} + + diff --git a/Widgets/vtk3DWidget.h b/Widgets/vtk3DWidget.h new file mode 100644 index 0000000..c0bf60e --- /dev/null +++ b/Widgets/vtk3DWidget.h @@ -0,0 +1,141 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtk3DWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtk3DWidget - an abstract superclass for 3D widgets +// .SECTION Description +// vtk3DWidget is an abstract superclass for 3D interactor observers. These +// 3D widgets represent themselves in the scene, and have special callbacks +// associated with them that allows interactive manipulation of the widget. +// Inparticular, the difference between a vtk3DWidget and its abstract +// superclass vtkInteractorObserver is that vtk3DWidgets are "placed" in 3D +// space. vtkInteractorObservers have no notion of where they are placed, +// and may not exist in 3D space at all. 3D widgets also provide auxiliary +// functions like producing a transformation, creating polydata (for seeding +// streamlines, probes, etc.) or creating implicit functions. See the +// concrete subclasses for particulars. +// +// Typically the widget is used by specifying a vtkProp3D or VTK dataset as +// input, and then invoking the "On" method to activate it. (You can also +// specify a bounding box to help position the widget.) Prior to invoking the +// On() method, the user may also wish to use the PlaceWidget() to initially +// position it. The 'i' (for "interactor") keypresses also can be used to +// turn the widgets on and off (methods exist to change the key value +// and enable keypress activiation). +// +// To support interactive manipulation of objects, this class (and +// subclasses) invoke the events StartInteractionEvent, InteractionEvent, and +// EndInteractionEvent. These events are invoked when the vtk3DWidget enters +// a state where rapid response is desired: mouse motion, etc. The events can +// be used, for example, to set the desired update frame rate +// (StartInteractionEvent), operate on the vtkProp3D or other object +// (InteractionEvent), and set the desired frame rate back to normal values +// (EndInteractionEvent). +// +// Note that the Priority attribute inherited from vtkInteractorObserver has +// a new default value which is now 0.5 so that all 3D widgets have a higher +// priority than the usual interactor styles. +// +// .SECTION See Also +// vtkBoxWidget vtkPlaneWidget vtkLineWidget vtkPointWidget +// vtkSphereWidget vtkImplicitPlaneWidget + +#ifndef __vtk3DWidget_h +#define __vtk3DWidget_h + +#include "vtkInteractorObserver.h" + +class vtkDataSet; +class vtkProp3D; + +class VTK_WIDGETS_EXPORT vtk3DWidget : public vtkInteractorObserver +{ +public: + vtkTypeRevisionMacro(vtk3DWidget,vtkInteractorObserver); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // This method is used to initially place the widget. The placement of the + // widget depends on whether a Prop3D or input dataset is provided. If one + // of these two is provided, they will be used to obtain a bounding box, + // around which the widget is placed. Otherwise, you can manually specify a + // bounds with the PlaceWidget(bounds) method. Note: PlaceWidget(bounds) + // is required by all subclasses; the other methods are provided as + // convenience methods. + virtual void PlaceWidget(double bounds[6]) = 0; + virtual void PlaceWidget(); + virtual void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax); + + // Description: + // Specify a vtkProp3D around which to place the widget. This + // is not required, but if supplied, it is used to initially + // position the widget. + virtual void SetProp3D(vtkProp3D*); + vtkGetObjectMacro(Prop3D,vtkProp3D); + + // Description: + // Specify the input dataset. This is not required, but if supplied, + // and no vtkProp3D is specified, it is used to initially position + // the widget. + virtual void SetInput(vtkDataSet*); + vtkGetObjectMacro(Input,vtkDataSet); + + // Description: + // Set/Get a factor representing the scaling of the widget upon placement + // (via the PlaceWidget() method). Normally the widget is placed so that + // it just fits within the bounding box defined in PlaceWidget(bounds). + // The PlaceFactor will make the widget larger (PlaceFactor > 1) or smaller + // (PlaceFactor < 1). By default, PlaceFactor is set to 0.5. + vtkSetClampMacro(PlaceFactor,double,0.01,VTK_FLOAT_MAX); + vtkGetMacro(PlaceFactor,double); + + // Description: + // Set/Get the factor that controls the size of the handles that + // appear as part of the widget. These handles (like spheres, etc.) + // are used to manipulate the widget, and are sized as a fraction of + // the screen diagonal. + vtkSetClampMacro(HandleSize,double,0.001,0.5); + vtkGetMacro(HandleSize,double); + +protected: + vtk3DWidget(); + ~vtk3DWidget(); + + // Used to position and scale the widget initially + vtkProp3D *Prop3D; + vtkDataSet *Input; + + //has the widget ever been placed + double PlaceFactor; + int Placed; + void AdjustBounds(double bounds[6], double newBounds[6], double center[3]); + + //control the size of handles (if there are any) + double InitialBounds[6]; + double InitialLength; + double HandleSize; + double SizeHandles(double factor); + virtual void SizeHandles() {}//subclass in turn invokes parent's SizeHandles() + + //used to track the depth of the last pick; also interacts with handle sizing + int ValidPick; + double LastPickPosition[3]; + +private: + vtk3DWidget(const vtk3DWidget&); // Not implemented. + void operator=(const vtk3DWidget&); // Not implemented. + +}; + +#endif diff --git a/Widgets/vtkBoxWidget.cxx b/Widgets/vtkBoxWidget.cxx new file mode 100644 index 0000000..9495ae4 --- /dev/null +++ b/Widgets/vtkBoxWidget.cxx @@ -0,0 +1,1426 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBoxWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkBoxWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkCellPicker.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlanes.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkBoxWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkBoxWidget); + +vtkBoxWidget::vtkBoxWidget() +{ + this->State = vtkBoxWidget::Start; + this->EventCallbackCommand->SetCallback(vtkBoxWidget::ProcessEvents); + + // Enable/disable the translation, rotation, and scaling of the widget + this->TranslationEnabled = 1; + this->RotationEnabled = 1; + this->ScalingEnabled = 1; + + //Build the representation of the widget + int i; + + // Control orientation of normals + this->InsideOut = 0; + this->OutlineFaceWires = 0; + this->OutlineCursorWires = 1; + + // Construct the poly data representing the hex + this->HexPolyData = vtkPolyData::New(); + this->HexMapper = vtkPolyDataMapper::New(); + this->HexMapper->SetInput(HexPolyData); + this->HexActor = vtkActor::New(); + this->HexActor->SetMapper(this->HexMapper); + + // Construct initial points + this->Points = vtkPoints::New(VTK_DOUBLE); + this->Points->SetNumberOfPoints(15);//8 corners; 6 faces; 1 center + this->HexPolyData->SetPoints(this->Points); + + // Construct connectivity for the faces. These are used to perform + // the picking. + vtkIdType pts[4]; + vtkCellArray *cells = vtkCellArray::New(); + cells->Allocate(cells->EstimateSize(6,4)); + pts[0] = 3; pts[1] = 0; pts[2] = 4; pts[3] = 7; + cells->InsertNextCell(4,pts); + pts[0] = 1; pts[1] = 2; pts[2] = 6; pts[3] = 5; + cells->InsertNextCell(4,pts); + pts[0] = 0; pts[1] = 1; pts[2] = 5; pts[3] = 4; + cells->InsertNextCell(4,pts); + pts[0] = 2; pts[1] = 3; pts[2] = 7; pts[3] = 6; + cells->InsertNextCell(4,pts); + pts[0] = 0; pts[1] = 3; pts[2] = 2; pts[3] = 1; + cells->InsertNextCell(4,pts); + pts[0] = 4; pts[1] = 5; pts[2] = 6; pts[3] = 7; + cells->InsertNextCell(4,pts); + this->HexPolyData->SetPolys(cells); + cells->Delete(); + this->HexPolyData->BuildCells(); + + // The face of the hexahedra + cells = vtkCellArray::New(); + cells->Allocate(cells->EstimateSize(1,4)); + cells->InsertNextCell(4,pts); //temporary, replaced later + this->HexFacePolyData = vtkPolyData::New(); + this->HexFacePolyData->SetPoints(this->Points); + this->HexFacePolyData->SetPolys(cells); + this->HexFaceMapper = vtkPolyDataMapper::New(); + this->HexFaceMapper->SetInput(HexFacePolyData); + this->HexFace = vtkActor::New(); + this->HexFace->SetMapper(this->HexFaceMapper); + cells->Delete(); + + // Create the outline for the hex + this->OutlinePolyData = vtkPolyData::New(); + this->OutlinePolyData->SetPoints(this->Points); + this->OutlineMapper = vtkPolyDataMapper::New(); + this->OutlineMapper->SetInput(this->OutlinePolyData); + this->HexOutline = vtkActor::New(); + this->HexOutline->SetMapper(this->OutlineMapper); + cells = vtkCellArray::New(); + cells->Allocate(cells->EstimateSize(15,2)); + this->OutlinePolyData->SetLines(cells); + cells->Delete(); + + // Set up the initial properties + this->CreateDefaultProperties(); + + // Create the outline + this->GenerateOutline(); + + // Create the handles + this->Handle = new vtkActor* [7]; + this->HandleMapper = new vtkPolyDataMapper* [7]; + this->HandleGeometry = new vtkSphereSource* [7]; + for (i=0; i<7; i++) + { + this->HandleGeometry[i] = vtkSphereSource::New(); + this->HandleGeometry[i]->SetThetaResolution(16); + this->HandleGeometry[i]->SetPhiResolution(8); + this->HandleMapper[i] = vtkPolyDataMapper::New(); + this->HandleMapper[i]->SetInput(this->HandleGeometry[i]->GetOutput()); + this->Handle[i] = vtkActor::New(); + this->Handle[i]->SetMapper(this->HandleMapper[i]); + } + + // Define the point coordinates + double bounds[6]; + bounds[0] = -0.5; + bounds[1] = 0.5; + bounds[2] = -0.5; + bounds[3] = 0.5; + bounds[4] = -0.5; + bounds[5] = 0.5; + // Points 8-14 are down by PositionHandles(); + this->PlaceWidget(bounds); + + //Manage the picking stuff + this->HandlePicker = vtkCellPicker::New(); + this->HandlePicker->SetTolerance(0.001); + for (i=0; i<7; i++) + { + this->HandlePicker->AddPickList(this->Handle[i]); + } + this->HandlePicker->PickFromListOn(); + + this->HexPicker = vtkCellPicker::New(); + this->HexPicker->SetTolerance(0.001); + this->HexPicker->AddPickList(HexActor); + this->HexPicker->PickFromListOn(); + + this->CurrentHandle = NULL; + + this->Transform = vtkTransform::New(); +} + +vtkBoxWidget::~vtkBoxWidget() +{ + this->HexActor->Delete(); + this->HexMapper->Delete(); + this->HexPolyData->Delete(); + this->Points->Delete(); + + this->HexFace->Delete(); + this->HexFaceMapper->Delete(); + this->HexFacePolyData->Delete(); + + this->HexOutline->Delete(); + this->OutlineMapper->Delete(); + this->OutlinePolyData->Delete(); + + for (int i=0; i<7; i++) + { + this->HandleGeometry[i]->Delete(); + this->HandleMapper[i]->Delete(); + this->Handle[i]->Delete(); + } + delete [] this->Handle; + delete [] this->HandleMapper; + delete [] this->HandleGeometry; + + this->HandlePicker->Delete(); + this->HexPicker->Delete(); + + this->Transform->Delete(); + + this->HandleProperty->Delete(); + this->SelectedHandleProperty->Delete(); + this->FaceProperty->Delete(); + this->SelectedFaceProperty->Delete(); + this->OutlineProperty->Delete(); + this->SelectedOutlineProperty->Delete(); +} + +void vtkBoxWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //------------------------------------------------------------ + { + vtkDebugMacro(<<"Enabling widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // listen to the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // Add the various actors + // Add the outline + this->CurrentRenderer->AddActor(this->HexActor); + this->CurrentRenderer->AddActor(this->HexOutline); + this->HexActor->SetProperty(this->OutlineProperty); + this->HexOutline->SetProperty(this->OutlineProperty); + + // Add the hex face + this->CurrentRenderer->AddActor(this->HexFace); + this->HexFace->SetProperty(this->FaceProperty); + + // turn on the handles + for (int j=0; j<7; j++) + { + this->CurrentRenderer->AddActor(this->Handle[j]); + this->Handle[j]->SetProperty(this->HandleProperty); + } + + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling------------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the outline + this->CurrentRenderer->RemoveActor(this->HexActor); + this->CurrentRenderer->RemoveActor(this->HexOutline); + + // turn off the hex face + this->CurrentRenderer->RemoveActor(this->HexFace); + + // turn off the handles + for (int i=0; i<7; i++) + { + this->CurrentRenderer->RemoveActor(this->Handle[i]); + } + + this->CurrentHandle = NULL; + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkBoxWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkBoxWidget* self = reinterpret_cast<vtkBoxWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkBoxWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + double *bounds=this->InitialBounds; + os << indent << "Initial Bounds: " + << "(" << bounds[0] << "," << bounds[1] << ") " + << "(" << bounds[2] << "," << bounds[3] << ") " + << "(" << bounds[4] << "," << bounds[5] << ")\n"; + + if ( this->HandleProperty ) + { + os << indent << "Handle Property: " << this->HandleProperty << "\n"; + } + else + { + os << indent << "Handle Property: (none)\n"; + } + if ( this->SelectedHandleProperty ) + { + os << indent << "Selected Handle Property: " + << this->SelectedHandleProperty << "\n"; + } + else + { + os << indent << "SelectedHandle Property: (none)\n"; + } + + if ( this->FaceProperty ) + { + os << indent << "Face Property: " << this->FaceProperty << "\n"; + } + else + { + os << indent << "Face Property: (none)\n"; + } + if ( this->SelectedFaceProperty ) + { + os << indent << "Selected Face Property: " + << this->SelectedFaceProperty << "\n"; + } + else + { + os << indent << "Selected Face Property: (none)\n"; + } + + if ( this->OutlineProperty ) + { + os << indent << "Outline Property: " << this->OutlineProperty << "\n"; + } + else + { + os << indent << "Outline Property: (none)\n"; + } + if ( this->SelectedOutlineProperty ) + { + os << indent << "Selected Outline Property: " + << this->SelectedOutlineProperty << "\n"; + } + else + { + os << indent << "Selected Outline Property: (none)\n"; + } + + os << indent << "Outline Face Wires: " << (this->OutlineFaceWires ? "On\n" : "Off\n"); + os << indent << "Outline Cursor Wires: " << (this->OutlineCursorWires ? "On\n" : "Off\n"); + os << indent << "Inside Out: " << (this->InsideOut ? "On\n" : "Off\n"); + os << indent << "Translation Enabled: " << (this->TranslationEnabled ? "On\n" : "Off\n"); + os << indent << "Scaling Enabled: " << (this->ScalingEnabled ? "On\n" : "Off\n"); + os << indent << "Rotation Enabled: " << (this->RotationEnabled ? "On\n" : "Off\n"); + +} + +#define VTK_AVERAGE(a,b,c) \ + c[0] = (a[0] + b[0])/2.0; \ + c[1] = (a[1] + b[1])/2.0; \ + c[2] = (a[2] + b[2])/2.0; + +void vtkBoxWidget::PositionHandles() +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + double *p0 = pts; + double *p1 = pts + 3*1; + double *p2 = pts + 3*2; + double *p3 = pts + 3*3; + //double *p4 = pts + 3*4; + double *p5 = pts + 3*5; + double *p6 = pts + 3*6; + double *p7 = pts + 3*7; + double x[3]; + + VTK_AVERAGE(p0,p7,x); + this->Points->SetPoint(8, x); + VTK_AVERAGE(p1,p6,x); + this->Points->SetPoint(9, x); + VTK_AVERAGE(p0,p5,x); + this->Points->SetPoint(10, x); + VTK_AVERAGE(p2,p7,x); + this->Points->SetPoint(11, x); + VTK_AVERAGE(p1,p3,x); + this->Points->SetPoint(12, x); + VTK_AVERAGE(p5,p7,x); + this->Points->SetPoint(13, x); + VTK_AVERAGE(p0,p6,x); + this->Points->SetPoint(14, x); + + int i; + for (i = 0; i < 7; ++i) + { + this->HandleGeometry[i]->SetCenter(this->Points->GetPoint(8+i)); + } + + this->Points->GetData()->Modified(); + this->HexFacePolyData->Modified(); + this->HexPolyData->Modified(); + this->GenerateOutline(); +} +#undef VTK_AVERAGE + +void vtkBoxWidget::HandlesOn() +{ + for (int i=0; i<7; i++) + { + this->Handle[i]->VisibilityOn(); + } +} + +void vtkBoxWidget::HandlesOff() +{ + for (int i=0; i<7; i++) + { + this->Handle[i]->VisibilityOff(); + } +} + +void vtkBoxWidget::SizeHandles() +{ + double radius = this->vtk3DWidget::SizeHandles(1.5); + for(int i=0; i<7; i++) + { + this->HandleGeometry[i]->SetRadius(radius); + } +} + +int vtkBoxWidget::HighlightHandle(vtkProp *prop) +{ + // first unhighlight anything picked + this->HighlightOutline(0); + if ( this->CurrentHandle ) + { + this->CurrentHandle->SetProperty(this->HandleProperty); + } + + this->CurrentHandle = (vtkActor *)prop; + + if ( this->CurrentHandle ) + { + this->CurrentHandle->SetProperty(this->SelectedHandleProperty); + for (int i=0; i<6; i++) //find attached face + { + if ( this->CurrentHandle == this->Handle[i] ) + { + return i; + } + } + } + + if ( this->CurrentHandle == this->Handle[6] ) + { + this->HighlightOutline(1); + } + + return -1; +} + +void vtkBoxWidget::HighlightFace(int cellId) +{ + if ( cellId >= 0 ) + { + vtkIdType npts; + vtkIdType *pts; + vtkCellArray *cells = this->HexFacePolyData->GetPolys(); + this->HexPolyData->GetCellPoints(cellId, npts, pts); + this->HexFacePolyData->Modified(); + cells->ReplaceCell(0,npts,pts); + this->CurrentHexFace = cellId; + this->HexFace->SetProperty(this->SelectedFaceProperty); + if ( !this->CurrentHandle ) + { + this->CurrentHandle = this->HexFace; + } + } + else + { + this->HexFace->SetProperty(this->FaceProperty); + this->CurrentHexFace = -1; + } +} + +void vtkBoxWidget::HighlightOutline(int highlight) +{ + if ( highlight ) + { + this->HexActor->SetProperty(this->SelectedOutlineProperty); + this->HexOutline->SetProperty(this->SelectedOutlineProperty); + } + else + { + this->HexActor->SetProperty(this->OutlineProperty); + this->HexOutline->SetProperty(this->OutlineProperty); + } +} + +void vtkBoxWidget::OnLeftButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkBoxWidget::Outside; + return; + } + + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkBoxWidget::Moving; + this->HighlightFace( + this->HighlightHandle(path->GetFirstNode()->GetViewProp())); + this->HandlePicker->GetPickPosition(this->LastPickPosition); + this->ValidPick = 1; + } + else + { + this->HexPicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HexPicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkBoxWidget::Moving; + this->HexPicker->GetPickPosition(this->LastPickPosition); + this->ValidPick = 1; + if ( !this->Interactor->GetShiftKey() ) + { + this->HighlightHandle(NULL); + this->HighlightFace(this->HexPicker->GetCellId()); + } + else + { + this->CurrentHandle = this->Handle[6]; + this->HighlightOutline(1); + } + } + else + { + this->HighlightFace(this->HighlightHandle(NULL)); + this->State = vtkBoxWidget::Outside; + return; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent, NULL); + this->Interactor->Render(); +} + +void vtkBoxWidget::OnLeftButtonUp() +{ + if ( this->State == vtkBoxWidget::Outside || + this->State == vtkBoxWidget::Start ) + { + return; + } + + this->State = vtkBoxWidget::Start; + this->HighlightFace(this->HighlightHandle(NULL)); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent, NULL); + this->Interactor->Render(); + +} + +void vtkBoxWidget::OnMiddleButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkBoxWidget::Outside; + return; + } + + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkBoxWidget::Moving; + this->CurrentHandle = this->Handle[6]; + this->HighlightOutline(1); + this->HandlePicker->GetPickPosition(this->LastPickPosition); + this->ValidPick = 1; + } + else + { + this->HexPicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HexPicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkBoxWidget::Moving; + this->CurrentHandle = this->Handle[6]; + this->HighlightOutline(1); + this->HexPicker->GetPickPosition(this->LastPickPosition); + this->ValidPick = 1; + } + else + { + this->HighlightFace(this->HighlightHandle(NULL)); + this->State = vtkBoxWidget::Outside; + return; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent, NULL); + this->Interactor->Render(); +} + +void vtkBoxWidget::OnMiddleButtonUp() +{ + if ( this->State == vtkBoxWidget::Outside || + this->State == vtkBoxWidget::Start ) + { + return; + } + + this->State = vtkBoxWidget::Start; + this->HighlightFace(this->HighlightHandle(NULL)); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent, NULL); + this->Interactor->Render(); + +} + +void vtkBoxWidget::OnRightButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkBoxWidget::Outside; + return; + } + + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkBoxWidget::Scaling; + this->HighlightOutline(1); + this->HandlePicker->GetPickPosition(this->LastPickPosition); + this->ValidPick = 1; + } + else + { + this->HexPicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HexPicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkBoxWidget::Scaling; + this->HighlightOutline(1); + this->HexPicker->GetPickPosition(this->LastPickPosition); + this->ValidPick = 1; + } + else + { + this->State = vtkBoxWidget::Outside; + return; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent, NULL); + this->Interactor->Render(); +} + +void vtkBoxWidget::OnRightButtonUp() +{ + if ( this->State == vtkBoxWidget::Outside ) + { + return; + } + + this->State = vtkBoxWidget::Start; + this->HighlightOutline(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent, NULL); + this->Interactor->Render(); +} + +void vtkBoxWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkBoxWidget::Outside || + this->State == vtkBoxWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z, vpn[3]; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( !camera ) + { + return; + } + + // Compute the two points defining the motion vector + this->ComputeWorldToDisplay(this->LastPickPosition[0], this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + // Process the motion + if ( this->State == vtkBoxWidget::Moving ) + { + // Okay to process + if ( this->CurrentHandle ) + { + if ( this->RotationEnabled && this->CurrentHandle == this->HexFace ) + { + camera->GetViewPlaneNormal(vpn); + this->Rotate(X, Y, prevPickPoint, pickPoint, vpn); + } + else if ( this->TranslationEnabled && this->CurrentHandle == this->Handle[6] ) + { + this->Translate(prevPickPoint, pickPoint); + } + else if ( this->TranslationEnabled && this->ScalingEnabled ) + { + if ( this->CurrentHandle == this->Handle[0] ) + { + this->MoveMinusXFace(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[1] ) + { + this->MovePlusXFace(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[2] ) + { + this->MoveMinusYFace(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[3] ) + { + this->MovePlusYFace(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[4] ) + { + this->MoveMinusZFace(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[5] ) + { + this->MovePlusZFace(prevPickPoint, pickPoint); + } + } + } + } + else if ( this->ScalingEnabled && this->State == vtkBoxWidget::Scaling ) + { + this->Scale(prevPickPoint, pickPoint, X, Y); + } + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + this->Interactor->Render(); +} + +void vtkBoxWidget::MoveFace(double *p1, double *p2, double *dir, + double *x1, double *x2, double *x3, double *x4, + double *x5) + { + int i; + double v[3], v2[3]; + + for (i=0; i<3; i++) + { + v[i] = p2[i] - p1[i]; + v2[i] = dir[i]; + } + + vtkMath::Normalize(v2); + double f = vtkMath::Dot(v,v2); + + for (i=0; i<3; i++) + { + v[i] = f*v2[i]; + + x1[i] += v[i]; + x2[i] += v[i]; + x3[i] += v[i]; + x4[i] += v[i]; + x5[i] += v[i]; + } + this->PositionHandles(); +} + +void vtkBoxWidget::GetDirection(const double Nx[3],const double Ny[3], const double Nz[3], double dir[3]) +{ + double dotNy, dotNz; + double y[3]; + + if(vtkMath::Dot(Nx,Nx)!=0) + { + dir[0] = Nx[0]; + dir[1] = Nx[1]; + dir[2] = Nx[2]; + } + else + { + dotNy = vtkMath::Dot(Ny,Ny); + dotNz = vtkMath::Dot(Nz,Nz); + if(dotNy != 0 && dotNz != 0) + { + vtkMath::Cross(Ny,Nz,dir); + } + else if(dotNy != 0) + { + //dir must have been initialized to the + //corresponding coordinate direction before calling + //this method + vtkMath::Cross(Ny,dir,y); + vtkMath::Cross(y,Ny,dir); + } + else if(dotNz != 0) + { + //dir must have been initialized to the + //corresponding coordinate direction before calling + //this method + vtkMath::Cross(Nz,dir,y); + vtkMath::Cross(y,Nz,dir); + } + } +} +void vtkBoxWidget::MovePlusXFace(double *p1, double *p2) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + + double *h1 = pts + 3*9; + + double *x1 = pts + 3*1; + double *x2 = pts + 3*2; + double *x3 = pts + 3*5; + double *x4 = pts + 3*6; + + double dir[3] = { 1 , 0 , 0}; + this->ComputeNormals(); + this->GetDirection(this->N[1],this->N[3],this->N[5],dir); + this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1); +} + +void vtkBoxWidget::MoveMinusXFace(double *p1, double *p2) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + + double *h1 = pts + 3*8; + + double *x1 = pts + 3*0; + double *x2 = pts + 3*3; + double *x3 = pts + 3*4; + double *x4 = pts + 3*7; + + double dir[3]={-1,0,0}; + this->ComputeNormals(); + this->GetDirection(this->N[0],this->N[4],this->N[2],dir); + + this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1); +} + +void vtkBoxWidget::MovePlusYFace(double *p1, double *p2) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + + double *h1 = pts + 3*11; + + double *x1 = pts + 3*2; + double *x2 = pts + 3*3; + double *x3 = pts + 3*6; + double *x4 = pts + 3*7; + + double dir[3]={0,1,0}; + this->ComputeNormals(); + this->GetDirection(this->N[3],this->N[5],this->N[1],dir); + + this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1); +} + +void vtkBoxWidget::MoveMinusYFace(double *p1, double *p2) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + + double *h1 = pts + 3*10; + + double *x1 = pts + 3*0; + double *x2 = pts + 3*1; + double *x3 = pts + 3*4; + double *x4 = pts + 3*5; + + double dir[3] = {0, -1, 0}; + this->ComputeNormals(); + this->GetDirection(this->N[2],this->N[0],this->N[4],dir); + + this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1); +} + +void vtkBoxWidget::MovePlusZFace(double *p1, double *p2) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + + double *h1 = pts + 3*13; + + double *x1 = pts + 3*4; + double *x2 = pts + 3*5; + double *x3 = pts + 3*6; + double *x4 = pts + 3*7; + + double dir[3]={0,0,1}; + this->ComputeNormals(); + this->GetDirection(this->N[5],this->N[1],this->N[3],dir); + + this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1); +} + +void vtkBoxWidget::MoveMinusZFace(double *p1, double *p2) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + + double *h1 = pts + 3*12; + + double *x1 = pts + 3*0; + double *x2 = pts + 3*1; + double *x3 = pts + 3*2; + double *x4 = pts + 3*3; + + double dir[3]={0,0,-1}; + this->ComputeNormals(); + this->GetDirection(this->N[4],this->N[2],this->N[0],dir); + + this->MoveFace(p1,p2,dir,x1,x2,x3,x4,h1); +} + +// Loop through all points and translate them +void vtkBoxWidget::Translate(double *p1, double *p2) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + double v[3]; + + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Move the corners + for (int i=0; i<8; i++) + { + *pts++ += v[0]; + *pts++ += v[1]; + *pts++ += v[2]; + } + this->PositionHandles(); +} + +void vtkBoxWidget::Scale(double* vtkNotUsed(p1), double* vtkNotUsed(p2), + int vtkNotUsed(X), int Y) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + double *center + = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(3*14); + double sf; + + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.03; + } + else + { + sf = 0.97; + } + + // Move the corners + for (int i=0; i<8; i++, pts+=3) + { + pts[0] = sf * (pts[0] - center[0]) + center[0]; + pts[1] = sf * (pts[1] - center[1]) + center[1]; + pts[2] = sf * (pts[2] - center[2]) + center[2]; + } + this->PositionHandles(); +} + +void vtkBoxWidget::ComputeNormals() +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + double *p0 = pts; + double *px = pts + 3*1; + double *py = pts + 3*3; + double *pz = pts + 3*4; + int i; + + for (i=0; i<3; i++) + { + this->N[0][i] = p0[i] - px[i]; + this->N[2][i] = p0[i] - py[i]; + this->N[4][i] = p0[i] - pz[i]; + } + vtkMath::Normalize(this->N[0]); + vtkMath::Normalize(this->N[2]); + vtkMath::Normalize(this->N[4]); + for (i=0; i<3; i++) + { + this->N[1][i] = -this->N[0][i]; + this->N[3][i] = -this->N[2][i]; + this->N[5][i] = -this->N[4][i]; + } +} + +void vtkBoxWidget::GetPlanes(vtkPlanes *planes) +{ + if ( ! planes ) + { + return; + } + + this->ComputeNormals(); + + vtkPoints *pts = vtkPoints::New(VTK_DOUBLE); + pts->SetNumberOfPoints(6); + + vtkDoubleArray *normals = vtkDoubleArray::New(); + normals->SetNumberOfComponents(3); + normals->SetNumberOfTuples(6); + + // Set the normals and coordinate values + double factor = (this->InsideOut ? -1.0 : 1.0); + for (int i=0; i<6; i++) + { + pts->SetPoint(i,this->Points->GetPoint(8+i)); + normals->SetTuple3(i, factor*this->N[i][0], factor*this->N[i][1], + factor*this->N[i][2]); + } + + planes->SetPoints(pts); + planes->SetNormals(normals); + + pts->Delete(); + normals->Delete(); +} + +void vtkBoxWidget::Rotate(int X, int Y, double *p1, double *p2, double *vpn) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + double *center = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(3*14); + double v[3]; //vector of motion + double axis[3]; //axis of rotation + double theta; //rotation angle + int i; + + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Create axis of rotation and angle of rotation + vtkMath::Cross(vpn,v,axis); + if ( vtkMath::Normalize(axis) == 0.0 ) + { + return; + } + int *size = this->CurrentRenderer->GetSize(); + double l2 = (X-this->Interactor->GetLastEventPosition()[0])*(X-this->Interactor->GetLastEventPosition()[0]) + (Y-this->Interactor->GetLastEventPosition()[1])*(Y-this->Interactor->GetLastEventPosition()[1]); + theta = 360.0 * sqrt(l2/((double)size[0]*size[0]+size[1]*size[1])); + + //Manipulate the transform to reflect the rotation + this->Transform->Identity(); + this->Transform->Translate(center[0],center[1],center[2]); + this->Transform->RotateWXYZ(theta,axis); + this->Transform->Translate(-center[0],-center[1],-center[2]); + + //Set the corners + vtkPoints *newPts = vtkPoints::New(VTK_DOUBLE); + this->Transform->TransformPoints(this->Points,newPts); + + for (i=0; i<8; i++, pts+=3) + { + this->Points->SetPoint(i, newPts->GetPoint(i)); + } + + newPts->Delete(); + this->PositionHandles(); +} + +void vtkBoxWidget::CreateDefaultProperties() +{ + // Handle properties + this->HandleProperty = vtkProperty::New(); + this->HandleProperty->SetColor(1,1,1); + + this->SelectedHandleProperty = vtkProperty::New(); + this->SelectedHandleProperty->SetColor(1,0,0); + + // Face properties + this->FaceProperty = vtkProperty::New(); + this->FaceProperty->SetColor(1,1,1); + this->FaceProperty->SetOpacity(0.0); + + this->SelectedFaceProperty = vtkProperty::New(); + this->SelectedFaceProperty->SetColor(1,1,0); + this->SelectedFaceProperty->SetOpacity(0.25); + + // Outline properties + this->OutlineProperty = vtkProperty::New(); + this->OutlineProperty->SetRepresentationToWireframe(); + this->OutlineProperty->SetAmbient(1.0); + this->OutlineProperty->SetAmbientColor(1.0,1.0,1.0); + this->OutlineProperty->SetLineWidth(2.0); + + this->SelectedOutlineProperty = vtkProperty::New(); + this->SelectedOutlineProperty->SetRepresentationToWireframe(); + this->SelectedOutlineProperty->SetAmbient(1.0); + this->SelectedOutlineProperty->SetAmbientColor(0.0,1.0,0.0); + this->SelectedOutlineProperty->SetLineWidth(2.0); +} + +void vtkBoxWidget::PlaceWidget(double bds[6]) +{ + int i; + double bounds[6], center[3]; + + this->AdjustBounds(bds,bounds,center); + + this->Points->SetPoint(0, bounds[0], bounds[2], bounds[4]); + this->Points->SetPoint(1, bounds[1], bounds[2], bounds[4]); + this->Points->SetPoint(2, bounds[1], bounds[3], bounds[4]); + this->Points->SetPoint(3, bounds[0], bounds[3], bounds[4]); + this->Points->SetPoint(4, bounds[0], bounds[2], bounds[5]); + this->Points->SetPoint(5, bounds[1], bounds[2], bounds[5]); + this->Points->SetPoint(6, bounds[1], bounds[3], bounds[5]); + this->Points->SetPoint(7, bounds[0], bounds[3], bounds[5]); + + for (i=0; i<6; i++) + { + this->InitialBounds[i] = bounds[i]; + } + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + + this->PositionHandles(); + this->ComputeNormals(); + this->SizeHandles(); +} + +void vtkBoxWidget::GetTransform(vtkTransform *t) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + double *p0 = pts; + double *p1 = pts + 3*1; + double *p3 = pts + 3*3; + double *p4 = pts + 3*4; + double *p14 = pts + 3*14; + double center[3], translate[3], scale[3], scaleVec[3][3]; + double InitialCenter[3]; + int i; + + // The transformation is relative to the initial bounds. + // Initial bounds are set when PlaceWidget() is invoked. + t->Identity(); + + // Translation + for (i=0; i<3; i++) + { + InitialCenter[i] = + (this->InitialBounds[2*i+1]+this->InitialBounds[2*i]) / 2.0; + center[i] = p14[i] - InitialCenter[i]; + } + translate[0] = center[0] + InitialCenter[0]; + translate[1] = center[1] + InitialCenter[1]; + translate[2] = center[2] + InitialCenter[2]; + t->Translate(translate[0], translate[1], translate[2]); + + // Orientation + vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); + this->PositionHandles(); + this->ComputeNormals(); + for (i=0; i<3; i++) + { + matrix->SetElement(i,0,this->N[1][i]); + matrix->SetElement(i,1,this->N[3][i]); + matrix->SetElement(i,2,this->N[5][i]); + } + t->Concatenate(matrix); + matrix->Delete(); + + // Scale + for (i=0; i<3; i++) + { + scaleVec[0][i] = (p1[i] - p0[i]); + scaleVec[1][i] = (p3[i] - p0[i]); + scaleVec[2][i] = (p4[i] - p0[i]); + } + + scale[0] = vtkMath::Norm(scaleVec[0]); + if (this->InitialBounds[1] != this->InitialBounds[0]) + { + scale[0] = scale[0] / (this->InitialBounds[1]-this->InitialBounds[0]); + } + scale[1] = vtkMath::Norm(scaleVec[1]); + if (this->InitialBounds[3] != this->InitialBounds[2]) + { + scale[1] = scale[1] / (this->InitialBounds[3]-this->InitialBounds[2]); + } + scale[2] = vtkMath::Norm(scaleVec[2]); + if (this->InitialBounds[5] != this->InitialBounds[4]) + { + scale[2] = scale[2] / (this->InitialBounds[5]-this->InitialBounds[4]); + } + t->Scale(scale[0],scale[1],scale[2]); + + // Add back in the contribution due to non-origin center + t->Translate(-InitialCenter[0], -InitialCenter[1], -InitialCenter[2]); +} + +void vtkBoxWidget::SetTransform(vtkTransform* t) +{ + double *pts = ((vtkDoubleArray *)this->Points->GetData())->GetPointer(0); + double xIn[3]; + // make sure the transform is up-to-date before using it + t->Update(); + + // Position the eight points of the box and then update the + // position of the other handles. + double *bounds=this->InitialBounds; + + xIn[0] = bounds[0]; xIn[1] = bounds[2]; xIn[2] = bounds[4]; + t->InternalTransformPoint(xIn,pts); + + xIn[0] = bounds[1]; xIn[1]= bounds[2]; xIn[2] = bounds[4]; + t->InternalTransformPoint(xIn,pts+3); + + xIn[0] = bounds[1]; xIn[1]= bounds[3]; xIn[2] = bounds[4]; + t->InternalTransformPoint(xIn,pts+6); + + xIn[0] = bounds[0]; xIn[1]= bounds[3]; xIn[2] = bounds[4]; + t->InternalTransformPoint(xIn,pts+9); + + xIn[0] = bounds[0]; xIn[1]= bounds[2]; xIn[2] = bounds[5]; + t->InternalTransformPoint(xIn,pts+12); + + xIn[0] = bounds[1]; xIn[1]= bounds[2]; xIn[2] = bounds[5]; + t->InternalTransformPoint(xIn,pts+15); + + xIn[0] = bounds[1]; xIn[1]= bounds[3]; xIn[2] = bounds[5]; + t->InternalTransformPoint(xIn,pts+18); + + xIn[0] = bounds[0]; xIn[1]= bounds[3]; xIn[2] = bounds[5]; + t->InternalTransformPoint(xIn,pts+21); + + this->PositionHandles(); +} + +void vtkBoxWidget::GetPolyData(vtkPolyData *pd) +{ + pd->SetPoints(this->HexPolyData->GetPoints()); + pd->SetPolys(this->HexPolyData->GetPolys()); +} + +void vtkBoxWidget::SetOutlineFaceWires(int newValue) +{ + if (this->OutlineFaceWires != newValue) + { + this->OutlineFaceWires = newValue; + this->Modified(); + // the outline is dependent on this value, so we have to regen + this->GenerateOutline(); + } +} + +void vtkBoxWidget::SetOutlineCursorWires(int newValue) +{ + if (this->OutlineCursorWires != newValue) + { + this->OutlineCursorWires = newValue; + this->Modified(); + // the outline is dependent on this value, so we have to regen + this->GenerateOutline(); + } +} + +void vtkBoxWidget::GenerateOutline() +{ + // Whatever the case may be, we have to reset the Lines of the + // OutlinePolyData (i.e. nuke all current line data) + vtkCellArray *cells = this->OutlinePolyData->GetLines(); + cells->Reset(); + + // Now the outline lines + if ( ! this->OutlineFaceWires && ! this->OutlineCursorWires ) + { + return; + } + + vtkIdType pts[2]; + + if ( this->OutlineFaceWires ) + { + pts[0] = 0; pts[1] = 7; //the -x face + cells->InsertNextCell(2,pts); + pts[0] = 3; pts[1] = 4; + cells->InsertNextCell(2,pts); + pts[0] = 1; pts[1] = 6; //the +x face + cells->InsertNextCell(2,pts); + pts[0] = 2; pts[1] = 5; + cells->InsertNextCell(2,pts); + pts[0] = 1; pts[1] = 4; //the -y face + cells->InsertNextCell(2,pts); + pts[0] = 0; pts[1] = 5; + cells->InsertNextCell(2,pts); + pts[0] = 3; pts[1] = 6; //the +y face + cells->InsertNextCell(2,pts); + pts[0] = 2; pts[1] = 7; + cells->InsertNextCell(2,pts); + pts[0] = 0; pts[1] = 2; //the -z face + cells->InsertNextCell(2,pts); + pts[0] = 1; pts[1] = 3; + cells->InsertNextCell(2,pts); + pts[0] = 4; pts[1] = 6; //the +Z face + cells->InsertNextCell(2,pts); + pts[0] = 5; pts[1] = 7; + cells->InsertNextCell(2,pts); + } + if ( this->OutlineCursorWires ) + { + pts[0] = 8; pts[1] = 9; //the x cursor line + cells->InsertNextCell(2,pts); + pts[0] = 10; pts[1] = 11; //the y cursor line + cells->InsertNextCell(2,pts); + pts[0] = 12; pts[1] = 13; //the z cursor line + cells->InsertNextCell(2,pts); + } + this->OutlinePolyData->Modified(); + if ( this->OutlineProperty) + { + this->OutlineProperty->SetRepresentationToWireframe(); + this->SelectedOutlineProperty->SetRepresentationToWireframe(); + } +} diff --git a/Widgets/vtkBoxWidget.h b/Widgets/vtkBoxWidget.h new file mode 100644 index 0000000..f5c4f80 --- /dev/null +++ b/Widgets/vtkBoxWidget.h @@ -0,0 +1,326 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkBoxWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkBoxWidget - orthogonal hexahedron 3D widget +// .SECTION Description +// This 3D widget defines a region of interest that is represented by an +// arbitrarily oriented hexahedron with interior face angles of 90 degrees +// (orthogonal faces). The object creates 7 handles that can be moused on and +// manipulated. The first six correspond to the six faces, the seventh is in +// the center of the hexahedron. In addition, a bounding box outline is shown, +// the "faces" of which can be selected for object rotation or scaling. A +// nice feature of the object is that the vtkBoxWidget, like any 3D widget, +// will work with the current interactor style. That is, if vtkBoxWidget does +// not handle an event, then all other registered observers (including the +// interactor style) have an opportunity to process the event. Otherwise, the +// vtkBoxWidget will terminate the processing of the event that it handles. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. The interactor will act +// normally until the "i" key (for "interactor") is pressed, at which point the +// vtkBoxWidget will appear. (See superclass documentation for information +// about changing this behavior.) By grabbing the six face handles (use the +// left mouse button), faces can be moved. By grabbing the center handle +// (with the left mouse button), the entire hexahedron can be +// translated. (Translation can also be employed by using the +// "shift-left-mouse-button" combination inside of the widget.) Scaling is +// achieved by using the right mouse button "up" the render window (makes the +// widget bigger) or "down" the render window (makes the widget smaller). To +// rotate vtkBoxWidget, pick a face (but not a face handle) and move the left +// mouse. (Note: the mouse button must be held down during manipulation.) +// Events that occur outside of the widget (i.e., no part of the widget is +// picked) are propagated to any other registered obsevers (such as the +// interaction style). Turn off the widget by pressing the "i" key again. +// (See the superclass documentation on key press activiation.) +// +// The vtkBoxWidget is very flexible. It can be used to select, cut, clip, or +// perform any other operation that depends on an implicit function (use the +// GetPlanes() method); or it can be used to transform objects using a linear +// transformation (use the GetTransform() method). Typical usage of the +// widget is to make use of the StartInteractionEvent, InteractionEvent, and +// EndInteractionEvent events. The InteractionEvent is called on mouse +// motion; the other two events are called on button down and button up +// (either left or right button). +// +// Some additional features of this class include the ability to control the +// rendered properties of the widget. You can set the properties of the +// selected and unselected representations of the parts of the widget. For +// example, you can set the property for the handles, faces, and outline in +// their normal and selected states. + +// .SECTION Caveats +// Note that handles can be picked even when they are "behind" other actors. +// This is an intended feature and not a bug. +// +// The box widget can be oriented by specifying a transformation matrix. +// This transformation is applied to the initial bounding box as defined by +// the PlaceWidget() method. DO NOT ASSUME that the transformation is applied +// to a unit box centered at the origin; this is wrong! + +// .SECTION See Also +// vtk3DWidget vtkPointWidget vtkLineWidget vtkPlaneWidget +// vtkImplicitPlaneWidget vtkImagePlaneWidget + +#ifndef __vtkBoxWidget_h +#define __vtkBoxWidget_h + +#include "vtk3DWidget.h" + +class vtkActor; +class vtkCellPicker; +class vtkPlanes; +class vtkPoints; +class vtkPolyData; +class vtkPolyDataMapper; +class vtkProp; +class vtkProperty; +class vtkSphereSource; +class vtkTransform; + +class VTK_WIDGETS_EXPORT vtkBoxWidget : public vtk3DWidget +{ +public: + // Description: + // Instantiate the object. + static vtkBoxWidget *New(); + + vtkTypeRevisionMacro(vtkBoxWidget,vtk3DWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Get the planes describing the implicit function defined by the box + // widget. The user must provide the instance of the class vtkPlanes. Note + // that vtkPlanes is a subclass of vtkImplicitFunction, meaning that it can + // be used by a variety of filters to perform clipping, cutting, and + // selection of data. (The direction of the normals of the planes can be + // reversed enabling the InsideOut flag.) + void GetPlanes(vtkPlanes *planes); + + // Description: + // Set/Get the InsideOut flag. When off, the normals point out of the + // box. When on, the normals point into the hexahedron. InsideOut + // is off by default. + vtkSetMacro(InsideOut,int); + vtkGetMacro(InsideOut,int); + vtkBooleanMacro(InsideOut,int); + + // Description: + // Retrieve a linear transform characterizing the transformation of the + // box. Note that the transformation is relative to where PlaceWidget + // was initially called. This method modifies the transform provided. The + // transform can be used to control the position of vtkProp3D's, as well as + // other transformation operations (e.g., vtkTranformPolyData). + virtual void GetTransform(vtkTransform *t); + + // Description: + // Set the position, scale and orientation of the box widget using the + // transform specified. Note that the transformation is relative to + // where PlaceWidget was initially called (i.e., the original bounding + // box). + virtual void SetTransform(vtkTransform* t); + + // Description: + // Grab the polydata (including points) that define the box widget. The + // polydata consists of 6 quadrilateral faces and 15 points. The first + // eight points define the eight corner vertices; the next six define the + // -x,+x, -y,+y, -z,+z face points; and the final point (the 15th out of 15 + // points) defines the center of the hexahedron. These point values are + // guaranteed to be up-to-date when either the InteractionEvent or + // EndInteractionEvent events are invoked. The user provides the + // vtkPolyData and the points and cells are added to it. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Get the handle properties (the little balls are the handles). The + // properties of the handles when selected and normal can be + // set. + vtkGetObjectMacro(HandleProperty,vtkProperty); + vtkGetObjectMacro(SelectedHandleProperty,vtkProperty); + + // Description: + // Switches handles (the spheres) on or off by manipulating the actor + // visibility. + void HandlesOn(); + void HandlesOff(); + + // Description: + // Get the face properties (the faces of the box). The + // properties of the face when selected and normal can be + // set. + vtkGetObjectMacro(FaceProperty,vtkProperty); + vtkGetObjectMacro(SelectedFaceProperty,vtkProperty); + + // Description: + // Get the outline properties (the outline of the box). The + // properties of the outline when selected and normal can be + // set. + vtkGetObjectMacro(OutlineProperty,vtkProperty); + vtkGetObjectMacro(SelectedOutlineProperty,vtkProperty); + + // Description: + // Control the representation of the outline. This flag enables + // face wires. By default face wires are off. + void SetOutlineFaceWires(int); + vtkGetMacro(OutlineFaceWires,int); + void OutlineFaceWiresOn() {this->SetOutlineFaceWires(1);} + void OutlineFaceWiresOff() {this->SetOutlineFaceWires(0);} + + // Description: + // Control the representation of the outline. This flag enables + // the cursor lines running between the handles. By default cursor + // wires are on. + void SetOutlineCursorWires(int); + vtkGetMacro(OutlineCursorWires,int); + void OutlineCursorWiresOn() {this->SetOutlineCursorWires(1);} + void OutlineCursorWiresOff() {this->SetOutlineCursorWires(0);} + + // Description: + // Control the behavior of the widget. Translation, rotation, and + // scaling can all be enabled and disabled. + vtkSetMacro(TranslationEnabled,int); + vtkGetMacro(TranslationEnabled,int); + vtkBooleanMacro(TranslationEnabled,int); + vtkSetMacro(ScalingEnabled,int); + vtkGetMacro(ScalingEnabled,int); + vtkBooleanMacro(ScalingEnabled,int); + vtkSetMacro(RotationEnabled,int); + vtkGetMacro(RotationEnabled,int); + vtkBooleanMacro(RotationEnabled,int); + +protected: + vtkBoxWidget(); + ~vtkBoxWidget(); + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Start=0, + Moving, + Scaling, + Outside + }; +//ETX + + // Handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // the hexahedron (6 faces) + vtkActor *HexActor; + vtkPolyDataMapper *HexMapper; + vtkPolyData *HexPolyData; + vtkPoints *Points; //used by others as well + double N[6][3]; //the normals of the faces + + // A face of the hexahedron + vtkActor *HexFace; + vtkPolyDataMapper *HexFaceMapper; + vtkPolyData *HexFacePolyData; + + // glyphs representing hot spots (e.g., handles) + vtkActor **Handle; + vtkPolyDataMapper **HandleMapper; + vtkSphereSource **HandleGeometry; + virtual void PositionHandles(); + int HighlightHandle(vtkProp *prop); //returns cell id + void HighlightFace(int cellId); + void HighlightOutline(int highlight); + void ComputeNormals(); + virtual void SizeHandles(); + + // wireframe outline + vtkActor *HexOutline; + vtkPolyDataMapper *OutlineMapper; + vtkPolyData *OutlinePolyData; + + // Do the picking + vtkCellPicker *HandlePicker; + vtkCellPicker *HexPicker; + vtkActor *CurrentHandle; + int CurrentHexFace; + + // Methods to manipulate the hexahedron. + virtual void Translate(double *p1, double *p2); + virtual void Scale(double *p1, double *p2, int X, int Y); + virtual void Rotate(int X, int Y, double *p1, double *p2, double *vpn); + void MovePlusXFace(double *p1, double *p2); + void MoveMinusXFace(double *p1, double *p2); + void MovePlusYFace(double *p1, double *p2); + void MoveMinusYFace(double *p1, double *p2); + void MovePlusZFace(double *p1, double *p2); + void MoveMinusZFace(double *p1, double *p2); + + //"dir" is the direction in which the face can be moved i.e. the axis passing + //through the center + void MoveFace(double *p1, double *p2, double *dir, + double *x1, double *x2, double *x3, double *x4, + double *x5); + //Helper method to obtain the direction in which the face is to be moved. + //Handles special cases where some of the scale factors are 0. + void GetDirection(const double Nx[3],const double Ny[3], + const double Nz[3], double dir[3]); + + // Transform the hexahedral points (used for rotations) + vtkTransform *Transform; + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *HandleProperty; + vtkProperty *SelectedHandleProperty; + vtkProperty *FaceProperty; + vtkProperty *SelectedFaceProperty; + vtkProperty *OutlineProperty; + vtkProperty *SelectedOutlineProperty; + void CreateDefaultProperties(); + + // Control the orientation of the normals + int InsideOut; + int OutlineFaceWires; + int OutlineCursorWires; + void GenerateOutline(); + + // Control whether scaling, rotation, and translation are supported + int TranslationEnabled; + int ScalingEnabled; + int RotationEnabled; + +private: + vtkBoxWidget(const vtkBoxWidget&); //Not implemented + void operator=(const vtkBoxWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkImagePlaneWidget.cxx b/Widgets/vtkImagePlaneWidget.cxx new file mode 100644 index 0000000..ad45116 --- /dev/null +++ b/Widgets/vtkImagePlaneWidget.cxx @@ -0,0 +1,2782 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagePlaneWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImagePlaneWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkCellPicker.h" +#include "vtkImageData.h" +#include "vtkImageMapToColors.h" +#include "vtkImageReslice.h" +#include "vtkLookupTable.h" +#include "vtkMath.h" +#include "vtkMatrix4x4.h" +#include "vtkObjectFactory.h" +#include "vtkPlaneSource.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkTextActor.h" +#include "vtkTextProperty.h" +#include "vtkTexture.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkImagePlaneWidget, "$Revision: 1.4.2.1 $"); +vtkStandardNewMacro(vtkImagePlaneWidget); + +vtkCxxSetObjectMacro(vtkImagePlaneWidget, PlaneProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImagePlaneWidget, SelectedPlaneProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImagePlaneWidget, CursorProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImagePlaneWidget, MarginProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImagePlaneWidget, TexturePlaneProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImagePlaneWidget, ColorMap, vtkImageMapToColors); + +vtkImagePlaneWidget::vtkImagePlaneWidget() : vtkPolyDataSourceWidget() +{ + this->State = vtkImagePlaneWidget::Start; + this->EventCallbackCommand->SetCallback(vtkImagePlaneWidget::ProcessEvents); + + this->Interaction = 1; + this->PlaneOrientation = 0; + this->PlaceFactor = 1.0; + this->RestrictPlaneToVolume = 1; + this->OriginalWindow = 1.0; + this->OriginalLevel = 0.5; + this->CurrentWindow = 1.0; + this->CurrentLevel = 0.5; + this->TextureInterpolate = 1; + this->ResliceInterpolate = VTK_LINEAR_RESLICE; + this->UserControlledLookupTable= 0; + this->DisplayText = 0; + this->CurrentCursorPosition[0] = 0; + this->CurrentCursorPosition[1] = 0; + this->CurrentCursorPosition[2] = 0; + this->CurrentImageValue = VTK_DOUBLE_MAX; + this->MarginSelectMode = 8; + this->UseContinuousCursor = 0; + + // Represent the plane's outline + // + this->PlaneSource = vtkPlaneSource::New(); + this->PlaneSource->SetXResolution(1); + this->PlaneSource->SetYResolution(1); + this->PlaneOutlinePolyData = vtkPolyData::New(); + this->PlaneOutlineActor = vtkActor::New(); + + // Represent the resliced image plane + // + this->ColorMap = vtkImageMapToColors::New(); + this->Reslice = vtkImageReslice::New(); + this->Reslice->TransformInputSamplingOff(); + this->ResliceAxes = vtkMatrix4x4::New(); + this->Texture = vtkTexture::New(); + this->TexturePlaneActor = vtkActor::New(); + this->Transform = vtkTransform::New(); + this->ImageData = 0; + this->LookupTable = 0; + + // Represent the cross hair cursor + // + this->CursorPolyData = vtkPolyData::New(); + this->CursorActor = vtkActor::New(); + + // Represent the oblique positioning margins + // + this->MarginPolyData = vtkPolyData::New(); + this->MarginActor = vtkActor::New(); + + // Represent the text: annotation for cursor position and W/L + // + this->TextActor = vtkTextActor::New(); + + this->GeneratePlaneOutline(); + + // Define some default point coordinates + // + double bounds[6]; + bounds[0] = -0.5; + bounds[1] = 0.5; + bounds[2] = -0.5; + bounds[3] = 0.5; + bounds[4] = -0.5; + bounds[5] = 0.5; + + // Initial creation of the widget, serves to initialize it + // + this->PlaceWidget(bounds); + + this->GenerateTexturePlane(); + this->GenerateCursor(); + this->GenerateMargins(); + this->GenerateText(); + + // Manage the picking stuff + // + this->PlanePicker = vtkCellPicker::New(); + this->PlanePicker->SetTolerance(0.005); //need some fluff + this->PlanePicker->AddPickList(this->TexturePlaneActor); + this->PlanePicker->PickFromListOn(); + this->PlanePicker->Register(this); + this->PlanePicker->Delete(); + + // Set up the initial properties + // + this->PlaneProperty = 0; + this->SelectedPlaneProperty = 0; + this->TexturePlaneProperty = 0; + this->CursorProperty = 0; + this->MarginProperty = 0; + this->CreateDefaultProperties(); + + // Set up actions + + this->LeftButtonAction = vtkImagePlaneWidget::CURSOR_ACTION; + this->MiddleButtonAction = vtkImagePlaneWidget::SLICE_MOTION_ACTION; + this->RightButtonAction = vtkImagePlaneWidget::WINDOW_LEVEL_ACTION; + + // Set up modifiers + + this->LeftButtonAutoModifier = vtkImagePlaneWidget::NO_MODIFIER; + this->MiddleButtonAutoModifier = vtkImagePlaneWidget::NO_MODIFIER; + this->RightButtonAutoModifier = vtkImagePlaneWidget::NO_MODIFIER; + + this->LastButtonPressed = vtkImagePlaneWidget::NO_BUTTON; + + this->TextureVisibility = 1; +} + +vtkImagePlaneWidget::~vtkImagePlaneWidget() +{ + this->PlaneOutlineActor->Delete(); + this->PlaneOutlinePolyData->Delete(); + this->PlaneSource->Delete(); + + if ( this->PlanePicker ) + { + this->PlanePicker->UnRegister(this); + } + + if ( this->PlaneProperty ) + { + this->PlaneProperty->Delete(); + } + + if ( this->SelectedPlaneProperty ) + { + this->SelectedPlaneProperty->Delete(); + } + + if ( this->CursorProperty ) + { + this->CursorProperty->Delete(); + } + + if ( this->MarginProperty ) + { + this->MarginProperty->Delete(); + } + + this->ResliceAxes->Delete(); + this->Transform->Delete(); + this->Reslice->Delete(); + + if ( this->LookupTable ) + { + this->LookupTable->UnRegister(this); + } + + this->TexturePlaneActor->Delete(); + this->ColorMap->Delete(); + this->Texture->Delete(); + + if ( this->TexturePlaneProperty ) + { + this->TexturePlaneProperty->Delete(); + } + + if ( this->ImageData ) + { + this->ImageData = 0; + } + + this->CursorActor->Delete(); + this->CursorPolyData->Delete(); + + this->MarginActor->Delete(); + this->MarginPolyData->Delete(); + + this->TextActor->Delete(); +} + +void vtkImagePlaneWidget::SetTextureVisibility(int vis) +{ + if (this->TextureVisibility == vis) + { + return; + } + + this->TextureVisibility = vis; + + if ( this->Enabled ) + { + if (this->TextureVisibility) + { + this->CurrentRenderer->AddViewProp(this->TexturePlaneActor); + } + else + { + this->CurrentRenderer->RemoveViewProp(this->TexturePlaneActor); + } + } + + this->Modified(); +} + + +void vtkImagePlaneWidget::SetEnabled(int enabling) +{ + + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //---------------------------------------------------------- + { + vtkDebugMacro(<<"Enabling plane widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // we have to honour this ivar: it could be that this->Interaction was + // set to off when we were disabled + if (this->Interaction) + { + this->AddObservers(); + } + + // Add the plane + this->CurrentRenderer->AddViewProp(this->PlaneOutlineActor); + this->PlaneOutlineActor->SetProperty(this->PlaneProperty); + + //add the TexturePlaneActor + if (this->TextureVisibility) + { + this->CurrentRenderer->AddViewProp(this->TexturePlaneActor); + } + this->TexturePlaneActor->SetProperty(this->TexturePlaneProperty); + + // Add the cross-hair cursor + this->CurrentRenderer->AddViewProp(this->CursorActor); + this->CursorActor->SetProperty(this->CursorProperty); + + // Add the margins + this->CurrentRenderer->AddViewProp(this->MarginActor); + this->MarginActor->SetProperty(this->MarginProperty); + + // Add the image data annotation + this->CurrentRenderer->AddViewProp(this->TextActor); + + if ( this->PlanePicker ) + { + this->TexturePlaneActor->PickableOn(); + } + + this->InvokeEvent(vtkCommand::EnableEvent,0); + + } + + else //disabling---------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling plane widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the plane + this->CurrentRenderer->RemoveViewProp(this->PlaneOutlineActor); + + //turn off the texture plane + this->CurrentRenderer->RemoveViewProp(this->TexturePlaneActor); + + //turn off the cursor + this->CurrentRenderer->RemoveViewProp(this->CursorActor); + + //turn off the margins + this->CurrentRenderer->RemoveViewProp(this->MarginActor); + + //turn off the image data annotation + this->CurrentRenderer->RemoveViewProp(this->TextActor); + + if ( this->PlanePicker ) + { + this->TexturePlaneActor->PickableOff(); + } + + this->InvokeEvent(vtkCommand::DisableEvent,0); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkImagePlaneWidget* self = + reinterpret_cast<vtkImagePlaneWidget *>( clientdata ); + + self->LastButtonPressed = vtkImagePlaneWidget::NO_BUTTON; + + //okay, let's do the right thing + switch ( event ) + { + case vtkCommand::LeftButtonPressEvent: + self->LastButtonPressed = vtkImagePlaneWidget::LEFT_BUTTON; + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->LastButtonPressed = vtkImagePlaneWidget::LEFT_BUTTON; + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->LastButtonPressed = vtkImagePlaneWidget::MIDDLE_BUTTON; + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->LastButtonPressed = vtkImagePlaneWidget::MIDDLE_BUTTON; + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->LastButtonPressed = vtkImagePlaneWidget::RIGHT_BUTTON; + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->LastButtonPressed = vtkImagePlaneWidget::RIGHT_BUTTON; + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkImagePlaneWidget::AddObservers(void) +{ + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + if (i) + { + i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + } +} + +void vtkImagePlaneWidget::SetInteraction(int interact) +{ + if (this->Interactor && this->Enabled) + { + if (this->Interaction == interact) + { + return; + } + if (interact == 0) + { + this->Interactor->RemoveObserver(this->EventCallbackCommand); + } + else + { + this->AddObservers(); + } + this->Interaction = interact; + } + else + { + vtkGenericWarningMacro(<<"set interactor and Enabled before changing interaction..."); + } +} + +void vtkImagePlaneWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->PlaneProperty ) + { + os << indent << "Plane Property:\n"; + this->PlaneProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Plane Property: (none)\n"; + } + + if ( this->SelectedPlaneProperty ) + { + os << indent << "Selected Plane Property:\n"; + this->SelectedPlaneProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Selected Plane Property: (none)\n"; + } + + if ( this->LookupTable ) + { + os << indent << "LookupTable:\n"; + this->LookupTable->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "LookupTable: (none)\n"; + } + + if ( this->CursorProperty ) + { + os << indent << "Cursor Property:\n"; + this->CursorProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Cursor Property: (none)\n"; + } + + if ( this->MarginProperty ) + { + os << indent << "Margin Property:\n"; + this->MarginProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Margin Property: (none)\n"; + } + + if ( this->TexturePlaneProperty ) + { + os << indent << "TexturePlane Property:\n"; + this->TexturePlaneProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "TexturePlane Property: (none)\n"; + } + + if ( this->ColorMap ) + { + os << indent << "ColorMap:\n"; + this->ColorMap->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "ColorMap: (none)\n"; + } + + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + os << indent << "Origin: (" << o[0] << ", " + << o[1] << ", " + << o[2] << ")\n"; + os << indent << "Point 1: (" << pt1[0] << ", " + << pt1[1] << ", " + << pt1[2] << ")\n"; + os << indent << "Point 2: (" << pt2[0] << ", " + << pt2[1] << ", " + << pt2[2] << ")\n"; + + os << indent << "Current Cursor Position: (" + << this->CurrentCursorPosition[0] << ", " + << this->CurrentCursorPosition[1] << ", " + << this->CurrentCursorPosition[2] << ")\n"; + + os << indent << "Current Image Value: " + << this->CurrentImageValue << "\n"; + + os << indent << "Plane Orientation: " << this->PlaneOrientation << "\n"; + os << indent << "Reslice Interpolate: " << this->ResliceInterpolate << "\n"; + os << indent << "Texture Interpolate: " + << (this->TextureInterpolate ? "On\n" : "Off\n") ; + os << indent << "Texture Visibility: " + << (this->TextureVisibility ? "On\n" : "Off\n") ; + os << indent << "Restrict Plane To Volume: " + << (this->RestrictPlaneToVolume ? "On\n" : "Off\n") ; + os << indent << "Display Text: " + << (this->DisplayText ? "On\n" : "Off\n") ; + os << indent << "Interaction: " + << (this->Interaction ? "On\n" : "Off\n") ; + os << indent << "User Controlled Lookup Table: " + << (this->UserControlledLookupTable ? "On\n" : "Off\n") ; + os << indent << "LeftButtonAction: " << this->LeftButtonAction << endl; + os << indent << "MiddleButtonAction: " << this->MiddleButtonAction << endl; + os << indent << "RightButtonAction: " << this->RightButtonAction << endl; + os << indent << "LeftButtonAutoModifier: " << + this->LeftButtonAutoModifier << endl; + os << indent << "MiddleButtonAutoModifier: " << + this->MiddleButtonAutoModifier << endl; + os << indent << "RightButtonAutoModifier: " << + this->RightButtonAutoModifier << endl; + os << indent << "UseContinuousCursor: " + << (this->UseContinuousCursor ? "On\n" : "Off\n") ; +} + +void vtkImagePlaneWidget::BuildRepresentation() +{ + this->PlaneSource->Update(); + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + double x[3]; + x[0] = o[0] + (pt1[0]-o[0]) + (pt2[0]-o[0]); + x[1] = o[1] + (pt1[1]-o[1]) + (pt2[1]-o[1]); + x[2] = o[2] + (pt1[2]-o[2]) + (pt2[2]-o[2]); + + vtkPoints* points = this->PlaneOutlinePolyData->GetPoints(); + points->SetPoint(0,o); + points->SetPoint(1,pt1); + points->SetPoint(2,x); + points->SetPoint(3,pt2); + points->GetData()->Modified(); + this->PlaneOutlinePolyData->Modified(); +} + +void vtkImagePlaneWidget::HighlightPlane(int highlight) +{ + if ( highlight ) + { + this->PlaneOutlineActor->SetProperty(this->SelectedPlaneProperty); + this->PlanePicker->GetPickPosition(this->LastPickPosition); + } + else + { + this->PlaneOutlineActor->SetProperty(this->PlaneProperty); + } +} + +void vtkImagePlaneWidget::OnLeftButtonDown() +{ + switch (this->LeftButtonAction) + { + case vtkImagePlaneWidget::CURSOR_ACTION: + this->StartCursor(); + break; + case vtkImagePlaneWidget::SLICE_MOTION_ACTION: + this->StartSliceMotion(); + break; + case vtkImagePlaneWidget::WINDOW_LEVEL_ACTION: + this->StartWindowLevel(); + break; + } +} + +void vtkImagePlaneWidget::OnLeftButtonUp() +{ + switch (this->LeftButtonAction) + { + case vtkImagePlaneWidget::CURSOR_ACTION: + this->StopCursor(); + break; + case vtkImagePlaneWidget::SLICE_MOTION_ACTION: + this->StopSliceMotion(); + break; + case vtkImagePlaneWidget::WINDOW_LEVEL_ACTION: + this->StopWindowLevel(); + break; + } +} + +void vtkImagePlaneWidget::OnMiddleButtonDown() +{ + switch (this->MiddleButtonAction) + { + case vtkImagePlaneWidget::CURSOR_ACTION: + this->StartCursor(); + break; + case vtkImagePlaneWidget::SLICE_MOTION_ACTION: + this->StartSliceMotion(); + break; + case vtkImagePlaneWidget::WINDOW_LEVEL_ACTION: + this->StartWindowLevel(); + break; + } +} + +void vtkImagePlaneWidget::OnMiddleButtonUp() +{ + switch (this->MiddleButtonAction) + { + case vtkImagePlaneWidget::CURSOR_ACTION: + this->StopCursor(); + break; + case vtkImagePlaneWidget::SLICE_MOTION_ACTION: + this->StopSliceMotion(); + break; + case vtkImagePlaneWidget::WINDOW_LEVEL_ACTION: + this->StopWindowLevel(); + break; + } +} + +void vtkImagePlaneWidget::OnRightButtonDown() +{ + switch (this->RightButtonAction) + { + case vtkImagePlaneWidget::CURSOR_ACTION: + this->StartCursor(); + break; + case vtkImagePlaneWidget::SLICE_MOTION_ACTION: + this->StartSliceMotion(); + break; + case vtkImagePlaneWidget::WINDOW_LEVEL_ACTION: + this->StartWindowLevel(); + break; + } +} + +void vtkImagePlaneWidget::OnRightButtonUp() +{ + switch (this->RightButtonAction) + { + case vtkImagePlaneWidget::CURSOR_ACTION: + this->StopCursor(); + break; + case vtkImagePlaneWidget::SLICE_MOTION_ACTION: + this->StopSliceMotion(); + break; + case vtkImagePlaneWidget::WINDOW_LEVEL_ACTION: + this->StopWindowLevel(); + break; + } +} + +void vtkImagePlaneWidget::StartCursor() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkImagePlaneWidget::Outside; + return; + } + + // Okay, we can process this. If anything is picked, then we + // can start pushing the plane. + vtkAssemblyPath *path; + this->PlanePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->PlanePicker->GetPath(); + + int found = 0; + int i; + if ( path != 0 ) + { + // Deal with the possibility that we may be using a shared picker + vtkCollectionSimpleIterator sit; + path->InitTraversal(sit); + vtkAssemblyNode *node; + for ( i = 0; i < path->GetNumberOfItems() && !found ; i++ ) + { + node = path->GetNextNode(sit); + if ( node->GetViewProp() == vtkProp::SafeDownCast(this->TexturePlaneActor) ) + { + found = 1; + } + } + } + + if( ! found || path == 0 ) + { + this->State = vtkImagePlaneWidget::Outside; + this->HighlightPlane(0); + this->ActivateCursor(0); + this->ActivateText(0); + return; + } + else + { + this->State = vtkImagePlaneWidget::Cursoring; + this->HighlightPlane(1); + this->ActivateCursor(1); + this->ActivateText(1); + this->UpdateCursor(X,Y); + this->ManageTextDisplay(); + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,0); + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::StopCursor() +{ + if ( this->State == vtkImagePlaneWidget::Outside || + this->State == vtkImagePlaneWidget::Start ) + { + return; + } + + this->State = vtkImagePlaneWidget::Start; + this->HighlightPlane(0); + this->ActivateCursor(0); + this->ActivateText(0); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,0); + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::StartSliceMotion() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkImagePlaneWidget::Outside; + return; + } + + // Okay, we can process this. If anything is picked, then we + // can start pushing or check for adjusted states. + vtkAssemblyPath *path; + this->PlanePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->PlanePicker->GetPath(); + + int found = 0; + int i; + if ( path != 0 ) + { + // Deal with the possibility that we may be using a shared picker + vtkCollectionSimpleIterator sit; + path->InitTraversal(sit); + vtkAssemblyNode *node; + for(i = 0; i< path->GetNumberOfItems() && !found ;i++) + { + node = path->GetNextNode(sit); + if(node->GetViewProp() == vtkProp::SafeDownCast(this->TexturePlaneActor) ) + { + found = 1; + } + } + } + + if ( !found || path == 0 ) + { + this->State = vtkImagePlaneWidget::Outside; + this->HighlightPlane(0); + this->ActivateMargins(0); + return; + } + else + { + this->State = vtkImagePlaneWidget::Pushing; + this->HighlightPlane(1); + this->ActivateMargins(1); + this->AdjustState(); + this->UpdateMargins(); + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,0); + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::StopSliceMotion() +{ + if ( this->State == vtkImagePlaneWidget::Outside || + this->State == vtkImagePlaneWidget::Start ) + { + return; + } + + this->State = vtkImagePlaneWidget::Start; + this->HighlightPlane(0); + this->ActivateMargins(0); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,0); + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::StartWindowLevel() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkImagePlaneWidget::Outside; + return; + } + + // Okay, we can process this. If anything is picked, then we + // can start window-levelling. + vtkAssemblyPath *path; + this->PlanePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->PlanePicker->GetPath(); + + int found = 0; + int i; + if ( path != 0 ) + { + // Deal with the possibility that we may be using a shared picker + vtkCollectionSimpleIterator sit; + path->InitTraversal(sit); + vtkAssemblyNode *node; + for ( i = 0; i < path->GetNumberOfItems() && !found ; i++ ) + { + node = path->GetNextNode(sit); + if ( node->GetViewProp() == vtkProp::SafeDownCast(this->TexturePlaneActor) ) + { + found = 1; + } + } + } + + if( ! found || path == 0 ) + { + this->State = vtkImagePlaneWidget::Outside; + this->HighlightPlane(0); + this->ActivateText(0); + return; + } + else + { + this->State = vtkImagePlaneWidget::WindowLevelling; + this->HighlightPlane(1); + this->ActivateText(1); + this->WindowLevel(X,Y); + this->ManageTextDisplay(); + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,0); + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::StopWindowLevel() +{ + if ( this->State == vtkImagePlaneWidget::Outside || + this->State == vtkImagePlaneWidget::Start ) + { + return; + } + + this->State = vtkImagePlaneWidget::Start; + this->HighlightPlane(0); + this->ActivateText(0); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,0); + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::OnMouseMove() +{ + // See whether we're active + // + if ( this->State == vtkImagePlaneWidget::Outside || + this->State == vtkImagePlaneWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + // + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z, vpn[3]; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( ! camera ) + { + return; + } + + // Compute the two points defining the motion vector + // + this->ComputeWorldToDisplay(this->LastPickPosition[0], + this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + + this->ComputeDisplayToWorld( + double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + if ( this->State == vtkImagePlaneWidget::WindowLevelling ) + { + this->WindowLevel(X,Y); + this->ManageTextDisplay(); + } + else if ( this->State == vtkImagePlaneWidget::Pushing ) + { + this->Push(prevPickPoint, pickPoint); + this->UpdatePlane(); + this->UpdateMargins(); + this->BuildRepresentation(); + } + else if ( this->State == vtkImagePlaneWidget::Spinning ) + { + this->Spin(prevPickPoint, pickPoint); + this->UpdatePlane(); + this->UpdateMargins(); + this->BuildRepresentation(); + } + else if ( this->State == vtkImagePlaneWidget::Rotating ) + { + camera->GetViewPlaneNormal(vpn); + this->Rotate(prevPickPoint, pickPoint, vpn); + this->UpdatePlane(); + this->UpdateMargins(); + this->BuildRepresentation(); + } + else if ( this->State == vtkImagePlaneWidget::Scaling ) + { + this->Scale(prevPickPoint, pickPoint, X, Y); + this->UpdatePlane(); + this->UpdateMargins(); + this->BuildRepresentation(); + } + else if ( this->State == vtkImagePlaneWidget::Moving ) + { + this->Translate(prevPickPoint, pickPoint); + this->UpdatePlane(); + this->UpdateMargins(); + this->BuildRepresentation(); + } + else if ( this->State == vtkImagePlaneWidget::Cursoring ) + { + this->UpdateCursor(X,Y); + this->ManageTextDisplay(); + } + + // Interact, if desired + // + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,0); + + this->Interactor->Render(); +} + +void vtkImagePlaneWidget::WindowLevel(int X, int Y) +{ + double range[2]; + this->LookupTable->GetTableRange(range); + double window = range[1] - range[0]; + double level = 0.5*(range[0] + range[1]); + + double owin = this->OriginalWindow; + + level = level + (X - this->Interactor->GetLastEventPosition()[0])*owin/500.0; + window = + window + (this->Interactor->GetLastEventPosition()[1] - Y)*owin/250.0; + + if ( window == 0.0 ) + { + window = 0.001; + } + + double rmin = level - window*0.5; + double rmax = level + window*0.5; + + if( rmin < rmax ) + { + this->CurrentWindow = window; + this->CurrentLevel = level; + if (!this->UserControlledLookupTable) + { + this->LookupTable->SetTableRange(rmin,rmax); + } + } +} + +void vtkImagePlaneWidget::SetWindowLevel(double window, double level) +{ + double rmin = level - window*0.5; + double rmax = level + window*0.5; + this->CurrentWindow = window; + this->OriginalWindow = window; + this->CurrentLevel = level; + this->OriginalLevel = level; + this->LookupTable->SetTableRange(rmin,rmax); + + if(this->Enabled) + { + this->Interactor->Render(); + } +} + +void vtkImagePlaneWidget::GetWindowLevel(double wl[2]) +{ + double range[2]; + this->LookupTable->GetTableRange(range); + wl[0] = range[1] - range[0]; + wl[1] = 0.5*(range[0]+range[1]); +} + +int vtkImagePlaneWidget::GetCursorData(double xyzv[4]) +{ + if ( this->State != vtkImagePlaneWidget::Cursoring || \ + this->CurrentImageValue == VTK_DOUBLE_MAX ) + { + return 0; + } + + xyzv[0] = this->CurrentCursorPosition[0]; + xyzv[1] = this->CurrentCursorPosition[1]; + xyzv[2] = this->CurrentCursorPosition[2]; + xyzv[3] = this->CurrentImageValue; + + return 1; +} + +int vtkImagePlaneWidget::GetCursorDataStatus() +{ + if ( this->State != vtkImagePlaneWidget::Cursoring || \ + this->CurrentImageValue == VTK_DOUBLE_MAX ) + { + return 0; + } + + return 1; +} + +void vtkImagePlaneWidget::ManageTextDisplay() +{ + if ( !this->DisplayText ) + { + return; + } + + if ( this->State == vtkImagePlaneWidget::WindowLevelling ) + { + sprintf(this->TextBuff,"Window, Level: ( %g, %g )", + this->CurrentWindow, this->CurrentLevel ); + } + else if ( this->State == vtkImagePlaneWidget::Cursoring ) + { + if( this->CurrentImageValue == VTK_DOUBLE_MAX ) + { + sprintf(this->TextBuff,"Off Image"); + } + else + { + sprintf(this->TextBuff,"( %g, %g, %g ): %g", + this->CurrentCursorPosition[0], + this->CurrentCursorPosition[1], + this->CurrentCursorPosition[2],this->CurrentImageValue); + } + } + + this->TextActor->SetInput(this->TextBuff); + this->TextActor->Modified(); +} + +void vtkImagePlaneWidget::Push(double *p1, double *p2) +{ + // Get the motion vector + // + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + this->PlaneSource->Push( vtkMath::Dot( v, this->PlaneSource->GetNormal() ) ); +} + +void vtkImagePlaneWidget::CreateDefaultProperties() +{ + if ( ! this->PlaneProperty ) + { + this->PlaneProperty = vtkProperty::New(); + this->PlaneProperty->SetAmbient(1); + this->PlaneProperty->SetColor(1,1,1); + this->PlaneProperty->SetRepresentationToWireframe(); + this->PlaneProperty->SetInterpolationToFlat(); + } + + if ( ! this->SelectedPlaneProperty ) + { + this->SelectedPlaneProperty = vtkProperty::New(); + this->SelectedPlaneProperty->SetAmbient(1); + this->SelectedPlaneProperty->SetColor(0,1,0); + this->SelectedPlaneProperty->SetRepresentationToWireframe(); + this->SelectedPlaneProperty->SetInterpolationToFlat(); + } + + if ( ! this->CursorProperty ) + { + this->CursorProperty = vtkProperty::New(); + this->CursorProperty->SetAmbient(1); + this->CursorProperty->SetColor(1,0,0); + this->CursorProperty->SetRepresentationToWireframe(); + this->CursorProperty->SetInterpolationToFlat(); + } + + if ( ! this->MarginProperty ) + { + this->MarginProperty = vtkProperty::New(); + this->MarginProperty->SetAmbient(1); + this->MarginProperty->SetColor(0,0,1); + this->MarginProperty->SetRepresentationToWireframe(); + this->MarginProperty->SetInterpolationToFlat(); + } + + if ( ! this->TexturePlaneProperty ) + { + this->TexturePlaneProperty = vtkProperty::New(); + this->TexturePlaneProperty->SetAmbient(1); + this->TexturePlaneProperty->SetInterpolationToFlat(); + } +} + +void vtkImagePlaneWidget::PlaceWidget(double bds[6]) +{ + double bounds[6], center[3]; + + this->AdjustBounds(bds, bounds, center); + + if ( this->PlaneOrientation == 1 ) + { + this->PlaneSource->SetOrigin(bounds[0],center[1],bounds[4]); + this->PlaneSource->SetPoint1(bounds[1],center[1],bounds[4]); + this->PlaneSource->SetPoint2(bounds[0],center[1],bounds[5]); + } + else if ( this->PlaneOrientation == 2 ) + { + this->PlaneSource->SetOrigin(bounds[0],bounds[2],center[2]); + this->PlaneSource->SetPoint1(bounds[1],bounds[2],center[2]); + this->PlaneSource->SetPoint2(bounds[0],bounds[3],center[2]); + } + else //default or x-normal + { + this->PlaneSource->SetOrigin(center[0],bounds[2],bounds[4]); + this->PlaneSource->SetPoint1(center[0],bounds[3],bounds[4]); + this->PlaneSource->SetPoint2(center[0],bounds[2],bounds[5]); + } + + this->UpdatePlane(); + this->BuildRepresentation(); +} + +void vtkImagePlaneWidget::SetPlaneOrientation(int i) +{ + // Generate a XY plane if i = 2, z-normal + // or a YZ plane if i = 0, x-normal + // or a ZX plane if i = 1, y-normal + // + this->PlaneOrientation = i; + + // This method must be called _after_ SetInput + // + this->ImageData = vtkImageData::SafeDownCast(this->Reslice->GetInput()); + if ( !this->ImageData ) + { + vtkErrorMacro(<<"SetInput() before setting plane orientation."); + return; + } + + this->ImageData->UpdateInformation(); + int extent[6]; + this->ImageData->GetWholeExtent(extent); + double origin[3]; + this->ImageData->GetOrigin(origin); + double spacing[3]; + this->ImageData->GetSpacing(spacing); + + // Prevent obscuring voxels by offsetting the plane geometry + // + double xbounds[] = {origin[0] + spacing[0] * (extent[0] - 0.5), + origin[0] + spacing[0] * (extent[1] + 0.5)}; + double ybounds[] = {origin[1] + spacing[1] * (extent[2] - 0.5), + origin[1] + spacing[1] * (extent[3] + 0.5)}; + double zbounds[] = {origin[2] + spacing[2] * (extent[4] - 0.5), + origin[2] + spacing[2] * (extent[5] + 0.5)}; + + if ( spacing[0] < 0.0 ) + { + double t = xbounds[0]; + xbounds[0] = xbounds[1]; + xbounds[1] = t; + } + if ( spacing[1] < 0.0 ) + { + double t = ybounds[0]; + ybounds[0] = ybounds[1]; + ybounds[1] = t; + } + if ( spacing[2] < 0.0 ) + { + double t = zbounds[0]; + zbounds[0] = zbounds[1]; + zbounds[1] = t; + } + + if ( i == 2 ) //XY, z-normal + { + this->PlaneSource->SetOrigin(xbounds[0],ybounds[0],zbounds[0]); + this->PlaneSource->SetPoint1(xbounds[1],ybounds[0],zbounds[0]); + this->PlaneSource->SetPoint2(xbounds[0],ybounds[1],zbounds[0]); + } + else if ( i == 0 ) //YZ, x-normal + { + this->PlaneSource->SetOrigin(xbounds[0],ybounds[0],zbounds[0]); + this->PlaneSource->SetPoint1(xbounds[0],ybounds[1],zbounds[0]); + this->PlaneSource->SetPoint2(xbounds[0],ybounds[0],zbounds[1]); + } + else //ZX, y-normal + { + this->PlaneSource->SetOrigin(xbounds[0],ybounds[0],zbounds[0]); + this->PlaneSource->SetPoint1(xbounds[0],ybounds[0],zbounds[1]); + this->PlaneSource->SetPoint2(xbounds[1],ybounds[0],zbounds[0]); + } + + this->UpdatePlane(); + this->BuildRepresentation(); + this->Modified(); +} + +void vtkImagePlaneWidget::SetInput(vtkDataSet* input) +{ + this->Superclass::SetInput(input); + this->ImageData = vtkImageData::SafeDownCast(this->GetInput()); + + if( !this->ImageData ) + { + // If NULL is passed, remove any reference that Reslice had + // on the old ImageData + // + this->Reslice->SetInput(NULL); + return; + } + + double range[2]; + this->ImageData->GetScalarRange(range); + + if ( !this->UserControlledLookupTable ) + { + this->LookupTable->SetTableRange(range[0],range[1]); + this->LookupTable->Build(); + } + + this->OriginalWindow = range[1] - range[0]; + this->OriginalLevel = 0.5*(range[0] + range[1]); + + this->Reslice->SetInput(this->ImageData); + int interpolate = this->ResliceInterpolate; + this->ResliceInterpolate = -1; // Force change + this->SetResliceInterpolate(interpolate); + + this->ColorMap->SetInput(this->Reslice->GetOutput()); + + this->Texture->SetInput(this->ColorMap->GetOutput()); + this->Texture->SetInterpolate(this->TextureInterpolate); + + this->SetPlaneOrientation(this->PlaneOrientation); +} + +void vtkImagePlaneWidget::UpdatePlane() +{ + if ( !this->Reslice || \ + !(this->ImageData = vtkImageData::SafeDownCast(this->Reslice->GetInput())) ) + { + return; + } + + // Calculate appropriate pixel spacing for the reslicing + // + this->ImageData->UpdateInformation(); + double spacing[3]; + this->ImageData->GetSpacing(spacing); + + int i; + + if ( this->RestrictPlaneToVolume ) + { + double origin[3]; + this->ImageData->GetOrigin(origin); + int extent[6]; + this->ImageData->GetWholeExtent(extent); + double bounds[] = {origin[0] + spacing[0]*extent[0], //xmin + origin[0] + spacing[0]*extent[1], //xmax + origin[1] + spacing[1]*extent[2], //ymin + origin[1] + spacing[1]*extent[3], //ymax + origin[2] + spacing[2]*extent[4], //zmin + origin[2] + spacing[2]*extent[5]};//zmax + + for ( i = 0; i <= 4; i += 2 ) // reverse bounds if necessary + { + if ( bounds[i] > bounds[i+1] ) + { + double t = bounds[i+1]; + bounds[i+1] = bounds[i]; + bounds[i] = t; + } + } + + double abs_normal[3]; + this->PlaneSource->GetNormal(abs_normal); + double planeCenter[3]; + this->PlaneSource->GetCenter(planeCenter); + double nmax = 0.0; + int k = 0; + for ( i = 0; i < 3; i++ ) + { + abs_normal[i] = fabs(abs_normal[i]); + if ( abs_normal[i]>nmax ) + { + nmax = abs_normal[i]; + k = i; + } + } + // Force the plane to lie within the true image bounds along its normal + // + if ( planeCenter[k] > bounds[2*k+1] ) + { + planeCenter[k] = bounds[2*k+1]; + } + else if ( planeCenter[k] < bounds[2*k] ) + { + planeCenter[k] = bounds[2*k]; + } + + this->PlaneSource->SetCenter(planeCenter); + } + + double planeAxis1[3]; + double planeAxis2[3]; + + this->GetVector1(planeAxis1); + this->GetVector2(planeAxis2); + + // The x,y dimensions of the plane + // + double planeSizeX = vtkMath::Normalize(planeAxis1); + double planeSizeY = vtkMath::Normalize(planeAxis2); + + double normal[3]; + this->PlaneSource->GetNormal(normal); + + // Generate the slicing matrix + // + + this->ResliceAxes->Identity(); + for ( i = 0; i < 3; i++ ) + { + this->ResliceAxes->SetElement(0,i,planeAxis1[i]); + this->ResliceAxes->SetElement(1,i,planeAxis2[i]); + this->ResliceAxes->SetElement(2,i,normal[i]); + } + + double planeOrigin[4]; + this->PlaneSource->GetOrigin(planeOrigin); + + planeOrigin[3] = 1.0; + double originXYZW[4]; + this->ResliceAxes->MultiplyPoint(planeOrigin, originXYZW); + + this->ResliceAxes->Transpose(); + double neworiginXYZW[4]; + this->ResliceAxes->MultiplyPoint(originXYZW, neworiginXYZW); + + this->ResliceAxes->SetElement(0,3,neworiginXYZW[0]); + this->ResliceAxes->SetElement(1,3,neworiginXYZW[1]); + this->ResliceAxes->SetElement(2,3,neworiginXYZW[2]); + + this->Reslice->SetResliceAxes(this->ResliceAxes); + + double spacingX = fabs(planeAxis1[0]*spacing[0])+\ + fabs(planeAxis1[1]*spacing[1])+\ + fabs(planeAxis1[2]*spacing[2]); + + double spacingY = fabs(planeAxis2[0]*spacing[0])+\ + fabs(planeAxis2[1]*spacing[1])+\ + fabs(planeAxis2[2]*spacing[2]); + + + // Pad extent up to a power of two for efficient texture mapping + + // make sure we're working with valid values + double realExtentX = ( spacingX == 0 ) ? 0 : planeSizeX / spacingX; + + int extentX; + // Sanity check the input data: + // * if realExtentX is too large, extentX will wrap + // * if spacingX is 0, things will blow up. + // * if realExtentX is naturally 0 or < 0, the padding will yield an + // extentX of 1, which is also not desirable if the input data is invalid. + if (realExtentX > (VTK_INT_MAX >> 1) || realExtentX < 1) + { + vtkErrorMacro(<<"Invalid X extent. Perhaps the input data is empty?"); + extentX = 0; + } + else + { + extentX = 1; + while (extentX < realExtentX) + { + extentX = extentX << 1; + } + } + + // make sure extentY doesn't wrap during padding + double realExtentY = ( spacingY == 0 ) ? 0 : planeSizeY / spacingY; + + int extentY; + if (realExtentY > (VTK_INT_MAX >> 1) || realExtentY < 1) + { + vtkErrorMacro(<<"Invalid Y extent. Perhaps the input data is empty?"); + extentY = 0; + } + else + { + extentY = 1; + while (extentY < realExtentY) + { + extentY = extentY << 1; + } + } + + double outputSpacingX = planeSizeX/extentX; + double outputSpacingY = planeSizeY/extentY; + this->Reslice->SetOutputSpacing(outputSpacingX, outputSpacingY, 1); + this->Reslice->SetOutputOrigin(0.5*outputSpacingX, 0.5*outputSpacingY, 0); + this->Reslice->SetOutputExtent(0, extentX-1, 0, extentY-1, 0, 0); +} + +vtkImageData* vtkImagePlaneWidget::GetResliceOutput() +{ + if ( ! this->Reslice ) + { + return 0; + } + return this->Reslice->GetOutput(); +} + +void vtkImagePlaneWidget::SetResliceInterpolate(int i) +{ + if ( this->ResliceInterpolate == i ) + { + return; + } + this->ResliceInterpolate = i; + this->Modified(); + + if ( !this->Reslice ) + { + return; + } + + if ( i == VTK_NEAREST_RESLICE ) + { + this->Reslice->SetInterpolationModeToNearestNeighbor(); + } + else if ( i == VTK_LINEAR_RESLICE) + { + this->Reslice->SetInterpolationModeToLinear(); + } + else + { + this->Reslice->SetInterpolationModeToCubic(); + } + this->Texture->SetInterpolate(this->TextureInterpolate); +} + +void vtkImagePlaneWidget::SetPicker(vtkCellPicker* picker) +{ + if (this->PlanePicker != picker) + { + // to avoid destructor recursion + vtkCellPicker *temp = this->PlanePicker; + this->PlanePicker = picker; + if (temp != 0) + { + temp->UnRegister(this); + } + if (this->PlanePicker != 0) + { + this->PlanePicker->Register(this); + this->PlanePicker->SetTolerance(0.005); //need some fluff + this->PlanePicker->AddPickList(this->TexturePlaneActor); + this->PlanePicker->PickFromListOn(); + } + } +} + +vtkLookupTable* vtkImagePlaneWidget::CreateDefaultLookupTable() +{ + vtkLookupTable* lut = vtkLookupTable::New(); + lut->Register(this); + lut->Delete(); + lut->SetNumberOfColors( 256); + lut->SetHueRange( 0, 0); + lut->SetSaturationRange( 0, 0); + lut->SetValueRange( 0 ,1); + lut->SetAlphaRange( 1, 1); + lut->Build(); + return lut; +} + +void vtkImagePlaneWidget::SetLookupTable(vtkLookupTable* table) +{ + if (this->LookupTable != table) + { + // to avoid destructor recursion + vtkLookupTable *temp = this->LookupTable; + this->LookupTable = table; + if (temp != 0) + { + temp->UnRegister(this); + } + if (this->LookupTable != 0) + { + this->LookupTable->Register(this); + } + else //create a default lut + { + this->LookupTable = this->CreateDefaultLookupTable(); + } + } + + this->ColorMap->SetLookupTable(this->LookupTable); + this->Texture->SetLookupTable(this->LookupTable); + + if( this->ImageData && !this->UserControlledLookupTable) + { + double range[2]; + this->ImageData->GetScalarRange(range); + + this->LookupTable->SetTableRange(range[0],range[1]); + this->LookupTable->Build(); + + this->OriginalWindow = range[1] - range[0]; + this->OriginalLevel = 0.5*(range[0] + range[1]); + } +} + +void vtkImagePlaneWidget::SetSlicePosition(double position) +{ + double amount = 0.0; + double planeOrigin[3]; + this->PlaneSource->GetOrigin( planeOrigin ); + + if ( this->PlaneOrientation == 2 ) // z axis + { + amount = position - planeOrigin[2]; + } + else if ( this->PlaneOrientation == 0 ) // x axis + { + amount = position - planeOrigin[0]; + } + else if ( this->PlaneOrientation == 1 ) //y axis + { + amount = position - planeOrigin[1]; + } + else + { + vtkGenericWarningMacro("only works for ortho planes: set plane orientation first"); + return; + } + + this->PlaneSource->Push( amount ); + this->UpdatePlane(); + this->BuildRepresentation(); + this->Modified(); +} + +double vtkImagePlaneWidget::GetSlicePosition() +{ + double planeOrigin[3]; + this->PlaneSource->GetOrigin( planeOrigin); + + if ( this->PlaneOrientation == 2 ) + { + return planeOrigin[2]; + } + else if ( this->PlaneOrientation == 1 ) + { + return planeOrigin[1]; + } + else if ( this->PlaneOrientation == 0 ) + { + return planeOrigin[0]; + } + else + { + vtkGenericWarningMacro("only works for ortho planes: set plane orientation first"); + } + + return 0.0; +} + +void vtkImagePlaneWidget::SetSliceIndex(int index) +{ + if ( !this->Reslice ) + { + return; + } + this->ImageData = vtkImageData::SafeDownCast(this->Reslice->GetInput()); + if ( !this->ImageData ) + { + return; + } + this->ImageData->UpdateInformation(); + double origin[3]; + this->ImageData->GetOrigin(origin); + double spacing[3]; + this->ImageData->GetSpacing(spacing); + double planeOrigin[3]; + this->PlaneSource->GetOrigin(planeOrigin); + double pt1[3]; + this->PlaneSource->GetPoint1(pt1); + double pt2[3]; + this->PlaneSource->GetPoint2(pt2); + + if ( this->PlaneOrientation == 2 ) + { + planeOrigin[2] = origin[2] + index*spacing[2]; + pt1[2] = planeOrigin[2]; + pt2[2] = planeOrigin[2]; + } + else if ( this->PlaneOrientation == 1 ) + { + planeOrigin[1] = origin[1] + index*spacing[1]; + pt1[1] = planeOrigin[1]; + pt2[1] = planeOrigin[1]; + } + else if ( this->PlaneOrientation == 0 ) + { + planeOrigin[0] = origin[0] + index*spacing[0]; + pt1[0] = planeOrigin[0]; + pt2[0] = planeOrigin[0]; + } + else + { + vtkGenericWarningMacro("only works for ortho planes: set plane orientation first"); + return; + } + + this->PlaneSource->SetOrigin(planeOrigin); + this->PlaneSource->SetPoint1(pt1); + this->PlaneSource->SetPoint2(pt2); + this->UpdatePlane(); + this->BuildRepresentation(); + this->Modified(); +} + +int vtkImagePlaneWidget::GetSliceIndex() +{ + if ( ! this->Reslice ) + { + return 0; + } + this->ImageData = vtkImageData::SafeDownCast(this->Reslice->GetInput()); + if ( ! this->ImageData ) + { + return 0; + } + this->ImageData->UpdateInformation(); + double origin[3]; + this->ImageData->GetOrigin(origin); + double spacing[3]; + this->ImageData->GetSpacing(spacing); + double planeOrigin[3]; + this->PlaneSource->GetOrigin(planeOrigin); + + if ( this->PlaneOrientation == 2 ) + { + return vtkMath::Round((planeOrigin[2]-origin[2])/spacing[2]); + } + else if ( this->PlaneOrientation == 1 ) + { + return vtkMath::Round((planeOrigin[1]-origin[1])/spacing[1]); + } + else if ( this->PlaneOrientation == 0 ) + { + return vtkMath::Round((planeOrigin[0]-origin[0])/spacing[0]); + } + else + { + vtkGenericWarningMacro("only works for ortho planes: set plane orientation first"); + } + + return 0; +} + +void vtkImagePlaneWidget::ActivateCursor(int i) +{ + + if( !this->CurrentRenderer ) + { + return; + } + + if( i == 0 ) + { + this->CursorActor->VisibilityOff(); + } + else + { + this->CursorActor->VisibilityOn(); + } +} + +void vtkImagePlaneWidget::ActivateMargins(int i) +{ + + if( !this->CurrentRenderer ) + { + return; + } + + if( i == 0 ) + { + this->MarginActor->VisibilityOff(); + } + else + { + this->MarginActor->VisibilityOn(); + } +} + +void vtkImagePlaneWidget::ActivateText(int i) +{ + if( !this->CurrentRenderer || !this->DisplayText) + { + return; + } + + if( i == 0 ) + { + this->TextActor->VisibilityOff(); + } + else + { + this->TextActor->VisibilityOn(); + } +} + +void vtkImagePlaneWidget::UpdateCursor(int X, int Y ) +{ + this->ImageData = vtkImageData::SafeDownCast(this->Reslice->GetInput()); + if ( !this->ImageData ) + { + return; + } + // We're going to be extracting values with GetScalarComponentAsDouble(), + // we might as well make sure that the data is there. If the data is + // up to date already, this call doesn't cost very much. If we don't make + // this call and the data is not up to date, the GetScalar... call will + // cause a segfault. + this->ImageData->Update(); + + vtkAssemblyPath *path; + this->PlanePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->PlanePicker->GetPath(); + this->CurrentImageValue = VTK_DOUBLE_MAX; + + int found = 0; + int i; + if ( path ) + { + // Deal with the possibility that we may be using a shared picker + vtkCollectionSimpleIterator sit; + path->InitTraversal(sit); + vtkAssemblyNode *node; + for ( i = 0; i< path->GetNumberOfItems() && !found ; i++ ) + { + node = path->GetNextNode(sit); + if ( node->GetViewProp() == vtkProp::SafeDownCast(this->TexturePlaneActor) ) + { + found = 1; + } + } + } + + if( !found || path == 0 ) + { + this->CursorActor->VisibilityOff(); + return; + } + else + { + this->CursorActor->VisibilityOn(); + } + + double q[3]; + this->PlanePicker->GetPickPosition(q); + + if(this->UseContinuousCursor) + { + found = this->UpdateContinuousCursor(q); + } + else + { + found = this->UpdateDiscreteCursor(q); + } + + if(!found) + { + this->CursorActor->VisibilityOff(); + return; + } + + double o[3]; + this->PlaneSource->GetOrigin(o); + + // q relative to the plane origin + // + double qro[3]; + qro[0]= q[0] - o[0]; + qro[1]= q[1] - o[1]; + qro[2]= q[2] - o[2]; + + double p1o[3]; + double p2o[3]; + + this->GetVector1(p1o); + this->GetVector2(p2o); + + double Lp1 = vtkMath::Dot(qro,p1o)/vtkMath::Dot(p1o,p1o); + double Lp2 = vtkMath::Dot(qro,p2o)/vtkMath::Dot(p2o,p2o); + + double p1[3]; + this->PlaneSource->GetPoint1(p1); + double p2[3]; + this->PlaneSource->GetPoint2(p2); + + double a[3]; + double b[3]; + double c[3]; + double d[3]; + + for (i = 0; i < 3; i++) + { + a[i] = o[i] + Lp2*p2o[i]; // left + b[i] = p1[i] + Lp2*p2o[i]; // right + c[i] = o[i] + Lp1*p1o[i]; // bottom + d[i] = p2[i] + Lp1*p1o[i]; // top + } + + vtkPoints* cursorPts = this->CursorPolyData->GetPoints(); + + cursorPts->SetPoint(0,a); + cursorPts->SetPoint(1,b); + cursorPts->SetPoint(2,c); + cursorPts->SetPoint(3,d); + + this->CursorPolyData->Modified(); +} + +int vtkImagePlaneWidget::UpdateContinuousCursor(double *q) +{ + double tol2; + vtkCell *cell; + vtkPointData *pd; + int subId; + double pcoords[3], weights[8]; + + this->CurrentCursorPosition[0] = q[0]; + this->CurrentCursorPosition[1] = q[1]; + this->CurrentCursorPosition[2] = q[2]; + + pd = this->ImageData->GetPointData(); + + vtkPointData* outPD = vtkPointData::New(); + outPD->InterpolateAllocate(pd, 1, 1); + + // Use tolerance as a function of size of source data + // + tol2 = this->ImageData->GetLength(); + tol2 = tol2 ? tol2*tol2 / 1000.0 : 0.001; + + // Find the cell that contains q and get it + // + cell = this->ImageData->FindAndGetCell(q,NULL,-1,tol2,subId,pcoords,weights); + int found = 0; + if (cell) + { + // Interpolate the point data + // + outPD->InterpolatePoint(pd,0,cell->PointIds,weights); + this->CurrentImageValue = outPD->GetScalars()->GetTuple1(0); + found = 1; + } + + outPD->Delete(); + return found; +} + +int vtkImagePlaneWidget::UpdateDiscreteCursor(double *q) +{ + // vtkImageData will find the nearest implicit point to q + // + vtkIdType ptId = this->ImageData->FindPoint(q); + + if ( ptId == -1 ) + { + return 0; + } + + double closestPt[3]; + this->ImageData->GetPoint(ptId,closestPt); + + double origin[3]; + this->ImageData->GetOrigin(origin); + double spacing[3]; + this->ImageData->GetSpacing(spacing); + int extent[6]; + this->ImageData->GetExtent(extent); + + int iq[3]; + int iqtemp; + for (int i = 0; i < 3; i++) + { + // compute world to image coords + iqtemp = vtkMath::Round((closestPt[i]-origin[i])/spacing[i]); + + // we have a valid pick already, just enforce bounds check + iq[i] = (iqtemp < extent[2*i])?extent[2*i]:((iqtemp > extent[2*i+1])?extent[2*i+1]:iqtemp); + + // compute image to world coords + q[i] = iq[i]*spacing[i] + origin[i]; + + this->CurrentCursorPosition[i] = iq[i]; + } + + this->CurrentImageValue = this->ImageData->GetScalarComponentAsDouble( \ + static_cast<int>(this->CurrentCursorPosition[0]), + static_cast<int>(this->CurrentCursorPosition[1]), + static_cast<int>(this->CurrentCursorPosition[2]),0); + return 1; +} + +void vtkImagePlaneWidget::SetOrigin(double x, double y, double z) +{ + this->PlaneSource->SetOrigin(x,y,z); + this->Modified(); +} + +void vtkImagePlaneWidget::SetOrigin(double xyz[3]) +{ + this->PlaneSource->SetOrigin(xyz); + this->Modified(); +} + +double* vtkImagePlaneWidget::GetOrigin() +{ + return this->PlaneSource->GetOrigin(); +} + +void vtkImagePlaneWidget::GetOrigin(double xyz[3]) +{ + this->PlaneSource->GetOrigin(xyz); +} + +void vtkImagePlaneWidget::SetPoint1(double x, double y, double z) +{ + this->PlaneSource->SetPoint1(x,y,z); + this->Modified(); +} + +void vtkImagePlaneWidget::SetPoint1(double xyz[3]) +{ + this->PlaneSource->SetPoint1(xyz); + this->Modified(); +} + +double* vtkImagePlaneWidget::GetPoint1() +{ + return this->PlaneSource->GetPoint1(); +} + +void vtkImagePlaneWidget::GetPoint1(double xyz[3]) +{ + this->PlaneSource->GetPoint1(xyz); +} + +void vtkImagePlaneWidget::SetPoint2(double x, double y, double z) +{ + this->PlaneSource->SetPoint2(x,y,z); + this->Modified(); +} + +void vtkImagePlaneWidget::SetPoint2(double xyz[3]) +{ + this->PlaneSource->SetPoint2(xyz); + this->Modified(); +} + +double* vtkImagePlaneWidget::GetPoint2() +{ + return this->PlaneSource->GetPoint2(); +} + +void vtkImagePlaneWidget::GetPoint2(double xyz[3]) +{ + this->PlaneSource->GetPoint2(xyz); +} + +double* vtkImagePlaneWidget::GetCenter() +{ + return this->PlaneSource->GetCenter(); +} + +void vtkImagePlaneWidget::GetCenter(double xyz[3]) +{ + this->PlaneSource->GetCenter(xyz); +} + +double* vtkImagePlaneWidget::GetNormal() +{ + return this->PlaneSource->GetNormal(); +} + +void vtkImagePlaneWidget::GetNormal(double xyz[3]) +{ + this->PlaneSource->GetNormal(xyz); +} + +void vtkImagePlaneWidget::GetPolyData(vtkPolyData *pd) +{ + pd->ShallowCopy(this->PlaneSource->GetOutput()); +} + +vtkPolyDataAlgorithm *vtkImagePlaneWidget::GetPolyDataAlgorithm() +{ + return this->PlaneSource; +} + +void vtkImagePlaneWidget::UpdatePlacement(void) +{ + this->UpdatePlane(); + this->UpdateMargins(); + this->BuildRepresentation(); +} + +void vtkImagePlaneWidget::SetTextProperty(vtkTextProperty* tprop) +{ + this->TextActor->SetTextProperty(tprop); +} + +vtkTextProperty* vtkImagePlaneWidget::GetTextProperty() +{ + return this->TextActor->GetTextProperty(); +} + +vtkTexture* vtkImagePlaneWidget::GetTexture() +{ + return this->Texture; +} + +void vtkImagePlaneWidget::GetVector1(double v1[3]) +{ + double* p1 = this->PlaneSource->GetPoint1(); + double* o = this->PlaneSource->GetOrigin(); + v1[0] = p1[0] - o[0]; + v1[1] = p1[1] - o[1]; + v1[2] = p1[2] - o[2]; +} + +void vtkImagePlaneWidget::GetVector2(double v2[3]) +{ + double* p2 = this->PlaneSource->GetPoint2(); + double* o = this->PlaneSource->GetOrigin(); + v2[0] = p2[0] - o[0]; + v2[1] = p2[1] - o[1]; + v2[2] = p2[2] - o[2]; +} + +void vtkImagePlaneWidget::AdjustState() +{ + int *auto_modifier = NULL; + switch (this->LastButtonPressed) + { + case vtkImagePlaneWidget::LEFT_BUTTON: + auto_modifier = &this->LeftButtonAutoModifier; + break; + case vtkImagePlaneWidget::MIDDLE_BUTTON: + auto_modifier = &this->MiddleButtonAutoModifier; + break; + case vtkImagePlaneWidget::RIGHT_BUTTON: + auto_modifier = &this->RightButtonAutoModifier; + break; + } + + if (this->Interactor->GetShiftKey() || + (auto_modifier && + (*auto_modifier & vtkImagePlaneWidget::SHIFT_MODIFIER))) + { + this->State = vtkImagePlaneWidget::Scaling; + return; + } + + double v1[3]; + this->GetVector1(v1); + double v2[3]; + this->GetVector2(v2); + double planeSize1 = vtkMath::Normalize(v1); + double planeSize2 = vtkMath::Normalize(v2); + double* planeOrigin = this->PlaneSource->GetOrigin(); + + double ppo[3] = {this->LastPickPosition[0] - planeOrigin[0], + this->LastPickPosition[1] - planeOrigin[1], + this->LastPickPosition[2] - planeOrigin[2] }; + + double x2D = vtkMath::Dot(ppo,v1); + double y2D = vtkMath::Dot(ppo,v2); + + // Divide plane into three zones for different user interactions: + // four corners -- spin around the plane's normal at its center + // four edges -- rotate around one of the plane's axes at its center + // center area -- push + // + double marginX = planeSize1 * 0.05; + double marginY = planeSize2 * 0.05; + + double x0 = marginX; + double y0 = marginY; + double x1 = planeSize1 - marginX; + double y1 = planeSize2 - marginY; + + if ( x2D < x0 ) // left margin + { + if (y2D < y0) // bottom left corner + { + this->MarginSelectMode = 0; + } + else if (y2D > y1) // top left corner + { + this->MarginSelectMode = 3; + } + else // left edge + { + this->MarginSelectMode = 4; + } + } + else if ( x2D > x1 ) // right margin + { + if (y2D < y0) // bottom right corner + { + this->MarginSelectMode = 1; + } + else if (y2D > y1) // top right corner + { + this->MarginSelectMode = 2; + } + else // right edge + { + this->MarginSelectMode = 5; + } + } + else // middle + { + if (y2D < y0) // bottom edge + { + this->MarginSelectMode = 6; + } + else if (y2D > y1) // top edge + { + this->MarginSelectMode = 7; + } + else // central area + { + this->MarginSelectMode = 8; + } + } + + if (this->Interactor->GetControlKey() || + (auto_modifier && + (*auto_modifier & vtkImagePlaneWidget::CONTROL_MODIFIER))) + { + this->State = vtkImagePlaneWidget::Moving; + } + else + { + if (this->MarginSelectMode >= 0 && this->MarginSelectMode < 4) + { + this->State = vtkImagePlaneWidget::Spinning; + return; + } + else if (this->MarginSelectMode == 8) + { + this->State = vtkImagePlaneWidget::Pushing; + return; + } + else + { + this->State = vtkImagePlaneWidget::Rotating; + } + } + + double *raPtr = 0; + double *rvPtr = 0; + double rvfac = 1.0; + double rafac = 1.0; + + switch ( this->MarginSelectMode ) + { + // left bottom corner + case 0: raPtr = v2; rvPtr = v1; rvfac = -1.0; rafac = -1.0; break; + // right bottom corner + case 1: raPtr = v2; rvPtr = v1; rafac = -1.0; break; + // right top corner + case 2: raPtr = v2; rvPtr = v1; break; + // left top corner + case 3: raPtr = v2; rvPtr = v1; rvfac = -1.0; break; + case 4: raPtr = v2; rvPtr = v1; rvfac = -1.0; break; // left + case 5: raPtr = v2; rvPtr = v1; break; // right + case 6: raPtr = v1; rvPtr = v2; rvfac = -1.0; break; // bottom + case 7: raPtr = v1; rvPtr = v2; break; // top + default: raPtr = v1; rvPtr = v2; break; + } + + for (int i = 0; i < 3; i++) + { + this->RotateAxis[i] = *raPtr++ * rafac; + this->RadiusVector[i] = *rvPtr++ * rvfac; + } +} + +void vtkImagePlaneWidget::Spin(double *p1, double *p2) +{ + // Disable cursor snap + // + this->PlaneOrientation = 3; + + // Get the motion vector, in world coords + // + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Plane center and normal before transform + // + double* wc = this->PlaneSource->GetCenter(); + double* wn = this->PlaneSource->GetNormal(); + + // Radius vector from center to cursor position + // + double rv[3] = {p2[0]-wc[0], p2[1]-wc[1], p2[2]-wc[2]}; + + // Distance between center and cursor location + // + double rs = vtkMath::Normalize(rv); + + // Spin direction + // + double wn_cross_rv[3]; + vtkMath::Cross(wn,rv,wn_cross_rv); + + // Spin angle + // + double dw = vtkMath::RadiansToDegrees() * vtkMath::Dot(v,wn_cross_rv) / rs; + + this->Transform->Identity(); + this->Transform->Translate(wc[0],wc[1],wc[2]); + this->Transform->RotateWXYZ(dw,wn); + this->Transform->Translate(-wc[0],-wc[1],-wc[2]); + + double newpt[3]; + this->Transform->TransformPoint(this->PlaneSource->GetPoint1(),newpt); + this->PlaneSource->SetPoint1(newpt); + this->Transform->TransformPoint(this->PlaneSource->GetPoint2(),newpt); + this->PlaneSource->SetPoint2(newpt); + this->Transform->TransformPoint(this->PlaneSource->GetOrigin(),newpt); + this->PlaneSource->SetOrigin(newpt); +} + +void vtkImagePlaneWidget::Rotate(double *p1, double *p2, double *vpn) +{ + // Disable cursor snap + // + this->PlaneOrientation = 3; + + // Get the motion vector, in world coords + // + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Plane center and normal + // + double* wc = this->PlaneSource->GetCenter(); + + // Radius of the rotating circle of the picked point + // + double radius = fabs( this->RadiusVector[0]*(p2[0]-wc[0]) + + this->RadiusVector[1]*(p2[1]-wc[1]) + + this->RadiusVector[2]*(p2[2]-wc[2]) ); + + // Rotate direction ra_cross_rv + // + double rd[3]; + vtkMath::Cross(this->RotateAxis,this->RadiusVector,rd); + + // Direction cosin between rotating direction and view normal + // + double rd_dot_vpn = rd[0]*vpn[0] + rd[1]*vpn[1] + rd[2]*vpn[2]; + + // 'push' plane edge when mouse moves away from plane center + // 'pull' plane edge when mouse moves toward plane center + // + double dw = vtkMath::RadiansToDegrees() * (vtkMath::Dot(this->RadiusVector,v))/radius * (-rd_dot_vpn); + + this->Transform->Identity(); + this->Transform->Translate(wc[0],wc[1],wc[2]); + this->Transform->RotateWXYZ(dw,this->RotateAxis); + this->Transform->Translate(-wc[0],-wc[1],-wc[2]); + + double newpt[3]; + this->Transform->TransformPoint(this->PlaneSource->GetPoint1(),newpt); + this->PlaneSource->SetPoint1(newpt); + this->Transform->TransformPoint(this->PlaneSource->GetPoint2(),newpt); + this->PlaneSource->SetPoint2(newpt); + this->Transform->TransformPoint(this->PlaneSource->GetOrigin(),newpt); + this->PlaneSource->SetOrigin(newpt); +} + +void vtkImagePlaneWidget::GeneratePlaneOutline() +{ + vtkPoints* points = vtkPoints::New(VTK_DOUBLE); + points->SetNumberOfPoints(4); + int i; + for (i = 0; i < 4; i++) + { + points->SetPoint(i,0.0,0.0,0.0); + } + + vtkCellArray *cells = vtkCellArray::New(); + cells->Allocate(cells->EstimateSize(4,2)); + vtkIdType pts[2]; + pts[0] = 3; pts[1] = 2; // top edge + cells->InsertNextCell(2,pts); + pts[0] = 0; pts[1] = 1; // bottom edge + cells->InsertNextCell(2,pts); + pts[0] = 0; pts[1] = 3; // left edge + cells->InsertNextCell(2,pts); + pts[0] = 1; pts[1] = 2; // right edge + cells->InsertNextCell(2,pts); + + this->PlaneOutlinePolyData->SetPoints(points); + points->Delete(); + this->PlaneOutlinePolyData->SetLines(cells); + cells->Delete(); + + vtkPolyDataMapper* planeOutlineMapper = vtkPolyDataMapper::New(); + planeOutlineMapper->SetInput( this->PlaneOutlinePolyData ); + planeOutlineMapper->SetResolveCoincidentTopologyToPolygonOffset(); + this->PlaneOutlineActor->SetMapper(planeOutlineMapper); + this->PlaneOutlineActor->PickableOff(); + planeOutlineMapper->Delete(); +} + +void vtkImagePlaneWidget::GenerateTexturePlane() +{ + this->SetResliceInterpolate(this->ResliceInterpolate); + + this->LookupTable = this->CreateDefaultLookupTable(); + + this->ColorMap->SetLookupTable(this->LookupTable); + this->ColorMap->SetOutputFormatToRGBA(); + this->ColorMap->PassAlphaToOutputOn(); + + vtkPolyDataMapper* texturePlaneMapper = vtkPolyDataMapper::New(); + texturePlaneMapper->SetInput( + vtkPolyData::SafeDownCast(this->PlaneSource->GetOutput())); + + this->Texture->SetQualityTo32Bit(); + this->Texture->MapColorScalarsThroughLookupTableOff(); + this->Texture->SetInterpolate(this->TextureInterpolate); + this->Texture->RepeatOff(); + this->Texture->SetLookupTable(this->LookupTable); + + this->TexturePlaneActor->SetMapper(texturePlaneMapper); + this->TexturePlaneActor->SetTexture(this->Texture); + this->TexturePlaneActor->PickableOn(); + texturePlaneMapper->Delete(); +} + +void vtkImagePlaneWidget::GenerateMargins() +{ + // Construct initial points + vtkPoints* points = vtkPoints::New(VTK_DOUBLE); + points->SetNumberOfPoints(8); + int i; + for (i = 0; i < 8; i++) + { + points->SetPoint(i,0.0,0.0,0.0); + } + + vtkCellArray *cells = vtkCellArray::New(); + cells->Allocate(cells->EstimateSize(4,2)); + vtkIdType pts[2]; + pts[0] = 0; pts[1] = 1; // top margin + cells->InsertNextCell(2,pts); + pts[0] = 2; pts[1] = 3; // bottom margin + cells->InsertNextCell(2,pts); + pts[0] = 4; pts[1] = 5; // left margin + cells->InsertNextCell(2,pts); + pts[0] = 6; pts[1] = 7; // right margin + cells->InsertNextCell(2,pts); + + this->MarginPolyData->SetPoints(points); + points->Delete(); + this->MarginPolyData->SetLines(cells); + cells->Delete(); + + vtkPolyDataMapper* marginMapper = vtkPolyDataMapper::New(); + marginMapper->SetInput(this->MarginPolyData); + marginMapper->SetResolveCoincidentTopologyToPolygonOffset(); + this->MarginActor->SetMapper(marginMapper); + this->MarginActor->PickableOff(); + this->MarginActor->VisibilityOff(); + marginMapper->Delete(); +} + +void vtkImagePlaneWidget::GenerateCursor() +{ + // Construct initial points + // + vtkPoints* points = vtkPoints::New(VTK_DOUBLE); + points->SetNumberOfPoints(4); + int i; + for (i = 0; i < 4; i++) + { + points->SetPoint(i,0.0,0.0,0.0); + } + + vtkCellArray *cells = vtkCellArray::New(); + cells->Allocate(cells->EstimateSize(2,2)); + vtkIdType pts[2]; + pts[0] = 0; pts[1] = 1; // horizontal segment + cells->InsertNextCell(2,pts); + pts[0] = 2; pts[1] = 3; // vertical segment + cells->InsertNextCell(2,pts); + + this->CursorPolyData->SetPoints(points); + points->Delete(); + this->CursorPolyData->SetLines(cells); + cells->Delete(); + + vtkPolyDataMapper* cursorMapper = vtkPolyDataMapper::New(); + cursorMapper->SetInput(this->CursorPolyData); + cursorMapper->SetResolveCoincidentTopologyToPolygonOffset(); + this->CursorActor->SetMapper(cursorMapper); + this->CursorActor->PickableOff(); + this->CursorActor->VisibilityOff(); + cursorMapper->Delete(); +} + +void vtkImagePlaneWidget::GenerateText() +{ + sprintf(this->TextBuff,"NA"); + this->TextActor->SetInput(this->TextBuff); + this->TextActor->ScaledTextOff(); + + vtkTextProperty* textprop = this->TextActor->GetTextProperty(); + textprop->SetColor(1,1,1); + textprop->SetFontFamilyToArial(); + textprop->SetFontSize(18); + textprop->BoldOff(); + textprop->ItalicOff(); + textprop->ShadowOff(); + textprop->SetJustificationToLeft(); + textprop->SetVerticalJustificationToBottom(); + + vtkCoordinate* coord = this->TextActor->GetPositionCoordinate(); + coord->SetCoordinateSystemToNormalizedViewport(); + coord->SetValue(.01, .01); + + this->TextActor->VisibilityOff(); +} + +void vtkImagePlaneWidget::UpdateMargins() +{ + double v1[3]; + this->GetVector1(v1); + double v2[3]; + this->GetVector2(v2); + double o[3]; + this->PlaneSource->GetOrigin(o); + double p1[3]; + this->PlaneSource->GetPoint1(p1); + double p2[3]; + this->PlaneSource->GetPoint2(p2); + + double a[3]; + double b[3]; + double c[3]; + double d[3]; + + double s = 0.05; + double t = 0.05; + + int i; + for ( i = 0; i < 3; i++) + { + a[i] = o[i] + v2[i]*(1-t); + b[i] = p1[i] + v2[i]*(1-t); + c[i] = o[i] + v2[i]*t; + d[i] = p1[i] + v2[i]*t; + } + + vtkPoints* marginPts = this->MarginPolyData->GetPoints(); + + marginPts->SetPoint(0,a); + marginPts->SetPoint(1,b); + marginPts->SetPoint(2,c); + marginPts->SetPoint(3,d); + + for ( i = 0; i < 3; i++) + { + a[i] = o[i] + v1[i]*s; + b[i] = p2[i] + v1[i]*s; + c[i] = o[i] + v1[i]*(1-s); + d[i] = p2[i] + v1[i]*(1-s); + } + + marginPts->SetPoint(4,a); + marginPts->SetPoint(5,b); + marginPts->SetPoint(6,c); + marginPts->SetPoint(7,d); + + this->MarginPolyData->Modified(); +} + +void vtkImagePlaneWidget::Translate(double *p1, double *p2) +{ + // Get the motion vector + // + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + double origin[3], point1[3], point2[3]; + + double vdrv = this->RadiusVector[0]*v[0] + \ + this->RadiusVector[1]*v[1] + \ + this->RadiusVector[2]*v[2]; + double vdra = this->RotateAxis[0]*v[0] + \ + this->RotateAxis[1]*v[1] + \ + this->RotateAxis[2]*v[2]; + + int i; + if ( this->MarginSelectMode == 8 ) // everybody comes along + { + for (i=0; i<3; i++) + { + origin[i] = o[i] + v[i]; + point1[i] = pt1[i] + v[i]; + point2[i] = pt2[i] + v[i]; + } + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); + } + else if ( this->MarginSelectMode == 4 ) // left edge + { + for (i=0; i<3; i++) + { + origin[i] = o[i] + vdrv*this->RadiusVector[i]; + point2[i] = pt2[i] + vdrv*this->RadiusVector[i]; + } + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint2(point2); + } + else if ( this->MarginSelectMode == 5 ) // right edge + { + for (i=0; i<3; i++) + { + point1[i] = pt1[i] + vdrv*this->RadiusVector[i]; + } + this->PlaneSource->SetPoint1(point1); + } + else if ( this->MarginSelectMode == 6 ) // bottom edge + { + for (i=0; i<3; i++) + { + origin[i] = o[i] + vdrv*this->RadiusVector[i]; + point1[i] = pt1[i] + vdrv*this->RadiusVector[i]; + } + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + } + else if ( this->MarginSelectMode == 7 ) // top edge + { + for (i=0; i<3; i++) + { + point2[i] = pt2[i] + vdrv*this->RadiusVector[i]; + } + this->PlaneSource->SetPoint2(point2); + } + else if ( this->MarginSelectMode == 3 ) // top left corner + { + for (i=0; i<3; i++) + { + origin[i] = o[i] + vdrv*this->RadiusVector[i]; + point2[i] = pt2[i] + vdrv*this->RadiusVector[i] + + vdra*this->RotateAxis[i]; + } + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint2(point2); + } + else if ( this->MarginSelectMode == 0 ) // bottom left corner + { + for (i=0; i<3; i++) + { + origin[i] = o[i] + vdrv*this->RadiusVector[i] + + vdra*this->RotateAxis[i]; + point1[i] = pt1[i] + vdra*this->RotateAxis[i]; + point2[i] = pt2[i] + vdrv*this->RadiusVector[i]; + } + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); + } + else if ( this->MarginSelectMode == 2 ) // top right corner + { + for (i=0; i<3; i++) + { + point1[i] = pt1[i] + vdrv*this->RadiusVector[i]; + point2[i] = pt2[i] + vdra*this->RotateAxis[i]; + } + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); + } + else // bottom right corner + { + for (i=0; i<3; i++) + { + origin[i] = o[i] + vdra*this->RotateAxis[i]; + point1[i] = pt1[i] + vdrv*this->RadiusVector[i] + + vdra*this->RotateAxis[i]; + } + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetOrigin(origin); + } +} + +void vtkImagePlaneWidget::Scale(double *p1, double *p2, + int vtkNotUsed(X), int Y) +{ + // Get the motion vector + // + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + double* center = this->PlaneSource->GetCenter(); + + // Compute the scale factor + // + double sf = vtkMath::Norm(v) / + sqrt(vtkMath::Distance2BetweenPoints(pt1,pt2)); + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.0 + sf; + } + else + { + sf = 1.0 - sf; + } + + // Move the corner points + // + double origin[3], point1[3], point2[3]; + + for (int i=0; i<3; i++) + { + origin[i] = sf * (o[i] - center[i]) + center[i]; + point1[i] = sf * (pt1[i] - center[i]) + center[i]; + point2[i] = sf * (pt2[i] - center[i]) + center[i]; + } + + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); +} + + diff --git a/Widgets/vtkImagePlaneWidget.h b/Widgets/vtkImagePlaneWidget.h new file mode 100644 index 0000000..4a62580 --- /dev/null +++ b/Widgets/vtkImagePlaneWidget.h @@ -0,0 +1,591 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImagePlaneWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImagePlaneWidget - 3D widget for reslicing image data +// .SECTION Description +// This 3D widget defines a plane that can be interactively placed in an +// image volume. A nice feature of the object is that the +// vtkImagePlaneWidget, like any 3D widget, will work with the current +// interactor style. That is, if vtkImagePlaneWidget does not handle an +// event, then all other registered observers (including the interactor +// style) have an opportunity to process the event. Otherwise, the +// vtkImagePlaneWidget will terminate the processing of the event that it +// handles. +// +// The core functionality of the widget is provided by a vtkImageReslice +// object which passes its output onto a texture mapping pipeline for fast +// slicing through volumetric data. See the key methods: GenerateTexturePlane() +// and UpdatePlane() for implementation details. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. If the "i" key (for +// "interactor") is pressed, the vtkImagePlaneWidget will appear. (See +// superclass documentation for information about changing this behavior.) +// +// Selecting the widget with the middle mouse button with and without holding +// the shift or control keys enables complex reslicing capablilites. +// To facilitate use, a set of 'margins' (left, right, top, bottom) are shown as +// a set of plane-axes aligned lines, the properties of which can be changed +// as a group. +// Without keyboard modifiers: selecting in the middle of the margins +// enables translation of the plane along its normal. Selecting one of the +// corners within the margins enables spinning around the plane's normal at its +// center. Selecting within a margin allows rotating about the center of the +// plane around an axis aligned with the margin (i.e., selecting left margin +// enables rotating around the plane's local y-prime axis). +// With control key modifier: margin selection enables edge translation (i.e., a +// constrained form of scaling). Selecting within the margins enables +// translation of the entire plane. +// With shift key modifier: uniform plane scaling is enabled. Moving the mouse +// up enlarges the plane while downward movement shrinks it. +// +// Window-level is achieved by using the right mouse button. +// The left mouse button can be used to query the underlying image data +// with a snap-to cross-hair cursor. Currently, the nearest point in the input +// image data to the mouse cursor generates the cross-hairs. With oblique +// slicing, this behaviour may appear unsatisfactory. Text display of +// window-level and image coordinates/data values are provided by a text +// actor/mapper pair. +// Events that occur outside of the widget (i.e., no part of the widget is +// picked) are propagated to any other registered obsevers (such as the +// interaction style). Turn off the widget by pressing the "i" key again +// (or invoke the Off() method). +// +// The vtkImagePlaneWidget has several methods that can be used in +// conjunction with other VTK objects. The GetPolyData() method can be used +// to get the polygonal representation of the plane and can be used as input +// for other VTK objects. Typical usage of the widget is to make use of the +// StartInteractionEvent, InteractionEvent, and EndInteractionEvent +// events. The InteractionEvent is called on mouse motion; the other two +// events are called on button down and button up (either left or right +// button). +// +// Some additional features of this class include the ability to control the +// properties of the widget. You can set the properties of: the selected and +// unselected representations of the plane's outline; the text actor via its +// vtkTextProperty; the cross-hair cursor. In addition there are methods to +// constrain the plane so that it is aligned along the x-y-z axes. Finally, +// one can specify the degree of interpolation (vtkImageReslice): nearest +// neighbour, linear, and cubic. + +// .SECTION Thanks +// Thanks to Dean Inglis for developing and contributing this class. +// Based on the Python SlicePlaneFactory from Atamai, Inc. + +// .SECTION Caveats +// Note that handles and plane can be picked even when they are "behind" other +// actors. This is an intended feature and not a bug. + +// .SECTION See Also +// vtk3DWidget vtkBoxWidget vtkLineWidget vtkPlaneWidget vtkPointWidget +// vtkPolyDataSourceWidget vtkSphereWidget vtkImplicitPlaneWidget + + +#ifndef __vtkImagePlaneWidget_h +#define __vtkImagePlaneWidget_h + +#include "vtkPolyDataSourceWidget.h" + +class vtkActor; +class vtkCellPicker; +class vtkDataSetMapper; +class vtkImageData; +class vtkImageMapToColors; +class vtkImageReslice; +class vtkLookupTable; +class vtkMatrix4x4; +class vtkPlaneSource; +class vtkPoints; +class vtkPolyData; +class vtkProperty; +class vtkTextActor; +class vtkTextProperty; +class vtkTexture; +class vtkTransform; + +#define VTK_NEAREST_RESLICE 0 +#define VTK_LINEAR_RESLICE 1 +#define VTK_CUBIC_RESLICE 2 + +class VTK_WIDGETS_EXPORT vtkImagePlaneWidget : public vtkPolyDataSourceWidget +{ +public: + // Description: + // Instantiate the object. + static vtkImagePlaneWidget *New(); + + vtkTypeRevisionMacro(vtkImagePlaneWidget,vtkPolyDataSourceWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Set the vtkImageData* input for the vtkImageReslice. + void SetInput(vtkDataSet* input); + + // Description: + // Set/Get the origin of the plane. + void SetOrigin(double x, double y, double z); + void SetOrigin(double xyz[3]); + double* GetOrigin(); + void GetOrigin(double xyz[3]); + + // Description: + // Set/Get the position of the point defining the first axis of the plane. + void SetPoint1(double x, double y, double z); + void SetPoint1(double xyz[3]); + double* GetPoint1(); + void GetPoint1(double xyz[3]); + + // Description: + // Set/Get the position of the point defining the second axis of the plane. + void SetPoint2(double x, double y, double z); + void SetPoint2(double xyz[3]); + double* GetPoint2(); + void GetPoint2(double xyz[3]); + + // Description: + // Get the center of the plane. + double* GetCenter(); + void GetCenter(double xyz[3]); + + // Description: + // Get the normal to the plane. + double* GetNormal(); + void GetNormal(double xyz[3]); + + // Description: + // Get the vector from the plane origin to point1. + void GetVector1(double v1[3]); + + // Description: + // Get the vector from the plane origin to point2. + void GetVector2(double v2[3]); + + // Description: + // Get the slice position in terms of the data extent. + int GetSliceIndex(); + + // Description: + // Set the slice position in terms of the data extent. + void SetSliceIndex(int index); + + // Description: + // Get the position of the slice along its normal. + double GetSlicePosition(); + + // Description: + // Set the position of the slice along its normal. + void SetSlicePosition(double position); + + // Description: + // Set the interpolation to use when texturing the plane. + void SetResliceInterpolate(int); + vtkGetMacro(ResliceInterpolate,int); + void SetResliceInterpolateToNearestNeighbour() + { this->SetResliceInterpolate(VTK_NEAREST_RESLICE); } + void SetResliceInterpolateToLinear() + { this->SetResliceInterpolate(VTK_LINEAR_RESLICE); } + void SetResliceInterpolateToCubic() + { this->SetResliceInterpolate(VTK_CUBIC_RESLICE); } + + // Description: + // Convenience method to get the vtkImageReslice output. + vtkImageData* GetResliceOutput(); + + // Description: + // Make sure that the plane remains within the volume. + // Default is On. + vtkSetMacro(RestrictPlaneToVolume,int); + vtkGetMacro(RestrictPlaneToVolume,int); + vtkBooleanMacro(RestrictPlaneToVolume,int); + + // Description: + // Let the user control the lookup table. NOTE: apply this method BEFORE + // applying the SetLookupTable method. + // Default is Off. + vtkSetMacro(UserControlledLookupTable,int); + vtkGetMacro(UserControlledLookupTable,int); + vtkBooleanMacro(UserControlledLookupTable,int); + + // Description: + // Specify whether to interpolate the texture or not. When off, the + // reslice interpolation is nearest neighbour regardless of how the + // interpolation is set through the API. Set before setting the + // vtkImageData imput. Default is On. + vtkSetMacro(TextureInterpolate,int); + vtkGetMacro(TextureInterpolate,int); + vtkBooleanMacro(TextureInterpolate,int); + + // Description: + // Control the visibility of the actual texture mapped reformatted plane. + // in some cases you may only want the plane outline for example. + virtual void SetTextureVisibility(int); + vtkGetMacro(TextureVisibility,int); + vtkBooleanMacro(TextureVisibility,int); + + // Description: + // Grab the polydata (including points) that defines the plane. The + // polydata consists of (res+1)*(res+1) points, and res*res quadrilateral + // polygons, where res is the resolution of the plane. These point values + // are guaranteed to be up-to-date when either the InteractionEvent or + // EndInteraction events are invoked. The user provides the vtkPolyData and + // the points and polyplane are added to it. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Satisfies superclass API. This returns a pointer to the underlying + // PolyData. Make changes to this before calling the initial PlaceWidget() + // to have the initial placement follow suit. Or, make changes after the + // widget has been initialised and call UpdatePlacement() to realise. + vtkPolyDataAlgorithm* GetPolyDataAlgorithm(); + + // Description: + // Satisfies superclass API. This will change the state of the widget to + // match changes that have been made to the underlying PolyDataSource + void UpdatePlacement(void); + + // Description: + // Convenience method to get the texture used by this widget. This can be + // used in external slice viewers. + vtkTexture *GetTexture(); + + // Description: + // Convenience method to get the vtkImageMapToColors filter used by this + // widget. The user can properly render other transparent actors in a + // scene by calling the filter's SetOuputFormatToRGB and + // PassAlphaToOutputOff. + vtkGetObjectMacro(ColorMap, vtkImageMapToColors); + virtual void SetColorMap(vtkImageMapToColors *); + + // Description: + // Set/Get the plane's outline properties. The properties of the plane's + // outline when selected and unselected can be manipulated. + virtual void SetPlaneProperty(vtkProperty*); + vtkGetObjectMacro(PlaneProperty,vtkProperty); + virtual void SetSelectedPlaneProperty(vtkProperty*); + vtkGetObjectMacro(SelectedPlaneProperty,vtkProperty); + + // Description: + // Convenience method sets the plane orientation normal to the + // x, y, or z axes. Default is XAxes (0). + void SetPlaneOrientation(int); + vtkGetMacro(PlaneOrientation,int); + void SetPlaneOrientationToXAxes() + { this->SetPlaneOrientation(0); } + void SetPlaneOrientationToYAxes() + { this->SetPlaneOrientation(1); } + void SetPlaneOrientationToZAxes() + { this->SetPlaneOrientation(2); } + + // Description: + // Set the internal picker to one defined by the user. In this way, + // a set of three orthogonal planes can share the same picker so that + // picking is performed correctly. The default internal picker can be + // re-set/allocated by setting to 0 (NULL). + void SetPicker(vtkCellPicker*); + + // Description: + // Set/Get the internal lookuptable (lut) to one defined by the user, or, + // alternatively, to the lut of another vtkImgePlaneWidget. In this way, + // a set of three orthogonal planes can share the same lut so that + // window-levelling is performed uniformly among planes. The default + // internal lut can be re- set/allocated by setting to 0 (NULL). + virtual void SetLookupTable(vtkLookupTable*); + vtkGetObjectMacro(LookupTable,vtkLookupTable); + + // Description: + // Enable/disable text display of window-level, image coords and values in a + // render window. + vtkSetMacro(DisplayText,int); + vtkGetMacro(DisplayText,int); + vtkBooleanMacro(DisplayText,int); + + // Description: + // Set the properties of the cross-hair cursor. + virtual void SetCursorProperty(vtkProperty*); + vtkGetObjectMacro(CursorProperty,vtkProperty); + + // Description: + // Set the properties of the margins. + virtual void SetMarginProperty(vtkProperty*); + vtkGetObjectMacro(MarginProperty,vtkProperty); + + // Description: + // Set/Get the text property for the image data and window-level annotation. + void SetTextProperty(vtkTextProperty* tprop); + vtkTextProperty* GetTextProperty(); + + // Description: + // Set/Get the property for the resliced image. + virtual void SetTexturePlaneProperty(vtkProperty*); + vtkGetObjectMacro(TexturePlaneProperty,vtkProperty); + + // Description: + // Set/Get the current window and level values. Set should + // only be called after SetInput. + void SetWindowLevel(double window, double level); + void GetWindowLevel(double wl[2]); + + // Description: + // Get the image coordinate position and voxel value. Currently only + // supports single component image data. + int GetCursorData(double xyzv[4]); + + // Description: + // Get the status of the cursor data. If this returns 1 the + // CurrentCursorPosition and CurrentImageValue will have current + // data. If it returns 0, these values are invalid. + int GetCursorDataStatus(); + + // Description: + // Get the current cursor position. To be used in conjunction with + // GetCursorDataStatus. + vtkGetVectorMacro(CurrentCursorPosition,double,3); + + // Description: + // Get the current image value at the current cursor position. To + // be used in conjunction with GetCursorDataStatus. The value is + // VTK_DOUBLE_MAX when the data is invalid. + vtkGetMacro(CurrentImageValue,double); + + // Description: + // Choose between voxel centered or continuous cursor probing. With voxel + // centered probing, the cursor snaps to the nearest voxel and the reported + // cursor coordinates are extent based. With continuous probing, voxel data + // is interpolated using vtkDataSetAttributes' InterpolatePoint method and + // the reported coordinates are 3D spacial continuous. + vtkSetMacro(UseContinuousCursor,int); + vtkGetMacro(UseContinuousCursor,int); + vtkBooleanMacro(UseContinuousCursor,int); + + // Description: + // Enable/disable mouse interaction so the widget remains on display. + void SetInteraction(int interact); + vtkGetMacro(Interaction,int); + vtkBooleanMacro(Interaction,int); + + // Description: + // Set action associated to buttons. + //BTX + enum + { + CURSOR_ACTION = 0, + SLICE_MOTION_ACTION = 1, + WINDOW_LEVEL_ACTION = 2 + }; + //ETX + vtkSetClampMacro(LeftButtonAction,int, CURSOR_ACTION, WINDOW_LEVEL_ACTION); + vtkGetMacro(LeftButtonAction, int); + vtkSetClampMacro(MiddleButtonAction,int, CURSOR_ACTION, WINDOW_LEVEL_ACTION); + vtkGetMacro(MiddleButtonAction, int); + vtkSetClampMacro(RightButtonAction,int, CURSOR_ACTION, WINDOW_LEVEL_ACTION); + vtkGetMacro(RightButtonAction, int); + + // Description: + // Set the auto-modifiers associated to buttons. + // This allows users to bind some buttons to actions that are usually + // triggered by a key modifier. For example, if you do not need cursoring, + // you can bind the left button action to SLICE_MOTION_ACTION (see above) + // and the left button auto modifier to CONTROL_MODIFIER: you end up with + // the left button controling panning without pressing a key. + //BTX + enum + { + NO_MODIFIER = 0, + SHIFT_MODIFIER = 1, + CONTROL_MODIFIER = 2 + }; + //ETX + vtkSetClampMacro(LeftButtonAutoModifier,int, NO_MODIFIER, CONTROL_MODIFIER); + vtkGetMacro(LeftButtonAutoModifier, int); + vtkSetClampMacro(MiddleButtonAutoModifier,int, NO_MODIFIER, CONTROL_MODIFIER); + vtkGetMacro(MiddleButtonAutoModifier, int); + vtkSetClampMacro(RightButtonAutoModifier,int, NO_MODIFIER, CONTROL_MODIFIER); + vtkGetMacro(RightButtonAutoModifier, int); + +protected: + vtkImagePlaneWidget(); + ~vtkImagePlaneWidget(); + + int TextureVisibility; + + int LeftButtonAction; + int MiddleButtonAction; + int RightButtonAction; + + int LeftButtonAutoModifier; + int MiddleButtonAutoModifier; + int RightButtonAutoModifier; + + //BTX + enum + { + NO_BUTTON = 0, + LEFT_BUTTON = 1, + MIDDLE_BUTTON = 2, + RIGHT_BUTTON = 3 + }; + //ETX + int LastButtonPressed; + + //BTX - manage the state of the widget + int State; + enum WidgetState + { + Start=0, + Cursoring, + WindowLevelling, + Pushing, + Spinning, + Rotating, + Moving, + Scaling, + Outside + }; + //ETX + + // Handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // internal utility method that adds observers to the RenderWindowInteractor + // so that our ProcessEvents is eventually called. this method is called + // by SetEnabled as well as SetInteraction + void AddObservers(); + + // ProcessEvents() dispatches to these methods. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + virtual void StartCursor(); + virtual void StopCursor(); + virtual void StartSliceMotion(); + virtual void StopSliceMotion(); + virtual void StartWindowLevel(); + virtual void StopWindowLevel(); + + // controlling ivars + int Interaction; // Is the widget responsive to mouse events + int PlaneOrientation; + int RestrictPlaneToVolume; + double OriginalWindow; + double OriginalLevel; + double CurrentWindow; + double CurrentLevel; + int ResliceInterpolate; + int TextureInterpolate; + int UserControlledLookupTable; + int DisplayText; + + // The geometric represenation of the plane and it's outline + vtkPlaneSource *PlaneSource; + vtkPolyData *PlaneOutlinePolyData; + vtkActor *PlaneOutlineActor; + void HighlightPlane(int highlight); + void GeneratePlaneOutline(); + + // Re-builds the plane outline based on the plane source + void BuildRepresentation(); + + // Do the picking + vtkCellPicker *PlanePicker; + + // Methods to manipulate the plane + void WindowLevel(int X, int Y); + void Push(double *p1, double *p2); + void Spin(double *p1, double *p2); + void Rotate(double *p1, double *p2, double *vpn); + void Scale(double *p1, double *p2, int X, int Y); + void Translate(double *p1, double *p2); + + vtkImageData *ImageData; + vtkImageReslice *Reslice; + vtkMatrix4x4 *ResliceAxes; + vtkTransform *Transform; + vtkActor *TexturePlaneActor; + vtkImageMapToColors *ColorMap; + vtkTexture *Texture; + vtkLookupTable *LookupTable; + vtkLookupTable *CreateDefaultLookupTable(); + + // Properties used to control the appearance of selected objects and + // the manipulator in general. The plane property is actually that for + // the outline. The TexturePlaneProperty can be used to control the + // lighting etc. of the resliced image data. + vtkProperty *PlaneProperty; + vtkProperty *SelectedPlaneProperty; + vtkProperty *CursorProperty; + vtkProperty *MarginProperty; + vtkProperty *TexturePlaneProperty; + void CreateDefaultProperties(); + + // Reslice and texture management + void UpdatePlane(); + void GenerateTexturePlane(); + + // The cross-hair cursor + vtkPolyData *CursorPolyData; + vtkActor *CursorActor; + double CurrentCursorPosition[3]; + double CurrentImageValue; // Set to VTK_DOUBLE_MAX when invalid + void GenerateCursor(); + void UpdateCursor(int,int); + void ActivateCursor(int); + int UpdateContinuousCursor(double *q); + int UpdateDiscreteCursor(double *q); + int UseContinuousCursor; + + // The text to display W/L, image data + vtkTextActor *TextActor; + char TextBuff[128]; + void GenerateText(); + void ManageTextDisplay(); + void ActivateText(int); + + // Oblique reslice control + double RotateAxis[3]; + double RadiusVector[3]; + void AdjustState(); + + // Visible margins to assist user interaction + vtkPolyData *MarginPolyData; + vtkActor *MarginActor; + int MarginSelectMode; + void GenerateMargins(); + void UpdateMargins(); + void ActivateMargins(int); + +private: + vtkImagePlaneWidget(const vtkImagePlaneWidget&); //Not implemented + void operator=(const vtkImagePlaneWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkImageTracerWidget.cxx b/Widgets/vtkImageTracerWidget.cxx new file mode 100644 index 0000000..c1bbac4 --- /dev/null +++ b/Widgets/vtkImageTracerWidget.cxx @@ -0,0 +1,1542 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageTracerWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImageTracerWidget.h" + +#include "vtkAbstractPicker.h" +#include "vtkActor.h" +#include "vtkAssemblyPath.h" +#include "vtkAssemblyNode.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkCellPicker.h" +#include "vtkFloatArray.h" +#include "vtkGlyphSource2D.h" +#include "vtkImageData.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkPolyLine.h" +#include "vtkProperty.h" +#include "vtkPropPicker.h" +#include "vtkRenderer.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkTransformPolyDataFilter.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkImageTracerWidget, "$Revision: 1.3.4.1 $"); +vtkStandardNewMacro(vtkImageTracerWidget); + +vtkCxxSetObjectMacro(vtkImageTracerWidget, HandleProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImageTracerWidget, SelectedHandleProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImageTracerWidget, LineProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkImageTracerWidget, SelectedLineProperty, vtkProperty); + +vtkImageTracerWidget::vtkImageTracerWidget() +{ + this->State = vtkImageTracerWidget::Start; + this->EventCallbackCommand->SetCallback(vtkImageTracerWidget::ProcessEvents); + + this->Interaction = 1; + this->ViewProp = NULL; + this->PickCount = 0; + this->SnapToImage = 0; + this->AutoClose = 0; + this->CaptureRadius = 1.0; + this->IsSnapping = 0; + this->ImageSnapType = VTK_ITW_SNAP_CELLS; + this->CurrentPicker = NULL; + this->CurrentHandle = NULL; + this->CurrentHandleIndex = -1; + this->ProjectionNormal = VTK_ITW_PROJECTION_XY; + this->ProjectionPosition = 0.0; + this->ProjectToPlane = 0; + this->NumberOfHandles = 0; + this->LastX = 0; + this->LastY = 0; + + this->PropPicker = vtkPropPicker::New(); + this->PropPicker->PickFromListOn(); + + // Build the representation of the widget + this->HandleGenerator = vtkGlyphSource2D::New(); + this->HandleGenerator->SetGlyphTypeToCross(); + this->HandleGenerator->FilledOff(); + this->HandleGenerator->SetCenter(0,0,0); + + this->TransformFilter = vtkTransformPolyDataFilter::New(); + this->Transform = vtkTransform::New(); + this->TransformFilter->SetTransform(this->Transform); + this->Transform->Identity(); + this->TransformFilter->SetInput(this->HandleGenerator->GetOutput()); + this->TransformFilter->Update(); + + this->TemporaryHandlePoints = vtkFloatArray::New(); + this->TemporaryHandlePoints->SetNumberOfComponents(3); + + this->LinePoints = vtkPoints::New(); + this->LinePoints->Allocate(1001); + this->LineCells = vtkCellArray::New(); + this->LineCells->Allocate(this->LineCells->EstimateSize(1000,2)); + this->LineActor = vtkActor::New(); + vtkPolyDataMapper* lineMapper = vtkPolyDataMapper::New(); + this->LineData = vtkPolyData::New(); + + lineMapper->SetInput(this->LineData); + lineMapper->SetResolveCoincidentTopologyToPolygonOffset(); + lineMapper->ScalarVisibilityOff(); + this->LineActor->SetMapper(lineMapper); + this->LineActor->PickableOff(); + this->LineActor->VisibilityOff(); + lineMapper->Delete(); + + // Manage the picking stuff + this->HandlePicker = vtkCellPicker::New(); + this->HandlePicker->SetTolerance(0.005); + this->HandlePicker->PickFromListOn(); + + this->LinePicker = vtkCellPicker::New(); + this->LinePicker->SetTolerance(0.005); + this->LinePicker->PickFromListOn(); + + // Set up the initial properties + this->HandleProperty = NULL; + this->SelectedHandleProperty = NULL; + this->LineProperty = NULL; + this->SelectedLineProperty = NULL; + this->CreateDefaultProperties(); + + // Initialize ivars + this->Handle = NULL; + this->HandleGeometry = NULL; + + // Create one handle + this->AllocateHandles(1); + this->AdjustHandlePosition(0,this->HandleGenerator->GetCenter()); + + // Initial creation of the widget, serves to initialize it + // using default bounds to get started + double bounds[6]; + vtkMath::UninitializeBounds(bounds); + + this->PlaceFactor = 1.0; + this->PlaceWidget(bounds); +} + +vtkImageTracerWidget::~vtkImageTracerWidget() +{ + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->Delete(); + this->Handle[i]->Delete(); + } + if ( this->Handle ) + { + delete [] this->Handle; + this->Handle = NULL; + } + if ( this->HandleGeometry ) + { + delete [] this->HandleGeometry; + this->HandleGeometry = NULL; + } + + if ( this->HandleProperty ) + { + this->HandleProperty->Delete(); + } + if ( this->SelectedHandleProperty ) + { + this->SelectedHandleProperty->Delete(); + } + if ( this->LineProperty ) + { + this->LineProperty->Delete(); + } + if ( this->SelectedLineProperty ) + { + this->SelectedLineProperty->Delete(); + } + if ( this->ViewProp ) + { + this->ViewProp->UnRegister(this); + } + + this->LinePoints->Delete(); + this->LineCells->Delete(); + this->LineActor->Delete(); + this->LineData->Delete(); + + this->LinePicker->Delete(); + this->HandlePicker->Delete(); + this->CurrentPicker = NULL; + this->CurrentHandle = NULL; + + this->PropPicker->Delete(); + this->TransformFilter->Delete(); + this->Transform->Delete(); + this->TemporaryHandlePoints->Delete(); + this->HandleGenerator->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkImageTracerWidget::SetViewProp(vtkProp* prop) +{ + if ( this->ViewProp != prop ) + { + // Avoid destructor recursion + vtkProp *temp = this->ViewProp; + this->ViewProp = prop; + if ( temp ) + { + temp->UnRegister(this); + } + if ( this->ViewProp ) + { + this->ViewProp->Register(this); + this->PropPicker->InitializePickList(); + this->PropPicker->AddPickList(this->ViewProp); + } + } +} + +void vtkImageTracerWidget::SetEnabled(int enabling) +{ + if ( !this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( !this->ViewProp ) + { + vtkErrorMacro(<<"The external prop must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) + { + vtkDebugMacro(<<"Enabling line widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( !this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if ( !this->CurrentRenderer ) + { + return; + } + } + + this->Enabled = 1; + + this->AddObservers(); + + // Turn on the handles + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->CurrentRenderer->AddViewProp(this->Handle[i]); + this->Handle[i]->SetProperty(this->HandleProperty); + this->Handle[i]->PickableOff(); + } + + this->SizeHandles(); + + this->CurrentRenderer->AddViewProp(this->LineActor); + this->LineActor->SetProperty(this->LineProperty); + this->LineActor->PickableOff(); + + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else // disabling + { + vtkDebugMacro(<<"Disabling tracer widget"); + + if ( !this->Enabled ) //already disabled, just return + { + return; + } + + // if disabling occurs without finishing an activity, cleanup states + if ( this->State == vtkImageTracerWidget::Tracing ) + { + this->OnLeftButtonUp(); + } + else if ( this->State == vtkImageTracerWidget::Snapping ) + { + this->Interactor->SetControlKey( 1 ); + this->OnMiddleButtonUp(); + } + + this->Enabled = 0; + + // Don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // Turn off the handles + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->CurrentRenderer->RemoveViewProp(this->Handle[i]); + } + + this->CurrentRenderer->RemoveViewProp(this->LineActor); + + this->CurrentHandle = NULL; + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkImageTracerWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkImageTracerWidget* self = reinterpret_cast<vtkImageTracerWidget *>( clientdata ); + + switch ( event ) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkImageTracerWidget::AddObservers(void) +{ + // Listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + if (i) + { + i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + } +} + +void vtkImageTracerWidget::SetInteraction(int interact) +{ + if ( this->Interactor && this->Enabled ) + { + if ( this->Interaction == interact ) + { + return; + } + if ( interact == 0 ) + { + this->Interactor->RemoveObserver(this->EventCallbackCommand); + } + else + { + this->AddObservers(); + } + this->Interaction = interact; + } + else + { + vtkGenericWarningMacro(<<"Set interactor and Enabled before changing interaction..."); + } +} + +void vtkImageTracerWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->HandleProperty ) + { + os << indent << "Handle Property: " << this->HandleProperty << "\n"; + } + else + { + os << indent << "Handle Property: (none)\n"; + } + + if ( this->SelectedHandleProperty ) + { + os << indent << "Selected Handle Property: " + << this->SelectedHandleProperty << "\n"; + } + else + { + os << indent << "Selected Handle Property: (none)\n"; + } + + if ( this->LineProperty ) + { + os << indent << "Line Property: " << this->LineProperty << "\n"; + } + else + { + os << indent << "Line Property: (none)\n"; + } + + if ( this->SelectedLineProperty ) + { + os << indent << "Selected Line Property: " + << this->SelectedLineProperty << "\n"; + } + else + { + os << indent << "Selected Line Property: (none)\n"; + } + + if ( this->ViewProp ) + { + os << indent << "ViewProp: " << this->ViewProp << "\n"; + } + else + { + os << indent << "ViewProp: (none)\n"; + } + + os << indent << "Interaction: " + << (this->Interaction ? "On\n" : "Off\n") ; + os << indent << "ProjectionNormal: " << this->ProjectionNormal << "\n"; + os << indent << "ProjectionPosition: " << this->ProjectionPosition << "\n"; + os << indent << "ProjectToPlane: " + << (this->ProjectToPlane ? "On\n" : "Off\n") ; + os << indent << "ImageSnapType: " << this->ImageSnapType << "\n"; + os << indent << "SnapToImage: " + << (this->SnapToImage ? "On\n" : "Off\n") ; + os << indent << "CaptureRadius: " << this->CaptureRadius << "\n"; + os << indent << "NumberOfHandles: " << this->NumberOfHandles << "\n"; + os << indent << "AutoClose: " + << (this->AutoClose ? "On\n" : "Off\n") ; +} + +int vtkImageTracerWidget::HighlightHandle(vtkProp* prop) +{ + // First unhighlight anything picked + if ( this->CurrentHandle ) + { + this->CurrentHandle->SetProperty(this->HandleProperty); + this->Interactor->Render(); + } + + this->CurrentHandle = (vtkActor *)prop; + + if ( this->CurrentHandle ) + { + this->ValidPick = 1; + this->CurrentPicker->GetPickPosition(this->LastPickPosition); + this->CurrentHandle->SetProperty(this->SelectedHandleProperty); + for ( int i = 0; i < this->NumberOfHandles; ++i ) // find handle + { + if ( this->CurrentHandle == this->Handle[i] ) + { + return i; + } + } + } + return -1; +} + +void vtkImageTracerWidget::HighlightLine(const int& highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->CurrentPicker->GetPickPosition(this->LastPickPosition); + this->LineActor->SetProperty(this->SelectedLineProperty); + } + else + { + this->LineActor->SetProperty(this->LineProperty); + } +} + +void vtkImageTracerWidget::AdjustHandlePosition(const int& handle, double pos[3]) +{ + if ( handle < 0 || handle >= this->NumberOfHandles ){ return; } + + if ( this->ProjectToPlane ) + { + pos[this->ProjectionNormal] = this->ProjectionPosition; + } + + this->HandleGenerator->SetCenter(0.0,0.0,0.0); + this->Transform->Identity(); + this->Transform->PostMultiply(); + + if ( this->ProjectionNormal == VTK_ITW_PROJECTION_YZ ) + { + this->Transform->RotateY(90.0); + } + else if ( this->ProjectionNormal == VTK_ITW_PROJECTION_XZ ) + { + this->Transform->RotateX(90.0); + } + + this->Transform->Translate(pos); + this->TransformFilter->Update(); + + this->HandleGeometry[handle]->CopyStructure(this->TransformFilter->GetOutput()); + this->HandleGeometry[handle]->Modified(); +} + +void vtkImageTracerWidget::SetProjectionPosition(double position) +{ + this->ProjectionPosition = position; + + int i; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->AdjustHandlePosition(i,this->HandleGeometry[i]->GetCenter()); + } + + double pt[3]; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->LinePoints->GetPoint(i,pt); + pt[ this->ProjectionNormal ] = this->ProjectionPosition; + this->LinePoints->SetPoint(i,pt); + } + + this->LinePoints->GetData()->Modified(); + this->LineData->Modified(); +} + +void vtkImageTracerWidget::SetHandlePosition(int handle, double xyz[3]) +{ + this->AdjustHandlePosition(handle, xyz); +} + +void vtkImageTracerWidget::SetHandlePosition(int handle, double x, double y, double z) +{ + double xyz[3] = {x,y,z}; + this->AdjustHandlePosition(handle, xyz); +} + +void vtkImageTracerWidget::GetHandlePosition(int handle, double xyz[3]) +{ + if ( handle < 0 || handle >= this->NumberOfHandles ){ return; } + this->HandleGeometry[handle]->GetCenter(xyz); +} + +double* vtkImageTracerWidget::GetHandlePosition(int handle) +{ + if ( handle < 0 || handle >= this->NumberOfHandles ){ return NULL; } + return this->HandleGeometry[handle]->GetCenter(); +} + +void vtkImageTracerWidget::OnLeftButtonDown() +{ + // If the user is snap defining a line by middle mouse button, + // ignore this button + if ( this->State == vtkImageTracerWidget::Snapping ){ return; } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X,Y) ) + { + this->State = vtkImageTracerWidget::Outside; + return; + } + + int found = 0; + if ( this->PropPicker->PickProp(X,Y,this->CurrentRenderer) ) + { + if ( this->ViewProp == this->PropPicker->GetViewProp() ) + { + found = 1; + this->State = vtkImageTracerWidget::Tracing; + } + } + + if ( !found ) + { + this->State = vtkImageTracerWidget::Outside; + return; + } + + // first erase any handles if there any + if ( this->NumberOfHandles > 1 ) + { + this->AllocateHandles(1); + } + + this->CurrentPicker = this->PropPicker; //collect the pick position from the prop picker + this->CurrentHandleIndex = this->HighlightHandle((vtkProp*)this->Handle[0]); + + if ( this->CurrentHandleIndex == -1 ) //this should never happen + { + this->State = vtkImageTracerWidget::Outside; + return; + } + + // set the handle to the picked position + this->AdjustHandlePosition(this->CurrentHandleIndex,this->LastPickPosition); + + // erase the line and initialize it + this->ResetLine(this->LastPickPosition); + + this->LastX = X; + this->LastY = Y; + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImageTracerWidget::OnLeftButtonUp() +{ + if ( this->State == vtkImageTracerWidget::Outside || + this->State == vtkImageTracerWidget::Start || + this->State == vtkImageTracerWidget::Snapping ) + { + return; + } + + this->State = vtkImageTracerWidget::Start; + this->CurrentHandleIndex = this->HighlightHandle(NULL); + + if ( this->AutoClose ) // attempt to close by tolerance + { + this->ClosePath(); + if ( this->IsClosed() ) // if successful, remove the overlapping handle + { + this->EraseHandle(this->NumberOfHandles - 1); + } + } + + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); + this->CurrentPicker = NULL; +} + +void vtkImageTracerWidget::OnMiddleButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X,Y) ) + { + this->State = vtkImageTracerWidget::Outside; + return; + } + + int found = 0; + if ( this->PropPicker->PickProp(X,Y,this->CurrentRenderer) ) + { + if ( this->ViewProp == this->PropPicker->GetViewProp() ) + { + found = 1; + this->State = vtkImageTracerWidget::Snapping; // do snap tracing + } + } + + if ( !found ) + { + this->State = vtkImageTracerWidget::Outside; + return; + } + + if ( !this->IsSnapping ) // this is the first time so reset the handles + { + if ( this->NumberOfHandles > 1 ) + { + this->AllocateHandles(1); + } + } + + this->CurrentPicker = this->PropPicker; // highlight the last handle + this->CurrentHandleIndex = this->HighlightHandle((vtkProp*)this->Handle[this->NumberOfHandles - 1]); + + if ( this->CurrentHandleIndex == -1 ) // sanity check: this should never happen + { + this->State = vtkImageTracerWidget::Outside; + return; + } + + this->AdjustHandlePosition(this->CurrentHandleIndex,this->LastPickPosition); + + if ( !this->IsSnapping ) // this is the first time so initialize the line + { + this->ResetLine(this->GetHandlePosition(this->CurrentHandleIndex)); + } + + this->IsSnapping = this->NumberOfHandles; + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImageTracerWidget::OnMiddleButtonUp() +{ + if ( this->State == vtkImageTracerWidget::Outside || + this->State == vtkImageTracerWidget::Start ) + { + return; + } + + if ( this->Interactor->GetControlKey() ) // finished the snapping + { + this->IsSnapping = 0; + } + else // continue snap drawing + { + return; + } + + this->State = vtkImageTracerWidget::Start; + this->CurrentHandleIndex = this->HighlightHandle(NULL); + + if ( this->AutoClose ) + { + this->ClosePath(); + if ( this->IsClosed() ) // if successful, remove the last overlapping handle + { + this->EraseHandle(this->NumberOfHandles - 1); + } + } + + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); + this->CurrentPicker = NULL; +} + +void vtkImageTracerWidget::OnRightButtonDown() +{ + if ( this->State == vtkImageTracerWidget::Snapping ){ return; } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X,Y) ) + { + this->State = vtkImageTracerWidget::Outside; + return; + } + + if ( this->Interactor->GetControlKey() && (this->NumberOfHandles > 1) ) + { + this->State = vtkImageTracerWidget::Erasing; // pick a handle to delete + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->Handle[i]->PickableOn(); + } + this->CurrentPicker = this->HandlePicker; + } + else if ( this->Interactor->GetShiftKey() && (this->NumberOfHandles > 1) ) + { + this->State = vtkImageTracerWidget::Inserting; // pick a line to insert on + this->LineActor->PickableOn(); + this->LinePicker->AddPickList(this->LineActor); + this->CurrentPicker = this->LinePicker; + } + else + { + if ( this->NumberOfHandles < 3 && this->LinePoints->GetNumberOfPoints() > this->NumberOfHandles ) + { + this->State = vtkImageTracerWidget::Translating; + } + else + { + this->State = vtkImageTracerWidget::Moving; + } + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->Handle[i]->PickableOn(); + } + this->CurrentPicker = this->HandlePicker; + } + + if ( this->ViewProp ) // don't pick the prop + { + this->ViewProp->PickableOff(); + } + + int found = 0; + if ( this->CurrentPicker->Pick(X,Y,0.0,this->CurrentRenderer) ) + { + vtkAssemblyPath* path = this->CurrentPicker->GetPath(); + + if ( path ) + { + found = 1; + if ( this->State == vtkImageTracerWidget::Erasing || + this->State == vtkImageTracerWidget::Moving || + this->State == vtkImageTracerWidget::Translating ) + { + this->CurrentHandleIndex = this->HighlightHandle(path->GetFirstNode()->GetViewProp()); + if ( this->CurrentHandleIndex == -1 ) + { + found = 0; // we didn't hit a handle + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->Handle[i]->PickableOff(); + } + } + } + else if ( this->State == vtkImageTracerWidget::Inserting ) + { + if ( (vtkActor*)path->GetFirstNode()->GetViewProp() == this->LineActor ) + { + this->HighlightLine(1); + } + else + { + found = 0; + this->LineActor->PickableOff(); + } + } + } + } + + if ( !found ) + { + this->State = vtkImageTracerWidget::Outside; + if ( this->ViewProp ) + { + this->ViewProp->PickableOn(); + } + this->CurrentPicker = NULL; + return; + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImageTracerWidget::OnRightButtonUp() +{ + if ( this->State == vtkImageTracerWidget::Outside || + this->State == vtkImageTracerWidget::Start || + this->State == vtkImageTracerWidget::Snapping) + { + return; + } + + if ( this->State == vtkImageTracerWidget::Erasing ) + { + int index = this->CurrentHandleIndex; + this->CurrentHandleIndex = this->HighlightHandle(NULL); + int closed = this->IsClosed(); + this->EraseHandle(index); + this->BuildLinesFromHandles(); + if ( closed && this->NumberOfHandles > 2 ) + { + this->AppendLine(this->HandleGeometry[0]->GetCenter()); + } + } + else if ( this->State == vtkImageTracerWidget::Inserting ) + { + this->HighlightLine(0); + int closed = this->IsClosed(); + this->InsertHandleOnLine(this->LastPickPosition); + this->BuildLinesFromHandles(); + if ( closed ) + { + this->AppendLine(this->HandleGeometry[0]->GetCenter()); + } + } + else if ( this->State == vtkImageTracerWidget::Moving ) + { + this->CurrentHandleIndex = this->HighlightHandle(NULL); + if ( this->AutoClose && !this->IsClosed() ) + { + this->ClosePath(); + if ( this->IsClosed() ) // if successful, remove the last overlapping handle + { + this->EraseHandle(this->NumberOfHandles - 1); + } + } + } + else if ( this->State == vtkImageTracerWidget::Translating ) + { + this->CurrentHandleIndex = this->HighlightHandle(NULL); + } + + this->State = vtkImageTracerWidget::Start; + + this->SizeHandles(); + + if ( this->ViewProp ) + { + this->ViewProp->PickableOn(); + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); + this->CurrentPicker = NULL; +} + +void vtkImageTracerWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkImageTracerWidget::Outside || + this->State == vtkImageTracerWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + double z; + + // Process the motion + if ( this->CurrentHandle ) + { + if ( this->State == vtkImageTracerWidget::Tracing || + this->State == vtkImageTracerWidget::Snapping ) + { + this->Trace(X,Y); + } + else if ( this->State == vtkImageTracerWidget::Moving || + this->State == vtkImageTracerWidget::Translating ) + { + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( !camera ){ return; } + + // Compute the two points defining the motion vector + this->ComputeWorldToDisplay(this->LastPickPosition[0], + this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld( + double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + if ( this->State == vtkImageTracerWidget::Moving ) + { + this->MovePoint(prevPickPoint, pickPoint); + } + else + { + this->Translate(prevPickPoint, pickPoint); + } + } + } + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImageTracerWidget::Trace(int X, int Y) +{ + if ( !this->PropPicker->PickProp(X,Y,this->CurrentRenderer) ){ return; } + if ( this->ViewProp != this->PropPicker->GetViewProp() ){ return; } + + double pos[3]; + this->PropPicker->GetPickPosition(pos); + + if ( this->SnapToImage ) + { + this->Snap(pos); + } + + if ( this->ProjectToPlane ) + { + pos[this->ProjectionNormal] = this->ProjectionPosition; + } + + if ( this->LastX != X || this->LastY != Y ) + { + if ( this->State == vtkImageTracerWidget::Tracing ) + { + if ( this->NumberOfHandles == 1 ) + { + this->AppendHandles(pos); + } + else + { + this->AdjustHandlePosition(this->CurrentHandleIndex,pos); + } + this->AppendLine(pos); + } + else if ( this->State == vtkImageTracerWidget::Snapping ) + { + if ( this->IsSnapping != this->CurrentHandleIndex ) + { + this->AppendHandles(pos); + this->AppendLine(pos); + this->IsSnapping = this->CurrentHandleIndex; + } + else + { + this->AdjustHandlePosition(this->CurrentHandleIndex,pos); + this->LinePoints->SetPoint(this->PickCount,pos); + this->LinePoints->GetData()->Modified(); + this->LineData->Modified(); + } + } + } + + this->LastX = X; + this->LastY = Y; +} + +void vtkImageTracerWidget::MovePoint(const double *p1, const double *p2) +{ + // Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double *ctr = this->HandleGeometry[this->CurrentHandleIndex]->GetCenter(); + + double newCtr[3]; + newCtr[0] = ctr[0] + v[0]; + newCtr[1] = ctr[1] + v[1]; + newCtr[2] = ctr[2] + v[2]; + + // Move the widget handle + this->AdjustHandlePosition(this->CurrentHandleIndex,newCtr); + + // Enforce consistency with the line + int closed = this->IsClosed(); + + this->LinePoints->SetPoint(this->CurrentHandleIndex, + this->HandleGeometry[this->CurrentHandleIndex]->GetCenter()); + + // Special case when moving the first point + if ( closed && (this->CurrentHandleIndex == 0) ) + { + this->LinePoints->SetPoint(this->LinePoints->GetNumberOfPoints()-1, + this->HandleGeometry[0]->GetCenter()); + } + + this->LinePoints->GetData()->Modified(); + this->LineData->Modified(); +} + +void vtkImageTracerWidget::Translate(const double *p1, const double *p2) +{ + // Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double newCtr[3]; + int i; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + double *ctr = this->HandleGeometry[i]->GetCenter(); + newCtr[0] = ctr[0] + v[0]; + newCtr[1] = ctr[1] + v[1]; + newCtr[2] = ctr[2] + v[2]; + this->AdjustHandlePosition(i,newCtr); + } + + for ( i = 0; i < this->LinePoints->GetNumberOfPoints(); ++i ) + { + double *ctr = this->LinePoints->GetPoint(i); + newCtr[0] = ctr[0] + v[0]; + newCtr[1] = ctr[1] + v[1]; + newCtr[2] = ctr[2] + v[2]; + if ( this->ProjectToPlane ) + { + newCtr[this->ProjectionNormal] = this->ProjectionPosition; + } + this->LinePoints->SetPoint(i,newCtr); + } + + this->LinePoints->GetData()->Modified(); + this->LineData->Modified(); +} + +void vtkImageTracerWidget::ResetHandles(void) +{ + if ( this->NumberOfHandles == 0 ){ return; } + + if ( this->CurrentHandle ) + { + this->CurrentHandle = NULL; + } + + this->HandlePicker->InitializePickList(); + + int i; + if ( this->CurrentRenderer ) + { + for (i = 0; i < this->NumberOfHandles; ++i ) + { + this->CurrentRenderer->RemoveViewProp(this->Handle[i]); + } + } + + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->Delete(); + this->Handle[i]->Delete(); + } + + this->NumberOfHandles = 0; + + if ( this->Handle ) + { + delete [] this->Handle; + this->Handle = NULL; + } + if ( this->HandleGeometry ) + { + delete [] this->HandleGeometry; + this->HandleGeometry = NULL; + } +} + +void vtkImageTracerWidget::AllocateHandles(const int& nhandles) +{ + if ( (this->NumberOfHandles == nhandles) || (nhandles < 1) ){ return; } + + // De-allocate the handles + this->ResetHandles(); + this->NumberOfHandles = nhandles; + + // Create the handles + this->Handle = new vtkActor* [this->NumberOfHandles]; + this->HandleGeometry = new vtkPolyData* [this->NumberOfHandles]; + + int i; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i] = vtkPolyData::New(); + vtkPolyDataMapper* handleMapper = vtkPolyDataMapper::New(); + handleMapper->SetInput(this->HandleGeometry[i]); + this->Handle[i] = vtkActor::New(); + this->Handle[i]->SetMapper(handleMapper); + handleMapper->Delete(); + this->Handle[i]->SetProperty(this->HandleProperty); + this->Handle[i]->PickableOff(); + this->HandlePicker->AddPickList(this->Handle[i]); + } + + if ( this->CurrentRenderer && this->Enabled ) + { + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->CurrentRenderer->AddViewProp(this->Handle[i]); + } + } +} + +void vtkImageTracerWidget::AppendHandles(double* pos) +{ + this->TemporaryHandlePoints->Reset(); + this->TemporaryHandlePoints->SetNumberOfTuples(this->NumberOfHandles+1); + int i; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->TemporaryHandlePoints->SetTuple(i,this->HandleGeometry[i]->GetCenter()); + } + + this->TemporaryHandlePoints->SetTuple(this->NumberOfHandles,pos); + + this->AllocateHandles(this->TemporaryHandlePoints->GetNumberOfTuples()); + + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->AdjustHandlePosition(i,this->TemporaryHandlePoints->GetTuple(i)); + } + + if ( this->CurrentHandleIndex != -1 ) + { + this->CurrentHandleIndex = this->NumberOfHandles - 1; + this->CurrentHandle = this->Handle[this->CurrentHandleIndex]; + this->CurrentHandle->SetProperty(this->SelectedHandleProperty); + } +} + +void vtkImageTracerWidget::InsertHandleOnLine(double* pos) +{ + if ( this->NumberOfHandles < 3 && + this->LinePoints->GetNumberOfPoints() > 2 ) + { + return; // don't insert on a continuously traced line + } + + int id = this->LinePicker->GetCellId(); + if ( id == -1 ){ return; } + + this->TemporaryHandlePoints->Reset(); + this->TemporaryHandlePoints->SetNumberOfTuples(this->NumberOfHandles+1); + int i; + for ( i = 0; i <= id; i++ ) + { + this->TemporaryHandlePoints->SetTuple(i,this->HandleGeometry[i]->GetCenter()); + } + + this->TemporaryHandlePoints->SetTuple(id+1,pos); + + for ( i = id + 1; i < this->NumberOfHandles; ++i ) + { + this->TemporaryHandlePoints->SetTuple(i+1,this->HandleGeometry[i]->GetCenter()); + } + + this->AllocateHandles(this->TemporaryHandlePoints->GetNumberOfTuples()); + + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->AdjustHandlePosition(i,this->TemporaryHandlePoints->GetTuple(i)); + } +} + +void vtkImageTracerWidget::InitializeHandles(vtkPoints* points) +{ + if ( !points ){ return; } + + int npts = points->GetNumberOfPoints(); + if ( npts == 0 ){ return; } + + this->AllocateHandles( npts ); + + for ( int i = 0; i < npts; ++i ) + { + this->AdjustHandlePosition(i,points->GetPoint(i)); + } + + if ( npts > 1 ) + { + this->BuildLinesFromHandles(); + if ( this->AutoClose ) + { + this->ClosePath(); + if ( this->IsClosed() ) // if successful, remove the overlapping handle + { + this->EraseHandle(this->NumberOfHandles - 1); + } + } + } +} + +void vtkImageTracerWidget::EraseHandle(const int& index) +{ + if ( this->NumberOfHandles == 1 ){ return; } + + this->TemporaryHandlePoints->Reset(); + this->TemporaryHandlePoints->SetNumberOfTuples(this->NumberOfHandles-1); + int i; + int count = 0; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + if ( i != index ) + { + this->TemporaryHandlePoints->SetTuple(count++,this->HandleGeometry[i]->GetCenter()); + } + } + + this->AllocateHandles(this->TemporaryHandlePoints->GetNumberOfTuples()); + + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->AdjustHandlePosition(i,this->TemporaryHandlePoints->GetTuple(i)); + } +} + +void vtkImageTracerWidget::ResetLine(double* pos) +{ + this->LinePicker->DeletePickList(this->LineActor); + this->LineActor->VisibilityOff(); + this->LineActor->PickableOff(); + + this->LinePoints->Delete(); + this->LineCells->Delete(); + + this->LineData->Initialize(); + this->LineData->Squeeze(); + + this->LinePoints = vtkPoints::New(); + this->LineCells = vtkCellArray::New(); + + this->LineData->SetPoints( this->LinePoints ); + this->LineData->SetLines( this->LineCells ); + + this->PickCount = 0; + + this->LinePoints->InsertPoint(this->PickCount,pos); +} + +void vtkImageTracerWidget::AppendLine(double* pos) +{ + this->CurrentPoints[0] = this->PickCount++; + this->CurrentPoints[1] = this->PickCount; + + this->LinePoints->InsertPoint(this->PickCount,pos); + this->LineCells->InsertNextCell(2,this->CurrentPoints); + + this->LinePoints->GetData()->Modified(); + this->LineData->SetPoints(this->LinePoints); + this->LineData->SetLines(this->LineCells); + this->LineData->Modified(); + + this->LineActor->VisibilityOn(); +} + +void vtkImageTracerWidget::BuildLinesFromHandles() +{ + this->ResetLine(this->HandleGeometry[0]->GetCenter()); + + for ( int i = 1; i < this->NumberOfHandles; ++i ) + { + this->AppendLine(this->HandleGeometry[i]->GetCenter()); + } +} + +void vtkImageTracerWidget::ClosePath() +{ + int npts = this->LinePoints->GetNumberOfPoints(); + if ( npts < 4 ){ return; } + + double p0[3]; + this->LinePoints->GetPoint(0,p0); + double p1[3]; + this->LinePoints->GetPoint(npts-1,p1); + + if ( sqrt(vtkMath::Distance2BetweenPoints(p0,p1)) <= this->CaptureRadius ) + { + this->LinePoints->SetPoint(npts-1,p0); + this->LinePoints->GetData()->Modified(); + this->LineData->Modified(); + } +} + +int vtkImageTracerWidget::IsClosed() // can only be based on line data +{ + int npts = this->LinePoints->GetNumberOfPoints(); + if ( npts < 4 ) { return 0; } + + double p0[3]; + this->LinePoints->GetPoint(0,p0); + double p1[3]; + this->LinePoints->GetPoint(npts-1,p1); + + return (p0[0] == p1[0] && p0[1] == p1[1] && p0[2] == p1[2]); +} + +void vtkImageTracerWidget::GetPath(vtkPolyData *pd) +{ + pd->ShallowCopy(this->LineData); +} + +void vtkImageTracerWidget::SetSnapToImage(int snap) +{ + if ( this->Input ) + { + if ( this->Input->GetDataObjectType() != VTK_IMAGE_DATA ) + { + vtkErrorMacro(<<"Input data must be of type vtkImageData"); + return; + } + else + { + this->SnapToImage = snap; + } + } + else + { + vtkGenericWarningMacro(<<"SetInput with type vtkImageData first"); + return; + } +} + +void vtkImageTracerWidget::Snap(double* pos) // overwrites pos +{ + vtkImageData* ptr = vtkImageData::SafeDownCast(this->GetInput()); + if ( !ptr ){ return; } + + if ( this->ImageSnapType == VTK_ITW_SNAP_CELLS ) // snap to cell center + { + double bounds[6]; + double weights[8]; + double pcoords[3]; + int subId; + vtkIdType cellId = ptr->FindCell(pos,NULL,-1,0.0,subId,pcoords,weights); + if ( cellId != -1 ) + { + ptr->GetCellBounds(cellId,bounds); + for ( int i = 0; i < 3; ++i ) + { + pos[i] = bounds[i*2]+ 0.5*(bounds[i*2+1]-bounds[i*2]); + } + } + } + else // snap to nearest point + { + vtkIdType ptId = ptr->FindPoint(pos); + if ( ptId != -1 ) + { + ptr->GetPoint(ptId,pos); + } + } +} + +void vtkImageTracerWidget::CreateDefaultProperties() +{ + if ( !this->HandleProperty ) + { + this->HandleProperty = vtkProperty::New(); + this->HandleProperty->SetAmbient(1.0); + this->HandleProperty->SetDiffuse(0.0); + this->HandleProperty->SetColor(1,0,1); + this->HandleProperty->SetLineWidth(2); + this->HandleProperty->SetRepresentationToWireframe(); + this->HandleProperty->SetInterpolationToFlat(); + } + if ( !this->SelectedHandleProperty ) + { + this->SelectedHandleProperty = vtkProperty::New(); + this->SelectedHandleProperty->SetAmbient(1.0); + this->SelectedHandleProperty->SetDiffuse(0.0); + this->SelectedHandleProperty->SetColor(0,1,0); + this->SelectedHandleProperty->SetLineWidth(2); + this->SelectedHandleProperty->SetRepresentationToWireframe(); + this->SelectedHandleProperty->SetInterpolationToFlat(); + } + if ( !this->LineProperty ) + { + this->LineProperty = vtkProperty::New(); + this->LineProperty->SetAmbient(1.0); + this->LineProperty->SetDiffuse(0.0); + this->LineProperty->SetColor(0,1,0); + this->LineProperty->SetLineWidth(2); + this->LineProperty->SetRepresentationToWireframe(); + this->LineProperty->SetInterpolationToFlat(); + } + if ( !this->SelectedLineProperty ) + { + this->SelectedLineProperty = vtkProperty::New(); + this->SelectedLineProperty->SetAmbient(1.0); + this->SelectedLineProperty->SetDiffuse(0.0); + this->SelectedLineProperty->SetColor(0,1,1); + this->SelectedLineProperty->SetLineWidth(2); + this->SelectedLineProperty->SetRepresentationToWireframe(); + this->SelectedLineProperty->SetInterpolationToFlat(); + } +} + +void vtkImageTracerWidget::PlaceWidget(double bds[6]) +{ + double bounds[6], center[3]; + this->AdjustBounds(bds, bounds, center); + + // create a default handle within the data bounds + double x0 = bounds[0]; + double x1 = bounds[1]; + double y0 = bounds[2]; + double y1 = bounds[3]; + double z0 = bounds[4]; + double z1 = bounds[5]; + double xyz[3]; + double position = 0.5; + xyz[0] = (1.0-position)*x0 + position*x1; + xyz[1] = (1.0-position)*y0 + position*y1; + xyz[2] = (1.0-position)*z0 + position*z1; + + this->AdjustHandlePosition(0,xyz); + + for ( int i = 0; i < 6; ++i ) + { + this->InitialBounds[i] = bounds[i]; + } + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + this->SizeHandles(); +} + +void vtkImageTracerWidget::SizeHandles() +{ + // TODO... + return; +} + +//---------------------------------------------------------------------------- +#ifndef VTK_LEGACY_REMOVE +# ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SetProp +void vtkImageTracerWidget::SetPropA(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkImageTracerWidget::SetProp, "VTK 5.0", + vtkImageTracerWidget::SetViewProp); + this->SetViewProp(prop); +} +void vtkImageTracerWidget::SetPropW(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkImageTracerWidget::SetProp, "VTK 5.0", + vtkImageTracerWidget::SetViewProp); + this->SetViewProp(prop); +} +# endif +void vtkImageTracerWidget::SetProp(vtkProp* prop) +{ + VTK_LEGACY_REPLACED_BODY(vtkImageTracerWidget::SetProp, "VTK 5.0", + vtkImageTracerWidget::SetViewProp); + this->SetViewProp(prop); +} +#endif diff --git a/Widgets/vtkImageTracerWidget.h b/Widgets/vtkImageTracerWidget.h new file mode 100644 index 0000000..f31ff62 --- /dev/null +++ b/Widgets/vtkImageTracerWidget.h @@ -0,0 +1,339 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImageTracerWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImageTracerWidget - 3D widget for tracing on planar props. +// .SECTION Description +// vtkImageTracerWidget is different from other widgets in three distinct ways: +// 1) any sub-class of vtkProp can be input rather than just vtkProp3D, so that +// vtkImageActor can be set as the prop and then traced over, 2) the widget fires +// pick events at the input prop to decide where to move its handles, 3) the +// widget has 2D glyphs for handles instead of 3D spheres as is done in other +// sub-classes of vtk3DWidget. This widget is primarily designed for manually +// tracing over image data. +// The button actions and key modifiers are as follows for controlling the +// widget: +// 1) left button click over the image, hold and drag draws a free hand line. +// 2) left button click and release erases the widget line, +// if it exists, and repositions the first handle. +// 3) middle button click starts a snap drawn line. The line is terminated by +// clicking the middle button while depressing the ctrl key. +// 4) when tracing a continuous or snap drawn line, if the last cursor position +// is within a specified tolerance to the first handle, the widget line will form +// a closed loop. +// 5) right button clicking and holding on any handle that is part of a snap +// drawn line allows handle dragging: existing line segments are updated +// accordingly. If the path is open and AutoClose is set to On, the path can +// be closed by repositioning the first and last points over one another. +// 6) ctrl key + right button down on any handle will erase it: existing +// snap drawn line segments are updated accordingly. If the line was formed by +// continous tracing, the line is deleted leaving one handle. +// 7) shift key + right button down on any snap drawn line segment will insert +// a handle at the cursor position. The line segment is split accordingly. + +// .SECTION Caveats +// the input vtkDataSet should be vtkImageData. + +// .SECTION See Also +// vtk3DWidget vtkBoxWidget vtkLineWidget vtkPointWidget vtkSphereWidget +// vtkImagePlaneWidget vtkImplicitPlaneWidget vtkPlaneWidget + +#ifndef __vtkImageTracerWidget_h +#define __vtkImageTracerWidget_h + +#include "vtk3DWidget.h" + +class vtkAbstractPropPicker; +class vtkActor; +class vtkCellArray; +class vtkCellPicker; +class vtkFloatArray; +class vtkGlyphSource2D; +class vtkPoints; +class vtkPolyData; +class vtkProp; +class vtkProperty; +class vtkPropPicker; +class vtkTransform; +class vtkTransformPolyDataFilter; + +#define VTK_ITW_PROJECTION_YZ 0 +#define VTK_ITW_PROJECTION_XZ 1 +#define VTK_ITW_PROJECTION_XY 2 +#define VTK_ITW_SNAP_CELLS 0 +#define VTK_ITW_SNAP_POINTS 1 + +class VTK_WIDGETS_EXPORT vtkImageTracerWidget : public vtk3DWidget +{ +public: + // Description: + // Instantiate the object. + static vtkImageTracerWidget *New(); + + vtkTypeRevisionMacro(vtkImageTracerWidget,vtk3DWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Set/Get the handle properties (the 2D glyphs are the handles). The + // properties of the handles when selected and normal can be manipulated. + virtual void SetHandleProperty(vtkProperty*); + vtkGetObjectMacro(HandleProperty, vtkProperty); + virtual void SetSelectedHandleProperty(vtkProperty*); + vtkGetObjectMacro(SelectedHandleProperty, vtkProperty); + + // Description: + // Set/Get the line properties. The properties of the line when selected + // and unselected can be manipulated. + virtual void SetLineProperty(vtkProperty*); + vtkGetObjectMacro(LineProperty, vtkProperty); + virtual void SetSelectedLineProperty(vtkProperty*); + vtkGetObjectMacro(SelectedLineProperty, vtkProperty); + + // Description: + // Set the prop, usually a vtkImageActor, to trace over. + void SetViewProp(vtkProp* prop); + + // Description: + // Force handles to be on a specific ortho plane. + vtkSetMacro(ProjectToPlane,int); + vtkGetMacro(ProjectToPlane,int); + vtkBooleanMacro(ProjectToPlane,int); + + // Description: + // Set the projection normal. The normal in SetProjectionNormal is 0,1,2 + // for YZ,XZ,XY planes respectively. Since the handles are 2D glyphs, it is + // necessary to specify a plane on which to generate them, even though + // ProjectToPlane may be turned off. + vtkSetClampMacro(ProjectionNormal,int,VTK_ITW_PROJECTION_YZ,VTK_ITW_PROJECTION_XY); + vtkGetMacro(ProjectionNormal,int); + void SetProjectionNormalToXAxes() + { this->SetProjectionNormal(0); } + void SetProjectionNormalToYAxes() + { this->SetProjectionNormal(1); } + void SetProjectionNormalToZAxes() + { this->SetProjectionNormal(2); } + + // Description: + // Set the position of the widgets' handles in terms of a plane's position. + // e.g., if ProjectionNormal is 0, all of the x-coordinate values of the + // handles are set to ProjectionPosition. No attempt is made to ensure that + // the position is within the bounds of either the underlying image data or + // the prop on which tracing is performed. + void SetProjectionPosition(double position); + vtkGetMacro(ProjectionPosition,double); + + // Description: + // Force snapping to image data while tracing. + void SetSnapToImage(int snap); + vtkGetMacro(SnapToImage,int); + vtkBooleanMacro(SnapToImage,int); + + // Description: + // In concert with a CaptureRadius value, automatically + // form a closed path by connecting first to last path points. + vtkSetMacro(AutoClose,int); + vtkGetMacro(AutoClose,int); + vtkBooleanMacro(AutoClose,int); + + // Description: + // Set/Get the capture radius for automatic path closing. For image + // data, capture radius should be half the distance between voxel/pixel + // centers. + vtkSetMacro(CaptureRadius,double); + vtkGetMacro(CaptureRadius,double); + + // Description: + // Grab the points and lines that define the traced path. These point values + // are guaranteed to be up-to-date when either the InteractionEvent or + // EndInteraction events are invoked. The user provides the vtkPolyData and + // the points and cells representing the line are added to it. + void GetPath(vtkPolyData *pd); + + // Description: + // Get the handles' geometric representation via vtkGlyphSource2D. + vtkGlyphSource2D* GetGlyphSource() { return this->HandleGenerator; } + + // Description: + // Set/Get the type of snapping to image data: center of a pixel/voxel or + // nearest point defining a pixel/voxel. + vtkSetClampMacro(ImageSnapType,int,VTK_ITW_SNAP_CELLS,VTK_ITW_SNAP_POINTS); + vtkGetMacro(ImageSnapType,int); + + // Description: + // Set/Get the handle position in terms of a zero-based array of handles. + void SetHandlePosition(int handle, double xyz[3]); + void SetHandlePosition(int handle, double x, double y, double z); + void GetHandlePosition(int handle, double xyz[3]); + double* GetHandlePosition(int handle); + + // Description: + // Get the number of handles. + vtkGetMacro(NumberOfHandles,int); + + // Description: + // Enable/disable mouse interaction when the widget is visible. + void SetInteraction(int interact); + vtkGetMacro(Interaction,int); + vtkBooleanMacro(Interaction,int); + + // Description: + // Initialize the widget with a set of points and generate + // lines between them. If AutoClose is on it will handle the + // case wherein the first and last points are congruent. + void InitializeHandles(vtkPoints*); + + // Description: + // Is the path closed or open? + int IsClosed(); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# define SetPropA SetProp +# define SetPropW SetProp +#endif + + // Description: + // @deprecated Replaced by vtkImageTracerWidget::SetViewProp() as of VTK 5.0. + VTK_LEGACY(void SetProp(vtkProp* prop)); + +#ifdef VTK_WORKAROUND_WINDOWS_MANGLE +# undef SetPropA +# undef SetPropW + //BTX + VTK_LEGACY(void SetPropA(vtkProp*)); + VTK_LEGACY(void SetPropW(vtkProp*)); + //ETX +#endif + +protected: + vtkImageTracerWidget(); + ~vtkImageTracerWidget(); + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Start=0, + Tracing, + Snapping, + Erasing, + Inserting, + Moving, + Translating, + Outside + }; +//ETX + + //handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnMiddleButtonDown(); + void OnMiddleButtonUp(); + void OnRightButtonDown(); + void OnRightButtonUp(); + void OnMouseMove(); + + void AddObservers(); + + // Controlling ivars + int Interaction; + int ProjectionNormal; + double ProjectionPosition; + int ProjectToPlane; + int ImageSnapType; + int SnapToImage; + double CaptureRadius; // tolerance for auto path close + int AutoClose; + int IsSnapping; + int LastX; + int LastY; + + void Trace(int , int ); + void Snap(double* ); + void MovePoint(const double* , const double* ); + void Translate(const double* , const double* ); + void ClosePath(); + + // 2D glyphs representing hot spots (e.g., handles) + vtkActor **Handle; + vtkPolyData **HandleGeometry; + vtkGlyphSource2D *HandleGenerator; + + // Transforms required as 2D glyphs are generated in the x-y plane + vtkTransformPolyDataFilter *TransformFilter; + vtkTransform *Transform; + vtkFloatArray *TemporaryHandlePoints; + + void AppendHandles(double*); + void ResetHandles(); + void AllocateHandles(const int& ); + void AdjustHandlePosition(const int& , double*); + int HighlightHandle(vtkProp* ); // returns handle index or -1 on fail + void EraseHandle(const int& ); + virtual void SizeHandles(); + void InsertHandleOnLine(double* ); + + int NumberOfHandles; + vtkActor *CurrentHandle; + int CurrentHandleIndex; + + vtkProp *ViewProp; // the prop we want to pick on + vtkPropPicker *PropPicker; // the prop's picker + + // Representation of the line + vtkPoints *LinePoints; + vtkCellArray *LineCells; + vtkActor *LineActor; + vtkPolyData *LineData; + vtkIdType CurrentPoints[2]; + + void HighlightLine(const int& ); + void BuildLinesFromHandles(); + void ResetLine(double* ); + void AppendLine(double* ); + int PickCount; + + // Do the picking of the handles and the lines + vtkCellPicker *HandlePicker; + vtkCellPicker *LinePicker; + vtkAbstractPropPicker* CurrentPicker; + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *HandleProperty; + vtkProperty *SelectedHandleProperty; + vtkProperty *LineProperty; + vtkProperty *SelectedLineProperty; + void CreateDefaultProperties(); + +private: + vtkImageTracerWidget(const vtkImageTracerWidget&); //Not implemented + void operator=(const vtkImageTracerWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkImplicitPlaneWidget.cxx b/Widgets/vtkImplicitPlaneWidget.cxx new file mode 100644 index 0000000..d90f430 --- /dev/null +++ b/Widgets/vtkImplicitPlaneWidget.cxx @@ -0,0 +1,1224 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitPlaneWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkImplicitPlaneWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellPicker.h" +#include "vtkConeSource.h" +#include "vtkCutter.h" +#include "vtkFeatureEdges.h" +#include "vtkImageData.h" +#include "vtkLineSource.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkOutlineFilter.h" +#include "vtkPlane.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" +#include "vtkTubeFilter.h" + +vtkCxxRevisionMacro(vtkImplicitPlaneWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkImplicitPlaneWidget); + +vtkImplicitPlaneWidget::vtkImplicitPlaneWidget() : vtkPolyDataSourceWidget() +{ + this->State = vtkImplicitPlaneWidget::Start; + this->EventCallbackCommand->SetCallback(vtkImplicitPlaneWidget::ProcessEvents); + + this->NormalToXAxis = 0; + this->NormalToYAxis = 0; + this->NormalToZAxis = 0; + + // Build the representation of the widget + // + this->Plane = vtkPlane::New(); + this->Plane->SetNormal(0,0,1); + this->Plane->SetOrigin(0,0,0); + + this->Box = vtkImageData::New(); + this->Box->SetDimensions(2,2,2); + this->Outline = vtkOutlineFilter::New(); + this->Outline->SetInput(this->Box); + this->OutlineMapper = vtkPolyDataMapper::New(); + this->OutlineMapper->SetInput(this->Outline->GetOutput()); + this->OutlineActor = vtkActor::New(); + this->OutlineActor->SetMapper(this->OutlineMapper); + this->OutlineTranslation = 1; + this->ScaleEnabled = 1; + + this->Cutter = vtkCutter::New(); + this->Cutter->SetInput(this->Box); + this->Cutter->SetCutFunction(this->Plane); + this->CutMapper = vtkPolyDataMapper::New(); + this->CutMapper->SetInput(this->Cutter->GetOutput()); + this->CutActor = vtkActor::New(); + this->CutActor->SetMapper(this->CutMapper); + this->DrawPlane = 1; + + this->Edges = vtkFeatureEdges::New(); + this->Edges->SetInput(this->Cutter->GetOutput()); + this->EdgesTuber = vtkTubeFilter::New(); + this->EdgesTuber->SetInput(this->Edges->GetOutput()); + this->EdgesTuber->SetNumberOfSides(12); + this->EdgesMapper = vtkPolyDataMapper::New(); + this->EdgesMapper->SetInput(this->EdgesTuber->GetOutput()); + this->EdgesActor = vtkActor::New(); + this->EdgesActor->SetMapper(this->EdgesMapper); + this->Tubing = 1; //control whether tubing is on + + // Create the + plane normal + this->LineSource = vtkLineSource::New(); + this->LineSource->SetResolution(1); + this->LineMapper = vtkPolyDataMapper::New(); + this->LineMapper->SetInput(this->LineSource->GetOutput()); + this->LineActor = vtkActor::New(); + this->LineActor->SetMapper(this->LineMapper); + + this->ConeSource = vtkConeSource::New(); + this->ConeSource->SetResolution(12); + this->ConeSource->SetAngle(25.0); + this->ConeMapper = vtkPolyDataMapper::New(); + this->ConeMapper->SetInput(this->ConeSource->GetOutput()); + this->ConeActor = vtkActor::New(); + this->ConeActor->SetMapper(this->ConeMapper); + + // Create the - plane normal + this->LineSource2 = vtkLineSource::New(); + this->LineSource2->SetResolution(1); + this->LineMapper2 = vtkPolyDataMapper::New(); + this->LineMapper2->SetInput(this->LineSource2->GetOutput()); + this->LineActor2 = vtkActor::New(); + this->LineActor2->SetMapper(this->LineMapper2); + + this->ConeSource2 = vtkConeSource::New(); + this->ConeSource2->SetResolution(12); + this->ConeSource2->SetAngle(25.0); + this->ConeMapper2 = vtkPolyDataMapper::New(); + this->ConeMapper2->SetInput(this->ConeSource2->GetOutput()); + this->ConeActor2 = vtkActor::New(); + this->ConeActor2->SetMapper(this->ConeMapper2); + + // Create the origin handle + this->Sphere = vtkSphereSource::New(); + this->Sphere->SetThetaResolution(16); + this->Sphere->SetPhiResolution(8); + this->SphereMapper = vtkPolyDataMapper::New(); + this->SphereMapper->SetInput(this->Sphere->GetOutput()); + this->SphereActor = vtkActor::New(); + this->SphereActor->SetMapper(this->SphereMapper); + + this->Transform = vtkTransform::New(); + + // Define the point coordinates + double bounds[6]; + bounds[0] = -0.5; + bounds[1] = 0.5; + bounds[2] = -0.5; + bounds[3] = 0.5; + bounds[4] = -0.5; + bounds[5] = 0.5; + + // Initial creation of the widget, serves to initialize it + this->PlaceWidget(bounds); + + //Manage the picking stuff + this->Picker = vtkCellPicker::New(); + this->Picker->SetTolerance(0.005); + this->Picker->AddPickList(this->CutActor); + this->Picker->AddPickList(this->LineActor); + this->Picker->AddPickList(this->ConeActor); + this->Picker->AddPickList(this->LineActor2); + this->Picker->AddPickList(this->ConeActor2); + this->Picker->AddPickList(this->SphereActor); + this->Picker->AddPickList(this->OutlineActor); + this->Picker->PickFromListOn(); + + // Set up the initial properties + this->CreateDefaultProperties(); +} + +vtkImplicitPlaneWidget::~vtkImplicitPlaneWidget() +{ + this->Plane->Delete(); + this->Box->Delete(); + this->Outline->Delete(); + this->OutlineMapper->Delete(); + this->OutlineActor->Delete(); + + this->Cutter->Delete(); + this->CutMapper->Delete(); + this->CutActor->Delete(); + + this->Edges->Delete(); + this->EdgesTuber->Delete(); + this->EdgesMapper->Delete(); + this->EdgesActor->Delete(); + + this->LineSource->Delete(); + this->LineMapper->Delete(); + this->LineActor->Delete(); + + this->ConeSource->Delete(); + this->ConeMapper->Delete(); + this->ConeActor->Delete(); + + this->LineSource2->Delete(); + this->LineMapper2->Delete(); + this->LineActor2->Delete(); + + this->ConeSource2->Delete(); + this->ConeMapper2->Delete(); + this->ConeActor2->Delete(); + + this->Sphere->Delete(); + this->SphereMapper->Delete(); + this->SphereActor->Delete(); + + this->Transform->Delete(); + + this->Picker->Delete(); + + this->NormalProperty->Delete(); + this->SelectedNormalProperty->Delete(); + this->PlaneProperty->Delete(); + this->SelectedPlaneProperty->Delete(); + this->OutlineProperty->Delete(); + this->SelectedOutlineProperty->Delete(); + this->EdgesProperty->Delete(); +} + +void vtkImplicitPlaneWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //------------------------------------------------------------ + { + vtkDebugMacro(<<"Enabling plane widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // add the outline + this->CurrentRenderer->AddActor(this->OutlineActor); + this->OutlineActor->SetProperty(this->OutlineProperty); + + // add the edges + this->CurrentRenderer->AddActor(this->EdgesActor); + this->OutlineActor->SetProperty(this->EdgesProperty); + + // add the normal vector + this->CurrentRenderer->AddActor(this->LineActor); + this->LineActor->SetProperty(this->NormalProperty); + this->CurrentRenderer->AddActor(this->ConeActor); + this->ConeActor->SetProperty(this->NormalProperty); + + this->CurrentRenderer->AddActor(this->LineActor2); + this->LineActor2->SetProperty(this->NormalProperty); + this->CurrentRenderer->AddActor(this->ConeActor2); + this->ConeActor2->SetProperty(this->NormalProperty); + + // add the origin handle + this->CurrentRenderer->AddActor(this->SphereActor); + this->SphereActor->SetProperty(this->NormalProperty); + + // add the plane (if desired) + if ( this->DrawPlane ) + { + this->CurrentRenderer->AddActor(this->CutActor); + } + this->CutActor->SetProperty(this->PlaneProperty); + + this->UpdateRepresentation(); + this->SizeHandles(); + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling---------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling plane widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the various actors + this->CurrentRenderer->RemoveActor(this->OutlineActor); + this->CurrentRenderer->RemoveActor(this->EdgesActor); + this->CurrentRenderer->RemoveActor(this->LineActor); + this->CurrentRenderer->RemoveActor(this->ConeActor); + this->CurrentRenderer->RemoveActor(this->LineActor2); + this->CurrentRenderer->RemoveActor(this->ConeActor2); + this->CurrentRenderer->RemoveActor(this->SphereActor); + this->CurrentRenderer->RemoveActor(this->CutActor); + + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkImplicitPlaneWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkImplicitPlaneWidget* self = + reinterpret_cast<vtkImplicitPlaneWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkImplicitPlaneWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->NormalProperty ) + { + os << indent << "Normal Property: " << this->NormalProperty << "\n"; + } + else + { + os << indent << "Normal Property: (none)\n"; + } + if ( this->SelectedNormalProperty ) + { + os << indent << "Selected Normal Property: " + << this->SelectedNormalProperty << "\n"; + } + else + { + os << indent << "Selected Normal Property: (none)\n"; + } + + if ( this->PlaneProperty ) + { + os << indent << "Plane Property: " << this->PlaneProperty << "\n"; + } + else + { + os << indent << "Plane Property: (none)\n"; + } + if ( this->SelectedPlaneProperty ) + { + os << indent << "Selected Plane Property: " + << this->SelectedPlaneProperty << "\n"; + } + else + { + os << indent << "Selected Plane Property: (none)\n"; + } + + if ( this->OutlineProperty ) + { + os << indent << "Outline Property: " << this->OutlineProperty << "\n"; + } + else + { + os << indent << "Outline Property: (none)\n"; + } + if ( this->SelectedOutlineProperty ) + { + os << indent << "Selected Outline Property: " + << this->SelectedOutlineProperty << "\n"; + } + else + { + os << indent << "Selected Outline Property: (none)\n"; + } + + if ( this->EdgesProperty ) + { + os << indent << "Edges Property: " << this->EdgesProperty << "\n"; + } + else + { + os << indent << "Edges Property: (none)\n"; + } + + os << indent << "Normal To X Axis: " + << (this->NormalToXAxis ? "On" : "Off") << "\n"; + os << indent << "Normal To Y Axis: " + << (this->NormalToYAxis ? "On" : "Off") << "\n"; + os << indent << "Normal To Z Axis: " + << (this->NormalToZAxis ? "On" : "Off") << "\n"; + + os << indent << "Tubing: " << (this->Tubing ? "On" : "Off") << "\n"; + os << indent << "Outline Translation: " + << (this->OutlineTranslation ? "On" : "Off") << "\n"; + os << indent << "Scale Enabled: " + << (this->ScaleEnabled ? "On" : "Off") << "\n"; + os << indent << "Draw Plane: " << (this->DrawPlane ? "On" : "Off") << "\n"; +} + + +void vtkImplicitPlaneWidget::HighlightNormal(int highlight) +{ + if ( highlight ) + { + this->LineActor->SetProperty(this->SelectedNormalProperty); + this->ConeActor->SetProperty(this->SelectedNormalProperty); + this->LineActor2->SetProperty(this->SelectedNormalProperty); + this->ConeActor2->SetProperty(this->SelectedNormalProperty); + this->SphereActor->SetProperty(this->SelectedNormalProperty); + } + else + { + this->LineActor->SetProperty(this->NormalProperty); + this->ConeActor->SetProperty(this->NormalProperty); + this->LineActor2->SetProperty(this->NormalProperty); + this->ConeActor2->SetProperty(this->NormalProperty); + this->SphereActor->SetProperty(this->NormalProperty); + } +} + + +void vtkImplicitPlaneWidget::HighlightPlane(int highlight) +{ + if ( highlight ) + { + this->CutActor->SetProperty(this->SelectedPlaneProperty); + } + else + { + this->CutActor->SetProperty(this->PlaneProperty); + } +} + + +void vtkImplicitPlaneWidget::HighlightOutline(int highlight) +{ + if ( highlight ) + { + this->OutlineActor->SetProperty(this->SelectedOutlineProperty); + } + else + { + this->OutlineActor->SetProperty(this->OutlineProperty); + } +} + + +void vtkImplicitPlaneWidget::OnLeftButtonDown() +{ + // We're only here if we are enabled + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, we can process this. See if we've picked anything. + // Make sure it's in the activated renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkImplicitPlaneWidget::Outside; + return; + } + + vtkAssemblyPath *path; + this->Picker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->Picker->GetPath(); + + if ( path == NULL ) //not picking this widget + { + this->HighlightPlane(0); + this->HighlightNormal(0); + this->HighlightOutline(0); + this->State = vtkImplicitPlaneWidget::Outside; + return; + } + + vtkProp *prop = path->GetFirstNode()->GetViewProp(); + this->ValidPick = 1; + this->Picker->GetPickPosition(this->LastPickPosition); + if ( prop == this->ConeActor || prop == this->LineActor || + prop == this->ConeActor2 || prop == this->LineActor2 ) + { + this->HighlightPlane(1); + this->HighlightNormal(1); + this->State = vtkImplicitPlaneWidget::Rotating; + } + else if ( prop == this->CutActor ) + { + this->HighlightPlane(1); + this->State = vtkImplicitPlaneWidget::Pushing; + } + else if ( prop == this->SphereActor ) + { + this->HighlightNormal(1); + this->State = vtkImplicitPlaneWidget::MovingOrigin; + } + else + { + if ( this->OutlineTranslation ) + { + this->HighlightOutline(1); + this->State = vtkImplicitPlaneWidget::MovingOutline; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImplicitPlaneWidget::OnLeftButtonUp() +{ + if ( this->State == vtkImplicitPlaneWidget::Outside ) + { + return; + } + + this->State = vtkImplicitPlaneWidget::Start; + this->HighlightPlane(0); + this->HighlightOutline(0); + this->HighlightNormal(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImplicitPlaneWidget::OnMiddleButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, we can process this. See if we've picked anything. + // Make sure it's in the activated renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkImplicitPlaneWidget::Outside; + return; + } + + // Okay, we can process this. + vtkAssemblyPath *path; + this->Picker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->Picker->GetPath(); + + if ( path == NULL ) //nothing picked + { + this->State = vtkImplicitPlaneWidget::Outside; + return; + } + + this->ValidPick = 1; + this->Picker->GetPickPosition(this->LastPickPosition); + this->State = vtkImplicitPlaneWidget::MovingPlane; + this->HighlightNormal(1); + this->HighlightPlane(1); + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImplicitPlaneWidget::OnMiddleButtonUp() +{ + if ( this->State == vtkImplicitPlaneWidget::Outside ) + { + return; + } + + this->State = vtkImplicitPlaneWidget::Start; + this->HighlightPlane(0); + this->HighlightOutline(0); + this->HighlightNormal(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImplicitPlaneWidget::OnRightButtonDown() +{ + if ( this->ScaleEnabled ) + { + this->State = vtkImplicitPlaneWidget::Scaling; + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, we can process this. See if we've picked anything. + // Make sure it's in the activated renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkImplicitPlaneWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + vtkAssemblyPath *path; + this->Picker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->Picker->GetPath(); + if ( path == NULL ) //nothing picked + { + this->State = vtkImplicitPlaneWidget::Outside; + return; + } + + this->ValidPick = 1; + this->Picker->GetPickPosition(this->LastPickPosition); + this->HighlightPlane(1); + this->HighlightOutline(1); + this->HighlightNormal(1); + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); + } +} + +void vtkImplicitPlaneWidget::OnRightButtonUp() +{ + if ( this->State == vtkImplicitPlaneWidget::Outside ) + { + return; + } + + this->State = vtkImplicitPlaneWidget::Start; + this->HighlightPlane(0); + this->HighlightOutline(0); + this->HighlightNormal(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkImplicitPlaneWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkImplicitPlaneWidget::Outside || + this->State == vtkImplicitPlaneWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z, vpn[3]; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( !camera ) + { + return; + } + + // Compute the two points defining the motion vector + this->ComputeWorldToDisplay(this->LastPickPosition[0], this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + // Process the motion + if ( this->State == vtkImplicitPlaneWidget::MovingPlane ) + { + this->TranslatePlane(prevPickPoint, pickPoint); + } + else if ( this->State == vtkImplicitPlaneWidget::MovingOutline ) + { + this->TranslateOutline(prevPickPoint, pickPoint); + } + else if ( this->State == vtkImplicitPlaneWidget::MovingOrigin ) + { + this->TranslateOrigin(prevPickPoint, pickPoint); + } + else if ( this->State == vtkImplicitPlaneWidget::Pushing ) + { + this->Push(prevPickPoint, pickPoint); + } + else if ( this->State == vtkImplicitPlaneWidget::Scaling ) + { + this->Scale(prevPickPoint, pickPoint, X, Y); + } + else if ( this->State == vtkImplicitPlaneWidget::Rotating ) + { + camera->GetViewPlaneNormal(vpn); + this->Rotate(X, Y, prevPickPoint, pickPoint, vpn); + } + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + + this->Interactor->Render(); +} + +void vtkImplicitPlaneWidget::Rotate(int X, int Y, double *p1, double *p2, double *vpn) +{ + double v[3]; //vector of motion + double axis[3]; //axis of rotation + double theta; //rotation angle + + // mouse motion vector in world space + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double *origin = this->Plane->GetOrigin(); + double *normal = this->Plane->GetNormal(); + + // Create axis of rotation and angle of rotation + vtkMath::Cross(vpn,v,axis); + if ( vtkMath::Normalize(axis) == 0.0 ) + { + return; + } + int *size = this->CurrentRenderer->GetSize(); + double l2 = (X-this->Interactor->GetLastEventPosition()[0])*(X-this->Interactor->GetLastEventPosition()[0]) + (Y-this->Interactor->GetLastEventPosition()[1])*(Y-this->Interactor->GetLastEventPosition()[1]); + theta = 360.0 * sqrt(l2/((double)size[0]*size[0]+size[1]*size[1])); + + //Manipulate the transform to reflect the rotation + this->Transform->Identity(); + this->Transform->Translate(origin[0],origin[1],origin[2]); + this->Transform->RotateWXYZ(theta,axis); + this->Transform->Translate(-origin[0],-origin[1],-origin[2]); + + //Set the new normal + double nNew[3]; + this->Transform->TransformNormal(normal,nNew); + this->Plane->SetNormal(nNew); + + this->UpdateRepresentation(); +} + +// Loop through all points and translate them +void vtkImplicitPlaneWidget::TranslatePlane(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //Translate the plane + double oNew[3]; + double *origin = this->Plane->GetOrigin(); + oNew[0] = origin[0] + v[0]; + oNew[1] = origin[1] + v[1]; + oNew[2] = origin[2] + v[2]; + this->Plane->SetOrigin(oNew); + + this->UpdateRepresentation(); +} + +// Loop through all points and translate them +void vtkImplicitPlaneWidget::TranslateOutline(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //Translate the bounding box + double *origin = this->Box->GetOrigin(); + double oNew[3]; + oNew[0] = origin[0] + v[0]; + oNew[1] = origin[1] + v[1]; + oNew[2] = origin[2] + v[2]; + this->Box->SetOrigin(oNew); + + //Translate the plane + origin = this->Plane->GetOrigin(); + oNew[0] = origin[0] + v[0]; + oNew[1] = origin[1] + v[1]; + oNew[2] = origin[2] + v[2]; + this->Plane->SetOrigin(oNew); + + this->UpdateRepresentation(); +} + +// Loop through all points and translate them +void vtkImplicitPlaneWidget::TranslateOrigin(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //Add to the current point, project back down onto plane + double *o = this->Plane->GetOrigin(); + double *n = this->Plane->GetNormal(); + double newOrigin[3]; + + newOrigin[0] = o[0] + v[0]; + newOrigin[1] = o[1] + v[1]; + newOrigin[2] = o[2] + v[2]; + + vtkPlane::ProjectPoint(newOrigin,o,n,newOrigin); + this->SetOrigin(newOrigin[0],newOrigin[1],newOrigin[2]); + this->UpdateRepresentation(); +} + +void vtkImplicitPlaneWidget::Scale(double *p1, double *p2, + int vtkNotUsed(X), int Y) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //int res = this->PlaneSource->GetXResolution(); + double *o = this->Plane->GetOrigin(); + + // Compute the scale factor + double sf = vtkMath::Norm(v) / this->Outline->GetOutput()->GetLength(); + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.0 + sf; + } + else + { + sf = 1.0 - sf; + } + + this->Transform->Identity(); + this->Transform->Translate(o[0],o[1],o[2]); + this->Transform->Scale(sf,sf,sf); + this->Transform->Translate(-o[0],-o[1],-o[2]); + + double *origin = this->Box->GetOrigin(); + double *spacing = this->Box->GetSpacing(); + double oNew[3], p[3], pNew[3]; + p[0] = origin[0] + spacing[0]; + p[1] = origin[1] + spacing[1]; + p[2] = origin[2] + spacing[2]; + + this->Transform->TransformPoint(origin,oNew); + this->Transform->TransformPoint(p,pNew); + + this->Box->SetOrigin(oNew); + this->Box->SetSpacing( (pNew[0]-oNew[0]), + (pNew[1]-oNew[1]), + (pNew[2]-oNew[2]) ); + + this->UpdateRepresentation(); +} + +void vtkImplicitPlaneWidget::Push(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + this->Plane->Push( vtkMath::Dot(v,this->Plane->GetNormal()) ); + this->SetOrigin(this->Plane->GetOrigin()); + this->UpdateRepresentation(); +} + +void vtkImplicitPlaneWidget::CreateDefaultProperties() +{ + // Normal properties + this->NormalProperty = vtkProperty::New(); + this->NormalProperty->SetColor(1,1,1); + this->NormalProperty->SetLineWidth(2); + + this->SelectedNormalProperty = vtkProperty::New(); + this->SelectedNormalProperty->SetColor(1,0,0); + this->NormalProperty->SetLineWidth(2); + + // Plane properties + this->PlaneProperty = vtkProperty::New(); + this->PlaneProperty->SetAmbient(1.0); + this->PlaneProperty->SetAmbientColor(1.0,1.0,1.0); + + this->SelectedPlaneProperty = vtkProperty::New(); + this->SelectedPlaneProperty->SetAmbient(1.0); + this->SelectedPlaneProperty->SetAmbientColor(0.0,1.0,0.0); + this->SelectedPlaneProperty->SetOpacity(0.25); + + // Outline properties + this->OutlineProperty = vtkProperty::New(); + this->OutlineProperty->SetAmbient(1.0); + this->OutlineProperty->SetAmbientColor(1.0,1.0,1.0); + + this->SelectedOutlineProperty = vtkProperty::New(); + this->SelectedOutlineProperty->SetAmbient(1.0); + this->SelectedOutlineProperty->SetAmbientColor(0.0,1.0,0.0); + + // Edge property + this->EdgesProperty = vtkProperty::New(); + this->EdgesProperty->SetAmbient(1.0); + this->EdgesProperty->SetAmbientColor(1.0,1.0,1.0); +} + +void vtkImplicitPlaneWidget::PlaceWidget(double bds[6]) +{ + int i; + double bounds[6], origin[3]; + + this->AdjustBounds(bds, bounds, origin); + + // Set up the bounding box + this->Box->SetOrigin(bounds[0],bounds[2],bounds[4]); + this->Box->SetSpacing((bounds[1]-bounds[0]),(bounds[3]-bounds[2]), + (bounds[5]-bounds[4])); + this->Outline->Update(); + + this->LineSource->SetPoint1(this->Plane->GetOrigin()); + if ( this->NormalToYAxis ) + { + this->Plane->SetNormal(0,1,0); + this->LineSource->SetPoint2(0,1,0); + } + else if ( this->NormalToZAxis ) + { + this->Plane->SetNormal(0,0,1); + this->LineSource->SetPoint2(0,0,1); + } + else //default or x-normal + { + this->Plane->SetNormal(1,0,0); + this->LineSource->SetPoint2(1,0,0); + } + + for (i=0; i<6; i++) + { + this->InitialBounds[i] = bounds[i]; + } + + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + + this->UpdateRepresentation(); + + this->SizeHandles(); +} + +// Description: +// Set the origin of the plane. +void vtkImplicitPlaneWidget::SetOrigin(double x, double y, double z) +{ + double origin[3]; + origin[0] = x; + origin[1] = y; + origin[2] = z; + this->SetOrigin(origin); +} + +// Description: +// Set the origin of the plane. +void vtkImplicitPlaneWidget::SetOrigin(double x[3]) +{ + double *bounds = this->Outline->GetOutput()->GetBounds(); + for (int i=0; i<3; i++) + { + if ( x[i] < bounds[2*i] ) + { + x[i] = bounds[2*i]; + } + else if ( x[i] > bounds[2*i+1] ) + { + x[i] = bounds[2*i+1]; + } + } + this->Plane->SetOrigin(x); + this->UpdateRepresentation(); +} + +// Description: +// Get the origin of the plane. +double* vtkImplicitPlaneWidget::GetOrigin() +{ + return this->Plane->GetOrigin(); +} + +void vtkImplicitPlaneWidget::GetOrigin(double xyz[3]) +{ + this->Plane->GetOrigin(xyz); +} + +// Description: +// Set the normal to the plane. +void vtkImplicitPlaneWidget::SetNormal(double x, double y, double z) +{ + double n[3]; + n[0] = x; + n[1] = y; + n[2] = z; + vtkMath::Normalize(n); + this->Plane->SetNormal(n); + this->UpdateRepresentation(); +} + +// Description: +// Set the normal to the plane. +void vtkImplicitPlaneWidget::SetNormal(double n[3]) +{ + this->SetNormal(n[0], n[1], n[2]); +} + +// Description: +// Get the normal to the plane. +double* vtkImplicitPlaneWidget::GetNormal() +{ + return this->Plane->GetNormal(); +} + +void vtkImplicitPlaneWidget::GetNormal(double xyz[3]) +{ + this->Plane->GetNormal(xyz); +} + +void vtkImplicitPlaneWidget::SetDrawPlane(int drawPlane) +{ + if ( drawPlane == this->DrawPlane ) + { + return; + } + + this->Modified(); + this->DrawPlane = drawPlane; + if ( this->Enabled ) + { + if ( drawPlane ) + { + this->CurrentRenderer->AddActor(this->CutActor); + } + else + { + this->CurrentRenderer->RemoveActor(this->CutActor); + } + this->Interactor->Render(); + } +} + +void vtkImplicitPlaneWidget::SetNormalToXAxis (int var) +{ + if (this->NormalToXAxis != var) + { + this->NormalToXAxis = var; + this->Modified(); + } + if (var) + { + this->NormalToYAxisOff(); + this->NormalToZAxisOff(); + } +} + +void vtkImplicitPlaneWidget::SetNormalToYAxis (int var) +{ + if (this->NormalToYAxis != var) + { + this->NormalToYAxis = var; + this->Modified(); + } + if (var) + { + this->NormalToXAxisOff(); + this->NormalToZAxisOff(); + } +} + +void vtkImplicitPlaneWidget::SetNormalToZAxis (int var) +{ + if (this->NormalToZAxis != var) + { + this->NormalToZAxis = var; + this->Modified(); + } + if (var) + { + this->NormalToXAxisOff(); + this->NormalToYAxisOff(); + } +} + +void vtkImplicitPlaneWidget::GetPolyData(vtkPolyData *pd) +{ + pd->ShallowCopy(this->Cutter->GetOutput()); +} + +vtkPolyDataAlgorithm *vtkImplicitPlaneWidget::GetPolyDataAlgorithm() +{ + return this->Cutter; +} + +void vtkImplicitPlaneWidget::GetPlane(vtkPlane *plane) +{ + if ( plane == NULL ) + { + return; + } + + plane->SetNormal(this->Plane->GetNormal()); + plane->SetOrigin(this->Plane->GetOrigin()); +} + +void vtkImplicitPlaneWidget::UpdatePlacement(void) +{ + this->Outline->Update(); + this->Cutter->Update(); + this->Edges->Update(); +} + +void vtkImplicitPlaneWidget::UpdateRepresentation() +{ + if ( ! this->CurrentRenderer ) + { + return; + } + + double *origin = this->Plane->GetOrigin(); + double *normal = this->Plane->GetNormal(); + double p2[3]; + + // Setup the plane normal + double d = this->Outline->GetOutput()->GetLength(); + + p2[0] = origin[0] + 0.30 * d * normal[0]; + p2[1] = origin[1] + 0.30 * d * normal[1]; + p2[2] = origin[2] + 0.30 * d * normal[2]; + + this->LineSource->SetPoint1(origin); + this->LineSource->SetPoint2(p2); + this->ConeSource->SetCenter(p2); + this->ConeSource->SetDirection(normal); + + p2[0] = origin[0] - 0.30 * d * normal[0]; + p2[1] = origin[1] - 0.30 * d * normal[1]; + p2[2] = origin[2] - 0.30 * d * normal[2]; + + this->LineSource2->SetPoint1(origin[0],origin[1],origin[2]); + this->LineSource2->SetPoint2(p2); + this->ConeSource2->SetCenter(p2); + this->ConeSource2->SetDirection(normal[0],normal[1],normal[2]); + + // Set up the position handle + this->Sphere->SetCenter(origin[0],origin[1],origin[2]); + + // Control the look of the edges + if ( this->Tubing ) + { + this->EdgesMapper->SetInput(this->EdgesTuber->GetOutput()); + } + else + { + this->EdgesMapper->SetInput(this->Edges->GetOutput()); + } +} + +void vtkImplicitPlaneWidget::SizeHandles() +{ + double radius = this->vtk3DWidget::SizeHandles(1.35); + + this->ConeSource->SetHeight(2.0*radius); + this->ConeSource->SetRadius(radius); + this->ConeSource2->SetHeight(2.0*radius); + this->ConeSource2->SetRadius(radius); + + this->Sphere->SetRadius(radius); + + this->EdgesTuber->SetRadius(0.25*radius); +} diff --git a/Widgets/vtkImplicitPlaneWidget.h b/Widgets/vtkImplicitPlaneWidget.h new file mode 100644 index 0000000..7df8286 --- /dev/null +++ b/Widgets/vtkImplicitPlaneWidget.h @@ -0,0 +1,334 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkImplicitPlaneWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkImplicitPlaneWidget - 3D widget for manipulating an infinite plane +// .SECTION Description +// This 3D widget defines an infinite plane that can be interactively placed +// in a scene. The widget is represented by a plane with a normal vector; the +// plane is contained by a bounding box, and where the plane intersects the +// bounding box the edges are shown (possibly tubed). The normal can be +// selected and moved to rotate the plane; the plane itself can be selected +// and translated in various directions. As the plane is moved, the implicit +// plane function and polygon (representing the plane cut against the bounding +// box) is updated. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. If the "i" key (for +// "interactor") is pressed, the vtkImplicitPlaneWidget will appear. (See +// superclass documentation for information about changing this behavior.) +// If you select the normal vector, the plane can be arbitrarily rotated. The +// plane can be translated along the normal by selecting the plane and moving +// it. The plane (the plane origin) can also be arbitrary moved by selecting +// the plane with the middle mouse button. The right mouse button can be used +// to uniformly scale the bounding box (moving "up" the box scales larger; +// moving "down" the box scales smaller). Events that occur outside of the +// widget (i.e., no part of the widget is picked) are propagated to any other +// registered obsevers (such as the interaction style). Turn off the widget +// by pressing the "i" key again (or invoke the Off() method). +// +// The vtkImplicitPlaneWidget has several methods that can be used in +// conjunction with other VTK objects. The GetPolyData() method can be used +// to get a polygonal representation (the single polygon clipped by the +// bounding box). Typical usage of the widget is to make use of the +// StartInteractionEvent, InteractionEvent, and EndInteractionEvent +// events. The InteractionEvent is called on mouse motion; the other two +// events are called on button down and button up (either left or right +// button). (Note: there is also a PlaceWidgetEvent that is invoked when +// the widget is placed with PlaceWidget().) +// +// Some additional features of this class include the ability to control the +// properties of the widget. You do this by setting property values on the +// normal vector (selected and unselected properties); the plane (selected +// and unselected properties); the outline (selected and unselected +// properties); and the edges. The edges may also be tubed or not. + +// .SECTION Caveats +// Note that the widget can be picked even when it is "behind" +// other actors. This is an intended feature and not a bug. + +// .SECTION See Also +// vtk3DWidget vtkBoxWidget vtkPlaneWidget vtkLineWidget vtkPointWidget +// vtkSphereWidget vtkImagePlaneWidget + +#ifndef __vtkImplicitPlaneWidget_h +#define __vtkImplicitPlaneWidget_h + +#include "vtkPolyDataSourceWidget.h" + +class vtkActor; +class vtkPolyDataMapper; +class vtkCellPicker; +class vtkConeSource; +class vtkLineSource; +class vtkSphereSource; +class vtkTubeFilter; +class vtkPlane; +class vtkCutter; +class vtkProperty; +class vtkImageData; +class vtkOutlineFilter; +class vtkFeatureEdges; +class vtkPolyData; +class vtkTransform; + +class VTK_WIDGETS_EXPORT vtkImplicitPlaneWidget : public vtkPolyDataSourceWidget +{ +public: + // Description: + // Instantiate the object. + static vtkImplicitPlaneWidget *New(); + + vtkTypeRevisionMacro(vtkImplicitPlaneWidget,vtkPolyDataSourceWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Get the origin of the plane. + void SetOrigin(double x, double y, double z); + void SetOrigin(double x[3]); + double* GetOrigin(); + void GetOrigin(double xyz[3]); + + // Description: + // Get the normal to the plane. + void SetNormal(double x, double y, double z); + void SetNormal(double x[3]); + double* GetNormal(); + void GetNormal(double xyz[3]); + + // Description: + // Force the plane widget to be aligned with one of the x-y-z axes. + // If one axis is set on, the other two will be set off. + // Remember that when the state changes, a ModifiedEvent is invoked. + // This can be used to snap the plane to the axes if it is orginally + // not aligned. + void SetNormalToXAxis(int); + vtkGetMacro(NormalToXAxis,int); + vtkBooleanMacro(NormalToXAxis,int); + void SetNormalToYAxis(int); + vtkGetMacro(NormalToYAxis,int); + vtkBooleanMacro(NormalToYAxis,int); + void SetNormalToZAxis(int); + vtkGetMacro(NormalToZAxis,int); + vtkBooleanMacro(NormalToZAxis,int); + + // Description: + // Turn on/off tubing of the wire outline of the plane. The tube thickens + // the line by wrapping with a vtkTubeFilter. + vtkSetMacro(Tubing,int); + vtkGetMacro(Tubing,int); + vtkBooleanMacro(Tubing,int); + + // Description: + // Enable/disable the drawing of the plane. In some cases the plane + // interferes with the object that it is operating on (i.e., the + // plane interferes with the cut surface it produces producing + // z-buffer artifacts.) + void SetDrawPlane(int plane); + vtkGetMacro(DrawPlane,int); + vtkBooleanMacro(DrawPlane,int); + + // Description: + // Turn on/off the ability to translate the bounding box by grabbing it + // with the left mouse button. + vtkSetMacro(OutlineTranslation,int); + vtkGetMacro(OutlineTranslation,int); + vtkBooleanMacro(OutlineTranslation,int); + // Description: + // Turn on/off the ability to scale with the mouse + vtkSetMacro(ScaleEnabled,int); + vtkGetMacro(ScaleEnabled,int); + vtkBooleanMacro(ScaleEnabled,int); + + // Description: + // Grab the polydata that defines the plane. The polydata contains a single + // polygon that is clipped by the bounding box. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Satisfies superclass API. This returns a pointer to the underlying + // PolyData (which represents the plane). + vtkPolyDataAlgorithm* GetPolyDataAlgorithm(); + + // Description: + // Get the implicit function for the plane. The user must provide the + // instance of the class vtkPlane. Note that vtkPlane is a subclass of + // vtkImplicitFunction, meaning that it can be used by a variety of filters + // to perform clipping, cutting, and selection of data. + void GetPlane(vtkPlane *plane); + + // Description: + // Satisfies the superclass API. This will change the state of the widget + // to match changes that have been made to the underlying PolyDataSource + void UpdatePlacement(void); + + // Description: + // Control widget appearance + virtual void SizeHandles(); + + // Description: + // Get the properties on the normal (line and cone). + vtkGetObjectMacro(NormalProperty,vtkProperty); + vtkGetObjectMacro(SelectedNormalProperty,vtkProperty); + + // Description: + // Get the plane properties. The properties of the plane when selected + // and unselected can be manipulated. + vtkGetObjectMacro(PlaneProperty,vtkProperty); + vtkGetObjectMacro(SelectedPlaneProperty,vtkProperty); + + // Description: + // Get the property of the outline. + vtkGetObjectMacro(OutlineProperty,vtkProperty); + vtkGetObjectMacro(SelectedOutlineProperty,vtkProperty); + + // Description: + // Get the property of the intersection edges. (This property also + // applies to the edges when tubed.) + vtkGetObjectMacro(EdgesProperty,vtkProperty); + +protected: + vtkImplicitPlaneWidget(); + ~vtkImplicitPlaneWidget(); + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Start=0, + MovingPlane, + MovingOutline, + MovingOrigin, + Scaling, + Pushing, + Rotating, + Outside + }; +//ETX + + //handles the events + static void ProcessEvents(vtkObject* object, unsigned long event, + void* clientdata, void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnMiddleButtonDown(); + void OnMiddleButtonUp(); + void OnRightButtonDown(); + void OnRightButtonUp(); + void OnMouseMove(); + + // Controlling ivars + int NormalToXAxis; + int NormalToYAxis; + int NormalToZAxis; + void UpdateRepresentation(); + + // The actual plane which is being manipulated + vtkPlane *Plane; + + // The bounding box is represented by a single voxel image data + vtkImageData *Box; + vtkOutlineFilter *Outline; + vtkPolyDataMapper *OutlineMapper; + vtkActor *OutlineActor; + void HighlightOutline(int highlight); + int OutlineTranslation; //whether the outline can be moved + int ScaleEnabled; //whether the widget can be scaled + + // The cut plane is produced with a vtkCutter + vtkCutter *Cutter; + vtkPolyDataMapper *CutMapper; + vtkActor *CutActor; + int DrawPlane; + void HighlightPlane(int highlight); + + // Optional tubes are represented by extracting boundary edges and tubing + vtkFeatureEdges *Edges; + vtkTubeFilter *EdgesTuber; + vtkPolyDataMapper *EdgesMapper; + vtkActor *EdgesActor; + int Tubing; //control whether tubing is on + + // The + normal cone + vtkConeSource *ConeSource; + vtkPolyDataMapper *ConeMapper; + vtkActor *ConeActor; + void HighlightNormal(int highlight); + + // The + normal line + vtkLineSource *LineSource; + vtkPolyDataMapper *LineMapper; + vtkActor *LineActor; + + // The - normal cone + vtkConeSource *ConeSource2; + vtkPolyDataMapper *ConeMapper2; + vtkActor *ConeActor2; + + // The - normal line + vtkLineSource *LineSource2; + vtkPolyDataMapper *LineMapper2; + vtkActor *LineActor2; + + // The origin positioning handle + vtkSphereSource *Sphere; + vtkPolyDataMapper *SphereMapper; + vtkActor *SphereActor; + + // Do the picking + vtkCellPicker *Picker; + + // Transform the normal (used for rotation) + vtkTransform *Transform; + + // Methods to manipulate the plane + void ConstrainOrigin(double x[3]); + void Rotate(int X, int Y, double *p1, double *p2, double *vpn); + void TranslatePlane(double *p1, double *p2); + void TranslateOutline(double *p1, double *p2); + void TranslateOrigin(double *p1, double *p2); + void Push(double *p1, double *p2); + void Scale(double *p1, double *p2, int X, int Y); + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *NormalProperty; + vtkProperty *SelectedNormalProperty; + vtkProperty *PlaneProperty; + vtkProperty *SelectedPlaneProperty; + vtkProperty *OutlineProperty; + vtkProperty *SelectedOutlineProperty; + vtkProperty *EdgesProperty; + void CreateDefaultProperties(); + + void GeneratePlane(); + +private: + vtkImplicitPlaneWidget(const vtkImplicitPlaneWidget&); //Not implemented + void operator=(const vtkImplicitPlaneWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkLineWidget.cxx b/Widgets/vtkLineWidget.cxx new file mode 100644 index 0000000..44d3c5f --- /dev/null +++ b/Widgets/vtkLineWidget.cxx @@ -0,0 +1,1075 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLineWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkLineWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellPicker.h" +#include "vtkCommand.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlanes.h" +#include "vtkPointWidget.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" + +vtkCxxRevisionMacro(vtkLineWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkLineWidget); + +// This class is used to coordinate the interaction between the point widget +// at the center of the line and the line widget. When the line is selected +// (as compared to the handles), a point widget appears at the selection +// point, which can be manipulated in the usual way. +class vtkPWCallback : public vtkCommand +{ +public: + static vtkPWCallback *New() + { return new vtkPWCallback; } + virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*) + { + double x[3]; + this->PointWidget->GetPosition(x); + this->LineWidget->SetLinePosition(x); + } + vtkPWCallback():LineWidget(0),PointWidget(0) {} + vtkLineWidget *LineWidget; + vtkPointWidget *PointWidget; +}; + +// This class is used to coordinate the interaction between the point widget +// (point 1) and the line widget. +class vtkPW1Callback : public vtkCommand +{ +public: + static vtkPW1Callback *New() + { return new vtkPW1Callback; } + virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*) + { + double x[3]; + this->PointWidget->GetPosition(x); + this->LineWidget->SetPoint1(x); + } + vtkPW1Callback():LineWidget(0),PointWidget(0) {} + vtkLineWidget *LineWidget; + vtkPointWidget *PointWidget; +}; + +// This class is used to coordinate the interaction between the point widget +// (point 2) and the line widget. +class vtkPW2Callback : public vtkCommand +{ +public: + static vtkPW2Callback *New() + { return new vtkPW2Callback; } + virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long, void*) + { + double x[3]; + this->PointWidget->GetPosition(x); + this->LineWidget->SetPoint2(x); + } + vtkPW2Callback():LineWidget(0),PointWidget(0) {} + vtkLineWidget *LineWidget; + vtkPointWidget *PointWidget; +}; + +// Begin the definition of the vtkLineWidget methods +// +vtkLineWidget::vtkLineWidget() +{ + this->State = vtkLineWidget::Start; + this->EventCallbackCommand->SetCallback(vtkLineWidget::ProcessEvents); + + this->Align = vtkLineWidget::XAxis; + + //Build the representation of the widget + int i; + // Represent the line + this->LineSource = vtkLineSource::New(); + this->LineSource->SetResolution(5); + this->LineMapper = vtkPolyDataMapper::New(); + this->LineMapper->SetInput(this->LineSource->GetOutput()); + this->LineActor = vtkActor::New(); + this->LineActor->SetMapper(this->LineMapper); + + // Create the handles + this->Handle = new vtkActor* [2]; + this->HandleMapper = new vtkPolyDataMapper* [2]; + this->HandleGeometry = new vtkSphereSource* [2]; + for (i=0; i<2; i++) + { + this->HandleGeometry[i] = vtkSphereSource::New(); + this->HandleGeometry[i]->SetThetaResolution(16); + this->HandleGeometry[i]->SetPhiResolution(8); + this->HandleMapper[i] = vtkPolyDataMapper::New(); + this->HandleMapper[i]->SetInput(this->HandleGeometry[i]->GetOutput()); + this->Handle[i] = vtkActor::New(); + this->Handle[i]->SetMapper(this->HandleMapper[i]); + } + + // Define the point coordinates + double bounds[6]; + bounds[0] = -0.5; + bounds[1] = 0.5; + bounds[2] = -0.5; + bounds[3] = 0.5; + bounds[4] = -0.5; + bounds[5] = 0.5; + this->PlaceFactor = 1.0; //overload parent's value + + // Initial creation of the widget, serves to initialize it + this->PlaceWidget(bounds); + this->ClampToBounds = 0; + + //Manage the picking stuff + this->HandlePicker = vtkCellPicker::New(); + this->HandlePicker->SetTolerance(0.001); + for (i=0; i<2; i++) + { + this->HandlePicker->AddPickList(this->Handle[i]); + } + this->HandlePicker->PickFromListOn(); + + this->LinePicker = vtkCellPicker::New(); + this->LinePicker->SetTolerance(0.005); //need some fluff + this->LinePicker->AddPickList(this->LineActor); + this->LinePicker->PickFromListOn(); + + this->CurrentHandle = NULL; + + // Set up the initial properties + this->CreateDefaultProperties(); + + // Create the point widgets and associated callbacks + this->PointWidget = vtkPointWidget::New(); + this->PointWidget->AllOff(); + this->PointWidget->SetHotSpotSize(0.5); + + this->PointWidget1 = vtkPointWidget::New(); + this->PointWidget1->AllOff(); + this->PointWidget1->SetHotSpotSize(0.5); + + this->PointWidget2 = vtkPointWidget::New(); + this->PointWidget2->AllOff(); + this->PointWidget2->SetHotSpotSize(0.5); + + this->PWCallback = vtkPWCallback::New(); + this->PWCallback->LineWidget = this; + this->PWCallback->PointWidget = this->PointWidget; + this->PW1Callback = vtkPW1Callback::New(); + this->PW1Callback->LineWidget = this; + this->PW1Callback->PointWidget = this->PointWidget1; + this->PW2Callback = vtkPW2Callback::New(); + this->PW2Callback->LineWidget = this; + this->PW2Callback->PointWidget = this->PointWidget2; + + // Very tricky, the point widgets watch for their own + // interaction events. + this->PointWidget->AddObserver(vtkCommand::InteractionEvent, + this->PWCallback, 0.0); + this->PointWidget1->AddObserver(vtkCommand::InteractionEvent, + this->PW1Callback, 0.0); + this->PointWidget2->AddObserver(vtkCommand::InteractionEvent, + this->PW2Callback, 0.0); + this->CurrentPointWidget = NULL; +} + +vtkLineWidget::~vtkLineWidget() +{ + this->LineActor->Delete(); + this->LineMapper->Delete(); + this->LineSource->Delete(); + + for (int i=0; i<2; i++) + { + this->HandleGeometry[i]->Delete(); + this->HandleMapper[i]->Delete(); + this->Handle[i]->Delete(); + } + delete [] this->Handle; + delete [] this->HandleMapper; + delete [] this->HandleGeometry; + + this->HandlePicker->Delete(); + this->LinePicker->Delete(); + + this->HandleProperty->Delete(); + this->SelectedHandleProperty->Delete(); + this->LineProperty->Delete(); + this->SelectedLineProperty->Delete(); + + this->PointWidget->RemoveObserver(this->PWCallback); + this->PointWidget1->RemoveObserver(this->PW1Callback); + this->PointWidget2->RemoveObserver(this->PW2Callback); + this->PointWidget->Delete(); + this->PointWidget1->Delete(); + this->PointWidget2->Delete(); + this->PWCallback->Delete(); + this->PW1Callback->Delete(); + this->PW2Callback->Delete(); +} + +void vtkLineWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //----------------------------------------------------------- + { + vtkDebugMacro(<<"Enabling line widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer( + this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->PointWidget->SetCurrentRenderer(this->CurrentRenderer); + this->PointWidget1->SetCurrentRenderer(this->CurrentRenderer); + this->PointWidget2->SetCurrentRenderer(this->CurrentRenderer); + + this->Enabled = 1; + + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // Add the line + this->CurrentRenderer->AddActor(this->LineActor); + this->LineActor->SetProperty(this->LineProperty); + + // turn on the handles + for (int j=0; j<2; j++) + { + this->CurrentRenderer->AddActor(this->Handle[j]); + this->Handle[j]->SetProperty(this->HandleProperty); + } + + this->BuildRepresentation(); + this->SizeHandles(); + + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling---------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling line widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the line + this->CurrentRenderer->RemoveActor(this->LineActor); + + // turn off the handles + for (int i=0; i<2; i++) + { + this->CurrentRenderer->RemoveActor(this->Handle[i]); + } + + if (this->CurrentPointWidget) + { + this->CurrentPointWidget->EnabledOff(); + } + + this->CurrentHandle = NULL; + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkLineWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkLineWidget* self = reinterpret_cast<vtkLineWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkLineWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->HandleProperty ) + { + os << indent << "Handle Property: " << this->HandleProperty << "\n"; + } + else + { + os << indent << "Handle Property: (none)\n"; + } + if ( this->SelectedHandleProperty ) + { + os << indent << "Selected Handle Property: " + << this->SelectedHandleProperty << "\n"; + } + else + { + os << indent << "Selected Handle Property: (none)\n"; + } + + if ( this->LineProperty ) + { + os << indent << "Line Property: " << this->LineProperty << "\n"; + } + else + { + os << indent << "Line Property: (none)\n"; + } + if ( this->SelectedLineProperty ) + { + os << indent << "Selected Line Property: " + << this->SelectedLineProperty << "\n"; + } + else + { + os << indent << "Selected Line Property: (none)\n"; + } + + os << indent << "Constrain To Bounds: " + << (this->ClampToBounds ? "On\n" : "Off\n"); + + os << indent << "Align with: "; + switch ( this->Align ) + { + case XAxis: + os << "X Axis"; + break; + case YAxis: + os << "Y Axis"; + break; + case ZAxis: + os << "Z Axis"; + break; + default: + os << "None"; + } + int res = this->LineSource->GetResolution(); + double *pt1 = this->LineSource->GetPoint1(); + double *pt2 = this->LineSource->GetPoint2(); + + os << indent << "Resolution: " << res << "\n"; + os << indent << "Point 1: (" << pt1[0] << ", " + << pt1[1] << ", " + << pt1[2] << ")\n"; + os << indent << "Point 2: (" << pt2[0] << ", " + << pt2[1] << ", " + << pt2[2] << ")\n"; +} + +void vtkLineWidget::BuildRepresentation() +{ + //int res = this->LineSource->GetResolution(); + double *pt1 = this->LineSource->GetPoint1(); + double *pt2 = this->LineSource->GetPoint2(); + + this->HandleGeometry[0]->SetCenter(pt1); + this->HandleGeometry[1]->SetCenter(pt2); +} + +void vtkLineWidget::SizeHandles() +{ + double radius = this->vtk3DWidget::SizeHandles(1.0); + this->HandleGeometry[0]->SetRadius(radius); + this->HandleGeometry[1]->SetRadius(radius); +} + +int vtkLineWidget::HighlightHandle(vtkProp *prop) +{ + // first unhighlight anything picked + if ( this->CurrentHandle ) + { + this->CurrentHandle->SetProperty(this->HandleProperty); + } + + // set the current handle + this->CurrentHandle = (vtkActor *)prop; + + // find the current handle + if ( this->CurrentHandle ) + { + this->ValidPick = 1; + this->HandlePicker->GetPickPosition(this->LastPickPosition); + this->CurrentHandle->SetProperty(this->SelectedHandleProperty); + return (this->CurrentHandle == this->Handle[0] ? 0 : 1); + } + else + { + return -1; + } +} + +int vtkLineWidget::ForwardEvent(unsigned long event) +{ + if ( ! this->CurrentPointWidget ) + { + return 0; + } + + this->CurrentPointWidget->ProcessEvents(this,event, + this->CurrentPointWidget,NULL); + + return 1; +} + +// assumed current handle is set +void vtkLineWidget::EnablePointWidget() +{ + // Set up the point widgets + double x[3]; + if ( this->CurrentHandle ) //picking the handles + { + if ( this->CurrentHandle == this->Handle[0] ) + { + this->CurrentPointWidget = this->PointWidget1; + this->LineSource->GetPoint1(x); + } + else + { + this->CurrentPointWidget = this->PointWidget2; + this->LineSource->GetPoint2(x); + } + } + else //picking the line + { + this->CurrentPointWidget = this->PointWidget; + this->LinePicker->GetPickPosition(x); + this->LastPosition[0] = x[0]; + this->LastPosition[1] = x[1]; + this->LastPosition[2] = x[2]; + } + + double bounds[6]; + for (int i=0; i<3; i++) + { + bounds[2*i] = x[i] - 0.1*this->InitialLength; + bounds[2*i+1] = x[i] + 0.1*this->InitialLength; + } + + // Note: translation mode is disabled and enabled to control + // the proper positioning of the bounding box. + this->CurrentPointWidget->SetInteractor(this->Interactor); + this->CurrentPointWidget->TranslationModeOff(); + this->CurrentPointWidget->SetPlaceFactor(1.0); + this->CurrentPointWidget->PlaceWidget(bounds); + this->CurrentPointWidget->TranslationModeOn(); + this->CurrentPointWidget->SetPosition(x); + this->CurrentPointWidget->SetCurrentRenderer(this->CurrentRenderer); + this->CurrentPointWidget->On(); +} + +// assumed current handle is set +void vtkLineWidget::DisablePointWidget() +{ + if (this->CurrentPointWidget) + { + this->CurrentPointWidget->Off(); + } + this->CurrentPointWidget = NULL; +} + +void vtkLineWidget::HighlightHandles(int highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->HandlePicker->GetPickPosition(this->LastPickPosition); + this->Handle[0]->SetProperty(this->SelectedHandleProperty); + this->Handle[1]->SetProperty(this->SelectedHandleProperty); + } + else + { + this->Handle[0]->SetProperty(this->HandleProperty); + this->Handle[1]->SetProperty(this->HandleProperty); + } +} + +void vtkLineWidget::HighlightLine(int highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->LinePicker->GetPickPosition(this->LastPickPosition); + this->LineActor->SetProperty(this->SelectedLineProperty); + } + else + { + this->LineActor->SetProperty(this->LineProperty); + } +} + +void vtkLineWidget::OnLeftButtonDown() +{ + int forward=0; + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkLineWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then try to pick the line. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->State = vtkLineWidget::MovingHandle; + this->HighlightHandle(path->GetFirstNode()->GetViewProp()); + this->EnablePointWidget(); + forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent); + } + else + { + this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->LinePicker->GetPath(); + if ( path != NULL ) + { + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->State = vtkLineWidget::MovingLine; + this->HighlightLine(1); + this->EnablePointWidget(); + forward = this->ForwardEvent(vtkCommand::LeftButtonPressEvent); + } + else + { + this->State = vtkLineWidget::Outside; + this->HighlightHandle(NULL); + return; + } + } + + if ( ! forward ) + { + this->Interactor->Render(); + } +} + +void vtkLineWidget::OnLeftButtonUp() +{ + if ( this->State == vtkLineWidget::Outside || + this->State == vtkLineWidget::Start ) + { + return; + } + + this->State = vtkLineWidget::Start; + this->HighlightHandle(NULL); + this->HighlightLine(0); + + this->SizeHandles(); + + int forward = this->ForwardEvent(vtkCommand::LeftButtonReleaseEvent); + this->DisablePointWidget(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + if ( ! forward ) + { + this->Interactor->Render(); + } +} + +void vtkLineWidget::OnMiddleButtonDown() +{ + int forward=0; + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkLineWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->State = vtkLineWidget::MovingLine; + this->HighlightHandles(1); + this->HighlightLine(1); + this->EnablePointWidget(); + this->ForwardEvent(vtkCommand::LeftButtonPressEvent); + } + else + { + this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->LinePicker->GetPath(); + if ( path != NULL ) + { + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + //The highlight methods set the LastPickPosition, so they are ordered + this->HighlightHandles(1); + this->HighlightLine(1); + this->State = vtkLineWidget::MovingLine; + this->EnablePointWidget(); + this->ForwardEvent(vtkCommand::LeftButtonPressEvent); + } + else + { + this->State = vtkLineWidget::Outside; + return; + } + } + + if ( ! forward ) + { + this->Interactor->Render(); + } +} + +void vtkLineWidget::OnMiddleButtonUp() +{ + if ( this->State == vtkLineWidget::Outside || + this->State == vtkLineWidget::Start ) + { + return; + } + + this->State = vtkLineWidget::Start; + this->HighlightLine(0); + this->HighlightHandles(0); + + this->SizeHandles(); + + int forward = this->ForwardEvent(vtkCommand::LeftButtonReleaseEvent); + this->DisablePointWidget(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + if ( ! forward ) + { + this->Interactor->Render(); + } +} + +void vtkLineWidget::OnRightButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkLineWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->HighlightLine(1); + this->HighlightHandles(1); + this->State = vtkLineWidget::Scaling; + } + else + { + this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->LinePicker->GetPath(); + if ( path != NULL ) + { + this->HighlightHandles(1); + this->HighlightLine(1); + this->State = vtkLineWidget::Scaling; + } + else + { + this->State = vtkLineWidget::Outside; + this->HighlightLine(0); + return; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkLineWidget::OnRightButtonUp() +{ + if ( this->State == vtkLineWidget::Outside || + this->State == vtkLineWidget::Start ) + { + return; + } + + this->State = vtkLineWidget::Start; + this->HighlightLine(0); + this->HighlightHandles(0); + + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkLineWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkLineWidget::Outside || + this->State == vtkLineWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( ! camera ) + { + return; + } + + // Compute the two points defining the motion vector + this->ComputeWorldToDisplay(this->LastPickPosition[0], + this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld( + double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + // Process the motion + int forward=0; + if ( this->State == vtkLineWidget::MovingHandle ) + { + forward = this->ForwardEvent(vtkCommand::MouseMoveEvent); + } + else if ( this->State == vtkLineWidget::MovingLine ) + { + forward = this->ForwardEvent(vtkCommand::MouseMoveEvent); + } + else if ( this->State == vtkLineWidget::Scaling ) + { + this->Scale(prevPickPoint, pickPoint, X, Y); + } + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + if ( ! forward ) + { + this->Interactor->Render(); + } +} + +void vtkLineWidget::Scale(double *p1, double *p2, int vtkNotUsed(X), int Y) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //int res = this->LineSource->GetResolution(); + double *pt1 = this->LineSource->GetPoint1(); + double *pt2 = this->LineSource->GetPoint2(); + + double center[3]; + center[0] = (pt1[0]+pt2[0]) / 2.0; + center[1] = (pt1[1]+pt2[1]) / 2.0; + center[2] = (pt1[2]+pt2[2]) / 2.0; + + // Compute the scale factor + double sf = + vtkMath::Norm(v) / sqrt(vtkMath::Distance2BetweenPoints(pt1,pt2)); + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.0 + sf; + } + else + { + sf = 1.0 - sf; + } + + // Move the end points + double point1[3], point2[3]; + for (int i=0; i<3; i++) + { + point1[i] = sf * (pt1[i] - center[i]) + center[i]; + point2[i] = sf * (pt2[i] - center[i]) + center[i]; + } + + this->LineSource->SetPoint1(point1); + this->LineSource->SetPoint2(point2); + this->LineSource->Update(); + + this->BuildRepresentation(); +} + +void vtkLineWidget::CreateDefaultProperties() +{ + // Handle properties + this->HandleProperty = vtkProperty::New(); + this->HandleProperty->SetColor(1,1,1); + + this->SelectedHandleProperty = vtkProperty::New(); + this->SelectedHandleProperty->SetColor(1,0,0); + + // Line properties + this->LineProperty = vtkProperty::New(); + this->LineProperty->SetRepresentationToWireframe(); + this->LineProperty->SetAmbient(1.0); + this->LineProperty->SetAmbientColor(1.0,1.0,1.0); + this->LineProperty->SetLineWidth(2.0); + + this->SelectedLineProperty = vtkProperty::New(); + this->SelectedLineProperty->SetRepresentationToWireframe(); + this->SelectedLineProperty->SetAmbient(1.0); + this->SelectedLineProperty->SetAmbientColor(0.0,1.0,0.0); + this->SelectedLineProperty->SetLineWidth(2.0); +} + +void vtkLineWidget::PlaceWidget(double bds[6]) +{ + int i; + double bounds[6], center[3]; + + this->AdjustBounds(bds, bounds, center); + + if ( this->Align == vtkLineWidget::YAxis ) + { + this->LineSource->SetPoint1(center[0],bounds[2],center[2]); + this->LineSource->SetPoint2(center[0],bounds[3],center[2]); + } + else if ( this->Align == vtkLineWidget::ZAxis ) + { + this->LineSource->SetPoint1(center[0],center[1],bounds[4]); + this->LineSource->SetPoint2(center[0],center[1],bounds[5]); + } + else if ( this->Align == vtkLineWidget::XAxis )//default or x-aligned + { + this->LineSource->SetPoint1(bounds[0],center[1],center[2]); + this->LineSource->SetPoint2(bounds[1],center[1],center[2]); + } + this->LineSource->Update(); + + for (i=0; i<6; i++) + { + this->InitialBounds[i] = bounds[i]; + } + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + + // Position the handles at the end of the lines + this->BuildRepresentation(); + this->SizeHandles(); +} + +void vtkLineWidget::SetPoint1(double x, double y, double z) +{ + double xyz[3]; + xyz[0] = x; xyz[1] = y; xyz[2] = z; + + if ( this->ClampToBounds ) + { + this->ClampPosition(xyz); + this->PointWidget1->SetPosition(xyz); + } + this->LineSource->SetPoint1(xyz); + this->BuildRepresentation(); +} + +void vtkLineWidget::SetPoint2(double x, double y, double z) +{ + double xyz[3]; + xyz[0] = x; xyz[1] = y; xyz[2] = z; + + if ( this->ClampToBounds ) + { + this->ClampPosition(xyz); + this->PointWidget2->SetPosition(xyz); + } + this->LineSource->SetPoint2(xyz); + this->BuildRepresentation(); +} + +void vtkLineWidget::SetLinePosition(double x[3]) +{ + double p1[3], p2[3], v[3]; + + // vector of motion + v[0] = x[0] - this->LastPosition[0]; + v[1] = x[1] - this->LastPosition[1]; + v[2] = x[2] - this->LastPosition[2]; + + // update position + this->GetPoint1(p1); + this->GetPoint2(p2); + for (int i=0; i<3; i++) + { + p1[i] += v[i]; + p2[i] += v[i]; + } + + // See whether we can move + if ( this->ClampToBounds && (!this->InBounds(p1) || !this->InBounds(p2)) ) + { + this->PointWidget->SetPosition(this->LastPosition); + return; + } + + this->SetPoint1(p1); + this->SetPoint2(p2); + + // remember last position + this->LastPosition[0] = x[0]; + this->LastPosition[1] = x[1]; + this->LastPosition[2] = x[2]; +} + + +void vtkLineWidget::ClampPosition(double x[3]) +{ + for (int i=0; i<3; i++) + { + if ( x[i] < this->InitialBounds[2*i] ) + { + x[i] = this->InitialBounds[2*i]; + } + if ( x[i] > this->InitialBounds[2*i+1] ) + { + x[i] = this->InitialBounds[2*i+1]; + } + } +} + +int vtkLineWidget::InBounds(double x[3]) +{ + for (int i=0; i<3; i++) + { + if ( x[i] < this->InitialBounds[2*i] || + x[i] > this->InitialBounds[2*i+1] ) + { + return 0; + } + } + return 1; +} + +void vtkLineWidget::GetPolyData(vtkPolyData *pd) +{ + pd->ShallowCopy(this->LineSource->GetOutput()); +} diff --git a/Widgets/vtkLineWidget.h b/Widgets/vtkLineWidget.h new file mode 100644 index 0000000..e936f0f --- /dev/null +++ b/Widgets/vtkLineWidget.h @@ -0,0 +1,282 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkLineWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkLineWidget - 3D widget for manipulating a line +// .SECTION Description +// This 3D widget defines a line that can be interactively placed in a +// scene. The line has two handles (at its endpoints), plus the line can be +// picked to translate it in the scene. A nice feature of the object is that +// the vtkLineWidget, like any 3D widget, will work with the current +// interactor style and any other widgets present in the scene. That is, if +// vtkLineWidget does not handle an event, then all other registered +// observers (including the interactor style) have an opportunity to process +// the event. Otherwise, the vtkLineWidget will terminate the processing of +// the event that it handles. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. The interactor will act +// normally until the "i" key (for "interactor") is pressed, at which point +// the vtkLineWidget will appear. (See superclass documentation for +// information about changing this behavior.) By grabbing one of the two end +// point handles (use the left mouse button), the line can be oriented and +// stretched (the other end point remains fixed). By grabbing the line +// itself, or using the middle mouse button, the entire line can be +// translated. Scaling (about the center of the line) is achieved by using +// the right mouse button. By moving the mouse "up" the render window the +// line will be made bigger; by moving "down" the render window the widget +// will be made smaller. Turn off the widget by pressing the "i" key again +// (or invoke the Off() method). (Note: picking the line or either one of the +// two end point handles causes a vtkPointWidget to appear. This widget has +// the ability to constrain motion to an axis by pressing the "shift" key +// while moving the mouse.) +// +// The vtkLineWidget has several methods that can be used in conjunction with +// other VTK objects. The Set/GetResolution() methods control the number of +// subdivisions of the line; the GetPolyData() method can be used to get the +// polygonal representation and can be used for things like seeding +// streamlines. Typical usage of the widget is to make use of the +// StartInteractionEvent, InteractionEvent, and EndInteractionEvent +// events. The InteractionEvent is called on mouse motion; the other two +// events are called on button down and button up (either left or right +// button). +// +// Some additional features of this class include the ability to control the +// properties of the widget. You can set the properties of the selected and +// unselected representations of the line. For example, you can set the +// property for the handles and line. In addition there are methods to +// constrain the line so that it is aligned along the x-y-z axes. + +// .SECTION Caveats +// Note that handles and line can be picked even when they are "behind" other +// actors. This is an intended feature and not a bug. + +// .SECTION See Also +// vtk3DWidget vtkBoxWidget vtkPlaneWidget + + +#ifndef __vtkLineWidget_h +#define __vtkLineWidget_h + +#include "vtk3DWidget.h" +#include "vtkLineSource.h" // For passing calls to it + +class vtkActor; +class vtkPolyDataMapper; +class vtkPoints; +class vtkPolyData; +class vtkProp; +class vtkProperty; +class vtkSphereSource; +class vtkCellPicker; +class vtkPointWidget; +class vtkPWCallback; +class vtkPW1Callback; +class vtkPW2Callback; + +class VTK_WIDGETS_EXPORT vtkLineWidget : public vtk3DWidget +{ +public: + // Description: + // Instantiate the object. + static vtkLineWidget *New(); + + vtkTypeRevisionMacro(vtkLineWidget,vtk3DWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Set/Get the resolution (number of subdivisions) of the line. + void SetResolution(int r) + { this->LineSource->SetResolution(r); } + int GetResolution() + { return this->LineSource->GetResolution(); } + + // Description: + // Set/Get the position of first end point. + void SetPoint1(double x, double y, double z); + void SetPoint1(double x[3]) + {this->SetPoint1(x[0], x[1], x[2]); } + double* GetPoint1() + {return this->LineSource->GetPoint1();} + void GetPoint1(double xyz[3]) + {this->LineSource->GetPoint1(xyz);} + + // Description: + // Set position of other end point. + void SetPoint2(double x, double y, double z); + void SetPoint2(double x[3]) + {this->SetPoint2(x[0], x[1], x[2]);} + double* GetPoint2() + {return this->LineSource->GetPoint2();} + void GetPoint2(double xyz[3]) + {this->LineSource->GetPoint2(xyz);} + + // Description: + // Force the line widget to be aligned with one of the x-y-z axes. + // Remember that when the state changes, a ModifiedEvent is invoked. + // This can be used to snap the line to the axes if it is orginally + // not aligned. + vtkSetClampMacro(Align, int, XAxis, None); + vtkGetMacro(Align, int); + void SetAlignToXAxis() { this->SetAlign(XAxis); } + void SetAlignToYAxis() { this->SetAlign(YAxis); } + void SetAlignToZAxis() { this->SetAlign(ZAxis); } + void SetAlignToNone() { this->SetAlign(None); } + + // Description: + // Enable/disable clamping of the point end points to the bounding box + // of the data. The bounding box is defined from the last PlaceWidget() + // invocation, and includes the effect of the PlaceFactor which is used + // to gram/shrink the bounding box. + vtkSetMacro(ClampToBounds,int); + vtkGetMacro(ClampToBounds,int); + vtkBooleanMacro(ClampToBounds,int); + + // Description: + // Grab the polydata (including points) that defines the line. The + // polydata consists of n+1 points, where n is the resolution of the + // line. These point values are guaranteed to be up-to-date when either the + // InteractionEvent or EndInteraction events are invoked. The user provides + // the vtkPolyData and the points and polyline are added to it. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Get the handle properties (the little balls are the handles). The + // properties of the handles when selected and normal can be + // manipulated. + vtkGetObjectMacro(HandleProperty,vtkProperty); + vtkGetObjectMacro(SelectedHandleProperty,vtkProperty); + + // Description: + // Get the line properties. The properties of the line when selected + // and unselected can be manipulated. + vtkGetObjectMacro(LineProperty,vtkProperty); + vtkGetObjectMacro(SelectedLineProperty,vtkProperty); + +protected: + vtkLineWidget(); + ~vtkLineWidget(); + +//BTX - manage the state of the widget + friend class vtkPWCallback; + + int State; + enum WidgetState + { + Start=0, + MovingHandle, + MovingLine, + Scaling, + Outside + }; +//ETX + + //handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnMiddleButtonDown(); + void OnMiddleButtonUp(); + void OnRightButtonDown(); + void OnRightButtonUp(); + virtual void OnMouseMove(); + + // controlling ivars + int Align; + +//BTX + enum AlignmentState { + XAxis, + YAxis, + ZAxis, + None + }; +//ETX + + // the line + vtkActor *LineActor; + vtkPolyDataMapper *LineMapper; + vtkLineSource *LineSource; + void HighlightLine(int highlight); + + // glyphs representing hot spots (e.g., handles) + vtkActor **Handle; + vtkPolyDataMapper **HandleMapper; + vtkSphereSource **HandleGeometry; + + void BuildRepresentation(); + virtual void SizeHandles(); + void HandlesOn(double length); + void HandlesOff(); + int HighlightHandle(vtkProp *prop); //returns cell id + void HighlightHandles(int highlight); + + // Do the picking + vtkCellPicker *HandlePicker; + vtkCellPicker *LinePicker; + vtkActor *CurrentHandle; + double LastPosition[3]; + void SetLinePosition(double x[3]); + + // Methods to manipulate the hexahedron. + void Scale(double *p1, double *p2, int X, int Y); + + // Initial bounds + int ClampToBounds; + void ClampPosition(double x[3]); + int InBounds(double x[3]); + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *HandleProperty; + vtkProperty *SelectedHandleProperty; + vtkProperty *LineProperty; + vtkProperty *SelectedLineProperty; + void CreateDefaultProperties(); + + void GenerateLine(); + + // Methods for managing the point widgets used to control the endpoints + vtkPointWidget *PointWidget; + vtkPointWidget *PointWidget1; + vtkPointWidget *PointWidget2; + vtkPWCallback *PWCallback; + vtkPW1Callback *PW1Callback; + vtkPW2Callback *PW2Callback; + vtkPointWidget *CurrentPointWidget; + void EnablePointWidget(); + void DisablePointWidget(); + int ForwardEvent(unsigned long event); + +private: + vtkLineWidget(const vtkLineWidget&); //Not implemented + void operator=(const vtkLineWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkOrientationMarkerWidget.cxx b/Widgets/vtkOrientationMarkerWidget.cxx new file mode 100644 index 0000000..6f26e7a --- /dev/null +++ b/Widgets/vtkOrientationMarkerWidget.cxx @@ -0,0 +1,811 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOrientationMarkerWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkOrientationMarkerWidget.h" + +#include "vtkActor2D.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCoordinate.h" +#include "vtkObjectFactory.h" +#include "vtkPoints.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkProperty2D.h" +#include "vtkProp.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" + +vtkStandardNewMacro(vtkOrientationMarkerWidget); +vtkCxxRevisionMacro(vtkOrientationMarkerWidget, "$Revision: 1.1 $"); + +vtkCxxSetObjectMacro(vtkOrientationMarkerWidget, OrientationMarker, vtkProp); + +class vtkOrientationMarkerWidgetObserver : public vtkCommand +{ +public: + static vtkOrientationMarkerWidgetObserver *New() + {return new vtkOrientationMarkerWidgetObserver;}; + + vtkOrientationMarkerWidgetObserver() + { + this->OrientationMarkerWidget = 0; + } + + virtual void Execute(vtkObject* wdg, unsigned long event, void *calldata) + { + if (this->OrientationMarkerWidget) + { + this->OrientationMarkerWidget->ExecuteCameraUpdateEvent(wdg, event, calldata); + } + } + + vtkOrientationMarkerWidget *OrientationMarkerWidget; +}; + +vtkOrientationMarkerWidget::vtkOrientationMarkerWidget() +{ + this->StartEventObserverId = 0; + this->EventCallbackCommand->SetCallback( vtkOrientationMarkerWidget::ProcessEvents ); + + this->Observer = vtkOrientationMarkerWidgetObserver::New(); + this->Observer->OrientationMarkerWidget = this; + + this->Renderer = vtkRenderer::New(); + this->Renderer->SetViewport( 0.0, 0.0, 0.2, 0.2 ); + this->Renderer->SetLayer( 1 ); + this->Renderer->InteractiveOff(); + + this->Priority = 0.55; + this->OrientationMarker = NULL; + this->State = vtkOrientationMarkerWidget::Outside; + this->Interactive = 1; + + this->Outline = vtkPolyData::New(); + this->Outline->Allocate(); + vtkPoints *points = vtkPoints::New(); + vtkIdType ptIds[5]; + ptIds[4] = ptIds[0] = points->InsertNextPoint( 1, 1, 0 ); + ptIds[1] = points->InsertNextPoint( 2, 1, 0 ); + ptIds[2] = points->InsertNextPoint( 2, 2, 0 ); + ptIds[3] = points->InsertNextPoint( 1, 2, 0 ); + + this->Outline->SetPoints( points ); + this->Outline->InsertNextCell( VTK_POLY_LINE, 5, ptIds ); + + vtkCoordinate *tcoord = vtkCoordinate::New(); + tcoord->SetCoordinateSystemToDisplay(); + + vtkPolyDataMapper2D *mapper = vtkPolyDataMapper2D::New(); + mapper->SetInput( this->Outline ); + mapper->SetTransformCoordinate( tcoord ); + + this->OutlineActor = vtkActor2D::New(); + this->OutlineActor->SetMapper( mapper ); + this->OutlineActor->SetPosition( 0, 0 ); + this->OutlineActor->SetPosition2( 1, 1 ); + + points->Delete(); + mapper->Delete(); + tcoord->Delete(); +} + +vtkOrientationMarkerWidget::~vtkOrientationMarkerWidget() +{ + this->Observer->Delete(); + this->Renderer->Delete(); + this->SetOrientationMarker( NULL ); + this->OutlineActor->Delete(); + this->Outline->Delete(); +} + +void vtkOrientationMarkerWidget::SetEnabled(int enabling) +{ + if (!this->Interactor) + { + vtkErrorMacro("The interactor must be set prior to enabling/disabling widget"); + } + + if (enabling) + { + if (this->Enabled) + { + return; + } + + if (!this->OrientationMarker) + { + vtkErrorMacro("An orientation marker must be set prior to enabling/disabling widget"); + return; + } + + if (!this->CurrentRenderer) + { + this->SetCurrentRenderer( this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + vtkRenderWindow* renwin = this->CurrentRenderer->GetRenderWindow(); + renwin->AddRenderer( this->Renderer ); + if (renwin->GetNumberOfLayers() < 2) + { + renwin->SetNumberOfLayers( 2 ); + } + + this->Renderer->AddViewProp( this->OutlineActor ); + this->OutlineActor->VisibilityOff(); + this->Renderer->AddViewProp( this->OrientationMarker ); + this->OrientationMarker->VisibilityOn(); + + if (this->Interactive) + { + vtkRenderWindowInteractor *i = this->Interactor; + if ( this->EventCallbackCommand ) + { + i->AddObserver( vtkCommand::MouseMoveEvent, + this->EventCallbackCommand, this->Priority ); + i->AddObserver( vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority ); + i->AddObserver( vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority ); + } + } + + vtkCamera* pcam = this->CurrentRenderer->GetActiveCamera(); + vtkCamera* cam = this->Renderer->GetActiveCamera(); + if (pcam && cam) + { + cam->SetParallelProjection( pcam->GetParallelProjection() ); + } + + // We need to copy the camera before the compositing observer is called. + // Compositing temporarily changes the camera to display an image. + this->StartEventObserverId = this->CurrentRenderer->AddObserver( + vtkCommand::StartEvent, this->Observer, 1 ); + this->InvokeEvent( vtkCommand::EnableEvent, NULL ); + } + else + { + if (!this->Enabled) + { + return; + } + + this->Enabled = 0; + this->Interactor->RemoveObserver( this->EventCallbackCommand ); + + this->OrientationMarker->VisibilityOff(); + this->Renderer->RemoveViewProp( this->OrientationMarker ); + this->OutlineActor->VisibilityOff(); + this->Renderer->RemoveViewProp( this->OutlineActor ); + + // if the render window is still around, remove our renderer from it + if (this->CurrentRenderer->GetRenderWindow()) + { + this->CurrentRenderer->GetRenderWindow()-> + RemoveRenderer( this->Renderer ); + } + if ( this->StartEventObserverId != 0 ) + { + this->CurrentRenderer->RemoveObserver( this->StartEventObserverId ); + } + + this->InvokeEvent( vtkCommand::DisableEvent, NULL ); + this->SetCurrentRenderer( NULL ); + } +} + +void vtkOrientationMarkerWidget::ExecuteCameraUpdateEvent(vtkObject *vtkNotUsed(o), + unsigned long vtkNotUsed(event), + void *vtkNotUsed(calldata)) +{ + if (!this->CurrentRenderer) + { + return; + } + + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + double pos[3], fp[3], viewup[3]; + cam->GetPosition( pos ); + cam->GetFocalPoint( fp ); + cam->GetViewUp( viewup ); + + cam = this->Renderer->GetActiveCamera(); + cam->SetPosition( pos ); + cam->SetFocalPoint( fp ); + cam->SetViewUp( viewup ); + this->Renderer->ResetCamera(); + + this->UpdateOutline(); +} + +int vtkOrientationMarkerWidget::ComputeStateBasedOnPosition(int X, int Y, + int *pos1, int *pos2) +{ + int result; + + // what are we modifying? The position, or size? + // if size what piece? + // if we are within 7 pixels of an edge... + int e1 = 0; + int e2 = 0; + int e3 = 0; + int e4 = 0; + if (X - pos1[0] < 7) + { + e1 = 1; + } + if (pos2[0] - X < 7) + { + e3 = 1; + } + if (Y - pos1[1] < 7) + { + e2 = 1; + } + if (pos2[1] - Y < 7) + { + e4 = 1; + } + + // assume we are moving + result = vtkOrientationMarkerWidget::Moving; + // unless we are on a corner or edges + if (e1) + { + if (e2) + { + result = vtkOrientationMarkerWidget::AdjustingP1; // lower left + } + if (e4) + { + result = vtkOrientationMarkerWidget::AdjustingP4; // upper left + } + } + if (e3) + { + if (e2) + { + result = vtkOrientationMarkerWidget::AdjustingP2; // lower right + } + if (e4) + { + result = vtkOrientationMarkerWidget::AdjustingP3; // upper right + } + } + + return result; +} + +void vtkOrientationMarkerWidget::SetCursor(int state) +{ + switch (state) + { + case vtkOrientationMarkerWidget::AdjustingP1: + this->Interactor->GetRenderWindow()->SetCurrentCursor( VTK_CURSOR_SIZESW ); + break; + case vtkOrientationMarkerWidget::AdjustingP3: + this->Interactor->GetRenderWindow()->SetCurrentCursor( VTK_CURSOR_SIZENE ); + break; + case vtkOrientationMarkerWidget::AdjustingP2: + this->Interactor->GetRenderWindow()->SetCurrentCursor( VTK_CURSOR_SIZESE ); + break; + case vtkOrientationMarkerWidget::AdjustingP4: + this->Interactor->GetRenderWindow()->SetCurrentCursor( VTK_CURSOR_SIZENW ); + break; + case vtkOrientationMarkerWidget::Moving: + this->Interactor->GetRenderWindow()->SetCurrentCursor( VTK_CURSOR_SIZEALL ); + break; + } +} + +void vtkOrientationMarkerWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void *clientdata, + void* vtkNotUsed(calldata)) +{ + vtkOrientationMarkerWidget *self = + reinterpret_cast<vtkOrientationMarkerWidget*>( clientdata ); + + if (!self->GetInteractive()) + { + return; + } + + switch (event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkOrientationMarkerWidget::OnLeftButtonDown() +{ + // We're only here if we are enabled + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // are we over the widget? + double vp[4]; + this->Renderer->GetViewport( vp ); + + this->Renderer->NormalizedDisplayToDisplay( vp[0], vp[1] ); + this->Renderer->NormalizedDisplayToDisplay( vp[2], vp[3] ); + + int pos1[2] = { static_cast<int>( vp[0] ), static_cast<int>( vp[1] ) }; + int pos2[2] = { static_cast<int>( vp[2] ), static_cast<int>( vp[3] ) }; + + // are we not over the xy plot, ignore + if (X < pos1[0] || X > pos2[0] || Y < pos1[1] || Y > pos2[1]) + { + this->State = vtkOrientationMarkerWidget::Outside; + return; + } + + this->StartPosition[0] = X; + this->StartPosition[1] = Y; + + this->State = this->ComputeStateBasedOnPosition( X, Y, pos1, pos2 ); + this->SetCursor( this->State ); + + this->EventCallbackCommand->SetAbortFlag( 1 ); + this->StartInteraction(); + this->InvokeEvent( vtkCommand::StartInteractionEvent, NULL ); +} + +void vtkOrientationMarkerWidget::OnLeftButtonUp() +{ + if (this->State == vtkOrientationMarkerWidget::Outside) + { + return; + } + + // finalize any corner adjustments + this->SquareRenderer(); + + // stop adjusting + this->State = vtkOrientationMarkerWidget::Outside; + + this->Interactor->GetRenderWindow()->SetCurrentCursor( VTK_CURSOR_DEFAULT ); + this->EndInteraction(); + this->InvokeEvent( vtkCommand::EndInteractionEvent, NULL ); + this->Interactor->Render(); +} + +void vtkOrientationMarkerWidget::SquareRenderer() +{ + int *size = this->Renderer->GetSize(); + if (size[0] == 0 || size[1] == 0) + { + return; + } + + double vp[4]; + this->Renderer->GetViewport(vp); + + // get the minimum viewport edge size + // + double dx = vp[2] - vp[0]; + double dy = vp[3] - vp[1]; + + if (dx != dy) + { + double delta = dx < dy ? dx : dy; + + switch (this->State) + { + case vtkOrientationMarkerWidget::AdjustingP1: + vp[2] = vp[0] + delta; + vp[3] = vp[1] + delta; + break; + case vtkOrientationMarkerWidget::AdjustingP2: + vp[0] = vp[2] - delta; + vp[3] = vp[1] + delta; + break; + case vtkOrientationMarkerWidget::AdjustingP3: + vp[0] = vp[2] - delta; + vp[1] = vp[3] - delta; + break; + case vtkOrientationMarkerWidget::AdjustingP4: + vp[2] = vp[0] + delta; + vp[1] = vp[3] - delta; + break; + } + this->Renderer->SetViewport( vp ); + } +} + +void vtkOrientationMarkerWidget::UpdateOutline() +{ + double vp[4]; + this->Renderer->GetViewport( vp ); + + this->Renderer->NormalizedDisplayToDisplay( vp[0], vp[1] ); + this->Renderer->NormalizedDisplayToDisplay( vp[2], vp[3] ); + + vtkPoints *points = this->Outline->GetPoints(); + + points->SetPoint( 0, vp[0]+1, vp[1]+1, 0 ); + points->SetPoint( 1, vp[2]-1, vp[1]+1, 0 ); + points->SetPoint( 2, vp[2]-1, vp[3]-1, 0 ); + points->SetPoint( 3, vp[0]+1, vp[3]-1, 0 ); +} + +void vtkOrientationMarkerWidget::SetInteractive(int interact) +{ + if (this->Interactor && this->Enabled) + { + if (this->Interactive == interact) + { + return; + } + if (interact) + { + vtkRenderWindowInteractor *i = this->Interactor; + if ( this->EventCallbackCommand ) + { + i->AddObserver( vtkCommand::MouseMoveEvent, + this->EventCallbackCommand, this->Priority ); + i->AddObserver( vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority ); + i->AddObserver( vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority ); + } + } + else + { + this->Interactor->RemoveObserver( this->EventCallbackCommand ); + } + this->Interactive = interact; + this->Interactor->Render(); + } + else + { + vtkGenericWarningMacro("Set interactor and Enabled before changing \ + interaction."); + } +} + +void vtkOrientationMarkerWidget::OnMouseMove() +{ + // compute some info we need for all cases + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + double vp[4]; + this->Renderer->GetViewport( vp ); + + // compute display bounds of the widget to see if we are inside or outside + this->Renderer->NormalizedDisplayToDisplay( vp[0], vp[1] ); + this->Renderer->NormalizedDisplayToDisplay( vp[2], vp[3] ); + + int pos1[2] = { static_cast<int>( vp[0] ), static_cast<int>( vp[1] ) }; + int pos2[2] = { static_cast<int>( vp[2] ), static_cast<int>( vp[3] ) }; + + if (this->State == vtkOrientationMarkerWidget::Outside || + this->State == vtkOrientationMarkerWidget::Inside) + { + + if (this->State == vtkOrientationMarkerWidget::Outside) + { + // if we are not over the widget, ignore + if (X < pos1[0] || X > pos2[0] || Y < pos1[1] || Y > pos2[1]) + { + return; + } + // otherwise change our state to inside + this->State = vtkOrientationMarkerWidget::Inside; + } + + // if inside, set the cursor to the correct shape + if (this->State == vtkOrientationMarkerWidget::Inside) + { + // if we have left then change cursor back to default + if (X < pos1[0] || X > pos2[0] || Y < pos1[1] || Y > pos2[1]) + { + this->State = vtkOrientationMarkerWidget::Outside; + this->Interactor->GetRenderWindow()->SetCurrentCursor( VTK_CURSOR_DEFAULT ); + } + else + { + // adjust the cursor based on our position + // this bypasses setting the State ivar to show the user + // what would happen if they actually pressed the mouse button + this->SetCursor( this->ComputeStateBasedOnPosition( X, Y, pos1, pos2) ); + } + } + + // any state other than Outside will do + this->OutlineActor->SetVisibility( this->State ); + this->Interactor->Render(); + return; + } + + // based on the state set when the left mouse button is clicked, + // adjust the renderer's viewport + switch (this->State) + { + case vtkOrientationMarkerWidget::AdjustingP1: + this->ResizeBottomLeft( X, Y ); + break; + case vtkOrientationMarkerWidget::AdjustingP2: + this->ResizeBottomRight( X, Y ); + break; + case vtkOrientationMarkerWidget::AdjustingP3: + this->ResizeTopRight( X, Y ); + break; + case vtkOrientationMarkerWidget::AdjustingP4: + this->ResizeTopLeft( X, Y ); + break; + case vtkOrientationMarkerWidget::Moving: + this->MoveWidget( X, Y ); + break; + } + + this->UpdateOutline(); + this->EventCallbackCommand->SetAbortFlag( 1 ); + this->InvokeEvent( vtkCommand::InteractionEvent, NULL ); + this->Interactor->Render(); +} + +void vtkOrientationMarkerWidget::MoveWidget(int X, int Y) +{ + int dx = X - this->StartPosition[0]; + int dy = Y - this->StartPosition[1]; + + this->StartPosition[0] = X; + this->StartPosition[1] = Y; + + int *size = this->CurrentRenderer->GetSize(); + double dxNorm = dx / (double)size[0]; + double dyNorm = dy / (double)size[1]; + + double *vp = this->Renderer->GetViewport(); + + double newPos[4]; + newPos[0] = vp[0] + dxNorm; + newPos[1] = vp[1] + dyNorm; + newPos[2] = vp[2] + dxNorm; + newPos[3] = vp[3] + dyNorm; + + if (newPos[0] < 0.0) + { + newPos[0] = 0.0; + newPos[2] = vp[2] - vp[0]; + this->StartPosition[0] = static_cast<int>( 0.5*size[0]*newPos[2] ); + } + if (newPos[1] < 0.0) + { + newPos[1] = 0.0; + newPos[3] = vp[3] - vp[1]; + this->StartPosition[1] = static_cast<int>( 0.5*size[1]*newPos[3] ); + } + if (newPos[2] > 1.0) + { + newPos[0] = 1.0 - (vp[2] - vp[0]); + newPos[2] = 1.0; + this->StartPosition[0] = static_cast<int>( size[0]*(newPos[0] + \ + 0.5*(vp[2] - vp[0])) ); + } + if (newPos[3] > 1.0) + { + newPos[1] = 1.0 - (vp[3] - vp[1]); + newPos[3] = 1.0; + this->StartPosition[1] = static_cast<int>( size[1]*(newPos[1] + \ + 0.5*(vp[3] - vp[1])) ); + } + + this->Renderer->SetViewport( newPos ); +} + +void vtkOrientationMarkerWidget::ResizeTopLeft(int X, int Y) +{ + int dx = X - this->StartPosition[0]; + int dy = Y - this->StartPosition[1]; + + int *size = this->CurrentRenderer->GetSize(); + + double *vp = this->Renderer->GetViewport(); + + double newPos[4]; + newPos[0] = vp[0] + dx / (double)size[0]; + newPos[1] = vp[1]; + newPos[2] = vp[2]; + newPos[3] = vp[3] + dy / (double)size[1]; + + if (newPos[0] < 0.0) + { + newPos[0] = 0.0; + } + if (newPos[0] >= newPos[2] - 0.01) // keep from making it too small + { + newPos[0] = newPos[2] - 0.01; + } + if (newPos[3] > 1.0) + { + newPos[3] = 1.0; + } + if (newPos[3] <= newPos[1] + 0.01) + { + newPos[3] = newPos[1] + 0.01; + } + + this->StartPosition[0] = static_cast<int>( newPos[0]*size[0] ); + this->StartPosition[1] = static_cast<int>( newPos[3]*size[1] ); + + this->Renderer->SetViewport( newPos ); +} + +void vtkOrientationMarkerWidget::ResizeTopRight(int X, int Y) +{ + int dx = X - this->StartPosition[0]; + int dy = Y - this->StartPosition[1]; + + int *size = this->CurrentRenderer->GetSize(); + + double *vp = this->Renderer->GetViewport(); + + double newPos[4]; + newPos[0] = vp[0]; + newPos[1] = vp[1]; + newPos[2] = vp[2] + dx / (double)size[0]; + newPos[3] = vp[3] + dy / (double)size[1]; + + if (newPos[2] > 1.0) + { + newPos[2] = 1.0; + } + if (newPos[2] <= newPos[0] + 0.01) // keep from making it too small + { + newPos[2] = newPos[0] + 0.01; + } + if (newPos[3] > 1.0) + { + newPos[3] = 1.0; + } + if (newPos[3] <= newPos[1] + 0.01) + { + newPos[3] = newPos[1] + 0.01; + } + + this->StartPosition[0] = static_cast<int>( newPos[2]*size[0] ); + this->StartPosition[1] = static_cast<int>( newPos[3]*size[1] ); + + this->Renderer->SetViewport( newPos ); +} + +void vtkOrientationMarkerWidget::ResizeBottomRight(int X, int Y) +{ + int dx = X - this->StartPosition[0]; + int dy = Y - this->StartPosition[1]; + + int *size = this->CurrentRenderer->GetSize(); + + double *vp = this->Renderer->GetViewport(); + + double newPos[4]; + newPos[0] = vp[0]; + newPos[1] = vp[1] + dy / (double)size[1]; + newPos[2] = vp[2] + dx / (double)size[0]; + newPos[3] = vp[3]; + + if (newPos[2] > 1.0) + { + newPos[2] = 1.0; + } + if (newPos[2] <= newPos[0] + 0.01) // keep from making it too small + { + newPos[2] = newPos[0] + 0.01; + } + if (newPos[1] < 0.0) + { + newPos[1] = 0.0; + } + if (newPos[1] >= newPos[3] - 0.01) + { + newPos[1] = newPos[3] - 0.01; + } + + this->StartPosition[0] = static_cast<int>( newPos[2]*size[0] ); + this->StartPosition[1] = static_cast<int>( newPos[1]*size[1] ); + + this->Renderer->SetViewport( newPos ); +} + +void vtkOrientationMarkerWidget::ResizeBottomLeft(int X, int Y) +{ + int dx = X - this->StartPosition[0]; + int dy = Y - this->StartPosition[1]; + + int *size = this->CurrentRenderer->GetSize(); + + double *vp = this->Renderer->GetViewport(); + + double newPos[4]; + newPos[0] = vp[0] + dx / (double)size[0]; + newPos[1] = vp[1] + dy / (double)size[1]; + newPos[2] = vp[2]; + newPos[3] = vp[3]; + + if (newPos[0] < 0.0) + { + newPos[0] = 0.0; + } + if (newPos[0] >= newPos[2] - 0.01) // keep from making it too small + { + newPos[0] = newPos[2] - 0.01; + } + if (newPos[1] < 0.0) + { + newPos[1] = 0.0; + } + if (newPos[1] >= newPos[3] - 0.01) + { + newPos[1] = newPos[3] - 0.01; + } + + this->StartPosition[0] = static_cast<int>( newPos[0]*size[0] ); + this->StartPosition[1] = static_cast<int>( newPos[1]*size[1] ); + + this->Renderer->SetViewport( newPos ); +} + +void vtkOrientationMarkerWidget::SetOutlineColor(double r, double g, double b) +{ + this->OutlineActor->GetProperty()->SetColor( r, g, b ); + if (this->Interactor) + { + this->Interactor->Render(); + } +} + +double* vtkOrientationMarkerWidget::GetOutlineColor() +{ + return this->OutlineActor->GetProperty()->GetColor(); +} + +void vtkOrientationMarkerWidget::SetViewport(double minX, double minY, + double maxX, double maxY) +{ + this->Renderer->SetViewport( minX, minY, maxX, maxY ); +} + +double* vtkOrientationMarkerWidget::GetViewport() +{ + return this->Renderer->GetViewport(); +} + +void vtkOrientationMarkerWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + + os << indent << "OrientationMarker: " << this->OrientationMarker << endl; + os << indent << "Interactive: " << this->Interactive << endl; +} diff --git a/Widgets/vtkOrientationMarkerWidget.h b/Widgets/vtkOrientationMarkerWidget.h new file mode 100644 index 0000000..485c402 --- /dev/null +++ b/Widgets/vtkOrientationMarkerWidget.h @@ -0,0 +1,179 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkOrientationMarkerWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkOrientationMarkerWidget - 2D widget for manipulating a marker prop +// .SECTION Description +// This class provides support for interactively manipulating the position, +// size, and apparent orientation of a prop that represents an orientation +// marker. This class works by adding its internal renderer to an external +// "parent" renderer on a different layer. The input orientation marker is +// rendered as an overlay on the parent renderer and, thus, appears superposed +// over all props in the parent's scene. The camera view of the orientation +// the marker is made to match that of the parent's by means of an observer +// mechanism, giving the illusion that the orientation of the marker relfects +// that of the prop(s) in the parent's scene. +// +// The widget listens to left mouse button and mouse movement events. It will +// change the cursor shape based on its location. If the cursor is over the +// overlay renderer, it will change the cursor shape to a SIZEALL shape +// or to a resize corner shape (e.g., SIZENW) if the cursor is near a corner. +// If the left mouse button is pressed and held down while moving, the overlay +// renderer, and hence, the orientation marker, is resized or moved. I the case +// of a resize operation, releasing the left mouse button causes the widget +// to enforce its renderer to be square. The diagonally opposite corner to the +// one moved is repositioned such that all edges of the renderer have the same +// length: the minimum. +// +// To use this object, there are two key steps: 1) invoke SetInteractor() with +// the argument of the method a vtkRenderWindowInteractor, and 2) invoke +// SetOrientationMarker with an instance of vtkProp (see caveats below). +// Specifically, vtkAxesActor and vtkAnnoatedCubeActor are two classes +// designed to work with this class. A composite orientation marker can be +// generated by adding instances of vtkAxesActor and vtkAnnoatedCubeActor to a +// vtkPropAssembly, which can then be set as the input orientation marker. +// The widget can be also be set up in a non-interactive fashion by setting +// Ineractive to Off and sizing/placing the overlay renderer in its parent +// renderer by calling the widget's SetViewport method. + +// .SECTION Thanks +// This class was based originally on Paraview's vtkPVAxesWidget. + +// .SECTION Caveats +// The input orientation marker prop should calculate its bounds as though they +// are symmetric about it's origin. This must currently be done to correctly +// implement the camera synchronization between the ivar renderer and the +// renderer associated with the set interactor. Importantly, the InteractorStyle +// associated with the interactor must be of the type vtkInteractorStyle*Camera. +// Where desirable, the parent renderer should be set by the SetDefaultRenderer +// method. The parent renderer's number of layers is modified to 2 where +// required. + +// .SECTION See Also +// vtkInteractorObserver vtkXYPlotWidget vtkScalarBarWidget vtkAxesActor +// vtkAnnotatedCubeActor + +#ifndef __vtkOrientationMarkerWidget_h +#define __vtkOrientationMarkerWidget_h + +#include "vtkInteractorObserver.h" + +class vtkActor2D; +class vtkPolyData; +class vtkProp; +class vtkOrientationMarkerWidgetObserver; +class vtkRenderer; + +class VTK_WIDGETS_EXPORT vtkOrientationMarkerWidget : public vtkInteractorObserver +{ +public: + static vtkOrientationMarkerWidget* New(); + vtkTypeRevisionMacro(vtkOrientationMarkerWidget, vtkInteractorObserver); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Set/get the orientation marker to be displayed in this widget. + virtual void SetOrientationMarker(vtkProp *prop); + vtkGetObjectMacro(OrientationMarker, vtkProp); + + // Description: + // Enable/disable the widget. + virtual void SetEnabled(int); + + // Description: + // Callback to keep the camera for the orientation marker up to date with the + // camera in the parent renderer. + void ExecuteCameraUpdateEvent(vtkObject *o, unsigned long event, void *calldata); + + // Description: + // Set/get whether to allow this widget to be interactively moved/scaled. + void SetInteractive(int state); + vtkGetMacro(Interactive, int); + vtkBooleanMacro(Interactive, int); + + // Description: + // Set/get the color of the outline of this widget. The outline is visible + // when (in interactive mode) the cursor is over this widget. + void SetOutlineColor(double r, double g, double b); + double *GetOutlineColor(); + + // Description: + // Set/get the viewport to position/size this widget. + void SetViewport(double minX, double minY, double maxX, double maxY); + double* GetViewport(); + +protected: + vtkOrientationMarkerWidget(); + ~vtkOrientationMarkerWidget(); + + vtkRenderer *Renderer; + vtkProp *OrientationMarker; + vtkPolyData *Outline; + vtkActor2D *OutlineActor; + + unsigned long StartEventObserverId; + + static void ProcessEvents(vtkObject *object, unsigned long event, + void *clientdata, void *calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnMouseMove(); + + // observer to update the renderer's camera + vtkOrientationMarkerWidgetObserver *Observer; + + int Interactive; + + // used to compute relative movements + int StartPosition[2]; + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Outside = 0, + Inside, + Moving, + AdjustingP1, + AdjustingP2, + AdjustingP3, + AdjustingP4 + }; +//ETX + + + // use to determine what state the mouse is over, edge1 p1, etc. + // returns a state from the WidgetState enum above + int ComputeStateBasedOnPosition(int X, int Y, int *pos1, int *pos2); + + // set the cursor to the correct shape based on State argument + void SetCursor(int state); + + // adjust the viewport depending on state + void MoveWidget(int X, int Y); + void ResizeTopLeft(int X, int Y); + void ResizeTopRight(int X, int Y); + void ResizeBottomLeft(int X, int Y); + void ResizeBottomRight(int X, int Y); + + void SquareRenderer(); + void UpdateOutline(); + +private: + vtkOrientationMarkerWidget(const vtkOrientationMarkerWidget&); // Not implemented + void operator=(const vtkOrientationMarkerWidget&); // Not implemented +}; + +#endif diff --git a/Widgets/vtkPlaneWidget.cxx b/Widgets/vtkPlaneWidget.cxx new file mode 100644 index 0000000..ac27b41 --- /dev/null +++ b/Widgets/vtkPlaneWidget.cxx @@ -0,0 +1,1540 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlaneWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPlaneWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkCellPicker.h" +#include "vtkConeSource.h" +#include "vtkDoubleArray.h" +#include "vtkFloatArray.h" +#include "vtkLineSource.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPlaneSource.h" +#include "vtkPlanes.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkPlaneWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPlaneWidget); + +vtkCxxSetObjectMacro(vtkPlaneWidget,PlaneProperty,vtkProperty); + +vtkPlaneWidget::vtkPlaneWidget() : vtkPolyDataSourceWidget() +{ + this->State = vtkPlaneWidget::Start; + this->EventCallbackCommand->SetCallback(vtkPlaneWidget::ProcessEvents); + + this->NormalToXAxis = 0; + this->NormalToYAxis = 0; + this->NormalToZAxis = 0; + this->Representation = VTK_PLANE_WIREFRAME; + + //Build the representation of the widget + int i; + // Represent the plane + this->PlaneSource = vtkPlaneSource::New(); + this->PlaneSource->SetXResolution(4); + this->PlaneSource->SetYResolution(4); + this->PlaneOutline = vtkPolyData::New(); + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(4); + vtkCellArray *outline = vtkCellArray::New(); + outline->InsertNextCell(4); + outline->InsertCellPoint(0); + outline->InsertCellPoint(1); + outline->InsertCellPoint(2); + outline->InsertCellPoint(3); + this->PlaneOutline->SetPoints(pts); + pts->Delete(); + this->PlaneOutline->SetPolys(outline); + outline->Delete(); + this->PlaneMapper = vtkPolyDataMapper::New(); + this->PlaneMapper->SetInput(this->PlaneSource->GetOutput()); + this->PlaneActor = vtkActor::New(); + this->PlaneActor->SetMapper(this->PlaneMapper); + + // Create the handles + this->Handle = new vtkActor* [4]; + this->HandleMapper = new vtkPolyDataMapper* [4]; + this->HandleGeometry = new vtkSphereSource* [4]; + for (i=0; i<4; i++) + { + this->HandleGeometry[i] = vtkSphereSource::New(); + this->HandleGeometry[i]->SetThetaResolution(16); + this->HandleGeometry[i]->SetPhiResolution(8); + this->HandleMapper[i] = vtkPolyDataMapper::New(); + this->HandleMapper[i]->SetInput(this->HandleGeometry[i]->GetOutput()); + this->Handle[i] = vtkActor::New(); + this->Handle[i]->SetMapper(this->HandleMapper[i]); + } + + // Create the + plane normal + this->LineSource = vtkLineSource::New(); + this->LineSource->SetResolution(1); + this->LineMapper = vtkPolyDataMapper::New(); + this->LineMapper->SetInput(this->LineSource->GetOutput()); + this->LineActor = vtkActor::New(); + this->LineActor->SetMapper(this->LineMapper); + + this->ConeSource = vtkConeSource::New(); + this->ConeSource->SetResolution(12); + this->ConeSource->SetAngle(25.0); + this->ConeMapper = vtkPolyDataMapper::New(); + this->ConeMapper->SetInput(this->ConeSource->GetOutput()); + this->ConeActor = vtkActor::New(); + this->ConeActor->SetMapper(this->ConeMapper); + + // Create the - plane normal + this->LineSource2 = vtkLineSource::New(); + this->LineSource2->SetResolution(1); + this->LineMapper2 = vtkPolyDataMapper::New(); + this->LineMapper2->SetInput(this->LineSource2->GetOutput()); + this->LineActor2 = vtkActor::New(); + this->LineActor2->SetMapper(this->LineMapper2); + + this->ConeSource2 = vtkConeSource::New(); + this->ConeSource2->SetResolution(12); + this->ConeSource2->SetAngle(25.0); + this->ConeMapper2 = vtkPolyDataMapper::New(); + this->ConeMapper2->SetInput(this->ConeSource2->GetOutput()); + this->ConeActor2 = vtkActor::New(); + this->ConeActor2->SetMapper(this->ConeMapper2); + + this->Transform = vtkTransform::New(); + + // Define the point coordinates + double bounds[6]; + bounds[0] = -0.5; + bounds[1] = 0.5; + bounds[2] = -0.5; + bounds[3] = 0.5; + bounds[4] = -0.5; + bounds[5] = 0.5; + + // Initial creation of the widget, serves to initialize it + this->PlaceWidget(bounds); + + //Manage the picking stuff + this->HandlePicker = vtkCellPicker::New(); + this->HandlePicker->SetTolerance(0.001); + for (i=0; i<4; i++) + { + this->HandlePicker->AddPickList(this->Handle[i]); + } + this->HandlePicker->PickFromListOn(); + + this->PlanePicker = vtkCellPicker::New(); + this->PlanePicker->SetTolerance(0.005); //need some fluff + this->PlanePicker->AddPickList(this->PlaneActor); + this->PlanePicker->AddPickList(this->ConeActor); + this->PlanePicker->AddPickList(this->LineActor); + this->PlanePicker->AddPickList(this->ConeActor2); + this->PlanePicker->AddPickList(this->LineActor2); + this->PlanePicker->PickFromListOn(); + + this->CurrentHandle = NULL; + + // Set up the initial properties + this->CreateDefaultProperties(); + + this->SelectRepresentation(); +} + +vtkPlaneWidget::~vtkPlaneWidget() +{ + this->PlaneActor->Delete(); + this->PlaneMapper->Delete(); + this->PlaneSource->Delete(); + this->PlaneOutline->Delete(); + + for (int i=0; i<4; i++) + { + this->HandleGeometry[i]->Delete(); + this->HandleMapper[i]->Delete(); + this->Handle[i]->Delete(); + } + delete [] this->Handle; + delete [] this->HandleMapper; + delete [] this->HandleGeometry; + + this->ConeActor->Delete(); + this->ConeMapper->Delete(); + this->ConeSource->Delete(); + + this->LineActor->Delete(); + this->LineMapper->Delete(); + this->LineSource->Delete(); + + this->ConeActor2->Delete(); + this->ConeMapper2->Delete(); + this->ConeSource2->Delete(); + + this->LineActor2->Delete(); + this->LineMapper2->Delete(); + this->LineSource2->Delete(); + + this->HandlePicker->Delete(); + this->PlanePicker->Delete(); + + this->HandleProperty->Delete(); + this->SelectedHandleProperty->Delete(); + this->PlaneProperty->Delete(); + this->SelectedPlaneProperty->Delete(); + + this->Transform->Delete(); +} + +void vtkPlaneWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //----------------------------------------------------------- + { + vtkDebugMacro(<<"Enabling plane widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // Add the plane + this->CurrentRenderer->AddActor(this->PlaneActor); + this->PlaneActor->SetProperty(this->PlaneProperty); + + // turn on the handles + for (int j=0; j<4; j++) + { + this->CurrentRenderer->AddActor(this->Handle[j]); + this->Handle[j]->SetProperty(this->HandleProperty); + } + + // add the normal vector + this->CurrentRenderer->AddActor(this->LineActor); + this->LineActor->SetProperty(this->HandleProperty); + this->CurrentRenderer->AddActor(this->ConeActor); + this->ConeActor->SetProperty(this->HandleProperty); + this->CurrentRenderer->AddActor(this->LineActor2); + this->LineActor2->SetProperty(this->HandleProperty); + this->CurrentRenderer->AddActor(this->ConeActor2); + this->ConeActor2->SetProperty(this->HandleProperty); + + this->SelectRepresentation(); + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling---------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling plane widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the plane + this->CurrentRenderer->RemoveActor(this->PlaneActor); + + // turn off the handles + for (int i=0; i<4; i++) + { + this->CurrentRenderer->RemoveActor(this->Handle[i]); + } + + // turn off the normal vector + this->CurrentRenderer->RemoveActor(this->LineActor); + this->CurrentRenderer->RemoveActor(this->ConeActor); + this->CurrentRenderer->RemoveActor(this->LineActor2); + this->CurrentRenderer->RemoveActor(this->ConeActor2); + + this->CurrentHandle = NULL; + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkPlaneWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkPlaneWidget* self = reinterpret_cast<vtkPlaneWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkPlaneWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->HandleProperty ) + { + os << indent << "Handle Property: " << this->HandleProperty << "\n"; + } + else + { + os << indent << "Handle Property: (none)\n"; + } + if ( this->SelectedHandleProperty ) + { + os << indent << "Selected Handle Property: " + << this->SelectedHandleProperty << "\n"; + } + else + { + os << indent << "SelectedHandle Property: (none)\n"; + } + + if ( this->PlaneProperty ) + { + os << indent << "Plane Property: " << this->PlaneProperty << "\n"; + } + else + { + os << indent << "Plane Property: (none)\n"; + } + if ( this->SelectedPlaneProperty ) + { + os << indent << "Selected Plane Property: " + << this->SelectedPlaneProperty << "\n"; + } + else + { + os << indent << "Selected Plane Property: (none)\n"; + } + + os << indent << "Plane Representation: "; + if ( this->Representation == VTK_PLANE_WIREFRAME ) + { + os << "Wireframe\n"; + } + else if ( this->Representation == VTK_PLANE_SURFACE ) + { + os << "Surface\n"; + } + else //( this->Representation == VTK_PLANE_OUTLINE ) + { + os << "Outline\n"; + } + + os << indent << "Normal To X Axis: " + << (this->NormalToXAxis ? "On" : "Off") << "\n"; + os << indent << "Normal To Y Axis: " + << (this->NormalToYAxis ? "On" : "Off") << "\n"; + os << indent << "Normal To Z Axis: " + << (this->NormalToZAxis ? "On" : "Off") << "\n"; + + int res = this->PlaneSource->GetXResolution(); + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + os << indent << "Resolution: " << res << "\n"; + os << indent << "Origin: (" << o[0] << ", " + << o[1] << ", " + << o[2] << ")\n"; + os << indent << "Point 1: (" << pt1[0] << ", " + << pt1[1] << ", " + << pt1[2] << ")\n"; + os << indent << "Point 2: (" << pt2[0] << ", " + << pt2[1] << ", " + << pt2[2] << ")\n"; +} + +void vtkPlaneWidget::PositionHandles() +{ + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + this->HandleGeometry[0]->SetCenter(o); + this->HandleGeometry[1]->SetCenter(pt1); + this->HandleGeometry[2]->SetCenter(pt2); + + double x[3]; + x[0] = pt1[0] + pt2[0] - o[0]; + x[1] = pt1[1] + pt2[1] - o[1]; + x[2] = pt1[2] + pt2[2] - o[2]; + this->HandleGeometry[3]->SetCenter(x); //far corner + + // set up the outline + if ( this->Representation == VTK_PLANE_OUTLINE ) + { + this->PlaneOutline->GetPoints()->SetPoint(0,o); + this->PlaneOutline->GetPoints()->SetPoint(1,pt1); + this->PlaneOutline->GetPoints()->SetPoint(2,x); + this->PlaneOutline->GetPoints()->SetPoint(3,pt2); + this->PlaneOutline->Modified(); + } + this->SelectRepresentation(); + + // Create the normal vector + double center[3]; + this->PlaneSource->GetCenter(center); + this->LineSource->SetPoint1(center); + this->LineSource2->SetPoint1(center); + double p2[3]; + this->PlaneSource->GetNormal(this->Normal); + vtkMath::Normalize(this->Normal); + double d = sqrt( + vtkMath::Distance2BetweenPoints( + this->PlaneSource->GetPoint1(),this->PlaneSource->GetPoint2()) ); + + p2[0] = center[0] + 0.35 * d * this->Normal[0]; + p2[1] = center[1] + 0.35 * d * this->Normal[1]; + p2[2] = center[2] + 0.35 * d * this->Normal[2]; + this->LineSource->SetPoint2(p2); + this->ConeSource->SetCenter(p2); + this->ConeSource->SetDirection(this->Normal); + + p2[0] = center[0] - 0.35 * d * this->Normal[0]; + p2[1] = center[1] - 0.35 * d * this->Normal[1]; + p2[2] = center[2] - 0.35 * d * this->Normal[2]; + this->LineSource2->SetPoint2(p2); + this->ConeSource2->SetCenter(p2); + this->ConeSource2->SetDirection(this->Normal); +} + +int vtkPlaneWidget::HighlightHandle(vtkProp *prop) +{ + // first unhighlight anything picked + if ( this->CurrentHandle ) + { + this->CurrentHandle->SetProperty(this->HandleProperty); + } + + this->CurrentHandle = (vtkActor *)prop; + + if ( this->CurrentHandle ) + { + this->ValidPick = 1; + this->HandlePicker->GetPickPosition(this->LastPickPosition); + this->CurrentHandle->SetProperty(this->SelectedHandleProperty); + for (int i=0; i<4; i++) //find handle + { + if ( this->CurrentHandle == this->Handle[i] ) + { + return i; + } + } + } + + return -1; +} + +void vtkPlaneWidget::HighlightNormal(int highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->PlanePicker->GetPickPosition(this->LastPickPosition); + this->LineActor->SetProperty(this->SelectedHandleProperty); + this->ConeActor->SetProperty(this->SelectedHandleProperty); + this->LineActor2->SetProperty(this->SelectedHandleProperty); + this->ConeActor2->SetProperty(this->SelectedHandleProperty); + } + else + { + this->LineActor->SetProperty(this->HandleProperty); + this->ConeActor->SetProperty(this->HandleProperty); + this->LineActor2->SetProperty(this->HandleProperty); + this->ConeActor2->SetProperty(this->HandleProperty); + } +} + +void vtkPlaneWidget::HighlightPlane(int highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->PlanePicker->GetPickPosition(this->LastPickPosition); + this->PlaneActor->SetProperty(this->SelectedPlaneProperty); + } + else + { + this->PlaneActor->SetProperty(this->PlaneProperty); + } +} + +void vtkPlaneWidget::OnLeftButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkPlaneWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then try to pick the plane. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkPlaneWidget::Moving; + this->HighlightHandle(path->GetFirstNode()->GetViewProp()); + } + else + { + this->PlanePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->PlanePicker->GetPath(); + if ( path != NULL ) + { + vtkProp *prop = path->GetFirstNode()->GetViewProp(); + if ( prop == this->ConeActor || prop == this->LineActor || + prop == this->ConeActor2 || prop == this->LineActor2 ) + { + this->State = vtkPlaneWidget::Rotating; + this->HighlightNormal(1); + } + else if (this->Interactor->GetControlKey()) + { + this->State = vtkPlaneWidget::Spinning; + this->HighlightNormal(1); + } + else + { + this->State = vtkPlaneWidget::Moving; + this->HighlightPlane(1); + } + } + else + { + this->State = vtkPlaneWidget::Outside; + this->HighlightHandle(NULL); + return; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPlaneWidget::OnLeftButtonUp() +{ + if ( this->State == vtkPlaneWidget::Outside || + this->State == vtkPlaneWidget::Start ) + { + return; + } + + this->State = vtkPlaneWidget::Start; + this->HighlightHandle(NULL); + this->HighlightPlane(0); + this->HighlightNormal(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPlaneWidget::OnMiddleButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkPlaneWidget::Outside; + return; + } + + // Okay, we can process this. If anything is picked, then we + // can start pushing the plane. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkPlaneWidget::Pushing; + this->HighlightPlane(1); + this->HighlightNormal(1); + this->HighlightHandle(path->GetFirstNode()->GetViewProp()); + } + else + { + this->PlanePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->PlanePicker->GetPath(); + if ( path == NULL ) //nothing picked + { + this->State = vtkPlaneWidget::Outside; + return; + } + else + { + this->State = vtkPlaneWidget::Pushing; + this->HighlightNormal(1); + this->HighlightPlane(1); + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPlaneWidget::OnMiddleButtonUp() +{ + if ( this->State == vtkPlaneWidget::Outside || + this->State == vtkPlaneWidget::Start ) + { + return; + } + + this->State = vtkPlaneWidget::Start; + this->HighlightPlane(0); + this->HighlightNormal(0); + this->HighlightHandle(NULL); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPlaneWidget::OnRightButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkPlaneWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkPlaneWidget::Scaling; + this->HighlightPlane(1); + this->HighlightHandle(path->GetFirstNode()->GetViewProp()); + } + else //see if we picked the plane or a normal + { + this->PlanePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->PlanePicker->GetPath(); + if ( path == NULL ) + { + this->State = vtkPlaneWidget::Outside; + return; + } + else + { + this->State = vtkPlaneWidget::Scaling; + this->HighlightPlane(1); + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPlaneWidget::OnRightButtonUp() +{ + if ( this->State == vtkPlaneWidget::Outside || + this->State == vtkPlaneWidget::Start ) + { + return; + } + + this->State = vtkPlaneWidget::Start; + this->HighlightPlane(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPlaneWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkPlaneWidget::Outside || + this->State == vtkPlaneWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z, vpn[3]; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( !camera ) + { + return; + } + + // Compute the two points defining the motion vector + this->ComputeWorldToDisplay(this->LastPickPosition[0], + this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld( + double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + // Process the motion + if ( this->State == vtkPlaneWidget::Moving ) + { + // Okay to process + if ( this->CurrentHandle ) + { + if ( this->CurrentHandle == this->Handle[0] ) + { + this->MoveOrigin(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[1] ) + { + this->MovePoint1(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[2] ) + { + this->MovePoint2(prevPickPoint, pickPoint); + } + else if ( this->CurrentHandle == this->Handle[3] ) + { + this->MovePoint3(prevPickPoint, pickPoint); + } + } + else //must be moving the plane + { + this->Translate(prevPickPoint, pickPoint); + } + } + else if ( this->State == vtkPlaneWidget::Scaling ) + { + this->Scale(prevPickPoint, pickPoint, X, Y); + } + else if ( this->State == vtkPlaneWidget::Pushing ) + { + this->Push(prevPickPoint, pickPoint); + } + else if ( this->State == vtkPlaneWidget::Rotating ) + { + camera->GetViewPlaneNormal(vpn); + this->Rotate(X, Y, prevPickPoint, pickPoint, vpn); + } + else if ( this->State == vtkPlaneWidget::Spinning ) + { + this->Spin(prevPickPoint, pickPoint); + } + + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + + this->Interactor->Render(); +} + +void vtkPlaneWidget::MoveOrigin(double *p1, double *p2) +{ + //Get the plane definition + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + //Get the vector of motion + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // The point opposite the origin (pt3) stays fixed + double pt3[3]; + pt3[0] = o[0] + (pt1[0] - o[0]) + (pt2[0] - o[0]); + pt3[1] = o[1] + (pt1[1] - o[1]) + (pt2[1] - o[1]); + pt3[2] = o[2] + (pt1[2] - o[2]) + (pt2[2] - o[2]); + + // Define vectors from point pt3 + double p13[3], p23[3]; + p13[0] = pt1[0] - pt3[0]; + p13[1] = pt1[1] - pt3[1]; + p13[2] = pt1[2] - pt3[2]; + p23[0] = pt2[0] - pt3[0]; + p23[1] = pt2[1] - pt3[1]; + p23[2] = pt2[2] - pt3[2]; + + double vN = vtkMath::Norm(v); + double n13 = vtkMath::Norm(p13); + double n23 = vtkMath::Norm(p23); + + // Project v onto these vector to determine the amount of motion + // Scale it by the relative size of the motion to the vector length + double d1 = (vN/n13) * vtkMath::Dot(v,p13) / (vN*n13); + double d2 = (vN/n23) * vtkMath::Dot(v,p23) / (vN*n23); + + double point1[3], point2[3], origin[3]; + for (int i=0; i<3; i++) + { + point1[i] = pt3[i] + (1.0+d1)*p13[i]; + point2[i] = pt3[i] + (1.0+d2)*p23[i]; + origin[i] = pt3[i] + (1.0+d1)*p13[i] + (1.0+d2)*p23[i]; + } + + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +void vtkPlaneWidget::MovePoint1(double *p1, double *p2) +{ + //Get the plane definition + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + //Get the vector of motion + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Need the point opposite the origin (pt3) + double pt3[3]; + pt3[0] = o[0] + (pt1[0] - o[0]) + (pt2[0] - o[0]); + pt3[1] = o[1] + (pt1[1] - o[1]) + (pt2[1] - o[1]); + pt3[2] = o[2] + (pt1[2] - o[2]) + (pt2[2] - o[2]); + + // Define vectors from point pt2 + double p32[3], p02[3]; + p02[0] = o[0] - pt2[0]; + p02[1] = o[1] - pt2[1]; + p02[2] = o[2] - pt2[2]; + p32[0] = pt3[0] - pt2[0]; + p32[1] = pt3[1] - pt2[1]; + p32[2] = pt3[2] - pt2[2]; + + double vN = vtkMath::Norm(v); + double n02 = vtkMath::Norm(p02); + double n32 = vtkMath::Norm(p32); + + // Project v onto these vector to determine the amount of motion + // Scale it by the relative size of the motion to the vector length + double d1 = (vN/n02) * vtkMath::Dot(v,p02) / (vN*n02); + double d2 = (vN/n32) * vtkMath::Dot(v,p32) / (vN*n32); + + double point1[3], origin[3]; + for (int i=0; i<3; i++) + { + origin[i] = pt2[i] + (1.0+d1)*p02[i]; + point1[i] = pt2[i] + (1.0+d1)*p02[i] + (1.0+d2)*p32[i]; + } + + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +void vtkPlaneWidget::MovePoint2(double *p1, double *p2) +{ + //Get the plane definition + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + //Get the vector of motion + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // The point opposite point2 (pt1) stays fixed + double pt3[3]; + pt3[0] = o[0] + (pt1[0] - o[0]) + (pt2[0] - o[0]); + pt3[1] = o[1] + (pt1[1] - o[1]) + (pt2[1] - o[1]); + pt3[2] = o[2] + (pt1[2] - o[2]) + (pt2[2] - o[2]); + + // Define vectors from point pt1 + double p01[3], p31[3]; + p31[0] = pt3[0] - pt1[0]; + p31[1] = pt3[1] - pt1[1]; + p31[2] = pt3[2] - pt1[2]; + p01[0] = o[0] - pt1[0]; + p01[1] = o[1] - pt1[1]; + p01[2] = o[2] - pt1[2]; + + double vN = vtkMath::Norm(v); + double n31 = vtkMath::Norm(p31); + double n01 = vtkMath::Norm(p01); + + // Project v onto these vector to determine the amount of motion + // Scale it by the relative size of the motion to the vector length + double d1 = (vN/n31) * vtkMath::Dot(v,p31) / (vN*n31); + double d2 = (vN/n01) * vtkMath::Dot(v,p01) / (vN*n01); + + double point2[3], origin[3]; + for (int i=0; i<3; i++) + { + point2[i] = pt1[i] + (1.0+d1)*p31[i] + (1.0+d2)*p01[i]; + origin[i] = pt1[i] + (1.0+d2)*p01[i]; + } + + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint2(point2); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +void vtkPlaneWidget::MovePoint3(double *p1, double *p2) +{ + //Get the plane definition + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + //Get the vector of motion + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Define vectors from point pt3 + double p10[3], p20[3]; + p10[0] = pt1[0] - o[0]; + p10[1] = pt1[1] - o[1]; + p10[2] = pt1[2] - o[2]; + p20[0] = pt2[0] - o[0]; + p20[1] = pt2[1] - o[1]; + p20[2] = pt2[2] - o[2]; + + double vN = vtkMath::Norm(v); + double n10 = vtkMath::Norm(p10); + double n20 = vtkMath::Norm(p20); + + // Project v onto these vector to determine the amount of motion + // Scale it by the relative size of the motion to the vector length + double d1 = (vN/n10) * vtkMath::Dot(v,p10) / (vN*n10); + double d2 = (vN/n20) * vtkMath::Dot(v,p20) / (vN*n20); + + double point1[3], point2[3]; + for (int i=0; i<3; i++) + { + point1[i] = o[i] + (1.0+d1)*p10[i]; + point2[i] = o[i] + (1.0+d2)*p20[i]; + } + + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +void vtkPlaneWidget::Rotate(int X, int Y, double *p1, double *p2, double *vpn) +{ + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + double *center = this->PlaneSource->GetCenter(); + + double v[3]; //vector of motion + double axis[3]; //axis of rotation + double theta; //rotation angle + + // mouse motion vector in world space + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Create axis of rotation and angle of rotation + vtkMath::Cross(vpn,v,axis); + if ( vtkMath::Normalize(axis) == 0.0 ) + { + return; + } + int *size = this->CurrentRenderer->GetSize(); + double l2 = + (X-this->Interactor->GetLastEventPosition()[0])* + (X-this->Interactor->GetLastEventPosition()[0]) + + (Y-this->Interactor->GetLastEventPosition()[1])* + (Y-this->Interactor->GetLastEventPosition()[1]); + theta = 360.0 * sqrt(l2/((double)size[0]*size[0]+size[1]*size[1])); + + //Manipulate the transform to reflect the rotation + this->Transform->Identity(); + this->Transform->Translate(center[0],center[1],center[2]); + this->Transform->RotateWXYZ(theta,axis); + this->Transform->Translate(-center[0],-center[1],-center[2]); + + //Set the corners + double oNew[3], pt1New[3], pt2New[3]; + this->Transform->TransformPoint(o,oNew); + this->Transform->TransformPoint(pt1,pt1New); + this->Transform->TransformPoint(pt2,pt2New); + + this->PlaneSource->SetOrigin(oNew); + this->PlaneSource->SetPoint1(pt1New); + this->PlaneSource->SetPoint2(pt2New); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +void vtkPlaneWidget::Spin(double *p1, double *p2) +{ + // Mouse motion vector in world space + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double* normal = this->PlaneSource->GetNormal(); + // Axis of rotation + double axis[3] = { normal[0], normal[1], normal[2] }; + vtkMath::Normalize(axis); + + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + double *center = this->PlaneSource->GetCenter(); + + // Radius vector (from center to cursor position) + double rv[3] = {p2[0] - center[0], + p2[1] - center[1], + p2[2] - center[2]}; + + // Distance between center and cursor location + double rs = vtkMath::Normalize(rv); + + // Spin direction + double ax_cross_rv[3]; + vtkMath::Cross(axis,rv,ax_cross_rv); + + // Spin angle + double theta = + vtkMath::RadiansToDegrees() * vtkMath::Dot(v,ax_cross_rv) / rs; + + // Manipulate the transform to reflect the rotation + this->Transform->Identity(); + this->Transform->Translate(center[0],center[1],center[2]); + this->Transform->RotateWXYZ(theta,axis); + this->Transform->Translate(-center[0],-center[1],-center[2]); + + //Set the corners + double oNew[3], pt1New[3], pt2New[3]; + this->Transform->TransformPoint(o,oNew); + this->Transform->TransformPoint(pt1,pt1New); + this->Transform->TransformPoint(pt2,pt2New); + + this->PlaneSource->SetOrigin(oNew); + this->PlaneSource->SetPoint1(pt1New); + this->PlaneSource->SetPoint2(pt2New); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +// Loop through all points and translate them +void vtkPlaneWidget::Translate(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //int res = this->PlaneSource->GetXResolution(); + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + double origin[3], point1[3], point2[3]; + for (int i=0; i<3; i++) + { + origin[i] = o[i] + v[i]; + point1[i] = pt1[i] + v[i]; + point2[i] = pt2[i] + v[i]; + } + + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +void vtkPlaneWidget::Scale(double *p1, double *p2, int vtkNotUsed(X), int Y) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //int res = this->PlaneSource->GetXResolution(); + double *o = this->PlaneSource->GetOrigin(); + double *pt1 = this->PlaneSource->GetPoint1(); + double *pt2 = this->PlaneSource->GetPoint2(); + + double center[3]; + center[0] = 0.5 * ( pt1[0] + pt2[0] ); + center[1] = 0.5 * ( pt1[1] + pt2[1] ); + center[2] = 0.5 * ( pt1[2] + pt2[2] ); + + // Compute the scale factor + double sf = + vtkMath::Norm(v) / sqrt(vtkMath::Distance2BetweenPoints(pt1,pt2)); + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.0 + sf; + } + else + { + sf = 1.0 - sf; + } + + // Move the corner points + double origin[3], point1[3], point2[3]; + for (int i=0; i<3; i++) + { + origin[i] = sf * (o[i] - center[i]) + center[i]; + point1[i] = sf * (pt1[i] - center[i]) + center[i]; + point2[i] = sf * (pt2[i] - center[i]) + center[i]; + } + + this->PlaneSource->SetOrigin(origin); + this->PlaneSource->SetPoint1(point1); + this->PlaneSource->SetPoint2(point2); + this->PlaneSource->Update(); + + this->PositionHandles(); +} + +void vtkPlaneWidget::Push(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + this->PlaneSource->Push( vtkMath::Dot(v,this->Normal) ); + this->PlaneSource->Update(); + this->PositionHandles(); +} + +void vtkPlaneWidget::CreateDefaultProperties() +{ + // Handle properties + this->HandleProperty = vtkProperty::New(); + this->HandleProperty->SetColor(1,1,1); + + this->SelectedHandleProperty = vtkProperty::New(); + this->SelectedHandleProperty->SetColor(1,0,0); + + // Plane properties + this->PlaneProperty = vtkProperty::New(); + this->PlaneProperty->SetAmbient(1.0); + this->PlaneProperty->SetAmbientColor(1.0,1.0,1.0); + + this->SelectedPlaneProperty = vtkProperty::New(); + this->SelectRepresentation(); + this->SelectedPlaneProperty->SetAmbient(1.0); + this->SelectedPlaneProperty->SetAmbientColor(0.0,1.0,0.0); +} + +void vtkPlaneWidget::PlaceWidget(double bds[6]) +{ + int i; + double bounds[6], center[3]; + + this->AdjustBounds(bds, bounds, center); + + if (this->Input || this->Prop3D) + { + if ( this->NormalToYAxis ) + { + this->PlaneSource->SetOrigin(bounds[0],center[1],bounds[4]); + this->PlaneSource->SetPoint1(bounds[1],center[1],bounds[4]); + this->PlaneSource->SetPoint2(bounds[0],center[1],bounds[5]); + } + else if ( this->NormalToZAxis ) + { + this->PlaneSource->SetOrigin(bounds[0],bounds[2],center[2]); + this->PlaneSource->SetPoint1(bounds[1],bounds[2],center[2]); + this->PlaneSource->SetPoint2(bounds[0],bounds[3],center[2]); + } + else //default or x-normal + { + this->PlaneSource->SetOrigin(center[0],bounds[2],bounds[4]); + this->PlaneSource->SetPoint1(center[0],bounds[3],bounds[4]); + this->PlaneSource->SetPoint2(center[0],bounds[2],bounds[5]); + } + } + + this->PlaneSource->Update(); + + // Position the handles at the end of the planes + this->PositionHandles(); + + for (i=0; i<6; i++) + { + this->InitialBounds[i] = bounds[i]; + } + + + if (this->Input || this->Prop3D) + { + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + } + else + { + // this means we have to make use of the PolyDataSource, so + // we just calculate the magnitude of the longest diagonal on + // the plane and use that as InitialLength + double origin[3], point1[3], point2[3]; + this->PlaneSource->GetOrigin(origin); + this->PlaneSource->GetPoint1(point1); + this->PlaneSource->GetPoint2(point2); + double sqr1 = 0, sqr2 = 0; + for (i = 0; i < 3; i++) + { + sqr1 += (point1[i] - origin[i]) * (point1[i] - origin[i]); + sqr2 += (point2[i] - origin[i]) * (point2[i] - origin[i]); + } + + this->InitialLength = sqrt(sqr1 + sqr2); + } + + // Set the radius on the sphere handles + this->SizeHandles(); +} + +void vtkPlaneWidget::SizeHandles() +{ + double radius = this->vtk3DWidget::SizeHandles(1.25); + + for(int i=0; i<4; i++) + { + this->HandleGeometry[i]->SetRadius(radius); + } + + // Set the height and radius of the cone + this->ConeSource->SetHeight(2.0*radius); + this->ConeSource->SetRadius(radius); + this->ConeSource2->SetHeight(2.0*radius); + this->ConeSource2->SetRadius(radius); +} + + +void vtkPlaneWidget::SelectRepresentation() +{ + if ( ! this->CurrentRenderer ) + { + return; + } + + if ( this->Representation == VTK_PLANE_OFF ) + { + this->CurrentRenderer->RemoveActor(this->PlaneActor); + } + else if ( this->Representation == VTK_PLANE_OUTLINE ) + { + this->CurrentRenderer->RemoveActor(this->PlaneActor); + this->CurrentRenderer->AddActor(this->PlaneActor); + this->PlaneMapper->SetInput( this->PlaneOutline ); + this->PlaneActor->GetProperty()->SetRepresentationToWireframe(); + } + else if ( this->Representation == VTK_PLANE_SURFACE ) + { + this->CurrentRenderer->RemoveActor(this->PlaneActor); + this->CurrentRenderer->AddActor(this->PlaneActor); + this->PlaneMapper->SetInput( this->PlaneSource->GetOutput() ); + this->PlaneActor->GetProperty()->SetRepresentationToSurface(); + } + else //( this->Representation == VTK_PLANE_WIREFRAME ) + { + this->CurrentRenderer->RemoveActor(this->PlaneActor); + this->CurrentRenderer->AddActor(this->PlaneActor); + this->PlaneMapper->SetInput( this->PlaneSource->GetOutput() ); + this->PlaneActor->GetProperty()->SetRepresentationToWireframe(); + } +} + +// Description: +// Set/Get the resolution (number of subdivisions) of the plane. +void vtkPlaneWidget::SetResolution(int r) +{ + this->PlaneSource->SetXResolution(r); + this->PlaneSource->SetYResolution(r); +} + +int vtkPlaneWidget::GetResolution() +{ + return this->PlaneSource->GetXResolution(); +} + +// Description: +// Set/Get the origin of the plane. +void vtkPlaneWidget::SetOrigin(double x, double y, double z) +{ + this->PlaneSource->SetOrigin(x,y,z); + this->PositionHandles(); +} + +void vtkPlaneWidget::SetOrigin(double x[3]) +{ + this->SetOrigin(x[0], x[1], x[2]); +} + +double* vtkPlaneWidget::GetOrigin() +{ + return this->PlaneSource->GetOrigin(); +} + +void vtkPlaneWidget::GetOrigin(double xyz[3]) +{ + this->PlaneSource->GetOrigin(xyz); +} + +// Description: +// Set/Get the position of the point defining the first axis of the plane. +void vtkPlaneWidget::SetPoint1(double x, double y, double z) +{ + this->PlaneSource->SetPoint1(x,y,z); + this->PositionHandles(); +} + +void vtkPlaneWidget::SetPoint1(double x[3]) +{ + this->SetPoint1(x[0], x[1], x[2]); +} + +double* vtkPlaneWidget::GetPoint1() +{ + return this->PlaneSource->GetPoint1(); +} + +void vtkPlaneWidget::GetPoint1(double xyz[3]) +{ + this->PlaneSource->GetPoint1(xyz); +} + +// Description: +// Set/Get the position of the point defining the second axis of the plane. +void vtkPlaneWidget::SetPoint2(double x, double y, double z) +{ + this->PlaneSource->SetPoint2(x,y,z); + this->PositionHandles(); +} + +void vtkPlaneWidget::SetPoint2(double x[3]) +{ + this->SetPoint2(x[0], x[1], x[2]); +} + +double* vtkPlaneWidget::GetPoint2() +{ + return this->PlaneSource->GetPoint2(); +} + +void vtkPlaneWidget::GetPoint2(double xyz[3]) +{ + this->PlaneSource->GetPoint2(xyz); +} + +// Description: +// Set the center of the plane. +void vtkPlaneWidget::SetCenter(double x, double y, double z) +{ + this->PlaneSource->SetCenter(x, y, z); + this->PositionHandles(); +} + +// Description: +// Set the center of the plane. +void vtkPlaneWidget::SetCenter(double c[3]) +{ + this->SetCenter(c[0], c[1], c[2]); +} + +// Description: +// Get the center of the plane. +double* vtkPlaneWidget::GetCenter() +{ + return this->PlaneSource->GetCenter(); +} + +void vtkPlaneWidget::GetCenter(double xyz[3]) +{ + this->PlaneSource->GetCenter(xyz); +} + +// Description: +// Set the normal to the plane. +void vtkPlaneWidget::SetNormal(double x, double y, double z) +{ + this->PlaneSource->SetNormal(x, y, z); + this->PositionHandles(); +} + +// Description: +// Set the normal to the plane. +void vtkPlaneWidget::SetNormal(double n[3]) +{ + this->SetNormal(n[0], n[1], n[2]); +} + +// Description: +// Get the normal to the plane. +double* vtkPlaneWidget::GetNormal() +{ + return this->PlaneSource->GetNormal(); +} + +void vtkPlaneWidget::GetNormal(double xyz[3]) +{ + this->PlaneSource->GetNormal(xyz); +} + +void vtkPlaneWidget::GetPolyData(vtkPolyData *pd) +{ + pd->ShallowCopy(this->PlaneSource->GetOutput()); +} + +vtkPolyDataAlgorithm *vtkPlaneWidget::GetPolyDataAlgorithm() +{ + return this->PlaneSource; +} + +void vtkPlaneWidget::GetPlane(vtkPlane *plane) +{ + if ( plane == NULL ) + { + return; + } + + plane->SetNormal(this->GetNormal()); + plane->SetOrigin(this->GetCenter()); +} + +void vtkPlaneWidget::UpdatePlacement(void) +{ + this->PlaneSource->Update(); + this->PositionHandles(); +} diff --git a/Widgets/vtkPlaneWidget.h b/Widgets/vtkPlaneWidget.h new file mode 100644 index 0000000..5204821 --- /dev/null +++ b/Widgets/vtkPlaneWidget.h @@ -0,0 +1,351 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPlaneWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPlaneWidget - 3D widget for manipulating a finite plane +// .SECTION Description +// This 3D widget defines a finite (bounded) plane that can be interactively +// placed in a scene. The plane has four handles (at its corner vertices), a +// normal vector, and the plane itself. The handles are used to resize the +// plane; the normal vector to rotate it, and the plane can be picked and +// translated. Selecting the plane while pressing CTRL makes it spin around +// the normal. A nice feature of the object is that the vtkPlaneWidget, like +// any 3D widget, will work with the current interactor style. That is, if +// vtkPlaneWidget does not handle an event, then all other registered +// observers (including the interactor style) have an opportunity to process +// the event. Otherwise, the vtkPlaneWidget will terminate the processing of +// the event that it handles. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. If the "i" key (for +// "interactor") is pressed, the vtkPlaneWidget will appear. (See superclass +// documentation for information about changing this behavior.) By grabbing +// the one of the four handles (use the left mouse button), the plane can be +// resized. By grabbing the plane itself, the entire plane can be +// arbitrarily translated. Pressing CTRL while grabbing the plane will spin +// the plane around the normal. If you select the normal vector, the plane can be +// arbitrarily rotated. Selecting any part of the widget with the middle +// mouse button enables translation of the plane along its normal. (Once +// selected using middle mouse, moving the mouse in the direction of the +// normal translates the plane in the direction of the normal; moving in the +// direction opposite the normal translates the plane in the direction +// opposite the normal.) Scaling (about the center of the plane) is achieved +// by using the right mouse button. By moving the mouse "up" the render +// window the plane will be made bigger; by moving "down" the render window +// the widget will be made smaller. Events that occur outside of the widget +// (i.e., no part of the widget is picked) are propagated to any other +// registered obsevers (such as the interaction style). Turn off the widget +// by pressing the "i" key again (or invoke the Off() method). +// +// The vtkPlaneWidget has several methods that can be used in conjunction +// with other VTK objects. The Set/GetResolution() methods control the number +// of subdivisions of the plane; the GetPolyData() method can be used to get +// the polygonal representation and can be used for things like seeding +// stream lines. GetPlane() can be used to update a vtkPlane implicit +// function. Typical usage of the widget is to make use of the +// StartInteractionEvent, InteractionEvent, and EndInteractionEvent +// events. The InteractionEvent is called on mouse motion; the other two +// events are called on button down and button up (either left or right +// button). +// +// Some additional features of this class include the ability to control the +// properties of the widget. You can set the properties of the selected and +// unselected representations of the plane. For example, you can set the +// property for the handles and plane. In addition there are methods to +// constrain the plane so that it is perpendicular to the x-y-z axes. + +// .SECTION Caveats +// Note that handles and plane can be picked even when they are "behind" other +// actors. This is an intended feature and not a bug. + +// .SECTION See Also +// vtk3DWidget vtkBoxWidget vtkLineWidget vtkSphereWidget +// vtkImplicitPlaneWidget + +#ifndef __vtkPlaneWidget_h +#define __vtkPlaneWidget_h + +#include "vtkPolyDataSourceWidget.h" + +class vtkActor; +class vtkCellPicker; +class vtkConeSource; +class vtkLineSource; +class vtkPlaneSource; +class vtkPoints; +class vtkPolyData; +class vtkPolyDataMapper; +class vtkProp; +class vtkProperty; +class vtkSphereSource; +class vtkTransform; +class vtkPlane; + +#define VTK_PLANE_OFF 0 +#define VTK_PLANE_OUTLINE 1 +#define VTK_PLANE_WIREFRAME 2 +#define VTK_PLANE_SURFACE 3 + +class VTK_WIDGETS_EXPORT vtkPlaneWidget : public vtkPolyDataSourceWidget +{ +public: + // Description: + // Instantiate the object. + static vtkPlaneWidget *New(); + + vtkTypeRevisionMacro(vtkPlaneWidget,vtkPolyDataSourceWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Set/Get the resolution (number of subdivisions) of the plane. + void SetResolution(int r); + int GetResolution(); + + // Description: + // Set/Get the origin of the plane. + void SetOrigin(double x, double y, double z); + void SetOrigin(double x[3]); + double* GetOrigin(); + void GetOrigin(double xyz[3]); + + // Description: + // Set/Get the position of the point defining the first axis of the plane. + void SetPoint1(double x, double y, double z); + void SetPoint1(double x[3]); + double* GetPoint1(); + void GetPoint1(double xyz[3]); + + // Description: + // Set/Get the position of the point defining the second axis of the plane. + void SetPoint2(double x, double y, double z); + void SetPoint2(double x[3]); + double* GetPoint2(); + void GetPoint2(double xyz[3]); + + // Description: + // Get the center of the plane. + void SetCenter(double x, double y, double z); + void SetCenter(double x[3]); + double* GetCenter(); + void GetCenter(double xyz[3]); + + // Description: + // Get the normal to the plane. + void SetNormal(double x, double y, double z); + void SetNormal(double x[3]); + double* GetNormal(); + void GetNormal(double xyz[3]); + + // Description: + // Control how the plane appears when GetPolyData() is invoked. + // If the mode is "outline", then just the outline of the plane + // is shown. If the mode is "wireframe" then the plane is drawn + // with the outline plus the interior mesh (corresponding to the + // resolution specified). If the mode is "surface" then the plane + // is drawn as a surface. + vtkSetClampMacro(Representation,int,VTK_PLANE_OFF,VTK_PLANE_SURFACE); + vtkGetMacro(Representation,int); + void SetRepresentationToOff() + {this->SetRepresentation(VTK_PLANE_OFF);} + void SetRepresentationToOutline() + {this->SetRepresentation(VTK_PLANE_OUTLINE);} + void SetRepresentationToWireframe() + {this->SetRepresentation(VTK_PLANE_WIREFRAME);} + void SetRepresentationToSurface() + {this->SetRepresentation(VTK_PLANE_SURFACE);} + + // Description: + // Force the plane widget to be aligned with one of the x-y-z axes. + // Remember that when the state changes, a ModifiedEvent is invoked. + // This can be used to snap the plane to the axes if it is orginally + // not aligned. + vtkSetMacro(NormalToXAxis,int); + vtkGetMacro(NormalToXAxis,int); + vtkBooleanMacro(NormalToXAxis,int); + vtkSetMacro(NormalToYAxis,int); + vtkGetMacro(NormalToYAxis,int); + vtkBooleanMacro(NormalToYAxis,int); + vtkSetMacro(NormalToZAxis,int); + vtkGetMacro(NormalToZAxis,int); + vtkBooleanMacro(NormalToZAxis,int); + + // Description: + // Grab the polydata (including points) that defines the plane. The + // polydata consists of (res+1)*(res+1) points, and res*res quadrilateral + // polygons, where res is the resolution of the plane. These point values + // are guaranteed to be up-to-date when either the InteractionEvent or + // EndInteraction events are invoked. The user provides the vtkPolyData and + // the points and polyplane are added to it. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Get the planes describing the implicit function defined by the plane + // widget. The user must provide the instance of the class vtkPlane. Note + // that vtkPlane is a subclass of vtkImplicitFunction, meaning that it can + // be used by a variety of filters to perform clipping, cutting, and + // selection of data. + void GetPlane(vtkPlane *plane); + + // Description: + // Satisfies superclass API. This returns a pointer to the underlying + // PolyData. Make changes to this before calling the initial PlaceWidget() + // to have the initial placement follow suit. Or, make changes after the + // widget has been initialised and call UpdatePlacement() to realise. + vtkPolyDataAlgorithm* GetPolyDataAlgorithm(); + + // Description: + // Satisfies superclass API. This will change the state of the widget to + // match changes that have been made to the underlying PolyDataSource + void UpdatePlacement(void); + + // Description: + // Get the handle properties (the little balls are the handles). The + // properties of the handles when selected and normal can be + // manipulated. + vtkGetObjectMacro(HandleProperty,vtkProperty); + vtkGetObjectMacro(SelectedHandleProperty,vtkProperty); + + // Description: + // Get the plane properties. The properties of the plane when selected + // and unselected can be manipulated. + virtual void SetPlaneProperty(vtkProperty*); + vtkGetObjectMacro(PlaneProperty,vtkProperty); + vtkGetObjectMacro(SelectedPlaneProperty,vtkProperty); + +protected: + vtkPlaneWidget(); + ~vtkPlaneWidget(); + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Start=0, + Moving, + Scaling, + Pushing, + Rotating, + Spinning, + Outside + }; +//ETX + + //handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnMiddleButtonDown(); + void OnMiddleButtonUp(); + void OnRightButtonDown(); + void OnRightButtonUp(); + void OnMouseMove(); + + // controlling ivars + int NormalToXAxis; + int NormalToYAxis; + int NormalToZAxis; + int Representation; + void SelectRepresentation(); + + // the plane + vtkActor *PlaneActor; + vtkPolyDataMapper *PlaneMapper; + vtkPlaneSource *PlaneSource; + vtkPolyData *PlaneOutline; + void HighlightPlane(int highlight); + + // glyphs representing hot spots (e.g., handles) + vtkActor **Handle; + vtkPolyDataMapper **HandleMapper; + vtkSphereSource **HandleGeometry; + void PositionHandles(); + void HandlesOn(double length); + void HandlesOff(); + int HighlightHandle(vtkProp *prop); //returns cell id + virtual void SizeHandles(); + + // the normal cone + vtkActor *ConeActor; + vtkPolyDataMapper *ConeMapper; + vtkConeSource *ConeSource; + void HighlightNormal(int highlight); + + // the normal line + vtkActor *LineActor; + vtkPolyDataMapper *LineMapper; + vtkLineSource *LineSource; + + // the normal cone + vtkActor *ConeActor2; + vtkPolyDataMapper *ConeMapper2; + vtkConeSource *ConeSource2; + + // the normal line + vtkActor *LineActor2; + vtkPolyDataMapper *LineMapper2; + vtkLineSource *LineSource2; + + // Do the picking + vtkCellPicker *HandlePicker; + vtkCellPicker *PlanePicker; + vtkActor *CurrentHandle; + + // Methods to manipulate the hexahedron. + void MoveOrigin(double *p1, double *p2); + void MovePoint1(double *p1, double *p2); + void MovePoint2(double *p1, double *p2); + void MovePoint3(double *p1, double *p2); + void Rotate(int X, int Y, double *p1, double *p2, double *vpn); + void Spin(double *p1, double *p2); + void Scale(double *p1, double *p2, int X, int Y); + void Translate(double *p1, double *p2); + void Push(double *p1, double *p2); + + // Plane normal, normalized + double Normal[3]; + + // Transform the hexahedral points (used for rotations) + vtkTransform *Transform; + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *HandleProperty; + vtkProperty *SelectedHandleProperty; + vtkProperty *PlaneProperty; + vtkProperty *SelectedPlaneProperty; + void CreateDefaultProperties(); + + void GeneratePlane(); + +private: + vtkPlaneWidget(const vtkPlaneWidget&); //Not implemented + void operator=(const vtkPlaneWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkPointWidget.cxx b/Widgets/vtkPointWidget.cxx new file mode 100644 index 0000000..0ce2561 --- /dev/null +++ b/Widgets/vtkPointWidget.cxx @@ -0,0 +1,668 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkPointWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellPicker.h" +#include "vtkMath.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderWindow.h" +#include "vtkObjectFactory.h" + +vtkCxxRevisionMacro(vtkPointWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkPointWidget); + +vtkPointWidget::vtkPointWidget() +{ + this->State = vtkPointWidget::Start; + this->EventCallbackCommand->SetCallback(vtkPointWidget::ProcessEvents); + + // Represent the line + this->Cursor3D = vtkCursor3D::New(); + this->Mapper = vtkPolyDataMapper::New(); + this->Mapper->SetInput(this->Cursor3D->GetOutput()); + this->Actor = vtkActor::New(); + this->Actor->SetMapper(this->Mapper); + + // Define the point coordinates + double bounds[6]; + bounds[0] = -0.5; + bounds[1] = 0.5; + bounds[2] = -0.5; + bounds[3] = 0.5; + bounds[4] = -0.5; + bounds[5] = 0.5; + + // Initial creation of the widget, serves to initialize it + this->PlaceWidget(bounds); + + //Manage the picking stuff + this->CursorPicker = vtkCellPicker::New(); + this->CursorPicker->PickFromListOn(); + this->CursorPicker->AddPickList(this->Actor); + this->CursorPicker->SetTolerance(0.005); //need some fluff + + // Set up the initial properties + this->CreateDefaultProperties(); + + // Constraints not set + this->ConstraintAxis = -1; + + // Override superclass' + this->PlaceFactor = 1.0; + + // The size of the hot spot + this->HotSpotSize = 0.05; + this->WaitingForMotion = 0; +} + +vtkPointWidget::~vtkPointWidget() +{ + this->Actor->Delete(); + this->Mapper->Delete(); + this->Cursor3D->Delete(); + + this->CursorPicker->Delete(); + + this->Property->Delete(); + this->SelectedProperty->Delete(); +} + +void vtkPointWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //----------------------------------------------------------- + { + vtkDebugMacro(<<"Enabling point widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // Add the line + this->CurrentRenderer->AddActor(this->Actor); + this->Actor->SetProperty(this->Property); + this->Cursor3D->Update(); + + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling---------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling point widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the line + this->CurrentRenderer->RemoveActor(this->Actor); + + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkPointWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkPointWidget* self = reinterpret_cast<vtkPointWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkPointWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->Property ) + { + os << indent << "Property: " << this->Property << "\n"; + } + else + { + os << indent << "Property: (none)\n"; + } + if ( this->SelectedProperty ) + { + os << indent << "Selected Property: " << this->SelectedProperty << "\n"; + } + else + { + os << indent << "Selected Property: (none)\n"; + } + + double *pos = this->Cursor3D->GetFocalPoint(); + os << indent << "Position: (" << pos[0] << ", " + << pos[1] << ", " << pos[2] << ")\n"; + + os << indent << "Outline: " << (this->GetOutline() ? "On\n" : "Off\n"); + os << indent << "XShadows: " << (this->GetXShadows() ? "On\n" : "Off\n"); + os << indent << "YShadows: " << (this->GetYShadows() ? "On\n" : "Off\n"); + os << indent << "ZShadows: " << (this->GetZShadows() ? "On\n" : "Off\n"); + + os << indent << "Translation Mode: " + << (this->Cursor3D->GetTranslationMode() ? "On\n" : "Off\n"); + + os << indent << "Hot Spot Size: " << this->HotSpotSize << "\n"; +} + +void vtkPointWidget::Highlight(int highlight) +{ + if ( highlight ) + { + this->Actor->SetProperty(this->SelectedProperty); + this->CursorPicker->GetPickPosition(this->LastPickPosition); + this->ValidPick = 1; + } + else + { + this->Actor->SetProperty(this->Property); + } +} + +int vtkPointWidget::DetermineConstraintAxis(int constraint, double *x) +{ + // Look for trivial cases + if ( ! this->Interactor->GetShiftKey() ) + { + return -1; + } + else if ( constraint >= 0 && constraint < 3 ) + { + return constraint; + } + + // Okay, figure out constraint. First see if the choice is + // outside the hot spot + if ( ! this->WaitingForMotion ) + { + double p[3], d2, tol; + this->CursorPicker->GetPickPosition(p); + d2 = vtkMath::Distance2BetweenPoints(p,this->LastPickPosition); + tol = this->HotSpotSize*this->InitialLength; + if ( d2 > (tol*tol) ) + { + this->WaitingForMotion = 0; + return this->CursorPicker->GetCellId(); + } + else + { + this->WaitingForMotion = 1; + this->WaitCount = 0; + return -1; + } + } + else if ( this->WaitingForMotion && x ) + { + double v[3]; + this->WaitingForMotion = 0; + v[0] = fabs(x[0] - this->LastPickPosition[0]); + v[1] = fabs(x[1] - this->LastPickPosition[1]); + v[2] = fabs(x[2] - this->LastPickPosition[2]); + return ( v[0]>v[1] ? (v[0]>v[2]?0:2) : (v[1]>v[2]?1:2)); + } + else + { + return -1; + } +} + +void vtkPointWidget::OnLeftButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkPointWidget::Outside; + return; + } + + vtkAssemblyPath *path; + this->CursorPicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->CursorPicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkPointWidget::Moving; + this->Highlight(1); + this->ConstraintAxis = this->DetermineConstraintAxis(-1,NULL); + } + else + { + this->State = vtkPointWidget::Outside; + this->Highlight(0); + this->ConstraintAxis = -1; + return; + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPointWidget::OnLeftButtonUp() +{ + if ( this->State == vtkPointWidget::Outside || + this->State == vtkPointWidget::Start ) + { + return; + } + + this->State = vtkPointWidget::Start; + this->Highlight(0); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPointWidget::OnMiddleButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkPointWidget::Outside; + return; + } + + // Okay, we can process this. + vtkAssemblyPath *path; + this->CursorPicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->CursorPicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkPointWidget::Translating; + this->Highlight(1); + this->ConstraintAxis = this->DetermineConstraintAxis(-1,NULL); + } + else + { + this->State = vtkPointWidget::Outside; + this->ConstraintAxis = -1; + return; + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPointWidget::OnMiddleButtonUp() +{ + if ( this->State == vtkPointWidget::Outside || + this->State == vtkPointWidget::Start ) + { + return; + } + + this->State = vtkPointWidget::Start; + this->Highlight(0); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPointWidget::OnRightButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkPointWidget::Outside; + return; + } + + // Okay, we can process this. Pick the cursor. + vtkAssemblyPath *path; + this->CursorPicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->CursorPicker->GetPath(); + if ( path != NULL ) + { + this->State = vtkPointWidget::Scaling; + int idx = this->CursorPicker->GetCellId(); + if ( idx >= 0 && idx < 3 ) + { + this->ConstraintAxis = idx; + } + this->Highlight(1); + } + else + { + this->State = vtkPointWidget::Outside; + this->ConstraintAxis = -1; + return; + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPointWidget::OnRightButtonUp() +{ + if ( this->State == vtkPointWidget::Outside || + this->State == vtkPointWidget::Start ) + { + return; + } + + this->State = vtkPointWidget::Start; + this->Highlight(0); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPointWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkPointWidget::Outside || + this->State == vtkPointWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( !camera ) + { + return; + } + + // Compute the two points defining the motion vector + this->ComputeWorldToDisplay(this->LastPickPosition[0], this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]),double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + // Process the motion + if ( this->State == vtkPointWidget::Moving ) + { + if ( !this->WaitingForMotion || this->WaitCount++ > 3 ) + { + this->ConstraintAxis = + this->DetermineConstraintAxis(this->ConstraintAxis,pickPoint); + this->MoveFocus(prevPickPoint, pickPoint); + } + else + { + return; //avoid the extra render + } + } + + else if ( this->State == vtkPointWidget::Scaling ) + { + this->Scale(prevPickPoint, pickPoint, X, Y); + } + + else if ( this->State == vtkPointWidget::Translating ) + { + if ( !this->WaitingForMotion || this->WaitCount++ > 3 ) + { + this->ConstraintAxis = + this->DetermineConstraintAxis(this->ConstraintAxis,pickPoint); + this->Translate(prevPickPoint, pickPoint); + } + else + { + return; //avoid the extra render + } + } + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkPointWidget::MoveFocus(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double focus[3]; + this->Cursor3D->GetFocalPoint(focus); + if ( this->ConstraintAxis >= 0 ) + { + focus[this->ConstraintAxis] += v[this->ConstraintAxis]; + } + else + { + focus[0] += v[0]; + focus[1] += v[1]; + focus[2] += v[2]; + } + + this->Cursor3D->SetFocalPoint(focus); +} + +// Translate everything +void vtkPointWidget::Translate(double *p1, double *p2) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double *bounds = this->Cursor3D->GetModelBounds(); + double *pos = this->Cursor3D->GetFocalPoint(); + double newBounds[6], newFocus[3]; + int i; + + if ( this->ConstraintAxis >= 0 ) + {//move along axis + for (i=0; i<3; i++) + { + if ( i != this->ConstraintAxis ) + { + v[i] = 0.0; + } + } + } + + for (i=0; i<3; i++) + { + newBounds[2*i] = bounds[2*i] + v[i]; + newBounds[2*i+1] = bounds[2*i+1] + v[i]; + newFocus[i] = pos[i] + v[i]; + } + + this->Cursor3D->SetModelBounds(newBounds); + this->Cursor3D->SetFocalPoint(newFocus); +} + +void vtkPointWidget::Scale(double *p1, double *p2, int vtkNotUsed(X), int Y) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //int res = this->Cursor3D->GetResolution(); + double *bounds = this->Cursor3D->GetModelBounds(); + double *focus = this->Cursor3D->GetFocalPoint(); + + // Compute the scale factor + double sf = vtkMath::Norm(v) / + sqrt( (bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.0 + sf; + } + else + { + sf = 1.0 - sf; + } + + // Move the end points + double newBounds[6]; + for (int i=0; i<3; i++) + { + newBounds[2*i] = sf * (bounds[2*i] - focus[i]) + focus[i]; + newBounds[2*i+1] = sf * (bounds[2*i+1] - focus[i]) + focus[i]; + } + + this->Cursor3D->SetModelBounds(newBounds); + this->Cursor3D->Update(); +} + +void vtkPointWidget::CreateDefaultProperties() +{ + this->Property = vtkProperty::New(); + this->Property->SetAmbient(1.0); + this->Property->SetAmbientColor(1.0,1.0,1.0); + this->Property->SetLineWidth(0.5); + + this->SelectedProperty = vtkProperty::New(); + this->SelectedProperty->SetAmbient(1.0); + this->SelectedProperty->SetAmbientColor(0.0,1.0,0.0); + this->SelectedProperty->SetLineWidth(2.0); +} + +void vtkPointWidget::PlaceWidget(double bds[6]) +{ + int i; + double bounds[6], center[3]; + + this->AdjustBounds(bds, bounds, center); + + this->Cursor3D->SetModelBounds(bounds); + this->Cursor3D->SetFocalPoint(center); + this->Cursor3D->Update(); + + for (i=0; i<6; i++) + { + this->InitialBounds[i] = bounds[i]; + } + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + +} + +void vtkPointWidget::GetPolyData(vtkPolyData *pd) +{ + this->Cursor3D->Update(); + pd->DeepCopy(this->Cursor3D->GetFocus()); +} diff --git a/Widgets/vtkPointWidget.h b/Widgets/vtkPointWidget.h new file mode 100644 index 0000000..7f99cd9 --- /dev/null +++ b/Widgets/vtkPointWidget.h @@ -0,0 +1,269 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPointWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPointWidget - position a point in 3D space +// .SECTION Description +// This 3D widget allows the user to position a point in 3D space using a 3D +// cursor. The cursor has an outline bounding box, axes-aligned cross-hairs, +// and axes shadows. (The outline and shadows can be turned off.) Any of +// these can be turned off. A nice feature of the object is that the +// vtkPointWidget, like any 3D widget, will work with the current interactor +// style. That is, if vtkPointWidget does not handle an event, then all other +// registered observers (including the interactor style) have an opportunity +// to process the event. Otherwise, the vtkPointWidget will terminate the +// processing of the event that it handles. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. The interactor will act +// normally until the "i" key (for "interactor") is pressed, at which point +// the vtkPointWidget will appear. (See superclass documentation for +// information about changing this behavior.) To move the point, the user can +// grab (left mouse) on any widget line and "slide" the point into +// position. Scaling is achieved by using the right mouse button "up" the +// render window (makes the widget bigger) or "down" the render window (makes +// the widget smaller). To translate the widget use the middle mouse button. +// (Note: all of the translation interactions can be constrained to one of +// the x-y-z axes by using the "shift" key.) The vtkPointWidget produces as +// output a polydata with a single point and a vertex cell. +// +// Some additional features of this class include the ability to control the +// rendered properties of the widget. You can set the properties of the +// selected and unselected representations of the parts of the widget. For +// example, you can set the property of the 3D cursor in its normal and +// selected states. + +// .SECTION Caveats +// Note that widget can be picked even when it is "behind" other actors. +// This is an intended feature and not a bug. +// +// The constrained translation/sliding action (i.e., when the "shift" key is +// depressed) along the axes is based on a combination of a "hot" spot around +// the cursor focus plus the initial mouse motion after selection. That is, +// if the user selects an axis outside of the hot spot, then the motion is +// constrained along that axis. If the user selects the point widget near the +// focus (within the hot spot), the initial motion defines a vector which is +// compared to the x-y-z axes. The motion is constrained to the axis that is +// most parallel to the initial motion vector. +// + +// .SECTION See Also +// vtk3DWidget vtkLineWidget vtkBoxWidget vtkPlaneWidget + +#ifndef __vtkPointWidget_h +#define __vtkPointWidget_h + +#include "vtk3DWidget.h" +#include "vtkCursor3D.h" // Needed for faster access to the Cursor3D + +class vtkActor; +class vtkPolyDataMapper; +class vtkCellPicker; +class vtkPolyData; +class vtkProperty; + +class VTK_WIDGETS_EXPORT vtkPointWidget : public vtk3DWidget +{ +public: + // Description: + // Instantiate this widget + static vtkPointWidget *New(); + + vtkTypeRevisionMacro(vtkPointWidget,vtk3DWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Grab the polydata (including points) that defines the point. A + // single point and a vertex compose the vtkPolyData. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Set/Get the position of the point. Note that if the position is set + // outside of the bounding box, it will be clamped to the boundary of + // the bounding box. + void SetPosition(double x, double y, double z) + {this->Cursor3D->SetFocalPoint(x,y,z);} + void SetPosition(double x[3]) + {this->SetPosition(x[0],x[1],x[2]);} + double* GetPosition() + {return this->Cursor3D->GetFocalPoint();} + void GetPosition(double xyz[3]) + {this->Cursor3D->GetFocalPoint(xyz);} + + // Description: + // Turn on/off the wireframe bounding box. + void SetOutline(int o) + {this->Cursor3D->SetOutline(o);} + int GetOutline() + {return this->Cursor3D->GetOutline();} + void OutlineOn() + {this->Cursor3D->OutlineOn();} + void OutlineOff() + {this->Cursor3D->OutlineOff();} + + // Description: + // Turn on/off the wireframe x-shadows. + void SetXShadows(int o) + {this->Cursor3D->SetXShadows(o);} + int GetXShadows() + {return this->Cursor3D->GetXShadows();} + void XShadowsOn() + {this->Cursor3D->XShadowsOn();} + void XShadowsOff() + {this->Cursor3D->XShadowsOff();} + + // Description: + // Turn on/off the wireframe y-shadows. + void SetYShadows(int o) + {this->Cursor3D->SetYShadows(o);} + int GetYShadows() + {return this->Cursor3D->GetYShadows();} + void YShadowsOn() + {this->Cursor3D->YShadowsOn();} + void YShadowsOff() + {this->Cursor3D->YShadowsOff();} + + // Description: + // Turn on/off the wireframe z-shadows. + void SetZShadows(int o) + {this->Cursor3D->SetZShadows(o);} + int GetZShadows() + {return this->Cursor3D->GetZShadows();} + void ZShadowsOn() + {this->Cursor3D->ZShadowsOn();} + void ZShadowsOff() + {this->Cursor3D->ZShadowsOff();} + + // Description: + // If translation mode is on, as the widget is moved the bounding box, + // shadows, and cursor are all translated simultaneously as the point + // moves. + void SetTranslationMode(int mode) + { this->Cursor3D->SetTranslationMode(mode); this->Cursor3D->Update(); } + int GetTranslationMode() + { return this->Cursor3D->GetTranslationMode(); } + void TranslationModeOn() + { this->SetTranslationMode(1); } + void TranslationModeOff() + { this->SetTranslationMode(0); } + + // Description: + // Convenience methods to turn outline and shadows on and off. + void AllOn() + { + this->OutlineOn(); + this->XShadowsOn(); + this->YShadowsOn(); + this->ZShadowsOn(); + } + void AllOff() + { + this->OutlineOff(); + this->XShadowsOff(); + this->YShadowsOff(); + this->ZShadowsOff(); + } + + // Description: + // Get the handle properties (the little balls are the handles). The + // properties of the handles when selected and normal can be + // set. + vtkGetObjectMacro(Property,vtkProperty); + vtkGetObjectMacro(SelectedProperty,vtkProperty); + + // Description: + // Set the "hot spot" size; i.e., the region around the focus, in which the + // motion vector is used to control the constrained sliding action. Note the + // size is specified as a fraction of the length of the diagonal of the + // point widget's bounding box. + vtkSetClampMacro(HotSpotSize,double,0.0,1.0); + vtkGetMacro(HotSpotSize,double); + +protected: + vtkPointWidget(); + ~vtkPointWidget(); + +//BTX - manage the state of the widget + friend class vtkLineWidget; + + int State; + enum WidgetState + { + Start=0, + Moving, + Scaling, + Translating, + Outside + }; +//ETX + + // Handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + + // the cursor3D + vtkActor *Actor; + vtkPolyDataMapper *Mapper; + vtkCursor3D *Cursor3D; + void Highlight(int highlight); + + // Do the picking + vtkCellPicker *CursorPicker; + + // Methods to manipulate the cursor + int ConstraintAxis; + void Translate(double *p1, double *p2); + void Scale(double *p1, double *p2, int X, int Y); + void MoveFocus(double *p1, double *p2); + int TranslationMode; + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *Property; + vtkProperty *SelectedProperty; + void CreateDefaultProperties(); + + // The size of the hot spot. + double HotSpotSize; + int DetermineConstraintAxis(int constraint, double *x); + int WaitingForMotion; + int WaitCount; + +private: + vtkPointWidget(const vtkPointWidget&); //Not implemented + void operator=(const vtkPointWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkPolyDataSourceWidget.cxx b/Widgets/vtkPolyDataSourceWidget.cxx new file mode 100644 index 0000000..dbdcbb5 --- /dev/null +++ b/Widgets/vtkPolyDataSourceWidget.cxx @@ -0,0 +1,69 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataSourceWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkPolyDataSourceWidget.h" + +#include "vtkDataSet.h" +#include "vtkProp3D.h" + + +vtkCxxRevisionMacro(vtkPolyDataSourceWidget, "$Revision: 1.1 $"); + +vtkPolyDataSourceWidget::vtkPolyDataSourceWidget() : vtk3DWidget() +{ + // child classes should call this constructor so that the vtk3DWidget() + // constructor can set up some pertinent variables (e.g. Input and Prop3D) +} + +void vtkPolyDataSourceWidget::PlaceWidget() +{ + double bounds[6]; + + if ( this->Prop3D ) + { + this->Prop3D->GetBounds(bounds); + } + else if ( this->Input ) + { + this->Input->Update(); + this->Input->GetBounds(bounds); + } + else + { + // if Prop3D and Input aren't set, we assume that we're going to + // look at what the user has already done with our polydata (and this + // should happen in the child PlaceWidget(bounds), but we have to setup + // some defaults for misbehaving child classes + bounds[0] = -1.0; + bounds[1] = 1.0; + bounds[2] = -1.0; + bounds[3] = 1.0; + bounds[4] = -1.0; + bounds[5] = 1.0; + } + + this->PlaceWidget(bounds); +} + +vtkPolyDataSource* vtkPolyDataSourceWidget::GetPolyDataSource() +{ + vtkErrorMacro("Use GetPolyDataAlgorithm instead."); + return NULL; +} + +void vtkPolyDataSourceWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); +} diff --git a/Widgets/vtkPolyDataSourceWidget.h b/Widgets/vtkPolyDataSourceWidget.h new file mode 100644 index 0000000..cd3c14e --- /dev/null +++ b/Widgets/vtkPolyDataSourceWidget.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPolyDataSourceWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkPolyDataSourceWidget - abstract PolyDataSource-based 3D widget +// .SECTION Description +// This abstract class serves as parent to 3D widgets that have simple +// vtkPolyDataSource instances defining their geometry. +// +// In addition to what is offered by the vtk3DWidget parent, this class +// makes it possible to manipulate the underlying polydatasource and to +// PlaceWidget() according to that, instead of having to make use of +// SetInput() or SetProp3D(). +// +// Implementors of child classes HAVE to implement their PlaceWidget(bounds) +// to check for the existence of Input and Prop3D FIRST. If these don't +// exist, place according to the underlying PolyDataSource. Child classes +// also have to imprement UpdatePlacement(), which updates the widget according +// to the geometry of the underlying PolyDataSource. + +// .SECTION See Also +// vtk3DWidget vtkLineWidget vtkPlaneWidget vtkSphereWidget + +#ifndef __vtkPolyDataSourceWidget_h +#define __vtkPolyDataSourceWidget_h + +#include "vtk3DWidget.h" + +class vtkPolyDataAlgorithm; +class vtkPolyDataSource; + +class VTK_WIDGETS_EXPORT vtkPolyDataSourceWidget : public vtk3DWidget +{ + public: + vtkTypeRevisionMacro(vtkPolyDataSourceWidget, vtk3DWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Overrides vtk3DWidget PlaceWidget() so that it doesn't complain if + // there's no Input and no Prop3D. + virtual void PlaceWidget(); + + // Description: + // We have to redeclare this abstract, PlaceWidget() requires it. You HAVE + // to override this in your concrete child classes. If there's no Prop3D + // and no Input, your PlaceWidget must make use of the underlying + // PolyDataSource to do its work. + virtual void PlaceWidget(double bounds[6]) = 0; + + // Description: + // Convenience method brought over from vtkPlaneWidget. + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Returns underlying vtkPolyDataSource that determines geometry. This + // can be modified after which PlaceWidget() or UpdatePlacement() can be + // called. UpdatePlacement() will always update the planewidget according + // to the geometry of the underlying PolyDataSource. PlaceWidget() will + // only make use of this geometry if there is no Input and no Prop3D set. + virtual vtkPolyDataSource* GetPolyDataSource(); + virtual vtkPolyDataAlgorithm* GetPolyDataAlgorithm() = 0; + + // Description: + // If you've made changes to the underlying vtkPolyDataSource AFTER your + // initial call to PlaceWidget(), use this method to realise the changes + // in the widget. + virtual void UpdatePlacement() = 0; + +protected: + // Description: + // Empty constructor that calls the parent constructor. Child classes + // should call this constructor as part of their initialisation. + vtkPolyDataSourceWidget(); + +private: + // this copy constructor and assignment operator are deliberately not + // implemented so that any "accidental" invocation of a copy (pass by value) + // or assignment will trigger linker errors; the class is not meant to + // be used in these ways. I couldn't resist adding this explanation. :) + vtkPolyDataSourceWidget(const vtkPolyDataSourceWidget&); // Not implemented. + void operator=(const vtkPolyDataSourceWidget&); // Not implemented. +}; + +#endif diff --git a/Widgets/vtkScalarBarWidget.cxx b/Widgets/vtkScalarBarWidget.cxx new file mode 100644 index 0000000..f0cf506 --- /dev/null +++ b/Widgets/vtkScalarBarWidget.cxx @@ -0,0 +1,488 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarBarWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkScalarBarWidget.h" +#include "vtkScalarBarActor.h" +#include "vtkCallbackCommand.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkCoordinate.h" + +vtkCxxRevisionMacro(vtkScalarBarWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkScalarBarWidget); +vtkCxxSetObjectMacro(vtkScalarBarWidget, ScalarBarActor, vtkScalarBarActor); + +vtkScalarBarWidget::vtkScalarBarWidget() +{ + this->ScalarBarActor = vtkScalarBarActor::New(); + this->EventCallbackCommand->SetCallback(vtkScalarBarWidget::ProcessEvents); + this->State = vtkScalarBarWidget::Outside; + this->LeftButtonDown = 0; + this->RightButtonDown = 0; + this->Priority = 0.55; +} + +vtkScalarBarWidget::~vtkScalarBarWidget() +{ + this->SetScalarBarActor(0); +} + +void vtkScalarBarWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) + { + vtkDebugMacro(<<"Enabling line widget"); + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // Add the scalar bar + this->CurrentRenderer->AddViewProp(this->ScalarBarActor); + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + else //disabling------------------------------------------ + { + vtkDebugMacro(<<"Disabling line widget"); + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the line + this->CurrentRenderer->RemoveActor(this->ScalarBarActor); + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkScalarBarWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkScalarBarWidget* self = reinterpret_cast<vtkScalarBarWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + + +int vtkScalarBarWidget::ComputeStateBasedOnPosition(int X, int Y, + int *pos1, int *pos2) +{ + int Result; + + // what are we modifying? The position, or size? + // if size what piece? + // if we are within 7 pixels of an edge... + int e1 = 0; + int e2 = 0; + int e3 = 0; + int e4 = 0; + if (X - pos1[0] < 7) + { + e1 = 1; + } + if (pos2[0] - X < 7) + { + e3 = 1; + } + if (Y - pos1[1] < 7) + { + e2 = 1; + } + if (pos2[1] - Y < 7) + { + e4 = 1; + } + + // assume we are moving + Result = vtkScalarBarWidget::Moving; + // unless we are on a corner or edges + if (e2) + { + Result = vtkScalarBarWidget::AdjustingE2; + } + if (e4) + { + Result = vtkScalarBarWidget::AdjustingE4; + } + if (e1) + { + Result = vtkScalarBarWidget::AdjustingE1; + if (e2) + { + Result = vtkScalarBarWidget::AdjustingP1; + } + if (e4) + { + Result = vtkScalarBarWidget::AdjustingP4; + } + } + if (e3) + { + Result = vtkScalarBarWidget::AdjustingE3; + if (e2) + { + Result = vtkScalarBarWidget::AdjustingP2; + } + if (e4) + { + Result = vtkScalarBarWidget::AdjustingP3; + } + } + + return Result; +} + +void vtkScalarBarWidget::SetCursor(int cState) +{ + switch (cState) + { + case vtkScalarBarWidget::AdjustingP1: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZESW); + break; + case vtkScalarBarWidget::AdjustingP3: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZENE); + break; + case vtkScalarBarWidget::AdjustingP2: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZESE); + break; + case vtkScalarBarWidget::AdjustingP4: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZENW); + break; + case vtkScalarBarWidget::AdjustingE1: + case vtkScalarBarWidget::AdjustingE3: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZEWE); + break; + case vtkScalarBarWidget::AdjustingE2: + case vtkScalarBarWidget::AdjustingE4: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZENS); + break; + case vtkScalarBarWidget::Moving: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZEALL); + break; + } +} + + +void vtkScalarBarWidget::OnLeftButtonDown() +{ + // We're only here is we are enabled + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // are we over the widget? + //this->Interactor->FindPokedRenderer(X,Y); + int *pos1 = this->ScalarBarActor->GetPositionCoordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + int *pos2 = this->ScalarBarActor->GetPosition2Coordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + + // are we not over the scalar bar, ignore + if (X < pos1[0] || X > pos2[0] || Y < pos1[1] || Y > pos2[1]) + { + return; + } + + // start a drag, store the normalized view coords + double X2 = X; + double Y2 = Y; + // convert to normalized viewport coordinates + this->CurrentRenderer->DisplayToNormalizedDisplay(X2,Y2); + this->CurrentRenderer->NormalizedDisplayToViewport(X2,Y2); + this->CurrentRenderer->ViewportToNormalizedViewport(X2,Y2); + this->StartPosition[0] = X2; + this->StartPosition[1] = Y2; + + this->State = this->ComputeStateBasedOnPosition(X, Y, pos1, pos2); + this->SetCursor(this->State); + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->LeftButtonDown = 1; +} + +void vtkScalarBarWidget::OnMouseMove() +{ + // compute some info we need for all cases + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + + // compute the display bounds of the scalar bar if we are inside or outside + int *pos1, *pos2; + if (this->State == vtkScalarBarWidget::Outside || + this->State == vtkScalarBarWidget::Inside) + { + pos1 = this->ScalarBarActor->GetPositionCoordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + pos2 = this->ScalarBarActor->GetPosition2Coordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + + if (this->State == vtkScalarBarWidget::Outside) + { + // if we are not over the scalar bar, ignore + if (X < pos1[0] || X > pos2[0] || + Y < pos1[1] || Y > pos2[1]) + { + return; + } + // otherwise change our state to inside + this->State = vtkScalarBarWidget::Inside; + } + + // if inside, set the cursor to the correct shape + if (this->State == vtkScalarBarWidget::Inside) + { + // if we have left then change cursor back to default + if (X < pos1[0] || X > pos2[0] || + Y < pos1[1] || Y > pos2[1]) + { + this->State = vtkScalarBarWidget::Outside; + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_DEFAULT); + return; + } + // adjust the cursor based on our position + this->SetCursor(this->ComputeStateBasedOnPosition(X,Y,pos1,pos2)); + return; + } + } + + double XF = X; + double YF = Y; + // convert to normalized viewport coordinates + this->CurrentRenderer->DisplayToNormalizedDisplay(XF,YF); + this->CurrentRenderer->NormalizedDisplayToViewport(XF,YF); + this->CurrentRenderer->ViewportToNormalizedViewport(XF,YF); + + // there are four parameters that can be adjusted + double *fpos1 = this->ScalarBarActor->GetPositionCoordinate()->GetValue(); + double *fpos2 = this->ScalarBarActor->GetPosition2Coordinate()->GetValue(); + double par1[2]; + double par2[2]; + par1[0] = fpos1[0]; + par1[1] = fpos1[1]; + par2[0] = fpos1[0] + fpos2[0]; + par2[1] = fpos1[1] + fpos2[1]; + + // based on the state, adjust the ScalarBar parameters + switch (this->State) + { + case vtkScalarBarWidget::AdjustingP1: + par1[0] = par1[0] + XF - this->StartPosition[0]; + par1[1] = par1[1] + YF - this->StartPosition[1]; + break; + case vtkScalarBarWidget::AdjustingP2: + par2[0] = par2[0] + XF - this->StartPosition[0]; + par1[1] = par1[1] + YF - this->StartPosition[1]; + break; + case vtkScalarBarWidget::AdjustingP3: + par2[0] = par2[0] + XF - this->StartPosition[0]; + par2[1] = par2[1] + YF - this->StartPosition[1]; + break; + case vtkScalarBarWidget::AdjustingP4: + par1[0] = par1[0] + XF - this->StartPosition[0]; + par2[1] = par2[1] + YF - this->StartPosition[1]; + break; + case vtkScalarBarWidget::AdjustingE1: + par1[0] = par1[0] + XF - this->StartPosition[0]; + break; + case vtkScalarBarWidget::AdjustingE2: + par1[1] = par1[1] + YF - this->StartPosition[1]; + break; + case vtkScalarBarWidget::AdjustingE3: + par2[0] = par2[0] + XF - this->StartPosition[0]; + break; + case vtkScalarBarWidget::AdjustingE4: + par2[1] = par2[1] + YF - this->StartPosition[1]; + break; + case vtkScalarBarWidget::Moving: + // first apply the move + par1[0] = par1[0] + XF - this->StartPosition[0]; + par1[1] = par1[1] + YF - this->StartPosition[1]; + par2[0] = par2[0] + XF - this->StartPosition[0]; + par2[1] = par2[1] + YF - this->StartPosition[1]; + // then check for an orientation change if the scalar bar moves so that + // its center is closer to a different edge that its current edge by + // 0.2 then swap orientation + double centerX = (par1[0] + par2[0])/2.0; + double centerY = (par1[1] + par2[1])/2.0; + // what edge is it closest to + if (fabs(centerX - 0.5) > fabs(centerY - 0.5)) + { + // is it far enough in to consider a change in orientation? + if (fabs(centerX - 0.5) > 0.2+fabs(centerY - 0.5)) + { + // do we need to change orientation + if (this->ScalarBarActor->GetOrientation() == VTK_ORIENT_HORIZONTAL) + { + this->ScalarBarActor->SetOrientation(VTK_ORIENT_VERTICAL); + // also change the corners + par2[0] = centerX + centerY - par1[1]; + par2[1] = centerY + centerX - par1[0]; + par1[0] = 2*centerX - par2[0]; + par1[1] = 2*centerY - par2[1]; + } + } + } + else + { + // is it far enough in to consider a change in orientation? + if (fabs(centerY - 0.5) > 0.2+fabs(centerX - 0.5)) + { + // do we need to change orientation + if (this->ScalarBarActor->GetOrientation() != VTK_ORIENT_HORIZONTAL) + { + this->ScalarBarActor->SetOrientation(VTK_ORIENT_HORIZONTAL); + // also change the corners + par2[0] = centerX + centerY - par1[1]; + par2[1] = centerY + centerX - par1[0]; + par1[0] = 2*centerX - par2[0]; + par1[1] = 2*centerY - par2[1]; + } + } + } + break; + } + + // push the change out to the scalar bar + // make sure the scalar bar doesn't shrink to nothing + if (par2[0] > par1[0] && par2[1] > par1[1]) + { + this->ScalarBarActor->GetPositionCoordinate()->SetValue(par1[0],par1[1]); + this->ScalarBarActor->GetPosition2Coordinate()-> + SetValue(par2[0] - par1[0], par2[1] - par1[1]); + this->StartPosition[0] = XF; + this->StartPosition[1] = YF; + } + + // start a drag + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkScalarBarWidget::OnLeftButtonUp() +{ + if (this->State == vtkScalarBarWidget::Outside || this->LeftButtonDown == 0) + { + return; + } + + // stop adjusting + this->State = vtkScalarBarWidget::Outside; + this->EventCallbackCommand->SetAbortFlag(1); + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_DEFAULT); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->LeftButtonDown = 0; +} + +void vtkScalarBarWidget::OnRightButtonDown() +{ + + // are we not over the scalar bar, ignore + if (this->State == vtkScalarBarWidget::Outside) + { + return; + } + + if (this->HasObserver(vtkCommand::RightButtonPressEvent) ) + { + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::RightButtonPressEvent,NULL); + } + RightButtonDown = 1; +} + +void vtkScalarBarWidget::OnRightButtonUp() +{ + if (RightButtonDown == 0) { + return; + } + + if (this->HasObserver(vtkCommand::RightButtonReleaseEvent)) + { + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::RightButtonReleaseEvent,NULL); + } + this->RightButtonDown = 0; +} + +void vtkScalarBarWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "ScalarBarActor: " << this->ScalarBarActor << "\n"; +} diff --git a/Widgets/vtkScalarBarWidget.h b/Widgets/vtkScalarBarWidget.h new file mode 100644 index 0000000..b280688 --- /dev/null +++ b/Widgets/vtkScalarBarWidget.h @@ -0,0 +1,112 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkScalarBarWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkScalarBarWidget - 2D widget for manipulating a scalar bar +// .SECTION Description +// This class provides support for interactively manipulating the position, +// size, and orientation of a scalar bar. It listens to Left mouse events and +// mouse movement. It also listens to Right mouse events and notifies any +// observers of Right mouse events on this object when they occur. +// It will change the cursor shape based on its location. If +// the cursor is over an edge of the scalar bar it will change the cursor +// shape to a resize edge shape. If the position of a scalar bar is moved to +// be close to the center of one of the four edges of the viewport, then the +// scalar bar will change its orientation to align with that edge. This +// orientation is sticky in that it will stay that orientation until the +// position is moved close to another edge. + +// .SECTION See Also +// vtkInteractorObserver + + +#ifndef __vtkScalarBarWidget_h +#define __vtkScalarBarWidget_h + +#include "vtkInteractorObserver.h" +class vtkScalarBarActor; + +class VTK_WIDGETS_EXPORT vtkScalarBarWidget : public vtkInteractorObserver +{ +public: + static vtkScalarBarWidget *New(); + vtkTypeRevisionMacro(vtkScalarBarWidget,vtkInteractorObserver); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the ScalarBar used by this Widget. One is created automatically. + void SetScalarBarActor(vtkScalarBarActor *scalarbar); + vtkGetObjectMacro(ScalarBarActor,vtkScalarBarActor); + + // Description: + // Methods for turning the interactor observer on and off. + virtual void SetEnabled(int); + +protected: + vtkScalarBarWidget(); + ~vtkScalarBarWidget(); + + // the actor that is used + vtkScalarBarActor *ScalarBarActor; + + //handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnRightButtonDown(); + void OnRightButtonUp(); + void OnMouseMove(); + + // used to compute relative movements + double StartPosition[2]; + +//BTX - manage the state of the widget + int State; + // use this to track whether left/right button was pressed to gate + // action on button up event. + int LeftButtonDown; + int RightButtonDown; + enum WidgetState + { + Moving=0, + AdjustingP1, + AdjustingP2, + AdjustingP3, + AdjustingP4, + AdjustingE1, + AdjustingE2, + AdjustingE3, + AdjustingE4, + Inside, + Outside + }; +//ETX + + // use to determine what state the mouse is over, edge1 p1, etc. + // returns a state from the WidgetState enum above + int ComputeStateBasedOnPosition(int X, int Y, int *pos1, int *pos2); + + // set the cursor to the correct shape based on State argument + void SetCursor(int State); + +private: + vtkScalarBarWidget(const vtkScalarBarWidget&); //Not implemented + void operator=(const vtkScalarBarWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkSphereWidget.cxx b/Widgets/vtkSphereWidget.cxx new file mode 100644 index 0000000..9ca0173 --- /dev/null +++ b/Widgets/vtkSphereWidget.cxx @@ -0,0 +1,734 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphereWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSphereWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellPicker.h" +#include "vtkDoubleArray.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphere.h" +#include "vtkSphereSource.h" + +vtkCxxRevisionMacro(vtkSphereWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkSphereWidget); + +vtkSphereWidget::vtkSphereWidget() +{ + this->State = vtkSphereWidget::Start; + this->EventCallbackCommand->SetCallback(vtkSphereWidget::ProcessEvents); + + this->Representation = VTK_SPHERE_WIREFRAME; + + //Build the representation of the widget + // Represent the sphere + this->SphereSource = vtkSphereSource::New(); + this->SphereSource->SetThetaResolution(16); + this->SphereSource->SetPhiResolution(8); + this->SphereSource->LatLongTessellationOn(); + this->SphereMapper = vtkPolyDataMapper::New(); + this->SphereMapper->SetInput(this->SphereSource->GetOutput()); + this->SphereActor = vtkActor::New(); + this->SphereActor->SetMapper(this->SphereMapper); + + // controls + this->Translation = 1; + this->Scale = 1; + + // handles + this->HandleVisibility = 0; + this->HandleDirection[0] = 1.0; + this->HandleDirection[1] = 0.0; + this->HandleDirection[2] = 0.0; + this->HandleSource = vtkSphereSource::New(); + this->HandleSource->SetThetaResolution(16); + this->HandleSource->SetPhiResolution(8); + this->HandleMapper = vtkPolyDataMapper::New(); + this->HandleMapper->SetInput(this->HandleSource->GetOutput()); + this->HandleActor = vtkActor::New(); + this->HandleActor->SetMapper(this->HandleMapper); + + // Define the point coordinates + double bounds[6]; + bounds[0] = -0.5; + bounds[1] = 0.5; + bounds[2] = -0.5; + bounds[3] = 0.5; + bounds[4] = -0.5; + bounds[5] = 0.5; + + // Initial creation of the widget, serves to initialize it + this->PlaceWidget(bounds); + + //Manage the picking stuff + this->Picker = vtkCellPicker::New(); + this->Picker->SetTolerance(0.005); //need some fluff + this->Picker->AddPickList(this->SphereActor); + this->Picker->AddPickList(this->HandleActor); + this->Picker->PickFromListOn(); + + // Set up the initial properties + this->SphereProperty = NULL; + this->SelectedSphereProperty = NULL; + this->HandleProperty = NULL; + this->SelectedHandleProperty = NULL; + this->CreateDefaultProperties(); +} + +vtkSphereWidget::~vtkSphereWidget() +{ + this->SphereActor->Delete(); + this->SphereMapper->Delete(); + this->SphereSource->Delete(); + + this->Picker->Delete(); + + this->HandleSource->Delete(); + this->HandleMapper->Delete(); + this->HandleActor->Delete(); + + if ( this->SphereProperty ) + { + this->SphereProperty->Delete(); + } + if ( this->SelectedSphereProperty ) + { + this->SelectedSphereProperty->Delete(); + } + if ( this->HandleProperty ) + { + this->HandleProperty->Delete(); + } + if ( this->SelectedHandleProperty ) + { + this->SelectedHandleProperty->Delete(); + } +} + +void vtkSphereWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //---------------------------------------------------------- + { + vtkDebugMacro(<<"Enabling sphere widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer( + this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // Add the sphere + this->CurrentRenderer->AddActor(this->SphereActor); + this->SphereActor->SetProperty(this->SphereProperty); + + this->CurrentRenderer->AddActor(this->HandleActor); + this->HandleActor->SetProperty(this->HandleProperty); + this->SelectRepresentation(); + this->SizeHandles(); + + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling---------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling sphere widget"); + + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the sphere + this->CurrentRenderer->RemoveActor(this->SphereActor); + this->CurrentRenderer->RemoveActor(this->HandleActor); + + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkSphereWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkSphereWidget* self = reinterpret_cast<vtkSphereWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkSphereWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "Sphere Representation: "; + if ( this->Representation == VTK_SPHERE_OFF ) + { + os << "Off\n"; + } + else if ( this->Representation == VTK_SPHERE_WIREFRAME ) + { + os << "Wireframe\n"; + } + else //if ( this->Representation == VTK_SPHERE_SURFACE ) + { + os << "Surface\n"; + } + + if ( this->SphereProperty ) + { + os << indent << "Sphere Property: " << this->SphereProperty << "\n"; + } + else + { + os << indent << "Sphere Property: (none)\n"; + } + if ( this->SelectedSphereProperty ) + { + os << indent << "Selected Sphere Property: " + << this->SelectedSphereProperty << "\n"; + } + else + { + os << indent << "Selected Sphere Property: (none)\n"; + } + + if ( this->HandleProperty ) + { + os << indent << "Handle Property: " << this->HandleProperty << "\n"; + } + else + { + os << indent << "Handle Property: (none)\n"; + } + if ( this->SelectedHandleProperty ) + { + os << indent << "Selected Handle Property: " + << this->SelectedHandleProperty << "\n"; + } + else + { + os << indent << "Selected Handle Property: (none)\n"; + } + + os << indent << "Translation: " << (this->Translation ? "On\n" : "Off\n"); + os << indent << "Scale: " << (this->Scale ? "On\n" : "Off\n"); + + os << indent << "Handle Visibility: " + << (this->HandleVisibility ? "On\n" : "Off\n"); + os << indent << "Handle Direction: (" << this->HandleDirection[0] << ", " + << this->HandleDirection[1] << ", " + << this->HandleDirection[2] << ")\n"; + os << indent << "Handle Position: (" << this->HandlePosition[0] << ", " + << this->HandlePosition[1] << ", " + << this->HandlePosition[2] << ")\n"; + + int thetaRes = this->SphereSource->GetThetaResolution(); + int phiRes = this->SphereSource->GetPhiResolution(); + double *center = this->SphereSource->GetCenter(); + double r = this->SphereSource->GetRadius(); + + os << indent << "Theta Resolution: " << thetaRes << "\n"; + os << indent << "Phi Resolution: " << phiRes << "\n"; + os << indent << "Center: (" << center[0] << ", " + << center[1] << ", " << center[2] << ")\n"; + os << indent << "Radius: " << r << "\n"; +} + +void vtkSphereWidget::SelectRepresentation() +{ + if ( ! this->HandleVisibility ) + { + this->CurrentRenderer->RemoveActor(this->HandleActor); + } + + if ( this->Representation == VTK_SPHERE_OFF ) + { + this->CurrentRenderer->RemoveActor(this->SphereActor); + } + else if ( this->Representation == VTK_SPHERE_WIREFRAME ) + { + this->CurrentRenderer->RemoveActor(this->SphereActor); + this->CurrentRenderer->AddActor(this->SphereActor); + this->SphereProperty->SetRepresentationToWireframe(); + this->SelectedSphereProperty->SetRepresentationToWireframe(); + } + else //if ( this->Representation == VTK_SPHERE_SURFACE ) + { + this->CurrentRenderer->RemoveActor(this->SphereActor); + this->CurrentRenderer->AddActor(this->SphereActor); + this->SphereProperty->SetRepresentationToSurface(); + this->SelectedSphereProperty->SetRepresentationToSurface(); + } +} + +void vtkSphereWidget::GetSphere(vtkSphere *sphere) +{ + sphere->SetRadius(this->SphereSource->GetRadius()); + sphere->SetCenter(this->SphereSource->GetCenter()); +} + +void vtkSphereWidget::HighlightSphere(int highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->Picker->GetPickPosition(this->LastPickPosition); + this->SphereActor->SetProperty(this->SelectedSphereProperty); + } + else + { + this->SphereActor->SetProperty(this->SphereProperty); + } +} + +void vtkSphereWidget::HighlightHandle(int highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->Picker->GetPickPosition(this->LastPickPosition); + this->HandleActor->SetProperty(this->SelectedHandleProperty); + } + else + { + this->HandleActor->SetProperty(this->HandleProperty); + } +} + +void vtkSphereWidget::OnLeftButtonDown() +{ + if (!this->Interactor) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkSphereWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then try to pick the sphere. + vtkAssemblyPath *path; + this->Picker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->Picker->GetPath(); + if ( path == NULL ) + { + this->State = vtkSphereWidget::Outside; + return; + } + else if (path->GetFirstNode()->GetViewProp() == this->SphereActor ) + { + this->State = vtkSphereWidget::Moving; + this->HighlightSphere(1); + } + else if (path->GetFirstNode()->GetViewProp() == this->HandleActor ) + { + this->State = vtkSphereWidget::Positioning; + this->HighlightHandle(1); + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSphereWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkSphereWidget::Outside || + this->State == vtkSphereWidget::Start ) + { + return; + } + + if (!this->Interactor) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( !camera ) + { + return; + } + + // Compute the two points defining the motion vector + camera->GetFocalPoint(focalPoint); + this->ComputeWorldToDisplay(focalPoint[0], focalPoint[1], + focalPoint[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, + prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + // Process the motion + if ( this->State == vtkSphereWidget::Moving ) + { + this->Translate(prevPickPoint, pickPoint); + } + else if ( this->State == vtkSphereWidget::Scaling ) + { + this->ScaleSphere(prevPickPoint, pickPoint, X, Y); + } + else if ( this->State == vtkSphereWidget::Positioning ) + { + this->MoveHandle(prevPickPoint, pickPoint, X, Y); + } + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSphereWidget::OnLeftButtonUp() +{ + if ( this->State == vtkSphereWidget::Outside ) + { + return; + } + + this->State = vtkSphereWidget::Start; + this->HighlightSphere(0); + this->HighlightHandle(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + if (this->Interactor) + { + this->Interactor->Render(); + } +} + +void vtkSphereWidget::OnRightButtonDown() +{ + if (!this->Interactor) + { + return; + } + + this->State = vtkSphereWidget::Scaling; + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if (!this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y)) + { + this->State = vtkSphereWidget::Outside; + return; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then pick the bounding box. + vtkAssemblyPath *path; + this->Picker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->Picker->GetPath(); + if ( path == NULL ) + { + this->State = vtkSphereWidget::Outside; + this->HighlightSphere(0); + return; + } + else + { + this->HighlightSphere(1); + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSphereWidget::OnRightButtonUp() +{ + if ( this->State == vtkSphereWidget::Outside ) + { + return; + } + + this->State = vtkSphereWidget::Start; + this->HighlightSphere(0); + this->HighlightHandle(0); + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + if (this->Interactor) + { + this->Interactor->Render(); + } +} + +// Loop through all points and translate them +void vtkSphereWidget::Translate(double *p1, double *p2) +{ + if ( !this->Translation ) + { + return; + } + + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + //int res = this->SphereSource->GetResolution(); + double *center = this->SphereSource->GetCenter(); + + double center1[3]; + for (int i=0; i<3; i++) + { + center1[i] = center[i] + v[i]; + this->HandlePosition[i] += v[i]; + } + + this->SphereSource->SetCenter(center1); + this->HandleSource->SetCenter(HandlePosition); + + this->SelectRepresentation(); +} + +void vtkSphereWidget::ScaleSphere(double *p1, double *p2, + int vtkNotUsed(X), int Y) +{ + if ( !this->Scale ) + { + return; + } + + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double radius = this->SphereSource->GetRadius(); + double *c = this->SphereSource->GetCenter(); + + // Compute the scale factor + double sf = vtkMath::Norm(v) / radius; + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.0 + sf; + } + else + { + sf = 1.0 - sf; + } + + this->SphereSource->SetRadius(sf*radius); + this->HandlePosition[0] = c[0]+sf*(this->HandlePosition[0]-c[0]); + this->HandlePosition[1] = c[1]+sf*(this->HandlePosition[1]-c[1]); + this->HandlePosition[2] = c[2]+sf*(this->HandlePosition[2]-c[2]); + this->HandleSource->SetCenter(this->HandlePosition); + + this->SelectRepresentation(); +} + +void vtkSphereWidget::MoveHandle(double *p1, double *p2, + int vtkNotUsed(X), int vtkNotUsed(Y)) +{ + //Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Compute the new location of the sphere + double *center = this->SphereSource->GetCenter(); + double radius = this->SphereSource->GetRadius(); + + // set the position of the sphere + double p[3]; + for (int i=0; i<3; i++) + { + p[i] = this->HandlePosition[i] + v[i]; + this->HandleDirection[i] = p[i] - center[i]; + } + + this->PlaceHandle(center,radius); + + this->SelectRepresentation(); +} + +void vtkSphereWidget::CreateDefaultProperties() +{ + if ( ! this->SphereProperty ) + { + this->SphereProperty = vtkProperty::New(); + } + if ( ! this->SelectedSphereProperty ) + { + this->SelectedSphereProperty = vtkProperty::New(); + } + + if ( ! this->HandleProperty ) + { + this->HandleProperty = vtkProperty::New(); + this->HandleProperty->SetColor(1,1,1); + } + if ( ! this->SelectedHandleProperty ) + { + this->SelectedHandleProperty = vtkProperty::New(); + this->SelectedHandleProperty->SetColor(1,0,0); + } +} + +void vtkSphereWidget::PlaceWidget(double bds[6]) +{ + double bounds[6], center[3], radius; + + this->AdjustBounds(bds, bounds, center); + + radius = (bounds[1]-bounds[0]) / 2.0; + if ( radius > ((bounds[3]-bounds[2])/2.0) ) + { + radius = (bounds[3]-bounds[2])/2.0; + } + radius = (bounds[1]-bounds[0]) / 2.0; + if ( radius > ((bounds[5]-bounds[4])/2.0) ) + { + radius = (bounds[5]-bounds[4])/2.0; + } + + this->SphereSource->SetCenter(center); + this->SphereSource->SetRadius(radius); + this->SphereSource->Update(); + + // place the handle + this->PlaceHandle(center,radius); + + for (int i=0; i<6; i++) + { + this->InitialBounds[i] = bounds[i]; + } + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + + this->SizeHandles(); +} + +void vtkSphereWidget::PlaceHandle(double *center, double radius) +{ + double sf = radius / vtkMath::Norm(this->HandleDirection); + + this->HandlePosition[0] = center[0] + sf*this->HandleDirection[0]; + this->HandlePosition[1] = center[1] + sf*this->HandleDirection[1]; + this->HandlePosition[2] = center[2] + sf*this->HandleDirection[2]; + this->HandleSource->SetCenter(this->HandlePosition); +} + +void vtkSphereWidget::SizeHandles() +{ + double radius = this->vtk3DWidget::SizeHandles(1.25); + this->HandleSource->SetRadius(radius); +} + + +void vtkSphereWidget::GetPolyData(vtkPolyData *pd) +{ + pd->ShallowCopy(this->SphereSource->GetOutput()); +} diff --git a/Widgets/vtkSphereWidget.h b/Widgets/vtkSphereWidget.h new file mode 100644 index 0000000..736a1db --- /dev/null +++ b/Widgets/vtkSphereWidget.h @@ -0,0 +1,278 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSphereWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSphereWidget - 3D widget for manipulating a sphere +// .SECTION Description +// This 3D widget defines a sphere that can be interactively placed in a +// scene. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. The interactor will act +// normally until the "i" key (for "interactor") is pressed, at which point the +// vtkSphereWidget will appear. (See superclass documentation for information +// about changing this behavior.) +// Events that occur outside of the widget (i.e., no part of +// the widget is picked) are propagated to any other registered obsevers +// (such as the interaction style). Turn off the widget by pressing the "i" +// key again (or invoke the Off() method). +// +// The vtkSphereWidget has several methods that can be used in conjunction +// with other VTK objects. The Set/GetThetaResolution() and +// Set/GetPhiResolution() methods control the number of subdivisions of the +// sphere in the theta and phi directions; the GetPolyData() method can be +// used to get the polygonal representation and can be used for things like +// seeding streamlines. The GetSphere() method returns a sphere implicit +// function that can be used for cutting and clipping. Typical usage of the +// widget is to make use of the StartInteractionEvent, InteractionEvent, and +// EndInteractionEvent events. The InteractionEvent is called on mouse +// motion; the other two events are called on button down and button up +// (any mouse button). +// +// Some additional features of this class include the ability to control the +// properties of the widget. You can set the properties of the selected and +// unselected representations of the sphere. + +// .SECTION Caveats +// Note that the sphere can be picked even when they are "behind" other +// actors. This is an intended feature and not a bug. + +// .SECTION See Also +// vtk3DWidget vtkLineWidget vtkBoxWidget vtkPlaneWidget + + +#ifndef __vtkSphereWidget_h +#define __vtkSphereWidget_h + +#include "vtk3DWidget.h" +#include "vtkSphereSource.h" // Needed for faster access to the sphere source + +class vtkActor; +class vtkPolyDataMapper; +class vtkPoints; +class vtkPolyData; +class vtkSphereSource; +class vtkSphere; +class vtkCellPicker; +class vtkProperty; + +#define VTK_SPHERE_OFF 0 +#define VTK_SPHERE_WIREFRAME 1 +#define VTK_SPHERE_SURFACE 2 + +class VTK_WIDGETS_EXPORT vtkSphereWidget : public vtk3DWidget +{ +public: + // Description: + // Instantiate the object. + static vtkSphereWidget *New(); + + vtkTypeRevisionMacro(vtkSphereWidget,vtk3DWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Set the representation of the sphere. Different representations are + // useful depending on the application. + vtkSetClampMacro(Representation,int,VTK_SPHERE_OFF,VTK_SPHERE_SURFACE); + vtkGetMacro(Representation,int); + void SetRepresentationToOff() + { this->SetRepresentation(VTK_SPHERE_OFF);} + void SetRepresentationToWireframe() + { this->SetRepresentation(VTK_SPHERE_WIREFRAME);} + void SetRepresentationToSurface() + { this->SetRepresentation(VTK_SPHERE_SURFACE);} + + // Description: + // Set/Get the resolution of the sphere in the Theta direction. + void SetThetaResolution(int r) + { this->SphereSource->SetThetaResolution(r); } + int GetThetaResolution() + { return this->SphereSource->GetThetaResolution(); } + + // Description: + // Set/Get the resolution of the sphere in the Phi direction. + void SetPhiResolution(int r) + { this->SphereSource->SetPhiResolution(r); } + int GetPhiResolution() + { return this->SphereSource->GetPhiResolution(); } + + // Description: + // Set/Get the radius of sphere. Default is .5. + void SetRadius(double r) + { + if ( r <= 0 ) + { + r = .00001; + } + this->SphereSource->SetRadius(r); + } + double GetRadius() + { return this->SphereSource->GetRadius(); } + + // Description: + // Set/Get the center of the sphere. + void SetCenter(double x, double y, double z) + { + this->SphereSource->SetCenter(x,y,z); + } + void SetCenter(double x[3]) + { + this->SetCenter(x[0], x[1], x[2]); + } + double* GetCenter() + {return this->SphereSource->GetCenter();} + void GetCenter(double xyz[3]) + {this->SphereSource->GetCenter(xyz);} + + // Description: + // Enable translation and scaling of the widget. By default, the widget + // can be translated and rotated. + vtkSetMacro(Translation,int); + vtkGetMacro(Translation,int); + vtkBooleanMacro(Translation,int); + vtkSetMacro(Scale,int); + vtkGetMacro(Scale,int); + vtkBooleanMacro(Scale,int); + + // Description: + // The handle sits on the surface of the sphere and may be moved around + // the surface by picking (left mouse) and then moving. The position + // of the handle can be retrieved, this is useful for positioning cameras + // and lights. By default, the handle is turned off. + vtkSetMacro(HandleVisibility,int); + vtkGetMacro(HandleVisibility,int); + vtkBooleanMacro(HandleVisibility,int); + + // Description: + // Set/Get the direction vector of the handle relative to the center of + // the sphere. + vtkSetVector3Macro(HandleDirection,double); + vtkGetVector3Macro(HandleDirection,double); + + // Description: + // Get the position of the handle. + vtkGetVector3Macro(HandlePosition,double); + + // Description: + // Grab the polydata (including points) that defines the sphere. The + // polydata consists of n+1 points, where n is the resolution of the + // sphere. These point values are guaranteed to be up-to-date when either the + // InteractionEvent or EndInteraction events are invoked. The user provides + // the vtkPolyData and the points and polysphere are added to it. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Get the spherical implicit function defined by this widget. Note that + // vtkPlanes is a subclass of vtkImplicitFunction, meaning that it can be + // used by a variety of filters to perform clipping, cutting, and selection + // of data. + void GetSphere(vtkSphere *sphere); + + // Description: + // Get the sphere properties. The properties of the sphere when selected + // and unselected can be manipulated. + vtkGetObjectMacro(SphereProperty,vtkProperty); + vtkGetObjectMacro(SelectedSphereProperty,vtkProperty); + + // Description: + // Get the handle properties (the little ball on the sphere is the + // handle). The properties of the handle when selected and unselected + // can be manipulated. + vtkGetObjectMacro(HandleProperty,vtkProperty); + vtkGetObjectMacro(SelectedHandleProperty,vtkProperty); + +protected: + vtkSphereWidget(); + ~vtkSphereWidget(); + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Start=0, + Moving, + Scaling, + Positioning, + Outside + }; +//ETX + + //handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnRightButtonDown(); + void OnRightButtonUp(); + void OnMouseMove(); + + // the sphere + vtkActor *SphereActor; + vtkPolyDataMapper *SphereMapper; + vtkSphereSource *SphereSource; + void HighlightSphere(int highlight); + void SelectRepresentation(); + + // The representation of the sphere + int Representation; + + // Do the picking + vtkCellPicker *Picker; + + // Methods to manipulate the sphere widget + int Translation; + int Scale; + void Translate(double *p1, double *p2); + void ScaleSphere(double *p1, double *p2, int X, int Y); + void MoveHandle(double *p1, double *p2, int X, int Y); + void PlaceHandle(double *center, double radius); + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *SphereProperty; + vtkProperty *SelectedSphereProperty; + vtkProperty *HandleProperty; + vtkProperty *SelectedHandleProperty; + void CreateDefaultProperties(); + + // Managing the handle + vtkActor *HandleActor; + vtkPolyDataMapper *HandleMapper; + vtkSphereSource *HandleSource; + void HighlightHandle(int); + int HandleVisibility; + double HandleDirection[3]; + double HandlePosition[3]; + virtual void SizeHandles(); + +private: + vtkSphereWidget(const vtkSphereWidget&); //Not implemented + void operator=(const vtkSphereWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkSplineWidget.cxx b/Widgets/vtkSplineWidget.cxx new file mode 100644 index 0000000..9b3720a --- /dev/null +++ b/Widgets/vtkSplineWidget.cxx @@ -0,0 +1,1464 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSplineWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkSplineWidget.h" + +#include "vtkActor.h" +#include "vtkAssemblyNode.h" +#include "vtkAssemblyPath.h" +#include "vtkCallbackCommand.h" +#include "vtkCamera.h" +#include "vtkCellArray.h" +#include "vtkCellPicker.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkParametricFunctionSource.h" +#include "vtkParametricSpline.h" +#include "vtkPlaneSource.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderer.h" +#include "vtkSphereSource.h" +#include "vtkTransform.h" + +vtkCxxRevisionMacro(vtkSplineWidget, "$Revision: 1.2 $"); +vtkStandardNewMacro(vtkSplineWidget); + +vtkCxxSetObjectMacro(vtkSplineWidget, HandleProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkSplineWidget, SelectedHandleProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkSplineWidget, LineProperty, vtkProperty); +vtkCxxSetObjectMacro(vtkSplineWidget, SelectedLineProperty, vtkProperty); + +vtkSplineWidget::vtkSplineWidget() +{ + this->State = vtkSplineWidget::Start; + this->EventCallbackCommand->SetCallback(vtkSplineWidget::ProcessEvents); + this->ProjectToPlane = 0; //default off + this->ProjectionNormal = 0; //default YZ not used + this->ProjectionPosition = 0.0; + this->PlaneSource = NULL; + this->Closed = 0; + + // Build the representation of the widget + + // Default bounds to get started + double bounds[6] = { -0.5, 0.5, -0.5, 0.5, -0.5, 0.5 }; + + // Create the handles along a straight line within the bounds of a unit cube + this->NumberOfHandles = 5; + this->Handle = new vtkActor* [this->NumberOfHandles]; + this->HandleGeometry = new vtkSphereSource* [this->NumberOfHandles]; + int i; + double u[3]; + double x0 = bounds[0]; + double x1 = bounds[1]; + double y0 = bounds[2]; + double y1 = bounds[3]; + double z0 = bounds[4]; + double z1 = bounds[5]; + double x; + double y; + double z; + vtkPoints* points = vtkPoints::New(VTK_DOUBLE); + points->SetNumberOfPoints(this->NumberOfHandles); + + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i] = vtkSphereSource::New(); + this->HandleGeometry[i]->SetThetaResolution(16); + this->HandleGeometry[i]->SetPhiResolution(8); + vtkPolyDataMapper* handleMapper = vtkPolyDataMapper::New(); + handleMapper->SetInput(this->HandleGeometry[i]->GetOutput()); + this->Handle[i] = vtkActor::New(); + this->Handle[i]->SetMapper(handleMapper); + handleMapper->Delete(); + u[0] = (double)i / (double)(this->NumberOfHandles - 1.0); + x = (1.0 - u[0])*x0 + u[0]*x1; + y = (1.0 - u[0])*y0 + u[0]*y1; + z = (1.0 - u[0])*z0 + u[0]*z1; + points->SetPoint(i, x, y, z); + this->HandleGeometry[i]->SetCenter(x,y,z); + } + + // vtkParametric spline acts as the interpolating engine + this->ParametricSpline = vtkParametricSpline::New(); + this->ParametricSpline->Register(this); + this->ParametricSpline->SetPoints(points); + this->ParametricSpline->ParameterizeByLengthOff(); + points->Delete(); + this->ParametricSpline->Delete(); + + // Define the points and line segments representing the spline + this->Resolution = 499; + + this->ParametricFunctionSource = vtkParametricFunctionSource::New(); + this->ParametricFunctionSource->SetParametricFunction(this->ParametricSpline); + this->ParametricFunctionSource->SetScalarModeToNone(); + this->ParametricFunctionSource->GenerateTextureCoordinatesOff(); + this->ParametricFunctionSource->SetUResolution( this->Resolution ); + this->ParametricFunctionSource->Update(); + + vtkPolyDataMapper* lineMapper = vtkPolyDataMapper::New(); + lineMapper->SetInput( this->ParametricFunctionSource->GetOutput() ) ; + lineMapper->ImmediateModeRenderingOn(); + lineMapper->SetResolveCoincidentTopologyToPolygonOffset(); + + this->LineActor = vtkActor::New(); + this->LineActor->SetMapper( lineMapper ); + lineMapper->Delete(); + + // Initial creation of the widget, serves to initialize it + this->PlaceFactor = 1.0; + this->PlaceWidget(bounds); + + // Manage the picking stuff + this->HandlePicker = vtkCellPicker::New(); + this->HandlePicker->SetTolerance(0.005); + + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandlePicker->AddPickList(this->Handle[i]); + } + this->HandlePicker->PickFromListOn(); + + this->LinePicker = vtkCellPicker::New(); + this->LinePicker->SetTolerance(0.01); + this->LinePicker->AddPickList(this->LineActor); + this->LinePicker->PickFromListOn(); + + this->CurrentHandle = NULL; + this->CurrentHandleIndex = -1; + + this->Transform = vtkTransform::New(); + + // Set up the initial properties + this->HandleProperty = NULL; + this->SelectedHandleProperty = NULL; + this->LineProperty = NULL; + this->SelectedLineProperty = NULL; + this->CreateDefaultProperties(); +} + +vtkSplineWidget::~vtkSplineWidget() +{ + if ( this->ParametricSpline ) + { + this->ParametricSpline->UnRegister(this); + } + + this->ParametricFunctionSource->Delete(); + + this->LineActor->Delete(); + + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->Delete(); + this->Handle[i]->Delete(); + } + delete [] this->Handle; + delete [] this->HandleGeometry; + + this->HandlePicker->Delete(); + this->LinePicker->Delete(); + + if ( this->HandleProperty ) + { + this->HandleProperty->Delete(); + } + if ( this->SelectedHandleProperty ) + { + this->SelectedHandleProperty->Delete(); + } + if ( this->LineProperty ) + { + this->LineProperty->Delete(); + } + if ( this->SelectedLineProperty ) + { + this->SelectedLineProperty->Delete(); + } + + this->Transform->Delete(); +} + +void vtkSplineWidget::SetClosed(int closed) +{ + if ( this->Closed == closed ) + { + return; + } + this->Closed = closed; + this->ParametricSpline->SetClosed(this->Closed); + + this->BuildRepresentation(); +} + +void vtkSplineWidget::SetParametricSpline(vtkParametricSpline* spline) +{ + if ( this->ParametricSpline != spline ) + { + // to avoid destructor recursion + vtkParametricSpline *temp = this->ParametricSpline; + this->ParametricSpline = spline; + if (temp != NULL) + { + temp->UnRegister(this); + } + if (this->ParametricSpline != NULL) + { + this->ParametricSpline->Register(this); + this->ParametricFunctionSource->SetParametricFunction(this->ParametricSpline); + } + } +} + +void vtkSplineWidget::SetHandlePosition(int handle, double x, + double y, double z) +{ + if ( handle < 0 || handle >= this->NumberOfHandles ) + { + vtkErrorMacro(<<"vtkSplineWidget: handle index out of range."); + return; + } + this->HandleGeometry[handle]->SetCenter(x,y,z); + this->HandleGeometry[handle]->Update(); + if ( this->ProjectToPlane ) + { + this->ProjectPointsToPlane(); + } + this->BuildRepresentation(); +} + +void vtkSplineWidget::SetHandlePosition(int handle, double xyz[3]) +{ + this->SetHandlePosition(handle,xyz[0],xyz[1],xyz[2]); +} + +void vtkSplineWidget::GetHandlePosition(int handle, double xyz[3]) +{ + if ( handle < 0 || handle >= this->NumberOfHandles ) + { + vtkErrorMacro(<<"vtkSplineWidget: handle index out of range."); + return; + } + + this->HandleGeometry[handle]->GetCenter(xyz); +} + +double* vtkSplineWidget::GetHandlePosition(int handle) +{ + if ( handle < 0 || handle >= this->NumberOfHandles ) + { + vtkErrorMacro(<<"vtkSplineWidget: handle index out of range."); + return NULL; + } + + return this->HandleGeometry[handle]->GetCenter(); +} + +void vtkSplineWidget::SetEnabled(int enabling) +{ + if ( !this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) //------------------------------------------------------------ + { + vtkDebugMacro(<<"Enabling line widget"); + + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( !this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if ( this->CurrentRenderer == NULL ) + { + return; + } + } + + this->Enabled = 1; + + // Listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::MiddleButtonPressEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::RightButtonPressEvent, this->EventCallbackCommand, + this->Priority); + i->AddObserver(vtkCommand::RightButtonReleaseEvent, this->EventCallbackCommand, + this->Priority); + + // Add the line + this->CurrentRenderer->AddActor(this->LineActor); + this->LineActor->SetProperty(this->LineProperty); + + // Turn on the handles + for ( int j = 0; j < this->NumberOfHandles; ++j ) + { + this->CurrentRenderer->AddActor(this->Handle[j]); + this->Handle[j]->SetProperty(this->HandleProperty); + } + this->BuildRepresentation(); + this->SizeHandles(); + + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + + else //disabling---------------------------------------------------------- + { + vtkDebugMacro(<<"Disabling line widget"); + + if ( !this->Enabled ) //already disabled, just return + { + return; + } + + this->Enabled = 0; + + // Don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // Turn off the line + this->CurrentRenderer->RemoveActor(this->LineActor); + + // Turn off the handles + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->CurrentRenderer->RemoveActor(this->Handle[i]); + } + + this->CurrentHandle = NULL; + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkSplineWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkSplineWidget* self = reinterpret_cast<vtkSplineWidget *>( clientdata ); + + // Okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MiddleButtonPressEvent: + self->OnMiddleButtonDown(); + break; + case vtkCommand::MiddleButtonReleaseEvent: + self->OnMiddleButtonUp(); + break; + case vtkCommand::RightButtonPressEvent: + self->OnRightButtonDown(); + break; + case vtkCommand::RightButtonReleaseEvent: + self->OnRightButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + +void vtkSplineWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + if ( this->HandleProperty ) + { + os << indent << "Handle Property: " << this->HandleProperty << "\n"; + } + else + { + os << indent << "Handle Property: (none)\n"; + } + if ( this->SelectedHandleProperty ) + { + os << indent << "Selected Handle Property: " + << this->SelectedHandleProperty << "\n"; + } + else + { + os << indent << "Selected Handle Property: (none)\n"; + } + if ( this->LineProperty ) + { + os << indent << "Line Property: " << this->LineProperty << "\n"; + } + else + { + os << indent << "Line Property: (none)\n"; + } + if ( this->SelectedLineProperty ) + { + os << indent << "Selected Line Property: " + << this->SelectedLineProperty << "\n"; + } + else + { + os << indent << "Selected Line Property: (none)\n"; + } + if ( this->ParametricSpline ) + { + os << indent << "ParametricSpline: " + << this->ParametricSpline << "\n"; + } + else + { + os << indent << "ParametricSpline: (none)\n"; + } + + os << indent << "Project To Plane: " + << (this->ProjectToPlane ? "On" : "Off") << "\n"; + os << indent << "Projection Normal: " << this->ProjectionNormal << "\n"; + os << indent << "Projection Position: " << this->ProjectionPosition << "\n"; + os << indent << "Resolution: " << this->Resolution << "\n"; + os << indent << "Number Of Handles: " << this->NumberOfHandles << "\n"; + os << indent << "Closed: " + << (this->Closed ? "On" : "Off") << "\n"; +} + +void vtkSplineWidget::ProjectPointsToPlane() +{ + if ( this->ProjectionNormal == VTK_PROJECTION_OBLIQUE ) + { + if ( this->PlaneSource != NULL ) + { + this->ProjectPointsToObliquePlane(); + } + else + { + vtkGenericWarningMacro(<<"Set the plane source for oblique projections..."); + } + } + else + { + this->ProjectPointsToOrthoPlane(); + } +} + +void vtkSplineWidget::ProjectPointsToObliquePlane() +{ + double o[3]; + double u[3]; + double v[3]; + + this->PlaneSource->GetPoint1(u); + this->PlaneSource->GetPoint2(v); + this->PlaneSource->GetOrigin(o); + + int i; + for ( i = 0; i < 3; ++i ) + { + u[i] = u[i] - o[i]; + v[i] = v[i] - o[i]; + } + vtkMath::Normalize(u); + vtkMath::Normalize(v); + + double o_dot_u = vtkMath::Dot(o,u); + double o_dot_v = vtkMath::Dot(o,v); + double fac1; + double fac2; + double ctr[3]; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->GetCenter(ctr); + fac1 = vtkMath::Dot(ctr,u) - o_dot_u; + fac2 = vtkMath::Dot(ctr,v) - o_dot_v; + ctr[0] = o[0] + fac1*u[0] + fac2*v[0]; + ctr[1] = o[1] + fac1*u[1] + fac2*v[1]; + ctr[2] = o[2] + fac1*u[2] + fac2*v[2]; + this->HandleGeometry[i]->SetCenter(ctr); + this->HandleGeometry[i]->Update(); + } +} + +void vtkSplineWidget::ProjectPointsToOrthoPlane() +{ + double ctr[3]; + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->GetCenter(ctr); + ctr[this->ProjectionNormal] = this->ProjectionPosition; + this->HandleGeometry[i]->SetCenter(ctr); + this->HandleGeometry[i]->Update(); + } +} + +void vtkSplineWidget::BuildRepresentation() +{ + // Handles have changed position, re-compute the spline coeffs + vtkPoints* points = this->ParametricSpline->GetPoints(); + if ( points->GetNumberOfPoints() != this->NumberOfHandles ) + { + points->SetNumberOfPoints( this->NumberOfHandles ); + } + + double pt[3]; + int i; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->GetCenter(pt); + points->SetPoint(i, pt); + } + this->ParametricSpline->Modified(); +} + +int vtkSplineWidget::HighlightHandle(vtkProp *prop) +{ + // First unhighlight anything picked + if ( this->CurrentHandle ) + { + this->CurrentHandle->SetProperty(this->HandleProperty); + } + + this->CurrentHandle = (vtkActor *)prop; + + if ( this->CurrentHandle ) + { + for ( int i = 0; i < this->NumberOfHandles; ++i ) // find handle + { + if ( this->CurrentHandle == this->Handle[i] ) + { + this->ValidPick = 1; + this->HandlePicker->GetPickPosition(this->LastPickPosition); + this->CurrentHandle->SetProperty(this->SelectedHandleProperty); + return i; + } + } + } + return -1; +} + +void vtkSplineWidget::HighlightLine(int highlight) +{ + if ( highlight ) + { + this->ValidPick = 1; + this->LinePicker->GetPickPosition(this->LastPickPosition); + this->LineActor->SetProperty(this->SelectedLineProperty); + } + else + { + this->LineActor->SetProperty(this->LineProperty); + } +} + +void vtkSplineWidget::OnLeftButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y) ) + { + this->State = vtkSplineWidget::Outside; + return; + } + + this->State = vtkSplineWidget::Moving; + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then try to pick the line. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path != NULL ) + { + this->CurrentHandleIndex = this->HighlightHandle(path->GetFirstNode()->GetViewProp()); + } + else + { + this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->LinePicker->GetPath(); + if ( path != NULL ) + { + this->HighlightLine(1); + } + else + { + this->CurrentHandleIndex = this->HighlightHandle(NULL); + this->State = vtkSplineWidget::Outside; + return; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSplineWidget::OnLeftButtonUp() +{ + if ( this->State == vtkSplineWidget::Outside || + this->State == vtkSplineWidget::Start ) + { + return; + } + + this->State = vtkSplineWidget::Start; + this->HighlightHandle(NULL); + this->HighlightLine(0); + + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSplineWidget::OnMiddleButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y) ) + { + this->State = vtkSplineWidget::Outside; + return; + } + + if ( this->Interactor->GetControlKey() ) + { + this->State = vtkSplineWidget::Spinning; + this->CalculateCentroid(); + } + else + { + this->State = vtkSplineWidget::Moving; + } + + // Okay, we can process this. Try to pick handles first; + // if no handles picked, then try to pick the line. + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + if ( path == NULL ) + { + this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->LinePicker->GetPath(); + if ( path == NULL ) + { + this->State = vtkSplineWidget::Outside; + this->HighlightLine(0); + return; + } + else + { + this->HighlightLine(1); + } + } + else //we picked a handle but lets make it look like the line is picked + { + this->HighlightLine(1); + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSplineWidget::OnMiddleButtonUp() +{ + if ( this->State == vtkSplineWidget::Outside || + this->State == vtkSplineWidget::Start ) + { + return; + } + + this->State = vtkSplineWidget::Start; + this->HighlightLine(0); + + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSplineWidget::OnRightButtonDown() +{ + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Okay, make sure that the pick is in the current renderer + if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X, Y) ) + { + this->State = vtkSplineWidget::Outside; + return; + } + + if ( this->Interactor->GetShiftKey() ) + { + this->State = vtkSplineWidget::Inserting; + } + else if ( this->Interactor->GetControlKey() ) + { + this->State = vtkSplineWidget::Erasing; + } + else + { + this->State = vtkSplineWidget::Scaling; + } + + vtkAssemblyPath *path; + this->HandlePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->HandlePicker->GetPath(); + + if ( path != NULL ) + { + switch ( this->State ) + { + // deny insertion over existing handles + case vtkSplineWidget::Inserting: + this->State = vtkSplineWidget::Outside; + return; + case vtkSplineWidget::Erasing: + this->CurrentHandleIndex = \ + this->HighlightHandle(path->GetFirstNode()->GetViewProp()); + break; + case vtkSplineWidget::Scaling: + this->HighlightLine(1); + break; + } + } + else + { + // trying to erase handle but nothing picked + if ( this->State == vtkSplineWidget::Erasing ) + { + this->State = vtkSplineWidget::Outside; + return; + } + // try to insert or scale so pick the line + this->LinePicker->Pick(X,Y,0.0,this->CurrentRenderer); + path = this->LinePicker->GetPath(); + if ( path != NULL ) + { + this->HighlightLine(1); + } + else + { + this->State = vtkSplineWidget::Outside; + return; + } + } + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSplineWidget::OnRightButtonUp() +{ + if ( this->State == vtkSplineWidget::Outside || + this->State == vtkSplineWidget::Start ) + { + return; + } + + if ( this->State == vtkSplineWidget::Inserting ) + { + this->InsertHandleOnLine(this->LastPickPosition); + } + else if ( this->State == vtkSplineWidget::Erasing ) + { + int index = this->CurrentHandleIndex; + this->CurrentHandleIndex = this->HighlightHandle(NULL); + this->EraseHandle(index); + } + + this->State = vtkSplineWidget::Start; + this->HighlightLine(0); + + this->SizeHandles(); + + this->EventCallbackCommand->SetAbortFlag(1); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSplineWidget::OnMouseMove() +{ + // See whether we're active + if ( this->State == vtkSplineWidget::Outside || + this->State == vtkSplineWidget::Start ) + { + return; + } + + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // Do different things depending on state + // Calculations everybody does + double focalPoint[4], pickPoint[4], prevPickPoint[4]; + double z, vpn[3]; + + vtkCamera *camera = this->CurrentRenderer->GetActiveCamera(); + if ( !camera ) + { + return; + } + + // Compute the two points defining the motion vector + this->ComputeWorldToDisplay(this->LastPickPosition[0], this->LastPickPosition[1], + this->LastPickPosition[2], focalPoint); + z = focalPoint[2]; + this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]), + double(this->Interactor->GetLastEventPosition()[1]), + z, prevPickPoint); + this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint); + + // Process the motion + if ( this->State == vtkSplineWidget::Moving ) + { + // Okay to process + if ( this->CurrentHandle ) + { + this->MovePoint(prevPickPoint, pickPoint); + } + else // Must be moving the spline + { + this->Translate(prevPickPoint, pickPoint); + } + } + else if ( this->State == vtkSplineWidget::Scaling ) + { + this->Scale(prevPickPoint, pickPoint, X, Y); + } + else if ( this->State == vtkSplineWidget::Spinning ) + { + camera->GetViewPlaneNormal(vpn); + this->Spin(prevPickPoint, pickPoint, vpn); + } + + if ( this->ProjectToPlane ) + { + this->ProjectPointsToPlane(); + } + + this->BuildRepresentation(); + + // Interact, if desired + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent,NULL); + this->Interactor->Render(); +} + +void vtkSplineWidget::MovePoint(double *p1, double *p2) +{ + if ( this->CurrentHandleIndex < 0 || this->CurrentHandleIndex >= this->NumberOfHandles ) + { + vtkGenericWarningMacro(<<"Spline handle index out of range."); + return; + } + // Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double *ctr = this->HandleGeometry[this->CurrentHandleIndex]->GetCenter(); + + double newCtr[3]; + newCtr[0] = ctr[0] + v[0]; + newCtr[1] = ctr[1] + v[1]; + newCtr[2] = ctr[2] + v[2]; + + this->HandleGeometry[this->CurrentHandleIndex]->SetCenter(newCtr); + this->HandleGeometry[this->CurrentHandleIndex]->Update(); +} + +void vtkSplineWidget::Translate(double *p1, double *p2) +{ + // Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double newCtr[3]; + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + double* ctr = this->HandleGeometry[i]->GetCenter(); + for ( int j = 0; j < 3; ++j ) + { + newCtr[j] = ctr[j] + v[j]; + } + this->HandleGeometry[i]->SetCenter(newCtr); + this->HandleGeometry[i]->Update(); + } +} + +void vtkSplineWidget::Scale(double *p1, double *p2, int vtkNotUsed(X), int Y) +{ + // Get the motion vector + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + double center[3] = {0.0,0.0,0.0}; + double avgdist = 0.0; + double *prevctr = this->HandleGeometry[0]->GetCenter(); + double *ctr; + + center[0] += prevctr[0]; + center[1] += prevctr[1]; + center[2] += prevctr[2]; + + int i; + for ( i = 1; i < this->NumberOfHandles; ++i ) + { + ctr = this->HandleGeometry[i]->GetCenter(); + center[0] += ctr[0]; + center[1] += ctr[1]; + center[2] += ctr[2]; + avgdist += sqrt(vtkMath::Distance2BetweenPoints(ctr,prevctr)); + prevctr = ctr; + } + + avgdist /= this->NumberOfHandles; + + center[0] /= this->NumberOfHandles; + center[1] /= this->NumberOfHandles; + center[2] /= this->NumberOfHandles; + + // Compute the scale factor + double sf = vtkMath::Norm(v) / avgdist; + if ( Y > this->Interactor->GetLastEventPosition()[1] ) + { + sf = 1.0 + sf; + } + else + { + sf = 1.0 - sf; + } + + // Move the handle points + double newCtr[3]; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + ctr = this->HandleGeometry[i]->GetCenter(); + for ( int j = 0; j < 3; ++j ) + { + newCtr[j] = sf * (ctr[j] - center[j]) + center[j]; + } + this->HandleGeometry[i]->SetCenter(newCtr); + this->HandleGeometry[i]->Update(); + } +} + +void vtkSplineWidget::Spin(double *p1, double *p2, double *vpn) +{ + // Mouse motion vector in world space + double v[3]; + v[0] = p2[0] - p1[0]; + v[1] = p2[1] - p1[1]; + v[2] = p2[2] - p1[2]; + + // Axis of rotation + double axis[3] = {0.0,0.0,0.0}; + + if ( this->ProjectToPlane ) + { + if ( this->ProjectionNormal == VTK_PROJECTION_OBLIQUE && \ + this->PlaneSource != NULL ) + { + double* normal = this->PlaneSource->GetNormal(); + axis[0] = normal[0]; + axis[1] = normal[1]; + axis[2] = normal[2]; + vtkMath::Normalize(axis); + } + else + { + axis[ this->ProjectionNormal ] = 1.0; + } + } + else + { + // Create axis of rotation and angle of rotation + vtkMath::Cross(vpn,v,axis); + if ( vtkMath::Normalize(axis) == 0.0 ) + { + return; + } + } + + // Radius vector (from mean center to cursor position) + double rv[3] = {p2[0] - this->Centroid[0], + p2[1] - this->Centroid[1], + p2[2] - this->Centroid[2]}; + + // Distance between center and cursor location + double rs = vtkMath::Normalize(rv); + + // Spin direction + double ax_cross_rv[3]; + vtkMath::Cross(axis,rv,ax_cross_rv); + + // Spin angle + double theta = 360.0 * vtkMath::Dot(v,ax_cross_rv) / rs; + + // Manipulate the transform to reflect the rotation + this->Transform->Identity(); + this->Transform->Translate(this->Centroid[0],this->Centroid[1],this->Centroid[2]); + this->Transform->RotateWXYZ(theta,axis); + this->Transform->Translate(-this->Centroid[0],-this->Centroid[1],-this->Centroid[2]); + + // Set the handle points + double newCtr[3]; + double ctr[3]; + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->GetCenter(ctr); + this->Transform->TransformPoint(ctr,newCtr); + this->HandleGeometry[i]->SetCenter(newCtr); + this->HandleGeometry[i]->Update(); + } +} + +void vtkSplineWidget::CreateDefaultProperties() +{ + if ( !this->HandleProperty ) + { + this->HandleProperty = vtkProperty::New(); + this->HandleProperty->SetColor(1,1,1); + } + if ( !this->SelectedHandleProperty ) + { + this->SelectedHandleProperty = vtkProperty::New(); + this->SelectedHandleProperty->SetColor(1,0,0); + } + + if ( !this->LineProperty ) + { + this->LineProperty = vtkProperty::New(); + this->LineProperty->SetRepresentationToWireframe(); + this->LineProperty->SetAmbient(1.0); + this->LineProperty->SetColor(1.0,1.0,0.0); + this->LineProperty->SetLineWidth(2.0); + } + if ( !this->SelectedLineProperty ) + { + this->SelectedLineProperty = vtkProperty::New(); + this->SelectedLineProperty->SetRepresentationToWireframe(); + this->SelectedLineProperty->SetAmbient(1.0); + this->SelectedLineProperty->SetAmbientColor(0.0,1.0,0.0); + this->SelectedLineProperty->SetLineWidth(2.0); + } +} + +void vtkSplineWidget::PlaceWidget(double bds[6]) +{ + int i; + double bounds[6], center[3]; + this->AdjustBounds(bds, bounds, center); + + if ( this->ProjectToPlane ) + { + this->ProjectPointsToPlane(); + } + else //place the center + { + // Create a default straight line within the data bounds + double x0 = bounds[0]; + double x1 = bounds[1]; + double y0 = bounds[2]; + double y1 = bounds[3]; + double z0 = bounds[4]; + double z1 = bounds[5]; + double x; + double y; + double z; + double u; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + u = (double)i / (double)(this->NumberOfHandles - 1.0); + x = (1.0 - u)*x0 + u*x1; + y = (1.0 - u)*y0 + u*y1; + z = (1.0 - u)*z0 + u*z1; + this->HandleGeometry[i]->SetCenter(x,y,z); + } + } + + for ( i = 0; i < 6; ++i ) + { + this->InitialBounds[i] = bounds[i]; + } + this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) + + (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) + + (bounds[5]-bounds[4])*(bounds[5]-bounds[4])); + + // Re-compute the spline coeffs + this->BuildRepresentation(); + this->SizeHandles(); +} + +void vtkSplineWidget::SetProjectionPosition(double position) +{ + this->ProjectionPosition = position; + if ( this->ProjectToPlane ) + { + this->ProjectPointsToPlane(); + } + this->BuildRepresentation(); +} + +void vtkSplineWidget::SetPlaneSource(vtkPlaneSource* plane) +{ + if (this->PlaneSource == plane) + { + return; + } + this->PlaneSource = plane; +} + +void vtkSplineWidget::SetNumberOfHandles(int npts) +{ + if ( this->NumberOfHandles == npts ) + { + return; + } + if (npts < 2) + { + vtkGenericWarningMacro(<<"vtkSplineWidget: minimum of 2 points required."); + return; + } + + double radius = this->HandleGeometry[0]->GetRadius(); + this->Initialize(); + + this->NumberOfHandles = npts; + + // Create the handles + this->Handle = new vtkActor* [this->NumberOfHandles]; + this->HandleGeometry = new vtkSphereSource* [this->NumberOfHandles]; + + int i; + double pt[3]; + double u[3]; + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i] = vtkSphereSource::New(); + this->HandleGeometry[i]->SetThetaResolution(16); + this->HandleGeometry[i]->SetPhiResolution(8); + vtkPolyDataMapper* handleMapper = vtkPolyDataMapper::New(); + handleMapper->SetInput(this->HandleGeometry[i]->GetOutput()); + this->Handle[i] = vtkActor::New(); + this->Handle[i]->SetMapper(handleMapper); + handleMapper->Delete(); + this->Handle[i]->SetProperty(this->HandleProperty); + u[0] = (double)i / (double)(this->NumberOfHandles - 1.0); + this->ParametricSpline->Evaluate(u, pt, NULL); + this->HandleGeometry[i]->SetCenter(pt); + this->HandleGeometry[i]->SetRadius(radius); + this->HandlePicker->AddPickList(this->Handle[i]); + } + + this->BuildRepresentation(); + + if ( this->Interactor ) + { + if ( !this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + } + if ( this->CurrentRenderer != NULL ) + { + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->CurrentRenderer->AddViewProp(this->Handle[i]); + } + this->SizeHandles(); + } + this->Interactor->Render(); + } +} + +void vtkSplineWidget::Initialize(void) +{ + int i; + if ( this->Interactor ) + { + if ( !this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + } + if ( this->CurrentRenderer != NULL) + { + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->CurrentRenderer->RemoveViewProp(this->Handle[i]); + } + } + } + + for ( i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandlePicker->DeletePickList(this->Handle[i]); + this->HandleGeometry[i]->Delete(); + this->Handle[i]->Delete(); + } + + this->NumberOfHandles = 0; + + delete [] this->Handle; + delete [] this->HandleGeometry; +} + +void vtkSplineWidget::SetResolution(int resolution) +{ + if ( this->Resolution == resolution || resolution < (this->NumberOfHandles-1) ) + { + return; + } + + this->Resolution = resolution; + this->ParametricFunctionSource->SetUResolution( this->Resolution ); + this->ParametricFunctionSource->Modified(); +} + +void vtkSplineWidget::GetPolyData(vtkPolyData *pd) +{ + pd->ShallowCopy( this->ParametricFunctionSource->GetOutput() ); +} + +void vtkSplineWidget::SizeHandles() +{ + double radius = this->vtk3DWidget::SizeHandles(1.0); + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->SetRadius(radius); + } +} + +double vtkSplineWidget::GetSummedLength() +{ + vtkPoints* points = this->ParametricFunctionSource->GetOutput()->GetPoints(); + int npts = points->GetNumberOfPoints(); + + if ( npts < 2 ) { return 0.0; } + + double a[3]; + double b[3]; + double sum = 0.0; + int i = 0; + points->GetPoint(i, a); + int imax = (npts%2 == 0) ? npts-2 : npts-1; + + while ( i < imax ) + { + points->GetPoint(i+1, b); + sum += sqrt(vtkMath::Distance2BetweenPoints(a, b)); + i = i + 2; + points->GetPoint(i, a); + sum = sum + sqrt(vtkMath::Distance2BetweenPoints(a, b)); + } + + if ( npts%2 == 0 ) + { + points->GetPoint(i+1, b); + sum += sqrt(vtkMath::Distance2BetweenPoints(a, b)); + } + + return sum; +} + +void vtkSplineWidget::CalculateCentroid() +{ + this->Centroid[0] = 0.0; + this->Centroid[1] = 0.0; + this->Centroid[2] = 0.0; + + double ctr[3]; + for ( int i = 0; i < this->NumberOfHandles; ++i ) + { + this->HandleGeometry[i]->GetCenter(ctr); + this->Centroid[0] += ctr[0]; + this->Centroid[1] += ctr[1]; + this->Centroid[2] += ctr[2]; + } + + this->Centroid[0] /= this->NumberOfHandles; + this->Centroid[1] /= this->NumberOfHandles; + this->Centroid[2] /= this->NumberOfHandles; +} + +void vtkSplineWidget::InsertHandleOnLine(double* pos) +{ + if (this->NumberOfHandles < 2) { return; } + + vtkIdType id = this->LinePicker->GetCellId(); + if (id == -1){ return; } + + vtkIdType subid = this->LinePicker->GetSubId(); + + vtkPoints* newpoints = vtkPoints::New(VTK_DOUBLE); + newpoints->SetNumberOfPoints(this->NumberOfHandles+1); + + int istart = vtkMath::Floor(subid*(this->NumberOfHandles + this->Closed - 1.0)/((double)this->Resolution)); + int istop = istart + 1; + int count = 0; + int i; + for ( i = 0; i <= istart; ++i ) + { + newpoints->SetPoint(count++,this->HandleGeometry[i]->GetCenter()); + } + + newpoints->SetPoint(count++,pos); + + for ( i = istop; i < this->NumberOfHandles; ++i ) + { + newpoints->SetPoint(count++,this->HandleGeometry[i]->GetCenter()); + } + + this->InitializeHandles(newpoints); + newpoints->Delete(); +} + +void vtkSplineWidget::EraseHandle(const int& index) +{ + if ( this->NumberOfHandles < 3 || index < 0 || index >= this->NumberOfHandles ) + { + return; + } + + vtkPoints* newpoints = vtkPoints::New(VTK_DOUBLE); + newpoints->SetNumberOfPoints(this->NumberOfHandles-1); + int count = 0; + for (int i = 0; i < this->NumberOfHandles; ++i ) + { + if ( i != index ) + { + newpoints->SetPoint(count++,this->HandleGeometry[i]->GetCenter()); + } + } + + this->InitializeHandles(newpoints); + newpoints->Delete(); +} + +void vtkSplineWidget::InitializeHandles(vtkPoints* points) +{ + if ( !points ){ return; } + + int npts = points->GetNumberOfPoints(); + if ( npts < 2 ){ return; } + + double p0[3]; + double p1[3]; + + points->GetPoint(0,p0); + points->GetPoint(npts-1,p1); + + if ( vtkMath::Distance2BetweenPoints(p0,p1) == 0.0 ) + { + --npts; + this->Closed = 1; + this->ParametricSpline->ClosedOn(); + } + + this->SetNumberOfHandles(npts); + int i; + for ( i = 0; i < npts; ++i ) + { + this->SetHandlePosition(i,points->GetPoint(i)); + } + + if ( this->Interactor && this->Enabled ) + { + this->Interactor->Render(); + } +} + +int vtkSplineWidget::IsClosed() +{ + if ( this->NumberOfHandles < 3 || !this->Closed ) { return 0; } + + vtkPolyData* lineData = this->ParametricFunctionSource->GetOutput(); + if ( !lineData || !(lineData->GetPoints()) ) + { + vtkErrorMacro(<<"No line data to query geometric closure"); + return 0; + } + + vtkPoints *points = lineData->GetPoints(); + int numPoints = points->GetNumberOfPoints(); + + if ( numPoints < 3 ) + { + return 0; + } + + int numEntries = lineData->GetLines()->GetNumberOfConnectivityEntries(); + + double p0[3]; + double p1[3]; + + points->GetPoint( 0, p0 ); + points->GetPoint( numPoints - 1, p1 ); + int minusNth = ( p0[0] == p1[0] && p0[1] == p1[1] && p0[2] == p1[2] ) ? 1 : 0; + int result; + if ( minusNth ) //definitely closed + { + result = 1; + } + else // not physically closed, check connectivity + { + result = ( ( numEntries - numPoints ) == 2 ) ? 1 : 0; + } + + return result; +} diff --git a/Widgets/vtkSplineWidget.h b/Widgets/vtkSplineWidget.h new file mode 100644 index 0000000..616d1f4 --- /dev/null +++ b/Widgets/vtkSplineWidget.h @@ -0,0 +1,340 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkSplineWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkSplineWidget - 3D widget for manipulating a spline +// .SECTION Description +// This 3D widget defines a spline that can be interactively placed in a +// scene. The spline has handles, the number of which can be changed, plus it +// can be picked on the spline itself to translate or rotate it in the scene. +// A nice feature of the object is that the vtkSplineWidget, like any 3D +// widget, will work with the current interactor style. That is, if +// vtkSplineWidget does not handle an event, then all other registered +// observers (including the interactor style) have an opportunity to process +// the event. Otherwise, the vtkSplineWidget will terminate the processing of +// the event that it handles. +// +// To use this object, just invoke SetInteractor() with the argument of the +// method a vtkRenderWindowInteractor. You may also wish to invoke +// "PlaceWidget()" to initially position the widget. The interactor will act +// normally until the "i" key (for "interactor") is pressed, at which point the +// vtkSplineWidget will appear. (See superclass documentation for information +// about changing this behavior.) Events that occur outside of the widget +// (i.e., no part of the widget is picked) are propagated to any other +// registered obsevers (such as the interaction style). Turn off the widget +// by pressing the "i" key again (or invoke the Off() method). +// +// The button actions and key modifiers are as follows for controlling the +// widget: +// 1) left button down on and drag one of the spherical handles to change the +// shape of the spline: the handles act as "control points". +// 2) left button or middle button down on a line segment forming the spline +// allows uniform translation of the widget. +// 3) ctrl + middle button down on the widget enables spinning of the widget +// about its center. +// 4) right button down on the widget enables scaling of the widget. By moving +// the mouse "up" the render window the spline will be made bigger; by moving +// "down" the render window the widget will be made smaller. +// 5) ctrl key + right button down on any handle will erase it providing there +// will be two or more points remaining to form a spline. +// 6) shift key + right button down on any line segment will insert a handle +// onto the spline at the cursor position. +// +// The vtkSplineWidget has several methods that can be used in conjunction with +// other VTK objects. The Set/GetResolution() methods control the number of +// subdivisions of the spline; the GetPolyData() method can be used to get the +// polygonal representation and can be used for things like seeding +// streamlines or probing other data sets. Typical usage of the widget is to +// make use of the StartInteractionEvent, InteractionEvent, and +// EndInteractionEvent events. The InteractionEvent is called on mouse motion; +// the other two events are called on button down and button up (either left or +// right button). +// +// Some additional features of this class include the ability to control the +// properties of the widget. You can set the properties of the selected and +// unselected representations of the spline. For example, you can set the +// property for the handles and spline. In addition there are methods to +// constrain the spline so that it is aligned with a plane. Note that a simple +// ruler widget can be derived by setting the resolution to 1, the number of +// handles to 2, and calling the GetSummedLength method! + +// .SECTION Thanks +// Thanks to Dean Inglis for developing and contributing this class. + +// .SECTION Caveats +// Note that handles and line can be picked even when they are "behind" other +// actors. This is an intended feature and not a bug. + +// .SECTION See Also +// vtk3DWidget vtkBoxWidget vtkLineWidget vtkPointWidget vtkSphereWidget +// vtkImagePlaneWidget vtkImplicitPlaneWidget vtkPlaneWidget + + +#ifndef __vtkSplineWidget_h +#define __vtkSplineWidget_h + +#include "vtk3DWidget.h" + +class vtkActor; +class vtkCellPicker; +class vtkParametricSpline; +class vtkParametricFunctionSource; +class vtkPlaneSource; +class vtkPoints; +class vtkPolyData; +class vtkProp; +class vtkProperty; +class vtkSphereSource; +class vtkTransform; + +#define VTK_PROJECTION_YZ 0 +#define VTK_PROJECTION_XZ 1 +#define VTK_PROJECTION_XY 2 +#define VTK_PROJECTION_OBLIQUE 3 + +class VTK_WIDGETS_EXPORT vtkSplineWidget : public vtk3DWidget +{ +public: + // Description: + // Instantiate the object. + static vtkSplineWidget *New(); + + vtkTypeRevisionMacro(vtkSplineWidget,vtk3DWidget); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Methods that satisfy the superclass' API. + virtual void SetEnabled(int); + virtual void PlaceWidget(double bounds[6]); + void PlaceWidget() + {this->Superclass::PlaceWidget();} + void PlaceWidget(double xmin, double xmax, double ymin, double ymax, + double zmin, double zmax) + {this->Superclass::PlaceWidget(xmin,xmax,ymin,ymax,zmin,zmax);} + + // Description: + // Force the spline widget to be projected onto one of the orthogonal planes. + // Remember that when the state changes, a ModifiedEvent is invoked. + // This can be used to snap the spline to the plane if it is orginally + // not aligned. The normal in SetProjectionNormal is 0,1,2 for YZ,XZ,XY + // planes respectively and 3 for arbitrary oblique planes when the widget + // is tied to a vtkPlaneSource. + vtkSetMacro(ProjectToPlane,int); + vtkGetMacro(ProjectToPlane,int); + vtkBooleanMacro(ProjectToPlane,int); + + // Description: + // Set up a reference to a vtkPlaneSource that could be from another widget + // object, e.g. a vtkPolyDataSourceWidget. + void SetPlaneSource(vtkPlaneSource* plane); + + vtkSetClampMacro(ProjectionNormal,int,VTK_PROJECTION_YZ,VTK_PROJECTION_OBLIQUE); + vtkGetMacro(ProjectionNormal,int); + void SetProjectionNormalToXAxes() + { this->SetProjectionNormal(0); } + void SetProjectionNormalToYAxes() + { this->SetProjectionNormal(1); } + void SetProjectionNormalToZAxes() + { this->SetProjectionNormal(2); } + void SetProjectionNormalToOblique() + { this->SetProjectionNormal(3); } + + // Description: + // Set the position of spline handles and points in terms of a plane's + // position. i.e., if ProjectionNormal is 0, all of the x-coordinate + // values of the points are set to position. Any value can be passed (and is + // ignored) to update the spline points when Projection normal is set to 3 + // for arbritrary plane orientations. + void SetProjectionPosition(double position); + vtkGetMacro(ProjectionPosition, double); + + // Description: + // Grab the polydata (including points) that defines the spline. The + // polydata consists of points and line segments numbering Resolution + 1 + // and Resoltuion, respectively. Points are guaranteed to be up-to-date when + // either the InteractionEvent or EndInteraction events are invoked. The + // user provides the vtkPolyData and the points and polyline are added to it. + void GetPolyData(vtkPolyData *pd); + + // Description: + // Set/Get the handle properties (the spheres are the handles). The + // properties of the handles when selected and unselected can be manipulated. + virtual void SetHandleProperty(vtkProperty*); + vtkGetObjectMacro(HandleProperty, vtkProperty); + virtual void SetSelectedHandleProperty(vtkProperty*); + vtkGetObjectMacro(SelectedHandleProperty, vtkProperty); + + // Description: + // Set/Get the line properties. The properties of the line when selected + // and unselected can be manipulated. + virtual void SetLineProperty(vtkProperty*); + vtkGetObjectMacro(LineProperty, vtkProperty); + virtual void SetSelectedLineProperty(vtkProperty*); + vtkGetObjectMacro(SelectedLineProperty, vtkProperty); + + // Description: + // Set/Get the number of handles for this widget. + virtual void SetNumberOfHandles(int npts); + vtkGetMacro(NumberOfHandles, int); + + // Description: + // Set/Get the number of line segments representing the spline for + // this widget. + void SetResolution(int resolution); + vtkGetMacro(Resolution,int); + + // Description: + // Set the parametric spline object. Through vtkParametricSpline's API, the + // user can supply and configure one of currently two types of spline: + // vtkCardinalSpline, vtkKochanekSpline. The widget controls the open + // or closed configuration of the spline. + // WARNING: The widget does not enforce internal consistency so that all + // three are of the same type. + virtual void SetParametricSpline(vtkParametricSpline*); + vtkGetObjectMacro(ParametricSpline,vtkParametricSpline); + + // Description: + // Set/Get the position of the spline handles. Call GetNumberOfHandles + // to determine the valid range of handle indices. + void SetHandlePosition(int handle, double x, double y, double z); + void SetHandlePosition(int handle, double xyz[3]); + void GetHandlePosition(int handle, double xyz[3]); + double* GetHandlePosition(int handle); + + // Description: + // Control whether the spline is open or closed. A closed spline forms + // a continuous loop: the first and last points are the same, and + // derivatives are continuous. A minimum of 3 handles are required to + // form a closed loop. This method enforces consistency with + // user supplied subclasses of vtkSpline. + void SetClosed(int closed); + vtkGetMacro(Closed,int); + vtkBooleanMacro(Closed,int); + + // Description: + // Convenience method to determine whether the spline is + // closed in a geometric sense. The widget may be set "closed" but still + // be geometrically open (e.g., a straight line). + int IsClosed(); + + // Description: + // Get the approximate vs. the true arc length of the spline. Calculated as + // the summed lengths of the individual straight line segments. Use + // SetResolution to control the accuracy. + double GetSummedLength(); + + // Description: + // Convenience method to allocate and set the handles from a vtkPoints + // instance. If the first and last points are the same, the spline sets + // Closed to the on state and disregards the last point, otherwise Closed + // remains unchanged. + void InitializeHandles(vtkPoints* points); + +protected: + vtkSplineWidget(); + ~vtkSplineWidget(); + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Start=0, + Moving, + Scaling, + Spinning, + Inserting, + Erasing, + Outside + }; +//ETX + + //handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnMiddleButtonDown(); + void OnMiddleButtonUp(); + void OnRightButtonDown(); + void OnRightButtonUp(); + void OnMouseMove(); + + // Controlling vars + int ProjectionNormal; + double ProjectionPosition; + int ProjectToPlane; + vtkPlaneSource* PlaneSource; + + // Projection capabilities + void ProjectPointsToPlane(); + void ProjectPointsToOrthoPlane(); + void ProjectPointsToObliquePlane(); + + // The spline + vtkParametricSpline *ParametricSpline; + vtkParametricFunctionSource *ParametricFunctionSource; + int NumberOfHandles; + int Closed; + void BuildRepresentation(); + + // The line segments + vtkActor *LineActor; + void HighlightLine(int highlight); + int Resolution; + + // Glyphs representing hot spots (e.g., handles) + vtkActor **Handle; + vtkSphereSource **HandleGeometry; + void Initialize(); + int HighlightHandle(vtkProp *prop); //returns handle index or -1 on fail + virtual void SizeHandles(); + void InsertHandleOnLine(double* pos); + void EraseHandle(const int&); + + // Do the picking + vtkCellPicker *HandlePicker; + vtkCellPicker *LinePicker; + vtkActor *CurrentHandle; + int CurrentHandleIndex; + + // Methods to manipulate the spline. + void MovePoint(double *p1, double *p2); + void Scale(double *p1, double *p2, int X, int Y); + void Translate(double *p1, double *p2); + void Spin(double *p1, double *p2, double *vpn); + + // Transform the control points (used for spinning) + vtkTransform *Transform; + + // Properties used to control the appearance of selected objects and + // the manipulator in general. + vtkProperty *HandleProperty; + vtkProperty *SelectedHandleProperty; + vtkProperty *LineProperty; + vtkProperty *SelectedLineProperty; + void CreateDefaultProperties(); + + // For efficient spinning + double Centroid[3]; + void CalculateCentroid(); + +private: + vtkSplineWidget(const vtkSplineWidget&); //Not implemented + void operator=(const vtkSplineWidget&); //Not implemented +}; + +#endif diff --git a/Widgets/vtkXYPlotWidget.cxx b/Widgets/vtkXYPlotWidget.cxx new file mode 100644 index 0000000..e9d8b2b --- /dev/null +++ b/Widgets/vtkXYPlotWidget.cxx @@ -0,0 +1,449 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXYPlotWidget.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkXYPlotWidget.h" +#include "vtkXYPlotActor.h" +#include "vtkCallbackCommand.h" +#include "vtkObjectFactory.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkCoordinate.h" + +vtkCxxRevisionMacro(vtkXYPlotWidget, "$Revision: 1.1 $"); +vtkStandardNewMacro(vtkXYPlotWidget); +vtkCxxSetObjectMacro(vtkXYPlotWidget, XYPlotActor, vtkXYPlotActor); + +vtkXYPlotWidget::vtkXYPlotWidget() +{ + this->XYPlotActor = vtkXYPlotActor::New(); + this->EventCallbackCommand->SetCallback(vtkXYPlotWidget::ProcessEvents); + this->State = vtkXYPlotWidget::Outside; + this->Priority = 0.55; +} + +vtkXYPlotWidget::~vtkXYPlotWidget() +{ + if (this->XYPlotActor) + { + this->XYPlotActor->Delete(); + } +} + +void vtkXYPlotWidget::SetEnabled(int enabling) +{ + if ( ! this->Interactor ) + { + vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget"); + return; + } + + if ( enabling ) + { + vtkDebugMacro(<<"Enabling line widget"); + if ( this->Enabled ) //already enabled, just return + { + return; + } + + if ( ! this->CurrentRenderer ) + { + this->SetCurrentRenderer(this->Interactor->FindPokedRenderer( + this->Interactor->GetLastEventPosition()[0], + this->Interactor->GetLastEventPosition()[1])); + if (this->CurrentRenderer == NULL) + { + return; + } + } + + this->Enabled = 1; + + // listen for the following events + vtkRenderWindowInteractor *i = this->Interactor; + i->AddObserver(vtkCommand::MouseMoveEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonPressEvent, + this->EventCallbackCommand, this->Priority); + i->AddObserver(vtkCommand::LeftButtonReleaseEvent, + this->EventCallbackCommand, this->Priority); + + // Add the xy plot + this->CurrentRenderer->AddViewProp(this->XYPlotActor); + this->InvokeEvent(vtkCommand::EnableEvent,NULL); + } + else //disabling------------------------------------------ + { + vtkDebugMacro(<<"Disabling line widget"); + if ( ! this->Enabled ) //already disabled, just return + { + return; + } + this->Enabled = 0; + + // don't listen for events any more + this->Interactor->RemoveObserver(this->EventCallbackCommand); + + // turn off the line + this->CurrentRenderer->RemoveActor(this->XYPlotActor); + this->InvokeEvent(vtkCommand::DisableEvent,NULL); + this->SetCurrentRenderer(NULL); + } + + this->Interactor->Render(); +} + +void vtkXYPlotWidget::ProcessEvents(vtkObject* vtkNotUsed(object), + unsigned long event, + void* clientdata, + void* vtkNotUsed(calldata)) +{ + vtkXYPlotWidget* self = reinterpret_cast<vtkXYPlotWidget *>( clientdata ); + + //okay, let's do the right thing + switch(event) + { + case vtkCommand::LeftButtonPressEvent: + self->OnLeftButtonDown(); + break; + case vtkCommand::LeftButtonReleaseEvent: + self->OnLeftButtonUp(); + break; + case vtkCommand::MouseMoveEvent: + self->OnMouseMove(); + break; + } +} + + +int vtkXYPlotWidget::ComputeStateBasedOnPosition(int X, int Y, + int *pos1, int *pos2) +{ + int Result; + + // what are we modifying? The position, or size? + // if size what piece? + // if we are within 7 pixels of an edge... + int e1 = 0; + int e2 = 0; + int e3 = 0; + int e4 = 0; + if (X - pos1[0] < 7) + { + e1 = 1; + } + if (pos2[0] - X < 7) + { + e3 = 1; + } + if (Y - pos1[1] < 7) + { + e2 = 1; + } + if (pos2[1] - Y < 7) + { + e4 = 1; + } + + // assume we are moving + Result = vtkXYPlotWidget::Moving; + // unless we are on a corner or edges + if (e2) + { + Result = vtkXYPlotWidget::AdjustingE2; + } + if (e4) + { + Result = vtkXYPlotWidget::AdjustingE4; + } + if (e1) + { + Result = vtkXYPlotWidget::AdjustingE1; + if (e2) + { + Result = vtkXYPlotWidget::AdjustingP1; + } + if (e4) + { + Result = vtkXYPlotWidget::AdjustingP4; + } + } + if (e3) + { + Result = vtkXYPlotWidget::AdjustingE3; + if (e2) + { + Result = vtkXYPlotWidget::AdjustingP2; + } + if (e4) + { + Result = vtkXYPlotWidget::AdjustingP3; + } + } + + return Result; +} + +void vtkXYPlotWidget::SetCursor(int cState) +{ + switch (cState) + { + case vtkXYPlotWidget::AdjustingP1: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZESW); + break; + case vtkXYPlotWidget::AdjustingP3: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZENE); + break; + case vtkXYPlotWidget::AdjustingP2: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZESE); + break; + case vtkXYPlotWidget::AdjustingP4: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZENW); + break; + case vtkXYPlotWidget::AdjustingE1: + case vtkXYPlotWidget::AdjustingE3: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZEWE); + break; + case vtkXYPlotWidget::AdjustingE2: + case vtkXYPlotWidget::AdjustingE4: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZENS); + break; + case vtkXYPlotWidget::Moving: + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_SIZEALL); + break; + } +} + + +void vtkXYPlotWidget::OnLeftButtonDown() +{ + // We're only here is we are enabled + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + // are we over the widget? + //this->Interactor->FindPokedRenderer(X,Y); + int *pos1 = this->XYPlotActor->GetPositionCoordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + int *pos2 = this->XYPlotActor->GetPosition2Coordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + + // are we not over the xy plot, ignore + if (X < pos1[0] || X > pos2[0] || Y < pos1[1] || Y > pos2[1]) + { + return; + } + + // start a drag, store the normalized view coords + double X2 = X; + double Y2 = Y; + // convert to normalized viewport coordinates + this->CurrentRenderer->DisplayToNormalizedDisplay(X2,Y2); + this->CurrentRenderer->NormalizedDisplayToViewport(X2,Y2); + this->CurrentRenderer->ViewportToNormalizedViewport(X2,Y2); + this->StartPosition[0] = X2; + this->StartPosition[1] = Y2; + + this->State = this->ComputeStateBasedOnPosition(X, Y, pos1, pos2); + this->SetCursor(this->State); + + this->EventCallbackCommand->SetAbortFlag(1); + this->StartInteraction(); + this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL); +} + +void vtkXYPlotWidget::OnMouseMove() +{ + // compute some info we need for all cases + int X = this->Interactor->GetEventPosition()[0]; + int Y = this->Interactor->GetEventPosition()[1]; + + + // compute the display bounds of the xy plot if we are inside or outside + int *pos1, *pos2; + if (this->State == vtkXYPlotWidget::Outside || + this->State == vtkXYPlotWidget::Inside) + { + pos1 = this->XYPlotActor->GetPositionCoordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + pos2 = this->XYPlotActor->GetPosition2Coordinate() + ->GetComputedDisplayValue(this->CurrentRenderer); + + if (this->State == vtkXYPlotWidget::Outside) + { + // if we are not over the xy plot, ignore + if (X < pos1[0] || X > pos2[0] || + Y < pos1[1] || Y > pos2[1]) + { + return; + } + // otherwise change our state to inside + this->State = vtkXYPlotWidget::Inside; + } + + // if inside, set the cursor to the correct shape + if (this->State == vtkXYPlotWidget::Inside) + { + // if we have left then change cursor back to default + if (X < pos1[0] || X > pos2[0] || + Y < pos1[1] || Y > pos2[1]) + { + this->State = vtkXYPlotWidget::Outside; + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_DEFAULT); + return; + } + // adjust the cursor based on our position + this->SetCursor(this->ComputeStateBasedOnPosition(X,Y,pos1,pos2)); + return; + } + } + + double XF = X; + double YF = Y; + // convert to normalized viewport coordinates + this->CurrentRenderer->DisplayToNormalizedDisplay(XF,YF); + this->CurrentRenderer->NormalizedDisplayToViewport(XF,YF); + this->CurrentRenderer->ViewportToNormalizedViewport(XF,YF); + + // there are four parameters that can be adjusted + double *fpos1 = this->XYPlotActor->GetPositionCoordinate()->GetValue(); + double *fpos2 = this->XYPlotActor->GetPosition2Coordinate()->GetValue(); + float par1[2]; + float par2[2]; + par1[0] = fpos1[0]; + par1[1] = fpos1[1]; + par2[0] = fpos1[0] + fpos2[0]; + par2[1] = fpos1[1] + fpos2[1]; + + // based on the state, adjust the xy plot parameters + switch (this->State) + { + case vtkXYPlotWidget::AdjustingP1: + par1[0] = par1[0] + XF - this->StartPosition[0]; + par1[1] = par1[1] + YF - this->StartPosition[1]; + break; + case vtkXYPlotWidget::AdjustingP2: + par2[0] = par2[0] + XF - this->StartPosition[0]; + par1[1] = par1[1] + YF - this->StartPosition[1]; + break; + case vtkXYPlotWidget::AdjustingP3: + par2[0] = par2[0] + XF - this->StartPosition[0]; + par2[1] = par2[1] + YF - this->StartPosition[1]; + break; + case vtkXYPlotWidget::AdjustingP4: + par1[0] = par1[0] + XF - this->StartPosition[0]; + par2[1] = par2[1] + YF - this->StartPosition[1]; + break; + case vtkXYPlotWidget::AdjustingE1: + par1[0] = par1[0] + XF - this->StartPosition[0]; + break; + case vtkXYPlotWidget::AdjustingE2: + par1[1] = par1[1] + YF - this->StartPosition[1]; + break; + case vtkXYPlotWidget::AdjustingE3: + par2[0] = par2[0] + XF - this->StartPosition[0]; + break; + case vtkXYPlotWidget::AdjustingE4: + par2[1] = par2[1] + YF - this->StartPosition[1]; + break; + case vtkXYPlotWidget::Moving: + // first apply the move + par1[0] = par1[0] + XF - this->StartPosition[0]; + par1[1] = par1[1] + YF - this->StartPosition[1]; + par2[0] = par2[0] + XF - this->StartPosition[0]; + par2[1] = par2[1] + YF - this->StartPosition[1]; + // then check for an orientation change if the xy plot moves so that + // its center is closer to a different edge that its current edge by + // 0.2 then swap orientation + float centerX = (par1[0] + par2[0])/2.0; + float centerY = (par1[1] + par2[1])/2.0; + // what edge is it closest to + if (fabs(centerX - 0.5) > fabs(centerY - 0.5)) + { + // is it far enough in to consider a change in orientation? + if (fabs(centerX - 0.5) > 0.2+fabs(centerY - 0.5)) + { + // do we need to change orientation + if (!this->XYPlotActor->GetExchangeAxes()) + { + this->XYPlotActor->SetExchangeAxes(1); + // also change the corners + par2[0] = centerX + centerY - par1[1]; + par2[1] = centerY + centerX - par1[0]; + par1[0] = 2*centerX - par2[0]; + par1[1] = 2*centerY - par2[1]; + } + } + } + else + { + // is it far enough in to consider a change in orientation? + if (fabs(centerY - 0.5) > 0.2+fabs(centerX - 0.5)) + { + // do we need to change orientation + if (this->XYPlotActor->GetExchangeAxes()) + { + this->XYPlotActor->SetExchangeAxes(0); + // also change the corners + par2[0] = centerX + centerY - par1[1]; + par2[1] = centerY + centerX - par1[0]; + par1[0] = 2*centerX - par2[0]; + par1[1] = 2*centerY - par2[1]; + } + } + } + break; + } + + // push the change out to the xy plot + // make sure the xy plot doesn't shrink to nothing + if (par2[0] > par1[0] && par2[1] > par1[1]) + { + this->XYPlotActor->GetPositionCoordinate()->SetValue(par1[0],par1[1]); + this->XYPlotActor->GetPosition2Coordinate()-> + SetValue(par2[0] - par1[0], par2[1] - par1[1]); + this->StartPosition[0] = XF; + this->StartPosition[1] = YF; + } + + // start a drag + this->EventCallbackCommand->SetAbortFlag(1); + this->InvokeEvent(vtkCommand::InteractionEvent, NULL); + this->Interactor->Render(); +} + +void vtkXYPlotWidget::OnLeftButtonUp() +{ + if (this->State == vtkXYPlotWidget::Outside) + { + return; + } + + // stop adjusting + this->State = vtkXYPlotWidget::Outside; + this->EventCallbackCommand->SetAbortFlag(1); + this->Interactor->GetRenderWindow()->SetCurrentCursor(VTK_CURSOR_DEFAULT); + this->EndInteraction(); + this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL); + this->Interactor->Render(); +} + + + +void vtkXYPlotWidget::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + + os << indent << "XYPlotActor: " << this->XYPlotActor << "\n"; +} diff --git a/Widgets/vtkXYPlotWidget.h b/Widgets/vtkXYPlotWidget.h new file mode 100644 index 0000000..fc3c2a8 --- /dev/null +++ b/Widgets/vtkXYPlotWidget.h @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkXYPlotWidget.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME vtkXYPlotWidget - 2D widget for manipulating a XY plot +// .SECTION Description +// This class provides support for interactively manipulating the position, +// size, and orientation of a XY Plot. It listens to Left mouse events and +// mouse movement. It will change the cursor shape based on its location. If +// the cursor is over an edge of thea XY plot it will change the cursor shape +// to a resize edge shape. If the position of a XY plot is moved to be close to +// the center of one of the four edges of the viewport, then the XY plot will +// change its orientation to align with that edge. This orientation is sticky +// in that it will stay that orientation until the position is moved close to +// another edge. + +// .SECTION See Also +// vtkInteractorObserver + + +#ifndef __vtkXYPlotWidget_h +#define __vtkXYPlotWidget_h + +#include "vtkInteractorObserver.h" +class vtkXYPlotActor; + +class VTK_WIDGETS_EXPORT vtkXYPlotWidget : public vtkInteractorObserver +{ +public: + static vtkXYPlotWidget *New(); + vtkTypeRevisionMacro(vtkXYPlotWidget,vtkInteractorObserver); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Get the XY plot used by this Widget. One is created automatically. + virtual void SetXYPlotActor(vtkXYPlotActor *); + vtkGetObjectMacro(XYPlotActor,vtkXYPlotActor); + + // Description: + // Methods for turning the interactor observer on and off. + virtual void SetEnabled(int); + +protected: + vtkXYPlotWidget(); + ~vtkXYPlotWidget(); + + // the actor that is used + vtkXYPlotActor *XYPlotActor; + + //handles the events + static void ProcessEvents(vtkObject* object, + unsigned long event, + void* clientdata, + void* calldata); + + // ProcessEvents() dispatches to these methods. + void OnLeftButtonDown(); + void OnLeftButtonUp(); + void OnMouseMove(); + + // used to compute relative movements + float StartPosition[2]; + +//BTX - manage the state of the widget + int State; + enum WidgetState + { + Moving=0, + AdjustingP1, + AdjustingP2, + AdjustingP3, + AdjustingP4, + AdjustingE1, + AdjustingE2, + AdjustingE3, + AdjustingE4, + Inside, + Outside + }; +//ETX + + // use to determine what state the mouse is over, edge1 p1, etc. + // returns a state from the WidgetState enum above + int ComputeStateBasedOnPosition(int X, int Y, int *pos1, int *pos2); + + // set the cursor to the correct shape based on State argument + void SetCursor(int State); + +private: + vtkXYPlotWidget(const vtkXYPlotWidget&); //Not implemented + void operator=(const vtkXYPlotWidget&); //Not implemented +}; + +#endif diff --git a/Wrapping/CMakeLists.txt b/Wrapping/CMakeLists.txt new file mode 100644 index 0000000..5c2fa35 --- /dev/null +++ b/Wrapping/CMakeLists.txt @@ -0,0 +1,31 @@ +# Allow the user to customize their build with some local options +# +INCLUDE (${VTK_SOURCE_DIR}/Wrapping/LocalUserOptions.cmake OPTIONAL) + +# vtkParse.tab.c has #line markers that break #include with double quotes. +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +IF (VTK_WRAP_TCL) + ADD_EXECUTABLE(vtkWrapTcl vtkWrapTcl.c vtkParse.tab.c) + ADD_EXECUTABLE(vtkWrapTclInit vtkWrapTclInit.c) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_TARGETS(${VTK_INSTALL_BIN_DIR} vtkWrapTcl vtkWrapTclInit) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF (VTK_WRAP_TCL) + +IF (VTK_WRAP_PYTHON) + ADD_EXECUTABLE(vtkWrapPython vtkWrapPython.c vtkParse.tab.c) + ADD_EXECUTABLE(vtkWrapPythonInit vtkWrapPythonInit.c) + TARGET_LINK_LIBRARIES(vtkWrapPython ${VTK_PYTHON_LIBRARIES}) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_TARGETS(${VTK_INSTALL_BIN_DIR} vtkWrapPython vtkWrapPythonInit) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF (VTK_WRAP_PYTHON) + +IF (VTK_WRAP_JAVA) + ADD_EXECUTABLE(vtkParseJava vtkParseJava.c vtkParse.tab.c) + ADD_EXECUTABLE(vtkWrapJava vtkWrapJava.c vtkParse.tab.c) + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_TARGETS(${VTK_INSTALL_BIN_DIR} vtkParseJava vtkWrapJava) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF (VTK_WRAP_JAVA) diff --git a/Wrapping/Java/.cvsignore b/Wrapping/Java/.cvsignore new file mode 100644 index 0000000..6b468b6 --- /dev/null +++ b/Wrapping/Java/.cvsignore @@ -0,0 +1 @@ +*.class diff --git a/Wrapping/Java/AxesActor.java b/Wrapping/Java/AxesActor.java new file mode 100644 index 0000000..980a092 --- /dev/null +++ b/Wrapping/Java/AxesActor.java @@ -0,0 +1,130 @@ +import vtk.*; + +public class AxesActor extends vtkAssembly { + + private vtkRenderer ren; + private double axisLength = 0.8; + private double axisTextLength = 1.2; + private vtkTextActor xactor, yactor, zactor; + + public AxesActor(vtkRenderer _ren) { + super(); + ren = _ren; + createAxes(); + } + + public void createAxes() { + vtkAxes axes = new vtkAxes(); + axes.SetOrigin(0, 0, 0); + axes.SetScaleFactor(axisLength); + + xactor = new vtkTextActor(); + yactor = new vtkTextActor(); + zactor = new vtkTextActor(); + + xactor.SetInput("X"); + yactor.SetInput("Y"); + zactor.SetInput("Z"); + + xactor.ScaledTextOn(); + yactor.ScaledTextOn(); + zactor.ScaledTextOn(); + + xactor.GetPositionCoordinate().SetCoordinateSystemToWorld(); + yactor.GetPositionCoordinate().SetCoordinateSystemToWorld(); + zactor.GetPositionCoordinate().SetCoordinateSystemToWorld(); + + xactor.GetPositionCoordinate().SetValue(axisLength, 0.0, 0.0); + yactor.GetPositionCoordinate().SetValue(0.0, axisLength, 0.0); + zactor.GetPositionCoordinate().SetValue(0.0, 0.0, axisLength); + + xactor.GetTextProperty().SetColor(1.0, 1.0, 1.0); + xactor.GetTextProperty().ShadowOn(); + xactor.GetTextProperty().ItalicOn(); + xactor.GetTextProperty().BoldOff(); + + yactor.GetTextProperty().SetColor(1.0, 1.0, 1.0); + yactor.GetTextProperty().ShadowOn(); + yactor.GetTextProperty().ItalicOn(); + yactor.GetTextProperty().BoldOff(); + + zactor.GetTextProperty().SetColor(1.0, 1.0, 1.0); + zactor.GetTextProperty().ShadowOn(); + zactor.GetTextProperty().ItalicOn(); + zactor.GetTextProperty().BoldOff(); + + xactor.SetMaximumLineHeight(0.25); + yactor.SetMaximumLineHeight(0.25); + zactor.SetMaximumLineHeight(0.25); + + vtkTubeFilter tube = new vtkTubeFilter(); + tube.SetInput(axes.GetOutput()); + tube.SetRadius(0.05); + tube.SetNumberOfSides(8); + + vtkPolyDataMapper tubeMapper = new vtkPolyDataMapper(); + tubeMapper.SetInput(tube.GetOutput()); + + vtkActor tubeActor = new vtkActor(); + tubeActor.SetMapper(tubeMapper); + tubeActor.PickableOff(); + + int coneRes = 12; + double coneScale = 0.3; + + //--- x-Cone + vtkConeSource xcone = new vtkConeSource(); + xcone.SetResolution(coneRes); + vtkPolyDataMapper xconeMapper = new vtkPolyDataMapper(); + xconeMapper.SetInput(xcone.GetOutput()); + vtkActor xconeActor = new vtkActor(); + xconeActor.SetMapper(xconeMapper); + xconeActor.GetProperty().SetColor(1,0,0); + xconeActor.SetScale(coneScale, coneScale, coneScale); + xconeActor.SetPosition(axisLength, 0.0, 0.0); + + //--- y-Cone + vtkConeSource ycone = new vtkConeSource(); + ycone.SetResolution(coneRes); + vtkPolyDataMapper yconeMapper = new vtkPolyDataMapper(); + yconeMapper.SetInput(ycone.GetOutput()); + vtkActor yconeActor = new vtkActor(); + yconeActor.SetMapper(yconeMapper); + yconeActor.GetProperty().SetColor(1,1,0); + yconeActor.RotateZ(90); + yconeActor.SetScale(coneScale, coneScale, coneScale); + yconeActor.SetPosition(0.0, axisLength, 0.0); + + //--- z-Cone + vtkConeSource zcone = new vtkConeSource(); + zcone.SetResolution(coneRes); + vtkPolyDataMapper zconeMapper = new vtkPolyDataMapper(); + zconeMapper.SetInput(zcone.GetOutput()); + vtkActor zconeActor = new vtkActor(); + zconeActor.SetMapper(zconeMapper); + zconeActor.GetProperty().SetColor(0,1,0); + zconeActor.RotateY(-90); + zconeActor.SetScale(coneScale, coneScale, coneScale); + zconeActor.SetPosition(0.0, 0.0, axisLength); + + ren.AddActor2D(xactor); + ren.AddActor2D(yactor); + ren.AddActor2D(zactor); + + this.AddPart(tubeActor); + this.AddPart(xconeActor); + this.AddPart(yconeActor); + this.AddPart(zconeActor); + + ren.AddActor(this); + + } + + public void setAxesVisibility(boolean ison) { + this.SetVisibility(ison ? 1 : 0); + xactor.SetVisibility(ison ? 1 : 0); + yactor.SetVisibility(ison ? 1 : 0); + zactor.SetVisibility(ison ? 1 : 0); + } + +} diff --git a/Wrapping/Java/CMakeLists.txt b/Wrapping/Java/CMakeLists.txt new file mode 100644 index 0000000..b827000 --- /dev/null +++ b/Wrapping/Java/CMakeLists.txt @@ -0,0 +1,265 @@ +IF(JAVA_COMPILE) + SET(VTK_JAVA_DEPENDENCIES "") + INCLUDE(${VTK_BINARY_DIR}/Common/JavaDependencies.cmake OPTIONAL) + INCLUDE(${VTK_BINARY_DIR}/Filtering/JavaDependencies.cmake OPTIONAL) + INCLUDE(${VTK_BINARY_DIR}/Graphics/JavaDependencies.cmake OPTIONAL) + INCLUDE(${VTK_BINARY_DIR}/IO/JavaDependencies.cmake OPTIONAL) + INCLUDE(${VTK_BINARY_DIR}/Imaging/JavaDependencies.cmake OPTIONAL) + IF (VTK_USE_PARALLEL) + INCLUDE(${VTK_BINARY_DIR}/Parallel/JavaDependencies.cmake OPTIONAL) + ENDIF(VTK_USE_PARALLEL) + IF (VTK_USE_RENDERING) + INCLUDE(${VTK_BINARY_DIR}/Widgets/JavaDependencies.cmake OPTIONAL) + INCLUDE(${VTK_BINARY_DIR}/Hybrid/JavaDependencies.cmake OPTIONAL) + INCLUDE(${VTK_BINARY_DIR}/VolumeRendering/JavaDependencies.cmake OPTIONAL) + INCLUDE(${VTK_BINARY_DIR}/Rendering/JavaDependencies.cmake OPTIONAL) + ENDIF(VTK_USE_RENDERING) + SET(VTK_JAVA_NEW_STYLE 0) + IF(COMMAND VTK_GENERATE_JAVA_DEPENDENCIES) + IF(VTK_JAVA_DEPENDENCIES) + SET(VTK_JAVA_NEW_STYLE 1) + ENDIF(VTK_JAVA_DEPENDENCIES) + ENDIF(COMMAND VTK_GENERATE_JAVA_DEPENDENCIES) + + IF(VTK_JAVA_NEW_STYLE) + SET(CLASS_FILES ${VTK_JAVA_DEPENDENCIES}) + STRING(REGEX REPLACE "\\.java" ".class;" CLASS_FILES ${VTK_JAVA_DEPENDENCIES}) + ADD_CUSTOM_TARGET(VTKJava ALL) + ADD_CUSTOM_TARGET(VTKJavaJar ALL) + + SET(KITS Common Filtering Graphics IO Imaging) + IF (VTK_USE_PARALLEL) + SET(KITS ${KITS} Parallel) + ENDIF(VTK_USE_PARALLEL) + IF (VTK_USE_RENDERING) + SET(KITS ${KITS} Widgets) + SET(KITS ${KITS} Hybrid) + SET(KITS ${KITS} VolumeRendering) + SET(KITS ${KITS} Rendering) + ENDIF(VTK_USE_RENDERING) + + # Some platforms have libjvm in a subdirectory from + # the rest of the java libraries and are missing the symlink. + IF(JAVA_AWT_LIBRARY) + GET_FILENAME_COMPONENT(JAVA_LIB_DIR ${JAVA_AWT_LIBRARY} PATH) + IF(EXISTS ${JAVA_LIB_DIR}/client) + LINK_DIRECTORIES(${JAVA_LIB_DIR}/client) + ENDIF(EXISTS ${JAVA_LIB_DIR}/client) + ENDIF(JAVA_AWT_LIBRARY) + SET(CMAKE_SKIP_RPATH 0) + ADD_EXECUTABLE(VTKJavaExecutable VTKJava.cxx) + SET(JAVA_LIBRARIES) + + SET(VTK_BUILD_ALL_CONTENT "") + SET(VTK_BUILD_ALL_DEPENDS "") + + FOREACH(kit ${KITS}) + IF(APPLE) + SET(src ${LIBRARY_OUTPUT_PATH}/libvtk${kit}Java.dylib) + SET(tgt ${LIBRARY_OUTPUT_PATH}/libvtk${kit}Java.jnilib) + ADD_CUSTOM_COMMAND(SOURCE ${src} + COMMAND ln + ARGS -sf ${src} ${tgt} + OUTPUTS ${tgt} + TARGET VTKJava) + SET(JAVA_LIBRARIES ${JAVA_LIBRARIES} ${tgt}) + ENDIF(APPLE) + TARGET_LINK_LIBRARIES(VTKJavaExecutable vtk${kit}Java) + SET(VTK_JAVA_DEPENDENCIES "") + ADD_CUSTOM_TARGET(VTKJava${kit} "") + SET(VTK_BUILD_ALL_CONTENT + "${VTK_BUILD_ALL_CONTENT}\n vtk.vtkVTKJava${kit}Driver.Initialize(args);") + SET(VTK_BUILD_ALL_DEPENDS + ${VTK_BUILD_ALL_DEPENDS} + ${VTK_BINARY_DIR}/java/vtk/vtkVTKJava${kit}Driver.java) + INCLUDE(${VTK_BINARY_DIR}/${kit}/JavaDependencies.cmake OPTIONAL) + VTK_GENERATE_JAVA_DEPENDENCIES(VTKJava${kit} ${VTK_JAVA_DEPENDENCIES}) + #ADD_DEPENDENCIES(VTKJava${kit} VTKJavaExecutable) + #ADD_DEPENDENCIES(VTKJava${kit} vtk${kit}JavaJavaClasses) + #ADD_DEPENDENCIES(VTKJavaJar VTKJava${kit}) + ENDFOREACH(kit) + CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Java/vtkBuildAllDriver.java.in + ${VTK_BINARY_DIR}/java/vtk/vtkBuildAllDriver.java) + ADD_CUSTOM_TARGET(VTKBuildAll ALL) + ADD_CUSTOM_COMMAND( + TARGET VTKBuildAll + OUTPUTS ${VTK_BINARY_DIR}/java/vtk/vtkBuildAllDriver.class + DEPENDS ${VTK_BUILD_ALL_DEPENDS} + SOURCE ${VTK_BINARY_DIR}/java/vtk/vtkBuildAllDriver.java + COMMAND ${JAVA_COMPILE} + ARGS -classpath ${VTK_JAVA_HOME}/.. -d ${VTK_JAVA_HOME}/.. + ${VTK_BINARY_DIR}/java/vtk/vtkBuildAllDriver.java + ) + ADD_CUSTOM_COMMAND( + TARGET VTKBuildAll + SOURCE VTKBuildAll + DEPENDS ${VTK_BINARY_DIR}/java/vtk/vtkBuildAllDriver.class + ) + ADD_DEPENDENCIES(VTKJavaJar VTKBuildAll) + + ADD_DEPENDENCIES(VTKJavaFiltering VTKJavaCommon) + ADD_DEPENDENCIES(VTKJavaImaging VTKJavaFiltering) + ADD_DEPENDENCIES(VTKJavaGraphics VTKJavaFiltering) + ADD_DEPENDENCIES(VTKJavaIO VTKJavaFiltering) + SET(VTK_JAVA_DEPENDENCIES vtkTesting2 vtkSettings) + IF(VTK_USE_RENDERING) + SET(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES} vtkPanel) + ADD_DEPENDENCIES(VTKJavaRendering VTKJavaGraphics VTKJavaIO VTKJavaImaging) + ADD_DEPENDENCIES(VTKJavaVolumeRendering VTKJavaRendering) + SET(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES} vtkCanvas) + ADD_DEPENDENCIES(VTKJavaHybrid VTKJavaRendering) + ADD_DEPENDENCIES(VTKJavaWidgets VTKJavaRendering) + ENDIF(VTK_USE_RENDERING) + IF(VTK_USE_PARALLEL) + ADD_DEPENDENCIES(VTKJavaParallel VTKJavaRendering) + ENDIF(VTK_USE_PARALLEL) + FOREACH(jfile ${VTK_JAVA_DEPENDENCIES}) + SET(src ${VTK_SOURCE_DIR}/Wrapping/Java/vtk/${jfile}.java) + SET(dst ${VTK_JAVA_HOME}/${jfile}.java) + SET(class ${VTK_JAVA_HOME}/${jfile}.class) + IF(${jfile} MATCHES vtkSettings) + CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Java/vtk/vtkSettings.java.in + ${VTK_JAVA_HOME}/vtkSettings.java) + ELSE(${jfile} MATCHES vtkSettings) + ADD_CUSTOM_COMMAND( + TARGET VTKJavaJar + SOURCE ${src} + OUTPUTS ${dst} + COMMAND ${CMAKE_COMMAND} + ARGS -E copy ${src} ${dst} + ) + ENDIF(${jfile} MATCHES vtkSettings) + ADD_CUSTOM_COMMAND( + TARGET VTKJavaJar + SOURCE ${dst} + OUTPUTS ${class} + DEPENDS ${VTK_JAVA_HOME}/vtkPanel.java + COMMAND ${JAVA_COMPILE} + ARGS -classpath ${VTK_JAVA_HOME}/.. -d ${VTK_JAVA_HOME}/.. ${dst} + ) + SET(CLASS_FILES ${CLASS_FILES} ${class}) + ENDFOREACH(jfile) + ADD_DEPENDENCIES(VTKJava VTKJavaJar) + + ADD_CUSTOM_COMMAND(SOURCE ${VTK_JAVA_HOME}/vtkObject.class + COMMAND ${JAVA_ARCHIVE} + ARGS -cvf "${LIBRARY_OUTPUT_PATH}/vtk.jar" + -C ${VTK_BINARY_DIR}/java + vtk + TARGET VTKJavaJar + DEPENDS ${CLASS_FILES} ${JAVA_LIBRARIES} + OUTPUTS ${LIBRARY_OUTPUT_PATH}/vtk.jar + COMMENT "Java Archive") + ADD_CUSTOM_COMMAND(SOURCE VTKJavaJar + TARGET VTKJavaJar + DEPENDS ${LIBRARY_OUTPUT_PATH}/vtk.jar) + IF(BUILD_TESTING) + FOREACH(jfile + SimpleVTK + Regression + TestVTKCanvas + TestInternalFrames + ImagePlaneWidget + AxesActor) + ADD_CUSTOM_COMMAND( + SOURCE ${VTK_SOURCE_DIR}/Wrapping/Java/${jfile}.java + COMMAND ${JAVA_COMPILE} + ARGS -classpath ${LIBRARY_OUTPUT_PATH}/vtk.jar + -sourcepath ${VTK_SOURCE_DIR}/Wrapping/Java + -d ${VTK_BINARY_DIR}/Wrapping/Java + ${VTK_SOURCE_DIR}/Wrapping/Java/${jfile}.java + TARGET VTKJava + DEPENDS ${LIBRARY_OUTPUT_PATH}/vtk.jar + OUTPUTS ${VTK_BINARY_DIR}/Wrapping/Java/${jfile}.class + COMMENT "Java Test") + SET(JAVA_TESTS ${JAVA_TESTS} ${VTK_BINARY_DIR}/Wrapping/Java/${jfile}.class) + ENDFOREACH(jfile) + IF(WIN32) + SET(SEPARATOR "\;") + ELSE(WIN32) + SET(SEPARATOR ":") + ENDIF(WIN32) + + # Since vtkTesting is within vtkRendering we need blockers + IF(VTK_USE_RENDERING AND VTK_USE_DISPLAY) + ADD_TEST(JavaRegression ${JAVA_RUNTIME} + -classpath ${LIBRARY_OUTPUT_PATH}/vtk.jar${SEPARATOR}${VTK_BINARY_DIR}/Wrapping/Java + Regression -D ${VTK_DATA_ROOT} + -V Baseline/Graphics/Cone.png) + ENDIF(VTK_USE_RENDERING AND VTK_USE_DISPLAY) + ENDIF(BUILD_TESTING) + + ADD_CUSTOM_COMMAND( + SOURCE VTKJava + TARGET VTKJava + DEPENDS ${LIBRARY_OUTPUT_PATH}/vtk.jar ${JAVA_TESTS} + ) + + ELSE(VTK_JAVA_NEW_STYLE) + + ADD_CUSTOM_TARGET(VTKJava ALL) + ADD_CUSTOM_COMMAND(SOURCE ${VTK_JAVA_HOME}/VTKJavaWrapped + COMMAND ${JAVA_COMPILE} + ARGS ${VTK_JAVA_HOME}/vtk*.java + TARGET VTKJava + OUTPUTS ${VTK_JAVA_HOME}/vtkObject.class) + IF(JAVA_ARCHIVE) + ADD_CUSTOM_COMMAND(SOURCE ${VTK_JAVA_HOME}/vtkObject.class + COMMAND ${CMAKE_COMMAND} + ARGS -E chdir + ${VTK_BINARY_DIR}/java ${JAVA_ARCHIVE} + -cvf "\"${LIBRARY_OUTPUT_PATH}/vtk.jar\"" + vtk + TARGET VTKJava + DEPENDS ${VTK_JAVA_HOME}/vtkObject.class + OUTPUTS ${LIBRARY_OUTPUT_PATH}/vtk.jar) + + IF(BUILD_TESTING) + FOREACH(jfile + SimpleVTK + Regression + TestVTKCanvas + TestInternalFrames + ImagePlaneWidget + AxesActor) + ADD_CUSTOM_COMMAND( + SOURCE ${VTK_SOURCE_DIR}/Wrapping/Java/${jfile}.java + COMMAND ${JAVA_COMPILE} + ARGS -classpath ${LIBRARY_OUTPUT_PATH}/vtk.jar + -sourcepath ${VTK_SOURCE_DIR}/Wrapping/Java + -d ${VTK_BINARY_DIR}/Wrapping/Java + ${VTK_SOURCE_DIR}/Wrapping/Java/${jfile}.java + TARGET VTKJava + DEPENDS ${LIBRARY_OUTPUT_PATH}/vtk.jar + OUTPUTS ${VTK_BINARY_DIR}/Wrapping/Java/${jfile}.class) + SET(JAVA_TESTS ${JAVA_TESTS} ${VTK_BINARY_DIR}/Wrapping/Java/${jfile}.class) + ENDFOREACH(jfile) + IF(WIN32) + SET(SEPARATOR "\;") + ELSE(WIN32) + SET(SEPARATOR ":") + ENDIF(WIN32) + + # Since vtkTesting is within vtkRendering we need blockers + IF(VTK_USE_RENDERING AND VTK_USE_DISPLAY) + ADD_TEST(JavaRegression ${JAVA_RUNTIME} + -classpath ${LIBRARY_OUTPUT_PATH}/vtk.jar${SEPARATOR}${VTK_BINARY_DIR}/Wrapping/Java + Regression -D ${VTK_DATA_ROOT} + -V Baseline/Graphics/Cone.png) + ENDIF(VTK_USE_RENDERING AND VTK_USE_DISPLAY) + ENDIF(BUILD_TESTING) + + ADD_CUSTOM_COMMAND( + SOURCE VTKJava + COMMAND echo + ARGS "Checking dependencies for VTK Java" + TARGET VTKJava + DEPENDS ${LIBRARY_OUTPUT_PATH}/vtk.jar ${JAVA_TESTS} + ) + + IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_INSTALL_JAVA_DIR} FILES ${LIBRARY_OUTPUT_PATH}/vtk.jar) + ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + ENDIF(JAVA_ARCHIVE) + ENDIF(VTK_JAVA_NEW_STYLE) +ENDIF(JAVA_COMPILE) diff --git a/Wrapping/Java/ImagePlaneWidget.java b/Wrapping/Java/ImagePlaneWidget.java new file mode 100644 index 0000000..c8b6979 --- /dev/null +++ b/Wrapping/Java/ImagePlaneWidget.java @@ -0,0 +1,162 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.*; +import vtk.*; + +// Example of complex 3D widget in use. +public class ImagePlaneWidget extends vtkCanvas { + + private int width = 512; + private int height = 512; + + public ImagePlaneWidget(String path) { + super(); + + // attach observer to set the render window size after + // the render window is created... + addWindowSetObserver(new Observer() { + public void update(Observable o, Object arg) { + setSize(width, height); + } + }); + + //Start by loading some data. + vtkVolume16Reader v16 = new vtkVolume16Reader(); + v16.SetDataDimensions(64, 64); + v16.SetDataByteOrderToLittleEndian(); + v16.SetFilePrefix(path); + v16.SetImageRange (1, 93); + v16.SetDataSpacing(3.2, 3.2, 1.5); + v16.Update(); + + setImageData(v16.GetOutput()); + + JPanel p = new JPanel(); + p.setLayout(new BorderLayout()); + p.add(this, BorderLayout.CENTER); + + JFrame frame = new JFrame("ImagePlaneWidget Test"); + frame.setBounds(10, 10, width, height); + frame.getContentPane().add(p, BorderLayout.CENTER); + frame.setVisible(true); + frame.pack(); + + frame.addWindowListener(new WindowAdapter() + { + public void windowClosing(WindowEvent e) {System.exit(0);} + }); + } + + public void setImageData(vtkImageData id) { + + //The shared picker enables us to use 3 planes at one time + //and gets the picking order right + vtkCellPicker picker = new vtkCellPicker(); + picker.SetTolerance(0.005); + + //The 3 image plane widgets are used to probe the dataset. + vtkImagePlaneWidget planeWidgetX = new vtkImagePlaneWidget(); + planeWidgetX.DisplayTextOn(); + planeWidgetX.SetInput(id); + planeWidgetX.SetInteractor(getIren()); + planeWidgetX.SetPlaneOrientationToXAxes(); + planeWidgetX.SetSliceIndex(32); + planeWidgetX.SetPicker(picker); + planeWidgetX.SetKeyPressActivationValue('x'); + planeWidgetX.GetPlaneProperty().SetColor(1, 0, 0); + planeWidgetX.On(); + + vtkImagePlaneWidget planeWidgetY = new vtkImagePlaneWidget(); + planeWidgetY.DisplayTextOn(); + planeWidgetY.SetInput(id); + planeWidgetY.SetInteractor(getIren()); + planeWidgetY.SetPlaneOrientationToYAxes(); + planeWidgetY.SetSliceIndex(32); + planeWidgetY.SetPicker(picker); + planeWidgetY.SetKeyPressActivationValue('y'); + planeWidgetY.GetPlaneProperty().SetColor(1, 1, 0); + planeWidgetY.SetLookupTable(planeWidgetX.GetLookupTable()); + planeWidgetY.On(); + + //for the z-slice, turn off texture interpolation: + //interpolation is now nearest neighbour, to demonstrate + //cross-hair cursor snapping to pixel centers + vtkImagePlaneWidget planeWidgetZ = new vtkImagePlaneWidget(); + planeWidgetZ.DisplayTextOn(); + planeWidgetZ.SetInput(id); + planeWidgetZ.TextureInterpolateOff(); + planeWidgetZ.SetInteractor(getIren()); + planeWidgetZ.SetPlaneOrientationToZAxes(); + planeWidgetZ.SetSliceIndex(46); + planeWidgetZ.SetPicker(picker); + planeWidgetZ.SetKeyPressActivationValue('z'); + planeWidgetZ.GetPlaneProperty().SetColor (0, 0, 1); + planeWidgetZ.SetLookupTable(planeWidgetX.GetLookupTable()); + planeWidgetZ.On(); + + //An outline is shown for context. + vtkOutlineFilter outline = new vtkOutlineFilter(); + outline.SetInput (id); + + vtkPolyDataMapper outlineMapper = new vtkPolyDataMapper(); + outlineMapper.SetInput ( outline.GetOutput() ); + + vtkActor outlineActor = new vtkActor(); + outlineActor.SetMapper(outlineMapper); + + GetRenderer().AddActor(outlineActor); + + //Add the outline actor to the renderer, set the background and size + GetRenderer().GetCullers().RemoveAllItems(); + + GetRenderer().SetBackground(0.1, 0.1, 0.2); + + } + + static public void printUsage(String err) { + if (!err.equals("")) { + System.err.println("Error: " + err); + } + System.err.println("Usage: java ImagePlaneWidget [-D path]"); + System.err.println("Where:"); + System.err.println(" path is location of your VTKData directory"); + System.exit(-1); + } + + + public static void main(String[] argv) { + int argSize = argv.length; + + String pathToVTKData = ""; + + int argCurrent = 0; + + try { + while (argSize > argCurrent) { + if (argv[argCurrent].equals("-D")) { + ++argCurrent; + pathToVTKData = argv[argCurrent]; + ++argCurrent; + } + else { + ImagePlaneWidget.printUsage(""); + } + } + } + catch (Exception e) { + ImagePlaneWidget.printUsage(""); + } + + if (pathToVTKData.equals("")) + ImagePlaneWidget.printUsage(""); + + File f = new File(pathToVTKData + "/Data/headsq"); + if (!f.exists() || !f.canRead() || !f.isDirectory()) + ImagePlaneWidget.printUsage(f.getAbsolutePath() + " does not exist or cannot be read."); + + new ImagePlaneWidget(f.getAbsolutePath() + "/quarter"); + + } +} diff --git a/Wrapping/Java/Regression.java b/Wrapping/Java/Regression.java new file mode 100644 index 0000000..90d2087 --- /dev/null +++ b/Wrapping/Java/Regression.java @@ -0,0 +1,176 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: Regression.java,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +import vtk.*; + +public class Regression +{ + public static void main (String []args) + { + vtkTesting2.Initialize(args, true); + + + vtkShortArray array = new vtkShortArray(); + array.InsertNextTuple1(3.0); + array.InsertNextTuple1(1.0); + array.InsertNextTuple1(4.0); + array.InsertNextTuple1(1.0); + array.InsertNextTuple1(5.0); + array.InsertNextTuple1(9.0); + array.InsertNextTuple1(2.0); + array.InsertNextTuple1(6.0); + array.InsertNextTuple1(5.0); + array.InsertNextTuple1(3.0); + array.InsertNextTuple1(5.0); + array.InsertNextTuple1(8.0); + array.InsertNextTuple1(9.0); + array.InsertNextTuple1(7.0); + array.InsertNextTuple1(9.0); + array.InsertNextTuple1(3.0); + array.InsertNextTuple1(1.0); + short[] carray = array.GetJavaArray(); + int cc; + System.out.print("["); + for ( cc = 0; cc < carray.length; cc ++ ) + { + short i = carray[cc]; + System.out.print(i); + } + System.out.println("]"); + + vtkUnsignedShortArray narray = new vtkUnsignedShortArray(); + narray.SetJavaArray(carray); + System.out.print("["); + for ( cc = 0; cc <= narray.GetMaxId(); cc ++ ) + { + int i = narray.GetValue(cc); + System.out.print(i); + } + System.out.println("]"); + + vtkRenderWindow renWin = new vtkRenderWindow(); + vtkRenderer ren1 = new vtkRenderer(); + renWin.AddRenderer(ren1); + vtkRenderWindowInteractor iren = new vtkRenderWindowInteractor(); + iren.SetRenderWindow(renWin); + vtkConeSource cone = new vtkConeSource(); + cone.SetResolution(8); + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInput(cone.GetOutput()); + + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper(coneMapper); + + ren1.AddActor(coneActor); + renWin.Render(); + vtkWindowToImageFilter w2i = new vtkWindowToImageFilter(); + w2i.SetInput(renWin); + w2i.Modified(); + renWin.Render(); + w2i.Update(); + vtkImageData image = w2i.GetOutput(); + + vtkUnsignedCharArray da = (vtkUnsignedCharArray)image.GetPointData().GetScalars(); + byte[] barray = da.GetJavaArray(); + + System.out.println("Length of array: " + barray.length); + + vtkUnsignedCharArray nda = new vtkUnsignedCharArray(); + nda.SetJavaArray(barray); + + vtkImageData nimage = new vtkImageData(); + nimage.SetDimensions(image.GetDimensions()); + nimage.SetSpacing(image.GetSpacing()); + nimage.SetOrigin(image.GetOrigin()); + nimage.SetScalarType(image.GetScalarType()); + nimage.SetNumberOfScalarComponents(image.GetNumberOfScalarComponents()); + nimage.AllocateScalars(); + vtkUnsignedCharArray nida = (vtkUnsignedCharArray)nimage.GetPointData().GetScalars(); + nida.SetJavaArray(barray); + + int retVal0 = vtkTesting2.PASSED; + + for ( cc = 0; cc <= da.GetMaxId(); cc ++ ) + { + int v1=0, v2=0, v3=0; + v1 = da.GetValue(cc); + if ( cc <= nda.GetMaxId() ) + { + v2 = nda.GetValue(cc); + } + else + { + System.out.println("Cannot find point " + cc + " in nda"); + retVal0 = vtkTesting2.FAILED; + } + if ( cc <= nida.GetMaxId() ) + { + v3 = nida.GetValue(cc); + } + else + { + System.out.println("Cannot find point " + cc + " in nida"); + retVal0 = vtkTesting2.FAILED; + } + if ( v1 != v2 || v1 != v3 ) + { + System.out.println("Wrong point: " + v1 + " <> " + v2 + " <> " + v3); + retVal0 = vtkTesting2.FAILED; + } + } + + vtkImageDifference imgDiff = new vtkImageDifference(); + imgDiff.SetInput(nimage); + imgDiff.SetImage(image); + imgDiff.Update(); + + int retVal1 = vtkTesting2.PASSED; + if ( imgDiff.GetThresholdedError() != 0 ) + { + System.out.println("Problem with array conversion. Image difference is: " + imgDiff.GetThresholdedError()); + vtkPNGWriter wr = new vtkPNGWriter(); + wr.SetInput(image); + wr.SetFileName("im1.png"); + wr.Write(); + wr.SetInput(nimage); + wr.SetFileName("im2.png"); + wr.Write(); + wr.SetInput(imgDiff.GetOutput()); + wr.SetFileName("diff.png"); + wr.Write(); + retVal1 = vtkTesting2.FAILED; + } + + int retVal2 = vtkTesting2.PASSED; + if ( vtkTesting2.IsInteractive() ) + { + iren.Start(); + } + else + { + vtkTesting2.RegressionTest(renWin, 10); + } + + if ( retVal0 != vtkTesting2.PASSED ) + { + vtkTesting2.Exit(retVal0); + } + if ( retVal1 != vtkTesting2.PASSED ) + { + vtkTesting2.Exit(retVal1); + } + vtkTesting2.Exit(retVal2); + } +} + diff --git a/Wrapping/Java/Regression.png b/Wrapping/Java/Regression.png new file mode 100644 index 0000000..d2ce008 Binary files /dev/null and b/Wrapping/Java/Regression.png differ diff --git a/Wrapping/Java/SimpleVTK.java b/Wrapping/Java/SimpleVTK.java new file mode 100644 index 0000000..b78a02e --- /dev/null +++ b/Wrapping/Java/SimpleVTK.java @@ -0,0 +1,61 @@ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import vtk.*; + +/** + * An application that displays a JButton and several JRadioButtons. + * The JRadioButtons determine the look and feel used by the application. + */ +public class SimpleVTK extends JPanel implements ActionListener { + static JFrame frame; + vtkPanel renWin; + JButton exitButton; + + public SimpleVTK() { + setLayout(new BorderLayout()); + // Create the buttons. + renWin = new vtkPanel(); + vtkConeSource cone = new vtkConeSource(); + cone.SetResolution(8); + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInput(cone.GetOutput()); + + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper(coneMapper); + + renWin.GetRenderer().AddActor(coneActor); + + exitButton = new JButton("Exit"); + exitButton.addActionListener(this); + + add(renWin, BorderLayout.CENTER); + add(exitButton, BorderLayout.EAST); + } + + + /** An ActionListener that listens to the radio buttons. */ + public void actionPerformed(ActionEvent e) + { + if (e.getSource().equals(exitButton)) + { + System.exit(0); + } + } + + public static void main(String s[]) + { + SimpleVTK panel = new SimpleVTK(); + + frame = new JFrame("SimpleVTK"); + frame.addWindowListener(new WindowAdapter() + { + public void windowClosing(WindowEvent e) {System.exit(0);} + }); + frame.getContentPane().add("Center", panel); + frame.pack(); + frame.setVisible(true); + } +} + diff --git a/Wrapping/Java/TestInternalFrames.java b/Wrapping/Java/TestInternalFrames.java new file mode 100644 index 0000000..accb49e --- /dev/null +++ b/Wrapping/Java/TestInternalFrames.java @@ -0,0 +1,143 @@ +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import javax.swing.plaf.basic.*; + +public class TestInternalFrames extends JFrame { + + private Desktop theDesktop; + private Dimension screenSize; + + public TestInternalFrames() { + super("VTK Internal Frame Demo"); + screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + this.setSize(900, 900); + + WindowListener l = new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }; + this.addWindowListener(l); + + this.getContentPane().add(new SplitFrame()); + + new MenuMgr(); + + this.show(); + } + + public void addMenuBar(JMenuBar m) { + setJMenuBar(m); + } + + private class SplitFrame extends JSplitPane { + + public SplitFrame( ) { + super(JSplitPane.VERTICAL_SPLIT); + this.setDividerLocation(screenSize.height/2); + setContinuousLayout(true); + setOneTouchExpandable(true); + add(theDesktop = new Desktop()); + add(new Tabbed()); + } + } + + private class Desktop extends JDesktopPane { + + public Desktop( ) { + super(); + this.setPreferredSize(screenSize); + this.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); + this.add(new VTKFrame(10, 10)); + this.add(new VTKFrame(500, 10)); + } + } + + private class Tabbed extends JTabbedPane { + + public Tabbed() { + this.addTab( "vtk1", new TestVTKCanvas() ); + this.addTab( "vtk2", new TestVTKCanvas() ); + + setMinimumSize(new Dimension(300, 300)); + // another swing bug work around + // for some reason the first time the tabbed item is drawn, + // tab 0 is selected but the sphere (tab 1) is drawn + // manually selecting the tabs synchs the tab and the draw order + // it is harmless but it is still annoying + // so we force tab 1 to be selected and hide the bug from the user + // note that selecting 0 does not work.... + this.setSelectedIndex(1); + } + } + + private class VTKFrame extends JInternalFrame { + + public VTKFrame(int x, int y) { + super("VTK Window", true, true, true, true); + Dimension mySize = new Dimension(); + mySize.height = 300; + mySize.width = 300; + this.setSize(mySize); + this.getContentPane().setLayout(new BorderLayout()); + this.setLocation(x, y); + + this.getContentPane().add(new TestVTKCanvas(), BorderLayout.CENTER); + this.pack(); + this.setVisible(true); + } + } + + private class MenuMgr extends JMenuBar { + + JMenu menu; + + public MenuMgr() { + super(); + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + + menu = new JMenu("File"); + menu.add(new CreateWindowAction("Create New VTK Window")); + menu.add(new KillAction("Exit")); + add(menu); + + addMenuBar(this); + } + } + + private class CreateWindowAction extends AbstractAction { + + private int layer = 0; + public CreateWindowAction (String label) { + super(label); + } + + public void actionPerformed(ActionEvent ev) { + theDesktop.add(new VTKFrame(340, 200), + new Integer(layer)); + } + } + + private class KillAction extends AbstractAction { + + public KillAction(String label) { + super(label); + } + + public void actionPerformed(ActionEvent ev) { + System.exit(0); + } + } + + + public static void main(String[] args) { + JFrame f = new TestInternalFrames(); + } +} + + + + + diff --git a/Wrapping/Java/TestVTKCanvas.java b/Wrapping/Java/TestVTKCanvas.java new file mode 100644 index 0000000..f0ec7ff --- /dev/null +++ b/Wrapping/Java/TestVTKCanvas.java @@ -0,0 +1,45 @@ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import vtk.*; + +public class TestVTKCanvas extends JPanel { + + public TestVTKCanvas() { + setLayout(new BorderLayout()); + // Create the buttons. + vtkCanvas renWin = new vtkCanvas(); + add(renWin, BorderLayout.CENTER); + vtkConeSource cone = new vtkConeSource(); + cone.SetResolution(8); + vtkPolyDataMapper coneMapper = new vtkPolyDataMapper(); + coneMapper.SetInput(cone.GetOutput()); + + vtkActor coneActor = new vtkActor(); + coneActor.SetMapper(coneMapper); + + renWin.GetRenderer().AddActor(coneActor); + AxesActor aa = new AxesActor(renWin.GetRenderer()); + renWin.GetRenderer().AddActor(aa); + } + + + public static void main(String s[]) + { + TestVTKCanvas panel = new TestVTKCanvas(); + TestVTKCanvas panel2 = new TestVTKCanvas(); + + JFrame frame = new JFrame("VTK Canvas Test"); + frame.getContentPane().setLayout(new GridLayout(2,1)); + frame.addWindowListener(new WindowAdapter() + { + public void windowClosing(WindowEvent e) {System.exit(0);} + }); + frame.getContentPane().add(panel); + frame.getContentPane().add(panel2); + frame.pack(); + frame.setBounds(100, 100, 500, 500); + frame.setVisible(true); + } +} + diff --git a/Wrapping/Java/VTKJava.cxx b/Wrapping/Java/VTKJava.cxx new file mode 100644 index 0000000..c8d4711 --- /dev/null +++ b/Wrapping/Java/VTKJava.cxx @@ -0,0 +1,6 @@ +#include "vtkSystemIncludes.h" + +int main() +{ + return 0; +} diff --git a/Wrapping/Java/vtk/.cvsignore b/Wrapping/Java/vtk/.cvsignore new file mode 100644 index 0000000..6b468b6 --- /dev/null +++ b/Wrapping/Java/vtk/.cvsignore @@ -0,0 +1 @@ +*.class diff --git a/Wrapping/Java/vtk/vtkCanvas.java b/Wrapping/Java/vtk/vtkCanvas.java new file mode 100644 index 0000000..ebd853d --- /dev/null +++ b/Wrapping/Java/vtk/vtkCanvas.java @@ -0,0 +1,262 @@ +package vtk; +import vtk.*; +import javax.swing.Timer; +import java.awt.*; +import java.awt.event.*; + +public class vtkCanvas extends vtkPanel implements MouseListener, MouseMotionListener, KeyListener +{ + protected vtkGenericRenderWindowInteractor iren = new vtkGenericRenderWindowInteractor(); + protected Timer timer = new Timer(10, new DelayAction()); + protected int ctrlPressed = 0; + protected int shiftPressed = 0; + protected vtkPlaneWidget pw = new vtkPlaneWidget(); + protected vtkBoxWidget bw = new vtkBoxWidget(); + + static { + // load up hybrid for 3d widgets + System.loadLibrary("vtkHybridJava"); + System.loadLibrary("vtkWidgetsJava"); + } + + public vtkCanvas() + { + super(); + iren.SetRenderWindow(rw); + iren.AddObserver("CreateTimerEvent", this, "StartTimer"); + iren.AddObserver("DestroyTimerEvent", this, "DestroyTimer"); + iren.SetSize(200, 200); + iren.ConfigureEvent(); + pw.AddObserver("EnableEvent", this, "BeginPlaneInteraction"); + bw.AddObserver("EnableEvent", this, "BeginBoxInteraction"); + pw.SetKeyPressActivationValue('l'); + bw.SetKeyPressActivationValue('b'); + pw.SetInteractor(iren); + bw.SetInteractor(iren); + + addComponentListener(new ComponentAdapter() + { + public void componentResized(ComponentEvent event) + { + // The Canvas is being resized, get the new size + int width = getWidth(); + int height = getHeight(); + setSize(width, height); + } + }); + + ren.SetBackground(0.0, 0.0, 0.0); + } + + public void StartTimer() { + if (timer.isRunning()) + timer.stop(); + + timer.setRepeats(false); + + timer.start(); + + } + + public void DestroyTimer() { + if (timer.isRunning()) + timer.stop(); + } + + public vtkGenericRenderWindowInteractor getIren() { + return this.iren; + } + + public void setInteractorStyle(vtkInteractorStyle style) { + iren.SetInteractorStyle(style); + } + + public void addToPlaneWidget(vtkProp3D prop) { + pw.SetProp3D(prop); + pw.PlaceWidget(); + } + + public void addToBoxWidget(vtkProp3D prop) { + bw.SetProp3D(prop); + bw.PlaceWidget(); + } + + public void BeginPlaneInteraction() { + System.out.println("Plane widget begin interaction"); + } + + public void BeginBoxInteraction() { + System.out.println("Box widget begin interaction"); + } + + public void setSize(int x, int y) + { + super.setSize(x,y); + if (windowset == 1) { + Lock(); + rw.SetSize(x,y); + iren.SetSize(x, y); + iren.ConfigureEvent(); + UnLock(); + } + } + + public void mouseClicked(MouseEvent e) { + + } + + public void mousePressed(MouseEvent e) + { + if (ren.VisibleActorCount() == 0) return; + Lock(); + rw.SetDesiredUpdateRate(5.0); + lastX = e.getX(); + lastY = e.getY(); + + ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1:0; + shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1:0; + + int repeat = 0; + if(e.getClickCount() != 1) + repeat = 1; + + iren.SetEventInformationFlipY(e.getX(), e.getY(), + ctrlPressed, shiftPressed, '0', 0, "0"); + + if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == + InputEvent.BUTTON1_MASK) + { + iren.LeftButtonPressEvent(); + } + + else if ((e.getModifiers() & InputEvent.BUTTON2_MASK) == + InputEvent.BUTTON2_MASK) { + { + iren.MiddleButtonPressEvent(); + } + } + + else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == + InputEvent.BUTTON3_MASK) { + { + iren.RightButtonPressEvent(); + } + } + + UnLock(); + } + + public void mouseReleased(MouseEvent e) + { + rw.SetDesiredUpdateRate(0.01); + + ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1:0; + shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1:0; + + iren.SetEventInformationFlipY(e.getX(), e.getY(), + ctrlPressed, shiftPressed, '0', 0, "0"); + + if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == + InputEvent.BUTTON1_MASK) { + Lock(); + iren.LeftButtonReleaseEvent(); + UnLock(); + } + + if ((e.getModifiers() & InputEvent.BUTTON2_MASK) == + InputEvent.BUTTON2_MASK) { + Lock(); + iren.MiddleButtonReleaseEvent(); + UnLock(); + } + + if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == + InputEvent.BUTTON3_MASK) { + Lock(); + iren.RightButtonReleaseEvent(); + UnLock(); + } + + } + + public void mouseEntered(MouseEvent e) + { + this.requestFocus(); + iren.SetEventInformationFlipY(e.getX(), e.getY(), + 0, 0, '0', 0, "0"); + iren.EnterEvent(); + } + + public void mouseExited(MouseEvent e) { + iren.SetEventInformationFlipY(e.getX(), e.getY(), + 0, 0, '0', 0, "0"); + iren.LeaveEvent(); + } + + public void mouseMoved(MouseEvent e) + { + lastX = e.getX(); + lastY = e.getY(); + + ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1:0; + shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1:0; + + iren.SetEventInformationFlipY(e.getX(), e.getY(), + ctrlPressed, shiftPressed, '0', 0, "0"); + + Lock(); + iren.MouseMoveEvent(); + UnLock(); + } + + + public void mouseDragged(MouseEvent e) + { + if (ren.VisibleActorCount() == 0) return; + int x = e.getX(); + int y = e.getY(); + + ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1:0; + shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1:0; + + iren.SetEventInformationFlipY(e.getX(), e.getY(), + ctrlPressed, shiftPressed, '0', 0, "0"); + + Lock(); + iren.MouseMoveEvent(); + UnLock(); + + UpdateLight(); + } + + public void keyTyped(KeyEvent e) {} + + public void keyPressed(KeyEvent e) + { + if (ren.VisibleActorCount() == 0) return; + char keyChar = e.getKeyChar(); + + ctrlPressed = (e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK ? 1:0; + shiftPressed = (e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK ? 1:0; + + iren.SetEventInformationFlipY(lastX, lastY, + ctrlPressed, shiftPressed, keyChar, 0, String.valueOf(keyChar)); + + Lock(); + iren.KeyPressEvent(); + iren.CharEvent(); + UnLock(); + } + + public void keyReleased(KeyEvent e) {} + + private class DelayAction implements ActionListener { + public void actionPerformed(ActionEvent evt) { + Lock(); + iren.TimerEvent(); + UpdateLight(); + UnLock(); + } + } + +} diff --git a/Wrapping/Java/vtk/vtkPanel.java b/Wrapping/Java/vtk/vtkPanel.java new file mode 100644 index 0000000..8b2c374 --- /dev/null +++ b/Wrapping/Java/vtk/vtkPanel.java @@ -0,0 +1,460 @@ +package vtk; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import javax.swing.SwingUtilities; + +public class vtkPanel extends Canvas implements + MouseListener, + MouseMotionListener, + KeyListener +{ + protected vtkRenderWindow rw = new vtkRenderWindow(); + protected vtkRenderer ren = new vtkRenderer(); + protected vtkCamera cam = null; + protected vtkLight lgt = new vtkLight(); + protected int lastX; + protected int lastY; + protected int windowset = 0; + protected int lightingset = 0; + protected int LightFollowCamera = 1; + protected int InteractionMode = 1; + protected boolean rendering = false; + protected WindowObservable windowSetObservable = new WindowObservable(); + + static { + System.loadLibrary("vtkCommonJava"); + System.loadLibrary("vtkFilteringJava"); + System.loadLibrary("vtkIOJava"); + System.loadLibrary("vtkImagingJava"); + System.loadLibrary("vtkGraphicsJava"); + System.loadLibrary("vtkRenderingJava"); + try { + System.loadLibrary("vtkHybridJava"); + } catch (Throwable e) { + System.out.println("cannot load vtkHybrid, skipping..."); + } + try { + System.loadLibrary("vtkVolumeRenderingJava"); + } catch (Throwable e) { + System.out.println("cannot load vtkVolumeRendering, skipping..."); + } + } + + protected native int RenderCreate(vtkRenderWindow id0); + protected native int Lock(); + protected native int UnLock(); + + public vtkPanel() + { + rw.AddRenderer(ren); + addMouseListener(this); + addMouseMotionListener(this); + addKeyListener(this); + super.setSize(200,200); + rw.SetSize(200,200); + addWindowSetObserver(new WindowSetObserver()); + } + + public void Report() { + + // must be performed on awt event thread + Runnable updateAComponent = new Runnable() { + public void run() { + Lock(); + System.out.println("direct rendering = " + (rw.IsDirect()==1)); + System.out.println("opengl supported = " + (rw.SupportsOpenGL()==1)); + System.out.println("report = " + rw.ReportCapabilities()); + UnLock(); + } + }; + + SwingUtilities.invokeLater(updateAComponent); + + } + + public vtkRenderer GetRenderer() + { + return ren; + } + + public vtkRenderWindow GetRenderWindow() + { + return rw; + } + + public void addWindowSetObserver(Observer obs) { + windowSetObservable.addObserver(obs); + } + + public void removeWindowSetObserver(Observer obs) { + windowSetObservable.deleteObserver(obs); + } + + public void setSize(int x, int y) + { + super.setSize(x,y); + if (windowset == 1) + { + Lock(); + rw.SetSize(x,y); + UnLock(); + } + } + + public void addNotify() + { + super.addNotify(); + windowset = 0; + rw.SetForceMakeCurrent(); + rendering = false; + } + + public void removeNotify() + { + rendering = true; + super.removeNotify(); + } + + public synchronized void Render() + { + if (!rendering) + { + rendering = true; + if (ren.VisibleActorCount() == 0) {rendering = false; return;} + if (rw != null) + { + if (windowset == 0) + { + // set the window id and the active camera + cam = ren.GetActiveCamera(); + if (lightingset == 0) { + ren.AddLight(lgt); + lgt.SetPosition(cam.GetPosition()); + lgt.SetFocalPoint(cam.GetFocalPoint()); + lightingset = 1; + } + RenderCreate(rw); + Lock(); + rw.SetSize(getWidth(), getHeight()); + UnLock(); + windowset = 1; + // notify observers that we have a renderwindow created + windowSetObservable.notifyObservers(); + } + Lock(); + rw.Render(); + UnLock(); + rendering = false; + } + } + } + + public boolean isWindowSet() + { + return (this.windowset==1); + } + + public void paint(Graphics g) + { + this.Render(); + } + + public void update(Graphics g) { + paint(g); + } + + public void LightFollowCameraOn() + { + this.LightFollowCamera = 1; + } + + public void LightFollowCameraOff() + { + this.LightFollowCamera = 0; + } + + public void InteractionModeRotate() + { + this.InteractionMode = 1; + } + + public void InteractionModeTranslate() + { + this.InteractionMode = 2; + } + + public void InteractionModeZoom() + { + this.InteractionMode = 3; + } + + public void UpdateLight() + { + lgt.SetPosition(cam.GetPosition()); + lgt.SetFocalPoint(cam.GetFocalPoint()); + } + + public void resetCameraClippingRange() { + Lock(); + ren.ResetCameraClippingRange(); + UnLock(); + } + + public void resetCamera() { + Lock(); + ren.ResetCamera(); + UnLock(); + } + + public void mouseClicked(MouseEvent e) { + + } + + public void mousePressed(MouseEvent e) + { + + if (ren.VisibleActorCount() == 0) return; + rw.SetDesiredUpdateRate(5.0); + lastX = e.getX(); + lastY = e.getY(); + if ((e.getModifiers()==InputEvent.BUTTON2_MASK) || + (e.getModifiers()==(InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK))) + { + InteractionModeTranslate(); + } + else if (e.getModifiers()==InputEvent.BUTTON3_MASK) + { + InteractionModeZoom(); + } + else + { + InteractionModeRotate(); + } + } + + public void mouseReleased(MouseEvent e) + { + rw.SetDesiredUpdateRate(0.01); + } + + public void mouseEntered(MouseEvent e) + { + this.requestFocus(); + } + + public void mouseExited(MouseEvent e) {} + + public void mouseMoved(MouseEvent e) + { + lastX = e.getX(); + lastY = e.getY(); + } + + + public void mouseDragged(MouseEvent e) + { + if (ren.VisibleActorCount() == 0) return; + int x = e.getX(); + int y = e.getY(); + // rotate + if (this.InteractionMode == 1) + { + cam.Azimuth(lastX - x); + cam.Elevation(y - lastY); + cam.OrthogonalizeViewUp(); + resetCameraClippingRange(); + if (this.LightFollowCamera == 1) + { + lgt.SetPosition(cam.GetPosition()); + lgt.SetFocalPoint(cam.GetFocalPoint()); + } + } + // translate + if (this.InteractionMode == 2) + { + double FPoint[]; + double PPoint[]; + double APoint[] = new double[3]; + double RPoint[]; + double focalDepth; + + // get the current focal point and position + FPoint = cam.GetFocalPoint(); + PPoint = cam.GetPosition(); + + // calculate the focal depth since we'll be using it a lot + ren.SetWorldPoint(FPoint[0],FPoint[1],FPoint[2],1.0); + ren.WorldToDisplay(); + focalDepth = ren.GetDisplayPoint()[2]; + + APoint[0] = rw.GetSize()[0]/2.0 + (x - lastX); + APoint[1] = rw.GetSize()[1]/2.0 - (y - lastY); + APoint[2] = focalDepth; + ren.SetDisplayPoint(APoint); + ren.DisplayToWorld(); + RPoint = ren.GetWorldPoint(); + if (RPoint[3] != 0.0) + { + RPoint[0] = RPoint[0]/RPoint[3]; + RPoint[1] = RPoint[1]/RPoint[3]; + RPoint[2] = RPoint[2]/RPoint[3]; + } + + /* + * Compute a translation vector, moving everything 1/2 + * the distance to the cursor. (Arbitrary scale factor) + */ + cam.SetFocalPoint( + (FPoint[0]-RPoint[0])/2.0 + FPoint[0], + (FPoint[1]-RPoint[1])/2.0 + FPoint[1], + (FPoint[2]-RPoint[2])/2.0 + FPoint[2]); + cam.SetPosition( + (FPoint[0]-RPoint[0])/2.0 + PPoint[0], + (FPoint[1]-RPoint[1])/2.0 + PPoint[1], + (FPoint[2]-RPoint[2])/2.0 + PPoint[2]); + resetCameraClippingRange(); + } + // zoom + if (this.InteractionMode == 3) + { + double zoomFactor; + double clippingRange[]; + + zoomFactor = Math.pow(1.02,(y - lastY)); + if (cam.GetParallelProjection() == 1) + { + cam.SetParallelScale(cam.GetParallelScale()/zoomFactor); + } + else + { + cam.Dolly(zoomFactor); + resetCameraClippingRange(); + } + } + lastX = x; + lastY = y; + this.Render(); + } + + public void keyTyped(KeyEvent e) {} + + public void keyPressed(KeyEvent e) + { + if (ren.VisibleActorCount() == 0) return; + char keyChar = e.getKeyChar(); + + if ('r' == keyChar) + { + resetCamera(); + this.Render(); + } + if ('u' == keyChar) + { + pickActor(lastX, lastY); + } + if ('w' == keyChar) + { + vtkActorCollection ac; + vtkActor anActor; + vtkActor aPart; + int i, j; + + ac = ren.GetActors(); + ac.InitTraversal(); + for (i = 0; i < ac.GetNumberOfItems(); i++) + { + anActor = ac.GetNextActor(); + anActor.InitPartTraversal(); + for (j = 0; j < anActor.GetNumberOfParts(); j++) + { + aPart = anActor.GetNextPart(); + aPart.GetProperty().SetRepresentationToWireframe(); + } + } + this.Render(); + } + if ('s' == keyChar) + { + vtkActorCollection ac; + vtkActor anActor; + vtkActor aPart; + int i, j; + + ac = ren.GetActors(); + ac.InitTraversal(); + for (i = 0; i < ac.GetNumberOfItems(); i++) + { + anActor = ac.GetNextActor(); + anActor.InitPartTraversal(); + for (j = 0; j < anActor.GetNumberOfParts(); j++) + { + aPart = anActor.GetNextPart(); + aPart.GetProperty().SetRepresentationToSurface(); + } + } + this.Render(); + } + } + + public void HardCopy(String filename, int mag) { + + Lock(); + + vtkWindowToImageFilter w2if = new vtkWindowToImageFilter(); + w2if.SetInput(rw); + + w2if.SetMagnification(mag); + w2if.Update(); + + vtkTIFFWriter writer = new vtkTIFFWriter(); + writer.SetInput(w2if.GetOutput()); + writer.SetFileName(filename); + writer.Write(); + + UnLock(); + } + + public void pickActor(int x, int y) { + + vtkPropPicker picker = new vtkPropPicker(); + + Lock(); + picker.PickProp(x, rw.GetSize()[1] - y , ren); + UnLock(); + + if (picker.GetActor() != null) + System.out.println(picker.GetActor().GetClassName()); + } + + public void keyReleased(KeyEvent e) {} + + private class WindowObservable extends Observable { + + public void notifyObservers() { + this.setChanged(); + super.notifyObservers(); + } + + public void notifyObservers(Object message) { + this.setChanged(); + super.notifyObservers(message); + } + + public boolean hasObservers() { + return 0 < super.countObservers(); + } + } + + private class WindowSetObserver implements Observer { + + public void update(Observable o, Object arg) { + // we know the window is set, so changes to the render window size + // will actually take place +// if (getWidth() > 0 && getHeight() > 0) +// rw.SetSize(getWidth(), getHeight()); + } + + } + +} diff --git a/Wrapping/Java/vtk/vtkSettings.java.in b/Wrapping/Java/vtk/vtkSettings.java.in new file mode 100644 index 0000000..4abf3f1 --- /dev/null +++ b/Wrapping/Java/vtk/vtkSettings.java.in @@ -0,0 +1,51 @@ +package vtk; + +import java.util.Properties; +import java.util.StringTokenizer; + +public class vtkSettings +{ + private static String GetVTKBuildLibDir() { return "@LIBRARY_OUTPUT_PATH@"; } + private static String GetVTKInstallLibDir() { return "@CMAKE_INSTALL_PREFIX@/@VTK_INSTALL_LIB_DIR@"; } + + private static String[] Split(String str, String sep) + { + StringTokenizer st = new StringTokenizer(str, sep); + int size = st.countTokens(); + String[] res = new String[size]; + int cnt = 0; + while (st.hasMoreTokens()) + { + res[cnt] = st.nextToken(); + cnt ++; + } + return res; + } + + public static String GetVTKLibraryDir() + { + String lpath = null; + Properties p = System.getProperties(); + String path_separator = p.getProperty("path.separator"); + String s = p.getProperty("java.class.path"); + String[] paths = vtkSettings.Split(s, path_separator); + int cc; + for ( cc = 0; cc < paths.length; cc ++ ) + { + if ( paths[cc].endsWith("vtk.jar") ) + { + lpath = paths[cc].substring(0, paths[cc].length()-"vtk.jar".length()-1); + } + } + if ( lpath == null ) + { + lpath = vtkSettings.GetVTKInstallLibDir(); + } + return lpath; + } + + public static String[] GetKits() + { + return vtkSettings.Split("@KITS@", ";"); + } +} diff --git a/Wrapping/Java/vtk/vtkTesting2.java b/Wrapping/Java/vtk/vtkTesting2.java new file mode 100644 index 0000000..956b88f --- /dev/null +++ b/Wrapping/Java/vtk/vtkTesting2.java @@ -0,0 +1,117 @@ +package vtk; +import java.io.File; + +import java.util.Properties; + +public class vtkTesting2 +{ + public static final int FAILED = 0; + public static final int PASSED = 1; + public static final int NOT_RUN = 2; + public static final int DO_INTERACTOR = 3; + + private static int LoadLib(String lib, boolean verbose) + { + try + { + if ( verbose ) + { + System.out.println("Try to load: " + lib); + } + Runtime.getRuntime().load(lib); + } + catch (UnsatisfiedLinkError e) + { + if ( verbose ) + { + System.out.println("Failed to load: " + lib); + } + return 0; + } + if ( verbose ) + { + System.out.println("Successfully loaded: " + lib); + } + return 1; + } + + private static void LoadLibrary(String path, String library, boolean verbose) + { + String lname = System.mapLibraryName(library); + String sep = System.getProperty("file.separator"); + String libname = path + sep + lname; + String releaselibname = path + sep + "Release" + sep + lname; + String debuglibname = path + sep + "Debug" + sep + lname; + if ( vtkTesting2.LoadLib(library, verbose) != 1 && + vtkTesting2.LoadLib(libname, verbose) != 1 && + vtkTesting2.LoadLib(releaselibname, verbose) != 1 && + vtkTesting2.LoadLib(debuglibname, verbose) != 1 ) + { + System.out.println("Problem loading apropriate library"); + } + } + + public static void Initialize(String[] args) + { + vtkTesting2.Initialize(args, false); + } + + public static void Initialize(String[] args, boolean verbose) + { + String lpath = vtkSettings.GetVTKLibraryDir(); + if ( lpath != null ) + { + String path_separator = System.getProperty("path.separator"); + String s = System.getProperty("java.library.path"); + s = s + path_separator + lpath; + System.setProperty("java.library.path", s); + } + String lname = System.mapLibraryName("vtkCommonJava"); + String[] kits = vtkSettings.GetKits(); + int cc; + for ( cc = 0; cc < kits.length; cc ++ ) + { + vtkTesting2.LoadLibrary(lpath, "vtk" + kits[cc] + "Java", verbose); + } + vtkTesting2.Tester = new vtk.vtkTesting(); + for ( cc = 0; cc < args.length; cc ++ ) + { + vtkTesting2.Tester.AddArgument(args[cc]); + } + } + + public static boolean IsInteractive() + { + if ( vtkTesting2.Tester.IsInteractiveModeSpecified() == 0 ) + { + return false; + } + return true; + } + + public static void Exit(int retVal) + { + if ( retVal == vtkTesting2.FAILED || retVal == vtkTesting2.NOT_RUN ) + { + System.out.println("Test failed or was not run"); + System.exit(1); + } + System.out.println("Test passed"); + System.exit(0); + } + + public static int RegressionTest( vtkRenderWindow renWin, int threshold ) + { + vtkTesting2.Tester.SetRenderWindow(renWin); + + if (vtkTesting2.Tester.RegressionTest(threshold) == vtkTesting2.PASSED ) + { + return vtkTesting2.PASSED; + } + System.out.println("Image difference: " + vtkTesting2.Tester.GetImageDifference()); + return vtkTesting2.FAILED; + } + + + private static vtkTesting Tester = null; +} diff --git a/Wrapping/Java/vtkBuildAllDriver.java.in b/Wrapping/Java/vtkBuildAllDriver.java.in new file mode 100644 index 0000000..02b7d35 --- /dev/null +++ b/Wrapping/Java/vtkBuildAllDriver.java.in @@ -0,0 +1,10 @@ +// Do not edit +// This file is generated by CMake in VTK +import vtk.*; +class vtkBuildAllDriver +{ + public static void main(String[] args) + { + @VTK_BUILD_ALL_CONTENT@ + } +} diff --git a/Wrapping/JavaDependencies.cmake.in b/Wrapping/JavaDependencies.cmake.in new file mode 100644 index 0000000..016235e --- /dev/null +++ b/Wrapping/JavaDependencies.cmake.in @@ -0,0 +1,5 @@ +# This file is automatically generated by CMake VTK_WRAP_JAVA +SET(VTK_JAVA_DEPENDENCIES ${VTK_JAVA_DEPENDENCIES} +@VTK_JAVA_DEPENDENCIES_FILE@ +) + diff --git a/Wrapping/Python/.cvsignore b/Wrapping/Python/.cvsignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/Wrapping/Python/.cvsignore @@ -0,0 +1 @@ +*.pyc diff --git a/Wrapping/Python/CMakeLists.txt b/Wrapping/Python/CMakeLists.txt new file mode 100644 index 0000000..40f8e1d --- /dev/null +++ b/Wrapping/Python/CMakeLists.txt @@ -0,0 +1,374 @@ +# create the VTK/Python executable +CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Python/vtkPythonAppInitConfigure.h.in + ${VTK_BINARY_DIR}/Wrapping/Python/vtkPythonAppInitConfigure.h) + +ADD_EXECUTABLE(vtkpython vtkPythonAppInit.cxx) +IF(CMAKE_SYSTEM_NAME MATCHES "AIX") + GET_FILENAME_COMPONENT(CMAKE_PYTHON_LIB_PREFIX "${PYTHON_LIBRARY}" PATH) + FIND_FILE(CMAKE_PYTHON_LIBRARY_EXPORT python.exp "${CMAKE_PYTHON_LIB_PREFIX}") + SET_TARGET_PROPERTIES( vtkpython PROPERTIES LINK_FLAGS + "-Wl,-bE:${CMAKE_PYTHON_LIBRARY_EXPORT}") +ENDIF(CMAKE_SYSTEM_NAME MATCHES "AIX") + +IF(VTK_USE_CARBON) + FIND_PROGRAM(VTK_APPLE_RESOURCE Rez /Developer/Tools) + IF(VTK_APPLE_RESOURCE) + ADD_CUSTOM_COMMAND( + SOURCE vtkpython + COMMAND ${VTK_APPLE_RESOURCE} + ARGS Carbon.r -o ${VTK_EXECUTABLE_DIR}/vtkpython + TARGET vtkpython + ) + ENDIF(VTK_APPLE_RESOURCE) +ENDIF(VTK_USE_CARBON) + +IF(UNIX) + FIND_LIBRARY(PYTHON_UTIL_LIBRARY + NAMES util + PATHS /usr/lib + DOC "Utility library needed for vtkpython" + ) + MARK_AS_ADVANCED(PYTHON_UTIL_LIBRARY) + IF(PYTHON_UTIL_LIBRARY) + SET(PYTHON_UTIL_LIBRARY_LIB ${PYTHON_UTIL_LIBRARY}) + ENDIF(PYTHON_UTIL_LIBRARY) +ENDIF(UNIX) + +IF (APPLE) + SET_TARGET_PROPERTIES(vtkpython PROPERTIES LINK_FLAGS "-flat_namespace -undefined suppress -u _PyMac_Error") +ENDIF (APPLE) + +# Link against all the kit wrappers. +TARGET_LINK_LIBRARIES(vtkpython + ${VTK_PYTHON_LIBRARIES} + vtksys + vtkCommon + vtkFiltering + vtkIO + vtkGraphics + vtkImaging + ${PYTHON_UTIL_LIBRARY_LIB}) + +SET (vtkpython_pyc_depends + vtkCommonPython + vtkFilteringPython + vtkIOPython + vtkGraphicsPython + vtkImagingPython + ) + +IF(VTK_WRAP_TCL) + TARGET_LINK_LIBRARIES(vtkpython ${VTK_TK_LIBRARIES}) +ENDIF(VTK_WRAP_TCL) + +IF(BORLAND) + SET(KITS Common Filtering Graphics IO Imaging) + IF (VTK_USE_PARALLEL) + SET(KITS ${KITS} Parallel) + ENDIF(VTK_USE_PARALLEL) + IF (VTK_USE_RENDERING) + SET(KITS ${KITS} Widgets) + SET(KITS ${KITS} Hybrid) + SET(KITS ${KITS} VolumeRendering) + SET(KITS ${KITS} Rendering) + ENDIF(VTK_USE_RENDERING) + FOREACH(KIT ${KITS}) + WRITE_FILE(${LIBRARY_OUTPUT_PATH}/vtk${KIT}Python.def + "EXPORTS\ninitvtk${KIT}Python=_initvtk${KIT}Python\n") + ENDFOREACH(KIT) +ENDIF(BORLAND) + + +IF (VTK_USE_RENDERING) + TARGET_LINK_LIBRARIES(vtkpython vtkRendering) + TARGET_LINK_LIBRARIES(vtkpython vtkVolumeRendering) + TARGET_LINK_LIBRARIES(vtkpython vtkHybrid) + TARGET_LINK_LIBRARIES(vtkpython vtkWidgets) + SET (vtkpython_pyc_depends + ${vtkpython_pyc_depends} + vtkRenderingPython + vtkVolumeRenderingPython + vtkHybridPython + vtkWidgetsPython + ) +ENDIF (VTK_USE_RENDERING) + +IF (VTK_USE_PARALLEL) + TARGET_LINK_LIBRARIES(vtkpython vtkParallel) + SET(vtkpython_pyc_depends + ${vtkpython_pyc_depends} + vtkParallelPython + ) +ENDIF (VTK_USE_PARALLEL) + +# Link to rt to prevent undefined symbol 'fdatasync' + +IF(CMAKE_SYSTEM MATCHES "SunOS.*") + IF(NOT CMAKE_COMPILER_IS_GNUCXX) + FIND_LIBRARY(VTK_SUNCC_RT_LIBRARY rt /usr/lib) + IF(VTK_SUNCC_RT_LIBRARY) + TARGET_LINK_LIBRARIES(vtkpython ${VTK_SUNCC_RT_LIBRARY}) + ENDIF(VTK_SUNCC_RT_LIBRARY) + ENDIF(NOT CMAKE_COMPILER_IS_GNUCXX) +ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*") + +# Create the pvtkpython Python wrapper executable with MPI support. +IF (VTK_USE_PARALLEL) + IF (VTK_USE_MPI) + ADD_EXECUTABLE(pvtkpython vtkParaPythonAppInit.cxx) + IF(CMAKE_SYSTEM_NAME MATCHES "AIX") + SET_TARGET_PROPERTIES( pvtkpython PROPERTIES LINK_FLAGS + "-Wl,-bE:${CMAKE_PYTHON_LIBRARY_EXPORT}") + ENDIF(CMAKE_SYSTEM_NAME MATCHES "AIX") + IF(VTK_USE_CARBON) + FIND_PROGRAM(VTK_APPLE_RESOURCE Rez /Developer/Tools) + IF(VTK_APPLE_RESOURCE) + ADD_CUSTOM_COMMAND( + SOURCE pvtkpython + COMMAND ${VTK_APPLE_RESOURCE} + ARGS Carbon.r -o ${VTK_EXECUTABLE_DIR}/pvtkpython + TARGET pvtkpython + ) + ENDIF(VTK_APPLE_RESOURCE) + ENDIF(VTK_USE_CARBON) + + TARGET_LINK_LIBRARIES (pvtkpython + ${VTK_PYTHON_LIBRARIES} + vtksys + vtkCommon + vtkFiltering + vtkIO + vtkGraphics + vtkImaging + vtkParallel + ${PYTHON_UTIL_LIBRARY_LIB} + ) + IF (VTK_USE_RENDERING) + TARGET_LINK_LIBRARIES(pvtkpython vtkVolumeRendering) + TARGET_LINK_LIBRARIES(pvtkpython vtkHybrid) + TARGET_LINK_LIBRARIES(pvtkpython vtkWidgets) + ENDIF (VTK_USE_RENDERING) + IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_TARGETS(${VTK_INSTALL_BIN_DIR} pvtkpython) + ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + ENDIF (VTK_USE_MPI) +ENDIF (VTK_USE_PARALLEL) + +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_TARGETS(${VTK_INSTALL_BIN_DIR} vtkpython) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + +# Handle out-of-source builds correctly. +# +# 1. Create a list of Python files to be installed/copied. +# 2. Copy them to VTK_BINARY_DIR if it is different from VTK_SOURCE_DIR. +# 3. Use Python's compileall to compile the copied files. +# +# *** Step 1 has to be done carefully to avoid missing out files *** + +IF(PYTHON_EXECUTABLE) +# Make the necessary directories. + FOREACH(dir + ${VTK_BINARY_DIR}/Wrapping/Python/vtk/gtk + ${VTK_BINARY_DIR}/Wrapping/Python/vtk/qt + ${VTK_BINARY_DIR}/Wrapping/Python/vtk/tk + ${VTK_BINARY_DIR}/Wrapping/Python/vtk/util + ${VTK_BINARY_DIR}/Wrapping/Python/vtk/wx + ${VTK_BINARY_DIR}/Wrapping/Python/vtk/test + ) + MAKE_DIRECTORY(${dir}) + ENDFOREACH(dir) + +# Now create a list of Python files. + +# Wrapping/Python/vtk/*.py + SET(VTK_PYTHON_FILES + vtk/__helper + vtk/__init__ + vtk/common + vtk/filtering + vtk/genericfiltering + vtk/graphics + vtk/hybrid + vtk/imaging + vtk/io + vtk/parallel + vtk/rendering + vtk/required + vtk/volumerendering + vtk/widgets + ) + +# vtk.util package + SET(VTK_PYTHON_FILES + ${VTK_PYTHON_FILES} + vtk/util/__init__ + vtk/util/vtkMethodParser + vtk/util/misc + vtk/util/vtkConstants + vtk/util/vtkImageExportToArray + vtk/util/vtkImageImportFromArray + vtk/util/colors + ) + +# vtk.test package + SET(VTK_PYTHON_FILES + ${VTK_PYTHON_FILES} + vtk/test/BlackBox + vtk/test/Testing + vtk/test/__init__ + ) + +# Tk related files + SET(VTK_PYTHON_FILES + ${VTK_PYTHON_FILES} + vtk/tk/__init__ + vtk/tk/vtkLoadPythonTkWidgets + vtk/tk/vtkTkImageViewerWidget + vtk/tk/vtkTkRenderWidget + vtk/tk/vtkTkRenderWindowInteractor + vtk/tk/vtkTkPhotoImage + ) + +# QT related files + SET(VTK_PYTHON_FILES + ${VTK_PYTHON_FILES} + vtk/qt/QVTKRenderWidget + vtk/qt/__init__ + vtk/qt/QVTKRenderWindowInteractor + ) + +# wxPython related files + SET(VTK_PYTHON_FILES + ${VTK_PYTHON_FILES} + vtk/wx/__init__ + vtk/wx/wxVTKRenderWindow + vtk/wx/wxVTKRenderWindowInteractor + ) + +# pyGTK related files + SET(VTK_PYTHON_FILES + ${VTK_PYTHON_FILES} + vtk/gtk/GtkVTKRenderWindow + vtk/gtk/__init__ + vtk/gtk/GtkVTKRenderWindowInteractor + ) + +# Done listing of files. + +# Now copy these files if necessary. + SET(VTK_PYTHON_SOURCE_FILES) + SET(VTK_PYTHON_OUTPUT_FILES) + FOREACH(file ${VTK_PYTHON_FILES}) + SET(src "${VTK_BINARY_DIR}/Wrapping/Python/${file}.py") + SET(VTK_PYTHON_SOURCE_FILES ${VTK_PYTHON_SOURCE_FILES} ${src}) + ENDFOREACH(file) + + IF ("${VTK_BINARY_DIR}" MATCHES "^${VTK_SOURCE_DIR}$") + #MESSAGE("In source build -- no need to copy Python files.") + ELSE ("${VTK_BINARY_DIR}" MATCHES "^${VTK_SOURCE_DIR}$") + FOREACH(file ${VTK_PYTHON_FILES}) + SET(src "${VTK_SOURCE_DIR}/Wrapping/Python/${file}.py") + SET(tgt "${VTK_BINARY_DIR}/Wrapping/Python/${file}.py") + ADD_CUSTOM_COMMAND(DEPENDS ${src} + COMMAND ${CMAKE_COMMAND} + ARGS -E copy ${src} ${tgt} + OUTPUT ${tgt} + COMMENT "source copy") + ENDFOREACH(file) + ENDIF ("${VTK_BINARY_DIR}" MATCHES "^${VTK_SOURCE_DIR}$") + + # Byte compile the Python files. + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/compile_all_vtk.py.in + ${CMAKE_CURRENT_BINARY_DIR}/compile_all_vtk.py + @ONLY IMMEDIATE) + ADD_CUSTOM_COMMAND( + COMMAND ${PYTHON_EXECUTABLE} + ARGS ${CMAKE_CURRENT_BINARY_DIR}/compile_all_vtk.py + DEPENDS ${VTK_PYTHON_SOURCE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/compile_all_vtk.py + OUTPUT "${VTK_BINARY_DIR}/Wrapping/Python/vtk_compile_complete" + ) + + # Create a target on which custom commands can depend. When this + # is up-to-date, it is safe to run VTK python code. Therefore + # this should also depend on the vtkpython executable. + ADD_CUSTOM_TARGET(vtkpython_pyc ALL echo "..." + DEPENDS "${VTK_BINARY_DIR}/Wrapping/Python/vtk_compile_complete") + ADD_DEPENDENCIES(vtkpython_pyc + vtkpython + ${vtkpython_pyc_depends}) + + # If no runtime is to be installed then do not install python modules. + IF(VTK_INSTALL_NO_RUNTIME) + SET(VTK_INSTALL_NO_PYTHON 1) + ENDIF(VTK_INSTALL_NO_RUNTIME) + + # Add a rule to use python distutils to install the python wrappers. + IF(NOT VTK_INSTALL_NO_PYTHON) + SET(DOLLAR "$") + + # Create default python setup arguments if they are not set. + IF(DEFINED VTK_PYTHON_SETUP_ARGS) + ELSE(DEFINED VTK_PYTHON_SETUP_ARGS) + SET(VTK_PYTHON_SETUP_ARGS "--prefix=\"${DOLLAR}{CMAKE_INSTALL_PREFIX}\"" + CACHE STRING "Arguments passed to \"python setup.py install ...\" during installation.") + MARK_AS_ADVANCED(VTK_PYTHON_SETUP_ARGS) + ENDIF(DEFINED VTK_PYTHON_SETUP_ARGS) + + # If there are multiple configurations then add a BUILD_TYPE=... + # argument to the python setup.py call. The build type to use is set + # in the CMake variable BUILD_TYPE while running the install script. + IF(CMAKE_CONFIGURATION_TYPES) + SET(VTK_PYTHON_SETUP_BUILD_TYPE "BUILD_TYPE=${DOLLAR}{BUILD_TYPE}") + ELSE(CMAKE_CONFIGURATION_TYPES) + SET(VTK_PYTHON_SETUP_BUILD_TYPE) + ENDIF(CMAKE_CONFIGURATION_TYPES) + + # Configure the post-install script to run python on setup.py. + CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Python/PythonInstall.cmake.in + ${VTK_BINARY_DIR}/Wrapping/Python/PythonInstall.cmake + @ONLY IMMEDIATE) + SET_TARGET_PROPERTIES(vtkpython_pyc PROPERTIES POST_INSTALL_SCRIPT + ${VTK_BINARY_DIR}/Wrapping/Python/PythonInstall.cmake + ) + ENDIF(NOT VTK_INSTALL_NO_PYTHON) +ENDIF(PYTHON_EXECUTABLE) + +# Create the setup.py file. +IF(CMAKE_CONFIGURATION_TYPES) + # The build has multiple configuration types. If CMAKE_BUILD_TYPE + # is set use it as the default BUILD_TYPE for setup.py to install. + SET(VTK_PYTHON_HAS_CONFIG_TYPES 1) + IF(CMAKE_BUILD_TYPE) + SET(VTK_PYTHON_BUILD_TYPE "\"${CMAKE_BUILD_TYPE}\"") + ELSE(CMAKE_BUILD_TYPE) + SET(VTK_PYTHON_BUILD_TYPE "[]") + ENDIF(CMAKE_BUILD_TYPE) +ELSE(CMAKE_CONFIGURATION_TYPES) + # The build has one configuration type. The build type does not + # affect installation. + SET(VTK_PYTHON_HAS_CONFIG_TYPES 0) + SET(VTK_PYTHON_BUILD_TYPE "[]") +ENDIF(CMAKE_CONFIGURATION_TYPES) +IF(VTK_USE_RENDERING) + SET(VTK_PYTHON_USE_RENDERING 1) +ELSE(VTK_USE_RENDERING) + SET(VTK_PYTHON_USE_RENDERING 0) +ENDIF(VTK_USE_RENDERING) +IF(VTK_USE_PARALLEL) + SET(VTK_PYTHON_USE_PARALLEL 1) +ELSE(VTK_USE_PARALLEL) + SET(VTK_PYTHON_USE_PARALLEL 0) +ENDIF(VTK_USE_PARALLEL) +IF(VTK_USE_MPI) + SET(VTK_PYTHON_USE_MPI 1) +ELSE(VTK_USE_MPI) + SET(VTK_PYTHON_USE_MPI 0) +ENDIF(VTK_USE_MPI) +CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Python/setup.py.in + ${VTK_BINARY_DIR}/Wrapping/Python/setup.py @ONLY IMMEDIATE) + +# Allow the user to customize their build with some local options +# +INCLUDE (${VTK_BINARY_DIR}/Wrapping/Tcl/LocalUserOptions.cmake OPTIONAL) +INCLUDE (${VTK_SOURCE_DIR}/Wrapping/Tcl/LocalUserOptions.cmake OPTIONAL) diff --git a/Wrapping/Python/PythonInstall.cmake.in b/Wrapping/Python/PythonInstall.cmake.in new file mode 100644 index 0000000..92df5a6 --- /dev/null +++ b/Wrapping/Python/PythonInstall.cmake.in @@ -0,0 +1,18 @@ +# Configured file and directory locations. +SET(PYTHON_EXECUTABLE "@PYTHON_EXECUTABLE@") +SET(CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") +SET(VTK_BINARY_DIR "@VTK_BINARY_DIR@") + +# Convert the prefix to a windows path if necessary. The python +# distutils implementation seems sensitive to the slash direction. +IF(WIN32) + IF(NOT CYGWIN) + STRING(REGEX REPLACE "/" "\\\\" CMAKE_INSTALL_PREFIX + "${CMAKE_INSTALL_PREFIX}") + ENDIF(NOT CYGWIN) +ENDIF(WIN32) + +# Run python on setup.py to install the python modules. +EXEC_PROGRAM("${PYTHON_EXECUTABLE}" "${VTK_BINARY_DIR}/Wrapping/Python" ARGS + "setup.py" "install" @VTK_PYTHON_SETUP_BUILD_TYPE@ @VTK_PYTHON_SETUP_ARGS@ + ) diff --git a/Wrapping/Python/README.txt b/Wrapping/Python/README.txt new file mode 100644 index 0000000..2084dab --- /dev/null +++ b/Wrapping/Python/README.txt @@ -0,0 +1,360 @@ +================================ +VTK-Python Package Documentation +================================ +:Contact: vtk-developers@vtk.org + +.. contents:: + + +Introduction +^^^^^^^^^^^^ + +This file documents the VTK-Python modules. + +The file `README_WRAP.txt` provides a detailed description of how VTK +objects are accessed and modified through Python. + + +Installation +^^^^^^^^^^^^ + +VTK can be built either from inside the source directory (an +in-source build) or in another directory separate from the source +directory (called an out-of-source build). The VTK source directory +is called `VTK_SOURCE_DIR` and the directory in which VTK is built +is called `VTK_BINARY_DIR`. Note that `VTK_BINARY_DIR` is identical +to `VTK_SOURCE_DIR` when an in-source build is performed. Both +these variables are defined in `CMakeCache.txt`. The following +instructions apply to both in-source or out-of-source builds. The +variable `VTK_ROOT` used in the following refers to +`VTK_BINARY_DIR`. + +There are primarily three ways of using the VTK-Python wrappers and +modules. + + (1) If you are building VTK from source and want to use the + VTK-Python packages alone, i.e. you don't want to use VTK via + C++, Tcl, etc., then simply use the `vtkpython` interpreter + that is built with VTK. This is a Python interpreter that is + linked to the relevant VTK libraries and sets the `PYTHONPATH` + internally to the correct locations. So, all you need to do + is use `vtkpython` instead of `python`. Naturally this will + work only if you retain your build tree and don't change the + directories where VTK was built. + + (2) Using the package from the source build without installing it + system wide and without using `vtkpython`. This is most + useful when you build VTK off a CVS checkout and do not want + to install it system wide and still want to use the vanilla + Python interpreter. This is also useful if you are not the + administrator of the machine you are using/building VTK on. + + Unix/Linux + Under Unix the way to do this is to set the `LD_LIBRARY_PATH` + (or equivalent) to the directory that contains the libvtk*.so + libraries. You must also set your `PYTHONPATH` to *both* the + directory that contains all the `libvtk*Python.so` files *and* + the `Wrapping/Python` directory. Under bash/sh something like + so needs to be done:: + + $ export LD_LIBRARY_PATH=$LIBRARY_OUTPUT_PATH + $ export PYTHONPATH=$VTK_ROOT/Wrapping/Python:${LIBRARY_OUTPUT_PATH} + + and under csh:: + + $ setenv LD_LIBRARY_PATH ${LIBRARY_OUTPUT_PATH} + $ setenv PYTHONPATH ${VTK_ROOT}/Wrapping/Python:${LIBRARY_OUTPUT_PATH} + + where VTK_ROOT is the directory where VTK is being built + (`VTK_BINARY_DIR`) and `LIBRARY_OUTPUT_PATH` (this variable is + set in `CMakeCache.txt`) is where the libraries are built. + Change this to suit your configuration. + + Win32 + Similar to the Unix approach, set your `PATH` to point to the + directory that contains the VTK DLL's and the `PYTHONPATH` to + the directory that contains the Wrapping/Python directory and + the DLL's. Note that under Win32 the directory containing the + DLL's is in a sub-directory of `LIBRARY_OUTPUT_PATH`. The + sub-directory is one of Release, Debug, MinSizeRel or + RelWithDebInfo. + + + (3) Installation via distutils to a directory different from the + `VTK_ROOT` directory. To install VTK built from source you + simply need to run the "install rule". Under Unix this + implies running `make install` and under Windows this implies + running the INSTALL target. + + The installation rule internally executes the + ``VTK_BINARY_DIR/Wrapping/Python/setup.py`` script. + `setup.py` is a distutils script that should install + VTK-Python correctly. The `setup.py` script may also be + executed from the `VTK_BINARY_DIR` in order to build an + installer (via `bdist_wininst`) or to build a Python Egg. + + +VTK-Python interpreters +^^^^^^^^^^^^^^^^^^^^^^^ + +In order to solve some problems with running VTK-Python on some +platforms and compilers a special Python interpreter is distributed +along with VTK. This new interpreter is called `vtkpython` and is +the recommended way of running VTK-Python scripts. If the vanilla +Python interpreter is good enough and works well for you, please use +it. However if you run into severe problems you might want to give +vtkpython a try. Incidentally, to see what the problems are with +the vanilla Python interpreter on some platforms read this thread: + +http://public.kitware.com/pipermail/vtk-developers/2002-May/001536.html + +Additionally, if you built VTK along with MPI support +(`VTK_USE_PARALLEL` and `VTK_USE_MPI` are true) then another +VTK-Python interpreter called `pvtkpython` is also built. This +interpreter initializes MPI correctly and is the recommended way to +run parallel VTK-Python scripts. + + +Structure/Usage +^^^^^^^^^^^^^^^ + +Once the Python packages are installed properly (either system wide +or by using environment variables) to use the new package structure +users will just do:: + + import vtk + # or + from vtk import * + +and all the available 'kits' will be loaded - just like with the +older vtkpython. The name of the kits is available in the kits +variable:: + + import vtk + print vtk.kits + ['common', 'filtering', 'io', ...] + +If the user specifically wants just the classes the Common directory +imported the user does:: + + import vtk.common + +All the kit names are in lowercase. This is similar to the way in +which the Tcl packages are split. Similarly, classes specifically +in other kits can be imported by using the appropriate kit name. +Please do note that even when you import vtk.common, the vtk +namespace will still have all the kits loaded inside it. Its just +that vtk.common will have only the classes from the Common +directory. + + +Valid Kit names +~~~~~~~~~~~~~~~ + +Required Kits +------------- + +common, filtering, io, imaging and graphics. + +These are the required kits that you must have to use VTK. You +can import all of them using the required module like so: + + from vtk.required import * + +You should have all the required kits in your namespace. If any +of them is not importable you *will* get an ImportError. + +Optional Kits +------------- + +genericfiltering, hybrid, parallel, rendering, volumerendering, +and widgets. + +These are the optional kits. Unlike the Tcl packages importing +these kits *will not* import all the required kits in as well. +For the rationale behind this please read this mail and also the +thread here: + +http://public.kitware.com/pipermail/vtk-developers/2001-October/000828.html + +If you don't have a particular optional kit then Python will not +raise an exception when importing vtk, but if you try loading it +directly like so:: + + import vtk.parallel + +Then you will receive an import error if there was one. Also, if +the module exists but there are linking errors you will get a +LinkError exception. + + +Other VTK related modules +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Apart from the basic VTK functionality there are other useful VTK +related modules in the package. There are various widgets for +different GUI toolkits. These are available in the various +sub-directories of the vtk directory. At the time of this writing +the following widgets are available. + + gtk -- pyGTK widgets. + + qt -- Qt widgets. + + tk -- The Tkinter widgets. + + wx -- wxPython widgets. + +The widgets can be used like so:: + + from vtk.tk import vtkTkRenderWidget + # or + from vtk.gtk import GtkVTKRenderWindow + # etc. + +To see what widgets are available please look at the various +directories in the `vtk` sub-directory. + +Apart from the GUI widgets there is a package called `vtk.util`. +This directory will contain miscellaneous modules that are useful +for different things. Again, look at the directory to see what is +available. + +There is also a `vtk.test` package that allows one to create unit +tests for VTK-Python. + + +Backwards compatibility +^^^^^^^^^^^^^^^^^^^^^^^ + +Since VTK-4.0, the usage of `vtkpython`, `vtkpythontk`, +`vtkTkRenderWidget` and other modules in the Wrapping/Python +directory were deprecated. As of VTK-5.0, these files are no longer +available. Please use the `vtk` package instead which provides the +functionality. + + +Writing and running VTK-Python tests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `vtk.test` package provides a module called `Testing` that +contains useful utility functions and a `vtkTest` class. These ease +creation of VTK-Python unittests. The file +`Wrapping/Python/vtk/test/Testing.py` is well documented and provides +more detailed information including pointers to examples. VTK-Python +test writers are encouraged to use this module. + +When you need to run a VTK-Python unittest that uses the +`vtk.test.Testing` module run the example with a `-h` (or `--help`) +argument to see all the supported options. Typically you will need +to do something like the following:: + + python TestTkRenderWidget.py -B $VTK_DATA_ROOT/Baseline/Rendering + +To see the options available use this:: + + python TestTkRenderWidget.py -h + + +Information for packagers +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section provides some details on how best to package VTK-Python +in the form of Debian, RPM and other packages. + + 1. VTK releases by default have `VTK_USE_RPATH` set to `OFF`. + However, VTK from CVS defaults to `ON`. Therefore, it is + important to make sure that `VTK_USE_RPATH` is `OFF`. + `VTK_USE_RPATH` is handy for developers who build VTK from CVS + and do not install it system wide. It is not handy for + packagers. + + 2. VTK libraries (starting with VTK-5.0) are versioned. + Therefore, it is safe to install multiple versions of VTK. + Prior to VTK-5.0 this was not the case. + + 3. VTK-Python has two components. The ``libvtk*PythonD.so.*`` (or + ``vtk*PythonD.dll``) files should be treated as libraries and + *not* as Python extension modules. Only the + ``libvtk*Python.so`` (or ``vtk*Python.dll``) files are Python + extension modules. These extension modules are linked to the + `PythonD.so` libraries. + + Therefore, the ``libvtk*PythonD.so*`` files should be installed + somewhere in the linkers path (for example in `\usr\lib`). + Under Windows these should be installed in a directory that is + in the `PATH`. The Python extension modules should be + installed via the `setup.py` file inside the `vtk` package. + Typically these should be installed to + `/usr/lib/pythonX.Y/site-packages/vtk` (or + `PythonX.Y\Lib\site-packages\vtk`). + +The VTK install rule (`make install` under Unix) will usually do the +right thing in installing everything. Make sure that the +`CMAKE_INSTALL_PREFIX` variable is set appropriately. There are two +ways to customize python module installation. First, one may modify +the VTK_PYTHON_SETUP_ARGS CMake cache variable to set the options +passed to the setup.py script. The default value for this variable +provides reasonable behavior for packagers. Second, one may +define VTK_INSTALL_NO_PYTHON:BOOL=ON in the CMake cache which will +disable the automatic execution of setup.py as part of the install +process. Then one may run ``python setup.py install`` manually +with the desired options. + + +Common problems +^^^^^^^^^^^^^^^ + +Some common problems are described in the VTK FAQ available here: + + http://public.kitware.com/cgi-bin/vtkfaq?req=home + +The following lists a few serious problems and their solution from +the above FAQ. + +Q. Why do I get the Python error -- ValueError: method requires a +VTK object? + +A. You just built VTK with Python support and everything went +smoothly. After you install everything and try running a Python-VTK +script you get a traceback with this error: + + ValueError: method requires a VTK object. + +This error occurs if you have two copies of the VTK libraries on +your system. These copies need not be in your linkers path. VTK +from CVS defaults to building libraries with an rpath flag (under +Unix). This is necessary to be able to test the build in place. +When you install VTK into another directory in your linkers path and +then run a Python script, the Python modules remember the old path +and load the libraries in the build directory as well. This triggers +the above error since the object you passed the method was +instantiated from the other copy. + +So how do you fix it? The easiest solution is to simply delete the +copy of the libraries inside your build directory or move the build +directory to another place. For example, if you build the libraries +in `VTK/bin` then move `VTK/bin` to `VTK/bin1` or remove all the +`VTK/bin/*.so` files. The error should no longer occur. + +Another way to fix the error is to turn the `VTK_USE_RPATH` boolean +to `OFF` in your `CMakeCache.txt` file and then rebuild VTK. You +shouldn't have to rebuild all of VTK, just delete the libraries +(`*.so` files) and then re-run cmake and make. + +Alternatively, starting with recent VTK CVS versions (post Dec. 6, +2002) and with VTK versions greater than 4.1 (i.e. 4.2 and beyond) +there is a special VTK-Python interpreter built as part of VTK +called 'vtkpython' that should eliminate this problem. Simply use +'vtkpython' in place of the usual 'python' interpreter when you use +VTK-Python scripts and the problem should not occur. This is +because vtkpython uses the libraries inside the build directory. + + + +Reporting Bugs +^^^^^^^^^^^^^^ + +If you have trouble or spot bugs please let us know at +vtk-developers@vtk.org + diff --git a/Wrapping/Python/README_WRAP.txt b/Wrapping/Python/README_WRAP.txt new file mode 100644 index 0000000..0651a53 --- /dev/null +++ b/Wrapping/Python/README_WRAP.txt @@ -0,0 +1,263 @@ +Notes on the Python Wrappers for VTK + +Latest Revision: Dec 19, 2002 +Refers to VTK version 4.2 + +Abstract: +========= + +This document provides a detailed description of how VTK objects are +accessed and modified through Python. The installation of VTK-Python +is covered in README.txt. + + +Overview: +========= + +Nearly all the power of VTK objects are available through Python +(with a few exceptions as noted below). The C++ symantics are +translated as directly as possible to Python symantics. + + +The Basics: +=========== + +For the most part, using VTK from Python is very similar to using VTK +from C++ except for changes in syntax, e.g. + vtkObject *o = vtkObject::New() +becomes + o = vtkObject() + +and + o->Method() +becomes + o.Method() + +Some other important differences are that you can pass a Python tuple, +list or array to a method that requires a C++ array e.g.: + +>>> a = vtkActor() +>>> p = (100.0, 200.0, 100.0) +>>> a.SetPosition(p) + +or if the C++ array is used to return information, you must pass a +Python list or array that has the correct number of slots: + +>>> z = [0.0, 0.0, 0.0] +>>> vtkMath.Cross((1,0,0),(0,1,0),z) +>>> print z +[0.0, 0.0, 1.0] + +If the C++ method returns a pointer to an array, then that method is +only wrapped if there is a hint that gives the size of the array. +This hint is either given in the 'hints' file e.g. VTK/Wrapping/hints +or by the number specified in the macro used to declare the method in +the C++ header file e.g. vtkGetVectorMacro(Position,float,3): + +>>> a = vtkActor() +>>> print a.GetPosition() +(0.0, 0.0, 0.0) + +Finally, the python 'None' is treated the same as C++ NULL: + +>>> a = vtkActor() +>>> a.SetMapper(None) +>>> print a.GetMapper() +None + +And perhaps one of the most pleasant features of Python is that all +type-checking is performed at run time, so the type casts that are +often necessary in VTK-C++ are never needed in VTK-Python. + +Finally, a C++ method that requires a void * can be passed a Python +string. No check is done to ensure that the string is the correct +size, and the string's reference count is not incremented. Extreme +caution should be applied when using this feature. + + +Unavailable methods +------------------- + +A method is not wrapped if +1) its parameter list contains a pointer/reference that is not a + pointer/reference to a vtkObject +2) its parameter list contains a multidimensional array +3) it returns a pointer/reference that is not a pointer/reference + to a vtkObject and there is no entry in hints file +4) it is an operator method (there should not be any of these in VTK) + + +Unavailable classes +------------------- + +Some classes are meant to be used only by other VTK classes and are +not wrapped. These are labelled as WRAP_EXCLUDE in the CMakeLists.txt +files. + + +Printing VTK objects +==================== + +Printing a vtk object will provide the same information as provided +by the vtkObject::Print() method (i.e. the values of all instance variables) +The same information is provided by calling str(obj). A more compact +representation of the object is available by calling repr(obj) + + repr(obj) -> '<vtkclass libVTKCommonPython.vtkObject at 100c8d48>' + +(under Windows (TM), 'libVTKCommonPython' is replaced by 'vtkpython'). + + +Built-in documentation +====================== + +All of the documentation that is available in the VTK header files and +in the html man pages is also available through python. + +If you want to see what methods are available for a class, use e.g. + +>>> dir(vtkActor) + +to get a list of all the methods defined in vtkActor.h or if you also +want a listing of all method defined for vtkActor and its superclasses + +>>> a = vtkActor() +>>> dir(a) + +will print a very long list of all the methods for object 'a'. + + +Using the 'pydoc' module (part of the standard python library) you +can also retrieve documentation about VTK classes and methods: + +>>> import pydoc +>>> pydoc.doc(vtkActor) +[ lots of info printed, try it yourself] + +For the method documentation, all the different 'signatures' for the +method are given in both Python and in the original C++ format before +the documentation itself is given. + +>>> pydoc.doc(vtkActor.SetPosition) +Python Library Documentation: built-in function SetPosition + +SetPosition(...) + V.SetPosition(float, float, float) + C++: virtual void SetPosition (float _arg1, float _arg2, float _arg3); + V.SetPosition((float, float, float)) + C++: virtual void SetPosition (float _arg[3]); + + Set/Get/Add the position of the Prop3D in world coordinates. + + +Peculiarities and special features +================================== + +Deleting a vtkObject: +--------------------- + +There is no direct equivalent of o->Delete() since Python provides a +mechanism for automatic garbage collection. The object will be +deleted once there are no remaining references to it either from +inside Python or from other VTK objects. It is possible to get rid of +the local reference to the object by using the python 'del' command, +i.e. "del o", and this will results in a call to o->Delete() if the +local reference to the object was the last remaining reference to the +object from within Python. + + +Class methods +------------- + +In C++, if you want to call a method from a superclass you can do the +following: + +vtkActor *a = vtkActor::New(); +a->vtkProp3D::SetPosition(10,20,50); + +The equivalent in python is + +>>> a = vtkActor() +>>> vtkProp3D.SetPosition(a,10,20,50) + +The wrappers also provide an additional feature which isn't very +'pythonic' at all: support for static methods e.g. class methods +that don't require a 'self' (equivalent to the C++ 'this'): + +vtkMath::Norm(x); + +becomes + +>>> vtkMath.Norm(x) + +This sort of thing is not allowed by most Python classes! In fact, +the wrapped VTK classes aren't real Python classes at all, they just +behave similarly. + + +Subclassing a VTK class +----------------------- + +It is possible to subclass a VTK class from within Python, but it +is NOT possible to override the virtual methods of the class. +The python-level code will be invisible to the VTK C++ code, +the methods that you define will only be visible when you access +the class from Python. + +It is therefore not reasonable, for instance, to subclass the +vtkInteractorStyle to provide custom python interaction. Instead, +you have to do this by adding Observers to the vtkInteractor object. + + +Transmitting data from Python to VTK +------------------------------------ + +If you have a large block of data in Python (for example a Numeric +array) that you want to access from VTK, then you can do so using +the vtkDataArray.SetVoidArray() method. + + +Creating a Python object from just the address of a VTK object +-------------------------------------------------------------- + +When you instantiate a class, you can provide a hexidecimal string +containing the address of an existing vtk object, e.g. + t = vtkTransform('_1010e068_vtkTransform_p') +The string follows SWIG mangling conventions. If a wrapper for the +specified object already exists, then that wrapper will be used rather +than a new wrapper being created. If you want to use this feature +of vtkpython, please think twice. + + +Special attributes available from VTK-Python +============================================ + +Special vtkobject attributes: +----------------------------- + + o.__class__ the vtkclass that this object is an instance of + o.__doc__ a description of the class (obtained from C++ header file) + o.__methods__ list of all methods of this object + o.__members__ list of all attributes of this object + o.__this__ a string containing the address of the VTK object + + +Special method attributes: +-------------------------- + + m.__doc__ a description of the method (obtained from C++ header file) + + +Special vtkclass attributes: +---------------------------- + + c.__bases__ a tuple of base classes for this class (empty for vtkObject) + c.__doc__ a description of the class (obtained from C++ header file) + c.__methods__ methods of this class (not including inherited methods) + c.__members__ list of all attributes of this class + c.__name__ the name of the class, same as returned by GetClassName() + + + +END OF FILE + diff --git a/Wrapping/Python/compile_all_vtk.py.in b/Wrapping/Python/compile_all_vtk.py.in new file mode 100644 index 0000000..d86b2d9 --- /dev/null +++ b/Wrapping/Python/compile_all_vtk.py.in @@ -0,0 +1,4 @@ +import compileall +compileall.compile_dir('@VTK_BINARY_DIR@/Wrapping/Python') +file = open('@VTK_BINARY_DIR@/Wrapping/Python/vtk_compile_complete', 'w') +file.write('Done') diff --git a/Wrapping/Python/conversionlist.in b/Wrapping/Python/conversionlist.in new file mode 100644 index 0000000..7223153 --- /dev/null +++ b/Wrapping/Python/conversionlist.in @@ -0,0 +1 @@ +@CONVERSIONLIST@ diff --git a/Wrapping/Python/setup.py.in b/Wrapping/Python/setup.py.in new file mode 100644 index 0000000..dc44c28 --- /dev/null +++ b/Wrapping/Python/setup.py.in @@ -0,0 +1,156 @@ +#!/usr/bin/env python + +""" +setup.py for installing the VTK-Python bindings using distutils. + +Created by Prabhu Ramachandran, June 2002. + +Updated for install with configuration types by Brad King, August 2005. + +""" + +import sys +import string +import os +import os.path +from types import StringType +from distutils.core import setup +from distutils.command.install_data import install_data +from distutils.sysconfig import get_config_var + +# Support for Python Eggs: +# http://peak.telecommunity.com/DevCenter/PythonEggs +# http://peak.telecommunity.com/DevCenter/EasyInstall +has_setup_tools = 0 +# Uncomment the following two lines if you need to build an Egg. +# This is commented out by default since the install rule seems +# broken for setuptools-0.5a13. +#from setuptools import setup +#has_setup_tools = 1 + +# VTK build configuration settings. +vtk_version = "@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@.@VTK_BUILD_VERSION@" +vtk_lib_dir = "@LIBRARY_OUTPUT_PATH@" +vtk_bin_dir = "@EXECUTABLE_OUTPUT_PATH@" +vtk_use_rendering = @VTK_PYTHON_USE_RENDERING@ +vtk_use_parallel = @VTK_PYTHON_USE_PARALLEL@ +vtk_use_mpi = @VTK_PYTHON_USE_MPI@ +vtk_has_configuration_types = @VTK_PYTHON_HAS_CONFIG_TYPES@ + +# The build type ('Release', 'Debug' etc.). If vtk_has_configuration_types +# is true this must be set. It may be set on the command line by something +# like 'BUILD_TYPE=Release'. For example:: +# python setup.py install --prefix=D:\\Python23 BUILD_TYPE=Release +vtk_build_type = @VTK_PYTHON_BUILD_TYPE@ + +# Construct the list of kit names to be installed. +vtk_kit_names = ['Common', 'Filtering', 'IO', 'Graphics', + 'GenericFiltering', 'Imaging'] +if vtk_use_rendering: + vtk_kit_names.extend(['Rendering', 'VolumeRendering', 'Hybrid', 'Widgets']) +if vtk_use_parallel: + vtk_kit_names.extend(['Parallel']) + +# Construct the list of executable names to be installed. +vtk_exe_names = ['vtkpython'] +if vtk_use_parallel and vtk_use_mpi: + vtk_exe_names.extend(['pvtkpython']) + +def get_libs(): + """Returns a list of libraries to be installed. """ + libs = [] + + # Select platform-specific components of the module file names. + if os.name == 'posix': + dir = vtk_lib_dir + prefix = 'libvtk' + suffix = 'Python' + get_config_var('SO') + else: + dir = vtk_bin_dir.replace('/', '\\') + prefix = 'vtk' + suffix = 'Python.dll' + + # If this build has configuration types append the selected configuration. + if vtk_has_configuration_types: + dir = os.path.join(dir, vtk_build_type) + + # Enumerate ths list of module files. + for kit in vtk_kit_names: + libs.append(os.path.abspath(os.path.join(dir, prefix+kit+suffix))) + + return libs + + +def get_scripts(): + """Returns the appropriate vtkpython executable and pvtkpython + that is to be installed.""" + scripts = [] + + # Select platform-specific components of the executable file names. + if os.name == 'posix': + dir = vtk_lib_dir + suffix = '' + else: + dir = vtk_bin_dir.replace('/', '\\') + suffix = '.exe' + + # If this build has configuration types append the selected configuration. + if vtk_has_configuration_types: + dir = os.path.join(dir, vtk_build_type) + + # Enumerate ths list of executable files. + for exe in vtk_exe_names: + scripts.append(os.path.abspath(os.path.join(dir, exe+suffix))) + + return scripts + + +class my_install_data (install_data): + def finalize_options (self): + """Needed to make this thing work properly.""" + self.set_undefined_options ('install', + ('install_lib', 'install_dir'), + ('root', 'root'), + ('force', 'force'), + ) + +if __name__ == '__main__': + # Get the optional build type argument. + for x in sys.argv[:]: + if string.find(x, 'BUILD_TYPE') > -1: + vtk_build_type = string.strip(string.split(x, '=')[1]) + sys.argv.remove(x) + break + + # Make sure a build type was specified if it is required. + if vtk_has_configuration_types: + if not vtk_build_type: + raise "ERROR: Must specify BUILD_TYPE=<config-name> on command line." + + def mk_dict(**kw): + # Unnecessary in recent Pythons but handy for earlier + # versions. + return kw + + # The options for setup. + opts = mk_dict(name = "VTK", + version = vtk_version, + description = "The Visualization Toolkit", + maintainer = "VTK Developers", + maintainer_email = "vtk-developers@vtk.org", + license = "BSD", + long_description = "A high level visualization library", + url = "http://www.vtk.org/", + platforms = ['Any'], + cmdclass = {'install_data': my_install_data}, + packages = ['vtk', 'vtk.gtk', 'vtk.qt', 'vtk.tk', + 'vtk.util', 'vtk.wx', 'vtk.test'], + #scripts = get_scripts(), + data_files = [('vtk', get_libs())] + ) + # If setup_tools is available, then add an extra option to disable + # creation of a ZIP file. + if has_setup_tools: + opts['zip_safe'] = 0 + + setup(**opts) diff --git a/Wrapping/Python/vtk/.cvsignore b/Wrapping/Python/vtk/.cvsignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/Wrapping/Python/vtk/.cvsignore @@ -0,0 +1 @@ +*.pyc diff --git a/Wrapping/Python/vtk/__helper.py b/Wrapping/Python/vtk/__helper.py new file mode 100644 index 0000000..ce61947 --- /dev/null +++ b/Wrapping/Python/vtk/__helper.py @@ -0,0 +1,33 @@ +""" This provides some useful code used by other modules. This is not to be +used by the end user which is why it is hidden. """ + +import string, sys +class LinkError(Exception): + pass + +def refine_import_err(mod_name, extension_name, exc): + """ Checks to see if the ImportError was because the library + itself was not there or because there was a link error. If there + was a link error it raises a LinkError if not it does nothing. + + Keyword arguments + ----------------- + + - mod_name : The name of the Python module that was imported. + + - extension_name : The name of the extension module that is to be + imported by the module having mod_name. + + - exc : The exception raised when the module called mod_name was + imported. + + To see example usage look at __init__.py. + + """ + try: + del sys.modules['vtk.%s'%mod_name] + except KeyError: + pass + if string.find(str(exc), extension_name) == -1: + raise LinkError, str(exc) + diff --git a/Wrapping/Python/vtk/__init__.py b/Wrapping/Python/vtk/__init__.py new file mode 100644 index 0000000..04f7f8d --- /dev/null +++ b/Wrapping/Python/vtk/__init__.py @@ -0,0 +1,87 @@ +""" This module loads the entire VTK library into its namespace. It +also allows one to use specific packages inside the vtk directory..""" + +import os +import sys + +# AIX apparently does not have dl? +try: + import dl +except ImportError: + dl = None +except SystemError: + dl = None + +import __helper + +# set the dlopen flags so that VTK does not run into problems with +# shared symbols. +try: + # only Python >= 2.2 has this functionality + orig_dlopen_flags = sys.getdlopenflags() +except AttributeError: + orig_dlopen_flags = None + +if dl and (os.name == 'posix'): + sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL) + +# Load all required kits. +from common import * +from filtering import * +from io import * +from imaging import * +from graphics import * + +# the vtk.kits variable tells us which kits we actually have +kits = ['common', 'filtering', 'io', 'imaging', 'graphics'] + +# Try to load optional kits. The helper function checks if the +# ImportError is actually a link error. + +try: + from genericfiltering import * + kits.append('genericfiltering') +except ImportError, exc: + __helper.refine_import_err('genericfiltering', 'vtkGenericFilteringPython', + exc) +try: + from rendering import * + kits.append('rendering') +except ImportError, exc: + __helper.refine_import_err('rendering', 'vtkRenderingPython', exc) + +try: + from volumerendering import * + kits.append('volumerendering') +except ImportError, exc: + __helper.refine_import_err('volumerendering', + 'vtkVolumeRenderingPython', exc) + +try: + from hybrid import * + kits.append('hybrid') +except ImportError, exc: + __helper.refine_import_err('hybrid', 'vtkHybridPython', exc) + +try: + from widgets import * + kits.append('widgets') +except ImportError, exc: + __helper.refine_import_err('widgets', 'vtkWidgetsPython', exc) + +try: + from parallel import * + kits.append('parallel') +except ImportError, exc: + __helper.refine_import_err('parallel', 'vtkParallelPython', exc) + +# import useful VTK related constants. +from util.vtkConstants import * + +# reset the dlopen flags to the original state if possible. +if dl and (os.name == 'posix') and orig_dlopen_flags: + sys.setdlopenflags(orig_dlopen_flags) + +# removing things the user shouldn't have to see. +del __helper, orig_dlopen_flags +del sys, dl, os diff --git a/Wrapping/Python/vtk/common.py b/Wrapping/Python/vtk/common.py new file mode 100644 index 0000000..c4fd433 --- /dev/null +++ b/Wrapping/Python/vtk/common.py @@ -0,0 +1,10 @@ +""" This module loads all the classes from the VTK Common library into its +namespace. This is a required module.""" + +import os + +if os.name == 'posix': + from libvtkCommonPython import * +else: + from vtkCommonPython import * + diff --git a/Wrapping/Python/vtk/filtering.py b/Wrapping/Python/vtk/filtering.py new file mode 100644 index 0000000..2403e88 --- /dev/null +++ b/Wrapping/Python/vtk/filtering.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK Filtering library into +its namespace. This is a required module.""" + +import os + +if os.name == 'posix': + from libvtkFilteringPython import * +else: + from vtkFilteringPython import * diff --git a/Wrapping/Python/vtk/genericfiltering.py b/Wrapping/Python/vtk/genericfiltering.py new file mode 100644 index 0000000..8fe1a51 --- /dev/null +++ b/Wrapping/Python/vtk/genericfiltering.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK GenericFiltering +library into its namespace. This is an optional module.""" + +import os + +if os.name == 'posix': + from libvtkGenericFilteringPython import * +else: + from vtkGenericFilteringPython import * diff --git a/Wrapping/Python/vtk/graphics.py b/Wrapping/Python/vtk/graphics.py new file mode 100644 index 0000000..497cd02 --- /dev/null +++ b/Wrapping/Python/vtk/graphics.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK Graphics library into its +namespace. This is a required module.""" + +import os + +if os.name == 'posix': + from libvtkGraphicsPython import * +else: + from vtkGraphicsPython import * diff --git a/Wrapping/Python/vtk/gtk/GtkGLExtVTKRenderWindow.py b/Wrapping/Python/vtk/gtk/GtkGLExtVTKRenderWindow.py new file mode 100644 index 0000000..ae2545b --- /dev/null +++ b/Wrapping/Python/vtk/gtk/GtkGLExtVTKRenderWindow.py @@ -0,0 +1,539 @@ +""" +Description: + + This provides a VTK widget for pyGtk. This embeds a vtkRenderWindow + inside a GTK widget. This is based on GtkVTKRenderWindow.py. + + The extensions here allow the use of gtkglext rather than gtkgl and + pygtk-2 rather than pygtk-0. It requires pygtk-2.0.0 or later. + + There is a working example at the bottom. + +Credits: + + John Hunter <jdhunter@ace.bsd.uchicago.edu> developed and tested + this code based on VTK's GtkVTKRenderWindow.py and extended it to + work with pygtk-2.0.0. + +License: + + VTK license. + +""" + +import math, sys +import pygtk +pygtk.require('2.0') +import gtk +import gtk.gtkgl +from gtk import gdk +import vtk + + +class GtkGLExtVTKRenderWindowBase(gtk.gtkgl.DrawingArea): + + """ A base class that enables one to embed a vtkRenderWindow into + a pyGTK widget. This class embeds the RenderWindow correctly. + Provided are some empty methods that can be overloaded to provide + a user defined interaction behaviour. The event handling + functions have names that are somewhat similar to the ones in the + vtkInteractorStyle class included with VTK. """ + + def __init__(self, *args): + gtk.gtkgl.DrawingArea.__init__(self) + self.set_double_buffered(gtk.FALSE) + + self._RenderWindow = vtk.vtkRenderWindow() + # private attributes + self.__Created = 0 + + # used by the LOD actors + self._DesiredUpdateRate = 15 + self._StillUpdateRate = 0.0001 + + self.ConnectSignals() + + # need this to be able to handle key_press events. + self.set_flags(gtk.CAN_FOCUS) + # default size + self.set_size_request(300, 300) + + def ConnectSignals(self): + self.connect("realize", self.OnRealize) + self.connect("expose_event", self.OnExpose) + self.connect("configure_event", self.OnConfigure) + self.connect("button_press_event", self.OnButtonDown) + self.connect("button_release_event", self.OnButtonUp) + self.connect("motion_notify_event", self.OnMouseMove) + self.connect("enter_notify_event", self.OnEnter) + self.connect("leave_notify_event", self.OnLeave) + self.connect("key_press_event", self.OnKeyPress) + self.connect("delete_event", self.OnDestroy) + self.add_events(gdk.EXPOSURE_MASK| + gdk.BUTTON_PRESS_MASK | + gdk.BUTTON_RELEASE_MASK | + gdk.KEY_PRESS_MASK | + gdk.POINTER_MOTION_MASK | + gdk.POINTER_MOTION_HINT_MASK | + gdk.ENTER_NOTIFY_MASK | + gdk.LEAVE_NOTIFY_MASK) + + def GetRenderWindow(self): + return self._RenderWindow + + def GetRenderer(self): + self._RenderWindow.GetRenderers().InitTraversal() + return self._RenderWindow.GetRenderers().GetNextItem() + + def SetDesiredUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._DesiredUpdateRate = rate + + def GetDesiredUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._DesiredUpdateRate + + def SetStillUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._StillUpdateRate = rate + + def GetStillUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._StillUpdateRate + + def Render(self): + if self.__Created: + self._RenderWindow.Render() + + def OnRealize(self, *args): + if self.__Created == 0: + # you can't get the xid without the window being realized. + self.realize() + if sys.platform=='win32': + win_id = str(self.widget.window.handle) + else: + win_id = str(self.widget.window.xid) + self._RenderWindow.SetWindowInfo(win_id) + self.__Created = 1 + return gtk.TRUE + + def Created(self): + return self.__Created + + def OnConfigure(self, widget, event): + self.widget=widget + self._RenderWindow.SetSize(event.width, event.height) + self.Render() + return gtk.TRUE + + def OnExpose(self, *args): + self.Render() + return gtk.TRUE + + def OnDestroy(self, *args): + self.hide() + del self._RenderWindow + self.destroy() + return gtk.TRUE + + def OnButtonDown(self, wid, event): + """Mouse button pressed.""" + self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate) + return gtk.TRUE + + def OnButtonUp(self, wid, event): + """Mouse button released.""" + self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate) + return gtk.TRUE + + def OnMouseMove(self, wid, event): + """Mouse has moved.""" + return gtk.TRUE + + def OnEnter(self, wid, event): + """Entering the vtkRenderWindow.""" + return gtk.TRUE + + def OnLeave(self, wid, event): + """Leaving the vtkRenderWindow.""" + return gtk.TRUE + + def OnKeyPress(self, wid, event): + """Key pressed.""" + return gtk.TRUE + + def OnKeyRelease(self, wid, event): + "Key released." + return gtk.TRUE + + +class GtkGLExtVTKRenderWindow(GtkGLExtVTKRenderWindowBase): + + """ An example of a fully functional GtkGLExtVTKRenderWindow that + is based on the vtkRenderWidget.py provided with the VTK + sources.""" + + def __init__(self, *args): + GtkGLExtVTKRenderWindowBase.__init__(self) + + self._CurrentRenderer = None + self._CurrentCamera = None + self._CurrentZoom = 1.0 + self._CurrentLight = None + + self._ViewportCenterX = 0 + self._ViewportCenterY = 0 + + self._Picker = vtk.vtkCellPicker() + self._PickedAssembly = None + self._PickedProperty = vtk.vtkProperty() + self._PickedProperty.SetColor(1, 0, 0) + self._PrePickedProperty = None + + self._OldFocus = None + + # these record the previous mouse position + self._LastX = 0 + self._LastY = 0 + + def OnButtonDown(self, wid, event): + self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate) + return self.StartMotion(wid, event) + return gtk.TRUE + + def OnButtonUp(self, wid, event): + self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate) + return self.EndMotion(wid, event) + return gtk.TRUE + + def OnMouseMove(self, wid, event=None): + if ((event.state & gdk.BUTTON1_MASK) == gdk.BUTTON1_MASK): + if ((event.state & gdk.SHIFT_MASK) == gdk.SHIFT_MASK): + m = self.get_pointer() + self.Pan(m[0], m[1]) + else: + m = self.get_pointer() + self.Rotate(m[0], m[1]) + elif ((event.state & gdk.BUTTON2_MASK) == gdk.BUTTON2_MASK): + m = self.get_pointer() + self.Pan(m[0], m[1]) + elif ((event.state & gdk.BUTTON3_MASK) == gdk.BUTTON3_MASK): + m = self.get_pointer() + self.Zoom(m[0], m[1]) + else: + return gtk.FALSE + + return gtk.TRUE + + def OnEnter(self, wid, event=None): + # a render hack because grab_focus blanks the renderwin + self.grab_focus() + w = self.get_pointer() + self.UpdateRenderer(w[0], w[1]) + return gtk.TRUE + + def OnKeyPress(self, wid, event=None): + #if (event.keyval == gdk.keyval_from_name("q") or + # event.keyval == gdk.keyval_from_name("Q")): + # gtk.mainquit() + + if (event.keyval == gdk.keyval_from_name('r') or + event.keyval == gdk.keyval_from_name('R')): + self.Reset() + return gtk.TRUE + elif (event.keyval == gdk.keyval_from_name('w') or + event.keyval == gdk.keyval_from_name('W')): + self.Wireframe() + return gtk.TRUE + elif (event.keyval == gdk.keyval_from_name('s') or + event.keyval == gdk.keyval_from_name('S')): + self.Surface() + return gtk.TRUE + elif (event.keyval == gdk.keyval_from_name('p') or + event.keyval == gdk.keyval_from_name('P')): + m = self.get_pointer() + self.PickActor(m[0], m[1]) + return gtk.TRUE + else: + return gtk.FALSE + + def GetZoomFactor(self): + return self._CurrentZoom + + def SetZoomFactor(self, zf): + self._CurrentZoom = zf + + def GetPicker(self): + return self._Picker + + def Render(self): + if (self._CurrentLight): + light = self._CurrentLight + light.SetPosition(self._CurrentCamera.GetPosition()) + light.SetFocalPoint(self._CurrentCamera.GetFocalPoint()) + + GtkGLExtVTKRenderWindowBase.Render(self) + + + def UpdateRenderer(self,x,y): + """ + UpdateRenderer will identify the renderer under the mouse and set + up _CurrentRenderer, _CurrentCamera, and _CurrentLight. + """ + windowX,windowY = self.widget.window.get_size() + + renderers = self._RenderWindow.GetRenderers() + numRenderers = renderers.GetNumberOfItems() + + self._CurrentRenderer = None + renderers.InitTraversal() + for i in range(0,numRenderers): + renderer = renderers.GetNextItem() + vx,vy = (0,0) + if (windowX > 1): + vx = float(x)/(windowX-1) + if (windowY > 1): + vy = (windowY-float(y)-1)/(windowY-1) + (vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport() + + if (vx >= vpxmin and vx <= vpxmax and + vy >= vpymin and vy <= vpymax): + self._CurrentRenderer = renderer + self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\ + +vpxmin + self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\ + +vpymin + self._CurrentCamera = self._CurrentRenderer.GetActiveCamera() + lights = self._CurrentRenderer.GetLights() + lights.InitTraversal() + self._CurrentLight = lights.GetNextItem() + break + + self._LastX = x + self._LastY = y + + def GetCurrentRenderer(self): + if self._CurrentRenderer is None: + renderers = self._RenderWindow.GetRenderers() + numRenderers = renderers.GetNumberOfItems() + + renderers.InitTraversal() + for i in range(0,numRenderers): + renderer = renderers.GetNextItem() + break + self._CurrentRenderer = renderer + return self._CurrentRenderer + + def GetCurrentCamera(self): + if self._CurrentCamera is None: + renderer = self.GetCurrentRenderer() + self._CurrentCamera = renderer.GetActiveCamera() + return self._CurrentCamera + + def StartMotion(self, wid, event=None): + x = event.x + y = event.y + self.UpdateRenderer(x,y) + return gtk.TRUE + + def EndMotion(self, wid, event=None): + if self._CurrentRenderer: + self.Render() + return gtk.TRUE + + def Rotate(self,x,y): + if self._CurrentRenderer: + + self._CurrentCamera.Azimuth(self._LastX - x) + self._CurrentCamera.Elevation(y - self._LastY) + self._CurrentCamera.OrthogonalizeViewUp() + + self._LastX = x + self._LastY = y + + self._CurrentRenderer.ResetCameraClippingRange() + self.Render() + + def Pan(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + (pPoint0,pPoint1,pPoint2) = camera.GetPosition() + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + + if (camera.GetParallelProjection()): + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetFocalPoint(fx,fy,fz) + + renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetPosition(fx,fy,fz) + + else: + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + # Specify a point location in world coordinates + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + # Convert world point coordinates to display coordinates + dPoint = renderer.GetDisplayPoint() + focalDepth = dPoint[2] + + aPoint0 = self._ViewportCenterX + (x - self._LastX) + aPoint1 = self._ViewportCenterY - (y - self._LastY) + + renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth) + renderer.DisplayToWorld() + + (rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint() + if (rPoint3 != 0.0): + rPoint0 = rPoint0/rPoint3 + rPoint1 = rPoint1/rPoint3 + rPoint2 = rPoint2/rPoint3 + + camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0, + (fPoint1 - rPoint1) + fPoint1, + (fPoint2 - rPoint2) + fPoint2) + + camera.SetPosition((fPoint0 - rPoint0) + pPoint0, + (fPoint1 - rPoint1) + pPoint1, + (fPoint2 - rPoint2) + pPoint2) + + self._LastX = x + self._LastY = y + + self.Render() + + def Zoom(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + + zoomFactor = math.pow(1.02,(0.5*(self._LastY - y))) + self._CurrentZoom = self._CurrentZoom * zoomFactor + + if camera.GetParallelProjection(): + parallelScale = camera.GetParallelScale()/zoomFactor + camera.SetParallelScale(parallelScale) + else: + camera.Dolly(zoomFactor) + renderer.ResetCameraClippingRange() + + self._LastX = x + self._LastY = y + + self.Render() + + def Reset(self): + if self._CurrentRenderer: + self._CurrentRenderer.ResetCamera() + + self.Render() + + def Wireframe(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToWireframe() + + self.Render() + + def Surface(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToSurface() + + self.Render() + + def PickActor(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + picker = self._Picker + + windowX,windowY = self.widget.window.get_size() + picker.Pick(x,(windowY - y - 1),0.0,renderer) + assembly = picker.GetAssembly() + + if (self._PickedAssembly != None and + self._PrePickedProperty != None): + self._PickedAssembly.SetProperty(self._PrePickedProperty) + # release hold of the property + self._PrePickedProperty.UnRegister(self._PrePickedProperty) + self._PrePickedProperty = None + + if (assembly != None): + self._PickedAssembly = assembly + self._PrePickedProperty = self._PickedAssembly.GetProperty() + # hold onto the property + self._PrePickedProperty.Register(self._PrePickedProperty) + self._PickedAssembly.SetProperty(self._PickedProperty) + + self.Render() + + +def main(): + # The main window + window = gtk.Window() + window.set_title("A GtkGLExtVTKRenderWindow Demo!") + window.connect("destroy", gtk.mainquit) + window.connect("delete_event", gtk.mainquit) + window.set_border_width(10) + + vtkgtk = GtkGLExtVTKRenderWindow() + vtkgtk.show() + + vbox = gtk.VBox(spacing=3) + vbox.show() + vbox.pack_start(vtkgtk) + + button = gtk.Button('My Button') + button.show() + vbox.pack_start(button) + window.add(vbox) + + window.set_size_request(400, 400) + + # The VTK stuff. + cone = vtk.vtkConeSource() + cone.SetResolution(80) + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + #coneActor = vtk.vtkLODActor() + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + coneActor.GetProperty().SetColor(0.5, 0.5, 1.0) + ren = vtk.vtkRenderer() + vtkgtk.GetRenderWindow().AddRenderer(ren) + ren.AddActor(coneActor) + + # show the main window and start event processing. + window.show() + gtk.mainloop() + + +if __name__ == "__main__": + main() diff --git a/Wrapping/Python/vtk/gtk/GtkGLExtVTKRenderWindowInteractor.py b/Wrapping/Python/vtk/gtk/GtkGLExtVTKRenderWindowInteractor.py new file mode 100644 index 0000000..1302b09 --- /dev/null +++ b/Wrapping/Python/vtk/gtk/GtkGLExtVTKRenderWindowInteractor.py @@ -0,0 +1,304 @@ +""" +Description: + + Provides a pyGtk vtkRenderWindowInteractor widget. This embeds a + vtkRenderWindow inside a GTK widget and uses the + vtkGenericRenderWindowInteractor for the event handling. This is + similar to GtkVTKRenderWindowInteractor.py. + + The extensions here allow the use of gtkglext rather than gtkgl and + pygtk-2 rather than pygtk-0. It requires pygtk-2.0.0 or later. + + There is a working example at the bottom. + +Credits: + + John Hunter <jdhunter@ace.bsd.uchicago.edu> developed and tested + this code based on VTK's GtkVTKRenderWindow.py and extended it to + work with pygtk-2.0.0. + +License: + + VTK license. + +""" + +import sys +import pygtk +pygtk.require('2.0') +import gtk +from gtk import gdk +import gtk.gtkgl +import vtk + +class GtkGLExtVTKRenderWindowInteractor(gtk.gtkgl.DrawingArea): + + """ Embeds a vtkRenderWindow into a pyGTK widget and uses + vtkGenericRenderWindowInteractor for the event handling. This + class embeds the RenderWindow correctly. A __getattr__ hook is + provided that makes the class behave like a + vtkGenericRenderWindowInteractor.""" + + def __init__(self, *args): + gtk.gtkgl.DrawingArea.__init__(self) + + self.set_double_buffered(gtk.FALSE) + + self._RenderWindow = vtk.vtkRenderWindow() + + # private attributes + self.__Created = 0 + self._ActiveButton = 0 + + self._Iren = vtk.vtkGenericRenderWindowInteractor() + self._Iren.SetRenderWindow(self._RenderWindow) + self._Iren.GetInteractorStyle().SetCurrentStyleToTrackballCamera() + self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer) + self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer) + self.ConnectSignals() + + # need this to be able to handle key_press events. + self.set_flags(gtk.CAN_FOCUS) + + def set_size_request(self, w, h): + gtk.gtkgl.DrawingArea.set_size_request(self, w, h) + self._RenderWindow.SetSize(w, h) + self._Iren.SetSize(w, h) + self._Iren.ConfigureEvent() + + def ConnectSignals(self): + self.connect("realize", self.OnRealize) + self.connect("expose_event", self.OnExpose) + self.connect("configure_event", self.OnConfigure) + self.connect("button_press_event", self.OnButtonDown) + self.connect("button_release_event", self.OnButtonUp) + self.connect("motion_notify_event", self.OnMouseMove) + self.connect("enter_notify_event", self.OnEnter) + self.connect("leave_notify_event", self.OnLeave) + self.connect("key_press_event", self.OnKeyPress) + self.connect("delete_event", self.OnDestroy) + self.add_events(gdk.EXPOSURE_MASK| gdk.BUTTON_PRESS_MASK | + gdk.BUTTON_RELEASE_MASK | + gdk.KEY_PRESS_MASK | + gdk.POINTER_MOTION_MASK | + gdk.POINTER_MOTION_HINT_MASK | + gdk.ENTER_NOTIFY_MASK | gdk.LEAVE_NOTIFY_MASK) + + def __getattr__(self, attr): + """Makes the object behave like a + vtkGenericRenderWindowInteractor""" + if attr == '__vtk__': + return lambda t=self._Iren: t + elif hasattr(self._Iren, attr): + return getattr(self._Iren, attr) + else: + raise AttributeError, self.__class__.__name__ + \ + " has no attribute named " + attr + + def CreateTimer(self, obj, event): + gtk.timeout_add(10, self._Iren.TimerEvent) + + def DestroyTimer(self, obj, event): + """The timer is a one shot timer so will expire automatically.""" + return 1 + + def GetRenderWindow(self): + return self._RenderWindow + + def Render(self): + if self.__Created: + self._RenderWindow.Render() + + def OnRealize(self, *args): + if self.__Created == 0: + # you can't get the xid without the window being realized. + self.realize() + if sys.platform=='win32': + win_id = str(self.widget.window.handle) + else: + win_id = str(self.widget.window.xid) + + self._RenderWindow.SetWindowInfo(win_id) + #self._Iren.Initialize() + self.__Created = 1 + return gtk.TRUE + + def OnConfigure(self, widget, event): + self.widget=widget + self._Iren.SetSize(event.width, event.height) + self._Iren.ConfigureEvent() + self.Render() + return gtk.TRUE + + def OnExpose(self, *args): + self.Render() + return gtk.TRUE + + def OnDestroy(self, event=None): + self.hide() + del self._RenderWindow + self.destroy() + return gtk.TRUE + + def _GetCtrlShift(self, event): + ctrl, shift = 0, 0 + if ((event.state & gdk.CONTROL_MASK) == gdk.CONTROL_MASK): + ctrl = 1 + if ((event.state & gdk.SHIFT_MASK) == gdk.SHIFT_MASK): + shift = 1 + return ctrl, shift + + def OnButtonDown(self, wid, event): + """Mouse button pressed.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + button = event.button + if button == 3: + self._Iren.RightButtonPressEvent() + return gtk.TRUE + elif button == 1: + self._Iren.LeftButtonPressEvent() + return gtk.TRUE + elif button == 2: + self._Iren.MiddleButtonPressEvent() + return gtk.TRUE + else: + return gtk.FALSE + + def OnButtonUp(self, wid, event): + """Mouse button released.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + button = event.button + if button == 3: + self._Iren.RightButtonReleaseEvent() + return gtk.TRUE + elif button == 1: + self._Iren.LeftButtonReleaseEvent() + return gtk.TRUE + elif button == 2: + self._Iren.MiddleButtonReleaseEvent() + return gtk.TRUE + + return gtk.FALSE + + def OnMouseMove(self, wid, event): + """Mouse has moved.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + self._Iren.MouseMoveEvent() + return gtk.TRUE + + def OnEnter(self, wid, event): + """Entering the vtkRenderWindow.""" + self.grab_focus() + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + self._Iren.EnterEvent() + return gtk.TRUE + + def OnLeave(self, wid, event): + """Leaving the vtkRenderWindow.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + self._Iren.LeaveEvent() + return gtk.TRUE + + def OnKeyPress(self, wid, event): + """Key pressed.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + keycode, keysym = event.keyval, event.string + key = chr(0) + if keycode < 256: + key = chr(keycode) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + key, 0, keysym) + self._Iren.KeyPressEvent() + self._Iren.CharEvent() + return gtk.TRUE + + def OnKeyRelease(self, wid, event): + "Key released." + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + keycode, keysym = event.keyval, event.string + key = chr(0) + if keycode < 256: + key = chr(keycode) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + key, 0, keysym) + self._Iren.KeyReleaseEvent() + return gtk.TRUE + + def Initialize(self): + if self.__Created: + self._Iren.Initialize() + + def SetPicker(self, picker): + self._Iren.SetPicker(picker) + + def GetPicker(self, picker): + return self._Iren.GetPicker() + + +def main(): + # The main window + window = gtk.Window(gtk.WINDOW_TOPLEVEL) + window.set_title("A GtkVTKRenderWindow Demo!") + window.connect("destroy", gtk.mainquit) + window.connect("delete_event", gtk.mainquit) + window.set_border_width(10) + + # A VBox into which widgets are packed. + vbox = gtk.VBox(spacing=3) + window.add(vbox) + vbox.show() + + # The GtkVTKRenderWindow + gvtk = GtkGLExtVTKRenderWindowInteractor() + #gvtk.SetDesiredUpdateRate(1000) + gvtk.set_size_request(400, 400) + vbox.pack_start(gvtk) + gvtk.show() + gvtk.Initialize() + gvtk.Start() + # prevents 'q' from exiting the app. + gvtk.AddObserver("ExitEvent", lambda o,e,x=None: x) + + # The VTK stuff. + cone = vtk.vtkConeSource() + cone.SetResolution(80) + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + #coneActor = vtk.vtkLODActor() + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + coneActor.GetProperty().SetColor(0.5, 0.5, 1.0) + ren = vtk.vtkRenderer() + gvtk.GetRenderWindow().AddRenderer(ren) + ren.AddActor(coneActor) + + # A simple quit button + quit = gtk.Button("Quit!") + quit.connect("clicked", gtk.mainquit) + vbox.pack_start(quit) + quit.show() + + # show the main window and start event processing. + window.show() + gtk.mainloop() + + +if __name__ == "__main__": + main() diff --git a/Wrapping/Python/vtk/gtk/GtkVTKRenderWindow.py b/Wrapping/Python/vtk/gtk/GtkVTKRenderWindow.py new file mode 100644 index 0000000..9d88e90 --- /dev/null +++ b/Wrapping/Python/vtk/gtk/GtkVTKRenderWindow.py @@ -0,0 +1,529 @@ +""" +Description: + + Provides a simple VTK widget for pyGtk. This embeds a + vtkRenderWindow inside a GTK widget. This is based on + vtkTkRenderWidget.py. The GtkVTKRenderWindowBase class provides the + abstraction necessary for someone to use their own interaction + behaviour. The method names are similar to those in + vtkInteractorStyle.h. + + The class uses the gtkgl.GtkGLArea widget (gtkglarea). This avoids + a lot of problems with flicker. + + There is a working example at the bottom. + +Credits: + + Thanks to Dave Reed for testing the code under various platforms and + for his suggestion to use the GtkGLArea widget to avoid flicker + related issues. + +Created by Prabhu Ramachandran, March 2001. + +Using GtkGLArea, March, 2002. + +Bugs: + + (*) There is a focus related problem. Tkinter has a focus object + that handles focus events. I dont know of an equivalent object + under GTK. So, when an 'enter_notify_event' is received on the + GtkVTKRenderWindow I grab the focus but I dont know what to do when + I get a 'leave_notify_event'. + + (*) Will not work under Win32 because it uses the XID of a window in + OnRealize. Suggestions to fix this will be appreciated. + +""" + +import gtk, GDK, gtkgl +import vtk +import math + + +class GtkVTKRenderWindowBase(gtkgl.GtkGLArea): + + """ A base class that enables one to embed a vtkRenderWindow into + a pyGTK widget. This class embeds the RenderWindow correctly. + Provided are some empty methods that can be overloaded to provide + a user defined interaction behaviour. The event handling + functions have names that are somewhat similar to the ones in the + vtkInteractorStyle class included with VTK. """ + + def __init__(self, *args): + l = list(args) + attr = (gtkgl.RGBA, gtkgl.DOUBLEBUFFER) + l.insert(0, self) + l.insert(1, attr) + apply(gtkgl.GtkGLArea.__init__, l) + self._RenderWindow = vtk.vtkRenderWindow() + + # private attributes + self.__Created = 0 + + # used by the LOD actors + self._DesiredUpdateRate = 15 + self._StillUpdateRate = 0.0001 + + self.ConnectSignals() + + # need this to be able to handle key_press events. + self.set_flags(gtk.CAN_FOCUS) + # default size + self.set_usize(300, 300) + + def ConnectSignals(self): + self.connect("realize", self.OnRealize) + self.connect("expose_event", self.OnExpose) + self.connect("configure_event", self.OnConfigure) + self.connect("button_press_event", self.OnButtonDown) + self.connect("button_release_event", self.OnButtonUp) + self.connect("motion_notify_event", self.OnMouseMove) + self.connect("enter_notify_event", self.OnEnter) + self.connect("leave_notify_event", self.OnLeave) + self.connect("key_press_event", self.OnKeyPress) + self.connect("delete_event", self.OnDestroy) + self.add_events(GDK.EXPOSURE_MASK| GDK.BUTTON_PRESS_MASK | + GDK.BUTTON_RELEASE_MASK | + GDK.KEY_PRESS_MASK | + GDK.POINTER_MOTION_MASK | + GDK.POINTER_MOTION_HINT_MASK | + GDK.ENTER_NOTIFY_MASK | GDK.LEAVE_NOTIFY_MASK) + + def GetRenderWindow(self): + return self._RenderWindow + + def GetRenderer(self): + self._RenderWindow.GetRenderers().InitTraversal() + return self._RenderWindow.GetRenderers().GetNextItem() + + def SetDesiredUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._DesiredUpdateRate = rate + + def GetDesiredUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._DesiredUpdateRate + + def SetStillUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._StillUpdateRate = rate + + def GetStillUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._StillUpdateRate + + def Render(self): + if self.__Created: + self._RenderWindow.Render() + + def OnRealize(self, *args): + if self.__Created == 0: + # you can't get the xid without the window being realized. + self.realize() + win_id = str(self.get_window().xid) + self._RenderWindow.SetWindowInfo(win_id) + self.__Created = 1 + return gtk.TRUE + + def OnConfigure(self, wid, event=None): + sz = self._RenderWindow.GetSize() + if (event.width != sz[0]) or (event.height != sz[1]): + self._RenderWindow.SetSize(event.width, event.height) + return gtk.TRUE + + def OnExpose(self, *args): + self.Render() + return gtk.TRUE + + def OnDestroy(self, event=None): + self.hide() + del self._RenderWindow + self.destroy() + return gtk.TRUE + + def OnButtonDown(self, wid, event): + """Mouse button pressed.""" + self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate) + return gtk.TRUE + + def OnButtonUp(self, wid, event): + """Mouse button released.""" + self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate) + return gtk.TRUE + + def OnMouseMove(self, wid, event): + """Mouse has moved.""" + return gtk.TRUE + + def OnEnter(self, wid, event): + """Entering the vtkRenderWindow.""" + return gtk.TRUE + + def OnLeave(self, wid, event): + """Leaving the vtkRenderWindow.""" + return gtk.TRUE + + def OnKeyPress(self, wid, event): + """Key pressed.""" + return gtk.TRUE + + def OnKeyRelease(self, wid, event): + "Key released." + return gtk.TRUE + + +class GtkVTKRenderWindow(GtkVTKRenderWindowBase): + + """ An example of a fully functional GtkVTKRenderWindow that is + based on the vtkRenderWidget.py provided with the VTK sources.""" + + def __init__(self, *args): + l = list(args) + l.insert(0, self) + apply(GtkVTKRenderWindowBase.__init__, l) + + self._CurrentRenderer = None + self._CurrentCamera = None + self._CurrentZoom = 1.0 + self._CurrentLight = None + + self._ViewportCenterX = 0 + self._ViewportCenterY = 0 + + self._Picker = vtk.vtkCellPicker() + self._PickedAssembly = None + self._PickedProperty = vtk.vtkProperty() + self._PickedProperty.SetColor(1, 0, 0) + self._PrePickedProperty = None + + self._OldFocus = None + + # these record the previous mouse position + self._LastX = 0 + self._LastY = 0 + + def OnButtonDown(self, wid, event): + self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate) + return self.StartMotion(wid, event) + + def OnButtonUp(self, wid, event): + self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate) + return self.EndMotion(wid, event) + + def OnMouseMove(self, wid, event=None): + if ((event.state & GDK.BUTTON1_MASK) == GDK.BUTTON1_MASK): + if ((event.state & GDK.SHIFT_MASK) == GDK.SHIFT_MASK): + m = self.get_pointer() + self.Pan(m[0], m[1]) + return gtk.TRUE + else: + m = self.get_pointer() + self.Rotate(m[0], m[1]) + return gtk.TRUE + elif ((event.state & GDK.BUTTON2_MASK) == GDK.BUTTON2_MASK): + m = self.get_pointer() + self.Pan(m[0], m[1]) + return gtk.TRUE + elif ((event.state & GDK.BUTTON3_MASK) == GDK.BUTTON3_MASK): + m = self.get_pointer() + self.Zoom(m[0], m[1]) + return gtk.TRUE + else: + return gtk.FALSE + + def OnEnter(self, wid, event=None): + self.grab_focus() + w = self.get_pointer() + self.UpdateRenderer(w[0], w[1]) + return gtk.TRUE + + def OnLeave(self, wid, event): + return gtk.TRUE + + def OnKeyPress(self, wid, event=None): + if (event.keyval == GDK.r) or (event.keyval == GDK.R): + self.Reset() + return gtk.TRUE + elif (event.keyval == GDK.w) or (event.keyval == GDK.W): + self.Wireframe() + return gtk.TRUE + elif (event.keyval == GDK.s) or (event.keyval == GDK.S): + self.Surface() + return gtk.TRUE + elif (event.keyval == GDK.p) or (event.keyval == GDK.P): + m = self.get_pointer() + self.PickActor(m[0], m[1]) + return gtk.TRUE + else: + return gtk.FALSE + + def GetZoomFactor(self): + return self._CurrentZoom + + def SetZoomFactor(self, zf): + self._CurrentZoom = zf + + def GetPicker(self): + return self._Picker + + def Render(self): + if (self._CurrentLight): + light = self._CurrentLight + light.SetPosition(self._CurrentCamera.GetPosition()) + light.SetFocalPoint(self._CurrentCamera.GetFocalPoint()) + + GtkVTKRenderWindowBase.Render(self) + + def UpdateRenderer(self,x,y): + """ + UpdateRenderer will identify the renderer under the mouse and set + up _CurrentRenderer, _CurrentCamera, and _CurrentLight. + """ + windowX = self.get_window().width + windowY = self.get_window().height + + renderers = self._RenderWindow.GetRenderers() + numRenderers = renderers.GetNumberOfItems() + + self._CurrentRenderer = None + renderers.InitTraversal() + for i in range(0,numRenderers): + renderer = renderers.GetNextItem() + vx,vy = (0,0) + if (windowX > 1): + vx = float(x)/(windowX-1) + if (windowY > 1): + vy = (windowY-float(y)-1)/(windowY-1) + (vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport() + + if (vx >= vpxmin and vx <= vpxmax and + vy >= vpymin and vy <= vpymax): + self._CurrentRenderer = renderer + self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\ + +vpxmin + self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\ + +vpymin + self._CurrentCamera = self._CurrentRenderer.GetActiveCamera() + lights = self._CurrentRenderer.GetLights() + lights.InitTraversal() + self._CurrentLight = lights.GetNextItem() + break + + self._LastX = x + self._LastY = y + + def GetCurrentRenderer(self): + return self._CurrentRenderer + + def StartMotion(self, wid, event=None): + x = event.x + y = event.y + self.UpdateRenderer(x,y) + return gtk.TRUE + + def EndMotion(self, wid, event=None): + if self._CurrentRenderer: + self.Render() + return gtk.TRUE + + def Rotate(self,x,y): + if self._CurrentRenderer: + + self._CurrentCamera.Azimuth(self._LastX - x) + self._CurrentCamera.Elevation(y - self._LastY) + self._CurrentCamera.OrthogonalizeViewUp() + + self._LastX = x + self._LastY = y + + self._CurrentRenderer.ResetCameraClippingRange() + self.Render() + + def Pan(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + (pPoint0,pPoint1,pPoint2) = camera.GetPosition() + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + + if (camera.GetParallelProjection()): + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetFocalPoint(fx,fy,fz) + + renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetPosition(fx,fy,fz) + + else: + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + # Specify a point location in world coordinates + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + # Convert world point coordinates to display coordinates + dPoint = renderer.GetDisplayPoint() + focalDepth = dPoint[2] + + aPoint0 = self._ViewportCenterX + (x - self._LastX) + aPoint1 = self._ViewportCenterY - (y - self._LastY) + + renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth) + renderer.DisplayToWorld() + + (rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint() + if (rPoint3 != 0.0): + rPoint0 = rPoint0/rPoint3 + rPoint1 = rPoint1/rPoint3 + rPoint2 = rPoint2/rPoint3 + + camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0, + (fPoint1 - rPoint1) + fPoint1, + (fPoint2 - rPoint2) + fPoint2) + + camera.SetPosition((fPoint0 - rPoint0) + pPoint0, + (fPoint1 - rPoint1) + pPoint1, + (fPoint2 - rPoint2) + pPoint2) + + self._LastX = x + self._LastY = y + + self.Render() + + def Zoom(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + + zoomFactor = math.pow(1.02,(0.5*(self._LastY - y))) + self._CurrentZoom = self._CurrentZoom * zoomFactor + + if camera.GetParallelProjection(): + parallelScale = camera.GetParallelScale()/zoomFactor + camera.SetParallelScale(parallelScale) + else: + camera.Dolly(zoomFactor) + renderer.ResetCameraClippingRange() + + self._LastX = x + self._LastY = y + + self.Render() + + def Reset(self): + if self._CurrentRenderer: + self._CurrentRenderer.ResetCamera() + + self.Render() + + def Wireframe(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToWireframe() + + self.Render() + + def Surface(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToSurface() + + self.Render() + + def PickActor(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + picker = self._Picker + + windowY = self.get_window().height + picker.Pick(x,(windowY - y - 1),0.0,renderer) + assembly = picker.GetAssembly() + + if (self._PickedAssembly != None and + self._PrePickedProperty != None): + self._PickedAssembly.SetProperty(self._PrePickedProperty) + # release hold of the property + self._PrePickedProperty.UnRegister(self._PrePickedProperty) + self._PrePickedProperty = None + + if (assembly != None): + self._PickedAssembly = assembly + self._PrePickedProperty = self._PickedAssembly.GetProperty() + # hold onto the property + self._PrePickedProperty.Register(self._PrePickedProperty) + self._PickedAssembly.SetProperty(self._PickedProperty) + + self.Render() + + +def main(): + # The main window + window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL) + window.set_title("A GtkVTKRenderWindow Demo!") + window.connect("destroy", gtk.mainquit) + window.connect("delete_event", gtk.mainquit) + window.set_border_width(10) + + # A VBox into which widgets are packed. + vbox = gtk.GtkVBox(spacing=3) + window.add(vbox) + vbox.show() + + # The GtkVTKRenderWindow + gvtk = GtkVTKRenderWindow() + #gvtk.SetDesiredUpdateRate(1000) + gvtk.set_usize(400, 400) + vbox.pack_start(gvtk) + gvtk.show() + + # The VTK stuff. + cone = vtk.vtkConeSource() + cone.SetResolution(80) + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + #coneActor = vtk.vtkLODActor() + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + coneActor.GetProperty().SetColor(0.5, 0.5, 1.0) + ren = vtk.vtkRenderer() + gvtk.GetRenderWindow().AddRenderer(ren) + ren.AddActor(coneActor) + + # A simple quit button + quit = gtk.GtkButton("Quit!") + quit.connect("clicked", gtk.mainquit) + vbox.pack_start(quit) + quit.show() + + # show the main window and start event processing. + window.show() + gtk.mainloop() + + +if __name__ == "__main__": + main() diff --git a/Wrapping/Python/vtk/gtk/GtkVTKRenderWindowInteractor.py b/Wrapping/Python/vtk/gtk/GtkVTKRenderWindowInteractor.py new file mode 100644 index 0000000..8976b5a --- /dev/null +++ b/Wrapping/Python/vtk/gtk/GtkVTKRenderWindowInteractor.py @@ -0,0 +1,297 @@ +""" +Description: + + Provides a pyGtk vtkRenderWindowInteractor widget. This embeds a + vtkRenderWindow inside a GTK widget and uses the + vtkGenericRenderWindowInteractor for the event handling. This is + based on vtkTkRenderWindow.py. + + The class uses the gtkgl.GtkGLArea widget (gtkglarea). This avoids + a lot of problems with flicker. + + There is a working example at the bottom. + +Created by Prabhu Ramachandran, April 2002. + +Bugs: + + (*) There is a focus related problem. Tkinter has a focus object + that handles focus events. I dont know of an equivalent object + under GTK. So, when an 'enter_notify_event' is received on the + GtkVTKRenderWindow I grab the focus but I dont know what to do when + I get a 'leave_notify_event'. + + (*) Will not work under Win32 because it uses the XID of a window in + OnRealize. Suggestions to fix this will be appreciated. + +""" + +import gtk, GDK, gtkgl +import vtk +import math + + +class GtkVTKRenderWindowInteractor(gtkgl.GtkGLArea): + + """ Embeds a vtkRenderWindow into a pyGTK widget and uses + vtkGenericRenderWindowInteractor for the event handling. This + class embeds the RenderWindow correctly. A __getattr__ hook is + provided that makes the class behave like a + vtkGenericRenderWindowInteractor.""" + + def __init__(self, *args): + l = list(args) + attr = (gtkgl.RGBA, gtkgl.DOUBLEBUFFER) + l.insert(0, self) + l.insert(1, attr) + apply(gtkgl.GtkGLArea.__init__, l) + self._RenderWindow = vtk.vtkRenderWindow() + + # private attributes + self.__Created = 0 + self._ActiveButton = 0 + + self._Iren = vtk.vtkGenericRenderWindowInteractor() + self._Iren.SetRenderWindow(self._RenderWindow) + + self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer) + self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer) + self.ConnectSignals() + + # need this to be able to handle key_press events. + self.set_flags(gtk.CAN_FOCUS) + # default size + self.set_usize(300, 300) + + def set_usize(self, w, h): + gtkgl.GtkGLArea.set_usize(self, w, h) + self._RenderWindow.SetSize(w, h) + self._Iren.SetSize(w, h) + self._Iren.ConfigureEvent() + + def ConnectSignals(self): + self.connect("realize", self.OnRealize) + self.connect("expose_event", self.OnExpose) + self.connect("configure_event", self.OnConfigure) + self.connect("button_press_event", self.OnButtonDown) + self.connect("button_release_event", self.OnButtonUp) + self.connect("motion_notify_event", self.OnMouseMove) + self.connect("enter_notify_event", self.OnEnter) + self.connect("leave_notify_event", self.OnLeave) + self.connect("key_press_event", self.OnKeyPress) + self.connect("delete_event", self.OnDestroy) + self.add_events(GDK.EXPOSURE_MASK| GDK.BUTTON_PRESS_MASK | + GDK.BUTTON_RELEASE_MASK | + GDK.KEY_PRESS_MASK | + GDK.POINTER_MOTION_MASK | + GDK.POINTER_MOTION_HINT_MASK | + GDK.ENTER_NOTIFY_MASK | GDK.LEAVE_NOTIFY_MASK) + + def __getattr__(self, attr): + """Makes the object behave like a + vtkGenericRenderWindowInteractor""" + if attr == '__vtk__': + return lambda t=self._Iren: t + elif hasattr(self._Iren, attr): + return getattr(self._Iren, attr) + else: + raise AttributeError, self.__class__.__name__ + \ + " has no attribute named " + attr + + def CreateTimer(self, obj, event): + gtk.timeout_add(10, self._Iren.TimerEvent) + + def DestroyTimer(self, obj, event): + """The timer is a one shot timer so will expire automatically.""" + return 1 + + def GetRenderWindow(self): + return self._RenderWindow + + def Render(self): + if self.__Created: + self._RenderWindow.Render() + + def OnRealize(self, *args): + if self.__Created == 0: + # you can't get the xid without the window being realized. + self.realize() + win_id = str(self.get_window().xid) + self._RenderWindow.SetWindowInfo(win_id) + self._Iren.Initialize() + self.__Created = 1 + return gtk.TRUE + + def OnConfigure(self, wid, event=None): + sz = self._RenderWindow.GetSize() + if (event.width != sz[0]) or (event.height != sz[1]): + self._Iren.SetSize(event.width, event.height) + self._Iren.ConfigureEvent() + return gtk.TRUE + + def OnExpose(self, *args): + self.Render() + return gtk.TRUE + + def OnDestroy(self, event=None): + self.hide() + del self._RenderWindow + self.destroy() + return gtk.TRUE + + def _GetCtrlShift(self, event): + ctrl, shift = 0, 0 + if ((event.state & GDK.CONTROL_MASK) == GDK.CONTROL_MASK): + ctrl = 1 + if ((event.state & GDK.SHIFT_MASK) == GDK.SHIFT_MASK): + shift = 1 + return ctrl, shift + + def OnButtonDown(self, wid, event): + """Mouse button pressed.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + button = event.button + if button == 3: + self._Iren.RightButtonPressEvent() + return gtk.TRUE + elif button == 1: + self._Iren.LeftButtonPressEvent() + return gtk.TRUE + elif button == 2: + self._Iren.MiddleButtonPressEvent() + return gtk.TRUE + else: + return gtk.FALSE + + def OnButtonUp(self, wid, event): + """Mouse button released.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + button = event.button + if button == 3: + self._Iren.RightButtonReleaseEvent() + return gtk.TRUE + elif button == 1: + self._Iren.LeftButtonReleaseEvent() + return gtk.TRUE + elif button == 2: + self._Iren.MiddleButtonReleaseEvent() + return gtk.TRUE + + return gtk.FALSE + + def OnMouseMove(self, wid, event): + """Mouse has moved.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + self._Iren.MouseMoveEvent() + return gtk.TRUE + + def OnEnter(self, wid, event): + """Entering the vtkRenderWindow.""" + self.grab_focus() + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + self._Iren.EnterEvent() + return gtk.TRUE + + def OnLeave(self, wid, event): + """Leaving the vtkRenderWindow.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + chr(0), 0, None) + self._Iren.LeaveEvent() + return gtk.TRUE + + def OnKeyPress(self, wid, event): + """Key pressed.""" + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + keycode, keysym = event.keyval, event.string + key = chr(0) + if keycode < 256: + key = chr(keycode) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + key, 0, keysym) + self._Iren.KeyPressEvent() + self._Iren.CharEvent() + return gtk.TRUE + + def OnKeyRelease(self, wid, event): + "Key released." + m = self.get_pointer() + ctrl, shift = self._GetCtrlShift(event) + keycode, keysym = event.keyval, event.string + key = chr(0) + if keycode < 256: + key = chr(keycode) + self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift, + key, 0, keysym) + self._Iren.KeyReleaseEvent() + return gtk.TRUE + + def Initialize(self): + if self.__Created: + self._Iren.Initialize() + + +def main(): + # The main window + window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL) + window.set_title("A GtkVTKRenderWindow Demo!") + window.connect("destroy", gtk.mainquit) + window.connect("delete_event", gtk.mainquit) + window.set_border_width(10) + + # A VBox into which widgets are packed. + vbox = gtk.GtkVBox(spacing=3) + window.add(vbox) + vbox.show() + + # The GtkVTKRenderWindow + gvtk = GtkVTKRenderWindowInteractor() + #gvtk.SetDesiredUpdateRate(1000) + gvtk.set_usize(400, 400) + vbox.pack_start(gvtk) + gvtk.show() + gvtk.Initialize() + gvtk.Start() + # prevents 'q' from exiting the app. + gvtk.AddObserver("ExitEvent", lambda o,e,x=None: x) + + # The VTK stuff. + cone = vtk.vtkConeSource() + cone.SetResolution(80) + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + #coneActor = vtk.vtkLODActor() + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + coneActor.GetProperty().SetColor(0.5, 0.5, 1.0) + ren = vtk.vtkRenderer() + gvtk.GetRenderWindow().AddRenderer(ren) + ren.AddActor(coneActor) + + # A simple quit button + quit = gtk.GtkButton("Quit!") + quit.connect("clicked", gtk.mainquit) + vbox.pack_start(quit) + quit.show() + + # show the main window and start event processing. + window.show() + gtk.mainloop() + + +if __name__ == "__main__": + main() diff --git a/Wrapping/Python/vtk/gtk/__init__.py b/Wrapping/Python/vtk/gtk/__init__.py new file mode 100644 index 0000000..9962bf7 --- /dev/null +++ b/Wrapping/Python/vtk/gtk/__init__.py @@ -0,0 +1,4 @@ +"""pyGTK widgets for VTK.""" + +__all__ = ['GtkVTKRenderWindow', 'GtkVTKRenderWindowInteractor', + 'GtkGLExtVTKRenderWindow', 'GtkGLExtVTKRenderWindowInteractor'] diff --git a/Wrapping/Python/vtk/hybrid.py b/Wrapping/Python/vtk/hybrid.py new file mode 100644 index 0000000..ca59b81 --- /dev/null +++ b/Wrapping/Python/vtk/hybrid.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK Hybrid library into +its namespace. This is an optional module.""" + +import os + +if os.name == 'posix': + from libvtkHybridPython import * +else: + from vtkHybridPython import * diff --git a/Wrapping/Python/vtk/imaging.py b/Wrapping/Python/vtk/imaging.py new file mode 100644 index 0000000..d7e6e66 --- /dev/null +++ b/Wrapping/Python/vtk/imaging.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK Imaging library into +its namespace. This is a required module.""" + +import os + +if os.name == 'posix': + from libvtkImagingPython import * +else: + from vtkImagingPython import * diff --git a/Wrapping/Python/vtk/io.py b/Wrapping/Python/vtk/io.py new file mode 100644 index 0000000..7fd5db4 --- /dev/null +++ b/Wrapping/Python/vtk/io.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK IO library into its +namespace. This is a required module.""" + +import os + +if os.name == 'posix': + from libvtkIOPython import * +else: + from vtkIOPython import * diff --git a/Wrapping/Python/vtk/parallel.py b/Wrapping/Python/vtk/parallel.py new file mode 100644 index 0000000..962c056 --- /dev/null +++ b/Wrapping/Python/vtk/parallel.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK Parallel library into +its namespace. This is an optional module.""" + +import os + +if os.name == 'posix': + from libvtkParallelPython import * +else: + from vtkParallelPython import * diff --git a/Wrapping/Python/vtk/qt/QVTKRenderWidget.py b/Wrapping/Python/vtk/qt/QVTKRenderWidget.py new file mode 100644 index 0000000..46ec40d --- /dev/null +++ b/Wrapping/Python/vtk/qt/QVTKRenderWidget.py @@ -0,0 +1,476 @@ +""" +A simple VTK input file for PyQt, the qt bindings for python. +See http://www.trolltech.com for qt documentation, and +http://www.river-bank.demon.co.uk or http://www.thekompany.com +for the qt python bindings. + +******************************************************* + + NOTE: The widget provided by this module is not free of bugs and it + is recommended that you consider using the + QVTKRenderWindowInteractor widget that is also in this directory + instead of this one. + +******************************************************* + + +Created by David Gobbi, December 2001 +Based on vtkTkRenderWindget.py + +Changes by Gerard Vermeulen Feb. 2003 + Win32 support +""" + +""" +This class should work with both the UNIX version of Qt and also on +Win32. + +Depending on the OpenGL graphics drivers, it may not +be possible to have more than one QVTKRenderWidget +per application. + +In short, this class is experimental. A proper implementation +will probably require a QVTKRenderWidget that is written in +C++ and then wrapped to be made available through python, +similar to the vtkTkRenderWidget. +""" + +# Problems on Win32: +# 1. The widget is not cleaned up properly and crashes the +# application. + +import vtk +import math, os, sys +from qt import * + +class QVTKRenderWidget(QWidget): + """ + A QVTKRenderWidget for Python and Qt. + Use GetRenderWindow() to get the vtkRenderWindow. + Create with the keyword stereo=1 in order to + generate a stereo-capable window. + """ + def __init__(self, parent=None, name=None, *args, **kw): + + # miscellaneous protected variables + self._CurrentRenderer = None + self._CurrentCamera = None + self._CurrentZoom = 1.0 + self._CurrentLight = None + + self._ViewportCenterX = 0 + self._ViewportCenterY = 0 + + self._Picker = vtk.vtkCellPicker() + self._PickedActor = None + self._PickedProperty = vtk.vtkProperty() + self._PickedProperty.SetColor(1,0,0) + self._PrePickedProperty = None + + # these record the previous mouse position + self._LastX = 0 + self._LastY = 0 + + # the current interaction mode (Rotate, Pan, Zoom, etc) + self._Mode = None + self._ActiveButton = 0 + + # used by the LOD actors + self._DesiredUpdateRate = 15 + self._StillUpdateRate = 0.0001 + + # private attributes + self.__oldFocus = None + self.__saveX = 0 + self.__saveY = 0 + self.__saveState = 0 + self.__connected = 0 # is QT->VTK connection done? + + # do special handling of some keywords: + # stereo, rw + + stereo = 0 + + if kw.has_key('stereo'): + if kw['stereo']: + stereo = 1 + del kw['stereo'] + + rw = None + + if kw.has_key('rw'): + rw = kw['rw'] + del kw['rw'] + + # create qt-level widget + apply(QWidget.__init__, (self,parent,name) + args, kw) + + if rw: # user-supplied render window + self._RenderWindow = rw + else: + self._RenderWindow = vtk.vtkRenderWindow() + + if stereo: # stereo mode + self._RenderWindow.StereoCapableWindowOn() + self._RenderWindow.SetStereoTypeToCrystalEyes() + + # do all the necessary qt setup + self.setBackgroundMode(2) # NoBackground + self.setMouseTracking(1) # get all mouse events + self.setFocusPolicy(2) # ClickFocus + if parent == None: + self.show() + + if self.isVisible(): + if self.__connected == 0: + size = self.size() + self._RenderWindow.SetSize(size.width(),size.height()) + self._RenderWindow.SetWindowInfo(str(int(self.winId()))) + self.__connected = 1 + + + def show(self): + QWidget.show(self) + self.repaint() # needed for initial contents display on Win32 + + def paintEvent(self,ev): + if self.isVisible(): + if self.__connected == 0: + size = self.size() + self._RenderWindow.SetSize(size.width(),size.height()) + self._RenderWindow.SetWindowInfo(str(int(self.winId()))) + self.__connected = 1 + if self.__connected: + self.Render() + + def resizeEvent(self,ev): + self.repaint() + + def enterEvent(self,ev): + if not self.hasFocus(): + self.__oldFocus = self.focusWidget() + self.setFocus() + + def leaveEvent(self,ev): + if (self.__saveState & 0x7) == 0 and self.__oldFocus: + self.__oldFocus.setFocus() + self.__oldFocus = None + + def mousePressEvent(self,ev): + if self._Mode != None: + return + + if (ev.button() == 2 or + ev.button() == 1 and ev.state() & 16): + self._Mode = "Zoom" + self._ActiveButton = ev.button() + elif (ev.button() == 4 or + ev.button() == 1 and ev.state() & 8): + self._Mode = "Pan" + self._ActiveButton = ev.button() + elif (ev.button() == 1): + self._Mode = "Rotate" + self._ActiveButton = ev.button() + + if self._Mode != None: + self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate) + + self.UpdateRenderer(ev.x(),ev.y()) + + def mouseReleaseEvent(self,ev): + if self._Mode == None: + return + + self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate) + + if self._CurrentRenderer: + self.Render() + if ev.button() == self._ActiveButton: + self._Mode = None + self._ActiveButton = 0 + + def mouseMoveEvent(self,ev): + self.__saveState = ev.state() + self.__saveX = ev.x() + self.__saveY = ev.y() + if self._Mode == "Pan": + self.Pan(ev.x(),ev.y()) + elif self._Mode == "Rotate": + self.Rotate(ev.x(),ev.y()) + elif self._Mode == "Zoom": + self.Zoom(ev.x(),ev.y()) + + def keyPressEvent(self,ev): + if ev.key() == ord('R'): + self.Reset(self.__saveX,self.__saveY) + if ev.key() == ord('W'): + self.Wireframe() + if ev.key() == ord('S'): + self.Surface() + if ev.key() == ord('P'): + self.PickActor(self.__saveX,self.__saveY) + + def contextMenuEvent(self,ev): + ev.accept(); + + def SetDesiredUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._DesiredUpdateRate = rate + + def GetDesiredUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._DesiredUpdateRate + + def SetStillUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._StillUpdateRate = rate + + def GetStillUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._StillUpdateRate + + def GetZoomFactor(self): + return self._CurrentZoom + + def GetRenderWindow(self): + return self._RenderWindow + + def GetPicker(self): + return self._Picker + + def Render(self): + if (self._CurrentLight): + light = self._CurrentLight + light.SetPosition(self._CurrentCamera.GetPosition()) + light.SetFocalPoint(self._CurrentCamera.GetFocalPoint()) + + self._RenderWindow.Render() + + def UpdateRenderer(self,x,y): + """ + UpdateRenderer will identify the renderer under the mouse and set + up _CurrentRenderer, _CurrentCamera, and _CurrentLight. + """ + windowX = self.width() + windowY = self.height() + + renderers = self._RenderWindow.GetRenderers() + numRenderers = renderers.GetNumberOfItems() + + self._CurrentRenderer = None + renderers.InitTraversal() + for i in range(0,numRenderers): + renderer = renderers.GetNextItem() + vx,vy = (0,0) + if (windowX > 1): + vx = float(x)/(windowX-1) + if (windowY > 1): + vy = (windowY-float(y)-1)/(windowY-1) + (vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport() + + if (vx >= vpxmin and vx <= vpxmax and + vy >= vpymin and vy <= vpymax): + self._CurrentRenderer = renderer + self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\ + +vpxmin + self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\ + +vpymin + self._CurrentCamera = self._CurrentRenderer.GetActiveCamera() + lights = self._CurrentRenderer.GetLights() + lights.InitTraversal() + self._CurrentLight = lights.GetNextItem() + break + + self._LastX = x + self._LastY = y + + def GetCurrentRenderer(self): + return self._CurrentRenderer + + def Rotate(self,x,y): + if self._CurrentRenderer: + + self._CurrentCamera.Azimuth(self._LastX - x) + self._CurrentCamera.Elevation(y - self._LastY) + self._CurrentCamera.OrthogonalizeViewUp() + + self._LastX = x + self._LastY = y + + self._CurrentRenderer.ResetCameraClippingRange() + self.Render() + + def Pan(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + (pPoint0,pPoint1,pPoint2) = camera.GetPosition() + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + + if (camera.GetParallelProjection()): + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetFocalPoint(fx,fy,fz) + + renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetPosition(fx,fy,fz) + + else: + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + # Specify a point location in world coordinates + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + # Convert world point coordinates to display coordinates + dPoint = renderer.GetDisplayPoint() + focalDepth = dPoint[2] + + aPoint0 = self._ViewportCenterX + (x - self._LastX) + aPoint1 = self._ViewportCenterY - (y - self._LastY) + + renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth) + renderer.DisplayToWorld() + + (rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint() + if (rPoint3 != 0.0): + rPoint0 = rPoint0/rPoint3 + rPoint1 = rPoint1/rPoint3 + rPoint2 = rPoint2/rPoint3 + + camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0, + (fPoint1 - rPoint1) + fPoint1, + (fPoint2 - rPoint2) + fPoint2) + + camera.SetPosition((fPoint0 - rPoint0) + pPoint0, + (fPoint1 - rPoint1) + pPoint1, + (fPoint2 - rPoint2) + pPoint2) + + self._LastX = x + self._LastY = y + + self.Render() + + def Zoom(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + + zoomFactor = math.pow(1.02,(0.5*(self._LastY - y))) + self._CurrentZoom = self._CurrentZoom * zoomFactor + + if camera.GetParallelProjection(): + parallelScale = camera.GetParallelScale()/zoomFactor + camera.SetParallelScale(parallelScale) + else: + camera.Dolly(zoomFactor) + renderer.ResetCameraClippingRange() + + self._LastX = x + self._LastY = y + + self.Render() + + def Reset(self,x,y): + if self._CurrentRenderer: + self._CurrentRenderer.ResetCamera() + + self.Render() + + def Wireframe(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToWireframe() + + self.Render() + + def Surface(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToSurface() + + self.Render() + + def PickActor(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + picker = self._Picker + + windowY = self.height() + picker.Pick(x,(windowY - y - 1),0.0,renderer) + actor = picker.GetActor() + + if (self._PickedActor != None and + self._PrePickedProperty != None): + self._PickedActor.SetProperty(self._PrePickedProperty) + # release hold of the property + self._PrePickedProperty.UnRegister(self._PrePickedProperty) + self._PrePickedProperty = None + + if (actor != None): + self._PickedActor = actor + self._PrePickedProperty = self._PickedActor.GetProperty() + # hold onto the property + self._PrePickedProperty.Register(self._PrePickedProperty) + self._PickedActor.SetProperty(self._PickedProperty) + + self.Render() + +#---------------------------------------------------------------------------- +def QVTKRenderWidgetConeExample(): + """Like it says, just a simple example + """ + # every QT app needs an app + app = QApplication(['QVTKRenderWidget']) + + # create the widget + widget = QVTKRenderWidget() + + ren = vtk.vtkRenderer() + widget.GetRenderWindow().AddRenderer(ren) + + cone = vtk.vtkConeSource() + cone.SetResolution(8) + + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + + ren.AddActor(coneActor) + + # show the widget + widget.show() + # close the application when window is closed + qApp.setMainWidget(widget) + # start event processing + app.exec_loop() + +if __name__ == "__main__": + QVTKRenderWidgetConeExample() + diff --git a/Wrapping/Python/vtk/qt/QVTKRenderWindowInteractor.py b/Wrapping/Python/vtk/qt/QVTKRenderWindowInteractor.py new file mode 100644 index 0000000..5175105 --- /dev/null +++ b/Wrapping/Python/vtk/qt/QVTKRenderWindowInteractor.py @@ -0,0 +1,349 @@ +""" +A simple VTK input file for PyQt, the qt bindings for python. +See http://www.trolltech.com for qt documentation, and +http://www.river-bank.demon.co.uk or http://www.thekompany.com +for the qt python bindings. + +This class is based on the vtkGenericRenderWindowInteractor and is +therefore fairly powerful. It should also play nicely with the +vtk3DWidget code. + +Created by Prabhu Ramachandran, May 2002 +Based on David Gobbi's QVTKRenderWidget.py + +Changes by Gerard Vermeulen Feb. 2003 + Win32 support. + +Changes by Gerard Vermeulen, May 2003 + Bug fixes and better integration with the Qt framework. +""" + +""" +This class works with the UNIX and Win32 versions of Qt. + +Depending on the OpenGL graphics drivers, it may not +be possible to have more than one QVTKRenderWidget +per application. + +In short, this class is experimental. +""" + + +# To do for Win32: +# 1. More testing to assure that the widget is always cleaned up +# properly and does not crash the application. + +import qt +import vtk + +class QVTKRenderWindowInteractor(qt.QWidget): + + """ A QVTKRenderWindowInteractor for Python and Qt. Uses a + vtkGenericRenderWindowInteractor to handle the interactions. Use + GetRenderWindow() to get the vtkRenderWindow. Create with the + keyword stereo=1 in order to generate a stereo-capable window. + + The user interface is summarized in vtkInteractorStyle.h: + + - Keypress j / Keypress t: toggle between joystick (position + sensitive) and trackball (motion sensitive) styles. In joystick + style, motion occurs continuously as long as a mouse button is + pressed. In trackball style, motion occurs when the mouse button + is pressed and the mouse pointer moves. + + - Keypress c / Keypress o: toggle between camera and object + (actor) modes. In camera mode, mouse events affect the camera + position and focal point. In object mode, mouse events affect + the actor that is under the mouse pointer. + + - Button 1: rotate the camera around its focal point (if camera + mode) or rotate the actor around its origin (if actor mode). The + rotation is in the direction defined from the center of the + renderer's viewport towards the mouse position. In joystick mode, + the magnitude of the rotation is determined by the distance the + mouse is from the center of the render window. + + - Button 2: pan the camera (if camera mode) or translate the actor + (if object mode). In joystick mode, the direction of pan or + translation is from the center of the viewport towards the mouse + position. In trackball mode, the direction of motion is the + direction the mouse moves. (Note: with 2-button mice, pan is + defined as <Shift>-Button 1.) + + - Button 3: zoom the camera (if camera mode) or scale the actor + (if object mode). Zoom in/increase scale if the mouse position is + in the top half of the viewport; zoom out/decrease scale if the + mouse position is in the bottom half. In joystick mode, the amount + of zoom is controlled by the distance of the mouse pointer from + the horizontal centerline of the window. + + - Keypress 3: toggle the render window into and out of stereo + mode. By default, red-blue stereo pairs are created. Some systems + support Crystal Eyes LCD stereo glasses; you have to invoke + SetStereoTypeToCrystalEyes() on the rendering window. Note: to + use stereo you also need to pass a stereo=1 keyword argument to + the constructor. + + - Keypress e: exit the application. + + - Keypress f: fly to the picked point + + - Keypress p: perform a pick operation. The render window interactor + has an internal instance of vtkCellPicker that it uses to pick. + + - Keypress r: reset the camera view along the current view + direction. Centers the actors and moves the camera so that all actors + are visible. + + - Keypress s: modify the representation of all actors so that they + are surfaces. + + - Keypress u: invoke the user-defined function. Typically, this + keypress will bring up an interactor that you can type commands in. + + - Keypress w: modify the representation of all actors so that they + are wireframe. + """ + + def __init__(self, parent=None, name=None, *args, **kw): + # the current button + self._ActiveButton = 0 + + # private attributes + self.__oldFocus = None + self.__saveX = 0 + self.__saveY = 0 + self.__saveState = 0 + self.__connected = 0 # is QT->VTK connection done? + + # do special handling of some keywords: + # stereo, rw + + stereo = 0 + + if kw.has_key('stereo'): + if kw['stereo']: + stereo = 1 + del kw['stereo'] + + rw = None + + if kw.has_key('rw'): + rw = kw['rw'] + del kw['rw'] + + # create qt-level widget + # You cannot pass kw anymore, you'll a TypeError: keyword arguments are not supported + # http://goldenspud.com/webrog/archives/2004/07/20/pyqt-platform-inconsistencies/ + apply(qt.QWidget.__init__, (self,parent,name) + args) + + if rw: # user-supplied render window + self._RenderWindow = rw + else: + self._RenderWindow = vtk.vtkRenderWindow() + + if stereo: # stereo mode + self._RenderWindow.StereoCapableWindowOn() + self._RenderWindow.SetStereoTypeToCrystalEyes() + + self._Iren = vtk.vtkGenericRenderWindowInteractor() + self._Iren.SetRenderWindow(self._RenderWindow) + + # do all the necessary qt setup + self.setBackgroundMode(2) # NoBackground + self.setMouseTracking(1) # get all mouse events + self.setFocusPolicy(2) # ClickFocus + if parent == None: + self.show() + + self._Timer = qt.QTimer(self, 'timer handler') + self.connect(self._Timer, qt.SIGNAL('timeout()'), + self.TimerEvent) + + self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer) + self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer) + + def __getattr__(self, attr): + """Makes the object behave like a + vtkGenericRenderWindowInteractor""" + if attr == '__vtk__': + return lambda t=self._Iren: t + elif hasattr(self._Iren, attr): + return getattr(self._Iren, attr) + elif hasattr(qt.QWidget, attr): + return getattr(self.sipThis, attr) + else: + raise AttributeError, self.__class__.__name__ + \ + " has no attribute named " + attr + + def CreateTimer(self, obj, evt): + self._Timer.start(10) + + def DestroyTimer(self, obj, evt): + self._Timer.stop() + return 1 + + def TimerEvent(self): + self._Iren.TimerEvent() + + def polish(self): + """Final initialization just before the widget is displayed.""" + size = self.size() + self._Iren.SetSize(size.width(), size.height()) + self._RenderWindow.SetWindowInfo(str(int(self.winId()))) + self._Iren.ConfigureEvent() + self.__connected = 1 + + def show(self): + qt.QWidget.show(self) + self.update() # needed for initial contents display on Win32 + + def paintEvent(self,ev): + if self.__connected: + self.Render() + + def resizeEvent(self,ev): + size = self.size() + self._Iren.SetSize(size.width(), size.height()) + self._Iren.ConfigureEvent() + self.update() + + def _GetCtrlShift(self, ev): + ctrl, shift = 0, 0 + if hasattr(ev, 'state'): + if (ev.state() & 8): + shift = 1 + if (ev.state() & 16): + ctrl = 1 + elif self.__saveState: + if (self.__saveState & 8): + shift = 1 + if (self.__saveState & 16): + ctrl = 1 + return ctrl, shift + + def enterEvent(self,ev): + if not self.hasFocus(): + self.__oldFocus = self.focusWidget() + self.setFocus() + ctrl, shift = self._GetCtrlShift(ev) + self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY, + ctrl, shift, chr(0), 0, None) + self._Iren.EnterEvent() + + def leaveEvent(self,ev): + if (self.__saveState & 0x7) == 0 and self.__oldFocus: + self.__oldFocus.setFocus() + self.__oldFocus = None + ctrl, shift = self._GetCtrlShift(ev) + self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY, + ctrl, shift, chr(0), 0, None) + self._Iren.LeaveEvent() + + def mousePressEvent(self,ev): + ctrl, shift = self._GetCtrlShift(ev) + repeat = 0 + if ev.type() == qt.QEvent.MouseButtonDblClick: + repeat = 1 + self._Iren.SetEventInformationFlipY(ev.x(), ev.y(), + ctrl, shift, chr(0), repeat, None) + + self._ActiveButton = 0 + if ev.button() == 1: + self._Iren.LeftButtonPressEvent() + self._ActiveButton = 'Left' + elif ev.button() == 2: + self._Iren.RightButtonPressEvent() + self._ActiveButton = 'Right' + elif ev.button() == 4: + self._Iren.MiddleButtonPressEvent() + self._ActiveButton = 'Middle' + + def mouseReleaseEvent(self,ev): + ctrl, shift = self._GetCtrlShift(ev) + self._Iren.SetEventInformationFlipY(ev.x(), ev.y(), + ctrl, shift, chr(0), 0, None) + + if self._ActiveButton == 'Right': + self._Iren.RightButtonReleaseEvent() + elif self._ActiveButton == 'Left': + self._Iren.LeftButtonReleaseEvent() + elif self._ActiveButton == 'Middle': + self._Iren.MiddleButtonReleaseEvent() + + def mouseMoveEvent(self,ev): + self.__saveState = ev.state() + self.__saveX = ev.x() + self.__saveY = ev.y() + ctrl, shift = self._GetCtrlShift(ev) + self._Iren.SetEventInformationFlipY(ev.x(), ev.y(), + ctrl, shift, chr(0), 0, None) + self._Iren.MouseMoveEvent() + + def keyPressEvent(self,ev): + ctrl, shift = self._GetCtrlShift(ev) + key = chr(0) + if ev.key() < 256: + key = str(ev.text()) + + self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY, + ctrl, shift, key, 0, None) + self._Iren.KeyPressEvent() + self._Iren.CharEvent() + + def keyReleaseEvent(self,ev): + ctrl, shift = self._GetCtrlShift(ev) + key = chr(0) + if ev.key() < 256: + key = chr(ev.key()) + + self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY, + ctrl, shift, key, 0, None) + self._Iren.KeyReleaseEvent() + + def GetRenderWindow(self): + return self._RenderWindow + + def Render(self): + self._RenderWindow.Render() + + +#----------------------------------------------------------------------- +def QVTKRenderWidgetConeExample(): + """A simple example that uses the QVTKRenderWindowInteractor + class. """ + + # every QT app needs an app + app = qt.QApplication(['QVTKRenderWindowInteractor']) + + # create the widget + widget = QVTKRenderWindowInteractor() + widget.Initialize() + widget.Start() + # if you dont want the 'q' key to exit comment this. + widget.AddObserver("ExitEvent", lambda o, e, a=app: a.quit()) + + ren = vtk.vtkRenderer() + widget.GetRenderWindow().AddRenderer(ren) + + cone = vtk.vtkConeSource() + cone.SetResolution(8) + + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + + ren.AddActor(coneActor) + + # show the widget + widget.show() + # close the application when window is closed + app.setMainWidget(widget) + # start event processing + app.exec_loop() + +if __name__ == "__main__": + QVTKRenderWidgetConeExample() + diff --git a/Wrapping/Python/vtk/qt/__init__.py b/Wrapping/Python/vtk/qt/__init__.py new file mode 100644 index 0000000..1108daf --- /dev/null +++ b/Wrapping/Python/vtk/qt/__init__.py @@ -0,0 +1,3 @@ +"""pyQt widgets for VTK.""" + +__all__ = ['QVTKRenderWidget', 'QVTKRenderWindowInteractor'] diff --git a/Wrapping/Python/vtk/rendering.py b/Wrapping/Python/vtk/rendering.py new file mode 100644 index 0000000..a5bf3ff --- /dev/null +++ b/Wrapping/Python/vtk/rendering.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK Rendering library into +its namespace. This is an optional module.""" + +import os + +if os.name == 'posix': + from libvtkRenderingPython import * +else: + from vtkRenderingPython import * diff --git a/Wrapping/Python/vtk/required.py b/Wrapping/Python/vtk/required.py new file mode 100644 index 0000000..f647fae --- /dev/null +++ b/Wrapping/Python/vtk/required.py @@ -0,0 +1,8 @@ +""" This module loads all the required VTK libraries.""" + +# Load all required kits. +from common import * +from filtering import * +from io import * +from imaging import * +from graphics import * diff --git a/Wrapping/Python/vtk/test/BlackBox.py b/Wrapping/Python/vtk/test/BlackBox.py new file mode 100644 index 0000000..6cf6c09 --- /dev/null +++ b/Wrapping/Python/vtk/test/BlackBox.py @@ -0,0 +1,90 @@ +from vtk.util import vtkMethodParser + + +class Tester: + def __init__(self, debug=0): + self.setDebug(debug) + self.parser = vtkMethodParser.VtkDirMethodParser() + self.obj = None + + def setDebug(self, val): + """Sets debug value of the vtkMethodParser. 1 is verbose and + 0 is not. 0 is default.""" + vtkMethodParser.DEBUG = val + + def testParse(self, obj): + """ Testing if the object is parseable.""" + self.parser.parse_methods(obj) + self.obj = obj + + def testGetSet(self, obj): + """ Testing Get/Set methods.""" + if obj != self.obj: + self.testParse(obj) + methods = self.parser.get_set_methods() + toggle = map(lambda x: x[:-2], self.parser.toggle_methods()) + methods.extend(toggle) + for method in methods: + setm = "Set%s"%method + getm = "Get%s"%method + val = eval("obj.%s()"%getm) + try: + apply(eval("obj.%s"%setm), val) + except TypeError: + apply(eval("obj.%s"%setm), (val,)) + + val1 = eval("obj.%s()"%getm) + + if val1 != val: + name = obj.GetClassName() + msg = "Failed test for %(name)s.Get/Set%(method)s\n"\ + "Before Set, value = %(val)s; "\ + "After Set, value = %(val1)s"%locals() + raise AssertionError, msg + + def testBoolean(self, obj): + """ Testing boolean (On/Off) methods.""" + if obj != self.obj: + self.testParse(obj) + methods = self.parser.toggle_methods() + for method1 in methods: + method = method1[:-2] + getm = "Get%s"%method + + orig_val = eval("obj.%s()"%getm) + + # Turn on + eval("obj.%sOn()"%method) + val = eval("obj.%s()"%getm) + + if val != 1: + name = obj.GetClassName() + msg = "Failed test for %(name)s.%(method)sOn\n"\ + "Result not equal to 1 "%locals() + raise AssertionError, msg + + # Turn on + eval("obj.%sOff()"%method) + val = eval("obj.%s()"%getm) + + if val != 0: + name = obj.GetClassName() + msg = "Failed test for %(name)s.%(method)sOff\n"\ + "Result not equal to 0 "%locals() + raise AssertionError, msg + + # set the value back to the original value. + eval("obj.Set%s(orig_val)"%method) + + + def test(self, obj): + """Test the given vtk object.""" + + # first try parsing the object. + self.testParse(obj) + + # test the get/set methods + self.testGetSet(obj) + + # test the boolean methods + self.testBoolean(obj) diff --git a/Wrapping/Python/vtk/test/Testing.py b/Wrapping/Python/vtk/test/Testing.py new file mode 100644 index 0000000..3ea7022 --- /dev/null +++ b/Wrapping/Python/vtk/test/Testing.py @@ -0,0 +1,518 @@ +""" This module attempts to make it easy to create VTK-Python +unittests. The module uses unittest for the test interface. For more +documentation on what unittests are and how to use them, please read +these: + + http://www.python.org/doc/current/lib/module-unittest.html + + http://www.diveintopython.org/roman_divein.html + + +This VTK-Python test module supports image based tests with multiple +images per test suite and multiple images per individual test as well. +It also prints information appropriate for Dart +(http://public.kitware.com/Dart/). + +This module defines several useful classes and functions to make +writing tests easy. The most important of these are: + +class vtkTest: + Subclass this for your tests. It also has a few useful internal + functions that can be used to do some simple blackbox testing. + +compareImage(renwin, img_fname, threshold=10): + Compares renwin with image and generates image if it does not + exist. The threshold determines how closely the images must match. + The function also handles multiple images and finds the best + matching image. + +compareImageWithSavedImage(src_img, img_fname, threshold=10): + Compares given source image (in the form of a vtkImageData) with + saved image and generates the image if it does not exist. The + threshold determines how closely the images must match. The + function also handles multiple images and finds the best matching + image. + +getAbsImagePath(img_basename): + Returns the full path to the image given the basic image name. + +main(cases): + Does the testing given a list of tuples containing test classes and + the starting string of the functions used for testing. + +interact(): + Interacts with the user if necessary. The behavior of this is + rather trivial and works best when using Tkinter. It does not do + anything by default and stops to interact with the user when given + the appropriate command line arguments. + +isInteractive(): + If interact() is not good enough, use this to find if the mode is + interactive or not and do whatever is necessary to generate an + interactive view. + +Examples: + + The best way to learn on how to use this module is to look at a few + examples. The end of this file contains a trivial example. Please + also look at the following examples: + + Rendering/Testing/Python/TestTkRenderWidget.py, + Rendering/Testing/Python/TestTkRenderWindowInteractor.py + +Created: September, 2002 + +Prabhu Ramachandran <prabhu@aero.iitm.ernet.in> +""" + +import sys, os, time +import unittest, getopt +import vtk +import BlackBox + +# location of the VTK data files. Set via command line args or +# environment variable. +VTK_DATA_ROOT = "" + +# location of the VTK baseline images. Set via command line args or +# environment variable. +VTK_BASELINE_ROOT = "" + +# Verbosity of the test messages (used by unittest) +_VERBOSE = 0 + +# Determines if it is necessary to interact with the user. If zero +# dont interact if 1 interact. Set via command line args +_INTERACT = 0 + +# This will be set to 1 when the image test will not be performed. +# This option is used internally by the script and set via command +# line arguments. +_NO_IMAGE = 0 + + +class vtkTest(unittest.TestCase): + """A simple default VTK test class that defines a few useful + blackbox tests that can be readily used. Derive your test cases + from this class and use the following if you'd like to. + + Note: Unittest instantiates this class (or your subclass) each + time it tests a method. So if you do not want that to happen when + generating VTK pipelines you should create the pipeline in the + class definition as done below for _blackbox. + """ + + _blackbox = BlackBox.Tester(debug=0) + + # Due to what seems to be a bug in python some objects leak. + # Avoid the exit-with-error in vtkDebugLeaks. + dl = vtk.vtkDebugLeaks() + dl.SetExitError(0) + dl = None + + def _testParse(self, obj): + """Does a blackbox test by attempting to parse the class for + its various methods using vtkMethodParser. This is a useful + test because it gets all the methods of the vtkObject, parses + them and sorts them into different classes of objects.""" + self._blackbox.testParse(obj) + + def _testGetSet(self, obj): + """Checks the Get/Set method pairs by setting the value using + the current state and making sure that it equals the value it + was originally. This effectively calls _testParse + internally. """ + self._blackbox.testGetSet(obj) + + def _testBoolean(self, obj): + """Checks the Boolean methods by setting the value on and off + and making sure that the GetMethod returns the the set value. + This effectively calls _testParse internally. """ + self._blackbox.testBoolean(obj) + + + +def interact(): + """Interacts with the user if necessary. """ + global _INTERACT + if _INTERACT: + raw_input("\nPress Enter/Return to continue with the testing. --> ") + +def isInteractive(): + """Returns if the currently chosen mode is interactive or not + based on command line options.""" + return _INTERACT + +def getAbsImagePath(img_basename): + """Returns the full path to the image given the basic image + name.""" + global VTK_BASELINE_ROOT + return os.path.join(VTK_BASELINE_ROOT, img_basename) + +def compareImageWithSavedImage(src_img, img_fname, threshold=10): + """Compares a source image (src_img, which is a vtkImageData) with + the saved image file whose name is given in the second argument. + If the image file does not exist the image is generated and + stored. If not the source image is compared to that of the + figure. This function also handles multiple images and finds the + best matching image. + """ + global _NO_IMAGE + if _NO_IMAGE: + return + + f_base, f_ext = os.path.splitext(img_fname) + + if not os.path.isfile(img_fname): + # generate the image + pngw = vtk.vtkPNGWriter() + pngw.SetFileName(img_fname) + pngw.SetInput(src_img) + pngw.Write() + return + + pngr = vtk.vtkPNGReader() + pngr.SetFileName(img_fname) + + idiff = vtk.vtkImageDifference() + idiff.SetInput(src_img) + idiff.SetImage(pngr.GetOutput()) + idiff.Update() + + min_err = idiff.GetThresholdedError() + img_err = min_err + best_img = img_fname + + err_index = 0 + count = 0 + if min_err > threshold: + count = 1 + test_failed = 1 + err_index = -1 + while 1: # keep trying images till we get the best match. + new_fname = f_base + "_%d.png"%count + if not os.path.exists(new_fname): + # no other image exists. + break + # since file exists check if it matches. + pngr.SetFileName(new_fname) + pngr.Update() + idiff.Update() + alt_err = idiff.GetThresholdedError() + if alt_err < threshold: + # matched, + err_index = count + test_failed = 0 + min_err = alt_err + img_err = alt_err + best_img = new_fname + break + else: + if alt_err < min_err: + # image is a better match. + err_index = count + min_err = alt_err + img_err = alt_err + best_img = new_fname + + count = count + 1 + # closes while loop. + + if test_failed: + _handleFailedImage(idiff, pngr, best_img) + # Print for Dart. + _printDartImageError(img_err, err_index, f_base) + msg = "Failed image test: %f\n"%idiff.GetThresholdedError() + raise AssertionError, msg + # output the image error even if a test passed + _printDartImageSuccess(img_err, err_index) + + +def compareImage(renwin, img_fname, threshold=10): + """Compares renwin's (a vtkRenderWindow) contents with the image + file whose name is given in the second argument. If the image + file does not exist the image is generated and stored. If not the + image in the render window is compared to that of the figure. + This function also handles multiple images and finds the best + matching image. """ + + global _NO_IMAGE + if _NO_IMAGE: + return + + w2if = vtk.vtkWindowToImageFilter() + w2if.ReadFrontBufferOff() + w2if.SetInput(renwin) + return compareImageWithSavedImage(w2if.GetOutput(), img_fname, threshold) + + +def _printDartImageError(img_err, err_index, img_base): + """Prints the XML data necessary for Dart.""" + print "Failed image test with error: %f"%img_err + print "<DartMeasurement name=\"ImageError\" type=\"numeric/double\">", + print "%f </DartMeasurement>"%img_err + if err_index <= 0: + print "<DartMeasurement name=\"BaselineImage\" type=\"text/string\">Standard</DartMeasurement>", + else: + print "<DartMeasurement name=\"BaselineImage\" type=\"numeric/integer\">", + print "%d </DartMeasurement>"%err_index + + print "<DartMeasurementFile name=\"TestImage\" type=\"image/jpeg\">", + print "%s </DartMeasurementFile>"%(img_base + '.test.small.jpg') + + print "<DartMeasurementFile name=\"DifferenceImage\" type=\"image/jpeg\">", + print "%s </DartMeasurementFile>"%(img_base + '.diff.small.jpg') + print "<DartMeasurementFile name=\"ValidImage\" type=\"image/jpeg\">", + print "%s </DartMeasurementFile>"%(img_base + '.small.jpg') + + +def _printDartImageSuccess(img_err, err_index): + "Prints XML data for Dart when image test succeeded." + print "<DartMeasurement name=\"ImageError\" type=\"numeric/double\">", + print "%f </DartMeasurement>"%img_err + if err_index <= 0: + print "<DartMeasurement name=\"BaselineImage\" type=\"text/string\">Standard</DartMeasurement>", + else: + print "<DartMeasurement name=\"BaselineImage\" type=\"numeric/integer\">", + print "%d </DartMeasurement>"%err_index + + +def _handleFailedImage(idiff, pngr, img_fname): + """Writes all the necessary images when an image comparison + failed.""" + f_base, f_ext = os.path.splitext(img_fname) + + # write out the difference file in full. + pngw = vtk.vtkPNGWriter() + pngw.SetFileName(f_base + ".diff.png") + pngw.SetInput(idiff.GetOutput()) + pngw.Write() + + # write the difference image scaled and gamma adjusted for the + # dashboard. + sz = pngr.GetOutput().GetDimensions() + if sz[1] <= 250.0: + mag = 1.0 + else: + mag = 250.0/sz[1] + + shrink = vtk.vtkImageResample() + shrink.SetInput(idiff.GetOutput()) + shrink.InterpolateOn() + shrink.SetAxisMagnificationFactor(0, mag) + shrink.SetAxisMagnificationFactor(1, mag) + + gamma = vtk.vtkImageShiftScale() + gamma.SetInput(shrink.GetOutput()) + gamma.SetShift(0) + gamma.SetScale(10) + + jpegw = vtk.vtkJPEGWriter() + jpegw.SetFileName(f_base + ".diff.small.jpg") + jpegw.SetInput(gamma.GetOutput()) + jpegw.SetQuality(85) + jpegw.Write() + + # write out the image that was generated. + shrink.SetInput(idiff.GetInput()) + jpegw.SetInput(shrink.GetOutput()) + jpegw.SetFileName(f_base + ".test.small.jpg") + jpegw.Write() + + # write out the valid image that matched. + shrink.SetInput(idiff.GetImage()) + jpegw.SetInput(shrink.GetOutput()) + jpegw.SetFileName(f_base + ".small.jpg") + jpegw.Write() + + +def main(cases): + """ Pass a list of tuples containing test classes and the starting + string of the functions used for testing. + + Example: + + main ([(vtkTestClass, 'test'), (vtkTestClass1, 'test')]) + """ + + processCmdLine() + + timer = vtk.vtkTimerLog() + s_time = timer.GetCPUTime() + s_wall_time = time.time() + + # run the tests + result = test(cases) + + tot_time = timer.GetCPUTime() - s_time + tot_wall_time = float(time.time() - s_wall_time) + + # output measurements for Dart + print "<DartMeasurement name=\"WallTime\" type=\"numeric/double\">", + print " %f </DartMeasurement>"%tot_wall_time + print "<DartMeasurement name=\"CPUTime\" type=\"numeric/double\">", + print " %f </DartMeasurement>"%tot_time + + # Delete these to eliminate debug leaks warnings. + del cases, timer + + if result.wasSuccessful(): + sys.exit(0) + else: + sys.exit(1) + + +def test(cases): + """ Pass a list of tuples containing test classes and the + functions used for testing. + + It returns a unittest._TextTestResult object. + + Example: + + test = test_suite([(vtkTestClass, 'test'), + (vtkTestClass1, 'test')]) + """ + # Make the test suites from the arguments. + suites = [] + for case in cases: + suites.append(unittest.makeSuite(case[0], case[1])) + test_suite = unittest.TestSuite(suites) + + # Now run the tests. + runner = unittest.TextTestRunner(verbosity=_VERBOSE) + result = runner.run(test_suite) + + return result + + +def usage(): + msg="""Usage:\nTestScript.py [options]\nWhere options are:\n + + -D /path/to/VTKData + --data-dir /path/to/VTKData + + Directory containing VTK Data use for tests. If this option + is not set via the command line the environment variable + VTK_DATA_ROOT is used. If the environment variable is not + set the value defaults to '../../../../VTKData'. + + -B /path/to/valid/image_dir/ + --baseline-root /path/to/valid/image_dir/ + + This is a path to the directory containing the valid images + for comparison. If this option is not set via the command + line the environment variable VTK_BASELINE_ROOT is used. If + the environment variable is not set the value defaults to + the same value set for -D (--data-dir). + + -v level + --verbose level + + Sets the verbosity of the test runner. Valid values are 0, + 1, and 2 in increasing order of verbosity. + + -I + --interact + + Interacts with the user when chosen. If this is not chosen + the test will run and exit as soon as it is finished. When + enabled, the behavior of this is rather trivial and works + best when the test uses Tkinter. + + -n + --no-image + + Does not do any image comparisons. This is useful if you + want to run the test and not worry about test images or + image failures etc. + + -h + --help + + Prints this message. + +""" + return msg + + +def parseCmdLine(): + arguments = sys.argv[1:] + + options = "B:D:v:hnI" + long_options = ['baseline-root=', 'data-dir=', 'verbose=', 'help', + 'no-image', 'interact'] + + try: + opts, args = getopt.getopt(arguments, options, long_options) + except getopt.error, msg: + print usage() + print '-'*70 + print msg + sys.exit (1) + + return opts, args + + +def processCmdLine(): + opts, args = parseCmdLine() + + global VTK_DATA_ROOT, VTK_BASELINE_ROOT + global _VERBOSE, _NO_IMAGE, _INTERACT + + # setup defaults + try: + VTK_DATA_ROOT = os.environ['VTK_DATA_ROOT'] + except KeyError: + VTK_DATA_ROOT = os.path.normpath("../../../../VTKData") + + try: + VTK_BASELINE_ROOT = os.environ['VTK_BASELINE_ROOT'] + except KeyError: + pass + + for o, a in opts: + if o in ('-D', '--data-dir'): + VTK_DATA_ROOT = os.path.abspath(a) + if o in ('-B', '--baseline-root'): + VTK_BASELINE_ROOT = os.path.abspath(a) + if o in ('-n', '--no-image'): + _NO_IMAGE = 1 + if o in ('-I', '--interact'): + _INTERACT = 1 + if o in ('-v', '--verbose'): + try: + _VERBOSE = int(a) + except: + msg="Verbosity should be an integer. 0, 1, 2 are valid." + print msg + sys.exit(1) + if o in ('-h', '--help'): + print usage() + sys.exit() + + if not VTK_BASELINE_ROOT: # default value. + VTK_BASELINE_ROOT = VTK_DATA_ROOT + + + +if __name__ == "__main__": + ###################################################################### + # A Trivial test case to illustrate how this module works. + class SampleTest(vtkTest): + obj = vtk.vtkActor() + def testParse(self): + "Test if class is parseable" + self._testParse(self.obj) + + def testGetSet(self): + "Testing Get/Set methods" + self._testGetSet(self.obj) + + def testBoolean(self): + "Testing Boolean methods" + self._testBoolean(self.obj) + + # Test with the above trivial sample test. + main( [ (SampleTest, 'test') ] ) + diff --git a/Wrapping/Python/vtk/test/__init__.py b/Wrapping/Python/vtk/test/__init__.py new file mode 100644 index 0000000..961abd0 --- /dev/null +++ b/Wrapping/Python/vtk/test/__init__.py @@ -0,0 +1,4 @@ +"""Modules used for testing VTK-Python wrappers and writing tests for +VTK using Python.""" + +__all__ = ['Testing', 'BlackBox'] diff --git a/Wrapping/Python/vtk/tk/.cvsignore b/Wrapping/Python/vtk/tk/.cvsignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/Wrapping/Python/vtk/tk/.cvsignore @@ -0,0 +1 @@ +*.pyc diff --git a/Wrapping/Python/vtk/tk/__init__.py b/Wrapping/Python/vtk/tk/__init__.py new file mode 100644 index 0000000..78f0eba --- /dev/null +++ b/Wrapping/Python/vtk/tk/__init__.py @@ -0,0 +1,4 @@ +"""Tkinter widgets for VTK.""" + +__all__ = ['vtkTkRenderWidget', 'vtkTkImageViewerWidget', + 'vtkTkRenderWindowInteractor', 'vtkTkPhotoImage'] diff --git a/Wrapping/Python/vtk/tk/vtkLoadPythonTkWidgets.py b/Wrapping/Python/vtk/tk/vtkLoadPythonTkWidgets.py new file mode 100644 index 0000000..14a9cff --- /dev/null +++ b/Wrapping/Python/vtk/tk/vtkLoadPythonTkWidgets.py @@ -0,0 +1,64 @@ +import sys, os, string + +def vtkLoadPythonTkWidgets(interp): + """vtkLoadPythonTkWidgets(interp) -- load vtk-tk widget extensions + + This is a mess of mixed python and tcl code that searches for the + shared object file that contains the python-vtk-tk widgets. Both + the python path and the tcl path are searched. + """ + name = 'vtkRenderingPythonTkWidgets' + pkgname = string.capitalize(string.lower(name)) + + # find out if the file is already loaded + loaded = interp.call('info', 'loaded') + if string.find(loaded, pkgname) >= 0: + return + + # create the platform-dependent file name + prefix = '' + if os.name == 'posix': + prefix = 'lib' + extension = interp.call('info', 'sharedlibextension') + filename = prefix+name+extension + + # create an extensive list of paths to search + pathlist = sys.path + # add tcl paths, ensure that {} is handled properly + try: + auto_paths = string.split(interp.getvar('auto_path')) + except AttributeError: + auto_paths = interp.getvar('auto_path') + for path in auto_paths: + prev = str(pathlist[-1]) + try: + # try block needed when one uses Gordon McMillan's Python + # Installer. + if len(prev) > 0 and prev[0] == '{' and prev[-1] != '}': + pathlist[-1] = prev+' '+path + else: + pathlist.append(path) + except AttributeError: + pass + # a common place for these sorts of things + if os.name == 'posix': + pathlist.append('/usr/local/lib') + + # attempt to load + for path in pathlist: + try: + # try block needed when one uses Gordon McMillan's Python + # Installer. + if len(path) > 0 and path[0] == '{' and path[-1] == '}': + path = path[1:-1] + fullpath = os.path.join(path, filename) + except AttributeError: + pass + if ' ' in fullpath: + fullpath = '{'+fullpath+'}' + if interp.eval('catch {load '+fullpath+' '+pkgname+'}') == '0': + return + + # re-generate the error + interp.call('load', filename) + diff --git a/Wrapping/Python/vtk/tk/vtkTkImageViewerWidget.py b/Wrapping/Python/vtk/tk/vtkTkImageViewerWidget.py new file mode 100644 index 0000000..aa59d5b --- /dev/null +++ b/Wrapping/Python/vtk/tk/vtkTkImageViewerWidget.py @@ -0,0 +1,360 @@ +""" +A vtkTkImageViewerWidget for python, which is based on the +vtkTkImageWindowWidget. + +Specify double=1 to get a double-buffered window. + +Created by David Gobbi, Nov 1999 +""" + +import Tkinter +import math, os, sys +import vtk + +from vtkLoadPythonTkWidgets import vtkLoadPythonTkWidgets + +class vtkTkImageViewerWidget(Tkinter.Widget): + """ + A vtkTkImageViewerWidget for Python. + + Use GetImageViewer() to get the vtkImageViewer. + + Create with the keyword double=1 in order to generate a + double-buffered viewer. + + Create with the keyword focus_on_enter=1 to enable + focus-follows-mouse. The default is for a click-to-focus mode. + """ + def __init__(self, master, cnf={}, **kw): + """ + Constructor. + + Keyword arguments: + + iv -- Use passed image viewer instead of creating a new one. + + double -- If True, generate a double-buffered viewer. + Defaults to False. + + focus_on_enter -- If True, use a focus-follows-mouse mode. + Defaults to False where the widget will use a click-to-focus + mode. + """ + # load the necessary extensions into tk + vtkLoadPythonTkWidgets(master.tk) + + try: # use specified vtkImageViewer + imageViewer = kw['iv'] + except KeyError: # or create one if none specified + imageViewer = vtk.vtkImageViewer() + + doubleBuffer = 0 + try: + if kw['double']: + doubleBuffer = 1 + del kw['double'] + except: + pass + + # check if focus should follow mouse + if kw.get('focus_on_enter'): + self._FocusOnEnter = 1 + del kw['focus_on_enter'] + else: + self._FocusOnEnter = 0 + + kw['iv'] = imageViewer.GetAddressAsString("vtkImageViewer") + Tkinter.Widget.__init__(self, master, 'vtkTkImageViewerWidget', + cnf, kw) + if doubleBuffer: + imageViewer.GetRenderWindow().DoubleBufferOn() + + self.BindTkImageViewer() + + def __getattr__(self,attr): + # because the tk part of vtkTkImageViewerWidget must have + # the only remaining reference to the ImageViewer when + # it is destroyed, we can't actually store the ImageViewer + # as an attribute but instead have to get it from the tk-side + if attr == '_ImageViewer': + addr = self.tk.call(self._w, 'GetImageViewer')[5:] + return vtk.vtkImageViewer('_%s_vtkImageViewer_p' % addr) + raise AttributeError, self.__class__.__name__ + \ + " has no attribute named " + attr + + def GetImageViewer(self): + return self._ImageViewer + + def Render(self): + self._ImageViewer.Render() + + def BindTkImageViewer(self): + imager = self._ImageViewer.GetRenderer() + + # stuff for window level text. + mapper = vtk.vtkTextMapper() + mapper.SetInput("none") + t_prop = mapper.GetTextProperty() + t_prop.SetFontFamilyToTimes() + t_prop.SetFontSize(18) + t_prop.BoldOn() + t_prop.ShadowOn() + + self._LevelMapper = mapper + + actor = vtk.vtkActor2D() + actor.SetMapper(mapper) + actor.SetLayerNumber(1) + actor.GetPositionCoordinate().SetValue(4,22) + actor.GetProperty().SetColor(1,1,0.5) + actor.SetVisibility(0) + imager.AddActor2D(actor) + + self._LevelActor = actor + + mapper = vtk.vtkTextMapper() + mapper.SetInput("none") + t_prop = mapper.GetTextProperty() + t_prop.SetFontFamilyToTimes() + t_prop.SetFontSize(18) + t_prop.BoldOn() + t_prop.ShadowOn() + + self._WindowMapper = mapper + + actor = vtk.vtkActor2D() + actor.SetMapper(mapper) + actor.SetLayerNumber(1) + actor.GetPositionCoordinate().SetValue(4,4) + actor.GetProperty().SetColor(1,1,0.5) + actor.SetVisibility(0) + imager.AddActor2D(actor) + + self._WindowActor = actor + + self._LastX = 0 + self._LastY = 0 + self._OldFocus = 0 + self._InExpose = 0 + + # bindings + # window level + self.bind("<ButtonPress-1>", + lambda e,s=self: s.StartWindowLevelInteraction(e.x,e.y)) + self.bind("<B1-Motion>", + lambda e,s=self: s.UpdateWindowLevelInteraction(e.x,e.y)) + self.bind("<ButtonRelease-1>", + lambda e,s=self: s.EndWindowLevelInteraction()) + + # Get the value + self.bind("<ButtonPress-3>", + lambda e,s=self: s.StartQueryInteraction(e.x,e.y)) + self.bind("<B3-Motion>", + lambda e,s=self: s.UpdateQueryInteraction(e.x,e.y)) + self.bind("<ButtonRelease-3>", + lambda e,s=self: s.EndQueryInteraction()) + + self.bind("<Expose>", + lambda e,s=self: s.ExposeTkImageViewer()) + self.bind("<Enter>", + lambda e,s=self: s.EnterTkViewer()) + self.bind("<Leave>", + lambda e,s=self: s.LeaveTkViewer()) + self.bind("<KeyPress-e>", + lambda e,s=self: s.quit()) + self.bind("<KeyPress-r>", + lambda e,s=self: s.ResetTkImageViewer()) + + def GetImageViewer(self): + return self._ImageViewer + + def Render(self): + self._ImageViewer.Render() + + def _GrabFocus(self): + self._OldFocus=self.focus_get() + self.focus() + + def EnterTkViewer(self): + if self._FocusOnEnter: + self._GrabFocus() + + def LeaveTkViewer(self): + if self._FocusOnEnter and (self._OldFocus != None): + self._OldFocus.focus() + + def ExposeTkImageViewer(self): + if (self._InExpose == 0): + self._InExpose = 1 + self.update() + self._ImageViewer.Render() + self._InExpose = 0 + + def StartWindowLevelInteraction(self,x,y): + if not self._FocusOnEnter: + self._GrabFocus() + viewer = self._ImageViewer + self._LastX = x + self._LastY = y + self._Window = float(viewer.GetColorWindow()) + self._Level = float(viewer.GetColorLevel()) + + # make the window level text visible + self._LevelActor.SetVisibility(1) + self._WindowActor.SetVisibility(1) + + self.UpdateWindowLevelInteraction(x,y) + + def EndWindowLevelInteraction(self): + # make the window level text invisible + self._LevelActor.SetVisibility(0) + self._WindowActor.SetVisibility(0) + self.Render() + + def UpdateWindowLevelInteraction(self,x,y): + # compute normalized delta + dx = 4.0*(x - self._LastX)/self.winfo_width()*self._Window + dy = 4.0*(self._LastY - y)/self.winfo_height()*self._Level + + # abs so that direction does not flip + if (self._Window < 0.0): + dx = -dx + if (self._Level < 0.0): + dy = -dy + + # compute new window level + window = self._Window + dx + if (window < 0.0): + level = self._Level + dy + else: + level = self._Level - dy + + viewer = self._ImageViewer + viewer.SetColorWindow(window) + viewer.SetColorLevel(level) + + self._WindowMapper.SetInput("Window: %g" % window) + self._LevelMapper.SetInput("Level: %g" % level) + + self.Render() + + + def ResetTkImageViewer(self): + # Reset: Set window level to show all values + viewer = self._ImageViewer + input = viewer.GetInput() + if (input == None): + return + + # Get the extent in viewer + z = viewer.GetZSlice() + + input.SetUpdateExtent(-99999,99999,-99999,99999,z,z) + input.Update() + + (low,high) = input.GetScalarRange() + + viewer.SetColorWindow(high - low) + viewer.SetColorLevel((high + low) * 0.5) + + self.Render() + + def StartQueryInteraction(self,x,y): + if not self._FocusOnEnter: + self._GrabFocus() + # Query PixleValue stuff + self._WindowActor.SetVisibility(1) + self.UpdateQueryInteraction(x,y) + + def EndQueryInteraction(self): + self._WindowActor.SetVisibility(0) + self.Render() + + def UpdateQueryInteraction(self,x,y): + viewer = self._ImageViewer + input = viewer.GetInput() + z = viewer.GetZSlice() + + # y is flipped upside down + y = self.winfo_height() - y + + # make sure point is in the whole extent of the image. + (xMin,xMax,yMin,yMax,zMin,zMax) = input.GetWholeExtent() + if (x < xMin or x > xMax or y < yMin or \ + y > yMax or z < zMin or z > zMax): + return + + input.SetUpdateExtent(x,x,y,y,z,z) + input.Update() + numComps = input.GetNumberOfScalarComponents() + text = "" + for i in xrange(numComps): + val = input.GetScalarComponentAsDouble(x,y,z,i) + text = "%s %.1f" % (text,val) + + self._WindowMapper.SetInput("(%d, %d): %s" % (x,y,text)) + + self.Render() + +#----------------------------------------------------------------------------- +# an example of how to use this widget +if __name__ == "__main__": + canvas = vtk.vtkImageCanvasSource2D() + canvas.SetNumberOfScalarComponents(3) + canvas.SetScalarType(3) + canvas.SetExtent(0,511,0,511,0,0) + canvas.SetDrawColor(100,100,0) + canvas.FillBox(0,511,0,511) + canvas.SetDrawColor(200,0,200) + canvas.FillBox(32,511,100,500) + canvas.SetDrawColor(100,0,0) + canvas.FillTube(550,20,30,400,5) + canvas.SetDrawColor(255,255,255) + canvas.DrawSegment3D(10,20,0,90,510,0) + canvas.SetDrawColor(200,50,50) + canvas.DrawSegment3D(510,90,0,10,20,0) + + # Check segment clipping + canvas.SetDrawColor(0,200,0) + canvas.DrawSegment(-10,30,30,-10) + canvas.DrawSegment(-10,481,30,521) + canvas.DrawSegment(481,-10,521,30) + canvas.DrawSegment(481,521,521,481) + + # Check Filling a triangle + canvas.SetDrawColor(20,200,200) + canvas.FillTriangle(-100,100,190,150,40,300) + + # Check drawing a circle + canvas.SetDrawColor(250,250,10) + canvas.DrawCircle(350,350,200.0) + + # Check drawing a point + canvas.SetDrawColor(250,250,250) + canvas.DrawPoint(350,350) + canvas.DrawPoint(350,550) + + # Test filling functionality + canvas.SetDrawColor(55,0,0) + canvas.DrawCircle(450,350,80.0) + canvas.SetDrawColor(100,255,100) + canvas.FillPixel(450,350) + + # Create the GUI: two renderer widgets and a quit button + + frame = Tkinter.Frame() + + widget = vtkTkImageViewerWidget(frame,width=512,height=512,double=1) + viewer = widget.GetImageViewer() + viewer.SetInput(canvas.GetOutput()) + viewer.SetColorWindow(256) + viewer.SetColorLevel(127.5) + + button = Tkinter.Button(frame,text="Quit",command=frame.quit) + + widget.pack(side='top',padx=3,pady=3,fill='both',expand='t') + frame.pack(fill='both',expand='t') + button.pack(fill='x') + + frame.mainloop() + diff --git a/Wrapping/Python/vtk/tk/vtkTkPhotoImage.py b/Wrapping/Python/vtk/tk/vtkTkPhotoImage.py new file mode 100644 index 0000000..85eb541 --- /dev/null +++ b/Wrapping/Python/vtk/tk/vtkTkPhotoImage.py @@ -0,0 +1,24 @@ +""" +A subclass of Tkinter.PhotoImage that connects a +vtkImageData to a photo widget. + +Created by Daniel Blezek, August 2002 +""" + +import Tkinter + +from vtkLoadPythonTkWidgets import vtkLoadPythonTkWidgets + +class vtkTkPhotoImage ( Tkinter.PhotoImage ): + """ + A subclass of PhotoImage with helper functions + for displaying vtkImageData + """ + def __init__ ( self, **kw ): + # Caller the superclass + Tkinter.PhotoImage.__init__ ( self, kw ) + vtkLoadPythonTkWidgets ( self.tk ) + def PutImageSlice ( self, image, z, orientation='transverse', window=256, level=128 ): + t = image.__this__ + s = 'vtkImageDataToTkPhoto %s %s %d %s %d %d' % ( t[:-2], self.name, z, orientation, window, level ) + self.tk.eval ( s ) diff --git a/Wrapping/Python/vtk/tk/vtkTkRenderWidget.py b/Wrapping/Python/vtk/tk/vtkTkRenderWidget.py new file mode 100644 index 0000000..91f3362 --- /dev/null +++ b/Wrapping/Python/vtk/tk/vtkTkRenderWidget.py @@ -0,0 +1,467 @@ +""" +A simple vtkTkRenderWidget for Tkinter. + +Created by David Gobbi, April 1999 + +May ??, 1999 - Modifications peformed by Heather Drury, + to rewrite _pan to match method in TkInteractor.tcl +May 11, 1999 - Major rewrite by David Gobbi to make the + interactor bindings identical to the TkInteractor.tcl + bindings. +July 14, 1999 - Added modification by Ken Martin for VTK 2.4, to + use vtk widgets instead of Togl. +Aug 29, 1999 - Renamed file to vtkRenderWidget.py +Nov 14, 1999 - Added support for keyword 'rw' +Mar 23, 2000 - Extensive but backwards compatible changes, + improved documentation +""" + +""" +A few important notes: + +This class is meant to be used as a base-class widget for +doing VTK rendering in Python. + +In VTK (and C++) there is a very important distinction between +public ivars (attributes in pythonspeak), protected ivars, and +private ivars. When you write a python class that you want +to 'look and feel' like a VTK class, you should follow these rules. + +1) Attributes should never be public. Attributes should always be + either protected (prefixed with a single underscore) or private + (prefixed with a double underscore). You can provide access to + attributes through public Set/Get methods (same as VTK). + +2) Use a single underscore to denote a protected attribute, e.g. + self._RenderWindow is protected (can be accessed from this + class or a derived class). + +3) Use a double underscore to denote a private attribute, e.g. + self.__InExpose cannot be accessed outside of this class. + +All attributes should be 'declared' in the __init__() function +i.e. set to some initial value. Don't forget that 'None' means +'NULL' - the python/vtk wrappers guarantee their equivalence. +""" + +import Tkinter +import math, os, sys +import vtk + +from vtkLoadPythonTkWidgets import vtkLoadPythonTkWidgets + +class vtkTkRenderWidget(Tkinter.Widget): + """ + A vtkTkRenderWidget for Python. + + Use GetRenderWindow() to get the vtkRenderWindow. + + Create with the keyword stereo=1 in order to generate a + stereo-capable window. + + Create with the keyword focus_on_enter=1 to enable + focus-follows-mouse. The default is for a click-to-focus mode. + """ + def __init__(self, master, cnf={}, **kw): + """ + Constructor. + + Keyword arguments: + + rw -- Use passed render window instead of creating a new one. + + stereo -- If True, generate a stereo-capable window. + Defaults to False. + + focus_on_enter -- If True, use a focus-follows-mouse mode. + Defaults to False where the widget will use a click-to-focus + mode. + """ + # load the necessary extensions into tk + vtkLoadPythonTkWidgets(master.tk) + + try: # check to see if a render window was specified + renderWindow = kw['rw'] + except KeyError: + renderWindow = vtk.vtkRenderWindow() + + try: # was a stereo rendering context requested? + if kw['stereo']: + renderWindow.StereoCapableWindowOn() + del kw['stereo'] + except KeyError: + pass + + # check if focus should follow mouse + if kw.get('focus_on_enter'): + self._FocusOnEnter = 1 + del kw['focus_on_enter'] + else: + self._FocusOnEnter = 0 + + kw['rw'] = renderWindow.GetAddressAsString("vtkRenderWindow") + Tkinter.Widget.__init__(self, master, 'vtkTkRenderWidget', cnf, kw) + + self._CurrentRenderer = None + self._CurrentCamera = None + self._CurrentZoom = 1.0 + self._CurrentLight = None + + self._ViewportCenterX = 0 + self._ViewportCenterY = 0 + + self._Picker = vtk.vtkCellPicker() + self._PickedAssembly = None + self._PickedProperty = vtk.vtkProperty() + self._PickedProperty.SetColor(1,0,0) + self._PrePickedProperty = None + + self._OldFocus = None + + # used by the LOD actors + self._DesiredUpdateRate = 15 + self._StillUpdateRate = 0.0001 + + # these record the previous mouse position + self._LastX = 0 + self._LastY = 0 + + # private attributes + self.__InExpose = 0 + + # create the Tk bindings + self.BindTkRenderWidget() + + def __getattr__(self,attr): + # because the tk part of vtkTkRenderWidget must have + # the only remaining reference to the RenderWindow when + # it is destroyed, we can't actually store the RenderWindow + # as an attribute but instead have to get it from the tk-side + if attr == '_RenderWindow': + return self.GetRenderWindow() + raise AttributeError, self.__class__.__name__ + \ + " has no attribute named " + attr + + def BindTkRenderWidget(self): + """ + Bind some default actions. + """ + self.bind("<ButtonPress>", + lambda e,s=self: s.StartMotion(e.x,e.y)) + self.bind("<ButtonRelease>", + lambda e,s=self: s.EndMotion(e.x,e.y)) + self.bind("<B1-Motion>", + lambda e,s=self: s.Rotate(e.x,e.y)) + self.bind("<B2-Motion>", + lambda e,s=self: s.Pan(e.x,e.y)) + self.bind("<B3-Motion>", + lambda e,s=self: s.Zoom(e.x,e.y)) + self.bind("<Shift-B1-Motion>", + lambda e,s=self: s.Pan(e.x,e.y)) + self.bind("<KeyPress-r>", + lambda e,s=self: s.Reset(e.x,e.y)) + self.bind("<KeyPress-u>", + lambda e,s=self: s.deiconify()) + self.bind("<KeyPress-w>", + lambda e,s=self: s.Wireframe()) + self.bind("<KeyPress-s>", + lambda e,s=self: s.Surface()) + self.bind("<KeyPress-p>", + lambda e,s=self: s.PickActor(e.x,e.y)) + if self._FocusOnEnter: + self.bind("<Enter>", + lambda e,s=self: s.Enter(e.x,e.y)) + self.bind("<Leave>", + lambda e,s=self: s.Leave(e.x,e.y)) + else: + self.bind("<ButtonPress>", + lambda e,s=self: s.Enter(e.x,e.y)) + self.bind("<Expose>", + lambda e,s=self: s.Expose()) + + def GetZoomFactor(self): + return self._CurrentZoom + + def SetDesiredUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._DesiredUpdateRate = rate + + def GetDesiredUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._DesiredUpdateRate + + def SetStillUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._StillUpdateRate = rate + + def GetStillUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._StillUpdateRate + + def GetRenderWindow(self): + addr = self.tk.call(self._w, 'GetRenderWindow')[5:] + return vtk.vtkRenderWindow('_%s_vtkRenderWindow_p' % addr) + + def GetPicker(self): + return self._Picker + + def Expose(self): + if (not self.__InExpose): + self.__InExpose = 1 + self.update() + self._RenderWindow.Render() + self.__InExpose = 0 + + def Render(self): + if (self._CurrentLight): + light = self._CurrentLight + light.SetPosition(self._CurrentCamera.GetPosition()) + light.SetFocalPoint(self._CurrentCamera.GetFocalPoint()) + + self._RenderWindow.Render() + + def UpdateRenderer(self,x,y): + """ + UpdateRenderer will identify the renderer under the mouse and set + up _CurrentRenderer, _CurrentCamera, and _CurrentLight. + """ + windowX = self.winfo_width() + windowY = self.winfo_height() + + renderers = self._RenderWindow.GetRenderers() + numRenderers = renderers.GetNumberOfItems() + + self._CurrentRenderer = None + renderers.InitTraversal() + for i in range(0,numRenderers): + renderer = renderers.GetNextItem() + vx,vy = (0,0) + if (windowX > 1): + vx = float(x)/(windowX-1) + if (windowY > 1): + vy = (windowY-float(y)-1)/(windowY-1) + (vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport() + + if (vx >= vpxmin and vx <= vpxmax and + vy >= vpymin and vy <= vpymax): + self._CurrentRenderer = renderer + self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\ + +vpxmin + self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\ + +vpymin + self._CurrentCamera = self._CurrentRenderer.GetActiveCamera() + lights = self._CurrentRenderer.GetLights() + lights.InitTraversal() + self._CurrentLight = lights.GetNextItem() + break + + self._LastX = x + self._LastY = y + + def GetCurrentRenderer(self): + return self._CurrentRenderer + + def Enter(self,x,y): + self._OldFocus=self.focus_get() + self.focus() + self.StartMotion(x, y) + + def Leave(self,x,y): + if (self._OldFocus != None): + self._OldFocus.focus() + + def StartMotion(self,x,y): + self.GetRenderWindow().SetDesiredUpdateRate(self._DesiredUpdateRate) + self.UpdateRenderer(x,y) + + def EndMotion(self,x,y): + self.GetRenderWindow().SetDesiredUpdateRate(self._StillUpdateRate) + if self._CurrentRenderer: + self.Render() + + def Rotate(self,x,y): + if self._CurrentRenderer: + + self._CurrentCamera.Azimuth(self._LastX - x) + self._CurrentCamera.Elevation(y - self._LastY) + self._CurrentCamera.OrthogonalizeViewUp() + + self._LastX = x + self._LastY = y + + self._CurrentRenderer.ResetCameraClippingRange() + self.Render() + + def Pan(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + (pPoint0,pPoint1,pPoint2) = camera.GetPosition() + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + + if (camera.GetParallelProjection()): + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetFocalPoint(fx,fy,fz) + + renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetPosition(fx,fy,fz) + + else: + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + # Specify a point location in world coordinates + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + # Convert world point coordinates to display coordinates + dPoint = renderer.GetDisplayPoint() + focalDepth = dPoint[2] + + aPoint0 = self._ViewportCenterX + (x - self._LastX) + aPoint1 = self._ViewportCenterY - (y - self._LastY) + + renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth) + renderer.DisplayToWorld() + + (rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint() + if (rPoint3 != 0.0): + rPoint0 = rPoint0/rPoint3 + rPoint1 = rPoint1/rPoint3 + rPoint2 = rPoint2/rPoint3 + + camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0, + (fPoint1 - rPoint1) + fPoint1, + (fPoint2 - rPoint2) + fPoint2) + + camera.SetPosition((fPoint0 - rPoint0) + pPoint0, + (fPoint1 - rPoint1) + pPoint1, + (fPoint2 - rPoint2) + pPoint2) + + self._LastX = x + self._LastY = y + + self.Render() + + def Zoom(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + + zoomFactor = math.pow(1.02,(0.5*(self._LastY - y))) + self._CurrentZoom = self._CurrentZoom * zoomFactor + + if camera.GetParallelProjection(): + parallelScale = camera.GetParallelScale()/zoomFactor + camera.SetParallelScale(parallelScale) + else: + camera.Dolly(zoomFactor) + renderer.ResetCameraClippingRange() + + self._LastX = x + self._LastY = y + + self.Render() + + def Reset(self,x,y): + if self._CurrentRenderer: + self._CurrentRenderer.ResetCamera() + + self.Render() + + def Wireframe(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToWireframe() + + self.Render() + + def Surface(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToSurface() + + self.Render() + + def PickActor(self,x,y): + if self._CurrentRenderer: + + renderer = self._CurrentRenderer + picker = self._Picker + + windowY = self.winfo_height() + picker.Pick(x,(windowY - y - 1),0.0,renderer) + assembly = picker.GetAssembly() + + if (self._PickedAssembly != None and + self._PrePickedProperty != None): + self._PickedAssembly.SetProperty(self._PrePickedProperty) + # release hold of the property + self._PrePickedProperty.UnRegister(self._PrePickedProperty) + self._PrePickedProperty = None + + if (assembly != None): + self._PickedAssembly = assembly + self._PrePickedProperty = self._PickedAssembly.GetProperty() + # hold onto the property + self._PrePickedProperty.Register(self._PrePickedProperty) + self._PickedAssembly.SetProperty(self._PickedProperty) + + self.Render() + +#---------------------------------------------------------------------------- +def vtkRenderWidgetConeExample(): + """Like it says, just a simple example + """ + # create root window + root = Tkinter.Tk() + + # create vtkTkRenderWidget + pane = vtkTkRenderWidget(root,width=300,height=300) + + ren = vtk.vtkRenderer() + pane.GetRenderWindow().AddRenderer(ren) + + cone = vtk.vtkConeSource() + cone.SetResolution(8) + + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + + ren.AddActor(coneActor) + + # pack the pane into the tk root + pane.pack() + + # start the tk mainloop + root.mainloop() + +if __name__ == "__main__": + vtkRenderWidgetConeExample() + diff --git a/Wrapping/Python/vtk/tk/vtkTkRenderWindowInteractor.py b/Wrapping/Python/vtk/tk/vtkTkRenderWindowInteractor.py new file mode 100644 index 0000000..2cbfba9 --- /dev/null +++ b/Wrapping/Python/vtk/tk/vtkTkRenderWindowInteractor.py @@ -0,0 +1,395 @@ +""" + +A fully functional VTK widget for Tkinter that uses +vtkGenericRenderWindowInteractor. The widget is called +vtkTkRenderWindowInteractor. The initialization part of this code is +similar to that of the vtkTkRenderWidget. + +Created by Prabhu Ramachandran, April 2002 + +""" + +import Tkinter +import math, os, sys +import vtk + +from vtkLoadPythonTkWidgets import vtkLoadPythonTkWidgets + +class vtkTkRenderWindowInteractor(Tkinter.Widget): + """ A vtkTkRenderWidndowInteractor for Python. + + Use GetRenderWindow() to get the vtkRenderWindow. + + Create with the keyword stereo=1 in order to generate a + stereo-capable window. + + Create with the keyword focus_on_enter=1 to enable + focus-follows-mouse. The default is for a click-to-focus mode. + + __getattr__ is used to make the widget also behave like a + vtkGenericRenderWindowInteractor. + """ + def __init__(self, master, cnf={}, **kw): + """ + Constructor. + + Keyword arguments: + + rw -- Use passed render window instead of creating a new one. + + stereo -- If True, generate a stereo-capable window. + Defaults to False. + + focus_on_enter -- If True, use a focus-follows-mouse mode. + Defaults to False where the widget will use a click-to-focus + mode. + """ + # load the necessary extensions into tk + vtkLoadPythonTkWidgets(master.tk) + + try: # check to see if a render window was specified + renderWindow = kw['rw'] + except KeyError: + renderWindow = vtk.vtkRenderWindow() + + try: # was a stereo rendering context requested? + if kw['stereo']: + renderWindow.StereoCapableWindowOn() + del kw['stereo'] + except KeyError: + pass + + # check if focus should follow mouse + if kw.get('focus_on_enter'): + self._FocusOnEnter = 1 + del kw['focus_on_enter'] + else: + self._FocusOnEnter = 0 + + kw['rw'] = renderWindow.GetAddressAsString("vtkRenderWindow") + Tkinter.Widget.__init__(self, master, 'vtkTkRenderWidget', cnf, kw) + + self._Iren = vtk.vtkGenericRenderWindowInteractor() + self._Iren.SetRenderWindow(self._RenderWindow) + + self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer) + self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer) + + self._OldFocus = None + + # private attributes + self.__InExpose = 0 + + # create the Tk bindings + self.BindEvents() + #self.tk_focusFollowsMouse() + + def __getattr__(self, attr): + # because the tk part of vtkTkRenderWidget must have + # the only remaining reference to the RenderWindow when + # it is destroyed, we can't actually store the RenderWindow + # as an attribute but instead have to get it from the tk-side + if attr == '__vtk__': + return lambda t=self._Iren: t + elif attr == '_RenderWindow': + return self.GetRenderWindow() + elif hasattr(self._Iren, attr): + return getattr(self._Iren, attr) + else: + raise AttributeError, self.__class__.__name__ + \ + " has no attribute named " + attr + + def BindEvents(self): + """ Bind all the events. """ + self.bind("<Motion>", + lambda e, s=self: s.MouseMoveEvent(e, 0, 0)) + self.bind("<Control-Motion>", + lambda e, s=self: s.MouseMoveEvent(e, 1, 0)) + self.bind("<Shift-Motion>", + lambda e, s=self: s.MouseMoveEvent(e, 1, 1)) + self.bind("<Control-Shift-Motion>", + lambda e, s=self: s.MouseMoveEvent(e, 0, 1)) + + # Left Button + self.bind("<ButtonPress-1>", + lambda e, s=self: s.LeftButtonPressEvent(e, 0, 0)) + self.bind("<Control-ButtonPress-1>", + lambda e, s=self: s.LeftButtonPressEvent(e, 1, 0)) + self.bind("<Shift-ButtonPress-1>", + lambda e, s=self: s.LeftButtonPressEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonPress-1>", + lambda e, s=self: s.LeftButtonPressEvent(e, 1, 1)) + self.bind("<ButtonRelease-1>", + lambda e, s=self: s.LeftButtonReleaseEvent(e, 0, 0)) + self.bind("<Control-ButtonRelease-1>", + lambda e, s=self: s.LeftButtonReleaseEvent(e, 1, 0)) + self.bind("<Shift-ButtonRelease-1>", + lambda e, s=self: s.LeftButtonReleaseEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonRelease-1>", + lambda e, s=self: s.LeftButtonReleaseEvent(e, 1, 1)) + + # Middle Button + self.bind("<ButtonPress-2>", + lambda e, s=self: s.MiddleButtonPressEvent(e, 0, 0)) + self.bind("<Control-ButtonPress-2>", + lambda e, s=self: s.MiddleButtonPressEvent(e, 1, 0)) + self.bind("<Shift-ButtonPress-2>", + lambda e, s=self: s.MiddleButtonPressEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonPress-2>", + lambda e, s=self: s.MiddleButtonPressEvent(e, 1, 1)) + self.bind("<ButtonRelease-2>", + lambda e, s=self: s.MiddleButtonReleaseEvent(e, 0, 0)) + self.bind("<Control-ButtonRelease-2>", + lambda e, s=self: s.MiddleButtonReleaseEvent(e, 1, 0)) + self.bind("<Shift-ButtonRelease-2>", + lambda e, s=self: s.MiddleButtonReleaseEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonRelease-2>", + lambda e, s=self: s.MiddleButtonReleaseEvent(e, 1, 1)) + + # Right Button + self.bind("<ButtonPress-3>", + lambda e, s=self: s.RightButtonPressEvent(e, 0, 0)) + self.bind("<Control-ButtonPress-3>", + lambda e, s=self: s.RightButtonPressEvent(e, 1, 0)) + self.bind("<Shift-ButtonPress-3>", + lambda e, s=self: s.RightButtonPressEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonPress-3>", + lambda e, s=self: s.RightButtonPressEvent(e, 1, 1)) + self.bind("<ButtonRelease-3>", + lambda e, s=self: s.RightButtonReleaseEvent(e, 0, 0)) + self.bind("<Control-ButtonRelease-3>", + lambda e, s=self: s.RightButtonReleaseEvent(e, 1, 0)) + self.bind("<Shift-ButtonRelease-3>", + lambda e, s=self: s.RightButtonReleaseEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonRelease-3>", + lambda e, s=self: s.RightButtonReleaseEvent(e, 1, 1)) + + if sys.platform == 'win32': + self.bind("<MouseWheel>", + lambda e, s=self: s.MouseWheelEvent(e, 0, 0)) + self.bind("<Control-MouseWheel>", + lambda e, s=self: s.MouseWheelEvent(e, 1, 0)) + self.bind("<Shift-MouseWheel>", + lambda e, s=self: s.MouseWheelEvent(e, 0, 1)) + self.bind("<Control-Shift-MouseWheel>", + lambda e, s=self: s.MouseWheelEvent(e, 1, 1)) + else: + # Mouse wheel forward event + self.bind("<ButtonPress-4>", + lambda e, s=self: s.MouseWheelForwardEvent(e, 0, 0)) + self.bind("<Control-ButtonPress-4>", + lambda e, s=self: s.MouseWheelForwardEvent(e, 1, 0)) + self.bind("<Shift-ButtonPress-4>", + lambda e, s=self: s.MouseWheelForwardEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonPress-4>", + lambda e, s=self: s.MouseWheelForwardEvent(e, 1, 1)) + + # Mouse wheel backward event + self.bind("<ButtonPress-5>", + lambda e, s=self: s.MouseWheelBackwardEvent(e, 0, 0)) + self.bind("<Control-ButtonPress-5>", + lambda e, s=self: s.MouseWheelBackwardEvent(e, 1, 0)) + self.bind("<Shift-ButtonPress-5>", + lambda e, s=self: s.MouseWheelBackwardEvent(e, 0, 1)) + self.bind("<Control-Shift-ButtonPress-5>", + lambda e, s=self: s.MouseWheelBackwardEvent(e, 1, 1)) + + # Key related events + self.bind("<KeyPress>", + lambda e, s=self: s.KeyPressEvent(e, 0, 0)) + self.bind("<Control-KeyPress>", + lambda e, s=self: s.KeyPressEvent(e, 1, 0)) + self.bind("<Shift-KeyPress>", + lambda e, s=self: s.KeyPressEvent(e, 0, 1)) + self.bind("<Control-Shift-KeyPress>", + lambda e, s=self: s.KeyPressEvent(e, 1, 1)) + + self.bind("<KeyRelease>", + lambda e, s=self: s.KeyReleaseEvent(e, 0, 0)) + self.bind("<Control-KeyRelease>", + lambda e, s=self: s.KeyReleaseEvent(e, 1, 0)) + self.bind("<Shift-KeyRelease>", + lambda e, s=self: s.KeyReleaseEvent(e, 0, 1)) + self.bind("<Control-Shift-KeyRelease>", + lambda e, s=self: s.KeyReleaseEvent(e, 1, 1)) + + self.bind("<Enter>", + lambda e, s=self: s.EnterEvent(e, 0, 0)) + self.bind("<Control-Enter>", + lambda e, s=self: s.EnterEvent(e, 1, 0)) + self.bind("<Shift-Enter>", + lambda e, s=self: s.EnterEvent(e, 0, 1)) + self.bind("<Control-Shift-Enter>", + lambda e, s=self: s.EnterEvent(e, 1, 1)) + self.bind("<Leave>", + lambda e, s=self: s.LeaveEvent(e, 0, 0)) + self.bind("<Control-Leave>", + lambda e, s=self: s.LeaveEvent(e, 1, 0)) + self.bind("<Shift-Leave>", + lambda e, s=self: s.LeaveEvent(e, 0, 1)) + self.bind("<Control-Shift-Leave>", + lambda e, s=self: s.LeaveEvent(e, 1, 1)) + + self.bind("<Configure>", self.ConfigureEvent) + self.bind("<Expose>",lambda e,s=self: s.ExposeEvent()) + + def CreateTimer(self, obj, evt): + self.after(10, self._Iren.TimerEvent) + + def DestroyTimer(self, obj, event): + """The timer is a one shot timer so will expire automatically.""" + return 1 + + def _GrabFocus(self, enter=0): + self._OldFocus=self.focus_get() + self.focus() + + def MouseMoveEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.MouseMoveEvent() + + def LeftButtonPressEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.LeftButtonPressEvent() + if not self._FocusOnEnter: + self._GrabFocus() + + def LeftButtonReleaseEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.LeftButtonReleaseEvent() + + def MiddleButtonPressEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.MiddleButtonPressEvent() + if not self._FocusOnEnter: + self._GrabFocus() + + def MiddleButtonReleaseEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.MiddleButtonReleaseEvent() + + def RightButtonPressEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.RightButtonPressEvent() + if not self._FocusOnEnter: + self._GrabFocus() + + def RightButtonReleaseEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.RightButtonReleaseEvent() + + def MouseWheelEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + if event.delta > 0: + self._Iren.MouseWheelForwardEvent() + else: + self._Iren.MouseWheelBackwardEvent() + + def MouseWheelForwardEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.MouseWheelForwardEvent() + + def MouseWheelBackwardEvent(self, event, ctrl, shift): + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, chr(0), 0, None) + self._Iren.MouseWheelBackwardEvent() + + def KeyPressEvent(self, event, ctrl, shift): + key = chr(0) + if event.keysym_num < 256: + key = chr(event.keysym_num) + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, key, 0, event.keysym) + self._Iren.KeyPressEvent() + self._Iren.CharEvent() + + def KeyReleaseEvent(self, event, ctrl, shift): + key = chr(0) + if event.keysym_num < 256: + key = chr(event.keysym_num) + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, + shift, key, 0, event.keysym) + self._Iren.KeyReleaseEvent() + + def ConfigureEvent(self, event): + self._Iren.SetSize(event.width, event.height) + self._Iren.ConfigureEvent() + + def EnterEvent(self, event, ctrl, shift): + if self._FocusOnEnter: + self._GrabFocus() + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, shift, + chr(0), 0, None) + self._Iren.EnterEvent() + + def LeaveEvent(self, event, ctrl, shift): + if self._FocusOnEnter and (self._OldFocus != None): + self._OldFocus.focus() + self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, shift, + chr(0), 0, None) + self._Iren.LeaveEvent() + + def ExposeEvent(self): + if (not self.__InExpose): + self.__InExpose = 1 + self.update() + self._RenderWindow.Render() + self.__InExpose = 0 + + def GetRenderWindow(self): + addr = self.tk.call(self._w, 'GetRenderWindow')[5:] + return vtk.vtkRenderWindow('_%s_vtkRenderWindow_p' % addr) + + def Render(self): + self._RenderWindow.Render() + + +#---------------------------------------------------------------------------- +def vtkRenderWindowInteractorConeExample(): + """Like it says, just a simple example + """ + # create root window + root = Tkinter.Tk() + + # create vtkTkRenderWidget + pane = vtkTkRenderWindowInteractor(root, width=300, height=300) + pane.Initialize() + + def quit(obj=root): + obj.quit() + + pane.AddObserver("ExitEvent", lambda o,e,q=quit: q()) + + ren = vtk.vtkRenderer() + pane.GetRenderWindow().AddRenderer(ren) + + cone = vtk.vtkConeSource() + cone.SetResolution(8) + + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + + ren.AddActor(coneActor) + + # pack the pane into the tk root + pane.pack(fill='both', expand=1) + pane.Start() + + # start the tk mainloop + root.mainloop() + +if __name__ == "__main__": + vtkRenderWindowInteractorConeExample() + diff --git a/Wrapping/Python/vtk/util/.cvsignore b/Wrapping/Python/vtk/util/.cvsignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/Wrapping/Python/vtk/util/.cvsignore @@ -0,0 +1 @@ +*.pyc diff --git a/Wrapping/Python/vtk/util/__init__.py b/Wrapping/Python/vtk/util/__init__.py new file mode 100644 index 0000000..95a9649 --- /dev/null +++ b/Wrapping/Python/vtk/util/__init__.py @@ -0,0 +1,4 @@ +"""Utility modules for the VTK-Python wrappers.""" + +__all__ = ['colors', 'misc', 'vtkConstants', 'vtkImageExportToArray', + 'vtkImageImportFromArray', 'vtkMethodParser'] diff --git a/Wrapping/Python/vtk/util/colors.py b/Wrapping/Python/vtk/util/colors.py new file mode 100644 index 0000000..57cd0ac --- /dev/null +++ b/Wrapping/Python/vtk/util/colors.py @@ -0,0 +1,216 @@ +# This module defines many standard colors that should be useful. +# These colors should be exactly the same as the ones defined in +# colors.tcl. + +# Whites +antique_white = (0.9804, 0.9216, 0.8431) +azure = (0.9412, 1.0000, 1.0000) +bisque = (1.0000, 0.8941, 0.7686) +blanched_almond = (1.0000, 0.9216, 0.8039) +cornsilk = (1.0000, 0.9725, 0.8627) +eggshell = (0.9900, 0.9000, 0.7900) +floral_white = (1.0000, 0.9804, 0.9412) +gainsboro = (0.8627, 0.8627, 0.8627) +ghost_white = (0.9725, 0.9725, 1.0000) +honeydew = (0.9412, 1.0000, 0.9412) +ivory = (1.0000, 1.0000, 0.9412) +lavender = (0.9020, 0.9020, 0.9804) +lavender_blush = (1.0000, 0.9412, 0.9608) +lemon_chiffon = (1.0000, 0.9804, 0.8039) +linen = (0.9804, 0.9412, 0.9020) +mint_cream = (0.9608, 1.0000, 0.9804) +misty_rose = (1.0000, 0.8941, 0.8824) +moccasin = (1.0000, 0.8941, 0.7098) +navajo_white = (1.0000, 0.8706, 0.6784) +old_lace = (0.9922, 0.9608, 0.9020) +papaya_whip = (1.0000, 0.9373, 0.8353) +peach_puff = (1.0000, 0.8549, 0.7255) +seashell = (1.0000, 0.9608, 0.9333) +snow = (1.0000, 0.9804, 0.9804) +thistle = (0.8471, 0.7490, 0.8471) +titanium_white = (0.9900, 1.0000, 0.9400) +wheat = (0.9608, 0.8706, 0.7020) +white = (1.0000, 1.0000, 1.0000) +white_smoke = (0.9608, 0.9608, 0.9608) +zinc_white = (0.9900, 0.9700, 1.0000) + +# Greys +cold_grey = (0.5000, 0.5400, 0.5300) +dim_grey = (0.4118, 0.4118, 0.4118) +grey = (0.7529, 0.7529, 0.7529) +light_grey = (0.8275, 0.8275, 0.8275) +slate_grey = (0.4392, 0.5020, 0.5647) +slate_grey_dark = (0.1843, 0.3098, 0.3098) +slate_grey_light = (0.4667, 0.5333, 0.6000) +warm_grey = (0.5000, 0.5000, 0.4100) + +# Blacks +black = (0.0000, 0.0000, 0.0000) +ivory_black = (0.1600, 0.1400, 0.1300) +lamp_black = (0.1800, 0.2800, 0.2300) + +# Reds +alizarin_crimson = (0.8900, 0.1500, 0.2100) +brick = (0.6100, 0.4000, 0.1200) +cadmium_red_deep = (0.8900, 0.0900, 0.0500) +coral = (1.0000, 0.4980, 0.3137) +coral_light = (0.9412, 0.5020, 0.5020) +deep_pink = (1.0000, 0.0784, 0.5765) +english_red = (0.8300, 0.2400, 0.1000) +firebrick = (0.6980, 0.1333, 0.1333) +geranium_lake = (0.8900, 0.0700, 0.1900) +hot_pink = (1.0000, 0.4118, 0.7059) +indian_red = (0.6900, 0.0900, 0.1200) +light_salmon = (1.0000, 0.6275, 0.4784) +madder_lake_deep = (0.8900, 0.1800, 0.1900) +maroon = (0.6902, 0.1882, 0.3765) +pink = (1.0000, 0.7529, 0.7961) +pink_light = (1.0000, 0.7137, 0.7569) +raspberry = (0.5300, 0.1500, 0.3400) +red = (1.0000, 0.0000, 0.0000) +rose_madder = (0.8900, 0.2100, 0.2200) +salmon = (0.9804, 0.5020, 0.4471) +tomato = (1.0000, 0.3882, 0.2784) +venetian_red = (0.8300, 0.1000, 0.1200) + +# Browns +beige = (0.6400, 0.5800, 0.5000) +brown = (0.5000, 0.1647, 0.1647) +brown_madder = (0.8600, 0.1600, 0.1600) +brown_ochre = (0.5300, 0.2600, 0.1200) +burlywood = (0.8706, 0.7216, 0.5294) +burnt_sienna = (0.5400, 0.2100, 0.0600) +burnt_umber = (0.5400, 0.2000, 0.1400) +chocolate = (0.8235, 0.4118, 0.1176) +deep_ochre = (0.4500, 0.2400, 0.1000) +flesh = (1.0000, 0.4900, 0.2500) +flesh_ochre = (1.0000, 0.3400, 0.1300) +gold_ochre = (0.7800, 0.4700, 0.1500) +greenish_umber = (1.0000, 0.2400, 0.0500) +khaki = (0.9412, 0.9020, 0.5490) +khaki_dark = (0.7412, 0.7176, 0.4196) +light_beige = (0.9608, 0.9608, 0.8627) +peru = (0.8039, 0.5216, 0.2471) +rosy_brown = (0.7373, 0.5608, 0.5608) +raw_sienna = (0.7800, 0.3800, 0.0800) +raw_umber = (0.4500, 0.2900, 0.0700) +sepia = (0.3700, 0.1500, 0.0700) +sienna = (0.6275, 0.3216, 0.1765) +saddle_brown = (0.5451, 0.2706, 0.0745) +sandy_brown = (0.9569, 0.6431, 0.3765) +tan = (0.8235, 0.7059, 0.5490) +van_dyke_brown = (0.3700, 0.1500, 0.0200) + +# Oranges +cadmium_orange = (1.0000, 0.3800, 0.0100) +cadmium_red_light = (1.0000, 0.0100, 0.0500) +carrot = (0.9300, 0.5700, 0.1300) +dark_orange = (1.0000, 0.5490, 0.0000) +mars_orange = (0.5900, 0.2700, 0.0800) +mars_yellow = (0.8900, 0.4400, 0.1000) +orange = (1.0000, 0.5000, 0.0000) +orange_red = (1.0000, 0.2706, 0.0000) +yellow_ochre = (0.8900, 0.5100, 0.0900) + +# Yellows +aureoline_yellow = (1.0000, 0.6600, 0.1400) +banana = (0.8900, 0.8100, 0.3400) +cadmium_lemon = (1.0000, 0.8900, 0.0100) +cadmium_yellow = (1.0000, 0.6000, 0.0700) +cadmium_yellow_light = (1.0000, 0.6900, 0.0600) +gold = (1.0000, 0.8431, 0.0000) +goldenrod = (0.8549, 0.6471, 0.1255) +goldenrod_dark = (0.7216, 0.5255, 0.0431) +goldenrod_light = (0.9804, 0.9804, 0.8235) +goldenrod_pale = (0.9333, 0.9098, 0.6667) +light_goldenrod = (0.9333, 0.8667, 0.5098) +melon = (0.8900, 0.6600, 0.4100) +naples_yellow_deep = (1.0000, 0.6600, 0.0700) +yellow = (1.0000, 1.0000, 0.0000) +yellow_light = (1.0000, 1.0000, 0.8784) + +# Greens +chartreuse = (0.4980, 1.0000, 0.0000) +chrome_oxide_green = (0.4000, 0.5000, 0.0800) +cinnabar_green = (0.3800, 0.7000, 0.1600) +cobalt_green = (0.2400, 0.5700, 0.2500) +emerald_green = (0.0000, 0.7900, 0.3400) +forest_green = (0.1333, 0.5451, 0.1333) +green = (0.0000, 1.0000, 0.0000) +green_dark = (0.0000, 0.3922, 0.0000) +green_pale = (0.5961, 0.9843, 0.5961) +green_yellow = (0.6784, 1.0000, 0.1843) +lawn_green = (0.4863, 0.9882, 0.0000) +lime_green = (0.1961, 0.8039, 0.1961) +mint = (0.7400, 0.9900, 0.7900) +olive = (0.2300, 0.3700, 0.1700) +olive_drab = (0.4196, 0.5569, 0.1373) +olive_green_dark = (0.3333, 0.4196, 0.1843) +permanent_green = (0.0400, 0.7900, 0.1700) +sap_green = (0.1900, 0.5000, 0.0800) +sea_green = (0.1804, 0.5451, 0.3412) +sea_green_dark = (0.5608, 0.7373, 0.5608) +sea_green_medium = (0.2353, 0.7020, 0.4431) +sea_green_light = (0.1255, 0.6980, 0.6667) +spring_green = (0.0000, 1.0000, 0.4980) +spring_green_medium = (0.0000, 0.9804, 0.6039) +terre_verte = (0.2200, 0.3700, 0.0600) +viridian_light = (0.4300, 1.0000, 0.4400) +yellow_green = (0.6039, 0.8039, 0.1961) + +# Cyans +aquamarine = (0.4980, 1.0000, 0.8314) +aquamarine_medium = (0.4000, 0.8039, 0.6667) +cyan = (0.0000, 1.0000, 1.0000) +cyan_white = (0.8784, 1.0000, 1.0000) +turquoise = (0.2510, 0.8784, 0.8157) +turquoise_dark = (0.0000, 0.8078, 0.8196) +turquoise_medium = (0.2824, 0.8196, 0.8000) +turquoise_pale = (0.6863, 0.9333, 0.9333) + +# Blues +alice_blue = (0.9412, 0.9725, 1.0000) +blue = (0.0000, 0.0000, 1.0000) +blue_light = (0.6784, 0.8471, 0.9020) +blue_medium = (0.0000, 0.0000, 0.8039) +cadet = (0.3725, 0.6196, 0.6275) +cobalt = (0.2400, 0.3500, 0.6700) +cornflower = (0.3922, 0.5843, 0.9294) +cerulean = (0.0200, 0.7200, 0.8000) +dodger_blue = (0.1176, 0.5647, 1.0000) +indigo = (0.0300, 0.1800, 0.3300) +manganese_blue = (0.0100, 0.6600, 0.6200) +midnight_blue = (0.0980, 0.0980, 0.4392) +navy = (0.0000, 0.0000, 0.5020) +peacock = (0.2000, 0.6300, 0.7900) +powder_blue = (0.6902, 0.8784, 0.9020) +royal_blue = (0.2549, 0.4118, 0.8824) +slate_blue = (0.4157, 0.3529, 0.8039) +slate_blue_dark = (0.2824, 0.2392, 0.5451) +slate_blue_light = (0.5176, 0.4392, 1.0000) +slate_blue_medium = (0.4824, 0.4078, 0.9333) +sky_blue = (0.5294, 0.8078, 0.9216) +sky_blue_deep = (0.0000, 0.7490, 1.0000) +sky_blue_light = (0.5294, 0.8078, 0.9804) +steel_blue = (0.2745, 0.5098, 0.7059) +steel_blue_light = (0.6902, 0.7686, 0.8706) +turquoise_blue = (0.0000, 0.7800, 0.5500) +ultramarine = (0.0700, 0.0400, 0.5600) + +# Magentas +blue_violet = (0.5412, 0.1686, 0.8863) +cobalt_violet_deep = (0.5700, 0.1300, 0.6200) +magenta = (1.0000, 0.0000, 1.0000) +orchid = (0.8549, 0.4392, 0.8392) +orchid_dark = (0.6000, 0.1961, 0.8000) +orchid_medium = (0.7294, 0.3333, 0.8275) +permanent_red_violet = (0.8600, 0.1500, 0.2700) +plum = (0.8667, 0.6275, 0.8667) +purple = (0.6275, 0.1255, 0.9412) +purple_medium = (0.5765, 0.4392, 0.8588) +ultramarine_violet = (0.3600, 0.1400, 0.4300) +violet = (0.5600, 0.3700, 0.6000) +violet_dark = (0.5804, 0.0000, 0.8275) +violet_red = (0.8157, 0.1255, 0.5647) +violet_red_medium = (0.7804, 0.0824, 0.5216) +violet_red_pale = (0.8588, 0.4392, 0.5765) diff --git a/Wrapping/Python/vtk/util/misc.py b/Wrapping/Python/vtk/util/misc.py new file mode 100644 index 0000000..2d97907 --- /dev/null +++ b/Wrapping/Python/vtk/util/misc.py @@ -0,0 +1,69 @@ +"""Miscellaneous functions and classes that dont fit into specific +categories.""" + +import sys, os, vtk + +#---------------------------------------------------------------------- +# the following functions are for the vtk regression testing and examples + +def vtkGetDataRoot(): + """vtkGetDataRoot() -- return vtk example data directory + """ + dataIndex=-1; + for i in range(0, len(sys.argv)): + if sys.argv[i] == '-D' and i < len(sys.argv)-1: + dataIndex = i+1 + + if dataIndex != -1: + dataRoot = sys.argv[dataIndex] + else: + try: + dataRoot = os.environ['VTK_DATA_ROOT'] + except KeyError: + dataRoot = '../../../../VTKData' + + return dataRoot + + +def vtkRegressionTestImage( renWin ): + """vtkRegressionTestImage(renWin) -- produce regression image for window + + This function writes out a regression .png file for a vtkWindow. + Does anyone involved in testing care to elaborate? + """ + imageIndex=-1; + for i in range(0, len(sys.argv)): + if sys.argv[i] == '-V' and i < len(sys.argv)-1: + imageIndex = i+1 + + if imageIndex != -1: + fname = os.path.join(vtkGetDataRoot(), sys.argv[imageIndex]) + + rt_w2if = vtk.vtkWindowToImageFilter() + rt_w2if.SetInput(renWin) + + if os.path.isfile(fname): + pass + else: + rt_pngw = vtk.vtkPNGWriter() + rt_pngw.SetFileName(fname) + rt_pngw.SetInput(rt_w2if.GetOutput()) + rt_pngw.Write() + rt_pngw = None + + rt_png = vtk.vtkPNGReader() + rt_png.SetFileName(fname) + + rt_id = vtk.vtkImageDifference() + rt_id.SetInput(rt_w2if.GetOutput()) + rt_id.SetImage(rt_png.GetOutput()) + rt_id.Update() + + if rt_id.GetThresholdedError() <= 10: + return 1 + else: + sys.stderr.write('Failed image test: %f\n' + % rt_id.GetThresholdedError()) + return 0 + return 2 + diff --git a/Wrapping/Python/vtk/util/vtkConstants.py b/Wrapping/Python/vtk/util/vtkConstants.py new file mode 100644 index 0000000..8ec79c1 --- /dev/null +++ b/Wrapping/Python/vtk/util/vtkConstants.py @@ -0,0 +1,122 @@ +""" +Miscellaneous constants copied from vtkSystemIncludes.h +(It would be nice if this file were automatically generated, +but the constants don't change very often) +""" + +# Some constants used throughout code + +VTK_LARGE_FLOAT = 1.0e+38 +VTK_LARGE_INTEGER = 2147483647 # 2^31 - 1 + +# These types are returned by GetDataType to indicate pixel type. +VTK_VOID = 0 +VTK_BIT = 1 +VTK_CHAR = 2 +VTK_UNSIGNED_CHAR = 3 +VTK_SHORT = 4 +VTK_UNSIGNED_SHORT = 5 +VTK_INT = 6 +VTK_UNSIGNED_INT = 7 +VTK_LONG = 8 +VTK_UNSIGNED_LONG = 9 +VTK_FLOAT =10 +VTK_DOUBLE =11 +VTK_ID_TYPE =12 + +# These types are not currently supported by GetDataType, but are +# for completeness. +VTK_STRING =13 +VTK_OPAQUE =14 + +# Some constant required for correct template performance +VTK_BIT_MIN = 0 +VTK_BIT_MAX = 1 +VTK_CHAR_MIN = -128 +VTK_CHAR_MAX = 127 +VTK_UNSIGNED_CHAR_MIN = 0 +VTK_UNSIGNED_CHAR_MAX = 255 +VTK_SHORT_MIN = -32768 +VTK_SHORT_MAX = 32767 +VTK_UNSIGNED_SHORT_MIN = 0 +VTK_UNSIGNED_SHORT_MAX = 65535 +VTK_INT_MIN = (-VTK_LARGE_INTEGER-1) +VTK_INT_MAX = VTK_LARGE_INTEGER +#VTK_UNSIGNED_INT_MIN = 0 +#VTK_UNSIGNED_INT_MAX = 4294967295 +VTK_LONG_MIN = (-VTK_LARGE_INTEGER-1) +VTK_LONG_MAX = VTK_LARGE_INTEGER +#VTK_UNSIGNED_LONG_MIN = 0 +#VTK_UNSIGNED_LONG_MAX = 4294967295 +VTK_FLOAT_MIN = -VTK_LARGE_FLOAT +VTK_FLOAT_MAX = VTK_LARGE_FLOAT +VTK_DOUBLE_MIN = -1.0e+99 +VTK_DOUBLE_MAX = 1.0e+99 + +# These types are returned to distinguish dataset types +VTK_POLY_DATA = 0 +VTK_STRUCTURED_POINTS = 1 +VTK_STRUCTURED_GRID = 2 +VTK_RECTILINEAR_GRID = 3 +VTK_UNSTRUCTURED_GRID = 4 +VTK_PIECEWISE_FUNCTION = 5 +VTK_IMAGE_DATA = 6 +VTK_DATA_OBJECT = 7 +VTK_DATA_SET = 8 +VTK_POINT_SET = 9 + +# These types define error codes for vtk functions +VTK_OK = 1 +VTK_ERROR = 2 + +# These types define different text properties +VTK_ARIAL = 0 +VTK_COURIER = 1 +VTK_TIMES = 2 + +VTK_TEXT_LEFT = 0 +VTK_TEXT_CENTERED = 1 +VTK_TEXT_RIGHT = 2 + +VTK_TEXT_BOTTOM = 0 +VTK_TEXT_TOP = 2 + +VTK_TEXT_GLOBAL_ANTIALIASING_SOME = 0 +VTK_TEXT_GLOBAL_ANTIALIASING_NONE = 1 +VTK_TEXT_GLOBAL_ANTIALIASING_ALL = 2 + +VTK_LUMINANCE = 1 +VTK_LUMINANCE_ALPHA = 2 +VTK_RGB = 3 +VTK_RGBA = 4 + +VTK_COLOR_MODE_DEFAULT = 0 +VTK_COLOR_MODE_MAP_SCALARS = 1 + +# Constants for InterpolationType +VTK_NEAREST_INTERPOLATION = 0 +VTK_LINEAR_INTERPOLATION = 1 + +# For volume rendering +VTK_MAX_VRCOMP = 4 + + +# A macro to get the name of a type + +__vtkTypeNameDict = {VTK_VOID:"void", + VTK_DOUBLE:"double", + VTK_FLOAT:"float", + VTK_LONG:"long", + VTK_UNSIGNED_LONG:"unsigned long", + VTK_INT:"int", + VTK_UNSIGNED_INT:"unsigned int", + VTK_SHORT:"short", + VTK_UNSIGNED_SHORT:"unsigned short", + VTK_CHAR:"char", + VTK_UNSIGNED_CHAR:"unsigned char", + VTK_BIT:"bit"} + +def vtkImageScalarTypeNameMacro(type): + return __vtkTypeNameDict[type] + + diff --git a/Wrapping/Python/vtk/util/vtkImageExportToArray.py b/Wrapping/Python/vtk/util/vtkImageExportToArray.py new file mode 100644 index 0000000..a5bba38 --- /dev/null +++ b/Wrapping/Python/vtk/util/vtkImageExportToArray.py @@ -0,0 +1,131 @@ +""" +vtkImageExportToArray - a NumPy front-end to vtkImageExport + +This class converts a VTK image to a Numeric Python array. + +To use this class, you must have the LLNL Numeric Python distribution +(http://numpy.sf.net) + +Methods + + SetInput(input) -- connect to VTK image pipeline + GetArray() -- execute pipeline and return a Numeric array + +Convert VTK_UNSIGNED_SHORT to python Int +(this might be necessary because Python doesn't support unsigned short, +the default is to cast unsigned short to signed short). + + SetConvertUnsignedShortToInt(yesno) + ConvertUnsignedShortToIntOn() + ConvertUnsignedShortToIntOff() + +From vtkImageExport + + GetDataExtent() + GetDataSpacing() + GetDataOrigin() +""" + +import Numeric +import umath +from vtk import vtkImageExport +from vtkConstants import * + +_NEW_NUMERIC = 0 +try: + val = float(Numeric.__version__) +except ValueError: + _NEW_NUMERIC = 0 +else: + if val > 20.0: + _NEW_NUMERIC = 1 + else: + _NEW_NUMERIC = 0 + + +class vtkImageExportToArray: + def __init__(self): + self.__export = vtkImageExport() + self.__ConvertUnsignedShortToInt = 0 + + # type dictionary: note that python doesn't support + # unsigned integers! + + __typeDict = { VTK_CHAR:Numeric.Int8, + VTK_UNSIGNED_CHAR:Numeric.UnsignedInt8, + VTK_SHORT:Numeric.Int16, + VTK_UNSIGNED_SHORT:Numeric.Int16, + VTK_INT:Numeric.Int32, + VTK_FLOAT:Numeric.Float32, + VTK_DOUBLE:Numeric.Float64 } + + __sizeDict = { VTK_CHAR:1, + VTK_UNSIGNED_CHAR:1, + VTK_SHORT:2, + VTK_UNSIGNED_SHORT:2, + VTK_INT:4, + VTK_FLOAT:4, + VTK_DOUBLE:8 } + + # convert unsigned shorts to ints, to avoid sign problems + def SetConvertUnsignedShortToInt(self,yesno): + self.__ConvertUnsignedShortToInt = yesno + + def GetConvertUnsignedShortToInt(self): + return self.__ConvertUnsignedShortToInt + + def ConvertUnsignedShortToIntOn(self): + self.__ConvertUnsignedShortToInt = 1 + + def ConvertUnsignedShortToIntOff(self): + self.__ConvertUnsignedShortToInt = 0 + + # set the input + def SetInput(self,input): + return self.__export.SetInput(input) + + def GetInput(self): + return self.__export.GetInput() + + def GetArray(self): + input = self.__export.GetInput() + input.UpdateInformation() + type = input.GetScalarType() + extent = input.GetWholeExtent() + numComponents = input.GetNumberOfScalarComponents() + dim = (extent[5]-extent[4]+1, + extent[3]-extent[2]+1, + extent[1]-extent[0]+1) + if (numComponents > 1): + dim = dim + (numComponents,) + size = dim[0]*dim[1]*dim[2]*numComponents*self.__sizeDict[type] + + if _NEW_NUMERIC: + imArray = Numeric.zeros((size,),Numeric.UnsignedInt8) + self.__export.Export(imArray) + else: + imString = Numeric.zeros((size,), + Numeric.UnsignedInt8).tostring() + self.__export.Export(imString) + imArray = Numeric.fromstring(imString,self.__typeDict[type]) + # just to remind myself of the dangers of memory management + del imString + + # reshape array appropriately. + imArray = Numeric.reshape(imArray, dim) + # convert unsigned short to int to avoid sign issues + if (type == VTK_UNSIGNED_SHORT and self.__ConvertUnsignedShortToInt): + imArray = umath.bitwise_and(imArray.astype(Numeric.Int32),0xffff) + + return imArray + + def GetDataExtent(self): + return self.__export.GetDataExtent() + + def GetDataSpacing(self): + return self.__export.GetDataSpacing() + + def GetDataOrigin(self): + return self.__export.GetDataOrigin() + + diff --git a/Wrapping/Python/vtk/util/vtkImageImportFromArray.py b/Wrapping/Python/vtk/util/vtkImageImportFromArray.py new file mode 100644 index 0000000..b53c2a2 --- /dev/null +++ b/Wrapping/Python/vtk/util/vtkImageImportFromArray.py @@ -0,0 +1,149 @@ +""" +vtkImageImportFromArray: a NumPy front-end to vtkImageImport + +Load a Numeric Python array into a VTK image. +To use this class, you must have the LLNL Numeric Python distribution +(http://numpy.sf.net) + +Methods: + + GetOutput() -- connect to VTK image pipeline + SetArray() -- set the array to load in + +Convert python 'Int' to VTK_UNSIGNED_SHORT: +(python doesn't support unsigned short, so this might be necessary) + + SetConvertIntToUnsignedShort(yesno) + ConvertIntToUnsignedShortOn() + ConvertIntToUnsignedShortOff() + +Methods from vtkImageImport: +(if you don't set these, sensible defaults will be used) + + SetDataExtent() + SetDataSpacing() + SetDataOrigin() +""" + +import Numeric +from vtk import vtkImageImport +from vtkConstants import * + +_NEW_NUMERIC = 0 +try: + val = float(Numeric.__version__) +except ValueError: + _NEW_NUMERIC = 0 +else: + if val > 20.0: + _NEW_NUMERIC = 1 + else: + _NEW_NUMERIC = 0 + + +class vtkImageImportFromArray: + def __init__(self): + self.__import = vtkImageImport() + self.__ConvertIntToUnsignedShort = 0 + self.__Array = None + + # type dictionary: note that python doesn't support + # unsigned integers properly! + __typeDict = {'c':VTK_UNSIGNED_CHAR, + 'b':VTK_UNSIGNED_CHAR, + '1':VTK_CHAR, + 's':VTK_SHORT, + 'i':VTK_INT, + 'l':VTK_LONG, + 'f':VTK_FLOAT, + 'd':VTK_DOUBLE, + 'F':VTK_FLOAT, + 'D':VTK_DOUBLE } + + __sizeDict = { VTK_CHAR:1, + VTK_UNSIGNED_CHAR:1, + VTK_SHORT:2, + VTK_UNSIGNED_SHORT:2, + VTK_INT:4, + VTK_FLOAT:4, + VTK_DOUBLE:8 } + + # convert 'Int32' to 'unsigned short' + def SetConvertIntToUnsignedShort(self,yesno): + self.__ConvertIntToUnsignedShort = yesno + + def GetConvertIntToUnsignedShort(self): + return self.__ConvertIntToUnsignedShort + + def ConvertIntToUnsignedShortOn(self): + self.__ConvertIntToUnsignedShort = 1 + + def ConvertIntToUnsignedShortOff(self): + self.__ConvertIntToUnsignedShort = 0 + + # get the output + def GetOutput(self): + return self.__import.GetOutput() + + # import an array + def SetArray(self,imArray): + self.__Array = imArray + numComponents = 1 + dim = imArray.shape + + if (len(dim) == 4): + numComponents = dim[3] + dim = (dim[0],dim[1],dim[2]) + + type = self.__typeDict[imArray.typecode()] + + if (imArray.typecode() == 'F' or imArray.typecode == 'D'): + numComponents = numComponents * 2 + + if (self.__ConvertIntToUnsignedShort and imArray.typecode() == 'i'): + if _NEW_NUMERIC: + imTmpArr = imArray.astype(Numeric.Int16).flat + else: + imTmpArr = imArray.astype(Numeric.Int16).tostring() + type = VTK_UNSIGNED_SHORT + else: + if _NEW_NUMERIC: + imTmpArr = imArray.flat + else: + imTmpArr = imArray.tostring() + + size = len(imTmpArr)*self.__sizeDict[type] + self.__import.CopyImportVoidPointer(imTmpArr, size) + self.__import.SetDataScalarType(type) + self.__import.SetNumberOfScalarComponents(numComponents) + extent = self.__import.GetDataExtent() + self.__import.SetDataExtent(extent[0],extent[0]+dim[2]-1, + extent[2],extent[2]+dim[1]-1, + extent[4],extent[4]+dim[0]-1) + self.__import.SetWholeExtent(extent[0],extent[0]+dim[2]-1, + extent[2],extent[2]+dim[1]-1, + extent[4],extent[4]+dim[0]-1) + + def GetArray(self): + return self.__Array + + # a whole bunch of methods copied from vtkImageImport + + def SetDataExtent(self,extent): + self.__import.SetDataExtent(extent) + + def GetDataExtent(self): + return self.__import.GetDataExtent() + + def SetDataSpacing(self,spacing): + self.__import.SetDataSpacing(spacing) + + def GetDataSpacing(self): + return self.__import.GetDataSpacing() + + def SetDataOrigin(self,origin): + self.__import.SetDataOrigin(origin) + + def GetDataOrigin(self): + return self.__import.GetDataOrigin() + diff --git a/Wrapping/Python/vtk/util/vtkMethodParser.py b/Wrapping/Python/vtk/util/vtkMethodParser.py new file mode 100644 index 0000000..be5c103 --- /dev/null +++ b/Wrapping/Python/vtk/util/vtkMethodParser.py @@ -0,0 +1,364 @@ +""" +This python module provides functionality to parse the methods of a +VTK object. + +Created by Prabhu Ramachandran. Committed in Apr, 2002. + +""" + +import string, re, sys +import types + +# set this to 1 if you want to see debugging messages - very useful if +# you have problems +DEBUG=0 + +def debug (msg): + if DEBUG: + print msg + +class VtkDirMethodParser: + """ Parses the methods from dir(vtk_obj). """ + def initialize_methods (self, vtk_obj): + debug ("VtkDirMethodParser:: initialize_methods ()") + + self.methods = dir (vtk_obj)[:] + # stores the <blah>On methods + self.toggle_meths = [] + # stores the Set<blah>To<blah> methods + self.state_meths = [] + # stores the methods that have a Get<blah> and Set<blah> + # only the <blah> is stored + self.get_set_meths = [] + # pure get methods + self.get_meths = [] + self.state_patn = re.compile ("To[A-Z0-9]") + + def parse_methods (self, vtk_obj): + debug ("VtkDirMethodParser:: parse_methods()") + self.initialize_methods (vtk_obj) + debug ("VtkDirMethodParser:: parse_methods() - initialized methods") + + for method in self.methods[:]: + # finding all the methods that set the state. + if string.find (method[:3], "Set") >= 0 and \ + self.state_patn.search (method) is not None : + try: + eval ("vtk_obj.Get%s"%method[3:]) + except AttributeError: + self.state_meths.append (method) + self.methods.remove (method) + # finding all the On/Off toggle methods + elif string.find (method[-2:], "On") >= 0: + try: + self.methods.index ("%sOff"%method[:-2]) + except ValueError: + pass + else: + self.toggle_meths.append (method) + self.methods.remove (method) + self.methods.remove ("%sOff"%method[:-2]) + # finding the Get/Set methods. + elif string.find (method[:3], "Get") == 0: + set_m = "Set"+method[3:] + try: + self.methods.index (set_m) + except ValueError: + pass + else: + self.get_set_meths.append (method[3:]) + self.methods.remove (method) + self.methods.remove (set_m) + + self.clean_up_methods (vtk_obj) + + def clean_up_methods (self, vtk_obj): + self.clean_get_set (vtk_obj) + self.clean_state_methods (vtk_obj) + self.clean_get_methods (vtk_obj) + + def clean_get_set (self, vtk_obj): + debug ("VtkDirMethodParser:: clean_get_set()") + # cleaning up the Get/Set methods by removing the toggle funcs. + for method in self.toggle_meths: + try: + self.get_set_meths.remove (method[:-2]) + except ValueError: + pass + + # cleaning them up by removing any methods that are responsible for + # other vtkObjects + for method in self.get_set_meths[:]: + try: + eval ("vtk_obj.Get%s ().GetClassName ()"%method) + except (TypeError, AttributeError): + pass + else: + self.get_set_meths.remove (method) + continue + try: + val = eval ("vtk_obj.Get%s ()"%method) + except (TypeError, AttributeError): + self.get_set_meths.remove (method) + else: + if val is None: + self.get_set_meths.remove (method) + + def clean_state_methods (self, vtk_obj): + debug ("VtkDirMethodParser:: clean_state_methods()") + # Getting the remaining pure GetMethods + for method in self.methods[:]: + if string.find (method[:3], "Get") == 0: + self.get_meths.append (method) + self.methods.remove (method) + + # Grouping similar state methods + if len (self.state_meths) != 0: + tmp = self.state_meths[:] + self.state_meths = [] + state_group = [tmp[0]] + end = self.state_patn.search (tmp[0]).start () + # stores the method type common to all similar methods + m = tmp[0][3:end] + for i in range (1, len (tmp)): + if string.find (tmp[i], m) >= 0: + state_group.append (tmp[i]) + else: + self.state_meths.append (state_group) + state_group = [tmp[i]] + end = self.state_patn.search (tmp[i]).start () + m = tmp[i][3:end] + try: # remove the corresponding set method in get_set + val = self.get_set_meths.index (m) + except ValueError: + pass + else: + del self.get_set_meths[val] + #self.get_meths.append ("Get"+m) + clamp_m = "Get" + m + "MinValue" + try: # remove the GetNameMax/MinValue in get_meths + val = self.get_meths.index (clamp_m) + except ValueError: + pass + else: + del self.get_meths[val] + val = self.get_meths.index ("Get" + m + "MaxValue") + del self.get_meths[val] + + if len (state_group) > 0: + self.state_meths.append (state_group) + + def clean_get_methods (self, vtk_obj): + debug ("VtkDirMethodParser:: clean_get_methods()") + for method in self.get_meths[:]: + debug (method) + try: + res = eval ("vtk_obj.%s ()"%method) + except (TypeError, AttributeError): + self.get_meths.remove (method) + continue + else: + try: + eval ("vtk_obj.%s ().GetClassName ()"%method) + except AttributeError: + pass + else: + self.get_meths.remove (method) + continue + if string.find (method[-8:], "MaxValue") > -1: + self.get_meths.remove( method) + elif string.find (method[-8:], "MinValue") > -1: + self.get_meths.remove( method) + + self.get_meths.sort () + + def toggle_methods (self): + return self.toggle_meths + + def state_methods (self): + return self.state_meths + + def get_set_methods (self): + return self.get_set_meths + + def get_methods (self): + return self.get_meths + + +class VtkPrintMethodParser: + + """ This class finds the methods for a given vtkObject. It uses + the output from vtkObject->Print() (or in Python str(vtkObject)) + and output from the VtkDirMethodParser to obtain the methods. """ + + def parse_methods (self, vtk_obj): + "Parse for the methods." + debug ("VtkPrintMethodParser:: parse_methods()") + + if self._initialize_methods (vtk_obj): + # if David Gobbi's improvements are in this version of VTK + # then I need to go no further. + return + + for method in self.methods[:]: + # removing methods that have nothing to the right of the ':' + if (method[1] == '') or \ + (string.find (method[1], "none") > -1) : + self.methods.remove (method) + + for method in self.methods: + # toggle methods are first identified + if (method[1] == "On") or (method[1] == "Off"): + try: + val = eval ("vtk_obj.Get%s ()"%method[0]) + if val == 1: + eval ("vtk_obj.%sOn ()"%method[0]) + elif val == 0: + eval ("vtk_obj.%sOff ()"%method[0]) + except AttributeError: + pass + else: + self.toggle_meths.append (method[0]+"On") + else: # see it it is get_set or get or a state method + found = 0 + # checking if it is a state func. + # figure out the long names from the dir_state_meths + for sms in self.dir_state_meths[:]: + if string.find (sms[0], method[0]) >= 0: + self.state_meths.append (sms) + self.dir_state_meths.remove (sms) + found = 1 + if found: + self.get_meths.append ("Get"+method[0]) + try: + t = eval ("vtk_obj.Get%sAsString ()"%method[0]) + except AttributeError: + pass + else: + self.get_meths.append ("Get"+method[0]+"AsString") + else: + # the long name is inherited or it is not a state method + try: + t = eval ("vtk_obj.Get%s ().GetClassName ()"% + method[0]) + except AttributeError: + pass + else: + continue + val = 0 + try: + val = eval ("vtk_obj.Get%s ()"%method[0]) + except (TypeError, AttributeError): + pass + else: + try: + f = eval ("vtk_obj.Set%s"%method[0]) + except AttributeError: + self.get_meths.append ("Get"+method[0]) + else: + try: + apply (f, val) + except TypeError: + try: + apply (f, (val, )) + except TypeError: + self.get_meths.append ("Get"+method[0]) + else: + self.get_set_meths.append (method[0]) + else: + self.get_set_meths.append (method[0]) + + self._clean_up_methods (vtk_obj) + + def _get_str_obj (self, vtk_obj): + debug ("VtkPrintMethodParser:: _get_str_obj()") + self.methods = str (vtk_obj) + self.methods = string.split (self.methods, "\n") + del self.methods[0] + + def _initialize_methods (self, vtk_obj): + "Do the basic parsing and setting up" + debug ("VtkPrintMethodParser:: _initialize_methods()") + dir_p = VtkDirMethodParser () + dir_p.parse_methods (vtk_obj) + + # testing if this version of vtk has David Gobbi's cool + # stuff. If it does then no need to do other things. + try: + junk = vtk_obj.__class__ + except AttributeError: + pass + else: + self.toggle_meths = dir_p.toggle_methods () + self.state_meths = dir_p.state_methods () + self.get_set_meths = dir_p.get_set_methods () + self.get_meths = dir_p.get_methods () + return 1 + + self.dir_toggle_meths = dir_p.toggle_methods () + self.dir_state_meths = dir_p.state_methods () + self.dir_get_set_meths = dir_p.get_set_methods () + self.dir_get_meths = dir_p.get_methods () + + self._get_str_obj (vtk_obj) + patn = re.compile (" \S") + + for method in self.methods[:]: + if not patn.match (method): + self.methods.remove (method) + + for method in self.methods[:]: + if string.find (method, ":") == -1: + self.methods.remove (method) + + for i in range (0, len (self.methods)): + strng = self.methods[i] + strng = string.replace (strng, " ", "") + self.methods[i] = string.split (strng, ":") + + + self.toggle_meths = [] + self.state_meths = [] + self.get_set_meths = [] + self.get_meths = [] + + return 0 + + def _clean_up_methods (self, vtk_obj): + "Merge dir and str methods. Finish up." + debug ("VtkPrintMethodParser:: _clean_up_methods()") + for meth_list in ((self.dir_toggle_meths, self.toggle_meths),\ + (self.dir_get_set_meths, self.get_set_meths),\ + (self.dir_get_meths, self.get_meths)): + for method in meth_list[0]: + try: + meth_list[1].index (method) + except ValueError: + meth_list[1].append (method) + + # Remove all get_set methods that are already in toggle_meths + # This case can happen if the str produces no "On/Off" but + # dir does and str produces a get_set instead. + for method in self.toggle_meths: + try: + self.get_set_meths.remove (method[:-2]) + except ValueError: + pass + + self.toggle_meths.sort () + self.state_meths.sort () + self.get_set_meths.sort () + self.get_meths.sort () + + def toggle_methods (self): + return self.toggle_meths + + def state_methods (self): + return self.state_meths + + def get_set_methods (self): + return self.get_set_meths + + def get_methods (self): + return self.get_meths + diff --git a/Wrapping/Python/vtk/volumerendering.py b/Wrapping/Python/vtk/volumerendering.py new file mode 100644 index 0000000..4aac9f1 --- /dev/null +++ b/Wrapping/Python/vtk/volumerendering.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK VolumeRendering library into +its namespace. This is an optional module.""" + +import os + +if os.name == 'posix': + from libvtkVolumeRenderingPython import * +else: + from vtkVolumeRenderingPython import * diff --git a/Wrapping/Python/vtk/widgets.py b/Wrapping/Python/vtk/widgets.py new file mode 100644 index 0000000..406208e --- /dev/null +++ b/Wrapping/Python/vtk/widgets.py @@ -0,0 +1,9 @@ +""" This module loads all the classes from the VTK Widgets library +into its namespace. This is an optional module.""" + +import os + +if os.name == 'posix': + from libvtkWidgetsPython import * +else: + from vtkWidgetsPython import * diff --git a/Wrapping/Python/vtk/wx/__init__.py b/Wrapping/Python/vtk/wx/__init__.py new file mode 100644 index 0000000..5ec1b00 --- /dev/null +++ b/Wrapping/Python/vtk/wx/__init__.py @@ -0,0 +1,3 @@ +"""wxPython widgets for VTK.""" + +__all__ = ['wxVTKRenderWindow', 'wxVTKRenderWindowInteractor'] diff --git a/Wrapping/Python/vtk/wx/wxVTKRenderWindow.py b/Wrapping/Python/vtk/wx/wxVTKRenderWindow.py new file mode 100644 index 0000000..441adc5 --- /dev/null +++ b/Wrapping/Python/vtk/wx/wxVTKRenderWindow.py @@ -0,0 +1,699 @@ +""" +A simple VTK widget for wxPython. Note that wxPython comes +with its own wxVTKRenderWindow in wxPython.lib.vtk. Try both +and see which one works better for you. + +Find wxPython info at http://wxPython.org + +Created by David Gobbi, December 2001 +Based on vtkTkRenderWindget.py + +""" + +""" +Please see the example at the end of this file. + +---------------------------------------- +Creation: + +wxVTKRenderWindow(parent, ID, stereo=0, [wx keywords]): + +You should create a wxPySimpleApp() or some other wx**App +before creating the window. + +---------------------------------------- +Methods: + +Render() +AddRenderer(ren) +GetRenderers() +GetRenderWindow() + +---------------------------------------- +Methods to override (all take a wxEvent): + +OnButtonDown(event) default: propagate event to Left, Right, Middle +OnLeftDown(event) default: set _Mode to 'Rotate' +OnRightDown(event) default: set _Mode to 'Zoom' +OnMiddleDown(event) default: set _Mode to 'Pan' + +OnButtonUp(event) default: propagate event to L, R, M and unset _Mode +OnLeftUp(event) +OnRightUp(event) +OnMiddleUp(event) + +OnMotion(event) default: call appropriate handler for _Mode + +OnEnterWindow(event) default: set focus to this window +OnLeaveWindow(event) default: release focus + +OnKeyDown(event) default: [R]eset, [W]irefreme, [S]olid, [P]ick +OnKeyUp(event) +OnChar(event) + +OnSetFocus(event) +OnKillFocus(event) + +OnSize(event) +OnMove(event) + +OnPaint(event) default: Render() + +---------------------------------------- +Protected Members: + +_Mode: Current mode: 'Rotate', 'Zoom', 'Pan' +_LastX, _LastY: The (x,y) coordinates of the previous event +_CurrentRenderer: The renderer that was most recently clicked in +_CurrentCamera: The camera for the current renderer + +---------------------------------------- +Private Members: + +__Handle: Handle to the window containing the vtkRenderWindow + +""" + +# import usual libraries +import math, os, sys +from wxPython.wx import * +import vtk + +# a few configuration items, see what works best on your system + +# Use wxGLCanvas as base class instead of wxWindow. +# This is sometimes necessary under wxGTK or the image is blank. +# (in wxWindows 2.3.1 and earlier, the GLCanvas had scroll bars) +try: + WX_USE_GL_CANVAS +except NameError: + if wxPlatform == '__WXMSW__': + WX_USE_GLCANVAS = 0 + else: + WX_USE_GLCANVAS = 1 + +# Keep capturing mouse after mouse is dragged out of window +# (in wxGTK 2.3.2 there is a bug that keeps this from working, +# but it is only relevant in wxGTK if there are multiple windows) +try: + WX_USE_X_CAPTURE +except NameError: + if wxPlatform == '__WXMSW__': + WX_USE_X_CAPTURE = 1 + else: + WX_USE_X_CAPTURE = 0 + +# end of configuration items + + +if WX_USE_GLCANVAS: + from wxPython.glcanvas import * + baseClass = wxGLCanvas +else: + baseClass = wxWindow + +class wxVTKRenderWindow(baseClass): + """ + A wxRenderWindow for wxPython. + Use GetRenderWindow() to get the vtkRenderWindow. + Create with the keyword stereo=1 in order to + generate a stereo-capable window. + """ + def __init__(self, parent, ID, *args, **kw): + + # miscellaneous protected variables + self._CurrentRenderer = None + self._CurrentCamera = None + self._CurrentZoom = 1.0 + self._CurrentLight = None + + self._ViewportCenterX = 0 + self._ViewportCenterY = 0 + + self._Picker = vtk.vtkCellPicker() + self._PickedActor = None + self._PickedProperty = vtk.vtkProperty() + self._PickedProperty.SetColor(1,0,0) + self._PrePickedProperty = None + + # these record the previous mouse position + self._LastX = 0 + self._LastY = 0 + + # the current interaction mode (Rotate, Pan, Zoom, etc) + self._Mode = None + self._ActiveButton = None + + # private attributes + self.__OldFocus = None + + # used by the LOD actors + self._DesiredUpdateRate = 15 + self._StillUpdateRate = 0.0001 + + # First do special handling of some keywords: + # stereo, position, size, width, height, style + + stereo = 0 + + if kw.has_key('stereo'): + if kw['stereo']: + stereo = 1 + del kw['stereo'] + + position = wxDefaultPosition + + if kw.has_key('position'): + position = kw['position'] + del kw['position'] + + try: + size = parent.GetSize() + except AttributeError: + size = wxDefaultSize + + if kw.has_key('size'): + size = kw['size'] + del kw['size'] + + if kw.has_key('width') and kw.has_key('height'): + size = (kw['width'], kw['height']) + del kw['width'] + del kw['height'] + + # wxWANTS_CHARS says to give us e.g. TAB + # wxNO_FULL_REPAINT_ON_RESIZE cuts down resize flicker under GTK + style = wxWANTS_CHARS | wxNO_FULL_REPAINT_ON_RESIZE + + if kw.has_key('style'): + style = style | kw['style'] + del kw['style'] + + # the enclosing frame must be shown under GTK or the windows + # don't connect together properly + l = [] + p = parent + while p: # make a list of all parents + l.append(p) + p = p.GetParent() + l.reverse() # sort list into descending order + for p in l: + p.Show(1) + + # initialize the wxWindow + baseClass.__init__(self, parent, ID, position, size, style) + + # create the RenderWindow and initialize it + self._RenderWindow = vtk.vtkRenderWindow() + try: + self._RenderWindow.SetSize(size.width, size.height) + except AttributeError: + self._RenderWindow.SetSize(size[0], size[1]) + if stereo: + self._RenderWindow.StereoCapableWindowOn() + self._RenderWindow.SetStereoTypeToCrystalEyes() + + self.__handle = None + + # refresh window by doing a Render + EVT_PAINT(self, self.OnPaint) + # turn off background erase to reduce flicker + EVT_ERASE_BACKGROUND(self, lambda e: None) + + # Bind the events to the event converters + EVT_RIGHT_DOWN(self, self._OnButtonDown) + EVT_LEFT_DOWN(self, self._OnButtonDown) + EVT_MIDDLE_DOWN(self, self._OnButtonDown) + EVT_RIGHT_UP(self, self._OnButtonUp) + EVT_LEFT_UP(self, self._OnButtonUp) + EVT_MIDDLE_UP(self, self._OnButtonUp) + EVT_MOTION(self, self.OnMotion) + + EVT_ENTER_WINDOW(self, self._OnEnterWindow) + EVT_LEAVE_WINDOW(self, self._OnLeaveWindow) + + EVT_CHAR(self, self.OnChar) + + # If we use EVT_KEY_DOWN instead of EVT_CHAR, capital versions + # of all characters are always returned. EVT_CHAR also performs + # other necessary keyboard-dependent translations. + EVT_CHAR(self, self.OnKeyDown) + EVT_KEY_UP(self, self.OnKeyUp) + + EVT_SIZE(self, self._OnSize) + EVT_MOVE(self, self.OnMove) + + EVT_SET_FOCUS(self, self.OnSetFocus) + EVT_KILL_FOCUS(self, self.OnKillFocus) + + def SetDesiredUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._DesiredUpdateRate = rate + + def GetDesiredUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._DesiredUpdateRate + + def SetStillUpdateRate(self, rate): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + self._StillUpdateRate = rate + + def GetStillUpdateRate(self): + """Mirrors the method with the same name in + vtkRenderWindowInteractor.""" + return self._StillUpdateRate + + def OnPaint(self,event): + dc = wxPaintDC(self) + self.Render() + + def _OnSize(self,event): + if wxPlatform != '__WXMSW__': + try: + width, height = event.GetSize() + except: + width = event.GetSize().width + height = event.GetSize().height + self._RenderWindow.SetSize(width, height) + self.OnSize(event) + + self.Render() + + def OnSize(self, event): + pass + + def OnMove(self,event): + pass + + def _OnEnterWindow(self,event): + self.UpdateRenderer(event) + self.OnEnterWindow(event) + + def OnEnterWindow(self,event): + if self.__OldFocus == None: + self.__OldFocus = wxWindow_FindFocus() + self.SetFocus() + + def _OnLeaveWindow(self,event): + self.OnLeaveWindow(event) + + def OnLeaveWindow(self,event): + if self.__OldFocus: + self.__OldFocus.SetFocus() + self.__OldFocus = None + + def OnSetFocus(self,event): + pass + + def OnKillFocus(self,event): + pass + + def _OnButtonDown(self,event): + # helper function for capturing mouse until button released + self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate) + + if event.RightDown(): + button = "Right" + elif event.LeftDown(): + button = "Left" + elif event.MiddleDown(): + button = "Middle" + else: + button = None + + # save the button and capture mouse until the button is released + if button and not self._ActiveButton: + self._ActiveButton = button + if WX_USE_X_CAPTURE: + self.CaptureMouse() + + self.OnButtonDown(event) + + def OnButtonDown(self,event): + if not self._Mode: + # figure out what renderer the mouse is over + self.UpdateRenderer(event) + + if event.LeftDown(): + self.OnLeftDown(event) + elif event.RightDown(): + self.OnRightDown(event) + elif event.MiddleDown(): + self.OnMiddleDown(event) + + def OnLeftDown(self,event): + if not self._Mode: + if event.ControlDown(): + self._Mode = "Zoom" + elif event.ShiftDown(): + self._Mode = "Pan" + else: + self._Mode = "Rotate" + + def OnRightDown(self,event): + if not self._Mode: + self._Mode = "Zoom" + + def OnMiddleDown(self,event): + if not self._Mode: + self._Mode = "Pan" + + def _OnButtonUp(self,event): + # helper function for releasing mouse capture + self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate) + + if event.RightUp(): + button = "Right" + elif event.LeftUp(): + button = "Left" + elif event.MiddleUp(): + button = "Middle" + else: + button = None + + # if the ActiveButton is realeased, then release mouse capture + if self._ActiveButton and button == self._ActiveButton: + if WX_USE_X_CAPTURE: + self.ReleaseMouse() + self._ActiveButton = None + + self.OnButtonUp(event) + + def OnButtonUp(self,event): + if event.LeftUp(): + self.OnLeftUp(event) + elif event.RightUp(): + self.OnRightUp(event) + elif event.MiddleUp(): + self.OnMiddleUp(event) + + # if not interacting, then do nothing more + if self._Mode: + if self._CurrentRenderer: + self.Render() + + self._Mode = None + + def OnLeftUp(self,event): + pass + + def OnRightUp(self,event): + pass + + def OnMiddleUp(self,event): + pass + + def OnMotion(self,event): + if self._Mode == "Pan": + self.Pan(event) + elif self._Mode == "Rotate": + self.Rotate(event) + elif self._Mode == "Zoom": + self.Zoom(event) + + def OnChar(self,event): + pass + + def OnKeyDown(self,event): + if event.GetKeyCode() == ord('r'): + self.Reset(event) + if event.GetKeyCode() == ord('w'): + self.Wireframe() + if event.GetKeyCode() == ord('s'): + self.Surface() + if event.GetKeyCode() == ord('p'): + self.PickActor(event) + + if event.GetKeyCode() < 256: + self.OnChar(event) + + def OnKeyUp(self,event): + pass + + def GetZoomFactor(self): + return self._CurrentZoom + + def GetRenderWindow(self): + return self._RenderWindow + + def GetPicker(self): + return self._Picker + + def Render(self): + if self._CurrentLight: + light = self._CurrentLight + light.SetPosition(self._CurrentCamera.GetPosition()) + light.SetFocalPoint(self._CurrentCamera.GetFocalPoint()) + + if((not self.GetUpdateRegion().IsEmpty())or(self.__handle)): + if self.__handle and self.__handle == self.GetHandle(): + self._RenderWindow.Render() + + elif self.GetHandle(): + # this means the user has reparented us + # let's adapt to the new situation by doing the WindowRemap + # dance + self._RenderWindow.SetNextWindowInfo(str(self.GetHandle())) + self._RenderWindow.WindowRemap() + # store the new situation + self.__handle = self.GetHandle() + + self._RenderWindow.Render() + + def UpdateRenderer(self,event): + """ + UpdateRenderer will identify the renderer under the mouse and set + up _CurrentRenderer, _CurrentCamera, and _CurrentLight. + """ + x = event.GetX() + y = event.GetY() + windowX, windowY = self._RenderWindow.GetSize() + + renderers = self._RenderWindow.GetRenderers() + numRenderers = renderers.GetNumberOfItems() + + self._CurrentRenderer = None + renderers.InitTraversal() + for i in range(0,numRenderers): + renderer = renderers.GetNextItem() + vx,vy = (0,0) + if (windowX > 1): + vx = float(x)/(windowX-1) + if (windowY > 1): + vy = (windowY-float(y)-1)/(windowY-1) + (vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport() + + if (vx >= vpxmin and vx <= vpxmax and + vy >= vpymin and vy <= vpymax): + self._CurrentRenderer = renderer + self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\ + +vpxmin + self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\ + +vpymin + self._CurrentCamera = self._CurrentRenderer.GetActiveCamera() + lights = self._CurrentRenderer.GetLights() + lights.InitTraversal() + self._CurrentLight = lights.GetNextItem() + break + + self._LastX = x + self._LastY = y + + def GetCurrentRenderer(self): + return self._CurrentRenderer + + def Rotate(self,event): + if self._CurrentRenderer: + x = event.GetX() + y = event.GetY() + + self._CurrentCamera.Azimuth(self._LastX - x) + self._CurrentCamera.Elevation(y - self._LastY) + self._CurrentCamera.OrthogonalizeViewUp() + + self._LastX = x + self._LastY = y + + self._CurrentRenderer.ResetCameraClippingRange() + self.Render() + + def Pan(self,event): + if self._CurrentRenderer: + x = event.GetX() + y = event.GetY() + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + (pPoint0,pPoint1,pPoint2) = camera.GetPosition() + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + + if (camera.GetParallelProjection()): + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetFocalPoint(fx,fy,fz) + + renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0) + renderer.WorldToDisplay() + fx,fy,fz = renderer.GetDisplayPoint() + renderer.SetDisplayPoint(fx-x+self._LastX, + fy+y-self._LastY, + fz) + renderer.DisplayToWorld() + fx,fy,fz,fw = renderer.GetWorldPoint() + camera.SetPosition(fx,fy,fz) + + else: + (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() + # Specify a point location in world coordinates + renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) + renderer.WorldToDisplay() + # Convert world point coordinates to display coordinates + dPoint = renderer.GetDisplayPoint() + focalDepth = dPoint[2] + + aPoint0 = self._ViewportCenterX + (x - self._LastX) + aPoint1 = self._ViewportCenterY - (y - self._LastY) + + renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth) + renderer.DisplayToWorld() + + (rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint() + if (rPoint3 != 0.0): + rPoint0 = rPoint0/rPoint3 + rPoint1 = rPoint1/rPoint3 + rPoint2 = rPoint2/rPoint3 + + camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0, + (fPoint1 - rPoint1) + fPoint1, + (fPoint2 - rPoint2) + fPoint2) + + camera.SetPosition((fPoint0 - rPoint0) + pPoint0, + (fPoint1 - rPoint1) + pPoint1, + (fPoint2 - rPoint2) + pPoint2) + + self._LastX = x + self._LastY = y + + self.Render() + + def Zoom(self,event): + if self._CurrentRenderer: + x = event.GetX() + y = event.GetY() + + renderer = self._CurrentRenderer + camera = self._CurrentCamera + + zoomFactor = math.pow(1.02,(0.5*(self._LastY - y))) + self._CurrentZoom = self._CurrentZoom * zoomFactor + + if camera.GetParallelProjection(): + parallelScale = camera.GetParallelScale()/zoomFactor + camera.SetParallelScale(parallelScale) + else: + camera.Dolly(zoomFactor) + renderer.ResetCameraClippingRange() + + self._LastX = x + self._LastY = y + + self.Render() + + def Reset(self,event=None): + if self._CurrentRenderer: + self._CurrentRenderer.ResetCamera() + + self.Render() + + def Wireframe(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToWireframe() + + self.Render() + + def Surface(self): + actors = self._CurrentRenderer.GetActors() + numActors = actors.GetNumberOfItems() + actors.InitTraversal() + for i in range(0,numActors): + actor = actors.GetNextItem() + actor.GetProperty().SetRepresentationToSurface() + + self.Render() + + def PickActor(self,event): + if self._CurrentRenderer: + x = event.GetX() + y = event.GetY() + + renderer = self._CurrentRenderer + picker = self._Picker + + windowX, windowY = self._RenderWindow.GetSize() + picker.Pick(x,(windowY - y - 1),0.0,renderer) + actor = picker.GetActor() + + if (self._PickedActor != None and + self._PrePickedProperty != None): + self._PickedActor.SetProperty(self._PrePickedProperty) + # release hold of the property + self._PrePickedProperty.UnRegister(self._PrePickedProperty) + self._PrePickedProperty = None + + if (actor != None): + self._PickedActor = actor + self._PrePickedProperty = self._PickedActor.GetProperty() + # hold onto the property + self._PrePickedProperty.Register(self._PrePickedProperty) + self._PickedActor.SetProperty(self._PickedProperty) + + self.Render() + +#---------------------------------------------------------------------------- +def wxVTKRenderWindowConeExample(): + + """Like it says, just a simple example + """ + # every wx app needs an app + app = wxPySimpleApp() + + # create the widget + frame = wxFrame(None, -1, "wxRenderWindow", size=wxSize(400,400)) + widget = wxVTKRenderWindow(frame, -1) + + ren = vtk.vtkRenderer() + widget.GetRenderWindow().AddRenderer(ren) + + cone = vtk.vtkConeSource() + cone.SetResolution(8) + + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + + ren.AddActor(coneActor) + + # show the window + + frame.Show(1) + + app.MainLoop() + +if __name__ == "__main__": + wxVTKRenderWindowConeExample() + diff --git a/Wrapping/Python/vtk/wx/wxVTKRenderWindowInteractor.py b/Wrapping/Python/vtk/wx/wxVTKRenderWindowInteractor.py new file mode 100644 index 0000000..f7cf68c --- /dev/null +++ b/Wrapping/Python/vtk/wx/wxVTKRenderWindowInteractor.py @@ -0,0 +1,558 @@ +""" + +A VTK RenderWindowInteractor widget for wxPython. Note that wxPython +comes with its own wxVTKRenderWindow in wxPython.lib.vtk. Try both +and see which one works better for you. + +Find wxPython info at http://wxPython.org + +Created by Prabhu Ramachandran, April 2002 +Based on wxVTKRenderWindow.py + +Fixes and updates by Charl P. Botha 2003-2005 +""" + +""" +Please see the example at the end of this file. + +---------------------------------------- +Creation: + + wxVTKRenderWindowInteractor(parent, ID, stereo=0, [wx keywords]): + + You should create a wxPySimpleApp() or some other wx**App before + creating the window. + +Behaviour: + + Uses __getattr__ to make the wxVTKRenderWindowInteractor behave just + like a vtkGenericRenderWindowInteractor. + +---------------------------------------- + +""" + +# import usual libraries +import math, os, sys +from wxPython.wx import * +import vtk + +# wxPython 2.4.0.4 and newer prefers the use of True and False, standard +# booleans in Python 2.2 but not earlier. Here we define these values if +# they don't exist so that we can use True and False in the rest of the +# code. At the time of this writing, that happens exactly ONCE in +# CreateTimer() +try: + True +except NameError: + True = 1 + False = 0 + +# a few configuration items, see what works best on your system + +# Use wxGLCanvas as base class instead of wxWindow. +# This is sometimes necessary under wxGTK or the image is blank. +# (in wxWindows 2.3.1 and earlier, the GLCanvas had scroll bars) +try: + WX_USE_GL_CANVAS +except NameError: + if wxPlatform == '__WXMSW__': + WX_USE_GLCANVAS = 0 + else: + WX_USE_GLCANVAS = 1 + +# Keep capturing mouse after mouse is dragged out of window +# (in wxGTK 2.3.2 there is a bug that keeps this from working, +# but it is only relevant in wxGTK if there are multiple windows) +try: + WX_USE_X_CAPTURE +except NameError: + if wxPlatform == '__WXMSW__': + WX_USE_X_CAPTURE = 1 + else: + WX_USE_X_CAPTURE = 0 + +# end of configuration items + + +if WX_USE_GLCANVAS: + from wxPython.glcanvas import * + baseClass = wxGLCanvas +else: + baseClass = wxWindow + +class EventTimer(wxTimer): + def __init__(self, iren): + wxTimer.__init__(self) + self.iren = iren + def Notify(self): + self.iren.TimerEvent() + +class wxVTKRenderWindowInteractor(baseClass): + """ + A wxRenderWindow for wxPython. + Use GetRenderWindow() to get the vtkRenderWindow. + Create with the keyword stereo=1 in order to + generate a stereo-capable window. + """ + + # class variable that can also be used to request instances that use + # stereo; this is overridden by the stereo=1/0 parameter. If you set + # it to True, the NEXT instantiated object will attempt to allocate a + # stereo visual. E.g.: + # wxVTKRenderWindowInteractor.USE_STEREO = True + # myRWI = wxVTKRenderWindowInteractor(parent, -1) + USE_STEREO = False + + def __init__(self, parent, ID, *args, **kw): + + # private attributes + self.__RenderWhenDisabled = 0 + + # First do special handling of some keywords: + # stereo, position, size, width, height, style + + stereo = 0 + + if kw.has_key('stereo'): + if kw['stereo']: + stereo = 1 + del kw['stereo'] + + elif self.USE_STEREO: + stereo = 1 + + position = wxDefaultPosition + + if kw.has_key('position'): + position = kw['position'] + del kw['position'] + + size = wxDefaultSize + + if kw.has_key('size'): + size = kw['size'] + del kw['size'] + + if kw.has_key('width') and kw.has_key('height'): + size = (kw['width'], kw['height']) + del kw['width'] + del kw['height'] + + # wxWANTS_CHARS says to give us e.g. TAB + # wxNO_FULL_REPAINT_ON_RESIZE cuts down resize flicker under GTK + style = wxWANTS_CHARS | wxNO_FULL_REPAINT_ON_RESIZE + + if kw.has_key('style'): + style = style | kw['style'] + del kw['style'] + + # the enclosing frame must be shown under GTK or the windows + # don't connect together properly + l = [] + p = parent + while p: # make a list of all parents + l.append(p) + p = p.GetParent() + l.reverse() # sort list into descending order + for p in l: + p.Show(1) + + # code added by cpbotha to enable stereo correctly where the user + # requests this; remember that the glXContext in this case is NOT + # allocated by VTK, but by WX, hence all of this. + if stereo and baseClass.__name__ == 'wxGLCanvas': + # initialize GLCanvas with correct attriblist for stereo + attribList = [WX_GL_RGBA, + WX_GL_MIN_RED, 1, WX_GL_MIN_GREEN, 1, + WX_GL_MIN_BLUE, 1, + WX_GL_DEPTH_SIZE, 1, WX_GL_DOUBLEBUFFER, + WX_GL_STEREO] + try: + baseClass.__init__(self, parent, ID, position, size, style, + attribList=attribList) + + except wxPyAssertionError: + # stereo visual couldn't be allocated, so we go back to default + baseClass.__init__(self, parent, ID, position, size, style) + # and make sure everyone knows about it + stereo = 0 + + else: + baseClass.__init__(self, parent, ID, position, size, style) + + # create the RenderWindow and initialize it + self._Iren = vtk.vtkGenericRenderWindowInteractor() + self._Iren.SetRenderWindow( vtk.vtkRenderWindow() ) + self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer) + self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer) + + try: + self._Iren.GetRenderWindow().SetSize(size.width, size.height) + except AttributeError: + self._Iren.GetRenderWindow().SetSize(size[0], size[1]) + + if stereo: + self._Iren.GetRenderWindow().StereoCapableWindowOn() + self._Iren.GetRenderWindow().SetStereoTypeToCrystalEyes() + + self.__handle = None + self._ActiveButton = 0 + + self.BindEvents() + + # with this, we can make sure that the reparenting logic in + # Render() isn't called before the first OnPaint() has + # successfully been run (and set up the VTK/WX display links) + self.__has_painted = False + + def BindEvents(self): + # refresh window by doing a Render + EVT_PAINT(self, self.OnPaint) + # turn off background erase to reduce flicker + EVT_ERASE_BACKGROUND(self, lambda e: None) + + # Bind the events to the event converters + EVT_RIGHT_DOWN(self, self.OnButtonDown) + EVT_LEFT_DOWN(self, self.OnButtonDown) + EVT_MIDDLE_DOWN(self, self.OnButtonDown) + EVT_RIGHT_UP(self, self.OnButtonUp) + EVT_LEFT_UP(self, self.OnButtonUp) + EVT_MIDDLE_UP(self, self.OnButtonUp) + EVT_MOUSEWHEEL(self, self.OnMouseWheel) + EVT_MOTION(self, self.OnMotion) + + EVT_ENTER_WINDOW(self, self.OnEnter) + EVT_LEAVE_WINDOW(self, self.OnLeave) + + # If we use EVT_KEY_DOWN instead of EVT_CHAR, capital versions + # of all characters are always returned. EVT_CHAR also performs + # other necessary keyboard-dependent translations. + EVT_CHAR(self, self.OnKeyDown) + EVT_KEY_UP(self, self.OnKeyUp) + + EVT_SIZE(self, self.OnSize) + + def __getattr__(self, attr): + """Makes the object behave like a + vtkGenericRenderWindowInteractor""" + if attr == '__vtk__': + return lambda t=self._Iren: t + elif hasattr(self._Iren, attr): + return getattr(self._Iren, attr) + else: + raise AttributeError, self.__class__.__name__ + \ + " has no attribute named " + attr + + def CreateTimer(self, obj, evt): + self._timer = EventTimer(self) + self._timer.Start(10, True) + + def DestroyTimer(self, obj, evt): + """The timer is a one shot timer so will expire automatically.""" + return 1 + + def GetDisplayId(self): + """Function to get X11 Display ID from WX and return it in a format + that can be used by VTK Python. + + We query the X11 Display with a new call that was added in wxPython + 2.6.0.1. The call returns a SWIG object which we can query for the + address and subsequently turn into an old-style SWIG-mangled string + representation to pass to VTK. + """ + + d = None + + try: + d = wxGetXDisplay() + + except NameError: + # wxGetXDisplay was added by Robin Dunn in wxPython 2.6.0.1 + # if it's not available, we can't pass it. In general, + # things will still work; on some setups, it'll break. + pass + + else: + # wx returns None on platforms where wxGetXDisplay is not relevant + if d: + d = hex(d) + # we now have 0xdeadbeef + # VTK wants it as: _deadbeef_void_p (pre-SWIG-1.3 style) + d = '_%s_%s' % (d[2:], 'void_p') + + return d + + def OnPaint(self,event): + dc = wxPaintDC(self) + + # make sure the RenderWindow is sized correctly + self._Iren.GetRenderWindow().SetSize(self.GetSizeTuple()) + + # Tell the RenderWindow to render inside the wxWindow. + if not self.__handle: + + # on relevant platforms, set the X11 Display ID + d = self.GetDisplayId() + if d: + self._Iren.GetRenderWindow().SetDisplayId(d) + + # store the handle + self.__handle = self.GetHandle() + # and give it to VTK + self._Iren.GetRenderWindow().SetWindowInfo(str(self.__handle)) + + # now that we've painted once, the Render() reparenting logic + # is safe + self.__has_painted = True + + self.Render() + + def OnSize(self,event): + try: + width, height = event.GetSize() + except: + width = event.GetSize().width + height = event.GetSize().height + self._Iren.SetSize(width, height) + self._Iren.ConfigureEvent() + # this will check for __handle + self.Render() + + # event processing should continue + event.Skip() + + def OnMotion(self, event): + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(), + event.ControlDown(), + event.ShiftDown(), + chr(0), 0, None) + self._Iren.MouseMoveEvent() + + # event processing should continue + event.Skip() + + def OnEnter(self,event): + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(), + event.ControlDown(), + event.ShiftDown(), + chr(0), 0, None) + self._Iren.EnterEvent() + + # event processing should continue + event.Skip() + + def OnLeave(self,event): + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(), + event.ControlDown(), + event.ShiftDown(), + chr(0), 0, None) + self._Iren.LeaveEvent() + + # event processing should continue + event.Skip() + + + def OnButtonDown(self,event): + ctrl, shift = event.ControlDown(), event.ShiftDown() + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(), + ctrl, shift, chr(0), 0, None) + + self._ActiveButton = 0 + if event.RightDown(): + self._Iren.RightButtonPressEvent() + self._ActiveButton = 'Right' + elif event.LeftDown(): + self._Iren.LeftButtonPressEvent() + self._ActiveButton = 'Left' + elif event.MiddleDown(): + self._Iren.MiddleButtonPressEvent() + self._ActiveButton = 'Middle' + + # save the button and capture mouse until the button is released + if self._ActiveButton and WX_USE_X_CAPTURE: + self.CaptureMouse() + + # allow wx event processing to continue + # on wxPython 2.6.0.1, omitting this will cause problems with + # the initial focus, resulting in the wxVTKRWI ignoring keypresses + # until we focus elsewhere and then refocus the wxVTKRWI frame + event.Skip() + + def OnButtonUp(self,event): + ctrl, shift = event.ControlDown(), event.ShiftDown() + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(), + ctrl, shift, chr(0), 0, None) + + if self._ActiveButton == 'Right': + self._Iren.RightButtonReleaseEvent() + elif self._ActiveButton == 'Left': + self._Iren.LeftButtonReleaseEvent() + elif self._ActiveButton == 'Middle': + self._Iren.MiddleButtonReleaseEvent() + + # if the ActiveButton is realeased, then release mouse capture + if self._ActiveButton and WX_USE_X_CAPTURE: + self.ReleaseMouse() + + # event processing should continue + event.Skip() + + + def OnMouseWheel(self,event): + ctrl, shift = event.ControlDown(), event.ShiftDown() + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(), + ctrl, shift, chr(0), 0, None) + if event.GetWheelRotation() > 0: + self._Iren.MouseWheelForwardEvent() + else: + self._Iren.MouseWheelBackwardEvent() + + # event processing should continue + event.Skip() + + + def OnKeyDown(self,event): + ctrl, shift = event.ControlDown(), event.ShiftDown() + keycode, keysym = event.GetKeyCode(), None + key = chr(0) + if keycode < 256: + key = chr(keycode) + + # wxPython 2.6.0.1 does not return a valid event.Get{X,Y}() + # for this event, so we use the cached position. + (x,y)= self._Iren.GetEventPosition() + self._Iren.SetEventInformation(x, y, + ctrl, shift, key, 0, + keysym) + + self._Iren.KeyPressEvent() + self._Iren.CharEvent() + + # event processing should continue + event.Skip() + + + def OnKeyUp(self,event): + ctrl, shift = event.ControlDown(), event.ShiftDown() + keycode, keysym = event.GetKeyCode(), None + key = chr(0) + if keycode < 256: + key = chr(keycode) + + self._Iren.SetEventInformationFlipY(event.GetX(), event.GetY(), + ctrl, shift, key, 0, + keysym) + self._Iren.KeyReleaseEvent() + + # event processing should continue + event.Skip() + + + def GetRenderWindow(self): + return self._Iren.GetRenderWindow() + + def Render(self): + RenderAllowed = 1 + + if not self.__RenderWhenDisabled: + # the user doesn't want us to render when the toplevel frame + # is disabled - first find the top level parent + topParent = wxGetTopLevelParent(self) + if topParent: + # if it exists, check whether it's enabled + # if it's not enabeld, RenderAllowed will be false + RenderAllowed = topParent.IsEnabled() + + if RenderAllowed: + if self.__handle and self.__handle == self.GetHandle(): + self._Iren.GetRenderWindow().Render() + + elif self.GetHandle() and self.__has_painted: + # this means the user has reparented us; let's adapt to the + # new situation by doing the WindowRemap dance + self._Iren.GetRenderWindow().SetNextWindowInfo( + str(self.GetHandle())) + + # make sure the DisplayId is also set correctly + d = self.GetDisplayId() + if d: + self._Iren.GetRenderWindow().SetDisplayId(d) + + # do the actual remap with the new parent information + self._Iren.GetRenderWindow().WindowRemap() + + # store the new situation + self.__handle = self.GetHandle() + self._Iren.GetRenderWindow().Render() + + def SetRenderWhenDisabled(self, newValue): + """Change value of __RenderWhenDisabled ivar. + + If __RenderWhenDisabled is false (the default), this widget will not + call Render() on the RenderWindow if the top level frame (i.e. the + containing frame) has been disabled. + + This prevents recursive rendering during wxSafeYield() calls. + wxSafeYield() can be called during the ProgressMethod() callback of + a VTK object to have progress bars and other GUI elements updated - + it does this by disabling all windows (disallowing user-input to + prevent re-entrancy of code) and then handling all outstanding + GUI events. + + However, this often triggers an OnPaint() method for wxVTKRWIs, + resulting in a Render(), resulting in Update() being called whilst + still in progress. + """ + self.__RenderWhenDisabled = bool(newValue) + + +#-------------------------------------------------------------------- +def wxVTKRenderWindowInteractorConeExample(): + """Like it says, just a simple example + """ + # every wx app needs an app + app = wxPySimpleApp() + + # create the top-level frame, sizer and wxVTKRWI + frame = wxFrame(None, -1, "wxRenderWindow", size=wxSize(400,400)) + widget = wxVTKRenderWindowInteractor(frame, -1) + sizer = wxBoxSizer(wxVERTICAL) + sizer.Add(widget, 1, wxEXPAND) + frame.SetSizer(sizer) + frame.Layout() + + # It would be more correct (API-wise) to call widget.Initialize() and + # widget.Start() here, but Initialize() calls RenderWindow.Render(). + # That Render() call will get through before we can setup the + # RenderWindow() to render via the wxWidgets-created context; this + # causes flashing on some platforms and downright breaks things on + # other platforms. Instead, we call widget.Enable(). This means + # that the RWI::Initialized ivar is not set, but in THIS SPECIFIC CASE, + # that doesn't matter. + widget.Enable(1) + + widget.AddObserver("ExitEvent", lambda o,e,f=frame: f.Close()) + + ren = vtk.vtkRenderer() + widget.GetRenderWindow().AddRenderer(ren) + + cone = vtk.vtkConeSource() + cone.SetResolution(8) + + coneMapper = vtk.vtkPolyDataMapper() + coneMapper.SetInput(cone.GetOutput()) + + coneActor = vtk.vtkActor() + coneActor.SetMapper(coneMapper) + + ren.AddActor(coneActor) + + # show the window + frame.Show(1) + + app.MainLoop() + +if __name__ == "__main__": + wxVTKRenderWindowInteractorConeExample() + diff --git a/Wrapping/Python/vtkParaPythonAppInit.cxx b/Wrapping/Python/vtkParaPythonAppInit.cxx new file mode 100644 index 0000000..649d559 --- /dev/null +++ b/Wrapping/Python/vtkParaPythonAppInit.cxx @@ -0,0 +1,16 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParaPythonAppInit.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#define VTK_COMPILED_USING_MPI +#include "vtkPythonAppInit.cxx" diff --git a/Wrapping/Python/vtkPythonAppInit.cxx b/Wrapping/Python/vtkPythonAppInit.cxx new file mode 100644 index 0000000..8c8f958 --- /dev/null +++ b/Wrapping/Python/vtkPythonAppInit.cxx @@ -0,0 +1,294 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkPythonAppInit.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/* Minimal main program -- everything is loaded from the library */ + +#include "vtkPython.h" + +#ifdef VTK_COMPILED_USING_MPI +# include <mpi.h> +# include "vtkMPIController.h" +#endif // VTK_COMPILED_USING_MPI + +#include "vtkVersion.h" +#include "Wrapping/Python/vtkPythonAppInitConfigure.h" + +#if defined(CMAKE_INTDIR) +# define VTK_PYTHON_LIBRARY_DIR VTK_PYTHON_LIBRARY_DIR_BUILD "/" CMAKE_INTDIR +#else +# define VTK_PYTHON_LIBRARY_DIR VTK_PYTHON_LIBRARY_DIR_BUILD +#endif + +#include <sys/stat.h> + +/* + * Make sure all the kits register their classes with vtkInstantiator. + */ +#include "vtkCommonInstantiator.h" +#include "vtkFilteringInstantiator.h" +#include "vtkIOInstantiator.h" +#include "vtkImagingInstantiator.h" +#include "vtkGraphicsInstantiator.h" + +#ifdef VTK_USE_RENDERING +#include "vtkRenderingInstantiator.h" +#include "vtkVolumeRenderingInstantiator.h" +#include "vtkHybridInstantiator.h" +#endif + +#ifdef VTK_USE_PARALLEL +#include "vtkParallelInstantiator.h" +#endif + +#include <vtkstd/string> +#include <vtksys/SystemTools.hxx> + +#ifdef VTK_COMPILED_USING_MPI +class vtkMPICleanup { +public: + vtkMPICleanup() + { + this->Controller = 0; + } + void Initialize(int* argc, char ***argv) + { + MPI_Init(argc, argv); + this->Controller = vtkMPIController::New(); + this->Controller->Initialize(argc, argv, 1); + vtkMultiProcessController::SetGlobalController(this->Controller); + } + ~vtkMPICleanup() + { + if ( this->Controller ) + { + this->Controller->Finalize(); + this->Controller->Delete(); + } + } +private: + vtkMPIController *Controller; +}; + +static vtkMPICleanup VTKMPICleanup; + +#endif // VTK_COMPILED_USING_MPI + +extern "C" { + extern DL_IMPORT(int) Py_Main(int, char **); +} + +static void vtkPythonAppInitEnableMSVCDebugHook(); +static void vtkPythonAppInitPrependPath(const char* self_dir); + +/* The maximum length of a file name. */ +#if defined(PATH_MAX) +# define VTK_PYTHON_MAXPATH PATH_MAX +#elif defined(MAXPATHLEN) +# define VTK_PYTHON_MAXPATH MAXPATHLEN +#else +# define VTK_PYTHON_MAXPATH 16384 +#endif + +/* Python major.minor version string. */ +#define VTK_PYTHON_TO_STRING(x) VTK_PYTHON_TO_STRING0(x) +#define VTK_PYTHON_TO_STRING0(x) VTK_PYTHON_TO_STRING1(x) +#define VTK_PYTHON_TO_STRING1(x) #x +#define VTK_PYTHON_VERSION VTK_PYTHON_TO_STRING(PY_MAJOR_VERSION.PY_MINOR_VERSION) + +int main(int argc, char **argv) +{ + vtkPythonAppInitEnableMSVCDebugHook(); + +#ifdef VTK_COMPILED_USING_MPI + VTKMPICleanup.Initialize(&argc, &argv); +#endif // VTK_COMPILED_USING_MPI + + int displayVersion = 0; + if ( argc > 1 ) + { + int cc; + for ( cc = 1; cc < argc; cc ++ ) + { + if ( strcmp(argv[cc], "-V") == 0 ) + { + displayVersion = 1; + break; + } + } + } + else + { + displayVersion = 1; + } + if ( displayVersion ) + { + cout << vtkVersion::GetVTKSourceVersion() << endl; + } + + // The following code will hack in the path for running VTK/Python + // from the build tree. Do not try this at home. We are + // professionals. + + // Set the program name, so that we can ask python to provide us + // full path. We need to collapse the path name to aid relative + // path computation for the VTK python module installation. + static char argv0[VTK_PYTHON_MAXPATH]; + vtkstd::string av0 = vtksys::SystemTools::CollapseFullPath(argv[0]); + strcpy(argv0, av0.c_str()); + Py_SetProgramName(argv0); + + // Initialize interpreter. + Py_Initialize(); + + // Compute the directory containing this executable. The python + // sys.executable variable contains the full path to the interpreter + // executable. + char tmpExe[] = "executable"; + PyObject* executable = PySys_GetObject(tmpExe); + if(const char* exe_str = PyString_AsString(executable)) + { + // Use the executable location to try to set sys.path to include + // the VTK python modules. + vtkstd::string self_dir = vtksys::SystemTools::GetFilenamePath(exe_str); + vtkPythonAppInitPrependPath(self_dir.c_str()); + } + + // Ok, all done, now enter python main. + return Py_Main(argc, argv); +} + +// For a DEBUG build on MSVC, add a hook to prevent error dialogs when +// being run from DART. +#if defined(_MSC_VER) && defined(_DEBUG) +# include <crtdbg.h> +static int vtkPythonAppInitDebugReport(int, char* message, int*) +{ + fprintf(stderr, message); + exit(1); +} +void vtkPythonAppInitEnableMSVCDebugHook() +{ + if(getenv("DART_TEST_FROM_DART")) + { + _CrtSetReportHook(vtkPythonAppInitDebugReport); + } +} +#else +void vtkPythonAppInitEnableMSVCDebugHook() +{ +} +#endif + +//---------------------------------------------------------------------------- +static void vtkPythonAppInitPrependPythonPath(const char* dir) +{ + // Convert slashes for this platform. + vtkstd::string out_dir = dir; +#if defined(_WIN32) && !defined(__CYGWIN__) + for(vtkstd::string::size_type i = 0; i < out_dir.length(); ++i) + { + if(out_dir[i] == '/') + { + out_dir[i] = '\\'; + } + } +#endif + + // Append the path to the python sys.path object. + char tmpPath[] = "path"; + PyObject* path = PySys_GetObject(tmpPath); + PyObject* newpath; + newpath = PyString_FromString(out_dir.c_str()); + PyList_Insert(path, 0, newpath); + Py_DECREF(newpath); +} + +//---------------------------------------------------------------------------- +static void vtkPythonAppInitPrependPath(const char* self_dir) +{ + // Try to put the VTK python module location in sys.path. + vtkstd::string package_dir = self_dir; +#if defined(CMAKE_INTDIR) + package_dir += "/.."; +#endif + package_dir += "/../Wrapping/Python"; + package_dir = vtksys::SystemTools::CollapseFullPath(package_dir.c_str()); + if(vtksys::SystemTools::FileIsDirectory(package_dir.c_str())) + { + // This executable is running from the build tree. Prepend the + // library directory and package directory to the search path. + vtkPythonAppInitPrependPythonPath(package_dir.c_str()); + vtkPythonAppInitPrependPythonPath(VTK_PYTHON_LIBRARY_DIR); + } + else + { + // This executable is running from an install tree. Check for + // possible VTK python module locations. See + // http://python.org/doc/2.4.1/inst/alt-install-windows.html for + // information about possible install locations. If the user + // changes the prefix to something other than VTK's prefix or + // python's native prefix then he/she will have to get the + // packages in sys.path himself/herself. + const char* inst_dirs[] = { + "/lib/python" VTK_PYTHON_VERSION "/site-packages/vtk", // UNIX --prefix + "/lib/python/vtk", // UNIX --home + "/Lib/site-packages/vtk", "/Lib/vtk", // Windows + "/site-packages/vtk", "/vtk", // Windows + 0 + }; + vtkstd::string prefix = vtksys::SystemTools::GetFilenamePath(self_dir); + for(const char** dir = inst_dirs; *dir; ++dir) + { + package_dir = prefix; + package_dir += *dir; + package_dir = vtksys::SystemTools::CollapseFullPath(package_dir.c_str()); + if(vtksys::SystemTools::FileIsDirectory(package_dir.c_str())) + { + // We found the modules. Add the location to sys.path, but + // without the "/vtk" suffix. + vtkstd::string path_dir = + vtksys::SystemTools::GetFilenamePath(package_dir); + vtkPythonAppInitPrependPythonPath(path_dir.c_str()); + break; + } + } + + // This executable does not actually link to the python wrapper + // libraries, though it probably should now that the stub-modules + // are separated from them. Since it does not we have to make + // sure the wrapper libraries can be found by the dynamic loader + // when the stub-modules are loaded. On UNIX this executable must + // be running in an environment where the main VTK libraries (to + // which this executable does link) have been found, so the + // wrapper libraries will also be found. On Windows this + // executable may have simply found its .dll files next to itself + // so the wrapper libraries may not be found when the wrapper + // modules are loaded. Solve this problem by adding this + // executable's location to the system PATH variable. Note that + // this need only be done for an installed VTK because in the + // build tree the wrapper modules are in the same directory as the + // wrapper libraries. +#if defined(_WIN32) + static char system_path[(VTK_PYTHON_MAXPATH+1)*10] = "PATH="; + strcat(system_path, self_dir); + if(char* oldpath = getenv("PATH")) + { + strcat(system_path, ";"); + strcat(system_path, oldpath); + } + putenv(system_path); +#endif + } +} diff --git a/Wrapping/Python/vtkPythonAppInitConfigure.h.in b/Wrapping/Python/vtkPythonAppInitConfigure.h.in new file mode 100644 index 0000000..96aaa25 --- /dev/null +++ b/Wrapping/Python/vtkPythonAppInitConfigure.h.in @@ -0,0 +1,6 @@ +#ifndef __vtkPythonAppInitConfigure_h +#define __vtkPythonAppInitConfigure_h + +#define VTK_PYTHON_LIBRARY_DIR_BUILD "@LIBRARY_OUTPUT_PATH@" + +#endif diff --git a/Wrapping/Python/vtkpython.cxx.in b/Wrapping/Python/vtkpython.cxx.in new file mode 100644 index 0000000..89d59d1 --- /dev/null +++ b/Wrapping/Python/vtkpython.cxx.in @@ -0,0 +1,2 @@ +/* This file has been replaced by vtkPythonAppInit and vtkParaPythonAppInit. */ + diff --git a/Wrapping/README.txt b/Wrapping/README.txt new file mode 100644 index 0000000..9c2649e --- /dev/null +++ b/Wrapping/README.txt @@ -0,0 +1,37 @@ +Notes on usage of LEX and YACC to generate VTK parse files +---------------------------------------------------------- + +LEX: +---- +1. vtkParse.l is edited as necessary +2. LEX is run (should be flex. Last tested on flex version 2.5.4 on Cygwin, + but it should work on Linux or on anything that uses flex) +3. LEX spits out lex.yy.c +4. Remove line: + #include <unistd.h> + Suggested method is to run: + + perl -ne "s/\t/ /g; next if /unistd/; print" lex.yy.c > lex.yy.c.new + mv lex.yy.c.new lex.yy.c + + This removes the line and replaces tabs with spaces. + +YACC: +----- +1. vtkParse.y is edited as necessary +2. yacc is run: "yacc -b vtkParse vtkParse.y" and spits out vtkParse.tab.c + (Note: yacc was run RedHat Linux 5.2 1/14/00 by W. Schroeder) +3. Build vtkHTML.exe, vtkWrapTcl.exe, vtkParseJava.exe,vtkWrapJava.exe, + vtkWrapPython.exe on the PC and check them in. +4. Check in vtkParse.l, lex.yy.c, vtkParse.y, vtkParse.tab.c + + +Important Note on YACC: +----------------------- + + Do not use GNU Bison on vtkParse.y. New versions won't even parse + the file and old ones will create compile problems on various + platforms. Use a recent byacc instead. Byacc is the Berkeley LALR + parser generator. Red Hat Linux apparently installs byacc by + default. + diff --git a/Wrapping/Tcl/CMakeLists.txt b/Wrapping/Tcl/CMakeLists.txt new file mode 100644 index 0000000..26b8115 --- /dev/null +++ b/Wrapping/Tcl/CMakeLists.txt @@ -0,0 +1,201 @@ +# Defined local options to add to VTK Tcl interpreter +# +# Example of such options are: +# VTK_EXTRA_TCL_WRAPPING_CODE which should define extra code that will be +# added to vtkTkAppInitConfigure.h. This code may include something like +# +# +# extern "C" int Vtkmyspecialtcl_Init(Tcl_Interp *interp); +# #define VTK_EXTRA_TCL_INIT \ +# if (Vtkmyspecialtcl_Init(interp) == TCL_ERROR) \ +# { +# return TCL_ERROR; +# } +# +# and +# +# SET(VTK_EXTRA_TCL_LIBRARIES ${VTK_EXTRA_TCL_LIBRARIES} vtkMySpecialTCL) +INCLUDE (${VTK_BINARY_DIR}/Wrapping/Tcl/LocalUserOptions.cmake OPTIONAL) +INCLUDE (${VTK_SOURCE_DIR}/Wrapping/Tcl/LocalUserOptions.cmake OPTIONAL) + +CONFIGURE_FILE( + ${VTK_SOURCE_DIR}/Wrapping/Tcl/vtkTkAppInitConfigure.h.in + ${VTK_BINARY_DIR}/Wrapping/Tcl/vtkTkAppInitConfigure.h + @ONLY IMMEDIATE +) + +IF (NOT TCL_LIBRARY) + MESSAGE("VTK_WRAP_TCL is ON, but the Tcl library was not found. Please set TCL_LIBRARY." "Error") +ENDIF (NOT TCL_LIBRARY) + +IF (WIN32) + IF (NOT BORLAND) + IF(NOT CYGWIN) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/resources/vtk.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/resources/vtk.rc) + INCLUDE_DIRECTORIES( + "${VTK_TK_RESOURCES_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/resources" + "${CMAKE_CURRENT_BINARY_DIR}/resources" + ) + SET(VTK_EXE_RESOURCE_FILES + "${CMAKE_CURRENT_BINARY_DIR}/resources/vtk.rc") + ENDIF(NOT CYGWIN) + ENDIF (NOT BORLAND) +ENDIF (WIN32) + +# Create the vtk Tcl wrapper executable. +ADD_EXECUTABLE(vtk vtkTkAppInit.cxx ${VTK_EXE_RESOURCE_FILES}) +TARGET_LINK_LIBRARIES (vtk + vtkCommonTCL + vtkFilteringTCL + vtkGraphicsTCL + vtkImagingTCL + vtkIOTCL +) + +IF(VTK_USE_CARBON) + FIND_PROGRAM(VTK_APPLE_RESOURCE Rez /Developer/Tools) + IF(VTK_APPLE_RESOURCE) + ADD_CUSTOM_COMMAND( + SOURCE vtk + COMMAND ${VTK_APPLE_RESOURCE} + ARGS Carbon.r -o ${VTK_EXECUTABLE_DIR}/vtk + TARGET vtk + ) + ENDIF(VTK_APPLE_RESOURCE) +ENDIF(VTK_USE_CARBON) + +IF (VTK_USE_RENDERING) + TARGET_LINK_LIBRARIES(vtk vtkRenderingTCL) + TARGET_LINK_LIBRARIES(vtk vtkVolumeRenderingTCL) + TARGET_LINK_LIBRARIES(vtk vtkHybridTCL) + TARGET_LINK_LIBRARIES(vtk vtkWidgetsTCL) +ENDIF (VTK_USE_RENDERING) + +IF (VTK_USE_PARALLEL) + TARGET_LINK_LIBRARIES(vtk vtkParallelTCL) +ENDIF (VTK_USE_PARALLEL) + +# Link to extra TCL libraries +FOREACH(lib ${VTK_EXTRA_TCL_LIBRARIES}) + TARGET_LINK_LIBRARIES(vtk ${lib}) +ENDFOREACH(lib) + +# Setup install location for vtk tcl scripts. +SET(VTK_TCL_INSTALL_DIR ${VTK_INSTALL_TCL_DIR}/tcl) + +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_TARGETS(${VTK_INSTALL_BIN_DIR} vtk) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + +# Create the pvtk Tcl wrapper executable with MPI support. +IF (VTK_USE_PARALLEL) + IF (VTK_USE_MPI) + ADD_EXECUTABLE(pvtk vtkParaTkAppInit.cxx ${VTK_EXE_RESOURCE_FILES}) + IF(VTK_USE_CARBON) + FIND_PROGRAM(VTK_APPLE_RESOURCE Rez /Developer/Tools) + IF(VTK_APPLE_RESOURCE) + ADD_CUSTOM_COMMAND( + SOURCE pvtk + COMMAND ${VTK_APPLE_RESOURCE} + ARGS Carbon.r -o ${VTK_EXECUTABLE_DIR}/pvtk + TARGET pvtk + ) + ENDIF(VTK_APPLE_RESOURCE) + ENDIF(VTK_USE_CARBON) + + TARGET_LINK_LIBRARIES (pvtk + vtkCommonTCL + vtkFilteringTCL + vtkGraphicsTCL + vtkImagingTCL + vtkIOTCL + vtkParallelTCL + ) + + IF (VTK_USE_RENDERING) + TARGET_LINK_LIBRARIES(pvtk vtkHybridTCL) + TARGET_LINK_LIBRARIES(pvtk vtkWidgetsTCL) + TARGET_LINK_LIBRARIES(pvtk vtkVolumeRenderingTCL) + ENDIF (VTK_USE_RENDERING) + + IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_TARGETS(${VTK_INSTALL_BIN_DIR} pvtk) + ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + ENDIF (VTK_USE_MPI) +ENDIF (VTK_USE_PARALLEL) + +# Process all packages +SUBDIRS(vtk vtkbase vtkcommon vtkfiltering vtkgraphics vtkimaging vtkinteraction vtkio vtktesting) + +IF(NOT VTK_INSTALL_NO_DOCUMENTATION) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR} "" README) +ENDIF(NOT VTK_INSTALL_NO_DOCUMENTATION) +IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR} .c vtktcl) +ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) + +SET(VTK_TCL_RENDERING_CONFIG "") +SET(VTK_TCL_VOLUMERENDERING_CONFIG "") +SET(VTK_TCL_HYBRID_CONFIG "") +SET(VTK_TCL_WIDGETS_CONFIG "") +SET(VTK_TCL_PARALLEL_CONFIG "") + +IF (VTK_USE_PARALLEL) + SET(VTK_TCL_PARALLEL_CONFIG "Parallel") + SUBDIRS(vtkparallel) +ENDIF (VTK_USE_PARALLEL) + +IF (VTK_USE_RENDERING) + SET(VTK_TCL_WIDGETS_CONFIG "Widgets") + SUBDIRS(vtkwidgets) + SET(VTK_TCL_HYBRID_CONFIG "Hybrid") + SUBDIRS(vtkhybrid) + SET(VTK_TCL_VOLUMERENDERING_CONFIG "VolumeRendering") + SUBDIRS(vtkvolumerendering) + SET(VTK_TCL_RENDERING_CONFIG "Rendering") + SUBDIRS(vtkrendering) +ENDIF (VTK_USE_RENDERING) + +# Configure the Tcl package index files for the build tree. +SET(VTK_TCL_SCRIPT_DIR "${VTK_SOURCE_DIR}/Wrapping/Tcl") + +SET(VTK_TCL_LIBNAME_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}") +SET(VTK_TCL_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}) + +IF(VTK_TCL_CONFIGURATION_TYPES) + FOREACH(config ${VTK_TCL_CONFIGURATION_TYPES}) + SET(VTK_TCL_LIBRARY_DIR "${LIBRARY_OUTPUT_PATH}/${config}") + CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Tcl/pkgIndex.tcl.in + ${VTK_BINARY_DIR}/Wrapping/Tcl/${config}/pkgIndex.tcl + @ONLY IMMEDIATE) + ENDFOREACH(config) +ELSE(VTK_TCL_CONFIGURATION_TYPES) + SET(VTK_TCL_LIBRARY_DIR "${LIBRARY_OUTPUT_PATH}") + CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Tcl/pkgIndex.tcl.in + ${VTK_BINARY_DIR}/Wrapping/Tcl/pkgIndex.tcl + @ONLY IMMEDIATE) +ENDIF(VTK_TCL_CONFIGURATION_TYPES) + +# Configure the Tcl package index file for the install tree. +SET(VTK_TCL_SCRIPT_DIR "[file dirname [info script]]/tcl") +IF(UNIX) + SET(VTK_TCL_LIBRARY_DIR "[file dirname [file dirname [info script]]]") +ELSE(UNIX) + SET(VTK_TCL_LIBRARY_DIR + "[file join [file dirname [file dirname [file dirname [info script]]]] bin]") +ENDIF(UNIX) +CONFIGURE_FILE(${VTK_SOURCE_DIR}/Wrapping/Tcl/pkgIndex.tcl.in + ${VTK_BINARY_DIR}/Wrapping/Tcl/Install/Hide/pkgIndex.tcl + @ONLY IMMEDIATE) +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_INSTALL_TCL_DIR} FILES + ${VTK_BINARY_DIR}/Wrapping/Tcl/Install/Hide/pkgIndex.tcl) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) + +# Allow the user to customize their build with some local options +# +INCLUDE (${VTK_BINARY_DIR}/Wrapping/Tcl/LocalUserOptions.cmake OPTIONAL) +INCLUDE (${VTK_SOURCE_DIR}/Wrapping/Tcl/LocalUserOptions.cmake OPTIONAL) diff --git a/Wrapping/Tcl/README b/Wrapping/Tcl/README new file mode 100644 index 0000000..0e579f2 --- /dev/null +++ b/Wrapping/Tcl/README @@ -0,0 +1,160 @@ +VTK Tcl wrappers +=========================================================================== + + I) Invoking the VTK package(s) + II) Invoking additional packages +III) Installing the packages + + + +============================= + I) Invoking the VTK Tcl package(s) + +Load the whole VTK API by issuing the following line before any +invocation of a VTK command (typically at the top of your Tcl script): + + package require vtk + +This will load all VTK components and the corresponding +commands. Depending on how VTK was built, some components might not be +available (since Hybrid, Parallel, and Rendering can be +excluded). + +VTK may also be used on a component-by-component basis by requiring +the component explicitly. Example: + + package require vtkrendering + +The above line will resolve the dependencies and invoke (in that case) +the vtkgraphics and vtkimaging packages automatically (which will +trigger the vtkfiltering and vtkcommon packages too). This method can +be used to speed-up startup-time since only the required commands will +be loaded. + + + +============================= + II) Invoking additional packages + + +A) vtkinteraction +************** + +The vtkinteraction package can be loaded to provide additional +interaction support. + + package require vtkinteraction + +i) Tcl interactor: + +The vtkinteraction package creates a generic Tcl interactor inside a +console widget, allowing you to issue any Tcl commands while running +the script. Once the package is loaded, a hidden .vtkInteract widget +is created. Bind a key or set the user method of your +vtkRenderWindowInteractor to deiconify that widget: + + vtkRenderWindowInteractor iren + [...] + iren SetUserMethod {wm deiconify .vtkInteract} + +Example: see Examples/GUI/Tcl/Mace.Tcl. + + +ii) 'vtkTkRenderWidget bindings': + +The vtkinteraction package also brings a set of user-interaction +bindings for the vtkTkRenderWidget class. It allows you to use this Tk +widget in a way similar to the usual VTK interactor. Once the package +is loaded, call ::vtk::bind_tk_render_widget to associate the bindings +to the render widget: + + set ren [vtkTkRenderWidget .ren -width 300 -height 300 -rw renWin] + ::vtk::bind_tk_render_widget $ren + +Example: see Examples/GUI/Tcl/MaceTk.Tcl. + + +B) vtktesting +************* + +Some developpers might load the vtktesting package to include +additional facilities. + + package require vtktesting + +Once loaded, the package provides the functions usually located in the following files: + + backdrop.tcl + colors.tcl + mccases.tcl + + + +============================= + IV) Installing the package index file + +A good description of the package and library facilities is given in +the Chapter 12 "Script, Libraries and Packages" (page 135) of +"Practical Programming in Tcl & Tk", Brent B. Welch, ISBN +0-13-616830-2. + +When a package is "required" by the 'package' command (see part I to +III), the Tcl interpreter looks through a set of directories and their +subdirectories for pkgIndex.tcl files. It sources those to build an +internal database of packages (and version information). + +A pkgIndex.tcl file is generated by this VTK distribution to provide +the packages described in the previous sections to the +interpreter. They will load the corresponding DLLs, set some default +behaviours/bindings/widgets and exit with an error message if the +package could not be provided (DLL not found, for example). + +The package facility assume that Tcl libraries (and packages) are kept +in well-known directories (and their subdirectories). The list of +well-known directories is kept in the auto_path Tcl variable. It is +initialized by tclsh or wish to provide default directories, including +the default Tcl script library directory. For example : + +Windows: +-------- + +% puts $auto_path +C:/devel/langages/tcl/8.3/lib/tcl8.3 C:/devel/langages/tcl/8.3/lib C:/devel/langages/tcl/8.3/lib/tk8.3 + +Linux/Unix: +-------- + +root [1003] ~/tmp# wish +% puts $auto_path +/usr/lib/tcl8.3 /usr/lib /usr/lib/tk8.3 + +Now let's see how we can make Tcl aware of the VTK Tcl packages. Tcl +provides a way for you to tell the Tcl interpreter to search for +pkgIndex.tcl files in any user-specified directory (and its +subdirectories). Just set the TCLLIBPATH environment variable to a set +of space-separated directories to search in (warning: Windows users +shall use '/' instead of '\'). + +If you have a VTK build tree on your hard disk, add Wrapping/Tcl to +TCLLIBPATH. For example: + +Windows: +-------- + +TCLLIBPATH=C:/Project/VTK-msvc6/Wrapping/Tcl/Debug + +Now check auto_path : + +% puts $auto_path +C:/Project/VTK-msvc6/Wrapping/Tcl/Debug C:/devel/langages/tcl/8.3/lib/tcl8.3 C:/devel/langages/tcl/8.3/lib C:/devel/langages/tcl/8.3/lib/tk8.3 + +Linux/Unix: +-------- + +root [1011] ~/tmp# export TCLLIBPATH=/home/myuser/VTK-gcc/Wrapping/Tcl +root [1012] ~/tmp# wish +% puts $auto_path +/home/myuser/VTK-gcc/Wrapping/Tcl /usr/lib/tcl8.3 /usr/lib /usr/lib/tk8.3 + +This shall do the trick :)) +Sebastien BARRE (sebastien.barre@kitware.com) diff --git a/Wrapping/Tcl/pkgIndex.tcl.in b/Wrapping/Tcl/pkgIndex.tcl.in new file mode 100644 index 0000000..6d74429 --- /dev/null +++ b/Wrapping/Tcl/pkgIndex.tcl.in @@ -0,0 +1,57 @@ +# Visualization Toolkit (VTK) Tcl package configuration. + +package ifneeded vtkinit {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} { + namespace eval ::vtk::init { + proc load_library_package {libName libPath {libPrefix {@VTK_TCL_LIBNAME_PREFIX@}}} { + set libExt [info sharedlibextension] + set currentDirectory [pwd] + set libFile [file join $libPath "$libPrefix$libName$libExt"] + if {[catch "cd {$libPath}; load {$libFile}" errorMessage]} { + puts $errorMessage + } + cd $currentDirectory + } + proc require_package {name {version {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@}}} { + if {[catch "package require -exact $name $version" errorMessage]} { + puts $errorMessage + return 0 + } else { + return 1 + } + } + set version {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} + set kits {} + foreach kit { base Common Filtering IO Imaging Graphics + @VTK_TCL_RENDERING_CONFIG@ @VTK_TCL_VOLUMERENDERING_CONFIG@ + @VTK_TCL_HYBRID_CONFIG@ @VTK_TCL_WIDGETS_CONFIG@ + @VTK_TCL_PARALLEL_CONFIG@ } { + lappend kits [string tolower "${kit}"] + } + } + package provide vtkinit {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} +} + +foreach kit { Common Filtering IO Imaging Graphics + @VTK_TCL_RENDERING_CONFIG@ @VTK_TCL_VOLUMERENDERING_CONFIG@ + @VTK_TCL_HYBRID_CONFIG@ @VTK_TCL_WIDGETS_CONFIG@ + @VTK_TCL_PARALLEL_CONFIG@ } { + package ifneeded "vtk${kit}TCL" {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} " + package require -exact vtkinit {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} + ::vtk::init::load_library_package {vtk${kit}TCL} {@VTK_TCL_LIBRARY_DIR@} + " + package ifneeded "vtk[string tolower ${kit}]" {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} " + package require -exact vtkinit {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} + if {\[catch {source \[file join {@VTK_TCL_SCRIPT_DIR@} {vtk[string tolower ${kit}]} {vtk[string tolower ${kit}].tcl}\]} errorMessage\]} { + puts \$errorMessage + } + " +} + +foreach src {vtk vtkbase vtkinteraction vtktesting} { + package ifneeded ${src} {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} " + package require -exact vtkinit {@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@} + if {\[catch {source \[file join {@VTK_TCL_SCRIPT_DIR@} {$src} {$src.tcl}\]} errorMessage\]} { + puts \$errorMessage + } + " +} diff --git a/Wrapping/Tcl/resources/vtk.rc.in b/Wrapping/Tcl/resources/vtk.rc.in new file mode 100644 index 0000000..bdd9b3e --- /dev/null +++ b/Wrapping/Tcl/resources/vtk.rc.in @@ -0,0 +1,44 @@ +#include "vtkrc.h" + +// The icon whose name or resource ID is lexigraphically first, is used +// as the application's icon. +// Tk was defining app. + +//IDI_APPLICATION ICON DISCARDABLE "vtkicon32.ico" +//IDI_VTKICO ICON DISCARDABLE "vtkicon32.ico" +//IDI_VTKICOSMALL ICON DISCARDABLE "vtkicon16.ico" + + + +#include <windows.h> + +#include "vtkConfigure.h" +#ifdef VTK_TCL_TK_STATIC +#include "tk_base.rc" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @VTK_MAJOR_VERSION@,@VTK_MINOR_VERSION@ + PRODUCTVERSION @VTK_MAJOR_VERSION@,@VTK_MINOR_VERSION@ + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "VTK\0" + VALUE "OriginalFilename", "vtk.exe\0" + VALUE "CompanyName", "Kitware Inc.\0" + VALUE "FileVersion", "@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@\0" + VALUE "LegalCopyright", "Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\0" + VALUE "ProductName", "VTK @VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@ for Windows\0" + VALUE "ProductVersion", "@VTK_MAJOR_VERSION@.@VTK_MINOR_VERSION@\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/Wrapping/Tcl/resources/vtkrc.h b/Wrapping/Tcl/resources/vtkrc.h new file mode 100644 index 0000000..99ae610 --- /dev/null +++ b/Wrapping/Tcl/resources/vtkrc.h @@ -0,0 +1,17 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkrc.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#define IDI_VTKICO 107 +#define IDI_VTKICOSMALL 108 + diff --git a/Wrapping/Tcl/vtk/CMakeLists.txt b/Wrapping/Tcl/vtk/CMakeLists.txt new file mode 100644 index 0000000..3045739 --- /dev/null +++ b/Wrapping/Tcl/vtk/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtk .tcl vtk ) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtk/vtk.tcl b/Wrapping/Tcl/vtk/vtk.tcl new file mode 100644 index 0000000..387b4f5 --- /dev/null +++ b/Wrapping/Tcl/vtk/vtk.tcl @@ -0,0 +1,13 @@ +foreach kit ${vtk::init::kits} { + package require -exact vtk${kit} 5.0 +} + +# Invoke DeleteAllObjects on exit + +rename ::exit ::vtk::exit +proc ::exit {{returnCode 0}} { + vtkCommand DeleteAllObjects + return [::vtk::exit $returnCode] +} + +package provide vtk 5.0 diff --git a/Wrapping/Tcl/vtkDetermineTkResources.cmake b/Wrapping/Tcl/vtkDetermineTkResources.cmake new file mode 100644 index 0000000..ed7ad2e --- /dev/null +++ b/Wrapping/Tcl/vtkDetermineTkResources.cmake @@ -0,0 +1,18 @@ +IF (WIN32) + IF (NOT BORLAND) + IF(NOT CYGWIN) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + IF (TCL_TK_MAJOR_VERSION AND TCL_TK_MINOR_VERSION) + SET (VTK_TK_RESOURCE_FILE_TRY + "${VTK_SOURCE_DIR}/Utilities/TclTk/resources/tk${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}/win/rc/tk.rc") + IF (EXISTS ${VTK_TK_RESOURCE_FILE_TRY}) + GET_FILENAME_COMPONENT(dir ${VTK_TK_RESOURCE_FILE_TRY} PATH) + SET(VTK_TK_RESOURCES_DIR ${dir} CACHE INTERNAL + "The directory where the tk.rc and other Tk resource files can be found. They are required to add the proper resources to a Tk command-line interpreter (vtk.exe for example)") + INCLUDE_DIRECTORIES(${VTK_TK_RESOURCES_DIR}) + ENDIF (EXISTS ${VTK_TK_RESOURCE_FILE_TRY}) + ENDIF (TCL_TK_MAJOR_VERSION AND TCL_TK_MINOR_VERSION) + ENDIF(NOT CYGWIN) + ENDIF (NOT BORLAND) +ENDIF (WIN32) + diff --git a/Wrapping/Tcl/vtkParaTkAppInit.cxx b/Wrapping/Tcl/vtkParaTkAppInit.cxx new file mode 100644 index 0000000..ed48838 --- /dev/null +++ b/Wrapping/Tcl/vtkParaTkAppInit.cxx @@ -0,0 +1,16 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParaTkAppInit.cxx,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#define VTK_COMPILED_USING_MPI +#include "vtkTkAppInit.cxx" diff --git a/Wrapping/Tcl/vtkTkAppInit.cxx b/Wrapping/Tcl/vtkTkAppInit.cxx new file mode 100644 index 0000000..78e9935 --- /dev/null +++ b/Wrapping/Tcl/vtkTkAppInit.cxx @@ -0,0 +1,371 @@ +/*========================================================================= + +Program: Visualization Toolkit +Module: $RCSfile: vtkTkAppInit.cxx,v $ + +Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. +See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +/* + * tkAppInit.c -- + * + * Provides a default version of the Tcl_AppInit procedure for + * use in wish and similar Tk-based applications. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifdef VTK_COMPILED_USING_MPI +# include <mpi.h> +# include "vtkMPIController.h" +#endif // VTK_COMPILED_USING_MPI + +#include "vtkConfigure.h" +#include "vtkSystemIncludes.h" +#include "vtkToolkits.h" +#include "Wrapping/Tcl/vtkTkAppInitConfigure.h" + +#ifdef VTK_TCL_TK_COPY_SUPPORT_LIBRARY +#include <sys/stat.h> +#endif + +#ifdef VTK_USE_TK +# include "vtkTk.h" +#else +# include "vtkTcl.h" +#endif + +/* + * Make sure all the kits register their classes with vtkInstantiator. + */ +#include "vtkCommonInstantiator.h" +#include "vtkFilteringInstantiator.h" +#include "vtkIOInstantiator.h" +#include "vtkImagingInstantiator.h" +#include "vtkGraphicsInstantiator.h" + +#ifdef VTK_USE_RENDERING +#include "vtkRenderingInstantiator.h" +#include "vtkVolumeRenderingInstantiator.h" +#include "vtkHybridInstantiator.h" +#include "vtkWidgetsInstantiator.h" +#endif + +#ifdef VTK_USE_PARALLEL +#include "vtkParallelInstantiator.h" +#endif + +#include "vtkTclUtil.h" + +static void vtkTkAppInitEnableMSVCDebugHook(); + +// I need those two Tcl functions. They usually are declared in tclIntDecls.h, +// but Unix build do not have access to VTK's tkInternals include path. +// Since the signature has not changed for years (at least since 8.2), +// let's just prototype them. + +EXTERN Tcl_Obj* TclGetLibraryPath _ANSI_ARGS_((void)); +EXTERN void TclSetLibraryPath _ANSI_ARGS_((Tcl_Obj * pathPtr)); + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tk_Main never returns here, so this procedure never + * returns either. + * + * Side effects: + * Whatever the application does. + * + *---------------------------------------------------------------------- + */ +#ifdef VTK_COMPILED_USING_MPI +class vtkMPICleanup { +public: + vtkMPICleanup() + { + this->Controller = 0; + } + void Initialize(int *argc, char ***argv) + { + MPI_Init(argc, argv); + this->Controller = vtkMPIController::New(); + this->Controller->Initialize(argc, argv, 1); + vtkMultiProcessController::SetGlobalController(this->Controller); + } + ~vtkMPICleanup() + { + if ( this->Controller ) + { + this->Controller->Finalize(); + this->Controller->Delete(); + } + } +private: + vtkMPIController *Controller; +}; + +static vtkMPICleanup VTKMPICleanup; + +#endif // VTK_COMPILED_USING_MPI + +int +main(int argc, char **argv) +{ + ios::sync_with_stdio(); + vtkTkAppInitEnableMSVCDebugHook(); + +#ifdef VTK_COMPILED_USING_MPI + VTKMPICleanup.Initialize(&argc, &argv); +#endif // VTK_COMPILED_USING_MPI + + // This is mandatory *now*, it does more than just finding the executable + // (like finding the encodings, setting variables depending on the value + // of TCL_LIBRARY, TK_LIBRARY + + vtkTclApplicationInitExecutable(argc, argv); + +#ifdef VTK_USE_TK + Tk_Main(argc, argv, Tcl_AppInit); +#else + Tcl_Main(argc, argv, Tcl_AppInit); +#endif + + return 0; /* Needed only to prevent compiler warning. */ +} + + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. + * Most applications, especially those that incorporate additional + * packages, will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error + * message in interp->result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +extern "C" int Vtkcommontcl_Init(Tcl_Interp *interp); +extern "C" int Vtkfilteringtcl_Init(Tcl_Interp *interp); +extern "C" int Vtkimagingtcl_Init(Tcl_Interp *interp); +extern "C" int Vtkgraphicstcl_Init(Tcl_Interp *interp); +extern "C" int Vtkiotcl_Init(Tcl_Interp *interp); + +#ifdef VTK_USE_RENDERING +extern "C" int Vtkrenderingtcl_Init(Tcl_Interp *interp); + +#if defined(VTK_USE_TK) +extern "C" int Vtktkrenderwidget_Init(Tcl_Interp *interp); +extern "C" int Vtktkimageviewerwidget_Init(Tcl_Interp *interp); +#endif + +extern "C" int Vtkvolumerenderingtcl_Init(Tcl_Interp *interp); +extern "C" int Vtkhybridtcl_Init(Tcl_Interp *interp); +extern "C" int Vtkwidgetstcl_Init(Tcl_Interp *interp); +#endif + +#ifdef VTK_USE_PARALLEL +extern "C" int Vtkparalleltcl_Init(Tcl_Interp *interp); +#endif + +void help() +{ +} + +int Tcl_AppInit(Tcl_Interp *interp) +{ +#ifdef __CYGWIN__ + Tcl_SetVar(interp, "tclDefaultLibrary", "/usr/share/tcl" TCL_VERSION, TCL_GLOBAL_ONLY); +#endif + + // Help Tcl find the Tcl/Tk helper files. + const char* relative_dirs[] = + { + "TclTk/lib", + ".." VTK_INSTALL_TCL_DIR, + 0 + }; + vtkTclApplicationInitTclTk(interp, relative_dirs); + + if (Tcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + +#ifdef VTK_USE_TK + if (Tk_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } +#endif + + /* init the core vtk stuff */ + if (Vtkcommontcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkfilteringtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkimagingtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkgraphicstcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkiotcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + +#ifdef VTK_USE_RENDERING + if (Vtkrenderingtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + +#if defined(VTK_USE_TK) + if (Vtktkrenderwidget_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtktkimageviewerwidget_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } +#endif + + if (Vtkvolumerenderingtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + + if (Vtkhybridtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + + if (Vtkwidgetstcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } +#endif + +#ifdef VTK_USE_PARALLEL + if (Vtkparalleltcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } +#endif + +#ifdef VTK_EXTRA_TCL_INIT + VTK_EXTRA_TCL_INIT; +#endif + + /* + * Append path to VTK packages to auto_path + */ + static char script[] = + "foreach dir [list " +#if defined(CMAKE_INTDIR) + " [file join [file dirname [file dirname [file dirname [info nameofexecutable]]]] Wrapping Tcl " CMAKE_INTDIR "]" +#else + " [file join [file dirname [file dirname [info nameofexecutable]]] Wrapping Tcl]" +#endif + " ] {\n" + " if {[file isdirectory \"$dir\"]} {\n" + " lappend auto_path $dir\n" + " }\n" + "}\n" + "rename package package.orig\n" + "proc package {args} {\n" + " if {[catch {set package_res [eval package.orig $args]} catch_res]} {\n" + " global errorInfo env\n" + " if {[lindex $args 0] == \"require\"} {\n" + " set expecting {can\'t find package vtk}\n" + " if {![string compare -length [string length $expecting] $catch_res $expecting]} {\n" + " set msg {The Tcl interpreter was probably not able to find the" + " VTK packages. Please check that your TCLLIBPATH environment variable" + " includes the path to your VTK Tcl directory. You might find it under" + " your VTK binary directory in Wrapping/Tcl, or under your" + " site-specific installation directory.}\n" + " if {[info exists env(TCLLIBPATH)]} {\n" + " append msg \" The TCLLIBPATH current value is: $env(TCLLIBPATH).\"\n" + " }\n" + " set errorInfo \"$msg The TCLLIBPATH variable is a set of" + " space separated paths (hence, path containing spaces should be" + " surrounded by quotes first). Windows users should use forward" + " (Unix-style) slashes \'/\' instead of the usual backward slashes. " + " More informations can be found in the Wrapping/Tcl/README source" + " file (also available online at" + " http://www.vtk.org/cgi-bin/cvsweb.cgi/~checkout~/VTK/Wrapping/Tcl/README).\n" + "$errorInfo\"\n" + " }\n" + " }\n" + " error $catch_res $errorInfo\n" + " }\n" + " return $package_res\n" + "}\n"; + Tcl_Eval(interp, script); + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + + Tcl_SetVar(interp, + (char *) "tcl_rcFileName", + (char *) "~/.vtkrc", + TCL_GLOBAL_ONLY); + return TCL_OK; +} + +// For a DEBUG build on MSVC, add a hook to prevent error dialogs when +// being run from DART. +#if defined(_MSC_VER) && defined(_DEBUG) +# include <crtdbg.h> +static int vtkTkAppInitDebugReport(int, char* message, int*) +{ + fprintf(stderr, message); + exit(1); +} +void vtkTkAppInitEnableMSVCDebugHook() +{ + if(getenv("DART_TEST_FROM_DART")) + { + _CrtSetReportHook(vtkTkAppInitDebugReport); + } +} +#else +void vtkTkAppInitEnableMSVCDebugHook() +{ +} +#endif diff --git a/Wrapping/Tcl/vtkTkAppInitConfigure.h.in b/Wrapping/Tcl/vtkTkAppInitConfigure.h.in new file mode 100644 index 0000000..fd9c1aa --- /dev/null +++ b/Wrapping/Tcl/vtkTkAppInitConfigure.h.in @@ -0,0 +1,8 @@ +#ifndef __vtkTkAppInitConfigure_h +#define __vtkTkAppInitConfigure_h + +#define VTK_INSTALL_TCL_DIR "@VTK_INSTALL_TCL_DIR@" + +@VTK_EXTRA_TCL_WRAPPING_CODE@ + +#endif diff --git a/Wrapping/Tcl/vtkbase/CMakeLists.txt b/Wrapping/Tcl/vtkbase/CMakeLists.txt new file mode 100644 index 0000000..4bec7bb --- /dev/null +++ b/Wrapping/Tcl/vtkbase/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkbase .tcl vtkbase) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkbase/vtkbase.tcl b/Wrapping/Tcl/vtkbase/vtkbase.tcl new file mode 100644 index 0000000..9ad2c22 --- /dev/null +++ b/Wrapping/Tcl/vtkbase/vtkbase.tcl @@ -0,0 +1,106 @@ +package provide vtkbase 5.0 + +namespace eval ::vtk { + + namespace export * + + # load_component: load a VTK component + # Example: ::vtk::load_component vtkFilteringTCL + + # Windows: the 'load' command looks for DLL in the Tcl/Tk dir, + # the current dir, c:\window\system[32], c:\windows and the dirs + # listed in the PATH environment var. + # Unix: the 'load' command looks for shared libs in dirs listed in the + # LD_LIBRARY_PATH environment var. + + variable complain_on_loading 1 + + proc load_component {name {optional_paths {}}} { + + global tcl_platform auto_path env + + # First dir is empty, to let Tcl try in the current dir + + set dirs $optional_paths + set dirs [concat $dirs {""}] + set ext [info sharedlibextension] + if {$tcl_platform(platform) == "unix"} { + set prefix "lib" + # Help Unix a bit by browsing into $auto_path and /usr/lib... + set dirs [concat $dirs /usr/local/lib /usr/local/lib/vtk $auto_path] + if {[info exists env(LD_LIBRARY_PATH)]} { + set dirs [concat $dirs [split $env(LD_LIBRARY_PATH) ":"]] + } + if {[info exists env(PATH)]} { + set dirs [concat $dirs [split $env(PATH) ":"]] + } + } else { + set prefix "" + if {$tcl_platform(platform) == "windows"} { + if {[info exists env(PATH)]} { + set dirs [concat $dirs [split $env(PATH) ";"]] + } + } + } + + foreach dir $dirs { + set libname [file join $dir ${prefix}${name}${ext}] + if {[file exists $libname]} { + if {![catch {load $libname} errormsg]} { + # WARNING: it HAS to be "" so that pkg_mkIndex work (since + # while evaluating a package ::vtk::load_component won't + # exist and will default to the unknown() proc that + # returns "" + return "" + } elseif {$::vtk::complain_on_loading} { + # If not loaded but file was found, oops + puts stderr $errormsg + } + } + } + + if {$::vtk::complain_on_loading} { + puts stderr "::vtk::load_component: $name could not be found." + } + + return 1 + } + + # Function returning either a command line argument, an environment + # variable or a default value. + + proc get_arg_or_env_or_default {arg envvar def} { + + # Look at command line args + + global argc argv + if {[info exists argc]} { + set argcm1 [expr $argc - 1] + for {set i 0} {$i < $argcm1} {incr i} { + if {[lindex $argv $i] == $arg && $i < $argcm1} { + return [lindex $argv [expr $i + 1]] + } + } + } + + # Look at environment vars + + global env + if {[info exists env($envvar)]} { + return $env($envvar) + } + + # Return default + + return $def + } + + # Get VTK_DATA_ROOT if we can + + variable VTK_DATA_ROOT [::vtk::get_arg_or_env_or_default \ + "-D" \ + "VTK_DATA_ROOT" \ + [file nativename [file join [file dirname [info script]] "../../../../VTKData"]]] +} + +set VTK_DATA_ROOT $::vtk::VTK_DATA_ROOT diff --git a/Wrapping/Tcl/vtkcommon/CMakeLists.txt b/Wrapping/Tcl/vtkcommon/CMakeLists.txt new file mode 100644 index 0000000..c087d76 --- /dev/null +++ b/Wrapping/Tcl/vtkcommon/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkcommon .tcl vtkcommon) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkcommon/vtkcommon.tcl b/Wrapping/Tcl/vtkcommon/vtkcommon.tcl new file mode 100644 index 0000000..ba88fc0 --- /dev/null +++ b/Wrapping/Tcl/vtkcommon/vtkcommon.tcl @@ -0,0 +1,20 @@ +package require -exact vtkbase 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkCommonTCL 5.0]} { + package provide vtkcommon 5.0 + } +} else { + puts stderr "Warning: Your TCLLIBPATH points to the VTK source tree. \ + Support for this is deprecated in VTK 4.2, and will be removed in a\ + future version. Please point TCLLIBPATH to\ + {VTK_BINARY_DIR}/Wrapping/Tcl<config>, where <config>\ + is the build configuration. The <config> value is empty for most\ + platforms, and /Debug, /Release, etc. for Visual Studio builds. \ + After this is done, you no longer need to set PATH or LD_LIBRARY_PATH\ + to point to the VTK build tree." + if {[info commands vtkObject] != "" || + [::vtk::load_component vtkCommonTCL] == ""} { + package provide vtkcommon 5.0 + } +} diff --git a/Wrapping/Tcl/vtkfiltering/CMakeLists.txt b/Wrapping/Tcl/vtkfiltering/CMakeLists.txt new file mode 100644 index 0000000..107e87a --- /dev/null +++ b/Wrapping/Tcl/vtkfiltering/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkfiltering .tcl vtkfiltering) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkfiltering/vtkfiltering.tcl b/Wrapping/Tcl/vtkfiltering/vtkfiltering.tcl new file mode 100644 index 0000000..38f578d --- /dev/null +++ b/Wrapping/Tcl/vtkfiltering/vtkfiltering.tcl @@ -0,0 +1,12 @@ +package require -exact vtkcommon 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkFilteringTCL 5.0]} { + package provide vtkfiltering 5.0 + } +} else { + if {[info commands vtkCardinalSpline] != "" || + [::vtk::load_component vtkFilteringTCL] == ""} { + package provide vtkfiltering 5.0 + } +} diff --git a/Wrapping/Tcl/vtkgraphics/CMakeLists.txt b/Wrapping/Tcl/vtkgraphics/CMakeLists.txt new file mode 100644 index 0000000..1530883 --- /dev/null +++ b/Wrapping/Tcl/vtkgraphics/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkgraphics .tcl vtkgraphics) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkgraphics/vtkgraphics.tcl b/Wrapping/Tcl/vtkgraphics/vtkgraphics.tcl new file mode 100644 index 0000000..273d0be --- /dev/null +++ b/Wrapping/Tcl/vtkgraphics/vtkgraphics.tcl @@ -0,0 +1,12 @@ +package require -exact vtkfiltering 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkGraphicsTCL 5.0]} { + package provide vtkgraphics 5.0 + } +} else { + if {[info commands vtkAxes] != "" || + [::vtk::load_component vtkGraphicsTCL] == ""} { + package provide vtkgraphics 5.0 + } +} diff --git a/Wrapping/Tcl/vtkhybrid/CMakeLists.txt b/Wrapping/Tcl/vtkhybrid/CMakeLists.txt new file mode 100644 index 0000000..205b13e --- /dev/null +++ b/Wrapping/Tcl/vtkhybrid/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkhybrid .tcl vtkhybrid) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkhybrid/vtkhybrid.tcl b/Wrapping/Tcl/vtkhybrid/vtkhybrid.tcl new file mode 100644 index 0000000..8b6e0ef --- /dev/null +++ b/Wrapping/Tcl/vtkhybrid/vtkhybrid.tcl @@ -0,0 +1,13 @@ +package require -exact vtkio 5.0 +package require -exact vtkrendering 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkHybridTCL 5.0]} { + package provide vtkhybrid 5.0 + } +} else { + if {[info commands vtkEarthSource] != "" || + [::vtk::load_component vtkHybridTCL] == ""} { + package provide vtkhybrid 5.0 + } +} diff --git a/Wrapping/Tcl/vtkimaging/CMakeLists.txt b/Wrapping/Tcl/vtkimaging/CMakeLists.txt new file mode 100644 index 0000000..940caf4 --- /dev/null +++ b/Wrapping/Tcl/vtkimaging/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkimaging .tcl vtkimaging ) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkimaging/vtkimaging.tcl b/Wrapping/Tcl/vtkimaging/vtkimaging.tcl new file mode 100644 index 0000000..dcc3f1d --- /dev/null +++ b/Wrapping/Tcl/vtkimaging/vtkimaging.tcl @@ -0,0 +1,12 @@ +package require -exact vtkfiltering 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkImagingTCL 5.0]} { + package provide vtkimaging 5.0 + } +} else { + if {[info commands vtkImageFFT] != "" || + [::vtk::load_component vtkImagingTCL] == ""} { + package provide vtkimaging 5.0 + } +} diff --git a/Wrapping/Tcl/vtkinteraction/CMakeLists.txt b/Wrapping/Tcl/vtkinteraction/CMakeLists.txt new file mode 100644 index 0000000..cc10ba3 --- /dev/null +++ b/Wrapping/Tcl/vtkinteraction/CMakeLists.txt @@ -0,0 +1,10 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkinteraction .tcl + vtkinteraction + Interactor + bindings + bindings-iw + bindings-rw + setget + ) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkinteraction/Interactor.tcl b/Wrapping/Tcl/vtkinteraction/Interactor.tcl new file mode 100644 index 0000000..7feac8e --- /dev/null +++ b/Wrapping/Tcl/vtkinteraction/Interactor.tcl @@ -0,0 +1,100 @@ +# a generic interactor for tcl and vtk +# + +catch {unset vtkInteract.bold} +catch {unset vtkInteract.normal} +catch {unset vtkInteract.tagcount} +set vtkInteractBold "-background #43ce80 -foreground #221133 -relief raised -borderwidth 1" +set vtkInteractNormal "-background #dddddd -foreground #221133 -relief flat" +set vtkInteractTagcount 1 +set vtkInteractCommandList "" +set vtkInteractCommandIndex 0 + +proc vtkInteract {} { + global vtkInteractCommandList vtkInteractCommandIndex + global vtkInteractTagcount + + proc dovtk {s w} { + global vtkInteractBold vtkInteractNormal vtkInteractTagcount + global vtkInteractCommandList vtkInteractCommandIndex + + set tag [append tagnum $vtkInteractTagcount] + set vtkInteractCommandIndex $vtkInteractTagcount + incr vtkInteractTagcount 1 + .vtkInteract.display.text configure -state normal + .vtkInteract.display.text insert end $s $tag + set vtkInteractCommandList [linsert $vtkInteractCommandList end $s] + eval .vtkInteract.display.text tag configure $tag $vtkInteractNormal + .vtkInteract.display.text tag bind $tag <Any-Enter> \ + ".vtkInteract.display.text tag configure $tag $vtkInteractBold" + .vtkInteract.display.text tag bind $tag <Any-Leave> \ + ".vtkInteract.display.text tag configure $tag $vtkInteractNormal" + .vtkInteract.display.text tag bind $tag <1> "dovtk [list $s] .vtkInteract" + .vtkInteract.display.text insert end \n; + .vtkInteract.display.text insert end [uplevel 1 $s] + .vtkInteract.display.text insert end \n\n + .vtkInteract.display.text configure -state disabled + .vtkInteract.display.text yview end + } + + catch {destroy .vtkInteract} + toplevel .vtkInteract -bg #bbbbbb + wm title .vtkInteract "vtk Interactor" + wm iconname .vtkInteract "vtk" + + frame .vtkInteract.buttons -bg #bbbbbb + pack .vtkInteract.buttons -side bottom -fill both -expand 0 -pady 2m + button .vtkInteract.buttons.dismiss -text Dismiss \ + -command "wm withdraw .vtkInteract" \ + -bg #bbbbbb -fg #221133 -activebackground #cccccc -activeforeground #221133 + pack .vtkInteract.buttons.dismiss -side left -expand 1 -fill x + + frame .vtkInteract.file -bg #bbbbbb + label .vtkInteract.file.label -text "Command:" -width 10 -anchor w \ + -bg #bbbbbb -fg #221133 + entry .vtkInteract.file.entry -width 40 \ + -bg #dddddd -fg #221133 -highlightthickness 1 -highlightcolor #221133 + bind .vtkInteract.file.entry <Return> { + dovtk [%W get] .vtkInteract; %W delete 0 end + } + pack .vtkInteract.file.label -side left + pack .vtkInteract.file.entry -side left -expand 1 -fill x + + frame .vtkInteract.display -bg #bbbbbb + text .vtkInteract.display.text -yscrollcommand ".vtkInteract.display.scroll set" \ + -setgrid true -width 60 -height 8 -wrap word -bg #dddddd -fg #331144 \ + -state disabled + scrollbar .vtkInteract.display.scroll \ + -command ".vtkInteract.display.text yview" -bg #bbbbbb \ + -troughcolor #bbbbbb -activebackground #cccccc -highlightthickness 0 + pack .vtkInteract.display.text -side left -expand 1 -fill both + pack .vtkInteract.display.scroll -side left -expand 0 -fill y + + pack .vtkInteract.display -side bottom -expand 1 -fill both + pack .vtkInteract.file -pady 3m -padx 2m -side bottom -fill x + + set vtkInteractCommandIndex 0 + + bind .vtkInteract <Down> { + if { $vtkInteractCommandIndex < [expr $vtkInteractTagcount - 1] } { + incr vtkInteractCommandIndex + set command_string [lindex $vtkInteractCommandList $vtkInteractCommandIndex] + .vtkInteract.file.entry delete 0 end + .vtkInteract.file.entry insert end $command_string + } elseif { $vtkInteractCommandIndex == [expr $vtkInteractTagcount - 1] } { + .vtkInteract.file.entry delete 0 end + } + } + + bind .vtkInteract <Up> { + if { $vtkInteractCommandIndex > 0 } { + set vtkInteractCommandIndex [expr $vtkInteractCommandIndex - 1] + set command_string [lindex $vtkInteractCommandList $vtkInteractCommandIndex] + .vtkInteract.file.entry delete 0 end + .vtkInteract.file.entry insert end $command_string + } + } + + wm withdraw .vtkInteract +} +vtkInteract diff --git a/Wrapping/Tcl/vtkinteraction/bindings-iw.tcl b/Wrapping/Tcl/vtkinteraction/bindings-iw.tcl new file mode 100644 index 0000000..e682735 --- /dev/null +++ b/Wrapping/Tcl/vtkinteraction/bindings-iw.tcl @@ -0,0 +1,223 @@ +namespace eval ::vtk { + + namespace export * + + # ------------------------------------------------------------------- + # Specific vtkTkImageViewerWidget bindings + + # Create a 2d text actor that can be used to display infos + # like window/level, pixel picking, etc + + proc cb_vtkiw_create_text1 {vtkiw} { + set mapper [::vtk::get_widget_variable_value $vtkiw text1_mapper] + if {$mapper == ""} { + set mapper \ + [::vtk::new_widget_object $vtkiw vtkTextMapper text1_mapper] + $mapper SetInput "none" + set tprop [$mapper GetTextProperty] + $tprop SetFontFamilyToArial + $tprop SetFontSize 12 + $tprop BoldOn + $tprop ShadowOn + $tprop SetColor 1 1 0.5 + } + set actor [::vtk::get_widget_variable_value $vtkiw text1_actor] + if {$actor == ""} { + set actor \ + [::vtk::new_widget_object $vtkiw vtkActor2D text1_actor] + $actor SetMapper $mapper + $actor SetLayerNumber 1 + [$actor GetPositionCoordinate] SetValue 5 4 0 + $actor SetVisibility 0 + [[$vtkiw GetImageViewer] GetRenderer] AddActor2D $actor + } + } + + # Show/Hide the 2d text actor + # Ensure that it stays in the upper left corner of the window + + proc cb_vtkiw_show_text1 {vtkiw} { + set actor [::vtk::get_widget_variable_value $vtkiw text1_actor] + if {![$actor GetVisibility]} { + set height [lindex [$vtkiw configure -height] 4] + set pos [$actor GetPositionCoordinate] + set value [$pos GetValue] + $pos SetValue \ + [lindex $value 0] [expr $height - 15] [lindex $value 2] + $actor VisibilityOn + } + } + + proc cb_vtkiw_hide_text1 {vtkiw} { + set actor [::vtk::get_widget_variable_value $vtkiw text1_actor] + if {[$actor GetVisibility]} { + $actor VisibilityOff + } + } + + # ------------------------------------------------------------------- + # vtkInteractorStyleImage callbacks/observers + # istyle: interactor style + # vtkiw: vtkTkImageRenderWindget + + # StartWindowLevelEvent observer. + # Create the text actor, show it + + proc cb_istyleimg_start_window_level_event {istyle vtkiw} { + ::vtk::cb_vtkiw_create_text1 $vtkiw + ::vtk::cb_vtkiw_show_text1 $vtkiw + } + + # EndWindowLevelEvent observer. + # Hide the text actor. + + proc cb_istyleimg_end_window_level_event {istyle vtkiw} { + ::vtk::cb_vtkiw_hide_text1 $vtkiw + $vtkiw Render + } + + # WindowLevelEvent observer. + # Update the text actor with the current window/level values. + + proc cb_istyleimg_window_level_event {istyle vtkiw} { + set mapper [::vtk::get_widget_variable_value $vtkiw text1_mapper] + set viewer [$vtkiw GetImageViewer] + $mapper SetInput [format "W/L: %.0f/%.0f" \ + [$viewer GetColorWindow] [$viewer GetColorLevel]] + } + + # RightButtonPressEvent observer. + # Invert the 'shift' key. The usual vtkInteractorStyleImage + # behaviour is to enable picking mode with "Shift+Right button", + # whereas we want picking mode to be "Right button" (for backward + # compatibility). + + proc cb_istyleimg_right_button_press_event {istyle} { + set iren [$istyle GetInteractor] + $iren SetShiftKey [expr [$iren GetShiftKey] ? 0 : 1] + $istyle OnRightButtonDown + } + + proc cb_istyleimg_right_button_release_event {istyle} { + set iren [$istyle GetInteractor] + $iren SetShiftKey [expr [$iren GetShiftKey] ? 0 : 1] + $istyle OnRightButtonUp + } + + # StartPickEvent observer. + # Create the text actor, show it + + proc cb_istyleimg_start_pick_event {istyle vtkiw} { + ::vtk::cb_vtkiw_create_text1 $vtkiw + ::vtk::cb_vtkiw_show_text1 $vtkiw + } + + # EndPickEvent observer. + # Hide the text actor. + + proc cb_istyleimg_end_pick_event {istyle vtkiw} { + ::vtk::cb_vtkiw_hide_text1 $vtkiw + $vtkiw Render + } + + # PickEvent observer. + # Update the text actor with the current value of the picked pixel. + + proc cb_istyleimg_pick_event {istyle vtkiw} { + + set viewer [$vtkiw GetImageViewer] + set input [$viewer GetInput] + set pos [[$istyle GetInteractor] GetEventPosition] + set x [lindex $pos 0] + set y [lindex $pos 1] + set z [$viewer GetZSlice] + + # Y is flipped upside down + + set height [lindex [$vtkiw configure -height] 4] + set y [expr $height - $y] + + # Make sure point is in the whole extent of the image. + + scan [$input GetWholeExtent] "%d %d %d %d %d %d" \ + xMin xMax yMin yMax zMin zMax + if {$x < $xMin || $x > $xMax || \ + $y < $yMin || $y > $yMax || \ + $z < $zMin || $z > $zMax} { + return + } + + $input SetUpdateExtent $x $x $y $y $z $z + $input Update + + set num_comps [$input GetNumberOfScalarComponents] + set str "($x, $y):" + for {set idx 0} {$idx < $num_comps} {incr idx} { + set str [format "%s %.0f" $str \ + [$input GetScalarComponentAsDouble $x $y $z $idx]] + } + + set mapper [::vtk::get_widget_variable_value $vtkiw text1_mapper] + $mapper SetInput "$str" + $vtkiw Render + } + + # ------------------------------------------------------------------- + # Create vtkTkImageViewerWidget bindings, setup observers + + proc bind_tk_imageviewer_widget {vtkiw} { + + bind_tk_widget $vtkiw [[$vtkiw GetImageViewer] GetRenderWindow] + + set viewer [$vtkiw GetImageViewer] + set iren [[$viewer GetRenderWindow] GetInteractor] + + # Ask the viewer to setup an image style interactor + + $viewer SetupInteractor $iren + set istyle [$iren GetInteractorStyle] + + # Window/Level observers + + ::vtk::set_widget_variable_value $istyle StartWindowLevelEventTag \ + [$istyle AddObserver StartWindowLevelEvent \ + "::vtk::cb_istyleimg_start_window_level_event $istyle $vtkiw"] + + ::vtk::set_widget_variable_value $istyle WindowLevelEventTag \ + [$istyle AddObserver WindowLevelEvent \ + "::vtk::cb_istyleimg_window_level_event $istyle $vtkiw"] + + ::vtk::set_widget_variable_value $istyle EndWindowLevelEventTag \ + [$istyle AddObserver EndWindowLevelEvent \ + "::vtk::cb_istyleimg_end_window_level_event $istyle $vtkiw"] + + # Picking observers + + ::vtk::set_widget_variable_value $istyle RightButtonPressEventTag \ + [$istyle AddObserver RightButtonPressEvent \ + "::vtk::cb_istyleimg_right_button_press_event $istyle"] + + ::vtk::set_widget_variable_value $istyle RightButtonReleaseEventTag \ + [$istyle AddObserver RightButtonReleaseEvent \ + "::vtk::cb_istyleimg_right_button_release_event $istyle"] + + ::vtk::set_widget_variable_value $istyle StartPickEventTag \ + [$istyle AddObserver StartPickEvent \ + "::vtk::cb_istyleimg_start_pick_event $istyle $vtkiw"] + + ::vtk::set_widget_variable_value $istyle EndPickEventTag \ + [$istyle AddObserver EndPickEvent \ + "::vtk::cb_istyleimg_end_pick_event $istyle $vtkiw"] + + ::vtk::set_widget_variable_value $istyle PickEventTag \ + [$istyle AddObserver PickEvent \ + "::vtk::cb_istyleimg_pick_event $istyle $vtkiw"] + } +} + +# Handle deprecated calls + +proc BindTkImageViewer {widget} { + puts stderr "BindTkImageViewer is deprecated. Please use ::vtk::bind_tk_imageviewer_widget instead" + ::vtk::bind_tk_imageviewer_widget $widget +} diff --git a/Wrapping/Tcl/vtkinteraction/bindings-rw.tcl b/Wrapping/Tcl/vtkinteraction/bindings-rw.tcl new file mode 100644 index 0000000..67d5fba --- /dev/null +++ b/Wrapping/Tcl/vtkinteraction/bindings-rw.tcl @@ -0,0 +1,18 @@ +namespace eval ::vtk { + + namespace export * + + # ------------------------------------------------------------------- + # Create vtkTkRenderWidget bindings, setup observers + + proc bind_tk_render_widget {vtkrw} { + bind_tk_widget $vtkrw [$vtkrw GetRenderWindow] + } +} + +# Handle deprecated calls + +proc BindTkRenderWidget {widget} { + puts stderr "BindTkImageViewer is deprecated. Please use ::vtk::bind_tk_render_widget instead" + ::vtk::bind_tk_render_widget $widget +} diff --git a/Wrapping/Tcl/vtkinteraction/bindings.tcl b/Wrapping/Tcl/vtkinteraction/bindings.tcl new file mode 100644 index 0000000..b601920 --- /dev/null +++ b/Wrapping/Tcl/vtkinteraction/bindings.tcl @@ -0,0 +1,352 @@ +namespace eval ::vtk { + + namespace export * + + # ------------------------------------------------------------------- + # vtkTk(ImageViewer/Render)Widget callbacks. + # vtkw: Tk pathname of the widget + # renwin: render window embeded in the widget + # x: X coord, widget relative + # y: X coord, widget relative + # w: width of an event or update + # h: height of an event or update + # ctrl: 1 if the Control key modifier was pressed, 0 otherwise + # shift: 1 if the Control key modifier was pressed, 0 otherwise + # delta: delta field for the MouseWheel event. + # repeat: 1 if a mouse button is double clicked, 0 if single clicked + + # Called when a Tk mouse motion event is triggered. + # Helper binding: propagate the event as a VTK event. + + proc cb_vtkw_motion_binding {vtkw renwin x y} { + set iren [$renwin GetInteractor] + $iren SetEventPositionFlipY $x $y + $iren MouseMoveEvent + } + + # Called when a Tk button mouse event is triggered. + # Helper binding: propagate the event as a VTK event. + # event: button state, Press or Release + # pos: position of the button, Left, Middle or Right + + proc cb_vtkw_button_binding {vtkw renwin x y ctrl shift event pos repeat} { + set iren [$renwin GetInteractor] + $iren SetEventPositionFlipY $x $y + $iren SetControlKey $ctrl + $iren SetShiftKey $shift + $iren ${pos}Button${event}Event + $iren SetRepeatCount $repeat + } + + # Called when a Tk wheel motion event is triggered. + # Helper binding: propagate the event as a VTK event. + + proc cb_vtkw_wheel_motion_binding {vtkw renwin delta} { + set iren [$renwin GetInteractor] + if {$delta < 0} { + $iren MouseWheelBackwardEvent + } else { + $iren MouseWheelForwardEvent + } + } + + # Called when a Tk key event is triggered. + # Helper binding: propagate the event as a VTK event (indeed, two). + # event: key state, Press or Release + # keycode: keycode field + # keysym: keysym field + + proc cb_vtkw_key_binding {vtkw renwin x y ctrl shift event keycode keysym} { + set iren [$renwin GetInteractor] + # Not a bug, two times keysym, since 5th param expect a char, and + # $keycode is %k, which is a number + $iren SetEventInformationFlipY $x $y $ctrl $shift $keysym 0 $keysym + $iren Key${event}Event + if {$event == "Press"} { + $iren SetEventInformationFlipY $x $y $ctrl $shift $keysym 0 $keysym + $iren CharEvent + } + } + + # Called when a Tk Expose/Configure event is triggered. + # Helper binding: propagate the event as a VTK event. + + proc cb_vtkw_configure_binding {vtkw renwin w h} { + set iren [$renwin GetInteractor] + $iren UpdateSize $w $h + $iren ConfigureEvent + } + + proc cb_vtkw_expose_binding {vtkw renwin x y w h} { + set iren [$renwin GetInteractor] + $iren SetEventPositionFlipY $x $y + $iren SetEventSize $w $h + $iren ExposeEvent + } + + # Called when a Tk Enter/Leave event is triggered. + # Helper binding: propagate the event as a VTK event. + # Note that entering the widget automatically grabs the focus so + # that key events can be processed. + + proc cb_vtkw_enter_binding {vtkw renwin x y} { + focus $vtkw + set iren [$renwin GetInteractor] + $iren SetEventPositionFlipY $x $y + $iren EnterEvent + } + + proc cb_vtkw_leave_binding {vtkw renwin x y} { + set iren [$renwin GetInteractor] + $iren SetEventPositionFlipY $x $y + $iren LeaveEvent + } + + # Set the above bindings for a vtkTkRenderWidget widget. + + proc create_vtkw_bindings {vtkw renwin} { + + global tcl_platform + + # Find the render window (which creates it if it was not set). + # Find the interactor, create a generic one if needed. + + if {[$renwin GetInteractor] == ""} { + # the duh is critical in the follwing line, it causes + # vtkTclUtil.cxx to know that the object was created in + # a Tcl script, otherwise if ${renwin} was a return value + # from a C++ function it would be called vtkTemp### and + # the interactor instance would have the same name causeing Tcl + # to think it also was a C++ return value. + set iren [vtkGenericRenderWindowInteractor duh_${renwin}_iren] + $iren SetRenderWindow $renwin + $iren Initialize + } + + # Mouse motion + + bind $vtkw <Motion> "::vtk::cb_vtkw_motion_binding $vtkw $renwin %x %y" + + # Mouse buttons and key events + + foreach {modifier ctrl shift repeat} { + "" 0 0 0 + "Control-" 1 0 0 + "Shift-" 0 1 0 + "Control-Shift-" 1 1 0 + "Double-" 0 0 1 + "Double-Control-" 1 0 1 + "Double-Shift-" 0 1 1 + "Double-Control-Shift-" 1 1 1 + } { + foreach event { + Press + Release + } { + foreach {pos number} { + Left 1 + Middle 2 + Right 3 + } { + bind $vtkw <${modifier}Button${event}-${number}> \ + "::vtk::cb_vtkw_button_binding $vtkw $renwin %x %y $ctrl $shift $event $pos $repeat" + } + + bind $vtkw <${modifier}Key${event}> \ + "::vtk::cb_vtkw_key_binding $vtkw $renwin %x %y $ctrl $shift $event %k %K" + } + } + + # Wheel motion + # Only x11 does not understand a mousewheel event + # [tk windowingsystem] can be x11, win32, classic, aqua + # Unfortunately this call only appear recently + # so for now remove it + # if {[tk windowingsystem] == "x11"} + if {$tcl_platform(platform) == "unix"} { + bind $vtkw <Button-4> \ + "::vtk::cb_vtkw_wheel_motion_binding $vtkw $renwin 1" + bind $vtkw <Button-5> \ + "::vtk::cb_vtkw_wheel_motion_binding $vtkw $renwin -1" + } else { + bind $vtkw <MouseWheel> \ + "::vtk::cb_vtkw_wheel_motion_binding $vtkw $renwin %D" + } + + # Expose/Configure + + bind $vtkw <Configure> \ + "::vtk::cb_vtkw_configure_binding $vtkw $renwin %w %h" + + bind $vtkw <Expose> \ + "::vtk::cb_vtkw_expose_binding $vtkw $renwin %x %y %w %h" + + # Enter/Leave + + bind $vtkw <Enter> \ + "::vtk::cb_vtkw_enter_binding $vtkw $renwin %x %y" + + bind $vtkw <Leave> \ + "::vtk::cb_vtkw_leave_binding $vtkw $renwin %x %y" + } + + # ------------------------------------------------------------------- + # vtkRenderWindow callbacks/observers + # renwin: render window object + + # AbortCheckEvent observer. + # Check if some events are pending, and abort render in that case + + proc cb_renwin_abort_check_event {renwin} { + if {[$renwin GetEventPending] != 0} { + $renwin SetAbortRender 1 + } + } + + # Add the above observers to a vtkRenderWindow + + proc add_renwin_observers {renwin} { + + # Check for aborting rendering + + ::vtk::set_widget_variable_value $renwin AbortCheckEventTag \ + [$renwin AddObserver AbortCheckEvent \ + [list ::vtk::cb_renwin_abort_check_event $renwin]] + } + + # ------------------------------------------------------------------- + # vtk(Generic)RenderWindowInteractor callbacks/observers + # iren: interactor object + + # CreateTimerEvent/DestroyTimerEvent obversers. + # Handle the creation of a timer event (10 ms) + + proc cb_iren_create_timer_event {iren} { + set timer [after 10 "$iren TimerEvent"] + ::vtk::set_widget_variable_value $iren CreateTimerEventTimer $timer + } + + proc cb_iren_destroy_timer_event {iren} { + set timer \ + [::vtk::get_widget_variable_value $iren CreateTimerEventTimer] + if {$timer != ""} { + after cancel $timer + } + } + + # UserEvent obverser. + # Popup the vtkInteract widget (simple wish-like console) + + proc cb_iren_user_event {} { + wm deiconify .vtkInteract + } + + # ConfigureEvent obverser. + # This event is triggered when the widget is re-configured, i.e. its + # size is changed. Note that for every ConfigureEvent an ExposeEvent is + # triggered too and the corresponding observer will re-render the window. + # It might be nice to switch the frame update rate to an interactive + # update rate while the window is getting resized, so that the user can + # experience a decent feedback. This is achieved by launching a timer + # each time the ConfigureEvent is triggered. This timer lasts 300 ms. When + # the ExposeEvent observer is called, it checks if this timer still exists. + # If it is the case, it implies that the user is configuring/resizing the + # window and that an interactive frame rate may be used. If it is not, + # it uses the still update rate to render the scene with full details. + # The timer itself is a call to the ExposeEvent observer, which will + # finaly render the window using a still update rate. + + proc cb_iren_configure_event {iren} { + # Cancel the previous timer if any + set timer [::vtk::get_widget_variable_value $iren ConfigureEventTimer] + if {$timer != ""} { + after cancel $timer + } + ::vtk::set_widget_variable_value $iren ConfigureEventTimer \ + [after 300 [list ::vtk::cb_iren_expose_event $iren]] + } + + # ExposeEvent obverser. + # This event is triggered when a part (or all) of the widget is exposed, + # i.e. a new area is visible. It usually happens when the widget window + # is brought to the front, or when the widget is resized. + # See above for explanations about the update rate tricks. + + proc cb_iren_expose_event {iren} { + set renwin [$iren GetRenderWindow] + # Check if a ConfigureEvent timer is pending + set timer [::vtk::get_widget_variable_value $iren ConfigureEventTimer] + if {$timer != ""} { + if {[catch {after info $timer}]} { + ::vtk::unset_widget_variable $iren ConfigureEventTimer + $renwin SetDesiredUpdateRate [$iren GetStillUpdateRate] + } else { + $renwin SetDesiredUpdateRate [$iren GetDesiredUpdateRate] + } + } + update + $renwin Render + } + + # ExitEvent obverser. + # Destroy all VTK objects (therefore, try not to call this function + # directly from a VTK object), then exit. + + proc cb_exit {} { + vtkCommand DeleteAllObjects + exit + } + + proc cb_iren_exit_event {} { + ::vtk::cb_exit + } + + # Add the above observers to a vtk(Generic)RenderWindowInteractor + + proc add_iren_observers {iren} { + + # Timer events + + ::vtk::set_widget_variable_value $iren CreateTimerEventTag \ + [$iren AddObserver CreateTimerEvent \ + [list ::vtk::cb_iren_create_timer_event $iren]] + + ::vtk::set_widget_variable_value $iren DestroyTimerEventTag \ + [$iren AddObserver DestroyTimerEvent \ + [list ::vtk::cb_iren_destroy_timer_event $iren]] + + # User Tk interactor + + ::vtk::set_widget_variable_value $iren UserEventTag \ + [$iren AddObserver UserEvent \ + [list ::vtk::cb_iren_user_event]] + + # Expose and Configure + + ::vtk::set_widget_variable_value $iren ConfigureEventTag \ + [$iren AddObserver ConfigureEvent \ + [list ::vtk::cb_iren_configure_event $iren]] + + ::vtk::set_widget_variable_value $iren ExposeEventTag \ + [$iren AddObserver ExposeEvent \ + [list ::vtk::cb_iren_expose_event $iren]] + + # Exit + # Since the callback is likely to delete all VTK objects + # using vtkCommand::DeleteAllObject, let's try not to call it from + # the object itself. Use a timer. + + ::vtk::set_widget_variable_value $iren ExitEventTag \ + [$iren AddObserver ExitEvent \ + "after 100 [list ::vtk::cb_iren_exit_event]"] + } + + # ------------------------------------------------------------------- + # Create vtkTk(ImageViewer/Render)Widget bindings, setup observers + + proc bind_tk_widget {vtkw renwin} { + create_vtkw_bindings $vtkw $renwin + add_renwin_observers $renwin + add_iren_observers [$renwin GetInteractor] + } +} diff --git a/Wrapping/Tcl/vtkinteraction/setget.tcl b/Wrapping/Tcl/vtkinteraction/setget.tcl new file mode 100644 index 0000000..4a5ee3b --- /dev/null +++ b/Wrapping/Tcl/vtkinteraction/setget.tcl @@ -0,0 +1,77 @@ +namespace eval ::vtk { + + namespace export * + + # ------------------------------------------------------------------- + # Some functions that can be used to associate variables to + # widgets without polluting the global space + + variable gvars + + # Generate a "unique" name for a widget variable + + proc get_widget_variable {widget var_name} { + variable gvars + return "gvars($widget,vars,$var_name)" + } + + # Set the value of a widget variable + + proc set_widget_variable_value {widget var_name value} { + variable gvars + set var [get_widget_variable $widget $var_name] + set $var $value + } + + proc unset_widget_variable {widget var_name} { + variable gvars + set var [get_widget_variable $widget $var_name] + if {[info exists $var]} { + unset $var + } + } + + # Get the value of a widget variable ("" if undef) + + proc get_widget_variable_value {widget var_name} { + variable gvars + set var [get_widget_variable $widget $var_name] + if {[info exists $var]} { + return [expr $$var] + } else { + return "" + } + } + + # Return an object which will be associated with a widget + + proc new_widget_object {widget type var_name} { + variable gvars + set var [get_widget_variable $widget "${var_name}_obj"] + $type $var + set_widget_variable_value $widget $var_name $var + return $var + } +} + +# Handle deprecated calls + +proc GetWidgetVariable {widget varName} { + puts stderr "GetWidgetVariable is deprecated. Please use ::vtk::get_widget_variable instead" + return [::vtk::get_widget_variable $widget $varName] +} + +proc SetWidgetVariableValue {widget varName value} { + puts stderr "SetWidgetVariableValue is deprecated. Please use ::vtk::set_widget_variable_value instead" + ::vtk::set_widget_variable_value $widget $varName $value +} + +proc GetWidgetVariableValue {widget varName} { + puts stderr "GetWidgetVariableValue is deprecated. Please use ::vtk::get_widget_variable_value instead" + return [::vtk::get_widget_variable_value $widget $varName] +} + +proc NewWidgetObject {widget type varName} { + puts stderr "NewWidgetObject is deprecated. Please use ::vtk::new_widget_object instead" + return [::vtk::new_widget_object $widget $type $varName] +} diff --git a/Wrapping/Tcl/vtkinteraction/vtkinteraction.tcl b/Wrapping/Tcl/vtkinteraction/vtkinteraction.tcl new file mode 100644 index 0000000..db344e6 --- /dev/null +++ b/Wrapping/Tcl/vtkinteraction/vtkinteraction.tcl @@ -0,0 +1,11 @@ +package require -exact vtkrendering 5.0 + +# We need Tk to implement the interactive features. +package require Tk + +# Load the interaction features. +foreach s {Interactor bindings-rw bindings-iw bindings setget} { + source [file join [file dirname [info script]] "${s}.tcl"] +} + +package provide vtkinteraction 5.0 diff --git a/Wrapping/Tcl/vtkio/CMakeLists.txt b/Wrapping/Tcl/vtkio/CMakeLists.txt new file mode 100644 index 0000000..51d2d43 --- /dev/null +++ b/Wrapping/Tcl/vtkio/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkio .tcl vtkio) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkio/vtkio.tcl b/Wrapping/Tcl/vtkio/vtkio.tcl new file mode 100644 index 0000000..38ea57b --- /dev/null +++ b/Wrapping/Tcl/vtkio/vtkio.tcl @@ -0,0 +1,12 @@ +package require -exact vtkfiltering 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkIOTCL 5.0]} { + package provide vtkio 5.0 + } +} else { + if {[info commands vtkBMPReader] != "" || + [::vtk::load_component vtkIOTCL] == ""} { + package provide vtkio 5.0 + } +} diff --git a/Wrapping/Tcl/vtkparallel/CMakeLists.txt b/Wrapping/Tcl/vtkparallel/CMakeLists.txt new file mode 100644 index 0000000..98cf0b7 --- /dev/null +++ b/Wrapping/Tcl/vtkparallel/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkparallel .tcl vtkparallel) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkparallel/vtkparallel.tcl b/Wrapping/Tcl/vtkparallel/vtkparallel.tcl new file mode 100644 index 0000000..b75d278 --- /dev/null +++ b/Wrapping/Tcl/vtkparallel/vtkparallel.tcl @@ -0,0 +1,13 @@ +package require -exact vtkio 5.0 +package require -exact vtkrendering 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkParallelTCL 5.0]} { + package provide vtkparallel 5.0 + } +} else { + if {[info commands vtkParallelFactory] != "" || + [::vtk::load_component vtkParallelTCL] == ""} { + package provide vtkparallel 5.0 + } +} diff --git a/Wrapping/Tcl/vtkrendering/CMakeLists.txt b/Wrapping/Tcl/vtkrendering/CMakeLists.txt new file mode 100644 index 0000000..9d337b2 --- /dev/null +++ b/Wrapping/Tcl/vtkrendering/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkrendering .tcl vtkrendering) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkrendering/vtkrendering.tcl b/Wrapping/Tcl/vtkrendering/vtkrendering.tcl new file mode 100644 index 0000000..db3915f --- /dev/null +++ b/Wrapping/Tcl/vtkrendering/vtkrendering.tcl @@ -0,0 +1,45 @@ +package require -exact vtkgraphics 5.0 +package require -exact vtkimaging 5.0 + +catch { + unset __tk_error +} + +namespace eval ::vtk::rendering { + proc SetWin32ExitCallback {} { + # Set the default exit method of vtkWin32RenderWindowInteractor to + # call the Tcl 'exit' command + if {[info commands vtkWin32RenderWindowInteractor] != ""} { + if {[catch { + # this exit method is called when the user exists interactively + # (such as pressing 'e' or 'q'). An extra reference is added to + # the callback command used to process it by the + # vtkSubjectHelper::InvokeEvent method. If the callback exits the + # application immediately in its Execute() method, this reference + # is never removed and the object leaks. Using 'after idle' allows + # the stack to unwind far enough. This is similar to Win32 + # PostQuitMessage() logic. + vtkWin32RenderWindowInteractor __temp_vtkwin32iren__ + __temp_vtkwin32iren__ SetClassExitMethod {after idle exit} + __temp_vtkwin32iren__ Delete + } errormsg]} { + puts $errormsg + } + } + } +} + +if {[info commands ::vtk::init::require_package] != ""} { + if {![info exists __tk_error] && \ + [::vtk::init::require_package vtkRenderingTCL 5.0]} { + ::vtk::rendering::SetWin32ExitCallback + package provide vtkrendering 5.0 + } +} else { + if {![info exists __tk_error] && \ + ([info commands vtkAxisActor2D] != "" || \ + [::vtk::load_component vtkRenderingTCL] == "")} { + ::vtk::rendering::SetWin32ExitCallback + package provide vtkrendering 5.0 + } +} diff --git a/Wrapping/Tcl/vtktcl.c b/Wrapping/Tcl/vtktcl.c new file mode 100644 index 0000000..4631ea2 --- /dev/null +++ b/Wrapping/Tcl/vtktcl.c @@ -0,0 +1,104 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtktcl.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkToolkits.h" + +#ifdef VTK_USE_RENDERING +# include "vtkTk.h" +#else +# include "vtkTcl.h" +#endif + +extern int Vtkcommontcl_Init(Tcl_Interp *interp); +extern int Vtkfilteringtcl_Init(Tcl_Interp *interp); +extern int Vtkgraphicstcl_Init(Tcl_Interp *interp); +extern int Vtkimagingtcl_Init(Tcl_Interp *interp); +extern int Vtkiotcl_Init(Tcl_Interp *interp); + +#ifdef VTK_USE_RENDERING +extern int Vtkrenderingtcl_Init(Tcl_Interp *interp); +extern int Vtkvolumerenderingtcl_Init(Tcl_Interp *interp); +extern int Vtkhybridtcl_Init(Tcl_Interp *interp); +extern int Vtkwidgetstcl_Init(Tcl_Interp *interp); +#ifdef VTK_USE_TKWIDGET +extern int Vtktkrenderwidget_Init(Tcl_Interp *interp); +extern int Vtktkimagewindowwidget_Init(Tcl_Interp *interp); +extern int Vtktkimageviewerwidget_Init(Tcl_Interp *interp); +#endif +#endif + +#ifdef VTK_USE_PARALLEL +extern int Vtkparalleltcl_Init(Tcl_Interp *interp); +#endif + +int Vtktcl_Init(Tcl_Interp *interp) +{ + /* init the core vtk stuff */ + if (Vtkcommontcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkfilteringtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkiotcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkgraphicstcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + if (Vtkimagingtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + +#ifdef VTK_USE_RENDERING + if (Vtkrenderingtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + + if (Vtkvolumerenderingtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + + if (Vtkhybridtcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } + + if (Vtkwidgetstcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } +#endif + +#ifdef VTK_USE_PARALLEL + if (Vtkparalleltcl_Init(interp) == TCL_ERROR) + { + return TCL_ERROR; + } +#endif + + return TCL_OK; +} + +int Vtktcl_SafeInit(Tcl_Interp *interp) +{ + return Vtktcl_Init(interp); +} diff --git a/Wrapping/Tcl/vtktesting/CMakeLists.txt b/Wrapping/Tcl/vtktesting/CMakeLists.txt new file mode 100644 index 0000000..5468bc4 --- /dev/null +++ b/Wrapping/Tcl/vtktesting/CMakeLists.txt @@ -0,0 +1,9 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtktesting .tcl + vtktesting + backdrop + grab + colors + mccases + ) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtktesting/backdrop.tcl b/Wrapping/Tcl/vtktesting/backdrop.tcl new file mode 100644 index 0000000..ef05ccb --- /dev/null +++ b/Wrapping/Tcl/vtktesting/backdrop.tcl @@ -0,0 +1,35 @@ +proc BuildBackdrop {minX maxX minY maxY minZ maxZ thickness} { + if { [info command basePlane] == "" } {vtkCubeSource basePlane;} + basePlane SetCenter [expr ($maxX + $minX) / 2.0] $minY [expr ($maxZ + $minZ) / 2.0] + basePlane SetXLength [expr ($maxX - $minX)] + basePlane SetYLength $thickness + basePlane SetZLength [expr ($maxZ - $minZ)] + + if { [info command baseMapper] == "" } {vtkPolyDataMapper baseMapper;} + baseMapper SetInput [basePlane GetOutput] + if { [info command base] == "" } {vtkActor base;} + base SetMapper baseMapper + + if { [info command backPlane] == "" } {vtkCubeSource backPlane;} + backPlane SetCenter [expr ($maxX + $minX) / 2.0] [expr ($maxY + $minY) / 2.0] $minZ + backPlane SetXLength [expr ($maxX - $minX)] + backPlane SetYLength [expr ($maxY - $minY)] + backPlane SetZLength $thickness + + if { [info command backMapper] == "" } {vtkPolyDataMapper backMapper;} + backMapper SetInput [backPlane GetOutput] + if { [info command back] == "" } {vtkActor back;} + back SetMapper backMapper + + if { [info command leftPlane] == "" } {vtkCubeSource leftPlane;} + leftPlane SetCenter $minX [expr ($maxY + $minY) / 2.0] [expr ($maxZ + $minZ) / 2.0] + leftPlane SetXLength $thickness + leftPlane SetYLength [expr ($maxY - $minY)] + leftPlane SetZLength [expr ($maxZ - $minZ)] + + if { [info command leftMapper] == "" } {vtkPolyDataMapper leftMapper;} + leftMapper SetInput [leftPlane GetOutput] + if { [info command left] == "" } {vtkActor left;} + left SetMapper leftMapper + +} diff --git a/Wrapping/Tcl/vtktesting/colors.tcl b/Wrapping/Tcl/vtktesting/colors.tcl new file mode 100644 index 0000000..a8dcb57 --- /dev/null +++ b/Wrapping/Tcl/vtktesting/colors.tcl @@ -0,0 +1,214 @@ +# Standard colors used by many vtk scripts + +set antique_white "0.9804 0.9216 0.8431" +set azure "0.9412 1.0000 1.0000" +set bisque "1.0000 0.8941 0.7686" +set blanched_almond "1.0000 0.9216 0.8039" +set cornsilk "1.0000 0.9725 0.8627" +set eggshell "0.9900 0.9000 0.7900" +set floral_white "1.0000 0.9804 0.9412" +set gainsboro "0.8627 0.8627 0.8627" +set ghost_white "0.9725 0.9725 1.0000" +set honeydew "0.9412 1.0000 0.9412" +set ivory "1.0000 1.0000 0.9412" +set lavender "0.9020 0.9020 0.9804" +set lavender_blush "1.0000 0.9412 0.9608" +set lemon_chiffon "1.0000 0.9804 0.8039" +set linen "0.9804 0.9412 0.9020" +set mint_cream "0.9608 1.0000 0.9804" +set misty_rose "1.0000 0.8941 0.8824" +set moccasin "1.0000 0.8941 0.7098" +set navajo_white "1.0000 0.8706 0.6784" +set old_lace "0.9922 0.9608 0.9020" +set papaya_whip "1.0000 0.9373 0.8353" +set peach_puff "1.0000 0.8549 0.7255" +set seashell "1.0000 0.9608 0.9333" +set snow "1.0000 0.9804 0.9804" +set thistle "0.8471 0.7490 0.8471" +set titanium_white "0.9900 1.0000 0.9400" +set wheat "0.9608 0.8706 0.7020" +set white "1.0000 1.0000 1.0000" +set white_smoke "0.9608 0.9608 0.9608" +set zinc_white "0.9900 0.9700 1.0000" + +# Greys +set cold_grey "0.5000 0.5400 0.5300" +set dim_grey "0.4118 0.4118 0.4118" +set grey "0.7529 0.7529 0.7529" +set light_grey "0.8275 0.8275 0.8275" +set slate_grey "0.4392 0.5020 0.5647" +set slate_grey_dark "0.1843 0.3098 0.3098" +set slate_grey_light "0.4667 0.5333 0.6000" +set warm_grey "0.5000 0.5000 0.4100" + +# Blacks +set black "0.0000 0.0000 0.0000" +set ivory_black "0.1600 0.1400 0.1300" +set lamp_black "0.1800 0.2800 0.2300" + +# Reds +set alizarin_crimson "0.8900 0.1500 0.2100" +set brick "0.6100 0.4000 0.1200" +set cadmium_red_deep "0.8900 0.0900 0.0500" +set coral "1.0000 0.4980 0.3137" +set coral_light "0.9412 0.5020 0.5020" +set deep_pink "1.0000 0.0784 0.5765" +set english_red "0.8300 0.2400 0.1000" +set firebrick "0.6980 0.1333 0.1333" +set geranium_lake "0.8900 0.0700 0.1900" +set hot_pink "1.0000 0.4118 0.7059" +set indian_red "0.6900 0.0900 0.1200" +set light_salmon "1.0000 0.6275 0.4784" +set madder_lake_deep "0.8900 0.1800 0.1900" +set maroon "0.6902 0.1882 0.3765" +set pink "1.0000 0.7529 0.7961" +set pink_light "1.0000 0.7137 0.7569" +set raspberry "0.5300 0.1500 0.3400" +set red "1.0000 0.0000 0.0000" +set rose_madder "0.8900 0.2100 0.2200" +set salmon "0.9804 0.5020 0.4471" +set tomato "1.0000 0.3882 0.2784" +set venetian_red "0.8300 0.1000 0.1200" + +# Browns +set beige "0.6400 0.5800 0.5000" +set brown "0.5000 0.1647 0.1647" +set brown_madder "0.8600 0.1600 0.1600" +set brown_ochre "0.5300 0.2600 0.1200" +set burlywood "0.8706 0.7216 0.5294" +set burnt_sienna "0.5400 0.2100 0.0600" +set burnt_umber "0.5400 0.2000 0.1400" +set chocolate "0.8235 0.4118 0.1176" +set deep_ochre "0.4500 0.2400 0.1000" +set flesh "1.0000 0.4900 0.2500" +set flesh_ochre "1.0000 0.3400 0.1300" +set gold_ochre "0.7800 0.4700 0.1500" +set greenish_umber "1.0000 0.2400 0.0500" +set khaki "0.9412 0.9020 0.5490" +set khaki_dark "0.7412 0.7176 0.4196" +set light_beige "0.9608 0.9608 0.8627" +set peru "0.8039 0.5216 0.2471" +set rosy_brown "0.7373 0.5608 0.5608" +set raw_sienna "0.7800 0.3800 0.0800" +set raw_umber "0.4500 0.2900 0.0700" +set sepia "0.3700 0.1500 0.0700" +set sienna "0.6275 0.3216 0.1765" +set saddle_brown "0.5451 0.2706 0.0745" +set sandy_brown "0.9569 0.6431 0.3765" +set tan "0.8235 0.7059 0.5490" +set van_dyke_brown "0.3700 0.1500 0.0200" + +# Oranges +set cadmium_orange "1.0000 0.3800 0.0100" +set cadmium_red_light "1.0000 0.0100 0.0500" +set carrot "0.9300 0.5700 0.1300" +set dark_orange "1.0000 0.5490 0.0000" +set mars_orange "0.5900 0.2700 0.0800" +set mars_yellow "0.8900 0.4400 0.1000" +set orange "1.0000 0.5000 0.0000" +set orange_red "1.0000 0.2706 0.0000" +set yellow_ochre "0.8900 0.5100 0.0900" + +# Yellows +set aureoline_yellow "1.0000 0.6600 0.1400" +set banana "0.8900 0.8100 0.3400" +set cadmium_lemon "1.0000 0.8900 0.0100" +set cadmium_yellow "1.0000 0.6000 0.0700" +set cadmium_yellow_light "1.0000 0.6900 0.0600" +set gold "1.0000 0.8431 0.0000" +set goldenrod "0.8549 0.6471 0.1255" +set goldenrod_dark "0.7216 0.5255 0.0431" +set goldenrod_light "0.9804 0.9804 0.8235" +set goldenrod_pale "0.9333 0.9098 0.6667" +set light_goldenrod "0.9333 0.8667 0.5098" +set melon "0.8900 0.6600 0.4100" +set naples_yellow_deep "1.0000 0.6600 0.0700" +set yellow "1.0000 1.0000 0.0000" +set yellow_light "1.0000 1.0000 0.8784" + +# Greens +set chartreuse "0.4980 1.0000 0.0000" +set chrome_oxide_green "0.4000 0.5000 0.0800" +set cinnabar_green "0.3800 0.7000 0.1600" +set cobalt_green "0.2400 0.5700 0.2500" +set emerald_green "0.0000 0.7900 0.3400" +set forest_green "0.1333 0.5451 0.1333" +set green "0.0000 1.0000 0.0000" +set green_dark "0.0000 0.3922 0.0000" +set green_pale "0.5961 0.9843 0.5961" +set green_yellow "0.6784 1.0000 0.1843" +set lawn_green "0.4863 0.9882 0.0000" +set lime_green "0.1961 0.8039 0.1961" +set mint "0.7400 0.9900 0.7900" +set olive "0.2300 0.3700 0.1700" +set olive_drab "0.4196 0.5569 0.1373" +set olive_green_dark "0.3333 0.4196 0.1843" +set permanent_green "0.0400 0.7900 0.1700" +set sap_green "0.1900 0.5000 0.0800" +set sea_green "0.1804 0.5451 0.3412" +set sea_green_dark "0.5608 0.7373 0.5608" +set sea_green_medium "0.2353 0.7020 0.4431" +set sea_green_light "0.1255 0.6980 0.6667" +set spring_green "0.0000 1.0000 0.4980" +set spring_green_medium "0.0000 0.9804 0.6039" +set terre_verte "0.2200 0.3700 0.0600" +set viridian_light "0.4300 1.0000 0.4400" +set yellow_green "0.6039 0.8039 0.1961" + +# Cyans +set aquamarine "0.4980 1.0000 0.8314" +set aquamarine_medium "0.4000 0.8039 0.6667" +set cyan "0.0000 1.0000 1.0000" +set cyan_white "0.8784 1.0000 1.0000" +set turquoise "0.2510 0.8784 0.8157" +set turquoise_dark "0.0000 0.8078 0.8196" +set turquoise_medium "0.2824 0.8196 0.8000" +set turquoise_pale "0.6863 0.9333 0.9333" + +# Blues +set alice_blue "0.9412 0.9725 1.0000" +set blue "0.0000 0.0000 1.0000" +set blue_light "0.6784 0.8471 0.9020" +set blue_medium "0.0000 0.0000 0.8039" +set cadet "0.3725 0.6196 0.6275" +set cobalt "0.2400 0.3500 0.6700" +set cornflower "0.3922 0.5843 0.9294" +set cerulean "0.0200 0.7200 0.8000" +set dodger_blue "0.1176 0.5647 1.0000" +set indigo "0.0300 0.1800 0.3300" +set manganese_blue "0.0100 0.6600 0.6200" +set midnight_blue "0.0980 0.0980 0.4392" +set navy "0.0000 0.0000 0.5020" +set peacock "0.2000 0.6300 0.7900" +set powder_blue "0.6902 0.8784 0.9020" +set royal_blue "0.2549 0.4118 0.8824" +set slate_blue "0.4157 0.3529 0.8039" +set slate_blue_dark "0.2824 0.2392 0.5451" +set slate_blue_light "0.5176 0.4392 1.0000" +set slate_blue_medium "0.4824 0.4078 0.9333" +set sky_blue "0.5294 0.8078 0.9216" +set sky_blue_deep "0.0000 0.7490 1.0000" +set sky_blue_light "0.5294 0.8078 0.9804" +set steel_blue "0.2745 0.5098 0.7059" +set steel_blue_light "0.6902 0.7686 0.8706" +set turquoise_blue "0.0000 0.7800 0.5500" +set ultramarine "0.0700 0.0400 0.5600" + +# Magentas +set blue_violet "0.5412 0.1686 0.8863" +set cobalt_violet_deep "0.5700 0.1300 0.6200" +set magenta "1.0000 0.0000 1.0000" +set orchid "0.8549 0.4392 0.8392" +set orchid_dark "0.6000 0.1961 0.8000" +set orchid_medium "0.7294 0.3333 0.8275" +set permanent_red_violet "0.8600 0.1500 0.2700" +set plum "0.8667 0.6275 0.8667" +set purple "0.6275 0.1255 0.9412" +set purple_medium "0.5765 0.4392 0.8588" +set ultramarine_violet "0.3600 0.1400 0.4300" +set violet "0.5600 0.3700 0.6000" +set violet_dark "0.5804 0.0000 0.8275" +set violet_red "0.8157 0.1255 0.5647" +set violet_red_medium "0.7804 0.0824 0.5216" +set violet_red_pale "0.8588 0.4392 0.5765" + diff --git a/Wrapping/Tcl/vtktesting/grab.tcl b/Wrapping/Tcl/vtktesting/grab.tcl new file mode 100644 index 0000000..7183fae --- /dev/null +++ b/Wrapping/Tcl/vtktesting/grab.tcl @@ -0,0 +1,38 @@ +package require -exact vtkrendering 5.0 + +namespace eval ::vtk { + + proc grab_screenshot {renderer basename} { + + $renderer Render + + set rs \ + [::vtk::new_widget_object "_${renderer}" vtkRendererSource rs] + $rs SetInput $renderer + $rs DepthValuesOff + $rs DepthValuesInScalarsOn + + set pw \ + [::vtk::new_widget_object "_${renderer}" vtkPNGWriter pw] + $pw SetInput [$rs GetOutput] + $pw SetFileName "$basename-rgbz.png" + $pw Write + + set iec \ + [::vtk::new_widget_object "_${renderer}" vtkImageExtractComponents iec] + $iec SetInput [$rs GetOutput] + $iec SetComponents 3 + + $pw SetInput [$iec GetOutput] + $pw SetFileName "$basename-z.png" + $pw Write + + $iec SetComponents 0 1 2 + $pw SetFileName "$basename-rgb.png" + $pw Write + + $rs Delete + $pw Delete + $iec Delete + } +} diff --git a/Wrapping/Tcl/vtktesting/mccases.tcl b/Wrapping/Tcl/vtktesting/mccases.tcl new file mode 100644 index 0000000..5c72744 --- /dev/null +++ b/Wrapping/Tcl/vtktesting/mccases.tcl @@ -0,0 +1,242 @@ +# Used for setting vertex values for clipping, cutting, and contouring tests + +proc case1 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $OUT +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 1 - 00000001" + } else { + caseLabel SetText "Case 1c - 11111110" + } +} + +proc case2 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 2 - 00000011" + } else { + caseLabel SetText "Case 2c - 11111100" + } +} + +proc case3 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $OUT +$scalars InsertValue 2 $IN +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 3 - 00000101" + } else { + caseLabel SetText "Case 3c - 11111010" + } +} + +proc case4 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $OUT +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $IN +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 4 - 01000001" + } else { + caseLabel SetText "Case 4c - 10111110" + } +} + +proc case5 { scalars IN OUT } { +$scalars InsertValue 0 $OUT +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $IN +$scalars InsertValue 5 $IN +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 5 - 00110010" + } else { + caseLabel SetText "Case 5c - 11001101" + } +} + +proc case6 { scalars IN OUT } { +$scalars InsertValue 0 $OUT +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $IN +$scalars InsertValue 4 $IN +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 6 - 00011010" + } else { + caseLabel SetText "Case 6c - 11100101" + } +} + +proc case7 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $IN +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 7 - 01000011" + } else { + caseLabel SetText "Case 7c - 10111100" + } +} + +proc case8 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $IN +$scalars InsertValue 5 $IN +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 8 - 00110011" + } else { + caseLabel SetText "Case 8c - 11001100" + } +} + +proc case9 { scalars IN OUT } { +$scalars InsertValue 0 $OUT +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $IN +$scalars InsertValue 3 $IN +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $IN +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 9 - 01001110" + } else { + caseLabel SetText "Case 9c - 10110001" + } +} +# 27 -> 1b -> 00011011 +proc case9 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $IN +$scalars InsertValue 4 $IN +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 9 - 00011011" + } else { + caseLabel SetText "Case 9c - 11101011" + } +} + +proc case10 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $OUT +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $IN +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $IN +$scalars InsertValue 6 $IN +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 10 - 01101001" + } else { + caseLabel SetText "Case 10c - 10010110" + } +} + +proc case11 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $OUT +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $OUT +$scalars InsertValue 4 $IN +$scalars InsertValue 5 $IN +$scalars InsertValue 6 $IN +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 11 - 01110001" + } else { + caseLabel SetText "Case 11c - 10001110" + } +} + +proc case12 { scalars IN OUT } { +$scalars InsertValue 0 $OUT +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $IN +$scalars InsertValue 4 $IN +$scalars InsertValue 5 $IN +$scalars InsertValue 6 $OUT +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 12 - 00111010" + } else { + caseLabel SetText "Case 12c - 11000101" + } +} + +proc case13 { scalars IN OUT } { +$scalars InsertValue 0 $OUT +$scalars InsertValue 1 $IN +$scalars InsertValue 2 $OUT +$scalars InsertValue 3 $IN +$scalars InsertValue 4 $IN +$scalars InsertValue 5 $OUT +$scalars InsertValue 6 $IN +$scalars InsertValue 7 $OUT + if {$IN == 1} { + caseLabel SetText "Case 13 - 01011010" + } else { + caseLabel SetText "Case 13c - 10100101" + } +} + +proc case14 { scalars IN OUT } { +$scalars InsertValue 0 $IN +$scalars InsertValue 1 $OUT +$scalars InsertValue 2 $IN +$scalars InsertValue 3 $IN +$scalars InsertValue 4 $OUT +$scalars InsertValue 5 $IN +$scalars InsertValue 6 $IN +$scalars InsertValue 7 $IN + if {$IN == 1} { + caseLabel SetText "Case 14 - 11101101" + } else { + caseLabel SetText "Case 14c - 00010010" + } +} + diff --git a/Wrapping/Tcl/vtktesting/vtktesting.tcl b/Wrapping/Tcl/vtktesting/vtktesting.tcl new file mode 100644 index 0000000..8055120 --- /dev/null +++ b/Wrapping/Tcl/vtktesting/vtktesting.tcl @@ -0,0 +1,7 @@ +package require -exact vtkcommon 5.0 + +foreach s {colors mccases backdrop grab} { + source [file join [file dirname [info script]] "${s}.tcl"] +} + +package provide vtktesting 5.0 diff --git a/Wrapping/Tcl/vtkvolumerendering/CMakeLists.txt b/Wrapping/Tcl/vtkvolumerendering/CMakeLists.txt new file mode 100644 index 0000000..3aa35f2 --- /dev/null +++ b/Wrapping/Tcl/vtkvolumerendering/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkvolumerendering .tcl vtkvolumerendering) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkvolumerendering/vtkvolumerendering.tcl b/Wrapping/Tcl/vtkvolumerendering/vtkvolumerendering.tcl new file mode 100644 index 0000000..ec82673 --- /dev/null +++ b/Wrapping/Tcl/vtkvolumerendering/vtkvolumerendering.tcl @@ -0,0 +1,12 @@ +package require -exact vtkrendering 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkVolumeRenderingTCL 5.0]} { + package provide vtkvolumerendering 5.0 + } +} else { + if {[info commands vtkEncodedGradientShader] != "" || + [::vtk::load_component vtkVolumeRenderingTCL] == ""} { + package provide vtkvolumerendering 5.0 + } +} diff --git a/Wrapping/Tcl/vtkwidgets/CMakeLists.txt b/Wrapping/Tcl/vtkwidgets/CMakeLists.txt new file mode 100644 index 0000000..4920885 --- /dev/null +++ b/Wrapping/Tcl/vtkwidgets/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(NOT VTK_INSTALL_NO_RUNTIME) + INSTALL_FILES(${VTK_TCL_INSTALL_DIR}/vtkwidgets .tcl vtkwidgets) +ENDIF(NOT VTK_INSTALL_NO_RUNTIME) diff --git a/Wrapping/Tcl/vtkwidgets/vtkwidgets.tcl b/Wrapping/Tcl/vtkwidgets/vtkwidgets.tcl new file mode 100644 index 0000000..4583b6b --- /dev/null +++ b/Wrapping/Tcl/vtkwidgets/vtkwidgets.tcl @@ -0,0 +1,12 @@ +package require -exact vtkhybrid 5.0 + +if {[info commands ::vtk::init::require_package] != ""} { + if {[::vtk::init::require_package vtkWidgetsTCL 5.0]} { + package provide vtkwidgets 5.0 + } +} else { + if {[info commands vtkBorderWidget] != "" || + [::vtk::load_component vtkWidgetsTCL] == ""} { + package provide vtkwidgets 5.0 + } +} diff --git a/Wrapping/hints b/Wrapping/hints new file mode 100644 index 0000000..ac57c19 --- /dev/null +++ b/Wrapping/hints @@ -0,0 +1,196 @@ +vtkAbstractMapper3D GetBounds 307 6 +vtkAbstractMapper3D GetCenter 307 3 +vtkAbstractTransform TransformDoubleNormalAtPoint 307 3 +vtkAbstractTransform TransformDoublePoint 307 3 +vtkAbstractTransform TransformDoubleVectorAtPoint 307 3 +vtkAbstractTransform TransformFloatNormalAtPoint 301 3 +vtkAbstractTransform TransformFloatPoint 301 3 +vtkAbstractTransform TransformFloatVectorAtPoint 301 3 +vtkAbstractTransform TransformNormalAtPoint 307 3 +vtkAbstractTransform TransformPoint 307 3 +vtkAbstractTransform TransformPoint 307 3 +vtkAbstractTransform TransformVectorAtPoint 307 3 +vtkActor GetBounds 307 6 +vtkAssembly GetBounds 307 6 +vtkAxesActor GetBounds 307 6 +vtkCamera GetOrientation 307 3 +vtkCamera GetOrientationWXYZ 307 4 +vtkCell GetBounds 307 6 +vtkColorTransferFunction GetColor 307 3 +vtkCoordinate GetComputedDisplayValue 304 2 +vtkCoordinate GetComputedDoubleDisplayValue 307 2 +vtkCoordinate GetComputedDoubleViewportValue 307 2 +vtkCoordinate GetComputedLocalDisplayValue 304 2 +vtkCoordinate GetComputedViewportValue 304 2 +vtkCoordinate GetComputedWorldValue 307 3 +vtkCubeAxesActor2D GetBounds 307 6 +vtkCubeAxesActor2D GetRanges 307 6 +vtkDataObject GetWholeExtent 304 6 +vtkDataObject GetUpdateExtent 304 6 +vtkDataArray GetRange 307 2 +vtkDataArray GetTuple2 307 2 +vtkDataArray GetTuple3 307 3 +vtkDataArray GetTuple4 307 4 +vtkDataArray GetTuple9 307 9 +vtkDataSet GetBounds 307 6 +vtkDataSet GetCenter 307 3 +vtkDataSet GetPoint 307 3 +vtkDataSet GetScalarRange 307 2 +vtkDICOMImageReader GetPixelSpacing 301 3 +vtkExtractUnstructuredGrid GetExtent 307 6 +vtkExtentSplitter GetSubExtent 304 6 +vtkFunctionParser GetVectorResult 307 3 +vtkFunctionParser GetVectorVariableValue 307 3 +vtkFunctionParser GetVectorVariableValue 307 3 +vtkGeometryFilter GetExtent 307 6 +vtkGridSynchronizedTemplates3D GetExecuteExtent 304 6 +vtkHexahedron GetEdgeArray 304 2 +vtkHexahedron GetFaceArray 304 4 +vtkHyperStreamline GetStartPosition 307 3 +vtkImageAccumulate GetComponentExtent 304 6 +vtkImageActor GetBounds 307 6 +vtkImageActor GetDisplayExtent 304 6 +vtkImageButterworthHighPass GetCutOff 307 3 +vtkImageButterworthLowPass GetCutOff 307 3 +vtkImageClip GetOutputWholeExtent 304 6 +vtkImageConvolve GetKernel3x3 301 9 +vtkImageConvolve GetKernel5x5 301 25 +vtkImageConvolve GetKernel3x3x3 301 27 +vtkImageData GetDimensions 304 3 +vtkImageData GetExtent 304 6 +vtkImageData GetIncrements 30A 3 +vtkImageData GetPoint 307 3 +vtkImageEllipsoidSource GetWholeExtent 304 6 +vtkImageExport GetDataDimensions 304 3 +vtkImageExport GetDataExtent 304 6 +vtkImageExport GetDataOrigin 307 3 +vtkImageExport GetDataSpacing 307 3 +vtkImageMandelbrotSource GetSizeCX 307 4 +vtkImagePadFilter GetOutputWholeExtent 304 6 +vtkImagePlaneWidget GetCenter 307 3 +vtkImagePlaneWidget GetNormal 307 3 +vtkImagePlaneWidget GetOrigin 307 3 +vtkImagePlaneWidget GetPoint1 307 3 +vtkImagePlaneWidget GetPoint2 307 3 +vtkImageReslice GetResliceAxesDirectionCosines 307 9 +vtkImageReslice GetResliceAxesOrigin 307 3 +vtkImageSource GetExecuteExtent 304 6 +vtkImageSpatialAlgorithm GetKernelMiddle 304 3 +vtkImageSpatialAlgorithm GetKernelSize 304 3 +vtkImageSpatialFilter GetKernelMiddle 304 3 +vtkImageSpatialFilter GetKernelSize 304 3 +vtkImageTracerWidget GetHandlePosition 307 3 +vtkImageVectorConvolve GetKernel 301 3 +vtkImageViewer GetPosition 304 2 +vtkImageViewer GetSize 304 2 +vtkImplicitFunction FunctionGradient 307 3 +vtkImplicitPlaneWidget GetNormal 307 3 +vtkImplicitPlaneWidget GetOrigin 307 3 +vtkLegendBoxActor GetEntryColor 307 3 +vtkLight GetColor 307 3 +vtkLight GetTransformedFocalPoint 307 3 +vtkLight GetTransformedPosition 307 3 +vtkLinearTransform TransformDoubleNormal 307 3 +vtkLinearTransform TransformDoubleNormal 307 3 +vtkLinearTransform TransformDoubleVector 307 3 +vtkLinearTransform TransformDoubleVector 307 3 +vtkLinearTransform TransformFloatNormal 301 3 +vtkLinearTransform TransformFloatNormal 301 3 +vtkLinearTransform TransformFloatVector 301 3 +vtkLinearTransform TransformFloatVector 301 3 +vtkLinearTransform TransformNormal 307 3 +vtkLinearTransform TransformNormal 307 3 +vtkLinearTransform TransformVector 307 3 +vtkLinearTransform TransformVector 307 3 +vtkLODProp3D GetBounds 307 6 +vtkLookupTable GetColor 307 3 +vtkLookupTable GetTableValue 307 4 +vtkMapper GetBounds 307 6 +vtkMath HSVToRGB 2307 3 +vtkMath RGBToHSV 2307 3 +vtkMath SolveCubic 2307 3 +vtkMath SolveLinear 2307 1 +vtkMath SolveQuadratic 2307 2 +vtkMatrix4x4 MultiplyDoublePoint 307 4 +vtkMatrix4x4 MultiplyFloatPoint 301 4 +vtkMatrix4x4 MultiplyPoint 301 4 +vtkMedicalImageProperties GetWindowLevelPreset 307 2 +vtkMedicalImageProperties GetNthWindowLevelPreset 307 2 +vtkPiecewiseFunction GetRange 307 2 +vtkPlaneWidget GetCenter 307 3 +vtkPlaneWidget GetNormal 307 3 +vtkPlaneWidget GetOrigin 307 3 +vtkPlaneWidget GetPoint1 307 3 +vtkPlaneWidget GetPoint2 307 3 +vtkLineWidget GetPoint1 307 3 +vtkLineWidget GetPoint2 307 3 +vtkSphereWidget GetCenter 307 3 +vtkPointWidget GetPosition 307 3 +vtkPointSet GetPoint 307 3 +vtkPoints GetBounds 307 6 +vtkPoints GetPoint 307 3 +vtkPolyDataMapper GetBounds 307 6 +vtkPolygon FitEllipse 307 6 +vtkPolygon ConvertEllipseToImplicit 307 5 +vtkPolyLine FitEllipse 307 6 +vtkPolyLine ConvertEllipseToImplicit 307 5 +vtkPolyLine EllipseToImplicit 307 3 +vtkProjectedPolyDataRayBounder GetRayBounds 301 2 +vtkProp3D GetBounds 307 6 +vtkProp3D GetCenter 307 3 +vtkProp3D GetOrientation 307 3 +vtkProp3D GetOrientationWXYZ 307 4 +vtkProp3D GetXRange 307 2 +vtkProp3D GetYRange 307 2 +vtkProp3D GetZRange 307 2 +vtkPropAssembly GetBounds 307 6 +vtkProperty GetColor 307 3 +vtkPyramid GetEdgeArray 304 2 +vtkPyramid GetFaceArray 304 4 +vtkQuadricClustering GetNumberOfDivisions 304 3 +vtkRayCaster GetParallelIncrements 301 2 +vtkRayCaster GetParallelStartPosition 301 3 +vtkRectilinearGrid GetExtent 304 6 +vtkRectilinearGrid GetPoint 307 3 +vtkRecursiveSphereDirectionEncoder GetDecodedGradient 301 3 +vtkRenderer ComputeVisiblePropBounds 307 6 +vtkScalarsToColors GetColor 307 3 +vtkSplineWidget GetHandlePosition 307 3 +vtkStreamer GetStartPosition 307 3 +vtkStructuredGrid GetDimensions 304 3 +vtkStructuredGrid GetExtent 304 6 +vtkStructuredGrid GetPoint 307 3 +vtkStructuredGrid GetScalarRange 307 2 +vtkStructuredPointsGeometryFilter GetExtent 304 6 +vtkSynchronizedTemplates3D GetExecuteExtent 304 6 +vtkTetra GetEdgeArray 304 2 +vtkTetra GetFaceArray 304 3 +vtkTransform GetDoublePoint 307 4 +vtkTransform GetOrientation 307 3 +vtkTransform GetOrientationWXYZ 307 4 +vtkTransform GetPoint 307 4 +vtkTransform GetPosition 307 3 +vtkTransform GetScale 307 3 +vtkViewport GetCenter 307 2 +vtkViewport GetOrigin 304 2 +vtkViewport GetSize 304 2 +vtkViewRays GetParallelIncrements 301 2 +vtkViewRays GetParallelStartPosition 301 3 +vtkVolume GetBounds 307 6 +vtkVolumeMapper GetBounds 307 6 +vtkVoxel GetEdgeArray 304 2 +vtkVoxel GetFaceArray 304 4 +vtkWarpLens GetCenter 307 2 +vtkWedge GetEdgeArray 304 2 +vtkWedge GetFaceArray 304 4 +vtkWindow GetPosition 304 2 +vtkWindow GetSize 304 2 +vtkWindowLevelLookupTable GetMaximumTableValue 307 4 +vtkWindowLevelLookupTable GetMinimumTableValue 307 4 +vtkXImageWindow GetPosition 304 2 +vtkXImageWindow GetSize 304 2 +vtkXRenderWindow GetPosition 304 2 +vtkXRenderWindow GetScreenSize 304 2 +vtkXRenderWindow GetSize 304 2 +vtkXYPlotActor GetPlotColor 307 3 + diff --git a/Wrapping/lex.yy.c b/Wrapping/lex.yy.c new file mode 100644 index 0000000..c634bf0 --- /dev/null +++ b/Wrapping/lex.yy.c @@ -0,0 +1,2778 @@ +#line 2 "lex.yy.c" + +#line 4 "lex.yy.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 31 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#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. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE yylex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ + #define YY_LESS_LINENO(n) \ + do { \ + int yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ + }while(0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - 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). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *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; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* 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 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* 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". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* 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 ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* 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 = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 80 +#define YY_END_OF_BUFFER 81 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[697] = + { 0, + 0, 0, 81, 79, 75, 75, 79, 78, 79, 70, + 74, 74, 76, 77, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 75, 9, 9, 79, 79, + 0, 1, 11, 70, 0, 0, 74, 74, 74, 0, + 0, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 0, 9, 0, 0, 72, 10, 71, 11, 0, + 74, 0, 0, 14, 74, 74, 74, 74, 74, 74, + 74, 74, 30, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 73, 10, 10, 10, 10, 0, + + 74, 74, 74, 36, 74, 74, 74, 74, 74, 0, + 74, 74, 33, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 35, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 10, 10, 10, 10, 10, 10, + 0, 74, 74, 74, 26, 38, 74, 31, 74, 0, + 0, 74, 74, 0, 74, 74, 74, 74, 74, 74, + 32, 74, 74, 74, 74, 0, 0, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 10, 10, + 10, 10, 10, 10, 10, 0, 74, 74, 74, 0, + 34, 41, 0, 0, 74, 74, 0, 0, 74, 74, + + 74, 74, 74, 27, 0, 74, 74, 42, 74, 74, + 0, 0, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 10, 10, 10, 10, 10, 10, 10, + 10, 2, 0, 74, 12, 24, 0, 0, 0, 0, + 20, 74, 0, 0, 18, 74, 74, 28, 74, 0, + 74, 0, 74, 74, 37, 0, 0, 0, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 10, 10, 10, + 10, 10, 10, 10, 12, 74, 0, 20, 0, 0, + 74, 19, 18, 0, 21, 39, 74, 0, 17, 0, + + 74, 40, 0, 0, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 10, 10, 10, 3, 10, 10, + 74, 0, 0, 19, 74, 21, 0, 74, 29, 17, + 0, 74, 0, 0, 73, 73, 73, 73, 73, 73, + 44, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 3, 10, 10, 3, 10, 10, + 69, 0, 0, 15, 0, 74, 0, 74, 0, 25, + 0, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 12, + + 3, 10, 10, 10, 10, 0, 22, 0, 23, 25, + 0, 73, 73, 47, 73, 73, 73, 0, 0, 73, + 46, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 10, 10, 10, 10, 22, 23, 0, 73, 73, 73, + 73, 73, 0, 13, 73, 73, 73, 73, 73, 45, + 67, 73, 73, 73, 10, 10, 10, 10, 0, 0, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 10, 10, 10, 10, 10, 10, 10, 0, 16, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 54, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 8, 73, 73, 73, 73, 73, 73, 73, 73, + 50, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 10, 10, 10, 10, 8, 10, 10, 10, + 10, 8, 73, 53, 49, 73, 73, 73, 73, 64, + 51, 73, 48, 73, 73, 73, 73, 63, 73, 73, + + 73, 10, 10, 10, 10, 8, 10, 10, 10, 10, + 73, 59, 60, 61, 62, 73, 55, 56, 57, 58, + 73, 73, 73, 10, 10, 10, 10, 10, 10, 10, + 10, 73, 73, 73, 73, 73, 10, 10, 10, 10, + 7, 10, 10, 10, 43, 73, 68, 73, 73, 7, + 10, 10, 10, 7, 10, 5, 6, 73, 73, 73, + 7, 10, 5, 6, 10, 5, 6, 73, 73, 73, + 10, 5, 6, 10, 73, 73, 66, 10, 4, 73, + 73, 4, 4, 73, 73, 4, 73, 65, 73, 73, + 73, 73, 73, 73, 52, 0 + + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 1, 6, 7, 1, 1, 8, 1, 9, + 10, 11, 1, 8, 8, 12, 13, 14, 15, 16, + 17, 18, 15, 19, 15, 15, 15, 20, 21, 1, + 8, 1, 1, 1, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 29, 31, 32, 33, 34, 35, 36, + 29, 37, 38, 39, 40, 41, 42, 43, 44, 29, + 45, 1, 46, 1, 47, 1, 48, 49, 50, 51, + + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 29, 64, 65, 66, 67, 68, 69, 29, + 70, 29, 8, 1, 8, 8, 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 flex_int32_t yy_meta[71] = + { 0, + 1, 2, 3, 2, 2, 4, 1, 1, 1, 5, + 1, 1, 1, 6, 6, 6, 6, 6, 6, 1, + 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 1, 1, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 + } ; + +static yyconst flex_int16_t yy_base[722] = + { 0, + 0, 69, 1490, 1491, 1491, 1491, 0, 1491, 64, 69, + 1442, 42, 88, 1491, 52, 53, 32, 50, 49, 33, + 54, 55, 71, 64, 73, 128, 1491, 1491, 1485, 110, + 1481, 1491, 0, 128, 1439, 87, 1438, 102, 93, 148, + 174, 111, 112, 108, 113, 101, 127, 110, 124, 134, + 122, 135, 139, 149, 123, 150, 155, 152, 158, 159, + 126, 205, 1491, 1471, 1480, 1491, 206, 1491, 0, 169, + 1435, 221, 0, 1491, 183, 166, 167, 174, 181, 185, + 188, 186, 238, 190, 198, 200, 203, 201, 202, 204, + 205, 207, 206, 208, 252, 251, 0, 245, 1442, 237, + + 251, 229, 234, 1433, 231, 240, 242, 241, 248, 308, + 255, 261, 316, 257, 267, 275, 276, 277, 278, 279, + 282, 281, 335, 1432, 284, 286, 295, 302, 294, 303, + 287, 304, 312, 332, 0, 340, 1439, 328, 1425, 1433, + 329, 342, 324, 351, 349, 1428, 331, 1427, 330, 1411, + 1417, 333, 337, 383, 343, 344, 345, 346, 211, 350, + 405, 354, 366, 356, 367, 416, 424, 375, 376, 377, + 393, 383, 384, 394, 397, 399, 389, 411, 421, 1419, + 1427, 1447, 1442, 1402, 1463, 410, 420, 417, 415, 466, + 1418, 1417, 1402, 1400, 348, 416, 1400, 1398, 418, 425, + + 419, 426, 427, 1412, 485, 430, 492, 1411, 451, 445, + 497, 507, 459, 428, 481, 435, 473, 511, 477, 474, + 438, 478, 491, 1435, 1430, 1390, 1451, 1420, 1428, 1401, + 1447, 1491, 484, 507, 1402, 1401, 557, 1381, 1392, 1381, + 561, 485, 1378, 1382, 1395, 486, 483, 1394, 498, 1379, + 489, 565, 524, 432, 1392, 570, 579, 587, 546, 510, + 530, 538, 539, 547, 548, 549, 553, 554, 557, 566, + 556, 569, 560, 586, 577, 580, 582, 1405, 1413, 1386, + 1432, 1408, 1394, 1368, 1384, 585, 1372, 632, 1363, 639, + 583, 1381, 1491, 1373, 645, 1379, 604, 1359, 1377, 1368, + + 591, 1375, 654, 662, 605, 613, 506, 614, 615, 623, + 625, 628, 634, 636, 621, 637, 629, 638, 640, 647, + 650, 627, 672, 662, 1395, 1381, 1355, 0, 1388, 1361, + 656, 703, 1354, 1491, 664, 710, 718, 670, 1368, 1491, + 1366, 663, 730, 1351, 679, 681, 682, 689, 691, 671, + 1365, 692, 697, 698, 701, 702, 703, 704, 705, 708, + 709, 716, 713, 607, 0, 1381, 1354, 0, 1374, 1345, + 1360, 779, 783, 1491, 1345, 717, 1344, 725, 1340, 1356, + 1346, 732, 722, 731, 742, 747, 743, 790, 749, 754, + 756, 750, 760, 755, 762, 763, 764, 766, 768, 1354, + + 0, 1365, 1336, 1364, 1331, 1342, 1348, 1328, 1346, 1491, + 1341, 720, 782, 1344, 772, 777, 775, 831, 1380, 795, + 1342, 778, 794, 779, 787, 796, 798, 563, 811, 800, + 1354, 1321, 1381, 1329, 1491, 1491, 850, 809, 801, 824, + 829, 849, 1374, 1491, 822, 839, 826, 841, 861, 1336, + 1335, 828, 836, 834, 1376, 1324, 865, 1317, 902, 890, + 850, 854, 864, 868, 876, 884, 885, 886, 873, 852, + 877, 879, 880, 889, 901, 902, 904, 891, 893, 894, + 896, 920, 1316, 1329, 1324, 1323, 1322, 1312, 957, 1491, + 895, 900, 903, 916, 917, 921, 923, 925, 927, 928, + + 929, 931, 934, 939, 941, 943, 946, 948, 935, 933, + 952, 1324, 1319, 1318, 1317, 1307, 1299, 1301, 1313, 1312, + 1343, 1315, 953, 954, 956, 955, 957, 959, 961, 963, + 967, 968, 988, 969, 974, 975, 976, 981, 970, 997, + 989, 990, 1293, 1295, 1307, 1306, 1337, 1304, 1305, 1349, + 1348, 0, 907, 992, 994, 995, 996, 998, 999, 1002, + 1305, 1003, 1004, 1005, 1006, 1008, 1010, 1011, 1014, 1000, + 1021, 1022, 1299, 1300, 1344, 1343, 0, 1299, 1282, 1323, + 1296, 0, 1024, 1296, 1295, 1031, 1033, 1034, 1035, 1294, + 1293, 1032, 1292, 1036, 1038, 1039, 1040, 1291, 1042, 1043, + + 1056, 1289, 1272, 1313, 1286, 0, 1267, 1276, 1268, 1261, + 1044, 1266, 1259, 1252, 1245, 1058, 1238, 1231, 1224, 1217, + 1059, 1062, 1078, 1184, 1189, 1185, 1178, 1160, 1148, 1139, + 1132, 1065, 1066, 1067, 1068, 1073, 1119, 1115, 1112, 1111, + 0, 1109, 1112, 1111, 1125, 1075, 1124, 1079, 1083, 0, + 1103, 1106, 1105, 0, 1108, 0, 0, 1077, 1102, 1089, + 0, 1028, 0, 0, 1011, 0, 0, 1103, 1092, 1090, + 829, 0, 0, 788, 1069, 1094, 726, 655, 0, 1098, + 1095, 0, 0, 1096, 1099, 0, 1104, 496, 1100, 1123, + 1110, 1113, 1115, 1118, 387, 1491, 1180, 286, 130, 1187, + + 1194, 1201, 92, 1208, 1215, 1221, 1227, 1234, 1240, 1247, + 1254, 1261, 1268, 1275, 1282, 1289, 1296, 1303, 1310, 1317, + 1324 + } ; + +static yyconst flex_int16_t yy_def[722] = + { 0, + 696, 1, 696, 696, 696, 696, 697, 696, 696, 698, + 699, 699, 696, 696, 699, 699, 699, 699, 699, 699, + 699, 699, 699, 699, 699, 696, 696, 696, 700, 696, + 697, 696, 701, 698, 698, 698, 699, 699, 699, 696, + 696, 699, 699, 699, 699, 699, 699, 699, 699, 699, + 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, + 699, 696, 696, 696, 700, 696, 702, 696, 701, 698, + 699, 696, 41, 696, 699, 699, 699, 699, 699, 699, + 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, + 699, 699, 699, 699, 703, 704, 702, 702, 702, 698, + + 699, 699, 699, 699, 699, 699, 699, 699, 699, 696, + 699, 699, 699, 699, 699, 699, 699, 699, 699, 699, + 699, 699, 699, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 704, 704, 704, 702, 702, 702, + 698, 699, 699, 699, 699, 699, 699, 699, 699, 696, + 696, 699, 699, 696, 699, 699, 699, 699, 699, 699, + 699, 699, 699, 699, 699, 696, 696, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 704, 704, + 704, 702, 702, 702, 705, 698, 699, 699, 699, 696, + 699, 699, 696, 696, 699, 699, 696, 696, 699, 699, + + 699, 699, 699, 699, 696, 699, 699, 699, 699, 699, + 696, 706, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 704, 704, 704, 707, 702, 702, 702, + 705, 696, 698, 699, 699, 699, 696, 696, 696, 696, + 699, 699, 696, 696, 699, 699, 699, 699, 699, 696, + 699, 696, 699, 699, 699, 696, 696, 706, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 704, 704, 704, + 707, 702, 702, 702, 698, 699, 696, 696, 696, 696, + 699, 699, 696, 696, 699, 699, 699, 696, 699, 696, + + 699, 699, 696, 696, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 704, 704, 704, 708, 702, 702, + 699, 709, 696, 696, 699, 696, 696, 699, 699, 696, + 696, 699, 696, 696, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 710, 704, 704, 708, 702, 702, + 699, 696, 709, 696, 696, 699, 696, 699, 696, 699, + 696, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + + 710, 704, 704, 702, 702, 696, 699, 696, 699, 696, + 696, 703, 703, 703, 703, 703, 703, 696, 711, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 704, 704, 702, 702, 696, 696, 696, 703, 703, 703, + 703, 703, 711, 696, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 704, 704, 702, 702, 696, 696, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 704, 704, 702, 702, 702, 702, 702, 696, 696, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 704, 704, 704, 704, 704, 702, 702, 702, 702, + 702, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 704, 704, 704, 704, 704, 702, 702, 702, + 702, 712, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 704, 704, 704, 704, 713, 702, 702, 702, + 702, 712, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + + 703, 704, 704, 704, 704, 713, 702, 702, 702, 702, + 703, 703, 703, 703, 703, 703, 703, 703, 703, 703, + 703, 703, 703, 704, 704, 704, 704, 702, 702, 702, + 702, 703, 703, 703, 703, 703, 704, 704, 704, 704, + 714, 702, 702, 702, 703, 703, 703, 703, 703, 715, + 704, 704, 704, 714, 702, 716, 717, 703, 703, 703, + 715, 704, 718, 719, 702, 716, 717, 703, 703, 703, + 704, 718, 719, 702, 703, 703, 703, 704, 720, 703, + 703, 721, 720, 703, 703, 721, 703, 703, 703, 703, + 703, 703, 703, 703, 703, 0, 696, 696, 696, 696, + + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696 + } ; + +static yyconst flex_int16_t yy_nxt[1562] = + { 0, + 4, 5, 6, 5, 5, 7, 4, 8, 8, 8, + 8, 8, 9, 10, 10, 10, 10, 10, 10, 8, + 8, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 11, 11, 11, 13, 14, 15, 11, 11, 16, + 17, 11, 18, 11, 11, 19, 11, 11, 20, 11, + 11, 21, 22, 11, 23, 11, 24, 25, 11, 11, + 26, 27, 28, 26, 32, 29, 33, 42, 38, 38, + 39, 30, 34, 34, 34, 34, 34, 34, 38, 40, + 40, 40, 40, 47, 51, 38, 38, 124, 43, 38, + + 38, 38, 41, 41, 41, 41, 41, 44, 48, 50, + 38, 45, 70, 49, 46, 36, 52, 38, 53, 38, + 32, 54, 67, 71, 58, 55, 56, 42, 59, 62, + 63, 63, 62, 36, 60, 37, 57, 42, 61, 38, + 64, 34, 34, 34, 34, 34, 34, 38, 38, 40, + 40, 40, 40, 75, 38, 77, 38, 38, 38, 38, + 78, 79, 41, 41, 41, 41, 41, 76, 38, 38, + 38, 81, 38, 38, 36, 72, 72, 72, 72, 82, + 38, 38, 84, 95, 89, 38, 85, 73, 73, 73, + 73, 73, 73, 80, 86, 38, 38, 88, 38, 83, + + 87, 38, 91, 90, 38, 38, 62, 63, 63, 62, + 98, 100, 38, 38, 94, 36, 92, 64, 102, 74, + 38, 93, 72, 72, 72, 72, 103, 38, 99, 38, + 104, 38, 38, 107, 38, 108, 38, 109, 105, 110, + 110, 110, 110, 113, 38, 106, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 136, 138, 38, 123, 117, + 203, 114, 121, 143, 119, 118, 74, 115, 116, 139, + 120, 122, 141, 137, 125, 38, 42, 38, 126, 127, + 38, 128, 142, 36, 38, 129, 38, 38, 38, 130, + 131, 35, 132, 133, 38, 145, 111, 38, 134, 144, + + 147, 38, 112, 38, 157, 146, 148, 38, 149, 110, + 110, 110, 110, 38, 158, 153, 152, 154, 154, 154, + 154, 38, 38, 38, 38, 38, 159, 38, 38, 162, + 134, 160, 134, 134, 163, 164, 166, 166, 166, 166, + 134, 134, 161, 167, 169, 168, 170, 165, 134, 134, + 134, 179, 171, 190, 173, 172, 175, 178, 134, 176, + 188, 182, 38, 186, 180, 183, 150, 187, 174, 189, + 38, 155, 151, 177, 156, 36, 38, 38, 134, 38, + 192, 38, 191, 38, 154, 154, 154, 154, 38, 38, + 38, 38, 38, 195, 38, 38, 38, 38, 196, 204, + + 38, 241, 38, 199, 207, 200, 205, 205, 205, 205, + 201, 202, 38, 38, 210, 208, 209, 166, 166, 166, + 166, 134, 134, 134, 167, 211, 211, 211, 211, 134, + 134, 216, 236, 134, 212, 134, 213, 214, 197, 134, + 134, 198, 215, 134, 219, 134, 233, 234, 217, 218, + 221, 38, 222, 223, 224, 235, 36, 134, 225, 220, + 206, 38, 38, 38, 38, 38, 38, 237, 237, 237, + 237, 38, 38, 38, 134, 260, 38, 248, 38, 242, + 247, 134, 302, 245, 134, 246, 205, 205, 205, 205, + 251, 38, 249, 252, 252, 252, 252, 38, 211, 211, + + 211, 211, 254, 255, 265, 134, 275, 212, 256, 256, + 256, 256, 266, 261, 273, 262, 257, 259, 263, 134, + 134, 264, 285, 134, 134, 274, 277, 134, 286, 38, + 36, 38, 38, 238, 267, 38, 276, 134, 38, 295, + 250, 253, 134, 268, 38, 269, 296, 270, 271, 297, + 292, 272, 134, 38, 299, 347, 134, 134, 237, 237, + 237, 237, 290, 290, 290, 290, 252, 252, 252, 252, + 38, 256, 256, 256, 256, 306, 134, 307, 301, 257, + 303, 303, 303, 303, 134, 134, 308, 304, 256, 256, + 256, 256, 134, 134, 134, 134, 257, 305, 310, 134, + + 134, 314, 134, 134, 309, 315, 134, 38, 331, 134, + 311, 313, 134, 312, 300, 134, 324, 316, 320, 291, + 318, 317, 321, 134, 238, 319, 134, 452, 134, 38, + 323, 38, 134, 290, 290, 290, 290, 38, 342, 322, + 290, 290, 290, 290, 335, 400, 337, 337, 337, 337, + 38, 134, 345, 134, 339, 303, 303, 303, 303, 134, + 134, 134, 304, 343, 343, 343, 343, 134, 346, 134, + 348, 134, 350, 134, 134, 134, 351, 355, 349, 352, + 134, 353, 134, 134, 134, 354, 134, 358, 362, 356, + 333, 38, 357, 134, 360, 363, 134, 333, 364, 371, + + 338, 361, 38, 359, 372, 372, 372, 372, 134, 38, + 38, 337, 337, 337, 337, 682, 38, 134, 134, 337, + 337, 337, 337, 374, 376, 134, 380, 134, 134, 344, + 378, 343, 343, 343, 343, 134, 387, 134, 134, 382, + 385, 383, 388, 134, 134, 384, 386, 134, 134, 134, + 134, 134, 391, 392, 134, 134, 389, 396, 393, 134, + 395, 390, 134, 38, 412, 377, 134, 438, 134, 394, + 407, 38, 134, 377, 399, 413, 397, 134, 134, 398, + 372, 372, 372, 372, 372, 372, 372, 372, 134, 134, + 409, 415, 414, 134, 418, 134, 134, 344, 419, 374, + + 134, 134, 134, 374, 417, 422, 134, 416, 134, 134, + 134, 420, 134, 423, 134, 421, 425, 439, 134, 428, + 424, 134, 426, 134, 134, 134, 427, 445, 134, 430, + 441, 429, 448, 134, 453, 418, 134, 440, 442, 419, + 134, 134, 134, 446, 134, 447, 134, 134, 679, 450, + 449, 459, 459, 459, 459, 134, 463, 134, 461, 451, + 460, 464, 462, 454, 465, 466, 467, 468, 134, 470, + 134, 471, 134, 473, 134, 134, 474, 475, 476, 477, + 134, 469, 134, 479, 481, 134, 472, 134, 484, 485, + 678, 489, 489, 478, 489, 134, 134, 480, 134, 490, + + 134, 500, 486, 459, 459, 459, 459, 134, 495, 492, + 134, 493, 460, 491, 134, 494, 496, 497, 498, 134, + 499, 504, 134, 134, 501, 134, 134, 503, 502, 487, + 134, 134, 134, 505, 506, 134, 507, 134, 508, 134, + 134, 134, 134, 512, 513, 583, 134, 134, 134, 134, + 134, 511, 524, 134, 509, 510, 522, 514, 489, 489, + 523, 489, 134, 134, 526, 525, 490, 134, 527, 134, + 528, 134, 529, 134, 134, 134, 530, 134, 532, 134, + 134, 134, 533, 534, 515, 134, 535, 134, 536, 134, + 537, 531, 134, 538, 134, 540, 541, 539, 134, 134, + + 134, 134, 134, 134, 556, 134, 557, 134, 558, 134, + 559, 563, 542, 134, 134, 134, 134, 554, 553, 555, + 134, 134, 134, 565, 566, 567, 560, 134, 561, 570, + 568, 562, 564, 569, 134, 134, 134, 572, 134, 571, + 134, 134, 134, 134, 134, 134, 134, 599, 134, 134, + 134, 134, 134, 584, 134, 585, 134, 134, 586, 587, + 134, 588, 589, 590, 591, 592, 593, 134, 134, 594, + 134, 595, 674, 596, 597, 598, 600, 134, 134, 134, + 134, 134, 134, 671, 134, 134, 134, 601, 134, 134, + 134, 621, 612, 611, 613, 614, 615, 617, 616, 618, + + 619, 620, 134, 622, 134, 134, 632, 623, 134, 635, + 636, 134, 134, 134, 134, 134, 645, 680, 633, 134, + 649, 134, 634, 134, 134, 134, 658, 668, 647, 134, + 659, 646, 660, 648, 669, 134, 134, 675, 134, 676, + 134, 134, 134, 681, 134, 134, 134, 687, 134, 134, + 134, 677, 670, 689, 684, 691, 134, 692, 685, 134, + 688, 134, 693, 665, 134, 690, 664, 663, 662, 134, + 134, 134, 657, 656, 655, 653, 652, 651, 694, 695, + 31, 31, 31, 650, 31, 31, 31, 65, 65, 65, + 65, 65, 65, 65, 69, 69, 644, 69, 69, 69, + + 69, 97, 97, 643, 97, 97, 97, 97, 135, 135, + 642, 135, 135, 135, 135, 231, 231, 231, 231, 231, + 231, 231, 258, 258, 641, 258, 258, 281, 281, 281, + 281, 281, 281, 281, 368, 368, 640, 368, 368, 368, + 368, 373, 373, 639, 638, 373, 373, 401, 401, 637, + 401, 401, 401, 401, 443, 443, 443, 443, 443, 443, + 443, 582, 582, 134, 582, 582, 582, 582, 606, 606, + 134, 606, 606, 606, 606, 654, 654, 134, 654, 654, + 654, 654, 661, 661, 134, 661, 661, 661, 661, 666, + 666, 134, 666, 666, 666, 666, 667, 667, 134, 667, + + 667, 667, 667, 672, 672, 134, 672, 672, 672, 672, + 673, 673, 134, 673, 673, 673, 673, 683, 683, 631, + 683, 683, 683, 683, 686, 686, 630, 686, 686, 686, + 686, 629, 628, 627, 626, 625, 624, 134, 134, 134, + 134, 134, 134, 610, 609, 608, 607, 605, 604, 603, + 602, 134, 581, 580, 579, 578, 577, 576, 575, 574, + 573, 134, 552, 551, 550, 549, 548, 547, 546, 545, + 544, 543, 521, 520, 519, 518, 517, 516, 488, 483, + 482, 134, 134, 444, 458, 457, 456, 455, 134, 444, + 134, 437, 38, 436, 38, 435, 434, 433, 432, 431, + + 134, 411, 38, 410, 408, 406, 38, 405, 404, 403, + 402, 134, 381, 379, 38, 375, 370, 369, 367, 366, + 365, 38, 341, 38, 340, 38, 336, 38, 334, 332, + 36, 330, 329, 328, 232, 327, 326, 325, 38, 298, + 38, 38, 294, 293, 289, 288, 287, 38, 38, 232, + 284, 283, 282, 232, 280, 279, 278, 38, 38, 244, + 243, 240, 239, 38, 38, 232, 230, 229, 228, 227, + 226, 194, 193, 38, 38, 185, 184, 181, 134, 38, + 140, 101, 66, 96, 38, 36, 68, 66, 38, 696, + 3, 696, 696, 696, 696, 696, 696, 696, 696, 696, + + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696 + } ; + +static yyconst flex_int16_t yy_chk[1562] = + { 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, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 9, 2, 9, 15, 17, 20, + 12, 2, 10, 10, 10, 10, 10, 10, 12, 13, + 13, 13, 13, 17, 20, 19, 18, 703, 15, 16, + + 21, 22, 13, 13, 13, 13, 13, 16, 18, 19, + 24, 16, 36, 18, 16, 10, 21, 23, 22, 25, + 30, 22, 30, 39, 24, 23, 23, 38, 25, 26, + 26, 26, 26, 36, 25, 699, 23, 43, 25, 39, + 26, 34, 34, 34, 34, 34, 34, 46, 38, 40, + 40, 40, 40, 42, 44, 44, 48, 42, 43, 45, + 45, 46, 40, 40, 40, 40, 40, 43, 51, 55, + 49, 48, 61, 47, 34, 41, 41, 41, 41, 49, + 50, 52, 51, 61, 55, 53, 52, 41, 41, 41, + 41, 41, 41, 47, 53, 54, 56, 54, 58, 50, + + 53, 57, 57, 56, 59, 60, 62, 62, 62, 62, + 67, 70, 76, 77, 60, 70, 58, 62, 75, 41, + 78, 59, 72, 72, 72, 72, 76, 79, 67, 75, + 77, 80, 82, 80, 81, 81, 84, 82, 78, 83, + 83, 83, 83, 84, 85, 79, 86, 88, 89, 87, + 90, 91, 93, 92, 94, 96, 98, 159, 94, 88, + 159, 85, 92, 102, 90, 89, 72, 86, 87, 98, + 91, 93, 100, 96, 95, 102, 101, 105, 95, 95, + 103, 95, 101, 100, 83, 95, 106, 108, 107, 95, + 95, 698, 95, 95, 109, 105, 83, 101, 95, 103, + + 107, 111, 83, 114, 114, 106, 108, 112, 109, 110, + 110, 110, 110, 115, 115, 112, 111, 113, 113, 113, + 113, 116, 117, 118, 119, 120, 116, 122, 121, 119, + 125, 117, 126, 131, 120, 121, 123, 123, 123, 123, + 129, 127, 118, 123, 126, 125, 127, 122, 128, 130, + 132, 136, 128, 145, 130, 129, 131, 134, 133, 132, + 143, 138, 113, 141, 136, 138, 110, 142, 130, 144, + 143, 113, 110, 133, 113, 141, 149, 147, 134, 152, + 149, 123, 147, 153, 154, 154, 154, 154, 142, 155, + 156, 157, 158, 152, 195, 145, 160, 144, 153, 160, + + 162, 195, 164, 155, 162, 156, 161, 161, 161, 161, + 157, 158, 163, 165, 165, 163, 164, 166, 166, 166, + 166, 168, 169, 170, 166, 167, 167, 167, 167, 172, + 173, 171, 189, 695, 167, 177, 168, 169, 154, 171, + 174, 154, 170, 175, 174, 176, 186, 187, 172, 173, + 176, 161, 177, 178, 179, 188, 186, 178, 179, 175, + 161, 189, 196, 188, 199, 201, 187, 190, 190, 190, + 190, 200, 202, 203, 214, 214, 206, 202, 254, 196, + 201, 216, 254, 199, 221, 200, 205, 205, 205, 205, + 206, 210, 203, 207, 207, 207, 207, 209, 211, 211, + + 211, 211, 209, 210, 216, 213, 221, 211, 212, 212, + 212, 212, 217, 215, 219, 215, 212, 213, 215, 217, + 220, 215, 233, 219, 222, 220, 223, 215, 234, 247, + 233, 242, 246, 190, 218, 251, 222, 223, 207, 246, + 205, 207, 688, 218, 249, 218, 247, 218, 218, 249, + 242, 218, 307, 234, 251, 307, 260, 218, 237, 237, + 237, 237, 241, 241, 241, 241, 252, 252, 252, 252, + 253, 256, 256, 256, 256, 260, 261, 261, 253, 256, + 257, 257, 257, 257, 262, 263, 262, 257, 258, 258, + 258, 258, 259, 264, 265, 266, 258, 259, 264, 267, + + 268, 268, 271, 269, 263, 269, 273, 241, 286, 428, + 265, 267, 270, 266, 252, 272, 277, 270, 274, 241, + 272, 271, 274, 275, 237, 273, 276, 428, 277, 291, + 276, 286, 274, 288, 288, 288, 288, 301, 301, 275, + 290, 290, 290, 290, 291, 364, 295, 295, 295, 295, + 297, 305, 305, 364, 297, 303, 303, 303, 303, 306, + 308, 309, 303, 304, 304, 304, 304, 315, 306, 310, + 308, 311, 310, 322, 312, 317, 311, 315, 309, 312, + 313, 313, 314, 316, 318, 314, 319, 318, 322, 316, + 288, 295, 317, 320, 320, 323, 321, 290, 324, 331, + + 295, 321, 331, 319, 332, 332, 332, 332, 324, 342, + 335, 336, 336, 336, 336, 678, 338, 350, 323, 337, + 337, 337, 337, 332, 335, 345, 342, 346, 347, 304, + 338, 343, 343, 343, 343, 348, 350, 349, 352, 345, + 348, 346, 352, 353, 354, 347, 349, 355, 356, 357, + 358, 359, 355, 356, 360, 361, 353, 360, 357, 363, + 359, 354, 362, 376, 382, 336, 412, 412, 383, 358, + 376, 378, 677, 337, 363, 383, 361, 384, 382, 362, + 372, 372, 372, 372, 373, 373, 373, 373, 385, 387, + 378, 385, 384, 386, 388, 389, 392, 343, 388, 372, + + 390, 394, 391, 373, 387, 391, 393, 386, 395, 396, + 397, 389, 398, 392, 399, 390, 394, 413, 415, 397, + 393, 417, 395, 416, 422, 424, 396, 420, 413, 399, + 416, 398, 424, 425, 429, 418, 388, 415, 417, 418, + 423, 420, 426, 422, 427, 423, 430, 439, 674, 426, + 425, 437, 437, 437, 437, 438, 440, 429, 438, 427, + 437, 441, 439, 430, 442, 442, 442, 442, 445, 445, + 440, 446, 447, 448, 452, 441, 449, 449, 449, 449, + 454, 442, 453, 452, 454, 446, 447, 448, 457, 457, + 671, 460, 460, 449, 460, 442, 461, 453, 470, 460, + + 462, 470, 457, 459, 459, 459, 459, 449, 465, 462, + 463, 463, 459, 461, 464, 464, 466, 467, 468, 469, + 469, 474, 465, 471, 471, 472, 473, 473, 472, 457, + 466, 467, 468, 475, 476, 474, 477, 478, 478, 479, + 480, 491, 481, 482, 482, 553, 492, 475, 476, 493, + 477, 481, 493, 553, 479, 480, 491, 482, 489, 489, + 492, 489, 494, 495, 495, 494, 489, 496, 496, 497, + 497, 498, 498, 499, 500, 501, 499, 502, 501, 510, + 503, 509, 502, 503, 482, 504, 504, 505, 505, 506, + 506, 500, 507, 507, 508, 509, 510, 508, 511, 523, + + 524, 526, 525, 527, 526, 528, 527, 529, 528, 530, + 529, 533, 511, 531, 532, 534, 539, 524, 523, 525, + 535, 536, 537, 535, 536, 537, 530, 538, 531, 540, + 538, 532, 534, 539, 533, 541, 542, 542, 554, 541, + 555, 556, 557, 540, 558, 559, 570, 570, 560, 562, + 563, 564, 565, 554, 566, 555, 567, 568, 556, 557, + 569, 558, 559, 560, 562, 563, 564, 571, 572, 565, + 583, 566, 665, 567, 568, 569, 571, 586, 592, 587, + 588, 589, 594, 662, 595, 596, 597, 572, 599, 600, + 611, 599, 586, 583, 587, 588, 589, 594, 592, 595, + + 596, 597, 601, 600, 616, 621, 611, 601, 622, 622, + 623, 632, 633, 634, 635, 675, 632, 675, 616, 636, + 636, 646, 621, 658, 623, 648, 646, 658, 634, 649, + 648, 633, 649, 635, 659, 660, 670, 668, 669, 669, + 676, 681, 684, 676, 680, 685, 689, 684, 659, 668, + 687, 670, 660, 687, 680, 690, 691, 691, 681, 692, + 685, 693, 692, 655, 694, 689, 653, 652, 651, 690, + 647, 645, 644, 643, 642, 640, 639, 638, 693, 694, + 697, 697, 697, 637, 697, 697, 697, 700, 700, 700, + 700, 700, 700, 700, 701, 701, 631, 701, 701, 701, + + 701, 702, 702, 630, 702, 702, 702, 702, 704, 704, + 629, 704, 704, 704, 704, 705, 705, 705, 705, 705, + 705, 705, 706, 706, 628, 706, 706, 707, 707, 707, + 707, 707, 707, 707, 708, 708, 627, 708, 708, 708, + 708, 709, 709, 626, 625, 709, 709, 710, 710, 624, + 710, 710, 710, 710, 711, 711, 711, 711, 711, 711, + 711, 712, 712, 620, 712, 712, 712, 712, 713, 713, + 619, 713, 713, 713, 713, 714, 714, 618, 714, 714, + 714, 714, 715, 715, 617, 715, 715, 715, 715, 716, + 716, 615, 716, 716, 716, 716, 717, 717, 614, 717, + + 717, 717, 717, 718, 718, 613, 718, 718, 718, 718, + 719, 719, 612, 719, 719, 719, 719, 720, 720, 610, + 720, 720, 720, 720, 721, 721, 609, 721, 721, 721, + 721, 608, 607, 605, 604, 603, 602, 598, 593, 591, + 590, 585, 584, 581, 580, 579, 578, 576, 575, 574, + 573, 561, 551, 550, 549, 548, 547, 546, 545, 544, + 543, 522, 521, 520, 519, 518, 517, 516, 515, 514, + 513, 512, 488, 487, 486, 485, 484, 483, 458, 456, + 455, 451, 450, 443, 434, 433, 432, 431, 421, 419, + 414, 411, 409, 408, 407, 406, 405, 404, 403, 402, + + 400, 381, 380, 379, 377, 375, 371, 370, 369, 367, + 366, 351, 344, 341, 339, 333, 330, 329, 327, 326, + 325, 302, 300, 299, 298, 296, 294, 292, 289, 287, + 285, 284, 283, 282, 281, 280, 279, 278, 255, 250, + 248, 245, 244, 243, 240, 239, 238, 236, 235, 231, + 230, 229, 228, 227, 226, 225, 224, 208, 204, 198, + 197, 194, 193, 192, 191, 185, 184, 183, 182, 181, + 180, 151, 150, 148, 146, 140, 139, 137, 124, 104, + 99, 71, 65, 64, 37, 35, 31, 29, 11, 3, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696, 696, 696, 696, 696, 696, 696, 696, 696, 696, + 696 + } ; + +/* Table of booleans, true if rule could match eol. */ +static yyconst flex_int32_t yy_rule_can_match_eol[81] = + { 0, +0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 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, 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, 0, + 0, }; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* 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 +char *yytext; +#line 1 "vtkParse.l" +#line 3 "vtkParse.l" + +/* + +This file must be translated to C and modified to build everywhere. + +Run flex like this: + + flex -olex.yy.c vtkParse.l + +Modify lex.yy.c: + - remove yyunput function + - remove TABs + +*/ + +/* We do not care of interactive mode */ +#define YY_NEVER_INTERACTIVE 1 +#define YY_NO_UNPUT 1 + +/* Do not include unistd.h in generated source. */ +#define YY_NO_UNISTD_H + +/* Skip declaring this function. It is a macro. */ +#define YY_SKIP_YYWRAP + +#ifdef _WIN32 +#pragma warning ( disable : 4127 ) +#pragma warning ( disable : 4131 ) +#pragma warning ( disable : 4244 ) +#pragma warning ( disable : 4251 ) +#pragma warning ( disable : 4267 ) +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4309 ) +#pragma warning ( disable : 4706 ) +#pragma warning ( disable : 4786 ) +#endif + +#line 1084 "lex.yy.c" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#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 +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#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 ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#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) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* 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 \ + if ( yyleng > 0 ) \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 43 "vtkParse.l" + + +#line 1241 "lex.yy.c" + + 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 = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + 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_current_state += YY_AT_BOL(); +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 >= 697 ) + 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] != 1491 ); + +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; + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) + { + int yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + + yylineno++; +; + } + +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 45 "vtkParse.l" +{ int c1 = 0, c2 = input(); + for (;;) + { + if (c2 == 0) + { + fprintf(yyout,"Cannot find closing comment.\n"); + break; + } + if (c1 == '*' && c2 == '/') break; + c1 = c2; c2 = input(); + } + }; + YY_BREAK +case 2: +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 58 "vtkParse.l" +{ + int c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = input(); + for (;;) + { + if (c5 == 0) + { + fprintf(yyout,"Cannot find matching //ETX.\n"); + break; + } + if (c1 == '/' && c2 == '/' && c3 == 'E' && c4 == 'T' && c5 == 'X') break; + c1 = c2; c2 = c3; c3 = c4; c4 = c5; c5 = input(); + } + for (;;) + { + if (c5 == 0) break; + if (c5 == '\n') break; + c5 = input(); + } + }; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 78 "vtkParse.l" +{ + int pos = 1; + while (yytext[pos-1] != 'M' || yytext[pos] != 'E') + { + pos++; + } + yylval.str = (char *)malloc(yyleng + 1 - pos - 1); + memcpy(yylval.str,yytext+ pos + 1,yyleng - pos - 1); + yylval.str[yyleng - pos - 1] = '\0'; + data.NameComment = vtkstrdup(yylval.str); + }; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 90 "vtkParse.l" +{ + CommentState = 1; + data.Description = (char*)malloc(100000); + data.Description[0] = '\0'; + }; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 96 "vtkParse.l" +{ + CommentState = 3; + data.SeeAlso = (char*)malloc(100000); + data.SeeAlso[0] = '\0'; + }; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 102 "vtkParse.l" +{ + CommentState = 3; + data.SeeAlso = (char*)malloc(100000); + data.SeeAlso[0] = '\0'; + }; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 108 "vtkParse.l" +{ + CommentState = 4; + data.Caveats = (char*)malloc(100000); + data.Caveats[0] = '\0'; + }; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 114 "vtkParse.l" +{ + CommentState = 2; + HaveComment = 1; + CommentText[0] = '\0'; + }; + YY_BREAK +case 9: +/* rule 9 can match eol */ +YY_RULE_SETUP +#line 120 "vtkParse.l" +{ + HaveComment = 0; + CommentState = 0; + }; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 125 "vtkParse.l" +{ + int pos = 1; + while (yytext[pos-1] != '/' || yytext[pos] != '/') pos++; + yylval.str = (char *)malloc(yyleng + 1 - pos - 1 + 1); + memcpy(yylval.str,yytext+ pos + 1,yyleng - pos - 1); + yylval.str[yyleng - pos - 1] = '\n'; + yylval.str[yyleng - pos] = '\0'; + switch (CommentState) + { + case 1: strcat(data.Description,yylval.str); break; + case 2: strcat(CommentText,yylval.str); break; + case 3: strcat(data.SeeAlso,yylval.str); break; + case 4: strcat(data.Caveats,yylval.str); break; + } + }; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 141 "vtkParse.l" +; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 143 "vtkParse.l" +; + YY_BREAK +case 13: +/* rule 13 can match eol */ +YY_RULE_SETUP +#line 145 "vtkParse.l" +; + YY_BREAK +case 14: +/* rule 14 can match eol */ +YY_RULE_SETUP +#line 147 "vtkParse.l" +{ + sscanf(yytext+1,"%d",&yylval.integer); return(ARRAY_NUM);} + YY_BREAK +case 15: +/* rule 15 can match eol */ +YY_RULE_SETUP +#line 151 "vtkParse.l" +return(CLASS_REF); + YY_BREAK +case 16: +/* rule 16 can match eol */ +YY_RULE_SETUP +#line 153 "vtkParse.l" +return(VAR_FUNCTION); + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +#line 155 "vtkParse.l" +return(SHORT); + YY_BREAK +case 18: +/* rule 18 can match eol */ +YY_RULE_SETUP +#line 156 "vtkParse.l" +return(LONG); + YY_BREAK +case 19: +/* rule 19 can match eol */ +YY_RULE_SETUP +#line 157 "vtkParse.l" +return(SHORT); + YY_BREAK +case 20: +/* rule 20 can match eol */ +YY_RULE_SETUP +#line 158 "vtkParse.l" +return(LONG); + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +#line 160 "vtkParse.l" +return(LONG_LONG); + YY_BREAK +case 22: +/* rule 22 can match eol */ +YY_RULE_SETUP +#line 161 "vtkParse.l" +return(LONG_LONG); + YY_BREAK +case 23: +/* rule 23 can match eol */ +YY_RULE_SETUP +#line 162 "vtkParse.l" +return(LONG_LONG); + YY_BREAK +case 24: +YY_RULE_SETUP +#line 164 "vtkParse.l" +return(INT64__); + YY_BREAK +case 25: +/* rule 25 can match eol */ +YY_RULE_SETUP +#line 166 "vtkParse.l" +return(SIGNED_CHAR); + YY_BREAK +case 26: +YY_RULE_SETUP +#line 168 "vtkParse.l" +return(CLASS); + YY_BREAK +case 27: +YY_RULE_SETUP +#line 169 "vtkParse.l" +return(PUBLIC); + YY_BREAK +case 28: +YY_RULE_SETUP +#line 170 "vtkParse.l" +return(PRIVATE); + YY_BREAK +case 29: +YY_RULE_SETUP +#line 171 "vtkParse.l" +return(PROTECTED); + YY_BREAK +case 30: +YY_RULE_SETUP +#line 172 "vtkParse.l" +return(INT); + YY_BREAK +case 31: +YY_RULE_SETUP +#line 173 "vtkParse.l" +return(FLOAT); + YY_BREAK +case 32: +YY_RULE_SETUP +#line 174 "vtkParse.l" +return(SHORT); + YY_BREAK +case 33: +YY_RULE_SETUP +#line 175 "vtkParse.l" +return(LONG); + YY_BREAK +case 34: +YY_RULE_SETUP +#line 176 "vtkParse.l" +return(DOUBLE); + YY_BREAK +case 35: +YY_RULE_SETUP +#line 177 "vtkParse.l" +return(VOID); + YY_BREAK +case 36: +YY_RULE_SETUP +#line 178 "vtkParse.l" +return(CHAR); + YY_BREAK +case 37: +YY_RULE_SETUP +#line 179 "vtkParse.l" +return(VIRTUAL); + YY_BREAK +case 38: +YY_RULE_SETUP +#line 180 "vtkParse.l" +return(CONST); + YY_BREAK +case 39: +YY_RULE_SETUP +#line 181 "vtkParse.l" +return(OPERATOR); + YY_BREAK +case 40: +YY_RULE_SETUP +#line 182 "vtkParse.l" +return(UNSIGNED); + YY_BREAK +case 41: +YY_RULE_SETUP +#line 183 "vtkParse.l" +return(FRIEND); + YY_BREAK +case 42: +YY_RULE_SETUP +#line 184 "vtkParse.l" +return(STATIC); + YY_BREAK +case 43: +YY_RULE_SETUP +#line 186 "vtkParse.l" +return(DOUBLE); + YY_BREAK +case 44: +YY_RULE_SETUP +#line 187 "vtkParse.l" +return(IdType); + YY_BREAK +case 45: +YY_RULE_SETUP +#line 188 "vtkParse.l" +return(StdString); + YY_BREAK +case 46: +YY_RULE_SETUP +#line 189 "vtkParse.l" +return(SetMacro); + YY_BREAK +case 47: +YY_RULE_SETUP +#line 190 "vtkParse.l" +return(GetMacro); + YY_BREAK +case 48: +YY_RULE_SETUP +#line 191 "vtkParse.l" +return(SetStringMacro); + YY_BREAK +case 49: +YY_RULE_SETUP +#line 192 "vtkParse.l" +return(GetStringMacro); + YY_BREAK +case 50: +YY_RULE_SETUP +#line 193 "vtkParse.l" +return(SetClampMacro); + YY_BREAK +case 51: +YY_RULE_SETUP +#line 194 "vtkParse.l" +return(SetObjectMacro); + YY_BREAK +case 52: +YY_RULE_SETUP +#line 195 "vtkParse.l" +return(SetReferenceCountedObjectMacro); + YY_BREAK +case 53: +YY_RULE_SETUP +#line 196 "vtkParse.l" +return(GetObjectMacro); + YY_BREAK +case 54: +YY_RULE_SETUP +#line 197 "vtkParse.l" +return(BooleanMacro); + YY_BREAK +case 55: +YY_RULE_SETUP +#line 198 "vtkParse.l" +return(SetVector2Macro); + YY_BREAK +case 56: +YY_RULE_SETUP +#line 199 "vtkParse.l" +return(SetVector3Macro); + YY_BREAK +case 57: +YY_RULE_SETUP +#line 200 "vtkParse.l" +return(SetVector4Macro); + YY_BREAK +case 58: +YY_RULE_SETUP +#line 201 "vtkParse.l" +return(SetVector6Macro); + YY_BREAK +case 59: +YY_RULE_SETUP +#line 202 "vtkParse.l" +return(GetVector2Macro); + YY_BREAK +case 60: +YY_RULE_SETUP +#line 203 "vtkParse.l" +return(GetVector3Macro); + YY_BREAK +case 61: +YY_RULE_SETUP +#line 204 "vtkParse.l" +return(GetVector4Macro); + YY_BREAK +case 62: +YY_RULE_SETUP +#line 205 "vtkParse.l" +return(GetVector6Macro); + YY_BREAK +case 63: +YY_RULE_SETUP +#line 206 "vtkParse.l" +return(SetVectorMacro); + YY_BREAK +case 64: +YY_RULE_SETUP +#line 207 "vtkParse.l" +return(GetVectorMacro); + YY_BREAK +case 65: +YY_RULE_SETUP +#line 208 "vtkParse.l" +return(ViewportCoordinateMacro); + YY_BREAK +case 66: +YY_RULE_SETUP +#line 209 "vtkParse.l" +return(WorldCoordinateMacro); + YY_BREAK +case 67: +YY_RULE_SETUP +#line 210 "vtkParse.l" +return(TypeMacro); + YY_BREAK +case 68: +YY_RULE_SETUP +#line 211 "vtkParse.l" +return(TypeMacro); + YY_BREAK +case 69: +YY_RULE_SETUP +#line 212 "vtkParse.l" +return(VTK_LEGACY); + YY_BREAK +case 70: +YY_RULE_SETUP +#line 214 "vtkParse.l" +{ sscanf(yytext,"%d",&yylval.integer); return(NUM);} + YY_BREAK +case 71: +/* rule 71 can match eol */ +YY_RULE_SETUP +#line 216 "vtkParse.l" +{ + yylval.str = vtkstrdup(yytext + 1); + yylval.str[strlen(yytext)-2] = '\0'; + return(STRING); + } + YY_BREAK +case 72: +*yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 222 "vtkParse.l" +; + YY_BREAK +case 73: +YY_RULE_SETUP +#line 225 "vtkParse.l" +{ yylval.str = (char *)malloc(yyleng + 1); + memcpy(yylval.str,yytext,yyleng); + yylval.str[yyleng] = '\0'; + return(VTK_ID); + } + YY_BREAK +case 74: +YY_RULE_SETUP +#line 231 "vtkParse.l" +{ yylval.str = (char *)malloc(yyleng + 1); + memcpy(yylval.str,yytext,yyleng); + yylval.str[yyleng] = '\0'; + return(ID); + } + YY_BREAK +case 75: +/* rule 75 can match eol */ +YY_RULE_SETUP +#line 237 "vtkParse.l" +; + YY_BREAK +case 76: +YY_RULE_SETUP +#line 240 "vtkParse.l" +return(yytext[0]); + YY_BREAK +case 77: +YY_RULE_SETUP +#line 241 "vtkParse.l" +return(yytext[0]); + YY_BREAK +case 78: +YY_RULE_SETUP +#line 244 "vtkParse.l" +{ return(yytext[0]); } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 246 "vtkParse.l" +return(OTHER); + YY_BREAK +case 80: +YY_RULE_SETUP +#line 247 "vtkParse.l" +ECHO; + YY_BREAK +#line 1845 "lex.yy.c" +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_LVALUE->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_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->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_LVALUE->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_LVALUE->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 */ + +/* 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 + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->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_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->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_LVALUE->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_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* 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. */ + yyrealloc((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_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->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_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + yy_current_state += YY_AT_BOL(); + + 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 >= 697 ) + 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 ); + */ + static yy_state_type 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 >= 697 ) + 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 == 696); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + 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_LVALUE->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 ); + + /*FALLTHROUGH*/ + + 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); + + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); + if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol ) + + yylineno++; +; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + 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_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = 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; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(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 *) yyalloc(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; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void 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( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param str a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yy_str ) +{ + + return yy_scan_bytes(yy_str,strlen(yy_str) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * bytes, int len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + 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. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* 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 ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef yytext_ptr +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif +#line 247 "vtkParse.l" diff --git a/Wrapping/vtkHTML.c b/Wrapping/vtkHTML.c new file mode 100644 index 0000000..ed06b6e --- /dev/null +++ b/Wrapping/vtkHTML.c @@ -0,0 +1,193 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "vtkParse.h" + +/* print the parsed structures */ +void vtkParseOutput(FILE *fp, FileInfo *data) +{ + int i,closed,no_methods; + + fprintf(fp,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"); + fprintf(fp,"<!-- manual pages generated by vtkHTML -->\n\n"); + fprintf(fp,"<HTML><HEADER>\n<TITLE>Documentation for %s\n", + data->ClassName); + + fprintf(fp,"\n"); + + fprintf(fp,"
\n"); + + if (data->NameComment) + { + fprintf(fp,"

%s

\n\n",data->NameComment); + } + else + { + fprintf(fp,"

%s - no description provided.

\n\n",data->ClassName); + } + + fprintf(fp,"
\n"); + + if (data->NumberOfSuperClasses > 0) + { + fprintf(fp,"

Super Class: %s

\n", + data->SuperClasses[0], data->SuperClasses[0]); + } + + fprintf(fp,"

Description:

\n\n
\n"); + fprintf(fp,"

%s

\n
\n\n", + data->Description ? data->Description : "None provided."); + + if (data->Caveats) + { + fprintf(fp,"

Caveats:

\n\n
\n"); + fprintf(fp,"

%s

\n
\n\n", data->Caveats); + } + + if (data->SeeAlso) + { + char *dup, *tok; + + fprintf(fp,"

See Also:

\n\n
\n"); + fprintf(fp,"

"); + /* change simple see also into html references */ + dup = strdup(data->SeeAlso); + tok = strtok(dup," "); + while (tok) + { + if (!strncmp("vtk",tok,3)) + { + fprintf(fp,"%s ",tok, tok); + } + else + { + fprintf(fp,"%s ",tok); + } + tok = strtok(NULL," "); + } + fprintf(fp,"

\n
\n\n"); + free(dup); + } + + fprintf(fp,"

 

\n\n"); + fprintf(fp,"
\n"); + + no_methods = 1; + fprintf(fp,"

Public Methods:

\n\n
    \n\n"); + for (i = 0; i < data->NumberOfFunctions; i++) + { + if (data->Functions[i].Name && data->Functions[i].IsPublic) + { + no_methods = 0; + if (data->Functions[i].Comment) + { + fprintf(fp,"
  • %s
  • ", i, + data->Functions[i].Signature); + } + else + { + fprintf(fp,"
  • %s
  • ", data->Functions[i].Signature); + } + } + } + if (no_methods) + { + fprintf(fp,"
  • %s
  • ","[no public methods]"); + } + fprintf(fp,"
\n\n"); + fprintf(fp,"

 

\n\n"); + + no_methods = 1; + fprintf(fp,"

Protected Methods:

\n\n
    \n\n"); + for (i = 0; i < data->NumberOfFunctions; i++) + { + if (data->Functions[i].Name && data->Functions[i].IsProtected) + { + no_methods = 0; + if (data->Functions[i].Comment) + { + fprintf(fp,"
  • %s
  • ", i, + data->Functions[i].Signature); + } + else + { + fprintf(fp,"
  • %s
  • ", data->Functions[i].Signature); + } + } + } + if (no_methods) + { + fprintf(fp,"
  • %s
  • ","[no protected methods]"); + } + fprintf(fp,"
\n\n"); + fprintf(fp,"

 

\n\n"); + + no_methods = 1; + fprintf(fp,"

Private Methods:

\n\n
    \n\n"); + for (i = 0; i < data->NumberOfFunctions; i++) + { + if (data->Functions[i].Name && !(data->Functions[i].IsProtected || + data->Functions[i].IsPublic)) + { + no_methods = 0; + if (data->Functions[i].Comment) + { + fprintf(fp,"
  • %s
  • ", i, + data->Functions[i].Signature); + } + else + { + fprintf(fp,"
  • %s
  • ", data->Functions[i].Signature); + } + } + } + if (no_methods) + { + fprintf(fp,"
  • %s
  • ","[no private methods]"); + } + fprintf(fp,"
\n\n"); + fprintf(fp,"

 

\n\n"); + + fprintf(fp,"
\n"); + + fprintf(fp,"

Detailed Method Descriptions:


\n"); + closed = 1; + for (i = 0; i < data->NumberOfFunctions; i++) + { + if (data->Functions[i].Name && data->Functions[i].Comment) + { + if (closed) + { + fprintf(fp,"
    \n"); + closed = 0; + } + fprintf(fp,"
  • %s%s
  • \n", i, + data->Functions[i].Signature, + ((data->Functions[i].IsPublic) ? "" : + (data->Functions[i].IsProtected) ? " [protected]" : + " [private]")); + /* if we have a comment */ + if (data->Functions[i].Comment) + { + /* and this is the last method */ + if (i == (data->NumberOfFunctions - 1) || + /* or it isn't the last */ + (i < (data->NumberOfFunctions - 1) && + /* and the next comment either doesn't exist */ + (!data->Functions[i+1].Comment || + /* or it does exist but is different */ + (data->Functions[i+1].Comment && + strcmp(data->Functions[i].Comment, + data->Functions[i+1].Comment))))) + { + closed = 1; + fprintf(fp,"
    "); + fprintf(fp,"

    %s

    \n

\n\n", + data->Functions[i].Comment); + } + } + } + } + fprintf(fp,"

 

\n\n\n"); +} + diff --git a/Wrapping/vtkParse.h b/Wrapping/vtkParse.h new file mode 100644 index 0000000..d93d553 --- /dev/null +++ b/Wrapping/vtkParse.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParse.h,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#define MAX_ARGS 20 + + typedef struct _FunctionInfo + { + char *Name; + int NumberOfArguments; + int ArrayFailure; + int IsPureVirtual; + int IsPublic; + int IsProtected; + int IsOperator; + int HaveHint; + int HintSize; + int ArgTypes[MAX_ARGS]; + int ArgCounts[MAX_ARGS]; + char *ArgClasses[MAX_ARGS]; + int ReturnType; + char *ReturnClass; + char *Comment; + char *Signature; + int IsLegacy; + } FunctionInfo; + + typedef struct _FileInfo + { + int HasDelete; + int IsAbstract; + int IsConcrete; + char *ClassName; + char *FileName; + char *OutputFileName; + + char *SuperClasses[10]; + int NumberOfSuperClasses; + int NumberOfFunctions; + FunctionInfo Functions[1000]; + char *NameComment; + char *Description; + char *Caveats; + char *SeeAlso; + } FileInfo; diff --git a/Wrapping/vtkParse.l b/Wrapping/vtkParse.l new file mode 100644 index 0000000..c93334a --- /dev/null +++ b/Wrapping/vtkParse.l @@ -0,0 +1,248 @@ +%option yylineno +%{ + +/* + +This file must be translated to C and modified to build everywhere. + +Run flex like this: + + flex -olex.yy.c vtkParse.l + +Modify lex.yy.c: + - remove yyunput function + - remove TABs + +*/ + +/* We do not care of interactive mode */ +#define YY_NEVER_INTERACTIVE 1 +#define YY_NO_UNPUT 1 + +/* Do not include unistd.h in generated source. */ +#define YY_NO_UNISTD_H + +/* Skip declaring this function. It is a macro. */ +#define YY_SKIP_YYWRAP + +#ifdef _WIN32 +#pragma warning ( disable : 4127 ) +#pragma warning ( disable : 4131 ) +#pragma warning ( disable : 4244 ) +#pragma warning ( disable : 4251 ) +#pragma warning ( disable : 4267 ) +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4309 ) +#pragma warning ( disable : 4706 ) +#pragma warning ( disable : 4786 ) +#endif + +%} + + +%% + +"/*" { int c1 = 0, c2 = input(); + for (;;) + { + if (c2 == 0) + { + fprintf(yyout,"Cannot find closing comment.\n"); + break; + } + if (c1 == '*' && c2 == '/') break; + c1 = c2; c2 = input(); + } + }; + +^[\t ]*"//BTX".*$ { + int c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = input(); + for (;;) + { + if (c5 == 0) + { + fprintf(yyout,"Cannot find matching //ETX.\n"); + break; + } + if (c1 == '/' && c2 == '/' && c3 == 'E' && c4 == 'T' && c5 == 'X') break; + c1 = c2; c2 = c3; c3 = c4; c4 = c5; c5 = input(); + } + for (;;) + { + if (c5 == 0) break; + if (c5 == '\n') break; + c5 = input(); + } + }; + +^[\t ]*"// .NAME".* { + int pos = 1; + while (yytext[pos-1] != 'M' || yytext[pos] != 'E') + { + pos++; + } + yylval.str = (char *)malloc(yyleng + 1 - pos - 1); + memcpy(yylval.str,yytext+ pos + 1,yyleng - pos - 1); + yylval.str[yyleng - pos - 1] = '\0'; + data.NameComment = vtkstrdup(yylval.str); + }; + +^[\t ]*"// .SECTION Description".* { + CommentState = 1; + data.Description = (char*)malloc(100000); + data.Description[0] = '\0'; + }; + +^[\t ]*"// .SECTION See Also".* { + CommentState = 3; + data.SeeAlso = (char*)malloc(100000); + data.SeeAlso[0] = '\0'; + }; + +^[\t ]*"// .SECTION see also".* { + CommentState = 3; + data.SeeAlso = (char*)malloc(100000); + data.SeeAlso[0] = '\0'; + }; + +^[\t ]*"// .SECTION Caveats".* { + CommentState = 4; + data.Caveats = (char*)malloc(100000); + data.Caveats[0] = '\0'; + }; + +^[\t ]*"// Description:".* { + CommentState = 2; + HaveComment = 1; + CommentText[0] = '\0'; + }; + +^[\t ]*[\r\n] { + HaveComment = 0; + CommentState = 0; + }; + +^[\t ]*"//".* { + int pos = 1; + while (yytext[pos-1] != '/' || yytext[pos] != '/') pos++; + yylval.str = (char *)malloc(yyleng + 1 - pos - 1 + 1); + memcpy(yylval.str,yytext+ pos + 1,yyleng - pos - 1); + yylval.str[yyleng - pos - 1] = '\n'; + yylval.str[yyleng - pos] = '\0'; + switch (CommentState) + { + case 1: strcat(data.Description,yylval.str); break; + case 2: strcat(CommentText,yylval.str); break; + case 3: strcat(data.SeeAlso,yylval.str); break; + case 4: strcat(data.Caveats,yylval.str); break; + } + }; + +"//".* ; + +[A-Za-z0-9_]*"_EXPORT" ; + +"vtkNotUsed"[ ]*"("[^)]*")" ; + +"["[\t\n\r\ ]*[1-9][0-9]*[\t\n\r ]*"]" { + sscanf(yytext+1,"%d",&yylval.integer); return(ARRAY_NUM);} + + +"class "[\t\n\r ]*"vtk"[a-zA-Z0-9_]*[\t\n\r ]*";" return(CLASS_REF); + +"void"[\t\n\r ]*"("[\t\n\r ]*"*"[a-zA-Z0-9_]*[\t\n\r ]*")"[\t\n\r ]*"("[\t\n\r ]*"void"[\t\n\r ]*"*"[\n\t ]*")" return(VAR_FUNCTION); + +"short"[\t\n\r ]*"int" return(SHORT); +"long"[\t\n\r ]*"int" return(LONG); +"int"[\t\n\r ]*"short" return(SHORT); +"int"[\t\n\r ]*"long" return(LONG); + +"long"[\t\n\r ]*"long" return(LONG_LONG); +"int"[\t\n\r ]*"long"[\t\n\r ]*"long" return(LONG_LONG); +"long"[\t\n\r ]*"long"[\t\n\r ]*"int" return(LONG_LONG); + +"__int64" return(INT64__); + +"signed"[\t\n\r ]*"char" return(SIGNED_CHAR); + +"class" return(CLASS); +"public" return(PUBLIC); +"private" return(PRIVATE); +"protected" return(PROTECTED); +"int" return(INT); +"float" return(FLOAT); +"short" return(SHORT); +"long" return(LONG); +"double" return(DOUBLE); +"void" return(VOID); +"char" return(CHAR); +"virtual" return(VIRTUAL); +"const" return(CONST); +"operator" return(OPERATOR); +"unsigned" return(UNSIGNED); +"friend" return(FRIEND); +"static" return(STATIC); + +"vtkFloatingPointType" return(DOUBLE); +"vtkIdType" return(IdType); +"vtkStdString" return(StdString); +"vtkSetMacro" return(SetMacro); +"vtkGetMacro" return(GetMacro); +"vtkSetStringMacro" return(SetStringMacro); +"vtkGetStringMacro" return(GetStringMacro); +"vtkSetClampMacro" return(SetClampMacro); +"vtkSetObjectMacro" return(SetObjectMacro); +"vtkSetReferenceCountedObjectMacro" return(SetReferenceCountedObjectMacro); +"vtkGetObjectMacro" return(GetObjectMacro); +"vtkBooleanMacro" return(BooleanMacro); +"vtkSetVector2Macro" return(SetVector2Macro); +"vtkSetVector3Macro" return(SetVector3Macro); +"vtkSetVector4Macro" return(SetVector4Macro); +"vtkSetVector6Macro" return(SetVector6Macro); +"vtkGetVector2Macro" return(GetVector2Macro); +"vtkGetVector3Macro" return(GetVector3Macro); +"vtkGetVector4Macro" return(GetVector4Macro); +"vtkGetVector6Macro" return(GetVector6Macro); +"vtkSetVectorMacro" return(SetVectorMacro); +"vtkGetVectorMacro" return(GetVectorMacro); +"vtkViewportCoordinateMacro" return(ViewportCoordinateMacro); +"vtkWorldCoordinateMacro" return(WorldCoordinateMacro); +"vtkTypeMacro" return(TypeMacro); +"vtkTypeRevisionMacro" return(TypeMacro); +"VTK_LEGACY" return(VTK_LEGACY); + +[0-9]+ { sscanf(yytext,"%d",&yylval.integer); return(NUM);} + +\"[^\"]+\" { + yylval.str = vtkstrdup(yytext + 1); + yylval.str[strlen(yytext)-2] = '\0'; + return(STRING); + } + +^"#"[^\n]*$ ; + + +"vtk"[0-9a-zA-Z_]* { yylval.str = (char *)malloc(yyleng + 1); + memcpy(yylval.str,yytext,yyleng); + yylval.str[yyleng] = '\0'; + return(VTK_ID); + } + +[a-zA-Z_][0-9a-zA-Z_]* { yylval.str = (char *)malloc(yyleng + 1); + memcpy(yylval.str,yytext,yyleng); + yylval.str[yyleng] = '\0'; + return(ID); + } + +[\t\n\r ] ; + + +"[" return(yytext[0]); +"]" return(yytext[0]); + + +[~{}():;*=,&.\-] { return(yytext[0]); } + +. return(OTHER); +%% + diff --git a/Wrapping/vtkParse.tab.c b/Wrapping/vtkParse.tab.c new file mode 100644 index 0000000..0db3df5 --- /dev/null +++ b/Wrapping/vtkParse.tab.c @@ -0,0 +1,3153 @@ +/* A Bison parser, made by GNU Bison 1.875d. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + CLASS = 258, + PUBLIC = 259, + PRIVATE = 260, + PROTECTED = 261, + VIRTUAL = 262, + STRING = 263, + NUM = 264, + ID = 265, + INT = 266, + FLOAT = 267, + SHORT = 268, + LONG = 269, + LONG_LONG = 270, + INT64__ = 271, + DOUBLE = 272, + VOID = 273, + CHAR = 274, + SIGNED_CHAR = 275, + CLASS_REF = 276, + OTHER = 277, + CONST = 278, + OPERATOR = 279, + UNSIGNED = 280, + FRIEND = 281, + VTK_ID = 282, + STATIC = 283, + VAR_FUNCTION = 284, + ARRAY_NUM = 285, + VTK_LEGACY = 286, + IdType = 287, + StdString = 288, + SetMacro = 289, + GetMacro = 290, + SetStringMacro = 291, + GetStringMacro = 292, + SetClampMacro = 293, + SetObjectMacro = 294, + SetReferenceCountedObjectMacro = 295, + GetObjectMacro = 296, + BooleanMacro = 297, + SetVector2Macro = 298, + SetVector3Macro = 299, + SetVector4Macro = 300, + SetVector6Macro = 301, + GetVector2Macro = 302, + GetVector3Macro = 303, + GetVector4Macro = 304, + GetVector6Macro = 305, + SetVectorMacro = 306, + GetVectorMacro = 307, + ViewportCoordinateMacro = 308, + WorldCoordinateMacro = 309, + TypeMacro = 310 + }; +#endif +#define CLASS 258 +#define PUBLIC 259 +#define PRIVATE 260 +#define PROTECTED 261 +#define VIRTUAL 262 +#define STRING 263 +#define NUM 264 +#define ID 265 +#define INT 266 +#define FLOAT 267 +#define SHORT 268 +#define LONG 269 +#define LONG_LONG 270 +#define INT64__ 271 +#define DOUBLE 272 +#define VOID 273 +#define CHAR 274 +#define SIGNED_CHAR 275 +#define CLASS_REF 276 +#define OTHER 277 +#define CONST 278 +#define OPERATOR 279 +#define UNSIGNED 280 +#define FRIEND 281 +#define VTK_ID 282 +#define STATIC 283 +#define VAR_FUNCTION 284 +#define ARRAY_NUM 285 +#define VTK_LEGACY 286 +#define IdType 287 +#define StdString 288 +#define SetMacro 289 +#define GetMacro 290 +#define SetStringMacro 291 +#define GetStringMacro 292 +#define SetClampMacro 293 +#define SetObjectMacro 294 +#define SetReferenceCountedObjectMacro 295 +#define GetObjectMacro 296 +#define BooleanMacro 297 +#define SetVector2Macro 298 +#define SetVector3Macro 299 +#define SetVector4Macro 300 +#define SetVector6Macro 301 +#define GetVector2Macro 302 +#define GetVector3Macro 303 +#define GetVector4Macro 304 +#define GetVector6Macro 305 +#define SetVectorMacro 306 +#define GetVectorMacro 307 +#define ViewportCoordinateMacro 308 +#define WorldCoordinateMacro 309 +#define TypeMacro 310 + + + + +/* Copy the first part of user declarations. */ +#line 15 "vtkParse.y" + + +/* + +This file must be translated to C and modified to build everywhere. + +Run yacc like this: + + yacc -b vtkParse vtkParse.y + +Modify vtkParse.tab.c: + - remove TABs + - comment out yyerrorlab stuff + +*/ + +#include +#include +#include +#define yyerror(a) fprintf(stderr,"%s\n",a) +#define yywrap() 1 + +static void vtkParseDebug(const char* s1, const char* s2); + +/* MSVC Does not define __STDC__ properly. */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 && !defined(__STDC__) +# define __STDC__ 1 +#endif + +/* Disable warnings in generated code. */ +#if defined(_MSC_VER) +# pragma warning (disable: 4127) /* conditional expression is constant */ +# pragma warning (disable: 4244) /* conversion to smaller integer type */ +#endif + +int yylex(void); +void output_function(); + +/* vtkstrdup is not part of POSIX so we create our own */ +char *vtkstrdup(const char *in) +{ + char *res = malloc(strlen(in)+1); + strcpy(res,in); + return res; +} + +#include "vtkParse.h" + + FileInfo data; + FunctionInfo *currentFunction; + + FILE *fhint; + char temps[2048]; + int in_public; + int in_protected; + int HaveComment; + char CommentText[50000]; + int CommentState; + int openSig; + int invertSig; + unsigned int sigAllocatedLength; + +#define YYMAXDEPTH 1000 + + void checkSigSize(char *arg) + { + if (strlen(currentFunction->Signature) + strlen(arg) + 3 > + sigAllocatedLength) + { + currentFunction->Signature = (char *) + realloc(currentFunction->Signature, sigAllocatedLength*2); + sigAllocatedLength = sigAllocatedLength*2; + } + } + void preSig(char *arg) + { + if (!currentFunction->Signature) + { + currentFunction->Signature = (char*)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s",arg); + } + else if (openSig) + { + char *tmp; + checkSigSize(arg); + tmp = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s%s",arg,tmp); + free(tmp); + } + } + void postSig(char *arg) + { + if (!currentFunction->Signature) + { + currentFunction->Signature = (char*)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s",arg); + } + else if (openSig) + { + char *tmp; + checkSigSize(arg); + tmp = vtkstrdup(currentFunction->Signature); + if (invertSig) + { + sprintf(currentFunction->Signature,"%s%s",arg,tmp); + } + else + { + sprintf(currentFunction->Signature,"%s%s",tmp,arg); + } + free(tmp); + } + } + void delSig(void) + { + if (currentFunction->Signature) + { + free(currentFunction->Signature); + currentFunction->Signature = NULL; + } + } + void legacySig(void) + { + currentFunction->IsLegacy = 1; + } + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 144 "vtkParse.y" +typedef union YYSTYPE { + char *str; + int integer; + } YYSTYPE; +/* Line 191 of yacc.c. */ +#line 320 "vtkParse.tab.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 214 of yacc.c. */ +#line 332 "vtkParse.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# endif +# else +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short int yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short int yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 50 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 626 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 71 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 74 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 183 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 355 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 310 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 67, 2, + 60, 61, 68, 2, 64, 69, 70, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 58, 59, + 2, 63, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 65, 2, 66, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 56, 2, 57, 62, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short int yyprhs[] = +{ + 0, 0, 3, 7, 8, 16, 18, 21, 24, 26, + 28, 31, 34, 38, 41, 44, 46, 51, 54, 58, + 60, 63, 67, 72, 76, 79, 81, 84, 88, 93, + 97, 100, 104, 105, 106, 111, 115, 116, 118, 119, + 125, 127, 129, 131, 133, 135, 140, 144, 148, 149, + 151, 153, 154, 159, 161, 162, 167, 169, 170, 173, + 177, 180, 183, 184, 185, 189, 194, 197, 199, 202, + 206, 208, 211, 213, 215, 218, 221, 223, 225, 227, + 230, 233, 234, 238, 240, 242, 244, 246, 248, 250, + 252, 254, 256, 258, 260, 262, 264, 266, 267, 270, + 273, 274, 280, 282, 284, 286, 289, 291, 293, 297, + 299, 300, 308, 309, 310, 319, 320, 326, 327, 333, + 334, 335, 346, 347, 355, 356, 364, 365, 366, 375, + 376, 384, 385, 393, 394, 402, 403, 411, 412, 420, + 421, 429, 430, 438, 439, 447, 448, 456, 457, 467, + 468, 478, 483, 488, 495, 496, 499, 500, 503, 505, + 507, 509, 511, 513, 515, 517, 519, 521, 523, 525, + 527, 529, 531, 533, 535, 537, 539, 541, 543, 545, + 547, 549, 553, 557 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const short int yyrhs[] = +{ + 72, 0, -1, 138, 73, 138, -1, -1, 3, 27, + 74, 109, 56, 75, 57, -1, 76, -1, 76, 75, + -1, 112, 58, -1, 97, -1, 79, -1, 26, 79, + -1, 78, 90, -1, 26, 78, 90, -1, 77, 90, + -1, 115, 59, -1, 115, -1, 31, 60, 78, 61, + -1, 62, 81, -1, 7, 62, 81, -1, 81, -1, + 101, 81, -1, 101, 23, 81, -1, 7, 101, 23, + 81, -1, 7, 101, 81, -1, 7, 81, -1, 80, + -1, 101, 80, -1, 101, 23, 80, -1, 7, 101, + 23, 80, -1, 7, 101, 80, -1, 7, 80, -1, + 24, 139, 59, -1, -1, -1, 85, 82, 84, 83, + -1, 85, 63, 9, -1, -1, 23, -1, -1, 89, + 60, 86, 91, 61, -1, 23, -1, 28, -1, 27, + -1, 10, -1, 59, -1, 56, 138, 57, 59, -1, + 56, 138, 57, -1, 58, 139, 59, -1, -1, 92, + -1, 94, -1, -1, 94, 93, 64, 92, -1, 101, + -1, -1, 101, 98, 95, 96, -1, 29, -1, -1, + 63, 113, -1, 101, 98, 59, -1, 29, 59, -1, + 89, 99, -1, -1, -1, 30, 100, 99, -1, 65, + 139, 66, 99, -1, 87, 102, -1, 102, -1, 88, + 102, -1, 88, 87, 102, -1, 106, -1, 106, 105, + -1, 103, -1, 104, -1, 104, 67, -1, 104, 68, + -1, 33, -1, 67, -1, 68, -1, 67, 105, -1, + 68, 105, -1, -1, 25, 107, 108, -1, 108, -1, + 12, -1, 18, -1, 19, -1, 11, -1, 13, -1, + 14, -1, 17, -1, 10, -1, 27, -1, 32, -1, + 15, -1, 16, -1, 20, -1, -1, 58, 110, -1, + 112, 27, -1, -1, 112, 27, 111, 64, 110, -1, + 4, -1, 5, -1, 6, -1, 69, 114, -1, 114, + -1, 9, -1, 9, 70, 9, -1, 89, -1, -1, + 34, 60, 89, 64, 116, 106, 61, -1, -1, -1, + 35, 60, 117, 89, 64, 118, 106, 61, -1, -1, + 36, 60, 119, 89, 61, -1, -1, 37, 60, 120, + 89, 61, -1, -1, -1, 38, 60, 89, 64, 121, + 106, 122, 64, 139, 61, -1, -1, 39, 60, 89, + 64, 123, 106, 61, -1, -1, 40, 60, 89, 64, + 124, 106, 61, -1, -1, -1, 41, 60, 125, 89, + 64, 126, 106, 61, -1, -1, 42, 60, 89, 127, + 64, 106, 61, -1, -1, 43, 60, 89, 64, 128, + 106, 61, -1, -1, 47, 60, 89, 64, 129, 106, + 61, -1, -1, 44, 60, 89, 64, 130, 106, 61, + -1, -1, 48, 60, 89, 64, 131, 106, 61, -1, + -1, 45, 60, 89, 64, 132, 106, 61, -1, -1, + 49, 60, 89, 64, 133, 106, 61, -1, -1, 46, + 60, 89, 64, 134, 106, 61, -1, -1, 50, 60, + 89, 64, 135, 106, 61, -1, -1, 51, 60, 89, + 64, 136, 106, 64, 113, 61, -1, -1, 52, 60, + 89, 64, 137, 106, 64, 113, 61, -1, 53, 60, + 89, 61, -1, 54, 60, 89, 61, -1, 55, 60, + 89, 64, 89, 61, -1, -1, 140, 138, -1, -1, + 141, 139, -1, 59, -1, 141, -1, 22, -1, 142, + -1, 143, -1, 68, -1, 63, -1, 58, -1, 64, + -1, 70, -1, 8, -1, 106, -1, 104, -1, 9, + -1, 21, -1, 67, -1, 144, -1, 23, -1, 24, + -1, 69, -1, 62, -1, 28, -1, 30, -1, 56, + 138, 57, -1, 60, 138, 61, -1, 65, 138, 66, + -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short int yyrline[] = +{ + 0, 209, 209, 212, 211, 217, 217, 219, 219, 220, + 221, 222, 223, 224, 225, 226, 228, 230, 231, 232, + 233, 237, 241, 246, 251, 257, 261, 266, 271, 277, + 283, 289, 295, 295, 295, 301, 310, 310, 312, 312, + 314, 316, 318, 318, 320, 321, 322, 323, 325, 325, + 327, 328, 328, 330, 336, 335, 342, 349, 349, 351, + 351, 353, 361, 362, 362, 365, 368, 369, 370, 371, + 373, 374, 376, 378, 379, 380, 382, 392, 393, 394, + 395, 397, 397, 399, 402, 403, 404, 405, 406, 407, + 408, 409, 414, 431, 432, 433, 434, 436, 436, 438, + 444, 443, 449, 450, 451, 453, 453, 455, 456, 456, + 460, 459, 471, 471, 471, 480, 480, 491, 491, 501, + 502, 500, 533, 532, 545, 544, 556, 557, 556, 566, + 565, 583, 582, 613, 612, 630, 629, 662, 661, 679, + 678, 713, 712, 730, 729, 768, 767, 785, 784, 803, + 802, 819, 866, 915, 971, 971, 972, 972, 974, 974, + 976, 976, 976, 976, 976, 976, 976, 976, 977, 977, + 977, 977, 977, 977, 977, 978, 978, 978, 978, 978, + 978, 980, 981, 982 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "CLASS", "PUBLIC", "PRIVATE", + "PROTECTED", "VIRTUAL", "STRING", "NUM", "ID", "INT", "FLOAT", "SHORT", + "LONG", "LONG_LONG", "INT64__", "DOUBLE", "VOID", "CHAR", "SIGNED_CHAR", + "CLASS_REF", "OTHER", "CONST", "OPERATOR", "UNSIGNED", "FRIEND", + "VTK_ID", "STATIC", "VAR_FUNCTION", "ARRAY_NUM", "VTK_LEGACY", "IdType", + "StdString", "SetMacro", "GetMacro", "SetStringMacro", "GetStringMacro", + "SetClampMacro", "SetObjectMacro", "SetReferenceCountedObjectMacro", + "GetObjectMacro", "BooleanMacro", "SetVector2Macro", "SetVector3Macro", + "SetVector4Macro", "SetVector6Macro", "GetVector2Macro", + "GetVector3Macro", "GetVector4Macro", "GetVector6Macro", + "SetVectorMacro", "GetVectorMacro", "ViewportCoordinateMacro", + "WorldCoordinateMacro", "TypeMacro", "'{'", "'}'", "':'", "';'", "'('", + "')'", "'~'", "'='", "','", "'['", "']'", "'&'", "'*'", "'-'", "'.'", + "$accept", "strt", "class_def", "@1", "class_def_body", "class_def_item", + "legacy_function", "function", "operator", "operator_sig", "func", "@2", + "@3", "maybe_const", "func_sig", "@4", "const_mod", "static_mod", + "any_id", "func_body", "args_list", "more_args", "@5", "arg", "@6", + "opt_var_assign", "var", "var_id", "var_array", "@7", "type", + "type_red1", "type_string1", "type_string2", "type_indirection", + "type_red2", "@8", "type_primitive", "optional_scope", "scope_list", + "@9", "scope_type", "float_num", "float_prim", "macro", "@10", "@11", + "@12", "@13", "@14", "@15", "@16", "@17", "@18", "@19", "@20", "@21", + "@22", "@23", "@24", "@25", "@26", "@27", "@28", "@29", "@30", "@31", + "maybe_other", "maybe_other_no_semi", "other_stuff", + "other_stuff_no_semi", "braces", "parens", "brackets", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short int yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 123, 125, 58, 59, + 40, 41, 126, 61, 44, 91, 93, 38, 42, 45, + 46 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 71, 72, 74, 73, 75, 75, 76, 76, 76, + 76, 76, 76, 76, 76, 76, 77, 78, 78, 78, + 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, + 79, 80, 82, 83, 81, 81, 84, 84, 86, 85, + 87, 88, 89, 89, 90, 90, 90, 90, 91, 91, + 92, 93, 92, 94, 95, 94, 94, 96, 96, 97, + 97, 98, 99, 100, 99, 99, 101, 101, 101, 101, + 102, 102, 102, 103, 103, 103, 104, 105, 105, 105, + 105, 107, 106, 106, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 109, 109, 110, + 111, 110, 112, 112, 112, 113, 113, 114, 114, 114, + 116, 115, 117, 118, 115, 119, 115, 120, 115, 121, + 122, 115, 123, 115, 124, 115, 125, 126, 115, 127, + 115, 128, 115, 129, 115, 130, 115, 131, 115, 132, + 115, 133, 115, 134, 115, 135, 115, 136, 115, 137, + 115, 115, 115, 115, 138, 138, 139, 139, 140, 140, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 142, 143, 144 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 3, 0, 7, 1, 2, 2, 1, 1, + 2, 2, 3, 2, 2, 1, 4, 2, 3, 1, + 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, + 2, 3, 0, 0, 4, 3, 0, 1, 0, 5, + 1, 1, 1, 1, 1, 4, 3, 3, 0, 1, + 1, 0, 4, 1, 0, 4, 1, 0, 2, 3, + 2, 2, 0, 0, 3, 4, 2, 1, 2, 3, + 1, 2, 1, 1, 2, 2, 1, 1, 1, 2, + 2, 0, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, + 0, 5, 1, 1, 1, 2, 1, 1, 3, 1, + 0, 7, 0, 0, 8, 0, 5, 0, 5, 0, + 0, 10, 0, 7, 0, 7, 0, 0, 8, 0, + 7, 0, 7, 0, 7, 0, 7, 0, 7, 0, + 7, 0, 7, 0, 7, 0, 7, 0, 9, 0, + 9, 4, 4, 6, 0, 2, 0, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 3, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 154, 168, 171, 91, 87, 84, 88, 89, 94, 95, + 90, 85, 86, 96, 172, 160, 175, 176, 81, 92, + 179, 180, 93, 76, 154, 165, 158, 154, 178, 164, + 166, 154, 173, 163, 177, 167, 0, 170, 169, 83, + 0, 154, 159, 161, 162, 174, 0, 0, 0, 0, + 1, 0, 154, 155, 82, 181, 182, 183, 3, 2, + 97, 0, 0, 102, 103, 104, 98, 0, 0, 99, + 0, 91, 40, 156, 0, 92, 41, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 9, 25, 19, 32, + 0, 0, 0, 8, 0, 67, 72, 73, 70, 0, + 15, 0, 0, 30, 24, 0, 0, 156, 0, 10, + 0, 60, 0, 0, 112, 115, 117, 0, 0, 0, + 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 43, 42, 17, 4, 6, + 154, 156, 44, 13, 11, 0, 36, 66, 0, 68, + 38, 0, 26, 20, 62, 0, 74, 75, 77, 78, + 71, 7, 14, 0, 18, 0, 29, 23, 31, 157, + 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 35, 37, + 33, 69, 48, 27, 21, 63, 156, 61, 59, 79, + 80, 101, 28, 22, 0, 16, 0, 110, 0, 0, + 0, 119, 122, 124, 0, 0, 131, 135, 139, 143, + 133, 137, 141, 145, 147, 149, 151, 152, 0, 46, + 47, 34, 56, 0, 49, 50, 53, 62, 0, 0, + 0, 113, 116, 118, 0, 0, 0, 127, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 45, 39, 0, 62, 54, 64, 62, 0, 0, 120, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 153, 0, 57, 65, 111, 0, + 0, 123, 125, 0, 130, 132, 136, 140, 144, 134, + 138, 142, 146, 0, 0, 52, 0, 55, 114, 156, + 128, 107, 0, 109, 0, 106, 0, 58, 0, 0, + 105, 148, 150, 121, 108 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short int yydefgoto[] = +{ + -1, 36, 52, 60, 102, 103, 104, 105, 106, 107, + 108, 166, 261, 220, 109, 222, 110, 111, 112, 163, + 263, 264, 292, 265, 316, 337, 113, 175, 227, 267, + 114, 115, 116, 37, 180, 38, 46, 39, 62, 66, + 121, 67, 344, 345, 120, 270, 195, 298, 196, 197, + 274, 320, 275, 276, 201, 302, 245, 279, 283, 280, + 284, 281, 285, 282, 286, 287, 288, 40, 126, 41, + 42, 43, 44, 45 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -254 +static const short int yypact[] = +{ + 276, -254, -254, -254, -254, -254, -254, -254, -254, -254, + -254, -254, -254, -254, -254, -254, -254, -254, -254, -254, + -254, -254, -254, -254, 276, -254, -254, 276, -254, -254, + -254, 276, -254, -254, -254, -254, 27, -254, -254, -254, + 37, 276, -254, -254, -254, -254, 364, 21, 29, 16, + -254, 59, 276, -254, -254, -254, -254, -254, -254, -254, + 31, 53, 39, -254, -254, -254, -254, 69, 406, 34, + 514, 40, -254, 339, 459, 42, -254, 44, 47, 48, + 51, 54, 55, 58, 60, 62, 63, 65, 75, 91, + 92, 94, 96, 99, 100, 101, 103, 115, 118, 120, + 123, 28, 49, 406, -30, -30, -254, -254, -254, 36, + 593, 154, 125, -254, 46, -254, -254, -34, -4, 61, + 71, 124, 28, -254, -254, 70, 130, 339, -30, -254, + 46, -254, 483, 28, -254, -254, -254, 28, 28, 28, + -254, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, -254, -254, -254, -254, -254, + 276, 339, -254, -254, -254, 184, 89, -254, 593, -254, + -254, 25, -254, -254, -28, 135, -254, -254, -4, -4, + -254, -254, -254, 53, -254, 25, -254, -254, -254, -254, + -254, 538, 68, 52, 131, 28, 28, 28, 133, 134, + 136, 28, -254, 137, 138, 140, 141, 142, 146, 158, + 160, 162, 164, 168, 169, 170, 175, 174, -254, -254, + -254, -254, 569, -254, -254, -254, 339, -254, -254, -254, + -254, -254, -254, -254, 64, -254, 28, -254, 172, 188, + 194, -254, -254, -254, 192, 193, -254, -254, -254, -254, + -254, -254, -254, -254, -254, -254, -254, -254, 28, 199, + -254, -254, -254, 201, -254, 200, 28, -15, 197, 28, + 227, -254, -254, -254, 227, 227, 227, -254, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 227, 227, 204, + -254, -254, 203, -15, -254, -254, -15, 207, 227, -254, + 208, 209, 227, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 238, -254, 569, 242, -254, -254, 220, + 243, -254, -254, 221, -254, -254, -254, -254, -254, -254, + -254, -254, -254, 3, 3, -254, 3, -254, -254, 339, + -254, 129, 14, -254, 249, -254, 250, -254, 251, 271, + -254, -254, -254, -254, -254 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const short int yypgoto[] = +{ + -254, -254, -254, -254, 222, -254, -254, -66, 239, -54, + -9, -254, -254, -254, -254, -254, 205, -254, -5, -80, + -254, -1, -254, -254, -254, -254, -254, 56, -245, -254, + -65, -91, -254, -64, -94, -67, -254, 269, -254, 143, + -254, -50, -253, -25, -254, -254, -254, -254, -254, -254, + -254, -254, -254, -254, -254, -254, -254, -254, -254, -254, + -254, -254, -254, -254, -254, -254, -254, -10, -116, -254, + -73, -254, -254, -254 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -101 +static const short int yytable[] = +{ + 127, 118, 225, 118, 117, 125, 117, 118, 128, 130, + 117, 189, 341, 155, 47, 225, 123, 48, 119, 167, + 169, 49, 295, 341, 155, 164, 160, 50, 161, 162, + 156, 53, 170, 176, 177, 155, 118, 226, 155, 117, + 51, 156, 59, 118, 118, 217, 117, 117, 190, 73, + 226, 317, 156, 119, 127, 156, 155, 63, 64, 65, + 172, 124, 155, 178, 179, 118, 192, 193, 117, 171, + 73, 186, 342, 156, 155, 236, 172, 221, 55, 156, + 155, 346, 57, 347, 229, 230, 58, 269, 127, 61, + 56, 156, 157, 185, 73, 68, 69, 156, -100, 165, + -43, 118, -42, 131, 117, 173, 158, 132, 133, 174, + 268, 134, 219, 184, 135, 136, 187, 223, 137, 181, + 138, 173, 139, 140, 118, 141, 234, 117, 194, 235, + 182, 232, 198, 199, 200, 142, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 143, 144, 127, 145, 118, 146, 266, 117, 147, + 148, 149, 224, 150, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 151, 233, 72, 152, 18, + 153, 19, 124, 154, 173, 170, 22, 23, 183, 188, + 238, 239, 240, 218, 228, 237, 244, 241, 242, 349, + 243, 246, 247, 297, 248, 249, 250, 299, 300, 301, + 251, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 252, 348, 253, 187, 254, 224, 255, 256, + 257, 319, 259, 260, 258, 323, 271, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 118, 272, + 266, 117, 18, 289, 19, 273, 277, 278, 290, 22, + 233, 293, 291, 296, -51, 314, 127, 315, 318, 321, + 322, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 354, 338, 340, 333, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 334, 19, 20, 336, 21, 339, 22, 23, + 351, 352, 353, 129, 335, 54, 168, 350, 0, 0, + 0, 0, 294, 0, 0, 159, 231, 0, 343, 343, + 0, 343, 24, 0, 25, 26, 27, 343, 28, 29, + 30, 31, 0, 32, 33, 34, 35, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 0, 19, 20, 0, 21, + 0, 22, 23, 0, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, + 0, 19, 0, 0, 0, 24, 22, 25, 0, 27, + 0, 28, 29, 30, 31, 0, 32, 33, 34, 35, + 63, 64, 65, 70, 0, 0, 71, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 0, 0, 72, + 73, 18, 74, 75, 76, 77, 0, 78, 22, 23, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 0, 0, 0, 0, 70, 0, 101, 71, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 0, 0, 72, 73, 18, 0, 75, 76, 0, 0, + 191, 22, 23, 71, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 0, 0, 72, 0, 18, 0, + 75, 76, 0, 0, 0, 22, 23, 0, 0, 0, + 0, 101, 0, 0, 71, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 0, 0, 72, 73, 18, + 0, 75, 76, 0, 0, 101, 22, 23, 71, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, + 0, 72, 0, 18, 0, 75, 76, 0, 0, 0, + 22, 23, 0, 0, 0, 0, 122, 0, 0, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 0, 0, 72, 0, 18, 0, 19, 76, 262, 0, + 122, 22, 23, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 0, 0, 0, 0, 18, 0, + 19, 0, 0, 0, 0, 22, 23 +}; + +static const short int yycheck[] = +{ + 73, 68, 30, 70, 68, 70, 70, 74, 74, 74, + 74, 127, 9, 10, 24, 30, 70, 27, 68, 110, + 111, 31, 267, 9, 10, 105, 56, 0, 58, 59, + 27, 41, 60, 67, 68, 10, 103, 65, 10, 103, + 3, 27, 52, 110, 111, 161, 110, 111, 128, 24, + 65, 296, 27, 103, 127, 27, 10, 4, 5, 6, + 114, 70, 10, 67, 68, 132, 132, 132, 132, 23, + 24, 125, 69, 27, 10, 23, 130, 168, 57, 27, + 10, 334, 66, 336, 178, 179, 27, 23, 161, 58, + 61, 27, 101, 23, 24, 56, 27, 27, 64, 63, + 60, 168, 60, 59, 168, 114, 57, 60, 60, 114, + 226, 60, 23, 122, 60, 60, 125, 171, 60, 58, + 60, 130, 60, 60, 191, 60, 191, 191, 133, 61, + 59, 185, 137, 138, 139, 60, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 160, 60, 60, 226, 60, 222, 60, 222, 222, 60, + 60, 60, 171, 60, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 60, 185, 23, 60, 25, + 60, 27, 191, 60, 193, 60, 32, 33, 64, 59, + 195, 196, 197, 9, 59, 64, 201, 64, 64, 70, + 64, 64, 64, 270, 64, 64, 64, 274, 275, 276, + 64, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 64, 339, 64, 234, 64, 236, 64, 61, + 61, 298, 57, 59, 64, 302, 64, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 315, 61, + 315, 315, 25, 258, 27, 61, 64, 64, 59, 32, + 269, 266, 61, 66, 64, 61, 339, 64, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 9, 61, 61, 64, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 64, 27, 28, 63, 30, 64, 32, 33, + 61, 61, 61, 74, 315, 46, 111, 342, -1, -1, + -1, -1, 266, -1, -1, 103, 183, -1, 333, 334, + -1, 336, 56, -1, 58, 59, 60, 342, 62, 63, + 64, 65, -1, 67, 68, 69, 70, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, -1, 27, 28, -1, 30, + -1, 32, 33, -1, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, -1, -1, -1, -1, -1, + -1, 27, -1, -1, -1, 56, 32, 58, -1, 60, + -1, 62, 63, 64, 65, -1, 67, 68, 69, 70, + 4, 5, 6, 7, -1, -1, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, -1, -1, 23, + 24, 25, 26, 27, 28, 29, -1, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, -1, -1, -1, -1, 7, -1, 62, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + -1, -1, 23, 24, 25, -1, 27, 28, -1, -1, + 7, 32, 33, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, -1, -1, 23, -1, 25, -1, + 27, 28, -1, -1, -1, 32, 33, -1, -1, -1, + -1, 62, -1, -1, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, -1, -1, 23, 24, 25, + -1, 27, 28, -1, -1, 62, 32, 33, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, -1, + -1, 23, -1, 25, -1, 27, 28, -1, -1, -1, + 32, 33, -1, -1, -1, -1, 62, -1, -1, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + -1, -1, 23, -1, 25, -1, 27, 28, 29, -1, + 62, 32, 33, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, -1, -1, -1, -1, 25, -1, + 27, -1, -1, -1, -1, 32, 33 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, + 28, 30, 32, 33, 56, 58, 59, 60, 62, 63, + 64, 65, 67, 68, 69, 70, 72, 104, 106, 108, + 138, 140, 141, 142, 143, 144, 107, 138, 138, 138, + 0, 3, 73, 138, 108, 57, 61, 66, 27, 138, + 74, 58, 109, 4, 5, 6, 110, 112, 56, 27, + 7, 10, 23, 24, 26, 27, 28, 29, 31, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 62, 75, 76, 77, 78, 79, 80, 81, 85, + 87, 88, 89, 97, 101, 102, 103, 104, 106, 112, + 115, 111, 62, 80, 81, 101, 139, 141, 78, 79, + 101, 59, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 10, 27, 81, 57, 75, + 56, 58, 59, 90, 90, 63, 82, 102, 87, 102, + 60, 23, 80, 81, 89, 98, 67, 68, 67, 68, + 105, 58, 59, 64, 81, 23, 80, 81, 59, 139, + 90, 7, 78, 101, 89, 117, 119, 120, 89, 89, + 89, 125, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 138, 139, 9, 23, + 84, 102, 86, 80, 81, 30, 65, 99, 59, 105, + 105, 110, 80, 81, 101, 61, 23, 64, 89, 89, + 89, 64, 64, 64, 89, 127, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 61, 61, 64, 57, + 59, 83, 29, 91, 92, 94, 101, 100, 139, 23, + 116, 64, 61, 61, 121, 123, 124, 64, 64, 128, + 130, 132, 134, 129, 131, 133, 135, 136, 137, 89, + 59, 61, 93, 89, 98, 99, 66, 106, 118, 106, + 106, 106, 126, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 61, 64, 95, 99, 61, 106, + 122, 61, 61, 106, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 64, 64, 92, 63, 96, 61, 64, + 61, 9, 69, 89, 113, 114, 113, 113, 139, 70, + 114, 61, 61, 61, 9 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + ((Current).first_line = (Rhs)[1].first_line, \ + (Current).first_column = (Rhs)[1].first_column, \ + (Current).last_line = (Rhs)[N].last_line, \ + (Current).last_column = (Rhs)[N].last_column) +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short int *bottom, short int *top) +#else +static void +yy_stack_print (bottom, top) + short int *bottom; + short int *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + register short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short int *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 3: +#line 212 "vtkParse.y" + { + data.ClassName = vtkstrdup(yyvsp[0].str); + } + break; + + case 11: +#line 222 "vtkParse.y" + { output_function(); } + break; + + case 12: +#line 223 "vtkParse.y" + { output_function(); } + break; + + case 13: +#line 224 "vtkParse.y" + { legacySig(); output_function(); } + break; + + case 17: +#line 230 "vtkParse.y" + { preSig("~"); } + break; + + case 18: +#line 231 "vtkParse.y" + { preSig("virtual ~"); } + break; + + case 20: +#line 234 "vtkParse.y" + { + currentFunction->ReturnType = yyvsp[-1].integer; + } + break; + + case 21: +#line 238 "vtkParse.y" + { + currentFunction->ReturnType = yyvsp[-2].integer; + } + break; + + case 22: +#line 242 "vtkParse.y" + { + preSig("virtual "); + currentFunction->ReturnType = yyvsp[-2].integer; + } + break; + + case 23: +#line 247 "vtkParse.y" + { + preSig("virtual "); + currentFunction->ReturnType = yyvsp[-1].integer; + } + break; + + case 24: +#line 252 "vtkParse.y" + { + preSig("virtual "); + } + break; + + case 25: +#line 258 "vtkParse.y" + { + output_function(); + } + break; + + case 26: +#line 262 "vtkParse.y" + { + currentFunction->ReturnType = yyvsp[-1].integer; + output_function(); + } + break; + + case 27: +#line 267 "vtkParse.y" + { + currentFunction->ReturnType = yyvsp[-2].integer; + output_function(); + } + break; + + case 28: +#line 272 "vtkParse.y" + { + preSig("virtual "); + currentFunction->ReturnType = yyvsp[-2].integer; + output_function(); + } + break; + + case 29: +#line 278 "vtkParse.y" + { + preSig("virtual "); + currentFunction->ReturnType = yyvsp[-1].integer; + output_function(); + } + break; + + case 30: +#line 284 "vtkParse.y" + { + preSig("virtual "); + output_function(); + } + break; + + case 31: +#line 290 "vtkParse.y" + { + currentFunction->IsOperator = 1; + vtkParseDebug("Converted operator", 0); + } + break; + + case 32: +#line 295 "vtkParse.y" + { postSig(")"); } + break; + + case 33: +#line 295 "vtkParse.y" + { postSig(";"); openSig = 0; } + break; + + case 34: +#line 296 "vtkParse.y" + { + openSig = 1; + currentFunction->Name = yyvsp[-3].str; + vtkParseDebug("Parsed func", yyvsp[-3].str); + } + break; + + case 35: +#line 302 "vtkParse.y" + { + postSig(") = 0;"); + currentFunction->Name = yyvsp[-2].str; + vtkParseDebug("Parsed func", yyvsp[-2].str); + currentFunction->IsPureVirtual = 1; + data.IsAbstract = 1; + } + break; + + case 37: +#line 310 "vtkParse.y" + {postSig(" const");} + break; + + case 38: +#line 312 "vtkParse.y" + {postSig(" ("); } + break; + + case 40: +#line 314 "vtkParse.y" + {postSig("const ");} + break; + + case 41: +#line 316 "vtkParse.y" + {postSig("static ");} + break; + + case 42: +#line 318 "vtkParse.y" + {postSig(yyvsp[0].str);} + break; + + case 43: +#line 318 "vtkParse.y" + {postSig(yyvsp[0].str);} + break; + + case 50: +#line 327 "vtkParse.y" + { currentFunction->NumberOfArguments++;} + break; + + case 51: +#line 328 "vtkParse.y" + { currentFunction->NumberOfArguments++; postSig(", ");} + break; + + case 53: +#line 331 "vtkParse.y" + { + currentFunction->ArgCounts[currentFunction->NumberOfArguments] = 0; + currentFunction->ArgTypes[currentFunction->NumberOfArguments] = + yyvsp[0].integer;} + break; + + case 54: +#line 336 "vtkParse.y" + { + currentFunction->ArgCounts[currentFunction->NumberOfArguments] = + yyvsp[0].integer / 0x10000; + currentFunction->ArgTypes[currentFunction->NumberOfArguments] = + yyvsp[-1].integer + yyvsp[0].integer % 0x10000; + } + break; + + case 56: +#line 343 "vtkParse.y" + { + postSig("void (*func)(void *) "); + currentFunction->ArgCounts[currentFunction->NumberOfArguments] = 0; + currentFunction->ArgTypes[currentFunction->NumberOfArguments] = 0x5000; + } + break; + + case 59: +#line 351 "vtkParse.y" + {delSig();} + break; + + case 60: +#line 351 "vtkParse.y" + {delSig();} + break; + + case 61: +#line 353 "vtkParse.y" + { yyval.integer = yyvsp[0].integer; } + break; + + case 62: +#line 361 "vtkParse.y" + { yyval.integer = 0; } + break; + + case 63: +#line 362 "vtkParse.y" + { char temp[100]; sprintf(temp,"[%i]",yyvsp[0].integer); + postSig(temp); } + break; + + case 64: +#line 364 "vtkParse.y" + { yyval.integer = 0x300 + 0x10000 * yyvsp[-2].integer + yyvsp[0].integer % 0x1000; } + break; + + case 65: +#line 366 "vtkParse.y" + { postSig("[]"); yyval.integer = 0x300 + yyvsp[0].integer % 0x1000; } + break; + + case 66: +#line 368 "vtkParse.y" + {yyval.integer = 0x1000 + yyvsp[0].integer;} + break; + + case 67: +#line 369 "vtkParse.y" + {yyval.integer = yyvsp[0].integer;} + break; + + case 68: +#line 370 "vtkParse.y" + {yyval.integer = 0x2000 + yyvsp[0].integer;} + break; + + case 69: +#line 371 "vtkParse.y" + {yyval.integer = 0x3000 + yyvsp[0].integer;} + break; + + case 70: +#line 373 "vtkParse.y" + {yyval.integer = yyvsp[0].integer;} + break; + + case 71: +#line 375 "vtkParse.y" + {yyval.integer = yyvsp[-1].integer + yyvsp[0].integer;} + break; + + case 72: +#line 376 "vtkParse.y" + {yyval.integer = yyvsp[0].integer;} + break; + + case 73: +#line 378 "vtkParse.y" + {yyval.integer = yyvsp[0].integer;} + break; + + case 74: +#line 379 "vtkParse.y" + { postSig("&"); yyval.integer = yyvsp[-1].integer;} + break; + + case 75: +#line 380 "vtkParse.y" + { postSig("*"); yyval.integer = 0x400 + yyvsp[-1].integer;} + break; + + case 76: +#line 382 "vtkParse.y" + { postSig("vtkStdString "); yyval.integer = 0x1303; } + break; + + case 77: +#line 392 "vtkParse.y" + { postSig("&"); yyval.integer = 0x100;} + break; + + case 78: +#line 393 "vtkParse.y" + { postSig("*"); yyval.integer = 0x300;} + break; + + case 79: +#line 394 "vtkParse.y" + { yyval.integer = 0x100 + yyvsp[0].integer;} + break; + + case 80: +#line 395 "vtkParse.y" + { yyval.integer = 0x400 + yyvsp[0].integer;} + break; + + case 81: +#line 397 "vtkParse.y" + {postSig("unsigned ");} + break; + + case 82: +#line 398 "vtkParse.y" + { yyval.integer = 0x10 + yyvsp[0].integer;} + break; + + case 83: +#line 399 "vtkParse.y" + { yyval.integer = yyvsp[0].integer;} + break; + + case 84: +#line 402 "vtkParse.y" + { postSig("float "); yyval.integer = 0x1;} + break; + + case 85: +#line 403 "vtkParse.y" + { postSig("void "); yyval.integer = 0x2;} + break; + + case 86: +#line 404 "vtkParse.y" + { postSig("char "); yyval.integer = 0x3;} + break; + + case 87: +#line 405 "vtkParse.y" + { postSig("int "); yyval.integer = 0x4;} + break; + + case 88: +#line 406 "vtkParse.y" + { postSig("short "); yyval.integer = 0x5;} + break; + + case 89: +#line 407 "vtkParse.y" + { postSig("long "); yyval.integer = 0x6;} + break; + + case 90: +#line 408 "vtkParse.y" + { postSig("double "); yyval.integer = 0x7;} + break; + + case 91: +#line 409 "vtkParse.y" + { + char ctmpid[2048]; + sprintf(ctmpid,"%s ",yyvsp[0].str); + postSig(ctmpid); + yyval.integer = 0x8;} + break; + + case 92: +#line 415 "vtkParse.y" + { + char ctmpid[2048]; + sprintf(ctmpid,"%s ",yyvsp[0].str); + postSig(ctmpid); + yyval.integer = 0x9; + currentFunction->ArgClasses[currentFunction->NumberOfArguments] = + vtkstrdup(yyvsp[0].str); + /* store the string into the return value just in case we need it */ + /* this is a parsing hack because the first "type" parser will */ + /* possibly be ht ereturn type of the first argument */ + if ((!currentFunction->ReturnClass) && + (!currentFunction->NumberOfArguments)) + { + currentFunction->ReturnClass = vtkstrdup(yyvsp[0].str); + } + } + break; + + case 93: +#line 431 "vtkParse.y" + { postSig("vtkIdType "); yyval.integer = 0xA;} + break; + + case 94: +#line 432 "vtkParse.y" + { postSig("long long "); yyval.integer = 0xB;} + break; + + case 95: +#line 433 "vtkParse.y" + { postSig("__int64 "); yyval.integer = 0xC;} + break; + + case 96: +#line 434 "vtkParse.y" + { postSig("signed char "); yyval.integer = 0xD;} + break; + + case 99: +#line 439 "vtkParse.y" + { + data.SuperClasses[data.NumberOfSuperClasses] = vtkstrdup(yyvsp[0].str); + data.NumberOfSuperClasses++; + } + break; + + case 100: +#line 444 "vtkParse.y" + { + data.SuperClasses[data.NumberOfSuperClasses] = vtkstrdup(yyvsp[0].str); + data.NumberOfSuperClasses++; + } + break; + + case 102: +#line 449 "vtkParse.y" + {in_public = 1; in_protected = 0;} + break; + + case 103: +#line 450 "vtkParse.y" + {in_public = 0; in_protected = 0;} + break; + + case 104: +#line 451 "vtkParse.y" + {in_public = 0; in_protected = 1;} + break; + + case 107: +#line 455 "vtkParse.y" + {yyval.integer = yyvsp[0].integer;} + break; + + case 108: +#line 456 "vtkParse.y" + {yyval.integer = -1;} + break; + + case 109: +#line 456 "vtkParse.y" + {yyval.integer = -1;} + break; + + case 110: +#line 460 "vtkParse.y" + {preSig("void Set"); postSig(" ("); } + break; + + case 111: +#line 461 "vtkParse.y" + { + postSig(");"); + sprintf(temps,"Set%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + } + break; + + case 112: +#line 471 "vtkParse.y" + {postSig("Get");} + break; + + case 113: +#line 471 "vtkParse.y" + {postSig(" ();"); invertSig = 1;} + break; + + case 114: +#line 473 "vtkParse.y" + { + sprintf(temps,"Get%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = yyvsp[-1].integer; + output_function(); + } + break; + + case 115: +#line 480 "vtkParse.y" + {preSig("void Set");} + break; + + case 116: +#line 481 "vtkParse.y" + { + postSig(" (char *);"); + sprintf(temps,"Set%s",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x303; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + } + break; + + case 117: +#line 491 "vtkParse.y" + {preSig("char *Get");} + break; + + case 118: +#line 492 "vtkParse.y" + { + postSig(" ();"); + sprintf(temps,"Get%s",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x303; + output_function(); + } + break; + + case 119: +#line 501 "vtkParse.y" + {preSig("void Set"); postSig(" ("); } + break; + + case 120: +#line 502 "vtkParse.y" + {postSig(");"); openSig = 0;} + break; + + case 121: +#line 503 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sscanf (currentFunction->Signature, "%*s %*s (%s);", local); + sprintf(temps,"Set%s",yyvsp[-7].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = yyvsp[-4].integer; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s Get%sMinValue ();",local,yyvsp[-7].str); + sprintf(temps,"Get%sMinValue",yyvsp[-7].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = yyvsp[-4].integer; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s Get%sMaxValue ();",local,yyvsp[-7].str); + sprintf(temps,"Get%sMaxValue",yyvsp[-7].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = yyvsp[-4].integer; + output_function(); + } + break; + + case 122: +#line 533 "vtkParse.y" + {preSig("void Set"); postSig(" ("); } + break; + + case 123: +#line 534 "vtkParse.y" + { + postSig("*);"); + sprintf(temps,"Set%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x309; + currentFunction->ArgCounts[0] = 1; + currentFunction->ReturnType = 0x2; + output_function(); + } + break; + + case 124: +#line 545 "vtkParse.y" + {preSig("void Set"); postSig(" ("); } + break; + + case 125: +#line 546 "vtkParse.y" + { + postSig("*);"); + sprintf(temps,"Set%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x309; + currentFunction->ArgCounts[0] = 1; + currentFunction->ReturnType = 0x2; + output_function(); + } + break; + + case 126: +#line 556 "vtkParse.y" + {postSig("*Get");} + break; + + case 127: +#line 557 "vtkParse.y" + {postSig(" ();"); invertSig = 1;} + break; + + case 128: +#line 558 "vtkParse.y" + { + sprintf(temps,"Get%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + output_function(); + } + break; + + case 129: +#line 566 "vtkParse.y" + {preSig("void "); postSig("On ();"); openSig = 0; } + break; + + case 130: +#line 568 "vtkParse.y" + { + sprintf(temps,"%sOn",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x2; + output_function(); + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void %sOff ();",yyvsp[-4].str); + sprintf(temps,"%sOff",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + output_function(); + } + break; + + case 131: +#line 583 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 132: +#line 588 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s);",yyvsp[-4].str, + local, local); + sprintf(temps,"Set%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 2; + currentFunction->ArgTypes[0] = yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = yyvsp[-1].integer; + currentFunction->ArgCounts[1] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[2]);",yyvsp[-4].str, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 0x2; + output_function(); + } + break; + + case 133: +#line 613 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 134: +#line 618 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, yyvsp[-4].str); + sprintf(temps,"Get%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + yyvsp[-1].integer; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 2; + output_function(); + } + break; + + case 135: +#line 630 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 136: +#line 635 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s, %s);", + yyvsp[-4].str, local, local, local); + sprintf(temps,"Set%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 3; + currentFunction->ArgTypes[0] = yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = yyvsp[-1].integer; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = yyvsp[-1].integer; + currentFunction->ArgCounts[2] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[3]);",yyvsp[-4].str, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 3; + output_function(); + } + break; + + case 137: +#line 662 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 138: +#line 667 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, yyvsp[-4].str); + sprintf(temps,"Get%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + yyvsp[-1].integer; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 3; + output_function(); + } + break; + + case 139: +#line 679 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 140: +#line 684 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s, %s, %s);", + yyvsp[-4].str, local, local, local, local); + sprintf(temps,"Set%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 4; + currentFunction->ArgTypes[0] = yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = yyvsp[-1].integer; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = yyvsp[-1].integer; + currentFunction->ArgCounts[2] = 0; + currentFunction->ArgTypes[3] = yyvsp[-1].integer; + currentFunction->ArgCounts[3] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[4]);",yyvsp[-4].str, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 4; + output_function(); + } + break; + + case 141: +#line 713 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 142: +#line 718 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, yyvsp[-4].str); + sprintf(temps,"Get%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + yyvsp[-1].integer; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 4; + output_function(); + } + break; + + case 143: +#line 730 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 144: +#line 735 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s, %s, %s, %s, %s);", + yyvsp[-4].str, local, local, local, local, local, local); + sprintf(temps,"Set%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 6; + currentFunction->ArgTypes[0] = yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = yyvsp[-1].integer; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = yyvsp[-1].integer; + currentFunction->ArgCounts[2] = 0; + currentFunction->ArgTypes[3] = yyvsp[-1].integer; + currentFunction->ArgCounts[3] = 0; + currentFunction->ArgTypes[4] = yyvsp[-1].integer; + currentFunction->ArgCounts[4] = 0; + currentFunction->ArgTypes[5] = yyvsp[-1].integer; + currentFunction->ArgCounts[5] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[6]);",yyvsp[-4].str, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + yyvsp[-1].integer; + currentFunction->ArgCounts[0] = 6; + output_function(); + } + break; + + case 145: +#line 768 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 146: +#line 773 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, yyvsp[-4].str); + sprintf(temps,"Get%s",yyvsp[-4].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + yyvsp[-1].integer; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 6; + output_function(); + } + break; + + case 147: +#line 785 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 148: +#line 790 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s [%i]);",yyvsp[-6].str, + local, yyvsp[-1].integer); + sprintf(temps,"Set%s",yyvsp[-6].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->ReturnType = 0x2; + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + yyvsp[-3].integer; + currentFunction->ArgCounts[0] = yyvsp[-1].integer; + output_function(); + } + break; + + case 149: +#line 803 "vtkParse.y" + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + break; + + case 150: +#line 808 "vtkParse.y" + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, yyvsp[-6].str); + sprintf(temps,"Get%s",yyvsp[-6].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + yyvsp[-3].integer; + currentFunction->HaveHint = 1; + currentFunction->HintSize = yyvsp[-1].integer; + output_function(); + } + break; + + case 151: +#line 820 "vtkParse.y" + { + sprintf(currentFunction->Signature,"vtkCoordinate *Get%sCoordinate ();", + yyvsp[-1].str); + + sprintf(temps,"Get%sCoordinate",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + currentFunction->ReturnClass = vtkstrdup("vtkCoordinate"); + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double, double);", + yyvsp[-1].str); + sprintf(temps,"Set%s",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 2; + currentFunction->ArgTypes[0] = 0x7; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = 0x7; + currentFunction->ArgCounts[1] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double a[2]);", + yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x307; + currentFunction->ArgCounts[0] = 2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"double *Get%s ();", yyvsp[-1].str); + sprintf(temps,"Get%s",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x307; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 2; + output_function(); + } + break; + + case 152: +#line 867 "vtkParse.y" + { + sprintf(currentFunction->Signature,"vtkCoordinate *Get%sCoordinate ();", + yyvsp[-1].str); + + sprintf(temps,"Get%sCoordinate",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + currentFunction->ReturnClass = vtkstrdup("vtkCoordinate"); + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double, double, double);", + yyvsp[-1].str); + sprintf(temps,"Set%s",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 3; + currentFunction->ArgTypes[0] = 0x7; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = 0x7; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = 0x7; + currentFunction->ArgCounts[2] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double a[3]);", + yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x307; + currentFunction->ArgCounts[0] = 3; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"double *Get%s ();", yyvsp[-1].str); + sprintf(temps,"Get%s",yyvsp[-1].str); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x307; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 3; + output_function(); + } + break; + + case 153: +#line 916 "vtkParse.y" + { + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, "const char *GetClassName ();"); + sprintf(temps,"GetClassName"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x1303; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, + "int IsA (const char *name);"); + sprintf(temps,"IsA"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x1303; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x4; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, "%s *NewInstance ();", + yyvsp[-3].str); + sprintf(temps,"NewInstance"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + currentFunction->ReturnClass = vtkstrdup(yyvsp[-3].str); + output_function(); + + if ( data.IsConcrete ) + { + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, "%s *SafeDownCast (vtkObject* o);", + yyvsp[-3].str); + sprintf(temps,"SafeDownCast"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x309; + currentFunction->ArgCounts[0] = 1; + currentFunction->ArgClasses[0] = vtkstrdup("vtkObject"); + currentFunction->ReturnType = 0x2309; + currentFunction->ReturnClass = vtkstrdup(yyvsp[-3].str); + output_function(); + } + } + break; + + + } + +/* Line 1010 of yacc.c. */ +#line 2741 "vtkParse.tab.c" + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + const char* yyprefix; + char *yymsg; + int yyx; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("syntax error"); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + } + } + else + { + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); + yychar = YYEMPTY; + + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 984 "vtkParse.y" + +#include +#include "lex.yy.c" + +static void vtkParseDebug(const char* s1, const char* s2) +{ + if ( getenv("DEBUG") ) + { + fprintf(stderr, " %s", s1); + if ( s2 ) + { + fprintf(stderr, " %s", s2); + } + fprintf(stderr, "\n"); + } +} + +/* initialize the structure */ +void InitFunction(FunctionInfo *func) +{ + func->Name = NULL; + func->NumberOfArguments = 0; + func->ArrayFailure = 0; + func->IsPureVirtual = 0; + func->IsPublic = 0; + func->IsOperator = 0; + func->HaveHint = 0; + func->HintSize = 0; + func->ReturnType = 0x2; + func->ReturnClass = NULL; + func->Comment = NULL; + func->Signature = NULL; + func->IsLegacy = 0; + sigAllocatedLength = 0; + openSig = 1; + invertSig = 0; +} + +/* when the cpp file doesn't have enough info use the hint file */ +void look_for_hint() +{ + char h_cls[80]; + char h_func[80]; + unsigned int h_type; + int h_value; + + /* reset the position */ + if (!fhint) + { + return; + } + rewind(fhint); + + /* first find a hint */ + while (fscanf(fhint,"%s %s %x %i",h_cls,h_func,&h_type,&h_value) != EOF) + { + if ((!strcmp(h_cls,data.ClassName))&& + currentFunction->Name && + (!strcmp(h_func,currentFunction->Name))&& + ((int)h_type == currentFunction->ReturnType)) + { + currentFunction->HaveHint = 1; + currentFunction->HintSize = h_value; + } + } +} + +/* a simple routine that updates a few variables */ +void output_function() +{ + int i; + + /* a void argument is the same as no arguements */ + if (currentFunction->ArgTypes[0] % 0x1000 == 0x2) + { + currentFunction->NumberOfArguments = 0; + } + + currentFunction->IsPublic = in_public; + currentFunction->IsProtected = in_protected; + + /* look for VAR FUNCTIONS */ + if (currentFunction->NumberOfArguments + && (currentFunction->ArgTypes[0] == 0x5000)) + { + if (currentFunction->NumberOfArguments == 2) + { + currentFunction->NumberOfArguments = 1; + } + else + { + currentFunction->ArrayFailure = 1; + } + } + + /* is it a delete function */ + if (currentFunction->Name && !strcmp("Delete",currentFunction->Name)) + { + data.HasDelete = 1; + } + + + /* if we need a return type hint and dont currently have one */ + /* then try to find one */ + if (!currentFunction->HaveHint) + { + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x302: case 0x307: case 0x30A: case 0x30B: case 0x30C: + case 0x304: case 0x305: case 0x306: case 0x313: + look_for_hint(); + break; + } + } + + /* reject multi-dimensional arrays from wrappers */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if ((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x6 || + (currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x9) + { + currentFunction->ArrayFailure = 1; + } + } + + if (HaveComment) + { + currentFunction->Comment = vtkstrdup(CommentText); + } + + data.NumberOfFunctions++; + currentFunction = data.Functions + data.NumberOfFunctions; + InitFunction(currentFunction); +} + +extern void vtkParseOutput(FILE *,FileInfo *); + +int main(int argc,char *argv[]) +{ + FILE *fin; + int ret; + FILE *fout; + + if (argc < 4 || argc > 5) + { + fprintf(stderr, + "Usage: %s input_file is_concrete output_file\n",argv[0]); + exit(1); + } + + if (!(fin = fopen(argv[1],"r"))) + { + fprintf(stderr,"Error opening input file %s\n",argv[1]); + exit(1); + } + + fhint = 0; + data.FileName = argv[1]; + data.NameComment = NULL; + data.Description = NULL; + data.Caveats = NULL; + data.SeeAlso = NULL; + CommentState = 0; + + if (argc == 5) + { + if (!(fhint = fopen(argv[2],"r"))) + { + fprintf(stderr,"Error opening hint file %s\n",argv[2]); + exit(1); + } + data.IsConcrete = atoi(argv[3]); + } + else + { + data.IsConcrete = atoi(argv[2]); + } + + currentFunction = data.Functions; + InitFunction(currentFunction); + + yyin = fin; + yyout = stdout; + ret = yyparse(); + if (ret) + { + fprintf(stdout, + "*** SYNTAX ERROR found in parsing the header file %s before line %d ***\n", + argv[1], yylineno); + return ret; + } + + if (argc == 5) + { + fout = fopen(argv[4],"w"); + data.OutputFileName = argv[4]; + } + else + { + fout = fopen(argv[3],"w"); + data.OutputFileName = argv[3]; + } + + if (!fout) + { + fprintf(stderr,"Error opening output file %s\n",argv[3]); + exit(1); + } + vtkParseOutput(fout,&data); + fclose (fout); + + return 0; +} diff --git a/Wrapping/vtkParse.y b/Wrapping/vtkParse.y new file mode 100644 index 0000000..0faa645 --- /dev/null +++ b/Wrapping/vtkParse.y @@ -0,0 +1,1198 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParse.y,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +%{ + +/* + +This file must be translated to C and modified to build everywhere. + +Run yacc like this: + + yacc -b vtkParse vtkParse.y + +Modify vtkParse.tab.c: + - remove TABs + - comment out yyerrorlab stuff + +*/ + +#include +#include +#include +#define yyerror(a) fprintf(stderr,"%s\n",a) +#define yywrap() 1 + +static void vtkParseDebug(const char* s1, const char* s2); + +/* MSVC Does not define __STDC__ properly. */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 && !defined(__STDC__) +# define __STDC__ 1 +#endif + +/* Disable warnings in generated code. */ +#if defined(_MSC_VER) +# pragma warning (disable: 4127) /* conditional expression is constant */ +# pragma warning (disable: 4244) /* conversion to smaller integer type */ +#endif + +int yylex(void); +void output_function(); + +/* vtkstrdup is not part of POSIX so we create our own */ +char *vtkstrdup(const char *in) +{ + char *res = malloc(strlen(in)+1); + strcpy(res,in); + return res; +} + +#include "vtkParse.h" + + FileInfo data; + FunctionInfo *currentFunction; + + FILE *fhint; + char temps[2048]; + int in_public; + int in_protected; + int HaveComment; + char CommentText[50000]; + int CommentState; + int openSig; + int invertSig; + unsigned int sigAllocatedLength; + +#define YYMAXDEPTH 1000 + + void checkSigSize(char *arg) + { + if (strlen(currentFunction->Signature) + strlen(arg) + 3 > + sigAllocatedLength) + { + currentFunction->Signature = (char *) + realloc(currentFunction->Signature, sigAllocatedLength*2); + sigAllocatedLength = sigAllocatedLength*2; + } + } + void preSig(char *arg) + { + if (!currentFunction->Signature) + { + currentFunction->Signature = (char*)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s",arg); + } + else if (openSig) + { + char *tmp; + checkSigSize(arg); + tmp = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s%s",arg,tmp); + free(tmp); + } + } + void postSig(char *arg) + { + if (!currentFunction->Signature) + { + currentFunction->Signature = (char*)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s",arg); + } + else if (openSig) + { + char *tmp; + checkSigSize(arg); + tmp = vtkstrdup(currentFunction->Signature); + if (invertSig) + { + sprintf(currentFunction->Signature,"%s%s",arg,tmp); + } + else + { + sprintf(currentFunction->Signature,"%s%s",tmp,arg); + } + free(tmp); + } + } + void delSig(void) + { + if (currentFunction->Signature) + { + free(currentFunction->Signature); + currentFunction->Signature = NULL; + } + } + void legacySig(void) + { + currentFunction->IsLegacy = 1; + } +%} + +%union{ + char *str; + int integer; + } + +%token CLASS +%token PUBLIC +%token PRIVATE +%token PROTECTED +%token VIRTUAL +%token STRING +%token NUM +%token ID +%token INT +%token FLOAT +%token SHORT +%token LONG +%token LONG_LONG +%token INT64__ +%token DOUBLE +%token VOID +%token CHAR +%token SIGNED_CHAR +%token CLASS_REF +%token OTHER +%token CONST +%token OPERATOR +%token UNSIGNED +%token FRIEND +%token VTK_ID +%token STATIC +%token VAR_FUNCTION +%token ARRAY_NUM +%token VTK_LEGACY + +/* macro tokens */ +%token IdType +%token StdString +%token SetMacro +%token GetMacro +%token SetStringMacro +%token GetStringMacro +%token SetClampMacro +%token SetObjectMacro +%token SetReferenceCountedObjectMacro +%token GetObjectMacro +%token BooleanMacro +%token SetVector2Macro +%token SetVector3Macro +%token SetVector4Macro +%token SetVector6Macro +%token GetVector2Macro +%token GetVector3Macro +%token GetVector4Macro +%token GetVector6Macro +%token SetVectorMacro +%token GetVectorMacro +%token ViewportCoordinateMacro +%token WorldCoordinateMacro +%token TypeMacro + +%% +/* + * Here is the start of the grammer + */ +strt: maybe_other class_def maybe_other; + +class_def : CLASS VTK_ID + { + data.ClassName = vtkstrdup($2); + } + optional_scope '{' class_def_body '}'; + +class_def_body: class_def_item | class_def_item class_def_body; + +class_def_item: scope_type ':' | var + | operator + | FRIEND operator + | function func_body { output_function(); } + | FRIEND function func_body { output_function(); } + | legacy_function func_body { legacySig(); output_function(); } + | macro ';' + | macro; + +legacy_function: VTK_LEGACY '(' function ')' + +function: '~' func { preSig("~"); } + | VIRTUAL '~' func { preSig("virtual ~"); } + | func + | type func + { + currentFunction->ReturnType = $1; + } + | type CONST func + { + currentFunction->ReturnType = $1; + } + | VIRTUAL type CONST func + { + preSig("virtual "); + currentFunction->ReturnType = $2; + } + | VIRTUAL type func + { + preSig("virtual "); + currentFunction->ReturnType = $2; + } + | VIRTUAL func + { + preSig("virtual "); + }; + +operator: + operator_sig + { + output_function(); + } + | type operator_sig + { + currentFunction->ReturnType = $1; + output_function(); + } + | type CONST operator_sig + { + currentFunction->ReturnType = $1; + output_function(); + } + | VIRTUAL type CONST operator_sig + { + preSig("virtual "); + currentFunction->ReturnType = $2; + output_function(); + } + | VIRTUAL type operator_sig + { + preSig("virtual "); + currentFunction->ReturnType = $2; + output_function(); + } + | VIRTUAL operator_sig + { + preSig("virtual "); + output_function(); + }; + +operator_sig: OPERATOR maybe_other_no_semi ';' + { + currentFunction->IsOperator = 1; + vtkParseDebug("Converted operator", 0); + } + +func: func_sig { postSig(")"); } maybe_const { postSig(";"); openSig = 0; } + { + openSig = 1; + currentFunction->Name = $1; + vtkParseDebug("Parsed func", $1); + } + | func_sig '=' NUM + { + postSig(") = 0;"); + currentFunction->Name = $1; + vtkParseDebug("Parsed func", $1); + currentFunction->IsPureVirtual = 1; + data.IsAbstract = 1; + }; + +maybe_const: | CONST {postSig(" const");}; + +func_sig: any_id '(' {postSig(" ("); } args_list ')'; + +const_mod: CONST {postSig("const ");}; + +static_mod: STATIC {postSig("static ");}; + +any_id: VTK_ID {postSig($1);} | ID {postSig($1);}; + +func_body: ';' + | '{' maybe_other '}' ';' + | '{' maybe_other '}' + | ':' maybe_other_no_semi ';'; + +args_list: | more_args; + +more_args: arg { currentFunction->NumberOfArguments++;} + | arg { currentFunction->NumberOfArguments++; postSig(", ");} ',' more_args; + +arg: type + { + currentFunction->ArgCounts[currentFunction->NumberOfArguments] = 0; + currentFunction->ArgTypes[currentFunction->NumberOfArguments] = + $1;} + | type var_id + { + currentFunction->ArgCounts[currentFunction->NumberOfArguments] = + $2 / 0x10000; + currentFunction->ArgTypes[currentFunction->NumberOfArguments] = + $1 + $2 % 0x10000; + } opt_var_assign + | VAR_FUNCTION + { + postSig("void (*func)(void *) "); + currentFunction->ArgCounts[currentFunction->NumberOfArguments] = 0; + currentFunction->ArgTypes[currentFunction->NumberOfArguments] = 0x5000; + }; + +opt_var_assign: | '=' float_num; + +var: type var_id ';' {delSig();} | VAR_FUNCTION ';' {delSig();}; + +var_id: any_id var_array { $$ = $2; }; + +/* + 0x300 = [n] + 0x600 = [n][m] + 0x900 = [n][m][l] +*/ + +var_array: { $$ = 0; } + | ARRAY_NUM { char temp[100]; sprintf(temp,"[%i]",$1); + postSig(temp); } + var_array { $$ = 0x300 + 0x10000 * $1 + $3 % 0x1000; } + | '[' maybe_other_no_semi ']' var_array + { postSig("[]"); $$ = 0x300 + $4 % 0x1000; }; + +type: const_mod type_red1 {$$ = 0x1000 + $2;} + | type_red1 {$$ = $1;} + | static_mod type_red1 {$$ = 0x2000 + $2;} + | static_mod const_mod type_red1 {$$ = 0x3000 + $3;}; + +type_red1: type_red2 {$$ = $1;} + | type_red2 type_indirection + {$$ = $1 + $2;} + | type_string1 {$$ = $1;}; + +type_string1: type_string2 {$$ = $1;} + | type_string2 '&' { postSig("&"); $$ = $1;} + | type_string2 '*' { postSig("*"); $$ = 0x400 + $1;} + +type_string2: StdString { postSig("vtkStdString "); $$ = 0x1303; }; + + +/* 0x100 = & + 0x200 = && + 0x300 = * + 0x400 = &* + 0x500 = *& + 0x700 = ** + */ +type_indirection: '&' { postSig("&"); $$ = 0x100;} + | '*' { postSig("*"); $$ = 0x300;} + | '&' type_indirection { $$ = 0x100 + $2;} + | '*' type_indirection { $$ = 0x400 + $2;}; + +type_red2: UNSIGNED {postSig("unsigned ");} + type_primitive { $$ = 0x10 + $3;} + | type_primitive { $$ = $1;}; + +type_primitive: + FLOAT { postSig("float "); $$ = 0x1;} | + VOID { postSig("void "); $$ = 0x2;} | + CHAR { postSig("char "); $$ = 0x3;} | + INT { postSig("int "); $$ = 0x4;} | + SHORT { postSig("short "); $$ = 0x5;} | + LONG { postSig("long "); $$ = 0x6;} | + DOUBLE { postSig("double "); $$ = 0x7;} | + ID { + char ctmpid[2048]; + sprintf(ctmpid,"%s ",$1); + postSig(ctmpid); + $$ = 0x8;} | + VTK_ID + { + char ctmpid[2048]; + sprintf(ctmpid,"%s ",$1); + postSig(ctmpid); + $$ = 0x9; + currentFunction->ArgClasses[currentFunction->NumberOfArguments] = + vtkstrdup($1); + /* store the string into the return value just in case we need it */ + /* this is a parsing hack because the first "type" parser will */ + /* possibly be ht ereturn type of the first argument */ + if ((!currentFunction->ReturnClass) && + (!currentFunction->NumberOfArguments)) + { + currentFunction->ReturnClass = vtkstrdup($1); + } + } | + IdType { postSig("vtkIdType "); $$ = 0xA;} | + LONG_LONG { postSig("long long "); $$ = 0xB;} | + INT64__ { postSig("__int64 "); $$ = 0xC;} | + SIGNED_CHAR { postSig("signed char "); $$ = 0xD;}; + +optional_scope: | ':' scope_list; + +scope_list: scope_type VTK_ID + { + data.SuperClasses[data.NumberOfSuperClasses] = vtkstrdup($2); + data.NumberOfSuperClasses++; + } + | scope_type VTK_ID + { + data.SuperClasses[data.NumberOfSuperClasses] = vtkstrdup($2); + data.NumberOfSuperClasses++; + } ',' scope_list; + +scope_type: PUBLIC {in_public = 1; in_protected = 0;} + | PRIVATE {in_public = 0; in_protected = 0;} + | PROTECTED {in_public = 0; in_protected = 1;}; + +float_num: '-' float_prim | float_prim; + +float_prim: NUM {$$ = $1;} + | NUM '.' NUM {$$ = -1;} | any_id {$$ = -1;}; + +macro: + SetMacro '(' any_id ',' + {preSig("void Set"); postSig(" ("); } type_red2 ')' + { + postSig(");"); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = $6; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + } +| GetMacro '('{postSig("Get");} any_id ',' {postSig(" ();"); invertSig = 1;} + type_red2 ')' + { + sprintf(temps,"Get%s",$4); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = $7; + output_function(); + } +| SetStringMacro '(' {preSig("void Set");} any_id ')' + { + postSig(" (char *);"); + sprintf(temps,"Set%s",$4); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x303; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + } +| GetStringMacro '(' {preSig("char *Get");} any_id ')' + { + postSig(" ();"); + sprintf(temps,"Get%s",$4); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x303; + output_function(); + } +| SetClampMacro '(' any_id ',' + {preSig("void Set"); postSig(" ("); } type_red2 + {postSig(");"); openSig = 0;} ',' maybe_other_no_semi ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sscanf (currentFunction->Signature, "%*s %*s (%s);", local); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = $6; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s Get%sMinValue ();",local,$3); + sprintf(temps,"Get%sMinValue",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = $6; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"%s Get%sMaxValue ();",local,$3); + sprintf(temps,"Get%sMaxValue",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = $6; + output_function(); + } +| SetObjectMacro '(' any_id ',' + {preSig("void Set"); postSig(" ("); } type_red2 ')' + { + postSig("*);"); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x309; + currentFunction->ArgCounts[0] = 1; + currentFunction->ReturnType = 0x2; + output_function(); + } +| SetReferenceCountedObjectMacro '(' any_id ',' + {preSig("void Set"); postSig(" ("); } type_red2 ')' + { + postSig("*);"); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x309; + currentFunction->ArgCounts[0] = 1; + currentFunction->ReturnType = 0x2; + output_function(); + } +| GetObjectMacro '(' {postSig("*Get");} any_id ',' + {postSig(" ();"); invertSig = 1;} type_red2 ')' + { + sprintf(temps,"Get%s",$4); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + output_function(); + } +| BooleanMacro '(' any_id + {preSig("void "); postSig("On ();"); openSig = 0; } + ',' type_red2 ')' + { + sprintf(temps,"%sOn",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x2; + output_function(); + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void %sOff ();",$3); + sprintf(temps,"%sOff",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + output_function(); + } +| SetVector2Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s);",$3, + local, local); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 2; + currentFunction->ArgTypes[0] = $6; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = $6; + currentFunction->ArgCounts[1] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[2]);",$3, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + $6; + currentFunction->ArgCounts[0] = 0x2; + output_function(); + } +| GetVector2Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, $3); + sprintf(temps,"Get%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + $6; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 2; + output_function(); + } +| SetVector3Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s, %s);", + $3, local, local, local); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 3; + currentFunction->ArgTypes[0] = $6; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = $6; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = $6; + currentFunction->ArgCounts[2] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[3]);",$3, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + $6; + currentFunction->ArgCounts[0] = 3; + output_function(); + } +| GetVector3Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, $3); + sprintf(temps,"Get%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + $6; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 3; + output_function(); + } +| SetVector4Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s, %s, %s);", + $3, local, local, local, local); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 4; + currentFunction->ArgTypes[0] = $6; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = $6; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = $6; + currentFunction->ArgCounts[2] = 0; + currentFunction->ArgTypes[3] = $6; + currentFunction->ArgCounts[3] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[4]);",$3, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + $6; + currentFunction->ArgCounts[0] = 4; + output_function(); + } +| GetVector4Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, $3); + sprintf(temps,"Get%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + $6; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 4; + output_function(); + } +| SetVector6Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s, %s, %s, %s, %s, %s);", + $3, local, local, local, local, local, local); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 6; + currentFunction->ArgTypes[0] = $6; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = $6; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = $6; + currentFunction->ArgCounts[2] = 0; + currentFunction->ArgTypes[3] = $6; + currentFunction->ArgCounts[3] = 0; + currentFunction->ArgTypes[4] = $6; + currentFunction->ArgCounts[4] = 0; + currentFunction->ArgTypes[5] = $6; + currentFunction->ArgCounts[5] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (%s a[6]);",$3, + local); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + $6; + currentFunction->ArgCounts[0] = 6; + output_function(); + } +| GetVector6Macro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, $3); + sprintf(temps,"Get%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + $6; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 6; + output_function(); + } +| SetVectorMacro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ',' float_num ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"void Set%s (%s [%i]);",$3, + local, $8); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->ReturnType = 0x2; + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x300 + $6; + currentFunction->ArgCounts[0] = $8; + output_function(); + } +| GetVectorMacro '(' any_id ',' + { + free (currentFunction->Signature); + currentFunction->Signature = NULL; + } + type_red2 ',' float_num ')' + { + char *local = vtkstrdup(currentFunction->Signature); + sprintf(currentFunction->Signature,"%s *Get%s ();",local, $3); + sprintf(temps,"Get%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x300 + $6; + currentFunction->HaveHint = 1; + currentFunction->HintSize = $8; + output_function(); + } +| ViewportCoordinateMacro '(' any_id ')' + { + sprintf(currentFunction->Signature,"vtkCoordinate *Get%sCoordinate ();", + $3); + + sprintf(temps,"Get%sCoordinate",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + currentFunction->ReturnClass = vtkstrdup("vtkCoordinate"); + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double, double);", + $3); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 2; + currentFunction->ArgTypes[0] = 0x7; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = 0x7; + currentFunction->ArgCounts[1] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double a[2]);", + $3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x307; + currentFunction->ArgCounts[0] = 2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"double *Get%s ();", $3); + sprintf(temps,"Get%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x307; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 2; + output_function(); + } +| WorldCoordinateMacro '(' any_id ')' + { + sprintf(currentFunction->Signature,"vtkCoordinate *Get%sCoordinate ();", + $3); + + sprintf(temps,"Get%sCoordinate",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + currentFunction->ReturnClass = vtkstrdup("vtkCoordinate"); + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double, double, double);", + $3); + sprintf(temps,"Set%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 3; + currentFunction->ArgTypes[0] = 0x7; + currentFunction->ArgCounts[0] = 0; + currentFunction->ArgTypes[1] = 0x7; + currentFunction->ArgCounts[1] = 0; + currentFunction->ArgTypes[2] = 0x7; + currentFunction->ArgCounts[2] = 0; + currentFunction->ReturnType = 0x2; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"void Set%s (double a[3]);", + $3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x307; + currentFunction->ArgCounts[0] = 3; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature,"double *Get%s ();", $3); + sprintf(temps,"Get%s",$3); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x307; + currentFunction->HaveHint = 1; + currentFunction->HintSize = 3; + output_function(); + } +| TypeMacro '(' any_id ',' any_id ')' + { + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, "const char *GetClassName ();"); + sprintf(temps,"GetClassName"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x1303; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, + "int IsA (const char *name);"); + sprintf(temps,"IsA"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x1303; + currentFunction->ArgCounts[0] = 0; + currentFunction->ReturnType = 0x4; + output_function(); + + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, "%s *NewInstance ();", + $3); + sprintf(temps,"NewInstance"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 0; + currentFunction->ReturnType = 0x309; + currentFunction->ReturnClass = vtkstrdup($3); + output_function(); + + if ( data.IsConcrete ) + { + currentFunction->Signature = (char *)malloc(2048); + sigAllocatedLength = 2048; + sprintf(currentFunction->Signature, "%s *SafeDownCast (vtkObject* o);", + $3); + sprintf(temps,"SafeDownCast"); + currentFunction->Name = vtkstrdup(temps); + currentFunction->NumberOfArguments = 1; + currentFunction->ArgTypes[0] = 0x309; + currentFunction->ArgCounts[0] = 1; + currentFunction->ArgClasses[0] = vtkstrdup("vtkObject"); + currentFunction->ReturnType = 0x2309; + currentFunction->ReturnClass = vtkstrdup($3); + output_function(); + } + } +; + +/* + * These just eat up misc garbage + */ +maybe_other : | other_stuff maybe_other; +maybe_other_no_semi : | other_stuff_no_semi maybe_other_no_semi; + +other_stuff : ';' | other_stuff_no_semi; + +other_stuff_no_semi : OTHER | braces | parens | '*' | '=' | ':' | ',' | '.' + | STRING | type_red2 | type_string2 | NUM | CLASS_REF | '&' | brackets + | CONST | OPERATOR | '-' | '~' | STATIC | ARRAY_NUM; + +braces: '{' maybe_other '}'; +parens: '(' maybe_other ')'; +brackets: '[' maybe_other ']'; + +%% +#include +#include "lex.yy.c" + +static void vtkParseDebug(const char* s1, const char* s2) +{ + if ( getenv("DEBUG") ) + { + fprintf(stderr, " %s", s1); + if ( s2 ) + { + fprintf(stderr, " %s", s2); + } + fprintf(stderr, "\n"); + } +} + +/* initialize the structure */ +void InitFunction(FunctionInfo *func) +{ + func->Name = NULL; + func->NumberOfArguments = 0; + func->ArrayFailure = 0; + func->IsPureVirtual = 0; + func->IsPublic = 0; + func->IsOperator = 0; + func->HaveHint = 0; + func->HintSize = 0; + func->ReturnType = 0x2; + func->ReturnClass = NULL; + func->Comment = NULL; + func->Signature = NULL; + func->IsLegacy = 0; + sigAllocatedLength = 0; + openSig = 1; + invertSig = 0; +} + +/* when the cpp file doesn't have enough info use the hint file */ +void look_for_hint() +{ + char h_cls[80]; + char h_func[80]; + unsigned int h_type; + int h_value; + + /* reset the position */ + if (!fhint) + { + return; + } + rewind(fhint); + + /* first find a hint */ + while (fscanf(fhint,"%s %s %x %i",h_cls,h_func,&h_type,&h_value) != EOF) + { + if ((!strcmp(h_cls,data.ClassName))&& + currentFunction->Name && + (!strcmp(h_func,currentFunction->Name))&& + ((int)h_type == currentFunction->ReturnType)) + { + currentFunction->HaveHint = 1; + currentFunction->HintSize = h_value; + } + } +} + +/* a simple routine that updates a few variables */ +void output_function() +{ + int i; + + /* a void argument is the same as no arguements */ + if (currentFunction->ArgTypes[0] % 0x1000 == 0x2) + { + currentFunction->NumberOfArguments = 0; + } + + currentFunction->IsPublic = in_public; + currentFunction->IsProtected = in_protected; + + /* look for VAR FUNCTIONS */ + if (currentFunction->NumberOfArguments + && (currentFunction->ArgTypes[0] == 0x5000)) + { + if (currentFunction->NumberOfArguments == 2) + { + currentFunction->NumberOfArguments = 1; + } + else + { + currentFunction->ArrayFailure = 1; + } + } + + /* is it a delete function */ + if (currentFunction->Name && !strcmp("Delete",currentFunction->Name)) + { + data.HasDelete = 1; + } + + + /* if we need a return type hint and dont currently have one */ + /* then try to find one */ + if (!currentFunction->HaveHint) + { + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x302: case 0x307: case 0x30A: case 0x30B: case 0x30C: + case 0x304: case 0x305: case 0x306: case 0x313: + look_for_hint(); + break; + } + } + + /* reject multi-dimensional arrays from wrappers */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if ((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x6 || + (currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x9) + { + currentFunction->ArrayFailure = 1; + } + } + + if (HaveComment) + { + currentFunction->Comment = vtkstrdup(CommentText); + } + + data.NumberOfFunctions++; + currentFunction = data.Functions + data.NumberOfFunctions; + InitFunction(currentFunction); +} + +extern void vtkParseOutput(FILE *,FileInfo *); + +int main(int argc,char *argv[]) +{ + FILE *fin; + int ret; + FILE *fout; + + if (argc < 4 || argc > 5) + { + fprintf(stderr, + "Usage: %s input_file is_concrete output_file\n",argv[0]); + exit(1); + } + + if (!(fin = fopen(argv[1],"r"))) + { + fprintf(stderr,"Error opening input file %s\n",argv[1]); + exit(1); + } + + fhint = 0; + data.FileName = argv[1]; + data.NameComment = NULL; + data.Description = NULL; + data.Caveats = NULL; + data.SeeAlso = NULL; + CommentState = 0; + + if (argc == 5) + { + if (!(fhint = fopen(argv[2],"r"))) + { + fprintf(stderr,"Error opening hint file %s\n",argv[2]); + exit(1); + } + data.IsConcrete = atoi(argv[3]); + } + else + { + data.IsConcrete = atoi(argv[2]); + } + + currentFunction = data.Functions; + InitFunction(currentFunction); + + yyin = fin; + yyout = stdout; + ret = yyparse(); + if (ret) + { + fprintf(stdout, + "*** SYNTAX ERROR found in parsing the header file %s before line %d ***\n", + argv[1], yylineno); + return ret; + } + + if (argc == 5) + { + fout = fopen(argv[4],"w"); + data.OutputFileName = argv[4]; + } + else + { + fout = fopen(argv[3],"w"); + data.OutputFileName = argv[3]; + } + + if (!fout) + { + fprintf(stderr,"Error opening output file %s\n",argv[3]); + exit(1); + } + vtkParseOutput(fout,&data); + fclose (fout); + + return 0; +} + + diff --git a/Wrapping/vtkParseJava.c b/Wrapping/vtkParseJava.c new file mode 100644 index 0000000..5c5430f --- /dev/null +++ b/Wrapping/vtkParseJava.c @@ -0,0 +1,643 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParseJava.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include +#include "vtkParse.h" + +int numberOfWrappedFunctions = 0; +FunctionInfo *wrappedFunctions[1000]; +extern FunctionInfo *currentFunction; + +void output_temp(FILE *fp,int i) +{ + /* ignore void */ + if (((currentFunction->ArgTypes[i] % 0x10) == 0x2)&& + (!((currentFunction->ArgTypes[i] % 0x1000)/0x100))) + { + return; + } + + if (currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp,"Object id0, String id1"); + return; + } + + if (currentFunction->ArgTypes[i] % 0x1000 == 0x303) + { + fprintf(fp,"String "); + } + else + { + switch (currentFunction->ArgTypes[i] % 0x10) + { + case 0x1: fprintf(fp,"double "); break; + case 0x7: fprintf(fp,"double "); break; + case 0x4: fprintf(fp,"int "); break; + case 0x5: fprintf(fp,"int "); break; + case 0x6: fprintf(fp,"int "); break; + case 0xA: fprintf(fp,"int "); break; + case 0xB: fprintf(fp,"int "); break; + case 0xC: fprintf(fp,"int "); break; + case 0xD: fprintf(fp,"char "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"char "); break; + case 0x9: fprintf(fp,"%s ",currentFunction->ArgClasses[i]); break; + case 0x8: return; + } + } + + fprintf(fp,"id%i",i); + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x3)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x303)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x309)) + { + fprintf(fp,"[]"); + } +} + +void return_result(FILE *fp) +{ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x1: fprintf(fp,"double "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"char "); break; + case 0x7: fprintf(fp,"double "); break; + case 0x4: case 0x5: case 0x6: case 0xA: case 0xB: case 0xC: case 0xD: + case 0x13: case 0x14: case 0x15: case 0x16: case 0x1A: case 0x1B: case 0x1C: + fprintf(fp,"int "); + break; + case 0x303: fprintf(fp,"String "); break; + case 0x109: + case 0x309: + fprintf(fp,"%s ",currentFunction->ReturnClass); + break; + + /* handle functions returning vectors */ + /* this is done by looking them up in a hint file */ + case 0x301: case 0x307: + fprintf(fp,"double[] "); + break; + case 0x313: + fprintf(fp,"byte[] "); + break; + case 0x304: case 0x305: case 0x306: case 0x30A: case 0x30B: case 0x30C: case 0x30D: + case 0x314: case 0x315: case 0x316: case 0x31A: case 0x31B: case 0x31C: + fprintf(fp,"int[] "); break; + } +} + +/* have we done one of these yet */ +int DoneOne() +{ + int i,j; + int match; + FunctionInfo *fi; + + for (i = 0; i < numberOfWrappedFunctions; i++) + { + fi = wrappedFunctions[i]; + if ((!strcmp(fi->Name,currentFunction->Name)) + &&(fi->NumberOfArguments == currentFunction->NumberOfArguments)) + { + match = 1; + for (j = 0; j < fi->NumberOfArguments; j++) + { + if ((fi->ArgTypes[j] != currentFunction->ArgTypes[j]) && + !(((fi->ArgTypes[j] % 0x1000 == 0x309)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x109)) || + ((fi->ArgTypes[j] % 0x1000 == 0x109)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x309)) || + ((fi->ArgTypes[j] % 0x1000 == 0x301)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x307)) || + ((fi->ArgTypes[j] % 0x1000 == 0x307)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x301)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30A)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30A)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30A)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30A)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30B)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30B)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30B)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30B)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30C)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30C)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30C)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30C)) || + ((fi->ArgTypes[j] % 0x1000 == 0x1)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x7)) || + ((fi->ArgTypes[j] % 0x1000 == 0x7)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x1)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xA)) || + ((fi->ArgTypes[j] % 0x1000 == 0xA)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xA)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xA)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xB)) || + ((fi->ArgTypes[j] % 0x1000 == 0xB)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xB)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xB)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xC)) || + ((fi->ArgTypes[j] % 0x1000 == 0xC)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xC)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xC)))) + { + match = 0; + } + else + { + if (fi->ArgTypes[j] % 0x1000 == 0x309 || fi->ArgTypes[j] % 0x1000 == 0x109) + { + if (strcmp(fi->ArgClasses[j],currentFunction->ArgClasses[j])) + { + match = 0; + } + } + } + } + if ((fi->ReturnType != currentFunction->ReturnType) && + !(((fi->ReturnType % 0x1000 == 0x309)&& + (currentFunction->ReturnType % 0x1000 == 0x109)) || + ((fi->ReturnType % 0x1000 == 0x109)&& + (currentFunction->ReturnType % 0x1000 == 0x309)) || + ((fi->ReturnType % 0x1000 == 0x301)&& + (currentFunction->ReturnType % 0x1000 == 0x307)) || + ((fi->ReturnType % 0x1000 == 0x307)&& + (currentFunction->ReturnType % 0x1000 == 0x301)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x30A)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30A)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30A)) || + ((fi->ReturnType % 0x1000 == 0x30A)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x30B)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30B)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30B)) || + ((fi->ReturnType % 0x1000 == 0x30B)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x30C)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30C)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30C)) || + ((fi->ReturnType % 0x1000 == 0x30C)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x1)&& + (currentFunction->ReturnType % 0x1000 == 0x7)) || + ((fi->ReturnType % 0x1000 == 0x7)&& + (currentFunction->ReturnType % 0x1000 == 0x1)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xA)) || + ((fi->ReturnType % 0x1000 == 0xA)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xA)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xA)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xB)) || + ((fi->ReturnType % 0x1000 == 0xB)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xB)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xB)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xC)) || + ((fi->ReturnType % 0x1000 == 0xC)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xC)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xC)))) + { + match = 0; + } + else + { + if (fi->ReturnType % 0x1000 == 0x309 || fi->ReturnType % 0x1000 == 0x109) + { + if (strcmp(fi->ReturnClass,currentFunction->ReturnClass)) + { + match = 0; + } + } + } + if (match) return 1; + } + } + return 0; +} + +void HandleDataReader(FILE *fp, FileInfo *data) +{ + fprintf(fp,"\n private native void "); + fprintf(fp,"%s_%i(byte id0[],int id1);\n", + currentFunction->Name,numberOfWrappedFunctions); + fprintf(fp,"\n public void "); + fprintf(fp,"%s(byte id0[],int id1)\n",currentFunction->Name); + fprintf(fp," { %s_%i(id0,id1); }\n", + currentFunction->Name,numberOfWrappedFunctions); + data = 0; +} + +void HandleDataArray(FILE *fp, FileInfo *data) +{ + char* type = 0; + + if (!strcmp("vtkCharArray",data->ClassName) ) + { + type = "char"; + } + else if (!strcmp("vtkDoubleArray",data->ClassName) ) + { + type = "double"; + } + else if (!strcmp("vtkFloatArray",data->ClassName) ) + { + type = "float"; + } + else if (!strcmp("vtkIntArray",data->ClassName) ) + { + type = "int"; + } + else if (!strcmp("vtkLongArray",data->ClassName) ) + { + type = "long"; + } + else if (!strcmp("vtkShortArray",data->ClassName) ) + { + type = "short"; + } + else if (!strcmp("vtkUnsignedCharArray",data->ClassName) ) + { + type = "byte"; + } + else if (!strcmp("vtkUnsignedIntArray",data->ClassName) ) + { + type = "int"; + } + else if (!strcmp("vtkUnsignedLongArray",data->ClassName) ) + { + type = "long"; + } + else if (!strcmp("vtkUnsignedShortArray",data->ClassName) ) + { + type = "short"; + } + else + { + return; + } + + fprintf(fp,"\n"); + fprintf(fp," private native %s[] GetJavaArray_0();\n", type); + fprintf(fp," public %s[] GetJavaArray()\n", type); + fprintf(fp," { return GetJavaArray_0(); }\n"); + fprintf(fp,"\n"); + fprintf(fp," private native void SetJavaArray_0(%s[] arr);\n", type); + fprintf(fp," public void SetJavaArray(%s[] arr)\n", type); + fprintf(fp," { SetJavaArray_0(arr); }\n"); +} + +void outputFunction(FILE *fp, FileInfo *data) +{ + int i; + int args_ok = 1; + + /* some functions will not get wrapped no matter what else */ + if (currentFunction->IsOperator || + currentFunction->ArrayFailure || + !currentFunction->IsPublic || + !currentFunction->Name) + { + return; + } + + /* NewInstance and SafeDownCast can not be wrapped because it is a + (non-virtual) method which returns a pointer of the same type as + the current pointer. Since all methods are virtual in Java, this + looks like polymorphic return type. */ + if (!strcmp("NewInstance",currentFunction->Name)) + { + return ; + } + + if (!strcmp("SafeDownCast",currentFunction->Name)) + { + return ; + } + + /* check to see if we can handle the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (currentFunction->ArgTypes[i] % 0x1000 == 0x9) args_ok = 0; + if ((currentFunction->ArgTypes[i] % 0x10) == 0x8) args_ok = 0; + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 != 0x3)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x109)&& + ((currentFunction->ArgTypes[i] % 0x1000)/0x100)) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x313) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x316) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31C) args_ok = 0; + } + if ((currentFunction->ReturnType % 0x10) == 0x8) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x9) args_ok = 0; + if (((currentFunction->ReturnType % 0x1000)/0x100 != 0x3)&& + (currentFunction->ReturnType % 0x1000 != 0x109)&& + ((currentFunction->ReturnType % 0x1000)/0x100)) args_ok = 0; + + + /* eliminate unsigned char * and unsigned short * */ + if (currentFunction->ReturnType % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x316) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31C) args_ok = 0; + + if (currentFunction->NumberOfArguments && + (currentFunction->ArgTypes[0] == 0x5000) + &&(currentFunction->NumberOfArguments != 1)) args_ok = 0; + + /* make sure we have all the info we need for array arguments in */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x3)&& + (currentFunction->ArgCounts[i] <= 0)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x309)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x303)) args_ok = 0; + } + + /* if we need a return type hint make sure we have one */ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x302: case 0x307: + case 0x304: case 0x305: case 0x306: + case 0x30A: case 0x30B: case 0x30C: + case 0x313: + args_ok = currentFunction->HaveHint; + break; + } + + /* make sure it isn't a Delete or New function */ + if (!strcmp("Delete",currentFunction->Name) || + !strcmp("New",currentFunction->Name)) + { + args_ok = 0; + } + + /* handle DataReader SetBinaryInputString as a special case */ + if (!strcmp("SetBinaryInputString",currentFunction->Name) && + (!strcmp("vtkDataReader",data->ClassName) || + !strcmp("vtkStructuredGridReader",data->ClassName) || + !strcmp("vtkRectilinearGridReader",data->ClassName) || + !strcmp("vtkUnstructuredGridReader",data->ClassName) || + !strcmp("vtkStructuredPointsReader",data->ClassName) || + !strcmp("vtkPolyDataReader",data->ClassName))) + { + HandleDataReader(fp,data); + wrappedFunctions[numberOfWrappedFunctions] = currentFunction; + numberOfWrappedFunctions++; + } + + if (currentFunction->IsPublic && args_ok && + strcmp(data->ClassName,currentFunction->Name) && + strcmp(data->ClassName, currentFunction->Name + 1)) + { + /* make sure we haven't already done one of these */ + if (!DoneOne()) + { + fprintf(fp,"\n private native "); + return_result(fp); + fprintf(fp,"%s_%i(",currentFunction->Name,numberOfWrappedFunctions); + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + output_temp(fp,i); + } + fprintf(fp,");\n"); + fprintf(fp," public "); + return_result(fp); + fprintf(fp,"%s(",currentFunction->Name); + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + output_temp(fp,i); + } + /* if not void then need return otherwise none */ + if (currentFunction->ReturnType % 0x1000 == 0x2) + { + fprintf(fp,")\n { %s_%i(",currentFunction->Name, + numberOfWrappedFunctions); + } + else + { + fprintf(fp,")\n { return %s_%i(",currentFunction->Name, + numberOfWrappedFunctions); + } + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + fprintf(fp,"id%i",i); + } + if ((currentFunction->NumberOfArguments == 1) && + (currentFunction->ArgTypes[0] == 0x5000)) fprintf(fp,",id1"); + fprintf(fp,"); }\n"); + + wrappedFunctions[numberOfWrappedFunctions] = currentFunction; + numberOfWrappedFunctions++; + } + } +} + +/* print the parsed structures */ +void vtkParseOutput(FILE *fp, FileInfo *data) +{ + int i; + + fprintf(fp,"// java wrapper for %s object\n//\n",data->ClassName); + fprintf(fp,"\npackage vtk;\n"); + + if (strcmp("vtkObjectBase",data->ClassName)) + { + fprintf(fp,"import vtk.*;\n"); + } + fprintf(fp,"\npublic class %s",data->ClassName); + if (strcmp("vtkObjectBase",data->ClassName)) + { + if (data->NumberOfSuperClasses) + { + fprintf(fp," extends %s",data->SuperClasses[0]); + } + } + fprintf(fp,"\n{\n"); + + /* insert function handling code here */ + for (i = 0; i < data->NumberOfFunctions; i++) + { + currentFunction = data->Functions + i; + outputFunction(fp, data); + } + + HandleDataArray(fp, data); + + if (!data->NumberOfSuperClasses) + { + if (data->IsConcrete) + { + fprintf(fp,"\n public %s() { this.VTKInit();};\n",data->ClassName); + } + else + { + fprintf(fp,"\n public %s() { super();};\n",data->ClassName); + } + fprintf(fp,"\n protected %s(int dmy) { super(); };\n",data->ClassName); + fprintf(fp," protected int vtkId = 0;\n"); + + + /* if we are a base class and have a delete method */ + if (data->HasDelete) + { + fprintf(fp,"\n public native void VTKDelete();\n"); + fprintf(fp," protected void finalize() { this.VTKDelete();};\n"); + } + } + /* Special case for vtkObject */ + else if ( strcmp("vtkObject",data->ClassName) == 0 ) + { + fprintf(fp,"\n public %s() { super(); this.VTKInit(); };\n", + data->ClassName); + fprintf(fp,"\n protected %s(int dmy) { super(dmy); };\n",data->ClassName); + } + else + { + fprintf(fp,"\n public %s() { super(); };\n",data->ClassName); + fprintf(fp,"\n protected %s(int dmy) { super(dmy); };\n",data->ClassName); + } + + if (data->IsConcrete) + { + fprintf(fp," public native void VTKInit();\n"); + } + + fprintf(fp," protected native void VTKCastInit();\n"); + + if (!strcmp("vtkObject",data->ClassName)) + { + /* Add the Print method to vtkObject. */ + fprintf(fp," public native String Print();\n"); + /* Add the PrintRevisions method to vtkObject. */ + fprintf(fp," public native String PrintRevisions();\n"); + /* Add the default toString from java object */ + fprintf(fp," public String toString() { return Print(); }\n"); + } + + if (!strcmp("vtkObject",data->ClassName)) + { + fprintf(fp," public native int AddObserver(String id0, Object id1, String id2);\n"); + } + fprintf(fp,"\n}\n"); + { + int cc; + int len; + char *dir; + char *fname; + char javaDone[] = "VTKJavaWrapped"; + FILE* tfp; + fname = data->OutputFileName; + dir = (char*)malloc(strlen(fname) + strlen(javaDone) + 2); + sprintf(dir, "%s", fname); + len = (int)strlen(dir); + for ( cc = len-1; cc > 0; cc -- ) + { + if ( dir[cc] == '/' || dir[cc] == '\\' ) + { + dir[cc+1] = 0; + break; + } + } + strcat(dir, javaDone); + tfp = fopen(dir, "w"); + if ( tfp ) + { + fprintf(tfp, "File: %s\n", fname); + fclose(tfp); + } + } +} + diff --git a/Wrapping/vtkParseJavaBeans.c b/Wrapping/vtkParseJavaBeans.c new file mode 100644 index 0000000..a14c9c8 --- /dev/null +++ b/Wrapping/vtkParseJavaBeans.c @@ -0,0 +1,563 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkParseJavaBeans.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include "vtkParse.h" + +int numberOfWrappedFunctions = 0; +FunctionInfo *wrappedFunctions[1000]; +extern FunctionInfo *currentFunction; + +void output_temp(FILE *fp,int i) +{ + /* ignore void */ + if (((currentFunction->ArgTypes[i] % 0x10) == 0x2)&& + (!((currentFunction->ArgTypes[i] % 0x1000)/0x100))) + { + return; + } + + if (currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp,"Object id0, String id1"); + return; + } + + if (currentFunction->ArgTypes[i] % 0x1000 == 0x303) + { + fprintf(fp,"String "); + } + else + { + switch (currentFunction->ArgTypes[i] % 0x10) + { + case 0x1: fprintf(fp,"double "); break; + case 0x7: fprintf(fp,"double "); break; + case 0x4: fprintf(fp,"int "); break; + case 0x5: fprintf(fp,"int "); break; + case 0x6: fprintf(fp,"int "); break; + case 0xA: fprintf(fp,"int "); break; + case 0xB: fprintf(fp,"int "); break; + case 0xC: fprintf(fp,"int "); break; + case 0x2: fprintf(fp,"void "); break; + case 0xD: fprintf(fp,"char "); break; + case 0x3: fprintf(fp,"char "); break; + case 0x9: fprintf(fp,"%s ",currentFunction->ArgClasses[i]); break; + case 0x8: return; + } + } + + fprintf(fp,"id%i",i); + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x3)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x303)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x309)) + { + fprintf(fp,"[]"); + } +} + +void return_result(FILE *fp) +{ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x1: fprintf(fp,"double "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"char "); break; + case 0x7: fprintf(fp,"double "); break; + case 0x4: case 0x5: case 0x6: case 0xA: case 0xB: case 0xC: + case 0x13: case 0x14: case 0x15: case 0x16: case 0x1A: case 0x1B: case 0x1C: + fprintf(fp,"int "); + break; + case 0x303: fprintf(fp,"String "); break; + case 0x109: + case 0x309: + fprintf(fp,"%s ",currentFunction->ReturnClass); + break; + + /* handle functions returning vectors */ + /* this is done by looking them up in a hint file */ + case 0x301: case 0x307: + fprintf(fp,"double[] "); + break; + case 0x304: case 0x305: case 0x306: case 0x30A: case 0x30B: case 0x30C: case 0x30D: + case 0x313: case 0x314: case 0x315: case 0x316: case 0x31A: case 0x31B: case 0x31C: + fprintf(fp,"int[] "); break; + } +} + +/* have we done one of these yet */ +int DoneOne() +{ + int i,j; + int match; + FunctionInfo *fi; + + for (i = 0; i < numberOfWrappedFunctions; i++) + { + fi = wrappedFunctions[i]; + if ((!strcmp(fi->Name,currentFunction->Name)) + &&(fi->NumberOfArguments == currentFunction->NumberOfArguments)) + { + match = 1; + for (j = 0; j < fi->NumberOfArguments; j++) + { + if ((fi->ArgTypes[j] != currentFunction->ArgTypes[j]) && + !(((fi->ArgTypes[j] % 0x1000 == 0x309)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x109)) || + ((fi->ArgTypes[j] % 0x1000 == 0x109)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x309)) || + ((fi->ArgTypes[j] % 0x1000 == 0x301)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x307)) || + ((fi->ArgTypes[j] % 0x1000 == 0x307)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x301)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30A)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30A)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30A)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30A)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30B)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30B)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30B)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30B)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30C)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30C)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30C)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30C)) || + ((fi->ArgTypes[j] % 0x1000 == 0x1)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x7)) || + ((fi->ArgTypes[j] % 0x1000 == 0x7)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x1)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xA)) || + ((fi->ArgTypes[j] % 0x1000 == 0xA)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xA)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xA)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xB)) || + ((fi->ArgTypes[j] % 0x1000 == 0xB)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xB)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xB)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xC)) || + ((fi->ArgTypes[j] % 0x1000 == 0xC)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xC)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xC)))) + { + match = 0; + } + else + { + if (fi->ArgTypes[j] % 0x1000 == 0x309 || fi->ArgTypes[j] % 0x1000 == 0x109) + { + if (strcmp(fi->ArgClasses[j],currentFunction->ArgClasses[j])) + { + match = 0; + } + } + } + } + if ((fi->ReturnType != currentFunction->ReturnType) && + !(((fi->ReturnType % 0x1000 == 0x309)&& + (currentFunction->ReturnType % 0x1000 == 0x109)) || + ((fi->ReturnType % 0x1000 == 0x109)&& + (currentFunction->ReturnType % 0x1000 == 0x309)) || + ((fi->ReturnType % 0x1000 == 0x301)&& + (currentFunction->ReturnType % 0x1000 == 0x307)) || + ((fi->ReturnType % 0x1000 == 0x307)&& + (currentFunction->ReturnType % 0x1000 == 0x301)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x30A)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30A)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30A)) || + ((fi->ReturnType % 0x1000 == 0x30A)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x30B)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30B)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30B)) || + ((fi->ReturnType % 0x1000 == 0x30B)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x30C)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30C)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30C)) || + ((fi->ReturnType % 0x1000 == 0x30C)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x1)&& + (currentFunction->ReturnType % 0x1000 == 0x7)) || + ((fi->ReturnType % 0x1000 == 0x7)&& + (currentFunction->ReturnType % 0x1000 == 0x1)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xA)) || + ((fi->ReturnType % 0x1000 == 0xA)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xA)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xA)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xB)) || + ((fi->ReturnType % 0x1000 == 0xB)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xB)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xB)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xC)) || + ((fi->ReturnType % 0x1000 == 0xC)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xC)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xC)))) + { + match = 0; + } + else + { + if (fi->ReturnType % 0x1000 == 0x309 || fi->ReturnType % 0x1000 == 0x109) + { + if (strcmp(fi->ReturnClass,currentFunction->ReturnClass)) + { + match = 0; + } + } + } + if (match) return 1; + } + } + return 0; +} + +void outputFunction(FILE *fp, FileInfo *data) +{ + int i; + int args_ok = 1; + /* beans */ + char *beanfunc; + + /* some functions will not get wrapped no matter what else */ + if (currentFunction->IsPureVirtual || + currentFunction->IsOperator || + currentFunction->ArrayFailure || + !currentFunction->IsPublic || + !currentFunction->Name) + { + return; + } + + /* make the first letter lowercase for set get methods */ + beanfunc = strdup(currentFunction->Name); + if (isupper(beanfunc[0])) beanfunc[0] = beanfunc[0] + 32; + + /* check to see if we can handle the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (currentFunction->ArgTypes[i] % 0x1000 == 0x9) args_ok = 0; + if ((currentFunction->ArgTypes[i] % 0x10) == 0x8) args_ok = 0; + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 != 0x3)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x109)&& + ((currentFunction->ArgTypes[i] % 0x1000)/0x100)) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x313) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x316) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31C) args_ok = 0; + } + if ((currentFunction->ReturnType % 0x10) == 0x8) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x9) args_ok = 0; + if (((currentFunction->ReturnType % 0x1000)/0x100 != 0x3)&& + (currentFunction->ReturnType % 0x1000 != 0x109)&& + ((currentFunction->ReturnType % 0x1000)/0x100)) args_ok = 0; + + + /* eliminate unsigned char * and unsigned short * */ + if (currentFunction->ReturnType % 0x1000 == 0x313) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x316) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31C) args_ok = 0; + + if (currentFunction->NumberOfArguments && + (currentFunction->ArgTypes[0] == 0x5000) + &&(currentFunction->NumberOfArguments != 1)) args_ok = 0; + + /* make sure we have all the info we need for array arguments in */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x3)&& + (currentFunction->ArgCounts[i] <= 0)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x309)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x303)) args_ok = 0; + } + + /* if we need a return type hint make sure we have one */ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x302: case 0x307: + case 0x304: case 0x305: case 0x306: + case 0x30A: case 0x30B: case 0x30C: + args_ok = currentFunction->HaveHint; + break; + } + + /* make sure it isn't a Delete or New function */ + if (!strcmp("Delete",currentFunction->Name) || + !strcmp("New",currentFunction->Name)) + { + args_ok = 0; + } + + if (currentFunction->IsPublic && args_ok && + strcmp(data->ClassName,currentFunction->Name) && + strcmp(data->ClassName, currentFunction->Name + 1)) + { + /* make sure we haven't already done one of these */ + if (!DoneOne()) + { + fprintf(fp,"\n private native "); + return_result(fp); + fprintf(fp,"%s_%i(",currentFunction->Name,numberOfWrappedFunctions); + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + output_temp(fp,i); + } + fprintf(fp,");\n"); + fprintf(fp," public "); + return_result(fp); + fprintf(fp,"%s(",beanfunc); + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + output_temp(fp,i); + } + /* if not void then need return otherwise none */ + if (currentFunction->ReturnType % 0x1000 == 0x2) + { + fprintf(fp,")\n { %s_%i(",currentFunction->Name, + numberOfWrappedFunctions); + } + else + { + fprintf(fp,")\n { return %s_%i(",currentFunction->Name, + numberOfWrappedFunctions); + } + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + fprintf(fp,"id%i",i); + } + if ((currentFunction->NumberOfArguments == 1) && + (currentFunction->ArgTypes[0] == 0x5000)) fprintf(fp,",id1"); + + /* stick in secret beanie code for set methods */ + if (currentFunction->ReturnType % 0x1000 == 0x2) + { + /* only care about set methods and On/Off methods */ + if (!strncmp(beanfunc,"set",3) && + currentFunction->NumberOfArguments == 1 && + (currentFunction->ArgTypes[0] % 0x1000 < 0x10 || + currentFunction->ArgTypes[0] % 0x1000 == 0x303 || + currentFunction->ArgTypes[0] % 0x10 == 0x9)) + { + char prop[256]; + + strncpy(prop,beanfunc+3,strlen(beanfunc)-3); + prop[strlen(beanfunc)-3] = '\0'; + if (isupper(prop[0])) prop[0] = prop[0] + 32; + fprintf(fp,");\n changes.firePropertyChange(\"%s\",null,",prop); + + /* handle basic types */ + if (currentFunction->ArgTypes[0] % 0x1000 == 0x303) + { + fprintf(fp," id0"); + } + else + { + switch (currentFunction->ArgTypes[0] % 0x10) + { + case 0x1: + case 0x7: fprintf(fp," new Double(id0)"); break; + case 0x4: + case 0x5: + case 0x6: fprintf(fp," new Integer(id0)"); break; + case 0x9: fprintf(fp," id0"); break; + case 0x3: /* not implemented yet */ + default: fprintf(fp," null"); + } + } + } + /* not a set method is it an On/Off method ? */ + else + { + if (!strncmp(beanfunc + strlen(beanfunc) - 2, "On",2)) + { + /* OK we think this is a Boolean method so need to fire a change */ + char prop[256]; + strncpy(prop,beanfunc,strlen(beanfunc)-2); + prop[strlen(beanfunc)-2] = '\0'; + fprintf(fp,");\n changes.firePropertyChange(\"%s\",null,new Integer(1)", + prop); + } + if (!strncmp(beanfunc + strlen(beanfunc) - 3, "Off",3)) + { + /* OK we think this is a Boolean method so need to fire a change */ + char prop[256]; + strncpy(prop,beanfunc,strlen(beanfunc)-3); + prop[strlen(beanfunc)-3] = '\0'; + fprintf(fp,");\n changes.firePropertyChange(\"%s\",null,new Integer(0)", + prop); + } + } + } + fprintf(fp,"); }\n"); + + wrappedFunctions[numberOfWrappedFunctions] = currentFunction; + numberOfWrappedFunctions++; + } + } + free(beanfunc); +} + +/* print the parsed structures */ +void vtkParseOutput(FILE *fp, FileInfo *data) +{ + int i; + + fprintf(fp,"// java wrapper for %s object\n//\n",data->ClassName); + fprintf(fp,"\npackage vtk;\n"); + + /* beans */ + if (!data->NumberOfSuperClasses) + { + fprintf(fp,"import java.beans.*;\n"); + } + +if (strcmp("vtkObject",data->ClassName)) + { + fprintf(fp,"import vtk.*;\n"); + } + fprintf(fp,"\npublic class %s",data->ClassName); + if (strcmp("vtkObject",data->ClassName)) + { + if (data->NumberOfSuperClasses) + fprintf(fp," extends %s",data->SuperClasses[0]); + } + fprintf(fp,"\n{\n"); + + fprintf(fp," public %s getThis%s() { return this;}\n\n", + data->ClassName, data->ClassName+3); + + /* insert function handling code here */ + for (i = 0; i < data->NumberOfFunctions; i++) + { + currentFunction = data->Functions + i; + outputFunction(fp, data); + } + +if (!data->NumberOfSuperClasses) + { + fprintf(fp,"\n public %s() { this.VTKInit();};\n",data->ClassName); + fprintf(fp," protected int vtkId = 0;\n"); + + /* beans */ + fprintf(fp," public void addPropertyChangeListener(PropertyChangeListener l)\n {\n"); + fprintf(fp," changes.addPropertyChangeListener(l);\n }\n"); + fprintf(fp," public void removePropertyChangeListener(PropertyChangeListener l)\n {\n"); + fprintf(fp," changes.removePropertyChangeListener(l);\n }\n"); + fprintf(fp," protected PropertyChangeSupport changes = new PropertyChangeSupport(this);\n\n"); + + /* if we are a base class and have a delete method */ + if (data->HasDelete) + { + fprintf(fp,"\n public native void VTKDelete();\n"); + fprintf(fp," protected void finalize() { this.VTKDelete();};\n"); + } + } + if ((!data->IsAbstract)&& + strcmp(data->ClassName,"vtkDataWriter") && + strcmp(data->ClassName,"vtkPointSet") && + strcmp(data->ClassName,"vtkDataSetSource") + ) + { + fprintf(fp," public native void VTKInit();\n"); + } + if (!strcmp("vtkObject",data->ClassName)) + { + fprintf(fp," public native String Print();\n"); + } + fprintf(fp,"}\n"); +} + diff --git a/Wrapping/vtkPrint.c b/Wrapping/vtkPrint.c new file mode 100644 index 0000000..88b8717 --- /dev/null +++ b/Wrapping/vtkPrint.c @@ -0,0 +1,52 @@ +#include +#include "vtkParse.h" + +/* print the parsed structures */ +void vtkParseOutput(FILE *fp, FileInfo *data) +{ + int i; + + fprintf(fp,"Class Name: %s\n",data->ClassName); + fprintf(fp,"Name Comment: %s\n",data->NameComment ? data->NameComment : "None"); + fprintf(fp,"Description: %s\n",data->Description ?data->Description : "None"); + fprintf(fp,"Caveats: %s\n",data->Caveats ? data->Caveats : "None"); + fprintf(fp,"See Also: %s\n",data->SeeAlso ?data->SeeAlso : "None"); + fprintf(fp,"Has Delete: %s\n",data->HasDelete ? "Yes" : "No"); + fprintf(fp,"Abstract: %s\n",data->HasDelete ? "Yes" : "No"); + fprintf(fp,"Number Of Super Classes: %i\n",data->NumberOfSuperClasses); + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp," %s\n",data->SuperClasses[i]); + } + + fprintf(fp,"Number Of Functions: %i\n",data->NumberOfFunctions); + for (i = 0; i < data->NumberOfFunctions; i++) + { + fprintf(fp," Function Name: %s\n",data->Functions[i].Name ? + data->Functions[i].Name : "None"); + fprintf(fp," Function Signature: %s\n",data->Functions[i].Signature ? + data->Functions[i].Signature : "None"); + fprintf(fp," Number Of Arguments: %i\n", + data->Functions[i].NumberOfArguments); + fprintf(fp," Array Failure: %s\n", + data->Functions[i].ArrayFailure ? "Yes" : "No"); + fprintf(fp," Pure Virtual: %s\n", + data->Functions[i].IsPureVirtual ? "Yes" : "No"); + fprintf(fp," Public: %s\n", + data->Functions[i].IsPublic ? "Yes" : "No"); + fprintf(fp," Operator: %s\n", + data->Functions[i].IsOperator ? "Yes" : "No"); + fprintf(fp," Have Hint: %s\n", + data->Functions[i].HaveHint ? "Yes" : "No"); + fprintf(fp," Hint Size: %i\n", + data->Functions[i].HintSize); + fprintf(fp," Return Type: %i\n", + data->Functions[i].ReturnType); + fprintf(fp," ReturnClass: %s\n", + data->Functions[i].ReturnClass ? + data->Functions[i].ReturnClass : "None"); + fprintf(fp," Comment: %s\n", + data->Functions[i].Comment ? + data->Functions[i].Comment : "None"); + } +} diff --git a/Wrapping/vtkWrapJava.c b/Wrapping/vtkWrapJava.c new file mode 100644 index 0000000..2c832ca --- /dev/null +++ b/Wrapping/vtkWrapJava.c @@ -0,0 +1,1066 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWrapJava.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include "vtkParse.h" + +int numberOfWrappedFunctions = 0; +FunctionInfo *wrappedFunctions[1000]; +extern FunctionInfo *currentFunction; +FileInfo *CurrentData; + +void output_proto_vars(FILE *fp, int i) +{ + /* ignore void */ + if (((currentFunction->ArgTypes[i] % 0x10) == 0x2)&& + (!((currentFunction->ArgTypes[i] % 0x1000)/0x100))) + { + return; + } + + if (currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp,"jobject id0, jstring id1"); + return; + } + + if (currentFunction->ArgTypes[i] % 0x1000 == 0x303) + { + fprintf(fp,"jstring "); + fprintf(fp,"id%i",i); + return; + } + + if ((currentFunction->ArgTypes[i] % 0x1000 == 0x301)||(currentFunction->ArgTypes[i] % 0x1000 == 0x307)) + { + fprintf(fp,"jdoubleArray "); + fprintf(fp,"id%i",i); + return; + } + + if ((currentFunction->ArgTypes[i] % 0x1000 == 0x304)|| + (currentFunction->ArgTypes[i] % 0x1000 == 0x306)|| + (currentFunction->ArgTypes[i] % 0x1000 == 0x30A)|| + (currentFunction->ArgTypes[i] % 0x1000 == 0x30B)|| + (currentFunction->ArgTypes[i] % 0x1000 == 0x30C)) + { + fprintf(fp,"jintArray "); + fprintf(fp,"id%i",i); + return; + } + + + switch (currentFunction->ArgTypes[i] % 0x10) + { + case 0x1: fprintf(fp,"jdouble "); break; + case 0x7: fprintf(fp,"jdouble "); break; + case 0x4: fprintf(fp,"jint "); break; + case 0x5: fprintf(fp,"jint "); break; + case 0x6: fprintf(fp,"jint "); break; + case 0xA: fprintf(fp,"jint "); break; + case 0xB: fprintf(fp,"jint "); break; + case 0xC: fprintf(fp,"jint "); break; + case 0xD: fprintf(fp,"jint "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"jchar "); break; + case 0x9: fprintf(fp,"jobject "); break; + case 0x8: return; + } + + fprintf(fp,"id%i",i); +} + +/* when the cpp file doesn't have enough info use the hint file */ +void use_hints(FILE *fp) +{ + /* use the hint */ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x313: + /* for vtkDataWriter we want to handle this case specially */ + if (strcmp(currentFunction->Name,"GetBinaryOutputString") || + strcmp(CurrentData->ClassName,"vtkDataWriter")) + { + fprintf(fp," return vtkJavaMakeJArrayOfByteFromUnsignedChar(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + } + else + { + fprintf(fp," return vtkJavaMakeJArrayOfByteFromUnsignedChar(env,temp%i,op->GetOutputStringLength());\n", MAX_ARGS); + } + break; + case 0x301: + fprintf(fp," return vtkJavaMakeJArrayOfDoubleFromFloat(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + break; + + case 0x307: + fprintf(fp," return vtkJavaMakeJArrayOfDoubleFromDouble(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + break; + + case 0x304: + fprintf(fp," return vtkJavaMakeJArrayOfIntFromInt(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + break; + + case 0x30A: + fprintf(fp," return vtkJavaMakeJArrayOfIntFromIdType(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + break; + case 0x30B: + fprintf(fp," return vtkJavaMakeJArrayOfIntFromLongLong(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + break; + case 0x30C: + fprintf(fp," return vtkJavaMakeJArrayOfIntFrom__Int64(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + break; + case 0x30D: + fprintf(fp," return vtkJavaMakeJArrayOfIntFromSignedChar(env,temp%i,%i);\n", + MAX_ARGS, currentFunction->HintSize); + break; + case 0x305: case 0x306: case 0x314: case 0x315: case 0x316: + case 0x31A: case 0x31B: case 0x31C: + break; + } +} + +void return_result(FILE *fp) +{ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x1: fprintf(fp,"jdouble "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"jchar "); break; + case 0x7: fprintf(fp,"jdouble "); break; + case 0x4: case 0x5: case 0x6: case 0xA: case 0xB: case 0xC: case 0xD: + case 0x13: case 0x14: case 0x15: case 0x16: case 0x1A: case 0x1B: case 0x1C: + fprintf(fp,"jint "); + break; + case 0x303: fprintf(fp,"jstring "); break; + case 0x109: + case 0x309: + fprintf(fp,"jobject "); break; + + case 0x301: case 0x307: case 0x313: + case 0x304: case 0x305: case 0x306: case 0x30A: case 0x30B: case 0x30C: + case 0x30D: case 0x31A: case 0x31B: case 0x31C: + fprintf(fp,"jarray "); break; + } +} + + +void output_temp(FILE *fp, int i, int aType, char *Id, int aCount) +{ + /* handle VAR FUNCTIONS */ + if (aType == 0x5000) + { + fprintf(fp," vtkJavaVoidFuncArg *temp%i = new vtkJavaVoidFuncArg;\n",i); + return; + } + + /* ignore void */ + if (((aType % 0x10) == 0x2)&&(!((aType % 0x1000)/0x100))) + { + return; + } + + /* for const * return types prototype with const */ + if ((i == MAX_ARGS)&&(aType % 0x2000 >= 0x1000)) + { + fprintf(fp," const "); + } + else + { + fprintf(fp," "); + } + + if ((aType % 0x100)/0x10 == 0x1) + { + fprintf(fp," unsigned "); + } + + switch (aType % 0x10) + { + case 0x1: fprintf(fp,"float "); break; + case 0x7: fprintf(fp,"double "); break; + case 0x4: fprintf(fp,"int "); break; + case 0x5: fprintf(fp,"short "); break; + case 0x6: fprintf(fp,"long "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"char "); break; + case 0xA: fprintf(fp,"vtkIdType "); break; + case 0xB: fprintf(fp,"long long "); break; + case 0xC: fprintf(fp,"__int64 "); break; + case 0xD: fprintf(fp,"signed char "); break; + case 0x9: + fprintf(fp,"%s ",Id); break; + case 0x8: return; + } + + switch ((aType % 0x1000)/0x100) + { + case 0x1: fprintf(fp, " *"); break; /* act " &" */ + case 0x2: fprintf(fp, "&&"); break; + case 0x3: + if ((i == MAX_ARGS)||(aType % 0x10 == 0x9)||(aType % 0x1000 == 0x303)) + { + fprintf(fp, " *"); + } + break; + case 0x4: fprintf(fp, "&*"); break; + case 0x5: fprintf(fp, "*&"); break; + case 0x7: fprintf(fp, "**"); break; + default: fprintf(fp," "); break; + } + fprintf(fp,"temp%i",i); + + /* handle arrays */ + if ((aType % 0x1000/0x100 == 0x3)&& + (i != MAX_ARGS)&&(aType % 0x10 != 0x9)&&(aType % 0x1000 != 0x303)) + { + fprintf(fp,"[%i]",aCount); + fprintf(fp,";\n void *tempArray%i",i); + } + + fprintf(fp,";\n"); + if ((i == MAX_ARGS) && ((aType % 0x1000 == 0x309)||(aType % 0x1000 == 0x109))) + { + fprintf(fp," jobject tempH;\n"); + } +} + +void get_args(FILE *fp, int i) +{ + int j; + + /* handle VAR FUNCTIONS */ + if (currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp," env->GetJavaVM(&(temp%i->vm));\n",i); + fprintf(fp," temp%i->uobj = env->NewGlobalRef(id0);\n",i); + fprintf(fp," temp%i->mid = env->GetMethodID(env->GetObjectClass(id0),vtkJavaUTFToChar(env,id1),\"()V\");\n",i); + return; + } + + /* ignore void */ + if (((currentFunction->ArgTypes[i] % 0x10) == 0x2)&& + (!((currentFunction->ArgTypes[i] % 0x1000)/0x100))) + { + return; + } + + switch (currentFunction->ArgTypes[i] % 0x1000) + { + case 0x3: + fprintf(fp," temp%i = (char)(0xff & id%i);\n",i,i); + break; + case 0x303: + fprintf(fp," temp%i = vtkJavaUTFToChar(env,id%i);\n",i,i); + break; + case 0x109: + case 0x309: + fprintf(fp," temp%i = (%s *)(vtkJavaGetPointerFromObject(env,id%i,(char *) \"%s\"));\n",i,currentFunction->ArgClasses[i],i,currentFunction->ArgClasses[i]); + break; + case 0x301: + case 0x307: + fprintf(fp," tempArray%i = (void *)(env->GetDoubleArrayElements(id%i,NULL));\n",i,i); + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + fprintf(fp," temp%i[%i] = ((jdouble *)tempArray%i)[%i];\n",i,j,i,j); + } + break; + case 0x304: + case 0x306: + case 0x30A: + case 0x30B: + case 0x30C: + case 0x30D: + fprintf(fp," tempArray%i = (void *)(env->GetIntArrayElements(id%i,NULL));\n",i,i); + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + fprintf(fp," temp%i[%i] = ((jint *)tempArray%i)[%i];\n",i,j,i,j); + } + break; + case 0x2: + case 0x9: break; + default: fprintf(fp," temp%i = id%i;\n",i,i); break; + } +} + + +void copy_and_release_args(FILE *fp, int i) +{ + int j; + + /* handle VAR FUNCTIONS */ + if (currentFunction->ArgTypes[i] == 0x5000) + { + return; + } + + /* ignore void */ + if (((currentFunction->ArgTypes[i] % 0x10) == 0x2)&& + (!((currentFunction->ArgTypes[i] % 0x1000)/0x100))) + { + return; + } + + switch (currentFunction->ArgTypes[i] % 0x1000) + { + case 0x301: + case 0x307: + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + fprintf(fp," ((jdouble *)tempArray%i)[%i] = temp%i[%i];\n",i,j,i,j); + } + fprintf(fp," env->ReleaseDoubleArrayElements(id%i,(jdouble *)tempArray%i,0);\n",i,i); + break; + case 0x304: + case 0x306: + case 0x30A: + case 0x30B: + case 0x30C: + case 0x30D: + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + fprintf(fp," ((jint *)tempArray%i)[%i] = temp%i[%i];\n",i,j,i,j); + } + fprintf(fp," env->ReleaseIntArrayElements(id%i,(jint *)tempArray%i,0);\n",i,i); + break; + default: + break; + } +} + +void do_return(FILE *fp) +{ + /* ignore void */ + if (((currentFunction->ReturnType % 0x10) == 0x2)&&(!((currentFunction->ReturnType % 0x1000)/0x100))) + { + return; + } + + switch (currentFunction->ReturnType % 0x1000) + { + case 0x303: + { + fprintf(fp," return vtkJavaMakeJavaString(env,temp%i);\n", + MAX_ARGS); + } + break; + case 0x109: + case 0x309: + { + fprintf(fp," if (temp%i == NULL) { return NULL; }\n", MAX_ARGS); + fprintf(fp," tempH = vtkJavaGetObjectFromPointer((void *)temp%i);\n", MAX_ARGS); + fprintf(fp," if (!tempH)\n {\n"); + fprintf(fp," tempH = vtkJavaCreateNewJavaStubForObject(env, (vtkObject *)temp%i);\n", MAX_ARGS); + fprintf(fp," if (!tempH)\n {\n"); + fprintf(fp," // clear the exception first\n"); + fprintf(fp," env->ExceptionClear();\n"); + fprintf(fp," // no java stub for this class exists? Use function return type\n"); + fprintf(fp," tempH = vtkJavaCreateNewJavaStub(env, \"vtk/%s\", (void *)temp%i);\n", + currentFunction->ReturnClass, MAX_ARGS); + fprintf(fp," }\n"); + fprintf(fp," }\n"); + fprintf(fp," return tempH;\n"); + break; + } + + /* handle functions returning vectors */ + /* this is done by looking them up in a hint file */ + case 0x301: case 0x307: case 0x313: + case 0x304: case 0x305: case 0x306: + case 0x30A: case 0x30B: case 0x30C: case 0x30D: + use_hints(fp); + break; + default: fprintf(fp," return temp%i;\n", MAX_ARGS); break; + } +} + +/* have we done one of these yet */ +int DoneOne() +{ + int i,j; + int match; + FunctionInfo *fi; + + for (i = 0; i < numberOfWrappedFunctions; i++) + { + fi = wrappedFunctions[i]; + if ((!strcmp(fi->Name,currentFunction->Name)) + &&(fi->NumberOfArguments == currentFunction->NumberOfArguments)) + { + match = 1; + for (j = 0; j < fi->NumberOfArguments; j++) + { + if ((fi->ArgTypes[j] != currentFunction->ArgTypes[j]) && + !(((fi->ArgTypes[j] % 0x1000 == 0x309)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x109)) || + ((fi->ArgTypes[j] % 0x1000 == 0x109)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x309)) || + ((fi->ArgTypes[j] % 0x1000 == 0x301)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x307)) || + ((fi->ArgTypes[j] % 0x1000 == 0x307)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x301)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30A)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30A)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30A)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30A)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30B)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30B)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30B)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30B)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30C)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x304)) || + ((fi->ArgTypes[j] % 0x1000 == 0x304)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30C)) || + ((fi->ArgTypes[j] % 0x1000 == 0x30C)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x306)) || + ((fi->ArgTypes[j] % 0x1000 == 0x306)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x30C)) || + ((fi->ArgTypes[j] % 0x1000 == 0x1)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x7)) || + ((fi->ArgTypes[j] % 0x1000 == 0x7)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x1)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xA)) || + ((fi->ArgTypes[j] % 0x1000 == 0xA)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xA)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xA)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xB)) || + ((fi->ArgTypes[j] % 0x1000 == 0xB)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xB)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xB)) || + ((fi->ArgTypes[j] % 0x1000 == 0x4)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xC)) || + ((fi->ArgTypes[j] % 0x1000 == 0xC)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x4)) || + ((fi->ArgTypes[j] % 0x1000 == 0xC)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0x6)) || + ((fi->ArgTypes[j] % 0x1000 == 0x6)&& + (currentFunction->ArgTypes[j] % 0x1000 == 0xC)))) + { + match = 0; + } + else + { + if (fi->ArgTypes[j] % 0x1000 == 0x309 || fi->ArgTypes[j] % 0x1000 == 0x109) + { + if (strcmp(fi->ArgClasses[j],currentFunction->ArgClasses[j])) + { + match = 0; + } + } + } + } + if ((fi->ReturnType != currentFunction->ReturnType) && + !(((fi->ReturnType % 0x1000 == 0x309)&& + (currentFunction->ReturnType % 0x1000 == 0x109)) || + ((fi->ReturnType % 0x1000 == 0x109)&& + (currentFunction->ReturnType % 0x1000 == 0x309)) || + ((fi->ReturnType % 0x1000 == 0x301)&& + (currentFunction->ReturnType % 0x1000 == 0x307)) || + ((fi->ReturnType % 0x1000 == 0x307)&& + (currentFunction->ReturnType % 0x1000 == 0x301)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30A)) || + ((fi->ReturnType % 0x1000 == 0x30A)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30A)) || + ((fi->ReturnType % 0x1000 == 0x30A)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30B)) || + ((fi->ReturnType % 0x1000 == 0x30B)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30B)) || + ((fi->ReturnType % 0x1000 == 0x30B)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x304)&& + (currentFunction->ReturnType % 0x1000 == 0x30C)) || + ((fi->ReturnType % 0x1000 == 0x30C)&& + (currentFunction->ReturnType % 0x1000 == 0x304)) || + ((fi->ReturnType % 0x1000 == 0x306)&& + (currentFunction->ReturnType % 0x1000 == 0x30C)) || + ((fi->ReturnType % 0x1000 == 0x30C)&& + (currentFunction->ReturnType % 0x1000 == 0x306)) || + ((fi->ReturnType % 0x1000 == 0x1)&& + (currentFunction->ReturnType % 0x1000 == 0x7)) || + ((fi->ReturnType % 0x1000 == 0x7)&& + (currentFunction->ReturnType % 0x1000 == 0x1)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xA)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xA)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xA)) || + ((fi->ReturnType % 0x1000 == 0xA)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xB)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xB)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xB)) || + ((fi->ReturnType % 0x1000 == 0xB)&& + (currentFunction->ReturnType % 0x1000 == 0x4)) || + ((fi->ReturnType % 0x1000 == 0xC)&& + (currentFunction->ReturnType % 0x1000 == 0x6)) || + ((fi->ReturnType % 0x1000 == 0x6)&& + (currentFunction->ReturnType % 0x1000 == 0xC)) || + ((fi->ReturnType % 0x1000 == 0x4)&& + (currentFunction->ReturnType % 0x1000 == 0xC)) || + ((fi->ReturnType % 0x1000 == 0xC)&& + (currentFunction->ReturnType % 0x1000 == 0x4)))) + + { + match = 0; + } + else + { + if (fi->ReturnType % 0x1000 == 0x309 || fi->ReturnType % 0x1000 == 0x109) + { + if (strcmp(fi->ReturnClass,currentFunction->ReturnClass)) + { + match = 0; + } + } + } + if (match) return 1; + } + } + return 0; +} + +void HandleDataReader(FILE *fp, FileInfo *data) +{ + fprintf(fp,"\n"); + fprintf(fp,"extern \"C\" JNIEXPORT void"); + fprintf(fp," JNICALL Java_vtk_%s_%s_1%i(JNIEnv *env, jobject obj, jbyteArray id0, jint id1)\n", + data->ClassName,currentFunction->Name, numberOfWrappedFunctions); + fprintf(fp,"{\n"); + fprintf(fp," %s *op;\n",data->ClassName); + fprintf(fp," op = (%s *)vtkJavaGetPointerFromObject(env,obj,(char *) \"%s\");\n", + data->ClassName, data->ClassName); + fprintf(fp," jboolean isCopy;\n"); + fprintf(fp," jbyte *data = env->GetByteArrayElements(id0,&isCopy);\n"); + fprintf(fp," op->SetBinaryInputString((const char *)data,id1);\n"); + fprintf(fp," env->ReleaseByteArrayElements(id0,data,JNI_ABORT);\n"); + fprintf(fp,"}\n"); +} + +void HandleDataArray(FILE *fp, FileInfo *data) +{ + char* type = 0; + char* jtype = 0; + char* fromtype = 0; + char* jfromtype = 0; + + if (!strcmp("vtkCharArray",data->ClassName) ) + { + type = "char"; + fromtype = "Char"; + jtype = "byte"; + jfromtype = "Byte"; + } + else if (!strcmp("vtkDoubleArray",data->ClassName) ) + { + type = "double"; + fromtype = "Double"; + jtype = type; + jfromtype = fromtype; + } + else if (!strcmp("vtkFloatArray",data->ClassName) ) + { + type = "float"; + fromtype = "Float"; + jtype = type; + jfromtype = fromtype; + } + else if (!strcmp("vtkIntArray",data->ClassName) ) + { + type = "int"; + fromtype = "Int"; + jtype = type; + jfromtype = fromtype; + } + else if (!strcmp("vtkLongArray",data->ClassName) ) + { + type = "long"; + fromtype = "Long"; + jtype = type; + jfromtype = fromtype; + } + else if (!strcmp("vtkShortArray",data->ClassName) ) + { + type = "short"; + fromtype = "Short"; + jtype = type; + jfromtype = fromtype; + } + else if (!strcmp("vtkUnsignedCharArray",data->ClassName) ) + { + type = "unsigned char"; + fromtype = "UnsignedChar"; + jtype = "byte"; + jfromtype = "Byte"; + } + else if (!strcmp("vtkUnsignedIntArray",data->ClassName) ) + { + type = "unsigned int"; + fromtype = "UnsignedInt"; + jtype = "int"; + jfromtype = "Int"; + } + else if (!strcmp("vtkUnsignedLongArray",data->ClassName) ) + { + type = "unsigned long"; + fromtype = "UnsignedLong"; + jtype = "long"; + jfromtype = "Long"; + } + else if (!strcmp("vtkUnsignedShortArray",data->ClassName) ) + { + type = "unsigned short"; + fromtype = "UnsignedShort"; + jtype = "short"; + jfromtype = "Short"; + } + else + { + return; + } + + fprintf(fp,"// Array conversion routines\n"); + fprintf(fp,"extern \"C\" JNIEXPORT jarray JNICALL Java_vtk_%s_GetJavaArray_10(" + "JNIEnv *env, jobject obj)\n", + data->ClassName); + fprintf(fp,"{\n"); + fprintf(fp," %s *op;\n", data->ClassName); + fprintf(fp," %s *temp20;\n", type); + fprintf(fp," vtkIdType size;\n"); + fprintf(fp,"\n"); + fprintf(fp," op = (%s *)vtkJavaGetPointerFromObject(env,obj,(char *) \"%s\");\n", + data->ClassName, data->ClassName); + fprintf(fp," temp20 = static_cast<%s*>(op->GetVoidPointer(0));\n", type); + fprintf(fp," size = op->GetMaxId()+1;\n"); + fprintf(fp," return vtkJavaMakeJArrayOf%sFrom%s(env,temp20,size);\n", fromtype, fromtype); + fprintf(fp,"}\n"); + + fprintf(fp,"extern \"C\" JNIEXPORT void JNICALL Java_vtk_%s_SetJavaArray_10(" + "JNIEnv *env, jobject obj,j%sArray id0)\n", data->ClassName, jtype); + fprintf(fp,"{\n"); + fprintf(fp," %s *op;\n", data->ClassName); + fprintf(fp," %s *tempArray0;\n", type); + fprintf(fp," int length;\n"); + fprintf(fp," tempArray0 = (%s *)(env->Get%sArrayElements(id0,NULL));\n", type, jfromtype); + fprintf(fp," length = env->GetArrayLength(id0);\n"); + fprintf(fp," op = (%s *)vtkJavaGetPointerFromObject(env,obj,(char *) \"%s\");\n", + data->ClassName, data->ClassName); + fprintf(fp," op->SetNumberOfTuples(length/op->GetNumberOfComponents());\n"); + fprintf(fp," memcpy(op->GetVoidPointer(0), tempArray0, length*sizeof(%s));\n", type); + fprintf(fp," env->Release%sArrayElements(id0,(j%s *)tempArray0,0);\n", jfromtype, jtype); + fprintf(fp,"}\n"); +} + + +void outputFunction(FILE *fp, FileInfo *data) +{ + int i; + int args_ok = 1; + CurrentData = data; + + /* some functions will not get wrapped no matter what else */ + if (currentFunction->IsOperator || + currentFunction->ArrayFailure || + !currentFunction->IsPublic || + !currentFunction->Name) + { + return; + } + + /* NewInstance and SafeDownCast can not be wrapped because it is a + (non-virtual) method which returns a pointer of the same type as + the current pointer. Since all methods are virtual in Java, this + looks like polymorphic return type. */ + if (!strcmp("NewInstance",currentFunction->Name)) + { + return ; + } + + if (!strcmp("SafeDownCast",currentFunction->Name)) + { + return ; + } + + /* check to see if we can handle the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (currentFunction->ArgTypes[i] % 0x1000 == 0x9) args_ok = 0; + if ((currentFunction->ArgTypes[i] % 0x10) == 0x8) args_ok = 0; + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 != 0x3)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x109)&& + ((currentFunction->ArgTypes[i] % 0x1000)/0x100)) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x313) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x316) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31C) args_ok = 0; + } + if ((currentFunction->ReturnType % 0x10) == 0x8) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x9) args_ok = 0; + if (((currentFunction->ReturnType % 0x1000)/0x100 != 0x3)&& + (currentFunction->ReturnType % 0x1000 != 0x109)&& + ((currentFunction->ReturnType % 0x1000)/0x100)) args_ok = 0; + + + /* eliminate unsigned short * usigned int * etc */ + if (currentFunction->ReturnType % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x316) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31C) args_ok = 0; + + if (currentFunction->NumberOfArguments && + (currentFunction->ArgTypes[0] == 0x5000) + &&(currentFunction->NumberOfArguments != 1)) args_ok = 0; + + /* make sure we have all the info we need for array arguments in */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x3)&& + (currentFunction->ArgCounts[i] <= 0)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x309)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x303)) args_ok = 0; + } + + /* if we need a return type hint make sure we have one */ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x302: case 0x307: + case 0x304: case 0x305: case 0x306: + case 0x30A: case 0x30B: case 0x30C: case 0x30D: + case 0x313: + args_ok = currentFunction->HaveHint; + break; + } + + /* make sure it isn't a Delete or New function */ + if (!strcmp("Delete",currentFunction->Name) || + !strcmp("New",currentFunction->Name)) + { + args_ok = 0; + } + + /* handle DataReader SetBinaryInputString as a special case */ + if (!strcmp("SetBinaryInputString",currentFunction->Name) && + (!strcmp("vtkDataReader",data->ClassName) || + !strcmp("vtkStructuredGridReader",data->ClassName) || + !strcmp("vtkRectilinearGridReader",data->ClassName) || + !strcmp("vtkUnstructuredGridReader",data->ClassName) || + !strcmp("vtkStructuredPointsReader",data->ClassName) || + !strcmp("vtkPolyDataReader",data->ClassName))) + { + if(currentFunction->IsLegacy) + { + fprintf(fp,"#if !defined(VTK_LEGACY_REMOVE)\n"); + } + HandleDataReader(fp,data); + if(currentFunction->IsLegacy) + { + fprintf(fp,"#endif\n"); + } + wrappedFunctions[numberOfWrappedFunctions] = currentFunction; + numberOfWrappedFunctions++; + } + + + if (currentFunction->IsPublic && args_ok && + strcmp(data->ClassName,currentFunction->Name) && + strcmp(data->ClassName, currentFunction->Name + 1)) + { + /* make sure we haven't already done one of these */ + if (!DoneOne()) + { + fprintf(fp,"\n"); + + if(currentFunction->IsLegacy) + { + fprintf(fp,"#if !defined(VTK_LEGACY_REMOVE)\n"); + } + fprintf(fp,"extern \"C\" JNIEXPORT "); + return_result(fp); + fprintf(fp," JNICALL Java_vtk_%s_%s_1%i(JNIEnv *env, jobject obj", + data->ClassName,currentFunction->Name, numberOfWrappedFunctions); + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + fprintf(fp,","); + output_proto_vars(fp, i); + } + fprintf(fp,")\n{\n"); + + /* get the object pointer */ + fprintf(fp," %s *op;\n",data->ClassName); + /* process the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + output_temp(fp, i, currentFunction->ArgTypes[i], + currentFunction->ArgClasses[i], + currentFunction->ArgCounts[i]); + } + output_temp(fp, MAX_ARGS,currentFunction->ReturnType, + currentFunction->ReturnClass,0); + + /* now get the required args from the stack */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + get_args(fp, i); + } + + fprintf(fp,"\n op = (%s *)vtkJavaGetPointerFromObject(env,obj,(char *) \"%s\");\n", + data->ClassName,data->ClassName); + + + switch (currentFunction->ReturnType % 0x1000) + { + case 0x2: + fprintf(fp," op->%s(",currentFunction->Name); + break; + case 0x109: + fprintf(fp," temp%i = &(op)->%s(",MAX_ARGS, currentFunction->Name); + break; + default: + fprintf(fp," temp%i = (op)->%s(",MAX_ARGS, currentFunction->Name); + } + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + if (currentFunction->ArgTypes[i] % 0x1000 == 0x109) + { + fprintf(fp,"*(temp%i)",i); + } + else if (currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp,"vtkJavaVoidFunc,(void *)temp%i",i); + } + else + { + fprintf(fp,"temp%i",i); + } + } /* for */ + fprintf(fp,");\n"); + if (currentFunction->NumberOfArguments == 1 && currentFunction->ArgTypes[0] == 0x5000) + { + fprintf(fp," op->%sArgDelete(vtkJavaVoidFuncArgDelete);\n", + currentFunction->Name); + } + + /* now copy and release any arrays */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + copy_and_release_args(fp, i); + } + do_return(fp); + fprintf(fp,"}\n"); + if(currentFunction->IsLegacy) + { + fprintf(fp,"#endif\n"); + } + + wrappedFunctions[numberOfWrappedFunctions] = currentFunction; + numberOfWrappedFunctions++; + } /* isDone() */ + } /* isAbstract */ +} + +/* print the parsed structures */ +void vtkParseOutput(FILE *fp, FileInfo *data) +{ + int i; + + fprintf(fp,"// java wrapper for %s object\n//\n",data->ClassName); + fprintf(fp,"#define VTK_WRAPPING_CXX\n"); + if (strcmp("vtkObject",data->ClassName) != 0) + { + /* Block inclusion of full streams. */ + fprintf(fp,"#define VTK_STREAMS_FWD_ONLY\n"); + } + fprintf(fp,"#include \"vtkSystemIncludes.h\"\n"); + fprintf(fp,"#include \"%s.h\"\n",data->ClassName); + fprintf(fp,"#include \"vtkJavaUtil.h\"\n\n"); + + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp,"extern \"C\" JNIEXPORT void* %s_Typecast(void *op,char *dType);\n", + data->SuperClasses[i]); + } + + fprintf(fp,"\nextern \"C\" JNIEXPORT void* %s_Typecast(void *me,char *dType)\n{\n",data->ClassName); + if (data->NumberOfSuperClasses > 0) + { + fprintf(fp," void* res;\n"); + } + fprintf(fp," if (!strcmp(\"%s\",dType)) { return me; }\n", data->ClassName); + /* check our superclasses */ + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp," if ((res= %s_Typecast(me,dType)) != NULL)", + data->SuperClasses[i]); + fprintf(fp," { return res; }\n"); + } + fprintf(fp," return NULL;\n"); + fprintf(fp,"}\n\n"); + + HandleDataArray(fp, data); + + /* insert function handling code here */ + for (i = 0; i < data->NumberOfFunctions; i++) + { + currentFunction = data->Functions + i; + outputFunction(fp, data); + } + + if ((!data->NumberOfSuperClasses)&&(data->HasDelete)) + { + fprintf(fp,"\nextern \"C\" JNIEXPORT void JNICALL Java_vtk_%s_VTKDelete(JNIEnv *env,jobject obj)\n", + data->ClassName); + fprintf(fp,"{\n %s *op;\n",data->ClassName); + fprintf(fp," op = (%s *)vtkJavaGetPointerFromObject(env,obj,(char *) \"%s\");\n", + data->ClassName,data->ClassName); + fprintf(fp," vtkJavaDeleteObject(env,obj);\n"); + fprintf(fp," op->Delete();\n"); + fprintf(fp,"}\n"); + } + if (data->IsConcrete) + { + fprintf(fp,"\nextern \"C\" JNIEXPORT void JNICALL Java_vtk_%s_VTKInit(JNIEnv *env, jobject obj)", + data->ClassName); + fprintf(fp,"\n{"); + fprintf(fp,"\n %s *aNewOne = %s::New();",data->ClassName, data->ClassName); + fprintf(fp,"\n int id= vtkJavaRegisterNewObject(env,obj,(void *)aNewOne);"); + fprintf(fp,"\n vtkJavaRegisterCastFunction(env,obj,id,(void *)%s_Typecast);", data->ClassName); + fprintf(fp,"\n}\n"); + } + + fprintf(fp,"\nextern \"C\" JNIEXPORT void JNICALL Java_vtk_%s_VTKCastInit(JNIEnv *env, jobject obj)", + data->ClassName); + fprintf(fp,"\n{"); + fprintf(fp,"\n int id= vtkJavaGetId(env,obj);"); + fprintf(fp,"\n vtkJavaRegisterCastFunction(env,obj,id,(void *)%s_Typecast);", + data->ClassName); + fprintf(fp,"\n}\n"); + + /* for vtkRenderWindow we want to add a special method to support */ + /* native AWT rendering */ + if (!strcmp("vtkRenderWindow",data->ClassName)) + { + fprintf(fp,"\n#include \"vtkJavaAwt.h\"\n\n"); + } + + if (!strcmp("vtkObject",data->ClassName)) + { + /* Add the Print method to vtkObject. */ + fprintf(fp,"\nextern \"C\" JNIEXPORT jstring JNICALL Java_vtk_vtkObject_Print(JNIEnv *env,jobject obj)\n"); + fprintf(fp,"{\n vtkObject *op;\n"); + fprintf(fp," jstring tmp;\n\n"); + fprintf(fp," op = (vtkObject *)vtkJavaGetPointerFromObject(env,obj,(char *) \"vtkObject\");\n"); + + fprintf(fp," ostrstream vtkmsg_with_warning_C4701;\n"); + fprintf(fp," op->Print(vtkmsg_with_warning_C4701);\n"); + fprintf(fp," vtkmsg_with_warning_C4701.put('\\0');\n"); + fprintf(fp," tmp = vtkJavaMakeJavaString(env,vtkmsg_with_warning_C4701.str());\n"); + fprintf(fp," delete vtkmsg_with_warning_C4701.str();\n"); + + fprintf(fp," return tmp;\n"); + fprintf(fp,"}\n"); + /* Add the PrintRevisions method to vtkObject. */ + fprintf(fp,"\nextern \"C\" JNIEXPORT jstring JNICALL Java_vtk_vtkObject_PrintRevisions(JNIEnv *env,jobject obj)\n"); + fprintf(fp,"{\n vtkObject *op;\n"); + fprintf(fp," jstring tmp;\n\n"); + fprintf(fp," op = (vtkObject *)vtkJavaGetPointerFromObject(env,obj,(char *) \"vtkObject\");\n"); + + fprintf(fp," ostrstream vtkmsg_with_warning_C4701;\n"); + fprintf(fp," op->PrintRevisions(vtkmsg_with_warning_C4701);\n"); + fprintf(fp," vtkmsg_with_warning_C4701.put('\\0');\n"); + fprintf(fp," tmp = vtkJavaMakeJavaString(env,vtkmsg_with_warning_C4701.str());\n"); + fprintf(fp," delete vtkmsg_with_warning_C4701.str();\n"); + + fprintf(fp," return tmp;\n"); + fprintf(fp,"}\n"); + } + + if (!strcmp("vtkObject",data->ClassName)) + { + fprintf(fp,"\nextern \"C\" JNIEXPORT jint JNICALL Java_vtk_vtkObject_AddObserver(JNIEnv *env,jobject obj, jstring id0, jobject id1, jstring id2)\n"); + fprintf(fp,"{\n vtkObject *op;\n"); + + fprintf(fp," vtkJavaCommand *cbc = vtkJavaCommand::New();\n"); + fprintf(fp," cbc->AssignJavaVM(env);\n"); + fprintf(fp," cbc->SetGlobalRef(env->NewGlobalRef(id1));\n"); + fprintf(fp," cbc->SetMethodID(env->GetMethodID(env->GetObjectClass(id1),vtkJavaUTFToChar(env,id2),\"()V\"));\n"); + fprintf(fp," char *temp0;\n"); + fprintf(fp," temp0 = vtkJavaUTFToChar(env,id0);\n"); + fprintf(fp," op = (vtkObject *)vtkJavaGetPointerFromObject(env,obj,(char *) \"vtkObject\");\n"); + fprintf(fp," unsigned long temp20;\n"); + fprintf(fp," temp20 = op->AddObserver(temp0,cbc);\n"); + fprintf(fp," cbc->Delete();\n"); + fprintf(fp," return temp20;\n}\n"); + } +} + diff --git a/Wrapping/vtkWrapPython.c b/Wrapping/vtkWrapPython.c new file mode 100644 index 0000000..1f23b16 --- /dev/null +++ b/Wrapping/vtkWrapPython.c @@ -0,0 +1,1487 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWrapPython.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "vtkPython.h" +#include +#include +#include +#include +#include "vtkParse.h" +#include "vtkConfigure.h" + +int numberOfWrappedFunctions = 0; +FunctionInfo *wrappedFunctions[1000]; +extern FunctionInfo *currentFunction; + +static int class_has_new = 0; + +/* when the cpp file doesn't have enough info use the hint file */ +void use_hints(FILE *fp) +{ + int i; + + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: + fprintf(fp," return Py_BuildValue((char*)\""); + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"f"); + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%d]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + break; + case 0x307: + fprintf(fp," return Py_BuildValue((char*)\""); + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"d"); + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%d]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + break; + case 0x304: + case 0x30D: + fprintf(fp," return Py_BuildValue((char*)\""); + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"i"); + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%d]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + break; + case 0x30A: + fprintf(fp," return Py_BuildValue((char*)\""); +#ifdef VTK_USE_64BIT_IDS +#ifdef PY_LONG_LONG + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"L"); +#else + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"l"); +#endif +#else + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"i"); +#endif + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%d]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + break; + case 0x30B: case 0x30C: + fprintf(fp," return Py_BuildValue((char*)\""); +#ifdef PY_LONG_LONG + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"L"); +#else + for (i = 0; i < currentFunction->HintSize; i++) fprintf(fp,"l"); +#endif + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%d]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + break; + case 0x305: case 0x306: case 0x313: case 0x314: + case 0x31A: case 0x31B: case 0x31C: case 0x315: case 0x316: + break; + } + return; +} + + +void output_temp(FILE *fp, int i, int aType, char *Id, int aCount) +{ + /* handle VAR FUNCTIONS */ + if (aType == 0x5000) + { + fprintf(fp," PyObject *temp%i;\n",i); + return; + } + + if (((aType % 0x10) == 0x2)&&(!((aType % 0x1000)/0x100))) + { + return; + } + + /* for const * return types prototype with const */ + if ((i == MAX_ARGS)&&(aType % 0x2000 >= 0x1000)) + { + fprintf(fp," const "); + } + else + { + fprintf(fp," "); + } + + if ((aType % 0x100)/0x10 == 0x1) + { + fprintf(fp,"unsigned "); + } + + switch (aType % 0x10) + { + case 0x1: fprintf(fp,"float "); break; + case 0x7: fprintf(fp,"double "); break; + case 0x4: fprintf(fp,"int "); break; + case 0x5: fprintf(fp,"short "); break; + case 0x6: fprintf(fp,"long "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"char "); break; + case 0x9: + fprintf(fp,"%s ",Id); break; + case 0xA: fprintf(fp,"vtkIdType "); break; + case 0xB: fprintf(fp,"long long "); break; + case 0xC: fprintf(fp,"__int64 "); break; + case 0xD: fprintf(fp,"signed char "); break; + case 0x8: return; + } + + switch ((aType % 0x1000)/0x100) + { + case 0x1: fprintf(fp, " *"); break; /* act " &" */ + case 0x2: fprintf(fp, "&&"); break; + case 0x3: + if ((i == MAX_ARGS)||(aType % 0x10 == 0x9)||(aType % 0x1000 == 0x303) + ||(aType % 0x1000 == 0x302)) + { + fprintf(fp, " *"); + } + break; + case 0x4: fprintf(fp, "&*"); break; + case 0x5: fprintf(fp, "*&"); break; + case 0x7: fprintf(fp, "**"); break; + default: fprintf(fp," "); break; + } + fprintf(fp,"temp%i",i); + + /* handle arrays */ + if ((aType % 0x1000/0x100 == 0x3)&& + (i != MAX_ARGS)&&(aType % 0x10 != 0x9)&&(aType % 0x1000 != 0x303) + &&(aType % 0x1000 != 0x302)) + { + fprintf(fp,"[%i]",aCount); + } + + fprintf(fp,";\n"); + if (aType % 0x1000 == 0x302 && i != MAX_ARGS) + { + fprintf(fp," int size%d;\n",i); + } + if ((i != MAX_ARGS) && ((aType % 0x1000 == 0x309)||(aType % 0x1000 == 0x109))) + { + fprintf(fp," PyObject *tempH%d;\n",i); + } +} + +void do_return(FILE *fp) +{ + /* ignore void */ + if (((currentFunction->ReturnType % 0x10) == 0x2)&& + (!((currentFunction->ReturnType % 0x1000)/0x100))) + { + fprintf(fp," Py_INCREF(Py_None);\n"); + fprintf(fp," return Py_None;\n"); + return; + } + + switch (currentFunction->ReturnType % 0x1000) + { + case 0x303: + fprintf(fp," if (temp%i == NULL) {\n",MAX_ARGS); + fprintf(fp," Py_INCREF(Py_None);\n"); + fprintf(fp," return Py_None;\n }\n"); + fprintf(fp," else {\n"); + fprintf(fp," return PyString_FromString(temp%i);\n }\n",MAX_ARGS); + break; + case 0x109: + case 0x309: + { + fprintf(fp," return vtkPythonGetObjectFromPointer((vtkObjectBase *)temp%i);\n", + MAX_ARGS); + break; + } + + /* handle functions returning vectors */ + /* this is done by looking them up in a hint file */ + case 0x301: case 0x307: case 0x30A: case 0x30B: case 0x30C: case 0x30D: + case 0x304: case 0x305: case 0x306: + use_hints(fp); + break; + case 0x302: + { + fprintf(fp," if (temp%i == NULL)\n {\n",MAX_ARGS); + fprintf(fp," Py_INCREF(Py_None);\n"); + fprintf(fp," return Py_None;\n }\n"); + fprintf(fp," else\n {\n"); + fprintf(fp," return PyString_FromString(vtkPythonManglePointer(temp%i,\"void_p\"));\n }\n", + MAX_ARGS); + break; + } + case 0x1: + case 0x7: + { + fprintf(fp," return PyFloat_FromDouble(temp%i);\n", + MAX_ARGS); + break; + } + case 0x13: + case 0x14: + case 0x15: + case 0x4: + case 0x5: + case 0x6: + case 0xD: + { + fprintf(fp," return PyInt_FromLong(temp%i);\n", MAX_ARGS); + break; + } + case 0x16: + { +#if (PY_VERSION_HEX >= 0x02020000) + fprintf(fp," return PyLong_FromUnsignedLong(temp%i);\n", + MAX_ARGS); +#else + fprintf(fp," return PyInt_FromLong((long)temp%i);\n", + MAX_ARGS); +#endif + break; + } +#if defined(VTK_USE_64BIT_IDS) && defined(PY_LONG_LONG) && (VTK_SIZEOF_LONG != VTK_SIZEOF_ID_TYPE) + case 0xA: + { + fprintf(fp," return PyLong_FromLongLong(temp%i);\n", MAX_ARGS); + break; + } + case 0x1A: + { + fprintf(fp," return PyLong_FromUnsignedLongLong(temp%i);\n", + MAX_ARGS); + break; + } +#else + case 0xA: + { + fprintf(fp," return PyInt_FromLong((long)temp%i);\n", MAX_ARGS); + break; + } + case 0x1A: + { +#if (PY_VERSION_HEX >= 0x02020000) + fprintf(fp," return PyLong_FromUnsignedLong((unsigned long)temp%i);\n", + MAX_ARGS); +#else + fprintf(fp," return PyInt_FromLong((long)temp%i);\n", + MAX_ARGS); +#endif + break; + } +#endif +#if defined(VTK_SIZEOF_LONG_LONG) +# if defined(PY_LONG_LONG) && (VTK_SIZEOF_LONG != VTK_SIZEOF_LONG_LONG) + case 0xB: + { + fprintf(fp," return PyLong_FromLongLong(temp%i);\n", MAX_ARGS); + break; + } + case 0x1B: + { + fprintf(fp," return PyLong_FromUnsignedLongLong(temp%i);\n", + MAX_ARGS); + break; + } +# else + case 0xB: + { + fprintf(fp," return PyLong_FromLong(temp%i);\n", MAX_ARGS); + break; + } + case 0x1B: + { + fprintf(fp," return PyLong_FromUnsignedLong(temp%i);\n", + MAX_ARGS); + break; + } +# endif +#endif +#if defined(VTK_SIZEOF___INT64) +# if defined(PY_LONG_LONG) && (VTK_SIZEOF_LONG != VTK_SIZEOF___INT64) + case 0xC: + { + fprintf(fp," return PyLong_FromLongLong(temp%i);\n", MAX_ARGS); + break; + } + case 0x1C: + { + fprintf(fp," return PyLong_FromUnsignedLongLong(temp%i);\n", + MAX_ARGS); + break; + } +# else + case 0xC: + { + fprintf(fp," return PyLong_FromLong(temp%i);\n", MAX_ARGS); + break; + } + case 0x1C: + { + fprintf(fp," return PyLong_FromUnsignedLong(temp%i);\n", + MAX_ARGS); + break; + } +# endif +#endif + case 0x3: + { + fprintf(fp," return PyString_FromStringAndSize((char *)&temp%i,1);\n", + MAX_ARGS); + break; + } + } +} + +char *get_format_string() +{ + static char result[1024]; + int currPos = 0; + int argtype; + int i, j; + + if (currentFunction->ArgTypes[0] == 0x5000) + { + result[currPos] = 'O'; currPos++; + result[currPos] = '\0'; + return result; + } + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + argtype = currentFunction->ArgTypes[i] % 0x1000; + + switch (argtype) + { + case 0x301: + result[currPos] = '('; currPos++; + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + result[currPos] = 'f'; currPos++; + } + result[currPos] = ')'; currPos++; + break; + case 0x307: + result[currPos] = '('; currPos++; + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + result[currPos] = 'd'; currPos++; + } + result[currPos] = ')'; currPos++; + break; + case 0x304: + result[currPos] = '('; currPos++; + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + result[currPos] = 'i'; currPos++; + } + result[currPos] = ')'; currPos++; + break; + case 0x30A: + result[currPos] = '('; currPos++; + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { +#ifdef VTK_USE_64BIT_IDS +#ifdef PY_LONG_LONG + result[currPos] = 'L'; currPos++; +#else + result[currPos] = 'l'; currPos++; +#endif +#else + result[currPos] = 'i'; currPos++; +#endif + } + result[currPos] = ')'; currPos++; + break; + case 0x30B: case 0x30C: + result[currPos] = '('; currPos++; + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { +#ifdef PY_LONG_LONG + result[currPos] = 'L'; currPos++; +#else + result[currPos] = 'l'; currPos++; +#endif + } + result[currPos] = ')'; currPos++; + break; + case 0x109: + case 0x309: result[currPos] = 'O'; currPos++; break; + case 0x303: result[currPos] = 'z'; currPos++; break; + case 0x302: result[currPos] = 's'; currPos++; + result[currPos] = '#'; currPos++; break; + case 0x1: result[currPos] = 'f'; currPos++; break; + case 0x7: result[currPos] = 'd'; currPos++; break; + case 0x14: + case 0x4: result[currPos] = 'i'; currPos++; break; + case 0x15: + case 0x5: result[currPos] = 'h'; currPos++; break; + case 0x16: + case 0x6: result[currPos] = 'l'; currPos++; break; + case 0x1A: + case 0xA: +#ifdef VTK_USE_64BIT_IDS +#ifdef PY_LONG_LONG + result[currPos] = 'L'; currPos++; break; +#else + result[currPos] = 'l'; currPos++; break; +#endif +#else + result[currPos] = 'i'; currPos++; break; +#endif +#ifdef PY_LONG_LONG + case 0xB: case 0xC: + result[currPos] = 'L'; currPos++; break; +#else + case 0xB: case 0xC: + result[currPos] = 'l'; currPos++; break; +#endif + case 0xD: result[currPos] = 'i'; currPos++; break; + case 0x3: result[currPos] = 'c'; currPos++; break; + case 0x13: result[currPos] = 'b'; currPos++; break; + } + } + + result[currPos] = '\0'; + return result; +} + +static void add_to_sig(char *sig, char *add, int *i) +{ + strcpy(&sig[*i],add); + *i += (int)strlen(add); +} + +void get_python_signature() +{ + static char result[1024]; + int currPos = 0; + int argtype; + int i, j; + + /* print out the name of the method */ + add_to_sig(result,"V.",&currPos); + add_to_sig(result,currentFunction->Name,&currPos); + + /* print the arg list */ + add_to_sig(result,"(",&currPos); + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (currentFunction->ArgTypes[i] == 0x5000) + { + add_to_sig(result,"function",&currPos); + } + + argtype = currentFunction->ArgTypes[i] % 0x1000; + + if (i != 0) + { + add_to_sig(result,", ",&currPos); + } + + switch (argtype) + { + case 0x301: + case 0x307: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } + add_to_sig(result,"float",&currPos); + } + add_to_sig(result,")",&currPos); + break; + case 0x304: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } + add_to_sig(result,"int",&currPos); + } + add_to_sig(result,")",&currPos); + break; + case 0x30A: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } +#if defined(VTK_USE_64BIT_IDS) && (VTK_SIZEOF_LONG != VTK_SIZEOF_ID_TYPE) + add_to_sig(result,"long",&currPos); +#else + add_to_sig(result,"int",&currPos); +#endif + } + add_to_sig(result,")",&currPos); + break; + case 0x30B: case 0x30C: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } + add_to_sig(result,"long",&currPos); + } + add_to_sig(result,")",&currPos); + break; + case 0x109: + case 0x309: add_to_sig(result,currentFunction->ArgClasses[i],&currPos); break; + case 0x302: + case 0x303: add_to_sig(result,"string",&currPos); break; + case 0x1: + case 0x7: add_to_sig(result,"float",&currPos); break; + case 0xD: + case 0xA: + case 0x1B: + case 0xB: + case 0x1C: + case 0xC: + case 0x14: + case 0x4: + case 0x15: + case 0x5: + case 0x16: + case 0x6: add_to_sig(result,"int",&currPos); break; + case 0x3: add_to_sig(result,"char",&currPos); break; + case 0x13: add_to_sig(result,"int",&currPos); break; + } + } + + add_to_sig(result,")",&currPos); + + /* if this is a void method, we are finished */ + /* otherwise, print "->" and the return type */ + if ((!((currentFunction->ReturnType % 0x10) == 0x2)) || + ((currentFunction->ReturnType % 0x1000)/0x100)) + { + add_to_sig(result," -> ",&currPos); + + switch (currentFunction->ReturnType % 0x1000) + { + case 0x302: + case 0x303: add_to_sig(result,"string",&currPos); break; + case 0x109: + case 0x309: add_to_sig(result,currentFunction->ReturnClass,&currPos); break; + case 0x301: + case 0x307: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->HintSize; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } + add_to_sig(result,"float",&currPos); + } + add_to_sig(result,")",&currPos); + break; + case 0x304: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->HintSize; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } + add_to_sig(result,"int",&currPos); + } + add_to_sig(result,")",&currPos); + break; + case 0x30A: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->HintSize; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } +#if defined(VTK_USE_64BIT_IDS) && (VTK_SIZEOF_LONG != VTK_SIZEOF_ID_TYPE) + add_to_sig(result,"long",&currPos); +#else + add_to_sig(result,"int",&currPos); +#endif + } + add_to_sig(result,")",&currPos); + break; + case 0x30B: case 0x30C: + add_to_sig(result,"(",&currPos); + for (j = 0; j < currentFunction->HintSize; j++) + { + if (j != 0) + { + add_to_sig(result,", ",&currPos); + } + add_to_sig(result,"long",&currPos); + } + add_to_sig(result,")",&currPos); + break; + case 0x1: + case 0x7: add_to_sig(result,"float",&currPos); break; + case 0xA: + case 0xB: + case 0xC: + case 0xD: + case 0x1B: + case 0x1C: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x4: + case 0x5: + case 0x6: add_to_sig(result,"int",&currPos); break; + case 0x3: add_to_sig(result,"char",&currPos); break; + } + } + + if (currentFunction->Signature) + { + add_to_sig(result,"\\nC++: ",&currPos); + add_to_sig(result,currentFunction->Signature,&currPos); + } + + currentFunction->Signature = realloc(currentFunction->Signature,currPos+1); + strcpy(currentFunction->Signature,result); + /* fprintf(stderr,"%s\n",currentFunction->Signature); */ +} + +/* convert special characters in a string into their escape codes, + so that the string can be quoted in a source file (the specified + maxlen must be at least 32 chars)*/ +static const char *quote_string(const char *comment, int maxlen) +{ + static char *result = 0; + static int oldmaxlen = 0; + int i, j, n; + + if (maxlen > oldmaxlen) + { + if (result) + { + free(result); + } + result = (char *)malloc(maxlen); + oldmaxlen = maxlen; + } + + if (comment == NULL) + { + return ""; + } + + j = 0; + + n = (int)strlen(comment); + for (i = 0; i < n; i++) + { + if (comment[i] == '\"') + { + strcpy(&result[j],"\\\""); + j += 2; + } + else if (comment[i] == '\\') + { + strcpy(&result[j],"\\\\"); + j += 2; + } + else if (comment[i] == '\n') + { + strcpy(&result[j],"\\n"); + j += 2; + } + else if (isprint(comment[i])) + { + result[j] = comment[i]; + j++; + } + else + { + sprintf(&result[j],"\\%3.3o",comment[i]); + j += 4; + } + if (j >= maxlen - 21) + { + sprintf(&result[j]," ...\\n [Truncated]\\n"); + j += (int)strlen(" ...\\n [Truncated]\\n"); + break; + } + } + result[j] = '\0'; + + return result; +} + + +void outputFunction2(FILE *fp, FileInfo *data) +{ + int i, j, k, is_static, is_vtkobject, fnum, occ, backnum, goto_used; + FunctionInfo *theFunc; + FunctionInfo *backFunc; + + is_vtkobject = ((strcmp(data->ClassName,"vtkObjectBase") == 0) || + (data->NumberOfSuperClasses != 0)); + + /* create a python-type signature for each method (for use in docstring) */ + for (fnum = 0; fnum < numberOfWrappedFunctions; fnum++) + { + theFunc = wrappedFunctions[fnum]; + currentFunction = theFunc; + get_python_signature(); + } + + /* create external type declarations for all object + return types */ + for (fnum = 0; fnum < numberOfWrappedFunctions; fnum++) + { + theFunc = wrappedFunctions[fnum]; + currentFunction = theFunc; + + /* check for object return types */ + if ((theFunc->ReturnType % 0x1000 == 0x309)|| + (theFunc->ReturnType % 0x1000 == 0x109)) + { + /* check that we haven't done this type (no duplicate declarations) */ + for (backnum = fnum-1; backnum >= 0; backnum--) + { + backFunc = wrappedFunctions[backnum]; + if (((backFunc->ReturnType % 0x1000 == 0x309)|| + (backFunc->ReturnType % 0x1000 == 0x109)) && + (strcmp(theFunc->ReturnClass,backFunc->ReturnClass) == 0)) + { + break; + } + } + } + } + + /* for each function in the array */ + for (fnum = 0; fnum < numberOfWrappedFunctions; fnum++) + { + /* make sure we haven't already done one of these */ + theFunc = wrappedFunctions[fnum]; + currentFunction = theFunc; + + if (theFunc->Name) + { + fprintf(fp,"\n"); + + /* check whether all signatures are static methods */ + is_static = 1; + for (occ = fnum; occ < numberOfWrappedFunctions; occ++) + { + /* is it the same name */ + if (wrappedFunctions[occ]->Name && + !strcmp(theFunc->Name,wrappedFunctions[occ]->Name)) + { + /* check for static methods */ + if (((wrappedFunctions[occ]->ReturnType/0x1000) & 0x2) != 0x2) + { + is_static = 0; + } + } + } + + if(currentFunction->IsLegacy) + { + fprintf(fp,"#if !defined(VTK_LEGACY_REMOVE)\n"); + } + fprintf(fp,"static PyObject *Py%s_%s(PyObject *%s, PyObject *args)\n", + data->ClassName,currentFunction->Name, + (is_static ? "" : "self")); + fprintf(fp,"{\n"); + + /* find all occurances of this method */ + for (occ = fnum; occ < numberOfWrappedFunctions; occ++) + { + goto_used = 0; + is_static = 0; + + /* is it the same name */ + if (wrappedFunctions[occ]->Name && + !strcmp(theFunc->Name,wrappedFunctions[occ]->Name)) + { + /* check for static methods */ + if (((wrappedFunctions[occ]->ReturnType/0x1000) & 0x2) == 0x2) + { + is_static = 1; + } + + fprintf(fp," /* handle an occurrence */\n {\n"); + /* declare the variables */ + if (!is_static) + { + if (is_vtkobject) + { + fprintf(fp," %s *op;\n\n",data->ClassName); + } + else + { + fprintf(fp," %s *op = (%s *)((PyVTKSpecialObject *)self)->vtk_ptr;\n\n",data->ClassName,data->ClassName); + } + } + + currentFunction = wrappedFunctions[occ]; + /* process the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + output_temp(fp, i, currentFunction->ArgTypes[i], + currentFunction->ArgClasses[i], + currentFunction->ArgCounts[i]); + } + output_temp(fp, MAX_ARGS,currentFunction->ReturnType, + currentFunction->ReturnClass,0); + /* don't clear error first time around */ + if (occ != fnum) + { + fprintf(fp," PyErr_Clear();\n"); + } + if (is_static || !is_vtkobject) + { + fprintf(fp," if ((PyArg_ParseTuple(args, (char*)\"%s\"", + get_format_string()); + } + else + { + fprintf(fp," if ((op = (%s *)PyArg_VTKParseTuple(self, args, (char*)\"%s\"", + data->ClassName,get_format_string()); + } + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if ((currentFunction->ArgTypes[i] % 0x1000 == 0x309)|| + (currentFunction->ArgTypes[i] % 0x1000 == 0x109)) + { + fprintf(fp,", &tempH%d",i); + } + else if (currentFunction->ArgTypes[i] % 0x1000 == 0x302) + { + fprintf(fp,", &temp%d, &size%d",i,i); + } + else + { + if (currentFunction->ArgCounts[i]) + { + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + fprintf(fp,", temp%d + %d",i,j); + } + } + else + { + fprintf(fp,", &temp%d",i); + } + } + } + fprintf(fp,")))\n {\n"); + + /* lookup and required objects */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if ((currentFunction->ArgTypes[i] % 0x1000 == 0x309)|| + (currentFunction->ArgTypes[i] % 0x1000 == 0x109)) + { + fprintf(fp," temp%d = (%s *)vtkPythonGetPointerFromObject(tempH%d,(char*)\"%s\");\n", + i, currentFunction->ArgClasses[i], i, + currentFunction->ArgClasses[i]); + fprintf(fp," if (!temp%d && tempH%d != Py_None) goto break%d;\n",i,i,occ); + goto_used = 1; + } + } + + /* make sure passed method is callable for VAR functions */ + if (currentFunction->NumberOfArguments == 0x1 && + currentFunction->ArgTypes[0] == 0x5000) + { + fprintf(fp," if (!PyCallable_Check(temp0) && temp0 != Py_None)\n"); + fprintf(fp," {\n PyErr_SetString(PyExc_ValueError,\"vtk callback method passed to %s in %s was not callable.\");\n", + currentFunction->Name,data->ClassName); + fprintf(fp," return NULL;\n }\n"); + fprintf(fp," Py_INCREF(temp0);\n"); + } + + /* check for void pointers and pass appropriate info*/ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (currentFunction->ArgTypes[i] % 0x1000 == 0x302) + { + fprintf(fp," temp%i = vtkPythonUnmanglePointer((char *)temp%i,&size%i,(char*)\"%s\");\n",i,i,i,"void_p"); + fprintf(fp," if (size%i == -1) {\n PyErr_SetString(PyExc_ValueError,\"mangled pointer to %s in %s was of incorrect type.\");\n", + i,currentFunction->Name,data->ClassName); + fprintf(fp," return NULL;\n }\n"); + fprintf(fp," else if (size%i == -2) {\n PyErr_SetString(PyExc_ValueError,\"mangled pointer to %s in %s was poorly formed.\");\n", + i,currentFunction->Name,data->ClassName); + fprintf(fp," return NULL;\n }\n"); + } + } + + for (k = 0; k < (2 - (is_static || !is_vtkobject)); k++) + { + char methodname[256]; + if (k == 0) + { + if (is_static) + { + fprintf(fp," {\n"); + sprintf(methodname,"%s::%s", + data->ClassName,currentFunction->Name); + } + else if (!is_vtkobject) + { + fprintf(fp," {\n"); + sprintf(methodname,"op->%s",currentFunction->Name); + } + else + { + if (currentFunction->IsPureVirtual) + { + fprintf(fp," if (PyVTKClass_Check(self))\n {\n"); + fprintf(fp," PyErr_SetString(PyExc_TypeError,\"pure virtual method call\");\n"); + fprintf(fp," return NULL;\n }\n"); + continue; + } + else + { + fprintf(fp," if (PyVTKClass_Check(self))\n {\n"); + sprintf(methodname,"op->%s::%s", + data->ClassName,currentFunction->Name); + } + } + } + else + { + fprintf(fp," else\n {\n"); + sprintf(methodname,"op->%s",currentFunction->Name); + } + + switch (currentFunction->ReturnType % 0x1000) + { + case 0x2: + fprintf(fp," %s(",methodname); + break; + case 0x109: + fprintf(fp," temp%i = &%s(",MAX_ARGS,methodname); + break; + default: + fprintf(fp," temp%i = %s(",MAX_ARGS,methodname); + } + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + if (currentFunction->ArgTypes[i] % 0x1000 == 0x109) + { + fprintf(fp,"*(temp%i)",i); + } + else if (currentFunction->NumberOfArguments == 1 + && currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp,"((temp0 != Py_None) ? vtkPythonVoidFunc : NULL),(void *)temp%i",i); + } + else + { + fprintf(fp,"temp%i",i); + } + } + fprintf(fp,");\n"); + + if (currentFunction->NumberOfArguments == 1 + && currentFunction->ArgTypes[0] == 0x5000) + { + fprintf(fp," %sArgDelete(vtkPythonVoidFuncArgDelete);\n", + methodname); + } + fprintf(fp," }\n"); + } + + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (currentFunction->ArgCounts[i] && /* array */ + currentFunction->ArgTypes[i] % 0x10 != 0 && /* not a special type */ + currentFunction->ArgTypes[i] % 0x10 != 0x9 && /* not class pointer */ + currentFunction->ArgTypes[i] % 0x10 != 0x8 && + currentFunction->ArgTypes[i] % 0x10 != 0x2 && /* not void pointer */ + (currentFunction->ArgTypes[i] % 0x2000 < 0x1000)) /* not const */ + { + fprintf(fp," if (vtkPythonCheckArray(args,%d,temp%d,%d)) {\n" + " return 0;\n" + " }\n", i, i, currentFunction->ArgCounts[i]); + } + } + do_return(fp); + fprintf(fp," }\n }\n"); + if (goto_used) + { + fprintf(fp," break%d:\n",occ); + } + } + } + fprintf(fp," return NULL;\n}\n"); + if(currentFunction->IsLegacy) + { + fprintf(fp,"#endif\n"); + } + fprintf(fp,"\n"); + + /* clear all occurances of this method from further consideration */ + for (occ = fnum + 1; occ < numberOfWrappedFunctions; occ++) + { + /* is it the same name */ + if (wrappedFunctions[occ]->Name && + !strcmp(theFunc->Name,wrappedFunctions[occ]->Name)) + { + int siglen = (int)strlen(wrappedFunctions[fnum]->Signature); + /* memory leak here but ... */ + wrappedFunctions[occ]->Name = NULL; + wrappedFunctions[fnum]->Signature = (char *) + realloc(wrappedFunctions[fnum]->Signature,siglen+3+ + strlen(wrappedFunctions[occ]->Signature)); + strcpy(&wrappedFunctions[fnum]->Signature[siglen],"\\n"); + strcpy(&wrappedFunctions[fnum]->Signature[siglen+2], + wrappedFunctions[occ]->Signature); + } + } + } /* is this method non NULL */ + } /* loop over all methods */ + + /* output the method table */ + /* for each function in the array */ + fprintf(fp,"static PyMethodDef Py%sMethods[] = {\n",data->ClassName); + + for (fnum = 0; fnum < numberOfWrappedFunctions; fnum++) + { + if(wrappedFunctions[fnum]->IsLegacy) + { + fprintf(fp,"#if !defined(VTK_LEGACY_REMOVE)\n"); + } + if (wrappedFunctions[fnum]->Name) + { + fprintf(fp," {(char*)\"%s\", (PyCFunction)Py%s_%s, 1,\n (char*)\"%s\\n\\n%s\"},\n", + wrappedFunctions[fnum]->Name, data->ClassName, + wrappedFunctions[fnum]->Name, wrappedFunctions[fnum]->Signature, + quote_string(wrappedFunctions[fnum]->Comment,1000)); + } + if(wrappedFunctions[fnum]->IsLegacy) + { + fprintf(fp,"#endif\n"); + } + } + + if (!strcmp("vtkObject",data->ClassName)) + { + fprintf(fp," {(char*)\"AddObserver\", (PyCFunction)Py%s_AddObserver, 1,\n (char*)\"V.AddObserver(int, function) -> int\\n\\n Add an event callback function(vtkObject, int) for an event type.\\n Returns a handle that can be used with RemoveEvent(int).\"},\n", data->ClassName); + } + else if (!strcmp("vtkObjectBase",data->ClassName)) + { + fprintf(fp," {(char*)\"GetAddressAsString\", (PyCFunction)Py%s_GetAddressAsString, 1,\n (char*)\"V.GetAddressAsString(string) -> string\\n\\n Get address of C++ object in format 'Addr=%%p' after casting to\\n the specified type. You can get the same information from V.__this__.\"},\n", data->ClassName); + fprintf(fp," {(char*)\"PrintRevisions\", (PyCFunction)Py%s_PrintRevisions, 1,\n (char*)\"V.PrintRevisions() -> string\\n\\n Prints the .cxx file CVS revisions of the classes in the\\n object's inheritance chain.\"},\n", data->ClassName); + } + + fprintf(fp," {NULL, NULL, 0, NULL}\n};\n\n"); +} + + + +void outputFunction(FILE *fp, FileInfo *data) +{ + int i; + int args_ok = 1; + + fp = fp; + /* some functions will not get wrapped no matter what else, + and some really common functions will appear only in vtkObjectPython */ + if (currentFunction->IsOperator || + currentFunction->ArrayFailure || + !currentFunction->IsPublic || + !currentFunction->Name) + { + return; + } + + /* check to see if we can handle the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (currentFunction->ArgTypes[i] % 0x1000 == 9) args_ok = 0; + if ((currentFunction->ArgTypes[i] % 0x10) == 8) args_ok = 0; + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 != 0x3)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x109)&& + ((currentFunction->ArgTypes[i] % 0x1000)/0x100)) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x313) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x31C) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ArgTypes[i] % 0x1000 == 0x316) args_ok = 0; + } + if ((currentFunction->ReturnType % 0x10) == 0x8) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x9) args_ok = 0; + if (((currentFunction->ReturnType % 0x1000)/0x100 != 0x3)&& + (currentFunction->ReturnType % 0x1000 != 0x109)&& + ((currentFunction->ReturnType % 0x1000)/0x100)) args_ok = 0; + + + /* eliminate unsigned char * and unsigned short * */ + if (currentFunction->ReturnType % 0x1000 == 0x313) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x314) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31A) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31B) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x31C) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x315) args_ok = 0; + if (currentFunction->ReturnType % 0x1000 == 0x316) args_ok = 0; + + if (currentFunction->NumberOfArguments && + (currentFunction->ArgTypes[0] == 0x5000) + &&(currentFunction->NumberOfArguments != 0x1)) args_ok = 0; + + /* make sure we have all the info we need for array arguments in */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (((currentFunction->ArgTypes[i] % 0x1000)/0x100 == 0x3)&& + (currentFunction->ArgCounts[i] <= 0)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x309)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x303)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x302)) args_ok = 0; + } + + /* if we need a return type hint make sure we have one */ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x307: case 0x30A: case 0x30B: case 0x30C: case 0x30D: + case 0x304: case 0x305: case 0x306: + args_ok = currentFunction->HaveHint; + break; + } + + /* make sure it isn't a Delete or New function */ + if (!strcmp("Delete",currentFunction->Name) || + !strcmp("New",currentFunction->Name)) + { + args_ok = 0; + } + + /* check for New() function */ + if (!strcmp("New",currentFunction->Name) && + currentFunction->NumberOfArguments == 0) + { + class_has_new = 1; + } + + if (currentFunction->IsPublic && args_ok && + strcmp(data->ClassName,currentFunction->Name) && + strcmp(data->ClassName, currentFunction->Name + 1)) + { + wrappedFunctions[numberOfWrappedFunctions] = currentFunction; + numberOfWrappedFunctions++; + } +} + +static void create_class_doc(FILE *fp, FileInfo *data) +{ + const char *text; + int i, n; + char temp[500]; + + if (data->NameComment) + { + text = data->NameComment; + while (*text == ' ') + { + text++; + } + fprintf(fp," (char*)\"%s\\n\\n\",\n",quote_string(text,500)); + } + else + { + fprintf(fp," (char*)\"%s - no description provided.\\n\\n\",\n", + quote_string(data->ClassName,500)); + } + + if (data->NumberOfSuperClasses > 0) + { + fprintf(fp," \"Super Class:\\n\\n %s\\n\\n\",\n", + quote_string(data->SuperClasses[0],500)); + } + + if (data->Description) + { + n = (int)((strlen(data->Description) + 400-1)/400); + for (i = 0; i < n; i++) + { + strncpy(temp, &data->Description[400*i], 400); + temp[400] = '\0'; + if (i < n-1) + { + fprintf(fp," (char*)\"%s\",\n",quote_string(temp,500)); + } + else + { /* just for the last time */ + fprintf(fp," (char*)\"%s\\n\",\n",quote_string(temp,500)); + } + } + } + else + { + fprintf(fp," (char*)\"%s\\n\",\n", "None provided.\\n"); + } + + if (data->Caveats) + { + fprintf(fp," \"Caveats:\\n\\n"); + fprintf(fp,"%s\\n\",\n", quote_string(data->Caveats,500)); + } + + if (data->SeeAlso) + { + char *dup, *tok; + + fprintf(fp," \"See Also:\\n\\n"); + dup = strdup(data->SeeAlso); + tok = strtok(dup," "); + while (tok) + { + fprintf(fp," %s",quote_string(tok,120)); + tok = strtok(NULL," "); + } + free(dup); + fprintf(fp,"\\n\",\n"); + } + + fprintf(fp," NULL\n"); +} + +/* print the parsed structures */ +void vtkParseOutput(FILE *fp, FileInfo *data) +{ + int i; + + fprintf(fp,"// python wrapper for %s object\n//\n",data->ClassName); + fprintf(fp,"#define VTK_WRAPPING_CXX\n"); + if (strcmp("vtkObjectBase",data->ClassName) != 0) + { + /* Block inclusion of full streams. */ + fprintf(fp,"#define VTK_STREAMS_FWD_ONLY\n"); + } + #if !defined(__APPLE__) + fprintf(fp,"#include \"vtkPython.h\"\n"); + fprintf(fp,"#undef _XOPEN_SOURCE /* Conflicts with standards.h. */\n"); + fprintf(fp,"#undef _THREAD_SAFE /* Conflicts with pthread.h. */\n"); + fprintf(fp,"#include \"vtkPythonUtil.h\"\n"); + #endif + fprintf(fp,"#include \"%s.h\"\n",data->ClassName); + #if defined(__APPLE__) + fprintf(fp,"#include \"vtkPythonUtil.h\"\n"); + #endif + + fprintf(fp,"#if defined(WIN32)\n"); + fprintf(fp,"extern \"C\" { __declspec( dllexport ) PyObject *PyVTKClass_%sNew(char *); }\n", + data->ClassName); + fprintf(fp,"#else\n"); + fprintf(fp,"extern \"C\" { PyObject *PyVTKClass_%sNew(char *); }\n", + data->ClassName); + fprintf(fp,"#endif\n\n"); + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp,"extern \"C\" { PyObject *PyVTKClass_%sNew(char *); }\n", + data->SuperClasses[i]); + } + + if (!strcmp("vtkObject",data->ClassName)) + { + /* Add the AddObserver method to vtkObject. */ + fprintf(fp,"static PyObject *PyvtkObject_AddObserver(PyObject *self, PyObject *args)\n"); + fprintf(fp,"{\n"); + fprintf(fp," vtkObject *op;\n"); + fprintf(fp," char *temp0;\n"); + fprintf(fp," PyObject *temp1;\n"); + fprintf(fp," float temp2;\n"); + fprintf(fp," unsigned long temp20 = 0;\n"); + fprintf(fp," if ((op = (vtkObject *)PyArg_VTKParseTuple(self, args, (char*)\"zO\", &temp0, &temp1)))\n"); + fprintf(fp," {\n"); + fprintf(fp," if (!PyCallable_Check(temp1) && temp1 != Py_None)\n"); + fprintf(fp," {\n"); + fprintf(fp," PyErr_SetString(PyExc_ValueError,\"vtk callback method passed to AddObserver was not callable.\");\n"); + fprintf(fp," return NULL;\n"); + fprintf(fp," }\n"); + fprintf(fp," Py_INCREF(temp1);\n"); + fprintf(fp," vtkPythonCommand *cbc = vtkPythonCommand::New();\n"); + fprintf(fp," cbc->SetObject(temp1);\n"); + fprintf(fp," temp20 = op->AddObserver(temp0,cbc);\n"); + fprintf(fp," cbc->Delete();\n"); + fprintf(fp," return PyInt_FromLong((long)temp20);\n"); + fprintf(fp," }\n"); + fprintf(fp," PyErr_Clear();\n"); + fprintf(fp," if ((op = (vtkObject *)PyArg_VTKParseTuple(self, args, (char*)\"zOf\", &temp0, &temp1, &temp2)))\n"); + fprintf(fp," {\n"); + fprintf(fp," if (!PyCallable_Check(temp1) && temp1 != Py_None)\n"); + fprintf(fp," {\n"); + fprintf(fp," PyErr_SetString(PyExc_ValueError,\"vtk callback method passed to AddObserver was not callable.\");\n"); + fprintf(fp," return NULL;\n"); + fprintf(fp," }\n"); + fprintf(fp," Py_INCREF(temp1);\n"); + fprintf(fp," vtkPythonCommand *cbc = vtkPythonCommand::New();\n"); + fprintf(fp," cbc->SetObject(temp1);\n"); + fprintf(fp," temp20 = op->AddObserver(temp0,cbc,temp2);\n"); + fprintf(fp," cbc->Delete();\n"); + fprintf(fp," return PyInt_FromLong((long)temp20);\n"); + fprintf(fp," }\n"); + fprintf(fp," return NULL;\n"); + fprintf(fp,"}\n\n"); + } + + if (!strcmp("vtkObjectBase",data->ClassName)) + { + /* while we are at it spit out the GetStringFromObject method */ + fprintf(fp,"PyObject *PyvtkObjectBase_GetAddressAsString(PyObject *self, PyObject *args)\n"); + fprintf(fp,"{\n"); + + /* declare the variables */ + fprintf(fp," %s *op;\n",data->ClassName); + + /* handle unbound method call if 'self' is a PyVTKClass */ + fprintf(fp," char *typecast;\n\n"); + fprintf(fp," if ((op = (%s *)PyArg_VTKParseTuple(self, args, (char*)\"s\", &typecast)))\n",data->ClassName); + fprintf(fp," {\n char temp20[256];\n"); + fprintf(fp," sprintf(temp20,\"Addr=%%p\",op);\n"); + fprintf(fp," return PyString_FromString(temp20);\n"); + fprintf(fp," }\n"); + fprintf(fp," return NULL;\n}\n\n"); + + /* Add the PrintRevisions method to vtkObjectBase. */ + fprintf(fp,"PyObject *PyvtkObjectBase_PrintRevisions(PyObject *self, PyObject *args)\n"); + fprintf(fp,"{\n"); + fprintf(fp," %s *op;\n",data->ClassName); + fprintf(fp," if ((op = (%s *)PyArg_VTKParseTuple(self, args, (char*)\"\")))\n",data->ClassName); + fprintf(fp," {\n"); + fprintf(fp," ostrstream vtkmsg_with_warning_C4701;\n"); + fprintf(fp," op->PrintRevisions(vtkmsg_with_warning_C4701);\n"); + fprintf(fp," vtkmsg_with_warning_C4701.put('\\0');\n"); + fprintf(fp," PyObject *result = PyString_FromString(vtkmsg_with_warning_C4701.str());\n"); + fprintf(fp," delete vtkmsg_with_warning_C4701.str();\n"); + fprintf(fp," return result;\n"); + fprintf(fp," }\n"); + fprintf(fp," return NULL;\n}\n\n"); + + } + + /* insert function handling code here */ + for (i = 0; i < data->NumberOfFunctions; i++) + { + currentFunction = data->Functions + i; + outputFunction(fp, data); + } + if (data->NumberOfSuperClasses || !data->IsAbstract) + { + outputFunction2(fp, data); + } + + /* the docstring for the class */ + if (data->NumberOfSuperClasses || !data->IsAbstract) + { + fprintf(fp,"static const char *%sDoc[] = {\n",data->ClassName); + create_class_doc(fp,data); + fprintf(fp,"};\n\n"); + } + + /* output the class initilization function */ + if (strcmp(data->ClassName,"vtkObjectBase") == 0) + { /* special wrapping for vtkObject */ + if (class_has_new) + { + fprintf(fp,"static vtkObjectBase *%sStaticNew()\n",data->ClassName); + fprintf(fp,"{\n return %s::New();\n}\n\n",data->ClassName); + } + fprintf(fp,"PyObject *PyVTKClass_%sNew(char *modulename)\n{\n",data->ClassName); + if (class_has_new) + { + fprintf(fp," return PyVTKClass_New(&%sStaticNew,\n",data->ClassName); + } + else + { + fprintf(fp," return PyVTKClass_New(NULL,\n"); + } + fprintf(fp," Py%sMethods,\n",data->ClassName); + fprintf(fp," (char*)\"%s\",modulename,\n",data->ClassName); + fprintf(fp," (char**)%sDoc,0);\n}\n\n",data->ClassName); + } + else if (data->NumberOfSuperClasses) + { /* wrapping of descendants of vtkObjectBase */ + if (class_has_new) + { + fprintf(fp,"static vtkObjectBase *%sStaticNew()\n",data->ClassName); + fprintf(fp,"{\n return %s::New();\n}\n\n",data->ClassName); + } + fprintf(fp,"PyObject *PyVTKClass_%sNew(char *modulename)\n{\n",data->ClassName); + if (class_has_new) + { + fprintf(fp," return PyVTKClass_New(&%sStaticNew,\n",data->ClassName); + } + else + { + fprintf(fp," return PyVTKClass_New(NULL,\n"); + } + fprintf(fp," Py%sMethods,\n",data->ClassName); + fprintf(fp," (char*)\"%s\",modulename,\n",data->ClassName); + fprintf(fp," (char**)%sDoc,\n",data->ClassName); + fprintf(fp," PyVTKClass_%sNew(modulename));\n}\n\n", + data->SuperClasses[0]); + } + else if (!data->IsAbstract) + { /* wrapping of 'special' non-vtkObject classes */ + fprintf(fp,"PyObject *PyVTKObject_%sNew(PyObject *, PyObject *args)\n{\n",data->ClassName); + fprintf(fp," if (!(PyArg_ParseTuple(args, (char*)\"\")))\n {\n"); + fprintf(fp," return NULL;\n }\n\n"); + fprintf(fp," %s *obj = new %s;\n",data->ClassName,data->ClassName); + fprintf(fp," return PyVTKSpecialObject_New(obj, Py%sMethods, (char*)\"%s\",(char**)%sDoc);\n",data->ClassName,data->ClassName,data->ClassName); + fprintf(fp,"}\n\n"); + + fprintf(fp,"static PyMethodDef Py%sNewMethod = \\\n",data->ClassName); + fprintf(fp,"{ (char*)\"%s\", (PyCFunction)PyVTKObject_%sNew, 1,\n", + data->ClassName,data->ClassName); + fprintf(fp," (char*)%sDoc[0] };\n\n",data->ClassName); + + fprintf(fp,"PyObject *PyVTKClass_%sNew(char *)\n{\n",data->ClassName); + fprintf(fp," return PyCFunction_New(&Py%sNewMethod,Py_None);\n}\n\n", + data->ClassName); + } + else + { /* un-wrappable classes */ + fprintf(fp,"PyObject *PyVTKClass_%sNew(char *)\n{\n",data->ClassName); + fprintf(fp," return NULL;\n}\n\n"); + } +} + diff --git a/Wrapping/vtkWrapPythonInit.c b/Wrapping/vtkWrapPythonInit.c new file mode 100644 index 0000000..6abf011 --- /dev/null +++ b/Wrapping/vtkWrapPythonInit.c @@ -0,0 +1,113 @@ +#include +#include +#include + +/* warning this code is also in getclasses.cxx under pcmaker */ +/* this roputine creates the init file */ +static void CreateInitFile(const char *libName, + int numConcrete, char **concrete, + FILE *fout) +{ + int i; + +#if defined(_WIN32) && !defined(__CYGWIN__) + const char* prefix = ""; +#else + const char* prefix = "lib"; +#endif + +#if defined(_WIN32) + const char* dllexp = "__declspec(dllexport) "; +#else + const char* dllexp = ""; +#endif + + fprintf(fout,"// Generated by vtkWrapPythonInit in VTK/Wrapping\n"); + fprintf(fout,"#include \"vtkPython.h\"\n\n"); + fprintf(fout,"#include \"vtkSystemIncludes.h\"\n"); + fprintf(fout,"#include \n"); + fprintf(fout,"// Handle compiler warning messages, etc.\n" + "#if defined( _MSC_VER ) && !defined(VTK_DISPLAY_WIN32_WARNINGS)\n" + "#pragma warning ( disable : 4706 )\n" + "#endif // Windows Warnings \n\n"); + +for (i = 0; i < numConcrete; i++) + { + fprintf(fout,"extern \"C\" {%sPyObject *PyVTKClass_%sNew(char *); }\n", dllexp, concrete[i]); + } + + fprintf(fout,"\nstatic PyMethodDef Py%s_ClassMethods[] = {\n", libName); + fprintf(fout,"{NULL, NULL, 0, NULL}};\n\n"); + + fprintf(fout,"extern \"C\" {%svoid init%s%s();}\n\n", dllexp, prefix, libName); + fprintf(fout,"void init%s%s()\n{\n", prefix, libName); + + /* module init function */ + fprintf(fout," PyObject *m, *d, *c;\n\n"); + fprintf(fout," static const char modulename[] = \"%s%s\";\n", prefix, libName); + fprintf(fout," m = Py_InitModule((char*)modulename, Py%s_ClassMethods);\n", + libName); + + fprintf(fout," d = PyModule_GetDict(m);\n"); + fprintf(fout," if (!d) Py_FatalError((char*)\"can't get dictionary for module %s!\");\n\n", + libName); + + for (i = 0; i < numConcrete; i++) + { + fprintf(fout," if ((c = PyVTKClass_%sNew((char*)modulename)))\n", + concrete[i]); + fprintf(fout," if (-1 == PyDict_SetItemString(d, (char*)\"%s\", c))\n", + concrete[i]); + fprintf(fout," Py_FatalError((char*)\"can't add class %s to dictionary!\");\n\n", + concrete[i]); + } + fprintf(fout,"}\n\n"); +} + + +int main(int argc,char *argv[]) +{ + FILE *file; + FILE *fout; + int numConcrete = 0; + char libName[250]; + char tmpVal[250]; + char *concrete[4000]; + + if (argc < 3) + { + fprintf(stderr,"Usage: %s input_file output_file\n",argv[0]); + return 1; + } + + file = fopen(argv[1],"r"); + if (!file) + { + fprintf(stderr,"Input file %s could not be opened\n",argv[1]); + return 1; + } + + fout = fopen(argv[2],"w"); + if (!fout) + { + return 1; + } + + /* read the info from the file */ + fscanf(file,"%s",libName); + + /* read in the classes */ + while (fscanf(file,"%s",tmpVal) != EOF) + { + concrete[numConcrete] = strdup(tmpVal); + numConcrete++; + } + /* close the file */ + fclose(file); + + CreateInitFile(libName, numConcrete, concrete, fout); + fclose(fout); + + return 0; +} + diff --git a/Wrapping/vtkWrapTcl.c b/Wrapping/vtkWrapTcl.c new file mode 100644 index 0000000..075ad77 --- /dev/null +++ b/Wrapping/vtkWrapTcl.c @@ -0,0 +1,934 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkWrapTcl.c,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include "vtkParse.h" +#include "vtkConfigure.h" + +int numberOfWrappedFunctions = 0; +FunctionInfo *wrappedFunctions[1000]; +extern FunctionInfo *currentFunction; + + +void output_temp(FILE *fp, int i, int aType, char *Id, int count) +{ + /* handle VAR FUNCTIONS */ + if (aType == 0x5000) + { + fprintf(fp," vtkTclVoidFuncArg *temp%i = new vtkTclVoidFuncArg;\n",i); + return; + } + + /* ignore void */ + if (((aType % 0x10) == 0x2)&&(!((aType % 0x1000)/0x100))) + { + return; + } + + /* for const * return types prototype with const */ + if ((i == MAX_ARGS) && (aType % 0x2000 >= 0x1000)) + { + fprintf(fp," const "); + } + else + { + fprintf(fp," "); + } + + if ((aType % 0x100)/0x10 == 0x1) + { + fprintf(fp,"unsigned "); + } + + switch (aType % 0x10) + { + case 0x1: fprintf(fp,"float "); break; + case 0x7: fprintf(fp,"double "); break; + case 0x4: fprintf(fp,"int "); break; + case 0x5: fprintf(fp,"short "); break; + case 0x6: fprintf(fp,"long "); break; + case 0x2: fprintf(fp,"void "); break; + case 0x3: fprintf(fp,"char "); break; + case 0x9: fprintf(fp,"%s ",Id); break; + case 0xA: fprintf(fp,"vtkIdType "); break; + case 0xB: fprintf(fp,"long long "); break; + case 0xC: fprintf(fp,"__int64 "); break; + case 0xD: fprintf(fp,"signed char "); break; + case 0x8: return; + } + + /* handle array arguements */ + if (count > 0x1) + { + fprintf(fp,"temp%i[%i];\n",i,count); + return; + } + + switch ((aType % 0x1000)/0x100) + { + case 0x1: fprintf(fp, " *"); break; /* act " &" */ + case 0x2: fprintf(fp, "&&"); break; + case 0x3: fprintf(fp, " *"); break; + case 0x4: fprintf(fp, "&*"); break; + case 0x5: fprintf(fp, "*&"); break; + case 0x7: fprintf(fp, "**"); break; + default: fprintf(fp," "); break; + } + + fprintf(fp,"temp%i",i); + fprintf(fp,";\n"); +} + +/* when the cpp file doesn't have enough info use the hint file */ +void use_hints(FILE *fp) +{ + int i; + + /* use the hint */ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x307: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%g "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x304: case 0x305: case 0x30D: +#ifndef VTK_USE_64BIT_IDS + case 0x30A: +#endif + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%i "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x306: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%li "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#ifdef VTK_USE_64BIT_IDS + case 0x30A: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { +# if defined(_MSC_VER) + fprintf(fp,"%%I64i "); +# else + fprintf(fp,"%%lli "); +# endif + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#endif + case 0x30B: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%lli "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x30C: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%I64i "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x313: case 0x314: case 0x315: +#ifndef VTK_USE_64BIT_IDS + case 0x31A: +#endif + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%u "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x316: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%lu "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#ifdef VTK_USE_64BIT_IDS + case 0x31A: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { +# if defined(_MSC_VER) + fprintf(fp,"%%I64u "); +# else + fprintf(fp,"%%llu "); +# endif + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#endif + case 0x31B: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%llu "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x31C: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,"%%I64u "); + } + fprintf(fp,"\""); + for (i = 0; i < currentFunction->HintSize; i++) + { + fprintf(fp,",temp%i[%i]",MAX_ARGS,i); + } + fprintf(fp,");\n"); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + } +} + +void return_result(FILE *fp) +{ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x2: + fprintf(fp," Tcl_ResetResult(interp);\n"); + break; + case 0x1: case 0x7: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%g\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x4: +#ifndef VTK_USE_64BIT_IDS + case 0xA: +#endif + case 0xD: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%i\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x5: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%hi\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x6: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%li\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#ifdef VTK_USE_64BIT_IDS + case 0xA: + fprintf(fp," char tempResult[1024];\n"); +# if defined(_MSC_VER) + fprintf(fp," sprintf(tempResult,\"%%I64i\",temp%i);\n", + MAX_ARGS); +# else + fprintf(fp," sprintf(tempResult,\"%%lli\",temp%i);\n", + MAX_ARGS); +# endif + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#endif + case 0xB: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%lli\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0xC: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%I64i\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x14: +#ifndef VTK_USE_64BIT_IDS + case 0x1A: +#endif + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%u\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x15: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%hu\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x16: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%lu\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x13: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%hu\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#ifdef VTK_USE_64BIT_IDS + case 0x1A: + fprintf(fp," char tempResult[1024];\n"); +# if defined(_MSC_VER) + fprintf(fp," sprintf(tempResult,\"%%I64u\",temp%i);\n", + MAX_ARGS); +# else + fprintf(fp," sprintf(tempResult,\"%%llu\",temp%i);\n", + MAX_ARGS); +# endif + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; +#endif + case 0x1B: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%llu\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x1C: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%I64u\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x303: + fprintf(fp," if (temp%i)\n {\n Tcl_SetResult(interp, (char*)temp%i, TCL_VOLATILE);\n",MAX_ARGS,MAX_ARGS); + fprintf(fp," }\n else\n {\n"); + fprintf(fp," Tcl_ResetResult(interp);\n }\n"); + break; + case 0x3: + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%c\",temp%i);\n", + MAX_ARGS); + fprintf(fp," Tcl_SetResult(interp, tempResult, TCL_VOLATILE);\n"); + break; + case 0x109: + case 0x309: + fprintf(fp," vtkTclGetObjectFromPointer(interp,(void *)temp%i,\"%s\");\n",MAX_ARGS,currentFunction->ReturnClass); + break; + + /* handle functions returning vectors */ + /* this is done by looking them up in a hint file */ + case 0x301: case 0x307: + case 0x304: case 0x305: case 0x306: case 0x30A: case 0x30B: case 0x30C: case 0x30D: + case 0x313: case 0x314: case 0x315: case 0x316: case 0x31A: case 0x31B: case 0x31C: + use_hints(fp); + break; + default: + fprintf(fp," Tcl_SetResult(interp, (char *) \"unable to return result.\", TCL_VOLATILE);\n"); + break; + } +} + +void get_args(FILE *fp, int i) +{ + int j; + int start_arg = 2; + + /* what arg do we start with */ + for (j = 0; j < i; j++) + { + start_arg = start_arg + + (currentFunction->ArgCounts[j] ? currentFunction->ArgCounts[j] : 1); + } + + /* handle VAR FUNCTIONS */ + if (currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp," temp%i->interp = interp;\n",i); + fprintf(fp," temp%i->command = strcpy(new char [strlen(argv[2])+1],argv[2]);\n",i); + return; + } + + /* ignore void */ + if (((currentFunction->ArgTypes[i] % 0x10) == 0x2)&& + (!((currentFunction->ArgTypes[i] % 0x1000)/0x100))) + { + return; + } + + switch (currentFunction->ArgTypes[i] % 0x1000) + { + case 0x1: case 0x7: + fprintf(fp, + " if (Tcl_GetDouble(interp,argv[%i],&tempd) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i = tempd;\n",i); + break; + case 0x4: case 0x5: case 0x6: case 0xA: case 0xB: case 0xC: case 0xD: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i = tempi;\n",i); + break; + case 0x3: + fprintf(fp," temp%i = *(argv[%i]);\n",i,start_arg); + break; + case 0x13: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i = (unsigned char)tempi;\n",i); + break; + case 0x14: case 0x1A: case 0x1B: case 0x1C: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i = (unsigned int)tempi;\n",i); + break; + case 0x15: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i = (unsigned short)tempi;\n",i); + break; + case 0x16: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i = (unsigned long)tempi;\n",i); + break; + case 0x303: + fprintf(fp," temp%i = argv[%i];\n",i,start_arg); + break; + case 0x109: + case 0x309: + fprintf(fp," temp%i = (%s *)(vtkTclGetPointerFromObject(argv[%i],(char *) \"%s\",interp,error));\n",i,currentFunction->ArgClasses[i],start_arg, + currentFunction->ArgClasses[i]); + break; + case 0x2: + case 0x9: + break; + default: + if (currentFunction->ArgCounts[i] > 1) + { + for (j = 0; j < currentFunction->ArgCounts[i]; j++) + { + switch (currentFunction->ArgTypes[i] % 0x100) + { + case 0x1: case 0x7: + fprintf(fp, + " if (Tcl_GetDouble(interp,argv[%i],&tempd) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i[%i] = tempd;\n",i,j); + break; + case 0x4: case 0x5: case 0x6: case 0xA: case 0xB: case 0xC: case 0xD: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i[%i] = tempi;\n",i,j); + break; + case 0x3: + fprintf(fp," temp%i[%i] = *(argv[%i]);\n",i,j,start_arg); + break; + case 0x13: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i[%i] = (unsigned char)tempi;\n",i,j); + break; + case 0x14: case 0x1A: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i[%i] = (unsigned int)tempi;\n",i,j); + break; + case 0x15: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i[%i] = (unsigned short)tempi;\n",i,j); + break; + case 0x16: + fprintf(fp," if (Tcl_GetInt(interp,argv[%i],&tempi) != TCL_OK) error = 1;\n", + start_arg); + fprintf(fp," temp%i[%i] = (unsigned long)tempi;\n",i,j); + break; + } + start_arg++; + } + } + + } +} + +void outputFunction(FILE *fp, FileInfo *data) +{ + int i; + int args_ok = 1; + + /* some functions will not get wrapped no matter what else */ + if (currentFunction->IsOperator || + currentFunction->ArrayFailure || + !currentFunction->IsPublic || + !currentFunction->Name) + { + return; + } + + /* check to see if we can handle the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if ((currentFunction->ArgTypes[i] % 0x10) == 0x8) args_ok = 0; + /* if its a pointer arg make sure we have the ArgCount */ + if ((currentFunction->ArgTypes[i] % 0x1000 >= 0x100) && + (currentFunction->ArgTypes[i] % 0x1000 != 0x303)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x309)&& + (currentFunction->ArgTypes[i] % 0x1000 != 0x109)) + { + if (currentFunction->NumberOfArguments > 1 || + !currentFunction->ArgCounts[i]) + { + args_ok = 0; + } + } + if ((currentFunction->ArgTypes[i] % 0x100 >= 0x10)&& + (currentFunction->ArgTypes[i] != 0x13)&& + (currentFunction->ArgTypes[i] != 0x14)&& + (currentFunction->ArgTypes[i] != 0x15)&& + (currentFunction->ArgTypes[i] != 0x16)&& + (currentFunction->ArgTypes[i] != 0x1A)) args_ok = 0; + } + if ((currentFunction->ReturnType % 0x10) == 0x8) args_ok = 0; + if (((currentFunction->ReturnType % 0x1000)/0x100 != 0x3)&& + ((currentFunction->ReturnType % 0x1000)/0x100 != 0x1)&& + ((currentFunction->ReturnType % 0x1000)/0x100)) args_ok = 0; + if (currentFunction->NumberOfArguments && + (currentFunction->ArgTypes[0] == 0x5000) + &&(currentFunction->NumberOfArguments != 1)) args_ok = 0; + + /* we can't handle void * return types */ + if ((currentFunction->ReturnType % 0x1000) == 0x302) + { + args_ok = 0; + } + + /* watch out for functions that dont have enough info */ + switch (currentFunction->ReturnType % 0x1000) + { + case 0x301: case 0x307: + case 0x304: case 0x305: case 0x306: case 0x30A: case 0x30B: case 0x30C: case 0x30D: + case 0x313: case 0x314: case 0x315: case 0x316: case 0x31A: case 0x31B: case 0x31C: + args_ok = currentFunction->HaveHint; + break; + } + + /* if the args are OK and it is not a constructor or destructor */ + if (args_ok && + strcmp(data->ClassName,currentFunction->Name) && + strcmp(data->ClassName,currentFunction->Name + 1)) + { + int required_args = 0; + + /* calc the total required args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + required_args = required_args + + (currentFunction->ArgCounts[i] ? currentFunction->ArgCounts[i] : 1); + } + + if(currentFunction->IsLegacy) + { + fprintf(fp,"#if !defined(VTK_LEGACY_REMOVE)\n"); + } + fprintf(fp," if ((!strcmp(\"%s\",argv[1]))&&(argc == %i))\n {\n", + currentFunction->Name, required_args + 2); + + /* process the args */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + output_temp(fp, i, currentFunction->ArgTypes[i], + currentFunction->ArgClasses[i], + currentFunction->ArgCounts[i]); + } + output_temp(fp, MAX_ARGS,currentFunction->ReturnType, + currentFunction->ReturnClass, 0); + + /* only use the error variable if we have arguments to parse */ + if (currentFunction->NumberOfArguments) + { + fprintf(fp," error = 0;\n\n"); + /* now get the required args from the stack */ + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + get_args(fp,i); + } + fprintf(fp," if (!error)\n {\n"); + } + + switch (currentFunction->ReturnType % 0x1000) + { + case 0x2: + fprintf(fp," op->%s(",currentFunction->Name); + break; + case 0x109: + fprintf(fp," temp%i = &(op)->%s(",MAX_ARGS,currentFunction->Name); + break; + default: + fprintf(fp," temp%i = (op)->%s(",MAX_ARGS,currentFunction->Name); + } + for (i = 0; i < currentFunction->NumberOfArguments; i++) + { + if (i) + { + fprintf(fp,","); + } + if (currentFunction->ArgTypes[i] == 0x109) + { + fprintf(fp,"*(temp%i)",i); + } + else if (currentFunction->ArgTypes[i] == 0x5000) + { + fprintf(fp,"vtkTclVoidFunc,(void *)temp%i",i); + } + else + { + fprintf(fp,"temp%i",i); + } + } + fprintf(fp,");\n"); + if (currentFunction->NumberOfArguments && + (currentFunction->ArgTypes[0] == 0x5000)) + { + fprintf(fp," op->%sArgDelete(vtkTclVoidFuncArgDelete);\n", + currentFunction->Name); + } + return_result(fp); + fprintf(fp," return TCL_OK;\n"); + + /* close the if error */ + if (currentFunction->NumberOfArguments) + { + fprintf(fp," }\n"); + } + + fprintf(fp," }\n"); + if(currentFunction->IsLegacy) + { + fprintf(fp,"#endif\n"); + } + + wrappedFunctions[numberOfWrappedFunctions] = currentFunction; + numberOfWrappedFunctions++; + } +} + +/* print the parsed structures */ +void vtkParseOutput(FILE *fp, FileInfo *data) +{ + int i,j; + + fprintf(fp,"// tcl wrapper for %s object\n//\n",data->ClassName); + fprintf(fp,"#define VTK_WRAPPING_CXX\n"); + if (strcmp("vtkObjectBase",data->ClassName) != 0) + { + /* Block inclusion of full streams. */ + fprintf(fp,"#define VTK_STREAMS_FWD_ONLY\n"); + } + fprintf(fp,"#include \"vtkSystemIncludes.h\"\n"); + fprintf(fp,"#include \"%s.h\"\n\n",data->ClassName); + fprintf(fp,"#include \"vtkTclUtil.h\"\n"); + fprintf(fp,"#include \n"); + if (data->IsConcrete) + { + if (strcmp(data->ClassName, "vtkRenderWindowInteractor") == 0) + { + fprintf(fp,"#include \"vtkToolkits.h\"\n"); + fprintf(fp,"#if defined( VTK_USE_X ) && defined( VTK_USE_TK )\n"); + fprintf(fp,"# include \"vtkXRenderWindowTclInteractor.h\"\n"); + fprintf(fp,"#endif\n"); + + fprintf(fp,"\nClientData %sNewCommand()\n{\n",data->ClassName); + + fprintf(fp,"#if defined( VTK_USE_X ) && defined( VTK_USE_TK )\n"); + fprintf(fp," %s *temp = vtkXRenderWindowTclInteractor::New();\n", + data->ClassName); + fprintf(fp,"#else\n"); + fprintf(fp," %s *temp = %s::New();\n",data->ClassName,data->ClassName); + fprintf(fp,"#endif\n"); + fprintf(fp," return ((ClientData)temp);\n}\n\n"); + } + else + { + fprintf(fp,"\nClientData %sNewCommand()\n{\n",data->ClassName); + fprintf(fp," %s *temp = %s::New();\n",data->ClassName,data->ClassName); + fprintf(fp," return ((ClientData)temp);\n}\n\n"); + } + } + + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp,"int %sCppCommand(%s *op, Tcl_Interp *interp,\n int argc, char *argv[]);\n",data->SuperClasses[i],data->SuperClasses[i]); + } + fprintf(fp,"int VTKTCL_EXPORT %sCppCommand(%s *op, Tcl_Interp *interp,\n int argc, char *argv[]);\n",data->ClassName,data->ClassName); + fprintf(fp,"\nint VTKTCL_EXPORT %sCommand(ClientData cd, Tcl_Interp *interp,\n int argc, char *argv[])\n{\n",data->ClassName); + fprintf(fp," if ((argc == 2)&&(!strcmp(\"Delete\",argv[1]))&& !vtkTclInDelete(interp))\n {\n"); + fprintf(fp," Tcl_DeleteCommand(interp,argv[0]);\n"); + fprintf(fp," return TCL_OK;\n }\n"); + fprintf(fp," return %sCppCommand((%s *)(((vtkTclCommandArgStruct *)cd)->Pointer),interp, argc, argv);\n}\n",data->ClassName,data->ClassName); + + fprintf(fp,"\nint VTKTCL_EXPORT %sCppCommand(%s *op, Tcl_Interp *interp,\n int argc, char *argv[])\n{\n",data->ClassName,data->ClassName); + fprintf(fp," int tempi;\n"); + fprintf(fp," double tempd;\n"); + fprintf(fp," static char temps[80];\n"); + fprintf(fp," int error;\n\n"); + fprintf(fp," error = 0; error = error;\n"); + fprintf(fp," tempi = 0; tempi = tempi;\n"); + fprintf(fp," tempd = 0; tempd = tempd;\n"); + fprintf(fp," temps[0] = 0; temps[0] = temps[0];\n\n"); + + fprintf(fp," if (argc < 2)\n {\n Tcl_SetResult(interp, (char *) \"Could not find requested method.\", TCL_VOLATILE);\n return TCL_ERROR;\n }\n"); + + /* stick in the typecasting and delete functionality here */ + fprintf(fp," if (!interp)\n {\n"); + fprintf(fp," if (!strcmp(\"DoTypecasting\",argv[0]))\n {\n"); + fprintf(fp," if (!strcmp(\"%s\",argv[1]))\n {\n", + data->ClassName); + fprintf(fp," argv[2] = (char *)((void *)op);\n"); + fprintf(fp," return TCL_OK;\n }\n"); + + /* check our superclasses */ + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp," if (%sCppCommand((%s *)op,interp,argc,argv) == TCL_OK)\n {\n", + data->SuperClasses[i],data->SuperClasses[i]); + fprintf(fp," return TCL_OK;\n }\n"); + } + fprintf(fp," }\n return TCL_ERROR;\n }\n\n"); + + /* add the GetSuperClassName */ + if (data->NumberOfSuperClasses) + { + fprintf(fp," if (!strcmp(\"GetSuperClassName\",argv[1]))\n"); + fprintf(fp," {\n"); + fprintf(fp," Tcl_SetResult(interp,(char *) \"%s\", TCL_VOLATILE);\n",data->SuperClasses[0]); + fprintf(fp," return TCL_OK;\n"); + fprintf(fp," }\n\n"); + } + + fprintf(fp," try\n {\n"); + + /* insert function handling code here */ + for (i = 0; i < data->NumberOfFunctions; i++) + { + currentFunction = data->Functions + i; + outputFunction(fp, data); + } + + /* add the ListInstances method */ + fprintf(fp,"\n if (!strcmp(\"ListInstances\",argv[1]))\n {\n"); + fprintf(fp," vtkTclListInstances(interp,(ClientData)%sCommand);\n",data->ClassName); + fprintf(fp," return TCL_OK;\n }\n"); + + /* add the ListMethods method */ + fprintf(fp,"\n if (!strcmp(\"ListMethods\",argv[1]))\n {\n"); + /* recurse up the tree */ + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp," %sCppCommand(op,interp,argc,argv);\n", + data->SuperClasses[i]); + } + /* now list our methods */ + fprintf(fp," Tcl_AppendResult(interp,\"Methods from %s:\\n\",NULL);\n",data->ClassName); + fprintf(fp," Tcl_AppendResult(interp,\" GetSuperClassName\\n\",NULL);\n"); + for (i = 0; i < numberOfWrappedFunctions; i++) + { + int numArgs = 0; + + currentFunction = wrappedFunctions[i]; + if(currentFunction->IsLegacy) + { + fprintf(fp,"#if !defined(VTK_LEGACY_REMOVE)\n"); + } + + /* calc the total required args */ + for (j = 0; j < currentFunction->NumberOfArguments; j++) + { + numArgs = numArgs + + (currentFunction->ArgCounts[j] ? currentFunction->ArgCounts[j] : 1); + } + + if (numArgs > 1) + { + fprintf(fp," Tcl_AppendResult(interp,\" %s\\t with %i args\\n\",NULL);\n", + currentFunction->Name, numArgs); + } + if (numArgs == 1) + { + fprintf(fp," Tcl_AppendResult(interp,\" %s\\t with 1 arg\\n\",NULL);\n", + currentFunction->Name); + } + if (numArgs == 0) + { + fprintf(fp," Tcl_AppendResult(interp,\" %s\\n\",NULL);\n", + currentFunction->Name); + } + + if(currentFunction->IsLegacy) + { + fprintf(fp,"#endif\n"); + } + } + fprintf(fp," return TCL_OK;\n }\n"); + + /* try superclasses */ + for (i = 0; i < data->NumberOfSuperClasses; i++) + { + fprintf(fp,"\n if (%sCppCommand((%s *)op,interp,argc,argv) == TCL_OK)\n", + data->SuperClasses[i], data->SuperClasses[i]); + fprintf(fp," {\n return TCL_OK;\n }\n"); + } + + /* Add the Print method to vtkObjectBase. */ + if (!strcmp("vtkObjectBase",data->ClassName)) + { + fprintf(fp," if ((!strcmp(\"Print\",argv[1]))&&(argc == 2))\n {\n"); + fprintf(fp," ostrstream buf_with_warning_C4701;\n"); + fprintf(fp," op->Print(buf_with_warning_C4701);\n"); + fprintf(fp," buf_with_warning_C4701.put('\\0');\n"); + fprintf(fp," Tcl_SetResult(interp,buf_with_warning_C4701.str(),\n"); + fprintf(fp," TCL_VOLATILE);\n"); + fprintf(fp," buf_with_warning_C4701.rdbuf()->freeze(0);\n"); + fprintf(fp," return TCL_OK;\n }\n"); + /* Add the PrintRevisions method to vtkObjectBase. */ + fprintf(fp," if ((!strcmp(\"PrintRevisions\",argv[1]))&&(argc == 2))\n {\n"); + fprintf(fp," ostrstream buf_with_warning_C4701;\n"); + fprintf(fp," op->PrintRevisions(buf_with_warning_C4701);\n"); + fprintf(fp," buf_with_warning_C4701.put('\\0');\n"); + fprintf(fp," Tcl_SetResult(interp,buf_with_warning_C4701.str(),\n"); + fprintf(fp," TCL_VOLATILE);\n"); + fprintf(fp," delete [] buf_with_warning_C4701.str();\n"); + fprintf(fp," return TCL_OK;\n }\n"); + } + /* Add the AddObserver method to vtkObject. */ + if (!strcmp("vtkObject",data->ClassName)) + { + fprintf(fp," if ((!strcmp(\"AddObserver\",argv[1]))&&(argc >= 4))\n {\n"); + fprintf(fp," error = 0;\n"); + fprintf(fp," if (argc > 4 && Tcl_GetDouble(interp,argv[4],&tempd) != TCL_OK) error = 1;\n"); + fprintf(fp," if (!error)\n {\n"); + fprintf(fp," vtkTclCommand *cbc = vtkTclCommand::New();\n"); + fprintf(fp," cbc->SetInterp(interp);\n"); + fprintf(fp," cbc->SetStringCommand(argv[3]);\n"); + fprintf(fp," unsigned long temp20;\n"); + fprintf(fp," if (argc > 4)\n {\n"); + fprintf(fp," temp20 = op->AddObserver(argv[2],cbc,tempd);\n"); + fprintf(fp," }\n else\n {\n"); + fprintf(fp," temp20 = op->AddObserver(argv[2],cbc);\n"); + fprintf(fp," }\n"); + fprintf(fp," cbc->Delete();\n"); + fprintf(fp," char tempResult[1024];\n"); + fprintf(fp," sprintf(tempResult,\"%%li\",temp20);\n"); + fprintf(fp," Tcl_SetResult(interp,tempResult,TCL_VOLATILE);\n"); + fprintf(fp," return TCL_OK;\n }\n"); + fprintf(fp," }\n"); + } + fprintf(fp,"\n if ((argc >= 2)&&(!strstr(interp->result,\"Object named:\")))\n {\n"); + fprintf(fp," char temps2[256];\n sprintf(temps2,\"Object named: %%s, could not find requested method: %%s\\nor the method was called with incorrect arguments.\\n\",argv[0],argv[1]);\n Tcl_AppendResult(interp,temps2,NULL);\n }\n"); + fprintf(fp," }\n"); + fprintf(fp," catch (vtkstd::exception &e)\n"); + fprintf(fp," {\n"); + fprintf(fp," Tcl_AppendResult(interp, \"Uncaught exception: \", e.what(), \"\\n\", NULL);\n"); + fprintf(fp," return TCL_ERROR;\n"); + fprintf(fp," }\n"); + fprintf(fp," return TCL_ERROR;\n}\n"); + +} diff --git a/Wrapping/vtkWrapTclInit.c b/Wrapping/vtkWrapTclInit.c new file mode 100644 index 0000000..232b611 --- /dev/null +++ b/Wrapping/vtkWrapTclInit.c @@ -0,0 +1,237 @@ +#include +#include +#include + +char *Capitalized(const char *input) +{ + char *result; + unsigned int i; + + result = strdup(input); + if (result[0] > 90) + { + result[0] -= 32; + } + for (i = 1; i < strlen(result); i++) + { + if ((result[i] > 64)&&(result[i] < 91)) + { + result[i] += 32; + } + } + + return result; +} + +/* this roputine creates the init file */ +static void CreateInitFile(const char *libName, + int numConcrete, char **concrete, + int numCommands, char **commands, + const char *version, + FILE *fout) +{ + /* we have to make sure that the name is the correct case */ + char *kitName = Capitalized(libName); + int i; + char **capcommands = (char **)malloc(numCommands*sizeof(char *)); + + /* capitalize commands just once */ + for (i = 0; i < numCommands; i++) + { + capcommands[i] = Capitalized(commands[i]); + } + + fprintf(fout,"#include \"vtkTclUtil.h\"\n"); + fprintf(fout,"#include \"vtkVersion.h\"\n"); + fprintf(fout,"#define VTK_TCL_TO_STRING(x) VTK_TCL_TO_STRING0(x)\n"); + fprintf(fout,"#define VTK_TCL_TO_STRING0(x) #x\n"); + + fprintf(fout, + "extern \"C\"\n" + "{\n" + "#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4) && (TCL_RELEASE_LEVEL >= TCL_FINAL_RELEASE)\n" + " typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,int, CONST84 char *[]);\n" + "#else\n" + " typedef int (*vtkTclCommandType)(ClientData, Tcl_Interp *,int, char *[]);\n" + "#endif\n" + "}\n" + "\n"); + + for (i = 0; i < numConcrete; i++) + { + fprintf(fout,"int %sCommand(ClientData cd, Tcl_Interp *interp,\n int argc, char *argv[]);\n",concrete[i]); + fprintf(fout,"ClientData %sNewCommand();\n",concrete[i]); + } + + if (!strcmp(kitName,"Vtkcommontcl")) + { + fprintf(fout,"int vtkCreateCommand(ClientData cd, Tcl_Interp *interp,\n" + " int argc, char *argv[]);\n"); + fprintf(fout,"\nTcl_HashTable vtkInstanceLookup;\n"); + fprintf(fout,"Tcl_HashTable vtkPointerLookup;\n"); + fprintf(fout,"Tcl_HashTable vtkCommandLookup;\n"); + } + else + { + fprintf(fout,"\nextern Tcl_HashTable vtkInstanceLookup;\n"); + fprintf(fout,"extern Tcl_HashTable vtkPointerLookup;\n"); + fprintf(fout,"extern Tcl_HashTable vtkCommandLookup;\n"); + } + fprintf(fout,"extern void vtkTclDeleteObjectFromHash(void *);\n"); + fprintf(fout,"extern void vtkTclListInstances(Tcl_Interp *interp, ClientData arg);\n"); + + for (i = 0; i < numCommands; i++) + { + fprintf(fout, + "\nextern \"C\" {int VTK_EXPORT %s_Init(Tcl_Interp *interp);}\n", + capcommands[i]); + } + + fprintf(fout, + "\n\nextern \"C\" {int VTK_EXPORT %s_SafeInit(Tcl_Interp *interp);}\n", + kitName); + fprintf(fout, + "\nextern \"C\" {int VTK_EXPORT %s_Init(Tcl_Interp *interp);}\n", + kitName); + + /* create an extern ref to the generic delete function */ + fprintf(fout,"\nextern void vtkTclGenericDeleteObject(ClientData cd);\n"); + + if (!strcmp(kitName,"Vtkcommontcl")) + { + fprintf(fout, + "extern \"C\"\n{\nvoid vtkCommonDeleteAssocData(ClientData cd)\n"); + fprintf(fout," {\n"); + fprintf(fout," vtkTclInterpStruct *tis = static_cast(cd);\n"); + fprintf(fout," delete tis;\n }\n}\n"); + } + + /* the main declaration */ + fprintf(fout, + "\n\nint VTK_EXPORT %s_SafeInit(Tcl_Interp *interp)\n{\n",kitName); + fprintf(fout," return %s_Init(interp);\n}\n",kitName); + + fprintf(fout,"\n\nint VTK_EXPORT %s_Init(Tcl_Interp *interp)\n{\n", + kitName); + if (!strcmp(kitName,"Vtkcommontcl")) + { + fprintf(fout, + " vtkTclInterpStruct *info = new vtkTclInterpStruct;\n"); + fprintf(fout, + " info->Number = 0; info->InDelete = 0; info->DebugOn = 0; info->DeleteExistingObjectOnNew = 0;\n"); + fprintf(fout,"\n"); + fprintf(fout,"\n"); + fprintf(fout, + " Tcl_InitHashTable(&info->InstanceLookup, TCL_STRING_KEYS);\n"); + fprintf(fout, + " Tcl_InitHashTable(&info->PointerLookup, TCL_STRING_KEYS);\n"); + fprintf(fout, + " Tcl_InitHashTable(&info->CommandLookup, TCL_STRING_KEYS);\n"); + fprintf(fout, + " Tcl_SetAssocData(interp,(char *) \"vtk\",NULL,(ClientData *)info);\n"); + fprintf(fout, + " Tcl_CreateExitHandler(vtkCommonDeleteAssocData,(ClientData *)info);\n"); + + /* create special vtkCommand command */ + fprintf(fout," Tcl_CreateCommand(interp,(char *) \"vtkCommand\",\n" + " reinterpret_cast(vtkCreateCommand),\n" + " (ClientData *)NULL, NULL);\n\n"); + } + + for (i = 0; i < numCommands; i++) + { + fprintf(fout," %s_Init(interp);\n", capcommands[i]); + } + fprintf(fout,"\n"); + + for (i = 0; i < numConcrete; i++) + { + fprintf(fout," vtkTclCreateNew(interp,(char *) \"%s\", %sNewCommand,\n", + concrete[i], concrete[i]); + fprintf(fout," %sCommand);\n",concrete[i]); + } + + fprintf(fout," char pkgName[]=\"%s\";\n", libName); + if (version && *version) + { + fprintf(fout," char pkgVers[]=VTK_TCL_TO_STRING(%s);\n", version); + } + else + { + fprintf(fout," char pkgVers[]=VTK_TCL_TO_STRING(VTK_MAJOR_VERSION)" + " \".\" " + "VTK_TCL_TO_STRING(VTK_MINOR_VERSION);\n"); + } + fprintf(fout," Tcl_PkgProvide(interp, pkgName, pkgVers);\n"); + fprintf(fout," return TCL_OK;\n}\n"); + + for ( i = 0; i < numCommands; i++ ) + { + free(capcommands[i]); + } + free(capcommands); + free(kitName); +} + + +int main(int argc,char *argv[]) +{ + FILE *file; + FILE *fout; + int numConcrete = 0; + int numCommands = 0; + char libName[250]; + char tmpVal[250]; + char *concrete[4000]; + char *commands[4000]; + char version[4000] = {'\0'}; + + if (argc < 3) + { + fprintf(stderr,"Usage: %s input_file output_file\n",argv[0]); + return 1; + } + + file = fopen(argv[1],"r"); + if (!file) + { + fprintf(stderr,"Input file %s could not be opened\n",argv[1]); + return 1; + } + + fout = fopen(argv[2],"w"); + if (!fout) + { + return 1; + } + + /* read the info from the file */ + fscanf(file,"%s",libName); + + /* read in the classes and commands */ + while (fscanf(file,"%s",tmpVal) != EOF) + { + if (!strcmp(tmpVal,"COMMAND")) + { + fscanf(file,"%s",tmpVal); + commands[numCommands] = strdup(tmpVal); + numCommands++; + } + else if (!strcmp(tmpVal,"VERSION")) + { + fscanf(file,"%s",version); + } + else + { + concrete[numConcrete] = strdup(tmpVal); + numConcrete++; + } + } + /* close the file */ + fclose(file); + + CreateInitFile(libName, numConcrete, concrete, numCommands, commands, version, fout); + fclose(fout); + + return 0; +} diff --git a/Wrapping/vtkWrapperInit.data.in b/Wrapping/vtkWrapperInit.data.in new file mode 100644 index 0000000..3d10232 --- /dev/null +++ b/Wrapping/vtkWrapperInit.data.in @@ -0,0 +1 @@ +@VTK_WRAPPER_INIT_DATA@ diff --git a/installForEMoffice/installForEMoffice.sh b/installForEMoffice/installForEMoffice.sh new file mode 100644 index 0000000..ee4da18 --- /dev/null +++ b/installForEMoffice/installForEMoffice.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +INSTALL_DIR=$EMoffice_HOME +BUILD_DIR=build +CC=gcc +CXX=g++ + +runCommand () +{ + if [ -n "$0" ] + then + echo -n "***** Executing command : " + echo "$*" + $* + return $? + else + echo "****** Internal Error: no command passed to runCommand()" + exit -1 + fi +} + +if [ -d $BUILD_DIR ]; then + command="/bin/rm -rf $BUILD_DIR" + runCommand $command +fi + +command="mkdir $BUILD_DIR" +runCommand $command + +command="cd $BUILD_DIR" +runCommand $command + +command="env CC=$CC CXX=$CXX cmake -DCMAKE_INSTALL_PREFIX:PATH=$INSTALL_DIR ../../" +runCommand $command + +command="make" +runCommand $command + +command="make install" +runCommand $command + +command="cd ../" +runCommand $command diff --git a/vtkBanner.gif b/vtkBanner.gif new file mode 100644 index 0000000..11d8103 Binary files /dev/null and b/vtkBanner.gif differ diff --git a/vtkConfigure.h.in b/vtkConfigure.h.in new file mode 100644 index 0000000..ff36468 --- /dev/null +++ b/vtkConfigure.h.in @@ -0,0 +1,181 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkConfigure.h.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkConfigure_h +#define __vtkConfigure_h + +/* This header is configured by VTK's build process. */ + +/*--------------------------------------------------------------------------*/ +/* Platform Features */ + +/* Byte order. */ +#cmakedefine VTK_WORDS_BIGENDIAN + +/* Threading system. */ +#cmakedefine VTK_USE_PTHREADS +#cmakedefine VTK_USE_SPROC +#cmakedefine VTK_HP_PTHREADS +#cmakedefine VTK_USE_WIN32_THREADS + +/* Size of fundamental data types. */ +#define VTK_SIZEOF_CHAR @VTK_SIZEOF_CHAR@ +#define VTK_SIZEOF_DOUBLE @VTK_SIZEOF_DOUBLE@ +#define VTK_SIZEOF_FLOAT @VTK_SIZEOF_FLOAT@ +#define VTK_SIZEOF_INT @VTK_SIZEOF_INT@ +#define VTK_SIZEOF_LONG @VTK_SIZEOF_LONG@ +#define VTK_SIZEOF_SHORT @VTK_SIZEOF_SHORT@ + +/* Define size of long long and/or __int64 bit integer type only if the type + exists. */ +#cmakedefine VTK_SIZEOF_LONG_LONG @VTK_SIZEOF_LONG_LONG@ +#cmakedefine VTK_SIZEOF___INT64 @VTK_SIZEOF___INT64@ + +/* Whether types "long long" and "__int64" are enabled. If a type is + enabled then it is a unique fundamental type. */ +#cmakedefine VTK_TYPE_USE_LONG_LONG +#cmakedefine VTK_TYPE_USE___INT64 + +/* Some properties of the available types. */ +#cmakedefine VTK_TYPE_SAME_LONG_AND___INT64 +#cmakedefine VTK_TYPE_SAME_LONG_LONG_AND___INT64 +#cmakedefine VTK_TYPE_CONVERT_UI64_TO_DOUBLE + +/* Whether type "char" is signed (it may be signed or unsigned). */ +#define VTK_TYPE_CHAR_IS_SIGNED @VTK_TYPE_CHAR_IS_SIGNED@ + +/* Compiler features. */ +#cmakedefine VTK_NO_EXPLICIT_TEMPLATE_INSTANTIATION +#cmakedefine VTK_NO_FULL_TEMPLATE_SPECIALIZATION +#cmakedefine VTK_NO_ANSI_STRING_STREAM +#cmakedefine VTK_NO_STD_NAMESPACE +#cmakedefine VTK_NO_FOR_SCOPE +#cmakedefine VTK_COMPILER_HAS_BOOL +#cmakedefine VTK_ISTREAM_SUPPORTS_LONG_LONG +#cmakedefine VTK_OSTREAM_SUPPORTS_LONG_LONG +#define VTK_STREAM_EOF_SEVERITY @VTK_STREAM_EOF_SEVERITY@ +#cmakedefine VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T + +/*--------------------------------------------------------------------------*/ +/* VTK Platform Configuration */ + +/* Whether we are building shared libraries. */ +#cmakedefine VTK_BUILD_SHARED_LIBS + +/* Whether vtkIdType is a 64-bit integer type (or a 32-bit integer type). */ +#cmakedefine VTK_USE_64BIT_IDS + +/* Whether we are using ANSI C++ streams (or old-style streams). */ +#cmakedefine VTK_USE_ANSI_STDLIB + +/* Whether VTK was built to support Carbon or Cocoa on the Mac. */ +#cmakedefine VTK_USE_CARBON +#cmakedefine VTK_USE_COCOA + +/* Whether we are linking to Tcl/Tk statically. */ +#cmakedefine VTK_TCL_TK_STATIC + +/* Whether Tk widgets are NOT initialized when vtkRendering loads. */ +#cmakedefine VTK_USE_TK + +/* Wheter the Tcl/Tk support files are copied to the build dir */ +#cmakedefine VTK_TCL_TK_COPY_SUPPORT_LIBRARY + +/* Configure internal Tk headers. */ +#ifdef VTK_USE_CARBON +# define USE_NON_CONST +# define MAC_OSX_TK +#endif + + +/*--------------------------------------------------------------------------*/ +/* VTK Versioning */ + +/* Version number. */ +#define VTK_MAJOR_VERSION @VTK_MAJOR_VERSION@ +#define VTK_MINOR_VERSION @VTK_MINOR_VERSION@ +#define VTK_BUILD_VERSION @VTK_BUILD_VERSION@ +#define VTK_VERSION "@VTK_VERSION@" + +/* C++ compiler used. */ +#define VTK_CXX_COMPILER "@CMAKE_CXX_COMPILER@" + +/* Compatibility settings. */ +#cmakedefine VTK_LEGACY_REMOVE +#cmakedefine VTK_LEGACY_SILENT + +/*--------------------------------------------------------------------------*/ +/* Setup VTK based on platform features and configuration. */ + +/* Setup vtkstd, a portable namespace for std. */ +#ifndef VTK_NO_STD_NAMESPACE +# define vtkstd std +#else +# define vtkstd +#endif + +/* Define a "vtkstd_bool" type. This should be used as the + return type of comparison operators to keep STL happy on all + platforms. It should not be used elsewhere. Only use bool + if this file is included by a c++ file. */ +#if defined(VTK_COMPILER_HAS_BOOL) && defined(__cplusplus) +typedef bool vtkstd_bool; +#else +typedef int vtkstd_bool; +#endif + +/* Define a macro to help define template specializations. Skip if + compiling a windows resource file because the resource compiler + warns about truncating the long symbol. */ +#if !defined(RC_INVOKED) +# if defined(VTK_NO_FULL_TEMPLATE_SPECIALIZATION) +# define VTK_TEMPLATE_SPECIALIZE +# else +# define VTK_TEMPLATE_SPECIALIZE template <> +# endif +#endif + +/* Use the common for-scope work-around when compiling a source in VTK. */ +#if defined(VTK_IN_VTK) && !defined(VTK_NO_WORKAROUND_FOR_SCOPE) +# define VTK_WORKAROUND_FOR_SCOPE +#endif +#if defined(VTK_NO_FOR_SCOPE) && defined(VTK_WORKAROUND_FOR_SCOPE) +# ifndef for +# define for if(0) {} else for +# if defined(_MSC_VER) +# pragma warning (disable: 4127) /* conditional expression is constant */ +# endif +# endif +#endif + +/* Provide missing streaming operators. */ +#if defined(VTK_SIZEOF_LONG_LONG) +# if !defined(VTK_OSTREAM_SUPPORTS_LONG_LONG) +# define VTK_IOSTREAM_NEED_OPERATORS_LL +# elif !defined(VTK_ISTREAM_SUPPORTS_LONG_LONG) +# define VTK_IOSTREAM_NEED_OPERATORS_LL +# endif +# if defined(VTK_IOSTREAM_NEED_OPERATORS_LL) + typedef long long vtkIOStreamSLL; + typedef unsigned long long vtkIOStreamULL; +# endif +#elif defined(VTK_SIZEOF___INT64) +# if defined(_MSC_VER) && (_MSC_VER < 1300) +# define VTK_IOSTREAM_NEED_OPERATORS_LL + typedef __int64 vtkIOStreamSLL; + typedef unsigned __int64 vtkIOStreamULL; +# endif +#endif + +#endif diff --git a/vtkGenerateVTKConfig.cmake b/vtkGenerateVTKConfig.cmake new file mode 100644 index 0000000..336ea5a --- /dev/null +++ b/vtkGenerateVTKConfig.cmake @@ -0,0 +1,327 @@ +# Generate the VTKConfig.cmake file in the build tree. Also configure +# one for installation. The file tells external projects how to use +# VTK. + +# Help store a literal dollar in a string. CMake 2.2 allows escaped +# dollars but we have to support CMake 2.0. +SET(DOLLAR "$") + +#----------------------------------------------------------------------------- +# Settings shared between the build tree and install tree. + +IF(VTK_USE_MPI) + SET(VTK_MPIRUN_EXE_CONFIG ${VTK_MPIRUN_EXE}) + SET(VTK_MPI_MAX_NUMPROCS_CONFIG ${VTK_MPI_MAX_NUMPROCS}) + SET(VTK_MPI_POSTFLAGS_CONFIG ${VTK_MPI_POSTFLAGS}) + SET(VTK_MPI_PREFLAGS_CONFIG ${VTK_MPI_PREFLAGS}) + SET(VTK_MPI_CLIENT_PREFLAGS_CONFIG ${VTK_MPI_CLIENT_PREFLAGS}) + SET(VTK_MPI_SERVER_PREFLAGS_CONFIG ${VTK_MPI_SERVER_PREFLAGS}) +ELSE(VTK_USE_MPI) + SET(VTK_MPIRUN_EXE_CONFIG "") + SET(VTK_MPI_MAX_NUMPROCS_CONFIG "") + SET(VTK_MPI_POSTFLAGS_CONFIG "") + SET(VTK_MPI_PREFLAGS_CONFIG "") + SET(VTK_MPI_CLIENT_PREFLAGS_CONFIG "") + SET(VTK_MPI_SERVER_PREFLAGS_CONFIG "") +ENDIF(VTK_USE_MPI) + +# Some setting for the remote testing +SET(VTK_MPI_CLIENT_POSTFLAGS_CONFIG ${VTK_MPI_CLIENT_POSTFLAGS}) +SET(VTK_MPI_SERVER_POSTFLAGS_CONFIG ${VTK_MPI_SERVER_POSTFLAGS}) + +#----------------------------------------------------------------------------- +# Settings specific to the build tree. + +# The install-only section is empty for the build tree. +SET(VTK_CONFIG_INSTALL_ONLY) + +# The "use" file. +SET(VTK_USE_FILE ${VTK_BINARY_DIR}/UseVTK.cmake) + +# The build settings file. +SET(VTK_BUILD_SETTINGS_FILE ${VTK_BINARY_DIR}/VTKBuildSettings.cmake) + +# The directory containing class list files for each kit. +SET(VTK_KITS_DIR_CONFIG ${VTK_BINARY_DIR}/Utilities) + +# The wrapping hints file. +SET(VTK_WRAP_HINTS_CONFIG ${VTK_WRAP_HINTS}) + +# Library directory. +SET(VTK_LIBRARY_DIRS_CONFIG ${LIBRARY_OUTPUT_PATH}) + +# Runtime library directory. +SET(VTK_RUNTIME_LIBRARY_DIRS_CONFIG ${LIBRARY_OUTPUT_PATH}) + +# Determine the include directories needed. +SET(VTK_INCLUDE_DIRS_CONFIG + ${VTK_INCLUDE_DIRS_BUILD_TREE} + ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_INCLUDE_DIRS_SYSTEM} +) + +# Executable locations. +SET(VTK_TCL_HOME_CONFIG "") +SET(VTK_JAVA_JAR_CONFIG "") +SET(VTK_PARSE_JAVA_EXE_CONFIG "") +SET(VTK_WRAP_JAVA_EXE_CONFIG "") +SET(VTK_WRAP_PYTHON_EXE_CONFIG "") +SET(VTK_WRAP_PYTHON_INIT_EXE_CONFIG "") +SET(VTK_WRAP_TCL_EXE_CONFIG "") +SET(VTK_WRAP_TCL_INIT_EXE_CONFIG "") +IF(VTK_WRAP_TCL) + SET(VTK_WRAP_TCL_EXE_CONFIG ${VTK_WRAP_TCL_EXE}) + SET(VTK_WRAP_TCL_INIT_EXE_CONFIG ${VTK_WRAP_TCL_INIT_EXE}) + SET(VTK_TCL_HOME_CONFIG ${VTK_TCL_HOME}) +ENDIF(VTK_WRAP_TCL) +IF(VTK_WRAP_PYTHON) + SET(VTK_WRAP_PYTHON_EXE_CONFIG ${VTK_WRAP_PYTHON_EXE}) + SET(VTK_WRAP_PYTHON_INIT_EXE_CONFIG ${VTK_WRAP_PYTHON_INIT_EXE}) +ENDIF(VTK_WRAP_PYTHON) +IF(VTK_WRAP_JAVA) + SET(VTK_PARSE_JAVA_EXE_CONFIG ${VTK_PARSE_JAVA_EXE}) + SET(VTK_WRAP_JAVA_EXE_CONFIG ${VTK_WRAP_JAVA_EXE}) + SET(VTK_JAVA_JAR_CONFIG ${LIBRARY_OUTPUT_PATH}/vtk.jar) +ENDIF(VTK_WRAP_JAVA) + +# VTK style script locations. +SET(VTK_DOXYGEN_HOME_CONFIG ${VTK_SOURCE_DIR}/Utilities/Doxygen) +SET(VTK_HEADER_TESTING_PY_CONFIG ${VTK_SOURCE_DIR}/Common/Testing/HeaderTesting.py) +SET(VTK_FIND_STRING_TCL_CONFIG ${VTK_SOURCE_DIR}/Common/Testing/Tcl/FindString.tcl) +SET(VTK_PRINT_SELF_CHECK_TCL_CONFIG ${VTK_SOURCE_DIR}/Common/Testing/Tcl/PrintSelfCheck.tcl) +SET(VTK_RT_IMAGE_TEST_TCL_CONFIG ${VTK_SOURCE_DIR}/Common/Testing/Tcl/rtImageTest.tcl) + +IF(VTK_USE_PARALLEL) + SET(VTK_PRT_IMAGE_TEST_TCL_CONFIG ${VTK_SOURCE_DIR}/Common/Testing/Tcl/prtImageTest.tcl) +ELSE(VTK_USE_PARALLEL) + SET(VTK_PRT_IMAGE_TEST_TCL_CONFIG "") +ENDIF(VTK_USE_PARALLEL) + +# Location of tk internal headers and resources provided by VTK. +SET(VTK_TK_INTERNAL_DIR_CONFIG "${TK_INTERNAL_PATH}") + +# The resources dir is only worth exporting if we are building with +# Tcl/Tk static +SET(VTK_TK_RESOURCES_DIR_CONFIG "") +IF(VTK_USE_TK AND VTK_TCL_TK_STATIC) + SET(VTK_TK_RESOURCES_DIR_CONFIG ${VTK_TK_RESOURCES_DIR}) +ENDIF(VTK_USE_TK AND VTK_TCL_TK_STATIC) + +SET(VTK_TCL_SUPPORT_LIBRARY_PATH_CONFIG ${VTK_TCL_SUPPORT_LIBRARY_PATH}) +SET(VTK_TK_SUPPORT_LIBRARY_PATH_CONFIG ${VTK_TK_SUPPORT_LIBRARY_PATH}) + +# CMake extension module directory. +SET(VTK_LOAD_CMAKE_EXTENSIONS_MACRO_CONFIG + "${VTK_SOURCE_DIR}/CMake/vtkLoadCMakeExtensions.cmake") +SET(VTK_CMAKE_DIR_CONFIG + "${VTK_SOURCE_DIR}/CMake") +SET(VTK_TCL_TK_MACROS_MODULE_CONFIG + "${VTK_SOURCE_DIR}/CMake/vtkTclTkMacros.cmake") +SET(VTK_CMAKE_EXTENSIONS_DIR_CONFIG ${VTK_BINARY_DIR}/CMake) + +# Library dependencies file. +SET(VTK_LIBRARY_DEPENDS_FILE "${VTK_BINARY_DIR}/VTKLibraryDepends.cmake") + +# Build configuration information. +SET(VTK_CONFIGURATION_TYPES_CONFIG ${CMAKE_CONFIGURATION_TYPES}) +SET(VTK_BUILD_TYPE_CONFIG ${CMAKE_BUILD_TYPE}) + +# Hack to give source tree access for a build tree configuration. +STRING(ASCII 35 VTK_STRING_POUND) +STRING(ASCII 64 VTK_STRING_AT) +SET(VTK_CONFIG_BACKWARD_COMPATIBILITY_HACK + "\n${VTK_STRING_POUND} For backward compatability. DO NOT USE.\nSET(VTK_SOURCE_DIR \"${VTK_SOURCE_DIR}\")\nIF(NOT TCL_LIBRARY)\n SET(TCL_LIBRARY \"${TCL_LIBRARY}\" CACHE FILEPATH \"Location of Tcl library imported from VTK. This may mean your project is depending on VTK to get this setting. Consider using FindTCL.cmake.\")\nENDIF(NOT TCL_LIBRARY)\nIF(NOT TK_LIBRARY)\n SET(TK_LIBRARY \"${TK_LIBRARY}\" CACHE FILEPATH \"Location of Tk library imported from VTK. This may mean your project is depending on VTK to get this setting. Consider using FindTCL.cmake.\")\nENDIF(NOT TK_LIBRARY)\nMARK_AS_ADVANCED(TCL_LIBRARY TK_LIBRARY)\n") + +#----------------------------------------------------------------------------- +# Configure VTKConfig.cmake for the build tree. +CONFIGURE_FILE(${VTK_SOURCE_DIR}/VTKConfig.cmake.in + ${VTK_BINARY_DIR}/VTKConfig.cmake @ONLY IMMEDIATE) + +#----------------------------------------------------------------------------- +# Settings specific to the install tree. + +# The "use" file. +SET(VTK_USE_FILE ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/UseVTK.cmake) + +# The build settings file. +SET(VTK_BUILD_SETTINGS_FILE ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/VTKBuildSettings.cmake) + +# The directory containing class list files for each kit. +SET(VTK_KITS_DIR_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}) + +# The wrapping hints file. +IF(VTK_WRAP_HINTS) + GET_FILENAME_COMPONENT(VTK_HINTS_FNAME ${VTK_WRAP_HINTS} NAME) + SET(VTK_WRAP_HINTS_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/${VTK_HINTS_FNAME}) +ENDIF(VTK_WRAP_HINTS) + +# Include directories. +SET(VTK_INCLUDE_DIRS_CONFIG + ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_INCLUDE_DIR} + ${VTK_INCLUDE_DIRS_SYSTEM} +) + +# Link directories. +IF(CYGWIN AND BUILD_SHARED_LIBS) + # In Cygwin programs directly link to the .dll files. + SET(VTK_LIBRARY_DIRS_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}) +ELSE(CYGWIN AND BUILD_SHARED_LIBS) + SET(VTK_LIBRARY_DIRS_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_LIB_DIR}) +ENDIF(CYGWIN AND BUILD_SHARED_LIBS) + +# Runtime directories. +IF(WIN32) + SET(VTK_RUNTIME_LIBRARY_DIRS_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}) +ELSE(WIN32) + SET(VTK_RUNTIME_LIBRARY_DIRS_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_LIB_DIR}) +ENDIF(WIN32) + +IF(WIN32) + SET(VTK_EXE_EXT ".exe") +ENDIF(WIN32) + +# Executable locations. +SET(VTK_TCL_HOME_CONFIG "") +SET(VTK_JAVA_JAR_CONFIG "") +SET(VTK_PARSE_JAVA_EXE_CONFIG "") +SET(VTK_WRAP_JAVA_EXE_CONFIG "") +SET(VTK_WRAP_PYTHON_EXE_CONFIG "") +SET(VTK_WRAP_PYTHON_INIT_EXE_CONFIG "") +SET(VTK_WRAP_TCL_EXE_CONFIG "") +SET(VTK_WRAP_TCL_INIT_EXE_CONFIG "") +SET(VTK_DOXYGEN_HOME_CONFIG "") +IF(VTK_WRAP_TCL) + SET(VTK_WRAP_TCL_EXE_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}/vtkWrapTcl${VTK_EXE_EXT}) + SET(VTK_WRAP_TCL_INIT_EXE_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}/vtkWrapTclInit${VTK_EXE_EXT}) + SET(VTK_TCL_HOME_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_TCL_DIR}) +ENDIF(VTK_WRAP_TCL) +IF(VTK_WRAP_PYTHON) + SET(VTK_WRAP_PYTHON_EXE_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}/vtkWrapPython${VTK_EXE_EXT}) + SET(VTK_WRAP_PYTHON_INIT_EXE_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}/vtkWrapPythonInit${VTK_EXE_EXT}) +ENDIF(VTK_WRAP_PYTHON) +IF(VTK_WRAP_JAVA) + SET(VTK_PARSE_JAVA_EXE_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}/vtkParseJava${VTK_EXE_EXT}) + SET(VTK_WRAP_JAVA_EXE_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_BIN_DIR}/vtkWrapJava${VTK_EXE_EXT}) + SET(VTK_JAVA_JAR_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_JAVA_DIR}/vtk.jar) +ENDIF(VTK_WRAP_JAVA) + +# VTK style script locations. +SET(VTK_DOXYGEN_HOME_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_DOXYGEN_DIR}) +SET(VTK_HEADER_TESTING_PY_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/testing/HeaderTesting.py) +SET(VTK_FIND_STRING_TCL_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/testing/FindString.tcl) +SET(VTK_PRINT_SELF_CHECK_TCL_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/testing/PrintSelfCheck.tcl) +SET(VTK_RT_IMAGE_TEST_TCL_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/testing/rtImageTest.tcl) + +IF(VTK_USE_PARALLEL) + SET(VTK_PRT_IMAGE_TEST_TCL_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/testing/prtImageTest.tcl) +ELSE(VTK_USE_PARALLEL) + SET(VTK_PRT_IMAGE_TEST_TCL_CONFIG "") +ENDIF(VTK_USE_PARALLEL) + +# Location of tk internal headers and resources provided by VTK. +SET(VTK_TK_INTERNAL_DIR_CONFIG "") +IF(TK_INTERNAL_PATH) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + IF("${TK_INTERNAL_PATH}" MATCHES + "Utilities/TclTk/internals/tk${TCL_TK_VERSION}") + SET(VTK_TK_INTERNAL_DIR_CONFIG + ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_INCLUDE_DIR}/TclTk/internals/tk${TCL_TK_VERSION}) + ENDIF("${TK_INTERNAL_PATH}" MATCHES + "Utilities/TclTk/internals/tk${TCL_TK_VERSION}") +ENDIF(TK_INTERNAL_PATH) + +SET(VTK_TK_INTERNAL_ROOT_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_INCLUDE_DIR}) + +# The resources dir is only worth exporting if we are building with +# Tcl/Tk static +SET(VTK_TK_RESOURCES_DIR_CONFIG "") +IF(VTK_USE_TK AND VTK_TCL_TK_STATIC) + IF(VTK_TK_RESOURCES_DIR) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + IF("${VTK_TK_RESOURCES_DIR}" MATCHES + "Utilities/TclTk/resources/tk${TCL_TK_VERSION}") + SET(VTK_TK_RESOURCES_DIR_CONFIG + ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_INCLUDE_DIR}/TclTk/resources/tk${TCL_TK_VERSION}/win/rc) + ENDIF("${VTK_TK_RESOURCES_DIR}" MATCHES + "Utilities/TclTk/resources/tk${TCL_TK_VERSION}") + ENDIF(VTK_TK_RESOURCES_DIR) +ENDIF(VTK_USE_TK AND VTK_TCL_TK_STATIC) + +IF(VTK_TCL_TK_COPY_SUPPORT_LIBRARY) + VTK_GET_TCL_TK_VERSION ("TCL_TK_MAJOR_VERSION" "TCL_TK_MINOR_VERSION") + SET (TCL_TK_VERSION "${TCL_TK_MAJOR_VERSION}.${TCL_TK_MINOR_VERSION}") + SET(VTK_TCL_SUPPORT_LIBRARY_PATH_CONFIG + ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_TCL_DIR}/tcl${TCL_TK_VERSION}) + SET(VTK_TK_SUPPORT_LIBRARY_PATH_CONFIG + ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_TCL_DIR}/tk${TCL_TK_VERSION}) +ELSE(VTK_TCL_TK_COPY_SUPPORT_LIBRARY) + SET(VTK_TCL_SUPPORT_LIBRARY_PATH_CONFIG ${VTK_TCL_SUPPORT_LIBRARY_PATH}) + SET(VTK_TK_SUPPORT_LIBRARY_PATH_CONFIG ${VTK_TK_SUPPORT_LIBRARY_PATH}) +ENDIF(VTK_TCL_TK_COPY_SUPPORT_LIBRARY) + +# CMake extension module directory and macro file. +SET(VTK_LOAD_CMAKE_EXTENSIONS_MACRO_CONFIG + "${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/CMake/vtkLoadCMakeExtensions.cmake") +SET(VTK_CMAKE_DIR_CONFIG + "${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/CMake") +SET(VTK_TCL_TK_MACROS_MODULE_CONFIG + "${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/CMake/vtkTclTkMacros.cmake") +SET(VTK_CMAKE_EXTENSIONS_DIR_CONFIG ${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/CMake) + +# Library dependencies file. +SET(VTK_LIBRARY_DEPENDS_FILE "${DOLLAR}{VTK_INSTALL_PREFIX}${VTK_INSTALL_PACKAGE_DIR}/VTKLibraryDepends.cmake") + +# No backward compatibility hack needed for installed path +SET(VTK_CONFIG_BACKWARD_COMPATIBILITY_HACK) + +#----------------------------------------------------------------------------- +# Configure VTKConfig.cmake for the install tree. + +# Construct the proper number of GET_FILENAME_COMPONENT(... PATH) +# calls to compute the installation prefix from VTK_DIR. +STRING(REGEX REPLACE "/" ";" VTK_INSTALL_PACKAGE_DIR_COUNT + "${VTK_INSTALL_PACKAGE_DIR}") +SET(VTK_CONFIG_INSTALL_ONLY " +# Compute the installation prefix from VTK_DIR. +SET(VTK_INSTALL_PREFIX \"${DOLLAR}{VTK_DIR}\") +") +FOREACH(p ${VTK_INSTALL_PACKAGE_DIR_COUNT}) + SET(VTK_CONFIG_INSTALL_ONLY + "${VTK_CONFIG_INSTALL_ONLY}GET_FILENAME_COMPONENT(VTK_INSTALL_PREFIX \"${DOLLAR}{VTK_INSTALL_PREFIX}\" PATH)\n" + ) +ENDFOREACH(p) + +# The install tree only has one configuration. +SET(VTK_CONFIGURATION_TYPES_CONFIG) + +IF(CMAKE_CONFIGURATION_TYPES) + # There are multiple build configurations. Configure one + # VTKConfig.cmake for each configuration. + FOREACH(config ${CMAKE_CONFIGURATION_TYPES}) + SET(VTK_BUILD_TYPE_CONFIG ${config}) + CONFIGURE_FILE(${VTK_SOURCE_DIR}/VTKConfig.cmake.in + ${VTK_BINARY_DIR}/Utilities/${config}/VTKConfig.cmake + @ONLY IMMEDIATE) + ENDFOREACH(config) + + # Install the config file corresponding to the build configuration + # specified when building the install target. The BUILD_TYPE variable + # will be set while CMake is processing the install files. + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR} FILES + ${VTK_BINARY_DIR}/Utilities/${DOLLAR}{BUILD_TYPE}/VTKConfig.cmake) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ELSE(CMAKE_CONFIGURATION_TYPES) + # There is only one build configuration. Configure one VTKConfig.cmake. + SET(VTK_BUILD_TYPE_CONFIG ${CMAKE_BUILD_TYPE}) + CONFIGURE_FILE(${VTK_SOURCE_DIR}/VTKConfig.cmake.in + ${VTK_BINARY_DIR}/Utilities/VTKConfig.cmake @ONLY IMMEDIATE) + + # Setup an install rule for the config file. + IF(NOT VTK_INSTALL_NO_DEVELOPMENT) + INSTALL_FILES(${VTK_INSTALL_PACKAGE_DIR} FILES + ${VTK_BINARY_DIR}/Utilities/VTKConfig.cmake) + ENDIF(NOT VTK_INSTALL_NO_DEVELOPMENT) +ENDIF(CMAKE_CONFIGURATION_TYPES) diff --git a/vtkIncludeDirectories.cmake b/vtkIncludeDirectories.cmake new file mode 100644 index 0000000..294cf98 --- /dev/null +++ b/vtkIncludeDirectories.cmake @@ -0,0 +1,166 @@ +#----------------------------------------------------------------------------- +# Include directories for other projects installed on the system. +SET(VTK_INCLUDE_DIRS_SYSTEM "") +IF(VTK_USE_RENDERING) + # OpenGL include directories. + IF(APPLE) + IF(VTK_USE_X) + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} + ${OPENGL_INCLUDE_DIR}) + ENDIF(VTK_USE_X) + ELSE(APPLE) + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} + ${OPENGL_INCLUDE_DIR}) + ENDIF(APPLE) + + IF(VTK_USE_X) + # X include directories. + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} ${X11_INCLUDE_DIR}) + ENDIF(VTK_USE_X) + + IF(VTK_USE_MANGLED_MESA) + # Mangled Mesa include directory. + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} + ${MESA_INCLUDE_PATH}) + ELSE(VTK_USE_MANGLED_MESA) + # Off-Screen Mesa include directory. + IF(VTK_OPENGL_HAS_OSMESA) + IF(OSMESA_INCLUDE_DIR) + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} + ${OSMESA_INCLUDE_DIR}) + ENDIF(OSMESA_INCLUDE_DIR) + ENDIF(VTK_OPENGL_HAS_OSMESA) + ENDIF(VTK_USE_MANGLED_MESA) +ENDIF(VTK_USE_RENDERING) + +IF(VTK_USE_PARALLEL) + IF(VTK_USE_MPI) + # MPI include directory. + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} ${MPI_INCLUDE_PATH}) + ENDIF(VTK_USE_MPI) +ENDIF(VTK_USE_PARALLEL) + +IF(VTK_WRAP_TCL) + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} ${TCL_INCLUDE_PATH}) +ENDIF(VTK_WRAP_TCL) + +IF(VTK_WRAP_PYTHON) + # Python include directory. + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} + ${PYTHON_INCLUDE_PATH}) +ENDIF(VTK_WRAP_PYTHON) + +# VTK_INCLUDE_NEED_TK is set in toplevel CMakeLists.txt file. +IF(VTK_INCLUDE_NEED_TK) + # Tcl/Tk include directories. + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} ${TK_INCLUDE_PATH}) + IF (WIN32) + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} ${TK_XLIB_PATH}) + ENDIF (WIN32) +ENDIF(VTK_INCLUDE_NEED_TK) + +IF(VTK_WRAP_JAVA) + # Java include directories. + SET(VTK_INCLUDE_DIRS_SYSTEM ${VTK_INCLUDE_DIRS_SYSTEM} + ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2} ${JAVA_AWT_INCLUDE_PATH}) +ENDIF(VTK_WRAP_JAVA) + +#----------------------------------------------------------------------------- +# Include directories from the build tree. +SET(VTK_INCLUDE_DIRS_BUILD_TREE + ${VTK_BINARY_DIR} + ${VTK_BINARY_DIR}/Utilities + ) + + +#----------------------------------------------------------------------------- +# Include directories from the source tree. +SET(VTK_INCLUDE_DIRS_SOURCE_TREE "") +IF(VTK_USE_PARALLEL) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} ${VTK_SOURCE_DIR}/Parallel) +ENDIF(VTK_USE_PARALLEL) + +IF(VTK_USE_RENDERING) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} ${VTK_SOURCE_DIR}/VolumeRendering) + SET(VTK_INCLUDE_DIRS_BUILD_TREE ${VTK_INCLUDE_DIRS_BUILD_TREE} ${VTK_BINARY_DIR}/VolumeRendering) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} ${VTK_SOURCE_DIR}/Hybrid) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} ${VTK_SOURCE_DIR}/Widgets) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} ${VTK_SOURCE_DIR}/Rendering) + SET(VTK_INCLUDE_DIRS_BUILD_TREE ${VTK_INCLUDE_DIRS_BUILD_TREE} ${VTK_BINARY_DIR}/Rendering) +# Access to vtkRegressionTestImage.h. +SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_SOURCE_DIR}/Rendering/Testing/Cxx +) +ENDIF(VTK_USE_RENDERING) + +# These directories are always needed. +SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_SOURCE_DIR}/IO + ${VTK_SOURCE_DIR}/Imaging + ${VTK_SOURCE_DIR}/Graphics + ${VTK_SOURCE_DIR}/GenericFiltering + ${VTK_SOURCE_DIR}/Filtering + ${VTK_SOURCE_DIR}/Common + ${VTK_SOURCE_DIR}/Utilities +) + + + +# Access to vtkTestUtilities.h. +SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_SOURCE_DIR}/Common/Testing/Cxx +) + +#----------------------------------------------------------------------------- +# Include directories needed for .cxx files in VTK. These include +# directories will NOT be available to user projects. +SET(VTK_INCLUDE_DIRS_BUILD_TREE_CXX + ${VTK_SOURCE_DIR}/Utilities/vtkfreetype/include + ${VTK_BINARY_DIR}/Utilities/vtkfreetype + ${VTK_SOURCE_DIR}/Utilities/ftgl/src + ${VTK_BINARY_DIR}/Utilities/ftgl +) + +IF(VTK_USE_TK) + # Need access to internal Tk headers for the vtkTk... widget .cxx files. + SET(VTK_INCLUDE_DIRS_BUILD_TREE_CXX ${VTK_INCLUDE_DIRS_BUILD_TREE_CXX} + ${TK_INTERNAL_PATH}) +ENDIF(VTK_USE_TK) + +IF (VTK_USE_MATROX_IMAGING) + # Need access to mil.h include file for vtkMILVideoSource.cxx. + SET(VTK_INCLUDE_DIRS_BUILD_TREE_CXX ${VTK_INCLUDE_DIRS_BUILD_TREE_CXX} + ${MIL_INCLUDE_PATH}) +ENDIF (VTK_USE_MATROX_IMAGING) + +#----------------------------------------------------------------------------- +# Include directories for 3rd-party utilities provided by VTK. +VTK_THIRD_PARTY_INCLUDE2(ZLIB) +VTK_THIRD_PARTY_INCLUDE2(JPEG) +VTK_THIRD_PARTY_INCLUDE2(PNG) +VTK_THIRD_PARTY_INCLUDE2(TIFF) +VTK_THIRD_PARTY_INCLUDE2(EXPAT) +VTK_THIRD_PARTY_INCLUDE(DICOMParser DICOMParser) +VTK_THIRD_PARTY_INCLUDE(FREETYPE vtkfreetype/include) +VTK_THIRD_PARTY_INCLUDE(NetCDF vtknetcdf) +VTK_THIRD_PARTY_INCLUDE(Exodus2 vtkexodus2/include) + +# Include GUI support +IF(VTK_USE_GUISUPPORT) + IF(VTK_USE_QVTK) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_SOURCE_DIR}/GUISupport/Qt) + ENDIF(VTK_USE_QVTK) + IF(VTK_USE_MFC) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_SOURCE_DIR}/GUISupport/MFC) + ENDIF(VTK_USE_MFC) +ENDIF(VTK_USE_GUISUPPORT) + +# GL2PS include directory. +IF(VTK_USE_RENDERING) + IF(VTK_USE_GL2PS) + SET(VTK_INCLUDE_DIRS_SOURCE_TREE ${VTK_INCLUDE_DIRS_SOURCE_TREE} + ${VTK_SOURCE_DIR}/Utilities/gl2ps) + ENDIF(VTK_USE_GL2PS) +ENDIF(VTK_USE_RENDERING) diff --git a/vtkLogo.jpg b/vtkLogo.jpg new file mode 100644 index 0000000..d965e71 Binary files /dev/null and b/vtkLogo.jpg differ diff --git a/vtkMacros.cmake b/vtkMacros.cmake new file mode 100644 index 0000000..1c30bd5 --- /dev/null +++ b/vtkMacros.cmake @@ -0,0 +1,88 @@ +# +# add the instantiator logic for this kit +# +# takes as arguments: +# KIT e.g. Common IO +# CAPS_KIT e.g. COMMON IO +# +MACRO(VTK_USE_INSTANTIATOR KIT CAPS_KIT) + # Setup vtkInstantiator registration for this library's classes. + IF (COMMAND VTK_MAKE_INSTANTIATOR2) + VTK_MAKE_INSTANTIATOR2(vtk${KIT}Instantiator Instantiator_SRCS + ${${KIT}_SRCS} + EXPORT_MACRO VTK_${CAPS_KIT}_EXPORT + HEADER_LOCATION ${VTK_BINARY_DIR}) + ELSE (COMMAND VTK_MAKE_INSTANTIATOR2) + VTK_MAKE_INSTANTIATOR(vtk${KIT}Instantiator Instantiator_SRCS + ${${KIT}_SRCS} + EXPORT_MACRO VTK_${CAPS_KIT}_EXPORT + HEADER_LOCATION ${VTK_BINARY_DIR}) + ENDIF (COMMAND VTK_MAKE_INSTANTIATOR2) + ADD_LIBRARY(vtk${KIT}${VTK_VERSION} ${${KIT}_SRCS} ${Instantiator_SRCS}) +ENDMACRO(VTK_USE_INSTANTIATOR KIT CAPS_KIT) + +# +# generate Tcl wrappers etc +# +# takes arguments: +# KIT e.g. Common IO +# DEPENDS e.g. vtkCommonTCL41 +# +MACRO(VTK_USE_TCL KIT DEPEND) + IF (VTK_WRAP_TCL) + VTK_WRAP_TCL(vtk${KIT}TCL${VTK_VERSION} ${KIT}TCL_SRCS ${${KIT}_SRCS}) + IF (APPLE) + ADD_LIBRARY(vtk${KIT}TCL${VTK_VERSION} SHARED ${${KIT}TCL_SRCS}) + ELSE (APPLE) + ADD_LIBRARY(vtk${KIT}TCL${VTK_VERSION} ${${KIT}TCL_SRCS}) + ENDIF (APPLE) + TARGET_LINK_LIBRARIES(vtk${KIT}TCL${VTK_VERSION} + ${DEPEND} vtk${KIT}${VTK_VERSION} ${TCL_LIBRARY}) + INSTALL_TARGETS(/lib vtk${KIT}TCL${VTK_VERSION}) + ENDIF (VTK_WRAP_TCL) +ENDMACRO(VTK_USE_TCL) + + +# +# generate Python wrappers etc +# +# takes arguments: +# KIT e.g. Common IO +# DEPENDS e.g. vtkCommonTCL41 +# +MACRO(VTK_USE_PYTHON KIT DEPEND) + IF (VTK_WRAP_PYTHON) + VTK_WRAP_PYTHON(vtk${KIT}Python${VTK_VERSION} + ${KIT}Python_SRCS ${${KIT}_SRCS}) + ADD_LIBRARY(vtk${KIT}Python${VTK_VERSION} MODULE ${${KIT}Python_SRCS}) + IF (NOT APPLE) + TARGET_LINK_LIBRARIES (vtk${KIT}Python${VTK_VERSION} ${DEPEND}) + ENDIF (NOT APPLE) + IF(WIN32) + TARGET_LINK_LIBRARIES (vtk${KIT}Python${VTK_VERSION} + debug ${PYTHON_DEBUG_LIBRARY} + optimized ${PYTHON_LIBRARY}) + ENDIF(WIN32) + TARGET_LINK_LIBRARIES(vtk${KIT}Python${VTK_VERSION} + vtk${KIT}${VTK_VERSION}) + INSTALL_TARGETS(/lib vtk${KIT}Python${VTK_VERSION}) + ENDIF (VTK_WRAP_PYTHON) +ENDMACRO(VTK_USE_PYTHON) + + +# +# generate Python wrappers etc +# +# takes arguments: +# KIT e.g. Common IO +# DEPENDS e.g. vtkCommonTCL41 +# +MACRO(VTK_USE_JAVA KIT DEPEND) + IF (VTK_WRAP_JAVA) + VTK_WRAP_JAVA(vtk${KIT}Java${VTK_VERSION} ${KIT}Java_SRCS ${${KIT}_SRCS}) + ADD_LIBRARY(vtk${KIT}Java${VTK_VERSION} SHARED ${${KIT}Java_SRCS}) + TARGET_LINK_LIBRARIES (vtk${KIT}Java${VTK_VERSION} + ${DEPEND} vtk${KIT}${VTK_VERSION}) + INSTALL_TARGETS(/lib vtk${KIT}Java${VTK_VERSION}) + ENDIF (VTK_WRAP_JAVA) +ENDMACRO(VTK_USE_JAVA) diff --git a/vtkToolkits.h.in b/vtkToolkits.h.in new file mode 100644 index 0000000..85c2f4e --- /dev/null +++ b/vtkToolkits.h.in @@ -0,0 +1,97 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile: vtkToolkits.h.in,v $ + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef __vtkToolkits_h +#define __vtkToolkits_h + +/* This header is configured by VTK's build process. */ + +/*--------------------------------------------------------------------------*/ +/* Selected VTK Toolkits */ + +#cmakedefine VTK_USE_PARALLEL +#cmakedefine VTK_USE_RENDERING +#cmakedefine VTK_USE_GL2PS + +/* The Hybrid and VolumeRendering kits are now switched with Rendering. */ +#ifdef VTK_USE_RENDERING +# define VTK_USE_HYBRID +# define VTK_USE_VOLUMERENDERING +#endif + +/*--------------------------------------------------------------------------*/ +/* Rendering Configuration */ + +#cmakedefine VTK_USE_X +#cmakedefine VTK_USE_MANGLED_MESA +#cmakedefine VTK_USE_OPENGL_LIBRARY +#cmakedefine VTK_OPENGL_HAS_OSMESA +#cmakedefine VTK_USE_OFFSCREEN + +/*--------------------------------------------------------------------------*/ +/* Wrapping Configuration */ + +#cmakedefine VTK_WRAP_TCL +#cmakedefine VTK_WRAP_PYTHON +#cmakedefine VTK_WRAP_JAVA + +/*--------------------------------------------------------------------------*/ +/* Other Configuration Options */ + +/* Whether we are building MPI support. */ +#cmakedefine VTK_USE_MPI + +/* Should VTK use the display? */ +#cmakedefine VTK_USE_DISPLAY + +/* is VTK_DATA_ROOT defined? */ +#cmakedefine VTK_DATA_ROOT +#ifdef VTK_DATA_ROOT +# undef VTK_DATA_ROOT +# define VTK_DATA_ROOT "@VTK_DATA_ROOT@" +#endif + +/* Debug leaks support. */ +#cmakedefine VTK_DEBUG_LEAKS + +/* Whether VTK is using its own utility libraries. */ +#cmakedefine VTK_USE_SYSTEM_PNG +#cmakedefine VTK_USE_SYSTEM_ZLIB +#cmakedefine VTK_USE_SYSTEM_JPEG +#cmakedefine VTK_USE_SYSTEM_TIFF +#cmakedefine VTK_USE_SYSTEM_EXPAT +#cmakedefine VTK_USE_SYSTEM_FREETYPE + +/* Whether VTK is using vfw32 and if it supports video capture */ +#cmakedefine VTK_USE_VIDEO_FOR_WINDOWS +#cmakedefine VTK_VFW_SUPPORTS_CAPTURE + +/* Whether the real python debug library has been provided. */ +#cmakedefine VTK_WINDOWS_PYTHON_DEBUGGABLE + +/* Whether the user has linked in the MPEG2 library or not */ +#cmakedefine VTK_USE_MPEG2_ENCODER + +/*--------------------------------------------------------------------------*/ +/* Setup VTK based on platform features and configuration. */ + +/* OGLR */ +#if ((defined(VTK_USE_OPENGL_LIBRARY) && !defined(_WIN32)) || \ + (defined(VTK_USE_X) && defined(_WIN32)) || \ + (defined(VTK_USE_MANGLED_MESA) && !defined(_WIN32))) && \ + !(defined (VTK_USE_CARBON) || defined(VTK_USE_COCOA)) +# define VTK_USE_OGLR +#endif + +#endif